From 489b66d0b2809ca6f569442fb88d8c96e248daeb Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 05:53:28 -0400 Subject: [PATCH 01/30] Add Ix.Kernel certified checking and set-model consistency proofs Add certified source and claim entry points whose receipts connect authenticated Ixon source to the set model. A closed logical receipt excludes the profile's false proposition under the explicit SetTheory hypothesis. Move Ix.Tc and its callers to Ix.Kernel, internalize the named specification, and import the kernel, theory, and host scaffolding from jcb/monorepo at 7b06b754. Remove the root lean4lean dependency and its replay benchmark and test targets. Preserve source identities, licenses, exact theorem audits, and the frozen adapter corpus. Include the separate Mathlib ZFSet construction: a countable increasing chain of strongly inaccessible cardinals supplies the actual Ix SetTheory interface. The model-existence theorem's full dependency audit permits only propext, Classical.choice, and Quot.sound; the cardinal hypothesis stays explicit. Direct production refinements cover universe comparison, structural expression reading, interning, and sort inference. Full checkEnvAnon refinement remains open. New compiler, circuit, and certificate VM development is deferred; existing compiler proofs receive the necessary namespace and exact hash-axiom audit updates. Run the implementation-proof audits on ordinary PRs, add the unified lake run check-kernel --with-model gate, and document the theorem boundaries and review entry points. Replace milestone labels in docs, comments, and test diagnostics with functional descriptions while retaining frozen inputs. Validation: - lake run check-kernel --with-model - lake test --wfail -- cli - ix codegen --check - bench-measures tests and benchmark CLI help - nix-instantiate --parse flake.nix --- .github/workflows/ci.yml | 27 +- .github/workflows/merge-tests.yml | 23 +- .github/workflows/set-theory-model.yml | 47 + BENCHMARKS.md | 6 +- Benchmarks/Lean4Lean.lean | 541 - Benchmarks/Lean4LeanMain.lean | 11 - Ix.lean | 2 +- Ix/Address.lean | 7 +- Ix/AuxGen/ExprUtils.lean | 2 +- Ix/AuxGen/Kernel.lean | 148 +- Ix/AuxGen/Nested.lean | 2 +- Ix/AuxGen/Recursor.lean | 10 +- Ix/BenchConstants.lean | 4 +- Ix/Certified.lean | 13 + Ix/Certified/Audit.lean | 28 + Ix/Certified/AuditAll.lean | 25 + Ix/Certified/AuditSupport.lean | 162 + Ix/Certified/Bytes.lean | 152 + Ix/Certified/ClaimAccept.lean | 164 + Ix/Certified/ClaimAudit.lean | 49 + Ix/Certified/ClaimCheck.lean | 104 + Ix/Certified/ClaimCommand.lean | 117 + Ix/Certified/ClaimInput.lean | 145 + Ix/Certified/ClaimMain.lean | 8 + Ix/Certified/ClaimMeaning.lean | 151 + Ix/Certified/ClaimSuggest.lean | 75 + Ix/Certified/Command.lean | 96 + Ix/Certified/Corpus.lean | 123 + Ix/Certified/Envelope.lean | 92 + Ix/Certified/Fixtures.lean | 141 + Ix/Certified/Ingress.lean | 315 + Ix/Certified/Ixon.lean | 225 + Ix/Certified/Main.lean | 8 + Ix/Certified/ModelHints.lean | 104 + Ix/Certified/ModeledAudit.lean | 56 + Ix/Certified/NOTICE | 22 + Ix/Certified/Reveal.lean | 155 + Ix/Certified/SourceAudit.lean | 39 + Ix/Certified/SourceExpr.lean | 274 + Ix/Certified/SourceMeaning.lean | 245 + Ix/Certified/SourceStore.lean | 318 + Ix/Certified/Store.lean | 74 + Ix/Certified/Suggest.lean | 31 + Ix/Certified/TcAudit.lean | 42 + Ix/Certified/Trees.lean | 117 + Ix/Cli/BenchCmd.lean | 42 +- Ix/Cli/CheckLeanCmd.lean | 12 +- Ix/Cli/ValidateLeanCmd.lean | 6 +- Ix/Compile/Verify/Audit/SorryFrontier.lean | 2 +- Ix/Compile/Verify/Audit/Statements.lean | 163 +- Ix/Compile/Verify/Catalog.lean | 6 +- Ix/Compile/Verify/CompileExpr.lean | 50 +- Ix/Compile/Verify/CompilePreseed.lean | 6 +- Ix/Compile/Verify/CompileUniv.lean | 4 +- Ix/Compile/Verify/IxonValue.lean | 18 +- Ix/Compile/Verify/Reference.lean | 10 +- Ix/Compile/Verify/SourceValue.lean | 8 +- Ix/Compile/Verify/Statements.lean | 10 +- Ix/Environment.lean | 2 +- Ix/IxVM/ClaimHarness.lean | 6 +- Ix/IxVM/Kernel/DefEq.lean | 4 +- Ix/IxVM/Kernel/Infer.lean | 4 +- Ix/IxVM/Kernel/Whnf.lean | 6 +- Ix/IxonUniv.lean | 22 +- Ix/Kernel.lean | 54 + Ix/{Tc => Kernel}/CanonicalCheck.lean | 8 +- Ix/Kernel/Certified.lean | 338 + Ix/Kernel/CertifiedClaims.lean | 95 + Ix/{Tc => Kernel}/Check.lean | 10 +- Ix/{Tc => Kernel}/Const.lean | 6 +- Ix/{Tc => Kernel}/DefEq.lean | 8 +- Ix/{Tc => Kernel}/Driver.lean | 20 +- Ix/{Tc => Kernel}/Egress.lean | 8 +- Ix/{Tc => Kernel}/EgressLean.lean | 6 +- Ix/{Tc => Kernel}/Env.lean | 14 +- Ix/{Tc => Kernel}/Equiv.lean | 4 +- Ix/{Tc => Kernel}/Error.lean | 6 +- Ix/{Tc => Kernel}/Expr.lean | 10 +- Ix/{Tc => Kernel}/Id.lean | 6 +- Ix/{Tc => Kernel}/Inductive.lean | 12 +- Ix/{Tc => Kernel}/Infer.lean | 12 +- Ix/{Tc => Kernel}/Ingress.lean | 12 +- Ix/{Tc => Kernel}/IngressMeta.lean | 12 +- Ix/{Tc => Kernel}/Knot.lean | 8 +- Ix/{Tc => Kernel}/Lctx.lean | 6 +- Ix/{Tc => Kernel}/Level.lean | 16 +- Ix/{Tc => Kernel}/Mode.lean | 6 +- Ix/{Tc => Kernel}/Monad.lean | 27 +- Ix/{Tc => Kernel}/ParCheck.lean | 10 +- Ix/{Tc => Kernel}/Primitive.lean | 6 +- Ix/{Tc => Kernel}/Subst.lean | 8 +- Ix/{Tc => Kernel}/Validate.lean | 16 +- Ix/{Tc => Kernel}/Verify/Audit/Basic.lean | 106 +- Ix/{Tc => Kernel}/Verify/Audit/Completed.lean | 7267 ++++---- .../Verify/Audit/Conditional.lean | 22 +- .../Verify/Audit/SorryFrontier.lean | 28 +- .../Verify/Audit/Statements.lean | 124 +- Ix/{Tc => Kernel}/Verify/Cache.lean | 18 +- .../Verify/Check/Acceptance.lean | 20 +- .../Verify/Check/BinderRoundTrip.lean | 20 +- .../Verify/Check/BlockAcceptance.lean | 28 +- .../Verify/Check/BlockCache.lean | 6 +- .../Verify/Check/BlockClassification.lean | 6 +- .../Verify/Check/BlockDefinition.lean | 18 +- .../Verify/Check/BlockExecution.lean | 6 +- .../Verify/Check/BlockIdentity.lean | 8 +- .../Verify/Check/BlockNatFixture.lean | 8 +- .../Verify/Check/BlockOracle.lean | 10 +- .../Verify/Check/BlockRouteFrame.lean | 6 +- .../Verify/Check/BlockRouting.lean | 8 +- .../Verify/Check/BlockTransaction.lean | 10 +- .../Verify/Check/BoundedPipelines.lean | 28 +- .../Verify/Check/CheckConstExecution.lean | 8 +- .../Verify/Check/CheckConstTransaction.lean | 6 +- .../Verify/Check/CheckerEvidence.lean | 14 +- .../Verify/Check/DeclarationIngress.lean | 12 +- .../Verify/Check/DeclarationValidation.lean | 10 +- .../Verify/Check/DefEqBasicPolicy.lean | 8 +- .../Verify/Check/DefEqCachePolicy.lean | 6 +- .../Verify/Check/DefEqEtaPolicy.lean | 6 +- .../Verify/Check/DefEqFinalWhnfPolicy.lean | 6 +- .../Verify/Check/DefEqLazyDeltaPolicy.lean | 6 +- .../Verify/Check/DefEqNatPolicy.lean | 6 +- .../Verify/Check/DefEqPipelinePolicy.lean | 6 +- .../Check/DefEqProjectionDeltaPolicy.lean | 6 +- .../Verify/Check/DefEqPropositionPolicy.lean | 6 +- .../Verify/Check/FullInference.lean | 10 +- .../Check/FullInferenceApplications.lean | 12 +- .../Verify/Check/FullInferenceBinders.lean | 22 +- .../Verify/Check/FullInferenceCache.lean | 14 +- .../Verify/Check/FullInferenceDispatcher.lean | 12 +- .../Verify/Check/FullInferenceKnot.lean | 22 +- .../Verify/Check/FullInferenceLeaves.lean | 20 +- .../Check/FullInferenceProjections.lean | 10 +- .../Verify/Check/InferencePolicy.lean | 14 +- .../Verify/Check/MemberEvidence.lean | 16 +- .../Verify/Check/NatAcceptance.lean | 22 +- .../Verify/Check/PositiveFuelSort.lean | 26 +- .../Verify/Check/PreTranslation.lean | 14 +- .../Check/PreTranslationCompatibility.lean | 16 +- .../Verify/Check/PreTranslationIngress.lean | 26 +- .../Verify/Check/PreTranslationOpening.lean | 10 +- .../Verify/Check/PreTranslationScopes.lean | 20 +- .../Check/ProjectionInferencePolicy.lean | 6 +- .../Verify/Check/PublicBlocks.lean | 22 +- .../Verify/Check/PublicStandalone.lean | 44 +- .../Verify/Check/QuotientAdmission.lean | 42 +- .../Verify/Check/QuotientBoundary.lean | 10 +- .../Verify/Check/QuotientBridge.lean | 50 +- .../Verify/Check/RecursiveMethodPolicy.lean | 6 +- .../Verify/Check/ResetFrame.lean | 6 +- .../Verify/Check/SafetyFrame.lean | 6 +- Ix/{Tc => Kernel}/Verify/Check/Scoped.lean | 16 +- .../Verify/Check/ScopedActiveBlock.lean | 14 +- .../Verify/Check/ScopedBoundedPipelines.lean | 22 +- .../Verify/Check/ScopedMemberEvidence.lean | 18 +- .../Verify/Check/ScopedPositiveFuelAxiom.lean | 26 +- .../Check/ScopedPositiveFuelCertificate.lean | 6 +- .../Verify/Check/ScopedStandaloneDriver.lean | 14 +- .../Verify/Check/SingletonInductive.lean | 34 +- .../Verify/Check/StandaloneDriver.lean | 12 +- .../Verify/Check/UncachedInferencePolicy.lean | 8 +- .../Check/UniverseInstantiationPolicy.lean | 6 +- .../Verify/Check/ValidationReach.lean | 8 +- .../Verify/Check/ValidatorFrame.lean | 8 +- .../Verify/Check/ValidatorSoundness.lean | 6 +- .../Verify/Check/WhnfBasicHelperPolicy.lean | 6 +- .../Verify/Check/WhnfBitVecPolicy.lean | 6 +- .../Verify/Check/WhnfDecidablePolicy.lean | 6 +- .../Verify/Check/WhnfDriverPolicy.lean | 6 +- .../Verify/Check/WhnfHelperPolicy.lean | 6 +- .../Verify/Check/WhnfIotaBasePolicy.lean | 6 +- .../Verify/Check/WhnfIotaDispatchPolicy.lean | 6 +- .../Verify/Check/WhnfIotaRecursionPolicy.lean | 6 +- .../Verify/Check/WhnfIotaScopePolicy.lean | 6 +- .../Verify/Check/WhnfIotaSynthesisPolicy.lean | 6 +- .../Verify/Check/WhnfNatArgumentPolicy.lean | 6 +- .../Verify/Check/WhnfNatPolicy.lean | 6 +- .../Verify/Check/WhnfNativePolicy.lean | 6 +- .../Verify/Check/WhnfProjectionPolicy.lean | 6 +- .../Verify/Check/WhnfReductionPolicy.lean | 6 +- Ix/Kernel/Verify/Consistency.lean | 19 + Ix/Kernel/Verify/Consistency/Audit.lean | 51 + Ix/Kernel/Verify/Consistency/Expr.lean | 88 + Ix/Kernel/Verify/Consistency/Infer.lean | 47 + Ix/Kernel/Verify/Consistency/Judgment.lean | 118 + Ix/Kernel/Verify/Consistency/Level.lean | 74 + Ix/{Tc => Kernel}/Verify/Ctx.lean | 58 +- Ix/{Tc => Kernel}/Verify/Decl.lean | 42 +- Ix/{Tc => Kernel}/Verify/DefEq.lean | 12 +- .../Verify/DefEq/AcceleratorGates.lean | 10 +- .../Verify/DefEq/ApplicationSpine.lean | 8 +- Ix/{Tc => Kernel}/Verify/DefEq/BoolTrue.lean | 8 +- .../Verify/DefEq/CacheBranches.lean | 16 +- .../Verify/DefEq/CacheShell.lean | 22 +- .../Verify/DefEq/CheapReduction.lean | 10 +- Ix/{Tc => Kernel}/Verify/DefEq/Closure.lean | 10 +- .../Verify/DefEq/DeltaClassification.lean | 10 +- .../Verify/DefEq/EqualRankCache.lean | 10 +- .../Verify/DefEq/EqualRankPrefix.lean | 8 +- .../Verify/DefEq/EqualRankReduction.lean | 8 +- .../Verify/DefEq/FinalWhnf/Application.lean | 8 +- .../Verify/DefEq/FinalWhnf/Closure.lean | 18 +- .../Verify/DefEq/FinalWhnf/Contracts.lean | 10 +- .../Verify/DefEq/FinalWhnf/EtaExpansion.lean | 12 +- .../DefEq/FinalWhnf/LetDeclaration.lean | 10 +- .../Verify/DefEq/FinalWhnf/NatBridge.lean | 20 +- .../Verify/DefEq/FinalWhnf/ProofTail.lean | 10 +- .../DefEq/FinalWhnf/StringExpansion.lean | 10 +- .../DefEq/FinalWhnf/StructuralPrefix.lean | 16 +- .../Verify/DefEq/FinalWhnf/StructureEta.lean | 14 +- .../DefEq/FinalWhnf/StructureEtaBase.lean | 12 +- .../DefEq/FinalWhnf/StructureEtaFields.lean | 8 +- .../DefEq/FinalWhnf/StructureEtaTail.lean | 8 +- .../Verify/DefEq/FinalWhnf/UnitLike.lean | 16 +- Ix/{Tc => Kernel}/Verify/DefEq/LazyDelta.lean | 8 +- .../Verify/DefEq/LazyDeltaClosure.lean | 8 +- .../Verify/DefEq/LazyDeltaIteration.lean | 8 +- .../Verify/DefEq/LoopFinish.lean | 8 +- Ix/{Tc => Kernel}/Verify/DefEq/NatOffset.lean | 20 +- .../Verify/DefEq/NatOffsetDecomposition.lean | 10 +- .../Verify/DefEq/NatReduction.lean | 8 +- .../Verify/DefEq/OneSidedDelta.lean | 8 +- .../Verify/DefEq/ProjectionDeltaActive.lean | 8 +- .../Verify/DefEq/ProjectionDeltaClosure.lean | 8 +- .../DefEq/ProjectionDeltaEqualRank.lean | 10 +- .../Verify/DefEq/ProjectionDeltaFinish.lean | 8 +- .../Verify/DefEq/ProjectionDeltaLoop.lean | 8 +- .../Verify/DefEq/ProjectionDeltaRank.lean | 8 +- .../Verify/DefEq/ProjectionDeltaStep.lean | 12 +- .../DefEq/ProjectionDeltaUnfolding.lean | 8 +- .../Verify/DefEq/ProjectionProbe.lean | 8 +- .../Verify/DefEq/ProjectionReduction.lean | 10 +- .../Verify/DefEq/ProofIrrelevance.lean | 10 +- .../Verify/DefEq/PropositionClassifier.lean | 10 +- .../Verify/DefEq/RankDispatch.lean | 8 +- .../Verify/DefEq/SameHeadSpine.lean | 12 +- .../Verify/DefEq/SpineArguments.lean | 10 +- .../Verify/DefEq/StoppedContinuation.lean | 10 +- .../DefEq/StoppedContinuationClosure.lean | 8 +- .../Verify/DefEq/StringLiteral.lean | 10 +- .../Verify/DefEq/Structural.lean | 18 +- .../Verify/DefEq/StructuralCongruence.lean | 10 +- .../Verify/Driver/BooleanAcceptance.lean | 8 +- .../Verify/Driver/Dependencies.lean | 6 +- .../Verify/Driver/Enumeration.lean | 6 +- Ix/{Tc => Kernel}/Verify/Driver/Fixtures.lean | 6 +- Ix/{Tc => Kernel}/Verify/Driver/Model.lean | 12 +- Ix/{Tc => Kernel}/Verify/Driver/Serial.lean | 16 +- .../Verify/Driver/SupportedAcceptance.lean | 36 +- .../Driver/SupportedAcceptanceFixtures.lean | 12 +- Ix/{Tc => Kernel}/Verify/Env.lean | 34 +- .../Verify/EquivalenceManager.lean | 8 +- Ix/{Tc => Kernel}/Verify/Execution.lean | 6 +- Ix/{Tc => Kernel}/Verify/Expr.lean | 8 +- Ix/{Tc => Kernel}/Verify/Frame.lean | 14 +- .../Verify/Frontier}/Pending.lean | 31 +- Ix/{Tc => Kernel}/Verify/Inductive.lean | 64 +- .../Inductive/AliasFormerAdmission.lean | 12 +- .../Inductive/AliasFormerCertificate.lean | 22 +- .../Verify/Inductive/AliasFormerFixture.lean | 16 +- .../Verify/Inductive/AliasFormerPattern.lean | 14 +- .../Inductive/AliasFormerRecursorFixture.lean | 12 +- .../Verify/Inductive/AliasRecAdmission.lean | 12 +- .../Verify/Inductive/AliasRecCertificate.lean | 20 +- .../Verify/Inductive/AliasRecFixture.lean | 16 +- .../Verify/Inductive/AliasRecPattern.lean | 14 +- .../Inductive/AliasRecRecursorFixture.lean | 12 +- .../Verify/Inductive/AliasRecSoundness.lean | 28 +- .../Inductive/AnnotatedPiAdmission.lean | 12 +- .../Inductive/AnnotatedPiCertificate.lean | 26 +- .../Verify/Inductive/AnnotatedPiFixture.lean | 16 +- .../Verify/Inductive/AnnotatedPiPattern.lean | 14 +- .../Inductive/AnnotatedPiRecursorFixture.lean | 12 +- .../Inductive/AnnotatedPiSoundness.lean | 28 +- .../Verify/Inductive/BlockCertificate.lean | 16 +- .../Inductive/BlockPatternSoundness.lean | 14 +- .../Verify/Inductive/CandidateSyntax.lean | 26 +- .../Verify/Inductive/Certificate.lean | 14 +- .../Verify/Inductive/ConcreteFixture.lean | 12 +- .../ConstructorPositivityTraversal.lean | 6 +- .../ConstructorValidationTraversal.lean | 6 +- .../Inductive/EliminationBreadthFixture.lean | 24 +- .../Inductive/EnumerationAcceptance.lean | 20 +- .../Verify/Inductive/EnumerationFixture.lean | 20 +- .../Verify/Inductive/ExactLeanSyntax.lean | 6 +- .../GeneratedRecursorAcceptance.lean | 10 +- .../GeneratedRecursorAcceptanceClosure.lean | 18 +- .../Inductive/GeneratedRecursorAdmission.lean | 16 +- .../GeneratedRecursorCheckerFixture.lean | 14 +- .../GeneratedRecursorCommitFixture.lean | 12 +- .../GeneratedRecursorComparison.lean | 6 +- .../GeneratedRecursorInitialInvariant.lean | 54 +- .../GeneratedRecursorMemberCheck.lean | 16 +- .../GeneratedRecursorMemberFixture.lean | 32 +- .../Inductive/GeneratedRecursorMetadata.lean | 8 +- .../GeneratedRecursorRuleFixture.lean | 14 +- .../Inductive/GeneratedRecursorSelection.lean | 12 +- .../Inductive/GeneratedRecursorSemantics.lean | 22 +- .../GeneratedRecursorTypeClosure.lean | 32 +- .../GeneratedRecursorTypeFixture.lean | 18 +- .../Inductive/IndexedBlockValidation.lean | 10 +- .../Inductive/IndexedCandidateOperations.lean | 12 +- .../Inductive/IndexedCandidateSyntax.lean | 40 +- .../IndexedCandidateTransaction.lean | 22 +- .../IndexedConstructorPositivity.lean | 8 +- .../IndexedConstructorValidation.lean | 74 +- .../Inductive/IndexedPositivityTransport.lean | 130 +- .../Inductive/IndexedProducerClosure.lean | 12 +- .../IndexedProductionPositivity.lean | 10 +- .../Inductive/IndexedRecursiveAcceptance.lean | 30 +- .../IndexedRecursiveCertificate.lean | 18 +- .../Inductive/IndexedRecursiveFixture.lean | 16 +- .../Inductive/IndexedRecursiveOracle.lean | 12 +- .../Inductive/IndexedRecursivePattern.lean | 16 +- .../Inductive/IndexedRecursiveSoundness.lean | 80 +- .../Verify/Inductive/IngressExecution.lean | 10 +- .../Verify/Inductive/IotaPattern.lean | 76 +- .../Inductive/MutualBlockCertificate.lean | 22 +- .../Verify/Inductive/MutualBlockFixture.lean | 14 +- .../Inductive/MutualBlockValidation.lean | 8 +- .../Verify/Inductive/MutualFamily.lean | 16 +- .../Inductive/MutualFamilyAdmission.lean | 20 +- .../Verify/Inductive/MutualRecursor.lean | 18 +- .../Inductive/MutualRecursorAdmission.lean | 110 +- .../Verify/Inductive/NestedAdmission.lean | 16 +- .../Inductive/NestedAuxiliaryExpansion.lean | 6 +- .../Inductive/NestedAuxiliaryPositivity.lean | 52 +- .../Inductive/NestedBlockCertificate.lean | 12 +- .../Inductive/NestedCandidateSyntax.lean | 60 +- .../NestedConstructorValidation.lean | 56 +- .../Inductive/NestedPositivityTransport.lean | 54 +- .../Inductive/NestedPositivityTraversal.lean | 8 +- .../Inductive/NestedRecursiveFixture.lean | 10 +- .../Inductive/NestedRecursorAdmission.lean | 12 +- .../Inductive/NestedRecursorFixture.lean | 6 +- .../Inductive/NestedRecursorPattern.lean | 14 +- .../Inductive/NestedRecursorSoundness.lean | 52 +- .../Inductive/NestedSemanticTransaction.lean | 22 +- .../Verify/Inductive/OccurrenceClosure.lean | 8 +- .../Inductive/OccurrenceValidation.lean | 20 +- .../Verify/Inductive/OneFamilyAdmission.lean | 34 +- .../Inductive/PositivityTraceAdapter.lean | 84 +- .../Verify/Inductive/PositivityTraversal.lean | 6 +- .../ProducedGenerationTransaction.lean | 26 +- .../Inductive/RecursivePiAcceptance.lean | 14 +- .../Inductive/RecursivePiAdmission.lean | 12 +- .../Inductive/RecursivePiCertificate.lean | 16 +- .../Verify/Inductive/RecursivePiFixture.lean | 12 +- .../Verify/Inductive/RecursivePiPattern.lean | 16 +- .../Inductive/RecursivePiRecursorFixture.lean | 10 +- .../Inductive/RecursivePiSoundness.lean | 64 +- .../RecursivePositivityTraversal.lean | 6 +- .../Verify/Inductive/ResultSortTelescope.lean | 8 +- .../Verify/Inductive/RuleApplication.lean | 14 +- .../Inductive/SingletonEnumeration.lean | 48 +- .../Verify/Inductive/SingletonFamily.lean | 10 +- .../Verify/Inductive/SingletonIngress.lean | 18 +- .../Verify/Inductive/SingletonOracle.lean | 8 +- .../Verify/Inductive/SingletonRecursor.lean | 14 +- .../Inductive/SpecializationIdentity.lean | 6 +- .../Inductive/StructuralCacheSemantics.lean | 6 +- Ix/{Tc => Kernel}/Verify/Infer.lean | 10 +- .../Verify/Infer/Applications.lean | 16 +- .../Verify/Infer/BinderClosing.lean | 14 +- .../Verify/Infer/BinderOpening.lean | 12 +- .../Verify/Infer/BinderScopes.lean | 12 +- .../Verify/Infer/CacheShell.lean | 6 +- .../Verify/Infer/CacheSoundness.lean | 14 +- Ix/{Tc => Kernel}/Verify/Infer/Callbacks.lean | 10 +- Ix/{Tc => Kernel}/Verify/Infer/CheapBeta.lean | 12 +- Ix/{Tc => Kernel}/Verify/Infer/Constants.lean | 18 +- .../Verify/Infer/Dispatcher.lean | 22 +- .../Verify/Infer/ForallTypes.lean | 16 +- .../Verify/Infer/FunctionTypes.lean | 12 +- .../Verify/Infer/LambdaTypes.lean | 20 +- Ix/{Tc => Kernel}/Verify/Infer/LeafCases.lean | 16 +- Ix/{Tc => Kernel}/Verify/Infer/LetScopes.lean | 8 +- Ix/{Tc => Kernel}/Verify/Infer/LetTypes.lean | 22 +- Ix/{Tc => Kernel}/Verify/Infer/Literals.lean | 32 +- .../Infer/ProjectionClassification.lean | 10 +- .../Verify/Infer/ProjectionTelescope.lean | 62 +- .../Verify/Infer/ProjectionTypes.lean | 18 +- .../Verify/Infer/ScopedLocals.lean | 12 +- Ix/{Tc => Kernel}/Verify/Infer/SortTypes.lean | 18 +- .../Verify/Infer/Substitution.lean | 8 +- .../Verify/InferDefEq/Closure.lean | 8 +- .../Verify/Ingress/AnonStructural.lean | 20 +- .../Verify/Ingress/LiteralBlobs.lean | 8 +- .../Verify/Ingress/Representation.lean | 10 +- .../Verify/Ingress/SerializedBoolean.lean | 10 +- Ix/{Tc => Kernel}/Verify/InstL.lean | 40 +- Ix/{Tc => Kernel}/Verify/InstUniv.lean | 12 +- Ix/{Tc => Kernel}/Verify/Knot.lean | 6 +- Ix/{Tc => Kernel}/Verify/Level.lean | 79 +- Ix/{Tc => Kernel}/Verify/Monad.lean | 8 +- Ix/{Tc => Kernel}/Verify/NatFixture.lean | 116 +- .../Verify/Projection/Concrete.lean | 52 +- .../Verify/Projection/ConcreteFixture.lean | 30 +- .../Verify/RecursiveMethods/CallDomains.lean | 18 +- .../Verify/RecursiveMethods/Closure.lean | 8 +- .../FiniteSupportBoundary.lean | 6 +- .../Verify/RecursiveMethods/Inference.lean | 16 +- .../Verify/RecursiveMethods/Public.lean | 22 +- .../RecursiveMethods/ScopedCallDomains.lean | 20 +- .../RecursiveMethods/ScopedInference.lean | 16 +- .../RecursiveMethods/ScopedSortInference.lean | 18 +- .../RecursiveMethods/SortInference.lean | 16 +- Ix/{Tc => Kernel}/Verify/Run.lean | 22 +- .../Verify/ScopedSuffix/ClosedContext.lean | 8 +- Ix/{Tc => Kernel}/Verify/State.lean | 18 +- Ix/{Tc => Kernel}/Verify/Statements.lean | 12 +- Ix/{Tc => Kernel}/Verify/Subst.lean | 8 +- Ix/{Tc => Kernel}/Verify/Suffix.lean | 6 +- Ix/{Tc => Kernel}/Verify/Support.lean | 6 +- Ix/{Tc => Kernel}/Verify/Totalization.lean | 10 +- Ix/{Tc => Kernel}/Verify/Trans.lean | 204 +- Ix/{Tc => Kernel}/Verify/VLCtx.lean | 16 +- Ix/{Tc => Kernel}/Verify/Whnf.lean | 76 +- .../Verify/Whnf/Beta/ArgumentAlignment.lean | 8 +- .../Verify/Whnf/Beta/ConsumptionBoundary.lean | 26 +- .../Verify/Whnf/Beta/DependentContexts.lean | 14 +- .../Verify/Whnf/Beta/InstantiationChain.lean | 10 +- .../Verify/Whnf/Beta/LambdaInstantiation.lean | 48 +- .../Verify/Whnf/Beta/LambdaPeeling.lean | 6 +- .../Verify/Whnf/Beta/LiftSubstitution.lean | 6 +- .../Verify/Whnf/Beta/Meaning.lean | 8 +- .../Verify/Whnf/Beta/PeelTrace.lean | 30 +- .../Verify/Whnf/Beta/PrefixSemantics.lean | 36 +- .../Verify/Whnf/Beta/SemanticCore.lean | 8 +- .../Whnf/Beta/SimultaneousSubstitution.lean | 6 +- .../Whnf/Beta/SingletonSubstitution.lean | 6 +- .../Verify/Whnf/Beta/Translation.lean | 12 +- Ix/{Tc => Kernel}/Verify/Whnf/Closure.lean | 8 +- .../Verify/Whnf/Delta/CacheExecution.lean | 10 +- .../Verify/Whnf/Delta/CacheSemantics.lean | 6 +- .../Verify/Whnf/Delta/ClosedTranslation.lean | 58 +- .../Verify/Whnf/Delta/Integration.lean | 8 +- .../Verify/Whnf/Delta/OptionalReduction.lean | 8 +- .../Verify/Whnf/Delta/SpineUnfolding.lean | 12 +- .../Verify/Whnf/Delta/StableCache.lean | 16 +- .../Verify/Whnf/Delta/TrustedBody.lean | 10 +- .../Verify/Whnf/Delta/UnfoldingState.lean | 8 +- .../Whnf/Delta/UniverseMonotonicity.lean | 10 +- .../Verify/Whnf/Driver/FullStep.lean | 6 +- .../Verify/Whnf/Driver/PublicReducers.lean | 12 +- .../Verify/Whnf/Iota/ApplicationRequests.lean | 8 +- .../Verify/Whnf/Iota/ArgumentBranches.lean | 18 +- .../Verify/Whnf/Iota/ArgumentExecution.lean | 18 +- .../Verify/Whnf/Iota/ConstructorDispatch.lean | 22 +- .../Whnf/Iota/ConstructorSynthesis.lean | 14 +- .../Iota/ConstructorSynthesisFallback.lean | 6 +- .../Verify/Whnf/Iota/Ingress.lean | 12 +- .../Verify/Whnf/Iota/NatLiteral.lean | 14 +- .../Verify/Whnf/Iota/NatOffset.lean | 10 +- .../Verify/Whnf/Iota/NatPatternMatching.lean | 70 +- .../Verify/Whnf/Iota/NatRecognizer.lean | 6 +- .../Verify/Whnf/Iota/NatReduction.lean | 30 +- .../Verify/Whnf/Iota/NatRuleLayout.lean | 26 +- .../Verify/Whnf/Iota/OptionalReduction.lean | 8 +- .../Verify/Whnf/Iota/RuleInstantiation.lean | 12 +- .../Verify/Whnf/Iota/RuleSuffixTransport.lean | 16 +- .../Verify/Whnf/Iota/SelectedRule.lean | 24 +- .../Verify/Whnf/Iota/StringLiteral.lean | 14 +- .../Verify/Whnf/Iota/StructEtaControl.lean | 6 +- .../Verify/Whnf/Iota/Substitution.lean | 14 +- .../Verify/Whnf/Iota/SynthesisRequests.lean | 16 +- .../Verify/Whnf/NoDelta/BaseReductions.lean | 6 +- .../Whnf/NoDelta/ProjectionApplication.lean | 8 +- .../Whnf/NoDelta/ProjectionDefinition.lean | 8 +- .../Verify/Whnf/NoDelta/Quotient.lean | 12 +- .../Whnf/NoDelta/QuotientReflection.lean | 40 +- .../Verify/Whnf/NoDelta/Reducer.lean | 8 +- .../Verify/Whnf/NoDelta/StringPrimitive.lean | 8 +- .../Verify/Whnf/Projection/NoAccelTail.lean | 6 +- .../Whnf/Projection/StringCallback.lean | 6 +- .../Whnf/Projection/StringExpansion.lean | 6 +- Ix/{Tc => Kernel}/Verify/Whnf/README.md | 2 +- .../Verify/Whnf/Runtime/LazyIngress.lean | 8 +- .../Verify/Whnf/RuntimeContracts.lean | 6 +- .../Verify/Whnf/StructEta/CallbackPrefix.lean | 12 +- .../Verify/Whnf/StructEta/Classifier.lean | 10 +- .../Whnf/StructEta/ExactMajorTelescope.lean | 6 +- .../Verify/Whnf/StructEta/Rebuild.lean | 6 +- .../Whnf/StructEta/RebuildRequests.lean | 10 +- .../Verify/Whnf/StructEta/RebuildTail.lean | 6 +- .../Whnf/StructEta/RecursionClassifier.lean | 10 +- .../Whnf/StructEta/ScopedClassifier.lean | 14 +- .../Whnf/StructEta/ScopedTelescope.lean | 24 +- .../Structural/ApplicationCongruence.lean | 14 +- .../Whnf/Structural/ApplicationRebuild.lean | 8 +- .../Whnf/Structural/ApplicationStep.lean | 6 +- .../Whnf/Structural/ApplicationTails.lean | 10 +- .../Verify/Whnf/Structural/BasicStep.lean | 6 +- .../Verify/Whnf/Structural/BetaBoundary.lean | 10 +- .../Verify/Whnf/Structural/CacheShell.lean | 12 +- .../Whnf/Structural/ProjectionStep.lean | 6 +- .../Whnf/Structural/RecursiveCallbacks.lean | 16 +- .../Verify/Whnf/Structural/Reducer.lean | 8 +- .../Verify/Whnf/Structural/StepAssembly.lean | 6 +- .../Verify/Whnf/Structural/VariableStep.lean | 8 +- .../Verify/Whnf/Structural/VerifiedStep.lean | 6 +- Ix/{Tc => Kernel}/Verify/World.lean | 12 +- Ix/{Tc => Kernel}/Whnf.lean | 24 +- Ix/Tc.lean | 54 - Ix/Theory.lean | 6 + Ix/Theory/Certificate/Build.lean | 211 + Ix/Theory/Certificate/Claims.lean | 50 + Ix/Theory/Certificate/Modeled.lean | 104 + Ix/Theory/Certificate/Ordinary.lean | 98 + Ix/Theory/Certificate/OrdinarySource.lean | 98 + Ix/Theory/Certificate/Quotient.lean | 75 + Ix/Theory/Certificate/Standard.lean | 54 + Ix/Theory/Certificate/Structure.lean | 43 + Ix/Theory/Certificate/Suggest.lean | 417 + Ix/Theory/Certified.lean | 48 + Ix/Theory/Certified/Accept.lean | 139 + Ix/Theory/Certified/Admission.lean | 245 + Ix/Theory/Certified/Basis/Equality.lean | 199 + Ix/Theory/Certified/Basis/Iff.lean | 171 + Ix/Theory/Certified/Basis/Interface.lean | 38 + Ix/Theory/Certified/Basis/Nonempty.lean | 138 + Ix/Theory/Certified/Checker.lean | 316 + Ix/Theory/Certified/ClaimComposition.lean | 245 + Ix/Theory/Certified/Claims.lean | 242 + Ix/Theory/Certified/Frontier.lean | 279 + Ix/Theory/Certified/Level.lean | 121 + Ix/Theory/Certified/LevelEq.lean | 116 + Ix/Theory/Certified/LogicalPolicy.lean | 130 + Ix/Theory/Certified/Modeled/Admission.lean | 59 + Ix/Theory/Certified/Modeled/Equation.lean | 73 + Ix/Theory/Certified/Modeled/Source.lean | 268 + Ix/Theory/Certified/Modeled/Transport.lean | 290 + Ix/Theory/Certified/Natural/Admission.lean | 63 + Ix/Theory/Certified/Natural/Checked.lean | 46 + Ix/Theory/Certified/Natural/Publish.lean | 90 + Ix/Theory/Certified/Natural/Value.lean | 120 + Ix/Theory/Certified/Operations.lean | 103 + Ix/Theory/Certified/Ordinary/Admission.lean | 113 + Ix/Theory/Certified/Ordinary/Checked.lean | 164 + Ix/Theory/Certified/Ordinary/Computation.lean | 133 + .../Certified/Ordinary/ConstructorStage.lean | 154 + .../Certified/Ordinary/Constructors.lean | 237 + Ix/Theory/Certified/Ordinary/Container.lean | 266 + Ix/Theory/Certified/Ordinary/Eliminator.lean | 264 + Ix/Theory/Certified/Ordinary/Family.lean | 139 + Ix/Theory/Certified/Ordinary/LargeElim.lean | 65 + Ix/Theory/Certified/Ordinary/Reading.lean | 309 + .../Certified/Ordinary/RecursorReading.lean | 415 + .../Certified/Ordinary/RecursorStage.lean | 163 + .../Certified/Ordinary/RecursorSyntax.lean | 155 + .../Certified/Ordinary/RecursorValue.lean | 136 + Ix/Theory/Certified/Ordinary/RuleChecks.lean | 90 + .../Certified/Ordinary/RuleEquations.lean | 115 + Ix/Theory/Certified/Ordinary/RuleReading.lean | 270 + Ix/Theory/Certified/Ordinary/Shape.lean | 212 + Ix/Theory/Certified/Policy.lean | 131 + Ix/Theory/Certified/Prelude.lean | 247 + Ix/Theory/Certified/PropWhen.lean | 330 + Ix/Theory/Certified/Quotient/Admission.lean | 57 + Ix/Theory/Certified/Quotient/Checked.lean | 179 + Ix/Theory/Certified/Quotient/Publish.lean | 195 + Ix/Theory/Certified/Quotient/Reading.lean | 184 + Ix/Theory/Certified/Quotient/Syntax.lean | 144 + Ix/Theory/Certified/Quotient/Value.lean | 185 + Ix/Theory/Certified/Signature.lean | 162 + Ix/Theory/Certified/Source.lean | 153 + Ix/Theory/Certified/Standard/Admission.lean | 61 + Ix/Theory/Certified/Standard/Checked.lean | 89 + Ix/Theory/Certified/Standard/Realization.lean | 127 + Ix/Theory/Certified/Store.lean | 69 + Ix/Theory/Certified/Structure/Admission.lean | 62 + Ix/Theory/Certified/Structure/Checked.lean | 117 + .../Certified/Structure/Computation.lean | 84 + Ix/Theory/Certified/Structure/Publish.lean | 161 + Ix/Theory/Certified/Structure/Reading.lean | 149 + Ix/Theory/Certified/Structure/Syntax.lean | 111 + Ix/Theory/Certified/Structure/Value.lean | 141 + Ix/Theory/Certified/Telescope.lean | 172 + Ix/Theory/Const.lean | 165 + Ix/Theory/Expr.lean | 284 + Ix/Theory/Inductive/Levels.lean | 124 + Ix/Theory/LICENSE | 234 + Ix/Theory/LICENSE-APACHE | 201 + Ix/Theory/LICENSE-MIT | 21 + Ix/Theory/Model/Annotated.lean | 221 + Ix/Theory/Model/Context.lean | 56 + Ix/Theory/Model/Environment.lean | 76 + Ix/Theory/Model/Extension.lean | 346 + Ix/Theory/Model/Inductive/Codes.lean | 43 + Ix/Theory/Model/Inductive/Container.lean | 192 + Ix/Theory/Model/Inductive/Recursor.lean | 218 + Ix/Theory/Model/Inductive/Telescope.lean | 585 + Ix/Theory/Model/Instantiation.lean | 96 + Ix/Theory/Model/Interpret.lean | 150 + Ix/Theory/Model/Judgment.lean | 280 + Ix/Theory/Model/PrimitiveValues.lean | 38 + Ix/Theory/Model/ReferenceMap.lean | 168 + Ix/Theory/Model/SetModel/Container.lean | 665 + Ix/Theory/Model/SetModel/Iter.lean | 107 + Ix/Theory/Model/SetModel/Ops.lean | 366 + Ix/Theory/Model/SetModel/RecGraph.lean | 270 + Ix/Theory/Model/SetModel/TaggedSum.lean | 186 + Ix/Theory/Model/SetModel/TupleTower.lean | 424 + Ix/Theory/Model/SetTheory/Core.lean | 166 + Ix/Theory/Model/SetTheory/Derive/Choice.lean | 75 + Ix/Theory/Model/SetTheory/Derive/Empty.lean | 79 + Ix/Theory/Model/SetTheory/Derive/Graphs.lean | 252 + Ix/Theory/Model/SetTheory/Derive/Lfp.lean | 162 + Ix/Theory/Model/SetTheory/Derive/LfpFam.lean | 170 + Ix/Theory/Model/SetTheory/Derive/Omega.lean | 142 + Ix/Theory/Model/SetTheory/Derive/Pair.lean | 128 + Ix/Theory/Model/SetTheory/Derive/Pt.lean | 240 + Ix/Theory/Model/SetTheory/Derive/Quot.lean | 234 + Ix/Theory/Model/SetTheory/Derive/Sep.lean | 74 + Ix/Theory/Model/SetTheory/Derive/Sigma.lean | 158 + Ix/Theory/Model/SetTheory/Derive/Univ.lean | 110 + .../Model/SetTheory/Derive/Universe.lean | 175 + Ix/Theory/Model/Signature.lean | 159 + Ix/Theory/Model/Support.lean | 126 + Ix/Theory/Model/TelescopeSemantics.lean | 81 + Ix/Theory/Model/Value.lean | 90 + Ix/Theory/Model/WellDenoted.lean | 148 + Ix/Theory/NOTICE | 51 + .../Named/ConstructorValidityFixtures.lean | 176 + .../Fixtures/ProjectionExpressibility.lean | 1307 ++ Ix/Theory/Named/Inductive.lean | 3045 ++++ Ix/Theory/Named/InductiveFixtures.lean | 2897 +++ Ix/Theory/Named/LICENSE | 201 + Ix/Theory/Named/Literals.lean | 682 + Ix/Theory/Named/LocalContext.lean | 150 + Ix/Theory/Named/Meta.lean | 120 + Ix/Theory/Named/MutualInductiveFixtures.lean | 199 + Ix/Theory/Named/NOTICE | 116 + Ix/Theory/Named/NestedInductive.lean | 534 + Ix/Theory/Named/NestedInductiveFixtures.lean | 329 + Ix/Theory/Named/Projection.lean | 3518 ++++ Ix/Theory/Named/Quot.lean | 27 + Ix/Theory/Named/Reference/Declaration.lean | 33 + Ix/Theory/Named/Reference/Environment.lean | 125 + .../Named/Reference/Environment/Basic.lean | 226 + Ix/Theory/Named/Reference/Expr.lean | 138 + Ix/Theory/Named/Reference/ForEachExprV.lean | 36 + Ix/Theory/Named/Reference/FuelConfig.lean | 41 + Ix/Theory/Named/Reference/Inductive/Add.lean | 2941 ++++ .../Reference/Inductive/EliminationTrace.lean | 581 + .../Named/Reference/Inductive/Reduce.lean | 120 + .../Reference/Inductive/ValidationTrace.lean | 1600 ++ Ix/Theory/Named/Reference/Instantiate.lean | 39 + Ix/Theory/Named/Reference/Level.lean | 412 + Ix/Theory/Named/Reference/List.lean | 11 + Ix/Theory/Named/Reference/LocalContext.lean | 27 + Ix/Theory/Named/Reference/Primitive.lean | 498 + Ix/Theory/Named/Reference/PtrEq.lean | 28 + Ix/Theory/Named/Reference/Quot.lean | 126 + Ix/Theory/Named/Reference/TypeChecker.lean | 1074 ++ Ix/Theory/Named/SingletonParity.lean | 186 + Ix/Theory/Named/Std/AxiomAudit.lean | 130 + Ix/Theory/Named/Std/Basic.lean | 269 + Ix/Theory/Named/Std/Control.lean | 8 + Ix/Theory/Named/Std/HashMap.lean | 105 + Ix/Theory/Named/Std/NodupKeys.lean | 45 + Ix/Theory/Named/Std/Ord.lean | 58 + Ix/Theory/Named/Std/PersistentHashMap.lean | 48 + Ix/Theory/Named/Std/SMap.lean | 83 + Ix/Theory/Named/Std/ToExpr.lean | 73 + Ix/Theory/Named/Std/VariableBang.lean | 22 + Ix/Theory/Named/Typing/Basic.lean | 141 + Ix/Theory/Named/Typing/Env.lean | 79 + Ix/Theory/Named/Typing/EnvLemmas.lean | 120 + .../Named/Typing/InductiveCertificate.lean | 514 + Ix/Theory/Named/Typing/InductiveLemmas.lean | 14628 ++++++++++++++++ Ix/Theory/Named/Typing/InductivePattern.lean | 761 + .../Named/Typing/InductivePatternWF.lean | 943 + Ix/Theory/Named/Typing/Injectivity.lean | 43 + Ix/Theory/Named/Typing/Lemmas.lean | 1115 ++ Ix/Theory/Named/Typing/Meta.lean | 54 + .../Named/Typing/NestedInductiveLemmas.lean | 190 + Ix/Theory/Named/Typing/Pattern.lean | 466 + Ix/Theory/Named/Typing/QuotLemmas.lean | 39 + Ix/Theory/Named/Typing/Strong.lean | 1031 ++ Ix/Theory/Named/Typing/UniqueTyping.lean | 377 + Ix/Theory/Named/VDecl.lean | 37 + Ix/Theory/Named/VEnv.lean | 214 + Ix/Theory/Named/VExpr.lean | 831 + Ix/Theory/Named/VLevel.lean | 99 + Ix/Theory/Named/Verify/Axioms.lean | 516 + Ix/Theory/Named/Verify/Environment/Basic.lean | 555 + .../Environment/ConstructorValidation.lean | 9028 ++++++++++ .../ConstructorValidityMatrix.lean | 358 + .../Named/Verify/Environment/Elimination.lean | 244 + .../EliminationFixturesCommon.lean | 65 + .../Environment/EliminationFixturesEdges.lean | 249 + .../Environment/EliminationFixturesEq.lean | 65 + .../Environment/EliminationFixturesEqNat.lean | 10 + .../Environment/EliminationFixturesNat.lean | 114 + .../Environment/EliminationFixturesOrAnd.lean | 137 + .../Environment/EliminationFixturesSmall.lean | 100 + .../Environment/IndexedVecCandidate.lean | 1686 ++ .../Environment/IndexedVecConsReplay.lean | 2863 +++ .../Environment/IndexedVecConstructors.lean | 1803 ++ .../Environment/IndexedVecOuterReplay.lean | 1757 ++ .../Environment/IndexedVecSemanticReplay.lean | 3540 ++++ .../Verify/Environment/InductiveFixtures.lean | 12189 +++++++++++++ .../Named/Verify/Environment/Lemmas.lean | 664 + .../Environment/MutualInductiveFixtures.lean | 3150 ++++ .../Verify/Environment/NestedReplay.lean | 3402 ++++ .../Environment/NestedRepresentation.lean | 718 + .../Environment/NestedTransformation.lean | 389 + .../Verify/Environment/Normalization.lean | 6953 ++++++++ .../Environment/NormalizationMatrix.lean | 749 + .../Environment/SingletonParityMatrix.lean | 471 + .../Environment/SingletonParityReplay.lean | 2820 +++ Ix/Theory/Named/Verify/Expr.lean | 1303 ++ Ix/Theory/Named/Verify/Level.lean | 3916 +++++ Ix/Theory/Named/Verify/LevelStd.lean | 549 + Ix/Theory/Named/Verify/LocalContext.lean | 337 + Ix/Theory/Named/Verify/Name.lean | 96 + Ix/Theory/Named/Verify/NameGenerator.lean | 34 + Ix/Theory/Named/Verify/NormLt.lean | 370 + Ix/Theory/Named/Verify/QSort.lean | 398 + Ix/Theory/Named/Verify/TypeChecker.lean | 236 + Ix/Theory/Named/Verify/TypeChecker/Basic.lean | 1176 ++ .../Named/Verify/TypeChecker/InferType.lean | 1082 ++ .../Named/Verify/TypeChecker/IsDefEq.lean | 1228 ++ .../Named/Verify/TypeChecker/Reduce.lean | 221 + Ix/Theory/Named/Verify/TypeChecker/WHNF.lean | 275 + .../Verify/Typing/ConditionallyTyped.lean | 150 + Ix/Theory/Named/Verify/Typing/Expr.lean | 146 + Ix/Theory/Named/Verify/Typing/Lemmas.lean | 2636 +++ Ix/Theory/Named/Verify/VLCtx.lean | 88 + Ix/Theory/PORTING.md | 11 + Ix/Theory/Quot.lean | 239 + Ix/Theory/Ref.lean | 23 + Ix/Theory/Rename.lean | 308 + Ix/Theory/Std/Basic.lean | 31 + Ix/Theory/Store.lean | 116 + Ix/Theory/VLevel.lean | 128 + Models/SetTheory/IxSetTheoryModel.lean | 6 + Models/SetTheory/IxSetTheoryModel/Audit.lean | 52 + .../SetTheory/IxSetTheoryModel/Carneiro.lean | 181 + Models/SetTheory/LICENSE-CON-LECHE | 70 + Models/SetTheory/NOTICE | 11 + Models/SetTheory/README.md | 56 + Models/SetTheory/lake-manifest.json | 123 + Models/SetTheory/lakefile.toml | 16 + Models/SetTheory/lean-toolchain | 1 + README.md | 14 + Tests/Certified/CLI.lean | 264 + Tests/Certified/Check.lean | 144 + Tests/Certified/Claims.lean | 375 + Tests/Certified/ClaimsMain.lean | 13 + Tests/Certified/FeatureCases.lean | 284 + Tests/Certified/Features.lean | 13 + Tests/Certified/Fidelity.lean | 132 + Tests/Certified/FidelityMain.lean | 13 + Tests/Certified/ImportManifest.lean | 82 + Tests/Certified/ModelSerialize.lean | 113 + Tests/Certified/Modeled.lean | 140 + Tests/Certified/ModeledAdversarial.lean | 232 + Tests/Certified/ModeledMain.lean | 11 + Tests/Certified/Ordinary.lean | 236 + Tests/Certified/Serialize.lean | 243 + Tests/Certified/Source.lean | 272 + Tests/Certified/SourceMain.lean | 13 + Tests/Certified/foundation.txt | 4243 +++++ Tests/Fixtures/Certified/README.md | 27 + Tests/Fixtures/Certified/c7-handoff.tar.gz | Bin 0 -> 3510635 bytes Tests/Ix/Catalog.lean | 4 +- Tests/Ix/CatalogDedup.lean | 5 +- Tests/Ix/Compile/LevelSpellings.lean | 2 +- Tests/Ix/ImportIxe.lean | 6 +- Tests/Ix/IxVM/Exploits.lean | 4 +- Tests/Ix/{Tc => Kernel}/AccelDiff.lean | 14 +- Tests/Ix/{Tc => Kernel}/AnonDiff.lean | 10 +- Tests/Ix/Kernel/CheckPrimeGaps.lean | 2 +- Tests/Ix/Kernel/CheckTauCetiReduction.lean | 2 +- Tests/Ix/{Tc => Kernel}/CheckTests.lean | 22 +- .../CheckerRoundtrip.lean} | 48 +- Tests/Ix/Kernel/FocusedLeanCheck.lean | 4 +- Tests/Ix/{Tc => Kernel}/InferDefEq.lean | 22 +- Tests/Ix/{Tc => Kernel}/IngressMetaTests.lean | 42 +- Tests/Ix/{Tc => Kernel}/InitScale.lean | 12 +- Tests/Ix/{Tc => Kernel}/IxonFixtures.lean | 12 +- Tests/Ix/{Tc => Kernel}/ParityEnv.lean | 4 +- Tests/Ix/{Tc => Kernel}/Pins.lean | 16 +- Tests/Ix/Kernel/PrimAddrs.lean | 10 +- Tests/Ix/{Tc => Kernel}/Substrate.lean | 10 +- Tests/Ix/{Tc => Kernel}/TutorialTc.lean | 18 +- Tests/Ix/{Tc => Kernel}/Unit.lean | 14 +- Tests/Ix/{Tc => Kernel}/WhnfTests.lean | 12 +- Tests/Ix/Lean4Lean.lean | 37 - Tests/Main.lean | 56 +- Tests/Theory.lean | 22 + Tests/Theory/Acceptance.lean | 161 + Tests/Theory/Audit/Certified.lean | 484 + Tests/Theory/Certified.lean | 76 + Tests/Theory/Checker.lean | 86 + Tests/Theory/Claims.lean | 130 + Tests/Theory/ImportManifest.lean | 176 + Tests/Theory/Modeled.lean | 165 + Tests/Theory/ModeledEquations.lean | 99 + Tests/Theory/ModeledFixtures.lean | 83 + Tests/Theory/ModeledNested.lean | 177 + Tests/Theory/ModeledPermutation.lean | 105 + Tests/Theory/NamedManifest.lean | 123 + Tests/Theory/Natural.lean | 108 + Tests/Theory/Operations.lean | 49 + Tests/Theory/Ordinary.lean | 203 + Tests/Theory/OrdinaryAcceptance.lean | 162 + Tests/Theory/Provenance.lean | 57 + Tests/Theory/Quotient.lean | 144 + Tests/Theory/RecursorGoldens.lean | 45 + Tests/Theory/Standard.lean | 132 + Tests/Theory/Structure.lean | 159 + Tests/Theory/Suggestions.lean | 55 + Tests/Theory/certified-foundation.txt | 10669 +++++++++++ crates/kernel/src/def_eq.rs | 4 +- crates/kernel/src/inductive.rs | 2 +- docs/benchmarking.md | 6 - docs/certified-checking.md | 160 + docs/ix_canonicity.md | 24 +- docs/kernel-verification.md | 144 + docs/tc-context-digest-collision-boundary.md | 2 +- docs/tc-k0-backedge-audit.md | 18 +- docs/theory.md | 68 + flake.nix | 16 - lake-manifest.json | 12 +- lakefile.lean | 210 +- 829 files changed, 167541 insertions(+), 8517 deletions(-) create mode 100644 .github/workflows/set-theory-model.yml delete mode 100644 Benchmarks/Lean4Lean.lean delete mode 100644 Benchmarks/Lean4LeanMain.lean create mode 100644 Ix/Certified.lean create mode 100644 Ix/Certified/Audit.lean create mode 100644 Ix/Certified/AuditAll.lean create mode 100644 Ix/Certified/AuditSupport.lean create mode 100644 Ix/Certified/Bytes.lean create mode 100644 Ix/Certified/ClaimAccept.lean create mode 100644 Ix/Certified/ClaimAudit.lean create mode 100644 Ix/Certified/ClaimCheck.lean create mode 100644 Ix/Certified/ClaimCommand.lean create mode 100644 Ix/Certified/ClaimInput.lean create mode 100644 Ix/Certified/ClaimMain.lean create mode 100644 Ix/Certified/ClaimMeaning.lean create mode 100644 Ix/Certified/ClaimSuggest.lean create mode 100644 Ix/Certified/Command.lean create mode 100644 Ix/Certified/Corpus.lean create mode 100644 Ix/Certified/Envelope.lean create mode 100644 Ix/Certified/Fixtures.lean create mode 100644 Ix/Certified/Ingress.lean create mode 100644 Ix/Certified/Ixon.lean create mode 100644 Ix/Certified/Main.lean create mode 100644 Ix/Certified/ModelHints.lean create mode 100644 Ix/Certified/ModeledAudit.lean create mode 100644 Ix/Certified/NOTICE create mode 100644 Ix/Certified/Reveal.lean create mode 100644 Ix/Certified/SourceAudit.lean create mode 100644 Ix/Certified/SourceExpr.lean create mode 100644 Ix/Certified/SourceMeaning.lean create mode 100644 Ix/Certified/SourceStore.lean create mode 100644 Ix/Certified/Store.lean create mode 100644 Ix/Certified/Suggest.lean create mode 100644 Ix/Certified/TcAudit.lean create mode 100644 Ix/Certified/Trees.lean create mode 100644 Ix/Kernel.lean rename Ix/{Tc => Kernel}/CanonicalCheck.lean (99%) create mode 100644 Ix/Kernel/Certified.lean create mode 100644 Ix/Kernel/CertifiedClaims.lean rename Ix/{Tc => Kernel}/Check.lean (99%) rename Ix/{Tc => Kernel}/Const.lean (98%) rename Ix/{Tc => Kernel}/DefEq.lean (99%) rename Ix/{Tc => Kernel}/Driver.lean (97%) rename Ix/{Tc => Kernel}/Egress.lean (99%) rename Ix/{Tc => Kernel}/EgressLean.lean (99%) rename Ix/{Tc => Kernel}/Env.lean (98%) rename Ix/{Tc => Kernel}/Equiv.lean (99%) rename Ix/{Tc => Kernel}/Error.lean (98%) rename Ix/{Tc => Kernel}/Expr.lean (99%) rename Ix/{Tc => Kernel}/Id.lean (97%) rename Ix/{Tc => Kernel}/Inductive.lean (99%) rename Ix/{Tc => Kernel}/Infer.lean (97%) rename Ix/{Tc => Kernel}/Ingress.lean (99%) rename Ix/{Tc => Kernel}/IngressMeta.lean (99%) rename Ix/{Tc => Kernel}/Knot.lean (94%) rename Ix/{Tc => Kernel}/Lctx.lean (98%) rename Ix/{Tc => Kernel}/Level.lean (97%) rename Ix/{Tc => Kernel}/Mode.lean (98%) rename Ix/{Tc => Kernel}/Monad.lean (98%) rename Ix/{Tc => Kernel}/ParCheck.lean (98%) rename Ix/{Tc => Kernel}/Primitive.lean (99%) rename Ix/{Tc => Kernel}/Subst.lean (99%) rename Ix/{Tc => Kernel}/Validate.lean (98%) rename Ix/{Tc => Kernel}/Verify/Audit/Basic.lean (64%) rename Ix/{Tc => Kernel}/Verify/Audit/Completed.lean (59%) rename Ix/{Tc => Kernel}/Verify/Audit/Conditional.lean (51%) rename Ix/{Tc => Kernel}/Verify/Audit/SorryFrontier.lean (66%) rename Ix/{Tc => Kernel}/Verify/Audit/Statements.lean (50%) rename Ix/{Tc => Kernel}/Verify/Cache.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/Acceptance.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/BinderRoundTrip.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/BlockAcceptance.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/BlockCache.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/BlockClassification.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/BlockDefinition.lean (94%) rename Ix/{Tc => Kernel}/Verify/Check/BlockExecution.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/BlockIdentity.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/BlockNatFixture.lean (97%) rename Ix/{Tc => Kernel}/Verify/Check/BlockOracle.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/BlockRouteFrame.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/BlockRouting.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/BlockTransaction.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/BoundedPipelines.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/CheckConstExecution.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/CheckConstTransaction.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/CheckerEvidence.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/DeclarationIngress.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/DeclarationValidation.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqBasicPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqCachePolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqEtaPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqFinalWhnfPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqLazyDeltaPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqNatPolicy.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqPipelinePolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqProjectionDeltaPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/DefEqPropositionPolicy.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/FullInference.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/FullInferenceApplications.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/FullInferenceBinders.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/FullInferenceCache.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/FullInferenceDispatcher.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/FullInferenceKnot.lean (94%) rename Ix/{Tc => Kernel}/Verify/Check/FullInferenceLeaves.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/FullInferenceProjections.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/InferencePolicy.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/MemberEvidence.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/NatAcceptance.lean (97%) rename Ix/{Tc => Kernel}/Verify/Check/PositiveFuelSort.lean (94%) rename Ix/{Tc => Kernel}/Verify/Check/PreTranslation.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/PreTranslationCompatibility.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/PreTranslationIngress.lean (97%) rename Ix/{Tc => Kernel}/Verify/Check/PreTranslationOpening.lean (97%) rename Ix/{Tc => Kernel}/Verify/Check/PreTranslationScopes.lean (97%) rename Ix/{Tc => Kernel}/Verify/Check/ProjectionInferencePolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/PublicBlocks.lean (80%) rename Ix/{Tc => Kernel}/Verify/Check/PublicStandalone.lean (91%) rename Ix/{Tc => Kernel}/Verify/Check/QuotientAdmission.lean (88%) rename Ix/{Tc => Kernel}/Verify/Check/QuotientBoundary.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/QuotientBridge.lean (94%) rename Ix/{Tc => Kernel}/Verify/Check/RecursiveMethodPolicy.lean (97%) rename Ix/{Tc => Kernel}/Verify/Check/ResetFrame.lean (97%) rename Ix/{Tc => Kernel}/Verify/Check/SafetyFrame.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/Scoped.lean (89%) rename Ix/{Tc => Kernel}/Verify/Check/ScopedActiveBlock.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/ScopedBoundedPipelines.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/ScopedMemberEvidence.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/ScopedPositiveFuelAxiom.lean (96%) rename Ix/{Tc => Kernel}/Verify/Check/ScopedPositiveFuelCertificate.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/ScopedStandaloneDriver.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/SingletonInductive.lean (92%) rename Ix/{Tc => Kernel}/Verify/Check/StandaloneDriver.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/UncachedInferencePolicy.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/UniverseInstantiationPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/ValidationReach.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/ValidatorFrame.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/ValidatorSoundness.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfBasicHelperPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfBitVecPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfDecidablePolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfDriverPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfHelperPolicy.lean (95%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfIotaBasePolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfIotaDispatchPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfIotaRecursionPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfIotaScopePolicy.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfIotaSynthesisPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfNatArgumentPolicy.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfNatPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfNativePolicy.lean (98%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfProjectionPolicy.lean (99%) rename Ix/{Tc => Kernel}/Verify/Check/WhnfReductionPolicy.lean (99%) create mode 100644 Ix/Kernel/Verify/Consistency.lean create mode 100644 Ix/Kernel/Verify/Consistency/Audit.lean create mode 100644 Ix/Kernel/Verify/Consistency/Expr.lean create mode 100644 Ix/Kernel/Verify/Consistency/Infer.lean create mode 100644 Ix/Kernel/Verify/Consistency/Judgment.lean create mode 100644 Ix/Kernel/Verify/Consistency/Level.lean rename Ix/{Tc => Kernel}/Verify/Ctx.lean (96%) rename Ix/{Tc => Kernel}/Verify/Decl.lean (95%) rename Ix/{Tc => Kernel}/Verify/DefEq.lean (99%) rename Ix/{Tc => Kernel}/Verify/DefEq/AcceleratorGates.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/ApplicationSpine.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/BoolTrue.lean (99%) rename Ix/{Tc => Kernel}/Verify/DefEq/CacheBranches.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/CacheShell.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/CheapReduction.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/Closure.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/DeltaClassification.lean (96%) rename Ix/{Tc => Kernel}/Verify/DefEq/EqualRankCache.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/EqualRankPrefix.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/EqualRankReduction.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/Application.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/Closure.lean (91%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/Contracts.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/EtaExpansion.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/LetDeclaration.lean (99%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/NatBridge.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/ProofTail.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/StringExpansion.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/StructuralPrefix.lean (95%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/StructureEta.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/StructureEtaBase.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/StructureEtaFields.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/StructureEtaTail.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/FinalWhnf/UnitLike.lean (96%) rename Ix/{Tc => Kernel}/Verify/DefEq/LazyDelta.lean (99%) rename Ix/{Tc => Kernel}/Verify/DefEq/LazyDeltaClosure.lean (93%) rename Ix/{Tc => Kernel}/Verify/DefEq/LazyDeltaIteration.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/LoopFinish.lean (95%) rename Ix/{Tc => Kernel}/Verify/DefEq/NatOffset.lean (96%) rename Ix/{Tc => Kernel}/Verify/DefEq/NatOffsetDecomposition.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/NatReduction.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/OneSidedDelta.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaActive.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaClosure.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaEqualRank.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaFinish.lean (96%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaLoop.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaRank.lean (95%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaStep.lean (96%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionDeltaUnfolding.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionProbe.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProjectionReduction.lean (96%) rename Ix/{Tc => Kernel}/Verify/DefEq/ProofIrrelevance.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/PropositionClassifier.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/RankDispatch.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/SameHeadSpine.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/SpineArguments.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/StoppedContinuation.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/StoppedContinuationClosure.lean (94%) rename Ix/{Tc => Kernel}/Verify/DefEq/StringLiteral.lean (98%) rename Ix/{Tc => Kernel}/Verify/DefEq/Structural.lean (97%) rename Ix/{Tc => Kernel}/Verify/DefEq/StructuralCongruence.lean (97%) rename Ix/{Tc => Kernel}/Verify/Driver/BooleanAcceptance.lean (99%) rename Ix/{Tc => Kernel}/Verify/Driver/Dependencies.lean (99%) rename Ix/{Tc => Kernel}/Verify/Driver/Enumeration.lean (99%) rename Ix/{Tc => Kernel}/Verify/Driver/Fixtures.lean (98%) rename Ix/{Tc => Kernel}/Verify/Driver/Model.lean (97%) rename Ix/{Tc => Kernel}/Verify/Driver/Serial.lean (95%) rename Ix/{Tc => Kernel}/Verify/Driver/SupportedAcceptance.lean (96%) rename Ix/{Tc => Kernel}/Verify/Driver/SupportedAcceptanceFixtures.lean (95%) rename Ix/{Tc => Kernel}/Verify/Env.lean (98%) rename Ix/{Tc => Kernel}/Verify/EquivalenceManager.lean (99%) rename Ix/{Tc => Kernel}/Verify/Execution.lean (99%) rename Ix/{Tc => Kernel}/Verify/Expr.lean (99%) rename Ix/{Tc => Kernel}/Verify/Frame.lean (98%) rename Ix/{Tc/Verify/Upstream => Kernel/Verify/Frontier}/Pending.lean (69%) rename Ix/{Tc => Kernel}/Verify/Inductive.lean (94%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasFormerAdmission.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasFormerCertificate.lean (91%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasFormerFixture.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasFormerPattern.lean (90%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasFormerRecursorFixture.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasRecAdmission.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasRecCertificate.lean (91%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasRecFixture.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasRecPattern.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasRecRecursorFixture.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/AliasRecSoundness.lean (95%) rename Ix/{Tc => Kernel}/Verify/Inductive/AnnotatedPiAdmission.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/AnnotatedPiCertificate.lean (91%) rename Ix/{Tc => Kernel}/Verify/Inductive/AnnotatedPiFixture.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/AnnotatedPiPattern.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/AnnotatedPiRecursorFixture.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/AnnotatedPiSoundness.lean (95%) rename Ix/{Tc => Kernel}/Verify/Inductive/BlockCertificate.lean (91%) rename Ix/{Tc => Kernel}/Verify/Inductive/BlockPatternSoundness.lean (90%) rename Ix/{Tc => Kernel}/Verify/Inductive/CandidateSyntax.lean (95%) rename Ix/{Tc => Kernel}/Verify/Inductive/Certificate.lean (94%) rename Ix/{Tc => Kernel}/Verify/Inductive/ConcreteFixture.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/ConstructorPositivityTraversal.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/ConstructorValidationTraversal.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/EliminationBreadthFixture.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/EnumerationAcceptance.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/EnumerationFixture.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/ExactLeanSyntax.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorAcceptance.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorAdmission.lean (95%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorCheckerFixture.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorCommitFixture.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorComparison.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorInitialInvariant.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorMemberCheck.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorMemberFixture.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorMetadata.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorRuleFixture.lean (94%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorSelection.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorSemantics.lean (94%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorTypeClosure.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/GeneratedRecursorTypeFixture.lean (92%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedBlockValidation.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedCandidateOperations.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedCandidateSyntax.lean (81%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedCandidateTransaction.lean (78%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedConstructorPositivity.lean (91%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedConstructorValidation.lean (85%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedPositivityTransport.lean (90%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedProducerClosure.lean (84%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedProductionPositivity.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedRecursiveAcceptance.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedRecursiveCertificate.lean (91%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedRecursiveFixture.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedRecursiveOracle.lean (93%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedRecursivePattern.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/IndexedRecursiveSoundness.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/IngressExecution.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/IotaPattern.lean (79%) rename Ix/{Tc => Kernel}/Verify/Inductive/MutualBlockCertificate.lean (85%) rename Ix/{Tc => Kernel}/Verify/Inductive/MutualBlockFixture.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/MutualBlockValidation.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/MutualFamily.lean (94%) rename Ix/{Tc => Kernel}/Verify/Inductive/MutualFamilyAdmission.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/MutualRecursor.lean (94%) rename Ix/{Tc => Kernel}/Verify/Inductive/MutualRecursorAdmission.lean (92%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedAdmission.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedAuxiliaryExpansion.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedAuxiliaryPositivity.lean (93%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedBlockCertificate.lean (95%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedCandidateSyntax.lean (85%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedConstructorValidation.lean (78%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedPositivityTransport.lean (84%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedPositivityTraversal.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedRecursiveFixture.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedRecursorAdmission.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedRecursorFixture.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedRecursorPattern.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedRecursorSoundness.lean (95%) rename Ix/{Tc => Kernel}/Verify/Inductive/NestedSemanticTransaction.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/OccurrenceClosure.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/OccurrenceValidation.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/OneFamilyAdmission.lean (90%) rename Ix/{Tc => Kernel}/Verify/Inductive/PositivityTraceAdapter.lean (85%) rename Ix/{Tc => Kernel}/Verify/Inductive/PositivityTraversal.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/ProducedGenerationTransaction.lean (91%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePiAcceptance.lean (95%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePiAdmission.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePiCertificate.lean (89%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePiFixture.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePiPattern.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePiRecursorFixture.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePiSoundness.lean (94%) rename Ix/{Tc => Kernel}/Verify/Inductive/RecursivePositivityTraversal.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/ResultSortTelescope.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/RuleApplication.lean (98%) rename Ix/{Tc => Kernel}/Verify/Inductive/SingletonEnumeration.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/SingletonFamily.lean (99%) rename Ix/{Tc => Kernel}/Verify/Inductive/SingletonIngress.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/SingletonOracle.lean (96%) rename Ix/{Tc => Kernel}/Verify/Inductive/SingletonRecursor.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/SpecializationIdentity.lean (97%) rename Ix/{Tc => Kernel}/Verify/Inductive/StructuralCacheSemantics.lean (99%) rename Ix/{Tc => Kernel}/Verify/Infer.lean (99%) rename Ix/{Tc => Kernel}/Verify/Infer/Applications.lean (97%) rename Ix/{Tc => Kernel}/Verify/Infer/BinderClosing.lean (98%) rename Ix/{Tc => Kernel}/Verify/Infer/BinderOpening.lean (98%) rename Ix/{Tc => Kernel}/Verify/Infer/BinderScopes.lean (98%) rename Ix/{Tc => Kernel}/Verify/Infer/CacheShell.lean (99%) rename Ix/{Tc => Kernel}/Verify/Infer/CacheSoundness.lean (97%) rename Ix/{Tc => Kernel}/Verify/Infer/Callbacks.lean (92%) rename Ix/{Tc => Kernel}/Verify/Infer/CheapBeta.lean (98%) rename Ix/{Tc => Kernel}/Verify/Infer/Constants.lean (96%) rename Ix/{Tc => Kernel}/Verify/Infer/Dispatcher.lean (94%) rename Ix/{Tc => Kernel}/Verify/Infer/ForallTypes.lean (95%) rename Ix/{Tc => Kernel}/Verify/Infer/FunctionTypes.lean (94%) rename Ix/{Tc => Kernel}/Verify/Infer/LambdaTypes.lean (95%) rename Ix/{Tc => Kernel}/Verify/Infer/LeafCases.lean (96%) rename Ix/{Tc => Kernel}/Verify/Infer/LetScopes.lean (99%) rename Ix/{Tc => Kernel}/Verify/Infer/LetTypes.lean (95%) rename Ix/{Tc => Kernel}/Verify/Infer/Literals.lean (88%) rename Ix/{Tc => Kernel}/Verify/Infer/ProjectionClassification.lean (97%) rename Ix/{Tc => Kernel}/Verify/Infer/ProjectionTelescope.lean (94%) rename Ix/{Tc => Kernel}/Verify/Infer/ProjectionTypes.lean (97%) rename Ix/{Tc => Kernel}/Verify/Infer/ScopedLocals.lean (97%) rename Ix/{Tc => Kernel}/Verify/Infer/SortTypes.lean (92%) rename Ix/{Tc => Kernel}/Verify/Infer/Substitution.lean (93%) rename Ix/{Tc => Kernel}/Verify/InferDefEq/Closure.lean (96%) rename Ix/{Tc => Kernel}/Verify/Ingress/AnonStructural.lean (94%) rename Ix/{Tc => Kernel}/Verify/Ingress/LiteralBlobs.lean (99%) rename Ix/{Tc => Kernel}/Verify/Ingress/Representation.lean (98%) rename Ix/{Tc => Kernel}/Verify/Ingress/SerializedBoolean.lean (99%) rename Ix/{Tc => Kernel}/Verify/InstL.lean (95%) rename Ix/{Tc => Kernel}/Verify/InstUniv.lean (99%) rename Ix/{Tc => Kernel}/Verify/Knot.lean (99%) rename Ix/{Tc => Kernel}/Verify/Level.lean (98%) rename Ix/{Tc => Kernel}/Verify/Monad.lean (98%) rename Ix/{Tc => Kernel}/Verify/NatFixture.lean (98%) rename Ix/{Tc => Kernel}/Verify/Projection/Concrete.lean (75%) rename Ix/{Tc => Kernel}/Verify/Projection/ConcreteFixture.lean (80%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/CallDomains.lean (98%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/Closure.lean (96%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/FiniteSupportBoundary.lean (98%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/Inference.lean (96%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/Public.lean (94%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/ScopedCallDomains.lean (96%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/ScopedInference.lean (98%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/ScopedSortInference.lean (96%) rename Ix/{Tc => Kernel}/Verify/RecursiveMethods/SortInference.lean (96%) rename Ix/{Tc => Kernel}/Verify/Run.lean (97%) rename Ix/{Tc => Kernel}/Verify/ScopedSuffix/ClosedContext.lean (98%) rename Ix/{Tc => Kernel}/Verify/State.lean (98%) rename Ix/{Tc => Kernel}/Verify/Statements.lean (89%) rename Ix/{Tc => Kernel}/Verify/Subst.lean (99%) rename Ix/{Tc => Kernel}/Verify/Suffix.lean (99%) rename Ix/{Tc => Kernel}/Verify/Support.lean (99%) rename Ix/{Tc => Kernel}/Verify/Totalization.lean (99%) rename Ix/{Tc => Kernel}/Verify/Trans.lean (94%) rename Ix/{Tc => Kernel}/Verify/VLCtx.lean (93%) rename Ix/{Tc => Kernel}/Verify/Whnf.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/ArgumentAlignment.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/ConsumptionBoundary.lean (87%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/DependentContexts.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/InstantiationChain.lean (95%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/LambdaInstantiation.lean (83%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/LambdaPeeling.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/LiftSubstitution.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/Meaning.lean (94%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/PeelTrace.lean (81%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/PrefixSemantics.lean (95%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/SemanticCore.lean (95%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/SimultaneousSubstitution.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/SingletonSubstitution.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Beta/Translation.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Closure.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/CacheExecution.lean (96%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/CacheSemantics.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/ClosedTranslation.lean (80%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/Integration.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/OptionalReduction.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/SpineUnfolding.lean (96%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/StableCache.lean (94%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/TrustedBody.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/UnfoldingState.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Delta/UniverseMonotonicity.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Driver/FullStep.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Driver/PublicReducers.lean (94%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/ApplicationRequests.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/ArgumentBranches.lean (95%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/ArgumentExecution.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/ConstructorDispatch.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/ConstructorSynthesis.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/ConstructorSynthesisFallback.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/Ingress.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/NatLiteral.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/NatOffset.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/NatPatternMatching.lean (86%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/NatRecognizer.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/NatReduction.lean (91%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/NatRuleLayout.lean (96%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/OptionalReduction.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/RuleInstantiation.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/RuleSuffixTransport.lean (94%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/SelectedRule.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/StringLiteral.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/StructEtaControl.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/Substitution.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Iota/SynthesisRequests.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/NoDelta/BaseReductions.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/NoDelta/ProjectionApplication.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/NoDelta/ProjectionDefinition.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/NoDelta/Quotient.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/NoDelta/QuotientReflection.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/NoDelta/Reducer.lean (94%) rename Ix/{Tc => Kernel}/Verify/Whnf/NoDelta/StringPrimitive.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Projection/NoAccelTail.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/Projection/StringCallback.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Projection/StringExpansion.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/README.md (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Runtime/LazyIngress.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/RuntimeContracts.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/CallbackPrefix.lean (96%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/Classifier.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/ExactMajorTelescope.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/Rebuild.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/RebuildRequests.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/RebuildTail.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/RecursionClassifier.lean (99%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/ScopedClassifier.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/StructEta/ScopedTelescope.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/ApplicationCongruence.lean (92%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/ApplicationRebuild.lean (94%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/ApplicationStep.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/ApplicationTails.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/BasicStep.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/BetaBoundary.lean (96%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/CacheShell.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/ProjectionStep.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/RecursiveCallbacks.lean (93%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/Reducer.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/StepAssembly.lean (97%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/VariableStep.lean (98%) rename Ix/{Tc => Kernel}/Verify/Whnf/Structural/VerifiedStep.lean (96%) rename Ix/{Tc => Kernel}/Verify/World.lean (98%) rename Ix/{Tc => Kernel}/Whnf.lean (99%) delete mode 100644 Ix/Tc.lean create mode 100644 Ix/Theory.lean create mode 100644 Ix/Theory/Certificate/Build.lean create mode 100644 Ix/Theory/Certificate/Claims.lean create mode 100644 Ix/Theory/Certificate/Modeled.lean create mode 100644 Ix/Theory/Certificate/Ordinary.lean create mode 100644 Ix/Theory/Certificate/OrdinarySource.lean create mode 100644 Ix/Theory/Certificate/Quotient.lean create mode 100644 Ix/Theory/Certificate/Standard.lean create mode 100644 Ix/Theory/Certificate/Structure.lean create mode 100644 Ix/Theory/Certificate/Suggest.lean create mode 100644 Ix/Theory/Certified.lean create mode 100644 Ix/Theory/Certified/Accept.lean create mode 100644 Ix/Theory/Certified/Admission.lean create mode 100644 Ix/Theory/Certified/Basis/Equality.lean create mode 100644 Ix/Theory/Certified/Basis/Iff.lean create mode 100644 Ix/Theory/Certified/Basis/Interface.lean create mode 100644 Ix/Theory/Certified/Basis/Nonempty.lean create mode 100644 Ix/Theory/Certified/Checker.lean create mode 100644 Ix/Theory/Certified/ClaimComposition.lean create mode 100644 Ix/Theory/Certified/Claims.lean create mode 100644 Ix/Theory/Certified/Frontier.lean create mode 100644 Ix/Theory/Certified/Level.lean create mode 100644 Ix/Theory/Certified/LevelEq.lean create mode 100644 Ix/Theory/Certified/LogicalPolicy.lean create mode 100644 Ix/Theory/Certified/Modeled/Admission.lean create mode 100644 Ix/Theory/Certified/Modeled/Equation.lean create mode 100644 Ix/Theory/Certified/Modeled/Source.lean create mode 100644 Ix/Theory/Certified/Modeled/Transport.lean create mode 100644 Ix/Theory/Certified/Natural/Admission.lean create mode 100644 Ix/Theory/Certified/Natural/Checked.lean create mode 100644 Ix/Theory/Certified/Natural/Publish.lean create mode 100644 Ix/Theory/Certified/Natural/Value.lean create mode 100644 Ix/Theory/Certified/Operations.lean create mode 100644 Ix/Theory/Certified/Ordinary/Admission.lean create mode 100644 Ix/Theory/Certified/Ordinary/Checked.lean create mode 100644 Ix/Theory/Certified/Ordinary/Computation.lean create mode 100644 Ix/Theory/Certified/Ordinary/ConstructorStage.lean create mode 100644 Ix/Theory/Certified/Ordinary/Constructors.lean create mode 100644 Ix/Theory/Certified/Ordinary/Container.lean create mode 100644 Ix/Theory/Certified/Ordinary/Eliminator.lean create mode 100644 Ix/Theory/Certified/Ordinary/Family.lean create mode 100644 Ix/Theory/Certified/Ordinary/LargeElim.lean create mode 100644 Ix/Theory/Certified/Ordinary/Reading.lean create mode 100644 Ix/Theory/Certified/Ordinary/RecursorReading.lean create mode 100644 Ix/Theory/Certified/Ordinary/RecursorStage.lean create mode 100644 Ix/Theory/Certified/Ordinary/RecursorSyntax.lean create mode 100644 Ix/Theory/Certified/Ordinary/RecursorValue.lean create mode 100644 Ix/Theory/Certified/Ordinary/RuleChecks.lean create mode 100644 Ix/Theory/Certified/Ordinary/RuleEquations.lean create mode 100644 Ix/Theory/Certified/Ordinary/RuleReading.lean create mode 100644 Ix/Theory/Certified/Ordinary/Shape.lean create mode 100644 Ix/Theory/Certified/Policy.lean create mode 100644 Ix/Theory/Certified/Prelude.lean create mode 100644 Ix/Theory/Certified/PropWhen.lean create mode 100644 Ix/Theory/Certified/Quotient/Admission.lean create mode 100644 Ix/Theory/Certified/Quotient/Checked.lean create mode 100644 Ix/Theory/Certified/Quotient/Publish.lean create mode 100644 Ix/Theory/Certified/Quotient/Reading.lean create mode 100644 Ix/Theory/Certified/Quotient/Syntax.lean create mode 100644 Ix/Theory/Certified/Quotient/Value.lean create mode 100644 Ix/Theory/Certified/Signature.lean create mode 100644 Ix/Theory/Certified/Source.lean create mode 100644 Ix/Theory/Certified/Standard/Admission.lean create mode 100644 Ix/Theory/Certified/Standard/Checked.lean create mode 100644 Ix/Theory/Certified/Standard/Realization.lean create mode 100644 Ix/Theory/Certified/Store.lean create mode 100644 Ix/Theory/Certified/Structure/Admission.lean create mode 100644 Ix/Theory/Certified/Structure/Checked.lean create mode 100644 Ix/Theory/Certified/Structure/Computation.lean create mode 100644 Ix/Theory/Certified/Structure/Publish.lean create mode 100644 Ix/Theory/Certified/Structure/Reading.lean create mode 100644 Ix/Theory/Certified/Structure/Syntax.lean create mode 100644 Ix/Theory/Certified/Structure/Value.lean create mode 100644 Ix/Theory/Certified/Telescope.lean create mode 100644 Ix/Theory/Const.lean create mode 100644 Ix/Theory/Expr.lean create mode 100644 Ix/Theory/Inductive/Levels.lean create mode 100644 Ix/Theory/LICENSE create mode 100644 Ix/Theory/LICENSE-APACHE create mode 100644 Ix/Theory/LICENSE-MIT create mode 100644 Ix/Theory/Model/Annotated.lean create mode 100644 Ix/Theory/Model/Context.lean create mode 100644 Ix/Theory/Model/Environment.lean create mode 100644 Ix/Theory/Model/Extension.lean create mode 100644 Ix/Theory/Model/Inductive/Codes.lean create mode 100644 Ix/Theory/Model/Inductive/Container.lean create mode 100644 Ix/Theory/Model/Inductive/Recursor.lean create mode 100644 Ix/Theory/Model/Inductive/Telescope.lean create mode 100644 Ix/Theory/Model/Instantiation.lean create mode 100644 Ix/Theory/Model/Interpret.lean create mode 100644 Ix/Theory/Model/Judgment.lean create mode 100644 Ix/Theory/Model/PrimitiveValues.lean create mode 100644 Ix/Theory/Model/ReferenceMap.lean create mode 100644 Ix/Theory/Model/SetModel/Container.lean create mode 100644 Ix/Theory/Model/SetModel/Iter.lean create mode 100644 Ix/Theory/Model/SetModel/Ops.lean create mode 100644 Ix/Theory/Model/SetModel/RecGraph.lean create mode 100644 Ix/Theory/Model/SetModel/TaggedSum.lean create mode 100644 Ix/Theory/Model/SetModel/TupleTower.lean create mode 100644 Ix/Theory/Model/SetTheory/Core.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Choice.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Empty.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Graphs.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Lfp.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/LfpFam.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Omega.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Pair.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Pt.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Quot.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Sep.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Sigma.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Univ.lean create mode 100644 Ix/Theory/Model/SetTheory/Derive/Universe.lean create mode 100644 Ix/Theory/Model/Signature.lean create mode 100644 Ix/Theory/Model/Support.lean create mode 100644 Ix/Theory/Model/TelescopeSemantics.lean create mode 100644 Ix/Theory/Model/Value.lean create mode 100644 Ix/Theory/Model/WellDenoted.lean create mode 100644 Ix/Theory/NOTICE create mode 100644 Ix/Theory/Named/ConstructorValidityFixtures.lean create mode 100644 Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean create mode 100644 Ix/Theory/Named/Inductive.lean create mode 100644 Ix/Theory/Named/InductiveFixtures.lean create mode 100644 Ix/Theory/Named/LICENSE create mode 100644 Ix/Theory/Named/Literals.lean create mode 100644 Ix/Theory/Named/LocalContext.lean create mode 100644 Ix/Theory/Named/Meta.lean create mode 100644 Ix/Theory/Named/MutualInductiveFixtures.lean create mode 100644 Ix/Theory/Named/NOTICE create mode 100644 Ix/Theory/Named/NestedInductive.lean create mode 100644 Ix/Theory/Named/NestedInductiveFixtures.lean create mode 100644 Ix/Theory/Named/Projection.lean create mode 100644 Ix/Theory/Named/Quot.lean create mode 100644 Ix/Theory/Named/Reference/Declaration.lean create mode 100644 Ix/Theory/Named/Reference/Environment.lean create mode 100644 Ix/Theory/Named/Reference/Environment/Basic.lean create mode 100644 Ix/Theory/Named/Reference/Expr.lean create mode 100644 Ix/Theory/Named/Reference/ForEachExprV.lean create mode 100644 Ix/Theory/Named/Reference/FuelConfig.lean create mode 100644 Ix/Theory/Named/Reference/Inductive/Add.lean create mode 100644 Ix/Theory/Named/Reference/Inductive/EliminationTrace.lean create mode 100644 Ix/Theory/Named/Reference/Inductive/Reduce.lean create mode 100644 Ix/Theory/Named/Reference/Inductive/ValidationTrace.lean create mode 100644 Ix/Theory/Named/Reference/Instantiate.lean create mode 100644 Ix/Theory/Named/Reference/Level.lean create mode 100644 Ix/Theory/Named/Reference/List.lean create mode 100644 Ix/Theory/Named/Reference/LocalContext.lean create mode 100644 Ix/Theory/Named/Reference/Primitive.lean create mode 100644 Ix/Theory/Named/Reference/PtrEq.lean create mode 100644 Ix/Theory/Named/Reference/Quot.lean create mode 100644 Ix/Theory/Named/Reference/TypeChecker.lean create mode 100644 Ix/Theory/Named/SingletonParity.lean create mode 100644 Ix/Theory/Named/Std/AxiomAudit.lean create mode 100644 Ix/Theory/Named/Std/Basic.lean create mode 100644 Ix/Theory/Named/Std/Control.lean create mode 100644 Ix/Theory/Named/Std/HashMap.lean create mode 100644 Ix/Theory/Named/Std/NodupKeys.lean create mode 100644 Ix/Theory/Named/Std/Ord.lean create mode 100644 Ix/Theory/Named/Std/PersistentHashMap.lean create mode 100644 Ix/Theory/Named/Std/SMap.lean create mode 100644 Ix/Theory/Named/Std/ToExpr.lean create mode 100644 Ix/Theory/Named/Std/VariableBang.lean create mode 100644 Ix/Theory/Named/Typing/Basic.lean create mode 100644 Ix/Theory/Named/Typing/Env.lean create mode 100644 Ix/Theory/Named/Typing/EnvLemmas.lean create mode 100644 Ix/Theory/Named/Typing/InductiveCertificate.lean create mode 100644 Ix/Theory/Named/Typing/InductiveLemmas.lean create mode 100644 Ix/Theory/Named/Typing/InductivePattern.lean create mode 100644 Ix/Theory/Named/Typing/InductivePatternWF.lean create mode 100644 Ix/Theory/Named/Typing/Injectivity.lean create mode 100644 Ix/Theory/Named/Typing/Lemmas.lean create mode 100644 Ix/Theory/Named/Typing/Meta.lean create mode 100644 Ix/Theory/Named/Typing/NestedInductiveLemmas.lean create mode 100644 Ix/Theory/Named/Typing/Pattern.lean create mode 100644 Ix/Theory/Named/Typing/QuotLemmas.lean create mode 100644 Ix/Theory/Named/Typing/Strong.lean create mode 100644 Ix/Theory/Named/Typing/UniqueTyping.lean create mode 100644 Ix/Theory/Named/VDecl.lean create mode 100644 Ix/Theory/Named/VEnv.lean create mode 100644 Ix/Theory/Named/VExpr.lean create mode 100644 Ix/Theory/Named/VLevel.lean create mode 100644 Ix/Theory/Named/Verify/Axioms.lean create mode 100644 Ix/Theory/Named/Verify/Environment/Basic.lean create mode 100644 Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean create mode 100644 Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean create mode 100644 Ix/Theory/Named/Verify/Environment/Elimination.lean create mode 100644 Ix/Theory/Named/Verify/Environment/EliminationFixturesCommon.lean create mode 100644 Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean create mode 100644 Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean create mode 100644 Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean create mode 100644 Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean create mode 100644 Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean create mode 100644 Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean create mode 100644 Ix/Theory/Named/Verify/Environment/IndexedVecCandidate.lean create mode 100644 Ix/Theory/Named/Verify/Environment/IndexedVecConsReplay.lean create mode 100644 Ix/Theory/Named/Verify/Environment/IndexedVecConstructors.lean create mode 100644 Ix/Theory/Named/Verify/Environment/IndexedVecOuterReplay.lean create mode 100644 Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean create mode 100644 Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean create mode 100644 Ix/Theory/Named/Verify/Environment/Lemmas.lean create mode 100644 Ix/Theory/Named/Verify/Environment/MutualInductiveFixtures.lean create mode 100644 Ix/Theory/Named/Verify/Environment/NestedReplay.lean create mode 100644 Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean create mode 100644 Ix/Theory/Named/Verify/Environment/NestedTransformation.lean create mode 100644 Ix/Theory/Named/Verify/Environment/Normalization.lean create mode 100644 Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean create mode 100644 Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean create mode 100644 Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean create mode 100644 Ix/Theory/Named/Verify/Expr.lean create mode 100644 Ix/Theory/Named/Verify/Level.lean create mode 100644 Ix/Theory/Named/Verify/LevelStd.lean create mode 100644 Ix/Theory/Named/Verify/LocalContext.lean create mode 100644 Ix/Theory/Named/Verify/Name.lean create mode 100644 Ix/Theory/Named/Verify/NameGenerator.lean create mode 100644 Ix/Theory/Named/Verify/NormLt.lean create mode 100644 Ix/Theory/Named/Verify/QSort.lean create mode 100644 Ix/Theory/Named/Verify/TypeChecker.lean create mode 100644 Ix/Theory/Named/Verify/TypeChecker/Basic.lean create mode 100644 Ix/Theory/Named/Verify/TypeChecker/InferType.lean create mode 100644 Ix/Theory/Named/Verify/TypeChecker/IsDefEq.lean create mode 100644 Ix/Theory/Named/Verify/TypeChecker/Reduce.lean create mode 100644 Ix/Theory/Named/Verify/TypeChecker/WHNF.lean create mode 100644 Ix/Theory/Named/Verify/Typing/ConditionallyTyped.lean create mode 100644 Ix/Theory/Named/Verify/Typing/Expr.lean create mode 100644 Ix/Theory/Named/Verify/Typing/Lemmas.lean create mode 100644 Ix/Theory/Named/Verify/VLCtx.lean create mode 100644 Ix/Theory/PORTING.md create mode 100644 Ix/Theory/Quot.lean create mode 100644 Ix/Theory/Ref.lean create mode 100644 Ix/Theory/Rename.lean create mode 100644 Ix/Theory/Std/Basic.lean create mode 100644 Ix/Theory/Store.lean create mode 100644 Ix/Theory/VLevel.lean create mode 100644 Models/SetTheory/IxSetTheoryModel.lean create mode 100644 Models/SetTheory/IxSetTheoryModel/Audit.lean create mode 100644 Models/SetTheory/IxSetTheoryModel/Carneiro.lean create mode 100644 Models/SetTheory/LICENSE-CON-LECHE create mode 100644 Models/SetTheory/NOTICE create mode 100644 Models/SetTheory/README.md create mode 100644 Models/SetTheory/lake-manifest.json create mode 100644 Models/SetTheory/lakefile.toml create mode 100644 Models/SetTheory/lean-toolchain create mode 100644 Tests/Certified/CLI.lean create mode 100644 Tests/Certified/Check.lean create mode 100644 Tests/Certified/Claims.lean create mode 100644 Tests/Certified/ClaimsMain.lean create mode 100644 Tests/Certified/FeatureCases.lean create mode 100644 Tests/Certified/Features.lean create mode 100644 Tests/Certified/Fidelity.lean create mode 100644 Tests/Certified/FidelityMain.lean create mode 100644 Tests/Certified/ImportManifest.lean create mode 100644 Tests/Certified/ModelSerialize.lean create mode 100644 Tests/Certified/Modeled.lean create mode 100644 Tests/Certified/ModeledAdversarial.lean create mode 100644 Tests/Certified/ModeledMain.lean create mode 100644 Tests/Certified/Ordinary.lean create mode 100644 Tests/Certified/Serialize.lean create mode 100644 Tests/Certified/Source.lean create mode 100644 Tests/Certified/SourceMain.lean create mode 100644 Tests/Certified/foundation.txt create mode 100644 Tests/Fixtures/Certified/README.md create mode 100644 Tests/Fixtures/Certified/c7-handoff.tar.gz rename Tests/Ix/{Tc => Kernel}/AccelDiff.lean (93%) rename Tests/Ix/{Tc => Kernel}/AnonDiff.lean (96%) rename Tests/Ix/{Tc => Kernel}/CheckTests.lean (98%) rename Tests/Ix/{Tc/Roundtrip.lean => Kernel/CheckerRoundtrip.lean} (92%) rename Tests/Ix/{Tc => Kernel}/InferDefEq.lean (97%) rename Tests/Ix/{Tc => Kernel}/IngressMetaTests.lean (96%) rename Tests/Ix/{Tc => Kernel}/InitScale.lean (94%) rename Tests/Ix/{Tc => Kernel}/IxonFixtures.lean (98%) rename Tests/Ix/{Tc => Kernel}/ParityEnv.lean (97%) rename Tests/Ix/{Tc => Kernel}/Pins.lean (94%) rename Tests/Ix/{Tc => Kernel}/Substrate.lean (98%) rename Tests/Ix/{Tc => Kernel}/TutorialTc.lean (96%) rename Tests/Ix/{Tc => Kernel}/Unit.lean (98%) rename Tests/Ix/{Tc => Kernel}/WhnfTests.lean (98%) delete mode 100644 Tests/Ix/Lean4Lean.lean create mode 100644 Tests/Theory.lean create mode 100644 Tests/Theory/Acceptance.lean create mode 100644 Tests/Theory/Audit/Certified.lean create mode 100644 Tests/Theory/Certified.lean create mode 100644 Tests/Theory/Checker.lean create mode 100644 Tests/Theory/Claims.lean create mode 100644 Tests/Theory/ImportManifest.lean create mode 100644 Tests/Theory/Modeled.lean create mode 100644 Tests/Theory/ModeledEquations.lean create mode 100644 Tests/Theory/ModeledFixtures.lean create mode 100644 Tests/Theory/ModeledNested.lean create mode 100644 Tests/Theory/ModeledPermutation.lean create mode 100644 Tests/Theory/NamedManifest.lean create mode 100644 Tests/Theory/Natural.lean create mode 100644 Tests/Theory/Operations.lean create mode 100644 Tests/Theory/Ordinary.lean create mode 100644 Tests/Theory/OrdinaryAcceptance.lean create mode 100644 Tests/Theory/Provenance.lean create mode 100644 Tests/Theory/Quotient.lean create mode 100644 Tests/Theory/RecursorGoldens.lean create mode 100644 Tests/Theory/Standard.lean create mode 100644 Tests/Theory/Structure.lean create mode 100644 Tests/Theory/Suggestions.lean create mode 100644 Tests/Theory/certified-foundation.txt create mode 100644 docs/certified-checking.md create mode 100644 docs/kernel-verification.md create mode 100644 docs/theory.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 267f0b62e..db8944612 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,8 @@ jobs: with: build-args: "--wfail -v" test: false - # build-all lint driver compiles every lib/exe target with --wfail, so a + # build-all checks production targets and the consistency foundation + # with --wfail. Named implementation proofs have a separate trust gate. A # warning in any target (exes, benchmarks, Apps) — not just the default lib # lean-action builds above — fails CI. - name: Build all targets @@ -86,6 +87,30 @@ jobs: use-github-cache: false - name: Test Ix CLI run: lake test --wfail -- cli + - name: Check certified source and claim adapters + run: lake run check-certified + + theory: + needs: build + runs-on: warp-ubuntu-latest-x64-16x + steps: + - uses: actions/checkout@v7 + - uses: ./.github/actions/setup-rust-toolchain + - uses: actions/cache/restore@v6 + with: + path: ./.lake + key: lake-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('lean-toolchain') }}-${{ hashFiles('lake-manifest.json') }}-${{ github.sha }} + restore-keys: lake-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('lean-toolchain') }}-${{ hashFiles('lake-manifest.json') }}- + - uses: leanprover/lean-action@v1 + with: + auto-config: false + use-github-cache: false + - name: Check implementation proofs and exact trust manifests + run: lake build IxKernelVerify IxCompileVerify + - name: Check direct kernel consistency refinement + run: lake build --wfail IxKernelConsistency + - name: Check consistency model and exact foundation manifest + run: lake run check-theory rust-test: runs-on: warp-ubuntu-latest-x64-8x diff --git a/.github/workflows/merge-tests.yml b/.github/workflows/merge-tests.yml index dccdf83cd..420798b0b 100644 --- a/.github/workflows/merge-tests.yml +++ b/.github/workflows/merge-tests.yml @@ -47,13 +47,13 @@ jobs: - name: Valgrind FFI kind: valgrind runner: warp-ubuntu-latest-x64-8x - - name: Ix.Tc verification and parity + - name: Ix.Kernel verification and parity kind: tc runner: warp-ubuntu-latest-x64-16x test_args: >- --ignored tc-anon-diff tc-init tc-tutorial tc-roundtrip tc-ingress-meta - tc-pins tc-accel-diff lean4lean + tc-pins tc-accel-diff runs-on: ${{ matrix.runner }} steps: - name: Validate merge-test variant @@ -147,19 +147,22 @@ jobs: --suppressions=.github/valgrind.supp \ .lake/build/bin/IxTests ffi - - name: Check Ix.Tc exported theorem trust manifest + - name: Check Ix.Kernel exported theorem trust manifest if: ${{ matrix.kind == 'tc' }} - run: lake build Ix.Tc.Verify.Audit.Completed Ix.Tc.Verify.Audit.Conditional Ix.Tc.Verify.Audit.Statements - - name: Build Ix.Tc formal verification + run: lake build Ix.Kernel.Verify.Audit.Completed Ix.Kernel.Verify.Audit.Conditional Ix.Kernel.Verify.Audit.Statements + - name: Build Ix.Kernel formal verification if: ${{ matrix.kind == 'tc' }} - run: lake build IxTcVerify - - name: Check Ix.Tc verification sorry frontier + run: lake build IxKernelVerify IxCompileVerify + - name: Check Ix.Kernel consistency refinement if: ${{ matrix.kind == 'tc' }} - run: lake build Ix.Tc.Verify.Audit.SorryFrontier - - name: Test Ix.Tc unit and adversarial fixtures + run: lake build --wfail IxKernelConsistency + - name: Check Ix.Kernel verification sorry frontier + if: ${{ matrix.kind == 'tc' }} + run: lake build Ix.Kernel.Verify.Audit.SorryFrontier + - name: Test Ix.Kernel unit and adversarial fixtures if: ${{ matrix.kind == 'tc' }} run: lake test --wfail -- tc-unit - - name: Run Ix.Tc ignored tests + - name: Run Ix.Kernel ignored tests if: ${{ matrix.kind == 'tc' }} run: lake test --wfail -- ${{ matrix.test_args }} diff --git a/.github/workflows/set-theory-model.yml b/.github/workflows/set-theory-model.yml new file mode 100644 index 000000000..e415b0c2a --- /dev/null +++ b/.github/workflows/set-theory-model.yml @@ -0,0 +1,47 @@ +name: Set-theory model + +on: + pull_request: + paths: + - 'Models/SetTheory/**' + - 'Ix/Theory/Model/SetTheory/Core.lean' + - 'lakefile.lean' + - 'lake-manifest.json' + - 'lean-toolchain' + - '.github/workflows/set-theory-model.yml' + merge_group: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + model: + runs-on: warp-ubuntu-latest-x64-16x + timeout-minutes: 60 + defaults: + run: + working-directory: Models/SetTheory + env: + MATHLIB_NO_CACHE_ON_UPDATE: '1' + MATHLIB_CACHE_DIR: .lake/mathlib-cache + steps: + - uses: actions/checkout@v7 + - uses: leanprover/lean-action@v1 + with: + auto-config: false + use-github-cache: false + - name: Check Lean toolchains match + run: cmp ../../lean-toolchain lean-toolchain + - uses: actions/cache@v6 + with: + path: Models/SetTheory/.lake + key: set-theory-model-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Models/SetTheory/lean-toolchain', 'Models/SetTheory/lakefile.toml', 'Models/SetTheory/lake-manifest.json') }} + - name: Fetch the imported Mathlib modules and dependencies + run: lake exe cache get Mathlib.SetTheory.Cardinal.Regular Mathlib.SetTheory.ZFC.VonNeumann Mathlib.SetTheory.ZFC.Cardinal + - name: Build model and check axiom guard + run: lake build --wfail diff --git a/BENCHMARKS.md b/BENCHMARKS.md index 6d1740331..5b1b683d0 100644 --- a/BENCHMARKS.md +++ b/BENCHMARKS.md @@ -2,7 +2,7 @@ Head-to-head timings for every stage of the Ix pipeline across three environments, comparing the pure-Lean implementation (`Ix.CompileM` / -`Ix.DecompileM` / `Ix.Tc`) against the Rust implementation +`Ix.DecompileM` / `Ix.Kernel`) against the Rust implementation (`crates/compile` / `crates/kernel`). ## Methodology @@ -119,7 +119,7 @@ Rust: `ix decompile` (the decompile pass over a `.ixe`). Lean: flags → Pass 2 aux regeneration/recovery) *plus* the hash comparison against the canonicalized source (comparison overhead ~5 s at 205k constants). Lean decompilation is dominated by Pass 2's kernel bridge -(regeneration re-infers through `Ix.Tc`); Pass 2 runs on the +(regeneration re-infers through `Ix.Kernel`); Pass 2 runs on the wave-parallel driver (`decompileEnvPass2Parallel`, 16 workers — the count is memory-bound, not core-bound; `IX_DECOMPILE_WORKERS` overrides). The sequential figures from before the parallel driver are @@ -147,7 +147,7 @@ full verdict parity. worker config keeps warm caches; both a 32-worker meta run and a 32-worker anon run without cache clearing were OOM-killed while swap-thrashing). The anon row uses the scale configuration from the -`Ix.Tc` Mathlib-tier validation: 16 workers, `--clear-every 50` +`Ix.Kernel` Mathlib-tier validation: 16 workers, `--clear-every 50` (whole-worker-state renewal every 50 items; RSS plateaus ~42 GB) — **640,658/640,658 passed, zero failures, full verdict parity**. Anon mode dedups alpha-identical constants, hence the smaller count. diff --git a/Benchmarks/Lean4Lean.lean b/Benchmarks/Lean4Lean.lean deleted file mode 100644 index f7437b91c..000000000 --- a/Benchmarks/Lean4Lean.lean +++ /dev/null @@ -1,541 +0,0 @@ -import Cli -import Lean4Lean.Environment -import Ix.Meta -import Ix.TracingTexray -import Ix.Benchmark.Results -import Ix.Cli.ConstsFile - -/-! -# lean4lean typecheck benchmark - -Benchmarks the reference Lean4-in-Lean4 kernel — -[lean4lean](https://github.com/digama0/lean4lean), required by the lakefile -at a pinned rev — over the same library envs the other kernel backends -measure (`Benchmarks/Compile/Compile.lean`). It is the external -yardstick for the Ix kernels: `ix check-rs` (Rust, the `ooc` backend) and -`ix check-lean` (pure-Lean `Ix.Tc`) check the serialized `.ixe` of an env; -this tool has lean4lean check the same library from its `.olean`s. - -``` -lake exe bench-lean4lean [flags] - - the env's Lean source, same input `ix compile` takes - (e.g. `Benchmarks/Compile/CompileInitStd.lean`). Its - lake project supplies the module search path; the - module set is the file's transitive import closure. - --consts per-constant mode: replay each named constant's whole - transitive closure into a fresh kernel environment — - one row per name, the lean4lean counterpart of the ooc - backend's full-closure rows. Same flag/shape as - `ix check-rs --consts`. - --consts-file additionally read names from a file (one per line, - `#` comments ignored). Unions with --consts. - --json write benchmark results rows to (the shared - row contract, `Ix.Benchmark.Results`). - --json-name row key for the whole-library row (default: the - file's stem). The orchestrator passes the env name. - --no-build skip the `lake build` of the env module (for callers - that know the oleans are fresh). - --verbose print each declaration as it is added. -``` - -Without `--consts` the tool measures the **whole library**: every module in -the import closure is replayed through lean4lean — each module's new -constants are re-checked against its imports, one `IO.asTask` per module — -upstream `lake exe lean4lean`'s default mode, i.e. the canonical "how does -lean4lean perform on this library" number. Two driver divergences from -upstream, both required to run at all on this toolchain (the kernel itself -is untouched): duplicated cross-module realizations are skipped instead of -spuriously rejected, and only import regions are freed per task — the -stock binary segfaults freeing a module's own parts (see -`replayFromImports` for both). The row -carries `check-time` (wall over the sweep), `constants` (Σ declarations -added), `throughput` (constants/s), `peak-rss`. Caveats for cross-kernel -reading: lean4lean trusts `.olean` loading for a module's *imports* (every -constant is still checked exactly once, in its home module's task), its -parallelism unit is the module (tune with `LEAN_NUM_THREADS`), the -constant count is Lean declarations rather than Ixon constants — compare -end-to-end library numbers, not per-constant arithmetic — and auto-generated -lemmas that v4.29 multi-part oleans materialize in several modules are -checked once and skipped as duplicates thereafter (see `replayFromImports`; -upstream re-declares and spuriously rejects them). - -A kernel rejection writes the row as `{"status": "rejected"}` (no metrics — -a rejection is a correctness signal, not a benchmark datum) and the run -exits with the reserved code 3; a missing `.olean` is an infrastructure -error (exit 1) detected before any timed window. Rows are flushed after -every result, so a killed run keeps the rows measured so far. - -The replay machinery (`Context`/`State`/`replayConstant`/`replay`, -`replayFromImports`) is adapted from lean4lean's own `Main.lean` -(Apache 2.0, © the lean4lean authors) at the pinned rev — kept in lockstep -with the require so both sides agree on `Lean4Lean.addDecl`'s surface. --/ - -open Lean hiding Environment Exception -open Kernel - -namespace BenchLean4Lean - -/-- Like `Expr.getUsedConstants`, but produce a `NameSet`. -/ -def getUsedConstants' (e : Expr) : NameSet := - e.foldConsts {} fun c cs => cs.insert c - -/-- Return all names appearing in the type or value of a `ConstantInfo`. - -`allowOpaque := true` is load-bearing since v4.33: `ConstantInfo.value?` -now hides theorem proofs (and opaque bodies) by default, and a replay walk -that misses proof references skips their auxiliaries — e.g. the -`._f` structural-recursion helpers (`Nat.add_comm._f`), so the kernel then -rejects the theorem with "unknown constant". Mirrors the fork's -`Lean4Lean.Replay` fix. -/ -def getUsedConstants (c : ConstantInfo) : NameSet := - getUsedConstants' c.type ++ match c.value? (allowOpaque := true) with - | some v => getUsedConstants' v - | none => match c with - | .inductInfo val => .ofList val.ctors - | .ctorInfo val => ({} : NameSet).insert val.name - | .recInfo val => .ofList val.all - | _ => {} - -structure Context where - newConstants : Std.HashMap Name ConstantInfo - verbose := false - checkQuot := true - -structure State where - env : Environment - remaining : NameSet := {} - pending : NameSet := {} - postponedConstructors : NameSet := {} - postponedRecursors : NameSet := {} - numAdded : Nat := 0 - hasStrings := false - -abbrev M := ReaderT Context <| StateRefT State IO - -/-- Check if a `Name` still needs processing. If so, move it from `remaining` to `pending`. -/ -def isTodo (name : Name) : M Bool := do - let r := (← get).remaining - if r.contains name then - modify fun s => { s with remaining := s.remaining.erase name, pending := s.pending.insert name } - return true - else - return false - -def mapEnvM [Monad m] (ex : Exception) (f : Environment → m Environment) : m Exception := do - match ex with - | .unknownConstant env c => return .unknownConstant (← f env) c - | .alreadyDeclared env c => return .alreadyDeclared (← f env) c - | .declTypeMismatch env d t => return .declTypeMismatch env d t - | .declHasMVars env c e => return .declHasMVars (← f env) c e - | .declHasFVars env c e => return .declHasFVars (← f env) c e - | .funExpected env lctx e => return .funExpected (← f env) lctx e - | .typeExpected env lctx e => return .typeExpected (← f env) lctx e - | .letTypeMismatch env lctx n t1 t2 => return .letTypeMismatch (← f env) lctx n t1 t2 - | .exprTypeMismatch env lctx e t => return .exprTypeMismatch (← f env) lctx e t - | .appTypeMismatch env lctx e fn arg => return .appTypeMismatch (← f env) lctx e fn arg - | .invalidProj env lctx e => return .invalidProj (← f env) lctx e - | .thmTypeIsNotProp env c t => return .thmTypeIsNotProp (← f env) c t - | .other _ - | .deterministicTimeout - | .excessiveMemory - | .deepRecursion - | .interrupted => return ex - -/-- Use the current `Environment` to throw a `Kernel.Exception`. -/ -def throwKernelException (ex : Exception) : M α := do - let options := pp.match.set (pp.rawOnError.set {} true) false - -- The replayed environment has no extension state, so it cannot back the - -- pretty printer; a fresh empty environment is good enough for basic - -- printing of the offending declaration. - let env ← mkEmptyEnvironment - let ex ← mapEnvM ex fun _ => return env.toKernelEnv - Prod.fst <$> (Lean.Core.CoreM.toIO · { fileName := "", options, fileMap := default } { env }) do - Lean.throwKernelException ex - -def declName : Declaration → String - | .axiomDecl d => s!"axiomDecl {d.name}" - | .defnDecl d => s!"defnDecl {d.name}" - | .thmDecl d => s!"thmDecl {d.name}" - | .opaqueDecl d => s!"opaqueDecl {d.name}" - | .quotDecl => s!"quotDecl" - | .mutualDefnDecl d => s!"mutualDefnDecl {d.map (·.name)}" - | .inductDecl _ _ d _ => s!"inductDecl {d.map (·.name)}" - -/-- Add a declaration through the lean4lean kernel, possibly throwing a - `KernelException`. -/ -def addDecl (d : Declaration) : M Unit := do - if (← read).verbose then - println! "adding {declName d}" - let t1 ← IO.monoMsNow - match Lean4Lean.addDecl (← get).env d true with - | .ok env => - let t2 ← IO.monoMsNow - if t2 - t1 > 1000 then - println! "{declName d}: lean4lean took {t2 - t1}ms" - modify fun s => { s with env, numAdded := s.numAdded + 1 } - | .error ex => - throwKernelException ex - -def hasStrLit (e : Expr) : Bool := (e.find? (·.isStringLit)).isSome - -def constHasStrLit (ci : ConstantInfo) : Bool := - -- `allowOpaque := true` for the same reason as `getUsedConstants`: a string - -- literal inside a theorem proof must still pre-seed `String.ofList`. - hasStrLit ci.type || (ci.value? (allowOpaque := true)).any hasStrLit - -mutual -/-- -Check if a `Name` still needs to be processed (i.e. is in `remaining`). - -If so, recursively replay any constants it refers to, -to ensure we add declarations in the right order. - -Then construct the `Declaration` from its stored `ConstantInfo`, -and add it to the environment. --/ -partial def replayConstant (name : Name) : M Unit := do - if ← isTodo name then - let some ci := (← read).newConstants[name]? | unreachable! - let mut usedConstants := getUsedConstants ci - -- We want `String.ofList` to be available when encountering string literals. - unless (← get).hasStrings do - if constHasStrLit ci then - usedConstants := usedConstants.insert ``String.ofList - usedConstants := usedConstants.insert ``Char.ofNat - modify ({· with hasStrings := true }) - replayConstants usedConstants - -- Check that this name is still pending: a mutual block may have taken care of it. - if (← get).pending.contains name then - let addDeclAt (d : Declaration) := - try addDecl d catch e => throw <| IO.userError s!"at {name}: {e.toString}" - match ci with - | .defnInfo info => addDeclAt (.defnDecl info) - | .thmInfo info => addDeclAt (.thmDecl info) - | .axiomInfo info => addDeclAt (.axiomDecl info) - | .opaqueInfo info => addDeclAt (.opaqueDecl info) - | .inductInfo info => - let lparams := info.levelParams - let nparams := info.numParams - let all ← info.all.mapM fun n => do pure <| (← read).newConstants[n]! - for o in all do - modify fun s => - { s with remaining := s.remaining.erase o.name, pending := s.pending.erase o.name } - let ctorInfo ← all.mapM fun ci => do - pure (ci, ← ci.inductiveVal!.ctors.mapM fun n => do - pure (← read).newConstants[n]!) - -- Make sure we are really finished with the constructors. - for (_, ctors) in ctorInfo do - for ctor in ctors do - replayConstants (getUsedConstants ctor) - let types : List InductiveType := ctorInfo.map fun ⟨ci, ctors⟩ => - { name := ci.name - type := ci.type - ctors := ctors.map fun ci => { name := ci.name, type := ci.type } } - addDeclAt (.inductDecl lparams nparams types false) - -- We postpone checking constructors, - -- and at the end make sure they are identical - -- to the constructors generated when we replay the inductives. - | .ctorInfo info => - modify fun s => { s with postponedConstructors := s.postponedConstructors.insert info.name } - -- Similarly we postpone checking recursors. - | .recInfo info => - modify fun s => { s with postponedRecursors := s.postponedRecursors.insert info.name } - | .quotInfo _ => addDeclAt .quotDecl - modify fun s => { s with pending := s.pending.erase name } - -/-- Replay a set of constants one at a time. -/ -partial def replayConstants (names : NameSet) : M Unit := do - for n in names do replayConstant n - -end - -end BenchLean4Lean - -deriving instance BEq for ConstantVal -deriving instance BEq for ConstructorVal -deriving instance BEq for RecursorRule -deriving instance BEq for RecursorVal - -namespace BenchLean4Lean - -/-- -Check that all postponed constructors are identical to those generated -when we replayed the inductives. --/ -def checkPostponedConstructors : M Unit := do - for ctor in (← get).postponedConstructors do - match (← get).env.constants.find? ctor, (← read).newConstants[ctor]? with - | some (.ctorInfo info), some (.ctorInfo info') => - unless info == info' do throw <| IO.userError s!"Invalid constructor {ctor}" - | _, _ => throw <| IO.userError s!"No such constructor {ctor}" - -/-- -Check that all postponed recursors are identical to those generated -when we replayed the inductives. --/ -def checkPostponedRecursors : M Unit := do - for ctor in (← get).postponedRecursors do - match (← get).env.constants.find? ctor, (← read).newConstants[ctor]? with - | some (.recInfo info), some (.recInfo info') => - unless info == info' do throw <| IO.userError s!"Invalid recursor {ctor}" - | _, _ => throw <| IO.userError s!"No such recursor {ctor}" - -/-- Check that at the end of (any) file, the quotient module is initialized. -(It will already be initialized at the beginning, unless this is the very -first file, which is responsible for initializing it.) -/ -def checkQuotInit : M Unit := do - unless (← get).env.quotInit do - throw <| IO.userError s!"initial import (Init.Prelude) didn't initialize quotient module" - -/-- "Replay" some constants into an `Environment`, sending them to the - lean4lean kernel for checking. Returns the number of declarations added - and the final environment. -/ -def replay (ctx : Context) (env : Environment) (decl : Option Name := none) : - IO (Nat × Environment) := do - let mut remaining : NameSet := ∅ - for (n, ci) in ctx.newConstants.toList do - -- We skip unsafe constants, and also partial constants. - if !ci.isUnsafe && !ci.isPartial then - remaining := remaining.insert n - let (_, s) ← StateRefT'.run (s := { env, remaining }) do - ReaderT.run (r := ctx) do - match decl with - | some d => replayConstant d - | none => - for n in remaining do - replayConstant n - checkPostponedConstructors - checkPostponedRecursors - if (← read).checkQuot then checkQuotInit - return (s.numAdded, s.env) - -/-- Read a module's olean parts (base + server + private when present), - most complete last — the shape `readModuleDataParts` and the - toolchain's own `LeanChecker` frontend use. Shared by the closure - scanner and the replay tasks so both see the same (private-level) - import set. Throws when the base olean is missing. -/ -def readModuleParts (module : Name) : IO (Array (ModuleData × CompactedRegion)) := do - let mFile ← findOLean module - unless (← mFile.pathExists) do - throw <| IO.userError s!"object file '{mFile}' of module {module} does not exist" - let mut fnames := #[mFile] - let sFile := OLeanLevel.server.adjustFileName mFile - if (← sFile.pathExists) then - fnames := fnames.push sFile - let pFile := OLeanLevel.private.adjustFileName mFile - if (← pFile.pathExists) then - fnames := fnames.push pFile - readModuleDataParts fnames - -open private ImportedModule.mk from Lean.Environment in -/-- Replay one module's new constants against its (trusted-loaded) imports — - upstream `lake exe lean4lean`'s per-module unit of work. -/ -unsafe def replayFromImports (module : Name) (verbose := false) : IO Nat := do - let parts ← readModuleParts module - let some (mod, _) := parts[parts.size - 1]? | unreachable! -- load private module data - let (_, s) ← (importModulesCore mod.imports).run - let env ← match Kernel.Environment.finalizeImport s mod.imports module 0 with - | .ok env => pure env - | .error e => throw <| .userError <| ← (e.toMessageData {}).toString - let mut newConstants := {} - for name in mod.constNames, ci in mod.constants do - -- v4.29 multi-part oleans can materialize the same auto-generated - -- lemma (`*.eq_1`, `*.congr_simp`, …) in several modules' parts; a - -- real import dedups those realizations in `finalizeImport`, so the - -- replay must skip names the imported env already provides instead of - -- re-declaring them (upstream replays them and spuriously rejects, - -- e.g. on v4.29 Std). - if (env.constants.find? name).isNone then - newConstants := newConstants.insert name ci - let (n, env') ← replay { newConstants, verbose } env - -- Free the task's IMPORT regions only (the memory that scales with the - -- sweep: every task maps its whole import closure). Upstream also frees - -- the module's own `parts` regions, which segfaults — reproducibly, in - -- the stock `lean4lean` binary too on this toolchain (decref of - -- persistent region objects after munmap at scope exit) — so the small - -- per-module parts stay mapped: one copy of the library across the - -- sweep, not one closure per task. - (Environment.ofKernelEnv env').freeRegions - pure n - -/-- Replay every module of the library through lean4lean, one `IO.asTask` - per module (parallelism follows the task pool, i.e. `LEAN_NUM_THREADS`). - Callers pre-flight olean existence via `moduleClosure`, so a task - failure here is a kernel rejection, not infrastructure. Returns the - total declarations added plus per-module failures. -/ -unsafe def replayLibrary (modules : Array Name) (verbose : Bool) : - IO (Nat × Array (Name × String)) := do - let mut tasks := #[] - for m in modules do - tasks := tasks.push (m, ← IO.asTask (replayFromImports m verbose)) - let mut added := 0 - let mut failures : Array (Name × String) := #[] - for (m, t) in tasks do - match t.get with - | .error e => failures := failures.push (m, toString e) - | .ok n => added := added + n - return (added, failures) - -/-- Transitive module closure of `roots`, discovered by scanning olean - headers (private-level parts, so `private import`s are covered). No - environment is imported here: the whole-library sweep's tasks free - their compacted regions when done — upstream's memory bound — which is - only sound while nothing else in the process shares mapped regions. - The scanner's own header regions stay mapped (the returned `Name`s - live inside them): one copy of the library's headers, not one per - task. A missing olean throws here, before any timed window. -/ -def moduleClosure (roots : Array Name) : IO (Array Name) := do - let mut seen : NameSet := {} - let mut order : Array Name := #[] - let mut stack : List Name := roots.toList - repeat - match stack with - | [] => break - | m :: rest => - stack := rest - if seen.contains m then - continue - seen := seen.insert m - order := order.push m - let parts ← readModuleParts m - let some (mod, _) := parts[parts.size - 1]? | unreachable! - for imp in mod.imports do - unless seen.contains imp.module do - stack := imp.module :: stack - return order - -/-- Replay `target`'s whole transitive closure into a fresh kernel - environment — the full-closure check semantics of the ooc backend's - per-constant rows. Returns the closure size (declarations added). -/ -def replayClosure (env : Lean.Environment) (newConstants : Std.HashMap Name ConstantInfo) - (target : Name) (verbose : Bool) : IO Nat := do - let _ := env - (·.1) <$> replay { newConstants, verbose, checkQuot := false } (.empty default) (some target) - -/-- Resolve a raw `--consts` string against the env: `toName` first, then a - displayed-form scan (numeric/private components don't round-trip through - `toName`) — the same fallback the other tools' resolvers use. -/ -def resolveName (env : Lean.Environment) (raw : String) : Option Name := - let n := raw.toName - if env.constants.contains n then some n - else env.constants.fold (init := none) fun acc cn _ => - acc <|> if toString cn == raw then some cn else none - -open Ix.Benchmark.Results in -unsafe def runBenchCmd (p : Cli.Parsed) : IO UInt32 := do - let some pathArg := p.positionalArg? "path" - | p.printError "error: must specify to the env's Lean source (e.g. Benchmarks/Compile/CompileInitStd.lean)" - return exitUsage - let path := pathArg.as! String - let jsonOut : Option String := (p.flag? "json").map (·.as! String) - let jsonName := ((p.flag? "json-name").map (·.as! String)).getD - ((System.FilePath.mk path).fileStem.getD path) - let verbose := p.hasFlag "verbose" - let rawNames ← Ix.Cli.ConstsFile.gather p - - -- Build the env module first (outside every timed window). The file's - -- lake project supplies the module search path — the same entry - -- `ix compile` uses, so both backends accept the same registry - -- `module` path. - unless p.hasFlag "no-build" do buildFile path - - if rawNames.isEmpty then - -- Whole-library mode. The import closure is enumerated by scanning - -- olean headers — deliberately WITHOUT importing an environment into - -- this process: the replay tasks free their compacted regions when - -- done (upstream's memory bound, ~steady-state instead of the whole - -- library's fixed-up regions accumulating), and those frees are only - -- sound while no co-resident env shares mapped regions. - initLeanSearchPath (← IO.FS.realPath path).parent - let header ← Lean.parseImports' (← IO.FS.readFile path) path - let modules ← moduleClosure (header.imports.map (·.module)) - IO.println s!"Loaded {path}: {modules.size} modules in the import closure" - TracingTexray.startSampler - -- Whole-library row: module-parallel replay of the import closure. - IO.println s!"replaying {modules.size} modules through lean4lean …" - (← IO.getStdout).flush - TracingTexray.resetPeakTreeRss - let t0 ← IO.monoNanosNow - let (added, failures) ← replayLibrary modules verbose - let t1 ← IO.monoNanosNow - let secs := (t1 - t0).toFloat / 1e9 - let peak ← TracingTexray.peakTreeRssBytes - if failures.isEmpty then - if let some out := jsonOut then - writeRow out jsonName "ok" - [ ("check-time", jsonRound 6 secs) - , ("constants", Lean.toJson added) - , ("throughput", jsonRound 2 (if secs > 0 then added.toFloat / secs else 0)) - , ("peak-rss", Lean.toJson peak) ] - IO.println s!"{jsonName}: checked {added} declarations in {secs}s \ - ({(added.toFloat / secs).toUInt64} consts/s)" - return 0 - else - for (m, e) in failures do - IO.eprintln s!"❌ lean4lean REJECTED module {m}: {e}" - if let some out := jsonOut then - writeRow out jsonName "rejected" [] - return exitRejected - else - -- Per-constant mode: the elaborated file env supplies the constants - -- map (`getFileEnv`, the same entry `ix compile` uses — it also sets - -- the search path). Closure replays never free regions, so the - -- co-resident env is fine here. Each row is the name's whole - -- transitive closure into a fresh kernel env. - let env ← getFileEnv path - TracingTexray.startSampler - let newConstants := env.constants.fold - (init := ({} : Std.HashMap Name ConstantInfo)) fun m n ci => m.insert n ci - let mut anyRejected := false - let mut idx := 0 - for raw in rawNames do - idx := idx + 1 - match resolveName env raw with - | none => IO.eprintln s!"warning: {raw} not found in the env; skipping" - | some target => - -- Announce BEFORE the replay (flushed): a kill mid-replay must - -- leave the in-flight constant's name in the log. - IO.println s!" [{idx}/{rawNames.size}] replaying closure of {raw} …" - (← IO.getStdout).flush - TracingTexray.resetPeakTreeRss - let t0 ← IO.monoNanosNow - let res ← (replayClosure env newConstants target verbose).toBaseIO - let t1 ← IO.monoNanosNow - let secs := (t1 - t0).toFloat / 1e9 - let peak ← TracingTexray.peakTreeRssBytes - match res with - | .ok added => - if let some out := jsonOut then - writeRow out raw "ok" - [ ("check-time", jsonRound 6 secs) - , ("constants", Lean.toJson added) - , ("throughput", jsonRound 2 (if secs > 0 then added.toFloat / secs else 0)) - , ("peak-rss", Lean.toJson peak) ] - IO.println s!" {raw}: constants={added} check={secs}s" - | .error e => - IO.eprintln s!" ❌ {raw} FAILED TO TYPECHECK: {e}" - if let some out := jsonOut then - writeRow out raw "rejected" [] - anyRejected := true - return if anyRejected then exitRejected else 0 - -end BenchLean4Lean - -unsafe def benchLean4LeanCmd : Cli.Cmd := `[Cli| - "bench-lean4lean" VIA BenchLean4Lean.runBenchCmd; - "Benchmark the lean4lean reference kernel over a library env (whole-library module replay, or per-constant closures with --consts)" - - FLAGS: - consts : String; "Per-constant mode: comma-separated fully-qualified names, each replayed as its whole transitive closure into a fresh kernel env (the ooc backend's full-closure row shape). Same flag/shape as `ix check-rs --consts`." - "consts-file" : String; "Additionally read constant names from a file (one per line; `#` comments and blank lines ignored). Unions with --consts." - json : String; "Write benchmark results rows to this path (shared row contract). Off by default." - "json-name" : String; "Row key for the whole-library row (default: the file stem; the orchestrator passes the registry env name)." - "no-build"; "Skip the `lake build` of the env module (callers that know the oleans are fresh)." - verbose; "Print each declaration as it is added." - - ARGS: - path : String; "Path to the env's Lean source, e.g. Benchmarks/Compile/CompileInitStd.lean (same input as `ix compile`)" -] - diff --git a/Benchmarks/Lean4LeanMain.lean b/Benchmarks/Lean4LeanMain.lean deleted file mode 100644 index dbfb3d5b0..000000000 --- a/Benchmarks/Lean4LeanMain.lean +++ /dev/null @@ -1,11 +0,0 @@ -import Benchmarks.Lean4Lean - -/-! -Exe root for `bench-lean4lean`. `main` lives here, in a module nothing -imports, so the machinery in `Benchmarks.Lean4Lean` stays importable -(the `lean4lean` ignored test runner uses it) without a root-level `main` -collision. --/ - -unsafe def main (args : List String) : IO UInt32 := - benchLean4LeanCmd.validate args diff --git a/Ix.lean b/Ix.lean index 9ad43890d..8f0c35502 100644 --- a/Ix.lean +++ b/Ix.lean @@ -17,7 +17,7 @@ public import Ix.Catalog public import Ix.ImportIxe public import Ix.IxEval public import Ix.KernelCheck -public import Ix.Tc +public import Ix.Kernel public import Ix.Claim public import Ix.Merkle public import Ix.AssumptionTree diff --git a/Ix/Address.lean b/Ix/Address.lean index a3a75bf25..a3196baaa 100644 --- a/Ix/Address.lean +++ b/Ix/Address.lean @@ -45,7 +45,12 @@ instance : Hashable Address where ||| ((h.get! 7).toUInt64 <<< 56) /-- Compute the Blake3 hash of a `ByteArray`, returning an `Address`. -/ -def Address.blake3 (x: ByteArray) : Address := ⟨(Blake3.Rust.hash x).val⟩ +def Address.blake3 (x: ByteArray) : Address := + let hasher := Blake3.Rust.hasherUpdate (Blake3.Rust.hasherInit ()) x + -- Supply a kernel-checked size bound: the upstream `hash` helper fills + -- this argument using native evaluation, adding an unnecessary axiom. + ⟨(Blake3.HasherOps.finalizeWithLength hasher 32 (by + rcases System.Platform.numBits_eq with bits | bits <;> rw [bits] <;> decide)).val⟩ /-- Convert a nibble (0--15) to its lowercase hexadecimal character. -/ def hexOfNat : Nat -> Option Char diff --git a/Ix/AuxGen/ExprUtils.lean b/Ix/AuxGen/ExprUtils.lean index 9f2a14ffa..fc6618a79 100644 --- a/Ix/AuxGen/ExprUtils.lean +++ b/Ix/AuxGen/ExprUtils.lean @@ -13,7 +13,7 @@ The kernel-backed half of expr_utils.rs (TcScope, kenv ingress, `decompose_inductive_type`, `kexpr_to_lean`, `to_kexpr_static`, the WHNF source-name restore machinery) is intentionally NOT here — it is a - separate milestone that bridges to `Ix.Tc`. + separate milestone that bridges to `Ix.Kernel`. PARITY RULE: every constructed node goes through the hash-maintaining smart constructors in `Ix.Environment` (`Expr.mkApp`, `Level.mkMax`, ...) diff --git a/Ix/AuxGen/Kernel.lean b/Ix/AuxGen/Kernel.lean index 5de7681e6..10604ae7b 100644 --- a/Ix/AuxGen/Kernel.lean +++ b/Ix/AuxGen/Kernel.lean @@ -6,7 +6,7 @@ compile-side entry points of `crates/kernel/src/ingress.rs` (:2097-2270). aux_gen needs exactly four kernel operations — `whnf`, `infer` + `ensureSort`, `isDefEq`, `isLargeEliminator` — over Meta-mode `KExpr`; - the pure-Lean kernel `Ix.Tc` exposes all four (Knot.lean), so this file + the pure-Lean kernel `Ix.Kernel` exposes all four (Knot.lean), so this file only supplies the VALUE bridge: - `Ix.Expr → KExpr .meta` (`toKexprStatic` for open terms in an FVar @@ -16,13 +16,13 @@ `ensureInKenvOf` family) under PROVISIONAL addresses (`resolveLeanNameAddr`: compiled address if known, else the name hash — mirrors KernelCtx's "addresses may shift" model); - - `TcScope`: a scoped view running `Ix.Tc.TcM` actions against the + - `TcScope`: a scoped view running `Ix.Kernel.TcM` actions against the bridge state, with the fault-in retry loop and WHNF source-name restoration. State model: Rust's `KernelCtx { kenv }` + `KEnv.ingress_cache` become `AuxKernelCtx { tcState, ingressCache }` — the cache lives HERE, not in - `Ix.Tc.KEnv` (`Ix/Tc` is consumed, never modified). Rust's fresh + `Ix.Kernel.KEnv` (`Ix/Kernel` is consumed, never modified). Rust's fresh `TypeChecker::new(&mut kenv)` per scope = fresh `TcState.new` carrying over the persistent `KEnv` (whose whnf/infer caches live inside it, matching the Rust split of TC-transient vs kenv-persistent state). @@ -32,7 +32,7 @@ public import Ix.Common public import Ix.Address public import Ix.Environment public import Ix.CompileM -public import Ix.Tc +public import Ix.Kernel public import Ix.AuxGen.Types public import Ix.AuxGen.ExprUtils public import Ix.AuxGen.Levels @@ -43,16 +43,16 @@ namespace Ix.AuxGen open Ix.CompileM (CompileM CompileError) -abbrev MKExpr := Ix.Tc.KExpr .meta -abbrev MKUniv := Ix.Tc.KUniv .meta -abbrev MKId := Ix.Tc.KId .meta -abbrev MKConst := Ix.Tc.KConst .meta +abbrev MKExpr := Ix.Kernel.KExpr .meta +abbrev MKUniv := Ix.Kernel.KUniv .meta +abbrev MKId := Ix.Kernel.KId .meta +abbrev MKConst := Ix.Kernel.KConst .meta -/-- Inverse of `Ix.Tc.EgressLean.safetyToLean`. -/ +/-- Inverse of `Ix.Kernel.EgressLean.safetyToLean`. -/ def safetyOfLean : Lean.DefinitionSafety → Ix.DefinitionSafety | .unsafe => .unsaf | .safe => .safe | .partial => .part -/-- Inverse of `Ix.Tc.EgressLean.quotKindToLean`. -/ +/-- Inverse of `Ix.Kernel.EgressLean.quotKindToLean`. -/ def quotKindOfLean : Lean.QuotKind → Ix.QuotKind | .type => .type | .ctor => .ctor | .lift => .lift | .ind => .ind @@ -98,17 +98,17 @@ def AddrMaps.ofCompileEnv (cenv : Ix.CompileM.CompileEnv) SMART `mkMax`/`mkIMax` (Rust `KUniv::max/imax` normalize). -/ partial def leanLevelToKuniv (lvl : Level) (paramNames : Array Name) : MKUniv := match lvl with - | .zero _ => Ix.Tc.KUniv.mkZero - | .succ l _ => Ix.Tc.KUniv.mkSucc (leanLevelToKuniv l paramNames) + | .zero _ => Ix.Kernel.KUniv.mkZero + | .succ l _ => Ix.Kernel.KUniv.mkSucc (leanLevelToKuniv l paramNames) | .max a b _ => - Ix.Tc.KUniv.mkMax (leanLevelToKuniv a paramNames) + Ix.Kernel.KUniv.mkMax (leanLevelToKuniv a paramNames) (leanLevelToKuniv b paramNames) | .imax a b _ => - Ix.Tc.KUniv.mkIMax (leanLevelToKuniv a paramNames) + Ix.Kernel.KUniv.mkIMax (leanLevelToKuniv a paramNames) (leanLevelToKuniv b paramNames) | .param name _ => match paramNames.findIdx? (· == name) with - | some idx => Ix.Tc.KUniv.mkParam idx.toUInt64 name + | some idx => Ix.Kernel.KUniv.mkParam idx.toUInt64 name | none => panic! s!"unknown level param `{name.pretty}` not found in param_names \ {paramNames.toList.map (·.pretty)}" @@ -135,7 +135,7 @@ partial def kunivToLevel (u : MKUniv) (paramNames : Array Name) : Level := /-- Rust `KernelCtx` + `KEnv.ingress_cache`. The cache key is `(expr contentHash, paramNamesHash)` — Rust ingress.rs:2216. -/ structure AuxKernelCtx where - tcState : Ix.Tc.TcState .meta + tcState : Ix.Kernel.TcState .meta ingressCache : Std.HashMap (Address × Address) MKExpr := {} /-- Mirrors Rust `KernelCtx.aux_ingress_seen`: ids whose `ingressAuxGenDep` dispatch already ran against this kenv. The @@ -152,16 +152,16 @@ structure AuxKernelCtx where simply never match the provisional-address constants — same shape as the Rust bridge, whose static prim addresses don't match either). -/ def AuxKernelCtx.new : AuxKernelCtx := - { tcState := Ix.Tc.TcState.new {} - (Ix.Tc.Primitives.ofResolve .canonical fun _ => none) } + { tcState := Ix.Kernel.TcState.new {} + (Ix.Kernel.Primitives.ofResolve .canonical fun _ => none) } /-- Bridge monad: aux kernel state over CompileM. -/ abbrev KBridgeM := StateT AuxKernelCtx CompileM -/-- Run an `Ix.Tc.TcM` action against the bridge's kernel state, +/-- Run an `Ix.Kernel.TcM` action against the bridge's kernel state, threading the state back in BOTH outcomes (Rust's `&mut` semantics — caches warmed by a failing call stay warm). -/ -def runTc (act : Ix.Tc.TcM .meta α) : KBridgeM (Except (Ix.Tc.TcError .meta) α) := do +def runTc (act : Ix.Kernel.TcM .meta α) : KBridgeM (Except (Ix.Kernel.TcError .meta) α) := do let kctx ← get match act kctx.tcState with | .ok a st' => @@ -214,7 +214,7 @@ partial def leanExprToKexprCached (e : Expr) (paramNames : Array Name) return hit -- Accumulate consecutive mdata wrappers. - let mut mdataLayers : Array Ix.Tc.MData := #[] + let mut mdataLayers : Array Ix.Kernel.MData := #[] let mut cur := e let mut go := true while go do @@ -230,50 +230,50 @@ partial def leanExprToKexprCached (e : Expr) (paramNames : Array Name) if idx < binderNames.size then return binderNames[binderNames.size - 1 - idx]! return Name.mkAnon - pure (Ix.Tc.KExpr.mkVar (UInt64.ofNat idx) name mdataLayers) + pure (Ix.Kernel.KExpr.mkVar (UInt64.ofNat idx) name mdataLayers) | .sort lvl _ => - pure (Ix.Tc.KExpr.mkSort (leanLevelToKuniv lvl paramNames) mdataLayers) + pure (Ix.Kernel.KExpr.mkSort (leanLevelToKuniv lvl paramNames) mdataLayers) | .const name us _ => let zid : MKId := ⟨maps.resolve name, name⟩ let zus := us.map (leanLevelToKuniv · paramNames) - pure (Ix.Tc.KExpr.mkConst zid zus mdataLayers) + pure (Ix.Kernel.KExpr.mkConst zid zus mdataLayers) | .app f a _ => let fk ← leanExprToKexprCached f paramNames binderNames pnHash maps let ak ← leanExprToKexprCached a paramNames binderNames pnHash maps - pure (Ix.Tc.KExpr.mkApp fk ak mdataLayers) + pure (Ix.Kernel.KExpr.mkApp fk ak mdataLayers) | .forallE binderName dom body bi _ => let dk ← leanExprToKexprCached dom paramNames binderNames pnHash maps let bk ← leanExprToKexprCached body paramNames (binderNames.push binderName) pnHash maps - pure (Ix.Tc.KExpr.mkAll binderName bi dk bk mdataLayers) + pure (Ix.Kernel.KExpr.mkAll binderName bi dk bk mdataLayers) | .lam binderName dom body bi _ => let dk ← leanExprToKexprCached dom paramNames binderNames pnHash maps let bk ← leanExprToKexprCached body paramNames (binderNames.push binderName) pnHash maps - pure (Ix.Tc.KExpr.mkLam binderName bi dk bk mdataLayers) + pure (Ix.Kernel.KExpr.mkLam binderName bi dk bk mdataLayers) | .letE binderName ty val body nd _ => let tk ← leanExprToKexprCached ty paramNames binderNames pnHash maps let vk ← leanExprToKexprCached val paramNames binderNames pnHash maps let bk ← leanExprToKexprCached body paramNames (binderNames.push binderName) pnHash maps - pure (Ix.Tc.KExpr.mkLet binderName tk vk bk nd mdataLayers) + pure (Ix.Kernel.KExpr.mkLet binderName tk vk bk nd mdataLayers) | .proj pname idx s _ => let zid : MKId := ⟨maps.resolve pname, pname⟩ let sk ← leanExprToKexprCached s paramNames binderNames pnHash maps - pure (Ix.Tc.KExpr.mkPrj zid (UInt64.ofNat idx) sk mdataLayers) + pure (Ix.Kernel.KExpr.mkPrj zid (UInt64.ofNat idx) sk mdataLayers) | .lit (.natVal n) _ => -- Compile-side blob convention: 8-byte u64 LE (Rust to_kexpr_static -- / ingress use `nat_to_u64(n).to_le_bytes()`), NOT the kernel's -- trimmed `natBlob`. - pure (Ix.Tc.KExpr.mkNat n (Address.blake3 (UInt64.ofNat n).toLEBytes) mdataLayers) + pure (Ix.Kernel.KExpr.mkNat n (Address.blake3 (UInt64.ofNat n).toLEBytes) mdataLayers) | .lit (.strVal s) _ => - pure (Ix.Tc.KExpr.mkStr s (Address.blake3 s.toUTF8) mdataLayers) + pure (Ix.Kernel.KExpr.mkStr s (Address.blake3 s.toUTF8) mdataLayers) | .fvar _ _ => -- Closed-term converter: fvars have no meaning here (Rust `_raw` -- has no Fvar arm reachable from ensure-in-kenv callers). - pure (Ix.Tc.KExpr.mkSort Ix.Tc.KUniv.mkZero) + pure (Ix.Kernel.KExpr.mkSort Ix.Kernel.KUniv.mkZero) | .mvar _ _ => - pure (Ix.Tc.KExpr.mkSort Ix.Tc.KUniv.mkZero) + pure (Ix.Kernel.KExpr.mkSort Ix.Kernel.KUniv.mkZero) | .mdata .. => unreachable! let result ← internK raw @@ -303,11 +303,11 @@ def ensurePreludeInKenvOf (maps : AddrMaps) : KBridgeM Unit := do let uName := Name.mkStr .mkAnon "u" -- PUnit.{u} : Sort u ; PUnit.unit : PUnit.{u} - let u0 : MKUniv := Ix.Tc.KUniv.mkParam 0 uName - let punitTy := Ix.Tc.KExpr.mkSort u0 + let u0 : MKUniv := Ix.Kernel.KUniv.mkParam 0 uName + let punitTy := Ix.Kernel.KExpr.mkSort u0 let unitName := Name.mkStr punitName "unit" let unitId : MKId := ⟨maps.resolve unitName, unitName⟩ - let unitTy := Ix.Tc.KExpr.mkConst punitId #[Ix.Tc.KUniv.mkParam 0 uName] + let unitTy := Ix.Kernel.KExpr.mkConst punitId #[Ix.Kernel.KUniv.mkParam 0 uName] kenvInsert unitId (.ctor unitName #[uName] false 1 punitId 0 0 0 unitTy) kenvInsert punitId (.indc punitName #[uName] 1 0 0 false punitId 0 punitTy #[unitId] #[]) @@ -320,28 +320,28 @@ def ensurePreludeInKenvOf (maps : AddrMaps) : KBridgeM Unit := do let betaName := Name.mkStr .mkAnon "β" let fstName := Name.mkStr .mkAnon "fst" let sndName := Name.mkStr .mkAnon "snd" - let u0' : MKUniv := Ix.Tc.KUniv.mkParam 0 uName - let u1 : MKUniv := Ix.Tc.KUniv.mkParam 1 vName - let sortU := Ix.Tc.KExpr.mkSort u0' - let sortV := Ix.Tc.KExpr.mkSort u1 + let u0' : MKUniv := Ix.Kernel.KUniv.mkParam 0 uName + let u1 : MKUniv := Ix.Kernel.KUniv.mkParam 1 vName + let sortU := Ix.Kernel.KExpr.mkSort u0' + let sortV := Ix.Kernel.KExpr.mkSort u1 -- Lean stores `max 1 u v` LEFT-associated: max(max(1,u),v). Essential: -- after substitution the normalizing max collapses differently for the -- right-associated form (expr_utils.rs:1813-1821). - let max1uv := Ix.Tc.KUniv.mkMax - (Ix.Tc.KUniv.mkMax (Ix.Tc.KUniv.mkSucc Ix.Tc.KUniv.mkZero) u0') u1 - let pprodTy := Ix.Tc.KExpr.mkAll alphaName Lean.BinderInfo.default sortU - (Ix.Tc.KExpr.mkAll betaName Lean.BinderInfo.default sortV (Ix.Tc.KExpr.mkSort max1uv)) + let max1uv := Ix.Kernel.KUniv.mkMax + (Ix.Kernel.KUniv.mkMax (Ix.Kernel.KUniv.mkSucc Ix.Kernel.KUniv.mkZero) u0') u1 + let pprodTy := Ix.Kernel.KExpr.mkAll alphaName Lean.BinderInfo.default sortU + (Ix.Kernel.KExpr.mkAll betaName Lean.BinderInfo.default sortV (Ix.Kernel.KExpr.mkSort max1uv)) -- PProd.mk : {α : Sort u} → {β : Sort v} → α → β → PProd.{u,v} α β let mkName := Name.mkStr pprodName "mk" let mkId : MKId := ⟨maps.resolve mkName, mkName⟩ - let pprodApp := Ix.Tc.KExpr.mkApp - (Ix.Tc.KExpr.mkApp (Ix.Tc.KExpr.mkConst pprodId #[u0', u1]) - (Ix.Tc.KExpr.mkVar 3 Name.mkAnon)) - (Ix.Tc.KExpr.mkVar 2 Name.mkAnon) - let mkTy := Ix.Tc.KExpr.mkAll alphaName Lean.BinderInfo.implicit sortU - (Ix.Tc.KExpr.mkAll betaName Lean.BinderInfo.implicit sortV - (Ix.Tc.KExpr.mkAll fstName Lean.BinderInfo.default (Ix.Tc.KExpr.mkVar 1 Name.mkAnon) - (Ix.Tc.KExpr.mkAll sndName Lean.BinderInfo.default (Ix.Tc.KExpr.mkVar 1 Name.mkAnon) + let pprodApp := Ix.Kernel.KExpr.mkApp + (Ix.Kernel.KExpr.mkApp (Ix.Kernel.KExpr.mkConst pprodId #[u0', u1]) + (Ix.Kernel.KExpr.mkVar 3 Name.mkAnon)) + (Ix.Kernel.KExpr.mkVar 2 Name.mkAnon) + let mkTy := Ix.Kernel.KExpr.mkAll alphaName Lean.BinderInfo.implicit sortU + (Ix.Kernel.KExpr.mkAll betaName Lean.BinderInfo.implicit sortV + (Ix.Kernel.KExpr.mkAll fstName Lean.BinderInfo.default (Ix.Kernel.KExpr.mkVar 1 Name.mkAnon) + (Ix.Kernel.KExpr.mkAll sndName Lean.BinderInfo.default (Ix.Kernel.KExpr.mkVar 1 Name.mkAnon) pprodApp))) kenvInsert mkId (.ctor mkName #[uName, vName] false 2 pprodId 0 2 2 mkTy) kenvInsert pprodId @@ -451,41 +451,41 @@ partial def toKexprStatic (e : Expr) (fvarLevels : Std.HashMap Name Nat) match e with | .fvar fname _ => match fvarLevels.get? fname with - | some level => Ix.Tc.KExpr.mkVar (UInt64.ofNat (ctxDepth - level - 1)) .mkAnon - | none => Ix.Tc.KExpr.mkSort Ix.Tc.KUniv.mkZero - | .bvar idx _ => Ix.Tc.KExpr.mkVar (UInt64.ofNat idx) .mkAnon - | .sort lvl _ => Ix.Tc.KExpr.mkSort (leanLevelToKuniv lvl paramNames) + | some level => Ix.Kernel.KExpr.mkVar (UInt64.ofNat (ctxDepth - level - 1)) .mkAnon + | none => Ix.Kernel.KExpr.mkSort Ix.Kernel.KUniv.mkZero + | .bvar idx _ => Ix.Kernel.KExpr.mkVar (UInt64.ofNat idx) .mkAnon + | .sort lvl _ => Ix.Kernel.KExpr.mkSort (leanLevelToKuniv lvl paramNames) | .const cname us _ => let zid : MKId := ⟨maps.resolve cname, cname⟩ - Ix.Tc.KExpr.mkConst zid (us.map (leanLevelToKuniv · paramNames)) + Ix.Kernel.KExpr.mkConst zid (us.map (leanLevelToKuniv · paramNames)) | .app f a _ => - Ix.Tc.KExpr.mkApp (toKexprStatic f fvarLevels ctxDepth paramNames maps) + Ix.Kernel.KExpr.mkApp (toKexprStatic f fvarLevels ctxDepth paramNames maps) (toKexprStatic a fvarLevels ctxDepth paramNames maps) | .forallE binderName dom body bi _ => - Ix.Tc.KExpr.mkAll binderName bi + Ix.Kernel.KExpr.mkAll binderName bi (toKexprStatic dom fvarLevels ctxDepth paramNames maps) (toKexprStatic body fvarLevels (ctxDepth + 1) paramNames maps) | .lam binderName dom body bi _ => - Ix.Tc.KExpr.mkLam binderName bi + Ix.Kernel.KExpr.mkLam binderName bi (toKexprStatic dom fvarLevels ctxDepth paramNames maps) (toKexprStatic body fvarLevels (ctxDepth + 1) paramNames maps) | .letE binderName ty val body nd _ => - Ix.Tc.KExpr.mkLet binderName + Ix.Kernel.KExpr.mkLet binderName (toKexprStatic ty fvarLevels ctxDepth paramNames maps) (toKexprStatic val fvarLevels ctxDepth paramNames maps) (toKexprStatic body fvarLevels (ctxDepth + 1) paramNames maps) nd | .proj pname idx s _ => let zid : MKId := ⟨maps.resolve pname, pname⟩ - Ix.Tc.KExpr.mkPrj zid (UInt64.ofNat idx) + Ix.Kernel.KExpr.mkPrj zid (UInt64.ofNat idx) (toKexprStatic s fvarLevels ctxDepth paramNames maps) | .lit (.natVal n) _ => -- 8-byte u64 LE blob convention (see leanExprToKexprCached). - Ix.Tc.KExpr.mkNat n (Address.blake3 (UInt64.ofNat n).toLEBytes) + Ix.Kernel.KExpr.mkNat n (Address.blake3 (UInt64.ofNat n).toLEBytes) | .lit (.strVal s) _ => - Ix.Tc.KExpr.mkStr s (Address.blake3 s.toUTF8) + Ix.Kernel.KExpr.mkStr s (Address.blake3 s.toUTF8) | .mdata _ inner _ => toKexprStatic inner fvarLevels ctxDepth paramNames maps - | .mvar _ _ => Ix.Tc.KExpr.mkSort Ix.Tc.KUniv.mkZero + | .mvar _ _ => Ix.Kernel.KExpr.mkSort Ix.Kernel.KUniv.mkZero /-- `KExpr .meta → Ix.Expr` reconstructing FVars from de-Bruijn `Var`s: indices below `localDepth` stay BVars; above, level = @@ -683,7 +683,7 @@ def new (outerFvarCtx : Array LocalDecl) (paramNames : Array Name) (maps : AddrMaps) : KBridgeM TcScopeSt := do -- Fresh TC portions, persistent env (caches live in KEnv). modify fun kctx => { kctx with tcState := - { Ix.Tc.TcState.new kctx.tcState.env kctx.tcState.prims with + { Ix.Kernel.TcState.new kctx.tcState.env kctx.tcState.prims with inferOnly := true } } let mut fvarLevels : Std.HashMap Name Nat := {} for (decl, i) in outerFvarCtx.zipIdx do @@ -692,7 +692,7 @@ def new (outerFvarCtx : Array LocalDecl) (paramNames : Array Name) { fvarLevels, baseDepth := outerFvarCtx.size, paramNames, maps } for (decl, i) in outerFvarCtx.zipIdx do let kty := toKexprStatic decl.domain fvarLevels i paramNames maps - discard <| runTc (Ix.Tc.TcM.pushLocal kty) + discard <| runTc (Ix.Kernel.TcM.pushLocal kty) return scope /-- Push additional locals (e.g. minor-premise binders); balance with @@ -706,7 +706,7 @@ def pushLocals (scope : TcScopeSt) (decls : Array LocalDecl) fvarLevels := scope.fvarLevels.insert decl.fvarName (depth0 + i) } let kty := toKexprStatic decl.domain scope.fvarLevels (depth0 + i) scope.paramNames scope.maps - discard <| runTc (Ix.Tc.TcM.pushLocal kty) + discard <| runTc (Ix.Kernel.TcM.pushLocal kty) return { scope with extraLocals := scope.extraLocals + decls.size } /-- Mirrors Rust `pop_locals` (expr_utils.rs:2274). -/ @@ -714,7 +714,7 @@ def popLocals (scope : TcScopeSt) (decls : Array LocalDecl) : KBridgeM TcScopeSt := do let mut scope := scope for decl in decls.reverse do - discard <| runTc Ix.Tc.TcM.popLocal + discard <| runTc Ix.Kernel.TcM.popLocal scope := { scope with fvarLevels := scope.fvarLevels.erase decl.fvarName } return { scope with extraLocals := scope.extraLocals - decls.size } @@ -829,7 +829,7 @@ partial def getLevel (scope : TcScopeSt) (ty : Expr) : KBridgeM Level := do let mut faultedAddrs : Std.HashSet Address := {} let mut inferred? : Option MKExpr := none while inferred?.isNone do - match ← runTc (Ix.Tc.TcM.infer kexpr) with + match ← runTc (Ix.Kernel.TcM.infer kexpr) with | .ok e => inferred? := some e | .error (.unknownConst addr) => if !faultedAddrs.contains addr then @@ -847,7 +847,7 @@ partial def getLevel (scope : TcScopeSt) (ty : Expr) : KBridgeM Level := do s!"TcScope::get_level: tc.infer failed: {e}") let inferred := inferred?.get! - let ku ← match ← runTc (Ix.Tc.TcM.ensureSort inferred) with + let ku ← match ← runTc (Ix.Kernel.TcM.ensureSort inferred) with | .ok u => pure u | .error e => throw (.unsupportedExpr s!"TcScope::get_level: ensure_sort failed: {e}") @@ -865,7 +865,7 @@ def whnfLean (scope : TcScopeSt) (ty : Expr) : KBridgeM Expr := do let depth := scope.depth let kexpr := toKexprStatic ty scope.fvarLevels depth scope.paramNames scope.maps - let whnfed ← match ← runTc (Ix.Tc.TcM.whnf kexpr) with + let whnfed ← match ← runTc (Ix.Kernel.TcM.whnf kexpr) with | .ok k => pure k | .error _ => return ty let out := kexprToLean whnfed depth scope.fvarLevels 0 scope.paramNames @@ -883,7 +883,7 @@ def isDefEq (scope : TcScopeSt) (a b : Expr) : KBridgeM Bool := do let depth := scope.depth let ka := toKexprStatic a scope.fvarLevels depth scope.paramNames scope.maps let kb := toKexprStatic b scope.fvarLevels depth scope.paramNames scope.maps - match ← runTc (Ix.Tc.TcM.isDefEq ka kb) with + match ← runTc (Ix.Kernel.TcM.isDefEq ka kb) with | .ok r => return r | .error _ => return false @@ -896,7 +896,7 @@ def isDefEq (scope : TcScopeSt) (a b : Expr) : KBridgeM Bool := do def inferLean (scope : TcScopeSt) (e : Expr) : KBridgeM (Option Expr) := do let depth := scope.depth let ke := toKexprStatic e scope.fvarLevels depth scope.paramNames scope.maps - match ← runTc (Ix.Tc.TcM.infer ke) with + match ← runTc (Ix.Kernel.TcM.infer ke) with | .ok ty => return some (kexprToLean ty depth scope.fvarLevels 0 scope.paramNames) | .error _ => return none diff --git a/Ix/AuxGen/Nested.lean b/Ix/AuxGen/Nested.lean index eeb21a566..b4542ecfb 100644 --- a/Ix/AuxGen/Nested.lean +++ b/Ix/AuxGen/Nested.lean @@ -18,7 +18,7 @@ `AuxLayout {perm, sourceCtorCounts}` metadata. The kernel re-derives this order via blake3 `AUX_INDC_VIEW` / - `AUX_MARKER_VIEW` seed addresses (`Ix/Tc/Inductive.lean:canonicalAuxOrder`, + `AUX_MARKER_VIEW` seed addresses (`Ix/Kernel/Inductive.lean:canonicalAuxOrder`, `crates/kernel/src/inductive.rs:canonical_aux_order`) — those seed strings are the CONSUMER's reconstruction and must not appear here: the compile side orders purely by marker ctor + `sortConsts`. diff --git a/Ix/AuxGen/Recursor.lean b/Ix/AuxGen/Recursor.lean index 72e62ed9f..edff092e3 100644 --- a/Ix/AuxGen/Recursor.lean +++ b/Ix/AuxGen/Recursor.lean @@ -1606,12 +1606,12 @@ def computeIsLargeAndK (classes : Array FlatInfo) (nClasses nParams : Nat) -- Fresh TypeChecker over the persistent kenv (Rust -- `TypeChecker::new(&mut kctx.kenv)`). modify fun kctx => { kctx with - tcState := Ix.Tc.TcState.new kctx.tcState.env kctx.tcState.prims } + tcState := Ix.Kernel.TcState.new kctx.tcState.env kctx.tcState.prims } -- WHNF-reduced result sort level via the kernel. let resultKuniv ← - match ← runTc (Ix.Tc.TcM.runRec - (Ix.Tc.RecM.getResultSortLevel firstTyZ + match ← runTc (Ix.Kernel.TcM.runRec + (Ix.Kernel.RecM.getResultSortLevel firstTyZ (nParams + firstNIndices.toNat))) with | .ok u => pure u | .error e => @@ -1620,8 +1620,8 @@ def computeIsLargeAndK (classes : Array FlatInfo) (nClasses nParams : Nat) {classes[0]!.ind.cnst.name.pretty}: {e}") let isLarge ← - match ← runTc (Ix.Tc.TcM.runRec - (Ix.Tc.RecM.isLargeEliminator resultKuniv indInfos)) with + match ← runTc (Ix.Kernel.TcM.runRec + (Ix.Kernel.RecM.isLargeEliminator resultKuniv indInfos)) with | .ok b => pure b | .error e => throw (.invalidMutualBlock diff --git a/Ix/BenchConstants.lean b/Ix/BenchConstants.lean index cee6bc26a..434f499ad 100644 --- a/Ix/BenchConstants.lean +++ b/Ix/BenchConstants.lean @@ -1,7 +1,7 @@ /- The shared benchmark constant set: the single source of truth for which - constants every per-constant benchmark backend (aiur, zisk, sp1, ooc, - lean4lean) runs. Every backend runs this same set — spanning the cheap → + constants every per-constant benchmark backend (aiur, zisk, sp1, ooc) + runs. Every backend runs this same set — spanning the cheap → heavy cost range across the registry envs — so their numbers stay comparable per constant; the only per-backend carve-outs are the hard feasibility exclusions in `Ix.Cli.BenchCmd.benchExclusions`. diff --git a/Ix/Certified.lean b/Ix/Certified.lean new file mode 100644 index 000000000..05cb4f0ef --- /dev/null +++ b/Ix/Certified.lean @@ -0,0 +1,13 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Command +import Ix.Certified.ClaimCommand + +/-! Source and claim adapters for the explicit certified profile. +Their validation receipts connect authenticated Ixon inputs to the set model. +The production checker's general inference path and Aiur public acceptance +have separate refinement obligations. +-/ diff --git a/Ix/Certified/Audit.lean b/Ix/Certified/Audit.lean new file mode 100644 index 000000000..c5e47e3c9 --- /dev/null +++ b/Ix/Certified/Audit.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.AuditSupport +import Ix.Certified.Bytes + +/-! +The serialized host adapter has its own audit. This is not the pure model's +import boundary or an Aiur compiler/AIR soundness theorem. Foreign hashing and +its output contract remain explicit runtime dependencies. +-/ + +open Lean Lean.Elab Command + +namespace Ix.Certified.Audit + +def roots : Array Lean.Name := #[ + `Ix.Certified.decodeObject?, `Ix.Certified.decodeNatural?, + `Ix.Certified.readSignature?, `Ix.Certified.prepare?, + `Ix.Certified.acceptsSerialized_prepared, + `Ix.Certified.accepted_serialized_has_model, + `Ix.Certified.no_serialized_proof_of_False] + +run_cmd AuditSupport.report "serialized" roots #[] + +end Ix.Certified.Audit diff --git a/Ix/Certified/AuditAll.lean b/Ix/Certified/AuditAll.lean new file mode 100644 index 000000000..a6f8b020c --- /dev/null +++ b/Ix/Certified/AuditAll.lean @@ -0,0 +1,25 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Audit +import Ix.Certified.TcAudit +import Ix.Certified.SourceAudit +import Ix.Certified.ClaimAudit +import Ix.Certified.ModeledAudit + +/-! The union of the five historical adapter boundaries, without duplicate +root, premise or worker reports. Each component remains independently audited. -/ + +namespace Ix.Certified.AuditAll + +def roots : Array Lean.Name := AuditSupport.distinct + (Audit.roots ++ TcAudit.roots ++ SourceAudit.roots ++ ClaimAudit.roots ++ ModeledAudit.roots) + +def premises : Array Lean.Name := AuditSupport.distinct + (TcAudit.premises ++ SourceAudit.premises ++ ClaimAudit.premises ++ ModeledAudit.premises) + +run_cmd AuditSupport.report "Certified host adapters" roots premises + +end Ix.Certified.AuditAll diff --git a/Ix/Certified/AuditSupport.lean b/Ix/Certified/AuditSupport.lean new file mode 100644 index 000000000..f27c6ff67 --- /dev/null +++ b/Ix/Certified/AuditSupport.lean @@ -0,0 +1,162 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean + +/-! Checked declaration traversal for the certified host adapters. Runtime +workers and foreign interfaces are inventoried separately from proof axioms. -/ + +open Lean Lean.Elab Command + +namespace Ix.Certified.AuditSupport + +private def constants (info : ConstantInfo) : Array Name := + info.type.getUsedConstants ++ match info with + | .thmInfo value => value.value.getUsedConstants + | .defnInfo value => value.value.getUsedConstants + | .opaqueInfo value => value.value.getUsedConstants + | .inductInfo value => value.ctors.toArray + | _ => #[] + +private partial def closure (env : Environment) (runtime : Bool) (pending : List Name) + (seen : NameSet := {}) : NameSet := + match pending with + | [] => seen + | name :: rest => + if seen.contains name then closure env runtime rest seen + else match env.checked.get.find? name with + | none => closure env runtime rest (seen.insert name) + | some info => + let extras := if runtime then Id.run do + let mut names := #[] + let worker := Lean.Compiler.mkUnsafeRecName name + if (env.checked.get.find? worker).isSome then names := names.push worker + if let some other := Lean.Compiler.getImplementedBy? env name then + names := names.push other + if let some other := (Lean.Compiler.CSimp.ext.getState env).map.find? name then + names := names.push other.toDeclName + return names + else #[] + closure env runtime ((constants info ++ extras).toList ++ rest) (seen.insert name) + +private def projectConstant (env : Environment) (name : Name) : Bool := + match env.getModuleIdxFor? name with + | none => false + | some idx => + let moduleName := env.allImportedModuleNames[idx.toNat]! + (`Ix).isPrefixOf moduleName || (`Blake3).isPrefixOf moduleName + +/-- Include constructor types and full checked bodies instead of relying on +imported axiom summaries. Both added and removed assumptions require review. -/ +def checkAxioms (env : Environment) (root : Name) (expected : Array Name) : + CommandElabM (Array Name) := do + let mut actual := #[] + for name in closure env false [root] do + let some info := env.checked.get.find? name + | throwError "certified adapter has an unavailable checked dependency: {name}" + if info.isAxiom then actual := actual.push name + let sorted := actual.qsort Name.lt + unless sorted == expected.qsort Name.lt do + throwError "certified axiom boundary changed for {root}: expected {expected.qsort Name.lt}, actual {sorted}" + return sorted + +private def expectedAxioms (root : Name) : Array Name := + if #[`Ix.Certified.readLevel_value, `Ix.Certified.treeLeaves_join].contains root then + #[``propext] + else if #[`Ix.Certified.readSignature?, `Ix.Certified.constantBytes?, + `Ix.Certified.resolveReference_iff, `Ix.Certified.readExpr_sound, + `Ix.Certified.ExprReading.unique, `Ix.Certified.readExpr_fuel_independent, + `Ix.Certified.readBlock_sourceHeader, `Ix.Certified.readStore_sourceHeader, + `Ix.Certified.readSignature_sound, `Ix.Theory.Certificate.Modeled.witness?, + `Ix.Theory.Certificate.sourceGroup?, `Ix.Theory.Certificate.proofWitness?, + `Ix.Certified.modelCandidate?, `Ix.Certified.modelCandidates?].contains root then + #[``propext, ``Quot.sound] + else #[``propext, ``Classical.choice, ``Quot.sound] + +def distinct (names : Array Name) : Array Name := + names.foldl (fun result name => if result.contains name then result else result.push name) #[] + +/-- Freeze theorem types, premise definitions, and transitive execution +dependencies. This does not establish correctness of native execution. -/ +def report (label : String) (roots premises : Array Name) : CommandElabM Unit := do + let env ← getEnv + for root in roots do + let some info := env.checked.get.find? root + | throwError "certified audit: missing root {root}" + let axioms ← checkAxioms env root (expectedAxioms root) + liftTermElabM do logInfo m!"ROOT {root}\n{← Meta.ppExpr info.type}\nAXIOMS {axioms}" + for name in premises do + let some info := env.checked.get.find? name + | throwError "certified audit: missing premise {name}" + liftTermElabM do + logInfo m!"PREMISE {name}\n{← Meta.ppExpr info.type}" + if let .defnInfo value := info then logInfo m!"DEFINITION\n{← Meta.ppExpr value.value}" + let logical := closure env false roots.toList + let reachable := (closure env true roots.toList).toList.mergeSort (fun a b => a.toString < b.toString) + let mut workers : Array Name := #[] + let mut externs : Array Name := #[] + let mut replacements : Array (Name × Name) := #[] + for name in reachable do + let some info := env.checked.get.find? name + | throwError "certified adapter has an unavailable checked runtime dependency: {name}" + if projectConstant env name then + if let some parent := Lean.Compiler.isUnsafeRecName? name then + match env.checked.get.find? parent with + | some (.defnInfo original) => + unless original.safety == .safe do + throwError "certified recursion worker source is not safe: {name}" + | _ => throwError "certified recursion worker has no safe source definition: {name}" + workers := workers.push name + if Lean.isExtern env name then externs := externs.push name + if let some other := Lean.Compiler.getImplementedBy? env name then + replacements := replacements.push (name, other) + if let some other := (Lean.Compiler.CSimp.ext.getState env).map.find? name then + replacements := replacements.push (name, other.toDeclName) + if let .defnInfo definition := info then + unless definition.safety == .safe || (Lean.Compiler.isUnsafeRecName? name).isSome do + throwError "certified adapter has an unreviewed unsafe runtime: {name}" + if let .opaqueInfo definition := info then + if definition.isUnsafe then throwError "certified adapter has an unsafe opaque runtime: {name}" + if Lean.Elab.ComputedFields.computedFieldAttr.hasTag env name then + throwError "certified adapter has an unreviewed computed field: {name}" + unless externs == #[`Blake3.Rust.hasherFinalize, `Blake3.Rust.hasherInit, + `Blake3.Rust.hasherInitDeriveKey, `Blake3.Rust.hasherInitKeyed, + `Blake3.Rust.hasherUpdate] do + throwError "certified runtime extern inventory changed: {externs}" + unless replacements.isEmpty do + throwError "certified runtime replacements changed: {replacements}" + for name in externs do + let some info := env.checked.get.find? name + | throwError "certified runtime extern is missing: {name}" + liftTermElabM do logInfo m!"RUNTIME EXTERN {name}\n{← Meta.ppExpr info.type}" + for name in workers.qsort Name.lt do + let some (.defnInfo value) := env.checked.get.find? name + | throwError "certified recursion worker is missing: {name}" + liftTermElabM do + logInfo m!"RECURSION WORKER {name}\n{← Meta.ppExpr value.type}\nIMPLEMENTATION\n{← Meta.ppExpr value.value}" + logInfo m!"{label} ROOTS {roots.size}; LOGICAL DECLARATIONS {logical.size}; WITH RUNTIME {reachable.length}" + logInfo m!"RUNTIME EXTERNS {externs}\nRECURSION WORKERS {workers.size}" + logInfo "All inventoried recursion workers have safe logical sources; no partial opaque source or executable replacement is permitted. Runtime diagnostics cover Ix and Blake3 modules, including private constants. Lean/Std execution and the BLAKE3 foreign interface remain external runtime boundaries." + logInfo "These host-adapter roots establish semantic claims under the enforced profile and explicit model premises. They do not establish full production-checker refinement or Aiur compiler/AIR soundness." + +private inductive ConstructorAuditFixture where + | plain + | withProof (proof : propext (Iff.refl True) = rfl) + +run_cmd do + let _ ← checkAxioms (← getEnv) ``ConstructorAuditFixture.plain #[``propext] + let _ ← checkAxioms (← getEnv) ``Eq.refl #[] + +/-- error: certified axiom boundary changed for Eq.refl: expected [propext], actual [] -/ +#guard_msgs in +run_cmd do + let _ ← checkAxioms (← getEnv) ``Eq.refl #[``propext] + +/-- error: certified axiom boundary changed for propext: expected [], actual [propext] -/ +#guard_msgs in +run_cmd do + let _ ← checkAxioms (← getEnv) ``propext #[] + +end Ix.Certified.AuditSupport diff --git a/Ix/Certified/Bytes.lean b/Ix/Certified/Bytes.lean new file mode 100644 index 000000000..0aeda099c --- /dev/null +++ b/Ix/Certified/Bytes.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Ixon + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified +open Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v + +/-- These external constant addresses are part of the selected public profile, +not fields supplied by an annotation or typing witness. -/ +structure Profile where + falseType : Address + falseElim : Address + natType : Option Address := none + deriving DecidableEq + +abbrev ConstantBlobs := List (Address × ByteArray) + +abbrev DecodedObject (address : Address) (bytes : ByteArray) := + { value : Ixon.Constant // + address.hash.size = 32 ∧ Address.blake3 bytes = address ∧ + Ixon.runGetExact Ixon.getConstant bytes = .ok value ∧ Ixon.serConstant value = bytes } + +/-- Check canonical re-encoding after a single parse. Keeping the parser's +result as a separate argument makes the cache reflection equation explicit. -/ +def canonicalObject? (address : Address) (bytes : ByteArray) + (auth : address.hash.size = 32 ∧ Address.blake3 bytes = address) + (result : Except String Ixon.Constant) + (parsed : Ixon.runGetExact Ixon.getConstant bytes = result) : Option (DecodedObject address bytes) := + match result, parsed with + | .error _, _ => none + | .ok source, hp => + if hc : Ixon.serConstant source = bytes then some ⟨source, auth.1, auth.2, hp, hc⟩ else none + +/-- The accepted byte domain consists of complete canonical Ixon constants. +The returned proof records authentication, exact consumption, and re-encoding +of the same bytes. It grants no typing or semantic acceptance by itself. -/ +def decodeObject? (address : Address) (bytes : ByteArray) : Option (DecodedObject address bytes) := + if h : address.hash.size = 32 ∧ Address.blake3 bytes = address then + canonicalObject? address bytes h (Ixon.runGetExact Ixon.getConstant bytes) rfl + else none + +def decodeObjects? (blobs : ConstantBlobs) : Option Objects := + blobs.mapM fun (address, bytes) => do + let source ← decodeObject? address bytes + return (address, source.val) + +/-- Natural blobs use Ix's unsigned little-endian encoding, with authentication +and canonical re-encoding checked before any literal is read. -/ +def decodeNatural? (address : Address) (bytes : ByteArray) : + Option { value : Nat // + address.hash.size = 32 ∧ Address.blake3 bytes = address ∧ + Nat.fromBytesLE bytes.data = value ∧ ByteArray.mk value.toBytesLE = bytes } := + if h : address.hash.size = 32 ∧ Address.blake3 bytes = address then + let value := Nat.fromBytesLE bytes.data + if hc : ByteArray.mk value.toBytesLE = bytes then some ⟨value, h.1, h.2, rfl, hc⟩ else none + else none + +def decodeNaturals? (blobs : ConstantBlobs) : Option Naturals := + blobs.mapM fun (address, bytes) => do + let value ← decodeNatural? address bytes + return (address, value.val) + +def readSignature? (profile : Profile) (objects : Objects) : + Option (PrimitiveSignature Address) := do + let falseType ← resolveReference? objects profile.falseType + let falseElim ← resolveReference? objects profile.falseElim + let natType ← match profile.natType with + | none => some none + | some address => (resolveReference? objects address).map some + if h : falseType ≠ falseElim then + return ⟨falseType, falseElim, h, natType⟩ + else none + +structure PreparedInput where + signature : PrimitiveSignature Address + input : ProofInput Address + +def prepare? (fuel : Nat) (profile : Profile) (target : Address) (blobs : ConstantBlobs) + (literalBlobs : ConstantBlobs := []) : Option PreparedInput := do + if !((blobs ++ literalBlobs).map Prod.fst).Nodup then none else do + let naturals ← decodeNaturals? literalBlobs + let objects ← decodeObjects? blobs + let signature ← readSignature? profile objects + let input ← readProofInput? fuel objects target naturals + return ⟨signature, input⟩ + +/-- The actual serialized-input gate invokes the mathematical validator after +authentication and decoding. The byte/statement preservation and compiled +execution theorems remain separate obligations. -/ +def acceptsSerialized (fuel : Nat) (profile : Profile) (target : Address) + (blobs : ConstantBlobs) (witness : ProofWitness Address) + (literalBlobs : ConstantBlobs := []) : Bool := + match prepare? fuel profile target blobs literalBlobs with + | none => false + | some prepared => + acceptsCertified.{0,v} fuel prepared.signature prepared.input witness + +theorem acceptsSerialized_prepared {fuel : Nat} {profile : Profile} {target : Address} + {blobs literalBlobs : ConstantBlobs} {witness : ProofWitness Address} + (h : acceptsSerialized.{v} fuel profile target blobs witness literalBlobs = true) : + ∃ prepared, prepare? fuel profile target blobs literalBlobs = some prepared ∧ + acceptsCertified.{0,v} fuel prepared.signature prepared.input witness = true := by + unfold acceptsSerialized at h + cases hp : prepare? fuel profile target blobs literalBlobs with + | none => simp [hp] at h + | some prepared => exact ⟨prepared, rfl, by simpa only [hp] using h⟩ + +/-- A successful serialized host check constructs the model of its decoded +input. Source meaning, claim binding, and authenticated backend execution +require their respective refinement theorems. -/ +theorem accepted_serialized_has_model {fuel : Nat} {profile : Profile} {target : Address} + {blobs literalBlobs : ConstantBlobs} {witness : ProofWitness Address} + (h : acceptsSerialized.{v} fuel profile target blobs witness literalBlobs = true) + (V : Type v) [SetTheory V] (levels : List Nat) (env : Nat → V) : + ∃ prepared, prepare? fuel profile target blobs literalBlobs = some prepared ∧ + ∃ result : CheckedProof.{0,v} prepared.signature prepared.input, + checkProofCertified fuel prepared.signature prepared.input witness = some result ∧ + ∃ constants : Assignment Address V, + prepared.signature.Compatible result.environment.entries constants ∧ + WellDenoted constants levels env result.proof.val ∧ + WellDenoted constants levels env result.proposition.val ∧ + interp constants levels env result.proof.val ∈ˢ + interp constants levels env result.proposition.val := by + obtain ⟨prepared, hp, ha⟩ := acceptsSerialized_prepared h + exact ⟨prepared, hp, accepted_has_model ha V levels env⟩ + +/-- This checks the decoded target statement against the profile's exact +empty proposition. It performs no theorem or semantic witness search. -/ +def isFalseStatement (fuel : Nat) (profile : Profile) (target : Address) + (blobs : ConstantBlobs) (literalBlobs : ConstantBlobs := []) : Bool := + match prepare? fuel profile target blobs literalBlobs with + | none => false + | some prepared => decide (prepared.input.proposition = prepared.signature.falseExpr) + +theorem no_serialized_proof_of_False {fuel : Nat} {profile : Profile} {target : Address} + {blobs literalBlobs : ConstantBlobs} {witness : ProofWitness Address} + (V : Type v) [SetTheory V] + (hf : isFalseStatement fuel profile target blobs literalBlobs = true) + (h : acceptsSerialized.{v} fuel profile target blobs witness literalBlobs = true) : False := by + obtain ⟨prepared, hp, ha⟩ := acceptsSerialized_prepared h + have he : prepared.input.proposition = prepared.signature.falseExpr := by + simpa only [isFalseStatement, hp, decide_eq_true_eq] using hf + exact no_proof_of_False V he ha + +end Ix.Certified diff --git a/Ix/Certified/ClaimAccept.lean b/Ix/Certified/ClaimAccept.lean new file mode 100644 index 000000000..7e5203f5d --- /dev/null +++ b/Ix/Certified/ClaimAccept.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Reveal + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v + +def LogicalKind : Ix.Claim → Prop + | .check .. | .checkEnv .. | .catalog .. => True + | _ => False + +theorem LogicalReceipt.kind (receipt : LogicalReceipt.{v} source fuel envelope witness) : + LogicalKind envelope.claim := by + have h := receipt.checked.content.meaning + cases hc : envelope.claim <;> simp_all [LogicalKind] + +/-- Meaning of the exact source declarations selected by the public claim. +The annotated readings remain tied to their original type fields and tables. -/ +def SubjectsInterpreted (receipt : LogicalReceipt.{v} source fuel envelope witness) + (V : Type v) [SetTheory V] (constants : Assignment Address V) : Prop := + ∀ ref ∈ receipt.checked.subjects, ∃ entry, + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env entry.type ∧ + constants ref levels ∈ˢ interp constants levels env entry.type + +def LogicalMeaning (source : Ixon.Env) (fuel : Nat) (envelope : Envelope) : Prop := + ∃ witness : LogicalWitness, ∃ receipt : LogicalReceipt.{v} source fuel envelope witness, + SignatureReading envelope.profile receipt.snapshot.decodedObjects receipt.checked.signature ∧ + (∀ ref ∈ receipt.checked.frontierRefs, ∃ entry, + receipt.checked.batch.receipt.frontier.interface.entries ref = some entry ∧ + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry) ∧ + (∀ ref ∈ receipt.checked.axiomRefs, ∃ entry, + Standard.EntrySource receipt.checked.store ref entry ∨ Quotient.EntrySource receipt.checked.store ref entry) ∧ + (∀ (V : Type v) [SetTheory V] (constants : Assignment Address V), + receipt.checked.signature.Compatible receipt.checked.batch.receipt.frontier.interface.entries constants → + ∃ constants' : Assignment Address V, + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants' ∧ + Assignment.AgreesOn receipt.checked.batch.receipt.frontier.interface.entries constants constants' ∧ + SubjectsInterpreted receipt V constants') ∧ + (claimFrontier envelope.claim = none → ∀ (V : Type v) [SetTheory V], + ∃ constants : Assignment Address V, + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants ∧ + SubjectsInterpreted receipt V constants) + +theorem LogicalReceipt.meaning (receipt : LogicalReceipt.{v} source fuel envelope witness) : + LogicalMeaning.{v} source fuel envelope := + ⟨witness, receipt, readSignature_sound receipt.checked.signatureReading, + fun _ h => receipt.checked.original_frontier h, + fun _ h => receipt.checked.logical_policy h, + fun V _ constants hM => receipt.subject_meaning V constants hM, + fun closed V _ => receipt.closed_subject_meaning closed V⟩ + +/-- One contract for the versioned claim protocol. Structural membership and +revelation remain structural. Evaluation is excluded until a separate +execution/result interpretation has been proved and bound to the profile. -/ +def SemanticClaimMeaning (source : Ixon.Env) (fuel : Nat) (envelope : Envelope) : Prop := + envelope.protocol = Protocol.current ∧ + match envelope.claim with + | .check .. | .checkEnv .. | .catalog .. => LogicalMeaning.{v} source fuel envelope + | .contains root target => envelope.logicalAxioms = none ∧ TreeMembership root target + | .reveal commitment info => envelope.logicalAxioms = none ∧ RevealMeaning source commitment info + | .eval .. => False + +inductive ClaimWitness where + | logical (witness : LogicalWitness) + | contains (tree : ByteArray) + | reveal (witness : RevealWitness) + +inductive ClaimAction (source : Ixon.Env) (fuel : Nat) (envelope : Envelope) where + | logical {witness : LogicalWitness} (receipt : LogicalReceipt.{v} source fuel envelope witness) + | contains {root target : Address} {bytes : ByteArray} + (claim : envelope.claim = .contains root target) + (noAxioms : envelope.logicalAxioms = none) (opening : TreeOpening fuel root bytes) + (member : target ∈ treeLeaves opening.tree) + | reveal {commitment : Address} {info : Ix.RevealConstantInfo} {witness : RevealWitness} + (claim : envelope.claim = .reveal commitment info) + (noAxioms : envelope.logicalAxioms = none) (receipt : RevealReceipt source commitment info witness) + +structure ClaimReceipt (source : Ixon.Env) (fuel : Nat) (address : Address) (bytes : ByteArray) where + reading : EnvelopeReading address bytes + action : ClaimAction.{v} source fuel reading.envelope + +def checkClaimAction? (fuel : Nat) (source : Ixon.Env) (envelope : Envelope) (witness : ClaimWitness) : + Read source (ClaimAction.{v} source fuel envelope) := + match hc : envelope.claim, witness with + | .check .., .logical witness | .checkEnv .., .logical witness | .catalog .., .logical witness => do + let receipt ← checkLogicalSource?.{v} fuel source envelope witness + return .logical receipt + | .contains root target, .contains bytes => + if ha : envelope.logicalAxioms = none then + match readTree? fuel root bytes with + | none => failure + | some opening => + if hm : (treeLeaves opening.tree).contains target = true then + pure (.contains hc ha opening (List.contains_iff_mem.mp hm)) else failure + else failure + | .reveal commitment info, .reveal witness => + if ha : envelope.logicalAxioms = none then do + let receipt ← checkReveal? source commitment info witness + return .reveal hc ha receipt + else failure + | _, _ => failure + +/-- Public source acceptance starts with exact authenticated claim bytes. +Protocol and policy versions are checked before any dispatcher branch. -/ +def checkClaimBytes? (fuel : Nat) (source : Ixon.Env) (address : Address) (bytes : ByteArray) + (witness : ClaimWitness) : Read source (ClaimReceipt.{v} source fuel address bytes) := + match readEnvelope? fuel address bytes with + | none => failure + | some reading => do + let action ← checkClaimAction?.{v} fuel source reading.envelope witness + return ⟨reading, action⟩ + +def acceptsClaimBytes (fuel : Nat) (source : Ixon.Env) (address : Address) (bytes : ByteArray) + (witness : ClaimWitness) : Bool := + (checkClaimBytes?.{v} fuel source address bytes witness {}).isSome + +theorem ClaimReceipt.meaning (receipt : ClaimReceipt.{v} source fuel address bytes) : + SemanticClaimMeaning.{v} source fuel receipt.reading.envelope := by + refine ⟨receipt.reading.supported, ?_⟩ + cases receipt.action with + | logical logical => + have kind := logical.kind + have meaning := logical.meaning + cases hc : receipt.reading.envelope.claim <;> simp_all [LogicalKind] + | contains claim noAxioms opening member => + rw [claim] + exact ⟨noAxioms, opening.membership member⟩ + | reveal claim noAxioms revealed => + rw [claim] + exact ⟨noAxioms, revealed.meaning⟩ + +/-- Successful source checking yields the meaning of the exact authenticated +public envelope, including profile, statement, frontier and logical-use root. -/ +theorem accepted_claim_meaning {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} + {witness : ClaimWitness} (h : acceptsClaimBytes.{v} fuel source address bytes witness = true) : + ∃ receipt : ClaimReceipt.{v} source fuel address bytes, ∃ cache, + checkClaimBytes? fuel source address bytes witness {} = some (receipt, cache) ∧ + Address.blake3 bytes = address ∧ envelopeBytes receipt.reading.envelope = bytes ∧ + SemanticClaimMeaning.{v} source fuel receipt.reading.envelope := by + unfold acceptsClaimBytes at h + obtain ⟨⟨receipt, cache⟩, hc⟩ := Option.isSome_iff_exists.mp h + exact ⟨receipt, cache, hc, receipt.reading.authenticated, receipt.reading.canonical, receipt.meaning⟩ + +theorem evaluation_not_semantic {source : Ixon.Env} {fuel : Nat} {envelope : Envelope} + {input output : Address} {frontier : Option Address} + (h : envelope.claim = .eval input output frontier) : ¬ SemanticClaimMeaning.{v} source fuel envelope := by + simp [SemanticClaimMeaning, h] + +theorem membership_not_leaf {fuel : Nat} {root target : Address} {bytes : Option ByteArray} : + readSubjectView? fuel (.contains root target) bytes = none := by cases bytes <;> rfl + +theorem revelation_not_leaf {fuel : Nat} {commitment : Address} {info : Ix.RevealConstantInfo} + {bytes : Option ByteArray} : readSubjectView? fuel (.reveal commitment info) bytes = none := by + cases bytes <;> rfl + +end Ix.Certified diff --git a/Ix/Certified/ClaimAudit.lean b/Ix/Certified/ClaimAudit.lean new file mode 100644 index 000000000..23b9676b7 --- /dev/null +++ b/Ix/Certified/ClaimAudit.lean @@ -0,0 +1,49 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.AuditSupport +import Ix.Certified.ClaimCommand + +/-! Trust, runtime and premise inventory of the versioned semantic claim +checker, source command and actual TcM acceptance boundary. -/ + +open Lean Lean.Elab Command + +namespace Ix.Certified.ClaimAudit + +def roots : Array Lean.Name := #[ + `Ix.Certified.TreeOpening.membership, `Ix.Certified.TreeOpening.unique, + `Ix.Certified.treeLeaves_join, `Ix.Certified.EnvelopeReading.unique, + `Ix.Certified.readEnvelope?, `Ix.Certified.readTree?, + `Ix.Certified.LogicalChecking.original_subject, `Ix.Certified.LogicalChecking.original_frontier, + `Ix.Certified.LogicalChecking.logical_policy, `Ix.Certified.LogicalChecking.closed_frontier, + `Ix.Certified.LogicalReceipt.subject_meaning, `Ix.Certified.LogicalReceipt.closed_subject_meaning, + `Ix.Certified.LogicalReceipt.no_False, + `Ix.Certified.RevealReceipt.meaning, `Ix.Certified.ClaimReceipt.meaning, + `Ix.Certified.accepted_claim_meaning, `Ix.Certified.evaluation_not_semantic, + `Ix.Certified.membership_not_leaf, `Ix.Certified.revelation_not_leaf, + `Ix.Kernel.TcM.checkClaimCertified_success, + `Ix.Kernel.certifiedClaimStep_failure, `Ix.Kernel.certifiedClaimStep_success, + `Ix.Kernel.accepted_tc_claim_meaning, + `Ix.Certified.ClaimCommand.readRequest, + `Ix.Certified.ClaimCommand.run_success, `Ix.Certified.ClaimCommand.run_meaning] + +def premises : Array Lean.Name := #[ + `Ix.Certified.Protocol.current, `Ix.Certified.envelopeMagic, + `Ix.Certified.putEnvelope, `Ix.Certified.getEnvelope, + `Ix.Certified.EnvelopeReading.mk, `Ix.Certified.TreeOpening.mk, + `Ix.Certified.OptionalTreeOpening.mk, `Ix.Certified.SubjectView.mk, + `Ix.Certified.PreparedLeaf.mk, `Ix.Certified.ContentView.mk, + `Ix.Certified.ownedReferences, `Ix.Certified.claimFrontier, + `Ix.Certified.LogicalChecking.mk, `Ix.Certified.LogicalReceipt.mk, + `Ix.Certified.SubjectsInterpreted, `Ix.Certified.LogicalMeaning, + `Ix.Certified.RevealMatches, `Ix.Certified.ConstructorMatches, + `Ix.Certified.ConstructorsMatch, `Ix.Certified.MutMatches, + `Ix.Certified.ComponentsMatch, `Ix.Certified.RulesMatch, + `Ix.Certified.RevealMeaning, `Ix.Certified.SemanticClaimMeaning] + +run_cmd AuditSupport.report "claim meaning" roots premises + +end Ix.Certified.ClaimAudit diff --git a/Ix/Certified/ClaimCheck.lean b/Ix/Certified/ClaimCheck.lean new file mode 100644 index 000000000..7a8b8cb43 --- /dev/null +++ b/Ix/Certified/ClaimCheck.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.ClaimInput + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v + +structure LogicalWitness where + selection : InputSelection + leaves : List LeafWitness + subjects : Option ByteArray + members : Option ByteArray + frontierTree : Option ByteArray + frontier : List (FrontierWitness Address) + axiomTree : Option ByteArray + +structure LogicalChecking {source : Ixon.Env} (snapshot : SourceSnapshot source) + (fuel : Nat) (envelope : Envelope) (witness : LogicalWitness) where + uniqueSource : ((snapshot.blobs ++ snapshot.literalBlobs).map Prod.fst).Nodup + signature : PrimitiveSignature Address + signatureReading : readSignature? envelope.profile snapshot.decodedObjects = some signature + store : Store Address + storeReading : readStore? fuel snapshot.decodedObjects snapshot.decodedNaturals = some store + leaves : List (LeafInput fuel snapshot.decodedObjects) + leavesReading : witness.leaves.mapM (readLeafInput? fuel snapshot.decodedObjects) = some leaves + content : ContentView fuel envelope.claim witness.subjects witness.members leaves + subjects : List (ConstRef Address) + subjectsReading : content.addresses.flatMapM (subjectReferences? snapshot.decodedObjects) = some subjects + frontier : OptionalTreeOpening fuel (claimFrontier envelope.claim) witness.frontierTree + frontierRefs : List (ConstRef Address) + frontierReading : frontier.leaves.flatMapM (subjectReferences? snapshot.decodedObjects) = some frontierRefs + batch : CheckedBatch.{0,v} fuel signature store (leaves.map (fun leaf => leaf.prepared.node signature)) + batchChecking : checkBatch? fuel signature store witness.frontier + (leaves.map (fun leaf => leaf.prepared.node signature)) = some batch + exactSubjects : ∀ ref, ref ∈ nodeSubjects batch.nodes ↔ ref ∈ ownedReferences signature subjects + exactFrontier : ∀ ref, ref ∈ batch.receipt.frontier.refs ↔ ref ∈ frontierRefs + axioms : OptionalTreeOpening fuel envelope.logicalAxioms witness.axiomTree + axiomRefs : List (ConstRef Address) + axiomsReading : axioms.leaves.flatMapM (subjectReferences? snapshot.decodedObjects) = some axiomRefs + exactAxioms : ∀ ref, ref ∈ batch.logicalUses ↔ ref ∈ axiomRefs + +def checkLogicalSnapshot? {source : Ixon.Env} (snapshot : SourceSnapshot source) + (fuel : Nat) (envelope : Envelope) (witness : LogicalWitness) : + Option (LogicalChecking.{v} snapshot fuel envelope witness) := + if hu : ((snapshot.blobs ++ snapshot.literalBlobs).map Prod.fst).Nodup then + match hs : readSignature? envelope.profile snapshot.decodedObjects with + | none => none + | some signature => + match ht : readStore? fuel snapshot.decodedObjects snapshot.decodedNaturals with + | none => none + | some store => + match hl : witness.leaves.mapM (readLeafInput? fuel snapshot.decodedObjects) with + | none => none + | some leaves => do + let content ← readContentView? fuel envelope.claim witness.subjects witness.members leaves + match htargets : content.addresses.flatMapM (subjectReferences? snapshot.decodedObjects) with + | none => none + | some subjects => do + let frontier ← readOptionalTree? fuel (claimFrontier envelope.claim) witness.frontierTree + match hfrontier : frontier.leaves.flatMapM (subjectReferences? snapshot.decodedObjects) with + | none => none + | some frontierRefs => + match hc : checkBatch?.{0,v} fuel signature store witness.frontier + (leaves.map (fun leaf => leaf.prepared.node signature)) with + | none => none + | some batch => + if hsubjects : sameMembers (nodeSubjects batch.nodes) (ownedReferences signature subjects) = true then + if hf : sameMembers batch.receipt.frontier.refs frontierRefs = true then do + let axioms ← readOptionalTree? fuel envelope.logicalAxioms witness.axiomTree + match haxioms : axioms.leaves.flatMapM (subjectReferences? snapshot.decodedObjects) with + | none => none + | some axiomRefs => + if ha : sameMembers batch.logicalUses axiomRefs = true then + some ⟨hu, signature, hs, store, ht, leaves, hl, content, subjects, htargets, + frontier, frontierRefs, hfrontier, batch, hc, sameMembers_iff.mp hsubjects, + sameMembers_iff.mp hf, axioms, axiomRefs, haxioms, sameMembers_iff.mp ha⟩ + else none + else none + else none + else none + +structure LogicalReceipt (source : Ixon.Env) (fuel : Nat) (envelope : Envelope) (witness : LogicalWitness) where + snapshot : SourceSnapshot source + checked : LogicalChecking.{v} snapshot fuel envelope witness + supported : envelope.protocol = Protocol.current + +/-- Every cache hit revalidates the actual complete claim. Only authenticated +data is reused; claim, policy, frontier and model checks run on every request. -/ +def checkLogicalSource? (fuel : Nat) (source : Ixon.Env) (envelope : Envelope) (witness : LogicalWitness) : + Read source (LogicalReceipt.{v} source fuel envelope witness) := + if hp : envelope.protocol = Protocol.current then do + let snapshot ← readSnapshot? fuel source witness.selection + match checkLogicalSnapshot?.{v} snapshot fuel envelope witness with + | none => failure + | some checked => return ⟨snapshot, checked, hp⟩ + else failure + +end Ix.Certified diff --git a/Ix/Certified/ClaimCommand.lean b/Ix/Certified/ClaimCommand.lean new file mode 100644 index 000000000..659c87de0 --- /dev/null +++ b/Ix/Certified/ClaimCommand.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.ClaimSuggest +import Ix.Kernel.CertifiedClaims + +/-! Generic command for the versioned public claim protocol. Public bytes +and their expected address are inputs; JSON supplies only untrusted search +hints. Each successful command ends in the certified TcM claim checker. -/ + +namespace Ix.Certified.ClaimCommand + +universe v + +inductive Hint where + | logical (hint : LogicalHint) + | contains (tree : ByteArray) + | reveal (witness : RevealWitness) + +structure Request where + address : Address + hint : Hint + +def readAddress (value : String) : Except String Address := + match Address.fromString value with + | none => .error "expected a 32-byte hexadecimal address" + | some address => .ok address + +def readHex (value : String) : Except String ByteArray := + match bytesOfHex value with + | none => .error "expected an even-length hexadecimal byte string" + | some bytes => .ok bytes + +def readOptionalHex (json : Lean.Json) (field : String) : Except String (Option ByteArray) := do + (← json.getObjValAs? (Option String) field).mapM readHex + +def readLeaf (json : Lean.Json) : Except String LeafHint := do + let bytes ← readHex (← json.getObjValAs? String "claim") + let claim ← Ixon.runGetExact Ix.Claim.get bytes + if Ix.Claim.ser claim != bytes then throw "noncanonical leaf claim bytes" + return ⟨claim, ← readOptionalHex json "subjects", ← readOptionalHex json "frontier"⟩ + +def readLogicalHint (json : Lean.Json) : Except String LogicalHint := do + let objects ← (← json.getObjValAs? (List String) "objects").mapM readAddress + let naturals ← (← json.getObjValAs? (List String) "naturals").mapM readAddress + let leaves ← (← json.getObjValAs? (List Lean.Json) "leaves").mapM readLeaf + return ⟨⟨objects, naturals⟩, leaves, ← readOptionalHex json "subjects", + ← readOptionalHex json "members", ← readOptionalHex json "frontier", ← readOptionalHex json "axioms", + ← ModelHint.readOptional json⟩ + +def readRequest (json : Lean.Json) : Except String Request := do + let address ← readAddress (← json.getObjValAs? String "address") + let kind ← json.getObjValAs? String "kind" + let hint : Hint ← if kind = "logical" then do pure (Hint.logical (← readLogicalHint json)) + else if kind = "contains" then do pure (Hint.contains (← readHex (← json.getObjValAs? String "tree"))) + else if kind = "reveal" then do + let secret ← readAddress (← json.getObjValAs? String "secret") + let payload ← readAddress (← json.getObjValAs? String "payload") + pure (Hint.reveal ⟨⟨secret, payload⟩⟩) + else throw "kind must be logical, contains or reveal" + return ⟨address, hint⟩ + +def suggestWitness? (fuel : Nat) (source : Ixon.Env) (bytes : ByteArray) (request : Request) : + Option ClaimWitness := do + let reading ← readEnvelope? fuel request.address bytes + match request.hint with + | .logical hint => return .logical (← suggestLogical? fuel source reading.envelope hint) + | .contains tree => return .contains tree + | .reveal witness => return .reveal witness + +def run (fuel : Nat) (source : Ixon.Env) (bytes : ByteArray) (request : Request) : Except String Unit := do + let some witness := suggestWitness? fuel source bytes request + | throw "certified envelope or witness search declined" + if Kernel.acceptsCertifiedClaim.{v} fuel source request.address bytes witness then return () + else throw "certified claim validation rejected the witness" + +theorem run_success {fuel : Nat} {source : Ixon.Env} {bytes : ByteArray} {request : Request} + (h : run.{v} fuel source bytes request = .ok ()) : + ∃ witness, Kernel.acceptsCertifiedClaim.{v} fuel source request.address bytes witness = true := by + cases hw : suggestWitness? fuel source bytes request with + | none => simp [run, hw] at h + | some witness => + by_cases ha : Kernel.acceptsCertifiedClaim.{v} fuel source request.address bytes witness = true + · exact ⟨witness, ha⟩ + · simp [run, hw, ha] at h + +theorem run_meaning {fuel : Nat} {source : Ixon.Env} {bytes : ByteArray} {request : Request} + (h : run.{v} fuel source bytes request = .ok ()) : + ∃ receipt : ClaimReceipt.{v} source fuel request.address bytes, + Address.blake3 bytes = request.address ∧ envelopeBytes receipt.reading.envelope = bytes ∧ + SemanticClaimMeaning.{v} source fuel receipt.reading.envelope := by + obtain ⟨witness, hw⟩ := run_success h + obtain ⟨receipt, _, ha, hb, hm⟩ := Kernel.accepted_tc_claim_meaning hw + exact ⟨receipt, ha, hb, hm⟩ + +def main (args : List String) : IO UInt32 := do + let [sourcePath, envelopePath, requestPath] := args | do + IO.eprintln "usage: certified-claim-check SOURCE.ixe ENVELOPE.bin REQUEST.json" + return 2 + let sourceBytes ← IO.FS.readBinFile sourcePath + let envelope ← IO.FS.readBinFile envelopePath + let requestText ← IO.FS.readFile requestPath + let result := do + let request ← readRequest (← Lean.Json.parse requestText) + let parts ← Ixon.deEnvVerifiedLazy sourceBytes + run.{0} 6400 parts.env envelope request + return request.address + match result with + | .error error => IO.eprintln error; return 1 + | .ok address => + IO.println <| (Lean.Json.mkObj [("accepted", Lean.toJson true), + ("address", Lean.toJson (hexOfBytes address.hash))]).compress + return 0 + +end Ix.Certified.ClaimCommand diff --git a/Ix/Certified/ClaimInput.lean b/Ix/Certified/ClaimInput.lean new file mode 100644 index 000000000..c5497b8a5 --- /dev/null +++ b/Ix/Certified/ClaimInput.lean @@ -0,0 +1,145 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Envelope +import Ix.Theory.Certified.ClaimComposition + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model + +def sameMembers {α : Type _} [DecidableEq α] (a b : List α) : Bool := + a.all (b.contains ·) && b.all (a.contains ·) + +theorem sameMembers_iff {α : Type _} [DecidableEq α] {a b : List α} : + sameMembers a b = true ↔ ∀ x, x ∈ a ↔ x ∈ b := by + simp only [sameMembers, Bool.and_eq_true, List.all_eq_true, List.contains_iff_mem] + exact ⟨fun h x => ⟨h.1 x, h.2 x⟩, fun h => ⟨fun x => (h x).mp, fun x => (h x).mpr⟩⟩ + +def claimFrontier : Ix.Claim → Option Address + | .check _ frontier | .checkEnv _ frontier | .catalog _ _ frontier | .eval _ _ frontier => frontier + | _ => none + +structure SubjectView (fuel : Nat) (claim : Ix.Claim) (bytes : Option ByteArray) where + addresses : List Address + meaning : match claim with + | .check address _ => bytes = none ∧ addresses = [address] + | .checkEnv root _ => ∃ raw, bytes = some raw ∧ + ∃ opening : TreeOpening fuel root raw, treeLeaves opening.tree = addresses + | _ => False + +def readSubjectView? (fuel : Nat) (claim : Ix.Claim) (bytes : Option ByteArray) : + Option (SubjectView fuel claim bytes) := + match claim, bytes with + | .check address _, none => some ⟨[address], rfl, rfl⟩ + | .checkEnv root _, some raw => do + let opening ← readTree? fuel root raw + return ⟨treeLeaves opening.tree, raw, rfl, opening, rfl⟩ + | _, _ => none + +def ownedReferences (signature : PrimitiveSignature Address) (refs : List (ConstRef Address)) : + List (ConstRef Address) := + (refs.filter fun ref => ref != signature.falseType && ref != signature.falseElim).eraseDups + +theorem mem_ownedReferences {signature : PrimitiveSignature Address} {refs : List (ConstRef Address)} + {ref : ConstRef Address} : ref ∈ ownedReferences signature refs ↔ + ref ∈ refs ∧ ref ≠ signature.falseType ∧ ref ≠ signature.falseElim := by + simp [ownedReferences] + +structure LeafWitness where + claim : Ix.Claim + subjects : Option ByteArray + frontierTree : Option ByteArray + frontier : List (FrontierWitness Address) + declarations : List (DeclarationWitness Address) + +structure PreparedLeaf (fuel : Nat) (objects : Objects) (witness : LeafWitness) where + subjectView : SubjectView fuel witness.claim witness.subjects + subjectRefs : List (ConstRef Address) + subjectsResolved : subjectView.addresses.flatMapM (subjectReferences? objects) = some subjectRefs + frontierView : OptionalTreeOpening fuel (claimFrontier witness.claim) witness.frontierTree + frontierRefs : List (ConstRef Address) + frontierResolved : frontierView.leaves.flatMapM (subjectReferences? objects) = some frontierRefs + frontierExact : ∀ ref, ref ∈ witness.frontier.map (·.ref) ↔ ref ∈ frontierRefs + +def prepareLeaf? (fuel : Nat) (objects : Objects) (witness : LeafWitness) : + Option (PreparedLeaf fuel objects witness) := do + let subjectView ← readSubjectView? fuel witness.claim witness.subjects + match hs : subjectView.addresses.flatMapM (subjectReferences? objects) with + | none => none + | some subjectRefs => do + let frontierView ← readOptionalTree? fuel (claimFrontier witness.claim) witness.frontierTree + match hf : frontierView.leaves.flatMapM (subjectReferences? objects) with + | none => none + | some frontierRefs => + if he : sameMembers (witness.frontier.map (·.ref)) frontierRefs = true then + some ⟨subjectView, subjectRefs, hs, frontierView, frontierRefs, hf, sameMembers_iff.mp he⟩ + else none + +def PreparedLeaf.node {fuel : Nat} {objects : Objects} {witness : LeafWitness} + (leaf : PreparedLeaf fuel objects witness) (signature : PrimitiveSignature Address) : ClaimNode Address := + ⟨ownedReferences signature leaf.subjectRefs, witness.frontier, witness.declarations⟩ + +structure LeafInput (fuel : Nat) (objects : Objects) where + witness : LeafWitness + prepared : PreparedLeaf fuel objects witness + +def readLeafInput? (fuel : Nat) (objects : Objects) (witness : LeafWitness) : + Option (LeafInput fuel objects) := do + let prepared ← prepareLeaf? fuel objects witness + return ⟨witness, prepared⟩ + +def leafAddresses {fuel : Nat} {objects : Objects} (leaves : List (LeafInput fuel objects)) : List Address := + leaves.flatMap (·.prepared.subjectView.addresses) + +def environmentRoot? : Ix.Claim → Option Address + | .checkEnv root _ => some root + | _ => none + +structure ContentView (fuel : Nat) (claim : Ix.Claim) (subjects members : Option ByteArray) + {objects : Objects} (leaves : List (LeafInput fuel objects)) where + addresses : List Address + exactLeaves : ∀ address, address ∈ addresses ↔ address ∈ leafAddresses leaves + meaning : match claim with + | .check address _ => subjects = none ∧ members = none ∧ addresses = [address] + | .checkEnv root _ => members = none ∧ ∃ raw, subjects = some raw ∧ + ∃ opening : TreeOpening fuel root raw, treeLeaves opening.tree = addresses + | .catalog memberRoot contentRoot _ => ∃ rawContent rawMembers, + subjects = some rawContent ∧ members = some rawMembers ∧ + ∃ content : TreeOpening fuel contentRoot rawContent, + ∃ membership : TreeOpening fuel memberRoot rawMembers, + treeLeaves content.tree = addresses ∧ + ∃ roots, leaves.mapM (fun leaf => environmentRoot? leaf.witness.claim) = some roots ∧ + ∀ root, root ∈ treeLeaves membership.tree ↔ root ∈ roots + | _ => False + +def readContentView? (fuel : Nat) (claim : Ix.Claim) (subjects members : Option ByteArray) + {objects : Objects} (leaves : List (LeafInput fuel objects)) : + Option (ContentView fuel claim subjects members leaves) := + match claim, subjects, members with + | .check address _, none, none => + if he : sameMembers [address] (leafAddresses leaves) = true then + some ⟨[address], sameMembers_iff.mp he, rfl, rfl, rfl⟩ + else none + | .checkEnv root _, some raw, none => do + let opening ← readTree? fuel root raw + if he : sameMembers (treeLeaves opening.tree) (leafAddresses leaves) = true then + some ⟨treeLeaves opening.tree, sameMembers_iff.mp he, rfl, raw, rfl, opening, rfl⟩ + else none + | .catalog memberRoot contentRoot _, some rawContent, some rawMembers => do + let content ← readTree? fuel contentRoot rawContent + let membership ← readTree? fuel memberRoot rawMembers + match hr : leaves.mapM (fun leaf => environmentRoot? leaf.witness.claim) with + | none => none + | some roots => + if he : sameMembers (treeLeaves content.tree) (leafAddresses leaves) = true then + if hm : sameMembers (treeLeaves membership.tree) roots = true then + some ⟨treeLeaves content.tree, sameMembers_iff.mp he, rawContent, rawMembers, rfl, rfl, + content, membership, rfl, roots, hr, sameMembers_iff.mp hm⟩ + else none + else none + | _, _, _ => none + +end Ix.Certified diff --git a/Ix/Certified/ClaimMain.lean b/Ix/Certified/ClaimMain.lean new file mode 100644 index 000000000..2028b1f52 --- /dev/null +++ b/Ix/Certified/ClaimMain.lean @@ -0,0 +1,8 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.ClaimCommand + +def main := Ix.Certified.ClaimCommand.main diff --git a/Ix/Certified/ClaimMeaning.lean b/Ix/Certified/ClaimMeaning.lean new file mode 100644 index 000000000..08158bd8f --- /dev/null +++ b/Ix/Certified/ClaimMeaning.lean @@ -0,0 +1,151 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.ClaimCheck + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v +variable {source : Ixon.Env} {snapshot : SourceSnapshot source} + {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + +theorem OptionalTreeOpening.none_leaves (opening : OptionalTreeOpening fuel none bytes) : + opening.leaves = [] := by + cases bytes with + | none => exact opening.evidence + | some => exact False.elim opening.evidence + +theorem OptionalTreeOpening.closed_leaves (opening : OptionalTreeOpening fuel root bytes) + (closed : root = none) : opening.leaves = [] := by + subst root + exact opening.none_leaves + +theorem LogicalChecking.target_entry + (checked : LogicalChecking.{v} snapshot fuel envelope witness) + {ref : ConstRef Address} (hr : ref ∈ checked.subjects) : + ∃ entry, checked.batch.receipt.checked.result.entries ref = some entry ∧ + EntrySource checked.signature checked.store ref entry := by + have validated := (checked.signature.validate_iff checked.store).mp checked.batch.receipt.frontier.validated + by_cases hF : ref = checked.signature.falseType + · subst ref + exact ⟨PrimitiveSignature.falseEntry, checked.batch.receipt.checked.result.present.1, + Or.inl ⟨rfl, rfl, validated.1⟩⟩ + · by_cases hE : ref = checked.signature.falseElim + · subst ref + exact ⟨checked.signature.falseElimEntry, checked.batch.receipt.checked.result.present.2, + Or.inr (Or.inl ⟨rfl, rfl, validated.2⟩)⟩ + · have owned := (checked.exactSubjects ref).mpr (mem_ownedReferences.mpr ⟨hr, hF, hE⟩) + have hp := checked.batch.receipt.present ref owned + obtain ⟨entry, he⟩ := Option.isSome_iff_exists.mp hp + refine ⟨entry, he, ?_⟩ + rcases checked.batch.receipt.checked.source ref entry he with old | new + · rw [checked.batch.receipt.fresh ref owned] at old + cases old + · exact new + +theorem LogicalChecking.original_subject + (checked : LogicalChecking.{v} snapshot fuel envelope witness) + {ref : ConstRef Address} (hr : ref ∈ checked.subjects) : + ∃ entry, checked.batch.receipt.checked.result.entries ref = some entry ∧ + SourceDeclarationReading source snapshot.decodedObjects snapshot.decodedNaturals ref entry := by + obtain ⟨entry, he, hs⟩ := checked.target_entry hr + exact ⟨entry, he, snapshot.declaration_reading checked.storeReading hs.header⟩ + +theorem LogicalChecking.original_frontier + (checked : LogicalChecking.{v} snapshot fuel envelope witness) + {ref : ConstRef Address} (hr : ref ∈ checked.frontierRefs) : + ∃ entry, checked.batch.receipt.frontier.interface.entries ref = some entry ∧ + SourceDeclarationReading source snapshot.decodedObjects snapshot.decodedNaturals ref entry := by + have hm := (checked.exactFrontier ref).mpr hr + obtain ⟨header, hh, rfl⟩ := List.mem_map.mp hm + exact ⟨header.entry, checked.batch.receipt.frontier.formed.lookup hh, + snapshot.declaration_reading checked.storeReading (checked.batch.receipt.frontier.header_source hh)⟩ + +/-- The claim's public axiom tree contains every use, including uses retained +from leaves. Each address resolves to an exactly realized source schema. -/ +theorem LogicalChecking.logical_policy + (checked : LogicalChecking.{v} snapshot fuel envelope witness) + {ref : ConstRef Address} (hr : ref ∈ checked.axiomRefs) : + ∃ entry, Standard.EntrySource checked.store ref entry ∨ Quotient.EntrySource checked.store ref entry := + checked.batch.logicalUses_authorized ((checked.exactAxioms ref).mpr hr) + +theorem LogicalChecking.closed_frontier + (checked : LogicalChecking.{v} snapshot fuel envelope witness) + (closed : claimFrontier envelope.claim = none) : checked.batch.receipt.frontier.refs = [] := by + have hl : checked.frontier.leaves = [] := by + exact checked.frontier.closed_leaves closed + have hr : checked.frontierRefs = [] := by + have h := checked.frontierReading + rw [hl] at h + simpa using h.symm + apply List.eq_nil_iff_forall_not_mem.mpr + intro ref hm + have h := (checked.exactFrontier ref).mp hm + rw [hr] at h + cases h + +/-- Conditional soundness of every original source member or constructor in +the exact committed subject set. All declared frontier values are preserved +at every universe instance while the shared interpretation is extended. -/ +theorem LogicalReceipt.subject_meaning + (receipt : LogicalReceipt.{v} source fuel envelope witness) + (V : Type v) [SetTheory V] (constants : Assignment Address V) + (hM : receipt.checked.signature.Compatible receipt.checked.batch.receipt.frontier.interface.entries constants) : + ∃ constants' : Assignment Address V, + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants' ∧ + Assignment.AgreesOn receipt.checked.batch.receipt.frontier.interface.entries constants constants' ∧ + ∀ ref ∈ receipt.checked.subjects, ∃ entry, + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants' levels env entry.type ∧ + constants' ref levels ∈ˢ interp constants' levels env entry.type := by + obtain ⟨constants', hm, ha⟩ := receipt.checked.batch.receipt.checked.extension.models V constants hM + refine ⟨constants', hm, ha, ?_⟩ + intro ref hr + obtain ⟨entry, he, hs⟩ := receipt.checked.original_subject hr + refine ⟨entry, hs, ?_⟩ + intro levels hl env + exact ⟨hm.realizes.typeValid ref entry he levels hl env, + hm.realizes.member ref entry he levels hl env⟩ + +/-- A public claim with no structural frontier constructs its model. This +does not assert that its separately recorded logical-axiom set is empty. -/ +theorem LogicalReceipt.closed_subject_meaning + (receipt : LogicalReceipt.{v} source fuel envelope witness) + (closed : claimFrontier envelope.claim = none) (V : Type v) [SetTheory V] : + ∃ constants : Assignment Address V, + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants ∧ + ∀ ref ∈ receipt.checked.subjects, ∃ entry, + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env entry.type ∧ + constants ref levels ∈ˢ interp constants levels env entry.type := by + have hf := receipt.checked.closed_frontier closed + have initial : receipt.checked.signature.Compatible receipt.checked.batch.receipt.frontier.interface.entries + (receipt.checked.signature.assignment (V := V)) := by + rw [receipt.checked.batch.receipt.frontier.empty_interface hf] + exact receipt.checked.signature.compatible_assignment + obtain ⟨constants, hm, _, subjects⟩ := receipt.subject_meaning V receipt.checked.signature.assignment initial + exact ⟨constants, hm, subjects⟩ + +theorem LogicalReceipt.no_False + (receipt : LogicalReceipt.{v} source fuel envelope witness) + (closed : claimFrontier envelope.claim = none) {ref : ConstRef Address} + (subject : ref ∈ receipt.checked.subjects) + (type : receipt.checked.store.type ref = some receipt.checked.signature.falseExpr) + (V : Type v) [SetTheory V] : False := by + have hf := receipt.checked.closed_frontier closed + obtain ⟨constants, hm, _⟩ := receipt.checked.batch.closed_has_model hf V + obtain ⟨entry, he, hs⟩ := receipt.checked.target_entry subject + have hc : entry.type = .const receipt.checked.signature.falseType [] := + AExpr.eq_const_of_erase_eq (Option.some.inj (hs.header.type.symm.trans type)) + have hmem := hm.realizes.member ref entry he (List.replicate entry.universes 0) (by simp) (fun _ => empty) + rw [hc] at hmem + simp only [interp, List.map_nil, hm.falseValue] at hmem + exact not_mem_empty _ hmem + +end Ix.Certified diff --git a/Ix/Certified/ClaimSuggest.lean b/Ix/Certified/ClaimSuggest.lean new file mode 100644 index 000000000..4052efd7c --- /dev/null +++ b/Ix/Certified/ClaimSuggest.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Claims +import Ix.Certified.ClaimAccept +import Ix.Certified.ModelHints + +/-! Untrusted witness construction. The acceptance path imports none of +these search functions and checks the public envelope and complete returned +witness again. Trees are hints whose public Merkle roots are checked. -/ + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model + +structure LeafHint where + claim : Ix.Claim + subjects : Option ByteArray + frontierTree : Option ByteArray + +structure LogicalHint where + selection : InputSelection + leaves : List LeafHint + subjects : Option ByteArray + members : Option ByteArray + frontierTree : Option ByteArray + axiomTree : Option ByteArray + models : List ModelHint := [] + +/-- Header dependency order is independent of the Merkle tree's leaf order. -/ +def frontierOrder? (fuel : Nat) (signature : PrimitiveSignature Address) (store : Store Address) + (allowed pending visited active : List (ConstRef Address)) : Option (List (ConstRef Address)) := + match fuel, pending with + | _, [] => some visited + | 0, _ :: _ => none + | fuel + 1, ref :: rest => + if ref = signature.falseType ∨ ref = signature.falseElim ∨ ref ∈ visited then + frontierOrder? fuel signature store allowed rest visited active + else if ref ∈ active ∨ ref ∉ allowed then none + else do + let type ← store.type ref + let visited ← frontierOrder? fuel signature store allowed type.refs visited (ref :: active) + frontierOrder? fuel signature store allowed rest (visited ++ [ref]) active + +def frontierSuggestion? (fuel : Nat) (signature : PrimitiveSignature Address) (store : Store Address) + (objects : Objects) (root : Option Address) (bytes : Option ByteArray) : + Option (List (ConstRef Address) × List (FrontierWitness Address)) := do + let opening ← readOptionalTree? fuel root bytes + let refs ← opening.leaves.flatMapM (subjectReferences? objects) + let ordered ← frontierOrder? fuel signature store refs refs [] [] + let (_, witnesses) ← Certificate.frontierWitnesses? fuel store signature.environment ordered + return (ordered, witnesses) + +def leafSuggestion? (fuel : Nat) (signature : PrimitiveSignature Address) (store : Store Address) + (objects : Objects) (hint : LeafHint) (models : List (Certificate.Modeled.Candidate Address) := []) : Option LeafWitness := do + let subjects ← readSubjectView? fuel hint.claim hint.subjects + let refs ← subjects.addresses.flatMapM (subjectReferences? objects) + let (frontier, _) ← frontierSuggestion? fuel signature store objects (claimFrontier hint.claim) hint.frontierTree + let node ← Certificate.claimNode? fuel signature store frontier (ownedReferences signature refs) models + return ⟨hint.claim, hint.subjects, hint.frontierTree, node.frontier, node.declarations⟩ + +def suggestLogical? (fuel : Nat) (source : Ixon.Env) (envelope : Envelope) (hint : LogicalHint) : + Option LogicalWitness := do + let (snapshot, _) ← readSnapshot? fuel source hint.selection {} + let signature ← readSignature? envelope.profile snapshot.decodedObjects + let store ← readStore? fuel snapshot.decodedObjects snapshot.decodedNaturals + let models ← modelCandidates? snapshot.decodedObjects store hint.models + let leaves ← hint.leaves.mapM (fun leaf => leafSuggestion? fuel signature store snapshot.decodedObjects leaf models) + let (_, frontier) ← frontierSuggestion? fuel signature store snapshot.decodedObjects + (claimFrontier envelope.claim) hint.frontierTree + return ⟨hint.selection, leaves, hint.subjects, hint.members, hint.frontierTree, frontier, hint.axiomTree⟩ + +end Ix.Certified diff --git a/Ix/Certified/Command.lean b/Ix/Certified/Command.lean new file mode 100644 index 000000000..0ad2ba24c --- /dev/null +++ b/Ix/Certified/Command.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Suggest +import Ix.Kernel.Certified + +/-! Generic source-file driver for the certified profile. The JSON request +selects the expected target/subjects, primitive signature and finite source +closure. Witness search is untrusted and always followed by certified TcM +validation. There is no inference-only or unchecked fallback command. -/ + +namespace Ix.Certified.Command + +universe v + +structure Request where + profile : Profile + target : Address + subjects : List Address + selection : InputSelection + models : List ModelHint := [] + +def readAddress (value : String) : Except String Address := + match Address.fromString value with + | none => .error "expected a 32-byte hexadecimal address" + | some address => .ok address + +def readRequest (json : Lean.Json) : Except String Request := do + let falseType ← readAddress (← json.getObjValAs? String "falseType") + let falseElim ← readAddress (← json.getObjValAs? String "falseElim") + let natural ← json.getObjValAs? (Option String) "natType" + let natType ← natural.mapM readAddress + let target ← readAddress (← json.getObjValAs? String "target") + let subjects ← (← json.getObjValAs? (List String) "subjects").mapM readAddress + let objects ← (← json.getObjValAs? (List String) "objects").mapM readAddress + let naturals ← (← json.getObjValAs? (List String) "naturals").mapM readAddress + return ⟨⟨falseType, falseElim, natType⟩, target, subjects, ⟨objects, naturals⟩, ← ModelHint.readOptional json⟩ + +def run (mode : String) (fuel : Nat) (source : Ixon.Env) (request : Request) : Except String Unit := do + if mode = "proof" then + let some witness := suggestSource? fuel source request.profile request.target request.selection request.models + | throw "certified proof witness search declined" + if Kernel.acceptsCertifiedSource.{v} fuel source request.profile request.target request.selection witness then + return () + else throw "certified proof validation rejected the witness" + else if mode = "store" then + let some witness := suggestStore? fuel source request.profile request.subjects request.selection request.models + | throw "certified declaration witness search declined" + if Kernel.acceptsCertifiedStoreSource.{v} fuel source request.profile request.subjects request.selection witness then + return () + else throw "certified declaration validation rejected the witness" + else throw "mode must be proof or store" + +/-- The generic command can report success only after an actual certified +source run. Witness search is not an alternate acceptance path. -/ +theorem run_success {mode : String} {fuel : Nat} {source : Ixon.Env} {request : Request} + (h : run.{v} mode fuel source request = .ok ()) : + (mode = "proof" ∧ ∃ witness, Kernel.acceptsCertifiedSource.{v} fuel source + request.profile request.target request.selection witness = true) ∨ + (mode = "store" ∧ ∃ witness, Kernel.acceptsCertifiedStoreSource.{v} fuel source + request.profile request.subjects request.selection witness = true) := by + by_cases hp : mode = "proof" + · cases hw : suggestSource? fuel source request.profile request.target request.selection request.models with + | none => simp [run, hp, hw] at h + | some witness => + by_cases ha : Kernel.acceptsCertifiedSource.{v} fuel source request.profile request.target request.selection witness = true + · exact .inl ⟨hp, witness, ha⟩ + · simp [run, hp, hw, ha] at h + · by_cases hs : mode = "store" + · cases hw : suggestStore? fuel source request.profile request.subjects request.selection request.models with + | none => simp [run, hs, hw] at h + | some witness => + by_cases ha : Kernel.acceptsCertifiedStoreSource.{v} fuel source request.profile request.subjects request.selection witness = true + · exact .inr ⟨hs, witness, ha⟩ + · simp [run, hs, hw, ha] at h + · simp [run, hp, hs] at h + +def main (args : List String) : IO UInt32 := do + let [mode, sourcePath, requestPath] := args | do + IO.eprintln "usage: certified-check proof|store SOURCE.ixe REQUEST.json" + return 2 + let bytes ← IO.FS.readBinFile sourcePath + let requestText ← IO.FS.readFile requestPath + let result := do + let request ← readRequest (← Lean.Json.parse requestText) + let parts ← Ixon.deEnvVerifiedLazy bytes + run.{0} mode 6400 parts.env request + match result with + | .error error => IO.eprintln error; return 1 + | .ok () => + IO.println <| (Lean.Json.mkObj [("accepted", Lean.toJson true), ("mode", Lean.toJson mode)]).compress + return 0 + +end Ix.Certified.Command diff --git a/Ix/Certified/Corpus.lean b/Ix/Certified/Corpus.lean new file mode 100644 index 000000000..688c899db --- /dev/null +++ b/Ix/Certified/Corpus.lean @@ -0,0 +1,123 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Fixtures + +namespace Ix.Certified.Corpus + +open Fixtures + +def idType (level : UInt64) : Ixon.Expr := + .leanAll (.sort level) (.leanAll (.var 0) (.var 1)) + +def idBody (level : UInt64) : Ixon.Expr := + .leanLam (.sort level) (.leanLam (.var 0) (.var 0)) + +def polyId (kind : Ix.DefKind) : Ixon.Constant := { + info := .defn { + kind, safety := .safe, lvls := 1, typ := idType 0, value := idBody 0 } + sharing := #[], refs := #[], univs := #[.var 0] +} + +def polyUse (kind : Ix.DefKind) (large : Bool) : Ixon.Constant := { + info := .defn { + kind := .thm, safety := .safe, lvls := 0, typ := idType 0, + value := if large then + .app (.leanLam (idType 1) (idBody 0)) (.ref 0 #[1]) + else .ref 0 #[0] } + sharing := #[], refs := #[(encode (polyId kind)).1], + univs := #[.zero, .succ .zero] +} + +def dependent (n : UInt64) (u : Ixon.Univ) : Ixon.Constant := { + info := .defn { + kind := .thm, safety := .safe, lvls := n, + typ := .leanAll (.sort 0) + (.leanAll (.leanAll (.var 0) (.sort 1)) + (.leanAll (.leanAll (.var 1) (.app (.var 1) (.var 0))) + (.leanAll (.var 2) (.app (.var 2) (.var 0))))), + value := .leanLam (.sort 0) + (.leanLam (.leanAll (.var 0) (.sort 1)) + (.leanLam (.leanAll (.var 1) (.app (.var 1) (.var 0))) + (.leanLam (.var 2) (.app (.var 1) (.var 0))))) } + sharing := #[], refs := #[], univs := #[u, .zero] +} + +-- The declared proposition contains a beta redex. The body is checked +-- against that original proposition through a beta conversion certificate. +def betaStatement : Ixon.Constant := { + info := .defn { + kind := .thm, safety := .safe, lvls := 0, + typ := .app (.leanLam (.sort 0) (.var 0)) (idType 0), + value := idBody 0 } + sharing := #[], refs := #[], univs := #[.zero] +} + +-- ∀ A : Prop, ∀ F : (A → A) → Prop, ∀ f, F f → F (fun x => f x). +-- The supplied proof returns its last argument, so admission needs eta +-- beneath a dependent application and a telescope of products. +def etaStatement : Ixon.Constant := { + info := .defn { + kind := .thm, safety := .safe, lvls := 0, + typ := .leanAll (.sort 0) + (.leanAll (.leanAll (.leanAll (.var 0) (.var 1)) (.sort 0)) + (.leanAll (.leanAll (.var 1) (.var 2)) + (.leanAll (.app (.var 1) (.var 0)) + (.app (.var 2) (.leanLam (.var 3) (.app (.var 2) (.var 0))))))), + value := .leanLam (.sort 0) + (.leanLam (.leanAll (.leanAll (.var 0) (.var 1)) (.sort 0)) + (.leanLam (.leanAll (.var 1) (.var 2)) + (.leanLam (.app (.var 1) (.var 0)) (.var 0)))) } + sharing := #[], refs := #[], univs := #[.zero] +} + +def eliminatorStatement : Ixon.Constant := { + info := .defn { + kind := .thm, safety := .safe, lvls := 0, + typ := .leanAll (.leanAll (.ref 0 #[]) (.sort 0)) + (.leanAll (.ref 0 #[]) (.app (.var 1) (.var 0))), + value := .ref 1 #[0] } + sharing := #[], refs := #[falseObject.1, falseElimObject.1], univs := #[.zero] +} + +structure Case where + name : String + target : Address + blobs : ConstantBlobs + +def one (name : String) (source : Ixon.Constant) + (dependencies : List Ixon.Constant := []) : Case := + let object := encode source + ⟨name, object.1, prelude ++ dependencies.map encode ++ [object]⟩ + +def positive : List Case := [ + one "identity" identity, + one "dependent-polymorphic" (dependent 1 (.var 0)), + one "dependent-Prop" (dependent 0 .zero), + one "dependent-Type" (dependent 0 (.succ .zero)), + one "dependent-Type1" (dependent 0 (.succ (.succ .zero))), + one "definition-at-Prop" (polyUse .defn false) [polyId .defn], + one "definition-at-Type" (polyUse .defn true) [polyId .defn], + one "theorem-at-Prop" (polyUse .thm false) [polyId .thm], + one "opaque-at-Type" (polyUse .opaq true) [polyId .opaq], + one "beta-statement" betaStatement, + one "eta-statement" etaStatement, + one "False-eliminator" eliminatorStatement +] + +#guard positive.all fun c => accepted c.blobs c.target + +/-- Syntactic exclusions measured separately from failed witness generation. +The selected profile never enables literals or linear binder flags. -/ +def declined : List Case := [ + one "linear-binder-profile" linearIdentity, + one "literal-profile" { identity with info := .defn { + kind := .thm, safety := .safe, lvls := 0, + typ := idType 0, value := .nat 0 } } +] + +#guard declined.all fun c => (prepare? 300 profile c.target c.blobs).isNone + +end Ix.Certified.Corpus diff --git a/Ix/Certified/Envelope.lean b/Ix/Certified/Envelope.lean new file mode 100644 index 000000000..c88cb93e9 --- /dev/null +++ b/Ix/Certified/Envelope.lean @@ -0,0 +1,92 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Trees +import Ix.Claim + +/-! Versioned public claims for the certified source checker. This envelope +binds the original Ix claim, primitive addresses, modeled logical policy and +axiom-use root. The thin-frontier convention is distinct from the legacy +whole-environment convention. A backend still has to bind its actual program +and permitted keys to this source program version. -/ + +namespace Ix.Certified + +structure Protocol where + format : UInt64 := 1 + codec : UInt64 := 1 + checker : UInt64 := 1 + policy : UInt64 := 1 + aggregation : UInt64 := 1 + deriving DecidableEq + +/-- Checker version 2 includes checked model companions for mutual and +nested declarations. Older checker identities do not select this program. -/ +def Protocol.current : Protocol := { checker := 2 } + +structure Envelope where + protocol : Protocol + profile : Profile + claim : Ix.Claim + logicalAxioms : Option Address + +def envelopeMagic : ByteArray := "IX-CERTIFIED-CLAIM".toUTF8 ++ ⟨#[0]⟩ + +def putEnvelope (envelope : Envelope) : Ixon.PutM Unit := do + Ixon.putBytes envelopeMagic + Ixon.putTag0 ⟨envelope.protocol.format⟩ + Ixon.putTag0 ⟨envelope.protocol.codec⟩ + Ixon.putTag0 ⟨envelope.protocol.checker⟩ + Ixon.putTag0 ⟨envelope.protocol.policy⟩ + Ixon.putTag0 ⟨envelope.protocol.aggregation⟩ + Ixon.Serialize.put envelope.profile.falseType + Ixon.Serialize.put envelope.profile.falseElim + Ix.Claim.putOptAddr envelope.profile.natType + Ix.Claim.put envelope.claim + Ix.Claim.putOptAddr envelope.logicalAxioms + +def envelopeBytes (envelope : Envelope) : ByteArray := Ixon.runPut (putEnvelope envelope) + +def getEnvelope : Ixon.GetM Envelope := do + if (← Ixon.getBytes envelopeMagic.size) != envelopeMagic then throw "invalid certified claim magic" + let format := (← Ixon.getTag0).size + let codec := (← Ixon.getTag0).size + let checker := (← Ixon.getTag0).size + let policy := (← Ixon.getTag0).size + let aggregation := (← Ixon.getTag0).size + let falseType ← Ixon.Serialize.get + let falseElim ← Ixon.Serialize.get + let natType ← Ix.Claim.getOptAddr + let claim ← Ix.Claim.get + let logicalAxioms ← Ix.Claim.getOptAddr + return ⟨⟨format, codec, checker, policy, aggregation⟩, ⟨falseType, falseElim, natType⟩, claim, logicalAxioms⟩ + +structure EnvelopeReading (address : Address) (bytes : ByteArray) where + envelope : Envelope + addressSize : address.hash.size = 32 + authenticated : Address.blake3 bytes = address + parsing : Ixon.runGetExact getEnvelope bytes = .ok envelope + canonical : envelopeBytes envelope = bytes + supported : envelope.protocol = Protocol.current + +def readEnvelope? (fuel : Nat) (address : Address) (bytes : ByteArray) : + Option (EnvelopeReading address bytes) := + if bytes.size > fuel then none else + if ha : address.hash.size = 32 ∧ Address.blake3 bytes = address then + match hp : Ixon.runGetExact getEnvelope bytes with + | .error _ => none + | .ok envelope => + if hc : envelopeBytes envelope = bytes then + if hs : envelope.protocol = Protocol.current then some ⟨envelope, ha.1, ha.2, hp, hc, hs⟩ + else none + else none + else none + +/-- Exact parsing fixes the complete public claim and profile. Semantic or +expression equality is never used to recover the authenticated bytes. -/ +theorem EnvelopeReading.unique {a b : EnvelopeReading address bytes} : a.envelope = b.envelope := + Except.ok.inj (a.parsing.symm.trans b.parsing) + +end Ix.Certified diff --git a/Ix/Certified/Fixtures.lean b/Ix/Certified/Fixtures.lean new file mode 100644 index 000000000..e7306ffd3 --- /dev/null +++ b/Ix/Certified/Fixtures.lean @@ -0,0 +1,141 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Bytes +import Ix.Theory.Certificate.Build + +namespace Ix.Certified.Fixtures + +open Ix.Theory Ix.Theory.Certified + +def encode (source : Ixon.Constant) : Address × ByteArray := + let bytes := Ixon.serConstant source + (Address.blake3 bytes, bytes) + +def falseBlock : Ixon.Constant := { + info := .muts #[.indc { + isUnsafe := false, lvls := 0, params := 0, indices := 0, + typ := .sort 0, ctors := #[] + }] + sharing := #[] + refs := #[] + univs := #[.zero] +} + +def falseBlockObject := encode falseBlock + +def falseProjection : Ixon.Constant := + ⟨.iPrj ⟨0, falseBlockObject.1⟩, #[], #[], #[]⟩ + +def falseObject := encode falseProjection + +def falseElim : Ixon.Constant := { + info := .recr { + k := false, isUnsafe := false, lvls := 1, params := 0, indices := 0, + motives := 1, minors := 0, + typ := .leanAll (.leanAll (.ref 0 #[]) (.sort 0)) + (.leanAll (.ref 0 #[]) (.app (.var 1) (.var 0))), + rules := #[] + } + sharing := #[] + refs := #[falseObject.1] + univs := #[.var 0] +} + +def falseElimObject := encode falseElim + +def profile : Profile := ⟨falseObject.1, falseElimObject.1, none⟩ +def prelude : ConstantBlobs := [falseBlockObject, falseObject, falseElimObject] + +def identity : Ixon.Constant := { + info := .defn { + kind := .thm, safety := .safe, lvls := 0, + typ := .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), + value := .leanLam (.sort 0) (.leanLam (.var 0) (.var 0)) + } + sharing := #[] + refs := #[] + univs := #[.zero] +} + +def identityObject := encode identity +def identityBlobs : ConstantBlobs := prelude ++ [identityObject] + +def witness? (blobs : ConstantBlobs) (target : Address) : Option (ProofWitness Address) := do + let prepared ← prepare? 300 profile target blobs + Ix.Theory.Certificate.proofWitness? 300 prepared.signature prepared.input + +def accepted (blobs : ConstantBlobs) (target : Address) : Bool := + (witness? blobs target).any (acceptsSerialized.{0} 300 profile target blobs) + +#guard accepted identityBlobs identityObject.1 + +-- A new valid hash cannot license trailing data outside the constant grammar. +def trailingIdentity : Address × ByteArray := + let bytes := identityObject.2.push 0 + (Address.blake3 bytes, bytes) +#guard (prepare? 300 profile trailingIdentity.1 (prelude ++ [trailingIdentity])).isNone + +-- Changed bytes under an old address fail authentication. +#guard (prepare? 300 profile identityObject.1 + (prelude ++ [(identityObject.1, identityObject.2.push 0)])).isNone + +-- Duplicate object addresses are not silently overwritten. +#guard (prepare? 300 profile identityObject.1 (identityBlobs ++ [identityObject])).isNone + +def linearIdentity : Ixon.Constant := + { identity with info := .defn { + kind := .thm, safety := .safe, lvls := 0, + typ := .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), + value := .lam .linear (.sort 0) (.leanLam (.var 0) (.var 0)) + } } + +def linearIdentityObject := encode linearIdentity +#guard (prepare? 300 profile linearIdentityObject.1 + (prelude ++ [linearIdentityObject])).isNone + +def wrongTable : Ixon.Constant := { identity with univs := #[] } +def wrongTableObject := encode wrongTable +#guard (prepare? 300 profile wrongTableObject.1 (prelude ++ [wrongTableObject])).isNone + +def cyclicSharing : Ixon.Constant := { + identity with + info := .defn { + kind := .thm, safety := .safe, lvls := 0, + typ := .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), value := .share 0 } + sharing := #[.share 0] +} +def cyclicSharingObject := encode cyclicSharing +#guard (prepare? 30 profile cyclicSharingObject.1 (prelude ++ [cyclicSharingObject])).isNone + +def axiomIdentity : Ixon.Constant := { + identity with + info := .axio { + isUnsafe := false, lvls := 0, + typ := .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)) } +} +def axiomIdentityObject := encode axiomIdentity + +-- Force an untrusted proof witness through the actual acceptance gate. This +-- is a policy rejection, not merely a failure of the suggestion producer. +def axiomRejected : Bool := + match witness? identityBlobs identityObject.1 with + | none => false + | some witness => + let forged := { witness with declarations := witness.declarations.map fun declaration => + match declaration with + | .definition definition => .definition { definition with ref := .member axiomIdentityObject.1 0 } + | .ordinary block => .ordinary block + | .standard witness => .standard witness + | .quotient witness => .quotient witness + | .structure witness => .structure witness + | .natural witness => .natural witness + | .modeled witness => .modeled witness } + !acceptsSerialized.{0} 300 profile axiomIdentityObject.1 + (prelude ++ [axiomIdentityObject]) forged + +#guard axiomRejected + +end Ix.Certified.Fixtures diff --git a/Ix/Certified/Ingress.lean b/Ix/Certified/Ingress.lean new file mode 100644 index 000000000..8e799407f --- /dev/null +++ b/Ix/Certified/Ingress.lean @@ -0,0 +1,315 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Store + +/-! Certified lazy reads from the actual Ixon environment. Only selected +addresses are visited. Materialized source caches and kernel judgment caches +cannot replace authenticated bytes. The reusable cache stores decoded data; +each hit also compares the exact current source bytes. -/ + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v + +/-- A constant window must be wholly inside its backing buffer. The cached +materialization in `LazyConstant` is intentionally not an input to this read. -/ +def constantBytes? (source : Ixon.Env) (address : Address) : Option ByteArray := do + let entry ← source.consts.get? address + if entry.off ≤ entry.buf.size ∧ entry.len ≤ entry.buf.size - entry.off then + some entry.rawBytes + else none + +abbrev DecodedNatural (address : Address) (bytes : ByteArray) := + { value : Nat // + address.hash.size = 32 ∧ Address.blake3 bytes = address ∧ + Nat.fromBytesLE bytes.data = value ∧ ByteArray.mk value.toBytesLE = bytes } + +theorem decodeObject_complete {address : Address} {bytes : ByteArray} + (value : DecodedObject address bytes) : decodeObject? address bytes = some value := by + rcases value with ⟨value, hs, hh, hp, hc⟩ + unfold decodeObject? + split + · rename_i auth + have he : canonicalObject? address bytes auth (Ixon.runGetExact Ixon.getConstant bytes) rfl = + canonicalObject? address bytes auth (.ok value) hp := by congr 1 + rw [he] + simp [canonicalObject?, hc] + · rename_i h + exact False.elim (h ⟨hs, hh⟩) + +theorem decodeNatural_complete {address : Address} {bytes : ByteArray} + (value : DecodedNatural address bytes) : decodeNatural? address bytes = some value := by + rcases value with ⟨value, hs, hh, hp, hc⟩ + simp [decodeNatural?, hs, hh, hp, hc] + +structure CachedObject where + address : Address + bytes : ByteArray + decoded : DecodedObject address bytes + +structure CachedNatural where + address : Address + bytes : ByteArray + decoded : DecodedNatural address bytes + +/-- The public driver starts with this empty cache. Entries contain only +canonical, authenticated data; no typing, conversion or admission verdicts. -/ +structure InputCache where + objects : List CachedObject := [] + naturals : List CachedNatural := [] + hits : Nat := 0 + misses : Nat := 0 + +namespace InputCache + +def object? (address : Address) (bytes : ByteArray) : + List CachedObject → Option (DecodedObject address bytes) + | [] => none + | entry :: rest => + if ha : entry.address = address then + if hb : entry.bytes = bytes then some (by simpa only [← ha, ← hb] using entry.decoded) + else object? address bytes rest + else object? address bytes rest + +def natural? (address : Address) (bytes : ByteArray) : + List CachedNatural → Option (DecodedNatural address bytes) + | [] => none + | entry :: rest => + if ha : entry.address = address then + if hb : entry.bytes = bytes then some (by simpa only [← ha, ← hb] using entry.decoded) + else natural? address bytes rest + else natural? address bytes rest + +end InputCache + +structure SourceObject (source : Ixon.Env) extends CachedObject where + fromSource : constantBytes? source address = some bytes + +structure SourceNatural (source : Ixon.Env) extends CachedNatural where + fromSource : source.getBlob? address = some bytes + +abbrev Read (_source : Ixon.Env) := StateT InputCache Option + +def readObject? (source : Ixon.Env) (address : Address) : Read source (SourceObject source) := fun cache => + match hs : constantBytes? source address with + | none => none + | some bytes => + match InputCache.object? address bytes cache.objects with + | some decoded => some (⟨⟨address, bytes, decoded⟩, hs⟩, { cache with hits := cache.hits + 1 }) + | none => do + let decoded ← decodeObject? address bytes + let entry : CachedObject := ⟨address, bytes, decoded⟩ + return (⟨entry, hs⟩, { cache with objects := entry :: cache.objects, misses := cache.misses + 1 }) + +def readNatural? (source : Ixon.Env) (address : Address) : Read source (SourceNatural source) := fun cache => + match hs : source.getBlob? address with + | none => none + | some bytes => + match InputCache.natural? address bytes cache.naturals with + | some decoded => some (⟨⟨address, bytes, decoded⟩, hs⟩, { cache with hits := cache.hits + 1 }) + | none => do + let decoded ← decodeNatural? address bytes + let entry : CachedNatural := ⟨address, bytes, decoded⟩ + return (⟨entry, hs⟩, { cache with naturals := entry :: cache.naturals, misses := cache.misses + 1 }) + +/-- An untrusted finite selection of source addresses. It must include all +source groups and raw blobs required by the independently checked witness. -/ +structure InputSelection where + objects : List Address + naturals : List Address := [] + +structure SourceSnapshot (source : Ixon.Env) where + objects : List (SourceObject source) + naturals : List (SourceNatural source) + +namespace SourceSnapshot + +def blobs (snapshot : SourceSnapshot source) : ConstantBlobs := + snapshot.objects.map fun entry => (entry.address, entry.bytes) + +def literalBlobs (snapshot : SourceSnapshot source) : ConstantBlobs := + snapshot.naturals.map fun entry => (entry.address, entry.bytes) + +def decodedObjects (snapshot : SourceSnapshot source) : Objects := + snapshot.objects.map fun entry => (entry.address, entry.decoded.val) + +def decodedNaturals (snapshot : SourceSnapshot source) : Naturals := + snapshot.naturals.map fun entry => (entry.address, entry.decoded.val) + +theorem objects_decode (snapshot : SourceSnapshot source) : + decodeObjects? snapshot.blobs = some snapshot.decodedObjects := by + rcases snapshot with ⟨objects, naturals⟩ + simp only [blobs, decodedObjects, decodeObjects?] + induction objects with + | nil => rfl + | cons entry rest ih => + dsimp only [bind, pure] at ih + simp only [List.map_cons, List.mapM_cons, decodeObject_complete entry.decoded, + bind, Option.bind_some, ih, pure] + +theorem naturals_decode (snapshot : SourceSnapshot source) : + decodeNaturals? snapshot.literalBlobs = some snapshot.decodedNaturals := by + rcases snapshot with ⟨objects, naturals⟩ + simp only [literalBlobs, decodedNaturals, decodeNaturals?] + induction naturals with + | nil => rfl + | cons entry rest ih => + dsimp only [bind, pure] at ih + simp only [List.map_cons, List.mapM_cons, decodeNatural_complete entry.decoded, + bind, Option.bind_some, ih, pure] + +/-- Reusing decoded data saves hashing/parsing. Scope, source metadata, +primitive selection, dependency order and semantic validation still run. -/ +def prepare? (fuel : Nat) (profile : Profile) (target : Address) + (snapshot : SourceSnapshot source) : Option PreparedInput := do + if !((snapshot.blobs ++ snapshot.literalBlobs).map Prod.fst).Nodup then none else do + let signature ← readSignature? profile snapshot.decodedObjects + let input ← readProofInput? fuel snapshot.decodedObjects target snapshot.decodedNaturals + return ⟨signature, input⟩ + +theorem prepare_eq (fuel : Nat) (profile : Profile) (target : Address) + (snapshot : SourceSnapshot source) : + Ix.Certified.prepare? fuel profile target snapshot.blobs snapshot.literalBlobs = + snapshot.prepare? fuel profile target := by + simp only [Ix.Certified.prepare?, prepare?, snapshot.objects_decode, snapshot.naturals_decode, + bind, Option.bind_some] + +/-- Each byte string consumed by the cached checker comes from the current +source environment, even when that address occurred in an earlier request. -/ +theorem objects_from_source (snapshot : SourceSnapshot source) {address : Address} {bytes : ByteArray} + (h : (address, bytes) ∈ snapshot.blobs) : constantBytes? source address = some bytes := by + obtain ⟨entry, _, he⟩ := List.mem_map.mp h + cases he + exact entry.fromSource + +theorem naturals_from_source (snapshot : SourceSnapshot source) {address : Address} {bytes : ByteArray} + (h : (address, bytes) ∈ snapshot.literalBlobs) : source.getBlob? address = some bytes := by + obtain ⟨entry, _, he⟩ := List.mem_map.mp h + cases he + exact entry.fromSource + +end SourceSnapshot + +/-- Failure returns no partially loaded snapshot or semantic verdict. -/ +def readSnapshot? (fuel : Nat) (source : Ixon.Env) (selection : InputSelection) : + Read source (SourceSnapshot source) := do + if selection.objects.length + selection.naturals.length > fuel then failure else do + let objects ← selection.objects.mapM (readObject? source) + let naturals ← selection.naturals.mapM (readNatural? source) + return ⟨objects, naturals⟩ + +/-- A receipt is produced only after complete checking against the snapshot. +All semantic fields are computed by the validator; they are not input data. -/ +structure SourceReceipt (source : Ixon.Env) (fuel : Nat) (profile : Profile) (target : Address) + (witness : ProofWitness Address) where + snapshot : SourceSnapshot source + prepared : PreparedInput + preparation : snapshot.prepare? fuel profile target = some prepared + proof : CheckedProof.{0,v} prepared.signature prepared.input + checked : checkProofCertified fuel prepared.signature prepared.input witness = some proof + +def checkSource? (fuel : Nat) (source : Ixon.Env) (profile : Profile) (target : Address) + (selection : InputSelection) (witness : ProofWitness Address) : + Read source (SourceReceipt.{v} source fuel profile target witness) := do + let snapshot ← readSnapshot? fuel source selection + match hp : snapshot.prepare? fuel profile target with + | none => failure + | some prepared => + match hc : checkProofCertified fuel prepared.signature prepared.input witness with + | none => failure + | some proof => return ⟨snapshot, prepared, hp, proof, hc⟩ + +namespace SourceReceipt + +theorem serialized (receipt : SourceReceipt.{v} source fuel profile target witness) : + acceptsSerialized.{v} fuel profile target receipt.snapshot.blobs witness receipt.snapshot.literalBlobs = true := by + have hp := receipt.snapshot.prepare_eq fuel profile target + rw [receipt.preparation] at hp + simp only [acceptsSerialized, hp, acceptsCertified, receipt.checked, Option.isSome_some] + +theorem has_model (receipt : SourceReceipt.{v} source fuel profile target witness) + (V : Type v) [SetTheory V] (levels : List Nat) (env : Nat → V) : + ∃ constants : Assignment Address V, + receipt.prepared.signature.Compatible receipt.proof.environment.entries constants ∧ + WellDenoted constants levels env receipt.proof.proof.val ∧ + WellDenoted constants levels env receipt.proof.proposition.val ∧ + interp constants levels env receipt.proof.proof.val ∈ˢ + interp constants levels env receipt.proof.proposition.val := by + have ha : acceptsCertified.{0,v} fuel receipt.prepared.signature receipt.prepared.input witness = true := by + simp only [acceptsCertified, receipt.checked, Option.isSome_some] + obtain ⟨result, hr, constants, hM, hW, hP, hm⟩ := accepted_has_model ha V levels env + have he : result = receipt.proof := Option.some.inj (hr.symm.trans receipt.checked) + subst result + exact ⟨constants, hM, hW, hP, hm⟩ + +end SourceReceipt + + +namespace SourceSnapshot + +def prepareStore? (fuel : Nat) (profile : Profile) (subjects : List Address) + (snapshot : SourceSnapshot source) : Option PreparedStore := do + if !((snapshot.blobs ++ snapshot.literalBlobs).map Prod.fst).Nodup then none else + prepareStoreObjects? fuel profile subjects snapshot.decodedObjects snapshot.decodedNaturals + +theorem prepareStore_eq (fuel : Nat) (profile : Profile) (subjects : List Address) + (snapshot : SourceSnapshot source) : + Ix.Certified.prepareStore? fuel profile subjects snapshot.blobs snapshot.literalBlobs = + snapshot.prepareStore? fuel profile subjects := by + simp only [Ix.Certified.prepareStore?, prepareStore?, snapshot.objects_decode, snapshot.naturals_decode, + bind, Option.bind_some] + +end SourceSnapshot + +structure StoreReceipt (source : Ixon.Env) (fuel : Nat) (profile : Profile) (subjects : List Address) + (witness : List (DeclarationWitness Address)) where + snapshot : SourceSnapshot source + prepared : PreparedStore + preparation : snapshot.prepareStore? fuel profile subjects = some prepared + result : CheckedStore.{0,v} prepared.signature prepared.store prepared.targets + checked : checkStoreCertified fuel prepared.signature prepared.store prepared.targets witness = some result + +def checkSourceStore? (fuel : Nat) (source : Ixon.Env) (profile : Profile) (subjects : List Address) + (selection : InputSelection) (witness : List (DeclarationWitness Address)) : + Read source (StoreReceipt.{v} source fuel profile subjects witness) := do + let snapshot ← readSnapshot? fuel source selection + match hp : snapshot.prepareStore? fuel profile subjects with + | none => failure + | some prepared => + match hc : checkStoreCertified fuel prepared.signature prepared.store prepared.targets witness with + | none => failure + | some result => return ⟨snapshot, prepared, hp, result, hc⟩ + +namespace StoreReceipt + +theorem serialized (receipt : StoreReceipt.{v} source fuel profile subjects witness) : + acceptsSerializedStore.{v} fuel profile subjects receipt.snapshot.blobs witness receipt.snapshot.literalBlobs = true := by + have hp := receipt.snapshot.prepareStore_eq fuel profile subjects + rw [receipt.preparation] at hp + simp only [acceptsSerializedStore, hp, acceptsStoreCertified, receipt.checked, Option.isSome_some] + +theorem has_model (receipt : StoreReceipt.{v} source fuel profile subjects witness) + (V : Type v) [SetTheory V] : + ∃ constants : Assignment Address V, + receipt.prepared.signature.Compatible receipt.result.environment.entries constants ∧ + ∀ r ∈ receipt.prepared.targets, ∃ entry, receipt.result.environment.entries r = some entry ∧ + EntrySource receipt.prepared.signature receipt.prepared.store r entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env : Nat → V, + WellDenoted constants levels env entry.type ∧ + constants r levels ∈ˢ interp constants levels env entry.type := by + have ha : acceptsStoreCertified.{0,v} fuel receipt.prepared.signature receipt.prepared.store + receipt.prepared.targets witness = true := by + simp only [acceptsStoreCertified, receipt.checked, Option.isSome_some] + obtain ⟨result, hr, hM⟩ := accepted_store_has_model ha V + have he : result = receipt.result := Option.some.inj (hr.symm.trans receipt.checked) + subst result + exact hM + +end StoreReceipt + +end Ix.Certified diff --git a/Ix/Certified/Ixon.lean b/Ix/Certified/Ixon.lean new file mode 100644 index 000000000..303d1f328 --- /dev/null +++ b/Ix/Certified/Ixon.lean @@ -0,0 +1,225 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Ixon +import Ix.Theory.Certified + +/-! +# Ixon input adapter for the certified profile + +This adapter checks table indices, projection ownership/kinds, ordinary Lean +binder modes, and bounded sharing expansion. It preserves block/member +positions and constructor metadata, including checked constructor positions. +Natural literals use a separately authenticated canonical blob table. +Lets and strings are not enabled here. Semantic admission independently +restricts inductive shapes. Byte authentication and the public claim binding +are separate from this structural adapter. +-/ + +namespace Ix.Certified + +open Ix.Theory +open Ix.Theory.Certified + +instance addressDecidableEq : DecidableEq Address := fun a b => + if h : a.hash = b.hash then + .isTrue (by cases a; cases b; cases h; rfl) + else .isFalse (fun he => h (congrArg Address.hash he)) + +def lookup (entries : List (Address × α)) (address : Address) : Option α := + match entries with + | [] => none + | (key, value) :: rest => if address = key then some value else lookup rest address + +theorem lookup_isSome (entries : List (Address × α)) (address : Address) : + (lookup entries address).isSome ↔ address ∈ entries.map Prod.fst := by + induction entries with + | nil => simp [lookup] + | cons entry rest ih => + obtain ⟨key, value⟩ := entry + by_cases h : address = key <;> simp_all [lookup] + +def readLevel : Ixon.Univ → VLevel + | .zero => .zero + | .succ u => .succ (readLevel u) + | .max u v => .max (readLevel u) (readLevel v) + | .imax u v => .imax (readLevel u) (readLevel v) + | .var i => .param i.toNat + +abbrev Objects := List (Address × Ixon.Constant) +abbrev Naturals := List (Address × Nat) + +def mutMember? (objects : Objects) (block : Address) (index : UInt64) : Option Ixon.MutConst := do + let source ← lookup objects block + let .muts members := source.info | none + members[index.toNat]? + +/-- Projection wrappers must refer to the matching source member kind. -/ +def resolveReference? (objects : Objects) (address : Address) : Option (ConstRef Address) := do + let source ← lookup objects address + match source.info with + | .defn _ | .recr _ | .axio _ | .quot _ => some (.member address 0) + | .iPrj projection => do + let .indc _ ← mutMember? objects projection.block projection.idx | none + return .member projection.block projection.idx.toNat + | .rPrj projection => do + let .recr _ ← mutMember? objects projection.block projection.idx | none + return .member projection.block projection.idx.toNat + | .dPrj projection => do + let .defn _ ← mutMember? objects projection.block projection.idx | none + return .member projection.block projection.idx.toNat + | .cPrj projection => do + let .indc family ← mutMember? objects projection.block projection.idx | none + let _ ← family.ctors[projection.cidx.toNat]? + return .ctor projection.block projection.idx.toNat projection.cidx.toNat + | .muts _ => none + +def readLevels? (source : Ixon.Constant) (indices : Array UInt64) : Option (List VLevel) := + indices.toList.mapM fun index => (source.univs[index.toNat]?).map readLevel + +def readExpr? (fuel : Nat) (objects : Objects) (naturals : Naturals) (block : Address) (source : Ixon.Constant) : + Ixon.Expr → Option (VExpr Address) := + match fuel with + | 0 => fun _ => none + | fuel + 1 => fun expression => + match expression with + | .var index => some (.bvar index.toNat) + | .sort index => (source.univs[index.toNat]?).map (VExpr.sort ∘ readLevel) + | .ref index levels => do + let address ← source.refs[index.toNat]? + let reference ← resolveReference? objects address + let levels ← readLevels? source levels + return .const reference levels + | .recur index levels => do + let levels ← readLevels? source levels + return .const (.member block index.toNat) levels + | .app f a => do + let f ← readExpr? fuel objects naturals block source f + let a ← readExpr? fuel objects naturals block source a + return .app f a + | .lam .many A b => do + let A ← readExpr? fuel objects naturals block source A + let b ← readExpr? fuel objects naturals block source b + return .lam A b + | .all .many .shared A B => do + let A ← readExpr? fuel objects naturals block source A + let B ← readExpr? fuel objects naturals block source B + return .forallE A B + | .prj owner field value => do + let address ← source.refs[owner.toNat]? + let ownerSource ← lookup objects address + let .iPrj _ := ownerSource.info | none + let reference ← resolveReference? objects address + let value ← readExpr? fuel objects naturals block source value + return .proj reference field.toNat value + | .nat index => do + let address ← source.refs[index.toNat]? + return .natLit (← lookup naturals address) + | .share index => do + let shared ← source.sharing[index.toNat]? + readExpr? fuel objects naturals block source shared + | _ => none + +def readSafety : Ix.DefinitionSafety → Safety + | .safe => .safe + | .unsaf => .unsafe + | .part => .partial + +def readDefKind : Ix.DefKind → Ix.Theory.DefKind + | .defn => .definition + | .thm => .theorem + | .opaq => .opaque + +def readQuotKind : Ix.QuotKind → Ix.Theory.QuotKind + | .type => .type + | .ctor => .ctor + | .lift => .lift + | .ind => .ind + +def readDefinition? (fuel : Nat) (objects : Objects) (naturals : Naturals) (block : Address) + (source : Ixon.Constant) (definition : Ixon.Definition) : Option (Const Address) := do + let type ← readExpr? fuel objects naturals block source definition.typ + let body ← readExpr? fuel objects naturals block source definition.value + return .defn definition.lvls.toNat (readDefKind definition.kind) type body + (readSafety definition.safety) + +def readRecursor? (fuel : Nat) (objects : Objects) (naturals : Naturals) (block : Address) + (source : Ixon.Constant) (recursor : Ixon.Recursor) : Option (Const Address) := do + let type ← readExpr? fuel objects naturals block source recursor.typ + let rules ← recursor.rules.toList.mapM fun rule => do + let rhs ← readExpr? fuel objects naturals block source rule.rhs + return (⟨rule.fields.toNat, rhs⟩ : RecRule Address) + return .recursor recursor.lvls.toNat recursor.params.toNat recursor.indices.toNat + recursor.motives.toNat recursor.minors.toNat type rules recursor.k + (if recursor.isUnsafe then .unsafe else .safe) + +def readInductive? (fuel : Nat) (objects : Objects) (naturals : Naturals) (block : Address) + (source : Ixon.Constant) (family : Ixon.Inductive) : Option (Const Address) := do + let type ← readExpr? fuel objects naturals block source family.typ + let constructors ← family.ctors.toList.zipIdx.mapM fun (ctor, index) => do + if ctor.cidx.toNat != index then none else do + let type ← readExpr? fuel objects naturals block source ctor.typ + return (⟨ctor.lvls.toNat, ctor.params.toNat, ctor.fields.toNat, type, + if ctor.isUnsafe then .unsafe else .safe⟩ : Ctor Address) + return .induct family.lvls.toNat family.params.toNat family.indices.toNat + type constructors (if family.isUnsafe then .unsafe else .safe) + +def readMutualMember? (fuel : Nat) (objects : Objects) (naturals : Naturals) (block : Address) + (source : Ixon.Constant) : Ixon.MutConst → Option (Const Address) + | .defn definition => readDefinition? fuel objects naturals block source definition + | .recr recursor => readRecursor? fuel objects naturals block source recursor + | .indc family => readInductive? fuel objects naturals block source family + +def readBlock? (fuel : Nat) (objects : Objects) (naturals : Naturals) (block : Address) + (source : Ixon.Constant) : Option (Block Address) := + match source.info with + | .defn definition => do return ⟨[← readDefinition? fuel objects naturals block source definition]⟩ + | .recr recursor => do return ⟨[← readRecursor? fuel objects naturals block source recursor]⟩ + | .axio declaration => do + let type ← readExpr? fuel objects naturals block source declaration.typ + return ⟨[.axiom declaration.lvls.toNat type (if declaration.isUnsafe then .unsafe else .safe)]⟩ + | .quot quotient => do + let type ← readExpr? fuel objects naturals block source quotient.typ + return ⟨[.quot (readQuotKind quotient.kind) quotient.lvls.toNat type]⟩ + | .muts members => do + return ⟨← members.toList.mapM (readMutualMember? fuel objects naturals block source)⟩ + | _ => none + +def isProjection : Ixon.ConstantInfo → Bool + | .iPrj _ | .rPrj _ | .dPrj _ | .cPrj _ => true + | _ => false + +def readBlocks? (fuel : Nat) (objects : Objects) (naturals : Naturals) : + Objects → Option (List (Address × Block Address)) + | [] => some [] + | (address, source) :: rest => do + if isProjection source.info then + let _ ← resolveReference? objects address + readBlocks? fuel objects naturals rest + else + let block ← readBlock? fuel objects naturals address source + let rest ← readBlocks? fuel objects naturals rest + return (address, block) :: rest + +def readStore? (fuel : Nat) (objects : Objects) (naturals : Naturals := []) : Option (Store Address) := do + if (objects.map Prod.fst).Nodup then + let blocks ← readBlocks? fuel objects naturals objects + if h : (blocks.map Prod.fst).Nodup then + return ⟨blocks.map Prod.fst, h, lookup blocks, lookup_isSome blocks⟩ + else none + else none + +def readProofInput? (fuel : Nat) (objects : Objects) (target : Address) + (naturals : Naturals := []) : + Option (ProofInput Address) := do + let store ← readStore? fuel objects naturals + let reference ← resolveReference? objects target + let declaration ← store.lookup reference + if declaration.uvars ≤ fuel then + return ⟨store, declaration.uvars, .const reference (VLevel.params declaration.uvars), + declaration.type⟩ + else none + +end Ix.Certified diff --git a/Ix/Certified/Main.lean b/Ix/Certified/Main.lean new file mode 100644 index 000000000..0570b7cec --- /dev/null +++ b/Ix/Certified/Main.lean @@ -0,0 +1,8 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Command + +def main := Ix.Certified.Command.main diff --git a/Ix/Certified/ModelHints.lean b/Ix/Certified/ModelHints.lean new file mode 100644 index 000000000..4d65dec82 --- /dev/null +++ b/Ix/Certified/ModelHints.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Bytes +import Ix.Theory.Certificate.Modeled + +/-! Optional untrusted model-package hints refer to actual stored objects. +No mathematical declaration is imported from JSON: model definitions and +equation proofs come from the selected authenticated source store and are +admitted before the original block by the ordinary certified checker. -/ + +namespace Ix.Certified + +open Ix.Theory + +structure ModelProofHint where + equality : Address + reflexivity : Address + eliminator : Address + proof : Address + +structure ModelRuleHints where + owner : Address + proofs : List (Option ModelProofHint) + +structure ModelHint where + source : Address + recursors : List Address + targets : List Address + proofs : List ModelRuleHints := [] + +def modelCandidate? (objects : Objects) (store : Store Address) (hint : ModelHint) : + Option (Certificate.Modeled.Candidate Address) := do + let recursors ← hint.recursors.mapM (resolveReference? objects) + let targets ← hint.targets.mapM (resolveReference? objects) + let proofs ← hint.proofs.mapM fun rules => do + let owner ← resolveReference? objects rules.owner + let universes ← store.uvars owner + let proofs ← rules.proofs.mapM fun proof => proof.mapM fun proof => do + let equality ← resolveReference? objects proof.equality + let reflexivity ← resolveReference? objects proof.reflexivity + let eliminator ← resolveReference? objects proof.eliminator + let ref ← resolveReference? objects proof.proof + return (⟨equality, reflexivity, eliminator, + .const ref ((List.range universes).map VLevel.param)⟩ : Certificate.Modeled.ProofHint Address) + return (owner, proofs) + return ⟨hint.source, recursors, targets, proofs⟩ + +def modelCandidates? (objects : Objects) (store : Store Address) (hints : List ModelHint) : + Option (List (Certificate.Modeled.Candidate Address)) := hints.mapM (modelCandidate? objects store) + +namespace ModelHint + +def address (value : String) : Except String Address := + match Address.fromString value with + | none => .error "expected a 32-byte hexadecimal model address" + | some address => .ok address + +def readProof (json : Lean.Json) : Except String ModelProofHint := do + return ⟨← address (← json.getObjValAs? String "equality"), + ← address (← json.getObjValAs? String "reflexivity"), + ← address (← json.getObjValAs? String "eliminator"), + ← address (← json.getObjValAs? String "proof")⟩ + +def readRules (json : Lean.Json) : Except String ModelRuleHints := do + let owner ← address (← json.getObjValAs? String "owner") + let values ← json.getObjValAs? (List (Option Lean.Json)) "proofs" + let proofs ← values.mapM (Option.mapM readProof) + return ⟨owner, proofs⟩ + +def read (json : Lean.Json) : Except String ModelHint := do + let source ← address (← json.getObjValAs? String "source") + let recursors ← (← json.getObjValAs? (List String) "recursors").mapM address + let targets ← (← json.getObjValAs? (List String) "targets").mapM address + let proofs ← match json.getObjVal? "proofs" with + | .error _ => pure [] + | .ok values => (← values.getArr?).toList.mapM readRules + return ⟨source, recursors, targets, proofs⟩ + +def readOptional (json : Lean.Json) : Except String (List ModelHint) := do + match json.getObjVal? "models" with + | .error _ => pure [] + | .ok models => (← models.getArr?).toList.mapM read + +def proofJson (hint : ModelProofHint) : Lean.Json := Lean.Json.mkObj [ + ("equality", Lean.toJson (hexOfBytes hint.equality.hash)), + ("reflexivity", Lean.toJson (hexOfBytes hint.reflexivity.hash)), + ("eliminator", Lean.toJson (hexOfBytes hint.eliminator.hash)), + ("proof", Lean.toJson (hexOfBytes hint.proof.hash))] + +def rulesJson (hint : ModelRuleHints) : Lean.Json := Lean.Json.mkObj [ + ("owner", Lean.toJson (hexOfBytes hint.owner.hash)), + ("proofs", Lean.toJson (hint.proofs.map (Option.map proofJson)))] + +def json (hint : ModelHint) : Lean.Json := Lean.Json.mkObj [ + ("source", Lean.toJson (hexOfBytes hint.source.hash)), + ("recursors", Lean.toJson (hint.recursors.map (hexOfBytes ·.hash))), + ("targets", Lean.toJson (hint.targets.map (hexOfBytes ·.hash))), + ("proofs", Lean.toJson (hint.proofs.map rulesJson))] + +end ModelHint +end Ix.Certified diff --git a/Ix/Certified/ModeledAudit.lean b/Ix/Certified/ModeledAudit.lean new file mode 100644 index 000000000..738fe740b --- /dev/null +++ b/Ix/Certified/ModeledAudit.lean @@ -0,0 +1,56 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.AuditSupport +import Ix.Certified.ClaimCommand +import Ix.Certified.Command + +/-! Trust, runtime and premise inventory of the versioned semantic claim +checker, source command and actual TcM acceptance boundary. -/ + +open Lean Lean.Elab Command + +namespace Ix.Certified.ModeledAudit + +def roots : Array Lean.Name := #[ + `Ix.Theory.Certified.Modeled.check?_sound, + `Ix.Theory.Certified.Modeled.checkEquation?_sound, + `Ix.Theory.Certified.Modeled.assignment_realizes, + `Ix.Theory.Certified.Modeled.assignment_agrees, + `Ix.Theory.Certified.checkModeledExtension?, + `Ix.Theory.Certificate.Modeled.witness?, + `Ix.Theory.Certificate.sourceGroup?, + `Ix.Theory.Certificate.proofWitness?, + `Ix.Certified.modelCandidate?, `Ix.Certified.modelCandidates?, + `Ix.Certified.ModelHint.readOptional, `Ix.Certified.ModelHint.read, + `Ix.Certified.suggestSource?, `Ix.Certified.suggestStore?, + `Ix.Certified.Command.readRequest, `Ix.Certified.Command.run_success, + `Ix.Certified.suggestLogical?, `Ix.Certified.ClaimCommand.readRequest, + `Ix.Certified.ClaimCommand.run_meaning, + `Ix.Kernel.acceptsCertifiedSource, `Ix.Kernel.acceptsCertifiedStoreSource, + `Ix.Kernel.accepted_tc_claim_meaning] + +def premises : Array Lean.Name := #[ + `Ix.Certified.Protocol.current, + `Ix.Certified.ModelHint.mk, `Ix.Certified.ModelRuleHints.mk, + `Ix.Certified.ModelProofHint.mk, + `Ix.Theory.Certificate.Modeled.Candidate.mk, + `Ix.Theory.Certificate.Modeled.ProofHint.mk, + `Ix.Theory.Certified.Modeled.Witness.mk, + `Ix.Theory.Certified.Modeled.Checked.mk, + `Ix.Theory.Certified.Modeled.SourceMatches, + `Ix.Theory.Certified.Modeled.sourceRefs?, + `Ix.Theory.Certified.Modeled.recursorSource?, + `Ix.Theory.Certified.Modeled.majorSource?, + `Ix.Theory.Certified.Modeled.ruleSource?, + `Ix.Theory.Certified.Modeled.Companion.entry, + `Ix.Theory.Certified.Modeled.CompanionChecked.mk, + `Ix.Theory.Certified.Modeled.CheckedCompanions.mk, + `Ix.Theory.Certified.Modeled.CheckedEquation.mk, + `Ix.Theory.Certified.Modeled.checkEquation?] + +run_cmd AuditSupport.report "modeled source" roots premises + +end Ix.Certified.ModeledAudit diff --git a/Ix/Certified/NOTICE b/Ix/Certified/NOTICE new file mode 100644 index 000000000..41ed404df --- /dev/null +++ b/Ix/Certified/NOTICE @@ -0,0 +1,22 @@ +Certified source and claim adapters + +Copyright (c) 2026 Argument Computer Corporation. +Licensed under MIT OR Apache-2.0; see LICENSE-MIT and LICENSE-APACHE at the +repository root. + +The source and claim adapters were reconstructed from the authenticated +ix-pilot.patch and ix-c3.patch through ix-c7.patch supplied with the former +Lean4Ix consistency work. Original adapter files, patches, source identities, +reports, licenses and differential fixtures are retained in +Tests/Fixtures/Certified/c7-handoff.tar.gz. Individual source and maintained +file identities appear in Tests/Certified/ImportManifest.lean. + +Maintained theory imports use Ix.Theory, and the checker wrappers use +Ix.Kernel. The five historical audits now traverse full checked declaration +graphs and transitive runtime workers. The unused historical native profiling +counter module is preserved in the archive but is not maintained or linked. + +The set model and its separate attribution are maintained under Ix/Theory. +The old checkout is not a build or test dependency. This handoff archive +contains the selected adapter sources and regression evidence, not the +complete historical Ix base checkout. diff --git a/Ix/Certified/Reveal.lean b/Ix/Certified/Reveal.lean new file mode 100644 index 000000000..993a492ca --- /dev/null +++ b/Ix/Certified/Reveal.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.ClaimMeaning + +namespace Ix.Certified + +def Selected {α : Type _} (expected : Option α) (actual : α) : Prop := + match expected with + | none => True + | some value => value = actual + +instance {α : Type _} [DecidableEq α] (expected : Option α) (actual : α) : + Decidable (Selected expected actual) := by + unfold Selected + split <;> infer_instance + +/-- The structural reveal protocol commits to the exact serialized raw +expression, including its original table indices and sharing references. -/ +def expressionAddress (expression : Ixon.Expr) : Address := + Address.blake3 (Ixon.runPut (Ixon.putExpr expression)) + +def ConstructorMatches (expected : Ix.RevealConstructorInfo) (actual : Ixon.Constructor) : Prop := + Selected expected.isUnsafe actual.isUnsafe ∧ Selected expected.lvls actual.lvls ∧ + Selected expected.cidx actual.cidx ∧ Selected expected.params actual.params ∧ + Selected expected.fields actual.fields ∧ Selected expected.typ (expressionAddress actual.typ) + +instance (expected : Ix.RevealConstructorInfo) (actual : Ixon.Constructor) : + Decidable (ConstructorMatches expected actual) := inferInstanceAs (Decidable (_ ∧ _ ∧ _ ∧ _ ∧ _ ∧ _)) + +def ConstructorsMatch (expected : Option (Array (UInt64 × Ix.RevealConstructorInfo))) + (actual : Array Ixon.Constructor) : Prop := + match expected with + | none => True + | some constructors => ∀ pair ∈ constructors.toList, + match actual[pair.1.toNat]? with + | none => False + | some constructor => ConstructorMatches pair.2 constructor + +instance (expected : Option (Array (UInt64 × Ix.RevealConstructorInfo))) (actual : Array Ixon.Constructor) : + Decidable (ConstructorsMatch expected actual) := by + unfold ConstructorsMatch + split + · infer_instance + · apply @List.decidableBAll _ _ (fun pair => by split <;> infer_instance) + +def RulesMatch (expected : Option (Array Ix.RevealRecursorRule)) (actual : Array Ixon.RecursorRule) : Prop := + match expected with + | none => True + | some rules => ∀ rule ∈ rules.toList, + match actual[rule.ruleIdx.toNat]? with + | none => False + | some actual => rule.fields = actual.fields ∧ rule.rhs = expressionAddress actual.rhs + +instance (expected : Option (Array Ix.RevealRecursorRule)) (actual : Array Ixon.RecursorRule) : + Decidable (RulesMatch expected actual) := by + unfold RulesMatch + split + · infer_instance + · apply @List.decidableBAll _ _ (fun rule => by split <;> infer_instance) + +def MutMatches (expected : Ix.RevealMutConstInfo) (actual : Ixon.MutConst) : Prop := + match expected, actual with + | .defn kind safety levels type value, .defn actual => + Selected kind actual.kind ∧ Selected safety actual.safety ∧ Selected levels actual.lvls ∧ + Selected type (expressionAddress actual.typ) ∧ Selected value (expressionAddress actual.value) + | .indc safety levels params indices type ctors, .indc actual => + Selected safety actual.isUnsafe ∧ Selected levels actual.lvls ∧ Selected params actual.params ∧ + Selected indices actual.indices ∧ Selected type (expressionAddress actual.typ) ∧ ConstructorsMatch ctors actual.ctors + | .recr k safety levels params indices motives minors type rules, .recr actual => + Selected k actual.k ∧ Selected safety actual.isUnsafe ∧ Selected levels actual.lvls ∧ + Selected params actual.params ∧ Selected indices actual.indices ∧ Selected motives actual.motives ∧ + Selected minors actual.minors ∧ Selected type (expressionAddress actual.typ) ∧ RulesMatch rules actual.rules + | _, _ => False + +instance (expected : Ix.RevealMutConstInfo) (actual : Ixon.MutConst) : Decidable (MutMatches expected actual) := by + unfold MutMatches + cases expected <;> cases actual <;> infer_instance + +def ComponentsMatch (expected : Array (UInt64 × Ix.RevealMutConstInfo)) (actual : Array Ixon.MutConst) : Prop := + ∀ pair ∈ expected.toList, match actual[pair.1.toNat]? with + | none => False + | some member => MutMatches pair.2 member + +instance (expected : Array (UInt64 × Ix.RevealMutConstInfo)) (actual : Array Ixon.MutConst) : + Decidable (ComponentsMatch expected actual) := by + unfold ComponentsMatch + apply @List.decidableBAll _ _ (fun pair => by split <;> infer_instance) + +def RevealMatches (expected : Ix.RevealConstantInfo) (actual : Ixon.ConstantInfo) : Prop := + match expected, actual with + | .defn kind safety levels type value, .defn actual => + Selected kind actual.kind ∧ Selected safety actual.safety ∧ Selected levels actual.lvls ∧ + Selected type (expressionAddress actual.typ) ∧ Selected value (expressionAddress actual.value) + | .recr k safety levels params indices motives minors type rules, .recr actual => + Selected k actual.k ∧ Selected safety actual.isUnsafe ∧ Selected levels actual.lvls ∧ + Selected params actual.params ∧ Selected indices actual.indices ∧ Selected motives actual.motives ∧ + Selected minors actual.minors ∧ Selected type (expressionAddress actual.typ) ∧ RulesMatch rules actual.rules + | .axio safety levels type, .axio actual => + Selected safety actual.isUnsafe ∧ Selected levels actual.lvls ∧ Selected type (expressionAddress actual.typ) + | .quot kind levels type, .quot actual => + Selected kind actual.kind ∧ Selected levels actual.lvls ∧ Selected type (expressionAddress actual.typ) + | .cPrj index constructor block, .cPrj actual => + Selected index actual.idx ∧ Selected constructor actual.cidx ∧ Selected block actual.block + | .iPrj index block, .iPrj actual | .rPrj index block, .rPrj actual | .dPrj index block, .dPrj actual => + Selected index actual.idx ∧ Selected block actual.block + | .muts components, .muts actual => ComponentsMatch components actual + | _, _ => False + +instance (expected : Ix.RevealConstantInfo) (actual : Ixon.ConstantInfo) : Decidable (RevealMatches expected actual) := by + unfold RevealMatches + cases expected <;> cases actual <;> infer_instance + +structure RevealWitness where + opening : Ixon.Comm + +structure RevealReceipt (source : Ixon.Env) (commitment : Address) (info : Ix.RevealConstantInfo) + (witness : RevealWitness) where + secretSize : witness.opening.secret.hash.size = 32 + payloadSize : witness.opening.payload.hash.size = 32 + bound : witness.opening.commit = commitment + object : SourceObject source + payload : object.address = witness.opening.payload + fields : RevealMatches info object.decoded.val.info + +def checkReveal? (source : Ixon.Env) (commitment : Address) (info : Ix.RevealConstantInfo) + (witness : RevealWitness) : Read source (RevealReceipt source commitment info witness) := + if hs : witness.opening.secret.hash.size = 32 then + if hp : witness.opening.payload.hash.size = 32 then + if hb : witness.opening.commit = commitment then do + let object ← readObject? source witness.opening.payload + if ha : object.address = witness.opening.payload then + if hf : RevealMatches info object.decoded.val.info then + return ⟨hs, hp, hb, object, ha, hf⟩ + else failure + else failure + else failure + else failure + else failure + +def RevealMeaning (source : Ixon.Env) (commitment : Address) (info : Ix.RevealConstantInfo) : Prop := + ∃ opening : Ixon.Comm, opening.secret.hash.size = 32 ∧ opening.payload.hash.size = 32 ∧ + opening.commit = commitment ∧ ∃ bytes object, ObjectBytes source opening.payload bytes object ∧ + RevealMatches info object.info + +theorem RevealReceipt.meaning (receipt : RevealReceipt source commitment info witness) : + RevealMeaning source commitment info := by + refine ⟨witness.opening, receipt.secretSize, receipt.payloadSize, receipt.bound, + receipt.object.bytes, receipt.object.decoded.val, ?_, receipt.fields⟩ + rw [← receipt.payload] + exact ⟨receipt.object.fromSource, receipt.object.decoded.property⟩ + +end Ix.Certified diff --git a/Ix/Certified/SourceAudit.lean b/Ix/Certified/SourceAudit.lean new file mode 100644 index 000000000..96f5b3f33 --- /dev/null +++ b/Ix/Certified/SourceAudit.lean @@ -0,0 +1,39 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.AuditSupport +import Ix.Certified.SourceMeaning + +/-! The source audit freezes original expression/statement meaning and +its connection to the actual canonical source bytes. Claim composition and +backend execution are audited by their separate roots when connected. -/ + +open Lean Lean.Elab Command + +namespace Ix.Certified.SourceAudit + +def roots : Array Lean.Name := #[ + `Ix.Certified.resolveReference_iff, `Ix.Certified.readLevel_value, + `Ix.Certified.readExpr_sound, `Ix.Certified.ExprReading.unique, + `Ix.Certified.readExpr_fuel_independent, + `Ix.Certified.readBlock_sourceHeader, `Ix.Certified.readStore_sourceHeader, + `Ix.Certified.SourceSnapshot.object_bytes, `Ix.Certified.SourceSnapshot.natural_bytes, + `Ix.Certified.readSignature_sound, + `Ix.Certified.StoreReceipt.subject_meaning, `Ix.Certified.SourceReceipt.proposition_meaning, + `Ix.Certified.StoreReceipt.subject_coverage] + +def premises : Array Lean.Name := #[ + `Ix.Certified.MemberMeaning, `Ix.Certified.ReferenceTarget, `Ix.Certified.ReferenceMeaning, + `Ix.Certified.LevelsReading.nil, `Ix.Certified.LevelsReading.cons, + `Ix.Certified.ExprReading.var, `Ix.Certified.ExprReading.sort, `Ix.Certified.ExprReading.ref, + `Ix.Certified.ExprReading.recur, `Ix.Certified.ExprReading.app, `Ix.Certified.ExprReading.lam, + `Ix.Certified.ExprReading.all, `Ix.Certified.ExprReading.prj, `Ix.Certified.ExprReading.nat, + `Ix.Certified.ExprReading.share, `Ix.Certified.rawHeader?, + `Ix.Certified.ObjectBytes, `Ix.Certified.NaturalBytes, + `Ix.Certified.SignatureReading, `Ix.Certified.SourceDeclarationReading, `Ix.Certified.SubjectReading] + +run_cmd AuditSupport.report "source meaning" roots premises + +end Ix.Certified.SourceAudit diff --git a/Ix/Certified/SourceExpr.lean b/Ix/Certified/SourceExpr.lean new file mode 100644 index 000000000..5f29a49e9 --- /dev/null +++ b/Ix/Certified/SourceExpr.lean @@ -0,0 +1,274 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Ixon + +/-! Structural meaning of original Ixon expressions. References retain their +actual table positions and wrapper ownership; sharing expands only through +the original constant's sharing table. This relation has no typing premise. -/ + +namespace Ix.Certified + +open Ix.Theory + +def MemberMeaning (objects : Objects) (block : Address) (index : UInt64) + (member : Ixon.MutConst) : Prop := + ∃ source members, lookup objects block = some source ∧ source.info = .muts members ∧ + members[index.toNat]? = some member + +theorem mutMember_iff {objects : Objects} {block : Address} {index : UInt64} {member : Ixon.MutConst} : + mutMember? objects block index = some member ↔ MemberMeaning objects block index member := by + constructor + · intro h + unfold mutMember? at h + cases hs : lookup objects block with + | none => simp [hs] at h + | some source => + cases hi : source.info <;> simp [hs, hi] at h + exact ⟨source, _, hs, hi, h⟩ + · rintro ⟨source, members, hs, hi, hm⟩ + simp [mutMember?, hs, hi, hm] + +def ReferenceTarget (objects : Objects) (address : Address) (source : Ixon.Constant) + (ref : ConstRef Address) : Prop := + match source.info with + | .defn _ | .recr _ | .axio _ | .quot _ => ref = .member address 0 + | .iPrj projection => + (∃ family, MemberMeaning objects projection.block projection.idx (.indc family)) ∧ + ref = .member projection.block projection.idx.toNat + | .rPrj projection => + (∃ recursor, MemberMeaning objects projection.block projection.idx (.recr recursor)) ∧ + ref = .member projection.block projection.idx.toNat + | .dPrj projection => + (∃ definition, MemberMeaning objects projection.block projection.idx (.defn definition)) ∧ + ref = .member projection.block projection.idx.toNat + | .cPrj projection => + (∃ family ctor, MemberMeaning objects projection.block projection.idx (.indc family) ∧ + family.ctors[projection.cidx.toNat]? = some ctor) ∧ + ref = .ctor projection.block projection.idx.toNat projection.cidx.toNat + | .muts _ => False + +def ReferenceMeaning (objects : Objects) (address : Address) (ref : ConstRef Address) : Prop := + ∃ source, lookup objects address = some source ∧ ReferenceTarget objects address source ref + +theorem resolveReference_iff {objects : Objects} {address : Address} {ref : ConstRef Address} : + resolveReference? objects address = some ref ↔ ReferenceMeaning objects address ref := by + cases hs : lookup objects address with + | none => simp [resolveReference?, ReferenceMeaning, hs] + | some source => + simp only [ReferenceMeaning, hs, Option.some.injEq] + unfold resolveReference? + simp only [hs, bind, Option.bind_some] + unfold ReferenceTarget + rcases source with ⟨info, sharing, references, universes⟩ + cases info + all_goals dsimp only + all_goals try solve | simp [eq_comm] + all_goals simp only [← mutMember_iff] + all_goals rename_i projection + all_goals cases hm : mutMember? objects projection.block projection.idx with + | none => simp [hm] + | some member => + cases member <;> simp [hm, eq_comm, exists_and_left] + + all_goals rename_i family + all_goals cases hf : family.ctors[projection.cidx.toNat]? <;> simp [eq_comm] + +theorem ReferenceMeaning.unique {objects : Objects} {address : Address} {left right : ConstRef Address} + (hl : ReferenceMeaning objects address left) (hr : ReferenceMeaning objects address right) : left = right := + Option.some.inj ((resolveReference_iff.mpr hl).symm.trans (resolveReference_iff.mpr hr)) + +def sourceLevelValue (levels : List Nat) : Ixon.Univ → Nat + | .zero => 0 + | .succ level => sourceLevelValue levels level + 1 + | .max left right => max (sourceLevelValue levels left) (sourceLevelValue levels right) + | .imax left right => + if sourceLevelValue levels right = 0 then 0 else max (sourceLevelValue levels left) (sourceLevelValue levels right) + | .var index => levels.getD index.toNat 0 + +theorem readLevel_value (level : Ixon.Univ) (levels : List Nat) : + (readLevel level).eval levels = sourceLevelValue levels level := by + induction level <;> simp_all [readLevel, VLevel.eval, VLevel.natIMax, sourceLevelValue] + +inductive LevelsReading (source : Ixon.Constant) : List UInt64 → List VLevel → Prop where + | nil : LevelsReading source [] [] + | cons {index indices level levels} : source.univs[index.toNat]? = some level → + LevelsReading source indices levels → + LevelsReading source (index :: indices) (readLevel level :: levels) + +theorem readLevelsList_sound {source : Ixon.Constant} {indices : List UInt64} {levels : List VLevel} + (h : indices.mapM (fun index => (source.univs[index.toNat]?).map readLevel) = some levels) : + LevelsReading source indices levels := by + induction indices generalizing levels with + | nil => + simp at h + subst levels + exact .nil + | cons index indices ih => + cases hi : source.univs[index.toNat]? with + | none => simp [List.mapM_cons, hi] at h + | some level => + cases ht : indices.mapM (fun index => (source.univs[index.toNat]?).map readLevel) with + | none => simp [List.mapM_cons, hi, ht] at h + | some tail => + simp [List.mapM_cons, hi, ht] at h + subst levels + exact .cons hi (ih ht) + +theorem readLevels_sound {source : Ixon.Constant} {indices : Array UInt64} {levels : List VLevel} + (h : readLevels? source indices = some levels) : LevelsReading source indices.toList levels := + readLevelsList_sound h + +theorem LevelsReading.unique {source : Ixon.Constant} {indices : List UInt64} {left right : List VLevel} + (hl : LevelsReading source indices left) (hr : LevelsReading source indices right) : left = right := by + induction hl generalizing right with + | nil => cases hr; rfl + | cons hs _ ih => + cases hr with + | cons ht hr => + cases Option.some.inj (hs.symm.trans ht) + exact congrArg (_ :: ·) (ih hr) + +/-- A reading of the original source syntax, including all reference and +sharing-table lookups. Unsupported binder modes and literal forms have no +constructor in this relation. -/ +inductive ExprReading (objects : Objects) (naturals : Naturals) (block : Address) (source : Ixon.Constant) : + Ixon.Expr → VExpr Address → Prop where + | var (index) : ExprReading objects naturals block source (.var index) (.bvar index.toNat) + | sort {index level} : source.univs[index.toNat]? = some level → + ExprReading objects naturals block source (.sort index) (.sort (readLevel level)) + | ref {index indices address ref levels} : source.refs[index.toNat]? = some address → + ReferenceMeaning objects address ref → LevelsReading source indices.toList levels → + ExprReading objects naturals block source (.ref index indices) (.const ref levels) + | recur {index indices levels} : LevelsReading source indices.toList levels → + ExprReading objects naturals block source (.recur index indices) (.const (.member block index.toNat) levels) + | app {f a fr ar} : ExprReading objects naturals block source f fr → + ExprReading objects naturals block source a ar → + ExprReading objects naturals block source (.app f a) (.app fr ar) + | lam {A b Ar br} : ExprReading objects naturals block source A Ar → + ExprReading objects naturals block source b br → + ExprReading objects naturals block source (.lam .many A b) (.lam Ar br) + | all {A B Ar Br} : ExprReading objects naturals block source A Ar → + ExprReading objects naturals block source B Br → + ExprReading objects naturals block source (.all .many .shared A B) (.forallE Ar Br) + | prj {owner field value address ownerSource projection ref reading} : + source.refs[owner.toNat]? = some address → lookup objects address = some ownerSource → + ownerSource.info = .iPrj projection → ReferenceMeaning objects address ref → + ExprReading objects naturals block source value reading → + ExprReading objects naturals block source (.prj owner field value) (.proj ref field.toNat reading) + | nat {index address value} : source.refs[index.toNat]? = some address → lookup naturals address = some value → + ExprReading objects naturals block source (.nat index) (.natLit value) + | share {index shared reading} : source.sharing[index.toNat]? = some shared → + ExprReading objects naturals block source shared reading → + ExprReading objects naturals block source (.share index) reading + +theorem readExpr_sound {fuel : Nat} {objects : Objects} {naturals : Naturals} {block : Address} + {source : Ixon.Constant} {expression : Ixon.Expr} {reading : VExpr Address} + (h : readExpr? fuel objects naturals block source expression = some reading) : + ExprReading objects naturals block source expression reading := by + induction fuel generalizing expression reading with + | zero => simp [readExpr?] at h + | succ fuel ih => + cases expression with + | var index => + simp [readExpr?] at h + subst reading + exact .var index + | sort index => + simp only [readExpr?, Option.map_eq_some_iff] at h + obtain ⟨level, hl, rfl⟩ := h + exact .sort hl + | ref index indices => + simp only [readExpr?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨address, ha, ref, hr, levels, hl, rfl⟩ := h + exact .ref ha (resolveReference_iff.mp hr) (readLevels_sound hl) + | recur index indices => + simp only [readExpr?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨levels, hl, rfl⟩ := h + exact .recur (readLevels_sound hl) + | app f a => + simp only [readExpr?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨fr, hf, ar, ha, rfl⟩ := h + exact .app (ih hf) (ih ha) + | lam uses A b => + cases uses <;> simp only [readExpr?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + all_goals try contradiction + obtain ⟨Ar, hA, br, hb, rfl⟩ := h + exact .lam (ih hA) (ih hb) + | all uses owned A B => + cases uses <;> cases owned <;> + simp only [readExpr?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + all_goals try contradiction + obtain ⟨Ar, hA, Br, hB, rfl⟩ := h + exact .all (ih hA) (ih hB) + | prj owner field value => + simp only [readExpr?, bind, Option.bind_eq_some_iff] at h + obtain ⟨address, ha, ownerSource, hs, h⟩ := h + cases hp : ownerSource.info <;> simp only [hp] at h + all_goals try contradiction + simp only [Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨ref, hr, reading, hv, rfl⟩ := h + exact .prj ha hs hp (resolveReference_iff.mp hr) (ih hv) + | nat index => + simp only [readExpr?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨address, ha, value, hv, rfl⟩ := h + exact .nat ha hv + | share index => + simp only [readExpr?, bind, Option.bind_eq_some_iff] at h + obtain ⟨shared, hs, hr⟩ := h + exact .share hs (ih hr) + | str | letE => simp [readExpr?] at h + +/-- The original tables determine one expanded expression. Neither fuel nor +a different sharing-expansion derivation can change the statement. -/ +theorem ExprReading.unique {objects : Objects} {naturals : Naturals} {block : Address} + {source : Ixon.Constant} {expression : Ixon.Expr} {left right : VExpr Address} + (hl : ExprReading objects naturals block source expression left) + (hr : ExprReading objects naturals block source expression right) : left = right := by + induction hl generalizing right with + | var => cases hr; rfl + | sort hs => + cases hr with + | sort ht => cases Option.some.inj (hs.symm.trans ht); rfl + | ref ha hm hl => + cases hr with + | ref hb hn hr => + cases Option.some.inj (ha.symm.trans hb) + exact congr (congrArg VExpr.const (hm.unique hn)) (hl.unique hr) + | recur hl => + cases hr with + | recur hr => exact congrArg (VExpr.const _) (hl.unique hr) + | app _ _ ihf iha => + cases hr with + | app hf ha => exact congr (congrArg VExpr.app (ihf hf)) (iha ha) + | lam _ _ ihA ihb => + cases hr with + | lam hA hb => exact congr (congrArg VExpr.lam (ihA hA)) (ihb hb) + | all _ _ ihA ihB => + cases hr with + | all hA hB => exact congr (congrArg VExpr.forallE (ihA hA)) (ihB hB) + | prj ha _ _ hm _ ih => + cases hr with + | prj hb _ _ hn hv => + cases Option.some.inj (ha.symm.trans hb) + exact congr (congrArg (fun r e => VExpr.proj r _ e) (hm.unique hn)) (ih hv) + | nat ha hv => + cases hr with + | nat hb hw => + cases Option.some.inj (ha.symm.trans hb) + exact congrArg VExpr.natLit (Option.some.inj (hv.symm.trans hw)) + | share hs _ ih => + cases hr with + | share ht hr => + cases Option.some.inj (hs.symm.trans ht) + exact ih hr + +theorem readExpr_fuel_independent {fuel₁ fuel₂ : Nat} {objects : Objects} {naturals : Naturals} + {block : Address} {source : Ixon.Constant} {expression : Ixon.Expr} {left right : VExpr Address} + (hl : readExpr? fuel₁ objects naturals block source expression = some left) + (hr : readExpr? fuel₂ objects naturals block source expression = some right) : left = right := + (readExpr_sound hl).unique (readExpr_sound hr) + +end Ix.Certified diff --git a/Ix/Certified/SourceMeaning.lean b/Ix/Certified/SourceMeaning.lean new file mode 100644 index 000000000..4f8aae276 --- /dev/null +++ b/Ix/Certified/SourceMeaning.lean @@ -0,0 +1,245 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.SourceStore +import Ix.Kernel.Certified + +/-! Authenticated source-statement meaning for successful certified source +runs. The original bytes, raw type and table-resolved reading occur together +in the contract; semantic equality never substitutes for byte identity. -/ + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v + +def ObjectBytes (source : Ixon.Env) (address : Address) (bytes : ByteArray) (value : Ixon.Constant) : Prop := + constantBytes? source address = some bytes ∧ address.hash.size = 32 ∧ + Address.blake3 bytes = address ∧ Ixon.runGetExact Ixon.getConstant bytes = .ok value ∧ + Ixon.serConstant value = bytes + +def NaturalBytes (source : Ixon.Env) (address : Address) (bytes : ByteArray) (value : Nat) : Prop := + source.getBlob? address = some bytes ∧ address.hash.size = 32 ∧ + Address.blake3 bytes = address ∧ Nat.fromBytesLE bytes.data = value ∧ + ByteArray.mk value.toBytesLE = bytes + +theorem SourceSnapshot.object_bytes (snapshot : SourceSnapshot source) {address : Address} {value : Ixon.Constant} + (h : lookup snapshot.decodedObjects address = some value) : ∃ bytes, ObjectBytes source address bytes value := by + obtain ⟨entry, _, he⟩ := List.mem_map.mp (lookup_mem h) + rcases Prod.mk.inj he with ⟨rfl, rfl⟩ + exact ⟨entry.bytes, entry.fromSource, entry.decoded.property⟩ + +theorem SourceSnapshot.natural_bytes (snapshot : SourceSnapshot source) {address : Address} {value : Nat} + (h : lookup snapshot.decodedNaturals address = some value) : ∃ bytes, NaturalBytes source address bytes value := by + obtain ⟨entry, _, he⟩ := List.mem_map.mp (lookup_mem h) + rcases Prod.mk.inj he with ⟨rfl, rfl⟩ + exact ⟨entry.bytes, entry.fromSource, entry.decoded.property⟩ + +def SignatureReading (profile : Profile) (objects : Objects) (signature : PrimitiveSignature Address) : Prop := + ReferenceMeaning objects profile.falseType signature.falseType ∧ + ReferenceMeaning objects profile.falseElim signature.falseElim ∧ + match profile.natType, signature.natType with + | none, none => True + | some address, some ref => ReferenceMeaning objects address ref + | _, _ => False + +theorem readSignature_sound {profile : Profile} {objects : Objects} {signature : PrimitiveSignature Address} + (h : readSignature? profile objects = some signature) : SignatureReading profile objects signature := by + rcases profile with ⟨falseAddress, elimAddress, natural⟩ + cases natural with + | none => + simp only [readSignature?, bind, Option.bind_some, Option.bind_eq_some_iff] at h + obtain ⟨falseType, hF, falseElim, hE, h⟩ := h + split at h + · cases Option.some.inj h + exact ⟨resolveReference_iff.mp hF, resolveReference_iff.mp hE, trivial⟩ + · cases h + | some address => + simp only [readSignature?, bind, Option.bind_eq_some_iff, Option.map_eq_some_iff] at h + obtain ⟨falseType, hF, falseElim, hE, _, ⟨ref, hn, rfl⟩, h⟩ := h + split at h + · cases Option.some.inj h + exact ⟨resolveReference_iff.mp hF, resolveReference_iff.mp hE, resolveReference_iff.mp hn⟩ + · cases h + +theorem SourceSnapshot.prepareStore_parts {source : Ixon.Env} (snapshot : SourceSnapshot source) + {fuel : Nat} {profile : Profile} {subjects : List Address} {prepared : PreparedStore} + (h : snapshot.prepareStore? fuel profile subjects = some prepared) : + readSignature? profile snapshot.decodedObjects = some prepared.signature ∧ + readStore? fuel snapshot.decodedObjects snapshot.decodedNaturals = some prepared.store ∧ + subjects.flatMapM (subjectReferences? snapshot.decodedObjects) = some prepared.targets := by + unfold SourceSnapshot.prepareStore? at h + split at h + · cases h + · simp only [prepareStoreObjects?, bind, Option.bind_eq_some_iff] at h + obtain ⟨signature, hs, store, hstore, targets, ht, h⟩ := h + split at h + · cases h + · cases Option.some.inj h + exact ⟨hs, hstore, ht⟩ + +theorem SourceSnapshot.prepare_parts {source : Ixon.Env} (snapshot : SourceSnapshot source) + {fuel : Nat} {profile : Profile} {target : Address} {prepared : PreparedInput} + (h : snapshot.prepare? fuel profile target = some prepared) : + readSignature? profile snapshot.decodedObjects = some prepared.signature ∧ + readProofInput? fuel snapshot.decodedObjects target snapshot.decodedNaturals = some prepared.input := by + unfold SourceSnapshot.prepare? at h + split at h + · cases h + · simp only [bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨signature, hs, input, hi, rfl⟩ := h + exact ⟨hs, hi⟩ + +def SourceDeclarationReading (source : Ixon.Env) (objects : Objects) (naturals : Naturals) + (ref : ConstRef Address) (entry : ConstantEntry Address) : Prop := + ∃ bytes declaration rawType, + ObjectBytes source ref.block bytes declaration ∧ lookup objects ref.block = some declaration ∧ + rawHeader? declaration ref = some (entry.universes, rawType) ∧ + ExprReading objects naturals ref.block declaration rawType entry.type.erase + +theorem SourceSnapshot.declaration_reading {source : Ixon.Env} (snapshot : SourceSnapshot source) + {fuel : Nat} {store : Store Address} {ref : ConstRef Address} {entry : ConstantEntry Address} + (h : readStore? fuel snapshot.decodedObjects snapshot.decodedNaturals = some store) + (hh : SourceHeader store ref entry) : + SourceDeclarationReading source snapshot.decodedObjects snapshot.decodedNaturals ref entry := by + obtain ⟨declaration, rawType, hs, ht, hr⟩ := readStore_sourceHeader h hh + obtain ⟨bytes, hb⟩ := snapshot.object_bytes hs + exact ⟨bytes, declaration, rawType, hb, hs, ht, hr⟩ + +/-- Every original requested source declaration is realized in every compatible +model, with its complete canonical bytes and its original raw type retained. -/ +theorem StoreReceipt.subject_meaning + (receipt : StoreReceipt.{v} source fuel profile subjects witness) + {ref : ConstRef Address} (hr : ref ∈ receipt.prepared.targets) : + ∃ entry, receipt.result.environment.entries ref = some entry ∧ + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry ∧ + ∀ (V : Type v) [SetTheory V] (constants : Assignment Address V), + receipt.prepared.signature.Compatible receipt.result.environment.entries constants → + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env entry.type ∧ + constants ref levels ∈ˢ interp constants levels env entry.type := by + obtain ⟨entry, he, hh, hm⟩ := receipt.result.subject_sound hr + exact ⟨entry, he, receipt.snapshot.declaration_reading + (receipt.snapshot.prepareStore_parts receipt.preparation).2.1 hh, hm⟩ + +theorem readProofInput_parts {fuel : Nat} {objects : Objects} {naturals : Naturals} {target : Address} + {input : ProofInput Address} (h : readProofInput? fuel objects target naturals = some input) : + readStore? fuel objects naturals = some input.store ∧ + ∃ ref declaration, resolveReference? objects target = some ref ∧ + input.store.lookup ref = some declaration ∧ input.universes = declaration.uvars ∧ + input.proof = .const ref (VLevel.params input.universes) ∧ input.proposition = declaration.type := by + unfold readProofInput? at h + simp only [bind, Option.bind_eq_some_iff] at h + obtain ⟨store, hs, ref, hr, declaration, hd, h⟩ := h + split at h + · cases Option.some.inj h + exact ⟨hs, ref, declaration, hr, hd, rfl, rfl, rfl⟩ + · cases h + +theorem SourceReceipt.target_entry + (receipt : SourceReceipt.{v} source fuel profile target witness) : + ∃ ref entry, ReferenceMeaning receipt.snapshot.decodedObjects target ref ∧ + receipt.proof.environment.entries ref = some entry ∧ + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry ∧ + receipt.prepared.input.universes = entry.universes ∧ + receipt.prepared.input.proposition = entry.type.erase := by + have hp := receipt.snapshot.prepare_parts receipt.preparation + obtain ⟨hs, ref, declaration, hr, hd, hu, he, ht⟩ := readProofInput_parts hp.2 + have hproof : receipt.proof.proof.val = .const ref (VLevel.params receipt.prepared.input.universes) := + AExpr.eq_const_of_erase_eq (receipt.proof.proof.property.1.trans he) + have hmem : (receipt.proof.environment.entries ref).isSome = true := by + simpa [hproof, AExpr.ReferencesIn, AExpr.references] using receipt.proof.proofReferences + cases hf : receipt.proof.environment.entries ref with + | none => simp [hf] at hmem + | some entry => + have hh := receipt.proof.environment.sourceHeader hf + have hu' : declaration.uvars = entry.universes := by simpa [Store.uvars, hd] using hh.universes + have ht' : declaration.type = entry.type.erase := by simpa [Store.type, hd] using hh.type + exact ⟨ref, entry, resolveReference_iff.mp hr, hf, + receipt.snapshot.declaration_reading hs hh, hu.trans hu', ht.trans ht'⟩ + +/-- This is the original serialized proposition's type field, with its exact +source bytes and a validated reading of the original tables. The proposition +is inhabited in every compatible interpretation, not just a chosen model. -/ +theorem SourceReceipt.proposition_meaning + (receipt : SourceReceipt.{v} source fuel profile target witness) : + SignatureReading profile receipt.snapshot.decodedObjects receipt.prepared.signature ∧ + ∃ ref bytes declaration rawType, + ReferenceMeaning receipt.snapshot.decodedObjects target ref ∧ + ObjectBytes source ref.block bytes declaration ∧ + rawHeader? declaration ref = some (receipt.prepared.input.universes, rawType) ∧ + ExprReading receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref.block declaration + rawType receipt.proof.proposition.val.erase ∧ + ∀ (V : Type v) [SetTheory V] (constants : Assignment Address V), + receipt.prepared.signature.Compatible receipt.proof.environment.entries constants → ∀ levels env, + WellDenoted constants levels env receipt.proof.proposition.val ∧ + interp constants levels env receipt.proof.proposition.val ∈ˢ univ 0 ∧ + interp constants levels env receipt.proof.proof.val ∈ˢ + interp constants levels env receipt.proof.proposition.val := by + refine ⟨readSignature_sound (receipt.snapshot.prepare_parts receipt.preparation).1, ?_⟩ + obtain ⟨ref, entry, hr, _, ⟨bytes, declaration, rawType, hb, _, ht, hread⟩, hu, hp⟩ := receipt.target_entry + refine ⟨ref, bytes, declaration, rawType, hr, hb, hu ▸ ht, ?_, ?_⟩ + · rw [receipt.proof.proposition.property.1, hp] + exact hread + · intro V _ constants hM levels env + have hs := receipt.proof.isProp V constants hM.realizes levels env (Context.valid_nil constants levels env) + exact ⟨hs.1, hs.2.2, (receipt.proof.typing V constants hM.realizes levels env + (Context.valid_nil constants levels env)).2.2⟩ + +def SubjectReading (objects : Objects) (subject : Address) (refs : List (ConstRef Address)) : Prop := + ∃ source, lookup objects subject = some source ∧ + match source.info with + | .muts members => members.isEmpty = false ∧ refs = + (members.toList.zipIdx.flatMap fun (member, index) => + .member subject index :: match member with + | .indc family => (List.range family.ctors.size).map (.ctor subject index ·) + | _ => []) + | _ => ∃ ref, ReferenceMeaning objects subject ref ∧ refs = [ref] + +theorem subjectReferences_iff {objects : Objects} {subject : Address} {refs : List (ConstRef Address)} : + subjectReferences? objects subject = some refs ↔ SubjectReading objects subject refs := by + cases hs : lookup objects subject with + | none => simp [subjectReferences?, SubjectReading, hs] + | some source => + rcases source with ⟨info, sharing, references, levels⟩ + cases info <;> + simp only [subjectReferences?, SubjectReading, hs, ← resolveReference_iff, bind, + Option.bind_some, Option.bind_eq_some_iff, pure, Option.some.injEq, exists_eq_left'] + all_goals try solve | simp only [eq_comm] + rename_i members + cases he : members.isEmpty <;> simp [eq_comm] + rfl + +theorem flatMapM_mem_iff {α β : Type} {f : α → Option (List β)} {xs : List α} {ys : List β} + (h : xs.flatMapM f = some ys) (value : β) : + value ∈ ys ↔ ∃ source ∈ xs, ∃ values, f source = some values ∧ value ∈ values := by + induction xs generalizing ys with + | nil => simp at h; subst ys; simp + | cons x xs ih => + simp only [List.flatMapM_cons, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨values, hv, tail, ht, rfl⟩ := h + constructor + · intro hm + rcases List.mem_append.mp hm with hm | hm + · exact ⟨x, List.mem_cons_self .., values, hv, hm⟩ + · obtain ⟨source, hs, values, hf, hm⟩ := (ih ht).mp hm + exact ⟨source, List.mem_cons_of_mem _ hs, values, hf, hm⟩ + · rintro ⟨source, hs, result, hf, hm⟩ + rcases List.mem_cons.mp hs with rfl | hs + · cases Option.some.inj (hv.symm.trans hf) + exact List.mem_append_left _ hm + · exact List.mem_append_right _ ((ih ht).mpr ⟨source, hs, result, hf, hm⟩) + +/-- Exact subject coverage: projection owners, every block member and every +constructor are retained. No unrelated declaration is silently discharged. -/ +theorem StoreReceipt.subject_coverage + (receipt : StoreReceipt.{v} source fuel profile subjects witness) (ref : ConstRef Address) : + ref ∈ receipt.prepared.targets ↔ + ∃ subject ∈ subjects, ∃ refs, SubjectReading receipt.snapshot.decodedObjects subject refs ∧ ref ∈ refs := by + have h := flatMapM_mem_iff (receipt.snapshot.prepareStore_parts receipt.preparation).2.2 ref + simpa only [subjectReferences_iff] using h + +end Ix.Certified diff --git a/Ix/Certified/SourceStore.lean b/Ix/Certified/SourceStore.lean new file mode 100644 index 000000000..2555a34fd --- /dev/null +++ b/Ix/Certified/SourceStore.lean @@ -0,0 +1,318 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.SourceExpr +import Ix.Theory.Certified.Source + +/-! Exact original declaration headers through the source block reader. -/ + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified + +theorem mapM_get_right {α β : Type} {f : α → Option β} {xs : List α} {ys : List β} + {index : Nat} {value : β} (h : xs.mapM f = some ys) (hy : ys[index]? = some value) : + ∃ source, xs[index]? = some source ∧ f source = some value := by + induction xs generalizing ys index with + | nil => simp at h; subst ys; simp at hy + | cons x xs ih => + simp only [List.mapM_cons, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨y, hf, tail, ht, rfl⟩ := h + cases index with + | zero => simp at hy; subst value; exact ⟨x, rfl, hf⟩ + | succ index => + obtain ⟨source, hs, hf⟩ := ih ht hy + exact ⟨source, hs, hf⟩ + +def memberRawHeader : Ixon.MutConst → Nat × Ixon.Expr + | .defn value => (value.lvls.toNat, value.typ) + | .recr value => (value.lvls.toNat, value.typ) + | .indc value => (value.lvls.toNat, value.typ) + +def rawHeader? (source : Ixon.Constant) : ConstRef Address → Option (Nat × Ixon.Expr) + | .member _ index => + match source.info with + | .muts members => members[index]?.map memberRawHeader + | .defn value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | .recr value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | .axio value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | .quot value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | _ => none + | .ctor _ index field => do + let .muts members := source.info | none + let .indc family ← members[index]? | none + let ctor ← family.ctors[field]? + return (ctor.lvls.toNat, ctor.typ) + +def blockHeader? (block : Block Address) : ConstRef Address → Option (Nat × VExpr Address) + | .member _ index => block.members[index]?.map fun declaration => (declaration.uvars, declaration.type) + | .ctor _ index field => do + let .induct _ _ _ _ ctors _ ← block.members[index]? | none + let ctor ← ctors[field]? + return (ctor.uvars, ctor.type) + +theorem readMember_header {fuel : Nat} {objects : Objects} {naturals : Naturals} {block : Address} + {source : Ixon.Constant} {member : Ixon.MutConst} {declaration : Const Address} + (h : readMutualMember? fuel objects naturals block source member = some declaration) : + declaration.uvars = (memberRawHeader member).1 ∧ + readExpr? fuel objects naturals block source (memberRawHeader member).2 = some declaration.type := by + cases member with + | defn value => + simp only [readMutualMember?, readDefinition?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨type, ht, body, _, rfl⟩ := h + exact ⟨rfl, ht⟩ + | recr value => + simp only [readMutualMember?, readRecursor?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨type, ht, rules, _, rfl⟩ := h + exact ⟨rfl, ht⟩ + | indc value => + simp only [readMutualMember?, readInductive?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨type, ht, constructors, _, rfl⟩ := h + exact ⟨rfl, ht⟩ + +theorem readInductive_constructor {fuel : Nat} {objects : Objects} {naturals : Naturals} {block : Address} + {source : Ixon.Constant} {family : Ixon.Inductive} {declaration : Const Address} + {index : Nat} {universes : Nat} {type : VExpr Address} + (h : readInductive? fuel objects naturals block source family = some declaration) + (hc : blockHeader? ⟨[declaration]⟩ (.ctor block 0 index) = some (universes, type)) : + ∃ ctor, family.ctors[index]? = some ctor ∧ ctor.lvls.toNat = universes ∧ + readExpr? fuel objects naturals block source ctor.typ = some type := by + simp only [readInductive?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨familyType, _, ctors, hm, rfl⟩ := h + simp only [blockHeader?, List.getElem?_cons_zero, bind, Option.bind_some, + Option.bind_eq_some_iff, pure, Option.some.injEq, Prod.mk.injEq] at hc + obtain ⟨ctor, hc, hn, ht⟩ := hc + obtain ⟨⟨raw, position⟩, hr, hp⟩ := mapM_get_right hm hc + simp only [List.getElem?_zipIdx, Array.getElem?_toList, Nat.zero_add, + Option.map_eq_some_iff, Prod.mk.injEq] at hr + obtain ⟨raw', hs, rfl, rfl⟩ := hr + split at hp + · contradiction + · simp only [Option.bind_eq_some_iff, Option.some.injEq] at hp + obtain ⟨reading, ht', he⟩ := hp + cases he + exact ⟨raw', hs, hn, ht ▸ ht'⟩ + +theorem readBlock_sourceHeader {fuel : Nat} {objects : Objects} {naturals : Naturals} {block : Address} + {source : Ixon.Constant} {result : Block Address} {ref : ConstRef Address} + {universes : Nat} {type : VExpr Address} + (h : readBlock? fuel objects naturals block source = some result) + (hh : blockHeader? result ref = some (universes, type)) : + ∃ raw, rawHeader? source ref = some (universes, raw) ∧ + ExprReading objects naturals block source raw type := by + rcases source with ⟨info, sharing, references, levels⟩ + cases info with + | defn value => + simp only [readBlock?, readDefinition?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨_, ⟨type, ht, body, _, rfl⟩, rfl⟩ := h + cases ref with + | member owner index => + cases index with + | zero => + simp only [blockHeader?, List.getElem?_cons_zero, Option.map_some, + Const.uvars, Const.type, Option.some.injEq, Prod.mk.injEq] at hh + rcases hh with ⟨rfl, rfl⟩ + exact ⟨_, rfl, readExpr_sound ht⟩ + | succ index => simp [blockHeader?] at hh + | ctor owner index field => cases index <;> simp [blockHeader?] at hh + | recr value => + simp only [readBlock?, readRecursor?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨_, ⟨type, ht, rules, _, rfl⟩, rfl⟩ := h + cases ref with + | member owner index => + cases index with + | zero => + simp only [blockHeader?, List.getElem?_cons_zero, Option.map_some, + Const.uvars, Const.type, Option.some.injEq, Prod.mk.injEq] at hh + rcases hh with ⟨rfl, rfl⟩ + exact ⟨_, rfl, readExpr_sound ht⟩ + | succ index => simp [blockHeader?] at hh + | ctor owner index field => cases index <;> simp [blockHeader?] at hh + | axio value => + simp only [readBlock?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨type, ht, rfl⟩ := h + cases ref with + | member owner index => + cases index with + | zero => + simp only [blockHeader?, List.getElem?_cons_zero, Option.map_some, + Const.uvars, Const.type, Option.some.injEq, Prod.mk.injEq] at hh + rcases hh with ⟨rfl, rfl⟩ + exact ⟨_, rfl, readExpr_sound ht⟩ + | succ index => simp [blockHeader?] at hh + | ctor owner index field => cases index <;> simp [blockHeader?] at hh + | quot value => + simp only [readBlock?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨type, ht, rfl⟩ := h + cases ref with + | member owner index => + cases index with + | zero => + simp only [blockHeader?, List.getElem?_cons_zero, Option.map_some, + Const.uvars, Const.type, Option.some.injEq, Prod.mk.injEq] at hh + rcases hh with ⟨rfl, rfl⟩ + exact ⟨_, rfl, readExpr_sound ht⟩ + | succ index => simp [blockHeader?] at hh + | ctor owner index field => cases index <;> simp [blockHeader?] at hh + | muts rawMembers => + simp only [readBlock?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨members, hm, rfl⟩ := h + cases ref with + | member owner index => + simp only [blockHeader?, Option.map_eq_some_iff, Prod.mk.injEq] at hh + obtain ⟨declaration, hd, hn, ht⟩ := hh + obtain ⟨raw, hr, hread⟩ := mapM_get_right hm hd + have ⟨hu, htype⟩ := readMember_header hread + refine ⟨(memberRawHeader raw).2, ?_, readExpr_sound (ht ▸ htype)⟩ + simp only [rawHeader?, ← Array.getElem?_toList, hr, Option.map_some] + exact congrArg some (congrArg (·, (memberRawHeader raw).2) (hu.symm.trans hn)) + | ctor owner index field => + simp only [blockHeader?, bind, Option.bind_eq_some_iff] at hh + obtain ⟨declaration, hd, hc⟩ := hh + obtain ⟨raw, hr, hread⟩ := mapM_get_right hm hd + have hc' : blockHeader? ⟨[declaration]⟩ (.ctor block 0 field) = some (universes, type) := by + simpa only [blockHeader?, List.getElem?_cons_zero, bind, Option.bind_some] using hc + cases raw with + | defn value => + simp only [readMutualMember?, readDefinition?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at hread + obtain ⟨type, _, body, _, rfl⟩ := hread + simp [blockHeader?] at hc' + | recr value => + simp only [readMutualMember?, readRecursor?, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at hread + obtain ⟨type, _, rules, _, rfl⟩ := hread + simp [blockHeader?] at hc' + | indc family => + obtain ⟨ctor, hctor, hn, htype⟩ := readInductive_constructor hread hc' + refine ⟨ctor.typ, ?_, readExpr_sound htype⟩ + have hr' : rawMembers[index]? = some (.indc family) := by simpa using hr + simp [rawHeader?, hr', hctor, hn] + | cPrj | rPrj | iPrj | dPrj => simp [readBlock?] at h + +theorem lookup_mem {α : Type} {entries : List (Address × α)} {address : Address} {value : α} + (h : lookup entries address = some value) : (address, value) ∈ entries := by + induction entries with + | nil => cases h + | cons entry rest ih => + obtain ⟨key, data⟩ := entry + unfold lookup at h + split at h + · rename_i hk + subst address + cases Option.some.inj h + exact List.mem_cons_self .. + · exact List.mem_cons_of_mem _ (ih h) + +theorem lookup_of_mem {α : Type} {entries : List (Address × α)} {address : Address} {value : α} + (hn : (entries.map Prod.fst).Nodup) (h : (address, value) ∈ entries) : + lookup entries address = some value := by + induction entries with + | nil => cases h + | cons entry rest ih => + obtain ⟨key, data⟩ := entry + have hn := List.nodup_cons.mp hn + rcases List.mem_cons.mp h with he | hr + · cases he + simp [lookup] + · have hk : address ≠ key := by + intro he + apply hn.1 + exact List.mem_map.mpr ⟨(address, value), hr, he⟩ + simp only [lookup, hk, ↓reduceIte] + exact ih hn.2 hr + +theorem readBlocks_mem {fuel : Nat} {objects pending : Objects} {naturals : Naturals} + {blocks : List (Address × Block Address)} {address : Address} {block : Block Address} + (h : readBlocks? fuel objects naturals pending = some blocks) (hm : (address, block) ∈ blocks) : + ∃ source, (address, source) ∈ pending ∧ readBlock? fuel objects naturals address source = some block := by + induction pending generalizing blocks with + | nil => simp [readBlocks?] at h; subst blocks; cases hm + | cons entry rest ih => + obtain ⟨key, source⟩ := entry + unfold readBlocks? at h + split at h + · simp only [bind, Option.bind_eq_some_iff] at h + obtain ⟨_, _, h⟩ := h + obtain ⟨source, hs, hb⟩ := ih h hm + exact ⟨source, List.mem_cons_of_mem _ hs, hb⟩ + · simp only [bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨decoded, hd, tail, ht, rfl⟩ := h + rcases List.mem_cons.mp hm with he | hr + · rcases Prod.mk.inj he with ⟨rfl, rfl⟩ + exact ⟨source, List.mem_cons_self .., hd⟩ + · obtain ⟨source, hs, hb⟩ := ih ht hr + exact ⟨source, List.mem_cons_of_mem _ hs, hb⟩ + +theorem readStore_sourceBlock {fuel : Nat} {objects : Objects} {naturals : Naturals} + {store : Store Address} {address : Address} {block : Block Address} + (h : readStore? fuel objects naturals = some store) (hb : store.blocks address = some block) : + ∃ source, lookup objects address = some source ∧ readBlock? fuel objects naturals address source = some block := by + unfold readStore? at h + split at h + · rename_i hn + simp only [bind, Option.bind_eq_some_iff] at h + obtain ⟨blocks, hblocks, h⟩ := h + split at h + · cases Option.some.inj h + obtain ⟨source, hs, hr⟩ := readBlocks_mem hblocks (lookup_mem hb) + exact ⟨source, lookup_of_mem hn hs, hr⟩ + · cases h + · cases h + +def storeHeader? (store : Store Address) (ref : ConstRef Address) : Option (Nat × VExpr Address) := do + let block ← store.blocks ref.block + blockHeader? block ref + +theorem storeHeader_maps (store : Store Address) (ref : ConstRef Address) : + (storeHeader? store ref).map Prod.fst = store.uvars ref ∧ + (storeHeader? store ref).map Prod.snd = store.type ref := by + cases ref with + | member address index => + cases hs : store.blocks address with + | none => simp [storeHeader?, ConstRef.block, Store.type, Store.uvars, Store.lookup, Store.lookupCtor, hs] + | some block => + cases hm : block.members[index]? <;> + simp [storeHeader?, ConstRef.block, blockHeader?, Store.type, Store.uvars, Store.lookup, Store.lookupCtor, hs, hm] + | ctor address index field => + cases hs : store.blocks address with + | none => simp [storeHeader?, ConstRef.block, Store.type, Store.uvars, Store.lookup, Store.lookupCtor, hs] + | some block => + cases hm : block.members[index]? with + | none => simp [storeHeader?, ConstRef.block, blockHeader?, Store.type, Store.uvars, Store.lookup, Store.lookupCtor, hs, hm] + | some declaration => + cases declaration <;> + simp [storeHeader?, ConstRef.block, blockHeader?, Store.type, Store.uvars, Store.lookup, Store.lookupCtor, hs, hm] + rename_i ctors _ + cases hc : ctors[field]? <;> simp + +theorem sourceHeader_pair {store : Store Address} {ref : ConstRef Address} {entry : Ix.Theory.Model.ConstantEntry Address} + (h : SourceHeader store ref entry) : storeHeader? store ref = some (entry.universes, entry.type.erase) := by + have ⟨hu, ht⟩ := storeHeader_maps store ref + rw [h.universes] at hu + rw [h.type] at ht + cases hh : storeHeader? store ref with + | none => simp [hh] at ht + | some header => + rcases header with ⟨universes, type⟩ + simp only [hh, Option.map_some, Option.some.injEq] at hu ht + cases hu + cases ht + rfl + +/-- Exact source type, source universe arity and a unique structural reading +of that original type, for every admitted source member or constructor. -/ +theorem readStore_sourceHeader {fuel : Nat} {objects : Objects} {naturals : Naturals} + {store : Store Address} {ref : ConstRef Address} {entry : Ix.Theory.Model.ConstantEntry Address} + (h : readStore? fuel objects naturals = some store) (hh : SourceHeader store ref entry) : + ∃ source raw, lookup objects ref.block = some source ∧ + rawHeader? source ref = some (entry.universes, raw) ∧ + ExprReading objects naturals ref.block source raw entry.type.erase := by + have hp := sourceHeader_pair hh + simp only [storeHeader?, bind, Option.bind_eq_some_iff] at hp + obtain ⟨block, hb, hp⟩ := hp + obtain ⟨source, hs, hr⟩ := readStore_sourceBlock h hb + obtain ⟨raw, hraw, hread⟩ := readBlock_sourceHeader hr hp + exact ⟨source, raw, hs, hraw, hread⟩ + +end Ix.Certified diff --git a/Ix/Certified/Store.lean b/Ix/Certified/Store.lean new file mode 100644 index 000000000..40d9d5cba --- /dev/null +++ b/Ix/Certified/Store.lean @@ -0,0 +1,74 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Bytes +import Ix.Theory.Certified.Store + +namespace Ix.Certified + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v + +/-- A block subject requests every member and constructor. A projection +subject must resolve to its actual matching source kind and position. -/ +def subjectReferences? (objects : Objects) (subject : Address) : Option (List (ConstRef Address)) := do + let source ← lookup objects subject + match source.info with + | .muts members => + if members.isEmpty then none else + return members.toList.zipIdx.flatMap fun (member, index) => + .member subject index :: match member with + | .indc family => (List.range family.ctors.size).map (.ctor subject index ·) + | _ => [] + | _ => return [← resolveReference? objects subject] + +structure PreparedStore where + signature : PrimitiveSignature Address + store : Store Address + targets : List (ConstRef Address) + +def prepareStoreObjects? (fuel : Nat) (profile : Profile) (subjects : List Address) + (objects : Objects) (naturals : Naturals) : Option PreparedStore := do + let signature ← readSignature? profile objects + let store ← readStore? fuel objects naturals + let targets ← subjects.flatMapM (subjectReferences? objects) + if targets.length > fuel then none else return ⟨signature, store, targets⟩ + +def prepareStore? (fuel : Nat) (profile : Profile) (subjects : List Address) + (blobs : ConstantBlobs) (literalBlobs : ConstantBlobs := []) : Option PreparedStore := do + if !((blobs ++ literalBlobs).map Prod.fst).Nodup then none else do + let naturals ← decodeNaturals? literalBlobs + let objects ← decodeObjects? blobs + prepareStoreObjects? fuel profile subjects objects naturals + +def acceptsSerializedStore (fuel : Nat) (profile : Profile) (subjects : List Address) + (blobs : ConstantBlobs) (witness : List (DeclarationWitness Address)) + (literalBlobs : ConstantBlobs := []) : Bool := + match prepareStore? fuel profile subjects blobs literalBlobs with + | none => false + | some prepared => acceptsStoreCertified.{0,v} fuel prepared.signature prepared.store prepared.targets witness + +theorem accepted_serialized_store_has_model {fuel : Nat} {profile : Profile} {subjects : List Address} + {blobs literalBlobs : ConstantBlobs} {witness : List (DeclarationWitness Address)} + (h : acceptsSerializedStore.{v} fuel profile subjects blobs witness literalBlobs = true) + (V : Type v) [SetTheory V] : + ∃ prepared, prepareStore? fuel profile subjects blobs literalBlobs = some prepared ∧ + ∃ result : CheckedStore.{0,v} prepared.signature prepared.store prepared.targets, + checkStoreCertified fuel prepared.signature prepared.store prepared.targets witness = some result ∧ + ∃ constants : Assignment Address V, + prepared.signature.Compatible result.environment.entries constants ∧ + ∀ r ∈ prepared.targets, ∃ entry, result.environment.entries r = some entry ∧ + EntrySource prepared.signature prepared.store r entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env : Nat → V, + WellDenoted constants levels env entry.type ∧ + constants r levels ∈ˢ interp constants levels env entry.type := by + unfold acceptsSerializedStore at h + cases hp : prepareStore? fuel profile subjects blobs literalBlobs with + | none => simp [hp] at h + | some prepared => + exact ⟨prepared, rfl, accepted_store_has_model (by simpa only [hp] using h) V⟩ + +end Ix.Certified diff --git a/Ix/Certified/Suggest.lean b/Ix/Certified/Suggest.lean new file mode 100644 index 000000000..6a1340edb --- /dev/null +++ b/Ix/Certified/Suggest.lean @@ -0,0 +1,31 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Ingress +import Ix.Theory.Certificate.Build +import Ix.Certified.ModelHints + +namespace Ix.Certified + +open Ix.Theory.Certified + +/-- Untrusted witness search from selected addresses in the actual source +store. A returned witness still has to pass the certified TcM entry point. -/ +def suggestSource? (fuel : Nat) (source : Ixon.Env) (profile : Profile) (target : Address) + (selection : InputSelection) (hints : List ModelHint := []) : Option (ProofWitness Address) := do + let (snapshot, _) ← readSnapshot? fuel source selection {} + let prepared ← snapshot.prepare? fuel profile target + let models ← modelCandidates? snapshot.decodedObjects prepared.input.store hints + Ix.Theory.Certificate.proofWitness? fuel prepared.signature prepared.input models + +/-- Search for complete declaration groups for every requested source subject. -/ +def suggestStore? (fuel : Nat) (source : Ixon.Env) (profile : Profile) (subjects : List Address) + (selection : InputSelection) (hints : List ModelHint := []) : Option (List (DeclarationWitness Address)) := do + let (snapshot, _) ← readSnapshot? fuel source selection {} + let prepared ← snapshot.prepareStore? fuel profile subjects + let models ← modelCandidates? snapshot.decodedObjects prepared.store hints + Ix.Theory.Certificate.storeWitness? fuel prepared.signature prepared.store prepared.targets models + +end Ix.Certified diff --git a/Ix/Certified/TcAudit.lean b/Ix/Certified/TcAudit.lean new file mode 100644 index 000000000..d91767547 --- /dev/null +++ b/Ix/Certified/TcAudit.lean @@ -0,0 +1,42 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.AuditSupport +import Ix.Kernel.Certified +import Ix.Certified.Command + +/-! This audit covers the actual TcM certified entry points, the decoder +cache and source receipts. It does not promote legacy TcM successes. -/ + +open Lean Lean.Elab Command + +namespace Ix.Certified.TcAudit + +def roots : Array Lean.Name := #[ + `Ix.Certified.constantBytes?, `Ix.Certified.decodeObject_complete, + `Ix.Certified.decodeNatural_complete, + `Ix.Certified.SourceSnapshot.prepare_eq, `Ix.Certified.SourceSnapshot.prepareStore_eq, + `Ix.Certified.SourceSnapshot.objects_from_source, `Ix.Certified.SourceSnapshot.naturals_from_source, + `Ix.Certified.SourceReceipt.serialized, `Ix.Certified.StoreReceipt.serialized, + `Ix.Certified.accepted_serialized_store_has_model, + `Ix.Kernel.TcM.checkCertified_success, `Ix.Kernel.TcM.checkCertified_failure, + `Ix.Kernel.TcM.checkStoreCertified_success, + `Ix.Kernel.certifiedStep_success, `Ix.Kernel.certifiedStep_failure, + `Ix.Kernel.certifiedStoreStep_success, `Ix.Kernel.certifiedStoreStep_failure, + `Ix.Kernel.initialCertifiedState, `Ix.Kernel.accepted_tc_has_model, + `Ix.Kernel.accepted_tc_store_has_model, `Ix.Kernel.no_tc_proof_of_False, + `Ix.Certified.Command.run_success] + +def premises : Array Lean.Name := #[ + `Ix.Certified.InputCache.mk, `Ix.Certified.CachedObject.mk, `Ix.Certified.CachedNatural.mk, + `Ix.Certified.DecodedObject, `Ix.Certified.DecodedNatural, + `Ix.Certified.SourceObject.mk, `Ix.Certified.SourceNatural.mk, + `Ix.Certified.SourceReceipt.mk, `Ix.Certified.StoreReceipt.mk, + `Ix.Certified.InputSelection.mk, `Ix.Certified.subjectReferences?, + `Ix.Kernel.CertifiedState.mk] + +run_cmd AuditSupport.report "certified checker" roots premises + +end Ix.Certified.TcAudit diff --git a/Ix/Certified/Trees.lean b/Ix/Certified/Trees.lean new file mode 100644 index 000000000..59276b734 --- /dev/null +++ b/Ix/Certified/Trees.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.SourceMeaning +import Ix.AssumptionTree + +/-! Total checking of Ix's existing Merkle-tree wire representation. The +public slot determines whether leaves mean constant addresses, environment +roots, or logical-axiom addresses. Padding is never a declaration. -/ + +namespace Ix.Certified + +instance addressLawfulBEq : LawfulBEq Address where + eq_of_beq := by + intro a b h + change (a.hash.data == b.hash.data) = true at h + cases a + cases b + exact congrArg Address.mk (congrArg ByteArray.mk (eq_of_beq h)) + rfl := by + intro a + change (a.hash.data == a.hash.data) = true + exact beq_self_eq_true _ + +def treeRoot : AssumptionTree → Address + | .leaf address => Merkle.leafHash address + | .padding => Merkle.zeroAddress + | .node left right => Merkle.nodeHash (treeRoot left) (treeRoot right) + +def treeLeaves : AssumptionTree → List Address + | .leaf address => [address] + | .padding => [] + | .node left right => treeLeaves left ++ treeLeaves right + +def putTreeBody : AssumptionTree → Ixon.PutM Unit + | .leaf address => do Ixon.putU8 0; Ixon.Serialize.put address + | .padding => Ixon.putU8 1 + | .node left right => do + Ixon.putU8 2 + putTreeBody left + putTreeBody right + +def treeBytes (tree : AssumptionTree) : ByteArray := Ixon.runPut do + Ixon.putTag4 ⟨AssumptionTree.FLAG, AssumptionTree.VARIANT⟩ + putTreeBody tree + +def getTreeBody : Nat → Ixon.GetM AssumptionTree + | 0 => throw "certified tree depth limit" + | fuel + 1 => do + match ← Ixon.getU8 with + | 0 => return .leaf (← Ixon.Serialize.get) + | 1 => return .padding + | 2 => return .node (← getTreeBody fuel) (← getTreeBody fuel) + | _ => throw "invalid certified tree node" + +def getTree (fuel : Nat) : Ixon.GetM AssumptionTree := do + let tag ← Ixon.getTag4 + if tag.flag != AssumptionTree.FLAG || tag.size != AssumptionTree.VARIANT then + throw "invalid certified tree tag" + getTreeBody fuel + +structure TreeOpening (fuel : Nat) (root : Address) (bytes : ByteArray) where + tree : AssumptionTree + parsing : Ixon.runGetExact (getTree fuel) bytes = .ok tree + canonical : treeBytes tree = bytes + rootBound : treeRoot tree = root + addresses : ∀ address ∈ treeLeaves tree, address.hash.size = 32 + +def readTree? (fuel : Nat) (root : Address) (bytes : ByteArray) : + Option (TreeOpening fuel root bytes) := + match hp : Ixon.runGetExact (getTree fuel) bytes with + | .error _ => none + | .ok tree => + if hc : treeBytes tree = bytes then + if hr : treeRoot tree = root then + if ha : (treeLeaves tree).all (fun address => address.hash.size == 32) = true then + some ⟨tree, hp, hc, hr, by simpa using List.all_eq_true.mp ha⟩ + else none + else none + else none + +structure OptionalTreeOpening (fuel : Nat) (root : Option Address) (bytes : Option ByteArray) where + leaves : List Address + evidence : match root, bytes with + | none, none => leaves = [] + | some root, some bytes => ∃ opening : TreeOpening fuel root bytes, treeLeaves opening.tree = leaves + | _, _ => False + +def readOptionalTree? (fuel : Nat) (root : Option Address) (bytes : Option ByteArray) : + Option (OptionalTreeOpening fuel root bytes) := + match root, bytes with + | none, none => some ⟨[], rfl⟩ + | some root, some bytes => do + let opening ← readTree? fuel root bytes + return ⟨treeLeaves opening.tree, ⟨opening, rfl⟩⟩ + | _, _ => none + +def TreeMembership (root target : Address) : Prop := + ∃ tree, treeRoot tree = root ∧ target ∈ treeLeaves tree ∧ + ∀ address ∈ treeLeaves tree, address.hash.size = 32 + +/-- Membership is a structural assertion only. No environment or typing +judgment occurs in its conclusion. -/ +theorem TreeOpening.membership (opening : TreeOpening fuel root bytes) {target : Address} + (h : target ∈ treeLeaves opening.tree) : TreeMembership root target := + ⟨opening.tree, opening.rootBound, h, opening.addresses⟩ + +theorem treeLeaves_join (left right : AssumptionTree) (address : Address) : + address ∈ treeLeaves (.node left right) ↔ address ∈ treeLeaves left ∨ address ∈ treeLeaves right := + List.mem_append + +theorem TreeOpening.unique {a b : TreeOpening fuel root bytes} : a.tree = b.tree := + Except.ok.inj (a.parsing.symm.trans b.parsing) + +end Ix.Certified diff --git a/Ix/Cli/BenchCmd.lean b/Ix/Cli/BenchCmd.lean index 139154378..0fd410ed6 100644 --- a/Ix/Cli/BenchCmd.lean +++ b/Ix/Cli/BenchCmd.lean @@ -12,7 +12,6 @@ the benchmark); 3. spawns the run's measured tool — `bench-typecheck` (aiur), `zisk-host`/`sp1-host` (zkVM execute), `ix check-rs` (ooc), - `bench-lean4lean` (lean4lean; olean-driven, no `.ixe`), `ix compile` (compile) — wrapped in the RAM watchdog (`Ix.Watchdog`: cgroup `memory.max` via a systemd user scope; the kernel OOM-kills at the ceiling). The per-constant backends (aiur, zkVM) spawn @@ -335,22 +334,6 @@ def backendSpecs : List BackendSpec := [ metrics := [("execute", ["check-time", "throughput", "peak-rss"])], thresholds := [("constants", "0", "0"), ("check-time", "0.10", "_"), ("throughput", "_", "0.10"), ("peak-rss", "0.10", "_")] }, - -- lean4lean (github.com/digama0/lean4lean, required by the lakefile at a - -- pinned rev): the reference Lean4-in-Lean4 kernel, the external - -- yardstick for the Ix kernels (`ooc` / `ix check-lean`) on the same - -- libraries. Checks the env's library from its oleans (no `.ixe`): - -- whole-library row (module-parallel replay of the import closure) plus - -- one full-closure row per constant, mirroring ooc's row shape and - -- metric names so cross-kernel tables line up. Disabled in CI until a - -- bencher testbed exists — `ix bench run --backend lean4lean` works - -- locally regardless (`disabled` only gates the CI matrix and - -- `!benchmark` scheduling). - { name := "lean4lean", defaultMode := "execute", - inputs := .perConstantWithEnv, - disabled := some "local-only: no bencher testbed yet", - testbeds := [("execute", "lean4lean-check-x64-32x")], - metrics := [("execute", ["check-time", "throughput", "peak-rss", - "constants"])] }, -- AnthropicFLT remains on-demand: its from-scratch upstream build needs -- substantially more than the per-push workflow's one-hour budget. An -- explicit `--env AnthropicFLT` or `BENCH_ENVS=AnthropicFLT` still runs it. @@ -804,27 +787,6 @@ is not a benchmark run" "--json", out, "--json-name", info.name] if exit != 0 && exit != exitRejected then IO.eprintln s!"[bench] whole-env aiur check failed (exit {exit})" - | "lean4lean" => - -- The reference Lean4-in-Lean4 kernel checks the env's library from - -- its oleans, so no `.ixe` is resolved. The tool takes the same - -- registry `module` path `ix compile` does (its lake project supplies - -- the search path; the tool builds the module itself, outside every - -- timed window). Whole-library row keyed by the env name … - let bl ← resolveBin repo "bench-lean4lean" - let modulePath := s!"{repo}/{info.module}" - let exit ← runGuarded watchdog ceilingGb bl - #[modulePath, "--json", out, "--json-name", info.name] - if exit != 0 && exit != exitRejected then - IO.eprintln s!"[bench] whole-library replay failed (exit {exit})" - -- … plus one full-closure row per constant. ONE process for all names - -- (the ooc pattern): the imported env is shared across the closure - -- replays instead of re-paying the library import per name. - if !names.isEmpty then - IO.FS.writeFile namesFile ("\n".intercalate names.toList ++ "\n") - let exit ← runGuarded watchdog ceilingGb bl - #[modulePath, "--no-build", "--consts-file", namesFile, "--json", out] - if exit != 0 && exit != exitRejected then - IO.eprintln s!"[bench] per-constant closures failed (exit {exit})" | "aiur" => -- prove runs the whole pipeline (`bench-typecheck --recursive`): -- every stage per constant, closed by the pipeline ledger. One process @@ -891,7 +853,7 @@ is not a benchmark run" let expected := match backend with | "compile" => #[info.name] | "decompile" => #[info.name] - | "ooc" | "lean4lean" => #[info.name] ++ names + | "ooc" => #[info.name] ++ names | _ => names let code ← gate out expected if code == 0 || code == exitRejected then @@ -930,7 +892,7 @@ def benchRunCmd : Cli.Cmd := `[Cli| "Execute one benchmark run (backend × env × mode), writing benchmark results JSON. Exits 0 on success (rows saved as the local baseline), 3 when the kernel rejected any constant, 1 when no rows were produced." FLAGS: - backend : String; "aiur | aiur-sharded-env | zisk | sp1 | ooc | lean4lean | compile | decompile" + backend : String; "aiur | aiur-sharded-env | zisk | sp1 | ooc | compile | decompile" env : String; "Benchmark env from the registry (default: InitStd)" mode : String; "prove | execute (default: the backend's defaultMode)" out : String; "Benchmark results JSON output path (default: bench.json)" diff --git a/Ix/Cli/CheckLeanCmd.lean b/Ix/Cli/CheckLeanCmd.lean index af1c420be..2ac5bd962 100644 --- a/Ix/Cli/CheckLeanCmd.lean +++ b/Ix/Cli/CheckLeanCmd.lean @@ -1,6 +1,6 @@ /- `ix check-lean `: typecheck a serialized `.ixe` environment - through the pure-Lean `Ix.Tc` kernel — the reference-kernel counterpart + through the pure-Lean `Ix.Kernel` — the reference-kernel counterpart of `ix check-rs`, with matching mode default, live progress, and exit codes. Correctness-first: expect the Rust kernel to be much faster. @@ -17,7 +17,7 @@ subject-only but still reads dependencies' declared types, so every constant must be present. `--max` therefore bounds the check phase only, never ingress. Checking then runs work-stealing parallel workers - over the shared env (see `Ix.Tc.ParCheck`). + over the shared env (see `Ix.Kernel.ParCheck`). Progress mirrors `check-rs`: a periodic aggregate line (done/total, rate, eta, oldest in-flight) on stderr, persistent lines only for @@ -38,14 +38,14 @@ module public import Cli public import Ix.Common public import Ix.Cli.ConstsFile -public import Ix.Tc +public import Ix.Kernel public import Ix.Benchmark.Results public section namespace Ix.Cli.CheckLeanCmd -open Ix.Tc +open Ix.Kernel /-- First set env var wins; else the default. Zero is a valid setting. -/ def envNat (names : List String) (dflt : Nat) : IO Nat := do @@ -222,7 +222,7 @@ def runCheckLeanCmd (p : Cli.Parsed) : IO UInt32 := do maxRecFuel? := ((← IO.getEnv "IX_MAX_REC_FUEL").bind (·.trimAscii.toString.toNat?)).map (·.toUInt64) } - IO.println s!"Running Ix.Tc kernel check \ + IO.println s!"Running Ix.Kernel check \ ({if anon then "anon" else "meta"} mode) on {envPath}" let t0 ← IO.monoMsNow let bytes ← IO.FS.readBinFile envPath @@ -271,7 +271,7 @@ end Ix.Cli.CheckLeanCmd open Ix.Cli.CheckLeanCmd in def checkLeanCmd : Cli.Cmd := `[Cli| "check-lean" VIA runCheckLeanCmd; - "Typecheck a `.ixe` through the pure-Lean Ix.Tc kernel (meta mode by default; parallel)" + "Typecheck a `.ixe` through the pure-Lean Ix.Kernel (meta mode by default; parallel)" FLAGS: anon; "Run in anon mode (metadata never reaches the kernel; `#hex` labels)" diff --git a/Ix/Cli/ValidateLeanCmd.lean b/Ix/Cli/ValidateLeanCmd.lean index 8441d1711..9f8359a99 100644 --- a/Ix/Cli/ValidateLeanCmd.lean +++ b/Ix/Cli/ValidateLeanCmd.lean @@ -1,6 +1,6 @@ /- `ix validate-lean `: run the pure-Lean Ix pipeline validation - against the Lean environment for any file — the `Ix.Tc` counterpart to + against the Lean environment for any file — the `Ix.Kernel` counterpart to `ix validate` (which drives the Rust implementation's 8-phase pipeline). Phases (all pure-Lean): @@ -44,7 +44,7 @@ public import Ix.DecompileM public import Ix.DecompileDriver public import Ix.DecompileRoundtrip public import Ix.Meta -public import Ix.Tc +public import Ix.Kernel public import Ix.Cli.ValidateCmd public section @@ -54,7 +54,7 @@ open Ix.EnvScope namespace Ix.Cli.ValidateLeanCmd -open Ix.Tc +open Ix.Kernel /-- Phase outcome for the final report. -/ inductive PhaseResult where diff --git a/Ix/Compile/Verify/Audit/SorryFrontier.lean b/Ix/Compile/Verify/Audit/SorryFrontier.lean index db3ee1f65..0595ae8b1 100644 --- a/Ix/Compile/Verify/Audit/SorryFrontier.lean +++ b/Ix/Compile/Verify/Audit/SorryFrontier.lean @@ -4,7 +4,7 @@ import Ix.Compile.Verify.Audit.Statements # Compiler-verification source sorry frontier Fail the build if any declaration emitted from an `Ix.Compile.Verify` source -module directly references `sorryAx`. Upstream Lean4Lean debt is handled by +module directly references `sorryAx`. Named-specification debt is handled by per-root transitive manifests rather than being confused with local source placeholders. -/ diff --git a/Ix/Compile/Verify/Audit/Statements.lean b/Ix/Compile/Verify/Audit/Statements.lean index 4bee84cf0..d30f4c7a4 100644 --- a/Ix/Compile/Verify/Audit/Statements.lean +++ b/Ix/Compile/Verify/Audit/Statements.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Audit.Basic +import Ix.Kernel.Verify.Audit.Basic import Ix.Compile.Verify.Statements /-! @@ -13,25 +13,20 @@ a premise. namespace Ix.Compile.Verify.Audit.Statements -open Ix.Tc.Verify.Audit +open Ix.Kernel.Verify.Audit private def standard : Array Lean.Name := #[``propext, ``Classical.choice, ``Quot.sound] private def noChoice : Array Lean.Name := #[``propext, ``Quot.sound] -private def blake3Native : Array Lean.Name := #[ - nativeAxiom `Blake3 - `Blake3.HasherOps.hash._native.native_decide.ax_1 -] - private def nameNative : Array Lean.Name := #[ nativeAxiom `Ix.Environment `Ix.Name.mkStr._native.native_decide.ax_1 ] private def singletonDriverNative : Array Lean.Name := - blake3Native ++ nameNative + nameNative private def roots : Array RootAllowance := #[ { root := ``Ix.Compile.Verify.IxonExprRel.eraseModes_iff, @@ -71,7 +66,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard }, { root := ``Ix.Compile.Verify.ExprTableWF.mono }, { root := ``Ix.Compile.Verify.Catalog.empty_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.Catalog.ofEnv_finite, standardAxioms := noChoice }, { root := ``Ix.Compile.Verify.BlockState.internRef_wf, @@ -91,24 +86,24 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Compile.Verify.compileAndInternUnivCanon_run_refines, standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileAndInternUnivCanon_array_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileUniv_run_value, standardAxioms := standard }, { root := ``Ix.Compile.Verify.canonPreseedUnivs_run_refines, standardAxioms := standard }, { root := ``Ix.Compile.Verify.collectExprTablesStructural_run_ready, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.collectExprTablesStructural_run_ready_covers, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.collectPreseedExprs_singleton_run_ready_covers, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.collectPreseedExprs_pair_run_ready_covers, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.singletonPreseedCovers_of_ready, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.singletonPreseedCapacity_of_ready, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.internPreseedRefs_run_wf, standardAxioms := standard }, { root := ``Ix.Compile.Verify.internPreseedRefs_run_total, @@ -129,130 +124,130 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard }, { root := ``Ix.Compile.Verify.PreseedCollectionCovers.compileExprRef_of_indexed, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.BlockWireTablesWF.of_preseed, standardAxioms := noChoice }, { root := ``Ix.Compile.Verify.preseedExprTables_singleton_run_ready, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_singleton_run_ready_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_singleton_run_ready_frozenRef, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_of_collect_run_ready_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_pair_run_ready_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_pair_run_ready_frozenRefs, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_roots_run_ready_frozenRefs, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.collectPreseedExprs_inputs_run_ready_covers, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_inputs_run_ready_frozenRefs, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.heterogeneousPreseedSeenSafe_of_uniform, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_inputs_run_uniform_ready_frozenRefs, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.preseedExprTables_run_univsFinal, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.serializeIxSyntax_run_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.KVMapSupported.all, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileKVMap_run_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.metaCompileSupport_finite, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.BlockState_compileName_strict, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.serializeIxSyntax_run_strictStores, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileDataValue_run_strictStores, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileKVMap_run_strictStores, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.StructuralExprCacheWF.insert, standardAxioms := standard }, { root := ``Ix.Compile.Verify.OrdinaryExprCacheWF.insert, standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_surgeryFree, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExprNoSurgeryFuel_structural_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_structural_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_structural_value, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_sort_value, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_constEmpty_recur_value, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_constEmpty_ref_value, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_lit_value, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExprNoSurgeryFuel_ordinary_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_codec_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.deConstant_serUnsharedAxiomConstant, standardAxioms := standard }, { root := ``Ix.Compile.Verify.deConstant_serUnsharedDefinitionConstant, standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_axiomConstant_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_definitionConstant_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.BlockResult.mk'_codec_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.buildConstantWithSharing_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.BlockResult.constantInfo_codec_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.constantInfoRootExprs_toList, standardAxioms := #[``propext] }, { root := ``Ix.Compile.Verify.finishConstantInfoWithSharing_run_codecWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileAxiom_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.finishQuotientCompilation_run, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileQuotient_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileRecursorRules_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.finishRecursorCompilation_run, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileRecursor_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileConstructor_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileInductiveConstructors_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.finishInductiveCompilation_run, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileInductive_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileInductiveData_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileMutConsts_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.buildCompiledMutualBlock_codecWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileMutualBlock_run_of_preseed_ordinary_codecWF, standardAxioms := standard, nativeAxioms := singletonDriverNative }, @@ -281,20 +276,20 @@ private def roots : Array RootAllowance := #[ ``Ix.Compile.Verify.compileConstant_run_mutual_of_lookup_sorted_codecWF, standardAxioms := standard, nativeAxioms := singletonDriverNative }, { root := ``Ix.Compile.Verify.finishInductiveFamilyBlock_run_codecWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.lookupInductiveConstructors_run_of_lookup, standardAxioms := standard, nativeAxioms := nameNative }, { root := ``Ix.Compile.Verify.compileDefinition_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.finishDefinitionDataCompilation_run, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileDefinitionData_run_ordinary_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileDefinitionDataInfo_run_ready_codecWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.axiomCompileStartState_frozen, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileConstantInfo_axiom_run_ordinary_codecWF, standardAxioms := standard, nativeAxioms := singletonDriverNative }, @@ -325,30 +320,30 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Compile.Verify.rewriteWithSharing_wireWF, standardAxioms := standard }, { root := ``Ix.Compile.Verify.applySharing_wireWF, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_axiomBlock_noSharing_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_definitionBlock_noSharing_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_axiomBlock_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_definitionBlock_roundtrip, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_value, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExprNoSurgeryFuel_ordinary_arena_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_arena_refines, - standardAxioms := standard, nativeAxioms := blake3Native }, + standardAxioms := standard }, { root := ``Ix.Compile.Verify.compileExpr_run_ordinary_arena_value, - standardAxioms := standard, nativeAxioms := blake3Native } + standardAxioms := standard } ] -run_cmd Ix.Tc.Verify.Audit.check roots +run_cmd Ix.Kernel.Verify.Audit.check roots end Ix.Compile.Verify.Audit.Statements diff --git a/Ix/Compile/Verify/Catalog.lean b/Ix/Compile/Verify/Catalog.lean index 3ff230550..4eafad6c1 100644 --- a/Ix/Compile/Verify/Catalog.lean +++ b/Ix/Compile/Verify/Catalog.lean @@ -5,7 +5,7 @@ import Std.Data.HashMap.Lemmas /-! # Immutable compiler catalog and representation well-formedness -This module states the X1 representation boundary without running Ix.Tc. It +This module states the X1 representation boundary without running Ix.Kernel. It separates content-address integrity, finite immutable lookup support, logical environment views, wire representability, and expression-table resolution. @@ -393,7 +393,7 @@ structure Catalog.Finite (catalog : Catalog) : Prop where memberAddrs : FinitelySupported catalog.memberAddrs /-- X1 in-memory catalog integrity. This is representation -well-formedness, not Lean4Lean `VEnv.WF`. -/ +well-formedness, not Ix.Theory.Named `VEnv.WF`. -/ structure Catalog.WF (catalog : Catalog) : Prop where finite : catalog.Finite constants : ∀ {addr constant}, catalog.constants addr = some constant → @@ -434,7 +434,7 @@ theorem Catalog.empty_wf : Catalog.empty.WF := by /-- Immutable view of a concrete `Ixon.Env`. `nameOf` and mutual member addresses remain explicit semantic inputs because the wire environment stores -Ix names and projection constants, not Lean4Lean names or a redundant member +Ix names and projection constants, not Ix.Theory.Named names or a redundant member array. -/ def Catalog.ofEnv (env : Ixon.Env) (nameOf : Address → Option Lean.Name) diff --git a/Ix/Compile/Verify/CompileExpr.lean b/Ix/Compile/Verify/CompileExpr.lean index 8d2cf06a9..85347ceab 100644 --- a/Ix/Compile/Verify/CompileExpr.lean +++ b/Ix/Compile/Verify/CompileExpr.lean @@ -24,7 +24,7 @@ closes the complete ordinary-expression tree: sorts, arbitrary-universe local and external constants, recursive projections, literals, structural composition, and arbitrary metadata maps including recursive syntax values. The proof covers warm caches, universe spelling patches, blob/name commits, -and independent Lean4Lean values. Its strengthened frontier also relates the +and independent Ix.Theory.Named values. Its strengthened frontier also relates the returned `UInt64` root, including the encoded KV map, to the append-only presentation arena under an explicit no-wrap capacity premise. -/ @@ -1309,11 +1309,11 @@ theorem compileExpr_run_sort_refines exact hrun /-- The production sort result therefore denotes the same independent -Lean4Lean value as the source sort. -/ +Ix.Theory.Named value as the source sort. -/ theorem compileExpr_run_sort_value - {venv : Lean4Lean.VEnv} {sctx : SourceCtx} {catalog : Catalog} + {venv : Ix.Theory.Named.VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {trProj : ProjectionRel} - {uvars : Nat} {locals : List Lean4Lean.VExpr} + {uvars : Nat} {locals : List Ix.Theory.Named.VExpr} (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) (snapshot : Ix.CompileM.BlockState) {levelSupport : Ix.Level → Prop} @@ -1324,7 +1324,7 @@ theorem compileExpr_run_sort_value (hctx : RefCompileCtxRel (frozenRefCompileCtx compileEnv blockEnv snapshot) sctx catalog dctx) {state : Ix.CompileM.BlockState} {level : Ix.Level} {hash : Address} - {raw : Ixon.Univ} {idx : UInt64} {value : Lean4Lean.VExpr} + {raw : Ixon.Univ} {idx : UInt64} {value : Ix.Theory.Named.VExpr} (hlevel : levelSupport level) (hstate : FrozenExprStateWF compileEnv blockEnv levelSupport snapshot state) (hraw : compileUnivRef (univParamIndex blockEnv.univCtx) level = some raw) @@ -2097,9 +2097,9 @@ theorem compileExpr_run_constEmpty_ref_refines Ix.CompileM.exprCompileDepth] using hrun theorem compileExpr_run_constEmpty_recur_value - {venv : Lean4Lean.VEnv} {sctx : SourceCtx} {catalog : Catalog} + {venv : Ix.Theory.Named.VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {trProj : ProjectionRel} - {uvars : Nat} {locals : List Lean4Lean.VExpr} + {uvars : Nat} {locals : List Ix.Theory.Named.VExpr} (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) (snapshot : Ix.CompileM.BlockState) {levelSupport : Ix.Level → Prop} @@ -2108,7 +2108,7 @@ theorem compileExpr_run_constEmpty_recur_value (hctx : RefCompileCtxRel (frozenRefCompileCtx compileEnv blockEnv snapshot) sctx catalog dctx) {state : Ix.CompileM.BlockState} {name : Ix.Name} {hash : Address} - {recIdx : Nat} {value : Lean4Lean.VExpr} + {recIdx : Nat} {value : Ix.Theory.Named.VExpr} (hstate : FrozenExprStateWF compileEnv blockEnv levelSupport snapshot state) (hmut : blockEnv.mutCtx.get? name = some recIdx) (hsource : SourceExprRel (uvars := uvars) venv sctx trProj locals @@ -2138,9 +2138,9 @@ theorem compileExpr_run_constEmpty_recur_value compileExprRef_value hctx hsource href⟩ theorem compileExpr_run_constEmpty_ref_value - {venv : Lean4Lean.VEnv} {sctx : SourceCtx} {catalog : Catalog} + {venv : Ix.Theory.Named.VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {trProj : ProjectionRel} - {uvars : Nat} {locals : List Lean4Lean.VExpr} + {uvars : Nat} {locals : List Ix.Theory.Named.VExpr} (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) (snapshot : Ix.CompileM.BlockState) {levelSupport : Ix.Level → Prop} @@ -2149,7 +2149,7 @@ theorem compileExpr_run_constEmpty_ref_value (hctx : RefCompileCtxRel (frozenRefCompileCtx compileEnv blockEnv snapshot) sctx catalog dctx) {state : Ix.CompileM.BlockState} {name : Ix.Name} {hash addr : Address} - {refIdx : UInt64} {value : Lean4Lean.VExpr} + {refIdx : UInt64} {value : Ix.Theory.Named.VExpr} (hstate : FrozenExprStateWF compileEnv blockEnv levelSupport snapshot state) (hmut : blockEnv.mutCtx.get? name = none) (hresolve : resolveConstAddr? compileEnv snapshot name = some addr) @@ -2317,9 +2317,9 @@ theorem compileExpr_run_lit_refines Ix.CompileM.exprCompileDepth] using hrun theorem compileExpr_run_lit_value - {venv : Lean4Lean.VEnv} {sctx : SourceCtx} {catalog : Catalog} + {venv : Ix.Theory.Named.VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {trProj : ProjectionRel} - {uvars : Nat} {locals : List Lean4Lean.VExpr} + {uvars : Nat} {locals : List Ix.Theory.Named.VExpr} (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) (snapshot : Ix.CompileM.BlockState) {levelSupport : Ix.Level → Prop} @@ -2328,7 +2328,7 @@ theorem compileExpr_run_lit_value (hctx : RefCompileCtxRel (frozenRefCompileCtx compileEnv blockEnv snapshot) sctx catalog dctx) {state : Ix.CompileM.BlockState} {literal : Lean.Literal} {hash : Address} - {refIdx : UInt64} {value : Lean4Lean.VExpr} + {refIdx : UInt64} {value : Ix.Theory.Named.VExpr} (hstate : FrozenExprStateWF compileEnv blockEnv levelSupport snapshot state) (hpreseed : snapshot.refsIndex.get? (literalAddress literal) = some refIdx) (hsource : SourceExprRel (uvars := uvars) venv sctx trProj locals @@ -2460,18 +2460,18 @@ theorem compileExpr_run_structural_refines exact hrun /-- The production result in the structural fragment therefore denotes the -same independent Lean4Lean value as its named Ix source. -/ +same independent Ix.Theory.Named value as its named Ix source. -/ theorem compileExpr_run_structural_value - {venv : Lean4Lean.VEnv} {sctx : SourceCtx} {catalog : Catalog} + {venv : Ix.Theory.Named.VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {ctx : RefCompileCtx} {trProj : ProjectionRel} - {uvars : Nat} {locals : List Lean4Lean.VExpr} + {uvars : Nat} {locals : List Ix.Theory.Named.VExpr} (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) (hfree : compileEnv.surgeryFree = true) (hfaithful : ExprKeyFaithfulOn StructuralExpr) (hctx : RefCompileCtxRel ctx sctx catalog dctx) {state : Ix.CompileM.BlockState} {source : Ix.Expr} - {target : Ixon.Expr} {value : Lean4Lean.VExpr} + {target : Ixon.Expr} {value : Ix.Theory.Named.VExpr} (hstruct : StructuralExpr source) (hstate : StructuralExprCacheWF ctx state) (hsource : SourceExprRel (uvars := uvars) venv sctx trProj locals source value) @@ -4140,12 +4140,12 @@ theorem compileExpr_run_ordinary_wireWF hlevelFaithful hexprFaithful hsource hstate href exact ⟨root, state', hrun, hstate', compileExprRef_wireWF hbound href⟩ -/-- Complete ordinary compilation preserves the independent Lean4Lean value +/-- Complete ordinary compilation preserves the independent Ix.Theory.Named value assigned to the source expression. -/ theorem compileExpr_run_ordinary_value - {venv : Lean4Lean.VEnv} {sctx : SourceCtx} {catalog : Catalog} + {venv : Ix.Theory.Named.VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {trProj : ProjectionRel} - {uvars : Nat} {locals : List Lean4Lean.VExpr} + {uvars : Nat} {locals : List Ix.Theory.Named.VExpr} (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) (snapshot : Ix.CompileM.BlockState) {levelSupport : Ix.Level → Prop} @@ -4156,7 +4156,7 @@ theorem compileExpr_run_ordinary_value (hctx : RefCompileCtxRel (frozenRefCompileCtx compileEnv blockEnv snapshot) sctx catalog dctx) {state : Ix.CompileM.BlockState} {source : Ix.Expr} - {target : Ixon.Expr} {value : Lean4Lean.VExpr} + {target : Ixon.Expr} {value : Ix.Theory.Named.VExpr} (hordinary : SupportedOrdinaryExpr levelSupport source) (hstate : FrozenExprStateWF compileEnv blockEnv levelSupport snapshot state) (hsource : SourceExprRel (uvars := uvars) venv sctx trProj locals source value) @@ -4320,9 +4320,9 @@ theorem compileExpr_run_ordinary_arena_refines /-- The strengthened public theorem exposes canonical value preservation and the faithful presentation sidecar in one result. -/ theorem compileExpr_run_ordinary_arena_value - {venv : Lean4Lean.VEnv} {sctx : SourceCtx} {catalog : Catalog} + {venv : Ix.Theory.Named.VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {trProj : ProjectionRel} - {uvars : Nat} {locals : List Lean4Lean.VExpr} + {uvars : Nat} {locals : List Ix.Theory.Named.VExpr} (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) (snapshot : Ix.CompileM.BlockState) {levelSupport : Ix.Level → Prop} @@ -4333,7 +4333,7 @@ theorem compileExpr_run_ordinary_arena_value (hctx : RefCompileCtxRel (frozenRefCompileCtx compileEnv blockEnv snapshot) sctx catalog dctx) {state : Ix.CompileM.BlockState} {source : Ix.Expr} - {target : Ixon.Expr} {value : Lean4Lean.VExpr} + {target : Ixon.Expr} {value : Ix.Theory.Named.VExpr} (hordinary : SupportedOrdinaryExpr levelSupport source) (hstate : FrozenExprStateWF compileEnv blockEnv levelSupport snapshot state) (harena : ArenaCacheWF state) diff --git a/Ix/Compile/Verify/CompilePreseed.lean b/Ix/Compile/Verify/CompilePreseed.lean index 2611fa215..5fee400be 100644 --- a/Ix/Compile/Verify/CompilePreseed.lean +++ b/Ix/Compile/Verify/CompilePreseed.lean @@ -1,5 +1,5 @@ import Ix.Compile.Verify.CompileConstantCodec -import Lean4Lean.Verify.QSort +import Ix.Theory.Named.Verify.QSort /-! # Production expression-table preseeding @@ -350,7 +350,9 @@ theorem PreseedCollectionWireWF.pushUniv theorem addressBlake3_wire (bytes : ByteArray) : (Address.blake3 bytes).hash.size = 32 := by - exact (Blake3.Rust.hash bytes).property + exact (Blake3.HasherOps.finalizeWithLength + (Blake3.Rust.hasherUpdate (Blake3.Rust.hasherInit ()) bytes) 32 (by + rcases System.Platform.numBits_eq with bits | bits <;> rw [bits] <;> decide)).property /-- Conservative number of reference payloads a source walk can append. Seen-set deduplication can only decrease this cost. -/ diff --git a/Ix/Compile/Verify/CompileUniv.lean b/Ix/Compile/Verify/CompileUniv.lean index 6f5fe1e58..f548ee31b 100644 --- a/Ix/Compile/Verify/CompileUniv.lean +++ b/Ix/Compile/Verify/CompileUniv.lean @@ -2,6 +2,8 @@ import Ix.Compile.Verify.CompileState import Ix.Compile.Verify.Reference import Std.Data.HashMap.Lemmas +open Ix.Theory (VLevel) + /-! # Production universe-compiler refinement @@ -689,7 +691,7 @@ theorem compileAndInternUnivCanon_run_refines rw [run_bind compileEnv blockEnv canonState _ _, horiginalRun] rfl -/-- The production result therefore has the independent Lean4Lean universe +/-- The production result therefore has the independent Ix.Theory.Named universe value assigned to the named source level. -/ theorem compileUniv_run_value (compileEnv : Ix.CompileM.CompileEnv) (blockEnv : Ix.CompileM.BlockEnv) diff --git a/Ix/Compile/Verify/IxonValue.lean b/Ix/Compile/Verify/IxonValue.lean index 84358438e..41f25cd50 100644 --- a/Ix/Compile/Verify/IxonValue.lean +++ b/Ix/Compile/Verify/IxonValue.lean @@ -1,12 +1,14 @@ import Ix.Ixon -import Lean4Lean.Theory.Literals -import Lean4Lean.Theory.Typing.Env +import Ix.Theory.Named.Literals +import Ix.Theory.Named.Typing.Env + +open Ix.Theory (VLevel) /-! -# Ixon v2 expressions and Lean4Lean values +# Ixon v2 expressions and Ix.Theory.Named values This is the first compiler-facing semantic boundary. It interprets an Ixon -expression directly as a Lean4Lean `VExpr`; it does not run Ix.Tc and does not +expression directly as a Ix.Theory.Named `VExpr`; it does not run Ix.Kernel and does not use checker acceptance as a specification. The relation is table-aware. It resolves universe, reference, mutual-member, @@ -19,7 +21,7 @@ available to later substructural passes without changing the Lean meaning. namespace Ix.Compile.Verify -open Lean4Lean (VConstant VEnv VExpr VLevel) +open Ix.Theory.Named (VConstant VEnv VExpr) /-- Immutable semantic views needed to interpret an Ixon expression. -/ structure Catalog where @@ -70,7 +72,7 @@ def DecodeCtx.univArgs? (ctx : DecodeCtx) (idxs : Array UInt64) : /-- Projection interpretation is supplied by the surrounding declaration model. Its universe/local-context indices match the existing raw Theory -boundary, while this module remains independent of Ix.Tc. -/ +boundary, while this module remains independent of Ix.Kernel. -/ abbrev ProjectionRel := Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop @@ -81,7 +83,7 @@ def none : ProjectionRel := fun _ _ _ _ _ _ => False end ProjectionRel -/-- Direct semantic relation from table-indexed Ixon syntax to Lean4Lean +/-- Direct semantic relation from table-indexed Ixon syntax to Ix.Theory.Named syntax. This is a raw representation relation: typing and source-kernel well-formedness are separate obligations. -/ inductive IxonExprRel (venv : VEnv) (catalog : Catalog) (dctx : DecodeCtx) @@ -307,7 +309,7 @@ theorem eraseModes_iff {venv : VEnv} {catalog : Catalog} {dctx : DecodeCtx} end IxonExprRel -/-- Honest boundary for source-kernel meaning while upstream Lean4Lean +/-- Honest boundary for source-kernel meaning while upstream Ix.Theory.Named construction remains incomplete. Compiler theorems consume this explicit witness; no axiom is needed for the structural Ixon conversion itself. -/ structure KernelSourceWitness where diff --git a/Ix/Compile/Verify/Reference.lean b/Ix/Compile/Verify/Reference.lean index 9a5610c02..327e47377 100644 --- a/Ix/Compile/Verify/Reference.lean +++ b/Ix/Compile/Verify/Reference.lean @@ -1,6 +1,8 @@ import Ix.Compile.Verify.Catalog import Ix.Environment -import Lean4Lean.Std.Basic +import Ix.Theory.Named.Std.Basic + +open Ix.Theory (VLevel) /-! # Total ordinary-fragment compiler specification @@ -35,7 +37,7 @@ def compileUnivRef (paramIndex : Ix.Name → Option UInt64) : /-- Independent Theory reading of a named Ix universe under the same positional parameter assignment. -/ def sourceUnivValue (paramIndex : Ix.Name → Option UInt64) : - Ix.Level → Option Lean4Lean.VLevel + Ix.Level → Option Ix.Theory.VLevel | .zero _ => some .zero | .succ level _ => return .succ (← sourceUnivValue paramIndex level) | .max left right _ => @@ -161,8 +163,8 @@ private theorem array_mapM_size_of_eq_some {f : α → Option β} have hmapped := congrArg (Option.map Array.toList) h change Array.toList <$> xs.mapM f = Option.map Array.toList (some ys) at hmapped rw [Array.toList_mapM] at hmapped - have hlength := Lean4Lean.List.Forall₂.length_eq - (Lean4Lean.List.mapM_eq_some.mp hmapped) + have hlength := Ix.Theory.Named.List.Forall₂.length_eq + (Ix.Theory.Named.List.mapM_eq_some.mp hmapped) simpa using hlength.symm /-- Reference compilation preserves the three root-spine lengths used by the diff --git a/Ix/Compile/Verify/SourceValue.lean b/Ix/Compile/Verify/SourceValue.lean index 04fe77053..54051328a 100644 --- a/Ix/Compile/Verify/SourceValue.lean +++ b/Ix/Compile/Verify/SourceValue.lean @@ -1,10 +1,12 @@ import Ix.Compile.Verify.Reference +open Ix.Theory (VLevel) + /-! # Source-to-Ixon value preservation This module closes the first expression-level compiler square. `SourceExprRel` -gives a named `Ix.Expr` an independent Lean4Lean meaning. `RefCompileCtxRel` +gives a named `Ix.Expr` an independent Ix.Theory.Named meaning. `RefCompileCtxRel` states that the finite indices chosen by `compileExprRef` point at the same universes, names, and literal bytes in the target tables. The preservation theorem then constructs `IxonExprRel` for the exact compiler result. @@ -12,7 +14,7 @@ theorem then constructs `IxonExprRel` for the exact compiler result. namespace Ix.Compile.Verify -open Lean4Lean (VConstant VEnv VExpr VLevel) +open Ix.Theory.Named (VConstant VEnv VExpr) /-- Independent semantic interpretation choices for named source syntax. -/ structure SourceCtx where @@ -114,7 +116,7 @@ structure RefCompileCtxRel (compile : RefCompileCtx) (source : SourceCtx) String.fromUTF8? bytes = some value /-- Ordinary reference compilation preserves the independently stated -Lean4Lean value. -/ +Ix.Theory.Named value. -/ theorem compileExprRef_value {venv : VEnv} {sctx : SourceCtx} {catalog : Catalog} {dctx : DecodeCtx} {compile : RefCompileCtx} {trProj : ProjectionRel} {uvars : Nat} {locals : List VExpr} diff --git a/Ix/Compile/Verify/Statements.lean b/Ix/Compile/Verify/Statements.lean index 83c9d5cbe..5e53765a5 100644 --- a/Ix/Compile/Verify/Statements.lean +++ b/Ix/Compile/Verify/Statements.lean @@ -27,7 +27,7 @@ import Ix.Compile.Verify.SourceValue /-! # Public compiler-verification frontier -The first slice exports a direct, table-aware Ixon-to-Lean4Lean relation, the +The first slice exports a direct, table-aware Ixon-to-Ix.Theory.Named relation, the constructive theorem that v2 binder modes do not change the related Theory value, a total ordinary-fragment reference compiler, and proofs that its universe values are preserved and its expression outputs inhabit the @@ -158,14 +158,14 @@ digest-key faithfulness, well-addressed v2 expression tables and constants, and refinement proofs for the production reference/universe interning operations through `CompileM.run`. Production `compileUniv` is structurally total and refines the reference compiler while preserving both memo-cache -soundness and the independent Lean4Lean universe value. In surgery-free +soundness and the independent Ix.Theory.Named universe value. In surgery-free environments, production `compileExpr` now selects a kernel-visible total path; its recursive structural fragment refines `compileExprRef`, preserves a sound collision-disciplined expression cache, retains flattened App-spine -semantics, and composes with the independent Lean4Lean expression value. A +semantics, and composes with the independent Ix.Theory.Named expression value. A frozen-preseed state relation now closes the complete ordinary-expression tree through the actual production dispatcher, including arbitrary-universe -local and external constants, recursive projections, and their Lean4Lean +local and external constants, recursive projections, and their Ix.Theory.Named value corollary. The strengthened theorem also exposes a structural `ArenaRel` for the returned metadata root, preserves every warm-cache root under append-only growth, and makes the `UInt64` arena-capacity boundary @@ -211,6 +211,6 @@ for every variant in the explicit wire domain, with arbitrary canonical application, lambda, and forall spines in every expression payload. `KernelSourceWitness` is the sole upstream source-semantics boundary; later compiler-preservation slices take it -as an explicit hypothesis until Lean4Lean can construct it for a replayed Lean +as an explicit hypothesis until Ix.Theory.Named can construct it for a replayed Lean environment. -/ diff --git a/Ix/Environment.lean b/Ix/Environment.lean index 4bb2c6c3f..6726d69c6 100644 --- a/Ix/Environment.lean +++ b/Ix/Environment.lean @@ -114,7 +114,7 @@ instance : ToString Name where /-- Dot-separated bare rendering — byte-for-byte mirror of the Rust `Name::pretty` (str components verbatim, num components as plain digits, NO `«»` escaping). The kernel's canonical aux ordering seeds - on this exact string (`Ix.Tc.canonicalAuxOrder` ↔ Rust + on this exact string (`Ix.Kernel.canonicalAuxOrder` ↔ Rust `canonical_aux_order`), so `toString` (which escapes nums as `«n»`) must not be substituted there. -/ partial def pretty : Name → String diff --git a/Ix/IxVM/ClaimHarness.lean b/Ix/IxVM/ClaimHarness.lean index 45446a614..6a7539321 100644 --- a/Ix/IxVM/ClaimHarness.lean +++ b/Ix/IxVM/ClaimHarness.lean @@ -5,7 +5,7 @@ public import Ix.Claim public import Ix.AssumptionTree public import Ix.CompileM public import Ix.Common -public import Ix.Tc.Primitive +public import Ix.Kernel.Primitive public section @@ -357,7 +357,7 @@ private def seedTreeAt (root : Address) key`. -/ def closureFrom (env : Ixon.Env) (target : Address) : Std.HashSet Address := closureFromRoots env - (#[target] ++ Ix.Tc.primAddrSet.toArray.filter env.consts.contains) + (#[target] ++ Ix.Kernel.primAddrSet.toArray.filter env.consts.contains) /-- Serializes `claim`, seeds its bytes at `key = blake3(claim)`, and populates the IOBuffer with the `closureFrom` byte scope of every @@ -468,7 +468,7 @@ def shardCheckEnvClaimTrees (env : Ixon.Env) (owned : Array Address) : def shardCheckEnvClaim (env : Ixon.Env) (owned : Array Address) : Except String (Ix.Claim × Std.HashSet Address × Std.HashMap Address Ix.AssumptionTree) := do let (claim, trees) ← shardCheckEnvClaimTrees env owned - let primitiveRoots := Ix.Tc.primAddrSet.toArray.filter env.consts.contains + let primitiveRoots := Ix.Kernel.primAddrSet.toArray.filter env.consts.contains let closure := closureFromRoots env (owned ++ primitiveRoots) pure (claim, closure, trees) diff --git a/Ix/IxVM/Kernel/DefEq.lean b/Ix/IxVM/Kernel/DefEq.lean index 4c5567354..92e87b083 100644 --- a/Ix/IxVM/Kernel/DefEq.lean +++ b/Ix/IxVM/Kernel/DefEq.lean @@ -851,7 +851,7 @@ def defEq := ⟦ -- binder type, not out of `ty_a`, and the ensuing Lam/Lam comparison -- is what checks the two domains agree. Rust `try_eta_expansion` -- (`def_eq.rs:1179-1211`) infers `s`, whnfs to `All`, and takes that - -- `ty`; `Ix/Tc` `tryEtaExpansion` (`DefEq.lean:946-951`) does the same + -- `ty`; `Ix/Kernel` `tryEtaExpansion` (`DefEq.lean:946-951`) does the same -- via `inferOnlyCall`; lean4lean `tryEtaExpansionCore` -- (`TypeChecker.lean:507-511`) is `let .forallE name ty _ bi ← whnf -- (← inferType s)`. @@ -891,7 +891,7 @@ def defEq := ⟦ -- SEMANTIC on purpose — `level_equal`, matching `is_inductive_prop` -- (`Infer.lean:260`) and all three references: Rust gates both struct- -- eta (`whnf.rs:1884`) and proof irrelevance (`def_eq.rs:878`) on - -- `KUniv::is_semantic_zero`, `Ix/Tc` on `isSemanticZero` + -- `KUniv::is_semantic_zero`, `Ix/Kernel` on `isSemanticZero` -- (`Whnf.lean:1139`, `DefEq.lean:817`), and lean4lean's `isProp` on -- `Level.isAlwaysZero` (`TypeChecker.lean:230`), all of which normalize. -- diff --git a/Ix/IxVM/Kernel/Infer.lean b/Ix/IxVM/Kernel/Infer.lean index 3f7762dc4..1edfccc20 100644 --- a/Ix/IxVM/Kernel/Infer.lean +++ b/Ix/IxVM/Kernel/Infer.lean @@ -428,7 +428,7 @@ def infer := ⟦ -- Sort is malformed, and both references that implement this ERROR -- rather than answering — Rust `inductive_app_is_prop` -- (`infer.rs:485-517`, "projection: expected forall in inductive - -- type", then `ensure_sort`) and `Ix/Tc` `inductiveAppIsProp` + -- type", then `ensure_sort`) and `Ix/Kernel` `inductiveAppIsProp` -- (`Infer.lean:296-324`), with the same message. lean4lean has no -- counterpart: `inferProj` infers the type of the APPLIED struct -- expression instead and never peels the declaration's telescope, so @@ -568,7 +568,7 @@ def infer := ⟦ -- No fallthrough arm: a value whose type does not whnf to a Sort is not -- a type, and the references error there too (Rust `ensure_sort`, - -- `tc.rs:648-658`, returns `TcError::TypeExpected`; `Ix/Tc` + -- `tc.rs:648-658`, returns `TcError::TypeExpected`; `Ix/Kernel` -- `ensureSortWhnf` throws `.typeExpected`). Do not give it a default -- level — that would make an ill-typed `Lam` usable as a type. fn k_ensure_sort(e: KExpr, types: List‹KExpr›) -> KLevel { diff --git a/Ix/IxVM/Kernel/Whnf.lean b/Ix/IxVM/Kernel/Whnf.lean index bd89e681c..259d23b77 100644 --- a/Ix/IxVM/Kernel/Whnf.lean +++ b/Ix/IxVM/Kernel/Whnf.lean @@ -364,13 +364,13 @@ def whnf := ⟦ -- Dispatch is on the ADDRESS alone, and the stored `QuotKind` is not -- consulted. All three references decide this way — Rust -- `try_quot_reduce` (`whnf.rs:3073-3120`) compares against - -- `self.prims.quot_lift.addr` / `quot_ind.addr`, `Ix/Tc` + -- `self.prims.quot_lift.addr` / `quot_ind.addr`, `Ix/Kernel` -- `tryQuotReduce` (`Whnf.lean:1674-1698`) against `p.quotLift.addr` / -- `p.quotInd.addr`, and lean4lean `quotReduceRec` (`Quot.lean:85-100`) -- against the names `Quot.lift` / `Quot.ind`. -- -- The kind field is a checked REDUNDANCY, not a dispatch input: Rust's - -- `check_quot` and `Ix/Tc`'s `checkQuot` both DERIVE the expected kind + -- `check_quot` and `Ix/Kernel`'s `checkQuot` both DERIVE the expected kind -- from the address and assert the stored one matches. Reduction runs -- before any of that — `get_ci` typechecks nothing — so keying on the -- kind would trust a field no one has validated yet. @@ -424,7 +424,7 @@ def whnf := ⟦ -- The head is recognised by ADDRESS and the arity must be exactly 3, -- which is all the references look at: Rust -- `if *mk_addr != self.prims.quot_ctor.addr { return Ok(None) }` then - -- `if mk_args.len() != 3` (`whnf.rs:3108`), `Ix/Tc` the same against + -- `if mk_args.len() != 3` (`whnf.rs:3108`), `Ix/Kernel` the same against -- `p.quotCtor.addr` (`Whnf.lean:1690-1698`), lean4lean -- `if !mk.isAppOfArity ``Quot.mk 3` (`Quot.lean:88`). No `get_ci`, no -- stored kind — the constant need not even be resolvable for this to diff --git a/Ix/IxonUniv.lean b/Ix/IxonUniv.lean index 922372c41..94d96a03a 100644 --- a/Ix/IxonUniv.lean +++ b/Ix/IxonUniv.lean @@ -12,7 +12,7 @@ Mirror: crates/ixon/src/canon_univ.rs deterministic canonical representative of a stored level's Géran semantic-equality class, kernel-free and next to the wire type so `Ix.CompileM`, the Tc egress, and probes can all use it. The Géran -machinery is the transliteration of `Ix/Tc/Level.lean:227-472` onto +machinery is the transliteration of `Ix/Kernel/Level.lean:227-472` onto `Ixon.Univ` (positional `var` indices; no metadata); the three kernel `NormLevel` implementations stay untouched and serve as the P4 oracle. @@ -20,10 +20,10 @@ The frozen kernel `mk*` rule set (M1–M8 / I1–I6) is kept with its kernel-rebuild role: `reduceUniv` is the stage-1 decoration-presence test and the P6 oracle, and P3 (canonical forms are `mk*` fixpoints) is what makes kernel ingress the identity on canonical content. -(`Ix.Tc.reduceIxonUniv` computes the same closure by rounding through +(`Ix.Kernel.reduceIxonUniv` computes the same closure by rounding through the actual kernel constructors; `tc-unit` pins their agreement.) -Property set (tested in `Tests/Ix/Tc/Unit.lean` and the Rust twin; +Property set (tested in `Tests/Ix/Kernel/Unit.lean` and the Rust twin; Verify-layer proofs are the D7 follow-up): P1 idempotence; P2 roundtrip-fixpoint (`normalize (linearize L) = L`, exact on non-empty entries — `subsumption` can leave EMPTY entries which `linearize` @@ -42,7 +42,7 @@ namespace Ixon namespace Univ /-- Constructor count — termination measure for the normalization - family (mirrors `Ix.Tc.KUniv.size`). -/ + family (mirrors `Ix.Kernel.KUniv.size`). -/ def size : Univ → Nat | .zero => 1 | .succ u => u.size + 1 @@ -81,7 +81,7 @@ end Univ /-- `mkMax` of the frozen kernel rule set (M1–M8), on `Ixon.Univ`: numerals → the larger (ties → `a`); `max a a = a`; zero sides; - absorption; same-base offsets; raw. Mirrors `Ix.Tc.KUniv.mkMax` / + absorption; same-base offsets; raw. Mirrors `Ix.Kernel.KUniv.mkMax` / Rust `canon_univ::n_max`. -/ def nMax (a b : Univ) : Univ := if a.isExplicit && b.isExplicit then @@ -126,7 +126,7 @@ def nIMax (a b : Univ) : Univ := A non-fixpoint entry reaches the kernel changed (the stage-1 decoration-presence test); P6 pins that this rebuild refines into the Géran classes. `tc-unit` pins agreement with - `Ix.Tc.reduceIxonUniv` (the same closure via the kernel's own + `Ix.Kernel.reduceIxonUniv` (the same closure via the kernel's own constructors). -/ def reduceUniv : Univ → Univ | .zero => .zero @@ -157,7 +157,7 @@ abbrev CNorm := RBTree.RBMap CPath CNode compare instance : Inhabited CNorm := ⟨.empty⟩ /-- Insert `(idx, k)` into the sorted var list, max-merging offsets. - `k` must be the current succ-accumulator (`Ix/Tc/Level.lean:249-252` + `k` must be the current succ-accumulator (`Ix/Kernel/Level.lean:249-252` — dropping it is the classic port bug). -/ def CNode.addVar (n : CNode) (idx k : UInt64) : CNode := match n.vars.findIdx? (fun v => idx ≤ v.1) with @@ -187,13 +187,13 @@ def orderedInsert (a : UInt64) : CPath → Option CPath else (x :: ·) <$> orderedInsert a xs /-! -Termination mirrors `Ix/Tc/Level.lean:289-296`: the measure is +Termination mirrors `Ix/Kernel/Level.lean:289-296`: the measure is `3·Σ Univ.size + {0,1,2}` ordering the equal-size hops between the mutual members. -/ mutual -/-- Flatten a level into canonical form (`Ix.Tc.Level.normalizeAux` on +/-- Flatten a level into canonical form (`Ix.Kernel.Level.normalizeAux` on `Ixon.Univ`). `path` is the imax-conditioning chain, `k` the accumulated succ offset. -/ def normalizeAux (l : Univ) (path : CPath) (k : UInt64) (acc : CNorm) : @@ -276,7 +276,7 @@ def isSubset : CPath → CPath → Bool else false /-- Keep only the `xs` entries not dominated by a `ys` entry - (merge-walk over sorted var lists — `Ix.Tc.Level.subsumeVars`). -/ + (merge-walk over sorted var lists — `Ix.Kernel.Level.subsumeVars`). -/ def subsumeVars (xs ys : Array (UInt64 × UInt64)) : Array (UInt64 × UInt64) := go 0 0 #[] @@ -302,7 +302,7 @@ where decreasing_by all_goals omega /-- Drop contributions dominated by entries at sub-paths - (`Ix.Tc.Level.subsumption` — the in-loop `n1` mutations are + (`Ix.Kernel.Level.subsumption` — the in-loop `n1` mutations are order-sensitive). -/ def subsumption (acc : CNorm) : CNorm := Id.run do let snapshot := acc.toList diff --git a/Ix/Kernel.lean b/Ix/Kernel.lean new file mode 100644 index 000000000..91b1327b1 --- /dev/null +++ b/Ix/Kernel.lean @@ -0,0 +1,54 @@ +module + +public import Ix.Kernel.Mode +public import Ix.Kernel.Id +public import Ix.Kernel.Level +public import Ix.Kernel.Expr +public import Ix.Kernel.Error +public import Ix.Kernel.Const +public import Ix.Kernel.Equiv +public import Ix.Kernel.Env +public import Ix.Kernel.Primitive +public import Ix.Kernel.Subst +public import Ix.Kernel.Lctx +public import Ix.Kernel.Monad +public import Ix.Kernel.Ingress +public import Ix.Kernel.IngressMeta +public import Ix.Kernel.Egress +public import Ix.Kernel.EgressLean +public import Ix.Kernel.Driver +public import Ix.Kernel.ParCheck +public import Ix.Kernel.Validate +public import Ix.Kernel.Whnf +public import Ix.Kernel.Infer +public import Ix.Kernel.DefEq +public import Ix.Kernel.Knot +public import Ix.Kernel.CanonicalCheck +public import Ix.Kernel.Inductive +public import Ix.Kernel.Check + +/-! +# Ix.Kernel — pure-Lean Ix kernel over Ixon + +A correctness-first, formalizable port of the Rust Ix kernel +(`crates/kernel`), operating over the Ixon content-addressed format with +separated anon and meta modes. Designed for correctness and formalization; +for performance, use the Rust kernel. + +Module map (mirrors `crates/kernel/src/` file-for-file): + +| Lean module | Rust source | +|-------------------|----------------| +| `Ix.Kernel.Mode` | `mode.rs` | +| `Ix.Kernel.Id` | `id.rs` | +| `Ix.Kernel.Error` | `error.rs` | +| `Ix.Kernel.Level` | `level.rs` | +| `Ix.Kernel.Expr` | `expr.rs` | +| `Ix.Kernel.Const` | `constant.rs` | +| `Ix.Kernel.Equiv` | `equiv.rs` | +| `Ix.Kernel.Env` | `env.rs` | +| `Ix.Kernel.Primitive` | `primitive.rs` | +| `Ix.Kernel.Subst` | `subst.rs` | +| `Ix.Kernel.Lctx` | `lctx.rs` | +| `Ix.Kernel.Monad` | `tc.rs` | +-/ diff --git a/Ix/Tc/CanonicalCheck.lean b/Ix/Kernel/CanonicalCheck.lean similarity index 99% rename from Ix/Tc/CanonicalCheck.lean rename to Ix/Kernel/CanonicalCheck.lean index 0f6c82976..515fedc2c 100644 --- a/Ix/Tc/CanonicalCheck.lean +++ b/Ix/Kernel/CanonicalCheck.lean @@ -1,7 +1,7 @@ module -public import Ix.Tc.Const -public import Ix.Tc.Error +public import Ix.Kernel.Const +public import Ix.Kernel.Error /-! Mirror: crates/kernel/src/canonical_check.rs @@ -29,7 +29,7 @@ ctx hits compare positionally (weak), misses fall back to address order public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) @@ -465,7 +465,7 @@ def validateCanonicalBlockSinglePass (blockAddr : Address) | .eq, _ => throw (.nonCanonicalBlock blockAddr i .eq) | .gt, _ => throw (.nonCanonicalBlock blockAddr i .gt) -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Kernel/Certified.lean b/Ix/Kernel/Certified.lean new file mode 100644 index 000000000..6d37c9ee1 --- /dev/null +++ b/Ix/Kernel/Certified.lean @@ -0,0 +1,338 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Monad +import Ix.Certified.Ingress + +/-! The witness-assisted certified Ix.Kernel entry point. It reads the selected +closure from the actual lazy Ixon store and checks it against the modeled +policy. Its only reusable cache is the checked byte/decoder cache. Existing +inference flags, equivalence classes and judgment caches have no effect on +this entry point. Successful legacy checking does not create a receipt. -/ + +namespace Ix.Kernel + +open Ix.Certified Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Model.SetTheory + +universe v + +namespace TcM + +def checkCertified (fuel : Nat) (source : Ixon.Env) (profile : Profile) (target : Address) + (selection : InputSelection) (witness : ProofWitness Address) (cache : InputCache) : + TcM m (SourceReceipt.{v} source fuel profile target witness × InputCache) := fun state => + match checkSource? fuel source profile target selection witness cache with + | none => .error (.other "certified source, profile, resource or witness check failed") state + | some result => .ok result state + +/-- A successful TcM execution reflects the independent full validator, and +cannot be influenced by pre-existing kernel judgment caches or flags. -/ +theorem checkCertified_success {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} + {selection : InputSelection} {witness : ProofWitness Address} {cache nextCache : InputCache} + {before after : TcState m} {receipt : SourceReceipt.{v} source fuel profile target witness} + (h : (checkCertified fuel source profile target selection witness cache).run before = + .ok (receipt, nextCache) after) : + checkSource? fuel source profile target selection witness cache = some (receipt, nextCache) ∧ + after = before := by + unfold checkCertified EStateM.run at h + cases hc : checkSource? fuel source profile target selection witness cache with + | none => simp [hc] at h + | some result => + simp only [hc, EStateM.Result.ok.injEq] at h + rcases h with ⟨rfl, rfl⟩ + exact ⟨rfl, rfl⟩ + +/-- On failure the entire caller state is unchanged. No admission receipt or +partially populated cache escapes the failed source transaction. -/ +theorem checkCertified_failure {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} + {selection : InputSelection} {witness : ProofWitness Address} {cache : InputCache} + {before after : TcState m} {error : TcError m} + (h : (checkCertified.{v} fuel source profile target selection witness cache).run before = + .error error after) : + checkSource?.{v} fuel source profile target selection witness cache = none ∧ after = before := by + unfold checkCertified EStateM.run at h + cases hc : checkSource?.{v} fuel source profile target selection witness cache with + | none => + simp only [hc, EStateM.Result.error.injEq] at h + exact ⟨rfl, h.2.symm⟩ + | some result => simp [hc] at h + +end TcM + +/-- Anonymous initialization constructs IDs directly. It does not evaluate +meta-mode display-name hashing, whose legacy implementation carries native +proof leaves. The certified primitive signature is checked separately. -/ +def initialCertifiedPrimitives : Primitives .anon where + nat := ⟨PrimAddrs.canonical.nat, ()⟩ + natZero := ⟨PrimAddrs.canonical.natZero, ()⟩ + natSucc := ⟨PrimAddrs.canonical.natSucc, ()⟩ + natAdd := ⟨PrimAddrs.canonical.natAdd, ()⟩ + natPred := ⟨PrimAddrs.canonical.natPred, ()⟩ + natSub := ⟨PrimAddrs.canonical.natSub, ()⟩ + natMul := ⟨PrimAddrs.canonical.natMul, ()⟩ + natPow := ⟨PrimAddrs.canonical.natPow, ()⟩ + natGcd := ⟨PrimAddrs.canonical.natGcd, ()⟩ + natMod := ⟨PrimAddrs.canonical.natMod, ()⟩ + natDiv := ⟨PrimAddrs.canonical.natDiv, ()⟩ + natBitwise := ⟨PrimAddrs.canonical.natBitwise, ()⟩ + natBeq := ⟨PrimAddrs.canonical.natBeq, ()⟩ + natBle := ⟨PrimAddrs.canonical.natBle, ()⟩ + natLand := ⟨PrimAddrs.canonical.natLand, ()⟩ + natLor := ⟨PrimAddrs.canonical.natLor, ()⟩ + natXor := ⟨PrimAddrs.canonical.natXor, ()⟩ + natShiftLeft := ⟨PrimAddrs.canonical.natShiftLeft, ()⟩ + natShiftRight := ⟨PrimAddrs.canonical.natShiftRight, ()⟩ + boolType := ⟨PrimAddrs.canonical.boolType, ()⟩ + boolTrue := ⟨PrimAddrs.canonical.boolTrue, ()⟩ + boolFalse := ⟨PrimAddrs.canonical.boolFalse, ()⟩ + string := ⟨PrimAddrs.canonical.string, ()⟩ + stringMk := ⟨PrimAddrs.canonical.stringMk, ()⟩ + charType := ⟨PrimAddrs.canonical.charType, ()⟩ + charMk := ⟨PrimAddrs.canonical.charMk, ()⟩ + charOfNat := ⟨PrimAddrs.canonical.charOfNat, ()⟩ + stringOfList := ⟨PrimAddrs.canonical.stringOfList, ()⟩ + stringToByteArray := ⟨PrimAddrs.canonical.stringToByteArray, ()⟩ + byteArrayEmpty := ⟨PrimAddrs.canonical.byteArrayEmpty, ()⟩ + list := ⟨PrimAddrs.canonical.list, ()⟩ + listNil := ⟨PrimAddrs.canonical.listNil, ()⟩ + listCons := ⟨PrimAddrs.canonical.listCons, ()⟩ + eq := ⟨PrimAddrs.canonical.eq, ()⟩ + eqRefl := ⟨PrimAddrs.canonical.eqRefl, ()⟩ + quotType := ⟨PrimAddrs.canonical.quotType, ()⟩ + quotCtor := ⟨PrimAddrs.canonical.quotCtor, ()⟩ + quotLift := ⟨PrimAddrs.canonical.quotLift, ()⟩ + quotInd := ⟨PrimAddrs.canonical.quotInd, ()⟩ + reduceBool := ⟨PrimAddrs.canonical.reduceBool, ()⟩ + reduceNat := ⟨PrimAddrs.canonical.reduceNat, ()⟩ + eagerReduce := ⟨PrimAddrs.canonical.eagerReduce, ()⟩ + systemPlatformNumBits := ⟨PrimAddrs.canonical.systemPlatformNumBits, ()⟩ + systemPlatformGetNumBits := ⟨PrimAddrs.canonical.systemPlatformGetNumBits, ()⟩ + subtypeVal := ⟨PrimAddrs.canonical.subtypeVal, ()⟩ + natDecLe := ⟨PrimAddrs.canonical.natDecLe, ()⟩ + natDecEq := ⟨PrimAddrs.canonical.natDecEq, ()⟩ + natDecLt := ⟨PrimAddrs.canonical.natDecLt, ()⟩ + decidableRec := ⟨PrimAddrs.canonical.decidableRec, ()⟩ + decidableIsTrue := ⟨PrimAddrs.canonical.decidableIsTrue, ()⟩ + decidableIsFalse := ⟨PrimAddrs.canonical.decidableIsFalse, ()⟩ + natLeOfBleEqTrue := ⟨PrimAddrs.canonical.natLeOfBleEqTrue, ()⟩ + natNotLeOfNotBleEqTrue := ⟨PrimAddrs.canonical.natNotLeOfNotBleEqTrue, ()⟩ + natEqOfBeqEqTrue := ⟨PrimAddrs.canonical.natEqOfBeqEqTrue, ()⟩ + natNeOfBeqEqFalse := ⟨PrimAddrs.canonical.natNeOfBeqEqFalse, ()⟩ + fin := ⟨PrimAddrs.canonical.fin, ()⟩ + boolNoConfusion := ⟨PrimAddrs.canonical.boolNoConfusion, ()⟩ + int := ⟨PrimAddrs.canonical.int, ()⟩ + intOfNat := ⟨PrimAddrs.canonical.intOfNat, ()⟩ + intNegSucc := ⟨PrimAddrs.canonical.intNegSucc, ()⟩ + intAdd := ⟨PrimAddrs.canonical.intAdd, ()⟩ + intSub := ⟨PrimAddrs.canonical.intSub, ()⟩ + intMul := ⟨PrimAddrs.canonical.intMul, ()⟩ + intNeg := ⟨PrimAddrs.canonical.intNeg, ()⟩ + intEmod := ⟨PrimAddrs.canonical.intEmod, ()⟩ + intEdiv := ⟨PrimAddrs.canonical.intEdiv, ()⟩ + intBmod := ⟨PrimAddrs.canonical.intBmod, ()⟩ + intBdiv := ⟨PrimAddrs.canonical.intBdiv, ()⟩ + intNatAbs := ⟨PrimAddrs.canonical.intNatAbs, ()⟩ + intPow := ⟨PrimAddrs.canonical.intPow, ()⟩ + intDecEq := ⟨PrimAddrs.canonical.intDecEq, ()⟩ + intDecLe := ⟨PrimAddrs.canonical.intDecLe, ()⟩ + intDecLt := ⟨PrimAddrs.canonical.intDecLt, ()⟩ + punit := ⟨PrimAddrs.canonical.punit, ()⟩ + natRec := ⟨PrimAddrs.canonical.natRec, ()⟩ + natCasesOn := ⟨PrimAddrs.canonical.natCasesOn, ()⟩ + bitVec := ⟨PrimAddrs.canonical.bitVec, ()⟩ + bitVecToNat := ⟨PrimAddrs.canonical.bitVecToNat, ()⟩ + bitVecOfNat := ⟨PrimAddrs.canonical.bitVecOfNat, ()⟩ + bitVecUlt := ⟨PrimAddrs.canonical.bitVecUlt, ()⟩ + decidableDecide := ⟨PrimAddrs.canonical.decidableDecide, ()⟩ + ltLt := ⟨PrimAddrs.canonical.ltLt, ()⟩ + ofNatOfNat := ⟨PrimAddrs.canonical.ofNatOfNat, ()⟩ + unit := ⟨PrimAddrs.canonical.unit, ()⟩ + punitSizeOf1 := ⟨PrimAddrs.canonical.punitSizeOf1, ()⟩ + sizeOfSizeOf := ⟨PrimAddrs.canonical.sizeOfSizeOf, ()⟩ + stringBack := ⟨PrimAddrs.canonical.stringBack, ()⟩ + stringLegacyBack := ⟨PrimAddrs.canonical.stringLegacyBack, ()⟩ + stringUtf8ByteSize := ⟨PrimAddrs.canonical.stringUtf8ByteSize, ()⟩ + stringAppend := ⟨PrimAddrs.canonical.stringAppend, ()⟩ + stringDecEq := ⟨PrimAddrs.canonical.stringDecEq, ()⟩ + +/-- State of the certified driver. Semantic judgments are never cached. -/ +structure CertifiedState where + checker : TcState .anon := TcState.new {} initialCertifiedPrimitives + inputCache : InputCache := {} + +/-- The public source program starts with empty kernel and byte caches. -/ +def initialCertifiedState : CertifiedState := {} + +def certifiedStep (fuel : Nat) (source : Ixon.Env) (profile : Profile) (target : Address) + (selection : InputSelection) (witness : ProofWitness Address) : + EStateM (TcError .anon) CertifiedState (SourceReceipt.{v} source fuel profile target witness) := fun state => + match (TcM.checkCertified fuel source profile target selection witness state.inputCache).run state.checker with + | .error error _ => .error error state + | .ok (receipt, cache) checker => .ok receipt ⟨checker, cache⟩ + +theorem certifiedStep_failure {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} + {selection : InputSelection} {witness : ProofWitness Address} + {before after : CertifiedState} {error : TcError .anon} + (h : (certifiedStep.{v} fuel source profile target selection witness).run before = .error error after) : + after = before := by + unfold certifiedStep EStateM.run at h + dsimp only at h + split at h + · exact (EStateM.Result.error.inj h).2.symm + · cases h + +/-- All reused cache entries still match current bytes, and every request +reruns full scope, policy, dependency, formation and proof validation. -/ +theorem certifiedStep_success {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} + {selection : InputSelection} {witness : ProofWitness Address} + {before after : CertifiedState} {receipt : SourceReceipt.{v} source fuel profile target witness} + (h : (certifiedStep fuel source profile target selection witness).run before = .ok receipt after) : + checkSource? fuel source profile target selection witness before.inputCache = + some (receipt, after.inputCache) ∧ after.checker = before.checker := by + unfold certifiedStep EStateM.run at h + dsimp only at h + split at h + · cases h + · rename_i pair checker he + rcases pair with ⟨result, cache⟩ + cases h + exact TcM.checkCertified_success he + +def runCertified (fuel : Nat) (source : Ixon.Env) (profile : Profile) (target : Address) + (selection : InputSelection) (witness : ProofWitness Address) : + Option (SourceReceipt.{v} source fuel profile target witness) := + match (certifiedStep fuel source profile target selection witness).run initialCertifiedState with + | .error _ _ => none + | .ok receipt _ => some receipt + +def acceptsCertifiedSource (fuel : Nat) (source : Ixon.Env) (profile : Profile) (target : Address) + (selection : InputSelection) (witness : ProofWitness Address) : Bool := + (runCertified.{v} fuel source profile target selection witness).isSome + +/-- Source success constructs every model premise from actual byte reads and +validator execution. There is no initial semantic model or cache oracle. -/ +theorem accepted_tc_has_model {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} + {selection : InputSelection} {witness : ProofWitness Address} + (h : acceptsCertifiedSource.{v} fuel source profile target selection witness = true) + (V : Type v) [SetTheory V] (levels : List Nat) (env : Nat → V) : + ∃ receipt : SourceReceipt.{v} source fuel profile target witness, + runCertified fuel source profile target selection witness = some receipt ∧ + (∀ address bytes, (address, bytes) ∈ receipt.snapshot.blobs → constantBytes? source address = some bytes) ∧ + (∀ address bytes, (address, bytes) ∈ receipt.snapshot.literalBlobs → source.getBlob? address = some bytes) ∧ + ∃ constants : Assignment Address V, + receipt.prepared.signature.Compatible receipt.proof.environment.entries constants ∧ + WellDenoted constants levels env receipt.proof.proof.val ∧ + WellDenoted constants levels env receipt.proof.proposition.val ∧ + interp constants levels env receipt.proof.proof.val ∈ˢ + interp constants levels env receipt.proof.proposition.val := by + unfold acceptsCertifiedSource at h + cases hr : runCertified.{v} fuel source profile target selection witness with + | none => simp [hr] at h + | some receipt => + exact ⟨receipt, rfl, fun _ _ he => receipt.snapshot.objects_from_source he, + fun _ _ he => receipt.snapshot.naturals_from_source he, receipt.has_model V levels env⟩ + +theorem no_tc_proof_of_False (receipt : SourceReceipt.{v} source fuel profile target witness) + (V : Type v) [SetTheory V] + (h : receipt.prepared.input.proposition = receipt.prepared.signature.falseExpr) : False := by + apply no_proof_of_False (fuel := fuel) (witness := witness) V h + simp only [acceptsCertified, receipt.checked, Option.isSome_some] + + +namespace TcM + +def checkStoreCertified (fuel : Nat) (source : Ixon.Env) (profile : Profile) (subjects : List Address) + (selection : InputSelection) (witness : List (DeclarationWitness Address)) (cache : InputCache) : + TcM m (StoreReceipt.{v} source fuel profile subjects witness × InputCache) := fun state => + match checkSourceStore? fuel source profile subjects selection witness cache with + | none => .error (.other "certified declaration, profile, resource or witness check failed") state + | some result => .ok result state + +theorem checkStoreCertified_success {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} + {selection : InputSelection} {witness : List (DeclarationWitness Address)} {cache nextCache : InputCache} + {before after : TcState m} {receipt : StoreReceipt.{v} source fuel profile subjects witness} + (h : (checkStoreCertified fuel source profile subjects selection witness cache).run before = + .ok (receipt, nextCache) after) : + checkSourceStore? fuel source profile subjects selection witness cache = some (receipt, nextCache) ∧ + after = before := by + unfold checkStoreCertified EStateM.run at h + cases hc : checkSourceStore? fuel source profile subjects selection witness cache with + | none => simp [hc] at h + | some result => + simp only [hc, EStateM.Result.ok.injEq] at h + rcases h with ⟨rfl, rfl⟩ + exact ⟨rfl, rfl⟩ + +end TcM + +def certifiedStoreStep (fuel : Nat) (source : Ixon.Env) (profile : Profile) (subjects : List Address) + (selection : InputSelection) (witness : List (DeclarationWitness Address)) : + EStateM (TcError .anon) CertifiedState (StoreReceipt.{v} source fuel profile subjects witness) := fun state => + match (TcM.checkStoreCertified fuel source profile subjects selection witness state.inputCache).run state.checker with + | .error error _ => .error error state + | .ok (receipt, cache) checker => .ok receipt ⟨checker, cache⟩ + +theorem certifiedStoreStep_failure {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} + {selection : InputSelection} {witness : List (DeclarationWitness Address)} + {before after : CertifiedState} {error : TcError .anon} + (h : (certifiedStoreStep.{v} fuel source profile subjects selection witness).run before = .error error after) : + after = before := by + unfold certifiedStoreStep EStateM.run at h + dsimp only at h + split at h + · exact (EStateM.Result.error.inj h).2.symm + · cases h + +theorem certifiedStoreStep_success {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} + {selection : InputSelection} {witness : List (DeclarationWitness Address)} + {before after : CertifiedState} {receipt : StoreReceipt.{v} source fuel profile subjects witness} + (h : (certifiedStoreStep fuel source profile subjects selection witness).run before = .ok receipt after) : + checkSourceStore? fuel source profile subjects selection witness before.inputCache = + some (receipt, after.inputCache) ∧ after.checker = before.checker := by + unfold certifiedStoreStep EStateM.run at h + dsimp only at h + split at h + · cases h + · rename_i pair checker he + rcases pair with ⟨result, cache⟩ + cases h + exact TcM.checkStoreCertified_success he + +def runCertifiedStore (fuel : Nat) (source : Ixon.Env) (profile : Profile) (subjects : List Address) + (selection : InputSelection) (witness : List (DeclarationWitness Address)) : + Option (StoreReceipt.{v} source fuel profile subjects witness) := + match (certifiedStoreStep fuel source profile subjects selection witness).run initialCertifiedState with + | .error _ _ => none + | .ok receipt _ => some receipt + +def acceptsCertifiedStoreSource (fuel : Nat) (source : Ixon.Env) (profile : Profile) (subjects : List Address) + (selection : InputSelection) (witness : List (DeclarationWitness Address)) : Bool := + (runCertifiedStore.{v} fuel source profile subjects selection witness).isSome + +/-- Complete declaration requests, including source blocks, construct a +single model realizing every requested member and constructor. -/ +theorem accepted_tc_store_has_model {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} + {selection : InputSelection} {witness : List (DeclarationWitness Address)} + (h : acceptsCertifiedStoreSource.{v} fuel source profile subjects selection witness = true) + (V : Type v) [SetTheory V] : + ∃ receipt : StoreReceipt.{v} source fuel profile subjects witness, + runCertifiedStore fuel source profile subjects selection witness = some receipt ∧ + (∀ address bytes, (address, bytes) ∈ receipt.snapshot.blobs → constantBytes? source address = some bytes) ∧ + (∀ address bytes, (address, bytes) ∈ receipt.snapshot.literalBlobs → source.getBlob? address = some bytes) ∧ + ∃ constants : Assignment Address V, + receipt.prepared.signature.Compatible receipt.result.environment.entries constants ∧ + ∀ r ∈ receipt.prepared.targets, ∃ entry, receipt.result.environment.entries r = some entry ∧ + EntrySource receipt.prepared.signature receipt.prepared.store r entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env : Nat → V, + WellDenoted constants levels env entry.type ∧ + constants r levels ∈ˢ interp constants levels env entry.type := by + unfold acceptsCertifiedStoreSource at h + cases hr : runCertifiedStore.{v} fuel source profile subjects selection witness with + | none => simp [hr] at h + | some receipt => + exact ⟨receipt, rfl, fun _ _ he => receipt.snapshot.objects_from_source he, + fun _ _ he => receipt.snapshot.naturals_from_source he, receipt.has_model V⟩ + +end Ix.Kernel diff --git a/Ix/Kernel/CertifiedClaims.lean b/Ix/Kernel/CertifiedClaims.lean new file mode 100644 index 000000000..581360880 --- /dev/null +++ b/Ix/Kernel/CertifiedClaims.lean @@ -0,0 +1,95 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Certified +import Ix.Certified.ClaimAccept + +namespace Ix.Kernel + +open Ix.Certified + +universe v + +namespace TcM + +def checkClaimCertified (fuel : Nat) (source : Ixon.Env) (address : Address) (bytes : ByteArray) + (witness : ClaimWitness) (cache : InputCache) : + TcM m (ClaimReceipt.{v} source fuel address bytes × InputCache) := fun state => + match checkClaimBytes? fuel source address bytes witness cache with + | none => .error (.other "certified claim, source, policy or witness check failed") state + | some result => .ok result state + +theorem checkClaimCertified_success {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} + {witness : ClaimWitness} {cache nextCache : InputCache} + {before after : TcState m} {receipt : ClaimReceipt.{v} source fuel address bytes} + (h : (checkClaimCertified fuel source address bytes witness cache).run before = + .ok (receipt, nextCache) after) : + checkClaimBytes? fuel source address bytes witness cache = some (receipt, nextCache) ∧ + after = before := by + unfold checkClaimCertified EStateM.run at h + cases hc : checkClaimBytes? fuel source address bytes witness cache with + | none => simp [hc] at h + | some result => + simp only [hc, EStateM.Result.ok.injEq] at h + rcases h with ⟨rfl, rfl⟩ + exact ⟨rfl, rfl⟩ + +end TcM + +def certifiedClaimStep (fuel : Nat) (source : Ixon.Env) (address : Address) (bytes : ByteArray) + (witness : ClaimWitness) : + EStateM (TcError .anon) CertifiedState (ClaimReceipt.{v} source fuel address bytes) := fun state => + match (TcM.checkClaimCertified fuel source address bytes witness state.inputCache).run state.checker with + | .error error _ => .error error state + | .ok (receipt, cache) checker => .ok receipt ⟨checker, cache⟩ + +theorem certifiedClaimStep_failure {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} + {witness : ClaimWitness} {before after : CertifiedState} {error : TcError .anon} + (h : (certifiedClaimStep.{v} fuel source address bytes witness).run before = .error error after) : + after = before := by + unfold certifiedClaimStep EStateM.run at h + dsimp only at h + split at h + · exact (EStateM.Result.error.inj h).2.symm + · cases h + +theorem certifiedClaimStep_success {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} + {witness : ClaimWitness} {before after : CertifiedState} {receipt : ClaimReceipt.{v} source fuel address bytes} + (h : (certifiedClaimStep fuel source address bytes witness).run before = .ok receipt after) : + checkClaimBytes? fuel source address bytes witness before.inputCache = some (receipt, after.inputCache) ∧ + after.checker = before.checker := by + unfold certifiedClaimStep EStateM.run at h + dsimp only at h + split at h + · cases h + · rename_i pair checker he + rcases pair with ⟨result, cache⟩ + cases h + exact TcM.checkClaimCertified_success he + +def runCertifiedClaim (fuel : Nat) (source : Ixon.Env) (address : Address) (bytes : ByteArray) + (witness : ClaimWitness) : Option (ClaimReceipt.{v} source fuel address bytes) := + match (certifiedClaimStep fuel source address bytes witness).run initialCertifiedState with + | .error _ _ => none + | .ok receipt _ => some receipt + +def acceptsCertifiedClaim (fuel : Nat) (source : Ixon.Env) (address : Address) (bytes : ByteArray) + (witness : ClaimWitness) : Bool := (runCertifiedClaim.{v} fuel source address bytes witness).isSome + +/-- The actual TcM entry point constructs the meaning of the original claim +from empty initialization. Warm callers have the same receipt theorem and +full rollback; neither logical judgments nor policy decisions are cached. -/ +theorem accepted_tc_claim_meaning {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} + {witness : ClaimWitness} (h : acceptsCertifiedClaim.{v} fuel source address bytes witness = true) : + ∃ receipt : ClaimReceipt.{v} source fuel address bytes, + runCertifiedClaim fuel source address bytes witness = some receipt ∧ + Address.blake3 bytes = address ∧ envelopeBytes receipt.reading.envelope = bytes ∧ + SemanticClaimMeaning.{v} source fuel receipt.reading.envelope := by + unfold acceptsCertifiedClaim at h + cases hr : runCertifiedClaim.{v} fuel source address bytes witness with + | none => simp [hr] at h + | some receipt => exact ⟨receipt, rfl, receipt.reading.authenticated, receipt.reading.canonical, receipt.meaning⟩ + +end Ix.Kernel diff --git a/Ix/Tc/Check.lean b/Ix/Kernel/Check.lean similarity index 99% rename from Ix/Tc/Check.lean rename to Ix/Kernel/Check.lean index c2f176d4f..f2d2e14e6 100644 --- a/Ix/Tc/Check.lean +++ b/Ix/Kernel/Check.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Inductive +public import Ix.Kernel.Inductive /-! Mirror: crates/kernel/src/check.rs @@ -18,13 +18,13 @@ Constant checking dispatch: inductive machinery. The inductive and recursor member/block validators live in -`Ix.Tc.Inductive`. +`Ix.Kernel.Inductive`. -/ public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashSet) @@ -478,7 +478,7 @@ def checkBlockBody (block : KId m) (requested : KId m) : let kind ← classifyBlock members checkClassifiedBlock kind block members --- ### Inductive machinery (validation and recursor generation in Ix.Tc.Inductive) +-- ### Inductive machinery (validation and recursor generation in Ix.Kernel.Inductive) def checkInductiveMember (id : KId m) : RecM m Unit := checkInductiveMemberImpl id @@ -516,7 +516,7 @@ def checkConst (id : KId m) : TcM m Unit := end TcM -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Const.lean b/Ix/Kernel/Const.lean similarity index 98% rename from Ix/Tc/Const.lean rename to Ix/Kernel/Const.lean index 26b0fb7db..2690a4f35 100644 --- a/Ix/Tc/Const.lean +++ b/Ix/Kernel/Const.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Expr +public import Ix.Kernel.Expr /-! Mirror: crates/kernel/src/constant.rs @@ -13,7 +13,7 @@ fidelity in meta mode. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- A recursor computation rule. `ctor` carries the Lean name of the constructor this rule dispatches on; the kernel dispatches on the @@ -94,7 +94,7 @@ def kindName : KConst m → String end KConst -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/DefEq.lean b/Ix/Kernel/DefEq.lean similarity index 99% rename from Ix/Tc/DefEq.lean rename to Ix/Kernel/DefEq.lean index 234606b4a..c015446b1 100644 --- a/Ix/Tc/DefEq.lean +++ b/Ix/Kernel/DefEq.lean @@ -1,11 +1,11 @@ module -public import Ix.Tc.Infer +public import Ix.Kernel.Infer /-! Mirror: crates/kernel/src/def_eq.rs -Multi-tier definitional equality (lean4lean shape): +Multi-tier definitional equality (the named specification shape): 1. quick structural (hash / binder common-fvar opening) 1b. eager Bool.true reduction; 1c. string-literal expansion **before any whnf**; 1d. cheap whnf-core then cheap whnf-no-delta passes @@ -28,7 +28,7 @@ cheap cache; cheap `true` promotes to the full cache and the EquivManager public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- Lazy-delta single-step outcome. -/ inductive LazyDeltaStep where @@ -1277,7 +1277,7 @@ end end RecM -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Driver.lean b/Ix/Kernel/Driver.lean similarity index 97% rename from Ix/Tc/Driver.lean rename to Ix/Kernel/Driver.lean index 9cb37894b..be0310eeb 100644 --- a/Ix/Tc/Driver.lean +++ b/Ix/Kernel/Driver.lean @@ -1,12 +1,12 @@ module -public import Ix.Tc.Ingress -public import Ix.Tc.Egress -public import Ix.Tc.Check +public import Ix.Kernel.Ingress +public import Ix.Kernel.Egress +public import Ix.Kernel.Check /-! Mirror: crates/kernel/src/anon_work.rs (work enumeration) plus the driver -skeleton (the check loop itself lands with `Ix.Tc.Check`). +skeleton (the check loop itself lands with `Ix.Kernel.Check`). `buildAnonWork` identifies the kernel-checkable target set from `env.consts` without consulting metadata sections. For each entry: @@ -26,7 +26,7 @@ are visited in ascending byte-lexicographic address order (Rust public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- A single anon-mode work item — one `checkConst primary` per item suffices to typecheck every address in `targets`. -/ @@ -178,7 +178,7 @@ def ingressAll (ixonEnv : Ixon.Env) (verify : Bool := true) : then merge in chunk order with `KEnv.union` (deterministic conversion makes duplicate keys benign). The shared shape behind the eager whole-env parallel ingress drivers (anon here, meta in - `Ix.Tc.ParCheck`). Chunks schedule on the task pool (bounded by + `Ix.Kernel.ParCheck`). Chunks schedule on the task pool (bounded by `LEAN_NUM_THREADS`). -/ def ingressEnvParallelWith (work : Array W) (runItem : W → EStateM IngressErr (KEnv m) Unit) @@ -214,7 +214,7 @@ def ingressAnonEnvParallel (ixonEnv : Ixon.Env) (work : Array AnonWorkItem) /-- Driver configuration. -/ structure CheckCfg where /-- Verify `blake3(bytes) == addr` at every constant materialization - (the soundness-critical integrity check; see `Ix.Tc.Ingress`). -/ + (the soundness-critical integrity check; see `Ix.Kernel.Ingress`). -/ verifyHashes : Bool := true /-- Clear the reduction-memo caches every N work items (structural caches, constants, and the faulted set are preserved). `0` disables. -/ @@ -295,10 +295,10 @@ def checkEnvAnon (ixonEnv : Ixon.Env) (cfg : CheckCfg := {}) : /-! ### Kernel ↔ Ixon roundtrip driver -`Lean env → (Rust) compile → ixe → Ix.Tc ingress → Ix.Tc egress → canonical +`Lean env → (Rust) compile → ixe → Ix.Kernel ingress → Ix.Kernel egress → canonical compare` — the anon analog of the Rust `kernel-ixon-roundtrip` test. Certifies ingress loses no information: every constant reconstructs -structurally from kernel data alone (see `Ix.Tc.Egress` for the comparison +structurally from kernel data alone (see `Ix.Kernel.Egress` for the comparison contract). Each item runs against a **fresh** kernel env — egress needs no cross-item state, so memory stays bounded per item at any corpus size. -/ @@ -419,7 +419,7 @@ def checkIxeAnon (path : System.FilePath) (cfg : CheckCfg := {}) : let bytes ← IO.FS.readBinFile path return checkIxeBytesAnon bytes cfg -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Egress.lean b/Ix/Kernel/Egress.lean similarity index 99% rename from Ix/Tc/Egress.lean rename to Ix/Kernel/Egress.lean index c8f0ca312..691654350 100644 --- a/Ix/Tc/Egress.lean +++ b/Ix/Kernel/Egress.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Ingress +public import Ix.Kernel.Ingress /-! Mirror: crates/compile/src/kernel_egress.rs (the kernel → Ixon half, @@ -50,13 +50,13 @@ leg) becomes possible once meta-mode ingress lands. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) /-! ### Universe conversion and reduction -`ixonUnivToK` / `kUnivToIxon` / `reduceIxonUniv` live in `Ix.Tc.Ingress` +`ixonUnivToK` / `kUnivToIxon` / `reduceIxonUniv` live in `Ix.Kernel.Ingress` (shared with meta ingress's decoration-presence test). -/ /-! ### Expression egress -/ @@ -893,7 +893,7 @@ def roundtripCompare (original egressed : Ixon.Constant) : return none return some ((describeDiff ca cb).getD "canonical forms differ (no diff located)") -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/EgressLean.lean b/Ix/Kernel/EgressLean.lean similarity index 99% rename from Ix/Tc/EgressLean.lean rename to Ix/Kernel/EgressLean.lean index e2516cb89..92f07208c 100644 --- a/Ix/Tc/EgressLean.lean +++ b/Ix/Kernel/EgressLean.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Ingress +public import Ix.Kernel.Ingress public import Ix.Environment /-! @@ -33,7 +33,7 @@ recursors — and walk to the first structural divergence for messages. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) @@ -365,7 +365,7 @@ def compareLeanCI (original egressed : Ix.ConstantInfo) : Option String := Id.ru | _, _ => pure () return none -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Env.lean b/Ix/Kernel/Env.lean similarity index 98% rename from Ix/Tc/Env.lean rename to Ix/Kernel/Env.lean index 3df2be1c1..8c2ecfc41 100644 --- a/Ix/Tc/Env.lean +++ b/Ix/Kernel/Env.lean @@ -1,7 +1,7 @@ module -public import Ix.Tc.Const -public import Ix.Tc.Error +public import Ix.Kernel.Const +public import Ix.Kernel.Error /-! Mirror: crates/kernel/src/env.rs @@ -13,19 +13,19 @@ Divergences from Rust (documented, semantics-preserving): - The `prims: OnceCell>` field is not stored here (Rust has an env ↔ primitive module cycle Lean can't express); the resolved `Primitives` lives on `TcState` instead, which is where the Rust `TypeChecker` copies it - anyway. `Primitives.fromEnv` performs the resolution (see `Ix.Tc.Primitive`). + anyway. `Primitives.fromEnv` performs the resolution (see `Ix.Kernel.Primitive`). - The reserved-marker guard in Rust's `KEnv::insert` (a panic) is enforced at - ingress time instead (`Ix.Tc.Ingress`), which is the only path that feeds + ingress time instead (`Ix.Kernel.Ingress`), which is the only path that feeds untrusted constants into the env. - `subst_scratch`/`lift_scratch` buffer *reuse* is not ported (allocation - churn is a Rust concern); per-call memoization itself is (see `Ix.Tc.Subst`). + churn is a Rust concern); per-call memoization itself is (see `Ix.Kernel.Subst`). - Perf counters and the sharding profile sink are not ported. -/ public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap HashSet) @@ -383,7 +383,7 @@ def cacheSizes (env : KEnv m) : KEnvCacheSizes where end KEnv -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Equiv.lean b/Ix/Kernel/Equiv.lean similarity index 99% rename from Ix/Tc/Equiv.lean rename to Ix/Kernel/Equiv.lean index d8f2841f0..ac83a1ec1 100644 --- a/Ix/Tc/Equiv.lean +++ b/Ix/Kernel/Equiv.lean @@ -17,7 +17,7 @@ reads). Do not reuse the `IO.Ref`-based `Ix.UnionFind`. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- Composite key for one expression in one context-suffix interpretation. @@ -147,7 +147,7 @@ def addEquiv (em : EquivManager) (k1 k2 : EqKey) : EquivManager := end EquivManager -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Error.lean b/Ix/Kernel/Error.lean similarity index 98% rename from Ix/Tc/Error.lean rename to Ix/Kernel/Error.lean index be3513dfa..901f23182 100644 --- a/Ix/Tc/Error.lean +++ b/Ix/Kernel/Error.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Expr +public import Ix.Kernel.Expr /-! Mirror: crates/kernel/src/error.rs @@ -12,7 +12,7 @@ Type checker error types. (Rust's `u64_to_usize` helper is unneeded: Lean public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel inductive TcError (m : Mode) where | typeExpected @@ -80,7 +80,7 @@ instance : Inhabited (TcError m) := ⟨.typeExpected⟩ end TcError -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Expr.lean b/Ix/Kernel/Expr.lean similarity index 99% rename from Ix/Tc/Expr.lean rename to Ix/Kernel/Expr.lean index 69159a4b2..2d094a950 100644 --- a/Ix/Tc/Expr.lean +++ b/Ix/Kernel/Expr.lean @@ -1,8 +1,8 @@ module -public import Ix.Tc.Mode -public import Ix.Tc.Id -public import Ix.Tc.Level +public import Ix.Kernel.Mode +public import Ix.Kernel.Id +public import Ix.Kernel.Level public import Ix.Address public import Ix.Unsigned public import Ix.Ixon @@ -38,7 +38,7 @@ and mdata are never hashed — hash equality is alpha-invariant in meta mode. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Blake3.Rust (Hasher) @@ -531,7 +531,7 @@ instance : Repr (KExpr m) := ⟨fun e _ => .text e.render⟩ end KExpr -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Id.lean b/Ix/Kernel/Id.lean similarity index 97% rename from Ix/Tc/Id.lean rename to Ix/Kernel/Id.lean index b0e6969f7..721ec09d9 100644 --- a/Ix/Tc/Id.lean +++ b/Ix/Kernel/Id.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Mode +public import Ix.Kernel.Mode public import Ix.Address /-! @@ -11,7 +11,7 @@ definition ordering). public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- Kernel identifier: bundles a content address with a metadata name. In meta mode both fields participate in equality; in anon mode the name @@ -78,7 +78,7 @@ structure FVarId where instance : ToString FVarId := ⟨fun f => s!"fv${f.id}"⟩ -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Inductive.lean b/Ix/Kernel/Inductive.lean similarity index 99% rename from Ix/Tc/Inductive.lean rename to Ix/Kernel/Inductive.lean index dea08a8e9..18b78eb1e 100644 --- a/Ix/Tc/Inductive.lean +++ b/Ix/Kernel/Inductive.lean @@ -1,7 +1,7 @@ module -public import Ix.Tc.Knot -public import Ix.Tc.CanonicalCheck +public import Ix.Kernel.Knot +public import Ix.Kernel.CanonicalCheck /-! Mirror: crates/kernel/src/inductive.rs @@ -34,7 +34,7 @@ triggering recursor generation for the block public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashSet) @@ -394,7 +394,7 @@ def getResultSortLevel (ty : KExpr m) (n : Nat) : /-- Large eliminator (can target any universe): non-Prop, or Empty-like (0 ctors), or single-ctor Prop whose non-Prop fields all appear among - the return-type args (lean4lean `isLargeEliminator`). -/ + the return-type args (the named specification `isLargeEliminator`). -/ def isLargeEliminator (resultLevel : KUniv m) (indInfos : Array (KId m × UInt64 × UInt64 × Array (KId m) × KExpr m)) : RecM m Bool := do @@ -2945,7 +2945,7 @@ def checkGeneratedRecursorFromCache (recBlock id : KId m) (ty : KExpr m) checkGeneratedRecursorCandidate ty declaredLvls declaredIsUnsafe params motives minors indices storedRules selected | none => - -- C2: no generated recursor — MUST NOT silently pass. + -- Reject a recursor with no generated candidate for its major type. throw (.other "check_recursor: no generated recursor for major") /-- Freeze the complete stored recursor declaration and validate the exact @@ -3120,7 +3120,7 @@ end end RecM -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Infer.lean b/Ix/Kernel/Infer.lean similarity index 97% rename from Ix/Tc/Infer.lean rename to Ix/Kernel/Infer.lean index f48831ef3..abfedbfcc 100644 --- a/Ix/Tc/Infer.lean +++ b/Ix/Kernel/Infer.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Whnf +public import Ix.Kernel.Whnf /-! Mirror: crates/kernel/src/infer.rs @@ -22,7 +22,7 @@ Let inference eagerly substitutes the value into the abstracted body type public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -84,7 +84,7 @@ def inferUncached (inferRec : KExpr m → RecM m (KExpr m)) let t ← inferRec ty let _ ← ensureSortDirect t withLctxScope do - -- Open the binder with a fresh fvar (lean4lean inferLambda). + -- Open the binder with a fresh fvar (the named specification inferLambda). let (bodyOpen, fvId) ← TcM.openBinder name bi ty body let bodyTy ← inferRec bodyOpen -- Peephole-reduce App(λ…, …) shapes before wrapping in the Pi. @@ -107,7 +107,7 @@ def inferUncached (inferRec : KExpr m → RecM m (KExpr m)) let valTy ← inferRec val if !(← isDefEqCall valTy ty) then throw .declTypeMismatch - -- Open with a let-bound fvar (lean4lean inferLet); eagerly substitute + -- Open with a let-bound fvar (the named specification inferLet); eagerly substitute -- the value into the abstracted body type, then cheap-beta. withLctxScope do let (bodyOpen, fvId) ← TcM.openLet name ty val body @@ -179,7 +179,7 @@ def ensureForallDirect (e : KExpr m) : RecM m (KExpr m × KExpr m) := do return (a, b) ensureForallWhnf e -/-- The isDefEq back-edge (tied in `Ix.Tc.Knot`). -/ +/-- The isDefEq back-edge (tied in `Ix.Kernel.Knot`). -/ def isDefEqCall (a b : KExpr m) : RecM m Bool := do (← read).isDefEq a b @@ -327,7 +327,7 @@ end end RecM -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Ingress.lean b/Ix/Kernel/Ingress.lean similarity index 99% rename from Ix/Tc/Ingress.lean rename to Ix/Kernel/Ingress.lean index 33999c741..f459ddbd4 100644 --- a/Ix/Tc/Ingress.lean +++ b/Ix/Kernel/Ingress.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Monad +public import Ix.Kernel.Monad public import Ix.Ixon /-! @@ -22,7 +22,7 @@ universe-table index for the same reason. Every constructed node is interned. Integrity: `getConstVerified` checks `blake3(rawBytes) == addr` at materialization. Rust's `Env::get` does this on its main path; the -`rs_de_env_lazy`-style loaders and pure-Lean `getEnv` do not, and Ix.Tc is +`rs_de_env_lazy`-style loaders and pure-Lean `getEnv` do not, and Ix.Kernel is the soundness-critical consumer — so it verifies here (`verify := true` by default; the driver's `CheckCfg` can disable it for benchmarking). @@ -31,13 +31,13 @@ here in `insertEntries`, the only path feeding untrusted constants into the kernel env. Meta-mode ingress (arena parallel walk, name resolution, mdata layers) -lives in `Ix.Tc.IngressMeta`. +lives in `Ix.Kernel.IngressMeta`. -/ public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) @@ -100,7 +100,7 @@ def anonCtorAddrs (blockAddr : Address) (indcIdx : UInt64) UNCONDITIONALLY — `--no-verify` must not be able to bind them to other content, because acceleration substitutes native semantics for exactly these declarations (soundness argument in - `Ix/Tc/Primitive.lean` at `primAddrSet`). -/ + `Ix/Kernel/Primitive.lean` at `primAddrSet`). -/ def getConstVerified (ixonEnv : Ixon.Env) (addr : Address) (verify : Bool := true) : Except IngressErr (Option Ixon.Constant) := do match ixonEnv.consts[addr]? with @@ -597,7 +597,7 @@ def ingressAnonAddrShallow (ixonEnv : Ixon.Env) (addr : Address) let _ ← ingressAnonStandalone ixonEnv addr constant return true -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/IngressMeta.lean b/Ix/Kernel/IngressMeta.lean similarity index 99% rename from Ix/Tc/IngressMeta.lean rename to Ix/Kernel/IngressMeta.lean index 1e9533ba6..9f2971f59 100644 --- a/Ix/Tc/IngressMeta.lean +++ b/Ix/Kernel/IngressMeta.lean @@ -1,13 +1,13 @@ module -public import Ix.Tc.Ingress -public import Ix.Tc.CanonicalCheck +public import Ix.Kernel.Ingress +public import Ix.Kernel.CanonicalCheck /-! Mirror: crates/kernel/src/ingress.rs (the Ixon → kernel, meta-mode half) Meta ingress converts the same `Ixon.Constant` structure as the anon path -(`Ix.Tc.Ingress`) but additionally threads the per-constant metadata +(`Ix.Kernel.Ingress`) but additionally threads the per-constant metadata (`Ixon.ConstantMeta`) — binder names/infos, mdata layers, level-param names, constant names — into the kernel types' `Mode.F` fields. Semantic Blake3 addresses never include metadata, so every KExpr/KUniv/KConst @@ -62,13 +62,13 @@ tables the fallback never fires (P3: canonical forms are mk*-fixed), but it keeps raw-table fixtures exercised. Either way the `UnivDecor` on the KExpr node (`ExprInfo.univDecor`) folds into `metaAddr` only, never `addr`, so `tc-meta-addr` and all semantic checking are -untouched; meta egress replays the spelling (`Ix.Tc.egressExpr`). +untouched; meta egress replays the spelling (`Ix.Kernel.egressExpr`). -/ public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) @@ -954,7 +954,7 @@ def ingressMetaWorkItem (ixonEnv : Ixon.Env) (item : MetaWorkItem) catch e => throw s!"{name}: {e}" insertMutsEntriesMeta entries -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Knot.lean b/Ix/Kernel/Knot.lean similarity index 94% rename from Ix/Tc/Knot.lean rename to Ix/Kernel/Knot.lean index 5479bb563..b67bdbcc4 100644 --- a/Ix/Tc/Knot.lean +++ b/Ix/Kernel/Knot.lean @@ -1,9 +1,9 @@ module -public import Ix.Tc.DefEq +public import Ix.Kernel.DefEq /-! -The recursion knot. `Ix.Tc.Whnf`/`Infer`/`DefEq` define the kernel algorithms +The recursion knot. `Ix.Kernel.Whnf`/`Infer`/`DefEq` define the kernel algorithms in `RecM` (a `Methods`-reader over `TcM`); this module ties the back-edges with a total, depth-indexed method table and exports `TcM`-level entry points. Only the back-edges route through the record (whnf reads @@ -18,7 +18,7 @@ has already been consumed. Exhausting method-table depth throws the same public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- Fuel-exhausted end of the recursive method table. Every back-edge has the same error and error-state behavior as an exhausted `TcM.tick`. -/ @@ -81,7 +81,7 @@ def ensureForall (e : KExpr m) : TcM m (KExpr m × KExpr m) := end TcM -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Lctx.lean b/Ix/Kernel/Lctx.lean similarity index 98% rename from Ix/Tc/Lctx.lean rename to Ix/Kernel/Lctx.lean index 31c2d9a08..9fdd0581d 100644 --- a/Ix/Tc/Lctx.lean +++ b/Ix/Kernel/Lctx.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Subst +public import Ix.Kernel.Subst /-! Mirror: crates/kernel/src/lctx.rs @@ -19,7 +19,7 @@ Rust's legacy `NameGenerator` is not ported: fvar ids are minted from public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- A single local-context entry: a regular binder (`cdecl`, from lambda or forall) or a let-binding (`ldecl`, with an associated value that WHNF @@ -137,7 +137,7 @@ def isFVar (e : KExpr m) : Bool := | .fvar .. => true | _ => false -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Level.lean b/Ix/Kernel/Level.lean similarity index 97% rename from Ix/Tc/Level.lean rename to Ix/Kernel/Level.lean index a57d19314..62b99ecdb 100644 --- a/Ix/Tc/Level.lean +++ b/Ix/Kernel/Level.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Mode +public import Ix.Kernel.Mode public import Ix.Address public import Ix.Unsigned public import Batteries.Recycling.RBTree.Basic @@ -15,21 +15,21 @@ carries `m.F Name` — the parameter name in meta mode, erased in anon mode. Parameter *identity* is the positional index; names are display-only and never hashed, so anon and meta levels of the same structure share addresses. -`normalizeLevel` is a port of the Rust port of Lean4Lean's `Level.Normalize` +`normalizeLevel` is a port of the Rust port of Ix.Theory.Named's `Level.Normalize` (Yoan Géran, "A Canonical Form for Universe Levels in Impredicative Type Theory"). `NormLevel` maps sorted param-index paths (the imax conditioning chain) to nodes tracking constant offsets and variable contributions. Divergence inherited from Rust (see level.rs `norm_level_le` doc): the `≤` check splits constant and variable coverage into independent searches -(`coversConst` / `coversVar`), strictly more complete than Lean4Lean's -single-witness `NormLevel.le`. `univEq` matches Lean4Lean's `isEquiv'`. +(`coversConst` / `coversVar`), strictly more complete than Ix.Theory.Named's +single-witness `NormLevel.le`. `univEq` matches Ix.Theory.Named's `isEquiv'`. -/ public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Blake3.Rust (Hasher) @@ -320,7 +320,7 @@ def normalizeAux (l : KUniv m) (path : Path) (k : UInt64) normalizeAux u newPath k acc | none => -- idx already in path (fixed > 0 along this chain); the outer k succs - -- still contribute. Matches Lean4Lean's `acc.addVar v k path`. + -- still contribute. Matches Ix.Theory.Named's `acc.addVar v k path`. let acc := if k != 0 then acc.addVar idx k path else acc normalizeAux u path k acc | .param idx _ _ => @@ -450,7 +450,7 @@ def coversVar (l2 : NormLevel) (p1 : Path) (w off : UInt64) : Bool := /-- Semantic `l1 ≤ l2` on canonical forms. Each ingredient of every `l1` entry must be covered by *some* `l2` entry at a sub-path — constant and variable coverage searched independently (see module doc: intentionally - stronger than Lean4Lean's single-witness `NormLevel.le`). -/ + stronger than Ix.Theory.Named's single-witness `NormLevel.le`). -/ def normLevelLe (l1 l2 : NormLevel) : Bool := l1.toList.all fun (p1, n1) => if n1.constant == 0 && n1.vars.isEmpty then true @@ -505,7 +505,7 @@ def univGeq (u v : KUniv m) : Bool := def KUniv.isSemanticZero (u : KUniv m) : Bool := u.isZero || (Level.normalizeLevel u).toList.all (!Level.entryNonEmpty ·) -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Mode.lean b/Ix/Kernel/Mode.lean similarity index 98% rename from Ix/Tc/Mode.lean rename to Ix/Kernel/Mode.lean index 078493dd6..bae9ea9c5 100644 --- a/Ix/Tc/Mode.lean +++ b/Ix/Kernel/Mode.lean @@ -18,14 +18,14 @@ in either mode, so anon and meta terms of the same underlying structure carry identical Blake3 addresses. Rust's `MetaHash` trait is not ported: its only load-bearing uses are the -`Ord` on `KId` (ported directly in `Ix.Tc.Id` via stored name hashes) and +`Ord` on `KId` (ported directly in `Ix.Kernel.Id` via stored name hashes) and duplicate-level-param detection (`Mode.F.hasDups` below). -/ public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- Kernel mode. `anon` erases metadata fields to `Unit`; `«meta»` keeps them. Mirrors Rust `ZMode` (`Anon = ZMode`, `Meta = ZMode`). -/ @@ -173,7 +173,7 @@ instance {m : Mode} [MetaDisplay α] : MetaDisplay (m.F α) where end Mode.F -end Ix.Tc +end Ix.Kernel /-- Saturating decrement: `0 - 1 = 0`. Lean `UInt64` subtraction wraps where Rust's `saturating_sub` saturates; loose-bound-range (`lbr`) computations diff --git a/Ix/Tc/Monad.lean b/Ix/Kernel/Monad.lean similarity index 98% rename from Ix/Tc/Monad.lean rename to Ix/Kernel/Monad.lean index 45c06591d..f797e47c6 100644 --- a/Ix/Tc/Monad.lean +++ b/Ix/Kernel/Monad.lean @@ -1,10 +1,10 @@ module -public import Ix.Tc.Env -public import Ix.Tc.Equiv -public import Ix.Tc.Primitive -public import Ix.Tc.Subst -public import Ix.Tc.Lctx +public import Ix.Kernel.Env +public import Ix.Kernel.Equiv +public import Ix.Kernel.Primitive +public import Ix.Kernel.Subst +public import Ix.Kernel.Lctx /-! Mirror: crates/kernel/src/tc.rs @@ -26,7 +26,7 @@ Fuels are data-level and placed exactly where Rust places them (post-cache-miss). The `IX_MAX_REC_FUEL` env override is not ported. Cross-file recursion (whnf ↔ infer ↔ def_eq) is tied through a `Methods m` -record + `RecM m := ReaderT (Methods m) (TcM m)`; `Ix.Tc.Knot` ties a total +record + `RecM m := ReaderT (Methods m) (TcM m)`; `Ix.Kernel.Knot` ties a total method table indexed by the current `recFuel`. Only back-edges go through the record. @@ -37,7 +37,7 @@ Not ported (diagnostics/profiling only): perf counters, hot-miss sampler, public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap HashSet) @@ -145,8 +145,8 @@ structure TcState (m : Mode) where constant's block into `env` by address. Installed by the driver (`TcState.newLazyAnon`); `none` for eagerly-ingressed envs. The closure runs against `env` and returns whether the address was found in the - backing Ixon env. (The error type is `Ix.Tc.IngressErr`, spelled - `String` here because `Ix.Tc.Ingress` imports this module.) -/ + backing Ixon env. (The error type is `Ix.Kernel.IngressErr`, spelled + `String` here because `Ix.Kernel.Ingress` imports this module.) -/ lazyFault : Option (Address → EStateM String (KEnv m) Bool) := none /-- Addresses already faulted (hit or miss) — never re-ingress. Lives on the state (not reset per constant), mirroring Rust @@ -257,7 +257,7 @@ def addr8 (a : Address) : String := ((toString a).take 8).toString `[tag] ` mirrors the Rust kernel's `IX_STEP_TRACE` journal; diffing the two sequences localizes a behavioral divergence at the first fork (workflow in - `Ix.Tc.ParCheck`). -/ + `Ix.Kernel.ParCheck`). -/ @[inline] def stepTrace (tag : String) (payload : Unit → String) : TcM m Unit := do let s ← get @@ -383,7 +383,8 @@ def ctxAddrForLbrUncached (s : TcState m) (lbr : UInt64) : Address := | none => h := h.update "local".toUTF8 h := h.update s.ctx[i]!.addr.hash - return ⟨(h.finalizeWithLength 32).val⟩ + return ⟨(h.finalizeWithLength 32 (by + rcases System.Platform.numBits_eq with bits | bits <;> rw [bits] <;> decide)).val⟩ /-- Memoized wrapper around `ctxAddrForLbrUncached`, mirroring tc.rs `ctx_addr_for_lbr`. The pure helper is a verification seam as well as an @@ -602,7 +603,7 @@ def instUnivInner (e : KExpr m) (us : Array (KUniv m)) : -- `pure`, not `return`, in every rebuilding arm: `return` exits the -- whole function, skipping the intern + memo-insert tail below, and -- an interior-node-less memo turns shared-DAG walks exponential - -- (see the note in `Ix/Tc/Subst.lean` `liftCached`). + -- (see the note in `Ix/Kernel/Subst.lean` `liftCached`). | .sort u _ => pure (KExpr.mkSort (← TcM.ofExcept (substUniv u us))) | .const id curUs _ => do @@ -871,7 +872,7 @@ def ensureForall (e : KExpr m) : RecM m (KExpr m × KExpr m) := do end RecM -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/ParCheck.lean b/Ix/Kernel/ParCheck.lean similarity index 98% rename from Ix/Tc/ParCheck.lean rename to Ix/Kernel/ParCheck.lean index 606eddc29..b214fa29a 100644 --- a/Ix/Tc/ParCheck.lean +++ b/Ix/Kernel/ParCheck.lean @@ -1,12 +1,12 @@ module -public import Ix.Tc.Driver -public import Ix.Tc.IngressMeta +public import Ix.Kernel.Driver +public import Ix.Kernel.IngressMeta public import Std.Sync.Mutex /-! Parallel whole-env kernel check driver (`ix check-lean`'s engine) plus the -eager parallel meta-ingress driver it needs (shared with `Ix.Tc.Validate`). +eager parallel meta-ingress driver it needs (shared with `Ix.Kernel.Validate`). Mirrors the Rust parallel checker's coordination design (`crates/ffi/src/kernel.rs`: work-stealing over an atomic next-index, @@ -47,7 +47,7 @@ per-constant fuel budget on both sides. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- Set the stack size, in bytes, for subsequently spawned Lean runtime threads (`.dedicated` task threads and not-yet-spawned pool workers) — @@ -392,7 +392,7 @@ def checkEnvParallel (kenv : KEnv m) (prims : Primitives m) failures := failures.qsort fun a b => a.1 < b.1 elapsedMs := endMs - startMs } -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Primitive.lean b/Ix/Kernel/Primitive.lean similarity index 99% rename from Ix/Tc/Primitive.lean rename to Ix/Kernel/Primitive.lean index 026479be2..71e71a3b2 100644 --- a/Ix/Tc/Primitive.lean +++ b/Ix/Kernel/Primitive.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Env +public import Ix.Kernel.Env /-! Mirror: crates/kernel/src/primitive.rs @@ -23,7 +23,7 @@ nested-inductive recursor generation), mirroring Rust. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- Hardcoded canonical primitive addresses (for lookup in the env). -/ structure PrimAddrs where @@ -593,7 +593,7 @@ def ofAnonAddrs : Primitives .anon := end Primitives -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Subst.lean b/Ix/Kernel/Subst.lean similarity index 99% rename from Ix/Tc/Subst.lean rename to Ix/Kernel/Subst.lean index 5e8329e57..462a12129 100644 --- a/Ix/Tc/Subst.lean +++ b/Ix/Kernel/Subst.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Env +public import Ix.Kernel.Env /-! Mirror: crates/kernel/src/subst.rs @@ -21,7 +21,7 @@ node avoids gratuitous re-interning. public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel /-- State monad over the intern table — the Lean face of Rust's `&mut InternTable` threading. -/ @@ -463,14 +463,14 @@ def internAppChain (base : KExpr m) : List (KExpr m) → InternM m (KExpr m) /-- Cheap beta reduction: peephole-reduce `App(λ…λ. body, args)` without full `subst` in trivial cases (closed body, or single-bvar body). Otherwise - returns the input unchanged (full WHNF handles it). Mirrors lean4lean's + returns the input unchanged (full WHNF handles it). Mirrors the named specification's `Expr.cheapBetaReduce`. -/ def cheapBetaReduce (e : KExpr m) : InternM m (KExpr m) := do match cheapBetaPlan? e with | none => return e | some plan => internAppChain plan.base plan.trailing -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Validate.lean b/Ix/Kernel/Validate.lean similarity index 98% rename from Ix/Tc/Validate.lean rename to Ix/Kernel/Validate.lean index 9b27859fa..f0580674f 100644 --- a/Ix/Tc/Validate.lean +++ b/Ix/Kernel/Validate.lean @@ -1,13 +1,13 @@ module -public import Ix.Tc.Driver -public import Ix.Tc.IngressMeta -public import Ix.Tc.ParCheck -public import Ix.Tc.EgressLean +public import Ix.Kernel.Driver +public import Ix.Kernel.IngressMeta +public import Ix.Kernel.ParCheck +public import Ix.Kernel.EgressLean public import Ix.CanonM /-! -Whole-env validation drivers for the pure-Lean `Ix.Tc` pipeline — the +Whole-env validation drivers for the pure-Lean `Ix.Kernel` pipeline — the shared core behind the `tc-roundtrip` test suite and `ix validate-lean`. Three gates over a Rust-compiled `.ixe` byte image: @@ -18,7 +18,7 @@ Three gates over a Rust-compiled `.ixe` byte image: bytes EXACTLY. 2. `anonRoundtripEnv` — structural kernel roundtrip: every constant anon-ingressed, egressed back to `Ixon.Constant`, canonically compared - (see `Ix.Tc.Egress`); projections byte-exact. Parallel per work item. + (see `Ix.Kernel.Egress`); projections byte-exact. Parallel per work item. 3. `metaRoundtripEnv` — full-fidelity kernel roundtrip against the SOURCE Lean environment (the oracle): phase-parallel meta ingress of the whole env into one merged `KEnv .meta`, then per-named-entry egress to @@ -36,7 +36,7 @@ Three gates over a Rust-compiled `.ixe` byte image: public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) @@ -364,7 +364,7 @@ def metaRoundtripEnvStreaming (leanEnv : Lean.Environment) report := { report with errors := report.errors.push (name, msg) } return report -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc/Verify/Audit/Basic.lean b/Ix/Kernel/Verify/Audit/Basic.lean similarity index 64% rename from Ix/Tc/Verify/Audit/Basic.lean rename to Ix/Kernel/Verify/Audit/Basic.lean index 54f1c2f61..69b1991bb 100644 --- a/Ix/Tc/Verify/Audit/Basic.lean +++ b/Ix/Kernel/Verify/Audit/Basic.lean @@ -1,16 +1,18 @@ import Lean.Elab.Command import Lean.PrivateName -import Lean.Util.CollectAxioms import Lean.Util.FoldConsts +import Ix.Theory.Named.Std.AxiomAudit /-! -# Exact trust-boundary auditing for `Ix.Tc.Verify` +# Exact trust-boundary auditing for `Ix.Kernel.Verify` -`Lean.collectAxioms` gives the kernel-computed, transitive axiom set for a -declaration. This module adds two pieces needed by the verification plan: +The audit traverses the checked declarations directly, including types, +theorem bodies, and inductive constructors. Imported axiom summaries can +omit dependencies of recursive declaration groups, so they are not the +source of truth here. The audit checks: * an exact, per-root allowlist split into ordinary Lean axioms, explicitly - named upstream implementation axioms, quarantined pending-upstream axioms, + named implementation bridge axioms, quarantined pending metatheory axioms, and generated `native_decide` axioms; * an exact list of the reachable declarations that use `sorryAx` directly, so permitting `sorryAx` cannot hide where that debt entered the proof. @@ -21,7 +23,7 @@ import context from the concrete translation relations with which their opaque names currently collide. -/ -namespace Ix.Tc.Verify.Audit +namespace Ix.Kernel.Verify.Audit open Lean open Lean.Elab.Command @@ -29,19 +31,19 @@ open Lean.Elab.Command /-- The complete permitted trust boundary for one exported theorem root. Lean usually gives generated native axioms private names such as -`_private.Ix.Tc.Expr.0....`; a public theorem proved directly by +`_private.Ix.Kernel.Expr.0....`; a public theorem proved directly by `native_decide` can instead expose a public generated axiom. Use `nativeAxiom` below for the private case. `sorryOrigins` is checked by traversing the root's dependency graph. -/ structure RootAllowance where root : Lean.Name standardAxioms : Array Lean.Name := #[] - /-- Nonlogical implementation bridge axioms inherited from an upstream - package. These remain separate from Lean's three permitted logical axioms - so an executable upstream fixture cannot silently widen `standardAxioms`. -/ - upstreamAxioms : Array Lean.Name := #[] - /-- Temporary local witnesses for facts expected from a future upstream - release. Only the quarantined `Ix.Tc.Upstream.Pending` namespace may occur + /-- Nonlogical implementation bridge axioms retained in the local proof + support. These remain separate from Lean's three permitted logical axioms + so an executable fixture cannot silently widen `standardAxioms`. -/ + implementationAxioms : Array Lean.Name := #[] + /-- Temporary local witnesses for unfinished metatheory proofs. + Only the quarantined `Ix.Kernel.Frontier.Pending` namespace may occur here; completed theorem roots must leave this category empty. -/ pendingAxioms : Array Lean.Name := #[] nativeAxioms : Array Lean.Name := #[] @@ -63,49 +65,10 @@ private def permittedStandardAxioms : Array Lean.Name := private def sortNames (xs : Array Name) : Array Name := xs.qsort Name.lt -/-- Direct constant references, following the same declaration cases as -`Lean.collectAxioms`. In particular, opaque theorem values and inductive -constructors are included. -/ -private def directConstants : ConstantInfo → Array Name - | .axiomInfo v => v.type.getUsedConstants - | .defnInfo v => v.type.getUsedConstants ++ v.value.getUsedConstants - | .thmInfo v => v.type.getUsedConstants ++ v.value.getUsedConstants - | .opaqueInfo v => v.type.getUsedConstants ++ v.value.getUsedConstants - | .quotInfo _ => #[] - | .ctorInfo v => v.type.getUsedConstants - | .recInfo v => v.type.getUsedConstants - | .inductInfo v => v.type.getUsedConstants ++ v.ctors - namespace DependencyAudit -structure State where - visited : NameSet := {} - names : Array Name := #[] - origins : Array Name := #[] - -abbrev M := ReaderT Environment (StateM State) - -/-- Traverse the checked kernel environment and record each reachable -declaration whose type or value directly mentions `sorryAx`. -/ -partial def visit (declName : Name) : M Unit := do - let state ← get - unless state.visited.contains declName do - modify fun s => - { s with - visited := s.visited.insert declName - names := s.names.push declName } - let env ← read - match env.checked.get.find? declName with - | none => pure () - | some info => - let dependencies := directConstants info - if declName != ``sorryAx && dependencies.contains ``sorryAx then - modify fun s => { s with origins := s.origins.push declName } - dependencies.forM visit - -def collect (env : Environment) (root : Name) : State := - let (_, state) := ((visit root).run env).run {} - state +abbrev State := Ix.Theory.Named.AxiomAudit.State +abbrev collect := Ix.Theory.Named.AxiomAudit.collect end DependencyAudit @@ -114,20 +77,20 @@ private def validateCategories (allowance : RootAllowance) : for axiomName in allowance.standardAxioms do unless permittedStandardAxioms.contains axiomName do throwError m!"{allowance.root}: {axiomName} is not a permitted standard Lean axiom" - for axiomName in allowance.upstreamAxioms do + for axiomName in allowance.implementationAxioms do let rendered := axiomName.toString unless rendered.startsWith "Lean." || rendered.startsWith "Std." || - rendered.startsWith "Lean4Lean." do - throwError m!"{allowance.root}: upstream axiom is outside Lean/Std/Lean4Lean: {axiomName}" + rendered.startsWith "Ix.Theory.Named." do + throwError m!"{allowance.root}: implementation axiom is outside Lean/Std/Ix.Theory.Named: {axiomName}" if permittedStandardAxioms.contains axiomName then - throwError m!"{allowance.root}: standard axiom misclassified as upstream: {axiomName}" + throwError m!"{allowance.root}: standard axiom misclassified as implementation: {axiomName}" if axiomName == ``sorryAx then throwError m!"{allowance.root}: sorryAx must be accounted for by sorryOrigins" if Lean.isPrivateName axiomName then throwError m!"{allowance.root}: private axiom must be accounted for as native: {axiomName}" for axiomName in allowance.pendingAxioms do - unless axiomName.toString.startsWith "Ix.Tc.Upstream.Pending." do - throwError m!"{allowance.root}: pending axiom is outside Ix.Tc.Upstream.Pending: {axiomName}" + unless axiomName.toString.startsWith "Ix.Kernel.Frontier.Pending." do + throwError m!"{allowance.root}: pending axiom is outside Ix.Kernel.Frontier.Pending: {axiomName}" if permittedStandardAxioms.contains axiomName then throwError m!"{allowance.root}: standard axiom misclassified as pending: {axiomName}" if axiomName == ``sorryAx then @@ -139,18 +102,19 @@ private def validateCategories (allowance : RootAllowance) : throwError m!"{allowance.root}: malformed native_decide axiom: {axiomName}" private def expectedAxioms (allowance : RootAllowance) : Array Lean.Name := - let expected := allowance.standardAxioms ++ allowance.upstreamAxioms ++ + let expected := allowance.standardAxioms ++ allowance.implementationAxioms ++ allowance.pendingAxioms ++ allowance.nativeAxioms sortNames <| if allowance.sorryOrigins.isEmpty then expected else expected.push ``sorryAx -private def checkOne (allowance : RootAllowance) : CommandElabM Unit := do +private def checkOne (allowance : RootAllowance) (dependencyAudit : DependencyAudit.State) : + CommandElabM Unit := do validateCategories allowance let env ← getEnv unless env.contains allowance.root do throwError m!"axiom-audit root does not exist: {allowance.root}" - let actualAxioms := sortNames (← Lean.collectAxioms allowance.root) + let actualAxioms := sortNames dependencyAudit.axioms let expectedAxioms := expectedAxioms allowance unless actualAxioms == expectedAxioms do let missing := expectedAxioms.filter fun name => @@ -164,7 +128,6 @@ private def checkOne (allowance : RootAllowance) : CommandElabM Unit := do -- Origin and architectural-quarantine checks consume the same transitive -- dependency graph. Keep one exact traversal per root: large generated -- recursor proofs make two independent walks unnecessarily expensive. - let dependencyAudit := DependencyAudit.collect env allowance.root let actualOrigins := sortNames dependencyAudit.origins let expectedOrigins := sortNames allowance.sorryOrigins unless actualOrigins == expectedOrigins do @@ -173,12 +136,12 @@ private def checkOne (allowance : RootAllowance) : CommandElabM Unit := do actual direct origins: {repr actualOrigins.toList}" -- A root is unconditional exactly when it has no explicitly enumerated - -- pending-upstream axioms. Such a root must not reach even axiom-free + -- pending metatheory axioms. Such a root must not reach even axiom-free -- helper definitions from the quarantine module: otherwise replacing a -- pending witness could silently change the completed proof surface. if allowance.pendingAxioms.isEmpty then for dependency in dependencyAudit.names do - if dependency.toString.startsWith "Ix.Tc.Upstream.Pending." then + if dependency.toString.startsWith "Ix.Kernel.Frontier.Pending." then throwError m!"{allowance.root}: unconditional root reaches quarantined dependency {dependency}" for forbidden in allowance.forbiddenDependencies do @@ -188,12 +151,17 @@ private def checkOne (allowance : RootAllowance) : CommandElabM Unit := do /-- Check a complete executable trust manifest. Duplicate roots are rejected instead of being silently audited twice. -/ def check (allowances : Array RootAllowance) : CommandElabM Unit := do + let env ← getEnv let mut roots : NameSet := {} + let mut cache : Ix.Theory.Named.AxiomAudit.Cache := {} for allowance in allowances do if roots.contains allowance.root then throwError m!"duplicate axiom-audit root: {allowance.root}" roots := roots.insert allowance.root - checkOne allowance - logInfo m!"Ix.Tc verification trust audit passed for {allowances.size} theorem roots" + let (dependencies, nextCache) := + Ix.Theory.Named.AxiomAudit.collectCached env allowance.root cache + cache := nextCache + checkOne allowance dependencies + logInfo m!"Ix.Kernel verification trust audit passed for {allowances.size} theorem roots" -end Ix.Tc.Verify.Audit +end Ix.Kernel.Verify.Audit diff --git a/Ix/Tc/Verify/Audit/Completed.lean b/Ix/Kernel/Verify/Audit/Completed.lean similarity index 59% rename from Ix/Tc/Verify/Audit/Completed.lean rename to Ix/Kernel/Verify/Audit/Completed.lean index 920f76509..a9659a1d4 100644 --- a/Ix/Tc/Verify/Audit/Completed.lean +++ b/Ix/Kernel/Verify/Audit/Completed.lean @@ -1,138 +1,140 @@ -import Ix.Tc.Verify.Audit.Basic -import Ix.Tc.Verify.Check.Acceptance -import Ix.Tc.Verify.Check.BoundedPipelines -import Ix.Tc.Verify.Check.CheckerEvidence -import Ix.Tc.Verify.Check.FullInferenceApplications -import Ix.Tc.Verify.Check.FullInferenceBinders -import Ix.Tc.Verify.Check.FullInferenceCache -import Ix.Tc.Verify.Check.FullInferenceDispatcher -import Ix.Tc.Verify.Check.FullInferenceProjections -import Ix.Tc.Verify.Check.MemberEvidence -import Ix.Tc.Verify.Check.NatAcceptance -import Ix.Tc.Verify.Check.BlockNatFixture -import Ix.Tc.Verify.Check.PreTranslationScopes -import Ix.Tc.Verify.Check.PositiveFuelSort -import Ix.Tc.Verify.Check.ScopedPositiveFuelCertificate -import Ix.Tc.Verify.Check.SingletonInductive -import Ix.Tc.Verify.Inductive.EnumerationAcceptance -import Ix.Tc.Verify.Check.ProjectionInferencePolicy -import Ix.Tc.Verify.Check.ResetFrame -import Ix.Tc.Verify.Check.SafetyFrame -import Ix.Tc.Verify.Check.PublicStandalone -import Ix.Tc.Verify.Check.PublicBlocks -import Ix.Tc.Verify.Check.ValidatorFrame -import Ix.Tc.Verify.Ctx -import Ix.Tc.Verify.Decl -import Ix.Tc.Verify.DefEq -import Ix.Tc.Verify.DefEq.AcceleratorGates -import Ix.Tc.Verify.DefEq.ApplicationSpine -import Ix.Tc.Verify.DefEq.CacheShell -import Ix.Tc.Verify.DefEq.Closure -import Ix.Tc.Verify.DefEq.DeltaClassification -import Ix.Tc.Verify.DefEq.EqualRankCache -import Ix.Tc.Verify.DefEq.EqualRankPrefix -import Ix.Tc.Verify.DefEq.EqualRankReduction -import Ix.Tc.Verify.DefEq.FinalWhnf.Application -import Ix.Tc.Verify.DefEq.FinalWhnf.Closure -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts -import Ix.Tc.Verify.DefEq.FinalWhnf.EtaExpansion -import Ix.Tc.Verify.DefEq.FinalWhnf.LetDeclaration -import Ix.Tc.Verify.DefEq.FinalWhnf.NatBridge -import Ix.Tc.Verify.DefEq.FinalWhnf.ProofTail -import Ix.Tc.Verify.DefEq.FinalWhnf.StringExpansion -import Ix.Tc.Verify.DefEq.FinalWhnf.StructuralPrefix -import Ix.Tc.Verify.DefEq.FinalWhnf.StructureEta -import Ix.Tc.Verify.DefEq.FinalWhnf.UnitLike -import Ix.Tc.Verify.DefEq.LazyDelta -import Ix.Tc.Verify.DefEq.LazyDeltaClosure -import Ix.Tc.Verify.DefEq.LazyDeltaIteration -import Ix.Tc.Verify.DefEq.LoopFinish -import Ix.Tc.Verify.DefEq.NatOffset -import Ix.Tc.Verify.DefEq.NatOffsetDecomposition -import Ix.Tc.Verify.DefEq.NatReduction -import Ix.Tc.Verify.DefEq.OneSidedDelta -import Ix.Tc.Verify.DefEq.ProjectionDeltaActive -import Ix.Tc.Verify.DefEq.ProjectionDeltaClosure -import Ix.Tc.Verify.DefEq.ProjectionDeltaEqualRank -import Ix.Tc.Verify.DefEq.ProjectionDeltaFinish -import Ix.Tc.Verify.DefEq.ProjectionDeltaLoop -import Ix.Tc.Verify.DefEq.ProjectionDeltaRank -import Ix.Tc.Verify.DefEq.ProjectionDeltaStep -import Ix.Tc.Verify.DefEq.ProjectionDeltaUnfolding -import Ix.Tc.Verify.DefEq.ProjectionProbe -import Ix.Tc.Verify.DefEq.ProjectionReduction -import Ix.Tc.Verify.DefEq.PropositionClassifier -import Ix.Tc.Verify.DefEq.RankDispatch -import Ix.Tc.Verify.DefEq.SameHeadSpine -import Ix.Tc.Verify.DefEq.SpineArguments -import Ix.Tc.Verify.DefEq.StoppedContinuation -import Ix.Tc.Verify.DefEq.StoppedContinuationClosure -import Ix.Tc.Verify.DefEq.StructuralCongruence -import Ix.Tc.Verify.Driver.Fixtures -import Ix.Tc.Verify.Driver.BooleanAcceptance -import Ix.Tc.Verify.Driver.SupportedAcceptanceFixtures -import Ix.Tc.Verify.Execution -import Ix.Tc.Verify.Frame -import Ix.Tc.Verify.Infer.CacheSoundness -import Ix.Tc.Verify.InferDefEq.Closure -import Ix.Tc.Verify.Inductive.Certificate -import Ix.Tc.Verify.Inductive.AliasFormerAdmission -import Ix.Tc.Verify.Inductive.AliasRecAdmission -import Ix.Tc.Verify.Inductive.AnnotatedPiCertificate -import Ix.Tc.Verify.Inductive.AnnotatedPiAdmission -import Ix.Tc.Verify.Inductive.EliminationBreadthFixture -import Ix.Tc.Verify.Inductive.MutualBlockCertificate -import Ix.Tc.Verify.Inductive.MutualFamilyAdmission -import Ix.Tc.Verify.Inductive.IndexedRecursiveCertificate -import Ix.Tc.Verify.Inductive.RecursivePiCertificate -import Ix.Tc.Verify.Inductive.RecursivePiAdmission -import Ix.Tc.Verify.Inductive.IndexedRecursiveAcceptance -import Ix.Tc.Verify.Inductive.IndexedConstructorValidation -import Ix.Tc.Verify.Inductive.SpecializationIdentity -import Ix.Tc.Verify.Inductive.GeneratedRecursorMetadata -import Ix.Tc.Verify.Inductive.GeneratedRecursorAcceptance -import Ix.Tc.Verify.Inductive.GeneratedRecursorAcceptanceClosure -import Ix.Tc.Verify.Inductive.GeneratedRecursorAdmission -import Ix.Tc.Verify.Inductive.IndexedProducerClosure -import Ix.Tc.Verify.Inductive.GeneratedRecursorCheckerFixture -import Ix.Tc.Verify.Inductive.GeneratedRecursorCommitFixture -import Ix.Tc.Verify.Inductive.GeneratedRecursorComparison -import Ix.Tc.Verify.Inductive.GeneratedRecursorRuleFixture -import Ix.Tc.Verify.Inductive.GeneratedRecursorSelection -import Ix.Tc.Verify.Inductive.GeneratedRecursorSemantics -import Ix.Tc.Verify.Inductive.GeneratedRecursorTypeClosure -import Ix.Tc.Verify.Inductive.GeneratedRecursorTypeFixture -import Ix.Tc.Verify.Inductive.NestedAuxiliaryExpansion -import Ix.Tc.Verify.Inductive.NestedAdmission -import Ix.Tc.Verify.Inductive.NestedConstructorValidation -import Ix.Tc.Verify.Inductive.NestedRecursiveFixture -import Ix.Tc.Verify.Inductive.NestedRecursorAdmission -import Ix.Tc.Verify.Inductive.OccurrenceClosure -import Ix.Tc.Verify.Inductive.PositivityTraceAdapter -import Ix.Tc.Verify.Inductive.RecursivePositivityTraversal -import Ix.Tc.Verify.Ingress.LiteralBlobs -import Ix.Tc.Verify.Ingress.SerializedBoolean -import Ix.Tc.Verify.InstL -import Ix.Tc.Verify.Whnf.Closure -import Ix.Tc.Verify.Knot -import Ix.Tc.Verify.NatFixture -import Ix.Tc.Verify.Projection.ConcreteFixture -import Ix.Tc.Verify.Run -import Ix.Tc.Verify.RecursiveMethods.Closure -import Ix.Tc.Verify.RecursiveMethods.FiniteSupportBoundary -import Ix.Tc.Verify.RecursiveMethods.Public -import Ix.Tc.Verify.Support -import Ix.Tc.Verify.Totalization -import Ix.Tc.Verify.Whnf -import Ix.Tc.Verify.World +import Ix.Kernel.Verify.Audit.Basic +import Ix.Kernel.Verify.Check.Acceptance +import Ix.Kernel.Verify.Check.BoundedPipelines +import Ix.Kernel.Verify.Check.CheckerEvidence +import Ix.Kernel.Verify.Check.FullInferenceApplications +import Ix.Kernel.Verify.Check.FullInferenceBinders +import Ix.Kernel.Verify.Check.FullInferenceCache +import Ix.Kernel.Verify.Check.FullInferenceDispatcher +import Ix.Kernel.Verify.Check.FullInferenceProjections +import Ix.Kernel.Verify.Check.MemberEvidence +import Ix.Kernel.Verify.Check.NatAcceptance +import Ix.Kernel.Verify.Check.BlockNatFixture +import Ix.Kernel.Verify.Check.PreTranslationScopes +import Ix.Kernel.Verify.Check.PositiveFuelSort +import Ix.Kernel.Verify.Check.ScopedPositiveFuelCertificate +import Ix.Kernel.Verify.Check.SingletonInductive +import Ix.Kernel.Verify.Inductive.EnumerationAcceptance +import Ix.Kernel.Verify.Check.ProjectionInferencePolicy +import Ix.Kernel.Verify.Check.ResetFrame +import Ix.Kernel.Verify.Check.SafetyFrame +import Ix.Kernel.Verify.Check.PublicStandalone +import Ix.Kernel.Verify.Check.PublicBlocks +import Ix.Kernel.Verify.Check.ValidatorFrame +import Ix.Kernel.Verify.Ctx +import Ix.Kernel.Verify.Decl +import Ix.Kernel.Verify.DefEq +import Ix.Kernel.Verify.DefEq.AcceleratorGates +import Ix.Kernel.Verify.DefEq.ApplicationSpine +import Ix.Kernel.Verify.DefEq.CacheShell +import Ix.Kernel.Verify.DefEq.Closure +import Ix.Kernel.Verify.DefEq.DeltaClassification +import Ix.Kernel.Verify.DefEq.EqualRankCache +import Ix.Kernel.Verify.DefEq.EqualRankPrefix +import Ix.Kernel.Verify.DefEq.EqualRankReduction +import Ix.Kernel.Verify.DefEq.FinalWhnf.Application +import Ix.Kernel.Verify.DefEq.FinalWhnf.Closure +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.DefEq.FinalWhnf.EtaExpansion +import Ix.Kernel.Verify.DefEq.FinalWhnf.LetDeclaration +import Ix.Kernel.Verify.DefEq.FinalWhnf.NatBridge +import Ix.Kernel.Verify.DefEq.FinalWhnf.ProofTail +import Ix.Kernel.Verify.DefEq.FinalWhnf.StringExpansion +import Ix.Kernel.Verify.DefEq.FinalWhnf.StructuralPrefix +import Ix.Kernel.Verify.DefEq.FinalWhnf.StructureEta +import Ix.Kernel.Verify.DefEq.FinalWhnf.UnitLike +import Ix.Kernel.Verify.DefEq.LazyDelta +import Ix.Kernel.Verify.DefEq.LazyDeltaClosure +import Ix.Kernel.Verify.DefEq.LazyDeltaIteration +import Ix.Kernel.Verify.DefEq.LoopFinish +import Ix.Kernel.Verify.DefEq.NatOffset +import Ix.Kernel.Verify.DefEq.NatOffsetDecomposition +import Ix.Kernel.Verify.DefEq.NatReduction +import Ix.Kernel.Verify.DefEq.OneSidedDelta +import Ix.Kernel.Verify.DefEq.ProjectionDeltaActive +import Ix.Kernel.Verify.DefEq.ProjectionDeltaClosure +import Ix.Kernel.Verify.DefEq.ProjectionDeltaEqualRank +import Ix.Kernel.Verify.DefEq.ProjectionDeltaFinish +import Ix.Kernel.Verify.DefEq.ProjectionDeltaLoop +import Ix.Kernel.Verify.DefEq.ProjectionDeltaRank +import Ix.Kernel.Verify.DefEq.ProjectionDeltaStep +import Ix.Kernel.Verify.DefEq.ProjectionDeltaUnfolding +import Ix.Kernel.Verify.DefEq.ProjectionProbe +import Ix.Kernel.Verify.DefEq.ProjectionReduction +import Ix.Kernel.Verify.DefEq.PropositionClassifier +import Ix.Kernel.Verify.DefEq.RankDispatch +import Ix.Kernel.Verify.DefEq.SameHeadSpine +import Ix.Kernel.Verify.DefEq.SpineArguments +import Ix.Kernel.Verify.DefEq.StoppedContinuation +import Ix.Kernel.Verify.DefEq.StoppedContinuationClosure +import Ix.Kernel.Verify.DefEq.StructuralCongruence +import Ix.Kernel.Verify.Driver.Fixtures +import Ix.Kernel.Verify.Driver.BooleanAcceptance +import Ix.Kernel.Verify.Driver.SupportedAcceptanceFixtures +import Ix.Kernel.Verify.Execution +import Ix.Kernel.Verify.Frame +import Ix.Kernel.Verify.Infer.CacheSoundness +import Ix.Kernel.Verify.InferDefEq.Closure +import Ix.Kernel.Verify.Inductive.Certificate +import Ix.Kernel.Verify.Inductive.AliasFormerAdmission +import Ix.Kernel.Verify.Inductive.AliasRecAdmission +import Ix.Kernel.Verify.Inductive.AnnotatedPiCertificate +import Ix.Kernel.Verify.Inductive.AnnotatedPiAdmission +import Ix.Kernel.Verify.Inductive.EliminationBreadthFixture +import Ix.Kernel.Verify.Inductive.MutualBlockCertificate +import Ix.Kernel.Verify.Inductive.MutualFamilyAdmission +import Ix.Kernel.Verify.Inductive.IndexedRecursiveCertificate +import Ix.Kernel.Verify.Inductive.RecursivePiCertificate +import Ix.Kernel.Verify.Inductive.RecursivePiAdmission +import Ix.Kernel.Verify.Inductive.IndexedRecursiveAcceptance +import Ix.Kernel.Verify.Inductive.IndexedConstructorValidation +import Ix.Kernel.Verify.Inductive.SpecializationIdentity +import Ix.Kernel.Verify.Inductive.GeneratedRecursorMetadata +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAcceptance +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAcceptanceClosure +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAdmission +import Ix.Kernel.Verify.Inductive.IndexedProducerClosure +import Ix.Kernel.Verify.Inductive.GeneratedRecursorCheckerFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorCommitFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorComparison +import Ix.Kernel.Verify.Inductive.GeneratedRecursorRuleFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorSelection +import Ix.Kernel.Verify.Inductive.GeneratedRecursorSemantics +import Ix.Kernel.Verify.Inductive.GeneratedRecursorTypeClosure +import Ix.Kernel.Verify.Inductive.GeneratedRecursorTypeFixture +import Ix.Kernel.Verify.Inductive.NestedAuxiliaryExpansion +import Ix.Kernel.Verify.Inductive.NestedAdmission +import Ix.Kernel.Verify.Inductive.NestedConstructorValidation +import Ix.Kernel.Verify.Inductive.NestedRecursiveFixture +import Ix.Kernel.Verify.Inductive.NestedRecursorAdmission +import Ix.Kernel.Verify.Inductive.OccurrenceClosure +import Ix.Kernel.Verify.Inductive.PositivityTraceAdapter +import Ix.Kernel.Verify.Inductive.RecursivePositivityTraversal +import Ix.Kernel.Verify.Ingress.LiteralBlobs +import Ix.Kernel.Verify.Ingress.SerializedBoolean +import Ix.Kernel.Verify.InstL +import Ix.Kernel.Verify.Whnf.Closure +import Ix.Kernel.Verify.Knot +import Ix.Kernel.Verify.NatFixture +import Ix.Kernel.Verify.Projection.ConcreteFixture +import Ix.Kernel.Verify.Run +import Ix.Kernel.Verify.RecursiveMethods.Closure +import Ix.Kernel.Verify.RecursiveMethods.FiniteSupportBoundary +import Ix.Kernel.Verify.RecursiveMethods.Public +import Ix.Kernel.Verify.Support +import Ix.Kernel.Verify.Totalization +import Ix.Kernel.Verify.Whnf +import Ix.Kernel.Verify.World + +open Ix.Theory (VLevel) /-! -# Trust manifest for the completed `Ix.Tc.Verify` proof surface +# Trust manifest for the completed `Ix.Kernel.Verify` proof surface These are the current completed foundations and reusable semantic interfaces -that later C1--C3 roots will consume. A new headline theorem must be added here -when it becomes part of that exported proof surface. The temporary C1/C2 -statement skeletons are audited separately in `Audit/Statements.lean` +used by lookup, admission, and driver composition. A new headline theorem +must be added here when it becomes part of that exported proof surface. The +temporary statement skeletons are audited separately in `Audit/Statements.lean` because their opaque relation names intentionally collide with the concrete relations imported here. @@ -141,9 +143,9 @@ transitive trust boundary of any one interface should produce a focused CI failure. Shared arrays below are only labels for exactly repeated sets. -/ -namespace Ix.Tc.Verify.Audit.Completed +namespace Ix.Kernel.Verify.Audit.Completed -open Ix.Tc.Verify.Audit +open Ix.Kernel.Verify.Audit private def standard : Array Lean.Name := #[``propext, ``Classical.choice, ``Quot.sound] @@ -156,12 +158,12 @@ private def standardWithoutQuot : Array Lean.Name := private def propextOnly : Array Lean.Name := #[``propext] -/- The executable `AnnotatedPi` replay in the pinned Lean4Lean fork crosses +/- The executable `AnnotatedPi` replay in the local named specification crosses its verified wrappers for Lean's pointer-aware expression implementation. Keep that nonlogical upstream footprint distinct from `standard`: these are not ordinary logical axioms and must not become globally permitted. -/ private def annotatedPiUpstreamAxioms : Array Lean.Name := #[ - ``Lean4Lean.ptrEqConstantInfo_eq, + ``Ix.Theory.Named.ptrEqConstantInfo_eq, ``Lean.Expr.abstractRange_eq, ``Lean.Expr.abstract_eq, ``Lean.Expr.eqv_eq, @@ -189,17 +191,17 @@ private def annotatedPiUpstreamAxioms : Array Lean.Name := #[ ``Std.TreeMap.all_eq_all_toList ] -/- Exact direct `sorryAx` frontier inherited from Lean4Lean's executable +/- Exact direct `sorryAx` frontier inherited from Ix.Theory.Named's executable candidate-normalization proof. Unlike the earlier closed-form fixtures, `AnnotatedPi` exercises the verified implementation path far enough to reach the currently declared projection/typechecker proof debt. -/ private def annotatedPiUpstreamDebt : Array Lean.Name := #[ - ``Lean4Lean.VEnv.IsDefEqU.forallE_inv_stratified, - ``Lean4Lean.VEnv.IsDefEqU.sort_forallE_inv, - ``Lean4Lean.VEnv.IsDefEqU.sort_inv, - ``Lean4Lean.VEnv.IsDefEqU.weakN_iff, - ``Lean4Lean.VEnv.WF.registeredStructureHeadInversion, - ``Lean4Lean.TypeChecker.Inner.reduceRecursor.WF + ``Ix.Theory.Named.VEnv.IsDefEqU.forallE_inv_stratified, + ``Ix.Theory.Named.VEnv.IsDefEqU.sort_forallE_inv, + ``Ix.Theory.Named.VEnv.IsDefEqU.sort_inv, + ``Ix.Theory.Named.VEnv.IsDefEqU.weakN_iff, + ``Ix.Theory.Named.VEnv.WF.registeredStructureHeadInversion, + ``Ix.Theory.Named.TypeChecker.Inner.reduceRecursor.WF ] /- `AliasFormer` reaches the same executable normalization boundary as @@ -211,7 +213,7 @@ private def aliasFormerUpstreamAxioms : Array Lean.Name := private def aliasFormerUpstreamDebt : Array Lean.Name := annotatedPiUpstreamDebt.push - ``Lean4Lean.InductiveReplayFixtures.aliasFormerAlignmentRun + ``Ix.Theory.Named.InductiveReplayFixtures.aliasFormerAlignmentRun /- `AliasRec` reaches the same executable normalization boundary while unfolding a reducible wrapper around a recursive constructor field. Keep its @@ -222,31 +224,26 @@ private def aliasRecUpstreamAxioms : Array Lean.Name := private def aliasRecUpstreamDebt : Array Lean.Name := annotatedPiUpstreamDebt -private def blake3Native : Array Lean.Name := #[ - nativeAxiom `Blake3 - `Blake3.HasherOps.hash._native.native_decide.ax_1 -] - -private def expressionNative : Array Lean.Name := blake3Native.push - (nativeAxiom `Ix.Tc.Expr - `Ix.Tc.KExpr.mkVar._native.native_decide.ax_1) +private def expressionNative : Array Lean.Name := #[].push + (nativeAxiom `Ix.Kernel.Expr + `Ix.Kernel.KExpr.mkVar._native.native_decide.ax_1) private def levelNative : Array Lean.Name := expressionNative.push - (nativeAxiom `Ix.Tc.Level - `Ix.Tc.KUniv.mkSucc._native.native_decide.ax_1) + (nativeAxiom `Ix.Kernel.Level + `Ix.Kernel.KUniv.mkSucc._native.native_decide.ax_1) -private def occurrenceValidationNative : Array Lean.Name := blake3Native.push - (nativeAxiom `Ix.Tc.Level - `Ix.Tc.KUniv.mkSucc._native.native_decide.ax_1) +private def occurrenceValidationNative : Array Lean.Name := #[].push + (nativeAxiom `Ix.Kernel.Level + `Ix.Kernel.KUniv.mkSucc._native.native_decide.ax_1) private def specializationIdentityNative : Array Lean.Name := occurrenceValidationNative.push - (nativeAxiom `Ix.Tc.Verify.Inductive.SpecializationIdentity - `Ix.Tc.SpecializationIdentityFixture.semanticUniverseEquality_does_not_collapse_specializationNative._native.native_decide.ax_1_1) + (nativeAxiom `Ix.Kernel.Verify.Inductive.SpecializationIdentity + `Ix.Kernel.SpecializationIdentityFixture.semanticUniverseEquality_does_not_collapse_specializationNative._native.native_decide.ax_1_1) private def univOnlyNative : Array Lean.Name := #[ - nativeAxiom `Ix.Tc.Level - `Ix.Tc.KUniv.mkSucc._native.native_decide.ax_1 + nativeAxiom `Ix.Kernel.Level + `Ix.Kernel.KUniv.mkSucc._native.native_decide.ax_1 ] private def nameDecideNative : Lean.Name := @@ -259,38 +256,31 @@ private def expressionNameNative : Array Lean.Name := expressionNative.push nameDecideNative private def canonicalPrimitivesNative : Array Lean.Name := - blake3Native.push nameDecideNative - -private def ctxAddrNative : Lean.Name := - nativeAxiom `Ix.Tc.Monad - `Ix.Tc.TcM.ctxAddrForLbrUncached._native.native_decide.ax_3 - -private def blake3ContextNative : Array Lean.Name := - blake3Native.push ctxAddrNative + #[].push nameDecideNative private def contextNative : Array Lean.Name := - expressionNative.push ctxAddrNative + expressionNative private def inferNative : Array Lean.Name := - levelNative.push ctxAddrNative + levelNative private def nameContextNative : Array Lean.Name := - nameNative.push ctxAddrNative + nameNative private def canonicalPrimitivesContextNative : Array Lean.Name := - canonicalPrimitivesNative.push ctxAddrNative + canonicalPrimitivesNative private def natAddNeSuccNative : Lean.Name := - nativeAxiom `Ix.Tc.Verify.NatFixture - `Ix.Tc.AmbientNat.natAdd_ne_natSucc._native.native_decide.ax_1_1 + nativeAxiom `Ix.Kernel.Verify.NatFixture + `Ix.Kernel.AmbientNat.natAdd_ne_natSucc._native.native_decide.ax_1_1 private def natAddNeBeqNative : Lean.Name := - nativeAxiom `Ix.Tc.Verify.NatFixture - `Ix.Tc.AmbientNat.natAdd_ne_natBeq._native.native_decide.ax_1_1 + nativeAxiom `Ix.Kernel.Verify.NatFixture + `Ix.Kernel.AmbientNat.natAdd_ne_natBeq._native.native_decide.ax_1_1 private def natAddNeBleNative : Lean.Name := - nativeAxiom `Ix.Tc.Verify.NatFixture - `Ix.Tc.AmbientNat.natAdd_ne_natBle._native.native_decide.ax_1_1 + nativeAxiom `Ix.Kernel.Verify.NatFixture + `Ix.Kernel.AmbientNat.natAdd_ne_natBle._native.native_decide.ax_1_1 private def natReductionNative : Array Lean.Name := (((contextNative.push nameDecideNative).push natAddNeSuccNative).push @@ -311,8 +301,8 @@ private def natBranchOrderNative : Array Lean.Name := private def inductiveNative : Array Lean.Name := (inferNative.push (nativeAxiom `Ix.Environment `Ix.Name.mkStr._native.native_decide.ax_1)).push - (nativeAxiom `Ix.Tc.Inductive - `Ix.Tc.RecM.canonicalAuxOrder._native.native_decide.ax_9) + (nativeAxiom `Ix.Kernel.Inductive + `Ix.Kernel.RecM.canonicalAuxOrder._native.native_decide.ax_9) /- Mutual-block fixtures use many small closed `native_decide` facts. Build their exact private names structurally so the audit stays reviewable while @@ -321,7 +311,7 @@ private def mutualNativeUserName (decl : String) (index : Nat) : Lean.Name := Lean.Name.str (Lean.Name.str (Lean.Name.str - (Lean.Name.str `Ix.Tc.MutualTreeFixture decl) + (Lean.Name.str `Ix.Kernel.MutualTreeFixture decl) "_native") "native_decide") s!"ax_1_{index + 1}" @@ -341,15 +331,15 @@ private def mutualNativeSingletons (moduleName : Lean.Name) private def mutualFamilyAdmissionNativeSeries (decl : String) (count : Nat) : Array Lean.Name := - mutualNativeSeries `Ix.Tc.Verify.Inductive.MutualFamilyAdmission decl count + mutualNativeSeries `Ix.Kernel.Verify.Inductive.MutualFamilyAdmission decl count private def mutualBlockFixtureNativeSeries (decl : String) (count : Nat) : Array Lean.Name := - mutualNativeSeries `Ix.Tc.Verify.Inductive.MutualBlockFixture decl count + mutualNativeSeries `Ix.Kernel.Verify.Inductive.MutualBlockFixture decl count private def mutualRecursorAdmissionNativeSeries (decl : String) (count : Nat) : Array Lean.Name := - mutualNativeSeries `Ix.Tc.Verify.Inductive.MutualRecursorAdmission decl count + mutualNativeSeries `Ix.Kernel.Verify.Inductive.MutualRecursorAdmission decl count private def mutualInternDataValueNative : Lean.Name := nativeAxiom `Ix.CanonM @@ -378,20 +368,20 @@ def mutualFamilyNative : Array Lean.Name := mutualPublicNativeSeries "nameOf_treeList" 2 ++ mutualPublicNativeSeries "familyMembers_eq" 1 ++ mutualPublicNativeSeries "recursorMembers_eq" 1 ++ - mutualNativeSingletons `Ix.Tc.Verify.Inductive.MutualBlockFixture #[ + mutualNativeSingletons `Ix.Kernel.Verify.Inductive.MutualBlockFixture #[ "familyAuxCompileSucceededNative", "familyBlockLoadedNative", "familyIngressSucceededNative", "recursorBlockLoadedNative", "recursorIngressSucceededNative" ] ++ - mutualNativeSingletons `Ix.Tc.Verify.Inductive.MutualBlockValidation #[ + mutualNativeSingletons `Ix.Kernel.Verify.Inductive.MutualBlockValidation #[ "familyKernelSucceededNative", "recursorKernelSucceededNative" ] ++ mutualFamilyAdmissionNativeSeries "familyMemberShapeFactsNative" 19 ++ mutualFamilyAdmissionNativeSeries "ownershipShapeFactsNative" 9 ++ - mutualNativeSingletons `Ix.Tc.Verify.Inductive.MutualFamilyAdmission #[ + mutualNativeSingletons `Ix.Kernel.Verify.Inductive.MutualFamilyAdmission #[ "treeBranchTypeRawNative", "treeLeafTypeRawNative", "treeListConsTypeRawNative", @@ -411,7 +401,7 @@ def mutualRecursorConditionalNative : Array Lean.Name := mutualRecursorAdmissionNativeSeries "physicalSourceMembershipFactsNative" 5 ++ mutualRecursorAdmissionNativeSeries "recursorRepresentationFactsNative" 55 ++ - mutualNativeSingletons `Ix.Tc.Verify.Inductive.MutualRecursorAdmission #[ + mutualNativeSingletons `Ix.Kernel.Verify.Inductive.MutualRecursorAdmission #[ "branchRuleRawNative", "consRuleRawNative", "flatCtorFour", @@ -443,187 +433,187 @@ def mutualRecursorConditionalNative : Array Lean.Name := ] private def recursivePiFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.RecursivePiFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.RecursivePiFixture name private def recursivePiRecursorFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.RecursivePiRecursorFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.RecursivePiRecursorFixture name private def recursivePiAdmissionNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.RecursivePiAdmission name + nativeAxiom `Ix.Kernel.Verify.Inductive.RecursivePiAdmission name private def annotatedPiCertificateNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AnnotatedPiCertificate name + nativeAxiom `Ix.Kernel.Verify.Inductive.AnnotatedPiCertificate name private def annotatedPiCertificateBreadthNative : Array Lean.Name := #[ annotatedPiCertificateNativeAxiom - `Ix.Tc.AnnotatedPiCertificateFixture.breadthNative._native.native_decide.ax_1_1 + `Ix.Kernel.AnnotatedPiCertificateFixture.breadthNative._native.native_decide.ax_1_1 ] private def annotatedPiFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AnnotatedPiFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.AnnotatedPiFixture name private def annotatedPiRecursorFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AnnotatedPiRecursorFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.AnnotatedPiRecursorFixture name private def annotatedPiAdmissionNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AnnotatedPiAdmission name + nativeAxiom `Ix.Kernel.Verify.Inductive.AnnotatedPiAdmission name private def aliasFormerCertificateNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasFormerCertificate name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasFormerCertificate name private def aliasFormerCertificateBreadthNative : Array Lean.Name := #[ aliasFormerCertificateNativeAxiom - `Ix.Tc.AliasFormerCertificateFixture.breadthNative._native.native_decide.ax_1_1 + `Ix.Kernel.AliasFormerCertificateFixture.breadthNative._native.native_decide.ax_1_1 ] private def aliasFormerFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasFormerFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasFormerFixture name private def aliasFormerPatternNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasFormerPattern name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasFormerPattern name private def aliasFormerRecursorFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasFormerRecursorFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasFormerRecursorFixture name private def aliasFormerAdmissionNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasFormerAdmission name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasFormerAdmission name private def aliasRecCertificateNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasRecCertificate name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasRecCertificate name private def aliasRecCertificateBreadthNative : Array Lean.Name := #[ aliasRecCertificateNativeAxiom - `Ix.Tc.AliasRecCertificateFixture.breadthNative._native.native_decide.ax_1_1 + `Ix.Kernel.AliasRecCertificateFixture.breadthNative._native.native_decide.ax_1_1 ] private def aliasRecFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasRecFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasRecFixture name private def aliasRecRecursorFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasRecRecursorFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasRecRecursorFixture name private def aliasRecAdmissionNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.AliasRecAdmission name + nativeAxiom `Ix.Kernel.Verify.Inductive.AliasRecAdmission name /- Exact executable footprint of the family-result-normalizing AliasFormer family/recursor transaction. -/ private def aliasFormerAtomicClosureNative : Array Lean.Name := inductiveNative ++ aliasFormerCertificateBreadthNative ++ #[ aliasFormerAdmissionNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, aliasFormerAdmissionNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.entriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.entriesSizeNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.entriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.entriesUniqueNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.entryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.entryAtOneNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.entryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.entryAtZeroNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.entryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.entryIdsNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.familyEntryNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.familyShapeNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.memberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.memberKidsNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.mkEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.mkEntryNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.mkShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.mkShapeNative._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.sourceConstructorZero._native.native_decide.ax_1_1, aliasFormerFixtureNativeAxiom - `Ix.Tc.AliasFormerFixture.typeFamilyAliasIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerFixture.typeFamilyAliasIngressSucceededNative._native.native_decide.ax_1_1, aliasFormerPatternNativeAxiom - `Ix.Tc.AliasFormerPattern.generationCtorPairsNonempty._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerPattern.generationCtorPairsNonempty._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_2, + `Ix.Kernel.AliasFormerRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_2, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogMkNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.catalogMkNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogMkNative._native.native_decide.ax_1_2, + `Ix.Kernel.AliasFormerRecursorFixture.catalogMkNative._native.native_decide.ax_1_2, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogMkNative._native.native_decide.ax_1_3, + `Ix.Kernel.AliasFormerRecursorFixture.catalogMkNative._native.native_decide.ax_1_3, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_4, + `Ix.Kernel.AliasFormerRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_4, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.catalogTypeFamilyAliasNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.catalogTypeFamilyAliasNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.mkRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.mkRuleBinderCoreNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.mkRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.mkRuleFieldsNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.mkRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.mkRuleRawNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.mkRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.mkRuleScopedNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.mkRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.mkRuleSizeBoundNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.mkSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.mkSourceNameNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.mkTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.mkTypeRawNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.nameOfMkNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.nameOfMkNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.nameOfTypeFamilyAliasNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.nameOfTypeFamilyAliasNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasFormerRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1, aliasFormerRecursorFixtureNativeAxiom - `Ix.Tc.AliasFormerRecursorFixture.typeFamilyAliasTranslationsNative._native.native_decide.ax_1_1 + `Ix.Kernel.AliasFormerRecursorFixture.typeFamilyAliasTranslationsNative._native.native_decide.ax_1_1 ] /- Exact executable footprint of the recursive-field-normalizing `AliasRec` @@ -631,113 +621,113 @@ family/recursor transaction. -/ private def aliasRecAtomicClosureNative : Array Lean.Name := inductiveNative ++ aliasRecCertificateBreadthNative ++ #[ aliasRecAdmissionNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, aliasRecAdmissionNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.entriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.entriesSizeNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.entriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.entriesUniqueNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.entryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.entryAtOneNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.entryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.entryAtZeroNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.entryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.entryIdsNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.familyEntryNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.familyShapeNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.memberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.memberKidsNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.mkEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.mkEntryNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.mkShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.mkShapeNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.recAliasIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.recAliasIngressSucceededNative._native.native_decide.ax_1_1, aliasRecFixtureNativeAxiom - `Ix.Tc.AliasRecFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecFixture.sourceConstructorZero._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_2, + `Ix.Kernel.AliasRecRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_2, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogMkNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.catalogMkNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogMkNative._native.native_decide.ax_1_2, + `Ix.Kernel.AliasRecRecursorFixture.catalogMkNative._native.native_decide.ax_1_2, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogMkNative._native.native_decide.ax_1_3, + `Ix.Kernel.AliasRecRecursorFixture.catalogMkNative._native.native_decide.ax_1_3, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogRecAliasNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.catalogRecAliasNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_4, + `Ix.Kernel.AliasRecRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_4, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.mkRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.mkRuleBinderCoreNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.mkRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.mkRuleFieldsNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.mkRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.mkRuleRawNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.mkRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.mkRuleScopedNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.mkRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.mkRuleSizeBoundNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.mkSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.mkSourceNameNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.mkTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.mkTypeRawNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.nameOfMkNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.nameOfMkNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.nameOfRecAliasNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.nameOfRecAliasNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recAliasTranslationsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recAliasTranslationsNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AliasRecRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, aliasRecRecursorFixtureNativeAxiom - `Ix.Tc.AliasRecRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1 + `Ix.Kernel.AliasRecRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1 ] /- Exact executable footprint of the annotation-normalizing family/recursor @@ -746,113 +736,113 @@ family, constructor, and recursor entries. -/ private def annotatedPiAtomicClosureNative : Array Lean.Name := inductiveNative ++ annotatedPiCertificateBreadthNative ++ #[ annotatedPiAdmissionNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, annotatedPiAdmissionNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.entriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.entriesSizeNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.entriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.entriesUniqueNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.entryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.entryAtOneNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.entryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.entryAtZeroNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.entryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.entryIdsNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.familyEntryNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.familyShapeNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.memberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.memberKidsNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.mkEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.mkEntryNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.mkShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.mkShapeNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.outParamIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.outParamIngressSucceededNative._native.native_decide.ax_1_1, annotatedPiFixtureNativeAxiom - `Ix.Tc.AnnotatedPiFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiFixture.sourceConstructorZero._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_2, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_2, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogMkNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogMkNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogMkNative._native.native_decide.ax_1_2, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogMkNative._native.native_decide.ax_1_2, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogMkNative._native.native_decide.ax_1_3, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogMkNative._native.native_decide.ax_1_3, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogOutParamNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogOutParamNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_4, + `Ix.Kernel.AnnotatedPiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_4, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.mkRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.mkRuleBinderCoreNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.mkRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.mkRuleFieldsNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.mkRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.mkRuleRawNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.mkRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.mkRuleScopedNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.mkRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.mkRuleSizeBoundNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.mkSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.mkSourceNameNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.mkTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.mkTypeRawNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.nameOfMkNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.nameOfMkNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.nameOfOutParamNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.nameOfOutParamNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.outParamTranslationsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.outParamTranslationsNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, annotatedPiRecursorFixtureNativeAxiom - `Ix.Tc.AnnotatedPiRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1 + `Ix.Kernel.AnnotatedPiRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1 ] /- Exact executable footprint of the recursive-Pi family/recursor transaction. @@ -861,291 +851,291 @@ the `Acc` closure cannot silently acquire unrelated native assumptions. -/ private def recursivePiAtomicClosureNative : Array Lean.Name := inductiveNative ++ #[ recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.entriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.entriesSizeNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.entriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.entriesUniqueNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.entryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.entryAtOneNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.entryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.entryAtZeroNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.entryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.entryIdsNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.familyEntryNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.familyShapeNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.ingressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.ingressSucceededNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.introEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.introEntryNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.introShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.introShapeNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.memberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.memberKidsNative._native.native_decide.ax_1_1, recursivePiFixtureNativeAxiom - `Ix.Tc.RecursivePiFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiFixture.sourceConstructorZero._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.catalogFamilyNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.catalogIntroNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.catalogIntroNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.catalogIntroNative._native.native_decide.ax_1_2, + `Ix.Kernel.RecursivePiRecursorFixture.catalogIntroNative._native.native_decide.ax_1_2, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.RecursivePiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_2, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.RecursivePiRecursorFixture.catalogRecursorNative._native.native_decide.ax_1_3, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.constructorCountNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.familyTypeRawNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.generationCtorPairZero._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.introRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.introRuleBinderCoreNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.introRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.introRuleFieldsNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.introRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.introRuleRawNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.introRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.introRuleScopedNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.introRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.introRuleSizeBoundNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.introSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.introSourceNameNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.introTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.introTypeRawNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.nameOfFamilyNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.nameOfIntroNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.nameOfIntroNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.nameOfRecursorNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorEntryNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorEntrySizeNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorShapeNative._native.native_decide.ax_1_1, recursivePiRecursorFixtureNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.recursorTypeRawNative._native.native_decide.ax_1_1, recursivePiAdmissionNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.RecursivePiRecursorFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, recursivePiAdmissionNativeAxiom - `Ix.Tc.RecursivePiRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1 + `Ix.Kernel.RecursivePiRecursorFixture.recursorOwnerNative._native.native_decide.ax_1_1 ] private def enumerationFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.EnumerationFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.EnumerationFixture name private def enumerationAcceptanceNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.EnumerationAcceptance name + nativeAxiom `Ix.Kernel.Verify.Inductive.EnumerationAcceptance name private def indexedRecursiveFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedRecursiveFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedRecursiveFixture name private def indexedRecursiveAcceptanceNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedRecursiveAcceptance name + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedRecursiveAcceptance name private def eliminationBreadthNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.EliminationBreadthFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.EliminationBreadthFixture name private def smallEliminationAcceptanceNative : Array Lean.Name := inductiveNative.push mutualInternDataValueNative ++ #[ - `Lean4Lean.InductiveReplayFixtures.smallSourceAlignment06._native.native_decide.ax_1, - `Lean4Lean.InductiveReplayFixtures.smallSourceEliminationResult06_isOk._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_2, - `Ix.Tc.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_3, - `Ix.Tc.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_4, - `Ix.Tc.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_5, - `Ix.Tc.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_6, - `Ix.Tc.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_7, - `Ix.Tc.EliminationBreadthFixture.smallComputeKMatches_eq._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.smallPreparationMatches_eq._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.smallRecursorShape._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.smallTheoryRecUvars._native.native_decide.ax_1_1, + `Ix.Theory.Named.InductiveReplayFixtures.smallSourceAlignment06._native.native_decide.ax_1, + `Ix.Theory.Named.InductiveReplayFixtures.smallSourceEliminationResult06_isOk._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_2, + `Ix.Kernel.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_3, + `Ix.Kernel.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_4, + `Ix.Kernel.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_5, + `Ix.Kernel.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_6, + `Ix.Kernel.EliminationBreadthFixture.smallCompiledIdentity._native.native_decide.ax_1_7, + `Ix.Kernel.EliminationBreadthFixture.smallComputeKMatches_eq._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallPreparationMatches_eq._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallRecursorShape._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallTheoryRecUvars._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.smallCompilerSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallCompilerSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.smallExecutionKNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallExecutionKNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.smallExecutionModeNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallExecutionModeNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.smallFamilyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallFamilyIngressSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.smallFamilyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallFamilyKernelSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.smallRecursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.smallRecursorIngressSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.smallRecursorKernelSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.EliminationBreadthFixture.smallRecursorKernelSucceededNative._native.native_decide.ax_1_1 ] private def kTargetAcceptanceNative : Array Lean.Name := inductiveNative.push mutualInternDataValueNative ++ #[ - `Lean4Lean.InductiveReplayFixtures.eqAlignment06._native.native_decide.ax_1, - `Lean4Lean.InductiveReplayFixtures.eqEliminationResult06_isOk._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_2, - `Ix.Tc.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_3, - `Ix.Tc.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_4, - `Ix.Tc.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_5, - `Ix.Tc.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_6, - `Ix.Tc.EliminationBreadthFixture.eqComputeKMatches_eq._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.eqPreparationMatches_eq._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.eqRecursorShape._native.native_decide.ax_1_1, - `Ix.Tc.EliminationBreadthFixture.eqTheoryRecUvars._native.native_decide.ax_1_1, + `Ix.Theory.Named.InductiveReplayFixtures.eqAlignment06._native.native_decide.ax_1, + `Ix.Theory.Named.InductiveReplayFixtures.eqEliminationResult06_isOk._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_2, + `Ix.Kernel.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_3, + `Ix.Kernel.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_4, + `Ix.Kernel.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_5, + `Ix.Kernel.EliminationBreadthFixture.eqCompiledIdentity._native.native_decide.ax_1_6, + `Ix.Kernel.EliminationBreadthFixture.eqComputeKMatches_eq._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqPreparationMatches_eq._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqRecursorShape._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqTheoryRecUvars._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.eqCompilerSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqCompilerSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.eqExecutionKNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqExecutionKNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.eqExecutionModeNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqExecutionModeNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.eqFamilyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqFamilyIngressSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.eqFamilyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqFamilyKernelSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.eqRecursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.EliminationBreadthFixture.eqRecursorIngressSucceededNative._native.native_decide.ax_1_1, eliminationBreadthNativeAxiom - `Ix.Tc.EliminationBreadthFixture.eqRecursorKernelSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.EliminationBreadthFixture.eqRecursorKernelSucceededNative._native.native_decide.ax_1_1 ] private def indexedRecursiveFixtureNativeNames : Array Lean.Name := #[ - `Ix.Tc.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_2, - `Ix.Tc.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_3, - `Ix.Tc.IndexedRecursiveFixture.catalogFamilyNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_2, - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_3, - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_4, - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_5, - `Ix.Tc.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_2, - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_2, - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_3, - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_4, - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_2, - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_3, - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_4, - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_5, - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_6, - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_7, - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_2, - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_3, - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_4, - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_5, - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_6, - `Ix.Tc.IndexedRecursiveFixture.consEntryNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consSourceNameNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consRuleBinderCoreNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consRuleFieldsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consRuleRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consRuleScopedNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consRuleSizeBoundNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consShapeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.consTypeRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.constructorCountNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyEntryIdsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyEntryNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyMemberKidsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyShapeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyTypeRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.generationCtorPairOne._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.generationCtorPairZero._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nameOfConsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nameOfFamilyNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nameOfNatNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nameOfNilNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nameOfRecursorNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nameOfSuccNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nameOfZeroNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natConstructorCountNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natEntriesSizeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natEntriesUniqueNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natEntryAtOneNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natEntryAtTwoNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natEntryAtZeroNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natEntryIdsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natEntryNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natFamilyShapeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natIngressSucceededNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natMemberKidsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natSourceConstructorOne._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natSourceConstructorZero._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natTypeRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilEntryNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilSourceNameNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilRuleBinderCoreNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilRuleFieldsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilRuleRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilRuleScopedNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilRuleSizeBoundNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilShapeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.nilTypeRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorEntryNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorShapeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.sourceConstructorOne._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.sourceConstructorZero._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.succEntryNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.succSourceNameNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.succShapeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.succTypeRawNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.zeroEntryNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.zeroSourceNameNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.zeroShapeNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.zeroTypeRawNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_5, + `Ix.Kernel.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_5, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_6, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_7, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_5, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_6, + `Ix.Kernel.IndexedRecursiveFixture.consEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.constructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationCtorPairOne._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfConsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfNatNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfNilNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfSuccNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natConstructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryAtTwoNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natFamilyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natSourceConstructorOne._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natSourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.sourceConstructorOne._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroTypeRawNative._native.native_decide.ax_1_1 ] private def indexedRecursiveAcceptanceNativeNames : Array Lean.Name := #[ - `Ix.Tc.IndexedRecursiveFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.malformedRecursorRejectedNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natKernelSucceededNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.natNotFamilyDirectOwnerNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, - `Ix.Tc.IndexedRecursiveFixture.recursorOwnerNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.malformedRecursorRejectedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natNotFamilyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorOwnerNative._native.native_decide.ax_1_1 ] private def indexedRecursiveNative : Array Lean.Name := @@ -1161,75 +1151,75 @@ this builder root. -/ private def generatedRecursorTypeFixtureNative : Array Lean.Name := inductiveNative ++ #[ indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeBinderCoreNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeScopedNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeSizeBoundNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorTypeFixture - `Ix.Tc.IndexedRecursiveFixture.familyBuildTypeResultNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorTypeFixture - `Ix.Tc.IndexedRecursiveFixture.familyBuildTypeSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorTypeFixture - `Ix.Tc.IndexedRecursiveFixture.familyPreparationSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeSizeBoundNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorTypeFixture + `Ix.Kernel.IndexedRecursiveFixture.familyBuildTypeResultNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorTypeFixture + `Ix.Kernel.IndexedRecursiveFixture.familyBuildTypeSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorTypeFixture + `Ix.Kernel.IndexedRecursiveFixture.familyPreparationSucceededNative._native.native_decide.ax_1_1 ] private def generatedRecursorRuleFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorRuleFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorRuleFixture name /-- Exact native footprint of the complete IndexedVec peer-alignment and `buildRuleRhs` run. -/ private def generatedRecursorRuleFixtureNative : Array Lean.Name := inductiveNative ++ #[ indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeBinderCoreNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeScopedNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeSizeBoundNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationCtorPairZero._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.generationCtorPairOne._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationCtorPairOne._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleBinderCoreNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleFieldsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleScopedNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleSizeBoundNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleBinderCoreNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleFieldsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleScopedNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleSizeBoundNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyBuiltRulesNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyBuiltRulesNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyCompletedRecursorTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyCompletedRecursorTypeNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyRulePopulationSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyRulePopulationSucceededNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.generationRuleCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationRuleCountNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorRulesLiteralNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.recursorRulesLiteralNative._native.native_decide.ax_1_1 ] /- Exact native footprint of the transactional rule commit. This is kept @@ -1239,63 +1229,63 @@ completed-type observation used by the builder fixture. -/ private def generatedRecursorCommitFixtureNative : Array Lean.Name := inductiveNative ++ #[ indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeBinderCoreNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeScopedNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorTypeSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorTypeSizeBoundNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationCtorPairZero._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.generationCtorPairOne._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationCtorPairOne._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleBinderCoreNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleFieldsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleScopedNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilRuleSizeBoundNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleBinderCoreNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleFieldsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleScopedNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consRuleSizeBoundNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyBuiltRulesNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyBuiltRulesNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyGeneratedSnapshotSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyGeneratedSnapshotSizeNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyGeneratedWithRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyGeneratedWithRulesSizeNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyRulePopulationSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyRulePopulationSucceededNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.generationRuleCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.generationRuleCountNative._native.native_decide.ax_1_1, generatedRecursorRuleFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorRulesLiteralNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorCommitFixture - `Ix.Tc.IndexedRecursiveFixture.familyRuleCommitSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorCommitFixture - `Ix.Tc.IndexedRecursiveFixture.familyGeneratedSnapshotTypeNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.recursorRulesLiteralNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorCommitFixture + `Ix.Kernel.IndexedRecursiveFixture.familyRuleCommitSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorCommitFixture + `Ix.Kernel.IndexedRecursiveFixture.familyGeneratedSnapshotTypeNative._native.native_decide.ax_1_1 ] private def generatedRecursorCheckerFixtureNative : Array Lean.Name := generatedRecursorCommitFixtureNative ++ #[ indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorCheckerFixture - `Ix.Tc.IndexedRecursiveFixture.familyCacheCheckSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorCheckerFixture + `Ix.Kernel.IndexedRecursiveFixture.familyCacheCheckSucceededNative._native.native_decide.ax_1_1 ] /- The additional native facts used to construct the concrete IndexedVec @@ -1303,161 +1293,161 @@ semantic world. They are disjoint from the checker execution footprint above, so the concatenated canonical fixture manifest remains exact. -/ private def generatedRecursorCanonicalWorldNative : Array Lean.Name := #[ indexedRecursiveAcceptanceNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, indexedRecursiveAcceptanceNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, indexedRecursiveAcceptanceNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natNotFamilyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natNotFamilyDirectOwnerNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_2, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogConsNative._native.native_decide.ax_1_3, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogFamilyNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_2, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_3, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_4, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_5, + `Ix.Kernel.IndexedRecursiveFixture.catalogNatNative._native.native_decide.ax_1_5, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogNilNative._native.native_decide.ax_1_2, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_2, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_3, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_4, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_5, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_5, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_6, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_6, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_7, + `Ix.Kernel.IndexedRecursiveFixture.catalogSuccNative._native.native_decide.ax_1_7, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_2, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_3, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_4, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_5, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_5, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_6, + `Ix.Kernel.IndexedRecursiveFixture.catalogZeroNative._native.native_decide.ax_1_6, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consEntryNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consShapeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consSourceNameNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.consTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.consTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.constructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.constructorCountNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryIdsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyEntryNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberKidsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyShapeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nameOfConsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfConsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfFamilyNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nameOfNatNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfNatNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nameOfNilNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfNilNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nameOfSuccNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfSuccNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nameOfZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfZeroNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natConstructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natConstructorCountNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntriesSizeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntriesUniqueNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natEntryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryAtOneNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natEntryAtTwoNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryAtTwoNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natEntryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryAtZeroNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryIdsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natEntryNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natFamilyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natFamilyShapeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natIngressSucceededNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natMemberKidsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natSourceConstructorOne._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natSourceConstructorOne._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natSourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natSourceConstructorZero._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.natTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.natTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilEntryNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilShapeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilSourceNameNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nilTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nilTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.sourceConstructorOne._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.sourceConstructorOne._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.sourceConstructorZero._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.succEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succEntryNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.succShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succShapeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.succSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succSourceNameNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.succTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.succTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.zeroEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroEntryNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.zeroShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroShapeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.zeroSourceNameNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroSourceNameNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.zeroTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.zeroTypeRawNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorShapeNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.recursorShapeNative._native.native_decide.ax_1_1 ] private def generatedRecursorCanonicalFixtureNative : Array Lean.Name := @@ -1466,16 +1456,16 @@ private def generatedRecursorCanonicalFixtureNative : Array Lean.Name := private def generatedRecursorCommitFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorCommitFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorCommitFixture name private def generatedRecursorMemberFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.GeneratedRecursorMemberFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.GeneratedRecursorMemberFixture name private def generatedRecursorInitialInvariantNativeAxiom (name : Lean.Name) : Lean.Name := nativeAxiom - `Ix.Tc.Verify.Inductive.GeneratedRecursorInitialInvariant name + `Ix.Kernel.Verify.Inductive.GeneratedRecursorInitialInvariant name /- Exact executable footprint of the complete concrete recursor-member transaction. The earlier commit and semantic-world manifests are reused @@ -1486,221 +1476,221 @@ private def generatedRecursorAtomicClosureNative : Array Lean.Name := generatedRecursorCommitFixtureNative ++ generatedRecursorCanonicalWorldNative ++ #[ indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorUniverseCountNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_2, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_3, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_4, + `Ix.Kernel.IndexedRecursiveFixture.catalogRecursorNative._native.native_decide.ax_1_4, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.nameOfRecursorNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorEntryNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, indexedRecursiveFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, indexedRecursiveAcceptanceNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, indexedRecursiveAcceptanceNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorOwnerNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.consConcreteHeaderNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyConcreteHeaderNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.recursorOwnerNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.consConcreteHeaderNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyConcreteHeaderNative._native.native_decide.ax_1_1, generatedRecursorCommitFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyInstalledRecursorAtZeroMemberNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyInstalledRecursorAtZeroMemberNative._native.native_decide.ax_1_1, generatedRecursorCommitFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyInstalledRecursorTypeEqNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyInstalledRecursorTypeEqNative._native.native_decide.ax_1_1, generatedRecursorCommitFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyInstalledConsRuleInternSupported._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyInstalledConsRuleInternSupported._native.native_decide.ax_1_1, generatedRecursorCommitFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyInstalledNilRuleInternSupported._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyInstalledNilRuleInternSupported._native.native_decide.ax_1_1, generatedRecursorCommitFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyInstalledRecursorInductiveAddress._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyInstalledRecursorInductiveAddress._native.native_decide.ax_1_1, generatedRecursorCommitFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyInstalledRecursorRules._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyInstalledRecursorRules._native.native_decide.ax_1_1, generatedRecursorCommitFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyInstalledRecursorTypeInternSupported._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyInstalledRecursorTypeInternSupported._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberArityBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberArityBoundNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberSingletonSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberSingletonSizeNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialPrimitivesNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialPrimitivesNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyCharOfNatAbsent._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyCharOfNatAbsent._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberCheckSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberCheckSucceededNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberDirectMajorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberDirectMajorShapeNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialBlocksCoveredNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialBlocksCoveredNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialClosedFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialClosedFieldsNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialConstsCoveredNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialConstsCoveredNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialEquivEntriesEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialEquivEntriesEmpty._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialEquivLabelsEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialEquivLabelsEmpty._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialEquivParentEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialEquivParentEmpty._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialExprKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialExprKeysNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialRecursorLoaded._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialRecursorLoaded._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialReferencesCovered._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialReferencesCovered._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInitialUnivKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInitialUnivKeysNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberMajorSkipRunNeutral._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberMajorSkipRunNeutral._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberOwnerCacheMatchesNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberOwnerCacheMatchesNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberPopulationReferencesCovered._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberPopulationReferencesCovered._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberPreparationMatchesNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberPreparationMatchesNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRecursorConcreteHeader._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRecursorConcreteHeader._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberReferenceId_authorized._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberReferenceId_authorized._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberReferenceId_authorized._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberReferenceId_authorized._native.native_decide.ax_1_2, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberReferenceId_authorized._native.native_decide.ax_1_3, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberReferenceId_authorized._native.native_decide.ax_1_3, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberResolutionPrefixMatchesNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberResolutionPrefixMatchesNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberResultLevelNonzero._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberResultLevelNonzero._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberResultSortShape._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberResultSortShape._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRulePopulationCacheChecksNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRulePopulationCacheChecksNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRulePopulationExprKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRulePopulationExprKeysNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRulePopulationExtendsNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRulePopulationExtendsNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRulePopulationMatchesNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRulePopulationMatchesNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRulePopulationNoLazyNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRulePopulationNoLazyNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRulePopulationSemanticChecksNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRulePopulationSemanticChecksNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRulePopulationUnivKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRulePopulationUnivKeysNative._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberSnapshotFamilyLoaded._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberSnapshotFamilyLoaded._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberSnapshotGeneratedCache._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberSnapshotGeneratedCache._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyNatSuccLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyNatSuccLookup._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyNatZeroLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyNatZeroLookup._native.native_decide.ax_1_1, generatedRecursorMemberFixtureNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyNilConcreteHeader._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyNilConcreteHeader._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberBlockPeersClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberBlockPeersClassifiedNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberBlockResultKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberBlockResultKeysClassifiedNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberConsInfoLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberConsInfoLookup._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberConsInnerResultLevel_raw._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberConsInnerResultLevel_raw._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberConsResultLevel_raw._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberConsResultLevel_raw._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberConsTypeTranslation._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberConsTypeTranslation._native.native_decide.ax_1_2, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberDefEqCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberDefEqCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberDefEqCheapCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberDefEqCheapCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberDefEqFailureCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberDefEqFailureCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberFamilyInfoLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberFamilyInfoLookup._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberFamilyReferenceTranslation._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberFamilyReferenceTranslation._native.native_decide.ax_1_2, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberFamilyResultLevel_raw._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberFamilyResultLevel_raw._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberFamilyTypeTranslation._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberFamilyTypeTranslation._native.native_decide.ax_1_2, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInferCensusNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInferCensusNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberInferOnlyCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberInferOnlyCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberIsPropCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberIsPropCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberIsRecCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberIsRecCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatBlockAccepted._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatBlockAccepted._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatBlockAccepted._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatBlockAccepted._native.native_decide.ax_1_2, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatInfoLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatInfoLookup._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatReferenceTranslation._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatReferenceTranslation._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatReferenceWhnf._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatReferenceWhnf._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatSuccStuckCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatSuccStuckCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatTrusted._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatTrusted._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNatTypeTranslation._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNatTypeTranslation._native.native_decide.ax_1_2, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNilInfoLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNilInfoLookup._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberNilTypeTranslation._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberNilTypeTranslation._native.native_decide.ax_1_2, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRecMajorsClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRecMajorsClassifiedNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRecursorBlocksClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRecursorBlocksClassifiedNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRecursorOwnersClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRecursorOwnersClassifiedNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberRecursorPayloadsInternedNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberRecursorPayloadsInternedNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberSuccInfoLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberSuccInfoLookup._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberSuccReferenceTranslation._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberSuccReferenceTranslation._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberSuccTrusted._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberSuccTrusted._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberSuccTypeTranslation._native.native_decide.ax_1_2, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberSuccTypeTranslation._native.native_decide.ax_1_2, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberTypedConstantSyntaxNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberTypedConstantSyntaxNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberUnfoldCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberUnfoldCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberWhnfCensusNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberWhnfCensusNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberWhnfCoreCensusNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberWhnfCoreCensusNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberWhnfCoreCheapCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberWhnfCoreCheapCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberWhnfNoDeltaCensusNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberWhnfNoDeltaCensusNative._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberWhnfNoDeltaCheapCacheEmpty._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberWhnfNoDeltaCheapCacheEmpty._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberZeroInfoLookup._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberZeroInfoLookup._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberZeroReferenceTranslation._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberZeroReferenceTranslation._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberZeroTrusted._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyMemberZeroTrusted._native.native_decide.ax_1_1, generatedRecursorInitialInvariantNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyMemberZeroTypeTranslation._native.native_decide.ax_1_2 + `Ix.Kernel.IndexedRecursiveFixture.familyMemberZeroTypeTranslation._native.native_decide.ax_1_2 ] /-- Exact executable delta between the existing semantic recursor closure @@ -1709,236 +1699,232 @@ equation. The latter adds only the two outer production block checks. -/ private def indexedProducerClosureNative : Array Lean.Name := generatedRecursorAtomicClosureNative ++ #[ indexedRecursiveAcceptanceNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.IndexedRecursiveFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, indexedRecursiveAcceptanceNativeAxiom - `Ix.Tc.IndexedRecursiveFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.IndexedRecursiveFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1 ] /-- Exact executable footprint of the production-linked IndexedVec constructor-validation replay. Keep this separate from the broader end-to-end acceptance fixture so a new observation changes this root's audit. -/ private def indexedConstructorValidationNative : Array Lean.Name := #[ - nativeAxiom `Blake3 - `Blake3.HasherOps.hash._native.native_decide.ax_1, nativeAxiom `Ix.Environment `Ix.Name.mkStr._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Expr - `Ix.Tc.KExpr.mkVar._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Inductive - `Ix.Tc.RecM.canonicalAuxOrder._native.native_decide.ax_9, - nativeAxiom `Ix.Tc.Level - `Ix.Tc.KUniv.mkSucc._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Monad - `Ix.Tc.TcM.ctxAddrForLbrUncached._native.native_decide.ax_3, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.consConcreteHeaderNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyAritySucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyClassificationMatchesNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyConcreteHeaderNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyDiscoveryMatchesNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyMemberLoadedNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyNilAfterConsLoadedNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyNilValidationSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyPeerAgreementSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedBlockValidation - `Ix.Tc.IndexedRecursiveFixture.familyResultLevelSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedCandidateSyntax - `Ix.Tc.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_2, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedCandidateSyntax - `Ix.Tc.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_3, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedCandidateSyntax - `Ix.Tc.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_4, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedCandidateSyntax - `Ix.Tc.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_5, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedCandidateSyntax - `Ix.Tc.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_6, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedCandidateSyntax - `Ix.Tc.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_7, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorAfterParamShapeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorAlphaEnsureTypeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorConsumeAlphaNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorConsumeNatNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorConsumeTailNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorGetTypeAlphaNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorInstantiateHeadNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorInstantiateNNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorInstantiateTailNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorNatEnsureTypeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorNatUniverse._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorParamIsDefEqNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorParamUniverse._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorResultIsValidNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorTailEnsureTypeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedConstructorValidation - `Ix.Tc.IndexedRecursiveFixture.indexedVecConstructorTypeShapeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.familyConsHeadDomainCandidateCheckNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.familyConsNatDomainCandidateCheckNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.familyConsTailDomainCandidateCheckNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.familyConsTailWhnfCandidateCheckNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.indexedVecAlphaCandidateWhnfNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.indexedVecAlphaHasNoIndOccTrusted._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.indexedVecNatCandidateWhnfNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.indexedVecNatHasNoIndOccTrusted._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.indexedVecTailAppIsValidTrusted._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.indexedVecTailCandidateWhnfNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedPositivityTransport - `Ix.Tc.IndexedRecursiveFixture.indexedVecTailHasIndOccTrusted._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsHeadDomainRootFreeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsHeadOpenSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsHeadTelescopeWhnfIsForallNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsNatDomainRootFreeNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsNatOpenSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsNatTelescopeWhnfIsForallNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsPositivityParametersSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsResultWhnfSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsResultWhnfTerminalNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailDomainMentionsRootNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailDomainSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailDomainWhnfNotForallNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailDomainWhnfSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailOpenSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailTelescopeWhnfIsForallNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailWhnfSpineActiveNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedProductionPositivity - `Ix.Tc.IndexedRecursiveFixture.familyConsTailWhnfSpineIsConstNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedRecursiveAcceptance - `Ix.Tc.IndexedRecursiveFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, - nativeAxiom `Ix.Tc.Verify.Inductive.IndexedRecursiveFixture - `Ix.Tc.IndexedRecursiveFixture.familyEntriesSizeNative._native.native_decide.ax_1_1 + nativeAxiom `Ix.Kernel.Expr + `Ix.Kernel.KExpr.mkVar._native.native_decide.ax_1, + nativeAxiom `Ix.Kernel.Inductive + `Ix.Kernel.RecM.canonicalAuxOrder._native.native_decide.ax_9, + nativeAxiom `Ix.Kernel.Level + `Ix.Kernel.KUniv.mkSucc._native.native_decide.ax_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.consConcreteHeaderNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyAritySucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyClassificationMatchesNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyConcreteHeaderNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyDiscoveryMatchesNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyMemberLoadedNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyNilAfterConsLoadedNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyNilValidationSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyPeerAgreementSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedBlockValidation + `Ix.Kernel.IndexedRecursiveFixture.familyResultLevelSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedCandidateSyntax + `Ix.Kernel.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_2, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedCandidateSyntax + `Ix.Kernel.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_3, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedCandidateSyntax + `Ix.Kernel.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_4, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedCandidateSyntax + `Ix.Kernel.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_5, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedCandidateSyntax + `Ix.Kernel.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_6, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedCandidateSyntax + `Ix.Kernel.IndexedRecursiveFixture.candidateBlockSyntaxNative._native.native_decide.ax_1_7, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorAfterParamShapeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorAlphaEnsureTypeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorConsumeAlphaNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorConsumeNatNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorConsumeTailNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorGetTypeAlphaNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorInstantiateHeadNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorInstantiateNNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorInstantiateTailNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorNatEnsureTypeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorNatUniverse._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorParamIsDefEqNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorParamUniverse._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorResultIsValidNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorTailEnsureTypeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedConstructorValidation + `Ix.Kernel.IndexedRecursiveFixture.indexedVecConstructorTypeShapeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.familyConsHeadDomainCandidateCheckNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.familyConsNatDomainCandidateCheckNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailDomainCandidateCheckNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailWhnfCandidateCheckNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.indexedVecAlphaCandidateWhnfNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.indexedVecAlphaHasNoIndOccTrusted._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.indexedVecNatCandidateWhnfNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.indexedVecNatHasNoIndOccTrusted._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.indexedVecTailAppIsValidTrusted._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.indexedVecTailCandidateWhnfNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedPositivityTransport + `Ix.Kernel.IndexedRecursiveFixture.indexedVecTailHasIndOccTrusted._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsHeadDomainRootFreeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsHeadOpenSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsHeadTelescopeWhnfIsForallNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsNatDomainRootFreeNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsNatOpenSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsNatTelescopeWhnfIsForallNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsPositivityParametersSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsResultWhnfSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsResultWhnfTerminalNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailDomainMentionsRootNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailDomainSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailDomainWhnfNotForallNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailDomainWhnfSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailOpenSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailTelescopeWhnfIsForallNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailWhnfSpineActiveNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedProductionPositivity + `Ix.Kernel.IndexedRecursiveFixture.familyConsTailWhnfSpineIsConstNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedRecursiveAcceptance + `Ix.Kernel.IndexedRecursiveFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + nativeAxiom `Ix.Kernel.Verify.Inductive.IndexedRecursiveFixture + `Ix.Kernel.IndexedRecursiveFixture.familyEntriesSizeNative._native.native_decide.ax_1_1 ] private def nestedRecursiveFixtureNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.NestedRecursiveFixture name + nativeAxiom `Ix.Kernel.Verify.Inductive.NestedRecursiveFixture name private def nestedRecursiveActionNative : Array Lean.Name := nameContextNative ++ #[ nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxInactiveNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.boxInactiveNative._native.native_decide.ax_1_1, nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedMentionsRootNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedMentionsRootNative._native.native_decide.ax_1_1, nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedSpineNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedSpineNative._native.native_decide.ax_1_1, nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedWhnfSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedWhnfSucceededNative._native.native_decide.ax_1_1, nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.positivitySucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.positivitySucceededNative._native.native_decide.ax_1_1 ] private def nestedRecursiveProducedNative : Array Lean.Name := nestedRecursiveActionNative ++ #[ nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxConcreteHeaderMatchesNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.boxConcreteHeaderMatchesNative._native.native_decide.ax_1_1, nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxLookupConcreteNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.boxLookupConcreteNative._native.native_decide.ax_1_1, nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxLookupSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.boxLookupSucceededNative._native.native_decide.ax_1_1 ] private def nestedRecursiveFreshNative : Array Lean.Name := nestedRecursiveProducedNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.positivityRequestAbsentNative._native.native_decide.ax_1_1) + `Ix.Kernel.NestedRecursiveFixture.positivityRequestAbsentNative._native.native_decide.ax_1_1) private def nestedRecursiveReachabilityNative : Array Lean.Name := nestedRecursiveFreshNative ++ #[ nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.builtFlatShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.builtFlatShapeNative._native.native_decide.ax_1_1, nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.flatBuildSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.flatBuildSucceededNative._native.native_decide.ax_1_1 ] private def nestedCandidateSyntaxNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.NestedCandidateSyntax name + nativeAxiom `Ix.Kernel.Verify.Inductive.NestedCandidateSyntax name private def nestedPositivityTransportNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.NestedPositivityTransport name + nativeAxiom `Ix.Kernel.Verify.Inductive.NestedPositivityTransport name private def nestedAuxiliaryPositivityNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.NestedAuxiliaryPositivity name + nativeAxiom `Ix.Kernel.Verify.Inductive.NestedAuxiliaryPositivity name private def nestedConstructorValidationNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.NestedConstructorValidation name + nativeAxiom `Ix.Kernel.Verify.Inductive.NestedConstructorValidation name private def nestedCandidateRelationNative : Array Lean.Name := #[ nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanAuxiliaryOccursNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanAuxiliaryOccursNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanAuxiliarySourceNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanAuxiliarySourceNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanAuxiliaryTargetNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanAuxiliaryTargetNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanFlatNodeTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanFlatNodeTypeNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedDomainCandidateCheckNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.nestedDomainCandidateCheckNative._native.native_decide.ax_1_1 ] private def nestedRecursiveReachabilityWithResultNative : Array Lean.Name := nestedRecursiveReachabilityNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedWhnfResultNative._native.native_decide.ax_1_1) + `Ix.Kernel.NestedRecursiveFixture.nestedWhnfResultNative._native.native_decide.ax_1_1) private def nestedOuterTransportNative : Array Lean.Name := nestedRecursiveReachabilityWithResultNative ++ nestedCandidateRelationNative ++ #[ nestedPositivityTransportNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanAuxiliaryCandidateWhnfNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanAuxiliaryCandidateWhnfNative._native.native_decide.ax_1_1, nestedPositivityTransportNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedDomainMentionsRootNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedDomainMentionsRootNative._native.native_decide.ax_1_1, nestedPositivityTransportNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedExternalInactiveNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.nestedExternalInactiveNative._native.native_decide.ax_1_1 ] private def nestedAuxiliaryCandidateTargetNative : Array Lean.Name := @@ -1946,29 +1932,29 @@ private def nestedAuxiliaryCandidateTargetNative : Array Lean.Name := private def nestedAuxiliaryExecutionNative : Array Lean.Name := #[ nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryDiscoverySucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryDiscoverySucceededNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryDomainWhnfNotForallNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryDomainWhnfNotForallNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryDomainWhnfResultNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryDomainWhnfResultNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryDomainWhnfSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryDomainWhnfSucceededNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryFieldWhnfShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryFieldWhnfShapeNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryFieldWhnfSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryFieldWhnfSucceededNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryInstantiationSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryInstantiationSucceededNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryParameterArgsNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryParameterArgsNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryStrippingSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryStrippingSucceededNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliarySubstitutionSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliarySubstitutionSucceededNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryTreeMentionsRootNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryTreeMentionsRootNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryWrapLookupSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.auxiliaryWrapLookupSucceededNative._native.native_decide.ax_1_1 ] private def nestedAuxiliaryProductionNative : Array Lean.Name := @@ -1977,70 +1963,70 @@ private def nestedAuxiliaryProductionNative : Array Lean.Name := private def nestedAuxiliaryTransportNative : Array Lean.Name := nameContextNative ++ #[ nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryDomainWhnfResultNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryDomainWhnfResultNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryDomainWhnfSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryDomainWhnfSucceededNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.auxiliaryTreeMentionsRootNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.auxiliaryTreeMentionsRootNative._native.native_decide.ax_1_1, nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeCandidateWhnfNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanTreeCandidateWhnfNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeOccursNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanTreeOccursNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeTargetNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanTreeTargetNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.treeCandidateCheckNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.treeCandidateCheckNative._native.native_decide.ax_1_1 ] private def nestedAuxiliaryConstructorNative : Array Lean.Name := nestedAuxiliaryProductionNative ++ #[ nestedAuxiliaryPositivityNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeCandidateWhnfNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanTreeCandidateWhnfNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeOccursNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanTreeOccursNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeTargetNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanTreeTargetNative._native.native_decide.ax_1_1, nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.treeCandidateCheckNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.treeCandidateCheckNative._native.native_decide.ax_1_1 ] private def nestedNodeConstructorValidationNative : Array Lean.Name := nestedOuterTransportNative ++ #[ nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.consumeLeanAuxiliaryNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.consumeLeanAuxiliaryNative._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.instantiateLeanTreeNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.instantiateLeanTreeNative._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanAuxiliaryEnsureTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanAuxiliaryEnsureTypeNative._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanFlatFieldUniverse._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanFlatFieldUniverse._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeTerminalNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.leanTreeTerminalNative._native.native_decide.ax_1_1 ] private def nestedWrapConstructorValidationNative : Array Lean.Name := nestedAuxiliaryConstructorNative ++ #[ nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanFlatWrapTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanFlatWrapTypeNative._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.consumeLeanTreeNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.consumeLeanTreeNative._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.instantiateLeanAuxiliaryNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.instantiateLeanAuxiliaryNative._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanAuxiliaryTerminalNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanAuxiliaryTerminalNative._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanFlatFieldUniverse._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.leanFlatFieldUniverse._native.native_decide.ax_1_1, nestedConstructorValidationNativeAxiom - `Ix.Tc.NestedRecursiveFixture.leanTreeEnsureTypeNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.leanTreeEnsureTypeNative._native.native_decide.ax_1_1 ] private def nestedTreeCandidateSyntaxNative : Array Lean.Name := expressionNative.push (nestedCandidateSyntaxNativeAxiom - `Ix.Tc.NestedRecursiveFixture.treeCandidateCheckNative._native.native_decide.ax_1_1) + `Ix.Kernel.NestedRecursiveFixture.treeCandidateCheckNative._native.native_decide.ax_1_1) /- The nested semantic transaction has two independently executable halves: -the Lean4Lean source/restoration proof and Ix's physical catalog/checker +the Ix.Theory.Named source/restoration proof and Ix's physical catalog/checker join. Keep their native footprints explicit so the headline audit cannot silently acquire oracle materialization or pending assumptions. -/ private def nativeUnion (left right : Array Lean.Name) : Array Lean.Name := @@ -2048,75 +2034,75 @@ private def nativeUnion (left right : Array Lean.Name) : Array Lean.Name := if names.contains name then names else names.push name) left private def nestedSemanticBoxNative : Array Lean.Name := #[ - `Ix.Tc.NestedRecursiveFixture.semanticBoxAfter_isSome._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.semanticBoxChecked._native.native_decide.ax_1, - `Ix.Tc.NestedRecursiveFixture.semanticBoxGeneration._native.native_decide.ax_1, - `Ix.Tc.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_2, - `Ix.Tc.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_3, - `Ix.Tc.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_4, - `Ix.Tc.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_5 + `Ix.Kernel.NestedRecursiveFixture.semanticBoxAfter_isSome._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.semanticBoxChecked._native.native_decide.ax_1, + `Ix.Kernel.NestedRecursiveFixture.semanticBoxGeneration._native.native_decide.ax_1, + `Ix.Kernel.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_2, + `Ix.Kernel.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_3, + `Ix.Kernel.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_4, + `Ix.Kernel.NestedRecursiveFixture.semanticBoxShape._native.native_decide.ax_1_5 ] private def nestedSemanticWFNative : Array Lean.Name := nestedSemanticBoxNative ++ #[ - `Ix.Tc.NestedRecursiveFixture.semanticTreeNested_isSome._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.semanticTreeRecursors_eq._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.semanticTreeRules_eq._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.semanticTreeNested_isSome._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.semanticTreeRecursors_eq._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.semanticTreeRules_eq._native.native_decide.ax_1_1 ] private def nestedSemanticCertificateNative : Array Lean.Name := nestedSemanticWFNative.push - `Ix.Tc.NestedRecursiveFixture.semanticTreeAfter_isSome._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.semanticTreeAfter_isSome._native.native_decide.ax_1_1 private def nestedSemanticFactsNative : Array Lean.Name := nestedSemanticCertificateNative ++ #[ - `Ix.Tc.NestedRecursiveFixture.semanticTreeNodeName._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.semanticTreeRestoredClean._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.semanticTreeNodeName._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.semanticTreeRestoredClean._native.native_decide.ax_1_1 ] private def nestedSemanticAdmissionNative : Array Lean.Name := nestedSemanticCertificateNative ++ #[ - `Ix.Tc.NestedRecursiveFixture.semanticTreeNodeName._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.semanticTreeSourceInventory._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.semanticTreeSourceInventory._native.native_decide.ax_1_2 + `Ix.Kernel.NestedRecursiveFixture.semanticTreeNodeName._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.semanticTreeSourceInventory._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.semanticTreeSourceInventory._native.native_decide.ax_1_2 ] private def nestedAdmissionNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Inductive.NestedAdmission name + nativeAxiom `Ix.Kernel.Verify.Inductive.NestedAdmission name private def nestedAdmissionPublicNative : Array Lean.Name := #[ - `Ix.Tc.NestedRecursiveFixture.nestedCatalog_node._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.nestedCatalog_node._native.native_decide.ax_1_2, - `Ix.Tc.NestedRecursiveFixture.nestedCatalog_tree._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_2, - `Ix.Tc.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_3, - `Ix.Tc.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_4, - `Ix.Tc.NestedRecursiveFixture.nestedNameOf_tree._native.native_decide.ax_1_1, - `Ix.Tc.NestedRecursiveFixture.nestedNameOf_tree._native.native_decide.ax_1_2, - `Ix.Tc.NestedRecursiveFixture.nestedNameOf_tree._native.native_decide.ax_1_3 + `Ix.Kernel.NestedRecursiveFixture.nestedCatalog_node._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedCatalog_node._native.native_decide.ax_1_2, + `Ix.Kernel.NestedRecursiveFixture.nestedCatalog_tree._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_2, + `Ix.Kernel.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_3, + `Ix.Kernel.NestedRecursiveFixture.nestedNameOf_node._native.native_decide.ax_1_4, + `Ix.Kernel.NestedRecursiveFixture.nestedNameOf_tree._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedNameOf_tree._native.native_decide.ax_1_2, + `Ix.Kernel.NestedRecursiveFixture.nestedNameOf_tree._native.native_decide.ax_1_3 ] private def nestedAdmissionPrivateNative : Array Lean.Name := #[ nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedFamilyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedFamilyBlockLoadedNative._native.native_decide.ax_1_1, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_1, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_2, + `Ix.Kernel.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_2, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_3, + `Ix.Kernel.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_3, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_4, + `Ix.Kernel.NestedRecursiveFixture.nestedMemberShapeFactsNative._native.native_decide.ax_1_4, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedNodeDirectConstructor._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedNodeDirectConstructor._native.native_decide.ax_1_1, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedNodeTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedNodeTypeRawNative._native.native_decide.ax_1_1, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedTreeDirectOwner._native.native_decide.ax_1_1, + `Ix.Kernel.NestedRecursiveFixture.nestedTreeDirectOwner._native.native_decide.ax_1_1, nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedTreeTypeRawNative._native.native_decide.ax_1_1 + `Ix.Kernel.NestedRecursiveFixture.nestedTreeTypeRawNative._native.native_decide.ax_1_1 ] private def nestedFamilyCertificateNative : Array Lean.Name := @@ -2127,7 +2113,7 @@ private def nestedFamilyCertificateNative : Array Lean.Name := private def nestedFamilyKernelNative : Array Lean.Name := inductiveNative.push (nestedAdmissionNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedFamilyKernelSucceededNative._native.native_decide.ax_1_1) + `Ix.Kernel.NestedRecursiveFixture.nestedFamilyKernelSucceededNative._native.native_decide.ax_1_1) private def nestedSemanticTransactionClosureNative : Array Lean.Name := let withSemantics := nativeUnion nestedFamilyCertificateNative @@ -2137,10 +2123,10 @@ private def nestedSemanticTransactionClosureNative : Array Lean.Name := let withWrap := nativeUnion withNode nestedWrapConstructorValidationNative let withBoxIngress := withWrap.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxIngressSucceededNative._native.native_decide.ax_1_1) + `Ix.Kernel.NestedRecursiveFixture.boxIngressSucceededNative._native.native_decide.ax_1_1) withBoxIngress.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.treeIngressSucceededNative._native.native_decide.ax_1_1) + `Ix.Kernel.NestedRecursiveFixture.treeIngressSucceededNative._native.native_decide.ax_1_1) /- The physical nested-recursor slice is deliberately separate from the source transaction above. It compiles the retained kernel declarations, @@ -2153,7 +2139,7 @@ private def nestedRecursorNativeUserName (decl : String) Lean.Name.str (Lean.Name.str (Lean.Name.str - (Lean.Name.str `Ix.Tc.NestedRecursiveFixture decl) + (Lean.Name.str `Ix.Kernel.NestedRecursiveFixture decl) "_native") "native_decide") s!"ax_1_{index + 1}" @@ -2171,22 +2157,22 @@ private def nestedRecursorPublicNativeSeries (decl : String) private def nestedRecursorFixtureNativeSeries (decl : String) (count : Nat := 1) : Array Lean.Name := nestedRecursorNativeSeries - `Ix.Tc.Verify.Inductive.NestedRecursorFixture decl count + `Ix.Kernel.Verify.Inductive.NestedRecursorFixture decl count private def nestedRecursorPatternNativeSeries (decl : String) (count : Nat := 1) : Array Lean.Name := nestedRecursorNativeSeries - `Ix.Tc.Verify.Inductive.NestedRecursorPattern decl count + `Ix.Kernel.Verify.Inductive.NestedRecursorPattern decl count private def nestedRecursorSoundnessNativeSeries (decl : String) (count : Nat := 1) : Array Lean.Name := nestedRecursorNativeSeries - `Ix.Tc.Verify.Inductive.NestedRecursorSoundness decl count + `Ix.Kernel.Verify.Inductive.NestedRecursorSoundness decl count private def nestedRecursorAdmissionNativeSeries (decl : String) (count : Nat := 1) : Array Lean.Name := nestedRecursorNativeSeries - `Ix.Tc.Verify.Inductive.NestedRecursorAdmission decl count + `Ix.Kernel.Verify.Inductive.NestedRecursorAdmission decl count private def nestedRecursorCompilerBaseNative : Array Lean.Name := nameContextNative.push mutualInternDataValueNative @@ -2267,7 +2253,7 @@ private def nestedRecursorPublicNative : Array Lean.Name := nestedRecursorPublicNativeSeries "nestedRecursorNameOf_wrap" 2 private def nestedRecursorMemberShapeNative : Array Lean.Name := - nestedRecursorNativeSeries `Ix.Tc.Verify.Inductive.NestedAdmission + nestedRecursorNativeSeries `Ix.Kernel.Verify.Inductive.NestedAdmission "nestedMemberShapeFactsNative" 4 private def nestedRecursorAdmissionFactsNative : Array Lean.Name := @@ -2317,26 +2303,26 @@ private def nestedRecursorOperationalNative : Array Lean.Name := nestedRecursorFixtureNativeSeries "recursorEntriesUniqueNative" ++ nestedRecursorFixtureNativeSeries "recursorEntryIdsNative" ++ nestedRecursorFixtureNativeSeries "recursorIngressSucceededNative" ++ - #[nativeAxiom `Ix.Tc.Inductive - `Ix.Tc.RecM.canonicalAuxOrder._native.native_decide.ax_9] + #[nativeAxiom `Ix.Kernel.Inductive + `Ix.Kernel.RecM.canonicalAuxOrder._native.native_decide.ax_9] private def nestedRecursorAtomicClosureNative : Array Lean.Name := nativeUnion nestedRecursorAtomicAdmissionNative nestedRecursorOperationalNative private def nestedRestoredPatternUpstreamDebt : Array Lean.Name := #[ - ``Lean4Lean.VEnv.IsDefEqU.forallE_inv_stratified, - ``Lean4Lean.VEnv.IsDefEqU.sort_inv + ``Ix.Theory.Named.VEnv.IsDefEqU.forallE_inv_stratified, + ``Ix.Theory.Named.VEnv.IsDefEqU.sort_inv ] private def booleanAcceptanceNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Driver.BooleanAcceptance name + nativeAxiom `Ix.Kernel.Verify.Driver.BooleanAcceptance name private def serializedBooleanNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Ingress.SerializedBoolean name + nativeAxiom `Ix.Kernel.Verify.Ingress.SerializedBoolean name private def literalBlobsNativeAxiom (name : Lean.Name) : Lean.Name := - nativeAxiom `Ix.Tc.Verify.Ingress.LiteralBlobs name + nativeAxiom `Ix.Kernel.Verify.Ingress.LiteralBlobs name /- The explicit Boolean one-family admission consumes the finite catalog, ingress, generation, rule, and pattern facts below. Checker executions are @@ -2344,139 +2330,139 @@ kept out of this shared semantic slice so the one-family root cannot inherit them merely because the larger end-to-end witness also records those runs. -/ private def booleanSemanticFixtureNative : Array Lean.Name := #[ enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogFamilyNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_3, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_4, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_4, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_3, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_6, + `Ix.Kernel.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_6, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_7, + `Ix.Kernel.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_7, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleBinderCoreNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleFieldsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleRawNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleScopedNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleSizeBoundNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseSourceTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseSourceTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyConstructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyConstructorCountNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryIdsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyMemberKidsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.generationCtorPairOne._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.generationCtorPairOne._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.generationCtorPairZero._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfFalseNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfFamilyNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfRecursorNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfTrueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorTypeRawNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceConstructorOne._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceConstructorOne._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceConstructorZero._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleBinderCoreNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleFieldsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleRawNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleScopedNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleSizeBoundNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueSourceTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueSourceTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 + `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 ] private def booleanSemanticAdmissionNative : Array Lean.Name := nameNative ++ #[ enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorOwnerNative._native.native_decide.ax_1_1 + `Ix.Kernel.BooleanEnumerationFixture.recursorOwnerNative._native.native_decide.ax_1_1 ] ++ booleanSemanticFixtureNative /- The concrete Boolean end-to-end witness additionally evaluates the real @@ -2486,27 +2472,27 @@ than treating the witness as one opaque executable assumption. -/ private def booleanEnumerationNative : Array Lean.Name := inductiveNative ++ #[ enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBodySucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyBodySucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyClassificationSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyClassificationSucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyKernelSucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBlockLoadedAfterFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorBlockLoadedAfterFamilyNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBodySucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorBodySucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorClassificationSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorClassificationSucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorKernelSucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorOwnerNative._native.native_decide.ax_1_1 + `Ix.Kernel.BooleanEnumerationFixture.recursorOwnerNative._native.native_decide.ax_1_1 ] ++ booleanSemanticFixtureNative /- The E3-S family-body bridge consumes only the family-side slice of the @@ -2516,83 +2502,83 @@ recursor run, kernel-run, generated-rule, or recursor-ingress facts merely because the larger E2b witness uses them. -/ private def booleanFamilyBodyNative : Array Lean.Name := inductiveNative ++ #[ enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBodySucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyBodySucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyClassificationSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyClassificationSucceededNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogFamilyNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_3, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseSourceTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseSourceTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyConstructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyConstructorCountNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryIdsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyMemberKidsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfFalseNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfFamilyNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfTrueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceConstructorOne._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceConstructorOne._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceConstructorZero._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueSourceTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueSourceTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 + `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 ] /-- Exact evaluator boundary of the final E3-S Boolean whole-driver witness. @@ -2602,185 +2588,185 @@ does not inherit the earlier standalone body/kernel executions as semantic authority for the serial run. -/ def booleanDriverNative : Array Lean.Name := inductiveNative ++ #[ booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.buildAnonWorkNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.buildAnonWorkNative._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.checkEnvAnonNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.checkEnvAnonNative._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseProjectionEntry._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.falseProjectionEntry._native.native_decide.ax_1_2, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseProjectionEntry._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.falseProjectionEntry._native.native_decide.ax_1_3, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBlockEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyBlockEntry._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBlockEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.familyBlockEntry._native.native_decide.ax_1_2, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBlockEntry._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.familyBlockEntry._native.native_decide.ax_1_3, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyProjectionEntry._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.familyProjectionEntry._native.native_decide.ax_1_2, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyProjectionEntry._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.familyProjectionEntry._native.native_decide.ax_1_3, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyTargetsNonemptyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyTargetsNonemptyNative._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBlockEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorBlockEntry._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBlockEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.recursorBlockEntry._native.native_decide.ax_1_2, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBlockEntry._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.recursorBlockEntry._native.native_decide.ax_1_3, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorProjectionEntry._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.recursorProjectionEntry._native.native_decide.ax_1_2, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorProjectionEntry._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.recursorProjectionEntry._native.native_decide.ax_1_3, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorTargetsNonemptyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorTargetsNonemptyNative._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceAddressesNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceAddressesNative._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceAddressesNodupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceAddressesNodupNative._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceKeysNative._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueProjectionEntry._native.native_decide.ax_1_1, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.trueProjectionEntry._native.native_decide.ax_1_2, booleanAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueProjectionEntry._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.trueProjectionEntry._native.native_decide.ax_1_3, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyDirectOwnerNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorBlockLoadedNative._native.native_decide.ax_1_1, enumerationAcceptanceNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorOwnerNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorOwnerNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogFalseNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogFamilyNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_3, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_4, + `Ix.Kernel.BooleanEnumerationFixture.catalogRecursorNative._native.native_decide.ax_1_4, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_3, + `Ix.Kernel.BooleanEnumerationFixture.catalogTrueNative._native.native_decide.ax_1_3, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_6, + `Ix.Kernel.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_6, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_7, + `Ix.Kernel.BooleanEnumerationFixture.enumerationShapeNative._native.native_decide.ax_1_7, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleBinderCoreNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleFieldsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleRawNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleScopedNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseRuleSizeBoundNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseSourceTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseSourceTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanEnumerationFixture.falseTypeNative._native.native_decide.ax_1_2, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyConstructorCountNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyConstructorCountNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntriesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntriesUniqueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtOneNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtTwoNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryAtZeroNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryIdsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyIngressSucceededNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyMemberKidsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.familyTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.familyTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.generationCtorPairOne._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.generationCtorPairOne._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.generationCtorPairZero._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.generationCtorPairZero._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfFalseNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfFamilyNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfRecursorNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.nameOfTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.nameOfTrueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntriesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntriesUniqueNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntryIdsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorIngressSucceededNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorMemberKidsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorRulesSizeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.recursorTypeRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.recursorTypeRawNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceConstructorOne._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceConstructorOne._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.sourceConstructorZero._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.sourceConstructorZero._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueEntryNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueEntryNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleBinderCoreNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleBinderCoreNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleFieldsNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleFieldsNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleRawNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleRawNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleScopedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleScopedNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueRuleSizeBoundNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueRuleSizeBoundNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueShapeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueShapeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueSourceTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueSourceTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_1, enumerationFixtureNativeAxiom - `Ix.Tc.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 + `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 ] /-- Exact evaluator boundary of the serialized T0 Boolean certificate. Each @@ -2788,255 +2774,255 @@ closed computation is named so changes in the byte, eager, lazy, dependency, or driver slices are visible independently in the trust manifest. -/ def serializedBooleanNative : Array Lean.Name := booleanDriverNative ++ #[ serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.blobKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.blobKeysNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.buildAnonWorkNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.buildAnonWorkNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.checkEnvAnonNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.checkEnvAnonNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.decodeSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.decodeSucceededNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerBlockKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerBlockKeysClassifiedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerFalseNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerFamilyBlockNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerFamilyBlockNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerFamilyNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerKeysClassifiedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerRecursorBlockNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerRecursorBlockNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerRecursorNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerSucceededNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerTrueNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.eagerWorkNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.eagerWorkNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.encodeSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.encodeSucceededNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.falseProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.falseProjectionEntry._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.falseProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanSerialized.falseProjectionEntry._native.native_decide.ax_1_2, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.falseProjectionHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.falseProjectionHashNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.falseProjectionLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.falseProjectionLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyBlockEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.familyBlockEntry._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyBlockEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanSerialized.familyBlockEntry._native.native_decide.ax_1_2, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyBlockHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.familyBlockHashNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyBlockLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.familyBlockLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.familyProjectionEntry._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanSerialized.familyProjectionEntry._native.native_decide.ax_1_2, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyProjectionHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.familyProjectionHashNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyProjectionLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.familyProjectionLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.familyTargetsNonemptyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.familyTargetsNonemptyNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFalseLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFalseLoadedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFamilyBlockKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFamilyBlockKeysNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFamilyBlockNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFamilyBlockNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFamilyKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFamilyKeysClassifiedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFamilyLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFamilyLoadedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFamilySucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFamilySucceededNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFinalBlockKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFinalBlockKeysClassifiedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFinalFalseNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFinalFalseNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFinalFamilyBlockNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFinalFamilyBlockNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFinalFamilyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFinalFamilyNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFinalRecursorBlockNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFinalRecursorBlockNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFinalRecursorNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFinalRecursorNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyFinalTrueNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyFinalTrueNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyRecursorKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyRecursorKeysClassifiedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyRecursorSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyRecursorSucceededNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.lazyTrueLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.lazyTrueLoadedNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.originalFalseProjectionLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.originalFalseProjectionLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.originalFamilyBlockLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.originalFamilyBlockLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.originalFamilyProjectionLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.originalFamilyProjectionLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.originalRecursorBlockLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.originalRecursorBlockLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.originalRecursorProjectionLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.originalRecursorProjectionLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.originalTrueProjectionLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.originalTrueProjectionLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorBlockEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.recursorBlockEntry._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorBlockEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanSerialized.recursorBlockEntry._native.native_decide.ax_1_2, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorBlockHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.recursorBlockHashNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorBlockLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.recursorBlockLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.recursorProjectionEntry._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanSerialized.recursorProjectionEntry._native.native_decide.ax_1_2, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorProjectionHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.recursorProjectionHashNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorProjectionLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.recursorProjectionLookupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.recursorTargetsNonemptyNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.recursorTargetsNonemptyNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.sourceAddressesNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.sourceAddressesNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.sourceAddressesNodupNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.sourceAddressesNodupNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.sourceKeysNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.sourceKeysNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.trueProjectionEntry._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.trueProjectionEntry._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.trueProjectionEntry._native.native_decide.ax_1_2, + `Ix.Kernel.BooleanSerialized.trueProjectionEntry._native.native_decide.ax_1_2, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.trueProjectionHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.BooleanSerialized.trueProjectionHashNative._native.native_decide.ax_1_1, serializedBooleanNativeAxiom - `Ix.Tc.BooleanSerialized.trueProjectionLookupNative._native.native_decide.ax_1_1 + `Ix.Kernel.BooleanSerialized.trueProjectionLookupNative._native.native_decide.ax_1_1 ] /- Exact evaluator boundary of the non-vacuous literal/blob T0 fixture. -/ private def literalRoundTripNative : Array Lean.Name := nameNative ++ #[ literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.blobKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.blobKeysClassifiedNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.decodeSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.decodeSucceededNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.encodeSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.encodeSucceededNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natBlobHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.natBlobHashNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natBlobLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.natBlobLookupNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natEntry._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.natEntry._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natEntry._native.native_decide.ax_1_2, + `Ix.Kernel.SerializedLiteralBlobs.natEntry._native.native_decide.ax_1_2, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.natHashNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.natLoadedNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.natLookupNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.natSucceededNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.natSucceededNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.sourceAddressesClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.sourceAddressesClassifiedNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.sourceAddressesNodupNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.sourceAddressesNodupNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.sourceKeysClassifiedNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.sourceKeysClassifiedNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringBlobHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.stringBlobHashNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringBlobLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.stringBlobLookupNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringEntry._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.stringEntry._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringEntry._native.native_decide.ax_1_2, + `Ix.Kernel.SerializedLiteralBlobs.stringEntry._native.native_decide.ax_1_2, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringHashNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.stringHashNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringLoadedNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.stringLoadedNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringLookupNative._native.native_decide.ax_1_1, + `Ix.Kernel.SerializedLiteralBlobs.stringLookupNative._native.native_decide.ax_1_1, literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.stringSucceededNative._native.native_decide.ax_1_1 + `Ix.Kernel.SerializedLiteralBlobs.stringSucceededNative._native.native_decide.ax_1_1 ] private def malformedConstantNative : Array Lean.Name := canonicalPrimitivesNative.push <| literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.malformedConstantRejectedNative._native.native_decide.ax_1_1 + `Ix.Kernel.SerializedLiteralBlobs.malformedConstantRejectedNative._native.native_decide.ax_1_1 private def malformedBlobNative : Array Lean.Name := canonicalPrimitivesNative.push <| literalBlobsNativeAxiom - `Ix.Tc.SerializedLiteralBlobs.malformedBlobRejectedNative._native.native_decide.ax_1_1 + `Ix.Kernel.SerializedLiteralBlobs.malformedBlobRejectedNative._native.native_decide.ax_1_1 /- Direct upstream `sorryAx` origins. Listing the declarations, rather than merely allowing `sorryAx`, makes upstream debt movement visible in review. -The certificate-bearing Lean4Lean pin discharges the former `VInductDecl.WF`, +The certificate-bearing Ix.Theory.Named pin discharges the former `VInductDecl.WF`, `VEnv.addInduct`, `VEnv.addInduct_WF`, and `TrProj` origins. -/ private def forallEInv : Lean.Name := - ``Lean4Lean.VEnv.IsDefEqU.forallE_inv_stratified -private def sortInv : Lean.Name := ``Lean4Lean.VEnv.IsDefEqU.sort_inv + ``Ix.Theory.Named.VEnv.IsDefEqU.forallE_inv_stratified +private def sortInv : Lean.Name := ``Ix.Theory.Named.VEnv.IsDefEqU.sort_inv private def typingDebt : Array Lean.Name := #[forallEInv, sortInv] -/- P0's concrete projection adapter consumes Lean4Lean's structural laws. +/- P0's concrete projection adapter consumes Ix.Theory.Named's structural laws. Its uniqueness law reaches the named registered-structure inversion theorem; -the context-defeq law also crosses Lean4Lean's current unique-typing boundary +the context-defeq law also crosses Ix.Theory.Named's current unique-typing boundary and therefore inherits the two L2 inversion origins. Keep this exact rather than allowing the remainder of the executable inductive-fixture debt. -/ private def projectionDebt : Array Lean.Name := - typingDebt.push ``Lean4Lean.VEnv.WF.registeredStructureHeadInversion + typingDebt.push ``Ix.Theory.Named.VEnv.WF.registeredStructureHeadInversion /- The empty legacy whole-`KEnv` inductive path is forbidden from every G2b consumer root. Keeping this list in the executable audit prevents an innocent-looking helper from reintroducing the old `nomatch` dependency. -/ private def legacyWholeEnv : Array Lean.Name := #[ - ``Ix.Tc.AddKInduct, - ``Ix.Tc.AddKInduct.to_addInduct, - ``Ix.Tc.TrKEnv', - ``Ix.Tc.TrKEnv + ``Ix.Kernel.AddKInduct, + ``Ix.Kernel.AddKInduct.to_addInduct, + ``Ix.Kernel.TrKEnv', + ``Ix.Kernel.TrKEnv ] /- E2a is intentionally a Theory-only certificate consumer. These checker/catalog/pattern declarations must not enter its dependency graph. -/ private def certificateAdapterForbidden : Array Lean.Name := #[ - ``Ix.Tc.Catalog, - ``Ix.Tc.RawInductiveConstRel, - ``Ix.Tc.RawRecursorRuleRel, - ``Ix.Tc.RawRecursorRulePatternRel, - ``Ix.Tc.InductiveOracle, - ``Lean4Lean.TrProj + ``Ix.Kernel.Catalog, + ``Ix.Kernel.RawInductiveConstRel, + ``Ix.Kernel.RawRecursorRuleRel, + ``Ix.Kernel.RawRecursorRulePatternRel, + ``Ix.Kernel.InductiveOracle, + ``Ix.Theory.Named.TrProj ] -/- `AnnotatedPi`'s upstream certificate is produced by Lean4Lean's executable +/- `AnnotatedPi`'s upstream certificate is produced by Ix.Theory.Named's executable normalization pipeline, so it cannot satisfy the earlier closed-form certificate quarantine against `TrProj`. It must still remain independent of all Ix catalog, checker-pattern, and oracle authority. -/ private def annotatedPiCertificateForbidden : Array Lean.Name := #[ - ``Ix.Tc.Catalog, - ``Ix.Tc.RawInductiveConstRel, - ``Ix.Tc.RawRecursorRuleRel, - ``Ix.Tc.RawRecursorRulePatternRel, - ``Ix.Tc.InductiveOracle + ``Ix.Kernel.Catalog, + ``Ix.Kernel.RawInductiveConstRel, + ``Ix.Kernel.RawRecursorRuleRel, + ``Ix.Kernel.RawRecursorRulePatternRel, + ``Ix.Kernel.InductiveOracle ] /- The pre-TrustedBody delta route admitted successful unfolding through a broad reflection oracle and arbitrary cache-write authority. The final K1 closure must use exact trusted declaration certificates instead. -/ private def legacyDeltaAuthority : Array Lean.Name := #[ - ``Ix.Tc.UnfoldCacheWriteOracle, - ``Ix.Tc.DeltaUnfoldReflection, - ``Ix.Tc.RecM.DeltaUnfoldContext, - ``Ix.Tc.RecM.FullWhnfStepContext.ofDelta + ``Ix.Kernel.UnfoldCacheWriteOracle, + ``Ix.Kernel.DeltaUnfoldReflection, + ``Ix.Kernel.RecM.DeltaUnfoldContext, + ``Ix.Kernel.RecM.FullWhnfStepContext.ofDelta ] private def k1ForbiddenDependencies : Array Lean.Name := @@ -3047,13 +3033,13 @@ all-depth, single-support closure interface whose finite-sort obstruction is proved below. The legacy declarations remain audited as compatibility artifacts while consumers migrate. -/ private def legacyAllDepthKnot : Array Lean.Name := #[ - ``Ix.Tc.RecursiveMethodClosureContext, - ``Ix.Tc.RecursiveMethodClosureContext.closedAt, - ``Ix.Tc.RecursiveMethodClosureContext.methodsN, - ``Ix.Tc.RecursiveMethodClosureContext.fullInferenceContext, - ``Ix.Tc.RecursiveMethodClosureContext.next_fullInferenceWFAt, - ``Ix.Tc.RecursiveMethodClosureContext.methodsN_fullInferenceWFAt, - ``Ix.Tc.RecursiveMethodClosureContext.publicInfer_full_wf + ``Ix.Kernel.RecursiveMethodClosureContext, + ``Ix.Kernel.RecursiveMethodClosureContext.closedAt, + ``Ix.Kernel.RecursiveMethodClosureContext.methodsN, + ``Ix.Kernel.RecursiveMethodClosureContext.fullInferenceContext, + ``Ix.Kernel.RecursiveMethodClosureContext.next_fullInferenceWFAt, + ``Ix.Kernel.RecursiveMethodClosureContext.methodsN_fullInferenceWFAt, + ``Ix.Kernel.RecursiveMethodClosureContext.publicInfer_full_wf ] private def boundedKnotForbiddenDependencies : Array Lean.Name := @@ -3062,7 +3048,7 @@ private def boundedKnotForbiddenDependencies : Array Lean.Name := /- E2c occurrence-validation roots must be derived from the production run, not from the ambient semantic inductive oracle retained by E2b. -/ private def occurrenceValidationForbiddenDependencies : Array Lean.Name := - boundedKnotForbiddenDependencies.push ``Ix.Tc.InductiveOracle + boundedKnotForbiddenDependencies.push ``Ix.Kernel.InductiveOracle /- Existing semantic admission returns the shared `TrustedCatalogLog`, whose inductive declaration necessarily mentions its legacy ambient constructor. @@ -3070,19 +3056,19 @@ Constructor-insensitive dependency traversal therefore cannot forbid the `InductiveOracle` type itself here. Instead, quarantine every operation that materializes or admits an oracle-selected future world. -/ private def oracleWorldMaterialization : Array Lean.Name := #[ - ``Ix.Tc.VerifyWorld.admitOracle, - ``Ix.Tc.VerifyWorld.le_admitOracle, - ``Ix.Tc.OracleBlockCertificate.admit, - ``Ix.Tc.OracleBlockCertificate.admitState, - ``Ix.Tc.RecM.certifyOracleBackedBlock, - ``Ix.Tc.RecM.certifyOracleBackedAdmittedBlock, - ``Ix.Tc.SingletonFamilyCatalogLink.oracle, - ``Ix.Tc.SingletonRecursorCatalogLink.oracle, - ``Ix.Tc.InductiveOracle.reindex, - ``Ix.Tc.InductiveOracle.restageMissing, - ``Ix.Tc.IndexedRecursivePattern.oracle, - ``Ix.Tc.IndexedRecursiveFixture.recursorBlockOracle, - ``Ix.Tc.IndexedRecursiveFixture.recursorAtomicAdmission + ``Ix.Kernel.VerifyWorld.admitOracle, + ``Ix.Kernel.VerifyWorld.le_admitOracle, + ``Ix.Kernel.OracleBlockCertificate.admit, + ``Ix.Kernel.OracleBlockCertificate.admitState, + ``Ix.Kernel.RecM.certifyOracleBackedBlock, + ``Ix.Kernel.RecM.certifyOracleBackedAdmittedBlock, + ``Ix.Kernel.SingletonFamilyCatalogLink.oracle, + ``Ix.Kernel.SingletonRecursorCatalogLink.oracle, + ``Ix.Kernel.InductiveOracle.reindex, + ``Ix.Kernel.InductiveOracle.restageMissing, + ``Ix.Kernel.IndexedRecursivePattern.oracle, + ``Ix.Kernel.IndexedRecursiveFixture.recursorBlockOracle, + ``Ix.Kernel.IndexedRecursiveFixture.recursorAtomicAdmission ] private def existingSemanticBlockForbiddenDependencies : Array Lean.Name := @@ -3092,14 +3078,14 @@ private def existingSemanticBlockForbiddenDependencies : Array Lean.Name := finite positive-fuel construction must neither manufacture that model nor reach the older public adapters that consume it. -/ private def legacyGlobalSuffix : Array Lean.Name := #[ - ``Ix.Tc.KernelSuffixModel, - ``Ix.Tc.ScopedKernelSuffixModel.toKernelSuffixModel, - ``Ix.Tc.PropositionClassifierContext, - ``Ix.Tc.RecursiveMethodRunContext, - ``Ix.Tc.TcM.whnf.wf_legacy, - ``Ix.Tc.TcM.infer.wf_legacy, - ``Ix.Tc.TcM.isDefEq.wf_legacy, - ``Ix.Tc.TcM.checkConst.wf_legacy + ``Ix.Kernel.KernelSuffixModel, + ``Ix.Kernel.ScopedKernelSuffixModel.toKernelSuffixModel, + ``Ix.Kernel.PropositionClassifierContext, + ``Ix.Kernel.RecursiveMethodRunContext, + ``Ix.Kernel.TcM.whnf.wf_legacy, + ``Ix.Kernel.TcM.infer.wf_legacy, + ``Ix.Kernel.TcM.isDefEq.wf_legacy, + ``Ix.Kernel.TcM.checkConst.wf_legacy ] private def scopedK2SForbiddenDependencies : Array Lean.Name := @@ -3119,73 +3105,73 @@ set_option maxRecDepth 100000 private def roots : Array RootAllowance := #[ -- Level decision procedures. - { root := ``Ix.Tc.univEq_sound, standardAxioms := standard }, - { root := ``Ix.Tc.univGeq_sound, standardAxioms := standard }, + { root := ``Ix.Kernel.univEq_sound, standardAxioms := standard }, + { root := ``Ix.Kernel.univGeq_sound, standardAxioms := standard }, -- Memoized expression walkers against their pure specifications. - { root := ``Ix.Tc.lift_spec, + { root := ``Ix.Kernel.lift_spec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.subst_spec, + { root := ``Ix.Kernel.subst_spec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.simulSubst_spec, + { root := ``Ix.Kernel.simulSubst_spec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.instantiateRev_spec, + { root := ``Ix.Kernel.instantiateRev_spec, standardAxioms := standard, nativeAxioms := expressionNative }, -- There is not yet an API-level `abstractFVars_spec`; protect the current -- walker master until that final wrapper replaces it. - { root := ``Ix.Tc.abstractFVarsCached_spec, + { root := ``Ix.Kernel.abstractFVarsCached_spec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TcM.instantiateUnivParams_wf, + { root := ``Ix.Kernel.TcM.instantiateUnivParams_wf, standardAxioms := standard, nativeAxioms := levelNative }, -- G3a finite run support and generated-term resource bounds. Universe -- instantiation can rebuild sorts/constants and therefore reaches the now -- total expression serializer's standard `UInt8` quotient implementation. - { root := ``Ix.Tc.KExpr.LiftReach.finite, + { root := ``Ix.Kernel.KExpr.LiftReach.finite, standardAxioms := standardWithoutQuot, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.KExpr.SubstReach.finite, + { root := ``Ix.Kernel.KExpr.SubstReach.finite, standardAxioms := standardWithoutQuot, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.KExpr.InstUnivReach.finite, + { root := ``Ix.Kernel.KExpr.InstUnivReach.finite, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.WalkerRequest.reach_finite, + { root := ``Ix.Kernel.WalkerRequest.reach_finite, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.InternTable.exprSupport_finite, + { root := ``Ix.Kernel.InternTable.exprSupport_finite, standardAxioms := standard }, - { root := ``Ix.Tc.RunSupport.collisionFree_of_le, + { root := ``Ix.Kernel.RunSupport.collisionFree_of_le, standardAxioms := propextOnly }, - { root := ``Ix.Tc.RunSupport.singleton_collisionFree, + { root := ``Ix.Kernel.RunSupport.singleton_collisionFree, standardAxioms := propextOnly }, - { root := ``Ix.Tc.WalkerRequest.Bounds.lift_result, + { root := ``Ix.Kernel.WalkerRequest.Bounds.lift_result, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WalkerRequest.Bounds.subst_result, + { root := ``Ix.Kernel.WalkerRequest.Bounds.subst_result, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.CheckConstSupport.initial_support, + { root := ``Ix.Kernel.CheckConstSupport.initial_support, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.lift, + { root := ``Ix.Kernel.CheckConstSupport.lift, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.subst, + { root := ``Ix.Kernel.CheckConstSupport.subst, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.instUniv, + { root := ``Ix.Kernel.CheckConstSupport.instUniv, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.mono, + { root := ``Ix.Kernel.CheckConstSupport.mono, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.scope, + { root := ``Ix.Kernel.CheckConstSupport.scope, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.ResourceBounds.mono, + { root := ``Ix.Kernel.ResourceBounds.mono, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.checkSupport, + { root := ``Ix.Kernel.AmbientNat.checkSupport, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.resourceBounds, + { root := ``Ix.Kernel.AmbientNat.resourceBounds, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.supportAcceptance, + { root := ``Ix.Kernel.AmbientNat.supportAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, @@ -3193,310 +3179,310 @@ private def roots : Array RootAllowance := #[ -- ties the exact finite request list to an actual TcM computation. The -- simultaneous/reverse instantiation specs can likewise rebuild serialized -- expressions and inherit the same standard quotient footprint. - { root := ``Ix.Tc.KExpr.SimulSubstReach.finite, + { root := ``Ix.Kernel.KExpr.SimulSubstReach.finite, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.KExpr.InstRevReach.finite, + { root := ``Ix.Kernel.KExpr.InstRevReach.finite, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.KExpr.AbstractReach.finite, + { root := ``Ix.Kernel.KExpr.AbstractReach.finite, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WalkerRequest.univReach_finite, + { root := ``Ix.Kernel.WalkerRequest.univReach_finite, standardAxioms := propextOnly }, - { root := ``Ix.Tc.InternTable.univSupport_finite, + { root := ``Ix.Kernel.InternTable.univSupport_finite, standardAxioms := standard }, - { root := ``Ix.Tc.RunSupport.pair_collisionFree, + { root := ``Ix.Kernel.RunSupport.pair_collisionFree, standardAxioms := propextOnly }, - { root := ``Ix.Tc.WalkerRequest.Bounds.simulSubst_result, + { root := ``Ix.Kernel.WalkerRequest.Bounds.simulSubst_result, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WalkerRequest.Bounds.instRev_result, + { root := ``Ix.Kernel.WalkerRequest.Bounds.instRev_result, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WalkerRequest.Bounds.abstractFVars_result, + { root := ``Ix.Kernel.WalkerRequest.Bounds.abstractFVars_result, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.abstractFVars_eq, + { root := ``Ix.Kernel.abstractFVars_eq, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.InternPreservesUnivs.pure, + { root := ``Ix.Kernel.InternPreservesUnivs.pure, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.InternPreservesUnivs.runWalk, + { root := ``Ix.Kernel.InternPreservesUnivs.runWalk, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.WalkPreservesUnivs.pure, + { root := ``Ix.Kernel.WalkPreservesUnivs.pure, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.WalkPreservesUnivs.bind, + { root := ``Ix.Kernel.WalkPreservesUnivs.bind, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.WalkPreservesUnivs.scratchGet, + { root := ``Ix.Kernel.WalkPreservesUnivs.scratchGet, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.WalkPreservesUnivs.scratchInsert, + { root := ``Ix.Kernel.WalkPreservesUnivs.scratchInsert, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.WalkPreservesUnivs.liftIntern, + { root := ``Ix.Kernel.WalkPreservesUnivs.liftIntern, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.WalkPreservesUnivs.internExpr, + { root := ``Ix.Kernel.WalkPreservesUnivs.internExpr, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.lift_preservesUnivs, + { root := ``Ix.Kernel.lift_preservesUnivs, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.subst_preservesUnivs, + { root := ``Ix.Kernel.subst_preservesUnivs, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.simulSubst_preservesUnivs, + { root := ``Ix.Kernel.simulSubst_preservesUnivs, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.instantiateRev_preservesUnivs, + { root := ``Ix.Kernel.instantiateRev_preservesUnivs, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.abstractFVars_preservesUnivs, + { root := ``Ix.Kernel.abstractFVars_preservesUnivs, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WalkerRequest.Bounds.abstractFVarsCached_result, + { root := ``Ix.Kernel.WalkerRequest.Bounds.abstractFVarsCached_result, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.CheckConstSupport.initial_univ_support, + { root := ``Ix.Kernel.CheckConstSupport.initial_univ_support, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.internExpr, + { root := ``Ix.Kernel.CheckConstSupport.internExpr, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.internUniv, + { root := ``Ix.Kernel.CheckConstSupport.internUniv, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.simulSubst, + { root := ``Ix.Kernel.CheckConstSupport.simulSubst, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.instRev, + { root := ``Ix.Kernel.CheckConstSupport.instRev, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.CheckConstSupport.abstractFVars, + { root := ``Ix.Kernel.CheckConstSupport.abstractFVars, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.ExecutionRequests.bind, - standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.ExecutionRequests.tryCatch, - standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.ExecutionRequests.runRec, + { root := ``Ix.Kernel.ExecutionRequests.bind, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.ExecutionRequests.isolateCheckErrors, - standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.ExecutionRequests.modify, + { root := ``Ix.Kernel.ExecutionRequests.tryCatch, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.ExecutionRequests.weaken, - standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.ExecutionRequests.of_eq, - standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.ExecutionRequests.intern_eq_of_nil, + { root := ``Ix.Kernel.ExecutionRequests.runRec, + standardAxioms := standard, nativeAxioms := inferNative }, + { root := ``Ix.Kernel.ExecutionRequests.isolateCheckErrors, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RunAssumptions.initial, + { root := ``Ix.Kernel.ExecutionRequests.modify, + standardAxioms := standard, nativeAxioms := inferNative }, + { root := ``Ix.Kernel.ExecutionRequests.weaken, + standardAxioms := standard, nativeAxioms := inferNative }, + { root := ``Ix.Kernel.ExecutionRequests.of_eq, + standardAxioms := standard, nativeAxioms := inferNative }, + { root := ``Ix.Kernel.ExecutionRequests.intern_eq_of_nil, + standardAxioms := standard, nativeAxioms := inferNative }, + { root := ``Ix.Kernel.RunAssumptions.initial, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.requestBounds, - standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RunAssumptions.internExpr_spec, + { root := ``Ix.Kernel.RunAssumptions.requestBounds, + standardAxioms := standard, nativeAxioms := inferNative }, + { root := ``Ix.Kernel.RunAssumptions.internExpr_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.internUniv_spec, + { root := ``Ix.Kernel.RunAssumptions.internUniv_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunSupport.CoversIntern.of_expr_univs, + { root := ``Ix.Kernel.RunSupport.CoversIntern.of_expr_univs, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RunAssumptions.lift_spec, + { root := ``Ix.Kernel.RunAssumptions.lift_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.subst_spec, + { root := ``Ix.Kernel.RunAssumptions.subst_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.simulSubst_spec, + { root := ``Ix.Kernel.RunAssumptions.simulSubst_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.instRev_spec, + { root := ``Ix.Kernel.RunAssumptions.instRev_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.abstractFVarsCached_spec, + { root := ``Ix.Kernel.RunAssumptions.abstractFVarsCached_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.abstractFVars_spec, + { root := ``Ix.Kernel.RunAssumptions.abstractFVars_spec, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.instantiateUnivParams_wf, + { root := ``Ix.Kernel.RunAssumptions.instantiateUnivParams_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.runIntern_supported_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RunAssumptions.lift_wf, + { root := ``Ix.Kernel.RunAssumptions.runIntern_supported_wf, + standardAxioms := standard }, + { root := ``Ix.Kernel.RunAssumptions.lift_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.subst_wf, + { root := ``Ix.Kernel.RunAssumptions.subst_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.simulSubst_wf, + { root := ``Ix.Kernel.RunAssumptions.simulSubst_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.instRev_wf, + { root := ``Ix.Kernel.RunAssumptions.instRev_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.abstractFVars_wf, + { root := ``Ix.Kernel.RunAssumptions.abstractFVars_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.instUniv_wf, + { root := ``Ix.Kernel.RunAssumptions.instUniv_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.AmbientNat.supportExecution, + { root := ``Ix.Kernel.AmbientNat.supportExecution, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.runAssumptions, + { root := ``Ix.Kernel.AmbientNat.runAssumptions, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- Expression translation, typing, uniqueness, and defeq bridges. - { root := ``Ix.Tc.TrKExprS.instL, + { root := ``Ix.Kernel.TrKExprS.instL, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.TrKExprS.inst, + { root := ``Ix.Kernel.TrKExprS.inst, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TrKExprS.inst_let, + { root := ``Ix.Kernel.TrKExprS.inst_let, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TrKExprS.inst_let_lbr, + { root := ``Ix.Kernel.TrKExprS.inst_let_lbr, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TrKExprS.wf, standardAxioms := standard }, - { root := ``Ix.Tc.TrKExpr.wf, standardAxioms := standard }, - { root := ``Ix.Tc.TrKExprS.uniq, + { root := ``Ix.Kernel.TrKExprS.wf, standardAxioms := standard }, + { root := ``Ix.Kernel.TrKExpr.wf, standardAxioms := standard }, + { root := ``Ix.Kernel.TrKExprS.uniq, standardAxioms := standard, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.TrKExprS.defeqDFC, + { root := ``Ix.Kernel.TrKExprS.defeqDFC, standardAxioms := standard, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.TrKExpr.defeq, + { root := ``Ix.Kernel.TrKExpr.defeq, standardAxioms := standard, sorryOrigins := typingDebt }, -- Legacy whole-environment compatibility interfaces. G2b consumer roots -- below are forbidden from depending on these declarations. - { root := ``Ix.Tc.TrKEnv.wf, + { root := ``Ix.Kernel.TrKEnv.wf, standardAxioms := standard }, - { root := ``Ix.Tc.TrKEnv.find?, + { root := ``Ix.Kernel.TrKEnv.find?, standardAxioms := standard }, - { root := ``Ix.Tc.TcM.tick.tcInv, + { root := ``Ix.Kernel.TcM.tick.tcInv, standardAxioms := standard }, - { root := ``Ix.Tc.TcM.instantiateUnivParams.tcInv, + { root := ``Ix.Kernel.TcM.instantiateUnivParams.tcInv, standardAxioms := standard, nativeAxioms := levelNative }, -- The narrow upstream-context dependency behind translation uniqueness. - { root := ``Ix.Tc.KVLCtx.IsDefEq.find?_uniq, + { root := ``Ix.Kernel.KVLCtx.IsDefEq.find?_uniq, standardAxioms := standard }, -- Dual-context reconciliation entry points used by the checker proofs. - { root := ``Ix.Tc.CtxRecon.wf, standardAxioms := standard }, - { root := ``Ix.Tc.CtxRecon.lookupVar, + { root := ``Ix.Kernel.CtxRecon.wf, standardAxioms := standard }, + { root := ``Ix.Kernel.CtxRecon.lookupVar, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.CtxRecon.fvar_resolves, + { root := ``Ix.Kernel.CtxRecon.fvar_resolves, standardAxioms := standard }, -- G1a's non-circular world and one-way lazy-load boundary. - { root := ``Ix.Tc.VerifyWorld.ofCatalog_catalogued_not_trusted, + { root := ``Ix.Kernel.VerifyWorld.ofCatalog_catalogued_not_trusted, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.VerifyWorld.LE.trans, + { root := ``Ix.Kernel.VerifyWorld.LE.trans, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.VerifyWorld.LE.catalogued_iff, + { root := ``Ix.Kernel.VerifyWorld.LE.catalogued_iff, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.LoadedAgrees.world_iff, + { root := ``Ix.Kernel.LoadedAgrees.world_iff, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.LoadedAgrees.insert, + { root := ``Ix.Kernel.LoadedAgrees.insert, standardAxioms := standard }, - { root := ``Ix.Tc.LoadedAgrees.of_extension, + { root := ``Ix.Kernel.LoadedAgrees.of_extension, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.VerifyWorld.ofCatalog_loaded, + { root := ``Ix.Kernel.VerifyWorld.ofCatalog_loaded, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.VerifyWorld.ofCatalog_loaded_not_trusted, + { root := ``Ix.Kernel.VerifyWorld.ofCatalog_loaded_not_trusted, standardAxioms := standard }, -- G1b's raw/pending boundary. Raw correspondence has no declaration-WF -- premise; the fixture roots pin the concrete non-WF pending case. - { root := ``Ix.Tc.RawExprRel.mono, + { root := ``Ix.Kernel.RawExprRel.mono, standardAxioms := standard }, - { root := ``Ix.Tc.RawExprRel.reference_resolved, + { root := ``Ix.Kernel.RawExprRel.reference_resolved, standardAxioms := standard }, - { root := ``Ix.Tc.RawDeclRel.mono, + { root := ``Ix.Kernel.RawDeclRel.mono, standardAxioms := standard }, - { root := ``Ix.Tc.PendingDecl.no_target_lookup, + { root := ``Ix.Kernel.PendingDecl.no_target_lookup, standardAxioms := standard }, - { root := ``Ix.Tc.PendingDecl.no_self_expr_reference, + { root := ``Ix.Kernel.PendingDecl.no_self_expr_reference, standardAxioms := standard }, - { root := ``Ix.Tc.PendingDecl.not_trustedDecl, + { root := ``Ix.Kernel.PendingDecl.not_trustedDecl, standardAxioms := standard }, - { root := ``Ix.Tc.IllTypedPending.pending_but_not_wf, + { root := ``Ix.Kernel.IllTypedPending.pending_but_not_wf, standardAxioms := standard }, - { root := ``Ix.Tc.IllTypedPending.loaded_pending_but_not_wf, + { root := ``Ix.Kernel.IllTypedPending.loaded_pending_but_not_wf, standardAxioms := standard }, -- G1c's trusted-only catalog log and explicit-WF promotion boundary. - { root := ``Ix.Tc.RawDeclRel.wf_le, + { root := ``Ix.Kernel.RawDeclRel.wf_le, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogLog.wf, + { root := ``Ix.Kernel.TrustedCatalogLog.wf, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogLog.catalogued, + { root := ``Ix.Kernel.TrustedCatalogLog.catalogued, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogLog.find, + { root := ``Ix.Kernel.TrustedCatalogLog.find, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogRel.ofCatalog, + { root := ``Ix.Kernel.TrustedCatalogRel.ofCatalog, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogRel.find, + { root := ``Ix.Kernel.TrustedCatalogRel.find, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogEntry.recursorRule, + { root := ``Ix.Kernel.TrustedCatalogEntry.recursorRule, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogRel.recursorRule, + { root := ``Ix.Kernel.TrustedCatalogRel.recursorRule, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogEntry.recursorPattern, + { root := ``Ix.Kernel.TrustedCatalogEntry.recursorPattern, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogRel.recursorPattern, + { root := ``Ix.Kernel.TrustedCatalogRel.recursorPattern, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedDecl.lookup, + { root := ``Ix.Kernel.TrustedDecl.lookup, standardAxioms := standard }, - { root := ``Ix.Tc.TrustedCatalogRel.lookup, + { root := ``Ix.Kernel.TrustedCatalogRel.lookup, standardAxioms := standard }, - { root := ``Ix.Tc.Promotes.trans, + { root := ``Ix.Kernel.Promotes.trans, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TrustedCatalogRel.promote, + { root := ``Ix.Kernel.TrustedCatalogRel.promote, standardAxioms := standard }, - { root := ``Ix.Tc.IllTypedPending.trustedCatalogRel, + { root := ``Ix.Kernel.IllTypedPending.trustedCatalogRel, standardAxioms := standard }, - { root := ``Ix.Tc.WellTypedPromotion.promotes, + { root := ``Ix.Kernel.WellTypedPromotion.promotes, standardAxioms := standard }, -- G1d's world-based concrete-state invariant. Loading stays -- representation-only, promotion requires a fresh WF witness, and the -- fixed-world Hoare roots pin no-promotion behavior on both outcomes. - { root := ``Ix.Tc.TcStateWF.of_consts_eq, + { root := ``Ix.Kernel.TcStateWF.of_consts_eq, standardAxioms := standard }, - { root := ``Ix.Tc.TcStateWF.load, + { root := ``Ix.Kernel.TcStateWF.load, standardAxioms := standard }, - { root := ``Ix.Tc.TcStateWF.promote, + { root := ``Ix.Kernel.TcStateWF.promote, standardAxioms := standard }, - { root := ``Ix.Tc.TcStateWF.find?, + { root := ``Ix.Kernel.TcStateWF.find?, standardAxioms := standard }, - { root := ``Ix.Tc.TcInv.find?, + { root := ``Ix.Kernel.TcInv.find?, standardAxioms := standard }, - { root := ``Ix.Tc.IllTypedPending.tcInv_pending_but_not_wf, + { root := ``Ix.Kernel.IllTypedPending.tcInv_pending_but_not_wf, standardAxioms := standard }, - { root := ``Ix.Tc.TcM.tick.tcStateWF, + { root := ``Ix.Kernel.TcM.tick.tcStateWF, standardAxioms := standard }, - { root := ``Ix.Tc.TcM.instantiateUnivParams.tcStateWF, + { root := ``Ix.Kernel.TcM.instantiateUnivParams.tcStateWF, standardAxioms := standard, nativeAxioms := levelNative }, - -- Pin A / E2a: the certified-generation adapter may use only Lean4Lean + -- Pin A / E2a: the certified-generation adapter may use only Ix.Theory.Named -- Theory transaction facts, never Ix checker/catalog/pattern authority. - { root := ``Ix.Tc.CertifiedGenerationTransaction.trace, + { root := ``Ix.Kernel.CertifiedGenerationTransaction.trace, standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.CertifiedGenerationTransaction.afterWF, + { root := ``Ix.Kernel.CertifiedGenerationTransaction.afterWF, standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.CertifiedGenerationTransaction.facts, + { root := ``Ix.Kernel.CertifiedGenerationTransaction.facts, standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - -- L4L-08's Theory-only block adapter preserves the same quarantine while + -- Spec-08's Theory-only block adapter preserves the same quarantine while -- exposing one atomic all-families/all-constructors/all-recursors/all-rules -- transaction rather than a sequence of singleton admissions. - { root := ``Ix.Tc.CertifiedBlockGenerationTransaction.trace, + { root := ``Ix.Kernel.CertifiedBlockGenerationTransaction.trace, standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.CertifiedBlockGenerationTransaction.afterWF, + { root := ``Ix.Kernel.CertifiedBlockGenerationTransaction.afterWF, standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.CertifiedBlockGenerationTransaction.facts, + { root := ``Ix.Kernel.CertifiedBlockGenerationTransaction.facts, standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - -- E2c retains the exact Lean4Lean candidate-producer equation alongside + -- E2c retains the exact Ix.Theory.Named candidate-producer equation alongside -- the certified Theory transaction. Unlike the Theory-only adapter above, -- this Verify-backed bridge deliberately inherits the pinned analyzer debt. - { root := ``Ix.Tc.ProducedGenerationTransaction.facts, + { root := ``Ix.Kernel.ProducedGenerationTransaction.facts, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.ExactProducedGenerationTransaction.facts, + { root := ``Ix.Kernel.ExactProducedGenerationTransaction.facts, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, -- First genuine multi-family semantic witness: Tree/TreeList has two -- motives and recursors, five flattened constructors/rules, sibling -- recursion in both directions, and one recursive occurrence below a Pi. - { root := ``Ix.Tc.MutualTreeCertificateFixture.breadth, + { root := ``Ix.Kernel.MutualTreeCertificateFixture.breadth, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.MutualTreeCertificateFixture.certifiedFacts, + { root := ``Ix.Kernel.MutualTreeCertificateFixture.certifiedFacts, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.MutualTreeCertificateFixture.finalEnvWF, + { root := ``Ix.Kernel.MutualTreeCertificateFixture.finalEnvWF, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, @@ -3504,7 +3490,7 @@ private def roots : Array RootAllowance := #[ -- `TreeList, Tree`. All seven family/constructor entries are linked to the -- complete catalog and admitted atomically without the pending recursor -- pattern/WF witnesses used by the later conditional closure. - { root := ``Ix.Tc.MutualTreeFixture.mutualFamilyAtomicClosure, + { root := ``Ix.Kernel.MutualTreeFixture.mutualFamilyAtomicClosure, standardAxioms := standard, nativeAxioms := mutualFamilyNative }, @@ -3513,28 +3499,28 @@ private def roots : Array RootAllowance := #[ -- elimination, and both generated rules. It remains Theory-only here; -- production Ix catalog correspondence is audited in the later linkage. { root := - ``Ix.Tc.IndexedRecursiveCertificateFixture.transaction_generation, + ``Ix.Kernel.IndexedRecursiveCertificateFixture.transaction_generation, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.IndexedRecursiveCertificateFixture.breadth, + { root := ``Ix.Kernel.IndexedRecursiveCertificateFixture.breadth, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.IndexedRecursiveCertificateFixture.certifiedFacts, + { root := ``Ix.Kernel.IndexedRecursiveCertificateFixture.certifiedFacts, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.IndexedRecursiveCertificateFixture.producedCertificate_eq, + { root := ``Ix.Kernel.IndexedRecursiveCertificateFixture.producedCertificate_eq, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.IndexedRecursiveCertificateFixture.producedToCertified_eq, + { root := ``Ix.Kernel.IndexedRecursiveCertificateFixture.producedToCertified_eq, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.IndexedRecursiveCertificateFixture.producerLinkedFacts, + { root := ``Ix.Kernel.IndexedRecursiveCertificateFixture.producerLinkedFacts, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, @@ -3544,13 +3530,13 @@ private def roots : Array RootAllowance := #[ -- IndexedVec certificate, these roots remain entirely on the Theory side -- of the catalog/checker boundary. { root := - ``Ix.Tc.RecursivePiCertificateFixture.transaction_generation, + ``Ix.Kernel.RecursivePiCertificateFixture.transaction_generation, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.RecursivePiCertificateFixture.breadth, + { root := ``Ix.Kernel.RecursivePiCertificateFixture.breadth, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, - { root := ``Ix.Tc.RecursivePiCertificateFixture.certifiedFacts, + { root := ``Ix.Kernel.RecursivePiCertificateFixture.certifiedFacts, standardAxioms := standard, forbiddenDependencies := certificateAdapterForbidden }, @@ -3559,23 +3545,23 @@ private def roots : Array RootAllowance := #[ -- `outParam Prop`, while the analyzer-owned candidate exposes `Prop`. -- These certificate roots remain entirely on the Theory side. { root := - ``Ix.Tc.AnnotatedPiCertificateFixture.transaction_generation, + ``Ix.Kernel.AnnotatedPiCertificateFixture.transaction_generation, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AnnotatedPiCertificateFixture.breadth, + { root := ``Ix.Kernel.AnnotatedPiCertificateFixture.breadth, standardAxioms := standardWithoutChoice, nativeAxioms := annotatedPiCertificateBreadthNative, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AnnotatedPiCertificateFixture.certifiedFacts, + { root := ``Ix.Kernel.AnnotatedPiCertificateFixture.certifiedFacts, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AnnotatedPiCertificateFixture.producerLinkedFacts, + { root := ``Ix.Kernel.AnnotatedPiCertificateFixture.producerLinkedFacts, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, @@ -3584,23 +3570,23 @@ private def roots : Array RootAllowance := #[ -- `Type`. These roots certify the non-identity family-result view without -- Ix catalog, checker-pattern, or oracle authority. { root := - ``Ix.Tc.AliasFormerCertificateFixture.transaction_generation, + ``Ix.Kernel.AliasFormerCertificateFixture.transaction_generation, standardAxioms := standard, - upstreamAxioms := aliasFormerUpstreamAxioms, + implementationAxioms := aliasFormerUpstreamAxioms, sorryOrigins := aliasFormerUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AliasFormerCertificateFixture.breadth, + { root := ``Ix.Kernel.AliasFormerCertificateFixture.breadth, standardAxioms := standardWithoutChoice, nativeAxioms := aliasFormerCertificateBreadthNative, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AliasFormerCertificateFixture.certifiedFacts, + { root := ``Ix.Kernel.AliasFormerCertificateFixture.certifiedFacts, standardAxioms := standard, - upstreamAxioms := aliasFormerUpstreamAxioms, + implementationAxioms := aliasFormerUpstreamAxioms, sorryOrigins := aliasFormerUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AliasFormerCertificateFixture.producerLinkedFacts, + { root := ``Ix.Kernel.AliasFormerCertificateFixture.producerLinkedFacts, standardAxioms := standard, - upstreamAxioms := aliasFormerUpstreamAxioms, + implementationAxioms := aliasFormerUpstreamAxioms, sorryOrigins := aliasFormerUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, @@ -3608,20 +3594,20 @@ private def roots : Array RootAllowance := #[ -- certifying the direct-recursive checked field. The adapter packages the -- pinned upstream generation/WF replay without Ix-side semantic authority. { root := - ``Ix.Tc.AliasRecCertificateFixture.transaction_generation, + ``Ix.Kernel.AliasRecCertificateFixture.transaction_generation, standardAxioms := standard, - upstreamAxioms := aliasRecUpstreamAxioms, + implementationAxioms := aliasRecUpstreamAxioms, sorryOrigins := aliasRecUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AliasRecCertificateFixture.breadth, + { root := ``Ix.Kernel.AliasRecCertificateFixture.breadth, standardAxioms := standard, - upstreamAxioms := aliasRecUpstreamAxioms, + implementationAxioms := aliasRecUpstreamAxioms, nativeAxioms := aliasRecCertificateBreadthNative, sorryOrigins := aliasRecUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - { root := ``Ix.Tc.AliasRecCertificateFixture.certifiedFacts, + { root := ``Ix.Kernel.AliasRecCertificateFixture.certifiedFacts, standardAxioms := standard, - upstreamAxioms := aliasRecUpstreamAxioms, + implementationAxioms := aliasRecUpstreamAxioms, sorryOrigins := aliasRecUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, @@ -3629,40 +3615,40 @@ private def roots : Array RootAllowance := #[ -- family and strengthen every production guard into the elementwise -- valid-inductive-application invariant, without oracle authority. { root := - ``Ix.Tc.RecM.checkPositiveRecursiveApplicationPreconditions_success_iff, + ``Ix.Kernel.RecM.checkPositiveRecursiveApplicationPreconditions_success_iff, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.positiveUniverseArgumentsAgree_eq_true_iff, + { root := ``Ix.Kernel.RecM.positiveUniverseArgumentsAgree_eq_true_iff, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.positiveIndicesIndependent_eq_true_iff, + { root := ``Ix.Kernel.RecM.positiveIndicesIndependent_eq_true_iff, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositiveParametersFrom_success, + { root := ``Ix.Kernel.RecM.checkPositiveParametersFrom_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositiveParameters_success, + { root := ``Ix.Kernel.RecM.checkPositiveParameters_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.PositiveParameterComparisonTrace.sound, + { root := ``Ix.Kernel.RecM.PositiveParameterComparisonTrace.sound, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.PositiveParameterComparisonTrace.theoryDefEq, + { root := ``Ix.Kernel.RecM.PositiveParameterComparisonTrace.theoryDefEq, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.ValidPositiveRecursiveApplicationHeader.theoryParameters, + ``Ix.Kernel.RecM.ValidPositiveRecursiveApplicationHeader.theoryParameters, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.PositiveParameterComparisonTrace.theoryDefEqScoped, + ``Ix.Kernel.RecM.PositiveParameterComparisonTrace.theoryDefEqScoped, standardAxioms := standard, nativeAxioms := inferNative, -- This is the K2S instantiation bridge, not the oracle-free occurrence @@ -3671,40 +3657,40 @@ private def roots : Array RootAllowance := #[ -- confined to the projected `ScopedWFAtOn.isDefEq` field. forbiddenDependencies := boundedKnotForbiddenDependencies }, { root := - ``Ix.Tc.RecM.ValidPositiveRecursiveApplicationHeader.theoryParametersScoped, + ``Ix.Kernel.RecM.ValidPositiveRecursiveApplicationHeader.theoryParametersScoped, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.positivityGroupMatches_eq_true_iff, + { root := ``Ix.Kernel.RecM.positivityGroupMatches_eq_true_iff, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.SpecializationIdentityFixture.semanticUniverseEquality_does_not_collapse_specialization, + ``Ix.Kernel.SpecializationIdentityFixture.semanticUniverseEquality_does_not_collapse_specialization, standardAxioms := standard, nativeAxioms := specializationIdentityNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.checkPositiveRecursiveApplicationHeader_success, + ``Ix.Kernel.RecM.checkPositiveRecursiveApplicationHeader_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.PositiveRecursiveApplicationHeaderTrace.valid, + { root := ``Ix.Kernel.RecM.PositiveRecursiveApplicationHeaderTrace.valid, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositiveRecursiveApplicationHeader_valid, + { root := ``Ix.Kernel.RecM.checkPositiveRecursiveApplicationHeader_valid, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositiveRecursiveApplication_success, + { root := ``Ix.Kernel.RecM.checkPositiveRecursiveApplication_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.PositiveRecursiveApplicationTrace.valid, + { root := ``Ix.Kernel.RecM.PositiveRecursiveApplicationTrace.valid, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositiveRecursiveApplication_valid, + { root := ``Ix.Kernel.RecM.checkPositiveRecursiveApplication_valid, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -3713,31 +3699,31 @@ private def roots : Array RootAllowance := #[ -- direct recursive-family applications inherit the oracle-free occurrence -- invariant; and forall success exposes the decremented recursive run plus -- exact local-context restoration. - { root := ``Ix.Tc.RecM.withLctxRestoration_success, + { root := ``Ix.Kernel.RecM.withLctxRestoration_success, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_rootFree, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_rootFree, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_direct, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_direct, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_direct_valid, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_direct_valid, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_nested, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_nested, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_forall_success, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_forall_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_forall_negative, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_forall_negative, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -3747,79 +3733,79 @@ private def roots : Array RootAllowance := #[ -- traversal, universe instantiation, parameter stripping/substitution, -- recursive field-domain checks, and context restoration. The final root -- classifies every successful production domain without a branch oracle. - { root := ``Ix.Tc.RecM.findNestedPositivityGroup?_some, + { root := ``Ix.Kernel.RecM.findNestedPositivityGroup?_some, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.checkNestedPositivityApplicationPreconditions_success_iff, + ``Ix.Kernel.RecM.checkNestedPositivityApplicationPreconditions_success_iff, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.checkNestedPositivityApplicationResolvedFuel_success, + ``Ix.Kernel.RecM.checkNestedPositivityApplicationResolvedFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.checkNestedPositivityApplicationCheckedFuel_success, + ``Ix.Kernel.RecM.checkNestedPositivityApplicationCheckedFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkNestedConstructorFuel_success, + { root := ``Ix.Kernel.RecM.checkNestedConstructorFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkNestedConstructorsFuel_success, + { root := ``Ix.Kernel.RecM.checkNestedConstructorsFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.checkFreshNestedPositivityApplicationFuel_success, + ``Ix.Kernel.RecM.checkFreshNestedPositivityApplicationFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.stripNestedCtorParameters_success, + { root := ``Ix.Kernel.RecM.stripNestedCtorParameters_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkNestedCtorFieldsLoopFuel_success, + { root := ``Ix.Kernel.RecM.checkNestedCtorFieldsLoopFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkNestedCtorFieldsFuel_success, + { root := ``Ix.Kernel.RecM.checkNestedCtorFieldsFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.completeNestedConstructor_of_trace, + { root := ``Ix.Kernel.RecM.completeNestedConstructor_of_trace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.completeNestedConstructorList_of_trace, + { root := ``Ix.Kernel.RecM.completeNestedConstructorList_of_trace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.completeFreshNestedPositivity_of_trace, + { root := ``Ix.Kernel.RecM.completeFreshNestedPositivity_of_trace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.completeNestedPositivityChecked_of_trace, + { root := ``Ix.Kernel.RecM.completeNestedPositivityChecked_of_trace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.completeNestedPositivityResolved_of_trace, + { root := ``Ix.Kernel.RecM.completeNestedPositivityResolved_of_trace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.checkNestedPositivityApplicationFuel_success, + ``Ix.Kernel.RecM.checkNestedPositivityApplicationFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.checkNestedPositivityApplicationFuel_complete, + ``Ix.Kernel.RecM.checkNestedPositivityApplicationFuel_complete, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_success, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -3831,121 +3817,121 @@ private def roots : Array RootAllowance := #[ -- real public builder returns an aligned, duplicate-free physical/key list. -- The next fixture must identify its positivity request with one detector -- call; it cannot replace that reachability evidence with DefEq. - { root := ``Ix.Tc.lawfulBEqNestedSpecializationKey, + { root := ``Ix.Kernel.lawfulBEqNestedSpecializationKey, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedAuxiliaryHeaderRel.key_eq, + { root := ``Ix.Kernel.NestedAuxiliaryHeaderRel.key_eq, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedAuxiliaryHeaderRel.positivityFlatIdentity, + { root := ``Ix.Kernel.NestedAuxiliaryHeaderRel.positivityFlatIdentity, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedAuxiliaryAppendTrace.member_mem, + { root := ``Ix.Kernel.NestedAuxiliaryAppendTrace.member_mem, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedAuxiliaryAppendTrace.key_mem, + { root := ``Ix.Kernel.NestedAuxiliaryAppendTrace.key_mem, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.appendNestedAuxiliary_fresh, + { root := ``Ix.Kernel.RecM.appendNestedAuxiliary_fresh, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.appendNestedAuxiliary_existing, + { root := ``Ix.Kernel.RecM.appendNestedAuxiliary_existing, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxSeenSound.empty, + { root := ``Ix.Kernel.FlatAuxSeenSound.empty, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxSeenSound.push, + { root := ``Ix.Kernel.FlatAuxSeenSound.push, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxTransition.seenSound, + { root := ``Ix.Kernel.FlatAuxTransition.seenSound, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxTransition.flat_mem, + { root := ``Ix.Kernel.FlatAuxTransition.flat_mem, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxTransition.key_mem, + { root := ``Ix.Kernel.FlatAuxTransition.key_mem, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxHistory.single, + { root := ``Ix.Kernel.FlatAuxHistory.single, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxHistory.trans, + { root := ``Ix.Kernel.FlatAuxHistory.trans, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxHistory.seenSound, + { root := ``Ix.Kernel.FlatAuxHistory.seenSound, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxHistory.flat_mem, + { root := ``Ix.Kernel.FlatAuxHistory.flat_mem, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxHistory.key_mem, + { root := ``Ix.Kernel.FlatAuxHistory.key_mem, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxQueueExact.empty, + { root := ``Ix.Kernel.FlatAuxQueueExact.empty, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxQueueExact.pushOriginal, + { root := ``Ix.Kernel.FlatAuxQueueExact.pushOriginal, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxQueueExact.transition, + { root := ``Ix.Kernel.FlatAuxQueueExact.transition, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.FlatAuxQueueExact.history, + { root := ``Ix.Kernel.FlatAuxQueueExact.history, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.appendNestedAuxiliary_transition, + { root := ``Ix.Kernel.RecM.appendNestedAuxiliary_transition, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.appendNestedAuxiliary_seenSound, + { root := ``Ix.Kernel.RecM.appendNestedAuxiliary_seenSound, standardAxioms := standard, nativeAxioms := occurrenceValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryDetectNestedCore_transition, + { root := ``Ix.Kernel.RecM.tryDetectNestedCore_transition, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryDetectNested_transition, + { root := ``Ix.Kernel.RecM.tryDetectNested_transition, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryDetectNested_seenSound, + { root := ``Ix.Kernel.RecM.tryDetectNested_seenSound, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.scanFlatConstructorFields_history, + { root := ``Ix.Kernel.RecM.scanFlatConstructorFields_history, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.scanFlatConstructor_history, + { root := ``Ix.Kernel.RecM.scanFlatConstructor_history, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.scanFlatConstructors_history, + { root := ``Ix.Kernel.RecM.scanFlatConstructors_history, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.buildFlatBlockQueueStep_history, + { root := ``Ix.Kernel.RecM.buildFlatBlockQueueStep_history, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.runBounded_flatAuxHistory, + { root := ``Ix.Kernel.RecM.runBounded_flatAuxHistory, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.seedFlatBlockMembers_exact, + { root := ``Ix.Kernel.RecM.seedFlatBlockMembers_exact, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.buildFlatBlockWithAuxSeen_exact, + { root := ``Ix.Kernel.RecM.buildFlatBlockWithAuxSeen_exact, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.buildFlatBlock_auxiliaryOrder, + { root := ``Ix.Kernel.RecM.buildFlatBlock_auxiliaryOrder, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.CompleteNestedPositivityApplicationTrace.auxiliaryRequest, + ``Ix.Kernel.CompleteNestedPositivityApplicationTrace.auxiliaryRequest, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.CompleteNestedPositivityApplicationTrace.producedRequest, + ``Ix.Kernel.CompleteNestedPositivityApplicationTrace.producedRequest, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -3954,206 +3940,206 @@ private def roots : Array RootAllowance := #[ -- runs production ingress, positivity, and flat-block construction on the -- same `Box Tree` occurrence. Its headline root proves that the exact -- fresh positivity request is retained under the audited queue invariant. - { root := ``Ix.Tc.NestedRecursiveFixture.boxIngressRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.boxIngressRun, standardAxioms := standard, nativeAxioms := levelNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxIngressSucceededNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.boxIngressSucceededNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.treeIngressRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.treeIngressRun, standardAxioms := standard, nativeAxioms := levelNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.treeIngressSucceededNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.treeIngressSucceededNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.boxConcreteHeader, + { root := ``Ix.Kernel.NestedRecursiveFixture.boxConcreteHeader, standardAxioms := standard, nativeAxioms := levelNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxConcreteHeaderMatchesNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.boxConcreteHeaderMatchesNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nodeConcreteType, + { root := ``Ix.Kernel.NestedRecursiveFixture.nodeConcreteType, standardAxioms := standard, nativeAxioms := levelNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nodeConcreteTypeNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.nodeConcreteTypeNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.positivityRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.positivityRun, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.positivitySucceededNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.positivitySucceededNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedWhnfRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedWhnfRun, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedWhnfSucceededNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.nestedWhnfSucceededNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedWhnfResult_eq, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedWhnfResult_eq, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.nestedWhnfResultNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.nestedWhnfResultNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedActionRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedActionRun, standardAxioms := standard, nativeAxioms := nestedRecursiveActionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.requestHeaderRelation, + { root := ``Ix.Kernel.NestedRecursiveFixture.requestHeaderRelation, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.positivityCompleteTrace, + { root := ``Ix.Kernel.NestedRecursiveFixture.positivityCompleteTrace, standardAxioms := standard, nativeAxioms := nestedRecursiveActionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.boxLookupRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.boxLookupRun, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxLookupSucceededNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.boxLookupSucceededNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.boxLookupConcrete_eq, + { root := ``Ix.Kernel.NestedRecursiveFixture.boxLookupConcrete_eq, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.boxLookupConcreteNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.boxLookupConcreteNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.positivityRequestProduced, + { root := ``Ix.Kernel.NestedRecursiveFixture.positivityRequestProduced, standardAxioms := standard, nativeAxioms := nestedRecursiveProducedNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.positivityRequestFreshExpansion, + { root := ``Ix.Kernel.NestedRecursiveFixture.positivityRequestFreshExpansion, standardAxioms := standard, nativeAxioms := nestedRecursiveFreshNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.flatBuildRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.flatBuildRun, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.flatBuildSucceededNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.flatBuildSucceededNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.builtFlatShape, + { root := ``Ix.Kernel.NestedRecursiveFixture.builtFlatShape, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.builtFlatShapeNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.builtFlatShapeNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.requestedAuxiliaryPresent, + { root := ``Ix.Kernel.NestedRecursiveFixture.requestedAuxiliaryPresent, standardAxioms := standard, nativeAxioms := nameContextNative.push (nestedRecursiveFixtureNativeAxiom - `Ix.Tc.NestedRecursiveFixture.builtFlatShapeNative._native.native_decide.ax_1_1), + `Ix.Kernel.NestedRecursiveFixture.builtFlatShapeNative._native.native_decide.ax_1_1), forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedAuxiliaryReachability, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedAuxiliaryReachability, standardAxioms := standard, nativeAxioms := nestedRecursiveReachabilityNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- Exact Lean4Lean syntax and semantic transport for the retained nested + -- Exact Ix.Theory.Named syntax and semantic transport for the retained nested -- member. The outer field reaches the fresh auxiliary; the auxiliary's -- own field recursively reaches the original Tree member at lower fuel. - { root := ``Ix.Tc.NestedRecursiveFixture.treeCandidateSyntax, + { root := ``Ix.Kernel.NestedRecursiveFixture.treeCandidateSyntax, standardAxioms := standard, nativeAxioms := nestedTreeCandidateSyntaxNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedAuxiliaryCandidateTarget, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedAuxiliaryCandidateTarget, standardAxioms := standard, nativeAxioms := nestedAuxiliaryCandidateTargetNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedOuterPositivityTransport, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedOuterPositivityTransport, standardAxioms := standard, nativeAxioms := nestedOuterTransportNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedOuterConstructorPositivityTrace, + ``Ix.Kernel.NestedRecursiveFixture.nestedOuterConstructorPositivityTrace, standardAxioms := standard, nativeAxioms := nestedOuterTransportNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedAuxiliaryFieldProductionTrace, + ``Ix.Kernel.NestedRecursiveFixture.nestedAuxiliaryFieldProductionTrace, standardAxioms := standard, nativeAxioms := nestedAuxiliaryProductionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedAuxiliaryPositivityTransport, + ``Ix.Kernel.NestedRecursiveFixture.nestedAuxiliaryPositivityTransport, standardAxioms := standard, nativeAxioms := nestedAuxiliaryTransportNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedAuxiliaryFieldProductionTraceAt, + ``Ix.Kernel.NestedRecursiveFixture.nestedAuxiliaryFieldProductionTraceAt, standardAxioms := standard, nativeAxioms := nestedAuxiliaryProductionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedAuxiliaryConstructorPositivityTraceAt, + ``Ix.Kernel.NestedRecursiveFixture.nestedAuxiliaryConstructorPositivityTraceAt, standardAxioms := standard, nativeAxioms := nestedAuxiliaryConstructorNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedAuxiliaryConstructorPositivityTrace, + ``Ix.Kernel.NestedRecursiveFixture.nestedAuxiliaryConstructorPositivityTrace, standardAxioms := standard, nativeAxioms := nestedAuxiliaryConstructorNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.leanFlatNodeConstructorTypeValidationTrace, + ``Ix.Kernel.NestedRecursiveFixture.leanFlatNodeConstructorTypeValidationTrace, standardAxioms := standard, nativeAxioms := nestedNodeConstructorValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.leanFlatNodeConstructorValidationRun, + ``Ix.Kernel.NestedRecursiveFixture.leanFlatNodeConstructorValidationRun, standardAxioms := standard, nativeAxioms := nestedNodeConstructorValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.leanFlatWrapConstructorTypeValidationTrace, + ``Ix.Kernel.NestedRecursiveFixture.leanFlatWrapConstructorTypeValidationTrace, standardAxioms := standard, nativeAxioms := nestedWrapConstructorValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.leanFlatWrapConstructorValidationRun, + ``Ix.Kernel.NestedRecursiveFixture.leanFlatWrapConstructorValidationRun, standardAxioms := standard, nativeAxioms := nestedWrapConstructorValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, -- Completed nested semantic transaction. The generic adapter consumes a - -- pinned Lean4Lean `NestedBlockCertificate`; the concrete roots then prove + -- local named-specification `NestedBlockCertificate`; the concrete roots then prove -- restored source/recursor/rule well-formedness, run Ix's real nested -- family checker, and admit the exact two-member source block atomically. -- No auxiliary flattening name, legacy inductive oracle, or pending axiom -- may enter this completed boundary. - { root := ``Ix.Tc.NestedFamilyCatalogLink.translateMember, + { root := ``Ix.Kernel.NestedFamilyCatalogLink.translateMember, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedFamilyCatalogLink.semanticEntry, + { root := ``Ix.Kernel.NestedFamilyCatalogLink.semanticEntry, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedFamilyCatalogLink.transition, + { root := ``Ix.Kernel.NestedFamilyCatalogLink.transition, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.semanticTreeCertificate, + { root := ``Ix.Kernel.NestedRecursiveFixture.semanticTreeCertificate, standardAxioms := standard, nativeAxioms := nestedSemanticCertificateNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.semanticTreeTransactionFacts, + { root := ``Ix.Kernel.NestedRecursiveFixture.semanticTreeTransactionFacts, standardAxioms := standard, nativeAxioms := nestedSemanticFactsNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedFamilyKernelRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedFamilyKernelRun, standardAxioms := standard, nativeAxioms := nestedFamilyKernelNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedFamilyBlockCertificate, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedFamilyBlockCertificate, standardAxioms := standard, nativeAxioms := nestedFamilyCertificateNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedFamilyAtomicAdmission, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedFamilyAtomicAdmission, standardAxioms := standard, nativeAxioms := nestedFamilyCertificateNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedSemanticTransactionClosure, + ``Ix.Kernel.NestedRecursiveFixture.nestedSemanticTransactionClosure, standardAxioms := standard, nativeAxioms := nestedSemanticTransactionClosureNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, @@ -4162,40 +4148,40 @@ private def roots : Array RootAllowance := #[ -- ingress roots pin the actual generated block; the two pattern roots pin -- the restored node/wrap equations independently; the final roots require -- all-or-nothing family-plus-recursor admission. The only `sorryAx` - -- origins are two exact inversion lemmas inherited from Lean4Lean. - { root := ``Ix.Tc.NestedRecursiveFixture.nestedCompilerRun, + -- origins are two exact inversion lemmas inherited from Ix.Theory.Named. + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedCompilerRun, standardAxioms := standard, nativeAxioms := nestedRecursorCompilerRunNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedCompiledIdentityFacts, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedCompiledIdentityFacts, standardAxioms := standard, nativeAxioms := nestedRecursorCompilerIdentityNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.recursorIngressRun, + { root := ``Ix.Kernel.NestedRecursiveFixture.recursorIngressRun, standardAxioms := standard, nativeAxioms := nestedRecursorIngressNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, { root := - ``Ix.Tc.NestedRecursiveFixture.nestedRecursorRepresentationFacts, + ``Ix.Kernel.NestedRecursiveFixture.nestedRecursorRepresentationFacts, standardAxioms := standard, nativeAxioms := nestedRecursorRepresentationNative, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.treeNodePatternRel, + { root := ``Ix.Kernel.NestedRecursiveFixture.treeNodePatternRel, standardAxioms := standard, nativeAxioms := nestedRecursorNodePatternNative, sorryOrigins := nestedRestoredPatternUpstreamDebt, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.treeWrapPatternRel, + { root := ``Ix.Kernel.NestedRecursiveFixture.treeWrapPatternRel, standardAxioms := standard, nativeAxioms := nestedRecursorWrapPatternNative, sorryOrigins := nestedRestoredPatternUpstreamDebt, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedRecursorAtomicAdmission, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedRecursorAtomicAdmission, standardAxioms := standard, nativeAxioms := nestedRecursorAtomicAdmissionNative, sorryOrigins := nestedRestoredPatternUpstreamDebt, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.NestedRecursiveFixture.nestedRecursorAtomicClosure, + { root := ``Ix.Kernel.NestedRecursiveFixture.nestedRecursorAtomicClosure, standardAxioms := standard, nativeAxioms := nestedRecursorAtomicClosureNative, sorryOrigins := nestedRestoredPatternUpstreamDebt, @@ -4206,77 +4192,77 @@ private def roots : Array RootAllowance := #[ -- under both best-effort and complete rule population. The final root -- covers the actual anonymous-mode cache insertion phase; none of these -- roots may recover the legacy inductive oracle. - { root := ``Ix.Tc.GeneratedRecursorMetadata.at_of_expectedFlat, + { root := ``Ix.Kernel.GeneratedRecursorMetadata.at_of_expectedFlat, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.initialGeneratedRecursor_metadata, + { root := ``Ix.Kernel.initialGeneratedRecursor_metadata, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursor.metadata_setRules, + { root := ``Ix.Kernel.GeneratedRecursor.metadata_setRules, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursor.metadata_withRules, + { root := ``Ix.Kernel.GeneratedRecursor.metadata_withRules, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursor.ty_withRules, + { root := ``Ix.Kernel.GeneratedRecursor.ty_withRules, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursor.map_metadata_modify_withRules, + { root := ``Ix.Kernel.GeneratedRecursor.map_metadata_modify_withRules, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursor.map_metadata_zipWithRules, + { root := ``Ix.Kernel.GeneratedRecursor.map_metadata_zipWithRules, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursor.map_ty_zipWithRules, + { root := ``Ix.Kernel.GeneratedRecursor.map_ty_zipWithRules, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.commitGeneratedRecursorRulesAt_artifacts, + ``Ix.Kernel.RecM.commitGeneratedRecursorRulesAt_artifacts, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.populateOptionalGeneratedRecursorRules_metadata, + ``Ix.Kernel.RecM.populateOptionalGeneratedRecursorRules_metadata, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.RecM.populateCompleteGeneratedRecursorRules_metadata, + ``Ix.Kernel.RecM.populateCompleteGeneratedRecursorRules_metadata, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.populateRecursorRulesFromBlock_artifacts, + { root := ``Ix.Kernel.RecM.populateRecursorRulesFromBlock_artifacts, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.populateRecursorRulesFromBlock_metadata, + { root := ``Ix.Kernel.RecM.populateRecursorRulesFromBlock_metadata, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorSemantics.CanonicalRulesS.generatedRuleAt, + ``Ix.Kernel.GeneratedRecursorSemantics.CanonicalRulesS.generatedRuleAt, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorSemantics.CanonicalArtifactsS.withRules, + ``Ix.Kernel.GeneratedRecursorSemantics.CanonicalArtifactsS.withRules, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorSemantics.CanonicalTypeS.canonical, + ``Ix.Kernel.GeneratedRecursorSemantics.CanonicalTypeS.canonical, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorSemantics.CanonicalRulesS.canonical, + ``Ix.Kernel.GeneratedRecursorSemantics.CanonicalRulesS.canonical, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorSemantics.CanonicalArtifactsS.canonical, + ``Ix.Kernel.GeneratedRecursorSemantics.CanonicalArtifactsS.canonical, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorSemantics.RecM.commitGeneratedRecursorRulesAt_canonicalAt, + ``Ix.Kernel.GeneratedRecursorSemantics.RecM.commitGeneratedRecursorRulesAt_canonicalAt, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.buildGeneratedRecursorTypes_metadata, + { root := ``Ix.Kernel.RecM.buildGeneratedRecursorTypes_metadata, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.buildAndCacheGeneratedRecursors_metadata, + { root := ``Ix.Kernel.RecM.buildAndCacheGeneratedRecursors_metadata, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -4284,71 +4270,71 @@ private def roots : Array RootAllowance := #[ -- E2c generated-recursor type closure. Production closes the accumulated -- domains through explicit right-to-left intern requests. These roots prove -- exact finite-support execution, operation-shaped structural translation, - -- and equality with Lean4Lean's public canonical mixed recursor type. - { root := ``Ix.Tc.CertifiedGenerationTransaction.generationEnv, + -- and equality with Ix.Theory.Named's public canonical mixed recursor type. + { root := ``Ix.Kernel.CertifiedGenerationTransaction.generationEnv, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.opened_toCtx, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.opened_toCtx, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.isType_forallN_inv, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.isType_forallN_inv, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.onTel_isType_getElem, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.onTel_isType_getElem, standardAxioms := propextOnly, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorTypeClosure.canonical_onTel_and_bodyType, + ``Ix.Kernel.GeneratedRecursorTypeClosure.canonical_onTel_and_bodyType, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.canonical_domainType, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.canonical_domainType, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.canonical_bodyType, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.canonical_bodyType, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorTypeClosure.TelescopeS.of_canonical, + ``Ix.Kernel.GeneratedRecursorTypeClosure.TelescopeS.of_canonical, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorTypeClosure.closeV_eq_forallN_take, + ``Ix.Kernel.GeneratedRecursorTypeClosure.closeV_eq_forallN_take, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.closeV_canonical, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.closeV_canonical, standardAxioms := standardWithoutChoice, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.TelescopeS.close, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.TelescopeS.close, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.run_exact, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.run_exact, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.run_translation, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.run_translation, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.run_canonicalType, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.run_canonicalType, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.GeneratedRecursorTypeClosure.buildRecType_decompose, + { root := ``Ix.Kernel.GeneratedRecursorTypeClosure.buildRecType_decompose, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.GeneratedRecursorTypeClosure.buildRecType_canonical_of_body, + ``Ix.Kernel.GeneratedRecursorTypeClosure.buildRecType_canonical_of_body, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.familyBuildTypeExecution, + { root := ``Ix.Kernel.IndexedRecursiveFixture.familyBuildTypeExecution, standardAxioms := standard, nativeAxioms := generatedRecursorTypeFixtureNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.familyBuildArtifactsExecution, + { root := ``Ix.Kernel.IndexedRecursiveFixture.familyBuildArtifactsExecution, standardAxioms := standard, nativeAxioms := generatedRecursorRuleFixtureNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -4358,31 +4344,31 @@ private def roots : Array RootAllowance := #[ -- finite fold; one K2S successor layer preserves the scoped state across -- selection and gives semantic meaning to the repeated type and positional -- rule comparisons. - { root := ``Ix.Tc.RecM.checkGeneratedRecursorFromCache_success, + { root := ``Ix.Kernel.RecM.checkGeneratedRecursorFromCache_success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkGeneratedRecursorFromCache_canonical, + { root := ``Ix.Kernel.RecM.checkGeneratedRecursorFromCache_canonical, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkGeneratedRecursorFromCache_canonicalScoped, + { root := ``Ix.Kernel.RecM.checkGeneratedRecursorFromCache_canonicalScoped, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.RecM.selectGeneratedRecursorIndex_preservesScoped, + { root := ``Ix.Kernel.RecM.selectGeneratedRecursorIndex_preservesScoped, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.familyRuleCommitExecution, + { root := ``Ix.Kernel.IndexedRecursiveFixture.familyRuleCommitExecution, standardAxioms := standard, nativeAxioms := generatedRecursorCommitFixtureNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.familyCacheCheckExecution, + { root := ``Ix.Kernel.IndexedRecursiveFixture.familyCacheCheckExecution, standardAxioms := standard, nativeAxioms := generatedRecursorCheckerFixtureNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.familyCacheCheckCanonicalScoped, + { root := ``Ix.Kernel.IndexedRecursiveFixture.familyCacheCheckCanonicalScoped, standardAxioms := standard, nativeAxioms := generatedRecursorCanonicalFixtureNative, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, @@ -4395,88 +4381,88 @@ private def roots : Array RootAllowance := #[ -- audit forbids every oracle constructor/world-materialization operation -- rather than the `InductiveOracle` type name itself. { root := - ``Ix.Tc.SemanticBlockTransitionCertificate.le_admittedWorld, + ``Ix.Kernel.SemanticBlockTransitionCertificate.le_admittedWorld, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.SemanticBlockTransitionCertificate.admit, + { root := ``Ix.Kernel.SemanticBlockTransitionCertificate.admit, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.SemanticBlockTransitionCertificate.admitState, + { root := ``Ix.Kernel.SemanticBlockTransitionCertificate.admitState, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, { root := - ``Ix.Tc.ExistingSemanticBlockCertificate.le_admittedWorld, + ``Ix.Kernel.ExistingSemanticBlockCertificate.le_admittedWorld, standardAxioms := standard, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.ExistingSemanticBlockCertificate.admit, + { root := ``Ix.Kernel.ExistingSemanticBlockCertificate.admit, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.ExistingSemanticBlockCertificate.admitState, + { root := ``Ix.Kernel.ExistingSemanticBlockCertificate.admitState, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.OneFamilyRecursorCertificate.atomicClosure, + { root := ``Ix.Kernel.OneFamilyRecursorCertificate.atomicClosure, standardAxioms := standard, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.familyRecursorAtomicClosure, + { root := ``Ix.Kernel.IndexedRecursiveFixture.familyRecursorAtomicClosure, standardAxioms := standard, nativeAxioms := generatedRecursorAtomicClosureNative, sorryOrigins := typingDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.producerLinkedOneFamilyClosure, + { root := ``Ix.Kernel.IndexedRecursiveFixture.producerLinkedOneFamilyClosure, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, nativeAxioms := indexedProducerClosureNative, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, { root := - ``Ix.Tc.RecursivePiRecursorFixture.recursivePiAtomicClosure, + ``Ix.Kernel.RecursivePiRecursorFixture.recursivePiAtomicClosure, standardAxioms := standard, nativeAxioms := recursivePiAtomicClosureNative, sorryOrigins := typingDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, { root := - ``Ix.Tc.AnnotatedPiRecursorFixture.annotatedPiAtomicClosure, + ``Ix.Kernel.AnnotatedPiRecursorFixture.annotatedPiAtomicClosure, standardAxioms := standard, - upstreamAxioms := annotatedPiUpstreamAxioms, + implementationAxioms := annotatedPiUpstreamAxioms, nativeAxioms := annotatedPiAtomicClosureNative, sorryOrigins := annotatedPiUpstreamDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, { root := - ``Ix.Tc.AliasFormerRecursorFixture.aliasFormerAtomicClosure, + ``Ix.Kernel.AliasFormerRecursorFixture.aliasFormerAtomicClosure, standardAxioms := standard, - upstreamAxioms := aliasFormerUpstreamAxioms, + implementationAxioms := aliasFormerUpstreamAxioms, nativeAxioms := aliasFormerAtomicClosureNative, sorryOrigins := aliasFormerUpstreamDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, { root := - ``Ix.Tc.AliasRecRecursorFixture.aliasRecAtomicClosure, + ``Ix.Kernel.AliasRecRecursorFixture.aliasRecAtomicClosure, standardAxioms := standard, - upstreamAxioms := aliasRecUpstreamAxioms, + implementationAxioms := aliasRecUpstreamAxioms, nativeAxioms := aliasRecAtomicClosureNative, sorryOrigins := aliasRecUpstreamDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, -- E2c flat semantic transport. The refined flat production trace erases -- to the exhaustive classifier, and the operation-shaped cross-kernel - -- contract recursively constructs Lean4Lean's retained positivity trace. + -- contract recursively constructs Ix.Theory.Named's retained positivity trace. -- Nested auxiliary expansion remains a separate explicit bridge. - { root := ``Ix.Tc.FlatPositivityDomainTrace.toPositivityDomainTrace, + { root := ``Ix.Kernel.FlatPositivityDomainTrace.toPositivityDomainTrace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, { root := - ``Ix.Tc.FlatPositivityTraceTransport.constructorPositivityTrace, + ``Ix.Kernel.FlatPositivityTraceTransport.constructorPositivityTrace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, -- E2c's concrete cross-kernel trace bridge. These roots start at the -- exact positivity calls selected by the production IndexedVec family - -- checker, transport those operations to Lean4Lean, and replay the complete + -- checker, transport those operations to Ix.Theory.Named, and replay the complete -- retained constructor validator. The direct recursive fixture has no -- nested auxiliary expansion; that remains the next generic E2c bridge. { root := - ``Ix.Tc.IndexedRecursiveFixture.indexedVecConsConstructorValidationRun, + ``Ix.Kernel.IndexedRecursiveFixture.indexedVecConsConstructorValidationRun, standardAxioms := standard, nativeAxioms := indexedConstructorValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -4487,23 +4473,23 @@ private def roots : Array RootAllowance := #[ -- family/recursor checking, exact ownership, and atomic admission. The -- same executable witness rejects a recursor whose stored index arity was -- changed while its canonical type and rules were retained. - { root := ``Lean4Lean.VEnv.HasType.lamN_appN_beta, + { root := ``Ix.Theory.Named.VEnv.HasType.lamN_appN_beta, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursivePattern.nilPatternRel, + { root := ``Ix.Kernel.IndexedRecursivePattern.nilPatternRel, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursivePattern.consPatternRel, + { root := ``Ix.Kernel.IndexedRecursivePattern.consPatternRel, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursivePattern.oracle, + { root := ``Ix.Kernel.IndexedRecursivePattern.oracle, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IndexedRecursiveFixture.endToEndAcceptance, + { root := ``Ix.Kernel.IndexedRecursiveFixture.endToEndAcceptance, standardAxioms := standard, nativeAxioms := indexedRecursiveNative, sorryOrigins := typingDebt, @@ -4512,13 +4498,13 @@ private def roots : Array RootAllowance := #[ -- Elimination-breadth regression over exact kernel declarations. These -- roots compile, ingress, and run the production family/recursor checkers -- for both a source-universe-bearing small eliminator and `Eq`'s positive - -- K branch, then relate the stored physical metadata to Lean4Lean's exact + -- K branch, then relate the stored physical metadata to Ix.Theory.Named's exact -- generation trace. - { root := ``Ix.Tc.EliminationBreadthFixture.smallEliminationAcceptance, + { root := ``Ix.Kernel.EliminationBreadthFixture.smallEliminationAcceptance, standardAxioms := standard, nativeAxioms := smallEliminationAcceptanceNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - { root := ``Ix.Tc.EliminationBreadthFixture.kTargetAcceptance, + { root := ``Ix.Kernel.EliminationBreadthFixture.kTargetAcceptance, standardAxioms := standard, nativeAxioms := kTargetAcceptanceNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, @@ -4528,32 +4514,32 @@ private def roots : Array RootAllowance := #[ -- consumes those oracle constructors: its family block advances the exact -- generated Theory environment, and its recursor block consumes entries -- already installed there. - { root := ``Lean4Lean.VEnv.HasType.transfer_appN_telescope, + { root := ``Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.SingletonFamilyCatalogLink.oracle, + { root := ``Ix.Kernel.SingletonFamilyCatalogLink.oracle, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.SingletonRecursorCatalogLink.enumerationPatternRel, + { root := ``Ix.Kernel.SingletonRecursorCatalogLink.enumerationPatternRel, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.SingletonRecursorCatalogLink.oracle, + { root := ``Ix.Kernel.SingletonRecursorCatalogLink.oracle, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.certifySingletonFamilyBlock, + { root := ``Ix.Kernel.RecM.certifySingletonFamilyBlock, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.certifySingletonRecursorBlock, + { root := ``Ix.Kernel.RecM.certifySingletonRecursorBlock, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, -- Oracle-free semantic composition is audited independently of production -- execution so its native boundary contains only the finite representation, -- generation, equation, and pattern checks. - { root := ``Ix.Tc.BooleanEnumerationFixture.oneFamilyAtomicClosure, + { root := ``Ix.Kernel.BooleanEnumerationFixture.oneFamilyAtomicClosure, standardAxioms := standard, nativeAxioms := booleanSemanticAdmissionNative, sorryOrigins := typingDebt, @@ -4561,7 +4547,7 @@ private def roots : Array RootAllowance := #[ -- The headline additionally joins anonymous ingress, both production -- block-body and branch checkers, exact physical/catalog ownership, and the -- composed two-stage semantic transaction in one final world. - { root := ``Ix.Tc.BooleanEnumerationFixture.endToEndAcceptance, + { root := ``Ix.Kernel.BooleanEnumerationFixture.endToEndAcceptance, standardAxioms := standard, nativeAxioms := booleanEnumerationNative, sorryOrigins := typingDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, @@ -4569,410 +4555,408 @@ private def roots : Array RootAllowance := #[ -- G2a's explicit ambient-inductive assumption boundary. Audit every -- oracle projection so adding a field changes this manifest, then pin the -- constructive Nat model and its adversarial loaded-state witness. - { root := ``Ix.Tc.RawInductiveConstRel.mono, + { root := ``Ix.Kernel.RawInductiveConstRel.mono, standardAxioms := standard }, - { root := ``Ix.Tc.TrKExprS.mono, + { root := ``Ix.Kernel.TrKExprS.mono, standardAxioms := standard }, - { root := ``Ix.Tc.RegisteredRecursorRuleRhsRel.mono, + { root := ``Ix.Kernel.RegisteredRecursorRuleRhsRel.mono, standardAxioms := standard }, - { root := ``Ix.Tc.RegisteredRecursorRuleRhsRel.rhsTyped, + { root := ``Ix.Kernel.RegisteredRecursorRuleRhsRel.rhsTyped, standardAxioms := standard }, - { root := ``Ix.Tc.RawRecursorRuleRel.registeredRhs, + { root := ``Ix.Kernel.RawRecursorRuleRel.registeredRhs, standardAxioms := standard }, - { root := ``Ix.Tc.RawRecursorRuleRel.mono, + { root := ``Ix.Kernel.RawRecursorRuleRel.mono, standardAxioms := standard }, - { root := ``Ix.Tc.HeadConstN.of_varN_matches }, - { root := ``Ix.Tc.RecursorIotaPattern.matches_shape }, - { root := ``Ix.Tc.KConst.RecursorRuleAt.hasRecursorRule, + { root := ``Ix.Kernel.HeadConstN.of_varN_matches }, + { root := ``Ix.Kernel.RecursorIotaPattern.matches_shape }, + { root := ``Ix.Kernel.KConst.RecursorRuleAt.hasRecursorRule, standardAxioms := propextOnly }, - { root := ``Ix.Tc.RawRecursorRulePatternRel.mono, + { root := ``Ix.Kernel.RawRecursorRulePatternRel.mono, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.InductiveOracle.members, + { root := ``Ix.Kernel.InductiveOracle.members, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.nonempty, + { root := ``Ix.Kernel.InductiveOracle.nonempty, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.fresh, + { root := ``Ix.Kernel.InductiveOracle.fresh, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.after, + { root := ``Ix.Kernel.InductiveOracle.after, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.envLE, + { root := ``Ix.Kernel.InductiveOracle.envLE, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.blockWF, + { root := ``Ix.Kernel.InductiveOracle.blockWF, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.translateBlock, + { root := ``Ix.Kernel.InductiveOracle.translateBlock, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.recursorFacts, + { root := ``Ix.Kernel.InductiveOracle.recursorFacts, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.recursorPatterns, + { root := ``Ix.Kernel.InductiveOracle.recursorPatterns, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveOracle.catalogued, + { root := ``Ix.Kernel.InductiveOracle.catalogued, standardAxioms := standard }, - { root := ``Ix.Tc.AmbientNat.oracle, + { root := ``Ix.Kernel.AmbientNat.oracle, standardAxioms := standard }, - { root := ``Ix.Tc.AmbientNat.nat_lookup_good, + { root := ``Ix.Kernel.AmbientNat.nat_lookup_good, standardAxioms := standard }, - { root := ``Ix.Tc.AmbientNat.badDecl_not_wf, + { root := ``Ix.Kernel.AmbientNat.badDecl_not_wf, standardAxioms := standard }, - { root := ``Ix.Tc.AmbientNat.acceptance, + { root := ``Ix.Kernel.AmbientNat.acceptance, standardAxioms := standard }, - -- G2b's C1--C3 consumer path. These roots resolve exact concrete + -- Lookup and admission roots resolve exact concrete -- constants through trusted-world provenance and are mechanically barred -- from depending on the legacy whole-environment translation. - { root := ``Ix.Tc.TrustedConstRel.mono, + { root := ``Ix.Kernel.TrustedConstRel.mono, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrustedConstRel.trKExprS_const, + { root := ``Ix.Kernel.TrustedConstRel.trKExprS_const, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrustedCatalogRel.resolve, + { root := ``Ix.Kernel.TrustedCatalogRel.resolve, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcStateWF.resolve, + { root := ``Ix.Kernel.TcStateWF.resolve, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcInv.resolve, + { root := ``Ix.Kernel.TcInv.resolve, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.natResolved, + { root := ``Ix.Kernel.AmbientNat.natResolved, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.natReferenceTranslates, + { root := ``Ix.Kernel.AmbientNat.natReferenceTranslates, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.bad_not_resolved, + { root := ``Ix.Kernel.AmbientNat.bad_not_resolved, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.natResolvedInv, + { root := ``Ix.Kernel.AmbientNat.natResolvedInv, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, -- G4's lookup isolation, exhaustive semantic-cache provenance, monotone -- warm-world transport, and transactional public-check error boundary. - { root := ``Ix.Tc.PendingDecl.lookup_isolation, + { root := ``Ix.Kernel.PendingDecl.lookup_isolation, standardAxioms := standard }, - { root := ``Ix.Tc.CacheEntry.SupportedBy.mono }, - { root := ``Ix.Tc.CacheAuthority.stable_mono, + { root := ``Ix.Kernel.CacheEntry.SupportedBy.mono }, + { root := ``Ix.Kernel.CacheAuthority.stable_mono, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.CacheProvenance.mono, + { root := ``Ix.Kernel.CacheProvenance.mono, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.CacheProvenance.pending_isolation_stable, + { root := ``Ix.Kernel.CacheProvenance.pending_isolation_stable, standardAxioms := standard }, - { root := ``Ix.Tc.KEnv.restoreBlockCheckResultsOnError_origin, + { root := ``Ix.Kernel.KEnv.restoreBlockCheckResultsOnError_origin, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.mono, + { root := ``Ix.Kernel.CacheInvariant.mono, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.CacheInvariant.insertWhnf, + { root := ``Ix.Kernel.CacheInvariant.insertWhnf, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.insertWhnfNoDelta, + { root := ``Ix.Kernel.CacheInvariant.insertWhnfNoDelta, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.insertWhnfNoDeltaCheap, + { root := ``Ix.Kernel.CacheInvariant.insertWhnfNoDeltaCheap, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.insertWhnfCore, + { root := ``Ix.Kernel.CacheInvariant.insertWhnfCore, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.insertWhnfCoreCheap, + { root := ``Ix.Kernel.CacheInvariant.insertWhnfCoreCheap, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.of_intern_update, + { root := ``Ix.Kernel.CacheInvariant.of_intern_update, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.CacheInvariant.clearReductionCaches, + { root := ``Ix.Kernel.CacheInvariant.clearReductionCaches, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.restoreCheckCachesOnError, + { root := ``Ix.Kernel.CacheInvariant.restoreCheckCachesOnError, standardAxioms := standard }, - { root := ``Ix.Tc.TcM.isolateCheckErrors_error, + { root := ``Ix.Kernel.TcM.isolateCheckErrors_error, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TcM.reset_cache_frame, - standardAxioms := standard, - nativeAxioms := #[nativeAxiom `Blake3 - `Blake3.HasherOps.hash._native.native_decide.ax_1] }, - { root := ``Ix.Tc.KernelStateWF.pendingCacheIsolation, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.KernelStateWF.restoreCheckCachesOnError, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.AmbientNat.warmCache_worldTransport, + { root := ``Ix.Kernel.TcM.reset_cache_frame, + standardAxioms := standard }, + { root := ``Ix.Kernel.KernelStateWF.pendingCacheIsolation, + standardAxioms := standard }, + { root := ``Ix.Kernel.KernelStateWF.restoreCheckCachesOnError, + standardAxioms := standard }, + { root := ``Ix.Kernel.AmbientNat.warmCache_worldTransport, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.warmCache_cannotResolvePending, + { root := ``Ix.Kernel.AmbientNat.warmCache_cannotResolvePending, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.cacheAcceptance, + { root := ``Ix.Kernel.AmbientNat.cacheAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- K1's concrete Theory reduction meaning, exact five-way cache overlay, -- and real ambient-Nat warm-hit witness. The only sorries are the already -- named upstream inductive-environment boundary. - { root := ``Ix.Tc.WhnfMeaning.refl, + { root := ``Ix.Kernel.WhnfMeaning.refl, standardAxioms := standard }, - { root := ``Ix.Tc.WhnfMeaning.symm, + { root := ``Ix.Kernel.WhnfMeaning.symm, standardAxioms := standard }, - { root := ``Ix.Tc.WhnfMeaning.mono, + { root := ``Ix.Kernel.WhnfMeaning.mono, standardAxioms := standard }, - { root := ``Ix.Tc.ExprCacheKind.isWhnf_iff }, - { root := ``Ix.Tc.WhnfCacheValid.mono, + { root := ``Ix.Kernel.ExprCacheKind.isWhnf_iff }, + { root := ``Ix.Kernel.WhnfCacheValid.mono, standardAxioms := standard }, - { root := ``Ix.Tc.WhnfCacheValid.expr, + { root := ``Ix.Kernel.WhnfCacheValid.expr, standardAxioms := standard }, - { root := ``Ix.Tc.CacheProvenance.isRec_of_trusted, + { root := ``Ix.Kernel.CacheProvenance.isRec_of_trusted, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.IsRecCacheValid.mono, + { root := ``Ix.Kernel.IsRecCacheValid.mono, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.IsRecCacheValid.trusted, + { root := ``Ix.Kernel.IsRecCacheValid.trusted, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.kernelCacheSemantics_isRec_valid, + { root := ``Ix.Kernel.kernelCacheSemantics_isRec_valid, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheProvenance.whnfMeaning, + { root := ``Ix.Kernel.CacheProvenance.whnfMeaning, standardAxioms := standard }, - { root := ``Ix.Tc.CacheInvariant.whnfHit, + { root := ``Ix.Kernel.CacheInvariant.whnfHit, standardAxioms := standard }, - { root := ``Ix.Tc.AmbientNat.supportExpr_whnfMeaning, + { root := ``Ix.Kernel.AmbientNat.supportExpr_whnfMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.warmHit_whnfMeaning, + { root := ``Ix.Kernel.AmbientNat.warmHit_whnfMeaning, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNative_noAccel, + { root := ``Ix.Kernel.RecM.tryReduceNative_noAccel, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RecM.tryReduceBitvec_noAccel, + { root := ``Ix.Kernel.RecM.tryReduceBitvec_noAccel, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryReduceDecidable_noAccel, + { root := ``Ix.Kernel.RecM.tryReduceDecidable_noAccel, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RecM.tryReduceFinValDecidableRec_noAccel, + { root := ``Ix.Kernel.RecM.tryReduceFinValDecidableRec_noAccel, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WhnfTheory.exprWF, + { root := ``Ix.Kernel.WhnfTheory.exprWF, standardAxioms := standard }, - { root := ``Ix.Tc.WhnfTheory.transMeaning, + { root := ``Ix.Kernel.WhnfTheory.transMeaning, standardAxioms := standard, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RawProjRel.none_ok, + { root := ``Ix.Kernel.RawProjRel.none_ok, standardAxioms := propextOnly }, - { root := ``Ix.Tc.RawProjRel.lean4Lean_ok, + { root := ``Ix.Kernel.RawProjRel.named_ok, standardAxioms := standard, sorryOrigins := projectionDebt }, - { root := ``Ix.Tc.ConcreteProjectionFixture.acceptance, + { root := ``Ix.Kernel.ConcreteProjectionFixture.acceptance, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := projectionDebt }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_zero, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_zero, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.TcM.whnfKey_closed, + { root := ``Ix.Kernel.TcM.whnfKey_closed, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.ContextKeyFrame.whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_wf, + { root := ``Ix.Kernel.ContextKeyFrame.whnfStateInv, + standardAxioms := standard }, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_wf, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.TcM.whnfKey_wf, + { root := ``Ix.Kernel.TcM.whnfKey_wf, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.TcM.whnfKey_matches_wf, + { root := ``Ix.Kernel.TcM.whnfKey_matches_wf, standardAxioms := standard, nativeAxioms := contextNative }, -- interning frame: exact intern-only framing, execution-indexed simultaneous -- substitution, and the production one-argument beta path. - { root := ``Ix.Tc.InternUpdateFrame.whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.TcM.runIntern_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.TcM.runIntern_whnf_eval, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RunAssumptions.simulSubst_whnf_wf, + { root := ``Ix.Kernel.InternUpdateFrame.whnfStateInv, + standardAxioms := standard }, + { root := ``Ix.Kernel.TcM.runIntern_whnf_wf, + standardAxioms := standard }, + { root := ``Ix.Kernel.TcM.runIntern_whnf_eval, + standardAxioms := standard }, + { root := ``Ix.Kernel.RunAssumptions.simulSubst_whnf_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.simulSubst_whnf_eval, + { root := ``Ix.Kernel.RunAssumptions.simulSubst_whnf_eval, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.WhnfMeaning.beta, + { root := ``Ix.Kernel.WhnfMeaning.beta, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WhnfMeaning.letE, + { root := ``Ix.Kernel.WhnfMeaning.letE, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WhnfMeaning.betaSimul, + { root := ``Ix.Kernel.WhnfMeaning.betaSimul, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.WhnfCoreLeaf.eval, + { root := ``Ix.Kernel.RecM.WhnfCoreLeaf.eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_betaOne, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_betaOne, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_leaf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_leaf, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_betaOne, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_betaOne, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_betaOne_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_betaOne_wf, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_leaf_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_leaf_wf, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.warmStateInvAccelerated, + { root := ``Ix.Kernel.AmbientNat.warmStateInvAccelerated, standardAxioms := standard, nativeAxioms := inferNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.warmKey_matches_wf, + { root := ``Ix.Kernel.AmbientNat.warmKey_matches_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.whnfCoreConst_noAccel_acceptance, + { root := ``Ix.Kernel.AmbientNat.whnfCoreConst_noAccel_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaIdentityMeaning, + { root := ``Ix.Kernel.AmbientNat.betaIdentityMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaSimulSpec, + { root := ``Ix.Kernel.AmbientNat.betaSimulSpec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.betaSimulMeaning, + { root := ``Ix.Kernel.AmbientNat.betaSimulMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaWalker_eval, + { root := ``Ix.Kernel.AmbientNat.betaWalker_eval, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.betaResultMeaning, + { root := ``Ix.Kernel.AmbientNat.betaResultMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaCoreUncached_eval, + { root := ``Ix.Kernel.AmbientNat.betaCoreUncached_eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.betaCoreUncached_acceptance, + { root := ``Ix.Kernel.AmbientNat.betaCoreUncached_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- zeta reduction: both production zeta branches, including the legacy lifting walk, -- mixed-context semantic lookup, bounded driver, and inhabited fixtures. - { root := ``Ix.Tc.CtxRecon.lctxFindLetVal, + { root := ``Ix.Kernel.CtxRecon.lctxFindLetVal, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TcM.lookupLetVal_eval, + { root := ``Ix.Kernel.TcM.lookupLetVal_eval, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RunAssumptions.lift_whnf_wf, + { root := ``Ix.Kernel.RunAssumptions.lift_whnf_wf, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RunAssumptions.lift_whnf_eval, + { root := ``Ix.Kernel.RunAssumptions.lift_whnf_eval, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.WhnfMeaning.zetaVar, + { root := ``Ix.Kernel.WhnfMeaning.zetaVar, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.WhnfMeaning.zetaFVar, + { root := ``Ix.Kernel.WhnfMeaning.zetaFVar, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_varZeta, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_varZeta, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_fvarZeta, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_fvarZeta, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_nextLeaf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_nextLeaf, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_varZeta, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_varZeta, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_fvarZeta, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_fvarZeta, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_varZeta_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_varZeta_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_fvarZeta_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_fvarZeta_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.bvarZetaLiftSpec, + { root := ``Ix.Kernel.AmbientNat.bvarZetaLiftSpec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.bvarZetaLookupEval, + { root := ``Ix.Kernel.AmbientNat.bvarZetaLookupEval, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.bvarZetaMeaning, + { root := ``Ix.Kernel.AmbientNat.bvarZetaMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.bvarZetaCoreUncachedEval, + { root := ``Ix.Kernel.AmbientNat.bvarZetaCoreUncachedEval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.bvarZetaAcceptance, + { root := ``Ix.Kernel.AmbientNat.bvarZetaAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fvarZetaMeaning, + { root := ``Ix.Kernel.AmbientNat.fvarZetaMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fvarZetaCoreUncachedEval, + { root := ``Ix.Kernel.AmbientNat.fvarZetaCoreUncachedEval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.fvarZetaAcceptance, + { root := ``Ix.Kernel.AmbientNat.fvarZetaAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- projection/iota branch: exact projection/iota branches and bounded-driver composition. -- Semantic success is conditional on an explicit translated-source oracle; -- the two hostile fixtures prove that raw helper success cannot replace it. - { root := ``Ix.Tc.WhnfMeaning.projection, + { root := ``Ix.Kernel.WhnfMeaning.projection, standardAxioms := standard }, - { root := ``Ix.Tc.WhnfMeaning.registeredDefEq, + { root := ``Ix.Kernel.WhnfMeaning.registeredDefEq, standardAxioms := standard }, - { root := ``Ix.Tc.InductiveReductionOracle.projection, - standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.InductiveReductionOracle.iota, + { root := ``Ix.Kernel.InductiveReductionOracle.projection, + standardAxioms := standard, nativeAxioms := levelNative }, + { root := ``Ix.Kernel.InductiveReductionOracle.iota, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_projection, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_projection, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_iota, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_iota, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_projection, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_projection, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_iota, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_iota, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_projection_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_projection_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsUncached_iota_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsUncached_iota_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.projectionReduceEval, + { root := ``Ix.Kernel.AmbientNat.projectionReduceEval, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.projectionCoreEval, + { root := ``Ix.Kernel.AmbientNat.projectionCoreEval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.projectionSource_not_translated, + { root := ``Ix.Kernel.AmbientNat.projectionSource_not_translated, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.projectionAdversarialWitness, + { root := ``Ix.Kernel.AmbientNat.projectionAdversarialWitness, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStateInv, + { root := ``Ix.Kernel.AmbientNat.iotaStateInv, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaTryEval, + { root := ``Ix.Kernel.AmbientNat.iotaTryEval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaCoreEval, + { root := ``Ix.Kernel.AmbientNat.iotaCoreEval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaSource_not_translated, + { root := ``Ix.Kernel.AmbientNat.iotaSource_not_translated, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaAdversarialWitness, + { root := ``Ix.Kernel.AmbientNat.iotaAdversarialWitness, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- structural trace: arbitrary-length structural traces compose exact production -- execution, fixed-world/context invariants, and local Theory meanings. -- The inhabited fixture takes two `.next` steps before its leaf; the -- hostile zero-fuel witness cannot be certified as a successful trace. - { root := ``Ix.Tc.RecM.WhnfCoreTrace.no_zero, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.no_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.eval, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.initialInv, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.initialInv, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.finalInv, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.finalInv, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.meaning, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.meaning, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.uncached_eval, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.uncached_eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.uncached_acceptance, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.uncached_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.AmbientNat.structuralNatLit_type, + { root := ``Ix.Kernel.AmbientNat.structuralNatLit_type, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralWhnfTheory, + { root := ``Ix.Kernel.AmbientNat.structuralWhnfTheory, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopStateInv, + { root := ``Ix.Kernel.AmbientNat.structuralLoopStateInv, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopSourceMeaning, + { root := ``Ix.Kernel.AmbientNat.structuralLoopSourceMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopBetaMeaning, + { root := ``Ix.Kernel.AmbientNat.structuralLoopBetaMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopFVarStep, + { root := ``Ix.Kernel.AmbientNat.structuralLoopFVarStep, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopBetaStep, + { root := ``Ix.Kernel.AmbientNat.structuralLoopBetaStep, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopTrace, + { root := ``Ix.Kernel.AmbientNat.structuralLoopTrace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopAcceptance, + { root := ``Ix.Kernel.AmbientNat.structuralLoopAcceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralLoopZeroFuel, + { root := ``Ix.Kernel.AmbientNat.structuralLoopZeroFuel, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- structural cache: the public structural entry point's keyed body has exact full, @@ -4980,92 +4964,92 @@ private def roots : Array RootAllowance := #[ -- execution-indexed trace and universal provenance before insertion; -- hits require the physical entry, semantic invariant, and executed key -- match. The Nat fixture runs cold-to-warm in both isolated partitions. - { root := ``Ix.Tc.RecM.WhnfCoreNonLeaf.enter, + { root := ``Ix.Kernel.RecM.WhnfCoreNonLeaf.enter, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_varNotLet, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_varNotLet, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_varEnter, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_varEnter, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreKeyedEntry.eval, + { root := ``Ix.Kernel.RecM.WhnfCoreKeyedEntry.eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsNonLeaf_fullHit, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsNonLeaf_fullHit, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsNonLeaf_cheapHit, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsNonLeaf_cheapHit, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsNonLeaf_fullMiss, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsNonLeaf_fullMiss, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsNonLeaf_cheapMiss, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsNonLeaf_cheapMiss, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsNonLeaf_transient, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsNonLeaf_transient, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreCacheUpdate.full_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WhnfCoreCacheUpdate.cheap_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_fullHit_acceptance, + { root := ``Ix.Kernel.RecM.WhnfCoreCacheUpdate.full_whnfStateInv, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WhnfCoreCacheUpdate.cheap_whnfStateInv, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_fullHit_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_cheapHit_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_cheapHit_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_fullMiss_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_fullMiss_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_cheapMiss_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_cheapMiss_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_transient_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_transient_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.AmbientNat.betaArgMeaning, + { root := ``Ix.Kernel.AmbientNat.betaArgMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullCoreProvenance, + { root := ``Ix.Kernel.AmbientNat.fullCoreProvenance, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.cheapCoreProvenance, + { root := ``Ix.Kernel.AmbientNat.cheapCoreProvenance, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.coreCacheFreshStateInv, + { root := ``Ix.Kernel.AmbientNat.coreCacheFreshStateInv, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullCoreWarmStateInv, + { root := ``Ix.Kernel.AmbientNat.fullCoreWarmStateInv, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.bothCoreWarmStateInv, + { root := ``Ix.Kernel.AmbientNat.bothCoreWarmStateInv, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.coreCacheKey_eval, + { root := ``Ix.Kernel.AmbientNat.coreCacheKey_eval, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.coreCacheKey_matches, + { root := ``Ix.Kernel.AmbientNat.coreCacheKey_matches, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaTransientFalse, + { root := ``Ix.Kernel.AmbientNat.betaTransientFalse, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaWalker_eval_state, + { root := ``Ix.Kernel.AmbientNat.betaWalker_eval_state, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaStep_state, + { root := ``Ix.Kernel.AmbientNat.betaStep_state, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.coreCacheTrace, + { root := ``Ix.Kernel.AmbientNat.coreCacheTrace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullCoreColdAcceptance, + { root := ``Ix.Kernel.AmbientNat.fullCoreColdAcceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullCoreWarmAcceptance, + { root := ``Ix.Kernel.AmbientNat.fullCoreWarmAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.cheapCorePolicyMissAcceptance, + { root := ``Ix.Kernel.AmbientNat.cheapCorePolicyMissAcceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.cheapCoreWarmAcceptance, + { root := ``Ix.Kernel.AmbientNat.cheapCoreWarmAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.coreCachePolicyIsolation, + { root := ``Ix.Kernel.AmbientNat.coreCachePolicyIsolation, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, -- outer WHNF driver: no-delta and full-WHNF now have execution-indexed bounded traces, @@ -5073,174 +5057,174 @@ private def roots : Array RootAllowance := #[ -- and semantic hit/miss acceptance. The Nat fixture executes all nested -- cache layers, proves the cold call consumes exactly one fuel unit, and -- proves the warm public call preserves the entire state. - { root := ``Ix.Tc.WhnfStateInv.of_semantic_fields_eq, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.TcM.stepTrace_disabled, + { root := ``Ix.Kernel.WhnfStateInv.of_semantic_fields_eq, + standardAxioms := standard }, + { root := ``Ix.Kernel.TcM.stepTrace_disabled, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TcM.bumpStats_disabled, + { root := ``Ix.Kernel.TcM.bumpStats_disabled, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TcM.tick_success, + { root := ``Ix.Kernel.TcM.tick_success, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.no_zero, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.no_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.eval, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.initialInv, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.initialInv, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.finalInv, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.finalInv, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.meaning, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.meaning, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.uncached_eval, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.uncached_eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.uncached_acceptance, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.uncached_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.no_zero, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.no_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.eval, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.initialInv, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.initialInv, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.finalInv, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.finalInv, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.meaning, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.meaning, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.uncached_eval, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.uncached_eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.uncached_acceptance, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.uncached_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.WhnfDriverNonLeaf.noDelta_enter, + { root := ``Ix.Kernel.RecM.WhnfDriverNonLeaf.noDelta_enter, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfDriverNonLeaf.full_enter, + { root := ``Ix.Kernel.RecM.WhnfDriverNonLeaf.full_enter, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfDriverEntry.noDelta_eval, + { root := ``Ix.Kernel.RecM.WhnfDriverEntry.noDelta_eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfDriverEntry.full_eval, + { root := ``Ix.Kernel.RecM.WhnfDriverEntry.full_eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModePrefix_disabled, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModePrefix_disabled, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeMissCharge_disabled, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeMissCharge_disabled, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_fullHit, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_fullHit, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_cheapHit, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_cheapHit, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_fullMiss, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_fullMiss, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_cheapMiss, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_cheapMiss, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_stuck, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_stuck, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_transient, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_transient, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_nativeNoInsert, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_nativeNoInsert, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfDriverCacheUpdate.noDelta_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WhnfDriverCacheUpdate.noDeltaCheap_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WhnfDriverCacheUpdate.full_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_fullHit_acceptance, + { root := ``Ix.Kernel.RecM.WhnfDriverCacheUpdate.noDelta_whnfStateInv, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WhnfDriverCacheUpdate.noDeltaCheap_whnfStateInv, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WhnfDriverCacheUpdate.full_whnfStateInv, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_fullHit_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_cheapHit_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_cheapHit_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_fullMiss_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_fullMiss_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_cheapMiss_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_cheapMiss_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_stuck_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_stuck_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_transient_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_transient_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeNonLeaf_hit, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeNonLeaf_hit, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeNonLeaf_miss, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeNonLeaf_miss, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeNonLeaf_stuck, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeNonLeaf_stuck, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeNonLeaf_transient, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeNonLeaf_transient, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeNonLeaf_nativeNoInsert, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeNonLeaf_nativeNoInsert, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccMode_hit_acceptance, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccMode_hit_acceptance, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccMode_miss_acceptance, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccMode_miss_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccMode_stuck_acceptance, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccMode_stuck_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccMode_transient_acceptance, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccMode_transient_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnf_public_eq_whnfWithNatSuccMode, + { root := ``Ix.Kernel.RecM.whnf_public_eq_whnfWithNatSuccMode, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.betaNoDeltaStep, + { root := ``Ix.Kernel.AmbientNat.betaNoDeltaStep, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullNoDeltaProvenance, + { root := ``Ix.Kernel.AmbientNat.fullNoDeltaProvenance, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfProvenance, + { root := ``Ix.Kernel.AmbientNat.fullWhnfProvenance, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullNoDeltaWarmStateInv, + { root := ``Ix.Kernel.AmbientNat.fullNoDeltaWarmStateInv, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaTrace, + { root := ``Ix.Kernel.AmbientNat.noDeltaTrace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullNoDeltaColdAcceptance, + { root := ``Ix.Kernel.AmbientNat.fullNoDeltaColdAcceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullNoDeltaWarmAcceptance, + { root := ``Ix.Kernel.AmbientNat.fullNoDeltaWarmAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaCachePolicyIsolation, + { root := ``Ix.Kernel.AmbientNat.noDeltaCachePolicyIsolation, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfChargedStateInv, + { root := ``Ix.Kernel.AmbientNat.fullWhnfChargedStateInv, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfPrefixCold, + { root := ``Ix.Kernel.AmbientNat.fullWhnfPrefixCold, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfMissCharge, + { root := ``Ix.Kernel.AmbientNat.fullWhnfMissCharge, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfCharged_noDeltaHit, + { root := ``Ix.Kernel.AmbientNat.fullWhnfCharged_noDeltaHit, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaFullWhnfStep, + { root := ``Ix.Kernel.AmbientNat.betaFullWhnfStep, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfTrace, + { root := ``Ix.Kernel.AmbientNat.fullWhnfTrace, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfWarmStateInv, + { root := ``Ix.Kernel.AmbientNat.fullWhnfWarmStateInv, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfColdAcceptance, + { root := ``Ix.Kernel.AmbientNat.fullWhnfColdAcceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfWarmAcceptance, + { root := ``Ix.Kernel.AmbientNat.fullWhnfWarmAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfFuelDiscipline, + { root := ``Ix.Kernel.AmbientNat.fullWhnfFuelDiscipline, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfCacheLayering, + { root := ``Ix.Kernel.AmbientNat.fullWhnfCacheLayering, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, -- total-outcome boundary: local step contracts now construct success traces and classify @@ -5248,362 +5232,362 @@ private def roots : Array RootAllowance := #[ -- dispatchers close conditionally over suffix reconciliation, transient -- lookup safety, collision-robust insertion provenance, and the local -- semantic step contracts. Instrumentation and miss charging are proved. - { root := ``Ix.Tc.WhnfPost.transMeaning, + { root := ``Ix.Kernel.WhnfPost.transMeaning, standardAxioms := standard, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.WhnfPost.meaning, + { root := ``Ix.Kernel.WhnfPost.meaning, standardAxioms := standard }, - { root := ``Ix.Tc.TcM.isLetVar_wf, + { root := ``Ix.Kernel.TcM.isLetVar_wf, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TcM.stepTrace_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.TcM.bumpStats_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WF.liftTcM, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WF.get, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WF.modifyGet, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WF.modify, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.complete, - standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfCoreTrace.uncached_wf, + { root := ``Ix.Kernel.TcM.stepTrace_whnf_wf, + standardAxioms := standard }, + { root := ``Ix.Kernel.TcM.bumpStats_whnf_wf, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WF.liftTcM, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WF.get, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WF.modifyGet, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WF.modify, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.complete, + standardAxioms := standard, nativeAxioms := inferNative }, + { root := ``Ix.Kernel.RecM.WhnfCoreTrace.uncached_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.complete, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.complete, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfNoDeltaTrace.uncached_wf, + { root := ``Ix.Kernel.RecM.WhnfNoDeltaTrace.uncached_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.complete, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.complete, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.WhnfFullTrace.uncached_wf, + { root := ``Ix.Kernel.RecM.WhnfFullTrace.uncached_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplNonLeaf_wf, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplNonLeaf_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_nonLeaf_wf, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_nonLeaf_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeNonLeaf_wf, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeNonLeaf_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccMode_nonLeaf_wf, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccMode_nonLeaf_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModePrefix_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccModeMissCharge_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccMode_nonLeaf_semantic_wf, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModePrefix_wf, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccModeMissCharge_wf, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccMode_nonLeaf_semantic_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_wf, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfWithNatSuccMode_wf, + { root := ``Ix.Kernel.RecM.whnfWithNatSuccMode_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDelta_wf, + { root := ``Ix.Kernel.RecM.whnfNoDelta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnf_wf, + { root := ``Ix.Kernel.RecM.whnf_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaZeroFuel, + { root := ``Ix.Kernel.AmbientNat.noDeltaZeroFuel, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fullWhnfZeroFuel, + { root := ``Ix.Kernel.AmbientNat.fullWhnfZeroFuel, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.whnfLoopErrorSeparation, + { root := ``Ix.Kernel.AmbientNat.whnfLoopErrorSeparation, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfPost.refl, + { root := ``Ix.Kernel.WhnfPost.refl, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WF.bind, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.WF.bind, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.runBounded_wf, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.RecM.WhnfLeaf.eval, + { root := ``Ix.Kernel.RecM.runBounded_wf, + standardAxioms := standard }, + { root := ``Ix.Kernel.RecM.WhnfLeaf.eval, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnf_leaf_wf, + { root := ``Ix.Kernel.RecM.whnf_leaf_wf, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnf_leaf_wf_of_theory, + { root := ``Ix.Kernel.RecM.whnf_leaf_wf_of_theory, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.AmbientNat.noAccelStateInv, + { root := ``Ix.Kernel.AmbientNat.noAccelStateInv, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.whnfLeaf_noAccel_wf, + { root := ``Ix.Kernel.AmbientNat.whnfLeaf_noAccel_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.whnfLeaf_noAccel_acceptance, + { root := ``Ix.Kernel.AmbientNat.whnfLeaf_noAccel_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.whnfKey_fst, + { root := ``Ix.Kernel.TcM.whnfKey_fst, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.WhnfContextKeys.Matches.sourceAddr, + { root := ``Ix.Kernel.WhnfContextKeys.Matches.sourceAddr, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.CacheProvenance.whnfMeaningOfMatches, + { root := ``Ix.Kernel.CacheProvenance.whnfMeaningOfMatches, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.CacheInvariant.whnfHitOfMatches, + { root := ``Ix.Kernel.CacheInvariant.whnfHitOfMatches, standardAxioms := standard, nativeAxioms := contextNative }, - { root := ``Ix.Tc.AmbientNat.warmKey_matches, + { root := ``Ix.Kernel.AmbientNat.warmKey_matches, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.methodsN_zero, + { root := ``Ix.Kernel.methodsN_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.methodsN_succ_whnf, + { root := ``Ix.Kernel.methodsN_succ_whnf, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.methodsN_succ_whnfCore, + { root := ``Ix.Kernel.methodsN_succ_whnfCore, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.methodsN_succ_whnfMode, + { root := ``Ix.Kernel.methodsN_succ_whnfMode, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.methodsN_succ_whnfCoreFlags, + { root := ``Ix.Kernel.methodsN_succ_whnfCoreFlags, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.methodsN_succ_infer, + { root := ``Ix.Kernel.methodsN_succ_infer, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.methodsN_succ_isDefEq, + { root := ``Ix.Kernel.methodsN_succ_isDefEq, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.methodsOut_whnf, + { root := ``Ix.Kernel.methodsOut_whnf, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.methodsOut_whnfCore, + { root := ``Ix.Kernel.methodsOut_whnfCore, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.methodsOut_whnfMode, + { root := ``Ix.Kernel.methodsOut_whnfMode, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.methodsOut_whnfCoreFlags, + { root := ``Ix.Kernel.methodsOut_whnfCoreFlags, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.methodsOut_infer, + { root := ``Ix.Kernel.methodsOut_infer, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.methodsOut_isDefEq, + { root := ``Ix.Kernel.methodsOut_isDefEq, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TcM.runRec_apply, + { root := ``Ix.Kernel.TcM.runRec_apply, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.runRec_directInfer_zero, + { root := ``Ix.Kernel.TcM.runRec_directInfer_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.whnf_eq_runRec, + { root := ``Ix.Kernel.TcM.whnf_eq_runRec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.whnfCore_eq_runRec, + { root := ``Ix.Kernel.TcM.whnfCore_eq_runRec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.whnfNoDelta_eq_runRec, + { root := ``Ix.Kernel.TcM.whnfNoDelta_eq_runRec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.infer_eq_runRec, + { root := ``Ix.Kernel.TcM.infer_eq_runRec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.isDefEq_eq_runRec, + { root := ``Ix.Kernel.TcM.isDefEq_eq_runRec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.ensureSort_eq_runRec, + { root := ``Ix.Kernel.TcM.ensureSort_eq_runRec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.TcM.ensureForall_eq_runRec, + { root := ``Ix.Kernel.TcM.ensureForall_eq_runRec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.unfoldConstValue_equation, + { root := ``Ix.Kernel.RecM.unfoldConstValue_equation, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RecM.tryDeltaUnfold_equation, + { root := ``Ix.Kernel.RecM.tryDeltaUnfold_equation, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RecM.deltaUnfoldOne_equation, + { root := ``Ix.Kernel.RecM.deltaUnfoldOne_equation, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RecM.applyIotaArg_false, + { root := ``Ix.Kernel.RecM.applyIotaArg_false, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.applyIotaArg_true_lam, + { root := ``Ix.Kernel.RecM.applyIotaArg_true_lam, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.isNatLiteralRecursorApp_equation, + { root := ``Ix.Kernel.RecM.isNatLiteralRecursorApp_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isTransientNatLiteralWork_equation, + { root := ``Ix.Kernel.RecM.isTransientNatLiteralWork_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.cleanupNatOffsetMajor_equation, + { root := ``Ix.Kernel.RecM.cleanupNatOffsetMajor_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.projectDecidableFinValMinor_equation, + { root := ``Ix.Kernel.RecM.projectDecidableFinValMinor_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryReduceFinValDecidableRec_equation, + { root := ``Ix.Kernel.RecM.tryReduceFinValDecidableRec_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryReduceProjectionDefinition_equation, + { root := ``Ix.Kernel.RecM.tryReduceProjectionDefinition_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.natRecLiteralParts_equation, + { root := ``Ix.Kernel.RecM.natRecLiteralParts_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isNatStuckRecursorAddr_equation, + { root := ``Ix.Kernel.RecM.isNatStuckRecursorAddr_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isStuckNatPredicateProbe_equation, + { root := ``Ix.Kernel.RecM.isStuckNatPredicateProbe_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.bitvecOfNatArgs_equation, + { root := ``Ix.Kernel.RecM.bitvecOfNatArgs_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.charOfNatExpr_equation, + { root := ``Ix.Kernel.RecM.charOfNatExpr_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryReduceString_equation, + { root := ``Ix.Kernel.RecM.tryReduceString_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.discoverBlockInductives_equation, + { root := ``Ix.Kernel.RecM.discoverBlockInductives_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.runBounded_zero, + { root := ``Ix.Kernel.RecM.runBounded_zero, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.runBounded_succ, + { root := ``Ix.Kernel.RecM.runBounded_succ, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.consumeBetaLams_equation, + { root := ``Ix.Kernel.RecM.consumeBetaLams_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.consumeBetaLamsFuel_zero, + { root := ``Ix.Kernel.RecM.consumeBetaLamsFuel_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.consumeBetaLamsFuel_succ, + { root := ``Ix.Kernel.RecM.consumeBetaLamsFuel_succ, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.compareRank_equation, + { root := ``Ix.Kernel.RecM.compareRank_equation, standardAxioms := propextOnly }, - { root := ``Ix.Tc.RecM.isNatLike_equation, + { root := ``Ix.Kernel.RecM.isNatLike_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isNatZero_equation, + { root := ``Ix.Kernel.RecM.isNatZero_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.natSuccOf_equation, + { root := ``Ix.Kernel.RecM.natSuccOf_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.isBoolTrue_equation, + { root := ``Ix.Kernel.RecM.isBoolTrue_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isDelta_equation, + { root := ``Ix.Kernel.RecM.isDelta_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isRegular_equation, + { root := ``Ix.Kernel.RecM.isRegular_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.defRankId_equation, + { root := ``Ix.Kernel.RecM.defRankId_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.infer_eq_inferWith, + { root := ``Ix.Kernel.RecM.infer_eq_inferWith, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.inferCall_run, + { root := ``Ix.Kernel.RecM.inferCall_run, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.inferOnlyCall_run, + { root := ``Ix.Kernel.RecM.inferOnlyCall_run, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isDefEqCall_run, + { root := ``Ix.Kernel.RecM.isDefEqCall_run, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.whnfRec_run, + { root := ``Ix.Kernel.RecM.whnfRec_run, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.whnfModeRec_run, + { root := ``Ix.Kernel.RecM.whnfModeRec_run, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.whnfCoreFlagsRec_run, + { root := ``Ix.Kernel.RecM.whnfCoreFlagsRec_run, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.whnf_eq_whnfWithNatSuccMode, + { root := ``Ix.Kernel.RecM.whnf_eq_whnfWithNatSuccMode, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCore_eq_whnfCoreWithFlags, + { root := ``Ix.Kernel.RecM.whnfCore_eq_whnfCoreWithFlags, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDelta_eq_whnfNoDeltaImpl, + { root := ``Ix.Kernel.RecM.whnfNoDelta_eq_whnfNoDeltaImpl, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.ensureSortDirect_equation, + { root := ``Ix.Kernel.RecM.ensureSortDirect_equation, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.ensureForallDirect_equation, + { root := ``Ix.Kernel.RecM.ensureForallDirect_equation, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.peelProjForall_equation, + { root := ``Ix.Kernel.RecM.peelProjForall_equation, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.checkNoUnsafeRefs_equation, + { root := ``Ix.Kernel.RecM.checkNoUnsafeRefs_equation, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.checkNoUnsafeRefs_go_nil, + { root := ``Ix.Kernel.RecM.checkNoUnsafeRefs_go_nil, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.checkNoUnsafeRefs_go_app, + { root := ``Ix.Kernel.RecM.checkNoUnsafeRefs_go_app, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.validateUnivParamsSeen_equation, + { root := ``Ix.Kernel.RecM.validateUnivParamsSeen_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.validateUnivParamsSeen_go_nil, + { root := ``Ix.Kernel.RecM.validateUnivParamsSeen_go_nil, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.validateUnivParamsSeen_go_max, + { root := ``Ix.Kernel.RecM.validateUnivParamsSeen_go_max, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.validateExprWellScoped_equation, + { root := ``Ix.Kernel.RecM.validateExprWellScoped_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.validateExprWellScoped_go_nil, + { root := ``Ix.Kernel.RecM.validateExprWellScoped_go_nil, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.validateExprWellScoped_go_app, + { root := ``Ix.Kernel.RecM.validateExprWellScoped_go_app, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.peelRuleIhForalls_equation, + { root := ``Ix.Kernel.RecM.peelRuleIhForalls_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.checkPositivityDomain_equation, + { root := ``Ix.Kernel.RecM.checkPositivityDomain_equation, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.checkPositivityDomainFuel_zero, + { root := ``Ix.Kernel.RecM.checkPositivityDomainFuel_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.checkNestedCtorFieldsFuel_zero, + { root := ``Ix.Kernel.RecM.checkNestedCtorFieldsFuel_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.checkNestedCtorFieldsLoopFuel_zero, + { root := ``Ix.Kernel.RecM.checkNestedCtorFieldsLoopFuel_zero, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.countForalls_equation, + { root := ``Ix.Kernel.RecM.countForalls_equation, standardAxioms := standard, nativeAxioms := inferNative }, -- The complete checker dispatch is transparent now; these roots pin its -- exact production trust boundary in addition to the local equations. - { root := ``Ix.Tc.RecM.checkInductive, + { root := ``Ix.Kernel.RecM.checkInductive, standardAxioms := standard, nativeAxioms := inductiveNative }, - { root := ``Ix.Tc.RecM.checkRecursorMemberImpl, + { root := ``Ix.Kernel.RecM.checkRecursorMemberImpl, standardAxioms := standard, nativeAxioms := inductiveNative }, - { root := ``Ix.Tc.RecM.checkConst, + { root := ``Ix.Kernel.RecM.checkConst, standardAxioms := standard, nativeAxioms := inductiveNative }, - { root := ``Ix.Tc.TcM.checkConst, + { root := ``Ix.Kernel.TcM.checkConst, standardAxioms := standard, nativeAxioms := inductiveNative }, - { root := ``Ix.Tc.extractNatValue_app_const_equation, + { root := ``Ix.Kernel.extractNatValue_app_const_equation, standardAxioms := propextOnly }, - { root := ``Ix.Tc.extractNatValue_nat_equation, + { root := ``Ix.Kernel.extractNatValue_nat_equation, standardAxioms := propextOnly }, - { root := ``Ix.Tc.projectionDefinitionInfo_go_equation, + { root := ``Ix.Kernel.projectionDefinitionInfo_go_equation, standardAxioms := propextOnly }, - { root := ``Ix.Tc.EquivManager.find_equation, + { root := ``Ix.Kernel.EquivManager.find_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.EquivManager.find_go_zero }, - { root := ``Ix.Tc.EquivManager.find_go_succ }, - { root := ``Ix.Tc.LocalContext.truncate_equation, + { root := ``Ix.Kernel.EquivManager.find_go_zero }, + { root := ``Ix.Kernel.EquivManager.find_go_succ }, + { root := ``Ix.Kernel.LocalContext.truncate_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.LocalContext.truncate_go_zero, + { root := ``Ix.Kernel.LocalContext.truncate_go_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.LocalContext.truncate_go_succ, + { root := ``Ix.Kernel.LocalContext.truncate_go_succ, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TcM.restoreDepth_apply, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.TcM.restoreDepth_go_zero, - standardAxioms := standard, nativeAxioms := blake3Native }, - { root := ``Ix.Tc.TcM.ctxSuffixNeed_zero, + { root := ``Ix.Kernel.TcM.restoreDepth_apply, + standardAxioms := standard }, + { root := ``Ix.Kernel.TcM.restoreDepth_go_zero, + standardAxioms := standard }, + { root := ``Ix.Kernel.TcM.ctxSuffixNeed_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TcM.ctxSuffixNeed_succ, + { root := ``Ix.Kernel.TcM.ctxSuffixNeed_succ, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TcM.ctxSuffixNeed_of_fixed, + { root := ``Ix.Kernel.TcM.ctxSuffixNeed_of_fixed, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.KExpr.render_equation, + { root := ``Ix.Kernel.KExpr.render_equation, standardAxioms := standard }, - { root := ``Ix.Tc.KExpr.renderFuel_zero, + { root := ``Ix.Kernel.KExpr.renderFuel_zero, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.natOffset_equation, + { root := ``Ix.Kernel.RecM.natOffset_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.natOffsetOrZero_equation, + { root := ``Ix.Kernel.RecM.natOffsetOrZero_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.evalNatOffsetLiteral_equation, + { root := ``Ix.Kernel.RecM.evalNatOffsetLiteral_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.natOffsetFuel_zero, + { root := ``Ix.Kernel.RecM.natOffsetFuel_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.evalNatOffsetLiteralFuel_zero, + { root := ``Ix.Kernel.RecM.evalNatOffsetLiteralFuel_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryEvalNatValueForPred_equation, + { root := ``Ix.Kernel.RecM.tryEvalNatValueForPred_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryEvalNatValueForPredFuel_zero, + { root := ``Ix.Kernel.RecM.tryEvalNatValueForPredFuel_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.compareKUniv_succ_equation, + { root := ``Ix.Kernel.compareKUniv_succ_equation, standardAxioms := propextOnly }, - { root := ``Ix.Tc.compareKUniv_max_equation, + { root := ``Ix.Kernel.compareKUniv_max_equation, standardAxioms := propextOnly }, - { root := ``Ix.Tc.mergeSorted_equation, + { root := ``Ix.Kernel.mergeSorted_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.mergeSorted_go_zero, + { root := ``Ix.Kernel.mergeSorted_go_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.sortByCompare_equation, + { root := ``Ix.Kernel.sortByCompare_equation, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.sortByCompareFuel_zero, + { root := ``Ix.Kernel.sortByCompareFuel_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.sortKConstsRefineFuel_zero, + { root := ``Ix.Kernel.sortKConstsRefineFuel_zero, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.KExpr.treeSize_pos, + { root := ``Ix.Kernel.KExpr.treeSize_pos, standardAxioms := propextOnly }, - { root := ``Ix.Tc.exprMentionsAddr_equation, + { root := ``Ix.Kernel.exprMentionsAddr_equation, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.exprMentionsAddr_go_nil, + { root := ``Ix.Kernel.exprMentionsAddr_go_nil, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.exprMentionsAddr_go_app, + { root := ``Ix.Kernel.exprMentionsAddr_go_app, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.exprMentionsAddr_go_const, + { root := ``Ix.Kernel.exprMentionsAddr_go_const, standardAxioms := standardWithoutChoice }, -- RuntimeContracts: the repaired step source includes finite support plus an actual @@ -5611,77 +5595,77 @@ private def roots : Array RootAllowance := #[ -- collision-robust write validity. The transient Nat probe is proved -- state-pure for eager states. General lazy execution is reduced to the -- exact invariant contract of the driver-installed environment hook. - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_leaf_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_leaf_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_betaOne_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_betaOne_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_projection_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_projection_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_iota_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_iota_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RunAssumptions.subst_whnf_wf, + { root := ``Ix.Kernel.RunAssumptions.subst_whnf_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RunAssumptions.subst_whnf_eval, + { root := ``Ix.Kernel.RunAssumptions.subst_whnf_eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_letE, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_letE, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_letE_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_letE_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- regular-binder fallback: both translated regular-binder forms take the state-pure `.done` -- fallback and cannot be confused with their let-bound zeta siblings. - { root := ``Ix.Tc.TcM.lookupLetVal_none_state, + { root := ``Ix.Kernel.TcM.lookupLetVal_none_state, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_varDone, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_varDone, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_fvarDone, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_fvarDone, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_varDone_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_varDone_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_fvarDone_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_fvarDone_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.bvarStuckAcceptance, + { root := ``Ix.Kernel.AmbientNat.bvarStuckAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.fvarStuckAcceptance, + { root := ``Ix.Kernel.AmbientNat.fvarStuckAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- stuck-reduction fallback: projection misses and unchanged non-lambda application heads keep -- their original syntax, distinguish helper errors from `none`, and are -- inhabited by translated projection and constructor-application fixtures. - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_projectionDone, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_projectionDone, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_projectionWhnfError, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_projectionWhnfError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_projectionReduceError, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_projectionReduceError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appUnchangedDone, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appUnchangedDone, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appHeadError, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appHeadError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appUnchangedIotaError, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appUnchangedIotaError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_projectionDone_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_projectionDone_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appUnchangedDone_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appUnchangedDone_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.appStuckAcceptance, + { root := ``Ix.Kernel.AmbientNat.appStuckAcceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.ProjectionFallback.acceptance, + { root := ``Ix.Kernel.AmbientNat.ProjectionFallback.acceptance, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, @@ -5690,691 +5674,691 @@ private def roots : Array RootAllowance := #[ -- intern-only framing; general multi-beta and changed-head hit/miss/error -- equations consume that helper boundary. The Nat fixtures make argument -- reversal, a trailing argument, and physically changed heads observable. - { root := ``Ix.Tc.InternUpdateFrame.refl, + { root := ``Ix.Kernel.InternUpdateFrame.refl, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.InternUpdateFrame.trans, + { root := ``Ix.Kernel.InternUpdateFrame.trans, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RunAssumptions.internExpr_whnf_eval, + { root := ``Ix.Kernel.RunAssumptions.internExpr_whnf_eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishAppResult_eq_foldlM, + { root := ``Ix.Kernel.RecM.finishAppResult_eq_foldlM, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.finishAppResult_one, + { root := ``Ix.Kernel.RecM.finishAppResult_one, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.FinishAppRequests.result_eq_foldl, + { root := ``Ix.Kernel.RecM.FinishAppRequests.result_eq_foldl, standardAxioms := standardWithoutQuot, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.FinishAppRequests.support, + { root := ``Ix.Kernel.RecM.FinishAppRequests.support, standardAxioms := standard, nativeAxioms := levelNative }, - { root := ``Ix.Tc.RecM.FinishAppRequests.foldlM_eval, + { root := ``Ix.Kernel.RecM.FinishAppRequests.foldlM_eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.FinishAppRequests.eval, + { root := ``Ix.Kernel.RecM.FinishAppRequests.eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.FinishAppRequests.final_eq_spec, + { root := ``Ix.Kernel.RecM.FinishAppRequests.final_eq_spec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_betaMany, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_betaMany, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appChangedIota, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appChangedIota, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appChangedDone, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appChangedDone, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appChangedIotaError, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appChangedIotaError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_betaMany_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_betaMany_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appChangedDone_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appChangedDone_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appChangedIota_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appChangedIota_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appChangedIotaError_acceptance, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appChangedIotaError_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiBetaStep, + { root := ``Ix.Kernel.AmbientNat.multiBetaStep, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.changedHeadInternSpec, + { root := ``Ix.Kernel.AmbientNat.changedHeadInternSpec, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.changedHeadStep, + { root := ``Ix.Kernel.AmbientNat.changedHeadStep, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.WhnfKey.closed_represents, + { root := ``Ix.Kernel.RecM.WhnfKey.closed_represents, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.WhnfCacheWriteOracle.closed, + { root := ``Ix.Kernel.RecM.WhnfCacheWriteOracle.closed, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.tryGetConst_noLazy, + { root := ``Ix.Kernel.TcM.tryGetConst_noLazy, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TcM.lazyIngressAddr_wf, + { root := ``Ix.Kernel.TcM.lazyIngressAddr_wf, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.TcM.tryGetConst_wf, + { root := ``Ix.Kernel.TcM.tryGetConst_wf, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.KId.anon_eq_of_addr_eq }, - { root := ``Ix.Tc.TcM.tryGetConst_success_loaded, + { root := ``Ix.Kernel.KId.anon_eq_of_addr_eq }, + { root := ``Ix.Kernel.TcM.tryGetConst_success_loaded, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.NatRecLiteralPartsSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.NatRecLiteralPartsSuccessTrace.eval, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.NatRecLiteralPartsSuccessTrace.complete, + { root := ``Ix.Kernel.RecM.NatRecLiteralPartsSuccessTrace.complete, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.NatRecLiteralPartsSuccessTrace.trusted, + { root := ``Ix.Kernel.RecM.NatRecLiteralPartsSuccessTrace.trusted, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrustedNatRecLiteralParts.patternAt, + { root := ``Ix.Kernel.RecM.TrustedNatRecLiteralParts.patternAt, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.HeadConstN.matches_varN }, - { root := ``Ix.Tc.HeadConstN.natLit_zero }, - { root := ``Ix.Tc.HeadConstN.natLit_succ }, - { root := ``Ix.Tc.RecursorIotaPattern.matches_of_shapes }, - { root := ``Ix.Tc.RecursorIotaPattern.exists_matches_iff_shapes }, - { root := ``Ix.Tc.RecursorIotaPattern.matches_natZero }, - { root := ``Ix.Tc.RecursorIotaPattern.matches_natSucc }, - { root := ``Ix.Tc.NatRecIotaCase.major_shape }, - { root := ``Ix.Tc.RecursorRulePattern.matches_natLiteral }, - { root := ``Ix.Tc.RecM.TrAppSpine.headConstN, + { root := ``Ix.Kernel.HeadConstN.matches_varN }, + { root := ``Ix.Kernel.HeadConstN.natLit_zero }, + { root := ``Ix.Kernel.HeadConstN.natLit_succ }, + { root := ``Ix.Kernel.RecursorIotaPattern.matches_of_shapes }, + { root := ``Ix.Kernel.RecursorIotaPattern.exists_matches_iff_shapes }, + { root := ``Ix.Kernel.RecursorIotaPattern.matches_natZero }, + { root := ``Ix.Kernel.RecursorIotaPattern.matches_natSucc }, + { root := ``Ix.Kernel.NatRecIotaCase.major_shape }, + { root := ``Ix.Kernel.RecursorRulePattern.matches_natLiteral }, + { root := ``Ix.Kernel.RecM.TrAppSpine.headConstN, standardAxioms := standard }, - { root := ``Ix.Tc.RecM.TrAppSpine.matches_natRecRulePrefix, + { root := ``Ix.Kernel.RecM.TrAppSpine.matches_natRecRulePrefix, standardAxioms := standard }, - { root := ``Ix.Tc.RawRecursorRulePatternRel.matches_natLiteralPrefix, + { root := ``Ix.Kernel.RawRecursorRulePatternRel.matches_natLiteralPrefix, standardAxioms := standard }, - { root := ``Ix.Tc.AmbientNat.linearRecTheoryPrefix_shape }, - { root := ``Ix.Tc.AmbientNat.linearRecZeroPatternMatch }, - { root := ``Ix.Tc.AmbientNat.linearRecSuccPatternMatch }, - { root := ``Ix.Tc.TrustedNatRecursorLayout.caseForMajor, + { root := ``Ix.Kernel.AmbientNat.linearRecTheoryPrefix_shape }, + { root := ``Ix.Kernel.AmbientNat.linearRecZeroPatternMatch }, + { root := ``Ix.Kernel.AmbientNat.linearRecSuccPatternMatch }, + { root := ``Ix.Kernel.TrustedNatRecursorLayout.caseForMajor, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSuffix.tr, + { root := ``Ix.Kernel.RecM.TrAppSuffix.tr, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.splitAt, + { root := ``Ix.Kernel.RecM.TrAppSpine.splitAt, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatRecLiteralPartsDescriptor.patternMajor, + { root := ``Ix.Kernel.RecM.NatRecLiteralPartsDescriptor.patternMajor, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatRecLiteralPartsDescriptor.translatedSplit, + { root := ``Ix.Kernel.RecM.NatRecLiteralPartsDescriptor.translatedSplit, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrustedNatRecLiteralParts.translatedCase, + { root := ``Ix.Kernel.RecM.TrustedNatRecLiteralParts.translatedCase, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSuffix.startHasType, + { root := ``Ix.Kernel.RecM.TrAppSuffix.startHasType, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSuffix.rebase, + { root := ``Ix.Kernel.RecM.TrAppSuffix.rebase, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RawRecursorRulePatternRel.checkedReduction, + { root := ``Ix.Kernel.RawRecursorRulePatternRel.checkedReduction, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatRecLiteralTranslationSplit.checkedRhsSuffix, + { root := ``Ix.Kernel.RecM.NatRecLiteralTranslationSplit.checkedRhsSuffix, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RegisteredRecursorRuleRhsRel.rhsRaw, + { root := ``Ix.Kernel.RegisteredRecursorRuleRhsRel.rhsRaw, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RegisteredRecursorRuleRhsRel.rhsStructural, + { root := ``Ix.Kernel.RegisteredRecursorRuleRhsRel.rhsStructural, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RegisteredRecursorRuleRhsRel.instUnivSpec, + { root := ``Ix.Kernel.RegisteredRecursorRuleRhsRel.instUnivSpec, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RegisteredRecursorRuleRhsRel.instantiateUnivParams_nonempty, + ``Ix.Kernel.RegisteredRecursorRuleRhsRel.instantiateUnivParams_nonempty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RawRecursorRuleRel.registeredRhsTyped, + { root := ``Ix.Kernel.RawRecursorRuleRel.registeredRhsTyped, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSuffix.rebaseQuot, + { root := ``Ix.Kernel.RecM.TrAppSuffix.rebaseQuot, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.NatRecLiteralTranslationSplit.checkedRhsSuffixQuot, + ``Ix.Kernel.RecM.NatRecLiteralTranslationSplit.checkedRhsSuffixQuot, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KExpr.Constructed.liftNoIntern_eq_liftSpec, + { root := ``Ix.Kernel.KExpr.Constructed.liftNoIntern_eq_liftSpec, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KExpr.Constructed.substNoIntern_eq_substSpec, + { root := ``Ix.Kernel.KExpr.Constructed.substNoIntern_eq_substSpec, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArg_true_lam_spec, + { root := ``Ix.Kernel.RecM.applyIotaArg_true_lam_spec, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArg_true_lam_run, + { root := ``Ix.Kernel.RecM.applyIotaArg_true_lam_run, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.betaNoIntern, + { root := ``Ix.Kernel.WhnfMeaning.betaNoIntern, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaIotaArgRun, + { root := ``Ix.Kernel.AmbientNat.betaIotaArgRun, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.betaNoInternMeaning, + { root := ``Ix.Kernel.AmbientNat.betaNoInternMeaning, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.IotaArgNonLambda.applyIotaArg_true, + { root := ``Ix.Kernel.IotaArgNonLambda.applyIotaArg_true, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.IotaArgNonLambda.applyIotaArg_true_run, + { root := ``Ix.Kernel.IotaArgNonLambda.applyIotaArg_true_run, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.appRebuild, + { root := ``Ix.Kernel.WhnfMeaning.appRebuild, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArg_true_nonlam_semantic, + { root := ``Ix.Kernel.RecM.applyIotaArg_true_nonlam_semantic, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArg_false_eval, + { root := ``Ix.Kernel.RecM.applyIotaArg_false_eval, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArg_false_semantic, + { root := ``Ix.Kernel.RecM.applyIotaArg_false_semantic, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.appStuckIotaTransient, + { root := ``Ix.Kernel.AmbientNat.appStuckIotaTransient, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.appStuckIotaInterned, + { root := ``Ix.Kernel.AmbientNat.appStuckIotaInterned, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.resultQuot, + { root := ``Ix.Kernel.WhnfMeaning.resultQuot, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.ofStructuralQuot, + { root := ``Ix.Kernel.WhnfMeaning.ofStructuralQuot, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KExpr.substNoIntern_of_lbr_le, + { root := ``Ix.Kernel.KExpr.substNoIntern_of_lbr_le, standardAxioms := standardWithoutQuot, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KExpr.liftNoIntern_of_lbr_le, + { root := ``Ix.Kernel.KExpr.liftNoIntern_of_lbr_le, standardAxioms := standardWithoutQuot, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArgs_eq_foldlM, + { root := ``Ix.Kernel.RecM.applyIotaArgs_eq_foldlM, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.singleton, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.singleton, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.append, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.append, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.three, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.three, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaArgsTrace.transientNonLambdaSingleton, + ``Ix.Kernel.RecM.ApplyIotaArgsTrace.transientNonLambdaSingleton, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaArgsTrace.transientNonLambdaSingletonQuot, + ``Ix.Kernel.RecM.ApplyIotaArgsTrace.transientNonLambdaSingletonQuot, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.internedSingleton, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.internedSingleton, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.transientLambdaSingleton, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.transientLambdaSingleton, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.transientLambdaSingletonQuot, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.transientLambdaSingletonQuot, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.evalList, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.evalList, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.evalArray, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.evalArray, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.sourceTr, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.sourceTr, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.finalQuot, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.finalQuot, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.finalInv, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.finalInv, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.frame, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.frame, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.finalSupport, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.finalSupport, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.acceptance, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.acceptance, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.evalThreeArrays, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.evalThreeArrays, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.threeArrayAcceptance, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.threeArrayAcceptance, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.ofQuot, + { root := ``Ix.Kernel.WhnfMeaning.ofQuot, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.sourceQuot, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.sourceQuot, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.acceptanceQuot, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.acceptanceQuot, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaArgsTrace.threeArrayAcceptanceQuot, + { root := ``Ix.Kernel.RecM.ApplyIotaArgsTrace.threeArrayAcceptanceQuot, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.instantiateUnivParams_whnf_of_run, + { root := ``Ix.Kernel.TcM.instantiateUnivParams_whnf_of_run, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaRuleTrace.eval, + { root := ``Ix.Kernel.RecM.ApplyIotaRuleTrace.eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaRuleTrace.emptyInstantiation, + { root := ``Ix.Kernel.RecM.ApplyIotaRuleTrace.emptyInstantiation, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaRuleTrace.instantiatePost, + { root := ``Ix.Kernel.RecM.ApplyIotaRuleTrace.instantiatePost, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaRuleTrace.acceptance, + { root := ``Ix.Kernel.RecM.ApplyIotaRuleTrace.acceptance, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaRuleTrace.acceptance_empty, + { root := ``Ix.Kernel.RecM.ApplyIotaRuleTrace.acceptance_empty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaRuleTrace.registeredStartQuot_empty, + ``Ix.Kernel.RecM.ApplyIotaRuleTrace.registeredStartQuot_empty, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaRuleTrace.registeredAcceptance_empty, + ``Ix.Kernel.RecM.ApplyIotaRuleTrace.registeredAcceptance_empty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaRuleTrace.registeredStartQuot_nonempty, + ``Ix.Kernel.RecM.ApplyIotaRuleTrace.registeredStartQuot_nonempty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaRuleTrace.registeredAcceptance_nonempty, + ``Ix.Kernel.RecM.ApplyIotaRuleTrace.registeredAcceptance_nonempty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaRuleTrace.checkedMeaning, + { root := ``Ix.Kernel.RecM.ApplyIotaRuleTrace.checkedMeaning, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaRuleTrace.checkedAcceptance_empty, + ``Ix.Kernel.RecM.ApplyIotaRuleTrace.checkedAcceptance_empty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.ApplyIotaRuleTrace.checkedAcceptance_nonempty, + ``Ix.Kernel.RecM.ApplyIotaRuleTrace.checkedAcceptance_nonempty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KConst.recursorMajorIdx_of_iotaInfo, + { root := ``Ix.Kernel.KConst.recursorMajorIdx_of_iotaInfo, standardAxioms := propextOnly, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KConst.recursorRuleAt_of_iotaInfo, + { root := ``Ix.Kernel.KConst.recursorRuleAt_of_iotaInfo, standardAxioms := propextOnly, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryApplyIotaCtorSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.TryApplyIotaCtorSuccessTrace.eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaCtorTrace.operational, + { root := ``Ix.Kernel.RecM.ApplyIotaCtorTrace.operational, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaCtorTrace.eval, + { root := ``Ix.Kernel.RecM.ApplyIotaCtorTrace.eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaCtorTrace.recursorRuleAt, + { root := ``Ix.Kernel.RecM.ApplyIotaCtorTrace.recursorRuleAt, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaCtorTrace.acceptance_empty, + { root := ``Ix.Kernel.RecM.ApplyIotaCtorTrace.acceptance_empty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaCtorTrace.checkedAcceptance_empty, + { root := ``Ix.Kernel.RecM.ApplyIotaCtorTrace.checkedAcceptance_empty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ApplyIotaCtorTrace.checkedAcceptance_nonempty, + { root := ``Ix.Kernel.RecM.ApplyIotaCtorTrace.checkedAcceptance_nonempty, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaCtorOrStructEta_regular, + { root := ``Ix.Kernel.RecM.tryIotaCtorOrStructEta_regular, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaAfterMajorWhnf_regular, + { root := ``Ix.Kernel.RecM.tryIotaAfterMajorWhnf_regular, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_nonKPrefix, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_nonKPrefix, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_regularCtor, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_regularCtor, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryIotaWithFlags_regularCtor_checkedAcceptance_empty, + ``Ix.Kernel.RecM.tryIotaWithFlags_regularCtor_checkedAcceptance_empty, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natToConstructor_zero, + { root := ``Ix.Kernel.RecM.natToConstructor_zero, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natToConstructor_succ, + { root := ``Ix.Kernel.RecM.natToConstructor_succ, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaAfterMajorWhnf_nat, + { root := ``Ix.Kernel.RecM.tryIotaAfterMajorWhnf_nat, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_natCtor, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_natCtor, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryIotaWithFlags_natCtor_checkedAcceptance_empty, + ``Ix.Kernel.RecM.tryIotaWithFlags_natCtor_checkedAcceptance_empty, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.intern_success_frame, + { root := ``Ix.Kernel.RecM.intern_success_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.strLitListToConstructor_empty, + { root := ``Ix.Kernel.RecM.strLitListToConstructor_empty, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.strLitListToConstructor_success_frame, + { root := ``Ix.Kernel.RecM.strLitListToConstructor_success_frame, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.strLitToConstructor_success_frame, + { root := ``Ix.Kernel.RecM.strLitToConstructor_success_frame, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.evalNatOffsetLiteral_str, + { root := ``Ix.Kernel.RecM.evalNatOffsetLiteral_str, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natOffset_str, + { root := ``Ix.Kernel.RecM.natOffset_str, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.cleanupNatOffsetMajor_str, + { root := ``Ix.Kernel.RecM.cleanupNatOffsetMajor_str, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaAfterMajorWhnf_str, + { root := ``Ix.Kernel.RecM.tryIotaAfterMajorWhnf_str, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_strCtor, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_strCtor, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryIotaWithFlags_strCtor_checkedAcceptance_empty, + ``Ix.Kernel.RecM.tryIotaWithFlags_strCtor_checkedAcceptance_empty, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringEmptyFold, + { root := ``Ix.Kernel.AmbientNat.iotaStringEmptyFold, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringExpand, + { root := ``Ix.Kernel.AmbientNat.iotaStringExpand, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringCallback, + { root := ``Ix.Kernel.AmbientNat.iotaStringCallback, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringCleanup, + { root := ``Ix.Kernel.AmbientNat.iotaStringCleanup, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringGetZeroOfFrame, + { root := ``Ix.Kernel.AmbientNat.iotaStringGetZeroOfFrame, standardAxioms := standard, nativeAxioms := canonicalPrimitivesNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringApplyRule, + { root := ``Ix.Kernel.AmbientNat.iotaStringApplyRule, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringApplyCtor, + { root := ``Ix.Kernel.AmbientNat.iotaStringApplyCtor, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaStringAfterEval, + { root := ``Ix.Kernel.AmbientNat.iotaStringAfterEval, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, -- ConstructorSynthesis: the positive K-like recursor branch. Optional probes retain -- error-side state, candidate synthesis records the DefEq gate and counter -- order, and the inhabited fixture reaches the real bounded WHNF driver. - { root := ``Ix.Tc.RecM.tryOptional_success, + { root := ``Ix.Kernel.RecM.tryOptional_success, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryOptional_error, + { root := ``Ix.Kernel.RecM.tryOptional_error, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.VerifyKSynthCandidateSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.VerifyKSynthCandidateSuccessTrace.eval, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.VerifyKSynthCandidateRejectTrace.eval, + { root := ``Ix.Kernel.RecM.VerifyKSynthCandidateRejectTrace.eval, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSuccessTrace.eval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_kPrefix, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_kPrefix, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_kFallback, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_kFallback, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_kCtor, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_kCtor, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryIotaWithFlags_kCtor_checkedAcceptance_empty, + ``Ix.Kernel.RecM.tryIotaWithFlags_kCtor_checkedAcceptance_empty, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaIntern, + { root := ``Ix.Kernel.AmbientNat.kIotaIntern, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaMajorInfer, + { root := ``Ix.Kernel.AmbientNat.kIotaMajorInfer, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaMajorWhnf, + { root := ``Ix.Kernel.AmbientNat.kIotaMajorWhnf, standardAxioms := standard, nativeAxioms := canonicalPrimitivesNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaGetRec, + { root := ``Ix.Kernel.AmbientNat.kIotaGetRec, standardAxioms := standard, nativeAxioms := canonicalPrimitivesNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaGetNat, + { root := ``Ix.Kernel.AmbientNat.kIotaGetNat, standardAxioms := standard, nativeAxioms := canonicalPrimitivesNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaMajorInductive, + { root := ``Ix.Kernel.AmbientNat.kIotaMajorInductive, standardAxioms := standard, nativeAxioms := canonicalPrimitivesContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaCtorInfer, + { root := ``Ix.Kernel.AmbientNat.kIotaCtorInfer, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaAttemptStats, + { root := ``Ix.Kernel.AmbientNat.kIotaAttemptStats, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaTypeDefEq, + { root := ``Ix.Kernel.AmbientNat.kIotaTypeDefEq, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaCandidate, + { root := ``Ix.Kernel.AmbientNat.kIotaCandidate, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaSynth, + { root := ``Ix.Kernel.AmbientNat.kIotaSynth, standardAxioms := standard, nativeAxioms := inferNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaInternFrame, + { root := ``Ix.Kernel.AmbientNat.kIotaInternFrame, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaSynthCleanup, + { root := ``Ix.Kernel.AmbientNat.kIotaSynthCleanup, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaSynthWhnf, + { root := ``Ix.Kernel.AmbientNat.kIotaSynthWhnf, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaGetZeroAfter, + { root := ``Ix.Kernel.AmbientNat.kIotaGetZeroAfter, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaApplyRule, + { root := ``Ix.Kernel.AmbientNat.kIotaApplyRule, standardAxioms := standard, nativeAxioms := nameNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaApplyCtor, + { root := ``Ix.Kernel.AmbientNat.kIotaApplyCtor, standardAxioms := standard, nativeAxioms := nameNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaTryEval, + { root := ``Ix.Kernel.AmbientNat.kIotaTryEval, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaStepEval, + { root := ``Ix.Kernel.AmbientNat.kIotaStepEval, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kIotaCoreEval, + { root := ``Ix.Kernel.AmbientNat.kIotaCoreEval, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, -- ConstructorSynthesisFallback: exhaustive K-synthesis fallback and error branches. - { root := ``Ix.Tc.RecM.verifyKSynthCandidate_inferMiss, + { root := ``Ix.Kernel.RecM.verifyKSynthCandidate_inferMiss, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.verifyKSynthCandidate_inferError, + { root := ``Ix.Kernel.RecM.verifyKSynthCandidate_inferError, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.verifyKSynthCandidate_defEqError, + { root := ``Ix.Kernel.RecM.verifyKSynthCandidate_defEqError, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_mismatch, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_mismatch, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_missing, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_missing, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_nonInductive, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_nonInductive, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_empty, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_empty, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_selected, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_selected, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_selectedError, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_selectedError, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_majorInferMiss, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_majorInferMiss, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_majorInferError, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_majorInferError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_majorWhnfMiss, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_majorWhnfMiss, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_majorWhnfError, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_majorWhnfError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_nonConstHead, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_nonConstHead, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_recursorMissing, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_recursorMissing, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_majorInductiveMiss, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_majorInductiveMiss, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_majorInductiveError, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_majorInductiveError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSelectionTrace.eval, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSelectionTrace.eval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSelectionTrace.mismatch, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSelectionTrace.mismatch, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSelectionTrace.missing, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSelectionTrace.missing, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSelectionTrace.nonInductive, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSelectionTrace.nonInductive, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSelectionTrace.empty, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSelectionTrace.empty, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSelectionTrace.selected, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSelectionTrace.selected, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SynthCtorWhenKSelectionTrace.selectedError, + { root := ``Ix.Kernel.RecM.SynthCtorWhenKSelectionTrace.selectedError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kMajorInferRawError, + { root := ``Ix.Kernel.AmbientNat.kMajorInferRawError, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kMajorInferCaughtMiss, + { root := ``Ix.Kernel.AmbientNat.kMajorInferCaughtMiss, standardAxioms := standard, nativeAxioms := inferNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kCandidateInferRawError, + { root := ``Ix.Kernel.AmbientNat.kCandidateInferRawError, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kCandidateInferCaughtMiss, + { root := ``Ix.Kernel.AmbientNat.kCandidateInferCaughtMiss, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kDefEqRawError, + { root := ``Ix.Kernel.AmbientNat.kDefEqRawError, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kDefEqCandidateError, + { root := ``Ix.Kernel.AmbientNat.kDefEqCandidateError, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kDefEqSynthError, + { root := ``Ix.Kernel.AmbientNat.kDefEqSynthError, standardAxioms := standard, nativeAxioms := inferNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kEmptyGetRec, + { root := ``Ix.Kernel.AmbientNat.kEmptyGetRec, standardAxioms := standard, nativeAxioms := canonicalPrimitivesNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kEmptyGetNat, + { root := ``Ix.Kernel.AmbientNat.kEmptyGetNat, standardAxioms := standard, nativeAxioms := canonicalPrimitivesNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kEmptyMajorInductive, + { root := ``Ix.Kernel.AmbientNat.kEmptyMajorInductive, standardAxioms := standard, nativeAxioms := canonicalPrimitivesContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.kEmptyInductiveMiss, + { root := ``Ix.Kernel.AmbientNat.kEmptyInductiveMiss, standardAxioms := standard, nativeAxioms := inferNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, @@ -6382,270 +6366,270 @@ private def roots : Array RootAllowance := #[ -- StructEtaControl: exhaustive struct-eta classification, caught probes, rebuild, -- single-rule selection, and final constructor fallthrough. Rebuilding is -- proved total; only universe instantiation can produce a post-guard error. - { root := ``Ix.Tc.RecM.isStructLike_missing, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.isStructLike_missing, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isStructLike_nonInductive, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.isStructLike_nonInductive, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isStructLike_lookupError, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.isStructLike_lookupError, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isStructLike_badShape, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.isStructLike_badShape, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isStructLike_shapeQualified, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.isStructLike_shapeQualified, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isStructLike_recError, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.isStructLike_recError, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaResult_empty, + { root := ``Ix.Kernel.RecM.finishStructEtaResult_empty, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.structEtaIntern_total, + { root := ``Ix.Kernel.RecM.structEtaIntern_total, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaFields_total, + { root := ``Ix.Kernel.RecM.finishStructEtaFields_total, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaResult_of_segments, + { root := ``Ix.Kernel.RecM.finishStructEtaResult_of_segments, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaResult_total, + { root := ``Ix.Kernel.RecM.finishStructEtaResult_total, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaResult_ne_error, + { root := ``Ix.Kernel.RecM.finishStructEtaResult_ne_error, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaAfterSort_prop, + { root := ``Ix.Kernel.RecM.finishStructEtaAfterSort_prop, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaAfterSort_success, + { root := ``Ix.Kernel.RecM.finishStructEtaAfterSort_success, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaAfterSort_instantiateError, + { root := ``Ix.Kernel.RecM.finishStructEtaAfterSort_instantiateError, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaAfterSort_finishError, + { root := ``Ix.Kernel.RecM.finishStructEtaAfterSort_finishError, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_notStruct, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_notStruct, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_structError, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_structError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_majorInferMiss, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_majorInferMiss, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_majorInferError, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_majorInferError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_sortInferMiss, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_sortInferMiss, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_sortInferError, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_sortInferError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_sortWhnfMiss, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_sortWhnfMiss, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_sortWhnfError, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_sortWhnfError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaProbeTrace.eval, + { root := ``Ix.Kernel.RecM.StructEtaProbeTrace.eval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaProbeTrace.prop, + { root := ``Ix.Kernel.RecM.StructEtaProbeTrace.prop, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaProbeTrace.success, + { root := ``Ix.Kernel.RecM.StructEtaProbeTrace.success, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaProbeTrace.finishError, + { root := ``Ix.Kernel.RecM.StructEtaProbeTrace.finishError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_ruleCount, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_ruleCount, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_recursorMissing, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_recursorMissing, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_recursorError, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_recursorError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_majorInductiveMiss, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_majorInductiveMiss, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_majorInductiveError, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_majorInductiveError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaSelectionTrace.eval, + { root := ``Ix.Kernel.RecM.StructEtaSelectionTrace.eval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaIotaSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.StructEtaIotaSuccessTrace.eval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaIotaSuccessTrace.acceptance, + { root := ``Ix.Kernel.RecM.StructEtaIotaSuccessTrace.acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- Rebuild: the successful struct-eta rebuild derives its invariant, frame, -- and finite support from the exact projection/application request list. -- The registered Theory equation remains an explicit premise. - { root := ``Ix.Tc.RecM.StructEtaFieldRequests.support, + { root := ``Ix.Kernel.RecM.StructEtaFieldRequests.support, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaFieldRequests.eval, + { root := ``Ix.Kernel.RecM.StructEtaFieldRequests.eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaBuildRequests.eval, + { root := ``Ix.Kernel.RecM.StructEtaBuildRequests.eval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaIotaSuccessTrace.acceptance_of_requests, + { root := ``Ix.Kernel.RecM.StructEtaIotaSuccessTrace.acceptance_of_requests, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- CallbackPrefix: the exact infer-only and optional-catch wrappers preserve the -- complete fixed-world invariant while retaining callback mutations. - { root := ``Ix.Tc.TcM.withInferOnly_eq, + { root := ``Ix.Kernel.TcM.withInferOnly_eq, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.withInferOnly_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.TcM.withInferOnly_whnf_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.inferOnlyRec_run, + { root := ``Ix.Kernel.RecM.inferOnlyRec_run, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryOptional_run, + { root := ``Ix.Kernel.RecM.tryOptional_run, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryOptional_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.tryOptional_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.inferOnlyRec_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.inferOnlyRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryOptionalInferOnlyRec_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.tryOptionalInferOnlyRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryOptionalWhnfRec_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.tryOptionalWhnfRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, -- RecursionClassifier: recursion classification now owns its complete concrete state -- transaction. Both physical writes require explicit provenance; the -- final write is indexed by the exact classifier execution, and only -- errors inside that classifier enter the erase-and-rethrow handler. - { root := ``Ix.Tc.CacheInvariant.insertIsRec, + { root := ``Ix.Kernel.CacheInvariant.insertIsRec, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.eraseIsRec, + { root := ``Ix.Kernel.CacheInvariant.eraseIsRec, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsRecCacheUpdate.insert_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.IsRecCacheUpdate.insert_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsRecCacheUpdate.erase_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.IsRecCacheUpdate.erase_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsRecCacheWriteOracle.of_trusted, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.IsRecCacheWriteOracle.of_trusted, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.getConst_wf, + { root := ``Ix.Kernel.TcM.getConst_wf, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.tryGetBlock_wf, + { root := ``Ix.Kernel.TcM.tryGetBlock_wf, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.WhnfCallbackSupports.preserves, + { root := ``Ix.Kernel.RecM.WhnfCallbackSupports.preserves, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.getMajorInductiveId_wf, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.getMajorInductiveId_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.collectSpine_const_references, + { root := ``Ix.Kernel.RecM.collectSpine_const_references, standardAxioms := propextOnly, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.getMajorInductiveId_trusted_wf, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.getMajorInductiveId_trusted_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.discoverBlockInductives_wf, + { root := ``Ix.Kernel.RecM.discoverBlockInductives_wf, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.computeIsRec_wf, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.computeIsRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.cacheIsRec_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.cacheIsRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.eraseCachedIsRec_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.eraseCachedIsRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.computedIsRecClassify_wf, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.computedIsRecClassify_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.computedIsRecMiss_wf, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.computedIsRecMiss_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.computedIsRec_wf, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.computedIsRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, -- Classifier: compose the recursion classifier through `isStructLike`, then -- exhaust the single-rule recursor lookup and all three caught struct-eta -- probes. Only the explicitly parameterized cache-write, callback, and -- successful universe/rebuild authorities remain outside these proofs. - { root := ``Ix.Tc.RecM.isStructLike_wf, - standardAxioms := standard, nativeAxioms := blake3ContextNative, + { root := ``Ix.Kernel.RecM.isStructLike_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryOptional_state_wf, + { root := ``Ix.Kernel.RecM.tryOptional_state_wf, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryOptional_fixed_wf, + { root := ``Ix.Kernel.RecM.tryOptional_fixed_wf, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaAfterInductive_wf, + { root := ``Ix.Kernel.RecM.tryStructEtaAfterInductive_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_prefix_wf, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_prefix_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_trusted_prefix_wf, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_trusted_prefix_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructEtaIota_wf, + { root := ``Ix.Kernel.RecM.tryStructEtaIota_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- RebuildTail: the universe-instantiation/rebuild tail now preserves the complete -- invariant from the finite execution request census, including retained -- intern-table updates on a non-backtracking walker error. - { root := ``Ix.Tc.TcM.instantiateUnivParams_whnf_wf, + { root := ``Ix.Kernel.TcM.instantiateUnivParams_whnf_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaBuildRequests.wf, + { root := ``Ix.Kernel.RecM.StructEtaBuildRequests.wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishStructEtaAfterSort_wf_of_requests, + { root := ``Ix.Kernel.RecM.finishStructEtaAfterSort_wf_of_requests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, -- CacheShell: both structural-core cache partitions now have explicit -- collision-robust write authority, and the actual public dispatcher is -- closed conditionally on the remaining exhaustive structural step. - { root := ``Ix.Tc.RecM.WhnfCoreCacheWriteOracle.closed, + { root := ``Ix.Kernel.RecM.WhnfCoreCacheWriteOracle.closed, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfSuffixModel.coreCacheWriteOracle, + { root := ``Ix.Kernel.WhnfSuffixModel.coreCacheWriteOracle, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsNonLeaf_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsNonLeaf_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlags_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlags_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -6654,81 +6638,81 @@ private def roots : Array RootAllowance := #[ -- substitution now share one local structural-step contract. The fvar -- theorem exposes the real unchanged-value safety invariant rather than -- inferring closedness or arithmetic bounds from translation alone. - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_fvar_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_fvar_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_letE_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_letE_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_basic_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_basic_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- VariableStep: legacy zeta now derives its semantic weakening from the exact -- lift-walker bounds. The only additional safety fact is the real -- UInt64 `idx + 1` no-wrap condition on an actual let-value hit. - { root := ``Ix.Tc.CtxRecon.lookupLetVal_liftBounds, + { root := ``Ix.Kernel.CtxRecon.lookupLetVal_liftBounds, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.lookupLetVal_noLet, + { root := ``Ix.Kernel.TcM.lookupLetVal_noLet, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.zetaVar_liftBounds, + { root := ``Ix.Kernel.WhnfMeaning.zetaVar_liftBounds, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_var_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_var_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_basicVar_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_basicVar_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- RecursiveCallbacks: projection values and application-spine children now have an -- explicit finite-support boundary, and both recursive head callbacks are -- instantiated directly from the predecessor method-table contract. - { root := ``Ix.Tc.RecM.whnfCoreFlagsRec_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.whnfCoreFlagsRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.headTr, + { root := ``Ix.Kernel.RecM.TrAppSpine.headTr, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.projectionValueCallback_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.projectionValueCallback_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applicationHeadCallback_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.applicationHeadCallback_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applicationArgument_support, + { root := ``Ix.Kernel.RecM.applicationArgument_support, standardAxioms := propextOnly, forbiddenDependencies := legacyWholeEnv }, -- ProjectionStep: all projection-step outcomes now satisfy the local structural -- contract once the exact helper effect/result boundary is instantiated; -- callback and helper errors retain their partial post-state. - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_projection_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_projection_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_basicVarProjection_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_basicVarProjection_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- ApplicationCongruence: the application-head callback is tied to the exact typed suffix, -- and Theory application congruence transports head reduction across every -- argument rebuilt by the finite production certificate. - { root := ``Ix.Tc.RecM.TrAppSpine.toSuffix, + { root := ``Ix.Kernel.RecM.TrAppSpine.toSuffix, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applicationHeadCallbackWithSuffix_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.applicationHeadCallbackWithSuffix_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.WhnfMeaning.appHeadRebuild, + { root := ``Ix.Kernel.RecM.WhnfMeaning.appHeadRebuild, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, -- ApplicationRebuild: a finite census now executes each dynamic changed-head rebuild and -- returns its exact intern frame, support, and transported Theory meaning. - { root := ``Ix.Tc.RecM.changedHeadFinish_acceptance, + { root := ``Ix.Kernel.RecM.changedHeadFinish_acceptance, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -6736,13 +6720,13 @@ private def roots : Array RootAllowance := #[ -- ApplicationTails: both non-beta application tails are exhaustive over iota hit, -- miss, and error. Changed-head hits compose rebuild congruence with the -- helper result; unchanged misses remain reflexive at the original source. - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appUnchangedIota, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appUnchangedIota, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appUnchanged_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appUnchanged_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfCoreWithFlagsStep_appChanged_wf, + { root := ``Ix.Kernel.RecM.whnfCoreWithFlagsStep_appChanged_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -6752,48 +6736,48 @@ private def roots : Array RootAllowance := #[ -- and derives selected-field support from the concrete collected spine. -- Only String preprocessing and the installed lazy-ingress hook remain at -- the public helper constructor. - { root := ``Ix.Tc.RecM.WhnfCoreInputSupport.spineArg, + { root := ``Ix.Kernel.RecM.WhnfCoreInputSupport.spineArg, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjReduceTail_noAccel_wf, + { root := ``Ix.Kernel.RecM.tryProjReduceTail_noAccel_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionPrelude.nonString, + { root := ``Ix.Kernel.RecM.ProjectionPrelude.nonString, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionPrelude.ofString, + { root := ``Ix.Kernel.RecM.ProjectionPrelude.ofString, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjReduce_noAccel_wf, + { root := ``Ix.Kernel.RecM.tryProjReduce_noAccel_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionHelper.noAccel, + { root := ``Ix.Kernel.RecM.ProjectionHelper.noAccel, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionStringPrelude.ofExpansion, + { root := ``Ix.Kernel.RecM.ProjectionStringPrelude.ofExpansion, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionHelper.noAccelOfExpansion, + { root := ``Ix.Kernel.RecM.ProjectionHelper.noAccelOfExpansion, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, -- StringExpansion: the remaining String-expansion premise is reduced to a pure, -- finite plan. The actual primitive read, seven prefix interns, recursive -- character fold, and final intern preserve the complete K1 invariant and -- return the exact structurally translated generated expression. - { root := ``Ix.Tc.RecM.strLitListToConstructor_plan_wf, + { root := ``Ix.Kernel.RecM.strLitListToConstructor_plan_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.strLitToConstructorWithPrimitives_plan_wf, + ``Ix.Kernel.RecM.strLitToConstructorWithPrimitives_plan_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.strLitToConstructor_plan_wf, + { root := ``Ix.Kernel.RecM.strLitToConstructor_plan_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionStringExpansion.ofPlans, + { root := ``Ix.Kernel.RecM.ProjectionStringExpansion.ofPlans, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionHelper.noAccelOfStringPlans, + { root := ``Ix.Kernel.RecM.ProjectionHelper.noAccelOfStringPlans, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, -- LazyIngress: instantiate the generic lazy-fault plumbing with production's @@ -6801,37 +6785,37 @@ private def roots : Array RootAllowance := #[ -- covers a successful load, an absent address, and an error-carried partial -- environment; hook identity remains visible because `TcState.lazyFault` -- otherwise stores an arbitrary function. - { root := ``Ix.Tc.LazyIngressEnvFrame.refl, + { root := ``Ix.Kernel.LazyIngressEnvFrame.refl, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.LazyIngressEnvFrame.kernelStateWF, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.LazyIngressEnvFrame.kernelStateWF, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.LazyIngressEnvFrame.ctxRecon, + { root := ``Ix.Kernel.LazyIngressEnvFrame.ctxRecon, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.LazyIngressEnvFrame.whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.LazyIngressEnvFrame.whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ingressAnonAddrShallow_absent, + { root := ``Ix.Kernel.ingressAnonAddrShallow_absent, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AnonIngressRefinement.absentOfVerifiedMiss, + { root := ``Ix.Kernel.AnonIngressRefinement.absentOfVerifiedMiss, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AnonIngressRefinement.error, + { root := ``Ix.Kernel.AnonIngressRefinement.error, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AnonIngressRefinement.lazyFaultPreserves, + { root := ``Ix.Kernel.AnonIngressRefinement.lazyFaultPreserves, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AnonLazyIngressContext, + { root := ``Ix.Kernel.AnonLazyIngressContext, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AnonLazyIngressContext.preserves, + { root := ``Ix.Kernel.AnonLazyIngressContext.preserves, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.ProjectionHelper.noAccelOfAnonIngress, + { root := ``Ix.Kernel.RecM.ProjectionHelper.noAccelOfAnonIngress, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, -- NatOffset: the actual post-major iota preprocessing path. Bounded Nat-offset @@ -6839,64 +6823,64 @@ private def roots : Array RootAllowance := #[ -- finite String expansion, the policy-selected recursive callback, and the -- constructor/struct-eta dispatch all preserve the complete K1 invariant. -- Only the ordinary-constructor and struct-eta tails remain named inputs. - { root := ``Ix.Tc.RecM.prims_state_wf, + { root := ``Ix.Kernel.RecM.prims_state_wf, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatBinArithAddr_state_wf, + { root := ``Ix.Kernel.RecM.isNatBinArithAddr_state_wf, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natOffsetReaders_state_wf, + { root := ``Ix.Kernel.RecM.natOffsetReaders_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natOffset_state_wf, + { root := ``Ix.Kernel.RecM.natOffset_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.evalNatOffsetLiteral_state_wf, + { root := ``Ix.Kernel.RecM.evalNatOffsetLiteral_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natToConstructor_state_wf, + { root := ``Ix.Kernel.RecM.natToConstructor_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.mkNatSucc_state_wf, + { root := ``Ix.Kernel.RecM.mkNatSucc_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.mkNatAdd_state_wf, + { root := ``Ix.Kernel.RecM.mkNatAdd_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.WF.with_run_eq, + { root := ``Ix.Kernel.TcM.WF.with_run_eq, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.OptionalGeneratedInput, + { root := ``Ix.Kernel.RecM.OptionalGeneratedInput, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatOffsetCleanupInputOracle, - standardAxioms := standardWithoutChoice, + { root := ``Ix.Kernel.RecM.NatOffsetCleanupInputOracle, + standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.cleanupNatOffsetMajor_state_wf, + { root := ``Ix.Kernel.RecM.cleanupNatOffsetMajor_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.cleanupNatOffsetMajor_input_wf, + { root := ``Ix.Kernel.RecM.cleanupNatOffsetMajor_input_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryApplyIotaCtorPreserves, + { root := ``Ix.Kernel.RecM.TryApplyIotaCtorPreserves, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaIotaPreserves, + { root := ``Ix.Kernel.RecM.StructEtaIotaPreserves, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.SelectedStructEtaIotaPreserves, + { root := ``Ix.Kernel.RecM.SelectedStructEtaIotaPreserves, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaCtorOrStructEta_state_wf, + { root := ``Ix.Kernel.RecM.tryIotaCtorOrStructEta_state_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.strLitToConstructor_context_wf, + { root := ``Ix.Kernel.RecM.strLitToConstructor_context_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaAfterCleanup_state_wf, + { root := ``Ix.Kernel.RecM.tryIotaAfterCleanup_state_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaAfterMajorWhnf_state_wf, + { root := ``Ix.Kernel.RecM.tryIotaAfterMajorWhnf_state_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- ApplicationRequests--Ingress: finite ordinary-iota, struct-eta, and K-synthesis request @@ -6904,123 +6888,125 @@ private def roots : Array RootAllowance := #[ -- exhausts the actual tryIotaWithFlags state path through lazy lookup, -- caught probes, both cleanup stages, policy-selected major callbacks, -- statistics updates, and the final uncaught DefEq callback. - { root := ``Ix.Tc.RecM.IotaArgsInternRequests, + { root := ``Ix.Kernel.RecM.IotaArgsInternRequests, standardAxioms := standardWithoutQuot, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IotaArgsInternRequests.wfList, + { root := ``Ix.Kernel.RecM.IotaArgsInternRequests.wfList, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IotaArgsInternRequests.wfArray, + { root := ``Ix.Kernel.RecM.IotaArgsInternRequests.wfArray, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArg_true_state_wf, + { root := ``Ix.Kernel.RecM.applyIotaArg_true_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaArgs_true_state_wf, + { root := ``Ix.Kernel.RecM.applyIotaArgs_true_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IotaRuleRequests, + { root := ``Ix.Kernel.RecM.IotaRuleRequests, + standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IotaRuleRequestCensus, + { root := ``Ix.Kernel.RecM.IotaRuleRequestCensus, + standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.applyIotaRule_state_wf_of_requests, + { root := ``Ix.Kernel.RecM.applyIotaRule_state_wf_of_requests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryApplyIotaCtor_state_wf_of_requests, + { root := ``Ix.Kernel.RecM.tryApplyIotaCtor_state_wf_of_requests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryApplyIotaCtorPreserves.of_requests, + { root := ``Ix.Kernel.RecM.TryApplyIotaCtorPreserves.of_requests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaFinishRequests, + { root := ``Ix.Kernel.RecM.StructEtaFinishRequests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaFinishRequestCensus, + { root := ``Ix.Kernel.RecM.StructEtaFinishRequestCensus, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaFinishPreserves.of_requests, + { root := ``Ix.Kernel.RecM.StructEtaFinishPreserves.of_requests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructEtaIotaPreserves.of_components, + { root := ``Ix.Kernel.RecM.StructEtaIotaPreserves.of_components, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaAfterMajorWhnf_state_wf_of_contexts, + { root := ``Ix.Kernel.RecM.tryIotaAfterMajorWhnf_state_wf_of_contexts, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqCallbackPreserves, + { root := ``Ix.Kernel.RecM.IsDefEqCallbackPreserves, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.WF.tryFinally_const, + { root := ``Ix.Kernel.TcM.WF.tryFinally_const, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.enterDispatch_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.enterDispatch_whnf_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.exitDispatch_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.exitDispatch_whnf_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.callIsDefEq_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.callIsDefEq_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.KSynthCandidateRequests, + { root := ``Ix.Kernel.RecM.KSynthCandidateRequests, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.KSynthCandidateRequestCensus, + { root := ``Ix.Kernel.RecM.KSynthCandidateRequestCensus, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.KSynthCandidateInputs, + { root := ``Ix.Kernel.RecM.KSynthCandidateInputs, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.KSynthCandidateInputOracle, - standardAxioms := standardWithoutChoice, + { root := ``Ix.Kernel.RecM.KSynthCandidateInputOracle, + standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.FinishAppRequests.state_wf, + { root := ``Ix.Kernel.RecM.FinishAppRequests.state_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.verifyKSynthCandidate_state_wf_of_requests, + { root := ``Ix.Kernel.RecM.verifyKSynthCandidate_state_wf_of_requests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_state_wf_of_requests, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_state_wf_of_requests, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_state_wf_of_requests, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_state_wf_of_requests, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.verifyKSynthCandidate_state_wf_of_inputs, + { root := ``Ix.Kernel.RecM.verifyKSynthCandidate_state_wf_of_inputs, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.selectKSynthCandidate_state_wf_of_inputs, + { root := ``Ix.Kernel.RecM.selectKSynthCandidate_state_wf_of_inputs, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.synthCtorWhenK_state_wf_of_inputs, + { root := ``Ix.Kernel.RecM.synthCtorWhenK_state_wf_of_inputs, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_state_wf_of_contexts, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_state_wf_of_contexts, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- OptionalReduction: the exhaustive state proof and the direct admission-owned success -- boundary assemble the ordinary optional-reduction contract. The success -- boundary contributes support and Theory meaning only; it cannot hide an -- error-side or miss-side state assumption. - { root := ``Ix.Tc.IotaCallbackFrameOracle, + { root := ``Ix.Kernel.IotaCallbackFrameOracle, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.IotaSuccessOracle, + { root := ``Ix.Kernel.IotaSuccessOracle, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaWithFlags_optional_wf_of_contexts, + { root := ``Ix.Kernel.RecM.tryIotaWithFlags_optional_wf_of_contexts, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- Reducer: the structural contract is indexed by the actual universe/context -- represented by the cache model. The assembled theorem feeds OptionalReduction into -- the exhaustive syntax step and then through the bounded/cache driver. - { root := ``Ix.Tc.StructuralReduction.WF, + { root := ``Ix.Kernel.StructuralReduction.WF, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructuralCoreContext, + { root := ``Ix.Kernel.RecM.StructuralCoreContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.StructuralCoreContext.wf, + { root := ``Ix.Kernel.RecM.StructuralCoreContext.wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -7029,33 +7015,33 @@ private def roots : Array RootAllowance := #[ -- and successful projection followed by a certified complete-spine -- rebuild. Head meaning is transported through the typed suffix rather -- than inferred from expression-address equality. - { root := ``Ix.Tc.RecM.tryProjAppReduce_empty, + { root := ``Ix.Kernel.RecM.tryProjAppReduce_empty, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjAppReduce_notProjection, + { root := ``Ix.Kernel.RecM.tryProjAppReduce_notProjection, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjAppReduce_projectionWhnfError, + { root := ``Ix.Kernel.RecM.tryProjAppReduce_projectionWhnfError, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjAppReduce_projectionReduceError, + { root := ``Ix.Kernel.RecM.tryProjAppReduce_projectionReduceError, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjAppReduce_projectionNone, + { root := ``Ix.Kernel.RecM.tryProjAppReduce_projectionNone, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjAppReduce_projectionSome, + { root := ``Ix.Kernel.RecM.tryProjAppReduce_projectionSome, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjAppReduceFinished_empty_wf, + { root := ``Ix.Kernel.RecM.tryProjAppReduceFinished_empty_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProjAppReduceFinished_app_optional_wf, + { root := ``Ix.Kernel.RecM.tryProjAppReduceFinished_app_optional_wf, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryProjAppReduceFinished_optional_wf_of_contexts, + ``Ix.Kernel.RecM.tryProjAppReduceFinished_optional_wf_of_contexts, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -7063,38 +7049,39 @@ private def roots : Array RootAllowance := #[ -- classifier miss and all three hits. Its state proof derives finite -- generated-node support at each intern; the reflection boundary owns -- only Theory meaning for an observed successful run. - { root := ``Ix.Tc.StringReductionSupport, + { root := ``Ix.Kernel.StringReductionSupport, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.StringReductionReflection, + { root := ``Ix.Kernel.StringReductionReflection, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceString_inv_wf, + { root := ``Ix.Kernel.RecM.tryReduceString_inv_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceString_optional_wf_of_reflection, + { root := ``Ix.Kernel.RecM.tryReduceString_optional_wf_of_reflection, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, -- ProjectionDefinition: projection-wrapper reduction covers the real lazy constant lookup, -- the generated projection, and every suffix intern. The request plan -- exposes all intermediate support obligations instead of assuming that -- support for the final node retroactively makes those interns safe. - { root := ``Ix.Tc.ProjectionDefinitionRequestCensus, + { root := ``Ix.Kernel.ProjectionDefinitionRequestCensus, + standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ProjectionDefinitionReflection, + { root := ``Ix.Kernel.ProjectionDefinitionReflection, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.projectionDefinitionFinish_eq, + { root := ``Ix.Kernel.RecM.projectionDefinitionFinish_eq, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.FinishAppRequests.finishAppResult_wf, + { root := ``Ix.Kernel.RecM.FinishAppRequests.finishAppResult_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceProjectionDefinition_inv_wf, + { root := ``Ix.Kernel.RecM.tryReduceProjectionDefinition_inv_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceProjectionDefinition_optional_wf_of_contexts, + ``Ix.Kernel.RecM.tryReduceProjectionDefinition_optional_wf_of_contexts, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, -- Quotient: quotient reduction derives the selected major's support and @@ -7105,83 +7092,83 @@ private def roots : Array RootAllowance := #[ -- laws. Ix owns the complete dynamic trace, exact lift/ind layouts, -- normalized `Quot.mk` transport, collision-free base intern, and suffix -- reconstruction. - { root := ``Ix.Tc.QuotientReductionRequestCensus, + { root := ``Ix.Kernel.QuotientReductionRequestCensus, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.QuotientReductionReflection, + { root := ``Ix.Kernel.QuotientReductionReflection, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.QuotientReductionLaws, + { root := ``Ix.Kernel.QuotientReductionLaws, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.three, + { root := ``Ix.Kernel.RecM.TrAppSpine.three, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.four, + { root := ``Ix.Kernel.RecM.TrAppSpine.four, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.five, + { root := ``Ix.Kernel.RecM.TrAppSpine.five, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrKExprS.const_name, + { root := ``Ix.Kernel.RecM.TrKExprS.const_name, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.quotientLiftMeaning, + { root := ``Ix.Kernel.RecM.quotientLiftMeaning, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.quotientIndMeaning, + { root := ``Ix.Kernel.RecM.quotientIndMeaning, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.QuotientSelectedSuccessTrace.complete, + { root := ``Ix.Kernel.RecM.QuotientSelectedSuccessTrace.complete, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.QuotientSelectedSuccessTrace.semanticInputs, + { root := ``Ix.Kernel.RecM.QuotientSelectedSuccessTrace.semanticInputs, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.QuotientSelectedSuccessTrace.liftMeaning, + { root := ``Ix.Kernel.RecM.QuotientSelectedSuccessTrace.liftMeaning, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.QuotientSelectedSuccessTrace.indMeaning, + { root := ``Ix.Kernel.RecM.QuotientSelectedSuccessTrace.indMeaning, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.QuotientReductionReflection.of_laws, + { root := ``Ix.Kernel.QuotientReductionReflection.of_laws, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryQuotReduceSelected, + { root := ``Ix.Kernel.RecM.tryQuotReduceSelected, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryQuotReduceSelected_inv_wf, + { root := ``Ix.Kernel.RecM.tryQuotReduceSelected_inv_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryQuotReduce_inv_wf, + { root := ``Ix.Kernel.RecM.tryQuotReduce_inv_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryQuotReduce_optional_wf_of_contexts, + { root := ``Ix.Kernel.RecM.tryQuotReduce_optional_wf_of_contexts, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, -- BaseReductions: the five active no-acceleration reducers are assembled into the -- exact production base oracle for either successor policy. Native and -- BitVec remain independently discharged by the no-acceleration gate. - { root := ``Ix.Tc.RecM.NoDeltaBaseContext, + { root := ``Ix.Kernel.RecM.NoDeltaBaseContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NoDeltaBaseContext.oracle, + { root := ``Ix.Kernel.RecM.NoDeltaBaseContext.oracle, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, -- Reducer: Reducer's structural reducer and BaseReductions's active base oracle now feed -- the real bounded, keyed, transient-aware, cache-writing public -- `whnfNoDeltaImpl` shell for every flag and successor policy. - { root := ``Ix.Tc.RecM.NoDeltaDriverContext, + { root := ``Ix.Kernel.RecM.NoDeltaDriverContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NoDeltaDriverContext.wf, + { root := ``Ix.Kernel.RecM.NoDeltaDriverContext.wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -7191,279 +7178,279 @@ private def roots : Array RootAllowance := #[ -- the bare fallback closes `deltaUnfoldOne`. The final cache composition -- and method knot are indexed by the active universe count; concrete lazy -- ingress is carried by `AnonLazyIngressContext`, not a free callback. - { root := ``Ix.Tc.OptionalReduction.WFAt, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.OptionalReduction.WFAt, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrustedDeltaBody.meaning, + { root := ``Ix.Kernel.TrustedDeltaBody.meaning, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.StableWhnfTheory, + { root := ``Ix.Kernel.StableWhnfTheory, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrustedDeltaBody.unfoldCacheProvenance, + { root := ``Ix.Kernel.TrustedDeltaBody.unfoldCacheProvenance, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.unfoldConstValue_trusted_wf, + { root := ``Ix.Kernel.RecM.unfoldConstValue_trusted_wf, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrustedDeltaCensus, - standardAxioms := standard, + { root := ``Ix.Kernel.TrustedDeltaCensus, + standardAxioms := standard, nativeAxioms := univOnlyNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDeltaUnfold_trusted_wf, + { root := ``Ix.Kernel.RecM.tryDeltaUnfold_trusted_wf, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.deltaUnfoldOne_trusted_wf, + { root := ``Ix.Kernel.RecM.deltaUnfoldOne_trusted_wf, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrustedDeltaContext, + { root := ``Ix.Kernel.RecM.TrustedDeltaContext, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrustedDeltaContext.wfAt, + { root := ``Ix.Kernel.RecM.TrustedDeltaContext.wfAt, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.FullWhnfStepContext.ofTrustedDelta, + { root := ``Ix.Kernel.RecM.FullWhnfStepContext.ofTrustedDelta, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.WhnfClosedAt, + { root := ``Ix.Kernel.Methods.WhnfClosedAt, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.Methods.methodsN_wfAt, + { root := ``Ix.Kernel.Methods.methodsN_wfAt, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.K1ClosureContext, + { root := ``Ix.Kernel.RecM.K1ClosureContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.K1ClosureContext.closedAt, + { root := ``Ix.Kernel.RecM.K1ClosureContext.closedAt, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.AmbientNat.structEtaInferOnlyRun, + { root := ``Ix.Kernel.AmbientNat.structEtaInferOnlyRun, standardAxioms := standard, nativeAxioms := expressionNameNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structEtaOptionalInferOnlyRun, + { root := ``Ix.Kernel.AmbientNat.structEtaOptionalInferOnlyRun, standardAxioms := standard, nativeAxioms := expressionNameNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaCtorOrStructEta_nonConst, + { root := ``Ix.Kernel.RecM.tryIotaCtorOrStructEta_nonConst, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaCtorOrStructEta_missing, + { root := ``Ix.Kernel.RecM.tryIotaCtorOrStructEta_missing, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaCtorOrStructEta_notConstructor, + { root := ``Ix.Kernel.RecM.tryIotaCtorOrStructEta_notConstructor, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaCtorOrStructEta_lookupError, + { root := ``Ix.Kernel.RecM.tryIotaCtorOrStructEta_lookupError, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryIotaCtorOrStructEta_constructor, + { root := ``Ix.Kernel.RecM.tryIotaCtorOrStructEta_constructor, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structEtaIotaSuccess, + { root := ``Ix.Kernel.AmbientNat.structEtaIotaSuccess, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structEtaBuildRequests, + { root := ``Ix.Kernel.AmbientNat.structEtaBuildRequests, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structEtaDispatchSuccess, + { root := ``Ix.Kernel.AmbientNat.structEtaDispatchSuccess, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structEtaIotaAbsent, + { root := ``Ix.Kernel.AmbientNat.structEtaIotaAbsent, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structEtaIotaCaughtInferError, + { root := ``Ix.Kernel.AmbientNat.structEtaIotaCaughtInferError, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaCleanupOfNatValue, + { root := ``Ix.Kernel.AmbientNat.iotaCleanupOfNatValue, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatCleanup, + { root := ``Ix.Kernel.AmbientNat.iotaNatCleanup, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatCtorCleanup, + { root := ``Ix.Kernel.AmbientNat.iotaNatCtorCleanup, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatMajorWhnf, + { root := ``Ix.Kernel.AmbientNat.iotaNatMajorWhnf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatZeroExpand, + { root := ``Ix.Kernel.AmbientNat.iotaNatZeroExpand, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatSuccExpand, + { root := ``Ix.Kernel.AmbientNat.iotaNatSuccExpand, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatApplyRule, + { root := ``Ix.Kernel.AmbientNat.iotaNatApplyRule, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatApplyCtor, + { root := ``Ix.Kernel.AmbientNat.iotaNatApplyCtor, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatTryEval, + { root := ``Ix.Kernel.AmbientNat.iotaNatTryEval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatStepEval, + { root := ``Ix.Kernel.AmbientNat.iotaNatStepEval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaNatCoreEval, + { root := ``Ix.Kernel.AmbientNat.iotaNatCoreEval, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaApplyRule, + { root := ``Ix.Kernel.AmbientNat.iotaApplyRule, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaApplyCtor, + { root := ``Ix.Kernel.AmbientNat.iotaApplyCtor, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.support_le_iotaArgsSupport, + { root := ``Ix.Kernel.AmbientNat.support_le_iotaArgsSupport, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaArgsStateInv, + { root := ``Ix.Kernel.AmbientNat.iotaArgsStateInv, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaArgsSupport_head, + { root := ``Ix.Kernel.AmbientNat.iotaArgsSupport_head, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.iotaArgsSupport_source, + { root := ``Ix.Kernel.AmbientNat.iotaArgsSupport_source, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.appStuckIotaTransientThreeSegments, + { root := ``Ix.Kernel.AmbientNat.appStuckIotaTransientThreeSegments, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaFirstResult, + { root := ``Ix.Kernel.AmbientNat.multiIotaFirstResult, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaSecondResult, + { root := ``Ix.Kernel.AmbientNat.multiIotaSecondResult, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.appStuckHead_constructed, + { root := ``Ix.Kernel.AmbientNat.appStuckHead_constructed, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiBetaInner_constructed, + { root := ``Ix.Kernel.AmbientNat.multiBetaInner_constructed, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaIntermediate_constructed, + { root := ``Ix.Kernel.AmbientNat.multiIotaIntermediate_constructed, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.appStuckHead_tr_ctx, + { root := ``Ix.Kernel.AmbientNat.appStuckHead_tr_ctx, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.appStuckHead_type_ctx, + { root := ``Ix.Kernel.AmbientNat.appStuckHead_type_ctx, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaIntermediate_tr, + { root := ``Ix.Kernel.AmbientNat.multiIotaIntermediate_tr, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.support_le_multiIotaSupport, + { root := ``Ix.Kernel.AmbientNat.support_le_multiIotaSupport, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaStateInv, + { root := ``Ix.Kernel.AmbientNat.multiIotaStateInv, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaSupport_start, + { root := ``Ix.Kernel.AmbientNat.multiIotaSupport_start, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaSupport_intermediate, + { root := ``Ix.Kernel.AmbientNat.multiIotaSupport_intermediate, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaSupport_head, + { root := ``Ix.Kernel.AmbientNat.multiIotaSupport_head, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaSupport_result, + { root := ``Ix.Kernel.AmbientNat.multiIotaSupport_result, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaFirstTrace, + { root := ``Ix.Kernel.AmbientNat.multiIotaFirstTrace, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaSecondTrace, + { root := ``Ix.Kernel.AmbientNat.multiIotaSecondTrace, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaThirdTrace, + { root := ``Ix.Kernel.AmbientNat.multiIotaThirdTrace, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaTransientThreeSegments, + { root := ``Ix.Kernel.AmbientNat.multiIotaTransientThreeSegments, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaPrefixSlice, + { root := ``Ix.Kernel.AmbientNat.multiIotaPrefixSlice, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaFieldSlice, + { root := ``Ix.Kernel.AmbientNat.multiIotaFieldSlice, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaTrailingSlice, + { root := ``Ix.Kernel.AmbientNat.multiIotaTrailingSlice, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaRuleEval, + { root := ``Ix.Kernel.AmbientNat.multiIotaRuleEval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaRuleAcceptance, + { root := ``Ix.Kernel.AmbientNat.multiIotaRuleAcceptance, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaCtorEval, + { root := ``Ix.Kernel.AmbientNat.multiIotaCtorEval, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiIotaCtorAcceptance, + { root := ``Ix.Kernel.AmbientNat.multiIotaCtorAcceptance, standardAxioms := standard, nativeAxioms := levelNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.missingRuleDescriptor, + { root := ``Ix.Kernel.AmbientNat.missingRuleDescriptor, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.missingRuleDescriptor_noZeroRule, + { root := ``Ix.Kernel.AmbientNat.missingRuleDescriptor_noZeroRule, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.multiBetaMiddleSplit, + { root := ``Ix.Kernel.AmbientNat.multiBetaMiddleSplit, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.multiBetaMiddleRebase, + { root := ``Ix.Kernel.AmbientNat.multiBetaMiddleRebase, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.linearRecPartsRun, + { root := ``Ix.Kernel.AmbientNat.linearRecPartsRun, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.AmbientNat.linearRecPartsTrace, + { root := ``Ix.Kernel.AmbientNat.linearRecPartsTrace, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.TcM.LazyFaultPreserves.of_none, + { root := ``Ix.Kernel.TcM.LazyFaultPreserves.of_none, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.natRecLiteralParts_wf, + { root := ``Ix.Kernel.RecM.natRecLiteralParts_wf, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.NatRecLiteralPartsPreserves.of_lazy, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.NatRecLiteralPartsPreserves.of_lazy, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatRecLiteralPartsPreserves.eager, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.NatRecLiteralPartsPreserves.eager, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatLiteralRecursorApp_wf, + { root := ``Ix.Kernel.RecM.isNatLiteralRecursorApp_wf, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.isTransientNatLiteralWork_wf, + { root := ``Ix.Kernel.RecM.isTransientNatLiteralWork_wf, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.TransientNatWork.preserving, + { root := ``Ix.Kernel.RecM.TransientNatWork.preserving, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isTransientNatLiteralWork_noLazy, + { root := ``Ix.Kernel.RecM.isTransientNatLiteralWork_noLazy, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.TransientNatWork.eager, + { root := ``Ix.Kernel.RecM.TransientNatWork.eager, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, @@ -7472,100 +7459,100 @@ private def roots : Array RootAllowance := #[ -- every partial error state. The semantic package composes structural and -- reducer meanings, while the closed Nat.add fixture makes precedence -- executable and records its three canonical-address decisions explicitly. - { root := ``Ix.Tc.RecM.tryProjAppReduceFinished_some, + { root := ``Ix.Kernel.RecM.tryProjAppReduceFinished_some, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryProjAppReduceFinished_none, + { root := ``Ix.Kernel.RecM.tryProjAppReduceFinished_none, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryProjAppReduceFinished_projError, + { root := ``Ix.Kernel.RecM.tryProjAppReduceFinished_projError, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.tryProjAppReduceFinished_finishError, + { root := ``Ix.Kernel.RecM.tryProjAppReduceFinished_finishError, standardAxioms := standard, nativeAxioms := expressionNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_projApp, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_projApp, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_bitvec, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_bitvec, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_nat, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_nat, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_native, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_native, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_string, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_string, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_projectionDef, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_projectionDef, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_quotFull, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_quotFull, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_quotCheap, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_quotCheap, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_doneFull, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_doneFull, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_doneCheap, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_doneCheap, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_projError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_projError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_bitvecError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_bitvecError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_natError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_natError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_nativeError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_nativeError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_stringError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_stringError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_projectionDefError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_projectionDefError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_quotFullError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_quotFullError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_quotCheapError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_quotCheapError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_ofCore, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_ofCore, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_coreError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_coreError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_reducerError, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_reducerError, standardAxioms := standard, nativeAxioms := inferNative }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_next_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_next_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_done_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_done_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_error_acceptance, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_error_acceptance, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_wf, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaNatAddReduction, + { root := ``Ix.Kernel.AmbientNat.noDeltaNatAddReduction, standardAxioms := standard, nativeAxioms := natReductionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaNatBranchOrder, + { root := ``Ix.Kernel.AmbientNat.noDeltaNatBranchOrder, standardAxioms := standard, nativeAxioms := natBranchOrderNative, forbiddenDependencies := legacyWholeEnv }, -- primitive reduction: `.noAccel` concretely discharges the native and BitVec optional -- reducers. The five active helpers remain an explicit base oracle, which -- now feeds the exhaustive tail, outer step, and public no-delta shell. - { root := ``Ix.Tc.RecM.tryReduceNative_noAccel_optional_wf, + { root := ``Ix.Kernel.RecM.tryReduceNative_noAccel_optional_wf, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceBitvec_noAccel_optional_wf, + { root := ``Ix.Kernel.RecM.tryReduceBitvec_noAccel_optional_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.NoDeltaBaseOracle.toNoAccel, + { root := ``Ix.Kernel.NoDeltaBaseOracle.toNoAccel, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaReducersStep_noAccel_wf, + { root := ``Ix.Kernel.RecM.whnfNoDeltaReducersStep_noAccel_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_wf, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImplStep_noAccel_wf, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImplStep_noAccel_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNoDeltaImpl_noAccel_wf_of_base, + { root := ``Ix.Kernel.RecM.whnfNoDeltaImpl_noAccel_wf_of_base, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -7575,69 +7562,69 @@ private def roots : Array RootAllowance := #[ -- reducer closure. The world/context interface then binds the active Nat, -- String, projection, and quotient IDs to trusted Theory names and scopes -- generated results to actual successful helper executions. - { root := ``Ix.Tc.Primitives.ofAnonAddrs_canonical, + { root := ``Ix.Kernel.Primitives.ofAnonAddrs_canonical, standardAxioms := standard, nativeAxioms := canonicalPrimitivesNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfStateInv.noAccel_primitives, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.WhnfStateInv.noAccel_primitives, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfStateInv.accelerated_primitives, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.WhnfStateInv.accelerated_primitives, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.PrimitiveIdAgrees.contains, + { root := ``Ix.Kernel.PrimitiveIdAgrees.contains, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.PrimitiveIdAgrees.mono, + { root := ``Ix.Kernel.PrimitiveIdAgrees.mono, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.NoDeltaPrimitiveTableAgrees.mono, + { root := ``Ix.Kernel.NoDeltaPrimitiveTableAgrees.mono, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.NoDeltaPrimitiveContext.stateTable, + { root := ``Ix.Kernel.NoDeltaPrimitiveContext.stateTable, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, -- Nat reducer callback: the Nat reducer's shared callback/fuel boundary and exact binary -- arithmetic hit. The primitive computation is derived from the bound - -- canonical table and Lean4Lean reflection laws; no raw address equality + -- canonical table and Ix.Theory.Named reflection laws; no raw address equality -- is treated as semantic authority. - { root := ``Ix.Tc.WhnfStateInv.set_recFuel, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.WhnfStateInv.set_recFuel, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.WF.tryCatch, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.WF.tryCatch, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfRec_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.whnfRec_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNatReducerArg_post_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.whnfNatReducerArg_post_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNatReducerArg_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.whnfNatReducerArg_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.NoDeltaPrimitiveContext.computeNatBin_defeq, + { root := ``Ix.Kernel.NoDeltaPrimitiveContext.computeNatBin_defeq, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrKExprS.of_extractNatLit, + { root := ``Ix.Kernel.TrKExprS.of_extractNatLit, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrKExprS.natExprFromValue, + { root := ``Ix.Kernel.TrKExprS.natExprFromValue, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrKExprS.natBinExact_inv, + { root := ``Ix.Kernel.TrKExprS.natBinExact_inv, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfPost.of_extractNatLit, + { root := ``Ix.Kernel.WhnfPost.of_extractNatLit, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.natBinExact, + { root := ``Ix.Kernel.WhnfMeaning.natBinExact, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithExact, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithExact, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithExact_acceptance, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithExact_acceptance, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -7645,35 +7632,35 @@ private def roots : Array RootAllowance := #[ -- generic proof uses trusted-name separation instead of native hash -- inequalities, and the finite Bool intern is checked against explicit run -- collision freedom and generated-node support. - { root := ``Ix.Tc.TcM.intern_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.TcM.intern_whnf_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.intern_whnf_eval, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.TcM.intern_whnf_eval, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.PrimitiveIdAgrees.addr_ne, + { root := ``Ix.Kernel.PrimitiveIdAgrees.addr_ne, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.NoDeltaPrimitiveContext.computeNatBin_classifiers, + { root := ``Ix.Kernel.NoDeltaPrimitiveContext.computeNatBin_classifiers, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.NoDeltaPrimitiveContext.natPredicate_classifiers, + { root := ``Ix.Kernel.NoDeltaPrimitiveContext.natPredicate_classifiers, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.NoDeltaPrimitiveContext.natPredicate_defeq, + { root := ``Ix.Kernel.NoDeltaPrimitiveContext.natPredicate_defeq, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrKExprS.boolExprFromDecision, + { root := ``Ix.Kernel.TrKExprS.boolExprFromDecision, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_exact, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_exact, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binPredExact, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binPredExact, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binPredExact_acceptance, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binPredExact_acceptance, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -7681,118 +7668,118 @@ private def roots : Array RootAllowance := #[ -- reduction. Callback errors retain their partial state, arithmetic and -- predicate extraction order is pinned, and the complete two-argument -- dispatcher preserves the invariant on every outcome. - { root := ``Ix.Tc.RecM.WF.withInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.WF.withInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.prims_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.prims_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatBinArithAddr_inv_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.isNatBinArithAddr_inv_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatBinPredAddr_inv_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.isNatBinPredAddr_inv_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNatReducerArg_ok_inv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.whnfNatReducerArg_ok_inv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.whnfNatReducerArg_error_inv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.whnfNatReducerArg_error_inv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_bin_inv_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_bin_inv_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_bin_inv_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_bin_inv_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_argAMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_argAMiss, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_argAError, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_argAError, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_extractAMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_extractAMiss, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_argBMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_argBMiss, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_argBError, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_argBError, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_extractBMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_extractBMiss, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binPredMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binPredMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binPredError, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binPredError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithArgAMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithArgAMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithArgAError, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithArgAError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithArgBMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithArgBMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithArgBError, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithArgBError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithExtractAMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithExtractAMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithExtractBMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithExtractBMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithComputeMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithComputeMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, -- binary Nat success: every successful exact-binary Nat run is inverted into its actual -- callback/extraction/computation-or-intern trace, then folded into a -- semantic optional-reduction Hoare slice. Predicate precedence remains -- operationally exhaustive even before canonical classifier separation. - { root := ``Ix.Tc.RecM.isNatBinArithAddr_eval, + { root := ``Ix.Kernel.RecM.isNatBinArithAddr_eval, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatBinPredAddr_eval, + { root := ``Ix.Kernel.RecM.isNatBinPredAddr_eval, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatBinPredAddr_true, + { root := ``Ix.Kernel.RecM.isNatBinPredAddr_true, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binPredAnyExact, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binPredAnyExact, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatPredicateSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.NatPredicateSuccessTrace.eval, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatPredicateSuccessTrace.complete, + { root := ``Ix.Kernel.RecM.NatPredicateSuccessTrace.complete, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatBinSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.NatBinSuccessTrace.eval, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatBinSuccessTrace.complete, + { root := ``Ix.Kernel.RecM.NatBinSuccessTrace.complete, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatBinSuccessTrace.acceptance, + { root := ``Ix.Kernel.RecM.NatBinSuccessTrace.acceptance, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_bin_optional_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_bin_optional_wf, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.structuralInvariant_does_not_bind_primitives, + { root := ``Ix.Kernel.AmbientNat.structuralInvariant_does_not_bind_primitives, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.productionNoAccelStateInv, + { root := ``Ix.Kernel.AmbientNat.productionNoAccelStateInv, standardAxioms := standard, nativeAxioms := nameNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noAccelInvariant_rejects_mismatched_primitives, + { root := ``Ix.Kernel.AmbientNat.noAccelInvariant_rejects_mismatched_primitives, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, @@ -7800,80 +7787,80 @@ private def roots : Array RootAllowance := #[ -- spine, exact Nat equations are transported over arbitrary unchanged -- argument suffixes, and finite rebuild certificates preserve state and -- support. Successful general-spine executions are inverted exhaustively. - { root := ``Ix.Tc.RecM.appSpineView_go, + { root := ``Ix.Kernel.RecM.appSpineView_go, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.appSpineView_collectSpine, + { root := ``Ix.Kernel.RecM.appSpineView_collectSpine, standardAxioms := standardWithoutChoice }, - { root := ``Ix.Tc.RecM.trAppSpine_of_tr, + { root := ``Ix.Kernel.RecM.trAppSpine_of_tr, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.argument, + { root := ``Ix.Kernel.RecM.TrAppSpine.argument, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.tr, + { root := ``Ix.Kernel.RecM.TrAppSpine.tr, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.trAppSpine_of_collectSpine, + { root := ``Ix.Kernel.RecM.trAppSpine_of_collectSpine, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TrKExprS.foldlMkApp_initial, + { root := ``Ix.Kernel.TrKExprS.foldlMkApp_initial, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.appSameArg, + { root := ``Ix.Kernel.WhnfMeaning.appSameArg, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.foldlMkApp, + { root := ``Ix.Kernel.WhnfMeaning.foldlMkApp, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.mkAppN, + { root := ``Ix.Kernel.WhnfMeaning.mkAppN, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfMeaning.ofSharedSourceTranslation, + { root := ``Ix.Kernel.WhnfMeaning.ofSharedSourceTranslation, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_suffixExact, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_suffixExact, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binPredSuffixExact, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binPredSuffixExact, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithSuffixExact, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithSuffixExact, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binArithSuffix_acceptance, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binArithSuffix_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_binPredSuffix_acceptance, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_binPredSuffix_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatPredicateSuffixSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.NatPredicateSuffixSuccessTrace.eval, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatPredicateSuffixSuccessTrace.complete, + { root := ``Ix.Kernel.RecM.NatPredicateSuffixSuccessTrace.complete, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSpineSuccessTrace.eval, + { root := ``Ix.Kernel.RecM.NatSpineSuccessTrace.eval, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSpineSuccessTrace.complete, + { root := ``Ix.Kernel.RecM.NatSpineSuccessTrace.complete, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaNatAddSuffixSpine, + { root := ``Ix.Kernel.AmbientNat.noDeltaNatAddSuffixSpine, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaNatAddSuffixFinishRequests, + { root := ``Ix.Kernel.AmbientNat.noDeltaNatAddSuffixFinishRequests, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaNatAddSuffixReduction, + { root := ``Ix.Kernel.AmbientNat.noDeltaNatAddSuffixReduction, standardAxioms := standard, nativeAxioms := natSuffixReductionNative, forbiddenDependencies := legacyWholeEnv }, @@ -7882,33 +7869,33 @@ private def roots : Array RootAllowance := #[ -- with only its observed finite rebuild requests, then interpreted as the -- fixed-state optional-reduction Hoare contract. The over-applied Nat.add -- fixture inhabits that execution-indexed coverage boundary. - { root := ``Ix.Tc.RecM.finishAppResult_total, + { root := ``Ix.Kernel.RecM.finishAppResult_total, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natBinSpine_inputs, + { root := ``Ix.Kernel.RecM.natBinSpine_inputs, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatPredicate_spine_nonhit_inv, + { root := ``Ix.Kernel.RecM.tryReduceNatPredicate_spine_nonhit_inv, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_spine_nonhit_inv, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_spine_nonhit_inv, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSpineCertifiedSuccess.trace, + { root := ``Ix.Kernel.RecM.NatSpineCertifiedSuccess.trace, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSpineCertifiedSuccess.acceptance, + { root := ``Ix.Kernel.RecM.NatSpineCertifiedSuccess.acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_spine_optional_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_spine_optional_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaNatAddSuffixCertifiedSuccess, + { root := ``Ix.Kernel.AmbientNat.noDeltaNatAddSuffixCertifiedSuccess, standardAxioms := standard, nativeAxioms := natSuffixCertificateNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.noDeltaNatAddSuffixFinishCoverage, + { root := ``Ix.Kernel.AmbientNat.noDeltaNatAddSuffixFinishCoverage, standardAxioms := standard, nativeAxioms := natSuffixReductionNative, forbiddenDependencies := legacyWholeEnv }, @@ -7918,111 +7905,111 @@ private def roots : Array RootAllowance := #[ -- cache/state invariant only under explicit per-key provenance. The -- closed Nat.succ fixture runs through the actual dispatcher and bounded -- driver without mutating the state. - { root := ``Ix.Tc.CacheInvariant.insertNatSuccStuck, + { root := ``Ix.Kernel.CacheInvariant.insertNatSuccStuck, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.insertNatSuccStuckList, + { root := ``Ix.Kernel.CacheInvariant.insertNatSuccStuckList, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.insertNatSuccStuckArray, + { root := ``Ix.Kernel.CacheInvariant.insertNatSuccStuckArray, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSuccStuckCacheUpdate.fold_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.NatSuccStuckCacheUpdate.fold_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIter_entryHit, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIter_entryHit, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIter_entryKeyError, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIter_entryKeyError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIter_entryMiss, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIter_entryMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIterStep_linearHit, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIterStep_linearHit, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIterStep_linearError, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIterStep_linearError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIterStep_whnfError, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIterStep_whnfError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIterStep_afterWhnf, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIterStep_afterWhnf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccAfterWhnf_literal, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccAfterWhnf_literal, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccAfterWhnf_stuck, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccAfterWhnf_stuck, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.recordNatSuccStuck_eval, + { root := ``Ix.Kernel.RecM.recordNatSuccStuck_eval, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.recordNatSuccStuck_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.recordNatSuccStuck_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccPeel_keyError, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccPeel_keyError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccPeel_afterKey, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccPeel_afterKey, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccPeelAfterKey_hit, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccPeelAfterKey_hit, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccPeelAfterKey_miss, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccPeelAfterKey_miss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccPeelMiss_keyError, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccPeelMiss_keyError, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccPeelMiss_next, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccPeelMiss_next, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccAfterWhnf_succ, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccAfterWhnf_succ, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_succ_stuck, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_succ_stuck, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_succ_collapse, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_succ_collapse, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseSpine, + { root := ``Ix.Kernel.AmbientNat.succCollapseSpine, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseLinearMiss, + { root := ``Ix.Kernel.AmbientNat.succCollapseLinearMiss, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseWhnf, + { root := ``Ix.Kernel.AmbientNat.succCollapseWhnf, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseExtract, + { root := ``Ix.Kernel.AmbientNat.succCollapseExtract, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseStep, + { root := ``Ix.Kernel.AmbientNat.succCollapseStep, standardAxioms := standard, nativeAxioms := contextNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseKey, + { root := ``Ix.Kernel.AmbientNat.succCollapseKey, standardAxioms := standard, nativeAxioms := contextNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseMemoMiss, + { root := ``Ix.Kernel.AmbientNat.succCollapseMemoMiss, standardAxioms := standard, nativeAxioms := expressionNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseIter, + { root := ``Ix.Kernel.AmbientNat.succCollapseIter, standardAxioms := standard, nativeAxioms := contextNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succCollapseReduction, + { root := ``Ix.Kernel.AmbientNat.succCollapseReduction, standardAxioms := standard, nativeAxioms := contextNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, @@ -8032,34 +8019,34 @@ private def roots : Array RootAllowance := #[ -- provenance; the ghost loop state tracks Nat typing, arbitrary successor -- offsets, and every pending marker. Linear Nat.rec recognition remains -- behind its explicit oracle until inductive iota semantics instantiate it. - { root := ``Ix.Tc.WhnfCacheValid.natSuccStuck, + { root := ``Ix.Kernel.WhnfCacheValid.natSuccStuck, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheProvenance.whnfNatSuccStuck, + { root := ``Ix.Kernel.CacheProvenance.whnfNatSuccStuck, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSuccStuckWriteOracle.forWhnfCache, + { root := ``Ix.Kernel.RecM.NatSuccStuckWriteOracle.forWhnfCache, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natSucc_hasType, + { root := ``Ix.Kernel.RecM.natSucc_hasType, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natSuccSpine_tr, + { root := ``Ix.Kernel.RecM.natSuccSpine_tr, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccPeel_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccPeel_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccAfterWhnf_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccAfterWhnf_wf, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIterStep_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIterStep_wf, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccIter_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccIter_wf, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8073,66 +8060,66 @@ private def roots : Array RootAllowance := #[ -- while successful callback meaning reduces the former exact-arity -- assumption to canonical Nat/Bool result-shape separation. Nat.rec -- reflection and that Theory shape fact remain explicit. - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_succ_optional_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_succ_optional_wf, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.NatCollapseRequestCensus.suffix_eq_empty_of_result_shape, + ``Ix.Kernel.RecM.NatCollapseRequestCensus.suffix_eq_empty_of_result_shape, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatCollapseRequestCensus.of_no_suffix, + { root := ``Ix.Kernel.RecM.NatCollapseRequestCensus.of_no_suffix, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatCollapseRequestCensus.of_result_shape, + { root := ``Ix.Kernel.RecM.NatCollapseRequestCensus.of_result_shape, standardAxioms := standard, nativeAxioms := contextNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatCollapseRequestCensus.certify, + { root := ``Ix.Kernel.RecM.NatCollapseRequestCensus.certify, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatSuccIhStep_wf, + { root := ``Ix.Kernel.RecM.isNatSuccIhStep_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatSuccLinearRec_effect_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatSuccLinearRec_effect_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSuccLinearOracle.of_reflection, + { root := ``Ix.Kernel.RecM.NatSuccLinearOracle.of_reflection, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_collapse_optional_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_collapse_optional_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_collapse_optional_wf_of_boundaries, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_collapse_optional_wf_of_boundaries, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_stuck_short, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_stuck_short, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryReduceNatWithSuccMode_stuck_optional_wf, + { root := ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_stuck_optional_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_stuck_optional_wf_of_boundary, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_stuck_optional_wf_of_boundary, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_optional_wf_of_boundaries, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_optional_wf_of_boundaries, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.tryReduceNatWithSuccMode_optional_wf_of_lazy_boundaries, + ``Ix.Kernel.RecM.tryReduceNatWithSuccMode_optional_wf_of_lazy_boundaries, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.AmbientNat.succStuckReduction, + { root := ``Ix.Kernel.AmbientNat.succStuckReduction, standardAxioms := standard, nativeAxioms := contextNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, @@ -8140,257 +8127,257 @@ private def roots : Array RootAllowance := #[ -- K2a: suffix semantics reduce open-context cache validity to one explicit -- operational model. The recursive method table closes by induction from -- an exact one-layer contract split between WHNF and Infer/DefEq ownership. - { root := ``Ix.Tc.WhnfSuffixModel.keyRepresents, + { root := ``Ix.Kernel.WhnfSuffixModel.keyRepresents, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfSuffixModel.cacheWriteOracle, + { root := ``Ix.Kernel.WhnfSuffixModel.cacheWriteOracle, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.Methods.LayerWF.of_parts, + { root := ``Ix.Kernel.Methods.LayerWF.of_parts, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.Methods.Closed.of_parts, + { root := ``Ix.Kernel.Methods.Closed.of_parts, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.Methods.methodsOut_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.Methods.methodsOut_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.Methods.methodsN_wf, + { root := ``Ix.Kernel.Methods.methodsN_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.runRec_wf, + { root := ``Ix.Kernel.TcM.runRec_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, -- K2a also assigns exact meanings to the remaining cache families. A -- positive DefEq result carries Theory equality; negative results are -- intentionally vacuous for the one-way soundness claim. - { root := ``Ix.Tc.InferMeaning.mono, + { root := ``Ix.Kernel.InferMeaning.mono, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.InferMeaning.post, + { root := ``Ix.Kernel.InferMeaning.post, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.InferCacheValid.mono, + { root := ``Ix.Kernel.InferCacheValid.mono, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.inferHitOfMatches, + { root := ``Ix.Kernel.CacheInvariant.inferHitOfMatches, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.DefEqMeaning.mono, + { root := ``Ix.Kernel.DefEqMeaning.mono, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.DefEqMeaning.of_translations, + { root := ``Ix.Kernel.DefEqMeaning.of_translations, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.DefEqCacheValid.mono, + { root := ``Ix.Kernel.DefEqCacheValid.mono, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheProvenance.kernelWhnfMeaningOfMatches, + { root := ``Ix.Kernel.CacheProvenance.kernelWhnfMeaningOfMatches, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheProvenance.kernelInferMeaningOfMatches, + { root := ``Ix.Kernel.CacheProvenance.kernelInferMeaningOfMatches, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheProvenance.kernelDefEqMeaning, + { root := ``Ix.Kernel.CacheProvenance.kernelDefEqMeaning, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, -- K2b: production key executions now generate the canonical operational -- context witnesses. Physical inference/DefEq writes preserve every -- cache partition, including the rejection-only same-head failure set. - { root := ``Ix.Tc.CacheInvariant.insertInfer, + { root := ``Ix.Kernel.CacheInvariant.insertInfer, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.insertInferOnly, + { root := ``Ix.Kernel.CacheInvariant.insertInferOnly, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.insertDefEq, + { root := ``Ix.Kernel.CacheInvariant.insertDefEq, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.insertDefEqCheap, + { root := ``Ix.Kernel.CacheInvariant.insertDefEqCheap, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheInvariant.insertDefEqFailure, + { root := ``Ix.Kernel.CacheInvariant.insertDefEqFailure, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_empty, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_empty, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.whnfKey_ctx, + { root := ``Ix.Kernel.TcM.whnfKey_ctx, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.operationalWhnfContextKeys.represents, + { root := ``Ix.Kernel.operationalWhnfContextKeys.represents, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.operationalWhnfContextKeys.representsCtx, + { root := ``Ix.Kernel.operationalWhnfContextKeys.representsCtx, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ContextDigestSpec.execution, + { root := ``Ix.Kernel.ContextDigestSpec.execution, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ContextDigestSpec.StateValid, + { root := ``Ix.Kernel.ContextDigestSpec.StateValid, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ContextDigestSpec.memoValid, + { root := ``Ix.Kernel.ContextDigestSpec.memoValid, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ContextDigestSpec.preserves, + { root := ``Ix.Kernel.ContextDigestSpec.preserves, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_trivial, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_trivial, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_cacheHit, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_cacheHit, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_cacheMiss, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_cacheMiss, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_replay, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_replay, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.ContextAddrMemoValid, + { root := ``Ix.Kernel.TcM.ContextAddrMemoValid, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.ctxAddrForLbr_memoValid, + { root := ``Ix.Kernel.TcM.ctxAddrForLbr_memoValid, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.scopedOperationalWhnfContextKeys.represents, + { root := ``Ix.Kernel.scopedOperationalWhnfContextKeys.represents, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.scopedOperationalWhnfContextKeys.representsCtx, + { root := ``Ix.Kernel.scopedOperationalWhnfContextKeys.representsCtx, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.scopedOperationalWhnfContextKeys.digest_eq, + { root := ``Ix.Kernel.scopedOperationalWhnfContextKeys.digest_eq, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.scopedOperationalWhnfContextKeys.mem, + { root := ``Ix.Kernel.scopedOperationalWhnfContextKeys.mem, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.WhnfSuffixModel.operational, + { root := ``Ix.Kernel.WhnfSuffixModel.operational, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.inferKey_wf, + { root := ``Ix.Kernel.TcM.inferKey_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.inferKey_operational_matches_wf, + { root := ``Ix.Kernel.TcM.inferKey_operational_matches_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.inferWith_fullHit, + { root := ``Ix.Kernel.RecM.inferWith_fullHit, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.inferWith_inferOnlyHit, + { root := ``Ix.Kernel.RecM.inferWith_inferOnlyHit, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.InferCacheUpdate.full_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.InferCacheUpdate.full_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.InferCacheUpdate.inferOnly_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.InferCacheUpdate.inferOnly_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, -- The union-find frame and joint suffix model keep composite context-hash -- transport explicit for WHNF, inference, and DefEq. Collision-robust -- provenance constructors quantify over every supported address peer. - { root := ``Ix.Tc.TcM.withEquiv_eq, + { root := ``Ix.Kernel.TcM.withEquiv_eq, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.withEquiv_whnf_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.TcM.withEquiv_whnf_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.defEqCtxKey_wf, + { root := ``Ix.Kernel.TcM.defEqCtxKey_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.defEqCtxKey_operational_matches_wf, + { root := ``Ix.Kernel.TcM.defEqCtxKey_operational_matches_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.DefEqMeaning.of_addr_beq, + { root := ``Ix.Kernel.DefEqMeaning.of_addr_beq, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.DefEqMeaning.symm, + { root := ``Ix.Kernel.DefEqMeaning.symm, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KernelSuffixModel.toWhnfSuffixModel, + { root := ``Ix.Kernel.KernelSuffixModel.toWhnfSuffixModel, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KernelSuffixModel.operational, + { root := ``Ix.Kernel.KernelSuffixModel.operational, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ContextSuffixSemantics.whnf, + { root := ``Ix.Kernel.ContextSuffixSemantics.whnf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ContextSuffixSemantics.infer, + { root := ``Ix.Kernel.ContextSuffixSemantics.infer, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ContextSuffixSemantics.defEq, + { root := ``Ix.Kernel.ContextSuffixSemantics.defEq, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ScopedKernelSuffixModel.represents, + { root := ``Ix.Kernel.ScopedKernelSuffixModel.represents, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ScopedKernelSuffixModel.StateInScope, + { root := ``Ix.Kernel.ScopedKernelSuffixModel.StateInScope, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ScopedKernelSuffixModel.whnfTransport, + { root := ``Ix.Kernel.ScopedKernelSuffixModel.whnfTransport, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ScopedKernelSuffixModel.inferTransport, + { root := ``Ix.Kernel.ScopedKernelSuffixModel.inferTransport, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ScopedKernelSuffixModel.defEqTransport, + { root := ``Ix.Kernel.ScopedKernelSuffixModel.defEqTransport, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ScopedKernelSuffixModel.finiteOperational, + { root := ``Ix.Kernel.ScopedKernelSuffixModel.finiteOperational, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.ScopedKernelSuffixModel.toKernelSuffixModel, + { root := ``Ix.Kernel.ScopedKernelSuffixModel.toKernelSuffixModel, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KernelSuffixModel.finiteOperational, + { root := ``Ix.Kernel.KernelSuffixModel.finiteOperational, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheProvenance.kernelDefEqMeaningCanonical, + { root := ``Ix.Kernel.CacheProvenance.kernelDefEqMeaningCanonical, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KernelSuffixModel.inferProvenance, + { root := ``Ix.Kernel.KernelSuffixModel.inferProvenance, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KernelSuffixModel.defEqProvenance, + { root := ``Ix.Kernel.KernelSuffixModel.defEqProvenance, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.KernelSuffixModel.defEqFailureProvenance, + { root := ``Ix.Kernel.KernelSuffixModel.defEqFailureProvenance, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqCacheUpdate.full_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.DefEqCacheUpdate.full_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqCacheUpdate.cheap_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.DefEqCacheUpdate.cheap_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqCacheUpdate.failure_whnfStateInv, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.DefEqCacheUpdate.failure_whnfStateInv, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, -- First production K2 branches: both inference hit partitions, collision- -- safe DefEq address reflexivity, and a positive full DefEq hit including -- canonical ordering and its final union-find mutation. - { root := ``Ix.Tc.RecM.isDefEq_fullHit_true, + { root := ``Ix.Kernel.RecM.isDefEq_fullHit_true, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEq_fullHit_true_acceptance, + { root := ``Ix.Kernel.RecM.isDefEq_fullHit_true_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEq_addrEq_wf, + { root := ``Ix.Kernel.RecM.isDefEq_addrEq_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.inferWith_fullHit_acceptance, + { root := ``Ix.Kernel.RecM.inferWith_fullHit_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.inferWith_inferOnlyHit_acceptance, + { root := ``Ix.Kernel.RecM.inferWith_inferOnlyHit_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8398,11 +8385,11 @@ private def roots : Array RootAllowance := #[ -- The memoized proposition classifier closes proof irrelevance's sole -- auxiliary cache family. Positive hits and writes are tied to `Sort 0` -- through expression collision freedom and the explicit suffix model. - { root := ``Ix.Tc.RecM.isPropType_wf, + { root := ``Ix.Kernel.RecM.isPropType_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryProofIrrel_classifier_wf, + { root := ``Ix.Kernel.RecM.tryProofIrrel_classifier_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8410,20 +8397,20 @@ private def roots : Array RootAllowance := #[ -- Lazy delta is a bounded semantic state machine. These roots expose the -- pair invariant, the fuel-bounded closure, and the exact remaining -- obligations for one iteration and the stopped continuation. - { root := ``Ix.Tc.RecM.DefEqPairInvariant.refl, + { root := ``Ix.Kernel.RecM.DefEqPairInvariant.refl, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqPairInvariant.conclude, + { root := ``Ix.Kernel.RecM.DefEqPairInvariant.conclude, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.runDefEqLazyDelta_wf, + { root := ``Ix.Kernel.RecM.runDefEqLazyDelta_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqInnerAfterProofIrrelevance_wf, + { root := ``Ix.Kernel.RecM.isDefEqInnerAfterProofIrrelevance_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqAfterProofIrrelevance.ofLazyDelta, + { root := ``Ix.Kernel.RecM.DefEqAfterProofIrrelevance.ofLazyDelta, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, @@ -8431,84 +8418,84 @@ private def roots : Array RootAllowance := #[ -- literal/zero guards and both ordinary Nat-reduction attempts. Structural -- offset decomposition and the post-Nat reducer tiers remain explicit -- continuation contracts; negative recognizer results carry no semantics. - { root := ``Ix.Tc.RecM.isNatZero_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.isNatZero_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsNatZero.ofContext, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.IsNatZero.ofContext, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqOffset_wf, + { root := ``Ix.Kernel.RecM.tryDefEqOffset_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqOffset.ofContext, + { root := ``Ix.Kernel.RecM.TryDefEqOffset.ofContext, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepAfterOffsetMiss_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepAfterOffsetMiss_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaAfterOffsetMiss.ofNat, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaAfterOffsetMiss.ofNat, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepAfterNatMiss_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepAfterNatMiss_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaAfterNatMiss.ofNoAccel, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaAfterNatMiss.ofNoAccel, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.classifyDeltaHead_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.classifyDeltaHead_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepAfterAcceleratorMiss_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepAfterAcceleratorMiss_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.DefEqLazyDeltaAfterAcceleratorMiss.ofClassification, + ``Ix.Kernel.RecM.DefEqLazyDeltaAfterAcceleratorMiss.ofClassification, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryUnfoldProjApp_wf, + { root := ``Ix.Kernel.RecM.tryUnfoldProjApp_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepAfterDeltaClassification_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepAfterDeltaClassification_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.DefEqLazyDeltaAfterDeltaClassification.ofProjection, + ``Ix.Kernel.RecM.DefEqLazyDeltaAfterDeltaClassification.ofProjection, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.finishDefEqLazyDeltaStep_wf, + { root := ``Ix.Kernel.RecM.finishDefEqLazyDeltaStep_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepWithLeftDelta_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepWithLeftDelta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepWithRightDelta_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepWithRightDelta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.rankDeltaHead_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.rankDeltaHead_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepAfterProjectionMiss_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepAfterProjectionMiss_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaAfterProjectionMiss.ofRankDispatch, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaAfterProjectionMiss.ofRankDispatch, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepAfterSameHeadMiss_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepAfterSameHeadMiss_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaAfterSameHeadMiss.ofReduction, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaAfterSameHeadMiss.ofReduction, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8517,54 +8504,54 @@ private def roots : Array RootAllowance := #[ -- congruence, and the rejection-only failure-cache shell. A cache hit can -- only skip the comparison; every positive result still comes from the -- semantic same-head proof. - { root := ``Ix.Tc.RecM.allDefEqSpineArgs_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.allDefEqSpineArgs_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrAppSpine.defEq_of_zip, + { root := ``Ix.Kernel.RecM.TrAppSpine.defEq_of_zip, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.sameDefEqUniverses_sound, + { root := ``Ix.Kernel.RecM.sameDefEqUniverses_sound, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.constantHeadsDefEq, + { root := ``Ix.Kernel.RecM.constantHeadsDefEq, standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.trySameHeadSpine_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.trySameHeadSpine_wf, + standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrySameHeadSpine.ofResources, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.TrySameHeadSpine.ofResources, + standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.CacheEntry.defEqFailureReferencesAuthorized, + { root := ``Ix.Kernel.CacheEntry.defEqFailureReferencesAuthorized, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.DefEqFailureCacheResources.ofKernelSuffixModel, + { root := ``Ix.Kernel.DefEqFailureCacheResources.ofKernelSuffixModel, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isRegular_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.isRegular_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.trySameHeadSpineSpeculative_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.trySameHeadSpineSpeculative_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.trySameHeadSpineCached_wf, + { root := ``Ix.Kernel.RecM.trySameHeadSpineCached_wf, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TrySameHeadSpineCached.ofResources, + { root := ``Ix.Kernel.RecM.TrySameHeadSpineCached.ofResources, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defEqLazyDeltaStepWithEqualRank_wf, + { root := ``Ix.Kernel.RecM.defEqLazyDeltaStepWithEqualRank_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaEqualRank.ofPrefix, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaEqualRank.ofPrefix, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaEqualRank.ofKernelResources, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaEqualRank.ofKernelResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8573,20 +8560,20 @@ private def roots : Array RootAllowance := #[ -- path. Its only semantic input is an exact successful-run reflection; -- recursive equality is transported forward through the common successor -- suffix, without assuming offset injectivity or completeness. - { root := ``Ix.Tc.TcM.WF.withInvRunEq, + { root := ``Ix.Kernel.TcM.WF.withInvRunEq, standardAxioms := standardWithoutChoice, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natOffsetDecompose_state_wf, + { root := ``Ix.Kernel.RecM.natOffsetDecompose_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natOffsetRebuild_state_wf, + { root := ``Ix.Kernel.RecM.natOffsetRebuild_state_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqOffsetAfterCandidates_wf, + { root := ``Ix.Kernel.RecM.tryDefEqOffsetAfterCandidates_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqOffsetAfterCandidates.ofContext, + { root := ``Ix.Kernel.RecM.TryDefEqOffsetAfterCandidates.ofContext, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8595,33 +8582,33 @@ private def roots : Array RootAllowance := #[ -- general app probe reconstructs equality through both typed spines; -- structural congruence proves constants and variables directly and -- delegates matching projections to one execution-indexed helper contract. - { root := ``Ix.Tc.RecM.tryDefEqApp_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.tryDefEqApp_wf, + standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqApp.ofResources, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.TryDefEqApp.ofResources, + standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryStructuralCongruence_wf, + { root := ``Ix.Kernel.RecM.tryStructuralCongruence_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryStructuralCongruence.ofResources, + { root := ``Ix.Kernel.RecM.TryStructuralCongruence.ofResources, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqAfterLazyDeltaStopped_wf, + { root := ``Ix.Kernel.RecM.isDefEqAfterLazyDeltaStopped_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqAfterLazyDeltaStopped.ofResources, + { root := ``Ix.Kernel.RecM.DefEqAfterLazyDeltaStopped.ofResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaContext.ofKernelResources, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaContext.ofKernelResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqAfterProofIrrelevance.ofKernelResources, + { root := ``Ix.Kernel.RecM.DefEqAfterProofIrrelevance.ofKernelResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8629,11 +8616,11 @@ private def roots : Array RootAllowance := #[ -- The structural projection callback's bounded lazy-delta driver preserves -- the original projected semantics across delta steps, direct projection -- reduction, recursive comparison, and normal depth exhaustion. - { root := ``Ix.Tc.RecM.lazyDeltaProjReduction_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaProjReduction_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.LazyDeltaProjReduction.ofResources, + { root := ``Ix.Kernel.RecM.LazyDeltaProjReduction.ofResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8641,30 +8628,30 @@ private def roots : Array RootAllowance := #[ -- Direct projection reduction gets state/support closure from the proved -- no-acceleration helper and consults semantic reflection only for the -- exact successful execution that occurred. - { root := ``Ix.Tc.RecM.tryProjReduce_direct_wf, + { root := ``Ix.Kernel.RecM.tryProjReduce_direct_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryProjReduce.ofDirectResources, + { root := ``Ix.Kernel.RecM.TryProjReduce.ofDirectResources, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, -- The compact projection-loop delta step exposes its two lazy declaration -- classifications as a proved prefix; the exact branch continuation sees -- only their concrete results. - { root := ``Ix.Tc.RecM.lazyDeltaReductionStep_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStep_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.LazyDeltaReductionStep.ofClassification, + { root := ``Ix.Kernel.RecM.LazyDeltaReductionStep.ofClassification, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.lazyDeltaReductionStepAfterClassification_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStepAfterClassification_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.LazyDeltaReductionAfterClassification.ofActive, + ``Ix.Kernel.RecM.LazyDeltaReductionAfterClassification.ofActive, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.LazyDeltaReductionStep.ofActive, + { root := ``Ix.Kernel.RecM.LazyDeltaReductionStep.ofActive, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, @@ -8673,42 +8660,42 @@ private def roots : Array RootAllowance := #[ -- one- or two-sided unfolding, and equal ranks try same-head congruence -- before normalizing both sides. The final two roots assemble that branch -- proof with the already-audited classifier prefix. - { root := ``Ix.Tc.RecM.finishLazyDeltaReductionStep_wf, + { root := ``Ix.Kernel.RecM.finishLazyDeltaReductionStep_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.lazyDeltaReductionStepWithLeftDelta_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStepWithLeftDelta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.lazyDeltaReductionStepWithRightDelta_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStepWithRightDelta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.lazyDeltaReductionStepAfterSameHeadMiss_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStepAfterSameHeadMiss_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.lazyDeltaReductionStepWithEqualRank_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStepWithEqualRank_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.defRankId_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.defRankId_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.lazyDeltaReductionStepWithBothDelta_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStepWithBothDelta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.lazyDeltaReductionStepAfterActive_wf, + { root := ``Ix.Kernel.RecM.lazyDeltaReductionStepAfterActive_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.LazyDeltaReductionAfterActive.ofResources, + { root := ``Ix.Kernel.RecM.LazyDeltaReductionAfterActive.ofResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.LazyDeltaReductionStep.ofResources, + { root := ``Ix.Kernel.RecM.LazyDeltaReductionStep.ofResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8717,16 +8704,16 @@ private def roots : Array RootAllowance := #[ -- projection comparison, and structural-congruence projection branch from -- named lower reducers. The exact-run direct projection reflection is the -- remaining semantic boundary; the outer loop itself is no longer one. - { root := ``Ix.Tc.RecM.ProjectionDeltaClosureResources.loop, + { root := ``Ix.Kernel.RecM.ProjectionDeltaClosureResources.loop, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.LazyDeltaProjReduction.ofClosureResources, + { root := ``Ix.Kernel.RecM.LazyDeltaProjReduction.ofClosureResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.TryStructuralCongruence.ofProjectionDeltaResources, + ``Ix.Kernel.RecM.TryStructuralCongruence.ofProjectionDeltaResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8735,12 +8722,12 @@ private def roots : Array RootAllowance := #[ -- concrete projection loop and reuses that record's core/quick resources; -- only application-spine and final-WHNF contracts remain as sibling inputs. { root := - ``Ix.Tc.RecM.StoppedContinuationClosureResources.stopped, + ``Ix.Kernel.RecM.StoppedContinuationClosureResources.stopped, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, { root := - ``Ix.Tc.RecM.DefEqAfterLazyDeltaStopped.ofClosureResources, + ``Ix.Kernel.RecM.DefEqAfterLazyDeltaStopped.ofClosureResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8750,73 +8737,73 @@ private def roots : Array RootAllowance := #[ -- comparison and every constructor in the prefix are now exhaustive -- concrete proofs. The let roots include exact allocation, common-fvar -- body opening, context transport, and local-scope restoration. - { root := ``Ix.Tc.RecM.isDefEqWhnf_wf, + { root := ``Ix.Kernel.RecM.isDefEqWhnf_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqWhnf.ofPhases, + { root := ``Ix.Kernel.RecM.IsDefEqWhnf.ofPhases, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfApp_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfApp_wf, + standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqWhnfApp.ofResources, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.TryDefEqWhnfApp.ofResources, + standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.TcM.openLetWithFV_scope, + { root := ``Ix.Kernel.TcM.openLetWithFV_scope, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.withLctxScope_openLetWithFV_wf, + { root := ``Ix.Kernel.RecM.withLctxScope_openLetWithFV_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfLet_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfLet_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqWhnfLet.ofResources, + { root := ``Ix.Kernel.RecM.TryDefEqWhnfLet.ofResources, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isNatLike_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.isNatLike_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.natSuccOf_wf, + { root := ``Ix.Kernel.RecM.natSuccOf_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.NatSuccOf.ofResources, + { root := ``Ix.Kernel.RecM.NatSuccOf.ofResources, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqNatAfterLiteral_wf, + { root := ``Ix.Kernel.RecM.isDefEqNatAfterLiteral_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqNat_wf, + { root := ``Ix.Kernel.RecM.isDefEqNat_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfNat_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfNat_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqWhnfNat.ofResources, + { root := ``Ix.Kernel.RecM.TryDefEqWhnfNat.ofResources, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqWhnfAfterStructural_wf, + { root := ``Ix.Kernel.RecM.isDefEqWhnfAfterStructural_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqWhnfAfterStructural.ofNat, + { root := ``Ix.Kernel.RecM.IsDefEqWhnfAfterStructural.ofNat, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfStructural_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfStructural_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqWhnfStructural.ofResources, + { root := ``Ix.Kernel.RecM.TryDefEqWhnfStructural.ofResources, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8825,37 +8812,37 @@ private def roots : Array RootAllowance := #[ -- an explicit term builder. The builder's lifted source and generated #0 -- application are translated structurally before the recursive comparison -- is composed with Theory eta; the ordered reverse attempt uses symmetry. - { root := ``Ix.Tc.TcM.lift_whnf_wf_of_resources, + { root := ``Ix.Kernel.TcM.lift_whnf_wf_of_resources, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.compareEtaExpansion_wf, + { root := ``Ix.Kernel.RecM.compareEtaExpansion_wf, standardAxioms := standard, nativeAxioms := expressionNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryEtaExpansionAfterGuard_wf, + { root := ``Ix.Kernel.RecM.tryEtaExpansionAfterGuard_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryEtaExpansion_wf, + { root := ``Ix.Kernel.RecM.tryEtaExpansion_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfEtaAfterGuard_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfEtaAfterGuard_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfEta_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfEta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqWhnfEta.ofResources, + { root := ``Ix.Kernel.RecM.TryDefEqWhnfEta.ofResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqWhnfAfterNat_wf, + { root := ``Ix.Kernel.RecM.isDefEqWhnfAfterNat_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqWhnfAfterNat.ofEta, + { root := ``Ix.Kernel.RecM.IsDefEqWhnfAfterNat.ofEta, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8863,19 +8850,19 @@ private def roots : Array RootAllowance := #[ -- The final-WHNF String phase reuses the exact expansion plans proved for -- the earlier DefEq tier. Its optional result preserves the original -- two-way short-circuit order; reverse success is justified by symmetry. - { root := ``Ix.Tc.RecM.tryDefEqWhnfStringAfterGuard_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfStringAfterGuard_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfString_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfString_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqWhnfString.ofContext, + { root := ``Ix.Kernel.RecM.TryDefEqWhnfString.ofContext, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqWhnfAfterEta_wf, + { root := ``Ix.Kernel.RecM.isDefEqWhnfAfterEta_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqWhnfAfterEta.ofString, + { root := ``Ix.Kernel.RecM.IsDefEqWhnfAfterEta.ofString, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, @@ -8883,25 +8870,25 @@ private def roots : Array RootAllowance := #[ -- Proof irrelevance is concrete through the memoized proposition -- classifier; unit-like and structure-eta soundness remain separately -- named contracts until their exact inductive laws are supplied. - { root := ``Ix.Tc.RecM.isDefEqWhnfAfterUnit_wf, + { root := ``Ix.Kernel.RecM.isDefEqWhnfAfterUnit_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqWhnfAfterUnit.ofClassifier, + { root := ``Ix.Kernel.RecM.IsDefEqWhnfAfterUnit.ofClassifier, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqWhnfAfterStructEta_wf, + { root := ``Ix.Kernel.RecM.isDefEqWhnfAfterStructEta_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqWhnfAfterStructEta.ofUnitAndProof, + { root := ``Ix.Kernel.RecM.IsDefEqWhnfAfterStructEta.ofUnitAndProof, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.isDefEqWhnfAfterString_wf, + { root := ``Ix.Kernel.RecM.isDefEqWhnfAfterString_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.IsDefEqWhnfAfterString.ofStructEta, + { root := ``Ix.Kernel.RecM.IsDefEqWhnfAfterString.ofStructEta, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, @@ -8910,19 +8897,19 @@ private def roots : Array RootAllowance := #[ -- narrow unique-inhabitant law for that trusted zero-index, one-nullary- -- constructor shape; it does not recover the legacy whole-environment -- inductive oracle. - { root := ``Ix.Tc.RecM.isUnitLikeInductive_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.RecM.isUnitLikeInductive_wf, + standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.tryDefEqUnit_wf, + { root := ``Ix.Kernel.RecM.tryDefEqUnit_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.TryDefEqUnit.ofResources, + { root := ``Ix.Kernel.RecM.TryDefEqUnit.ofResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, - { root := ``Ix.Tc.RecM.DefEqLazyDeltaStep.ofKernelResources, + { root := ``Ix.Kernel.RecM.DefEqLazyDeltaStep.ofKernelResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := legacyWholeEnv }, @@ -8932,57 +8919,57 @@ private def roots : Array RootAllowance := #[ -- The positive structure classifier cannot manufacture semantic eta on -- its own, and every exported root remains quarantined from both legacy -- whole-environment and broad delta-authority paths. - { root := ``Ix.Tc.TrKExprS.prj_components, + { root := ``Ix.Kernel.TrKExprS.prj_components, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryEtaStructFields_wf, + { root := ``Ix.Kernel.RecM.tryEtaStructFields_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.etaExpansionBaseLoop_wf, + { root := ``Ix.Kernel.RecM.etaExpansionBaseLoop_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.etaExpansionBase_wf, + { root := ``Ix.Kernel.RecM.etaExpansionBase_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryEtaStructAfterTypes_wf, + { root := ``Ix.Kernel.RecM.tryEtaStructAfterTypes_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.normalizeEtaStructSource_wf, + { root := ``Ix.Kernel.RecM.normalizeEtaStructSource_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryEtaStructAfterConstructor_wf, + { root := ``Ix.Kernel.RecM.tryEtaStructAfterConstructor_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryEtaStructAfterNormalization_wf, + { root := ``Ix.Kernel.RecM.tryEtaStructAfterNormalization_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryEtaStruct_wf, + { root := ``Ix.Kernel.RecM.tryEtaStruct_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.tryDefEqWhnfStructEta_wf, + { root := ``Ix.Kernel.RecM.tryDefEqWhnfStructEta_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.TryDefEqWhnfStructEta.ofResources, + { root := ``Ix.Kernel.RecM.TryDefEqWhnfStructEta.ofResources, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, -- The final-WHNF phases are now assembled in exact production order. - { root := ``Ix.Tc.RecM.FinalWhnfClosureResources, + { root := ``Ix.Kernel.RecM.FinalWhnfClosureResources, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.FinalWhnfClosureResources.afterStructural, + { root := ``Ix.Kernel.RecM.FinalWhnfClosureResources.afterStructural, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.FinalWhnfClosureResources.finalWhnf, + { root := ``Ix.Kernel.RecM.FinalWhnfClosureResources.finalWhnf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, @@ -8990,36 +8977,36 @@ private def roots : Array RootAllowance := #[ -- Recursive DefEq closure: trusted finite expression references authorize -- only the two direct roots of an ordinary result entry. The complete -- inner tier then feeds the guarded public cache shell. - { root := ``Ix.Tc.CacheEntry.defEqReferencesAuthorized, + { root := ``Ix.Kernel.CacheEntry.defEqReferencesAuthorized, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.DefEqInner.WF, + { root := ``Ix.Kernel.RecM.DefEqInner.WF, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.isDefEq_wf, + { root := ``Ix.Kernel.RecM.isDefEq_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.DefEqClosureResources, + { root := ``Ix.Kernel.RecM.DefEqClosureResources, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.DefEqClosureResources.stopped, + { root := ``Ix.Kernel.RecM.DefEqClosureResources.stopped, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.DefEqClosureResources.lazyDelta, + { root := ``Ix.Kernel.RecM.DefEqClosureResources.lazyDelta, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.DefEqClosureResources.inner, + { root := ``Ix.Kernel.RecM.DefEqClosureResources.inner, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.DefEqClosureResources.entryPoint, + { root := ``Ix.Kernel.RecM.DefEqClosureResources.entryPoint, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.DefEqClosureResources.nextDefEq_wf, + { root := ``Ix.Kernel.RecM.DefEqClosureResources.nextDefEq_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, @@ -9027,21 +9014,21 @@ private def roots : Array RootAllowance := #[ -- Inference and DefEq consume the same predecessor table and suffix model; -- their fixed-universe pair closes before it is joined to the four WHNF -- fields. - { root := ``Ix.Tc.UncachedInference.Context.nextInfer_wf, + { root := ``Ix.Kernel.UncachedInference.Context.nextInfer_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.InferDefEqClosedAt, + { root := ``Ix.Kernel.Methods.InferDefEqClosedAt, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.InferDefEqClosureContext, + { root := ``Ix.Kernel.InferDefEqClosureContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.InferDefEqClosureContext.layer, + { root := ``Ix.Kernel.InferDefEqClosureContext.layer, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.InferDefEqClosureContext.closedAt, + { root := ``Ix.Kernel.InferDefEqClosureContext.closedAt, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, @@ -9049,29 +9036,29 @@ private def roots : Array RootAllowance := #[ -- Legacy all-depth six-field knot assembly under the canonical production -- cache stack. These roots remain audited as migration adapters, but the -- bounded public interfaces below are forbidden from depending on them. - { root := ``Ix.Tc.kernelCacheFallback, + { root := ``Ix.Kernel.kernelCacheFallback, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.kernelCacheSemantics_eq_k1, + { root := ``Ix.Kernel.kernelCacheSemantics_eq_k1, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.ClosedAt, + { root := ``Ix.Kernel.Methods.ClosedAt, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.ClosedAt.of_parts, + { root := ``Ix.Kernel.Methods.ClosedAt.of_parts, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.runRec_wfAt, + { root := ``Ix.Kernel.TcM.runRec_wfAt, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodClosureContext, + { root := ``Ix.Kernel.RecursiveMethodClosureContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodClosureContext.closedAt, + { root := ``Ix.Kernel.RecursiveMethodClosureContext.closedAt, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodClosureContext.methodsN, + { root := ``Ix.Kernel.RecursiveMethodClosureContext.methodsN, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, @@ -9081,7 +9068,7 @@ private def roots : Array RootAllowance := #[ -- an unbounded successor-sort chain. The replacement below separates the -- finite result footprint from fuel-indexed method-call domains. { root := - ``Ix.Tc.FiniteSupportBoundary.SyntaxInferenceResources.no_sort_source, + ``Ix.Kernel.FiniteSupportBoundary.SyntaxInferenceResources.no_sort_source, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := k1ForbiddenDependencies }, @@ -9089,40 +9076,40 @@ private def roots : Array RootAllowance := #[ -- method-table depths selected by this run's recursion fuel. The public -- adapters consume the terminal successor-layer domain and have no -- `sorryAx` dependency. - { root := ``Ix.Tc.Methods.CallDomain.empty_within, + { root := ``Ix.Kernel.Methods.CallDomain.empty_within, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.Methods.CallDomain.singletonInfer_within, + { root := ``Ix.Kernel.Methods.CallDomain.singletonInfer_within, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.Methods.methodsOut_wfAtOn, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.Methods.methodsOut_wfAtOn, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.Methods.CallScheduleAt.methodsN, + { root := ``Ix.Kernel.Methods.CallScheduleAt.methodsN, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.Methods.CallScheduleAt.nextSelected, + { root := ``Ix.Kernel.Methods.CallScheduleAt.nextSelected, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodRunContext, + { root := ``Ix.Kernel.RecursiveMethodRunContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.whnf.wf, + { root := ``Ix.Kernel.TcM.whnf.wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.infer.wf, + { root := ``Ix.Kernel.TcM.infer.wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.isDefEq.wf, + { root := ``Ix.Kernel.TcM.isDefEq.wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.Methods.SortSchedule.two, + { root := ``Ix.Kernel.Methods.SortSchedule.two, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.infer.sort_wf_bounded, + { root := ``Ix.Kernel.TcM.infer.sort_wf_bounded, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.infer.sort_wf_fuel_one, + { root := ``Ix.Kernel.TcM.infer.sort_wf_fuel_one, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, @@ -9130,382 +9117,382 @@ private def roots : Array RootAllowance := #[ -- K3 reconstructs the typed source translation from untyped/scoped -- checker ingress. These roots are usable before the final checkConst -- assembly and do not depend on its statement placeholder. - { root := ``Ix.Tc.KUniv.scoped_iff_toVLevel_wf, + { root := ``Ix.Kernel.KUniv.scoped_iff_toVLevel_wf, standardAxioms := propextOnly, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.PreTrKExprS.upgradeOfTyped, + { root := ``Ix.Kernel.PreTrKExprS.upgradeOfTyped, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TrKExprS.openFVarZero, + { root := ``Ix.Kernel.TrKExprS.openFVarZero, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Lean4Lean.VExpr.inst_subst_cons, + { root := ``Ix.Theory.Named.VExpr.inst_subst_cons, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RawCtxInterp.find?_inl, + { root := ``Ix.Kernel.RawCtxInterp.find?_inl, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RawCtxInterp.bvars_eq, + { root := ``Ix.Kernel.RawCtxInterp.bvars_eq, standardAxioms := propextOnly, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RawProjRel.none_substCompatible, + { root := ``Ix.Kernel.RawProjRel.none_substCompatible, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RawExprRel.toPre_of_scoped_aux, + { root := ``Ix.Kernel.RawExprRel.toPre_of_scoped_aux, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RawExprRel.toPre_of_scoped, + { root := ``Ix.Kernel.RawExprRel.toPre_of_scoped, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RawDeclRel.toPre_of_scope, + { root := ``Ix.Kernel.RawDeclRel.toPre_of_scope, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.PendingDecl.toPre_of_scope, + { root := ``Ix.Kernel.PendingDecl.toPre_of_scope, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TypeCheckEvidence.isType, + { root := ``Ix.Kernel.TypeCheckEvidence.isType, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.ValueCheckEvidence.hasType, + { root := ``Ix.Kernel.ValueCheckEvidence.hasType, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.StandaloneCheckEvidence.accepted, + { root := ``Ix.Kernel.StandaloneCheckEvidence.accepted, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.StandaloneCheckResult.accepted, + { root := ``Ix.Kernel.StandaloneCheckResult.accepted, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RawDeclRel.wfOfAccepted, + { root := ``Ix.Kernel.RawDeclRel.wfOfAccepted, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.PendingDecl.promoteOfAccepted, + { root := ``Ix.Kernel.PendingDecl.promoteOfAccepted, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.PendingDecl.checkResultAndPromote, + { root := ``Ix.Kernel.PendingDecl.checkResultAndPromote, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivParamsSeen_go_sound, + { root := ``Ix.Kernel.RecM.validateUnivParamsSeen_go_sound, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivParamsSeen_sound, + { root := ``Ix.Kernel.RecM.validateUnivParamsSeen_sound, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivRootsList_sound, + { root := ``Ix.Kernel.RecM.validateUnivRootsList_sound, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivRootsArray_sound, + { root := ``Ix.Kernel.RecM.validateUnivRootsArray_sound, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateExprWellScoped_go_sound, + { root := ``Ix.Kernel.RecM.validateExprWellScoped_go_sound, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateExprWellScoped_sound, + { root := ``Ix.Kernel.RecM.validateExprWellScoped_sound, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateConstWellScoped_sound, + { root := ``Ix.Kernel.RecM.validateConstWellScoped_sound, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.PendingDecl.toPre_of_validation, + { root := ``Ix.Kernel.PendingDecl.toPre_of_validation, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.PendingDecl.checkValidatedResultAndPromote, + { root := ``Ix.Kernel.PendingDecl.checkValidatedResultAndPromote, standardAxioms := standard, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivParamsSeen_go_frame, + { root := ``Ix.Kernel.RecM.validateUnivParamsSeen_go_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivParamsSeen_frame, + { root := ``Ix.Kernel.RecM.validateUnivParamsSeen_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivRootsList_frame, + { root := ``Ix.Kernel.RecM.validateUnivRootsList_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateUnivRootsArray_frame, + { root := ``Ix.Kernel.RecM.validateUnivRootsArray_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.getConst_frame, + { root := ``Ix.Kernel.TcM.getConst_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.hasConst_frame, + { root := ``Ix.Kernel.TcM.hasConst_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateExprWellScoped_go_frame, + { root := ``Ix.Kernel.RecM.validateExprWellScoped_go_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateExprWellScoped_frame, + { root := ``Ix.Kernel.RecM.validateExprWellScoped_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.validateConstWellScoped_frame, + { root := ``Ix.Kernel.RecM.validateConstWellScoped_frame, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.LazyFaultPreserves.withInferOnly, + { root := ``Ix.Kernel.TcM.LazyFaultPreserves.withInferOnly, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkTypePipeline_sound, + { root := ``Ix.Kernel.RecM.checkTypePipeline_sound, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkValuePipeline_sound, + { root := ``Ix.Kernel.RecM.checkValuePipeline_sound, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.FullInferenceWFAtOn.ofTypedIngress, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.Methods.FullInferenceWFAtOn.ofTypedIngress, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.Methods.FullInferenceWFAtOn.ofSingletonSort, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.Methods.FullInferenceWFAtOn.ofSingletonSort, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.StandalonePipelineResources.singletonSortAxiom, + { root := ``Ix.Kernel.StandalonePipelineResources.singletonSortAxiom, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkTypePipeline_bounded_sound, + { root := ``Ix.Kernel.RecM.checkTypePipeline_bounded_sound, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkValuePipeline_bounded_sound, + { root := ``Ix.Kernel.RecM.checkValuePipeline_bounded_sound, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConstMember_axiom_sound, + { root := ``Ix.Kernel.RecM.checkConstMember_axiom_sound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConstMember_defn_sound, + { root := ``Ix.Kernel.RecM.checkConstMember_defn_sound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConstMember_sound, + { root := ``Ix.Kernel.RecM.checkConstMember_sound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConstMember_validation_success, + { root := ``Ix.Kernel.RecM.checkConstMember_validation_success, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConstMember_pending_sound, + { root := ``Ix.Kernel.RecM.checkConstMember_pending_sound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConstMemberFresh_pending_sound, + { root := ``Ix.Kernel.RecM.checkConstMemberFresh_pending_sound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.StandaloneRoute.axiomRoute, + { root := ``Ix.Kernel.StandaloneRoute.axiomRoute, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConst_standalone_pending_sound, + { root := ``Ix.Kernel.RecM.checkConst_standalone_pending_sound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkNoUnsafeRefs_go_frame, + { root := ``Ix.Kernel.RecM.checkNoUnsafeRefs_go_frame, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkNoUnsafeRefs_frame, + { root := ``Ix.Kernel.RecM.checkNoUnsafeRefs_frame, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.KernelStateWF.rebaseWorld, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.KernelStateWF.rebaseWorld, + standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.WhnfStateInv.rebaseWorld, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.WhnfStateInv.rebaseWorld, + standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.reset_whnf_entry, + { root := ``Ix.Kernel.TcM.reset_whnf_entry, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.FullInferPost.of_typed, + { root := ``Ix.Kernel.FullInferPost.of_typed, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.WF.withInv, + { root := ``Ix.Kernel.TcM.WF.withInv, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferWith_fullHit_pre_acceptance, + { root := ``Ix.Kernel.RecM.inferWith_fullHit_pre_acceptance, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_sort_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_sort_full_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_var_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_var_full_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_fvar_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_fvar_full_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_const_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_const_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_nat_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_nat_full_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_str_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_str_full_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.FullInferenceStepContext, + { root := ``Ix.Kernel.FullInferenceStepContext, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_app_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_app_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.PreservesInferOnly.strengthenWFValue, + { root := ``Ix.Kernel.TcM.PreservesInferOnly.strengthenWFValue, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.PreservesInferOnly.withInferOnly, + { root := ``Ix.Kernel.TcM.PreservesInferOnly.withInferOnly, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.PreservesInferOnly.openBinder, + { root := ``Ix.Kernel.TcM.PreservesInferOnly.openBinder, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.PreservesInferOnly.inferKey, + { root := ``Ix.Kernel.TcM.PreservesInferOnly.inferKey, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.cacheInferResult_preservesInferOnly, + { root := ``Ix.Kernel.RecM.cacheInferResult_preservesInferOnly, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.withLctxScope_preservesInferOnly, + { root := ``Ix.Kernel.RecM.withLctxScope_preservesInferOnly, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.ensureForallDirect_preservesInferOnly, + { root := ``Ix.Kernel.RecM.ensureForallDirect_preservesInferOnly, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.ensureSortDirect_preservesInferOnly, + { root := ``Ix.Kernel.RecM.ensureSortDirect_preservesInferOnly, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.methodsOut_preservesInferOnly, + { root := ``Ix.Kernel.Methods.methodsOut_preservesInferOnly, standardAxioms := standardWithoutChoice, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.methodsN_preservesInferOnly, + { root := ``Ix.Kernel.Methods.methodsN_preservesInferOnly, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.PreservesInferOnly.isDefEq_full_wf, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.Methods.PreservesInferOnly.isDefEq_full_wf, + standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.openBinder_scope_base, + { root := ``Ix.Kernel.TcM.openBinder_scope_base, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.openBinder_pre_scope, + { root := ``Ix.Kernel.TcM.openBinder_pre_scope, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.KExpr.abstractFVarsSpec_instantiateRevSpec_singleton, + { root := ``Ix.Kernel.KExpr.abstractFVarsSpec_instantiateRevSpec_singleton, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TrKExprS.closeOpenedFVarZero, + { root := ``Ix.Kernel.TrKExprS.closeOpenedFVarZero, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.withLctxScope_openBinder_pre_wf, + { root := ``Ix.Kernel.RecM.withLctxScope_openBinder_pre_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_lam_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_lam_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_all_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_all_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.openLet_scope_base, + { root := ``Ix.Kernel.TcM.openLet_scope_base, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.openLet_pre_scope, + { root := ``Ix.Kernel.TcM.openLet_pre_scope, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.withLctxScope_openLet_pre_wf, + { root := ``Ix.Kernel.RecM.withLctxScope_openLet_pre_wf, standardAxioms := standard, nativeAxioms := expressionNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_let_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_let_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.ProjectionInference.FullWFAt.of_semantic_and_policy, + { root := ``Ix.Kernel.ProjectionInference.FullWFAt.of_semantic_and_policy, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_prj_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_prj_full_wf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_full_wf, + { root := ``Ix.Kernel.RecM.inferUncached_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferWith_full_wf, + { root := ``Ix.Kernel.RecM.inferWith_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.infer_full_wf, + { root := ``Ix.Kernel.RecM.infer_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.PreservesInferOnly.instantiateUnivParams, + { root := ``Ix.Kernel.TcM.PreservesInferOnly.instantiateUnivParams, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.inferUncached_preservesInferOnly, + { root := ``Ix.Kernel.RecM.inferUncached_preservesInferOnly, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.ProjectionInference.preservesInferOnlyAt, + { root := ``Ix.Kernel.ProjectionInference.preservesInferOnlyAt, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecM.infer_preservesInferOnly_of_whnf, + { root := ``Ix.Kernel.RecM.infer_preservesInferOnly_of_whnf, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, -- K3 closes the concrete operational policy and retains the old strong -- all-support inference roots below as compatibility artifacts. The -- public checker now consumes the bounded successor-layer resources above. - { root := ``Ix.Tc.Methods.next_preservesInferOnly, + { root := ``Ix.Kernel.Methods.next_preservesInferOnly, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.inferOnlyClosed, + { root := ``Ix.Kernel.Methods.inferOnlyClosed, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.methodsN_concrete_preservesInferOnly, + { root := ``Ix.Kernel.Methods.methodsN_concrete_preservesInferOnly, standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.FullInferenceWFAt, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.Methods.FullInferenceWFAt, + standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodClosureContext.fullInferenceContext, + { root := ``Ix.Kernel.RecursiveMethodClosureContext.fullInferenceContext, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodClosureContext.next_fullInferenceWFAt, + { root := ``Ix.Kernel.RecursiveMethodClosureContext.next_fullInferenceWFAt, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.Methods.methodsOut_fullInferenceWFAt, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.Methods.methodsOut_fullInferenceWFAt, + standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodClosureContext.methodsN_fullInferenceWFAt, + { root := ``Ix.Kernel.RecursiveMethodClosureContext.methodsN_fullInferenceWFAt, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.RecursiveMethodClosureContext.publicInfer_full_wf, + { root := ``Ix.Kernel.RecursiveMethodClosureContext.publicInfer_full_wf, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.checkConst.rollback_on_error, + { root := ``Ix.Kernel.TcM.checkConst.rollback_on_error, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.checkConst.rollback_preserves_kernel, + { root := ``Ix.Kernel.TcM.checkConst.rollback_preserves_kernel, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.TcM.checkConst.wf, + { root := ``Ix.Kernel.TcM.checkConst.wf, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.checkConst.rejected_of_no_decl_wf, + { root := ``Ix.Kernel.TcM.checkConst.rejected_of_no_decl_wf, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.checkConst.axiom_pending_sound, + { root := ``Ix.Kernel.TcM.checkConst.axiom_pending_sound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConstMemberFresh_scoped_pending_evidence, + { root := ``Ix.Kernel.RecM.checkConstMemberFresh_scoped_pending_evidence, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, @@ -9515,54 +9502,54 @@ private def roots : Array RootAllowance := #[ -- singleton-definition adapter consumes K3; inductive/recursor bodies keep -- their E2 oracle premise explicit. Quotients are audited as excluded from -- this authority rather than being silently admitted by the block theorem. - { root := ``Ix.Tc.ExactCheckBlock.rebaseWorld, + { root := ``Ix.Kernel.ExactCheckBlock.rebaseWorld, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.coordinatedBlockIfKind_success_trace, + { root := ``Ix.Kernel.RecM.coordinatedBlockIfKind_success_trace, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.classifyBlock_wf, + { root := ``Ix.Kernel.RecM.classifyBlock_wf, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.coordinatedBlockFor_some_preserves, + { root := ``Ix.Kernel.RecM.coordinatedBlockFor_some_preserves, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.CacheInvariant.replayCoordinatedMember, + { root := ``Ix.Kernel.CacheInvariant.replayCoordinatedMember, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.CacheInvariant.rejectsSuccessWithUntrustedMember, + { root := ``Ix.Kernel.CacheInvariant.rejectsSuccessWithUntrustedMember, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkCoordinatedBlock_accepted, + { root := ``Ix.Kernel.RecM.checkCoordinatedBlock_accepted, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkCoordinatedBlock_rejected, + { root := ``Ix.Kernel.RecM.checkCoordinatedBlock_rejected, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkConst_success_disposition, + { root := ``Ix.Kernel.RecM.checkConst_success_disposition, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.TcM.checkConst.blockDisposition, + { root := ``Ix.Kernel.TcM.checkConst.blockDisposition, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.certifySingletonDefinition, + { root := ``Ix.Kernel.RecM.certifySingletonDefinition, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.certifySingletonDefinitionScoped, + { root := ``Ix.Kernel.RecM.certifySingletonDefinitionScoped, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.RecM.certifyOracleBackedBlock, + { root := ``Ix.Kernel.RecM.certifyOracleBackedBlock, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.coordinatedBlockFor_quotient, + { root := ``Ix.Kernel.RecM.coordinatedBlockFor_quotient, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.Catalog.quotient_not_coordinated, + { root := ``Ix.Kernel.Catalog.quotient_not_coordinated, standardAxioms := propextOnly, forbiddenDependencies := boundedKnotForbiddenDependencies }, -- Quotients remain physically standalone, but semantic admission is one @@ -9570,74 +9557,74 @@ private def roots : Array RootAllowance := #[ -- equation. The production bridge inverts all four real checkQuot runs, -- converts digest equality through a finite collision scope, and publishes -- the completed transaction as one exact trusted-log event. Its temporary - -- Lean4Lean semantic input is an explicit theorem parameter, not an axiom. - { root := ``Ix.Tc.QuotientAdmissionStep.bind, + -- Ix.Theory.Named semantic input is an explicit theorem parameter, not an axiom. + { root := ``Ix.Kernel.QuotientAdmissionStep.bind, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientAdmissionStep.le, + { root := ``Ix.Kernel.QuotientAdmissionStep.le, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.catalogEntries, + { root := ``Ix.Kernel.QuotientBundleAdmission.catalogEntries, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.nameAssignments, + { root := ``Ix.Kernel.QuotientBundleAdmission.nameAssignments, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.toAddQuot, + { root := ``Ix.Kernel.QuotientBundleAdmission.toAddQuot, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.le, + { root := ``Ix.Kernel.QuotientBundleAdmission.le, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.quotType, + { root := ``Ix.Kernel.QuotientBundleAdmission.quotType, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.quotCtor, + { root := ``Ix.Kernel.QuotientBundleAdmission.quotCtor, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.quotLift, + { root := ``Ix.Kernel.QuotientBundleAdmission.quotLift, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.quotInd, + { root := ``Ix.Kernel.QuotientBundleAdmission.quotInd, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientBundleAdmission.quotientDefEq, + { root := ``Ix.Kernel.QuotientBundleAdmission.quotientDefEq, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientAdmission.wf, + { root := ``Ix.Kernel.QuotientAdmission.wf, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientAdmission.le, + { root := ``Ix.Kernel.QuotientAdmission.le, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkQuot_success_typeAddress, + { root := ``Ix.Kernel.RecM.checkQuot_success_typeAddress, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkQuot_success_levels, + { root := ``Ix.Kernel.RecM.checkQuot_success_levels, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.RecM.checkQuot_success_type, + { root := ``Ix.Kernel.RecM.checkQuot_success_type, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.CheckedQuotientBundle.toAdmission, + { root := ``Ix.Kernel.CheckedQuotientBundle.toAdmission, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientAdmission.entry, + { root := ``Ix.Kernel.QuotientAdmission.entry, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientAdmission.admit, + { root := ``Ix.Kernel.QuotientAdmission.admit, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.QuotientAdmission.newlyTrustedMember, + { root := ``Ix.Kernel.QuotientAdmission.newlyTrustedMember, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.CheckedQuotientBundle.admitAtomically, + { root := ``Ix.Kernel.CheckedQuotientBundle.admitAtomically, standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AmbientNat.E0.atomicAdmission, + { root := ``Ix.Kernel.AmbientNat.E0.atomicAdmission, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AmbientNat.E0.rejectsPrematureSuccess, + { root := ``Ix.Kernel.AmbientNat.E0.rejectsPrematureSuccess, standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, @@ -9645,125 +9632,125 @@ private def roots : Array RootAllowance := #[ -- domain, proves buildAnonWork is an exact duplicate-free partition, and -- composes successful items in a constructive collapsed-block order. The -- serial roots recover real successful checkConst calls from the public - -- result array before applying the named C2 success adapter. - { root := ``Ix.Tc.WorkCovers.covered, + -- result array before applying the named per-item success adapter. + { root := ``Ix.Kernel.WorkCovers.covered, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.WorkCovers.subjectOfCovered, + { root := ``Ix.Kernel.WorkCovers.subjectOfCovered, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.VerifyWorld.AcceptsAddress.mono, + { root := ``Ix.Kernel.VerifyWorld.AcceptsAddress.mono, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.WorkItemAccepted.mono, + { root := ``Ix.Kernel.WorkItemAccepted.mono, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.WorkItemAccepted.acceptsAddress, + { root := ``Ix.Kernel.WorkItemAccepted.acceptsAddress, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.WellFoundedBlocks.noTwoCycle, + { root := ``Ix.Kernel.WellFoundedBlocks.noTwoCycle, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.acceptedWorkset_subjectWF, + { root := ``Ix.Kernel.acceptedWorkset_subjectWF, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IxonEnv.dependencyCatalog_blockOf, + { root := ``Ix.Kernel.IxonEnv.dependencyCatalog_blockOf, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IxonEnv.dependencyCatalog_dependsOn_iff, + { root := ``Ix.Kernel.IxonEnv.dependencyCatalog_dependsOn_iff, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IxonExpr.DeclReference.target_mem_refs, + { root := ``Ix.Kernel.IxonExpr.DeclReference.target_mem_refs, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.IxonConstant.SemanticDependency.target_mem_refs, + { root := ``Ix.Kernel.IxonConstant.SemanticDependency.target_mem_refs, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.ExactAnonEntry.getConst, + { root := ``Ix.Kernel.ExactAnonEntry.getConst, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.ExactAnonEntry.constant_unique, + { root := ``Ix.Kernel.ExactAnonEntry.constant_unique, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.ExactAnonEntry.buildAnonWorkItem_eq, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.ExactAnonEntry.buildAnonWorkItem_eq, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.buildAnonWork_eq_expected, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.buildAnonWork_eq_expected, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.mem_expectedAnonWork_iff, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.mem_expectedAnonWork_iff, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkItem.ofConstantInfo_root, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkItem.ofConstantInfo_root, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkItem.covers_root, + { root := ``Ix.Kernel.AnonWorkItem.covers_root, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkItem.ofConstantInfo_primary_mem_targets, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkItem.ofConstantInfo_primary_mem_targets, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.source_covered, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.source_covered, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.covered_is_source, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.covered_is_source, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.expected_primary_mem_targets, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.expected_primary_mem_targets, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.ExactAnonEntry.blockOfAddr_eq_owner, + { root := ``Ix.Kernel.ExactAnonEntry.blockOfAddr_eq_owner, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.ExactAnonEntry.blockOfAddr_eq_self, + { root := ``Ix.Kernel.ExactAnonEntry.blockOfAddr_eq_self, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.matches_blockOfAddr, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.matches_blockOfAddr, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.expectedAnonWork_covers, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.expectedAnonWork_covers, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.expectedAnonWork_matchesCatalog, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.expectedAnonWork_matchesCatalog, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.buildAnonWork_exact, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.AnonWorkEnvWF.buildAnonWork_exact, + standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.finishAnonCheckItem_results, + { root := ``Ix.Kernel.finishAnonCheckItem_results, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.runAnonCheckItem_preserves_result, + { root := ``Ix.Kernel.runAnonCheckItem_preserves_result, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.runAnonCheckList_preserves_result, + { root := ``Ix.Kernel.runAnonCheckList_preserves_result, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.runAnonCheckItem_error_result, + { root := ``Ix.Kernel.runAnonCheckItem_error_result, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.serialChecksSucceeded_of_results, + { root := ``Ix.Kernel.serialChecksSucceeded_of_results, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.SerialChecksSucceeded.successfulStep, + { root := ``Ix.Kernel.SerialChecksSucceeded.successfulStep, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.SerialChecksSucceeded.allAccepted, + { root := ``Ix.Kernel.SerialChecksSucceeded.allAccepted, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.checkEnvAnon_eq_serial, + { root := ``Ix.Kernel.AnonWorkEnvWF.checkEnvAnon_eq_serial, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.checkEnvAnon_subjectWF, + { root := ``Ix.Kernel.AnonWorkEnvWF.checkEnvAnon_subjectWF, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.E1Fixture.exactSubjectsAndAssumptions, + { root := ``Ix.Kernel.E1Fixture.exactSubjectsAndAssumptions, standardAxioms := standardWithoutChoice, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.E1Fixture.droppingWorkItem_breaks_coverage, + { root := ``Ix.Kernel.E1Fixture.droppingWorkItem_breaks_coverage, standardAxioms := propextOnly, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.E1Fixture.unresolvedDependency_breaks_closure, + { root := ``Ix.Kernel.E1Fixture.unresolvedDependency_breaks_closure, standardAxioms := propextOnly, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.E1Fixture.cyclicStandalones_not_wellFounded, + { root := ``Ix.Kernel.E1Fixture.cyclicStandalones_not_wellFounded, standardAxioms := propextOnly, forbiddenDependencies := boundedKnotForbiddenDependencies }, @@ -9774,68 +9761,68 @@ private def roots : Array RootAllowance := #[ -- Separately, the certificate-backed replay adapter consumes already- -- installed member provenance, admits exact arrays idempotently, and gives -- all-block consumers a path which cannot reach oracle materialization. - { root := ``Ix.Tc.SupportedStandaloneResources.promotes, + { root := ``Ix.Kernel.SupportedStandaloneResources.promotes, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.SupportedBlockBodyResources.certify, + { root := ``Ix.Kernel.SupportedBlockBodyResources.certify, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.SupportedCheckRun.accepts, + { root := ``Ix.Kernel.SupportedCheckRun.accepts, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.SupportedCheckFragment.checkSuccessSound, + { root := ``Ix.Kernel.SupportedCheckFragment.checkSuccessSound, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.AnonWorkEnvWF.checkEnvAnon_supported_subjectWF, + { root := ``Ix.Kernel.AnonWorkEnvWF.checkEnvAnon_supported_subjectWF, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.CertificateBackedBlockResources.newlyTrustedMember, + { root := ``Ix.Kernel.CertificateBackedBlockResources.newlyTrustedMember, standardAxioms := standard, forbiddenDependencies := certificateBackedDriverForbiddenDependencies }, - { root := ``Ix.Tc.CertificateBackedBlockResources.accepts, - standardAxioms := standard, nativeAxioms := blake3Native, + { root := ``Ix.Kernel.CertificateBackedBlockResources.accepts, + standardAxioms := standard, forbiddenDependencies := certificateBackedDriverForbiddenDependencies }, - { root := ``Ix.Tc.CertificateBackedCheckFragment.checkSuccessSound, + { root := ``Ix.Kernel.CertificateBackedCheckFragment.checkSuccessSound, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := certificateBackedDriverForbiddenDependencies }, { root := - ``Ix.Tc.AnonWorkEnvWF.checkEnvAnon_certificateBacked_subjectWF, + ``Ix.Kernel.AnonWorkEnvWF.checkEnvAnon_certificateBacked_subjectWF, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := certificateBackedDriverForbiddenDependencies }, - { root := ``Ix.Tc.BooleanEnumerationFixture.subjectWF, + { root := ``Ix.Kernel.BooleanEnumerationFixture.subjectWF, standardAxioms := standard, nativeAxioms := booleanDriverNative, sorryOrigins := typingDebt, forbiddenDependencies := certificateBackedDriverForbiddenDependencies }, - { root := ``Ix.Tc.BooleanSerialized.subjectWF, + { root := ``Ix.Kernel.BooleanSerialized.subjectWF, standardAxioms := standard, nativeAxioms := serializedBooleanNative, sorryOrigins := typingDebt, forbiddenDependencies := certificateBackedDriverForbiddenDependencies }, - { root := ``Ix.Tc.SerializedLiteralBlobs.literalRoundTrip, + { root := ``Ix.Kernel.SerializedLiteralBlobs.literalRoundTrip, standardAxioms := standard, nativeAxioms := literalRoundTripNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.SerializedLiteralBlobs.malformedConstantRejected, + { root := ``Ix.Kernel.SerializedLiteralBlobs.malformedConstantRejected, standardAxioms := standard, nativeAxioms := malformedConstantNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.SerializedLiteralBlobs.malformedBlobRejected, + { root := ``Ix.Kernel.SerializedLiteralBlobs.malformedBlobRejected, standardAxioms := standard, nativeAxioms := malformedBlobNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, { root := - ``Ix.Tc.SupportedAcceptanceFixture.block_rejects_standalone_route, + ``Ix.Kernel.SupportedAcceptanceFixture.block_rejects_standalone_route, standardAxioms := propextOnly, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.SupportedAcceptanceFixture.block_rejects_wrong_route, + { root := ``Ix.Kernel.SupportedAcceptanceFixture.block_rejects_wrong_route, standardAxioms := propextOnly, forbiddenDependencies := scopedK2SForbiddenDependencies }, { root := - ``Ix.Tc.SupportedAcceptanceFixture.certificate_backed_definition_excluded, + ``Ix.Kernel.SupportedAcceptanceFixture.certificate_backed_definition_excluded, forbiddenDependencies := certificateBackedDriverForbiddenDependencies }, { root := - ``Ix.Tc.SupportedAcceptanceFixture.booleanFamilyBody_certified, + ``Ix.Kernel.SupportedAcceptanceFixture.booleanFamilyBody_certified, standardAxioms := standard, nativeAxioms := booleanFamilyBodyNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, @@ -9844,15 +9831,15 @@ private def roots : Array RootAllowance := #[ -- the joint suffix model explicit; the scoped checker roots below construct -- the finite model from their exact public execution certificate. Two -- exact Blake3 address inequalities remain explicit fixture inputs. - { root := ``Ix.Tc.PositiveFuelSort.methodContractAtFuelOne, + { root := ``Ix.Kernel.PositiveFuelSort.methodContractAtFuelOne, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.fullInferenceAtFuelOne, + { root := ``Ix.Kernel.PositiveFuelSort.fullInferenceAtFuelOne, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.pipelines_cover_concreteAxiom, + { root := ``Ix.Kernel.PositiveFuelSort.pipelines_cover_concreteAxiom, standardAxioms := standard, nativeAxioms := inferNative, sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, @@ -9862,26 +9849,26 @@ private def roots : Array RootAllowance := #[ -- schedule, instantiate `ScopedKernelSuffixModel.finiteOperational`, and -- retain `StateInScope` through successful semantic promotion. None may -- pass through the global suffix-model compatibility path. - { root := ``Ix.Tc.PositiveFuelSort.Checker.model, + { root := ``Ix.Kernel.PositiveFuelSort.Checker.model, standardAxioms := standard, nativeAxioms := contextNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.Checker.initialState_inv, + { root := ``Ix.Kernel.PositiveFuelSort.Checker.initialState_inv, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.Checker.inference_run, + { root := ``Ix.Kernel.PositiveFuelSort.Checker.inference_run, standardAxioms := standard, nativeAxioms := nameContextNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.Checker.public_requests, + { root := ``Ix.Kernel.PositiveFuelSort.Checker.public_requests, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.Checker.runAssumptions, + { root := ``Ix.Kernel.PositiveFuelSort.Checker.runAssumptions, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.Checker.publicContext, + { root := ``Ix.Kernel.PositiveFuelSort.Checker.publicContext, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - { root := ``Ix.Tc.PositiveFuelSort.Checker.checked_and_promoted, + { root := ``Ix.Kernel.PositiveFuelSort.Checker.checked_and_promoted, standardAxioms := standard, nativeAxioms := inductiveNative, sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, @@ -9890,20 +9877,20 @@ private def roots : Array RootAllowance := #[ -- and exact public checker executions for both verdicts. Its valid path -- carries a concrete acceptance result and promotion; its invalid path -- returns the malformed-universe error with exact rollback. - { root := ``Ix.Tc.AmbientNat.goodCheckResult, + { root := ``Ix.Kernel.AmbientNat.goodCheckResult, standardAxioms := standard, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.AmbientNat.initial_good_public, + { root := ``Ix.Kernel.AmbientNat.initial_good_public, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.AmbientNat.reset_bad_public, + { root := ``Ix.Kernel.AmbientNat.reset_bad_public, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := k1ForbiddenDependencies }, - { root := ``Ix.Tc.AmbientNat.publicCheckLifecycle, + { root := ``Ix.Kernel.AmbientNat.publicCheckLifecycle, standardAxioms := standard, nativeAxioms := inductiveNative, forbiddenDependencies := k1ForbiddenDependencies } ] -run_cmd Ix.Tc.Verify.Audit.check roots +run_cmd Ix.Kernel.Verify.Audit.check roots -end Ix.Tc.Verify.Audit.Completed +end Ix.Kernel.Verify.Audit.Completed diff --git a/Ix/Tc/Verify/Audit/Conditional.lean b/Ix/Kernel/Verify/Audit/Conditional.lean similarity index 51% rename from Ix/Tc/Verify/Audit/Conditional.lean rename to Ix/Kernel/Verify/Audit/Conditional.lean index 3e95368ec..2796dce90 100644 --- a/Ix/Tc/Verify/Audit/Conditional.lean +++ b/Ix/Kernel/Verify/Audit/Conditional.lean @@ -1,35 +1,35 @@ -import Ix.Tc.Verify.Audit.Completed -import Ix.Tc.Verify.Inductive.MutualRecursorAdmission +import Ix.Kernel.Verify.Audit.Completed +import Ix.Kernel.Verify.Inductive.MutualRecursorAdmission /-! -# Trust manifest for conditional `Ix.Tc.Verify` roots +# Trust manifest for conditional `Ix.Kernel.Verify` roots This manifest is deliberately separate from `Audit.Completed`. Its roots -may use only individually named witnesses from `Ix.Tc.Upstream.Pending`, and +may use only individually named witnesses from `Ix.Kernel.Frontier.Pending`, and the exact axiom audit fails as soon as either the pending or native footprint changes. Moving a theorem from here to `Completed` therefore requires removing every dependency on the quarantine namespace. -/ -namespace Ix.Tc.Verify.Audit.Conditional +namespace Ix.Kernel.Verify.Audit.Conditional -open Ix.Tc.Verify.Audit +open Ix.Kernel.Verify.Audit private def standard : Array Lean.Name := #[``propext, ``Classical.choice, ``Quot.sound] private def mutualRecursorPending : Array Lean.Name := #[ - ``Ix.Tc.Upstream.Pending.mutualTreePhysicalGenerationWF, - ``Ix.Tc.Upstream.Pending.mutualTreePhysicalRulePatternSound + ``Ix.Kernel.Frontier.Pending.mutualTreePhysicalGenerationWF, + ``Ix.Kernel.Frontier.Pending.mutualTreePhysicalRulePatternSound ] private def roots : Array RootAllowance := #[ - { root := ``Ix.Tc.MutualTreeFixture.mutualRecursorConditionalClosure, + { root := ``Ix.Kernel.MutualTreeFixture.mutualRecursorConditionalClosure, standardAxioms := standard, pendingAxioms := mutualRecursorPending, nativeAxioms := Completed.mutualRecursorConditionalNative } ] -run_cmd Ix.Tc.Verify.Audit.check roots +run_cmd Ix.Kernel.Verify.Audit.check roots -end Ix.Tc.Verify.Audit.Conditional +end Ix.Kernel.Verify.Audit.Conditional diff --git a/Ix/Tc/Verify/Audit/SorryFrontier.lean b/Ix/Kernel/Verify/Audit/SorryFrontier.lean similarity index 66% rename from Ix/Tc/Verify/Audit/SorryFrontier.lean rename to Ix/Kernel/Verify/Audit/SorryFrontier.lean index cad98b7ea..9658ca6f7 100644 --- a/Ix/Tc/Verify/Audit/SorryFrontier.lean +++ b/Ix/Kernel/Verify/Audit/SorryFrontier.lean @@ -1,21 +1,21 @@ -import Ix.Tc.Verify.Audit.Completed -import Ix.Tc.Verify.Audit.Statements +import Ix.Kernel.Verify.Audit.Completed +import Ix.Kernel.Verify.Audit.Statements /-! -# `Ix.Tc.Verify` source sorry frontier +# `Ix.Kernel.Verify` source sorry frontier -Fail the build if any declaration defined in an `Ix.Tc.Verify` source module +Fail the build if any declaration defined in an `Ix.Kernel.Verify` source module directly uses `sorryAx` — the elaborated form of a `sorry` token in that source. Reading it from the checked environment means `sorry` tokens in comments, string/char literals, or nested block comments cannot cause false positives. Filtering is by SOURCE MODULE via `getModuleIdxFor?`, not declaration name, so macro-emitted constants registered -under unqualified names are still attributed to their host module. Upstream -(Lean4Lean) `sorryAx` users are excluded because they live outside the -`Ix.Tc.Verify` namespace — the distinction `lake build --wfail` cannot make. +under unqualified names are still attributed to their host module. Named +specification (`Ix.Theory.Named`) `sorryAx` users are tracked separately because +their source modules are outside `Ix.Kernel.Verify`. Runs as a `run_cmd` at elaboration, next to the trust manifest it complements -(`Ix.Tc.Verify.Audit.check`): a build-time command, not an executable, so it +(`Ix.Kernel.Verify.Audit.check`): a build-time command, not an executable, so it never links the Rust FFI archives an exe over these modules would clash on. Importing the audit roots pulls the verified surface into scope; a declaration in a Verify module not reachable from those roots is not checked here. @@ -23,7 +23,7 @@ in a Verify module not reachable from those roots is not checked here. open Lean Lean.Elab.Command -namespace Ix.Tc.Verify.Audit +namespace Ix.Kernel.Verify.Audit /-- Constants referenced directly by a declaration's type or value, following the same cases as `Lean.collectAxioms`. The `Lean.` qualifiers are load-bearing: @@ -39,7 +39,7 @@ private def sorryFrontierDirectConstants : Lean.ConstantInfo → Array Lean.Name | .recInfo v => v.type.getUsedConstants | .inductInfo v => v.type.getUsedConstants ++ v.ctors -/-- Fail if any `Ix.Tc.Verify` source declaration directly references `sorryAx`. -/ +/-- Fail if any `Ix.Kernel.Verify` source declaration directly references `sorryAx`. -/ def checkSorryFrontier : CommandElabM Unit := do let env ← getEnv let moduleNames := env.allImportedModuleNames @@ -48,15 +48,15 @@ def checkSorryFrontier : CommandElabM Unit := do | none => none | some idx => let mod := moduleNames[idx.toNat]! - if (`Ix.Tc.Verify).isPrefixOf mod && (sorryFrontierDirectConstants info).contains ``sorryAx then some (mod, name) else none + if (`Ix.Kernel.Verify).isPrefixOf mod && (sorryFrontierDirectConstants info).contains ``sorryAx then some (mod, name) else none let offenders := offenders.toArray.qsort (fun a b => Lean.Name.lt a.1 b.1) if offenders.isEmpty then - logInfo m!"Ix.Tc.Verify sorry frontier OK: no source declaration uses sorryAx" + logInfo m!"Ix.Kernel.Verify sorry frontier OK: no source declaration uses sorryAx" else let body := String.intercalate "\n" (offenders.toList.map fun (mod, name) => s!" {mod} :: {name}") - throwError m!"Ix.Tc.Verify sorry frontier changed — {offenders.size} declaration(s) directly use sorryAx:\n{body}\nResolve the sorry, or extend the Ix.Tc.Verify.Audit trust manifest, only when the verification frontier intentionally changes." + throwError m!"Ix.Kernel.Verify sorry frontier changed — {offenders.size} declaration(s) directly use sorryAx:\n{body}\nResolve the sorry, or extend the Ix.Kernel.Verify.Audit trust manifest, only when the verification frontier intentionally changes." run_cmd checkSorryFrontier -end Ix.Tc.Verify.Audit +end Ix.Kernel.Verify.Audit diff --git a/Ix/Tc/Verify/Audit/Statements.lean b/Ix/Kernel/Verify/Audit/Statements.lean similarity index 50% rename from Ix/Tc/Verify/Audit/Statements.lean rename to Ix/Kernel/Verify/Audit/Statements.lean index 7c4fc3186..976bd7d50 100644 --- a/Ix/Tc/Verify/Audit/Statements.lean +++ b/Ix/Kernel/Verify/Audit/Statements.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Audit.Basic -import Ix.Tc.Verify.Audit.Completed -import Ix.Tc.Verify.Statements +import Ix.Kernel.Verify.Audit.Basic +import Ix.Kernel.Verify.Audit.Completed +import Ix.Kernel.Verify.Statements /-! # Trust manifest for the public checker statement frontier @@ -8,7 +8,7 @@ import Ix.Tc.Verify.Statements All seven roots are concrete results over the bounded production recursion schedule and checker. The three recursive-method adapters have no `sorryAx` dependency; the standalone and atomic-block checker roots retain only the two -named Lean4Lean typing lemmas through their singleton-definition branch. The +named Ix.Theory.Named typing lemmas through their singleton-definition branch. The E3-S root executes the exact Boolean serial workset and composes its actual runtime success gates with E1 and fixed certificate-backed E2 entries. This module permits no local statement placeholder and additionally forbids the @@ -16,33 +16,33 @@ Boolean/serialized roots from reaching oracle construction, restaging, or world materialization. -/ -namespace Ix.Tc.Verify.Audit.Statements +namespace Ix.Kernel.Verify.Audit.Statements -open Ix.Tc.Verify.Audit +open Ix.Kernel.Verify.Audit private def standard : Array Lean.Name := #[``propext, ``Classical.choice, ``Quot.sound] private def forallEInv : Lean.Name := - ``Lean4Lean.VEnv.IsDefEqU.forallE_inv_stratified -private def sortInv : Lean.Name := ``Lean4Lean.VEnv.IsDefEqU.sort_inv + ``Ix.Theory.Named.VEnv.IsDefEqU.forallE_inv_stratified +private def sortInv : Lean.Name := ``Ix.Theory.Named.VEnv.IsDefEqU.sort_inv private def checkerDebt : Array Lean.Name := #[forallEInv, sortInv] private def legacyWholeEnv : Array Lean.Name := #[ - ``Ix.Tc.AddKInduct, - ``Ix.Tc.AddKInduct.to_addInduct, - ``Ix.Tc.TrKEnv', - ``Ix.Tc.TrKEnv + ``Ix.Kernel.AddKInduct, + ``Ix.Kernel.AddKInduct.to_addInduct, + ``Ix.Kernel.TrKEnv', + ``Ix.Kernel.TrKEnv ] private def legacyAllDepthKnot : Array Lean.Name := #[ - ``Ix.Tc.RecursiveMethodClosureContext, - ``Ix.Tc.RecursiveMethodClosureContext.closedAt, - ``Ix.Tc.RecursiveMethodClosureContext.methodsN, - ``Ix.Tc.RecursiveMethodClosureContext.fullInferenceContext, - ``Ix.Tc.RecursiveMethodClosureContext.next_fullInferenceWFAt, - ``Ix.Tc.RecursiveMethodClosureContext.methodsN_fullInferenceWFAt, - ``Ix.Tc.RecursiveMethodClosureContext.publicInfer_full_wf + ``Ix.Kernel.RecursiveMethodClosureContext, + ``Ix.Kernel.RecursiveMethodClosureContext.closedAt, + ``Ix.Kernel.RecursiveMethodClosureContext.methodsN, + ``Ix.Kernel.RecursiveMethodClosureContext.fullInferenceContext, + ``Ix.Kernel.RecursiveMethodClosureContext.next_fullInferenceWFAt, + ``Ix.Kernel.RecursiveMethodClosureContext.methodsN_fullInferenceWFAt, + ``Ix.Kernel.RecursiveMethodClosureContext.publicInfer_full_wf ] private def forbidden : Array Lean.Name := @@ -52,14 +52,14 @@ private def forbidden : Array Lean.Name := library, but must not manufacture a global suffix model or pass through the old proposition-classifier/run-context path. -/ private def legacyGlobalSuffix : Array Lean.Name := #[ - ``Ix.Tc.KernelSuffixModel, - ``Ix.Tc.ScopedKernelSuffixModel.toKernelSuffixModel, - ``Ix.Tc.PropositionClassifierContext, - ``Ix.Tc.RecursiveMethodRunContext, - ``Ix.Tc.TcM.whnf.wf_legacy, - ``Ix.Tc.TcM.infer.wf_legacy, - ``Ix.Tc.TcM.isDefEq.wf_legacy, - ``Ix.Tc.TcM.checkConst.wf_legacy + ``Ix.Kernel.KernelSuffixModel, + ``Ix.Kernel.ScopedKernelSuffixModel.toKernelSuffixModel, + ``Ix.Kernel.PropositionClassifierContext, + ``Ix.Kernel.RecursiveMethodRunContext, + ``Ix.Kernel.TcM.whnf.wf_legacy, + ``Ix.Kernel.TcM.infer.wf_legacy, + ``Ix.Kernel.TcM.isDefEq.wf_legacy, + ``Ix.Kernel.TcM.checkConst.wf_legacy ] private def scopedForbidden : Array Lean.Name := @@ -69,79 +69,71 @@ private def scopedForbidden : Array Lean.Name := not regain the retired residual-oracle/world-materialization path through an adapter refactor. -/ private def oracleWorldMaterialization : Array Lean.Name := #[ - ``Ix.Tc.VerifyWorld.admitOracle, - ``Ix.Tc.VerifyWorld.le_admitOracle, - ``Ix.Tc.OracleBlockCertificate.admit, - ``Ix.Tc.OracleBlockCertificate.admitState, - ``Ix.Tc.RecM.certifyOracleBackedBlock, - ``Ix.Tc.RecM.certifyOracleBackedAdmittedBlock, - ``Ix.Tc.SingletonFamilyCatalogLink.oracle, - ``Ix.Tc.SingletonRecursorCatalogLink.oracle, - ``Ix.Tc.InductiveOracle.reindex, - ``Ix.Tc.InductiveOracle.restageMissing + ``Ix.Kernel.VerifyWorld.admitOracle, + ``Ix.Kernel.VerifyWorld.le_admitOracle, + ``Ix.Kernel.OracleBlockCertificate.admit, + ``Ix.Kernel.OracleBlockCertificate.admitState, + ``Ix.Kernel.RecM.certifyOracleBackedBlock, + ``Ix.Kernel.RecM.certifyOracleBackedAdmittedBlock, + ``Ix.Kernel.SingletonFamilyCatalogLink.oracle, + ``Ix.Kernel.SingletonRecursorCatalogLink.oracle, + ``Ix.Kernel.InductiveOracle.reindex, + ``Ix.Kernel.InductiveOracle.restageMissing ] private def certificateBackedForbidden : Array Lean.Name := scopedForbidden ++ oracleWorldMaterialization private def runNative : Array Lean.Name := #[ - nativeAxiom `Blake3 - `Blake3.HasherOps.hash._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Expr - `Ix.Tc.KExpr.mkVar._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Level - `Ix.Tc.KUniv.mkSucc._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Monad - `Ix.Tc.TcM.ctxAddrForLbrUncached._native.native_decide.ax_3 + nativeAxiom `Ix.Kernel.Expr + `Ix.Kernel.KExpr.mkVar._native.native_decide.ax_1, + nativeAxiom `Ix.Kernel.Level + `Ix.Kernel.KUniv.mkSucc._native.native_decide.ax_1, ] private def checkConstNative : Array Lean.Name := #[ - nativeAxiom `Blake3 - `Blake3.HasherOps.hash._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Expr - `Ix.Tc.KExpr.mkVar._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Level - `Ix.Tc.KUniv.mkSucc._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Monad - `Ix.Tc.TcM.ctxAddrForLbrUncached._native.native_decide.ax_3, + nativeAxiom `Ix.Kernel.Expr + `Ix.Kernel.KExpr.mkVar._native.native_decide.ax_1, + nativeAxiom `Ix.Kernel.Level + `Ix.Kernel.KUniv.mkSucc._native.native_decide.ax_1, nativeAxiom `Ix.Environment `Ix.Name.mkStr._native.native_decide.ax_1, - nativeAxiom `Ix.Tc.Inductive - `Ix.Tc.RecM.canonicalAuxOrder._native.native_decide.ax_9 + nativeAxiom `Ix.Kernel.Inductive + `Ix.Kernel.RecM.canonicalAuxOrder._native.native_decide.ax_9 ] private def roots : Array RootAllowance := #[ - { root := ``Ix.Tc.TcM.whnf.wf, + { root := ``Ix.Kernel.TcM.whnf.wf, standardAxioms := standard, nativeAxioms := runNative, forbiddenDependencies := scopedForbidden }, - { root := ``Ix.Tc.TcM.infer.wf, + { root := ``Ix.Kernel.TcM.infer.wf, standardAxioms := standard, nativeAxioms := runNative, forbiddenDependencies := scopedForbidden }, - { root := ``Ix.Tc.TcM.isDefEq.wf, + { root := ``Ix.Kernel.TcM.isDefEq.wf, standardAxioms := standard, nativeAxioms := runNative, forbiddenDependencies := scopedForbidden }, - { root := ``Ix.Tc.TcM.checkConst.wf, + { root := ``Ix.Kernel.TcM.checkConst.wf, standardAxioms := standard, nativeAxioms := checkConstNative, sorryOrigins := checkerDebt, forbiddenDependencies := scopedForbidden }, - { root := ``Ix.Tc.TcM.checkConst.blockDisposition, + { root := ``Ix.Kernel.TcM.checkConst.blockDisposition, standardAxioms := standard, nativeAxioms := checkConstNative, sorryOrigins := checkerDebt, forbiddenDependencies := scopedForbidden }, - { root := ``Ix.Tc.BooleanEnumerationFixture.subjectWF, + { root := ``Ix.Kernel.BooleanEnumerationFixture.subjectWF, standardAxioms := standard, - nativeAxioms := Ix.Tc.Verify.Audit.Completed.booleanDriverNative, + nativeAxioms := Ix.Kernel.Verify.Audit.Completed.booleanDriverNative, sorryOrigins := checkerDebt, forbiddenDependencies := certificateBackedForbidden }, - { root := ``Ix.Tc.BooleanSerialized.subjectWF, + { root := ``Ix.Kernel.BooleanSerialized.subjectWF, standardAxioms := standard, - nativeAxioms := Ix.Tc.Verify.Audit.Completed.serializedBooleanNative, + nativeAxioms := Ix.Kernel.Verify.Audit.Completed.serializedBooleanNative, sorryOrigins := checkerDebt, forbiddenDependencies := certificateBackedForbidden } ] -run_cmd Ix.Tc.Verify.Audit.check roots +run_cmd Ix.Kernel.Verify.Audit.check roots -end Ix.Tc.Verify.Audit.Statements +end Ix.Kernel.Verify.Audit.Statements diff --git a/Ix/Tc/Verify/Cache.lean b/Ix/Kernel/Verify/Cache.lean similarity index 99% rename from Ix/Tc/Verify/Cache.lean rename to Ix/Kernel/Verify/Cache.lean index 307893095..d35ea1e8a 100644 --- a/Ix/Tc/Verify/Cache.lean +++ b/Ix/Kernel/Verify/Cache.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Decl -import Ix.Tc.Verify.Env -import Ix.Tc.Verify.Monad -import Ix.Tc.Verify.Support +import Ix.Kernel.Verify.Decl +import Ix.Kernel.Verify.Env +import Ix.Kernel.Verify.Monad +import Ix.Kernel.Verify.Support import Std.Data.HashMap.Lemmas import Std.Data.HashSet.Lemmas @@ -56,7 +56,7 @@ does not treat an untagged concrete lookup as trusted merely because it was listed here. -/ -namespace Ix.Tc +namespace Ix.Kernel /-! ## Lookup authority -/ @@ -100,7 +100,7 @@ end LookupScope /-- The pending target can be acquired as the subject, but cannot be used by inference, delta unfolding, definitional equality, or a semantic cache hit. -/ theorem PendingDecl.lookup_isolation {trProj : RawProjRel} - {world : VerifyWorld} {target : KId .anon} {d : Lean4Lean.VDecl} + {world : VerifyWorld} {target : KId .anon} {d : Ix.Theory.Named.VDecl} (h : PendingDecl trProj world target d) : (LookupScope.standalone target).Allows world .subject target ∧ ¬(LookupScope.standalone target).Allows world .semantic target := by @@ -492,7 +492,7 @@ theorem mono {semantics : CacheSemantics} pending target. This is the cache-hit half of the self-unfolding barrier. -/ theorem pending_isolation {semantics : CacheSemantics} {authority : CacheAuthority} {support : RunSupport} {entry : CacheEntry} - {trProj : RawProjRel} {target : KId .anon} {d : Lean4Lean.VDecl} + {trProj : RawProjRel} {target : KId .anon} {d : Ix.Theory.Named.VDecl} (hpending : PendingDecl trProj authority.world target d) (hentry : ¬entry.SubjectScoped) (h : CacheProvenance semantics authority support entry) : @@ -507,7 +507,7 @@ theorem pending_isolation {semantics : CacheSemantics} target: there is no active-block authority left. -/ theorem pending_isolation_stable {semantics : CacheSemantics} {authority : CacheAuthority} {support : RunSupport} {entry : CacheEntry} - {trProj : RawProjRel} {target : KId .anon} {d : Lean4Lean.VDecl} + {trProj : RawProjRel} {target : KId .anon} {d : Ix.Theory.Named.VDecl} (hstable : ∀ id, ¬authority.active id) (hpending : PendingDecl trProj authority.world target d) (h : CacheProvenance semantics authority support entry) : @@ -1606,4 +1606,4 @@ theorem reset_cache_frame (s : TcState m) : end TcM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/Acceptance.lean b/Ix/Kernel/Verify/Check/Acceptance.lean similarity index 96% rename from Ix/Tc/Verify/Check/Acceptance.lean rename to Ix/Kernel/Verify/Check/Acceptance.lean index 37fc999c4..39eaf2b06 100644 --- a/Ix/Tc/Verify/Check/Acceptance.lean +++ b/Ix/Kernel/Verify/Check/Acceptance.lean @@ -1,6 +1,8 @@ -import Ix.Tc.Verify.Check.DeclarationValidation -import Ix.Tc.Verify.Infer.SortTypes -import Ix.Tc.Verify.State +import Ix.Kernel.Verify.Check.DeclarationValidation +import Ix.Kernel.Verify.Infer.SortTypes +import Ix.Kernel.Verify.State + +open Ix.Theory (VLevel) /-! # Standalone declaration acceptance and promotion @@ -18,9 +20,9 @@ This keeps K3's critical implication explicit: No field below assumes a `VDecl.WF` transition. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstant VDecl VDefVal VEnv VExpr) +open Ix.Theory.Named (VConstant VDecl VDefVal VEnv VExpr) /-! ## Semantic results of the two checker pipelines -/ @@ -89,14 +91,14 @@ Only the value-check result is needed by Theory's `VDefVal.WF`; keeping both premises makes the operational acceptance boundary exact. -/ inductive StandaloneCheckEvidence (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) : VDecl → Prop - | axiom {ci : Lean4Lean.VConstVal} : + | axiom {ci : Ix.Theory.Named.VConstVal} : TypeCheckEvidence trProj world support ci.uvars [] ci.type → StandaloneCheckEvidence trProj world support (.axiom ci) - | defn {ci : Lean4Lean.VDefVal} : + | defn {ci : Ix.Theory.Named.VDefVal} : TypeCheckEvidence trProj world support ci.uvars [] ci.type → ValueCheckEvidence world ci.uvars [] ci.value ci.type → StandaloneCheckEvidence trProj world support (.def ci) - | opaque {ci : Lean4Lean.VDefVal} : + | opaque {ci : Ix.Theory.Named.VDefVal} : TypeCheckEvidence trProj world support ci.uvars [] ci.type → ValueCheckEvidence world ci.uvars [] ci.value ci.type → StandaloneCheckEvidence trProj world support (.opaque ci) @@ -258,4 +260,4 @@ theorem checkValidatedResultAndPromote end PendingDecl -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BinderRoundTrip.lean b/Ix/Kernel/Verify/Check/BinderRoundTrip.lean similarity index 95% rename from Ix/Tc/Verify/Check/BinderRoundTrip.lean rename to Ix/Kernel/Verify/Check/BinderRoundTrip.lean index 4321a91af..cc6b44acb 100644 --- a/Ix/Tc/Verify/Check/BinderRoundTrip.lean +++ b/Ix/Kernel/Verify/Check/BinderRoundTrip.lean @@ -1,17 +1,17 @@ -import Ix.Tc.Verify.Check.PreTranslationScopes -import Ix.Tc.Verify.Infer.BinderClosing +import Ix.Kernel.Verify.Check.PreTranslationScopes +import Ix.Kernel.Verify.Infer.BinderClosing /-! # Binder open/close round trip -The Lean4Lean checker closes a freshly opened binder with +The Ix.Theory.Named checker closes a freshly opened binder with `FVarsIn.abstract_instantiate1`. Ix uses address-carrying `KExpr` smart constructors and separate cached walkers, so K3 needs the corresponding pure syntax theorem for `instantiateRevSpec` followed by singleton `abstractFVarsSpec`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KExpr @@ -33,9 +33,9 @@ namespace PreTrKExprS /-- A pre-translation can mention only fvars registered by its `KVLCtx`. -/ theorem fvarAbsent - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} - {Delta : KVLCtx} {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsource : PreTrKExprS env uvars nameOf trProj Delta source sourceV) {target : FVarId} (hfresh : target ∉ Delta.fvars) : source.FVarAbsent target := by @@ -216,10 +216,10 @@ syntax. The opening bounds justify the pure round trip; the closing bounds justify the production abstraction walker whose translation theorem supplies the typed result. -/ theorem TrKExprS.closeOpenedFVarZero - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} - {Delta : KVLCtx} {decl : Lean4Lean.VLocalDecl} - {body bodyOpen : KExpr .anon} {bodyV : Lean4Lean.VExpr} + {Delta : KVLCtx} {decl : Ix.Theory.Named.VLocalDecl} + {body bodyOpen : KExpr .anon} {bodyV : Ix.Theory.Named.VExpr} {fv : FVarId} {deps : List FVarId} {name : Mode.anon.F Name} (H : TrKExprS env uvars nameOf trProj ((some (fv, deps), decl) :: Delta) bodyOpen bodyV) @@ -239,4 +239,4 @@ theorem TrKExprS.closeOpenedFVarZero rw [hround] at hclosed exact hclosed -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockAcceptance.lean b/Ix/Kernel/Verify/Check/BlockAcceptance.lean similarity index 96% rename from Ix/Tc/Verify/Check/BlockAcceptance.lean rename to Ix/Kernel/Verify/Check/BlockAcceptance.lean index 111168bf5..d0d14584e 100644 --- a/Ix/Tc/Verify/Check/BlockAcceptance.lean +++ b/Ix/Kernel/Verify/Check/BlockAcceptance.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.Acceptance -import Ix.Tc.Verify.Check.BlockCache +import Ix.Kernel.Verify.Check.Acceptance +import Ix.Kernel.Verify.Check.BlockCache /-! # Atomic coordinated-block acceptance @@ -14,13 +14,13 @@ Legacy ambient inductive-family and recursor blocks may still be admitted relative to an explicit `InductiveOracle`. Certificate-backed paths instead use `SemanticBlockTransitionCertificate` for an exact Theory-environment extension or `ExistingSemanticBlockCertificate` for members already installed -by that extension. Definition admission is local, but Lean4Lean currently has +by that extension. Definition admission is local, but Ix.Theory.Named currently has no mutual-definition `VDecl`, so the constructive definition theorem below is deliberately restricted to production's singleton definition blocks. A multi-definition block is not silently decomposed into independent claims. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact promotion specialized to the ordered member array of one physical block. Array order remains available through `ExactCheckBlock`; the trust @@ -118,7 +118,7 @@ member array are fixed by the theorem statement. -/ structure SemanticBlockTransitionCertificate (trProj : RawProjRel) (world : VerifyWorld) (block : KId .anon) (members : Array (KId .anon)) (kind : CheckBlockKind) - (afterVEnv : Lean4Lean.VEnv) : Prop where + (afterVEnv : Ix.Theory.Named.VEnv) : Prop where exactBlock : ExactCheckBlock world block members kind fresh : ∀ ⦃id⦄, id ∈ members → ¬world.trusted id envLE : world.venv ≤ afterVEnv @@ -132,7 +132,7 @@ namespace SemanticBlockTransitionCertificate preserving all immutable ghost inputs. -/ def admittedWorld {trProj : RawProjRel} {world : VerifyWorld} {block : KId .anon} {members : Array (KId .anon)} - {kind : CheckBlockKind} {afterVEnv : Lean4Lean.VEnv} + {kind : CheckBlockKind} {afterVEnv : Ix.Theory.Named.VEnv} (certificate : SemanticBlockTransitionCertificate trProj world block members kind afterVEnv) : VerifyWorld where catalog := world.catalog @@ -153,7 +153,7 @@ def admittedWorld {trProj : RawProjRel} {world : VerifyWorld} /-- The explicit semantic transaction is a monotone world extension. -/ theorem le_admittedWorld {trProj : RawProjRel} {world : VerifyWorld} {block : KId .anon} {members : Array (KId .anon)} - {kind : CheckBlockKind} {afterVEnv : Lean4Lean.VEnv} + {kind : CheckBlockKind} {afterVEnv : Ix.Theory.Named.VEnv} (certificate : SemanticBlockTransitionCertificate trProj world block members kind afterVEnv) : world ≤ certificate.admittedWorld := @@ -163,7 +163,7 @@ theorem le_admittedWorld {trProj : RawProjRel} {world : VerifyWorld} and its per-member provenance. -/ theorem admit {trProj : RawProjRel} {world : VerifyWorld} {block : KId .anon} {members : Array (KId .anon)} - {kind : CheckBlockKind} {afterVEnv : Lean4Lean.VEnv} + {kind : CheckBlockKind} {afterVEnv : Ix.Theory.Named.VEnv} (certificate : SemanticBlockTransitionCertificate trProj world block members kind afterVEnv) (hrel : TrustedCatalogRel trProj world) : @@ -180,7 +180,7 @@ theorem admit {trProj : RawProjRel} {world : VerifyWorld} semantic transition. -/ theorem admitState {trProj : RawProjRel} {world : VerifyWorld} {block : KId .anon} {members : Array (KId .anon)} - {kind : CheckBlockKind} {afterVEnv : Lean4Lean.VEnv} + {kind : CheckBlockKind} {afterVEnv : Ix.Theory.Named.VEnv} {state : TcState .anon} (certificate : SemanticBlockTransitionCertificate trProj world block members kind afterVEnv) @@ -208,7 +208,7 @@ Every exact physical member must instead provide the same per-constant, per-rule, and per-pattern provenance consumed by trusted lookups. The important generated-recursor use case is deliberately two-phase. -Lean4Lean's certified family transaction has already installed the generated +Ix.Theory.Named's certified family transaction has already installed the generated recursor and equations in `world.venv`; the separate Ix recursor block remains untrusted until its production comparison succeeds. -/ structure ExistingSemanticBlockCertificate (trProj : RawProjRel) @@ -252,7 +252,7 @@ theorem le_admittedWorld {trProj : RawProjRel} {world : VerifyWorld} (certificate : ExistingSemanticBlockCertificate trProj world block members kind) : world ≤ certificate.admittedWorld := - ⟨rfl, rfl, rfl, fun {_} hold => Or.inr hold, Lean4Lean.VEnv.LE.rfl⟩ + ⟨rfl, rfl, rfl, fun {_} hold => Or.inr hold, Ix.Theory.Named.VEnv.LE.rfl⟩ /-- Commit the exact physical block using only its already-installed semantic entries. No `InductiveOracle` is constructed or consumed. -/ @@ -404,7 +404,7 @@ of standalone declarations would be unsound for mutual references until the Theory exposes a matching atomic declaration form. -/ structure SingletonDefinitionCertificate (trProj : RawProjRel) (world : VerifyWorld) (block id : KId .anon) - (decl : Lean4Lean.VDecl) : Prop where + (decl : Ix.Theory.Named.VDecl) : Prop where exactBlock : ExactCheckBlock world block #[id] .defn pending : PendingDecl trProj world id decl accepted : StandaloneAccepted world.venv decl @@ -415,7 +415,7 @@ namespace SingletonDefinitionCertificate transition. Every accepted member (the singleton) is trusted, and the exact promotion theorem rules out unrelated trust growth. -/ theorem admit {trProj : RawProjRel} {world : VerifyWorld} - {block id : KId .anon} {decl : Lean4Lean.VDecl} + {block id : KId .anon} {decl : Ix.Theory.Named.VDecl} {state : TcState .anon} (certificate : SingletonDefinitionCertificate trProj world block id decl) (hstate : BlockStateWF trProj state world) : @@ -446,4 +446,4 @@ theorem admit {trProj : RawProjRel} {world : VerifyWorld} end SingletonDefinitionCertificate -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockCache.lean b/Ix/Kernel/Verify/Check/BlockCache.lean similarity index 98% rename from Ix/Tc/Verify/Check/BlockCache.lean rename to Ix/Kernel/Verify/Check/BlockCache.lean index bec3e2b7d..777a0c4ed 100644 --- a/Ix/Tc/Verify/Check/BlockCache.lean +++ b/Ix/Kernel/Verify/Check/BlockCache.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.BlockIdentity +import Ix.Kernel.Verify.Check.BlockIdentity /-! # Coordinated block-cache closure @@ -13,7 +13,7 @@ recovers acceptance of the exact immutable block and therefore cannot certify a proper subset or treat the block address as a declaration. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace CacheAuthority @@ -121,4 +121,4 @@ theorem rejectsSuccessWithUntrustedMember end CacheInvariant -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockClassification.lean b/Ix/Kernel/Verify/Check/BlockClassification.lean similarity index 99% rename from Ix/Tc/Verify/Check/BlockClassification.lean rename to Ix/Kernel/Verify/Check/BlockClassification.lean index c74b7b60c..aa91fd77a 100644 --- a/Ix/Tc/Verify/Check/BlockClassification.lean +++ b/Ix/Kernel/Verify/Check/BlockClassification.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.BlockRouting +import Ix.Kernel.Verify.Check.BlockRouting /-! # Coordinated block classification @@ -11,7 +11,7 @@ successful classifier result is exactly that kind. Both success and error paths preserve the caller's invariant through lazy ingress. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM.BlockClassFlags @@ -214,4 +214,4 @@ theorem classifyBlock_success_exact end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockDefinition.lean b/Ix/Kernel/Verify/Check/BlockDefinition.lean similarity index 94% rename from Ix/Tc/Verify/Check/BlockDefinition.lean rename to Ix/Kernel/Verify/Check/BlockDefinition.lean index 395f9a177..573636b84 100644 --- a/Ix/Tc/Verify/Check/BlockDefinition.lean +++ b/Ix/Kernel/Verify/Check/BlockDefinition.lean @@ -1,13 +1,13 @@ -import Ix.Tc.Verify.Check.BlockTransaction -import Ix.Tc.Verify.Check.BlockClassification -import Ix.Tc.Verify.Check.ScopedStandaloneDriver -import Ix.Tc.Verify.Check.StandaloneDriver +import Ix.Kernel.Verify.Check.BlockTransaction +import Ix.Kernel.Verify.Check.BlockClassification +import Ix.Kernel.Verify.Check.ScopedStandaloneDriver +import Ix.Kernel.Verify.Check.StandaloneDriver /-! # Singleton definition blocks The production definition-block branch iterates `checkConstMemberFresh` over -the complete array and then publishes the peak DefEq depth. Lean4Lean does +the complete array and then publishes the peak DefEq depth. Ix.Theory.Named does not yet have an atomic mutual-definition declaration, so the constructive E0 bridge is intentionally the singleton specialization. It extracts the actual member run from `checkClassifiedBlock`, invokes K3 without performing @@ -15,7 +15,7 @@ K3's standalone promotion, and packages that evidence for the enclosing atomic block transaction. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -66,7 +66,7 @@ theorem certifySingletonDefinition model.keys.uvars calls (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {block requested id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} {before after : TcState .anon} + {decl : Ix.Theory.Named.VDecl} {before after : TcState .anon} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -124,7 +124,7 @@ theorem certifySingletonDefinitionScoped (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {block requested id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} {before after : TcState .anon} + {decl : Ix.Theory.Named.VDecl} {before after : TcState .anon} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -170,4 +170,4 @@ theorem certifySingletonDefinitionScoped end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockExecution.lean b/Ix/Kernel/Verify/Check/BlockExecution.lean similarity index 99% rename from Ix/Tc/Verify/Check/BlockExecution.lean rename to Ix/Kernel/Verify/Check/BlockExecution.lean index 93a1474aa..06e076f2a 100644 --- a/Ix/Tc/Verify/Check/BlockExecution.lean +++ b/Ix/Kernel/Verify/Check/BlockExecution.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.BlockAcceptance +import Ix.Kernel.Verify.Check.BlockAcceptance /-! # Coordinated block execution traces @@ -17,7 +17,7 @@ The semantic admission theorem remains in `BlockAcceptance`; this module is the operational half needed to join that transaction to production. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -380,4 +380,4 @@ theorem withBlockCheckResult {trProj : RawProjRel} end BlockStateWF -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockIdentity.lean b/Ix/Kernel/Verify/Check/BlockIdentity.lean similarity index 99% rename from Ix/Tc/Verify/Check/BlockIdentity.lean rename to Ix/Kernel/Verify/Check/BlockIdentity.lean index c8b60906f..b3e6bc8ef 100644 --- a/Ix/Tc/Verify/Check/BlockIdentity.lean +++ b/Ix/Kernel/Verify/Check/BlockIdentity.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Driver -import Ix.Tc.Verify.State +import Ix.Kernel.Driver +import Ix.Kernel.Verify.State /-! # Coordinated checker-block identity @@ -18,7 +18,7 @@ to any of them. In particular, a catalogued member is still untrusted until the atomic acceptance theorem admits the complete array. -/ -namespace Ix.Tc +namespace Ix.Kernel /-! ## Concrete/world block agreement -/ @@ -277,4 +277,4 @@ end MatchesBlockCatalog end AnonWorkItem -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockNatFixture.lean b/Ix/Kernel/Verify/Check/BlockNatFixture.lean similarity index 97% rename from Ix/Tc/Verify/Check/BlockNatFixture.lean rename to Ix/Kernel/Verify/Check/BlockNatFixture.lean index 84aa6407b..f53bbba2d 100644 --- a/Ix/Tc/Verify/Check/BlockNatFixture.lean +++ b/Ix/Kernel/Verify/Check/BlockNatFixture.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.PublicBlocks -import Ix.Tc.Verify.NatFixture +import Ix.Kernel.Verify.Check.PublicBlocks +import Ix.Kernel.Verify.NatFixture /-! # Concrete Nat block fixture for E0 @@ -10,7 +10,7 @@ the adversarial cache rule without pretending that E2 has already connected the production inductive checker to the oracle. -/ -namespace Ix.Tc.AmbientNat.E0 +namespace Ix.Kernel.AmbientNat.E0 /-- Ordered production member array for the Nat family. -/ def blockMembers : Array (KId .anon) := #[natId, zeroId, succId] @@ -118,4 +118,4 @@ theorem rejectsPrematureSuccess CacheInvariant.rejectsSuccessWithUntrustedMember exactBlock (id := zeroId) (by simp [blockMembers]) (fun h => h) -end Ix.Tc.AmbientNat.E0 +end Ix.Kernel.AmbientNat.E0 diff --git a/Ix/Tc/Verify/Check/BlockOracle.lean b/Ix/Kernel/Verify/Check/BlockOracle.lean similarity index 95% rename from Ix/Tc/Verify/Check/BlockOracle.lean rename to Ix/Kernel/Verify/Check/BlockOracle.lean index 265453653..744ae1c60 100644 --- a/Ix/Tc/Verify/Check/BlockOracle.lean +++ b/Ix/Kernel/Verify/Check/BlockOracle.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.BlockTransaction -import Ix.Tc.Verify.Inductive.Certificate +import Ix.Kernel.Verify.Check.BlockTransaction +import Ix.Kernel.Verify.Inductive.Certificate /-! # Oracle-backed inductive and recursor blocks @@ -7,7 +7,7 @@ import Ix.Tc.Verify.Inductive.Certificate E0 proves the transaction and cache ordering around production block checks. The semantic meaning of a successful inductive/recursor body remains the explicit E2b boundary: E2b must connect the actual Ix validators and generated -recursor patterns to an `InductiveOracle`. The Lean4Lean +recursor patterns to an `InductiveOracle`. The Ix.Theory.Named `CertifiedGenerationTransaction` supplies the Theory-owned portion of that future construction, but cannot determine Ix addresses, member arrays, or checker execution on its own. @@ -16,7 +16,7 @@ This module packages exactly that remaining boundary and ties it to the real classified-body trace. It introduces no unindexed “block succeeded” axiom. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The E2b resources which remain after E0 has fixed the exact physical array and production classifier kind. The post-state uses temporary block @@ -90,4 +90,4 @@ theorem certifyOracleBackedAdmittedBlock end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockRouteFrame.lean b/Ix/Kernel/Verify/Check/BlockRouteFrame.lean similarity index 98% rename from Ix/Tc/Verify/Check/BlockRouteFrame.lean rename to Ix/Kernel/Verify/Check/BlockRouteFrame.lean index bf2096a85..6fd9ad8f7 100644 --- a/Ix/Tc/Verify/Check/BlockRouteFrame.lean +++ b/Ix/Kernel/Verify/Check/BlockRouteFrame.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.BlockClassification +import Ix.Kernel.Verify.Check.BlockClassification /-! # State framing for successful coordinated routing @@ -9,7 +9,7 @@ if routing returns a coordinated block, every lazy lookup and classification step preserves the caller's invariant up to the exact post-route state. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -121,4 +121,4 @@ theorem coordinatedBlockFor_some_preserves end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockRouting.lean b/Ix/Kernel/Verify/Check/BlockRouting.lean similarity index 99% rename from Ix/Tc/Verify/Check/BlockRouting.lean rename to Ix/Kernel/Verify/Check/BlockRouting.lean index 07598a2da..210f2e0fd 100644 --- a/Ix/Tc/Verify/Check/BlockRouting.lean +++ b/Ix/Kernel/Verify/Check/BlockRouting.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.BlockIdentity -import Ix.Tc.Verify.Infer.Constants +import Ix.Kernel.Verify.Check.BlockIdentity +import Ix.Kernel.Verify.Infer.Constants /-! # Soundness of production block routing @@ -11,7 +11,7 @@ successful concrete parent lookup is the exact catalogued inductive and that the constructor itself belongs to that parent's exact member array. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -295,4 +295,4 @@ theorem coordinatedBlockFor_some_exact end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BlockTransaction.lean b/Ix/Kernel/Verify/Check/BlockTransaction.lean similarity index 98% rename from Ix/Tc/Verify/Check/BlockTransaction.lean rename to Ix/Kernel/Verify/Check/BlockTransaction.lean index 0ddaf4644..86a4e96b0 100644 --- a/Ix/Tc/Verify/Check/BlockTransaction.lean +++ b/Ix/Kernel/Verify/Check/BlockTransaction.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.BlockExecution +import Ix.Kernel.Verify.Check.BlockExecution /-! # Atomic coordinated-block transactions @@ -16,12 +16,12 @@ There are exactly two currently supported semantic sources: * an inductive or recursor block, relative to the explicit inductive oracle which E2 must construct from the corresponding production checker. -Lean4Lean does not yet expose an atomic mutual-definition declaration, so no +Ix.Theory.Named does not yet expose an atomic mutual-definition declaration, so no constructor below decomposes a multi-definition production block into a sequence of stronger semantic claims. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The complete checker invariant while one exact coordinated block is active. Only structural block caches may use the additional member @@ -105,7 +105,7 @@ inductive BlockAdmissionEvidence (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (block : KId .anon) : Array (KId .anon) → CheckBlockKind → Prop | singletonDefinition {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} : + {decl : Ix.Theory.Named.VDecl} : PendingDecl trProj world id decl → StandaloneCheckResult trProj world support id concrete decl → BlockAdmissionEvidence trProj world support block #[id] .defn @@ -400,4 +400,4 @@ theorem checkCoordinatedBlock_rejected end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/BoundedPipelines.lean b/Ix/Kernel/Verify/Check/BoundedPipelines.lean similarity index 96% rename from Ix/Tc/Verify/Check/BoundedPipelines.lean rename to Ix/Kernel/Verify/Check/BoundedPipelines.lean index 30055a116..8fd014a12 100644 --- a/Ix/Tc/Verify/Check/BoundedPipelines.lean +++ b/Ix/Kernel/Verify/Check/BoundedPipelines.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Check.CheckerEvidence -import Ix.Tc.Verify.Check.FullInferenceKnot -import Ix.Tc.Verify.Check.RecursiveMethodPolicy -import Ix.Tc.Verify.RecursiveMethods.CallDomains +import Ix.Kernel.Verify.Check.CheckerEvidence +import Ix.Kernel.Verify.Check.FullInferenceKnot +import Ix.Kernel.Verify.Check.RecursiveMethodPolicy +import Ix.Kernel.Verify.RecursiveMethods.CallDomains /-! # Bounded standalone-checker pipelines @@ -19,7 +19,7 @@ type/value calls made by one concrete standalone declaration and the bounded follow-up calls made on their results. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace Methods @@ -43,7 +43,7 @@ def FullInferenceWFAtOn (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (calls : CallDomain) (methods : Methods .anon) : Prop := ∀ {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr}, + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr}, calls.infer source → s.inferOnly = false → PreTrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → @@ -70,7 +70,7 @@ theorem ofTypedIngress uvars calls methods) (policy : methods.PreservesInferOnly) (upgrade : ∀ {Delta : KVLCtx} {source : KExpr .anon} - {sourceV : Lean4Lean.VExpr}, + {sourceV : Ix.Theory.Named.VExpr}, calls.infer source → PreTrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) : @@ -127,7 +127,7 @@ theorem methodsOut (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (calls : CallDomain) : Methods.FullInferenceWFAtOn semantics trProj world support uvars calls - (Ix.Tc.methodsOut : Methods .anon) := by + (Ix.Kernel.methodsOut : Methods .anon) := by intro Delta s source sourceV hcall hpolicy hsource exact TcM.WF.throw fun _ => hpolicy @@ -155,12 +155,12 @@ structure StandalonePipelineResources valueInfer : ∀ {value declaredType}, valueSources value declaredType → calls.infer value typeWhnf : ∀ {Delta : KVLCtx} {source : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {inferred : KExpr .anon}, + {sourceV : Ix.Theory.Named.VExpr} {inferred : KExpr .anon}, typeSources source → FullInferPost trProj world support uvars Delta source sourceV inferred → calls.AdmitsEnsureSortDirect inferred valueDefEq : ∀ {Delta : KVLCtx} {value declaredType : KExpr .anon} - {valueV : Lean4Lean.VExpr} {inferred : KExpr .anon}, + {valueV : Ix.Theory.Named.VExpr} {inferred : KExpr .anon}, valueSources value declaredType → FullInferPost trProj world support uvars Delta value valueV inferred → calls.isDefEq inferred declaredType @@ -259,7 +259,7 @@ private theorem ensureSortDirect_wfAtOn {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {calls : Methods.CallDomain} {methods : Methods .anon} {Delta : KVLCtx} {s : TcState .anon} {input : KExpr .anon} - {inputV : Lean4Lean.VExpr} + {inputV : Ix.Theory.Named.VExpr} (hmethods : Methods.WFAtOn .noAccel semantics trProj world support uvars calls (Methods.next methods)) (hresources : SortComponentResources support) @@ -320,7 +320,7 @@ theorem checkTypePipeline_bounded_sound calls (Methods.next methods)) (hpolicyMethods : (Methods.next methods).PreservesInferOnly) {Delta : KVLCtx} {s after : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceCall : resources.typeSources source) (hsource : PreTrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) @@ -402,7 +402,7 @@ theorem checkValuePipeline_bounded_sound calls (Methods.next methods)) {Delta : KVLCtx} {s after : TcState .anon} {value declaredType : KExpr .anon} - {valueV declaredTypeV : Lean4Lean.VExpr} + {valueV declaredTypeV : Ix.Theory.Named.VExpr} (hvalueCall : resources.valueSources value declaredType) (hvalue : PreTrKExprS world.venv uvars world.nameOf trProj Delta value valueV) @@ -471,4 +471,4 @@ theorem checkValuePipeline_bounded_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/CheckConstExecution.lean b/Ix/Kernel/Verify/Check/CheckConstExecution.lean similarity index 95% rename from Ix/Tc/Verify/Check/CheckConstExecution.lean rename to Ix/Kernel/Verify/Check/CheckConstExecution.lean index fb8678b0d..f74611892 100644 --- a/Ix/Tc/Verify/Check/CheckConstExecution.lean +++ b/Ix/Kernel/Verify/Check/CheckConstExecution.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.BlockRouteFrame -import Ix.Tc.Verify.Check.BlockTransaction +import Ix.Kernel.Verify.Check.BlockRouteFrame +import Ix.Kernel.Verify.Check.BlockTransaction /-! # Production `checkConst` dispatch traces @@ -11,7 +11,7 @@ ends at `checkCoordinatedBlock`; the standalone branch ends at for one branch from being reused for the other. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -65,4 +65,4 @@ theorem checkConst_success_trace end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/CheckConstTransaction.lean b/Ix/Kernel/Verify/Check/CheckConstTransaction.lean similarity index 98% rename from Ix/Tc/Verify/Check/CheckConstTransaction.lean rename to Ix/Kernel/Verify/Check/CheckConstTransaction.lean index 5b1bc35bc..57dd9c9b0 100644 --- a/Ix/Tc/Verify/Check/CheckConstTransaction.lean +++ b/Ix/Kernel/Verify/Check/CheckConstTransaction.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.CheckConstExecution +import Ix.Kernel.Verify.Check.CheckConstExecution /-! # Semantic assembly for production `checkConst` @@ -16,7 +16,7 @@ as the route. Thus the certifier cannot be applied to a TOCTOU-substituted block. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Stable kernel state plus E0's physical/ghost block-table agreement. -/ structure CoordinatedKernelStateWF (semantics : CacheSemantics) @@ -154,4 +154,4 @@ theorem checkConst_success_disposition end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/CheckerEvidence.lean b/Ix/Kernel/Verify/Check/CheckerEvidence.lean similarity index 95% rename from Ix/Tc/Verify/Check/CheckerEvidence.lean rename to Ix/Kernel/Verify/Check/CheckerEvidence.lean index adc4a0035..7dc5c6ad8 100644 --- a/Ix/Tc/Verify/Check/CheckerEvidence.lean +++ b/Ix/Kernel/Verify/Check/CheckerEvidence.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.Acceptance -import Ix.Tc.Verify.Check.FullInferenceCache +import Ix.Kernel.Verify.Check.Acceptance +import Ix.Kernel.Verify.Check.FullInferenceCache /-! # Semantic evidence from the standalone checker pipelines @@ -14,7 +14,7 @@ The value pipeline is parameterized by the semantic contract for the actual `methods.isDefEq` callback used inside recursive inference. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -29,7 +29,7 @@ theorem checkTypePipeline_sound (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars methods) {Delta : KVLCtx} {s after : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : PreTrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) @@ -96,7 +96,7 @@ theorem checkValuePipeline_sound (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars methods) (hdefeq : ∀ {Delta : KVLCtx} {s : TcState .anon} - {left right : KExpr .anon} {leftV rightV : Lean4Lean.VExpr}, + {left right : KExpr .anon} {leftV rightV : Ix.Theory.Named.VExpr}, support left → support right → TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta left leftV → @@ -108,7 +108,7 @@ theorem checkValuePipeline_sound world.venv.IsDefEqU model.keys.uvars Delta.toCtx leftV rightV)) {Delta : KVLCtx} {s after : TcState .anon} {value declaredType : KExpr .anon} - {valueV declaredTypeV : Lean4Lean.VExpr} + {valueV declaredTypeV : Ix.Theory.Named.VExpr} (hvalueSupport : support value) (hdeclaredSupport : support declaredType) (hvalue : PreTrKExprS world.venv model.keys.uvars world.nameOf trProj @@ -171,4 +171,4 @@ theorem checkValuePipeline_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DeclarationIngress.lean b/Ix/Kernel/Verify/Check/DeclarationIngress.lean similarity index 95% rename from Ix/Tc/Verify/Check/DeclarationIngress.lean rename to Ix/Kernel/Verify/Check/DeclarationIngress.lean index b2d89361c..5ec9df1e1 100644 --- a/Ix/Tc/Verify/Check/DeclarationIngress.lean +++ b/Ix/Kernel/Verify/Check/DeclarationIngress.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.PreTranslationIngress +import Ix.Kernel.Verify.Check.PreTranslationIngress /-! # Standalone declaration ingress @@ -12,9 +12,9 @@ consumed by the two `checkConstMember` pipelines. Neither relation contains a typing judgment or a declaration-WF premise. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDecl VExpr) +open Ix.Theory.Named (VDecl VExpr) /-- Successful standalone validation facts, including the no-wrap budget needed to interpret the validator's `UInt64` binder depth. -/ @@ -40,7 +40,7 @@ inductive StandaloneScope : KConst .anon -> Prop /-- Raw standalone correspondence after scoping validation, but before any typing has been established. -/ -inductive PreDeclRel (env : Lean4Lean.VEnv) +inductive PreDeclRel (env : Ix.Theory.Named.VEnv) (nameOf : Address -> Option Lean.Name) (trProj : RawProjRel) (id : KId .anon) : KConst .anon -> VDecl -> Prop | axiom @@ -74,7 +74,7 @@ namespace RawDeclRel /-- The exact raw declaration becomes a pre-translation declaration once the production validator's standalone certificate is available. -/ theorem toPre_of_scope - {env : Lean4Lean.VEnv} {nameOf : Address -> Option Lean.Name} + {env : Ix.Theory.Named.VEnv} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} {id : KId .anon} (hprojection : trProj.SubstCompatible) (hliterals : forall literal, env.ContainsLits literal) @@ -121,4 +121,4 @@ theorem toPre_of_scope end PendingDecl -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DeclarationValidation.lean b/Ix/Kernel/Verify/Check/DeclarationValidation.lean similarity index 96% rename from Ix/Tc/Verify/Check/DeclarationValidation.lean rename to Ix/Kernel/Verify/Check/DeclarationValidation.lean index db8b7cd33..68824d8c1 100644 --- a/Ix/Tc/Verify/Check/DeclarationValidation.lean +++ b/Ix/Kernel/Verify/Check/DeclarationValidation.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.ValidatorSoundness -import Ix.Tc.Verify.Check.DeclarationIngress +import Ix.Kernel.Verify.Check.ValidatorSoundness +import Ix.Kernel.Verify.Check.DeclarationIngress /-! # Standalone declaration validation @@ -10,7 +10,7 @@ handled by K3. Finite-run coverage and no-wrap size budgets are explicit resources; neither is inferred from a successful validator return. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Static resources needed to interpret successful standalone validation. The size inequalities justify transporting the validator's `UInt64` binder @@ -110,7 +110,7 @@ namespace PendingDecl pending raw declaration into the pre-translation relation. -/ theorem toPre_of_validation {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} - {id : KId .anon} {decl : Lean4Lean.VDecl} {concrete : KConst .anon} + {id : KId .anon} {decl : Ix.Theory.Named.VDecl} {concrete : KConst .anon} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -126,4 +126,4 @@ theorem toPre_of_validation end PendingDecl -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqBasicPolicy.lean b/Ix/Kernel/Verify/Check/DefEqBasicPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/DefEqBasicPolicy.lean rename to Ix/Kernel/Verify/Check/DefEqBasicPolicy.lean index 1b2e5ff0e..40402277d 100644 --- a/Ix/Tc/Verify/Check/DefEqBasicPolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqBasicPolicy.lean @@ -1,5 +1,5 @@ -import Ix.Tc.DefEq -import Ix.Tc.Verify.Check.WhnfHelperPolicy +import Ix.Kernel.DefEq +import Ix.Kernel.Verify.Check.WhnfHelperPolicy /-! # Operational policy for basic definitional-equality helpers @@ -11,7 +11,7 @@ application-spine recursion. Later DefEq phase proofs build exclusively on these concrete lemmas. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM.PreservesInferOnly @@ -464,4 +464,4 @@ theorem tryDefEqWhnfApp_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqCachePolicy.lean b/Ix/Kernel/Verify/Check/DefEqCachePolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/DefEqCachePolicy.lean rename to Ix/Kernel/Verify/Check/DefEqCachePolicy.lean index 60f09a723..f004e1d63 100644 --- a/Ix/Tc/Verify/Check/DefEqCachePolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqCachePolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqPipelinePolicy +import Ix.Kernel.Verify.Check.DefEqPipelinePolicy /-! # Operational policy for DefEq's cache and recursion shell @@ -9,7 +9,7 @@ shell around those tiers preserves the same caller policy on success and on every error path. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -342,4 +342,4 @@ theorem isDefEq_preservesInferOnly_of_inner end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqEtaPolicy.lean b/Ix/Kernel/Verify/Check/DefEqEtaPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/DefEqEtaPolicy.lean rename to Ix/Kernel/Verify/Check/DefEqEtaPolicy.lean index b2d0f9021..982a052e9 100644 --- a/Ix/Tc/Verify/Check/DefEqEtaPolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqEtaPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqPropositionPolicy +import Ix.Kernel.Verify.Check.DefEqPropositionPolicy /-! # Operational policy for DefEq eta phases @@ -9,7 +9,7 @@ infer-only type comparison, finite projection-field recursion, and the common-base scan. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -358,4 +358,4 @@ theorem tryEtaStruct_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqFinalWhnfPolicy.lean b/Ix/Kernel/Verify/Check/DefEqFinalWhnfPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/DefEqFinalWhnfPolicy.lean rename to Ix/Kernel/Verify/Check/DefEqFinalWhnfPolicy.lean index 086e4cfe4..8f62000c5 100644 --- a/Ix/Tc/Verify/Check/DefEqFinalWhnfPolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqFinalWhnfPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqEtaPolicy +import Ix.Kernel.Verify.Check.DefEqEtaPolicy /-! # Operational policy for final-WHNF definitional equality @@ -10,7 +10,7 @@ lemmas preserve that exact production order while framing every success and partial error state. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -366,4 +366,4 @@ theorem isDefEqWhnf_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqLazyDeltaPolicy.lean b/Ix/Kernel/Verify/Check/DefEqLazyDeltaPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/DefEqLazyDeltaPolicy.lean rename to Ix/Kernel/Verify/Check/DefEqLazyDeltaPolicy.lean index 09ff9bc13..06c25db3d 100644 --- a/Ix/Tc/Verify/Check/DefEqLazyDeltaPolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqLazyDeltaPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqProjectionDeltaPolicy +import Ix.Kernel.Verify.Check.DefEqProjectionDeltaPolicy /-! # Operational policy for the main DefEq lazy-delta loop @@ -9,7 +9,7 @@ probes, one- and two-sided unfolding, projection-app probes, and the stopped continuation into final WHNF comparison. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -476,4 +476,4 @@ theorem isDefEqInnerAfterProofIrrelevance_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqNatPolicy.lean b/Ix/Kernel/Verify/Check/DefEqNatPolicy.lean similarity index 98% rename from Ix/Tc/Verify/Check/DefEqNatPolicy.lean rename to Ix/Kernel/Verify/Check/DefEqNatPolicy.lean index 21675013f..18defcd2e 100644 --- a/Ix/Tc/Verify/Check/DefEqNatPolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqNatPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqBasicPolicy +import Ix.Kernel.Verify.Check.DefEqBasicPolicy /-! # Operational policy for DefEq Nat and String bridges @@ -9,7 +9,7 @@ successful recursive comparison is routed through the framed predecessor method table; all misses and allocation errors preserve the same policy. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -188,4 +188,4 @@ theorem tryStringLitExpansion_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqPipelinePolicy.lean b/Ix/Kernel/Verify/Check/DefEqPipelinePolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/DefEqPipelinePolicy.lean rename to Ix/Kernel/Verify/Check/DefEqPipelinePolicy.lean index ff1d54d36..7a089cc87 100644 --- a/Ix/Tc/Verify/Check/DefEqPipelinePolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqPipelinePolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqLazyDeltaPolicy +import Ix.Kernel.Verify.Check.DefEqLazyDeltaPolicy /-! # Operational policy for the DefEq comparison pipeline @@ -8,7 +8,7 @@ lazy-delta policies across the exact production `isDefEqInner` tier order. It stops at the cache/depth shell owned by `isDefEq` itself. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -239,4 +239,4 @@ theorem isDefEqInner_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqProjectionDeltaPolicy.lean b/Ix/Kernel/Verify/Check/DefEqProjectionDeltaPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/DefEqProjectionDeltaPolicy.lean rename to Ix/Kernel/Verify/Check/DefEqProjectionDeltaPolicy.lean index 7a1e5a5ab..16b0a662c 100644 --- a/Ix/Tc/Verify/Check/DefEqProjectionDeltaPolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqProjectionDeltaPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqFinalWhnfPolicy +import Ix.Kernel.Verify.Check.DefEqFinalWhnfPolicy /-! # Operational policy for projection-directed DefEq delta reduction @@ -9,7 +9,7 @@ callbacks, projection reduction, bounded iteration, and recursive equality all preserve the inference-policy bit on success and error. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -454,4 +454,4 @@ theorem tryDefEqApp_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/DefEqPropositionPolicy.lean b/Ix/Kernel/Verify/Check/DefEqPropositionPolicy.lean similarity index 98% rename from Ix/Tc/Verify/Check/DefEqPropositionPolicy.lean rename to Ix/Kernel/Verify/Check/DefEqPropositionPolicy.lean index 6681c55fb..8d9f85666 100644 --- a/Ix/Tc/Verify/Check/DefEqPropositionPolicy.lean +++ b/Ix/Kernel/Verify/Check/DefEqPropositionPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqNatPolicy +import Ix.Kernel.Verify.Check.DefEqNatPolicy /-! # Operational policy for DefEq proposition and unit classifiers @@ -9,7 +9,7 @@ shells, lazy declaration lookups, WHNF calls, and recursive equality edges restore the caller's exact inference policy. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -164,4 +164,4 @@ theorem tryDefEqUnit_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInference.lean b/Ix/Kernel/Verify/Check/FullInference.lean similarity index 95% rename from Ix/Tc/Verify/Check/FullInference.lean rename to Ix/Kernel/Verify/Check/FullInference.lean index 2eba0b79a..197c96b91 100644 --- a/Ix/Tc/Verify/Check/FullInference.lean +++ b/Ix/Kernel/Verify/Check/FullInference.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.PreTranslationCompatibility -import Ix.Tc.Verify.Infer.CacheSoundness +import Ix.Kernel.Verify.Check.PreTranslationCompatibility +import Ix.Kernel.Verify.Infer.CacheSoundness /-! # Full inference from untyped checker ingress @@ -15,9 +15,9 @@ an earlier typed translation, and `PreTrKExprS.upgradeOfTyped` reconciles it with the exact translation chosen by the current raw ingress. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Successful full inference both validates the source translation and returns a Theory type for that exact translated source. -/ @@ -93,4 +93,4 @@ theorem inferWith_fullHit_pre_acceptance end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInferenceApplications.lean b/Ix/Kernel/Verify/Check/FullInferenceApplications.lean similarity index 98% rename from Ix/Tc/Verify/Check/FullInferenceApplications.lean rename to Ix/Kernel/Verify/Check/FullInferenceApplications.lean index ec85c364c..263823f25 100644 --- a/Ix/Tc/Verify/Check/FullInferenceApplications.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceApplications.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.FullInferenceLeaves -import Ix.Tc.Verify.Check.InferencePolicy +import Ix.Kernel.Verify.Check.FullInferenceLeaves +import Ix.Kernel.Verify.Check.InferencePolicy /-! # Full inference for applications @@ -17,9 +17,9 @@ proof must construct this context; an arbitrary `Methods.WFAt` table cannot, because its semantic contract does not constrain that policy bit. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Strong recursive services used while reconstructing a typed translation from successful full inference. These are properties of one concrete @@ -287,7 +287,7 @@ private theorem fullApplicationResult exact ⟨hsource, codV.inst aV, hresultTr.trKExpr world.venvWF.ordered theory.literalWF theory.projections.wf hDelta, - Lean4Lean.VEnv.HasType.app hfunAtForall hargAtDom⟩ + Ix.Theory.Named.VEnv.HasType.app hfunAtForall hargAtDom⟩ /-- Execute the final dependent-codomain substitution after a successful full application check. `runIntern` cannot throw and its exact frame proves @@ -457,4 +457,4 @@ theorem inferUncached_app_full_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInferenceBinders.lean b/Ix/Kernel/Verify/Check/FullInferenceBinders.lean similarity index 98% rename from Ix/Tc/Verify/Check/FullInferenceBinders.lean rename to Ix/Kernel/Verify/Check/FullInferenceBinders.lean index fcb7b9a07..6000b42af 100644 --- a/Ix/Tc/Verify/Check/FullInferenceBinders.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceBinders.lean @@ -1,8 +1,10 @@ -import Ix.Tc.Verify.Check.BinderRoundTrip -import Ix.Tc.Verify.Check.FullInferenceApplications -import Ix.Tc.Verify.Infer.ForallTypes -import Ix.Tc.Verify.Infer.LambdaTypes -import Ix.Tc.Verify.Infer.LetTypes +import Ix.Kernel.Verify.Check.BinderRoundTrip +import Ix.Kernel.Verify.Check.FullInferenceApplications +import Ix.Kernel.Verify.Infer.ForallTypes +import Ix.Kernel.Verify.Infer.LambdaTypes +import Ix.Kernel.Verify.Infer.LetTypes + +open Ix.Theory (VLevel) /-! # Full inference for binding forms @@ -13,9 +15,9 @@ the domain, infer the freshly opened body, and close its newly established typed translation back to the original de Bruijn syntax. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -138,7 +140,7 @@ private theorem inferLambdaFullTail_wf .lam ⟨u, htySort⟩ htyTr hbodyTr exact ⟨hpolicyFinal, hresultSupport, hsourceTr, .forallE tyV bodyTyV, hresultTr, - Lean4Lean.VEnv.HasType.lam htySort hbodyTy'⟩ + Ix.Theory.Named.VEnv.HasType.lam htySort hbodyTy'⟩ · intro _ _ herror exact herror @@ -321,7 +323,7 @@ private theorem inferForallFullTail_wf world.venvWF.ordered theory.literalWF theory.projections.wf hDelta have hforall : world.venv.HasType uvars Delta.toCtx (.forallE tyV bodyV) (.sort (.imax u1.toVLevel u2.toVLevel)) := - Lean4Lean.VEnv.HasType.forallE htySort (by simpa using hbodySort) + Ix.Theory.Named.VEnv.HasType.forallE htySort (by simpa using hbodySort) have hlevelEq := hu1.mkIMax_equiv hcollision hu2 have hsortEq : world.venv.IsDefEqU uvars Delta.toCtx (.sort (.imax u1.toVLevel u2.toVLevel)) @@ -654,4 +656,4 @@ theorem inferUncached_let_full_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInferenceCache.lean b/Ix/Kernel/Verify/Check/FullInferenceCache.lean similarity index 96% rename from Ix/Tc/Verify/Check/FullInferenceCache.lean rename to Ix/Kernel/Verify/Check/FullInferenceCache.lean index ecb196aa4..17d4a6c3e 100644 --- a/Ix/Tc/Verify/Check/FullInferenceCache.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceCache.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.FullInferenceDispatcher -import Ix.Tc.Verify.Infer.CacheSoundness +import Ix.Kernel.Verify.Check.FullInferenceDispatcher +import Ix.Kernel.Verify.Infer.CacheSoundness /-! # Full-inference cache shell @@ -11,7 +11,7 @@ translation; misses construct ordinary collision-robust K2 provenance before writing the validated cache partition. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace FullUncachedInference.Context @@ -48,7 +48,7 @@ private theorem missTail_full_wf (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars methods) {Delta : KVLCtx} {before s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {key : Address × Address} (hmatch : model.keys.Matches trProj world before Delta source key) (hsourceSupport : support source) @@ -105,7 +105,7 @@ theorem inferWith_full_wf (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars methods) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : PreTrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) @@ -177,7 +177,7 @@ theorem infer_full_wf (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars methods) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : PreTrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) @@ -195,4 +195,4 @@ theorem infer_full_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInferenceDispatcher.lean b/Ix/Kernel/Verify/Check/FullInferenceDispatcher.lean similarity index 96% rename from Ix/Tc/Verify/Check/FullInferenceDispatcher.lean rename to Ix/Kernel/Verify/Check/FullInferenceDispatcher.lean index 6a9c5ad74..0e0549307 100644 --- a/Ix/Tc/Verify/Check/FullInferenceDispatcher.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceDispatcher.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.FullInferenceProjections -import Ix.Tc.Verify.Infer.Dispatcher +import Ix.Kernel.Verify.Check.FullInferenceProjections +import Ix.Kernel.Verify.Infer.Dispatcher /-! # Exhaustive full-mode inference dispatcher @@ -14,7 +14,7 @@ In particular, neither the ordinary method-table contract nor a successful typing postcondition says what `inferOnly` contains after a partial error. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace FullUncachedInference @@ -47,7 +47,7 @@ private theorem strengthenFullLeaf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {source : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {methods : Methods .anon} + {sourceV : Ix.Theory.Named.VExpr} {methods : Methods .anon} (hsemantic : TcM.WF (WhnfStateInv .noAccel semantics trProj world support uvars Delta) s ((inferUncached inferCall false source).run methods) @@ -80,7 +80,7 @@ theorem inferUncached_full_wf (context : FullUncachedInference.Context initial program requests semantics trProj world support uvars methods) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : PreTrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) @@ -172,4 +172,4 @@ theorem inferUncached_full_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInferenceKnot.lean b/Ix/Kernel/Verify/Check/FullInferenceKnot.lean similarity index 94% rename from Ix/Tc/Verify/Check/FullInferenceKnot.lean rename to Ix/Kernel/Verify/Check/FullInferenceKnot.lean index 62bf3218d..b6eedb221 100644 --- a/Ix/Tc/Verify/Check/FullInferenceKnot.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceKnot.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Check.FullInferenceCache -import Ix.Tc.Verify.Check.RecursiveMethodPolicy -import Ix.Tc.Verify.RecursiveMethods.Closure +import Ix.Kernel.Verify.Check.FullInferenceCache +import Ix.Kernel.Verify.Check.RecursiveMethodPolicy +import Ix.Kernel.Verify.RecursiveMethods.Closure /-! # Full-inference closure of the production recursion knot @@ -17,7 +17,7 @@ one outer `RecM.infer` layer uses only the semantic, operational, and strong full-inference contracts of its strictly smaller callback table. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace Methods @@ -29,7 +29,7 @@ def FullInferenceWFAt (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (methods : Methods .anon) : Prop := ∀ {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr}, + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr}, s.inferOnly = false → support source → PreTrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → @@ -159,7 +159,7 @@ theorem methodsN_fullInferenceWFAt Methods.FullInferenceWFAt (kernelCacheSemantics proposition.model.keys trProj) trProj world support proposition.model.keys.uvars - (Ix.Tc.methodsN (m := .anon) depth) := by + (Ix.Kernel.methodsN (m := .anon) depth) := by induction depth with | zero => exact Methods.methodsOut_fullInferenceWFAt @@ -171,14 +171,14 @@ theorem methodsN_fullInferenceWFAt (WhnfStateInv .noAccel (kernelCacheSemantics proposition.model.keys trProj) trProj world support proposition.model.keys.uvars Delta) s - ((Methods.next (Ix.Tc.methodsN depth)).infer source) + ((Methods.next (Ix.Kernel.methodsN depth)).infer source) (fun result after => after.inferOnly = false ∧ FullInferPost trProj world support proposition.model.keys.uvars Delta source sourceV result) (fun _ after => after.inferOnly = false) exact - (context.next_fullInferenceWFAt (Ix.Tc.methodsN depth) + (context.next_fullInferenceWFAt (Ix.Kernel.methodsN depth) (context.methodsN depth) (Methods.methodsN_concrete_preservesInferOnly depth) ih) hbefore hsourceSupport hsource @@ -194,7 +194,7 @@ theorem publicInfer_full_wf (context : RecursiveMethodClosureContext initial program requests support proposition eligible) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hbefore : s.inferOnly = false) (hsourceSupport : support source) (hsource : PreTrKExprS world.venv proposition.model.keys.uvars @@ -209,7 +209,7 @@ theorem publicInfer_full_wf FullInferPost trProj world support proposition.model.keys.uvars Delta source sourceV result) (fun _ after => after.inferOnly = false) := by - let methods := Ix.Tc.methodsN (m := .anon) s.recFuel.toNat + let methods := Ix.Kernel.methodsN (m := .anon) s.recFuel.toNat have hmethods : Methods.WFAt .noAccel (kernelCacheSemantics proposition.model.keys trProj) trProj world support proposition.model.keys.uvars methods := @@ -227,4 +227,4 @@ theorem publicInfer_full_wf end RecursiveMethodClosureContext -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInferenceLeaves.lean b/Ix/Kernel/Verify/Check/FullInferenceLeaves.lean similarity index 95% rename from Ix/Tc/Verify/Check/FullInferenceLeaves.lean rename to Ix/Kernel/Verify/Check/FullInferenceLeaves.lean index 768cd9174..46d13aafe 100644 --- a/Ix/Tc/Verify/Check/FullInferenceLeaves.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceLeaves.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Check.FullInference +import Ix.Kernel.Verify.Check.FullInference + +open Ix.Theory (VLevel) /-! # Full inference for untyped leaf ingress @@ -10,7 +12,7 @@ application and binder constructors remain genuinely new K3 work because their typed constructors contain the checks full inference must establish. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -20,7 +22,7 @@ theorem inferUncached_sort_full_wf {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {u : KUniv .anon} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hcollision : support.CollisionFree) (hresultSupport : support (KExpr.mkSort (KUniv.mkSucc u))) @@ -48,7 +50,7 @@ theorem inferUncached_var_full_wf {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {idx : UInt64} {name : Mode.anon.F Name} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hsource : PreTrKExprS world.venv uvars world.nameOf trProj Delta (.var idx name info) sourceV) @@ -75,7 +77,7 @@ theorem inferUncached_fvar_full_wf {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {fv : FVarId} {name : Mode.anon.F Name} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hsafe : FVarInferSafety layer semantics trProj world support uvars Delta) @@ -103,7 +105,7 @@ theorem inferUncached_const_full_wf {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {id : KId .anon} {levels : Array (KUniv .anon)} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hfault : TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) @@ -136,7 +138,7 @@ theorem inferUncached_nat_full_wf {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {n : Nat} {blob : Address} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (context : LiteralInferContext world support) (theory : WhnfTheory trProj world uvars) (hsource : PreTrKExprS world.venv uvars world.nameOf trProj Delta @@ -159,7 +161,7 @@ theorem inferUncached_str_full_wf {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {value : String} {blob : Address} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (context : LiteralInferContext world support) (theory : WhnfTheory trProj world uvars) (hsource : PreTrKExprS world.venv uvars world.nameOf trProj Delta @@ -179,4 +181,4 @@ theorem inferUncached_str_full_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/FullInferenceProjections.lean b/Ix/Kernel/Verify/Check/FullInferenceProjections.lean similarity index 96% rename from Ix/Tc/Verify/Check/FullInferenceProjections.lean rename to Ix/Kernel/Verify/Check/FullInferenceProjections.lean index 0c8ed01ac..cfe360bb4 100644 --- a/Ix/Tc/Verify/Check/FullInferenceProjections.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceProjections.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.FullInferenceBinders -import Ix.Tc.Verify.Infer.ProjectionTypes +import Ix.Kernel.Verify.Check.FullInferenceBinders +import Ix.Kernel.Verify.Infer.ProjectionTypes /-! # Full inference for projections @@ -15,9 +15,9 @@ policy frame. A typing proof alone cannot show that a partial error preserved for one concrete smaller method table. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace ProjectionInference @@ -124,4 +124,4 @@ theorem inferUncached_prj_full_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/InferencePolicy.lean b/Ix/Kernel/Verify/Check/InferencePolicy.lean similarity index 98% rename from Ix/Tc/Verify/Check/InferencePolicy.lean rename to Ix/Kernel/Verify/Check/InferencePolicy.lean index e4cde5e74..cba828a38 100644 --- a/Ix/Tc/Verify/Check/InferencePolicy.lean +++ b/Ix/Kernel/Verify/Check/InferencePolicy.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Knot -import Ix.Tc.Verify.Infer.Applications -import Ix.Tc.Verify.Whnf.StructEta.CallbackPrefix -import Ix.Tc.Verify.Whnf.StructEta.RecursionClassifier +import Ix.Kernel.Verify.Knot +import Ix.Kernel.Verify.Infer.Applications +import Ix.Kernel.Verify.Whnf.StructEta.CallbackPrefix +import Ix.Kernel.Verify.Whnf.StructEta.RecursionClassifier /-! # Inference-policy frames @@ -19,7 +19,7 @@ smaller callbacks do. No semantic typing claim is bundled into this operational frame. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- An action restores the caller's inference policy on both outcomes. -/ def TcM.PreservesInferOnly (x : TcM .anon alpha) : Prop := @@ -649,7 +649,7 @@ theorem PreservesInferOnly.isDefEq_full_wf {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {s : TcState .anon} {left right : KExpr .anon} - {leftV rightV : Lean4Lean.VExpr} + {leftV rightV : Ix.Theory.Named.VExpr} (hsemantic : Methods.WFAt layer semantics trProj world support uvars methods) (hframe : methods.PreservesInferOnly) @@ -677,4 +677,4 @@ theorem PreservesInferOnly.isDefEq_full_wf end Methods -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/MemberEvidence.lean b/Ix/Kernel/Verify/Check/MemberEvidence.lean similarity index 98% rename from Ix/Tc/Verify/Check/MemberEvidence.lean rename to Ix/Kernel/Verify/Check/MemberEvidence.lean index b3e45b2ab..33589ff34 100644 --- a/Ix/Tc/Verify/Check/MemberEvidence.lean +++ b/Ix/Kernel/Verify/Check/MemberEvidence.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.BoundedPipelines -import Ix.Tc.Verify.Check.SafetyFrame +import Ix.Kernel.Verify.Check.BoundedPipelines +import Ix.Kernel.Verify.Check.SafetyFrame /-! # Semantic evidence from standalone member checking @@ -14,7 +14,7 @@ successful execution is nevertheless part of the trace from which the typing evidence is extracted. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -92,7 +92,7 @@ theorem checkConstMember_axiom_sound {id : KId .anon} {name : Mode.anon.F Name} {levelParams : Mode.anon.F (Array Name)} {isUnsafe : Bool} {levels : UInt64} {type : KExpr .anon} - {typeV : Lean4Lean.VExpr} + {typeV : Ix.Theory.Named.VExpr} (hresources : StandaloneValidationResources support (.axio name levelParams isUnsafe levels type)) (hsourceCall : context.typeSources type) @@ -166,7 +166,7 @@ theorem checkConstMember_defn_sound {safety : Ix.DefinitionSafety} {hints : Lean.ReducibilityHints} {levels : UInt64} {type value : KExpr .anon} {leanAll : Mode.anon.F (Array (KId .anon))} {block : KId .anon} - {typeV valueV : Lean4Lean.VExpr} + {typeV valueV : Ix.Theory.Named.VExpr} (hresources : StandaloneValidationResources support (.defn name levelParams kind safety hints levels type value leanAll block)) @@ -350,7 +350,7 @@ theorem checkConstMember_sound model.keys.uvars calls (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hingress : PreDeclRel world.venv world.nameOf trProj id concrete decl) (hcovers : context.Covers concrete) (hresources : StandaloneValidationResources support concrete) @@ -456,7 +456,7 @@ theorem checkConstMember_pending_sound model.keys.uvars calls (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -496,4 +496,4 @@ theorem checkConstMember_pending_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/NatAcceptance.lean b/Ix/Kernel/Verify/Check/NatAcceptance.lean similarity index 97% rename from Ix/Tc/Verify/Check/NatAcceptance.lean rename to Ix/Kernel/Verify/Check/NatAcceptance.lean index becb4322b..c9de163f8 100644 --- a/Ix/Tc/Verify/Check/NatAcceptance.lean +++ b/Ix/Kernel/Verify/Check/NatAcceptance.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.NatFixture -import Ix.Tc.Verify.Check.PublicStandalone +import Ix.Kernel.Verify.NatFixture +import Ix.Kernel.Verify.Check.PublicStandalone + +open Ix.Theory (VLevel) /-! # Concrete standalone-check acceptance over the ambient Nat world @@ -17,7 +19,7 @@ cache use, reset, validation, acceptance, and rollback rather than about a mock implementation. -/ -namespace Ix.Tc.AmbientNat +namespace Ix.Kernel.AmbientNat def acceptanceEnv : KEnv .anon := { loadedEnv with inferCache := @@ -204,14 +206,14 @@ theorem natType_translation : · simpa [natType] using (TrKExprS.sort (env := worldNat.venv) (nameOf := worldNat.nameOf) (trProj := RawProjRel.none) (Δ := []) oneLevel_wf) - · exact Lean4Lean.VEnv.IsDefEqU.refl - ⟨_, Lean4Lean.VEnv.HasType.sort oneLevel_wf⟩ + · exact Ix.Theory.Named.VEnv.IsDefEqU.refl + ⟨_, Ix.Theory.Named.VEnv.HasType.sort oneLevel_wf⟩ theorem natReference_type : worldNat.venv.HasType 0 [] (.const natName []) (.sort oneLevel.toVLevel) := by exact - (Lean4Lean.VEnv.HasType.const (env := natEnv) (U := 0) (Γ := []) + (Ix.Theory.Named.VEnv.HasType.const (env := natEnv) (U := 0) (Γ := []) (ci := natConstant) (ls := []) natEnv_nat (by simp) rfl) theorem oneLevel_view : @@ -224,8 +226,8 @@ theorem oneLevel_view : | succ hchild => cases hchild exact Or.inl rfl - · exact Lean4Lean.VEnv.IsDefEqU.refl - ⟨_, Lean4Lean.VEnv.HasType.sort oneLevel_wf⟩ + · exact Ix.Theory.Named.VEnv.IsDefEqU.refl + ⟨_, Ix.Theory.Named.VEnv.HasType.sort oneLevel_wf⟩ theorem goodTypeEvidence : TypeCheckEvidence RawProjRel.none worldNat acceptanceSupport 0 [] @@ -549,7 +551,7 @@ structure PublicCheckLifecycle : Prop where invalidPending : PendingDecl RawProjRel.none worldGood IllTypedPending.targetId IllTypedPending.theoryDecl invalidSemantic : - ¬∃ env', Lean4Lean.VDecl.WF worldGood.venv + ¬∃ env', Ix.Theory.Named.VDecl.WF worldGood.venv IllTypedPending.theoryDecl env' invalidExecution : TcM.checkConst IllTypedPending.targetId resetState = @@ -582,4 +584,4 @@ def goodSucceeded : Bool := example : goodSucceeded = true := by simp [goodSucceeded, initial_good_public] -end Ix.Tc.AmbientNat +end Ix.Kernel.AmbientNat diff --git a/Ix/Tc/Verify/Check/PositiveFuelSort.lean b/Ix/Kernel/Verify/Check/PositiveFuelSort.lean similarity index 94% rename from Ix/Tc/Verify/Check/PositiveFuelSort.lean rename to Ix/Kernel/Verify/Check/PositiveFuelSort.lean index 1469c28a3..39cc0d1be 100644 --- a/Ix/Tc/Verify/Check/PositiveFuelSort.lean +++ b/Ix/Kernel/Verify/Check/PositiveFuelSort.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Check.BoundedPipelines -import Ix.Tc.Verify.RecursiveMethods.SortInference -import Ix.Tc.Verify.RecursiveMethods.ScopedSortInference -import Ix.Tc.Verify.ScopedSuffix.ClosedContext +import Ix.Kernel.Verify.Check.BoundedPipelines +import Ix.Kernel.Verify.RecursiveMethods.SortInference +import Ix.Kernel.Verify.RecursiveMethods.ScopedSortInference +import Ix.Kernel.Verify.ScopedSuffix.ClosedContext /-! # Positive-fuel bounded checker witness @@ -15,7 +15,7 @@ inequalities, strong inference upgrade, and checker pipeline resources are all concrete. -/ -namespace Ix.Tc.PositiveFuelSort +namespace Ix.Kernel.PositiveFuelSort def sourceUniv : KUniv .anon := KUniv.mkZero def resultUniv : KUniv .anon := KUniv.mkSucc sourceUniv @@ -118,8 +118,8 @@ def theory (uvars : Nat) : intro literal hliteral cases literal <;> simp [VerifyWorld.empty, VerifyWorld.ofCatalog, - Lean4Lean.VEnv.ContainsLits, Lean4Lean.VEnv.contains, - Lean4Lean.VEnv.empty] at hliteral + Ix.Theory.Named.VEnv.ContainsLits, Ix.Theory.Named.VEnv.contains, + Ix.Theory.Named.VEnv.empty] at hliteral projections := RawProjRel.none_ok VerifyWorld.empty.venv uvars /-! ## Concrete run-scoped suffix instance -/ @@ -235,12 +235,12 @@ theorem scopedPublicInference_execution result_supported scopedInitialState_baseInv have hbody : (RecM.inferUncached RecM.inferCall false source).run - (Ix.Tc.methodsN (m := .anon) 1) scopedInitialState = + (Ix.Kernel.methodsN (m := .anon) 1) scopedInitialState = .ok result afterIntern := by exact hintern have hshell := RecM.inferWith_fullMiss_success (inferRec := RecM.inferCall) - (methods := Ix.Tc.methodsN (m := .anon) 1) + (methods := Ix.Kernel.methodsN (m := .anon) 1) (source := source) (ty := result) (key := scopedInferKey) (s := scopedInitialState) (sKey := scopedInitialState) (sBody := afterIntern) (by rfl) scopedInitialState_inferKey @@ -277,7 +277,7 @@ theorem methodContractAtFuelOne (kernelCacheSemantics model.keys RawProjRel.none) RawProjRel.none VerifyWorld.empty support model.keys.uvars (.singletonInfer source) - (Methods.next (Ix.Tc.methodsN (m := .anon) 1)) := by + (Methods.next (Ix.Kernel.methodsN (m := .anon) 1)) := by simpa [Methods.SortSchedule.calls] using (scheduleAtFuelOne separation model).nextSelected @@ -290,7 +290,7 @@ theorem fullInferenceAtFuelOne (kernelCacheSemantics model.keys RawProjRel.none) RawProjRel.none VerifyWorld.empty support model.keys.uvars (.singletonInfer source) - (Methods.next (Ix.Tc.methodsN (m := .anon) 1)) := + (Methods.next (Ix.Kernel.methodsN (m := .anon) 1)) := Methods.FullInferenceWFAtOn.ofSingletonSort (methodContractAtFuelOne separation model) (Methods.next_preservesInferOnly _ @@ -304,7 +304,7 @@ def pipelinesAtFuelOne StandalonePipelineResources (kernelCacheSemantics model.keys RawProjRel.none) RawProjRel.none VerifyWorld.empty support model.keys.uvars - (.singletonInfer source) (Ix.Tc.methodsN (m := .anon) 1) := + (.singletonInfer source) (Ix.Kernel.methodsN (m := .anon) 1) := StandalonePipelineResources.singletonSortAxiom (fullInferenceAtFuelOne separation model) sortResources supported_is_sort @@ -317,4 +317,4 @@ theorem pipelines_cover_concreteAxiom (pipelinesAtFuelOne separation model).Covers concreteAxiom := .axiom rfl -end Ix.Tc.PositiveFuelSort +end Ix.Kernel.PositiveFuelSort diff --git a/Ix/Tc/Verify/Check/PreTranslation.lean b/Ix/Kernel/Verify/Check/PreTranslation.lean similarity index 96% rename from Ix/Tc/Verify/Check/PreTranslation.lean rename to Ix/Kernel/Verify/Check/PreTranslation.lean index 9f033a626..f2172cdf0 100644 --- a/Ix/Tc/Verify/Check/PreTranslation.lean +++ b/Ix/Kernel/Verify/Check/PreTranslation.lean @@ -1,6 +1,8 @@ -import Ix.Tc.Verify.Check.Scoped -import Ix.Tc.Verify.Decl -import Ix.Tc.Verify.Trans +import Ix.Kernel.Verify.Check.Scoped +import Ix.Kernel.Verify.Decl +import Ix.Kernel.Verify.Trans + +open Ix.Theory (VLevel) /-! # Untyped structural translation for checker ingress @@ -18,9 +20,9 @@ premise. Successful full inference will upgrade this relation to declaration. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VEnv VConstant) +open Ix.Theory.Named (VExpr VEnv VConstant) variable (env : VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) in @@ -146,4 +148,4 @@ theorem contextScoped end PreTrKExprS -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/PreTranslationCompatibility.lean b/Ix/Kernel/Verify/Check/PreTranslationCompatibility.lean similarity index 95% rename from Ix/Tc/Verify/Check/PreTranslationCompatibility.lean rename to Ix/Kernel/Verify/Check/PreTranslationCompatibility.lean index f4cf8c3bd..2db1c4c26 100644 --- a/Ix/Tc/Verify/Check/PreTranslationCompatibility.lean +++ b/Ix/Kernel/Verify/Check/PreTranslationCompatibility.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.PreTranslationIngress -import Lean4Lean.Theory.Typing.Strong +import Ix.Kernel.Verify.Check.PreTranslationIngress +import Ix.Theory.Named.Typing.Strong /-! # Compatibility of raw and typed structural translations @@ -11,9 +11,9 @@ chosen by the current raw translation and borrows only the typing evidence from the checked witness. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VEnv) +open Ix.Theory.Named (VExpr VEnv) /-- Upgrade a raw structural translation using any typed translation of the same kernel expression in a pairwise-definitionally-equal context. -/ @@ -138,14 +138,14 @@ theorem PreTrKExprS.upgradeBinderCoreOfWF | app hpreFn hpreArg ihFn ihArg => simp only [KExpr.binderCore, Bool.and_eq_true] at hcore obtain ⟨type, body, hfnType, hargType⟩ := - Lean4Lean.VExpr.WF.app_inv henv.ordered hDelta.toCtx hwf + Ix.Theory.Named.VExpr.WF.app_inv henv.ordered hDelta.toCtx hwf exact .app hfnType hargType (ihFn hDelta hcore.1 ⟨_, hfnType⟩) (ihArg hDelta hcore.2 ⟨_, hargType⟩) | lam hpreType hpreBody ihType ihBody => simp only [KExpr.binderCore, Bool.and_eq_true] at hcore obtain ⟨htype, hbody⟩ := - Lean4Lean.VExpr.WF.lam_inv henv.ordered hDelta.toCtx hwf + Ix.Theory.Named.VExpr.WF.lam_inv henv.ordered hDelta.toCtx hwf have htypeWF : VExpr.WF env uvars _ _ := ⟨_, htype.choose_spec⟩ exact .lam htype @@ -155,7 +155,7 @@ theorem PreTrKExprS.upgradeBinderCoreOfWF simp only [KExpr.binderCore, Bool.and_eq_true] at hcore obtain ⟨_, hwhole⟩ := hwf obtain ⟨htype, hbody⟩ := - Lean4Lean.VEnv.HasType.forallE_inv henv.ordered hwhole + Ix.Theory.Named.VEnv.HasType.forallE_inv henv.ordered hwhole have htypeWF : VExpr.WF env uvars _ _ := ⟨_, htype.choose_spec⟩ have hbodyWF : VExpr.WF env uvars _ _ := @@ -168,4 +168,4 @@ theorem PreTrKExprS.upgradeBinderCoreOfWF | nat => simp [KExpr.binderCore] at hcore | str => simp [KExpr.binderCore] at hcore -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/PreTranslationIngress.lean b/Ix/Kernel/Verify/Check/PreTranslationIngress.lean similarity index 97% rename from Ix/Tc/Verify/Check/PreTranslationIngress.lean rename to Ix/Kernel/Verify/Check/PreTranslationIngress.lean index 9ba869fa1..1bb26dfc7 100644 --- a/Ix/Tc/Verify/Check/PreTranslationIngress.lean +++ b/Ix/Kernel/Verify/Check/PreTranslationIngress.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Check.PreTranslation -import Ix.Tc.Verify.Subst +import Ix.Kernel.Verify.Check.PreTranslation +import Ix.Kernel.Verify.Subst + +open Ix.Theory (VLevel) /-! # Raw-declaration ingress into `PreTrKExprS` @@ -17,7 +19,7 @@ The main theorem below proves that raw translation plus the syntax-only translation required by full inference. No typing judgment is assumed. -/ -namespace Lean4Lean.VExpr +namespace Ix.Theory.Named.VExpr private def Subst.comp (sigma tau : Subst) : Subst := fun index => (sigma index).subst tau @@ -32,7 +34,7 @@ private theorem Subst.comp_lift {sigma tau : Subst} : rw [lift_eq_lift', lift_eq_lift', lift'_subst, subst_lift'] congr 1 funext inner - simp [Subst.lift_r, Subst.lift_l, Lean4Lean.Lift.liftVar, + simp [Subst.lift_r, Subst.lift_l, Ix.Theory.Named.Lift.liftVar, Subst.lift, lift_eq_lift'] private theorem subst_subst {e : VExpr} {sigma tau : Subst} : @@ -71,11 +73,11 @@ theorem inst_subst_cons (body value : VExpr) (sigma : Subst) : (lift_subst_cons (e := VExpr.bvar index) (sigma := sigma) (value := value.subst sigma)) -end Lean4Lean.VExpr +end Ix.Theory.Named.VExpr -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLocalDecl) +open Ix.Theory.Named (VExpr VLocalDecl) private theorem subst_natLit (value : Nat) (sigma : VExpr.Subst) : (VExpr.natLit value).subst sigma = VExpr.natLit value := by @@ -194,7 +196,7 @@ namespace RawExprRel /-- General substitution-aware ingress theorem. The size bound rules out `UInt64` wraparound when the validator descends through a binder. -/ theorem toPre_of_scoped_aux - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} (hprojection : trProj.SubstCompatible) (hliterals : forall literal, env.ContainsLits literal) @@ -282,7 +284,7 @@ theorem toPre_of_scoped_aux /-- Closed declaration ingress: successful scoping turns the exact raw Theory term into the `PreTrKExprS` witness consumed by full inference. -/ theorem toPre_of_scoped - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} (hprojection : trProj.SubstCompatible) (hliterals : forall literal, env.ContainsLits literal) @@ -298,7 +300,7 @@ theorem toPre_of_scoped lets, and projections makes their ambient semantic hypotheses unnecessary; all remaining premises are syntax-only scoping and exact raw translation. -/ theorem toPreBinderCore_of_scoped_aux - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} {ctx : List VExpr} {Delta : KVLCtx} {sigma : VExpr.Subst} {depth : UInt64} {source : KExpr .anon} {sourceV : VExpr} @@ -367,7 +369,7 @@ theorem toPreBinderCore_of_scoped_aux /-- Closed binder-core declarations enter `PreTrKExprS` without requiring an irrelevant primitive-literal environment. -/ theorem toPreBinderCore_of_scoped - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} {source : KExpr .anon} {sourceV : VExpr} (hraw : RawExprRel (uvars := uvars) env nameOf trProj [] source sourceV) @@ -380,4 +382,4 @@ theorem toPreBinderCore_of_scoped end RawExprRel -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/PreTranslationOpening.lean b/Ix/Kernel/Verify/Check/PreTranslationOpening.lean similarity index 97% rename from Ix/Tc/Verify/Check/PreTranslationOpening.lean rename to Ix/Kernel/Verify/Check/PreTranslationOpening.lean index 48f402999..d00ad1670 100644 --- a/Ix/Tc/Verify/Check/PreTranslationOpening.lean +++ b/Ix/Kernel/Verify/Check/PreTranslationOpening.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.PreTranslation -import Ix.Tc.Verify.Infer.BinderOpening +import Ix.Kernel.Verify.Check.PreTranslation +import Ix.Kernel.Verify.Infer.BinderOpening /-! # Binder opening for untyped checker ingress @@ -10,9 +10,9 @@ operation as the already verified typed inference path. This file proves that operation preserves the deliberately untyped `PreTrKExprS` relation. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VEnv VLocalDecl) +open Ix.Theory.Named (VExpr VEnv VLocalDecl) /-- Replacing one de Bruijn binder with its freshly tagged fvar leaves the pre-translation's Theory expression unchanged. -/ @@ -187,4 +187,4 @@ theorem PreTrKExprS.openFVarZero (KExpr.instantiateRevSpec body #[.mkFVar fv name] 0) bodyV := H.openFVar .zero rfl (by simpa using hfresh) (by simpa using hbound) -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/PreTranslationScopes.lean b/Ix/Kernel/Verify/Check/PreTranslationScopes.lean similarity index 97% rename from Ix/Tc/Verify/Check/PreTranslationScopes.lean rename to Ix/Kernel/Verify/Check/PreTranslationScopes.lean index 0ed1b2987..d1bf29d5c 100644 --- a/Ix/Tc/Verify/Check/PreTranslationScopes.lean +++ b/Ix/Kernel/Verify/Check/PreTranslationScopes.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Check.InferencePolicy -import Ix.Tc.Verify.Check.PreTranslationOpening -import Ix.Tc.Verify.Infer.BinderScopes -import Ix.Tc.Verify.Infer.LetScopes +import Ix.Kernel.Verify.Check.InferencePolicy +import Ix.Kernel.Verify.Check.PreTranslationOpening +import Ix.Kernel.Verify.Infer.BinderScopes +import Ix.Kernel.Verify.Infer.LetScopes /-! # Binder scopes for pre-typed checker ingress @@ -13,7 +13,7 @@ factored operational binder-opening core with `PreTrKExprS.openFVarZero` and the independent inference-policy frame. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -25,7 +25,7 @@ theorem openBinder_pre_scope {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} - {type body : KExpr .anon} {typeV bodyV : Lean4Lean.VExpr} + {type body : KExpr .anon} {typeV bodyV : Ix.Theory.Named.VExpr} (htype : TrKExprS world.venv uvars world.nameOf trProj Delta type typeV) (htypeType : world.venv.IsType uvars Delta.toCtx typeV) (hbody : PreTrKExprS world.venv uvars world.nameOf trProj @@ -83,7 +83,7 @@ theorem openLet_pre_scope {Delta : KVLCtx} {s : TcState .anon} {name : Mode.anon.F Name} {type value body : KExpr .anon} - {typeV valueV bodyV : Lean4Lean.VExpr} + {typeV valueV bodyV : Ix.Theory.Named.VExpr} (htype : TrKExprS world.venv uvars world.nameOf trProj Delta type typeV) (hvalue : TrKExprS world.venv uvars world.nameOf trProj Delta value valueV) (hvalueType : world.venv.HasType uvars Delta.toCtx valueV typeV) @@ -147,7 +147,7 @@ theorem withLctxScope_openBinder_pre_wf {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {s : TcState .anon} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} - {type body : KExpr .anon} {typeV bodyV : Lean4Lean.VExpr} + {type body : KExpr .anon} {typeV bodyV : Ix.Theory.Named.VExpr} (htype : TrKExprS world.venv uvars world.nameOf trProj Delta type typeV) (htypeType : world.venv.IsType uvars Delta.toCtx typeV) (hbody : PreTrKExprS world.venv uvars world.nameOf trProj @@ -261,7 +261,7 @@ theorem withLctxScope_openLet_pre_wf {Delta : KVLCtx} {methods : Methods .anon} {s : TcState .anon} {name : Mode.anon.F Name} {type value body : KExpr .anon} - {typeV valueV bodyV : Lean4Lean.VExpr} + {typeV valueV bodyV : Ix.Theory.Named.VExpr} (htype : TrKExprS world.venv uvars world.nameOf trProj Delta type typeV) (hvalue : TrKExprS world.venv uvars world.nameOf trProj Delta value valueV) (hvalueType : world.venv.HasType uvars Delta.toCtx valueV typeV) @@ -371,4 +371,4 @@ theorem withLctxScope_openLet_pre_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ProjectionInferencePolicy.lean b/Ix/Kernel/Verify/Check/ProjectionInferencePolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/ProjectionInferencePolicy.lean rename to Ix/Kernel/Verify/Check/ProjectionInferencePolicy.lean index 268104ae8..2a5896ce5 100644 --- a/Ix/Tc/Verify/Check/ProjectionInferencePolicy.lean +++ b/Ix/Kernel/Verify/Check/ProjectionInferencePolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.UncachedInferencePolicy +import Ix.Kernel.Verify.Check.UncachedInferencePolicy /-! # Operational policy for projection inference @@ -15,7 +15,7 @@ and cache shell, reducing the current inference layer to the current WHNF policy over a policy-framed smaller method table. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -385,4 +385,4 @@ theorem infer_preservesInferOnly_of_whnf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/PublicBlocks.lean b/Ix/Kernel/Verify/Check/PublicBlocks.lean similarity index 80% rename from Ix/Tc/Verify/Check/PublicBlocks.lean rename to Ix/Kernel/Verify/Check/PublicBlocks.lean index 3ba1abfb1..3817f3e11 100644 --- a/Ix/Tc/Verify/Check/PublicBlocks.lean +++ b/Ix/Kernel/Verify/Check/PublicBlocks.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Check.CheckConstTransaction -import Ix.Tc.Verify.Check.BlockDefinition -import Ix.Tc.Verify.Check.BlockOracle -import Ix.Tc.Verify.Check.QuotientBoundary +import Ix.Kernel.Verify.Check.CheckConstTransaction +import Ix.Kernel.Verify.Check.BlockDefinition +import Ix.Kernel.Verify.Check.BlockOracle +import Ix.Kernel.Verify.Check.QuotientBoundary /-! # Public coordinated-block checker theorem @@ -13,7 +13,7 @@ the semantic disposition is indexed by the public checker's exact final state. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM.checkConst @@ -37,21 +37,21 @@ theorem blockDisposition ExactCheckBlock world block members kind → id ∈ members → RecM.ExactBlockBodySuccessTrace - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) block id members kind routed bodyAfter → CertifiedBlockBodySuccess semantics trProj world support - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) block id members kind routed bodyAfter) (hrun : TcM.checkConst id before = .ok () after) : CheckConstSuccessDisposition semantics trProj world support - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) id before after := by - let methods := Ix.Tc.methodsN (m := .anon) before.recFuel.toNat + let methods := Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat have hbody : (RecM.checkConst id).run methods before = .ok () after := by unfold TcM.checkConst TcM.isolateCheckErrors TcM.runRec at hrun cases hinner : (RecM.checkConst id).run - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) before with + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) before with | ok value middle => simp only [hinner] at hrun cases hrun @@ -66,4 +66,4 @@ theorem blockDisposition end TcM.checkConst -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/PublicStandalone.lean b/Ix/Kernel/Verify/Check/PublicStandalone.lean similarity index 91% rename from Ix/Tc/Verify/Check/PublicStandalone.lean rename to Ix/Kernel/Verify/Check/PublicStandalone.lean index c7bd6312c..dae7ce08d 100644 --- a/Ix/Tc/Verify/Check/PublicStandalone.lean +++ b/Ix/Kernel/Verify/Check/PublicStandalone.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.ScopedStandaloneDriver -import Ix.Tc.Verify.RecursiveMethods.Public +import Ix.Kernel.Verify.Check.ScopedStandaloneDriver +import Ix.Kernel.Verify.RecursiveMethods.Public /-! # Public standalone constant checking @@ -16,7 +16,7 @@ definitionally, while standalone definitions may supply a finite routing proof for their concrete block environment. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM.checkConst @@ -29,7 +29,7 @@ theorem rollback_on_error {err : TcError .anon} (hbody : (RecM.checkConst id).run - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) before = + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) before = .error err failed) : TcM.checkConst id before = .error err (before.restoreCheckCachesOnError failed) := by @@ -47,7 +47,7 @@ theorem rollback_preserves_kernel {err : TcError .anon} (hbody : (RecM.checkConst id).run - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) before = + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) before = .error err failed) (hbefore : KernelStateWF semantics trProj world support before) (hfailedCore : TcStateWF trProj failed world) @@ -74,8 +74,8 @@ theorem wf_legacy (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars (context.calls (before.recFuel.toNat + 1)) - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat)) - {concrete : KConst .anon} {decl : Lean4Lean.VDecl} + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat)) + {concrete : KConst .anon} {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -88,7 +88,7 @@ theorem wf_legacy (WhnfStateInv .noAccel (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars []) - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) concrete) + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) concrete) (hI : WhnfStateInv .noAccel (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars [] before) @@ -105,7 +105,7 @@ theorem wf_legacy (kernelCacheSemantics context.proposition.model.keys trProj) trProj world' support context.proposition.model.keys.uvars [] after ∧ TrustedDecl trProj world' id decl := by - let methods := Ix.Tc.methodsN (m := .anon) before.recFuel.toNat + let methods := Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat have hmethods : Methods.WFAtOn .noAccel (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars @@ -123,7 +123,7 @@ theorem wf_legacy unfold TcM.checkConst TcM.isolateCheckErrors TcM.runRec at hrun cases hinner : (RecM.checkConst id).run - (Ix.Tc.methodsN before.recFuel.toNat) before with + (Ix.Kernel.methodsN before.recFuel.toNat) before with | ok value middle => simp only [hinner] at hrun cases hrun @@ -148,8 +148,8 @@ theorem wf requests trProj world support) (pipelines : ScopedStandalonePipelineResources context.model support (context.calls (before.recFuel.toNat + 1)) - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat)) - {concrete : KConst .anon} {decl : Lean4Lean.VDecl} + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat)) + {concrete : KConst .anon} {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -162,7 +162,7 @@ theorem wf (hroute : StandaloneRoute (ScopedWhnfStateInv context.model .noAccel (kernelCacheSemantics context.model.keys trProj) support []) - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) concrete) + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) concrete) (hI : ScopedWhnfStateInv context.model .noAccel (kernelCacheSemantics context.model.keys trProj) support [] before) (hfault : TcM.LazyFaultPreserves @@ -178,7 +178,7 @@ theorem wf support context.model.keys.uvars [] after ∧ context.model.StateInScope after ∧ TrustedDecl trProj world' id decl := by - let methods := Ix.Tc.methodsN (m := .anon) before.recFuel.toNat + let methods := Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat have hmethods : Methods.ScopedWFAtOn context.model .noAccel (kernelCacheSemantics context.model.keys trProj) support (context.calls (before.recFuel.toNat + 1)) (Methods.next methods) := by @@ -195,7 +195,7 @@ theorem wf unfold TcM.checkConst TcM.isolateCheckErrors TcM.runRec at hrun cases hinner : (RecM.checkConst id).run - (Ix.Tc.methodsN before.recFuel.toNat) before with + (Ix.Kernel.methodsN before.recFuel.toNat) before with | ok value middle => simp only [hinner] at hrun cases hrun @@ -222,8 +222,8 @@ theorem rejected_of_no_decl_wf (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars (context.calls (before.recFuel.toNat + 1)) - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat)) - {concrete : KConst .anon} {decl : Lean4Lean.VDecl} + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat)) + {concrete : KConst .anon} {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -236,7 +236,7 @@ theorem rejected_of_no_decl_wf (WhnfStateInv .noAccel (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars []) - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat) concrete) + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat) concrete) (hI : WhnfStateInv .noAccel (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars [] before) @@ -244,7 +244,7 @@ theorem rejected_of_no_decl_wf (WhnfStateInv .noAccel (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars [])) - (hnotWF : ¬∃ world', Lean4Lean.VDecl.WF world.venv decl world') : + (hnotWF : ¬∃ world', Ix.Theory.Named.VDecl.WF world.venv decl world') : ∃ err failed, TcM.checkConst id before = .error err failed ∧ PendingDecl trProj world id decl := by @@ -272,10 +272,10 @@ theorem axiom_pending_sound (kernelCacheSemantics context.proposition.model.keys trProj) trProj world support context.proposition.model.keys.uvars (context.calls (before.recFuel.toNat + 1)) - (Ix.Tc.methodsN (m := .anon) before.recFuel.toNat)) + (Ix.Kernel.methodsN (m := .anon) before.recFuel.toNat)) {name : Mode.anon.F Name} {levelParams : Mode.anon.F (Array Name)} {isUnsafe : Bool} - {levels : UInt64} {type : KExpr .anon} {decl : Lean4Lean.VDecl} + {levels : UInt64} {type : KExpr .anon} {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -313,4 +313,4 @@ theorem axiom_pending_sound end TcM.checkConst -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/QuotientAdmission.lean b/Ix/Kernel/Verify/Check/QuotientAdmission.lean similarity index 88% rename from Ix/Tc/Verify/Check/QuotientAdmission.lean rename to Ix/Kernel/Verify/Check/QuotientAdmission.lean index d018c0c17..54c609877 100644 --- a/Ix/Tc/Verify/Check/QuotientAdmission.lean +++ b/Ix/Kernel/Verify/Check/QuotientAdmission.lean @@ -1,12 +1,12 @@ -import Ix.Tc.Verify.Env -import Ix.Tc.Primitive -import Lean4Lean.Theory.Typing.QuotLemmas +import Ix.Kernel.Verify.Env +import Ix.Kernel.Primitive +import Ix.Theory.Named.Typing.QuotLemmas /-! # Atomic quotient admission `KConst.quot` declarations are physically standalone entries, but their -semantic meaning is not four independent axioms. Lean4Lean installs `Quot`, +semantic meaning is not four independent axioms. Ix.Theory.Named installs `Quot`, `Quot.mk`, `Quot.lift`, and `Quot.ind` in order and then registers one quotient definitional equation. This file records the corresponding address-keyed Ix boundary without granting a successful check of any one member authority over @@ -16,14 +16,14 @@ The relation deliberately retains each intermediate `VEnv`: later primitive types mention earlier primitives, so translating all four against the initial environment would be false. `QuotientBridge.lean` constructs this relation from four exact `checkQuot` successes, scoped collision freedom, and one -explicit proposition carrying the canonical Lean4Lean semantic transaction. +explicit proposition carrying the canonical Ix.Theory.Named semantic transaction. The theorems below then close the atomic transition without granting authority to any prefix. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDecl VEnv VConstant) +open Ix.Theory.Named (VDecl VEnv VConstant) /-- One address-keyed quotient insertion in the exact environment where its type is interpreted. The final conjunct prevents a prefix from masquerading @@ -76,7 +76,7 @@ theorem le end QuotientAdmissionStep -/-- The complete address-keyed analogue of Lean4Lean's four-step +/-- The complete address-keyed analogue of Ix.Theory.Named's four-step `AddQuot1` chain. The final equality installs the quotient defeq only after all four exact constants have been added. -/ def QuotientBundleAdmission @@ -84,14 +84,14 @@ def QuotientBundleAdmission (trProj : RawProjRel) (prims : Primitives .anon) (before after : VEnv) : Prop := QuotientAdmissionStep catalog nameOf trProj prims.quotType ``Quot - .type Lean4Lean.quotConst (before := before) fun env₁ => + .type Ix.Theory.Named.quotConst (before := before) fun env₁ => QuotientAdmissionStep catalog nameOf trProj prims.quotCtor ``Quot.mk - .ctor Lean4Lean.quotMkConst (before := env₁) fun env₂ => + .ctor Ix.Theory.Named.quotMkConst (before := env₁) fun env₂ => QuotientAdmissionStep catalog nameOf trProj prims.quotLift ``Quot.lift - .lift Lean4Lean.quotLiftConst (before := env₂) fun env₃ => + .lift Ix.Theory.Named.quotLiftConst (before := env₂) fun env₃ => QuotientAdmissionStep catalog nameOf trProj prims.quotInd ``Quot.ind - .ind Lean4Lean.quotIndConst (before := env₃) fun env₄ => - env₄.addDefEq Lean4Lean.quotDefEq = after + .ind Ix.Theory.Named.quotIndConst (before := env₃) fun env₄ => + env₄.addDefEq Ix.Theory.Named.quotDefEq = after /-- The complete semantic acceptance input: the pre-environment already has the canonical `Eq`, and the four-member Ix bundle follows the exact atomic @@ -149,7 +149,7 @@ theorem nameAssignments obtain ⟨_, _, _, _, hind, _, _, _, h₄⟩ := h₃ exact ⟨htype, hctor, hlift, hind⟩ -/-- A complete Ix bundle witness executes Lean4Lean's production-order +/-- A complete Ix bundle witness executes Ix.Theory.Named's production-order `addQuot` operation exactly. -/ theorem toAddQuot {catalog : Catalog} {nameOf : Address → Option Lean.Name} @@ -195,7 +195,7 @@ theorem quotType {trProj : RawProjRel} {prims : Primitives .anon} {before after : VEnv} (h : QuotientBundleAdmission catalog nameOf trProj prims before after) : - after.constants ``Quot = some Lean4Lean.quotConst := + after.constants ``Quot = some Ix.Theory.Named.quotConst := VEnv.addQuot_quot h.toAddQuot /-- The completed bundle installs the exact quotient constructor. -/ @@ -204,7 +204,7 @@ theorem quotCtor {trProj : RawProjRel} {prims : Primitives .anon} {before after : VEnv} (h : QuotientBundleAdmission catalog nameOf trProj prims before after) : - after.constants ``Quot.mk = some Lean4Lean.quotMkConst := + after.constants ``Quot.mk = some Ix.Theory.Named.quotMkConst := VEnv.addQuot_quotMk h.toAddQuot /-- The completed bundle installs the exact computational eliminator. -/ @@ -213,7 +213,7 @@ theorem quotLift {trProj : RawProjRel} {prims : Primitives .anon} {before after : VEnv} (h : QuotientBundleAdmission catalog nameOf trProj prims before after) : - after.constants ``Quot.lift = some Lean4Lean.quotLiftConst := + after.constants ``Quot.lift = some Ix.Theory.Named.quotLiftConst := VEnv.addQuot_quotLift h.toAddQuot /-- The completed bundle installs the exact propositional eliminator. -/ @@ -222,7 +222,7 @@ theorem quotInd {trProj : RawProjRel} {prims : Primitives .anon} {before after : VEnv} (h : QuotientBundleAdmission catalog nameOf trProj prims before after) : - after.constants ``Quot.ind = some Lean4Lean.quotIndConst := + after.constants ``Quot.ind = some Ix.Theory.Named.quotIndConst := VEnv.addQuot_quotInd h.toAddQuot /-- The quotient reduction equation is available only after the entire @@ -232,14 +232,14 @@ theorem quotientDefEq {trProj : RawProjRel} {prims : Primitives .anon} {before after : VEnv} (h : QuotientBundleAdmission catalog nameOf trProj prims before after) : - after.defeqs Lean4Lean.quotDefEq := + after.defeqs Ix.Theory.Named.quotDefEq := VEnv.addQuot_defeq h.toAddQuot end QuotientBundleAdmission namespace QuotientAdmission -/-- The complete Ix-side witness constructs one Lean4Lean quotient +/-- The complete Ix-side witness constructs one Ix.Theory.Named quotient declaration transition; no member can be promoted separately. -/ theorem wf {catalog : Catalog} {nameOf : Address → Option Lean.Name} @@ -260,4 +260,4 @@ theorem le end QuotientAdmission -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/QuotientBoundary.lean b/Ix/Kernel/Verify/Check/QuotientBoundary.lean similarity index 95% rename from Ix/Tc/Verify/Check/QuotientBoundary.lean rename to Ix/Kernel/Verify/Check/QuotientBoundary.lean index 05206d38d..1ea1fb437 100644 --- a/Ix/Tc/Verify/Check/QuotientBoundary.lean +++ b/Ix/Kernel/Verify/Check/QuotientBoundary.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Check.BlockClassification -import Ix.Tc.Verify.Check.QuotientBridge -import Ix.Tc.Verify.Check.StandaloneDriver +import Ix.Kernel.Verify.Check.BlockClassification +import Ix.Kernel.Verify.Check.QuotientBridge +import Ix.Kernel.Verify.Check.StandaloneDriver /-! # Quotient checking is not a coordinated-block transaction @@ -15,7 +15,7 @@ Quotient acceptance therefore uses the separate four-check atomic bridge; it never acquires inductive-oracle or block-cache authority through E0. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -103,4 +103,4 @@ theorem quotientRoute end StandaloneRoute -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/QuotientBridge.lean b/Ix/Kernel/Verify/Check/QuotientBridge.lean similarity index 94% rename from Ix/Tc/Verify/Check/QuotientBridge.lean rename to Ix/Kernel/Verify/Check/QuotientBridge.lean index a07efa63d..8f32fef69 100644 --- a/Ix/Tc/Verify/Check/QuotientBridge.lean +++ b/Ix/Kernel/Verify/Check/QuotientBridge.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Check.QuotientAdmission -import Ix.Tc.Verify.Whnf.RuntimeContracts -import Ix.Tc.Check +import Ix.Kernel.Verify.Check.QuotientAdmission +import Ix.Kernel.Verify.Whnf.RuntimeContracts +import Ix.Kernel.Check /-! # Production quotient bridge @@ -13,9 +13,9 @@ collision hypothesis, and commits a completed `QuotientAdmission` as one trusted-log event. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VEnv) +open Ix.Theory.Named (VEnv) namespace RecM @@ -275,14 +275,14 @@ theorem quotIndLevels_eq end CheckedQuotientBundle -/-! ## Lean4Lean semantic transaction input -/ +/-! ## Ix.Theory.Named semantic transaction input -/ /-- Canonical semantic proposition for the transaction supplied by -Lean4Lean's quotient-environment proof. This is deliberately independent of +Ix.Theory.Named's quotient-environment proof. This is deliberately independent of the physical catalog: the production runs above establish that the four catalog types are these canonical expressions. -Until Lean4Lean's `addQuot.WF` checker-closure theorem is constructive, callers +Until Ix.Theory.Named's `addQuot.WF` checker-closure theorem is constructive, callers may carry this proposition as the narrow temporary assumption. Making it a `Prop` prevents the boundary from supplying executable data. The Ix bridge itself introduces no axiom and exposes every premise that the future upstream @@ -296,39 +296,39 @@ inductive CanonicalQuotientSemanticTransaction (quotTypeName : nameOf prims.quotType.addr = some ``Quot) (quotTypeTranslated : TrKConstant .safe before nameOf trProj (.quot () () .type 1 (RecM.canonicalQuotType prims .type)) - Lean4Lean.quotConst) + Ix.Theory.Named.quotConst) (quotTypeRaw : RawExprRel (uvars := 1) before nameOf trProj [] - (RecM.canonicalQuotType prims .type) Lean4Lean.quotConst.type) - (addQuotType : before.addConst ``Quot Lean4Lean.quotConst = some env₁) + (RecM.canonicalQuotType prims .type) Ix.Theory.Named.quotConst.type) + (addQuotType : before.addConst ``Quot Ix.Theory.Named.quotConst = some env₁) (env₂ : VEnv) (quotCtorName : nameOf prims.quotCtor.addr = some ``Quot.mk) (quotCtorTranslated : TrKConstant .safe env₁ nameOf trProj (.quot () () .ctor 1 (RecM.canonicalQuotType prims .ctor)) - Lean4Lean.quotMkConst) + Ix.Theory.Named.quotMkConst) (quotCtorRaw : RawExprRel (uvars := 1) env₁ nameOf trProj [] - (RecM.canonicalQuotType prims .ctor) Lean4Lean.quotMkConst.type) - (addQuotCtor : env₁.addConst ``Quot.mk Lean4Lean.quotMkConst = some env₂) + (RecM.canonicalQuotType prims .ctor) Ix.Theory.Named.quotMkConst.type) + (addQuotCtor : env₁.addConst ``Quot.mk Ix.Theory.Named.quotMkConst = some env₂) (env₃ : VEnv) (quotLiftName : nameOf prims.quotLift.addr = some ``Quot.lift) (quotLiftTranslated : TrKConstant .safe env₂ nameOf trProj (.quot () () .lift 2 (RecM.canonicalQuotType prims .lift)) - Lean4Lean.quotLiftConst) + Ix.Theory.Named.quotLiftConst) (quotLiftRaw : RawExprRel (uvars := 2) env₂ nameOf trProj [] - (RecM.canonicalQuotType prims .lift) Lean4Lean.quotLiftConst.type) - (addQuotLift : env₂.addConst ``Quot.lift Lean4Lean.quotLiftConst = some env₃) + (RecM.canonicalQuotType prims .lift) Ix.Theory.Named.quotLiftConst.type) + (addQuotLift : env₂.addConst ``Quot.lift Ix.Theory.Named.quotLiftConst = some env₃) (env₄ : VEnv) (quotIndName : nameOf prims.quotInd.addr = some ``Quot.ind) (quotIndTranslated : TrKConstant .safe env₃ nameOf trProj (.quot () () .ind 1 (RecM.canonicalQuotType prims .ind)) - Lean4Lean.quotIndConst) + Ix.Theory.Named.quotIndConst) (quotIndRaw : RawExprRel (uvars := 1) env₃ nameOf trProj [] - (RecM.canonicalQuotType prims .ind) Lean4Lean.quotIndConst.type) - (addQuotInd : env₃.addConst ``Quot.ind Lean4Lean.quotIndConst = some env₄) - (final : env₄.addDefEq Lean4Lean.quotDefEq = after) + (RecM.canonicalQuotType prims .ind) Ix.Theory.Named.quotIndConst.type) + (addQuotInd : env₃.addConst ``Quot.ind Ix.Theory.Named.quotIndConst = some env₄) + (final : env₄.addDefEq Ix.Theory.Named.quotDefEq = after) namespace CheckedQuotientBundle -/-- Combine four successful physical checks with the canonical Lean4Lean +/-- Combine four successful physical checks with the canonical Ix.Theory.Named transaction. Production supplies exact roles, arities, and collision-safe types; the semantic input supplies the ordered `addQuot` meaning. -/ theorem toAdmission @@ -385,7 +385,7 @@ inductive QuotientMembers (prims : Primitives .anon) : KId .anon → Prop namespace QuotientAdmission -/-- Replaying the single Lean4Lean quotient declaration after a well-formed +/-- Replaying the single Ix.Theory.Named quotient declaration after a well-formed prefix produces a well-formed post-environment. -/ theorem afterWF {catalog : Catalog} {nameOf : Address → Option Lean.Name} @@ -582,7 +582,7 @@ theorem admittedStateWF intern := hstate.intern } /-- End-to-end quotient bridge: a coherent concrete/ghost state, four exact -production runs, scoped collision freedom, freshness, and the Lean4Lean +production runs, scoped collision freedom, freshness, and the Ix.Theory.Named semantic transaction yield one exact four-member promotion and one trusted-log event while preserving the checker-state invariant. -/ theorem admitAtomically @@ -607,4 +607,4 @@ theorem admitAtomically end CheckedQuotientBundle -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/RecursiveMethodPolicy.lean b/Ix/Kernel/Verify/Check/RecursiveMethodPolicy.lean similarity index 97% rename from Ix/Tc/Verify/Check/RecursiveMethodPolicy.lean rename to Ix/Kernel/Verify/Check/RecursiveMethodPolicy.lean index 035fec191..573ed87c4 100644 --- a/Ix/Tc/Verify/Check/RecursiveMethodPolicy.lean +++ b/Ix/Kernel/Verify/Check/RecursiveMethodPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.DefEqCachePolicy +import Ix.Kernel.Verify.Check.DefEqCachePolicy /-! # Operational closure of the recursive method table @@ -9,7 +9,7 @@ with the same six-field frame. This is the non-circular one-layer theorem needed to close every finite `methodsN` approximation. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace Methods @@ -78,4 +78,4 @@ theorem methodsN_concrete_preservesInferOnly (depth : Nat) : end Methods -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ResetFrame.lean b/Ix/Kernel/Verify/Check/ResetFrame.lean similarity index 97% rename from Ix/Tc/Verify/Check/ResetFrame.lean rename to Ix/Kernel/Verify/Check/ResetFrame.lean index 7cd4e1bec..94f777c42 100644 --- a/Ix/Tc/Verify/Check/ResetFrame.lean +++ b/Ix/Kernel/Verify/Check/ResetFrame.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.MemberEvidence +import Ix.Kernel.Verify.Check.MemberEvidence /-! # Per-constant reset framing @@ -9,7 +9,7 @@ local-context invariant while retaining the stable kernel/cache state needed by the fixed method table. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -99,4 +99,4 @@ theorem reset_whnf_entry end TcM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/SafetyFrame.lean b/Ix/Kernel/Verify/Check/SafetyFrame.lean similarity index 98% rename from Ix/Tc/Verify/Check/SafetyFrame.lean rename to Ix/Kernel/Verify/Check/SafetyFrame.lean index a142a95f2..816416774 100644 --- a/Ix/Tc/Verify/Check/SafetyFrame.lean +++ b/Ix/Kernel/Verify/Check/SafetyFrame.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.ValidatorFrame +import Ix.Kernel.Verify.Check.ValidatorFrame /-! # State framing for the unsafe-reference traversal @@ -9,7 +9,7 @@ state only through optional constant lookup. Consequently every outcome preserves any invariant framed by the installed lazy-ingress hook. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -139,4 +139,4 @@ theorem checkNoUnsafeRefs_frame end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/Scoped.lean b/Ix/Kernel/Verify/Check/Scoped.lean similarity index 89% rename from Ix/Tc/Verify/Check/Scoped.lean rename to Ix/Kernel/Verify/Check/Scoped.lean index f40b095bb..9f4ced707 100644 --- a/Ix/Tc/Verify/Check/Scoped.lean +++ b/Ix/Kernel/Verify/Check/Scoped.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Level -import Ix.Tc.Verify.Totalization +import Ix.Kernel.Verify.Level +import Ix.Kernel.Verify.Totalization + +open Ix.Theory (VLevel) /-! # Successful well-scopedness validation @@ -15,7 +17,7 @@ The operational proof below it is kept separate from typing; in particular, being admissible. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KUniv @@ -34,11 +36,11 @@ theorem scoped_iff_toVLevel_wf {u : KUniv m} {bound : Nat} : u.Scoped bound ↔ u.toVLevel.WF bound := by induction u with | zero => rfl - | succ u _ ih => simpa [Scoped, toVLevel, Lean4Lean.VLevel.WF] using ih + | succ u _ ih => simpa [Scoped, toVLevel, Ix.Theory.VLevel.WF] using ih | max a b _ iha ihb => - simp only [Scoped, toVLevel, Lean4Lean.VLevel.WF, iha, ihb] + simp only [Scoped, toVLevel, Ix.Theory.VLevel.WF, iha, ihb] | imax a b _ iha ihb => - simp only [Scoped, toVLevel, Lean4Lean.VLevel.WF, iha, ihb] + simp only [Scoped, toVLevel, Ix.Theory.VLevel.WF, iha, ihb] | param => rfl theorem Scoped.toVLevel_wf {u : KUniv m} {bound : Nat} @@ -74,4 +76,4 @@ def Scoped (depth : UInt64) (levelBound : Nat) : KExpr m → Prop end KExpr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ScopedActiveBlock.lean b/Ix/Kernel/Verify/Check/ScopedActiveBlock.lean similarity index 98% rename from Ix/Tc/Verify/Check/ScopedActiveBlock.lean rename to Ix/Kernel/Verify/Check/ScopedActiveBlock.lean index 082219fde..4768295e6 100644 --- a/Ix/Tc/Verify/Check/ScopedActiveBlock.lean +++ b/Ix/Kernel/Verify/Check/ScopedActiveBlock.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Check.BlockTransaction -import Ix.Tc.Verify.Inductive.StructuralCacheSemantics -import Ix.Tc.Verify.RecursiveMethods.ScopedInference +import Ix.Kernel.Verify.Check.BlockTransaction +import Ix.Kernel.Verify.Inductive.StructuralCacheSemantics +import Ix.Kernel.Verify.RecursiveMethods.ScopedInference /-! # Run-scoped recursive methods inside an active coordinated block @@ -18,7 +18,7 @@ WHNF, inference, or DefEq cache entries; that restriction remains enforced by can consume the active-member disjunct. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The complete K1/K2 state invariant while one exact coordinated block is active, refined by membership in a finite suffix-model state domain. -/ @@ -262,7 +262,7 @@ theorem isDefEq_eq_activeScoped_wf {support : RunSupport} {members : Array (KId .anon)} {Delta : KVLCtx} {state : TcState .anon} {left right : KExpr .anon} - {leftV rightV : Lean4Lean.VExpr} + {leftV rightV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world model.keys.uvars) (same : left = right) (leftTranslation : TrKExprS world.venv model.keys.uvars world.nameOf @@ -296,7 +296,7 @@ theorem isDefEq_eq_activeScoped_wf leftTranslation rightTranslation _ answerTrue intro _ exact ⟨leftV, leftV, leftTranslation, leftTranslation, - Lean4Lean.VEnv.IsDefEqU.refl + Ix.Theory.Named.VEnv.IsDefEqU.refl (theory.exprWF hI.context leftTranslation)⟩ end RecM @@ -384,4 +384,4 @@ theorem methodsOut_activeScopedWFAtOn end Methods -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ScopedBoundedPipelines.lean b/Ix/Kernel/Verify/Check/ScopedBoundedPipelines.lean similarity index 96% rename from Ix/Tc/Verify/Check/ScopedBoundedPipelines.lean rename to Ix/Kernel/Verify/Check/ScopedBoundedPipelines.lean index ffdb5cf89..b81ed4d73 100644 --- a/Ix/Tc/Verify/Check/ScopedBoundedPipelines.lean +++ b/Ix/Kernel/Verify/Check/ScopedBoundedPipelines.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.BoundedPipelines -import Ix.Tc.Verify.RecursiveMethods.ScopedCallDomains +import Ix.Kernel.Verify.Check.BoundedPipelines +import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Run-scoped standalone-checker pipelines @@ -9,7 +9,7 @@ every method callback. It deliberately consumes `Methods.ScopedWFAtOn` directly and contains no conversion to the legacy global suffix model. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace Methods @@ -21,7 +21,7 @@ def ScopedFullInferenceWFAtOn (support : RunSupport) (calls : CallDomain) (methods : Methods .anon) : Prop := ∀ {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr}, + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr}, calls.infer source → s.inferOnly = false → PreTrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source @@ -48,7 +48,7 @@ theorem ofTypedIngress (kernelCacheSemantics model.keys trProj) support calls methods) (policy : methods.PreservesInferOnly) (upgrade : ∀ {Delta : KVLCtx} {source : KExpr .anon} - {sourceV : Lean4Lean.VExpr}, + {sourceV : Ix.Theory.Named.VExpr}, calls.infer source → PreTrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV → @@ -104,13 +104,13 @@ structure ScopedStandalonePipelineResources valueInfer : ∀ {value declaredType}, valueSources value declaredType → calls.infer value typeWhnf : ∀ {Delta : KVLCtx} {source : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {inferred : KExpr .anon}, + {sourceV : Ix.Theory.Named.VExpr} {inferred : KExpr .anon}, typeSources source → FullInferPost trProj world support model.keys.uvars Delta source sourceV inferred → calls.AdmitsEnsureSortDirect inferred valueDefEq : ∀ {Delta : KVLCtx} {value declaredType : KExpr .anon} - {valueV : Lean4Lean.VExpr} {inferred : KExpr .anon}, + {valueV : Ix.Theory.Named.VExpr} {inferred : KExpr .anon}, valueSources value declaredType → FullInferPost trProj world support model.keys.uvars Delta value valueV inferred → @@ -176,7 +176,7 @@ private theorem ensureSortDirect_scopedWFAtOn {model : ScopedKernelSuffixModel trProj world} {support : RunSupport} {calls : Methods.CallDomain} {methods : Methods .anon} {Delta : KVLCtx} {s : TcState .anon} - {input : KExpr .anon} {inputV : Lean4Lean.VExpr} + {input : KExpr .anon} {inputV : Ix.Theory.Named.VExpr} (hmethods : Methods.ScopedWFAtOn model .noAccel (kernelCacheSemantics model.keys trProj) support calls (Methods.next methods)) @@ -239,7 +239,7 @@ theorem checkTypePipeline_scoped_sound (Methods.next methods)) (hpolicyMethods : (Methods.next methods).PreservesInferOnly) {Delta : KVLCtx} {s after : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceCall : resources.typeSources source) (hsource : PreTrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) @@ -330,7 +330,7 @@ theorem checkValuePipeline_scoped_sound (Methods.next methods)) {Delta : KVLCtx} {s after : TcState .anon} {value declaredType : KExpr .anon} - {valueV declaredTypeV : Lean4Lean.VExpr} + {valueV declaredTypeV : Ix.Theory.Named.VExpr} (hvalueCall : resources.valueSources value declaredType) (hvalue : PreTrKExprS world.venv model.keys.uvars world.nameOf trProj Delta value valueV) @@ -407,4 +407,4 @@ theorem checkValuePipeline_scoped_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ScopedMemberEvidence.lean b/Ix/Kernel/Verify/Check/ScopedMemberEvidence.lean similarity index 98% rename from Ix/Tc/Verify/Check/ScopedMemberEvidence.lean rename to Ix/Kernel/Verify/Check/ScopedMemberEvidence.lean index d30735c47..450878f28 100644 --- a/Ix/Tc/Verify/Check/ScopedMemberEvidence.lean +++ b/Ix/Kernel/Verify/Check/ScopedMemberEvidence.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Check.MemberEvidence -import Ix.Tc.Verify.Check.ScopedBoundedPipelines -import Ix.Tc.Verify.Check.SafetyFrame +import Ix.Kernel.Verify.Check.MemberEvidence +import Ix.Kernel.Verify.Check.ScopedBoundedPipelines +import Ix.Kernel.Verify.Check.SafetyFrame /-! # Run-scoped evidence from standalone member checking @@ -12,7 +12,7 @@ state carries the original model's `StateInScope` witness alongside the rebased checker invariant. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -79,7 +79,7 @@ theorem checkConstMember_axiom_scoped_sound {id : KId .anon} {name : Mode.anon.F Name} {levelParams : Mode.anon.F (Array Name)} {isUnsafe : Bool} {levels : UInt64} {type : KExpr .anon} - {typeV : Lean4Lean.VExpr} + {typeV : Ix.Theory.Named.VExpr} (hresources : StandaloneValidationResources support (.axio name levelParams isUnsafe levels type)) (hsourceCall : context.typeSources type) @@ -144,7 +144,7 @@ theorem checkConstMember_defn_scoped_sound {safety : Ix.DefinitionSafety} {hints : Lean.ReducibilityHints} {levels : UInt64} {type value : KExpr .anon} {leanAll : Mode.anon.F (Array (KId .anon))} {block : KId .anon} - {typeV valueV : Lean4Lean.VExpr} + {typeV valueV : Ix.Theory.Named.VExpr} (hresources : StandaloneValidationResources support (.defn name levelParams kind safety hints levels type value leanAll block)) @@ -319,7 +319,7 @@ theorem checkConstMember_scoped_sound (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hingress : PreDeclRel world.venv world.nameOf trProj id concrete decl) (hcovers : context.Covers concrete) (hresources : StandaloneValidationResources support concrete) @@ -376,7 +376,7 @@ theorem checkConstMember_scoped_pending_sound (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -416,4 +416,4 @@ theorem checkConstMember_scoped_pending_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ScopedPositiveFuelAxiom.lean b/Ix/Kernel/Verify/Check/ScopedPositiveFuelAxiom.lean similarity index 96% rename from Ix/Tc/Verify/Check/ScopedPositiveFuelAxiom.lean rename to Ix/Kernel/Verify/Check/ScopedPositiveFuelAxiom.lean index bbc0a1d44..8fd04565e 100644 --- a/Ix/Tc/Verify/Check/ScopedPositiveFuelAxiom.lean +++ b/Ix/Kernel/Verify/Check/ScopedPositiveFuelAxiom.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.PositiveFuelSort -import Ix.Tc.Verify.Check.PublicStandalone +import Ix.Kernel.Verify.Check.PositiveFuelSort +import Ix.Kernel.Verify.Check.PublicStandalone /-! # Executed positive-fuel checker over a finite suffix model @@ -10,7 +10,7 @@ closed eager states; the method schedule admits exactly the one sort inference performed by the checker. -/ -namespace Ix.Tc.PositiveFuelSort.Checker +namespace Ix.Kernel.PositiveFuelSort.Checker open PositiveFuelSort @@ -18,7 +18,7 @@ def targetAddress : Address := ⟨⟨Array.replicate 32 (37 : UInt8)⟩⟩ def targetId : KId .anon := ⟨targetAddress, ()⟩ -def targetName : Lean.Name := `Ix.Tc.Verify.positiveFuelSortAxiom +def targetName : Lean.Name := `Ix.Kernel.Verify.positiveFuelSortAxiom def catalog : Catalog := fun id => if id == targetId then some concreteAxiom else none @@ -39,7 +39,7 @@ def world : VerifyWorld where world.nameOf targetId.addr = some targetName := by simp [world, targetId] -def declaration : Lean4Lean.VDecl := +def declaration : Ix.Theory.Named.VDecl := .axiom { name := targetName, uvars := 0, type := .sort .zero } theorem rawDeclaration : @@ -58,7 +58,7 @@ theorem pending : rw [hsource] at href simp [KExpr.References] at href · intro name hname - change Lean4Lean.VEnv.empty.constants name = none + change Ix.Theory.Named.VEnv.empty.constants name = none rfl def env : KEnv .anon := @@ -134,8 +134,8 @@ def theory : WhnfTheory RawProjRel.none world model.keys.uvars where literalWF := by intro literal hliteral cases literal <;> - simp [world, Lean4Lean.VEnv.ContainsLits, - Lean4Lean.VEnv.contains, Lean4Lean.VEnv.empty] at hliteral + simp [world, Ix.Theory.Named.VEnv.ContainsLits, + Ix.Theory.Named.VEnv.contains, Ix.Theory.Named.VEnv.empty] at hliteral projections := RawProjRel.none_ok world.venv model.keys.uvars theorem trustedReferences : RecM.TrustedReferences world support := by @@ -155,14 +155,14 @@ theorem methodContract (separation : AddressSeparation) : Methods.ScopedWFAtOn model .noAccel (kernelCacheSemantics model.keys RawProjRel.none) support (.singletonInfer source) - (Methods.next (Ix.Tc.methodsN (m := .anon) 1)) := by + (Methods.next (Ix.Kernel.methodsN (m := .anon) 1)) := by simpa [Methods.ScopedSortSchedule.calls] using (schedule separation).nextSelected theorem fullInference (separation : AddressSeparation) : Methods.ScopedFullInferenceWFAtOn model support (.singletonInfer source) - (Methods.next (Ix.Tc.methodsN (m := .anon) 1)) := + (Methods.next (Ix.Kernel.methodsN (m := .anon) 1)) := Methods.ScopedFullInferenceWFAtOn.ofSingletonSort (methodContract separation) (Methods.next_preservesInferOnly _ @@ -170,7 +170,7 @@ theorem fullInference (separation : AddressSeparation) : def pipelines (separation : AddressSeparation) : ScopedStandalonePipelineResources model support - (.singletonInfer source) (Ix.Tc.methodsN (m := .anon) 1) := + (.singletonInfer source) (Ix.Kernel.methodsN (m := .anon) 1) := ScopedStandalonePipelineResources.singletonSortAxiom (fullInference separation) sortResources supported_is_sort @@ -197,7 +197,7 @@ theorem validationResources : /-! ## Exact production execution -/ -def methods : Methods .anon := Ix.Tc.methodsN 1 +def methods : Methods .anon := Ix.Kernel.methodsN 1 theorem initial_loaded : initialState.env.get? targetId = some concreteAxiom := by @@ -487,4 +487,4 @@ theorem checked_and_promoted (separation : AddressSeparation) : hevidence.1.1.rebaseWorld hpromotes.1 hcore, hevidence.1.2, htrusted⟩ -end Ix.Tc.PositiveFuelSort.Checker +end Ix.Kernel.PositiveFuelSort.Checker diff --git a/Ix/Tc/Verify/Check/ScopedPositiveFuelCertificate.lean b/Ix/Kernel/Verify/Check/ScopedPositiveFuelCertificate.lean similarity index 98% rename from Ix/Tc/Verify/Check/ScopedPositiveFuelCertificate.lean rename to Ix/Kernel/Verify/Check/ScopedPositiveFuelCertificate.lean index b9060b27e..bb9f4a65c 100644 --- a/Ix/Tc/Verify/Check/ScopedPositiveFuelCertificate.lean +++ b/Ix/Kernel/Verify/Check/ScopedPositiveFuelCertificate.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.ScopedPositiveFuelAxiom +import Ix.Kernel.Verify.Check.ScopedPositiveFuelAxiom /-! # Execution certificate for the scoped positive-fuel checker @@ -9,7 +9,7 @@ operation; reset, validation, lookup, routing, and cache insertion are certified silent steps. -/ -namespace Ix.Tc.PositiveFuelSort.Checker +namespace Ix.Kernel.PositiveFuelSort.Checker theorem tryGetConst_requests_of_loaded {state : TcState .anon} {id : KId .anon} {constant : KConst .anon} @@ -312,4 +312,4 @@ def publicContext (separation : AddressSeparation) : schedule := by simpa [initialState] using schedule separation -end Ix.Tc.PositiveFuelSort.Checker +end Ix.Kernel.PositiveFuelSort.Checker diff --git a/Ix/Tc/Verify/Check/ScopedStandaloneDriver.lean b/Ix/Kernel/Verify/Check/ScopedStandaloneDriver.lean similarity index 98% rename from Ix/Tc/Verify/Check/ScopedStandaloneDriver.lean rename to Ix/Kernel/Verify/Check/ScopedStandaloneDriver.lean index adbeeccf0..14df5a649 100644 --- a/Ix/Tc/Verify/Check/ScopedStandaloneDriver.lean +++ b/Ix/Kernel/Verify/Check/ScopedStandaloneDriver.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.ScopedMemberEvidence -import Ix.Tc.Verify.Check.StandaloneDriver +import Ix.Kernel.Verify.Check.ScopedMemberEvidence +import Ix.Kernel.Verify.Check.StandaloneDriver /-! # Run-scoped standalone per-constant driver @@ -11,7 +11,7 @@ frame theorem. Its effect on a suffix model's chosen state domain is therefore exposed as a small, explicit contract. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -30,7 +30,7 @@ theorem checkConstMemberFresh_scoped_pending_evidence (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -113,7 +113,7 @@ theorem checkConstMemberFresh_scoped_pending_sound (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -195,7 +195,7 @@ theorem checkConst_standalone_scoped_pending_sound (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -259,4 +259,4 @@ theorem checkConst_standalone_scoped_pending_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/SingletonInductive.lean b/Ix/Kernel/Verify/Check/SingletonInductive.lean similarity index 92% rename from Ix/Tc/Verify/Check/SingletonInductive.lean rename to Ix/Kernel/Verify/Check/SingletonInductive.lean index 3e8f38327..4e0679e3c 100644 --- a/Ix/Tc/Verify/Check/SingletonInductive.lean +++ b/Ix/Kernel/Verify/Check/SingletonInductive.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Check.BlockOracle -import Ix.Tc.Verify.Inductive.IngressExecution -import Ix.Tc.Verify.Inductive.SingletonIngress -import Ix.Tc.Verify.Inductive.SingletonOracle +import Ix.Kernel.Verify.Check.BlockOracle +import Ix.Kernel.Verify.Inductive.IngressExecution +import Ix.Kernel.Verify.Inductive.SingletonIngress +import Ix.Kernel.Verify.Inductive.SingletonOracle /-! # Certificate-backed singleton family blocks @@ -17,7 +17,7 @@ certifies that block with the enumeration oracle built from its registered generated equations. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace SingletonFamilyCatalogLink @@ -26,7 +26,7 @@ for an E0 inductive-block trace. -/ def blockResources {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} (link : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx) @@ -49,7 +49,7 @@ one-member production recursor block. -/ def blockResources {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} {family : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx} @@ -76,7 +76,7 @@ combining E0's exact trace with E2a/E2b's exact catalog link. -/ theorem certifySingletonFamilyBlock {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} (link : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx) @@ -95,7 +95,7 @@ combining E0's exact trace with E2a/E2b's generated-rule correspondence. -/ theorem certifySingletonRecursorBlock {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} {family : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx} @@ -123,7 +123,7 @@ before the family exists semantically. -/ theorem certifySingletonFamilyBlockPostAdmission {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} (link : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx) @@ -144,7 +144,7 @@ theorem certifySingletonFamilyBlockPostAdmission theorem certifySingletonRecursorBlockPostAdmission {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} {family : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx} @@ -174,7 +174,7 @@ trace prove that none of the linked addresses was already admitted. -/ theorem certifySingletonFamilyIngressBlock {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} {block requested : KId .anon} {before after : TcState .anon} (view : SingletonFamilyIngressView trProj after.env world.nameOf tx) @@ -191,12 +191,12 @@ theorem certifySingletonFamilyIngressBlock /-- Certify an actual successful singleton recursor block from the recursor entry loaded in its production post-state. The preceding family link fixes -the constructor order used by both the Ix rule array and Lean4Lean's +the constructor order used by both the Ix rule array and Ix.Theory.Named's generated equations. -/ theorem certifySingletonRecursorIngressBlock {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} {family : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx} @@ -225,7 +225,7 @@ trace, loaded-catalog invariant, trusted log, and E2a transaction. -/ theorem certifySingletonFamilyIngressExecution {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} {ixonEnv : Ixon.Env} {blockConstant : Ixon.Constant} {blockAddr : Address} {ingressBefore ingressAfter : AnonEnv} @@ -260,7 +260,7 @@ the supported enumeration shape. -/ theorem certifySingletonRecursorIngressExecution {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} - {source : Lean4Lean.VInductDecl} {theoryAfter : Lean4Lean.VEnv} + {source : Ix.Theory.Named.VInductDecl} {theoryAfter : Ix.Theory.Named.VEnv} {tx : CertifiedGenerationTransaction source world.venv theoryAfter} {family : SingletonFamilyCatalogLink trProj world.catalog world.nameOf world.trusted tx} @@ -294,4 +294,4 @@ theorem certifySingletonRecursorIngressExecution end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/StandaloneDriver.lean b/Ix/Kernel/Verify/Check/StandaloneDriver.lean similarity index 98% rename from Ix/Tc/Verify/Check/StandaloneDriver.lean rename to Ix/Kernel/Verify/Check/StandaloneDriver.lean index c47ac7633..5e4f707c1 100644 --- a/Ix/Tc/Verify/Check/StandaloneDriver.lean +++ b/Ix/Kernel/Verify/Check/StandaloneDriver.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.ResetFrame +import Ix.Kernel.Verify.Check.ResetFrame /-! # Standalone per-constant driver @@ -10,7 +10,7 @@ catalog agreement proof prevents a successful lazy lookup from silently changing which pending declaration is certified. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Operational boundary separating K3 standalone checking from E0 block coordination. The exact production router must preserve the checker @@ -55,7 +55,7 @@ theorem checkConstMemberFresh_pending_sound model.keys.uvars calls (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -136,7 +136,7 @@ theorem checkConstMemberFresh_pending_evidence model.keys.uvars calls (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -219,7 +219,7 @@ theorem checkConst_standalone_pending_sound model.keys.uvars calls (Methods.next methods)) (hmethodPolicy : (Methods.next methods).PreservesInferOnly) {id : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} + {decl : Ix.Theory.Named.VDecl} (hprojection : trProj.SubstCompatible) (hliterals : ∀ literal, world.venv.ContainsLits literal) (hpending : PendingDecl trProj world id decl) @@ -283,4 +283,4 @@ theorem checkConst_standalone_pending_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/UncachedInferencePolicy.lean b/Ix/Kernel/Verify/Check/UncachedInferencePolicy.lean similarity index 98% rename from Ix/Tc/Verify/Check/UncachedInferencePolicy.lean rename to Ix/Kernel/Verify/Check/UncachedInferencePolicy.lean index 047063dab..899d59afc 100644 --- a/Ix/Tc/Verify/Check/UncachedInferencePolicy.lean +++ b/Ix/Kernel/Verify/Check/UncachedInferencePolicy.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.UniverseInstantiationPolicy -import Ix.Tc.Verify.Check.FullInferenceProjections +import Ix.Kernel.Verify.Check.UniverseInstantiationPolicy +import Ix.Kernel.Verify.Check.FullInferenceProjections /-! # Operational policy for uncached inference @@ -16,7 +16,7 @@ last premise needed to feed this theorem into the already verified inference cache shell. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -286,4 +286,4 @@ theorem inferUncached_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/UniverseInstantiationPolicy.lean b/Ix/Kernel/Verify/Check/UniverseInstantiationPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/UniverseInstantiationPolicy.lean rename to Ix/Kernel/Verify/Check/UniverseInstantiationPolicy.lean index 32b2c7e55..5fde07bc6 100644 --- a/Ix/Tc/Verify/Check/UniverseInstantiationPolicy.lean +++ b/Ix/Kernel/Verify/Check/UniverseInstantiationPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.InferencePolicy +import Ix.Kernel.Verify.Check.InferencePolicy /-! # Inference-policy frame for universe instantiation @@ -15,7 +15,7 @@ constant-universe array loop, recursive child failures, interning, and memo writes on both outcomes. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM.PreservesInferOnly @@ -277,4 +277,4 @@ theorem instantiateUnivParams (e : KExpr .anon) end TcM.PreservesInferOnly -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ValidationReach.lean b/Ix/Kernel/Verify/Check/ValidationReach.lean similarity index 99% rename from Ix/Tc/Verify/Check/ValidationReach.lean rename to Ix/Kernel/Verify/Check/ValidationReach.lean index 23181e518..956aeddce 100644 --- a/Ix/Tc/Verify/Check/ValidationReach.lean +++ b/Ix/Kernel/Verify/Check/ValidationReach.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.Scoped -import Ix.Tc.Verify.Support +import Ix.Kernel.Verify.Check.Scoped +import Ix.Kernel.Verify.Support /-! # Finite syntax support for well-scopedness validation @@ -15,7 +15,7 @@ connects their finite footprints to an existing `RunSupport`, whose separate `CollisionFree` field is consumed by the operational proof. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KUniv @@ -404,4 +404,4 @@ end ValidationCoverage end KExpr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ValidatorFrame.lean b/Ix/Kernel/Verify/Check/ValidatorFrame.lean similarity index 99% rename from Ix/Tc/Verify/Check/ValidatorFrame.lean rename to Ix/Kernel/Verify/Check/ValidatorFrame.lean index dc4b37e0d..adee2bc3b 100644 --- a/Ix/Tc/Verify/Check/ValidatorFrame.lean +++ b/Ix/Kernel/Verify/Check/ValidatorFrame.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.DeclarationValidation -import Ix.Tc.Verify.Whnf.RuntimeContracts +import Ix.Kernel.Verify.Check.DeclarationValidation +import Ix.Kernel.Verify.Whnf.RuntimeContracts /-! # State framing for the scoping validators @@ -11,7 +11,7 @@ starts. This module proves that every validator outcome preserves an arbitrary state invariant whose installed lazy-fault hook preserves it. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -314,4 +314,4 @@ theorem validateConstWellScoped_frame end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/ValidatorSoundness.lean b/Ix/Kernel/Verify/Check/ValidatorSoundness.lean similarity index 99% rename from Ix/Tc/Verify/Check/ValidatorSoundness.lean rename to Ix/Kernel/Verify/Check/ValidatorSoundness.lean index 9b23fd76e..259f94b5b 100644 --- a/Ix/Tc/Verify/Check/ValidatorSoundness.lean +++ b/Ix/Kernel/Verify/Check/ValidatorSoundness.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.ValidationReach +import Ix.Kernel.Verify.Check.ValidationReach /-! # Soundness of the address-memoized scoping validators @@ -16,7 +16,7 @@ local guards imply full structural scoping. Address equality is converted to syntax equality only through finite-run collision freedom. -/ -namespace Ix.Tc +namespace Ix.Kernel open Std (HashSet) @@ -1220,4 +1220,4 @@ theorem validateExprWellScoped_sound end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfBasicHelperPolicy.lean b/Ix/Kernel/Verify/Check/WhnfBasicHelperPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfBasicHelperPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfBasicHelperPolicy.lean index 75c10e05c..b09951b81 100644 --- a/Ix/Tc/Verify/Check/WhnfBasicHelperPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfBasicHelperPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfReductionPolicy +import Ix.Kernel.Verify.Check.WhnfReductionPolicy /-! # Operational policy for non-recursive WHNF helpers @@ -11,7 +11,7 @@ application-finisher components rather than retained as an independent assumption. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -455,4 +455,4 @@ theorem tryQuotReduce_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfBitVecPolicy.lean b/Ix/Kernel/Verify/Check/WhnfBitVecPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfBitVecPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfBitVecPolicy.lean index c161a1354..19fdef3c7 100644 --- a/Ix/Tc/Verify/Check/WhnfBitVecPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfBitVecPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfNatPolicy +import Ix.Kernel.Verify.Check.WhnfNatPolicy /-! # Operational inference-policy frame for BitVec reduction @@ -9,7 +9,7 @@ pipeline. All recursive WHNF calls, fallback paths, and rebuilt applications restore the caller's inference policy. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -489,4 +489,4 @@ theorem tryReduceBitvec_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfDecidablePolicy.lean b/Ix/Kernel/Verify/Check/WhnfDecidablePolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfDecidablePolicy.lean rename to Ix/Kernel/Verify/Check/WhnfDecidablePolicy.lean index c3a07dc68..acb0d2b37 100644 --- a/Ix/Tc/Verify/Check/WhnfDecidablePolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfDecidablePolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfBitVecPolicy +import Ix.Kernel.Verify.Check.WhnfBitVecPolicy /-! # Operational inference-policy frame for decidability reduction @@ -9,7 +9,7 @@ recursive type normalization, canonical proof-term interning, application rebuilding, and every accelerator fallback. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -348,4 +348,4 @@ theorem tryReduceDecidable_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfDriverPolicy.lean b/Ix/Kernel/Verify/Check/WhnfDriverPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfDriverPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfDriverPolicy.lean index a82b59ff0..2736c89b0 100644 --- a/Ix/Tc/Verify/Check/WhnfDriverPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfDriverPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.ProjectionInferencePolicy +import Ix.Kernel.Verify.Check.ProjectionInferencePolicy /-! # Operational inference-policy frame for WHNF drivers @@ -14,7 +14,7 @@ individual structural, no-delta, and full-WHNF helper seams; this file ensures that no additional policy obligation is hidden in the outer drivers. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -547,4 +547,4 @@ theorem whnf_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfHelperPolicy.lean b/Ix/Kernel/Verify/Check/WhnfHelperPolicy.lean similarity index 95% rename from Ix/Tc/Verify/Check/WhnfHelperPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfHelperPolicy.lean index 28c3653c2..0a97dcae8 100644 --- a/Ix/Tc/Verify/Check/WhnfHelperPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfHelperPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfIotaDispatchPolicy +import Ix.Kernel.Verify.Check.WhnfIotaDispatchPolicy /-! # Concrete operational policy for every WHNF helper @@ -10,7 +10,7 @@ quotient reduction, and delta unfolding are all tied to their concrete implementations under one fixed predecessor method table. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -41,4 +41,4 @@ def concreteWhnfReductionPolicy end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfIotaBasePolicy.lean b/Ix/Kernel/Verify/Check/WhnfIotaBasePolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfIotaBasePolicy.lean rename to Ix/Kernel/Verify/Check/WhnfIotaBasePolicy.lean index 5b085de0c..5d4762dca 100644 --- a/Ix/Tc/Verify/Check/WhnfIotaBasePolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfIotaBasePolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfDecidablePolicy +import Ix.Kernel.Verify.Check.WhnfDecidablePolicy /-! # Operational inference-policy frame for iota rule execution @@ -10,7 +10,7 @@ workers are proved together over their shared fuel, so their production fallback behavior remains explicit. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -283,4 +283,4 @@ theorem cleanupNatOffsetMajor_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfIotaDispatchPolicy.lean b/Ix/Kernel/Verify/Check/WhnfIotaDispatchPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfIotaDispatchPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfIotaDispatchPolicy.lean index 989acfbce..a59f178d5 100644 --- a/Ix/Tc/Verify/Check/WhnfIotaDispatchPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfIotaDispatchPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfIotaSynthesisPolicy +import Ix.Kernel.Verify.Check.WhnfIotaSynthesisPolicy /-! # Operational inference-policy frame for complete iota dispatch @@ -10,7 +10,7 @@ major normalization. Its public theorem covers every branch of production the WHNF reducer frame. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -267,4 +267,4 @@ theorem tryIotaWithFlags_preservesInferOnly exact TcM.PreservesInferOnly.pure none end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfIotaRecursionPolicy.lean b/Ix/Kernel/Verify/Check/WhnfIotaRecursionPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfIotaRecursionPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfIotaRecursionPolicy.lean index 15597b74f..4af485247 100644 --- a/Ix/Tc/Verify/Check/WhnfIotaRecursionPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfIotaRecursionPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfIotaScopePolicy +import Ix.Kernel.Verify.Check.WhnfIotaScopePolicy /-! # Operational inference-policy frame for iota recursion classification @@ -9,7 +9,7 @@ bounded field scanning, legacy-context restoration, provisional and final cache writes, and cleanup of the provisional entry on classifier errors. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -309,4 +309,4 @@ theorem computedIsRec_preservesInferOnly exact TcM.PreservesInferOnly.throw _ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfIotaScopePolicy.lean b/Ix/Kernel/Verify/Check/WhnfIotaScopePolicy.lean similarity index 98% rename from Ix/Tc/Verify/Check/WhnfIotaScopePolicy.lean rename to Ix/Kernel/Verify/Check/WhnfIotaScopePolicy.lean index d9edfcdb4..acf05e7da 100644 --- a/Ix/Tc/Verify/Check/WhnfIotaScopePolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfIotaScopePolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfIotaBasePolicy +import Ix.Kernel.Verify.Check.WhnfIotaBasePolicy /-! # Operational inference-policy frame for scoped iota callbacks @@ -9,7 +9,7 @@ restoration. These are the scoped callback primitives shared by struct eta and K-like constructor synthesis. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM.PreservesInferOnly @@ -186,4 +186,4 @@ theorem getMajorInductiveId_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfIotaSynthesisPolicy.lean b/Ix/Kernel/Verify/Check/WhnfIotaSynthesisPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfIotaSynthesisPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfIotaSynthesisPolicy.lean index 120274ae3..6a5d68ef9 100644 --- a/Ix/Tc/Verify/Check/WhnfIotaSynthesisPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfIotaSynthesisPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfIotaRecursionPolicy +import Ix.Kernel.Verify.Check.WhnfIotaRecursionPolicy /-! # Operational inference-policy frame for struct eta and K synthesis @@ -10,7 +10,7 @@ inference and WHNF probes, universe instantiation, projection rebuilding, DefEq validation, and synthesis statistics on acceptance and rejection. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -351,4 +351,4 @@ theorem synthCtorWhenK_preservesInferOnly exact TcM.PreservesInferOnly.pure KSynthOutcome.inconclusive end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfNatArgumentPolicy.lean b/Ix/Kernel/Verify/Check/WhnfNatArgumentPolicy.lean similarity index 98% rename from Ix/Tc/Verify/Check/WhnfNatArgumentPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfNatArgumentPolicy.lean index 6727156cd..3e24dd2d1 100644 --- a/Ix/Tc/Verify/Check/WhnfNatArgumentPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfNatArgumentPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfProjectionPolicy +import Ix.Kernel.Verify.Check.WhnfProjectionPolicy /-! # Operational policy for Nat argument normalization and stuck offsets @@ -9,7 +9,7 @@ successful callbacks, caught exhaustion, and propagated errors. It then closes the complete `tryNatOffsetStuck` classifier and rebuild path. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -166,4 +166,4 @@ theorem tryNatOffsetStuck_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfNatPolicy.lean b/Ix/Kernel/Verify/Check/WhnfNatPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfNatPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfNatPolicy.lean index 98ec1977c..1f2de24c9 100644 --- a/Ix/Tc/Verify/Check/WhnfNatPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfNatPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfNativePolicy +import Ix.Kernel.Verify.Check.WhnfNativePolicy /-! # Operational inference-policy frame for native Nat reduction @@ -9,7 +9,7 @@ memo, callback and partial-error paths, local Nat-argument fuel, interning, and application rebuilding. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -456,4 +456,4 @@ theorem tryReduceNatWithSuccMode_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfNativePolicy.lean b/Ix/Kernel/Verify/Check/WhnfNativePolicy.lean similarity index 98% rename from Ix/Tc/Verify/Check/WhnfNativePolicy.lean rename to Ix/Kernel/Verify/Check/WhnfNativePolicy.lean index 8a15b3e73..f98686d59 100644 --- a/Ix/Tc/Verify/Check/WhnfNativePolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfNativePolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfNatArgumentPolicy +import Ix.Kernel.Verify.Check.WhnfNatArgumentPolicy /-! # Operational inference-policy frame for native WHNF reduction @@ -9,7 +9,7 @@ then owns lazy declaration lookup, universe instantiation, the recursive WHNF callback, and restoration of the re-entrancy guard on both outcomes. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -125,4 +125,4 @@ theorem tryReduceNative_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfProjectionPolicy.lean b/Ix/Kernel/Verify/Check/WhnfProjectionPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfProjectionPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfProjectionPolicy.lean index 21b1fb210..2a9d880af 100644 --- a/Ix/Tc/Verify/Check/WhnfProjectionPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfProjectionPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfBasicHelperPolicy +import Ix.Kernel.Verify.Check.WhnfBasicHelperPolicy /-! # Operational policy for WHNF projection reduction @@ -10,7 +10,7 @@ intern operation, lazy constructor lookup, recursive WHNF callback, miss, and partial error is covered. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -269,4 +269,4 @@ theorem tryProjReduce_preservesInferOnly end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Check/WhnfReductionPolicy.lean b/Ix/Kernel/Verify/Check/WhnfReductionPolicy.lean similarity index 99% rename from Ix/Tc/Verify/Check/WhnfReductionPolicy.lean rename to Ix/Kernel/Verify/Check/WhnfReductionPolicy.lean index 5e5696d7d..cfa4705f0 100644 --- a/Ix/Tc/Verify/Check/WhnfReductionPolicy.lean +++ b/Ix/Kernel/Verify/Check/WhnfReductionPolicy.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.WhnfDriverPolicy +import Ix.Kernel.Verify.Check.WhnfDriverPolicy /-! # Operational inference-policy frame for WHNF reduction steps @@ -13,7 +13,7 @@ helper fields are discharged, `reductionPolicy` supplies the complete step contract consumed by `WhnfDriverPolicy`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -593,4 +593,4 @@ def WhnfHelperPolicyAt.reductionPolicy end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean new file mode 100644 index 000000000..c00dfe950 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency.lean @@ -0,0 +1,19 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Level +import Ix.Kernel.Verify.Consistency.Expr +import Ix.Kernel.Verify.Consistency.Judgment +import Ix.Kernel.Verify.Consistency.Infer +import Ix.Kernel.Verify.Consistency.Audit + +/-! +# Refinement into the set-theoretic consistency model + +This library connects production kernel operations to `Ix.Theory`. Each +transport keeps its representation, arithmetic, and dependency assumptions +explicit. The component theorems are distinct from a full soundness theorem +for `checkEnvAnon`. +-/ diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean new file mode 100644 index 000000000..9fc86756d --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -0,0 +1,51 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Infer +import Ix.Kernel.Verify.Audit.Basic + +/-! Exact full-dependency boundaries for the direct model-refinement roots. +No root permits proof holes, implementation bridge axioms, or pending +metatheory axioms. Native assumptions are enumerated only where a production +smart constructor or dispatcher still contains a generated native proof. -/ + +namespace Ix.Kernel.Consistency.Audit + +open Kernel.Verify.Audit + +private def standard : Array Lean.Name := #[``propext, ``Classical.choice, ``Quot.sound] +private def levelNative : Lean.Name := + nativeAxiom `Ix.Kernel.Level `Ix.Kernel.KUniv.mkSucc._native.native_decide.ax_1 +private def expressionNative : Lean.Name := + nativeAxiom `Ix.Kernel.Expr `Ix.Kernel.KExpr.mkVar._native.native_decide.ax_1 + +def roots : Array RootAllowance := #[ + { root := ``readLevel_eq, standardAxioms := #[``propext] }, + { root := ``readLevel_eval, standardAxioms := #[``propext] }, + { root := ``readLevel_wf, standardAxioms := #[``propext] }, + { root := ``readLevel_eraseMeta, standardAxioms := #[``propext] }, + { root := ``readLevel_mkSucc, standardAxioms := #[``propext, ``Classical.choice], + nativeAxioms := #[levelNative] }, + { root := ``univEq_sound, standardAxioms := standard }, + { root := ``univGeq_sound, standardAxioms := standard }, + { root := ``readExpr?_mkSort, standardAxioms := standard, + nativeAxioms := #[expressionNative] }, + { root := ``readExpr?_eraseMeta, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``beq_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``internExpr_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``ModelTyping.sort, standardAxioms := standard, + nativeAxioms := #[expressionNative, levelNative] }, + { root := ``ModelTyping.of_beq, standardAxioms := standard }, + { root := ``ModelTyping.internExpr, standardAxioms := standard }, + { root := ``ModelTyping.internType, standardAxioms := standard }, + { root := ``ModelTyping.no_false, standardAxioms := standard }, + { root := ``sort_conversion, standardAxioms := standard }, + { root := ``inferUncached_sort_sound, standardAxioms := standard, + nativeAxioms := #[expressionNative, levelNative] } +] + +run_cmd Kernel.Verify.Audit.check roots + +end Ix.Kernel.Consistency.Audit diff --git a/Ix/Kernel/Verify/Consistency/Expr.lean b/Ix/Kernel/Verify/Consistency/Expr.lean new file mode 100644 index 000000000..2166660f7 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Expr.lean @@ -0,0 +1,88 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Level +import Ix.Kernel.Verify.Expr +import Ix.Theory.Expr + +/-! +# Reading kernel expressions into the consistency model + +References are resolved to explicit block/member/constructor coordinates. +The reader uses the expression tree, not cached hashes or scope annotations. +It preserves projections and natural literals, and expands a let by +capture-avoiding substitution. Free variables, unresolved references, and +string literals have no reading in this initial fragment. + +The theorems below connect the production hash-equality fast path and intern +table to this reading. Their finite-support collision hypotheses are retained; +no global hash-injectivity assumption is introduced. +-/ + +namespace Ix.Kernel.Consistency + +universe u +variable {β : Type u} {m : Mode} + +/-- A structural reading into the new theory. The reference resolver will be +supplied by the declaration/store refinement; an unknown address fails. -/ +def readExpr? (resolve : Address → Option (Theory.ConstRef β)) : + KExpr m → Option (Theory.VExpr β) + | .var index _ _ => some (.bvar index.toNat) + | .fvar .. => none + | .sort level _ => some (.sort (readLevel level)) + | .const id levels _ => do + let ref ← resolve id.addr + return .const ref (levels.toList.map readLevel) + | .app fn arg _ => do + return .app (← readExpr? resolve fn) (← readExpr? resolve arg) + | .lam _ _ domain body _ => do + return .lam (← readExpr? resolve domain) (← readExpr? resolve body) + | .all _ _ domain body _ => do + return .forallE (← readExpr? resolve domain) (← readExpr? resolve body) + | .letE _ domain value body _ _ => do + let _ ← readExpr? resolve domain + let value ← readExpr? resolve value + let body ← readExpr? resolve body + return body.inst value + | .prj id index value _ => do + let ref ← resolve id.addr + return .proj ref index.toNat (← readExpr? resolve value) + | .nat value _ _ => some (.natLit value) + | .str .. => none + +/-- Hashing and display metadata do not change a smart-constructed sort. -/ +@[simp] theorem readExpr?_mkSort + (resolve : Address → Option (Theory.ConstRef β)) (u : KUniv m) : + readExpr? resolve (KExpr.mkSort u) = some (.sort (readLevel u)) := rfl + +/-- Kernel metadata erasure preserves the exact model syntax. -/ +@[simp] theorem readExpr?_eraseMeta + (resolve : Address → Option (Theory.ConstRef β)) (e : KExpr m) : + readExpr? resolve e.eraseMeta = readExpr? resolve e := by + induction e <;> + simp_all [readExpr?, KExpr.eraseMeta, KId.eraseMeta, + Array.toList_map, List.map_map, Function.comp_def] + +/-- The production `BEq` fast path preserves the model reading when the +specific compared expressions have faithful addresses. -/ +theorem beq_readExpr? {resolve : Address → Option (Theory.ConstRef β)} + {left right : KExpr m} (faithful : left.AddrFaithful right) + (equal : (left == right) = true) : + readExpr? resolve left = readExpr? resolve right := by + have erased := faithful (KExpr.beq_def left right ▸ equal) + simpa only [readExpr?_eraseMeta] using + congrArg (readExpr? resolve) erased + +/-- The production intern table preserves the model reading of a candidate. +Collision-freedom is required only on the table support plus that candidate. -/ +theorem internExpr_readExpr? {resolve : Address → Option (Theory.ConstRef β)} + {table : InternTable m} {e : KExpr m} (coherent : table.WF) + (faithful : KExpr.KeyCollisionFree fun v => table.ExprSupport v ∨ v = e) : + readExpr? resolve (table.internExpr e).1 = readExpr? resolve e := by + simpa only [readExpr?_eraseMeta] using + congrArg (readExpr? resolve) (table.internExpr_eraseMeta coherent faithful) + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Infer.lean b/Ix/Kernel/Verify/Consistency/Infer.lean new file mode 100644 index 000000000..7c336a005 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Infer.lean @@ -0,0 +1,47 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Infer +import Ix.Kernel.Verify.Consistency.Judgment + +/-! +# Production sort inference in the set-theory model + +This theorem examines the actual uncached inference dispatcher and its intern +table update. The intern-table premises are its concrete key coherence and +collision freedom on the table support plus the newly constructed type. +No named-calculus typing or checker-soundness assumption is used. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v +variable {β : Type u} {m : Mode} + +/-- Every successful execution of the production sort-inference branch +establishes the model typing postcondition for its actual returned type. -/ +theorem inferUncached_sort_sound + {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {context : Model.Context β} + {inferRec : KExpr m → RecM m (KExpr m)} {inferOnly : Bool} + {methods : Methods m} {before after : TcState m} + {level : KUniv m} {info : ExprInfo m} {type : KExpr m} + (coherent : before.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun e => + before.env.intern.ExprSupport e ∨ e = KExpr.mkSort (KUniv.mkSucc level)) + (accepted : RecM.inferUncached inferRec inferOnly (.sort level info) methods before = + .ok type after) : + ModelTyping.{u,v} resolve entries context (.sort level info) type := by + change EStateM.Result.ok + (before.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).1 + { before with env := { before.env with intern := + (before.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).2 } } = + .ok type after at accepted + cases accepted + exact ModelTyping.internType coherent faithful (ModelTyping.sort level info) + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Judgment.lean b/Ix/Kernel/Verify/Consistency/Judgment.lean new file mode 100644 index 000000000..39def4633 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Judgment.lean @@ -0,0 +1,118 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Expr +import Ix.Theory.Certified.Accept + +/-! +# Semantic postcondition for kernel typing + +`ModelTyping` states the postcondition that the production inference and +conversion proofs must establish in the new model. It ties both annotated +endpoints to the actual `KExpr` trees. It is not defined by checker success, +and this module does not assume that checker success establishes it. + +The current producers transport existing evidence through hash equality and +interning. The consistency theorem constructs a dependency model from an +admitted environment and rules out this postcondition at the primitive False. +The remaining checker refinement must produce the postcondition for each +successful inference/declaration path. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model Theory.Model.SetTheory + +universe u v +variable {β : Type u} {m : Mode} + +/-- An annotated typing judgment whose two erasures read the exact kernel +term and type. This is a semantic specification, not a runtime acceptance bit. -/ +def ModelTyping (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) (context : Model.Context β) + (term type : KExpr m) : Prop := + ∃ e A : AExpr β, + readExpr? resolve term = some e.erase ∧ + readExpr? resolve type = some A.erase ∧ + TypingClaim.{u,v} entries context e A + +namespace ModelTyping + +/-- The sort rule applies to the exact source and production successor type. -/ +theorem sort {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {context : Model.Context β} + (level : KUniv m) (info : ExprInfo m) : + ModelTyping.{u,v} resolve entries context (.sort level info) + (KExpr.mkSort (KUniv.mkSucc level)) := by + refine ⟨.sort (readLevel level), .sort (.succ (readLevel level)), rfl, ?_, + TypingClaim.sort _⟩ + simp only [readExpr?_mkSort, readLevel_mkSucc, AExpr.erase] + +/-- Reusing a hash-equal term preserves the semantic typing postcondition +under the comparison's existing address-faithfulness hypothesis. -/ +theorem of_beq {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {context : Model.Context β} + {left right type : KExpr m} (faithful : left.AddrFaithful right) + (equal : (left == right) = true) + (typed : ModelTyping.{u,v} resolve entries context right type) : + ModelTyping.{u,v} resolve entries context left type := by + obtain ⟨e, A, he, hA, typing⟩ := typed + exact ⟨e, A, (beq_readExpr? faithful equal).trans he, hA, typing⟩ + +/-- Interning a typed candidate preserves its semantic typing postcondition. -/ +theorem internExpr {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {context : Model.Context β} + {table : InternTable m} {term type : KExpr m} + (coherent : table.WF) + (faithful : KExpr.KeyCollisionFree fun e => table.ExprSupport e ∨ e = term) + (typed : ModelTyping.{u,v} resolve entries context term type) : + ModelTyping.{u,v} resolve entries context (table.internExpr term).1 type := by + obtain ⟨e, A, he, hA, typing⟩ := typed + exact ⟨e, A, (internExpr_readExpr? coherent faithful).trans he, hA, typing⟩ + +/-- Interning the inferred type also preserves the semantic judgment. -/ +theorem internType {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {context : Model.Context β} + {table : InternTable m} {term type : KExpr m} + (coherent : table.WF) + (faithful : KExpr.KeyCollisionFree fun e => table.ExprSupport e ∨ e = type) + (typed : ModelTyping.{u,v} resolve entries context term type) : + ModelTyping.{u,v} resolve entries context term (table.internExpr type).1 := by + obtain ⟨e, A, he, hA, typing⟩ := typed + exact ⟨e, A, he, (internExpr_readExpr? coherent faithful).trans hA, typing⟩ + +/-- A closed kernel typing judgment at primitive False contradicts the +set-theoretic model. Dependency realizations are constructed by admission. -/ +theorem no_false [DecidableEq β] + {resolve : Address → Option (ConstRef β)} + {signature : Certified.PrimitiveSignature β} {store : Theory.Store β} + (admitted : Certified.AdmittedEnvironment.{u,v} signature store) + {term type : KExpr m} + (isFalse : readExpr? resolve type = some signature.falseExpr) + (typed : ModelTyping.{u,v} resolve admitted.entries [] term type) + (V : Type v) [SetTheory V] : False := by + obtain ⟨e, A, _he, hA, typing⟩ := typed + have erased : A.erase = signature.falseExpr := Option.some.inj (hA.symm.trans isFalse) + have falseExpr : A = .const signature.falseType [] := AExpr.eq_const_of_erase_eq erased + obtain ⟨constants, compatible⟩ := admitted.model V + have member := (typing V constants compatible.realizes [] (fun _ => empty) + (Model.Context.valid_nil constants [] (fun _ => empty))).2.2 + rw [falseExpr] at member + simp only [interp, List.map_nil, compatible.falseValue] at member + exact not_mem_empty _ member + +end ModelTyping + +/-- A successful production universe equality supplies semantic conversion +between the corresponding annotated sorts in every compatible model. -/ +theorem sort_conversion {entries : Model.Environment β} {context : Model.Context β} + {left right : KUniv m} (faithful : left.AddrFaithful right) + (boundLeft : left.size < UInt64.size) (boundRight : right.size < UInt64.size) + (accepted : Kernel.univEq left right = true) : + ConversionClaim.{u,v} entries context (.sort (readLevel left)) (.sort (readLevel right)) := + ConversionClaim.sort (Theory.VLevel.equiv_def.mp + (univEq_sound faithful boundLeft boundRight accepted)) + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Level.lean b/Ix/Kernel/Verify/Consistency/Level.lean new file mode 100644 index 000000000..59441f43d --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Level.lean @@ -0,0 +1,74 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Level +import Ix.Theory.VLevel + +open Ix.Theory (VLevel) + +/-! +# Kernel universe decisions in the consistency model + +The normalization proof and the set-theoretic model share `Theory.VLevel`. +This module states the production decisions directly in that model. The +comparison hypotheses are faithfulness of the compared addresses and bounds +excluding UInt64 overflow. +-/ + +namespace Ix.Kernel.Consistency + +variable {m : Mode} + +/-- Read a kernel universe structurally, without consulting its cached hash. -/ +def readLevel : KUniv m → Theory.VLevel + | .zero _ => .zero + | .succ u _ => .succ (readLevel u) + | .max a b _ => .max (readLevel a) (readLevel b) + | .imax a b _ => .imax (readLevel a) (readLevel b) + | .param index _ _ => .param index.toNat + +/-- Display metadata cannot change a universe's model reading. -/ +@[simp] theorem readLevel_eraseMeta (u : KUniv m) : + readLevel u.eraseMeta = readLevel u := by + induction u <;> simp_all [KUniv.eraseMeta, readLevel] + +/-- The structural reader and the normalization proof use the same syntax. -/ +theorem readLevel_eq (u : KUniv m) : readLevel u = u.toVLevel := by + induction u <;> simp_all [readLevel, KUniv.toVLevel] + +/-- The production successor constructor preserves the semantic successor. -/ +@[simp] theorem readLevel_mkSucc (u : KUniv m) : + readLevel (KUniv.mkSucc u) = .succ (readLevel u) := by + rw [readLevel_eq, KUniv.toVLevel_mkSucc, ← readLevel_eq] + +/-- The structural reader preserves universe evaluation. -/ +theorem readLevel_eval (levels : List Nat) (u : KUniv m) : + (readLevel u).eval levels = u.toVLevel.eval levels := by + rw [readLevel_eq] + +/-- Reading preserves the existing checker's universe-parameter scope. -/ +theorem readLevel_wf (n : Nat) (u : KUniv m) : + (readLevel u).WF n ↔ u.toVLevel.WF n := by + rw [readLevel_eq] + +/-- Successful production universe equality is equality in the new model. -/ +theorem univEq_sound {u v : KUniv m} (faithful : u.AddrFaithful v) + (boundU : u.size < UInt64.size) (boundV : v.size < UInt64.size) + (accepted : Kernel.univEq u v = true) : readLevel u ≈ readLevel v := by + apply Theory.VLevel.equiv_def.mpr + intro levels + rw [readLevel_eval, readLevel_eval] + exact Ix.Theory.VLevel.equiv_def.mp + (Kernel.univEq_sound faithful boundU boundV accepted) levels + +/-- Successful production universe comparison is inclusion in the new model. -/ +theorem univGeq_sound {u v : KUniv m} (faithful : u.AddrFaithful v) + (boundU : u.size < UInt64.size) (boundV : v.size < UInt64.size) + (accepted : Kernel.univGeq u v = true) : readLevel v ≤ readLevel u := by + intro levels + rw [readLevel_eval, readLevel_eval] + exact Kernel.univGeq_sound faithful boundU boundV accepted levels + +end Ix.Kernel.Consistency diff --git a/Ix/Tc/Verify/Ctx.lean b/Ix/Kernel/Verify/Ctx.lean similarity index 96% rename from Ix/Tc/Verify/Ctx.lean rename to Ix/Kernel/Verify/Ctx.lean index 4e044b8ca..6cc948568 100644 --- a/Ix/Tc/Verify/Ctx.lean +++ b/Ix/Kernel/Verify/Ctx.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.State -import Ix.Tc.Lctx +import Ix.Kernel.Verify.State +import Ix.Kernel.Lctx /-! # Dual-context reconciliation: `CtxRecon` @@ -45,9 +45,9 @@ production equations live in `Verify/Totalization`. Preservation lemmas for `CtxRecon` over more than one pop remain part of the checker-soundness layer. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VEnv VLocalDecl) +open Ix.Theory.Named (VExpr VEnv VLocalDecl) /-! ### List helpers (local, no stdlib-name gambling) -/ @@ -441,7 +441,7 @@ theorem bvar_frame {bs : List (KExpr .anon × Option (KExpr .anon))} simp only [List.getElem?_cons_zero] at hb cases hb refine ⟨Δ, .vlam ty', 0, ?_, ?_, ?_, .vlam h1 h2⟩ - · simpa [Lean4Lean.VLocalDecl.depth] using + · simpa [Ix.Theory.Named.VLocalDecl.depth] using KVLCtx.KBVLift.skip (.vlam ty') .refl · simp [KVLCtx.find?, KVLCtx.next] · simp only [KVLCtx.fvars_cons_none] @@ -450,10 +450,10 @@ theorem bvar_frame {bs : List (KExpr .anon × Option (KExpr .anon))} simp only [List.getElem?_cons_succ] at hb obtain ⟨Δ₀, vd, m, W, hf, hsub, htr⟩ := ih nd hb refine ⟨Δ₀, vd, m + 1, ?_, ?_, ?_, htr⟩ - · simpa [Lean4Lean.VLocalDecl.depth, Nat.add_assoc] using + · simpa [Ix.Theory.Named.VLocalDecl.depth, Nat.add_assoc] using KVLCtx.KBVLift.skip (.vlam ty') W · simp only [KVLCtx.find?, KVLCtx.next, Option.bind_eq_bind, hf] - simp [Lean4Lean.VLocalDecl.depth, Lean4Lean.VExpr.liftN_liftN] + simp [Ix.Theory.Named.VLocalDecl.depth, Ix.Theory.Named.VExpr.liftN_liftN] · simp only [KVLCtx.fvars_cons_none] exact hsub | @bvar_let bs fs Δ ty₀ val₀ ty' val' H1 h1 h2 h3 ih => @@ -463,7 +463,7 @@ theorem bvar_frame {bs : List (KExpr .anon × Option (KExpr .anon))} simp only [List.getElem?_cons_zero] at hb cases hb refine ⟨Δ, .vlet ty' val', 0, ?_, ?_, ?_, .vlet h1 h2 h3⟩ - · simpa [Lean4Lean.VLocalDecl.depth] using + · simpa [Ix.Theory.Named.VLocalDecl.depth] using KVLCtx.KBVLift.skip (.vlet ty' val') .refl · simp [KVLCtx.find?, KVLCtx.next] · simp only [KVLCtx.fvars_cons_none] @@ -472,10 +472,10 @@ theorem bvar_frame {bs : List (KExpr .anon × Option (KExpr .anon))} simp only [List.getElem?_cons_succ] at hb obtain ⟨Δ₀, vd, m, W, hf, hsub, htr⟩ := ih nd hb refine ⟨Δ₀, vd, m, ?_, ?_, ?_, htr⟩ - · simpa [Lean4Lean.VLocalDecl.depth] using + · simpa [Ix.Theory.Named.VLocalDecl.depth] using KVLCtx.KBVLift.skip (.vlet ty' val') W · simp only [KVLCtx.find?, KVLCtx.next, Option.bind_eq_bind, hf] - simp [Lean4Lean.VLocalDecl.depth] + simp [Ix.Theory.Named.VLocalDecl.depth] · simp only [KVLCtx.fvars_cons_none] exact hsub | @fvar bs fs Δ fv deps d vd' H1 h1 h2 ih => @@ -489,7 +489,7 @@ theorem bvar_frame {bs : List (KExpr .anon × Option (KExpr .anon))} · simpa [Nat.add_assoc] using KVLCtx.KBVLift.skip_fvar (fv, deps) vd' hfresh W · simp only [KVLCtx.find?, KVLCtx.next, Option.bind_eq_bind, hf] - simp [Lean4Lean.VExpr.liftN_liftN] + simp [Ix.Theory.Named.VExpr.liftN_liftN] · simp only [KVLCtx.fvars_cons_some] exact fun x hx => List.mem_cons_of_mem _ (hsub hx) @@ -517,20 +517,20 @@ theorem fvar_frame {bs : List (KExpr .anon × Option (KExpr .anon))} intro nd j fv d hb obtain ⟨Δ₀, vd, dn, m, W, hf, hsub, htr⟩ := ih nd hb refine ⟨Δ₀, vd, dn + 1, m + 1, ?_, ?_, ?_, htr⟩ - · simpa [Lean4Lean.VLocalDecl.depth, Nat.add_assoc] using + · simpa [Ix.Theory.Named.VLocalDecl.depth, Nat.add_assoc] using KVLCtx.KBVLift.skip (.vlam ty') W · simp only [KVLCtx.find?, KVLCtx.next, Option.bind_eq_bind, hf] - simp [Lean4Lean.VLocalDecl.depth, Lean4Lean.VExpr.liftN_liftN] + simp [Ix.Theory.Named.VLocalDecl.depth, Ix.Theory.Named.VExpr.liftN_liftN] · simp only [KVLCtx.fvars_cons_none] exact hsub | @bvar_let bs fs Δ ty₀ val₀ ty' val' H1 h1 h2 h3 ih => intro nd j fv d hb obtain ⟨Δ₀, vd, dn, m, W, hf, hsub, htr⟩ := ih nd hb refine ⟨Δ₀, vd, dn + 1, m, ?_, ?_, ?_, htr⟩ - · simpa [Lean4Lean.VLocalDecl.depth] using + · simpa [Ix.Theory.Named.VLocalDecl.depth] using KVLCtx.KBVLift.skip (.vlet ty' val') W · simp only [KVLCtx.find?, KVLCtx.next, Option.bind_eq_bind, hf] - simp [Lean4Lean.VLocalDecl.depth] + simp [Ix.Theory.Named.VLocalDecl.depth] · simp only [KVLCtx.fvars_cons_none] exact hsub | @fvar bs fs Δ fv₀ deps₀ d₀ vd₀ H1 h1 h2 ih => @@ -561,7 +561,7 @@ theorem fvar_frame {bs : List (KExpr .anon × Option (KExpr .anon))} · simpa [Nat.add_assoc] using KVLCtx.KBVLift.skip_fvar (fv₀, deps₀) vd₀ hfresh W · simp [KVLCtx.find?, KVLCtx.next, hne, hf, - Lean4Lean.VExpr.liftN_liftN] + Ix.Theory.Named.VExpr.liftN_liftN] · simp only [KVLCtx.fvars_cons_some] exact fun x hx => List.mem_cons_of_mem _ (hsub hx) @@ -675,7 +675,7 @@ private theorem frame_of_read (hidx : idx.toNat < s.ctx.size) (hty : s.ctx[s.ctx.size - 1 - idx.toNat]? = some ty) (hov : s.letVals[s.ctx.size - 1 - idx.toNat]? = some ov) : - ∃ (Δ₀ : KVLCtx) (vd : Lean4Lean.VLocalDecl) (m : Nat), + ∃ (Δ₀ : KVLCtx) (vd : Ix.Theory.Named.VLocalDecl) (m : Nat), KVLCtx.KBVLift Δ₀ Δ (idx.toNat + 1) 0 (vd.depth + m) 0 ∧ KVLCtx.find? Δ (.inl idx.toNat) = some (vd.value.liftN m 0, vd.type.liftN m 0) ∧ @@ -719,13 +719,13 @@ theorem lookupVar {idx : UInt64} {ty : KExpr .anon} refine ⟨_, _, hf, ?_⟩ have hw := h1.weakBV henv htp.weakN W hshift (show (0 : UInt64).toNat = 0 from rfl) hbig - simpa [Lean4Lean.VLocalDecl.type, Lean4Lean.VLocalDecl.depth, - Lean4Lean.VExpr.lift, Lean4Lean.VExpr.liftN_liftN] using hw + simpa [Ix.Theory.Named.VLocalDecl.type, Ix.Theory.Named.VLocalDecl.depth, + Ix.Theory.Named.VExpr.lift, Ix.Theory.Named.VExpr.liftN_liftN] using hw | vlet h1 h2 h3 => refine ⟨_, _, hf, ?_⟩ have hw := h1.weakBV henv htp.weakN W hshift (show (0 : UInt64).toNat = 0 from rfl) hbig - simpa [Lean4Lean.VLocalDecl.type, Lean4Lean.VLocalDecl.depth] + simpa [Ix.Theory.Named.VLocalDecl.type, Ix.Theory.Named.VLocalDecl.depth] using hw /-- `lookupLetVal`'s soundness core: at a let frame, the lifted stored @@ -752,7 +752,7 @@ theorem lookupLetVal {idx : UInt64} {ty val : KExpr .anon} refine ⟨_, _, hf, ?_⟩ have hw := h2.weakBV henv htp.weakN W hshift (show (0 : UInt64).toNat = 0 from rfl) hbig - simpa [Lean4Lean.VLocalDecl.value, Lean4Lean.VLocalDecl.depth] + simpa [Ix.Theory.Named.VLocalDecl.value, Ix.Theory.Named.VLocalDecl.depth] using hw /-- Walker-tight sibling of `lookupLetVal`. The older theorem asks for the @@ -781,7 +781,7 @@ theorem lookupLetVal_liftBounds {idx : UInt64} {ty val : KExpr .anon} refine ⟨_, _, hf, ?_⟩ have hw := h2.weakBV_lbr henv htp.weakN hcon W hshift (show (0 : UInt64).toNat = 0 from rfl) hcut hlift - simpa [Lean4Lean.VLocalDecl.value, Lean4Lean.VLocalDecl.depth] + simpa [Ix.Theory.Named.VLocalDecl.value, Ix.Theory.Named.VLocalDecl.depth] using hw /-- The fvar-side lookup bridge at the concrete state: a successful @@ -791,7 +791,7 @@ theorem lookupLetVal_liftBounds {idx : UInt64} {ty val : KExpr .anon} theorem lctxFind? {fv : FVarId} {d : LocalDecl .anon} (h : CtxRecon env uvars nameOf trProj s Δ) (hf : s.lctx.find? fv = some d) : - ∃ (Δ₀ : KVLCtx) (vd : Lean4Lean.VLocalDecl) (dn m : Nat), + ∃ (Δ₀ : KVLCtx) (vd : Ix.Theory.Named.VLocalDecl) (dn m : Nat), KVLCtx.KBVLift Δ₀ Δ dn 0 (vd.depth + m) 0 ∧ KVLCtx.find? Δ (.inr fv) = some (vd.value.liftN m 0, vd.type.liftN m 0) ∧ @@ -846,8 +846,8 @@ theorem lctxFindType {fv : FVarId} {d : LocalDecl .anon} (by simpa using (show ty.size < UInt64.size by omega)) simp [hclosed'] rw [hid] at hw - simpa [LocalDecl.ty, Lean4Lean.VLocalDecl.type, - Lean4Lean.VLocalDecl.depth, Lean4Lean.VExpr.liftN_liftN, + simpa [LocalDecl.ty, Ix.Theory.Named.VLocalDecl.type, + Ix.Theory.Named.VLocalDecl.depth, Ix.Theory.Named.VExpr.liftN_liftN, Nat.add_comm] using hw | @vlet nm ty val ty' val' hty hval hvalType => have hcon' : KExpr.Constructed ty := by @@ -863,8 +863,8 @@ theorem lctxFindType {fv : FVarId} {d : LocalDecl .anon} (by simpa using (show ty.size < UInt64.size by omega)) simp [hclosed'] rw [hid] at hw - simpa [LocalDecl.ty, Lean4Lean.VLocalDecl.type, - Lean4Lean.VLocalDecl.depth] using hw + simpa [LocalDecl.ty, Ix.Theory.Named.VLocalDecl.type, + Ix.Theory.Named.VLocalDecl.depth] using hw /-- A let-valued fvar lookup yields a translation of the concrete stored value at the current mixed context, provided that value is closed with @@ -898,7 +898,7 @@ theorem lctxFindLetVal {fv : FVarId} {nm : Mode.anon.F Name} (by simpa using (show val.size < UInt64.size by omega)) simp [hclosed] rw [hid] at hw - simpa [Lean4Lean.VLocalDecl.value, Lean4Lean.VLocalDecl.depth] using hw + simpa [Ix.Theory.Named.VLocalDecl.value, Ix.Theory.Named.VLocalDecl.depth] using hw /-- Fvar leaves resolve — the bare `TrKExprS.fvar` premise. -/ theorem fvar_resolves {fv : FVarId} {d : LocalDecl .anon} @@ -1154,4 +1154,4 @@ theorem closeFVar {fv : FVarId} {deps : List FVarId} {vd : VLocalDecl} end CtxRecon -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Decl.lean b/Ix/Kernel/Verify/Decl.lean similarity index 95% rename from Ix/Tc/Verify/Decl.lean rename to Ix/Kernel/Verify/Decl.lean index 1f0cbb9b1..0d46a008d 100644 --- a/Ix/Tc/Verify/Decl.lean +++ b/Ix/Kernel/Verify/Decl.lean @@ -1,7 +1,9 @@ -import Ix.Tc.Verify.World -import Ix.Tc.Verify.Level -import Lean4Lean.Verify.Typing.Expr -import Lean4Lean.Theory.Typing.Lemmas +import Ix.Kernel.Verify.World +import Ix.Kernel.Verify.Level +import Ix.Theory.Named.Verify.Typing.Expr +import Ix.Theory.Named.Typing.Lemmas + +open Ix.Theory (VLevel) /-! # Raw, pending, and trusted declarations @@ -30,14 +32,14 @@ catalogued, pending, and raw-translatable, but cannot be a well-formed Theory declaration in the empty trusted environment. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLevel VEnv VConstant VConstVal VDefVal VDecl) +open Ix.Theory.Named (VExpr VEnv VConstant VConstVal VDefVal VDecl) /-- The abstract projection component used by expression translation. Projection semantics are indexed by the ambient universe-parameter count. -Lean4Lean's concrete `TrProj` changes that index under universe +Ix.Theory.Named's concrete `TrProj` changes that index under universe instantiation, so erasing it here would make the `instL` law impossible to state faithfully. The raw boundary still carries no closure or typing contract; those laws live in `TrProjOK`. -/ @@ -300,7 +302,7 @@ inductive RawDefKindRel (ci : VDefVal) : Ix.DefKind → VDecl → Prop No constructor asks for `ci.WF` or `d.WF`. Quotients and inductive-family members cannot be represented soundly one constant at a time in -Lean4Lean.Theory, so they intentionally have no constructor here; their +Ix.Theory.Named.Theory, so they intentionally have no constructor here; their future relation is atomic at the block level. -/ inductive RawDeclRel (env : VEnv) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) (id : KId .anon) : KConst .anon → VDecl → Prop @@ -348,7 +350,7 @@ theorem mono {env env' : VEnv} (henv : env ≤ env') exact .defn hname (hty.mono henv) (hval.mono henv) hkind /-- A WF transition for a raw standalone declaration extends its input -environment. Lean4Lean does not provide this for arbitrary `VDecl.WF` +environment. Ix.Theory.Named does not provide this for arbitrary `VDecl.WF` (notably, its abstract `addInduct` has no extension theorem), but it follows constructively for exactly the axiom/definition/opaque cases admitted by `RawDeclRel`. -/ @@ -359,17 +361,17 @@ theorem wf_le {env env' : VEnv} {nameOf : Address → Option Lean.Name} cases hraw with | «axiom» => cases hwf with - | «axiom» _ hadd => exact Lean4Lean.VEnv.addConst_le hadd + | «axiom» _ hadd => exact Ix.Theory.Named.VEnv.addConst_le hadd | defn _ _ _ hkind => cases hkind with | defn => cases hwf with | «def» _ hadd => - exact (Lean4Lean.VEnv.addConst_le hadd).trans - Lean4Lean.VEnv.addDefEq_le + exact (Ix.Theory.Named.VEnv.addConst_le hadd).trans + Ix.Theory.Named.VEnv.addDefEq_le | opaq | thm => cases hwf with - | «opaque» _ hadd => exact Lean4Lean.VEnv.addConst_le hadd + | «opaque» _ hadd => exact Ix.Theory.Named.VEnv.addConst_le hadd /-- Target freshness rules out self-reference in every expression translated by a raw standalone declaration. -/ @@ -450,7 +452,7 @@ theorem lookup {trProj : RawProjRel} {world : VerifyWorld} cases hwf with | «axiom» hconstant hadd => exact ⟨_, _, .axiom _, hname, - hinstalled.constants (Lean4Lean.VEnv.addConst_self hadd)⟩ + hinstalled.constants (Ix.Theory.Named.VEnv.addConst_self hadd)⟩ | defn hname hty hval hkind => cases hkind with | defn => @@ -458,13 +460,13 @@ theorem lookup {trProj : RawProjRel} {world : VerifyWorld} | «def» hconstant hadd => exact ⟨_, _, .defn _, hname, hinstalled.constants - (Lean4Lean.VEnv.addDefEq_le.constants - (Lean4Lean.VEnv.addConst_self hadd))⟩ + (Ix.Theory.Named.VEnv.addDefEq_le.constants + (Ix.Theory.Named.VEnv.addConst_self hadd))⟩ | opaq | thm => cases hwf with | «opaque» hconstant hadd => exact ⟨_, _, .opaque _, hname, - hinstalled.constants (Lean4Lean.VEnv.addConst_self hadd)⟩ + hinstalled.constants (Ix.Theory.Named.VEnv.addConst_self hadd)⟩ end TrustedDecl @@ -510,7 +512,7 @@ end PendingDecl namespace IllTypedPending -def targetName : Lean.Name := `Ix.Tc.Verify.illTypedPending +def targetName : Lean.Name := `Ix.Kernel.Verify.illTypedPending /-- A fixed 32-byte address keeps the fixture independent of the Blake3 FFI and its generated `native_decide` axiom. Address coherence is a separate @@ -569,7 +571,7 @@ theorem theoryConstant_not_wf : ¬theoryConstant.toVConstant.WF world.venv := by intro hwf have hlevel : (VLevel.param 0).WF 0 := - hwf.sort_inv Lean4Lean.VEnv.Ordered.empty + hwf.sort_inv Ix.Theory.Named.VEnv.Ordered.empty exact (Nat.not_lt_zero 0) hlevel /-- Consequently there is no Theory declaration-WF step from the pending @@ -606,4 +608,4 @@ end Loaded end IllTypedPending -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq.lean b/Ix/Kernel/Verify/DefEq.lean similarity index 99% rename from Ix/Tc/Verify/DefEq.lean rename to Ix/Kernel/Verify/DefEq.lean index 03a855cb4..9bd1dfb45 100644 --- a/Ix/Tc/Verify/DefEq.lean +++ b/Ix/Kernel/Verify/DefEq.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Infer -import Ix.Tc.Verify.Whnf.Closure +import Ix.Kernel.Verify.Infer +import Ix.Kernel.Verify.Whnf.Closure import Batteries.Data.UInt /-! @@ -10,9 +10,9 @@ equality. A cached `false` (including the narrow failure set) can only reject an otherwise valid declaration, so it carries no acceptance claim here. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) private theorem uint64_max_comm (a b : UInt64) : max a b = max b a := by apply UInt64.toNat_inj.mp @@ -227,7 +227,7 @@ theorem of_addr_beq {trProj : RawProjRel} {world : VerifyWorld} subst b intro _ exact ⟨va, va, ha, ha, - Lean4Lean.VEnv.IsDefEqU.refl (theory.exprWF hctx ha)⟩ + Ix.Theory.Named.VEnv.IsDefEqU.refl (theory.exprWF hctx ha)⟩ theorem symm {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {a b : KExpr .anon} {answer : Bool} @@ -2836,4 +2836,4 @@ theorem inferWith_inferOnlyHit_acceptance end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/AcceleratorGates.lean b/Ix/Kernel/Verify/DefEq/AcceleratorGates.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/AcceleratorGates.lean rename to Ix/Kernel/Verify/DefEq/AcceleratorGates.lean index 0e59621d3..3227e9db3 100644 --- a/Ix/Tc/Verify/DefEq/AcceleratorGates.lean +++ b/Ix/Kernel/Verify/DefEq/AcceleratorGates.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.NatReduction -import Ix.Tc.Verify.Whnf.Driver.FullStep +import Ix.Kernel.Verify.DefEq.NatReduction +import Ix.Kernel.Verify.Whnf.Driver.FullStep /-! # Lazy-delta accelerator gates @@ -11,7 +11,7 @@ those four operationally unreachable hit branches from lazy delta and exposes the first substantive remaining tail: delta-head classification. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -35,7 +35,7 @@ theorem defEqLazyDeltaStepAfterNatMiss_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {state : TcState .anon} - {leftSource rightSource : Lean4Lean.VExpr} + {leftSource rightSource : Ix.Theory.Named.VExpr} {left right : KExpr .anon} (theory : WhnfTheory trProj world uvars) (hafter : DefEqLazyDeltaAfterAcceleratorMiss.WFAt .noAccel semantics @@ -158,4 +158,4 @@ end DefEqLazyDeltaAfterNatMiss end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ApplicationSpine.lean b/Ix/Kernel/Verify/DefEq/ApplicationSpine.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/ApplicationSpine.lean rename to Ix/Kernel/Verify/DefEq/ApplicationSpine.lean index 7c0704617..f062e5ab0 100644 --- a/Ix/Tc/Verify/DefEq/ApplicationSpine.lean +++ b/Ix/Kernel/Verify/DefEq/ApplicationSpine.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.SpineArguments +import Ix.Kernel.Verify.DefEq.SpineArguments /-! # General application-spine comparison @@ -9,9 +9,9 @@ argument loop. A positive result is reconstructed through the complete typed spines; constructor misses and unequal arities carry no semantic claim. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Finite support coverage for the head and arguments selected by the exact production `collectSpine` executions. -/ @@ -145,4 +145,4 @@ end TryDefEqApp end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/BoolTrue.lean b/Ix/Kernel/Verify/DefEq/BoolTrue.lean similarity index 99% rename from Ix/Tc/Verify/DefEq/BoolTrue.lean rename to Ix/Kernel/Verify/DefEq/BoolTrue.lean index 6ac0fc3ec..515983494 100644 --- a/Ix/Tc/Verify/DefEq/BoolTrue.lean +++ b/Ix/Kernel/Verify/DefEq/BoolTrue.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.Structural +import Ix.Kernel.Verify.DefEq.Structural /-! # Eager Bool.true definitional equality @@ -9,9 +9,9 @@ Acceptance is sound only when the runtime primitive address is tied to the trusted Theory name; address equality by itself is not authority. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Minimal trusted binding for the one primitive read by the eager Boolean tier. -/ @@ -316,4 +316,4 @@ theorem DefEqAfterBoolTrue.closesInner end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/CacheBranches.lean b/Ix/Kernel/Verify/DefEq/CacheBranches.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/CacheBranches.lean rename to Ix/Kernel/Verify/DefEq/CacheBranches.lean index f200f3670..13a46592d 100644 --- a/Ix/Tc/Verify/DefEq/CacheBranches.lean +++ b/Ix/Kernel/Verify/DefEq/CacheBranches.lean @@ -1,15 +1,15 @@ -import Ix.Tc.Verify.DefEq +import Ix.Kernel.Verify.DefEq /-! # DefEq cache-policy branches This module verifies cache exits whose state effects depend on cheap mode. The semantic manager and guarded root-cache foundations live in -`Ix.Tc.Verify.DefEq`; the exhaustive cache shell will assemble these branches +`Ix.Kernel.Verify.DefEq`; the exhaustive cache shell will assemble these branches before entering recursive comparison. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -100,7 +100,7 @@ theorem isDefEq_fullHitCheapMode_true_acceptance {methods : Methods .anon} {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} (model : KernelSuffixModel trProj world) - {Delta : KVLCtx} {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {Delta : KVLCtx} {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {s s1 s2 s3 s4 : TcState .anon} (theory : WhnfTheory trProj world model.keys.uvars) (hcollision : support.CollisionFree) @@ -344,7 +344,7 @@ theorem isDefEq_rootCheapHit_true_acceptance {methods : Methods .anon} {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} (model : KernelSuffixModel trProj world) - {Delta : KVLCtx} {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {Delta : KVLCtx} {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {aRoot bRoot : EqKey} {s s1 s2 s3 s4 s5 : TcState .anon} (theory : WhnfTheory trProj world model.keys.uvars) @@ -506,7 +506,7 @@ theorem guardedRootHit_copyBoth {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} (model : KernelSuffixModel trProj world) {kind : DefEqCacheKind} {Delta : KVLCtx} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {aRoot bRoot : EqKey} {s : TcState .anon} (theory : WhnfTheory trProj world model.keys.uvars) (hcollision : support.CollisionFree) @@ -724,7 +724,7 @@ theorem isDefEq_rootFullHitCheapMode_true_acceptance {methods : Methods .anon} {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} (model : KernelSuffixModel trProj world) - {Delta : KVLCtx} {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {Delta : KVLCtx} {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {aRoot bRoot : EqKey} {s s1 s2 s3 s4 s5 : TcState .anon} (theory : WhnfTheory trProj world model.keys.uvars) @@ -844,4 +844,4 @@ theorem isDefEq_rootFullHitCheapMode_true_acceptance end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/CacheShell.lean b/Ix/Kernel/Verify/DefEq/CacheShell.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/CacheShell.lean rename to Ix/Kernel/Verify/DefEq/CacheShell.lean index b6f72ddd9..29630d2fd 100644 --- a/Ix/Tc/Verify/DefEq/CacheShell.lean +++ b/Ix/Kernel/Verify/DefEq/CacheShell.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.CacheBranches +import Ix.Kernel.Verify.DefEq.CacheBranches /-! # DefEq cache shell @@ -10,7 +10,7 @@ final cache write. The bridge theorems below connect the entry-point prefix to those production-owned functions. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -252,7 +252,7 @@ private theorem guardedRootResult (theory : WhnfTheory trProj world model.keys.uvars) (hcollision : support.CollisionFree) {kind : DefEqCacheKind} {answer : Bool} {Delta : KVLCtx} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {aRoot bRoot : EqKey} {s : TcState .anon} (hI : WhnfStateInv layer (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars Delta s) @@ -307,7 +307,7 @@ private theorem applyFullRootResult_wf {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {model : KernelSuffixModel trProj world} {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} {ctxAddr : Address} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {answer cheapMode : Bool} (hcollision : support.CollisionFree) (haSupport : support a) (hbSupport : support b) @@ -369,7 +369,7 @@ private theorem applyCheapRootResult_wf {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {model : KernelSuffixModel trProj world} {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} {ctxAddr : Address} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {answer : Bool} (hcollision : support.CollisionFree) (haSupport : support a) (hbSupport : support b) @@ -442,7 +442,7 @@ private theorem applyDirectFullHit_wf {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {model : KernelSuffixModel trProj world} {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} {ctxAddr : Address} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {answer cheapMode : Bool} (hcollision : support.CollisionFree) (haSupport : support a) (hbSupport : support b) @@ -537,7 +537,7 @@ private theorem applyDirectCheapHit_wf {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {model : KernelSuffixModel trProj world} {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} {ctxAddr : Address} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {answer : Bool} (hcollision : support.CollisionFree) (haSupport : support a) (hbSupport : support b) @@ -609,7 +609,7 @@ theorem isDefEqAfterRootCacheMiss_wf (hcollision : support.CollisionFree) (hinner : DefEqInner.WF layer trProj world support model) {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} {ctxAddr : Address} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {cheapMode : Bool} (haSupport : support a) (hbSupport : support b) (ha : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta a va) @@ -770,7 +770,7 @@ theorem isDefEqAfterDirectCacheMiss_wf (hcollision : support.CollisionFree) (hinner : DefEqInner.WF layer trProj world support model) {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} {ctxAddr : Address} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} {ctxAddr : Address} {cheapMode : Bool} (haSupport : support a) (hbSupport : support b) (ha : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta a va) @@ -907,7 +907,7 @@ theorem isDefEq_wf (hcollision : support.CollisionFree) (hinner : DefEqInner.WF layer trProj world support model) {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} (haSupport : support a) (hbSupport : support b) (ha : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta a va) (hb : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta b vb) @@ -1046,4 +1046,4 @@ theorem isDefEq_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/CheapReduction.lean b/Ix/Kernel/Verify/DefEq/CheapReduction.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/CheapReduction.lean rename to Ix/Kernel/Verify/DefEq/CheapReduction.lean index 7b68bcd85..52500b8f2 100644 --- a/Ix/Tc/Verify/DefEq/CheapReduction.lean +++ b/Ix/Kernel/Verify/DefEq/CheapReduction.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.StringLiteral -import Ix.Tc.Verify.Whnf.NoDelta.Reducer +import Ix.Kernel.Verify.DefEq.StringLiteral +import Ix.Kernel.Verify.Whnf.NoDelta.Reducer /-! # Cheap DefEq reduction prefix @@ -10,9 +10,9 @@ cheap-depth scope itself and composes both passes with address collision freedom and the already verified structural comparison. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -332,4 +332,4 @@ end DefEqAfterNoDeltaPass end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/Closure.lean b/Ix/Kernel/Verify/DefEq/Closure.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/Closure.lean rename to Ix/Kernel/Verify/DefEq/Closure.lean index 752558a78..15b510c9c 100644 --- a/Ix/Tc/Verify/DefEq/Closure.lean +++ b/Ix/Kernel/Verify/DefEq/Closure.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.DefEq.CacheShell -import Ix.Tc.Verify.DefEq.FinalWhnf.Closure -import Ix.Tc.Verify.DefEq.LazyDeltaClosure +import Ix.Kernel.Verify.DefEq.CacheShell +import Ix.Kernel.Verify.DefEq.FinalWhnf.Closure +import Ix.Kernel.Verify.DefEq.LazyDeltaClosure /-! # Complete definitional-equality closure @@ -12,7 +12,7 @@ records: projection delta owns the shared Theory/collision/structural facts, while final WHNF owns the direct reducer and primitive-expansion facts. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace CacheEntry @@ -176,4 +176,4 @@ end DefEqClosureResources end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/DeltaClassification.lean b/Ix/Kernel/Verify/DefEq/DeltaClassification.lean similarity index 96% rename from Ix/Tc/Verify/DefEq/DeltaClassification.lean rename to Ix/Kernel/Verify/DefEq/DeltaClassification.lean index 7f3d9525f..db4d21057 100644 --- a/Ix/Tc/Verify/DefEq/DeltaClassification.lean +++ b/Ix/Kernel/Verify/DefEq/DeltaClassification.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.AcceleratorGates -import Ix.Tc.Verify.Whnf.Runtime.LazyIngress +import Ix.Kernel.Verify.DefEq.AcceleratorGates +import Ix.Kernel.Verify.Whnf.Runtime.LazyIngress /-! # Lazy-delta head classification @@ -11,7 +11,7 @@ no semantic claim is attached to a negative answer. This module also closes the exact stopped branch where neither head is classified as reducible. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -64,7 +64,7 @@ theorem defEqLazyDeltaStepAfterAcceleratorMiss_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {state : TcState .anon} - {leftSource rightSource : Lean4Lean.VExpr} + {leftSource rightSource : Ix.Theory.Named.VExpr} {left right : KExpr .anon} (hfault : TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) @@ -110,4 +110,4 @@ end DefEqLazyDeltaAfterAcceleratorMiss end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/EqualRankCache.lean b/Ix/Kernel/Verify/DefEq/EqualRankCache.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/EqualRankCache.lean rename to Ix/Kernel/Verify/DefEq/EqualRankCache.lean index 30004e11c..b4ce02801 100644 --- a/Ix/Tc/Verify/DefEq/EqualRankCache.lean +++ b/Ix/Kernel/Verify/DefEq/EqualRankCache.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.SameHeadSpine +import Ix.Kernel.Verify.DefEq.SameHeadSpine /-! # Equal-rank same-head cache @@ -9,7 +9,7 @@ proves the exact lookup/attempt/write shell and preserves provenance for the single write made after a genuine comparison miss. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Provenance available for every concrete failure marker this run may insert. -/ @@ -95,7 +95,7 @@ theorem trySameHeadSpineSpeculative_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {state : TcState .anon} - {left right : KExpr .anon} {leftV rightV : Lean4Lean.VExpr} + {left right : KExpr .anon} {leftV rightV : Ix.Theory.Named.VExpr} (hsame : TrySameHeadSpine.WFAt layer semantics trProj world support uvars) (hleftSupport : support left) (hrightSupport : support right) @@ -201,7 +201,7 @@ theorem trySameHeadSpineCached_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {state : TcState .anon} - {left right : KExpr .anon} {leftV rightV : Lean4Lean.VExpr} + {left right : KExpr .anon} {leftV rightV : Ix.Theory.Named.VExpr} (hcache : DefEqFailureCacheResources semantics world support) (hsame : TrySameHeadSpine.WFAt layer semantics trProj world support uvars) @@ -275,4 +275,4 @@ end TrySameHeadSpineCached end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/EqualRankPrefix.lean b/Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/EqualRankPrefix.lean rename to Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean index c045f9cbf..b8135d0bb 100644 --- a/Ix/Tc/Verify/DefEq/EqualRankPrefix.lean +++ b/Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.EqualRankCache +import Ix.Kernel.Verify.DefEq.EqualRankCache /-! # Equal-rank prefix assembly @@ -8,9 +8,9 @@ attempt, and the already-proved two-sided reduction continuation into the complete equal-rank lazy-delta contract. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -118,4 +118,4 @@ end DefEqLazyDeltaEqualRank end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/EqualRankReduction.lean b/Ix/Kernel/Verify/DefEq/EqualRankReduction.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/EqualRankReduction.lean rename to Ix/Kernel/Verify/DefEq/EqualRankReduction.lean index 1d95349af..207a6764b 100644 --- a/Ix/Tc/Verify/DefEq/EqualRankReduction.lean +++ b/Ix/Kernel/Verify/DefEq/EqualRankReduction.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.RankDispatch +import Ix.Kernel.Verify.DefEq.RankDispatch /-! # Equal-rank two-sided reduction @@ -9,9 +9,9 @@ four hit/miss combinations in that exact order and feeds every productive combination through the common finishing checks. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -148,4 +148,4 @@ end DefEqLazyDeltaAfterSameHeadMiss end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/Application.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/Application.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/FinalWhnf/Application.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/Application.lean index 4833994da..75f7b62e2 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/Application.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/Application.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts /-! # Final-WHNF application comparison @@ -8,9 +8,9 @@ constructor-directed final comparison. Argument equality is requested only after function equality succeeds, matching the production order. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Finite child coverage for supported applications selected by the final WHNF comparator. -/ @@ -117,4 +117,4 @@ end TryDefEqWhnfApp end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/Closure.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean similarity index 91% rename from Ix/Tc/Verify/DefEq/FinalWhnf/Closure.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean index b97a2f20a..36c1c5e6b 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/Closure.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean @@ -1,10 +1,10 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.NatBridge -import Ix.Tc.Verify.DefEq.FinalWhnf.EtaExpansion -import Ix.Tc.Verify.DefEq.FinalWhnf.StringExpansion -import Ix.Tc.Verify.DefEq.FinalWhnf.StructuralPrefix -import Ix.Tc.Verify.DefEq.FinalWhnf.StructureEta -import Ix.Tc.Verify.DefEq.FinalWhnf.UnitLike -import Ix.Tc.Verify.DefEq.PropositionClassifier +import Ix.Kernel.Verify.DefEq.FinalWhnf.NatBridge +import Ix.Kernel.Verify.DefEq.FinalWhnf.EtaExpansion +import Ix.Kernel.Verify.DefEq.FinalWhnf.StringExpansion +import Ix.Kernel.Verify.DefEq.FinalWhnf.StructuralPrefix +import Ix.Kernel.Verify.DefEq.FinalWhnf.StructureEta +import Ix.Kernel.Verify.DefEq.FinalWhnf.UnitLike +import Ix.Kernel.Verify.DefEq.PropositionClassifier /-! # Complete final-WHNF comparison @@ -15,7 +15,7 @@ irrelevance fallbacks. This module assembles those independently verified phases under one canonical K2 suffix model. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Concrete resources for every production phase of `isDefEqWhnf`. The @@ -102,4 +102,4 @@ theorem finalWhnf end FinalWhnfClosureResources end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/Contracts.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/Contracts.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/FinalWhnf/Contracts.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/Contracts.lean index f758d6b91..feae0f768 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/Contracts.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/Contracts.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.StoppedContinuation +import Ix.Kernel.Verify.DefEq.StoppedContinuation /-! # Final-WHNF comparison contracts @@ -9,7 +9,7 @@ contracts let their exhaustive proofs be developed independently and then compose them back into `isDefEqWhnf`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -19,7 +19,7 @@ def TryDefEqWhnfLet.WFAt (layer : WhnfLayer) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) : Prop := ∀ {Delta state leftName rightName ty1 val1 body1 ty2 val2 body2} {leftNondep rightNondep : Bool} - {leftInfo rightInfo : ExprInfo .anon} {leftV rightV : Lean4Lean.VExpr}, + {leftInfo rightInfo : ExprInfo .anon} {leftV rightV : Ix.Theory.Named.VExpr}, support (.letE leftName ty1 val1 body1 leftNondep leftInfo) → support (.letE rightName ty2 val2 body2 rightNondep rightInfo) → TrKExprS world.venv uvars world.nameOf trProj Delta @@ -212,7 +212,7 @@ theorem isDefEqWhnf_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {state : TcState .anon} - {left right : KExpr .anon} {leftV rightV : Lean4Lean.VExpr} + {left right : KExpr .anon} {leftV rightV : Ix.Theory.Named.VExpr} (hstructural : TryDefEqWhnfStructural.WFAt layer semantics trProj world support uvars) (htail : IsDefEqWhnfAfterStructural.WFAt layer semantics trProj world @@ -255,4 +255,4 @@ end IsDefEqWhnf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/EtaExpansion.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/EtaExpansion.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/FinalWhnf/EtaExpansion.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/EtaExpansion.lean index 314f923cc..c61d22b4c 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/EtaExpansion.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/EtaExpansion.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts -import Ix.Tc.Verify.DefEq.ProofIrrelevance +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.DefEq.ProofIrrelevance /-! # Final-WHNF lambda eta @@ -12,9 +12,9 @@ cover the exact lift footprint and generated syntax; no semantic eta callback is assumed. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Finite walker and generated-node closure for lambda eta. -/ structure FinalWhnfEtaResources (support : RunSupport) : Prop where @@ -55,7 +55,7 @@ theorem lift_whnf_wf_of_resources InternUpdateFrame state after) := TcM.runIntern_whnf_wf (fun intern hwf hsupport => by - have post := Ix.Tc.lift_spec hcollision.expr hbounds.1 hbounds.2.1 + have post := Ix.Kernel.lift_spec hcollision.expr hbounds.1 hbounds.2.1 hreach hwf hsupport.expr exact ⟨post.1, post.2.1, hsupport.of_expr_univs post.2.2 @@ -421,4 +421,4 @@ end IsDefEqWhnfAfterNat end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/LetDeclaration.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/LetDeclaration.lean similarity index 99% rename from Ix/Tc/Verify/DefEq/FinalWhnf/LetDeclaration.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/LetDeclaration.lean index 5445f31de..0814bea5c 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/LetDeclaration.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/LetDeclaration.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts -import Ix.Tc.Verify.Infer.LetScopes +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.Infer.LetScopes /-! # Final-WHNF let-declaration comparison @@ -11,9 +11,9 @@ opened bodies recursively. This module verifies that exact scoped program, including allocation failure and scope restoration on callback errors. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Finite constructor descent and body-opening coverage for supported lets. The right body is opened with the left let's display name, so body resources @@ -449,4 +449,4 @@ end TryDefEqWhnfLet end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/NatBridge.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/NatBridge.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/FinalWhnf/NatBridge.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/NatBridge.lean index 34562eb1b..47dc6cde8 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/NatBridge.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/NatBridge.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts -import Ix.Tc.Verify.DefEq.NatOffset +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.DefEq.NatOffset /-! # Final-WHNF Nat bridge @@ -11,9 +11,9 @@ predecessor equality can therefore be lifted through `Nat.succ` without assuming injectivity or reflection beyond the trusted primitive table. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Trusted primitive facts and finite support needed by the final Nat comparison. -/ @@ -41,9 +41,9 @@ private theorem finalNatLit_hasType obtain ⟨ci, hlookup⟩ := htable.natZero.contains hcatalog have hci := hprims.natZero hlookup subst ci - exact Lean4Lean.VEnv.HasType.const hlookup (by simp) rfl + exact Ix.Theory.Named.VEnv.HasType.const hlookup (by simp) rfl | n + 1 => - Lean4Lean.VEnv.HasType.app + Ix.Theory.Named.VEnv.HasType.app (natSucc_hasType hcatalog htable hprims) (finalNatLit_hasType hcatalog htable hprims n) @@ -135,7 +135,7 @@ theorem natSuccOf_wf have hpredTr : TrKExprS world.venv uvars world.nameOf trProj Delta (natExprFromValue predecessor : KExpr .anon) (.natLit predecessor) := by - exact .nat (by simpa [Lean4Lean.VEnv.ContainsLits] using + exact .nat (by simpa [Ix.Theory.Named.VEnv.ContainsLits] using resources.natContains) have hpredType : world.venv.HasType uvars Delta.toCtx (.natLit predecessor) .nat := @@ -240,7 +240,7 @@ theorem isDefEqNatAfterLiteral_wf have hrightValue := hrightZero rfl subst leftV subst rightV - exact Lean4Lean.VEnv.IsDefEqU.refl <| + exact Ix.Theory.Named.VEnv.IsDefEqU.refl <| hleft.wf world.venvWF.ordered theory.literalWF theory.projections.wf hI.2.1.wf | false => @@ -346,7 +346,7 @@ theorem isDefEqNat_wf exact RecM.WF.pure fun hI hanswer => by have hvalue := eq_of_beq hanswer subst_vars - exact Lean4Lean.VEnv.IsDefEqU.refl <| + exact Ix.Theory.Named.VEnv.IsDefEqU.refl <| hleftTr.wf world.venvWF.ordered theory.literalWF theory.projections.wf hI.2.1.wf @@ -452,4 +452,4 @@ end IsDefEqWhnfAfterStructural end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/ProofTail.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/ProofTail.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/FinalWhnf/ProofTail.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/ProofTail.lean index 019226425..55a884362 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/ProofTail.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/ProofTail.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts -import Ix.Tc.Verify.DefEq.ProofIrrelevance +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.DefEq.ProofIrrelevance /-! # Final-WHNF proof-irrelevance tail @@ -9,9 +9,9 @@ module packages it at the final-WHNF seam and composes it with an independently verified unit-like shortcut. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -144,4 +144,4 @@ end IsDefEqWhnfAfterString end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/StringExpansion.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/StringExpansion.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/FinalWhnf/StringExpansion.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/StringExpansion.lean index c23d6562e..82744e37e 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/StringExpansion.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/StringExpansion.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts -import Ix.Tc.Verify.DefEq.StringLiteral +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.DefEq.StringLiteral /-! # Final-WHNF String-literal expansion @@ -9,9 +9,9 @@ final-WHNF comparator. Each compact literal is expanded by the exact K1 plan, whose result translates to the same Theory literal as the source syntax. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -148,4 +148,4 @@ end IsDefEqWhnfAfterEta end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/StructuralPrefix.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructuralPrefix.lean similarity index 95% rename from Ix/Tc/Verify/DefEq/FinalWhnf/StructuralPrefix.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/StructuralPrefix.lean index 8a48063bd..0627c4c00 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/StructuralPrefix.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructuralPrefix.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Application -import Ix.Tc.Verify.DefEq.FinalWhnf.LetDeclaration +import Ix.Kernel.Verify.DefEq.FinalWhnf.Application +import Ix.Kernel.Verify.DefEq.FinalWhnf.LetDeclaration /-! # Final-WHNF structural prefix @@ -11,9 +11,9 @@ contract so its allocation and dual-body opening proof can be discharged in isolation. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -75,7 +75,7 @@ theorem tryDefEqWhnfStructural_wf (hleftLookup.symm.trans hrightLookup) have hvalue : leftV = rightV := congrArg Prod.fst hp subst rightV - exact Lean4Lean.VEnv.IsDefEqU.refl hleftWF + exact Ix.Theory.Named.VEnv.IsDefEqU.refl hleftWF · rename_i leftU leftInfo rightU rightInfo cases hleft with | sort hleftWF => @@ -153,7 +153,7 @@ theorem tryDefEqWhnfStructural_wf hI.2.1.wf cases hleft cases hright - exact Lean4Lean.VEnv.IsDefEqU.refl hleftWF + exact Ix.Theory.Named.VEnv.IsDefEqU.refl hleftWF · rename_i leftString leftBlob leftInfo rightString rightBlob rightInfo cases hvalue : leftString == rightString with | false => @@ -167,7 +167,7 @@ theorem tryDefEqWhnfStructural_wf hI.2.1.wf cases hleft cases hright - exact Lean4Lean.VEnv.IsDefEqU.refl hleftWF + exact Ix.Theory.Named.VEnv.IsDefEqU.refl hleftWF namespace TryDefEqWhnfStructural @@ -189,4 +189,4 @@ end TryDefEqWhnfStructural end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEta.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEta.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/FinalWhnf/StructureEta.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEta.lean index b29b620ff..c21041c10 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEta.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEta.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.StructureEtaTail -import Ix.Tc.Verify.Infer.Constants -import Ix.Tc.Verify.Infer.ProjectionTypes +import Ix.Kernel.Verify.DefEq.FinalWhnf.StructureEtaTail +import Ix.Kernel.Verify.Infer.Constants +import Ix.Kernel.Verify.Infer.ProjectionTypes /-! # Final-WHNF structure eta @@ -13,9 +13,9 @@ Theory boundary consumes that token together with the exact constructor metadata, typing derivations, and field equations selected by production. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Exact constructor fields retained from the declaration returned by the production lookup. -/ @@ -156,7 +156,7 @@ theorem normalizeEtaStructSource_wf simp only exact RecM.WF.pure fun hI => ⟨hsourceSupport, sourceV, hsource, - Lean4Lean.VEnv.IsDefEqU.refl (theory.exprWF hI.2.1 hsource)⟩ + Ix.Theory.Named.VEnv.IsDefEqU.refl (theory.exprWF hI.2.1 hsource)⟩ /-- Exhaust the size check, structure classifier, both caught inference calls, inferred-type comparison, and the verified structure-eta tail for one @@ -504,4 +504,4 @@ end TryDefEqWhnfStructEta end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaBase.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaBase.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaBase.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaBase.lean index c8451cf2f..b684ebbdc 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaBase.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaBase.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.StructureEtaFields -import Ix.Tc.Verify.DefEq.CheapReduction +import Ix.Kernel.Verify.DefEq.FinalWhnf.StructureEtaFields +import Ix.Kernel.Verify.DefEq.CheapReduction /-! # Structure-eta common-base scan @@ -12,9 +12,9 @@ state. A successful result carries the semantic projection equality for each scanned field. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Invert the structural translation of one concrete projection while retaining the resolved structure name and raw projection witness. -/ @@ -304,7 +304,7 @@ theorem etaExpansionBaseLoop_wf | none => have hvalueRefl : world.venv.IsDefEqU uvars Delta.toCtx valueV valueV := - Lean4Lean.VEnv.IsDefEqU.refl + Ix.Theory.Named.VEnv.IsDefEqU.refl (theory.exprWF hIValue.2.1 hvalueTr) exact hcontinue hvalueSupport hvalueTr hvalueRefl | some chosen => @@ -359,4 +359,4 @@ theorem etaExpansionBase_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaFields.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaFields.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaFields.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaFields.lean index d291cb45f..988e97f0c 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaFields.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaFields.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.Contracts +import Ix.Kernel.Verify.DefEq.FinalWhnf.Contracts /-! # Structure-eta field comparison @@ -11,9 +11,9 @@ structure metadata is not assumed here and remains the responsibility of the outer constructor/classifier proof. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -113,4 +113,4 @@ theorem tryEtaStructFields_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaTail.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaTail.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaTail.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaTail.lean index 0b63558ef..646e4f5fa 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/StructureEtaTail.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/StructureEtaTail.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.StructureEtaBase +import Ix.Kernel.Verify.DefEq.FinalWhnf.StructureEtaBase /-! # Structure-eta tail after type agreement @@ -9,9 +9,9 @@ types. The only semantic input is an eta law indexed by the exact field projection equations proved by those loops. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Exact semantic continuation needed after all structure fields agree. The outer constructor/classifier proof supplies this from the trusted @@ -129,4 +129,4 @@ theorem tryEtaStructAfterTypes_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/FinalWhnf/UnitLike.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/UnitLike.lean similarity index 96% rename from Ix/Tc/Verify/DefEq/FinalWhnf/UnitLike.lean rename to Ix/Kernel/Verify/DefEq/FinalWhnf/UnitLike.lean index 83418c0ad..e6b5410cb 100644 --- a/Ix/Tc/Verify/DefEq/FinalWhnf/UnitLike.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/UnitLike.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.DefEq.FinalWhnf.ProofTail -import Ix.Tc.Verify.Infer.Constants -import Ix.Tc.Verify.Whnf.StructEta.RecursionClassifier +import Ix.Kernel.Verify.DefEq.FinalWhnf.ProofTail +import Ix.Kernel.Verify.Infer.Constants +import Ix.Kernel.Verify.Whnf.StructEta.RecursionClassifier /-! # Final-WHNF unit-like equality @@ -8,15 +8,15 @@ import Ix.Tc.Verify.Whnf.StructEta.RecursionClassifier The operational classifier is proved exhaustively against the immutable catalog. Its semantic conclusion uses one deliberately narrow inductive law: inhabitants of a type headed by a trusted zero-index inductive with one -nullary constructor are definitionally equal. Lean4Lean's current +nullary constructor are definitionally equal. Ix.Theory.Named's current `VEnv.addInduct` interface does not expose that law, so it remains an explicit construction obligation for the inductive-theory bridge rather than being inferred from concrete metadata alone. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Constructor metadata accepted by production's unit-like shortcut. -/ def KConst.IsNullaryConstructor : KConst .anon → Prop @@ -30,7 +30,7 @@ def KConst.IsUnitLikeInductive (catalog : Catalog) : KConst .anon → Prop ∃ ctor, catalog ctors[0]! = some ctor ∧ ctor.IsNullaryConstructor | _ => False -/-- Semantic inductive law missing from Lean4Lean's current `addInduct` +/-- Semantic inductive law missing from Ix.Theory.Named's current `addInduct` specification. It is indexed by the exact trusted catalog shape and by the actual structurally translated type selected by production. -/ structure FinalWhnfUnitTheory (trProj : RawProjRel) @@ -252,4 +252,4 @@ end TryDefEqUnit end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/LazyDelta.lean b/Ix/Kernel/Verify/DefEq/LazyDelta.lean similarity index 99% rename from Ix/Tc/Verify/DefEq/LazyDelta.lean rename to Ix/Kernel/Verify/DefEq/LazyDelta.lean index 9a92b1e44..57dd93a2b 100644 --- a/Ix/Tc/Verify/DefEq/LazyDelta.lean +++ b/Ix/Kernel/Verify/DefEq/LazyDelta.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.ProofIrrelevance +import Ix.Kernel.Verify.DefEq.ProofIrrelevance /-! # Bounded lazy-delta DefEq closure @@ -10,9 +10,9 @@ step and the stopped tail. Individual reduction branches discharge those contracts in subsequent modules. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -280,4 +280,4 @@ theorem DefEqAfterProofIrrelevance.ofLazyDelta end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/LazyDeltaClosure.lean b/Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean similarity index 93% rename from Ix/Tc/Verify/DefEq/LazyDeltaClosure.lean rename to Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean index c3a2f4125..1716ac4dc 100644 --- a/Ix/Tc/Verify/DefEq/LazyDeltaClosure.lean +++ b/Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.LazyDeltaIteration -import Ix.Tc.Verify.DefEq.StoppedContinuationClosure +import Ix.Kernel.Verify.DefEq.LazyDeltaIteration +import Ix.Kernel.Verify.DefEq.StoppedContinuationClosure /-! # Complete lazy-delta tier assembly @@ -9,7 +9,7 @@ for a stopped pair. This module joins those independently proved executable surfaces under the canonical K2 suffix/cache model. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -58,4 +58,4 @@ end DefEqAfterProofIrrelevance end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/LazyDeltaIteration.lean b/Ix/Kernel/Verify/DefEq/LazyDeltaIteration.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/LazyDeltaIteration.lean rename to Ix/Kernel/Verify/DefEq/LazyDeltaIteration.lean index 82913e244..bf6b3180a 100644 --- a/Ix/Tc/Verify/DefEq/LazyDeltaIteration.lean +++ b/Ix/Kernel/Verify/DefEq/LazyDeltaIteration.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.EqualRankPrefix -import Ix.Tc.Verify.DefEq.NatOffsetDecomposition +import Ix.Kernel.Verify.DefEq.EqualRankPrefix +import Ix.Kernel.Verify.DefEq.NatOffsetDecomposition /-! # Complete lazy-delta iteration assembly @@ -14,7 +14,7 @@ DefEq, and finite run-scoped resources for same-head comparison and cache writes. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -108,4 +108,4 @@ end DefEqLazyDeltaStep end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/LoopFinish.lean b/Ix/Kernel/Verify/DefEq/LoopFinish.lean similarity index 95% rename from Ix/Tc/Verify/DefEq/LoopFinish.lean rename to Ix/Kernel/Verify/DefEq/LoopFinish.lean index 79e1411de..18a1926f0 100644 --- a/Ix/Tc/Verify/DefEq/LoopFinish.lean +++ b/Ix/Kernel/Verify/DefEq/LoopFinish.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.ProjectionProbe +import Ix.Kernel.Verify.DefEq.ProjectionProbe /-! # Lazy-delta loop finishing checks @@ -9,9 +9,9 @@ the bounded driver. This module discharges both accepting checks against the current pair and transports their result back through the loop invariant. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -63,4 +63,4 @@ theorem finishDefEqLazyDeltaStep_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/NatOffset.lean b/Ix/Kernel/Verify/DefEq/NatOffset.lean similarity index 96% rename from Ix/Tc/Verify/DefEq/NatOffset.lean rename to Ix/Kernel/Verify/DefEq/NatOffset.lean index 5aeee1ed3..103066960 100644 --- a/Ix/Tc/Verify/DefEq/NatOffset.lean +++ b/Ix/Kernel/Verify/DefEq/NatOffset.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.LazyDelta +import Ix.Kernel.Verify.DefEq.LazyDelta /-! # Nat-offset comparison @@ -9,9 +9,9 @@ the literal case and leaves the latter path behind a separately named contract. In particular, no negative result is assigned semantic meaning. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -182,7 +182,7 @@ theorem ofCandidates {uvars : Nat} (hafter : TryDefEqOffsetAfterCandidates.WFAt layer semantics trProj world support uvars) : - Ix.Tc.RecM.TryDefEqOffsetAfterZeroMiss.WFAt layer semantics trProj world + Ix.Kernel.RecM.TryDefEqOffsetAfterZeroMiss.WFAt layer semantics trProj world support uvars := by intro Delta state left right leftV rightV hleftSupport hrightSupport hleft hright @@ -235,7 +235,7 @@ theorem tryDefEqOffsetAfterLiteral_wf have hrightValue := hrightZero rfl subst leftV subst rightV - exact Lean4Lean.VEnv.IsDefEqU.refl hleftWF + exact Ix.Theory.Named.VEnv.IsDefEqU.refl hleftWF namespace TryDefEqOffsetAfterLiteral @@ -248,7 +248,7 @@ theorem ofZero (hzero : IsNatZero.WFAt layer semantics trProj world support uvars) (hafter : TryDefEqOffsetAfterZeroMiss.WFAt layer semantics trProj world support uvars) : - Ix.Tc.RecM.TryDefEqOffsetAfterLiteral.WFAt layer semantics trProj world + Ix.Kernel.RecM.TryDefEqOffsetAfterLiteral.WFAt layer semantics trProj world support uvars := by intro Delta state left right leftV rightV hleftSupport hrightSupport hleft hright @@ -296,7 +296,7 @@ theorem tryDefEqOffset_wf exact RecM.WF.pure fun _ hanswer => by have hvalues := eq_of_beq hanswer cases hvalues - exact Lean4Lean.VEnv.IsDefEqU.refl hleftWF + exact Ix.Theory.Named.VEnv.IsDefEqU.refl hleftWF namespace TryDefEqOffset @@ -308,7 +308,7 @@ theorem ofAfterLiteral (theory : WhnfTheory trProj world uvars) (hafter : TryDefEqOffsetAfterLiteral.WFAt layer semantics trProj world support uvars) : - Ix.Tc.RecM.TryDefEqOffset.WFAt layer semantics trProj world support + Ix.Kernel.RecM.TryDefEqOffset.WFAt layer semantics trProj world support uvars := by intro Delta state left right leftV rightV hleftSupport hrightSupport hleft hright @@ -325,7 +325,7 @@ theorem ofContext (zeroContext : NatZeroContext world) (hafter : TryDefEqOffsetAfterCandidates.WFAt .noAccel semantics trProj world support uvars) : - Ix.Tc.RecM.TryDefEqOffset.WFAt .noAccel semantics trProj world support + Ix.Kernel.RecM.TryDefEqOffset.WFAt .noAccel semantics trProj world support uvars := ofAfterLiteral theory <| TryDefEqOffsetAfterLiteral.ofZero theory @@ -336,4 +336,4 @@ end TryDefEqOffset end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/NatOffsetDecomposition.lean b/Ix/Kernel/Verify/DefEq/NatOffsetDecomposition.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/NatOffsetDecomposition.lean rename to Ix/Kernel/Verify/DefEq/NatOffsetDecomposition.lean index 5fb8ce726..1d6d5d58e 100644 --- a/Ix/Tc/Verify/DefEq/NatOffsetDecomposition.lean +++ b/Ix/Kernel/Verify/DefEq/NatOffsetDecomposition.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.NatOffset -import Ix.Tc.Verify.Whnf.Iota.NatOffset +import Ix.Kernel.Verify.DefEq.NatOffset +import Ix.Kernel.Verify.Whnf.Iota.NatOffset /-! # Nat-offset decomposition and reconstruction @@ -15,9 +15,9 @@ about successful parser/rebuilder executions. The latter is indexed by the exact production runs, so it cannot authorize an unrelated generated term. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace TcM.WF @@ -274,4 +274,4 @@ end TryDefEqOffsetAfterCandidates end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/NatReduction.lean b/Ix/Kernel/Verify/DefEq/NatReduction.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/NatReduction.lean rename to Ix/Kernel/Verify/DefEq/NatReduction.lean index 6327d751a..d64d279c0 100644 --- a/Ix/Tc/Verify/DefEq/NatReduction.lean +++ b/Ix/Kernel/Verify/DefEq/NatReduction.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.NatOffset +import Ix.Kernel.Verify.DefEq.NatOffset /-! # Lazy-delta Nat reduction @@ -9,9 +9,9 @@ against the opposite operand. This module composes the existing optional reducer and predecessor DefEq contracts with the lazy-delta pair invariant. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -127,4 +127,4 @@ end DefEqLazyDeltaAfterOffsetMiss end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/OneSidedDelta.lean b/Ix/Kernel/Verify/DefEq/OneSidedDelta.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/OneSidedDelta.lean rename to Ix/Kernel/Verify/DefEq/OneSidedDelta.lean index b6c5c8509..cdc0e215c 100644 --- a/Ix/Tc/Verify/DefEq/OneSidedDelta.lean +++ b/Ix/Kernel/Verify/DefEq/OneSidedDelta.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.LoopFinish +import Ix.Kernel.Verify.DefEq.LoopFinish /-! # One-sided lazy-delta unfolding @@ -9,9 +9,9 @@ finishing checks. This module gives those shared production helpers their complete pair-invariant contracts. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -116,4 +116,4 @@ theorem defEqLazyDeltaStepWithRightDelta_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaActive.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaActive.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaActive.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaActive.lean index 761d03ecb..dab1c786f 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaActive.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaActive.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.ProjectionDeltaRank +import Ix.Kernel.Verify.DefEq.ProjectionDeltaRank /-! # Active projection-delta branches @@ -10,9 +10,9 @@ unfold, normalization, and finishing proofs into the exact lower-step contract used by the bounded projection driver. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -133,4 +133,4 @@ end LazyDeltaReductionStep end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaClosure.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaClosure.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaClosure.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaClosure.lean index 35d6e2d1c..c2e8f645e 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaClosure.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaClosure.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.ProjectionDeltaActive -import Ix.Tc.Verify.DefEq.ProjectionProbe +import Ix.Kernel.Verify.DefEq.ProjectionDeltaActive +import Ix.Kernel.Verify.DefEq.ProjectionProbe /-! # Projection-directed delta closure @@ -15,7 +15,7 @@ left here is `DirectProjectionReflection`, indexed by the exact successful execution of `tryProjReduce`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -121,4 +121,4 @@ end TryStructuralCongruence end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaEqualRank.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaEqualRank.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaEqualRank.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaEqualRank.lean index dbb267250..4ccd66b7d 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaEqualRank.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaEqualRank.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.EqualRankCache -import Ix.Tc.Verify.DefEq.ProjectionDeltaUnfolding +import Ix.Kernel.Verify.DefEq.EqualRankCache +import Ix.Kernel.Verify.DefEq.ProjectionDeltaUnfolding /-! # Equal-rank projection-delta reduction @@ -12,9 +12,9 @@ iteration is intentionally absent here; this proof follows the actual compact helper. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -183,4 +183,4 @@ theorem lazyDeltaReductionStepWithEqualRank_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaFinish.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaFinish.lean similarity index 96% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaFinish.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaFinish.lean index 7dfe06a60..298e94a1f 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaFinish.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaFinish.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.ProjectionDeltaStep +import Ix.Kernel.Verify.DefEq.ProjectionDeltaStep /-! # Finishing a productive projection-directed delta step @@ -9,9 +9,9 @@ reports equality or schedules the transformed pair for another bounded iteration. This module proves that shared finish once. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -64,4 +64,4 @@ theorem finishLazyDeltaReductionStep_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaLoop.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaLoop.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaLoop.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaLoop.lean index 19e0874b2..e23100fc8 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaLoop.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaLoop.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.StructuralCongruence +import Ix.Kernel.Verify.DefEq.StructuralCongruence /-! # Projection-directed lazy-delta loop @@ -10,9 +10,9 @@ final recursive comparison. This module proves the bounded driver from exact contracts for those two lower helpers. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- A supported projection node exposes its value to the projection-directed loop. -/ @@ -228,4 +228,4 @@ end LazyDeltaProjReduction end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaRank.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaRank.lean similarity index 95% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaRank.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaRank.lean index f36da90b9..b28130a5f 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaRank.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaRank.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.ProjectionDeltaEqualRank +import Ix.Kernel.Verify.DefEq.ProjectionDeltaEqualRank /-! # Projection-delta rank dispatch @@ -9,9 +9,9 @@ Rank values carry no semantic authority: every selected helper is proved sound independently. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -68,4 +68,4 @@ theorem lazyDeltaReductionStepWithBothDelta_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaStep.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaStep.lean similarity index 96% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaStep.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaStep.lean index a95be5e66..49f579a13 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaStep.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaStep.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.DeltaClassification -import Ix.Tc.Verify.DefEq.ProjectionReduction +import Ix.Kernel.Verify.DefEq.DeltaClassification +import Ix.Kernel.Verify.DefEq.ProjectionReduction /-! # Projection-directed delta step @@ -12,7 +12,7 @@ success, absence, and partial-error behavior through the installed anonymous lazy-ingress contract. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -54,7 +54,7 @@ theorem lazyDeltaReductionStepAfterClassification_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {state : TcState .anon} - {leftSource rightSource : Lean4Lean.VExpr} + {leftSource rightSource : Ix.Theory.Named.VExpr} {left right : KExpr .anon} {aHead bHead : Option (KId .anon)} {aDelta bDelta : Bool} (hactive : LazyDeltaReductionAfterActive.WFAt layer semantics trProj @@ -99,7 +99,7 @@ theorem lazyDeltaReductionStep_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {state : TcState .anon} - {leftSource rightSource : Lean4Lean.VExpr} + {leftSource rightSource : Ix.Theory.Named.VExpr} {left right : KExpr .anon} (ingress : AnonLazyIngressContext .noAccel semantics trProj world support) @@ -151,4 +151,4 @@ end LazyDeltaReductionStep end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionDeltaUnfolding.lean b/Ix/Kernel/Verify/DefEq/ProjectionDeltaUnfolding.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/ProjectionDeltaUnfolding.lean rename to Ix/Kernel/Verify/DefEq/ProjectionDeltaUnfolding.lean index 425ab6fa7..430bc046e 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionDeltaUnfolding.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionDeltaUnfolding.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.ProjectionDeltaFinish +import Ix.Kernel.Verify.DefEq.ProjectionDeltaFinish /-! # One-sided projection-delta unfolding @@ -9,9 +9,9 @@ finish. The two theorems here cover both directions, including unfold misses and errors from either helper. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -111,4 +111,4 @@ theorem lazyDeltaReductionStepWithRightDelta_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionProbe.lean b/Ix/Kernel/Verify/DefEq/ProjectionProbe.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/ProjectionProbe.lean rename to Ix/Kernel/Verify/DefEq/ProjectionProbe.lean index 5e7944929..09131a2a6 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionProbe.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionProbe.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.DeltaClassification +import Ix.Kernel.Verify.DefEq.DeltaClassification /-! # Lazy-delta projection probe @@ -10,9 +10,9 @@ closes both asymmetric branches, transporting a successful projection result into the loop's pair invariant. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -148,4 +148,4 @@ end DefEqLazyDeltaAfterDeltaClassification end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProjectionReduction.lean b/Ix/Kernel/Verify/DefEq/ProjectionReduction.lean similarity index 96% rename from Ix/Tc/Verify/DefEq/ProjectionReduction.lean rename to Ix/Kernel/Verify/DefEq/ProjectionReduction.lean index ec0ffd1df..bf151c577 100644 --- a/Ix/Tc/Verify/DefEq/ProjectionReduction.lean +++ b/Ix/Kernel/Verify/DefEq/ProjectionReduction.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.ProjectionDeltaLoop -import Ix.Tc.Verify.Whnf.Projection.NoAccelTail +import Ix.Kernel.Verify.DefEq.ProjectionDeltaLoop +import Ix.Kernel.Verify.Whnf.Projection.NoAccelTail /-! # Direct projection reduction inside DefEq @@ -12,9 +12,9 @@ helper execution. It therefore cannot authorize a different projection, input, result, method table, or pair of states. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -106,4 +106,4 @@ end TryProjReduce end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/ProofIrrelevance.lean b/Ix/Kernel/Verify/DefEq/ProofIrrelevance.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/ProofIrrelevance.lean rename to Ix/Kernel/Verify/DefEq/ProofIrrelevance.lean index 0dc6175be..69fea4359 100644 --- a/Ix/Tc/Verify/DefEq/ProofIrrelevance.lean +++ b/Ix/Kernel/Verify/DefEq/ProofIrrelevance.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.CheapReduction -import Ix.Tc.Verify.Whnf.StructEta.CallbackPrefix +import Ix.Kernel.Verify.DefEq.CheapReduction +import Ix.Kernel.Verify.Whnf.StructEta.CallbackPrefix /-! # Pre-delta proof irrelevance @@ -10,9 +10,9 @@ types recursively. A positive result is justified by Theory proof irrelevance; caught callback errors remain ordinary misses. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -170,4 +170,4 @@ end DefEqAfterProofIrrelevance end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/PropositionClassifier.lean b/Ix/Kernel/Verify/DefEq/PropositionClassifier.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/PropositionClassifier.lean rename to Ix/Kernel/Verify/DefEq/PropositionClassifier.lean index ddc66951b..28d2118fa 100644 --- a/Ix/Tc/Verify/DefEq/PropositionClassifier.lean +++ b/Ix/Kernel/Verify/DefEq/PropositionClassifier.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.DefEq.ProofIrrelevance +import Ix.Kernel.Verify.DefEq.ProofIrrelevance + +open Ix.Theory (VLevel) /-! # Memoized proposition classification @@ -10,9 +12,9 @@ type with the direct K1 reducer, and install only a provenance-certified classification. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Resources needed by the concrete proposition classifier. Direct WHNF is the already-closed K1 reducer; inference remains a predecessor-table edge @@ -226,4 +228,4 @@ theorem tryProofIrrel_classifier_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/RankDispatch.lean b/Ix/Kernel/Verify/DefEq/RankDispatch.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/RankDispatch.lean rename to Ix/Kernel/Verify/DefEq/RankDispatch.lean index b0cf3ee57..aabf7fc8c 100644 --- a/Ix/Tc/Verify/DefEq/RankDispatch.lean +++ b/Ix/Kernel/Verify/DefEq/RankDispatch.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.OneSidedDelta +import Ix.Kernel.Verify.DefEq.OneSidedDelta /-! # Lazy-delta rank dispatch @@ -10,9 +10,9 @@ independently. Their declaration lookups must nevertheless preserve the state invariant across lazy ingress. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -134,4 +134,4 @@ end DefEqLazyDeltaAfterProjectionMiss end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/SameHeadSpine.lean b/Ix/Kernel/Verify/DefEq/SameHeadSpine.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/SameHeadSpine.lean rename to Ix/Kernel/Verify/DefEq/SameHeadSpine.lean index 85c4dba3c..5dbd00743 100644 --- a/Ix/Tc/Verify/DefEq/SameHeadSpine.lean +++ b/Ix/Kernel/Verify/DefEq/SameHeadSpine.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.DefEq.SpineArguments +import Ix.Kernel.Verify.DefEq.SpineArguments + +open Ix.Theory (VLevel) /-! # Same-head constant spines @@ -9,9 +11,9 @@ comparison, and successful recursive comparisons of every raw argument are lifted through the complete typed application spine. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLevel) +open Ix.Theory.Named (VExpr) /-- Finite support coverage needed by constant-headed spine comparison. -/ structure SameHeadSpineResources (support : RunSupport) : Prop where @@ -143,7 +145,7 @@ theorem constantHeadsDefEq cases hconst obtain ⟨hlength, hpairs⟩ := sameDefEqUniverses_sound hcollision hleftLevels hrightLevels hlevels - refine ⟨_, Lean4Lean.VEnv.IsDefEq.constDF hleftConst ?_ ?_ ?_ ?_⟩ + refine ⟨_, Ix.Theory.Named.VEnv.IsDefEq.constDF hleftConst ?_ ?_ ?_ ?_⟩ · intro level hmem obtain ⟨raw, hraw, rfl⟩ := List.mem_map.mp hmem exact hleftWF raw (by simpa using hraw) @@ -284,4 +286,4 @@ end TrySameHeadSpine end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/SpineArguments.lean b/Ix/Kernel/Verify/DefEq/SpineArguments.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/SpineArguments.lean rename to Ix/Kernel/Verify/DefEq/SpineArguments.lean index 78cac35f7..d23cdccd9 100644 --- a/Ix/Tc/Verify/DefEq/SpineArguments.lean +++ b/Ix/Kernel/Verify/DefEq/SpineArguments.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.EqualRankReduction +import Ix.Kernel.Verify.DefEq.EqualRankReduction /-! # Recursive application-spine arguments @@ -8,9 +8,9 @@ one left-to-right recursive DefEq loop. This module proves that loop once and gives its positive result a compositional Theory meaning. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -204,10 +204,10 @@ theorem defEq_of_zip hleftArgTr hrightArgTr have hlastTyped := hlastEq.of_l world.venvWF hDelta.toCtx hleftArg - exact ⟨_, Lean4Lean.VEnv.IsDefEq.appDF hcurrentTyped hlastTyped⟩ + exact ⟨_, Ix.Theory.Named.VEnv.IsDefEq.appDF hcurrentTyped hlastTyped⟩ end TrAppSpine end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/StoppedContinuation.lean b/Ix/Kernel/Verify/DefEq/StoppedContinuation.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/StoppedContinuation.lean rename to Ix/Kernel/Verify/DefEq/StoppedContinuation.lean index dde2cdbc3..67b77796d 100644 --- a/Ix/Tc/Verify/DefEq/StoppedContinuation.lean +++ b/Ix/Kernel/Verify/DefEq/StoppedContinuation.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.ApplicationSpine -import Ix.Tc.Verify.DefEq.StructuralCongruence +import Ix.Kernel.Verify.DefEq.ApplicationSpine +import Ix.Kernel.Verify.DefEq.StructuralCongruence /-! # Stopped lazy-delta continuation @@ -11,9 +11,9 @@ and the final WHNF comparator in that order. This module proves that exact outer control flow from contracts for its substantive helpers. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM @@ -190,4 +190,4 @@ end DefEqAfterLazyDeltaStopped end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/StoppedContinuationClosure.lean b/Ix/Kernel/Verify/DefEq/StoppedContinuationClosure.lean similarity index 94% rename from Ix/Tc/Verify/DefEq/StoppedContinuationClosure.lean rename to Ix/Kernel/Verify/DefEq/StoppedContinuationClosure.lean index 9a0839005..87cb2d2e3 100644 --- a/Ix/Tc/Verify/DefEq/StoppedContinuationClosure.lean +++ b/Ix/Kernel/Verify/DefEq/StoppedContinuationClosure.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.ProjectionDeltaClosure -import Ix.Tc.Verify.DefEq.StoppedContinuation +import Ix.Kernel.Verify.DefEq.ProjectionDeltaClosure +import Ix.Kernel.Verify.DefEq.StoppedContinuation /-! # Stopped-continuation closure @@ -10,7 +10,7 @@ comparison. This module constructs that resource record with the structural projection branch supplied by the concrete projection-delta closure. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -67,4 +67,4 @@ end DefEqAfterLazyDeltaStopped end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/StringLiteral.lean b/Ix/Kernel/Verify/DefEq/StringLiteral.lean similarity index 98% rename from Ix/Tc/Verify/DefEq/StringLiteral.lean rename to Ix/Kernel/Verify/DefEq/StringLiteral.lean index 2b33592fc..0a89eb4b4 100644 --- a/Ix/Tc/Verify/DefEq/StringLiteral.lean +++ b/Ix/Kernel/Verify/DefEq/StringLiteral.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.BoolTrue -import Ix.Tc.Verify.Whnf.Projection.StringExpansion +import Ix.Kernel.Verify.DefEq.BoolTrue +import Ix.Kernel.Verify.Whnf.Projection.StringExpansion /-! # String-literal definitional equality @@ -11,9 +11,9 @@ stronger fact recorded here: that exact generated term translates to the same Theory literal as the compact source syntax. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- A K1 String-expansion plan together with the exact Theory meaning needed by DefEq. Merely knowing that the generated expression has *some* @@ -200,4 +200,4 @@ end DefEqAfterStringExpansion end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/Structural.lean b/Ix/Kernel/Verify/DefEq/Structural.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/Structural.lean rename to Ix/Kernel/Verify/DefEq/Structural.lean index 195fc3905..2fc370351 100644 --- a/Ix/Tc/Verify/DefEq/Structural.lean +++ b/Ix/Kernel/Verify/DefEq/Structural.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Infer.BinderScopes -import Ix.Tc.Verify.Infer.Callbacks -import Ix.Tc.Verify.Infer.SortTypes +import Ix.Kernel.Verify.Infer.BinderScopes +import Ix.Kernel.Verify.Infer.Callbacks +import Ix.Kernel.Verify.Infer.SortTypes /-! # Structural definitional equality @@ -12,9 +12,9 @@ so its proof must be transported into the first domain's context before the recursive callback is invoked. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Finite resources needed to open both bodies of one quick binder comparison with the common production fvar. -/ @@ -220,8 +220,8 @@ theorem quickDefEq_wf have hbodyTyped : world.venv.IsDefEq uvars (ty1V :: Delta.toCtx) body1V body2V bodyTy := hbodyEq.of_l world.venvWF hDeltaBody.toCtx (by - simpa [KVLCtx.toCtx, Lean4Lean.VEnv.HasType] using hbody1Typed) - exact (Lean4Lean.VEnv.IsDefEq.lamDF + simpa [KVLCtx.toCtx, Ix.Theory.Named.VEnv.HasType] using hbody1Typed) + exact (Ix.Theory.Named.VEnv.IsDefEq.lamDF hdomainTyped hbodyTyped).toU · intro _ _ _ trivial @@ -253,7 +253,7 @@ theorem quickDefEq_wf (ty1V :: Delta.toCtx) body1V body2V (.sort bodyLevel) := hbodyEq.of_l world.venvWF hDeltaBody.toCtx (by simpa [KVLCtx.toCtx] using hbody1Sort) - exact (Lean4Lean.VEnv.IsDefEq.forallEDF + exact (Ix.Theory.Named.VEnv.IsDefEq.forallEDF hdomainTyped hbodyTyped).toU · intro _ _ _ trivial @@ -315,4 +315,4 @@ end DefEqAfterQuick end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/DefEq/StructuralCongruence.lean b/Ix/Kernel/Verify/DefEq/StructuralCongruence.lean similarity index 97% rename from Ix/Tc/Verify/DefEq/StructuralCongruence.lean rename to Ix/Kernel/Verify/DefEq/StructuralCongruence.lean index 08b130443..afe7c9131 100644 --- a/Ix/Tc/Verify/DefEq/StructuralCongruence.lean +++ b/Ix/Kernel/Verify/DefEq/StructuralCongruence.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq.SameHeadSpine +import Ix.Kernel.Verify.DefEq.SameHeadSpine /-! # Post-delta structural congruence @@ -10,9 +10,9 @@ other shapes and all failed guards return `false` without a completeness claim. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Finite universe support for constant nodes selected by structural congruence. -/ @@ -94,7 +94,7 @@ theorem tryStructuralCongruence_wf (hleftLookup.symm.trans hrightLookup) have hvalue : leftV = rightV := congrArg Prod.fst hp subst rightV - exact Lean4Lean.VEnv.IsDefEqU.refl hleftWF + exact Ix.Theory.Named.VEnv.IsDefEqU.refl hleftWF · rename_i leftId leftLevels leftInfo rightId rightLevels rightInfo exact RecM.WF.pure fun _ hanswer => by obtain ⟨hid, hlevels⟩ := Bool.and_eq_true_iff.mp hanswer @@ -145,4 +145,4 @@ end TryStructuralCongruence end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Driver/BooleanAcceptance.lean b/Ix/Kernel/Verify/Driver/BooleanAcceptance.lean similarity index 99% rename from Ix/Tc/Verify/Driver/BooleanAcceptance.lean rename to Ix/Kernel/Verify/Driver/BooleanAcceptance.lean index a10caebea..2690273ea 100644 --- a/Ix/Tc/Verify/Driver/BooleanAcceptance.lean +++ b/Ix/Kernel/Verify/Driver/BooleanAcceptance.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Driver.SupportedAcceptance -import Ix.Tc.Verify.Inductive.EnumerationAcceptance +import Ix.Kernel.Verify.Driver.SupportedAcceptance +import Ix.Kernel.Verify.Inductive.EnumerationAcceptance /-! # Certificate-backed Boolean driver acceptance @@ -20,7 +20,7 @@ then transported to each monotone current world and replayed idempotently; neither row constructs or admits an `InductiveOracle`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace BooleanEnumerationFixture @@ -596,4 +596,4 @@ theorem subjectWF : end BooleanEnumerationFixture -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Driver/Dependencies.lean b/Ix/Kernel/Verify/Driver/Dependencies.lean similarity index 99% rename from Ix/Tc/Verify/Driver/Dependencies.lean rename to Ix/Kernel/Verify/Driver/Dependencies.lean index 281c211ea..ace78133c 100644 --- a/Ix/Tc/Verify/Driver/Dependencies.lean +++ b/Ix/Kernel/Verify/Driver/Dependencies.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Driver.Model +import Ix.Kernel.Verify.Driver.Model /-! # Semantic dependencies of Ixon constants @@ -15,7 +15,7 @@ the expression constructors which ingress turns into kernel constants: * `.nat`/`.str` are data dependencies, not Theory declaration dependencies. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace IxonExpr @@ -179,4 +179,4 @@ theorem dependencyCatalog_dependsOn_iff (env : Ixon.Env) end IxonEnv -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Driver/Enumeration.lean b/Ix/Kernel/Verify/Driver/Enumeration.lean similarity index 99% rename from Ix/Tc/Verify/Driver/Enumeration.lean rename to Ix/Kernel/Verify/Driver/Enumeration.lean index 16411f32b..8bb44fac5 100644 --- a/Ix/Tc/Verify/Driver/Enumeration.lean +++ b/Ix/Kernel/Verify/Driver/Enumeration.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Driver.Dependencies +import Ix.Kernel.Verify.Driver.Dependencies /-! # Exact `buildAnonWork` enumeration @@ -14,7 +14,7 @@ Under that structural contract, the production builder succeeds, its collapses to its work item's root. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- `Except` carries no `DecidableEq` instance, so the `get`/`peekTag` equations of `ExactAnonEntry` cannot otherwise build the instance the @@ -570,4 +570,4 @@ theorem buildAnonWork_exact {env : Ixon.Env} end AnonWorkEnvWF -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Driver/Fixtures.lean b/Ix/Kernel/Verify/Driver/Fixtures.lean similarity index 98% rename from Ix/Tc/Verify/Driver/Fixtures.lean rename to Ix/Kernel/Verify/Driver/Fixtures.lean index 84c9403e4..1d3567768 100644 --- a/Ix/Tc/Verify/Driver/Fixtures.lean +++ b/Ix/Kernel/Verify/Driver/Fixtures.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Driver.Serial +import Ix.Kernel.Verify.Driver.Serial /-! # Adversarial E1 fixtures @@ -9,7 +9,7 @@ coverage, dependency closure, or graph well-foundedness cannot be hidden by content-address computation. -/ -namespace Ix.Tc.E1Fixture +namespace Ix.Kernel.E1Fixture def address (byte : UInt8) : Address := ⟨⟨Array.replicate 32 byte⟩⟩ @@ -178,4 +178,4 @@ theorem cyclicStandalones_not_wellFounded : · rfl · simp [firstItem, secondItem, AnonWorkItem.root] -end Ix.Tc.E1Fixture +end Ix.Kernel.E1Fixture diff --git a/Ix/Tc/Verify/Driver/Model.lean b/Ix/Kernel/Verify/Driver/Model.lean similarity index 97% rename from Ix/Tc/Verify/Driver/Model.lean rename to Ix/Kernel/Verify/Driver/Model.lean index a51e486a0..6428b01fa 100644 --- a/Ix/Tc/Verify/Driver/Model.lean +++ b/Ix/Kernel/Verify/Driver/Model.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Check.BlockIdentity +import Ix.Kernel.Verify.Check.BlockIdentity /-! # Workset and dependency model @@ -16,7 +16,7 @@ and every projection address have the same `blockOf` image. Standalones map to themselves. -/ -namespace Ix.Tc +namespace Ix.Kernel /-! ## Canonical finite address sets -/ @@ -188,7 +188,7 @@ def AssumptionsWF (baseline : VerifyWorld) (assumptions : FiniteAddressSet) : Prop := ∀ {addr}, addr ∈ assumptions → baseline.AcceptsAddress addr -/-- Per-item C2 consequence needed by composition. The rule is reusable at +/-- Per-item admission consequence needed by composition. The rule is reusable at any extension of `baseline`: once every dependency outside the item's own collapsed block is accepted, the item can be admitted atomically. -/ def AllAccepted (baseline : VerifyWorld) (catalog : DependencyCatalog) @@ -266,7 +266,7 @@ end WellFoundedBlocks /-! ## Checked-set composition -/ -/-- C3's semantic result: some final Theory world extends the baseline, +/-- Driver composition's semantic result: some final Theory world extends the baseline, accepts exactly the advertised subject domain at the raw-address interface, retains every explicit assumption, and records the closure/disjointness contracts needed for later claim-root binding. -/ @@ -338,7 +338,7 @@ private theorem composeTopological exact .inl (.head _) · exact .inr hrestMember -/-- The E1 checked-set theorem. Successful per-item C2 rules are reordered +/-- The checked-set theorem. Successful per-item admission rules are reordered by the constructive collapsed-block schedule; runtime address order is not assumed to be topological. -/ theorem acceptedWorkset_subjectWF @@ -366,4 +366,4 @@ theorem acceptedWorkset_subjectWF · intro addr haddr exact (hassumptions haddr).mono hfinal -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Driver/Serial.lean b/Ix/Kernel/Verify/Driver/Serial.lean similarity index 95% rename from Ix/Tc/Verify/Driver/Serial.lean rename to Ix/Kernel/Verify/Driver/Serial.lean index 1a19001f4..5a7de4f2c 100644 --- a/Ix/Tc/Verify/Driver/Serial.lean +++ b/Ix/Kernel/Verify/Driver/Serial.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Driver.Enumeration +import Ix.Kernel.Verify.Driver.Enumeration /-! # Serial `checkEnvAnon` composition @@ -8,13 +8,13 @@ per-item checker calls which produced it. A failed call always contributes at least one `CheckResult` for a well-formed production work item, so an all-success result array yields a concrete serial success trace. -`CheckSuccessSound` is the named C2 adapter: it consumes an actual successful +`CheckSuccessSound` is the named admission adapter: it consumes an actual successful `TcM.checkConst` execution and returns the reusable semantic admission rule needed by dependency-order composition. The serial corollary therefore does not assume `AllAccepted` directly. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Every public result row reports success. -/ def AllCheckResultsSucceeded (results : Array CheckResult) : Prop := @@ -146,9 +146,9 @@ theorem successfulStep {cfg : CheckCfg} {initial : AnonCheckLoopState} end SerialChecksSucceeded -/-- The concrete C2 adapter used by the serial corollary. Its premise is an +/-- The concrete admission adapter used by the serial corollary. Its premise is an actual successful `TcM.checkConst` call; its conclusion is the reusable -dependency-relative admission rule produced by the K3/E0 per-item theorem. -/ +dependency-relative admission rule produced by the per-item theorem. -/ def CheckSuccessSound (baseline : VerifyWorld) (catalog : DependencyCatalog) (work : Array AnonWorkItem) : Prop := ∀ item, item ∈ work → @@ -162,7 +162,7 @@ def CheckSuccessSound (baseline : VerifyWorld) current.AcceptsAddress target) → ∃ after, current ≤ after ∧ WorkItemAccepted after item -/-- A successful serial trace plus the concrete C2 adapter constructs the +/-- A successful serial trace plus the concrete admission adapter constructs the abstract admission predicate needed by topological composition. -/ theorem SerialChecksSucceeded.allAccepted {cfg : CheckCfg} {initial : AnonCheckLoopState} @@ -191,7 +191,7 @@ theorem checkEnvAnon_eq_serial {env : Ixon.Env} /-- E1's production serial-driver corollary. All emitted rows succeeding is converted to concrete per-item success traces, those traces are interpreted -through the C2 success rule, and the resulting admissions are reordered by +through the per-item success rule, and the resulting admissions are reordered by the proved collapsed-block schedule. -/ theorem checkEnvAnon_subjectWF {env : Ixon.Env} (h : AnonWorkEnvWF env) @@ -226,4 +226,4 @@ theorem checkEnvAnon_subjectWF end AnonWorkEnvWF -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Driver/SupportedAcceptance.lean b/Ix/Kernel/Verify/Driver/SupportedAcceptance.lean similarity index 96% rename from Ix/Tc/Verify/Driver/SupportedAcceptance.lean rename to Ix/Kernel/Verify/Driver/SupportedAcceptance.lean index f9c1e422d..e2c019ad2 100644 --- a/Ix/Tc/Verify/Driver/SupportedAcceptance.lean +++ b/Ix/Kernel/Verify/Driver/SupportedAcceptance.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Check.PublicBlocks -import Ix.Tc.Verify.Check.PublicStandalone -import Ix.Tc.Verify.Driver.Serial +import Ix.Kernel.Verify.Check.PublicBlocks +import Ix.Kernel.Verify.Check.PublicStandalone +import Ix.Kernel.Verify.Driver.Serial /-! # Supported production-checker acceptance @@ -26,7 +26,7 @@ The source-to-kernel route agreement remains an explicit representation premise until the later ingress/refinement phase discharges it generically. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace AnonWorkItem @@ -58,8 +58,8 @@ structure SupportedStandaloneResources (concrete : KConst .anon) : Type where pipelines : ScopedStandalonePipelineResources context.model support (context.calls (initial.recFuel.toNat + 1)) - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat) - decl : Lean4Lean.VDecl + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat) + decl : Ix.Theory.Named.VDecl projection : trProj.SubstCompatible literals : ∀ literal, world.venv.ContainsLits literal pending : PendingDecl trProj world id decl @@ -72,7 +72,7 @@ structure SupportedStandaloneResources route : StandaloneRoute (ScopedWhnfStateInv context.model .noAccel (kernelCacheSemantics context.model.keys trProj) support []) - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat) concrete + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat) concrete namespace SupportedStandaloneResources @@ -108,7 +108,7 @@ end SupportedStandaloneResources /-- Exhaustive body evidence supported by the E3-S adapter. The first constructor is constructive K3 evidence for the only definition -block shape currently modeled atomically by Lean4Lean: one definition. The +block shape currently modeled atomically by Ix.Theory.Named: one definition. The second constructor keeps the E2 inductive/recursor oracle visible. In particular there is no constructor containing a prebuilt `CertifiedBlockBodySuccess`. -/ @@ -122,10 +122,10 @@ inductive SupportedBlockBodyResources TcState .anon → TcState .anon → Prop | singletonDefinition {block requested member : KId .anon} {concrete : KConst .anon} - {decl : Lean4Lean.VDecl} {before after : TcState .anon} + {decl : Ix.Theory.Named.VDecl} {before after : TcState .anon} (pipelines : ScopedStandalonePipelineResources context.model support (context.calls (initial.recFuel.toNat + 1)) - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat)) + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat)) (projection : trProj.SubstCompatible) (literals : ∀ literal, world.venv.ContainsLits literal) (pending : PendingDecl trProj world member decl) @@ -168,17 +168,17 @@ theorem certify kind before after) (hexact : ExactCheckBlock world block members kind) (trace : RecM.ExactBlockBodySuccessTrace - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat) + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat) block requested members kind before after) : CertifiedBlockBodySuccess (kernelCacheSemantics context.model.keys trProj) trProj world support - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat) + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat) block requested members kind before after := by cases resources with | singletonDefinition pipelines projection literals pending catalog validation covered collision uvars resetScope initialInv lazyFault blocksAfter => - let methods := Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat + let methods := Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat have hmethods : Methods.ScopedWFAtOn context.model .noAccel (kernelCacheSemantics context.model.keys trProj) support (context.calls (initial.recFuel.toNat + 1)) @@ -291,7 +291,7 @@ theorem le_admittedWorld (resources : CertificateBackedBlockResources world blockAddr primary targets) : world ≤ resources.admittedWorld := - ⟨rfl, rfl, rfl, fun {_} hold => Or.inr hold, Lean4Lean.VEnv.LE.rfl⟩ + ⟨rfl, rfl, rfl, fun {_} hold => Or.inr hold, Ix.Theory.Named.VEnv.LE.rfl⟩ /-- Reindex installed semantic entries across an arbitrary monotone current world. This is the reusable bridge used by E1 after prior work items have @@ -391,14 +391,14 @@ structure SupportedCheckRun (world : VerifyWorld) (item : AnonWorkItem) TcM.getConst (⟨item.primary, ()⟩ : KId .anon) initial = .ok concrete loaded → (RecM.coordinatedBlockFor concrete).run - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat) loaded = + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat) loaded = .ok selected routed → item.SelectedBlockMatches selected standalone : ∀ {concrete : KConst .anon} {loaded routed : TcState .anon}, TcM.getConst (⟨item.primary, ()⟩ : KId .anon) initial = .ok concrete loaded → (RecM.coordinatedBlockFor concrete).run - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat) loaded = + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat) loaded = .ok none routed → SupportedStandaloneResources context concrete blockBody : ∀ {block : KId .anon} {members : Array (KId .anon)} @@ -406,7 +406,7 @@ structure SupportedCheckRun (world : VerifyWorld) (item : AnonWorkItem) ExactCheckBlock world block members kind → (⟨item.primary, ()⟩ : KId .anon) ∈ members → RecM.ExactBlockBodySuccessTrace - (Ix.Tc.methodsN (m := .anon) initial.recFuel.toNat) + (Ix.Kernel.methodsN (m := .anon) initial.recFuel.toNat) block (⟨item.primary, ()⟩ : KId .anon) members kind routed bodyAfter → SupportedBlockBodyResources context block @@ -668,4 +668,4 @@ theorem checkEnvAnon_supported_subjectWF end AnonWorkEnvWF -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Driver/SupportedAcceptanceFixtures.lean b/Ix/Kernel/Verify/Driver/SupportedAcceptanceFixtures.lean similarity index 95% rename from Ix/Tc/Verify/Driver/SupportedAcceptanceFixtures.lean rename to Ix/Kernel/Verify/Driver/SupportedAcceptanceFixtures.lean index 3003e1764..4feb1f616 100644 --- a/Ix/Tc/Verify/Driver/SupportedAcceptanceFixtures.lean +++ b/Ix/Kernel/Verify/Driver/SupportedAcceptanceFixtures.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Driver.Fixtures -import Ix.Tc.Verify.Driver.SupportedAcceptance -import Ix.Tc.Verify.Inductive.EnumerationAcceptance +import Ix.Kernel.Verify.Driver.Fixtures +import Ix.Kernel.Verify.Driver.SupportedAcceptance +import Ix.Kernel.Verify.Inductive.EnumerationAcceptance /-! # Supported-acceptance adversarial and inductive fixtures @@ -13,7 +13,7 @@ constructor; the only remaining inputs are the explicitly advertised scoped recursive context and active cache invariant. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace SupportedAcceptanceFixture @@ -88,7 +88,7 @@ theorem booleanFamilyBody_certified CertifiedBlockBodySuccess (kernelCacheSemantics context.model.keys RawProjRel.none) RawProjRel.none BooleanEnumerationFixture.world support - (Ix.Tc.methodsN (m := .anon) + (Ix.Kernel.methodsN (m := .anon) BooleanEnumerationFixture.checkerInitial.recFuel.toNat) BooleanEnumerationFixture.familyBlockId BooleanEnumerationFixture.familyId @@ -103,4 +103,4 @@ theorem booleanFamilyBody_certified end SupportedAcceptanceFixture -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Env.lean b/Ix/Kernel/Verify/Env.lean similarity index 98% rename from Ix/Tc/Verify/Env.lean rename to Ix/Kernel/Verify/Env.lean index b3c1283bf..f80f9f6d9 100644 --- a/Ix/Tc/Verify/Env.lean +++ b/Ix/Kernel/Verify/Env.lean @@ -1,8 +1,10 @@ -import Ix.Tc.Verify.Trans -import Ix.Tc.Verify.Decl -import Ix.Tc.Verify.Inductive -import Ix.Tc.Const -import Ix.Tc.Env +import Ix.Kernel.Verify.Trans +import Ix.Kernel.Verify.Decl +import Ix.Kernel.Verify.Inductive +import Ix.Kernel.Const +import Ix.Kernel.Env + +open Ix.Theory (VLevel) /-! # Environment translation: `KEnv` ↔ `VEnv` @@ -86,10 +88,10 @@ theorem le_antisymm {a b : Ix.DefinitionSafety} : end Ix.DefinitionSafety -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) -open Lean4Lean (VExpr VLevel VEnv VConstant VConstVal VDefVal VDecl +open Ix.Theory.Named (VExpr VEnv VConstant VConstVal VDefVal VDecl VInductDecl) /-! ### Constant safety -/ @@ -417,10 +419,10 @@ arbitrary well-formed Theory constant. It must select the exact constant and Lean name installed by `VEnv.addQuot` for the concrete declaration's role. -/ inductive QuotientConstRel : Ix.QuotKind → Lean.Name → VConstant → Prop - | quotType : QuotientConstRel .type ``Quot Lean4Lean.quotConst - | quotCtor : QuotientConstRel .ctor ``Quot.mk Lean4Lean.quotMkConst - | quotLift : QuotientConstRel .lift ``Quot.lift Lean4Lean.quotLiftConst - | quotInd : QuotientConstRel .ind ``Quot.ind Lean4Lean.quotIndConst + | quotType : QuotientConstRel .type ``Quot Ix.Theory.Named.quotConst + | quotCtor : QuotientConstRel .ctor ``Quot.mk Ix.Theory.Named.quotMkConst + | quotLift : QuotientConstRel .lift ``Quot.lift Ix.Theory.Named.quotLiftConst + | quotInd : QuotientConstRel .ind ``Quot.ind Ix.Theory.Named.quotIndConst /-- Provenance for one trusted catalog id. Standalone entries retain their actual declaration-WF transition. Ambient inductive-family entries retain the @@ -543,7 +545,7 @@ theorem recursorRule {trProj : RawProjRel} {catalog : Catalog} subst c exact False.elim hrule -/-- Recover the exact Lean4Lean iota-pattern witness associated with a +/-- Recover the exact Ix.Theory.Named iota-pattern witness associated with a trusted concrete recursor rule. -/ theorem recursorPattern {trProj : RawProjRel} {catalog : Catalog} {nameOf : Address → Option Lean.Name} {env : VEnv} @@ -577,7 +579,7 @@ end TrustedCatalogEntry /-- Consumer-facing provenance for one exact concrete constant. Unlike legacy `TrKConstant`, this relation does not require a translation log -over the whole concrete `KEnv`. It states only what C1--C3 consumers need at +over the whole concrete `KEnv`. It states what lookup and admission need at a trusted lookup: the immutable catalog entry is exactly `c`; its assigned Theory constant is installed and well-formed; universe arities agree; and the concrete type has a raw translation to that Theory type. Both standalone @@ -1002,7 +1004,7 @@ theorem IllTypedPending.trustedCatalogRel : namespace WellTypedPromotion -def targetName : Lean.Name := `Ix.Tc.Verify.wellTypedPromotion +def targetName : Lean.Name := `Ix.Kernel.Verify.wellTypedPromotion def fixtureAddress : Address := ⟨⟨Array.replicate 32 1⟩⟩ @@ -1060,7 +1062,7 @@ theorem pending : PendingDecl RawProjRel.none world targetId theoryDecl := by theorem theoryConstant_wf : theoryConstant.toVConstant.WF world.venv := by - exact ⟨.succ .zero, Lean4Lean.VEnv.HasType.sort (l := .zero) trivial⟩ + exact ⟨.succ .zero, Ix.Theory.Named.VEnv.HasType.sort (l := .zero) trivial⟩ theorem addConst : world.venv.addConst targetName theoryConstant.toVConstant = @@ -1085,4 +1087,4 @@ theorem promotes : end WellTypedPromotion -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/EquivalenceManager.lean b/Ix/Kernel/Verify/EquivalenceManager.lean similarity index 99% rename from Ix/Tc/Verify/EquivalenceManager.lean rename to Ix/Kernel/Verify/EquivalenceManager.lean index 7cc2c4719..0cadc80b9 100644 --- a/Ix/Tc/Verify/EquivalenceManager.lean +++ b/Ix/Kernel/Verify/EquivalenceManager.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Totalization -import Ix.Tc.Verify.Expr +import Ix.Kernel.Verify.Totalization +import Ix.Kernel.Verify.Expr import Batteries.Data.Array.Lemmas import Std.Data.HashMap.Lemmas @@ -14,7 +14,7 @@ edge remains semantically valid. That is sufficient for sound positive queries, root representatives, path compression, and union. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace EquivManager @@ -561,4 +561,4 @@ end WF end EquivManager -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Execution.lean b/Ix/Kernel/Verify/Execution.lean similarity index 99% rename from Ix/Tc/Verify/Execution.lean rename to Ix/Kernel/Verify/Execution.lean index 7c84bb886..4cac142ea 100644 --- a/Ix/Tc/Verify/Execution.lean +++ b/Ix/Kernel/Verify/Execution.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Support +import Ix.Kernel.Verify.Support /-! # G3b: execution-indexed finite run assumptions @@ -23,7 +23,7 @@ skeletons can use its concrete execution and support boundary without colliding with their temporary translation-relation placeholders. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- A proof-level decomposition of a `TcM` computation into audited interning operations. Lists conservatively include all continuation/handler @@ -253,4 +253,4 @@ theorem requestBounds {α : Type} {initial : TcState .anon} end RunAssumptions -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Expr.lean b/Ix/Kernel/Verify/Expr.lean similarity index 99% rename from Ix/Tc/Verify/Expr.lean rename to Ix/Kernel/Verify/Expr.lean index f7b0c7391..9f27b7c6d 100644 --- a/Ix/Tc/Verify/Expr.lean +++ b/Ix/Kernel/Verify/Expr.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Env -import Ix.Tc.Verify.Level +import Ix.Kernel.Env +import Ix.Kernel.Verify.Level import Std.Data.HashMap.Lemmas /-! @@ -31,7 +31,7 @@ module keeps as a named finite-support hypothesis — never a global axiom instance. -/ -namespace Ix.Tc +namespace Ix.Kernel variable {m : Mode} @@ -434,4 +434,4 @@ theorem internExpr_addr (hwf : it.WF) end InternTable -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Frame.lean b/Ix/Kernel/Verify/Frame.lean similarity index 98% rename from Ix/Tc/Verify/Frame.lean rename to Ix/Kernel/Verify/Frame.lean index 94948ac13..dccb04baa 100644 --- a/Ix/Tc/Verify/Frame.lean +++ b/Ix/Kernel/Verify/Frame.lean @@ -1,9 +1,9 @@ -import Ix.Tc.Verify.Subst +import Ix.Kernel.Verify.Subst /-! # Intern-table frame lemmas -The expression walkers in `Ix.Tc.Subst` mutate only the expression side of +The expression walkers in `Ix.Kernel.Subst` mutate only the expression side of `InternTable`. Their semantic master theorems establish expression support and table well-formedness, but the run-scoped invariant also tracks the finite universe range. This file proves the missing operational frame directly from @@ -14,7 +14,7 @@ The small effect predicates make sequential state threading explicit. They are intentionally restricted to anon mode, matching the verified kernel. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- An `InternM` action leaves the universe intern map unchanged. -/ def InternPreservesUnivs (x : InternM .anon α) : Prop := @@ -32,7 +32,7 @@ theorem pure (a : α) : InternPreservesUnivs (pure a) := by rfl theorem runWalk {x : WalkM .anon α} (h : WalkPreservesUnivs x) : - InternPreservesUnivs (Ix.Tc.runWalk x) := by + InternPreservesUnivs (Ix.Kernel.runWalk x) := by intro it exact h it {} @@ -53,12 +53,12 @@ theorem bind {x : WalkM .anon α} {f : α → WalkM .anon β} exact (hf _ _ _).trans (hx _ _) theorem scratchGet (key : Address × UInt64) : - WalkPreservesUnivs (Ix.Tc.scratchGet? key) := by + WalkPreservesUnivs (Ix.Kernel.scratchGet? key) := by intro it sc rfl theorem scratchInsert (key : Address × UInt64) (e : KExpr .anon) : - WalkPreservesUnivs (Ix.Tc.scratchInsert key e) := by + WalkPreservesUnivs (Ix.Kernel.scratchInsert key e) := by intro it sc rfl @@ -837,4 +837,4 @@ theorem abstractFVars_preservesUnivs (body : KExpr .anon) · exact .pure _ · exact .runWalk (abstractFVarsCached_preservesUnivs body _ _ 0) -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Upstream/Pending.lean b/Ix/Kernel/Verify/Frontier/Pending.lean similarity index 69% rename from Ix/Tc/Verify/Upstream/Pending.lean rename to Ix/Kernel/Verify/Frontier/Pending.lean index 58ea11c17..56660c6be 100644 --- a/Ix/Tc/Verify/Upstream/Pending.lean +++ b/Ix/Kernel/Verify/Frontier/Pending.lean @@ -1,25 +1,25 @@ -import Ix.Tc.Verify.Inductive.BlockPatternSoundness -import Lean4Lean.Verify.Environment.MutualInductiveFixtures +import Ix.Kernel.Verify.Inductive.BlockPatternSoundness +import Ix.Theory.Named.Verify.Environment.MutualInductiveFixtures /-! -# Quarantined pending-upstream witnesses +# Quarantined pending metatheory witnesses Nothing in this module may state an Ix ingress, address, ownership, checker, cache, collision, or workset fact. Conditional consumers import it directly; unconditional completed roots must not depend on it. -/ -namespace Ix.Tc.Upstream.Pending +namespace Ix.Kernel.Frontier.Pending -open Lean4Lean -open Lean4Lean.MutualInductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.MutualInductiveFixtures /-! ## Physical mutual-family permutation Ix's canonical mutual SCC order for this fixture is `TreeList, Tree`, while -the retained Lean declaration order is `Tree, TreeList`. Lean4Lean can -compute the exact reversed generation descriptor today; the missing upstream -piece is a theorem transporting block-generation WF across that family +the retained Lean declaration order is `Tree, TreeList`. The named specification +computes the exact reversed generation descriptor; the missing local +proof transports block-generation WF across that family permutation. -/ def mutualTreePhysicalDecl : VInductDecl := @@ -33,7 +33,7 @@ def mutualTreePhysicalBlockEnv : VEnv := (VEnv.empty.stageInductiveTypes mutualTreePhysicalDecl.types).get (by decide) -/-- Fixture-specific stand-in for the future Lean4Lean permutation theorem +/-- Fixture-specific stand-in for the missing named-specification permutation theorem `VInductDecl.BlockGenerationChecked.permuteFamiliesWF`. This is a Theory-only statement: it certifies the computed `TreeList, Tree` @@ -63,15 +63,14 @@ def mutualTreePhysicalCertificate : success := mutualTreePhysicalSuccess beforeWF := ⟨[], .empty⟩ -/-- Fixture-specific stand-in for the future Lean4Lean consumer theorem +/-- Fixture-specific stand-in for the missing named-specification consumer theorem `VInductDecl.BlockCertificate.recursorPatternSound` (the constructive wrapper around `BlockGenerationChecked.pat_wf`). -The current pin exposes the exact pattern payload and its registered rule but -does not yet publish this environment-parametric consumer conclusion without -the upstream metatheory gap. Delete this declaration, and replace its sole -use with that theorem, when the upstream result lands. -/ +The local specification exposes the exact pattern payload and its registered +rule. This conclusion still requires a metatheory proof. Completing that proof +must replace this axiom and its sole conditional use. -/ axiom mutualTreePhysicalRulePatternSound : CertifiedBlockRulePatternSound mutualTreePhysicalCertificate -end Ix.Tc.Upstream.Pending +end Ix.Kernel.Frontier.Pending diff --git a/Ix/Tc/Verify/Inductive.lean b/Ix/Kernel/Verify/Inductive.lean similarity index 94% rename from Ix/Tc/Verify/Inductive.lean rename to Ix/Kernel/Verify/Inductive.lean index baa2535c2..82567cb06 100644 --- a/Ix/Tc/Verify/Inductive.lean +++ b/Ix/Kernel/Verify/Inductive.lean @@ -1,12 +1,14 @@ -import Ix.Tc.Verify.Decl -import Ix.Tc.Verify.Inductive.Certificate -import Ix.Tc.Verify.Trans -import Lean4Lean.Theory.Typing.Pattern +import Ix.Kernel.Verify.Decl +import Ix.Kernel.Verify.Inductive.Certificate +import Ix.Kernel.Verify.Trans +import Ix.Theory.Named.Typing.Pattern + +open Ix.Theory (VLevel) /-! # Ambient inductive oracle -G2 introduced this interface before Lean4Lean had a usable inductive +G2 introduced this interface before Ix.Theory.Named had a usable inductive specification, so it records the semantic consequences needed by the checker directly: @@ -17,7 +19,7 @@ directly: * every concrete recursor rule has an explicit, well-formed Theory defeq witness headed by that recursor. -Pin A now provides Lean4Lean's proved normalized `GenerationCertificate` and +Pin A now provides Ix.Theory.Named's proved normalized `GenerationCertificate` and `addInductCertified` transaction. `Inductive/Certificate.lean` derives the Theory-owned environment, lookup, freshness, and rule-registration facts from that certificate. It intentionally cannot supply the Ix-owned catalog/name @@ -31,9 +33,9 @@ closed Nat model while the recursor clause prevents WHNF proofs from treating computation rules as an unrecorded ambient fact. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstant VDefEq VEnv VExpr) +open Ix.Theory.Named (VConstant VDefEq VEnv VExpr) /-- Concrete declaration kinds admitted through an ambient inductive block. Standalone declarations and quotients cannot cross this boundary. -/ @@ -125,12 +127,12 @@ def KConst.ConstructorAt (c : KConst .anon) (index : Nat) /-- A Theory expression is an application spine headed by `name`. -/ inductive HeadConst (name : Lean.Name) : VExpr → Prop - | const (levels : List Lean4Lean.VLevel) : + | const (levels : List Ix.Theory.VLevel) : HeadConst name (.const name levels) | app {fn arg : VExpr} : HeadConst name fn → HeadConst name (.app fn arg) /-- A closed rewrite equation may bind its complete rule telescope before -the recursor-headed application. Lean4Lean's generated iota equations and +the recursor-headed application. Ix.Theory.Named's generated iota equations and production's stored `RecRule.rhs` both use exactly this closed-lambda shape; requiring `HeadConst name defeq.lhs` at the outer node would reject every nonempty generated rule telescope. -/ @@ -168,7 +170,7 @@ end HeadConstUnderLambdas head. This is the counted form needed to distinguish an iota major from an arbitrary later occurrence of the same constructor. -/ inductive HeadConstN (name : Lean.Name) : Nat → VExpr → Prop - | const (levels : List Lean4Lean.VLevel) : + | const (levels : List Ix.Theory.VLevel) : HeadConstN name 0 (.const name levels) | app {arity : Nat} {fn arg : VExpr} : HeadConstN name arity fn → HeadConstN name (arity + 1) (.app fn arg) @@ -178,21 +180,21 @@ namespace HeadConstN /-- Matching `varN (const name) arity` exposes exactly that many application arguments over `name`. -/ theorem of_varN_matches {name : Lean.Name} {arity : Nat} {source : VExpr} - {levels : List Lean4Lean.VLevel} - {captures : ((Lean4Lean.Pattern.const name).varN arity).Path → VExpr} - (h : Lean4Lean.Pattern.Matches - ((Lean4Lean.Pattern.const name).varN arity) + {levels : List Ix.Theory.VLevel} + {captures : ((Ix.Theory.Named.Pattern.const name).varN arity).Path → VExpr} + (h : Ix.Theory.Named.Pattern.Matches + ((Ix.Theory.Named.Pattern.const name).varN arity) source levels captures) : HeadConstN name arity source := by induction arity generalizing source with | zero => - change Lean4Lean.Pattern.Matches (.const name) + change Ix.Theory.Named.Pattern.Matches (.const name) source levels captures at h cases h exact .const levels | succ arity ih => - change Lean4Lean.Pattern.Matches - (.var ((Lean4Lean.Pattern.const name).varN arity)) + change Ix.Theory.Named.Pattern.Matches + (.var ((Ix.Theory.Named.Pattern.const name).varN arity)) source levels captures at h cases h with | var hprefix => @@ -204,8 +206,8 @@ end HeadConstN /-- Exact Theory pattern selected by an ordinary constructor iota rule. -/ def RecursorIotaPattern (recursorName : Lean.Name) (majorIdx : Nat) (constructorName : Lean.Name) (constructorArgs : Nat) : - Lean4Lean.Pattern := - (Lean4Lean.SimplePattern.iota recursorName majorIdx constructorName + Ix.Theory.Named.Pattern := + (Ix.Theory.Named.SimplePattern.iota recursorName majorIdx constructorName constructorArgs).toPattern namespace RecursorIotaPattern @@ -216,17 +218,17 @@ contains precisely the parameters/motives/minors/indices before it. -/ theorem matches_shape {recursorName constructorName : Lean.Name} {majorIdx constructorArgs : Nat} {source : VExpr} - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs).Path → VExpr} - (h : Lean4Lean.Pattern.Matches + (h : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs) source levels captures) : ∃ recursorPrefix major, source = .app recursorPrefix major ∧ HeadConstN recursorName majorIdx recursorPrefix ∧ HeadConstN constructorName constructorArgs major := by - simp only [RecursorIotaPattern, Lean4Lean.SimplePattern.toPattern] at h + simp only [RecursorIotaPattern, Ix.Theory.Named.SimplePattern.toPattern] at h cases h with | app hrecursor hconstructor => exact ⟨_, _, rfl, HeadConstN.of_varN_matches hrecursor, @@ -342,7 +344,7 @@ end RawRecursorRuleRel `RawRecursorRuleRel` records a registered equation and its translated RHS, but a recursor-headed expression alone does not determine which argument is the major or which constructor rule was selected. This relation retains the -missing data in Lean4Lean's own rewrite vocabulary: +missing data in Ix.Theory.Named's own rewrite vocabulary: * the rule's exact array index and the production major index; * the exact catalogued constructor at that index, including parameter and @@ -399,14 +401,14 @@ def RecursorRulePattern.Sound (env : VEnv) ∀ {env' : VEnv}, env ≤ env' → env'.WF → ∀ {uvars : Nat} {Gamma : List VExpr} {source : VExpr} - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} {A : VExpr}, - Lean4Lean.OnCtx Gamma (env'.IsType uvars) → - Lean4Lean.Pattern.Matches + Ix.Theory.Named.OnCtx Gamma (env'.IsType uvars) → + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -436,14 +438,14 @@ def RawRecursorRulePatternRel (env : VEnv) (catalog : Catalog) ∀ {env' : VEnv}, env ≤ env' → env'.WF → ∀ {uvars : Nat} {Gamma : List VExpr} {source : VExpr} - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} {A : VExpr}, - Lean4Lean.OnCtx Gamma (env'.IsType uvars) → - Lean4Lean.Pattern.Matches + Ix.Theory.Named.OnCtx Gamma (env'.IsType uvars) → + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -668,4 +670,4 @@ def restageMissing end InductiveOracle -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/AliasFormerAdmission.lean b/Ix/Kernel/Verify/Inductive/AliasFormerAdmission.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/AliasFormerAdmission.lean rename to Ix/Kernel/Verify/Inductive/AliasFormerAdmission.lean index f5f84d8e8..e0ad3d12c 100644 --- a/Ix/Tc/Verify/Inductive/AliasFormerAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/AliasFormerAdmission.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.AliasFormerPattern -import Ix.Tc.Verify.Inductive.OneFamilyAdmission +import Ix.Kernel.Verify.Inductive.AliasFormerPattern +import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free family-result-normalizing singleton admission @@ -12,10 +12,10 @@ the family world. The sole iota pattern is justified by the registered generated equation, not by an inductive oracle. -/ -namespace Ix.Tc.AliasFormerRecursorFixture +namespace Ix.Kernel.AliasFormerRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AliasFormerCertificateFixture open AliasFormerFixture @@ -403,4 +403,4 @@ theorem aliasFormerAtomicClosure : AliasFormerAtomicClosure where iota := AliasFormerPattern.patternRel concreteRule_ruleAt familyResultNormalization := AliasFormerCertificateFixture.breadth -end Ix.Tc.AliasFormerRecursorFixture +end Ix.Kernel.AliasFormerRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/AliasFormerCertificate.lean b/Ix/Kernel/Verify/Inductive/AliasFormerCertificate.lean similarity index 91% rename from Ix/Tc/Verify/Inductive/AliasFormerCertificate.lean rename to Ix/Kernel/Verify/Inductive/AliasFormerCertificate.lean index 10f443821..54c3894b8 100644 --- a/Ix/Tc/Verify/Inductive/AliasFormerCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/AliasFormerCertificate.lean @@ -1,11 +1,11 @@ -import Ix.Tc.Verify.Inductive.ProducedGenerationTransaction -import Lean4Lean.Verify.Environment.InductiveFixtures +import Ix.Kernel.Verify.Inductive.ProducedGenerationTransaction +import Ix.Theory.Named.Verify.Environment.InductiveFixtures /-! # Certified family-result-normalizing fixture `AliasFormer` is declared with the raw result sort `TypeFamilyAlias`, a -transparent alias for `Type`. Lean4Lean's ordinary candidate pipeline +transparent alias for `Type`. Ix.Theory.Named's ordinary candidate pipeline normalizes that result to `Sort 1` before dependent inductive analysis while retaining the raw family and constructor declarations in the generated environment. @@ -15,11 +15,11 @@ anonymous ingress, production checking, and catalog admission are separate layers built on this certificate. -/ -namespace Ix.Tc.AliasFormerCertificateFixture +namespace Ix.Kernel.AliasFormerCertificateFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures noncomputable section @@ -53,8 +53,8 @@ theorem beforeWF : typeFamilyAliasEnv.WF := /-- Exact post-environment selected by that certificate. -/ def finalEnv : VEnv := aliasFormerFinalEnv -/-- The exact L4L-01E package. Its producer-shape index is deliberately -inferred here because Lean4Lean keeps the fixture's concrete shape witness +/-- The exact Spec-01E package. Its producer-shape index is deliberately +inferred here because Ix.Theory.Named keeps the fixture's concrete shape witness private while exposing this public dependent existence theorem. -/ def exactPackage := Classical.choice aliasFormerExactProducedGenerationCandidatePackage_exists @@ -75,7 +75,7 @@ def exactProducedTransaction := exact aliasFormer_addInductCertified_checked) beforeWF -/-- Intentional operational erasure of the exact L4L-01E indices. -/ +/-- Intentional operational erasure of the exact Spec-01E indices. -/ def producedTransaction : ProducedGenerationTransaction typeFamilyAliasEnv finalEnv [] := exactProducedTransaction.toProduced @@ -191,4 +191,4 @@ theorem certifiedFacts : end -end Ix.Tc.AliasFormerCertificateFixture +end Ix.Kernel.AliasFormerCertificateFixture diff --git a/Ix/Tc/Verify/Inductive/AliasFormerFixture.lean b/Ix/Kernel/Verify/Inductive/AliasFormerFixture.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/AliasFormerFixture.lean rename to Ix/Kernel/Verify/Inductive/AliasFormerFixture.lean index e31af049b..f18a65ca7 100644 --- a/Ix/Tc/Verify/Inductive/AliasFormerFixture.lean +++ b/Ix/Kernel/Verify/Inductive/AliasFormerFixture.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.AliasFormerCertificate -import Ix.Tc.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.AliasFormerCertificate +import Ix.Kernel.Verify.Ingress.AnonStructural /-! # Production family-result-normalizing fixture @@ -15,11 +15,11 @@ related to the exact Theory declaration, and promoted before the certified family transition; no ambient normalization or inductive oracle is used. -/ -namespace Ix.Tc.AliasFormerFixture +namespace Ix.Kernel.AliasFormerFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open AliasFormerCertificateFixture open InductiveConcreteFixture @@ -570,4 +570,4 @@ def familyLink : SingletonFamilyCatalogLink RawProjRel.none world.catalog interpretation.toCatalogLinkOfEntries familyIngressExecution catalogEntry trustedCatalog -end Ix.Tc.AliasFormerFixture +end Ix.Kernel.AliasFormerFixture diff --git a/Ix/Tc/Verify/Inductive/AliasFormerPattern.lean b/Ix/Kernel/Verify/Inductive/AliasFormerPattern.lean similarity index 90% rename from Ix/Tc/Verify/Inductive/AliasFormerPattern.lean rename to Ix/Kernel/Verify/Inductive/AliasFormerPattern.lean index 56723f491..746eb262e 100644 --- a/Ix/Tc/Verify/Inductive/AliasFormerPattern.lean +++ b/Ix/Kernel/Verify/Inductive/AliasFormerPattern.lean @@ -1,19 +1,19 @@ -import Ix.Tc.Verify.Inductive.SingletonEnumeration -import Ix.Tc.Verify.Inductive.AliasFormerRecursorFixture +import Ix.Kernel.Verify.Inductive.SingletonEnumeration +import Ix.Kernel.Verify.Inductive.AliasFormerRecursorFixture /-! # Family-result-normalizing enumeration pattern -Once Lean4Lean has normalized `TypeFamilyAlias` to `Type`, `AliasFormer` is +Once Ix.Theory.Named has normalized `TypeFamilyAlias` to `Type`, `AliasFormer` is the one-constructor instance of the certified singleton-enumeration fragment. This module proves that exact fragment classification and instantiates the generic registered-equation pattern theorem for `AliasFormer.mk`. -/ -namespace Ix.Tc.AliasFormerPattern +namespace Ix.Kernel.AliasFormerPattern -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AliasFormerCertificateFixture open AliasFormerRecursorFixture @@ -87,4 +87,4 @@ theorem patternRel {rule : RecRule .anon} RawRecursorRulePatternRel.of_metadata_sound (metadata hrule) (sound hrule) -end Ix.Tc.AliasFormerPattern +end Ix.Kernel.AliasFormerPattern diff --git a/Ix/Tc/Verify/Inductive/AliasFormerRecursorFixture.lean b/Ix/Kernel/Verify/Inductive/AliasFormerRecursorFixture.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/AliasFormerRecursorFixture.lean rename to Ix/Kernel/Verify/Inductive/AliasFormerRecursorFixture.lean index b29ca8516..0722f0c27 100644 --- a/Ix/Tc/Verify/Inductive/AliasFormerRecursorFixture.lean +++ b/Ix/Kernel/Verify/Inductive/AliasFormerRecursorFixture.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.AliasFormerFixture +import Ix.Kernel.Verify.Inductive.AliasFormerFixture /-! # Production `AliasFormer.rec` fixture @@ -9,11 +9,11 @@ the normalized result `Type`, the stored recursor and iota equation are the exact artifacts registered by the certificate for the raw declaration. -/ -namespace Ix.Tc.AliasFormerRecursorFixture +namespace Ix.Kernel.AliasFormerRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open AliasFormerCertificateFixture open AliasFormerFixture open InductiveConcreteFixture @@ -720,4 +720,4 @@ def recursorLink : SingletonRecursorCatalogLink RawProjRel.none world.catalog recursorInterpretation.toCatalogLinkOfEntry recursorIngressExecution catalog_recursor trustedCatalog -end Ix.Tc.AliasFormerRecursorFixture +end Ix.Kernel.AliasFormerRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/AliasRecAdmission.lean b/Ix/Kernel/Verify/Inductive/AliasRecAdmission.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/AliasRecAdmission.lean rename to Ix/Kernel/Verify/Inductive/AliasRecAdmission.lean index 7dcc65165..a1027c0ee 100644 --- a/Ix/Tc/Verify/Inductive/AliasRecAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/AliasRecAdmission.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.AliasRecSoundness -import Ix.Tc.Verify.Inductive.OneFamilyAdmission +import Ix.Kernel.Verify.Inductive.AliasRecSoundness +import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free recursive-field-normalizing direct-recursive admission @@ -12,10 +12,10 @@ the family world. The sole iota pattern is justified by the registered generated equation, not by an inductive oracle. -/ -namespace Ix.Tc.AliasRecRecursorFixture +namespace Ix.Kernel.AliasRecRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AliasRecCertificateFixture open AliasRecFixture @@ -401,5 +401,5 @@ theorem aliasRecAtomicClosure : AliasRecAtomicClosure where iota := AliasRecPattern.patternRel concreteRule_ruleAt recursiveFieldNormalization := AliasRecCertificateFixture.breadth -end Ix.Tc.AliasRecRecursorFixture +end Ix.Kernel.AliasRecRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/AliasRecCertificate.lean b/Ix/Kernel/Verify/Inductive/AliasRecCertificate.lean similarity index 91% rename from Ix/Tc/Verify/Inductive/AliasRecCertificate.lean rename to Ix/Kernel/Verify/Inductive/AliasRecCertificate.lean index 0aec2232e..f407a1c63 100644 --- a/Ix/Tc/Verify/Inductive/AliasRecCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/AliasRecCertificate.lean @@ -1,27 +1,27 @@ -import Ix.Tc.Verify.Inductive.Certificate -import Lean4Lean.Verify.Environment.InductiveFixtures +import Ix.Kernel.Verify.Inductive.Certificate +import Ix.Theory.Named.Verify.Environment.InductiveFixtures /-! # Certified recursive-field-normalizing fixture `AliasRec.mk` retains the raw field `RecAlias AliasRec`, where `RecAlias` is -a transparent identity definition. Lean4Lean's checked normalization path +a transparent identity definition. Ix.Theory.Named's checked normalization path unfolds that field to the direct recursive occurrence `AliasRec` before dependent inductive analysis, while the generated environment continues to store the raw constructor declaration. -Lean4Lean exposes the exact checked generation and its semantic WF theorem, +Ix.Theory.Named exposes the exact checked generation and its semantic WF theorem, but deliberately does not add another fixture-specific public certificate wrapper. This module performs that narrow consumer-side packaging. Physical anonymous ingress, production checking, and catalog admission remain separate layers. -/ -namespace Ix.Tc.AliasRecCertificateFixture +namespace Ix.Kernel.AliasRecCertificateFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures /-- The transparent identity definition preceding `AliasRec`. -/ def recAliasValue : VDefVal := recAliasVal @@ -45,7 +45,7 @@ theorem recAliasDeclWF : theorem beforeWF : recAliasEnv.WF := ⟨[.def recAliasValue], .decl recAliasDeclWF .empty⟩ -/-- Consumer-facing packaging of Lean4Lean's exact checker-produced +/-- Consumer-facing packaging of Ix.Theory.Named's exact checker-produced `AliasRec` generation. The proof field is erased by `addInductCertified`; the executable generation is definitionally the upstream checked artifact. -/ def certificate : aliasRecRawDecl.GenerationCertificate recAliasEnv where @@ -155,4 +155,4 @@ theorem certifiedFacts : CertifiedGenerationFacts recAliasEnv finalEnv transaction.certificate := transaction.facts -end Ix.Tc.AliasRecCertificateFixture +end Ix.Kernel.AliasRecCertificateFixture diff --git a/Ix/Tc/Verify/Inductive/AliasRecFixture.lean b/Ix/Kernel/Verify/Inductive/AliasRecFixture.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/AliasRecFixture.lean rename to Ix/Kernel/Verify/Inductive/AliasRecFixture.lean index 6106ea15b..4118e5a8b 100644 --- a/Ix/Tc/Verify/Inductive/AliasRecFixture.lean +++ b/Ix/Kernel/Verify/Inductive/AliasRecFixture.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.AliasRecCertificate -import Ix.Tc.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.AliasRecCertificate +import Ix.Kernel.Verify.Ingress.AnonStructural /-! # Production recursive-field-normalizing fixture @@ -15,11 +15,11 @@ related to the exact Theory declaration, and promoted before the certified family transition; no ambient inductive or normalization oracle is used. -/ -namespace Ix.Tc.AliasRecFixture +namespace Ix.Kernel.AliasRecFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open AliasRecCertificateFixture open InductiveConcreteFixture @@ -569,4 +569,4 @@ def familyLink : SingletonFamilyCatalogLink RawProjRel.none world.catalog interpretation.toCatalogLinkOfEntries familyIngressExecution catalogEntry trustedCatalog -end Ix.Tc.AliasRecFixture +end Ix.Kernel.AliasRecFixture diff --git a/Ix/Tc/Verify/Inductive/AliasRecPattern.lean b/Ix/Kernel/Verify/Inductive/AliasRecPattern.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/AliasRecPattern.lean rename to Ix/Kernel/Verify/Inductive/AliasRecPattern.lean index 60dbcf95f..48b6309b8 100644 --- a/Ix/Tc/Verify/Inductive/AliasRecPattern.lean +++ b/Ix/Kernel/Verify/Inductive/AliasRecPattern.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Inductive.IotaPattern -import Ix.Tc.Verify.Inductive.AliasRecRecursorFixture +import Ix.Kernel.Verify.Inductive.IotaPattern +import Ix.Kernel.Verify.Inductive.AliasRecRecursorFixture + +open Ix.Theory (VLevel) /-! # Recursive-field-normalizing direct-recursive iota pattern @@ -15,10 +17,10 @@ motive, minor premise, and constructor-field captures. The soundness proof beta-reduces that application to the registered equation. -/ -namespace Ix.Tc.AliasRecPattern +namespace Ix.Kernel.AliasRecPattern -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AliasRecCertificateFixture open AliasRecFixture open AliasRecRecursorFixture @@ -182,5 +184,5 @@ theorem metadata {rule : RecRule .anon} simpa only [pattern, mkFieldCount, show (1 : UInt64).toNat = 1 from rfl] using hfields -end Ix.Tc.AliasRecPattern +end Ix.Kernel.AliasRecPattern diff --git a/Ix/Tc/Verify/Inductive/AliasRecRecursorFixture.lean b/Ix/Kernel/Verify/Inductive/AliasRecRecursorFixture.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/AliasRecRecursorFixture.lean rename to Ix/Kernel/Verify/Inductive/AliasRecRecursorFixture.lean index 8fc9dcbe3..0f6fb668f 100644 --- a/Ix/Tc/Verify/Inductive/AliasRecRecursorFixture.lean +++ b/Ix/Kernel/Verify/Inductive/AliasRecRecursorFixture.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.AliasRecFixture +import Ix.Kernel.Verify.Inductive.AliasRecFixture /-! # Production `AliasRec.rec` fixture @@ -9,11 +9,11 @@ recursive-field-alias-bearing family. Its minor premise retains the raw field normalized direct-recursive value `motive a`. -/ -namespace Ix.Tc.AliasRecRecursorFixture +namespace Ix.Kernel.AliasRecRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open AliasRecCertificateFixture open AliasRecFixture open InductiveConcreteFixture @@ -726,4 +726,4 @@ def recursorLink : SingletonRecursorCatalogLink RawProjRel.none world.catalog recursorInterpretation.toCatalogLinkOfEntry recursorIngressExecution catalog_recursor trustedCatalog -end Ix.Tc.AliasRecRecursorFixture +end Ix.Kernel.AliasRecRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/AliasRecSoundness.lean b/Ix/Kernel/Verify/Inductive/AliasRecSoundness.lean similarity index 95% rename from Ix/Tc/Verify/Inductive/AliasRecSoundness.lean rename to Ix/Kernel/Verify/Inductive/AliasRecSoundness.lean index cbdb4d98d..66a4f4f2e 100644 --- a/Ix/Tc/Verify/Inductive/AliasRecSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/AliasRecSoundness.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.AliasRecPattern +import Ix.Kernel.Verify.Inductive.AliasRecPattern + +open Ix.Theory (VLevel) /-! # Recursive-field-normalizing direct-recursive iota soundness @@ -12,10 +14,10 @@ throughout; recursive classification comes from the certified normalized view. -/ -namespace Ix.Tc.AliasRecPattern +namespace Ix.Kernel.AliasRecPattern -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AliasRecCertificateFixture open AliasRecFixture open AliasRecRecursorFixture @@ -210,7 +212,7 @@ theorem patternSound {rule : RecRule .anon} hconstructorApplied⟩ := htype.app_inv hfutureWF.ordered hGamma obtain ⟨recursorHeadType, hrecursorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := hrecursorHeadTyped.const_inv hfutureWF.ordered hGamma have hcertifiedRecursorLookup := @@ -233,7 +235,7 @@ theorem patternSound {rule : RecRule .anon} subst levelTail obtain ⟨constructorHeadType, hconstructorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied obtain ⟨constructorConstant, hconstructorLookup, constructorLevelsWF, hconstructorLevelsArity⟩ := hconstructorHeadTyped.const_inv hfutureWF.ordered hGamma @@ -282,7 +284,7 @@ theorem patternSound {rule : RecRule .anon} have hrecursorConstantTyped : future.HasType uvars Gamma (.const ``AliasRec.rec [u]) (generation.recType.instL [u]) := by - have htyped := Lean4Lean.VEnv.HasType.const (Γ := Gamma) + have htyped := Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity rw [generationRecursorName] at htyped simpa [VInductDecl.GenerationChecked.recursor] using htyped @@ -306,14 +308,14 @@ theorem patternSound {rule : RecRule .anon} (VExpr.appN ((generation.rule 0 normalized).lhs.instL [u]) [motive, minor]) (equationFieldType u motive minor) := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hcommonLength hrecursorApplied hrecursorCommonType hequationLhsCommonType have hconstructorConstantTyped : future.HasType uvars Gamma (.const ``AliasRec.mk []) constructorFieldType := by simpa [constructorFieldType, normalizedName] using - (Lean4Lean.VEnv.HasType.const (Γ := Gamma) + (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedConstructorLookup constructorLevelsWF hconstructorLevelsArity) have hconstructorFieldHead : future.HasType uvars Gamma @@ -342,7 +344,7 @@ theorem patternSound {rule : RecRule .anon} rw [fieldBinders_eq] rfl have hequationLhsFieldsApplied := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hfieldLength hconstructorApplied hconstructorFieldHead' hequationFieldHead have hequationLhsApplied : future.HasType uvars Gamma @@ -354,7 +356,7 @@ theorem patternSound {rule : RecRule .anon} VExpr.appN_append] exact hequationLhsFieldsApplied have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationLhsApplied' := hequationLhsApplied @@ -364,7 +366,7 @@ theorem patternSound {rule : RecRule .anon} (ruleBinders.map (VExpr.instL [u])).length := by simpa only [List.length_cons, List.length_nil, List.length_map] using ruleBinders_length.symm - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleArgsLength hequationLhsApplied' rw [lhsBody_open] at hlhsBeta have hlhsBeta' : future.IsDefEqU uvars Gamma @@ -399,4 +401,4 @@ theorem patternRel {rule : RecRule .anon} RawRecursorRulePatternRel.of_metadata_sound (metadata hrule) (patternSound hrule) -end Ix.Tc.AliasRecPattern +end Ix.Kernel.AliasRecPattern diff --git a/Ix/Tc/Verify/Inductive/AnnotatedPiAdmission.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiAdmission.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/AnnotatedPiAdmission.lean rename to Ix/Kernel/Verify/Inductive/AnnotatedPiAdmission.lean index c55dc99b7..b5e2899b8 100644 --- a/Ix/Tc/Verify/Inductive/AnnotatedPiAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiAdmission.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.AnnotatedPiSoundness -import Ix.Tc.Verify.Inductive.OneFamilyAdmission +import Ix.Kernel.Verify.Inductive.AnnotatedPiSoundness +import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free annotation-normalizing recursive-Pi admission @@ -12,10 +12,10 @@ the family world. The sole iota pattern is justified by the registered generated equation, not by an inductive oracle. -/ -namespace Ix.Tc.AnnotatedPiRecursorFixture +namespace Ix.Kernel.AnnotatedPiRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AnnotatedPiCertificateFixture open AnnotatedPiFixture @@ -403,4 +403,4 @@ theorem annotatedPiAtomicClosure : AnnotatedPiAtomicClosure where iota := AnnotatedPiPattern.patternRel concreteRule_ruleAt annotationNormalization := AnnotatedPiCertificateFixture.breadth -end Ix.Tc.AnnotatedPiRecursorFixture +end Ix.Kernel.AnnotatedPiRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/AnnotatedPiCertificate.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiCertificate.lean similarity index 91% rename from Ix/Tc/Verify/Inductive/AnnotatedPiCertificate.lean rename to Ix/Kernel/Verify/Inductive/AnnotatedPiCertificate.lean index 258dc2bf2..cef1c052a 100644 --- a/Ix/Tc/Verify/Inductive/AnnotatedPiCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiCertificate.lean @@ -1,26 +1,26 @@ -import Ix.Tc.Verify.Inductive.ProducedGenerationTransaction -import Lean4Lean.Verify.Environment.InductiveFixtures +import Ix.Kernel.Verify.Inductive.ProducedGenerationTransaction +import Ix.Theory.Named.Verify.Environment.InductiveFixtures /-! # Certified annotation-normalizing recursive-Pi fixture `AnnotatedPi.mk` retains the raw binder domain `outParam Prop`, while the -Lean4Lean analyzer classifies recursion through the normalized domain `Prop`. +Ix.Theory.Named analyzer classifies recursion through the normalized domain `Prop`. This is the first Ix transaction whose certified generation is deliberately non-identity: the stored family and generated artifacts preserve raw syntax, but recursive classification is owned by the checked view produced by the -ordinary Lean4Lean candidate pipeline. +ordinary Ix.Theory.Named candidate pipeline. The module is still Theory-facing. Physical anonymous ingress, production checking, and catalog admission are separate layers built on this exact certificate. -/ -namespace Ix.Tc.AnnotatedPiCertificateFixture +namespace Ix.Kernel.AnnotatedPiCertificateFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures noncomputable section @@ -51,7 +51,7 @@ theorem outParamDeclWF : rfl /-- Explicit well-formed history for the annotation environment. The public -Lean4Lean certificate needs this environment as input, rather than silently +Ix.Theory.Named certificate needs this environment as input, rather than silently treating the reducible annotation as a primitive. -/ theorem beforeWF : outParamEnv.WF := ⟨[.def outParamValue], .decl outParamDeclWF .empty⟩ @@ -59,8 +59,8 @@ theorem beforeWF : outParamEnv.WF := /-- Exact post-environment selected by that certificate. -/ def finalEnv : VEnv := annotatedPiFinalEnv -/-- The exact L4L-01E package. Its producer-shape index is deliberately -inferred here because Lean4Lean keeps the fixture's concrete shape witness +/-- The exact Spec-01E package. Its producer-shape index is deliberately +inferred here because Ix.Theory.Named keeps the fixture's concrete shape witness private while exposing this public dependent existence theorem. -/ def exactPackage := Classical.choice annotatedPiExactProducedGenerationCandidatePackage_exists @@ -81,7 +81,7 @@ def exactProducedTransaction := exact annotatedPi_addInductCertified) beforeWF -/-- Intentional operational erasure of the exact L4L-01E indices. -/ +/-- Intentional operational erasure of the exact Spec-01E indices. -/ def producedTransaction : ProducedGenerationTransaction outParamEnv finalEnv [] := exactProducedTransaction.toProduced @@ -211,4 +211,4 @@ theorem certifiedFacts : end -end Ix.Tc.AnnotatedPiCertificateFixture +end Ix.Kernel.AnnotatedPiCertificateFixture diff --git a/Ix/Tc/Verify/Inductive/AnnotatedPiFixture.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiFixture.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/AnnotatedPiFixture.lean rename to Ix/Kernel/Verify/Inductive/AnnotatedPiFixture.lean index 1809344e6..225fd5a72 100644 --- a/Ix/Tc/Verify/Inductive/AnnotatedPiFixture.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiFixture.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.AnnotatedPiCertificate -import Ix.Tc.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.AnnotatedPiCertificate +import Ix.Kernel.Verify.Ingress.AnonStructural /-! # Production annotation-normalizing recursive-Pi fixture @@ -15,11 +15,11 @@ related to the exact Theory declaration, and promoted before the certified family transition; no ambient inductive or normalization oracle is used. -/ -namespace Ix.Tc.AnnotatedPiFixture +namespace Ix.Kernel.AnnotatedPiFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open AnnotatedPiCertificateFixture open InductiveConcreteFixture @@ -570,4 +570,4 @@ def familyLink : SingletonFamilyCatalogLink RawProjRel.none world.catalog interpretation.toCatalogLinkOfEntries familyIngressExecution catalogEntry trustedCatalog -end Ix.Tc.AnnotatedPiFixture +end Ix.Kernel.AnnotatedPiFixture diff --git a/Ix/Tc/Verify/Inductive/AnnotatedPiPattern.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiPattern.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/AnnotatedPiPattern.lean rename to Ix/Kernel/Verify/Inductive/AnnotatedPiPattern.lean index effa2ef86..44bbca657 100644 --- a/Ix/Tc/Verify/Inductive/AnnotatedPiPattern.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiPattern.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Inductive.IotaPattern -import Ix.Tc.Verify.Inductive.AnnotatedPiRecursorFixture +import Ix.Kernel.Verify.Inductive.IotaPattern +import Ix.Kernel.Verify.Inductive.AnnotatedPiRecursorFixture + +open Ix.Theory (VLevel) /-! # Annotation-normalizing recursive-Pi iota pattern @@ -16,10 +18,10 @@ apply it to the motive, minor premise, and constructor field captures. The soundness proof beta-reduces that application to the registered equation. -/ -namespace Ix.Tc.AnnotatedPiPattern +namespace Ix.Kernel.AnnotatedPiPattern -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AnnotatedPiCertificateFixture open AnnotatedPiFixture open AnnotatedPiRecursorFixture @@ -183,4 +185,4 @@ theorem metadata {rule : RecRule .anon} simpa only [pattern, mkFieldCount, show (1 : UInt64).toNat = 1 from rfl] using hfields -end Ix.Tc.AnnotatedPiPattern +end Ix.Kernel.AnnotatedPiPattern diff --git a/Ix/Tc/Verify/Inductive/AnnotatedPiRecursorFixture.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiRecursorFixture.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/AnnotatedPiRecursorFixture.lean rename to Ix/Kernel/Verify/Inductive/AnnotatedPiRecursorFixture.lean index f317169c2..c2c15a417 100644 --- a/Ix/Tc/Verify/Inductive/AnnotatedPiRecursorFixture.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiRecursorFixture.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.AnnotatedPiFixture +import Ix.Kernel.Verify.Inductive.AnnotatedPiFixture /-! # Production `AnnotatedPi.rec` fixture @@ -9,11 +9,11 @@ the raw field type `(p : outParam Prop) -> AnnotatedPi` with the normalized induction-hypothesis domain `(p : Prop) -> motive (f p)`. -/ -namespace Ix.Tc.AnnotatedPiRecursorFixture +namespace Ix.Kernel.AnnotatedPiRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open AnnotatedPiCertificateFixture open AnnotatedPiFixture open InductiveConcreteFixture @@ -731,4 +731,4 @@ def recursorLink : SingletonRecursorCatalogLink RawProjRel.none world.catalog recursorInterpretation.toCatalogLinkOfEntry recursorIngressExecution catalog_recursor trustedCatalog -end Ix.Tc.AnnotatedPiRecursorFixture +end Ix.Kernel.AnnotatedPiRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/AnnotatedPiSoundness.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiSoundness.lean similarity index 95% rename from Ix/Tc/Verify/Inductive/AnnotatedPiSoundness.lean rename to Ix/Kernel/Verify/Inductive/AnnotatedPiSoundness.lean index 24e74839e..0023a6b7e 100644 --- a/Ix/Tc/Verify/Inductive/AnnotatedPiSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiSoundness.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.AnnotatedPiPattern +import Ix.Kernel.Verify.Inductive.AnnotatedPiPattern + +open Ix.Theory (VLevel) /-! # Annotation-normalizing recursive-Pi iota soundness @@ -11,10 +13,10 @@ already the complete generated-rule telescope. The reducible `outParam Prop` annotation remains present in that raw field binder throughout the argument. -/ -namespace Ix.Tc.AnnotatedPiPattern +namespace Ix.Kernel.AnnotatedPiPattern -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open AnnotatedPiCertificateFixture open AnnotatedPiFixture open AnnotatedPiRecursorFixture @@ -209,7 +211,7 @@ theorem patternSound {rule : RecRule .anon} hconstructorApplied⟩ := htype.app_inv hfutureWF.ordered hGamma obtain ⟨recursorHeadType, hrecursorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := hrecursorHeadTyped.const_inv hfutureWF.ordered hGamma have hcertifiedRecursorLookup := @@ -232,7 +234,7 @@ theorem patternSound {rule : RecRule .anon} subst levelTail obtain ⟨constructorHeadType, hconstructorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied obtain ⟨constructorConstant, hconstructorLookup, constructorLevelsWF, hconstructorLevelsArity⟩ := hconstructorHeadTyped.const_inv hfutureWF.ordered hGamma @@ -281,7 +283,7 @@ theorem patternSound {rule : RecRule .anon} have hrecursorConstantTyped : future.HasType uvars Gamma (.const ``AnnotatedPi.rec [u]) (generation.recType.instL [u]) := by - have htyped := Lean4Lean.VEnv.HasType.const (Γ := Gamma) + have htyped := Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity rw [generationRecursorName] at htyped simpa [VInductDecl.GenerationChecked.recursor] using htyped @@ -305,14 +307,14 @@ theorem patternSound {rule : RecRule .anon} (VExpr.appN ((generation.rule 0 normalized).lhs.instL [u]) [motive, minor]) (equationFieldType u motive minor) := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hcommonLength hrecursorApplied hrecursorCommonType hequationLhsCommonType have hconstructorConstantTyped : future.HasType uvars Gamma (.const ``AnnotatedPi.mk []) constructorFieldType := by simpa [constructorFieldType, normalizedName] using - (Lean4Lean.VEnv.HasType.const (Γ := Gamma) + (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedConstructorLookup constructorLevelsWF hconstructorLevelsArity) have hconstructorFieldHead : future.HasType uvars Gamma @@ -341,7 +343,7 @@ theorem patternSound {rule : RecRule .anon} rw [fieldBinders_eq] rfl have hequationLhsFieldsApplied := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hfieldLength hconstructorApplied hconstructorFieldHead' hequationFieldHead have hequationLhsApplied : future.HasType uvars Gamma @@ -353,7 +355,7 @@ theorem patternSound {rule : RecRule .anon} VExpr.appN_append] exact hequationLhsFieldsApplied have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationLhsApplied' := hequationLhsApplied @@ -363,7 +365,7 @@ theorem patternSound {rule : RecRule .anon} (ruleBinders.map (VExpr.instL [u])).length := by simpa only [List.length_cons, List.length_nil, List.length_map] using ruleBinders_length.symm - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleArgsLength hequationLhsApplied' rw [lhsBody_open] at hlhsBeta have hlhsBeta' : future.IsDefEqU uvars Gamma @@ -399,4 +401,4 @@ theorem patternRel {rule : RecRule .anon} RawRecursorRulePatternRel.of_metadata_sound (metadata hrule) (patternSound hrule) -end Ix.Tc.AnnotatedPiPattern +end Ix.Kernel.AnnotatedPiPattern diff --git a/Ix/Tc/Verify/Inductive/BlockCertificate.lean b/Ix/Kernel/Verify/Inductive/BlockCertificate.lean similarity index 91% rename from Ix/Tc/Verify/Inductive/BlockCertificate.lean rename to Ix/Kernel/Verify/Inductive/BlockCertificate.lean index 70672f555..7f9c1c284 100644 --- a/Ix/Tc/Verify/Inductive/BlockCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/BlockCertificate.lean @@ -1,21 +1,21 @@ -import Lean4Lean.Theory.Typing.InductiveCertificate +import Ix.Theory.Named.Typing.InductiveCertificate /-! # Certified mutual-inductive block transactions -This is the Theory-only consumer boundary for Lean4Lean's L4L-08 block +This is the Theory-only consumer boundary for Ix.Theory.Named's Spec-08 block generation certificate. A mutual block is one atomic semantic transaction: all family constants are inserted before any constructors, all constructors before any recursors, and all recursors before the globally flattened iota rules. It must not be represented as a list of singleton transactions. As with `CertifiedGenerationTransaction`, this module imports no executable -Lean4Lean verifier and mentions no Ix address, catalog, or checker state. +Ix.Theory.Named verifier and mentions no Ix address, catalog, or checker state. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named /-- One successful proof-carrying block generation, together with the well-formed Theory environment it extends. -/ @@ -54,7 +54,7 @@ structure CertifiedBlockGenerationFacts {source : VInductDecl} namespace CertifiedBlockGenerationTransaction -/-- Repackage Ix's historical transaction adapter as Lean4Lean's current +/-- Repackage Ix's historical transaction adapter as Ix.Theory.Named's current consumer certificate. This is definitionally the same semantic input, successful atomic transaction, and pre-environment WF proof; no second generation run or compatibility axiom is introduced. -/ @@ -65,7 +65,7 @@ def toBlockCertificate {source : VInductDecl} {before after : VEnv} success := tx.success beforeWF := tx.beforeWF -/-- Recover L4L-08's exact four-phase trace for the atomic block. -/ +/-- Recover Spec-08's exact four-phase trace for the atomic block. -/ theorem trace {source : VInductDecl} {before after : VEnv} (tx : CertifiedBlockGenerationTransaction source before after) : Nonempty (VEnv.AddInductBlockGenerationTrace before after @@ -102,4 +102,4 @@ theorem facts {source : VInductDecl} {before after : VEnv} end CertifiedBlockGenerationTransaction -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/BlockPatternSoundness.lean b/Ix/Kernel/Verify/Inductive/BlockPatternSoundness.lean similarity index 90% rename from Ix/Tc/Verify/Inductive/BlockPatternSoundness.lean rename to Ix/Kernel/Verify/Inductive/BlockPatternSoundness.lean index 122afbf8b..3ac6b51d7 100644 --- a/Ix/Tc/Verify/Inductive/BlockPatternSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/BlockPatternSoundness.lean @@ -1,23 +1,25 @@ -import Ix.Tc.Verify.Inductive.BlockCertificate +import Ix.Kernel.Verify.Inductive.BlockCertificate + +open Ix.Theory (VLevel) /-! # Consumer boundary for certified generated-pattern soundness -Lean4Lean's block certificate already identifies the exact generated pattern, +Ix.Theory.Named's block certificate already identifies the exact generated pattern, RHS template, checks, registered equation, and well-formed post-environment for every flattened constructor. The remaining consumer theorem says that a well-typed match satisfying those checks is definitionally equal to that RHS in every future environment. -This interface is deliberately stated entirely in Lean4Lean's Theory +This interface is deliberately stated entirely in Ix.Theory.Named's Theory vocabulary. It carries no Ix address, catalog, ownership, ingress, or checker claim, so a temporary upstream witness cannot discharge any downstream correspondence obligation. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named /-- Environment-parametric soundness of one dependent pattern payload. Keeping this independent of any certificate makes transport along an equality @@ -64,4 +66,4 @@ def CertifiedBlockRulePatternSound (certificate.generation.ruleCheck certificate.ruleClosure (List.mem_of_getElem? entry)) -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/CandidateSyntax.lean b/Ix/Kernel/Verify/Inductive/CandidateSyntax.lean similarity index 95% rename from Ix/Tc/Verify/Inductive/CandidateSyntax.lean rename to Ix/Kernel/Verify/Inductive/CandidateSyntax.lean index 7f38c432e..97f5d3b15 100644 --- a/Ix/Tc/Verify/Inductive/CandidateSyntax.lean +++ b/Ix/Kernel/Verify/Inductive/CandidateSyntax.lean @@ -1,13 +1,13 @@ -import Ix.Tc.Verify.Inductive.PositivityTraceAdapter -import Ix.Tc.Verify.Totalization +import Ix.Kernel.Verify.Inductive.PositivityTraceAdapter +import Ix.Kernel.Verify.Totalization /-! -# Exact candidate syntax shared by Ix and Lean4Lean +# Exact candidate syntax shared by Ix and Ix.Theory.Named The Theory-level `VExpr` relations used elsewhere in the verification are semantic: they deliberately forget binder annotations and concrete free- variable identifiers. Constructor positivity has one stricter boundary. -Lean4Lean's `isValidIndApp?` inspects the exact kernel `Lean.Expr`, so a +Ix.Theory.Named's `isValidIndApp?` inspects the exact kernel `Lean.Expr`, so a Theory-level definitional-equality result cannot justify that executable syntax test. @@ -20,7 +20,7 @@ of those choices and discharges the corresponding field of `FlatPositivityTraceTransport` without a semantic oracle. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact correspondence between one Ix positivity expression and one Lean kernel candidate expression. This intentionally excludes syntax erased by @@ -330,18 +330,18 @@ theorem mentionsAnyAddr_eq_hasIndOcc (blocks : CandidateBlockRel nameOf ixAddrs leanConsts) (relation : CandidateSyntaxRel nameOf fvarRel levelRel ixExpr leanExpr) : exprMentionsAnyAddr ixExpr ixAddrs = - Lean4Lean.AddInductive.hasIndOcc leanConsts leanExpr := by + Ix.Theory.Named.AddInductive.hasIndOcc leanConsts leanExpr := by induction relation with | bvar => simp [exprMentionsAnyAddr, exprMentionsAddr, - exprMentionsAddr.go, Lean4Lean.AddInductive.hasIndOcc] + exprMentionsAddr.go, Ix.Theory.Named.AddInductive.hasIndOcc] | fvar => simp [exprMentionsAnyAddr, exprMentionsAddr, - exprMentionsAddr.go, Lean4Lean.AddInductive.hasIndOcc] + exprMentionsAddr.go, Ix.Theory.Named.AddInductive.hasIndOcc] | sort => simp [exprMentionsAnyAddr, exprMentionsAddr, - exprMentionsAddr.go, Lean4Lean.AddInductive.hasIndOcc] + exprMentionsAddr.go, Ix.Theory.Named.AddInductive.hasIndOcc] | @const id ixLevels info leanName leanLevels hname levels => simp only [exprMentionsAnyAddr, exprMentionsAddr_equation, exprMentionsAddr_go_const, exprMentionsAddr_go_nil, - Lean4Lean.AddInductive.hasIndOcc] + Ix.Theory.Named.AddInductive.hasIndOcc] have occurrence : exprMentionsAddr (.const id ixLevels info) = (fun addr => id.addr == addr) := by @@ -350,11 +350,11 @@ theorem mentionsAnyAddr_eq_hasIndOcc rw [occurrence] exact blocks hname | app fn arg ihFn ihArg => - rw [mentionsAny_app, Lean4Lean.AddInductive.hasIndOcc, ihFn, ihArg] + rw [mentionsAny_app, Ix.Theory.Named.AddInductive.hasIndOcc, ihFn, ihArg] | forallE domain body ihDomain ihBody => - rw [mentionsAny_all, Lean4Lean.AddInductive.hasIndOcc, + rw [mentionsAny_all, Ix.Theory.Named.AddInductive.hasIndOcc, ihDomain, ihBody] end CandidateSyntaxRel -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/Certificate.lean b/Ix/Kernel/Verify/Inductive/Certificate.lean similarity index 94% rename from Ix/Tc/Verify/Inductive/Certificate.lean rename to Ix/Kernel/Verify/Inductive/Certificate.lean index ead590788..06eaa4596 100644 --- a/Ix/Tc/Verify/Inductive/Certificate.lean +++ b/Ix/Kernel/Verify/Inductive/Certificate.lean @@ -1,11 +1,11 @@ -import Lean4Lean.Theory.Typing.EnvLemmas +import Ix.Theory.Named.Typing.EnvLemmas /-! # Certified inductive-generation transactions -This module is the Theory-only consumer boundary for Lean4Lean's normalized +This module is the Theory-only consumer boundary for Ix.Theory.Named's normalized inductive-generation certificate. It deliberately imports no -`Lean4Lean.Verify` module and mentions no Ix catalog, address, checker state, +`Ix.Theory.Named.Verify` module and mentions no Ix catalog, address, checker state, or recursor-pattern relation. `GenerationCertificate` proves that one exact normalized generation is @@ -20,9 +20,9 @@ checked, how their addresses map to names, or that production iota metadata matches the generated Theory rules. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named /-- One successful proof-carrying normalized inductive transaction, together with the well-formed input environment needed to extend a Theory history. @@ -36,7 +36,7 @@ structure CertifiedGenerationTransaction (source : VInductDecl) beforeWF : before.WF /-- The complete Theory-owned consequences of a certified generation -transaction. All fields concern only the Lean4Lean source, generated +transaction. All fields concern only the Ix.Theory.Named source, generated artifacts, and input/output `VEnv`s. -/ structure CertifiedGenerationFacts {source : VInductDecl} (before after : VEnv) (certificate : source.GenerationCertificate before) : @@ -128,4 +128,4 @@ theorem facts {source : VInductDecl} {before after : VEnv} end CertifiedGenerationTransaction -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/ConcreteFixture.lean b/Ix/Kernel/Verify/Inductive/ConcreteFixture.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/ConcreteFixture.lean rename to Ix/Kernel/Verify/Inductive/ConcreteFixture.lean index 41eb54154..b311259a3 100644 --- a/Ix/Tc/Verify/Inductive/ConcreteFixture.lean +++ b/Ix/Kernel/Verify/Inductive/ConcreteFixture.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Inductive.IngressExecution -import Ix.Tc.Verify.Check.PreTranslationCompatibility +import Ix.Kernel.Verify.Inductive.IngressExecution +import Ix.Kernel.Verify.Check.PreTranslationCompatibility + +open Ix.Theory (VLevel) /-! # Shared executable inductive-fixture support @@ -11,9 +13,9 @@ core binder syntax returned by anonymous ingress. Keeping these here avoids making indexed-recursive coverage depend on the Boolean enumeration fixture. -/ -namespace Ix.Tc.InductiveConcreteFixture +namespace Ix.Kernel.InductiveConcreteFixture -open Lean4Lean (VEnv VExpr) +open Ix.Theory.Named (VEnv VExpr) /-- Store a constant at its production content address. -/ def storeConstant (env : Ixon.Env) (constant : Ixon.Constant) : @@ -214,4 +216,4 @@ instance kExprScopedDecidable (depth : UInt64) (levelBound : Nat) .isFalse fun hscoped => h ((scopedExprB_eq_true_iff depth levelBound expression).mpr hscoped) -end Ix.Tc.InductiveConcreteFixture +end Ix.Kernel.InductiveConcreteFixture diff --git a/Ix/Tc/Verify/Inductive/ConstructorPositivityTraversal.lean b/Ix/Kernel/Verify/Inductive/ConstructorPositivityTraversal.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/ConstructorPositivityTraversal.lean rename to Ix/Kernel/Verify/Inductive/ConstructorPositivityTraversal.lean index 3a5adfac5..7df19c39f 100644 --- a/Ix/Tc/Verify/Inductive/ConstructorPositivityTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/ConstructorPositivityTraversal.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.RecursivePositivityTraversal +import Ix.Kernel.Verify.Inductive.RecursivePositivityTraversal /-! # Complete constructor-positivity traversal @@ -11,7 +11,7 @@ parameter opening, source-ordered field traversal, and final local-context restoration. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact successful execution of the production parameter-opening loop. The `short` case records the deliberately permissive result used so A1/A2 can @@ -366,4 +366,4 @@ theorem checkPositivity_success (methods : Methods m) exact .success (checkPositivityCore_success methods hcore) hrestored end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/ConstructorValidationTraversal.lean b/Ix/Kernel/Verify/Inductive/ConstructorValidationTraversal.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/ConstructorValidationTraversal.lean rename to Ix/Kernel/Verify/Inductive/ConstructorValidationTraversal.lean index 3b2914fd9..106a2826f 100644 --- a/Ix/Tc/Verify/Inductive/ConstructorValidationTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/ConstructorValidationTraversal.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.ConstructorPositivityTraversal +import Ix.Kernel.Verify.Inductive.ConstructorPositivityTraversal /-! # Production constructor-validation traversal @@ -10,7 +10,7 @@ execution around that call: derived metadata, shared-parameter agreement, safety gating, field-universe validation, and constructor-return validation. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Successful constructor-metadata validation together with the exact physical constructor header selected by its lookup. The aggregate run alone @@ -704,4 +704,4 @@ theorem checkInductiveBlockImpl_success (methods : Methods m) (checkInductiveMembers_success methods hinductives) hrun end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/EliminationBreadthFixture.lean b/Ix/Kernel/Verify/Inductive/EliminationBreadthFixture.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/EliminationBreadthFixture.lean rename to Ix/Kernel/Verify/Inductive/EliminationBreadthFixture.lean index 0592aee14..7d8f4403d 100644 --- a/Ix/Tc/Verify/Inductive/EliminationBreadthFixture.lean +++ b/Ix/Kernel/Verify/Inductive/EliminationBreadthFixture.lean @@ -1,14 +1,14 @@ import Ix.CompileDriver -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.SingletonRecursor -import Ix.Tc.Verify.Ingress.AnonStructural -import Lean4Lean.Verify.Environment.EliminationFixturesEq -import Lean4Lean.Verify.Environment.EliminationFixturesSmall +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.SingletonRecursor +import Ix.Kernel.Verify.Ingress.AnonStructural +import Ix.Theory.Named.Verify.Environment.EliminationFixturesEq +import Ix.Theory.Named.Verify.Environment.EliminationFixturesSmall /-! # Concrete small-elimination and K-target breadth -Lean4Lean's L4L-06 fixtures retain the exact kernel elimination traversal and +Ix.Theory.Named's Spec-06 fixtures retain the exact kernel elimination traversal and align it with the generated Theory metadata. This module takes the remaining Ix step: it compiles those same kernel declarations to production Ixon blocks, ingresses the family and recursor projections, and runs both production block @@ -16,7 +16,7 @@ checkers. The two cases are deliberately complementary: -* `L4L06SmallSource` keeps its source universe but introduces no fresh +* `Spec06SmallSource` keeps its source universe but introduces no fresh elimination universe; and * `Eq` uses large elimination and declares the independently computed K bit. @@ -24,11 +24,11 @@ Thus the shared singleton-recursor relation is exercised at both universe layouts and at both values of the physical `k` field. -/ -namespace Ix.Tc.EliminationBreadthFixture +namespace Ix.Kernel.EliminationBreadthFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures local instance eliminationAddressDecidableEq : DecidableEq Address := AnonStructural.addressDecidableEq @@ -686,4 +686,4 @@ theorem kTargetAcceptance : KTargetAcceptance where productionLayout := eqPreparationMatches_eq productionK := eqComputeKMatches_eq -end Ix.Tc.EliminationBreadthFixture +end Ix.Kernel.EliminationBreadthFixture diff --git a/Ix/Tc/Verify/Inductive/EnumerationAcceptance.lean b/Ix/Kernel/Verify/Inductive/EnumerationAcceptance.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/EnumerationAcceptance.lean rename to Ix/Kernel/Verify/Inductive/EnumerationAcceptance.lean index fefada66f..23edafca0 100644 --- a/Ix/Tc/Verify/Inductive/EnumerationAcceptance.lean +++ b/Ix/Kernel/Verify/Inductive/EnumerationAcceptance.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.EnumerationFixture -import Ix.Tc.Verify.Inductive.OneFamilyAdmission +import Ix.Kernel.Verify.Inductive.EnumerationFixture +import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Concrete singleton-enumeration checker acceptance @@ -10,7 +10,7 @@ constructs its canonical recursor cache; the separate recursor block is then checked against that exact generated result. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace BooleanEnumerationFixture @@ -359,8 +359,8 @@ theorem familyOwner : directInductiveOwner_inductiveMemberOf familyDirectOwner private theorem certifiedConstructor_inductiveMemberOf - {source : Lean4Lean.VInductDecl} {familyId block : KId .anon} - {index : Nat} {sourceConstructor : Lean4Lean.VConstVal} + {source : Ix.Theory.Named.VInductDecl} {familyId block : KId .anon} + {index : Nat} {sourceConstructor : Ix.Theory.Named.VConstVal} {concrete familyConcrete : KConst .anon} {catalog : Catalog} (hshape : concrete.IsCertifiedSingletonConstructor source familyId index sourceConstructor) @@ -391,7 +391,7 @@ theorem recursorOwner : recursorOwnerNative private theorem certifiedRecursor_not_inductiveMemberOf - {source : Lean4Lean.VInductDecl} {generation : source.GenerationChecked} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {constructorIds : Array (KId .anon)} {concrete : KConst .anon} {catalog : Catalog} {block : KId .anon} (hshape : concrete.IsCertifiedSingletonRecursor source generation @@ -407,7 +407,7 @@ theorem recursorNotFamilyOwner : certifiedRecursor_not_inductiveMemberOf recursorShape private theorem certifiedFamily_not_recursorMemberOf - {source : Lean4Lean.VInductDecl} {generation : source.GenerationChecked} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {constructorIds : Array (KId .anon)} {concrete : KConst .anon} {block : KId .anon} (hshape : concrete.IsCertifiedSingletonFamily source generation @@ -423,8 +423,8 @@ theorem familyNotRecursorOwner : certifiedFamily_not_recursorMemberOf familyShape private theorem certifiedConstructor_not_recursorMemberOf - {source : Lean4Lean.VInductDecl} {familyId : KId .anon} - {index : Nat} {sourceConstructor : Lean4Lean.VConstVal} + {source : Ix.Theory.Named.VInductDecl} {familyId : KId .anon} + {index : Nat} {sourceConstructor : Ix.Theory.Named.VConstVal} {concrete : KConst .anon} {block : KId .anon} (hshape : concrete.IsCertifiedSingletonConstructor source familyId index sourceConstructor) : @@ -729,4 +729,4 @@ theorem endToEndAcceptance : EndToEndAcceptance where end BooleanEnumerationFixture -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/EnumerationFixture.lean b/Ix/Kernel/Verify/Inductive/EnumerationFixture.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/EnumerationFixture.lean rename to Ix/Kernel/Verify/Inductive/EnumerationFixture.lean index 641e2ef46..c02c71f8e 100644 --- a/Ix/Tc/Verify/Inductive/EnumerationFixture.lean +++ b/Ix/Kernel/Verify/Inductive/EnumerationFixture.lean @@ -1,22 +1,24 @@ -import Ix.Tc.Verify.Check.SingletonInductive -import Ix.Tc.Verify.Check.PreTranslationCompatibility -import Lean4Lean.Theory.InductiveFixtures +import Ix.Kernel.Verify.Check.SingletonInductive +import Ix.Kernel.Verify.Check.PreTranslationCompatibility +import Ix.Theory.Named.InductiveFixtures + +open Ix.Theory (VLevel) /-! # Concrete singleton-enumeration fixture This module closes E2b's executable witness with a two-constructor Boolean -enumeration. The Theory side uses Lean4Lean's checked identity-generation +enumeration. The Theory side uses Ix.Theory.Named's checked identity-generation certificate; the concrete side below is built from the actual Ixon block encoding and production anonymous ingress/checker functions. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace BooleanEnumerationFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open VInductDecl local instance anonKIdDecidableEq : DecidableEq (KId .anon) := fun left right => @@ -25,7 +27,7 @@ local instance anonKIdDecidableEq : DecidableEq (KId .anon) := fun left right => else .isFalse fun equality => h (by cases equality; exact beq_self_eq_true left) -/-! ## Lean4Lean certificate -/ +/-! ## Ix.Theory.Named certificate -/ def checked : boolDecl.Checked where type := boolType @@ -1275,4 +1277,4 @@ def recursorLink : SingletonRecursorCatalogLink RawProjRel.none world.catalog end BooleanEnumerationFixture -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/ExactLeanSyntax.lean b/Ix/Kernel/Verify/Inductive/ExactLeanSyntax.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/ExactLeanSyntax.lean rename to Ix/Kernel/Verify/Inductive/ExactLeanSyntax.lean index cd080cf0b..c7bfa00c3 100644 --- a/Ix/Tc/Verify/Inductive/ExactLeanSyntax.lean +++ b/Ix/Kernel/Verify/Inductive/ExactLeanSyntax.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.CandidateSyntax +import Ix.Kernel.Verify.Inductive.CandidateSyntax /-! # Exact executable comparison for Lean kernel syntax @@ -17,7 +17,7 @@ separate exact metadata relation. Every successful comparison is proved to imply ordinary Lean equality. -/ -namespace Ix.Tc.ExactLeanSyntax +namespace Ix.Kernel.ExactLeanSyntax /-- Structural equality for universe levels, ignoring their cached `data` field and comparing metavariable identifiers through their names. -/ @@ -214,4 +214,4 @@ theorem exceptBool_eq_ok_of_check {outcome : Except ε Bool} outcome = .ok expected := by cases outcome <;> simp_all [exceptBoolCheck] -end Ix.Tc.ExactLeanSyntax +end Ix.Kernel.ExactLeanSyntax diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorAcceptance.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptance.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorAcceptance.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptance.lean index 8dbaa86fb..91df67353 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorAcceptance.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptance.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorComparison -import Ix.Tc.Verify.RecursiveMethods.CallDomains +import Ix.Kernel.Verify.Inductive.GeneratedRecursorComparison +import Ix.Kernel.Verify.RecursiveMethods.CallDomains /-! # Semantic acceptance of a generated-recursor candidate @@ -15,9 +15,9 @@ entry yields a DefEq-quotiented canonical stored type and every same-index stored rule. No coherence-only or whole-comparison oracle is available. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VEnv VExpr VInductDecl) +open Ix.Theory.Named (VEnv VExpr VInductDecl) open GeneratedRecursorSemantics namespace GeneratedRecursorSemantics @@ -402,4 +402,4 @@ theorem checkGeneratedRecursorFromCache_canonical end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean index 034ac7560..78c4e2a5b 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorAcceptance -import Ix.Tc.Verify.Check.ScopedActiveBlock -import Ix.Tc.Verify.RecursiveMethods.ScopedCallDomains +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAcceptance +import Ix.Kernel.Verify.Check.ScopedActiveBlock +import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Run-scoped generated-recursor acceptance closure @@ -11,7 +11,7 @@ through K2S's finite successor-layer method contract. It does not require a global DefEq oracle or place every expression in an unbounded call domain. -/ -namespace Ix.Tc +namespace Ix.Kernel open GeneratedRecursorSemantics @@ -81,7 +81,7 @@ theorem checkGeneratedRecursorCandidate_canonicalScoped {model : ScopedKernelSuffixModel trProj world} {layer : WhnfLayer} {semantics : CacheSemantics} {support : RunSupport} {calls : Methods.CallDomain} - {source : Lean4Lean.VInductDecl} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {ty : KExpr .anon} {declaredLvls : UInt64} {declaredIsUnsafe : Bool} {params motives minors indices : UInt64} @@ -121,7 +121,7 @@ theorem checkGeneratedRecursorFromCache_canonicalScoped {model : ScopedKernelSuffixModel trProj world} {layer : WhnfLayer} {semantics : CacheSemantics} {support : RunSupport} {calls : Methods.CallDomain} - {source : Lean4Lean.VInductDecl} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {recBlock id : KId .anon} {ty : KExpr .anon} {declaredLvls : UInt64} {declaredIsUnsafe : Bool} @@ -171,7 +171,7 @@ theorem checkGeneratedRecursorCandidate_canonicalActiveScoped {layer : WhnfLayer} {semantics : CacheSemantics} {support : RunSupport} {members : Array (KId .anon)} {calls : Methods.CallDomain} - {source : Lean4Lean.VInductDecl} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {ty : KExpr .anon} {declaredLvls : UInt64} {declaredIsUnsafe : Bool} {params motives minors indices : UInt64} @@ -213,7 +213,7 @@ theorem checkGeneratedRecursorFromCache_canonicalActiveScoped {layer : WhnfLayer} {semantics : CacheSemantics} {support : RunSupport} {members : Array (KId .anon)} {calls : Methods.CallDomain} - {source : Lean4Lean.VInductDecl} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {recBlock id : KId .anon} {ty : KExpr .anon} {declaredLvls : UInt64} {declaredIsUnsafe : Bool} @@ -257,4 +257,4 @@ theorem checkGeneratedRecursorFromCache_canonicalActiveScoped end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorAdmission.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAdmission.lean similarity index 95% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorAdmission.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorAdmission.lean index 063556602..6709d5c35 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAdmission.lean @@ -1,12 +1,12 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorInitialInvariant -import Ix.Tc.Verify.Inductive.OneFamilyAdmission +import Ix.Kernel.Verify.Inductive.GeneratedRecursorInitialInvariant +import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Canonical generated-recursor admission This module closes the first E2c production recursor transaction. The certified family transaction has already installed `IndexedVec.rec` and its -two equations in Lean4Lean's Theory environment. Ix nevertheless keeps the +two equations in Ix.Theory.Named's Theory environment. Ix nevertheless keeps the separately ingressed recursor block untrusted while `checkRecursorMemberImpl` compares its immutable declaration against the generated cache. @@ -19,11 +19,11 @@ pattern, and only then converts active cache authority into stable trust and publishes the block-success verdict. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open IndexedRecursiveCertificateFixture /-! ## Per-member semantic provenance already present after family generation -/ @@ -209,4 +209,4 @@ theorem familyRecursorAtomicClosure : CanonicalRecursorAtomicClosure where oneFamily := oneFamilyAtomicClosure stable := familyMemberCheckStable -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorCheckerFixture.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorCheckerFixture.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorCheckerFixture.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorCheckerFixture.lean index cc4db09be..f6fcce8c8 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorCheckerFixture.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorCheckerFixture.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorSelection -import Ix.Tc.Verify.Inductive.GeneratedRecursorAcceptanceClosure -import Ix.Tc.Verify.Inductive.GeneratedRecursorCommitFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorSelection +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAcceptanceClosure +import Ix.Kernel.Verify.Inductive.GeneratedRecursorCommitFixture /-! # Production generated-recursor checker fixture @@ -15,11 +15,11 @@ Consequently, later semantic closure cannot justify the stored declaration by silently reusing the generated artifact's translation. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture open GeneratedRecursorSemantics open IndexedRecursiveCertificateFixture -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures /-! ## Actual frozen-cache checker execution -/ @@ -112,7 +112,7 @@ theorem familyStoredArtifactTranslations : transaction.certificate.generation.recursor.uvars nameOf RawProjRel.none recursorConcrete.ty recursorRules := by refine ⟨⟨transaction.certificate.generation.recType, ?_⟩, ?_⟩ - · simpa [Lean4Lean.VInductDecl.GenerationChecked.recursor] using + · simpa [Ix.Theory.Named.VInductDecl.GenerationChecked.recursor] using recursorTypeTyped · intro index hindex have indexTwo : index < 2 := by @@ -371,4 +371,4 @@ theorem familyCacheCheckExecution : ⟨familyCacheCheckRun, familyInstalledRecursorCanonical, familyStoredArtifactTranslations⟩ -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorCommitFixture.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorCommitFixture.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorCommitFixture.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorCommitFixture.lean index 9704834d3..e922291ff 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorCommitFixture.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorCommitFixture.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorRuleFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorRuleFixture /-! # Production generated-recursor commit fixture @@ -16,11 +16,11 @@ proofs do not need to trust either a callback-mutated cache type or a callback-written rule array. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture open GeneratedRecursorSemantics open IndexedRecursiveCertificateFixture -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures local instance generatedCommitAddressDecidableEq : DecidableEq Address := AnonStructural.addressDecidableEq @@ -257,7 +257,7 @@ theorem familyGeneratedSnapshotType_eq : familyGeneratedSnapshotTypeNative /-- The immutable type selected by the public commit is the exact -Lean4Lean-generated recursor type. -/ +Ix.Theory.Named-generated recursor type. -/ theorem familyGeneratedSnapshotTypeCanonical : CanonicalTypeS indexedVecFinalEnv nameOf RawProjRel.none transaction.certificate.generation @@ -268,7 +268,7 @@ theorem familyGeneratedSnapshotTypeCanonical : [] (familyGeneratedSnapshot[0]'familyGeneratedSnapshotNonempty).ty transaction.certificate.generation.recType rw [familyGeneratedSnapshotType_eq] - simpa [Lean4Lean.VInductDecl.GenerationChecked.recursor] using + simpa [Ix.Theory.Named.VInductDecl.GenerationChecked.recursor] using recursorTypeTyped /-- The local completed entry's position-zero rule array is canonical. -/ @@ -336,4 +336,4 @@ theorem familyRuleCommitExecution : installed[0] := ⟨familyRuleCommitRun, familyRuleCommitCanonical⟩ -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorComparison.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorComparison.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorComparison.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorComparison.lean index 49b7efd07..66cd7903a 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorComparison.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorComparison.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorSemantics +import Ix.Kernel.Verify.Inductive.GeneratedRecursorSemantics /-! # Exhaustive generated-recursor comparison @@ -15,7 +15,7 @@ semantic layer can interpret only these concrete successful DefEq calls; it does not receive an oracle for the comparison as a whole. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact successful executions of the positional generated/stored rule comparisons, including all state changes made by DefEq. -/ @@ -263,4 +263,4 @@ theorem checkGeneratedRecursorFromCache_success end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorInitialInvariant.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorInitialInvariant.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorInitialInvariant.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorInitialInvariant.lean index 0ba194afc..125320ce2 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorInitialInvariant.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorInitialInvariant.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorMemberFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorMemberFixture + +open Ix.Theory (VLevel) /-! # Concrete generated-recursor ingress invariant @@ -11,11 +13,11 @@ canonical finite maps; it does not assume injectivity of Blake3 outside that run. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open IndexedRecursiveCertificateFixture local instance initialInvariantKConstDecidableEq : @@ -294,37 +296,37 @@ private theorem familyMemberResolveExact private theorem familyMemberNatInfoLookup : familyAcceptedWorld.venv.constants ``Nat = - some Lean4Lean.InductiveFixtures.natType.toVConstant := by + some Ix.Theory.Named.InductiveFixtures.natType.toVConstant := by native_decide private theorem familyMemberZeroInfoLookup : familyAcceptedWorld.venv.constants ``Nat.zero = - some Lean4Lean.InductiveFixtures.natType.ctors[0].toVConstant := by + some Ix.Theory.Named.InductiveFixtures.natType.ctors[0].toVConstant := by native_decide private theorem familyMemberSuccInfoLookup : familyAcceptedWorld.venv.constants ``Nat.succ = - some Lean4Lean.InductiveFixtures.natType.ctors[1].toVConstant := by + some Ix.Theory.Named.InductiveFixtures.natType.ctors[1].toVConstant := by native_decide private theorem familyMemberFamilyInfoLookup : familyAcceptedWorld.venv.constants ``IndexedVec = - some Lean4Lean.InductiveFixtures.indexedVecType.toVConstant := by + some Ix.Theory.Named.InductiveFixtures.indexedVecType.toVConstant := by native_decide private theorem familyMemberNilInfoLookup : familyAcceptedWorld.venv.constants ``IndexedVec.nil = - some Lean4Lean.InductiveFixtures.indexedVecType.ctors[0].toVConstant := by + some Ix.Theory.Named.InductiveFixtures.indexedVecType.ctors[0].toVConstant := by native_decide private theorem familyMemberConsInfoLookup : familyAcceptedWorld.venv.constants ``IndexedVec.cons = - some Lean4Lean.InductiveFixtures.indexedVecType.ctors[1].toVConstant := by + some Ix.Theory.Named.InductiveFixtures.indexedVecType.ctors[1].toVConstant := by native_decide private theorem familyMemberResolveNatExact : TrustedConstRel RawProjRel.none familyAcceptedWorld natId natConcrete - ``Nat Lean4Lean.InductiveFixtures.natType.toVConstant := by + ``Nat Ix.Theory.Named.InductiveFixtures.natType.toVConstant := by apply familyMemberResolveExact familyMemberResolveNat · simpa only [familyAcceptedWorld_nameOf_eq] using nameOf_nat · exact familyMemberNatInfoLookup @@ -332,7 +334,7 @@ private theorem familyMemberResolveNatExact : private theorem familyMemberResolveZeroExact : TrustedConstRel RawProjRel.none familyAcceptedWorld zeroId zeroConcrete ``Nat.zero - Lean4Lean.InductiveFixtures.natType.ctors[0].toVConstant := by + Ix.Theory.Named.InductiveFixtures.natType.ctors[0].toVConstant := by apply familyMemberResolveExact familyMemberResolveZero · simpa only [familyAcceptedWorld_nameOf_eq] using nameOf_zero · exact familyMemberZeroInfoLookup @@ -340,7 +342,7 @@ private theorem familyMemberResolveZeroExact : private theorem familyMemberResolveSuccExact : TrustedConstRel RawProjRel.none familyAcceptedWorld succId succConcrete ``Nat.succ - Lean4Lean.InductiveFixtures.natType.ctors[1].toVConstant := by + Ix.Theory.Named.InductiveFixtures.natType.ctors[1].toVConstant := by apply familyMemberResolveExact familyMemberResolveSucc · simpa only [familyAcceptedWorld_nameOf_eq] using nameOf_succ · exact familyMemberSuccInfoLookup @@ -348,7 +350,7 @@ private theorem familyMemberResolveSuccExact : private theorem familyMemberResolveFamilyExact : TrustedConstRel RawProjRel.none familyAcceptedWorld familyId familyConcrete ``IndexedVec - Lean4Lean.InductiveFixtures.indexedVecType.toVConstant := by + Ix.Theory.Named.InductiveFixtures.indexedVecType.toVConstant := by apply familyMemberResolveExact familyMemberResolveFamily · simpa only [familyAcceptedWorld_nameOf_eq] using nameOf_family · exact familyMemberFamilyInfoLookup @@ -356,7 +358,7 @@ private theorem familyMemberResolveFamilyExact : private theorem familyMemberResolveNilExact : TrustedConstRel RawProjRel.none familyAcceptedWorld nilId nilConcrete ``IndexedVec.nil - Lean4Lean.InductiveFixtures.indexedVecType.ctors[0].toVConstant := by + Ix.Theory.Named.InductiveFixtures.indexedVecType.ctors[0].toVConstant := by apply familyMemberResolveExact familyMemberResolveNil · simpa only [familyAcceptedWorld_nameOf_eq] using nameOf_nil · exact familyMemberNilInfoLookup @@ -364,27 +366,27 @@ private theorem familyMemberResolveNilExact : private theorem familyMemberResolveConsExact : TrustedConstRel RawProjRel.none familyAcceptedWorld consId consConcrete ``IndexedVec.cons - Lean4Lean.InductiveFixtures.indexedVecType.ctors[1].toVConstant := by + Ix.Theory.Named.InductiveFixtures.indexedVecType.ctors[1].toVConstant := by apply familyMemberResolveExact familyMemberResolveCons · simpa only [familyAcceptedWorld_nameOf_eq] using nameOf_cons · exact familyMemberConsInfoLookup private theorem familyMemberNatTypeHasType : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] - Lean4Lean.InductiveFixtures.natType.type + Ix.Theory.Named.InductiveFixtures.natType.type (.sort (.succ (.succ .zero))) := by type_tac private theorem familyMemberZeroTypeHasType : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] - Lean4Lean.InductiveFixtures.natType.ctors[0].type - Lean4Lean.InductiveFixtures.natType.type := by + Ix.Theory.Named.InductiveFixtures.natType.ctors[0].type + Ix.Theory.Named.InductiveFixtures.natType.type := by have hNat := familyMemberNatInfoLookup type_tac private theorem familyMemberSuccTypeHasType : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] - Lean4Lean.InductiveFixtures.natType.ctors[1].type + Ix.Theory.Named.InductiveFixtures.natType.ctors[1].type (.sort (.succ .zero)) := by have raw : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] (.forallE (.const ``Nat []) (.const ``Nat [])) @@ -399,7 +401,7 @@ private theorem familyMemberSuccTypeHasType : private theorem familyMemberFamilyTypeHasType : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] - Lean4Lean.InductiveFixtures.indexedVecType.type + Ix.Theory.Named.InductiveFixtures.indexedVecType.type (.sort (.max (.succ .zero) (.succ (.succ (.param 0))))) := by have raw : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] (.forallE (.sort (.succ (.param 0))) @@ -418,7 +420,7 @@ private theorem familyMemberFamilyTypeHasType : private theorem familyMemberNilTypeHasType : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] - Lean4Lean.InductiveFixtures.indexedVecType.ctors[0].type + Ix.Theory.Named.InductiveFixtures.indexedVecType.ctors[0].type (.sort (.succ (.succ (.param 0)))) := by have raw : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] (.forallE (.sort (.succ (.param 0))) @@ -455,11 +457,11 @@ private theorem familyMemberNilTypeHasType : private theorem familyMemberConsTypeHasType : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] - Lean4Lean.InductiveFixtures.indexedVecType.ctors[1].type + Ix.Theory.Named.InductiveFixtures.indexedVecType.ctors[1].type (.sort (.max (.succ (.succ (.param 0))) (.max (.succ .zero) (.succ (.param 0))))) := by have raw : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] - Lean4Lean.InductiveFixtures.indexedVecType.ctors[1].type + Ix.Theory.Named.InductiveFixtures.indexedVecType.ctors[1].type (.sort (.imax (.succ (.succ (.param 0))) (.imax (.succ .zero) (.imax (.succ (.param 0)) @@ -1704,4 +1706,4 @@ theorem familyMemberCheckCanonicalConcrete : (fun _ support => familyMemberSupport_new support) familyMemberInitial_activeInvariant -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorMemberCheck.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberCheck.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorMemberCheck.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberCheck.lean index 5ff2c1550..bb6320dc7 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorMemberCheck.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberCheck.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorAcceptanceClosure -import Ix.Tc.Verify.Inductive.StructuralCacheSemantics -import Ix.Tc.Verify.Check.BlockIdentity -import Ix.Tc.Verify.Whnf.StructEta.ExactMajorTelescope +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAcceptanceClosure +import Ix.Kernel.Verify.Inductive.StructuralCacheSemantics +import Ix.Kernel.Verify.Check.BlockIdentity +import Ix.Kernel.Verify.Whnf.StructEta.ExactMajorTelescope /-! # Generated-recursor member-check handoff @@ -17,7 +17,7 @@ postulate that the prelude preserves the K2S invariant; subsequent modules must prove that from the individual production operations. -/ -namespace Ix.Tc +namespace Ix.Kernel open GeneratedRecursorSemantics @@ -939,7 +939,7 @@ theorem checkPreparedRecursorMember_canonicalScoped {model : ScopedKernelSuffixModel trProj world} {layer : WhnfLayer} {semantics : CacheSemantics} {support : RunSupport} {calls : Methods.CallDomain} - {source : Lean4Lean.VInductDecl} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {id : KId .anon} {prepared : PreparedRecursorMemberCheck .anon} {methods : Methods .anon} {initial final : TcState .anon} @@ -983,7 +983,7 @@ theorem checkPreparedRecursorMember_canonicalActiveScoped {layer : WhnfLayer} {semantics : CacheSemantics} {support : RunSupport} {members : Array (KId .anon)} {calls : Methods.CallDomain} - {source : Lean4Lean.VInductDecl} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {id : KId .anon} {prepared : PreparedRecursorMemberCheck .anon} {methods : Methods .anon} {initial final : TcState .anon} @@ -1024,4 +1024,4 @@ theorem checkPreparedRecursorMember_canonicalActiveScoped end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorMemberFixture.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberFixture.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorMemberFixture.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberFixture.lean index 8e50253b5..17324a966 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorMemberFixture.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberFixture.lean @@ -1,9 +1,9 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorCheckerFixture -import Ix.Tc.Verify.Inductive.GeneratedRecursorMemberCheck -import Ix.Tc.Verify.Inductive.IndexedBlockValidation -import Ix.Tc.Verify.Inductive.ResultSortTelescope -import Ix.Tc.Verify.RecursiveMethods.ScopedInference -import Ix.Tc.Verify.ScopedSuffix.ClosedContext +import Ix.Kernel.Verify.Inductive.GeneratedRecursorCheckerFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorMemberCheck +import Ix.Kernel.Verify.Inductive.IndexedBlockValidation +import Ix.Kernel.Verify.Inductive.ResultSortTelescope +import Ix.Kernel.Verify.RecursiveMethods.ScopedInference +import Ix.Kernel.Verify.ScopedSuffix.ClosedContext /-! # Production recursor-member preparation fixture @@ -20,12 +20,12 @@ separate operation-level preservation obligations; no whole-prelude oracle is introduced. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture open GeneratedRecursorSemantics open IndexedRecursiveCertificateFixture -open Lean4Lean -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveReplayFixtures local instance generatedMemberAddressDecidableEq : DecidableEq Address := AnonStructural.addressDecidableEq @@ -44,11 +44,11 @@ local instance generatedMemberKConstDecidableEq : DecidableEq (KConst .anon) := AnonStructural.constDecidableEq local instance generatedMemberVConstantDecidableEq : - DecidableEq Lean4Lean.VConstant := by + DecidableEq Ix.Theory.Named.VConstant := by intro left right cases left cases right - simp only [Lean4Lean.VConstant.mk.injEq] + simp only [Ix.Theory.Named.VConstant.mk.injEq] infer_instance local instance generatedMemberRecRuleDecidableEq : @@ -160,7 +160,7 @@ theorem familyMemberNatLit_type (value : Nat) : induction value with | zero => simpa [VExpr.natLit, VExpr.natZero, VExpr.nat, VExpr.instL] using - (Lean4Lean.VEnv.HasType.const + (Ix.Theory.Named.VEnv.HasType.const (env := familyAcceptedWorld.venv) (U := familyMemberModel.keys.uvars) (Γ := []) (ci := ⟨0, VExpr.nat⟩) (ls := []) familyNatZeroLookup @@ -169,11 +169,11 @@ theorem familyMemberNatLit_type (value : Nat) : have successor : familyAcceptedWorld.venv.HasType familyMemberModel.keys.uvars [] (.const ``Nat.succ []) (.forallE VExpr.nat VExpr.nat) := by - exact Lean4Lean.VEnv.HasType.const familyNatSuccLookup + exact Ix.Theory.Named.VEnv.HasType.const familyNatSuccLookup (by simp) rfl simpa [VExpr.natLit, VExpr.natSucc, VExpr.nat, VExpr.inst, VExpr.instL] using - Lean4Lean.VEnv.HasType.app successor ih + Ix.Theory.Named.VEnv.HasType.app successor ih /-- The complete literal/projection theory needed by the finite generated- artifact comparison schedule. String literals are impossible because the @@ -631,7 +631,7 @@ theorem familyMemberInitial_equivalences rw [familyMemberInitialEquivEntriesEmpty] at member simp at member -/-- Empty runtime stacks reconstruct the empty Lean4Lean local context even +/-- Empty runtime stacks reconstruct the empty Ix.Theory.Named local context even though the environment and its semantic caches are warm. -/ theorem familyMemberInitial_context : CtxRecon familyAcceptedWorld.venv familyMemberModel.keys.uvars @@ -2435,4 +2435,4 @@ theorem familyMemberCheckCanonicalFromInitialActiveScoped rw [familyMemberPreparationRun] at post exact familyPreparedMemberCheckCanonicalActiveScoped uvars successor post.1 -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorMetadata.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMetadata.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorMetadata.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorMetadata.lean index c873b366a..147e0d0eb 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorMetadata.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMetadata.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.NestedAuxiliaryExpansion -import Ix.Tc.Verify.Env +import Ix.Kernel.Verify.Inductive.NestedAuxiliaryExpansion +import Ix.Kernel.Verify.Env /-! # Generated recursor metadata from the certified flat block @@ -16,7 +16,7 @@ it makes no assumption about the expression returned by `buildRecType` or the state in which that callback succeeds. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace GeneratedRecursorMetadata @@ -634,4 +634,4 @@ theorem buildAndCacheGeneratedRecursors_metadata end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorRuleFixture.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorRuleFixture.lean similarity index 94% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorRuleFixture.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorRuleFixture.lean index da97d6f17..a4b5738c9 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorRuleFixture.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorRuleFixture.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorTypeFixture +import Ix.Kernel.Verify.Inductive.GeneratedRecursorTypeFixture /-! # Production generated-recursor rule fixture @@ -11,15 +11,15 @@ invokes `buildRuleRhs` for both constructors before returning its local batch. As with the type fixture, total projections have unreachable fallbacks. The public run theorem proves the successful data-bearing branch, and the final -theorem identifies every returned rule position with Lean4Lean's canonical +theorem identifies every returned rule position with Ix.Theory.Named's canonical normalized-constructor rule. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture open GeneratedRecursorSemantics open IndexedRecursiveCertificateFixture -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures local instance generatedRuleKIdDecidableEq : DecidableEq (KId .anon) := AnonStructural.idDecidableEq @@ -127,7 +127,7 @@ private theorem generationRuleCountNative : native_decide /-- The array returned by the actual complete-rule builder is positionally the -canonical Lean4Lean rule array for the certified IndexedVec generation. -/ +canonical Ix.Theory.Named rule array for the certified IndexedVec generation. -/ theorem familyBuildRulesCanonical : CanonicalRulesS indexedVecFinalEnv nameOf RawProjRel.none transaction.certificate.generation familyBuiltRules := by @@ -157,7 +157,7 @@ theorem familyCompletedTypeCanonical : transaction.certificate.generation familyCompletedRecursor := by unfold CanonicalTypeS rw [familyCompletedRecursorType_eq] - simpa [Lean4Lean.VInductDecl.GenerationChecked.recursor] using + simpa [Ix.Theory.Named.VInductDecl.GenerationChecked.recursor] using recursorTypeTyped /-- The actual local result of the rule-population core contains both the @@ -187,4 +187,4 @@ theorem familyBuildArtifactsExecution : transaction.certificate.generation familyCompletedRecursor := ⟨familyRulePopulationRun, familyCompletedArtifactsCanonical⟩ -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorSelection.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSelection.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorSelection.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorSelection.lean index 15d91f28e..9183b0c16 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorSelection.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSelection.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorAcceptance -import Ix.Tc.Verify.Check.ScopedActiveBlock -import Ix.Tc.Verify.RecursiveMethods.ScopedCallDomains +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAcceptance +import Ix.Kernel.Verify.Check.ScopedActiveBlock +import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Generated-recursor selection callbacks @@ -12,7 +12,7 @@ call is tied to the exact generated array position and the frozen stored type; metadata-only iterations are state-pure. -/ -namespace Ix.Tc +namespace Ix.Kernel open GeneratedRecursorSemantics @@ -30,7 +30,7 @@ def GeneratedSelectionCallPlan (calls : Methods.CallDomain) /-- Closed translations for the stored type and every generated type that the finite selection fold can reach. -/ structure GeneratedSelectionTranslationPlan - (env : Lean4Lean.VEnv) (uvars : Nat) + (env : Ix.Theory.Named.VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) (generated : Array (GeneratedRecursor .anon)) (ty : KExpr .anon) : Prop where @@ -291,4 +291,4 @@ theorem selectGeneratedRecursorIndex_preservesActiveScoped end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorSemantics.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSemantics.lean similarity index 94% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorSemantics.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorSemantics.lean index 79207e2c4..90a3e53e1 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorSemantics.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSemantics.lean @@ -1,13 +1,13 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorMetadata -import Ix.Tc.Verify.Trans +import Ix.Kernel.Verify.Inductive.GeneratedRecursorMetadata +import Ix.Kernel.Verify.Trans /-! # Canonical semantics of generated recursor artifacts This is the representation boundary for E2c's generated artifacts. It names the exact structural correspondence that the production builders must prove: -the generated type is Lean4Lean's `GenerationChecked.recType`, and rule `i` -is Lean4Lean's `GenerationChecked.rule i` for constructor `i`. Rule lookup is +the generated type is Ix.Theory.Named's `GenerationChecked.recType`, and rule `i` +is Ix.Theory.Named's `GenerationChecked.rule i` for constructor `i`. Rule lookup is positional; equal bodies at a different index are not interchangeable. Types and rules are deliberately separate. The public production commit @@ -16,14 +16,14 @@ local builder. `commitGeneratedRecursorRulesAt_canonicalAt` proves that these two independently established facts compose across that exact transaction. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VEnv VExpr VInductDecl) +open Ix.Theory.Named (VEnv VExpr VInductDecl) namespace GeneratedRecursorSemantics /-- Exact structural correspondence between one immutable Ix generated type -and Lean4Lean's canonical mixed recursor type. -/ +and Ix.Theory.Named's canonical mixed recursor type. -/ def CanonicalTypeS (env : VEnv) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) {source : VInductDecl} (generation : source.GenerationChecked) @@ -32,7 +32,7 @@ def CanonicalTypeS (env : VEnv) (nameOf : Address → Option Lean.Name) generation.recType /-- Exact positional correspondence between one Ix rule array and all rules -generated by the same Lean4Lean generation. -/ +generated by the same Ix.Theory.Named generation. -/ structure CanonicalRulesS (env : VEnv) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) {source : VInductDecl} (generation : source.GenerationChecked) @@ -58,7 +58,7 @@ structure CanonicalArtifactsS (env : VEnv) namespace CanonicalRulesS /-- A positional Ix rule corresponds to the rule at the same position in -Lean4Lean's public `generatedRules` array. -/ +Ix.Theory.Named's public `generatedRules` array. -/ theorem generatedRuleAt {env : VEnv} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {source : VInductDecl} @@ -104,7 +104,7 @@ end CanonicalArtifactsS /-! ## Defeq-quotiented form consumed by recursor acceptance -/ /-- Semantic type correspondence after quotienting the structural target by -Lean4Lean definitional equality. Stored recursors accepted by production need +Ix.Theory.Named definitional equality. Stored recursors accepted by production need this form: `isDefEq` does not imply syntax equality. -/ def CanonicalType (env : VEnv) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) {source : VInductDecl} @@ -240,4 +240,4 @@ theorem RecM.commitGeneratedRecursorRulesAt_canonicalAt end GeneratedRecursorSemantics -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorTypeClosure.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorTypeClosure.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorTypeClosure.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorTypeClosure.lean index f072f0be9..750eff66d 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorTypeClosure.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorTypeClosure.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorSemantics -import Ix.Tc.Verify.Whnf +import Ix.Kernel.Verify.Inductive.GeneratedRecursorSemantics +import Ix.Kernel.Verify.Whnf + +open Ix.Theory (VLevel) /-! # Generated recursor telescope closure @@ -12,7 +14,7 @@ obtained. The proof has two deliberately separate parts: -* `closeK`/`closeV` are the exact Ix and Lean4Lean reverse closures; +* `closeK`/`closeV` are the exact Ix and Ix.Theory.Named reverse closures; * `TelescopeS` records each domain at the context in which production built it, rather than assuming a relation for the already-closed result. @@ -21,9 +23,9 @@ intern request. Thus hash-consing cannot silently replace a generated forall with a colliding expression. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VEnv VExpr VInductDecl VLevel VLocalDecl) +open Ix.Theory.Named (VEnv VExpr VInductDecl VLocalDecl) namespace GeneratedRecursorTypeClosure @@ -34,13 +36,13 @@ def closeK (domains : Array (KExpr .anon)) : Nat → KExpr .anon → KExpr .anon closeK domains remaining (.mkAll RecM.anonN RecM.anonBi domains[remaining]! body) -/-- Lean4Lean-side closure with the same array positions and order. -/ +/-- Ix.Theory.Named-side closure with the same array positions and order. -/ def closeV (domains : Array VExpr) : Nat → VExpr → VExpr | 0, body => body | remaining + 1, body => closeV domains remaining (.forallE domains[remaining]! body) -/-- The flattened target domain list used by Lean4Lean's canonical mixed +/-- The flattened target domain list used by Ix.Theory.Named's canonical mixed recursor type. -/ def canonicalMajorDomain {source : VInductDecl} (generation : source.GenerationChecked) : VExpr := @@ -91,7 +93,7 @@ theorem closeV_eq_forallN_take (domains : Array VExpr) (count : Nat) simp only [Option.toList_some, VExpr.forallN_append, VExpr.forallN, getElem!_def, hindex, Array.getElem?_eq_getElem] -/-- Closing the whole canonical flattened telescope is exactly Lean4Lean's +/-- Closing the whole canonical flattened telescope is exactly Ix.Theory.Named's public mixed recursor type, not merely a definitionally equal variant. -/ theorem closeV_canonical {source : VInductDecl} (generation : source.GenerationChecked) : @@ -133,7 +135,7 @@ theorem opened_toCtx (base : KVLCtx) (domains : Array VExpr) (count : Nat) Array.getElem?_eq_getElem, List.reverse_append, List.reverse_singleton, List.cons_append, List.nil_append] -/-- Inversion for a well-formed iterated forall. Lean4Lean provides the +/-- Inversion for a well-formed iterated forall. Ix.Theory.Named provides the constructor theorem `IsType.forallN`; the converse is what lets the production builder consume the canonical result type one open domain at a time. -/ theorem isType_forallN_inv @@ -146,7 +148,7 @@ theorem isType_forallN_inv | nil => exact ⟨trivial, h⟩ | cons domain domains ih => obtain ⟨hdomain, hrest⟩ := - Lean4Lean.VEnv.IsType.forallE_inv henv h + Ix.Theory.Named.VEnv.IsType.forallE_inv henv h obtain ⟨htelescope, hbody⟩ := ih hrest exact ⟨⟨hdomain, htelescope⟩, by simpa [List.reverse_cons, List.append_assoc] using hbody⟩ @@ -170,7 +172,7 @@ theorem onTel_isType_getElem simpa [List.take, List.reverse_cons, List.append_assoc] using ih hrest index htail -/-- Lean4Lean's semantic generation invariant decomposes into precisely the +/-- Ix.Theory.Named's semantic generation invariant decomposes into precisely the flattened target telescope and open body used by the production builder. -/ theorem canonical_onTel_and_bodyType {source : VInductDecl} {generation : source.GenerationChecked} @@ -252,7 +254,7 @@ namespace TelescopeS /-- Construct the operation-shaped telescope from only the Ix-to-target relations produced by the live builder. All target typing fields are recovered -from Lean4Lean's generation invariant. -/ +from Ix.Theory.Named's generation invariant. -/ theorem of_canonical {source : VInductDecl} {generation : source.GenerationChecked} {env : VEnv} @@ -330,7 +332,7 @@ theorem close have hclosedBodyType : env.IsType uvars (opened base targetDomains count).toCtx targetBody' := - Lean4Lean.VEnv.IsType.forallE hdomainType hbodyType + Ix.Theory.Named.VEnv.IsType.forallE hdomainType hbodyType have hprefix : TelescopeS env uvars nameOf trProj base ixDomains targetDomains count ixBody' targetBody' := { ixBound := by omega @@ -521,7 +523,7 @@ structure CanonicalBodyS (support : RunSupport) (env : VEnv) /-- Once the actual domain/body run establishes its operation-shaped postcondition, the real `buildRecType` execution returns a structurally -canonical Lean4Lean recursor type. This theorem closes all control-flow and +canonical Ix.Theory.Named recursor type. This theorem closes all control-flow and hash-consing obligations after that body boundary. -/ theorem buildRecType_canonical_of_body {support : RunSupport} (hcollision : support.CollisionFree) @@ -554,4 +556,4 @@ theorem buildRecType_canonical_of_body end GeneratedRecursorTypeClosure -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/GeneratedRecursorTypeFixture.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorTypeFixture.lean similarity index 92% rename from Ix/Tc/Verify/Inductive/GeneratedRecursorTypeFixture.lean rename to Ix/Kernel/Verify/Inductive/GeneratedRecursorTypeFixture.lean index 3e6d55d85..7411db576 100644 --- a/Ix/Tc/Verify/Inductive/GeneratedRecursorTypeFixture.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorTypeFixture.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorTypeClosure -import Ix.Tc.Verify.Inductive.IndexedRecursiveAcceptance -import Ix.Tc.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Inductive.GeneratedRecursorTypeClosure +import Ix.Kernel.Verify.Inductive.IndexedRecursiveAcceptance +import Ix.Kernel.Verify.Ingress.AnonStructural /-! # Production generated-recursor type fixture @@ -14,15 +14,15 @@ production helpers. The fallback values only make the projections total. The public run theorems prove that neither fallback is taken, and the final theorem relates -the expression returned by that exact execution to Lean4Lean's canonical +the expression returned by that exact execution to Ix.Theory.Named's canonical mixed recursor type. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture open GeneratedRecursorSemantics open IndexedRecursiveCertificateFixture -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures local instance generatedTypeKIdDecidableEq : DecidableEq (KId .anon) := AnonStructural.idDecidableEq @@ -163,7 +163,7 @@ def familyBuiltRecursor : GeneratedRecursor .anon := familyBuildTypeResult /-- The type produced by the concrete `buildRecType` execution is the exact -structural translation of Lean4Lean's canonical `IndexedVec` recursor type. -/ +structural translation of Ix.Theory.Named's canonical `IndexedVec` recursor type. -/ theorem familyBuildTypeCanonical : CanonicalTypeS indexedVecFinalEnv nameOf RawProjRel.none transaction.certificate.generation familyBuiltRecursor := by @@ -172,7 +172,7 @@ theorem familyBuildTypeCanonical : transaction.certificate.generation.recursor.uvars nameOf RawProjRel.none [] familyBuildTypeResult transaction.certificate.generation.recType rw [familyBuildTypeResult_eq] - simpa [Lean4Lean.VInductDecl.GenerationChecked.recursor] using + simpa [Ix.Theory.Named.VInductDecl.GenerationChecked.recursor] using recursorTypeTyped /-- One data-bearing theorem packages the production execution and its exact @@ -192,4 +192,4 @@ theorem familyBuildTypeExecution : simpa [familyBuiltRecursor, RecM.initialGeneratedRecursor] using familyBuildTypeRun -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedBlockValidation.lean b/Ix/Kernel/Verify/Inductive/IndexedBlockValidation.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/IndexedBlockValidation.lean rename to Ix/Kernel/Verify/Inductive/IndexedBlockValidation.lean index 4c810a83a..32a6ecdc0 100644 --- a/Ix/Tc/Verify/Inductive/IndexedBlockValidation.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedBlockValidation.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.ConstructorValidationTraversal -import Ix.Tc.Verify.Inductive.IndexedRecursiveAcceptance -import Ix.Tc.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Inductive.ConstructorValidationTraversal +import Ix.Kernel.Verify.Inductive.IndexedRecursiveAcceptance +import Ix.Kernel.Verify.Ingress.AnonStructural /-! # IndexedVec production block-validation trace @@ -13,7 +13,7 @@ header, constructor order, and safety-gated positivity executions reached by that one block run. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture local instance blockValidationIdDecidableEq : DecidableEq (KId .anon) := AnonStructural.idDecidableEq @@ -471,4 +471,4 @@ theorem indexedVecConsProductionPositivityTrace : exact ⟨indLevel, _, _, _, _, _, _, _, _, metadata, parameters, run, trace, universes, returnType⟩ -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedCandidateOperations.lean b/Ix/Kernel/Verify/Inductive/IndexedCandidateOperations.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/IndexedCandidateOperations.lean rename to Ix/Kernel/Verify/Inductive/IndexedCandidateOperations.lean index aa5d2e96e..823ac328c 100644 --- a/Ix/Tc/Verify/Inductive/IndexedCandidateOperations.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedCandidateOperations.lean @@ -1,19 +1,19 @@ -import Ix.Tc.Verify.Inductive.IndexedCandidateSyntax -import Ix.Tc.Verify.Inductive.IndexedRecursiveAcceptance +import Ix.Kernel.Verify.Inductive.IndexedCandidateSyntax +import Ix.Kernel.Verify.Inductive.IndexedRecursiveAcceptance /-! # IndexedVec candidate operations The closed syntax relation is not enough once constructor validation opens its telescope. This module follows the same anonymous binder instantiation used -by `TcM.openBinderAnon`, pairs each minted Ix identifier with Lean4Lean's +by `TcM.openBinderAnon`, pairs each minted Ix identifier with Ix.Theory.Named's corresponding validation identifier, and checks the three actual `cons` field domains at which positivity is invoked. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures /-- Domain projection used only after a separately checked constructor shape. Returning the source in the impossible fallback keeps the definition total. -/ @@ -430,4 +430,4 @@ theorem tailDomainCandidateSyntax : indexedVecConstructorNExpr) := CandidateSyntax.rel_of_check tailDomainCandidateCheckNative -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedCandidateSyntax.lean b/Ix/Kernel/Verify/Inductive/IndexedCandidateSyntax.lean similarity index 81% rename from Ix/Tc/Verify/Inductive/IndexedCandidateSyntax.lean rename to Ix/Kernel/Verify/Inductive/IndexedCandidateSyntax.lean index d8810062b..3629e913a 100644 --- a/Ix/Tc/Verify/Inductive/IndexedCandidateSyntax.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedCandidateSyntax.lean @@ -1,23 +1,23 @@ -import Ix.Tc.Verify.Inductive.CandidateSyntax -import Ix.Tc.Verify.Inductive.IndexedRecursiveFixture -import Lean4Lean.Verify.Environment.IndexedVecOuterReplay +import Ix.Kernel.Verify.Inductive.CandidateSyntax +import Ix.Kernel.Verify.Inductive.IndexedRecursiveFixture +import Ix.Theory.Named.Verify.Environment.IndexedVecOuterReplay /-! # Exact IndexedVec candidate syntax This module connects the actual anonymous expressions produced by Ix ingress -to the exact Lean kernel expressions consumed by Lean4Lean's constructor +to the exact Lean kernel expressions consumed by Ix.Theory.Named's constructor validator. The relation is deliberately syntactic: positivity occurrence and `isValidIndApp?` inspect the candidate expression rather than its Theory denotation. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean.InductiveReplayFixtures -open Lean4Lean.InductiveReplayFixtures.IndexedVecConsReplay +open Ix.Theory.Named.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures.IndexedVecConsReplay -/-! ## Proof-independent Lean4Lean validation fixture +/-! ## Proof-independent Ix.Theory.Named validation fixture The upstream replay exposes the right executable values, but its public `indexedVecCtorValidationContext` is projected out of a proof-bearing family @@ -30,7 +30,7 @@ data. These are the values E2c relates to production Ix execution. /-- Post-family context in which the two IndexedVec constructors are checked. It has the validated parameter/index local context and the staged environment containing the family constant, without retaining an upstream replay proof. -/ -def indexedVecConstructorContext : Lean4Lean.AddInductive.Context := +def indexedVecConstructorContext : Ix.Theory.Named.AddInductive.Context := { indexedVecValidationFamilyContext with env := ctorEnv } def indexedVecConstructorAlpha : Lean.Expr := @@ -45,18 +45,18 @@ def indexedVecConstructorNId : Lean.FVarId := def indexedVecConstructorNExpr : Lean.Expr := indexedVecConstructorContext.freshExpr -def indexedVecConstructorNContext : Lean4Lean.AddInductive.Context := +def indexedVecConstructorNContext : Ix.Theory.Named.AddInductive.Context := indexedVecConstructorContext.pushLocalDecl consNName .implicit (.const ``Nat []) def indexedVecConstructorHeadId : Lean.FVarId := indexedVecConstructorNContext.freshFVarId -def indexedVecConstructorHeadContext : Lean4Lean.AddInductive.Context := +def indexedVecConstructorHeadContext : Ix.Theory.Named.AddInductive.Context := indexedVecConstructorNContext.pushLocalDecl consHeadName .default indexedVecConstructorAlpha -def indexedVecConstructorTailContext : Lean4Lean.AddInductive.Context := +def indexedVecConstructorTailContext : Ix.Theory.Named.AddInductive.Context := indexedVecConstructorHeadContext.pushLocalDecl consTailName .default (ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr) @@ -65,13 +65,13 @@ def indexedVecConstructorTailContext : Lean4Lean.AddInductive.Context := one-index family spine. Writing the finite record directly prevents the statement from retaining `CandidateExprTrace.singletonCandidateInductiveStats` through an upstream proof object. -/ -def indexedVecConstructorStats : Lean4Lean.AddInductive.InductiveStats where +def indexedVecConstructorStats : Ix.Theory.Named.AddInductive.InductiveStats where lctx := indexedVecConstructorContext.lctx levels := [.param `u] resultLevel := .succ (.param `u) nindices := #[1] indConsts := - #[.const ``Lean4Lean.InductiveFixtures.IndexedVec [.param `u]] + #[.const ``Ix.Theory.Named.InductiveFixtures.IndexedVec [.param `u]] params := #[indexedVecConstructorAlpha] isNotZero := true @@ -120,7 +120,7 @@ private theorem consCandidateCheckNative : native_decide /-- The family type selected by production anonymous ingress is exactly the -Lean4Lean IndexedVec family candidate, modulo irrelevant binder metadata. -/ +Ix.Theory.Named IndexedVec family candidate, modulo irrelevant binder metadata. -/ theorem familyCandidateSyntax : CandidateSyntaxRel nameOf (fun ixId leanId => closedFVarMatches ixId leanId = true) @@ -130,7 +130,7 @@ theorem familyCandidateSyntax : CandidateSyntax.rel_of_check familyCandidateCheckNative /-- The ingressed nil constructor type is the exact candidate validated by -Lean4Lean. -/ +Ix.Theory.Named. -/ theorem nilCandidateSyntax : CandidateSyntaxRel nameOf (fun ixId leanId => closedFVarMatches ixId leanId = true) @@ -140,7 +140,7 @@ theorem nilCandidateSyntax : CandidateSyntax.rel_of_check nilCandidateCheckNative /-- The ingressed cons constructor type is the exact candidate validated by -Lean4Lean, including its recursive family application and changing index. -/ +Ix.Theory.Named, including its recursive family application and changing index. -/ theorem consCandidateSyntax : CandidateSyntaxRel nameOf (fun ixId leanId => closedFVarMatches ixId leanId = true) @@ -153,7 +153,7 @@ private theorem candidateBlockSyntaxNative : CandidateBlockRel nameOf #[familyId.addr] indexedVecConstructorStats.indConsts := by rw [show indexedVecConstructorStats.indConsts = - #[.const ``Lean4Lean.InductiveFixtures.IndexedVec [.param `u]] by rfl] + #[.const ``Ix.Theory.Named.InductiveFixtures.IndexedVec [.param `u]] by rfl] intro id leanName hname unfold nameOf at hname repeat' split at hname @@ -161,7 +161,7 @@ private theorem candidateBlockSyntaxNative : all_goals subst_vars all_goals native_decide -/-- The physical singleton-family address and Lean4Lean's singleton constant +/-- The physical singleton-family address and Ix.Theory.Named's singleton constant array make the same occurrence decision. The proof analyzes the concrete ingress name map, so it assumes neither address nor name injectivity. -/ theorem candidateBlockSyntax : @@ -169,4 +169,4 @@ theorem candidateBlockSyntax : indexedVecConstructorStats.indConsts := candidateBlockSyntaxNative -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedCandidateTransaction.lean b/Ix/Kernel/Verify/Inductive/IndexedCandidateTransaction.lean similarity index 78% rename from Ix/Tc/Verify/Inductive/IndexedCandidateTransaction.lean rename to Ix/Kernel/Verify/Inductive/IndexedCandidateTransaction.lean index b6ac31279..75bfda340 100644 --- a/Ix/Tc/Verify/Inductive/IndexedCandidateTransaction.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedCandidateTransaction.lean @@ -1,25 +1,25 @@ -import Ix.Tc.Verify.Inductive.IndexedRecursiveCertificate -import Ix.Tc.Verify.Inductive.ProducedGenerationTransaction -import Lean4Lean.Verify.Environment.IndexedVecSemanticReplay +import Ix.Kernel.Verify.Inductive.IndexedRecursiveCertificate +import Ix.Kernel.Verify.Inductive.ProducedGenerationTransaction +import Ix.Theory.Named.Verify.Environment.IndexedVecSemanticReplay /-! # Producer-linked IndexedVec generation transaction The existing `IndexedVec` certificate is deliberately reconstructed through the Theory-only API so its semantic roots keep a minimal trust footprint. -Lean4Lean also exposes the exact ordinary metadata producer and dependent +Ix.Theory.Named also exposes the exact ordinary metadata producer and dependent semantic package for that same generation. This module proves those two paths meet, without making the producer replay a dependency of the clean Theory-only transaction. -/ -namespace Ix.Tc.IndexedRecursiveCertificateFixture +namespace Ix.Kernel.IndexedRecursiveCertificateFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures -/-- The L4L-01E package retains the exact source declaration and checked +/-- The Spec-01E package retains the exact source declaration and checked generation selected by the ordinary metadata producer. -/ noncomputable def exactPackage : VInductDecl.ExactProducedGenerationCandidatePackage natFinalEnv [`u] @@ -45,7 +45,7 @@ noncomputable def exactProducedTransaction : exact indexedVecSemantic_addInductCertified beforeWF := natWF -/-- Intentional operational erasure of the exact L4L-01E indices. -/ +/-- Intentional operational erasure of the exact Spec-01E indices. -/ noncomputable def producedTransaction : ProducedGenerationTransaction natFinalEnv indexedVecFinalEnv [`u] := exactProducedTransaction.toProduced @@ -66,4 +66,4 @@ before erasure. -/ theorem producerLinkedFacts : producedTransaction.Facts := producedTransaction.facts -end Ix.Tc.IndexedRecursiveCertificateFixture +end Ix.Kernel.IndexedRecursiveCertificateFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedConstructorPositivity.lean b/Ix/Kernel/Verify/Inductive/IndexedConstructorPositivity.lean similarity index 91% rename from Ix/Tc/Verify/Inductive/IndexedConstructorPositivity.lean rename to Ix/Kernel/Verify/Inductive/IndexedConstructorPositivity.lean index 53c4c38a9..84b75ce6a 100644 --- a/Ix/Tc/Verify/Inductive/IndexedConstructorPositivity.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedConstructorPositivity.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.ConstructorPositivityTraversal -import Ix.Tc.Verify.Inductive.IndexedPositivityTransport +import Ix.Kernel.Verify.Inductive.ConstructorPositivityTraversal +import Ix.Kernel.Verify.Inductive.IndexedPositivityTransport /-! # IndexedVec enclosing constructor-positivity execution @@ -15,7 +15,7 @@ also records the shared-parameter opening, source-ordered bounded field loop, and public local-context restoration performed by production. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture /-- Exact result of running production strict positivity on the ingressed `IndexedVec.cons` declaration. -/ @@ -57,4 +57,4 @@ theorem indexedVecConsIxPositivityTrace : checkerMethods checkerInitial ixConsPositivityAfter := RecM.checkPositivity_success checkerMethods ixConsPositivityRun -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedConstructorValidation.lean b/Ix/Kernel/Verify/Inductive/IndexedConstructorValidation.lean similarity index 85% rename from Ix/Tc/Verify/Inductive/IndexedConstructorValidation.lean rename to Ix/Kernel/Verify/Inductive/IndexedConstructorValidation.lean index 530ad3a1c..cde7de964 100644 --- a/Ix/Tc/Verify/Inductive/IndexedConstructorValidation.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedConstructorValidation.lean @@ -1,24 +1,24 @@ -import Ix.Tc.Verify.Inductive.IndexedPositivityTransport +import Ix.Kernel.Verify.Inductive.IndexedPositivityTransport /-! # IndexedVec constructor-validation trace This module places the three production-derived positivity artifacts back into -Lean4Lean's complete retained constructor telescope. The resulting trace +Ix.Theory.Named's complete retained constructor telescope. The resulting trace records the shared parameter check, all ordinary field type/universe checks, the transported positivity evidence, and the terminal indexed-family application. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean.InductiveReplayFixtures -open Lean4Lean.InductiveReplayFixtures.IndexedVecConsReplay +open Ix.Theory.Named.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures.IndexedVecConsReplay private abbrev ConsValidationTrace - (context : Lean4Lean.AddInductive.Context) (source : Lean.Expr) + (context : Ix.Theory.Named.AddInductive.Context) (source : Lean.Expr) (argIdx fuel : Nat) := - Lean4Lean.AddInductive.ConstructorTypeValidationTrace + Ix.Theory.Named.AddInductive.ConstructorTypeValidationTrace indexedVecConstructorStats false 0 indexedVecKernelCons.name context source argIdx fuel @@ -26,13 +26,13 @@ private abbrev ConsValidationTrace private theorem indexedVecConstructorGetTypeAlphaNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.AddInductive.getType indexedVecConstructorAlpha + (Ix.Theory.Named.AddInductive.getType indexedVecConstructorAlpha indexedVecConstructorContext) (.sort (.succ (.param `u))) = true := by native_decide private theorem indexedVecConstructorGetTypeAlpha : - Lean4Lean.AddInductive.getType indexedVecConstructorAlpha + Ix.Theory.Named.AddInductive.getType indexedVecConstructorAlpha indexedVecConstructorContext = .ok (.sort (.succ (.param `u))) := ExactLeanSyntax.exceptExpr_eq_ok_of_check @@ -40,116 +40,116 @@ private theorem indexedVecConstructorGetTypeAlpha : private theorem indexedVecConstructorParamIsDefEqNative : ExactLeanSyntax.exceptBoolCheck - (Lean4Lean.TypeChecker.M.run indexedVecConstructorContext.env + (Ix.Theory.Named.TypeChecker.M.run indexedVecConstructorContext.env indexedVecConstructorContext.safety indexedVecConstructorContext.lctx indexedVecConstructorContext.lparams indexedVecConstructorContext.fuel - (Lean4Lean.TypeChecker.isDefEq + (Ix.Theory.Named.TypeChecker.isDefEq (.sort (.succ (.param `u))) (.sort (.succ (.param `u))))) true = true := by native_decide private theorem indexedVecConstructorParamIsDefEq : - Lean4Lean.AddInductive.CandidateIsDefEqStep.Valid + Ix.Theory.Named.AddInductive.CandidateIsDefEqStep.Valid ⟨indexedVecConstructorContext, .sort (.succ (.param `u)), .sort (.succ (.param `u))⟩ := by - unfold Lean4Lean.AddInductive.CandidateIsDefEqStep.Valid + unfold Ix.Theory.Named.AddInductive.CandidateIsDefEqStep.Valid exact ExactLeanSyntax.exceptBool_eq_ok_of_check indexedVecConstructorParamIsDefEqNative private theorem indexedVecConstructorNatEnsureTypeNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run indexedVecConstructorContext.env + (Ix.Theory.Named.TypeChecker.M.run indexedVecConstructorContext.env indexedVecConstructorContext.safety indexedVecConstructorContext.lctx indexedVecConstructorContext.lparams indexedVecConstructorContext.fuel - (Lean4Lean.TypeChecker.ensureType (.const ``Nat []))) + (Ix.Theory.Named.TypeChecker.ensureType (.const ``Nat []))) (.sort (.succ .zero)) = true := by native_decide private theorem indexedVecConstructorNatEnsureType : - Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid ⟨indexedVecConstructorContext, .const ``Nat [], .sort (.succ .zero)⟩ := by - unfold Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + unfold Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check indexedVecConstructorNatEnsureTypeNative private theorem indexedVecConstructorAlphaEnsureTypeNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run indexedVecConstructorNContext.env + (Ix.Theory.Named.TypeChecker.M.run indexedVecConstructorNContext.env indexedVecConstructorNContext.safety indexedVecConstructorNContext.lctx indexedVecConstructorNContext.lparams indexedVecConstructorNContext.fuel - (Lean4Lean.TypeChecker.ensureType indexedVecConstructorAlpha)) + (Ix.Theory.Named.TypeChecker.ensureType indexedVecConstructorAlpha)) (.sort (.succ (.param `u))) = true := by native_decide private theorem indexedVecConstructorAlphaEnsureType : - Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid ⟨indexedVecConstructorNContext, indexedVecConstructorAlpha, .sort (.succ (.param `u))⟩ := by - unfold Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + unfold Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check indexedVecConstructorAlphaEnsureTypeNative private theorem indexedVecConstructorTailEnsureTypeNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run indexedVecConstructorHeadContext.env + (Ix.Theory.Named.TypeChecker.M.run indexedVecConstructorHeadContext.env indexedVecConstructorHeadContext.safety indexedVecConstructorHeadContext.lctx indexedVecConstructorHeadContext.lparams indexedVecConstructorHeadContext.fuel - (Lean4Lean.TypeChecker.ensureType + (Ix.Theory.Named.TypeChecker.ensureType (ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr))) (.sort (.succ (.param `u))) = true := by native_decide private theorem indexedVecConstructorTailEnsureType : - Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid ⟨indexedVecConstructorHeadContext, ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr, .sort (.succ (.param `u))⟩ := by - unfold Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + unfold Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check indexedVecConstructorTailEnsureTypeNative private theorem indexedVecConstructorResultIsValidNative : - Lean4Lean.AddInductive.isValidIndAppIdx indexedVecConstructorStats + Ix.Theory.Named.AddInductive.isValidIndAppIdx indexedVecConstructorStats indexedVecConstructorResult 0 = true := by native_decide private theorem indexedVecConstructorConsumeNatNative : ExactLeanSyntax.exprCheck - (Lean4Lean.AddInductive.consumeTypeAnnotations (.const ``Nat [])) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations (.const ``Nat [])) (.const ``Nat []) = true := by native_decide private theorem indexedVecConstructorConsumeNat : - Lean4Lean.AddInductive.consumeTypeAnnotations (.const ``Nat []) = + Ix.Theory.Named.AddInductive.consumeTypeAnnotations (.const ``Nat []) = .const ``Nat [] := ExactLeanSyntax.expr_eq_of_check indexedVecConstructorConsumeNatNative private theorem indexedVecConstructorConsumeAlphaNative : ExactLeanSyntax.exprCheck - (Lean4Lean.AddInductive.consumeTypeAnnotations + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations indexedVecConstructorAlpha) indexedVecConstructorAlpha = true := by native_decide private theorem indexedVecConstructorConsumeAlpha : - Lean4Lean.AddInductive.consumeTypeAnnotations + Ix.Theory.Named.AddInductive.consumeTypeAnnotations indexedVecConstructorAlpha = indexedVecConstructorAlpha := ExactLeanSyntax.expr_eq_of_check indexedVecConstructorConsumeAlphaNative private theorem indexedVecConstructorConsumeTailNative : ExactLeanSyntax.exprCheck - (Lean4Lean.AddInductive.consumeTypeAnnotations + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations (ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr)) (ctorIndexedVecApp indexedVecConstructorAlpha @@ -157,7 +157,7 @@ private theorem indexedVecConstructorConsumeTailNative : native_decide private theorem indexedVecConstructorConsumeTail : - Lean4Lean.AddInductive.consumeTypeAnnotations + Ix.Theory.Named.AddInductive.consumeTypeAnnotations (ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr) = ctorIndexedVecApp indexedVecConstructorAlpha @@ -266,19 +266,19 @@ private theorem indexedVecConstructorInstantiateTail : indexedVecConstructorInstantiateTailNative private theorem indexedVecConstructorNatUniverse : - Lean4Lean.AddInductive.levelStructGe + Ix.Theory.Named.AddInductive.levelStructGe indexedVecConstructorStats.resultLevel (.succ .zero) = true := by native_decide private theorem indexedVecConstructorParamUniverse : - Lean4Lean.AddInductive.levelStructGe + Ix.Theory.Named.AddInductive.levelStructGe indexedVecConstructorStats.resultLevel (.succ (.param `u)) = true := by native_decide /-- Complete retained validation of the real `IndexedVec.cons` candidate. Unlike applying `ConstructorTypeValidationTrace.exists_of_run` to the -already-known Lean4Lean replay, this construction explicitly installs the +already-known Ix.Theory.Named replay, this construction explicitly installs the three traces transported from the production Ix positivity calls. -/ theorem indexedVecConsConstructorTypeValidationTrace : Nonempty (ConsValidationTrace indexedVecConstructorContext @@ -392,10 +392,10 @@ theorem indexedVecConsConstructorTypeValidationTrace : validator, so the vertical slice reaches the complete method rather than only its positivity helper. -/ theorem indexedVecConsConstructorValidationRun : - Lean4Lean.AddInductive.checkConstructorType + Ix.Theory.Named.AddInductive.checkConstructorType indexedVecConstructorStats false 0 indexedVecKernelCons.name indexedVecKernelCons.type indexedVecConstructorContext = .ok () := by obtain ⟨trace⟩ := indexedVecConsConstructorTypeValidationTrace exact trace.check_run -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedPositivityTransport.lean b/Ix/Kernel/Verify/Inductive/IndexedPositivityTransport.lean similarity index 90% rename from Ix/Tc/Verify/Inductive/IndexedPositivityTransport.lean rename to Ix/Kernel/Verify/Inductive/IndexedPositivityTransport.lean index 56f054155..c9fda586b 100644 --- a/Ix/Tc/Verify/Inductive/IndexedPositivityTransport.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedPositivityTransport.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.IndexedCandidateOperations -import Ix.Tc.Verify.Inductive.IndexedProductionPositivity -import Ix.Tc.Verify.Inductive.ExactLeanSyntax +import Ix.Kernel.Verify.Inductive.IndexedCandidateOperations +import Ix.Kernel.Verify.Inductive.IndexedProductionPositivity +import Ix.Kernel.Verify.Inductive.ExactLeanSyntax /-! # IndexedVec positivity transport @@ -12,11 +12,11 @@ exact Ix WHNF cache transition, so the correspondence does not silently treat the stateful production reducer as a pure function. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures -/-! ## Finite Lean4Lean observations at the trust boundary +/-! ## Finite Ix.Theory.Named observations at the trust boundary The upstream replay modules are useful for naming the exact candidate states, but their proof lemmas intentionally depend on reflected implementation @@ -25,25 +25,25 @@ consumed below with private native facts, so the exported transport depends on the concrete executions without admitting those reflected equations. -/ private theorem indexedVecNatHasNoIndOccTrusted : - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts (.const ``Nat []) = false := by native_decide private theorem indexedVecAlphaHasNoIndOccTrusted : - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts indexedVecConstructorAlpha = false := by native_decide private theorem indexedVecTailHasIndOccTrusted : - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts (ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr) = true := by native_decide private theorem indexedVecTailAppIsValidTrusted : - Lean4Lean.AddInductive.isValidIndApp? + Ix.Theory.Named.AddInductive.isValidIndApp? indexedVecConstructorStats (ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr) = some 0 := by @@ -122,48 +122,48 @@ theorem ixConsTailDomainMentionsRoot : tailDomainCandidateSyntax] exact indexedVecTailHasIndOccTrusted -/-! ## Exact Lean4Lean WHNF observations -/ +/-! ## Exact Ix.Theory.Named WHNF observations -/ private theorem indexedVecNatCandidateWhnfNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run ctorEnv + (Ix.Theory.Named.TypeChecker.M.run ctorEnv .safe indexedVecConstructorContext.lctx [`u] - ({} : Lean4Lean.FuelConfig) - (Lean4Lean.TypeChecker.whnf (.const ``Nat []))) + ({} : Ix.Theory.Named.FuelConfig) + (Ix.Theory.Named.TypeChecker.whnf (.const ``Nat []))) (.const ``Nat []) = true := by native_decide theorem indexedVecNatCandidateWhnf : - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨indexedVecConstructorContext, (.const ``Nat []), (.const ``Nat [])⟩ := by - unfold Lean4Lean.AddInductive.CandidateWhnfStep.Valid + unfold Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check indexedVecNatCandidateWhnfNative private theorem indexedVecAlphaCandidateWhnfNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run ctorEnv + (Ix.Theory.Named.TypeChecker.M.run ctorEnv .safe indexedVecConstructorNContext.lctx [`u] - ({} : Lean4Lean.FuelConfig) - (Lean4Lean.TypeChecker.whnf indexedVecConstructorAlpha)) + ({} : Ix.Theory.Named.FuelConfig) + (Ix.Theory.Named.TypeChecker.whnf indexedVecConstructorAlpha)) indexedVecConstructorAlpha = true := by native_decide theorem indexedVecAlphaCandidateWhnf : - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨indexedVecConstructorNContext, indexedVecConstructorAlpha, indexedVecConstructorAlpha⟩ := by - unfold Lean4Lean.AddInductive.CandidateWhnfStep.Valid + unfold Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check indexedVecAlphaCandidateWhnfNative private theorem indexedVecTailCandidateWhnfNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run ctorEnv + (Ix.Theory.Named.TypeChecker.M.run ctorEnv .safe indexedVecConstructorHeadContext.lctx [`u] - ({} : Lean4Lean.FuelConfig) - (Lean4Lean.TypeChecker.whnf + ({} : Ix.Theory.Named.FuelConfig) + (Ix.Theory.Named.TypeChecker.whnf (ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr))) (ctorIndexedVecApp indexedVecConstructorAlpha @@ -171,12 +171,12 @@ private theorem indexedVecTailCandidateWhnfNative : native_decide theorem indexedVecTailCandidateWhnf : - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨indexedVecConstructorHeadContext, ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr, ctorIndexedVecApp indexedVecConstructorAlpha indexedVecConstructorNExpr⟩ := by - unfold Lean4Lean.AddInductive.CandidateWhnfStep.Valid + unfold Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check indexedVecTailCandidateWhnfNative @@ -184,9 +184,9 @@ theorem indexedVecTailCandidateWhnf : /-- Sources of the three production positivity calls in the `cons` constructor. Each constructor fixes both the actual Ix binder state and the -corresponding Lean4Lean validation context. -/ +corresponding Ix.Theory.Named validation context. -/ inductive IndexedPositivitySourceRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | nat : IndexedPositivitySourceRel ixConsNatDomainState indexedVecConstructorContext ixConsNatDomain (.const ``Nat []) @@ -201,7 +201,7 @@ inductive IndexedPositivitySourceRel : syntax is the projected production WHNF result, related structurally rather than equated by its content address. -/ inductive IndexedPositivityResultRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | tail {ixResult : KExpr .anon} (candidate : CandidateSyntaxRel nameOf @@ -220,7 +220,7 @@ theorem indexedPositivitySourceMentions (relation : IndexedPositivitySourceRel ixState leanContext ixExpr leanExpr) : exprMentionsAnyAddr ixExpr #[familyId.addr] = - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts leanExpr := by cases relation with | nat => @@ -234,15 +234,15 @@ theorem indexedPositivitySourceMentions candidateBlockSyntax tailDomainCandidateSyntax private theorem indexedPositivityRootFree - {ixState : TcState .anon} {leanContext : Lean4Lean.AddInductive.Context} + {ixState : TcState .anon} {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource : KExpr .anon} {leanSource : Lean.Expr} (relation : IndexedPositivitySourceRel ixState leanContext ixSource leanSource) (free : exprMentionsAnyAddr ixSource #[familyId.addr] = false) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts leanResult = false := by cases relation with | nat => @@ -257,7 +257,7 @@ private theorem indexedPositivityRootFree private theorem indexedPositivityWhnf {ixBefore ixAfter : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource ixResult : KExpr .anon} {leanSource : Lean.Expr} (relation : IndexedPositivitySourceRel ixBefore leanContext ixSource leanSource) @@ -265,7 +265,7 @@ private theorem indexedPositivityWhnf (run : (RecM.whnf ixSource).run checkerMethods ixBefore = .ok ixResult ixAfter) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ IndexedPositivityResultRel ixAfter leanContext ixResult leanResult := by cases relation with @@ -284,7 +284,7 @@ private theorem indexedPositivityWhnf .tail ixConsTailWhnfResultCandidateSyntax⟩ private theorem indexedPositivityForall - {ixState : TcState .anon} {leanContext : Lean4Lean.AddInductive.Context} + {ixState : TcState .anon} {leanContext : Ix.Theory.Named.AddInductive.Context} {ixName : Mode.anon.F Name} {ixBinder : Mode.anon.F Lean.BinderInfo} {ixDomain ixBody : KExpr .anon} {ixInfo : ExprInfo .anon} {leanExpr : Lean.Expr} @@ -299,13 +299,13 @@ private theorem indexedPositivityForall .ok (ixOpen, ixFVar) ixAfterOpen → IndexedPositivitySourceRel ixAfterOpen (leanContext.pushLocalDecl leanName leanBinder - (Lean4Lean.AddInductive.consumeTypeAnnotations leanDomain)) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanDomain)) ixOpen (leanBody.instantiate1 leanContext.freshExpr) := by cases relation with | tail candidate => cases candidate private theorem indexedPositivityDirect - {ixState : TcState .anon} {leanContext : Lean4Lean.AddInductive.Context} + {ixState : TcState .anon} {leanContext : Ix.Theory.Named.AddInductive.Context} {ixResult : KExpr .anon} {leanResult : Lean.Expr} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} {args : Array (KExpr .anon)} {groups : Array (PositivityGroup .anon)} @@ -317,10 +317,10 @@ private theorem indexedPositivityDirect (_valid : ValidPositiveRecursiveApplication id us args groups #[familyId.addr] checkerMethods ixState final) : ∃ targetIdx, - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts leanResult = true ∧ leanResult.isForall = false ∧ - Lean4Lean.AddInductive.isValidIndApp? + Ix.Theory.Named.AddInductive.isValidIndApp? indexedVecConstructorStats leanResult = some targetIdx := by cases relation with | tail _ => @@ -516,10 +516,10 @@ theorem indexedVecTailFlatPositivityTrace : ixConsTailPositivityAfter := indexedVecTailFlatPositivityTraceAt 0 -/-! ## Lean4Lean constructor-positivity artifacts -/ +/-! ## Ix.Theory.Named constructor-positivity artifacts -/ theorem indexedVecNatConstructorPositivityTraceAt (fuel : Nat) : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 1 indexedVecConstructorContext (.const ``Nat []) (fuel + 1)) := FlatPositivityTraceTransport.constructorPositivityTrace @@ -527,7 +527,7 @@ theorem indexedVecNatConstructorPositivityTraceAt (fuel : Nat) : (indexedVecNatFlatPositivityTraceAt fuel) rfl .nat theorem indexedVecHeadConstructorPositivityTraceAt (fuel : Nat) : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 2 indexedVecConstructorNContext indexedVecConstructorAlpha (fuel + 1)) := FlatPositivityTraceTransport.constructorPositivityTrace @@ -535,7 +535,7 @@ theorem indexedVecHeadConstructorPositivityTraceAt (fuel : Nat) : (indexedVecHeadFlatPositivityTraceAt fuel) rfl .head theorem indexedVecTailConstructorPositivityTraceAt (fuel : Nat) : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 3 indexedVecConstructorHeadContext (ctorIndexedVecApp indexedVecConstructorAlpha @@ -545,19 +545,19 @@ theorem indexedVecTailConstructorPositivityTraceAt (fuel : Nat) : (indexedVecTailFlatPositivityTraceAt fuel) rfl .tail theorem indexedVecNatConstructorPositivityTrace : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 1 indexedVecConstructorContext (.const ``Nat []) 1) := indexedVecNatConstructorPositivityTraceAt 0 theorem indexedVecHeadConstructorPositivityTrace : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 2 indexedVecConstructorNContext indexedVecConstructorAlpha 1) := indexedVecHeadConstructorPositivityTraceAt 0 theorem indexedVecTailConstructorPositivityTrace : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 3 indexedVecConstructorHeadContext (ctorIndexedVecApp indexedVecConstructorAlpha @@ -660,7 +660,7 @@ theorem familyConsTailWhnfCandidateSyntax : /-- Sources are indexed by the exact states reached by the real family-block checker, rather than by a replay from `checkerInitial`. -/ inductive ProductionIndexedPositivitySourceRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | nat : ProductionIndexedPositivitySourceRel familyConsNatDomainState indexedVecConstructorContext familyConsNatDomain (.const ``Nat []) @@ -675,7 +675,7 @@ inductive ProductionIndexedPositivitySourceRel : /-- The mentioned production source has exactly one WHNF result shape in this fixture: the recursive `IndexedVec α n` application. -/ inductive ProductionIndexedPositivityResultRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | tail {ixResult : KExpr .anon} (candidate : CandidateSyntaxRel nameOf @@ -695,7 +695,7 @@ theorem productionIndexedPositivitySourceMentions (relation : ProductionIndexedPositivitySourceRel ixState leanContext ixExpr leanExpr) : exprMentionsAnyAddr ixExpr #[familyId.addr] = - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts leanExpr := by cases relation with | nat => @@ -709,15 +709,15 @@ theorem productionIndexedPositivitySourceMentions candidateBlockSyntax familyConsTailDomainCandidateSyntax private theorem productionIndexedPositivityRootFree - {ixState : TcState .anon} {leanContext : Lean4Lean.AddInductive.Context} + {ixState : TcState .anon} {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource : KExpr .anon} {leanSource : Lean.Expr} (relation : ProductionIndexedPositivitySourceRel ixState leanContext ixSource leanSource) (free : exprMentionsAnyAddr ixSource #[familyId.addr] = false) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts leanResult = false := by cases relation with | nat => @@ -732,7 +732,7 @@ private theorem productionIndexedPositivityRootFree private theorem productionIndexedPositivityWhnf {ixBefore ixAfter : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource ixResult : KExpr .anon} {leanSource : Lean.Expr} (relation : ProductionIndexedPositivitySourceRel ixBefore leanContext ixSource leanSource) @@ -740,7 +740,7 @@ private theorem productionIndexedPositivityWhnf (run : (RecM.whnf ixSource).run checkerMethods ixBefore = .ok ixResult ixAfter) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ ProductionIndexedPositivityResultRel ixAfter leanContext ixResult leanResult := by @@ -760,7 +760,7 @@ private theorem productionIndexedPositivityWhnf .tail familyConsTailWhnfCandidateSyntax⟩ private theorem productionIndexedPositivityForall - {ixState : TcState .anon} {leanContext : Lean4Lean.AddInductive.Context} + {ixState : TcState .anon} {leanContext : Ix.Theory.Named.AddInductive.Context} {ixName : Mode.anon.F Name} {ixBinder : Mode.anon.F Lean.BinderInfo} {ixDomain ixBody : KExpr .anon} {ixInfo : ExprInfo .anon} {leanExpr : Lean.Expr} @@ -776,13 +776,13 @@ private theorem productionIndexedPositivityForall .ok (ixOpen, ixFVar) ixAfterOpen → ProductionIndexedPositivitySourceRel ixAfterOpen (leanContext.pushLocalDecl leanName leanBinder - (Lean4Lean.AddInductive.consumeTypeAnnotations leanDomain)) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanDomain)) ixOpen (leanBody.instantiate1 leanContext.freshExpr) := by cases relation with | tail candidate => cases candidate private theorem productionIndexedPositivityDirect - {ixState : TcState .anon} {leanContext : Lean4Lean.AddInductive.Context} + {ixState : TcState .anon} {leanContext : Ix.Theory.Named.AddInductive.Context} {ixResult : KExpr .anon} {leanResult : Lean.Expr} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} {args : Array (KExpr .anon)} {groups : Array (PositivityGroup .anon)} @@ -794,10 +794,10 @@ private theorem productionIndexedPositivityDirect (_valid : ValidPositiveRecursiveApplication id us args groups #[familyId.addr] checkerMethods ixState final) : ∃ targetIdx, - Lean4Lean.AddInductive.hasIndOcc + Ix.Theory.Named.AddInductive.hasIndOcc indexedVecConstructorStats.indConsts leanResult = true ∧ leanResult.isForall = false ∧ - Lean4Lean.AddInductive.isValidIndApp? + Ix.Theory.Named.AddInductive.isValidIndApp? indexedVecConstructorStats leanResult = some targetIdx := by cases relation with | tail _ => @@ -818,7 +818,7 @@ theorem indexedVecProductionFlatPositivityTransport : /-! ## Production trace transport at the candidate checker's fuel -Ix enters constructor positivity with `maxWhnfFuel`, while Lean4Lean's retained +Ix enters constructor positivity with `maxWhnfFuel`, while Ix.Theory.Named's retained candidate context has its own inductive fuel. Fuel cannot be changed for an arbitrary recursive trace. The following lemmas first inspect the traces projected from the real production run and only reindex the two branch forms @@ -921,7 +921,7 @@ theorem indexedVecProductionTailFlatPositivityTraceAt (fuel : Nat) : active valid theorem indexedVecProductionNatConstructorPositivityTraceAt (fuel : Nat) : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 1 indexedVecConstructorContext (.const ``Nat []) (fuel + 1)) := FlatPositivityTraceTransport.constructorPositivityTrace @@ -930,7 +930,7 @@ theorem indexedVecProductionNatConstructorPositivityTraceAt (fuel : Nat) : ProductionIndexedPositivitySourceRel.nat theorem indexedVecProductionHeadConstructorPositivityTraceAt (fuel : Nat) : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 2 indexedVecConstructorNContext indexedVecConstructorAlpha (fuel + 1)) := FlatPositivityTraceTransport.constructorPositivityTrace @@ -939,7 +939,7 @@ theorem indexedVecProductionHeadConstructorPositivityTraceAt (fuel : Nat) : ProductionIndexedPositivitySourceRel.head theorem indexedVecProductionTailConstructorPositivityTraceAt (fuel : Nat) : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace indexedVecConstructorStats indexedVecKernelCons.name 3 indexedVecConstructorHeadContext (ctorIndexedVecApp indexedVecConstructorAlpha @@ -949,4 +949,4 @@ theorem indexedVecProductionTailConstructorPositivityTraceAt (fuel : Nat) : (indexedVecProductionTailFlatPositivityTraceAt fuel) rfl ProductionIndexedPositivitySourceRel.tail -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedProducerClosure.lean b/Ix/Kernel/Verify/Inductive/IndexedProducerClosure.lean similarity index 84% rename from Ix/Tc/Verify/Inductive/IndexedProducerClosure.lean rename to Ix/Kernel/Verify/Inductive/IndexedProducerClosure.lean index b781120ff..82113542d 100644 --- a/Ix/Tc/Verify/Inductive/IndexedProducerClosure.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedProducerClosure.lean @@ -1,18 +1,18 @@ -import Ix.Tc.Verify.Inductive.GeneratedRecursorAdmission -import Ix.Tc.Verify.Inductive.IndexedCandidateTransaction +import Ix.Kernel.Verify.Inductive.GeneratedRecursorAdmission +import Ix.Kernel.Verify.Inductive.IndexedCandidateTransaction /-! # Producer-linked IndexedVec one-family closure The trust-minimal `IndexedVec` Theory transaction and the executable -Lean4Lean candidate replay are intentionally audited separately. This module +Ix.Theory.Named candidate replay are intentionally audited separately. This module joins them only at a stronger E2c root: the exact producer-selected package erases to the same certificate transaction consumed by the Ix family and generated-recursor admission, while all three anonymous ingress calls and both production block checks remain explicit. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture open IndexedRecursiveCertificateFixture @@ -38,7 +38,7 @@ structure ProducerLinkedOneFamilyClosure : Prop where checkerMethods familyKernelAfter = .ok () recursorKernelAfter semantic : CanonicalRecursorAtomicClosure -/-- The exact outer Lean4Lean producer, production Ix executions, and +/-- The exact outer Ix.Theory.Named producer, production Ix executions, and oracle-free one-family semantic closure for the concrete indexed-recursive fixture. -/ theorem producerLinkedOneFamilyClosure : ProducerLinkedOneFamilyClosure where @@ -51,4 +51,4 @@ theorem producerLinkedOneFamilyClosure : ProducerLinkedOneFamilyClosure where recursorChecked := recursorKernelRun semantic := familyRecursorAtomicClosure -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedProductionPositivity.lean b/Ix/Kernel/Verify/Inductive/IndexedProductionPositivity.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/IndexedProductionPositivity.lean rename to Ix/Kernel/Verify/Inductive/IndexedProductionPositivity.lean index b9095aad8..73668a254 100644 --- a/Ix/Tc/Verify/Inductive/IndexedProductionPositivity.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedProductionPositivity.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.IndexedBlockValidation -import Ix.Tc.Verify.Inductive.PositivityTraceAdapter +import Ix.Kernel.Verify.Inductive.IndexedBlockValidation +import Ix.Kernel.Verify.Inductive.PositivityTraceAdapter /-! # Production-selected IndexedVec positivity @@ -11,7 +11,7 @@ projected from the `IndexedVec.cons` validation selected by the exact states is reconstructed by running positivity a second time. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture /-- The production-selected constructor is the exact ingressed `cons` declaration, not merely some telescope that happened to pass the same @@ -620,7 +620,7 @@ theorem familyConsResultWhnfTerminal : /-- Exact three-field view of the positivity traversal selected by the real family-block execution. Besides the complete enclosing loop, the view exposes -the direct-only flat traces consumed by the Lean4Lean adapter. -/ +the direct-only flat traces consumed by the Ix.Theory.Named adapter. -/ structure IndexedVecConsProductionFieldProjection : Prop where nat : FlatPositivityDomainTrace familyConsPositivityGroups #[familyId.addr] checkerMethods maxWhnfFuel.toNat familyConsNatDomain @@ -910,4 +910,4 @@ theorem indexedVecConsProductionParameterBranch : | fields parameters fields => exact ⟨ctorTy, initial, final, .inr ⟨_, _, _, parameters, fields⟩⟩ -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedRecursiveAcceptance.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursiveAcceptance.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/IndexedRecursiveAcceptance.lean rename to Ix/Kernel/Verify/Inductive/IndexedRecursiveAcceptance.lean index c04eb5156..e5b062822 100644 --- a/Ix/Tc/Verify/Inductive/IndexedRecursiveAcceptance.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursiveAcceptance.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.SingletonInductive -import Ix.Tc.Verify.Inductive.IndexedRecursiveFixture +import Ix.Kernel.Verify.Check.SingletonInductive +import Ix.Kernel.Verify.Inductive.IndexedRecursiveFixture /-! # Production acceptance of the indexed-recursive fixture @@ -10,10 +10,10 @@ ingressed recursor block is compared against that cached result. Every run starts from the exact final anonymous ingress state retained by the fixture. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveReplayFixtures open IndexedRecursiveCertificateFixture local instance acceptanceAnonKIdDecidableEq : DecidableEq (KId .anon) := @@ -183,8 +183,8 @@ private theorem directInductiveOwner_inductiveMemberOf simp_all [IsDirectInductiveOwner, KConst.IsInductiveMemberOf] private theorem certifiedConstructor_inductiveMemberOf - {source : Lean4Lean.VInductDecl} {familyId block : KId .anon} - {index : Nat} {sourceConstructor : Lean4Lean.VConstVal} + {source : Ix.Theory.Named.VInductDecl} {familyId block : KId .anon} + {index : Nat} {sourceConstructor : Ix.Theory.Named.VConstVal} {concrete familyConcrete : KConst .anon} {catalog : Catalog} (hshape : concrete.IsCertifiedSingletonConstructor source familyId index sourceConstructor) @@ -197,8 +197,8 @@ private theorem certifiedConstructor_inductiveMemberOf exact hfamilyOwner private theorem certifiedConstructor_not_inductiveMemberOf - {source : Lean4Lean.VInductDecl} {familyId block : KId .anon} - {index : Nat} {sourceConstructor : Lean4Lean.VConstVal} + {source : Ix.Theory.Named.VInductDecl} {familyId block : KId .anon} + {index : Nat} {sourceConstructor : Ix.Theory.Named.VConstVal} {concrete familyConcrete : KConst .anon} {catalog : Catalog} (hshape : concrete.IsCertifiedSingletonConstructor source familyId index sourceConstructor) @@ -220,7 +220,7 @@ private theorem certifiedConstructor_not_inductiveMemberOf simp [KConst.IsCertifiedSingletonConstructor] at hshape private theorem certifiedFamily_not_inductiveMemberOf - {source : Lean4Lean.VInductDecl} {generation : source.GenerationChecked} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {constructorIds : Array (KId .anon)} {concrete : KConst .anon} {catalog : Catalog} {block : KId .anon} (hshape : concrete.IsCertifiedSingletonFamily source generation @@ -233,7 +233,7 @@ private theorem certifiedFamily_not_inductiveMemberOf KConst.IsInductiveMemberOf, IsDirectInductiveOwner] private theorem certifiedRecursor_not_inductiveMemberOf - {source : Lean4Lean.VInductDecl} {generation : source.GenerationChecked} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {constructorIds : Array (KId .anon)} {concrete : KConst .anon} {catalog : Catalog} {block : KId .anon} (hshape : concrete.IsCertifiedSingletonRecursor source generation @@ -245,7 +245,7 @@ private theorem certifiedRecursor_not_inductiveMemberOf KConst.IsInductiveMemberOf] private theorem certifiedFamily_not_recursorMemberOf - {source : Lean4Lean.VInductDecl} {generation : source.GenerationChecked} + {source : Ix.Theory.Named.VInductDecl} {generation : source.GenerationChecked} {constructorIds : Array (KId .anon)} {concrete : KConst .anon} {block : KId .anon} (hshape : concrete.IsCertifiedSingletonFamily source generation @@ -257,8 +257,8 @@ private theorem certifiedFamily_not_recursorMemberOf KConst.IsRecursorMemberOf] private theorem certifiedConstructor_not_recursorMemberOf - {source : Lean4Lean.VInductDecl} {familyId : KId .anon} - {index : Nat} {sourceConstructor : Lean4Lean.VConstVal} + {source : Ix.Theory.Named.VInductDecl} {familyId : KId .anon} + {index : Nat} {sourceConstructor : Ix.Theory.Named.VConstVal} {concrete : KConst .anon} {block : KId .anon} (hshape : concrete.IsCertifiedSingletonConstructor source familyId index sourceConstructor) : @@ -631,4 +631,4 @@ theorem endToEndAcceptance : EndToEndAcceptance where admittedRecursor := recursorAtomicAdmission rejectsMalformedRecursor := malformedRecursorRun -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedRecursiveCertificate.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursiveCertificate.lean similarity index 91% rename from Ix/Tc/Verify/Inductive/IndexedRecursiveCertificate.lean rename to Ix/Kernel/Verify/Inductive/IndexedRecursiveCertificate.lean index 1729e1249..cb47c4ea1 100644 --- a/Ix/Tc/Verify/Inductive/IndexedRecursiveCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursiveCertificate.lean @@ -1,10 +1,10 @@ -import Ix.Tc.Verify.Inductive.Certificate -import Lean4Lean.Verify.Environment.InductiveFixtures +import Ix.Kernel.Verify.Inductive.Certificate +import Ix.Theory.Named.Verify.Environment.InductiveFixtures /-! # Certified parameterized, indexed, recursive generation fixture -Lean4Lean's `IndexedVec` fixture is the first certificate in the dependency +Ix.Theory.Named's `IndexedVec` fixture is the first certificate in the dependency whose source is simultaneously parameterized, indexed, and recursive. This module reconstructs it through the Theory-only proof-carrying transaction boundary and records the exact breadth facts that distinguish it from E2b's @@ -14,18 +14,18 @@ The ambient `Nat` environment is reconstructed through its own certified transaction instead of importing the implementation-reflection replay proof. This is important for the trust manifest: the resulting certificate depends only on the accepted Lean axioms, not on persistent-map or reflected-expression -equations from the `Lean4Lean.Verify` layer. +equations from the `Ix.Theory.Named.Verify` layer. Nothing here asserts an Ix catalog correspondence. That separate link must be constructed from production anonymous ingress and checking, so the certificate cannot silently choose the concrete declarations it certifies. -/ -namespace Ix.Tc.IndexedRecursiveCertificateFixture +namespace Ix.Kernel.IndexedRecursiveCertificateFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures /-- The exact proof-carrying transaction that constructs the ambient `Nat` environment needed by `IndexedVec`. -/ @@ -117,4 +117,4 @@ theorem certifiedFacts : transaction.certificate := transaction.facts -end Ix.Tc.IndexedRecursiveCertificateFixture +end Ix.Kernel.IndexedRecursiveCertificateFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedRecursiveFixture.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursiveFixture.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/IndexedRecursiveFixture.lean rename to Ix/Kernel/Verify/Inductive/IndexedRecursiveFixture.lean index 82b0a5bec..22d66da7e 100644 --- a/Ix/Tc/Verify/Inductive/IndexedRecursiveFixture.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursiveFixture.lean @@ -1,21 +1,21 @@ -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.IndexedRecursiveOracle +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.IndexedRecursiveOracle /-! # Concrete parameterized, indexed, recursive fixture -This module connects the certified Lean4Lean `IndexedVec` generation to the +This module connects the certified Ix.Theory.Named `IndexedVec` generation to the actual anonymous Ixon layout. `Nat`, the family/constructor block, and the separate recursor block are ingressed in dependency order. Later sections retain the exact converted entries so the production checker and atomic admission theorem consume the same physical declarations. -/ -namespace Ix.Tc.IndexedRecursiveFixture +namespace Ix.Kernel.IndexedRecursiveFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open IndexedRecursiveCertificateFixture open InductiveConcreteFixture @@ -1291,4 +1291,4 @@ def recursorLink : SingletonRecursorCatalogLink RawProjRel.none world.catalog recursorInterpretation.toCatalogLinkOfEntry recursorIngressExecution catalog_recursor trustedCatalog -end Ix.Tc.IndexedRecursiveFixture +end Ix.Kernel.IndexedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/IndexedRecursiveOracle.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursiveOracle.lean similarity index 93% rename from Ix/Tc/Verify/Inductive/IndexedRecursiveOracle.lean rename to Ix/Kernel/Verify/Inductive/IndexedRecursiveOracle.lean index 3bdc8f8f0..09be3e79a 100644 --- a/Ix/Tc/Verify/Inductive/IndexedRecursiveOracle.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursiveOracle.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.IndexedRecursiveSoundness +import Ix.Kernel.Verify.Inductive.IndexedRecursiveSoundness /-! # Certificate-backed indexed recursive recursor oracle @@ -9,11 +9,11 @@ patterns validate a uniform parameter and a changing index; the second rule also reconstructs the recursive call at the predecessor index. -/ -namespace Ix.Tc.IndexedRecursivePattern +namespace Ix.Kernel.IndexedRecursivePattern -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open IndexedRecursiveCertificateFixture /-- The exact two-rule indexed-recursive recursor oracle. The physical Ix @@ -84,4 +84,4 @@ def oracle change (id ∈ link.members) ↔ id ∈ link.members exact Iff.rfl -end Ix.Tc.IndexedRecursivePattern +end Ix.Kernel.IndexedRecursivePattern diff --git a/Ix/Tc/Verify/Inductive/IndexedRecursivePattern.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursivePattern.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/IndexedRecursivePattern.lean rename to Ix/Kernel/Verify/Inductive/IndexedRecursivePattern.lean index b877f21f9..d7f766f8f 100644 --- a/Ix/Tc/Verify/Inductive/IndexedRecursivePattern.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursivePattern.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Inductive.IndexedRecursiveCertificate -import Ix.Tc.Verify.Inductive.IotaPattern +import Ix.Kernel.Verify.Inductive.IndexedRecursiveCertificate +import Ix.Kernel.Verify.Inductive.IotaPattern + +open Ix.Theory (VLevel) /-! # Generated iota patterns for the indexed recursive fixture @@ -11,11 +13,11 @@ three fields and constructs the recursive call at the predecessor index from captured recursor and constructor arguments. -/ -namespace Ix.Tc.IndexedRecursivePattern +namespace Ix.Kernel.IndexedRecursivePattern -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open IndexedRecursiveCertificateFixture def recursorName : Lean.Name := ``IndexedVec.rec @@ -428,4 +430,4 @@ theorem consPatternMetadata simpa only [consPattern, consFieldCount, show (3 : UInt64).toNat = 3 from rfl] using hfields -end Ix.Tc.IndexedRecursivePattern +end Ix.Kernel.IndexedRecursivePattern diff --git a/Ix/Tc/Verify/Inductive/IndexedRecursiveSoundness.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursiveSoundness.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/IndexedRecursiveSoundness.lean rename to Ix/Kernel/Verify/Inductive/IndexedRecursiveSoundness.lean index b7cdf6983..5c2bedecf 100644 --- a/Ix/Tc/Verify/Inductive/IndexedRecursiveSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursiveSoundness.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.IndexedRecursivePattern +import Ix.Kernel.Verify.Inductive.IndexedRecursivePattern + +open Ix.Theory (VLevel) /-! # Indexed recursive iota soundness @@ -9,11 +11,11 @@ production WHNF. All equation shapes below reduce from the retained `GenerationChecked.rule`; no independently supplied rewrite law is used. -/ -namespace Ix.Tc.IndexedRecursivePattern +namespace Ix.Kernel.IndexedRecursivePattern -open Lean4Lean -open Lean4Lean.InductiveFixtures -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures open IndexedRecursiveCertificateFixture private abbrev generation := transaction.certificate.generation @@ -561,7 +563,7 @@ theorem nilPatternSound hconstructorApplied⟩ := htype.app_inv hfutureWF.ordered hGamma obtain ⟨recursorHeadType, hrecursorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := hrecursorHeadTyped.const_inv hfutureWF.ordered hGamma have hcertifiedRecursorLookup := @@ -586,7 +588,7 @@ theorem nilPatternSound subst levelTail obtain ⟨constructorHeadType, hconstructorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied obtain ⟨constructorConstant, hconstructorLookup, hconstructorLevelsWF, hconstructorLevelsArity⟩ := hconstructorHeadTyped.const_inv hfutureWF.ordered hGamma @@ -623,7 +625,7 @@ theorem nilPatternSound have hrecursorConstantTyped : future.HasType uvars Gamma (.const ``IndexedVec.rec [v, u]) (generation.recType.instL [v, u]) := by - have htyped := Lean4Lean.VEnv.HasType.const (Γ := Gamma) + have htyped := Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity rw [generationRecursorName] at htyped simpa [VInductDecl.GenerationChecked.recursor] using htyped @@ -639,20 +641,20 @@ theorem nilPatternSound (.forallE majorDomain majorBody) := by simpa using hrecursorApplied obtain ⟨recursorParameterResult, hrecursorParameterApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [alpha]) (suffixArgs := [motive, nilMinor, consMinor, index]) hrecursorAppliedSplit have hrecursorAlpha : future.HasType uvars Gamma alpha (.sort (.succ u)) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hrecursorParameterApplied hrecursorParameterHead have hconstructorConstantTyped : future.HasType uvars Gamma (.const ``IndexedVec.nil [constructorU]) (nilNormalized.raw.toVConstant.type.instL [constructorU]) := by simpa [nilNormalizedName] using - (Lean4Lean.VEnv.HasType.const (Γ := Gamma) + (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedConstructorLookup hconstructorLevelsWF hconstructorLevelsArity) have hconstructorParameterHead : future.HasType uvars Gamma @@ -664,7 +666,7 @@ theorem nilPatternSound exact hconstructorConstantTyped have hconstructorAlpha : future.HasType uvars Gamma constructorAlpha (.sort (.succ constructorU)) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hconstructorApplied hconstructorParameterHead obtain ⟨parameterType, hparameterTyped⟩ := hparameter' @@ -679,7 +681,7 @@ theorem nilPatternSound hrecursorSort.trans hfutureWF hGamma hconstructorSort.symm have huniverse : u ≈ constructorU := VLevel.succ_congr_iff.mp - (Lean4Lean.VEnv.IsDefEqU.sort_inv hfutureWF hGamma hsorts) + (Ix.Theory.Named.VEnv.IsDefEqU.sort_inv hfutureWF hGamma hsorts) have hnilLookup := hcertifiedConstructorLookup rw [nilNormalizedName] at hnilLookup @@ -717,7 +719,7 @@ theorem nilPatternSound [alpha, motive, nilMinor, consMinor, .const ``Nat.zero []]) := by refine ⟨indexBody.inst index, ?_⟩ simpa only [VExpr.appN] using - (Lean4Lean.VEnv.IsDefEq.appDF hrecursorBeforeIndex hindexAtDomain) + (Ix.Theory.Named.VEnv.IsDefEq.appDF hrecursorBeforeIndex hindexAtDomain) have hrecursorIndexEqTyped : future.IsDefEq uvars Gamma (VExpr.appN (.const ``IndexedVec.rec [v, u]) [alpha, motive, nilMinor, consMinor, index]) @@ -776,18 +778,18 @@ theorem nilPatternSound (.forallE majorDomain majorBody) := by simpa using hrecursorApplied obtain ⟨recursorCommonResult, hrecursorCommonApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [alpha, motive, nilMinor, consMinor]) (suffixArgs := [index]) hrecursorCommonAppliedSplit have hcommonLength : [alpha, motive, nilMinor, consMinor].length = (commonBinders.map (VExpr.instL [v, u])).length := by simp have hequationLhsApplied := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hcommonLength hrecursorCommonApplied hrecursorCommonType hequationLhsCommonType have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationRhsApplied := (hequationApplied.of_l hfutureWF hGamma @@ -800,7 +802,7 @@ theorem nilPatternSound have hequationLhsApplied' := hequationLhsApplied rw [(generatedRule_shape 0 nilNormalized).1, VExpr.instL_lamN] at hequationLhsApplied' - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleBinderLength hequationLhsApplied' rw [nilLhsBody_open] at hlhsBeta have hlhsBeta' : future.IsDefEqU uvars Gamma @@ -817,7 +819,7 @@ theorem nilPatternSound have hequationRhsApplied' := hequationRhsApplied rw [(generatedRule_shape 0 nilNormalized).2.1, VExpr.instL_lamN] at hequationRhsApplied' - have hrhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hrhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleBinderLength hequationRhsApplied' rw [nilRhsBody_open] at hrhsBeta have hrhsBeta' : future.IsDefEqU uvars Gamma @@ -928,7 +930,7 @@ theorem consPatternSound hconstructorApplied⟩ := htype.app_inv hfutureWF.ordered hGamma obtain ⟨recursorHeadType, hrecursorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := hrecursorHeadTyped.const_inv hfutureWF.ordered hGamma have hcertifiedRecursorLookup := @@ -953,7 +955,7 @@ theorem consPatternSound subst levelTail obtain ⟨constructorHeadType, hconstructorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied obtain ⟨constructorConstant, hconstructorLookup, hconstructorLevelsWF, hconstructorLevelsArity⟩ := hconstructorHeadTyped.const_inv hfutureWF.ordered hGamma @@ -990,7 +992,7 @@ theorem consPatternSound have hrecursorConstantTyped : future.HasType uvars Gamma (.const ``IndexedVec.rec [v, u]) (generation.recType.instL [v, u]) := by - have htyped := Lean4Lean.VEnv.HasType.const (Γ := Gamma) + have htyped := Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity rw [generationRecursorName] at htyped simpa [VInductDecl.GenerationChecked.recursor] using htyped @@ -1006,20 +1008,20 @@ theorem consPatternSound (.forallE majorDomain majorBody) := by simpa using hrecursorApplied obtain ⟨recursorParameterResult, hrecursorParameterApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [alpha]) (suffixArgs := [motive, nilMinor, consMinor, index]) hrecursorAppliedSplit have hrecursorAlpha : future.HasType uvars Gamma alpha (.sort (.succ u)) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hrecursorParameterApplied hrecursorParameterHead have hconstructorConstantTyped : future.HasType uvars Gamma (.const ``IndexedVec.cons [constructorU]) (consNormalized.raw.toVConstant.type.instL [constructorU]) := by simpa [consNormalizedName] using - (Lean4Lean.VEnv.HasType.const (Γ := Gamma) + (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedConstructorLookup hconstructorLevelsWF hconstructorLevelsArity) have hconstructorParameterHead : future.HasType uvars Gamma @@ -1034,12 +1036,12 @@ theorem consPatternSound ([constructorAlpha] ++ [n, a, as])) majorDomain := by simpa using hconstructorApplied obtain ⟨constructorParameterResult, hconstructorParameterApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [constructorAlpha]) (suffixArgs := [n, a, as]) hconstructorAppliedSplit have hconstructorAlpha : future.HasType uvars Gamma constructorAlpha (.sort (.succ constructorU)) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hconstructorParameterApplied hconstructorParameterHead obtain ⟨parameterType, hparameterTyped⟩ := hparameter' @@ -1054,7 +1056,7 @@ theorem consPatternSound hrecursorSort.trans hfutureWF hGamma hconstructorSort.symm have huniverse : u ≈ constructorU := VLevel.succ_congr_iff.mp - (Lean4Lean.VEnv.IsDefEqU.sort_inv hfutureWF hGamma hsorts) + (Ix.Theory.Named.VEnv.IsDefEqU.sort_inv hfutureWF hGamma hsorts) have hconsLookup := hcertifiedConstructorLookup rw [consNormalizedName] at hconsLookup @@ -1094,7 +1096,7 @@ theorem consPatternSound [constructorAlpha, n, a, as]) (VExpr.appN (.const ``IndexedVec.cons [u]) [alpha, n, a, as]) := by simpa only [VExpr.appN] using - (Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma + (Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hconstructorPrefixEqTyped hconstructorAppliedFromPrefix) obtain ⟨indexDomain, indexBody, hrecursorBeforeIndex, hindexTyped⟩ := @@ -1110,7 +1112,7 @@ theorem consPatternSound .app (.const ``Nat.succ []) n]) := by refine ⟨indexBody.inst index, ?_⟩ simpa only [VExpr.appN] using - (Lean4Lean.VEnv.IsDefEq.appDF hrecursorBeforeIndex hindexAtDomain) + (Ix.Theory.Named.VEnv.IsDefEq.appDF hrecursorBeforeIndex hindexAtDomain) have hrecursorIndexEqTyped : future.IsDefEq uvars Gamma (VExpr.appN (.const ``IndexedVec.rec [v, u]) [alpha, motive, nilMinor, consMinor, index]) @@ -1175,7 +1177,7 @@ theorem consPatternSound (.forallE majorDomain majorBody) := by simpa using hrecursorApplied obtain ⟨recursorCommonResult, hrecursorCommonApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [alpha, motive, nilMinor, consMinor]) (suffixArgs := [index]) hrecursorCommonAppliedSplit have hcommonLength : @@ -1185,14 +1187,14 @@ theorem consPatternSound (VExpr.appN ((generation.rule 1 consNormalized).lhs.instL [v, u]) [alpha, motive, nilMinor, consMinor]) (consEquationFieldType v u alpha motive nilMinor consMinor) := by - exact Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + exact Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hcommonLength hrecursorCommonApplied hrecursorCommonType hequationLhsCommonType have hcanonicalConstructorConstantTyped : future.HasType uvars Gamma (.const ``IndexedVec.cons [u]) (consNormalized.raw.toVConstant.type.instL [u]) := by - exact Lean4Lean.VEnv.HasType.const hconsLookup + exact Ix.Theory.Named.VEnv.HasType.const hconsLookup (fun level hlevel => by simp only [List.mem_singleton] at hlevel subst level @@ -1207,7 +1209,7 @@ theorem consPatternSound have hcanonicalConstructorPrefix : future.HasType uvars Gamma (.app (.const ``IndexedVec.cons [u]) alpha) (consConstructorFieldType u alpha) := by - have happ := Lean4Lean.VEnv.HasType.app + have happ := Ix.Theory.Named.VEnv.HasType.app hcanonicalConstructorParameterHead hrecursorAlpha simpa [consConstructorFieldType, VExpr.instRev] using happ have hcanonicalConstructorApplied : future.HasType uvars Gamma @@ -1252,7 +1254,7 @@ theorem consPatternSound VExpr.instRev, VExpr.instL, VExpr.inst, VExpr.instVar, VExpr.telN, VExpr.dropN] have hequationLhsFieldsApplied := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hfieldLength hcanonicalConstructorApplied hconstructorFieldHead' hequationFieldHead have hequationLhsApplied : future.HasType uvars Gamma @@ -1267,7 +1269,7 @@ theorem consPatternSound VExpr.appN_append] exact hequationLhsFieldsApplied have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationRhsApplied := (hequationApplied.of_l hfutureWF hGamma @@ -1280,7 +1282,7 @@ theorem consPatternSound have hequationLhsApplied' := hequationLhsApplied rw [(generatedRule_shape 1 consNormalized).1, VExpr.instL_lamN] at hequationLhsApplied' - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleBinderLength hequationLhsApplied' rw [consLhsBody_open] at hlhsBeta have hlhsBeta' : future.IsDefEqU uvars Gamma @@ -1299,7 +1301,7 @@ theorem consPatternSound have hequationRhsApplied' := hequationRhsApplied rw [(generatedRule_shape 1 consNormalized).2.1, VExpr.instL_lamN] at hequationRhsApplied' - have hrhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hrhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleBinderLength hequationRhsApplied' rw [consRhsBody_open] at hrhsBeta have hrhsBeta' : future.IsDefEqU uvars Gamma @@ -1366,4 +1368,4 @@ theorem consPatternRel (consPatternMetadata link hone hrule) (consPatternSound link hrule (family.constructorIds[1]'hone)) -end Ix.Tc.IndexedRecursivePattern +end Ix.Kernel.IndexedRecursivePattern diff --git a/Ix/Tc/Verify/Inductive/IngressExecution.lean b/Ix/Kernel/Verify/Inductive/IngressExecution.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/IngressExecution.lean rename to Ix/Kernel/Verify/Inductive/IngressExecution.lean index ebfc29670..2b27759a0 100644 --- a/Ix/Tc/Verify/Inductive/IngressExecution.lean +++ b/Ix/Kernel/Verify/Inductive/IngressExecution.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Ingress -import Ix.Tc.Verify.Inductive.SingletonIngress +import Ix.Kernel.Ingress +import Ix.Kernel.Verify.Inductive.SingletonIngress /-! # Anonymous inductive-block ingress execution @@ -17,7 +17,7 @@ discharge it for their actual projection addresses; no Blake3 injectivity is smuggled into the model. -/ -namespace Ix.Tc +namespace Ix.Kernel /-! ## Flat insertion semantics -/ @@ -196,7 +196,7 @@ end AnonBlockIngressSuccessTrace /-! ## Singleton source interpretations -/ -open Lean4Lean (VEnv VInductDecl) +open Ix.Theory.Named (VEnv VInductDecl) /-- Ghost interpretation of one production family-block conversion result. @@ -509,4 +509,4 @@ def toCatalogLinkOfEntry end SingletonRecursorIngressInterpretation -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/IotaPattern.lean b/Ix/Kernel/Verify/Inductive/IotaPattern.lean similarity index 79% rename from Ix/Tc/Verify/Inductive/IotaPattern.lean rename to Ix/Kernel/Verify/Inductive/IotaPattern.lean index 95788cded..7022c09d1 100644 --- a/Ix/Tc/Verify/Inductive/IotaPattern.lean +++ b/Ix/Kernel/Verify/Inductive/IotaPattern.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.RuleApplication +import Ix.Kernel.Verify.Inductive.RuleApplication + +open Ix.Theory (VLevel) /-! # Constructive iota-pattern paths @@ -11,15 +13,15 @@ at a constructor's exact rule index; an off-by-one or reversed-spine adapter cannot satisfy the positional theorem. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named /-- The dependent path of the `index`-th (left-to-right) argument captured by `pattern.varN arity`. -/ -def IotaVarPath (pattern : Lean4Lean.Pattern) : +def IotaVarPath (pattern : Ix.Theory.Named.Pattern) : (arity : Nat) → Fin arity → - (Lean4Lean.Pattern.varN pattern arity).Path + (Ix.Theory.Named.Pattern.varN pattern arity).Path | 0, index => Fin.elim0 index | arity + 1, index => if h : index.val < arity then @@ -30,35 +32,35 @@ def IotaVarPath (pattern : Lean4Lean.Pattern) : /-- Invert a `varN` match to the exact constant-headed argument list and identify every dependent capture path with its positional list entry. -/ theorem iotaVarMatch_spine - {name : Lean.Name} {arity : Nat} {source : Lean4Lean.VExpr} - {levels : List Lean4Lean.VLevel} - {captures : ((Lean4Lean.Pattern.const name).varN arity).Path → - Lean4Lean.VExpr} - (hmatch : Lean4Lean.Pattern.Matches - ((Lean4Lean.Pattern.const name).varN arity) + {name : Lean.Name} {arity : Nat} {source : Ix.Theory.Named.VExpr} + {levels : List Ix.Theory.VLevel} + {captures : ((Ix.Theory.Named.Pattern.const name).varN arity).Path → + Ix.Theory.Named.VExpr} + (hmatch : Ix.Theory.Named.Pattern.Matches + ((Ix.Theory.Named.Pattern.const name).varN arity) source levels captures) : - ∃ arguments : List Lean4Lean.VExpr, + ∃ arguments : List Ix.Theory.Named.VExpr, arguments.length = arity ∧ - source = Lean4Lean.VExpr.appN (.const name levels) arguments ∧ + source = Ix.Theory.Named.VExpr.appN (.const name levels) arguments ∧ ∀ index : Fin arity, arguments[index.val]? = some (captures (IotaVarPath (.const name) arity index)) := by induction arity generalizing source with | zero => - change Lean4Lean.Pattern.Matches (.const name) + change Ix.Theory.Named.Pattern.Matches (.const name) source levels captures at hmatch cases hmatch exact ⟨[], rfl, rfl, fun index => Fin.elim0 index⟩ | succ arity ih => - change Lean4Lean.Pattern.Matches - (.var ((Lean4Lean.Pattern.const name).varN arity)) + change Ix.Theory.Named.Pattern.Matches + (.var ((Ix.Theory.Named.Pattern.const name).varN arity)) source levels captures at hmatch cases hmatch with | var hprefix => rename_i fn argument prefixCaptures obtain ⟨arguments, hlength, rfl, hcaptures⟩ := ih hprefix refine ⟨arguments ++ [argument], by simp [hlength], ?_, ?_⟩ - · rw [Lean4Lean.VExpr.appN_append] + · rw [Ix.Theory.Named.VExpr.appN_append] rfl · intro index by_cases hlt : index.val < arity @@ -117,9 +119,9 @@ def constructorArgumentRhs @[simp] theorem recursorArgumentRhs_apply (recursorName : Lean.Name) (majorIdx : Nat) (constructorName : Lean.Name) (constructorArgs : Nat) - (index : Fin majorIdx) (levels : List Lean4Lean.VLevel) + (index : Fin majorIdx) (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern recursorName majorIdx constructorName - constructorArgs).Path → Lean4Lean.VExpr) : + constructorArgs).Path → Ix.Theory.Named.VExpr) : (recursorArgumentRhs recursorName majorIdx constructorName constructorArgs index).apply levels captures = captures (recursorArgumentPath recursorName majorIdx constructorName @@ -128,39 +130,39 @@ def constructorArgumentRhs @[simp] theorem constructorArgumentRhs_apply (recursorName : Lean.Name) (majorIdx : Nat) (constructorName : Lean.Name) (constructorArgs : Nat) - (index : Fin constructorArgs) (levels : List Lean4Lean.VLevel) + (index : Fin constructorArgs) (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern recursorName majorIdx constructorName - constructorArgs).Path → Lean4Lean.VExpr) : + constructorArgs).Path → Ix.Theory.Named.VExpr) : (constructorArgumentRhs recursorName majorIdx constructorName constructorArgs index).apply levels captures = captures (constructorArgumentPath recursorName majorIdx constructorName constructorArgs index) := rfl /-- A complete iota match exposes both positional application spines. The -constructor universe list is existential because Lean4Lean's pattern result +constructor universe list is existential because Ix.Theory.Named's pattern result retains the recursor levels only. -/ theorem matches_spines {recursorName constructorName : Lean.Name} - {majorIdx constructorArgs : Nat} {source : Lean4Lean.VExpr} - {levels : List Lean4Lean.VLevel} + {majorIdx constructorArgs : Nat} {source : Ix.Theory.Named.VExpr} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern recursorName majorIdx constructorName - constructorArgs).Path → Lean4Lean.VExpr} - (hmatch : Lean4Lean.Pattern.Matches + constructorArgs).Path → Ix.Theory.Named.VExpr} + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs) source levels captures) : ∃ recursorArguments constructorLevels constructorArguments, recursorArguments.length = majorIdx ∧ constructorArguments.length = constructorArgs ∧ source = .app - (Lean4Lean.VExpr.appN (.const recursorName levels) + (Ix.Theory.Named.VExpr.appN (.const recursorName levels) recursorArguments) - (Lean4Lean.VExpr.appN (.const constructorName constructorLevels) + (Ix.Theory.Named.VExpr.appN (.const constructorName constructorLevels) constructorArguments) ∧ (∀ index : Fin majorIdx, recursorArguments[index.val]? = some (captures (recursorArgumentPath recursorName majorIdx constructorName constructorArgs index))) := by - simp only [RecursorIotaPattern, Lean4Lean.SimplePattern.toPattern] at hmatch + simp only [RecursorIotaPattern, Ix.Theory.Named.SimplePattern.toPattern] at hmatch cases hmatch with | app hrecursor hconstructor => obtain ⟨recursorArguments, hrecLength, rfl, hrecCaptures⟩ := @@ -178,20 +180,20 @@ constructor equations as well as the recursor-prefix equations: their generated RHS and their index-consistency checks mention constructor fields. -/ theorem matches_spines_full {recursorName constructorName : Lean.Name} - {majorIdx constructorArgs : Nat} {source : Lean4Lean.VExpr} - {levels : List Lean4Lean.VLevel} + {majorIdx constructorArgs : Nat} {source : Ix.Theory.Named.VExpr} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern recursorName majorIdx constructorName - constructorArgs).Path → Lean4Lean.VExpr} - (hmatch : Lean4Lean.Pattern.Matches + constructorArgs).Path → Ix.Theory.Named.VExpr} + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs) source levels captures) : ∃ recursorArguments constructorLevels constructorArguments, recursorArguments.length = majorIdx ∧ constructorArguments.length = constructorArgs ∧ source = .app - (Lean4Lean.VExpr.appN (.const recursorName levels) + (Ix.Theory.Named.VExpr.appN (.const recursorName levels) recursorArguments) - (Lean4Lean.VExpr.appN (.const constructorName constructorLevels) + (Ix.Theory.Named.VExpr.appN (.const constructorName constructorLevels) constructorArguments) ∧ (∀ index : Fin majorIdx, recursorArguments[index.val]? = some @@ -201,7 +203,7 @@ theorem matches_spines_full constructorArguments[index.val]? = some (captures (constructorArgumentPath recursorName majorIdx constructorName constructorArgs index))) := by - simp only [RecursorIotaPattern, Lean4Lean.SimplePattern.toPattern] at hmatch + simp only [RecursorIotaPattern, Ix.Theory.Named.SimplePattern.toPattern] at hmatch cases hmatch with | app hrecursor hconstructor => obtain ⟨recursorArguments, hrecLength, rfl, hrecCaptures⟩ := @@ -217,4 +219,4 @@ theorem matches_spines_full end RecursorIotaPattern -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/MutualBlockCertificate.lean b/Ix/Kernel/Verify/Inductive/MutualBlockCertificate.lean similarity index 85% rename from Ix/Tc/Verify/Inductive/MutualBlockCertificate.lean rename to Ix/Kernel/Verify/Inductive/MutualBlockCertificate.lean index 9341a10f1..15731b877 100644 --- a/Ix/Tc/Verify/Inductive/MutualBlockCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/MutualBlockCertificate.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.BlockCertificate -import Lean4Lean.Verify.Environment.MutualInductiveFixtures +import Ix.Kernel.Verify.Inductive.BlockCertificate +import Ix.Theory.Named.Verify.Environment.MutualInductiveFixtures /-! # Genuine mutual-block certificate fixture @@ -10,16 +10,16 @@ globally flattened constructors, one generated recursor per family, and five globally flattened iota rules. Recursive fields target both the sibling family and their own family, including one recursive occurrence below a Pi. -This module consumes Lean4Lean's retained L4L-08 certificate through Ix's +This module consumes Ix.Theory.Named's retained Spec-08 certificate through Ix's Theory-only block adapter. Physical Ix ingress, checker execution, catalog linkage, and recursor admission remain separate obligations. -/ -namespace Ix.Tc.MutualTreeCertificateFixture +namespace Ix.Kernel.MutualTreeCertificateFixture -open Lean4Lean -open Lean4Lean.MutualInductiveFixtures -open Lean4Lean.MutualInductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.MutualInductiveFixtures +open Ix.Theory.Named.MutualInductiveReplayFixtures /-- One atomic two-family Theory transaction. -/ def transaction : @@ -28,10 +28,10 @@ def transaction : success := tree_addInductBlockCertified beforeWF := ⟨[], .empty⟩ -/-- The same completed transaction exposed through Lean4Lean's latest +/-- The same completed transaction exposed through Ix.Theory.Named's latest consumer API. In particular, its derived rule-closure and iota-pattern theorems are available to the physical recursor link without an Ix axiom. -/ -def lean4leanCertificate : +def specificationCertificate : treeDecl.BlockCertificate VEnv.empty treeFinalEnv := transaction.toBlockCertificate @@ -80,7 +80,7 @@ theorem breadth : BreadthFacts where treeListTargetsItself := rfl /-- Complete block-wide family/constructor/recursor/rule consequences from -the exact retained L4L-08 transaction. -/ +the exact retained Spec-08 transaction. -/ theorem certifiedFacts : CertifiedBlockGenerationFacts VEnv.empty treeFinalEnv transaction.certificate := @@ -91,4 +91,4 @@ history, rather than two sequential singleton history entries. -/ theorem finalEnvWF : treeFinalEnv.WF := transaction.afterWF -end Ix.Tc.MutualTreeCertificateFixture +end Ix.Kernel.MutualTreeCertificateFixture diff --git a/Ix/Tc/Verify/Inductive/MutualBlockFixture.lean b/Ix/Kernel/Verify/Inductive/MutualBlockFixture.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/MutualBlockFixture.lean rename to Ix/Kernel/Verify/Inductive/MutualBlockFixture.lean index 5d1f29d2f..6c7595844 100644 --- a/Ix/Tc/Verify/Inductive/MutualBlockFixture.lean +++ b/Ix/Kernel/Verify/Inductive/MutualBlockFixture.lean @@ -1,12 +1,12 @@ import Ix.CompileDriver -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.MutualBlockCertificate +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.MutualBlockCertificate /-! # Physical mutual `Tree`/`TreeList` fixture This module compiles the exact kernel metadata already retained by the -Lean4Lean mutual-inductive replay. It therefore exercises the same pure Ix +Ix.Theory.Named mutual-inductive replay. It therefore exercises the same pure Ix compiler used by production instead of maintaining a second handwritten Ixon encoding of the two families, five constructors, two recursors, and five rules. @@ -17,10 +17,10 @@ tables are the physical inputs for the mutual checker and semantic-admission links built in the following modules. -/ -namespace Ix.Tc.MutualTreeFixture +namespace Ix.Kernel.MutualTreeFixture -open Lean4Lean.MutualInductiveFixtures -open Lean4Lean.MutualInductiveReplayFixtures +open Ix.Theory.Named.MutualInductiveFixtures +open Ix.Theory.Named.MutualInductiveReplayFixtures open InductiveConcreteFixture local instance mutualAnonKIdDecidableEq : DecidableEq (KId .anon) := @@ -384,4 +384,4 @@ theorem recursorBlockLoaded : recursorIngressAfter.getBlock? recursorBlockId = some recursorMembers := recursorBlockLoadedNative -end Ix.Tc.MutualTreeFixture +end Ix.Kernel.MutualTreeFixture diff --git a/Ix/Tc/Verify/Inductive/MutualBlockValidation.lean b/Ix/Kernel/Verify/Inductive/MutualBlockValidation.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/MutualBlockValidation.lean rename to Ix/Kernel/Verify/Inductive/MutualBlockValidation.lean index 9b98e0427..100317017 100644 --- a/Ix/Tc/Verify/Inductive/MutualBlockValidation.lean +++ b/Ix/Kernel/Verify/Inductive/MutualBlockValidation.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.SingletonInductive -import Ix.Tc.Verify.Inductive.MutualBlockFixture +import Ix.Kernel.Verify.Check.SingletonInductive +import Ix.Kernel.Verify.Inductive.MutualBlockFixture /-! # Production validation of the mutual `Tree`/`TreeList` blocks @@ -10,7 +10,7 @@ by the real recursor-block checker for the separately owned physical block. No semantic certificate or oracle participates in either execution. -/ -namespace Ix.Tc.MutualTreeFixture +namespace Ix.Kernel.MutualTreeFixture local instance validationAnonKIdDecidableEq : DecidableEq (KId .anon) := fun left right => @@ -167,4 +167,4 @@ theorem endToEndExecution : EndToEndExecution where familyKernel := familyKernelRun recursorKernel := recursorKernelRun -end Ix.Tc.MutualTreeFixture +end Ix.Kernel.MutualTreeFixture diff --git a/Ix/Tc/Verify/Inductive/MutualFamily.lean b/Ix/Kernel/Verify/Inductive/MutualFamily.lean similarity index 94% rename from Ix/Tc/Verify/Inductive/MutualFamily.lean rename to Ix/Kernel/Verify/Inductive/MutualFamily.lean index 5501508ea..80b18fa7f 100644 --- a/Ix/Tc/Verify/Inductive/MutualFamily.lean +++ b/Ix/Kernel/Verify/Inductive/MutualFamily.lean @@ -1,10 +1,10 @@ -import Ix.Tc.Verify.Check.BlockAcceptance -import Ix.Tc.Verify.Inductive.BlockCertificate +import Ix.Kernel.Verify.Check.BlockAcceptance +import Ix.Kernel.Verify.Inductive.BlockCertificate /-! # Certified mutual-family admission -A Lean4Lean block certificate owns one atomic semantic transaction for every +A Ix.Theory.Named block certificate owns one atomic semantic transaction for every family and constructor in a mutual declaration. This module supplies the Ix-facing representation boundary for the corresponding physical family/constructor block. It does not split the source declaration into @@ -15,9 +15,9 @@ physical Ix block, although their Theory constants and equations are already installed by the same source transaction. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstant VConstVal VEnv VInductDecl) +open Ix.Theory.Named (VConstant VConstVal VEnv VInductDecl) /-- Exact concrete kinds permitted in the family/constructor half of a mutual-inductive transaction. -/ @@ -55,7 +55,7 @@ end KConst.IsMutualFamilyMember /-- A concrete member is tied either to one source family or to one source constructor of the complete mutual declaration. The disjunction retains -the exact source inventory membership used by Lean4Lean's lookup theorems. -/ +the exact source inventory membership used by Ix.Theory.Named's lookup theorems. -/ def MutualSourceMember (source : VInductDecl) (name : Lean.Name) (constant : VConstant) : Prop := (∃ family, family ∈ source.types ∧ name = family.name ∧ @@ -89,7 +89,7 @@ structure MutualFamilyCatalogLink (trProj : RawProjRel) namespace MutualFamilyCatalogLink /-- Derive the exact Theory lookup and constant-WF facts from the current -Lean4Lean consumer certificate. -/ +Ix.Theory.Named consumer certificate. -/ theorem translateMember {trProj : RawProjRel} {world : VerifyWorld} {source : VInductDecl} {after : VEnv} {tx : CertifiedBlockGenerationTransaction source world.venv after} @@ -154,4 +154,4 @@ theorem transition {trProj : RawProjRel} {world : VerifyWorld} end MutualFamilyCatalogLink -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/MutualFamilyAdmission.lean b/Ix/Kernel/Verify/Inductive/MutualFamilyAdmission.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/MutualFamilyAdmission.lean rename to Ix/Kernel/Verify/Inductive/MutualFamilyAdmission.lean index 1e90ad411..078de4a84 100644 --- a/Ix/Tc/Verify/Inductive/MutualFamilyAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/MutualFamilyAdmission.lean @@ -1,11 +1,11 @@ -import Ix.Tc.Verify.Inductive.MutualBlockValidation -import Ix.Tc.Verify.Inductive.MutualFamily +import Ix.Kernel.Verify.Inductive.MutualBlockValidation +import Ix.Kernel.Verify.Inductive.MutualFamily /-! # Atomic mutual `Tree`/`TreeList` family admission This module joins the production compiler/ingress/checker witness to the -single Lean4Lean `Tree`/`TreeList` block transaction. The seven physical +single Ix.Theory.Named `Tree`/`TreeList` block transaction. The seven physical family/constructor declarations are interpreted in the complete source inventory and admitted in one atomic semantic transition. @@ -14,11 +14,11 @@ semantic constants and rules are already installed by this transaction; the next recursor-link module supplies their rule and pattern provenance. -/ -namespace Ix.Tc.MutualTreeFixture +namespace Ix.Kernel.MutualTreeFixture -open Lean4Lean -open Lean4Lean.MutualInductiveFixtures -open Lean4Lean.MutualInductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.MutualInductiveFixtures +open Ix.Theory.Named.MutualInductiveReplayFixtures open MutualTreeCertificateFixture local instance admissionAnonKIdDecidableEq : DecidableEq (KId .anon) := @@ -677,7 +677,7 @@ structure MutualFamilyAtomicClosure : Prop where execution : EndToEndExecution exactFamily : ExactCheckBlock world familyBlockId familyMembers .inductive' exactRecursor : ExactCheckBlock world recursorBlockId recursorMembers .recursor - ruleClosure : lean4leanCertificate.generation.RuleClosure + ruleClosure : specificationCertificate.generation.RuleClosure familyAdmission : AtomicBlockAdmission RawProjRel.none world familyAcceptedWorld familyBlockId familyMembers .inductive' @@ -687,8 +687,8 @@ theorem mutualFamilyAtomicClosure : MutualFamilyAtomicClosure where execution := endToEndExecution exactFamily := exactFamilyBlock exactRecursor := exactRecursorBlock - ruleClosure := lean4leanCertificate.ruleClosure + ruleClosure := specificationCertificate.ruleClosure familyAdmission := familyAtomicAdmission accepted := familyBlockAccepted -end Ix.Tc.MutualTreeFixture +end Ix.Kernel.MutualTreeFixture diff --git a/Ix/Tc/Verify/Inductive/MutualRecursor.lean b/Ix/Kernel/Verify/Inductive/MutualRecursor.lean similarity index 94% rename from Ix/Tc/Verify/Inductive/MutualRecursor.lean rename to Ix/Kernel/Verify/Inductive/MutualRecursor.lean index 3af3791c8..87edab147 100644 --- a/Ix/Tc/Verify/Inductive/MutualRecursor.lean +++ b/Ix/Kernel/Verify/Inductive/MutualRecursor.lean @@ -1,21 +1,21 @@ -import Ix.Tc.Verify.Check.PreTranslationCompatibility -import Ix.Tc.Verify.Inductive.BlockPatternSoundness -import Ix.Tc.Verify.Inductive.MutualFamily +import Ix.Kernel.Verify.Check.PreTranslationCompatibility +import Ix.Kernel.Verify.Inductive.BlockPatternSoundness +import Ix.Kernel.Verify.Inductive.MutualFamily /-! # Generated recursors of a certified mutual block This module contains the reusable, representation-neutral part of the second -physical block in Ix's mutual-inductive layout. Lean4Lean installs all family +physical block in Ix's mutual-inductive layout. Ix.Theory.Named installs all family recursors and globally flattened equations in the original atomic source transaction; Ix later checks a separately owned recursor block. The lemmas below retain the exact global generated-rule position while permitting each physical recursor to dispatch by its family-local constructor index. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstant VConstVal VDefEq VEnv VExpr VInductDecl) +open Ix.Theory.Named (VConstant VConstVal VDefEq VEnv VExpr VInductDecl) namespace CertifiedMutualGeneration @@ -51,11 +51,11 @@ namespace CertifiedMutualRecursor variable {source : VInductDecl} {before after : VEnv} -/-- Repackage Lean4Lean's exact generated RHS/check payload as the finite +/-- Repackage Ix.Theory.Named's exact generated RHS/check payload as the finite pattern record consumed by Ix. `ruleIndex` is family-local (the physical dispatch index); `index` remains the global flattened equation position. `argumentArity` is the one explicit representation equality connecting the -serialized parameter/field split to Lean4Lean's pattern arity. -/ +serialized parameter/field split to Ix.Theory.Named's pattern arity. -/ def generatedPattern (certificate : source.BlockCertificate before after) {index : Nat} {constructor : VInductDecl.NormalizedBlockCtor} @@ -181,4 +181,4 @@ theorem generatedPatternRel end CertifiedMutualRecursor -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/MutualRecursorAdmission.lean b/Ix/Kernel/Verify/Inductive/MutualRecursorAdmission.lean similarity index 92% rename from Ix/Tc/Verify/Inductive/MutualRecursorAdmission.lean rename to Ix/Kernel/Verify/Inductive/MutualRecursorAdmission.lean index 721ec6306..f2368aad5 100644 --- a/Ix/Tc/Verify/Inductive/MutualRecursorAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/MutualRecursorAdmission.lean @@ -1,11 +1,11 @@ -import Ix.Tc.Verify.Inductive.MutualFamilyAdmission -import Ix.Tc.Verify.Inductive.MutualRecursor -import Ix.Tc.Verify.Upstream.Pending +import Ix.Kernel.Verify.Inductive.MutualFamilyAdmission +import Ix.Kernel.Verify.Inductive.MutualRecursor +import Ix.Kernel.Verify.Frontier.Pending /-! # Conditional atomic admission of the mutual `Tree`/`TreeList` recursors -The original Lean4Lean transaction has already installed both generated +The original Ix.Theory.Named transaction has already installed both generated recursors and all five globally flattened equations. This module proves the complete Ix-side correspondence for the separately owned two-member physical recursor block: exact family-local dispatch, global equation positions, @@ -13,27 +13,27 @@ structural translations, constructor metadata, ownership, and admission. The reversed-order semantic certificate and generated-pattern soundness are conditional on two fixture-specific Theory witnesses in -`Verify.Upstream.Pending`: family-permutation preservation of generation WF, +`Verify.Frontier.Pending`: family-permutation preservation of generation WF, and the certified rule-pattern conclusion. None of the Ix representation, ingress, ownership, or production-execution facts are assumed there. -/ -namespace Ix.Tc.MutualTreeFixture +namespace Ix.Kernel.MutualTreeFixture -open Lean4Lean -open Lean4Lean.MutualInductiveFixtures -open Lean4Lean.MutualInductiveReplayFixtures +open Ix.Theory.Named +open Ix.Theory.Named.MutualInductiveFixtures +open Ix.Theory.Named.MutualInductiveReplayFixtures open MutualTreeCertificateFixture /- The physical compiler canonically orders this SCC as `TreeList, Tree`. These private aliases keep every rule index below tied to the exact reversed -Lean4Lean descriptor certified in the quarantined upstream module. -/ +Ix.Theory.Named descriptor certified in the quarantined upstream module. -/ private abbrev treeGeneration := - Upstream.Pending.mutualTreePhysicalGeneration -private abbrev lean4leanCertificate := - Upstream.Pending.mutualTreePhysicalCertificate + Frontier.Pending.mutualTreePhysicalGeneration +private abbrev specificationCertificate := + Frontier.Pending.mutualTreePhysicalCertificate private abbrev treeFinalEnv := - Upstream.Pending.mutualTreePhysicalFinalEnv + Frontier.Pending.mutualTreePhysicalFinalEnv local instance anonKIdDecidableEq : DecidableEq (KId .anon) := fun left right => @@ -266,7 +266,7 @@ theorem recursorRepresentationFacts : RecursorRepresentationFacts := recursorRepresentationFactsNative private theorem certificateGeneration_eq : - lean4leanCertificate.generation = treeGeneration := rfl + specificationCertificate.generation = treeGeneration := rfl private theorem treeRecTypeRawNative : RawExprRel (uvars := treeRecConcrete.lvls.toNat) treeFinalEnv nameOf @@ -370,8 +370,8 @@ private theorem upgradeRule nameOf RawProjRel.none [] rule.rhs (treeGeneration.rule index constructor).rhs := by let pre := raw.toPreBinderCore_of_scoped binderCore hscoped hsize - have ruleWF := (lean4leanCertificate.recursorRuleFacts entry).wf - exact pre.upgradeBinderCoreOfWF lean4leanCertificate.afterWF + have ruleWF := (specificationCertificate.recursorRuleFacts entry).wf + exact pre.upgradeBinderCoreOfWF specificationCertificate.afterWF (Delta := []) (hDelta := trivial) binderCore ⟨_, ruleWF.2⟩ theorem leafRuleTyped : @@ -443,35 +443,35 @@ theorem treeListRecRaw : theorem treeRecLookup : treeFinalEnv.constants ``Tree.rec = some treeRecSource.toVConstant := by - have lookup := lean4leanCertificate.recursorLookup + have lookup := specificationCertificate.recursorLookup (List.mem_of_getElem? treeRecSourceAt) simpa [recursorRepresentationFacts.treeRecName] using lookup theorem treeListRecLookup : treeFinalEnv.constants ``TreeList.rec = some treeListRecSource.toVConstant := by - have lookup := lean4leanCertificate.recursorLookup + have lookup := specificationCertificate.recursorLookup (List.mem_of_getElem? treeListRecSourceAt) simpa [recursorRepresentationFacts.treeListRecName] using lookup theorem leafRegistered : RegisteredRecursorRuleRhsRel treeFinalEnv nameOf RawProjRel.none treeRecId treeRecConcrete leafRule (treeGeneration.rule 2 leafNormalized) := - CertifiedMutualRecursor.registeredRule lean4leanCertificate treeRecRaw + CertifiedMutualRecursor.registeredRule specificationCertificate treeRecRaw treeRecLookup recursorRepresentationFacts.leafRecursorName.symm leafEntry leafRuleRaw leafRuleTyped theorem nodeRegistered : RegisteredRecursorRuleRhsRel treeFinalEnv nameOf RawProjRel.none treeRecId treeRecConcrete nodeRule (treeGeneration.rule 3 nodeNormalized) := - CertifiedMutualRecursor.registeredRule lean4leanCertificate treeRecRaw + CertifiedMutualRecursor.registeredRule specificationCertificate treeRecRaw treeRecLookup recursorRepresentationFacts.nodeRecursorName.symm nodeEntry nodeRuleRaw nodeRuleTyped theorem branchRegistered : RegisteredRecursorRuleRhsRel treeFinalEnv nameOf RawProjRel.none treeRecId treeRecConcrete branchRule (treeGeneration.rule 4 branchNormalized) := - CertifiedMutualRecursor.registeredRule lean4leanCertificate treeRecRaw + CertifiedMutualRecursor.registeredRule specificationCertificate treeRecRaw treeRecLookup recursorRepresentationFacts.branchRecursorName.symm branchEntry branchRuleRaw branchRuleTyped @@ -479,7 +479,7 @@ theorem nilRegistered : RegisteredRecursorRuleRhsRel treeFinalEnv nameOf RawProjRel.none treeListRecId treeListRecConcrete nilRule (treeGeneration.rule 0 nilNormalized) := - CertifiedMutualRecursor.registeredRule lean4leanCertificate treeListRecRaw + CertifiedMutualRecursor.registeredRule specificationCertificate treeListRecRaw treeListRecLookup recursorRepresentationFacts.nilRecursorName.symm nilEntry nilRuleRaw nilRuleTyped @@ -487,34 +487,34 @@ theorem consRegistered : RegisteredRecursorRuleRhsRel treeFinalEnv nameOf RawProjRel.none treeListRecId treeListRecConcrete consRule (treeGeneration.rule 1 consNormalized) := - CertifiedMutualRecursor.registeredRule lean4leanCertificate treeListRecRaw + CertifiedMutualRecursor.registeredRule specificationCertificate treeListRecRaw treeListRecLookup recursorRepresentationFacts.consRecursorName.symm consEntry consRuleRaw consRuleTyped /-! ## Exact generated patterns -/ def leafPattern : RecursorRulePattern := - CertifiedMutualRecursor.generatedPattern lean4leanCertificate + CertifiedMutualRecursor.generatedPattern specificationCertificate leafEntry treeLeafId 0 1 1 recursorRepresentationFacts.leafArgumentArity def nodePattern : RecursorRulePattern := - CertifiedMutualRecursor.generatedPattern lean4leanCertificate + CertifiedMutualRecursor.generatedPattern specificationCertificate nodeEntry treeNodeId 1 1 1 recursorRepresentationFacts.nodeArgumentArity def branchPattern : RecursorRulePattern := - CertifiedMutualRecursor.generatedPattern lean4leanCertificate + CertifiedMutualRecursor.generatedPattern specificationCertificate branchEntry treeBranchId 2 1 1 recursorRepresentationFacts.branchArgumentArity def nilPattern : RecursorRulePattern := - CertifiedMutualRecursor.generatedPattern lean4leanCertificate + CertifiedMutualRecursor.generatedPattern specificationCertificate nilEntry treeListNilId 0 1 0 recursorRepresentationFacts.nilArgumentArity def consPattern : RecursorRulePattern := - CertifiedMutualRecursor.generatedPattern lean4leanCertificate + CertifiedMutualRecursor.generatedPattern specificationCertificate consEntry treeListConsId 1 1 2 recursorRepresentationFacts.consArgumentArity @@ -616,40 +616,40 @@ private theorem consPatternMetadata : theorem leafPatternRel : RawRecursorRulePatternRel treeFinalEnv catalog nameOf treeRecId treeRecConcrete leafRule leafPattern := - CertifiedMutualRecursor.generatedPatternRel lean4leanCertificate - Upstream.Pending.mutualTreePhysicalRulePatternSound + CertifiedMutualRecursor.generatedPatternRel specificationCertificate + Frontier.Pending.mutualTreePhysicalRulePatternSound leafEntry treeLeafId 0 1 1 recursorRepresentationFacts.leafArgumentArity leafPatternMetadata theorem nodePatternRel : RawRecursorRulePatternRel treeFinalEnv catalog nameOf treeRecId treeRecConcrete nodeRule nodePattern := - CertifiedMutualRecursor.generatedPatternRel lean4leanCertificate - Upstream.Pending.mutualTreePhysicalRulePatternSound + CertifiedMutualRecursor.generatedPatternRel specificationCertificate + Frontier.Pending.mutualTreePhysicalRulePatternSound nodeEntry treeNodeId 1 1 1 recursorRepresentationFacts.nodeArgumentArity nodePatternMetadata theorem branchPatternRel : RawRecursorRulePatternRel treeFinalEnv catalog nameOf treeRecId treeRecConcrete branchRule branchPattern := - CertifiedMutualRecursor.generatedPatternRel lean4leanCertificate - Upstream.Pending.mutualTreePhysicalRulePatternSound + CertifiedMutualRecursor.generatedPatternRel specificationCertificate + Frontier.Pending.mutualTreePhysicalRulePatternSound branchEntry treeBranchId 2 1 1 recursorRepresentationFacts.branchArgumentArity branchPatternMetadata theorem nilPatternRel : RawRecursorRulePatternRel treeFinalEnv catalog nameOf treeListRecId treeListRecConcrete nilRule nilPattern := - CertifiedMutualRecursor.generatedPatternRel lean4leanCertificate - Upstream.Pending.mutualTreePhysicalRulePatternSound + CertifiedMutualRecursor.generatedPatternRel specificationCertificate + Frontier.Pending.mutualTreePhysicalRulePatternSound nilEntry treeListNilId 0 1 0 recursorRepresentationFacts.nilArgumentArity nilPatternMetadata theorem consPatternRel : RawRecursorRulePatternRel treeFinalEnv catalog nameOf treeListRecId treeListRecConcrete consRule consPattern := - CertifiedMutualRecursor.generatedPatternRel lean4leanCertificate - Upstream.Pending.mutualTreePhysicalRulePatternSound + CertifiedMutualRecursor.generatedPatternRel specificationCertificate + Frontier.Pending.mutualTreePhysicalRulePatternSound consEntry treeListConsId 1 1 2 recursorRepresentationFacts.consArgumentArity consPatternMetadata @@ -657,11 +657,11 @@ theorem consPatternRel : /-- Historical adapter for the exact `TreeList, Tree` certificate. This is the same computed generation and post-environment exposed by the current -Lean4Lean consumer package in `Upstream.Pending`. -/ +Ix.Theory.Named consumer package in `Frontier.Pending`. -/ def physicalTransaction : CertifiedBlockGenerationTransaction - Upstream.Pending.mutualTreePhysicalDecl VEnv.empty treeFinalEnv where - certificate := Upstream.Pending.mutualTreePhysicalSemantic - success := Upstream.Pending.mutualTreePhysicalSuccess + Frontier.Pending.mutualTreePhysicalDecl VEnv.empty treeFinalEnv where + certificate := Frontier.Pending.mutualTreePhysicalSemantic + success := Frontier.Pending.mutualTreePhysicalSuccess beforeWF := ⟨[], .empty⟩ private theorem physicalTreeTypeRawNative : @@ -750,15 +750,15 @@ theorem physicalConsTypeRaw : structure PhysicalSourceMembershipFacts : Prop where leaf : treeLeafSource ∈ - Upstream.Pending.mutualTreePhysicalDecl.blockConstructorConstants + Frontier.Pending.mutualTreePhysicalDecl.blockConstructorConstants node : treeNodeSource ∈ - Upstream.Pending.mutualTreePhysicalDecl.blockConstructorConstants + Frontier.Pending.mutualTreePhysicalDecl.blockConstructorConstants branch : treeBranchSource ∈ - Upstream.Pending.mutualTreePhysicalDecl.blockConstructorConstants + Frontier.Pending.mutualTreePhysicalDecl.blockConstructorConstants nil : treeListNilSource ∈ - Upstream.Pending.mutualTreePhysicalDecl.blockConstructorConstants + Frontier.Pending.mutualTreePhysicalDecl.blockConstructorConstants cons : treeListConsSource ∈ - Upstream.Pending.mutualTreePhysicalDecl.blockConstructorConstants + Frontier.Pending.mutualTreePhysicalDecl.blockConstructorConstants private theorem physicalSourceMembershipFactsNative : PhysicalSourceMembershipFacts := by @@ -784,7 +784,7 @@ def physicalFamilyLink : nameOf_treeList, familyMemberShapeFacts.treeListUvars, physicalTreeListTypeRaw, .inl ⟨treeListType, by - simp [Upstream.Pending.mutualTreePhysicalDecl], rfl, rfl⟩⟩ + simp [Frontier.Pending.mutualTreePhysicalDecl], rfl, rfl⟩⟩ · exact ⟨treeListNilConcrete, ``TreeList.nil, treeListNilSource.toVConstant, catalog_nil, familyMemberShapeFacts.nilKind, nameOf_nil, @@ -801,7 +801,7 @@ def physicalFamilyLink : catalog_tree, familyMemberShapeFacts.treeKind, nameOf_tree, familyMemberShapeFacts.treeUvars, physicalTreeTypeRaw, .inl ⟨treeType, by - simp [Upstream.Pending.mutualTreePhysicalDecl], rfl, rfl⟩⟩ + simp [Frontier.Pending.mutualTreePhysicalDecl], rfl, rfl⟩⟩ · exact ⟨treeLeafConcrete, ``Tree.leaf, treeLeafSource.toVConstant, catalog_leaf, familyMemberShapeFacts.leafKind, nameOf_leaf, @@ -932,7 +932,7 @@ private theorem treeListRecPattern {index : Nat} {rule : RecRule .anon} private theorem treeRecSemanticEntry : TrustedCatalogEntry RawProjRel.none catalog nameOf treeFinalEnv treeRecId := .ambient catalog_treeRec treeRecRaw treeRecLookup - (lean4leanCertificate.afterWF.ordered.constWF treeRecLookup) + (specificationCertificate.afterWF.ordered.constWF treeRecLookup) (fun {_} hrule => treeRecRule hrule) (fun {_ _} hrule => treeRecPattern hrule) @@ -940,7 +940,7 @@ private theorem treeListRecSemanticEntry : TrustedCatalogEntry RawProjRel.none catalog nameOf treeFinalEnv treeListRecId := .ambient catalog_treeListRec treeListRecRaw treeListRecLookup - (lean4leanCertificate.afterWF.ordered.constWF treeListRecLookup) + (specificationCertificate.afterWF.ordered.constWF treeListRecLookup) (fun {_} hrule => treeListRecRule hrule) (fun {_ _} hrule => treeListRecPattern hrule) @@ -1025,7 +1025,7 @@ rule-pattern soundness. -/ structure MutualRecursorConditionalClosure : Prop where execution : EndToEndExecution family : MutualFamilyAtomicClosure - patternSound : CertifiedBlockRulePatternSound lean4leanCertificate + patternSound : CertifiedBlockRulePatternSound specificationCertificate physicalFamilyAdmission : AtomicBlockAdmission RawProjRel.none world physicalFamilyAcceptedWorld familyBlockId familyMembers .inductive' @@ -1039,7 +1039,7 @@ theorem mutualRecursorConditionalClosure : MutualRecursorConditionalClosure where execution := endToEndExecution family := mutualFamilyAtomicClosure - patternSound := Upstream.Pending.mutualTreePhysicalRulePatternSound + patternSound := Frontier.Pending.mutualTreePhysicalRulePatternSound physicalFamilyAdmission := physicalFamilyAtomicAdmission recursorAdmission := familyRecursorAtomicAdmission familyAccepted := @@ -1047,4 +1047,4 @@ theorem mutualRecursorConditionalClosure : familyRecursorAtomicAdmission.promotion.le recursorAccepted := familyRecursorBlockAccepted -end Ix.Tc.MutualTreeFixture +end Ix.Kernel.MutualTreeFixture diff --git a/Ix/Tc/Verify/Inductive/NestedAdmission.lean b/Ix/Kernel/Verify/Inductive/NestedAdmission.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/NestedAdmission.lean rename to Ix/Kernel/Verify/Inductive/NestedAdmission.lean index d5e632520..db073465b 100644 --- a/Ix/Tc/Verify/Inductive/NestedAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/NestedAdmission.lean @@ -1,19 +1,19 @@ -import Ix.Tc.Verify.Inductive.NestedSemanticTransaction +import Ix.Kernel.Verify.Inductive.NestedSemanticTransaction /-! # Atomic admission of the nested `LeanTree` source block -This module joins the concrete Ix block to the completed Lean4Lean nested +This module joins the concrete Ix block to the completed Ix.Theory.Named nested transaction. The physical block contains only the stored `Tree` family and -`node` constructor. Lean4Lean's transaction independently flattens the +`node` constructor. Ix.Theory.Named's transaction independently flattens the nested dependency, checks the restored constants/equations, removes every auxiliary name, and commits the source family, constructor, two recursors, and two rules at one public `addInductNested` boundary. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture -open Lean4Lean +open Ix.Theory.Named open InductiveConcreteFixture local instance nestedAdmissionAddressDecidableEq : DecidableEq Address := @@ -322,10 +322,10 @@ structure NestedSemanticTransactionClosure : Prop where groups rootGroup.addrs #[treeId.addr] checkerMethods nestedWhnfAfter positivityAfter flatNodeValidation : - Lean4Lean.AddInductive.checkConstructorType leanFlatStats false 0 + Ix.Theory.Named.AddInductive.checkConstructorType leanFlatStats false 0 leanFlatNode.name leanFlatNode.type leanFlatConstructorContext = .ok () flatWrapValidation : - Lean4Lean.AddInductive.checkConstructorType leanFlatStats false 1 + Ix.Theory.Named.AddInductive.checkConstructorType leanFlatStats false 1 leanFlatWrap.name leanFlatWrap.type leanFlatConstructorContext = .ok () semantic : SemanticTreeTransactionFacts ruleMetadata : @@ -352,4 +352,4 @@ theorem nestedSemanticTransactionClosure : admission := nestedFamilyAtomicAdmission accepted := nestedFamilyBlockAccepted -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedAuxiliaryExpansion.lean b/Ix/Kernel/Verify/Inductive/NestedAuxiliaryExpansion.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/NestedAuxiliaryExpansion.lean rename to Ix/Kernel/Verify/Inductive/NestedAuxiliaryExpansion.lean index e45a41f02..419c7a945 100644 --- a/Ix/Tc/Verify/Inductive/NestedAuxiliaryExpansion.lean +++ b/Ix/Kernel/Verify/Inductive/NestedAuxiliaryExpansion.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.NestedPositivityTraversal +import Ix.Kernel.Verify.Inductive.NestedPositivityTraversal /-! # Nested positivity requests and flat-block auxiliary expansion @@ -18,7 +18,7 @@ small representation bridge that later block traversal must derive from the two executions of the same loaded header. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Equality lawfulness is needed only for the physical `auxSeen` membership proofs in this module. Keep it local so the broader positivity traversal @@ -1359,4 +1359,4 @@ theorem CompleteNestedPositivityApplicationTrace.producedRequest simpa only [NestedPositivityAuxiliaryRequest.ProducedBy] using trace.auxiliaryRequest -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/NestedAuxiliaryPositivity.lean b/Ix/Kernel/Verify/Inductive/NestedAuxiliaryPositivity.lean similarity index 93% rename from Ix/Tc/Verify/Inductive/NestedAuxiliaryPositivity.lean rename to Ix/Kernel/Verify/Inductive/NestedAuxiliaryPositivity.lean index 34de2e3a9..1157bc3ec 100644 --- a/Ix/Tc/Verify/Inductive/NestedAuxiliaryPositivity.lean +++ b/Ix/Kernel/Verify/Inductive/NestedAuxiliaryPositivity.lean @@ -1,18 +1,18 @@ -import Ix.Tc.Verify.Inductive.NestedPositivityTransport +import Ix.Kernel.Verify.Inductive.NestedPositivityTransport /-! # Positivity of a generated nested auxiliary The outer `Tree.node` field is checked by Ix as the nested application -`Box Tree`, while Lean4Lean rewrites that application to a generated flat +`Box Tree`, while Ix.Theory.Named rewrites that application to a generated flat family. This module follows the other half of that transformation: the production nested traversal copies `Box.wrap`, strips its `Box` parameter, substitutes `Tree`, and checks the resulting `Tree` field. The retained -execution is transported to the direct recursive field of Lean4Lean's copied +execution is transported to the direct recursive field of Ix.Theory.Named's copied auxiliary constructor. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture local instance auxiliaryAddressDecidableEq : DecidableEq Address := AnonStructural.addressDecidableEq @@ -421,17 +421,17 @@ theorem nestedAuxiliaryFieldProductionTrace : private theorem leanTreeCandidateWhnfNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run leanFlatConstructorContext.env + (Ix.Theory.Named.TypeChecker.M.run leanFlatConstructorContext.env leanFlatConstructorContext.safety leanFlatConstructorContext.lctx leanFlatConstructorContext.lparams leanFlatConstructorContext.fuel - (Lean4Lean.TypeChecker.whnf leanTreeExpr)) + (Ix.Theory.Named.TypeChecker.whnf leanTreeExpr)) leanTreeExpr = true := by native_decide theorem leanTreeCandidateWhnf : - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanFlatConstructorContext, leanTreeExpr, leanTreeExpr⟩ := by - unfold Lean4Lean.AddInductive.CandidateWhnfStep.Valid + unfold Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check leanTreeCandidateWhnfNative @@ -440,14 +440,14 @@ constructor. Its state is the state selected by production after reducing the copied constructor telescope, rather than a separately initialized fixture state. -/ inductive NestedAuxiliaryPositivitySourceRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | domain : NestedAuxiliaryPositivitySourceRel auxiliaryFieldWhnfAfter leanFlatConstructorContext treeExpr leanTreeExpr /-- Exact post-WHNF syntax relation for the recursive `Tree` field. -/ inductive NestedAuxiliaryPositivityResultRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | domain {ixResult : KExpr .anon} (candidate : CandidateSyntaxRel nestedCandidateNameOf @@ -460,15 +460,15 @@ inductive NestedAuxiliaryPositivityResultRel : private theorem nestedAuxiliaryRootFree {ixState : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource : KExpr .anon} {leanSource : Lean.Expr} (relation : NestedAuxiliaryPositivitySourceRel ixState leanContext ixSource leanSource) (free : exprMentionsAnyAddr ixSource #[treeId.addr] = false) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = false := by cases relation rw [auxiliaryTreeMentionsRootNative] at free @@ -477,7 +477,7 @@ private theorem nestedAuxiliaryRootFree set_option maxRecDepth 100000 in private theorem nestedAuxiliaryWhnf {ixBefore ixAfter : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource ixResult : KExpr .anon} {leanSource : Lean.Expr} (relation : NestedAuxiliaryPositivitySourceRel ixBefore leanContext ixSource leanSource) @@ -485,7 +485,7 @@ private theorem nestedAuxiliaryWhnf (run : (RecM.whnf ixSource).run checkerMethods ixBefore = .ok ixResult ixAfter) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ NestedAuxiliaryPositivityResultRel ixAfter leanContext ixResult leanResult := by @@ -500,13 +500,13 @@ private theorem nestedAuxiliaryMentions (relation : NestedAuxiliaryPositivitySourceRel ixState leanContext ixExpr leanExpr) : exprMentionsAnyAddr ixExpr #[treeId.addr] = - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanExpr := by + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanExpr := by cases relation rw [auxiliaryTreeMentionsRootNative, leanTreeOccurs] private theorem nestedAuxiliaryForall {ixState : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixName : Mode.anon.F Name} {ixBinder : Mode.anon.F Lean.BinderInfo} {ixDomain ixBody : KExpr .anon} {ixInfo : ExprInfo .anon} {leanExpr : Lean.Expr} @@ -522,14 +522,14 @@ private theorem nestedAuxiliaryForall .ok (ixOpen, ixFVar) ixAfterOpen → NestedAuxiliaryPositivitySourceRel ixAfterOpen (leanContext.pushLocalDecl leanName leanBinder - (Lean4Lean.AddInductive.consumeTypeAnnotations leanDomain)) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanDomain)) ixOpen (leanBody.instantiate1 leanContext.freshExpr) := by cases relation with | domain candidate => cases candidate private theorem nestedAuxiliaryDirect {ixState : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixResult : KExpr .anon} {leanResult : Lean.Expr} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} {args : Array (KExpr .anon)} @@ -542,10 +542,10 @@ private theorem nestedAuxiliaryDirect (_valid : ValidPositiveRecursiveApplication id us args traceGroups #[treeId.addr] checkerMethods ixState final) : ∃ targetIdx, - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = true ∧ leanResult.isForall = false ∧ - Lean4Lean.AddInductive.isValidIndApp? leanFlatStats leanResult = + Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanResult = some targetIdx := by cases relation exact ⟨0, leanTreeOccurs, rfl, leanTreeTarget⟩ @@ -592,9 +592,9 @@ theorem nestedAuxiliaryFieldProductionTraceAt (fuel : Nat) : active valid⟩ /-- The production-derived direct field trace transported at any positive -Lean4Lean positivity fuel. -/ +Ix.Theory.Named positivity fuel. -/ theorem nestedAuxiliaryConstructorPositivityTraceAt (fuel : Nat) : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace leanFlatStats + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace leanFlatStats leanFlatWrap.name 0 leanFlatConstructorContext leanTreeExpr (fuel + 1)) := by rcases nestedAuxiliaryFieldProductionTraceAt fuel with @@ -603,9 +603,9 @@ theorem nestedAuxiliaryConstructorPositivityTraceAt (fuel : Nat) : nestedAuxiliaryPositivityTransport trace root .domain /-- The inner call retained from production's nested traversal constructs the -exact Lean4Lean positivity trace for the copied auxiliary field. -/ +exact Ix.Theory.Named positivity trace for the copied auxiliary field. -/ theorem nestedAuxiliaryConstructorPositivityTrace : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace leanFlatStats + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace leanFlatStats leanFlatWrap.name 0 leanFlatConstructorContext leanTreeExpr (positivityFuel - 3)) := by rcases nestedAuxiliaryFieldProductionTrace with @@ -613,4 +613,4 @@ theorem nestedAuxiliaryConstructorPositivityTrace : exact FlatPositivityTraceTransport.constructorPositivityTrace nestedAuxiliaryPositivityTransport trace root .domain -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedBlockCertificate.lean b/Ix/Kernel/Verify/Inductive/NestedBlockCertificate.lean similarity index 95% rename from Ix/Tc/Verify/Inductive/NestedBlockCertificate.lean rename to Ix/Kernel/Verify/Inductive/NestedBlockCertificate.lean index dd24863b7..0de4f579f 100644 --- a/Ix/Tc/Verify/Inductive/NestedBlockCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/NestedBlockCertificate.lean @@ -1,10 +1,10 @@ -import Ix.Tc.Verify.Check.BlockAcceptance -import Lean4Lean.Theory.Typing.InductiveCertificate +import Ix.Kernel.Verify.Check.BlockAcceptance +import Ix.Theory.Named.Typing.InductiveCertificate /-! # Certified nested-block transactions -This is the Ix consumer boundary for Lean4Lean's `NestedBlockCertificate`. +This is the Ix consumer boundary for Ix.Theory.Named's `NestedBlockCertificate`. The Theory transaction stores the original source families and constructors, then restores every generated recursor and rule before committing them. The Ix-facing link below covers only the physical source block; generated @@ -15,9 +15,9 @@ after an exhaustive physical catalog link and an `ExactCheckBlock` prove that the one nested transaction describes the complete checked block. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstant VConstVal VEnv VInductDecl) +open Ix.Theory.Named (VConstant VConstVal VEnv VInductDecl) /-- Exact concrete kinds permitted in the stored source half of a nested transaction. -/ @@ -143,4 +143,4 @@ theorem transition {trProj : RawProjRel} {world : VerifyWorld} end NestedFamilyCatalogLink -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/NestedCandidateSyntax.lean b/Ix/Kernel/Verify/Inductive/NestedCandidateSyntax.lean similarity index 85% rename from Ix/Tc/Verify/Inductive/NestedCandidateSyntax.lean rename to Ix/Kernel/Verify/Inductive/NestedCandidateSyntax.lean index b787181b6..ca7e07bdf 100644 --- a/Ix/Tc/Verify/Inductive/NestedCandidateSyntax.lean +++ b/Ix/Kernel/Verify/Inductive/NestedCandidateSyntax.lean @@ -1,27 +1,27 @@ -import Ix.Tc.Verify.Inductive.ExactLeanSyntax -import Ix.Tc.Verify.Inductive.NestedRecursiveFixture -import Lean4Lean.Verify.Environment.InductiveFixtures +import Ix.Kernel.Verify.Inductive.ExactLeanSyntax +import Ix.Kernel.Verify.Inductive.NestedRecursiveFixture +import Ix.Theory.Named.Verify.Environment.InductiveFixtures /-! -# Lean4Lean candidate produced by nested elimination +# Ix.Theory.Named candidate produced by nested elimination The production Ix fixture reaches `Box Tree` and records an auxiliary flat member whose physical identity remains the external `Box` address plus its -exact specialization key. Lean4Lean represents the same operation +exact specialization key. Ix.Theory.Named represents the same operation differently: `ElimNestedInductive.run` creates a fresh family constant and rewrites both the outer constructor and the copied external constructor to refer to that constant. -This module executes that real Lean4Lean transformation for the same +This module executes that real Ix.Theory.Named transformation for the same monomorphic `Box`/`Tree` shape and retains the exact flattened syntax. The fresh auxiliary name is therefore an output of the producer, not a name chosen by the transport proof. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture open Lean Meta Elab Term -open Lean4Lean.InductiveReplayFixtures +open Ix.Theory.Named.InductiveReplayFixtures /-! ## Previously declared external family -/ @@ -50,8 +50,8 @@ def leanNestedBaseEnv : Lean.Kernel.Environment := /-! ## Unflattened source declaration -/ -def leanTreeName : Lean.Name := `Ix.Tc.NestedRecursiveFixture.LeanTree -def leanNodeName : Lean.Name := `Ix.Tc.NestedRecursiveFixture.LeanTree.node +def leanTreeName : Lean.Name := `Ix.Kernel.NestedRecursiveFixture.LeanTree +def leanNodeName : Lean.Name := `Ix.Kernel.NestedRecursiveFixture.LeanTree.node def leanTreeExpr : Lean.Expr := .const leanTreeName [] def leanNestedDomain : Lean.Expr := .app (.const ``LeanBox []) leanTreeExpr @@ -63,7 +63,7 @@ def leanTreeSource : Lean.InductiveType := type := .forallE `value leanNestedDomain leanTreeExpr .default }] } def leanNestedEliminationOutcome := - (Lean4Lean.ElimNestedInductive.run 1000 0 [leanTreeSource] + (Ix.Theory.Named.ElimNestedInductive.run 1000 0 [leanTreeSource] leanNestedBaseEnv).run' { lvls := [], newTypes := #[leanTreeSource] } @@ -196,7 +196,7 @@ theorem leanAuxiliarySource : /-! ## Constructor-validation candidate -/ /-- Exact statistics of the two-member flattened mutual block. -/ -def leanFlatStats : Lean4Lean.AddInductive.InductiveStats where +def leanFlatStats : Ix.Theory.Named.AddInductive.InductiveStats where levels := [] resultLevel := .succ .zero nindices := #[0, 0] @@ -204,16 +204,16 @@ def leanFlatStats : Lean4Lean.AddInductive.InductiveStats where params := #[] isNotZero := true -def leanFlatFamilyContext : Lean4Lean.AddInductive.Context where +def leanFlatFamilyContext : Ix.Theory.Named.AddInductive.Context where env := leanNestedBaseEnv lparams := [] safety := .safe allowPrimitive := false - fuel := { ({} : Lean4Lean.FuelConfig) with + fuel := { ({} : Ix.Theory.Named.FuelConfig) with inductiveFuel := positivityFuel } def leanFlatDeclarationOutcome := - Lean4Lean.AddInductive.declareInductiveTypes leanFlatStats 0 + Ix.Theory.Named.AddInductive.declareInductiveTypes leanFlatStats 0 leanFlatTypes.toArray 1 false leanFlatFamilyContext def leanFlatConstructorEnv : Lean.Kernel.Environment := @@ -221,7 +221,7 @@ def leanFlatConstructorEnv : Lean.Kernel.Environment := | .ok environment => environment | .error _ => leanNestedBaseEnv -def leanFlatConstructorContext : Lean4Lean.AddInductive.Context := +def leanFlatConstructorContext : Ix.Theory.Named.AddInductive.Context := { leanFlatFamilyContext with env := leanFlatConstructorEnv } private theorem leanFlatDeclarationSucceededNative : @@ -240,39 +240,39 @@ theorem leanFlatDeclarationRun : cases outcome <;> simp_all private theorem leanTreeTargetNative : - Lean4Lean.AddInductive.isValidIndApp? leanFlatStats leanTreeExpr = + Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanTreeExpr = some 0 := by native_decide theorem leanTreeTarget : - Lean4Lean.AddInductive.isValidIndApp? leanFlatStats leanTreeExpr = + Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanTreeExpr = some 0 := leanTreeTargetNative private theorem leanAuxiliaryTargetNative : - Lean4Lean.AddInductive.isValidIndApp? leanFlatStats leanAuxiliaryExpr = + Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanAuxiliaryExpr = some 1 := by native_decide theorem leanAuxiliaryTarget : - Lean4Lean.AddInductive.isValidIndApp? leanFlatStats leanAuxiliaryExpr = + Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanAuxiliaryExpr = some 1 := leanAuxiliaryTargetNative private theorem leanTreeOccursNative : - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanTreeExpr = + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanTreeExpr = true := by native_decide theorem leanTreeOccurs : - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanTreeExpr = + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanTreeExpr = true := leanTreeOccursNative private theorem leanAuxiliaryOccursNative : - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanAuxiliaryExpr = true := by native_decide theorem leanAuxiliaryOccurs : - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanAuxiliaryExpr = true := leanAuxiliaryOccursNative /-! ## Exact cross-representation target certificate -/ @@ -289,7 +289,7 @@ private theorem nestedDomainCandidateCheckNative : nestedDomain leanNestedDomain = true := by native_decide -/-- Before flattening, the actual ingressed Ix domain and Lean4Lean's nested +/-- Before flattening, the actual ingressed Ix domain and Ix.Theory.Named's nested source have the same constant/application syntax. -/ theorem nestedDomainCandidateSyntax : CandidateSyntaxRel nestedCandidateNameOf @@ -315,11 +315,11 @@ theorem treeCandidateSyntax : treeExpr leanTreeExpr := CandidateSyntax.rel_of_check treeCandidateCheckNative -/-- Evidence that the target accepted by Lean4Lean is exactly the auxiliary +/-- Evidence that the target accepted by Ix.Theory.Named is exactly the auxiliary requested and retained by production Ix positivity/flat-block construction. The certificate keeps both representations visible: candidate syntax first -identifies `Box Tree`, the Lean4Lean eliminator's reverse map identifies the +identifies `Box Tree`, the Ix.Theory.Named eliminator's reverse map identifies the fresh target with that source, and the Ix request/header/key facts identify the physical flat member with the same specialization. -/ structure NestedAuxiliaryCandidateTarget : Prop where @@ -347,9 +347,9 @@ structure NestedAuxiliaryCandidateTarget : Prop where leanAuxiliarySource? leanAuxiliaryName = some leanNestedDomain outerRewrite : leanFlatNode.type = .forallE `value leanAuxiliaryExpr leanTreeExpr .default - occurs : Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts + occurs : Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanAuxiliaryExpr = true - valid : Lean4Lean.AddInductive.isValidIndApp? leanFlatStats + valid : Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanAuxiliaryExpr = some 1 /-- The concrete nested fixture closes every field of the cross-representation @@ -370,4 +370,4 @@ theorem nestedAuxiliaryCandidateTarget : NestedAuxiliaryCandidateTarget := by occurs := leanAuxiliaryOccurs valid := leanAuxiliaryTarget } -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedConstructorValidation.lean b/Ix/Kernel/Verify/Inductive/NestedConstructorValidation.lean similarity index 78% rename from Ix/Tc/Verify/Inductive/NestedConstructorValidation.lean rename to Ix/Kernel/Verify/Inductive/NestedConstructorValidation.lean index 64737cc85..56e4104ea 100644 --- a/Ix/Tc/Verify/Inductive/NestedConstructorValidation.lean +++ b/Ix/Kernel/Verify/Inductive/NestedConstructorValidation.lean @@ -1,33 +1,33 @@ -import Ix.Tc.Verify.Inductive.NestedAuxiliaryPositivity +import Ix.Kernel.Verify.Inductive.NestedAuxiliaryPositivity /-! # Constructor validation for the flattened nested fixture This module places both production-derived positivity traces into -Lean4Lean's exact constructor validator. The outer `Tree.node` field uses the +Ix.Theory.Named's exact constructor validator. The outer `Tree.node` field uses the nested-production transport, while the generated `Box.wrap` field uses the retained copied-constructor traversal. Both are checked in the same two-family environment produced by the real nested eliminator. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture private abbrev NodeValidationTrace - (context : Lean4Lean.AddInductive.Context) (source : Lean.Expr) + (context : Ix.Theory.Named.AddInductive.Context) (source : Lean.Expr) (argIdx fuel : Nat) := - Lean4Lean.AddInductive.ConstructorTypeValidationTrace leanFlatStats false + Ix.Theory.Named.AddInductive.ConstructorTypeValidationTrace leanFlatStats false 0 leanFlatNode.name context source argIdx fuel private abbrev WrapValidationTrace - (context : Lean4Lean.AddInductive.Context) (source : Lean.Expr) + (context : Ix.Theory.Named.AddInductive.Context) (source : Lean.Expr) (argIdx fuel : Nat) := - Lean4Lean.AddInductive.ConstructorTypeValidationTrace leanFlatStats false + Ix.Theory.Named.AddInductive.ConstructorTypeValidationTrace leanFlatStats false 1 leanFlatWrap.name context source argIdx fuel -def leanFlatNodeFieldContext : Lean4Lean.AddInductive.Context := +def leanFlatNodeFieldContext : Ix.Theory.Named.AddInductive.Context := leanFlatConstructorContext.pushLocalDecl `value .default leanAuxiliaryExpr -def leanFlatWrapFieldContext : Lean4Lean.AddInductive.Context := +def leanFlatWrapFieldContext : Ix.Theory.Named.AddInductive.Context := leanFlatConstructorContext.pushLocalDecl leanFlatWrapBinderName .default leanTreeExpr @@ -35,71 +35,71 @@ def leanFlatWrapFieldContext : Lean4Lean.AddInductive.Context := private theorem leanAuxiliaryEnsureTypeNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run leanFlatConstructorContext.env + (Ix.Theory.Named.TypeChecker.M.run leanFlatConstructorContext.env leanFlatConstructorContext.safety leanFlatConstructorContext.lctx leanFlatConstructorContext.lparams leanFlatConstructorContext.fuel - (Lean4Lean.TypeChecker.ensureType leanAuxiliaryExpr)) + (Ix.Theory.Named.TypeChecker.ensureType leanAuxiliaryExpr)) (.sort (.succ .zero)) = true := by native_decide private theorem leanAuxiliaryEnsureType : - Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid ⟨leanFlatConstructorContext, leanAuxiliaryExpr, .sort (.succ .zero)⟩ := by - unfold Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + unfold Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check leanAuxiliaryEnsureTypeNative private theorem leanTreeEnsureTypeNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run leanFlatConstructorContext.env + (Ix.Theory.Named.TypeChecker.M.run leanFlatConstructorContext.env leanFlatConstructorContext.safety leanFlatConstructorContext.lctx leanFlatConstructorContext.lparams leanFlatConstructorContext.fuel - (Lean4Lean.TypeChecker.ensureType leanTreeExpr)) + (Ix.Theory.Named.TypeChecker.ensureType leanTreeExpr)) (.sort (.succ .zero)) = true := by native_decide private theorem leanTreeEnsureType : - Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid ⟨leanFlatConstructorContext, leanTreeExpr, .sort (.succ .zero)⟩ := by - unfold Lean4Lean.AddInductive.ConstructorEnsureTypeStep.Valid + unfold Ix.Theory.Named.AddInductive.ConstructorEnsureTypeStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check leanTreeEnsureTypeNative private theorem leanFlatFieldUniverse : - Lean4Lean.AddInductive.levelStructGe leanFlatStats.resultLevel + Ix.Theory.Named.AddInductive.levelStructGe leanFlatStats.resultLevel (.succ .zero) = true := by native_decide private theorem leanTreeTerminalNative : - Lean4Lean.AddInductive.isValidIndAppIdx leanFlatStats leanTreeExpr 0 = + Ix.Theory.Named.AddInductive.isValidIndAppIdx leanFlatStats leanTreeExpr 0 = true := by native_decide private theorem leanAuxiliaryTerminalNative : - Lean4Lean.AddInductive.isValidIndAppIdx leanFlatStats + Ix.Theory.Named.AddInductive.isValidIndAppIdx leanFlatStats leanAuxiliaryExpr 1 = true := by native_decide private theorem consumeLeanAuxiliaryNative : ExactLeanSyntax.exprCheck - (Lean4Lean.AddInductive.consumeTypeAnnotations leanAuxiliaryExpr) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanAuxiliaryExpr) leanAuxiliaryExpr = true := by native_decide private theorem consumeLeanAuxiliary : - Lean4Lean.AddInductive.consumeTypeAnnotations leanAuxiliaryExpr = + Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanAuxiliaryExpr = leanAuxiliaryExpr := ExactLeanSyntax.expr_eq_of_check consumeLeanAuxiliaryNative private theorem consumeLeanTreeNative : ExactLeanSyntax.exprCheck - (Lean4Lean.AddInductive.consumeTypeAnnotations leanTreeExpr) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanTreeExpr) leanTreeExpr = true := by native_decide private theorem consumeLeanTree : - Lean4Lean.AddInductive.consumeTypeAnnotations leanTreeExpr = + Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanTreeExpr = leanTreeExpr := ExactLeanSyntax.expr_eq_of_check consumeLeanTreeNative @@ -160,10 +160,10 @@ theorem leanFlatNodeConstructorTypeValidationTrace : rw [consumeLeanAuxiliary, instantiateLeanTree] simpa [leanFlatNodeFieldContext, positivityFuel] using terminalTrace -/-- The assembled outer trace replays Lean4Lean's public constructor +/-- The assembled outer trace replays Ix.Theory.Named's public constructor validator. -/ theorem leanFlatNodeConstructorValidationRun : - Lean4Lean.AddInductive.checkConstructorType leanFlatStats false 0 + Ix.Theory.Named.AddInductive.checkConstructorType leanFlatStats false 0 leanFlatNode.name leanFlatNode.type leanFlatConstructorContext = .ok () := by obtain ⟨trace⟩ := leanFlatNodeConstructorTypeValidationTrace @@ -206,10 +206,10 @@ theorem leanFlatWrapConstructorTypeValidationTrace : /-- The generated auxiliary also passes the public constructor validator from the production-derived positivity evidence. -/ theorem leanFlatWrapConstructorValidationRun : - Lean4Lean.AddInductive.checkConstructorType leanFlatStats false 1 + Ix.Theory.Named.AddInductive.checkConstructorType leanFlatStats false 1 leanFlatWrap.name leanFlatWrap.type leanFlatConstructorContext = .ok () := by obtain ⟨trace⟩ := leanFlatWrapConstructorTypeValidationTrace exact trace.check_run -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedPositivityTransport.lean b/Ix/Kernel/Verify/Inductive/NestedPositivityTransport.lean similarity index 84% rename from Ix/Tc/Verify/Inductive/NestedPositivityTransport.lean rename to Ix/Kernel/Verify/Inductive/NestedPositivityTransport.lean index 9c64dda7b..4428fe988 100644 --- a/Ix/Tc/Verify/Inductive/NestedPositivityTransport.lean +++ b/Ix/Kernel/Verify/Inductive/NestedPositivityTransport.lean @@ -1,11 +1,11 @@ -import Ix.Tc.Verify.Inductive.NestedCandidateSyntax +import Ix.Kernel.Verify.Inductive.NestedCandidateSyntax /-! # Transporting the concrete nested positivity branch This module instantiates `FlattenedPositivityTraceTransport` for the outer `Tree.node : Box Tree → Tree` field. Ix validates the pre-flattening -`Box Tree` application by recursively traversing `Box.wrap`; Lean4Lean +`Box Tree` application by recursively traversing `Box.wrap`; Ix.Theory.Named validates the post-flattening generated auxiliary as a direct member of the two-family mutual block. @@ -15,24 +15,24 @@ complete branch trace and then consumes the audited cross-representation target certificate from `NestedCandidateSyntax`. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture /-! ## Exact candidate WHNF -/ private theorem leanAuxiliaryCandidateWhnfNative : ExactLeanSyntax.exceptExprCheck - (Lean4Lean.TypeChecker.M.run leanFlatConstructorContext.env + (Ix.Theory.Named.TypeChecker.M.run leanFlatConstructorContext.env leanFlatConstructorContext.safety leanFlatConstructorContext.lctx leanFlatConstructorContext.lparams leanFlatConstructorContext.fuel - (Lean4Lean.TypeChecker.whnf leanAuxiliaryExpr)) + (Ix.Theory.Named.TypeChecker.whnf leanAuxiliaryExpr)) leanAuxiliaryExpr = true := by native_decide theorem leanAuxiliaryCandidateWhnf : - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanFlatConstructorContext, leanAuxiliaryExpr, leanAuxiliaryExpr⟩ := by - unfold Lean4Lean.AddInductive.CandidateWhnfStep.Valid + unfold Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid exact ExactLeanSyntax.exceptExpr_eq_ok_of_check leanAuxiliaryCandidateWhnfNative @@ -52,7 +52,7 @@ private theorem nestedResultSpineNative : /-! ## Exact operation relations -/ inductive NestedOuterPositivitySourceRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | domain : NestedOuterPositivitySourceRel checkerInitial leanFlatConstructorContext nestedDomain leanAuxiliaryExpr @@ -62,7 +62,7 @@ is the fresh auxiliary produced for that exact application. The explicit shape equality makes impossible result forms eliminable without assuming an injective address/content correspondence. -/ inductive NestedOuterPositivityResultRel : - TcState .anon → Lean4Lean.AddInductive.Context → + TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop | domain {ixResult : KExpr .anon} (shape : ixResult = nestedDomain) : @@ -71,15 +71,15 @@ inductive NestedOuterPositivityResultRel : private theorem nestedOuterRootFree {ixState : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource : KExpr .anon} {leanSource : Lean.Expr} (relation : NestedOuterPositivitySourceRel ixState leanContext ixSource leanSource) (free : exprMentionsAnyAddr ixSource #[treeId.addr] = false) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = false := by cases relation rw [nestedDomainMentionsRootNative] at free @@ -87,7 +87,7 @@ private theorem nestedOuterRootFree private theorem nestedOuterWhnf {ixBefore ixAfter : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixSource ixResult : KExpr .anon} {leanSource : Lean.Expr} (relation : NestedOuterPositivitySourceRel ixBefore leanContext ixSource leanSource) @@ -95,7 +95,7 @@ private theorem nestedOuterWhnf (run : (RecM.whnf ixSource).run checkerMethods ixBefore = .ok ixResult ixAfter) : ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ NestedOuterPositivityResultRel ixAfter leanContext ixResult leanResult := by @@ -109,13 +109,13 @@ private theorem nestedOuterMentions (relation : NestedOuterPositivitySourceRel ixState leanContext ixExpr leanExpr) : exprMentionsAnyAddr ixExpr #[treeId.addr] = - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanExpr := by + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanExpr := by cases relation rw [nestedDomainMentionsRootNative, leanAuxiliaryOccurs] private theorem nestedOuterForall {ixState : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixName : Mode.anon.F Name} {ixBinder : Mode.anon.F Lean.BinderInfo} {ixDomain ixBody : KExpr .anon} {ixInfo : ExprInfo .anon} {leanExpr : Lean.Expr} @@ -131,7 +131,7 @@ private theorem nestedOuterForall .ok (ixOpen, ixFVar) ixAfterOpen → NestedOuterPositivitySourceRel ixAfterOpen (leanContext.pushLocalDecl leanName leanBinder - (Lean4Lean.AddInductive.consumeTypeAnnotations leanDomain)) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanDomain)) ixOpen (leanBody.instantiate1 leanContext.freshExpr) := by cases relation with | domain shape => cases shape @@ -174,7 +174,7 @@ theorem nestedTraceProducesCanonicalRequest private theorem nestedOuterDirect {ixState : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixResult : KExpr .anon} {leanResult : Lean.Expr} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} {args : Array (KExpr .anon)} @@ -187,10 +187,10 @@ private theorem nestedOuterDirect (_valid : ValidPositiveRecursiveApplication id us args traceGroups #[treeId.addr] checkerMethods ixState final) : ∃ targetIdx, - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = true ∧ leanResult.isForall = false ∧ - Lean4Lean.AddInductive.isValidIndApp? leanFlatStats leanResult = + Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanResult = some targetIdx := by cases relation with | domain shape => @@ -201,7 +201,7 @@ private theorem nestedOuterDirect private theorem nestedOuterNested {fuel : Nat} {ixState : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {ixResult : KExpr .anon} {leanResult : Lean.Expr} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} {args : Array (KExpr .anon)} @@ -214,10 +214,10 @@ private theorem nestedOuterNested (trace : CompleteNestedPositivityApplicationTrace fuel id us args traceGroups #[treeId.addr] traceActive checkerMethods ixState final) : ∃ targetIdx, - Lean4Lean.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = + Ix.Theory.Named.AddInductive.hasIndOcc leanFlatStats.indConsts leanResult = true ∧ leanResult.isForall = false ∧ - Lean4Lean.AddInductive.isValidIndApp? leanFlatStats leanResult = + Ix.Theory.Named.AddInductive.isValidIndApp? leanFlatStats leanResult = some targetIdx := by cases relation with | domain shape => @@ -229,7 +229,7 @@ private theorem nestedOuterNested /-- Complete operation-shaped transport for the outer nested field. The `nested` field is discharged from the exact producer request/flat target -certificate; it is not a preconstructed Lean4Lean trace. -/ +certificate; it is not a preconstructed Ix.Theory.Named trace. -/ theorem nestedOuterPositivityTransport : FlattenedPositivityTraceTransport leanFlatStats #[treeId.addr] checkerMethods NestedOuterPositivitySourceRel @@ -249,13 +249,13 @@ def nestedOuterProductionTrace : PositivityDomainTrace groups RecM.checkPositivityDomainFuel_success checkerMethods positivityRun /-- The actual nested production execution constructs the exact retained -Lean4Lean positivity trace for the flattened outer constructor field. -/ +Ix.Theory.Named positivity trace for the flattened outer constructor field. -/ theorem nestedOuterConstructorPositivityTrace : - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace leanFlatStats + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace leanFlatStats leanFlatNode.name 0 leanFlatConstructorContext leanAuxiliaryExpr positivityFuel) := by exact FlattenedPositivityTraceTransport.constructorPositivityTrace nestedOuterPositivityTransport nestedOuterProductionTrace (by rfl) .domain -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedPositivityTraversal.lean b/Ix/Kernel/Verify/Inductive/NestedPositivityTraversal.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/NestedPositivityTraversal.lean rename to Ix/Kernel/Verify/Inductive/NestedPositivityTraversal.lean index 46a3b46ca..705e51286 100644 --- a/Ix/Tc/Verify/Inductive/NestedPositivityTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/NestedPositivityTraversal.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.PositivityTraversal -import Ix.Tc.Verify.Inductive.SpecializationIdentity +import Ix.Kernel.Verify.Inductive.PositivityTraversal +import Ix.Kernel.Verify.Inductive.SpecializationIdentity /-! # Nested-family positivity traversal @@ -15,7 +15,7 @@ the exact loaded inductive header and continues from the real post-lookup checker state with the header's concrete arities, block, and constructor list. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Header information read from an external family reached by nested positivity traversal. -/ @@ -953,4 +953,4 @@ theorem checkNestedPositivityApplicationFuel_complete (checkNestedPositivityApplicationResolvedFuel_success hresolved)⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/NestedRecursiveFixture.lean b/Ix/Kernel/Verify/Inductive/NestedRecursiveFixture.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/NestedRecursiveFixture.lean rename to Ix/Kernel/Verify/Inductive/NestedRecursiveFixture.lean index 38b21bf6d..65551c631 100644 --- a/Ix/Tc/Verify/Inductive/NestedRecursiveFixture.lean +++ b/Ix/Kernel/Verify/Inductive/NestedRecursiveFixture.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.NestedAuxiliaryExpansion -import Ix.Tc.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.NestedAuxiliaryExpansion +import Ix.Kernel.Verify.Ingress.AnonStructural /-! # Concrete nested-recursive reachability fixture @@ -17,7 +17,7 @@ certificate identifies the request extracted from positivity with the exact auxiliary member retained by the public builder. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture open InductiveConcreteFixture @@ -571,4 +571,4 @@ theorem nestedAuxiliaryReachability : exact ⟨member, by simpa using member_mem, by simp [aux, key_eq]⟩ simpa using keyList -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedRecursorAdmission.lean b/Ix/Kernel/Verify/Inductive/NestedRecursorAdmission.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/NestedRecursorAdmission.lean rename to Ix/Kernel/Verify/Inductive/NestedRecursorAdmission.lean index dae66ce31..e222af38f 100644 --- a/Ix/Tc/Verify/Inductive/NestedRecursorAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/NestedRecursorAdmission.lean @@ -1,11 +1,11 @@ -import Ix.Tc.Verify.Inductive.NestedRecursorSoundness -import Ix.Tc.Verify.Inductive.OneFamilyAdmission +import Ix.Kernel.Verify.Inductive.NestedRecursorSoundness +import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Atomic admission of the nested family and both restored recursors The aux-aware compiler stores the source `LeanTree` block and a distinct -two-member recursor block. Lean4Lean's nested transaction installs the +two-member recursor block. Ix.Theory.Named's nested transaction installs the source family, constructor, both restored recursors, and both equations in one semantic step. This module reconciles those shapes as two exact physical admissions: the source block advances the Theory environment, then the @@ -13,9 +13,9 @@ already-installed recursor block is admitted with its two concrete iota patterns. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture -open Lean4Lean +open Ix.Theory.Named open InductiveConcreteFixture local instance nestedRecursorAdmissionAddressDecidableEq : @@ -623,4 +623,4 @@ theorem nestedRecursorAtomicClosure : NestedRecursorAtomicClosure where familyAccepted := nestedOneFamilyAtomicClosure.familyAccepted recursorAccepted := nestedOneFamilyAtomicClosure.recursorAccepted -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedRecursorFixture.lean b/Ix/Kernel/Verify/Inductive/NestedRecursorFixture.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/NestedRecursorFixture.lean rename to Ix/Kernel/Verify/Inductive/NestedRecursorFixture.lean index d7bee2a58..7c7e904ec 100644 --- a/Ix/Tc/Verify/Inductive/NestedRecursorFixture.lean +++ b/Ix/Kernel/Verify/Inductive/NestedRecursorFixture.lean @@ -1,5 +1,5 @@ import Ix.CompileDriver -import Ix.Tc.Verify.Inductive.NestedAdmission +import Ix.Kernel.Verify.Inductive.NestedAdmission /-! # Production nested-recursion block for `LeanTree` @@ -12,7 +12,7 @@ compiled source projections back to the already checked physical families; the recursor block is then ingressed and checked after that family block. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture open InductiveConcreteFixture @@ -299,4 +299,4 @@ theorem nestedRecursorKernelRun : generalize houtcome : nestedRecursorKernelOutcome = outcome at success ⊢ cases outcome <;> simp_all [nestedRecursorKernelOutcome] -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedRecursorPattern.lean b/Ix/Kernel/Verify/Inductive/NestedRecursorPattern.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/NestedRecursorPattern.lean rename to Ix/Kernel/Verify/Inductive/NestedRecursorPattern.lean index 8ea13cd7e..6cd2ceb2b 100644 --- a/Ix/Tc/Verify/Inductive/NestedRecursorPattern.lean +++ b/Ix/Kernel/Verify/Inductive/NestedRecursorPattern.lean @@ -1,20 +1,22 @@ -import Ix.Tc.Verify.Inductive.IotaPattern -import Ix.Tc.Verify.Inductive.NestedRecursorFixture +import Ix.Kernel.Verify.Inductive.IotaPattern +import Ix.Kernel.Verify.Inductive.NestedRecursorFixture + +open Ix.Theory (VLevel) /-! # Physical restored-recursion patterns for `LeanTree` The aux-aware compiler emits one physical recursor for the stored `LeanTree` -family and one for the flattened `LeanBox LeanTree` dependency. Lean4Lean's +family and one for the flattened `LeanBox LeanTree` dependency. Ix.Theory.Named's nested transaction restores those declarations as `LeanTree.rec` and `LeanTree.rec_1`, with one registered equation apiece. This module proves the complete representation correspondence and constructs the exact two iota patterns consumed by semantic admission. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture -open Lean4Lean +open Ix.Theory.Named open InductiveConcreteFixture local instance nestedPatternAddressDecidableEq : DecidableEq Address := @@ -592,4 +594,4 @@ structure NestedRestoredPatternSound : Prop where node : treeNodePattern.Sound semanticTreeEnv wrap : treeWrapPattern.Sound semanticTreeEnv -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedRecursorSoundness.lean b/Ix/Kernel/Verify/Inductive/NestedRecursorSoundness.lean similarity index 95% rename from Ix/Tc/Verify/Inductive/NestedRecursorSoundness.lean rename to Ix/Kernel/Verify/Inductive/NestedRecursorSoundness.lean index 38b65e320..8eb2198b5 100644 --- a/Ix/Tc/Verify/Inductive/NestedRecursorSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/NestedRecursorSoundness.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.NestedRecursorPattern +import Ix.Kernel.Verify.Inductive.NestedRecursorPattern + +open Ix.Theory (VLevel) /-! # Soundness of the two restored nested iota equations @@ -11,9 +13,9 @@ single pattern check to identify the physical `LeanBox` parameter with the restored specialization `LeanTree`. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture -open Lean4Lean +open Ix.Theory.Named /-! ## Shared concrete telescope shapes -/ @@ -287,7 +289,7 @@ theorem treeNodePatternSound : treeNodePattern.Sound semanticTreeEnv := by hconstructorApplied⟩ := htype.app_inv hfutureWF.ordered hGamma obtain ⟨recursorHeadType, hrecursorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := hrecursorHeadTyped.const_inv hfutureWF.ordered hGamma have hcertifiedRecursorLookup := @@ -308,7 +310,7 @@ theorem treeNodePatternSound : treeNodePattern.Sound semanticTreeEnv := by subst levelTail obtain ⟨constructorHeadType, hconstructorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied obtain ⟨constructorConstant, hconstructorLookup, constructorLevelsWF, hconstructorLevelsArity⟩ := hconstructorHeadTyped.const_inv hfutureWF.ordered hGamma @@ -337,7 +339,7 @@ theorem treeNodePatternSound : treeNodePattern.Sound semanticTreeEnv := by have hrecursorConstantTyped : future.HasType uvars Gamma (.const ``LeanTree.rec [u]) (semanticTreeRec.type.instL [u]) := by - simpa using (Lean4Lean.VEnv.HasType.const (Γ := Gamma) + simpa using (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity) have hrecursorCommonType : future.HasType uvars Gamma (.const ``LeanTree.rec [u]) @@ -360,13 +362,13 @@ theorem treeNodePatternSound : treeNodePattern.Sound semanticTreeEnv := by (VExpr.appN (semanticTreeNodeRule.lhs.instL [u]) [motiveTree, motiveBox, nodeMinor, wrapMinor]) (nodeEquationFieldType u motiveTree motiveBox nodeMinor wrapMinor) := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hcommonLength hrecursorApplied hrecursorCommonType hequationLhsCommonType have hconstructorConstantTyped : future.HasType uvars Gamma (.const ``LeanTree.node []) nodeConstructorFieldType := by - have htyped := Lean4Lean.VEnv.HasType.const (Γ := Gamma) + have htyped := Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedConstructorLookup constructorLevelsWF hconstructorLevelsArity rw [nodeConstructorTypeInstLNil] at htyped @@ -404,7 +406,7 @@ theorem treeNodePatternSound : treeNodePattern.Sound semanticTreeEnv := by rw [nodeFieldBindersEq] rfl have hequationLhsFieldsApplied := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hfieldLength hconstructorApplied hconstructorFieldHead' hequationFieldHead have hequationLhsApplied : future.HasType uvars Gamma @@ -419,7 +421,7 @@ theorem treeNodePatternSound : treeNodePattern.Sound semanticTreeEnv := by VExpr.appN_append] exact hequationLhsFieldsApplied have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationLhsApplied' := hequationLhsApplied @@ -429,7 +431,7 @@ theorem treeNodePatternSound : treeNodePattern.Sound semanticTreeEnv := by (nodeRuleBinders.map (VExpr.instL [u])).length := by simpa only [List.length_cons, List.length_nil, List.length_map] using nodeRuleBindersLength.symm - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleArgsLength hequationLhsApplied' rw [nodeLhsBodyOpen] at hlhsBeta have hlhsBeta' : future.IsDefEqU uvars Gamma @@ -511,7 +513,7 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by hconstructorApplied⟩ := htype.app_inv hfutureWF.ordered hGamma obtain ⟨recursorHeadType, hrecursorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := hrecursorHeadTyped.const_inv hfutureWF.ordered hGamma have hcertifiedRecursorLookup := @@ -532,7 +534,7 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by subst levelTail obtain ⟨constructorHeadType, hconstructorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied obtain ⟨constructorConstant, hconstructorLookup, constructorLevelsWF, hconstructorLevelsArity⟩ := hconstructorHeadTyped.const_inv hfutureWF.ordered hGamma @@ -555,11 +557,11 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by have hrecursorConstantTyped : future.HasType uvars Gamma (.const ``LeanTree.rec_1 [u]) (semanticTreeRecOne.type.instL [u]) := by - simpa using (Lean4Lean.VEnv.HasType.const (Γ := Gamma) + simpa using (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity) have hconstructorConstantTyped : future.HasType uvars Gamma (.const ``LeanBox.wrap []) semanticBoxWrap.type := by - have htyped := Lean4Lean.VEnv.HasType.const (Γ := Gamma) + have htyped := Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedConstructorLookup constructorLevelsWF hconstructorLevelsArity rw [wrapConstructorTypeInstLNil] at htyped @@ -575,12 +577,12 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by ([constructorAlpha] ++ [field])) majorDomain := by simpa using hconstructorApplied obtain ⟨constructorParameterResult, hconstructorParameterApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [constructorAlpha]) (suffixArgs := [field]) hconstructorAppliedSplit have hconstructorAlpha : future.HasType uvars Gamma constructorAlpha (.sort (.succ .zero)) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hconstructorParameterApplied hconstructorParameterHead have hparameterAtConstructor : future.IsDefEq uvars Gamma constructorAlpha (.const ``LeanTree []) (.sort (.succ .zero)) := @@ -606,7 +608,7 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by (VExpr.appN (.const ``LeanBox.wrap []) [.const ``LeanTree [], field]) := by simpa only [VExpr.appN] using - (Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma + (Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hconstructorPrefixEqTyped hconstructorAppliedFromPrefix) have hconstructorEqTyped : future.IsDefEq uvars Gamma (VExpr.appN (.const ``LeanBox.wrap []) [constructorAlpha, field]) @@ -653,7 +655,7 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by (VExpr.appN (semanticTreeWrapRule.lhs.instL [u]) [motiveTree, motiveBox, nodeMinor, wrapMinor]) (wrapEquationFieldType u motiveTree motiveBox nodeMinor wrapMinor) := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hcommonLength hrecursorApplied hrecursorCommonType hequationLhsCommonType @@ -661,14 +663,14 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by hfuture.constants semanticTreeTransactionFacts.sourceFamily have htreeConstantTyped : future.HasType uvars Gamma (.const ``LeanTree []) (.sort (.succ .zero)) := by - have htyped := Lean4Lean.VEnv.HasType.const (U := uvars) + have htyped := Ix.Theory.Named.VEnv.HasType.const (U := uvars) (Γ := Gamma) (ls := []) hcertifiedTreeLookup (by simp) (by rfl) rw [treeFamilyTypeInstLNil, treeFamilyTypeShape] at htyped exact htyped have hcanonicalConstructorPrefix : future.HasType uvars Gamma (.app (.const ``LeanBox.wrap []) (.const ``LeanTree [])) wrapConstructorFieldType := by - have happ := Lean4Lean.VEnv.HasType.app + have happ := Ix.Theory.Named.VEnv.HasType.app hconstructorParameterHead htreeConstantTyped change future.HasType uvars Gamma (.app (.const ``LeanBox.wrap []) (.const ``LeanTree [])) @@ -715,7 +717,7 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by rw [wrapFieldBindersEq] rfl have hequationLhsFieldsApplied := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hfieldLength hcanonicalConstructorApplied hconstructorFieldHead' hequationFieldHead have hequationLhsApplied : future.HasType uvars Gamma @@ -730,7 +732,7 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by VExpr.appN_append] exact hequationLhsFieldsApplied have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationLhsApplied' := hequationLhsApplied @@ -740,7 +742,7 @@ theorem treeWrapPatternSound : treeWrapPattern.Sound semanticTreeEnv := by (wrapRuleBinders.map (VExpr.instL [u])).length := by simpa only [List.length_cons, List.length_nil, List.length_map] using wrapRuleBindersLength.symm - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hruleArgsLength hequationLhsApplied' rw [wrapLhsBodyOpen] at hlhsBeta have hlhsBeta' : future.IsDefEqU uvars Gamma @@ -788,4 +790,4 @@ theorem treeWrapPatternRel : RawRecursorRulePatternRel.of_metadata_sound treeWrapPatternMetadata treeWrapPatternSound -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/NestedSemanticTransaction.lean b/Ix/Kernel/Verify/Inductive/NestedSemanticTransaction.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/NestedSemanticTransaction.lean rename to Ix/Kernel/Verify/Inductive/NestedSemanticTransaction.lean index 88b8b96ae..feab1157c 100644 --- a/Ix/Tc/Verify/Inductive/NestedSemanticTransaction.lean +++ b/Ix/Kernel/Verify/Inductive/NestedSemanticTransaction.lean @@ -1,13 +1,15 @@ -import Ix.Tc.Verify.Inductive.Certificate -import Ix.Tc.Verify.Inductive.NestedBlockCertificate -import Ix.Tc.Verify.Inductive.NestedConstructorValidation -import Lean4Lean.Verify.Environment.NestedReplay +import Ix.Kernel.Verify.Inductive.Certificate +import Ix.Kernel.Verify.Inductive.NestedBlockCertificate +import Ix.Kernel.Verify.Inductive.NestedConstructorValidation +import Ix.Theory.Named.Verify.Environment.NestedReplay + +open Ix.Theory (VLevel) /-! # Semantic transaction for the concrete nested `LeanBox`/`LeanTree` fixture The operational fixture has already connected Ix ingress and positivity to -Lean4Lean's flattened constructor validation. This module keeps the same +Ix.Theory.Named's flattened constructor validation. This module keeps the same exact names and builds the missing Theory half: * a certified dependency transaction for `LeanBox`; @@ -21,12 +23,12 @@ to Lean's stored nested metadata, so they cannot be substituted for semantic or physical correspondence evidence. -/ -namespace Ix.Tc.NestedRecursiveFixture +namespace Ix.Kernel.NestedRecursiveFixture open Lean -open Lean4Lean -open Lean4Lean.InductiveReplayFixtures -open Lean4Lean.NestedRepresentation +open Ix.Theory.Named +open Ix.Theory.Named.InductiveReplayFixtures +open Ix.Theory.Named.NestedRepresentation open VInductDecl local instance : Inhabited VEnv := ⟨.empty⟩ @@ -520,4 +522,4 @@ theorem semanticTreeTransactionFacts : SemanticTreeTransactionFacts := by rw [semanticTreeRules_eq] simp [semanticTreeRules] -end Ix.Tc.NestedRecursiveFixture +end Ix.Kernel.NestedRecursiveFixture diff --git a/Ix/Tc/Verify/Inductive/OccurrenceClosure.lean b/Ix/Kernel/Verify/Inductive/OccurrenceClosure.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/OccurrenceClosure.lean rename to Ix/Kernel/Verify/Inductive/OccurrenceClosure.lean index 2c4f3dec5..d66f5f8fb 100644 --- a/Ix/Tc/Verify/Inductive/OccurrenceClosure.lean +++ b/Ix/Kernel/Verify/Inductive/OccurrenceClosure.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.OccurrenceValidation -import Ix.Tc.Verify.RecursiveMethods.ScopedCallDomains +import Ix.Kernel.Verify.Inductive.OccurrenceValidation +import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Run-scoped recursive-occurrence closure @@ -16,7 +16,7 @@ finite `Methods.ScopedCallScheduleAt` and preserves the scoped suffix-state witness on every intermediate checker state. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact finite method-call footprint of one parameter-comparison slice. -/ def PositiveParameterCallPlan (calls : Methods.CallDomain) @@ -113,4 +113,4 @@ theorem theoryParametersScoped end RecM.ValidPositiveRecursiveApplicationHeader -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/OccurrenceValidation.lean b/Ix/Kernel/Verify/Inductive/OccurrenceValidation.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/OccurrenceValidation.lean rename to Ix/Kernel/Verify/Inductive/OccurrenceValidation.lean index d05995579..2751b612c 100644 --- a/Ix/Tc/Verify/Inductive/OccurrenceValidation.lean +++ b/Ix/Kernel/Verify/Inductive/OccurrenceValidation.lean @@ -1,8 +1,8 @@ -import Ix.Tc.Verify.Decl -import Ix.Tc.Verify.Support -import Ix.Tc.Verify.Totalization -import Ix.Tc.Verify.Trans -import Ix.Tc.Verify.World +import Ix.Kernel.Verify.Decl +import Ix.Kernel.Verify.Support +import Ix.Kernel.Verify.Totalization +import Ix.Kernel.Verify.Trans +import Ix.Kernel.Verify.World /-! # Recursive-occurrence validation @@ -14,7 +14,7 @@ guard, and the complete state-threaded parameter-definitional-equality loop. No semantic inductive oracle is used here. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Header information read from the actual recursive-family declaration. -/ def KConst.PositiveRecursiveHeader (concrete : KConst m) @@ -38,7 +38,7 @@ def PositiveUniverseSpecialization (group : PositivityGroup m) ∀ i, i < us.size → univEq us[i]! (.mkParam i.toUInt64 RecM.anonN : KUniv m) = true -/-- Elementwise form of Lean4Lean's root-family-free index condition. -/ +/-- Elementwise form of Ix.Theory.Named's root-family-free index condition. -/ def RootIndicesIndependent (args : Array (KExpr m)) (nParams : Nat) (rootAddrs : Array Address) : Prop := let indices := args.extract nParams args.size @@ -109,7 +109,7 @@ def PositiveParameterDefEqContract (uvars : Nat) (Delta : KVLCtx) (methods : Methods .anon) (invariant : TcState .anon → Prop) : Prop := ∀ {state : TcState .anon} {argument parameter : KExpr .anon} - {argumentV parameterV : Lean4Lean.VExpr}, + {argumentV parameterV : Ix.Theory.Named.VExpr}, support argument → support parameter → TrKExprS world.venv uvars world.nameOf trProj Delta argument argumentV → @@ -375,7 +375,7 @@ theorem ValidPositiveRecursiveApplicationHeader.theoryParameters rcases valid with ⟨_, _, _, _, afterParameters, _, trace, _, hfinal⟩ have hsemantic := - Ix.Tc.RecM.PositiveParameterComparisonTrace.theoryDefEq defEq trace + Ix.Kernel.RecM.PositiveParameterComparisonTrace.theoryDefEq defEq trace hinitial plan exact ⟨afterParameters, hsemantic.1, hsemantic.2, hfinal⟩ @@ -618,4 +618,4 @@ theorem ValidPositiveRecursiveApplication.run | ctor => contradiction end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/OneFamilyAdmission.lean b/Ix/Kernel/Verify/Inductive/OneFamilyAdmission.lean similarity index 90% rename from Ix/Tc/Verify/Inductive/OneFamilyAdmission.lean rename to Ix/Kernel/Verify/Inductive/OneFamilyAdmission.lean index 0a5a7a039..c51745e5f 100644 --- a/Ix/Tc/Verify/Inductive/OneFamilyAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/OneFamilyAdmission.lean @@ -1,9 +1,9 @@ -import Ix.Tc.Verify.Check.BlockAcceptance +import Ix.Kernel.Verify.Check.BlockAcceptance /-! # Oracle-free one-family generated-recursor admission -Lean4Lean's current public generation certificate covers one inductive family +Ix.Theory.Named's current public generation certificate covers one inductive family at a time. Such a transaction has two distinct physical Ix blocks: * the family/constructor block advances the certified Theory environment; and @@ -15,7 +15,7 @@ environment, constructing an `InductiveOracle`, or pretending that a mutual declaration is a sequence of singleton declarations. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Complete semantic evidence for the two physical blocks generated by one certified inductive family. Freshness of the recursor is stated in the @@ -25,7 +25,7 @@ structure OneFamilyRecursorCertificate (trProj : RawProjRel) (world : VerifyWorld) (familyBlock : KId .anon) (familyMembers : Array (KId .anon)) (recursorBlock : KId .anon) (recursorMembers : Array (KId .anon)) - (afterVEnv : Lean4Lean.VEnv) : Prop where + (afterVEnv : Ix.Theory.Named.VEnv) : Prop where family : SemanticBlockTransitionCertificate trProj world familyBlock familyMembers .inductive' afterVEnv @@ -39,7 +39,7 @@ namespace OneFamilyRecursorCertificate def familyWorld {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : VerifyWorld := certificate.family.admittedWorld @@ -49,7 +49,7 @@ admitted. -/ def admittedWorld {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : VerifyWorld := certificate.recursor.admittedWorld @@ -58,7 +58,7 @@ def admittedWorld {trProj : RawProjRel} {world : VerifyWorld} theorem familyAdmission {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) (trusted : TrustedCatalogRel trProj world) : @@ -71,7 +71,7 @@ stage and admits only semantic entries already present in `afterVEnv`. -/ theorem recursorAdmission {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) (trusted : TrustedCatalogRel trProj world) : @@ -84,7 +84,7 @@ theorem recursorAdmission {trProj : RawProjRel} {world : VerifyWorld} theorem le_admittedWorld {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : world ≤ certificate.admittedWorld := @@ -96,7 +96,7 @@ by the family members and the original trusted set. -/ theorem trusted_iff {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) (id : KId .anon) : @@ -107,7 +107,7 @@ theorem trusted_iff {trProj : RawProjRel} {world : VerifyWorld} @[simp] theorem admittedWorld_venv {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} - {recursorMembers : Array (KId .anon)} {afterVEnv : Lean4Lean.VEnv} + {recursorMembers : Array (KId .anon)} {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : certificate.admittedWorld.venv = afterVEnv := @@ -116,7 +116,7 @@ theorem trusted_iff {trProj : RawProjRel} {world : VerifyWorld} @[simp] theorem admittedWorld_catalog {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} - {recursorMembers : Array (KId .anon)} {afterVEnv : Lean4Lean.VEnv} + {recursorMembers : Array (KId .anon)} {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : certificate.admittedWorld.catalog = world.catalog := @@ -125,7 +125,7 @@ theorem trusted_iff {trProj : RawProjRel} {world : VerifyWorld} @[simp] theorem admittedWorld_blocks {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} - {recursorMembers : Array (KId .anon)} {afterVEnv : Lean4Lean.VEnv} + {recursorMembers : Array (KId .anon)} {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : certificate.admittedWorld.blocks = world.blocks := @@ -134,7 +134,7 @@ theorem trusted_iff {trProj : RawProjRel} {world : VerifyWorld} @[simp] theorem admittedWorld_nameOf {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} - {recursorMembers : Array (KId .anon)} {afterVEnv : Lean4Lean.VEnv} + {recursorMembers : Array (KId .anon)} {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : certificate.admittedWorld.nameOf = world.nameOf := @@ -146,7 +146,7 @@ world, not only the two intermediate promotion witnesses. -/ structure AtomicClosure {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) : Prop where familyAdmission : @@ -162,7 +162,7 @@ structure AtomicClosure {trProj : RawProjRel} {world : VerifyWorld} theorem atomicClosure {trProj : RawProjRel} {world : VerifyWorld} {familyBlock : KId .anon} {familyMembers : Array (KId .anon)} {recursorBlock : KId .anon} {recursorMembers : Array (KId .anon)} - {afterVEnv : Lean4Lean.VEnv} + {afterVEnv : Ix.Theory.Named.VEnv} (certificate : OneFamilyRecursorCertificate trProj world familyBlock familyMembers recursorBlock recursorMembers afterVEnv) (trusted : TrustedCatalogRel trProj world) : @@ -178,4 +178,4 @@ theorem atomicClosure {trProj : RawProjRel} {world : VerifyWorld} end OneFamilyRecursorCertificate -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/PositivityTraceAdapter.lean b/Ix/Kernel/Verify/Inductive/PositivityTraceAdapter.lean similarity index 85% rename from Ix/Tc/Verify/Inductive/PositivityTraceAdapter.lean rename to Ix/Kernel/Verify/Inductive/PositivityTraceAdapter.lean index b497aff1e..fb0b62a2c 100644 --- a/Ix/Tc/Verify/Inductive/PositivityTraceAdapter.lean +++ b/Ix/Kernel/Verify/Inductive/PositivityTraceAdapter.lean @@ -1,11 +1,11 @@ -import Ix.Tc.Verify.Inductive.RecursivePositivityTraversal -import Lean4Lean.Inductive.ValidationTrace +import Ix.Kernel.Verify.Inductive.RecursivePositivityTraversal +import Ix.Theory.Named.Reference.Inductive.ValidationTrace /-! -# Transporting production positivity into Lean4Lean's retained trace +# Transporting production positivity into Ix.Theory.Named's retained trace `PositivityDomainTrace` records the successful Ix execution, while -Lean4Lean's `ConstructorPositivityTrace` records the corresponding successful +Ix.Theory.Named's `ConstructorPositivityTrace` records the corresponding successful Lean-kernel execution. These traces cannot be cast into one another: they use different expression representations, local contexts, reducers, and state models. @@ -24,7 +24,7 @@ certified flat-block auxiliary expansion rather than supplied through this interface. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact successful production positivity traversal for the flat fragment. @@ -97,33 +97,33 @@ end FlatPositivityDomainTrace /-- Primitive cross-kernel correspondence needed to transport the flat positivity fragment. -`SourceRel` is indexed by the current Ix state and Lean4Lean constructor +`SourceRel` is indexed by the current Ix state and Ix.Theory.Named constructor context so the forall field must relate the *actual* free variable allocated by each checker. `ResultRel` separately relates the one WHNF result consumed by the branch discriminator. Keeping these phases distinct avoids demanding that a post-WHNF cache state be closed under an execution that production never performs. The direct field consumes Ix's already-proved logical -recursive-application invariant; it may not assume the final Lean4Lean trace +recursive-application invariant; it may not assume the final Ix.Theory.Named trace itself. -/ structure FlatPositivityTraceTransport - (stats : Lean4Lean.AddInductive.InductiveStats) + (stats : Ix.Theory.Named.AddInductive.InductiveStats) (rootAddrs : Array Address) (methods : Methods .anon) - (SourceRel ResultRel : TcState .anon → Lean4Lean.AddInductive.Context → + (SourceRel ResultRel : TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop) : Prop where /-- A syntactically root-free Ix domain has a corresponding successful - Lean4Lean WHNF result with no occurrence of the flat block. Establishing + Ix.Theory.Named WHNF result with no occurrence of the flat block. Establishing this field requires the declaration-order/freshness argument that reduction of an older constant cannot introduce a newly declared family. -/ rootFree : ∀ {ixState leanContext ixSource leanSource}, SourceRel ixState leanContext ixSource leanSource → exprMentionsAnyAddr ixSource rootAddrs = false → ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ - Lean4Lean.AddInductive.hasIndOcc stats.indConsts leanResult = false + Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts leanResult = false /-- One exact successful production WHNF execution on a root-mentioning - source corresponds to one exact successful Lean4Lean candidate-WHNF + source corresponds to one exact successful Ix.Theory.Named candidate-WHNF execution, and their results remain related in the post-Ix state. Production checks occurrence before entering this branch. Retaining that @@ -134,7 +134,7 @@ structure FlatPositivityTraceTransport exprMentionsAnyAddr ixSource rootAddrs = true → (RecM.whnf ixSource).run methods ixBefore = .ok ixResult ixAfter → ∃ leanResult, - Lean4Lean.AddInductive.CandidateWhnfStep.Valid + Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid ⟨leanContext, leanSource, leanResult⟩ ∧ ResultRel ixAfter leanContext ixResult leanResult @@ -143,11 +143,11 @@ structure FlatPositivityTraceTransport mentions : ∀ {ixState leanContext ixExpr leanExpr}, SourceRel ixState leanContext ixExpr leanExpr → exprMentionsAnyAddr ixExpr rootAddrs = - Lean4Lean.AddInductive.hasIndOcc stats.indConsts leanExpr + Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts leanExpr /-- A related Ix forall is a Lean forall. Its domains are related, and the two checkers' concrete binder-opening operations produce related bodies in - the exact extended Lean4Lean context. -/ + the exact extended Ix.Theory.Named context. -/ forallE : ∀ {ixState leanContext ixName ixBinder ixDomain ixBody ixInfo leanExpr}, ResultRel ixState leanContext @@ -161,11 +161,11 @@ structure FlatPositivityTraceTransport .ok (ixOpen, ixFVar) ixAfterOpen → SourceRel ixAfterOpen (leanContext.pushLocalDecl leanName leanBinder - (Lean4Lean.AddInductive.consumeTypeAnnotations leanDomain)) + (Ix.Theory.Named.AddInductive.consumeTypeAnnotations leanDomain)) ixOpen (leanBody.instantiate1 leanContext.freshExpr) /-- A production-validated active-family application becomes a valid flat - Lean4Lean target at the same related WHNF node. Parameter/universe + Ix.Theory.Named target at the same related WHNF node. Parameter/universe uniformity and index independence must be discharged from `valid`; they are not hidden in a whole-trace premise. -/ direct : ∀ {ixState leanContext ixResult leanResult id us info args groups @@ -176,36 +176,36 @@ structure FlatPositivityTraceTransport ValidPositiveRecursiveApplication id us args groups rootAddrs methods ixState final → ∃ targetIdx, - Lean4Lean.AddInductive.hasIndOcc stats.indConsts leanResult = true ∧ + Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts leanResult = true ∧ leanResult.isForall = false ∧ - Lean4Lean.AddInductive.isValidIndApp? stats leanResult = some targetIdx + Ix.Theory.Named.AddInductive.isValidIndApp? stats leanResult = some targetIdx namespace FlatPositivityTraceTransport -/-- Assemble Lean4Lean's exact retained positivity trace from a direct-only +/-- Assemble Ix.Theory.Named's exact retained positivity trace from a direct-only successful production trace. The result is wrapped in `Nonempty` because the Ix execution trace lives in `Prop`; this keeps the recursion within propositional elimination while still -supplying the Type-valued Lean4Lean trace to downstream semantic consumers. -/ +supplying the Type-valued Ix.Theory.Named trace to downstream semantic consumers. -/ theorem constructorPositivityTrace - {stats : Lean4Lean.AddInductive.InductiveStats} + {stats : Ix.Theory.Named.AddInductive.InductiveStats} {rootAddrs : Array Address} {methods : Methods .anon} {SourceRel ResultRel : TcState .anon → - Lean4Lean.AddInductive.Context → + Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop} (transport : FlatPositivityTraceTransport stats rootAddrs methods SourceRel ResultRel) : ∀ {groups : Array (PositivityGroup .anon)} {activeAddrs : Array Address} {fuel : Nat} {ixSource : KExpr .anon} {ixInitial ixFinal : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {leanSource : Lean.Expr} {ctor : Lean.Name} {argIdx : Nat} (_trace : FlatPositivityDomainTrace groups activeAddrs methods fuel ixSource ixInitial ixFinal), groups[0]?.map (·.addrs) = some rootAddrs → SourceRel ixInitial leanContext ixSource leanSource → - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace stats ctor + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace stats ctor argIdx leanContext leanSource fuel) | groups, activeAddrs, _, _, _, _, leanContext, leanSource, ctor, argIdx, .rootFree (fuel := innerFuel) (rootGroup := rootGroup) root free, @@ -228,14 +228,14 @@ theorem constructorPositivityTrace domainRelated, openRelated⟩ := transport.forallE resultRelated subst leanResult have leanDomainFree : - Lean4Lean.AddInductive.hasIndOcc stats.indConsts leanDomain = + Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts leanDomain = false := by rw [← transport.mentions domainRelated] simpa [rootAddrsEq] using domainFree have tailRelated := openRelated opening obtain ⟨leanTail⟩ := constructorPositivityTrace transport tail rootMatches tailRelated - cases leanOccurs : Lean4Lean.AddInductive.hasIndOcc stats.indConsts + cases leanOccurs : Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts (.forallE leanName leanDomain leanBody leanBinder) with | false => exact ⟨.absent leanContext leanSource @@ -277,13 +277,13 @@ remains the theorem below. Concrete instances must derive this field from an exact auxiliary request, its `NestedAuxiliaryHeaderRel`, physical `FlatAuxPresent` evidence, and the -candidate-level relation identifying that member with the Lean4Lean target. +candidate-level relation identifying that member with the Ix.Theory.Named target. This makes the flat-block correspondence visible at the only control-flow point where the two kernels' source syntax differs. -/ structure FlattenedPositivityTraceTransport - (stats : Lean4Lean.AddInductive.InductiveStats) + (stats : Ix.Theory.Named.AddInductive.InductiveStats) (rootAddrs : Array Address) (methods : Methods .anon) - (SourceRel ResultRel : TcState .anon → Lean4Lean.AddInductive.Context → + (SourceRel ResultRel : TcState .anon → Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop) : Prop extends FlatPositivityTraceTransport stats rootAddrs methods SourceRel ResultRel where @@ -297,37 +297,37 @@ structure FlattenedPositivityTraceTransport CompleteNestedPositivityApplicationTrace fuel id us args groups rootAddrs activeAddrs methods ixState final → ∃ targetIdx, - Lean4Lean.AddInductive.hasIndOcc stats.indConsts leanResult = true ∧ + Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts leanResult = true ∧ leanResult.isForall = false ∧ - Lean4Lean.AddInductive.isValidIndApp? stats leanResult = some targetIdx + Ix.Theory.Named.AddInductive.isValidIndApp? stats leanResult = some targetIdx namespace FlattenedPositivityTraceTransport -/-- Assemble Lean4Lean's retained positivity trace from the exhaustive +/-- Assemble Ix.Theory.Named's retained positivity trace from the exhaustive production traversal, including applications eliminated into exact generated flat auxiliaries. As in the direct-only adapter, `Nonempty` keeps elimination of the -proof-valued Ix trace within `Prop` while exposing Lean4Lean's Type-valued +proof-valued Ix trace within `Prop` while exposing Ix.Theory.Named's Type-valued trace to the enclosing constructor-validation proof. -/ theorem constructorPositivityTrace - {stats : Lean4Lean.AddInductive.InductiveStats} + {stats : Ix.Theory.Named.AddInductive.InductiveStats} {rootAddrs : Array Address} {methods : Methods .anon} {SourceRel ResultRel : TcState .anon → - Lean4Lean.AddInductive.Context → + Ix.Theory.Named.AddInductive.Context → KExpr .anon → Lean.Expr → Prop} (transport : FlattenedPositivityTraceTransport stats rootAddrs methods SourceRel ResultRel) : ∀ {groups : Array (PositivityGroup .anon)} {activeAddrs : Array Address} {fuel : Nat} {ixSource : KExpr .anon} {ixInitial ixFinal : TcState .anon} - {leanContext : Lean4Lean.AddInductive.Context} + {leanContext : Ix.Theory.Named.AddInductive.Context} {leanSource : Lean.Expr} {ctor : Lean.Name} {argIdx : Nat} (_trace : PositivityDomainTrace groups activeAddrs methods fuel ixSource ixInitial ixFinal), groups[0]?.map (·.addrs) = some rootAddrs → SourceRel ixInitial leanContext ixSource leanSource → - Nonempty (Lean4Lean.AddInductive.ConstructorPositivityTrace stats ctor + Nonempty (Ix.Theory.Named.AddInductive.ConstructorPositivityTrace stats ctor argIdx leanContext leanSource fuel) | groups, activeAddrs, _, _, _, _, leanContext, leanSource, ctor, argIdx, .rootFree (fuel := innerFuel) (rootGroup := rootGroup) root free, @@ -350,14 +350,14 @@ theorem constructorPositivityTrace domainRelated, openRelated⟩ := transport.forallE resultRelated subst leanResult have leanDomainFree : - Lean4Lean.AddInductive.hasIndOcc stats.indConsts leanDomain = + Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts leanDomain = false := by rw [← transport.mentions domainRelated] simpa [rootAddrsEq] using domainFree have tailRelated := openRelated opening obtain ⟨leanTail⟩ := constructorPositivityTrace transport tail rootMatches tailRelated - cases leanOccurs : Lean4Lean.AddInductive.hasIndOcc stats.indConsts + cases leanOccurs : Ix.Theory.Named.AddInductive.hasIndOcc stats.indConsts (.forallE leanName leanDomain leanBody leanBinder) with | false => exact ⟨.absent leanContext leanSource @@ -389,4 +389,4 @@ theorem constructorPositivityTrace end FlattenedPositivityTraceTransport -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/PositivityTraversal.lean b/Ix/Kernel/Verify/Inductive/PositivityTraversal.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/PositivityTraversal.lean rename to Ix/Kernel/Verify/Inductive/PositivityTraversal.lean index 4db3e0f54..338a5867d 100644 --- a/Ix/Tc/Verify/Inductive/PositivityTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/PositivityTraversal.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.OccurrenceValidation +import Ix.Kernel.Verify.Inductive.OccurrenceValidation /-! # Production positivity traversal @@ -14,7 +14,7 @@ its real intermediate checker state. The final theorem composes that equation with the oracle-free occurrence invariant from `OccurrenceValidation`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM private theorem runTryCatch (body : RecM m α) @@ -324,4 +324,4 @@ theorem checkPositivityDomainFuel_forall_negative rfl end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/ProducedGenerationTransaction.lean b/Ix/Kernel/Verify/Inductive/ProducedGenerationTransaction.lean similarity index 91% rename from Ix/Tc/Verify/Inductive/ProducedGenerationTransaction.lean rename to Ix/Kernel/Verify/Inductive/ProducedGenerationTransaction.lean index a142181f7..0f6b94cc2 100644 --- a/Ix/Tc/Verify/Inductive/ProducedGenerationTransaction.lean +++ b/Ix/Kernel/Verify/Inductive/ProducedGenerationTransaction.lean @@ -1,25 +1,25 @@ -import Ix.Tc.Verify.Inductive.Certificate -import Lean4Lean.Verify.Environment.ConstructorValidation +import Ix.Kernel.Verify.Inductive.Certificate +import Ix.Theory.Named.Verify.Environment.ConstructorValidation /-! # Producer-linked inductive-generation transactions `CertifiedGenerationTransaction` is intentionally Theory-only: it retains the generation certificate and the exact `VEnv.addInductCertified` result, but it -does not remember which ordinary Lean4Lean metadata execution selected that +does not remember which ordinary Ix.Theory.Named metadata execution selected that certificate. For E2c we need both facts at once. A successful outer producer call must not be allowed to justify Theory semantics by itself, and an independently chosen Theory certificate must not be passed off as the result of that producer. The -record below therefore owns Lean4Lean's dependent +record below therefore owns Ix.Theory.Named's dependent `ProducedGenerationCandidatePackage`, then erases it through the existing Theory-only transaction only at the consumer boundary. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named /-- One exact producer-selected singleton package together with its successful certified Theory insertion and well-formed input environment. @@ -98,7 +98,7 @@ end ProducedGenerationTransaction /-! ## Exact dependent producer transactions -/ -/-- The L4L-01E producer closure before source and generation indices are +/-- The Spec-01E producer closure before source and generation indices are erased. Its type retains the exact raw family, kernel source, producer arguments, normalized source declaration, and checked generation selected by one successful outer candidate execution. @@ -110,7 +110,7 @@ generation that merely happens to have the same erased package type. -/ structure ExactProducedGenerationTransaction {source : VInductDecl} {raw : VInductiveType} {kernelSource : Lean.InductiveType} {numNested : Nat} - {isUnsafe : Bool} {context : Lean4Lean.AddInductive.Context} + {isUnsafe : Bool} {context : Ix.Theory.Named.AddInductive.Context} (before after : VEnv) (Us : List Name) (producedCandidate : VInductDecl.ProducedGenerationShapeCandidate source raw kernelSource numNested isUnsafe context) @@ -129,7 +129,7 @@ consumer boundary. -/ noncomputable def toProduced {source : VInductDecl} {raw : VInductiveType} {kernelSource : Lean.InductiveType} {numNested : Nat} - {isUnsafe : Bool} {context : Lean4Lean.AddInductive.Context} + {isUnsafe : Bool} {context : Ix.Theory.Named.AddInductive.Context} {before after : VEnv} {Us : List Name} {producedCandidate : VInductDecl.ProducedGenerationShapeCandidate source raw kernelSource numNested isUnsafe context} @@ -144,7 +144,7 @@ noncomputable def toProduced @[simp] theorem toProduced_source {source : VInductDecl} {raw : VInductiveType} {kernelSource : Lean.InductiveType} {numNested : Nat} - {isUnsafe : Bool} {context : Lean4Lean.AddInductive.Context} + {isUnsafe : Bool} {context : Ix.Theory.Named.AddInductive.Context} {before after : VEnv} {Us : List Name} {producedCandidate : VInductDecl.ProducedGenerationShapeCandidate source raw kernelSource numNested isUnsafe context} @@ -156,7 +156,7 @@ noncomputable def toProduced @[simp] theorem toProduced_generation {source : VInductDecl} {raw : VInductiveType} {kernelSource : Lean.InductiveType} {numNested : Nat} - {isUnsafe : Bool} {context : Lean4Lean.AddInductive.Context} + {isUnsafe : Bool} {context : Ix.Theory.Named.AddInductive.Context} {before after : VEnv} {Us : List Name} {producedCandidate : VInductDecl.ProducedGenerationShapeCandidate source raw kernelSource numNested isUnsafe context} @@ -170,7 +170,7 @@ intentional erasure. -/ theorem facts {source : VInductDecl} {raw : VInductiveType} {kernelSource : Lean.InductiveType} {numNested : Nat} - {isUnsafe : Bool} {context : Lean4Lean.AddInductive.Context} + {isUnsafe : Bool} {context : Ix.Theory.Named.AddInductive.Context} {before after : VEnv} {Us : List Name} {producedCandidate : VInductDecl.ProducedGenerationShapeCandidate source raw kernelSource numNested isUnsafe context} @@ -181,4 +181,4 @@ theorem facts end ExactProducedGenerationTransaction -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/RecursivePiAcceptance.lean b/Ix/Kernel/Verify/Inductive/RecursivePiAcceptance.lean similarity index 95% rename from Ix/Tc/Verify/Inductive/RecursivePiAcceptance.lean rename to Ix/Kernel/Verify/Inductive/RecursivePiAcceptance.lean index 23bfa4832..e6df65ae8 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePiAcceptance.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiAcceptance.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Check.BlockAcceptance -import Ix.Tc.Verify.Inductive.RecursivePiFixture +import Ix.Kernel.Verify.Check.BlockAcceptance +import Ix.Kernel.Verify.Inductive.RecursivePiFixture /-! # Production acceptance of the recursive-Pi family @@ -9,7 +9,7 @@ This module joins three independently checked facts about the same physical * anonymous ingress produced its exact family/constructor member array; * the production family checker accepted that exact array; and -* the Lean4Lean certificate gives every member its stable Theory meaning in +* the Ix.Theory.Named certificate gives every member its stable Theory meaning in one atomic semantic transition. The result is deliberately limited to the family block. The separately @@ -17,10 +17,10 @@ generated `Acc.rec` declaration and its recursive-Pi iota rule are the next slice. -/ -namespace Ix.Tc.RecursivePiFixture +namespace Ix.Kernel.RecursivePiFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open RecursivePiCertificateFixture local instance acceptanceAnonKIdDecidableEq : DecidableEq (KId .anon) := @@ -193,4 +193,4 @@ theorem checkedSemanticAdmission : CheckedSemanticAdmission where admitted := familyAtomicAdmission recursivePi := breadth -end Ix.Tc.RecursivePiFixture +end Ix.Kernel.RecursivePiFixture diff --git a/Ix/Tc/Verify/Inductive/RecursivePiAdmission.lean b/Ix/Kernel/Verify/Inductive/RecursivePiAdmission.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/RecursivePiAdmission.lean rename to Ix/Kernel/Verify/Inductive/RecursivePiAdmission.lean index 05703e0f3..0d02dcc1b 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePiAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiAdmission.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.RecursivePiSoundness -import Ix.Tc.Verify.Inductive.OneFamilyAdmission +import Ix.Kernel.Verify.Inductive.RecursivePiSoundness +import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free recursive-Pi admission @@ -12,10 +12,10 @@ No `InductiveOracle`, ambient future-world choice, or sequential stand-in for a mutual declaration is used. -/ -namespace Ix.Tc.RecursivePiRecursorFixture +namespace Ix.Kernel.RecursivePiRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open RecursivePiCertificateFixture open RecursivePiFixture @@ -386,4 +386,4 @@ theorem recursivePiAtomicClosure : RecursivePiAtomicClosure where iota := RecursivePiPattern.patternRel concreteRule_ruleAt recursivePi := RecursivePiCertificateFixture.breadth -end Ix.Tc.RecursivePiRecursorFixture +end Ix.Kernel.RecursivePiRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/RecursivePiCertificate.lean b/Ix/Kernel/Verify/Inductive/RecursivePiCertificate.lean similarity index 89% rename from Ix/Tc/Verify/Inductive/RecursivePiCertificate.lean rename to Ix/Kernel/Verify/Inductive/RecursivePiCertificate.lean index da449432e..f6f4a4824 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePiCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiCertificate.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.Certificate -import Lean4Lean.Theory.InductiveFixtures +import Ix.Kernel.Verify.Inductive.Certificate +import Ix.Theory.Named.InductiveFixtures /-! # Certified recursive-Pi generation fixture @@ -10,18 +10,18 @@ the recursive argument is not a direct family application, and its induction hypothesis is itself a function. This module stays on the Theory-only side of the boundary. It constructs the -public proof-carrying Lean4Lean transaction directly from `accDecl_wf`; it +public proof-carrying Ix.Theory.Named transaction directly from `accDecl_wf`; it does not import the reflected Lean-environment replay or assert any Ix catalog correspondence. Production ingress, constructor traversal, and generated recursor comparison remain separate obligations. -/ -namespace Ix.Tc.RecursivePiCertificateFixture +namespace Ix.Kernel.RecursivePiCertificateFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures -/-- The public Lean4Lean certificate for the actual `Acc` declaration. -/ +/-- The public Ix.Theory.Named certificate for the actual `Acc` declaration. -/ def certificate : accDecl.GenerationCertificate VEnv.empty where generation := accChecked.identityGeneration wf := (accChecked.wf_of_decl accDecl_wf).identityGeneration .empty @@ -87,4 +87,4 @@ theorem certifiedFacts : CertifiedGenerationFacts VEnv.empty finalEnv transaction.certificate := transaction.facts -end Ix.Tc.RecursivePiCertificateFixture +end Ix.Kernel.RecursivePiCertificateFixture diff --git a/Ix/Tc/Verify/Inductive/RecursivePiFixture.lean b/Ix/Kernel/Verify/Inductive/RecursivePiFixture.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/RecursivePiFixture.lean rename to Ix/Kernel/Verify/Inductive/RecursivePiFixture.lean index 0d288d901..ea6807196 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePiFixture.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiFixture.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.ConcreteFixture -import Ix.Tc.Verify.Inductive.RecursivePiCertificate +import Ix.Kernel.Verify.Inductive.ConcreteFixture +import Ix.Kernel.Verify.Inductive.RecursivePiCertificate /-! # Production recursive-Pi fixture @@ -16,10 +16,10 @@ check. Semantic catalog linkage and generated-recursor admission are layered on these exact executions rather than assumed by the fixture. -/ -namespace Ix.Tc.RecursivePiFixture +namespace Ix.Kernel.RecursivePiFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open RecursivePiCertificateFixture open InductiveConcreteFixture @@ -441,4 +441,4 @@ def familyLink : SingletonFamilyCatalogLink RawProjRel.none world.catalog interpretation.toCatalogLinkOfEntries ingressExecution catalogEntry trustedCatalog -end Ix.Tc.RecursivePiFixture +end Ix.Kernel.RecursivePiFixture diff --git a/Ix/Tc/Verify/Inductive/RecursivePiPattern.lean b/Ix/Kernel/Verify/Inductive/RecursivePiPattern.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/RecursivePiPattern.lean rename to Ix/Kernel/Verify/Inductive/RecursivePiPattern.lean index e96311acc..d74c85737 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePiPattern.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiPattern.lean @@ -1,11 +1,13 @@ -import Ix.Tc.Verify.Inductive.IotaPattern -import Ix.Tc.Verify.Inductive.RecursivePiRecursorFixture +import Ix.Kernel.Verify.Inductive.IotaPattern +import Ix.Kernel.Verify.Inductive.RecursivePiRecursorFixture + +open Ix.Theory (VLevel) /-! # Recursive-Pi iota pattern The generated `Acc.intro` equation is the first supported iota rule whose -recursive call occurs beneath a function telescope. Lean4Lean's pattern RHS +recursive call occurs beneath a function telescope. Ix.Theory.Named's pattern RHS language intentionally contains only closed constants, applications, and captures; it has no primitive lambda constructor. We retain exact alignment with the registered equation by using its complete closed RHS lambda as a @@ -14,10 +16,10 @@ Beta reduction of that application constructs the two-binder induction hypothesis without adding an unverified pattern-language extension. -/ -namespace Ix.Tc.RecursivePiPattern +namespace Ix.Kernel.RecursivePiPattern -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open RecursivePiCertificateFixture open RecursivePiRecursorFixture @@ -229,4 +231,4 @@ theorem metadata {rule : RecRule .anon} simpa only [pattern, introFieldCount, show (2 : UInt64).toNat = 2 from rfl] using hfields -end Ix.Tc.RecursivePiPattern +end Ix.Kernel.RecursivePiPattern diff --git a/Ix/Tc/Verify/Inductive/RecursivePiRecursorFixture.lean b/Ix/Kernel/Verify/Inductive/RecursivePiRecursorFixture.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/RecursivePiRecursorFixture.lean rename to Ix/Kernel/Verify/Inductive/RecursivePiRecursorFixture.lean index f73c5de7d..43c7e018e 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePiRecursorFixture.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiRecursorFixture.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.RecursivePiAcceptance +import Ix.Kernel.Verify.Inductive.RecursivePiAcceptance /-! # Production recursive-Pi recursor fixture @@ -12,10 +12,10 @@ environment. Thus successful comparison exercises the production recursor generator and rule builder, not merely the Theory-side certificate. -/ -namespace Ix.Tc.RecursivePiRecursorFixture +namespace Ix.Kernel.RecursivePiRecursorFixture -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open RecursivePiCertificateFixture open RecursivePiFixture open InductiveConcreteFixture @@ -684,4 +684,4 @@ def recursorLink : SingletonRecursorCatalogLink RawProjRel.none world.catalog recursorInterpretation.toCatalogLinkOfEntry recursorIngressExecution catalog_recursor trustedCatalog -end Ix.Tc.RecursivePiRecursorFixture +end Ix.Kernel.RecursivePiRecursorFixture diff --git a/Ix/Tc/Verify/Inductive/RecursivePiSoundness.lean b/Ix/Kernel/Verify/Inductive/RecursivePiSoundness.lean similarity index 94% rename from Ix/Tc/Verify/Inductive/RecursivePiSoundness.lean rename to Ix/Kernel/Verify/Inductive/RecursivePiSoundness.lean index cee669019..e880344ef 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePiSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiSoundness.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.RecursivePiPattern +import Ix.Kernel.Verify.Inductive.RecursivePiPattern + +open Ix.Theory (VLevel) /-! # Recursive-Pi iota soundness @@ -11,10 +13,10 @@ application, so the functional induction hypothesis beneath two lambdas is not reconstructed by an independent rewrite axiom. -/ -namespace Ix.Tc.RecursivePiPattern +namespace Ix.Kernel.RecursivePiPattern -open Lean4Lean -open Lean4Lean.InductiveFixtures +open Ix.Theory.Named +open Ix.Theory.Named.InductiveFixtures open RecursivePiCertificateFixture open RecursivePiRecursorFixture @@ -377,7 +379,7 @@ theorem patternSound {rule : RecRule .anon} hconstructorApplied⟩ := htype.app_inv hfutureWF.ordered hGamma obtain ⟨recursorHeadType, hrecursorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := hrecursorHeadTyped.const_inv hfutureWF.ordered hGamma have hcertifiedRecursorLookup := @@ -402,7 +404,7 @@ theorem patternSound {rule : RecRule .anon} subst levelTail obtain ⟨constructorHeadType, hconstructorHeadTyped⟩ := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hconstructorApplied obtain ⟨constructorConstant, hconstructorLookup, hconstructorLevelsWF, hconstructorLevelsArity⟩ := hconstructorHeadTyped.const_inv hfutureWF.ordered hGamma @@ -437,7 +439,7 @@ theorem patternSound {rule : RecRule .anon} have hrecursorConstantTyped : future.HasType uvars Gamma (.const ``Acc.rec [v, u]) (generation.recType.instL [v, u]) := by - have htyped := Lean4Lean.VEnv.HasType.const (Γ := Gamma) + have htyped := Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity rw [generationRecursorName] at htyped simpa [VInductDecl.GenerationChecked.recursor] using htyped @@ -453,19 +455,19 @@ theorem patternSound {rule : RecRule .anon} (.forallE majorDomain majorBody) := by simpa using hrecursorApplied obtain ⟨recursorParameterResult, hrecursorParameterApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [alpha]) (suffixArgs := [relation, motive, minor, index]) hrecursorAppliedSplit have hrecursorAlpha : future.HasType uvars Gamma alpha (.sort u) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hrecursorParameterApplied hrecursorParameterHead have hconstructorConstantTyped : future.HasType uvars Gamma (.const ``Acc.intro [constructorU]) (normalized.raw.toVConstant.type.instL [constructorU]) := by simpa [normalizedName] using - (Lean4Lean.VEnv.HasType.const (Γ := Gamma) + (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedConstructorLookup hconstructorLevelsWF hconstructorLevelsArity) have hconstructorParameterHead : future.HasType uvars Gamma @@ -482,13 +484,13 @@ theorem patternSound {rule : RecRule .anon} majorDomain := by simpa using hconstructorApplied obtain ⟨constructorParameterResult, hconstructorParameterApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [constructorAlpha]) (suffixArgs := [constructorRelation, constructorIndex, recursiveField]) hconstructorAppliedSplit have hconstructorAlpha : future.HasType uvars Gamma constructorAlpha (.sort constructorU) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hconstructorParameterApplied hconstructorParameterHead obtain ⟨parameterType, hparameterTyped⟩ := hparameterEq @@ -502,7 +504,7 @@ theorem patternSound {rule : RecRule .anon} (.sort u) (.sort constructorU) := hrecursorSort.trans hfutureWF hGamma hconstructorSort.symm have huniverse : u ≈ constructorU := - Lean4Lean.VEnv.IsDefEqU.sort_inv hfutureWF hGamma hsorts + Ix.Theory.Named.VEnv.IsDefEqU.sort_inv hfutureWF hGamma hsorts have hintroLookup := hcertifiedConstructorLookup rw [normalizedName] at hintroLookup @@ -519,7 +521,7 @@ theorem patternSound {rule : RecRule .anon} rw [constructorType_parameter] at hconstructorConstantEq have hparameterAtConstructor : future.IsDefEq uvars Gamma constructorAlpha alpha (.sort constructorU) := - Lean4Lean.VEnv.IsDefEqU.defeqDF hfutureWF hGamma + Ix.Theory.Named.VEnv.IsDefEqU.defeqDF hfutureWF hGamma hconstructorSort.symm hparameterTyped.symm have hconstructorAlphaPrefixEq : future.IsDefEqU uvars Gamma (.app (.const ``Acc.intro [constructorU]) constructorAlpha) @@ -527,7 +529,7 @@ theorem patternSound {rule : RecRule .anon} ⟨_, .appDF hconstructorConstantEq hparameterAtConstructor⟩ obtain ⟨constructorParamsResult, hconstructorParamsApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [constructorAlpha, constructorRelation]) (suffixArgs := [constructorIndex, recursiveField]) hconstructorAppliedSplit @@ -548,11 +550,11 @@ theorem patternSound {rule : RecRule .anon} (VExpr.appN (.const ``Acc.intro [u]) [alpha, relation]) := by refine ⟨relationBody.inst constructorRelation, ?_⟩ simpa only [VExpr.appN] using - (Lean4Lean.VEnv.IsDefEq.appDF hconstructorAlphaPrefixEqTyped + (Ix.Theory.Named.VEnv.IsDefEq.appDF hconstructorAlphaPrefixEqTyped hrelationAtConstructor) obtain ⟨constructorIndexResult, hconstructorIndexApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [constructorAlpha, constructorRelation, constructorIndex]) (suffixArgs := [recursiveField]) hconstructorAppliedSplit @@ -575,7 +577,7 @@ theorem patternSound {rule : RecRule .anon} [alpha, relation, index]) := by refine ⟨indexBody.inst constructorIndex, ?_⟩ simpa only [VExpr.appN] using - (Lean4Lean.VEnv.IsDefEq.appDF hconstructorParamsEqTyped + (Ix.Theory.Named.VEnv.IsDefEq.appDF hconstructorParamsEqTyped hindexAtConstructor) obtain ⟨fieldDomain, fieldBody, hconstructorIndexHead, hrecursiveFieldTyped⟩ := @@ -593,7 +595,7 @@ theorem patternSound {rule : RecRule .anon} (VExpr.appN (.const ``Acc.intro [u]) [alpha, relation, index, recursiveField]) := by simpa only [VExpr.appN] using - (Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma + (Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hconstructorIndexEqTyped hconstructorApplied) have hconstructorEqTyped : future.IsDefEq uvars Gamma (VExpr.appN (.const ``Acc.intro [constructorU]) @@ -652,7 +654,7 @@ theorem patternSound {rule : RecRule .anon} (.forallE majorDomain majorBody) := by simpa using hrecursorApplied obtain ⟨recursorCommonResult, hrecursorCommonApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [alpha, relation, motive, minor]) (suffixArgs := [index]) hrecursorCommonAppliedSplit have hcommonLength : @@ -662,14 +664,14 @@ theorem patternSound {rule : RecRule .anon} (VExpr.appN ((generation.rule 0 normalized).lhs.instL [v, u]) [alpha, relation, motive, minor]) (equationFieldType v u alpha relation motive minor) := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hcommonLength hrecursorCommonApplied hrecursorCommonType hequationLhsCommonType have hcanonicalConstructorConstantTyped : future.HasType uvars Gamma (.const ``Acc.intro [u]) (normalized.raw.toVConstant.type.instL [u]) := - Lean4Lean.VEnv.HasType.const hintroLookup + Ix.Theory.Named.VEnv.HasType.const hintroLookup (fun level hlevel => by simp only [List.mem_singleton] at hlevel subst level @@ -682,7 +684,7 @@ theorem patternSound {rule : RecRule .anon} rw [← constructorType_parameter] exact hcanonicalConstructorConstantTyped obtain ⟨recursorParamsResult, hrecursorParamsApplied⟩ := - Lean4Lean.VEnv.HasType.appN_prefix hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.appN_prefix hfutureWF hGamma (prefixArgs := [alpha, relation]) (suffixArgs := [motive, minor, index]) hrecursorAppliedSplit have hrecursorAlphaHead : future.HasType uvars Gamma @@ -690,13 +692,13 @@ theorem patternSound {rule : RecRule .anon} (.forallE (relationType alpha) (VExpr.dropN 1 ((VExpr.dropN 1 (generation.recType.instL [v, u])).inst alpha))) := by - have happ := Lean4Lean.VEnv.HasType.app hrecursorParameterHead + have happ := Ix.Theory.Named.VEnv.HasType.app hrecursorParameterHead hrecursorAlpha rw [recType_relation] at happ exact happ have hrecursorRelation : future.HasType uvars Gamma relation (relationType alpha) := - Lean4Lean.VEnv.HasType.app_argument_of_head hfutureWF hGamma + Ix.Theory.Named.VEnv.HasType.app_argument_of_head hfutureWF hGamma hrecursorParamsApplied hrecursorAlphaHead have hcanonicalConstructorAlphaHead : future.HasType uvars Gamma (.app (.const ``Acc.intro [u]) alpha) @@ -704,14 +706,14 @@ theorem patternSound {rule : RecRule .anon} (VExpr.dropN 1 ((VExpr.dropN 1 (normalized.raw.toVConstant.type.instL [u])).inst alpha))) := by - have happ := Lean4Lean.VEnv.HasType.app + have happ := Ix.Theory.Named.VEnv.HasType.app hcanonicalConstructorParameterHead hrecursorAlpha rw [constructorType_relation] at happ exact happ have hcanonicalConstructorPrefix : future.HasType uvars Gamma (VExpr.appN (.const ``Acc.intro [u]) [alpha, relation]) (constructorFieldType u alpha relation) := by - have happ := Lean4Lean.VEnv.HasType.app + have happ := Ix.Theory.Named.VEnv.HasType.app hcanonicalConstructorAlphaHead hrecursorRelation change future.HasType uvars Gamma (.app (.app (.const ``Acc.intro [u]) alpha) relation) @@ -757,7 +759,7 @@ theorem patternSound {rule : RecRule .anon} VExpr.instL, VExpr.inst, VExpr.instVar, VExpr.telN, VExpr.dropN] have hequationLhsFieldsApplied := - Lean4Lean.VEnv.HasType.transfer_appN_telescope_instRev + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope_instRev hfutureWF hGamma hfieldLength hcanonicalConstructorApplied hconstructorFieldHead' hequationFieldHead have hequationLhsApplied : future.HasType uvars Gamma @@ -772,12 +774,12 @@ theorem patternSound {rule : RecRule .anon} VExpr.appN_append] exact hequationLhsFieldsApplied have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationLhsApplied' := hequationLhsApplied rw [generatedRule_shape.1, VExpr.instL_lamN] at hequationLhsApplied' - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma (by simp) hequationLhsApplied' rw [lhsBody_open] at hlhsBeta have hlhsBeta' : future.IsDefEqU uvars Gamma @@ -818,4 +820,4 @@ theorem patternRel {rule : RecRule .anon} RawRecursorRulePatternRel.of_metadata_sound (metadata hrule) (patternSound hrule) -end Ix.Tc.RecursivePiPattern +end Ix.Kernel.RecursivePiPattern diff --git a/Ix/Tc/Verify/Inductive/RecursivePositivityTraversal.lean b/Ix/Kernel/Verify/Inductive/RecursivePositivityTraversal.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/RecursivePositivityTraversal.lean rename to Ix/Kernel/Verify/Inductive/RecursivePositivityTraversal.lean index 8e16bb435..c3ae6c621 100644 --- a/Ix/Tc/Verify/Inductive/RecursivePositivityTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePositivityTraversal.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.NestedPositivityTraversal +import Ix.Kernel.Verify.Inductive.NestedPositivityTraversal /-! # Exhaustive recursive positivity traversal @@ -11,7 +11,7 @@ terminal constant spine is either a validated active-family occurrence or a fully expanded nested-family traversal. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The WHNF branch discriminator used by positivity after the forall case has been excluded. Naming it prevents indexed trace constructors from making @@ -298,4 +298,4 @@ theorem checkPositivityDomainFuel_success hterminal end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/ResultSortTelescope.lean b/Ix/Kernel/Verify/Inductive/ResultSortTelescope.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/ResultSortTelescope.lean rename to Ix/Kernel/Verify/Inductive/ResultSortTelescope.lean index 02f1ec47a..bc22d6e41 100644 --- a/Ix/Tc/Verify/Inductive/ResultSortTelescope.lean +++ b/Ix/Kernel/Verify/Inductive/ResultSortTelescope.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Inductive -import Ix.Tc.Verify.Whnf.StructEta.ExactMajorTelescope +import Ix.Kernel.Inductive +import Ix.Kernel.Verify.Whnf.StructEta.ExactMajorTelescope /-! # Exact result-sort telescope restoration @@ -13,7 +13,7 @@ The theorem is deliberately operational. It grants no authority to a WHNF callback and makes no scoped suffix model admit the temporary telescope. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Pure syntax certificate for a fixed forall prefix ending in a sort. -/ @@ -100,4 +100,4 @@ theorem getResultSortLevel_direct_exact exact scratch_tryFinally_ok bodyRun cleanup end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/RuleApplication.lean b/Ix/Kernel/Verify/Inductive/RuleApplication.lean similarity index 98% rename from Ix/Tc/Verify/Inductive/RuleApplication.lean rename to Ix/Kernel/Verify/Inductive/RuleApplication.lean index b79d3f1c1..fcc975464 100644 --- a/Ix/Tc/Verify/Inductive/RuleApplication.lean +++ b/Ix/Kernel/Verify/Inductive/RuleApplication.lean @@ -1,9 +1,9 @@ -import Ix.Tc.Verify.Inductive.SingletonRecursor +import Ix.Kernel.Verify.Inductive.SingletonRecursor /-! # Applying closed generated equations -Lean4Lean registers generated iota equations as closed lambda telescopes, +Ix.Theory.Named registers generated iota equations as closed lambda telescopes, whereas the production Ix reducer sees the recursor application after that telescope has been supplied. These lemmas isolate the ordinary dependent beta reasoning needed to cross that boundary. @@ -15,7 +15,7 @@ lambda-wrapped equations. The later singleton pattern compiler must provide the exact telescope arguments and use the lemmas below. -/ -namespace Lean4Lean.VExpr +namespace Ix.Theory.Named.VExpr /-- Positional lookup in the reverse de Bruijn range used by generated rule telescopes. -/ @@ -51,9 +51,9 @@ theorem instRev_bvar_at (arguments : List VExpr) (index : Nat) rw [List.getElem?_eq_getElem hindex] at hrange exact Option.some.inj hrange -end Lean4Lean.VExpr +end Ix.Theory.Named.VExpr -namespace Lean4Lean.VEnv +namespace Ix.Theory.Named.VEnv /-- Typing an application spine also types its original head. This is a small inversion helper for the equation-application proofs below. -/ @@ -309,7 +309,7 @@ theorem HasType.beta_head_appN exact IsDefEq.appN_same henv hGamma hbeta hsource /-- Supplying exactly one argument per closed lambda binder beta-reduces to -Lean4Lean's outer-to-inner `instRev` operation. This is the reusable semantic +Ix.Theory.Named's outer-to-inner `instRev` operation. This is the reusable semantic bridge from a registered closed equation to an open generated rule body. -/ theorem HasType.lamN_appN_beta {env : VEnv} {U : Nat} {Gamma : List VExpr} @@ -360,4 +360,4 @@ theorem HasType.lamN_appN_beta simpa only [VExpr.lamN, VExpr.appN, VExpr.instRev, Nat.zero_add, hrestLength] using hcombined -end Lean4Lean.VEnv +end Ix.Theory.Named.VEnv diff --git a/Ix/Tc/Verify/Inductive/SingletonEnumeration.lean b/Ix/Kernel/Verify/Inductive/SingletonEnumeration.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/SingletonEnumeration.lean rename to Ix/Kernel/Verify/Inductive/SingletonEnumeration.lean index b9beebddb..ff64eaac0 100644 --- a/Ix/Tc/Verify/Inductive/SingletonEnumeration.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonEnumeration.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Inductive.IotaPattern +import Ix.Kernel.Verify.Inductive.IotaPattern + +open Ix.Theory (VLevel) /-! # Certified singleton enumerations @@ -14,9 +16,9 @@ retained by E2a. It is therefore a decidable fragment boundary around the actual generated artifacts, not a second inductive-declaration model. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstVal VEnv VExpr VInductDecl) +open Ix.Theory.Named (VConstVal VEnv VExpr VInductDecl) namespace CertifiedSingletonGeneration @@ -28,7 +30,7 @@ structure IsEnumeration {source : VInductDecl} noUniverses : source.uvars = 0 noParameters : source.nparams = 0 /-- E2b's enumeration pattern currently covers the ordinary large - eliminator. Small and K elimination use the L4L-06 universe layout and + eliminator. Small and K elimination use the Spec-06 universe layout and remain explicit E2c breadth cases. -/ largeElimination : generation.elimination = .large noIndices : generation.block.rawIndices = [] @@ -73,8 +75,8 @@ recursor, independently of the selected elimination mode. -/ (shape : IsEnumeration generation) : generation.sourceLevels = [] := by simp [VInductDecl.GenerationChecked.sourceLevels, - Lean4Lean.VInductDecl.ElimMode.sourceLevels, - Lean4Lean.VLevel.params', shape.noUniverses] + Ix.Theory.Named.VInductDecl.ElimMode.sourceLevels, + Ix.Theory.VLevel.params', shape.noUniverses] @[simp] theorem paramsTel_nil {source : VInductDecl} {generation : source.GenerationChecked} @@ -145,7 +147,7 @@ theorem rule_lhs {source : VInductDecl} shape.resultIndices_nil hconstructor] simp [ruleBinders, VExpr.liftTelN, VExpr.appN, VExpr.bvarRevRange, shape.noUniverses, shape.noParameters, - Lean4Lean.VLevel.params', shape.largeElimination] + Ix.Theory.VLevel.params', shape.largeElimination] /-- Exact generated right-hand side: enum rule `index` is the corresponding minor variable and has no field/IH application suffix. -/ @@ -168,7 +170,7 @@ theorem rule_rhs {source : VInductDecl} open a generated enumeration equation. -/ @[simp] theorem ruleBinders_instL_length {source : VInductDecl} {generation : source.GenerationChecked} - (levels : List Lean4Lean.VLevel) : + (levels : List Ix.Theory.VLevel) : ((ruleBinders generation).map (VExpr.instL levels)).length = generation.block.ctorPairs.length + 1 := by simp @@ -179,7 +181,7 @@ retains only its final major binder after that common prefix. -/ theorem recType_instantiated {source : VInductDecl} {generation : source.GenerationChecked} (shape : IsEnumeration generation) - (levels : List Lean4Lean.VLevel) : + (levels : List Ix.Theory.VLevel) : generation.recType.instL levels = VExpr.forallN ((ruleBinders generation).map (VExpr.instL levels)) @@ -202,7 +204,7 @@ theorem ruleType_instantiated {source : VInductDecl} (shape : IsEnumeration generation) {index : Nat} {normalized : VInductDecl.NormalizedCtor} (hconstructor : generation.block.ctorPairs[index]? = some normalized) - (levels : List Lean4Lean.VLevel) : + (levels : List Ix.Theory.VLevel) : (generation.rule index normalized).type.instL levels = VExpr.forallN ((ruleBinders generation).map (VExpr.instL levels)) @@ -224,7 +226,7 @@ theorem ruleLhsBody_instantiated {source : VInductDecl} {generation : source.GenerationChecked} (shape : IsEnumeration generation) (normalized : VInductDecl.NormalizedCtor) - (levels : List Lean4Lean.VLevel) (arguments : List VExpr) + (levels : List Ix.Theory.VLevel) (arguments : List VExpr) (hlevels : levels.length = generation.recUvars) (harguments : arguments.length = generation.block.ctorPairs.length + 1) : @@ -245,7 +247,7 @@ theorem ruleLhsBody_instantiated {source : VInductDecl} arguments) (.const normalized.raw.name []) := by simp only [VExpr.instL, VExpr.instL_appN, - Lean4Lean.VLevel.inst_map_id hlevels, + Ix.Theory.VLevel.inst_map_id hlevels, shape.sourceLevels_nil, VInductDecl.bvarRevRange_instL] change VExpr.instRev @@ -270,7 +272,7 @@ left-to-right minor argument encoded by the dependent pattern path. -/ theorem ruleRhsBody_instantiated {source : VInductDecl} {generation : source.GenerationChecked} (index : Nat) (hindex : index < generation.block.ctorPairs.length) - (levels : List Lean4Lean.VLevel) (arguments : List VExpr) + (levels : List Ix.Theory.VLevel) (arguments : List VExpr) (harguments : arguments.length = generation.block.ctorPairs.length + 1) : VExpr.instRev @@ -464,7 +466,7 @@ theorem enumerationPatternMetadata /-- The compiled enum pattern is semantically justified by the exact registered generated equation. This is the central E2b bridge: a successful -pattern match is reduced through Lean4Lean's registered equality, rather than +pattern match is reduced through Ix.Theory.Named's registered equality, rather than through an independently postulated iota law. -/ theorem enumerationPatternSound {trProj : RawProjRel} {catalog : Catalog} @@ -491,7 +493,7 @@ theorem enumerationPatternSound generation.block.ctorPairs.length := by rw [family.constructorCount, ← generation.rawCtors_eq] simp - change Lean4Lean.Pattern.Matches + change Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern (.str generation.block.sourceType.name "rec") (family.constructorIds.size + 1) normalized.raw.name 0) @@ -506,7 +508,7 @@ theorem enumerationPatternSound htype.app_inv hfutureWF.ordered hGamma have hrecursorHead := - Lean4Lean.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied + Ix.Theory.Named.VEnv.HasType.appN_head hfutureWF hGamma hrecursorApplied obtain ⟨recursorHeadType, hrecursorHeadType⟩ := hrecursorHead obtain ⟨recursorConstant, hrecursorLookup, hlevelsWF, hlevelsArity⟩ := @@ -582,7 +584,7 @@ theorem enumerationPatternSound (.const (.str generation.block.sourceType.name "rec") levels) (generation.recType.instL levels) := by simpa [VInductDecl.GenerationChecked.recursor] using - (Lean4Lean.VEnv.HasType.const + (Ix.Theory.Named.VEnv.HasType.const (Γ := Gamma) hcertifiedRecursorLookup hlevelsWF hlevelsArity) have hrecursorCommonType : future.HasType uvars Gamma (.const (.str generation.block.sourceType.name "rec") levels) @@ -611,11 +613,11 @@ theorem enumerationPatternSound CertifiedSingletonGeneration.IsEnumeration.ruleBinders_length, hcount] obtain ⟨equationApplicationType, hequationLhsApplied⟩ := - Lean4Lean.VEnv.HasType.transfer_appN_telescope + Ix.Theory.Named.VEnv.HasType.transfer_appN_telescope hfutureWF hGamma hargumentLength hrecursorApplied hrecursorCommonType hequationLhsCommonType have hequationApplied := - Lean4Lean.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation + Ix.Theory.Named.VEnv.IsDefEq.appN_same hfutureWF hGamma hequation hequationLhsApplied have hequationRhsApplied : future.HasType uvars Gamma (VExpr.appN ((generation.rule index normalized).rhs.instL levels) @@ -639,7 +641,7 @@ theorem enumerationPatternSound rw [CertifiedSingletonGeneration.IsEnumeration.rule_lhs shape hnormalized, VExpr.instL_lamN] at hcopy exact hcopy - have hlhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hlhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hargumentLength hequationLhsApplied' rw [CertifiedSingletonGeneration.IsEnumeration.ruleLhsBody_instantiated shape normalized levels recursorArguments @@ -668,7 +670,7 @@ theorem enumerationPatternSound rw [CertifiedSingletonGeneration.IsEnumeration.rule_rhs shape hnormalized, VExpr.instL_lamN] at hcopy exact hcopy - have hrhsBeta := Lean4Lean.VEnv.HasType.lamN_appN_beta + have hrhsBeta := Ix.Theory.Named.VEnv.HasType.lamN_appN_beta hfutureWF hGamma hargumentLength hequationRhsApplied' have hindexGeneration : index < generation.block.ctorPairs.length := by simpa [hcount] using hindex @@ -713,7 +715,7 @@ theorem enumerationPatternSound simpa [SingletonRecursorCatalogLink.enumerationPattern, selected, RecursorIotaPattern.recursorArgumentRhs_apply, RecursorIotaPattern.recursorArgumentRhs, - Lean4Lean.Pattern.RHS.apply] using hresult + Ix.Theory.Named.Pattern.RHS.apply] using hresult /-- Package the finite pattern metadata and its registered-equation proof as the exact historical relation consumed by the production iota verifier. -/ @@ -742,4 +744,4 @@ theorem enumerationPatternRel end SingletonRecursorCatalogLink -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/SingletonFamily.lean b/Ix/Kernel/Verify/Inductive/SingletonFamily.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/SingletonFamily.lean rename to Ix/Kernel/Verify/Inductive/SingletonFamily.lean index 0a39133c1..57e960a1a 100644 --- a/Ix/Tc/Verify/Inductive/SingletonFamily.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonFamily.lean @@ -1,9 +1,9 @@ -import Ix.Tc.Verify.Inductive +import Ix.Kernel.Verify.Inductive /-! # Certified singleton-family admission -This module is the first production-facing half of E2b. A Lean4Lean +This module is the first production-facing half of E2b. A Ix.Theory.Named `CertifiedGenerationTransaction` already owns the semantic generation of one family, all of its constructors, its recursor, and its iota equations. What that transaction cannot know is which anonymous Ix addresses contain the @@ -26,9 +26,9 @@ are derived below from the E2a transaction. The later checker adapter must construct this link from ingress plus a successful production block run. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstVal VEnv VExpr VInductDecl) +open Ix.Theory.Named (VConstVal VEnv VExpr VInductDecl) /-! ## Header facts retained by normalized generation -/ @@ -470,4 +470,4 @@ def oracle end SingletonFamilyCatalogLink -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/SingletonIngress.lean b/Ix/Kernel/Verify/Inductive/SingletonIngress.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/SingletonIngress.lean rename to Ix/Kernel/Verify/Inductive/SingletonIngress.lean index 65f505047..06264b13a 100644 --- a/Ix/Tc/Verify/Inductive/SingletonIngress.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonIngress.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Inductive.SingletonRecursor -import Ix.Tc.Verify.Env +import Ix.Kernel.Verify.Inductive.SingletonRecursor +import Ix.Kernel.Verify.Env /-! # Loaded singleton-inductive ingress correspondence @@ -16,7 +16,7 @@ semantic authority to loading: recursor block; and * `toCatalogLink` transports those representation facts through `LoadedAgrees` and derives pre-admission freshness from the trusted log and - the Lean4Lean generation transaction. + the Ix.Theory.Named generation transaction. The views contain no catalog lookup, trusted-membership negation, declaration WF, or checker-success premise. In particular, an anonymous `KEnv` entry @@ -25,9 +25,9 @@ deliberate ghost input and will be constructed from the corresponding Ixon ingress trace. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstVal VEnv VInductDecl) +open Ix.Theory.Named (VConstVal VEnv VInductDecl) /-! ## Family and constructor ingress -/ @@ -124,7 +124,7 @@ theorem familyFresh Option.some.inj (hname.symm.trans view.familyName) subst name have hcollision : - (none : Option Lean4Lean.VConstant) = some ci := + (none : Option Ix.Theory.Named.VConstant) = some ci := tx.facts.familyFresh.symm.trans hlookup cases hcollision @@ -151,7 +151,7 @@ theorem constructorFresh tx.certificate.generation.block.sourceType.ctors := List.mem_of_getElem? hsource have hcollision : - (none : Option Lean4Lean.VConstant) = some ci := + (none : Option Ix.Theory.Named.VConstant) = some ci := (tx.facts.ctorFresh hsourceMem).symm.trans hlookup cases hcollision @@ -288,7 +288,7 @@ theorem recursorFresh Option.some.inj (hname.symm.trans view.recursorName) subst name have hcollision : - (none : Option Lean4Lean.VConstant) = some ci := + (none : Option Ix.Theory.Named.VConstant) = some ci := tx.facts.recursorFresh.symm.trans hlookup cases hcollision @@ -316,4 +316,4 @@ def toCatalogLink end SingletonRecursorIngressView -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/SingletonOracle.lean b/Ix/Kernel/Verify/Inductive/SingletonOracle.lean similarity index 96% rename from Ix/Tc/Verify/Inductive/SingletonOracle.lean rename to Ix/Kernel/Verify/Inductive/SingletonOracle.lean index 276ca8cf4..b35038ec6 100644 --- a/Ix/Tc/Verify/Inductive/SingletonOracle.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonOracle.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.SingletonEnumeration +import Ix.Kernel.Verify.Inductive.SingletonEnumeration /-! # Certificate-backed singleton recursor oracle @@ -10,9 +10,9 @@ generated equations and pattern-soundness theorem rather than an ambient reflection premise. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VEnv VInductDecl) +open Ix.Theory.Named (VEnv VInductDecl) namespace SingletonRecursorCatalogLink @@ -84,4 +84,4 @@ def oracle end SingletonRecursorCatalogLink -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/SingletonRecursor.lean b/Ix/Kernel/Verify/Inductive/SingletonRecursor.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/SingletonRecursor.lean rename to Ix/Kernel/Verify/Inductive/SingletonRecursor.lean index 489660981..f4e04c4d1 100644 --- a/Ix/Tc/Verify/Inductive/SingletonRecursor.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonRecursor.lean @@ -1,9 +1,9 @@ -import Ix.Tc.Verify.Inductive.SingletonFamily +import Ix.Kernel.Verify.Inductive.SingletonFamily /-! # Certified singleton-recursor correspondence -The Lean4Lean transaction used by E2a installs a singleton family's recursor +The Ix.Theory.Named transaction used by E2a installs a singleton family's recursor and all of its iota equations atomically with the family. Anonymous Ix ingress does not: the family/constructor block and the recursor block are distinct physical blocks. This module links the latter block to the exact @@ -16,9 +16,9 @@ compilation is kept for the next module because it has an additional semantic obligation beyond raw/structural translation. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstVal VDefEq VEnv VExpr VInductDecl) +open Ix.Theory.Named (VConstVal VDefEq VEnv VExpr VInductDecl) namespace CertifiedSingletonGeneration @@ -51,7 +51,7 @@ theorem rawConstructorAt {source : VInductDecl} exact hmapped /-- A generated iota equation is recursor-headed below its closed rule -telescope. This is the shape actually emitted by Lean4Lean; its outer node +telescope. This is the shape actually emitted by Ix.Theory.Named; its outer node is never directly a constant-headed application when the telescope is nonempty. -/ theorem generatedRuleHead {source : VInductDecl} @@ -120,7 +120,7 @@ theorem levels VInductDecl.GenerationChecked.recursor] /-- The physical recursor's declared K bit is exactly the independently -computed flag retained by the certified Lean4Lean generation. -/ +computed flag retained by the certified Ix.Theory.Named generation. -/ theorem kTarget {source : VInductDecl} {generation : source.GenerationChecked} {constructorIds : Array (KId .anon)} {concrete : KConst .anon} @@ -362,4 +362,4 @@ theorem member_eq end SingletonRecursorCatalogLink -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/SpecializationIdentity.lean b/Ix/Kernel/Verify/Inductive/SpecializationIdentity.lean similarity index 97% rename from Ix/Tc/Verify/Inductive/SpecializationIdentity.lean rename to Ix/Kernel/Verify/Inductive/SpecializationIdentity.lean index dbad71590..351868235 100644 --- a/Ix/Tc/Verify/Inductive/SpecializationIdentity.lean +++ b/Ix/Kernel/Verify/Inductive/SpecializationIdentity.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Inductive.OccurrenceValidation +import Ix.Kernel.Verify.Inductive.OccurrenceValidation /-! # Nested-inductive specialization identity @@ -9,7 +9,7 @@ intentionally broader than this identity: syntactically distinct applications receive distinct generated auxiliaries even when they denote equal types. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The production specialization key uses structural Boolean equality. Its derived implementation is lawful once raw address equality is known lawful. @@ -93,4 +93,4 @@ theorem semanticUniverseEquality_does_not_collapse_specialization : end SpecializationIdentityFixture -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Inductive/StructuralCacheSemantics.lean b/Ix/Kernel/Verify/Inductive/StructuralCacheSemantics.lean similarity index 99% rename from Ix/Tc/Verify/Inductive/StructuralCacheSemantics.lean rename to Ix/Kernel/Verify/Inductive/StructuralCacheSemantics.lean index 99cf177ee..1a240ec47 100644 --- a/Ix/Tc/Verify/Inductive/StructuralCacheSemantics.lean +++ b/Ix/Kernel/Verify/Inductive/StructuralCacheSemantics.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq +import Ix.Kernel.Verify.DefEq /-! # Certified semantics for inductive structural caches @@ -17,7 +17,7 @@ consumer obligation: the production recursor-member checker validates those artifacts exhaustively before accepting a stored recursor. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace CacheAuthority @@ -340,4 +340,4 @@ theorem insertRecursor end ScopedWhnfStateInv -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer.lean b/Ix/Kernel/Verify/Infer.lean similarity index 99% rename from Ix/Tc/Verify/Infer.lean rename to Ix/Kernel/Verify/Infer.lean index 8f347c140..b97f376b9 100644 --- a/Ix/Tc/Verify/Infer.lean +++ b/Ix/Kernel/Verify/Infer.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Suffix -import Ix.Tc.Verify.Knot +import Ix.Kernel.Verify.Suffix +import Ix.Kernel.Verify.Knot /-! # K2 inference semantics @@ -9,9 +9,9 @@ with its exact Theory meaning. Algorithmic branch proofs will consume the hit and insertion interfaces defined here. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace TcM @@ -349,4 +349,4 @@ theorem inferHitOfMatches {keys : WhnfContextKeys} {trProj : RawProjRel} end CacheInvariant -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/Applications.lean b/Ix/Kernel/Verify/Infer/Applications.lean similarity index 97% rename from Ix/Tc/Verify/Infer/Applications.lean rename to Ix/Kernel/Verify/Infer/Applications.lean index 53a71457b..6bee2d1b1 100644 --- a/Ix/Tc/Verify/Infer/Applications.lean +++ b/Ix/Kernel/Verify/Infer/Applications.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Infer.FunctionTypes -import Ix.Tc.Verify.Whnf.Beta.LambdaInstantiation +import Ix.Kernel.Verify.Infer.FunctionTypes +import Ix.Kernel.Verify.Whnf.Beta.LambdaInstantiation /-! # Application inference @@ -16,7 +16,7 @@ the exact family of substitution requests reachable after a supported codomain has been exposed. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite-support obligations for supported applications that reach the uncached inference dispatcher. Quantifying the final clause over supported @@ -73,7 +73,7 @@ private theorem applicationResult (theory : WhnfTheory trProj world uvars) (hDelta : KVLCtx.WF world.venv uvars Delta) {a cod : KExpr .anon} - {fV aV A B fTyV domV codV : Lean4Lean.VExpr} + {fV aV A B fTyV domV codV : Ix.Theory.Named.VExpr} (hfun : world.venv.HasType uvars Delta.toCtx fV (.forallE A B)) (harg : world.venv.HasType uvars Delta.toCtx aV A) (hargTr : TrKExprS world.venv uvars world.nameOf trProj Delta a aV) @@ -114,7 +114,7 @@ private theorem applicationResult refine ⟨codV.inst aV, ?_, ?_⟩ · exact hresultTr.trKExpr world.venvWF.ordered theory.literalWF theory.projections.wf hDelta - · exact (Lean4Lean.VEnv.HasType.app hfun harg).defeqU_r + · exact (Ix.Theory.Named.VEnv.HasType.app hfun harg).defeqU_r world.venvWF hDelta hcodInstEq /-- Execute the final substitution and package its support and Theory @@ -128,7 +128,7 @@ private theorem finishApplication_wf {s : TcState .anon} (theory : WhnfTheory trProj world uvars) {a cod : KExpr .anon} - {fV aV A B fTyV domV codV : Lean4Lean.VExpr} + {fV aV A B fTyV domV codV : Ix.Theory.Named.VExpr} (hfun : world.venv.HasType uvars Delta.toCtx fV (.forallE A B)) (harg : world.venv.HasType uvars Delta.toCtx aV A) (hargTr : TrKExprS world.venv uvars world.nameOf trProj Delta a aV) @@ -167,7 +167,7 @@ theorem inferUncached_app_wf {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {inferOnly : Bool} {f a : KExpr .anon} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hcomponents : ForallComponentSupport support) @@ -283,4 +283,4 @@ theorem inferUncached_app_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/BinderClosing.lean b/Ix/Kernel/Verify/Infer/BinderClosing.lean similarity index 98% rename from Ix/Tc/Verify/Infer/BinderClosing.lean rename to Ix/Kernel/Verify/Infer/BinderClosing.lean index a9773d984..6f4d580f2 100644 --- a/Ix/Tc/Verify/Infer/BinderClosing.lean +++ b/Ix/Kernel/Verify/Infer/BinderClosing.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.BinderScopes +import Ix.Kernel.Verify.Infer.BinderScopes /-! # Semantic binder closing for inference @@ -10,9 +10,9 @@ fvar abstraction retags the concrete expression back to the original de Bruijn context without changing its Theory translation. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLocalDecl) +open Ix.Theory.Named (VExpr VLocalDecl) namespace KVLCtx.RetagFVar @@ -110,7 +110,7 @@ theorem abstractFVarPositions_singleton_miss {fv other : FVarId} binder depth. `Constructed` supplies the no-wrap fact for the `i + 1` variable arm; the size bound supplies every recursive `depth + 1`. -/ theorem TrKExprS.closeFVarSpec - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} {target : KVLCtx} {body : KExpr .anon} {bodyV : VExpr} @@ -258,7 +258,7 @@ theorem TrKExprS.closeFVarSpec /-- Entry-depth form used after `openBinder`/`openLet`. -/ theorem TrKExprS.closeFVarZero - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} {Delta : KVLCtx} {decl : VLocalDecl} @@ -279,7 +279,7 @@ theorem TrKExprS.closeFVarZero /-- The API-level fast path is semantically identical to the singleton abstraction specification under its audited bounds. -/ theorem TrKExprS.closeFVarResult - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} {Delta : KVLCtx} {decl : VLocalDecl} @@ -432,4 +432,4 @@ theorem close_whnf_wf end SingletonAbstractionResources -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/BinderOpening.lean b/Ix/Kernel/Verify/Infer/BinderOpening.lean similarity index 98% rename from Ix/Tc/Verify/Infer/BinderOpening.lean rename to Ix/Kernel/Verify/Infer/BinderOpening.lean index ea9092332..8050b81e1 100644 --- a/Ix/Tc/Verify/Infer/BinderOpening.lean +++ b/Ix/Kernel/Verify/Infer/BinderOpening.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.ScopedLocals +import Ix.Kernel.Verify.Infer.ScopedLocals /-! # Semantic binder opening for inference @@ -10,9 +10,9 @@ that retagging and proves that `instantiateRev` preserves the translated Theory expression. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLocalDecl) +open Ix.Theory.Named (VExpr VLocalDecl) namespace KVLCtx @@ -125,7 +125,7 @@ end KVLCtx /-- Replacing one de Bruijn binder with its freshly tagged fvar leaves the Theory expression unchanged. -/ theorem TrKExprS.openFVar - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} {source : KVLCtx} {body : KExpr .anon} {bodyV : VExpr} @@ -282,7 +282,7 @@ theorem TrKExprS.openFVar /-- Entry-depth specialization used by the three production binder branches. -/ theorem TrKExprS.openFVarZero - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} {Delta : KVLCtx} {decl : VLocalDecl} @@ -297,4 +297,4 @@ theorem TrKExprS.openFVarZero (KExpr.instantiateRevSpec body #[.mkFVar fv name] 0) bodyV := H.openFVar .zero rfl (by simpa using hfresh) (by simpa using hbound) -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/BinderScopes.lean b/Ix/Kernel/Verify/Infer/BinderScopes.lean similarity index 98% rename from Ix/Tc/Verify/Infer/BinderScopes.lean rename to Ix/Kernel/Verify/Infer/BinderScopes.lean index a5d9281f2..64999d9ea 100644 --- a/Ix/Tc/Verify/Infer/BinderScopes.lean +++ b/Ix/Kernel/Verify/Infer/BinderScopes.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.BinderOpening +import Ix.Kernel.Verify.Infer.BinderOpening /-! # Operational binder scopes for inference @@ -9,9 +9,9 @@ opening a de Bruijn binder. This module verifies the production extension, walker execution, and the allocation-exhaustion error path. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-- Finite closure needed by a generic recursive method contract when it opens `body` with a freshly allocated anonymous-mode fvar. The fvar id is a @@ -53,7 +53,7 @@ theorem instRev_whnf_wf_of_resources InternUpdateFrame s after) := TcM.runIntern_whnf_wf (fun it hwf hsupport => by - have post := Ix.Tc.instantiateRev_spec hcollision.expr hbounds.1 + have post := Ix.Kernel.instantiateRev_spec hcollision.expr hbounds.1 hbounds.2.2 hreach hwf hsupport.expr exact ⟨post.1, post.2.1, hsupport.of_expr_univs post.2.2 @@ -78,7 +78,7 @@ theorem instRev_whnf_eval_of_resources InternUpdateFrame s after := TcM.runIntern_whnf_eval (fun it hwf hsupport => by - have post := Ix.Tc.instantiateRev_spec hcollision.expr hbounds.1 + have post := Ix.Kernel.instantiateRev_spec hcollision.expr hbounds.1 hbounds.2.2 hreach hwf hsupport.expr exact ⟨post.1, post.2.1, hsupport.of_expr_univs post.2.2 @@ -374,4 +374,4 @@ theorem withLctxScope_openBinder_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/CacheShell.lean b/Ix/Kernel/Verify/Infer/CacheShell.lean similarity index 99% rename from Ix/Tc/Verify/Infer/CacheShell.lean rename to Ix/Kernel/Verify/Infer/CacheShell.lean index e9166c92e..52a8e40d6 100644 --- a/Ix/Tc/Verify/Infer/CacheShell.lean +++ b/Ix/Kernel/Verify/Infer/CacheShell.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq +import Ix.Kernel.Verify.DefEq /-! # Inference cache shell @@ -9,7 +9,7 @@ partitions and for the full/infer-only miss paths, including partial errors before any result is cached. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -217,4 +217,4 @@ theorem inferWith_inferOnlyMiss_error end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/CacheSoundness.lean b/Ix/Kernel/Verify/Infer/CacheSoundness.lean similarity index 97% rename from Ix/Tc/Verify/Infer/CacheSoundness.lean rename to Ix/Kernel/Verify/Infer/CacheSoundness.lean index 620b3ebc9..54061b764 100644 --- a/Ix/Tc/Verify/Infer/CacheSoundness.lean +++ b/Ix/Kernel/Verify/Infer/CacheSoundness.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.Dispatcher +import Ix.Kernel.Verify.Infer.Dispatcher /-! # Inference cache soundness @@ -10,7 +10,7 @@ finite expression collision freedom, suffix transport, and the concrete uncached typing result before mutating either cache partition. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -90,7 +90,7 @@ private theorem missTail_wf (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars) {Delta : KVLCtx} {before s : TcState .anon} {inferOnly : Bool} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {key : Address × Address} (hmatch : model.keys.Matches trProj world before Delta source key) (hsourceSupport : support source) @@ -151,7 +151,7 @@ theorem inferWith_wf (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) : @@ -241,7 +241,7 @@ theorem infer_wf (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) : @@ -272,7 +272,7 @@ theorem nextInfer_wf (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars methods) : forall {Delta : KVLCtx} {s : TcState .anon} {source : KExpr .anon} - {sourceV : Lean4Lean.VExpr}, + {sourceV : Ix.Theory.Named.VExpr}, support source -> TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV -> @@ -287,4 +287,4 @@ theorem nextInfer_wf end UncachedInference.Context -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/Callbacks.lean b/Ix/Kernel/Verify/Infer/Callbacks.lean similarity index 92% rename from Ix/Tc/Verify/Infer/Callbacks.lean rename to Ix/Kernel/Verify/Infer/Callbacks.lean index fe79547e2..849a4183c 100644 --- a/Ix/Tc/Verify/Infer/Callbacks.lean +++ b/Ix/Kernel/Verify/Infer/Callbacks.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.Literals +import Ix.Kernel.Verify.Infer.Literals /-! # Inference callback contracts @@ -9,7 +9,7 @@ and the already-closed direct WHNF implementation used by `ensureSortDirect` and `ensureForallDirect`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace DirectWhnf @@ -36,7 +36,7 @@ theorem inferCall_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsource : support source) (htr : TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) : @@ -53,7 +53,7 @@ theorem isDefEqCall_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} (haSupport : support a) (hbSupport : support b) (ha : TrKExprS world.venv uvars world.nameOf trProj Delta a va) (hb : TrKExprS world.venv uvars world.nameOf trProj Delta b vb) : @@ -66,4 +66,4 @@ theorem isDefEqCall_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/CheapBeta.lean b/Ix/Kernel/Verify/Infer/CheapBeta.lean similarity index 98% rename from Ix/Tc/Verify/Infer/CheapBeta.lean rename to Ix/Kernel/Verify/Infer/CheapBeta.lean index 6675d9765..f7feb33a0 100644 --- a/Ix/Tc/Verify/Infer/CheapBeta.lean +++ b/Ix/Kernel/Verify/Infer/CheapBeta.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Infer.BinderScopes -import Ix.Tc.Verify.Whnf.Beta.Meaning -import Ix.Tc.Verify.Whnf.Structural.ApplicationCongruence +import Ix.Kernel.Verify.Infer.BinderScopes +import Ix.Kernel.Verify.Whnf.Beta.Meaning +import Ix.Kernel.Verify.Whnf.Structural.ApplicationCongruence /-! # Audited cheap beta reduction @@ -12,7 +12,7 @@ invariant. The Theory-level beta meaning is intentionally a separate layer; the operational theorem here cannot silently assume it. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM.BetaPeel @@ -215,7 +215,7 @@ theorem KExpr.cheapBetaReduceResult_meaning {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} (theory : WhnfTheory trProj world uvars) {Delta : KVLCtx} (hDelta : KVLCtx.WF world.venv uvars Delta) - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) (hbounds : WalkerRequest.Bounds (.cheapBeta source)) : @@ -459,4 +459,4 @@ theorem cheapBeta_whnf_wf end RunAssumptions -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/Constants.lean b/Ix/Kernel/Verify/Infer/Constants.lean similarity index 96% rename from Ix/Tc/Verify/Infer/Constants.lean rename to Ix/Kernel/Verify/Infer/Constants.lean index 11b35141d..d40014ef9 100644 --- a/Ix/Tc/Verify/Infer/Constants.lean +++ b/Ix/Kernel/Verify/Infer/Constants.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Infer.LeafCases -import Ix.Tc.Verify.Whnf.Delta.StableCache +import Ix.Kernel.Verify.Infer.LeafCases +import Ix.Kernel.Verify.Whnf.Delta.StableCache + +open Ix.Theory (VLevel) /-! # Constant inference @@ -12,7 +14,7 @@ closure must derive it from declaration admission rather than silently upgrading raw syntax correspondence. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -101,7 +103,7 @@ handled separately because production deliberately skips the walker there. -/ theorem instantiatedType {trProj : RawProjRel} {world : VerifyWorld} {id : KId .anon} {c : KConst .anon} {name : Lean.Name} - {ci : Lean4Lean.VConstant} + {ci : Ix.Theory.Named.VConstant} (h : TrustedConstRel trProj world id c name ci) (htype : TrKExprS world.venv ci.uvars world.nameOf trProj [] c.ty ci.type) @@ -138,7 +140,7 @@ theorem instantiatedType have hlevels := hciType.levelWF (by trivial) simpa only [hzero] using hlevels.1 have hinst : ci.type.instL [] = ci.type := by - simpa [Lean4Lean.VLevel.params] using hciLevels.instL_id + simpa [Ix.Theory.VLevel.params] using hciLevels.instL_id simpa [hinst] using htypeDelta.trKExpr world.venvWF.ordered theory.literalWF theory.projections.wf hDelta @@ -169,7 +171,7 @@ theorem inferUncached_const_wf {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hfault : TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) @@ -219,7 +221,7 @@ theorem inferUncached_const_wf sourceCi.type.instL (us.toList.map KUniv.toVLevel), ?_, ?_⟩ · exact hrel.instantiatedType htype theory hus harity hspec resources hIfinal.2.1.wf - · exact Lean4Lean.VEnv.HasType.const hlookup + · exact Ix.Theory.Named.VEnv.HasType.const hlookup (by intro level hlevel obtain ⟨source, hsourceLevel, rfl⟩ := List.mem_map.1 hlevel @@ -230,4 +232,4 @@ theorem inferUncached_const_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/Dispatcher.lean b/Ix/Kernel/Verify/Infer/Dispatcher.lean similarity index 94% rename from Ix/Tc/Verify/Infer/Dispatcher.lean rename to Ix/Kernel/Verify/Infer/Dispatcher.lean index 5642ebc49..e73864fa0 100644 --- a/Ix/Tc/Verify/Infer/Dispatcher.lean +++ b/Ix/Kernel/Verify/Infer/Dispatcher.lean @@ -1,11 +1,11 @@ -import Ix.Tc.Verify.Infer.Applications -import Ix.Tc.Verify.Infer.Constants -import Ix.Tc.Verify.Infer.ForallTypes -import Ix.Tc.Verify.Infer.LambdaTypes -import Ix.Tc.Verify.Infer.LeafCases -import Ix.Tc.Verify.Infer.LetTypes -import Ix.Tc.Verify.Infer.Literals -import Ix.Tc.Verify.Infer.ProjectionTypes +import Ix.Kernel.Verify.Infer.Applications +import Ix.Kernel.Verify.Infer.Constants +import Ix.Kernel.Verify.Infer.ForallTypes +import Ix.Kernel.Verify.Infer.LambdaTypes +import Ix.Kernel.Verify.Infer.LeafCases +import Ix.Kernel.Verify.Infer.LetTypes +import Ix.Kernel.Verify.Infer.Literals +import Ix.Kernel.Verify.Infer.ProjectionTypes /-! # Uncached inference dispatcher @@ -21,7 +21,7 @@ the syntax-only census facts. This avoids requiring facts about arbitrary invalid states merely to state recursive inference closure. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- State-indexed resources for the legacy de Bruijn-variable inference branch. The translated source establishes that the lookup is in range; this @@ -104,7 +104,7 @@ theorem inferUncached_wf (context : UncachedInference.Context initial program requests semantics trProj world support uvars) {Delta : KVLCtx} {s : TcState .anon} {inferOnly : Bool} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) : @@ -167,4 +167,4 @@ theorem inferUncached_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/ForallTypes.lean b/Ix/Kernel/Verify/Infer/ForallTypes.lean similarity index 95% rename from Ix/Tc/Verify/Infer/ForallTypes.lean rename to Ix/Kernel/Verify/Infer/ForallTypes.lean index efe4228c5..1f0b3435b 100644 --- a/Ix/Tc/Verify/Infer/ForallTypes.lean +++ b/Ix/Kernel/Verify/Infer/ForallTypes.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Infer.SortTypes -import Ix.Tc.Verify.Infer.BinderScopes +import Ix.Kernel.Verify.Infer.SortTypes +import Ix.Kernel.Verify.Infer.BinderScopes + +open Ix.Theory (VLevel) /-! # Forall inference @@ -10,7 +12,7 @@ opening and cleanup, the simplifying universe `imax` constructor, and final expression interning. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite result closure for `forall` inference. The premise ranges only over the finite universe support of the run, rather than over all levels. -/ @@ -29,7 +31,7 @@ private theorem inferForallTail_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {fv : FVarId} {deps : List FVarId} - {tyV bodyV input1 : Lean4Lean.VExpr} {bodyOpen : KExpr .anon} + {tyV bodyV input1 : Ix.Theory.Named.VExpr} {bodyOpen : KExpr .anon} {u1 : KUniv .anon} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) @@ -78,7 +80,7 @@ private theorem inferForallTail_wf hbodyTy.defeqU_r world.venvWF hIfinal.2.1.wf hu2.inputEq have hforall : world.venv.HasType uvars Delta.toCtx (.forallE tyV bodyV) (.sort (.imax u1.toVLevel u2.toVLevel)) := - Lean4Lean.VEnv.HasType.forallE htySort (by simpa using hbodySort) + Ix.Theory.Named.VEnv.HasType.forallE htySort (by simpa using hbodySort) have hlevelEq := hu1.mkIMax_equiv hcollision hu2 have hsortEq : world.venv.IsDefEqU uvars Delta.toCtx (.sort (.imax u1.toVLevel u2.toVLevel)) @@ -104,7 +106,7 @@ theorem inferUncached_all_wf {s : TcState .anon} {inferOnly : Bool} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body : KExpr .anon} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hresources : SortComponentResources support) @@ -155,4 +157,4 @@ theorem inferUncached_all_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/FunctionTypes.lean b/Ix/Kernel/Verify/Infer/FunctionTypes.lean similarity index 94% rename from Ix/Tc/Verify/Infer/FunctionTypes.lean rename to Ix/Kernel/Verify/Infer/FunctionTypes.lean index bc62597b0..6e0dd64a6 100644 --- a/Ix/Tc/Verify/Infer/FunctionTypes.lean +++ b/Ix/Kernel/Verify/Infer/FunctionTypes.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.Callbacks +import Ix.Kernel.Verify.Infer.Callbacks /-! # Function-type exposure for inference @@ -9,7 +9,7 @@ fallback expose the same semantic view, while retaining finite support for the returned domain and codomain. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite-support descent needed after a supported Pi is exposed. Run support is intentionally not globally constructor-closed. -/ @@ -23,7 +23,7 @@ the caller's quotient translation of the original inferred type to the exact structural translations of the returned concrete components. -/ def ForallView (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (Delta : KVLCtx) - (inputV : Lean4Lean.VExpr) (dom cod : KExpr .anon) : Prop := + (inputV : Ix.Theory.Named.VExpr) (dom cod : KExpr .anon) : Prop := exists domV codV, support dom /\ support cod /\ world.venv.IsType uvars Delta.toCtx domV /\ @@ -39,7 +39,7 @@ private theorem ensureForallWhnf_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {input : KExpr .anon} - {inputCoreV inputV : Lean4Lean.VExpr} + {inputCoreV inputV : Ix.Theory.Named.VExpr} (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hcomponents : ForallComponentSupport support) (hinputSupport : support input) @@ -76,7 +76,7 @@ theorem ensureForallDirect_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {input : KExpr .anon} - {inputV : Lean4Lean.VExpr} + {inputV : Ix.Theory.Named.VExpr} (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hcomponents : ForallComponentSupport support) (hinputSupport : support input) @@ -103,4 +103,4 @@ theorem ensureForallDirect_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/LambdaTypes.lean b/Ix/Kernel/Verify/Infer/LambdaTypes.lean similarity index 95% rename from Ix/Tc/Verify/Infer/LambdaTypes.lean rename to Ix/Kernel/Verify/Infer/LambdaTypes.lean index f543138d0..89e931f15 100644 --- a/Ix/Tc/Verify/Infer/LambdaTypes.lean +++ b/Ix/Kernel/Verify/Infer/LambdaTypes.lean @@ -1,7 +1,7 @@ -import Ix.Tc.Verify.Infer.CheapBeta -import Ix.Tc.Verify.Infer.BinderClosing -import Ix.Tc.Verify.Infer.SortTypes -import Ix.Tc.Verify.Whnf.Iota.ArgumentExecution +import Ix.Kernel.Verify.Infer.CheapBeta +import Ix.Kernel.Verify.Infer.BinderClosing +import Ix.Kernel.Verify.Infer.SortTypes +import Ix.Kernel.Verify.Whnf.Iota.ArgumentExecution /-! # Lambda inference @@ -11,7 +11,7 @@ validation, fresh-fvar binder opening, recursive body inference, cheap beta, singleton abstraction, anonymous Pi reconstruction, and scoped cleanup. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite closure for the anonymous Pi nodes produced from supported body types. The body argument ranges only over the finite run support. -/ @@ -29,7 +29,7 @@ private theorem inferLambdaTail_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {fv : FVarId} {deps : List FVarId} - {ty bodyOpen : KExpr .anon} {tyV bodyV : Lean4Lean.VExpr} + {ty bodyOpen : KExpr .anon} {tyV bodyV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hcheap : CheapBetaResources support) (habstract : SingletonAbstractionResources support) @@ -106,7 +106,7 @@ private theorem inferLambdaTail_wf (tyV :: Delta.toCtx) bodyV bodyTyV := by simpa [KVLCtx.toCtx] using hbodyTy exact ⟨hresultSupport, .forallE tyV bodyTyV, hresultTr, - Lean4Lean.VEnv.HasType.lam htySort hbodyTy'⟩ + Ix.Theory.Named.VEnv.HasType.lam htySort hbodyTy'⟩ · intro _ _ _ trivial @@ -118,7 +118,7 @@ private theorem inferLambdaScoped_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} - {ty body : KExpr .anon} {tyV bodyV : Lean4Lean.VExpr} + {ty body : KExpr .anon} {tyV bodyV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hcheap : CheapBetaResources support) (habstract : SingletonAbstractionResources support) @@ -177,7 +177,7 @@ theorem inferUncached_lam_wf {s : TcState .anon} {inferOnly : Bool} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body : KExpr .anon} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hsorts : SortComponentResources support) @@ -225,4 +225,4 @@ theorem inferUncached_lam_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/LeafCases.lean b/Ix/Kernel/Verify/Infer/LeafCases.lean similarity index 96% rename from Ix/Tc/Verify/Infer/LeafCases.lean rename to Ix/Kernel/Verify/Infer/LeafCases.lean index 9ae843527..ca6077b2d 100644 --- a/Ix/Tc/Verify/Infer/LeafCases.lean +++ b/Ix/Kernel/Verify/Infer/LeafCases.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Infer.CacheShell +import Ix.Kernel.Verify.Infer.CacheShell + +open Ix.Theory (VLevel) /-! # Non-recursive inference cases @@ -9,7 +11,7 @@ proofs separate makes the semantic boundary explicit: each branch must produce a supported concrete type together with a Theory typing derivation. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -55,7 +57,7 @@ theorem inferUncached_sort_wf {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {u : KUniv .anon} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hcollision : support.CollisionFree) (hresultSupport : support (KExpr.mkSort (KUniv.mkSucc u))) @@ -79,7 +81,7 @@ theorem inferUncached_sort_wf world.venvWF.ordered theory.literalWF theory.projections.wf hI.2.1.wf · simpa only [KUniv.toVLevel_mkSucc] using - (Lean4Lean.VEnv.HasType.sort hu) + (Ix.Theory.Named.VEnv.HasType.sort hu) · intro _ _ _ trivial @@ -95,7 +97,7 @@ theorem inferUncached_var_wf {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {idx : UInt64} {name : Mode.anon.F Name} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta (.var idx name info) sourceV) @@ -169,7 +171,7 @@ theorem inferUncached_fvar_wf {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {fv : FVarId} {name : Mode.anon.F Name} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hsafe : FVarInferSafety layer semantics trProj world support uvars Delta) @@ -206,4 +208,4 @@ theorem inferUncached_fvar_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/LetScopes.lean b/Ix/Kernel/Verify/Infer/LetScopes.lean similarity index 99% rename from Ix/Tc/Verify/Infer/LetScopes.lean rename to Ix/Kernel/Verify/Infer/LetScopes.lean index b2df97c68..a1abc967a 100644 --- a/Ix/Tc/Verify/Infer/LetScopes.lean +++ b/Ix/Kernel/Verify/Infer/LetScopes.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.BinderScopes +import Ix.Kernel.Verify.Infer.BinderScopes /-! # Operational let scopes for inference @@ -8,9 +8,9 @@ pushes an `ldecl` and translates to a Theory `vlet`. Keeping its proof separate makes that semantic distinction visible at the API boundary. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace TcM @@ -304,4 +304,4 @@ theorem withLctxScope_openLet_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/LetTypes.lean b/Ix/Kernel/Verify/Infer/LetTypes.lean similarity index 95% rename from Ix/Tc/Verify/Infer/LetTypes.lean rename to Ix/Kernel/Verify/Infer/LetTypes.lean index fe98e4165..bc614b75d 100644 --- a/Ix/Tc/Verify/Infer/LetTypes.lean +++ b/Ix/Kernel/Verify/Infer/LetTypes.lean @@ -1,9 +1,9 @@ -import Ix.Tc.Verify.Infer.LetScopes -import Ix.Tc.Verify.Infer.BinderClosing -import Ix.Tc.Verify.Infer.Substitution -import Ix.Tc.Verify.Infer.CheapBeta -import Ix.Tc.Verify.Infer.SortTypes -import Ix.Tc.Verify.Whnf.Iota.ArgumentExecution +import Ix.Kernel.Verify.Infer.LetScopes +import Ix.Kernel.Verify.Infer.BinderClosing +import Ix.Kernel.Verify.Infer.Substitution +import Ix.Kernel.Verify.Infer.CheapBeta +import Ix.Kernel.Verify.Infer.SortTypes +import Ix.Kernel.Verify.Whnf.Iota.ArgumentExecution /-! # Let inference @@ -13,7 +13,7 @@ body inference, singleton abstraction, eager value substitution, cheap beta, and scoped cleanup for the production `letE` branch. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -25,7 +25,7 @@ private theorem inferLetTail_wf {Delta : KVLCtx} {s : TcState .anon} {fv : FVarId} {deps : List FVarId} {val bodyOpen : KExpr .anon} - {tyV valV bodyV : Lean4Lean.VExpr} + {tyV valV bodyV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (habstract : SingletonAbstractionResources support) (hsubst : SubstitutionResources support) @@ -96,7 +96,7 @@ private theorem inferLetScoped_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {name : Mode.anon.F Name} - {ty val body : KExpr .anon} {tyV valV bodyV : Lean4Lean.VExpr} + {ty val body : KExpr .anon} {tyV valV bodyV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (habstract : SingletonAbstractionResources support) (hsubst : SubstitutionResources support) @@ -154,7 +154,7 @@ theorem inferUncached_let_wf {s : TcState .anon} {inferOnly : Bool} {name : Mode.anon.F Name} {ty val body : KExpr .anon} {nondep : Bool} {info : ExprInfo .anon} - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hsorts : SortComponentResources support) @@ -225,4 +225,4 @@ theorem inferUncached_let_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/Literals.lean b/Ix/Kernel/Verify/Infer/Literals.lean similarity index 88% rename from Ix/Tc/Verify/Infer/Literals.lean rename to Ix/Kernel/Verify/Infer/Literals.lean index e3caab00f..039f26d01 100644 --- a/Ix/Tc/Verify/Infer/Literals.lean +++ b/Ix/Kernel/Verify/Infer/Literals.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.Constants +import Ix.Kernel.Verify.Infer.Constants /-! # Literal inference @@ -11,7 +11,7 @@ constant accepts an empty universe array. Those representation obligations are therefore exposed explicitly below. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact Theory interpretation of the two primitive-table entries read by literal inference. Trust and address-to-name agreement come from @@ -35,7 +35,7 @@ theorem nat_tr (hcatalog : TrustedCatalogRel trProj world) (htable : LiteralPrimitiveTableAgrees world prims) : TrKExprS world.venv uvars world.nameOf trProj Delta - (KExpr.mkConst prims.nat #[]) Lean4Lean.VExpr.nat := by + (KExpr.mkConst prims.nat #[]) Ix.Theory.Named.VExpr.nat := by rw [KExpr.mkConst_shape] obtain ⟨ci, hlookup⟩ := htable.nat.contains hcatalog exact @@ -49,7 +49,7 @@ theorem string_tr (hcatalog : TrustedCatalogRel trProj world) (htable : LiteralPrimitiveTableAgrees world prims) : TrKExprS world.venv uvars world.nameOf trProj Delta - (KExpr.mkConst prims.string #[]) Lean4Lean.VExpr.string := by + (KExpr.mkConst prims.string #[]) Ix.Theory.Named.VExpr.string := by rw [KExpr.mkConst_shape] obtain ⟨ci, hlookup⟩ := htable.string.contains hcatalog exact @@ -83,7 +83,7 @@ theorem inferUncached_nat_wf {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon -> RecM .anon (KExpr .anon)} {inferOnly : Bool} {n : Nat} {blob : Address} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (context : LiteralInferContext world support) (theory : WhnfTheory trProj world uvars) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta @@ -110,14 +110,14 @@ theorem inferUncached_nat_wf TcM.intern_whnf_wf context.collisionFree hsupport) · intro result final hresult rcases hresult with ⟨hIfinal, rfl, _⟩ - refine ⟨hsupport, Lean4Lean.VExpr.nat, ?_, ?_⟩ + refine ⟨hsupport, Ix.Theory.Named.VExpr.nat, ?_, ?_⟩ · exact (htable.nat_tr hcatalog).trKExpr world.venvWF.ordered theory.literalWF theory.projections.wf hIfinal.2.1.wf · have htype0 : world.venv.HasType uvars [] - (.natLit n) Lean4Lean.VExpr.nat := by - simpa [Lean4Lean.VLCtx.toCtx] using - (Lean4Lean.TrExprS.natLit + (.natLit n) Ix.Theory.Named.VExpr.nat := by + simpa [Ix.Theory.Named.VLCtx.toCtx] using + (Ix.Theory.Named.TrExprS.natLit (Us := List.replicate uvars Lean.Name.anonymous) (Δ := []) context.theoryPrimitives hcontains n).2 exact htype0.weak0 world.venvWF (Γ := Delta.toCtx) @@ -125,7 +125,7 @@ theorem inferUncached_nat_wf trivial /-- A concrete String literal infers the runtime String constant. The source -typing is the full Lean4Lean literal construction, including `Char.ofNat` and +typing is the full Ix.Theory.Named literal construction, including `Char.ofNat` and `String.ofList`; the returned type is still the primitive `String` entry. -/ theorem inferUncached_str_wf {semantics : CacheSemantics} {trProj : RawProjRel} @@ -133,7 +133,7 @@ theorem inferUncached_str_wf {Delta : KVLCtx} {s : TcState .anon} {inferRec : KExpr .anon -> RecM .anon (KExpr .anon)} {inferOnly : Bool} {value : String} {blob : Address} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (context : LiteralInferContext world support) (theory : WhnfTheory trProj world uvars) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta @@ -160,15 +160,15 @@ theorem inferUncached_str_wf TcM.intern_whnf_wf context.collisionFree hsupport) · intro result final hresult rcases hresult with ⟨hIfinal, rfl, _⟩ - refine ⟨hsupport, Lean4Lean.VExpr.string, ?_, ?_⟩ + refine ⟨hsupport, Ix.Theory.Named.VExpr.string, ?_, ?_⟩ · exact (htable.string_tr hcatalog).trKExpr world.venvWF.ordered theory.literalWF theory.projections.wf hIfinal.2.1.wf · have htype0 : world.venv.HasType uvars [] - (.trLiteral (.strVal value)) Lean4Lean.VExpr.string := by - simpa [Lean4Lean.VExpr.string, Lean4Lean.VLCtx.toCtx, + (.trLiteral (.strVal value)) Ix.Theory.Named.VExpr.string := by + simpa [Ix.Theory.Named.VExpr.string, Ix.Theory.Named.VLCtx.toCtx, Lean.Literal.typeName] using - (Lean4Lean.TrExprS.trLiteral world.venvWF.ordered + (Ix.Theory.Named.TrExprS.trLiteral world.venvWF.ordered (Us := List.replicate uvars Lean.Name.anonymous) (Δ := []) context.theoryPrimitives (.strVal value) hcontains).2 exact htype0.weak0 world.venvWF (Γ := Delta.toCtx) @@ -177,4 +177,4 @@ theorem inferUncached_str_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/ProjectionClassification.lean b/Ix/Kernel/Verify/Infer/ProjectionClassification.lean similarity index 97% rename from Ix/Tc/Verify/Infer/ProjectionClassification.lean rename to Ix/Kernel/Verify/Infer/ProjectionClassification.lean index f4d490b6d..5ee091fa3 100644 --- a/Ix/Tc/Verify/Infer/ProjectionClassification.lean +++ b/Ix/Kernel/Verify/Infer/ProjectionClassification.lean @@ -1,7 +1,7 @@ import Init.Data.Range.Lemmas -import Ix.Tc.Verify.Infer.Constants -import Ix.Tc.Verify.Infer.ProjectionTelescope -import Ix.Tc.Verify.Whnf.StructEta.RecursionClassifier +import Ix.Kernel.Verify.Infer.Constants +import Ix.Kernel.Verify.Infer.ProjectionTelescope +import Ix.Kernel.Verify.Whnf.StructEta.RecursionClassifier /-! # Projection result-sort classification @@ -15,7 +15,7 @@ those intermediate bodies have a structural translation in the caller's context. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The exact universe-instantiation request selected when the classifier's lookup returns the catalogued inductive declaration. Other declaration @@ -194,4 +194,4 @@ theorem inductiveAppIsProp_state_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/ProjectionTelescope.lean b/Ix/Kernel/Verify/Infer/ProjectionTelescope.lean similarity index 94% rename from Ix/Tc/Verify/Infer/ProjectionTelescope.lean rename to Ix/Kernel/Verify/Infer/ProjectionTelescope.lean index 177ac930d..3a10513b3 100644 --- a/Ix/Tc/Verify/Infer/ProjectionTelescope.lean +++ b/Ix/Kernel/Verify/Infer/ProjectionTelescope.lean @@ -1,6 +1,6 @@ import Init.Data.Range.Lemmas -import Ix.Tc.Verify.Infer.LetTypes -import Ix.Tc.Verify.Infer.FunctionTypes +import Ix.Kernel.Verify.Infer.LetTypes +import Ix.Kernel.Verify.Infer.FunctionTypes /-! # Projection telescope exposure @@ -11,7 +11,7 @@ WHNF reducer. This module proves that both paths expose the same supported Theory forall view; the diagnostic string affects only the error payload. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- A concrete argument is admissible for every supported Π view that the production peeler may expose from `inputV`. The universal formulation avoids @@ -19,8 +19,8 @@ choosing a particular structural translation before WHNF has run; translation uniqueness makes all successful views definitionally coherent. -/ def ProjectionArgumentFits (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (Delta : KVLCtx) - (inputV : Lean4Lean.VExpr) (arg : KExpr .anon) : Prop := - ∀ {dom cod : KExpr .anon} {domV codV : Lean4Lean.VExpr}, + (inputV : Ix.Theory.Named.VExpr) (arg : KExpr .anon) : Prop := + ∀ {dom cod : KExpr .anon} {domV codV : Ix.Theory.Named.VExpr}, support dom → support cod → world.venv.IsType uvars Delta.toCtx domV → world.venv.IsType uvars (domV :: Delta.toCtx) codV → @@ -41,7 +41,7 @@ theorem peelProjForall_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {input : KExpr .anon} - {inputV : Lean4Lean.VExpr} {err : String} + {inputV : Ix.Theory.Named.VExpr} {err : String} (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hcomponents : ForallComponentSupport support) (hinputSupport : support input) @@ -89,7 +89,7 @@ private theorem substProjForallBody_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} - {inputV : Lean4Lean.VExpr} {dom body arg : KExpr .anon} + {inputV : Ix.Theory.Named.VExpr} {dom body arg : KExpr .anon} (theory : WhnfTheory trProj world uvars) (hsubst : SubstitutionResources support) (hcollision : support.CollisionFree) @@ -136,7 +136,7 @@ private theorem instantiateProjParamBody_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} - {current arg : KExpr .anon} {currentV : Lean4Lean.VExpr} + {current arg : KExpr .anon} {currentV : Ix.Theory.Named.VExpr} {err : String} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) @@ -171,7 +171,7 @@ theorem instantiateProjParamStep_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {args : Array (KExpr .anon)} {i : Nat} (hidx : i < args.size) - {current : KExpr .anon} {currentV : Lean4Lean.VExpr} + {current : KExpr .anon} {currentV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hcomponents : ForallComponentSupport support) @@ -215,14 +215,14 @@ replace any intermediate produced by `subst`. -/ def ProjectionParameterPlan (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (Delta : KVLCtx) (args : Array (KExpr .anon)) : - List Nat → Lean4Lean.VExpr → Prop + List Nat → Ix.Theory.Named.VExpr → Prop | [], _ => True | i :: indices, currentV => ∃ hidx : i < args.size, support (args[i]'hidx) ∧ ProjectionArgumentFits trProj world support uvars Delta currentV (args[i]'hidx) ∧ - ∀ {next : KExpr .anon} {nextV : Lean4Lean.VExpr}, + ∀ {next : KExpr .anon} {nextV : Ix.Theory.Named.VExpr}, support next → TrKExpr world.venv uvars world.nameOf trProj Delta next nextV → ProjectionParameterPlan trProj world support uvars Delta args @@ -242,7 +242,7 @@ theorem instantiateProjParamsList_wf (hcollision : support.CollisionFree) {args : Array (KExpr .anon)} : ∀ (indices : List Nat) {current : KExpr .anon} - {currentV : Lean4Lean.VExpr} {s : TcState .anon}, + {currentV : Ix.Theory.Named.VExpr} {s : TcState .anon}, support current → TrKExpr world.venv uvars world.nameOf trProj Delta current currentV → ProjectionParameterPlan trProj world support uvars Delta args indices @@ -289,7 +289,7 @@ theorem instantiateProjParams_wf (hsubst : SubstitutionResources support) (hcollision : support.CollisionFree) {args : Array (KExpr .anon)} {numParams : Nat} - {ctorTy : KExpr .anon} {ctorTyV : Lean4Lean.VExpr} + {ctorTy : KExpr .anon} {ctorTyV : Ix.Theory.Named.VExpr} (hctorSupport : support ctorTy) (hctor : TrKExpr world.venv uvars world.nameOf trProj Delta ctorTy ctorTyV) @@ -314,9 +314,9 @@ theorem instantiateProjParams_wf supported Π view of the current constructor-field telescope. -/ def ProjectionFieldResultFits (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) - (uvars : Nat) (Delta : KVLCtx) (inputV projectedV : Lean4Lean.VExpr) : + (uvars : Nat) (Delta : KVLCtx) (inputV projectedV : Ix.Theory.Named.VExpr) : Prop := - ∀ {dom body : KExpr .anon} {domV bodyV : Lean4Lean.VExpr}, + ∀ {dom body : KExpr .anon} {domV bodyV : Ix.Theory.Named.VExpr}, support dom → support body → world.venv.IsType uvars Delta.toCtx domV → world.venv.IsType uvars (domV :: Delta.toCtx) bodyV → @@ -333,8 +333,8 @@ substitutes; it cannot choose the subsequent telescope result. -/ structure ProjectionFieldStepPlan (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (Delta : KVLCtx) (structId : KId .anon) - (field : UInt64) (val : KExpr .anon) (projectedV : Lean4Lean.VExpr) - (i : Nat) (currentV : Lean4Lean.VExpr) : Prop where + (field : UInt64) (val : KExpr .anon) (projectedV : Ix.Theory.Named.VExpr) + (i : Nat) (currentV : Ix.Theory.Named.VExpr) : Prop where selected : i = field.toNat → ProjectionFieldResultFits trProj world support uvars Delta currentV projectedV @@ -347,7 +347,7 @@ structure ProjectionFieldStepPlan intermediate telescope yielded to the surrounding traversal. -/ def ProjectionFieldActionPost (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) - (uvars : Nat) (Delta : KVLCtx) (projectedV : Lean4Lean.VExpr) : + (uvars : Nat) (Delta : KVLCtx) (projectedV : Ix.Theory.Named.VExpr) : ForInStep (KExpr .anon) → Prop | .done result => support result ∧ InferPost trProj world uvars Delta projectedV result @@ -363,7 +363,7 @@ private theorem inferProjectionFieldSort_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} - {dom : KExpr .anon} {domV : Lean4Lean.VExpr} + {dom : KExpr .anon} {domV : Ix.Theory.Named.VExpr} (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hsorts : SortComponentResources support) (hdomSupport : support dom) @@ -388,7 +388,7 @@ private theorem finishSelectedProjectionField_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} - {inputV projectedV : Lean4Lean.VExpr} + {inputV projectedV : Ix.Theory.Named.VExpr} {dom body : KExpr .anon} (theory : WhnfTheory trProj world uvars) (hview : ForallView trProj world support uvars Delta inputV dom body) @@ -418,7 +418,7 @@ private theorem finishPrecedingProjectionField_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {structId : KId .anon} {i : Nat} {val : KExpr .anon} - {inputV projectedV : Lean4Lean.VExpr} + {inputV projectedV : Ix.Theory.Named.VExpr} {dom body : KExpr .anon} (theory : WhnfTheory trProj world uvars) (hsubst : SubstitutionResources support) @@ -455,7 +455,7 @@ theorem inferProjFieldStep_wf {Delta : KVLCtx} {s : TcState .anon} {structId : KId .anon} {field : UInt64} {val current : KExpr .anon} {isPropStruct : Bool} {i : Nat} - {currentV projectedV : Lean4Lean.VExpr} + {currentV projectedV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hcomponents : ForallComponentSupport support) @@ -532,13 +532,13 @@ production fold immediately. -/ def ProjectionFieldPlan (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (Delta : KVLCtx) (structId : KId .anon) - (field : UInt64) (val : KExpr .anon) (projectedV : Lean4Lean.VExpr) : - List Nat → Lean4Lean.VExpr → Prop + (field : UInt64) (val : KExpr .anon) (projectedV : Ix.Theory.Named.VExpr) : + List Nat → Ix.Theory.Named.VExpr → Prop | [], _ => True | i :: indices, currentV => ProjectionFieldStepPlan trProj world support uvars Delta structId field val projectedV i currentV ∧ - ∀ {next : KExpr .anon} {nextV : Lean4Lean.VExpr}, + ∀ {next : KExpr .anon} {nextV : Ix.Theory.Named.VExpr}, support next → TrKExpr world.venv uvars world.nameOf trProj Delta next nextV → ProjectionFieldPlan trProj world support uvars Delta structId field @@ -549,7 +549,7 @@ def ProjectionFieldPlan last yielded telescope and will be rejected by production as unreachable. -/ def ProjectionFieldLoopPost (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) - (uvars : Nat) (Delta : KVLCtx) (projectedV : Lean4Lean.VExpr) : + (uvars : Nat) (Delta : KVLCtx) (projectedV : Ix.Theory.Named.VExpr) : Option (KExpr .anon) × KExpr .anon → Prop | (some result, _) => support result ∧ InferPost trProj world uvars Delta projectedV result @@ -565,7 +565,7 @@ private theorem inferProjFieldLoopStep_wf {Delta : KVLCtx} {s : TcState .anon} {structId : KId .anon} {field : UInt64} {val current : KExpr .anon} {isPropStruct : Bool} {i : Nat} - {currentV projectedV : Lean4Lean.VExpr} + {currentV projectedV : Ix.Theory.Named.VExpr} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hcomponents : ForallComponentSupport support) @@ -619,9 +619,9 @@ theorem inferProjFieldsList_wf (hsubst : SubstitutionResources support) (hcollision : support.CollisionFree) {structId : KId .anon} {field : UInt64} {val : KExpr .anon} - {isPropStruct : Bool} {projectedV : Lean4Lean.VExpr} : + {isPropStruct : Bool} {projectedV : Ix.Theory.Named.VExpr} : ∀ (indices : List Nat) {current : KExpr .anon} - {currentV : Lean4Lean.VExpr} {s : TcState .anon}, + {currentV : Ix.Theory.Named.VExpr} {s : TcState .anon}, support current → TrKExpr world.venv uvars world.nameOf trProj Delta current currentV → ProjectionFieldPlan trProj world support uvars Delta structId field val @@ -671,7 +671,7 @@ theorem inferProjFields_wf (hsubst : SubstitutionResources support) (hcollision : support.CollisionFree) {structId : KId .anon} {field : UInt64} {val ctorTy : KExpr .anon} - {isPropStruct : Bool} {ctorTyV projectedV : Lean4Lean.VExpr} + {isPropStruct : Bool} {ctorTyV projectedV : Ix.Theory.Named.VExpr} (hctorSupport : support ctorTy) (hctor : TrKExpr world.venv uvars world.nameOf trProj Delta ctorTy ctorTyV) @@ -703,4 +703,4 @@ theorem inferProjFields_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/ProjectionTypes.lean b/Ix/Kernel/Verify/Infer/ProjectionTypes.lean similarity index 97% rename from Ix/Tc/Verify/Infer/ProjectionTypes.lean rename to Ix/Kernel/Verify/Infer/ProjectionTypes.lean index 80a1762a7..f1e3cfe9a 100644 --- a/Ix/Tc/Verify/Infer/ProjectionTypes.lean +++ b/Ix/Kernel/Verify/Infer/ProjectionTypes.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.ProjectionClassification +import Ix.Kernel.Verify.Infer.ProjectionClassification /-! # Projection inference @@ -19,7 +19,7 @@ edge, error propagation, and composition with the helper—without treating a successful helper execution as semantic evidence by itself. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite child coverage for a supported projection source. Run support is finite and intentionally not closed under arbitrary syntax descent. -/ @@ -66,7 +66,7 @@ structure ConstructorTypingPlan (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (Delta : KVLCtx) (structId : KId .anon) (field : UInt64) (val : KExpr .anon) - (projectedV : Lean4Lean.VExpr) (args : Array (KExpr .anon)) + (projectedV : Ix.Theory.Named.VExpr) (args : Array (KExpr .anon)) (levels : Array (KUniv .anon)) (numParams : Nat) (ctorTy : KExpr .anon) : Prop where instantiated : ∀ {instantiated : KExpr .anon}, @@ -81,7 +81,7 @@ structure ConstructorTypingPlan ([0:numParams] : _root_.Std.Legacy.Range).step) instantiatedV ∧ ∀ {parameterized : KExpr .anon} - {parameterizedV : Lean4Lean.VExpr}, + {parameterizedV : Ix.Theory.Named.VExpr}, support parameterized → TrKExpr world.venv uvars world.nameOf trProj Delta parameterized parameterizedV → @@ -101,7 +101,7 @@ selection, and the source projection witness. -/ def DeclarationOracle (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) : Prop := ∀ {Delta : KVLCtx} {structId headId : KId .anon} {field : UInt64} - {val : KExpr .anon} {valV projectedV valTyV reducedTyV : Lean4Lean.VExpr} + {val : KExpr .anon} {valV projectedV valTyV reducedTyV : Ix.Theory.Named.VExpr} {structName : Lean.Name} {levels : Array (KUniv .anon)} {headInfo : ExprInfo .anon} {args : Array (KExpr .anon)} {indName : Mode.anon.F Name} @@ -141,7 +141,7 @@ def WF (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) : Prop := ∀ {Delta : KVLCtx} {s : TcState .anon} {structId : KId .anon} {field : UInt64} {val valTy : KExpr .anon} - {valV projectedV : Lean4Lean.VExpr} {structName : Lean.Name}, + {valV projectedV : Ix.Theory.Named.VExpr} {structName : Lean.Name}, world.nameOf structId.addr = some structName → TrKExprS world.venv uvars world.nameOf trProj Delta val valV → trProj uvars Delta.toCtx structName field.toNat valV projectedV → @@ -190,7 +190,7 @@ theorem inferProj_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {structId : KId .anon} {field : UInt64} - {val valTy : KExpr .anon} {valV projectedV : Lean4Lean.VExpr} + {val valTy : KExpr .anon} {valV projectedV : Ix.Theory.Named.VExpr} {structName : Lean.Name} (theory : WhnfTheory trProj world uvars) (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) @@ -355,7 +355,7 @@ theorem inferUncached_prj_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {inferOnly : Bool} {structId : KId .anon} {field : UInt64} {val : KExpr .anon} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} (hinputs : ProjectionValueSupport support) (hprojection : ProjectionInference.WF semantics trProj world support uvars) @@ -380,4 +380,4 @@ theorem inferUncached_prj_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/ScopedLocals.lean b/Ix/Kernel/Verify/Infer/ScopedLocals.lean similarity index 97% rename from Ix/Tc/Verify/Infer/ScopedLocals.lean rename to Ix/Kernel/Verify/Infer/ScopedLocals.lean index 05d5b0013..627a7e0ab 100644 --- a/Ix/Tc/Verify/Infer/ScopedLocals.lean +++ b/Ix/Kernel/Verify/Infer/ScopedLocals.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.Callbacks +import Ix.Kernel.Verify.Infer.Callbacks /-! # Scoped local contexts for inference @@ -9,7 +9,7 @@ and failure. This module connects the operational cleanup to the ghost context used by the verification invariant. -/ -namespace Ix.Tc +namespace Ix.Kernel @[simp] theorem LocalContext.truncate_size (lctx : LocalContext m) : lctx.truncate lctx.size = lctx := by @@ -110,7 +110,7 @@ theorem openFVar {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {before after : TcState .anon} - {d : LocalDecl .anon} {vd : Lean4Lean.VLocalDecl} + {d : LocalDecl .anon} {vd : Ix.Theory.Named.VLocalDecl} {deps : List FVarId} (hbefore : WhnfStateInv layer semantics trProj world support uvars Delta before) @@ -140,7 +140,7 @@ theorem closeFVar {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {fv : FVarId} {deps : List FVarId} - {vd : Lean4Lean.VLocalDecl} {saved : Nat} + {vd : Ix.Theory.Named.VLocalDecl} {saved : Nat} (h : WhnfStateInv layer semantics trProj world support uvars ((some (fv, deps), vd) :: Delta) s) (hsaved : saved = Delta.fvars.length) : @@ -163,7 +163,7 @@ theorem closeFVarAtEntry {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {before after : TcState .anon} {fv : FVarId} {deps : List FVarId} - {vd : Lean4Lean.VLocalDecl} + {vd : Ix.Theory.Named.VLocalDecl} (hbefore : WhnfStateInv layer semantics trProj world support uvars Delta before) (hafter : WhnfStateInv layer semantics trProj world support uvars @@ -238,4 +238,4 @@ theorem withLctxScope_eq (x : RecM .anon α) end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/SortTypes.lean b/Ix/Kernel/Verify/Infer/SortTypes.lean similarity index 92% rename from Ix/Tc/Verify/Infer/SortTypes.lean rename to Ix/Kernel/Verify/Infer/SortTypes.lean index ad66c499a..f7d5b5dc3 100644 --- a/Ix/Tc/Verify/Infer/SortTypes.lean +++ b/Ix/Kernel/Verify/Infer/SortTypes.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Infer.Callbacks +import Ix.Kernel.Verify.Infer.Callbacks + +open Ix.Theory (VLevel) /-! # Sort exposure for inference @@ -8,7 +10,7 @@ an inferred type. This module proves the syntactic sort fast path and the direct-WHNF fallback against one shared semantic view. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite descent resources for a supported concrete sort. Smart universe constructors compare addresses throughout their argument subtrees and use @@ -24,7 +26,7 @@ def SortComponentResources (support : RunSupport) : Prop := connects the caller's quotient translation to the selected Theory sort and retains exactly the subtree support needed by later smart constructors. -/ structure SortView (world : VerifyWorld) (support : RunSupport) - (uvars : Nat) (Delta : KVLCtx) (inputV : Lean4Lean.VExpr) + (uvars : Nat) (Delta : KVLCtx) (inputV : Ix.Theory.Named.VExpr) (result : KUniv .anon) : Prop where sizeBound : result.size < UInt64.size subtermSupport : ∀ x, KUniv.Sub x result → support.univ x @@ -34,7 +36,7 @@ structure SortView (world : VerifyWorld) (support : RunSupport) theorem SortView.rootSupport {world : VerifyWorld} {support : RunSupport} {uvars : Nat} - {Delta : KVLCtx} {inputV : Lean4Lean.VExpr} {result : KUniv .anon} + {Delta : KVLCtx} {inputV : Ix.Theory.Named.VExpr} {result : KUniv .anon} (h : SortView world support uvars Delta inputV result) : support.univ result := h.subtermSupport result .refl @@ -46,7 +48,7 @@ comparison made by the smart constructor is covered by the two finite subterm footprints retained in the sort views. -/ theorem mkIMax_equiv {world : VerifyWorld} {support : RunSupport} {uvars : Nat} - {DeltaA DeltaB : KVLCtx} {inputA inputB : Lean4Lean.VExpr} + {DeltaA DeltaB : KVLCtx} {inputA inputB : Ix.Theory.Named.VExpr} {a b : KUniv .anon} (hcf : support.CollisionFree) (ha : SortView world support uvars DeltaA inputA a) @@ -73,7 +75,7 @@ private theorem ensureSortWhnf_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {input : KExpr .anon} - {inputCoreV inputV : Lean4Lean.VExpr} + {inputCoreV inputV : Ix.Theory.Named.VExpr} (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hresources : SortComponentResources support) (hinputSupport : support input) @@ -109,7 +111,7 @@ theorem ensureSortDirect_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {input : KExpr .anon} - {inputV : Lean4Lean.VExpr} + {inputV : Ix.Theory.Named.VExpr} (hwhnf : DirectWhnf.WFAt semantics trProj world support uvars) (hresources : SortComponentResources support) (hinputSupport : support input) @@ -136,4 +138,4 @@ theorem ensureSortDirect_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Infer/Substitution.lean b/Ix/Kernel/Verify/Infer/Substitution.lean similarity index 93% rename from Ix/Tc/Verify/Infer/Substitution.lean rename to Ix/Kernel/Verify/Infer/Substitution.lean index c3308fc95..0a74bf1b1 100644 --- a/Ix/Tc/Verify/Infer/Substitution.lean +++ b/Ix/Kernel/Verify/Infer/Substitution.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.Callbacks +import Ix.Kernel.Verify.Infer.Callbacks /-! # Recursive-result substitution resources @@ -8,7 +8,7 @@ callback. Since that body is dynamic, this module exposes the walker through a finite support closure rather than static request-list membership. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite operational and arithmetic closure for substitution over supported inputs. -/ @@ -44,7 +44,7 @@ theorem whnf_wf hbodySupport hargSupport apply TcM.WF.mono (TcM.runIntern_whnf_wf (fun it hwf hcover => by - have post := Ix.Tc.subst_spec hcollision.expr hbody harg hcut hargsz + have post := Ix.Kernel.subst_spec hcollision.expr hbody harg hcut hargsz hreach hwf hcover.expr exact ⟨post.1, post.2.1, hcover.of_expr_univs post.2.2 @@ -57,4 +57,4 @@ theorem whnf_wf end SubstitutionResources -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/InferDefEq/Closure.lean b/Ix/Kernel/Verify/InferDefEq/Closure.lean similarity index 96% rename from Ix/Tc/Verify/InferDefEq/Closure.lean rename to Ix/Kernel/Verify/InferDefEq/Closure.lean index 58527e9ed..830f4759b 100644 --- a/Ix/Tc/Verify/InferDefEq/Closure.lean +++ b/Ix/Kernel/Verify/InferDefEq/Closure.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq.Closure -import Ix.Tc.Verify.Infer.CacheSoundness +import Ix.Kernel.Verify.DefEq.Closure +import Ix.Kernel.Verify.Infer.CacheSoundness /-! # Recursive inference and definitional-equality closure @@ -10,7 +10,7 @@ universe induction step: both fields may call a strictly smaller method table, and neither proof assumes the next table is already sound. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Concrete resources for the inference and DefEq fields of one production method-table layer. The shared proposition context fixes the suffix model, @@ -66,4 +66,4 @@ theorem closedAt end InferDefEqClosureContext -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Ingress/AnonStructural.lean b/Ix/Kernel/Verify/Ingress/AnonStructural.lean similarity index 94% rename from Ix/Tc/Verify/Ingress/AnonStructural.lean rename to Ix/Kernel/Verify/Ingress/AnonStructural.lean index 77f899f4c..0c3cb779e 100644 --- a/Ix/Tc/Verify/Ingress/AnonStructural.lean +++ b/Ix/Kernel/Verify/Ingress/AnonStructural.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Const -import Ix.Tc.Verify.Expr +import Ix.Kernel.Const +import Ix.Kernel.Verify.Expr /-! # Structural equality for anonymous kernel values @@ -14,7 +14,7 @@ left-inverse back to the production datatype. Equality reflected through that left-inverse is therefore structural equality, not hash equality. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace AnonStructural def addressDecidableEq : DecidableEq Address := @@ -63,13 +63,13 @@ structure ExprInfo where hasFVars : Bool deriving DecidableEq -def ExprInfo.ofKernel (info : Ix.Tc.ExprInfo .anon) : ExprInfo := +def ExprInfo.ofKernel (info : Ix.Kernel.ExprInfo .anon) : ExprInfo := ⟨info.addr, info.lbr, info.count0, info.hasFVars⟩ -def ExprInfo.toKernel (info : ExprInfo) : Ix.Tc.ExprInfo .anon := +def ExprInfo.toKernel (info : ExprInfo) : Ix.Kernel.ExprInfo .anon := ⟨info.addr, info.lbr, info.count0, info.hasFVars, (), (), ()⟩ -@[simp] theorem ExprInfo.roundtrip (info : Ix.Tc.ExprInfo .anon) : +@[simp] theorem ExprInfo.roundtrip (info : Ix.Kernel.ExprInfo .anon) : (ofKernel info).toKernel = info := by cases info rfl @@ -135,13 +135,13 @@ structure RecRule where rhs : Expr deriving DecidableEq -def RecRule.ofKernel (rule : Ix.Tc.RecRule .anon) : RecRule := +def RecRule.ofKernel (rule : Ix.Kernel.RecRule .anon) : RecRule := ⟨rule.fields, Expr.ofKernel rule.rhs⟩ -def RecRule.toKernel (rule : RecRule) : Ix.Tc.RecRule .anon := +def RecRule.toKernel (rule : RecRule) : Ix.Kernel.RecRule .anon := ⟨(), rule.fields, rule.rhs.toKernel⟩ -@[simp] theorem RecRule.roundtrip (rule : Ix.Tc.RecRule .anon) : +@[simp] theorem RecRule.roundtrip (rule : Ix.Kernel.RecRule .anon) : (ofKernel rule).toKernel = rule := by cases rule simp [ofKernel, toKernel] @@ -228,4 +228,4 @@ def constDecidableEq : DecidableEq (KConst .anon) := decidableEqOfRoundtrip Const.ofKernel Const.toKernel Const.roundtrip end AnonStructural -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Ingress/LiteralBlobs.lean b/Ix/Kernel/Verify/Ingress/LiteralBlobs.lean similarity index 99% rename from Ix/Tc/Verify/Ingress/LiteralBlobs.lean rename to Ix/Kernel/Verify/Ingress/LiteralBlobs.lean index 41aa8c664..4b266d104 100644 --- a/Ix/Tc/Verify/Ingress/LiteralBlobs.lean +++ b/Ix/Kernel/Verify/Ingress/LiteralBlobs.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Ingress.AnonStructural -import Ix.Tc.Verify.Ingress.Representation +import Ix.Kernel.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Ingress.Representation /-! # Serialized literal/blob ingress @@ -12,7 +12,7 @@ malformed environments demonstrate that the decoder rejects a constant or a blob stored under an address that does not commit to its bytes. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace SerializedLiteralBlobs local instance addressDecidableEq : DecidableEq Address := @@ -462,4 +462,4 @@ theorem malformedBlobRejected : IxonEnv.serializedDecodeRejected_of_true malformedBlobRejectedNative end SerializedLiteralBlobs -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Ingress/Representation.lean b/Ix/Kernel/Verify/Ingress/Representation.lean similarity index 98% rename from Ix/Tc/Verify/Ingress/Representation.lean rename to Ix/Kernel/Verify/Ingress/Representation.lean index 79640e35e..4711d3c26 100644 --- a/Ix/Tc/Verify/Ingress/Representation.lean +++ b/Ix/Kernel/Verify/Ingress/Representation.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Driver.Enumeration -import Ix.Tc.Verify.Driver.Serial -import Ix.Tc.Verify.Whnf.Runtime.LazyIngress +import Ix.Kernel.Verify.Driver.Enumeration +import Ix.Kernel.Verify.Driver.Serial +import Ix.Kernel.Verify.Whnf.Runtime.LazyIngress /-! # Serialized Ixon representation correspondence @@ -18,7 +18,7 @@ later Rust transport phase; T0 reasons from the pure decoder and the actual Lean eager/lazy ingress functions. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace IxonEnv @@ -261,4 +261,4 @@ def SerializedSubjectWF (bytes : ByteArray) (world : VerifyWorld) Nonempty (SerializedSubjectCertificate bytes world dependencies assumptions lazyRequests) -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Ingress/SerializedBoolean.lean b/Ix/Kernel/Verify/Ingress/SerializedBoolean.lean similarity index 99% rename from Ix/Tc/Verify/Ingress/SerializedBoolean.lean rename to Ix/Kernel/Verify/Ingress/SerializedBoolean.lean index 3d5cdaac7..fbd208d02 100644 --- a/Ix/Tc/Verify/Ingress/SerializedBoolean.lean +++ b/Ix/Kernel/Verify/Ingress/SerializedBoolean.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Driver.BooleanAcceptance -import Ix.Tc.Verify.Ingress.AnonStructural -import Ix.Tc.Verify.Ingress.Representation +import Ix.Kernel.Verify.Driver.BooleanAcceptance +import Ix.Kernel.Verify.Ingress.AnonStructural +import Ix.Kernel.Verify.Ingress.Representation /-! # Serialized Boolean acceptance @@ -11,7 +11,7 @@ decoder, erases anonymous-irrelevant metadata, and reconnects the decoded source to the existing E3-S semantic world. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace BooleanSerialized open BooleanEnumerationFixture @@ -996,4 +996,4 @@ theorem subjectWF : ⟨certificate⟩ end BooleanSerialized -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/InstL.lean b/Ix/Kernel/Verify/InstL.lean similarity index 95% rename from Ix/Tc/Verify/InstL.lean rename to Ix/Kernel/Verify/InstL.lean index a22da5287..e80a4eb37 100644 --- a/Ix/Tc/Verify/InstL.lean +++ b/Ix/Kernel/Verify/InstL.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Trans -import Ix.Tc.Verify.InstUniv +import Ix.Kernel.Verify.Trans +import Ix.Kernel.Verify.InstUniv + +open Ix.Theory (VLevel) /-! # Universe instantiation tracks `VExpr.instL` through the translation @@ -20,9 +22,9 @@ The collision-freedom and no-wrap side conditions quantify over per level). -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLevel VEnv) +open Ix.Theory.Named (VExpr VEnv) /-! ### Level occurrences and the reach set -/ @@ -207,25 +209,25 @@ private theorem forall₂_toVLevel {us : Array (KUniv .anon)} : spine carries only the literal level `.zero`, which `inst` fixes.) -/ private theorem instL_listCharLit (s : List Char) (ls : List VLevel) : - (Lean4Lean.VExpr.listCharLit s).instL ls - = Lean4Lean.VExpr.listCharLit s := by + (Ix.Theory.Named.VExpr.listCharLit s).instL ls + = Ix.Theory.Named.VExpr.listCharLit s := by induction s with | nil => rfl | cons c s ih => - show Lean4Lean.VExpr.app (Lean4Lean.VExpr.app _ (Lean4Lean.VExpr.app _ - ((Lean4Lean.VExpr.natLit c.toNat).instL ls))) - ((Lean4Lean.VExpr.listCharLit s).instL ls) = _ - rw [Lean4Lean.VExpr.instL_natLit, ih] + show Ix.Theory.Named.VExpr.app (Ix.Theory.Named.VExpr.app _ (Ix.Theory.Named.VExpr.app _ + ((Ix.Theory.Named.VExpr.natLit c.toNat).instL ls))) + ((Ix.Theory.Named.VExpr.listCharLit s).instL ls) = _ + rw [Ix.Theory.Named.VExpr.instL_natLit, ih] rfl private theorem instL_trLiteral (l : Lean.Literal) (ls : List VLevel) : - (Lean4Lean.VExpr.trLiteral l).instL ls - = Lean4Lean.VExpr.trLiteral l := by + (Ix.Theory.Named.VExpr.trLiteral l).instL ls + = Ix.Theory.Named.VExpr.trLiteral l := by cases l with - | natVal v => exact Lean4Lean.VExpr.instL_natLit + | natVal v => exact Ix.Theory.Named.VExpr.instL_natLit | strVal s => - show Lean4Lean.VExpr.app _ - ((Lean4Lean.VExpr.listCharLit _).instL ls) = _ + show Ix.Theory.Named.VExpr.app _ + ((Ix.Theory.Named.VExpr.listCharLit _).instL ls) = _ rw [instL_listCharLit] rfl @@ -321,7 +323,7 @@ theorem TrKExprS.instL {env : VEnv} {uvars U' : Nat} have harr := array_mapM_ok hmus have hsize : vs.size = curUs.size := by rw [← Array.length_toList, ← Array.length_toList] - exact (Lean4Lean.List.Forall₂.length_eq harr).symm + exact (Ix.Theory.Named.List.Forall₂.length_eq harr).symm have hwf : ∀ w ∈ vs, (KUniv.toVLevel w).WF U' := by intro w hw obtain ⟨a, _, hab⟩ := forall₂_mem_right harr w (by simpa using hw) @@ -473,9 +475,9 @@ theorem TrKExprS.instL {env : VEnv} {uvars U' : Nat} = .ok (.nat n blob md) := rfl rw [hb] at hr cases hr - rw [show (Lean4Lean.VExpr.natLit n).instL + rw [show (Ix.Theory.Named.VExpr.natLit n).instL (us.toList.map KUniv.toVLevel) - = Lean4Lean.VExpr.natLit n from Lean4Lean.VExpr.instL_natLit] + = Ix.Theory.Named.VExpr.natLit n from Ix.Theory.Named.VExpr.instL_natLit] exact (TrKExprS.nat l1).trKExpr henv.ordered hlit htp.wf (wf_instL_size hus hΔ) | @str Δ s blob md l1 => @@ -488,4 +490,4 @@ theorem TrKExprS.instL {env : VEnv} {uvars U' : Nat} exact (TrKExprS.str l1).trKExpr henv.ordered hlit htp.wf (wf_instL_size hus hΔ) -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/InstUniv.lean b/Ix/Kernel/Verify/InstUniv.lean similarity index 99% rename from Ix/Tc/Verify/InstUniv.lean rename to Ix/Kernel/Verify/InstUniv.lean index 2dff7aa99..c3f2e2d1e 100644 --- a/Ix/Tc/Verify/InstUniv.lean +++ b/Ix/Kernel/Verify/InstUniv.lean @@ -1,13 +1,13 @@ -import Ix.Tc.Verify.Subst -import Ix.Tc.Verify.Monad -import Ix.Tc.Verify.Level +import Ix.Kernel.Verify.Subst +import Ix.Kernel.Verify.Monad +import Ix.Kernel.Verify.Level /-! # `instantiateUnivParams` memo-soundness The last of the five expression walkers: universe-parameter substitution with per-call address-keyed memoization (`TcM.instUnivInner`, -`Ix/Tc/Monad.lean`). Unlike the four `WalkM` siblings this one runs over +`Ix/Kernel/Monad.lean`). Unlike the four `WalkM` siblings this one runs over `TcM` — `StateT (HashMap Address (KExpr m)) (TcM m)` — so its soundness statement is the first composition of the walker kit with the EStateM Hoare kernel (`TcM.WF`): the intern table lives inside `TcState.env`, @@ -30,11 +30,11 @@ Scope: anon mode, matching the sibling masters (`internKey = addr`, `eraseMeta = id`, exact spec equality). -/ -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap) open EStateM (Result) -open Lean4Lean (VLevel) +open Ix.Theory (VLevel) /-! ### The pure spec -/ diff --git a/Ix/Tc/Verify/Knot.lean b/Ix/Kernel/Verify/Knot.lean similarity index 99% rename from Ix/Tc/Verify/Knot.lean rename to Ix/Kernel/Verify/Knot.lean index f09d54e96..a4fda3c5c 100644 --- a/Ix/Tc/Verify/Knot.lean +++ b/Ix/Kernel/Verify/Knot.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf +import Ix.Kernel.Verify.Whnf /-! # Verification of the recursive method knot @@ -18,7 +18,7 @@ K1 supplies the four WHNF fields and K2 supplies inference and definitional equality. No theorem below assumes the recursive table is already closed. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace Methods @@ -353,4 +353,4 @@ theorem runRec_wfAt end TcM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Level.lean b/Ix/Kernel/Verify/Level.lean similarity index 98% rename from Ix/Tc/Verify/Level.lean rename to Ix/Kernel/Verify/Level.lean index d4f2e486f..3dfb8d4b5 100644 --- a/Ix/Tc/Verify/Level.lean +++ b/Ix/Kernel/Verify/Level.lean @@ -1,16 +1,13 @@ -import Ix.Tc.Level +import Ix.Kernel.Level import Batteries.Recycling.RBTree.Lemmas -import Lean4Lean.Theory.VLevel +import Ix.Theory.Named.VLevel /-! -# Level slice: `KUniv` soundness against `Lean4Lean.Theory.VLevel` +# Universe soundness against `Ix.Theory.VLevel` -The first verification slice. This file is also the lean4lean-interop -spike. Interop outcome (2026-07-21): proof files are **classic** (no `module` header) — -a `module` file cannot import the classic-import lean4lean dep at all -(`cannot import non-`module` … from `module``), while classic files import -module-system `Ix.Tc` fine and see its `@[expose]` bodies. The sanity -`rfl`-lemmas below certify the cross-boundary unfolding. +These proofs use classic imports to combine the named specification's helper +lemmas with the exposed production definitions in `Ix.Kernel`. The `rfl` +lemmas below verify unfolding across that module boundary. `KUniv` and `VLevel` align constructor-for-constructor (both carry positional params), so the translation `toVLevel` is a total structural @@ -21,23 +18,22 @@ the headline theorems state that the kernel's `univEq`/`univGeq` decide compared pair (the `CollisionFree` pilot: `==` on `KUniv` is Blake3 address equality, sound only up to hash collisions). -Status: the slice is **sorry-free** — the full chain `univEq_sound` / -`univGeq_sound` ← `normalizeLevel_eval` ← the 4-way `normalizeAux_eval` -keystone + `subsumption_eval` (upstream's `Verify/Level.lean:545` is -still a live sorry there; proven here via the pure per-key model and a -lex (path length, constant-after-var) strong induction) is closed, -conditional only on addr-faithfulness and the UInt64 no-wrap bounds. +The proofs of `univEq_sound` and `univGeq_sound` contain no proof holes. +They use `normalizeLevel_eval`, the four cases of `normalizeAux_eval`, and +`subsumption_eval`, with address faithfulness and UInt64 bounds as explicit +hypotheses. Subsumption is proved using a pure model of each key and strong +induction on path length and the constant contribution after a variable. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VLevel) +open Ix.Theory (VLevel) variable {m : Mode} namespace KUniv -/-- Translate a kernel level to the lean4lean theory's `VLevel`. +/-- Translate a kernel level to the shared theory's `VLevel`. Structure-preserving; addresses and display names are dropped (`VLevel` is the fully anonymous mathematical object). -/ def toVLevel : KUniv m → VLevel @@ -72,7 +68,7 @@ def eraseMeta : KUniv m → KUniv .anon | param => rfl /-! Interop sanity checks: these unfold `@[expose]` bodies from -`Ix.Tc.Level` (smart constructors through `Id.run`) against `VLevel` +`Ix.Kernel.Level` (smart constructors through `Id.run`) against `VLevel` constructors from the classic-import dep — the interop spike proper. -/ theorem toVLevel_mkZero : (mkZero (m := m)).toVLevel = .zero := rfl @@ -118,15 +114,11 @@ theorem KUniv.toVLevel_of_isZero {v : KUniv m} (h : v.isZero = true) : /-! ### Denotation of the canonical form -Port of the upstream denotation layer (lean4lean `Verify/Level.lean`, -`evalParam`/`Node.eval`/`evalPath`/`NormLevel.eval`), leaner here because -params are positional (no `ls : List Name` plumbing — `evalParam` *is* -`VLevel.eval`'s param case) but with a genuinely new obligation class: Ix -stores offsets/constants as `UInt64`, so the normalization bookkeeping's -`+ 1`s carry no-wrap side conditions, threaded as size bounds -(`k.toNat + l.size < UInt64.size`). An in-memory `KUniv` can never -violate them; a 2⁶⁴-succ tower genuinely would wrap and mis-normalize — -the hypotheses are load-bearing, not pedantry. -/ +This adapts the denotation layer in `Ix.Theory.Named.Verify.Level` to +positional parameters: `evalParam` is the parameter case of `VLevel.eval`. +Ix stores offsets and constants as `UInt64`, so additions also require +bounds preventing wraparound, such as `k.toNat + l.size < UInt64.size`. +Those bounds are explicit hypotheses throughout the normalization proof. -/ namespace Level @@ -281,7 +273,7 @@ private theorem foldl_max_le {α : Type _} {l : List α} {f : α → Nat} | nil => simp | cons a l ih => rw [List.foldl_cons, ih, Nat.max_le] - simp [List.forall_mem_cons, and_assoc] + simp [and_assoc] theorem NormNode.eval_le {ρ : List Nat} {n : NormNode} {x : Nat} : n.eval ρ ≤ x ↔ n.constant.toNat ≤ x ∧ ∀ v ∈ n.vars, v.eval ρ ≤ x := by @@ -450,14 +442,16 @@ theorem EvalPaths.one_le {ρ : List Nat} {path : Path} {n : Nat} private theorem imax_max (a b c : Nat) : Lean.Nat.imax a (max b c) = max (Lean.Nat.imax a b) (Lean.Nat.imax a c) := by by_cases hb : b = 0 <;> by_cases hc : c = 0 <;> - simp [Lean.Nat.imax, hb, hc, Nat.max_eq_max, Nat.max_eq_zero_iff] <;> omega + simp [Lean.Nat.imax, hb, hc, Nat.max_eq_max, Nat.max_eq_zero_iff] + all_goals omega /-- `imax(a, imax(b, c)) = max(imax(a, c), imax(b, c))` — the semantic content of the `normalizeImaxImax` rewrite. -/ private theorem imax_imax (a b c : Nat) : Lean.Nat.imax a (Lean.Nat.imax b c) = max (Lean.Nat.imax a c) (Lean.Nat.imax b c) := by by_cases hc : c = 0 <;> by_cases hb : b = 0 <;> - simp [Lean.Nat.imax, hb, hc, Nat.max_eq_max, Nat.max_eq_zero_iff] <;> omega + simp [Lean.Nat.imax, hb, hc, Nat.max_eq_max, Nat.max_eq_zero_iff] + all_goals omega /-! #### Insert-eval lemmas -/ @@ -738,7 +732,7 @@ private theorem normalizeAux_eval' {ρ : List Nat} : | .imax u (.zero b_ad) ad, path, k, acc, hk, hp => by simp only [normalizeAux] rw [NormLevel.addConst_eval hp] - simp [KUniv.toVLevel, VLevel.eval, Lean.Nat.imax] + simp [KUniv.toVLevel, VLevel.eval, VLevel.natIMax] | .imax u (.succ v b_ad) ad, path, k, acc, hk, hp => by have hk1 : (k + 1).toNat = k.toNat + 1 := toNat_add_one (by simp [KUniv.size] at hk; omega) @@ -928,7 +922,7 @@ private theorem normalizeImaxDispatch_eval' {ρ : List Nat} : | a, .zero b_ad, path, k, acc, hk, hp => by simp only [normalizeImaxDispatch] rw [NormLevel.addConst_eval hp] - simp [KUniv.toVLevel, VLevel.eval, Lean.Nat.imax] + simp [KUniv.toVLevel, VLevel.eval, VLevel.natIMax] | a, .succ v b_ad, path, k, acc, hk, hp => by have hsza := KUniv.size_pos a have hk1 : (k + 1).toNat = k.toNat + 1 := @@ -1182,7 +1176,7 @@ theorem subsumption_eq_model (acc : NormLevel) : rw [processEntry] refine forIn_id_eq_foldl _ _ _ _ ?_ rintro ⟨p2, n2⟩ hmem2 n1 - simp only [letFun, subsumeStep] + simp only [subsumeStep] split · split · split @@ -1789,7 +1783,7 @@ theorem varsOnPath_subsumption {l : NormLevel} (hl : VarsOnPath l) : (P := fun (n1f : NormNode) => ∀ v ∈ n1f.vars, v ∈ n1₀.vars) _ _ _ ?_ ?_ · exact fun v hv => hv rintro ⟨p2, n2⟩ hmem2 n1cur hcur v hv - simp only [match_id_ite, match_id_bind_unit] at hv + simp only [match_id_ite] at hv split at hv · split at hv · split at hv @@ -2335,8 +2329,7 @@ private theorem le_subsumptionModel_eval {ρ : List Nat} {l : NormLevel} exact ⟨CC (p1.length + 1) p1 n1₀ hf (Nat.lt_succ_self _) hnz, fun v hv => V (p1.length + 1) p1 n1₀ hf (Nat.lt_succ_self _) hnz v hv⟩ -/-- **Fresh** (upstream's live sorry, lean4lean `Verify/Level.lean:545`): - the subsumption pass drops only dominated contributions. Needs the +/-- The subsumption pass drops only dominated contributions. Needs the var-placement invariant (stated raw; defeq to `VarsOnPath l`): the `maxVarOffset + 1` zeroing branch is justified by a var of the *same* entry whose active index contributes ≥ 1 — for raw maps it is @@ -2400,7 +2393,7 @@ theorem KUniv.isSemanticZero_eq_false {m : Mode} {u : KUniv m} rw [KUniv.isSemanticZero, Bool.or_eq_false_iff] refine ⟨?_, ?_⟩ · cases u <;> simp_all [KUniv.isZero, KUniv.toVLevel, - Lean4Lean.VLevel.eval] + Ix.Theory.VLevel.eval] · rw [Bool.eq_false_iff, ne_eq, List.all_eq_true] intro hall have hzero : Level.NormLevel.eval ρ (Level.normalizeLevel u) = 0 := @@ -2417,7 +2410,7 @@ theorem KUniv.toVLevel_equiv_zero_of_isSemanticZero {m : Mode} {u : KUniv m} (hu : u.size < UInt64.size) (hzero : u.isSemanticZero = true) : KUniv.toVLevel u ≈ .zero := by rw [KUniv.isSemanticZero, Bool.or_eq_true] at hzero - refine Lean4Lean.VLevel.equiv_def.mpr fun ρ => ?_ + refine Ix.Theory.VLevel.equiv_def.mpr fun ρ => ?_ show _ = 0 rcases hzero with h | h · rw [KUniv.toVLevel_of_isZero h]; rfl @@ -2455,7 +2448,7 @@ theorem normLevelLe_sound {u v : KUniv m} universe-equality decision procedure accepts, the translations are semantically equal under every parameter assignment. Conditional on addr-faithfulness of the compared pair (the `u == v` fast path at - Ix/Tc/Level.lean:426 — discharged through the `CollisionFree` pilot) + Ix/Kernel/Level.lean:426 — discharged through the `CollisionFree` pilot) and the UInt64 no-wrap size bounds. -/ theorem univEq_sound {u v : KUniv m} (hinj : u.AddrFaithful v) (hu : u.size < UInt64.size) (hv : v.size < UInt64.size) @@ -2468,7 +2461,7 @@ theorem univEq_sound {u v : KUniv m} (hinj : u.AddrFaithful v) /-- **Soundness of `univGeq`** (headline, Level slice): if the kernel accepts `u ≥ v`, then `⟦v⟧ρ ≤ ⟦u⟧ρ` for every assignment. All three - disjuncts of Ix/Tc/Level.lean:430 discharged: the addr fast path via + disjuncts of Ix/Kernel/Level.lean:430 discharged: the addr fast path via addr-faithfulness, `v.isZero` via `VLevel.zero_le`, and the canonical order via `normLevelLe_sound`. -/ theorem univGeq_sound {u v : KUniv m} (hinj : u.AddrFaithful v) @@ -2482,7 +2475,7 @@ theorem univGeq_sound {u v : KUniv m} (hinj : u.AddrFaithful v) /-! ### Simplifying smart constructors: `mkMax`/`mkIMax` soundness -`substUniv` (universe instantiation, `Ix/Tc/Monad.lean`) rebuilds with +`substUniv` (universe instantiation, `Ix/Kernel/Monad.lean`) rebuilds with the SIMPLIFYING `mkMax`/`mkIMax` (Lean/Rust parity), so its Theory correspondence is an equivalence `≈`, never a syntactic equality. This block proves the two constructors sound wrt `VLevel.eval`, conditional @@ -2979,4 +2972,4 @@ theorem toVLevel_mkIMax_wf {n : Nat} {a b : KUniv m} end KUniv -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Monad.lean b/Ix/Kernel/Verify/Monad.lean similarity index 98% rename from Ix/Tc/Verify/Monad.lean rename to Ix/Kernel/Verify/Monad.lean index b49e3b0a0..0d1789cd7 100644 --- a/Ix/Tc/Verify/Monad.lean +++ b/Ix/Kernel/Verify/Monad.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Knot +import Ix.Kernel.Knot /-! # EStateM Hoare kernel for `TcM` @@ -6,7 +6,7 @@ import Ix.Tc.Knot The verification's Hoare kernel, core form. `TcM m = EStateM (TcError m) (TcState m)` is **non-backtracking**: state written before a throw survives `tryCatch` (cache inserts, consumed fuel — load-bearing Rust parity, see -Ix/Tc/Monad.lean's module doc). So unlike lean4lean's `M.WF` (StateT over +Ix/Kernel/Monad.lean's module doc). So unlike the named specification's `M.WF` (StateT over `Except`, where errors discard state and `throw := nofun`), the triple here constrains **both outcomes**: an invariant `I` holds on the post-state of success *and* error, `Q` on success, `E` on error (default trivial — most @@ -18,7 +18,7 @@ immutable catalog and a growing trusted semantic environment; the combinator lemmas below carry over verbatim. -/ -namespace Ix.Tc +namespace Ix.Kernel variable {m : Mode} @@ -246,4 +246,4 @@ theorem TcM.tick.wf {I : TcState m → Prop} · exact TcM.WF.throw fun _ => ⟨rfl, rfl⟩ · exact TcM.WF.set (fun hI => hfuel _ hI) (fun _ => rfl) -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/NatFixture.lean b/Ix/Kernel/Verify/NatFixture.lean similarity index 98% rename from Ix/Tc/Verify/NatFixture.lean rename to Ix/Kernel/Verify/NatFixture.lean index 70c7df3b5..ce4d55760 100644 --- a/Ix/Tc/Verify/NatFixture.lean +++ b/Ix/Kernel/Verify/NatFixture.lean @@ -1,6 +1,8 @@ -import Ix.Tc.Verify.Run -import Ix.Tc.Verify.Whnf -import Ix.Tc.Verify.Whnf.Structural.BetaBoundary +import Ix.Kernel.Verify.Run +import Ix.Kernel.Verify.Whnf +import Ix.Kernel.Verify.Whnf.Structural.BetaBoundary + +open Ix.Theory (VLevel) /-! # G2a ambient-Nat fixture @@ -11,7 +13,7 @@ inductive/constructor kinds, while the Theory model contains the semantic constants those entries denote. The constants are installed through object-language `VDecl.axiom` steps; those are ordinary constructors of the Theory judgment, not new Lean axioms. This is deliberately an ambient model: -it does not claim an eliminator or pretend that Lean4Lean's still-opaque +it does not claim an eliminator or pretend that Ix.Theory.Named's still-opaque `VEnv.addInduct` has been verified. The fixture then promotes one ordinary axiom whose type is `Nat` and leaves a @@ -27,9 +29,9 @@ walker family, and a non-empty `ExecutionRequests` certificate for the exact same request list. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VConstant VConstVal VDecl VEnv VExpr VLevel) +open Ix.Theory.Named (VConstant VConstVal VDecl VEnv VExpr) namespace AmbientNat @@ -51,7 +53,7 @@ def iotaId : KId .anon := ⟨iotaAddress, ()⟩ def natName : Lean.Name := `Nat def zeroName : Lean.Name := `Nat.zero def succName : Lean.Name := `Nat.succ -def goodName : Lean.Name := `Ix.Tc.Verify.ambientNatWitness +def goodName : Lean.Name := `Ix.Kernel.Verify.ambientNatWitness def info (addr : Address) : ExprInfo .anon where addr := addr @@ -678,7 +680,7 @@ theorem bad_not_resolved : rintro ⟨_, _, hresolved⟩ exact bad_not_trusted hresolved.trusted -/-- The existential-world form used by C1--C3 consumers is non-vacuous on the +/-- The existential-world form used by lookup and admission is non-vacuous on the same ambient Nat state. -/ theorem natResolvedInv (prims : Primitives .anon) : ∃ world, worldGood ≤ world ∧ @@ -1189,7 +1191,7 @@ theorem warmCache_cannotResolvePending (prims : Primitives .anon) : /-- G4's formal acceptance witness contains both the fresh and nonempty warm states, transported provenance, and pending-declaration isolation. The -executable failed-then-valid regression lives in `Tests.Ix.Tc.CheckTests`. -/ +executable failed-then-valid regression lives in `Tests.Ix.Kernel.CheckTests`. -/ theorem cacheAcceptance (prims : Primitives .anon) : KernelStateWF whnfSemantics RawProjRel.none worldGood support (state prims) ∧ @@ -1242,7 +1244,7 @@ theorem betaArg_tr : theorem betaA_type : worldGood.venv.HasType 0 [] (.const natName []) (.sort (.succ .zero)) := by - exact Lean4Lean.VEnv.HasType.const (env := worldGood.venv) + exact Ix.Theory.Named.VEnv.HasType.const (env := worldGood.venv) (U := 0) (Γ := []) (ci := natConstant) (ls := []) (by simpa [worldGood, goodEnv, goodName, natName] using natEnv_nat) (by intro l hl; simp at hl) rfl @@ -1250,12 +1252,12 @@ theorem betaA_type : theorem betaBody_type : worldGood.venv.HasType 0 [(.const natName [])] (.bvar 0) (.const natName []) := by - exact Lean4Lean.VEnv.HasType.bvar .zero + exact Ix.Theory.Named.VEnv.HasType.bvar .zero theorem betaArg_type : worldGood.venv.HasType 0 [] (.const zeroName []) (.const natName []) := by - exact Lean4Lean.VEnv.HasType.const (env := worldGood.venv) + exact Ix.Theory.Named.VEnv.HasType.const (env := worldGood.venv) (U := 0) (Γ := []) (ci := zeroConstant) (ls := []) (by simpa [worldGood, goodEnv, goodName, zeroName] using natEnv_zero) (by intro l hl; simp at hl) rfl @@ -3316,12 +3318,12 @@ theorem structuralNatLit_type (n : Nat) : | succ n ih => have hsucc : worldGood.venv.HasType 0 [] (.const succName []) (.forallE (.const natName []) (.const natName [])) := by - exact Lean4Lean.VEnv.HasType.const (env := worldGood.venv) + exact Ix.Theory.Named.VEnv.HasType.const (env := worldGood.venv) (U := 0) (Γ := []) (ci := succConstant) (ls := []) (by simpa [worldGood, goodEnv, goodName, succName] using natEnv_succ) (by intro l hl; simp at hl) rfl - simpa [Lean4Lean.VExpr.inst, VExpr.natLit, VExpr.natSucc, succName] using - Lean4Lean.VEnv.HasType.app hsucc ih + simpa [Ix.Theory.Named.VExpr.inst, VExpr.natLit, VExpr.natSucc, succName] using + Ix.Theory.Named.VEnv.HasType.app hsucc ih /-- The finite Nat world supplies the uniform literal/projection facts needed to compose arbitrary structural trace meanings. -/ @@ -3331,7 +3333,7 @@ def structuralWhnfTheory : WhnfTheory RawProjRel.none worldGood 0 where cases literal with | natVal n => exact ⟨_, structuralNatLit_type n⟩ | strVal value => - simp [Lean4Lean.VEnv.ContainsLits, Lean4Lean.VEnv.contains, + simp [Ix.Theory.Named.VEnv.ContainsLits, Ix.Theory.Named.VEnv.contains, worldGood, goodEnv, natEnv, natEnv₂, natEnv₁, goodName, natName, zeroName, succName] at hliteral projections := RawProjRel.none_ok worldGood.venv 0 @@ -3343,15 +3345,15 @@ theorem structuralBetaSource_tr : betaSource (.app (.lam (.const natName []) (.bvar 0)) (.const zeroName [])) := by rw [betaSource, betaLam, KExpr.mkApp_shape, KExpr.mkLam_shape] - exact .app (Lean4Lean.VEnv.HasType.lam betaA_type betaBody_type) + exact .app (Ix.Theory.Named.VEnv.HasType.lam betaA_type betaBody_type) betaArg_type (.lam ⟨_, betaA_type⟩ betaTy_tr betaBody_tr) betaArg_tr theorem structuralBetaSource_type : worldGood.venv.HasType 0 [] (.app (.lam (.const natName []) (.bvar 0)) (.const zeroName [])) (.const natName []) := by - simpa [Lean4Lean.VExpr.inst] using Lean4Lean.VEnv.HasType.app - (Lean4Lean.VEnv.HasType.lam betaA_type betaBody_type) betaArg_type + simpa [Ix.Theory.Named.VExpr.inst] using Ix.Theory.Named.VEnv.HasType.app + (Ix.Theory.Named.VEnv.HasType.lam betaA_type betaBody_type) betaArg_type theorem structuralBetaSource_constructed : KExpr.Constructed betaSource := by unfold betaSource betaLam betaBody @@ -5053,7 +5055,7 @@ theorem appStuckHead_tr : theorem appStuckHead_type : worldGood.venv.HasType 0 [] (.const succName []) (.forallE (.const natName []) (.const natName [])) := by - exact Lean4Lean.VEnv.HasType.const (env := worldGood.venv) + exact Ix.Theory.Named.VEnv.HasType.const (env := worldGood.venv) (U := 0) (Γ := []) (ci := succConstant) (ls := []) (by simpa [worldGood, goodEnv, goodName, succName] using natEnv_succ) (by intro l hl; simp at hl) rfl @@ -5141,13 +5143,13 @@ its source-translation premise impossible. This identity interpretation is nonempty and closed under every structural translation operation. -/ namespace ProjectionFallback -def projectionName : Lean.Name := `Ix.Tc.Verify.projectionFallback +def projectionName : Lean.Name := `Ix.Kernel.Verify.projectionFallback def projectionRel : RawProjRel := fun _ _ _ _ value result => result = value theorem projectionRel_ok : - TrProjOK Lean4Lean.VEnv.empty 0 projectionRel := by + TrProjOK Ix.Theory.Named.VEnv.empty 0 projectionRel := by refine { weakN := ?_ instN := ?_ @@ -5223,8 +5225,8 @@ def theory : WhnfTheory projectionRel world 0 where literalWF := by intro literal hliteral cases literal <;> - simp [Lean4Lean.VEnv.ContainsLits, Lean4Lean.VEnv.contains, - Lean4Lean.VEnv.empty, world] + simp [Ix.Theory.Named.VEnv.ContainsLits, Ix.Theory.Named.VEnv.contains, + Ix.Theory.Named.VEnv.empty, world] at hliteral projections := projectionRel_ok @@ -5355,10 +5357,10 @@ theorem multiNatTr (Δ : KVLCtx) : (by simpa [worldGood, goodEnv, goodName, natName] using natEnv_nat) (by intro l hl; simp at hl) rfl -theorem multiNatType (Γ : List Lean4Lean.VExpr) : +theorem multiNatType (Γ : List Ix.Theory.Named.VExpr) : worldGood.venv.HasType 0 Γ (.const natName []) (.sort (.succ .zero)) := by - exact Lean4Lean.VEnv.HasType.const (env := worldGood.venv) + exact Ix.Theory.Named.VEnv.HasType.const (env := worldGood.venv) (U := 0) (Γ := Γ) (ci := natConstant) (ls := []) (by simpa [worldGood, goodEnv, goodName, natName] using natEnv_nat) (by intro l hl; simp at hl) rfl @@ -5374,12 +5376,12 @@ theorem multiBetaFunTyTr : (multiNatTr []) (multiNatTr [(none, .vlam (.const natName []))]) -theorem multiBetaFunType (Γ : List Lean4Lean.VExpr) : +theorem multiBetaFunType (Γ : List Ix.Theory.Named.VExpr) : worldGood.venv.HasType 0 Γ (.forallE (.const natName []) (.const natName [])) - (.sort ((Lean4Lean.VLevel.succ .zero).imax - (Lean4Lean.VLevel.succ .zero))) := - Lean4Lean.VEnv.HasType.forallE (multiNatType Γ) + (.sort ((Ix.Theory.VLevel.succ .zero).imax + (Ix.Theory.VLevel.succ .zero))) := + Ix.Theory.Named.VEnv.HasType.forallE (multiNatType Γ) (multiNatType ((.const natName []) :: Γ)) theorem multiBetaBodyTr : @@ -5395,8 +5397,8 @@ theorem multiBetaBodyType : [(.const natName []), (.forallE (.const natName []) (.const natName []))] (.bvar 1) (.forallE (.const natName []) (.const natName [])) := by - exact Lean4Lean.VEnv.HasType.bvar - (Lean4Lean.Lookup.succ (Lean4Lean.Lookup.zero)) + exact Ix.Theory.Named.VEnv.HasType.bvar + (Ix.Theory.Named.Lookup.succ (Ix.Theory.Named.Lookup.zero)) theorem multiBetaInnerTr : TrKExprS worldGood.venv 0 worldGood.nameOf RawProjRel.none @@ -5417,7 +5419,7 @@ theorem multiBetaInnerType : (.lam (.const natName []) (.bvar 1)) (.forallE (.const natName []) (.forallE (.const natName []) (.const natName []))) := by - exact Lean4Lean.VEnv.HasType.lam + exact Ix.Theory.Named.VEnv.HasType.lam (multiNatType [(.forallE (.const natName []) (.const natName []))]) multiBetaBodyType @@ -5438,18 +5440,18 @@ theorem multiBetaLamType : (.forallE (.forallE (.const natName []) (.const natName [])) (.forallE (.const natName []) (.forallE (.const natName []) (.const natName [])))) := by - exact Lean4Lean.VEnv.HasType.lam (multiBetaFunType []) multiBetaInnerType + exact Ix.Theory.Named.VEnv.HasType.lam (multiBetaFunType []) multiBetaInnerType -def multiBetaApp1V : Lean4Lean.VExpr := +def multiBetaApp1V : Ix.Theory.Named.VExpr := .app (.lam (.forallE (.const natName []) (.const natName [])) (.lam (.const natName []) (.bvar 1))) (.const succName []) -def multiBetaApp2V : Lean4Lean.VExpr := +def multiBetaApp2V : Ix.Theory.Named.VExpr := .app multiBetaApp1V (.const zeroName []) -def multiBetaSourceV : Lean4Lean.VExpr := +def multiBetaSourceV : Ix.Theory.Named.VExpr := .app multiBetaApp2V (.const zeroName []) theorem multiBetaApp1Type : @@ -5457,13 +5459,13 @@ theorem multiBetaApp1Type : (.forallE (.const natName []) (.forallE (.const natName []) (.const natName []))) := by unfold multiBetaApp1V - simpa [Lean4Lean.VExpr.inst] using Lean4Lean.VEnv.HasType.app multiBetaLamType appStuckHead_type + simpa [Ix.Theory.Named.VExpr.inst] using Ix.Theory.Named.VEnv.HasType.app multiBetaLamType appStuckHead_type theorem multiBetaApp2Type : worldGood.venv.HasType 0 [] multiBetaApp2V (.forallE (.const natName []) (.const natName [])) := by unfold multiBetaApp2V - simpa [Lean4Lean.VExpr.inst] using Lean4Lean.VEnv.HasType.app multiBetaApp1Type betaArg_type + simpa [Ix.Theory.Named.VExpr.inst] using Ix.Theory.Named.VEnv.HasType.app multiBetaApp1Type betaArg_type theorem multiBetaSourceTr : TrKExprS worldGood.venv 0 worldGood.nameOf RawProjRel.none [] @@ -5482,7 +5484,7 @@ theorem multiBetaSourceType : worldGood.venv.HasType 0 [] multiBetaSourceV (.const natName []) := by unfold multiBetaSourceV - simpa [Lean4Lean.VExpr.inst] using Lean4Lean.VEnv.HasType.app multiBetaApp2Type betaArg_type + simpa [Ix.Theory.Named.VExpr.inst] using Ix.Theory.Named.VEnv.HasType.app multiBetaApp2Type betaArg_type /-- The one dynamically generated trailing application is a real execution request, not an unindexed support assumption. -/ @@ -5715,10 +5717,10 @@ theorem appStuckHead_tr_ctx (Delta : KVLCtx) : (by simpa [worldGood, goodEnv, goodName, succName] using natEnv_succ) (by intro l hl; simp at hl) rfl -theorem appStuckHead_type_ctx (Gamma : List Lean4Lean.VExpr) : +theorem appStuckHead_type_ctx (Gamma : List Ix.Theory.Named.VExpr) : worldGood.venv.HasType 0 Gamma (.const succName []) (.forallE (.const natName []) (.const natName [])) := by - exact Lean4Lean.VEnv.HasType.const (env := worldGood.venv) + exact Ix.Theory.Named.VEnv.HasType.const (env := worldGood.venv) (U := 0) (Γ := Gamma) (ci := succConstant) (ls := []) (by simpa [worldGood, goodEnv, goodName, succName] using natEnv_succ) (by intro l hl; simp at hl) rfl @@ -6117,8 +6119,8 @@ theorem changedHeadMeaning : WhnfMeaning RawProjRel.none worldGood 0 [] changedHeadSource changedHeadRebuilt := by exact ⟨_, _, changedHeadSourceTr, changedHeadRebuiltTr, - Lean4Lean.VEnv.IsDefEqU.refl - ⟨_, Lean4Lean.VEnv.HasType.app appStuckHead_type betaArg_type⟩⟩ + Ix.Theory.Named.VEnv.IsDefEqU.refl + ⟨_, Ix.Theory.Named.VEnv.HasType.app appStuckHead_type betaArg_type⟩⟩ def changedHeadSupport : RunSupport := RunSupport.singleton changedHeadRebuilt @@ -6333,7 +6335,7 @@ theorem linearRecPartsTrace (prims : Primitives .anon) : /-- A concrete two-argument recursor prefix mirroring the descriptor fixture's major position. The argument values are immaterial to pattern matching; the count and constant head are not. -/ -def linearRecTheoryPrefix : Lean4Lean.VExpr := +def linearRecTheoryPrefix : Ix.Theory.Named.VExpr := .app (.app (.const ``Nat.rec []) (.const ``Nat [])) (.const ``Nat []) @@ -6344,26 +6346,26 @@ theorem linearRecTheoryPrefix_shape : simpa using HeadConstN.app (HeadConstN.app (HeadConstN.const (name := ``Nat.rec) [])) -/-- The zero branch constructs Lean4Lean's real dependent capture map. -/ +/-- The zero branch constructs Ix.Theory.Named's real dependent capture map. -/ theorem linearRecZeroPatternMatch : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern ``Nat.rec 2 ``Nat.zero 0).Path → - Lean4Lean.VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.VExpr), + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern ``Nat.rec 2 ``Nat.zero 0) - (.app linearRecTheoryPrefix (Lean4Lean.VExpr.natLit 0)) + (.app linearRecTheoryPrefix (Ix.Theory.Named.VExpr.natLit 0)) levels captures := RecursorIotaPattern.matches_natZero linearRecTheoryPrefix_shape /-- The successor branch constructs a capture map whose constructor argument is the canonical predecessor numeral. -/ theorem linearRecSuccPatternMatch : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern ``Nat.rec 2 ``Nat.succ 1).Path → - Lean4Lean.VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.VExpr), + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern ``Nat.rec 2 ``Nat.succ 1) - (.app linearRecTheoryPrefix (Lean4Lean.VExpr.natLit 3)) + (.app linearRecTheoryPrefix (Ix.Theory.Named.VExpr.natLit 3)) levels captures := by simpa using (RecursorIotaPattern.matches_natSucc (predecessor := 2) linearRecTheoryPrefix_shape) @@ -6395,7 +6397,7 @@ theorem missingRuleDescriptor_noZeroRule : argument retains the final argument in a nonempty typed suffix. -/ theorem multiBetaMiddleSplit : ∃ (priorArgs laterArgs : List (KExpr .anon)) - (priorV majorV : Lean4Lean.VExpr), + (priorV majorV : Ix.Theory.Named.VExpr), [appStuckHead, betaArg, betaArg] = priorArgs ++ betaArg :: laterArgs ∧ 1 = priorArgs.length ∧ @@ -6432,7 +6434,7 @@ Replacing the through-middle prefix by its own translation reconstructs the final application rather than silently returning the prefix. -/ theorem multiBetaMiddleRebase : ∃ (priorArgs laterArgs : List (KExpr .anon)) - (resultV : Lean4Lean.VExpr), + (resultV : Ix.Theory.Named.VExpr), laterArgs ≠ [] ∧ TrKExprS worldGood.venv 0 worldGood.nameOf RawProjRel.none [] (laterArgs.foldl KExpr.mkApp @@ -6468,4 +6470,4 @@ theorem acceptance (prims : Primitives .anon) : end AmbientNat -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Projection/Concrete.lean b/Ix/Kernel/Verify/Projection/Concrete.lean similarity index 75% rename from Ix/Tc/Verify/Projection/Concrete.lean rename to Ix/Kernel/Verify/Projection/Concrete.lean index 1d6279946..0f7d2eaaf 100644 --- a/Ix/Tc/Verify/Projection/Concrete.lean +++ b/Ix/Kernel/Verify/Projection/Concrete.lean @@ -1,17 +1,19 @@ -import Ix.Tc.Verify.Decl -import Ix.Tc.Verify.Trans -import Lean4Lean.Verify.Typing.Lemmas +import Ix.Kernel.Verify.Decl +import Ix.Kernel.Verify.Trans +import Ix.Theory.Named.Verify.Typing.Lemmas + +open Ix.Theory (VLevel) /-! -# Concrete Lean4Lean projection adapter +# Concrete Ix.Theory.Named projection adapter Ix keeps projection translation abstract so the checker proofs do not depend on one implementation of structure projections. This module closes that -boundary with Lean4Lean's registered, recursor-encoded `TrProj` relation. +boundary with Ix.Theory.Named's registered, recursor-encoded `TrProj` relation. The field mapping is direct: -* `weakN` uses Lean4Lean's general-depth weakening theorem; +* `weakN` uses Ix.Theory.Named's general-depth weakening theorem; * `instN`, `wf`, `uniq`, and `defeqDFC` consume the corresponding fields of `TrProj.structuralLaws`; * `instL` uses the named universe-instantiation theorem, whose statement is @@ -19,24 +21,24 @@ The field mapping is direct: * `monoU` instantiates with the identity parameter spine and discharges the resulting identities from the source context and projection typing data. -Consequently the adapter inherits Lean4Lean's named +Consequently the adapter inherits Ix.Theory.Named's named `VEnv.WF.registeredStructureHeadInversion` debt through projection uniqueness and the existing `VEnv.IsDefEqU.forallE_inv_stratified` / `VEnv.IsDefEqU.sort_inv` debts through context-defeq/unique typing; it introduces no Ix axiom or pending assumption. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (OnCtx VEnv VExpr VLevel) +open Ix.Theory.Named (OnCtx VEnv VExpr) namespace RawProjRel -/-- Lean4Lean's concrete, environment-indexed projection semantics in Ix's +/-- Ix.Theory.Named's concrete, environment-indexed projection semantics in Ix's universe-indexed projection slot. -/ -abbrev lean4Lean (env : VEnv) := +abbrev named (env : VEnv) := fun uvars ctx structName field major result => - Lean4Lean.TrProj env uvars ctx structName field major result + Ix.Theory.Named.TrProj env uvars ctx structName field major result private theorem vlevelWF_mono {before after : Nat} (hle : before ≤ after) : @@ -69,15 +71,15 @@ private theorem context_instParams_eq {uvars : Nat} : simp only [List.map_cons, context_instParams_eq hctx, htype.instL_id] /-- A concrete projection remains the same projection when only the available -universe-parameter budget grows. Lean4Lean supplies universe instantiation; +universe-parameter budget grows. Ix.Theory.Named supplies universe instantiation; its typing data proves that instantiating with the original parameter spine is the identity on the context, major, and computed result. -/ -private theorem lean4Lean_monoU +private theorem named_monoU {env : VEnv} {before after : Nat} {ctx : List VExpr} {structName : Lean.Name} {field : Nat} {major result : VExpr} (hle : before ≤ after) (hctx : OnCtx ctx (env.IsType before)) - (hproj : Lean4Lean.TrProj env before ctx structName field major result) : - Lean4Lean.TrProj env after ctx structName field major result := by + (hproj : Ix.Theory.Named.TrProj env before ctx structName field major result) : + Ix.Theory.Named.TrProj env after ctx structName field major result := by have hctxLevels := context_levelWF hctx have hlevels : ∀ level ∈ VLevel.params before, level.WF after := by intro level hlevel @@ -86,7 +88,7 @@ private theorem lean4Lean_monoU have hmajorWF : VExpr.WF env before ctx major := ⟨_, htheory.majorType⟩ have hresultWF : VExpr.WF env before ctx result := - (show Lean4Lean.TrProj env before ctx structName field major result from + (show Ix.Theory.Named.TrProj env before ctx structName field major result from ⟨view, levels, params, hname, htheory⟩).wf hmajorWF have hmajorLevels : major.LevelWF before := (htheory.majorType.levelWF hctxLevels).1 @@ -94,19 +96,19 @@ private theorem lean4Lean_monoU have hresultLevels : result.LevelWF before := (hresultType.levelWF hctxLevels).1 have hinst := - (show Lean4Lean.TrProj env before ctx structName field major result from + (show Ix.Theory.Named.TrProj env before ctx structName field major result from ⟨view, levels, params, hname, htheory⟩).instL hlevels rw [context_instParams_eq hctxLevels, hmajorLevels.instL_id, hresultLevels.instL_id] at hinst exact hinst -/-- Lean4Lean's concrete projection relation satisfies every Ix projection +/-- Ix.Theory.Named's concrete projection relation satisfies every Ix projection capability. The `uvars` index selects the laws used by ordinary checker proofs; universe instantiation and monotonicity remain polymorphic because declaration translation crosses universe counts. -/ -theorem lean4Lean_ok (henv : VEnv.WF env) (uvars : Nat) : - TrProjOK env uvars (lean4Lean env) := by - let laws := Lean4Lean.TrProj.structuralLaws henv +theorem named_ok (henv : VEnv.WF env) (uvars : Nat) : + TrProjOK env uvars (named env) := by + let laws := Ix.Theory.Named.TrProj.structuralLaws henv refine { weakN := ?_ instN := ?_ @@ -116,7 +118,7 @@ theorem lean4Lean_ok (henv : VEnv.WF env) (uvars : Nat) : instL := ?_ monoU := ?_ } · intro Γ Γ' n k s i e e' hlift hproj - exact Lean4Lean.TrProj.weakN henv.ordered hlift hproj + exact Ix.Theory.Named.TrProj.weakN henv.ordered hlift hproj · intro Γ₀ e₀ A₀ k Γ₁ Γ s i e e' htype hinst hproj exact laws.termSubstitution htype hinst hproj · intro Γ s i e e' hproj hwf @@ -128,7 +130,7 @@ theorem lean4Lean_ok (henv : VEnv.WF env) (uvars : Nat) : · intro U U' levels Γ s i e e' hlevels hproj exact hproj.instL hlevels · intro U U' Γ s i e e' hle hctx hproj - exact lean4Lean_monoU hle hctx hproj + exact named_monoU hle hctx hproj end RawProjRel -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Projection/ConcreteFixture.lean b/Ix/Kernel/Verify/Projection/ConcreteFixture.lean similarity index 80% rename from Ix/Tc/Verify/Projection/ConcreteFixture.lean rename to Ix/Kernel/Verify/Projection/ConcreteFixture.lean index 1772b64cf..1ee609625 100644 --- a/Ix/Tc/Verify/Projection/ConcreteFixture.lean +++ b/Ix/Kernel/Verify/Projection/ConcreteFixture.lean @@ -1,10 +1,10 @@ -import Ix.Tc.Verify.Projection.Concrete -import Lean4Lean.Tests.ProjectionExpressibility +import Ix.Kernel.Verify.Projection.Concrete +import Ix.Theory.Named.Fixtures.ProjectionExpressibility /-! # Production-syntax fixture for the concrete projection relation -This fixture connects an actual Ix `KExpr.mkPrj` node to Lean4Lean's +This fixture connects an actual Ix `KExpr.mkPrj` node to Ix.Theory.Named's universe-polymorphic, dependent `DependentRecord` projection fixture. The major is the leading local variable in the exact Theory context retained by the registered structure view; the result is the recursor-encoded key @@ -16,10 +16,10 @@ environment-indexed `TrProj` witness, and the acceptance theorem packages the real adapter laws with that production syntax node. -/ -namespace Ix.Tc.ConcreteProjectionFixture +namespace Ix.Kernel.ConcreteProjectionFixture -open Lean4Lean (VExpr VLocalDecl) -open Lean4Lean.Tests.ProjectionExpressibility +open Ix.Theory.Named (VExpr VLocalDecl) +open Ix.Theory.Named.Tests.ProjectionExpressibility def structureAddress : Address := ⟨⟨Array.replicate 32 64⟩⟩ @@ -34,11 +34,11 @@ theorem nameOf_structure : simp [nameOf] abbrev projectionRel := - Ix.Tc.RawProjRel.lean4Lean dependentRecordEnv + Ix.Kernel.RawProjRel.named dependentRecordEnv theorem projectionLaws : TrProjOK dependentRecordEnv 2 projectionRel := - Ix.Tc.RawProjRel.lean4Lean_ok dependentRecordEnv_wf 2 + Ix.Kernel.RawProjRel.named_ok dependentRecordEnv_wf 2 /-- The Verify compatibility witness exposing the registered key projection through the concrete relation used by Ix. -/ @@ -48,7 +48,7 @@ theorem keyProjection : exact ⟨dependentRecordView, symbolicLevels, symbolicMajorParams, rfl, key_representable⟩ -/-- The mixed Ix context corresponding definitionally to Lean4Lean's +/-- The mixed Ix context corresponding definitionally to Ix.Theory.Named's `[major, family, α]` Theory context. -/ def context : KVLCtx := [(none, .vlam symbolicMajorBinderType), @@ -72,14 +72,14 @@ theorem sourceConstructed : source.Constructed := by exact .prj (.var (by decide)) theorem majorRaw : - _root_.Ix.Tc.RawExprRel (uvars := 2) dependentRecordEnv nameOf projectionRel + _root_.Ix.Kernel.RawExprRel (uvars := 2) dependentRecordEnv nameOf projectionRel symbolicContext major symbolicMajor := by unfold major rw [KExpr.mkVar_shape] exact .var theorem sourceRaw : - _root_.Ix.Tc.RawExprRel (uvars := 2) dependentRecordEnv nameOf projectionRel + _root_.Ix.Kernel.RawExprRel (uvars := 2) dependentRecordEnv nameOf projectionRel symbolicContext source symbolicKeyResult := by unfold source rw [KExpr.mkPrj_shape] @@ -101,11 +101,11 @@ theorem sourceStructural : exact .prj nameOf_structure majorStructural keyProjection /-- The same concrete projection survives an increased universe budget via -the Ix capability derived from Lean4Lean universe instantiation. -/ +the Ix capability derived from Ix.Theory.Named universe instantiation. -/ theorem keyProjectionAtThree : projectionRel 3 symbolicContext ``DependentRecord 0 symbolicMajor symbolicKeyResult := - (Ix.Tc.RawProjRel.lean4Lean_ok dependentRecordEnv_wf 3).monoU + (Ix.Kernel.RawProjRel.named_ok dependentRecordEnv_wf 3).monoU (by omega) contextWF.toCtx keyProjection /-- P0's concrete vertical slice: a smart-constructor-built Ix projection is @@ -114,7 +114,7 @@ boundary, using the real registered projection relation and its complete Ix law bundle. -/ theorem acceptance : source.Constructed ∧ - _root_.Ix.Tc.RawExprRel (uvars := 2) dependentRecordEnv nameOf projectionRel + _root_.Ix.Kernel.RawExprRel (uvars := 2) dependentRecordEnv nameOf projectionRel symbolicContext source symbolicKeyResult ∧ TrKExprS dependentRecordEnv 2 nameOf projectionRel context source symbolicKeyResult ∧ @@ -124,4 +124,4 @@ theorem acceptance : ⟨sourceConstructed, sourceRaw, sourceStructural, projectionLaws, keyProjectionAtThree⟩ -end Ix.Tc.ConcreteProjectionFixture +end Ix.Kernel.ConcreteProjectionFixture diff --git a/Ix/Tc/Verify/RecursiveMethods/CallDomains.lean b/Ix/Kernel/Verify/RecursiveMethods/CallDomains.lean similarity index 98% rename from Ix/Tc/Verify/RecursiveMethods/CallDomains.lean rename to Ix/Kernel/Verify/RecursiveMethods/CallDomains.lean index d9bd2afa1..82fb4b1b9 100644 --- a/Ix/Tc/Verify/RecursiveMethods/CallDomains.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/CallDomains.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Knot +import Ix.Kernel.Verify.Knot /-! # Fuel-indexed recursive-method call domains @@ -21,7 +21,7 @@ is the entire run support; `FiniteSupportBoundary` proves why that special case cannot be the final public interface for sort-producing runs. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace Methods @@ -255,14 +255,14 @@ theorem methodsN calls depth) : ∀ n, n ≤ depth → Methods.WFAtOn layer semantics trProj world scope uvars (calls n) - (Ix.Tc.methodsN (m := .anon) n) + (Ix.Kernel.methodsN (m := .anon) n) | 0, _ => methodsOut_wfAtOn layer semantics trProj world scope uvars (calls 0) (schedule.within 0 (Nat.zero_le depth)) | n + 1, hn => by rw [Methods.methodsN_succ] exact schedule.step n (Nat.lt_of_succ_le hn) - (Ix.Tc.methodsN (m := .anon) n) + (Ix.Kernel.methodsN (m := .anon) n) (schedule.methodsN n (Nat.le_trans (Nat.le_succ n) hn)) /-- The contract selected at the schedule's terminal depth. -/ @@ -273,7 +273,7 @@ theorem selected (schedule : CallScheduleAt layer semantics trProj world scope uvars calls depth) : Methods.WFAtOn layer semantics trProj world scope uvars (calls depth) - (Ix.Tc.methodsN (m := .anon) depth) := + (Ix.Kernel.methodsN (m := .anon) depth) := schedule.methodsN depth (Nat.le_refl depth) /-- The method body executed by `TcM.runRec` sits one layer above its @@ -288,9 +288,9 @@ theorem nextSelected calls (depth + 1)) : Methods.WFAtOn layer semantics trProj world scope uvars (calls (depth + 1)) - (Methods.next (Ix.Tc.methodsN (m := .anon) depth)) := + (Methods.next (Ix.Kernel.methodsN (m := .anon) depth)) := schedule.step depth (Nat.lt_succ_self depth) - (Ix.Tc.methodsN (m := .anon) depth) + (Ix.Kernel.methodsN (m := .anon) depth) (schedule.methodsN depth (Nat.le_succ depth)) end CallScheduleAt @@ -479,8 +479,8 @@ theorem runRec_wfAtOn TcM.WF (WhnfStateInv layer semantics trProj world scope uvars Delta) s (TcM.runRec action) Q E := by exact - haction (Ix.Tc.methodsN (m := .anon) s.recFuel.toNat) schedule.selected + haction (Ix.Kernel.methodsN (m := .anon) s.recFuel.toNat) schedule.selected end TcM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/Closure.lean b/Ix/Kernel/Verify/RecursiveMethods/Closure.lean similarity index 96% rename from Ix/Tc/Verify/RecursiveMethods/Closure.lean rename to Ix/Kernel/Verify/RecursiveMethods/Closure.lean index 784cab9b3..495ea8a56 100644 --- a/Ix/Tc/Verify/RecursiveMethods/Closure.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/Closure.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.InferDefEq.Closure -import Ix.Tc.Verify.Whnf.Closure +import Ix.Kernel.Verify.InferDefEq.Closure +import Ix.Kernel.Verify.Whnf.Closure /-! # Complete recursive method-table closure @@ -10,7 +10,7 @@ cache stack and one predecessor table before `methodsN` can be justified. This module performs that final fixed-universe assembly. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The semantic cache layers beneath K1's outer WHNF and delta layers. -/ def kernelCacheFallback (keys : WhnfContextKeys) (trProj : RawProjRel) : @@ -75,4 +75,4 @@ theorem methodsN end RecursiveMethodClosureContext -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/FiniteSupportBoundary.lean b/Ix/Kernel/Verify/RecursiveMethods/FiniteSupportBoundary.lean similarity index 98% rename from Ix/Tc/Verify/RecursiveMethods/FiniteSupportBoundary.lean rename to Ix/Kernel/Verify/RecursiveMethods/FiniteSupportBoundary.lean index 19bc4d6b9..3d090864c 100644 --- a/Ix/Tc/Verify/RecursiveMethods/FiniteSupportBoundary.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/FiniteSupportBoundary.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Infer.Dispatcher +import Ix.Kernel.Verify.Infer.Dispatcher /-! # Finite-support boundary for recursive inference @@ -15,7 +15,7 @@ interface failure explicit so a recursive-method closure cannot accidentally hide it behind an uninhabitable premise. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace FiniteSupportBoundary @@ -95,4 +95,4 @@ theorem SyntaxInferenceResources.no_sort_source end FiniteSupportBoundary -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/Inference.lean b/Ix/Kernel/Verify/RecursiveMethods/Inference.lean similarity index 96% rename from Ix/Tc/Verify/RecursiveMethods/Inference.lean rename to Ix/Kernel/Verify/RecursiveMethods/Inference.lean index accfac3e7..523189c36 100644 --- a/Ix/Tc/Verify/RecursiveMethods/Inference.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/Inference.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Infer.CacheSoundness -import Ix.Tc.Verify.RecursiveMethods.CallDomains +import Ix.Kernel.Verify.Infer.CacheSoundness +import Ix.Kernel.Verify.RecursiveMethods.CallDomains /-! # Call-domain inference layer @@ -16,7 +16,7 @@ contains the all-support `SyntaxInferenceResources` field whose sort clause is provably uninhabitable for any finite support containing a sort. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Per-layer resources for production inference. `current` guards only the outer calls proved at this layer; `predecessor` governs recursive back-edges @@ -30,7 +30,7 @@ structure InferenceCallDomainContext theory : WhnfTheory trProj world model.keys.uvars references : RecM.TrustedReferences world scope uncached : ∀ {Delta : KVLCtx} {s : TcState .anon} {inferOnly : Bool} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr}, + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr}, current.infer source → TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV → @@ -98,7 +98,7 @@ private theorem missTail_wfOn {current predecessor : Methods.CallDomain} (context : InferenceCallDomainContext scope model current predecessor) {Delta : KVLCtx} {before s : TcState .anon} {inferOnly : Bool} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {key : Address × Address} (hmatch : model.keys.Matches trProj world before Delta source key) (hcall : current.infer source) @@ -152,7 +152,7 @@ theorem inferWith_wfOn {current predecessor : Methods.CallDomain} (context : InferenceCallDomainContext scope model current predecessor) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hcall : current.infer source) (hsource : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) : @@ -244,7 +244,7 @@ theorem nextInfer_wfAtOn (kernelCacheSemantics model.keys trProj) trProj world scope model.keys.uvars predecessor predecessorMethods) : ∀ {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr}, + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr}, current.infer source → TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV → @@ -260,4 +260,4 @@ theorem nextInfer_wfAtOn end InferenceCallDomainContext -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/Public.lean b/Ix/Kernel/Verify/RecursiveMethods/Public.lean similarity index 94% rename from Ix/Tc/Verify/RecursiveMethods/Public.lean rename to Ix/Kernel/Verify/RecursiveMethods/Public.lean index bd927fd9c..40ca11952 100644 --- a/Ix/Tc/Verify/RecursiveMethods/Public.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/Public.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.RecursiveMethods.CallDomains -import Ix.Tc.Verify.RecursiveMethods.Closure -import Ix.Tc.Verify.RecursiveMethods.ScopedCallDomains +import Ix.Kernel.Verify.RecursiveMethods.CallDomains +import Ix.Kernel.Verify.RecursiveMethods.Closure +import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Public recursive-method soundness over run-scoped bounded call domains @@ -18,7 +18,7 @@ finite run to infer a sort and return its successor sort without demanding an infinite successor-sort closure. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Legacy globally quantified evidence for one public recursive-method run. New public roots consume `ScopedRecursiveMethodRunContext` below. This type @@ -93,7 +93,7 @@ theorem wf_legacy {world : VerifyWorld} {support : RunSupport} (context : RecursiveMethodRunContext initial (TcM.whnf e) requests trProj world support) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hcall : (context.calls (initial.recFuel.toNat + 1)).whnf e) (hsource : TrKExprS world.venv context.proposition.model.keys.uvars world.nameOf trProj Delta e @@ -112,7 +112,7 @@ theorem wf {world : VerifyWorld} {support : RunSupport} (context : ScopedRecursiveMethodRunContext initial (TcM.whnf e) requests trProj world support) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hcall : (context.calls (initial.recFuel.toNat + 1)).whnf e) (hsource : TrKExprS world.venv context.model.keys.uvars world.nameOf trProj Delta e sourceV) : @@ -135,7 +135,7 @@ theorem wf_legacy {world : VerifyWorld} {support : RunSupport} (context : RecursiveMethodRunContext initial (TcM.infer e) requests trProj world support) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hcall : (context.calls (initial.recFuel.toNat + 1)).infer e) (hsource : TrKExprS world.venv context.proposition.model.keys.uvars world.nameOf trProj Delta e @@ -154,7 +154,7 @@ theorem wf {world : VerifyWorld} {support : RunSupport} (context : ScopedRecursiveMethodRunContext initial (TcM.infer e) requests trProj world support) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hcall : (context.calls (initial.recFuel.toNat + 1)).infer e) (hsource : TrKExprS world.venv context.model.keys.uvars world.nameOf trProj Delta e sourceV) : @@ -177,7 +177,7 @@ theorem wf_legacy {world : VerifyWorld} {support : RunSupport} (context : RecursiveMethodRunContext initial (TcM.isDefEq a b) requests trProj world support) - {Delta : KVLCtx} {va vb : Lean4Lean.VExpr} + {Delta : KVLCtx} {va vb : Ix.Theory.Named.VExpr} (hcall : (context.calls (initial.recFuel.toNat + 1)).isDefEq a b) (ha : TrKExprS world.venv context.proposition.model.keys.uvars world.nameOf trProj Delta a va) @@ -198,7 +198,7 @@ theorem wf {world : VerifyWorld} {support : RunSupport} (context : ScopedRecursiveMethodRunContext initial (TcM.isDefEq a b) requests trProj world support) - {Delta : KVLCtx} {va vb : Lean4Lean.VExpr} + {Delta : KVLCtx} {va vb : Ix.Theory.Named.VExpr} (hcall : (context.calls (initial.recFuel.toNat + 1)).isDefEq a b) (ha : TrKExprS world.venv context.model.keys.uvars world.nameOf trProj Delta a va) @@ -212,4 +212,4 @@ theorem wf end TcM.isDefEq -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/ScopedCallDomains.lean b/Ix/Kernel/Verify/RecursiveMethods/ScopedCallDomains.lean similarity index 96% rename from Ix/Tc/Verify/RecursiveMethods/ScopedCallDomains.lean rename to Ix/Kernel/Verify/RecursiveMethods/ScopedCallDomains.lean index a10318c27..1de663397 100644 --- a/Ix/Tc/Verify/RecursiveMethods/ScopedCallDomains.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/ScopedCallDomains.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.DefEq -import Ix.Tc.Verify.RecursiveMethods.CallDomains +import Ix.Kernel.Verify.DefEq +import Ix.Kernel.Verify.RecursiveMethods.CallDomains /-! # Run-scoped recursive-method call domains @@ -15,7 +15,7 @@ all-depth/global-model interfaces remain compatibility artifacts and are not used to justify the scoped schedule below. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace Methods @@ -129,14 +129,14 @@ theorem methodsN (schedule : ScopedCallScheduleAt model layer semantics scope calls depth) : ∀ n, n ≤ depth → ScopedWFAtOn model layer semantics scope (calls n) - (Ix.Tc.methodsN (m := .anon) n) + (Ix.Kernel.methodsN (m := .anon) n) | 0, _ => methodsOut_scopedWFAtOn model layer semantics scope (calls 0) (schedule.within 0 (Nat.zero_le depth)) | n + 1, hn => by rw [Methods.methodsN_succ] exact schedule.step n (Nat.lt_of_succ_le hn) - (Ix.Tc.methodsN (m := .anon) n) + (Ix.Kernel.methodsN (m := .anon) n) (schedule.methodsN n (Nat.le_trans (Nat.le_succ n) hn)) theorem selected @@ -146,7 +146,7 @@ theorem selected {scope : RunSupport} {calls : Nat → CallDomain} {depth : Nat} (schedule : ScopedCallScheduleAt model layer semantics scope calls depth) : ScopedWFAtOn model layer semantics scope (calls depth) - (Ix.Tc.methodsN (m := .anon) depth) := + (Ix.Kernel.methodsN (m := .anon) depth) := schedule.methodsN depth (Nat.le_refl depth) theorem nextSelected @@ -157,9 +157,9 @@ theorem nextSelected (schedule : ScopedCallScheduleAt model layer semantics scope calls (depth + 1)) : ScopedWFAtOn model layer semantics scope (calls (depth + 1)) - (Methods.next (Ix.Tc.methodsN (m := .anon) depth)) := + (Methods.next (Ix.Kernel.methodsN (m := .anon) depth)) := schedule.step depth (Nat.lt_succ_self depth) - (Ix.Tc.methodsN (m := .anon) depth) + (Ix.Kernel.methodsN (m := .anon) depth) (schedule.methodsN depth (Nat.le_succ depth)) end ScopedCallScheduleAt @@ -310,8 +310,8 @@ theorem runRec_scoped_wfAtOn TcM.WF (ScopedWhnfStateInv model layer semantics scope Delta) s (TcM.runRec action) Q E := by exact - haction (Ix.Tc.methodsN (m := .anon) s.recFuel.toNat) schedule.selected + haction (Ix.Kernel.methodsN (m := .anon) s.recFuel.toNat) schedule.selected end TcM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/ScopedInference.lean b/Ix/Kernel/Verify/RecursiveMethods/ScopedInference.lean similarity index 98% rename from Ix/Tc/Verify/RecursiveMethods/ScopedInference.lean rename to Ix/Kernel/Verify/RecursiveMethods/ScopedInference.lean index 74e3a81c8..520ceb5e4 100644 --- a/Ix/Tc/Verify/RecursiveMethods/ScopedInference.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/ScopedInference.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Infer.CacheSoundness -import Ix.Tc.Verify.RecursiveMethods.ScopedCallDomains +import Ix.Kernel.Verify.Infer.CacheSoundness +import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Run-scoped call-domain inference @@ -13,7 +13,7 @@ No theorem in this module converts a `ScopedKernelSuffixModel` to the legacy globally quantified `KernelSuffixModel`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace InternTable @@ -310,7 +310,7 @@ structure ScopedInferenceCallDomainContext theory : WhnfTheory trProj world model.keys.uvars references : RecM.TrustedReferences world scope uncached : ∀ {Delta : KVLCtx} {s : TcState .anon} {inferOnly : Bool} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr}, + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr}, current.infer source → TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV → @@ -383,7 +383,7 @@ private theorem missTail_scopedWFOn (context : ScopedInferenceCallDomainContext scope model current predecessor) {Delta : KVLCtx} {before s : TcState .anon} {inferOnly : Bool} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {key : Address × Address} (hmatch : model.keys.Matches trProj world before Delta source key) (hcall : current.infer source) @@ -438,7 +438,7 @@ theorem inferWith_scopedWFOn (context : ScopedInferenceCallDomainContext scope model current predecessor) {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hcall : current.infer source) (hsource : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV) : @@ -532,7 +532,7 @@ theorem nextInfer_scopedWFAtOn (kernelCacheSemantics model.keys trProj) scope predecessor predecessorMethods) : ∀ {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr}, + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr}, current.infer source → TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta source sourceV → @@ -549,4 +549,4 @@ theorem nextInfer_scopedWFAtOn end ScopedInferenceCallDomainContext -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/ScopedSortInference.lean b/Ix/Kernel/Verify/RecursiveMethods/ScopedSortInference.lean similarity index 96% rename from Ix/Tc/Verify/RecursiveMethods/ScopedSortInference.lean rename to Ix/Kernel/Verify/RecursiveMethods/ScopedSortInference.lean index 3111a9e0e..f099c235f 100644 --- a/Ix/Tc/Verify/RecursiveMethods/ScopedSortInference.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/ScopedSortInference.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Infer.LeafCases -import Ix.Tc.Verify.RecursiveMethods.ScopedInference +import Ix.Kernel.Verify.Infer.LeafCases +import Ix.Kernel.Verify.RecursiveMethods.ScopedInference + +open Ix.Theory (VLevel) /-! # Positive-fuel inference under a run-scoped suffix model @@ -11,7 +13,7 @@ recursive callback. Key memoization, interning, and cache insertion all preserve `StateInScope` explicitly. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace ScopedInferenceCallDomainContext @@ -52,7 +54,7 @@ def sort world.venvWF.ordered theory.literalWF theory.projections.wf hI.1.2.1.wf · simpa only [KUniv.toVLevel_mkSucc] using - (Lean4Lean.VEnv.HasType.sort hu) + (Ix.Theory.Named.VEnv.HasType.sort hu) · intro _ _ _ trivial @@ -161,7 +163,7 @@ theorem sort_scoped_wf_bounded (hresultSupport : scope (KExpr.mkSort (KUniv.mkSucc u))) (theory : WhnfTheory trProj world model.keys.uvars) (references : RecM.TrustedReferences world scope) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta (.sort u info) sourceV) : TcM.WF @@ -188,7 +190,7 @@ theorem sort_scoped_wf_fuel_one (hresultSupport : scope (KExpr.mkSort (KUniv.mkSucc u))) (theory : WhnfTheory trProj world model.keys.uvars) (references : RecM.TrustedReferences world scope) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv model.keys.uvars world.nameOf trProj Delta (.sort u info) sourceV) : TcM.WF @@ -217,7 +219,7 @@ theorem sort_finiteOperational_wf_fuel_one (hresultSupport : scope (KExpr.mkSort (KUniv.mkSucc u))) (theory : WhnfTheory trProj world uvars) (references : RecM.TrustedReferences world scope) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta (.sort u info) sourceV) : let model := ScopedKernelSuffixModel.finiteOperational spec digestScope @@ -234,4 +236,4 @@ theorem sort_finiteOperational_wf_fuel_one end TcM.infer -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/RecursiveMethods/SortInference.lean b/Ix/Kernel/Verify/RecursiveMethods/SortInference.lean similarity index 96% rename from Ix/Tc/Verify/RecursiveMethods/SortInference.lean rename to Ix/Kernel/Verify/RecursiveMethods/SortInference.lean index 0cac65417..64aa22580 100644 --- a/Ix/Tc/Verify/RecursiveMethods/SortInference.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/SortInference.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Infer.LeafCases -import Ix.Tc.Verify.RecursiveMethods.Inference -import Ix.Tc.Verify.RecursiveMethods.Public +import Ix.Kernel.Verify.Infer.LeafCases +import Ix.Kernel.Verify.RecursiveMethods.Inference +import Ix.Kernel.Verify.RecursiveMethods.Public /-! # A positive-fuel inference schedule @@ -15,7 +15,7 @@ membership of the result does not make it another inference call, so this contract does not demand closure under an infinite tower of successor sorts. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace InferenceCallDomainContext @@ -120,7 +120,7 @@ theorem selected Methods.WFAtOn .noAccel (kernelCacheSemantics model.keys trProj) trProj world scope model.keys.uvars (.singletonInfer (.sort u info)) - (Ix.Tc.methodsN (m := .anon) 1) := by + (Ix.Kernel.methodsN (m := .anon) 1) := by simpa [calls] using (one context).selected /-- The same finite source/result footprint supports every finite table depth: @@ -184,7 +184,7 @@ theorem sort_wf_bounded (hresultSupport : scope (KExpr.mkSort (KUniv.mkSucc u))) (theory : WhnfTheory trProj world proposition.model.keys.uvars) (references : RecM.TrustedReferences world scope) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv proposition.model.keys.uvars world.nameOf trProj Delta (.sort u info) sourceV) : TcM.WF @@ -221,7 +221,7 @@ theorem sort_wf_fuel_one (hresultSupport : scope (KExpr.mkSort (KUniv.mkSucc u))) (theory : WhnfTheory trProj world proposition.model.keys.uvars) (references : RecM.TrustedReferences world scope) - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv proposition.model.keys.uvars world.nameOf trProj Delta (.sort u info) sourceV) : TcM.WF @@ -247,4 +247,4 @@ theorem sort_wf_fuel_one end TcM.infer -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Run.lean b/Ix/Kernel/Verify/Run.lean similarity index 97% rename from Ix/Tc/Verify/Run.lean rename to Ix/Kernel/Verify/Run.lean index 08f5bc69c..0c53a2472 100644 --- a/Ix/Tc/Verify/Run.lean +++ b/Ix/Kernel/Verify/Run.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.State -import Ix.Tc.Verify.Execution -import Ix.Tc.Verify.Frame +import Ix.Kernel.Verify.State +import Ix.Kernel.Verify.Execution +import Ix.Kernel.Verify.Frame /-! # G3b: execution-indexed run assumptions @@ -19,7 +19,7 @@ translation relations. The adapter lemmas here project that bundle into the existing walker masters and retain both finite intern ranges in post-states. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- State invariant used by run-level adapters and top-level statements. G4 adds stable-world provenance for every warm cache entry. -/ @@ -122,7 +122,7 @@ theorem lift_spec {α : Type} {initial : TcState .anon} (lift e shift cutoff it).2.WF ∧ support.CoversIntern (lift e shift cutoff it).2 := by obtain ⟨hcon, hcut, _⟩ := h.requestBounds hmem - have post := Ix.Tc.lift_spec h.collisionFree.expr hcon hcut + have post := Ix.Kernel.lift_spec h.collisionFree.expr hcon hcut (h.coverage.lift hmem) hwf hsup.expr exact ⟨post.1, post.2.1, hsup.of_expr_univs post.2.2 (lift_preservesUnivs e shift cutoff it)⟩ @@ -139,7 +139,7 @@ theorem subst_spec {α : Type} {initial : TcState .anon} (subst body arg depth it).2.WF ∧ support.CoversIntern (subst body arg depth it).2 := by obtain ⟨hbody, harg, hcut, hargsz, _⟩ := h.requestBounds hmem - have post := Ix.Tc.subst_spec h.collisionFree.expr hbody harg hcut hargsz + have post := Ix.Kernel.subst_spec h.collisionFree.expr hbody harg hcut hargsz (h.coverage.subst hmem) hwf hsup.expr exact ⟨post.1, post.2.1, hsup.of_expr_univs post.2.2 (subst_preservesUnivs body arg depth it)⟩ @@ -157,7 +157,7 @@ theorem simulSubst_spec {α : Type} {initial : TcState .anon} (simulSubst body substs depth it).2.WF ∧ support.CoversIntern (simulSubst body substs depth it).2 := by obtain ⟨hbody, hsubsts, hsizes, hwalk, _⟩ := h.requestBounds hmem - have post := Ix.Tc.simulSubst_spec h.collisionFree.expr hbody hsubsts + have post := Ix.Kernel.simulSubst_spec h.collisionFree.expr hbody hsubsts hsizes hwalk (h.coverage.simulSubst hmem) hwf hsup.expr exact ⟨post.1, post.2.1, hsup.of_expr_univs post.2.2 @@ -176,7 +176,7 @@ theorem instRev_spec {α : Type} {initial : TcState .anon} (instantiateRev body fvars it).2.WF ∧ support.CoversIntern (instantiateRev body fvars it).2 := by obtain ⟨hbody, _, hwalk⟩ := h.requestBounds hmem - have post := Ix.Tc.instantiateRev_spec h.collisionFree.expr hbody hwalk + have post := Ix.Kernel.instantiateRev_spec h.collisionFree.expr hbody hwalk (h.coverage.instRev hmem) hwf hsup.expr exact ⟨post.1, post.2.1, hsup.of_expr_univs post.2.2 @@ -213,7 +213,7 @@ theorem abstractFVars_support_spec rfl rw [hrun] exact ⟨by simp [KExpr.abstractFVarsResult, hfast], hwf, hsup.expr⟩ - · have cached := Ix.Tc.abstractFVarsCached_spec + · have cached := Ix.Kernel.abstractFVarsCached_spec hcollision.expr hbody (depth := 0) (it := it) (sc := {}) (by simpa using hwalk) hreach hwf hsup.expr @@ -271,7 +271,7 @@ theorem abstractFVarsCached_spec {α : Type} fvars.size.toUInt64 depth (it, sc)) := by subst depth obtain ⟨hbody, _, hwalk, _⟩ := h.requestBounds hmem - exact Ix.Tc.abstractFVarsCached_spec h.collisionFree.expr hbody + exact Ix.Kernel.abstractFVarsCached_spec h.collisionFree.expr hbody (by simpa using hwalk) (h.coverage.abstractFVars hmem) hwf hsup hsc theorem instantiateUnivParams_wf {α : Type} @@ -460,4 +460,4 @@ theorem instUniv_wf {α : Type} {initial : TcState .anon} end RunAssumptions -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/ScopedSuffix/ClosedContext.lean b/Ix/Kernel/Verify/ScopedSuffix/ClosedContext.lean similarity index 98% rename from Ix/Tc/Verify/ScopedSuffix/ClosedContext.lean rename to Ix/Kernel/Verify/ScopedSuffix/ClosedContext.lean index fbd6c44f0..f9054d391 100644 --- a/Ix/Tc/Verify/ScopedSuffix/ClosedContext.lean +++ b/Ix/Kernel/Verify/ScopedSuffix/ClosedContext.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.DefEq +import Ix.Kernel.Verify.DefEq /-! # Finite suffix model for closed checker states @@ -13,7 +13,7 @@ proved from `TcM.ctxAddrForLbr_empty`, and the model's state predicate fixes the concrete fields needed to derive the empty reconciliation. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Concrete eager checker states with no legacy/opened local bindings and no driver-owned lazy-ingress hook. @@ -62,7 +62,7 @@ theorem contextDigestFrame {before after : TcState .anon} /-- Reconciliation from a concretely closed state has exactly the empty semantic local context. -/ theorem delta_eq_nil - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {s : TcState .anon} {Delta : KVLCtx} (hclosed : ClosedContextState s) @@ -201,4 +201,4 @@ theorem model_resetPreservesScope end ClosedContextDigest -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/State.lean b/Ix/Kernel/Verify/State.lean similarity index 98% rename from Ix/Tc/Verify/State.lean rename to Ix/Kernel/Verify/State.lean index 878541a03..d40d7b0eb 100644 --- a/Ix/Tc/Verify/State.lean +++ b/Ix/Kernel/Verify/State.lean @@ -1,8 +1,8 @@ -import Ix.Tc.Verify.Env -import Ix.Tc.Verify.Monad -import Ix.Tc.Verify.InstUniv -import Ix.Tc.Verify.Cache -import Ix.Tc.Verify.EquivalenceManager +import Ix.Kernel.Verify.Env +import Ix.Kernel.Verify.Monad +import Ix.Kernel.Verify.InstUniv +import Ix.Kernel.Verify.Cache +import Ix.Kernel.Verify.EquivalenceManager /-! # The verification world and the run invariant @@ -32,9 +32,9 @@ through `KernelStateWF` below. Dual-context agreement and the concrete reduction/inference/native semantic contracts remain K1/K2 obligations. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDecl VExpr) +open Ix.Theory.Named (VDecl VExpr) /-- A concrete checker state is coherent with one verification world. @@ -82,7 +82,7 @@ theorem TcStateWF.load {trProj : RawProjRel} {s : TcState .anon} supplied by successful checking. The concrete state remains unchanged. -/ theorem TcStateWF.promote {trProj : RawProjRel} {s : TcState .anon} {world : VerifyWorld} {id : KId .anon} {d : VDecl} - {venv' : Lean4Lean.VEnv} + {venv' : Ix.Theory.Named.VEnv} (h : TcStateWF trProj s world) (hpending : PendingDecl trProj world id d) (hwf : VDecl.WF world.venv d venv') : @@ -395,4 +395,4 @@ theorem TcM.instantiateUnivParams.tcInv rw [hrun] at hrunWF exact ⟨⟨world, hworld, hrunWF.1⟩, hrunWF.2⟩ -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Statements.lean b/Ix/Kernel/Verify/Statements.lean similarity index 89% rename from Ix/Tc/Verify/Statements.lean rename to Ix/Kernel/Verify/Statements.lean index 5d457294f..b37e30cce 100644 --- a/Ix/Tc/Verify/Statements.lean +++ b/Ix/Kernel/Verify/Statements.lean @@ -1,8 +1,8 @@ -import Ix.Tc.Verify.Check.PublicStandalone -import Ix.Tc.Verify.Check.PublicBlocks -import Ix.Tc.Verify.Driver.BooleanAcceptance -import Ix.Tc.Verify.Ingress.SerializedBoolean -import Ix.Tc.Verify.RecursiveMethods.Public +import Ix.Kernel.Verify.Check.PublicStandalone +import Ix.Kernel.Verify.Check.PublicBlocks +import Ix.Kernel.Verify.Driver.BooleanAcceptance +import Ix.Kernel.Verify.Ingress.SerializedBoolean +import Ix.Kernel.Verify.RecursiveMethods.Public /-! # Public checker theorem frontier @@ -34,7 +34,7 @@ coordinated transaction, physical/ghost identity, and cache-publication layers. Singleton definition blocks are constructive. Inductive and recursor bodies remain relative in the generic adapter to an explicitly supplied `InductiveOracle` resource; the public E3-S root instantiates both -resources from the Lean4Lean Boolean generation certificate. Quotient +resources from the Ix.Theory.Named Boolean generation certificate. Quotient semantics, mutual/nested inductives, indexed or parameterized families, and multi-definition blocks remain outside this certificate-backed release fragment. Collision, finite-resource, lazy-ingress, source-to-router diff --git a/Ix/Tc/Verify/Subst.lean b/Ix/Kernel/Verify/Subst.lean similarity index 99% rename from Ix/Tc/Verify/Subst.lean rename to Ix/Kernel/Verify/Subst.lean index e716a7684..09f265676 100644 --- a/Ix/Tc/Verify/Subst.lean +++ b/Ix/Kernel/Verify/Subst.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Subst -import Ix.Tc.Verify.Expr +import Ix.Kernel.Subst +import Ix.Kernel.Verify.Expr /-! # Subst slice: `lift`/`subst` walkers against pure specs @@ -31,7 +31,7 @@ UInt64.size` for the binder-descent `cutoff + 1`s). An in-memory expression cannot violate them; a 2⁶⁴-deep tower genuinely would. -/ -namespace Ix.Tc +namespace Ix.Kernel variable {m : Mode} @@ -4740,4 +4740,4 @@ theorem Constructed.abstractFVarsSpec {body : KExpr .anon} end KExpr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Suffix.lean b/Ix/Kernel/Verify/Suffix.lean similarity index 99% rename from Ix/Tc/Verify/Suffix.lean rename to Ix/Kernel/Verify/Suffix.lean index 28df86478..3dc7f5df8 100644 --- a/Ix/Tc/Verify/Suffix.lean +++ b/Ix/Kernel/Verify/Suffix.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf +import Ix.Kernel.Verify.Whnf /-! # K2 suffix-context transport boundary @@ -15,7 +15,7 @@ these clauses prevents either arbitrary-state context identification or bare address equality from entering the cache proof. -/ -namespace Ix.Tc +namespace Ix.Kernel /-! ## Exact production memo behavior -/ @@ -589,4 +589,4 @@ theorem cacheWriteOracle {trProj : RawProjRel} {fallback : CacheSemantics} end WhnfSuffixModel -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Support.lean b/Ix/Kernel/Verify/Support.lean similarity index 99% rename from Ix/Tc/Verify/Support.lean rename to Ix/Kernel/Verify/Support.lean index 8676da2d2..4fef22776 100644 --- a/Ix/Tc/Verify/Support.lean +++ b/Ix/Kernel/Verify/Support.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.InstUniv +import Ix.Kernel.Verify.InstUniv import Std.Data.HashMap.Lemmas /-! @@ -26,7 +26,7 @@ operations. Nothing here treats constructor closure as support: that would be infinite and would make finite collision freedom impossible. -/ -namespace Ix.Tc +namespace Ix.Kernel /-! ## Constructive finite predicates -/ @@ -803,4 +803,4 @@ theorem mono {before after : List WalkerRequest} end ResourceBounds -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Totalization.lean b/Ix/Kernel/Verify/Totalization.lean similarity index 99% rename from Ix/Tc/Verify/Totalization.lean rename to Ix/Kernel/Verify/Totalization.lean index 9f511d6a5..e9eeb84e3 100644 --- a/Ix/Tc/Verify/Totalization.lean +++ b/Ix/Kernel/Verify/Totalization.lean @@ -1,6 +1,6 @@ -import Ix.Tc.Verify.Monad -import Ix.Tc.CanonicalCheck -import Ix.Tc.Check +import Ix.Kernel.Verify.Monad +import Ix.Kernel.CanonicalCheck +import Ix.Kernel.Check /-! # K0: equations for the total recursive-methods knot @@ -11,7 +11,7 @@ These equations expose the production definitions needed by the later table runs the selected kernel method under the predecessor table. -/ -namespace Ix.Tc +namespace Ix.Kernel variable {m : Mode} @@ -883,4 +883,4 @@ theorem TcM.runRec_directInfer_zero (e : KExpr m) (s : TcState m) @[simp] theorem TcM.ensureForall_eq_runRec (e : KExpr m) : TcM.ensureForall e = TcM.runRec (RecM.ensureForallDirect e) := rfl -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Trans.lean b/Ix/Kernel/Verify/Trans.lean similarity index 94% rename from Ix/Tc/Verify/Trans.lean rename to Ix/Kernel/Verify/Trans.lean index 19ddd7929..30cf5d5d4 100644 --- a/Ix/Tc/Verify/Trans.lean +++ b/Ix/Kernel/Verify/Trans.lean @@ -1,13 +1,15 @@ -import Ix.Tc.Verify.Subst -import Ix.Tc.Verify.VLCtx -import Lean4Lean.Verify.Typing.Expr -import Lean4Lean.Verify.Typing.Lemmas -import Lean4Lean.Theory.Typing.Lemmas +import Ix.Kernel.Verify.Subst +import Ix.Kernel.Verify.VLCtx +import Ix.Theory.Named.Verify.Typing.Expr +import Ix.Theory.Named.Verify.Typing.Lemmas +import Ix.Theory.Named.Typing.Lemmas + +open Ix.Theory (VLevel) /-! # `TrKExprS` — the KExpr ↔ VExpr translation relation -The Ix.Tc restatement of lean4lean's `TrExprS`, rule-for-rule where the +The Ix.Kernel restatement of the named specification's `TrExprS`, rule-for-rule where the source languages agree, with the divergences owned deliberately: - **Universes are total.** Anon-mode `KUniv` parameters are already de @@ -46,9 +48,9 @@ Reused from the dep (VExpr-only content, fvar/Expr-agnostic): eventually `VEnv.HasPrimitives`. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLevel VLocalDecl VEnv VConstant) +open Ix.Theory.Named (VExpr VLocalDecl VEnv VConstant) /-- Typing-level context well-formedness, mirroring upstream `VLCtx.WF`: fvar-structural freshness plus per-entry `VLocalDecl.WF` (types are @@ -58,7 +60,7 @@ def KVLCtx.WF (env : VEnv) (U : Nat) : KVLCtx → Prop | (ofv, d) :: (Δ : KVLCtx) => KVLCtx.WF env U Δ ∧ (∀ fv deps, ofv = some (fv, deps) → fv ∉ Δ.fvars ∧ deps ⊆ Δ.fvars) ∧ - Lean4Lean.VLocalDecl.WF env U Δ.toCtx d + Ix.Theory.Named.VLocalDecl.WF env U Δ.toCtx d theorem KVLCtx.WF.fvwf {env : VEnv} {U : Nat} : ∀ {Δ : KVLCtx}, KVLCtx.WF env U Δ → Δ.FVWF @@ -96,7 +98,7 @@ def VarsScoped (bvars : Nat) (fvars : List FVarId) : KExpr m → Prop body.VarsScoped (bvars + 1) fvars | .prj _ _ value _ => value.VarsScoped bvars fvars -/-- Structural scope at one mixed Ix/Lean4Lean local context. -/ +/-- Structural scope at one mixed Ix/Ix.Theory.Named local context. -/ def ContextScoped (Delta : KVLCtx) (e : KExpr m) : Prop := e.VarsScoped Delta.bvars Delta.fvars @@ -334,7 +336,7 @@ inductive KBVLift : KVLCtx → KVLCtx → Nat → Nat → Nat → Nat → Prop theorem KBVLift.toCtx {Δ Δ' : KVLCtx} {dn dk n k : Nat} (W : KBVLift Δ Δ' dn dk n k) : - Lean4Lean.Ctx.LiftN n k Δ.toCtx Δ'.toCtx := by + Ix.Theory.Named.Ctx.LiftN n k Δ.toCtx Δ'.toCtx := by induction W with | refl => exact .zero [] | @skip _ Δ' _ _ d _ ih => @@ -474,15 +476,15 @@ protected theorem KBVLift.find? {Δ Δ' : KVLCtx} {dn dk n k : Nat} | refl => simp [H] | @skip _ Δ' _ _ d _ ih => obtain v | fv := v <;> simp [find?, liftVar, next] <;> - exact ⟨_, _, ih H, by simp [Lean4Lean.VExpr.liftN_liftN]⟩ + exact ⟨_, _, ih H, by simp [Ix.Theory.Named.VExpr.liftN_liftN]⟩ | @skip_fvar Δ Δ' _ _ fv d hfresh _ ih => obtain v | fv' := v · simp [find?, liftVar, next] - exact ⟨_, _, ih H, by simp [Lean4Lean.VExpr.liftN_liftN]⟩ + exact ⟨_, _, ih H, by simp [Ix.Theory.Named.VExpr.liftN_liftN]⟩ · have hne : ¬fv.1 = fv' := fun hEq => hfresh (hEq ▸ find?_inr_mem H) simp [find?, liftVar, next, hne] - exact ⟨_, _, ih H, by simp [Lean4Lean.VExpr.liftN_liftN]⟩ + exact ⟨_, _, ih H, by simp [Ix.Theory.Named.VExpr.liftN_liftN]⟩ | cons d _ ih => obtain (_ | v) | fv := v <;> simp [liftVar] <;> [ (simp [find?, next] at H ⊢; simp [← H]); @@ -496,43 +498,43 @@ protected theorem KBVLift.find? {Δ Δ' : KVLCtx} {dn dk n k : Nat} ( simp [find?, next] at H ⊢ obtain ⟨e, A, H, rfl, rfl⟩ := H refine ⟨_, _, ih H, ?_⟩ )] <;> - open Lean4Lean.VLocalDecl in + open Ix.Theory.Named.VLocalDecl in cases d <;> - simp [Lean4Lean.VExpr.lift_liftN', liftN, value, type, depth, - Lean4Lean.VExpr.liftN] + simp [Ix.Theory.Named.VExpr.lift_liftN', liftN, value, type, depth, + Ix.Theory.Named.VExpr.liftN] end KVLCtx /-- Closed literal encodings are `liftN`-invariant. -/ private theorem liftN_natLit (v n k : Nat) : - (Lean4Lean.VExpr.natLit v).liftN n k = Lean4Lean.VExpr.natLit v := by + (Ix.Theory.Named.VExpr.natLit v).liftN n k = Ix.Theory.Named.VExpr.natLit v := by induction v with | zero => rfl | succ v ih => - show Lean4Lean.VExpr.app _ _ = _ - rw [show ((Lean4Lean.VExpr.natLit v).liftN n k) - = Lean4Lean.VExpr.natLit v from ih] + show Ix.Theory.Named.VExpr.app _ _ = _ + rw [show ((Ix.Theory.Named.VExpr.natLit v).liftN n k) + = Ix.Theory.Named.VExpr.natLit v from ih] rfl private theorem liftN_listCharLit (s : List Char) (n k : Nat) : - (Lean4Lean.VExpr.listCharLit s).liftN n k - = Lean4Lean.VExpr.listCharLit s := by + (Ix.Theory.Named.VExpr.listCharLit s).liftN n k + = Ix.Theory.Named.VExpr.listCharLit s := by induction s with | nil => rfl | cons c s ih => - show Lean4Lean.VExpr.app (Lean4Lean.VExpr.app _ (Lean4Lean.VExpr.app _ - ((Lean4Lean.VExpr.natLit c.toNat).liftN n k))) - ((Lean4Lean.VExpr.listCharLit s).liftN n k) = _ + show Ix.Theory.Named.VExpr.app (Ix.Theory.Named.VExpr.app _ (Ix.Theory.Named.VExpr.app _ + ((Ix.Theory.Named.VExpr.natLit c.toNat).liftN n k))) + ((Ix.Theory.Named.VExpr.listCharLit s).liftN n k) = _ rw [liftN_natLit, ih] rfl private theorem liftN_trLiteral (l : Lean.Literal) (n k : Nat) : - (Lean4Lean.VExpr.trLiteral l).liftN n k - = Lean4Lean.VExpr.trLiteral l := by + (Ix.Theory.Named.VExpr.trLiteral l).liftN n k + = Ix.Theory.Named.VExpr.trLiteral l := by cases l with | natVal v => exact liftN_natLit v n k | strVal s => - show Lean4Lean.VExpr.app _ ((Lean4Lean.VExpr.listCharLit _).liftN n k) = _ + show Ix.Theory.Named.VExpr.app _ ((Ix.Theory.Named.VExpr.listCharLit _).liftN n k) = _ rw [liftN_listCharLit] rfl @@ -541,12 +543,12 @@ private theorem liftN_trLiteral (l : Lean.Literal) (n k : Nat) : walker's `UInt64` arguments; `htp` is the trProj-weakening the abstract projection parameter must satisfy (upstream `TrProj.weakN`'s shape). -/ -theorem TrKExprS.weakBV {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.weakBV {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) {Δ : KVLCtx} {e : KExpr .anon} {e' : VExpr} @@ -651,13 +653,13 @@ theorem TrKExprS.weakBV {env : Lean4Lean.VEnv} {uvars : Nat} (htp W.toCtx htrp) | @nat Δ v blob md h => intro Δ' dn dk n k shift cutoff W hshift hcutoff hbig - rw [show (Lean4Lean.VExpr.natLit v).liftN n k - = Lean4Lean.VExpr.natLit v from liftN_natLit v n k] + rw [show (Ix.Theory.Named.VExpr.natLit v).liftN n k + = Ix.Theory.Named.VExpr.natLit v from liftN_natLit v n k] exact .nat h | @str Δ s blob md h => intro Δ' dn dk n k shift cutoff W hshift hcutoff hbig - rw [show (Lean4Lean.VExpr.trLiteral (.strVal s)).liftN n k - = Lean4Lean.VExpr.trLiteral (.strVal s) from + rw [show (Ix.Theory.Named.VExpr.trLiteral (.strVal s)).liftN n k + = Ix.Theory.Named.VExpr.trLiteral (.strVal s) from liftN_trLiteral (.strVal s) n k] exact .str h @@ -692,12 +694,12 @@ private theorem tr_toNat_le_sat1_add_one (x : UInt64) : mention only the source expression: `hcut` bounds binder descent and `hlift` bounds shifted loose indices. These are exactly the two no-wrap obligations carried by `WalkerRequest.Bounds (.lift ...)`. -/ -theorem TrKExprS.weakBV_lbr {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.weakBV_lbr {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) {Δ : KVLCtx} {e : KExpr .anon} {e' : VExpr} @@ -848,14 +850,14 @@ theorem TrKExprS.weakBV_lbr {env : Lean4Lean.VEnv} {uvars : Nat} | @nat Δ v blob info h => cases hcon intro Δ' dn dk n k shift cutoff W hshift hcutoff hcut hlift - rw [show (Lean4Lean.VExpr.natLit v).liftN n k - = Lean4Lean.VExpr.natLit v from liftN_natLit v n k] + rw [show (Ix.Theory.Named.VExpr.natLit v).liftN n k + = Ix.Theory.Named.VExpr.natLit v from liftN_natLit v n k] exact .nat h | @str Δ v blob info h => cases hcon intro Δ' dn dk n k shift cutoff W hshift hcutoff hcut hlift - rw [show (Lean4Lean.VExpr.trLiteral (.strVal v)).liftN n k - = Lean4Lean.VExpr.trLiteral (.strVal v) from + rw [show (Ix.Theory.Named.VExpr.trLiteral (.strVal v)).liftN n k + = Ix.Theory.Named.VExpr.trLiteral (.strVal v) from liftN_trLiteral (.strVal v) n k] exact .str h @@ -889,7 +891,7 @@ private theorem depth_inst (d : VLocalDecl) (e₀ : VExpr) (k : Nat) : protected theorem KInstN.toCtx {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} {dk k : Nat} {Δ₁ Δ : KVLCtx} (W : KInstN Δ₀ e₀ A₀ dk k Δ₁ Δ) : - Lean4Lean.Ctx.InstN Δ₀.toCtx e₀ A₀ k Δ₁.toCtx Δ.toCtx := by + Ix.Theory.Named.Ctx.InstN Δ₀.toCtx e₀ A₀ k Δ₁.toCtx Δ.toCtx := by induction W with | zero => exact .zero | @succ dk k Γ Γ' d _ ih => @@ -924,7 +926,7 @@ private theorem liftN_depth_inst (d : VLocalDecl) (f e₀ : VExpr) cases d with | vlam A => show (f.liftN 1).inst e₀ (k + 1) = (f.inst e₀ k).liftN 1 - exact (Lean4Lean.VExpr.lift_instN_lo f e₀).symm + exact (Ix.Theory.Named.VExpr.lift_instN_lo f e₀).symm | vlet A v => show (f.liftN 0).inst e₀ (k + 0) = (f.inst e₀ k).liftN 0 simp @@ -945,7 +947,7 @@ theorem KInstN.find?_hit {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} {dk k : Nat} intro e' A H simp [find?, next] at H obtain ⟨e, A', H, rfl, rfl⟩ := H - rw [liftN_depth_inst, ih H, Lean4Lean.VExpr.liftN_liftN] + rw [liftN_depth_inst, ih H, Ix.Theory.Named.VExpr.liftN_liftN] /-- Below the substitution site: indices are untouched and values instantiate pointwise. -/ @@ -964,10 +966,10 @@ theorem KInstN.find?_lt {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} {dk k : Nat} obtain ⟨rfl, rfl⟩ := H constructor <;> · cases d <;> - simp [Lean4Lean.VLocalDecl.inst, Lean4Lean.VLocalDecl.value, - Lean4Lean.VLocalDecl.type, Lean4Lean.VLocalDecl.depth, - Lean4Lean.VExpr.inst, Lean4Lean.VExpr.instVar, - Lean4Lean.VExpr.lift_instN_lo] + simp [Ix.Theory.Named.VLocalDecl.inst, Ix.Theory.Named.VLocalDecl.value, + Ix.Theory.Named.VLocalDecl.type, Ix.Theory.Named.VLocalDecl.depth, + Ix.Theory.Named.VExpr.inst, Ix.Theory.Named.VExpr.instVar, + Ix.Theory.Named.VExpr.lift_instN_lo] | j + 1 => simp [find?, next] at H ⊢ obtain ⟨e, A', H, rfl, rfl⟩ := H @@ -988,8 +990,8 @@ theorem KInstN.find?_gt {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} {dk k : Nat} simp [find?, next] at H obtain ⟨e, A', H, rfl, rfl⟩ := H simp only [Nat.add_sub_cancel] - rw [show Lean4Lean.VLocalDecl.depth (.vlam A₀) = 1 from rfl, - Lean4Lean.VExpr.inst_liftN, Lean4Lean.VExpr.inst_liftN] + rw [show Ix.Theory.Named.VLocalDecl.depth (.vlam A₀) = 1 from rfl, + Ix.Theory.Named.VExpr.inst_liftN, Ix.Theory.Named.VExpr.inst_liftN] exact H | @succ dk k Γ Γ' d _ ih => intro j e' A hj H @@ -1017,8 +1019,8 @@ theorem KInstN.find?_fvar {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} {dk k : Nat} intro fv e' A H simp [find?, next] at H obtain ⟨e, A', H, rfl, rfl⟩ := H - rw [show Lean4Lean.VLocalDecl.depth (.vlam A₀) = 1 from rfl, - Lean4Lean.VExpr.inst_liftN, Lean4Lean.VExpr.inst_liftN] + rw [show Ix.Theory.Named.VLocalDecl.depth (.vlam A₀) = 1 from rfl, + Ix.Theory.Named.VExpr.inst_liftN, Ix.Theory.Named.VExpr.inst_liftN] exact H | @succ dk k Γ Γ' d _ ih => intro fv e' A H @@ -1088,12 +1090,12 @@ theorem KInstLet.find?_hit {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} intro e' A H simp [find?, next] at H obtain ⟨rfl, rfl⟩ := H - simp [Lean4Lean.VLocalDecl.value] + simp [Ix.Theory.Named.VLocalDecl.value] | @succ dk k Γ Γ' d _ ih => intro e' A H simp [find?, next] at H obtain ⟨e, A', H, rfl, rfl⟩ := H - rw [ih H, Lean4Lean.VExpr.liftN_liftN] + rw [ih H, Ix.Theory.Named.VExpr.liftN_liftN] /-- References below the removed let retain both their index and resolved Theory pair. -/ @@ -1129,7 +1131,7 @@ theorem KInstLet.find?_gt {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} | j + 1, _ => simp [find?, next] at H obtain ⟨e, A', H, rfl, rfl⟩ := H - simpa [Lean4Lean.VLocalDecl.depth] using H + simpa [Ix.Theory.Named.VLocalDecl.depth] using H | @succ dk k Γ Γ' d _ ih => intro j e' A hj H match j, hj with @@ -1153,7 +1155,7 @@ theorem KInstLet.find?_fvar {Δ₀ : KVLCtx} {e₀ A₀ : VExpr} intro fv e' A H simp [find?, next] at H obtain ⟨e, A', H, rfl, rfl⟩ := H - simpa [Lean4Lean.VLocalDecl.depth] using H + simpa [Ix.Theory.Named.VLocalDecl.depth] using H | @succ dk k Γ Γ' d _ ih => intro fv e' A H simp [find?, next] at H ⊢ @@ -1164,35 +1166,35 @@ end KVLCtx /-- Closed literal encodings are `inst`-invariant. -/ private theorem inst_natLit (v : Nat) (e₀ : VExpr) (k : Nat) : - (Lean4Lean.VExpr.natLit v).inst e₀ k = Lean4Lean.VExpr.natLit v := by + (Ix.Theory.Named.VExpr.natLit v).inst e₀ k = Ix.Theory.Named.VExpr.natLit v := by induction v with | zero => rfl | succ v ih => - show Lean4Lean.VExpr.app _ _ = _ - rw [show ((Lean4Lean.VExpr.natLit v).inst e₀ k) - = Lean4Lean.VExpr.natLit v from ih] + show Ix.Theory.Named.VExpr.app _ _ = _ + rw [show ((Ix.Theory.Named.VExpr.natLit v).inst e₀ k) + = Ix.Theory.Named.VExpr.natLit v from ih] rfl private theorem inst_listCharLit (s : List Char) (e₀ : VExpr) (k : Nat) : - (Lean4Lean.VExpr.listCharLit s).inst e₀ k - = Lean4Lean.VExpr.listCharLit s := by + (Ix.Theory.Named.VExpr.listCharLit s).inst e₀ k + = Ix.Theory.Named.VExpr.listCharLit s := by induction s with | nil => rfl | cons c s ih => - show Lean4Lean.VExpr.app (Lean4Lean.VExpr.app _ (Lean4Lean.VExpr.app _ - ((Lean4Lean.VExpr.natLit c.toNat).inst e₀ k))) - ((Lean4Lean.VExpr.listCharLit s).inst e₀ k) = _ + show Ix.Theory.Named.VExpr.app (Ix.Theory.Named.VExpr.app _ (Ix.Theory.Named.VExpr.app _ + ((Ix.Theory.Named.VExpr.natLit c.toNat).inst e₀ k))) + ((Ix.Theory.Named.VExpr.listCharLit s).inst e₀ k) = _ rw [inst_natLit, ih] rfl private theorem inst_trLiteral (l : Lean.Literal) (e₀ : VExpr) (k : Nat) : - (Lean4Lean.VExpr.trLiteral l).inst e₀ k - = Lean4Lean.VExpr.trLiteral l := by + (Ix.Theory.Named.VExpr.trLiteral l).inst e₀ k + = Ix.Theory.Named.VExpr.trLiteral l := by cases l with | natVal v => exact inst_natLit v e₀ k | strVal s => - show Lean4Lean.VExpr.app _ - ((Lean4Lean.VExpr.listCharLit _).inst e₀ k) = _ + show Ix.Theory.Named.VExpr.app _ + ((Ix.Theory.Named.VExpr.listCharLit _).inst e₀ k) = _ rw [inst_listCharLit] rfl @@ -1201,18 +1203,18 @@ private theorem inst_trLiteral (l : Lean.Literal) (e₀ : VExpr) (k : Nat) : the weakening/instantiation closure the abstract projection parameter must satisfy (upstream's `TrProj.weakN`/`TrProj.instN`, both sorried there). -/ -theorem TrKExprS.instN {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.instN {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) (htpI : ∀ {Γ₀ : List VExpr} {e₀ A₀ : VExpr} {k : Nat} {Γ₁ Γ : List VExpr} {s : Lean.Name} {i : Nat} {e e' : VExpr}, env.HasType uvars Γ₀ e₀ A₀ → - Lean4Lean.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → + Ix.Theory.Named.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → trProj uvars Γ₁ s i e e' → trProj uvars Γ s i (e.inst e₀ k) (e'.inst e₀ k)) {Δ₀ : KVLCtx} {arg : KExpr .anon} {e₀' A₀ : VExpr} @@ -1330,13 +1332,13 @@ theorem TrKExprS.instN {env : Lean4Lean.VEnv} {uvars : Nat} (htpI t₀ W.toCtx htrp) | @nat Δ₁' v blob md h => intro Δ dk k depth W hdepth hbig - rw [show (Lean4Lean.VExpr.natLit v).inst e₀' k - = Lean4Lean.VExpr.natLit v from inst_natLit v e₀' k] + rw [show (Ix.Theory.Named.VExpr.natLit v).inst e₀' k + = Ix.Theory.Named.VExpr.natLit v from inst_natLit v e₀' k] exact .nat h | @str Δ₁' s blob md h => intro Δ dk k depth W hdepth hbig - rw [show (Lean4Lean.VExpr.trLiteral (.strVal s)).inst e₀' k - = Lean4Lean.VExpr.trLiteral (.strVal s) from + rw [show (Ix.Theory.Named.VExpr.trLiteral (.strVal s)).inst e₀' k + = Ix.Theory.Named.VExpr.trLiteral (.strVal s) from inst_trLiteral (.strVal s) e₀' k] exact .str h @@ -1344,12 +1346,12 @@ theorem TrKExprS.instN {env : Lean4Lean.VEnv} {uvars : Nat} context `vlet` leaves the translated Theory expression unchanged. This mirrors upstream `TrExprS.instN_let`, while retaining the explicit UInt64 resource bound required by `KExpr.substSpec`. -/ -theorem TrKExprS.instN_let {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.instN_let {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) {Δ₀ : KVLCtx} {arg : KExpr .anon} {e₀' A₀ : VExpr} @@ -1474,12 +1476,12 @@ theorem TrKExprS.instN_let {env : Lean4Lean.VEnv} {uvars : Nat} /-- Walker-tight let instantiation. The bound is the final conjunct of `WalkerRequest.Bounds (.subst body arg depth)`, and `harg` is its constructed-argument conjunct. No ambient-context size is needed. -/ -theorem TrKExprS.instN_let_lbr {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.instN_let_lbr {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) {Δ₀ : KVLCtx} {arg : KExpr .anon} {e₀' A₀ : VExpr} @@ -1592,18 +1594,18 @@ theorem TrKExprS.instN_let_lbr {env : Lean4Lean.VEnv} {uvars : Nat} /-- **Beta step at the API level**: substituting under one `vlam`. Upstream `TrExprS.inst`. -/ -theorem TrKExprS.inst {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.inst {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) (htpI : ∀ {Γ₀ : List VExpr} {e₀ A₀ : VExpr} {k : Nat} {Γ₁ Γ : List VExpr} {s : Lean.Name} {i : Nat} {e e' : VExpr}, env.HasType uvars Γ₀ e₀ A₀ → - Lean4Lean.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → + Ix.Theory.Named.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → trProj uvars Γ₁ s i e e' → trProj uvars Γ s i (e.inst e₀ k) (e'.inst e₀ k)) {Δ : KVLCtx} {arg body : KExpr .anon} {e₀' A₀ body' : VExpr} @@ -1618,12 +1620,12 @@ theorem TrKExprS.inst {env : Lean4Lean.VEnv} {uvars : Nat} /-- **Explicit-let step at the API level**: substituting under one `vlet` preserves the already-inlined Theory translation. Upstream `TrExprS.inst_let`. -/ -theorem TrKExprS.inst_let {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.inst_let {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) {Δ : KVLCtx} {arg body : KExpr .anon} {e₀' A₀ body' : VExpr} @@ -1637,12 +1639,12 @@ theorem TrKExprS.inst_let {env : Lean4Lean.VEnv} {uvars : Nat} /-- Explicit-let instantiation with the exact depth-zero substitution resource bound, independent of the ambient context size. -/ -theorem TrKExprS.inst_let_lbr {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.inst_let_lbr {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) {Δ : KVLCtx} {arg body : KExpr .anon} {e₀' A₀ body' : VExpr} @@ -1670,7 +1672,7 @@ theorem KVLCtx.vlocalDecl_wf_hasType {env : VEnv} {U : Nat} {Δ : KVLCtx} /-- `VLocalDecl.is_liftN` re-keyed: consing an entry lifts the bare context by the entry's depth. -/ theorem KVLCtx.is_liftN {Δ : KVLCtx} {ofv} : - ∀ {d}, Lean4Lean.Ctx.LiftN (VLocalDecl.depth d) 0 Δ.toCtx + ∀ {d}, Ix.Theory.Named.Ctx.LiftN (VLocalDecl.depth d) 0 Δ.toCtx (KVLCtx.toCtx ((ofv, d) :: Δ)) | .vlam _ => .one | .vlet .. => .zero [] @@ -1694,7 +1696,7 @@ theorem KVLCtx.WF.find?_wf {env : VEnv} {U : Nat} (henv : env.Ordered) : translation context is `OnCtx`-well-formed. -/ theorem KVLCtx.WF.toCtx {env : VEnv} {U : Nat} : ∀ {Δ : KVLCtx}, KVLCtx.WF env U Δ → - Lean4Lean.OnCtx Δ.toCtx (env.IsType U) + Ix.Theory.Named.OnCtx Δ.toCtx (env.IsType U) | [], _ => ⟨⟩ | (_, .vlam _) :: _, ⟨hΔ, _, hA⟩ => ⟨hΔ.toCtx, hA⟩ | (_, .vlet ..) :: _, ⟨hΔ, _, _⟩ => hΔ.toCtx @@ -1702,7 +1704,7 @@ theorem KVLCtx.WF.toCtx {env : VEnv} {U : Nat} : /-- Upstream idiom (Verify/Typing/Lemmas.lean:216): context WF coerces to the bare-context `OnCtx` whenever a Theory lemma wants it. -/ instance {env : VEnv} {U : Nat} {Δ : KVLCtx} : - Coe (KVLCtx.WF env U Δ) (Lean4Lean.OnCtx Δ.toCtx (env.IsType U)) := + Coe (KVLCtx.WF env U Δ) (Ix.Theory.Named.OnCtx Δ.toCtx (env.IsType U)) := ⟨KVLCtx.WF.toCtx⟩ /-- A term well-formed in the empty context is well-formed anywhere @@ -1711,7 +1713,7 @@ private theorem wf_weak0 {env : VEnv} (henv : env.Ordered) {U : Nat} {e : VExpr} (h : VExpr.WF env U [] e) (Γ : List VExpr) : VExpr.WF env U Γ e := by obtain ⟨A, hA⟩ := h - have W : Lean4Lean.Ctx.LiftN Γ.length 0 [] (Γ ++ []) := .zero Γ rfl + have W : Ix.Theory.Named.Ctx.LiftN Γ.length 0 [] (Γ ++ []) := .zero Γ rfl rw [List.append_nil] at W have h2 := hA.weakN henv W have hce : e.ClosedN 0 := (hA.closedN' henv.closed trivial).1 @@ -1882,7 +1884,7 @@ inductive IsDefEq : KVLCtx → KVLCtx → Prop | cons {Δ₁ Δ₂ : KVLCtx} {ofv} {d₁ d₂ : VLocalDecl} : IsDefEq Δ₁ Δ₂ → (∀ fv deps, ofv = some (fv, deps) → fv ∉ Δ₁.fvars ∧ deps ⊆ Δ₁.fvars) → - Lean4Lean.VLocalDecl.IsDefEq env U Δ₁.toCtx d₁ d₂ → + Ix.Theory.Named.VLocalDecl.IsDefEq env U Δ₁.toCtx d₁ d₂ → IsDefEq ((ofv, d₁) :: Δ₁) ((ofv, d₂) :: Δ₂) theorem IsDefEq.refl {env : VEnv} {U : Nat} (henv : env.Ordered) : @@ -1890,7 +1892,7 @@ theorem IsDefEq.refl {env : VEnv} {U : Nat} (henv : env.Ordered) : | [], _ => .nil | (_, _) :: _, ⟨h1, h2, h3⟩ => .cons (IsDefEq.refl henv h1) h2 - (Lean4Lean.VLocalDecl.IsDefEq.refl henv h1.toCtx h3) + (Ix.Theory.Named.VLocalDecl.IsDefEq.refl henv h1.toCtx h3) theorem IsDefEq.defeqCtx {env : VEnv} {U : Nat} {Δ₁ Δ₂ : KVLCtx} : IsDefEq env U Δ₁ Δ₂ → @@ -1948,7 +1950,7 @@ theorem IsDefEq.find?_uniq {env : VEnv} {U : Nat} (henv : VEnv.WF env) : exact ⟨⟨_, h4⟩, h3⟩ · simp rintro d₁' n₁' H1' rfl rfl d₂' n₂' H2' rfl rfl - simpa [Lean4Lean.VLocalDecl.depth, KVLCtx.toCtx] using + simpa [Ix.Theory.Named.VLocalDecl.depth, KVLCtx.toCtx] using find?_uniq henv hΔ H1' H2' /-- Transport of `find?`-success along a context defeq (upstream @@ -1988,19 +1990,19 @@ makes the two targets syntactically equal, so self-defeq suffices — no /-- Closure properties of the abstract, universe-indexed projection translation. The substitution premise and the universe-index change are - kept exactly as Lean4Lean states them; erasing either makes the concrete + kept exactly as Ix.Theory.Named states them; erasing either makes the concrete `TrProj` impossible to instantiate. -/ structure TrProjOK (env : VEnv) (uvars : Nat) (trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop) : Prop where weakN : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k) instN : ∀ {Γ₀ : List VExpr} {e₀ A₀ : VExpr} {k : Nat} {Γ₁ Γ : List VExpr} {s : Lean.Name} {i : Nat} {e e' : VExpr}, env.HasType uvars Γ₀ e₀ A₀ → - Lean4Lean.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → + Ix.Theory.Named.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → trProj uvars Γ₁ s i e e' → trProj uvars Γ s i (e.inst e₀ k) (e'.inst e₀ k) wf : ∀ {Γ : List VExpr} {s : Lean.Name} {i : Nat} {e e' : VExpr}, @@ -2022,7 +2024,7 @@ structure TrProjOK (env : VEnv) (uvars : Nat) trProj U' (Γ.map (VExpr.instL ls)) s i (e.instL ls) (e'.instL ls) monoU : ∀ {U U' : Nat} {Γ : List VExpr} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, U ≤ U' → Lean4Lean.OnCtx Γ (env.IsType U) → + {e e' : VExpr}, U ≤ U' → Ix.Theory.Named.OnCtx Γ (env.IsType U) → trProj U Γ s i e e' → trProj U' Γ s i e e' /-- Uniqueness of structural translation up to defeq (upstream @@ -2225,7 +2227,7 @@ theorem TrKExpr.defeq {env : VEnv} {uvars : Nat} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : VEnv.WF env) {m : Mode} {Δ : KVLCtx} {e : KExpr m} {e₁ e₂ : VExpr} - (hΔ : Lean4Lean.OnCtx Δ.toCtx (env.IsType uvars)) + (hΔ : Ix.Theory.Named.OnCtx Δ.toCtx (env.IsType uvars)) (h1 : TrKExpr env uvars nameOf trProj Δ e e₁) (h2 : env.IsDefEqU uvars Δ.toCtx e₁ e₂) : TrKExpr env uvars nameOf trProj Δ e e₂ := @@ -2239,7 +2241,7 @@ theorem TrKExpr.app {env : VEnv} {uvars : Nat} (henv : VEnv.WF env) {m : Mode} {Δ : KVLCtx} {f a : KExpr m} {md : ExprInfo m} {f' a' A B : VExpr} - (hΔ : Lean4Lean.OnCtx Δ.toCtx (env.IsType uvars)) + (hΔ : Ix.Theory.Named.OnCtx Δ.toCtx (env.IsType uvars)) (h1 : env.HasType uvars Δ.toCtx f' (.forallE A B)) (h2 : env.HasType uvars Δ.toCtx a' A) (h3 : TrKExpr env uvars nameOf trProj Δ f f') @@ -2361,4 +2363,4 @@ theorem TrKExpr.prj {env : VEnv} {uvars : Nat} have ⟨_, H2'⟩ := htp.defeqDFC hΓ h2.symm H2 ⟨_, .prj h1 s2 H2', htp.uniq hΓ H2' H2 h2⟩ -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/VLCtx.lean b/Ix/Kernel/Verify/VLCtx.lean similarity index 93% rename from Ix/Tc/Verify/VLCtx.lean rename to Ix/Kernel/Verify/VLCtx.lean index c59e2aaa0..4bde03d5e 100644 --- a/Ix/Tc/Verify/VLCtx.lean +++ b/Ix/Kernel/Verify/VLCtx.lean @@ -1,10 +1,12 @@ -import Ix.Tc.Env -import Lean4Lean.Verify.VLCtx +import Ix.Kernel.Env +import Ix.Theory.Named.Verify.VLCtx + +open Ix.Theory (VLevel) /-! # `KVLCtx` — the translation-side local context -The Ix.Tc analogue of lean4lean's `VLCtx`: a list of local declarations, +The Ix.Kernel analogue of the named specification's `VLCtx`: a list of local declarations, each optionally tagged with the `FVarId` that addresses it (plus that entry's fvar dependency list, used by the well-formedness layer in Verify/Ctx.lean). Entries tagged `none` are addressable only by de @@ -17,7 +19,7 @@ Design notes: `VExpr`-valued and fvar-agnostic (Theory-shaped despite living in upstream's Verify tree), so its `liftN`/`inst`/`instL` lemmas transfer. Only the fvar-keyed list structure is re-stated, keyed by - `Ix.Tc.FVarId` (the checker's per-`TypeChecker` `UInt64` ids) instead + `Ix.Kernel.FVarId` (the checker's per-`TypeChecker` `UInt64` ids) instead of `Lean.FVarId`. - `find?` mirrors upstream exactly: a bvar hit on a `vlam` produces `.bvar 0` lifted by the depth walked; a hit on a `vlet` produces the @@ -29,9 +31,9 @@ Design notes: only the fvar-structural `FVWF` is here. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VLevel VLocalDecl) +open Ix.Theory.Named (VExpr VLocalDecl) /-! Lawfulness of `FVarId` equality (KId pattern) — here because the fvar-keyed context machinery needs it from `Trans.lean` on. -/ @@ -126,4 +128,4 @@ def FVWF : KVLCtx → Prop end KVLCtx -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf.lean b/Ix/Kernel/Verify/Whnf.lean similarity index 99% rename from Ix/Tc/Verify/Whnf.lean rename to Ix/Kernel/Verify/Whnf.lean index d4067df1a..a3113ecbe 100644 --- a/Ix/Tc/Verify/Whnf.lean +++ b/Ix/Kernel/Verify/Whnf.lean @@ -1,7 +1,9 @@ -import Ix.Tc.Verify.Ctx -import Ix.Tc.Verify.Inductive -import Ix.Tc.Verify.Run -import Ix.Tc.Verify.State +import Ix.Kernel.Verify.Ctx +import Ix.Kernel.Verify.Inductive +import Ix.Kernel.Verify.Run +import Ix.Kernel.Verify.State + +open Ix.Theory (VLevel) /-! # WHNF soundness boundary @@ -24,9 +26,9 @@ from this layer and continue through a caller-supplied fallback semantics; K2 replaces that fallback with their exact typing contracts. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) open Std (HashSet) /-! ## Concrete reduction meaning -/ @@ -216,7 +218,7 @@ def InternUpdateFrame (before after : TcState .anon) : Prop := /-- The empty projection relation satisfies every structural closure law vacuously. This is the canonical K1 fixture interpretation for fragments that contain no projection nodes. -/ -theorem RawProjRel.none_ok (env : Lean4Lean.VEnv) (uvars : Nat) : +theorem RawProjRel.none_ok (env : Ix.Theory.Named.VEnv) (uvars : Nat) : TrProjOK env uvars RawProjRel.none := by constructor <;> intros <;> contradiction @@ -1550,7 +1552,7 @@ theorem letE {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} TrKExprS.inst_let_lbr world.venvWF.ordered theory.projections.weakN hvalCon hbody hval hbig exact ⟨bodyV, bodyV, hsource, hresult, - Lean4Lean.VEnv.IsDefEqU.refl (theory.exprWF hctx hresult)⟩ + Ix.Theory.Named.VEnv.IsDefEqU.refl (theory.exprWF hctx hresult)⟩ /-- One concrete beta step. The result is the same `substSpec` computed by the verified substitution walker; the proof uses `TrKExprS.instN` and the @@ -1561,7 +1563,7 @@ theorem beta {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Δ : KVLCtx} {nm : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body arg : KExpr .anon} {lamMd appMd : ExprInfo .anon} - {A bodyV argV B : VExpr} {u : Lean4Lean.VLevel} + {A bodyV argV B : VExpr} {u : Ix.Theory.VLevel} (hty : TrKExprS world.venv uvars world.nameOf trProj Δ ty A) (hbody : TrKExprS world.venv uvars world.nameOf trProj ((none, .vlam A) :: Δ) body bodyV) @@ -1579,7 +1581,7 @@ theorem beta {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} have hsource : TrKExprS world.venv uvars world.nameOf trProj Δ (.app (.lam nm bi ty body lamMd) arg appMd) (.app (.lam A bodyV) argV) := - .app (Lean4Lean.VEnv.HasType.lam hA hbodyTy) hargTy hlam harg + .app (Ix.Theory.Named.VEnv.HasType.lam hA hbodyTy) hargTy hlam harg have hresult : TrKExprS world.venv uvars world.nameOf trProj Δ (KExpr.substSpec body arg 0) (bodyV.inst argV) := TrKExprS.instN world.venvWF.ordered projections.weakN @@ -1630,7 +1632,7 @@ instantiated left- and right-hand sides; mere membership of a raw recursor rule does not determine the production argument spine. -/ theorem registeredDefEq {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Δ : KVLCtx} {source result : KExpr .anon} - {df : Lean4Lean.VDefEq} {levels : List Lean4Lean.VLevel} + {df : Ix.Theory.Named.VDefEq} {levels : List Ix.Theory.VLevel} (hsource : TrKExprS world.venv uvars world.nameOf trProj Δ source (df.lhs.instL levels)) (hresult : TrKExprS world.venv uvars world.nameOf trProj Δ result @@ -5708,7 +5710,7 @@ theorem appSpineView_collectSpine (e : KExpr m) : /-- Translation-indexed spine view. Each extension retains the exact function and argument typing derivations needed for semantic application congruence. -/ -inductive TrAppSpine (env : Lean4Lean.VEnv) (uvars : Nat) +inductive TrAppSpine (env : Ix.Theory.Named.VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) (Δ : KVLCtx) (head : KExpr .anon) : List (KExpr .anon) → VExpr → Prop @@ -5726,7 +5728,7 @@ inductive TrAppSpine (env : Lean4Lean.VEnv) (uvars : Nat) /-- Every structural translation induces the corresponding typed spine translation; expression metadata is deliberately absent from the view. -/ theorem trAppSpine_of_tr - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Δ : KVLCtx} {e : KExpr .anon} {eV : VExpr} (h : TrKExprS env uvars nameOf trProj Δ e eV) : @@ -5757,7 +5759,7 @@ translation and typing derivation. This is the membership form needed by descriptor-driven reducers whose argument positions are discovered only at runtime. -/ theorem argument - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head arg : KExpr .anon} {args : List (KExpr .anon)} {resultV : VExpr} @@ -5777,7 +5779,7 @@ theorem argument /-- Rebuild the canonical metadata-free raw spine without changing its Theory translation. -/ theorem tr - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Δ : KVLCtx} {head : KExpr .anon} {args : List (KExpr .anon)} {eV : VExpr} @@ -5797,7 +5799,7 @@ end TrAppSpine /-- Re-index a source translation by the head and array returned by the actual production `collectSpine`. -/ theorem trAppSpine_of_collectSpine - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Δ : KVLCtx} {source head : KExpr .anon} {args : Array (KExpr .anon)} {sourceV : VExpr} @@ -7585,7 +7587,7 @@ structure NoDeltaInputSupport (support : RunSupport) : Prop where support head ∧ ∀ (i : Nat) (hi : i < args.size), support args[i] /-- The concrete K1 input for active no-delta primitive proofs. It binds the -canonical anon table to trusted Theory names, carries Lean4Lean's primitive +canonical anon table to trusted Theory names, carries Ix.Theory.Named's primitive reflection laws, records the quotient lift equation, and scopes generated syntax to actual supported executions. This is necessary but intentionally not sufficient for `NoDeltaBaseOracle`: helper state frames and branch-level @@ -7595,7 +7597,7 @@ structure NoDeltaPrimitiveContext (world : VerifyWorld) (support : RunSupport) table : ∀ prims, prims.CanonicalAnon → NoDeltaPrimitiveTableAgrees world prims theoryPrimitives : world.venv.HasPrimitives - quotientDefEq : world.venv.defeqs Lean4Lean.quotDefEq + quotientDefEq : world.venv.defeqs Ix.Theory.Named.quotDefEq collisionFree : support.CollisionFree inputs : NoDeltaInputSupport support generated : NoDeltaGeneratedSupport support flags natSuccMode @@ -7616,7 +7618,7 @@ theorem stateTable /-- `computeNatBin` uses the fixed canonical address table. Under the production table binding, every successful arithmetic result is therefore -one of Lean4Lean's reflected primitive equations, lifted from the empty +one of Ix.Theory.Named's reflected primitive equations, lifted from the empty universe/local context to the current checker context. -/ theorem computeNatBin_defeq {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -8085,7 +8087,7 @@ theorem natPredicate_classifiers · simp /-- Reflect the concrete predicate decision selected by production into the -corresponding Lean4Lean `Nat.beq` or `Nat.ble` equation. -/ +corresponding Ix.Theory.Named `Nat.beq` or `Nat.ble` equation. -/ theorem natPredicate_defeq {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {flags : WhnfFlags} {natSuccMode : NatSuccMode} @@ -8344,7 +8346,7 @@ theorem appSameArg have hfunEq := hsourceEq.trans world.venvWF hΔ hdefeq have hfunEqTyped := hfunEq.of_l world.venvWF hΔ hsourceType have hargEq : world.venv.IsDefEqU uvars Δ.toCtx _ _ := - Lean4Lean.VEnv.IsDefEqU.refl ⟨_, hargType⟩ + Ix.Theory.Named.VEnv.IsDefEqU.refl ⟨_, hargType⟩ have hargEqTyped := hargEq.of_l world.venvWF hΔ hargType have hresultTr' : TrKExprS world.venv uvars world.nameOf trProj Δ (KExpr.mkApp result arg) (.app resultV argV) := by @@ -11877,14 +11879,14 @@ to a function type in a well-formed context. This is strictly narrower than `ExactArity` below. It says nothing about production classifiers, concrete spines, method tables, or run support, and -is the intended target for Lean4Lean's eventual canonical-type +is the intended target for Ix.Theory.Named's eventual canonical-type no-confusion theorem. -/ structure NatBoolResultShapeSeparation (world : VerifyWorld) : Prop where nat : ∀ {uvars : Nat} {Gamma : List VExpr} {A B : VExpr}, - Lean4Lean.OnCtx Gamma (world.venv.IsType uvars) → + Ix.Theory.Named.OnCtx Gamma (world.venv.IsType uvars) → ¬ world.venv.IsDefEqU uvars Gamma .nat (.forallE A B) bool : ∀ {uvars : Nat} {Gamma : List VExpr} {A B : VExpr}, - Lean4Lean.OnCtx Gamma (world.venv.IsType uvars) → + Ix.Theory.Named.OnCtx Gamma (world.venv.IsType uvars) → ¬ world.venv.IsDefEqU uvars Gamma .bool (.forallE A B) /-- A translated application suffix must be empty when its base has a @@ -12088,8 +12090,8 @@ theorem of_result_shape rw [KExpr.mkApp_shape, KExpr.mkApp_shape] exact hbaseMeaningExact have hnatType₀ : world.venv.HasType uvars [] (.natLit value) .nat := by - simpa [Lean4Lean.VLCtx.toCtx] using - (Lean4Lean.TrExprS.natLit + simpa [Ix.Theory.Named.VLCtx.toCtx] using + (Ix.Theory.Named.TrExprS.natLit (Us := List.replicate uvars Lean.Name.anonymous) (Δ := []) context.theoryPrimitives (htable.nat.contains hcatalog) value).2 have hnatType : world.venv.HasType uvars Delta.toCtx @@ -12206,8 +12208,8 @@ theorem of_result_shape exact hbaseMeaningExact have hboolType₀ : world.venv.HasType uvars [] (.boolLit decision) .bool := by - simpa [Lean4Lean.VLCtx.toCtx] using - (Lean4Lean.TrExprS.boolLit + simpa [Ix.Theory.Named.VLCtx.toCtx] using + (Ix.Theory.Named.TrExprS.boolLit (Us := List.replicate uvars Lean.Name.anonymous) (Δ := []) context.theoryPrimitives (htable.boolType.contains hcatalog) decision).2 @@ -12857,25 +12859,25 @@ theorem natSucc_hasType obtain ⟨ci, hlookup⟩ := htable.natSucc.contains hcatalog have hci := hprims.natSucc hlookup subst ci - exact Lean4Lean.VEnv.HasType.const hlookup (by simp) rfl + exact Ix.Theory.Named.VEnv.HasType.const hlookup (by simp) rfl /-- Successor reconstruction preserves the canonical Nat type. -/ theorem natSuccIterV_hasType - {env : Lean4Lean.VEnv} {uvars : Nat} {Gamma : List VExpr} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {Gamma : List VExpr} (hsucc : env.HasType uvars Gamma .natSucc (.forallE .nat .nat)) {value : VExpr} (hvalue : env.HasType uvars Gamma value .nat) (offset : Nat) : env.HasType uvars Gamma (natSuccIterV offset value) .nat := by induction offset with | zero => exact hvalue - | succ offset ih => exact Lean4Lean.VEnv.HasType.app hsucc ih + | succ offset ih => exact Ix.Theory.Named.VEnv.HasType.app hsucc ih /-- Definitional equality of the current inner Nat lifts through every successor already represented by the loop offset. -/ theorem natSuccIterV_congr - {env : Lean4Lean.VEnv} (henv : env.WF) + {env : Ix.Theory.Named.VEnv} (henv : env.WF) {uvars : Nat} {Gamma : List VExpr} - (hGamma : Lean4Lean.OnCtx Gamma (env.IsType uvars)) + (hGamma : Ix.Theory.Named.OnCtx Gamma (env.IsType uvars)) (hsucc : env.HasType uvars Gamma .natSucc (.forallE .nat .nat)) {left right : VExpr} (hleft : env.HasType uvars Gamma left .nat) @@ -12975,7 +12977,7 @@ theorem isNatSuccSpine_wf /-- Singleton inversion for the typed application-spine view. -/ theorem trAppSpine_singleton - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head arg : KExpr .anon} {resultV : VExpr} @@ -13037,7 +13039,7 @@ theorem natSuccSpine_tr have htypes := hfun.uniqU world.venvWF hDelta.toCtx hsucc obtain ⟨⟨_, hdomain⟩, _⟩ := htypes.forallE_inv world.venvWF hDelta.toCtx - have hargNat := Lean4Lean.VEnv.HasType.defeqU_r + have hargNat := Ix.Theory.Named.VEnv.HasType.defeqU_r world.venvWF hDelta.toCtx ⟨_, hdomain⟩ harg exact ⟨curV, hcur, hargNat, rfl⟩ @@ -13681,7 +13683,7 @@ theorem tryReduceNatWithSuccMode_succ_optional_wf hI.1.core.trustedCatalog htable context.theoryPrimitives have happType : world.venv.HasType uvars Delta.toCtx (.app .natSucc argV) .nat := - Lean4Lean.VEnv.HasType.app hsucc hargType + Ix.Theory.Named.VEnv.HasType.app hsucc hargType have hsourceEq : world.venv.IsDefEqU uvars Delta.toCtx sourceV (natSuccIterV 1 argV) := by rw [hsourceV] @@ -15446,4 +15448,4 @@ theorem whnfNoDeltaImpl_noAccel_wf_of_base end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/ArgumentAlignment.lean b/Ix/Kernel/Verify/Whnf/Beta/ArgumentAlignment.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Beta/ArgumentAlignment.lean rename to Ix/Kernel/Verify/Whnf/Beta/ArgumentAlignment.lean index 262fb8489..666541530 100644 --- a/Ix/Tc/Verify/Whnf/Beta/ArgumentAlignment.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/ArgumentAlignment.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.InstantiationChain +import Ix.Kernel.Verify.Whnf.Beta.InstantiationChain /-! # Align concrete and Theory beta arguments @@ -9,9 +9,9 @@ the pointwise alignment once, including array/list indexing, so the one-pass translation theorem can use the exact selected argument in its variable arm. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named namespace RecM @@ -132,4 +132,4 @@ theorem ofValues end SimulArgs end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/ConsumptionBoundary.lean b/Ix/Kernel/Verify/Whnf/Beta/ConsumptionBoundary.lean similarity index 87% rename from Ix/Tc/Verify/Whnf/Beta/ConsumptionBoundary.lean rename to Ix/Kernel/Verify/Whnf/Beta/ConsumptionBoundary.lean index 6355c3b21..0e3cfd9cf 100644 --- a/Ix/Tc/Verify/Whnf/Beta/ConsumptionBoundary.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/ConsumptionBoundary.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.LambdaPeeling +import Ix.Kernel.Verify.Whnf.Beta.LambdaPeeling /-! # Typed splitting at the multi-beta consumption boundary @@ -9,7 +9,7 @@ position, retaining both the applications consumed by beta and every unconsumed application rebuilt afterward. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM namespace TrAppSuffix @@ -18,13 +18,13 @@ definitional equality while retaining the suffix as a `TrAppSuffix`. Unlike `rebase`, this form is intended for a second structural transformation of the replacement prefix before the original trailing arguments are reattached. -/ theorem rebaseStart - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} - {Delta : KVLCtx} {start : Lean4Lean.VExpr} - {args : List (KExpr .anon)} {resultV : Lean4Lean.VExpr} + {Delta : KVLCtx} {start : Ix.Theory.Named.VExpr} + {args : List (KExpr .anon)} {resultV : Ix.Theory.Named.VExpr} (h : TrAppSuffix env uvars nameOf trProj Delta start args resultV) (henv : env.WF) (hDelta : KVLCtx.WF env uvars Delta) - {replacementV : Lean4Lean.VExpr} + {replacementV : Ix.Theory.Named.VExpr} (hreplacement : env.IsDefEqU uvars Delta.toCtx start replacementV) : exists resultV', TrAppSuffix env uvars nameOf trProj Delta replacementV args resultV' /\ @@ -41,15 +41,15 @@ theorem rebaseStart hcurrentEq.of_l henv hDelta.toCtx hfun exact ⟨.app currentV' argV, .app hcurrentSuffix hcurrentType harg hargTr, - (Lean4Lean.VEnv.IsDefEq.appDF hcurrentEqAt harg).toU⟩ + (Ix.Theory.Named.VEnv.IsDefEq.appDF hcurrentEqAt harg).toU⟩ /-- Split a typed application suffix after exactly `n` arguments. Both pieces retain their original typing derivations and production order. -/ theorem splitAt - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} - {Delta : KVLCtx} {start : Lean4Lean.VExpr} - {args : List (KExpr .anon)} {resultV : Lean4Lean.VExpr} + {Delta : KVLCtx} {start : Ix.Theory.Named.VExpr} + {args : List (KExpr .anon)} {resultV : Ix.Theory.Named.VExpr} (h : TrAppSuffix env uvars nameOf trProj Delta start args resultV) (n : Nat) (hn : n <= args.length) : exists middleV, @@ -84,9 +84,9 @@ theorem splitAt arguments; the second contains exactly the `Array.extract` rebuilt by `finishAppResult`. -/ theorem splitConsume - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} - {Delta : KVLCtx} {startV resultV : Lean4Lean.VExpr} + {Delta : KVLCtx} {startV resultV : Ix.Theory.Named.VExpr} {start body : KExpr .anon} {args consumed : Array (KExpr .anon)} (hconsume : consumeBetaLams start args = (body, consumed)) (h : TrAppSuffix env uvars nameOf trProj Delta startV args.toList @@ -108,4 +108,4 @@ theorem splitConsume end TrAppSuffix end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/DependentContexts.lean b/Ix/Kernel/Verify/Whnf/Beta/DependentContexts.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Beta/DependentContexts.lean rename to Ix/Kernel/Verify/Whnf/Beta/DependentContexts.lean index 1041a688a..ce78965bd 100644 --- a/Ix/Tc/Verify/Whnf/Beta/DependentContexts.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/DependentContexts.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.PrefixSemantics +import Ix.Kernel.Verify.Whnf.Beta.PrefixSemantics /-! # Dependent context chains for simultaneous beta @@ -10,7 +10,7 @@ syntax binder and transports the abstract projection relation through every Theory instantiation. -/ -namespace Lean4Lean.VLocalDecl +namespace Ix.Theory.Named.VLocalDecl /-- Instantiate a declaration by outer-to-inner beta arguments. -/ def instBetaArgs (d : VLocalDecl) : List VExpr → (depth : Nat) → VLocalDecl @@ -52,11 +52,11 @@ theorem instBetaArgs_depth (d : VLocalDecl) (args : List VExpr) rw [instBetaArgs, VLocalDecl.inst, VExpr.instBetaArgs, VExpr.instBetaArgs, ih] -end Lean4Lean.VLocalDecl +end Ix.Theory.Named.VLocalDecl -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named namespace KVLCtx @@ -279,7 +279,7 @@ theorem projection (htpI : ∀ {Γ₀ : List VExpr} {e₀ A₀ : VExpr} {position : Nat} {Γ₁ Γ : List VExpr} {s : Lean.Name} {i : Nat} {e e' : VExpr}, env.HasType uvars Γ₀ e₀ A₀ → - Lean4Lean.Ctx.InstN Γ₀ e₀ A₀ position Γ₁ Γ → + Ix.Theory.Named.Ctx.InstN Γ₀ e₀ A₀ position Γ₁ Γ → trProj uvars Γ₁ s i e e' → trProj uvars Γ s i (e.inst e₀ position) (e'.inst e₀ position)) {structName : Lean.Name} {field : Nat} {value result : VExpr} @@ -295,4 +295,4 @@ theorem projection end KInsts end KVLCtx -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/InstantiationChain.lean b/Ix/Kernel/Verify/Whnf/Beta/InstantiationChain.lean similarity index 95% rename from Ix/Tc/Verify/Whnf/Beta/InstantiationChain.lean rename to Ix/Kernel/Verify/Whnf/Beta/InstantiationChain.lean index 3cf8cf957..740287607 100644 --- a/Ix/Tc/Verify/Whnf/Beta/InstantiationChain.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/InstantiationChain.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.DependentContexts +import Ix.Kernel.Verify.Whnf.Beta.DependentContexts /-! # The peeled telescope induces a dependent instantiation chain @@ -10,9 +10,9 @@ context chain itself follows from the recovered lambda declarations and the exact Theory argument values. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named namespace RecM.BetaPeel.Tr @@ -52,7 +52,7 @@ theorem contextInsts hfun'.lam_inv world.venvWF.ordered hDelta.toCtx have hlam' : world.venv.HasType uvars Delta.toCtx (.lam A' bodyV') (.forallE A' B') := - Lean4Lean.VEnv.HasType.lam hA' hbodyV' + Ix.Theory.Named.VEnv.HasType.lam hA' hbodyV' have hforallEq : world.venv.IsDefEqU uvars Delta.toCtx (.forallE domain codomain) (.forallE A' B') := hfun'.uniqU world.venvWF hDelta.toCtx hlam' @@ -75,4 +75,4 @@ theorem contextInsts exact hlifted'.append hfinal end RecM.BetaPeel.Tr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/LambdaInstantiation.lean b/Ix/Kernel/Verify/Whnf/Beta/LambdaInstantiation.lean similarity index 83% rename from Ix/Tc/Verify/Whnf/Beta/LambdaInstantiation.lean rename to Ix/Kernel/Verify/Whnf/Beta/LambdaInstantiation.lean index ebc32c44c..754e5b526 100644 --- a/Ix/Tc/Verify/Whnf/Beta/LambdaInstantiation.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/LambdaInstantiation.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.SimultaneousSubstitution +import Ix.Kernel.Verify.Whnf.Beta.SimultaneousSubstitution /-! # Walker-tight lambda instantiation @@ -10,57 +10,57 @@ This slice replays the same structural proof using `TrKExprS.weakBV_lbr`, so the theorem consumes precisely the final bound carried by `WalkerRequest`. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named private theorem instNatLit_bx (v : Nat) (e₀ : VExpr) (k : Nat) : - (Lean4Lean.VExpr.natLit v).inst e₀ k = Lean4Lean.VExpr.natLit v := by + (Ix.Theory.Named.VExpr.natLit v).inst e₀ k = Ix.Theory.Named.VExpr.natLit v := by induction v with | zero => rfl | succ v ih => - show Lean4Lean.VExpr.app _ _ = _ - rw [show ((Lean4Lean.VExpr.natLit v).inst e₀ k) = - Lean4Lean.VExpr.natLit v from ih] + show Ix.Theory.Named.VExpr.app _ _ = _ + rw [show ((Ix.Theory.Named.VExpr.natLit v).inst e₀ k) = + Ix.Theory.Named.VExpr.natLit v from ih] rfl private theorem instListCharLit_bx (s : List Char) (e₀ : VExpr) (k : Nat) : - (Lean4Lean.VExpr.listCharLit s).inst e₀ k = - Lean4Lean.VExpr.listCharLit s := by + (Ix.Theory.Named.VExpr.listCharLit s).inst e₀ k = + Ix.Theory.Named.VExpr.listCharLit s := by induction s with | nil => rfl | cons c s ih => - show Lean4Lean.VExpr.app (Lean4Lean.VExpr.app _ (Lean4Lean.VExpr.app _ - ((Lean4Lean.VExpr.natLit c.toNat).inst e₀ k))) - ((Lean4Lean.VExpr.listCharLit s).inst e₀ k) = _ + show Ix.Theory.Named.VExpr.app (Ix.Theory.Named.VExpr.app _ (Ix.Theory.Named.VExpr.app _ + ((Ix.Theory.Named.VExpr.natLit c.toNat).inst e₀ k))) + ((Ix.Theory.Named.VExpr.listCharLit s).inst e₀ k) = _ rw [instNatLit_bx, ih] rfl private theorem instTrLiteral_bx (l : Lean.Literal) (e₀ : VExpr) (k : Nat) : - (Lean4Lean.VExpr.trLiteral l).inst e₀ k = - Lean4Lean.VExpr.trLiteral l := by + (Ix.Theory.Named.VExpr.trLiteral l).inst e₀ k = + Ix.Theory.Named.VExpr.trLiteral l := by cases l with | natVal v => exact instNatLit_bx v e₀ k | strVal s => - show Lean4Lean.VExpr.app _ - ((Lean4Lean.VExpr.listCharLit _).inst e₀ k) = _ + show Ix.Theory.Named.VExpr.app _ + ((Ix.Theory.Named.VExpr.listCharLit _).inst e₀ k) = _ rw [instListCharLit_bx] rfl /-- `substSpec` tracks Theory instantiation under the exact loose-binder bound carried by a substitution walker request. -/ -theorem TrKExprS.instN_lbr {env : Lean4Lean.VEnv} {uvars : Nat} +theorem TrKExprS.instN_lbr {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : Nat → List VExpr → Lean.Name → Nat → VExpr → VExpr → Prop} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) (htpI : ∀ {Γ₀ : List VExpr} {e₀ A₀ : VExpr} {k : Nat} {Γ₁ Γ : List VExpr} {s : Lean.Name} {i : Nat} {e e' : VExpr}, env.HasType uvars Γ₀ e₀ A₀ → - Lean4Lean.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → + Ix.Theory.Named.Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → trProj uvars Γ₁ s i e e' → trProj uvars Γ s i (e.inst e₀ k) (e'.inst e₀ k)) {Δ₀ : KVLCtx} {arg : KExpr .anon} {e₀' A₀ : VExpr} @@ -167,14 +167,14 @@ theorem TrKExprS.instN_lbr {env : Lean4Lean.VEnv} {uvars : Nat} exact .prj h1 (ihval W hdepth (by omega)) (htpI t₀ W.toCtx htrp) | @nat Δ₁' v blob md h => intro Δ dk k depth W hdepth hbig - rw [show (Lean4Lean.VExpr.natLit v).inst e₀' k = - Lean4Lean.VExpr.natLit v from instNatLit_bx v e₀' k] + rw [show (Ix.Theory.Named.VExpr.natLit v).inst e₀' k = + Ix.Theory.Named.VExpr.natLit v from instNatLit_bx v e₀' k] exact .nat h | @str Δ₁' s blob md h => intro Δ dk k depth W hdepth hbig - rw [show (Lean4Lean.VExpr.trLiteral (.strVal s)).inst e₀' k = - Lean4Lean.VExpr.trLiteral (.strVal s) from + rw [show (Ix.Theory.Named.VExpr.trLiteral (.strVal s)).inst e₀' k = + Ix.Theory.Named.VExpr.trLiteral (.strVal s) from instTrLiteral_bx (.strVal s) e₀' k] exact .str h -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/LambdaPeeling.lean b/Ix/Kernel/Verify/Whnf/Beta/LambdaPeeling.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Beta/LambdaPeeling.lean rename to Ix/Kernel/Verify/Whnf/Beta/LambdaPeeling.lean index edeed4615..0d70cf0f8 100644 --- a/Ix/Tc/Verify/Whnf/Beta/LambdaPeeling.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/LambdaPeeling.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.StepAssembly +import Ix.Kernel.Verify.Whnf.Structural.StepAssembly /-! # Certified lambda peeling for general beta @@ -9,7 +9,7 @@ spine was consumed. This slice gives the loop a structural certificate and proves that the returned array is exactly a prefix of the input arguments. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- A sequence of lambda bodies reached by consuming arguments in production @@ -122,4 +122,4 @@ theorem consumed_append_remaining end BetaPeel end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/LiftSubstitution.lean b/Ix/Kernel/Verify/Whnf/Beta/LiftSubstitution.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Beta/LiftSubstitution.lean rename to Ix/Kernel/Verify/Whnf/Beta/LiftSubstitution.lean index 722f2e9f3..616c017fd 100644 --- a/Ix/Tc/Verify/Whnf/Beta/LiftSubstitution.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/LiftSubstitution.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.SingletonSubstitution +import Ix.Kernel.Verify.Whnf.Beta.SingletonSubstitution /-! # Lift/substitution cancellation for multi-beta @@ -9,7 +9,7 @@ remove precisely the added lift. This file proves that pure syntactic law with the same no-wrap discipline as the production walkers. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KExpr private theorem toNat_max_bv (a b : UInt64) : @@ -225,4 +225,4 @@ theorem substSpec_liftSpec_succ simpa only [UInt64.add_zero] using h end KExpr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/Meaning.lean b/Ix/Kernel/Verify/Whnf/Beta/Meaning.lean similarity index 94% rename from Ix/Tc/Verify/Whnf/Beta/Meaning.lean rename to Ix/Kernel/Verify/Whnf/Beta/Meaning.lean index c5c25ddeb..9ac67798a 100644 --- a/Ix/Tc/Verify/Whnf/Beta/Meaning.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/Meaning.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.Translation +import Ix.Kernel.Verify.Whnf.Beta.Translation /-! # Constructive multi-beta meaning @@ -10,9 +10,9 @@ file assembles those pieces into `BetaPrefixMeaning`, eliminating the last semantic oracle specific to general multi-beta. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named namespace RecM @@ -42,4 +42,4 @@ theorem betaManyMeaning (trProj : RawProjRel) (world : VerifyWorld) : BetaManyMeaningOracle.of_prefix (betaPrefixMeaning trProj world) end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/PeelTrace.lean b/Ix/Kernel/Verify/Whnf/Beta/PeelTrace.lean similarity index 81% rename from Ix/Tc/Verify/Whnf/Beta/PeelTrace.lean rename to Ix/Kernel/Verify/Whnf/Beta/PeelTrace.lean index 472647ada..029464ff5 100644 --- a/Ix/Tc/Verify/Whnf/Beta/PeelTrace.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/PeelTrace.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.SemanticCore +import Ix.Kernel.Verify.Whnf.Beta.SemanticCore /-! # Translated lambda-peel traces @@ -10,7 +10,7 @@ body. Subsequent simultaneous-instantiation proofs can therefore reason from the actual binder stack rather than only from the number of consumed terms. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM namespace BetaPeel @@ -19,10 +19,10 @@ namespace BetaPeel The final context is the original `Delta` extended by one `vlam` entry per consumed argument, in the same innermost-first order used by de Bruijn indices. -/ -inductive Tr (env : Lean4Lean.VEnv) (uvars : Nat) +inductive Tr (env : Ix.Theory.Named.VEnv) (uvars : Nat) (nameOf : Address -> Option Lean.Name) (trProj : RawProjRel) - (Delta : KVLCtx) (start : KExpr .anon) (startV : Lean4Lean.VExpr) : - List (KExpr .anon) -> KExpr .anon -> KVLCtx -> Lean4Lean.VExpr -> Prop + (Delta : KVLCtx) (start : KExpr .anon) (startV : Ix.Theory.Named.VExpr) : + List (KExpr .anon) -> KExpr .anon -> KVLCtx -> Ix.Theory.Named.VExpr -> Prop | nil (hstart : TrKExprS env uvars nameOf trProj Delta start startV) : Tr env uvars nameOf trProj Delta start startV [] start Delta startV @@ -30,7 +30,7 @@ inductive Tr (env : Lean4Lean.VEnv) (uvars : Nat) {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body : KExpr .anon} {info : ExprInfo .anon} {arg : KExpr .anon} {currentDelta : KVLCtx} - {A bodyV : Lean4Lean.VExpr} + {A bodyV : Ix.Theory.Named.VExpr} (hprefix : Tr env uvars nameOf trProj Delta start startV consumed (.lam name bi ty body info) currentDelta (.lam A bodyV)) (hA : env.IsType uvars currentDelta.toCtx A) @@ -45,11 +45,11 @@ namespace Tr /-- The final concrete body in a translated peel trace has the structural translation stored at the trace endpoint. -/ theorem result - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} - {Delta : KVLCtx} {start : KExpr .anon} {startV : Lean4Lean.VExpr} + {Delta : KVLCtx} {start : KExpr .anon} {startV : Ix.Theory.Named.VExpr} {consumed : List (KExpr .anon)} {body : KExpr .anon} - {bodyDelta : KVLCtx} {bodyV : Lean4Lean.VExpr} + {bodyDelta : KVLCtx} {bodyV : Ix.Theory.Named.VExpr} (h : Tr env uvars nameOf trProj Delta start startV consumed body bodyDelta bodyV) : TrKExprS env uvars nameOf trProj bodyDelta body bodyV := by @@ -60,11 +60,11 @@ theorem result /-- Every consumed lambda contributes exactly one Theory binder to the final mixed context. -/ theorem bvars - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} - {Delta : KVLCtx} {start : KExpr .anon} {startV : Lean4Lean.VExpr} + {Delta : KVLCtx} {start : KExpr .anon} {startV : Ix.Theory.Named.VExpr} {consumed : List (KExpr .anon)} {body : KExpr .anon} - {bodyDelta : KVLCtx} {bodyV : Lean4Lean.VExpr} + {bodyDelta : KVLCtx} {bodyV : Ix.Theory.Named.VExpr} (h : Tr env uvars nameOf trProj Delta start startV consumed body bodyDelta bodyV) : bodyDelta.bvars = Delta.bvars + consumed.length := by @@ -80,10 +80,10 @@ end Tr translated peel trace and an exact structural translation of the final raw body under the recovered binder context. -/ theorem translate - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start body : KExpr .anon} - {consumed : List (KExpr .anon)} {startV : Lean4Lean.VExpr} + {consumed : List (KExpr .anon)} {startV : Ix.Theory.Named.VExpr} (hpeel : BetaPeel start consumed body) (hstart : TrKExprS env uvars nameOf trProj Delta start startV) : exists bodyDelta bodyV, @@ -100,4 +100,4 @@ theorem translate end BetaPeel end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/PrefixSemantics.lean b/Ix/Kernel/Verify/Whnf/Beta/PrefixSemantics.lean similarity index 95% rename from Ix/Tc/Verify/Whnf/Beta/PrefixSemantics.lean rename to Ix/Kernel/Verify/Whnf/Beta/PrefixSemantics.lean index 5bbfb809a..98fdcabae 100644 --- a/Ix/Tc/Verify/Whnf/Beta/PrefixSemantics.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/PrefixSemantics.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Beta.LambdaInstantiation +import Ix.Kernel.Verify.Whnf.Beta.LambdaInstantiation + +open Ix.Theory (VLevel) /-! # Theory semantics of a peeled beta prefix @@ -11,13 +13,13 @@ separate one-pass theorem so it need not pretend that sequential intermediate terms satisfy production's size bound. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named -end Ix.Tc +end Ix.Kernel -namespace Lean4Lean.VExpr +namespace Ix.Theory.Named.VExpr /-- Instantiate outer-to-inner beta arguments. The first argument removes the outermost remaining binder; the final argument removes the binder at @@ -124,17 +126,17 @@ theorem instBetaArgs_liftN (e : VExpr) (args : List VExpr) (depth : Nat) : (depth + args.length) + 1 := by omega rw [hamount, inst_liftN_total, ih] -end Lean4Lean.VExpr +end Ix.Theory.Named.VExpr -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named namespace RecM.TrAppSuffix /-- A typed suffix together with the exact Theory argument values in the same production order as its concrete arguments. -/ -inductive Values (env : Lean4Lean.VEnv) (uvars : Nat) +inductive Values (env : Ix.Theory.Named.VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) (Delta : KVLCtx) (start : VExpr) : List (KExpr .anon) → List VExpr → VExpr → Prop @@ -152,7 +154,7 @@ namespace Values /-- Every typed suffix exposes its exact Theory argument list. -/ theorem ofSuffix - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start : VExpr} {args : List (KExpr .anon)} {resultV : VExpr} @@ -168,7 +170,7 @@ theorem ofSuffix /-- The empty concrete suffix has no Theory arguments and leaves its start expression unchanged. -/ theorem nil_inv - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start resultV : VExpr} {argValues : List VExpr} (h : Values env uvars nameOf trProj Delta start [] argValues resultV) : @@ -180,7 +182,7 @@ theorem nil_inv /-- Exact last-argument view, retaining the Theory-value list. -/ theorem unsnoc - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start : VExpr} {args : List (KExpr .anon)} {arg : KExpr .anon} @@ -207,7 +209,7 @@ end Values /-- Exact last-argument view of a typed suffix. -/ theorem unsnoc - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start : VExpr} {args : List (KExpr .anon)} {arg : KExpr .anon} {resultV : VExpr} @@ -263,7 +265,7 @@ theorem theoryMeaning induction h generalizing argValues appliedV with | nil hstart => obtain ⟨rfl, rfl⟩ := happs.nil_inv - exact Lean4Lean.VEnv.IsDefEqU.refl + exact Ix.Theory.Named.VEnv.IsDefEqU.refl (hstart.wf world.venvWF.ordered theory.literalWF theory.projections.wf hDelta) | @snoc consumed name bi ty body info arg currentDelta A bodyV hprefix @@ -281,7 +283,7 @@ theorem theoryMeaning hfun'.lam_inv world.venvWF.ordered hDelta.toCtx have hlam' : world.venv.HasType uvars Delta.toCtx (.lam A' bodyV') (.forallE A' B') := - Lean4Lean.VEnv.HasType.lam hA' hbodyV' + Ix.Theory.Named.VEnv.HasType.lam hA' hbodyV' have hforallEq : world.venv.IsDefEqU uvars Delta.toCtx (.forallE domain codomain) (.forallE A' B') := hfun'.uniqU world.venvWF hDelta.toCtx hlam' @@ -293,7 +295,7 @@ theorem theoryMeaning harg.defeqU_r world.venvWF hDelta.toCtx hdomainEq have happCong : world.venv.IsDefEqU uvars Delta.toCtx (.app currentV argV) (.app (.lam A' bodyV') argV) := - (Lean4Lean.VEnv.IsDefEq.appDF + (Ix.Theory.Named.VEnv.IsDefEq.appDF (hprefixEq.of_l world.venvWF hDelta.toCtx hfun) harg).toU have hbeta : world.venv.IsDefEqU uvars Delta.toCtx (.app (.lam A' bodyV') argV) (bodyV'.inst argV) := @@ -303,4 +305,4 @@ theorem theoryMeaning end RecM.BetaPeel.Tr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/SemanticCore.lean b/Ix/Kernel/Verify/Whnf/Beta/SemanticCore.lean similarity index 95% rename from Ix/Tc/Verify/Whnf/Beta/SemanticCore.lean rename to Ix/Kernel/Verify/Whnf/Beta/SemanticCore.lean index e9523bb74..344d60d98 100644 --- a/Ix/Tc/Verify/Whnf/Beta/SemanticCore.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/SemanticCore.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.ConsumptionBoundary +import Ix.Kernel.Verify.Whnf.Beta.ConsumptionBoundary /-! # Isolate the semantic core of general multi-beta @@ -11,7 +11,7 @@ substitution theorem, leaving `BetaPrefixMeaning` as the minimal semantic statement that must be proved structurally. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Semantic core of production multi-beta. Starting from a translated @@ -22,7 +22,7 @@ def BetaPrefixMeaning (trProj : RawProjRel) (world : VerifyWorld) : Prop := forall {uvars : Nat}, WhnfTheory trProj world uvars -> forall {Delta : KVLCtx} {start body : KExpr .anon} {consumed : Array (KExpr .anon)} - {startV consumedV : Lean4Lean.VExpr}, + {startV consumedV : Ix.Theory.Named.VExpr}, KVLCtx.WF world.venv uvars Delta -> TrKExprS world.venv uvars world.nameOf trProj Delta start startV -> BetaPeel start consumed.toList body -> @@ -63,4 +63,4 @@ theorem of_prefix {trProj : RawProjRel} {world : VerifyWorld} end BetaManyMeaningOracle end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/SimultaneousSubstitution.lean b/Ix/Kernel/Verify/Whnf/Beta/SimultaneousSubstitution.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Beta/SimultaneousSubstitution.lean rename to Ix/Kernel/Verify/Whnf/Beta/SimultaneousSubstitution.lean index b4f6ce3e5..ee51c3db5 100644 --- a/Ix/Tc/Verify/Whnf/Beta/SimultaneousSubstitution.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/SimultaneousSubstitution.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.LiftSubstitution +import Ix.Kernel.Verify.Whnf.Beta.LiftSubstitution /-! # Simultaneous-substitution decomposition @@ -9,7 +9,7 @@ result is exactly the older simultaneous substitution one binder deeper, followed by ordinary beta substitution for the newly peeled argument. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KExpr private theorem toNat_toUInt64_bw (k : Nat) : @@ -691,4 +691,4 @@ theorem simulSubstSpec_cons | str => rfl end KExpr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/SingletonSubstitution.lean b/Ix/Kernel/Verify/Whnf/Beta/SingletonSubstitution.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Beta/SingletonSubstitution.lean rename to Ix/Kernel/Verify/Whnf/Beta/SingletonSubstitution.lean index d621c0169..3129e2d37 100644 --- a/Ix/Tc/Verify/Whnf/Beta/SingletonSubstitution.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/SingletonSubstitution.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.PeelTrace +import Ix.Kernel.Verify.Whnf.Beta.PeelTrace /-! # Singleton simultaneous substitution @@ -9,7 +9,7 @@ single substitution as a premise. This slice proves that equality uniformly from the same no-wrap bound required by the walker. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KExpr /-- A one-element simultaneous substitution is exactly the ordinary single @@ -118,4 +118,4 @@ theorem simulSubstSpec_singleton | str => rfl end KExpr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Beta/Translation.lean b/Ix/Kernel/Verify/Whnf/Beta/Translation.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Beta/Translation.lean rename to Ix/Kernel/Verify/Whnf/Beta/Translation.lean index 4604d391c..87bcc3835 100644 --- a/Ix/Tc/Verify/Whnf/Beta/Translation.lean +++ b/Ix/Kernel/Verify/Whnf/Beta/Translation.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.ArgumentAlignment +import Ix.Kernel.Verify.Whnf.Beta.ArgumentAlignment /-! # One-pass translation of simultaneous beta substitution @@ -9,9 +9,9 @@ theorems for variables. No sequential concrete intermediate is constructed, so the proof consumes exactly production's original `WalkerRequest.Bounds`. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean +open Ix.Theory.Named private theorem toNat_toUInt64_cc (value : Nat) : value.toUInt64.toNat = value % UInt64.size := by @@ -61,13 +61,13 @@ theorem TrKExprS.simulSubstBeta {trProj : RawProjRel} (henv : env.Ordered) (htp : ∀ {Γ Γ' : List VExpr} {n k : Nat} {s : Lean.Name} {i : Nat} - {e e' : VExpr}, Lean4Lean.Ctx.LiftN n k Γ Γ' → + {e e' : VExpr}, Ix.Theory.Named.Ctx.LiftN n k Γ Γ' → trProj uvars Γ s i e e' → trProj uvars Γ' s i (e.liftN n k) (e'.liftN n k)) (htpI : ∀ {Γ₀ : List VExpr} {e₀ A₀ : VExpr} {position : Nat} {Γ₁ Γ : List VExpr} {s : Lean.Name} {i : Nat} {e e' : VExpr}, env.HasType uvars Γ₀ e₀ A₀ → - Lean4Lean.Ctx.InstN Γ₀ e₀ A₀ position Γ₁ Γ → + Ix.Theory.Named.Ctx.InstN Γ₀ e₀ A₀ position Γ₁ Γ → trProj uvars Γ₁ s i e e' → trProj uvars Γ s i (e.inst e₀ position) (e'.inst e₀ position)) {base : KVLCtx} {substs : Array (KExpr .anon)} @@ -354,4 +354,4 @@ theorem TrKExprS.simulSubstBeta rw [instBetaArgs_trLiteral_cc] exact .str hlit -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Closure.lean b/Ix/Kernel/Verify/Whnf/Closure.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Closure.lean rename to Ix/Kernel/Verify/Whnf/Closure.lean index b9d9b284c..6a4acd990 100644 --- a/Ix/Tc/Verify/Whnf/Closure.lean +++ b/Ix/Kernel/Verify/Whnf/Closure.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Whnf.Delta.OptionalReduction -import Ix.Tc.Verify.Knot +import Ix.Kernel.Verify.Whnf.Delta.OptionalReduction +import Ix.Kernel.Verify.Knot /-! # Four-field fixed-universe WHNF closure @@ -40,7 +40,7 @@ concrete successful, absent, stuck, and partial-error executions in substitute for K2's two missing recursive fields. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- The final K1 cache composition at the universe count encoded by `keys`: WHNF expression entries outside, universe-sensitive delta bodies underneath, @@ -140,4 +140,4 @@ theorem closedAt end K1ClosureContext end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/CacheExecution.lean b/Ix/Kernel/Verify/Whnf/Delta/CacheExecution.lean similarity index 96% rename from Ix/Tc/Verify/Whnf/Delta/CacheExecution.lean rename to Ix/Kernel/Verify/Whnf/Delta/CacheExecution.lean index ddb379603..71e63f63f 100644 --- a/Ix/Tc/Verify/Whnf/Delta/CacheExecution.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/CacheExecution.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Delta.StableCache +import Ix.Kernel.Verify.Whnf.Delta.StableCache /-! # Certified production unfold-cache execution @@ -16,7 +16,7 @@ physical paths of production's `unfoldConstValue`: No arbitrary head/result write authority is used. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace CacheProvenance @@ -69,14 +69,14 @@ theorem unfoldConstValue_trusted_wf (theory : StableWhnfTheory trProj world keys.uvars) (hreferences : TrustedReferences world support) {id : KId .anon} {concrete : KConst .anon} - {ci : Lean4Lean.VDefVal} {kind : Ix.DefKind} + {ci : Ix.Theory.Named.VDefVal} {kind : Ix.DefKind} {lvls : UInt64} {body : KExpr .anon} (trusted : TrustedDeltaBody trProj world id concrete ci kind lvls body) {us : Array (KUniv .anon)} {info : ExprInfo .anon} (resources : DeltaInstantiationResources us body) (hheadSupport : support (.const id us info)) (hrequest : WalkerRequest.instUniv body us ∈ requests) - {Delta : KVLCtx} {headV : Lean4Lean.VExpr} + {Delta : KVLCtx} {headV : Ix.Theory.Named.VExpr} (hhead : TrKExprS world.venv keys.uvars world.nameOf trProj Delta (.const id us info) headV) {s : TcState .anon} : @@ -140,4 +140,4 @@ theorem unfoldConstValue_trusted_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/CacheSemantics.lean b/Ix/Kernel/Verify/Whnf/Delta/CacheSemantics.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Delta/CacheSemantics.lean rename to Ix/Kernel/Verify/Whnf/Delta/CacheSemantics.lean index 8f721d12c..f679c9e00 100644 --- a/Ix/Tc/Verify/Whnf/Delta/CacheSemantics.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/CacheSemantics.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Delta.Integration +import Ix.Kernel.Verify.Whnf.Delta.Integration /-! # Semantic unfold-cache entries @@ -14,7 +14,7 @@ universe count is fixed, matching the `Methods.WFAt` contract used by the recursive reducer. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact fixed-universe validity for one unfold-cache entry. Every finite-support source sharing the stored address must reduce to the cached @@ -126,4 +126,4 @@ theorem unfoldOfMeaning {uvars : Nat} {trProj : RawProjRel} end CacheProvenance -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/ClosedTranslation.lean b/Ix/Kernel/Verify/Whnf/Delta/ClosedTranslation.lean similarity index 80% rename from Ix/Tc/Verify/Whnf/Delta/ClosedTranslation.lean rename to Ix/Kernel/Verify/Whnf/Delta/ClosedTranslation.lean index a63aa8a38..cb0b3c6cc 100644 --- a/Ix/Tc/Verify/Whnf/Delta/ClosedTranslation.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/ClosedTranslation.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Delta.CacheSemantics +import Ix.Kernel.Verify.Whnf.Delta.CacheSemantics /-! # Closed-expression translation under caller contexts @@ -15,9 +15,9 @@ cases compositional and exposes exactly where projection weakening and closedness are used. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr VEnv) +open Ix.Theory.Named (VExpr VEnv) namespace KVLCtx @@ -93,24 +93,24 @@ theorem weakRight {env : VEnv} {uvars : Nat} exact .const hname hlookup hlevels harity | @app inner f arg info f' arg' A B hfunTy hargTy hfun harg ihfun iharg => - have hclosed : Lean4Lean.CtxClosed inner.toCtx := - Lean4Lean.VEnv.CtxWF.closed henv hinner.toCtx + have hclosed : Ix.Theory.Named.CtxClosed inner.toCtx := + Ix.Theory.Named.VEnv.CtxWF.closed henv hinner.toCtx refine .app (A := A) (B := B) ?_ ?_ (ihfun hinner outer) (iharg hinner outer) - · simpa only [KVLCtx.toCtx_appendOuter, Lean4Lean.VEnv.HasType] using + · simpa only [KVLCtx.toCtx_appendOuter, Ix.Theory.Named.VEnv.HasType] using hfunTy.weakR henv hclosed outer.toCtx - · simpa only [KVLCtx.toCtx_appendOuter, Lean4Lean.VEnv.HasType] using + · simpa only [KVLCtx.toCtx_appendOuter, Ix.Theory.Named.VEnv.HasType] using hargTy.weakR henv hclosed outer.toCtx | @lam inner name bi ty body info ty' body' hty htyTr hbodyTr ihty ihbody => - have hclosed : Lean4Lean.CtxClosed inner.toCtx := - Lean4Lean.VEnv.CtxWF.closed henv hinner.toCtx + have hclosed : Ix.Theory.Named.CtxClosed inner.toCtx := + Ix.Theory.Named.VEnv.CtxWF.closed henv hinner.toCtx have htyOriginal := hty obtain ⟨level, htyHasType⟩ := hty have hty' : env.IsType uvars (KVLCtx.appendOuter inner outer).toCtx ty' := by refine ⟨level, ?_⟩ - simpa only [KVLCtx.toCtx_appendOuter, Lean4Lean.VEnv.HasType] using + simpa only [KVLCtx.toCtx_appendOuter, Ix.Theory.Named.VEnv.HasType] using htyHasType.weakR henv hclosed outer.toCtx have hbodyInner : KVLCtx.WF env uvars ((none, .vlam ty') :: inner) := @@ -118,40 +118,40 @@ theorem weakRight {env : VEnv} {uvars : Nat} exact .lam hty' (ihty hinner outer) (ihbody hbodyInner outer) | @all inner name bi ty body info ty' body' hty hbodyTy htyTr hbodyTr ihty ihbody => - have hclosed : Lean4Lean.CtxClosed inner.toCtx := - Lean4Lean.VEnv.CtxWF.closed henv hinner.toCtx + have hclosed : Ix.Theory.Named.CtxClosed inner.toCtx := + Ix.Theory.Named.VEnv.CtxWF.closed henv hinner.toCtx have htyOriginal := hty obtain ⟨level, htyHasType⟩ := hty have hty' : env.IsType uvars (KVLCtx.appendOuter inner outer).toCtx ty' := by refine ⟨level, ?_⟩ - simpa only [KVLCtx.toCtx_appendOuter, Lean4Lean.VEnv.HasType] using + simpa only [KVLCtx.toCtx_appendOuter, Ix.Theory.Named.VEnv.HasType] using htyHasType.weakR henv hclosed outer.toCtx have hbodyInner : KVLCtx.WF env uvars ((none, .vlam ty') :: inner) := ⟨hinner, nofun, htyOriginal⟩ have hbodyClosed : - Lean4Lean.CtxClosed - (KVLCtx.toCtx ((none, Lean4Lean.VLocalDecl.vlam ty') :: inner)) := - Lean4Lean.VEnv.CtxWF.closed henv hbodyInner.toCtx + Ix.Theory.Named.CtxClosed + (KVLCtx.toCtx ((none, Ix.Theory.Named.VLocalDecl.vlam ty') :: inner)) := + Ix.Theory.Named.VEnv.CtxWF.closed henv hbodyInner.toCtx obtain ⟨bodyLevel, hbodyHasType⟩ := hbodyTy have hbodyTy' : env.IsType uvars (KVLCtx.appendOuter - ((none, Lean4Lean.VLocalDecl.vlam ty') :: inner) outer).toCtx + ((none, Ix.Theory.Named.VLocalDecl.vlam ty') :: inner) outer).toCtx body' := by refine ⟨bodyLevel, ?_⟩ - simpa only [KVLCtx.toCtx_appendOuter, Lean4Lean.VEnv.HasType] using + simpa only [KVLCtx.toCtx_appendOuter, Ix.Theory.Named.VEnv.HasType] using hbodyHasType.weakR henv hbodyClosed outer.toCtx exact .all hty' hbodyTy' (ihty hinner outer) (ihbody hbodyInner outer) | @letE inner name ty val body nondep info ty' val' body' hvalTy htyTr hvalTr hbodyTr ihty ihval ihbody => - have hclosed : Lean4Lean.CtxClosed inner.toCtx := - Lean4Lean.VEnv.CtxWF.closed henv hinner.toCtx + have hclosed : Ix.Theory.Named.CtxClosed inner.toCtx := + Ix.Theory.Named.VEnv.CtxWF.closed henv hinner.toCtx have hvalTy' : env.HasType uvars (KVLCtx.appendOuter inner outer).toCtx val' ty' := by - simpa only [KVLCtx.toCtx_appendOuter, Lean4Lean.VEnv.HasType] using + simpa only [KVLCtx.toCtx_appendOuter, Ix.Theory.Named.VEnv.HasType] using hvalTy.weakR henv hclosed outer.toCtx have hbodyInner : KVLCtx.WF env uvars ((none, .vlet ty' val') :: inner) := @@ -160,8 +160,8 @@ theorem weakRight {env : VEnv} {uvars : Nat} (ihbody hbodyInner outer) | @prj inner sid field val info structName val' result' hname hvalTr hproj ihval => - have hclosed : Lean4Lean.CtxClosed inner.toCtx := - Lean4Lean.VEnv.CtxWF.closed henv hinner.toCtx + have hclosed : Ix.Theory.Named.CtxClosed inner.toCtx := + Ix.Theory.Named.VEnv.CtxWF.closed henv hinner.toCtx have hvalWF : VExpr.WF env uvars inner.toCtx val' := hvalTr.wf henv hlit htp.wf hinner have hresultWF : VExpr.WF env uvars inner.toCtx result' := @@ -171,9 +171,9 @@ theorem weakRight {env : VEnv} {uvars : Nat} have hresultClosed : result'.ClosedN inner.toCtx.length := hresultWF.closedN henv hclosed have hlift : - Lean4Lean.Ctx.LiftN outer.toCtx.length inner.toCtx.length + Ix.Theory.Named.Ctx.LiftN outer.toCtx.length inner.toCtx.length inner.toCtx (inner.toCtx ++ outer.toCtx) := - Lean4Lean.Ctx.LiftN.right hclosed outer.toCtx + Ix.Theory.Named.Ctx.LiftN.right hclosed outer.toCtx have hproj' := htp.weakN hlift hproj have hproj'' : trProj uvars (KVLCtx.appendOuter inner outer).toCtx structName @@ -206,13 +206,13 @@ theorem weakRight {env : VEnv} {uvars : Nat} (outer : KVLCtx) : TrKExpr env uvars nameOf trProj (KVLCtx.appendOuter inner outer) e e' := by obtain ⟨structural, hstructural, targetTy, htarget⟩ := H - have hclosed : Lean4Lean.CtxClosed inner.toCtx := - Lean4Lean.VEnv.CtxWF.closed henv hinner.toCtx + have hclosed : Ix.Theory.Named.CtxClosed inner.toCtx := + Ix.Theory.Named.VEnv.CtxWF.closed henv hinner.toCtx refine ⟨structural, hstructural.weakRight henv hlit htp hinner outer, targetTy, ?_⟩ - simpa only [KVLCtx.toCtx_appendOuter, Lean4Lean.VEnv.HasType] using + simpa only [KVLCtx.toCtx_appendOuter, Ix.Theory.Named.VEnv.HasType] using htarget.weakR henv hclosed outer.toCtx end TrKExpr -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/Integration.lean b/Ix/Kernel/Verify/Whnf/Delta/Integration.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Delta/Integration.lean rename to Ix/Kernel/Verify/Whnf/Delta/Integration.lean index 82f13c2e0..b8af069d3 100644 --- a/Ix/Tc/Verify/Whnf/Delta/Integration.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/Integration.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Delta.UnfoldingState +import Ix.Kernel.Verify.Whnf.Delta.UnfoldingState /-! # Package delta and the fourth public WHNF field @@ -15,7 +15,7 @@ theorem below upgrades Reducer's arbitrary-flags `WhnfMeaning` result to the `WhnfPost` shape required by `Methods.WhnfLayerWF`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Complete run-scoped authority for production delta unfolding. The @@ -93,7 +93,7 @@ theorem publicFlags_wf (context : StructuralCoreContext initial program requests keys fallback trProj world support Delta flags) {source : KExpr .anon} (hsourceSupport : support source) - {sourceV : Lean4Lean.VExpr} {s : TcState .anon} + {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta source sourceV) : RecM.WF .noAccel @@ -116,4 +116,4 @@ theorem publicFlags_wf end StructuralCoreContext end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/OptionalReduction.lean b/Ix/Kernel/Verify/Whnf/Delta/OptionalReduction.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Delta/OptionalReduction.lean rename to Ix/Kernel/Verify/Whnf/Delta/OptionalReduction.lean index 15232910c..e45372c99 100644 --- a/Ix/Tc/Verify/Whnf/Delta/OptionalReduction.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/OptionalReduction.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Delta.SpineUnfolding +import Ix.Kernel.Verify.Whnf.Delta.SpineUnfolding /-! # Exact delta optional-reducer closure @@ -9,7 +9,7 @@ the same trusted declaration census and packages the complete reducer in the fixed-universe optional contract consumed by the full-WHNF step. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Local run-equation strengthening used to connect a successful lazy @@ -54,7 +54,7 @@ theorem deltaUnfoldOne_trusted_wf (unfoldCacheSemantics keys.uvars trProj fallback)) trProj world support keys.uvars Delta)) (hreferences : TrustedReferences world support) - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsourceSupport : support source) (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta @@ -184,4 +184,4 @@ def FullWhnfStepContext.ofTrustedDelta delta := delta.wfAt end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/SpineUnfolding.lean b/Ix/Kernel/Verify/Whnf/Delta/SpineUnfolding.lean similarity index 96% rename from Ix/Tc/Verify/Whnf/Delta/SpineUnfolding.lean rename to Ix/Kernel/Verify/Whnf/Delta/SpineUnfolding.lean index f3793bb80..c11904702 100644 --- a/Ix/Tc/Verify/Whnf/Delta/SpineUnfolding.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/SpineUnfolding.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Delta.CacheExecution +import Ix.Kernel.Verify.Whnf.Delta.CacheExecution /-! # Trusted spine-aware delta unfolding @@ -11,7 +11,7 @@ the typed spine to prove that rebuilding preserves the complete source meaning. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Run-scoped trusted resolution and resource bounds for every supported reducible constant head that delta unfolding may reach. @@ -29,7 +29,7 @@ structure TrustedDeltaCensus (trProj : RawProjRel) (world : VerifyWorld) DeltaBodyShape kind lvls body concrete → world.catalog id = some concrete → kind ≠ .opaq → - ∃ ci : Lean4Lean.VDefVal, + ∃ ci : Ix.Theory.Named.VDefVal, TrustedDeltaBody trProj world id concrete ci kind lvls body ∧ DeltaInstantiationResources us body @@ -42,7 +42,7 @@ theorem toPost {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} (theory : WhnfTheory trProj world uvars) {Delta : KVLCtx} (hDelta : KVLCtx.WF world.venv uvars Delta) - {source result : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source result : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) (h : WhnfMeaning trProj world uvars Delta source result) : @@ -112,7 +112,7 @@ theorem tryDeltaUnfold_trusted_wf (unfoldCacheSemantics keys.uvars trProj fallback)) trProj world support keys.uvars Delta)) (hreferences : TrustedReferences world support) - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsourceSupport : support source) (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta @@ -190,4 +190,4 @@ theorem tryDeltaUnfold_trusted_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/StableCache.lean b/Ix/Kernel/Verify/Whnf/Delta/StableCache.lean similarity index 94% rename from Ix/Tc/Verify/Whnf/Delta/StableCache.lean rename to Ix/Kernel/Verify/Whnf/Delta/StableCache.lean index 33f925cb7..14c01710b 100644 --- a/Ix/Tc/Verify/Whnf/Delta/StableCache.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/StableCache.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Delta.TrustedBody +import Ix.Kernel.Verify.Whnf.Delta.TrustedBody + +open Ix.Theory (VLevel) /-! # Stable trusted delta-cache provenance @@ -21,7 +23,7 @@ request: obligations at every permitted extension. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Theory closure at one universe count for every extension of the world in which a stable cache entry may be interpreted. -/ @@ -73,11 +75,11 @@ constant found at the same source node. -/ theorem sourceInputs {trProj : RawProjRel} {world : VerifyWorld} {id : KId .anon} {concrete : KConst .anon} - {ci : Lean4Lean.VDefVal} {kind : Ix.DefKind} + {ci : Ix.Theory.Named.VDefVal} {kind : Ix.DefKind} {lvls : UInt64} {body : KExpr .anon} (h : TrustedDeltaBody trProj world id concrete ci kind lvls body) {uvars : Nat} {us : Array (KUniv .anon)} {info : ExprInfo .anon} - {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta (.const id us info) sourceV) : sourceV = @@ -97,7 +99,7 @@ by the stable cache authority. -/ theorem futureMeaning {trProj : RawProjRel} {world : VerifyWorld} {id : KId .anon} {concrete : KConst .anon} - {ci : Lean4Lean.VDefVal} {kind : Ix.DefKind} + {ci : Ix.Theory.Named.VDefVal} {kind : Ix.DefKind} {lvls : UInt64} {body : KExpr .anon} (h : TrustedDeltaBody trProj world id concrete ci kind lvls body) {uvars : Nat} (theory : StableWhnfTheory trProj world uvars) @@ -119,7 +121,7 @@ for `UnfoldCacheWriteOracle.write`. -/ theorem unfoldCacheProvenance {trProj : RawProjRel} {world : VerifyWorld} {id : KId .anon} {concrete : KConst .anon} - {ci : Lean4Lean.VDefVal} {kind : Ix.DefKind} + {ci : Ix.Theory.Named.VDefVal} {kind : Ix.DefKind} {lvls : UInt64} {body : KExpr .anon} (h : TrustedDeltaBody trProj world id concrete ci kind lvls body) {uvars : Nat} {fallback : CacheSemantics} @@ -144,4 +146,4 @@ theorem unfoldCacheProvenance end TrustedDeltaBody -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/TrustedBody.lean b/Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Delta/TrustedBody.lean rename to Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean index 723072d15..b42339ef3 100644 --- a/Ix/Tc/Verify/Whnf/Delta/TrustedBody.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Delta.UniverseMonotonicity +import Ix.Kernel.Verify.Whnf.Delta.UniverseMonotonicity + +open Ix.Theory (VLevel) /-! # Exact trusted delta-body semantics @@ -26,9 +28,9 @@ body unchanged. ClosedTranslation then weakens the closed body translation into caller's arbitrary mixed context. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDefVal VEnv VExpr VLevel) +open Ix.Theory.Named (VDefVal VEnv VExpr) /-- The exact definition-shaped catalog fields relevant to delta unfolding. Keeping this as an indexed proposition lets a certificate retain the complete @@ -283,4 +285,4 @@ theorem meaning end TrustedDeltaBody -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/UnfoldingState.lean b/Ix/Kernel/Verify/Whnf/Delta/UnfoldingState.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Delta/UnfoldingState.lean rename to Ix/Kernel/Verify/Whnf/Delta/UnfoldingState.lean index c7b7538c1..fa330f0f4 100644 --- a/Ix/Tc/Verify/Whnf/Delta/UnfoldingState.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/UnfoldingState.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Driver.PublicReducers +import Ix.Kernel.Verify.Whnf.Driver.PublicReducers /-! # Delta unfolding state and support closure @@ -17,7 +17,7 @@ reflection field: a loaded definition-shaped catalog entry is not by itself evidence that its body is the trusted definition installed in `VerifyWorld`. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Collision-robust provenance for the universe-instantiated definition body cached under the concrete constant-head address. -/ @@ -63,7 +63,7 @@ structure DeltaUnfoldReflection (semantics : CacheSemantics) (support : RunSupport) : Prop where success : ∀ {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {source result : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {s sf : TcState .anon}, + {sourceV : Ix.Theory.Named.VExpr} {s sf : TcState .anon}, Methods.WFAt .noAccel semantics trProj world support uvars methods → support source → TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → @@ -350,4 +350,4 @@ theorem deltaUnfoldOne_optional_wf_of_contexts reflection.success hmethods hsourceSupport hsource hI hrunDelta⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Delta/UniverseMonotonicity.lean b/Ix/Kernel/Verify/Whnf/Delta/UniverseMonotonicity.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Delta/UniverseMonotonicity.lean rename to Ix/Kernel/Verify/Whnf/Delta/UniverseMonotonicity.lean index 0578a29f9..5341b9b64 100644 --- a/Ix/Tc/Verify/Whnf/Delta/UniverseMonotonicity.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/UniverseMonotonicity.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Delta.ClosedTranslation +import Ix.Kernel.Verify.Whnf.Delta.ClosedTranslation + +open Ix.Theory (VLevel) /-! # Universe-count monotonicity for structural translation @@ -15,9 +17,9 @@ Structural translation follows by induction, carrying the source mixed context's well-formedness through binder cases. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (OnCtx VEnv VExpr VLevel) +open Ix.Theory.Named (OnCtx VEnv VExpr) /-- A well-formed universe level remains well-formed when the available parameter count grows. -/ @@ -159,4 +161,4 @@ theorem monoU {env : VEnv} {before after : Nat} end TrKExprS -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Driver/FullStep.lean b/Ix/Kernel/Verify/Whnf/Driver/FullStep.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Driver/FullStep.lean rename to Ix/Kernel/Verify/Whnf/Driver/FullStep.lean index a8745f155..0dc97ef09 100644 --- a/Ix/Tc/Verify/Whnf/Driver/FullStep.lean +++ b/Ix/Kernel/Verify/Whnf/Driver/FullStep.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.NoDelta.Reducer +import Ix.Kernel.Verify.Whnf.NoDelta.Reducer /-! # Full-WHNF one-step closure @@ -14,7 +14,7 @@ boundary: unlike a miss, successful unfolding must justify both support for the generated expression and its Theory meaning. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- The Decidable acceleration gate satisfies the optional-reducer contract @@ -203,4 +203,4 @@ theorem wf end FullWhnfStepContext end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Driver/PublicReducers.lean b/Ix/Kernel/Verify/Whnf/Driver/PublicReducers.lean similarity index 94% rename from Ix/Tc/Verify/Whnf/Driver/PublicReducers.lean rename to Ix/Kernel/Verify/Whnf/Driver/PublicReducers.lean index 220d51446..6755b23fe 100644 --- a/Ix/Tc/Verify/Whnf/Driver/PublicReducers.lean +++ b/Ix/Kernel/Verify/Whnf/Driver/PublicReducers.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Driver.FullStep +import Ix.Kernel.Verify.Whnf.Driver.FullStep /-! # Public full-WHNF reducers @@ -10,7 +10,7 @@ instrumentation, cache hits and writes, and both Nat successor policies. This slice supplies FullStep's concrete step to those theorems. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM namespace FullWhnfStepContext @@ -26,7 +26,7 @@ theorem publicMode_wf trProj world support Delta) (natSuccMode : NatSuccMode) {source : KExpr .anon} (hsourceSupport : support source) - {sourceV : Lean4Lean.VExpr} {s : TcState .anon} + {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta source sourceV) : RecM.WF .noAccel @@ -56,7 +56,7 @@ theorem publicWhnf_wf (context : FullWhnfStepContext initial program requests keys fallback trProj world support Delta) {source : KExpr .anon} (hsourceSupport : support source) - {sourceV : Lean4Lean.VExpr} {s : TcState .anon} + {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta source sourceV) : RecM.WF .noAccel @@ -77,7 +77,7 @@ theorem publicCore_wf (context : FullWhnfStepContext initial program requests keys fallback trProj world support Delta) {source : KExpr .anon} (hsourceSupport : support source) - {sourceV : Lean4Lean.VExpr} {s : TcState .anon} + {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta source sourceV) : RecM.WF .noAccel @@ -100,4 +100,4 @@ theorem publicCore_wf end FullWhnfStepContext end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/ApplicationRequests.lean b/Ix/Kernel/Verify/Whnf/Iota/ApplicationRequests.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Iota/ApplicationRequests.lean rename to Ix/Kernel/Verify/Whnf/Iota/ApplicationRequests.lean index ec61b5aa8..95ba62c0f 100644 --- a/Ix/Tc/Verify/Whnf/Iota/ApplicationRequests.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ApplicationRequests.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.NatOffset +import Ix.Kernel.Verify.Whnf.Iota.NatOffset /-! # Finite request closure for ordinary iota application @@ -16,7 +16,7 @@ The census is indexed by the exact three production argument slices. Thus a certificate for a convenient argument order cannot justify the real helper. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Exact non-transient intern requests for one left-to-right iota argument @@ -59,7 +59,7 @@ theorem wfList rw [List.foldlM_cons, ReaderT.run_bind] apply TcM.WF.bind (Q₁ := fun next _ => next = KExpr.mkApp result arg) - · rw [Ix.Tc.RecM.applyIotaArg_false, ReaderT.run_monadLift] + · rw [Ix.Kernel.RecM.applyIotaArg_false, ReaderT.run_monadLift] exact TcM.WF.mono (TcM.intern_whnf_wf hrun.collisionFree (hrun.coverage.internExpr request)) @@ -267,4 +267,4 @@ theorem of_requests end TryApplyIotaCtorPreserves end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/ArgumentBranches.lean b/Ix/Kernel/Verify/Whnf/Iota/ArgumentBranches.lean similarity index 95% rename from Ix/Tc/Verify/Whnf/Iota/ArgumentBranches.lean rename to Ix/Kernel/Verify/Whnf/Iota/ArgumentBranches.lean index 390f1e5ff..efe7f4bc6 100644 --- a/Ix/Tc/Verify/Whnf/Iota/ArgumentBranches.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ArgumentBranches.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.Substitution +import Ix.Kernel.Verify.Whnf.Iota.Substitution /-! # Remaining production iota-argument branches @@ -15,7 +15,7 @@ contracts are the branch-local inputs needed for the subsequent proof of the three production application loops. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Every expression shape that bypasses transient beta in `applyIotaArg`. Unlike `WhnfCoreNonLambda`, this includes `app`: an intermediate recursor RHS @@ -63,7 +63,7 @@ theorem appRebuild {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {result arg : KExpr .anon} {sourceInfo : ExprInfo .anon} - {resultV argV A B : Lean4Lean.VExpr} + {resultV argV A B : Ix.Theory.Named.VExpr} (hresultTy : world.venv.HasType uvars Delta.toCtx resultV (.forallE A B)) (hargTy : world.venv.HasType uvars Delta.toCtx argV A) @@ -80,8 +80,8 @@ theorem appRebuild rw [KExpr.mkApp_shape] exact .app hresultTy hargTy hresultTr hargTr exact ⟨_, _, hsource, hrebuilt, - Lean4Lean.VEnv.IsDefEqU.refl - ⟨_, Lean4Lean.VEnv.HasType.app hresultTy hargTy⟩⟩ + Ix.Theory.Named.VEnv.IsDefEqU.refl + ⟨_, Ix.Theory.Named.VEnv.HasType.app hresultTy hargTy⟩⟩ end WhnfMeaning @@ -95,7 +95,7 @@ theorem applyIotaArg_true_nonlam_semantic {sourceInfo : ExprInfo .anon} (hnonlam : IotaArgNonLambda result) (methods : Methods .anon) (s : TcState .anon) - {resultV argV A B : Lean4Lean.VExpr} + {resultV argV A B : Ix.Theory.Named.VExpr} (hresultTy : world.venv.HasType uvars Delta.toCtx resultV (.forallE A B)) (hargTy : world.venv.HasType uvars Delta.toCtx argV A) @@ -129,7 +129,7 @@ theorem applyIotaArg_false_eval obtain ⟨s', hintern, hI', hframe⟩ := TcM.intern_whnf_eval hcollision hsupport hI refine ⟨s', ?_, hI', hframe⟩ - rw [Ix.Tc.RecM.applyIotaArg_false] + rw [Ix.Kernel.RecM.applyIotaArg_false] exact hintern /-- Full non-transient per-argument contract: execution is intern-only, the @@ -144,7 +144,7 @@ theorem applyIotaArg_false_semantic (hsupport : support (KExpr.mkApp result arg)) (hI : WhnfStateInv layer semantics trProj world support uvars Delta s) (methods : Methods .anon) - {resultV argV A B : Lean4Lean.VExpr} + {resultV argV A B : Ix.Theory.Named.VExpr} (hresultTy : world.venv.HasType uvars Delta.toCtx resultV (.forallE A B)) (hargTy : world.venv.HasType uvars Delta.toCtx argV A) @@ -165,4 +165,4 @@ theorem applyIotaArg_false_semantic end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/ArgumentExecution.lean b/Ix/Kernel/Verify/Whnf/Iota/ArgumentExecution.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Iota/ArgumentExecution.lean rename to Ix/Kernel/Verify/Whnf/Iota/ArgumentExecution.lean index bdfc4f840..236a8d200 100644 --- a/Ix/Tc/Verify/Whnf/Iota/ArgumentExecution.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ArgumentExecution.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.ArgumentBranches +import Ix.Kernel.Verify.Whnf.Iota.ArgumentBranches + +open Ix.Theory (VLevel) /-! # Semantic execution of iota argument lists @@ -17,9 +19,9 @@ finite support, and `WhnfMeaning`; induction then transports the quotient translation through every intermediate. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace KExpr @@ -289,7 +291,7 @@ theorem transientLambdaSingletonQuot {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body arg : KExpr .anon} {info : ExprInfo .anon} {expectedV expectedA expectedB A bodyV argV B : VExpr} - {univ : Lean4Lean.VLevel} + {univ : Ix.Theory.VLevel} {s : TcState .anon} (hexpectedTy : world.venv.HasType uvars Delta.toCtx expectedV (.forallE expectedA expectedB)) @@ -313,7 +315,7 @@ theorem transientLambdaSingletonQuot have hrun : (applyIotaArg (.lam name bi ty body info) arg true).run methods s = .ok (substNoIntern body arg 0) s := by - rw [Ix.Tc.RecM.applyIotaArg_true_lam] + rw [Ix.Kernel.RecM.applyIotaArg_true_lam] rfl have hmeaning := WhnfMeaning.betaNoIntern (trProj := trProj) (world := world) (uvars := uvars) (Delta := Delta) @@ -337,7 +339,7 @@ theorem transientLambdaSingleton {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body arg : KExpr .anon} {info : ExprInfo .anon} - {A bodyV argV B : VExpr} {univ : Lean4Lean.VLevel} + {A bodyV argV B : VExpr} {univ : Ix.Theory.VLevel} {s : TcState .anon} (projections : TrProjOK world.venv uvars trProj) (hty : TrKExprS world.venv uvars world.nameOf trProj Delta ty A) @@ -356,7 +358,7 @@ theorem transientLambdaSingleton methods true (.lam name bi ty body info) (.lam A bodyV) s [arg] (substNoIntern body arg 0) (.app (.lam A bodyV) argV) s := transientLambdaSingletonQuot - (Lean4Lean.VEnv.HasType.lam hA hbodyTy) hargTy projections + (Ix.Theory.Named.VEnv.HasType.lam hA hbodyTy) hargTy projections hty hbody harg hA hbodyTy hargTy hbodyCon hargCon hbig hI hresultSupport @@ -613,4 +615,4 @@ end ApplyIotaArgsTrace end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/ConstructorDispatch.lean b/Ix/Kernel/Verify/Whnf/Iota/ConstructorDispatch.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Iota/ConstructorDispatch.lean rename to Ix/Kernel/Verify/Whnf/Iota/ConstructorDispatch.lean index da8d98de5..b281ccd9a 100644 --- a/Ix/Tc/Verify/Whnf/Iota/ConstructorDispatch.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ConstructorDispatch.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.SelectedRule +import Ix.Kernel.Verify.Whnf.Iota.SelectedRule + +open Ix.Theory (VLevel) /-! # Ordinary-constructor iota dispatch @@ -15,9 +17,9 @@ and String-literal expansion. Those remain separate exhaustive branches; the regular theorem cannot silently justify any of them. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDefEq VExpr) +open Ix.Theory.Named (VDefEq VExpr) namespace KConst @@ -236,12 +238,12 @@ theorem checkedAcceptance_empty (hsourceTr : TrKExprS world.venv 0 world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType 0 [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -299,12 +301,12 @@ theorem checkedAcceptance_nonempty (hsourceTr : TrKExprS world.venv uvars world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType uvars [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -559,12 +561,12 @@ theorem tryIotaWithFlags_regularCtor_checkedAcceptance_empty (hsourceTr : TrKExprS world.venv 0 world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType 0 [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -597,4 +599,4 @@ theorem tryIotaWithFlags_regularCtor_checkedAcceptance_empty end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/ConstructorSynthesis.lean b/Ix/Kernel/Verify/Whnf/Iota/ConstructorSynthesis.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Iota/ConstructorSynthesis.lean rename to Ix/Kernel/Verify/Whnf/Iota/ConstructorSynthesis.lean index 9bcf46184..a6827e46e 100644 --- a/Ix/Tc/Verify/Whnf/Iota/ConstructorSynthesis.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ConstructorSynthesis.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.StringLiteral +import Ix.Kernel.Verify.Whnf.Iota.StringLiteral + +open Ix.Theory (VLevel) /-! # Successful K-like constructor synthesis @@ -15,9 +17,9 @@ flag: malformed or untrusted catalog entries may legitimately make any of the caught stages return `none`, and callback errors may retain partial state. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDefEq VExpr) +open Ix.Theory.Named (VDefEq VExpr) namespace RecM @@ -538,12 +540,12 @@ theorem tryIotaWithFlags_kCtor_checkedAcceptance_empty {sourceV sourceType : VExpr} (hsourceTr : TrKExprS world.venv 0 world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType 0 [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -575,4 +577,4 @@ theorem tryIotaWithFlags_kCtor_checkedAcceptance_empty end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/ConstructorSynthesisFallback.lean b/Ix/Kernel/Verify/Whnf/Iota/ConstructorSynthesisFallback.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Iota/ConstructorSynthesisFallback.lean rename to Ix/Kernel/Verify/Whnf/Iota/ConstructorSynthesisFallback.lean index 1bc62a92a..3b5a0f0f1 100644 --- a/Ix/Tc/Verify/Whnf/Iota/ConstructorSynthesisFallback.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ConstructorSynthesisFallback.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.ConstructorSynthesis +import Ix.Kernel.Verify.Whnf.Iota.ConstructorSynthesis /-! # Exhaustive K-synthesis fallback branches @@ -16,7 +16,7 @@ malformed-inductive cases (for example an empty constructor array) from the defensive repeated-lookup cases without assuming catalog immutability. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -683,4 +683,4 @@ end SynthCtorWhenKSelectionTrace end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/Ingress.lean b/Ix/Kernel/Verify/Whnf/Iota/Ingress.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Iota/Ingress.lean rename to Ix/Kernel/Verify/Whnf/Iota/Ingress.lean index b2b209bb7..df8217d32 100644 --- a/Ix/Tc/Verify/Whnf/Iota/Ingress.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/Ingress.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.SynthesisRequests +import Ix.Kernel.Verify.Whnf.Iota.SynthesisRequests /-! # Actual iota ingress state closure @@ -16,7 +16,7 @@ from finite run censuses; the remaining callback premises are confined to bounded helper scans over open declaration telescopes. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Exhaustive state closure of the actual iota reducer. -/ @@ -46,7 +46,7 @@ theorem tryIotaWithFlags_state_wf_of_contexts (hreferences : TrustedReferences world support) (hwrites : ∀ id, world.trusted id → IsRecCacheWriteOracle semantics world support methods id) - (e : KExpr .anon) {sourceV : Lean4Lean.VExpr} + (e : KExpr .anon) {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support e) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta e sourceV) (flags : WhnfFlags) (s : TcState .anon) : @@ -58,12 +58,12 @@ theorem tryIotaWithFlags_state_wf_of_contexts WhnfStateInv .noAccel semantics trProj world support uvars Delta have hpost : ∀ (recId : KId .anon) (recr : IotaInfo .anon) (recUs : Array (KUniv .anon)) (spine : Array (KExpr .anon)) - (major : KExpr .anon) {majorV : Lean4Lean.VExpr} + (major : KExpr .anon) {majorV : Ix.Theory.Named.VExpr} (after : TcState .anon), support major → TrKExprS world.venv uvars world.nameOf trProj Delta major majorV → support spine[recr.majorIdx]! → - ∀ {spineMajorV : Lean4Lean.VExpr}, + ∀ {spineMajorV : Ix.Theory.Named.VExpr}, TrKExprS world.venv uvars world.nameOf trProj Delta spine[recr.majorIdx]! spineMajorV → TcM.WF I after @@ -186,4 +186,4 @@ theorem tryIotaWithFlags_state_wf_of_contexts exact TcM.WF.pure (fun _ => trivial) end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/NatLiteral.lean b/Ix/Kernel/Verify/Whnf/Iota/NatLiteral.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Iota/NatLiteral.lean rename to Ix/Kernel/Verify/Whnf/Iota/NatLiteral.lean index 0dba7dc2c..10645e160 100644 --- a/Ix/Tc/Verify/Whnf/Iota/NatLiteral.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/NatLiteral.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.ConstructorDispatch +import Ix.Kernel.Verify.Whnf.Iota.ConstructorDispatch + +open Ix.Theory (VLevel) /-! # Nat-literal iota preprocessing @@ -14,9 +16,9 @@ WHNF callback after constructing the String spine. K synthesis and struct eta likewise retain their own inference and recursive-WHNF obligations. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDefEq VExpr) +open Ix.Theory.Named (VDefEq VExpr) namespace RecM @@ -193,12 +195,12 @@ theorem tryIotaWithFlags_natCtor_checkedAcceptance_empty (hsourceTr : TrKExprS world.venv 0 world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType 0 [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -231,4 +233,4 @@ theorem tryIotaWithFlags_natCtor_checkedAcceptance_empty end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/NatOffset.lean b/Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Iota/NatOffset.lean rename to Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean index 69a561423..fb5b60aca 100644 --- a/Ix/Tc/Verify/Whnf/Iota/NatOffset.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Runtime.LazyIngress +import Ix.Kernel.Verify.Whnf.Runtime.LazyIngress /-! # State closure for iota's Nat-offset preprocessing @@ -13,7 +13,7 @@ that fact for every input and every invariant, then closes the complete cleanup helper without leaving it as an iota runtime premise. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM set_option maxHeartbeats 800000 @@ -235,7 +235,7 @@ structure NatOffsetCleanupInputOracle (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) : Prop where generated : ∀ {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {before after : TcState .anon} {result : KExpr .anon}, support source → TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → @@ -297,7 +297,7 @@ theorem cleanupNatOffsetMajor_input_wf {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} (inputs : NatOffsetCleanupInputOracle trProj world support) - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsourceSupport : support source) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) @@ -638,4 +638,4 @@ theorem tryIotaAfterMajorWhnf_state_wf | some cleanedMajor => exact hfinish cleanedMajor false afterCleanup end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/NatPatternMatching.lean b/Ix/Kernel/Verify/Whnf/Iota/NatPatternMatching.lean similarity index 86% rename from Ix/Tc/Verify/Whnf/Iota/NatPatternMatching.lean rename to Ix/Kernel/Verify/Whnf/Iota/NatPatternMatching.lean index a083c7404..b73b6e318 100644 --- a/Ix/Tc/Verify/Whnf/Iota/NatPatternMatching.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/NatPatternMatching.lean @@ -1,11 +1,13 @@ -import Ix.Tc.Verify.Whnf.Iota.NatRecognizer +import Ix.Kernel.Verify.Whnf.Iota.NatRecognizer + +open Ix.Theory (VLevel) /-! # Constructive Nat-iota pattern matching NatRecognizer identifies the exact recursor rule and the literal-major position used by the linear Nat recognizer. This slice crosses the next semantic boundary: -it constructs Lean4Lean's dependent `Pattern.Matches` capture map from exact +it constructs Ix.Theory.Named's dependent `Pattern.Matches` capture map from exact constant-spine shapes. The bridge deliberately ends at the application through the major argument. @@ -14,22 +16,22 @@ can be used to justify the production fast path; silently matching a prefix as though it were the whole source would lose over-application semantics. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace HeadConstN /-- Every exact constant-headed spine constructively matches the corresponding -`varN` pattern. The existential capture map is produced by Lean4Lean's own +`varN` pattern. The existential capture map is produced by Ix.Theory.Named's own `Pattern.Matches.var` constructor at each application. -/ theorem matches_varN {name : Lean.Name} {arity : Nat} {source : VExpr} (h : HeadConstN name arity source) : - ∃ (levels : List Lean4Lean.VLevel) - (captures : ((Lean4Lean.Pattern.const name).varN arity).Path → VExpr), - Lean4Lean.Pattern.Matches - ((Lean4Lean.Pattern.const name).varN arity) + ∃ (levels : List Ix.Theory.VLevel) + (captures : ((Ix.Theory.Named.Pattern.const name).varN arity).Path → VExpr), + Ix.Theory.Named.Pattern.Matches + ((Ix.Theory.Named.Pattern.const name).varN arity) source levels captures := by induction h with | const levels => @@ -37,10 +39,10 @@ theorem matches_varN | @app arity fn arg hprefix ih => obtain ⟨levels, captures, hmatch⟩ := ih refine ⟨levels, - (fun path : Option (((Lean4Lean.Pattern.const name).varN arity).Path) => + (fun path : Option (((Ix.Theory.Named.Pattern.const name).varN arity).Path) => path.elim arg captures), ?_⟩ - simpa only [Lean4Lean.Pattern.varN, Nat.add_comm] using - (Lean4Lean.Pattern.Matches.var (a' := arg) hmatch) + simpa only [Ix.Theory.Named.Pattern.varN, Nat.add_comm] using + (Ix.Theory.Named.Pattern.Matches.var (a' := arg) hmatch) /-- The canonical Theory numeral zero is a nullary `Nat.zero` spine. -/ theorem natLit_zero : @@ -60,7 +62,7 @@ end HeadConstN namespace RecursorIotaPattern /-- Exact recursor and constructor spines construct the dependent match for -Lean4Lean's ordinary iota pattern. The recursor levels and both capture maps +Ix.Theory.Named's ordinary iota pattern. The recursor levels and both capture maps are exactly those built by `Pattern.Matches`; no choice principle is needed. -/ theorem matches_of_shapes {recursorName constructorName : Lean.Name} @@ -68,10 +70,10 @@ theorem matches_of_shapes {recursorPrefix major : VExpr} (hrecursor : HeadConstN recursorName majorIdx recursorPrefix) (hconstructor : HeadConstN constructorName constructorArgs major) : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs).Path → VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs) (.app recursorPrefix major) levels captures := by @@ -80,8 +82,8 @@ theorem matches_of_shapes obtain ⟨_, constructorCaptures, hconstructorMatch⟩ := hconstructor.matches_varN refine ⟨recursorLevels, Sum.elim recursorCaptures constructorCaptures, ?_⟩ - simpa only [RecursorIotaPattern, Lean4Lean.SimplePattern.toPattern] using - Lean4Lean.Pattern.Matches.app hrecursorMatch hconstructorMatch + simpa only [RecursorIotaPattern, Ix.Theory.Named.SimplePattern.toPattern] using + Ix.Theory.Named.Pattern.Matches.app hrecursorMatch hconstructorMatch /-- Constructive matching and the counted-spine view are equivalent. This packages the registered-rule inversion together with the capture-map @@ -90,10 +92,10 @@ direction. -/ theorem exists_matches_iff_shapes {recursorName constructorName : Lean.Name} {majorIdx constructorArgs : Nat} {source : VExpr} : - (∃ (levels : List Lean4Lean.VLevel) + (∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs).Path → VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern recursorName majorIdx constructorName constructorArgs) source levels captures) ↔ @@ -112,10 +114,10 @@ theorem matches_natZero {recursorName : Lean.Name} {majorIdx : Nat} {recursorPrefix : VExpr} (hrecursor : HeadConstN recursorName majorIdx recursorPrefix) : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern recursorName majorIdx ``Nat.zero 0).Path → VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern recursorName majorIdx ``Nat.zero 0) (.app recursorPrefix (VExpr.natLit 0)) levels captures := matches_of_shapes hrecursor HeadConstN.natLit_zero @@ -126,10 +128,10 @@ theorem matches_natSucc {recursorName : Lean.Name} {majorIdx predecessor : Nat} {recursorPrefix : VExpr} (hrecursor : HeadConstN recursorName majorIdx recursorPrefix) : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern recursorName majorIdx ``Nat.succ 1).Path → VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern recursorName majorIdx ``Nat.succ 1) (.app recursorPrefix (VExpr.natLit (predecessor + 1))) levels captures := @@ -175,19 +177,19 @@ end NatRecIotaCase namespace RecursorRulePattern /-- Once the recursor prefix and Nat constructor case are fixed, the exact -trusted rule pattern has a concrete Lean4Lean match and capture map. -/ +trusted rule pattern has a concrete Ix.Theory.Named match and capture map. -/ theorem matches_natLiteral {pattern : RecursorRulePattern} {major : Nat} {recursorPrefix : VExpr} (hrecursor : HeadConstN pattern.recursorName pattern.majorIdx recursorPrefix) (hcase : NatRecIotaCase pattern major) : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -204,7 +206,7 @@ namespace TrAppSpine exactly counted Theory constant spine. In particular, this theorem does not forget how many arguments precede a descriptor-selected major. -/ theorem headConstN - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} @@ -228,7 +230,7 @@ theorem headConstN recursor half of the selected pattern match. The length equality is an explicit prefix-boundary obligation. -/ theorem matches_natRecRulePrefix - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} @@ -239,12 +241,12 @@ theorem matches_natRecRulePrefix (hname : nameOf id.addr = some pattern.recursorName) (hlength : args.length = pattern.majorIdx) (hcase : NatRecIotaCase pattern major) : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -264,7 +266,7 @@ pattern provenance. Constructor shape remains a separate Nat-specific fact, so a catalogued rule at index zero or one is not silently assumed to be the corresponding Nat rule. -/ theorem matches_natLiteralPrefix - {env : Lean4Lean.VEnv} {catalog : Catalog} + {env : Ix.Theory.Named.VEnv} {catalog : Catalog} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {id : KId .anon} {recursor : KConst .anon} {rule : RecRule .anon} {pattern : RecursorRulePattern} @@ -277,12 +279,12 @@ theorem matches_natLiteralPrefix (.const id us info) args recursorPrefix) (hlength : args.length = pattern.majorIdx) (hcase : NatRecIotaCase pattern major) : - ∃ (levels : List Lean4Lean.VLevel) + ∃ (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr), - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -292,4 +294,4 @@ theorem matches_natLiteralPrefix end RawRecursorRulePatternRel -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/NatRecognizer.lean b/Ix/Kernel/Verify/Whnf/Iota/NatRecognizer.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Iota/NatRecognizer.lean rename to Ix/Kernel/Verify/Whnf/Iota/NatRecognizer.lean index 1ad3dbf2c..72f005f25 100644 --- a/Ix/Tc/Verify/Whnf/Iota/NatRecognizer.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/NatRecognizer.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.RuntimeContracts +import Ix.Kernel.Verify.Whnf.RuntimeContracts /-! # Linear Nat-recognizer success provenance @@ -12,7 +12,7 @@ from being applied to a recursor rule or major index that execution never selected. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KId @@ -332,4 +332,4 @@ theorem patternAt end TrustedNatRecLiteralParts end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/NatReduction.lean b/Ix/Kernel/Verify/Whnf/Iota/NatReduction.lean similarity index 91% rename from Ix/Tc/Verify/Whnf/Iota/NatReduction.lean rename to Ix/Kernel/Verify/Whnf/Iota/NatReduction.lean index 9c34fe7d0..4da4e5808 100644 --- a/Ix/Tc/Verify/Whnf/Iota/NatReduction.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/NatReduction.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.NatRuleLayout +import Ix.Kernel.Verify.Whnf.Iota.NatRuleLayout + +open Ix.Theory (VLevel) /-! # Checked Nat-iota reduction through typed suffixes @@ -16,9 +18,9 @@ inductive-admission/RHS obligations; neither follows from rule-slot existence or from a successful pattern match alone. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM namespace TrAppSuffix @@ -27,7 +29,7 @@ namespace TrAppSuffix application is typed. For a nonempty suffix, the first applicable function type is recovered by walking backward through the snoc derivation. -/ theorem startHasType - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start : VExpr} {args : List (KExpr .anon)} {resultV resultType : VExpr} @@ -44,7 +46,7 @@ order, and the complete old and new applications remain definitionally equal. In particular, the result expression contains `args`; this theorem cannot justify dropping a trailing application. -/ theorem rebase - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start : VExpr} {args : List (KExpr .anon)} {resultV : VExpr} @@ -75,7 +77,7 @@ theorem rebase simp only [List.foldl_cons, List.foldl_nil] rw [KExpr.mkApp_shape] exact .app hcurrentType harg hcurrentTr hargTr - · exact (Lean4Lean.VEnv.IsDefEq.appDF hcurrentEqAt harg).toU + · exact (Ix.Theory.Named.VEnv.IsDefEq.appDF hcurrentEqAt harg).toU end TrAppSuffix end RecM @@ -86,7 +88,7 @@ namespace RawRecursorRulePatternRel environment. A match is deliberately insufficient: the pattern's explicit definitional-equality checks must also be discharged. -/ theorem checkedReduction - {env : Lean4Lean.VEnv} {catalog : Catalog} + {env : Ix.Theory.Named.VEnv} {catalog : Catalog} {nameOf : Address → Option Lean.Name} {id : KId .anon} {recursor : KConst .anon} {rule : RecRule .anon} {pattern : RecursorRulePattern} @@ -94,13 +96,13 @@ theorem checkedReduction rule pattern) (henv : env.WF) {uvars : Nat} {Gamma : List VExpr} {source A : VExpr} - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hGamma : Lean4Lean.OnCtx Gamma (env.IsType uvars)) - (hmatch : Lean4Lean.Pattern.Matches + (hGamma : Ix.Theory.Named.OnCtx Gamma (env.IsType uvars)) + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -113,7 +115,7 @@ theorem checkedReduction (pattern.rhs.apply levels captures) := by rcases hpattern with ⟨_, _, _, _, _, _, _, hsound⟩ - exact hsound Lean4Lean.VEnv.LE.rfl henv hGamma hmatch htype hchecks + exact hsound Ix.Theory.Named.VEnv.LE.rfl henv hGamma hmatch htype hchecks end RawRecursorRulePatternRel @@ -144,12 +146,12 @@ theorem checkedRhsSuffix {pattern : RecursorRulePattern} (hpattern : RawRecursorRulePatternRel world.venv world.catalog world.nameOf id recursor rule pattern) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -177,4 +179,4 @@ theorem checkedRhsSuffix end NatRecLiteralTranslationSplit end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/NatRuleLayout.lean b/Ix/Kernel/Verify/Whnf/Iota/NatRuleLayout.lean similarity index 96% rename from Ix/Tc/Verify/Whnf/Iota/NatRuleLayout.lean rename to Ix/Kernel/Verify/Whnf/Iota/NatRuleLayout.lean index cb260928b..6bef289d4 100644 --- a/Ix/Tc/Verify/Whnf/Iota/NatRuleLayout.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/NatRuleLayout.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.NatPatternMatching +import Ix.Kernel.Verify.Whnf.Iota.NatPatternMatching + +open Ix.Theory (VLevel) /-! # Trusted Nat-rule layout and through-major spine splitting @@ -15,9 +17,9 @@ suffix separately, so later RHS reasoning cannot accidentally discard an over-application. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) /-! ## Trusted Nat recursor layout -/ @@ -102,7 +104,7 @@ namespace RecM /-- Typed translation of a left-associated application suffix starting from an already translated prefix. The suffix is stored in production order. -/ -inductive TrAppSuffix (env : Lean4Lean.VEnv) (uvars : Nat) +inductive TrAppSuffix (env : Ix.Theory.Named.VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) (Delta : KVLCtx) (start : VExpr) : List (KExpr .anon) → VExpr → Prop @@ -119,7 +121,7 @@ namespace TrAppSuffix /-- Reattach a certified suffix to a translated concrete prefix. -/ theorem tr - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start : VExpr} {args : List (KExpr .anon)} {resultV : VExpr} @@ -144,7 +146,7 @@ namespace TrAppSpine argument. `throughTr` ends exactly after applying the major; `suffixTr` accounts for every later argument. -/ def SplitAt - (env : Lean4Lean.VEnv) (uvars : Nat) + (env : Ix.Theory.Named.VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) (Delta : KVLCtx) (head : KExpr .anon) (args : List (KExpr .anon)) (majorIdx : Nat) @@ -164,7 +166,7 @@ def SplitAt The proof follows the snoc structure of `TrAppSpine`, distinguishing a hit in the prior prefix from the newly appended final argument. -/ theorem splitAt - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head major : KExpr .anon} {args : List (KExpr .anon)} {majorIdx : Nat} {resultV : VExpr} @@ -210,7 +212,7 @@ end TrAppSpine /-- Exact translated decomposition induced by the literal position recorded in a successful Nat-recognizer descriptor. -/ def NatRecLiteralTranslationSplit - (env : Lean4Lean.VEnv) (uvars : Nat) + (env : Ix.Theory.Named.VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) (trProj : RawProjRel) (Delta : KVLCtx) (id : KId .anon) (source : KExpr .anon) (parts : NatRecLiteralParts .anon) @@ -269,7 +271,7 @@ theorem patternMajor The major translation becomes the canonical Theory numeral by inversion of the owned literal translation rule. -/ theorem translatedSplit - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {id : KId .anon} {recursor : KConst .anon} {source : KExpr .anon} {parts : NatRecLiteralParts .anon} @@ -324,7 +326,7 @@ theorem translatedCase ∃ (id : KId .anon) (recursor : KConst .anon) (rule : RecRule .anon) (pattern : RecursorRulePattern) (priorArgs laterArgs : List (KExpr .anon)) (priorV : VExpr) - (levels : List Lean4Lean.VLevel) + (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -338,7 +340,7 @@ theorem translatedCase RawRecursorRulePatternRel world.venv world.catalog world.nameOf id recursor rule pattern ∧ NatRecIotaCase pattern parts.major ∧ - Lean4Lean.Pattern.Matches + Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -363,4 +365,4 @@ end TrustedNatRecLiteralParts end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/OptionalReduction.lean b/Ix/Kernel/Verify/Whnf/Iota/OptionalReduction.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Iota/OptionalReduction.lean rename to Ix/Kernel/Verify/Whnf/Iota/OptionalReduction.lean index 286e3fee1..262a58432 100644 --- a/Ix/Tc/Verify/Whnf/Iota/OptionalReduction.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/OptionalReduction.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.Ingress +import Ix.Kernel.Verify.Whnf.Iota.Ingress /-! # Exhaustive iota optional-reduction contract @@ -21,7 +21,7 @@ ingress is supplied separately by `AnonLazyIngressContext`, which identifies the actual installed `ingressAnonAddrShallow` hook. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Remaining non-method authority used by `tryIotaWithFlags`. @@ -51,7 +51,7 @@ structure IotaSuccessOracle (semantics : CacheSemantics) (support : RunSupport) : Prop where accept : ∀ {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {source : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {flags : WhnfFlags} + {sourceV : Ix.Theory.Named.VExpr} {flags : WhnfFlags} {s sf : TcState .anon} {result : KExpr .anon}, Methods.WFAt .noAccel semantics trProj world support uvars methods → support source → @@ -119,4 +119,4 @@ theorem tryIotaWithFlags_optional_wf_of_contexts success.accept hmethods hsourceSupport hsource hI hrunIota⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/RuleInstantiation.lean b/Ix/Kernel/Verify/Whnf/Iota/RuleInstantiation.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Iota/RuleInstantiation.lean rename to Ix/Kernel/Verify/Whnf/Iota/RuleInstantiation.lean index 5d785cb08..620a82b35 100644 --- a/Ix/Tc/Verify/Whnf/Iota/RuleInstantiation.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/RuleInstantiation.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Whnf.Iota.NatReduction -import Ix.Tc.Verify.InstL +import Ix.Kernel.Verify.Whnf.Iota.NatReduction +import Ix.Kernel.Verify.InstL + +open Ix.Theory (VLevel) /-! # Typed registered recursor RHS instantiation @@ -23,9 +25,9 @@ arguments. Modeling those applications is the next bridge, and conflating the two terms here would be unsound. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDefEq VEnv VExpr) +open Ix.Theory.Named (VDefEq VEnv VExpr) namespace RegisteredRecursorRuleRhsRel @@ -137,4 +139,4 @@ theorem registeredRhsTyped end RawRecursorRuleRel -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/RuleSuffixTransport.lean b/Ix/Kernel/Verify/Whnf/Iota/RuleSuffixTransport.lean similarity index 94% rename from Ix/Tc/Verify/Whnf/Iota/RuleSuffixTransport.lean rename to Ix/Kernel/Verify/Whnf/Iota/RuleSuffixTransport.lean index 31daeebf8..94cc3fb77 100644 --- a/Ix/Tc/Verify/Whnf/Iota/RuleSuffixTransport.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/RuleSuffixTransport.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.RuleInstantiation +import Ix.Kernel.Verify.Whnf.Iota.RuleInstantiation + +open Ix.Theory (VLevel) /-! # Quotient-aware registered RHS suffix transport @@ -20,9 +22,9 @@ The theorem still does not identify an instantiated registered body with sequence remains an explicit subsequent obligation. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) namespace RecM namespace TrAppSuffix @@ -35,7 +37,7 @@ the structural suffix theorem. The result is structural again. In particular, all original concrete suffix arguments remain visible in `args.foldl KExpr.mkApp replacement`. -/ theorem rebaseQuot - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {start : VExpr} {args : List (KExpr .anon)} {resultV : VExpr} @@ -81,12 +83,12 @@ theorem checkedRhsSuffixQuot {pattern : RecursorRulePattern} (hpattern : RawRecursorRulePatternRel world.venv world.catalog world.nameOf id recursor rule pattern) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -115,4 +117,4 @@ theorem checkedRhsSuffixQuot end NatRecLiteralTranslationSplit end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/SelectedRule.lean b/Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Iota/SelectedRule.lean rename to Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean index b53cf19a5..680fd94ca 100644 --- a/Ix/Tc/Verify/Whnf/Iota/SelectedRule.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.ArgumentExecution +import Ix.Kernel.Verify.Whnf.Iota.ArgumentExecution + +open Ix.Theory (VLevel) /-! # Checked execution of one selected iota rule @@ -17,9 +19,9 @@ certificate, the selected-rule trace proves exact production execution, state/intern framing, finite support, and source-to-result `WhnfMeaning`. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDefEq VExpr) +open Ix.Theory.Named (VDefEq VExpr) namespace WhnfMeaning @@ -225,7 +227,7 @@ argument slices is the pattern RHS under the match's levels and captures. Current `RawRecursorRuleRel` and `RawRecursorRulePatternRel` do not imply this equation because they record their RHS values independently. -/ def IotaRhsApplicationAligned - (pattern : RecursorRulePattern) (levels : List Lean4Lean.VLevel) + (pattern : RecursorRulePattern) (levels : List Ix.Theory.VLevel) (captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -605,12 +607,12 @@ theorem checkedMeaning (hsourceTr : TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV) (hsourceType : world.venv.HasType uvars Delta.toCtx sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -662,12 +664,12 @@ theorem checkedAcceptance_empty (hsourceTr : TrKExprS world.venv 0 world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType 0 [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -731,12 +733,12 @@ theorem checkedAcceptance_nonempty (hsourceTr : TrKExprS world.venv uvars world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType uvars [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -763,4 +765,4 @@ end ApplyIotaRuleTrace end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/StringLiteral.lean b/Ix/Kernel/Verify/Whnf/Iota/StringLiteral.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Iota/StringLiteral.lean rename to Ix/Kernel/Verify/Whnf/Iota/StringLiteral.lean index 88c530e6e..8efaddced 100644 --- a/Ix/Tc/Verify/Whnf/Iota/StringLiteral.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/StringLiteral.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.Iota.NatLiteral +import Ix.Kernel.Verify.Whnf.Iota.NatLiteral + +open Ix.Theory (VLevel) /-! # String-literal iota preprocessing @@ -15,9 +17,9 @@ spines is a separate helper-closure obligation; this file does not disguise it as a consequence of the operational callback equation. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VDefEq VExpr) +open Ix.Theory.Named (VDefEq VExpr) namespace RecM @@ -393,12 +395,12 @@ theorem tryIotaWithFlags_strCtor_checkedAcceptance_empty (hsourceTr : TrKExprS world.venv 0 world.nameOf trProj [] source sourceV) (hsourceType : world.venv.HasType 0 [] sourceV sourceType) - {levels : List Lean4Lean.VLevel} + {levels : List Ix.Theory.VLevel} {captures : (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + pattern.constructorFields.toNat)).Path → VExpr} - (hmatch : Lean4Lean.Pattern.Matches + (hmatch : Ix.Theory.Named.Pattern.Matches (RecursorIotaPattern pattern.recursorName pattern.majorIdx pattern.constructorName (pattern.constructorParams.toNat + @@ -431,4 +433,4 @@ theorem tryIotaWithFlags_strCtor_checkedAcceptance_empty end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/StructEtaControl.lean b/Ix/Kernel/Verify/Whnf/Iota/StructEtaControl.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Iota/StructEtaControl.lean rename to Ix/Kernel/Verify/Whnf/Iota/StructEtaControl.lean index 199e21469..8ebcb7d67 100644 --- a/Ix/Tc/Verify/Whnf/Iota/StructEtaControl.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/StructEtaControl.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.ConstructorSynthesisFallback +import Ix.Kernel.Verify.Whnf.Iota.ConstructorSynthesisFallback /-! # Struct-eta iota control-flow closure @@ -16,7 +16,7 @@ structure-like does not itself manufacture the registered Theory recursor equation or projection interpretation. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -1035,4 +1035,4 @@ theorem tryIotaCtorOrStructEta_constructor end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/Substitution.lean b/Ix/Kernel/Verify/Whnf/Iota/Substitution.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Iota/Substitution.lean rename to Ix/Kernel/Verify/Whnf/Iota/Substitution.lean index a8eb642c8..91994ae4f 100644 --- a/Ix/Tc/Verify/Whnf/Iota/Substitution.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/Substitution.lean @@ -1,5 +1,7 @@ -import Ix.Tc.Verify.Whnf.Iota.RuleSuffixTransport -import Ix.Tc.Verify.Totalization +import Ix.Kernel.Verify.Whnf.Iota.RuleSuffixTransport +import Ix.Kernel.Verify.Totalization + +open Ix.Theory (VLevel) /-! # Transient iota substitution agrees with the verified spec @@ -17,7 +19,7 @@ uses the equality to expose the production `applyIotaArg` transient-lambda branch as the verified substitution spec and as a semantic beta reduction. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace KExpr @@ -268,7 +270,7 @@ theorem applyIotaArg_true_lam_spec (hbig : body.size + arg.size < UInt64.size) : RecM.applyIotaArg (.lam name bi dom body info) arg true = pure (KExpr.substSpec body arg 0) := by - rw [Ix.Tc.RecM.applyIotaArg_true_lam, + rw [Ix.Kernel.RecM.applyIotaArg_true_lam, hbody.substNoIntern_eq_substSpec harg (depth := 0) (by rw [show (0 : UInt64).toNat = 0 from rfl]; omega) (by omega)] @@ -299,7 +301,7 @@ theorem betaNoIntern {Delta : KVLCtx} {nm : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body arg : KExpr .anon} {lamMd appMd : ExprInfo .anon} - {A bodyV argV B : Lean4Lean.VExpr} {u : Lean4Lean.VLevel} + {A bodyV argV B : Ix.Theory.Named.VExpr} {u : Ix.Theory.VLevel} (hty : TrKExprS world.venv uvars world.nameOf trProj Delta ty A) (hbody : TrKExprS world.venv uvars world.nameOf trProj ((none, .vlam A) :: Delta) body bodyV) @@ -320,4 +322,4 @@ theorem betaNoIntern end WhnfMeaning -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Iota/SynthesisRequests.lean b/Ix/Kernel/Verify/Whnf/Iota/SynthesisRequests.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Iota/SynthesisRequests.lean rename to Ix/Kernel/Verify/Whnf/Iota/SynthesisRequests.lean index 7ecb711cc..69221e64e 100644 --- a/Ix/Tc/Verify/Whnf/Iota/SynthesisRequests.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/SynthesisRequests.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.StructEta.RebuildRequests +import Ix.Kernel.Verify.Whnf.StructEta.RebuildRequests /-! # Finite request closure for K-synthesis @@ -21,7 +21,7 @@ instantiate it. No catalog, walker, or generated-expression effect remains abstract. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- State-only contract for the actual DefEq back-edge, including production's @@ -75,7 +75,7 @@ theorem callIsDefEq_wf {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} (hmethods : Methods.WFAt layer semantics trProj world support uvars methods) - {a b : KExpr .anon} {va vb : Lean4Lean.VExpr} + {a b : KExpr .anon} {va vb : Ix.Theory.Named.VExpr} (haSupport : support a) (hbSupport : support b) (ha : TrKExprS world.venv uvars world.nameOf trProj Delta a va) (hb : TrKExprS world.venv uvars world.nameOf trProj Delta b vb) @@ -136,7 +136,7 @@ def KSynthCandidateInputs {params : Nat} (plan : KSynthCandidateRequests requests ctorId tyUs tyArgs params) (majorTyW : KExpr .anon) : Prop := - ∃ majorTyWV ctorAppV : Lean4Lean.VExpr, + ∃ majorTyWV ctorAppV : Ix.Theory.Named.VExpr, support majorTyW ∧ TrKExprS world.venv uvars world.nameOf trProj Delta majorTyW majorTyWV ∧ @@ -168,7 +168,7 @@ structure KSynthCandidateInputOracle (support : RunSupport) : Prop where candidate : ∀ {uvars : Nat} {Delta : KVLCtx} - {majorTyW : KExpr .anon} {majorTyWV : Lean4Lean.VExpr} + {majorTyW : KExpr .anon} {majorTyWV : Ix.Theory.Named.VExpr} {tyHeadId indId ctorId : KId .anon} {tyUs : Array (KUniv .anon)} {tyInfo : ExprInfo .anon} {tyArgs : Array (KExpr .anon)} {params : Nat} @@ -468,7 +468,7 @@ theorem selectKSynthCandidate_state_wf_of_inputs (hfault : TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) (candidateInputs : KSynthCandidateInputOracle trProj world support) - {majorTyW : KExpr .anon} {majorTyWV : Lean4Lean.VExpr} + {majorTyW : KExpr .anon} {majorTyWV : Ix.Theory.Named.VExpr} {tyHeadId : KId .anon} {tyUs : Array (KUniv .anon)} {tyInfo : ExprInfo .anon} {tyArgs : Array (KExpr .anon)} {indId : KId .anon} {params : Nat} @@ -663,7 +663,7 @@ theorem synthCtorWhenK_state_wf_of_inputs (WhnfStateInv layer semantics trProj world support uvars current)) (hreferences : TrustedReferences world support) (candidateInputs : KSynthCandidateInputOracle trProj world support) - {major : KExpr .anon} {majorV : Lean4Lean.VExpr} + {major : KExpr .anon} {majorV : Ix.Theory.Named.VExpr} (hmajorSupport : support major) (hmajorTr : TrKExprS world.venv uvars world.nameOf trProj Delta major majorV) @@ -757,4 +757,4 @@ theorem synthCtorWhenK_state_wf_of_inputs afterScan end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/NoDelta/BaseReductions.lean b/Ix/Kernel/Verify/Whnf/NoDelta/BaseReductions.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/NoDelta/BaseReductions.lean rename to Ix/Kernel/Verify/Whnf/NoDelta/BaseReductions.lean index dc21fcce9..954f38dec 100644 --- a/Ix/Tc/Verify/Whnf/NoDelta/BaseReductions.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/BaseReductions.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.NoDelta.QuotientReflection +import Ix.Kernel.Verify.Whnf.NoDelta.QuotientReflection /-! # Assemble the active no-delta base oracle @@ -10,7 +10,7 @@ constructs the `NoDeltaBaseOracle` consumed by the already-proved ordered no-delta step. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Complete input package for the five active no-delta reducers. @@ -92,4 +92,4 @@ theorem oracle end NoDeltaBaseContext end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/NoDelta/ProjectionApplication.lean b/Ix/Kernel/Verify/Whnf/NoDelta/ProjectionApplication.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/NoDelta/ProjectionApplication.lean rename to Ix/Kernel/Verify/Whnf/NoDelta/ProjectionApplication.lean index 95a18174d..088ed9097 100644 --- a/Ix/Tc/Verify/Whnf/NoDelta/ProjectionApplication.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/ProjectionApplication.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.Reducer +import Ix.Kernel.Verify.Whnf.Structural.Reducer /-! # Projection-application no-delta field @@ -14,7 +14,7 @@ boundary supplies meaning for the changed head; and the finite application census certifies the exact left-to-right suffix rebuilt by production. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-! ## Exact raw-helper equations -/ @@ -202,7 +202,7 @@ theorem tryProjAppReduceFinished_app_optional_wf (horacle : InductiveReductionOracle .noAccel semantics trProj world support) {f arg : KExpr .anon} {info : ExprInfo .anon} {flags : WhnfFlags} - {uvars : Nat} {Delta : KVLCtx} {sourceV : Lean4Lean.VExpr} + {uvars : Nat} {Delta : KVLCtx} {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsourceSupport : support (.app f arg info)) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta @@ -340,4 +340,4 @@ theorem tryProjAppReduceFinished_optional_wf_of_contexts (hempty := rfl) end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/NoDelta/ProjectionDefinition.lean b/Ix/Kernel/Verify/Whnf/NoDelta/ProjectionDefinition.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/NoDelta/ProjectionDefinition.lean rename to Ix/Kernel/Verify/Whnf/NoDelta/ProjectionDefinition.lean index 3b0c84de1..0c342d09b 100644 --- a/Ix/Tc/Verify/Whnf/NoDelta/ProjectionDefinition.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/ProjectionDefinition.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.NoDelta.StringPrimitive +import Ix.Kernel.Verify.Whnf.NoDelta.StringPrimitive /-! # Projection-definition no-delta field @@ -14,7 +14,7 @@ the run support; support for only the final expression is not enough to make the intern-table collision argument sound. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite request plan for a recognized projection-wrapper definition. @@ -48,7 +48,7 @@ structure ProjectionDefinitionReflection (semantics : CacheSemantics) (support : RunSupport) : Prop where success : ∀ {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {source result : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {s sf : TcState .anon}, + {sourceV : Ix.Theory.Named.VExpr} {s sf : TcState .anon}, Methods.WFAt .noAccel semantics trProj world support uvars methods → support source → TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → @@ -211,4 +211,4 @@ theorem tryReduceProjectionDefinition_optional_wf_of_contexts hrunProjection⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/NoDelta/Quotient.lean b/Ix/Kernel/Verify/Whnf/NoDelta/Quotient.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/NoDelta/Quotient.lean rename to Ix/Kernel/Verify/Whnf/NoDelta/Quotient.lean index 96eb1258d..9e0341399 100644 --- a/Ix/Tc/Verify/Whnf/NoDelta/Quotient.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/Quotient.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.NoDelta.ProjectionDefinition +import Ix.Kernel.Verify.Whnf.NoDelta.ProjectionDefinition /-! # Quotient no-delta field @@ -10,7 +10,7 @@ callback errors and every generated intern, from finite input and request coverage. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite generated-node plan for one selected quotient reduction. @@ -44,7 +44,7 @@ structure QuotientReductionReflection (semantics : CacheSemantics) (support : RunSupport) : Prop where success : ∀ {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {source result : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {s sf : TcState .anon}, + {sourceV : Ix.Theory.Named.VExpr} {s sf : TcState .anon}, Methods.WFAt .noAccel semantics trProj world support uvars methods → support source → TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → @@ -85,7 +85,7 @@ theorem tryQuotReduceSelected_inv_wf (inputs : NoDeltaInputSupport support) {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} - {source head : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source head : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {args : Array (KExpr .anon)} {prims : Primitives .anon} {fIdx majorIdx : Nat} {s : TcState .anon} (hsourceSupport : support source) @@ -164,7 +164,7 @@ theorem tryQuotReduce_inv_wf (inputs : NoDeltaInputSupport support) {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsourceSupport : support source) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta source @@ -253,4 +253,4 @@ theorem tryQuotReduce_optional_wf_of_contexts reflection.success hmethods hsourceSupport hsource hI hrunQuot⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/NoDelta/QuotientReflection.lean b/Ix/Kernel/Verify/Whnf/NoDelta/QuotientReflection.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/NoDelta/QuotientReflection.lean rename to Ix/Kernel/Verify/Whnf/NoDelta/QuotientReflection.lean index 38068dd08..549a76cbe 100644 --- a/Ix/Tc/Verify/Whnf/NoDelta/QuotientReflection.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/QuotientReflection.lean @@ -1,4 +1,6 @@ -import Ix.Tc.Verify.Whnf.NoDelta.Quotient +import Ix.Kernel.Verify.Whnf.NoDelta.Quotient + +open Ix.Theory (VLevel) /-! # Quotient reduction reflection @@ -7,27 +9,27 @@ This module turns the successful production `tryQuotReduce` path into the semantic `QuotientReductionReflection` consumed by the no-delta reducer. The only conditional input is a pair of Theory-level contraction laws. They mention no Ix state, addresses, hashes, support predicates, or executions and -are the narrow temporary interface intended to be replaced by Lean4Lean's +are the narrow temporary interface intended to be replaced by Ix.Theory.Named's constructive quotient result. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VExpr) +open Ix.Theory.Named (VExpr) -/-- Theory-only quotient contraction laws expected from Lean4Lean L4L-19B. +/-- Theory-only quotient contraction laws expected from Ix.Theory.Named Spec-19B. Both laws are deliberately phrased after the quotient major has been related to an exact `Quot.mk` application. The Ix adapter below owns the proof of that relation from the real recursive-WHNF callback and owns all concrete spine and suffix alignment. -/ -structure QuotientReductionLaws (env : Lean4Lean.VEnv) : Prop where +structure QuotientReductionLaws (env : Ix.Theory.Named.VEnv) : Prop where lift : ∀ {uvars : Nat} {Gamma : List VExpr} - {liftLevels mkLevels : List Lean4Lean.VLevel} + {liftLevels mkLevels : List Ix.Theory.VLevel} {alpha relation beta fn respects ctorAlpha ctorRelation representative major : VExpr}, env.WF → - env.defeqs Lean4Lean.quotDefEq → + env.defeqs Ix.Theory.Named.quotDefEq → VExpr.WF env uvars Gamma (.app (VExpr.appN (.const ``Quot.lift liftLevels) @@ -46,7 +48,7 @@ structure QuotientReductionLaws (env : Lean4Lean.VEnv) : Prop where major) (.app fn representative) ind : ∀ {uvars : Nat} {Gamma : List VExpr} - {indLevels mkLevels : List Lean4Lean.VLevel} + {indLevels mkLevels : List Ix.Theory.VLevel} {alpha relation motive fn ctorAlpha ctorRelation representative major : VExpr}, env.WF → @@ -141,7 +143,7 @@ namespace TrAppSpine /-- Invert an exact three-argument translated spine. -/ theorem three - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head a b c : KExpr .anon} {resultV : VExpr} (h : TrAppSpine env uvars nameOf trProj Delta head [a, b, c] @@ -169,7 +171,7 @@ theorem three /-- Invert an exact four-argument translated spine. -/ theorem four - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head a b c d : KExpr .anon} {resultV : VExpr} (h : TrAppSpine env uvars nameOf trProj Delta head [a, b, c, d] @@ -201,7 +203,7 @@ theorem four /-- Invert an exact five-argument translated spine. -/ theorem five - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head a b c d e : KExpr .anon} {resultV : VExpr} (h : TrAppSpine env uvars nameOf trProj Delta head [a, b, c, d, e] @@ -242,7 +244,7 @@ namespace TrKExprS /-- A translated constant whose address has an exact trusted-name binding has that name in its Theory syntax. -/ theorem const_name - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {id : KId .anon} {us : Array (KUniv .anon)} {info : ExprInfo .anon} {value : VExpr} {name : Lean.Name} @@ -265,7 +267,7 @@ theorem quotientLiftMeaning (theory : WhnfTheory trProj world uvars) (laws : QuotientReductionLaws world.venv) (htable : NoDeltaPrimitiveTableAgrees world prims) - (hregistered : world.venv.defeqs Lean4Lean.quotDefEq) + (hregistered : world.venv.defeqs Ix.Theory.Named.quotDefEq) (hDelta : KVLCtx.WF world.venv uvars Delta) {source : KExpr .anon} {sourceV : VExpr} {id : KId .anon} {us : Array (KUniv .anon)} @@ -305,7 +307,7 @@ theorem quotientLiftMeaning exact htable.quotLift.2 have hliftHead : liftHeadV = .const ``Quot.lift (us.toList.map KUniv.toVLevel) := - Ix.Tc.RecM.TrKExprS.const_name hliftHeadTr hliftName + Ix.Kernel.RecM.TrKExprS.const_name hliftHeadTr hliftName rw [hliftHead] at hpriorShape subst priorV @@ -337,7 +339,7 @@ theorem quotientLiftMeaning exact htable.quotCtor.2 have hmkHead : mkHeadV = .const ``Quot.mk (mkUs.toList.map KUniv.toVLevel) := - Ix.Tc.RecM.TrKExprS.const_name hmkHeadTr hmkName + Ix.Kernel.RecM.TrKExprS.const_name hmkHeadTr hmkName rw [hmkHead] at hmkShape subst majorWhnfV @@ -419,7 +421,7 @@ theorem quotientIndMeaning exact htable.quotInd.2 have hindHead : indHeadV = .const ``Quot.ind (us.toList.map KUniv.toVLevel) := - Ix.Tc.RecM.TrKExprS.const_name hindHeadTr hindName + Ix.Kernel.RecM.TrKExprS.const_name hindHeadTr hindName rw [hindHead] at hpriorShape subst priorV @@ -451,7 +453,7 @@ theorem quotientIndMeaning exact htable.quotCtor.2 have hmkHead : mkHeadV = .const ``Quot.mk (mkUs.toList.map KUniv.toVLevel) := - Ix.Tc.RecM.TrKExprS.const_name hmkHeadTr hmkName + Ix.Kernel.RecM.TrKExprS.const_name hmkHeadTr hmkName rw [hmkHead] at hmkShape subst majorWhnfV @@ -837,4 +839,4 @@ theorem of_laws cases hrun end QuotientReductionReflection -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/NoDelta/Reducer.lean b/Ix/Kernel/Verify/Whnf/NoDelta/Reducer.lean similarity index 94% rename from Ix/Tc/Verify/Whnf/NoDelta/Reducer.lean rename to Ix/Kernel/Verify/Whnf/NoDelta/Reducer.lean index 5e09646ac..316335442 100644 --- a/Ix/Tc/Verify/Whnf/NoDelta/Reducer.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/Reducer.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.NoDelta.BaseReductions +import Ix.Kernel.Verify.Whnf.NoDelta.BaseReductions /-! # Public no-delta reducer @@ -10,7 +10,7 @@ and collision-robust cache writes. This slice supplies those two concrete components to that shell. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Complete fixed-context input for the public no-delta reducer. -/ @@ -42,7 +42,7 @@ theorem wf trProj world support Delta flags) (mode : NatSuccMode) {source : KExpr .anon} (hsourceSupport : support source) - {sourceV : Lean4Lean.VExpr} {s : TcState .anon} + {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta source sourceV) : RecM.WF .noAccel (whnfCacheSemantics keys trProj fallback) trProj world @@ -65,4 +65,4 @@ theorem wf end NoDeltaDriverContext end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/NoDelta/StringPrimitive.lean b/Ix/Kernel/Verify/Whnf/NoDelta/StringPrimitive.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/NoDelta/StringPrimitive.lean rename to Ix/Kernel/Verify/Whnf/NoDelta/StringPrimitive.lean index 99af60b5d..87d9413d8 100644 --- a/Ix/Tc/Verify/Whnf/NoDelta/StringPrimitive.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/StringPrimitive.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.NoDelta.ProjectionApplication +import Ix.Kernel.Verify.Whnf.NoDelta.ProjectionApplication /-! # String primitive no-delta field @@ -13,7 +13,7 @@ exact generated nodes. Theory computation remains a deliberately narrow reflection boundary indexed by an observed successful production run. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Finite generated-node support for the String reducer. @@ -75,7 +75,7 @@ structure StringReductionReflection (semantics : CacheSemantics) (support : RunSupport) : Prop where success : ∀ {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {source result : KExpr .anon} - {sourceV : Lean4Lean.VExpr} {s sf : TcState .anon}, + {sourceV : Ix.Theory.Named.VExpr} {s sf : TcState .anon}, Methods.WFAt .noAccel semantics trProj world support uvars methods → support source → TrKExprS world.venv uvars world.nameOf trProj Delta source sourceV → @@ -281,4 +281,4 @@ theorem tryReduceString_optional_wf_of_reflection reflection.success hmethods hsourceSupport hsource hI hrun⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Projection/NoAccelTail.lean b/Ix/Kernel/Verify/Whnf/Projection/NoAccelTail.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Projection/NoAccelTail.lean rename to Ix/Kernel/Verify/Whnf/Projection/NoAccelTail.lean index 31ecac194..af1030ea3 100644 --- a/Ix/Tc/Verify/Whnf/Projection/NoAccelTail.lean +++ b/Ix/Kernel/Verify/Whnf/Projection/NoAccelTail.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.VerifiedStep +import Ix.Kernel.Verify.Whnf.Structural.VerifiedStep /-! # Concrete no-acceleration projection tail @@ -13,7 +13,7 @@ Only String-literal construction/normalization and the installed lazy-ingress hook remain as explicit premises when the tail is composed below. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM namespace WhnfCoreInputSupport @@ -267,4 +267,4 @@ theorem noAccel end ProjectionHelper end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Projection/StringCallback.lean b/Ix/Kernel/Verify/Whnf/Projection/StringCallback.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Projection/StringCallback.lean rename to Ix/Kernel/Verify/Whnf/Projection/StringCallback.lean index eab362128..8d3b1ffbc 100644 --- a/Ix/Tc/Verify/Whnf/Projection/StringCallback.lean +++ b/Ix/Kernel/Verify/Whnf/Projection/StringCallback.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Projection.NoAccelTail +import Ix.Kernel.Verify.Whnf.Projection.NoAccelTail /-! # Projection String callback closure @@ -10,7 +10,7 @@ interned constructor expansion itself: finite support and structural translation of the exact generated term. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM attribute [local irreducible] whnfRec strLitToConstructor @@ -82,4 +82,4 @@ theorem noAccelOfExpansion end ProjectionHelper end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Projection/StringExpansion.lean b/Ix/Kernel/Verify/Whnf/Projection/StringExpansion.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Projection/StringExpansion.lean rename to Ix/Kernel/Verify/Whnf/Projection/StringExpansion.lean index 1cc3a1b50..ad7a264f4 100644 --- a/Ix/Tc/Verify/Whnf/Projection/StringExpansion.lean +++ b/Ix/Kernel/Verify/Whnf/Projection/StringExpansion.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Projection.StringCallback +import Ix.Kernel.Verify.Whnf.Projection.StringCallback /-! # Finite String-constructor expansion plan @@ -10,7 +10,7 @@ collisions are excluded on the run domain, and the final generated term has a structural Theory translation. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM def stringCharConst (p : Primitives .anon) : KExpr .anon := @@ -376,4 +376,4 @@ theorem noAccelOfStringPlans end ProjectionHelper end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/README.md b/Ix/Kernel/Verify/Whnf/README.md similarity index 97% rename from Ix/Tc/Verify/Whnf/README.md rename to Ix/Kernel/Verify/Whnf/README.md index 5a8806528..f204baea5 100644 --- a/Ix/Tc/Verify/Whnf/README.md +++ b/Ix/Kernel/Verify/Whnf/README.md @@ -30,4 +30,4 @@ precise proof-dependency order needed by Lean. the boundary with the later `infer`/`isDefEq` closure work. The foundational semantic definitions remain in the sibling module -`Ix.Tc.Verify.Whnf` (`../Whnf.lean`). +`Ix.Kernel.Verify.Whnf` (`../Whnf.lean`). diff --git a/Ix/Tc/Verify/Whnf/Runtime/LazyIngress.lean b/Ix/Kernel/Verify/Whnf/Runtime/LazyIngress.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/Runtime/LazyIngress.lean rename to Ix/Kernel/Verify/Whnf/Runtime/LazyIngress.lean index 568254423..99045d5ce 100644 --- a/Ix/Tc/Verify/Whnf/Runtime/LazyIngress.lean +++ b/Ix/Kernel/Verify/Whnf/Runtime/LazyIngress.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Whnf.Projection.StringExpansion -import Ix.Tc.Ingress +import Ix.Kernel.Verify.Whnf.Projection.StringExpansion +import Ix.Kernel.Ingress /-! # Concrete anonymous lazy-ingress refinement @@ -17,7 +17,7 @@ frame. A separate installed-hook premise identifies the otherwise arbitrary function stored in `TcState`. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact environment facts needed after one lazy-ingress callback. @@ -324,4 +324,4 @@ theorem noAccelOfAnonIngress end RecM.ProjectionHelper -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/RuntimeContracts.lean b/Ix/Kernel/Verify/Whnf/RuntimeContracts.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/RuntimeContracts.lean rename to Ix/Kernel/Verify/Whnf/RuntimeContracts.lean index 04bdf6ff3..47ae3bf13 100644 --- a/Ix/Tc/Verify/Whnf/RuntimeContracts.lean +++ b/Ix/Kernel/Verify/Whnf/RuntimeContracts.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf +import Ix.Kernel.Verify.Whnf /-! # Closing the remaining WHNF runtime contracts @@ -8,7 +8,7 @@ for eagerly ingressed states and exposes the strictly smaller lazy-ingress obligation needed by the same proof in driver-backed states. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -432,4 +432,4 @@ end TransientNatWork end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/CallbackPrefix.lean b/Ix/Kernel/Verify/Whnf/StructEta/CallbackPrefix.lean similarity index 96% rename from Ix/Tc/Verify/Whnf/StructEta/CallbackPrefix.lean rename to Ix/Kernel/Verify/Whnf/StructEta/CallbackPrefix.lean index d639f48a7..884b7be7f 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/CallbackPrefix.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/CallbackPrefix.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.StructEta.Rebuild +import Ix.Kernel.Verify.Whnf.StructEta.Rebuild /-! # Struct-eta callback-prefix preservation @@ -11,7 +11,7 @@ full fixed-world invariant on success and error; they do not claim that a caught callback is state-pure. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -148,7 +148,7 @@ theorem inferOnlyRec_wf {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} (hmethods : Methods.WFAt layer semantics trProj world support uvars methods) - {s : TcState .anon} {e : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {s : TcState .anon} {e : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsource : support e) (htr : TrKExprS world.venv uvars world.nameOf trProj Delta e sourceV) : TcM.WF (WhnfStateInv layer semantics trProj world support uvars Delta) s @@ -168,7 +168,7 @@ theorem tryOptionalInferOnlyRec_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} - {s : TcState .anon} {e : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {s : TcState .anon} {e : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsource : support e) (htr : TrKExprS world.venv uvars world.nameOf trProj Delta e sourceV) : RecM.WF layer semantics trProj world support uvars Delta s @@ -196,7 +196,7 @@ theorem tryOptionalWhnfRec_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} - {s : TcState .anon} {e : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {s : TcState .anon} {e : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} (hsource : support e) (htr : TrKExprS world.venv uvars world.nameOf trProj Delta e sourceV) : RecM.WF layer semantics trProj world support uvars Delta s @@ -220,4 +220,4 @@ theorem tryOptionalWhnfRec_wf exact herror end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/Classifier.lean b/Ix/Kernel/Verify/Whnf/StructEta/Classifier.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/StructEta/Classifier.lean rename to Ix/Kernel/Verify/Whnf/StructEta/Classifier.lean index 250da9a2e..bc4ef4452 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/Classifier.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/Classifier.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.StructEta.RecursionClassifier +import Ix.Kernel.Verify.Whnf.StructEta.RecursionClassifier /-! # Struct-eta classifier state closure @@ -14,7 +14,7 @@ one constructor and no indices is not, by itself, a Theory proof of the struct-eta equation selected later in the reducer. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Exact typed/effect input for the recursor declaration instance scanned by @@ -174,7 +174,7 @@ theorem tryStructEtaAfterInductive_wf (hfault : TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) (hwrites : IsRecCacheWriteOracle semantics world support methods indId) - {majorV : Lean4Lean.VExpr} + {majorV : Ix.Theory.Named.VExpr} (hmajorSupport : support spine[recr.majorIdx]!) (hmajorTr : TrKExprS world.venv uvars world.nameOf trProj Delta spine[recr.majorIdx]! majorV) @@ -345,7 +345,7 @@ theorem tryStructEtaIota_wf (hreferences : TrustedReferences world support) (hwrites : ∀ id, world.trusted id → IsRecCacheWriteOracle semantics world support methods id) - {majorV : Lean4Lean.VExpr} + {majorV : Ix.Theory.Named.VExpr} (hmajorSupport : support spine[recr.majorIdx]!) (hmajorTr : TrKExprS world.venv uvars world.nameOf trProj Delta spine[recr.majorIdx]! majorV) @@ -363,4 +363,4 @@ theorem tryStructEtaIota_wf (hwrites indId htrusted) hmajorSupport hmajorTr hfinish end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/ExactMajorTelescope.lean b/Ix/Kernel/Verify/Whnf/StructEta/ExactMajorTelescope.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/StructEta/ExactMajorTelescope.lean rename to Ix/Kernel/Verify/Whnf/StructEta/ExactMajorTelescope.lean index d05486bb5..f23a030ac 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/ExactMajorTelescope.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/ExactMajorTelescope.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.StructEta.ScopedTelescope +import Ix.Kernel.Verify.Whnf.StructEta.ScopedTelescope /-! # Exact major-premise telescope restoration @@ -21,7 +21,7 @@ This module proves that fact from: No semantic state model is widened to admit the temporary telescope. -/ -namespace Ix.Tc +namespace Ix.Kernel /-- Exact state stack generated exclusively by successful `pushLocal` calls. Unlike `ScratchLamExtension`, this relation retains the operational @@ -249,4 +249,4 @@ theorem getMajorInductiveId_direct_exact exact scratch_tryFinally_ok bodyRun cleanup end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/Rebuild.lean b/Ix/Kernel/Verify/Whnf/StructEta/Rebuild.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/StructEta/Rebuild.lean rename to Ix/Kernel/Verify/Whnf/StructEta/Rebuild.lean index dce3929fb..2af833370 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/Rebuild.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/Rebuild.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.StructEtaControl +import Ix.Kernel.Verify.Whnf.Iota.StructEtaControl /-! # Finite struct-eta rebuild closure @@ -15,7 +15,7 @@ that the selected recursor rule is a registered Theory equation or that raw projections have the required interpretation. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Finite request certificate for the projection/application pairs generated @@ -213,4 +213,4 @@ theorem acceptance_of_requests end StructEtaIotaSuccessTrace end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/RebuildRequests.lean b/Ix/Kernel/Verify/Whnf/StructEta/RebuildRequests.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/StructEta/RebuildRequests.lean rename to Ix/Kernel/Verify/Whnf/StructEta/RebuildRequests.lean index 873c87405..c373b5fb9 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/RebuildRequests.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/RebuildRequests.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Iota.ApplicationRequests +import Ix.Kernel.Verify.Whnf.Iota.ApplicationRequests /-! # Finite request closure for the struct-eta rebuild tail @@ -12,7 +12,7 @@ recursor and spine. The inference probes are derived from `Methods.WF`; only the helper-scan and recursion-cache authorities remain. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- The exact finite requests for one successful struct-eta H3 tail. -/ @@ -85,7 +85,7 @@ theorem of_components (hreferences : TrustedReferences world support) (hwrites : ∀ id, world.trusted id → IsRecCacheWriteOracle semantics world support methods id) - {majorV : Lean4Lean.VExpr} + {majorV : Ix.Theory.Named.VExpr} (hmajorSupport : support spine[recr.majorIdx]!) (hmajorTr : TrKExprS world.venv uvars world.nameOf trProj Delta spine[recr.majorIdx]! majorV) : @@ -125,7 +125,7 @@ theorem tryIotaAfterMajorWhnf_state_wf_of_contexts IsRecCacheWriteOracle semantics world support methods id) {flags : WhnfFlags} {recId : KId .anon} {recr : IotaInfo .anon} {recUs : Array (KUniv .anon)} {spine : Array (KExpr .anon)} - {majorV : Lean4Lean.VExpr} + {majorV : Ix.Theory.Named.VExpr} (hmajorSupport : support spine[recr.majorIdx]!) (hmajorTr : TrKExprS world.venv uvars world.nameOf trProj Delta spine[recr.majorIdx]! majorV) @@ -142,4 +142,4 @@ theorem tryIotaAfterMajorWhnf_state_wf_of_contexts hctorInputs hrecInputs hfault hreferences hwrites hmajorSupport hmajorTr) end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/RebuildTail.lean b/Ix/Kernel/Verify/Whnf/StructEta/RebuildTail.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/StructEta/RebuildTail.lean rename to Ix/Kernel/Verify/Whnf/StructEta/RebuildTail.lean index 6eb618e19..ff2231721 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/RebuildTail.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/RebuildTail.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.StructEta.Classifier +import Ix.Kernel.Verify.Whnf.StructEta.Classifier /-! # Struct-eta universe and rebuild tail @@ -10,7 +10,7 @@ invariant on success and partial-state error, and a successful RHS is rebuilt only through request-certified projection/application interning. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -148,4 +148,4 @@ theorem finishStructEtaAfterSort_wf_of_requests exact TcM.WF.pure fun _ => trivial end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/RecursionClassifier.lean b/Ix/Kernel/Verify/Whnf/StructEta/RecursionClassifier.lean similarity index 99% rename from Ix/Tc/Verify/Whnf/StructEta/RecursionClassifier.lean rename to Ix/Kernel/Verify/Whnf/StructEta/RecursionClassifier.lean index ac04231ff..f667d6cac 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/RecursionClassifier.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/RecursionClassifier.lean @@ -1,5 +1,5 @@ import Init.Data.Range.Lemmas -import Ix.Tc.Verify.Whnf.StructEta.ScopedClassifier +import Ix.Kernel.Verify.Whnf.StructEta.ScopedClassifier /-! # Recursion-classifier and major-inductive helper effects @@ -15,7 +15,7 @@ re-entrant eta. Physical insertion alone is therefore not evidence that either Boolean is semantically valid. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -454,7 +454,7 @@ theorem getMajorInductiveId_wf TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) (hreferences : TrustedReferences world support) - {Delta : KVLCtx} {recTy : KExpr .anon} {recTyV : Lean4Lean.VExpr} + {Delta : KVLCtx} {recTy : KExpr .anon} {recTyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (skip : UInt64) (hrecSupport : support recTy) (hrecTr : @@ -516,7 +516,7 @@ theorem getMajorInductiveId_trusted_wf TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) (hreferences : TrustedReferences world support) - {Delta : KVLCtx} {recTy : KExpr .anon} {recTyV : Lean4Lean.VExpr} + {Delta : KVLCtx} {recTy : KExpr .anon} {recTyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (skip : UInt64) (hrecSupport : support recTy) (hrecTr : @@ -803,4 +803,4 @@ theorem computedIsRec_wf end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/ScopedClassifier.lean b/Ix/Kernel/Verify/Whnf/StructEta/ScopedClassifier.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/StructEta/ScopedClassifier.lean rename to Ix/Kernel/Verify/Whnf/StructEta/ScopedClassifier.lean index 1e0a0fc13..b69bee7de 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/ScopedClassifier.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/ScopedClassifier.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.StructEta.ScopedTelescope +import Ix.Kernel.Verify.Whnf.StructEta.ScopedTelescope /-! # Scoped recursion-classifier steps @@ -9,7 +9,7 @@ results and partial-error states before the complete classifier loop is assembled. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM def ScratchScopedForInStep @@ -50,7 +50,7 @@ theorem scratch_computeIsRecParamStep_scoped Methods.WFAt layer semantics trProj world support uvars methods) (hinputs : ScratchTelescopeInputSupport support) {base : KVLCtx} {n : Nat} {current : KVLCtx} - {ty : KExpr .anon} {tyV : Lean4Lean.VExpr} {s : TcState .anon} + {ty : KExpr .anon} {tyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hExtension : ScratchLamExtension base n current) (hsupport : support ty) (htr : TrKExprS world.venv uvars world.nameOf trProj current ty tyV) @@ -122,7 +122,7 @@ theorem scratch_computeIsRecFieldStep_scoped (hinputs : ScratchTelescopeInputSupport support) {base : KVLCtx} {n : Nat} {current : KVLCtx} {blockAddrs : Array Address} - {ty : KExpr .anon} {tyV : Lean4Lean.VExpr} {s : TcState .anon} + {ty : KExpr .anon} {tyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hExtension : ScratchLamExtension base n current) (hsupport : support ty) (htr : TrKExprS world.venv uvars world.nameOf trProj current ty tyV) @@ -365,7 +365,7 @@ theorem scratch_computeIsRecCtorBody_scoped Methods.WFAt layer semantics trProj world support uvars methods) (hinputs : ScratchTelescopeInputSupport support) {base : KVLCtx} {ctorTy : KExpr .anon} - {ctorTyV : Lean4Lean.VExpr} {s : TcState .anon} + {ctorTyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (nParams : Nat) (blockAddrs : Array Address) (hctorSupport : support ctorTy) (hctorTr : @@ -443,7 +443,7 @@ theorem scratch_computeIsRecCtor_wf Methods.WFAt layer semantics trProj world support uvars methods) (hinputs : ScratchTelescopeInputSupport support) {Delta : KVLCtx} {ctorTy : KExpr .anon} - {ctorTyV : Lean4Lean.VExpr} {s : TcState .anon} + {ctorTyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (nParams : Nat) (blockAddrs : Array Address) (hctorSupport : support ctorTy) (hctorTr : @@ -488,4 +488,4 @@ theorem scratch_computeIsRecCtor_wf exact ⟨hFinal, trivial⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/StructEta/ScopedTelescope.lean b/Ix/Kernel/Verify/Whnf/StructEta/ScopedTelescope.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/StructEta/ScopedTelescope.lean rename to Ix/Kernel/Verify/Whnf/StructEta/ScopedTelescope.lean index 9931a5689..6d243c270 100644 --- a/Ix/Tc/Verify/Whnf/StructEta/ScopedTelescope.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/ScopedTelescope.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.StructEta.CallbackPrefix +import Ix.Kernel.Verify.Whnf.StructEta.CallbackPrefix /-! # Scoped telescope state @@ -9,7 +9,7 @@ ambient WHNF state invariant while tracking the temporary lambda extension of the caller's context. -/ -namespace Ix.Tc +namespace Ix.Kernel theorem scratch_pushLocal_run {ty : KExpr .anon} {s s' : TcState .anon} @@ -35,7 +35,7 @@ theorem scratch_pushLocal_inv {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s s' : TcState .anon} - {ty : KExpr .anon} {tyV : Lean4Lean.VExpr} + {ty : KExpr .anon} {tyV : Ix.Theory.Named.VExpr} (hI : WhnfStateInv layer semantics trProj world support uvars Delta s) (htr : TrKExprS world.venv uvars world.nameOf trProj Delta ty tyV) (htype : world.venv.IsType uvars Delta.toCtx tyV) @@ -60,9 +60,9 @@ theorem scratch_pushLocal_inv simpa only [WhnfLayer.StateOK, hprims] using hI.2.2 theorem scratch_lam_back - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} - {s : TcState .anon} {Delta : KVLCtx} {tyV : Lean4Lean.VExpr} + {s : TcState .anon} {Delta : KVLCtx} {tyV : Ix.Theory.Named.VExpr} (h : CtxRecon env uvars nameOf trProj s ((none, .vlam tyV) :: Delta)) : s.letVals.back? = some none := by @@ -75,9 +75,9 @@ theorem scratch_lam_back Array.getLast?_toList] using hhead theorem scratch_popLocal_run - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address → Option Lean.Name} {trProj : RawProjRel} - {s s' : TcState .anon} {Delta : KVLCtx} {tyV : Lean4Lean.VExpr} + {s s' : TcState .anon} {Delta : KVLCtx} {tyV : Ix.Theory.Named.VExpr} (hctxRecon : CtxRecon env uvars nameOf trProj s ((none, .vlam tyV) :: Delta)) (hrun : TcM.popLocal s = .ok () s') : @@ -104,7 +104,7 @@ theorem scratch_popLocal_inv {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s s' : TcState .anon} - {tyV : Lean4Lean.VExpr} + {tyV : Ix.Theory.Named.VExpr} (hI : WhnfStateInv layer semantics trProj world support uvars ((none, .vlam tyV) :: Delta) s) (hrun : TcM.popLocal s = .ok () s') : @@ -128,7 +128,7 @@ theorem scratch_popLocal_inv inductive ScratchLamExtension (base : KVLCtx) : Nat → KVLCtx → Prop | zero : ScratchLamExtension base 0 base - | succ {n : Nat} {current : KVLCtx} {tyV : Lean4Lean.VExpr} : + | succ {n : Nat} {current : KVLCtx} {tyV : Ix.Theory.Named.VExpr} : ScratchLamExtension base n current → ScratchLamExtension base (n + 1) ((none, .vlam tyV) :: current) @@ -581,7 +581,7 @@ theorem scratch_majorInductiveBody_scoped TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) (hreferences : ScratchTrustedReferences world support) - {base : KVLCtx} {recTy : KExpr .anon} {recTyV : Lean4Lean.VExpr} + {base : KVLCtx} {recTy : KExpr .anon} {recTyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (skip : UInt64) (hrecSupport : support recTy) (hrecTr : TrKExprS world.venv uvars world.nameOf trProj base recTy recTyV) @@ -669,7 +669,7 @@ theorem scratch_getMajorInductiveId_wf TcM.LazyFaultPreserves (WhnfStateInv layer semantics trProj world support uvars Delta)) (hreferences : ScratchTrustedReferences world support) - {Delta : KVLCtx} {recTy : KExpr .anon} {recTyV : Lean4Lean.VExpr} + {Delta : KVLCtx} {recTy : KExpr .anon} {recTyV : Ix.Theory.Named.VExpr} {s : TcState .anon} (skip : UInt64) (hrecSupport : support recTy) (hrecTr : @@ -710,4 +710,4 @@ theorem scratch_getMajorInductiveId_wf exact ⟨hFinal, trivial⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/ApplicationCongruence.lean b/Ix/Kernel/Verify/Whnf/Structural/ApplicationCongruence.lean similarity index 92% rename from Ix/Tc/Verify/Whnf/Structural/ApplicationCongruence.lean rename to Ix/Kernel/Verify/Whnf/Structural/ApplicationCongruence.lean index 1778c5981..40fa133e3 100644 --- a/Ix/Tc/Verify/Whnf/Structural/ApplicationCongruence.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/ApplicationCongruence.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.ProjectionStep +import Ix.Kernel.Verify.Whnf.Structural.ProjectionStep /-! # Changed-head application congruence @@ -14,7 +14,7 @@ suffix. A `FinishAppRequests` certificate then identifies the semantic left fold with the expression actually returned by `finishAppResult`. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM namespace TrAppSpine @@ -23,10 +23,10 @@ namespace TrAppSpine suffix. Unlike `headTr`, this keeps the chosen head translation connected to all argument typing derivations. -/ theorem toSuffix - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head : KExpr .anon} - {args : List (KExpr .anon)} {resultV : Lean4Lean.VExpr} + {args : List (KExpr .anon)} {resultV : Ix.Theory.Named.VExpr} (h : TrAppSpine env uvars nameOf trProj Delta head args resultV) : exists headV, TrKExprS env uvars nameOf trProj Delta head headV /\ @@ -46,7 +46,7 @@ theorem applicationHeadCallbackWithSuffix_wf {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {f arg head : KExpr .anon} {info : ExprInfo .anon} - {args : Array (KExpr .anon)} {sourceV : Lean4Lean.VExpr} + {args : Array (KExpr .anon)} {sourceV : Ix.Theory.Named.VExpr} {flags : WhnfFlags} (hinputs : WhnfCoreInputSupport support) (hsupport : support (.app f arg info)) @@ -77,7 +77,7 @@ result. -/ theorem appHeadRebuild {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {source changed rebuilt : KExpr .anon} - {args : Array (KExpr .anon)} {sourceV headV : Lean4Lean.VExpr} + {args : Array (KExpr .anon)} {sourceV headV : Ix.Theory.Named.VExpr} {requests : List WalkerRequest} (hDelta : KVLCtx.WF world.venv uvars Delta) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta source @@ -99,4 +99,4 @@ theorem appHeadRebuild end WhnfMeaning end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/ApplicationRebuild.lean b/Ix/Kernel/Verify/Whnf/Structural/ApplicationRebuild.lean similarity index 94% rename from Ix/Tc/Verify/Whnf/Structural/ApplicationRebuild.lean rename to Ix/Kernel/Verify/Whnf/Structural/ApplicationRebuild.lean index 92a536dde..bcfb2c8a5 100644 --- a/Ix/Tc/Verify/Whnf/Structural/ApplicationRebuild.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/ApplicationRebuild.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.ApplicationCongruence +import Ix.Kernel.Verify.Whnf.Structural.ApplicationCongruence /-! # Changed-head rebuild execution @@ -10,7 +10,7 @@ head callback. The guard keeps the obligation finite while covering the dynamic callback result rather than one hand-picked expression. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Finite request census for rebuilding the complete argument suffix after @@ -39,7 +39,7 @@ theorem changedHeadFinish_acceptance {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} {Delta : KVLCtx} {methods : Methods .anon} {s : TcState .anon} {f arg head changed : KExpr .anon} {info : ExprInfo .anon} - {args : Array (KExpr .anon)} {sourceV headV : Lean4Lean.VExpr} + {args : Array (KExpr .anon)} {sourceV headV : Ix.Theory.Named.VExpr} (hsourceSupport : support (.app f arg info)) (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta (.app f arg info) sourceV) @@ -68,4 +68,4 @@ theorem changedHeadFinish_acceptance hrebuiltSupport, hmeaning⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/ApplicationStep.lean b/Ix/Kernel/Verify/Whnf/Structural/ApplicationStep.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Structural/ApplicationStep.lean rename to Ix/Kernel/Verify/Whnf/Structural/ApplicationStep.lean index 2e0af9769..5688fd2c8 100644 --- a/Ix/Tc/Verify/Whnf/Structural/ApplicationStep.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/ApplicationStep.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.BetaBoundary +import Ix.Kernel.Verify.Whnf.Structural.BetaBoundary /-! # Exhaustive application-step closure @@ -14,7 +14,7 @@ It uses the run's collision-freedom certificate over the supported callback result and original head before rewriting the callback equation. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Every outcome of the production application branch satisfies the local @@ -118,4 +118,4 @@ theorem whnfCoreWithFlagsStep_app_wf | str => exact hnonLambda .str hI end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/ApplicationTails.lean b/Ix/Kernel/Verify/Whnf/Structural/ApplicationTails.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Structural/ApplicationTails.lean rename to Ix/Kernel/Verify/Whnf/Structural/ApplicationTails.lean index 669994afe..4127fe455 100644 --- a/Ix/Tc/Verify/Whnf/Structural/ApplicationTails.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/ApplicationTails.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.ApplicationRebuild +import Ix.Kernel.Verify.Whnf.Structural.ApplicationRebuild /-! # Non-beta application tails @@ -11,7 +11,7 @@ invokes iota on that rebuilt source. In both cases the ordinary error states. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Generic unchanged-head/iota-hit equation. The older specialized theorem @@ -62,7 +62,7 @@ theorem whnfCoreWithFlagsStep_appUnchanged_wf (hmethods : Methods.WFAt layer semantics trProj world support uvars methods) (hsourceSupport : support (.app f arg info)) - {sourceV : Lean4Lean.VExpr} + {sourceV : Ix.Theory.Named.VExpr} (hsource : TrKExprS world.venv uvars world.nameOf trProj Delta (.app f arg info) sourceV) (hspine : (.app f arg info : KExpr .anon).collectSpine = (head, args)) @@ -112,7 +112,7 @@ theorem whnfCoreWithFlagsStep_appChanged_wf {Delta : KVLCtx} {methods : Methods .anon} {s s1 : TcState .anon} {f arg head changed : KExpr .anon} {info : ExprInfo .anon} {args : Array (KExpr .anon)} - {sourceV headV : Lean4Lean.VExpr} {flags : WhnfFlags} + {sourceV headV : Ix.Theory.Named.VExpr} {flags : WhnfFlags} (theory : WhnfTheory trProj world uvars) (hiota : OptionalReduction.WF layer semantics trProj world support (fun source => tryIotaWithFlags source flags)) @@ -165,4 +165,4 @@ theorem whnfCoreWithFlagsStep_appChanged_wf exact ⟨hiotaPost.1, hiotaPost.2.1, hmeaning⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/BasicStep.lean b/Ix/Kernel/Verify/Whnf/Structural/BasicStep.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Structural/BasicStep.lean rename to Ix/Kernel/Verify/Whnf/Structural/BasicStep.lean index 7243dc066..f9d33dd5c 100644 --- a/Ix/Tc/Verify/Whnf/Structural/BasicStep.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/BasicStep.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.CacheShell +import Ix.Kernel.Verify.Whnf.Structural.CacheShell /-! # Basic structural-step closure @@ -14,7 +14,7 @@ stack, and within the current weakening bound. Naming this state obligation prevents a translated-but-stale local value from being accepted silently. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Runtime safety needed by production's unchanged let-fvar return. This @@ -161,4 +161,4 @@ theorem whnfCoreWithFlagsStep_basic_wf | letE => exact whnfCoreWithFlagsStep_letE_wf hrun hcensus theory end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/BetaBoundary.lean b/Ix/Kernel/Verify/Whnf/Structural/BetaBoundary.lean similarity index 96% rename from Ix/Tc/Verify/Whnf/Structural/BetaBoundary.lean rename to Ix/Kernel/Verify/Whnf/Structural/BetaBoundary.lean index 39c32284a..5c86dcf30 100644 --- a/Ix/Tc/Verify/Whnf/Structural/BetaBoundary.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/BetaBoundary.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.ApplicationTails +import Ix.Kernel.Verify.Whnf.Structural.ApplicationTails /-! # General beta branch boundary and execution @@ -15,7 +15,7 @@ the substitution bounds to the final certified rebuild. No state effect, support fact, or production execution is hidden in that interface. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Finite request census for every dynamic multi-beta branch reachable from @@ -50,7 +50,7 @@ def BetaManyMeaningOracle (trProj : RawProjRel) (world : VerifyWorld) : Prop := {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body body0 : KExpr .anon} {lamInfo : ExprInfo .anon} {consumed : Array (KExpr .anon)} {result : KExpr .anon} - {sourceV headV : Lean4Lean.VExpr}, + {sourceV headV : Ix.Theory.Named.VExpr}, KVLCtx.WF world.venv uvars Delta -> TrKExprS world.venv uvars world.nameOf trProj Delta (.app f arg info) sourceV -> @@ -82,7 +82,7 @@ theorem whnfCoreWithFlagsStep_appBeta_wf {info : ExprInfo .anon} {args : Array (KExpr .anon)} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {ty body body0 : KExpr .anon} {lamInfo : ExprInfo .anon} - {consumed : Array (KExpr .anon)} {sourceV headV : Lean4Lean.VExpr} + {consumed : Array (KExpr .anon)} {sourceV headV : Ix.Theory.Named.VExpr} {flags : WhnfFlags} (theory : WhnfTheory trProj world uvars) (hmeaning : BetaManyMeaningOracle trProj world) @@ -125,4 +125,4 @@ theorem whnfCoreWithFlagsStep_appBeta_wf exact ⟨hI3, hresultSupport, hresultMeaning⟩ end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/CacheShell.lean b/Ix/Kernel/Verify/Whnf/Structural/CacheShell.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Structural/CacheShell.lean rename to Ix/Kernel/Verify/Whnf/Structural/CacheShell.lean index 7a43392c4..776a977ca 100644 --- a/Ix/Tc/Verify/Whnf/Structural/CacheShell.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/CacheShell.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Whnf.StructEta.RebuildTail -import Ix.Tc.Verify.Suffix +import Ix.Kernel.Verify.Whnf.StructEta.RebuildTail +import Ix.Kernel.Verify.Suffix /-! # Structural-core cache shell @@ -17,7 +17,7 @@ constructed, this file turns it into the complete public Nat bypass, and the legacy-variable prefix. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM @@ -125,7 +125,7 @@ theorem whnfCoreWithFlagsNonLeaf_wf stepError) (hwrites : WhnfCoreCacheWriteOracle keys trProj fallback world support) (hsupport : support source) - {sourceV : Lean4Lean.VExpr} {s : TcState .anon} + {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta source sourceV) : RecM.WF layer (whnfCacheSemantics keys trProj fallback) trProj world @@ -275,7 +275,7 @@ theorem whnfCoreWithFlags_wf stepError) (hwrites : WhnfCoreCacheWriteOracle keys trProj fallback world support) (hsupport : support source) - {sourceV : Lean4Lean.VExpr} {s : TcState .anon} + {sourceV : Ix.Theory.Named.VExpr} {s : TcState .anon} (hsource : TrKExprS world.venv keys.uvars world.nameOf trProj Delta source sourceV) : RecM.WF layer (whnfCacheSemantics keys trProj fallback) trProj world @@ -389,4 +389,4 @@ theorem coreCacheWriteOracle end WhnfSuffixModel -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/ProjectionStep.lean b/Ix/Kernel/Verify/Whnf/Structural/ProjectionStep.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Structural/ProjectionStep.lean rename to Ix/Kernel/Verify/Whnf/Structural/ProjectionStep.lean index c717b7bdb..5cb237693 100644 --- a/Ix/Tc/Verify/Whnf/Structural/ProjectionStep.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/ProjectionStep.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.RecursiveCallbacks +import Ix.Kernel.Verify.Whnf.Structural.RecursiveCallbacks /-! # Exhaustive projection-step closure @@ -18,7 +18,7 @@ with `InductiveReductionOracle`; a syntax-directed helper execution alone is not treated as a Theory projection equation. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM namespace ProjectionHelper @@ -152,4 +152,4 @@ theorem whnfCoreWithFlagsStep_basicVarProjection_wf horacle end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/RecursiveCallbacks.lean b/Ix/Kernel/Verify/Whnf/Structural/RecursiveCallbacks.lean similarity index 93% rename from Ix/Tc/Verify/Whnf/Structural/RecursiveCallbacks.lean rename to Ix/Kernel/Verify/Whnf/Structural/RecursiveCallbacks.lean index 708bcf076..cac2111cc 100644 --- a/Ix/Tc/Verify/Whnf/Structural/RecursiveCallbacks.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/RecursiveCallbacks.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.VariableStep +import Ix.Kernel.Verify.Whnf.Structural.VariableStep /-! # Structural recursive-callback closure @@ -16,7 +16,7 @@ only a support boundary; semantic translation of each child is derived from the translated parent. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Finite support closure needed by one structural-WHNF iteration. The app @@ -38,7 +38,7 @@ theorem whnfCoreFlagsRec_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} - {source : KExpr .anon} {sourceV : Lean4Lean.VExpr} + {source : KExpr .anon} {sourceV : Ix.Theory.Named.VExpr} {flags : WhnfFlags} (hsource : support source) (htr : TrKExprS world.venv uvars world.nameOf trProj Delta source @@ -55,10 +55,10 @@ namespace TrAppSpine /-- A typed application spine retains the translation of its raw head. -/ theorem headTr - {env : Lean4Lean.VEnv} {uvars : Nat} + {env : Ix.Theory.Named.VEnv} {uvars : Nat} {nameOf : Address -> Option Lean.Name} {trProj : RawProjRel} {Delta : KVLCtx} {head : KExpr .anon} - {args : List (KExpr .anon)} {resultV : Lean4Lean.VExpr} + {args : List (KExpr .anon)} {resultV : Ix.Theory.Named.VExpr} (h : TrAppSpine env uvars nameOf trProj Delta head args resultV) : exists headV, TrKExprS env uvars nameOf trProj Delta head headV := by @@ -76,7 +76,7 @@ theorem projectionValueCallback_wf {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {id : KId .anon} {field : UInt64} {value : KExpr .anon} - {info : ExprInfo .anon} {sourceV : Lean4Lean.VExpr} + {info : ExprInfo .anon} {sourceV : Ix.Theory.Named.VExpr} {flags : WhnfFlags} (hinputs : WhnfCoreInputSupport support) (hsupport : support (.prj id field value info)) @@ -109,7 +109,7 @@ theorem applicationHeadCallback_wf {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} {f arg head : KExpr .anon} {info : ExprInfo .anon} - {args : Array (KExpr .anon)} {sourceV : Lean4Lean.VExpr} + {args : Array (KExpr .anon)} {sourceV : Ix.Theory.Named.VExpr} {flags : WhnfFlags} (hinputs : WhnfCoreInputSupport support) (hsupport : support (.app f arg info)) @@ -142,4 +142,4 @@ theorem applicationArgument_support (hinputs.app hsupport hspine).2 child hmem end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/Reducer.lean b/Ix/Kernel/Verify/Whnf/Structural/Reducer.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Structural/Reducer.lean rename to Ix/Kernel/Verify/Whnf/Structural/Reducer.lean index adc6d8fce..d4e432ab8 100644 --- a/Ix/Tc/Verify/Whnf/Structural/Reducer.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/Reducer.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Verify.Whnf.Structural.VerifiedStep -import Ix.Tc.Verify.Whnf.Iota.OptionalReduction +import Ix.Kernel.Verify.Whnf.Structural.VerifiedStep +import Ix.Kernel.Verify.Whnf.Iota.OptionalReduction /-! # Construct the structural reducer @@ -16,7 +16,7 @@ state/semantic composition rather than a free `OptionalReduction.WF` parameter. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Complete fixed-context input for the production structural reducer. @@ -115,4 +115,4 @@ theorem wf end StructuralCoreContext end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/StepAssembly.lean b/Ix/Kernel/Verify/Whnf/Structural/StepAssembly.lean similarity index 97% rename from Ix/Tc/Verify/Whnf/Structural/StepAssembly.lean rename to Ix/Kernel/Verify/Whnf/Structural/StepAssembly.lean index cfdd1b8f5..34a187746 100644 --- a/Ix/Tc/Verify/Whnf/Structural/StepAssembly.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/StepAssembly.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.ApplicationStep +import Ix.Kernel.Verify.Whnf.Structural.ApplicationStep /-! # Exhaustive structural-step assembly @@ -8,7 +8,7 @@ the single local `WhnfStep.WF` consumed by the already verified bounded loop and cache shell; no syntax branch remains implicit in a classifier premise. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Exhaustive contract for one actual `whnfCoreWithFlagsStep` iteration. -/ @@ -82,4 +82,4 @@ theorem whnfCoreWithFlagsStep_wf (.basicVar (.basic (.leaf .str))) s hsource end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/VariableStep.lean b/Ix/Kernel/Verify/Whnf/Structural/VariableStep.lean similarity index 98% rename from Ix/Tc/Verify/Whnf/Structural/VariableStep.lean rename to Ix/Kernel/Verify/Whnf/Structural/VariableStep.lean index e81b293f5..e4211a760 100644 --- a/Ix/Tc/Verify/Whnf/Structural/VariableStep.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/VariableStep.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Structural.BasicStep +import Ix.Kernel.Verify.Whnf.Structural.BasicStep /-! # Legacy-variable structural-step closure @@ -11,7 +11,7 @@ those walker-tight bounds to the semantic context without introducing the older, stronger `Δ.bvars + val.size` assumption. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace TcM @@ -56,7 +56,7 @@ theorem zetaVar_liftBounds world.venvWF.ordered htp hidx hshift hty hov hcon hcut hlift have hsource : TrKExprS world.venv uvars world.nameOf trProj Delta (.var idx name info) e := .var hfind - have hwf : Lean4Lean.VExpr.WF world.venv uvars Delta.toCtx e := + have hwf : Ix.Theory.Named.VExpr.WF world.venv uvars Delta.toCtx e := ⟨A, hctx.wf.find?_wf world.venvWF.ordered hfind⟩ exact ⟨e, e, hsource, hresult, hwf⟩ @@ -192,4 +192,4 @@ theorem whnfCoreWithFlagsStep_basicVar_wf exact whnfCoreWithFlagsStep_var_wf hrun theory hvar end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/Whnf/Structural/VerifiedStep.lean b/Ix/Kernel/Verify/Whnf/Structural/VerifiedStep.lean similarity index 96% rename from Ix/Tc/Verify/Whnf/Structural/VerifiedStep.lean rename to Ix/Kernel/Verify/Whnf/Structural/VerifiedStep.lean index 0263c3dd0..44ef665bf 100644 --- a/Ix/Tc/Verify/Whnf/Structural/VerifiedStep.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/VerifiedStep.lean @@ -1,4 +1,4 @@ -import Ix.Tc.Verify.Whnf.Beta.Meaning +import Ix.Kernel.Verify.Whnf.Beta.Meaning /-! # Structural step without a beta oracle @@ -9,7 +9,7 @@ Theory and translation invariants, so the production structural step can now be exposed with only its genuine helper and finite-run boundaries. -/ -namespace Ix.Tc +namespace Ix.Kernel namespace RecM /-- Exhaustive `whnfCoreWithFlagsStep` closure with general multi-beta proved @@ -41,4 +41,4 @@ theorem whnfCoreWithFlagsStep_constructive_wf hinputs hprojection hinductive (betaManyMeaning trProj world) hiota end RecM -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Verify/World.lean b/Ix/Kernel/Verify/World.lean similarity index 98% rename from Ix/Tc/Verify/World.lean rename to Ix/Kernel/Verify/World.lean index f5cad0701..3876b7358 100644 --- a/Ix/Tc/Verify/World.lean +++ b/Ix/Kernel/Verify/World.lean @@ -1,5 +1,5 @@ -import Ix.Tc.Env -import Lean4Lean.Theory.Typing.Env +import Ix.Kernel.Env +import Ix.Theory.Named.Typing.Env /-! # Non-circular verification worlds @@ -13,7 +13,7 @@ whole-`KEnv` relation conflates: assigned to each coordinated checker block; * `VerifyWorld.trusted`: the ghost index intended to track declarations already admitted to the semantic world; -* `VerifyWorld.venv`: the well-formed Lean4Lean environment for that trusted +* `VerifyWorld.venv`: the well-formed Ix.Theory.Named environment for that trusted world; * `LoadedAgrees`: the one-way relation from the concrete lazy-load cache to the catalog. @@ -32,9 +32,9 @@ constants through `TrustedConstRel`. The legacy `TrKEnv` remains only as a quarantined compatibility proof interface. -/ -namespace Ix.Tc +namespace Ix.Kernel -open Lean4Lean (VEnv) +open Ix.Theory.Named (VEnv) /-- Immutable ghost input. A catalog entry says which concrete declaration is committed at an id; it says nothing about that declaration's typing. -/ @@ -356,4 +356,4 @@ theorem VerifyWorld.ofCatalog_loaded_not_trusted {catalog : Catalog} end CataloguedLoaded -end Ix.Tc +end Ix.Kernel diff --git a/Ix/Tc/Whnf.lean b/Ix/Kernel/Whnf.lean similarity index 99% rename from Ix/Tc/Whnf.lean rename to Ix/Kernel/Whnf.lean index 871e07457..d74511c4f 100644 --- a/Ix/Tc/Whnf.lean +++ b/Ix/Kernel/Whnf.lean @@ -1,6 +1,6 @@ module -public import Ix.Tc.Monad +public import Ix.Kernel.Monad /-! Mirror: crates/kernel/src/whnf.rs (plus `str_lit_to_constructor` from @@ -35,7 +35,7 @@ which otherwise descend into Nat.rec towers and trip maxDefEqDepth). public section @[expose] section -namespace Ix.Tc +namespace Ix.Kernel open Std (HashMap HashSet) @@ -90,7 +90,7 @@ def KConst.iotaCtorInfo? : KConst m → Option (Nat × Nat) | _ => none /-- Nat value from a literal or the `Nat.zero` constructor (C++ - `is_nat_lit_ext` / lean4lean `rawNatLitExt?`). -/ + `is_nat_lit_ext` / the named specification `rawNatLitExt?`). -/ def extractNatLit (e : KExpr m) (prims : Primitives m) : Option Nat := match e with | .nat val _ _ => some val @@ -121,7 +121,7 @@ def computeNatBin (addr : Address) (p : PrimAddrs) (a b : Nat) : Option Nat := else if addr == p.natDiv then some (if b == 0 then 0 else a / b) else if addr == p.natMod then some (if b == 0 then a else a % b) else if addr == p.natPow then - -- Matches C++ `ReducePowMaxExp` / lean4lean `reducePowMaxExp`. + -- Matches C++ `ReducePowMaxExp` / the named specification `reducePowMaxExp`. if b ≤ 16777216 then some (a ^ b) else none else if addr == p.natGcd then some (Nat.gcd a b) else if addr == p.natLand then some (a &&& b) @@ -174,7 +174,7 @@ namespace RecM Spelled with `tryCatch` and `pure` rather than `try`/`catch` with `return`: a `return` inside a `try` block elaborates through the early-return transformer, burying the plain `EStateM.tryCatch` this reduces to and that -`Ix/Tc/Verify/Whnf/Iota/ConstructorSynthesis.lean` reasons about. Both +`Ix/Kernel/Verify/Whnf/Iota/ConstructorSynthesis.lean` reasons about. Both spellings denote the same function. -/ @[inline] def try? (x : RecM m α) : RecM m (Option α) := tryCatch (do let a ← x; pure (some a)) (fun _ => pure none) @@ -240,7 +240,7 @@ def strLitListToConstructor (charOfNat cons : KExpr m) : /-- `"abc" → String.ofList (List.cons (Char.ofNat 97) … List.nil)` — the kernel's string-literal constructor expansion (def_eq.rs `str_lit_to_constructor`; `Char.ofNat` + `String.ofList`, matching - lean4lean / C++). -/ + the named specification / C++). -/ def strLitToConstructor (s : String) : RecM m (KExpr m) := do let p ← prims let charConst ← TcM.intern (.mkConst p.charType #[]) @@ -488,7 +488,7 @@ def tryApplyIotaCtor (recr : IotaInfo m) (recUs : Array (KUniv m)) (spine ctorArgs : Array (KExpr m)) (cidx ctorFields : Nat) (transient : Bool) : RecM m (Option (KExpr m)) := do let some rule := recr.rules[cidx]? | return none - -- H6: level arity; H5: fields ≤ ctor args (lean4lean Reduce.lean:75-76). + -- H6: level arity; H5: fields ≤ ctor args (the named specification Reduce.lean:75-76). if recUs.size.toUInt64 != recr.lvls then return none if ctorFields > ctorArgs.size then @@ -789,7 +789,7 @@ def whnfWithNatSuccModeStep (natSuccMode : NatSuccMode) if seen.contains cur.addr then return .done cur let seen := seen.insert cur.addr - -- Native reduction runs before nat reduction (lean4lean order). + -- Native reduction runs before nat reduction (the named specification order). if let some reduced ← tryReduceNative cur then return .next (reduced, seen) if let some reduced ← tryReduceBitvec cur then @@ -919,7 +919,7 @@ def whnfCoreWithFlagsStep (cur : KExpr m) (flags : WhnfFlags) : | some val => return .next val | none => return .done cur | .fvar id _ _ => - -- Let-bound fvar zeta-reduction (lean4lean `whnfFVar`). + -- Let-bound fvar zeta-reduction (the named specification `whnfFVar`). match (← get).lctx.find? id with | some (.ldecl _ _ val) => return .next val | _ => return .done cur @@ -1193,7 +1193,7 @@ def tryStructEtaAfterInductive (recUs : Array (KUniv m)) /-- Struct-eta iota: single-rule recursor over a non-recursive one-ctor zero-index inductive; rebuild the rule with projections of the major. - Prop-typed majors are excluded (lean4lean `toCtorWhenStruct`). -/ + Prop-typed majors are excluded (the named specification `toCtorWhenStruct`). -/ def tryStructEtaIota (recId : KId m) (recr : IotaInfo m) (recUs : Array (KUniv m)) (spine : Array (KExpr m)) : RecM m (Option (KExpr m)) := do @@ -1973,7 +1973,7 @@ def tryReduceNative (e : KExpr m) : RecM m (Option (KExpr m)) := do tryReduceNativeMarker p isReduceBool argId argUs -- ### `is_rec` verification (inductive.rs `computed_is_rec` — hosted here --- because struct-likeness needs it; `Ix.Tc.Inductive` reuses it) +-- because struct-likeness needs it; `Ix.Kernel.Inductive` reuses it) /-- Finish one constructor-parameter peel after the recursive WHNF callback. Naming the post-callback seam keeps the binder mutation equation stable for @@ -2106,7 +2106,7 @@ attribute [irreducible] tryProjPrepare tryProjReduce end RecM -end Ix.Tc +end Ix.Kernel end end diff --git a/Ix/Tc.lean b/Ix/Tc.lean deleted file mode 100644 index 3f0962a55..000000000 --- a/Ix/Tc.lean +++ /dev/null @@ -1,54 +0,0 @@ -module - -public import Ix.Tc.Mode -public import Ix.Tc.Id -public import Ix.Tc.Level -public import Ix.Tc.Expr -public import Ix.Tc.Error -public import Ix.Tc.Const -public import Ix.Tc.Equiv -public import Ix.Tc.Env -public import Ix.Tc.Primitive -public import Ix.Tc.Subst -public import Ix.Tc.Lctx -public import Ix.Tc.Monad -public import Ix.Tc.Ingress -public import Ix.Tc.IngressMeta -public import Ix.Tc.Egress -public import Ix.Tc.EgressLean -public import Ix.Tc.Driver -public import Ix.Tc.ParCheck -public import Ix.Tc.Validate -public import Ix.Tc.Whnf -public import Ix.Tc.Infer -public import Ix.Tc.DefEq -public import Ix.Tc.Knot -public import Ix.Tc.CanonicalCheck -public import Ix.Tc.Inductive -public import Ix.Tc.Check - -/-! -# Ix.Tc — pure-Lean Ix kernel over Ixon - -A correctness-first, formalizable port of the Rust Ix kernel -(`crates/kernel`), operating over the Ixon content-addressed format with -separated anon and meta modes. Designed for correctness and formalization; -for performance, use the Rust kernel. - -Module map (mirrors `crates/kernel/src/` file-for-file): - -| Lean module | Rust source | -|-------------------|----------------| -| `Ix.Tc.Mode` | `mode.rs` | -| `Ix.Tc.Id` | `id.rs` | -| `Ix.Tc.Error` | `error.rs` | -| `Ix.Tc.Level` | `level.rs` | -| `Ix.Tc.Expr` | `expr.rs` | -| `Ix.Tc.Const` | `constant.rs` | -| `Ix.Tc.Equiv` | `equiv.rs` | -| `Ix.Tc.Env` | `env.rs` | -| `Ix.Tc.Primitive` | `primitive.rs` | -| `Ix.Tc.Subst` | `subst.rs` | -| `Ix.Tc.Lctx` | `lctx.rs` | -| `Ix.Tc.Monad` | `tc.rs` | --/ diff --git a/Ix/Theory.lean b/Ix/Theory.lean new file mode 100644 index 000000000..8687dd69f --- /dev/null +++ b/Ix/Theory.lean @@ -0,0 +1,6 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified diff --git a/Ix/Theory/Certificate/Build.lean b/Ix/Theory/Certificate/Build.lean new file mode 100644 index 000000000..a8adb93e0 --- /dev/null +++ b/Ix/Theory/Certificate/Build.lean @@ -0,0 +1,211 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.OrdinarySource +import Ix.Theory.Certificate.Standard +import Ix.Theory.Certificate.Quotient +import Ix.Theory.Certificate.Structure +import Ix.Theory.Certificate.Modeled +import Ix.Theory.Certified.Accept + +namespace Ix.Theory.Certificate + +open Model Certified + +universe u +variable {β : Type u} [DecidableEq β] +variable [Hints β] + +def hasLiteral : VExpr β → Bool + | .natLit _ => true + | .app a b | .lam a b | .forallE a b => hasLiteral a || hasLiteral b + | .proj _ _ e => hasLiteral e + | _ => false + +def constantHasLiteral : Const β → Bool + | .defn _ _ type body _ => hasLiteral type || hasLiteral body + | .induct _ _ _ type ctors _ => hasLiteral type || ctors.any (hasLiteral ·.type) + | .recursor _ _ _ _ _ type rules _ _ => hasLiteral type || rules.any (hasLiteral ·.rhs) + | .axiom _ type _ | .quot _ _ type => hasLiteral type + +def literalDependencies? (natural : Option (ConstRef β)) (used : Bool) : Option (List (ConstRef β)) := + if used then natural.map (fun r => [r]) else some [] + +inductive DeclarationSource (β : Type u) where + | definition (ref : ConstRef β) + | ordinary (source recursor : β) + | standard (ref : ConstRef β) + | quotient (refs : Certified.Quotient.Refs β) + | modeled (candidate : Modeled.Candidate β) + +structure SourceGroup (β : Type u) where + declaration : DeclarationSource β + references : List (ConstRef β) + dependencies : List (ConstRef β) + +def recursorFamily? : VExpr β → Option β + | .forallE _ (.forallE A B) => recursorFamily? (.forallE A B) + | .forallE A _ => match A.appHead with + | .const (.member source 0) _ => some source + | _ => none + | _ => none + +def findRecursor? (store : Store β) (source : β) : Option β := + store.dom.find? fun candidate => match store.blocks candidate with + | some ⟨[.recursor _ _ _ _ _ type _ _ .safe]⟩ => recursorFamily? type == some source + | _ => false + +def ordinaryGroup? (store : Store β) (source recursor : β) + (natural : Option (ConstRef β) := none) : Option (SourceGroup β) := do + let ⟨[family@(.induct _ _ _ _ ctors .safe)]⟩ ← store.blocks source | none + let ⟨[recr@(.recursor _ _ _ _ _ _ _ _ .safe)]⟩ ← store.blocks recursor | none + let references := [.member source 0, .member recursor 0] ++ + (List.range ctors.length).map (.ctor source 0 ·) + let literals ← literalDependencies? natural (constantHasLiteral family || constantHasLiteral recr) + return ⟨.ordinary source recursor, references, + ((family.refs ++ recr.refs).filter fun r => !references.contains r) ++ literals⟩ + +def quotientGroup (refs : Certified.Quotient.Refs β) : SourceGroup β := + ⟨.quotient refs, Certified.Quotient.kinds.map refs.ref, [refs.eq, refs.eqRefl, refs.eqRec]⟩ + +def modeledGroup? (store : Store β) (candidate : Modeled.Candidate β) + (natural : Option (ConstRef β) := none) : Option (SourceGroup β) := do + let references ← Certified.Modeled.sourceRefs? store candidate.source candidate.recursors + let sources := references.filterMap (store.lookup ·) + let rawReferences := sources.flatMap Const.refs + let literals ← literalDependencies? natural (sources.any constantHasLiteral) + return ⟨.modeled candidate, references, + rawReferences.filter (fun ref => !references.contains ref) ++ candidate.models ++ + candidate.proofReferences ++ literals⟩ + +def sourceGroup? (store : Store β) (r : ConstRef β) + (natural : Option (ConstRef β) := none) (models : List (Modeled.Candidate β) := []) : Option (SourceGroup β) := do + match models.findSome? (fun candidate => do + let group ← modeledGroup? store candidate natural + if group.references.contains r then some group else none) with + | some group => return group + | none => pure ⟨⟩ + match r with + | .ctor source 0 _ => ordinaryGroup? store source (← findRecursor? store source) natural + | .ctor .. => none + | .member source member => + match ← store.lookup r with + | .defn _ _ type body .safe => + return ⟨.definition r, [r], type.refs ++ body.refs ++ + (← literalDependencies? natural (hasLiteral type || hasLiteral body))⟩ + | .axiom _ type .safe => + match Quotient.refs? store r with + | some refs => return quotientGroup refs + | none => return ⟨.standard r, [r], type.refs ++ (← literalDependencies? natural (hasLiteral type))⟩ + | .quot .. => return quotientGroup (← Quotient.refs? store r) + | .induct .. => + if member != 0 then none else ordinaryGroup? store source (← findRecursor? store source) natural + | .recursor _ _ _ _ _ type _ _ .safe => + if member != 0 then none else ordinaryGroup? store (← recursorFamily? type) source natural + | _ => none + +/-- Dependency order groups a whole ordinary family and recursor as one unit. +A cycle, missing reference, or unsupported declaration produces no suggestion. -/ +def dependencyOrder? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (pending visited active : List (ConstRef β)) + (order : List (DeclarationSource β) := []) (models : List (Modeled.Candidate β) := []) : + Option (List (ConstRef β) × List (DeclarationSource β)) := + match fuel, pending with + | _, [] => some (visited, order) + | 0, _ :: _ => none + | fuel + 1, r :: rest => + if r = signature.falseType ∨ r = signature.falseElim ∨ r ∈ visited then + dependencyOrder? fuel signature store rest visited active order models + else if r ∈ active then none + else do + let group ← sourceGroup? store r signature.natType models + if group.references.any (active.contains ·) then none else do + let (visited, order) ← dependencyOrder? fuel signature store + group.dependencies visited (group.references ++ active) order models + dependencyOrder? fuel signature store rest (visited ++ group.references) active + (order ++ [group.declaration]) models + +def definitionWitness? (fuel : Nat) (entries : Environment β) (r : ConstRef β) + (source : Const β) : Option (DefinitionWitness β) := + match source with + | .defn n _ type body .safe => do + let T ← inferSource? fuel n entries [] type + let .sort l := T.type | none + let b ← inferSource? fuel n entries [] body + let bw ← castWith? fuel n entries [] b T.expression + return ⟨r, annotations T.expression, annotations b.expression, l, T.witness, bw⟩ + | _ => none + +def declarationWitnesses? (fuel : Nat) (store : Store β) (entries : Environment β) : + List (DeclarationSource β) → Option (Environment β × List (DeclarationWitness β)) + | [] => some (entries, []) + | .definition r :: rest => do + let source ← store.lookup r + let witness ← definitionWitness? fuel entries r source + let reading ← readDefinition? source witness.typeAnnotations witness.bodyAnnotations + let (entries', witnesses) ← + declarationWitnesses? fuel store (entries.insert r reading.val.entry) rest + return (entries', .definition witness :: witnesses) + | .ordinary source recursor :: rest => do + let witness ← Ordinary.sourceBlock? fuel entries store source recursor + if Hints.natural (β := β) = some (.member source 0) then + if witness.shape.shape != Certified.Natural.shape then none else do + let (entries', witnesses) ← declarationWitnesses? fuel store + (Certified.Natural.environment entries source recursor witness.mode) rest + return (entries', .natural witness :: witnesses) + else + match Structure.witness? fuel entries witness with + | some structured => + let (entries', witnesses) ← declarationWitnesses? fuel store + (structured.facts.description.publishedEnvironment entries source recursor witness.mode) rest + return (entries', .structure structured :: witnesses) + | none => + let (entries', witnesses) ← declarationWitnesses? fuel store + (witness.shape.shape.publishedEnvironment entries source recursor witness.mode) rest + return (entries', .ordinary witness :: witnesses) + | .standard ref :: rest => do + let source ← store.lookup ref + let witness ← Standard.witness? fuel store entries ref source + let (entries', witnesses) ← declarationWitnesses? fuel store (entries.insert ref witness.spec.entry) rest + return (entries', .standard witness :: witnesses) + | .quotient refs :: rest => do + let witness ← Quotient.witness? fuel entries refs + let (entries', witnesses) ← declarationWitnesses? fuel store (refs.environment entries) rest + return (entries', .quotient witness :: witnesses) + | .modeled candidate :: rest => do + let witness ← candidate.witness? fuel entries store + let (entries', witnesses) ← declarationWitnesses? fuel store + (Certified.Modeled.environment entries witness.companions) rest + return (entries', .modeled witness :: witnesses) + +/-- A generic search driver over the exact input store and source syntax. +This is untrusted preprocessing: the final acceptance call validates the +entire returned witness again, including the primitive metadata and policy. -/ +def proofWitness? (fuel : Nat) (signature : PrimitiveSignature β) + (input : ProofInput β) (models : List (Modeled.Candidate β) := []) : Option (ProofWitness β) := + letI : Hints β := ⟨signature.natType⟩ + do + let literals ← literalDependencies? signature.natType (hasLiteral input.proposition || hasLiteral input.proof) + let (_, order) ← dependencyOrder? fuel signature input.store + (input.proposition.refs ++ input.proof.refs ++ literals) [] [] [] models + let (entries, declarations) ← + declarationWitnesses? fuel input.store signature.environment order + let P ← inferSource? fuel input.universes entries [] input.proposition + let Pw ← castWith? fuel input.universes entries [] P (.sort .zero) + let e ← inferSource? fuel input.universes entries [] input.proof + let ew ← castWith? fuel input.universes entries [] e P.expression + return ⟨declarations, annotations e.expression, annotations P.expression, ew, Pw⟩ + +/-- Declaration-only search also covers data declarations and complete source +groups. The independent store validator checks every requested reference. -/ +def storeWitness? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (targets : List (ConstRef β)) (models : List (Modeled.Candidate β) := []) : Option (List (DeclarationWitness β)) := + letI : Hints β := ⟨signature.natType⟩ + do + let (_, order) ← dependencyOrder? fuel signature store targets [] [] [] models + let (_, declarations) ← declarationWitnesses? fuel store signature.environment order + return declarations + +end Ix.Theory.Certificate diff --git a/Ix/Theory/Certificate/Claims.lean b/Ix/Theory/Certificate/Claims.lean new file mode 100644 index 000000000..3e799214a --- /dev/null +++ b/Ix/Theory/Certificate/Claims.lean @@ -0,0 +1,50 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Build +import Ix.Theory.Certified.Claims + +namespace Ix.Theory.Certificate + +open Model Certified + +universe u +variable {β : Type u} [DecidableEq β] [Hints β] + +/-- Untrusted construction of an ordered opaque frontier. The claim checker +independently re-reads each source type and verifies its formation. -/ +def frontierWitnesses? (fuel : Nat) (store : Store β) (entries : Environment β) : + List (ConstRef β) → Option (Environment β × List (FrontierWitness β)) + | [] => some (entries, []) + | ref :: refs => match store.uvars ref, store.type ref with + | some universes, some type => do + let inferred ← inferSource? fuel universes entries [] type + let .sort level := inferred.type | none + let witness : FrontierWitness β := ⟨ref, annotations inferred.expression, level, inferred.witness⟩ + let reading ← readFrontierHeader? store witness + let (entries', rest) ← frontierWitnesses? fuel store + (entries.insert ref reading.header.entry) refs + return (entries', witness :: rest) + | _, _ => none + +def claimNode? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (frontier subjects : List (ConstRef β)) (models : List (Modeled.Candidate β) := []) : Option (ClaimNode β) := + letI : Hints β := ⟨signature.natType⟩ + do + let (entries, dependencies) ← frontierWitnesses? fuel store signature.environment frontier + let (_, order) ← dependencyOrder? fuel signature store subjects frontier [] [] models + let (_, declarations) ← declarationWitnesses? fuel store entries order + return ⟨subjects, dependencies, declarations⟩ + +def batchFrontier? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (nodes : List (ClaimNode β)) : Option (List (FrontierWitness β)) := + letI : Hints β := ⟨signature.natType⟩ + do + let subjects := nodes.flatMap (·.subjects) + let refs := (nodes.flatMap fun node => node.frontier.map (·.ref)).filter + (fun ref => !subjects.contains ref) |>.eraseDups + return (← frontierWitnesses? fuel store signature.environment refs).2 + +end Ix.Theory.Certificate diff --git a/Ix/Theory/Certificate/Modeled.lean b/Ix/Theory/Certificate/Modeled.lean new file mode 100644 index 000000000..618fb171f --- /dev/null +++ b/Ix/Theory/Certificate/Modeled.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Quotient +import Ix.Theory.Certified.Modeled.Admission + +/-! Untrusted construction of exact model-companion certificates. Model +declarations are ordinary earlier checked declarations. This builder derives +all source headers and rule statements from the store, reads annotations in +the mapped model environment, and searches for conversion or a supplied +propositional proof. Its output must pass public declaration admission. +-/ + +namespace Ix.Theory.Certificate.Modeled + +open Model Certified Certified.Modeled + +universe u +variable {β : Type u} [DecidableEq β] [Hints β] + +structure ProofHint (β : Type u) where + equality : ConstRef β + reflexivity : ConstRef β + recursor : ConstRef β + proof : VExpr β + +/-- A finite untrusted package selects earlier model declarations and optional +equation proofs. The store remains the source of every original statement. -/ +structure Candidate (β : Type u) where + source : β + recursors : List (ConstRef β) + models : List (ConstRef β) + proofs : List (ConstRef β × List (Option (ProofHint β))) := [] + +def Candidate.hint (candidate : Candidate β) (ref : ConstRef β) (index : Nat) : Option (ProofHint β) := do + let (_, proofs) ← candidate.proofs.find? (fun pair => pair.1 == ref) + (proofs[index]?).join + +def Candidate.proofReferences (candidate : Candidate β) : List (ConstRef β) := + candidate.proofs.flatMap fun (_, proofs) => proofs.flatMap fun proof => + match proof with + | none => [] + | some proof => [proof.equality, proof.reflexivity, proof.recursor] ++ proof.proof.refs + +def target (pairs : List (ConstRef β × ConstRef β)) (ref : ConstRef β) : ConstRef β := + ((pairs.find? (fun pair => pair.1 == ref)).map (·.2)).getD ref + +def readMapped? (fuel n : Nat) (entries : Environment β) + (mapping : ConstRef β → ConstRef β) (raw : VExpr β) : Option (AExpr β) := do + let inferred ← inferSource? fuel n entries [] (raw.mapRefs mapping) + let annotated ← readAnnotations? n 0 raw (annotations inferred.expression) + if annotated.val.mapRefs mapping = inferred.expression then some annotated.val else none + +def rule? (fuel : Nat) (entries : Environment β) (mapping : ConstRef β → ConstRef β) + (raw : RawRule β) (hint : Option (ProofHint β)) : + Option (Signature.Rule β × EquationWitness β) := do + let type ← readMapped? fuel raw.universes entries mapping raw.type + let lhs ← readMapped? fuel raw.universes entries mapping raw.lhs + let rhs ← readMapped? fuel raw.universes entries mapping raw.rhs + let rule : Signature.Rule β := ⟨raw.universes, type, lhs, rhs⟩ + let mapped : Signature.Rule β := ⟨raw.universes, type.mapRefs mapping, lhs.mapRefs mapping, rhs.mapRefs mapping⟩ + let formation ← Quotient.ruleWitness? fuel entries mapped + match hint with + | none => do + let proof ← conversion? fuel raw.universes entries [] mapped.lhs mapped.rhs + return (rule, ⟨formation, .conversion proof⟩) + | some hint => do + let inferred ← inferSource? fuel raw.universes entries [] hint.proof + let expected := Basis.Equality.applied hint.equality formation.level mapped.type mapped.lhs mapped.rhs + let proof ← castWith? fuel raw.universes entries [] inferred expected + return (rule, ⟨formation, .propositional hint.equality hint.reflexivity hint.recursor inferred.expression proof⟩) + +def companion? (fuel : Nat) (entries : Environment β) (store : Store β) + (pairs : List (ConstRef β × ConstRef β)) (ref model : ConstRef β) + (hints : Nat → Option (ProofHint β)) : Option (Companion β × List (EquationWitness β)) := do + let raw ← store.type ref + let some universes := store.uvars ref | none + let modelEntry ← entries model + if modelEntry.universes != universes then none else do + let reading ← readAnnotations? universes 0 raw (annotations modelEntry.type) + if reading.val.mapRefs (target pairs) != modelEntry.type then none else do + let rawRules ← sourceRules? store ref + let rules ← rawRules.zipIdx.mapM fun (raw, index) => rule? fuel entries (target pairs) raw (hints index) + return (⟨⟨ref, universes, reading.val⟩, model, rules.map (·.1)⟩, rules.map (·.2)) + +/-- Model targets are positional in the actual source layout. Duplicated +targets are allowed; their exact types and equations still undergo the same +check, which supplies semantic justification for auxiliary merging. -/ +def witness? (fuel : Nat) (entries : Environment β) (store : Store β) (source : β) + (recursors models : List (ConstRef β)) + (hints : ConstRef β → Nat → Option (ProofHint β) := fun _ _ => none) : Option (Witness β) := do + let refs ← sourceRefs? store source recursors + if refs.length != models.length then none else do + let pairs := refs.zip models + let checked ← pairs.mapM fun (ref, model) => companion? fuel entries store pairs ref model (hints ref) + return ⟨source, recursors, checked.map (·.1), checked.map (·.2)⟩ + +def Candidate.witness? (candidate : Candidate β) (fuel : Nat) (entries : Environment β) + (store : Store β) : Option (Witness β) := + Modeled.witness? fuel entries store candidate.source candidate.recursors candidate.models candidate.hint + +end Ix.Theory.Certificate.Modeled diff --git a/Ix/Theory/Certificate/Ordinary.lean b/Ix/Theory/Certificate/Ordinary.lean new file mode 100644 index 000000000..531f83b72 --- /dev/null +++ b/Ix/Theory/Certificate/Ordinary.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Suggest +import Ix.Theory.Certified.Ordinary.Checked + +/-! Untrusted witness construction for a proposed ordinary description. -/ + +namespace Ix.Theory.Certificate.Ordinary + +open Model Certified Certified.Ordinary + +universe u +variable {β : Type u} [DecidableEq β] +variable [Hints β] + +def domains? (fuel n : Nat) (entries : Environment β) : + Context β → List (AExpr β) → Option (List (DomainWitness β)) + | _, [] => some [] + | Γ, A :: rest => do + let typed ← inferAnnotated? fuel n entries Γ A + let .sort level := typed.type | none + let tail ← domains? fuel n entries (Γ.push A) rest + return ⟨level, typed.witness⟩ :: tail + +def arguments? (fuel n : Nat) (entries : Environment β) (Γ : Context β) : + List (AExpr β) → List (AExpr β) → Option (List (TypingWitness β)) + | [], [] => some [] + | A :: domains, a :: args => do + let typed ← inferAnnotated? fuel n entries Γ a + let witness ← castWith? fuel n entries Γ typed A + let tail ← arguments? fuel n entries Γ (Telescope.inst a domains) args + return witness :: tail + | _, _ => none + +def recursive? (fuel : Nat) (entries : Environment β) (shape : Shape β) + (ctor : Constructor β) (field : RecursiveField β) : Option (RecursiveWitness β) := do + let domains ← domains? fuel shape.universes entries (ctor.context shape) field.domains + let indices ← arguments? fuel shape.universes entries + (Telescope.context (ctor.context shape) field.domains) + (Telescope.lift (ctor.fields.length + field.domains.length) shape.indices) field.indices + return ⟨domains, indices⟩ + +def constructor? (fuel : Nat) (entries : Environment β) (shape : Shape β) + (ctor : Constructor β) : Option (ConstructorWitness β) := do + let fields ← domains? fuel shape.universes entries shape.parameterContext ctor.fields + let indices ← arguments? fuel shape.universes entries (ctor.context shape) + (Telescope.lift ctor.fields.length shape.indices) ctor.indices + let recursive ← ctor.recursive.mapM (recursive? fuel entries shape ctor) + return ⟨fields, indices, recursive⟩ + +def shape? (fuel : Nat) (entries : Environment β) (shape : Shape β) : Option (ShapeWitness β) := do + let parameters ← domains? fuel shape.universes entries [] shape.parameters + let indices ← domains? fuel shape.universes entries shape.parameterContext shape.indices + let constructors ← shape.constructors.mapM (constructor? fuel entries shape) + return ⟨shape, parameters, indices, constructors⟩ + +def type? (fuel n : Nat) (entries : Environment β) (type : AExpr β) : Option (Shape.TypeWitness β) := do + let typed ← inferAnnotated? fuel n entries [] type + let .sort level := typed.type | none + return ⟨level, typed.witness⟩ + +def constructorTypes? (fuel : Nat) (entries : Environment β) (shape : Shape β) (source : β) : + Option (List (Shape.TypeWitness β)) := + shape.constructors.mapM fun ctor => type? fuel shape.universes (shape.familyEnvironment entries source) + (ctor.type shape source) + +def recursorType? (fuel : Nat) (entries : Environment β) (shape : Shape β) (source : β) + (mode : Inductive.ElimMode) : Option (Shape.TypeWitness β) := + type? fuel (mode.recUvars shape.universes) (shape.constructorEnvironment entries source) (shape.recursorType source mode) + +def rule? (fuel : Nat) (entries : Environment β) (shape : Shape β) (source recursor : β) + (mode : Inductive.ElimMode) (i : Nat) (ctor : Constructor β) : Option (RuleWitness β) := do + let n := mode.recUvars shape.universes + let type := shape.ruleType source mode i ctor + let typed ← type? fuel n entries type + let lhs ← inferAnnotated? fuel n entries [] (shape.ruleLhs source recursor mode i ctor) + let lh ← castWith? fuel n entries [] lhs type + let rhs ← inferAnnotated? fuel n entries [] (shape.ruleRhs source recursor mode i ctor) + let rh ← castWith? fuel n entries [] rhs type + return ⟨typed.level, typed.witness, lh, rh⟩ + +def rules? (fuel : Nat) (entries : Environment β) (shape : Shape β) (source recursor : β) + (mode : Inductive.ElimMode) : Option (List (RuleWitness β)) := + shape.constructors.zipIdx.mapM fun (ctor, i) => rule? fuel + (shape.recursorEnvironment entries source recursor mode) shape source recursor mode i ctor + +def block? (fuel : Nat) (entries : Environment β) (shape : Shape β) (source recursor : β) + (mode : Inductive.ElimMode) : Option (BlockWitness β) := do + let sw ← shape? fuel entries shape + let ct ← constructorTypes? fuel entries shape source + let rt ← recursorType? fuel entries shape source mode + let rs ← rules? fuel entries shape source recursor mode + return ⟨source, recursor, sw, mode, ct, rt, rs⟩ + +end Ix.Theory.Certificate.Ordinary diff --git a/Ix/Theory/Certificate/OrdinarySource.lean b/Ix/Theory/Certificate/OrdinarySource.lean new file mode 100644 index 000000000..663fac582 --- /dev/null +++ b/Ix/Theory/Certificate/OrdinarySource.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Ordinary + +/-! Untrusted recovery of ordinary descriptions from exact source declarations. +Every removed context slot is checked by lifting back, and the completed +description must reproduce all original source metadata and expressions. -/ + +namespace Ix.Theory.Certificate.Ordinary + +open Model Certified Certified.Ordinary + +universe u +variable {β : Type u} [DecidableEq β] +variable [Hints β] + +def telescope : VExpr β → List (VExpr β) × VExpr β + | .forallE A B => let (tail, result) := telescope B; (A :: tail, result) + | e => ([], e) + +def sourceDomains? (fuel n : Nat) (entries : Environment β) : + Context β → List (VExpr β) → Option (List (AExpr β)) + | _, [] => some [] + | Γ, A :: rest => do + let typed ← inferSource? fuel n entries Γ A + let .sort _ := typed.type | none + let tail ← sourceDomains? fuel n entries (Γ.push typed.expression) rest + return typed.expression :: tail + +def removeVariables? (count : Nat) (e : VExpr β) : Option (VExpr β) := + let candidate := e.unliftN count 0 + if candidate.liftN count = e then some candidate else none + +def sourceIndices? (fuel : Nat) (entries : Environment β) (shape : Shape β) + (source : β) (Γ : Context β) (offset : Nat) (result : VExpr β) : + Option (List (AExpr β)) := do + if result.appHead != .const (.member source 0) (VLevel.params shape.universes) then none else do + let args := result.appArgs [] + if args.length != shape.parameters.length + shape.indices.length then none else do + if args.take shape.parameters.length != VExpr.bvarRevRange offset shape.parameters.length then + none + else + (args.drop shape.parameters.length).mapM fun index => do + return (← inferSource? fuel shape.universes entries Γ index).expression + +def sourceRecursive? (fuel : Nat) (entries : Environment β) (shape : Shape β) + (source : β) (fields : List (AExpr β)) (previous : Nat) (raw : VExpr β) : + Option (RecursiveField β) := do + let raw ← removeVariables? previous raw + let (domains, result) := telescope raw + let Γ := Telescope.context shape.parameterContext fields + let domains ← sourceDomains? fuel shape.universes entries Γ domains + let indices ← sourceIndices? fuel entries shape source (Telescope.context Γ domains) + (fields.length + domains.length) result + return ⟨domains, indices⟩ + +def sourceConstructor? (fuel : Nat) (entries : Environment β) (shape : Shape β) + (source : β) (raw : Ctor β) : Option (Constructor β) := do + let (binders, result) := telescope raw.type + if binders.take shape.parameters.length != shape.parameters.map AExpr.erase then none else do + let fields := binders.drop shape.parameters.length + let ordinary := fields.takeWhile fun A => !A.refs.contains (.member source 0) + let recursive := fields.drop ordinary.length + let fields ← sourceDomains? fuel shape.universes entries shape.parameterContext ordinary + let recursive ← recursive.zipIdx.mapM fun (raw, previous) => + sourceRecursive? fuel entries shape source fields previous raw + let result ← removeVariables? recursive.length result + let indices ← sourceIndices? fuel entries shape source + (Telescope.context shape.parameterContext fields) fields.length result + return ⟨fields, recursive, indices⟩ + +def description? (fuel : Nat) (entries : Environment β) (source : β) (raw : Const β) : + Option (Shape β) := do + let .induct n p i type constructors .safe := raw | none + let (binders, result) := telescope type + let .sort level := result | none + if binders.length != p + i then none else do + let parameters ← sourceDomains? fuel n entries [] (binders.take p) + let indices ← sourceDomains? fuel n entries (Telescope.context [] parameters) (binders.drop p) + let shape : Shape β := ⟨n, parameters, indices, level, []⟩ + let constructors ← constructors.mapM (sourceConstructor? fuel entries shape source) + let shape := { shape with constructors } + if shape.source source = raw then some shape else none + +def sourceBlock? (fuel : Nat) (entries : Environment β) (store : Store β) + (source recursor : β) : Option (BlockWitness β) := do + let ⟨[raw]⟩ ← store.blocks source | none + let shape ← description? fuel entries source raw + if shape.RecursorSourceMatches store source recursor .small then + block? fuel entries shape source recursor .small + else if shape.RecursorSourceMatches store source recursor .large then + block? fuel entries shape source recursor .large + else none + +end Ix.Theory.Certificate.Ordinary diff --git a/Ix/Theory/Certificate/Quotient.lean b/Ix/Theory/Certificate/Quotient.lean new file mode 100644 index 000000000..b95b434d4 --- /dev/null +++ b/Ix/Theory/Certificate/Quotient.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Standard +import Ix.Theory.Certified.Quotient.Publish + +namespace Ix.Theory.Certificate.Quotient + +open Model Certified Certified.Quotient + +universe u +variable {β : Type u} [DecidableEq β] +variable [Hints β] + +def memberRefs (store : Store β) : List (ConstRef β) := + store.dom.flatMap fun block => + match store.blocks block with + | some value => (List.range value.members.length).map (.member block ·) + | none => [] + +def findSource? (store : Store β) (source : Const β) : Option (ConstRef β) := + (memberRefs store).find? fun r => store.lookup r == some source + +/-- Discover the quotient package from an exact lift type. The other members +are found by declaration content, independently of addresses or source names. -/ +def refsForLift? (store : Store β) (lift : ConstRef β) : Option (Refs β) := do + let .quot .lift 2 type ← store.lookup lift | none + type.refs.findSome? fun eq => do + let .member esource 0 := eq | none + let eqRefl := ConstRef.ctor esource 0 0 + let eqRec ← Standard.recursorFor? store 2 (Certified.Basis.Equality.recType eq eqRefl) + type.refs.findSome? fun family => do + let refs : Refs β := { eq, type := family, ctor := lift, lift, ind := lift, eqRefl, eqRec, sound := lift } + if (refs.source .lift) != .quot .lift 2 type then none else do + let ctor ← findSource? store (refs.source .ctor) + let refs := { refs with ctor } + let ind ← findSource? store (refs.source .ind) + let sound ← findSource? store (refs.source .sound) + let refs := { refs with ind, sound } + if refs.ExactSource store then some refs else none + +def refs? (store : Store β) (ref : ConstRef β) : Option (Refs β) := + (memberRefs store).findSome? fun lift => do + let refs ← refsForLift? store lift + if (kinds.map refs.ref).contains ref then some refs else none + +def typeWitnesses? (fuel : Nat) (entries : Environment β) : + List (Signature.Header β) → Option (List (Signature.TypeWitness β)) + | [] => some [] + | header :: headers => do + let inferred ← inferAnnotated? fuel header.universes entries [] header.type + let .sort level := inferred.type | none + let rest ← typeWitnesses? fuel (entries.insert header.ref header.entry) headers + return ⟨level, inferred.witness⟩ :: rest + +def ruleWitness? (fuel : Nat) (entries : Environment β) (rule : Signature.Rule β) : + Option (Signature.RuleWitness β) := do + let type ← inferAnnotated? fuel rule.universes entries [] rule.type + let .sort level := type.type | none + let lhs ← inferAnnotated? fuel rule.universes entries [] rule.lhs + let lhs ← castWith? fuel rule.universes entries [] lhs rule.type + let rhs ← inferAnnotated? fuel rule.universes entries [] rule.rhs + let rhs ← castWith? fuel rule.universes entries [] rhs rule.type + return ⟨level, type.witness, lhs, rhs⟩ + +def witness? (fuel : Nat) (entries : Environment β) (refs : Refs β) : Option (Witness β) := do + let types ← typeWitnesses? fuel entries refs.headers + let formed := refs.typeEnvironment entries + let liftRule ← ruleWitness? fuel formed refs.liftRule + let indRule ← ruleWitness? fuel formed refs.indRule + return ⟨refs, types, liftRule, indRule⟩ + +end Ix.Theory.Certificate.Quotient diff --git a/Ix/Theory/Certificate/Standard.lean b/Ix/Theory/Certificate/Standard.lean new file mode 100644 index 000000000..27a505a3f --- /dev/null +++ b/Ix/Theory/Certificate/Standard.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Suggest +import Ix.Theory.Certified.Standard.Checked + +namespace Ix.Theory.Certificate.Standard + +open Model Certified Certified.Standard Certified.Basis + +universe u +variable {β : Type u} [DecidableEq β] +variable [Hints β] + +def recursorFor? (store : Store β) (n : Nat) (type : AExpr β) : Option (ConstRef β) := + (store.dom.find? fun source => match store.blocks source with + | some ⟨[.recursor m _ _ _ _ raw _ _ .safe]⟩ => m == n && raw == type.erase + | _ => false).map (.member · 0) + +/-- Recover only known standard schemas, then require exact source erasure. +All prerequisite interfaces are checked again by standard admission. -/ +def spec? (store : Store β) (type : VExpr β) : Option (Spec β) := do + let spec ← match type with + | .forallE (.sort .zero) (.forallE (.sort .zero) (.forallE premise result)) => do + let .const iff [] := premise.appHead | none + let .const eq [.succ .zero] := result.appHead | none + let .member isource 0 := iff | none + let .member esource 0 := eq | none + let ei := ConstRef.ctor esource 0 0 + let ii := ConstRef.ctor isource 0 0 + let er ← recursorFor? store 2 (Equality.recType eq ei) + let ir ← recursorFor? store 1 (Iff.recType iff ii) + return Spec.propext eq ei er iff ii ir + | .forallE (.sort (.param 0)) (.forallE premise (.bvar 1)) => do + let .const ne [.param 0] := premise.appHead | none + let .member source 0 := ne | none + let ctor := ConstRef.ctor source 0 0 + let recursor ← recursorFor? store 1 (Nonempty.recType ne ctor) + return Spec.choice ne ctor recursor + | _ => none + if spec.type.erase = type then some spec else none + +def witness? (fuel : Nat) (store : Store β) (entries : Environment β) + (ref : ConstRef β) (source : Const β) : Option (Witness β) := do + let .axiom _ type .safe := source | none + let spec ← spec? store type + if spec.source != source then none else do + let inferred ← inferAnnotated? fuel spec.universes entries [] spec.type + let .sort level := inferred.type | none + return ⟨ref, spec, level, inferred.witness⟩ + +end Ix.Theory.Certificate.Standard diff --git a/Ix/Theory/Certificate/Structure.lean b/Ix/Theory/Certificate/Structure.lean new file mode 100644 index 000000000..2e123615b --- /dev/null +++ b/Ix/Theory/Certificate/Structure.lean @@ -0,0 +1,43 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.OrdinarySource +import Ix.Theory.Certificate.Quotient +import Ix.Theory.Certified.Structure.Publish + +namespace Ix.Theory.Certificate.Structure + +open Model Certified Certified.Structure + +universe u +variable {β : Type u} [DecidableEq β] +variable [Hints β] + +def description? (block : Certified.Ordinary.BlockWitness β) : Option (Description β) := do + let shape := block.shape.shape + let [ctor] := shape.constructors | none + let [witness] := block.shape.constructors | none + if ctor.fields.length != witness.fields.length then none else + let fields := (ctor.fields.zip witness.fields).map fun (domain, witness) => ⟨domain, witness.level⟩ + let d : Description β := ⟨shape.universes, shape.parameters, fields, shape.level⟩ + if d.ordinary = shape ∧ fields.all (checkZeroImplies shape.level ·.level) then some d else none + +/-- Recover all structure data from the already source-recovered ordinary +block, then suggest whole typing checks for its dependent projections. -/ +def witness? (fuel : Nat) (entries : Environment β) (block : Certified.Ordinary.BlockWitness β) : + Option (Witness β) := do + let d ← description? block + let [ctor] := block.shape.constructors | none + let domains ← Ordinary.domains? fuel d.universes + (d.ordinary.publishedEnvironment entries block.source block.recursor block.mode) [] + (d.projectionDomains block.source) + let facts : FactsWitness β := ⟨d, block, ctor.fields.map DomainWitness.typing, domains⟩ + let stage := d.factEnvironment entries block.source block.recursor block.mode + let eta ← Quotient.ruleWitness? fuel stage (d.etaRule block.source) + let iota ← d.fields.zipIdx.mapM fun (field, i) => Quotient.ruleWitness? fuel + (d.iotaEnvironment entries block.source block.recursor block.mode i) (d.iotaRule block.source i field) + return ⟨facts, eta, iota⟩ + +end Ix.Theory.Certificate.Structure diff --git a/Ix/Theory/Certificate/Suggest.lean b/Ix/Theory/Certificate/Suggest.lean new file mode 100644 index 000000000..1b8197d41 --- /dev/null +++ b/Ix/Theory/Certificate/Suggest.lean @@ -0,0 +1,417 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Operations + +/-! +# Untrusted certificate suggestions + +This bounded producer handles dependent functions with syntactic product +heads, conservative universe simplification, and conversion certificates. +Its output is ordinary data. +Only the certified validator can turn a suggestion into acceptance. Failure +to find a certificate is a decline and says nothing about untypability. +-/ + +namespace Ix.Theory.Certificate + +open Model Certified + +universe u +variable {β : Type u} [DecidableEq β] + +/-- Untrusted search hints. The public builder derives these from the fixed +profile; the semantic validator independently checks every resulting fact. -/ +class Hints (β : Type u) where + natural : Option (ConstRef β) + +instance (priority := low) : Hints β := ⟨none⟩ + +variable [Hints β] + +def annotations : AExpr β → AnnotationTree + | .bvar _ | .sort _ | .const .. | .natLit _ => .leaf + | .app f a => .app (annotations f) (annotations a) + | .lam p A b => .lam p.toRaw (annotations A) (annotations b) + | .forallE p A B => .forallE p.toRaw (annotations A) (annotations B) + | .proj _ _ e => .proj (annotations e) + +structure Suggestion (β : Type u) where + expression : AExpr β + type : AExpr β + witness : TypingWitness β + +/-- A limited conversion search. The validator independently rechecks every +level equality and the type of the expected type. -/ +def cast? (n : Nat) (suggestion : Suggestion β) (type : AExpr β) : Option (TypingWitness β) := + if suggestion.type = type then some suggestion.witness + else + match suggestion.type, type with + | .sort l, .sort l' => + if LevelEq.check n l l' then + some (.conv suggestion.type (.succ l') suggestion.witness .sort .sort) + else none + | _, _ => none + +def headConstant? : AExpr β → Option (ConstRef β × List VLevel) + | .const r levels => some (r, levels) + | .app f _ => headConstant? f + | _ => none + +def applicationArgs : AExpr β → List (AExpr β) → List (AExpr β) + | .app f a, args => applicationArgs f (a :: args) + | _, args => args + +def lambdaBody : AExpr β → Nat × AExpr β + | .lam _ _ body => let (n, result) := lambdaBody body; (n + 1, result) + | e => (0, e) + +/-- Collect possible arguments of a closed equation telescope. This search +does not certify matching: the fully instantiated endpoint is compared below +and every application/beta step is subsequently checked by the validator. -/ +def matchEquationArgs? : AExpr β → AExpr β → List (Option (AExpr β)) → Option (List (Option (AExpr β))) + | .bvar i, actual, slots => do + let slot ← slots[i]? + match slot with + | none => some (slots.set i (some actual)) + | some previous => if previous = actual then some slots else none + | .app f x, .app g y, slots => do + let slots ← matchEquationArgs? f g slots + matchEquationArgs? x y slots + | .const r ls, .const q ms, slots => if r = q ∧ ls = ms then some slots else none + | .sort l, .sort m, slots => if l = m then some slots else none + | .proj r i major, .proj q j actual, slots => + if r = q ∧ i = j then matchEquationArgs? major actual slots else none + | .lam .., .lam .., slots | .forallE .., .forallE .., slots => some slots + | _, _, _ => none + +def instantiateLambdas? : AExpr β → List (AExpr β) → Option (AExpr β) + | e, [] => some e + | .lam _ _ body, arg :: rest => instantiateLambdas? (body.inst arg) rest + | _, _ => none + +def equationArguments? (pattern actual : AExpr β) : Option (List (AExpr β)) := do + let (count, body) := lambdaBody pattern + let slots ← matchEquationArgs? body actual (List.replicate count none) + let args ← slots.reverse.mapM id + let instantiated ← instantiateLambdas? pattern args + if instantiated = actual then some args else none + +/-- Suggest the same equation with a different final major proof. The full +application prefix must still match exactly. A subsequent typed conversion +must justify replacing that proof; this matcher alone grants no equation. -/ +def equationProofArguments? (pattern actual : AExpr β) : Option (List (AExpr β)) := do + let (count, body) := lambdaBody pattern + let .app rulePrefix _ := body | none + let .app actualPrefix _ := actual | none + let slots ← matchEquationArgs? rulePrefix actualPrefix (List.replicate count none) + let args ← slots.reverse.mapM id + let .app instantiatedPrefix _ ← instantiateLambdas? pattern args | none + if instantiatedPrefix = actualPrefix then some args else none + +mutual +def inferSource? (fuel n : Nat) (entries : Environment β) (Γ : Context β) : + VExpr β → Option (Suggestion β) := + match fuel with + | 0 => fun _ => none + | fuel + 1 => fun source => + match source with + | .bvar i => do + let A ← Γ[i]? + return ⟨.bvar i, A, .bvar⟩ + | .sort l => + if l.WF n then some ⟨.sort l, .sort (.succ l), .sort⟩ else none + | .const r ls => do + let entry ← entries r + if ls.length = entry.universes ∧ ∀ l ∈ ls, l.WF n then + return ⟨.const r ls, entry.type.instL ls, .const⟩ + else none + | .forallE A B => do + let a ← inferSource? fuel n entries Γ A + let a ← normalizeType? fuel n entries Γ a + let .sort lA := a.type | none + let b ← inferSource? fuel n entries (Γ.push a.expression) B + let b ← normalizeType? fuel n entries (Γ.push a.expression) b + let .sort lB := b.type | none + return ⟨.forallE (zeroCondition lB) a.expression b.expression, .sort (.imax lA lB), + .forallE lA lB a.witness b.witness⟩ + | .lam A body => do + let a ← inferSource? fuel n entries Γ A + let a ← normalizeType? fuel n entries Γ a + let .sort lA := a.type | none + let b ← inferSource? fuel n entries (Γ.push a.expression) body + let b ← normalizeType? fuel n entries (Γ.push a.expression) b + let B ← inferAnnotated? fuel n entries (Γ.push a.expression) b.type + let B ← normalizeType? fuel n entries (Γ.push a.expression) B + let .sort lB := B.type | none + return ⟨.lam (zeroCondition lB) a.expression b.expression, + .forallE (zeroCondition lB) a.expression b.type, + .lam lA lB b.type a.witness B.witness b.witness⟩ + | .app f arg => do + let fn ← inferSource? fuel n entries Γ f + let fn ← normalizeType? fuel n entries Γ fn + let .forallE p A B := fn.type | none + let a ← inferSource? fuel n entries Γ arg + let aw ← castWith? fuel n entries Γ a A + return ⟨.app fn.expression a.expression, B.inst a.expression, + .app p A B fn.witness aw⟩ + | .proj ref index major => do + let major ← inferSource? fuel n entries Γ major + let typed ← normalizeType? fuel n entries Γ major + let (owner, ls) ← headConstant? typed.type + if owner != ref then none else do + let entry ← entries ref + if ls.length != entry.universes then none else + entry.facts.zipIdx.findSome? fun (fact, factIndex) => do + let .typed expression type := fact | none + let (_, .proj family field _) := lambdaBody expression | none + if family != ref || field != index then none else do + let result ← applyFact? fuel n entries Γ + ⟨expression.instL ls, type.instL ls, .fact ref factIndex ls⟩ + (applicationArgs typed.type [] ++ [major.expression]) + if result.expression = .proj ref index major.expression then some result else none + | .natLit value => do + let ref ← Hints.natural (β := β) + let entry ← entries ref + if entry.universes != 0 then none else + entry.facts.zipIdx.findSome? fun (fact, i) => match fact with + | .natural _ _ => some ⟨.natLit value, .const ref [], .natLit ref i⟩ + | _ => none + +/-- Instantiate an admitted closed typing fact using checked beta results. +The result retains the actual source projection rather than a replacement +term with a merely convertible type. -/ +def applyFact? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (fact : Suggestion β) (args : List (AExpr β)) : Option (Suggestion β) := + match fuel with + | 0 => none + | fuel + 1 => match args with + | [] => some fact + | arg :: rest => do + let .lam p D body := fact.expression | none + let .forallE q A B := fact.type | none + if p != q || D != A then none else do + let a ← inferAnnotated? fuel n entries Γ arg + let aw ← castWith? fuel n entries Γ a D + applyFact? fuel n entries Γ ⟨body.inst arg, B.inst arg, + .betaResult p D body arg B fact.witness aw⟩ rest + +def inferAnnotated? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (e : AExpr β) : Option (Suggestion β) := + match fuel with + | 0 => none + | fuel + 1 => do + let result ← inferSource? fuel n entries Γ e.erase + if result.expression = e then some result else none + +/-- Build a conversion certificate rather than normalizing away source +syntax. The semantic validator checks the target's sort independently. -/ +def castWith? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (suggestion : Suggestion β) (type : AExpr β) : Option (TypingWitness β) := + match fuel with + | 0 => none + | fuel + 1 => + match cast? n suggestion type with + | some witness => some witness + | none => do + let target ← inferAnnotated? fuel n entries Γ type + let target ← normalizeType? fuel n entries Γ target + let .sort l := target.type | none + let witness ← conversion? fuel n entries Γ suggestion.type type + return .conv suggestion.type l suggestion.witness target.witness witness + +def beta? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (e : AExpr β) : Option (AExpr β × ConversionWitness β) := + match fuel with + | 0 => none + | fuel + 1 => do + let .app (.lam p D body) arg := e | none + let fn ← inferAnnotated? fuel n entries Γ (.lam p D body) + let a ← inferAnnotated? fuel n entries Γ arg + let aw ← castWith? fuel n entries Γ a D + return (body.inst arg, .beta fn.type fn.witness aw) + +def eta? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (a b : AExpr β) : Option (ConversionWitness β) := + match fuel with + | 0 => none + | fuel + 1 => do + let .lam p D body := a | none + let fn ← inferAnnotated? fuel n entries Γ b + let fn ← normalizeType? fuel n entries Γ fn + let .forallE q D' B := fn.type | none + if p = q ∧ D = D' ∧ body = .app (b.liftN 1) (.bvar 0) then + return .eta B fn.witness + else none + +/-- A checked beta/delta step may occur in the function of an application. -/ +def headStep? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (e : AExpr β) : Option (AExpr β × ConversionWitness β) := + match fuel with + | 0 => none + | fuel + 1 => + let delta := fun (_ : Unit) => do + let .const r ls := e | none + let entry ← entries r + if ls.length != entry.universes then none else do + let body ← entry.body + return (body.instL ls, .delta) + let app := fun (_ : Unit) => do + let .app f x := e | none + let (f', w) ← headStep? fuel n entries Γ f <|> equationStep? fuel n entries Γ f + return (.app f' x, .app w .refl) + let argument := fun (_ : Unit) => do + let .app f x := e | none + let (x', w) ← headStep? fuel n entries Γ x <|> equationStep? fuel n entries Γ x + return (.app f x', .app .refl w) + let projection := fun (_ : Unit) => do + let .proj r i x := e | none + let (x', w) ← headStep? fuel n entries Γ x <|> equationStep? fuel n entries Γ x + return (.proj r i x', .proj w) + let literal := fun (_ : Unit) => do + let .natLit value := e | none + let ref ← Hints.natural (β := β) + let entry ← entries ref + if entry.universes != 0 then none else + entry.facts.zipIdx.findSome? fun (fact, i) => match fact with + | .natural zero succ => some + ((match value with | 0 => .const zero [] | n + 1 => .app (.const succ []) (.natLit n)), .natLiteral ref i) + | _ => none + beta? fuel n entries Γ e <|> delta () <|> app () <|> argument () <|> projection () <|> literal () + +def equationStep? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (e : AExpr β) : Option (AExpr β × ConversionWitness β) := + match fuel with + | 0 => none + | fuel + 1 => do + let (ref, levels) : ConstRef β × List VLevel ← match e with + | .proj ref _ major => do + let typed ← inferAnnotated? fuel n entries Γ major + let typed ← normalizeType? fuel n entries Γ typed + let (owner, levels) ← headConstant? typed.type + if owner = ref then some (ref, levels) else none + | _ => do + let (ref, levels) ← headConstant? e + let owner : ConstRef β := match ref with | .ctor source member _ => .member source member | _ => ref + some (owner, levels) + let entry ← entries ref + if levels.length != entry.universes then none else + entry.equations.zipIdx.findSome? fun (law, i) => do + let lhs := law.lhs.instL levels + let rhs := law.rhs.instL levels + let args ← equationArguments? lhs e <|> (do + let (_, .app _ constructor) := lambdaBody lhs | none + let (.ctor .., _) ← headConstant? constructor | none + let .app fn major := e | none + let expanded ← etaMajor? fuel n entries Γ major + equationArguments? lhs (.app fn expanded)) <|> (do + let .app _ major := e | none + let typed ← inferAnnotated? fuel n entries Γ major + let type ← inferAnnotated? fuel n entries Γ typed.type + let _ ← cast? n type (.sort .zero) + equationProofArguments? lhs e) + let lhsApplied := args.foldl AExpr.app lhs + let rhsApplied := args.foldl AExpr.app rhs + let beta ← conversion? fuel n entries Γ lhsApplied e + let equation := args.foldl (fun w _ => ConversionWitness.app w .refl) (.equation ref i levels) + return (rhsApplied, .trans lhsApplied (.symm beta) equation) + +/-- A stuck eliminator may use an existing structure's checked eta equation +to expose its constructor. This only suggests arguments: `equationStep?` +still constructs and checks conversion of the complete original application +to the chosen rule's complete instantiated left side. Model companions with +no eta equation cannot acquire this behavior from the search. -/ +def etaMajor? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (major : AExpr β) : Option (AExpr β) := + match fuel with + | 0 => none + | fuel + 1 => do + let typed ← inferAnnotated? fuel n entries Γ major + let typed ← normalizeType? fuel n entries Γ typed + let (family, levels) ← headConstant? typed.type + let entry ← entries family + if levels.length != entry.universes then none else + entry.equations.findSome? fun law => do + let arguments := applicationArgs typed.type [] ++ [major] + let rhs ← instantiateLambdas? (law.rhs.instL levels) arguments + if rhs != major then none else do + let lhs ← instantiateLambdas? (law.lhs.instL levels) arguments + if lhs = major then none else some lhs + +/-- Reduction of an inferred type is accompanied by a conversion witness +and a fresh formation witness for the resulting type. -/ +def normalizeType? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (suggestion : Suggestion β) : Option (Suggestion β) := + match fuel with + | 0 => none + | fuel + 1 => + match suggestion.type with + | .sort _ | .forallE .. => some suggestion + | _ => + match headStep? fuel n entries Γ suggestion.type <|> equationStep? fuel n entries Γ suggestion.type with + | none => some suggestion + | some (type, conversion) => do + let formed ← inferAnnotated? fuel n entries Γ type + let formed ← normalizeType? fuel n entries Γ formed + let .sort level := formed.type | none + normalizeType? fuel n entries Γ + ⟨suggestion.expression, type, .conv suggestion.type level suggestion.witness formed.witness conversion⟩ + +def conversion? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (a b : AExpr β) : Option (ConversionWitness β) := + match fuel with + | 0 => none + | fuel + 1 => + if a = b then some .refl + else + -- Once a checked reduction is available, follow it without exploring + -- alternate reduction orders again after fuel exhaustion. + match headStep? fuel n entries Γ a with + | some (a', w) => do return .trans a' w (← conversion? fuel n entries Γ a' b) + | none => match headStep? fuel n entries Γ b with + | some (b', w) => do return .trans b' (← conversion? fuel n entries Γ a b') (.symm w) + | none => + let congruence := fun (_ : Unit) => + match a, b with + | .sort l, .sort l' => if LevelEq.check n l l' then some .sort else none + | .app f x, .app g y => do + return .app (← conversion? fuel n entries Γ f g) (← conversion? fuel n entries Γ x y) + | .proj r i x, .proj q j y => + if r = q ∧ i = j then (.proj ·) <$> conversion? fuel n entries Γ x y else none + | .lam p D body, .lam q D' body' => do + if p != q then none else do + let domain ← inferAnnotated? fuel n entries Γ D + let .sort l := domain.type | none + return .lam l domain.witness (← conversion? fuel n entries Γ D D') + (← conversion? fuel n entries (Γ.push D) body body') + | .forallE p D B, .forallE q D' B' => do + if p != q then none else do + let domain ← inferAnnotated? fuel n entries Γ D + let .sort l := domain.type | none + return .forallE l domain.witness (← conversion? fuel n entries Γ D D') + (← conversion? fuel n entries (Γ.push D) B B') + | _, _ => none + let proofIrrel := fun (_ : Unit) => do + let left ← inferAnnotated? fuel n entries Γ a + let type ← inferAnnotated? fuel n entries Γ left.type + let typeWitness ← cast? n type (.sort .zero) + let right ← inferAnnotated? fuel n entries Γ b + let rightWitness ← castWith? fuel n entries Γ right left.type + return .proofIrrel left.type typeWitness left.witness rightWitness + eta? fuel n entries Γ a b <|> + ((.symm ·) <$> eta? fuel n entries Γ b a) <|> congruence () <|> + (match equationStep? fuel n entries Γ a with + | some (a', w) => do return .trans a' w (← conversion? fuel n entries Γ a' b) + | none => match equationStep? fuel n entries Γ b with + | some (b', w) => do return .trans b' (← conversion? fuel n entries Γ a b') (.symm w) + | none => proofIrrel ()) +end + +def inferenceWitness? (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (source : VExpr β) : Option (InferenceWitness β) := do + let suggestion ← inferSource? fuel n entries Γ source + return ⟨annotations suggestion.expression, suggestion.type, suggestion.witness⟩ + +end Ix.Theory.Certificate diff --git a/Ix/Theory/Certified.lean b/Ix/Theory/Certified.lean new file mode 100644 index 000000000..0f772d961 --- /dev/null +++ b/Ix/Theory/Certified.lean @@ -0,0 +1,48 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Accept +import Ix.Theory.Certified.Store +import Ix.Theory.Certified.Source +import Ix.Theory.Certified.ClaimComposition +import Ix.Theory.Certified.Operations +import Ix.Theory.Certified.Ordinary.Admission + +/-! +# Certified-profile mathematical boundary + +This target exports a witness validator for dependent functions, declaration +admission with compatible model extension, and abstract acceptance/model and +no-False theorems over exact Ix syntax. Declaration checking also constructs +one compatible model for every requested member and constructor. Connecting +these results to canonical serialized input and the production Ix.Kernel checker +requires a separate adapter and refinement proof. Conditional claims check formed +source headers and extend every compatible frontier model. Aggregation checks +an acyclic provider order and replays admissions in one shared interface; +closed bundles construct their model and retain all logical axiom use. The +Ix claim/byte adapter and backend acceptance have separate refinement roots. + +Ordinary-inductive admission constructs indexed carriers and eliminators, +checks the exact source and stored recursor types and rule endpoints, and +publishes their proved equations atomically. The supported shape class uses +ordinary fields followed by independent strictly positive recursive fields. +Standard propext and choice admission checks exact types and prerequisite +interfaces and constructs their realizations. Eq K uses typed proof +irrelevance with admitted computation. Quotient admission constructs its +carrier, constructor, lift, Prop induction and soundness values and proves +the complete computation equations. Structure admission produces dependent +projection facts and whole eta/iota equations, including the checked Prop +field restriction. Nat admission pins the zero/successor source and proves +membership and constructor conversion for every numeral. Mutual/nested +admission checks companions in an earlier model environment and validates +their complete translated source equations before simultaneous publication. +Reference restoration, permutation and shared model values have proved +semantic transport laws. This route supplies no projection, eta or K facts +for the new families. Other literal forms still need separate producers. + +The semantic results explicitly quantify over `V` and `[Model.SetTheory V]`. +The existence of this set-theoretic model is a mathematical hypothesis, not a +theorem of Lean. Audit tooling and experimental metatheory are separate targets. +-/ diff --git a/Ix/Theory/Certified/Accept.lean b/Ix/Theory/Certified/Accept.lean new file mode 100644 index 000000000..fe209ea45 --- /dev/null +++ b/Ix/Theory/Certified/Accept.lean @@ -0,0 +1,139 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Admission + +/-! +# Closed acceptance of the certified profile + +Acceptance checks the exact primitive declarations, a dependency-ordered list +of safe definitions and modeled ordinary blocks, the original proof and proposition readings, +and both typing certificates. It constructs its dependency model and starts +from the empty context. This is an abstract Ix-syntax acceptance result; +serialized bytes, Ix.Kernel execution, claims, and proving backends need their own +refinement theorems. +-/ + +namespace Ix.Theory.Certified + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +structure ProofInput (β : Type u) where + store : Store β + universes : Nat + proof : VExpr β + proposition : VExpr β + +structure ProofWitness (β : Type u) where + declarations : List (DeclarationWitness β) + proofAnnotations : AnnotationTree + propositionAnnotations : AnnotationTree + proofWitness : TypingWitness β + propositionWitness : TypingWitness β + +structure CheckedProof (signature : PrimitiveSignature β) (input : ProofInput β) where + environment : AdmittedEnvironment.{u,v} signature input.store + proof : Reading input.universes 0 input.proof + proposition : Reading input.universes 0 input.proposition + proofReferences : proof.val.ReferencesIn environment.entries + propositionReferences : proposition.val.ReferencesIn environment.entries + typing : TypingClaim.{u,v} environment.entries [] proof.val proposition.val + isProp : TypingClaim.{u,v} environment.entries [] proposition.val (.sort .zero) + +def checkProofCertified (fuel : Nat) (signature : PrimitiveSignature β) + (input : ProofInput β) (witness : ProofWitness β) : + Option (CheckedProof.{u,v} signature input) := do + let initial ← initialize? signature input.store + let declarations ← admitDeclarations? fuel initial witness.declarations + let proof ← readAnnotations? input.universes 0 input.proof witness.proofAnnotations + let proposition ← readAnnotations? input.universes 0 input.proposition witness.propositionAnnotations + if he : proof.val.ReferencesIn declarations.val.entries then + if hP : proposition.val.ReferencesIn declarations.val.entries then do + let hp ← verifyType.{u,v} fuel input.universes declarations.val.entries [] + proposition.val (.sort .zero) witness.propositionWitness + let ht ← verifyType.{u,v} fuel input.universes declarations.val.entries [] + proof.val proposition.val witness.proofWitness + return ⟨declarations.val, proof, proposition, he, hP, ht.down, hp.down⟩ + else none + else none + +def acceptsCertified (fuel : Nat) (signature : PrimitiveSignature β) + (input : ProofInput β) (witness : ProofWitness β) : Bool := + (checkProofCertified.{u,v} fuel signature input witness).isSome + +/-- Acceptance constructs the model; it does not ask the caller to supply a +realization of unchecked declarations, annotations, or a nonempty context. -/ +theorem accepted_has_model {fuel : Nat} {signature : PrimitiveSignature β} + {input : ProofInput β} {witness : ProofWitness β} + (h : acceptsCertified.{u,v} fuel signature input witness = true) + (V : Type v) [SetTheory V] (levels : List Nat) (env : Nat → V) : + ∃ result : CheckedProof.{u,v} signature input, + checkProofCertified fuel signature input witness = some result ∧ + ∃ constants : Assignment β V, signature.Compatible result.environment.entries constants ∧ + WellDenoted constants levels env result.proof.val ∧ + WellDenoted constants levels env result.proposition.val ∧ + interp constants levels env result.proof.val ∈ˢ + interp constants levels env result.proposition.val := by + unfold acceptsCertified at h + cases hc : checkProofCertified.{u,v} fuel signature input witness with + | none => simp [hc] at h + | some result => + obtain ⟨constants, hM⟩ := result.environment.model V + exact ⟨result, rfl, constants, hM, + result.typing V constants hM.realizes levels env (Context.valid_nil constants levels env)⟩ + +/-- The accepted proposition is inhabited in every compatible interpretation +of the checked dependency interface, not only in the model chosen above. -/ +theorem accepted_proof_sound {fuel : Nat} {signature : PrimitiveSignature β} + {input : ProofInput β} {witness : ProofWitness β} + (h : acceptsCertified.{u,v} fuel signature input witness = true) : + ∃ result : CheckedProof.{u,v} signature input, + checkProofCertified fuel signature input witness = some result ∧ + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + signature.Compatible result.environment.entries constants → ∀ levels env, + interp constants levels env result.proof.val ∈ˢ + interp constants levels env result.proposition.val := by + unfold acceptsCertified at h + cases hc : checkProofCertified.{u,v} fuel signature input witness with + | none => simp [hc] at h + | some result => + refine ⟨result, rfl, ?_⟩ + intro V _ constants hM levels env + exact (result.typing V constants hM.realizes levels env + (Context.valid_nil constants levels env)).2.2 + +theorem no_proof_of_False {fuel : Nat} {signature : PrimitiveSignature β} + {input : ProofInput β} {witness : ProofWitness β} + (V : Type v) [SetTheory V] + (hFalse : input.proposition = signature.falseExpr) + (h : acceptsCertified.{u,v} fuel signature input witness = true) : False := by + obtain ⟨result, _, constants, hM, _, _, hmem⟩ := + accepted_has_model h V [] (fun _ => empty) + have herase : result.proposition.val.erase = .const signature.falseType [] := + result.proposition.property.1.trans hFalse + have he := AExpr.eq_const_of_erase_eq herase + rw [he] at hmem + simp only [interp, List.map_nil, hM.falseValue] at hmem + exact not_mem_empty _ hmem + +/-- A source-level empty proposition can also be reached through certified +definitions or conversions. Its semantic emptiness contradicts acceptance. -/ +theorem no_proof_of_empty {fuel : Nat} {signature : PrimitiveSignature β} + {input : ProofInput β} {witness : ProofWitness β} + (V : Type v) [SetTheory V] + (hempty : ∀ result : CheckedProof.{u,v} signature input, + checkProofCertified fuel signature input witness = some result → + ∀ constants : Assignment β V, signature.Compatible result.environment.entries constants → + interp constants [] (fun _ => empty) result.proposition.val = empty) + (h : acceptsCertified.{u,v} fuel signature input witness = true) : False := by + obtain ⟨result, hc, constants, hM, _, _, hmem⟩ := + accepted_has_model h V [] (fun _ => empty) + rw [hempty result hc constants hM] at hmem + exact not_mem_empty _ hmem + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Admission.lean b/Ix/Theory/Certified/Admission.lean new file mode 100644 index 000000000..a993c1ddb --- /dev/null +++ b/Ix/Theory/Certified/Admission.lean @@ -0,0 +1,245 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Checker +import Ix.Theory.Certified.Prelude +import Ix.Theory.Certified.Ordinary.Checked +import Ix.Theory.Certified.Standard.Checked +import Ix.Theory.Certified.Quotient.Publish +import Ix.Theory.Certified.Structure.Publish +import Ix.Theory.Certified.Natural.Publish +import Ix.Theory.Certified.Modeled.Source + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +def DefinitionReading.entry (reading : DefinitionReading β) : ConstantEntry β := + ⟨reading.universes, reading.type, some reading.body, [], []⟩ + +/-- Every published dependency has an exact source declaration in the input +store. The two exceptional forms are the completely pinned primitives. -/ +def EntrySource (signature : PrimitiveSignature β) (store : Store β) + (r : ConstRef β) (entry : ConstantEntry β) : Prop := + (r = signature.falseType ∧ entry = PrimitiveSignature.falseEntry ∧ + store.lookup r = some PrimitiveSignature.falseDeclaration) ∨ + (r = signature.falseElim ∧ entry = signature.falseElimEntry ∧ + store.lookup r = some signature.falseElimDeclaration) ∨ + (∃ (kind : DefKind) (body : AExpr β), entry.body = some body ∧ + entry.equations = [] ∧ entry.facts = [] ∧ + store.lookup r = some (.defn entry.universes kind entry.type.erase body.erase .safe)) ∨ + Ordinary.EntrySource store r entry ∨ Standard.EntrySource store r entry ∨ + Quotient.EntrySource store r entry ∨ Structure.EntrySource store r entry ∨ + Natural.EntrySource signature.natType store r entry ∨ Modeled.EntrySource store r entry + +/-- An interface may be an explicit conditional frontier. Scope and reference +closure are checked here; existence of a realization is a separate obligation. -/ +structure CheckedInterface (signature : PrimitiveSignature β) where + entries : Environment β + wf : entries.WF + present : signature.Present entries + +/-- The model field is produced by the initialization and admission functions, +starting with the fixed prelude and extending it with checked bodies. -/ +structure AdmittedEnvironment (signature : PrimitiveSignature β) (store : Store β) where + entries : Environment β + wf : entries.WF + present : signature.Present entries + source : ∀ r entry, entries r = some entry → EntrySource signature store r entry + model : ∀ (V : Type v) [SetTheory V], ∃ constants : Assignment β V, + signature.Compatible entries constants + +def AdmittedEnvironment.interface {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) : CheckedInterface signature := + ⟨state.entries, state.wf, state.present⟩ + +/-- An extension preserves each previously selected interpretation. -/ +structure Extends (signature : PrimitiveSignature β) (entries entries' : Environment β) : Prop where + lookup : ∀ r entry, entries r = some entry → entries' r = some entry + models : ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + signature.Compatible entries constants → ∃ constants' : Assignment β V, + signature.Compatible entries' constants' ∧ Assignment.AgreesOn entries constants constants' + +omit [DecidableEq β] in +theorem Extends.refl (signature : PrimitiveSignature β) (entries : Environment β) : + Extends.{u,v} signature entries entries := + ⟨fun _ _ h => h, fun _ _ constants h => ⟨constants, h, fun _ _ _ _ => rfl⟩⟩ + +omit [DecidableEq β] in +theorem Extends.trans {signature : PrimitiveSignature β} {a b c : Environment β} + (hab : Extends.{u,v} signature a b) (hbc : Extends.{u,v} signature b c) : + Extends.{u,v} signature a c := by + refine ⟨fun r entry h => hbc.lookup r entry (hab.lookup r entry h), ?_⟩ + intro V _ constants hM + obtain ⟨constants', hM', hagree⟩ := hab.models V constants hM + obtain ⟨constants'', hM'', hagree'⟩ := hbc.models V constants' hM' + refine ⟨constants'', hM'', ?_⟩ + intro r entry hr levels + exact (hagree' r entry (hab.lookup r entry hr) levels).trans (hagree r entry hr levels) + +/-- Admission checks and their universal extension theorem do not require a +model of a deferred frontier. Every newly published entry has a checked source; +an existing frontier entry retains its exact interface. -/ +structure CheckedExtension (signature : PrimitiveSignature β) (store : Store β) + (input : CheckedInterface signature) where + result : CheckedInterface signature + extension : Extends.{u,v} signature input.entries result.entries + source : ∀ r entry, result.entries r = some entry → + input.entries r = some entry ∨ EntrySource signature store r entry + +def CheckedExtension.refl {signature : PrimitiveSignature β} {store : Store β} + (input : CheckedInterface signature) : CheckedExtension.{u,v} signature store input := + ⟨input, Extends.refl signature input.entries, fun _ _ h => Or.inl h⟩ + +def CheckedExtension.trans {signature : PrimitiveSignature β} {store : Store β} + {input : CheckedInterface signature} (first : CheckedExtension.{u,v} signature store input) + (second : CheckedExtension.{u,v} signature store first.result) : + CheckedExtension.{u,v} signature store input where + result := second.result + extension := first.extension.trans second.extension + source := by + intro r entry h + rcases second.source r entry h with old | new + · exact first.source r entry old + · exact Or.inr new + +/-- A closed admission uses the same checked extension and supplies the model +and source provenance constructed by its earlier successful admissions. -/ +def CheckedExtension.admit {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) + (checked : CheckedExtension.{u,v} signature store state.interface) : + { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := + ⟨{ + entries := checked.result.entries + wf := checked.result.wf + present := checked.result.present + source := by + intro r entry h + rcases checked.source r entry h with old | new + · exact state.source r entry old + · exact new + model := by + intro V _ + obtain ⟨constants, hM⟩ := state.model V + obtain ⟨constants', hM', _⟩ := checked.extension.models V constants hM + exact ⟨constants', hM'⟩ + }, checked.extension⟩ + +def initialize? (signature : PrimitiveSignature β) (store : Store β) : + Option (AdmittedEnvironment.{u,v} signature store) := + if h : signature.validate store = true then + some { + entries := signature.environment + wf := signature.environment_wf + present := signature.present_environment + source := by + intro r entry hr + have hv := (signature.validate_iff store).mp h + unfold PrimitiveSignature.environment at hr + split at hr + next he => + subst r + cases Option.some.inj hr + exact Or.inl ⟨rfl, rfl, hv.1⟩ + next => + split at hr + next he => + subst r + cases Option.some.inj hr + exact Or.inr (Or.inl ⟨rfl, rfl, hv.2⟩) + next => contradiction + model := fun V _ => ⟨signature.assignment, signature.compatible_assignment⟩ + } + else none + +structure DefinitionWitness (β : Type u) where + ref : ConstRef β + typeAnnotations : AnnotationTree + bodyAnnotations : AnnotationTree + typeLevel : VLevel + typeWitness : TypingWitness β + bodyWitness : TypingWitness β + +def checkDefinitionExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (witness : DefinitionWitness β) : + Option (CheckedExtension.{u,v} signature store state) := + match hs : store.lookup witness.ref with + | none => none + | some source => do + let reading : { reading : DefinitionReading β // reading.erase = source } ← + readDefinition? source witness.typeAnnotations witness.bodyAnnotations + let entry := reading.val.entry + if fresh : state.entries witness.ref = none then + if hTr : reading.val.type.ReferencesIn state.entries then + if hBr : reading.val.body.ReferencesIn state.entries then do + let hT ← verifyType.{u,v} fuel reading.val.universes state.entries [] + reading.val.type (.sort witness.typeLevel) witness.typeWitness + let hB ← verifyType.{u,v} fuel reading.val.universes state.entries [] + reading.val.body reading.val.type witness.bodyWitness + have extension : Extends.{u,v} signature state.entries + (state.entries.insert witness.ref entry) := by + refine ⟨fun _ _ h => Environment.insert_old fresh h, ?_⟩ + intro V _ constants hM + obtain ⟨constants', hM', hagree⟩ := extend_definition (entry := entry) state.wf fresh rfl rfl rfl + reading.val.bodyScope hTr hBr hT.down hB.down constants hM.realizes + exact ⟨constants', hM.extend signature state.present hM' hagree, hagree⟩ + let result : CheckedInterface signature := { + entries := state.entries.insert witness.ref entry + wf := state.wf.insert reading.val.typeScope + (fun body hb => by cases Option.some.inj hb; exact reading.val.bodyScope) + hTr (fun body hb => by cases Option.some.inj hb; exact hBr) + (by simp [entry, DefinitionReading.entry]) + (by simp [entry, DefinitionReading.entry]) + (by simp [entry, DefinitionReading.entry]) + (by simp [entry, DefinitionReading.entry]) + present := state.present.insert signature fresh + } + return { + result, extension + source := by + intro r old h + dsimp only [result] at h + unfold Environment.insert at h + split at h + next hr => + subst r + cases Option.some.inj h + refine Or.inr (Or.inr (Or.inr (Or.inl ⟨reading.val.kind, reading.val.body, rfl, rfl, rfl, ?_⟩))) + exact hs.trans (congrArg some reading.property.symm) + next => exact Or.inl h + } + else none + else none + else none + +def admitDefinition? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : DefinitionWitness β) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkDefinitionExtension?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +def admitDefinitions? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) : + List (DefinitionWitness β) → + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } + | [] => some ⟨state, Extends.refl signature state.entries⟩ + | witness :: rest => do + let step ← admitDefinition? fuel state witness + let rest ← admitDefinitions? fuel step.val rest + return ⟨rest.val, step.property.trans rest.property⟩ + +theorem admitDefinition?_extends {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {state : AdmittedEnvironment.{u,v} signature store} + {witness : DefinitionWitness β} {result} + (_ : admitDefinition? fuel state witness = some result) : + Extends.{u,v} signature state.entries result.val.entries := result.property + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Basis/Equality.lean b/Ix/Theory/Certified/Basis/Equality.lean new file mode 100644 index 000000000..bedac20da --- /dev/null +++ b/Ix/Theory/Certified/Basis/Equality.lean @@ -0,0 +1,199 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Basis.Interface +import Ix.Theory.Certified.Ordinary.Checked + +/-! Equality's meaning follows from the admitted former, reflexivity and +dependent eliminator types, in every compatible model. It does not assume +that an arbitrary prefix assignment is the model chosen by one producer. -/ + +namespace Ix.Theory.Certified.Basis.Equality + +open Model Model.SetTheory Model.SetModel + +universe u v +variable {β : Type u} + +def shape : Ordinary.Shape β := + ⟨1, [.sort (.param 0), .bvar 0], [.bvar 1], .zero, [⟨[], [], [.bvar 0]⟩]⟩ + +def type : AExpr β := + .forallE .never (.sort (.param 0)) + (.forallE .never (.bvar 0) (.forallE .never (.bvar 1) (.sort .zero))) + +def applied (family : ConstRef β) (l : VLevel) (A a b : AExpr β) : AExpr β := + .appN (.const family [l]) [A, a, b] + +def reflexivity (refl : ConstRef β) (l : VLevel) (A a : AExpr β) : AExpr β := + .appN (.const refl [l]) [A, a] + +def reflType (family : ConstRef β) : AExpr β := + .forallE .always (.sort (.param 0)) (.forallE .always (.bvar 0) + (applied family (.param 0) (.bvar 1) (.bvar 0) (.bvar 0))) + +def recType (family refl : ConstRef β) : AExpr β := + .forallE (.param 0) (.sort (.param 1)) <| + .forallE (.param 0) (.bvar 0) <| + .forallE (.param 0) + (.forallE .never (.bvar 1) + (.forallE .never (applied family (.param 1) (.bvar 2) (.bvar 1) (.bvar 0)) (.sort (.param 0)))) <| + .forallE (.param 0) + (.appN (.bvar 0) [.bvar 1, reflexivity refl (.param 1) (.bvar 2) (.bvar 1)]) <| + .forallE (.param 0) (.bvar 3) <| + .forallE (.param 0) (applied family (.param 1) (.bvar 4) (.bvar 3) (.bvar 0)) <| + .appN (.bvar 3) [.bvar 1, .bvar 0] + +structure Interface (entries : Environment β) (family refl recursor : ConstRef β) : Prop where + former : entries.HasType family 1 type + reflexivity : entries.HasType refl 1 (reflType family) + elimination : entries.HasType recursor 2 (recType family refl) + +instance [DecidableEq β] (entries : Environment β) (family refl recursor : ConstRef β) : + Decidable (Interface entries family refl recursor) := + decidable_of_iff (entries.HasType family 1 type ∧ entries.HasType refl 1 (reflType family) ∧ + entries.HasType recursor 2 (recType family refl)) + ⟨fun h => ⟨h.1, h.2.1, h.2.2⟩, fun h => ⟨h.former, h.reflexivity, h.elimination⟩⟩ + +theorem shape_type : (shape : Ordinary.Shape β).type = type := rfl + +theorem shape_reflType (source : β) : + (⟨[], [], [.bvar 0]⟩ : Ordinary.Constructor β).type shape source = + reflType (.member source 0) := rfl + +theorem shape_recType (source : β) : shape.recursorType source .large = + recType (.member source 0) (.ctor source 0 0) := rfl + +theorem Interface.of_checked [DecidableEq β] {entries : Environment β} {store : Store β} {source recursor : β} + (h : Ordinary.CheckedBlock.{u,v} entries store source recursor shape .large) : + Interface (shape.publishedEnvironment entries source recursor .large) + (.member source 0) (.ctor source 0 0) (.member recursor 0) := by + constructor + · refine ⟨shape.familyEntry, ?_, rfl, shape_type⟩ + exact Environment.insert_old h.recursorChecked.fresh + (Environment.overlay_old (Ordinary.Shape.constructorEntries_fresh h.shapeChecked) + (Environment.insert_same ..)) + · refine ⟨shape.constructorEntry source ⟨[], [], [.bvar 0]⟩, ?_, rfl, shape_reflType source⟩ + apply Environment.insert_old h.recursorChecked.fresh + apply Environment.overlay_new + simp [Ordinary.Shape.constructorEntries, shape] + · exact ⟨shape.publishedRecursorEntry source recursor .large, + Environment.insert_same .., rfl, shape_recType source⟩ + +theorem Interface.of_extension {entries next : Environment β} {family refl recursor : ConstRef β} + (h : Interface entries family refl recursor) + (hext : ∀ r entry, entries r = some entry → next r = some entry) : + Interface next family refl recursor := by + constructor + all_goals + first + | obtain ⟨entry, he, hn, ht⟩ := h.former + exact ⟨entry, hext _ _ he, hn, ht⟩ + | obtain ⟨entry, he, hn, ht⟩ := h.reflexivity + exact ⟨entry, hext _ _ he, hn, ht⟩ + | obtain ⟨entry, he, hn, ht⟩ := h.elimination + exact ⟨entry, hext _ _ he, hn, ht⟩ + +variable {V : Type v} [SetTheory V] + +noncomputable def value (constants : Assignment β V) (family : ConstRef β) + (u : Nat) (A a b : V) : V := app (app (app (constants family [u]) A) a) b + +noncomputable def reflValue (constants : Assignment β V) (refl : ConstRef β) + (u : Nat) (A a : V) : V := app (app (constants refl [u]) A) a + +theorem type_interp (constants : Assignment β V) (u : Nat) (env : Nat → V) : + interp constants [u] env (type : AExpr β) = + piR 1 (univ u) (fun A => piR 1 A (fun _ => piR 1 A (fun _ => univZero))) := by + simp [type, interp, VLevel.eval, Valuation.cons, univ_zero] + +theorem reflType_interp (constants : Assignment β V) (family : ConstRef β) + (u : Nat) (env : Nat → V) : + interp constants [u] env (reflType family) = + piR 0 (univ u) (fun A => piR 0 A (fun a => value constants family u A a a)) := by + simp [reflType, applied, AExpr.appN, value, interp, VLevel.eval, Valuation.cons] + +theorem recType_zero_interp (constants : Assignment β V) (family refl : ConstRef β) + (u : Nat) (env : Nat → V) : + interp constants [0, u] env (recType family refl) = + piR 0 (univ u) (fun A => piR 0 A (fun a => + piR 0 (piR 1 A (fun b => piR 1 (value constants family u A a b) (fun _ => univZero))) + (fun motive => piR 0 (app (app motive a) (reflValue constants refl u A a)) + (fun _ => piR 0 A (fun b => piR 0 (value constants family u A a b) + (fun h => app (app motive b) h)))))) := by + simp [recType, applied, reflexivity, AExpr.appN, value, reflValue, interp, VLevel.eval, + Valuation.cons, regime, PropWhen.param, PropWhen.holds, univ_zero] + +variable {entries : Environment β} {family refl recursor : ConstRef β} + {constants : Assignment β V} + +theorem value_mem_univZero (h : Interface entries family refl recursor) (hM : Realizes constants entries) + {u : Nat} {A a b : V} (hA : A ∈ˢ univ u) (ha : a ∈ˢ A) (hb : b ∈ˢ A) : + value constants family u A a b ∈ˢ univZero := by + have ht := h.former.member hM (levels := [u]) rfl (fun _ => empty) + rw [type_interp] at ht + have h1 : app (constants family [u]) A ∈ˢ + piR 1 A (fun _ => piR 1 A (fun _ => univZero)) := + app_mem_piR_pos (by decide : 1 ≠ 0) ht hA + have h2 : app (app (constants family [u]) A) a ∈ˢ piR 1 A (fun _ => univZero) := + app_mem_piR_pos (by decide : 1 ≠ 0) h1 ha + exact app_mem_piR_pos (by decide : 1 ≠ 0) h2 hb + +theorem reflValue_mem (h : Interface entries family refl recursor) (hM : Realizes constants entries) + {u : Nat} {A a : V} (hA : A ∈ˢ univ u) (ha : a ∈ˢ A) : + reflValue constants refl u A a ∈ˢ value constants family u A a a := by + have ht := h.reflexivity.member hM (levels := [u]) rfl (fun _ => empty) + rw [reflType_interp] at ht + have h1 : app (constants refl [u]) A ∈ˢ piR 0 A (fun x => value constants family u A x x) := + app_mem_piR ht hA (fun _ _ _ => piR_zero_mem_univZero) + exact app_mem_piR (B := fun x => value constants family u A x x) h1 ha + (fun _ b hb => value_mem_univZero h hM hA hb hb) + +theorem exists_of_mem_piR_zero {A f a : V} {B : V → V} + (hf : f ∈ˢ piR 0 A B) (ha : a ∈ˢ A) : ∃ b, b ∈ˢ B a := by + rw [piR_zero] at hf + exact of_mem_truthVal hf a ha + +theorem eq_of_mem (h : Interface entries family refl recursor) (hM : Realizes constants entries) + {u : Nat} {A a b proof : V} (hA : A ∈ˢ univ u) (ha : a ∈ˢ A) (hb : b ∈ˢ A) + (hp : proof ∈ˢ value constants family u A a b) : a = b := by + let motive := lamR 1 A (fun b => lamR 1 (value constants family u A a b) (fun _ => eqv a b)) + have hm : motive ∈ˢ piR 1 A (fun b => + piR 1 (value constants family u A a b) (fun _ => univZero)) := + lamR_mem fun _ _ => lamR_mem fun _ _ => eqv_mem_univZero _ _ + have hbeta (x q : V) (hx : x ∈ˢ A) (hq : q ∈ˢ value constants family u A a x) : + app (app motive x) q = eqv a x := by + rw [app_lamR_pos (by decide : 1 ≠ 0) hx, app_lamR_pos (by decide : 1 ≠ 0) hq] + have hminor : (pt : V) ∈ˢ app (app motive a) (reflValue constants refl u A a) := by + rw [hbeta _ _ ha (reflValue_mem h hM hA ha)] + exact pt_mem_eqv_self _ + have hr := h.elimination.member hM (levels := [0, u]) rfl (fun _ => empty) + rw [recType_zero_interp] at hr + obtain ⟨rA, hrA⟩ := exists_of_mem_piR_zero hr hA + obtain ⟨ra, hra⟩ := exists_of_mem_piR_zero hrA ha + obtain ⟨rm, hrm⟩ := exists_of_mem_piR_zero hra hm + obtain ⟨ri, hri⟩ := exists_of_mem_piR_zero hrm hminor + obtain ⟨rb, hrb⟩ := exists_of_mem_piR_zero hri hb + obtain ⟨result, hresult⟩ := exists_of_mem_piR_zero hrb hp + rw [hbeta _ _ hb hp] at hresult + exact eq_of_mem_eqv hresult + +/-- The prerequisite needed by standard axiom realizations is derived from +admitted types. No equality-meaning oracle is added to the prefix model. -/ +theorem value_eq_eqv (h : Interface entries family refl recursor) (hM : Realizes constants entries) + {u : Nat} {A a b : V} (hA : A ∈ˢ univ u) (ha : a ∈ˢ A) (hb : b ∈ˢ A) : + value constants family u A a b = eqv a b := by + apply univZero_ext (value_mem_univZero h hM hA ha hb) (eqv_mem_univZero _ _) + · intro hp + have he := eq_of_mem h hM hA ha hb hp + subst b + exact pt_mem_eqv_self _ + · intro hp + have he := eq_of_mem_eqv hp + subst b + have hr := reflValue_mem h hM hA ha + rwa [eq_pt_of_mem_univZero (value_mem_univZero h hM hA ha ha) hr] at hr + +end Ix.Theory.Certified.Basis.Equality diff --git a/Ix/Theory/Certified/Basis/Iff.lean b/Ix/Theory/Certified/Basis/Iff.lean new file mode 100644 index 000000000..e5209ba86 --- /dev/null +++ b/Ix/Theory/Certified/Basis/Iff.lean @@ -0,0 +1,171 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Basis.Equality + +namespace Ix.Theory.Certified.Basis.Iff + +open Model Model.SetTheory Model.SetModel + +universe u v +variable {β : Type u} + +def arrow (P Q : AExpr β) : AExpr β := .forallE .always P (Q.liftN 1) + +def constructor : Ordinary.Constructor β := + ⟨[arrow (.bvar 1) (.bvar 0), arrow (.bvar 1) (.bvar 2)], [], []⟩ + +def shape : Ordinary.Shape β := ⟨0, [.sort .zero, .sort .zero], [], .zero, [constructor]⟩ + +def type : AExpr β := + .forallE .never (.sort .zero) (.forallE .never (.sort .zero) (.sort .zero)) + +def applied (family : ConstRef β) (P Q : AExpr β) : AExpr β := .appN (.const family []) [P, Q] + +def introduction (ctor : ConstRef β) (P Q f g : AExpr β) : AExpr β := + .appN (.const ctor []) [P, Q, f, g] + +def introType (family : ConstRef β) : AExpr β := + .forallE .always (.sort .zero) <| .forallE .always (.sort .zero) <| + .forallE .always (arrow (.bvar 1) (.bvar 0)) <| + .forallE .always (arrow (.bvar 1) (.bvar 2)) <| + applied family (.bvar 3) (.bvar 2) + +def recType (family ctor : ConstRef β) : AExpr β := + .forallE (.param 0) (.sort .zero) <| .forallE (.param 0) (.sort .zero) <| + .forallE (.param 0) (.forallE .never (applied family (.bvar 1) (.bvar 0)) (.sort (.param 0))) <| + .forallE (.param 0) + (.forallE (.param 0) (arrow (.bvar 2) (.bvar 1)) + (.forallE (.param 0) (arrow (.bvar 2) (.bvar 3)) + (.app (.bvar 2) (introduction ctor (.bvar 4) (.bvar 3) (.bvar 1) (.bvar 0))))) <| + .forallE (.param 0) (applied family (.bvar 3) (.bvar 2)) <| + .app (.bvar 2) (.bvar 0) + +structure Interface (entries : Environment β) (family ctor recursor : ConstRef β) : Prop where + former : entries.HasType family 0 type + introduction : entries.HasType ctor 0 (introType family) + elimination : entries.HasType recursor 1 (recType family ctor) + +instance [DecidableEq β] (entries : Environment β) (family ctor recursor : ConstRef β) : + Decidable (Interface entries family ctor recursor) := + decidable_of_iff (entries.HasType family 0 type ∧ entries.HasType ctor 0 (introType family) ∧ + entries.HasType recursor 1 (recType family ctor)) + ⟨fun h => ⟨h.1, h.2.1, h.2.2⟩, fun h => ⟨h.former, h.introduction, h.elimination⟩⟩ + +theorem shape_type : (shape : Ordinary.Shape β).type = type := rfl +theorem shape_introType (source : β) : constructor.type shape source = introType (.member source 0) := rfl +theorem shape_recType (source : β) : shape.recursorType source .large = + recType (.member source 0) (.ctor source 0 0) := rfl + +theorem Interface.of_checked [DecidableEq β] {entries : Environment β} {store : Store β} {source recursor : β} + (h : Ordinary.CheckedBlock.{u,v} entries store source recursor shape .large) : + Interface (shape.publishedEnvironment entries source recursor .large) + (.member source 0) (.ctor source 0 0) (.member recursor 0) := by + constructor + · refine ⟨shape.familyEntry, ?_, rfl, shape_type⟩ + exact Environment.insert_old h.recursorChecked.fresh + (Environment.overlay_old (Ordinary.Shape.constructorEntries_fresh h.shapeChecked) + (Environment.insert_same ..)) + · refine ⟨shape.constructorEntry source constructor, ?_, rfl, shape_introType source⟩ + apply Environment.insert_old h.recursorChecked.fresh + apply Environment.overlay_new + simp [Ordinary.Shape.constructorEntries, shape] + · exact ⟨shape.publishedRecursorEntry source recursor .large, + Environment.insert_same .., rfl, shape_recType source⟩ + +variable {V : Type v} [SetTheory V] + +noncomputable def implication (P Q : V) : V := piR 0 P (fun _ => Q) +noncomputable def value (constants : Assignment β V) (family : ConstRef β) (P Q : V) : V := + app (app (constants family []) P) Q +noncomputable def introValue (constants : Assignment β V) (ctor : ConstRef β) (P Q f g : V) : V := + app (app (app (app (constants ctor []) P) Q) f) g + +theorem type_interp (constants : Assignment β V) (env : Nat → V) : + interp constants [] env (type : AExpr β) = + piR 1 univZero (fun _ => piR 1 univZero (fun _ => univZero)) := by + simp [type, interp, VLevel.eval, univ_zero] + +theorem introType_interp (constants : Assignment β V) (family : ConstRef β) (env : Nat → V) : + interp constants [] env (introType family) = + piR 0 univZero (fun P => piR 0 univZero (fun Q => + piR 0 (implication P Q) (fun _ => piR 0 (implication Q P) (fun _ => value constants family P Q)))) := by + simp [introType, arrow, applied, implication, value, AExpr.appN, AExpr.liftN, liftVar, + interp, VLevel.eval, Valuation.cons, univ_zero] + +theorem recType_zero_interp (constants : Assignment β V) (family ctor : ConstRef β) (env : Nat → V) : + interp constants [0] env (recType family ctor) = + piR 0 univZero (fun P => piR 0 univZero (fun Q => + piR 0 (piR 1 (value constants family P Q) (fun _ => univZero)) (fun motive => + piR 0 (piR 0 (implication P Q) (fun f => piR 0 (implication Q P) + (fun g => app motive (introValue constants ctor P Q f g)))) + (fun _ => piR 0 (value constants family P Q) (fun h => app motive h))))) := by + simp [recType, arrow, applied, introduction, implication, value, introValue, + AExpr.appN, AExpr.liftN, liftVar, interp, VLevel.eval, Valuation.cons, regime, + PropWhen.param, PropWhen.always, PropWhen.holds, univ_zero] + +variable {entries : Environment β} {family ctor recursor : ConstRef β} + {constants : Assignment β V} + +theorem value_mem_univZero (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {P Q : V} (hP : P ∈ˢ univZero) (hQ : Q ∈ˢ univZero) : + value constants family P Q ∈ˢ univZero := by + have ht := h.former.member hM (levels := []) rfl (fun _ => empty) + rw [type_interp] at ht + have h1 : app (constants family []) P ∈ˢ piR 1 univZero (fun _ => univZero) := + app_mem_piR_pos (by decide : 1 ≠ 0) ht hP + exact app_mem_piR_pos (by decide : 1 ≠ 0) h1 hQ + +theorem introValue_mem (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {P Q f g : V} (hP : P ∈ˢ univZero) (hQ : Q ∈ˢ univZero) + (hf : f ∈ˢ implication P Q) (hg : g ∈ˢ implication Q P) : + introValue constants ctor P Q f g ∈ˢ value constants family P Q := by + have ht := h.introduction.member hM (levels := []) rfl (fun _ => empty) + rw [introType_interp] at ht + have h1 := app_mem_piR ht hP (fun _ _ _ => piR_zero_mem_univZero) + have h2 := app_mem_piR h1 hQ (fun _ _ _ => piR_zero_mem_univZero) + have h3 := app_mem_piR h2 hf (fun _ _ _ => piR_zero_mem_univZero) + exact app_mem_piR h3 hg (fun _ _ _ => value_mem_univZero h hM hP hQ) + +theorem eliminate (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {P Q C proof : V} (hP : P ∈ˢ univZero) (hQ : Q ∈ˢ univZero) (hC : C ∈ˢ univZero) + (minor : ∀ f, f ∈ˢ implication P Q → ∀ g, g ∈ˢ implication Q P → (pt : V) ∈ˢ C) + (hp : proof ∈ˢ value constants family P Q) : (pt : V) ∈ˢ C := by + let motive := lamR 1 (value constants family P Q) (fun _ => C) + have hm : motive ∈ˢ piR 1 (value constants family P Q) (fun _ => univZero) := + lamR_mem fun _ _ => hC + let minorValue := lamR 0 (implication P Q) (fun _ => lamR 0 (implication Q P) (fun _ => pt)) + have hminor : minorValue ∈ˢ piR 0 (implication P Q) (fun f => piR 0 (implication Q P) + (fun g => app motive (introValue constants ctor P Q f g))) := by + apply lamR_mem + intro f hf + apply lamR_mem + intro g hg + rw [app_lamR_pos (by decide : 1 ≠ 0) (introValue_mem h hM hP hQ hf hg)] + exact minor f hf g hg + have hr := h.elimination.member hM (levels := [0]) rfl (fun _ => empty) + rw [recType_zero_interp] at hr + obtain ⟨rP, hrP⟩ := Equality.exists_of_mem_piR_zero hr hP + obtain ⟨rQ, hrQ⟩ := Equality.exists_of_mem_piR_zero hrP hQ + obtain ⟨rm, hrm⟩ := Equality.exists_of_mem_piR_zero hrQ hm + obtain ⟨ri, hri⟩ := Equality.exists_of_mem_piR_zero hrm hminor + obtain ⟨result, hresult⟩ := Equality.exists_of_mem_piR_zero hri hp + rw [app_lamR_pos (by decide : 1 ≠ 0) hp] at hresult + rwa [eq_pt_of_mem_univZero hC hresult] at hresult + +theorem eq_of_mem (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {P Q proof : V} (hP : P ∈ˢ univZero) (hQ : Q ∈ˢ univZero) + (hp : proof ∈ˢ value constants family P Q) : P = Q := by + have hf : (pt : V) ∈ˢ implication P Q := eliminate h hM hP hQ piR_zero_mem_univZero + (fun f hf _ _ => by rwa [eq_pt_of_mem_piR_zero hf] at hf) hp + have hg : (pt : V) ∈ˢ implication Q P := eliminate h hM hP hQ piR_zero_mem_univZero + (fun _ _ g hg => by rwa [eq_pt_of_mem_piR_zero hg] at hg) hp + apply univZero_ext hP hQ + · intro hpt + simpa only [app_pt] using app_mem_piR hf hpt (fun _ _ _ => hQ) + · intro hpt + simpa only [app_pt] using app_mem_piR hg hpt (fun _ _ _ => hP) + +end Ix.Theory.Certified.Basis.Iff diff --git a/Ix/Theory/Certified/Basis/Interface.lean b/Ix/Theory/Certified/Basis/Interface.lean new file mode 100644 index 000000000..761e3ce2e --- /dev/null +++ b/Ix/Theory/Certified/Basis/Interface.lean @@ -0,0 +1,38 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Environment + +namespace Ix.Theory.Model.Environment + +open SetTheory + +universe u v +variable {β : Type u} + +/-- An exact type interface read from an already admitted entry. Bodies and +equations remain those of that entry; this predicate grants no admission. -/ +def HasType (entries : Environment β) (ref : ConstRef β) (n : Nat) (type : AExpr β) : Prop := + ∃ entry, entries ref = some entry ∧ entry.universes = n ∧ entry.type = type + +instance [DecidableEq β] (entries : Environment β) (ref : ConstRef β) (n : Nat) (type : AExpr β) : + Decidable (entries.HasType ref n type) := + match h : entries ref with + | none => .isFalse (by rintro ⟨entry, he, _⟩; simp [h] at he) + | some entry => + if he : entry.universes = n ∧ entry.type = type then + .isTrue ⟨entry, h, he⟩ + else .isFalse (by rintro ⟨other, ho, hu, ht⟩; cases h.symm.trans ho; exact he ⟨hu, ht⟩) + +variable {V : Type v} [SetTheory V] {constants : Assignment β V} {entries : Environment β} + +theorem HasType.member {ref : ConstRef β} {n : Nat} {type : AExpr β} + (h : entries.HasType ref n type) (hM : Realizes constants entries) + {levels : List Nat} (hn : levels.length = n) (env : Nat → V) : + constants ref levels ∈ˢ interp constants levels env type := by + obtain ⟨entry, he, rfl, rfl⟩ := h + exact hM.member ref entry he levels hn env + +end Ix.Theory.Model.Environment diff --git a/Ix/Theory/Certified/Basis/Nonempty.lean b/Ix/Theory/Certified/Basis/Nonempty.lean new file mode 100644 index 000000000..e371e006e --- /dev/null +++ b/Ix/Theory/Certified/Basis/Nonempty.lean @@ -0,0 +1,138 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Basis.Equality + +namespace Ix.Theory.Certified.Basis.Nonempty + +open Model Model.SetTheory Model.SetModel + +universe u v +variable {β : Type u} + +def constructor : Ordinary.Constructor β := ⟨[.bvar 0], [], []⟩ +def shape : Ordinary.Shape β := ⟨1, [.sort (.param 0)], [], .zero, [constructor]⟩ +def type : AExpr β := .forallE .never (.sort (.param 0)) (.sort .zero) +def applied (family : ConstRef β) (l : VLevel) (A : AExpr β) : AExpr β := .app (.const family [l]) A +def introduction (ctor : ConstRef β) (l : VLevel) (A a : AExpr β) : AExpr β := + .appN (.const ctor [l]) [A, a] +def introType (family : ConstRef β) : AExpr β := + .forallE .always (.sort (.param 0)) (.forallE .always (.bvar 0) (applied family (.param 0) (.bvar 1))) +def recType (family ctor : ConstRef β) : AExpr β := + .forallE .always (.sort (.param 0)) <| + .forallE .always (.forallE .never (applied family (.param 0) (.bvar 0)) (.sort .zero)) <| + .forallE .always + (.forallE .always (.bvar 1) + (.app (.bvar 1) (introduction ctor (.param 0) (.bvar 2) (.bvar 0)))) <| + .forallE .always (applied family (.param 0) (.bvar 2)) <| + .app (.bvar 2) (.bvar 0) + +structure Interface (entries : Environment β) (family ctor recursor : ConstRef β) : Prop where + former : entries.HasType family 1 type + introduction : entries.HasType ctor 1 (introType family) + elimination : entries.HasType recursor 1 (recType family ctor) + +instance [DecidableEq β] (entries : Environment β) (family ctor recursor : ConstRef β) : + Decidable (Interface entries family ctor recursor) := + decidable_of_iff (entries.HasType family 1 type ∧ entries.HasType ctor 1 (introType family) ∧ + entries.HasType recursor 1 (recType family ctor)) + ⟨fun h => ⟨h.1, h.2.1, h.2.2⟩, fun h => ⟨h.former, h.introduction, h.elimination⟩⟩ + +theorem shape_type : (shape : Ordinary.Shape β).type = type := rfl +theorem shape_introType (source : β) : constructor.type shape source = introType (.member source 0) := rfl +theorem shape_recType (source : β) : shape.recursorType source .small = + recType (.member source 0) (.ctor source 0 0) := rfl + +theorem Interface.of_checked [DecidableEq β] {entries : Environment β} {store : Store β} {source recursor : β} + (h : Ordinary.CheckedBlock.{u,v} entries store source recursor shape .small) : + Interface (shape.publishedEnvironment entries source recursor .small) + (.member source 0) (.ctor source 0 0) (.member recursor 0) := by + constructor + · refine ⟨shape.familyEntry, ?_, rfl, shape_type⟩ + exact Environment.insert_old h.recursorChecked.fresh + (Environment.overlay_old (Ordinary.Shape.constructorEntries_fresh h.shapeChecked) + (Environment.insert_same ..)) + · refine ⟨shape.constructorEntry source constructor, ?_, rfl, shape_introType source⟩ + apply Environment.insert_old h.recursorChecked.fresh + apply Environment.overlay_new + simp [Ordinary.Shape.constructorEntries, shape] + · exact ⟨shape.publishedRecursorEntry source recursor .small, + Environment.insert_same .., rfl, shape_recType source⟩ + +variable {V : Type v} [SetTheory V] + +noncomputable def value (constants : Assignment β V) (family : ConstRef β) (u : Nat) (A : V) : V := + app (constants family [u]) A +noncomputable def introValue (constants : Assignment β V) (ctor : ConstRef β) (u : Nat) (A a : V) : V := + app (app (constants ctor [u]) A) a + +theorem type_interp (constants : Assignment β V) (u : Nat) (env : Nat → V) : + interp constants [u] env (type : AExpr β) = piR 1 (univ u) (fun _ => univZero) := by + simp [type, interp, VLevel.eval, univ_zero] + +theorem introType_interp (constants : Assignment β V) (family : ConstRef β) (u : Nat) (env : Nat → V) : + interp constants [u] env (introType family) = + piR 0 (univ u) (fun A => piR 0 A (fun _ => value constants family u A)) := by + simp [introType, applied, value, interp, VLevel.eval, Valuation.cons] + +theorem recType_interp (constants : Assignment β V) (family ctor : ConstRef β) (u : Nat) (env : Nat → V) : + interp constants [u] env (recType family ctor) = + piR 0 (univ u) (fun A => + piR 0 (piR 1 (value constants family u A) (fun _ => univZero)) (fun motive => + piR 0 (piR 0 A (fun a => app motive (introValue constants ctor u A a))) + (fun _ => piR 0 (value constants family u A) (fun h => app motive h)))) := by + simp [recType, applied, introduction, value, introValue, AExpr.appN, interp, + VLevel.eval, Valuation.cons, univ_zero] + +variable {entries : Environment β} {family ctor recursor : ConstRef β} + {constants : Assignment β V} + +theorem value_mem_univZero (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {u : Nat} {A : V} (hA : A ∈ˢ univ u) : value constants family u A ∈ˢ univZero := by + have ht := h.former.member hM (levels := [u]) rfl (fun _ => empty) + rw [type_interp] at ht + exact app_mem_piR_pos (by decide : 1 ≠ 0) ht hA + +theorem introValue_mem (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {u : Nat} {A a : V} (hA : A ∈ˢ univ u) (ha : a ∈ˢ A) : + introValue constants ctor u A a ∈ˢ value constants family u A := by + have ht := h.introduction.member hM (levels := [u]) rfl (fun _ => empty) + rw [introType_interp] at ht + have h1 := app_mem_piR ht hA (fun _ _ _ => piR_zero_mem_univZero) + exact app_mem_piR h1 ha (fun _ _ _ => value_mem_univZero h hM hA) + +theorem exists_of_mem (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {u : Nat} {A proof : V} (hA : A ∈ˢ univ u) (hp : proof ∈ˢ value constants family u A) : + ∃ a, a ∈ˢ A := by + let C : V := truthVal (∃ a, a ∈ˢ A) + let motive := lamR 1 (value constants family u A) (fun _ => C) + have hm : motive ∈ˢ piR 1 (value constants family u A) (fun _ => univZero) := + lamR_mem fun _ _ => truthVal_mem_univZero _ + let minor := lamR 0 A (fun _ => pt) + have hminor : minor ∈ˢ piR 0 A (fun a => app motive (introValue constants ctor u A a)) := by + apply lamR_mem + intro a ha + rw [app_lamR_pos (by decide : 1 ≠ 0) (introValue_mem h hM hA ha)] + exact pt_mem_truthVal ⟨a, ha⟩ + have hr := h.elimination.member hM (levels := [u]) rfl (fun _ => empty) + rw [recType_interp] at hr + obtain ⟨rA, hrA⟩ := Equality.exists_of_mem_piR_zero hr hA + obtain ⟨rm, hrm⟩ := Equality.exists_of_mem_piR_zero hrA hm + obtain ⟨ri, hri⟩ := Equality.exists_of_mem_piR_zero hrm hminor + obtain ⟨result, hresult⟩ := Equality.exists_of_mem_piR_zero hri hp + rw [app_lamR_pos (by decide : 1 ≠ 0) hp] at hresult + exact of_mem_truthVal hresult + +theorem value_eq_truthVal (h : Interface entries family ctor recursor) (hM : Realizes constants entries) + {u : Nat} {A : V} (hA : A ∈ˢ univ u) : + value constants family u A = truthVal (∃ a, a ∈ˢ A) := by + apply univZero_ext (value_mem_univZero h hM hA) (truthVal_mem_univZero _) + · exact fun hp => pt_mem_truthVal (exists_of_mem h hM hA hp) + · intro hp + obtain ⟨a, ha⟩ := of_mem_truthVal hp + have hc := introValue_mem h hM hA ha + rwa [eq_pt_of_mem_univZero (value_mem_univZero h hM hA) hc] at hc + +end Ix.Theory.Certified.Basis.Nonempty diff --git a/Ix/Theory/Certified/Checker.lean b/Ix/Theory/Certified/Checker.lean new file mode 100644 index 000000000..c2a2aa7d2 --- /dev/null +++ b/Ix/Theory/Certified/Checker.lean @@ -0,0 +1,316 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Judgment +import Ix.Theory.Certified.LevelEq + +/-! +# Executable validation of dependent-function certificates + +Witnesses are untrusted trees of rule choices and intermediate syntax. The +validator checks their exact endpoints, scopes, annotations, and dependency +lookups. Every recursive success constructs its semantic proof through the +rule theorems; no semantic proof is an input. Exhausted fuel and unsupported +syntax fail. Proof fields in successful results are erased during execution. +-/ + +namespace Ix.Theory.Certified + +open Model + +universe u v + +/-- An erased result at the data universe of the checked syntax. This permits +the proof-producing validator to compose with declaration readers. -/ +structure CheckedClaim (claim : Prop) : Type u where + down : claim + +mutual +inductive TypingWitness (β : Type u) where + | sort + | bvar + | const + | app (condition : PropWhen) (domain codomain : AExpr β) + (fn arg : TypingWitness β) + | lam (domainLevel codomainLevel : VLevel) (codomain : AExpr β) + (domainType codomainType body : TypingWitness β) + | forallE (domainLevel codomainLevel : VLevel) + (domainType codomainType : TypingWitness β) + | conv (intermediate : AExpr β) (targetLevel : VLevel) + (term target : TypingWitness β) (conversion : ConversionWitness β) + | fact (ref : ConstRef β) (index : Nat) (levels : List VLevel) + | natLit (ref : ConstRef β) (index : Nat) + | betaResult (condition : PropWhen) (domain body argument codomain : AExpr β) + (lambda argumentWitness : TypingWitness β) + +inductive ConversionWitness (β : Type u) where + | refl + | symm (proof : ConversionWitness β) + | trans (middle : AExpr β) (left right : ConversionWitness β) + | app (fn arg : ConversionWitness β) + | lam (domainLevel : VLevel) (domainType : TypingWitness β) + (domain body : ConversionWitness β) + | forallE (domainLevel : VLevel) (domainType : TypingWitness β) + (domain body : ConversionWitness β) + | beta (lambdaType : AExpr β) (lambda arg : TypingWitness β) + | eta (codomain : AExpr β) (fn : TypingWitness β) + | proofIrrel (type : AExpr β) (typeProof left right : TypingWitness β) + | delta + | sort + | equation (ref : ConstRef β) (index : Nat) (levels : List VLevel) + | natLiteral (ref : ConstRef β) (index : Nat) + | proj (major : ConversionWitness β) +end + +variable {β : Type u} [DecidableEq β] + +mutual +def verifyType (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (e A : AExpr β) (witness : TypingWitness β) : + Option (CheckedClaim.{u} (TypingClaim.{u,v} entries Γ e A)) := + match fuel with + | 0 => none + | fuel + 1 => + if e.Scope n Γ.length ∧ A.Scope n Γ.length then + match e, witness with + | .sort l, .sort => + if h : A = .sort (.succ l) then + some ⟨by subst A; exact TypingClaim.sort l⟩ + else none + | .bvar i, .bvar => + match h : Γ[i]? with + | none => none + | some B => + if hA : A = B then some ⟨by subst A; exact TypingClaim.bvar h⟩ else none + | .const r ls, .const => + match h : entries r with + | none => none + | some entry => + if hn : ls.length = entry.universes then + if hA : A = entry.type.instL ls then + some ⟨by subst A; exact TypingClaim.const h hn⟩ + else none + else none + | .app f a, .app p D B wf wa => + if hA : A = B.inst a then do + let hf ← verifyType fuel n entries Γ f (.forallE p D B) wf + let ha ← verifyType fuel n entries Γ a D wa + return ⟨by subst A; exact TypingClaim.app hf.down ha.down⟩ + else none + | .lam p D body, .lam lD lB B wD wB wb => + if hp : p = zeroCondition lB then + if hA : A = .forallE p D B then do + let hD ← verifyType fuel n entries Γ D (.sort lD) wD + let hB ← verifyType fuel n entries (Γ.push D) B (.sort lB) wB + let hb ← verifyType fuel n entries (Γ.push D) body B wb + return ⟨by subst A; exact TypingClaim.lam hD.down hB.down hb.down hp⟩ + else none + else none + | .forallE p D B, .forallE lD lB wD wB => + if hp : p = zeroCondition lB then + if hA : A = .sort (.imax lD lB) then do + let hD ← verifyType fuel n entries Γ D (.sort lD) wD + let hB ← verifyType fuel n entries (Γ.push D) B (.sort lB) wB + return ⟨by subst A; exact TypingClaim.forallE hD.down hB.down hp⟩ + else none + else none + | e, .conv B lA we wA wc => do + let he ← verifyType fuel n entries Γ e B we + let hA ← verifyType fuel n entries Γ A (.sort lA) wA + let hc ← verifyConversion fuel n entries Γ B A wc + return ⟨TypingClaim.conv he.down hA.down hc.down⟩ + | e, .fact r index ls => + match hr : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (.typed value type) => + if hn : ls.length = entry.universes then + if ∀ l ∈ ls, l.WF n then + if he : e = value.instL ls then + if hA : A = type.instL ls then + some ⟨by subst e A; exact TypingClaim.fact hr (List.mem_of_getElem? hf) hn⟩ + else none + else none + else none + else none + | _ => none + | .natLit value, .natLit r index => + match hr : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (.natural _ _) => + if hn : entry.universes = 0 then + if hA : A = .const r [] then + some ⟨by subst A; exact TypingClaim.natLit hr (List.mem_of_getElem? hf) hn value⟩ + else none + else none + | _ => none + | e, .betaResult p D body arg B wl wa => + if he : e = body.inst arg then + if hA : A = B.inst arg then do + let hl ← verifyType fuel n entries Γ (.lam p D body) (.forallE p D B) wl + let ha ← verifyType fuel n entries Γ arg D wa + return ⟨by subst e A; exact TypingClaim.betaResult hl.down ha.down⟩ + else none + else none + | _, _ => none + else none + +def verifyConversion (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (a b : AExpr β) (witness : ConversionWitness β) : + Option (CheckedClaim.{u} (ConversionClaim.{u,v} entries Γ a b)) := + match fuel with + | 0 => none + | fuel + 1 => + if a.Scope n Γ.length ∧ b.Scope n Γ.length then + match a, b, witness with + | a, b, .refl => + if h : a = b then some ⟨by subst b; exact ConversionClaim.refl a⟩ else none + | a, b, .symm w => do + let h ← verifyConversion fuel n entries Γ b a w + return ⟨ConversionClaim.symm h.down⟩ + | a, b, .trans c w₁ w₂ => do + let h₁ ← verifyConversion fuel n entries Γ a c w₁ + let h₂ ← verifyConversion fuel n entries Γ c b w₂ + return ⟨ConversionClaim.trans h₁.down h₂.down⟩ + | .app f a, .app f' a', .app wf wa => do + let hf ← verifyConversion fuel n entries Γ f f' wf + let ha ← verifyConversion fuel n entries Γ a a' wa + return ⟨ConversionClaim.app hf.down ha.down⟩ + | .proj r i a, .proj r' i' b, .proj w => + if hr : r = r' then + if hi : i = i' then do + let h ← verifyConversion fuel n entries Γ a b w + return ⟨by subst r' i'; exact ConversionClaim.proj h.down⟩ + else none + else none + | .lam p D body, .lam p' D' body', .lam lD wD wd wb => + if hp : p = p' then do + let hD ← verifyType fuel n entries Γ D (.sort lD) wD + let hd ← verifyConversion fuel n entries Γ D D' wd + let hb ← verifyConversion fuel n entries (Γ.push D) body body' wb + return ⟨by subst p'; exact ConversionClaim.lam hD.down hd.down hb.down⟩ + else none + | .forallE p D B, .forallE p' D' B', .forallE lD wD wd wb => + if hp : p = p' then do + let hD ← verifyType fuel n entries Γ D (.sort lD) wD + let hd ← verifyConversion fuel n entries Γ D D' wd + let hb ← verifyConversion fuel n entries (Γ.push D) B B' wb + return ⟨by subst p'; exact ConversionClaim.forallE hD.down hd.down hb.down⟩ + else none + | .app (.lam p D body) arg, result, .beta T wl wa => + if hr : result = body.inst arg then do + let hl ← verifyType fuel n entries Γ (.lam p D body) T wl + let ha ← verifyType fuel n entries Γ arg D wa + return ⟨by subst result; exact ConversionClaim.beta hl.down ha.down⟩ + else none + | .lam p D body, f, .eta B wf => + if hb : body = .app (f.liftN 1) (.bvar 0) then do + let hf ← verifyType fuel n entries Γ f (.forallE p D B) wf + return ⟨by subst body; exact ConversionClaim.eta hf.down⟩ + else none + | a, b, .proofIrrel A wA wa wb => do + let hA ← verifyType fuel n entries Γ A (.sort .zero) wA + let ha ← verifyType fuel n entries Γ a A wa + let hb ← verifyType fuel n entries Γ b A wb + return ⟨ConversionClaim.proofIrrel hA.down ha.down hb.down⟩ + | .const r ls, b, .delta => + match h : entries r with + | none => none + | some entry => + match hb : entry.body with + | none => none + | some body => + if hn : ls.length = entry.universes then + if hB : b = body.instL ls then + some ⟨by subst b; exact ConversionClaim.delta h hb hn⟩ + else none + else none + | .sort l, .sort l', .sort => + if h : LevelEq.check n l l' = true then + some ⟨ConversionClaim.sort (LevelEq.check_sound h).2.2⟩ + else none + | a, b, .equation r index ls => + match h : entries r with + | none => none + | some entry => + match he : entry.equations[index]? with + | none => none + | some law => + if hn : ls.length = entry.universes then + if hls : ∀ l ∈ ls, l.WF n then + if ha : a = law.lhs.instL ls then + if hb : b = law.rhs.instL ls then + some ⟨by + subst a b + exact ConversionClaim.equation h (List.mem_of_getElem? he) hn⟩ + else none + else none + else none + else none + | .natLit value, result, .natLiteral r index => + match hr : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (.natural zero succ) => + if hn : entry.universes = 0 then + match value with + | 0 => + if he : result = .const zero [] then + some ⟨by subst result; exact ConversionClaim.natZero hr (List.mem_of_getElem? hf) hn⟩ + else none + | value + 1 => + if he : result = .app (.const succ []) (.natLit value) then + some ⟨by subst result; exact ConversionClaim.natSucc hr (List.mem_of_getElem? hf) hn value⟩ + else none + else none + | _ => none + | _, _, _ => none + else none +end + +/-- Soundness is extracted only from an actual successful execution. The +dependency model and context are the documented local preconditions; the +closed acceptance producer must construct them. -/ +theorem verifyType_sound {fuel n : Nat} {entries : Environment β} {Γ : Context β} + {e A : AExpr β} {witness : TypingWitness β} {result} + (_ : verifyType.{u,v} fuel n entries Γ e A witness = some result) : + TypingClaim.{u,v} entries Γ e A := result.down + +theorem verifyConversion_sound {fuel n : Nat} {entries : Environment β} {Γ : Context β} + {a b : AExpr β} {witness : ConversionWitness β} {result} + (_ : verifyConversion.{u,v} fuel n entries Γ a b witness = some result) : + ConversionClaim.{u,v} entries Γ a b := result.down + +def checkTypeCertified (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (e A : AExpr β) (witness : TypingWitness β) : Bool := + (verifyType.{u,v} fuel n entries Γ e A witness).isSome + +def defeqCertified (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (a b : AExpr β) (witness : ConversionWitness β) : Bool := + (verifyConversion.{u,v} fuel n entries Γ a b witness).isSome + +theorem checkTypeCertified_sound {fuel n : Nat} {entries : Environment β} + {Γ : Context β} {e A : AExpr β} {witness : TypingWitness β} + (h : checkTypeCertified.{u,v} fuel n entries Γ e A witness = true) : + TypingClaim.{u,v} entries Γ e A := by + unfold checkTypeCertified at h + cases hr : verifyType.{u,v} fuel n entries Γ e A witness with + | none => simp [hr] at h + | some result => exact result.down + +theorem defeqCertified_sound {fuel n : Nat} {entries : Environment β} + {Γ : Context β} {a b : AExpr β} {witness : ConversionWitness β} + (h : defeqCertified.{u,v} fuel n entries Γ a b witness = true) : + ConversionClaim.{u,v} entries Γ a b := by + unfold defeqCertified at h + cases hr : verifyConversion.{u,v} fuel n entries Γ a b witness with + | none => simp [hr] at h + | some result => exact result.down + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/ClaimComposition.lean b/Ix/Theory/Certified/ClaimComposition.lean new file mode 100644 index 000000000..9c7c05420 --- /dev/null +++ b/Ix/Theory/Certified/ClaimComposition.lean @@ -0,0 +1,245 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Claims + +namespace Ix.Theory.Certified + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +theorem mem_outstanding {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {nodes : List (CheckedNode.{u,v} fuel signature store)} {ref : ConstRef β} : + ref ∈ outstanding nodes ↔ ref ∈ nodeFrontiers nodes ∧ ref ∉ nodeSubjects nodes := by + simp [outstanding] + +theorem CheckedBatch.exact_subjects {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) : + nodeSubjects batch.nodes = inputs.flatMap (·.subjects) := by + have h := congrArg (fun nodes => nodes.flatMap (·.subjects)) batch.exactNodes + simpa only [nodeSubjects, List.flatMap_map, Function.comp_def] using h + +theorem CheckedBatch.exact_frontiers {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) : + nodeFrontiers batch.nodes = inputs.flatMap (fun node => node.frontier.map (·.ref)) := by + calc + nodeFrontiers batch.nodes = batch.nodes.flatMap (fun node => node.input.frontier.map (·.ref)) := by + exact congrArg (fun f => batch.nodes.flatMap f) (funext fun node => node.frontier_refs) + _ = inputs.flatMap (fun node => node.frontier.map (·.ref)) := by + simpa only [List.flatMap_map, Function.comp_def] using + congrArg (fun nodes => nodes.flatMap (fun node => node.frontier.map (·.ref))) batch.exactNodes + +theorem CheckedBatch.frontier_coverage {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) {ref : ConstRef β} : + ref ∈ batch.receipt.frontier.refs ↔ + (∃ node ∈ inputs, ref ∈ node.frontier.map (·.ref)) ∧ + ¬ ∃ node ∈ inputs, ref ∈ node.subjects := by + rw [batch.exactFrontier, mem_outstanding, batch.exact_subjects, batch.exact_frontiers] + simp + +/-- Conservative logical-use manifest, including every axiom admitted by a +leaf and by the final replay. Neither kind of use is structurally discharged. -/ +def CheckedBatch.logicalUses {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) : List (ConstRef β) := + (logicalAxioms store batch.receipt.checked.result.entries ++ + batch.nodes.flatMap (fun node => logicalAxioms store node.receipt.checked.result.entries)).eraseDups + +theorem CheckedBatch.leaf_axiom_retained {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) + {node : CheckedNode.{u,v} fuel signature store} (hn : node ∈ batch.nodes) {ref : ConstRef β} + (hr : ref ∈ logicalAxioms store node.receipt.checked.result.entries) : + ref ∈ batch.logicalUses := by + simp only [logicalUses, List.mem_eraseDups, List.mem_append, List.mem_flatMap] + exact Or.inr ⟨node, hn, hr⟩ + +theorem CheckedBatch.logicalUses_authorized {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) {ref : ConstRef β} + (h : ref ∈ batch.logicalUses) : + ∃ entry, Standard.EntrySource store ref entry ∨ Quotient.EntrySource store ref entry := by + simp only [logicalUses, List.mem_eraseDups, List.mem_append, List.mem_flatMap] at h + rcases h with h | ⟨node, _, h⟩ + · obtain ⟨entry, _, hs⟩ := batch.receipt.logical_axioms_authorized h + exact ⟨entry, hs⟩ + · obtain ⟨entry, _, hs⟩ := node.receipt.logical_axioms_authorized h + exact ⟨entry, hs⟩ + +/-- Every discharged dependency has a provider at a strictly earlier position; +only an explicit external frontier may lack such a provider. -/ +theorem DependencyOrder.before {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {known : List (ConstRef β)} {nodes : List (CheckedNode.{u,v} fuel signature store)} + (order : DependencyOrder known nodes) {index : Nat} {node : CheckedNode.{u,v} fuel signature store} + (hn : nodes[index]? = some node) {ref : ConstRef β} (hr : ref ∈ node.receipt.frontier.refs) : + ref ∈ known ∨ ∃ previous, previous < index ∧ + ∃ provider, nodes[previous]? = some provider ∧ ref ∈ provider.input.subjects := by + induction order generalizing index with + | nil => simp at hn + | @cons known first rest available tail ih => + cases index with + | zero => + cases Option.some.inj hn + exact Or.inl (available ref hr) + | succ index => + rcases ih hn with hk | ⟨previous, hp, provider, hs, ho⟩ + · rcases List.mem_append.mp hk with hk | hk + · exact Or.inl hk + · exact Or.inr ⟨0, Nat.zero_lt_succ _, first, rfl, hk⟩ + · exact Or.inr ⟨previous + 1, Nat.succ_lt_succ hp, provider, hs, ho⟩ + +theorem unique_subject_provider {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {nodes : List (CheckedNode.{u,v} fuel signature store)} (unique : (nodeSubjects nodes).Nodup) + {i j : Nat} {a b : CheckedNode.{u,v} fuel signature store} + (ha : nodes[i]? = some a) (hb : nodes[j]? = some b) {ref : ConstRef β} + (hra : ref ∈ a.input.subjects) (hrb : ref ∈ b.input.subjects) : i = j := by + have hp := (List.pairwise_flatMap.mp unique).2 + obtain ⟨hi, hai⟩ := List.getElem?_eq_some_iff.mp ha + obtain ⟨hj, hbj⟩ := List.getElem?_eq_some_iff.mp hb + rcases Nat.lt_trichotomy i j with hij | he | hji + · have h := List.pairwise_iff_getElem.mp hp i j hi hj hij + rw [hai, hbj] at h + exact False.elim (h ref hra ref hrb rfl) + · exact he + · have h := List.pairwise_iff_getElem.mp hp j i hj hi hji + rw [hai, hbj] at h + exact False.elim (h ref hrb ref hra rfl) + +/-- The relation points from a supplying node to a consuming node. Its rank +is the actual checked schedule position, not a prover-supplied acyclicity flag. -/ +def DependencyEdge {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + (nodes : List (CheckedNode.{u,v} fuel signature store)) (provider consumer : Nat) : Prop := + ∃ a b ref, nodes[provider]? = some a ∧ nodes[consumer]? = some b ∧ + ref ∈ a.input.subjects ∧ ref ∈ b.receipt.frontier.refs ∧ + ∀ previous, previous < provider → ∀ other, nodes[previous]? = some other → ref ∉ other.input.subjects + +theorem first_subject_provider {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {nodes : List (CheckedNode.{u,v} fuel signature store)} {ref : ConstRef β} + (h : ref ∈ nodeSubjects nodes) : + ∃ index : Nat, ∃ node : CheckedNode.{u,v} fuel signature store, + nodes[index]? = some node ∧ ref ∈ node.input.subjects ∧ + ∀ previous : Nat, previous < index → ∀ other : CheckedNode.{u,v} fuel signature store, + nodes[previous]? = some other → ref ∉ other.input.subjects := by + induction nodes with + | nil => cases h + | cons first rest ih => + by_cases hf : ref ∈ first.input.subjects + · exact ⟨0, first, rfl, hf, fun previous hp => False.elim (Nat.not_lt_zero previous hp)⟩ + · have hr : ref ∈ nodeSubjects rest := (List.mem_append.mp h).resolve_left hf + obtain ⟨index, node, hn, hs, least⟩ := ih hr + refine ⟨index + 1, node, hn, hs, ?_⟩ + intro previous hp other ho + cases previous with + | zero => cases Option.some.inj ho; exact hf + | succ previous => exact least previous (Nat.lt_of_succ_lt_succ hp) other ho + +/-- Shared subjects choose their first checked provider. This supplies an +actual edge for every discharged frontier member, as opposed to merely +asserting that a separately supplied graph is acyclic. -/ +theorem DependencyOrder.edge_for {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {known : List (ConstRef β)} {nodes : List (CheckedNode.{u,v} fuel signature store)} + (order : DependencyOrder known nodes) {consumer : Nat} + {node : CheckedNode.{u,v} fuel signature store} (hn : nodes[consumer]? = some node) + {ref : ConstRef β} (hr : ref ∈ node.receipt.frontier.refs) : + ref ∈ known ∨ ∃ provider, DependencyEdge nodes provider consumer := by + rcases order.before hn hr with hk | ⟨previous, _, owner, ho, hs⟩ + · exact Or.inl hk + · obtain ⟨index, first, hf, hr', least⟩ := first_subject_provider + (List.mem_flatMap.mpr ⟨owner, List.mem_of_getElem? ho, hs⟩) + exact Or.inr ⟨index, first, node, ref, hf, hn, hr', hr, least⟩ + +theorem DependencyOrder.rank {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {known : List (ConstRef β)} {nodes : List (CheckedNode.{u,v} fuel signature store)} + (order : DependencyOrder known nodes) + (external : ∀ ref ∈ known, ref ∉ nodeSubjects nodes) {provider consumer : Nat} + (edge : DependencyEdge nodes provider consumer) : provider < consumer := by + obtain ⟨a, b, ref, ha, hb, hra, hrb, first⟩ := edge + rcases order.before hb hrb with hk | ⟨previous, hp, owner, ho, hr⟩ + · exact False.elim (external ref hk + (List.mem_flatMap.mpr ⟨a, List.mem_of_getElem? ha, hra⟩)) + · by_cases h : provider < consumer + · exact h + · have earlier : previous < provider := Nat.lt_of_lt_of_le hp (Nat.le_of_not_gt h) + exact False.elim (first previous earlier owner ho hr) + +theorem CheckedBatch.external_disjoint {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) {ref : ConstRef β} + (h : ref ∈ batch.receipt.frontier.refs ++ [signature.falseType, signature.falseElim]) : + ref ∉ nodeSubjects batch.nodes := by + intro hs + rcases List.mem_append.mp h with hf | hp + · exact (mem_outstanding.mp ((batch.exactFrontier ref).mp hf)).2 hs + · have fresh := batch.receipt.fresh ref hs + rcases List.mem_cons.mp hp with rfl | hp + · rw [batch.receipt.frontier.interface.present.1] at fresh; cases fresh + · rcases List.mem_cons.mp hp with rfl | hp + · rw [batch.receipt.frontier.interface.present.2] at fresh; cases fresh + · cases hp + +theorem CheckedBatch.acyclic {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) : + WellFounded (DependencyEdge batch.nodes) := + Subrelation.wf + (fun h => batch.order.rank (fun _ h => batch.external_disjoint h) h) + Nat.lt_wfRel.wf + +theorem CheckedBatch.no_circular_discharge {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) {a b : Nat} + (ab : DependencyEdge batch.nodes a b) (ba : DependencyEdge batch.nodes b a) : False := by + have hab := batch.order.rank (fun _ h => batch.external_disjoint h) ab + have hba := batch.order.rank (fun _ h => batch.external_disjoint h) ba + exact Nat.lt_asymm hab hba + +/-- Composition retains the leaf sequence. Validation of any grouping runs +the same source-bound checker over that complete sequence. -/ +def composeClaims (left right : List (ClaimNode β)) : List (ClaimNode β) := left ++ right + +omit [DecidableEq β] in +theorem composeClaims_assoc (a b c : List (ClaimNode β)) : + composeClaims (composeClaims a b) c = composeClaims a (composeClaims b c) := + List.append_assoc .. + +theorem checkBatch?_assoc (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (frontier : List (FrontierWitness β)) (a b c : List (ClaimNode β)) : + acceptsBatch.{u,v} fuel signature store frontier (composeClaims (composeClaims a b) c) = + acceptsBatch.{u,v} fuel signature store frontier (composeClaims a (composeClaims b c)) := by + rw [composeClaims_assoc] + +/-- Erasing structural obligations has no effect on the model's axiom-use +manifest. Every recorded axiom retains its exact realized source schema. -/ +theorem CheckedBatch.logical_axioms_authorized {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) {ref : ConstRef β} + (h : ref ∈ logicalAxioms store batch.receipt.checked.result.entries) : + ∃ entry, batch.receipt.checked.result.entries ref = some entry ∧ + (Standard.EntrySource store ref entry ∨ Quotient.EntrySource store ref entry) := + batch.receipt.logical_axioms_authorized h + +theorem CheckedBatch.no_False {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) + (closed : batch.receipt.frontier.refs = []) {ref : ConstRef β} + (subject : ref ∈ nodeSubjects batch.nodes) + (type : store.type ref = some signature.falseExpr) + (V : Type v) [SetTheory V] : False := by + obtain ⟨constants, hM, subjects⟩ := batch.closed_has_model closed V + obtain ⟨entry, _, hs, hm⟩ := subjects ref subject + have he : entry.type.erase = .const signature.falseType [] := + Option.some.inj (hs.type.symm.trans type) + have hc := AExpr.eq_const_of_erase_eq he + have member := hm (List.replicate entry.universes 0) (by simp) (fun _ => empty) + rw [hc] at member + simp only [interp, List.map_nil, hM.falseValue] at member + exact not_mem_empty _ member + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Claims.lean b/Ix/Theory/Certified/Claims.lean new file mode 100644 index 000000000..c80ce755c --- /dev/null +++ b/Ix/Theory/Certified/Claims.lean @@ -0,0 +1,242 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.LogicalPolicy + +/-! A certified claim bundle is an ordered dependency DAG. Aggregation checks +each conditional leaf, matches its complete deferred headers, and replays its +admission in one growing interface. Set subtraction alone grants no meaning. +The checked result extends every compatible interpretation of its remaining +frontier and constructs a model when that frontier is empty. -/ + +namespace Ix.Theory.Certified + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +structure ClaimNode (β : Type u) where + subjects : List (ConstRef β) + frontier : List (FrontierWitness β) + declarations : List (DeclarationWitness β) + deriving Inhabited + +structure CheckedNode (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) where + input : ClaimNode β + receipt : ConditionalStore.{u,v} signature store input.subjects + validation : checkConditionalStore? fuel signature store input.frontier input.subjects + input.declarations = some receipt + +def checkNode? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (node : ClaimNode β) : Option (CheckedNode.{u,v} fuel signature store) := + match h : checkConditionalStore?.{u,v} fuel signature store node.frontier node.subjects node.declarations with + | none => none + | some receipt => some ⟨node, receipt, h⟩ + +theorem checkNode?_input {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {node : ClaimNode β} {result : CheckedNode.{u,v} fuel signature store} + (h : checkNode? fuel signature store node = some result) : result.input = node := by + unfold checkNode? at h + split at h + · cases h + · cases Option.some.inj h; rfl + +theorem CheckedNode.frontier_refs {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + (node : CheckedNode.{u,v} fuel signature store) : + node.receipt.frontier.refs = node.input.frontier.map (·.ref) := + checkFrontier?_refs (checkConditionalStore?_frontier node.validation) + +def nodeSubjects {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + (nodes : List (CheckedNode.{u,v} fuel signature store)) : List (ConstRef β) := + nodes.flatMap (·.input.subjects) + +def nodeFrontiers {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + (nodes : List (CheckedNode.{u,v} fuel signature store)) : List (ConstRef β) := + nodes.flatMap (·.receipt.frontier.refs) + +def outstanding {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + (nodes : List (CheckedNode.{u,v} fuel signature store)) : List (ConstRef β) := + (nodeFrontiers nodes).filter (fun ref => !(nodeSubjects nodes).contains ref) |>.eraseDups + +/-- Dependencies refer to the external frontier or to subjects of earlier +nodes. Internal recursion stays inside one atomic declaration producer. -/ +inductive DependencyOrder {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} : + List (ConstRef β) → List (CheckedNode.{u,v} fuel signature store) → Prop where + | nil (known) : DependencyOrder known [] + | cons {known node rest} + (available : ∀ ref ∈ node.receipt.frontier.refs, ref ∈ known) + (tail : DependencyOrder (known ++ node.input.subjects) rest) : + DependencyOrder known (node :: rest) + +omit [DecidableEq β] in +theorem HeaderPresent.extend {signature : PrimitiveSignature β} {a b : Environment β} + (extension : Extends.{u,v} signature a b) {header : Signature.Header β} + (h : HeaderPresent a header) : HeaderPresent b header := by + obtain ⟨entry, he, hu, ht⟩ := h.entry + simp only [HeaderPresent, extension.lookup _ _ he] + exact ⟨hu, ht⟩ + +structure ReplayResult {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (known : List (ConstRef β)) + (nodes : List (CheckedNode.{u,v} fuel signature store)) where + checked : CheckedExtension.{u,v} signature store state + order : DependencyOrder known nodes + subjects : ∀ ref ∈ nodeSubjects nodes, (checked.result.entries ref).isSome = true + frontiers : ∀ node ∈ nodes, ∀ header ∈ node.receipt.frontier.headers, + HeaderPresent checked.result.entries header + +def Ordinary.BlockWitness.outputs (witness : Ordinary.BlockWitness β) : List (ConstRef β) := + [.member witness.source 0, .member witness.recursor 0] ++ + (List.range witness.shape.shape.constructors.length).map (.ctor witness.source 0 ·) + +def DeclarationWitness.outputs : DeclarationWitness β → List (ConstRef β) + | .definition witness => [witness.ref] + | .ordinary witness | .natural witness => witness.outputs + | .standard witness => [witness.ref] + | .quotient witness => Quotient.kinds.map witness.refs.ref + | .structure witness => witness.facts.block.outputs + | .modeled witness => witness.companions.map (·.header.ref) + +/-- Reusing an already available declaration grants no additional equation, +body or fact: the interface is unchanged. Every other declaration undergoes +the full admission check. This permits shared, independently checked closures +without replacing any chosen interpretation. -/ +def replayDeclarations? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) : List (DeclarationWitness β) → + Option (CheckedExtension.{u,v} signature store state) + | [] => some (CheckedExtension.refl state) + | witness :: rest => do + let step ← if witness.outputs.all (fun ref => (state.entries ref).isSome) then + some (CheckedExtension.refl state) + else checkDeclarationExtension?.{u,v} fuel (store := store) state witness + let rest ← replayDeclarations? fuel step.result rest + return step.trans rest + +/-- All semantic checks run again in the shared prefix. This constructs +compatibility of separately checked leaves instead of selecting unrelated +models and presuming they agree. Only published subjects discharge frontiers. -/ +def replayNodes? {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (known : List (ConstRef β)) : + (nodes : List (CheckedNode.{u,v} fuel signature store)) → + Option (ReplayResult state known nodes) + | [] => some ⟨CheckedExtension.refl state, .nil known, by simp [nodeSubjects], by simp⟩ + | node :: nodes => + if available : node.receipt.frontier.refs.all (known.contains ·) = true then + if aligned : node.receipt.frontier.headers.all (fun h => decide (HeaderPresent state.entries h)) = true then + do + let step ← replayDeclarations?.{u,v} fuel (store := store) state node.input.declarations + if present : node.input.subjects.all (fun ref => (step.result.entries ref).isSome) = true then do + let tail ← replayNodes? step.result (known ++ node.input.subjects) nodes + return { + checked := step.trans tail.checked + order := .cons (by simpa using List.all_eq_true.mp available) tail.order + subjects := by + intro ref hr + rcases List.mem_append.mp hr with hhead | htail + · have hp := List.all_eq_true.mp present ref hhead + obtain ⟨entry, he⟩ := Option.isSome_iff_exists.mp hp + exact Option.isSome_iff_exists.mpr ⟨entry, tail.checked.extension.lookup _ _ he⟩ + · exact tail.subjects ref htail + frontiers := by + intro other hm header hh + rcases List.mem_cons.mp hm with rfl | hm + · have h : HeaderPresent state.entries header := of_decide_eq_true + (List.all_eq_true.mp aligned header hh) + exact (h.extend step.extension).extend tail.checked.extension + · exact tail.frontiers other hm header hh + } + else none + else none + else none + +structure CheckedBatch (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (inputs : List (ClaimNode β)) where + nodes : List (CheckedNode.{u,v} fuel signature store) + exactNodes : nodes.map (·.input) = inputs + receipt : ConditionalStore.{u,v} signature store (nodeSubjects nodes) + exactFrontier : ∀ ref, ref ∈ receipt.frontier.refs ↔ ref ∈ outstanding nodes + order : DependencyOrder + (receipt.frontier.refs ++ [signature.falseType, signature.falseElim]) nodes + frontiers : ∀ node ∈ nodes, ∀ header ∈ node.receipt.frontier.headers, + HeaderPresent receipt.checked.result.entries header + +def checkBatch? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (frontier : List (FrontierWitness β)) (inputs : List (ClaimNode β)) : + Option (CheckedBatch.{u,v} fuel signature store inputs) := + if inputs.length > fuel then none else + match hn : inputs.mapM (checkNode?.{u,v} fuel signature store) with + | none => none + | some nodes => do + let dependencies ← checkFrontier?.{u,v} fuel signature store frontier + if exactFrontier : dependencies.refs.all (outstanding nodes |>.contains ·) = true ∧ + (outstanding nodes).all (dependencies.refs.contains ·) = true then + if fresh : (nodeSubjects nodes).all (fun ref => (dependencies.interface.entries ref).isNone) = true then do + let replay ← replayNodes? dependencies.interface + (dependencies.refs ++ [signature.falseType, signature.falseElim]) nodes + return { + nodes + exactNodes := by + have h := mapM_projection (checkNode?.{u,v} fuel signature store) (·.input) id + (fun _ _ h => checkNode?_input h) hn + simpa using h + receipt := ⟨dependencies, replay.checked, fun r hr => Option.isNone_iff_eq_none.mp + (List.all_eq_true.mp fresh r hr), replay.subjects⟩ + exactFrontier := by + intro ref + constructor + · intro hr; simpa using List.all_eq_true.mp exactFrontier.1 ref hr + · intro hr; simpa using List.all_eq_true.mp exactFrontier.2 ref hr + order := replay.order + frontiers := replay.frontiers + } + else none + else none + +def acceptsBatch (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (frontier : List (FrontierWitness β)) (inputs : List (ClaimNode β)) : Bool := + (checkBatch?.{u,v} fuel signature store frontier inputs).isSome + +/-- Every leaf's deferred interface is interpreted by the same final model. -/ +theorem CheckedBatch.compatible_leaves {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) + (V : Type v) [SetTheory V] (constants : Assignment β V) + (hM : signature.Compatible batch.receipt.checked.result.entries constants) + {node : CheckedNode.{u,v} fuel signature store} (hn : node ∈ batch.nodes) : + signature.Compatible node.receipt.frontier.interface.entries constants := + node.receipt.frontier.compatible batch.receipt.checked.result + (batch.frontiers node hn) V constants hM + +theorem CheckedFrontier.empty_interface {signature : PrimitiveSignature β} {store : Store β} + (frontier : CheckedFrontier.{u,v} signature store) (h : frontier.refs = []) : + frontier.interface.entries = signature.environment := by + have hh : frontier.headers = [] := List.map_eq_nil_iff.mp h + simp [CheckedFrontier.interface, hh, Signature.environment] + +/-- A closed aggregate constructs its model from the pinned prelude. No +realization of a private assumption set is a hypothesis of this theorem. -/ +theorem CheckedBatch.closed_has_model {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {inputs : List (ClaimNode β)} + (batch : CheckedBatch.{u,v} fuel signature store inputs) + (closed : batch.receipt.frontier.refs = []) (V : Type v) [SetTheory V] : + ∃ constants : Assignment β V, + signature.Compatible batch.receipt.checked.result.entries constants ∧ + ∀ ref ∈ nodeSubjects batch.nodes, ∃ entry, + batch.receipt.checked.result.entries ref = some entry ∧ + SourceHeader store ref entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env, + constants ref levels ∈ˢ interp constants levels env entry.type := by + have initial : signature.Compatible batch.receipt.frontier.interface.entries + (signature.assignment (V := V)) := by + rw [batch.receipt.frontier.empty_interface closed] + exact signature.compatible_assignment + obtain ⟨constants, hM, _, subjects⟩ := batch.receipt.subject_sound V signature.assignment initial + refine ⟨constants, hM, ?_⟩ + intro ref hr + obtain ⟨entry, he, _, hs, hm⟩ := subjects ref hr + exact ⟨entry, he, hs, fun levels hl env => (hm levels hl env).2⟩ + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Frontier.lean b/Ix/Theory/Certified/Frontier.lean new file mode 100644 index 000000000..1627a6c97 --- /dev/null +++ b/Ix/Theory/Certified/Frontier.lean @@ -0,0 +1,279 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Source + +/-! Conditional interfaces contain formed, source-bound headers. They carry +no assumed bodies, equations or primitive facts, and no claim that a model +exists. Object axioms and quotient primitives must use their semantic +producers; they cannot be deferred and later erased by frontier subtraction. -/ + +namespace Ix.Theory.Certified + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +def deferredSource (store : Store β) (ref : ConstRef β) : Bool := + match store.lookup ref with + | some (.defn _ _ _ _ .safe) | some (.induct _ _ _ _ _ .safe) | + some (.recursor _ _ _ _ _ _ _ _ .safe) => true + | some _ => false + | none => match store.lookupCtor ref with + | some ctor => ctor.safety == .safe + | none => false + +structure FrontierWitness (β : Type u) where + ref : ConstRef β + annotations : AnnotationTree + level : VLevel + typing : TypingWitness β + +structure FrontierHeader (store : Store β) where + header : Signature.Header β + source : SourceHeader store header.ref header.entry + allowed : deferredSource store header.ref = true + +def readFrontierHeader? (store : Store β) (witness : FrontierWitness β) : + Option (FrontierHeader store) := + if ha : deferredSource store witness.ref = true then + match ht : store.type witness.ref with + | none => none + | some type => match hn : store.uvars witness.ref with + | none => none + | some universes => do + let reading ← readAnnotations? universes 0 type witness.annotations + return { + header := ⟨witness.ref, universes, reading.val⟩ + source := ⟨ht.trans (congrArg some reading.property.1.symm), hn⟩ + allowed := ha + } + else none + +omit [DecidableEq β] in +theorem readFrontierHeader?_ref {store : Store β} {witness : FrontierWitness β} + {reading : FrontierHeader store} (h : readFrontierHeader? store witness = some reading) : + reading.header.ref = witness.ref := by + unfold readFrontierHeader? at h + split at h + · split at h + · cases h + · split at h + · cases h + · simp only [bind, Option.bind_eq_some_iff] at h + obtain ⟨value, _, h⟩ := h + cases Option.some.inj h + rfl + · cases h + +omit [DecidableEq β] in +theorem mapM_projection {α : Type _} {γ : Type _} {δ : Type _} + (f : α → Option γ) (project : γ → δ) (source : α → δ) + (step : ∀ a b, f a = some b → project b = source a) + {inputs : List α} {outputs : List γ} (h : inputs.mapM f = some outputs) : + outputs.map project = inputs.map source := by + induction inputs generalizing outputs with + | nil => simp only [List.mapM_nil, pure, Option.some.injEq] at h; subst outputs; rfl + | cons a rest ih => + simp only [List.mapM_cons, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at h + obtain ⟨b, hb, bs, hbs, rfl⟩ := h + simp only [List.map_cons, step a b hb, ih hbs] + +structure CheckedFrontier (signature : PrimitiveSignature β) (store : Store β) where + readings : List (FrontierHeader store) + validated : signature.validate store = true + formed : Signature.Formed.{u,v} signature.environment (readings.map (·.header)) + +def CheckedFrontier.headers {signature : PrimitiveSignature β} {store : Store β} + (frontier : CheckedFrontier.{u,v} signature store) : List (Signature.Header β) := + frontier.readings.map (·.header) + +def CheckedFrontier.refs {signature : PrimitiveSignature β} {store : Store β} + (frontier : CheckedFrontier.{u,v} signature store) : List (ConstRef β) := + frontier.headers.map (·.ref) + +def CheckedFrontier.interface {signature : PrimitiveSignature β} {store : Store β} + (frontier : CheckedFrontier.{u,v} signature store) : CheckedInterface signature where + entries := Signature.environment signature.environment frontier.headers + wf := frontier.formed.wf signature.environment_wf + present := ⟨frontier.formed.old signature.environment_false, + frontier.formed.old signature.environment_falseElim⟩ + +def checkFrontier? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (witnesses : List (FrontierWitness β)) : Option (CheckedFrontier.{u,v} signature store) := do + if hv : signature.validate store = true then + if witnesses.length > fuel then none else do + let readings ← witnesses.mapM (readFrontierHeader? store) + let checked ← Signature.checkTypes.{u,v} fuel signature.environment + (readings.map (·.header)) (witnesses.map fun witness => ⟨witness.level, witness.typing⟩) + return ⟨readings, hv, checked.down⟩ + else none + +theorem checkFrontier?_refs {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {witnesses : List (FrontierWitness β)} {result : CheckedFrontier.{u,v} signature store} + (h : checkFrontier? fuel signature store witnesses = some result) : + result.refs = witnesses.map (·.ref) := by + unfold checkFrontier? at h + split at h + · split at h + · cases h + · simp only [bind, Option.bind_eq_some_iff] at h + obtain ⟨readings, hr, formed, _, h⟩ := h + cases Option.some.inj h + simpa only [CheckedFrontier.refs, CheckedFrontier.headers, List.map_map, Function.comp_def] using + mapM_projection (readFrontierHeader? store) (fun r => r.header.ref) (·.ref) + (fun _ _ h => readFrontierHeader?_ref h) hr + · cases h + +theorem CheckedFrontier.header_source {signature : PrimitiveSignature β} {store : Store β} + (frontier : CheckedFrontier.{u,v} signature store) {header : Signature.Header β} + (h : header ∈ frontier.headers) : SourceHeader store header.ref header.entry := by + obtain ⟨reading, _, rfl⟩ := List.mem_map.mp h + exact reading.source + +/-- A provider may contain additional checked bodies and laws. Its entire +annotated type and universe arity must match the deferred header exactly. -/ +def HeaderPresent (entries : Environment β) (header : Signature.Header β) : Prop := + match entries header.ref with + | none => False + | some entry => entry.universes = header.universes ∧ entry.type = header.type + +instance (entries : Environment β) (header : Signature.Header β) : + Decidable (HeaderPresent entries header) := by + unfold HeaderPresent + split <;> infer_instance + +omit [DecidableEq β] in +theorem HeaderPresent.entry {entries : Environment β} {header : Signature.Header β} + (h : HeaderPresent entries header) : + ∃ entry, entries header.ref = some entry ∧ + entry.universes = header.universes ∧ entry.type = header.type := by + unfold HeaderPresent at h + cases he : entries header.ref with + | none => simp [he] at h + | some entry => exact ⟨entry, rfl, by simpa only [he] using h⟩ + +/-- The compatible interpretation of every provider gives one interpretation +of the complete deferred view, including shared references and primitive pins. -/ +theorem CheckedFrontier.compatible {signature : PrimitiveSignature β} {store : Store β} + (frontier : CheckedFrontier.{u,v} signature store) (provider : CheckedInterface signature) + (headers : ∀ header ∈ frontier.headers, HeaderPresent provider.entries header) + (V : Type v) [SetTheory V] (constants : Assignment β V) + (hM : signature.Compatible provider.entries constants) : + signature.Compatible frontier.interface.entries constants := by + have old : ∀ r entry, signature.environment r = some entry → + provider.entries r = some entry := by + intro r entry he + unfold PrimitiveSignature.environment at he + split at he + · subst r; cases Option.some.inj he; exact provider.present.1 + · split at he + · subst r; cases Option.some.inj he; exact provider.present.2 + · cases he + have he : ∀ r entry, frontier.interface.entries r = some entry → + ∃ actual, provider.entries r = some actual ∧ + actual.universes = entry.universes ∧ actual.type = entry.type ∧ + entry.body = none ∧ entry.equations = [] ∧ entry.facts = [] := by + intro r entry hr + rcases Signature.environment_source hr with hbase | ⟨header, hh, rfl, rfl⟩ + · refine ⟨entry, old r entry hbase, rfl, rfl, ?_⟩ + unfold PrimitiveSignature.environment at hbase + split at hbase + · cases Option.some.inj hbase; exact ⟨rfl, rfl, rfl⟩ + · split at hbase + · cases Option.some.inj hbase; exact ⟨rfl, rfl, rfl⟩ + · cases hbase + · obtain ⟨actual, ha, hu, ht⟩ := (headers header hh).entry + exact ⟨actual, ha, hu, ht, rfl, rfl, rfl⟩ + refine ⟨?_, hM.falseValue, hM.falseElimValue⟩ + constructor + · intro r entry hr levels hn env + obtain ⟨actual, ha, hu, ht, _⟩ := he r entry hr + rw [← ht] + exact hM.realizes.typeValid r actual ha levels (hn.trans hu.symm) env + · intro r entry hr levels hn env + obtain ⟨actual, ha, hu, ht, _⟩ := he r entry hr + rw [← ht] + exact hM.realizes.member r actual ha levels (hn.trans hu.symm) env + · intro r entry hr body hb + rw [(he r entry hr).choose_spec.2.2.2.1] at hb + cases hb + · intro r entry hr body hb + rw [(he r entry hr).choose_spec.2.2.2.1] at hb + cases hb + · intro r entry hr law hl + rw [(he r entry hr).choose_spec.2.2.2.2.1] at hl + cases hl + · intro r entry hr fact hf + rw [(he r entry hr).choose_spec.2.2.2.2.2] at hf + cases hf + +structure ConditionalStore (signature : PrimitiveSignature β) (store : Store β) + (subjects : List (ConstRef β)) where + frontier : CheckedFrontier.{u,v} signature store + checked : CheckedExtension.{u,v} signature store frontier.interface + fresh : ∀ r ∈ subjects, frontier.interface.entries r = none + present : ∀ r ∈ subjects, (checked.result.entries r).isSome = true + +def checkConditionalStore? (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (frontier : List (FrontierWitness β)) (subjects : List (ConstRef β)) + (witness : List (DeclarationWitness β)) : Option (ConditionalStore.{u,v} signature store subjects) := do + let dependencies ← checkFrontier?.{u,v} fuel signature store frontier + if fresh : subjects.all (fun r => (dependencies.interface.entries r).isNone) = true then + let checked ← checkDeclarationExtensions?.{u,v} fuel (store := store) dependencies.interface witness + if present : subjects.all (fun r => (checked.result.entries r).isSome) = true then + return ⟨dependencies, checked, fun r hr => Option.isNone_iff_eq_none.mp + (List.all_eq_true.mp fresh r hr), List.all_eq_true.mp present⟩ + else none + else none + +theorem checkConditionalStore?_frontier {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {frontier : List (FrontierWitness β)} {subjects : List (ConstRef β)} + {witness : List (DeclarationWitness β)} {result : ConditionalStore.{u,v} signature store subjects} + (h : checkConditionalStore? fuel signature store frontier subjects witness = some result) : + checkFrontier? fuel signature store frontier = some result.frontier := by + unfold checkConditionalStore? at h + simp only [bind, Option.bind_eq_some_iff] at h + obtain ⟨dependencies, hd, h⟩ := h + split at h + · simp only [Option.bind_eq_some_iff] at h + obtain ⟨checked, _, h⟩ := h + split at h + · cases Option.some.inj h; exact hd + · cases h + · cases h + +/-- No realization of the frontier is fabricated. Every realization supplied +by checked dependencies extends compatibly to all the exact subject types. -/ +theorem ConditionalStore.subject_sound {signature : PrimitiveSignature β} {store : Store β} + {subjects : List (ConstRef β)} (receipt : ConditionalStore.{u,v} signature store subjects) + (V : Type v) [SetTheory V] (constants : Assignment β V) + (hM : signature.Compatible receipt.frontier.interface.entries constants) : + ∃ constants' : Assignment β V, + signature.Compatible receipt.checked.result.entries constants' ∧ + Assignment.AgreesOn receipt.frontier.interface.entries constants constants' ∧ + ∀ ref ∈ subjects, ∃ entry, receipt.checked.result.entries ref = some entry ∧ + EntrySource signature store ref entry ∧ SourceHeader store ref entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants' levels env entry.type ∧ + constants' ref levels ∈ˢ interp constants' levels env entry.type := by + obtain ⟨constants', hM', ha⟩ := receipt.checked.extension.models V constants hM + refine ⟨constants', hM', ha, ?_⟩ + intro ref hr + have hp := receipt.present ref hr + cases he : receipt.checked.result.entries ref with + | none => simp [he] at hp + | some entry => + have hs : EntrySource signature store ref entry := by + rcases receipt.checked.source ref entry he with old | new + · rw [receipt.fresh ref hr] at old; cases old + · exact new + refine ⟨entry, rfl, hs, hs.header, ?_⟩ + intro levels hl env + exact ⟨hM'.realizes.typeValid ref entry he levels hl env, + hM'.realizes.member ref entry he levels hl env⟩ + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Level.lean b/Ix/Theory/Certified/Level.lean new file mode 100644 index 000000000..787ce5a18 --- /dev/null +++ b/Ix/Theory/Certified/Level.lean @@ -0,0 +1,121 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.PropWhen + +namespace Ix.Theory.Certified + +open VLevel + +/-- Compute the exact zero condition of a level. `imax` is zero exactly when +its right operand is zero; its left operand still needs a scoping check. -/ +def zeroCondition : VLevel → PropWhen + | .zero => .always + | .succ _ => .never + | .max a b => (zeroCondition a).inter (zeroCondition b) + | .imax _ b => zeroCondition b + | .param i => .param i + +theorem zeroCondition_correct (l : VLevel) (values : List Nat) : + (zeroCondition l).holds (values.getD · 0) = (l.eval values == 0) := by + induction l with + | zero => rfl + | succ l ih => simp [zeroCondition, eval] + | max a b ha hb => + rw [zeroCondition, PropWhen.holds_inter, ha, hb] + apply Bool.eq_iff_iff.mpr + simp [eval, Nat.max_eq_zero_iff] + | imax a b ha hb => + simp only [zeroCondition, hb] + apply Bool.eq_iff_iff.mpr + by_cases h : b.eval values = 0 + · simp [eval, natIMax, h] + · simp [eval, natIMax, h, Nat.max_eq_zero_iff] + | param i => simp [zeroCondition, eval] + +theorem zeroCondition_wf {n : Nat} {l : VLevel} (h : l.WF n) : + (zeroCondition l).WF n := by + induction l with + | zero => simp [zeroCondition, PropWhen.always, PropWhen.WF] + | succ l ih => trivial + | max a b ha hb => exact PropWhen.WF.inter (ha h.1) (hb h.2) + | imax a b ha hb => exact hb h.2 + | param i => simpa [zeroCondition, PropWhen.param, PropWhen.WF, VLevel.WF] using h + +/-- Substitute actual anonymous levels into an annotation. Out-of-bounds +fallback agrees with `VLevel.inst`; successful validation rules it out. -/ +def instCondition (levels : List VLevel) (p : PropWhen) : PropWhen := + p.bind (fun i => zeroCondition (levels.getD i .zero)) + +theorem zeroCondition_inst (l : VLevel) (levels : List VLevel) : + zeroCondition (l.inst levels) = instCondition levels (zeroCondition l) := by + induction l with + | zero => rfl + | succ l ih => rfl + | max a b ha hb => + simpa only [zeroCondition, VLevel.inst, instCondition, PropWhen.bind_inter] using + congr (congrArg PropWhen.inter ha) hb + | imax a b ha hb => exact hb + | param i => simp [VLevel.inst, zeroCondition, instCondition] + +theorem instCondition_correct (levels : List VLevel) (p : PropWhen) (values : List Nat) : + (instCondition levels p).holds (values.getD · 0) = + p.holds ((levels.map (VLevel.eval values)).getD · 0) := by + apply PropWhen.holds_bind_of + intro i + rw [zeroCondition_correct] + simp only [List.getD_eq_getElem?_getD, List.getElem?_map] + cases levels[i]? <;> rfl + +theorem instCondition_comp (p : PropWhen) (levels levels' : List VLevel) : + instCondition levels' (instCondition levels p) = + instCondition (levels.map (VLevel.inst levels')) p := by + cases p with + | never => rfl + | allZero ps hs => + change instCondition levels' (PropWhen.bindList _ ps) = PropWhen.bindList _ ps + clear hs + induction ps with + | nil => rfl + | cons i ps ih => + simp only [PropWhen.bindList, instCondition, PropWhen.bind_inter] at ih ⊢ + rw [ih] + congr 1 + rw [← instCondition, ← zeroCondition_inst] + simp only [List.getD_eq_getElem?_getD, List.getElem?_map] + cases levels[i]? <;> rfl + +/-- Validate the exact claimed condition, its canonical encoding, and every +universe index of the source level. This is executable and fails closed. -/ +def validateZero? (n : Nat) (l : VLevel) (raw : Option (List Nat)) : Option PropWhen := do + if !decide (l.WF n) then none else do + let p ← PropWhen.fromRaw? n raw + if p = zeroCondition l then some p else none + +theorem validateZero?_sound {n : Nat} {l : VLevel} {raw : Option (List Nat)} + {p : PropWhen} (h : validateZero? n l raw = some p) : + l.WF n ∧ p.toRaw = raw ∧ p.WF n ∧ p = zeroCondition l := by + simp only [validateZero?] at h + split at h + · contradiction + next hw => + have hw : l.WF n := by simpa using hw + cases he : PropWhen.fromRaw? n raw with + | none => simp [he] at h + | some q => + simp only [he] at h + change (if q = zeroCondition l then some q else none) = some p at h + split at h + next hq => + cases h + obtain ⟨hr, hqw⟩ := PropWhen.fromRaw?_sound he + exact ⟨hw, hr, hqw, hq⟩ + · contradiction + +theorem validateZero?_complete {n : Nat} {l : VLevel} (h : l.WF n) : + validateZero? n l (zeroCondition l).toRaw = some (zeroCondition l) := by + simp [validateZero?, h, PropWhen.fromRaw?_complete (zeroCondition_wf h)] + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/LevelEq.lean b/Ix/Theory/Certified/LevelEq.lean new file mode 100644 index 000000000..04c431306 --- /dev/null +++ b/Ix/Theory/Certified/LevelEq.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Level + +namespace Ix.Theory.Certified + +namespace LevelEq + +/-- A structural upper-bound check, used only when it proves pointwise +ordering. In particular, a field at u fits a carrier at u+1. -/ +def leq (a b : VLevel) : Bool := + if a = b then true else + match a, b with + | .zero, _ => true + | .max a b, c => leq a c && leq b c + | a, .max b c => leq a b || leq a c + | .succ a, .succ b => leq a b + | a, .succ b => leq a b + | .imax a b, c => leq a c && leq b c + | _, _ => false +termination_by sizeOf a + sizeOf b + +theorem leq_sound {a b : VLevel} (h : leq a b = true) (values : List Nat) : + a.eval values ≤ b.eval values := by + unfold leq at h + split at h + next he => subst b; exact Nat.le_refl _ + next => + split at h + next => exact Nat.zero_le _ + next a b c => + simp only [Bool.and_eq_true] at h + exact Nat.max_le.mpr ⟨leq_sound h.1 values, leq_sound h.2 values⟩ + next a b c => + simp only [Bool.or_eq_true] at h + rcases h with h | h + · exact Nat.le_trans (leq_sound h values) (Nat.le_max_left _ _) + · exact Nat.le_trans (leq_sound h values) (Nat.le_max_right _ _) + next a b => exact Nat.succ_le_succ (leq_sound h values) + next a b => exact Nat.le_trans (leq_sound h values) (Nat.le_succ _) + next a b c => + simp only [Bool.and_eq_true] at h + have hm := Nat.max_le.mpr ⟨leq_sound h.1 values, leq_sound h.2 values⟩ + change VLevel.natIMax _ _ ≤ _ + unfold VLevel.natIMax + split + · exact Nat.zero_le _ + · exact hm + next => contradiction +termination_by sizeOf a + sizeOf b + +/-- Conservative simplification. Failure to identify equivalent levels is a +decline, never permission to compare their zero conditions as full levels. -/ +def max (a b : VLevel) : VLevel := + match a, b with + | .zero, b => b + | a, .zero => a + | a, b => if leq a b then b else if leq b a then a else .max a b + +theorem eval_max (a b : VLevel) (values : List Nat) : + (max a b).eval values = Nat.max (a.eval values) (b.eval values) := by + unfold max + split <;> simp_all [VLevel.eval] + split + next h => exact (Nat.max_eq_right (leq_sound h values)).symm + next => + split + next h => exact (Nat.max_eq_left (leq_sound h values)).symm + next => rfl + +def imax (a b : VLevel) : VLevel := + match a, b with + | _, .zero => .zero + | a, .succ b => max a (.succ b) + | .zero, b => b + | a, b => if a = b then a else .imax a b + +theorem eval_imax (a b : VLevel) (values : List Nat) : + (imax a b).eval values = VLevel.natIMax (a.eval values) (b.eval values) := by + unfold imax + split + · simp [VLevel.eval, VLevel.natIMax] + · simp [eval_max, VLevel.eval, VLevel.natIMax] + · simp only [VLevel.eval, VLevel.natIMax, Nat.zero_max] + split <;> simp_all + · split + · subst b + simp [VLevel.natIMax] + · rfl + +def normalize : VLevel → VLevel + | .zero => .zero + | .param i => .param i + | .succ a => .succ (normalize a) + | .max a b => max (normalize a) (normalize b) + | .imax a b => imax (normalize a) (normalize b) + +theorem eval_normalize (l : VLevel) (values : List Nat) : + (normalize l).eval values = l.eval values := by + induction l <;> simp_all [normalize, VLevel.eval, eval_max, eval_imax] + +def check (n : Nat) (a b : VLevel) : Bool := + decide (a.WF n ∧ b.WF n) && decide (normalize a = normalize b) + +theorem check_sound {n : Nat} {a b : VLevel} (h : check n a b = true) : + a.WF n ∧ b.WF n ∧ ∀ values, a.eval values = b.eval values := by + simp only [check, Bool.and_eq_true, decide_eq_true_eq] at h + refine ⟨h.1.1, h.1.2, fun values => ?_⟩ + rw [← eval_normalize a values, ← eval_normalize b values, h.2] + +end LevelEq + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/LogicalPolicy.lean b/Ix/Theory/Certified/LogicalPolicy.lean new file mode 100644 index 000000000..974b2dcb0 --- /dev/null +++ b/Ix/Theory/Certified/LogicalPolicy.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Frontier + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +/-- Enumerate source members, retaining exact block and member positions. -/ +def sourceMembers (store : Store β) : List (ConstRef β) := + store.dom.flatMap fun block => match store.blocks block with + | none => [] + | some contents => (List.range contents.members.length).map (.member block ·) + +omit [DecidableEq β] in +theorem lookup_mem_sourceMembers {store : Store β} {ref : ConstRef β} {source : Const β} + (h : store.lookup ref = some source) : ref ∈ sourceMembers store := by + cases ref with + | ctor => cases h + | member block index => + cases hb : store.blocks block with + | none => simp [Store.lookup, hb] at h + | some contents => + have hm : contents.members[index]? = some source := by simpa [Store.lookup, hb] using h + have hi : index < contents.members.length := (List.getElem?_eq_some_iff.mp hm).choose + apply List.mem_flatMap.mpr + refine ⟨block, (store.mem_dom block).mp (by simp [hb]), ?_⟩ + simp only [hb] + exact List.mem_map.mpr ⟨index, List.mem_range.mpr hi, rfl⟩ + +def isLogicalAxiom (store : Store β) (ref : ConstRef β) : Bool := + match store.lookup ref with + | some (.axiom ..) => true + | _ => false + +/-- The manifest records all admitted source axioms, even unused ones. It is +computed from source kinds and the actual checked environment; it never +subtracts checked subjects or trusts a prover's declaration of axiom use. -/ +def logicalAxioms (store : Store β) (entries : Environment β) : List (ConstRef β) := + (sourceMembers store).filter fun ref => isLogicalAxiom store ref && (entries ref).isSome + +omit [DecidableEq β] in +theorem mem_logicalAxioms {store : Store β} {entries : Environment β} {ref : ConstRef β} : + ref ∈ logicalAxioms store entries ↔ + (∃ n type safety, store.lookup ref = some (.axiom n type safety)) ∧ + ∃ entry, entries ref = some entry := by + constructor + · intro h + obtain ⟨_, h⟩ := List.mem_filter.mp h + have hh : isLogicalAxiom store ref = true ∧ (entries ref).isSome = true := by simpa using h + obtain ⟨ha, he⟩ := hh + have hs : ∃ n type safety, store.lookup ref = some (.axiom n type safety) := by + unfold isLogicalAxiom at ha + cases hl : store.lookup ref with + | none => simp [hl] at ha + | some source => cases source <;> simp_all + exact ⟨hs, Option.isSome_iff_exists.mp he⟩ + · rintro ⟨⟨n, type, safety, hs⟩, entry, he⟩ + exact List.mem_filter.mpr ⟨lookup_mem_sourceMembers hs, by simp [isLogicalAxiom, hs, he]⟩ + +omit [DecidableEq β] in +theorem logicalAxioms_monotone {signature : PrimitiveSignature β} {store : Store β} + {a b : Environment β} (h : Extends.{u,v} signature a b) {ref : ConstRef β} + (hr : ref ∈ logicalAxioms store a) : ref ∈ logicalAxioms store b := by + obtain ⟨source, entry, he⟩ := mem_logicalAxioms.mp hr + exact mem_logicalAxioms.mpr ⟨source, entry, h.lookup ref entry he⟩ + +theorem CheckedFrontier.no_axioms {signature : PrimitiveSignature β} {store : Store β} + (frontier : CheckedFrontier.{u,v} signature store) {ref : ConstRef β} {entry : ConstantEntry β} + {n : Nat} {type : VExpr β} {safety : Safety} + (hs : store.lookup ref = some (.axiom n type safety)) : + frontier.interface.entries ref ≠ some entry := by + intro hr + rcases Signature.environment_source hr with old | ⟨header, hh, rfl, _⟩ + · have hv := (signature.validate_iff store).mp frontier.validated + unfold PrimitiveSignature.environment at old + split at old + · subst ref; rw [hv.1] at hs; cases hs + · split at old + · subst ref; rw [hv.2] at hs; cases hs + · cases old + · obtain ⟨reading, _, rfl⟩ := List.mem_map.mp hh + have ha := reading.allowed + simp [deferredSource, hs] at ha + +omit [DecidableEq β] in +/-- Every object axiom in an admitted interface is one of the exactly realized +standard schemas or quotient soundness, with its original source preserved. -/ +theorem EntrySource.axiom_policy {signature : PrimitiveSignature β} {store : Store β} + {ref : ConstRef β} {entry : ConstantEntry β} {n : Nat} {type : VExpr β} {safety : Safety} + (source : EntrySource signature store ref entry) + (hs : store.lookup ref = some (.axiom n type safety)) : + Standard.EntrySource store ref entry ∨ Quotient.EntrySource store ref entry := by + rcases source with ⟨_, _, he⟩ | ⟨_, _, he⟩ | ⟨_, _, _, _, _, he⟩ | h | h | h | h | h | h + · rw [he] at hs; cases hs + · rw [he] at hs; cases hs + · rw [he] at hs; cases hs + · rcases h with ⟨shape, block, recursor, mode, hb, hr, h⟩ + rcases h with ⟨rfl, _⟩ | ⟨index, ctor, _, rfl, _⟩ | ⟨rfl, _⟩ + · simp [Store.lookup, hb, Ordinary.Shape.source] at hs + · cases hs + · rcases hr with hr | ⟨_, hr⟩ <;> + simp [Store.lookup, hr, Ordinary.Shape.recursorSource] at hs + · exact Or.inl h + · exact Or.inr h + · rcases h with ⟨description, block, recursor, mode, hb, _, rfl, _⟩ + simp [Store.lookup, hb, Ordinary.Shape.source] at hs + · rcases h with ⟨_, block, recursor, mode, hb, _, rfl, _⟩ + simp [Store.lookup, hb, Ordinary.Shape.source] at hs + · exact False.elim (h.not_axiom hs) + +theorem ConditionalStore.logical_axioms_authorized {signature : PrimitiveSignature β} + {store : Store β} {subjects : List (ConstRef β)} + (receipt : ConditionalStore.{u,v} signature store subjects) {ref : ConstRef β} + (h : ref ∈ logicalAxioms store receipt.checked.result.entries) : + ∃ entry, receipt.checked.result.entries ref = some entry ∧ + (Standard.EntrySource store ref entry ∨ Quotient.EntrySource store ref entry) := by + obtain ⟨⟨n, type, safety, hs⟩, entry, he⟩ := mem_logicalAxioms.mp h + refine ⟨entry, he, ?_⟩ + rcases receipt.checked.source ref entry he with old | new + · exact False.elim (receipt.frontier.no_axioms hs old) + · exact new.axiom_policy hs + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Modeled/Admission.lean b/Ix/Theory/Certified/Modeled/Admission.lean new file mode 100644 index 000000000..0eea3996c --- /dev/null +++ b/Ix/Theory/Certified/Modeled/Admission.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Admission + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +/-- Simultaneous model companions preserve every earlier interpretation. +Models and their equation proofs must already be available through preceding +admissions; the new source block cannot justify its own model. -/ +def checkModeledExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (witness : Modeled.Witness β) : + Option (CheckedExtension.{u,v} signature store state) := do + let checked ← Modeled.check?.{u,v} fuel state.entries store witness + let entries := Modeled.environment state.entries witness.companions + have extension : Extends.{u,v} signature state.entries entries := by + constructor + · intro ref entry he + exact Environment.overlay_old checked.down.models.fresh_overlay he + · intro V _ constants hM + let constants' := Modeled.assignment constants witness.companions + have hm := Modeled.assignment_realizes checked.down.models state.wf constants hM.realizes + have ha := Modeled.assignment_agrees checked.down.models constants + exact ⟨constants', hM.extend signature state.present hm ha, ha⟩ + let result : CheckedInterface signature := { + entries + wf := Modeled.environment_wf checked.down.models state.wf + present := ⟨extension.lookup _ _ state.present.1, extension.lookup _ _ state.present.2⟩ + } + return { + result, extension + source := by + intro ref entry he + dsimp only [result] at he + rcases Modeled.publishedEntry_source checked.down he with old | new + · exact Or.inl old + · exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr new)))))))) + } + +def admitModeled? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : Modeled.Witness β) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkModeledExtension?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +theorem admitModeled?_extends {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {state : AdmittedEnvironment.{u,v} signature store} {witness : Modeled.Witness β} {result} + (_ : admitModeled? fuel state witness = some result) : + Extends.{u,v} signature state.entries result.val.entries := result.property + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Modeled/Equation.lean b/Ix/Theory/Certified/Modeled/Equation.lean new file mode 100644 index 000000000..fa270584d --- /dev/null +++ b/Ix/Theory/Certified/Modeled/Equation.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Signature +import Ix.Theory.Certified.Basis.Equality + +/-! Model equations may follow from checked conversion or from a checked +proof of the realized equality relation. Both complete endpoints and their +common type are checked before an equation can be published. -/ + +namespace Ix.Theory.Certified.Modeled + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +inductive EquationProof (β : Type u) where + | conversion (witness : ConversionWitness β) + | propositional (family reflexivity recursor : ConstRef β) + (proof : AExpr β) (witness : TypingWitness β) + +structure EquationWitness (β : Type u) where + formation : Signature.RuleWitness β + proof : EquationProof β + +structure CheckedEquation (entries : Environment β) (rule : Signature.Rule β) : Prop where + formed : Signature.RuleFormed.{u,v} entries rule + equality : ConversionClaim.{u,v} entries [] rule.lhs rule.rhs + +omit [DecidableEq β] in +theorem propositional_equation {entries : Environment β} {family reflexivity recursor : ConstRef β} + (interface : Basis.Equality.Interface entries family reflexivity recursor) + {rule : Signature.Rule β} {level : VLevel} {proof : AExpr β} + (type : TypingClaim.{u,v} entries [] rule.type (.sort level)) + (lhs : TypingClaim.{u,v} entries [] rule.lhs rule.type) + (rhs : TypingClaim.{u,v} entries [] rule.rhs rule.type) + (checked : TypingClaim.{u,v} entries [] proof + (Basis.Equality.applied family level rule.type rule.lhs rule.rhs)) : + ConversionClaim.{u,v} entries [] rule.lhs rule.rhs := by + intro V _ constants hM levels env hΓ + have htype := (type V constants hM levels env hΓ).2.2 + have hlhs := (lhs V constants hM levels env hΓ).2.2 + have hrhs := (rhs V constants hM levels env hΓ).2.2 + have hproof := (checked V constants hM levels env hΓ).2.2 + apply Basis.Equality.eq_of_mem interface hM (by simpa only [interp] using htype) hlhs hrhs + simpa only [Basis.Equality.applied, AExpr.appN, interp, List.map_cons, List.map_nil, + Basis.Equality.value] using hproof + +def checkEquation? (fuel : Nat) (entries : Environment β) (rule : Signature.Rule β) + (witness : EquationWitness β) : Option (CheckedClaim.{u} (CheckedEquation.{u,v} entries rule)) := do + let formed ← Signature.checkRule.{u,v} fuel entries rule witness.formation + match witness.proof with + | .conversion witness => + let equality ← verifyConversion.{u,v} fuel rule.universes entries [] rule.lhs rule.rhs witness + return ⟨formed.down, equality.down⟩ + | .propositional family reflexivity recursor proof typing => + if hi : Basis.Equality.Interface entries family reflexivity recursor then do + let type ← verifyType.{u,v} fuel rule.universes entries [] rule.type + (.sort witness.formation.level) witness.formation.type + let checked ← verifyType.{u,v} fuel rule.universes entries [] proof + (Basis.Equality.applied family witness.formation.level rule.type rule.lhs rule.rhs) typing + return ⟨formed.down, propositional_equation hi type.down formed.down.lhs formed.down.rhs checked.down⟩ + else none + +theorem checkEquation?_sound {fuel : Nat} {entries : Environment β} {rule : Signature.Rule β} + {witness : EquationWitness β} {result} + (_ : checkEquation?.{u,v} fuel entries rule witness = some result) : + CheckedEquation.{u,v} entries rule := result.down + +end Ix.Theory.Certified.Modeled diff --git a/Ix/Theory/Certified/Modeled/Source.lean b/Ix/Theory/Certified/Modeled/Source.lean new file mode 100644 index 000000000..da6dd905f --- /dev/null +++ b/Ix/Theory/Certified/Modeled/Source.lean @@ -0,0 +1,268 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Modeled.Transport + +/-! Exact source readings for model companions. The rule reader constructs +the whole left endpoint from the stored recursor type, specializes the actual +constructor at the major's universe and parameter arguments, and retains the +stored right endpoint. It grants no equation until `checkCompanions?` checks +the corresponding complete equation in the earlier model environment. + +Mutual recursors use the store's global constructor offsets. Only rules for +the recursor's actual major family are published on that recursor. Copies of +other families' rules in a shared table do not enable a reduction. Restored +nested auxiliary recursors use their target block's native constructor slots. +-/ + +namespace Ix.Theory.Certified.Modeled + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +structure FamilySource (β : Type u) where + universes : Nat + parameters : Nat + indices : Nat + type : VExpr β + constructors : List (Ctor β) + +def familySource? (store : Store β) (ref : ConstRef β) : Option (FamilySource β) := do + let .induct universes parameters indices type constructors .safe ← store.lookup ref | none + return ⟨universes, parameters, indices, type, constructors⟩ + +structure RecursorSource (β : Type u) where + universes : Nat + parameters : Nat + indices : Nat + motives : Nat + minors : Nat + type : VExpr β + rules : List (RecRule β) + +/-- K is deliberately unavailable on this admission route. It requires its +own semantic law; a model equation does not grant proof replacement. -/ +def recursorSource? (store : Store β) (ref : ConstRef β) : Option (RecursorSource β) := do + let .recursor universes parameters indices motives minors type rules false .safe ← store.lookup ref | none + return ⟨universes, parameters, indices, motives, minors, type, rules⟩ + +def RecursorSource.prefix (source : RecursorSource β) : Nat := + source.parameters + source.motives + source.minors + +/-- Unlike `telN`/`dropN`, a short telescope positively declines. -/ +def splitPi? : Nat → VExpr β → Option (List (VExpr β) × VExpr β) + | 0, type => some ([], type) + | n + 1, .forallE domain body => do + let (domains, result) ← splitPi? n body + return (domain :: domains, result) + | _ + 1, _ => none + +def splitLam? : Nat → VExpr β → Option (List (VExpr β) × VExpr β) + | 0, expression => some ([], expression) + | n + 1, .lam domain body => do + let (domains, result) ← splitLam? n body + return (domain :: domains, result) + | _ + 1, _ => none + +def applyPi? : VExpr β → List (VExpr β) → Option (VExpr β) + | type, [] => some type + | .forallE _ body, argument :: rest => applyPi? (body.inst argument) rest + | _, _ :: _ => none + +/-- Inspect a constant-headed application through explicit beta redexes. +Restoration may leave a parameter abstraction applied to its arguments. No +definition, equation, projection or other conversion is used by this reader. +The original type and complete equation are still checked without rewriting +their source erasures. Fuel exhaustion is a positive decline. -/ +def betaHead? : Nat → VExpr β → Option (VExpr β) + | 0, _ => none + | fuel + 1, .app function argument => do + let function ← betaHead? fuel function + match function with + | .lam _ body => betaHead? fuel (body.inst argument) + | _ => some (.app function argument) + | _ + 1, expression => some expression + +structure MajorSource (β : Type u) where + family : ConstRef β + levels : List VLevel + parameters : List (VExpr β) + prefixDomains : List (VExpr β) + +/-- Read the actual major, including nested parameter expressions. Removing +the index frame must round-trip exactly, so parameters cannot secretly depend +on the fresh result indices. The index arguments themselves are pinned. -/ +def majorSource? (store : Store β) (source : RecursorSource β) : Option (MajorSource β) := do + let (prefixDomains, tail) ← splitPi? source.prefix source.type + let (_, .forallE major _) ← splitPi? source.indices tail | none + let major ← betaHead? 512 major + let .const family levels := major.appHead | none + let info ← familySource? store family + if info.indices != source.indices || levels.length != info.universes then none else do + let arguments := major.appArgs [] + if arguments.length != info.parameters + source.indices then none else do + if arguments.drop info.parameters != VExpr.bvarRevRange 0 source.indices then none else do + let actual := arguments.take info.parameters + let parameters := actual.map (fun p => p.unliftN source.indices 0) + if parameters.map (·.liftN source.indices) != actual then none else + return ⟨family, levels, parameters, prefixDomains⟩ + +structure RawRule (β : Type u) where + universes : Nat + type : VExpr β + lhs : VExpr β + rhs : VExpr β + deriving DecidableEq + +def eraseRule (rule : Signature.Rule β) : RawRule β := + ⟨rule.universes, rule.type.erase, rule.lhs.erase, rule.rhs.erase⟩ + +/-- Construct the exact source rule at a constructor's native flattened slot. +The specialized field telescope, result family, levels, parameters and indices +determine its whole common type. The complete stored lambda telescope is +retained on the right, and `checkEquation?` checks it against that type; beta +redexes left by restoration need not have identical domain spellings. -/ +def ruleSource? (store : Store β) (recursor : ConstRef β) (source : RecursorSource β) + (major : MajorSource β) (constructor : ConstRef β) : Option (RawRule β) := do + let .ctor block member _ := constructor | none + if major.family != .member block member then none else do + let family ← familySource? store major.family + let ctor ← store.lookupCtor constructor + if ctor.safety != .safe || ctor.uvars != family.universes || + ctor.nparams != family.parameters then none else do + let some slot := store.ctorRuleIndex? constructor | none + let stored ← source.rules[slot]? + if stored.nfields != ctor.nfields then none else do + let specialized ← applyPi? ((ctor.type.instL major.levels).liftN source.prefix) major.parameters + let (fields, result) ← splitPi? ctor.nfields specialized + if result.appHead != .const major.family major.levels then none else do + let args := result.appArgs [] + let parameters := major.parameters.map (·.liftN ctor.nfields) + if args.length != ctor.nparams + source.indices || args.take ctor.nparams != parameters then none else do + let constructorValue := VExpr.appN (.const constructor major.levels) + (parameters ++ VExpr.bvarRevRange 0 ctor.nfields) + let callArgs := VExpr.bvarRevRange ctor.nfields source.prefix ++ + args.drop ctor.nparams ++ [constructorValue] + let resultType ← applyPi? (source.type.liftN (source.prefix + ctor.nfields)) callArgs + let telescope := major.prefixDomains ++ fields + let _ ← splitLam? telescope.length stored.rhs + return ⟨source.universes, VExpr.forallN telescope resultType, + VExpr.lamN telescope (VExpr.appN (.const recursor ((List.range source.universes).map VLevel.param)) + callArgs), stored.rhs⟩ + +def familyConstructors? (store : Store β) (ref : ConstRef β) : Option (List (ConstRef β)) := do + let .member block member := ref | none + let source ← familySource? store ref + return (List.range source.constructors.length).map (.ctor block member ·) + +def recursorRules? (store : Store β) (ref : ConstRef β) : Option (List (RawRule β)) := do + let source ← recursorSource? store ref + let major ← majorSource? store source + let constructors ← familyConstructors? store major.family + constructors.mapM (ruleSource? store ref source major) + +/-- A family or constructor gains no computation, projection, eta or K fact +from this route. A recursor gains exactly its checked source equations. -/ +def sourceRules? (store : Store β) (ref : ConstRef β) : Option (List (RawRule β)) := + match ref with + | .ctor block member _ => do + let _ ← familySource? store (.member block member) + let ctor ← store.lookupCtor ref + if ctor.safety = .safe then some [] else none + | .member .. => + match store.lookup ref with + | some (.induct _ _ _ _ _ .safe) => some [] + | some (.recursor ..) => recursorRules? store ref + | _ => none + +def SourceMatches (store : Store β) (companion : Companion β) : Prop := + store.type companion.header.ref = some companion.header.type.erase ∧ + store.uvars companion.header.ref = some companion.header.universes ∧ + sourceRules? store companion.header.ref = some (companion.rules.map eraseRule) + +instance (store : Store β) (companion : Companion β) : Decidable (SourceMatches store companion) := + inferInstanceAs (Decidable (_ ∧ _ ∧ _)) + +def sourceFamilies? (store : Store β) (source : β) : Option (List (ConstRef β)) := do + let contents ← store.blocks source + if contents.members.isEmpty then none else do + contents.members.zipIdx.mapM fun (constant, index) => + match constant with + | .induct _ _ _ _ _ .safe => some (.member source index) + | _ => none + +/-- Public family and constructor order is the actual block/member/constructor +order. Original recursors come first, in family order; checked auxiliary +recursors may follow. Each auxiliary's own major and native slots are read +independently, so a proposed permutation cannot change a rule's owner. -/ +def sourceRefs? (store : Store β) (source : β) (recursors : List (ConstRef β)) : + Option (List (ConstRef β)) := do + let families ← sourceFamilies? store source + if recursors.length < families.length then none else do + let majors ← recursors.mapM fun ref => do + let info ← recursorSource? store ref + let major ← majorSource? store info + return major.family + if majors.take families.length != families then none else do + let members ← families.mapM fun family => do + let ctors ← familyConstructors? store family + return family :: ctors + return members.flatten ++ recursors + +structure Witness (β : Type u) where + source : β + recursors : List (ConstRef β) + companions : List (Companion β) + equations : List (List (EquationWitness β)) + +structure Checked (entries : Environment β) (store : Store β) (witness : Witness β) : Prop where + layout : sourceRefs? store witness.source witness.recursors = some (witness.companions.map (·.header.ref)) + source : ∀ companion ∈ witness.companions, SourceMatches store companion + models : CheckedCompanions.{u,v} entries witness.companions + +def check? (fuel : Nat) (entries : Environment β) (store : Store β) (witness : Witness β) : + Option (CheckedClaim.{u} (Checked.{u,v} entries store witness)) := + if hl : sourceRefs? store witness.source witness.recursors = some (witness.companions.map (·.header.ref)) then + if hs : ∀ companion ∈ witness.companions, SourceMatches store companion then do + let checked ← checkCompanions?.{u,v} fuel entries witness.companions witness.equations + return ⟨hl, hs, checked.down⟩ + else none + else none + +theorem check?_sound {fuel : Nat} {entries : Environment β} {store : Store β} {witness : Witness β} {result} + (_ : check?.{u,v} fuel entries store witness = some result) : Checked.{u,v} entries store witness := result.down + +/-- Data-only provenance, kept in each published source entry. -/ +def EntrySource (store : Store β) (ref : ConstRef β) (entry : ConstantEntry β) : Prop := + ∃ decision : DecidableEq β, ∃ companion : Companion β, + @SourceMatches β decision store companion ∧ ref = companion.header.ref ∧ entry = companion.entry + +omit [DecidableEq β] in +theorem EntrySource.not_axiom {store : Store β} {ref : ConstRef β} {entry : ConstantEntry β} + (source : EntrySource store ref entry) {n : Nat} {type : VExpr β} {safety : Safety} + (h : store.lookup ref = some (.axiom n type safety)) : False := by + obtain ⟨decision, companion, hm, hr, _⟩ := source + letI := decision + have hh := hm.2.2 + rw [← hr] at hh + cases ref with + | ctor => cases h + | member => simp [sourceRules?, h] at hh + +theorem publishedEntry_source {entries : Environment β} {store : Store β} {witness : Witness β} + (checked : Checked.{u,v} entries store witness) {ref : ConstRef β} {entry : ConstantEntry β} + (h : environment entries witness.companions ref = some entry) : + entries ref = some entry ∨ EntrySource store ref entry := by + unfold environment Environment.overlay additions at h + cases hc : lookupCompanion witness.companions ref with + | none => simp only [hc, Option.map_none] at h; exact Or.inl h + | some companion => + have he : companion.entry = entry := by simpa [hc] using h + obtain ⟨hm, hr⟩ := lookupCompanion_sound hc + exact Or.inr ⟨inferInstance, companion, checked.source companion hm, hr.symm, he.symm⟩ + +end Ix.Theory.Certified.Modeled diff --git a/Ix/Theory/Certified/Modeled/Transport.lean b/Ix/Theory/Certified/Modeled/Transport.lean new file mode 100644 index 000000000..b568ad910 --- /dev/null +++ b/Ix/Theory/Certified/Modeled/Transport.lean @@ -0,0 +1,290 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Modeled.Equation +import Ix.Theory.Model.ReferenceMap + +/-! Simultaneous publication of source companions. Every target is already +in the checked prefix; exact mapped types and complete model equations are +validated here. Source kind and stored-rule correspondence are a separate +mandatory check before this internal result becomes declaration admission. -/ + +namespace Ix.Theory.Certified.Modeled + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +structure Companion (β : Type u) where + header : Signature.Header β + model : ConstRef β + rules : List (Signature.Rule β) + +def Companion.entry (companion : Companion β) : ConstantEntry β := + ⟨companion.header.universes, companion.header.type, none, + companion.rules.map (fun rule => ⟨rule.lhs, rule.rhs⟩), []⟩ + +def lookupCompanion : List (Companion β) → ConstRef β → Option (Companion β) + | [], _ => none + | companion :: rest, ref => + if companion.header.ref = ref then some companion else lookupCompanion rest ref + +theorem lookupCompanion_sound {companions : List (Companion β)} {ref : ConstRef β} {companion : Companion β} + (h : lookupCompanion companions ref = some companion) : + companion ∈ companions ∧ companion.header.ref = ref := by + induction companions with + | nil => cases h + | cons head rest ih => + unfold lookupCompanion at h + split at h + · cases Option.some.inj h + exact ⟨List.mem_cons_self, ‹companion.header.ref = ref›⟩ + · obtain ⟨hm, hr⟩ := ih h + exact ⟨List.mem_cons_of_mem _ hm, hr⟩ + +theorem lookupCompanion_of_mem {companions : List (Companion β)} + (unique : (companions.map (·.header.ref)).Nodup) {companion : Companion β} + (member : companion ∈ companions) : lookupCompanion companions companion.header.ref = some companion := by + induction companions with + | nil => cases member + | cons head rest ih => + have hu := List.nodup_cons.mp unique + rcases List.mem_cons.mp member with rfl | hm + · simp [lookupCompanion] + · have hne : head.header.ref ≠ companion.header.ref := by + intro he + apply hu.1 + change head.header.ref ∈ rest.map (·.header.ref) + rw [he] + exact List.mem_map.mpr ⟨companion, hm, rfl⟩ + simp only [lookupCompanion, if_neg hne] + exact ih hu.2 hm + +def mapping (companions : List (Companion β)) (ref : ConstRef β) : ConstRef β := + match lookupCompanion companions ref with + | none => ref + | some companion => companion.model + +def additions (companions : List (Companion β)) : Environment β := + fun ref => (lookupCompanion companions ref).map Companion.entry + +def environment (entries : Environment β) (companions : List (Companion β)) : Environment β := + entries.overlay (additions companions) + +def mapRule (companions : List (Companion β)) (rule : Signature.Rule β) : Signature.Rule β := + ⟨rule.universes, rule.type.mapRefs (mapping companions), + rule.lhs.mapRefs (mapping companions), rule.rhs.mapRefs (mapping companions)⟩ + +structure CompanionChecked (entries : Environment β) (companions : List (Companion β)) + (companion : Companion β) : Prop where + modelEntry : ∃ entry, entries companion.model = some entry ∧ + entry.universes = companion.header.universes ∧ + entry.type = companion.header.type.mapRefs (mapping companions) + scope : companion.header.type.Scope companion.header.universes 0 + references : companion.header.type.ReferencesIn (environment entries companions) + ruleScopes : ∀ rule ∈ companion.rules, rule.universes = companion.header.universes ∧ + rule.lhs.Scope companion.header.universes 0 ∧ rule.rhs.Scope companion.header.universes 0 + ruleReferences : ∀ rule ∈ companion.rules, + rule.lhs.ReferencesIn (environment entries companions) ∧ rule.rhs.ReferencesIn (environment entries companions) + rules : ∀ rule ∈ companion.rules, CheckedEquation.{u,v} entries (mapRule companions rule) + +structure CheckedCompanions (entries : Environment β) (companions : List (Companion β)) : Prop where + unique : (companions.map (·.header.ref)).Nodup + fresh : ∀ companion ∈ companions, entries companion.header.ref = none + checked : ∀ companion ∈ companions, CompanionChecked.{u,v} entries companions companion + +def checkRules? (fuel : Nat) (entries : Environment β) (companions : List (Companion β)) : + (rules : List (Signature.Rule β)) → List (EquationWitness β) → + Option (CheckedClaim.{u} (∀ rule ∈ rules, CheckedEquation.{u,v} entries (mapRule companions rule))) + | [], [] => some ⟨by simp⟩ + | rule :: rules, witness :: witnesses => do + let first ← checkEquation?.{u,v} fuel entries (mapRule companions rule) witness + let rest ← checkRules? fuel entries companions rules witnesses + return ⟨by + intro candidate h + rcases List.mem_cons.mp h with rfl | h + · exact first.down + · exact rest.down candidate h⟩ + | _, _ => none + +def checkCompanion? (fuel : Nat) (entries : Environment β) (companions : List (Companion β)) + (companion : Companion β) (witnesses : List (EquationWitness β)) : + Option (CheckedClaim.{u} (CompanionChecked.{u,v} entries companions companion)) := + match he : entries companion.model with + | none => none + | some entry => + if hn : entry.universes = companion.header.universes then + if ht : entry.type = companion.header.type.mapRefs (mapping companions) then + if hs : companion.header.type.Scope companion.header.universes 0 then + if hr : companion.header.type.ReferencesIn (environment entries companions) then + if hqs : ∀ rule ∈ companion.rules, rule.universes = companion.header.universes ∧ + rule.lhs.Scope companion.header.universes 0 ∧ rule.rhs.Scope companion.header.universes 0 then + if hqr : ∀ rule ∈ companion.rules, + rule.lhs.ReferencesIn (environment entries companions) ∧ + rule.rhs.ReferencesIn (environment entries companions) then do + let rules ← checkRules?.{u,v} fuel entries companions companion.rules witnesses + return ⟨⟨entry, he, hn, ht⟩, hs, hr, hqs, hqr, rules.down⟩ + else none + else none + else none + else none + else none + else none + +def checkEach? (fuel : Nat) (entries : Environment β) (companions : List (Companion β)) : + (pending : List (Companion β)) → List (List (EquationWitness β)) → + Option (CheckedClaim.{u} (∀ companion ∈ pending, CompanionChecked.{u,v} entries companions companion)) + | [], [] => some ⟨by simp⟩ + | companion :: rest, witnesses :: remaining => do + let first ← checkCompanion?.{u,v} fuel entries companions companion witnesses + let others ← checkEach? fuel entries companions rest remaining + return ⟨by + intro candidate h + rcases List.mem_cons.mp h with rfl | h + · exact first.down + · exact others.down candidate h⟩ + | _, _ => none + +def checkCompanions? (fuel : Nat) (entries : Environment β) (companions : List (Companion β)) + (witnesses : List (List (EquationWitness β))) : + Option (CheckedClaim.{u} (CheckedCompanions.{u,v} entries companions)) := + if hu : (companions.map (·.header.ref)).Nodup then + if hf : ∀ companion ∈ companions, entries companion.header.ref = none then do + let checked ← checkEach?.{u,v} fuel entries companions companions witnesses + return ⟨hu, hf, checked.down⟩ + else none + else none + +theorem CheckedCompanions.fixed_old {entries : Environment β} {companions : List (Companion β)} + (checked : CheckedCompanions.{u,v} entries companions) {ref : ConstRef β} {entry : ConstantEntry β} + (old : entries ref = some entry) : mapping companions ref = ref := by + cases hc : lookupCompanion companions ref with + | none => simp [mapping, hc] + | some companion => + obtain ⟨hm, hr⟩ := lookupCompanion_sound hc + have hf := checked.fresh companion hm + rw [hr, old] at hf + cases hf + +theorem CheckedCompanions.fresh_overlay {entries : Environment β} {companions : List (Companion β)} + (checked : CheckedCompanions.{u,v} entries companions) : entries.Fresh (additions companions) := by + intro ref entry he + cases hc : lookupCompanion companions ref with + | none => simp [additions, hc] at he + | some companion => + obtain ⟨hm, hr⟩ := lookupCompanion_sound hc + rw [← hr] + exact checked.fresh companion hm + +theorem CompanionChecked.closed {entries : Environment β} {companions : List (Companion β)} + {companion : Companion β} (checked : CompanionChecked.{u,v} entries companions companion) : + EntryClosed (environment entries companions) companion.entry := by + constructor + · exact checked.scope + · intro body h; cases h + · exact checked.references + · intro body h; cases h + · intro law hl + obtain ⟨rule, hr, rfl⟩ := List.mem_map.mp hl + exact (checked.ruleScopes rule hr).2 + · intro law hl + obtain ⟨rule, hr, rfl⟩ := List.mem_map.mp hl + exact checked.ruleReferences rule hr + · intro fact hf; cases hf + · intro fact hf; cases hf + +/-- New entries may refer to one another. All are checked against the final +finite signature, while old entries retain their established closure. -/ +theorem environment_wf {entries : Environment β} {companions : List (Companion β)} + (checked : CheckedCompanions.{u,v} entries companions) (wf : entries.WF) : + (environment entries companions).WF := by + have hnew : ∀ ref entry, additions companions ref = some entry → + EntryClosed (environment entries companions) entry := by + intro ref entry he + cases hc : lookupCompanion companions ref with + | none => simp [additions, hc] at he + | some companion => + have hm := (lookupCompanion_sound hc).1 + have heq : companion.entry = entry := by simpa [additions, hc] using he + rw [← heq] + exact (checked.checked companion hm).closed + constructor + all_goals + intro ref entry he + change entries.overlay (additions companions) ref = some entry at he + unfold Environment.overlay at he + split at he + · cases Option.some.inj he + first + | exact (hnew _ _ ‹_›).typeScope + | exact (hnew _ _ ‹_›).bodyScope + | exact (hnew _ _ ‹_›).typeReferences + | exact (hnew _ _ ‹_›).bodyReferences + | exact (hnew _ _ ‹_›).equationScope + | exact (hnew _ _ ‹_›).equationReferences + | exact (hnew _ _ ‹_›).factScope + | exact (hnew _ _ ‹_›).factReferences + · first + | exact wf.typeScope ref entry he + | exact wf.bodyScope ref entry he + | exact (wf.typeReferences ref entry he).overlay + | exact fun body hb => (wf.bodyReferences ref entry he body hb).overlay + | exact wf.equationScope ref entry he + | exact fun law hl => ⟨(wf.equationReferences ref entry he law hl).1.overlay, + (wf.equationReferences ref entry he law hl).2.overlay⟩ + | exact wf.factScope ref entry he + | exact fun fact hf => (wf.factReferences ref entry he fact hf).overlay + +variable {V : Type v} [SetTheory V] + +def assignment (constants : Assignment β V) (companions : List (Companion β)) : Assignment β V := + fun ref levels => constants (mapping companions ref) levels + +omit [SetTheory V] in +theorem assignment_agrees {entries : Environment β} {companions : List (Companion β)} + (checked : CheckedCompanions.{u,v} entries companions) (constants : Assignment β V) : + Assignment.AgreesOn entries constants (assignment constants companions) := by + intro ref entry he levels + simp only [assignment, checked.fixed_old he] + +theorem assignment_realizes {entries : Environment β} {companions : List (Companion β)} + (checked : CheckedCompanions.{u,v} entries companions) (wf : entries.WF) + (constants : Assignment β V) (model : Realizes constants entries) : + Realizes (assignment constants companions) (environment entries companions) := by + apply (model.of_agrees wf (assignment_agrees checked constants)).overlay + intro ref entry he + cases hc : lookupCompanion companions ref with + | none => simp [additions, hc] at he + | some companion => + obtain ⟨hm, hr⟩ := lookupCompanion_sound hc + have heq : companion.entry = entry := by simpa [additions, hc] using he + rw [← heq] + have hcomp := checked.checked companion hm + obtain ⟨target, ht, hn, htype⟩ := hcomp.modelEntry + constructor + · intro levels hlevels env + have h := model.typeValid companion.model target ht levels (hlevels.trans hn.symm) env + rw [htype, wellDenoted_mapRefs] at h + exact h + · intro levels hlevels env + have h := model.member companion.model target ht levels (hlevels.trans hn.symm) env + rw [htype, interp_mapRefs] at h + change constants (mapping companions ref) levels ∈ˢ + interp (fun ref values => constants (mapping companions ref) values) levels env companion.header.type + rw [mapping, hc] + exact h + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl levels _ env + obtain ⟨rule, hmem, rfl⟩ := List.mem_map.mp hl + have h := (hcomp.rules rule hmem).equality V constants model levels env + (Context.valid_nil constants levels env) + change interp (fun ref values => constants (mapping companions ref) values) levels env rule.lhs = + interp (fun ref values => constants (mapping companions ref) values) levels env rule.rhs + simpa only [mapRule, interp_mapRefs] using h + · intro fact hf; cases hf + +end Ix.Theory.Certified.Modeled diff --git a/Ix/Theory/Certified/Natural/Admission.lean b/Ix/Theory/Certified/Natural/Admission.lean new file mode 100644 index 000000000..d4b70d298 --- /dev/null +++ b/Ix/Theory/Certified/Natural/Admission.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Admission + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +/-- Literal support is installed with the canonical Nat model in one atomic +extension, at the reference selected by the public primitive signature. -/ +def checkNaturalExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (witness : Ordinary.BlockWitness β) : + Option (CheckedExtension.{u,v} signature store state) := + match hp : signature.natType with + | none => none + | some pin => do + let checked ← Natural.check.{u,v} fuel state.entries store pin witness + let entries := Natural.environment state.entries witness.source witness.recursor witness.mode + have extension : Extends.{u,v} signature state.entries entries := by + constructor + · intro r entry hr + exact Natural.environment_old checked.down hr + · intro V _ constants hM + let constants' := Natural.shape.recursorAssignment constants witness.source witness.recursor witness.mode + have hm := Natural.assignment_realizes checked.down state.wf constants hM.realizes + have ha := Ordinary.Shape.publishedAssignment_agrees checked.down.block constants + exact ⟨constants', hM.extend signature state.present hm ha, ha⟩ + let result : CheckedInterface signature := { + entries + wf := Natural.environment_wf checked.down state.wf + present := ⟨extension.lookup _ _ state.present.1, extension.lookup _ _ state.present.2⟩ + } + return { + result, extension + source := by + intro r entry hr + dsimp only [result] at hr + rcases Natural.environment_source checked.down hr with hold | hordinary | hnatural + · exact Or.inl hold + · exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inl hordinary)))) + · rw [← hp] at hnatural + exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inl hnatural)))))))) + } + +def admitNatural? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : Ordinary.BlockWitness β) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkNaturalExtension?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +theorem admitNatural?_extends {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {state : AdmittedEnvironment.{u,v} signature store} {witness : Ordinary.BlockWitness β} {result} + (_ : admitNatural? fuel state witness = some result) : + Extends.{u,v} signature state.entries result.val.entries := result.property + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Natural/Checked.lean b/Ix/Theory/Certified/Natural/Checked.lean new file mode 100644 index 000000000..49939ad6a --- /dev/null +++ b/Ix/Theory/Certified/Natural/Checked.lean @@ -0,0 +1,46 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Natural.Value + +namespace Ix.Theory.Certified.Natural + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +def fact (source : β) : ConstantFact β := .natural (.ctor source 0 0) (.ctor source 0 1) +def entry (source : β) : ConstantEntry β := { (shape : Ordinary.Shape β).familyEntry with facts := [fact source] } +def environment (entries : Environment β) (source recursor : β) (mode : Inductive.ElimMode) : Environment β := + (shape.publishedEnvironment entries source recursor mode).insert (.member source 0) (entry source) + +structure Checked (entries : Environment β) (store : Store β) (pin : ConstRef β) + (source recursor : β) (mode : Inductive.ElimMode) : Prop where + block : Ordinary.CheckedBlock.{u,v} entries store source recursor shape mode + primitive : pin = .member source 0 + references : (fact source).ReferencesIn (shape.publishedEnvironment entries source recursor mode) + +/-- Literal support is tied to the profile's selected Nat reference and the +whole ordinary zero/successor source, not to a diagnostic name or marker. -/ +def check (fuel : Nat) (entries : Environment β) (store : Store β) (pin : ConstRef β) + (witness : Ordinary.BlockWitness β) : + Option (CheckedClaim.{u} (Checked.{u,v} entries store pin witness.source witness.recursor witness.mode)) := + if hp : pin = .member witness.source 0 then + if hs : witness.shape.shape = shape then + if hr : (fact witness.source).ReferencesIn + (shape.publishedEnvironment entries witness.source witness.recursor witness.mode) then do + let block ← Ordinary.checkBlock.{u,v} fuel entries store witness + return ⟨⟨hs ▸ block.down, hp, hr⟩⟩ + else none + else none + else none + +theorem check_sound {fuel : Nat} {entries : Environment β} {store : Store β} {pin : ConstRef β} + {witness : Ordinary.BlockWitness β} {result} + (_ : check.{u,v} fuel entries store pin witness = some result) : + Checked.{u,v} entries store pin witness.source witness.recursor witness.mode := result.down + +end Ix.Theory.Certified.Natural diff --git a/Ix/Theory/Certified/Natural/Publish.lean b/Ix/Theory/Certified/Natural/Publish.lean new file mode 100644 index 000000000..259d8524d --- /dev/null +++ b/Ix/Theory/Certified/Natural/Publish.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Natural.Checked + +namespace Ix.Theory.Certified.Natural + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] {entries : Environment β} {store : Store β} + {pin : ConstRef β} {source recursor : β} {mode : Inductive.ElimMode} + +theorem family_lookup (h : Checked.{u,v} entries store pin source recursor mode) : + shape.publishedEnvironment entries source recursor mode (.member source 0) = some (shape : Ordinary.Shape β).familyEntry := by + apply Environment.insert_old h.block.recursorChecked.fresh + simp [Ordinary.Shape.constructorEnvironment, Environment.overlay, Ordinary.Shape.constructorEntries, + Ordinary.Shape.familyEnvironment] + +theorem environment_wf (h : Checked.{u,v} entries store pin source recursor mode) (hE : entries.WF) : + (environment entries source recursor mode).WF := by + have hb := Ordinary.Shape.publishedEnvironment_wf h.block hE + exact hb.insert (hb.typeScope _ (shape : Ordinary.Shape β).familyEntry (family_lookup h)) + (by simp [entry, Ordinary.Shape.familyEntry]) + (hb.typeReferences _ (shape : Ordinary.Shape β).familyEntry (family_lookup h)) + (by simp [entry, Ordinary.Shape.familyEntry]) + (by simp [entry, Ordinary.Shape.familyEntry]) + (by simp [entry, Ordinary.Shape.familyEntry]) + (by simp [entry, fact, ConstantFact.Scope, shape, Ordinary.Shape.familyEntry]) + (by simpa only [entry, List.mem_singleton, forall_eq] using h.references) + +theorem environment_old (h : Checked.{u,v} entries store pin source recursor mode) + {r : ConstRef β} {old : ConstantEntry β} (hr : entries r = some old) : + environment entries source recursor mode r = some old := by + simp only [environment, Environment.insert, + if_neg (fresh_ne (h.block.shapeChecked.fresh _ (List.mem_cons_self ..)) hr)] + exact Ordinary.Shape.publishedEnvironment_old h.block hr + +variable {V : Type v} [SetTheory V] + +theorem assignment_realizes (h : Checked.{u,v} entries store pin source recursor mode) + (hE : entries.WF) (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (shape.recursorAssignment constants source recursor mode) (environment entries source recursor mode) := by + have hb := Ordinary.Shape.publishedAssignment_realizes h.block hE constants hM + have hr := Ordinary.Shape.recursorAssignment_reading h.block.shapeChecked h.block.recursorChecked constants + apply hb.insert + constructor + · exact hb.typeValid _ (shape : Ordinary.Shape β).familyEntry (family_lookup h) + · exact hb.member _ (shape : Ordinary.Shape β).familyEntry (family_lookup h) + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl; cases hl + · intro f hf levels hn _ + cases List.mem_singleton.mp hf + have he : levels = [] := List.eq_nil_of_length_eq_zero hn + subst levels + exact ⟨rfl, meaning h.block.shapeChecked hr.toConstructorReading hM⟩ + +end Ix.Theory.Certified.Natural + +namespace Ix.Theory.Certified.Natural + +open Model +universe u v +variable {β : Type u} [DecidableEq β] + +def EntrySource (pin : Option (ConstRef β)) (store : Store β) (r : ConstRef β) (e : ConstantEntry β) : Prop := + pin = some r ∧ ∃ source recursor mode, + store.blocks source = some ⟨[shape.source source]⟩ ∧ + shape.RecursorSourceMatches store source recursor mode ∧ r = .member source 0 ∧ e = entry source + +theorem environment_source {entries : Environment β} {store : Store β} {pin : ConstRef β} + {source recursor : β} {mode : Inductive.ElimMode} + (h : Checked.{u,v} entries store pin source recursor mode) {r : ConstRef β} {e : ConstantEntry β} + (hr : environment entries source recursor mode r = some e) : + entries r = some e ∨ Ordinary.EntrySource store r e ∨ EntrySource (some pin) store r e := by + unfold environment Environment.insert at hr + split at hr + next he => + cases Option.some.inj hr + exact Or.inr (Or.inr ⟨congrArg some (h.primitive.trans he.symm), source, recursor, mode, + h.block.shapeChecked.exactSource, h.block.recursorChecked.exactSource, he, rfl⟩) + next => + rcases Ordinary.publishedEntry_source h.block hr with hold | hnew + · exact Or.inl hold + · exact Or.inr (Or.inl hnew) + +end Ix.Theory.Certified.Natural diff --git a/Ix/Theory/Certified/Natural/Value.lean b/Ix/Theory/Certified/Natural/Value.lean new file mode 100644 index 000000000..526ed0bc9 --- /dev/null +++ b/Ix/Theory/Certified/Natural/Value.lean @@ -0,0 +1,120 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Checked + +namespace Ix.Theory.Certified.Natural + +open Model Model.SetTheory Model.SetTheory.Tower Model.InductiveCodes Ordinary + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +def zeroConstructor : Constructor β := ⟨[], [], []⟩ +def succConstructor : Constructor β := ⟨[], [⟨[], []⟩], []⟩ +def shape : Shape β := ⟨0, [], [], .succ .zero, [zeroConstructor, succConstructor]⟩ + +variable (constants : Assignment β V) + +theorem zero_positions : + shape.positions constants [] (fun _ => empty) (inj 0 (pt : V)) = empty := by + apply eq_empty + intro p hp + obtain ⟨i, field, _, hi, _, _⟩ := Shape.mem_positions + (shape := shape) (constants := constants) (levels := []) (env := fun _ => empty) + (show (shape : Shape β).constructors[0]? = some zeroConstructor from rfl) + (xs := []) rfl hp + simp [zeroConstructor] at hi + +theorem succ_positions : + shape.positions constants [] (fun _ => empty) (inj 1 (pt : V)) = sing (inj 0 pt) := by + apply ext + intro p + constructor + · intro hp + obtain ⟨i, field, ys, hi, hys, rfl⟩ := Shape.mem_positions + (shape := shape) (constants := constants) (levels := []) (env := fun _ => empty) + (show (shape : Shape β).constructors[1]? = some succConstructor from rfl) + (xs := []) rfl hp + have he : i = 0 := by + have hb := (List.getElem?_eq_some_iff.mp hi).1 + simp only [succConstructor, List.length_singleton] at hb + omega + subst i + cases Option.some.inj hi + cases ys with + | nil => exact mem_sing.mpr rfl + | cons _ _ => exact hys.elim + · intro hp + cases mem_sing.mp hp + exact Shape.inj_mem_positions (shape := shape) (constants := constants) (levels := []) (env := fun _ => empty) + (show (shape : Shape β).constructors[1]? = some succConstructor from rfl) + (show (succConstructor : Constructor β).recursive[0]? = some ⟨[], []⟩ from rfl) + (xs := []) (ys := []) rfl trivial + +theorem zero_value : + shape.constructorValue constants [] (fun _ => empty) zeroConstructor 0 [] [] = (Numeral.value 0 : V) := by + have hg : shape.branches constants [] (fun _ => empty) zeroConstructor 0 [] [] = (empty : V) := by + rw [Shape.branches, mkTower, zero_positions] + apply eq_empty + intro p hp + obtain ⟨x, hx, _⟩ := mem_graph.mp hp + exact not_mem_empty x hx + rw [Shape.constructorValue, hg] + rfl + +theorem succ_value (n : V) : + shape.constructorValue constants [] (fun _ => empty) succConstructor 1 [] [n] = Numeral.succ n := by + have hg : shape.branches constants [] (fun _ => empty) succConstructor 1 [] [n] = + graph (fun _ => n) (sing (inj 0 pt)) := by + rw [Shape.branches, mkTower, succ_positions] + apply graph_congr + intro p hp + cases mem_sing.mp hp + simp only [Shape.branchBody, tag_inj, succConstructor, List.getElem?_cons_zero, + List.getD_cons_zero, List.length_nil, projList, Telescope.applyN] + rw [Shape.constructorValue, hg] + rfl + +variable {constants} {entries : Environment β} {store : Store β} {source : β} + +/-- Every literal is a member of the exact carrier built for zero/successor. +This is proved by natural-number induction, not supplied as a certificate. -/ +theorem value_mem (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (n : Nat) : + Numeral.value n ∈ˢ shape.familyValue constants [] := by + induction n with + | zero => + have hm := Shape.constructorValue_mem h hM (Context.valid_nil constants [] (fun _ => empty)) + (show (shape : Shape β).constructors[0]? = some zeroConstructor from rfl) + (xs := []) (fs := []) (by trivial) (by trivial) + rw [zero_value] at hm + exact hm + | succ n ih => + have hm := Shape.constructorValue_mem h hM (Context.valid_nil constants [] (fun _ => empty)) + (show (shape : Shape β).constructors[1]? = some succConstructor from rfl) + (xs := []) (fs := [Numeral.value n]) (by trivial) (show _ ∧ True from ⟨ih, trivial⟩) + rw [succ_value] at hm + exact hm + +theorem meaning (h : CheckedShape.{u,v} entries store source shape) + {reading : Assignment β V} (hr : ConstructorReading entries shape source constants reading) + (hM : Realizes constants entries) : + NaturalMeaning reading (.member source 0) (.ctor source 0 0) (.ctor source 0 1) := by + constructor + · intro n + rw [hr.family [] rfl] + exact value_mem h hM n + · rw [hr.constructor [] rfl 0 zeroConstructor rfl] + exact zero_value constants + · intro n + rw [hr.constructor [] rfl 1 succConstructor rfl] + have he := Shape.constructorClosedValue_apply h hM + (show (shape : Shape β).constructors[1]? = some succConstructor from rfl) + (levels := []) (ps := []) (xs := []) (fs := [Numeral.value n]) (by trivial) (by trivial) + (show _ ∧ True from ⟨value_mem h hM n, trivial⟩) + simpa only [Telescope.applyN, Telescope.extend, List.nil_append, succ_value, Numeral.value] using he + +end Ix.Theory.Certified.Natural diff --git a/Ix/Theory/Certified/Operations.lean b/Ix/Theory/Certified/Operations.lean new file mode 100644 index 000000000..012f2573d --- /dev/null +++ b/Ix/Theory/Certified/Operations.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Checker + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +structure InferenceWitness (β : Type u) where + annotations : AnnotationTree + type : AExpr β + typing : TypingWitness β + +structure InferenceResult (entries : Environment β) (n : Nat) (Γ : Context β) + (source : VExpr β) where + reading : Reading n Γ.length source + type : AExpr β + typeScope : type.Scope n Γ.length + sound : TypingClaim.{u,v} entries Γ reading.val type + +/-- Witness-directed inference. An unchecked type suggestion is accepted only +after the complete recursive typing validator establishes its meaning. -/ +def inferCertified (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (source : VExpr β) (witness : InferenceWitness β) : + Option (InferenceResult.{u,v} entries n Γ source) := do + let reading ← readAnnotations? n Γ.length source witness.annotations + if hs : witness.type.Scope n Γ.length then do + let h ← verifyType.{u,v} fuel n entries Γ reading.val witness.type witness.typing + return ⟨reading, witness.type, hs, h.down⟩ + else none + +/-- The permitted head forms, including a stuck application spine. Definitions +with bodies must be unfolded; unsupported literals and projections fail. -/ +def whnfShape (entries : Environment β) : AExpr β → Bool + | .bvar _ | .sort _ | .lam .. | .forallE .. => true + | .const r _ => (entries r).any (fun entry => entry.body.isNone) + | .app (.lam ..) _ => false + | .app f _ => whnfShape entries f + | .natLit _ | .proj .. => false + +structure WhnfWitness (β : Type u) where + source : InferenceWitness β + result : AExpr β + resultTyping : TypingWitness β + conversion : ConversionWitness β + +structure WhnfResult (entries : Environment β) (n : Nat) (Γ : Context β) + (source : VExpr β) where + input : InferenceResult.{u,v} entries n Γ source + result : AExpr β + resultScope : result.Scope n Γ.length + resultShape : whnfShape entries result = true + resultTyping : TypingClaim.{u,v} entries Γ result input.type + equal : ConversionClaim.{u,v} entries Γ input.reading.val result + +/-- Conservative validation rechecks both endpoints and all conversion +premises, including every actual beta domain. It establishes hereditary +validity for its result and does not consume an unchecked inference invariant. -/ +def whnfCertified (fuel n : Nat) (entries : Environment β) (Γ : Context β) + (source : VExpr β) (witness : WhnfWitness β) : + Option (WhnfResult.{u,v} entries n Γ source) := do + let input ← inferCertified fuel n entries Γ source witness.source + if hs : witness.result.Scope n Γ.length then + if hw : whnfShape entries witness.result = true then do + let ht ← verifyType.{u,v} fuel n entries Γ witness.result input.type witness.resultTyping + let he ← verifyConversion.{u,v} fuel n entries Γ input.reading.val witness.result + witness.conversion + return ⟨input, witness.result, hs, hw, ht.down, he.down⟩ + else none + else none + +theorem inferCertified_sound {fuel n : Nat} {entries : Environment β} + {Γ : Context β} {source : VExpr β} {witness : InferenceWitness β} + {result : InferenceResult.{u,v} entries n Γ source} + (_ : inferCertified fuel n entries Γ source witness = some result) : + result.reading.val.erase = source ∧ result.type.Scope n Γ.length ∧ + TypingClaim.{u,v} entries Γ result.reading.val result.type := + ⟨result.reading.property.1, result.typeScope, result.sound⟩ + +theorem whnfCertified_sound {fuel n : Nat} {entries : Environment β} + {Γ : Context β} {source : VExpr β} {witness : WhnfWitness β} + {result : WhnfResult.{u,v} entries n Γ source} + (_ : whnfCertified fuel n entries Γ source witness = some result) + (V : Type v) [SetTheory V] (constants : Assignment β V) + (hM : Realizes constants entries) (levels : List Nat) (env : Nat → V) + (hΓ : Γ.Valid constants levels env) : + result.input.reading.val.erase = source ∧ whnfShape entries result.result = true ∧ + WellDenoted constants levels env result.input.reading.val ∧ + WellDenoted constants levels env result.result ∧ + interp constants levels env result.input.reading.val = + interp constants levels env result.result := + ⟨result.input.reading.property.1, result.resultShape, + (result.input.sound V constants hM levels env hΓ).1, + (result.resultTyping V constants hM levels env hΓ).1, + result.equal V constants hM levels env hΓ⟩ + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Ordinary/Admission.lean b/Ix/Theory/Certified/Ordinary/Admission.lean new file mode 100644 index 000000000..bef0afc9d --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Admission.lean @@ -0,0 +1,113 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Standard.Admission +import Ix.Theory.Certified.Quotient.Admission +import Ix.Theory.Certified.Structure.Admission +import Ix.Theory.Certified.Natural.Admission +import Ix.Theory.Certified.Modeled.Admission + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +/-- Publish the family, constructors, recursor, and its complete equations +atomically, after their formation and semantic realization have been produced. -/ +def checkOrdinaryExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (witness : Ordinary.BlockWitness β) : + Option (CheckedExtension.{u,v} signature store state) := do + let checked ← Ordinary.checkBlock.{u,v} fuel state.entries store witness + let shape := witness.shape.shape + let entries := shape.publishedEnvironment state.entries witness.source witness.recursor witness.mode + have extension : Extends.{u,v} signature state.entries entries := by + constructor + · intro r entry hr + exact Ordinary.Shape.publishedEnvironment_old checked.down hr + · intro V _ constants hM + let constants' := shape.recursorAssignment constants witness.source witness.recursor witness.mode + have hnew := Ordinary.Shape.publishedAssignment_realizes checked.down state.wf constants hM.realizes + have hagree := Ordinary.Shape.publishedAssignment_agrees checked.down constants + exact ⟨constants', hM.extend signature state.present hnew hagree, hagree⟩ + let result : CheckedInterface signature := { + entries + wf := Ordinary.Shape.publishedEnvironment_wf checked.down state.wf + present := ⟨extension.lookup _ _ state.present.1, extension.lookup _ _ state.present.2⟩ + } + return { + result, extension + source := by + intro r entry hr + dsimp only [result] at hr + rcases Ordinary.publishedEntry_source checked.down hr with hold | hnew + · exact Or.inl hold + · exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inl hnew)))) + } + +def admitOrdinary? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : Ordinary.BlockWitness β) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkOrdinaryExtension?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +/-- Untrusted declaration choices in dependency order. A signature stage is +never itself an element of this public admission list. -/ +inductive DeclarationWitness (β : Type u) where + | definition (witness : DefinitionWitness β) + | ordinary (witness : Ordinary.BlockWitness β) + | standard (witness : Standard.Witness β) + | quotient (witness : Quotient.Witness β) + | structure (witness : Structure.Witness β) + | natural (witness : Ordinary.BlockWitness β) + | modeled (witness : Modeled.Witness β) + +def checkDeclarationExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) : DeclarationWitness β → + Option (CheckedExtension.{u,v} signature store state) + | .definition witness => checkDefinitionExtension? fuel state witness + | .ordinary witness => checkOrdinaryExtension? fuel state witness + | .standard witness => checkStandardExtension? fuel state witness + | .quotient witness => checkQuotientExtension? fuel state witness + | .structure witness => checkStructureExtension? fuel state witness + | .natural witness => checkNaturalExtension? fuel state witness + | .modeled witness => checkModeledExtension? fuel state witness + +def checkDeclarationExtensions? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) : List (DeclarationWitness β) → + Option (CheckedExtension.{u,v} signature store state) + | [] => some (CheckedExtension.refl state) + | witness :: rest => do + let step ← checkDeclarationExtension? fuel state witness + let rest ← checkDeclarationExtensions? fuel step.result rest + return step.trans rest + +def admitDeclaration? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) : DeclarationWitness β → + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } + | .definition witness => admitDefinition? fuel state witness + | .ordinary witness => admitOrdinary? fuel state witness + | .standard witness => admitStandard? fuel state witness + | .quotient witness => admitQuotient? fuel state witness + | .structure witness => admitStructure? fuel state witness + | .natural witness => admitNatural? fuel state witness + | .modeled witness => admitModeled? fuel state witness + +def admitDeclarations? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : List (DeclarationWitness β)) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkDeclarationExtensions?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +theorem admitOrdinary?_extends {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {state : AdmittedEnvironment.{u,v} signature store} {witness : Ordinary.BlockWitness β} {result} + (_ : admitOrdinary? fuel state witness = some result) : + Extends.{u,v} signature state.entries result.val.entries := result.property + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Ordinary/Checked.lean b/Ix/Theory/Certified/Ordinary/Checked.lean new file mode 100644 index 000000000..75e3d8547 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Checked.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.RuleEquations + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Inductive + +universe u v +variable {β : Type u} [DecidableEq β] + +structure BlockWitness (β : Type u) where + source : β + recursor : β + shape : ShapeWitness β + mode : ElimMode + constructorTypes : List (Shape.TypeWitness β) + recursorType : Shape.TypeWitness β + rules : List (RuleWitness β) + +structure CheckedBlock (entries : Environment β) (store : Store β) (source recursor : β) + (shape : Shape β) (mode : ElimMode) : Prop where + shapeChecked : CheckedShape.{u,v} entries store source shape + constructors : shape.ConstructorFormation.{u,v} entries source + recursorChecked : shape.RecursorFormation.{u,v} entries store source recursor mode + elimination : ModeEvidence.{u,v} entries shape mode + rules : ∀ i ctor, shape.constructors[i]? = some ctor → + shape.RuleFormation.{u,v} (shape.recursorEnvironment entries source recursor mode) source recursor mode i ctor + +def checkBlock (fuel : Nat) (entries : Environment β) (store : Store β) (witness : BlockWitness β) : + Option (CheckedClaim.{u} (CheckedBlock.{u,v} entries store witness.source witness.recursor witness.shape.shape witness.mode)) := do + let shape ← checkShape.{u,v} fuel entries store witness.source witness.shape + let mode ← checkMode.{u,v} fuel entries witness.shape witness.mode + let constructors ← witness.shape.shape.checkConstructorTypes.{u,v} fuel entries witness.source + witness.shape.shape.constructors witness.constructorTypes + let recursor ← witness.shape.shape.checkRecursorType.{u,v} fuel entries store witness.source witness.recursor + witness.mode witness.recursorType + let rules ← witness.shape.shape.checkRules.{u,v} fuel + (witness.shape.shape.recursorEnvironment entries witness.source witness.recursor witness.mode) + witness.source witness.recursor witness.mode witness.shape.shape.constructors.zipIdx witness.rules + return ⟨⟨shape.down, constructors.down, recursor.down, mode.down, fun i ctor hc => + rules.down ctor i (List.mk_mem_zipIdx_iff_getElem?.mpr hc)⟩⟩ + +theorem checkBlock_sound {fuel : Nat} {entries : Environment β} {store : Store β} {witness : BlockWitness β} + {result} (_ : checkBlock.{u,v} fuel entries store witness = some result) : + CheckedBlock.{u,v} entries store witness.source witness.recursor witness.shape.shape witness.mode := result.down + +namespace Shape + +def publishedRecursorEntry (shape : Shape β) (source recursor : β) (mode : ElimMode) : ConstantEntry β := + { shape.recursorEntry source mode with equations := shape.recursorLaws source recursor mode } + +def publishedEnvironment (shape : Shape β) (entries : Environment β) (source recursor : β) + (mode : ElimMode) : Environment β := + (shape.constructorEnvironment entries source).insert (.member recursor 0) + (shape.publishedRecursorEntry source recursor mode) + +omit [DecidableEq β] in +theorem recursorLaws_member {shape : Shape β} {source recursor : β} {mode : ElimMode} + {law : ConstantEquation β} (hl : law ∈ shape.recursorLaws source recursor mode) : + ∃ i ctor, shape.constructors[i]? = some ctor ∧ + law = ⟨shape.ruleLhs source recursor mode i ctor, shape.ruleRhs source recursor mode i ctor⟩ := by + obtain ⟨⟨ctor, i⟩, hc, he⟩ := List.mem_map.mp hl + exact ⟨i, ctor, List.mk_mem_zipIdx_iff_getElem?.mp hc, he.symm⟩ + +theorem publishedEnvironment_wf {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} (h : CheckedBlock.{u,v} entries store source recursor shape mode) + (hE : entries.WF) : (shape.publishedEnvironment entries source recursor mode).WF := by + have hwf := (recursorEnvironment_wf h.shapeChecked hE h.constructors h.recursorChecked).insert + (r := .member recursor 0) (entry := shape.publishedRecursorEntry source recursor mode) + h.recursorChecked.closed.typeScope (by simp [publishedRecursorEntry, recursorEntry]) + h.recursorChecked.closed.typeReferences.insert (by simp [publishedRecursorEntry, recursorEntry]) + (by + intro law hl + obtain ⟨i, ctor, hc, rfl⟩ := recursorLaws_member hl + exact (h.rules i ctor hc).scope) + (by + intro law hl + obtain ⟨i, ctor, hc, rfl⟩ := recursorLaws_member hl + exact (h.rules i ctor hc).references) + (by simp [publishedRecursorEntry, recursorEntry]) (by simp [publishedRecursorEntry, recursorEntry]) + simpa only [publishedEnvironment, recursorEnvironment, Environment.insert_replace] using hwf + +theorem publishedEnvironment_old {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} (h : CheckedBlock.{u,v} entries store source recursor shape mode) + {r : ConstRef β} {entry : ConstantEntry β} (hr : entries r = some entry) : + shape.publishedEnvironment entries source recursor mode r = some entry := + Environment.insert_old h.recursorChecked.fresh (Environment.overlay_old + (constructorEntries_fresh h.shapeChecked) (Environment.insert_old + (h.shapeChecked.fresh _ (List.mem_cons_self ..)) hr)) + +variable {V : Type v} [SetTheory V] + +theorem publishedAssignment_realizes {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} (h : CheckedBlock.{u,v} entries store source recursor shape mode) + (hE : entries.WF) (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (shape.recursorAssignment constants source recursor mode) + (shape.publishedEnvironment entries source recursor mode) := by + have hstage := recursorAssignment_realizes h.shapeChecked hE h.constructors h.recursorChecked h.elimination constants hM + have hlocal : EntryRealization (shape.recursorAssignment constants source recursor mode) (.member recursor 0) + (shape.publishedRecursorEntry source recursor mode) := by + constructor + · exact hstage.typeValid (.member recursor 0) (shape.recursorEntry source mode) (Environment.insert_same ..) + · exact hstage.member (.member recursor 0) (shape.recursorEntry source mode) (Environment.insert_same ..) + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl levels hn env + obtain ⟨i, ctor, hc, rfl⟩ := recursorLaws_member hl + exact produced_rule_eq h.shapeChecked hE h.constructors h.recursorChecked h.elimination hM hn hc (h.rules i ctor hc) env + · intro fact hf; cases hf + have hm := hstage.insert hlocal + simpa only [publishedEnvironment, recursorEnvironment, Environment.insert_replace] using hm + +theorem publishedAssignment_agrees {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} (h : CheckedBlock.{u,v} entries store source recursor shape mode) + (constants : Assignment β V) : + Assignment.AgreesOn entries constants (shape.recursorAssignment constants source recursor mode) := + (recursorAssignment_reading h.shapeChecked h.recursorChecked constants).agrees + +end Shape + +/-- Source provenance is data-only. Both blocks and every equation endpoint +are tied to the exact ordinary description and recursor stored in the input. -/ +def EntrySource (store : Store β) (r : ConstRef β) (entry : ConstantEntry β) : Prop := + ∃ shape : Shape β, ∃ source recursor mode, + store.blocks source = some ⟨[shape.source source]⟩ ∧ + shape.RecursorSourceMatches store source recursor mode ∧ + ((r = .member source 0 ∧ entry = shape.familyEntry) ∨ + (∃ i ctor, shape.constructors[i]? = some ctor ∧ r = .ctor source 0 i ∧ entry = shape.constructorEntry source ctor) ∨ + (r = .member recursor 0 ∧ entry = shape.publishedRecursorEntry source recursor mode)) + +theorem publishedEntry_source {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} (h : CheckedBlock.{u,v} entries store source recursor shape mode) + {r : ConstRef β} {entry : ConstantEntry β} + (hr : shape.publishedEnvironment entries source recursor mode r = some entry) : + entries r = some entry ∨ EntrySource store r entry := by + have wrap : ∀ entry, ((r = .member source 0 ∧ entry = shape.familyEntry) ∨ + (∃ i ctor, shape.constructors[i]? = some ctor ∧ r = .ctor source 0 i ∧ entry = shape.constructorEntry source ctor) ∨ + (r = .member recursor 0 ∧ entry = shape.publishedRecursorEntry source recursor mode)) → EntrySource store r entry := + fun _ hh => ⟨shape, source, recursor, mode, h.shapeChecked.exactSource, h.recursorChecked.exactSource, hh⟩ + unfold Shape.publishedEnvironment Environment.insert at hr + split at hr + next he => + cases Option.some.inj hr + exact Or.inr (wrap _ (Or.inr (Or.inr ⟨he, rfl⟩))) + next => + unfold Shape.constructorEnvironment Environment.overlay at hr + split at hr + next entry' he => + cases Option.some.inj hr + obtain ⟨i, ctor, hr, hc, he'⟩ := Shape.constructorEntries_some he + exact Or.inr (wrap _ (Or.inr (Or.inl ⟨i, ctor, hc, hr, he'⟩))) + next => + unfold Shape.familyEnvironment Environment.insert at hr + split at hr + next he => + cases Option.some.inj hr + exact Or.inr (wrap _ (Or.inl ⟨he, rfl⟩)) + next => exact Or.inl hr + +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/Computation.lean b/Ix/Theory/Certified/Ordinary/Computation.lean new file mode 100644 index 000000000..00c9c2274 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Computation.lean @@ -0,0 +1,133 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Eliminator + +namespace Ix.Theory.Certified.Ordinary.Shape + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Model.InductiveCodes + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +noncomputable def recursiveCall (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (minors : List V) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) + (xs fs : List V) (j : Nat) (field : RecursiveField β) : V := + Telescope.curry v (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) fun ys => + Telescope.applyN (shape.largeValue constants levels env v m minors hD hlarge) + (field.indices.map (interp constants levels (Telescope.extend (Telescope.extend env xs) ys)) ++ + [Telescope.applyN (fs.getD j empty) ys]) + +noncomputable def recursiveCalls (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (minors : List V) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) + (ctor : Constructor β) (xs fs : List V) : List V := + ctor.recursive.zipIdx.map fun (field, j) => + shape.recursiveCall constants levels env v m minors hD hlarge xs fs j field + +variable {entries : Environment β} {store : Store β} {source : β} {shape : Shape β} + {constants : Assignment β V} {levels : List Nat} {env : Nat → V} + +theorem ihValue_childResults (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {minors : List V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + (hminors : shape.MinorValuesFit constants levels env v m minors) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) + {i j : Nat} {ctor : Constructor β} {field : RecursiveField β} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) + {index : V} (hi : index ∈ˢ shape.indexSet constants levels env) + (ha : inj i (mkTower xs) ∈ˢ (shape.container constants levels env).shapes index) + {g : V} (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) + (he : g = shape.branches constants levels env ctor i xs fs) : + shape.ihValue constants levels env v xs j field + (IndexedContainer.childResults hD hi ha hg + (IndexedContainer.fold hD hlarge (shape.algebra constants levels env v m minors))) = + shape.recursiveCall constants levels env v m minors hD hlarge xs fs j field := by + subst g + have hctor := h.constructors ctor (List.mem_of_getElem? hc) + have hfield := hctor.2.2.2.2 field (List.mem_of_getElem? hf) + apply Telescope.curry_congr + intro ys hy + have hp := inj_mem_positions hc hf (FitsS.length_eq hx) hy + have ht := recursiveTarget_fits hctor hfield hM hΓ hx hy + have hchild := Telescope.applyN_mem _ (hfs.get hf) hy (recursiveResult_zero hctor hfield hM hΓ hx) + rw [IndexedContainer.app_childResults hD hi ha hg _ hp, + largeValue_apply h hM hΓ hm hminors hD hlarge ht hchild, + IndexedContainer.foldAt_eq hD hlarge _ (mkTower_mem (by decide : 1 ≠ 0) ht) hchild] + apply congrArg (IndexedContainer.fold hD hlarge (shape.algebra constants levels env v m minors)) + apply Subtype.ext + simp only [IndexedContainer.child, container, + targetIndex_inj constants levels env hc hf (FitsS.length_eq hx) (FitsS.length_eq hy), + app_branches hc hf (FitsS.length_eq hx) hy] + +theorem ihValues_childResults (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {minors : List V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + (hminors : shape.MinorValuesFit constants levels env v m minors) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) + {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) + {index : V} (hi : index ∈ˢ shape.indexSet constants levels env) + (ha : inj i (mkTower xs) ∈ˢ (shape.container constants levels env).shapes index) + {g : V} (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) + (he : g = shape.branches constants levels env ctor i xs fs) : + shape.ihValues constants levels env v ctor xs + (IndexedContainer.childResults hD hi ha hg + (IndexedContainer.fold hD hlarge (shape.algebra constants levels env v m minors))) = + shape.recursiveCalls constants levels env v m minors hD hlarge ctor xs fs := by + apply List.ext_getElem? + intro j + simp only [ihValues, recursiveCalls, List.getElem?_map, List.getElem?_zipIdx] + cases hf : ctor.recursive[j]? with + | none => rfl + | some field => + simp only [Option.map_some, Nat.zero_add] + exact congrArg some (ihValue_childResults h hM hΓ hm hminors hD hlarge hc hf hx hfs hi ha hg he) + +/-- Semantic iota at the original constructor's result indices, with one +recursive call for each source field and every functional argument. -/ +theorem largeValue_iota (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {minors : List V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + (hminors : shape.MinorValuesFit constants levels env v m minors) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) + {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) : + Telescope.applyN (shape.largeValue constants levels env v m minors hD hlarge) + (ctor.indices.map (interp constants levels (Telescope.extend env xs)) ++ + [shape.constructorValue constants levels env ctor i xs fs]) = + Telescope.applyN (minors.getD i empty) + (xs ++ fs ++ shape.recursiveCalls constants levels env v m minors hD hlarge ctor xs fs) := by + have hctor := h.constructors ctor (List.mem_of_getElem? hc) + have ht := constructorResult_fits hctor hM hΓ hx + have hi := constructorResult_mem hctor hM hΓ hx + have ha : inj i (mkTower xs) ∈ˢ (shape.container constants levels env).shapes + (mkTower (ctor.indices.map (interp constants levels (Telescope.extend env xs)))) := + mem_sep.mpr ⟨inj_mem_allShapes hc hx, resultIndex_inj constants levels env hc (FitsS.length_eq hx)⟩ + have hg := branches_mem hc hctor hM hΓ hx hfs + have hx' := constructorValue_mem h hM hΓ hc hx hfs + rw [largeValue_apply h hM hΓ hm hminors hD hlarge ht hx', + IndexedContainer.foldAt_eq hD hlarge _ hi hx'] + change IndexedContainer.fold hD hlarge _ ⟨(_, IndexedContainer.node _ _ _), _⟩ = _ + rw [IndexedContainer.fold_node hD hlarge _ hi ha hg] + simp only [algebra, tag_inj, hc, ordinaryValues_inj _ (FitsS.length_eq hx)] + rw [decodeFields_branches hc hctor hM hΓ hx hfs, + ihValues_childResults h hM hΓ hm hminors hD hlarge hc hx hfs hi ha hg rfl] + +end Ix.Theory.Certified.Ordinary.Shape diff --git a/Ix/Theory/Certified/Ordinary/ConstructorStage.lean b/Ix/Theory/Certified/Ordinary/ConstructorStage.lean new file mode 100644 index 000000000..d2d72a78b --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/ConstructorStage.lean @@ -0,0 +1,154 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.RecursorValue +import Ix.Theory.Model.Signature + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel + +universe u v +variable {β : Type u} [DecidableEq β] + +namespace Shape + +def constructorEntry (shape : Shape β) (source : β) (ctor : Constructor β) : ConstantEntry β := + ⟨shape.universes, ctor.type shape source, none, [], []⟩ + +def constructorEntries (shape : Shape β) (source : β) : Environment β + | .ctor b 0 i => if b = source then (shape.constructors[i]?).map (shape.constructorEntry source) else none + | _ => none + +theorem constructorEntries_some {shape : Shape β} {source : β} {r : ConstRef β} {entry : ConstantEntry β} + (h : shape.constructorEntries source r = some entry) : + ∃ i ctor, r = .ctor source 0 i ∧ shape.constructors[i]? = some ctor ∧ entry = shape.constructorEntry source ctor := by + cases r with + | member _ _ => simp [constructorEntries] at h + | ctor b member i => + cases member with + | succ _ => simp [constructorEntries] at h + | zero => + by_cases hb : b = source + · subst b + simp only [constructorEntries, ↓reduceIte] at h + obtain ⟨ctor, hc, he⟩ := Option.map_eq_some_iff.mp h + exact ⟨i, ctor, rfl, hc, he.symm⟩ + · simp [constructorEntries, hb] at h + +def constructorEnvironment (shape : Shape β) (entries : Environment β) (source : β) : Environment β := + (shape.familyEnvironment entries source).overlay (shape.constructorEntries source) + +theorem constructorEntries_fresh {entries : Environment β} {store : Store β} {source : β} {shape : Shape β} + (h : CheckedShape.{u,v} entries store source shape) : + (shape.familyEnvironment entries source).Fresh (shape.constructorEntries source) := by + intro r entry hr + obtain ⟨i, ctor, rfl, hc, _⟩ := constructorEntries_some hr + have hf := h.fresh (.ctor source 0 i) (List.mem_cons_of_mem _ + (List.mem_map.mpr ⟨i, List.mem_range.mpr (List.getElem?_eq_some_iff.mp hc).1, rfl⟩)) + simpa [familyEnvironment, Environment.insert] using hf + +def ConstructorFormation (entries : Environment β) (shape : Shape β) (source : β) : Prop := + ∀ ctor ∈ shape.constructors, + EntryClosed (shape.familyEnvironment entries source) (shape.constructorEntry source ctor) ∧ + ∃ l, TypingClaim.{u,v} (shape.familyEnvironment entries source) [] (ctor.type shape source) (.sort l) + +structure TypeWitness (β : Type u) where + level : VLevel + witness : TypingWitness β + +def checkConstructorTypes (fuel : Nat) (entries : Environment β) (shape : Shape β) (source : β) : + (ctors : List (Constructor β)) → List (TypeWitness β) → + Option (CheckedClaim.{u} (∀ ctor ∈ ctors, + EntryClosed (shape.familyEnvironment entries source) (shape.constructorEntry source ctor) ∧ + ∃ l, TypingClaim.{u,v} (shape.familyEnvironment entries source) [] (ctor.type shape source) (.sort l))) + | [], [] => some ⟨by simp⟩ + | ctor :: ctors, witness :: witnesses => + if hs : (ctor.type shape source).Scope shape.universes 0 then + if hr : (ctor.type shape source).ReferencesIn (shape.familyEnvironment entries source) then do + let ht ← verifyType.{u,v} fuel shape.universes (shape.familyEnvironment entries source) [] + (ctor.type shape source) (.sort witness.level) witness.witness + let rest ← checkConstructorTypes fuel entries shape source ctors witnesses + return ⟨by + intro ctor' hc + rcases List.mem_cons.mp hc with rfl | hc + · exact ⟨⟨hs, by simp [constructorEntry], hr, by simp [constructorEntry], + by simp [constructorEntry], by simp [constructorEntry], + by simp [constructorEntry], by simp [constructorEntry]⟩, witness.level, ht.down⟩ + · exact rest.down ctor' hc⟩ + else none + else none + | _, _ => none + +theorem constructorEnvironment_wf {entries : Environment β} {store : Store β} {source : β} {shape : Shape β} + (h : CheckedShape.{u,v} entries store source shape) (hE : entries.WF) + (hT : ConstructorFormation.{u,v} entries shape source) : + (shape.constructorEnvironment entries source).WF := by + apply (familyEnvironment_wf h hE).overlay + intro r entry hr + obtain ⟨i, ctor, rfl, hc, rfl⟩ := constructorEntries_some hr + exact (hT ctor (List.mem_of_getElem? hc)).1 + +variable {V : Type v} [SetTheory V] + +noncomputable def constructorValues (shape : Shape β) (constants : Assignment β V) : Assignment β V + | .ctor _ 0 i, levels => + match shape.constructors[i]? with + | some ctor => shape.constructorClosedValue constants levels i ctor + | none => empty + | _, _ => empty + +noncomputable def constructorAssignment (shape : Shape β) (constants : Assignment β V) (source : β) : Assignment β V := + (shape.familyAssignment constants source).overlay (shape.constructorValues constants) (shape.constructorEntries source) + +theorem constructorAssignment_agreesFamily {entries : Environment β} {store : Store β} {source : β} + {shape : Shape β} (h : CheckedShape.{u,v} entries store source shape) (constants : Assignment β V) : + Assignment.AgreesOn (shape.familyEnvironment entries source) (shape.familyAssignment constants source) + (shape.constructorAssignment constants source) := + Assignment.overlay_agrees (constructorEntries_fresh h) _ _ + +theorem constructorAssignment_reading {entries : Environment β} {store : Store β} {source : β} + {shape : Shape β} (h : CheckedShape.{u,v} entries store source shape) (constants : Assignment β V) : + ConstructorReading entries shape source constants (shape.constructorAssignment constants source) where + agrees := by + intro r entry hr levels + exact (constructorAssignment_agreesFamily h constants r entry + (Environment.insert_old (h.fresh _ (List.mem_cons_self ..)) hr) levels).trans + (familyAssignment_agrees h constants r entry hr levels) + family := by + intro levels _ + simp only [constructorAssignment, Assignment.overlay, constructorEntries, + familyAssignment, Assignment.insert_same] + constructor := by + intro levels _ i ctor hc + simp only [constructorAssignment, Assignment.overlay, constructorEntries, + ↓reduceIte, hc, Option.map_some, constructorValues] + +theorem constructorAssignment_realizes {entries : Environment β} {store : Store β} {source : β} + {shape : Shape β} (h : CheckedShape.{u,v} entries store source shape) (hE : entries.WF) + (hT : ConstructorFormation.{u,v} entries shape source) + (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (shape.constructorAssignment constants source) (shape.constructorEnvironment entries source) := by + have hr := constructorAssignment_reading h constants + have hbase := (familyAssignment_realizes h hE constants hM).of_agrees + (familyEnvironment_wf h hE) (constructorAssignment_agreesFamily h constants) + apply hbase.overlay + intro r entry hentry + obtain ⟨i, ctor, rfl, hc, rfl⟩ := constructorEntries_some hentry + obtain ⟨hclosed, l, htype⟩ := hT ctor (List.mem_of_getElem? hc) + constructor + · intro levels hn env + exact (htype V _ hbase levels env (Context.valid_nil _ _ _)).1 + · intro levels hn env + rw [hr.constructor levels hn i ctor hc] + have hm := constructorClosedValue_mem_source h hr.toFamilyReading hM hn hc + rwa [interp_closed (ctor.type shape source) _ levels hclosed.typeScope (fun _ => empty) env] at hm + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl; simp only [constructorEntry, List.not_mem_nil] at hl + · intro fact hf; simp only [constructorEntry, List.not_mem_nil] at hf + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/Constructors.lean b/Ix/Theory/Certified/Ordinary/Constructors.lean new file mode 100644 index 000000000..a06885be8 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Constructors.lean @@ -0,0 +1,237 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Container + +namespace Ix.Theory.Certified.Ordinary.Shape + +open Model Model.SetTheory Model.SetTheory.Tower Model.InductiveCodes + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +noncomputable def carrier (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) : V := (shape.container constants levels env).carrier (shape.level.eval levels) + +noncomputable def recursiveSet (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (xs : List V) (field : RecursiveField β) : V := + Telescope.piN (shape.level.eval levels) + (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) + (fun ys => app (shape.carrier constants levels env) + (mkTower (field.indices.map (interp constants levels (Telescope.extend (Telescope.extend env xs) ys))))) + +def RecursiveValuesFit (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (ctor : Constructor β) (xs fs : List V) : Prop := + FitsS (Telescope.simple (ctor.recursive.map (shape.recursiveSet constants levels env xs))) fs + +noncomputable def branchBody (ctor : Constructor β) (fs : List V) (p : V) : V := + match ctor.recursive[tag p]? with + | none => empty + | some field => Telescope.applyN (fs.getD (tag p) empty) (projList field.domains.length (ssnd p)) + +noncomputable def branches (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (ctor : Constructor β) (i : Nat) (xs fs : List V) : V := + graph (branchBody ctor fs) (shape.positions constants levels env (inj i (mkTower xs))) + +noncomputable def constructorValue (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (ctor : Constructor β) (i : Nat) (xs fs : List V) : V := + IndexedContainer.node (shape.level.eval levels) (inj i (mkTower xs)) + (shape.branches constants levels env ctor i xs fs) + +theorem RecursiveValuesFit.get {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {ctor : Constructor β} {xs fs : List V} + (h : shape.RecursiveValuesFit constants levels env ctor xs fs) + {j : Nat} {field : RecursiveField β} (hf : ctor.recursive[j]? = some field) : + fs.getD j empty ∈ˢ shape.recursiveSet constants levels env xs field := by + apply Telescope.fits_simple_getD h + simp only [List.getElem?_map, hf, Option.map_some] + +theorem app_branches {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {ctor : Constructor β} {field : RecursiveField β} {i j : Nat} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) + {xs ys fs : List V} (hx : xs.length = ctor.fields.length) + (hy : FitsS (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) ys) : + app (shape.branches constants levels env ctor i xs fs) (inj j (mkTower ys)) = + Telescope.applyN (fs.getD j empty) ys := by + rw [branches, app_graph (inj_mem_positions hc hf hx hy)] + simp only [branchBody, tag_inj, hf, ssnd_inj, projList_mkTower _ _ (FitsS.length_eq hy)] + +variable {entries : Environment β} {shape : Shape β} {constants : Assignment β V} + {levels : List Nat} {env : Nat → V} {ctor : Constructor β} + +theorem recursiveSet_mem_univ {field : RecursiveField β} + (h : ConstructorEvidence.{u,v} entries shape ctor) + (hr : RecursiveEvidence.{u,v} entries shape ctor field) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) : + shape.recursiveSet constants levels env xs field ∈ˢ (univ (shape.level.eval levels) : V) := by + apply Telescope.piN_mem_univ + · exact fun hw => hr.2.2.1 shape.level rfl V constants hM levels _ + (h.2.1.valid constants hM levels hΓ hx) hw + · intro ys hy + exact (shape.container constants levels env).carrier_fibre_mem (shape.level.eval levels) + (recursiveTarget_mem h hr hM hΓ hx hy) + +theorem recursiveResult_zero {field : RecursiveField β} + (h : ConstructorEvidence.{u,v} entries shape ctor) + (hr : RecursiveEvidence.{u,v} entries shape ctor field) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hw : shape.level.eval levels = 0) : + ∀ ys, FitsS (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) ys → + app (shape.carrier constants levels env) + (mkTower (field.indices.map (interp constants levels (Telescope.extend (Telescope.extend env xs) ys)))) + ∈ˢ (univZero : V) := by + intro ys hy + have hm := (shape.container constants levels env).carrier_fibre_mem (shape.level.eval levels) + (recursiveTarget_mem h hr hM hΓ hx hy) + simpa only [hw, univ_zero, carrier] using hm + +theorem branches_mem {i : Nat} (hc : shape.constructors[i]? = some ctor) + (h : ConstructorEvidence.{u,v} entries shape ctor) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) : + shape.branches constants levels env ctor i xs fs ∈ˢ + piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p)) := by + apply graph_mem_piSet + intro p hp + obtain ⟨j, field, ys, hf, hy, rfl⟩ := mem_positions hc (FitsS.length_eq hx) hp + simp only [branchBody, tag_inj, hf, ssnd_inj, projList_mkTower _ _ (FitsS.length_eq hy), + targetIndex_inj constants levels env hc hf (FitsS.length_eq hx) (FitsS.length_eq hy)] + exact Telescope.applyN_mem _ (hfs.get hf) hy + (recursiveResult_zero h (h.2.2.2.2 field (List.mem_of_getElem? hf)) hM hΓ hx) + +theorem constructorValue_mem {store : Store β} {source : β} + (h : CheckedShape.{u,v} entries store source shape) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {i : Nat} + (hc : shape.constructors[i]? = some ctor) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) : + shape.constructorValue constants levels env ctor i xs fs ∈ˢ + app (shape.carrier constants levels env) + (mkTower (ctor.indices.map (interp constants levels (Telescope.extend env xs)))) := by + have hctor := h.constructors ctor (List.mem_of_getElem? hc) + apply IndexedContainer.node_mem_carrier (container_wf h hM hΓ) + (constructorResult_mem hctor hM hΓ hx) + · exact mem_sep.mpr ⟨inj_mem_allShapes hc hx, resultIndex_inj constants levels env hc (FitsS.length_eq hx)⟩ + · exact branches_mem hc hctor hM hΓ hx hfs + +/-- Reconstruct one recursive function from the container's branch graph. +Eta will recover the original source function, including at Prop. -/ +noncomputable def decodeField (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (xs : List V) (j : Nat) (field : RecursiveField β) (g : V) : V := + Telescope.curry (shape.level.eval levels) + (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) + (fun ys => app g (inj j (mkTower ys))) + +noncomputable def decodeFields (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (ctor : Constructor β) (xs : List V) (g : V) : List V := + ctor.recursive.zipIdx.map fun (field, j) => shape.decodeField constants levels env xs j field g + +theorem getD_decodeFields (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (ctor : Constructor β) (xs : List V) (g : V) {j : Nat} {field : RecursiveField β} + (hf : ctor.recursive[j]? = some field) : + (shape.decodeFields constants levels env ctor xs g).getD j empty = + shape.decodeField constants levels env xs j field g := by + simp only [decodeFields, List.getD_eq_getElem?_getD, List.getElem?_map, + List.getElem?_zipIdx, hf, Option.map_some, Nat.zero_add, Option.getD_some] + +theorem decodeField_mem {i j : Nat} {field : RecursiveField β} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) + {xs : List V} (hx : xs.length = ctor.fields.length) {g : V} + (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) : + shape.decodeField constants levels env xs j field g ∈ˢ shape.recursiveSet constants levels env xs field := by + apply Telescope.curry_mem + intro ys hy + have hp := app_mem_of_mem_piSet hg (inj_mem_positions hc hf hx hy) + rwa [targetIndex_inj constants levels env hc hf hx (FitsS.length_eq hy)] at hp + +theorem decodeFields_fit {i : Nat} (hc : shape.constructors[i]? = some ctor) + {xs : List V} (hx : xs.length = ctor.fields.length) {g : V} + (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) : + shape.RecursiveValuesFit constants levels env ctor xs (shape.decodeFields constants levels env ctor xs g) := by + apply Telescope.fits_simple_map + · simp only [decodeFields, List.length_map, List.length_zipIdx] + · intro j field hf + rw [getD_decodeFields _ _ _ _ _ _ _ hf] + exact decodeField_mem hc hf hx hg + +theorem applyN_decodeField {i j : Nat} {field : RecursiveField β} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) + (h : ConstructorEvidence.{u,v} entries shape ctor) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs ys : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hy : FitsS (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) ys) {g : V} + (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) : + Telescope.applyN (shape.decodeField constants levels env xs j field g) ys = app g (inj j (mkTower ys)) := by + apply Telescope.applyN_curry _ hy + · intro zs hz + have hm := app_mem_of_mem_piSet hg (inj_mem_positions hc hf (FitsS.length_eq hx) hz) + rwa [targetIndex_inj constants levels env hc hf (FitsS.length_eq hx) (FitsS.length_eq hz)] at hm + · exact recursiveResult_zero h (h.2.2.2.2 field (List.mem_of_getElem? hf)) hM hΓ hx + +theorem decodeField_branches {i j : Nat} {field : RecursiveField β} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) + (h : ConstructorEvidence.{u,v} entries shape ctor) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) : + shape.decodeField constants levels env xs j field (shape.branches constants levels env ctor i xs fs) = + fs.getD j empty := by + change Telescope.curry _ _ _ = _ + calc + _ = Telescope.curry (shape.level.eval levels) + (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) + (Telescope.applyN (fs.getD j empty)) := by + apply Telescope.curry_congr + exact fun ys hy => app_branches hc hf (FitsS.length_eq hx) hy + _ = _ := Telescope.curry_applyN _ (hfs.get hf) + (recursiveResult_zero h (h.2.2.2.2 field (List.mem_of_getElem? hf)) hM hΓ hx) + +theorem decodeFields_branches {i : Nat} (hc : shape.constructors[i]? = some ctor) + (h : ConstructorEvidence.{u,v} entries shape ctor) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) : + shape.decodeFields constants levels env ctor xs (shape.branches constants levels env ctor i xs fs) = fs := by + apply List.ext_getElem + · simpa only [decodeFields, List.length_map, List.length_zipIdx] using (FitsS.length_eq hfs).symm + · intro j hj hj' + have hjc : j < ctor.recursive.length := by + simpa only [decodeFields, List.length_map, List.length_zipIdx] using hj + have hf := List.getElem?_eq_getElem (l := ctor.recursive) hjc + have he := (getD_decodeFields shape constants levels env ctor xs _ hf).trans + (decodeField_branches hc hf h hM hΓ hx hfs) + simpa only [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem hj, + List.getElem?_eq_getElem hj', Option.getD_some] using he + +theorem branches_decodeFields {i : Nat} (hc : shape.constructors[i]? = some ctor) + (h : ConstructorEvidence.{u,v} entries shape ctor) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) {g : V} + (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) : + shape.branches constants levels env ctor i xs (shape.decodeFields constants levels env ctor xs g) = g := by + apply eq_of_mem_piSet_app_eq (branches_mem hc h hM hΓ hx (decodeFields_fit hc (FitsS.length_eq hx) hg)) hg + intro p hp + obtain ⟨j, field, ys, hf, hy, rfl⟩ := mem_positions hc (FitsS.length_eq hx) hp + rw [app_branches hc hf (FitsS.length_eq hx) hy, getD_decodeFields _ _ _ _ _ _ _ hf] + apply Telescope.applyN_curry _ hy + · intro zs hz + have hm := app_mem_of_mem_piSet hg (inj_mem_positions hc hf (FitsS.length_eq hx) hz) + rwa [targetIndex_inj constants levels env hc hf (FitsS.length_eq hx) (FitsS.length_eq hz)] at hm + · exact recursiveResult_zero h (h.2.2.2.2 field (List.mem_of_getElem? hf)) hM hΓ hx + +end Ix.Theory.Certified.Ordinary.Shape diff --git a/Ix/Theory/Certified/Ordinary/Container.lean b/Ix/Theory/Certified/Ordinary/Container.lean new file mode 100644 index 000000000..c30fb56ea --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Container.lean @@ -0,0 +1,266 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Shape +import Ix.Theory.Model.Inductive.Container +import Ix.Theory.Model.Inductive.Codes + +/-! +Construct the indexed container from the exact checked source description. +Shapes contain a constructor tag and its ordinary fields. Positions contain +a recursive-field tag and that function field's arguments. Indices are +dependent tuple codes. No carrier, closed member, or semantic law is supplied +by the witness. +-/ + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower Model.InductiveCodes + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +namespace Shape + +noncomputable def indexSet (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) : V := towerSet 1 (Telescope.interpret constants levels env shape.indices) + +noncomputable def ordinaryValues (ctor : Constructor β) (a : V) : List V := + projList ctor.fields.length (ssnd a) + +noncomputable def ordinaryEnv (ctor : Constructor β) (env : Nat → V) (a : V) : Nat → V := + Telescope.extend env (ordinaryValues ctor a) + +noncomputable def ordinaryFibre (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (i : Nat) : V := + match shape.constructors[i]? with + | none => empty + | some ctor => towerSet 1 (Telescope.interpret constants levels env ctor.fields) + +noncomputable def allShapes (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) : V := sumSet 1 (shape.ordinaryFibre constants levels env) + +noncomputable def resultIndex (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (a : V) : V := + match shape.constructors[tag a]? with + | none => empty + | some ctor => mkTower (ctor.indices.map (interp constants levels (ordinaryEnv ctor env a))) + +noncomputable def positionFibre (ctor : Constructor β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (a : V) (i : Nat) : V := + match ctor.recursive[i]? with + | none => empty + | some field => towerSet 1 (Telescope.interpret constants levels (ordinaryEnv ctor env a) field.domains) + +noncomputable def positions (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (a : V) : V := + match shape.constructors[tag a]? with + | none => empty + | some ctor => sumSet 1 (positionFibre ctor constants levels env a) + +noncomputable def targetIndex (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (a p : V) : V := + match shape.constructors[tag a]? with + | none => empty + | some ctor => + match ctor.recursive[tag p]? with + | none => empty + | some field => + let args := projList field.domains.length (ssnd p) + let extended := Telescope.extend (ordinaryEnv ctor env a) args + mkTower (field.indices.map (interp constants levels extended)) + +noncomputable def container (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) : IndexedContainer V where + indices := shape.indexSet constants levels env + shapes i := sep (shape.allShapes constants levels env) + (fun a => shape.resultIndex constants levels env a = i) + positions := shape.positions constants levels env + target := shape.targetIndex constants levels env + +theorem ordinaryValues_inj {ctor : Constructor β} (i : Nat) {xs : List V} + (hlen : xs.length = ctor.fields.length) : + ordinaryValues ctor (inj i (mkTower xs)) = xs := by + simp only [ordinaryValues, ssnd_inj, projList_mkTower _ _ hlen] + +theorem ordinaryEnv_inj {ctor : Constructor β} (env : Nat → V) (i : Nat) {xs : List V} + (hlen : xs.length = ctor.fields.length) : + ordinaryEnv ctor env (inj i (mkTower xs)) = Telescope.extend env xs := by + rw [ordinaryEnv, ordinaryValues_inj i hlen] + +theorem resultIndex_inj {shape : Shape β} (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) + {xs : List V} (hlen : xs.length = ctor.fields.length) : + shape.resultIndex constants levels env (inj i (mkTower xs)) = + mkTower (ctor.indices.map (interp constants levels (Telescope.extend env xs))) := by + simp only [resultIndex, tag_inj, hc, ordinaryEnv_inj env i hlen] + +theorem positions_inj {shape : Shape β} (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) (x : V) : + shape.positions constants levels env (inj i x) = + sumSet 1 (positionFibre ctor constants levels env (inj i x)) := by + simp only [positions, tag_inj, hc] + +theorem targetIndex_inj {shape : Shape β} (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) {i j : Nat} {ctor : Constructor β} {field : RecursiveField β} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) + {xs ys : List V} (hx : xs.length = ctor.fields.length) (hy : ys.length = field.domains.length) : + shape.targetIndex constants levels env (inj i (mkTower xs)) (inj j (mkTower ys)) = + mkTower (field.indices.map (interp constants levels (Telescope.extend (Telescope.extend env xs) ys))) := by + simp only [targetIndex, tag_inj, hc, hf, ssnd_inj, + projList_mkTower _ _ hy, ordinaryEnv_inj env i hx] + +theorem mem_allShapes {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {a : V} (ha : a ∈ˢ shape.allShapes constants levels env) : + ∃ i ctor xs, shape.constructors[i]? = some ctor ∧ + FitsS (Telescope.interpret constants levels env ctor.fields) xs ∧ a = inj i (mkTower xs) := by + obtain ⟨i, x, hx, rfl⟩ := sumSet_elim (by decide : 1 ≠ 0) ha + cases hc : shape.constructors[i]? with + | none => + simp only [ordinaryFibre, hc] at hx + exact (not_mem_empty x hx).elim + | some ctor => + simp only [ordinaryFibre, hc] at hx + obtain ⟨hfit, he⟩ := towerSet_elim (by decide : 1 ≠ 0) _ hx + exact ⟨i, ctor, _, hc, hfit, congrArg (inj i) he⟩ + +theorem mem_positions {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) + {xs : List V} (hx : xs.length = ctor.fields.length) {p : V} + (hp : p ∈ˢ shape.positions constants levels env (inj i (mkTower xs))) : + ∃ j field ys, ctor.recursive[j]? = some field ∧ + FitsS (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) ys ∧ + p = inj j (mkTower ys) := by + rw [positions_inj constants levels env hc] at hp + obtain ⟨j, y, hy, rfl⟩ := sumSet_elim (by decide : 1 ≠ 0) hp + cases hf : ctor.recursive[j]? with + | none => + simp only [positionFibre, hf] at hy + exact (not_mem_empty y hy).elim + | some field => + simp only [positionFibre, hf, ordinaryEnv_inj env i hx] at hy + obtain ⟨hfit, he⟩ := towerSet_elim (by decide : 1 ≠ 0) _ hy + exact ⟨j, field, _, hf, hfit, congrArg (inj j) he⟩ + +theorem inj_mem_allShapes {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) + {xs : List V} (hxs : FitsS (Telescope.interpret constants levels env ctor.fields) xs) : + inj i (mkTower xs) ∈ˢ shape.allShapes constants levels env := by + apply inj_mem (by decide : 1 ≠ 0) + simpa only [ordinaryFibre, hc] using mkTower_mem (by decide : 1 ≠ 0) hxs + +theorem inj_mem_positions {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {i j : Nat} {ctor : Constructor β} {field : RecursiveField β} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) + {xs ys : List V} (hx : xs.length = ctor.fields.length) + (hys : FitsS (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) ys) : + inj j (mkTower ys) ∈ˢ shape.positions constants levels env (inj i (mkTower xs)) := by + rw [positions_inj constants levels env hc] + apply inj_mem (by decide : 1 ≠ 0) + simpa only [positionFibre, hf, ordinaryEnv_inj env i hx] using + mkTower_mem (by decide : 1 ≠ 0) hys + +variable {entries : Environment β} {shape : Shape β} {constants : Assignment β V} + {levels : List Nat} {env : Nat → V} + +theorem constructorResult_fits {ctor : Constructor β} + (h : ConstructorEvidence.{u,v} entries shape ctor) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) : + FitsS (Telescope.interpret constants levels env shape.indices) + (ctor.indices.map (interp constants levels (Telescope.extend env xs))) := by + have hΓ' := h.2.1.valid constants hM levels hΓ hx + have ht := h.2.2.2.1 V constants hM levels (Telescope.extend env xs) hΓ' + have ht' := (Telescope.fits_lift constants levels (Telescope.extend env xs) + ctor.fields.length shape.indices 0 _).mp ht + rw [← FitsS.length_eq hx, Telescope.skip_extend] at ht' + exact ht' + +theorem constructorResult_mem {ctor : Constructor β} + (h : ConstructorEvidence.{u,v} entries shape ctor) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) : + mkTower (ctor.indices.map (interp constants levels (Telescope.extend env xs))) ∈ˢ + shape.indexSet constants levels env := + mkTower_mem (by decide : 1 ≠ 0) (constructorResult_fits h hM hΓ hx) + +theorem recursiveTarget_fits {ctor : Constructor β} {field : RecursiveField β} + (h : ConstructorEvidence.{u,v} entries shape ctor) + (hr : RecursiveEvidence.{u,v} entries shape ctor field) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs ys : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hy : FitsS (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) ys) : + FitsS (Telescope.interpret constants levels env shape.indices) + (field.indices.map (interp constants levels (Telescope.extend (Telescope.extend env xs) ys))) := by + have hΓ' := h.2.1.valid constants hM levels hΓ hx + have hΓ'' := hr.2.1.valid constants hM levels hΓ' hy + have ht := hr.2.2.2 V constants hM levels _ hΓ'' + have ht' := (Telescope.fits_lift constants levels (Telescope.extend (Telescope.extend env xs) ys) + (ctor.fields.length + field.domains.length) shape.indices 0 _).mp ht + rw [← Telescope.extend_append, ← FitsS.length_eq hx, ← FitsS.length_eq hy, + ← List.length_append, Telescope.skip_extend] at ht' + simpa only [Telescope.extend_append] using ht' + +theorem recursiveTarget_mem {ctor : Constructor β} {field : RecursiveField β} + (h : ConstructorEvidence.{u,v} entries shape ctor) + (hr : RecursiveEvidence.{u,v} entries shape ctor field) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) {xs ys : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hy : FitsS (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) ys) : + mkTower (field.indices.map (interp constants levels (Telescope.extend (Telescope.extend env xs) ys))) ∈ˢ + shape.indexSet constants levels env := + mkTower_mem (by decide : 1 ≠ 0) (recursiveTarget_fits h hr hM hΓ hx hy) + +theorem allShapes_mem + (h : ∀ ctor ∈ shape.constructors, ConstructorEvidence.{u,v} entries shape ctor) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + (hw : shape.level.eval levels ≠ 0) : + shape.allShapes constants levels env ∈ˢ (univ (shape.level.eval levels) : V) := by + apply sum_graph_mem hw + intro i + cases hc : shape.constructors[i]? with + | none => simpa only [ordinaryFibre, hc] using empty_mem_univ (V := V) (shape.level.eval levels) + | some ctor => + simp only [ordinaryFibre, hc] + apply Telescope.tower_graph_mem hw + exact (h ctor (List.mem_of_getElem? hc)).2.2.1 shape.level rfl V constants hM levels env hΓ hw + +/-- Every fixed-point premise is produced from checked field sorts and +dependent index applications. In particular, target-index membership is not +an assumed container property of the input. -/ +theorem container_wf {store : Store β} {source : β} + (h : CheckedShape.{u,v} entries store source shape) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants levels env) : + (shape.container constants levels env).WF (shape.level.eval levels) := by + constructor + · intro hw i hi + exact univ_sep_mem (allShapes_mem h.constructors hM hΓ hw) + · intro hw i a hi ha + obtain ⟨ha, _⟩ := mem_sep.mp ha + obtain ⟨j, ctor, xs, hc, hxs, rfl⟩ := mem_allShapes ha + change shape.positions constants levels env _ ∈ˢ _ + rw [positions_inj constants levels env hc] + apply sum_graph_mem hw + intro k + cases hf : ctor.recursive[k]? with + | none => simpa only [positionFibre, hf] using empty_mem_univ (V := V) (shape.level.eval levels) + | some field => + simp only [positionFibre, hf, ordinaryEnv_inj env j (FitsS.length_eq hxs)] + apply Telescope.tower_graph_mem hw + have hctor := h.constructors ctor (List.mem_of_getElem? hc) + have hfield := hctor.2.2.2.2 field (List.mem_of_getElem? hf) + exact hfield.2.2.1 shape.level rfl V constants hM levels _ + (hctor.2.1.valid constants hM levels hΓ hxs) hw + · intro i a p hi ha hp + obtain ⟨ha, _⟩ := mem_sep.mp ha + obtain ⟨j, ctor, xs, hc, hxs, rfl⟩ := mem_allShapes ha + obtain ⟨k, field, ys, hf, hys, rfl⟩ := mem_positions hc (FitsS.length_eq hxs) hp + change shape.targetIndex constants levels env _ _ ∈ˢ shape.indexSet constants levels env + rw [targetIndex_inj constants levels env hc hf (FitsS.length_eq hxs) (FitsS.length_eq hys)] + have hctor := h.constructors ctor (List.mem_of_getElem? hc) + exact recursiveTarget_mem hctor (hctor.2.2.2.2 field (List.mem_of_getElem? hf)) hM hΓ hxs hys + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/Eliminator.lean b/Ix/Theory/Certified/Ordinary/Eliminator.lean new file mode 100644 index 000000000..937c805b2 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Eliminator.lean @@ -0,0 +1,264 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.LargeElim + +namespace Ix.Theory.Certified.Ordinary.Shape + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Model.InductiveCodes + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +noncomputable def motiveSet (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (motiveLevel : Nat) : V := + Telescope.piN 1 (Telescope.interpret constants levels env shape.indices) + (fun is => piR 1 (app (shape.carrier constants levels env) (mkTower is)) + (fun _ => univ motiveLevel)) + +noncomputable def motive (shape : Shape β) (m : V) (i x : V) : V := + app (Telescope.applyN m (projList shape.indices.length i)) x + +theorem motive_mem {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {v : Nat} {m i x : V} + (hm : m ∈ˢ shape.motiveSet constants levels env v) + (hi : i ∈ˢ shape.indexSet constants levels env) + (hx : x ∈ˢ app (shape.carrier constants levels env) i) : + shape.motive m i x ∈ˢ (univ v : V) := by + obtain ⟨hfit, he⟩ := towerSet_elim (by decide : 1 ≠ 0) _ hi + have ht := Telescope.applyN_mem _ hm hfit (fun h => (by omega : False).elim) + rw [← he] at ht + exact app_mem_piR_pos (by decide : 1 ≠ 0) ht hx + +noncomputable def ihSet (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (xs fs : List V) (j : Nat) (field : RecursiveField β) : V := + Telescope.piN v (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) + (fun ys => shape.motive m + (mkTower (field.indices.map (interp constants levels (Telescope.extend (Telescope.extend env xs) ys)))) + (Telescope.applyN (fs.getD j empty) ys)) + +noncomputable def ihTypes (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (ctor : Constructor β) (xs fs : List V) : List V := + ctor.recursive.zipIdx.map fun (field, j) => shape.ihSet constants levels env v m xs fs j field + +def IHValuesFit (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (ctor : Constructor β) (xs fs hs : List V) : Prop := + FitsS (Telescope.simple (shape.ihTypes constants levels env v m ctor xs fs)) hs + +noncomputable def minorSet (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (i : Nat) (ctor : Constructor β) : V := + Telescope.piN v (Telescope.interpret constants levels env ctor.fields) fun xs => + Telescope.piN v (Telescope.simple (ctor.recursive.map (shape.recursiveSet constants levels env xs))) fun fs => + Telescope.piN v (Telescope.simple (shape.ihTypes constants levels env v m ctor xs fs)) fun _ => + shape.motive m (mkTower (ctor.indices.map (interp constants levels (Telescope.extend env xs)))) + (shape.constructorValue constants levels env ctor i xs fs) + +noncomputable def minorTypes (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) : List V := + shape.constructors.zipIdx.map fun (ctor, i) => shape.minorSet constants levels env v m i ctor + +def MinorValuesFit (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (minors : List V) : Prop := + FitsS (Telescope.simple (shape.minorTypes constants levels env v m)) minors + +theorem MinorValuesFit.get {shape : Shape β} {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {v : Nat} {m : V} {minors : List V} + (h : shape.MinorValuesFit constants levels env v m minors) + {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) : + minors.getD i empty ∈ˢ shape.minorSet constants levels env v m i ctor := by + apply Telescope.fits_simple_getD h + simp only [minorTypes, List.getElem?_map, List.getElem?_zipIdx, hc, Option.map_some, Nat.zero_add] + +variable {entries : Environment β} {store : Store β} {source : β} {shape : Shape β} + {constants : Assignment β V} {levels : List Nat} {env : Nat → V} + +theorem minorResult_mem_univ (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) {xs fs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) : + shape.motive m (mkTower (ctor.indices.map (interp constants levels (Telescope.extend env xs)))) + (shape.constructorValue constants levels env ctor i xs fs) ∈ˢ (univ v : V) := + motive_mem hm (constructorResult_mem (h.constructors ctor (List.mem_of_getElem? hc)) hM hΓ hx) + (constructorValue_mem h hM hΓ hc hx hfs) + +theorem minor_apply_mem (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m minor : V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) + (hminor : minor ∈ˢ shape.minorSet constants levels env v m i ctor) {xs fs hs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels env ctor xs fs) + (hhs : shape.IHValuesFit constants levels env v m ctor xs fs hs) : + Telescope.applyN minor (xs ++ fs ++ hs) ∈ˢ + shape.motive m (mkTower (ctor.indices.map (interp constants levels (Telescope.extend env xs)))) + (shape.constructorValue constants levels env ctor i xs fs) := by + simp only [Telescope.applyN_append] + have hxstep := Telescope.applyN_mem _ hminor hx (fun hv ys hy => by + subst v + apply Telescope.piN_zero_mem + intro gs hgs + apply Telescope.piN_zero_mem + intro _ _ + simpa only [univ_zero] using minorResult_mem_univ h hM hΓ hm hc hy hgs) + have hfsstep := Telescope.applyN_mem _ hxstep hfs (fun hv gs hgs => by + subst v + apply Telescope.piN_zero_mem + intro _ _ + simpa only [univ_zero] using minorResult_mem_univ h hM hΓ hm hc hx hgs) + exact Telescope.applyN_mem _ hfsstep hhs (fun hv _ _ => by + simpa only [hv, univ_zero] using minorResult_mem_univ h hM hΓ hm hc hx hfs) + +noncomputable def ihValue (_shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (xs : List V) (j : Nat) (field : RecursiveField β) (ih : V) : V := + Telescope.curry v (Telescope.interpret constants levels (Telescope.extend env xs) field.domains) + (fun ys => app ih (inj j (mkTower ys))) + +noncomputable def ihValues (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (ctor : Constructor β) (xs : List V) (ih : V) : List V := + ctor.recursive.zipIdx.map fun (field, j) => shape.ihValue constants levels env v xs j field ih + +theorem ihValue_mem (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {i j : Nat} {ctor : Constructor β} {field : RecursiveField β} + (hc : shape.constructors[i]? = some ctor) (hf : ctor.recursive[j]? = some field) {xs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) {g ih : V} + (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) + (hih : ih ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => shape.motive m (shape.targetIndex constants levels env (inj i (mkTower xs)) p) (app g p))) : + shape.ihValue constants levels env v xs j field ih ∈ˢ + shape.ihSet constants levels env v m xs (shape.decodeFields constants levels env ctor xs g) j field := by + apply Telescope.curry_mem + intro ys hy + have hm := app_mem_of_mem_piSet hih (inj_mem_positions hc hf (FitsS.length_eq hx) hy) + rw [targetIndex_inj constants levels env hc hf (FitsS.length_eq hx) (FitsS.length_eq hy)] at hm + rw [getD_decodeFields _ _ _ _ _ _ _ hf, + applyN_decodeField hc hf (h.constructors ctor (List.mem_of_getElem? hc)) hM hΓ hx hy hg] + exact hm + +theorem ihValues_fit (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {xs : List V} + (hx : FitsS (Telescope.interpret constants levels env ctor.fields) xs) {g ih : V} + (hg : g ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => app (shape.carrier constants levels env) + (shape.targetIndex constants levels env (inj i (mkTower xs)) p))) + (hih : ih ∈ˢ piSet (shape.positions constants levels env (inj i (mkTower xs))) + (fun p => shape.motive m (shape.targetIndex constants levels env (inj i (mkTower xs)) p) (app g p))) : + shape.IHValuesFit constants levels env v m ctor xs (shape.decodeFields constants levels env ctor xs g) + (shape.ihValues constants levels env v ctor xs ih) := by + apply Telescope.fits_simple_of_getD + · simp only [ihValues, ihTypes, List.length_map, List.length_zipIdx] + · intro j A hA + simp only [ihTypes, List.getElem?_map, List.getElem?_zipIdx] at hA + cases hf : ctor.recursive[j]? with + | none => simp [hf] at hA + | some field => + simp only [hf, Option.map_some, Nat.zero_add, Option.some.injEq] at hA + subst A + simp only [ihValues, List.getD_eq_getElem?_getD, List.getElem?_map, + List.getElem?_zipIdx, hf, Option.map_some, Nat.zero_add, Option.getD_some] + exact ihValue_mem h hM hΓ hc hf hx hg hih + +noncomputable def algebra (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (_m : V) (minors : List V) (_i a g ih : V) : V := + match shape.constructors[tag a]? with + | none => empty + | some ctor => + let xs := ordinaryValues ctor a + let fs := shape.decodeFields constants levels env ctor xs g + let hs := shape.ihValues constants levels env v ctor xs ih + Telescope.applyN (minors.getD (tag a) empty) (xs ++ fs ++ hs) + +theorem algebra_typing (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {minors : List V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + (hminors : shape.MinorValuesFit constants levels env v m minors) : + (shape.container constants levels env).AlgebraTyping (shape.level.eval levels) + (shape.motive m) (shape.algebra constants levels env v m minors) := by + intro i hi a ha g hg ih hih + obtain ⟨has, hresult⟩ := mem_sep.mp ha + obtain ⟨j, ctor, xs, hc, hx, rfl⟩ := mem_allShapes has + rw [resultIndex_inj constants levels env hc (FitsS.length_eq hx)] at hresult + have hctor := h.constructors ctor (List.mem_of_getElem? hc) + have hfs := decodeFields_fit hc (FitsS.length_eq hx) hg + have hhs := ihValues_fit (v := v) h hM hΓ hc hx hg hih + have hstep := minor_apply_mem h hM hΓ hm hc (hminors.get hc) hx hfs hhs + rw [constructorValue, branches_decodeFields hc hctor hM hΓ hx hg, hresult] at hstep + simpa only [algebra, tag_inj, hc, ordinaryValues_inj _ (FitsS.length_eq hx)] using hstep + +noncomputable def recursorSet (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) : V := + Telescope.piN v (Telescope.interpret constants levels env shape.indices) fun is => + piR v (app (shape.carrier constants levels env) (mkTower is)) (shape.motive m (mkTower is)) + +noncomputable def largeValue (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (v : Nat) (m : V) (minors : List V) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) : V := + Telescope.curry v (Telescope.interpret constants levels env shape.indices) fun is => + lamR v (app (shape.carrier constants levels env) (mkTower is)) fun x => + IndexedContainer.foldAt hD hlarge (shape.algebra constants levels env v m minors) (mkTower is) x + +theorem largeValue_mem (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {minors : List V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + (hminors : shape.MinorValuesFit constants levels env v m minors) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) : + shape.largeValue constants levels env v m minors hD hlarge ∈ˢ shape.recursorSet constants levels env v m := by + apply Telescope.curry_mem + intro is his + apply lamR_mem + intro x hx + exact IndexedContainer.foldAt_mem hD hlarge (algebra_typing h hM hΓ hm hminors) + (mkTower_mem (by decide : 1 ≠ 0) his) hx + +theorem largeValue_apply (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {v : Nat} {m : V} {minors : List V} (hm : m ∈ˢ shape.motiveSet constants levels env v) + (hminors : shape.MinorValuesFit constants levels env v m minors) + (hD : (shape.container constants levels env).WF (shape.level.eval levels)) + (hlarge : (shape.container constants levels env).LargeElim (shape.level.eval levels)) + {is : List V} (his : FitsS (Telescope.interpret constants levels env shape.indices) is) + {x : V} (hx : x ∈ˢ app (shape.carrier constants levels env) (mkTower is)) : + Telescope.applyN (shape.largeValue constants levels env v m minors hD hlarge) (is ++ [x]) = + IndexedContainer.foldAt hD hlarge (shape.algebra constants levels env v m minors) (mkTower is) x := by + have hi := mkTower_mem (by decide : 1 ≠ 0) his + have hleaf ys hys y hy := IndexedContainer.foldAt_mem hD hlarge (algebra_typing h hM hΓ hm hminors) + (mkTower_mem (by decide : 1 ≠ 0) hys) (i := mkTower ys) (x := y) hy + have hlam ys hys := lamR_mem (v := v) (hleaf ys hys) + rw [Telescope.applyN_append] + change app (Telescope.applyN (Telescope.curry v _ _) is) x = _ + simp only [carrier] + rw [Telescope.applyN_curry (w := v) _ his hlam (fun hv ys hys => by + subst v + exact piR_zero_mem_univZero)] + exact app_lamR hx (hleaf is his) (fun hv y hy => by + simpa only [hv, univ_zero] using motive_mem hm hi hy) + +/-- Small elimination constructs the proof point by structural induction. +It applies equally to empty, singleton, and many-constructor Prop families. -/ +theorem pt_mem_smallRecursorSet (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) (hΓ : shape.parameterContext.Valid constants levels env) + {m : V} {minors : List V} (hm : m ∈ˢ shape.motiveSet constants levels env 0) + (hminors : shape.MinorValuesFit constants levels env 0 m minors) : + (pt : V) ∈ˢ shape.recursorSet constants levels env 0 m := by + have helim := IndexedContainer.small_elim (container_wf h hM hΓ) + (fun i hi x hx => by simpa only [univ_zero] using motive_mem hm hi hx) + (algebra_typing h hM hΓ hm hminors) + have hvalue := Telescope.curry_mem (w := 0) + (Telescope.interpret constants levels env shape.indices) + (R := fun is => piR 0 (app (shape.carrier constants levels env) (mkTower is)) + (shape.motive m (mkTower is))) + (f := fun _ => (pt : V)) (fun is his => + pt_mem_piR_zero_of (fun x hx => helim (mkTower is) (mkTower_mem (by decide : 1 ≠ 0) his) x hx)) + rwa [Telescope.curry_point] at hvalue + +end Ix.Theory.Certified.Ordinary.Shape diff --git a/Ix/Theory/Certified/Ordinary/Family.lean b/Ix/Theory/Certified/Ordinary/Family.lean new file mode 100644 index 000000000..2af5d8999 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Family.lean @@ -0,0 +1,139 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Computation +import Ix.Theory.Model.Extension + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +theorem eval_params {n : Nat} {levels : List Nat} (h : levels.length = n) : + (VLevel.params n).map (VLevel.eval levels) = levels := by + apply List.ext_getElem (by simp [h]) + intro i hi hi' + simp only [VLevel.params, List.getElem_map, List.getElem_range, VLevel.eval, + List.getD_eq_getElem?_getD, List.getElem?_eq_getElem hi', Option.getD_some] + +theorem interp_parameterVars_skip (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (offset count : Nat) : + (parameterVars offset count).map (interp constants levels env) = + (parameterVars 0 count).map (interp constants levels (Valuation.skip offset 0 env)) := by + induction count <;> simp_all [parameterVars, interp, Valuation.skip] + +theorem interp_parameterVars_extend (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (xs : List V) : + (parameterVars 0 xs.length).map (interp constants levels (Telescope.extend env xs)) = xs := by + induction xs generalizing env with + | nil => rfl + | cons x xs ih => + simp only [List.length_cons, parameterVars, Nat.zero_add, List.map_cons, interp, + Telescope.extend, ih] + have he := Telescope.extend_beyond (Valuation.cons x env) xs 0 + simpa only [Nat.add_zero, Valuation.cons_zero] using congrArg (· :: xs) he + +theorem interp_parameterVars_middle (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (xs tail : List V) : + (parameterVars tail.length xs.length).map + (interp constants levels (Telescope.extend (Telescope.extend env xs) tail)) = xs := by + rw [interp_parameterVars_skip, Telescope.skip_extend, interp_parameterVars_extend] + +namespace Shape + +noncomputable def familyValue (shape : Shape β) (constants : Assignment β V) (levels : List Nat) : V := + Telescope.curry 1 (Telescope.interpret constants levels (fun _ => empty) shape.parameters) fun ps => + Telescope.curry 1 (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) shape.indices) + (fun is => app (shape.carrier constants levels (Telescope.extend (fun _ => empty) ps)) (mkTower is)) + +theorem type_typing {entries : Environment β} {store : Store β} {source : β} {shape : Shape β} + (h : CheckedShape.{u,v} entries store source shape) : + ∃ l, TypingClaim.{u,v} entries [] shape.type (.sort l) := by + obtain ⟨l, _, hl⟩ := (h.parameters.append h.indices).forallN (TypingClaim.sort shape.level) + exact ⟨l, hl⟩ + +theorem type_references {entries : Environment β} {store : Store β} {source : β} {shape : Shape β} + (h : CheckedShape.{u,v} entries store source shape) : shape.type.ReferencesIn entries := + AExpr.ReferencesIn.forallN h.references (by simp [AExpr.ReferencesIn, AExpr.references]) + +theorem familyValue_mem (shape : Shape β) (constants : Assignment β V) (levels : List Nat) : + shape.familyValue constants levels ∈ˢ interp constants levels (fun _ => empty) shape.type := by + simp only [type, AExpr.forallN_append, AExpr.interp_forallN, regime_never, interp] + apply Telescope.curry_mem + intro ps hps + apply Telescope.curry_mem + intro is his + exact (shape.container constants levels (Telescope.extend (fun _ => empty) ps)).carrier_fibre_mem + (shape.level.eval levels) (mkTower_mem (by decide : 1 ≠ 0) his) + +theorem familyValue_apply (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + {ps is : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (his : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) shape.indices) is) : + Telescope.applyN (shape.familyValue constants levels) (ps ++ is) = + app (shape.carrier constants levels (Telescope.extend (fun _ => empty) ps)) (mkTower is) := by + have hresult xs ys hys := + (shape.container constants levels (Telescope.extend (fun _ => empty) xs)).carrier_fibre_mem + (shape.level.eval levels) (i := mkTower ys) (mkTower_mem (by decide : 1 ≠ 0) hys) + have hinner xs := Telescope.curry_mem (w := 1) + (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) xs) shape.indices) (hresult xs) + simp only [familyValue, carrier] + rw [Telescope.applyN_append, + Telescope.applyN_curry (w := 1) _ hps (fun xs _ => hinner xs) (fun h => (by omega : False).elim)] + exact Telescope.applyN_curry _ his (hresult ps) (fun h => (by omega : False).elim) + +def familyEntry (shape : Shape β) : ConstantEntry β := ⟨shape.universes, shape.type, none, [], []⟩ + +def familyEnvironment [DecidableEq β] (shape : Shape β) (entries : Environment β) (source : β) : Environment β := + entries.insert (.member source 0) shape.familyEntry + +noncomputable def familyAssignment [DecidableEq β] (shape : Shape β) (constants : Assignment β V) + (source : β) : Assignment β V := constants.insert (.member source 0) (shape.familyValue constants) + +theorem familyEnvironment_wf [DecidableEq β] {entries : Environment β} {store : Store β} {source : β} + {shape : Shape β} (h : CheckedShape.{u,v} entries store source shape) (hE : entries.WF) : + (shape.familyEnvironment entries source).WF := + hE.insert h.scope (by simp [familyEntry]) (type_references h) (by simp [familyEntry]) + (by simp [familyEntry]) (by simp [familyEntry]) + (by simp [familyEntry]) (by simp [familyEntry]) + +theorem familyAssignment_agrees [DecidableEq β] {entries : Environment β} {store : Store β} {source : β} + {shape : Shape β} (h : CheckedShape.{u,v} entries store source shape) (constants : Assignment β V) : + Assignment.AgreesOn entries constants (shape.familyAssignment constants source) := + Assignment.insert_agrees (h.fresh _ (List.mem_cons_self ..)) constants (shape.familyValue constants) + +/-- The family signature receives its constructed carrier before constructor +or recursor checking. This is an internal stage with no reduction equations. -/ +theorem familyAssignment_realizes [DecidableEq β] {entries : Environment β} {store : Store β} {source : β} + {shape : Shape β} (h : CheckedShape.{u,v} entries store source shape) (hE : entries.WF) + (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (shape.familyAssignment constants source) (shape.familyEnvironment entries source) := by + have hagree := familyAssignment_agrees h constants + have hrefs := type_references h + obtain ⟨l, htype⟩ := type_typing h + apply (hM.of_agrees hE hagree).insert + constructor + · intro levels hn env + exact (hagree.wellDenoted hrefs levels env).mpr + (htype V constants hM levels env (Context.valid_nil constants levels env)).1 + · intro levels hn env + change shape.familyAssignment constants source (.member source 0) levels ∈ˢ + interp (shape.familyAssignment constants source) levels env shape.type + rw [hagree.interp hrefs levels env, familyAssignment, Assignment.insert_same] + have hm := shape.familyValue_mem constants levels + rwa [interp_closed shape.type constants levels h.scope (fun _ => empty) env] at hm + · intro body hb + cases hb + · intro body hb + cases hb + · intro law hl + simp only [familyEntry, List.not_mem_nil] at hl + · intro fact hf + simp only [familyEntry, List.not_mem_nil] at hf + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/LargeElim.lean b/Ix/Theory/Certified/Ordinary/LargeElim.lean new file mode 100644 index 000000000..976aa0736 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/LargeElim.lean @@ -0,0 +1,65 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Constructors +import Ix.Theory.Model.Inductive.Recursor + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower + +universe u v +variable {β : Type u} + +def LargeEvidence (entries : Environment β) (shape : Shape β) : Prop := + (∀ levels, shape.level.eval levels ≠ 0) ∨ shape.constructors = [] ∨ + ∃ ctor, shape.constructors = [ctor] ∧ + TelescopeProp.{u,v} entries shape.parameterContext ctor.fields shape.level + +def checkLarge [DecidableEq β] (fuel : Nat) (entries : Environment β) (witness : ShapeWitness β) : + Option (CheckedClaim.{u} (LargeEvidence.{u,v} entries witness.shape)) := + if hp : zeroCondition witness.shape.level = .never then + some ⟨Or.inl (by + intro levels he + have hz := zeroCondition_correct witness.shape.level levels + simp only [hp, PropWhen.holds_never, he, beq_self_eq_true, Bool.false_eq_true] at hz)⟩ + else + match hc : witness.shape.constructors, witness.constructors with + | [], [] => some ⟨Or.inr (Or.inl hc)⟩ + | [ctor], [proof] => do + let fields ← verifyPropTelescope.{u,v} fuel witness.shape.universes entries witness.shape.level + witness.shape.parameterContext ctor.fields proof.fields + return ⟨Or.inr (Or.inr ⟨ctor, hc, fields.down⟩)⟩ + | _, _ => none + +theorem checkLarge_sound [DecidableEq β] {fuel : Nat} {entries : Environment β} {witness : ShapeWitness β} + {result} (_ : checkLarge.{u,v} fuel entries witness = some result) : + LargeEvidence.{u,v} entries witness.shape := result.down + +variable {V : Type v} [SetTheory V] + +theorem Shape.container_large {entries : Environment β} {shape : Shape β} + (hlarge : LargeEvidence.{u,v} entries shape) {constants : Assignment β V} + (hM : Realizes constants entries) {levels : List Nat} {env : Nat → V} + (hΓ : shape.parameterContext.Valid constants levels env) : + (shape.container constants levels env).LargeElim (shape.level.eval levels) := by + intro hw i hi a b ha hb + rcases hlarge with hpos | hempty | ⟨ctor, hsingle, hprop⟩ + · exact (hpos levels hw).elim + · obtain ⟨j, ctor, xs, hc, _, _⟩ := Shape.mem_allShapes (mem_sep.mp ha).1 + simp only [hempty, List.getElem?_nil] at hc + contradiction + · obtain ⟨j, ca, xs, hca, hxs, rfl⟩ := Shape.mem_allShapes (mem_sep.mp ha).1 + obtain ⟨k, cb, ys, hcb, hys, rfl⟩ := Shape.mem_allShapes (mem_sep.mp hb).1 + have hj : j = 0 := by cases j <;> simp_all + have hk : k = 0 := by cases k <;> simp_all + subst j k + have heca : ctor = ca := by simpa only [hsingle, List.getElem?_cons_zero, Option.some.injEq] using hca + have hecb : ctor = cb := by simpa only [hsingle, List.getElem?_cons_zero, Option.some.injEq] using hcb + subst ca cb + have he := Telescope.fits_unique_of_prop (hprop V constants hM levels env hΓ hw) hxs hys + rw [he] + +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/Reading.lean b/Ix/Theory/Certified/Ordinary/Reading.lean new file mode 100644 index 000000000..86a5cb955 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Reading.lean @@ -0,0 +1,309 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Family + +namespace Ix.Theory.Model + +open SetTheory SetTheory.Tower + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +theorem Assignment.AgreesOn.telescope {entries : Environment β} {constants constants' : Assignment β V} + (h : Assignment.AgreesOn entries constants constants') {domains : List (AExpr β)} + (hrefs : ∀ A ∈ domains, A.ReferencesIn entries) (levels : List Nat) (env : Nat → V) : + Telescope.interpret constants' levels env domains = Telescope.interpret constants levels env domains := by + induction domains generalizing env with + | nil => rfl + | cons A rest ih => + simp only [Telescope.interpret, h.interp (hrefs A (List.mem_cons_self ..))] + congr 1 + funext x + exact ih (fun D hd => hrefs D (List.mem_cons_of_mem A hd)) _ + +end Ix.Theory.Model + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +/-- Interface preserved while signatures are staged. The initial producer +installs the constructed family; subsequent fresh members preserve it. -/ +structure FamilyReading (entries : Environment β) (shape : Shape β) (source : β) + (constants reading : Assignment β V) : Prop where + agrees : Assignment.AgreesOn entries constants reading + family : ∀ levels, levels.length = shape.universes → + reading (.member source 0) levels = shape.familyValue constants levels + +theorem Shape.familyAssignment_reading [DecidableEq β] {entries : Environment β} {store : Store β} + {source : β} {shape : Shape β} (h : CheckedShape.{u,v} entries store source shape) + (constants : Assignment β V) : + FamilyReading entries shape source constants (shape.familyAssignment constants source) := + ⟨Shape.familyAssignment_agrees h constants, fun _ _ => Assignment.insert_same ..⟩ + +namespace Shape + +variable {entries : Environment β} {shape : Shape β} {source : β} + {constants reading : Assignment β V} {levels : List Nat} + +theorem familyApp_interp (h : FamilyReading entries shape source constants reading) + (hn : levels.length = shape.universes) {ps extra : List V} {indices : List (AExpr β)} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (his : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) shape.indices) + (indices.map (interp reading levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) extra)))) : + interp reading levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) extra) + (shape.familyApp source extra.length indices) = + app (shape.carrier constants levels (Telescope.extend (fun _ => empty) ps)) + (mkTower (indices.map (interp reading levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) extra)))) := by + have hp : (parameterVars extra.length shape.parameters.length).map + (interp reading levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) extra)) = ps := by + rw [interp_parameterVars_skip, Telescope.skip_extend, ← FitsS.length_eq hps, + interp_parameterVars_extend] + rw [familyApp, AExpr.interp_appN] + simp only [interp, eval_params hn, h.family levels hn, List.map_append, hp] + exact familyValue_apply shape constants levels hps his + +theorem recursiveType_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = shape.universes) {ctor : Constructor β} {field : RecursiveField β} + (hc : ctor ∈ shape.constructors) (hf : field ∈ ctor.recursive) {ps xs previous : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) : + interp reading levels (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) previous) + ((field.type shape source ctor.fields.length).liftN previous.length) = + shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs field := by + have hctor := h.constructors ctor hc + have hfield := hctor.2.2.2.2 field hf + have hΓ := h.parameters.valid constants hM levels (Context.valid_nil constants levels (fun _ => empty)) hps + rw [interp_liftN, Telescope.skip_extend, RecursiveField.type, AExpr.interp_forallN, + hr.agrees.telescope (fun A ha => hfield.1 A (List.mem_append_left _ ha))] + apply Telescope.piN_zero_agree (regime_zeroCondition shape.level levels) + intro ys hys + have he : field.indices.map (interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) ys)) = + field.indices.map (interp constants levels + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) ys)) := + List.map_congr_left fun e he => hr.agrees.interp (hfield.1 e (List.mem_append_right _ he)) levels _ + have hit := recursiveTarget_fits hctor hfield hM hΓ hxs hys + have hit' : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) shape.indices) + (field.indices.map (interp reading levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) (xs ++ ys)))) := by + simpa only [Telescope.extend_append, he] using hit + have happ := familyApp_interp hr hn hps hit' + simpa only [List.length_append, FitsS.length_eq hxs, FitsS.length_eq hys, + Telescope.extend_append, he] using happ + +theorem recursiveForall_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {fields : List (RecursiveField β)} (hf : ∀ field ∈ fields, field ∈ ctor.recursive) {ps xs : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (previous : List V) (B : AExpr β) : + interp reading levels (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) previous) + (.forallN (zeroCondition shape.level) + (recursiveTypesFrom shape source ctor.fields.length fields previous.length) B) = + Telescope.piN (shape.level.eval levels) + (Telescope.simple (fields.map (shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs))) + (fun fs => interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) previous) fs) B) := by + induction fields generalizing previous with + | nil => rfl + | cons field fields ih => + simp only [recursiveTypesFrom, List.zipIdx_cons, List.map_cons, AExpr.forallN, interp] + rw [recursiveType_interp h hr hM hn hc (hf field (List.mem_cons_self ..)) hps hxs] + apply piR_zero_agree (regime_zeroCondition shape.level levels) + intro x _ + have htail := ih (fun f hm => hf f (List.mem_cons_of_mem field hm)) (previous ++ [x]) + simpa only [recursiveTypesFrom, List.length_append, List.length_singleton, + Telescope.extend_append, Telescope.extend] using htail + +theorem piN_recursiveTypes {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {fields : List (RecursiveField β)} (hf : ∀ field ∈ fields, field ∈ ctor.recursive) {ps xs : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (previous : List V) (w : Nat) (R : List V → V) : + Telescope.piN w (Telescope.interpret reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) previous) + (recursiveTypesFrom shape source ctor.fields.length fields previous.length)) R = + Telescope.piN w + (Telescope.simple (fields.map (shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs))) R := by + induction fields generalizing previous R with + | nil => rfl + | cons field fields ih => + change piR w (interp reading levels _ ((field.type shape source ctor.fields.length).liftN previous.length)) _ = + piR w (shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs field) _ + rw [recursiveType_interp h hr hM hn hc (hf field (List.mem_cons_self ..)) hps hxs] + congr 1 + funext f + have ht := ih (fun f hf' => hf f (List.mem_cons_of_mem field hf')) (previous ++ [f]) (fun fs => R (f :: fs)) + have hlen : (previous ++ [f]).length = previous.length + 1 := by simp + rw [hlen] at ht + simpa only [recursiveTypesFrom, List.length_append, List.length_singleton, + Telescope.extend_append, Telescope.extend] using ht + +theorem curry_recursiveTypes {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {fields : List (RecursiveField β)} (hf : ∀ field ∈ fields, field ∈ ctor.recursive) {ps xs : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (previous : List V) (w : Nat) (f : List V → V) : + Telescope.curry w (Telescope.interpret reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) previous) + (recursiveTypesFrom shape source ctor.fields.length fields previous.length)) f = + Telescope.curry w + (Telescope.simple (fields.map (shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs))) f := by + induction fields generalizing previous f with + | nil => rfl + | cons field fields ih => + change lamR w (interp reading levels _ ((field.type shape source ctor.fields.length).liftN previous.length)) _ = + lamR w (shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs field) _ + rw [recursiveType_interp h hr hM hn hc (hf field (List.mem_cons_self ..)) hps hxs] + congr 1 + funext x + have ht := ih (fun f hf' => hf f (List.mem_cons_of_mem field hf')) (previous ++ [x]) (fun xs => f (x :: xs)) + have hlen : (previous ++ [x]).length = previous.length + 1 := by simp + rw [hlen] at ht + simpa only [recursiveTypesFrom, List.length_append, List.length_singleton, + Telescope.extend_append, Telescope.extend] using ht + +theorem constructorResult_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {ps xs fs : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hlen : fs.length = ctor.recursive.length) : + interp reading levels (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) fs) + (shape.familyApp source (ctor.fields.length + ctor.recursive.length) + (ctor.indices.map (AExpr.liftN ctor.recursive.length ·))) = + app (shape.carrier constants levels (Telescope.extend (fun _ => empty) ps)) + (mkTower (ctor.indices.map (interp constants levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs)))) := by + have hctor := h.constructors ctor hc + have hΓ := h.parameters.valid constants hM levels (Context.valid_nil constants levels (fun _ => empty)) hps + have he : (ctor.indices.map (AExpr.liftN ctor.recursive.length ·)).map + (interp reading levels (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) fs)) = + ctor.indices.map (interp constants levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs)) := by + rw [List.map_map] + apply List.map_congr_left + intro e he + simp only [Function.comp_def, interp_liftN, ← hlen, Telescope.skip_extend, + hr.agrees.interp (hctor.1 e (List.mem_append_right _ he))] + have hit := constructorResult_fits hctor hM hΓ hxs + have hit' : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) shape.indices) + ((ctor.indices.map (AExpr.liftN ctor.recursive.length ·)).map + (interp reading levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) (xs ++ fs)))) := by + simpa only [Telescope.extend_append, he] using hit + have happ := familyApp_interp hr hn hps hit' + simpa only [List.length_append, FitsS.length_eq hxs, hlen, Telescope.extend_append, he] using happ + +noncomputable def constructorSet (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (ctor : Constructor β) : V := + Telescope.piN (shape.level.eval levels) + (Telescope.interpret constants levels (fun _ => empty) shape.parameters) fun ps => + Telescope.piN (shape.level.eval levels) + (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) fun xs => + Telescope.piN (shape.level.eval levels) + (Telescope.simple (ctor.recursive.map (shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs))) + (fun _ => app (shape.carrier constants levels (Telescope.extend (fun _ => empty) ps)) + (mkTower (ctor.indices.map (interp constants levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs))))) + +theorem constructorType_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) : + interp reading levels (fun _ => empty) (ctor.type shape source) = shape.constructorSet constants levels ctor := by + have hctor := h.constructors ctor hc + rw [Constructor.type, AExpr.interp_forallN, + hr.agrees.telescope (fun A hA => h.references A (List.mem_append_left _ hA))] + apply Telescope.piN_zero_agree (regime_zeroCondition shape.level levels) + intro ps hps + rw [AExpr.interp_forallN, + hr.agrees.telescope (fun A hA => hctor.1 A (List.mem_append_left _ hA))] + apply Telescope.piN_zero_agree (regime_zeroCondition shape.level levels) + intro xs hxs + rw [Constructor.recursiveTypes] + have ht := recursiveForall_interp h hr hM hn hc (fun _ h => h) hps hxs [] + (shape.familyApp source (ctor.fields.length + ctor.recursive.length) + (ctor.indices.map (AExpr.liftN ctor.recursive.length ·))) + simp only [Telescope.extend, List.length_nil] at ht + rw [ht] + apply Telescope.piN_congr + intro fs hfs + exact constructorResult_interp h hr hM hn hc hps hxs (by simpa using FitsS.length_eq hfs) + +noncomputable def constructorClosedValue (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (i : Nat) (ctor : Constructor β) : V := + Telescope.curry (shape.level.eval levels) + (Telescope.interpret constants levels (fun _ => empty) shape.parameters) fun ps => + Telescope.curry (shape.level.eval levels) + (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) fun xs => + Telescope.curry (shape.level.eval levels) + (Telescope.simple (ctor.recursive.map (shape.recursiveSet constants levels (Telescope.extend (fun _ => empty) ps) xs))) + (fun fs => shape.constructorValue constants levels (Telescope.extend (fun _ => empty) ps) ctor i xs fs) + +theorem constructorClosedValue_mem {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) {i : Nat} {ctor : Constructor β} (hc : shape.constructors[i]? = some ctor) : + shape.constructorClosedValue constants levels i ctor ∈ˢ shape.constructorSet constants levels ctor := by + apply Telescope.curry_mem + intro ps hps + apply Telescope.curry_mem + intro xs hxs + apply Telescope.curry_mem + intro fs hfs + have hΓ := h.parameters.valid constants hM levels (Context.valid_nil constants levels (fun _ => empty)) hps + exact constructorValue_mem h hM hΓ hc hxs hfs + +theorem constructorClosedValue_mem_source {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) : + shape.constructorClosedValue constants levels i ctor ∈ˢ interp reading levels (fun _ => empty) (ctor.type shape source) := by + rw [constructorType_interp h hr hM hn (List.mem_of_getElem? hc)] + exact constructorClosedValue_mem h hM hc + +theorem constructorClosedValue_apply {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hM : Realizes constants entries) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {ps xs fs : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants levels (Telescope.extend (fun _ => empty) ps) ctor xs fs) : + Telescope.applyN (shape.constructorClosedValue constants levels i ctor) (ps ++ xs ++ fs) = + shape.constructorValue constants levels (Telescope.extend (fun _ => empty) ps) ctor i xs fs := by + have hresult (ps : List V) hps xs hxs fs hfs := constructorValue_mem h hM + (h.parameters.valid constants hM levels (xs := ps) (Context.valid_nil constants levels (fun _ => empty)) hps) + hc (xs := xs) hxs (fs := fs) hfs + have hbound (ps : List V) hps xs hxs : + app (shape.carrier constants levels (Telescope.extend (fun _ => empty) ps)) + (mkTower (ctor.indices.map (interp constants levels (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs)))) + ∈ˢ (univ (shape.level.eval levels) : V) := + (shape.container constants levels (Telescope.extend (fun _ => empty) ps)).carrier_fibre_mem _ + (constructorResult_mem (h.constructors ctor (List.mem_of_getElem? hc)) hM + (h.parameters.valid constants hM levels (xs := ps) (Context.valid_nil constants levels (fun _ => empty)) hps) hxs) + have hrec ps hps xs hxs := Telescope.curry_mem (w := shape.level.eval levels) _ (hresult ps hps xs hxs) + have hfields ps hps := Telescope.curry_mem (w := shape.level.eval levels) _ (hrec ps hps) + rw [constructorClosedValue, Telescope.applyN_append, Telescope.applyN_append, + Telescope.applyN_curry _ hps hfields (fun hw ps hps => by + rw [hw] + apply Telescope.piN_zero_mem + intro xs hxs + apply Telescope.piN_zero_mem + intro _ _ + simpa only [hw, univ_zero] using hbound ps hps xs hxs), + Telescope.applyN_curry _ hxs (hrec ps hps) (fun hw xs hxs => by + rw [hw] + apply Telescope.piN_zero_mem + intro _ _ + simpa only [hw, univ_zero] using hbound ps hps xs hxs)] + exact Telescope.applyN_curry _ hfs (hresult ps hps xs hxs) + (fun hw _ _ => by simpa only [hw, univ_zero] using hbound ps hps xs hxs) + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/RecursorReading.lean b/Ix/Theory/Certified/Ordinary/RecursorReading.lean new file mode 100644 index 000000000..65ba51332 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/RecursorReading.lean @@ -0,0 +1,415 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.RecursorSyntax + +namespace Ix.Theory.Inductive.ElimMode + +theorem sourceLevels_eval (mode : ElimMode) {levels : List Nat} {sourceUvars : Nat} + (h : levels.length = mode.recUvars sourceUvars) : + (mode.sourceLevels sourceUvars).map (VLevel.eval levels) = mode.sourceArgs levels := by + apply List.ext_get (by simp [sourceLevels, sourceArgs_length mode h]) + intro i hi _ + have hi' : i < sourceUvars := by simpa [sourceLevels] using hi + have bound : i + mode.offset < levels.length := by rw [h, recUvars]; omega + simp [sourceLevels, VLevel.params', VLevel.eval, sourceArgs, + List.getD_eq_getElem?_getD, List.getElem?_eq_getElem bound, Nat.add_comm] + +end Ix.Theory.Inductive.ElimMode + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Inductive + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +structure ConstructorReading (entries : Environment β) (shape : Shape β) (source : β) + (constants reading : Assignment β V) : Prop extends FamilyReading entries shape source constants reading where + constructor : ∀ levels, levels.length = shape.universes → ∀ i ctor, + shape.constructors[i]? = some ctor → + reading (.ctor source 0 i) levels = shape.constructorClosedValue constants levels i ctor + +namespace Shape + +variable {entries : Environment β} {shape : Shape β} {source : β} + {constants reading : Assignment β V} {levels : List Nat} {mode : ElimMode} + +theorem motiveType_interp (hr : FamilyReading entries shape source constants reading) + (hn : levels.length = mode.recUvars shape.universes) {ps : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hrefs : ∀ A ∈ shape.indices, A.ReferencesIn entries) : + interp reading levels (Telescope.extend (fun _ => empty) ps) (shape.motiveType source mode) = + shape.motiveSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) := by + rw [motiveType, AExpr.interp_forallN, Telescope.piN_instL, mode.sourceLevels_eval hn, + hr.agrees.telescope hrefs] + apply Telescope.piN_congr + intro is his + have hvars := interp_parameterVars_extend reading (mode.sourceArgs levels) + (Telescope.extend (fun _ => empty) ps) is + rw [FitsS.length_eq his] at hvars + have hit : FitsS (Telescope.interpret constants (mode.sourceArgs levels) + (Telescope.extend (fun _ => empty) ps) shape.indices) + ((parameterVars 0 shape.indices.length).map + (interp reading (mode.sourceArgs levels) + (Telescope.extend (Telescope.extend (fun _ => empty) ps) is))) := by + simpa only [hvars] using his + have happ := familyApp_interp hr (mode.sourceArgs_length hn) hps hit + simp only [interp, regime_never, interp_instL, mode.sourceLevels_eval hn, + FitsS.length_eq his, hvars] at happ ⊢ + rw [happ] + +theorem minorFields_piN {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {ps : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (m : V) (w : Nat) (R : List V → V) : + Telescope.piN w (Telescope.interpret reading levels + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (shape.minorFields source mode ctor)) R = + Telescope.piN w + (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) + (fun xs => Telescope.piN w + (Telescope.simple (ctor.recursive.map + (shape.recursiveSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) xs))) + (fun fs => R (xs ++ fs))) := by + rw [minorFields, Telescope.piN_lift, Valuation.skip_succ_cons, Valuation.skip_zero, + Telescope.piN_instL, mode.sourceLevels_eval hn, Telescope.piN_append, + hr.agrees.telescope (fun A ha => (h.constructors ctor hc).1 A (List.mem_append_left _ ha))] + apply Telescope.piN_congr + intro xs hxs + have ht := piN_recursiveTypes h hr hM (mode.sourceArgs_length hn) hc (fun _ h => h) hps hxs [] w + (fun fs => R (xs ++ fs)) + simpa only [Constructor.recursiveTypes, List.length_nil, Telescope.extend] using ht + +theorem ihType_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {j : Nat} {field : RecursiveField β} (hf : ctor.recursive[j]? = some field) + {ps xs fs : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : fs.length = ctor.recursive.length) (m : V) : + interp reading levels + (Telescope.extend (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) + (shape.ihType mode ctor j field) = + shape.ihSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m xs fs j field := by + have hctor := h.constructors ctor hc + have hfield := hctor.2.2.2.2 field (List.mem_of_getElem? hf) + have hΓ := h.parameters.valid constants hM (mode.sourceArgs levels) + (Context.valid_nil constants (mode.sourceArgs levels) (fun _ => empty)) hps + have hxlen := FitsS.length_eq hxs + have hskip : Valuation.skip 1 ctor.fields.length + (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) = + Telescope.extend (Telescope.extend (fun _ => empty) ps) xs := by + simpa only [List.length_singleton, Telescope.extend, hxlen] using + Telescope.skip_middle (Telescope.extend (fun _ => empty) ps) [m] xs + rw [ihType, AExpr.interp_forallN, Telescope.piN_lift, ← hfs, Telescope.skip_extend, + Telescope.piN_lift, hskip, Telescope.piN_instL, mode.sourceLevels_eval hn, + hr.agrees.telescope (fun A ha => hfield.1 A (List.mem_append_left _ ha))] + apply Telescope.piN_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro ys hys + have hylen := FitsS.length_eq hys + have hit := recursiveTarget_fits hctor hfield hM hΓ hxs hys + have hidx : field.indices.map (fun e => interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) ys) + (((e.instL (mode.sourceLevels shape.universes)).liftN 1 + (ctor.fields.length + field.domains.length)).liftN ctor.recursive.length field.domains.length)) = + field.indices.map (interp constants (mode.sourceArgs levels) + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) ys)) := by + apply List.map_congr_left + intro e he + rw [interp_liftN, ← hfs, ← hylen, Telescope.skip_middle, interp_liftN] + rw [show ctor.fields.length + ys.length = ys.length + ctor.fields.length by omega, + Telescope.skip_extend_at, hskip, interp_instL, mode.sourceLevels_eval hn, + hr.agrees.interp (hfield.1 e (List.mem_append_right _ he))] + have hmvar : Telescope.extend (Telescope.extend (Telescope.extend + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) ys + (ctor.fields.length + ctor.recursive.length + field.domains.length) = m := by + rw [← hxlen, ← hfs, ← hylen] + have ht := Telescope.extend_beyond (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (xs ++ fs ++ ys) 0 + simpa only [List.length_append, Nat.add_zero, Telescope.extend_append, Valuation.cons_zero] using ht + have hfvar : Telescope.extend (Telescope.extend (Telescope.extend + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) ys + (ctor.recursive.length - 1 - j + field.domains.length) = fs.getD j empty := by + rw [← hfs, ← hylen, Nat.add_comm, Telescope.extend_beyond, + Telescope.extend_getD _ _ j (by + rw [hfs] + exact (List.getElem?_eq_some_iff.mp hf).1)] + have hvars := interp_parameterVars_extend reading levels + (Telescope.extend (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) ys + rw [hylen] at hvars + simp only [hfs, AExpr.interp_appN, interp, List.map_append, List.map_map, Function.comp_def, + List.map_cons, List.map_nil, Telescope.applyN_append, Telescope.applyN, hmvar, hfvar, hvars, hidx] + rw [motive, projList_mkTower _ _ (FitsS.length_eq hit)] + +theorem ihTypes_piN {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {ps xs fs : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : fs.length = ctor.recursive.length) (m : V) (w : Nat) (R : List V → V) : + Telescope.piN w (Telescope.interpret reading levels + (Telescope.extend (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) + (shape.ihTypesSyntax mode ctor)) R = + Telescope.piN w (Telescope.simple (shape.ihTypes constants (mode.sourceArgs levels) + (Telescope.extend (fun _ => empty) ps) (mode.motiveLevel.eval levels) m ctor xs fs)) R := by + have ht := Telescope.piN_independent reading levels + (Telescope.extend (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) + (ctor.recursive.zipIdx.map fun (field, j) => shape.ihType mode ctor j field) [] w R + simp only [List.length_nil, Telescope.extend] at ht + rw [ihTypesSyntax, ht] + have he : ((ctor.recursive.zipIdx.map fun (field, j) => shape.ihType mode ctor j field).map + (interp reading levels (Telescope.extend + (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs))) = + shape.ihTypes constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m ctor xs fs := by + apply List.ext_getElem? + intro j + simp only [ihTypes, List.getElem?_map, List.getElem?_zipIdx] + cases hf : ctor.recursive[j]? with + | none => rfl + | some field => + simp only [Option.map_some, Nat.zero_add] + exact congrArg some (ihType_interp h hr hM hn hc hf hps hxs hfs m) + rw [he] + +theorem constructorVars_interp (hr : ConstructorReading entries shape source constants reading) + (hn : levels.length = mode.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) (ps extra fields tail : List V) + (hps : ps.length = shape.parameters.length) : + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) extra) fields) tail) + (.appN (.const (.ctor source 0 i) (mode.sourceLevels shape.universes)) + (parameterVars (extra.length + fields.length + tail.length) shape.parameters.length ++ + parameterVars tail.length fields.length)) = + Telescope.applyN (shape.constructorClosedValue constants (mode.sourceArgs levels) i ctor) (ps ++ fields) := by + have hp := interp_parameterVars_middle reading levels (fun _ => empty) ps (extra ++ fields ++ tail) + simp only [List.length_append, hps, Telescope.extend_append] at hp + have hf := interp_parameterVars_middle reading levels + (Telescope.extend (Telescope.extend (fun _ => empty) ps) extra) fields tail + simp only [AExpr.interp_appN, interp, mode.sourceLevels_eval hn, + hr.constructor _ (mode.sourceArgs_length hn) i ctor hc, List.map_append, hp, hf] + +theorem minorResult_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : ConstructorReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {ps xs fs hs : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor xs fs) + (hhs : hs.length = ctor.recursive.length) (m : V) : + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) hs) + (shape.minorResult source mode i ctor) = + shape.motive m + (mkTower (ctor.indices.map (interp constants (mode.sourceArgs levels) + (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs)))) + (shape.constructorValue constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor i xs fs) := by + have hxlen := FitsS.length_eq hxs + have hflen : fs.length = ctor.recursive.length := by simpa using FitsS.length_eq hfs + have hctor := h.constructors ctor (List.mem_of_getElem? hc) + have hΓ := h.parameters.valid constants hM (mode.sourceArgs levels) + (Context.valid_nil constants (mode.sourceArgs levels) (fun _ => empty)) hps + have hit := constructorResult_fits hctor hM hΓ hxs + have hcv := constructorVars_interp hr hn hc ps [m] (xs ++ fs) hs (FitsS.length_eq hps) + rw [← List.append_assoc, constructorClosedValue_apply h hM hc hps hxs hfs] at hcv + simp only [List.length_singleton, List.length_append, hxlen, hflen, hhs, + Telescope.extend_append, Telescope.extend, Nat.add_assoc] at hcv + have hidx : ctor.indices.map (fun e => interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) hs) + (((e.instL (mode.sourceLevels shape.universes)).liftN 1 ctor.fields.length).liftN + (ctor.recursive.length + ctor.recursive.length))) = + ctor.indices.map (interp constants (mode.sourceArgs levels) + (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs)) := by + apply List.map_congr_left + intro e he + rw [interp_liftN, show ctor.recursive.length + ctor.recursive.length = (fs ++ hs).length by simp [hflen, hhs], + ← Telescope.extend_append, Telescope.skip_extend, interp_liftN, ← hxlen] + have ht := Telescope.skip_middle (Telescope.extend (fun _ => empty) ps) [m] xs + simp only [List.length_singleton, Telescope.extend] at ht + rw [ht, interp_instL, mode.sourceLevels_eval hn, + hr.agrees.interp (hctor.1 e (List.mem_append_right _ he))] + have hmvar : Telescope.extend (Telescope.extend (Telescope.extend + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) xs) fs) hs + (ctor.fields.length + ctor.recursive.length + ctor.recursive.length) = m := by + have ht := Telescope.extend_beyond (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (xs ++ fs ++ hs) 0 + simpa only [List.length_append, Nat.add_zero, Telescope.extend_append, Valuation.cons_zero, + hxlen, hflen, hhs] using ht + simp only [Nat.add_assoc] at hmvar + rw [minorResult, AExpr.interp_appN] + simp only [interp, hmvar, List.map_append, List.map_map, Function.comp_def, hidx, + List.map_cons, List.map_nil, Telescope.applyN_append, Telescope.applyN, Nat.add_assoc, hcv] + rw [motive, projList_mkTower _ _ (FitsS.length_eq hit)] + +theorem minorType_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : ConstructorReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {ps : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (m : V) : + interp reading levels (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) + (shape.minorType source mode i ctor) = + shape.minorSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m i ctor := by + rw [minorType, AExpr.interp_forallN, minorFields_piN h hr.toFamilyReading hM hn + (List.mem_of_getElem? hc) hps] + apply Telescope.piN_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro xs hxs + apply Telescope.piN_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro fs hfs + have hflen : fs.length = ctor.recursive.length := by simpa using FitsS.length_eq hfs + rw [Telescope.extend_append, AExpr.interp_forallN, + ihTypes_piN h hr.toFamilyReading hM hn (List.mem_of_getElem? hc) hps hxs hflen] + apply Telescope.piN_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro hs hhs + exact minorResult_interp h hr hM hn hc hps hxs hfs + (by simpa only [ihTypes, List.length_map, List.length_zipIdx] using FitsS.length_eq hhs) m + +theorem minorTypes_piN {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : ConstructorReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {ps : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (m : V) (w : Nat) (R : List V → V) : + Telescope.piN w (Telescope.interpret reading levels + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (shape.minorTypesSyntax source mode)) R = + Telescope.piN w (Telescope.simple (shape.minorTypes constants (mode.sourceArgs levels) + (Telescope.extend (fun _ => empty) ps) (mode.motiveLevel.eval levels) m)) R := by + have ht := Telescope.piN_independent reading levels + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) + (shape.constructors.zipIdx.map fun (ctor, i) => shape.minorType source mode i ctor) [] w R + simp only [List.length_nil, Telescope.extend] at ht + rw [minorTypesSyntax, ht] + have he : ((shape.constructors.zipIdx.map fun (ctor, i) => shape.minorType source mode i ctor).map + (interp reading levels (Valuation.cons m (Telescope.extend (fun _ => empty) ps)))) = + shape.minorTypes constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m := by + apply List.ext_getElem? + intro i + simp only [minorTypes, List.getElem?_map, List.getElem?_zipIdx] + cases hc : shape.constructors[i]? with + | none => rfl + | some ctor => + simp only [Option.map_some, Nat.zero_add] + exact congrArg some (minorType_interp h hr hM hn hc hps m) + rw [he] + +theorem minorTypes_curry {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : ConstructorReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {ps : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (m : V) (w : Nat) (f : List V → V) : + Telescope.curry w (Telescope.interpret reading levels + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (shape.minorTypesSyntax source mode)) f = + Telescope.curry w (Telescope.simple (shape.minorTypes constants (mode.sourceArgs levels) + (Telescope.extend (fun _ => empty) ps) (mode.motiveLevel.eval levels) m)) f := by + have ht := Telescope.curry_independent reading levels + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) + (shape.constructors.zipIdx.map fun (ctor, i) => shape.minorType source mode i ctor) [] w f + simp only [List.length_nil, Telescope.extend] at ht + rw [minorTypesSyntax, ht] + have he : ((shape.constructors.zipIdx.map fun (ctor, i) => shape.minorType source mode i ctor).map + (interp reading levels (Valuation.cons m (Telescope.extend (fun _ => empty) ps)))) = + shape.minorTypes constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m := by + apply List.ext_getElem? + intro i + simp only [minorTypes, List.getElem?_map, List.getElem?_zipIdx] + cases hc : shape.constructors[i]? with + | none => rfl + | some ctor => + simp only [Option.map_some, Nat.zero_add] + exact congrArg some (minorType_interp h hr hM hn hc hps m) + rw [he] + +theorem recursorTail_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) + (hn : levels.length = mode.recUvars shape.universes) {ps minors : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hlen : minors.length = shape.constructors.length) (m : V) : + interp reading levels (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) + (shape.recursorTail source mode) = + shape.recursorSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m := by + have hcommon : 1 + shape.constructors.length = (m :: minors).length := by simp [hlen, Nat.add_comm] + have hskip : Valuation.skip (1 + shape.constructors.length) 0 + (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) = + Telescope.extend (fun _ => empty) ps := by + simpa only [← hcommon, Telescope.extend] using + Telescope.skip_extend (Telescope.extend (fun _ => empty) ps) (m :: minors) + rw [recursorTail, AExpr.interp_forallN, Telescope.piN_lift, hskip, + Telescope.piN_instL, mode.sourceLevels_eval hn, + hr.agrees.telescope (fun A ha => h.references A (List.mem_append_right _ ha))] + apply Telescope.piN_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro is his + have hil := FitsS.length_eq his + have hvars := interp_parameterVars_extend reading (mode.sourceArgs levels) + (Telescope.extend (fun _ => empty) ps) is + rw [hil] at hvars + have hit : FitsS (Telescope.interpret constants (mode.sourceArgs levels) + (Telescope.extend (fun _ => empty) ps) shape.indices) + ((parameterVars 0 shape.indices.length).map + (interp reading (mode.sourceArgs levels) + (Telescope.extend (Telescope.extend (fun _ => empty) ps) is))) := by + simpa only [hvars] using his + have happ := familyApp_interp hr (mode.sourceArgs_length hn) hps hit + simp only [hil, hvars] at happ + have hskip' : Valuation.skip (1 + shape.constructors.length) shape.indices.length + (Telescope.extend (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) is) = + Telescope.extend (Telescope.extend (fun _ => empty) ps) is := by + simpa only [← hcommon, Telescope.extend, hil] using + Telescope.skip_middle (Telescope.extend (fun _ => empty) ps) (m :: minors) is + rw [interp, interp_liftN, hskip', interp_instL, mode.sourceLevels_eval hn, happ] + apply piR_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro x _ + have hmvar : Valuation.cons x + (Telescope.extend (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) is) + (shape.constructors.length + shape.indices.length + 1) = m := by + rw [Valuation.cons_succ] + have ht := Telescope.extend_beyond (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (minors ++ is) 0 + simpa only [List.length_append, Nat.add_zero, hlen, hil, Telescope.extend_append, Valuation.cons_zero] using ht + have hisvars := interp_parameterVars_middle reading levels + (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) is [x] + simp only [List.length_singleton, hil, Telescope.extend] at hisvars + simp only [AExpr.interp_appN, interp, hmvar, List.map_append, hisvars, List.map_cons, + List.map_nil, Valuation.cons_zero, Telescope.applyN_append, Telescope.applyN] + rw [motive, projList_mkTower _ _ hil] + +noncomputable def closedRecursorSet (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (mode : ElimMode) : V := + let ls := mode.sourceArgs levels + let v := mode.motiveLevel.eval levels + Telescope.piN v (Telescope.interpret constants ls (fun _ => empty) shape.parameters) fun ps => + piR v (shape.motiveSet constants ls (Telescope.extend (fun _ => empty) ps) v) fun m => + Telescope.piN v (Telescope.simple (shape.minorTypes constants ls (Telescope.extend (fun _ => empty) ps) v m)) + (fun _ => shape.recursorSet constants ls (Telescope.extend (fun _ => empty) ps) v m) + +theorem recursorType_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : ConstructorReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) : + interp reading levels (fun _ => empty) (shape.recursorType source mode) = + shape.closedRecursorSet constants levels mode := by + rw [recursorType, AExpr.interp_forallN, Telescope.piN_instL, mode.sourceLevels_eval hn, + hr.agrees.telescope (fun A ha => h.references A (List.mem_append_left _ ha))] + apply Telescope.piN_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro ps hps + rw [interp, motiveType_interp hr.toFamilyReading hn hps + (fun A ha => h.references A (List.mem_append_right _ ha))] + apply piR_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro m _ + rw [AExpr.interp_forallN, minorTypes_piN h hr hM hn hps] + apply Telescope.piN_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro minors hminors + exact recursorTail_interp h hr.toFamilyReading hn hps + (by simpa only [minorTypes, List.length_map, List.length_zipIdx] using FitsS.length_eq hminors) m + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/RecursorStage.lean b/Ix/Theory/Certified/Ordinary/RecursorStage.lean new file mode 100644 index 000000000..9ef6c73c5 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/RecursorStage.lean @@ -0,0 +1,163 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.ConstructorStage + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Inductive + +universe u v +variable {β : Type u} [DecidableEq β] + +namespace Shape + +def recursorEntry (shape : Shape β) (source : β) (mode : ElimMode) : ConstantEntry β := + ⟨mode.recUvars shape.universes, shape.recursorType source mode, none, [], []⟩ + +def recursorSource (shape : Shape β) (source recursor : β) (mode : ElimMode) (k : Bool := false) : Const β := + .recursor (mode.recUvars shape.universes) shape.parameters.length shape.indices.length 1 + shape.constructors.length (shape.recursorType source mode).erase + (shape.constructors.zipIdx.map fun (ctor, i) => + ⟨ctor.fields.length + ctor.recursive.length, (shape.ruleRhs source recursor mode i ctor).erase⟩) + k .safe + +/-- K metadata is supported for a singleton proposition whose constructor has +no fields. Replacing a major proof still requires a typed proof-irrelevance +certificate at the exact constructor result, followed by the admitted rule. -/ +def SupportsK (shape : Shape β) : Prop := + shape.level = .zero ∧ ∃ ctor, shape.constructors = [ctor] ∧ ctor.fields = [] ∧ ctor.recursive = [] + +instance (shape : Shape β) : Decidable shape.SupportsK := + match h : shape.constructors with + | [ctor] => decidable_of_iff (shape.level = .zero ∧ ctor.fields = [] ∧ ctor.recursive = []) (by + simp [SupportsK, h]) + | [] => .isFalse (by simp [SupportsK, h]) + | _ :: _ :: _ => .isFalse (by simp [SupportsK, h]) + +def RecursorSourceMatches (shape : Shape β) (store : Store β) (source recursor : β) (mode : ElimMode) : Prop := + store.blocks recursor = some ⟨[shape.recursorSource source recursor mode]⟩ ∨ + (shape.SupportsK ∧ store.blocks recursor = some ⟨[shape.recursorSource source recursor mode true]⟩) + +instance (shape : Shape β) (store : Store β) (source recursor : β) (mode : ElimMode) : + Decidable (shape.RecursorSourceMatches store source recursor mode) := by + unfold RecursorSourceMatches + infer_instance + +def recursorLaws (shape : Shape β) (source recursor : β) (mode : ElimMode) : List (ConstantEquation β) := + shape.constructors.zipIdx.map fun (ctor, i) => + ⟨shape.ruleLhs source recursor mode i ctor, shape.ruleRhs source recursor mode i ctor⟩ + +def recursorEnvironment (shape : Shape β) (entries : Environment β) (source recursor : β) + (mode : ElimMode) : Environment β := + (shape.constructorEnvironment entries source).insert (.member recursor 0) (shape.recursorEntry source mode) + +structure RecursorFormation (entries : Environment β) (store : Store β) (shape : Shape β) + (source recursor : β) (mode : ElimMode) : Prop where + exactSource : shape.RecursorSourceMatches store source recursor mode + fresh : shape.constructorEnvironment entries source (.member recursor 0) = none + closed : EntryClosed (shape.constructorEnvironment entries source) (shape.recursorEntry source mode) + typing : ∃ l, TypingClaim.{u,v} (shape.constructorEnvironment entries source) [] + (shape.recursorType source mode) (.sort l) + +def checkRecursorType (fuel : Nat) (entries : Environment β) (store : Store β) (shape : Shape β) + (source recursor : β) (mode : ElimMode) (witness : TypeWitness β) : + Option (CheckedClaim.{u} (RecursorFormation.{u,v} entries store shape source recursor mode)) := + if hsource : shape.RecursorSourceMatches store source recursor mode then + if hfresh : shape.constructorEnvironment entries source (.member recursor 0) = none then + if hs : (shape.recursorType source mode).Scope (mode.recUvars shape.universes) 0 then + if hr : (shape.recursorType source mode).ReferencesIn (shape.constructorEnvironment entries source) then do + let ht ← verifyType.{u,v} fuel (mode.recUvars shape.universes) (shape.constructorEnvironment entries source) [] + (shape.recursorType source mode) (.sort witness.level) witness.witness + return ⟨⟨hsource, hfresh, ⟨hs, by simp [recursorEntry], hr, by simp [recursorEntry], + by simp [recursorEntry], by simp [recursorEntry], + by simp [recursorEntry], by simp [recursorEntry]⟩, witness.level, ht.down⟩⟩ + else none + else none + else none + else none + +theorem recursorEnvironment_wf {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} + (h : CheckedShape.{u,v} entries store source shape) (hE : entries.WF) + (hC : ConstructorFormation.{u,v} entries shape source) + (hR : RecursorFormation.{u,v} entries store shape source recursor mode) : + (shape.recursorEnvironment entries source recursor mode).WF := + (constructorEnvironment_wf h hE hC).insert hR.closed.typeScope hR.closed.bodyScope + hR.closed.typeReferences hR.closed.bodyReferences hR.closed.equationScope hR.closed.equationReferences + hR.closed.factScope hR.closed.factReferences + +variable {V : Type v} [SetTheory V] + +noncomputable def recursorAssignment (shape : Shape β) (constants : Assignment β V) + (source recursor : β) (mode : ElimMode) : Assignment β V := + (shape.constructorAssignment constants source).insert (.member recursor 0) + (fun levels => shape.closedRecursorValue constants levels mode) + +end Shape + +variable {V : Type v} [SetTheory V] + +structure RecursorReading (entries : Environment β) (shape : Shape β) (source recursor : β) + (mode : ElimMode) (constants reading : Assignment β V) : Prop + extends ConstructorReading entries shape source constants reading where + recursor : ∀ levels, levels.length = mode.recUvars shape.universes → + reading (.member recursor 0) levels = shape.closedRecursorValue constants levels mode + +namespace Shape + +theorem recursorAssignment_agreesConstructors {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} + (hR : RecursorFormation.{u,v} entries store shape source recursor mode) (constants : Assignment β V) : + Assignment.AgreesOn (shape.constructorEnvironment entries source) (shape.constructorAssignment constants source) + (shape.recursorAssignment constants source recursor mode) := Assignment.insert_agrees hR.fresh _ _ + +theorem recursorAssignment_reading {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} (h : CheckedShape.{u,v} entries store source shape) + (hR : RecursorFormation.{u,v} entries store shape source recursor mode) (constants : Assignment β V) : + RecursorReading entries shape source recursor mode constants (shape.recursorAssignment constants source recursor mode) := by + have hr := constructorAssignment_reading h constants + have ha := recursorAssignment_agreesConstructors hR constants + constructor + · constructor + · constructor + · intro r entry he levels + exact (ha r entry (Environment.overlay_old (constructorEntries_fresh h) + (Environment.insert_old (h.fresh _ (List.mem_cons_self ..)) he)) levels).trans (hr.agrees r entry he levels) + · intro levels hn + exact (ha _ _ (Environment.overlay_old (constructorEntries_fresh h) (Environment.insert_same ..)) levels).trans + (hr.family levels hn) + · intro levels hn i ctor hc + exact (ha _ (shape.constructorEntry source ctor) (Environment.overlay_new (by + simp only [constructorEntries, ↓reduceIte, hc, Option.map_some])) levels).trans (hr.constructor levels hn i ctor hc) + · intro levels _ + exact Assignment.insert_same .. + +theorem recursorAssignment_realizes {entries : Environment β} {store : Store β} {source recursor : β} + {shape : Shape β} {mode : ElimMode} + (h : CheckedShape.{u,v} entries store source shape) (hE : entries.WF) + (hC : ConstructorFormation.{u,v} entries shape source) + (hR : RecursorFormation.{u,v} entries store shape source recursor mode) + (hmode : ModeEvidence.{u,v} entries shape mode) (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (shape.recursorAssignment constants source recursor mode) (shape.recursorEnvironment entries source recursor mode) := by + have hr := recursorAssignment_reading h hR constants + have hbase := (constructorAssignment_realizes h hE hC constants hM).of_agrees + (constructorEnvironment_wf h hE hC) (recursorAssignment_agreesConstructors hR constants) + obtain ⟨l, ht⟩ := hR.typing + apply hbase.insert + constructor + · intro levels hn env + exact (ht V _ hbase levels env (Context.valid_nil _ _ _)).1 + · intro levels hn env + rw [hr.recursor levels hn] + have hm := closedRecursorValue_mem_source h hr.toConstructorReading hmode hM hn + rwa [interp_closed (shape.recursorType source mode) _ levels hR.closed.typeScope (fun _ => empty) env] at hm + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl; simp only [recursorEntry, List.not_mem_nil] at hl + · intro fact hf; simp only [recursorEntry, List.not_mem_nil] at hf + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/RecursorSyntax.lean b/Ix/Theory/Certified/Ordinary/RecursorSyntax.lean new file mode 100644 index 000000000..41ceed1b6 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/RecursorSyntax.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Reading +import Ix.Theory.Inductive.Levels + +/-! +Annotated ordinary recursor syntax. Every source expression is transported +through the explicit source-universe map; the motive keeps its own universe. +The generated syntax is subsequently compared with the complete stored type +and rule, and is checked for formation before any equation is published. +-/ + +namespace Ix.Theory.Certified.Ordinary + +open Model Inductive + +universe u +variable {β : Type u} + +namespace Shape + +def motiveType (shape : Shape β) (source : β) (mode : ElimMode) : AExpr β := + .forallN .never (shape.indices.map (AExpr.instL (mode.sourceLevels shape.universes))) <| + .forallE .never + ((shape.familyApp source shape.indices.length (parameterVars 0 shape.indices.length)).instL + (mode.sourceLevels shape.universes)) + (.sort mode.motiveLevel) + +def minorFields (shape : Shape β) (source : β) (mode : ElimMode) (ctor : Constructor β) : + List (AExpr β) := + Telescope.lift 1 ((ctor.fields ++ ctor.recursiveTypes shape source).map + (AExpr.instL (mode.sourceLevels shape.universes))) + +def ihType (shape : Shape β) (mode : ElimMode) (ctor : Constructor β) + (j : Nat) (field : RecursiveField β) : AExpr β := + let sl := mode.sourceLevels shape.universes + let a := ctor.fields.length + let b := ctor.recursive.length + let d := field.domains.length + .forallN (zeroCondition mode.motiveLevel) + (Telescope.lift b (Telescope.lift 1 (field.domains.map (AExpr.instL sl)) a)) + (.appN (.bvar (a + b + d)) + (field.indices.map (fun e => ((e.instL sl).liftN 1 (a + d)).liftN b d) ++ + [.appN (.bvar (b - 1 - j + d)) (parameterVars 0 d)])) + +def ihTypesSyntax (shape : Shape β) (mode : ElimMode) (ctor : Constructor β) : List (AExpr β) := + Telescope.independent (ctor.recursive.zipIdx.map fun (field, j) => shape.ihType mode ctor j field) + +def minorResult (shape : Shape β) (source : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + let sl := mode.sourceLevels shape.universes + let a := ctor.fields.length + let b := ctor.recursive.length + .appN (.bvar (a + b + b)) + (ctor.indices.map (fun e => ((e.instL sl).liftN 1 a).liftN (b + b)) ++ + [.appN (.const (.ctor source 0 i) sl) + (parameterVars (1 + a + b + b) shape.parameters.length ++ parameterVars b (a + b))]) + +def minorType (shape : Shape β) (source : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + .forallN (zeroCondition mode.motiveLevel) (shape.minorFields source mode ctor) <| + .forallN (zeroCondition mode.motiveLevel) (shape.ihTypesSyntax mode ctor) <| + shape.minorResult source mode i ctor + +def minorTypesSyntax (shape : Shape β) (source : β) (mode : ElimMode) : List (AExpr β) := + Telescope.independent (shape.constructors.zipIdx.map fun (ctor, i) => shape.minorType source mode i ctor) + +def recursorTail (shape : Shape β) (source : β) (mode : ElimMode) : AExpr β := + let sl := mode.sourceLevels shape.universes + let pv := zeroCondition mode.motiveLevel + let c := shape.constructors.length + let n := shape.indices.length + .forallN pv (Telescope.lift (1 + c) (shape.indices.map (AExpr.instL sl))) <| + .forallE pv + (((shape.familyApp source n (parameterVars 0 n)).instL sl).liftN (1 + c) n) + (.appN (.bvar (c + n + 1)) (parameterVars 1 n ++ [.bvar 0])) + +def recursorType (shape : Shape β) (source : β) (mode : ElimMode) : AExpr β := + let pv := zeroCondition mode.motiveLevel + .forallN pv (shape.parameters.map (AExpr.instL (mode.sourceLevels shape.universes))) <| + .forallE pv (shape.motiveType source mode) <| + .forallN pv (shape.minorTypesSyntax source mode) <| + shape.recursorTail source mode + +def ruleBinders (shape : Shape β) (source : β) (mode : ElimMode) (ctor : Constructor β) : + List (AExpr β) := + shape.parameters.map (AExpr.instL (mode.sourceLevels shape.universes)) ++ + [shape.motiveType source mode] ++ shape.minorTypesSyntax source mode ++ + Telescope.lift (1 + shape.constructors.length) + ((ctor.fields ++ ctor.recursiveTypes shape source).map + (AExpr.instL (mode.sourceLevels shape.universes))) + +def ruleCall (shape : Shape β) (recursor : β) (mode : ElimMode) + (ctor : Constructor β) (j : Nat) (field : RecursiveField β) : AExpr β := + let sl := mode.sourceLevels shape.universes + let common := 1 + shape.constructors.length + let a := ctor.fields.length + let b := ctor.recursive.length + let d := field.domains.length + .lamN (zeroCondition mode.motiveLevel) + (Telescope.lift b (Telescope.lift common (field.domains.map (AExpr.instL sl)) a)) + (.appN (.const (.member recursor 0) (mode.recLevels shape.universes)) + (parameterVars (a + b + d) (shape.parameters.length + common) ++ + field.indices.map (fun e => ((e.instL sl).liftN common (a + d)).liftN b d) ++ + [.appN (.bvar (b - 1 - j + d)) (parameterVars 0 d)])) + +def ruleRhsBody (shape : Shape β) (recursor : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + .appN (.bvar (shape.constructors.length - 1 - i + ctor.fields.length + ctor.recursive.length)) + (parameterVars 0 (ctor.fields.length + ctor.recursive.length) ++ + ctor.recursive.zipIdx.map (fun (field, j) => shape.ruleCall recursor mode ctor j field)) + +def ruleRhs (shape : Shape β) (source recursor : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + .lamN (zeroCondition mode.motiveLevel) (shape.ruleBinders source mode ctor) + (shape.ruleRhsBody recursor mode i ctor) + +def ruleIndices (shape : Shape β) (mode : ElimMode) (ctor : Constructor β) : List (AExpr β) := + ctor.indices.map fun e => + ((e.instL (mode.sourceLevels shape.universes)).liftN (1 + shape.constructors.length) + ctor.fields.length).liftN ctor.recursive.length + +def ruleConstructor (shape : Shape β) (source : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + let n := ctor.fields.length + ctor.recursive.length + .appN (.const (.ctor source 0 i) (mode.sourceLevels shape.universes)) + (parameterVars (1 + shape.constructors.length + n) shape.parameters.length ++ parameterVars 0 n) + +def ruleResult (shape : Shape β) (source : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + .appN (.bvar (shape.constructors.length + ctor.fields.length + ctor.recursive.length)) + (shape.ruleIndices mode ctor ++ [shape.ruleConstructor source mode i ctor]) + +def ruleType (shape : Shape β) (source : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + .forallN (zeroCondition mode.motiveLevel) (shape.ruleBinders source mode ctor) + (shape.ruleResult source mode i ctor) + +def ruleLhsBody (shape : Shape β) (source recursor : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + .appN (.const (.member recursor 0) (mode.recLevels shape.universes)) + (parameterVars (ctor.fields.length + ctor.recursive.length) + (shape.parameters.length + 1 + shape.constructors.length) ++ + shape.ruleIndices mode ctor ++ [shape.ruleConstructor source mode i ctor]) + +def ruleLhs (shape : Shape β) (source recursor : β) (mode : ElimMode) (i : Nat) + (ctor : Constructor β) : AExpr β := + .lamN (zeroCondition mode.motiveLevel) (shape.ruleBinders source mode ctor) + (shape.ruleLhsBody source recursor mode i ctor) + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/RecursorValue.lean b/Ix/Theory/Certified/Ordinary/RecursorValue.lean new file mode 100644 index 000000000..cffca1022 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/RecursorValue.lean @@ -0,0 +1,136 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.RecursorReading + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Inductive + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +def ModeEvidence (entries : Environment β) (shape : Shape β) : ElimMode → Prop + | .small => True + | .large => LargeEvidence.{u,v} entries shape + +def checkMode [DecidableEq β] (fuel : Nat) (entries : Environment β) (witness : ShapeWitness β) + (mode : ElimMode) : Option (CheckedClaim.{u} (ModeEvidence.{u,v} entries witness.shape mode)) := + match mode with + | .small => some ⟨trivial⟩ + | .large => checkLarge fuel entries witness + +namespace Shape + +noncomputable def recursorAt (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (mode : ElimMode) (m : V) (minors : List V) : V := by + classical + exact match mode with + | .small => pt + | .large => + if hD : (shape.container constants (mode.sourceArgs levels) env).WF + (shape.level.eval (mode.sourceArgs levels)) then + if hlarge : (shape.container constants (mode.sourceArgs levels) env).LargeElim + (shape.level.eval (mode.sourceArgs levels)) then + shape.largeValue constants (mode.sourceArgs levels) env (mode.motiveLevel.eval levels) m minors hD hlarge + else pt + else pt + +theorem recursorAt_large (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (m : V) (minors : List V) + (hD : (shape.container constants (ElimMode.large.sourceArgs levels) env).WF + (shape.level.eval (ElimMode.large.sourceArgs levels))) + (hlarge : (shape.container constants (ElimMode.large.sourceArgs levels) env).LargeElim + (shape.level.eval (ElimMode.large.sourceArgs levels))) : + shape.recursorAt constants levels env .large m minors = + shape.largeValue constants (ElimMode.large.sourceArgs levels) env + (ElimMode.large.motiveLevel.eval levels) m minors hD hlarge := by + simp only [recursorAt, dif_pos hD, dif_pos hlarge] + +theorem recursorSet_zero (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (m : V) : + shape.recursorSet constants levels env 0 m ∈ˢ (univZero : V) := + Telescope.piN_zero_mem _ (fun _ _ => piR_zero_mem_univZero) + +variable {entries : Environment β} {shape : Shape β} {source : β} {store : Store β} + {constants : Assignment β V} {levels : List Nat} {env : Nat → V} {mode : ElimMode} + +theorem recursorAt_mem (h : CheckedShape.{u,v} entries store source shape) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) + (hΓ : shape.parameterContext.Valid constants (mode.sourceArgs levels) env) + {m : V} {minors : List V} + (hm : m ∈ˢ shape.motiveSet constants (mode.sourceArgs levels) env (mode.motiveLevel.eval levels)) + (hminors : shape.MinorValuesFit constants (mode.sourceArgs levels) env (mode.motiveLevel.eval levels) m minors) : + shape.recursorAt constants levels env mode m minors ∈ˢ + shape.recursorSet constants (mode.sourceArgs levels) env (mode.motiveLevel.eval levels) m := by + cases mode with + | small => exact pt_mem_smallRecursorSet h hM hΓ hm hminors + | large => + rw [recursorAt_large _ _ _ _ _ _ (container_wf h hM hΓ) (container_large hmode hM hΓ)] + exact largeValue_mem h hM hΓ hm hminors _ _ + +noncomputable def closedRecursorValue (shape : Shape β) (constants : Assignment β V) + (levels : List Nat) (mode : ElimMode) : V := + let ls := mode.sourceArgs levels + let v := mode.motiveLevel.eval levels + Telescope.curry v (Telescope.interpret constants ls (fun _ => empty) shape.parameters) fun ps => + lamR v (shape.motiveSet constants ls (Telescope.extend (fun _ => empty) ps) v) fun m => + Telescope.curry v (Telescope.simple (shape.minorTypes constants ls (Telescope.extend (fun _ => empty) ps) v m)) + (fun minors => shape.recursorAt constants levels (Telescope.extend (fun _ => empty) ps) mode m minors) + +theorem closedRecursorValue_mem (h : CheckedShape.{u,v} entries store source shape) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) : + shape.closedRecursorValue constants levels mode ∈ˢ shape.closedRecursorSet constants levels mode := by + apply Telescope.curry_mem + intro ps hps + apply lamR_mem + intro m hm + apply Telescope.curry_mem + intro minors hminors + exact recursorAt_mem h hmode hM + (h.parameters.valid constants hM (mode.sourceArgs levels) + (Context.valid_nil constants (mode.sourceArgs levels) (fun _ => empty)) hps) hm hminors + +theorem closedRecursorValue_mem_source (h : CheckedShape.{u,v} entries store source shape) + {reading : Assignment β V} (hr : ConstructorReading entries shape source constants reading) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) : + shape.closedRecursorValue constants levels mode ∈ˢ + interp reading levels (fun _ => empty) (shape.recursorType source mode) := by + rw [recursorType_interp h hr hM hn] + exact closedRecursorValue_mem h hmode hM + +theorem closedRecursorValue_apply (h : CheckedShape.{u,v} entries store source shape) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) {ps : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + {m : V} {minors : List V} + (hm : m ∈ˢ shape.motiveSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels)) + (hminors : shape.MinorValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m minors) : + Telescope.applyN (shape.closedRecursorValue constants levels mode) (ps ++ [m] ++ minors) = + shape.recursorAt constants levels (Telescope.extend (fun _ => empty) ps) mode m minors := by + have hbody (ps : List V) hps m hm minors hminors := recursorAt_mem h hmode hM + (h.parameters.valid constants hM (mode.sourceArgs levels) (xs := ps) + (Context.valid_nil constants (mode.sourceArgs levels) (fun _ => empty)) hps) + (m := m) hm (minors := minors) hminors + have hminor ps hps m hm := Telescope.curry_mem (w := mode.motiveLevel.eval levels) _ (hbody ps hps m hm) + have hmotive ps hps := lamR_mem (v := mode.motiveLevel.eval levels) (hminor ps hps) + rw [closedRecursorValue, Telescope.applyN_append, Telescope.applyN_append, + Telescope.applyN_curry _ hps hmotive (fun hv _ _ => by + rw [hv] + exact piR_zero_mem_univZero)] + change Telescope.applyN (app (lamR _ _ _) m) minors = _ + rw [app_lamR hm (hminor ps hps) (fun hv _ _ => by + rw [hv] + apply Telescope.piN_zero_mem + intro _ _ + exact recursorSet_zero _ _ _ _ _)] + exact Telescope.applyN_curry _ hminors (hbody ps hps m hm) (fun hv _ _ => by + rw [hv] + exact recursorSet_zero _ _ _ _ _) + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/RuleChecks.lean b/Ix/Theory/Certified/Ordinary/RuleChecks.lean new file mode 100644 index 000000000..874c81654 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/RuleChecks.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.RecursorStage + +namespace Ix.Theory.Certified.Ordinary + +open Model Model.SetTheory Model.SetModel Inductive + +universe u v +variable {β : Type u} [DecidableEq β] + +structure RuleWitness (β : Type u) where + typeLevel : VLevel + typeWitness : TypingWitness β + lhsWitness : TypingWitness β + rhsWitness : TypingWitness β + +namespace Shape + +/-- These checks run against the formed recursor signature with no equations. +They establish the whole closed rule's type, both endpoint memberships, and +the syntactic scope/reference facts needed when its equation is published. -/ +structure RuleFormation (entries : Environment β) (shape : Shape β) (source recursor : β) + (mode : ElimMode) (i : Nat) (ctor : Constructor β) : Prop where + scope : (shape.ruleLhs source recursor mode i ctor).Scope (mode.recUvars shape.universes) 0 ∧ + (shape.ruleRhs source recursor mode i ctor).Scope (mode.recUvars shape.universes) 0 + references : (shape.ruleLhs source recursor mode i ctor).ReferencesIn entries ∧ + (shape.ruleRhs source recursor mode i ctor).ReferencesIn entries + type : ∃ l, TypingClaim.{u,v} entries [] (shape.ruleType source mode i ctor) (.sort l) ∧ + (mode = .small → ∀ levels, l.eval levels = 0) + lhs : TypingClaim.{u,v} entries [] (shape.ruleLhs source recursor mode i ctor) (shape.ruleType source mode i ctor) + rhs : TypingClaim.{u,v} entries [] (shape.ruleRhs source recursor mode i ctor) (shape.ruleType source mode i ctor) + +def checkRule (fuel : Nat) (entries : Environment β) (shape : Shape β) (source recursor : β) + (mode : ElimMode) (i : Nat) (ctor : Constructor β) (witness : RuleWitness β) : + Option (CheckedClaim.{u} (RuleFormation.{u,v} entries shape source recursor mode i ctor)) := + if hs : (shape.ruleLhs source recursor mode i ctor).Scope (mode.recUvars shape.universes) 0 ∧ + (shape.ruleRhs source recursor mode i ctor).Scope (mode.recUvars shape.universes) 0 then + if hr : (shape.ruleLhs source recursor mode i ctor).ReferencesIn entries ∧ + (shape.ruleRhs source recursor mode i ctor).ReferencesIn entries then + if hsmall : mode = .small → LevelEq.check (mode.recUvars shape.universes) witness.typeLevel .zero = true then do + let ht ← verifyType.{u,v} fuel (mode.recUvars shape.universes) entries [] + (shape.ruleType source mode i ctor) (.sort witness.typeLevel) witness.typeWitness + let hl ← verifyType.{u,v} fuel (mode.recUvars shape.universes) entries [] + (shape.ruleLhs source recursor mode i ctor) (shape.ruleType source mode i ctor) witness.lhsWitness + let hh ← verifyType.{u,v} fuel (mode.recUvars shape.universes) entries [] + (shape.ruleRhs source recursor mode i ctor) (shape.ruleType source mode i ctor) witness.rhsWitness + return ⟨⟨hs, hr, ⟨witness.typeLevel, ht.down, by + intro he levels + exact (LevelEq.check_sound (hsmall he)).2.2 levels⟩, hl.down, hh.down⟩⟩ + else none + else none + else none + +def checkRules (fuel : Nat) (entries : Environment β) (shape : Shape β) (source recursor : β) + (mode : ElimMode) : (ctors : List (Constructor β × Nat)) → List (RuleWitness β) → + Option (CheckedClaim.{u} (∀ ctor i, (ctor, i) ∈ ctors → + RuleFormation.{u,v} entries shape source recursor mode i ctor)) + | [], [] => some ⟨by simp⟩ + | (ctor, i) :: ctors, witness :: witnesses => do + let rule ← checkRule fuel entries shape source recursor mode i ctor witness + let rest ← checkRules fuel entries shape source recursor mode ctors witnesses + return ⟨by + intro ctor' i' hc + rcases List.mem_cons.mp hc with he | hc + · cases he; exact rule.down + · exact rest.down ctor' i' hc⟩ + | _, _ => none + +variable {V : Type v} [SetTheory V] + +omit [DecidableEq β] in +theorem small_rule_eq {entries : Environment β} {shape : Shape β} {source recursor : β} + {i : Nat} {ctor : Constructor β} + (h : RuleFormation.{u,v} entries shape source recursor .small i ctor) + (constants : Assignment β V) (hM : Realizes constants entries) (levels : List Nat) (env : Nat → V) : + interp constants levels env (shape.ruleLhs source recursor .small i ctor) = + interp constants levels env (shape.ruleRhs source recursor .small i ctor) := by + obtain ⟨l, ht, hz⟩ := h.type + have hΓ := Context.valid_nil constants levels env + have hprop := (ht V constants hM levels env hΓ).2.2 + rw [interp, hz rfl levels, univ_zero] at hprop + exact subsingleton_of_mem_univZero hprop (h.lhs V constants hM levels env hΓ).2.2 + (h.rhs V constants hM levels env hΓ).2.2 + +end Shape +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Ordinary/RuleEquations.lean b/Ix/Theory/Certified/Ordinary/RuleEquations.lean new file mode 100644 index 000000000..9af9d737b --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/RuleEquations.lean @@ -0,0 +1,115 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.RuleReading + +namespace Ix.Theory.Certified.Ordinary.Shape + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Inductive + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + {entries : Environment β} {shape : Shape β} {source recursor : β} + {constants reading : Assignment β V} {levels : List Nat} {mode : ElimMode} + +theorem ruleFields_curry {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {ps minors : List V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hmlen : minors.length = shape.constructors.length) (m : V) (w : Nat) (f : List V → V) : + Telescope.curry w (Telescope.interpret reading levels + (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) + (Telescope.lift (1 + shape.constructors.length) ((ctor.fields ++ ctor.recursiveTypes shape source).map + (AExpr.instL (mode.sourceLevels shape.universes))))) f = + Telescope.curry w + (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) + (fun xs => Telescope.curry w + (Telescope.simple (ctor.recursive.map + (shape.recursiveSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) xs))) + (fun fs => f (xs ++ fs))) := by + have hskip : Valuation.skip (1 + shape.constructors.length) 0 + (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) = + Telescope.extend (fun _ => empty) ps := by + have ht := Telescope.skip_extend (Telescope.extend (fun _ => empty) ps) (m :: minors) + simpa only [List.length_cons, hmlen, Telescope.extend, Nat.add_comm] using ht + rw [Telescope.curry_lift, hskip, Telescope.curry_instL, mode.sourceLevels_eval hn, + Telescope.curry_append, + hr.agrees.telescope (fun A ha => (h.constructors ctor hc).1 A (List.mem_append_left _ ha))] + apply Telescope.curry_congr + intro xs hxs + have ht := curry_recursiveTypes h hr hM (mode.sourceArgs_length hn) hc (fun _ h => h) hps hxs [] w + (fun fs => f (xs ++ fs)) + simpa only [Constructor.recursiveTypes, List.length_nil, Telescope.extend] using ht + +/-- Equality of the complete lambda-abstracted rule, including parameters, +the motive, every minor premise, and all constructor fields. -/ +theorem large_rule_eq {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : RecursorReading entries shape source recursor .large constants reading) + (hmode : ModeEvidence.{u,v} entries shape .large) (hM : Realizes constants entries) + (hn : levels.length = ElimMode.large.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) : + interp reading levels (fun _ => empty) (shape.ruleLhs source recursor .large i ctor) = + interp reading levels (fun _ => empty) (shape.ruleRhs source recursor .large i ctor) := by + simp only [ruleLhs, ruleRhs, ruleBinders, AExpr.lamN_append, AExpr.interp_lamN, + Telescope.curry_instL, ElimMode.sourceLevels_eval _ hn, + hr.agrees.telescope (fun A ha => h.references A (List.mem_append_left _ ha))] + apply Telescope.curry_congr + intro ps hps + change lamR _ (interp reading levels _ (shape.motiveType source .large)) _ = lamR _ _ _ + rw [motiveType_interp hr.toFamilyReading hn hps (fun A ha => h.references A (List.mem_append_right _ ha))] + apply lamR_congr + intro m hm + change Telescope.curry _ (Telescope.interpret reading levels + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (shape.minorTypesSyntax source .large)) _ = + Telescope.curry _ (Telescope.interpret reading levels + (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) (shape.minorTypesSyntax source .large)) _ + simp only [Telescope.extend] + simp only [minorTypes_curry h hr.toConstructorReading hM hn hps m] + apply Telescope.curry_congr + intro minors hminors + have hmlen : minors.length = shape.constructors.length := by + simpa only [minorTypes, List.length_map, List.length_zipIdx] using FitsS.length_eq hminors + simp only [ruleFields_curry h hr.toFamilyReading hM hn (List.mem_of_getElem? hc) hps hmlen m] + apply Telescope.curry_congr + intro xs hxs + apply Telescope.curry_congr + intro fs hfs + simp only [Telescope.extend_append] + exact large_ruleBody_eq h hr hmode hM hn hc hps hxs hfs hm hminors + +theorem large_rule_eq_closed {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : RecursorReading entries shape source recursor .large constants reading) + (hmode : ModeEvidence.{u,v} entries shape .large) (hM : Realizes constants entries) + (hn : levels.length = ElimMode.large.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) + (hscope : (shape.ruleLhs source recursor .large i ctor).Scope (ElimMode.large.recUvars shape.universes) 0 ∧ + (shape.ruleRhs source recursor .large i ctor).Scope (ElimMode.large.recUvars shape.universes) 0) + (env : Nat → V) : + interp reading levels env (shape.ruleLhs source recursor .large i ctor) = + interp reading levels env (shape.ruleRhs source recursor .large i ctor) := by + rw [← interp_closed _ _ _ hscope.1 (fun _ => empty) env, + ← interp_closed _ _ _ hscope.2 (fun _ => empty) env] + exact large_rule_eq h hr hmode hM hn hc + +variable [DecidableEq β] + +theorem produced_rule_eq {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hE : entries.WF) (hC : ConstructorFormation.{u,v} entries shape source) + (hR : RecursorFormation.{u,v} entries store shape source recursor mode) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) + (hRule : RuleFormation.{u,v} (shape.recursorEnvironment entries source recursor mode) + shape source recursor mode i ctor) (env : Nat → V) : + interp (shape.recursorAssignment constants source recursor mode) levels env (shape.ruleLhs source recursor mode i ctor) = + interp (shape.recursorAssignment constants source recursor mode) levels env (shape.ruleRhs source recursor mode i ctor) := by + cases mode with + | small => + exact small_rule_eq hRule _ (recursorAssignment_realizes h hE hC hR hmode constants hM) levels env + | large => + exact large_rule_eq_closed h (recursorAssignment_reading h hR constants) hmode hM hn hc hRule.scope env + +end Ix.Theory.Certified.Ordinary.Shape diff --git a/Ix/Theory/Certified/Ordinary/RuleReading.lean b/Ix/Theory/Certified/Ordinary/RuleReading.lean new file mode 100644 index 000000000..ab200fac7 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/RuleReading.lean @@ -0,0 +1,270 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.RuleChecks + +namespace Ix.Theory.Model + +open SetTheory + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +theorem Assignment.AgreesOn.interp_inserted {entries : Environment β} + {constants reading : Assignment β V} (h : Assignment.AgreesOn entries constants reading) + (levels : List Nat) (sourceLevels : List VLevel) (env : Nat → V) + (shared xs fs ys : List V) {e : AExpr β} (hrefs : e.ReferencesIn entries) : + Model.interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend env shared) xs) fs) ys) + (((e.instL sourceLevels).liftN shared.length (xs.length + ys.length)).liftN fs.length ys.length) = + Model.interp constants (sourceLevels.map (VLevel.eval levels)) (Telescope.extend (Telescope.extend env xs) ys) e := by + rw [interp_liftN, Telescope.skip_middle, interp_liftN, + show xs.length + ys.length = ys.length + xs.length by omega, + Telescope.skip_extend_at, Telescope.skip_middle, interp_instL, h.interp hrefs] + +end Ix.Theory.Model + +namespace Ix.Theory.Certified.Ordinary.Shape + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Inductive + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +noncomputable def recursorCall (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (mode : ElimMode) (m : V) (minors xs fs : List V) (j : Nat) (field : RecursiveField β) : V := + Telescope.curry (mode.motiveLevel.eval levels) + (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend env xs) field.domains) fun ys => + Telescope.applyN (shape.recursorAt constants levels env mode m minors) + (field.indices.map (interp constants (mode.sourceArgs levels) (Telescope.extend (Telescope.extend env xs) ys)) ++ + [Telescope.applyN (fs.getD j empty) ys]) + +noncomputable def recursorCalls (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (mode : ElimMode) (m : V) (minors : List V) (ctor : Constructor β) (xs fs : List V) : List V := + ctor.recursive.zipIdx.map fun (field, j) => shape.recursorCall constants levels env mode m minors xs fs j field + +theorem recursorCall_large (shape : Shape β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (m : V) (minors xs fs : List V) (j : Nat) (field : RecursiveField β) + (hD : (shape.container constants (ElimMode.large.sourceArgs levels) env).WF + (shape.level.eval (ElimMode.large.sourceArgs levels))) + (hlarge : (shape.container constants (ElimMode.large.sourceArgs levels) env).LargeElim + (shape.level.eval (ElimMode.large.sourceArgs levels))) : + shape.recursorCall constants levels env .large m minors xs fs j field = + shape.recursiveCall constants (ElimMode.large.sourceArgs levels) env + (ElimMode.large.motiveLevel.eval levels) m minors hD hlarge xs fs j field := by + simp only [recursorCall, recursiveCall, recursorAt_large _ _ _ _ _ _ hD hlarge] + +variable {entries : Environment β} {shape : Shape β} {source recursor : β} + {constants reading : Assignment β V} {levels : List Nat} {mode : ElimMode} + +theorem ruleCall_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : RecursorReading entries shape source recursor mode constants reading) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + {j : Nat} {field : RecursiveField β} (hf : ctor.recursive[j]? = some field) + {ps xs fs minors : List V} {m : V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : fs.length = ctor.recursive.length) + (hm : m ∈ˢ shape.motiveSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels)) + (hminors : shape.MinorValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m minors) : + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs) + (shape.ruleCall recursor mode ctor j field) = + shape.recursorCall constants levels (Telescope.extend (fun _ => empty) ps) mode m minors xs fs j field := by + have hctor := h.constructors ctor hc + have hfield := hctor.2.2.2.2 field (List.mem_of_getElem? hf) + have hplen := FitsS.length_eq hps + have hxlen := FitsS.length_eq hxs + have hmlen : minors.length = shape.constructors.length := by + simpa only [minorTypes, List.length_map, List.length_zipIdx] using FitsS.length_eq hminors + have hcommon : 1 + shape.constructors.length = (m :: minors).length := by simp [hmlen, Nat.add_comm] + have hskip : Valuation.skip (1 + shape.constructors.length) ctor.fields.length + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) = + Telescope.extend (Telescope.extend (fun _ => empty) ps) xs := by + simpa only [← hcommon, hxlen] using Telescope.skip_middle (Telescope.extend (fun _ => empty) ps) (m :: minors) xs + rw [ruleCall, AExpr.interp_lamN, Telescope.curry_lift, ← hfs, Telescope.skip_extend, + Telescope.curry_lift, hskip, Telescope.curry_instL, mode.sourceLevels_eval hn, + hr.agrees.telescope (fun A ha => hfield.1 A (List.mem_append_left _ ha))] + apply Telescope.curry_zero_agree (regime_zeroCondition mode.motiveLevel levels) + intro ys hys + have hylen := FitsS.length_eq hys + have hprefix := interp_parameterVars_middle reading levels (fun _ => empty) (ps ++ [m] ++ minors) (xs ++ fs ++ ys) + simp only [List.length_append, List.length_singleton, Telescope.extend_append, Telescope.extend, + hplen, hxlen, hfs, hmlen, hylen, Nat.add_assoc] at hprefix + have hidx : field.indices.map (fun e => interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) + (m :: minors)) xs) fs) ys) + (((e.instL (mode.sourceLevels shape.universes)).liftN (1 + shape.constructors.length) + (ctor.fields.length + field.domains.length)).liftN ctor.recursive.length field.domains.length)) = + field.indices.map (interp constants (mode.sourceArgs levels) + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs) ys)) := by + apply List.map_congr_left + intro e he + have ht := hr.agrees.interp_inserted levels (mode.sourceLevels shape.universes) + (Telescope.extend (fun _ => empty) ps) (m :: minors) xs fs ys (hfield.1 e (List.mem_append_right _ he)) + simpa only [mode.sourceLevels_eval hn, ← hcommon, hxlen, hfs, hylen] using ht + have hfvar : Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) + (m :: minors)) xs) fs) ys (ctor.recursive.length - 1 - j + field.domains.length) = fs.getD j empty := by + rw [← hfs, ← hylen, Nat.add_comm, Telescope.extend_beyond, + Telescope.extend_getD _ _ j (by rw [hfs]; exact (List.getElem?_eq_some_iff.mp hf).1)] + have hvars := interp_parameterVars_extend reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs) ys + rw [hylen] at hvars + simp only [Telescope.extend] at hidx hfvar hvars + simp only [hfs, AExpr.interp_appN, interp, ElimMode.recLevels, eval_params hn, + hr.recursor _ hn, List.map_append, List.map_map, Function.comp_def, List.map_cons, + List.map_nil, hidx, hfvar, hvars, Nat.add_assoc, Telescope.extend, hprefix] + rw [Telescope.applyN_append, Telescope.applyN_append, closedRecursorValue_apply h hmode hM hps hm hminors, + Telescope.applyN_append] + +theorem ruleConstructor_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : ConstructorReading entries shape source constants reading) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {ps xs fs minors : List V} (m : V) + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor xs fs) + (hmlen : minors.length = shape.constructors.length) : + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs) + (shape.ruleConstructor source mode i ctor) = + shape.constructorValue constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor i xs fs := by + have hflen : fs.length = ctor.recursive.length := by simpa using FitsS.length_eq hfs + have ht := constructorVars_interp hr hn hc ps (m :: minors) (xs ++ fs) [] (FitsS.length_eq hps) + rw [← List.append_assoc, constructorClosedValue_apply h hM hc hps hxs hfs] at ht + simpa only [ruleConstructor, List.length_cons, List.length_nil, List.length_append, + hmlen, FitsS.length_eq hxs, hflen, Nat.add_zero, Nat.zero_add, Telescope.extend_append, Telescope.extend, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using ht + +theorem ruleIndices_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : FamilyReading entries shape source constants reading) + (hn : levels.length = mode.recUvars shape.universes) {ctor : Constructor β} (hc : ctor ∈ shape.constructors) + (ps xs fs minors : List V) (m : V) (hxlen : xs.length = ctor.fields.length) + (hflen : fs.length = ctor.recursive.length) (hmlen : minors.length = shape.constructors.length) : + (shape.ruleIndices mode ctor).map (interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs)) = + ctor.indices.map (interp constants (mode.sourceArgs levels) + (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs)) := by + rw [ruleIndices, List.map_map] + apply List.map_congr_left + intro e he + have ht := hr.agrees.interp_inserted levels (mode.sourceLevels shape.universes) + (Telescope.extend (fun _ => empty) ps) (m :: minors) xs fs [] + ((h.constructors ctor hc).1 e (List.mem_append_right _ he)) + simpa only [mode.sourceLevels_eval hn, List.length_cons, List.length_nil, Nat.add_zero, Nat.zero_add, + hxlen, hflen, hmlen, Telescope.extend, Nat.add_comm, Function.comp_def] using ht + +theorem ruleLhsBody_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : RecursorReading entries shape source recursor mode constants reading) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {ps xs fs minors : List V} {m : V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor xs fs) + (hm : m ∈ˢ shape.motiveSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels)) + (hminors : shape.MinorValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m minors) : + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs) + (shape.ruleLhsBody source recursor mode i ctor) = + Telescope.applyN (shape.recursorAt constants levels (Telescope.extend (fun _ => empty) ps) mode m minors) + (ctor.indices.map (interp constants (mode.sourceArgs levels) (Telescope.extend (Telescope.extend (fun _ => empty) ps) xs)) ++ + [shape.constructorValue constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor i xs fs]) := by + have hflen : fs.length = ctor.recursive.length := by simpa using FitsS.length_eq hfs + have hmlen : minors.length = shape.constructors.length := by + simpa only [minorTypes, List.length_map, List.length_zipIdx] using FitsS.length_eq hminors + have hprefix := interp_parameterVars_middle reading levels (fun _ => empty) (ps ++ [m] ++ minors) (xs ++ fs) + simp only [List.length_append, List.length_singleton, Telescope.extend_append, Telescope.extend, + FitsS.length_eq hps, FitsS.length_eq hxs, hflen, hmlen] at hprefix + have hcv := ruleConstructor_interp h hr.toConstructorReading hM hn hc m hps hxs hfs hmlen + have hidx := ruleIndices_interp h hr.toFamilyReading hn (List.mem_of_getElem? hc) + ps xs fs minors m (FitsS.length_eq hxs) hflen hmlen + simp only [Telescope.extend] at hcv hidx + rw [ruleLhsBody, AExpr.interp_appN] + simp only [interp, ElimMode.recLevels, eval_params hn, hr.recursor _ hn, List.map_append, + List.map_cons, List.map_nil, hcv, hidx, Telescope.extend, hprefix] + rw [Telescope.applyN_append, Telescope.applyN_append, closedRecursorValue_apply h hmode hM hps hm hminors, + Telescope.applyN_append] + +theorem ruleRhsBody_interp {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : RecursorReading entries shape source recursor mode constants reading) + (hmode : ModeEvidence.{u,v} entries shape mode) (hM : Realizes constants entries) + (hn : levels.length = mode.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {ps xs fs minors : List V} {m : V} + (hps : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor xs fs) + (hm : m ∈ˢ shape.motiveSet constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels)) + (hminors : shape.MinorValuesFit constants (mode.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (mode.motiveLevel.eval levels) m minors) : + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs) + (shape.ruleRhsBody recursor mode i ctor) = + Telescope.applyN (minors.getD i empty) + (xs ++ fs ++ shape.recursorCalls constants levels (Telescope.extend (fun _ => empty) ps) mode m minors ctor xs fs) := by + have hflen : fs.length = ctor.recursive.length := by simpa using FitsS.length_eq hfs + have hmlen : minors.length = shape.constructors.length := by + simpa only [minorTypes, List.length_map, List.length_zipIdx] using FitsS.length_eq hminors + have hmvar : Telescope.extend + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs + (shape.constructors.length - 1 - i + ctor.fields.length + ctor.recursive.length) = minors.getD i empty := by + have ht := (Telescope.extend_beyond (Telescope.extend (Valuation.cons m (Telescope.extend (fun _ => empty) ps)) minors) + (xs ++ fs) (minors.length - 1 - i)).trans + (Telescope.extend_getD _ minors i (by rw [hmlen]; exact (List.getElem?_eq_some_iff.mp hc).1)) + simpa only [List.length_append, hmlen, FitsS.length_eq hxs, hflen, + Telescope.extend_append, Telescope.extend, Nat.add_comm, Nat.add_assoc, Nat.add_left_comm] using ht + have hfields := interp_parameterVars_extend reading levels + (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) (xs ++ fs) + simp only [List.length_append, FitsS.length_eq hxs, hflen, Telescope.extend_append] at hfields + have hcalls : (ctor.recursive.zipIdx.map fun (field, j) => shape.ruleCall recursor mode ctor j field).map + (interp reading levels (Telescope.extend + (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs)) = + shape.recursorCalls constants levels (Telescope.extend (fun _ => empty) ps) mode m minors ctor xs fs := by + apply List.ext_getElem? + intro j + simp only [recursorCalls, List.getElem?_map, List.getElem?_zipIdx] + cases hf : ctor.recursive[j]? with + | none => rfl + | some field => + simp only [Option.map_some, Nat.zero_add] + exact congrArg some (ruleCall_interp h hr hmode hM hn (List.mem_of_getElem? hc) hf hps hxs hflen hm hminors) + rw [ruleRhsBody, AExpr.interp_appN] + simp only [interp, hmvar, List.map_append, hfields, hcalls] + +theorem large_ruleBody_eq {store : Store β} (h : CheckedShape.{u,v} entries store source shape) + (hr : RecursorReading entries shape source recursor .large constants reading) + (hmode : ModeEvidence.{u,v} entries shape .large) (hM : Realizes constants entries) + (hn : levels.length = ElimMode.large.recUvars shape.universes) {i : Nat} {ctor : Constructor β} + (hc : shape.constructors[i]? = some ctor) {ps xs fs minors : List V} {m : V} + (hps : FitsS (Telescope.interpret constants (ElimMode.large.sourceArgs levels) (fun _ => empty) shape.parameters) ps) + (hxs : FitsS (Telescope.interpret constants (ElimMode.large.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor.fields) xs) + (hfs : shape.RecursiveValuesFit constants (ElimMode.large.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) ctor xs fs) + (hm : m ∈ˢ shape.motiveSet constants (ElimMode.large.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (ElimMode.large.motiveLevel.eval levels)) + (hminors : shape.MinorValuesFit constants (ElimMode.large.sourceArgs levels) (Telescope.extend (fun _ => empty) ps) + (ElimMode.large.motiveLevel.eval levels) m minors) : + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs) + (shape.ruleLhsBody source recursor .large i ctor) = + interp reading levels + (Telescope.extend (Telescope.extend (Telescope.extend (Telescope.extend (fun _ => empty) ps) (m :: minors)) xs) fs) + (shape.ruleRhsBody recursor .large i ctor) := by + rw [ruleLhsBody_interp h hr hmode hM hn hc hps hxs hfs hm hminors, + ruleRhsBody_interp h hr hmode hM hn hc hps hxs hfs hm hminors] + have hΓ := h.parameters.valid constants hM (ElimMode.large.sourceArgs levels) + (Context.valid_nil constants (ElimMode.large.sourceArgs levels) (fun _ => empty)) hps + have hD := container_wf h hM hΓ + have hlarge := container_large hmode hM hΓ + rw [recursorAt_large _ _ _ _ _ _ hD hlarge] + simp only [recursorCalls, recursorCall_large _ _ _ _ _ _ _ _ _ _ hD hlarge] + exact largeValue_iota h hM hΓ hm hminors hD hlarge hc hxs hfs + +end Ix.Theory.Certified.Ordinary.Shape diff --git a/Ix/Theory/Certified/Ordinary/Shape.lean b/Ix/Theory/Certified/Ordinary/Shape.lean new file mode 100644 index 000000000..7ae8b8037 --- /dev/null +++ b/Ix/Theory/Certified/Ordinary/Shape.lean @@ -0,0 +1,212 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Telescope +import Ix.Theory.Model.Support +import Ix.Theory.Store + +/-! +An executable producer for the ordinary container shape class. All ordinary +fields precede recursive fields. A recursive field is a dependent function +over checked external domains returning this family with the same parameters +and checked indices. Its domains and indices cannot depend on other recursive +fields. Exact source comparison, formation, and universe bounds are checked +here; publishing recursor equations requires the later realization producer. +-/ + +namespace Ix.Theory.Certified.Ordinary + +open Model + +universe u v + +structure RecursiveField (β : Type u) where + domains : List (AExpr β) + indices : List (AExpr β) +deriving DecidableEq + +structure Constructor (β : Type u) where + fields : List (AExpr β) + recursive : List (RecursiveField β) + indices : List (AExpr β) +deriving DecidableEq + +structure Shape (β : Type u) where + universes : Nat + parameters : List (AExpr β) + indices : List (AExpr β) + level : VLevel + constructors : List (Constructor β) +deriving DecidableEq + +variable {β : Type u} + +def parameterVars (offset : Nat) : Nat → List (AExpr β) + | 0 => [] + | n + 1 => .bvar (offset + n) :: parameterVars offset n + +@[simp] theorem erase_parameterVars (offset count : Nat) : + (parameterVars (β := β) offset count).map AExpr.erase = VExpr.bvarRevRange offset count := by + induction count <;> simp_all [parameterVars, VExpr.bvarRevRange, AExpr.erase] + +def Shape.familyApp (shape : Shape β) (source : β) (offset : Nat) + (indices : List (AExpr β)) : AExpr β := + .appN (.const (.member source 0) (VLevel.params shape.universes)) + (parameterVars offset shape.parameters.length ++ indices) + +def Shape.type (shape : Shape β) : AExpr β := + .forallN .never (shape.parameters ++ shape.indices) (.sort shape.level) + +def RecursiveField.type (field : RecursiveField β) (shape : Shape β) + (source : β) (ordinaryFields : Nat) : AExpr β := + .forallN (zeroCondition shape.level) field.domains + (shape.familyApp source (ordinaryFields + field.domains.length) field.indices) + +def recursiveTypesFrom (shape : Shape β) (source : β) (ordinaryFields : Nat) + (fields : List (RecursiveField β)) (offset : Nat) : List (AExpr β) := + (fields.zipIdx offset).map fun (field, previous) => + (field.type shape source ordinaryFields).liftN previous + +def Constructor.recursiveTypes (ctor : Constructor β) (shape : Shape β) (source : β) : List (AExpr β) := + recursiveTypesFrom shape source ctor.fields.length ctor.recursive 0 + +def Constructor.type (ctor : Constructor β) (shape : Shape β) (source : β) : AExpr β := + .forallN (zeroCondition shape.level) shape.parameters <| + .forallN (zeroCondition shape.level) ctor.fields <| + .forallN (zeroCondition shape.level) (ctor.recursiveTypes shape source) <| + shape.familyApp source (ctor.fields.length + ctor.recursive.length) + (ctor.indices.map (AExpr.liftN ctor.recursive.length ·)) + +def Constructor.source (ctor : Constructor β) (shape : Shape β) (source : β) : Ctor β := + ⟨shape.universes, shape.parameters.length, ctor.fields.length + ctor.recursive.length, + (ctor.type shape source).erase, .safe⟩ + +def Shape.source (shape : Shape β) (source : β) : Const β := + .induct shape.universes shape.parameters.length shape.indices.length shape.type.erase + (shape.constructors.map (Constructor.source · shape source)) .safe + +def Shape.references (shape : Shape β) (source : β) : List (ConstRef β) := + .member source 0 :: (List.range shape.constructors.length).map (.ctor source 0 ·) + +def Shape.parameterContext (shape : Shape β) : Context β := Telescope.context [] shape.parameters + +def Constructor.context (ctor : Constructor β) (shape : Shape β) : Context β := + Telescope.context shape.parameterContext ctor.fields + +def RecursiveEvidence (entries : Environment β) (shape : Shape β) (ctor : Constructor β) + (field : RecursiveField β) : Prop := + (∀ e ∈ field.domains ++ field.indices, e.ReferencesIn entries) ∧ + Telescope.Formed.{u,v} entries (ctor.context shape) field.domains ∧ + TelescopeBound.{u,v} entries (ctor.context shape) field.domains (some shape.level) ∧ + ArgumentsFit.{u,v} entries (Telescope.context (ctor.context shape) field.domains) + (Telescope.lift (ctor.fields.length + field.domains.length) shape.indices) field.indices + +def ConstructorEvidence (entries : Environment β) (shape : Shape β) (ctor : Constructor β) : Prop := + (∀ e ∈ ctor.fields ++ ctor.indices, e.ReferencesIn entries) ∧ + Telescope.Formed.{u,v} entries shape.parameterContext ctor.fields ∧ + TelescopeBound.{u,v} entries shape.parameterContext ctor.fields (some shape.level) ∧ + ArgumentsFit.{u,v} entries (ctor.context shape) + (Telescope.lift ctor.fields.length shape.indices) ctor.indices ∧ + ∀ field ∈ ctor.recursive, RecursiveEvidence.{u,v} entries shape ctor field + +/-- This is checked shape/formation evidence, not an admitted environment or +a premise asserting that an inductive has a model. -/ +structure CheckedShape (entries : Environment β) (store : Store β) (source : β) + (shape : Shape β) : Prop where + exactSource : store.blocks source = some ⟨[shape.source source]⟩ + fresh : ∀ r ∈ shape.references source, entries r = none + references : ∀ e ∈ shape.parameters ++ shape.indices, e.ReferencesIn entries + scope : shape.type.Scope shape.universes 0 + constructorScope : ∀ ctor ∈ shape.constructors, (ctor.type shape source).Scope shape.universes 0 + parameters : Telescope.Formed.{u,v} entries [] shape.parameters + indices : Telescope.Formed.{u,v} entries shape.parameterContext shape.indices + constructors : ∀ ctor ∈ shape.constructors, ConstructorEvidence.{u,v} entries shape ctor + +structure RecursiveWitness (β : Type u) where + domains : List (DomainWitness β) + indices : List (TypingWitness β) + +structure ConstructorWitness (β : Type u) where + fields : List (DomainWitness β) + indices : List (TypingWitness β) + recursive : List (RecursiveWitness β) + +structure ShapeWitness (β : Type u) where + shape : Shape β + parameters : List (DomainWitness β) + indices : List (DomainWitness β) + constructors : List (ConstructorWitness β) + +variable [DecidableEq β] + +def checkRecursive (fuel : Nat) (entries : Environment β) (shape : Shape β) + (ctor : Constructor β) : (fields : List (RecursiveField β)) → List (RecursiveWitness β) → + Option (CheckedClaim.{u} (∀ field ∈ fields, RecursiveEvidence.{u,v} entries shape ctor field)) + | [], [] => some ⟨by simp⟩ + | field :: fields, witness :: witnesses => + if hrefs : ∀ e ∈ field.domains ++ field.indices, e.ReferencesIn entries then do + let domains ← verifyTelescope.{u,v} fuel shape.universes entries (some shape.level) + (ctor.context shape) field.domains witness.domains + let indices ← verifyArguments.{u,v} fuel shape.universes entries + (Telescope.context (ctor.context shape) field.domains) + (Telescope.lift (ctor.fields.length + field.domains.length) shape.indices) + field.indices witness.indices + let rest ← checkRecursive fuel entries shape ctor fields witnesses + return ⟨by + intro field' hf + rcases List.mem_cons.mp hf with rfl | hf + · exact ⟨hrefs, domains.down.1, domains.down.2, indices.down⟩ + · exact rest.down field' hf⟩ + else none + | _, _ => none + +def checkConstructors (fuel : Nat) (entries : Environment β) (shape : Shape β) : + (ctors : List (Constructor β)) → List (ConstructorWitness β) → + Option (CheckedClaim.{u} (∀ ctor ∈ ctors, ConstructorEvidence.{u,v} entries shape ctor)) + | [], [] => some ⟨by simp⟩ + | ctor :: ctors, witness :: witnesses => + if hrefs : ∀ e ∈ ctor.fields ++ ctor.indices, e.ReferencesIn entries then do + let fields ← verifyTelescope.{u,v} fuel shape.universes entries (some shape.level) + shape.parameterContext ctor.fields witness.fields + let indices ← verifyArguments.{u,v} fuel shape.universes entries (ctor.context shape) + (Telescope.lift ctor.fields.length shape.indices) ctor.indices witness.indices + let recursive ← checkRecursive fuel entries shape ctor ctor.recursive witness.recursive + let rest ← checkConstructors fuel entries shape ctors witnesses + return ⟨by + intro ctor' hc + rcases List.mem_cons.mp hc with rfl | hc + · exact ⟨hrefs, fields.down.1, fields.down.2, indices.down, recursive.down⟩ + · exact rest.down ctor' hc⟩ + else none + | _, _ => none + +def checkShape (fuel : Nat) (entries : Environment β) (store : Store β) (source : β) + (witness : ShapeWitness β) : + Option (CheckedClaim.{u} (CheckedShape.{u,v} entries store source witness.shape)) := + let shape := witness.shape + if hs : store.blocks source = some ⟨[shape.source source]⟩ then + if hfresh : ∀ r ∈ shape.references source, entries r = none then + if hrefs : ∀ e ∈ shape.parameters ++ shape.indices, e.ReferencesIn entries then + if hscope : shape.type.Scope shape.universes 0 then + if hctors : ∀ ctor ∈ shape.constructors, (ctor.type shape source).Scope shape.universes 0 then do + let parameters ← verifyTelescope.{u,v} fuel shape.universes entries none [] + shape.parameters witness.parameters + let indices ← verifyTelescope.{u,v} fuel shape.universes entries none + shape.parameterContext shape.indices witness.indices + let constructors ← checkConstructors fuel entries shape shape.constructors witness.constructors + return ⟨⟨hs, hfresh, hrefs, hscope, hctors, + parameters.down.1, indices.down.1, constructors.down⟩⟩ + else none + else none + else none + else none + else none + +theorem checkShape_sound {fuel : Nat} {entries : Environment β} {store : Store β} {source : β} + {witness : ShapeWitness β} {result} + (_ : checkShape.{u,v} fuel entries store source witness = some result) : + CheckedShape.{u,v} entries store source witness.shape := result.down + +end Ix.Theory.Certified.Ordinary diff --git a/Ix/Theory/Certified/Policy.lean b/Ix/Theory/Certified/Policy.lean new file mode 100644 index 000000000..0b69e92aa --- /dev/null +++ b/Ix/Theory/Certified/Policy.lean @@ -0,0 +1,131 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Annotated +import Ix.Theory.Store + +/-! +# Primitive identity and the initial declaration policy + +The profile admits ordinary safe definitions, theorems and opaque declarations +only with a checked body. Initialization excludes object-language axioms; +the separate standard admission branch realizes supported exact schemas. Empty-inductive +primitives are selected by exact references and complete declaration shapes. +This is the policy/reading layer; the semantic checker must validate each body +before publishing a declaration as accepted. +-/ + +namespace Ix.Theory.Certified + +open Model + +universe u +variable {β : Type u} + +/-- The public configuration fixes these references. Diagnostic names and +semantic equality cannot select primitives or identify authenticated bytes. -/ +structure PrimitiveSignature (β : Type u) where + falseType : ConstRef β + falseElim : ConstRef β + distinct : falseType ≠ falseElim + natType : Option (ConstRef β) := none + +namespace PrimitiveSignature + +def falseExpr (signature : PrimitiveSignature β) : VExpr β := + .const signature.falseType [] + +/-- `False.rec.{u} : (motive : False → Sort u) → (x : False) → motive x`. -/ +def falseElimType (signature : PrimitiveSignature β) : VExpr β := + .forallE (.forallE signature.falseExpr (.sort (.param 0))) + (.forallE signature.falseExpr (.app (.bvar 1) (.bvar 0))) + +def falseDeclaration : Const β := .induct 0 0 0 (.sort .zero) [] .safe + +def falseElimDeclaration (signature : PrimitiveSignature β) : Const β := + .recursor 1 0 0 1 0 signature.falseElimType [] false .safe + +/-- A decidable match on the whole declaration, including rule and constructor +lists, safety, universe arity, and recursor counts. -/ +def validate [DecidableEq β] (signature : PrimitiveSignature β) (store : Store β) : Bool := + store.lookup signature.falseType == some falseDeclaration && + store.lookup signature.falseElim == some signature.falseElimDeclaration + +theorem validate_iff [DecidableEq β] (signature : PrimitiveSignature β) (store : Store β) : + signature.validate store = true ↔ + store.lookup signature.falseType = some falseDeclaration ∧ + store.lookup signature.falseElim = some signature.falseElimDeclaration := by + simp [validate] + +def rename (mapping : AddressEquiv β γ) (signature : PrimitiveSignature β) : + PrimitiveSignature γ where + falseType := signature.falseType.rename mapping + falseElim := signature.falseElim.rename mapping + distinct := fun h => signature.distinct (ConstRef.rename_injective mapping h) + natType := signature.natType.map (ConstRef.rename mapping) + +@[simp] theorem falseExpr_rename (mapping : AddressEquiv β γ) + (signature : PrimitiveSignature β) : + (signature.rename mapping).falseExpr = signature.falseExpr.rename mapping := rfl + +@[simp] theorem falseElimType_rename (mapping : AddressEquiv β γ) + (signature : PrimitiveSignature β) : + (signature.rename mapping).falseElimType = signature.falseElimType.rename mapping := rfl + +/-- The fixed annotation of the eliminator's type. The motive space is always +a positive sort; the remaining binders follow the result universe parameter. -/ +def falseElimReading (signature : PrimitiveSignature β) : AExpr β := + .forallE (.param 0) + (.forallE .never (.const signature.falseType []) (.sort (.param 0))) + (.forallE (.param 0) (.const signature.falseType []) (.app (.bvar 1) (.bvar 0))) + +@[simp] theorem erase_falseElimReading (signature : PrimitiveSignature β) : + signature.falseElimReading.erase = signature.falseElimType := rfl + +theorem falseElimReading_scoped (signature : PrimitiveSignature β) : + signature.falseElimReading.Scope 1 0 := by + simp [falseElimReading, AExpr.Scope, PropWhen.WF, PropWhen.param, VLevel.WF] + +end PrimitiveSignature + +/-- Data retained only after the declaration-kind and structural checks. +The body has not yet passed the semantic type checker. -/ +structure DefinitionReading (β : Type u) where + universes : Nat + kind : DefKind + type : AExpr β + body : AExpr β + typeScope : type.Scope universes 0 + bodyScope : body.Scope universes 0 + +def DefinitionReading.erase (entry : DefinitionReading β) : Const β := + .defn entry.universes entry.kind entry.type.erase entry.body.erase .safe + +/-- The definition-like declaration reading branch. Missing +opaque bodies, arbitrary axioms, unsafe declarations, and unmodeled primitive +kinds cannot acquire a successful reading through this function. -/ +def readDefinition? (source : Const β) (typeTree bodyTree : AnnotationTree) : + Option { entry : DefinitionReading β // entry.erase = source } := + match source with + | .defn n kind type body .safe => do + let type' ← readAnnotations? n 0 type typeTree + let body' ← readAnnotations? n 0 body bodyTree + return ⟨⟨n, kind, type'.val, body'.val, type'.property.2, body'.property.2⟩, + by simp [DefinitionReading.erase, type'.property.1, body'.property.1]⟩ + | _ => none + +theorem axiom_rejected (n : Nat) (type : VExpr β) (safety : Safety) + (typeTree bodyTree : AnnotationTree) : + readDefinition? (.axiom n type safety) typeTree bodyTree = none := rfl + +theorem unsafe_definition_rejected (n : Nat) (kind : DefKind) (type body : VExpr β) + (typeTree bodyTree : AnnotationTree) : + readDefinition? (.defn n kind type body .unsafe) typeTree bodyTree = none := rfl + +theorem partial_definition_rejected (n : Nat) (kind : DefKind) (type body : VExpr β) + (typeTree bodyTree : AnnotationTree) : + readDefinition? (.defn n kind type body .partial) typeTree bodyTree = none := rfl + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Prelude.lean b/Ix/Theory/Certified/Prelude.lean new file mode 100644 index 000000000..6fb0fd351 --- /dev/null +++ b/Ix/Theory/Certified/Prelude.lean @@ -0,0 +1,247 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Policy +import Ix.Theory.Model.Extension + +namespace Ix.Theory.Certified + +open Model Model.SetTheory Model.SetModel + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +namespace PrimitiveSignature + +variable (signature : PrimitiveSignature β) + +def falseEntry : ConstantEntry β := ⟨0, .sort .zero, none, [], []⟩ +def falseElimEntry : ConstantEntry β := ⟨1, signature.falseElimReading, none, [], []⟩ + +def environment [DecidableEq β] : Environment β := fun r => + if r = signature.falseType then some falseEntry + else if r = signature.falseElim then some signature.falseElimEntry + else none + +@[simp] theorem environment_false [DecidableEq β] : + signature.environment signature.falseType = some falseEntry := by + simp [environment] + +@[simp] theorem environment_falseElim [DecidableEq β] : + signature.environment signature.falseElim = some signature.falseElimEntry := by + simp [environment, Ne.symm signature.distinct] + +theorem environment_equations [DecidableEq β] {r : ConstRef β} {entry : ConstantEntry β} + (h : signature.environment r = some entry) : entry.equations = [] := by + unfold environment at h + split at h + · cases Option.some.inj h; rfl + · split at h + · cases Option.some.inj h; rfl + · contradiction + +def Present (entries : Environment β) : Prop := + entries signature.falseType = some falseEntry ∧ + entries signature.falseElim = some signature.falseElimEntry + +theorem environment_facts [DecidableEq β] {r : ConstRef β} {entry : ConstantEntry β} + (h : signature.environment r = some entry) : entry.facts = [] := by + unfold environment at h + split at h + · cases Option.some.inj h; rfl + · split at h + · cases Option.some.inj h; rfl + · contradiction + +theorem present_environment [DecidableEq β] : signature.Present signature.environment := + ⟨signature.environment_false, signature.environment_falseElim⟩ + +theorem Present.insert [DecidableEq β] {entries : Environment β} {r : ConstRef β} + {entry : ConstantEntry β} (h : signature.Present entries) (fresh : entries r = none) : + signature.Present (entries.insert r entry) := + ⟨Environment.insert_old fresh h.1, Environment.insert_old fresh h.2⟩ + +/-- Compatibility fixes primitive values in addition to declaration membership. +In particular, membership in Prop cannot choose the meaning of False. -/ +structure Compatible (entries : Environment β) (constants : Assignment β V) : Prop where + realizes : Realizes constants entries + falseValue : ∀ levels, constants signature.falseType levels = empty + falseElimValue : ∀ levels, + constants signature.falseElim levels = Model.falseElimValue (levels.getD 0 0) + +theorem Compatible.extend {entries entries' : Environment β} + {constants constants' : Assignment β V} + (h : signature.Compatible entries constants) (present : signature.Present entries) + (hM : Realizes constants' entries') + (agree : Assignment.AgreesOn entries constants constants') : + signature.Compatible entries' constants' where + realizes := hM + falseValue levels := (agree _ _ present.1 levels).trans (h.falseValue levels) + falseElimValue levels := (agree _ _ present.2 levels).trans (h.falseElimValue levels) + +noncomputable def assignment [DecidableEq β] : Assignment β V := fun r levels => + if r = signature.falseType then falseValue + else if r = signature.falseElim then falseElimValue (levels.getD 0 0) + else empty + +@[simp] theorem assignment_false [DecidableEq β] (levels : List Nat) : + signature.assignment signature.falseType levels = (empty : V) := by + simp [assignment, falseValue] + +@[simp] theorem assignment_falseElim [DecidableEq β] (levels : List Nat) : + signature.assignment signature.falseElim levels = (falseElimValue (levels.getD 0 0) : V) := by + simp [assignment, Ne.symm signature.distinct] + +theorem interp_falseElimReading (constants : Assignment β V) + (hfalse : constants signature.falseType [] = empty) + (levels : List Nat) (env : Nat → V) : + interp constants levels env signature.falseElimReading = + (Model.falseElimType (levels.getD 0 0) : V) := by + have hz : regime (.param 0) levels = 0 ↔ levels.getD 0 0 = 0 := + regime_zeroCondition (.param 0) levels + simp only [falseElimReading, interp, List.map_nil, hfalse, regime_never, + VLevel.eval, Valuation.cons_succ, Valuation.cons_zero, Model.falseElimType] + have hdom : piR 1 (empty : V) (fun _ => univ (levels.getD 0 0)) = + piR (levels.getD 0 0 + 1) empty (fun _ => univ (levels.getD 0 0)) := + piR_zero_agree (by simp) (fun _ _ => rfl) + rw [hdom] + apply piR_zero_agree hz + intro motive _ + exact piR_zero_agree hz (fun _ _ => rfl) + +theorem wellDenoted_falseElimReading (constants : Assignment β V) + (hfalse : constants signature.falseType [] = empty) + (levels : List Nat) (env : Nat → V) : + WellDenoted constants levels env signature.falseElimReading := by + have hz : regime (.param 0) levels = 0 ↔ levels.getD 0 0 = 0 := + regime_zeroCondition (.param 0) levels + simp only [falseElimReading, WellDenoted, interp, List.map_nil, hfalse, + regime_never, VLevel.eval, Valuation.cons_succ, Valuation.cons_zero] + refine ⟨⟨trivial, fun _ _ => trivial, levels.getD 0 0 + 1, by simp, + fun _ _ => univ_mem_univ _⟩, ?_, levels.getD 0 0, hz, ?_⟩ + · intro motive _ + exact ⟨trivial, fun x hx => (not_mem_empty x hx).elim, levels.getD 0 0, hz, + fun x hx => (not_mem_empty x hx).elim⟩ + · intro motive _ + have hpi := piR_mem_univ (V := V) (a := 0) (b := levels.getD 0 0) + (B := fun x => app motive x) (empty_mem_univ 0) + (fun x hx => (not_mem_empty x hx).elim) + rw [← piR_zero_agree hz (fun _ _ => rfl)] at hpi + have hi : VLevel.natIMax 0 (levels.getD 0 0) = levels.getD 0 0 := by + unfold VLevel.natIMax + split + · exact Eq.symm ‹_ = 0› + · exact Nat.zero_max _ + simpa only [hi] using hpi + +/-- A produced interpretation of the fixed, two-entry prelude. All later +declaration extensions must preserve these exact values. -/ +theorem realizes [DecidableEq β] : + Realizes (signature.assignment : Assignment β V) signature.environment := by + constructor + · intro r entry h levels _ env + unfold environment at h + split at h + next hr => + cases Option.some.inj h + exact trivial + next hr => + split at h + next he => + cases Option.some.inj h + exact signature.wellDenoted_falseElimReading _ (signature.assignment_false []) levels env + next => contradiction + · intro r entry h levels _ env + unfold environment at h + split at h + next hr => + subst r + cases Option.some.inj h + simpa only [assignment_false, falseEntry, interp, VLevel.eval] using + (empty_mem_univ 0 : (empty : V) ∈ˢ univ 0) + next hr => + split at h + next he => + subst r + cases Option.some.inj h + simp only [falseElimEntry, assignment_falseElim, + interp_falseElimReading _ _ (signature.assignment_false [])] + exact falseElimValue_mem _ + next => contradiction + · intro r entry h body hb levels _ env + unfold environment at h + split at h + · cases Option.some.inj h; contradiction + · split at h + · cases Option.some.inj h; contradiction + · contradiction + + · intro r entry h body hb levels _ env + unfold environment at h + split at h + · cases Option.some.inj h; contradiction + · split at h + · cases Option.some.inj h; contradiction + · contradiction + + · intro r entry h equation he + simp only [signature.environment_equations h, List.not_mem_nil] at he + + · intro r entry h fact hf + simp only [signature.environment_facts h, List.not_mem_nil] at hf + +theorem compatible_assignment [DecidableEq β] : + signature.Compatible signature.environment (signature.assignment : Assignment β V) := + ⟨signature.realizes, signature.assignment_false, signature.assignment_falseElim⟩ + +theorem environment_wf [DecidableEq β] : signature.environment.WF := by + have hrefs : signature.falseElimReading.ReferencesIn signature.environment := by + intro r hr + simp only [falseElimReading, AExpr.references, List.append_nil, + List.mem_append, List.mem_singleton, or_self] at hr + subst r + simp + constructor + · intro r entry h + unfold environment at h + split at h + · cases Option.some.inj h; exact trivial + · split at h + · cases Option.some.inj h; exact signature.falseElimReading_scoped + · contradiction + · intro r entry h body hb + unfold environment at h + split at h + · cases Option.some.inj h; contradiction + · split at h + · cases Option.some.inj h; contradiction + · contradiction + · intro r entry h + unfold environment at h + split at h + · cases Option.some.inj h + simp [falseEntry, AExpr.ReferencesIn, AExpr.references] + · split at h + · cases Option.some.inj h; exact hrefs + · contradiction + · intro r entry h body hb + unfold environment at h + split at h + · cases Option.some.inj h; contradiction + · split at h + · cases Option.some.inj h; contradiction + · contradiction + · intro r entry h equation he + simp only [signature.environment_equations h, List.not_mem_nil] at he + · intro r entry h equation he + simp only [signature.environment_equations h, List.not_mem_nil] at he + · intro r entry h fact hf + simp only [signature.environment_facts h, List.not_mem_nil] at hf + · intro r entry h fact hf + simp only [signature.environment_facts h, List.not_mem_nil] at hf + +end PrimitiveSignature + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/PropWhen.lean b/Ix/Theory/Certified/PropWhen.lean new file mode 100644 index 000000000..0c164d66a --- /dev/null +++ b/Ix/Theory/Certified/PropWhen.lean @@ -0,0 +1,330 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.VLevel + +/-! +# Checked zero conditions for anonymous universe parameters + +A condition is either never true or says that a finite set of parameter +indices are all zero. Strictly increasing lists give one representation for +each finite set. The empty set is the condition that always holds. + +These conditions describe only whether a level is zero. They do not identify +levels: for example, `Sort 1` and `Sort 2` both have condition `never`. +The decoder checks bounds independently, including for conditions that are +always false. Level well-formedness must also be checked on the source level. +-/ + +namespace Ix.Theory.Certified + +namespace IndexSet + +def insert (x : Nat) : List Nat → List Nat + | [] => [x] + | y :: ys => + if x < y then x :: y :: ys + else if x = y then y :: ys + else y :: insert x ys + +@[simp] theorem mem_insert {z x : Nat} {xs : List Nat} : + z ∈ insert x xs ↔ z = x ∨ z ∈ xs := by + induction xs with + | nil => simp [insert] + | cons y ys ih => + simp only [insert] + split + · simp + · split + · subst x; simp + · simp only [List.mem_cons, ih, or_left_comm] + +theorem sorted_insert {x : Nat} {xs : List Nat} + (h : xs.Pairwise (· < ·)) : (insert x xs).Pairwise (· < ·) := by + induction xs with + | nil => simp [insert] + | cons y ys ih => + obtain ⟨hy, hs⟩ := List.pairwise_cons.mp h + simp only [insert] + split + next hxy => + apply List.pairwise_cons.mpr + exact ⟨fun z hz => (List.mem_cons.mp hz).elim (fun e => e ▸ hxy) + (fun hz => Nat.lt_trans hxy (hy z hz)), h⟩ + next hxy => + split + · exact h + next hne => + apply List.pairwise_cons.mpr + refine ⟨?_, ih hs⟩ + intro z hz + rcases mem_insert.mp hz with rfl | hz + · omega + · exact hy z hz + +def normalize : List Nat → List Nat + | [] => [] + | x :: xs => insert x (normalize xs) + +@[simp] theorem mem_normalize {z : Nat} {xs : List Nat} : + z ∈ normalize xs ↔ z ∈ xs := by + induction xs <;> simp [normalize, *] + +theorem sorted_normalize (xs : List Nat) : (normalize xs).Pairwise (· < ·) := by + induction xs with + | nil => exact .nil + | cons x xs ih => exact sorted_insert ih + +/-- Equality of increasing lists is determined by their members. -/ +theorem eq_of_members {xs ys : List Nat} + (hx : xs.Pairwise (· < ·)) (hy : ys.Pairwise (· < ·)) + (hm : ∀ i, i ∈ xs ↔ i ∈ ys) : xs = ys := by + induction xs generalizing ys with + | nil => + symm + exact List.eq_nil_iff_forall_not_mem.mpr fun i hi => by simpa using (hm i).mpr hi + | cons x xs ih => + cases ys with + | nil => simpa using (hm x).mp (List.mem_cons_self ..) + | cons y ys => + obtain ⟨hxmin, hxs⟩ := List.pairwise_cons.mp hx + obtain ⟨hymin, hys⟩ := List.pairwise_cons.mp hy + have hxy : x = y := by + have hxmem := (hm x).mp (List.mem_cons_self ..) + have hymem := (hm y).mpr (List.mem_cons_self ..) + simp only [List.mem_cons] at hxmem hymem + rcases hxmem with h | h + · exact h + rcases hymem with h' | h' + · exact h'.symm + have := hxmin y h' + have := hymin x h + omega + subst y + congr 1 + apply ih hxs hys + intro i + have hxi : i ∈ xs → i ≠ x := fun hi e => by + have := hxmin i hi + omega + have hyi : i ∈ ys → i ≠ x := fun hi e => by + have := hymin i hi + omega + specialize hm i + simp only [List.mem_cons] at hm + by_cases hie : i = x + · subst i; simp_all + · simpa [hie] using hm + +end IndexSet + +inductive PropWhen where + | never + | allZero (params : List Nat) (sorted : params.Pairwise (· < ·)) +deriving DecidableEq, Repr + +namespace PropWhen + +def always : PropWhen := .allZero [] .nil + +def ofList (params : List Nat) : PropWhen := + .allZero (IndexSet.normalize params) (IndexSet.sorted_normalize params) + +def param (i : Nat) : PropWhen := .allZero [i] (by simp) + +def toRaw : PropWhen → Option (List Nat) + | .never => none + | .allZero ps _ => some ps + +theorem toRaw_injective {p q : PropWhen} (h : p.toRaw = q.toRaw) : p = q := by + cases p <;> cases q <;> simp_all [toRaw] + +def holds (valuation : Nat → Nat) : PropWhen → Bool + | .never => false + | .allZero ps _ => ps.all (valuation · == 0) + +@[simp] theorem holds_never (v : Nat → Nat) : holds v .never = false := rfl + +@[simp] theorem holds_always (v : Nat → Nat) : holds v always = true := rfl + +@[simp] theorem holds_param (v : Nat → Nat) (i : Nat) : + holds v (param i) = (v i == 0) := by simp [holds, param] + +@[simp] theorem holds_ofList (v : Nat → Nat) (ps : List Nat) : + holds v (ofList ps) = ps.all (v · == 0) := by + apply Bool.eq_iff_iff.mpr + simp [holds, ofList, List.all_eq_true] + +private theorem holds_separator (ps : List Nat) (hs : ps.Pairwise (· < ·)) (i : Nat) : + holds (fun j => if j = i then 1 else 0) (.allZero ps hs) = decide (i ∉ ps) := by + apply Bool.eq_iff_iff.mpr + simp only [holds, List.all_eq_true, beq_iff_eq, decide_eq_true_eq] + constructor + · intro h hi + have := h i hi + simp at this + · intro h j hj + have hji : j ≠ i := fun e => h (e ▸ hj) + simp [hji] + +/-- The representation is canonical, including the distinction between +`never` and a nonempty set of zero requirements. -/ +theorem eq_of_holds {p q : PropWhen} + (h : ∀ v : Nat → Nat, holds v p = holds v q) : p = q := by + cases p with + | never => + cases q with + | never => rfl + | allZero qs hq => simpa [holds] using h (fun _ => 0) + | allZero ps hp => + cases q with + | never => simpa [holds] using h (fun _ => 0) + | allZero qs hq => + have hm : ∀ i, i ∈ ps ↔ i ∈ qs := by + intro i + have hi := h (fun j => if j = i then 1 else 0) + rw [holds_separator, holds_separator] at hi + have hn : i ∉ ps ↔ i ∉ qs := by simpa using Bool.eq_iff_iff.mp hi + by_cases hp' : i ∈ ps <;> by_cases hq' : i ∈ qs <;> simp_all + have := IndexSet.eq_of_members hp hq hm + subst qs + rfl + +theorem eq_iff_holds (p q : PropWhen) : + p = q ↔ ∀ v : Nat → Nat, holds v p = holds v q := + ⟨fun h _ => h ▸ rfl, eq_of_holds⟩ + +/-- All named parameters are in scope; this is separate from the zero test. -/ +def WF (n : Nat) : PropWhen → Prop + | .never => True + | .allZero ps _ => ∀ i ∈ ps, i < n + +instance {n : Nat} {p : PropWhen} : Decidable (WF n p) := by + cases p <;> unfold WF <;> infer_instance + +/-- Decode the canonical representation. Malformed ordering and out-of-range +indices are rejected, rather than silently normalized or defaulted to zero. -/ +def fromRaw? (n : Nat) : Option (List Nat) → Option PropWhen + | none => some .never + | some ps => + if hs : ps.Pairwise (· < ·) then + if ∀ i ∈ ps, i < n then some (.allZero ps hs) else none + else none + +theorem fromRaw?_sound {n : Nat} {raw : Option (List Nat)} {p : PropWhen} + (h : fromRaw? n raw = some p) : p.toRaw = raw ∧ p.WF n := by + cases raw with + | none => simp [fromRaw?] at h; subst p; simp [toRaw, WF] + | some ps => + simp only [fromRaw?] at h + split at h + · split at h + next hb => cases h; exact ⟨rfl, hb⟩ + · contradiction + · contradiction + +theorem fromRaw?_complete {n : Nat} {p : PropWhen} (h : p.WF n) : + fromRaw? n p.toRaw = some p := by + cases p with + | never => rfl + | allZero ps hs => simp_all [fromRaw?, toRaw, WF] + +def inter : PropWhen → PropWhen → PropWhen + | .allZero ps _, .allZero qs _ => ofList (ps ++ qs) + | _, _ => .never + +@[simp] theorem holds_inter (v : Nat → Nat) (p q : PropWhen) : + holds v (inter p q) = (holds v p && holds v q) := by + apply Bool.eq_iff_iff.mpr + cases p <;> cases q <;> + simp [inter, holds, ofList, List.all_eq_true, or_imp, forall_and] + +theorem inter_comm (p q : PropWhen) : inter p q = inter q p := by + apply eq_of_holds; intro v; simp [Bool.and_comm] + +theorem inter_assoc (p q r : PropWhen) : inter (inter p q) r = inter p (inter q r) := by + apply eq_of_holds; intro v; simp [Bool.and_assoc] + +@[simp] theorem inter_always (p : PropWhen) : inter p always = p := by + apply eq_of_holds; intro v; simp + +@[simp] theorem always_inter (p : PropWhen) : inter always p = p := by + rw [inter_comm, inter_always] + +@[simp] theorem inter_self (p : PropWhen) : inter p p = p := by + apply eq_of_holds; intro v; simp + +theorem WF.inter {n : Nat} {p q : PropWhen} (hp : p.WF n) (hq : q.WF n) : + (p.inter q).WF n := by + cases p <;> cases q <;> + simp_all [PropWhen.inter, ofList, PropWhen.WF, or_imp] + +def bindList (f : Nat → PropWhen) : List Nat → PropWhen + | [] => always + | i :: ps => inter (f i) (bindList f ps) + +def bind (f : Nat → PropWhen) : PropWhen → PropWhen + | .never => .never + | .allZero ps _ => bindList f ps + +theorem holds_bindList (v : Nat → Nat) (f : Nat → PropWhen) (ps : List Nat) : + holds v (bindList f ps) = ps.all (fun i => holds v (f i)) := by + induction ps <;> simp [bindList, *] + +theorem holds_bind (v : Nat → Nat) (f : Nat → PropWhen) (p : PropWhen) : + holds v (bind f p) = holds (fun i => if holds v (f i) then 0 else 1) p := by + cases p with + | never => rfl + | allZero ps hs => + change holds v (bindList f ps) = + ps.all (fun i => (if holds v (f i) then 0 else 1) == 0) + rw [holds_bindList] + apply List.all_congr rfl + intro i + cases holds v (f i) <;> rfl + +theorem holds_bind_of (v w : Nat → Nat) (f : Nat → PropWhen) (p : PropWhen) + (h : ∀ i, holds v (f i) = (w i == 0)) : holds v (bind f p) = holds w p := by + cases p with + | never => rfl + | allZero ps hs => + change holds v (bindList f ps) = ps.all (w · == 0) + rw [holds_bindList] + exact List.all_congr rfl h + +@[simp] theorem bind_never (f : Nat → PropWhen) : bind f .never = .never := rfl + +@[simp] theorem bind_always (f : Nat → PropWhen) : bind f always = always := rfl + +@[simp] theorem bind_param (f : Nat → PropWhen) (i : Nat) : bind f (param i) = f i := by + simp [bind, param, bindList] + +theorem bind_inter (f : Nat → PropWhen) (p q : PropWhen) : + bind f (inter p q) = inter (bind f p) (bind f q) := by + apply eq_of_holds + intro v + simp only [holds_bind, holds_inter] + +@[simp] theorem bind_id (p : PropWhen) : bind param p = p := by + apply eq_of_holds + intro v + exact holds_bind_of v v param p (fun i => holds_param v i) + +theorem bindList_wf {n : Nat} {f : Nat → PropWhen} {ps : List Nat} + (h : ∀ i ∈ ps, (f i).WF n) : (bindList f ps).WF n := by + induction ps with + | nil => simp [bindList, always, WF] + | cons i ps ih => + exact WF.inter (h i (by simp)) (ih fun j hj => h j (by simp [hj])) + +theorem WF.bind {n k : Nat} {f : Nat → PropWhen} {p : PropWhen} + (hp : p.WF k) (h : ∀ i, i < k → (f i).WF n) : (bind f p).WF n := by + cases p with + | never => trivial + | allZero ps hs => exact bindList_wf fun i hi => h i (hp i hi) + +end PropWhen + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Quotient/Admission.lean b/Ix/Theory/Certified/Quotient/Admission.lean new file mode 100644 index 000000000..3359186dc --- /dev/null +++ b/Ix/Theory/Certified/Quotient/Admission.lean @@ -0,0 +1,57 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Admission + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +/-- Publish the exact quotient primitive package only after all source and +formation checks. Its values and computation laws are produced internally. -/ +def checkQuotientExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (witness : Quotient.Witness β) : + Option (CheckedExtension.{u,v} signature store state) := do + let checked ← Quotient.check.{u,v} fuel state.entries store witness + let refs := witness.refs + have extension : Extends.{u,v} signature state.entries (refs.environment state.entries) := by + constructor + · exact fun _ _ h => Quotient.environment_old checked.down h + · intro V _ constants hM + let constants' := refs.assignment constants + have ha := Quotient.assignment_agrees checked.down constants + have hm := Quotient.assignment_realizes checked.down state.wf constants hM.realizes + exact ⟨constants', hM.extend signature state.present hm ha, ha⟩ + let result : CheckedInterface signature := { + entries := refs.environment state.entries + wf := Quotient.environment_wf checked.down state.wf + present := ⟨extension.lookup _ _ state.present.1, extension.lookup _ _ state.present.2⟩ + } + return { + result, extension + source := by + intro r entry hr + dsimp only [result] at hr + rcases Quotient.environment_source checked.down hr with hold | hnew + · exact Or.inl hold + · exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inl hnew)))))) + } + +def admitQuotient? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : Quotient.Witness β) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkQuotientExtension?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +theorem admitQuotient?_extends {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {state : AdmittedEnvironment.{u,v} signature store} {witness : Quotient.Witness β} {result} + (_ : admitQuotient? fuel state witness = some result) : + Extends.{u,v} signature state.entries result.val.entries := result.property + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Quotient/Checked.lean b/Ix/Theory/Certified/Quotient/Checked.lean new file mode 100644 index 000000000..4179e66a5 --- /dev/null +++ b/Ix/Theory/Certified/Quotient/Checked.lean @@ -0,0 +1,179 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Quotient.Reading +import Ix.Theory.Certified.Signature + +namespace Ix.Theory.Certified.Quotient + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +theorem mem_kinds (kind : Kind) : kind ∈ kinds := by cases kind <;> simp [kinds] + +def Refs.header (refs : Refs β) (kind : Kind) : Signature.Header β := + ⟨refs.ref kind, kind.universes, refs.entryType kind⟩ + +def Refs.headers (refs : Refs β) : List (Signature.Header β) := kinds.map refs.header + +def Refs.typeEnvironment (refs : Refs β) (entries : Environment β) : Environment β := + Signature.environment entries refs.headers + +def Refs.liftRule (refs : Refs β) : Signature.Rule β := + ⟨2, liftRuleType refs, liftRuleLhs refs, liftRuleRhs refs⟩ + +def Refs.indRule (refs : Refs β) : Signature.Rule β := + ⟨1, indRuleType refs, indRuleLhs refs, indRuleRhs refs⟩ + +def Refs.ExactSource (refs : Refs β) (store : Store β) : Prop := + ∀ kind ∈ kinds, store.lookup (refs.ref kind) = some (refs.source kind) + +def Refs.Fresh (refs : Refs β) (entries : Environment β) : Prop := + ∀ kind ∈ kinds, entries (refs.ref kind) = none + +instance (refs : Refs β) (store : Store β) : Decidable (refs.ExactSource store) := + inferInstanceAs (Decidable (∀ kind ∈ kinds, store.lookup (refs.ref kind) = some (refs.source kind))) + +instance (refs : Refs β) (entries : Environment β) : Decidable (refs.Fresh entries) := + inferInstanceAs (Decidable (∀ kind ∈ kinds, entries (refs.ref kind) = none)) + +structure Witness (β : Type u) where + refs : Refs β + types : List (Signature.TypeWitness β) + liftRule : Signature.RuleWitness β + indRule : Signature.RuleWitness β + +structure Checked (entries : Environment β) (store : Store β) (refs : Refs β) : Prop where + exactSource : refs.ExactSource store + fresh : refs.Fresh entries + equality : Basis.Equality.Interface entries refs.eq refs.eqRefl refs.eqRec + types : Signature.Formed.{u,v} entries refs.headers + liftRule : Signature.RuleFormed.{u,v} (refs.typeEnvironment entries) refs.liftRule + indRule : Signature.RuleFormed.{u,v} (refs.typeEnvironment entries) refs.indRule + +def check (fuel : Nat) (entries : Environment β) (store : Store β) (witness : Witness β) : + Option (CheckedClaim.{u} (Checked.{u,v} entries store witness.refs)) := + if hs : witness.refs.ExactSource store then + if hf : witness.refs.Fresh entries then + if he : Basis.Equality.Interface entries witness.refs.eq witness.refs.eqRefl witness.refs.eqRec then do + let ht ← Signature.checkTypes.{u,v} fuel entries witness.refs.headers witness.types + let hl ← Signature.checkRule.{u,v} fuel (witness.refs.typeEnvironment entries) witness.refs.liftRule witness.liftRule + let hi ← Signature.checkRule.{u,v} fuel (witness.refs.typeEnvironment entries) witness.refs.indRule witness.indRule + return ⟨⟨hs, hf, he, ht.down, hl.down, hi.down⟩⟩ + else none + else none + else none + +theorem check_sound {fuel : Nat} {entries : Environment β} {store : Store β} {witness : Witness β} + {result} (_ : check.{u,v} fuel entries store witness = some result) : + Checked.{u,v} entries store witness.refs := result.down + +omit [DecidableEq β] in +theorem Refs.ExactSource.injective {refs : Refs β} {store : Store β} (h : refs.ExactSource store) : + Function.Injective refs.ref := by + intro a b he + have ha := h a (mem_kinds a) + have hb := h b (mem_kinds b) + rw [he, hb] at ha + have hs := Option.some.inj ha + cases a <;> cases b <;> simp [Refs.source] at hs <;> rfl + +def Refs.kind? (refs : Refs β) (r : ConstRef β) : Option Kind := + if r = refs.type then some .type else + if r = refs.ctor then some .ctor else + if r = refs.lift then some .lift else + if r = refs.ind then some .ind else + if r = refs.sound then some .sound else none + +theorem Refs.kind?_same {refs : Refs β} {store : Store β} (h : refs.ExactSource store) (kind : Kind) : + refs.kind? (refs.ref kind) = some kind := by + have he (a b : Kind) (hne : a ≠ b) : refs.ref a ≠ refs.ref b := fun hab => hne (h.injective hab) + have ht := he .ctor .type (by decide) + have hlt := he .lift .type (by decide) + have hlc := he .lift .ctor (by decide) + have hit := he .ind .type (by decide) + have hic := he .ind .ctor (by decide) + have hil := he .ind .lift (by decide) + have hst := he .sound .type (by decide) + have hsc := he .sound .ctor (by decide) + have hsl := he .sound .lift (by decide) + have hsi := he .sound .ind (by decide) + cases kind <;> simp_all [Refs.kind?, Refs.ref] + +theorem Refs.kind?_sound {refs : Refs β} {r : ConstRef β} {kind : Kind} + (h : refs.kind? r = some kind) : r = refs.ref kind := by + unfold Refs.kind? at h + split at h + · cases Option.some.inj h; assumption + · split at h + · cases Option.some.inj h; assumption + · split at h + · cases Option.some.inj h; assumption + · split at h + · cases Option.some.inj h; assumption + · split at h + · cases Option.some.inj h; assumption + · contradiction + +variable {entries : Environment β} {store : Store β} {refs : Refs β} + +theorem typeEnvironment_lookup (h : Checked.{u,v} entries store refs) (kind : Kind) : + refs.typeEnvironment entries (refs.ref kind) = some (refs.header kind).entry := + h.types.lookup (List.mem_map.mpr ⟨kind, mem_kinds kind, rfl⟩) + +variable {V : Type v} [SetTheory V] + +noncomputable def Refs.assignment (refs : Refs β) (constants : Assignment β V) : Assignment β V := + fun r levels => match refs.kind? r with + | some kind => refs.value constants kind levels + | none => constants r levels + +theorem assignment_same (h : Checked.{u,v} entries store refs) (constants : Assignment β V) + (kind : Kind) (levels : List Nat) : + refs.assignment constants (refs.ref kind) levels = refs.value constants kind levels := by + simp only [Refs.assignment, Refs.kind?_same h.exactSource] + +theorem assignment_agrees (h : Checked.{u,v} entries store refs) (constants : Assignment β V) : + Assignment.AgreesOn entries constants (refs.assignment constants) := by + intro r entry hr levels + unfold Refs.assignment + cases hk : refs.kind? r with + | none => rfl + | some kind => + have he := Refs.kind?_sound hk + have hf := h.fresh kind (mem_kinds kind) + rw [← he, hr] at hf + contradiction + +theorem assignment_reading (h : Checked.{u,v} entries store refs) (constants : Assignment β V) : + Reading (refs.assignment constants) refs := by + have heq (levels) : refs.assignment constants refs.eq levels = constants refs.eq levels := by + obtain ⟨entry, he, _, _⟩ := h.equality.former + exact assignment_agrees h constants _ _ he levels + constructor + · intro u + exact assignment_same h constants .type [u] + · intro u + exact assignment_same h constants .ctor [u] + · intro u v + rw [show refs.lift = refs.ref .lift from rfl, assignment_same h constants] + simp [Refs.value, liftValue, invariantSet, Basis.Equality.value, heq] + · intro u + exact assignment_same h constants .ind [u] + · intro u + exact assignment_same h constants .sound [u] + +theorem typeAssignment_realizes (h : Checked.{u,v} entries store refs) (hE : entries.WF) + (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (refs.assignment constants) (refs.typeEnvironment entries) := by + have hm := hM.of_agrees hE (assignment_agrees h constants) + apply h.types.realizes hm + intro header hh levels hn env + obtain ⟨kind, _, rfl⟩ := List.mem_map.mp hh + exact value_mem (assignment_reading h constants) h.equality hm kind levels hn env + +end Ix.Theory.Certified.Quotient diff --git a/Ix/Theory/Certified/Quotient/Publish.lean b/Ix/Theory/Certified/Quotient/Publish.lean new file mode 100644 index 000000000..938df6a02 --- /dev/null +++ b/Ix/Theory/Certified/Quotient/Publish.lean @@ -0,0 +1,195 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Quotient.Checked + +namespace Ix.Theory.Certified.Quotient + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +def Refs.environment (refs : Refs β) (entries : Environment β) : Environment β := + fun r => match refs.kind? r with + | some kind => some (refs.entry kind) + | none => entries r + +variable {entries : Environment β} {store : Store β} {refs : Refs β} + +theorem environment_same (h : Checked.{u,v} entries store refs) (kind : Kind) : + refs.environment entries (refs.ref kind) = some (refs.entry kind) := by + simp only [Refs.environment, Refs.kind?_same h.exactSource] + +theorem environment_old (h : Checked.{u,v} entries store refs) {r : ConstRef β} + {entry : ConstantEntry β} (hr : entries r = some entry) : refs.environment entries r = some entry := by + unfold Refs.environment + cases hk : refs.kind? r with + | none => exact hr + | some kind => + have he := Refs.kind?_sound hk + have hf := h.fresh kind (mem_kinds kind) + rw [← he, hr] at hf + contradiction + +theorem environment_cases {r : ConstRef β} {entry : ConstantEntry β} + (hr : refs.environment entries r = some entry) : + entries r = some entry ∨ ∃ kind, r = refs.ref kind ∧ entry = refs.entry kind := by + unfold Refs.environment at hr + split at hr + · exact Or.inr ⟨_, Refs.kind?_sound ‹_›, (Option.some.inj hr).symm⟩ + · exact Or.inl hr + +theorem environment_covers_types (h : Checked.{u,v} entries store refs) {r : ConstRef β} + {entry : ConstantEntry β} (hr : refs.typeEnvironment entries r = some entry) : + (refs.environment entries r).isSome := by + rcases Signature.environment_source hr with hold | ⟨header, hm, he, _⟩ + · simp only [environment_old h hold, Option.isSome_some] + · obtain ⟨kind, _, rfl⟩ := List.mem_map.mp hm + subst r + simp only [Refs.header, environment_same h, Option.isSome_some] + +theorem references_from_types (h : Checked.{u,v} entries store refs) {e : AExpr β} + (hr : e.ReferencesIn (refs.typeEnvironment entries)) : e.ReferencesIn (refs.environment entries) := by + intro r he + have hh := hr r he + cases ht : refs.typeEnvironment entries r with + | none => simp [ht] at hh + | some entry => exact environment_covers_types h ht + +theorem references_from_old (h : Checked.{u,v} entries store refs) {e : AExpr β} + (hr : e.ReferencesIn entries) : e.ReferencesIn (refs.environment entries) := by + intro r he + have hh := hr r he + cases ht : entries r with + | none => simp [ht] at hh + | some entry => simp only [environment_old h ht, Option.isSome_some] + +theorem fact_references_from_old (h : Checked.{u,v} entries store refs) {fact : ConstantFact β} + (hr : fact.ReferencesIn entries) : fact.ReferencesIn (refs.environment entries) := by + intro r he + have hh := hr r he + cases ht : entries r with + | none => simp [ht] at hh + | some entry => simp only [environment_old h ht, Option.isSome_some] + +theorem equation_scope (h : Checked.{u,v} entries store refs) (kind : Kind) + {law : ConstantEquation β} (hl : law ∈ refs.equations kind) : + law.lhs.Scope kind.universes 0 ∧ law.rhs.Scope kind.universes 0 := by + cases kind with + | type | ctor | sound => cases hl + | lift => + have he := List.mem_singleton.mp hl + subst law + exact h.liftRule.scope.2 + | ind => + have he := List.mem_singleton.mp hl + subst law + exact h.indRule.scope.2 + +theorem equation_references (h : Checked.{u,v} entries store refs) (kind : Kind) + {law : ConstantEquation β} (hl : law ∈ refs.equations kind) : + law.lhs.ReferencesIn (refs.environment entries) ∧ law.rhs.ReferencesIn (refs.environment entries) := by + cases kind with + | type | ctor | sound => cases hl + | lift => + have he := List.mem_singleton.mp hl + subst law + exact ⟨references_from_types h h.liftRule.references.2.1, references_from_types h h.liftRule.references.2.2⟩ + | ind => + have he := List.mem_singleton.mp hl + subst law + exact ⟨references_from_types h h.indRule.references.2.1, references_from_types h h.indRule.references.2.2⟩ + +theorem entry_closed (h : Checked.{u,v} entries store refs) (hE : entries.WF) (kind : Kind) : + EntryClosed (refs.environment entries) (refs.entry kind) := by + have ht := h.types.wf hE + have hl := typeEnvironment_lookup h kind + constructor + · exact ht.typeScope _ (refs.header kind).entry hl + · intro body hb; cases hb + · exact references_from_types h (ht.typeReferences _ (refs.header kind).entry hl) + · intro body hb; cases hb + · exact fun _ hh => equation_scope h kind hh + · exact fun _ hh => equation_references h kind hh + · intro fact hf; cases hf + · intro fact hf; cases hf + +theorem environment_wf (h : Checked.{u,v} entries store refs) (hE : entries.WF) : + (refs.environment entries).WF := by + have hc : ∀ r entry, refs.environment entries r = some entry → EntryClosed (refs.environment entries) entry := by + intro r entry hr + rcases environment_cases hr with hold | ⟨kind, _, rfl⟩ + · exact ⟨hE.typeScope _ _ hold, hE.bodyScope _ _ hold, + references_from_old h (hE.typeReferences _ _ hold), + fun body hb => references_from_old h (hE.bodyReferences _ _ hold body hb), + hE.equationScope _ _ hold, + fun law hl => ⟨references_from_old h (hE.equationReferences _ _ hold law hl).1, + references_from_old h (hE.equationReferences _ _ hold law hl).2⟩, + hE.factScope _ _ hold, + fun fact hf => fact_references_from_old h (hE.factReferences _ _ hold fact hf)⟩ + · exact entry_closed h hE kind + exact ⟨fun r e hr => (hc r e hr).typeScope, fun r e hr => (hc r e hr).bodyScope, + fun r e hr => (hc r e hr).typeReferences, fun r e hr => (hc r e hr).bodyReferences, + fun r e hr => (hc r e hr).equationScope, fun r e hr => (hc r e hr).equationReferences, + fun r e hr => (hc r e hr).factScope, fun r e hr => (hc r e hr).factReferences⟩ + +/-- The exact five source declarations, including the safe soundness axiom, +determine each published type and computation equation. -/ +def EntrySource (store : Store β) (r : ConstRef β) (entry : ConstantEntry β) : Prop := + ∃ refs : Refs β, ∃ kind, refs.ExactSource store ∧ r = refs.ref kind ∧ entry = refs.entry kind + +theorem environment_source (h : Checked.{u,v} entries store refs) {r : ConstRef β} {entry : ConstantEntry β} + (hr : refs.environment entries r = some entry) : entries r = some entry ∨ EntrySource store r entry := by + rcases environment_cases hr with hold | ⟨kind, he, hv⟩ + · exact Or.inl hold + · exact Or.inr ⟨refs, kind, h.exactSource, he, hv⟩ + +variable {V : Type v} [SetTheory V] + +theorem equation_value (h : Checked.{u,v} entries store refs) (hE : entries.WF) + (constants : Assignment β V) (hM : Realizes constants entries) (kind : Kind) + {law : ConstantEquation β} (hl : law ∈ refs.equations kind) + (levels : List Nat) (hn : levels.length = kind.universes) (env : Nat → V) : + interp (refs.assignment constants) levels env law.lhs = interp (refs.assignment constants) levels env law.rhs := by + cases kind with + | type | ctor | sound => cases hl + | lift => + have he := List.mem_singleton.mp hl + subst law + cases levels with + | nil => cases hn + | cons u tail => + obtain ⟨v, rfl⟩ := List.length_eq_one_iff.mp (Nat.succ.inj hn) + exact liftRule_eq (assignment_reading h constants) h.equality + (hM.of_agrees hE (assignment_agrees h constants)) u v env + | ind => + have he := List.mem_singleton.mp hl + subst law + exact indRule_eq _ _ _ _ + +theorem assignment_realizes (h : Checked.{u,v} entries store refs) (hE : entries.WF) + (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (refs.assignment constants) (refs.environment entries) := by + have hs := typeAssignment_realizes h hE constants hM + have ho := hM.of_agrees hE (assignment_agrees h constants) + have he : ∀ r entry, refs.environment entries r = some entry → EntryRealization (refs.assignment constants) r entry := by + intro r entry hr + rcases environment_cases hr with hold | ⟨kind, rfl, rfl⟩ + · exact ⟨ho.typeValid _ _ hold, ho.member _ _ hold, ho.bodyValid _ _ hold, + ho.bodyValue _ _ hold, ho.equationValue _ _ hold, ho.factMeaning _ _ hold⟩ + · have ht := typeEnvironment_lookup h kind + constructor + · exact hs.typeValid _ (refs.header kind).entry ht + · exact hs.member _ (refs.header kind).entry ht + · intro body hb; cases hb + · intro body hb; cases hb + · exact fun law hl => equation_value h hE constants hM kind hl + · intro fact hf; cases hf + exact ⟨fun r e hr => (he r e hr).typeValid, fun r e hr => (he r e hr).member, + fun r e hr => (he r e hr).bodyValid, fun r e hr => (he r e hr).bodyValue, + fun r e hr => (he r e hr).equationValue, fun r e hr => (he r e hr).factMeaning⟩ + +end Ix.Theory.Certified.Quotient diff --git a/Ix/Theory/Certified/Quotient/Reading.lean b/Ix/Theory/Certified/Quotient/Reading.lean new file mode 100644 index 000000000..3a0706afc --- /dev/null +++ b/Ix/Theory/Certified/Quotient/Reading.lean @@ -0,0 +1,184 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Quotient.Value + +namespace Ix.Theory.Certified.Quotient + +open Model Model.SetTheory Model.SetModel + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +noncomputable def Refs.value (refs : Refs β) (constants : Assignment β V) + (kind : Kind) (levels : List Nat) : V := + match kind with + | .type => formerValue (levels.getD 0 0) + | .ctor => constructorValue (levels.getD 0 0) + | .lift => liftValue constants refs.eq (levels.getD 0 0) (levels.getD 1 0) + | .ind | .sound => pt + +/-- This reading is proved for the internally constructed assignment. It is +not a field of an input certificate. -/ +structure Reading (constants : Assignment β V) (refs : Refs β) : Prop where + former : ∀ u, constants refs.type [u] = formerValue u + ctor : ∀ u, constants refs.ctor [u] = constructorValue u + lift : ∀ u v, constants refs.lift [u, v] = liftValue constants refs.eq u v + ind : ∀ u, constants refs.ind [u] = pt + sound : ∀ u, constants refs.sound [u] = pt + +noncomputable def formerAt (constants : Assignment β V) (refs : Refs β) (u : Nat) (A R : V) : V := + app (app (constants refs.type [u]) A) R + +noncomputable def constructorAt (constants : Assignment β V) (refs : Refs β) (u : Nat) (A R a : V) : V := + app (app (app (constants refs.ctor [u]) A) R) a + +variable {constants : Assignment β V} {refs : Refs β} + +theorem formerAt_eq (h : Reading constants refs) {u : Nat} {A R : V} + (hA : A ∈ˢ univ u) (hR : R ∈ˢ relationSet A) : formerAt constants refs u A R = quotSet u A R := by + rw [formerAt, h.former] + exact formerValue_apply hA hR + +theorem constructorAt_eq (h : Reading constants refs) {u : Nat} {A R a : V} + (hA : A ∈ˢ univ u) (hR : R ∈ˢ relationSet A) (ha : a ∈ˢ A) : + constructorAt constants refs u A R a = quotClass u A R a := by + rw [constructorAt, h.ctor] + exact constructorValue_apply hA hR ha + +theorem typeType_interp (constants : Assignment β V) (u : Nat) (env : Nat → V) : + interp constants [u] env (typeType : AExpr β) = formerSet u := by + simp [typeType, relationType, formerSet, relationSet, interp, VLevel.eval, Valuation.cons, univ_zero] + +theorem ctorType_interp (h : Reading constants refs) (u : Nat) (env : Nat → V) : + interp constants [u] env (ctorType refs) = constructorSet u := by + simp [ctorType, applied, AExpr.appN, relationType, interp, VLevel.eval, Valuation.cons, regime, PropWhen.param, PropWhen.holds, univ_zero] + change piR (bit u) (univ u) (fun A => piR (bit u) (relationSet A) (fun R => + piR (bit u) A (fun _ => formerAt constants refs u A R))) = constructorSet u + apply piR_congr + intro A hA + apply piR_congr + intro R hR + simp only [formerAt_eq h hA hR] + +theorem liftType_interp (h : Reading constants refs) (u v : Nat) (env : Nat → V) : + interp constants [u, v] env (liftType refs) = liftSet constants refs.eq u v := by + simp [liftType, liftPrefix, AExpr.forallN, invariantType, Basis.Equality.applied, + relationType, applied, AExpr.appN, interp, VLevel.eval, + Valuation.cons, regime, PropWhen.param, PropWhen.holds, univ_zero] + change piR (bit v) (univ u) (fun A => piR (bit v) (relationSet A) (fun R => + piR (bit v) (univ v) (fun B => piR (bit v) (piR (bit v) A (fun _ => B)) (fun f => + piR (bit v) (invariantSet constants refs.eq v A R B f) (fun _ => + piR (bit v) (formerAt constants refs u A R) (fun _ => B)))))) = liftSet constants refs.eq u v + apply piR_congr + intro A hA + apply piR_congr + intro R hR + simp only [formerAt_eq h hA hR] + +theorem indType_interp (h : Reading constants refs) (u : Nat) (env : Nat → V) : + interp constants [u] env (indType refs) = indSet u := by + simp [indType, indPrefix, AExpr.forallN, relationType, applied, constructed, AExpr.appN, + interp, VLevel.eval, Valuation.cons, + regime, PropWhen.holds, univ_zero] + change piR 0 (univ u) (fun A => piR 0 (relationSet A) (fun R => + piR 0 (piR 1 (formerAt constants refs u A R) (fun _ => univZero)) (fun motive => + piR 0 (piR 0 A (fun a => app motive (constructorAt constants refs u A R a))) (fun _ => + piR 0 (formerAt constants refs u A R) (fun q => app motive q))))) = indSet u + apply piR_congr + intro A hA + apply piR_congr + intro R hR + simp only [formerAt_eq h hA hR] + apply piR_congr + intro motive _ + have he : piR 0 A (fun a => app motive (constructorAt constants refs u A R a)) = + piR 0 A (fun a => app motive (quotClass u A R a)) := by + apply piR_congr + intro a ha + rw [constructorAt_eq h hA hR ha] + rw [he] + +theorem soundType_interp (h : Reading constants refs) (u : Nat) (env : Nat → V) : + interp constants [u] env (soundType refs) = soundSet constants refs.eq u := by + simp [soundType, relationType, applied, constructed, Basis.Equality.applied, AExpr.appN, + interp, VLevel.eval, Valuation.cons, + regime, PropWhen.holds, univ_zero] + change piR 0 (univ u) (fun A => piR 0 (relationSet A) (fun R => + piR 0 A (fun a => piR 0 A (fun b => piR 0 (app (app R a) b) (fun _ => + Basis.Equality.value constants refs.eq u (formerAt constants refs u A R) + (constructorAt constants refs u A R a) (constructorAt constants refs u A R b)))))) = + soundSet constants refs.eq u + apply piR_congr + intro A hA + apply piR_congr + intro R hR + apply piR_congr + intro a ha + apply piR_congr + intro b hb + simp only [formerAt_eq h hA hR, constructorAt_eq h hA hR ha, constructorAt_eq h hA hR hb] + +theorem value_mem {entries : Environment β} (h : Reading constants refs) + (hE : Basis.Equality.Interface entries refs.eq refs.eqRefl refs.eqRec) (hM : Realizes constants entries) + (kind : Kind) (levels : List Nat) (hn : levels.length = kind.universes) (env : Nat → V) : + constants (refs.ref kind) levels ∈ˢ interp constants levels env (refs.entryType kind) := by + cases kind with + | type => + obtain ⟨u, rfl⟩ := List.length_eq_one_iff.mp hn + rw [Refs.ref, h.former, Refs.entryType, typeType_interp] + exact formerValue_mem u + | ctor => + obtain ⟨u, rfl⟩ := List.length_eq_one_iff.mp hn + rw [Refs.ref, h.ctor, Refs.entryType, ctorType_interp h] + exact constructorValue_mem u + | lift => + cases levels with + | nil => cases hn + | cons u tail => + obtain ⟨v, rfl⟩ := List.length_eq_one_iff.mp (Nat.succ.inj hn) + rw [Refs.ref, h.lift, Refs.entryType, liftType_interp h] + exact liftValue_mem constants refs.eq u v + | ind => + obtain ⟨u, rfl⟩ := List.length_eq_one_iff.mp hn + rw [Refs.ref, h.ind, Refs.entryType, indType_interp h] + exact indValue_mem u + | sound => + obtain ⟨u, rfl⟩ := List.length_eq_one_iff.mp hn + rw [Refs.ref, h.sound, Refs.entryType, soundType_interp h] + exact soundValue_mem hE hM u + +/-- Equality of the complete lambda endpoints published as the primitive +computation law, for every environment and both universe regimes. -/ +theorem liftRule_eq {entries : Environment β} (h : Reading constants refs) + (hE : Basis.Equality.Interface entries refs.eq refs.eqRefl refs.eqRec) (hM : Realizes constants entries) + (u v : Nat) (env : Nat → V) : + interp constants [u, v] env (liftRuleLhs refs) = interp constants [u, v] env (liftRuleRhs refs) := by + simp [liftRuleLhs, liftRuleRhs, liftRuleBinders, liftPrefix, List.cons_append, List.nil_append, + AExpr.lamN, relationType, invariantType, Basis.Equality.applied, AExpr.appN, constructed, + interp, VLevel.eval, Valuation.cons, regime, PropWhen.param, PropWhen.holds, univ_zero] + apply lamR_congr + intro A hA + apply lamR_congr + intro R hR + apply lamR_congr + intro B hB + apply lamR_congr + intro f hf + apply lamR_congr + intro proof hp + apply lamR_congr + intro a ha + change app (app (app (app (app (app (constants refs.lift [u, v]) A) R) B) f) proof) + (constructorAt constants refs u A R a) = app f a + rw [h.lift, constructorAt_eq h hA hR ha] + exact liftValue_apply hE hM hA hR hB hf hp ha + +theorem indRule_eq (constants : Assignment β V) (refs : Refs β) (levels : List Nat) (env : Nat → V) : + interp constants levels env (indRuleLhs refs) = interp constants levels env (indRuleRhs refs) := by + simp only [indRuleLhs, indRuleRhs, indRuleBinders, indPrefix, List.cons_append, List.nil_append, + AExpr.lamN, interp, regime_always, lamR_zero] + +end Ix.Theory.Certified.Quotient diff --git a/Ix/Theory/Certified/Quotient/Syntax.lean b/Ix/Theory/Certified/Quotient/Syntax.lean new file mode 100644 index 000000000..b7499de97 --- /dev/null +++ b/Ix/Theory/Certified/Quotient/Syntax.lean @@ -0,0 +1,144 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Basis.Equality +import Ix.Theory.Quot + +namespace Ix.Theory.Certified.Quotient + +open Model + +universe u +variable {β : Type u} + +/-- The five quotient declarations are realized together. References may be +members of different authenticated blocks. Equality must already be admitted. -/ +structure Refs (β : Type u) extends Store.QuotRefs β where + eqRefl : ConstRef β + eqRec : ConstRef β + sound : ConstRef β + deriving DecidableEq + +inductive Kind where + | type | ctor | lift | ind | sound + deriving DecidableEq + +def kinds : List Kind := [.type, .ctor, .lift, .ind, .sound] + +def Refs.ref (refs : Refs β) : Kind → ConstRef β + | .type => refs.type + | .ctor => refs.ctor + | .lift => refs.lift + | .ind => refs.ind + | .sound => refs.sound + +def Kind.universes : Kind → Nat + | .lift => 2 + | _ => 1 + +def relationType : AExpr β := + .forallE .never (.bvar 0) (.forallE .never (.bvar 1) (.sort .zero)) + +def applied (refs : Refs β) (l : VLevel) (A R : AExpr β) : AExpr β := + .appN (.const refs.type [l]) [A, R] + +def constructed (refs : Refs β) (l : VLevel) (A R a : AExpr β) : AExpr β := + .appN (.const refs.ctor [l]) [A, R, a] + +def typeType : AExpr β := + .forallE .never (.sort (.param 0)) (.forallE .never relationType (.sort (.param 0))) + +def ctorType (refs : Refs β) : AExpr β := + .forallE (.param 0) (.sort (.param 0)) <| + .forallE (.param 0) relationType <| + .forallE (.param 0) (.bvar 1) <| + applied refs (.param 0) (.bvar 2) (.bvar 1) + +/-- In the context `A, R, B, f`, invariance of `f` under `R`. -/ +def invariantType (refs : Refs β) : AExpr β := + .forallE .always (.bvar 3) <| + .forallE .always (.bvar 4) <| + .forallE .always (.appN (.bvar 4) [.bvar 1, .bvar 0]) <| + Basis.Equality.applied refs.eq (.param 1) (.bvar 4) + (.app (.bvar 3) (.bvar 2)) (.app (.bvar 3) (.bvar 1)) + +def liftPrefix (refs : Refs β) : List (AExpr β) := + [.sort (.param 0), relationType, .sort (.param 1), + .forallE (.param 1) (.bvar 2) (.bvar 1), invariantType refs] + +def liftType (refs : Refs β) : AExpr β := + .forallN (.param 1) (liftPrefix refs) <| + .forallE (.param 1) (applied refs (.param 0) (.bvar 4) (.bvar 3)) (.bvar 3) + +def indPrefix (refs : Refs β) : List (AExpr β) := + [.sort (.param 0), relationType, + .forallE .never (applied refs (.param 0) (.bvar 1) (.bvar 0)) (.sort .zero), + .forallE .always (.bvar 2) + (.app (.bvar 1) (constructed refs (.param 0) (.bvar 3) (.bvar 2) (.bvar 0)))] + +def indType (refs : Refs β) : AExpr β := + .forallN .always (indPrefix refs) <| + .forallE .always (applied refs (.param 0) (.bvar 3) (.bvar 2)) (.app (.bvar 2) (.bvar 0)) + +def soundType (refs : Refs β) : AExpr β := + .forallE .always (.sort (.param 0)) <| + .forallE .always relationType <| + .forallE .always (.bvar 1) <| + .forallE .always (.bvar 2) <| + .forallE .always (.appN (.bvar 2) [.bvar 1, .bvar 0]) <| + Basis.Equality.applied refs.eq (.param 0) + (applied refs (.param 0) (.bvar 4) (.bvar 3)) + (constructed refs (.param 0) (.bvar 4) (.bvar 3) (.bvar 2)) + (constructed refs (.param 0) (.bvar 4) (.bvar 3) (.bvar 1)) + +def Refs.entryType (refs : Refs β) : Kind → AExpr β + | .type => typeType + | .ctor => ctorType refs + | .lift => liftType refs + | .ind => indType refs + | .sound => soundType refs + +def Refs.source (refs : Refs β) : Kind → Const β + | .type => .quot .type 1 typeType.erase + | .ctor => .quot .ctor 1 (ctorType refs).erase + | .lift => .quot .lift 2 (liftType refs).erase + | .ind => .quot .ind 1 (indType refs).erase + | .sound => .axiom 1 (soundType refs).erase .safe + +def liftRuleBinders (refs : Refs β) : List (AExpr β) := liftPrefix refs ++ [.bvar 4] +def liftRuleType (refs : Refs β) : AExpr β := .forallN (.param 1) (liftRuleBinders refs) (.bvar 3) +def liftRuleLhs (refs : Refs β) : AExpr β := + .lamN (.param 1) (liftRuleBinders refs) <| + .appN (.const refs.lift [.param 0, .param 1]) + [.bvar 5, .bvar 4, .bvar 3, .bvar 2, .bvar 1, + constructed refs (.param 0) (.bvar 5) (.bvar 4) (.bvar 0)] +def liftRuleRhs (refs : Refs β) : AExpr β := + .lamN (.param 1) (liftRuleBinders refs) (.app (.bvar 2) (.bvar 0)) + +def indRuleBinders (refs : Refs β) : List (AExpr β) := indPrefix refs ++ [.bvar 3] +def indRuleType (refs : Refs β) : AExpr β := + .forallN .always (indRuleBinders refs) <| + .app (.bvar 2) (constructed refs (.param 0) (.bvar 4) (.bvar 3) (.bvar 0)) +def indRuleLhs (refs : Refs β) : AExpr β := + .lamN .always (indRuleBinders refs) <| + .appN (.const refs.ind [.param 0]) [.bvar 4, .bvar 3, .bvar 2, .bvar 1, + constructed refs (.param 0) (.bvar 4) (.bvar 3) (.bvar 0)] +def indRuleRhs (refs : Refs β) : AExpr β := + .lamN .always (indRuleBinders refs) (.app (.bvar 1) (.bvar 0)) + +def Refs.equations (refs : Refs β) : Kind → List (ConstantEquation β) + | .lift => [⟨liftRuleLhs refs, liftRuleRhs refs⟩] + | .ind => [⟨indRuleLhs refs, indRuleRhs refs⟩] + | _ => [] + +def Refs.entry (refs : Refs β) (kind : Kind) : ConstantEntry β := + ⟨kind.universes, refs.entryType kind, none, refs.equations kind, []⟩ + +theorem typeType_erase : (typeType : AExpr β).erase = Store.Quotient.typeType := rfl +theorem ctorType_erase (refs : Refs β) : (ctorType refs).erase = Store.Quotient.ctorType refs.toQuotRefs := rfl +theorem liftType_erase (refs : Refs β) : (liftType refs).erase = Store.Quotient.liftType refs.toQuotRefs := rfl +theorem indType_erase (refs : Refs β) : (indType refs).erase = Store.Quotient.indType refs.toQuotRefs := rfl + +end Ix.Theory.Certified.Quotient diff --git a/Ix/Theory/Certified/Quotient/Value.lean b/Ix/Theory/Certified/Quotient/Value.lean new file mode 100644 index 000000000..45794753e --- /dev/null +++ b/Ix/Theory/Certified/Quotient/Value.lean @@ -0,0 +1,185 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Quotient.Syntax +import Ix.Theory.Model.SetTheory.Derive.Quot + +namespace Ix.Theory.Certified.Quotient + +open Model Model.SetTheory Model.SetModel + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +def bit (u : Nat) : Nat := if u = 0 then 0 else 1 + +noncomputable def relationSet (A : V) : V := + piR 1 A (fun _ => piR 1 A (fun _ => univZero)) + +noncomputable def formerValue (u : Nat) : V := + lamR 1 (univ u) (fun A => lamR 1 (relationSet A) (fun R => quotSet u A R)) + +noncomputable def constructorValue (u : Nat) : V := + lamR (bit u) (univ u) (fun A => lamR (bit u) (relationSet A) (fun R => + lamR (bit u) A (fun a => quotClass u A R a))) + +noncomputable def invariantSet (constants : Assignment β V) (eq : ConstRef β) + (v : Nat) (A R B f : V) : V := + piR 0 A (fun a => piR 0 A (fun b => piR 0 (app (app R a) b) + (fun _ => Basis.Equality.value constants eq v B (app f a) (app f b)))) + +noncomputable def liftValue (constants : Assignment β V) (eq : ConstRef β) (u v : Nat) : V := + lamR (bit v) (univ u) (fun A => lamR (bit v) (relationSet A) (fun R => + lamR (bit v) (univ v) (fun B => lamR (bit v) (piR (bit v) A (fun _ => B)) (fun f => + lamR (bit v) (invariantSet constants eq v A R B f) (fun _ => + lamR (bit v) (quotSet u A R) (fun q => app f (qrep u A R q))))))) + +noncomputable def formerSet (u : Nat) : V := + piR 1 (univ u) (fun A => piR 1 (relationSet A) (fun _ => univ u)) + +noncomputable def constructorSet (u : Nat) : V := + piR (bit u) (univ u) (fun A => piR (bit u) (relationSet A) (fun R => + piR (bit u) A (fun _ => quotSet u A R))) + +noncomputable def liftSet (constants : Assignment β V) (eq : ConstRef β) (u v : Nat) : V := + piR (bit v) (univ u) (fun A => piR (bit v) (relationSet A) (fun R => + piR (bit v) (univ v) (fun B => piR (bit v) (piR (bit v) A (fun _ => B)) (fun f => + piR (bit v) (invariantSet constants eq v A R B f) (fun _ => + piR (bit v) (quotSet u A R) (fun _ => B)))))) + +noncomputable def indSet (u : Nat) : V := + piR 0 (univ u) (fun A => piR 0 (relationSet A) (fun R => + piR 0 (piR 1 (quotSet u A R) (fun _ => univZero)) (fun motive => + piR 0 (piR 0 A (fun a => app motive (quotClass u A R a))) (fun _ => + piR 0 (quotSet u A R) (fun q => app motive q))))) + +noncomputable def soundSet (constants : Assignment β V) (eq : ConstRef β) (u : Nat) : V := + piR 0 (univ u) (fun A => piR 0 (relationSet A) (fun R => + piR 0 A (fun a => piR 0 A (fun b => piR 0 (app (app R a) b) (fun _ => + Basis.Equality.value constants eq u (quotSet u A R) + (quotClass u A R a) (quotClass u A R b)))))) + +theorem app_mem_bit {u : Nat} {A B f a : V} (hB : B ∈ˢ univ u) + (hf : f ∈ˢ piR (bit u) A (fun _ => B)) (ha : a ∈ˢ A) : app f a ∈ˢ B := by + apply app_mem_piR hf ha + intro hu _ _ + have he : u = 0 := by simpa [bit] using hu + simpa [he, univ_zero] using hB + +theorem formerValue_mem (u : Nat) : (formerValue u : V) ∈ˢ formerSet u := by + apply lamR_mem + intro A hA + exact lamR_mem fun _ _ => quotSet_mem_univ hA + +theorem constructorValue_mem (u : Nat) : (constructorValue u : V) ∈ˢ constructorSet u := by + apply lamR_mem + intro A _ + apply lamR_mem + intro R _ + exact lamR_mem fun _ ha => quotClass_mem ha + +theorem formerValue_apply {u : Nat} {A R : V} (hA : A ∈ˢ univ u) (hR : R ∈ˢ relationSet A) : + app (app (formerValue u) A) R = quotSet u A R := by + rw [formerValue, app_lamR_pos (by decide : 1 ≠ 0) hA, + app_lamR_pos (by decide : 1 ≠ 0) hR] + +theorem constructorValue_apply {u : Nat} {A R a : V} + (hA : A ∈ˢ univ u) (hR : R ∈ˢ relationSet A) (ha : a ∈ˢ A) : + app (app (app (constructorValue u) A) R) a = quotClass u A R a := by + by_cases hu : u = 0 + · subst u + simp [constructorValue, bit, lamR_zero, app_pt, quotClass] + · simp only [constructorValue, bit, if_neg hu] + rw [app_lamR_pos (by decide : 1 ≠ 0) hA, + app_lamR_pos (by decide : 1 ≠ 0) hR, app_lamR_pos (by decide : 1 ≠ 0) ha] + +theorem liftValue_mem (constants : Assignment β V) (eq : ConstRef β) (u v : Nat) : + liftValue constants eq u v ∈ˢ liftSet constants eq u v := by + apply lamR_mem + intro A _ + apply lamR_mem + intro R _ + apply lamR_mem + intro B hB + apply lamR_mem + intro f hf + apply lamR_mem + intro _ _ + apply lamR_mem + intro q hq + exact app_mem_bit hB hf (qrep_spec hq).1 + +theorem indValue_mem (u : Nat) : (pt : V) ∈ˢ indSet u := by + apply pt_mem_piR_zero_of + intro A _ + apply pt_mem_piR_zero_of + intro R _ + apply pt_mem_piR_zero_of + intro motive hm + apply pt_mem_piR_zero_of + intro f hf + apply pt_mem_piR_zero_of + intro q hq + obtain ⟨a, ha, rfl⟩ := quotClass_surj hq + have hprop : ∀ x, x ∈ˢ quotSet u A R → app motive x ∈ˢ univZero := + fun _ hx => app_mem_piR_pos (by decide : 1 ≠ 0) hm hx + have hf' : app f a ∈ˢ app motive (quotClass u A R a) := + app_mem_piR hf ha (fun _ a ha => hprop _ (quotClass_mem ha)) + rwa [eq_pt_of_mem_univZero (hprop _ (quotClass_mem ha)) hf'] at hf' + +theorem soundValue_mem {entries : Environment β} {constants : Assignment β V} {eq refl recursor : ConstRef β} + (hE : Basis.Equality.Interface entries eq refl recursor) (hM : Realizes constants entries) (u : Nat) : + (pt : V) ∈ˢ soundSet constants eq u := by + apply pt_mem_piR_zero_of + intro A hA + apply pt_mem_piR_zero_of + intro R _ + apply pt_mem_piR_zero_of + intro a ha + apply pt_mem_piR_zero_of + intro b hb + apply pt_mem_piR_zero_of + intro h hh + rw [Basis.Equality.value_eq_eqv hE hM (quotSet_mem_univ hA) (quotClass_mem ha) (quotClass_mem hb), + quotSound ha hb hh] + exact pt_mem_eqv_self _ + +theorem invariant_of_mem {entries : Environment β} {constants : Assignment β V} + {eq refl recursor : ConstRef β} (hE : Basis.Equality.Interface entries eq refl recursor) + (hM : Realizes constants entries) {v : Nat} {A R B f h : V} + (hB : B ∈ˢ univ v) (hf : f ∈ˢ piR (bit v) A (fun _ => B)) + (hh : h ∈ˢ invariantSet constants eq v A R B f) : + ∀ a b, a ∈ˢ A → b ∈ˢ A → (∃ w, w ∈ˢ app (app R a) b) → app f a = app f b := by + intro a b ha hb ⟨w, hw⟩ + obtain ⟨ha', hha⟩ := Basis.Equality.exists_of_mem_piR_zero hh ha + obtain ⟨hb', hhb⟩ := Basis.Equality.exists_of_mem_piR_zero hha hb + obtain ⟨q, hq⟩ := Basis.Equality.exists_of_mem_piR_zero hhb hw + exact Basis.Equality.eq_of_mem hE hM hB (app_mem_bit hB hf ha) (app_mem_bit hB hf hb) hq + +/-- The whole quotient-lift application computes for any typed invariant +function. Both the Prop and graph regimes are included. -/ +theorem liftValue_apply {entries : Environment β} {constants : Assignment β V} + {eq refl recursor : ConstRef β} (hE : Basis.Equality.Interface entries eq refl recursor) + (hM : Realizes constants entries) {u v : Nat} {A R B f h a : V} + (hA : A ∈ˢ univ u) (hR : R ∈ˢ relationSet A) (hB : B ∈ˢ univ v) + (hf : f ∈ˢ piR (bit v) A (fun _ => B)) + (hh : h ∈ˢ invariantSet constants eq v A R B f) (ha : a ∈ˢ A) : + app (app (app (app (app (app (liftValue constants eq u v) A) R) B) f) h) + (quotClass u A R a) = app f a := by + by_cases hv : v = 0 + · subst v + have he : f = pt := eq_pt_of_mem_piR_zero hf + simp [liftValue, bit, lamR_zero, he, app_pt] + · simp only [liftValue, bit, if_neg hv] + rw [app_lamR_pos (by decide : 1 ≠ 0) hA, + app_lamR_pos (by decide : 1 ≠ 0) hR, + app_lamR_pos (by decide : 1 ≠ 0) hB, + app_lamR_pos (by decide : 1 ≠ 0) (by simpa only [bit, if_neg hv] using hf), + app_lamR_pos (by decide : 1 ≠ 0) hh, + app_lamR_pos (by decide : 1 ≠ 0) (quotClass_mem ha)] + have hs := qrep_spec (u := u) (R := R) (quotClass_mem ha) + exact app_eq_of_quotClass_eq hA hs.1 ha (invariant_of_mem hE hM hB hf hh) hs.2.symm + +end Ix.Theory.Certified.Quotient diff --git a/Ix/Theory/Certified/Signature.lean b/Ix/Theory/Certified/Signature.lean new file mode 100644 index 000000000..240fdd808 --- /dev/null +++ b/Ix/Theory/Certified/Signature.lean @@ -0,0 +1,162 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Checker +import Ix.Theory.Model.Signature + +/-! Internal formation of a finite signature. These operations publish no +admitted environment: membership and every computation equation must still +be constructed by the caller's semantic producer. -/ + +namespace Ix.Theory.Certified.Signature + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +structure Header (β : Type u) where + ref : ConstRef β + universes : Nat + type : AExpr β + +def Header.entry (header : Header β) : ConstantEntry β := + ⟨header.universes, header.type, none, [], []⟩ + +def environment (entries : Environment β) : List (Header β) → Environment β + | [] => entries + | header :: rest => environment (entries.insert header.ref header.entry) rest + +structure TypeWitness (β : Type u) where + level : VLevel + typing : TypingWitness β + +inductive Formed : Environment β → List (Header β) → Prop where + | nil (entries) : Formed entries [] + | cons {entries header rest} (fresh : entries header.ref = none) + (scope : header.type.Scope header.universes 0) (references : header.type.ReferencesIn entries) + {level : VLevel} (typing : TypingClaim.{u,v} entries [] header.type (.sort level)) + (tail : Formed (entries.insert header.ref header.entry) rest) : Formed entries (header :: rest) + +def checkTypes (fuel : Nat) (entries : Environment β) : (headers : List (Header β)) → + List (TypeWitness β) → Option (CheckedClaim.{u} (Formed.{u,v} entries headers)) + | [], [] => some ⟨.nil entries⟩ + | header :: headers, witness :: witnesses => + if hf : entries header.ref = none then + if hs : header.type.Scope header.universes 0 then + if hr : header.type.ReferencesIn entries then do + let ht ← verifyType.{u,v} fuel header.universes entries [] header.type (.sort witness.level) witness.typing + let rest ← checkTypes fuel (entries.insert header.ref header.entry) headers witnesses + return ⟨.cons hf hs hr ht.down rest.down⟩ + else none + else none + else none + | _, _ => none + +theorem checkTypes_sound {fuel : Nat} {entries : Environment β} {headers : List (Header β)} + {witnesses : List (TypeWitness β)} {result} + (_ : checkTypes.{u,v} fuel entries headers witnesses = some result) : Formed.{u,v} entries headers := result.down + +theorem Formed.old {entries : Environment β} {headers : List (Header β)} + (h : Formed.{u,v} entries headers) {r : ConstRef β} {entry : ConstantEntry β} + (hr : entries r = some entry) : environment entries headers r = some entry := by + induction h with + | nil => exact hr + | cons hf _ _ _ _ ih => exact ih (Environment.insert_old hf hr) + +theorem Formed.lookup {entries : Environment β} {headers : List (Header β)} + (h : Formed.{u,v} entries headers) {header : Header β} (hm : header ∈ headers) : + environment entries headers header.ref = some header.entry := by + induction h with + | nil => cases hm + | @cons entries hd rest hf hs hr level ht tail ih => + rcases List.mem_cons.mp hm with he | hm + · subst header + exact tail.old (Environment.insert_same ..) + · exact ih hm + +theorem environment_source {entries : Environment β} {headers : List (Header β)} + {r : ConstRef β} {entry : ConstantEntry β} (h : environment entries headers r = some entry) : + entries r = some entry ∨ ∃ header ∈ headers, r = header.ref ∧ entry = header.entry := by + induction headers generalizing entries with + | nil => exact Or.inl h + | cons header rest ih => + rcases ih h with hold | ⟨hd, hm, he, hv⟩ + · unfold Environment.insert at hold + split at hold + · exact Or.inr ⟨header, List.mem_cons_self, ‹r = header.ref›, (Option.some.inj hold).symm⟩ + · exact Or.inl hold + · exact Or.inr ⟨hd, List.mem_cons_of_mem _ hm, he, hv⟩ + +theorem Formed.wf {entries : Environment β} {headers : List (Header β)} + (h : Formed.{u,v} entries headers) (hE : entries.WF) : (environment entries headers).WF := by + induction h with + | nil => exact hE + | cons _ hs hr _ _ ih => + apply ih + exact hE.insert hs (by simp [Header.entry]) hr (by simp [Header.entry]) + (by simp [Header.entry]) (by simp [Header.entry]) + (by simp [Header.entry]) (by simp [Header.entry]) + +structure Rule (β : Type u) where + universes : Nat + type : AExpr β + lhs : AExpr β + rhs : AExpr β + +structure RuleWitness (β : Type u) where + level : VLevel + type : TypingWitness β + lhs : TypingWitness β + rhs : TypingWitness β + +structure RuleFormed (entries : Environment β) (rule : Rule β) : Prop where + scope : rule.type.Scope rule.universes 0 ∧ rule.lhs.Scope rule.universes 0 ∧ rule.rhs.Scope rule.universes 0 + references : rule.type.ReferencesIn entries ∧ rule.lhs.ReferencesIn entries ∧ rule.rhs.ReferencesIn entries + type : ∃ level, TypingClaim.{u,v} entries [] rule.type (.sort level) + lhs : TypingClaim.{u,v} entries [] rule.lhs rule.type + rhs : TypingClaim.{u,v} entries [] rule.rhs rule.type + +/-- Both complete endpoints are checked against their common formed type, +before the environment has acquired the new computation equations. -/ +def checkRule (fuel : Nat) (entries : Environment β) (rule : Rule β) (witness : RuleWitness β) : + Option (CheckedClaim.{u} (RuleFormed.{u,v} entries rule)) := + if hs : rule.type.Scope rule.universes 0 ∧ rule.lhs.Scope rule.universes 0 ∧ rule.rhs.Scope rule.universes 0 then + if hr : rule.type.ReferencesIn entries ∧ rule.lhs.ReferencesIn entries ∧ rule.rhs.ReferencesIn entries then do + let ht ← verifyType.{u,v} fuel rule.universes entries [] rule.type (.sort witness.level) witness.type + let hl ← verifyType.{u,v} fuel rule.universes entries [] rule.lhs rule.type witness.lhs + let hh ← verifyType.{u,v} fuel rule.universes entries [] rule.rhs rule.type witness.rhs + return ⟨⟨hs, hr, ⟨witness.level, ht.down⟩, hl.down, hh.down⟩⟩ + else none + else none + +variable {V : Type v} [SetTheory V] +open SetTheory + +/-- Formation supplies hereditary validity. The caller supplies membership +from the concrete mathematical values, in the same assignment throughout. -/ +theorem Formed.realizes {entries : Environment β} {headers : List (Header β)} + (h : Formed.{u,v} entries headers) {constants : Assignment β V} (hM : Realizes constants entries) + (members : ∀ header ∈ headers, ∀ levels, levels.length = header.universes → ∀ env, + constants header.ref levels ∈ˢ interp constants levels env header.type) : + Realizes constants (environment entries headers) := by + induction h with + | nil => exact hM + | cons _ _ _ ht _ ih => + apply ih + · apply hM.insert + constructor + · intro levels _ env + exact (ht V constants hM levels env (Context.valid_nil constants levels env)).1 + · intro levels hn env + exact members _ List.mem_cons_self levels hn env + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl; cases hl + · intro fact hf; cases hf + · intro header hm + exact members header (List.mem_cons_of_mem _ hm) + +end Ix.Theory.Certified.Signature diff --git a/Ix/Theory/Certified/Source.lean b/Ix/Theory/Certified/Source.lean new file mode 100644 index 000000000..af60f6e20 --- /dev/null +++ b/Ix/Theory/Certified/Source.lean @@ -0,0 +1,153 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Store + +/-! Every admitted entry retains the exact type and universe arity of its +source member or constructor. Semantic facts and equations add evidence; +they do not replace the authenticated declaration's statement. -/ + +namespace Ix.Theory.Certified + +open Model Model.SetTheory + +universe u v +variable {β : Type u} + +structure SourceHeader (store : Store β) (ref : ConstRef β) (entry : ConstantEntry β) : Prop where + type : store.type ref = some entry.type.erase + universes : store.uvars ref = some entry.universes + +namespace Ordinary.Shape + +theorem family_sourceHeader {store : Store β} {shape : Ordinary.Shape β} {source : β} + (h : store.blocks source = some ⟨[shape.source source]⟩) : + SourceHeader store (.member source 0) shape.familyEntry := by + constructor <;> simp [Store.type, Store.uvars, Store.lookup, h, Shape.source, familyEntry, + Const.type, Const.uvars] + +theorem constructor_sourceHeader {store : Store β} {shape : Ordinary.Shape β} {source : β} + {index : Nat} {ctor : Ordinary.Constructor β} + (h : store.blocks source = some ⟨[shape.source source]⟩) + (hc : shape.constructors[index]? = some ctor) : + SourceHeader store (.ctor source 0 index) (shape.constructorEntry source ctor) := by + constructor <;> simp [Store.type, Store.uvars, Store.lookup, Store.lookupCtor, h, + Shape.source, List.getElem?_map, hc, Ordinary.Constructor.source, constructorEntry] + +theorem recursor_sourceHeader {store : Store β} {shape : Ordinary.Shape β} {source recursor : β} + {mode : Inductive.ElimMode} (h : shape.RecursorSourceMatches store source recursor mode) : + SourceHeader store (.member recursor 0) (shape.publishedRecursorEntry source recursor mode) := by + rcases h with h | ⟨_, h⟩ <;> + constructor <;> simp [Store.type, Store.uvars, Store.lookup, h, + recursorSource, publishedRecursorEntry, recursorEntry, Const.type, Const.uvars] + +end Ordinary.Shape + +theorem Ordinary.EntrySource.header {store : Store β} {ref : ConstRef β} {entry : ConstantEntry β} + (h : Ordinary.EntrySource store ref entry) : SourceHeader store ref entry := by + rcases h with ⟨shape, source, recursor, mode, hs, hr, h⟩ + rcases h with ⟨rfl, rfl⟩ | ⟨index, ctor, hc, rfl, rfl⟩ | ⟨rfl, rfl⟩ + · exact shape.family_sourceHeader hs + · exact shape.constructor_sourceHeader hs hc + · exact shape.recursor_sourceHeader hr + +theorem Standard.EntrySource.header {store : Store β} {ref : ConstRef β} {entry : ConstantEntry β} + (h : Standard.EntrySource store ref entry) : SourceHeader store ref entry := by + rcases h with ⟨spec, hs, rfl⟩ + constructor <;> simp [Store.type, Store.uvars, hs, Standard.Spec.source, Standard.Spec.entry, + Const.type, Const.uvars] + +theorem Quotient.EntrySource.header {store : Store β} {ref : ConstRef β} {entry : ConstantEntry β} + (h : Quotient.EntrySource store ref entry) : SourceHeader store ref entry := by + rcases h with ⟨refs, kind, hs, rfl, rfl⟩ + have he := hs kind (by cases kind <;> simp [Quotient.kinds]) + constructor <;> cases kind <;> + simp [Store.type, Store.uvars, he, Quotient.Refs.source, Quotient.Refs.entry, + Quotient.Refs.entryType, Quotient.Kind.universes, Const.type, Const.uvars] + +theorem Structure.EntrySource.header {store : Store β} {ref : ConstRef β} {entry : ConstantEntry β} + (h : Structure.EntrySource store ref entry) : SourceHeader store ref entry := by + rcases h with ⟨description, source, recursor, mode, hs, _, rfl, rfl⟩ + exact ⟨(description.ordinary.family_sourceHeader hs).type, + (description.ordinary.family_sourceHeader hs).universes⟩ + +theorem Natural.EntrySource.header {pin : Option (ConstRef β)} {store : Store β} + {ref : ConstRef β} {entry : ConstantEntry β} + (h : Natural.EntrySource pin store ref entry) : SourceHeader store ref entry := by + rcases h with ⟨_, source, recursor, mode, hs, _, rfl, rfl⟩ + exact ⟨(Ordinary.Shape.family_sourceHeader hs).type, + (Ordinary.Shape.family_sourceHeader hs).universes⟩ + +theorem Modeled.EntrySource.header {store : Store β} {ref : ConstRef β} {entry : ConstantEntry β} + (h : Modeled.EntrySource store ref entry) : SourceHeader store ref entry := by + obtain ⟨_, companion, hs, rfl, rfl⟩ := h + exact ⟨hs.1, hs.2.1⟩ + +/-- This covers every enabled admission form, including pinned primitives, +definition bodies, ordinary constructors and certified semantic extensions. -/ +theorem EntrySource.header {signature : PrimitiveSignature β} {store : Store β} + {ref : ConstRef β} {entry : ConstantEntry β} + (h : EntrySource signature store ref entry) : SourceHeader store ref entry := by + rcases h with ⟨rfl, rfl, hs⟩ | ⟨rfl, rfl, hs⟩ | ⟨kind, body, _, _, _, hs⟩ | h | h | h | h | h | h + · constructor <;> simp [Store.type, Store.uvars, hs, PrimitiveSignature.falseDeclaration, + PrimitiveSignature.falseEntry, Const.type, Const.uvars, AExpr.erase] + · constructor <;> simp [Store.type, Store.uvars, hs, PrimitiveSignature.falseElimDeclaration, + PrimitiveSignature.falseElimEntry, Const.type, Const.uvars] + · constructor <;> simp [Store.type, Store.uvars, hs, Const.type, Const.uvars] + · exact h.header + · exact h.header + · exact h.header + · exact h.header + · exact h.header + · exact h.header + +theorem AdmittedEnvironment.sourceHeader {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) {ref : ConstRef β} {entry : ConstantEntry β} + (h : state.entries ref = some entry) : SourceHeader store ref entry := + (state.source ref entry h).header + +/-- Every requested declaration is tied to its original source header and +is valid in each compatible interpretation of the admitted interface. -/ +theorem CheckedStore.subject_sound {signature : PrimitiveSignature β} {store : Store β} + {subjects : List (ConstRef β)} (result : CheckedStore.{u,v} signature store subjects) + {ref : ConstRef β} (h : ref ∈ subjects) : + ∃ entry, result.environment.entries ref = some entry ∧ + SourceHeader store ref entry ∧ + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + signature.Compatible result.environment.entries constants → + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env entry.type ∧ + constants ref levels ∈ˢ interp constants levels env entry.type := by + have hp := result.targetsPresent ref h + cases he : result.environment.entries ref with + | none => simp [he] at hp + | some entry => + refine ⟨entry, rfl, result.environment.sourceHeader he, ?_⟩ + intro V _ constants hM levels hl env + exact ⟨hM.realizes.typeValid ref entry he levels hl env, + hM.realizes.member ref entry he levels hl env⟩ + +/-- The exact source type has an inhabitant in a model constructed by the +checker; the source header is not an additional caller hypothesis. -/ +theorem accepted_store_source_sound [DecidableEq β] {fuel : Nat} {signature : PrimitiveSignature β} + {store : Store β} {subjects : List (ConstRef β)} {witness : List (DeclarationWitness β)} + (h : acceptsStoreCertified.{u,v} fuel signature store subjects witness = true) + (V : Type v) [SetTheory V] : + ∃ result : CheckedStore.{u,v} signature store subjects, + checkStoreCertified fuel signature store subjects witness = some result ∧ + ∃ constants : Assignment β V, + signature.Compatible result.environment.entries constants ∧ + ∀ ref ∈ subjects, ∃ entry, result.environment.entries ref = some entry ∧ + SourceHeader store ref entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env entry.type ∧ + constants ref levels ∈ˢ interp constants levels env entry.type := by + obtain ⟨result, checked, constants, compatible, _⟩ := accepted_store_has_model h V + refine ⟨result, checked, constants, compatible, ?_⟩ + intro ref hr + obtain ⟨entry, he, hs, hm⟩ := result.subject_sound hr + exact ⟨entry, he, hs, hm V constants compatible⟩ + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Standard/Admission.lean b/Ix/Theory/Certified/Standard/Admission.lean new file mode 100644 index 000000000..4fa38b320 --- /dev/null +++ b/Ix/Theory/Certified/Standard/Admission.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Admission + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +/-- Standard axiom schemas acquire values only after exact source, prerequisite +interface, and whole-type checks. No caller-supplied realization is accepted. -/ +def checkStandardExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (witness : Standard.Witness β) : + Option (CheckedExtension.{u,v} signature store state) := do + let checked ← Standard.check.{u,v} fuel state.entries store witness + have extension : Extends.{u,v} signature state.entries + (state.entries.insert witness.ref witness.spec.entry) := by + constructor + · exact fun _ _ h => Environment.insert_old checked.down.fresh h + · intro V _ constants hM + let constants' := Standard.assignment constants witness + have ha := Standard.assignment_agrees checked.down constants + have hm := Standard.assignment_realizes checked.down state.wf constants hM.realizes + exact ⟨constants', hM.extend signature state.present hm ha, ha⟩ + let result : CheckedInterface signature := { + entries := state.entries.insert witness.ref witness.spec.entry + wf := Standard.environment_wf checked.down state.wf + present := state.present.insert signature checked.down.fresh + } + return { + result, extension + source := by + intro r entry hr + dsimp only [result] at hr + unfold Environment.insert at hr + split at hr + next he => + subst r + cases Option.some.inj hr + exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inl ⟨witness.spec, checked.down.exactSource, rfl⟩))))) + next => exact Or.inl hr + } + +def admitStandard? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : Standard.Witness β) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkStandardExtension?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +theorem admitStandard?_extends {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {state : AdmittedEnvironment.{u,v} signature store} {witness : Standard.Witness β} {result} + (_ : admitStandard? fuel state witness = some result) : + Extends.{u,v} signature state.entries result.val.entries := result.property + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Standard/Checked.lean b/Ix/Theory/Certified/Standard/Checked.lean new file mode 100644 index 000000000..f2cd6dc34 --- /dev/null +++ b/Ix/Theory/Certified/Standard/Checked.lean @@ -0,0 +1,89 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Standard.Realization + +namespace Ix.Theory.Certified.Standard + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +structure Witness (β : Type u) where + ref : ConstRef β + spec : Spec β + level : VLevel + typing : TypingWitness β + +structure Checked (entries : Environment β) (store : Store β) (witness : Witness β) : Prop where + exactSource : store.lookup witness.ref = some witness.spec.source + fresh : entries witness.ref = none + prerequisites : witness.spec.Prerequisites entries + scope : witness.spec.type.Scope witness.spec.universes 0 + references : witness.spec.type.ReferencesIn entries + typing : TypingClaim.{u,v} entries [] witness.spec.type (.sort witness.level) + +def check (fuel : Nat) (entries : Environment β) (store : Store β) (witness : Witness β) : + Option (CheckedClaim.{u} (Checked.{u,v} entries store witness)) := + if hs : store.lookup witness.ref = some witness.spec.source then + if hf : entries witness.ref = none then + if hp : witness.spec.Prerequisites entries then + if hc : witness.spec.type.Scope witness.spec.universes 0 then + if hr : witness.spec.type.ReferencesIn entries then do + let ht ← verifyType.{u,v} fuel witness.spec.universes entries [] + witness.spec.type (.sort witness.level) witness.typing + return ⟨⟨hs, hf, hp, hc, hr, ht.down⟩⟩ + else none + else none + else none + else none + else none + +theorem check_sound {fuel : Nat} {entries : Environment β} {store : Store β} {witness : Witness β} + {result} (_ : check.{u,v} fuel entries store witness = some result) : + Checked.{u,v} entries store witness := result.down + +def EntrySource (store : Store β) (ref : ConstRef β) (entry : ConstantEntry β) : Prop := + ∃ spec : Spec β, store.lookup ref = some spec.source ∧ entry = spec.entry + +variable {entries : Environment β} {store : Store β} {witness : Witness β} + +theorem environment_wf (h : Checked.{u,v} entries store witness) (hE : entries.WF) : + (entries.insert witness.ref witness.spec.entry).WF := by + apply hE.insert h.scope (by simp [Spec.entry]) h.references + (by simp [Spec.entry]) (by simp [Spec.entry]) (by simp [Spec.entry]) + (by simp [Spec.entry]) (by simp [Spec.entry]) + +variable {V : Type v} [SetTheory V] + +noncomputable def assignment (constants : Assignment β V) (witness : Witness β) : Assignment β V := + constants.insert witness.ref (witness.spec.value constants) + +theorem assignment_agrees (h : Checked.{u,v} entries store witness) (constants : Assignment β V) : + Assignment.AgreesOn entries constants (assignment constants witness) := + Assignment.insert_agrees h.fresh _ _ + +theorem assignment_realizes (h : Checked.{u,v} entries store witness) (hE : entries.WF) + (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (assignment constants witness) (entries.insert witness.ref witness.spec.entry) := by + have ha := assignment_agrees h constants + apply (hM.of_agrees hE ha).insert + constructor + · intro levels hn env + exact (h.typing V (assignment constants witness) (hM.of_agrees hE ha) levels env + (Context.valid_nil (assignment constants witness) levels env)).1 + · intro levels hn env + change (assignment constants witness) witness.ref levels ∈ˢ + interp (assignment constants witness) levels env witness.spec.type + rw [ha.interp h.references] + rw [assignment, Assignment.insert_same] + exact witness.spec.value_mem h.prerequisites hM levels hn env + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl; simp only [Spec.entry, List.not_mem_nil] at hl + · intro fact hf; simp only [Spec.entry, List.not_mem_nil] at hf + +end Ix.Theory.Certified.Standard diff --git a/Ix/Theory/Certified/Standard/Realization.lean b/Ix/Theory/Certified/Standard/Realization.lean new file mode 100644 index 000000000..5a7d3e534 --- /dev/null +++ b/Ix/Theory/Certified/Standard/Realization.lean @@ -0,0 +1,127 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Basis.Iff +import Ix.Theory.Certified.Basis.Nonempty + +/-! Realizations of the exact standard propext and choice types. Their +prerequisite meanings follow from admitted inductive interfaces in every +compatible prefix model, rather than being new semantic assumptions. -/ + +namespace Ix.Theory.Certified.Standard + +open Model Model.SetTheory Model.SetModel Basis + +universe u v +variable {β : Type u} + +inductive Spec (β : Type u) where + | propext (eq eqRefl eqRec iff iffIntro iffRec : ConstRef β) + | choice (nonempty intro recursor : ConstRef β) + +def Spec.universes : Spec β → Nat + | .propext .. => 0 + | .choice .. => 1 + +def propextType (eq iff : ConstRef β) : AExpr β := + .forallE .always (.sort .zero) <| .forallE .always (.sort .zero) <| + .forallE .always (Iff.applied iff (.bvar 1) (.bvar 0)) <| + Equality.applied eq (.succ .zero) (.sort .zero) (.bvar 2) (.bvar 1) + +def choiceType (nonempty : ConstRef β) : AExpr β := + .forallE (.param 0) (.sort (.param 0)) <| + .forallE (.param 0) (Nonempty.applied nonempty (.param 0) (.bvar 0)) (.bvar 1) + +def Spec.type : Spec β → AExpr β + | .propext eq _ _ iff _ _ => propextType eq iff + | .choice nonempty _ _ => choiceType nonempty + +def Spec.Prerequisites (entries : Environment β) : Spec β → Prop + | .propext eq eqRefl eqRec iff iffIntro iffRec => + Equality.Interface entries eq eqRefl eqRec ∧ Iff.Interface entries iff iffIntro iffRec + | .choice nonempty intro recursor => Nonempty.Interface entries nonempty intro recursor + +instance [DecidableEq β] (entries : Environment β) (spec : Spec β) : + Decidable (spec.Prerequisites entries) := by cases spec <;> unfold Spec.Prerequisites <;> infer_instance + +def Spec.entry (spec : Spec β) : ConstantEntry β := ⟨spec.universes, spec.type, none, [], []⟩ +def Spec.source (spec : Spec β) : Const β := .axiom spec.universes spec.type.erase .safe + +variable {V : Type v} [SetTheory V] + +open Classical in +noncomputable def chooseSet (A : V) : V := + if h : ∃ a, a ∈ˢ A then Classical.choose h else empty + +theorem chooseSet_mem {A : V} (h : ∃ a, a ∈ˢ A) : chooseSet A ∈ˢ A := by + rw [chooseSet, dif_pos h] + exact Classical.choose_spec h + +noncomputable def choiceValue (constants : Assignment β V) (nonempty : ConstRef β) (u : Nat) : V := + lamR (if u = 0 then 0 else 1) (univ u) (fun A => + lamR (if u = 0 then 0 else 1) (Nonempty.value constants nonempty u A) (fun _ => chooseSet A)) + +noncomputable def Spec.value (spec : Spec β) (constants : Assignment β V) (levels : List Nat) : V := + match spec with + | .propext .. => pt + | .choice nonempty _ _ => choiceValue constants nonempty (levels.getD 0 0) + +theorem propextType_interp (constants : Assignment β V) (eq iff : ConstRef β) (env : Nat → V) : + interp constants [] env (propextType eq iff) = + piR 0 univZero (fun P => piR 0 univZero (fun Q => + piR 0 (Iff.value constants iff P Q) (fun _ => Equality.value constants eq 1 univZero P Q))) := by + simp [propextType, Iff.applied, Equality.applied, Iff.value, Equality.value, + AExpr.appN, interp, VLevel.eval, Valuation.cons, univ_zero] + +theorem choiceType_interp (constants : Assignment β V) (nonempty : ConstRef β) (u : Nat) (env : Nat → V) : + interp constants [u] env (choiceType nonempty) = + piR (if u = 0 then 0 else 1) (univ u) (fun A => + piR (if u = 0 then 0 else 1) (Nonempty.value constants nonempty u A) (fun _ => A)) := by + simp [choiceType, Nonempty.applied, Nonempty.value, interp, VLevel.eval, Valuation.cons, + regime, PropWhen.param, PropWhen.holds] + +theorem propextValue_mem {entries : Environment β} {constants : Assignment β V} + {eq eqRefl eqRec iff iffIntro iffRec : ConstRef β} + (hE : Equality.Interface entries eq eqRefl eqRec) + (hI : Iff.Interface entries iff iffIntro iffRec) (hM : Realizes constants entries) (env : Nat → V) : + (pt : V) ∈ˢ interp constants [] env (propextType eq iff) := by + rw [propextType_interp] + apply pt_mem_piR_zero_of + intro P hP + apply pt_mem_piR_zero_of + intro Q hQ + apply pt_mem_piR_zero_of + intro proof hp + rw [Equality.value_eq_eqv hE hM (by simpa only [univ_zero] using univ_mem_univ (V := V) 0) hP hQ] + have he := Iff.eq_of_mem hI hM hP hQ hp + subst Q + exact pt_mem_eqv_self _ + +theorem choiceValue_mem {entries : Environment β} {constants : Assignment β V} + {nonempty intro recursor : ConstRef β} + (h : Nonempty.Interface entries nonempty intro recursor) (hM : Realizes constants entries) + (u : Nat) (env : Nat → V) : + choiceValue constants nonempty u ∈ˢ interp constants [u] env (choiceType nonempty) := by + rw [choiceType_interp] + apply lamR_mem + intro A hA + apply lamR_mem + intro proof hp + exact chooseSet_mem (Nonempty.exists_of_mem h hM hA hp) + +theorem Spec.value_mem {entries : Environment β} {constants : Assignment β V} + (spec : Spec β) (h : spec.Prerequisites entries) (hM : Realizes constants entries) + (levels : List Nat) (hn : levels.length = spec.universes) (env : Nat → V) : + spec.value constants levels ∈ˢ interp constants levels env spec.type := by + cases spec with + | propext eq eqRefl eqRec iff iffIntro iffRec => + have he : levels = [] := List.length_eq_zero_iff.mp hn + subst levels + exact propextValue_mem h.1 h.2 hM env + | choice nonempty intro recursor => + obtain ⟨u, rfl⟩ := List.length_eq_one_iff.mp hn + exact choiceValue_mem h hM u env + +end Ix.Theory.Certified.Standard diff --git a/Ix/Theory/Certified/Store.lean b/Ix/Theory/Certified/Store.lean new file mode 100644 index 000000000..2087aad95 --- /dev/null +++ b/Ix/Theory/Certified/Store.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Admission + +/-! Certification of requested declarations, including data declarations. +Logical proof acceptance additionally checks the requested proposition is in +Prop. A declaration certificate constructs a compatible model for every +requested type, body and admitted computation rule. -/ + +namespace Ix.Theory.Certified + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +structure CheckedStore (signature : PrimitiveSignature β) (store : Store β) + (targets : List (ConstRef β)) where + environment : AdmittedEnvironment.{u,v} signature store + targetsPresent : ∀ r ∈ targets, (environment.entries r).isSome = true + +def checkStoreCertified (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (targets : List (ConstRef β)) (witness : List (DeclarationWitness β)) : + Option (CheckedStore.{u,v} signature store targets) := do + let initial ← initialize? signature store + let admitted ← admitDeclarations? fuel initial witness + if h : targets.all (fun r => (admitted.val.entries r).isSome) = true then + return ⟨admitted.val, List.all_eq_true.mp h⟩ + else none + +def acceptsStoreCertified (fuel : Nat) (signature : PrimitiveSignature β) (store : Store β) + (targets : List (ConstRef β)) (witness : List (DeclarationWitness β)) : Bool := + (checkStoreCertified.{u,v} fuel signature store targets witness).isSome + +/-- Successful admission constructs one compatible model for the entire +requested interface, at every permitted universe instance. -/ +theorem accepted_store_has_model {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {targets : List (ConstRef β)} {witness : List (DeclarationWitness β)} + (h : acceptsStoreCertified.{u,v} fuel signature store targets witness = true) + (V : Type v) [SetTheory V] : + ∃ result : CheckedStore.{u,v} signature store targets, + checkStoreCertified fuel signature store targets witness = some result ∧ + ∃ constants : Assignment β V, + signature.Compatible result.environment.entries constants ∧ + ∀ r ∈ targets, ∃ entry, result.environment.entries r = some entry ∧ + EntrySource signature store r entry ∧ + ∀ levels, levels.length = entry.universes → ∀ env : Nat → V, + WellDenoted constants levels env entry.type ∧ + constants r levels ∈ˢ interp constants levels env entry.type := by + unfold acceptsStoreCertified at h + cases hc : checkStoreCertified.{u,v} fuel signature store targets witness with + | none => simp [hc] at h + | some result => + obtain ⟨constants, hM⟩ := result.environment.model V + refine ⟨result, rfl, constants, hM, ?_⟩ + intro r hr + have present := result.targetsPresent r hr + cases he : result.environment.entries r with + | none => simp [he] at present + | some entry => + refine ⟨entry, rfl, result.environment.source r entry he, ?_⟩ + intro levels hl env + exact ⟨hM.realizes.typeValid r entry he levels hl env, + hM.realizes.member r entry he levels hl env⟩ + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Structure/Admission.lean b/Ix/Theory/Certified/Structure/Admission.lean new file mode 100644 index 000000000..894546f1f --- /dev/null +++ b/Ix/Theory/Certified/Structure/Admission.lean @@ -0,0 +1,62 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Admission + +namespace Ix.Theory.Certified + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +/-- Construct the structure and its projection facts in one extension of the +original prefix. This never strengthens an already admitted arbitrary model +by assuming that it used this producer's concrete field representation. -/ +def checkStructureExtension? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : CheckedInterface signature) (witness : Structure.Witness β) : + Option (CheckedExtension.{u,v} signature store state) := do + let checked ← Structure.check.{u,v} fuel state.entries store witness + let d := witness.facts.description + let block := witness.facts.block + let entries := d.publishedEnvironment state.entries block.source block.recursor block.mode + have extension : Extends.{u,v} signature state.entries entries := by + constructor + · intro r entry hr + exact d.publishedEnvironment_old checked.down hr + · intro V _ constants hM + let constants' := d.ordinary.recursorAssignment constants block.source block.recursor block.mode + have hm := d.publishedAssignment_realizes checked.down state.wf constants hM.realizes + have ha := Ordinary.Shape.publishedAssignment_agrees checked.down.facts.block constants + exact ⟨constants', hM.extend signature state.present hm ha, ha⟩ + let result : CheckedInterface signature := { + entries + wf := d.publishedEnvironment_wf checked.down state.wf + present := ⟨extension.lookup _ _ state.present.1, extension.lookup _ _ state.present.2⟩ + } + return { + result, extension + source := by + intro r entry hr + dsimp only [result] at hr + rcases Structure.publishedEntry_source checked.down hr with hold | hordinary | hstructure + · exact Or.inl hold + · exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inl hordinary)))) + · exact Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inr (Or.inl hstructure))))))) + } + +def admitStructure? (fuel : Nat) {signature : PrimitiveSignature β} {store : Store β} + (state : AdmittedEnvironment.{u,v} signature store) (witness : Structure.Witness β) : + Option { result : AdmittedEnvironment.{u,v} signature store // + Extends.{u,v} signature state.entries result.entries } := do + let checked ← checkStructureExtension?.{u,v} fuel (store := store) state.interface witness + return checked.admit state + +theorem admitStructure?_extends {fuel : Nat} {signature : PrimitiveSignature β} {store : Store β} + {state : AdmittedEnvironment.{u,v} signature store} {witness : Structure.Witness β} {result} + (_ : admitStructure? fuel state witness = some result) : + Extends.{u,v} signature state.entries result.val.entries := result.property + +end Ix.Theory.Certified diff --git a/Ix/Theory/Certified/Structure/Checked.lean b/Ix/Theory/Certified/Structure/Checked.lean new file mode 100644 index 000000000..66cc121a2 --- /dev/null +++ b/Ix/Theory/Certified/Structure/Checked.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Structure.Computation +import Ix.Theory.Certified.Signature + +namespace Ix.Theory.Certified.Structure + +open Model + +universe u v +variable {β : Type u} [DecidableEq β] + +def Description.factEntry (d : Description β) (source : β) : ConstantEntry β := + { d.ordinary.familyEntry with facts := d.facts source } + +def Description.factEnvironment (d : Description β) (entries : Environment β) (source recursor : β) + (mode : Inductive.ElimMode) : Environment β := + (d.ordinary.publishedEnvironment entries source recursor mode).insert (.member source 0) (d.factEntry source) + +/-- Field i may use the already produced equations for earlier fields when +checking its dependent result. Its own equation is absent from this stage. -/ +def Description.iotaEnvironment (d : Description β) (entries : Environment β) (source recursor : β) + (mode : Inductive.ElimMode) (count : Nat) : Environment β := + (d.ordinary.publishedEnvironment entries source recursor mode).insert (.member source 0) + { d.factEntry source with equations := ((d.equations source).drop 1).take count } + +structure FactsWitness (β : Type u) where + description : Description β + block : Ordinary.BlockWitness β + fields : List (TypingWitness β) + domains : List (DomainWitness β) + +structure FactsChecked (entries : Environment β) (store : Store β) (d : Description β) + (source recursor : β) (mode : Inductive.ElimMode) : Prop where + block : Ordinary.CheckedBlock.{u,v} entries store source recursor d.ordinary mode + fields : FieldsFormed.{u,v} entries d.level d.ordinary.parameterContext d.fields + domains : Telescope.Formed.{u,v} (d.ordinary.publishedEnvironment entries source recursor mode) [] + (d.projectionDomains source) + scope : ∀ fact ∈ d.facts source, fact.Scope d.universes + references : ∀ fact ∈ d.facts source, + fact.ReferencesIn (d.ordinary.publishedEnvironment entries source recursor mode) + +def checkFacts (fuel : Nat) (entries : Environment β) (store : Store β) (witness : FactsWitness β) : + Option (CheckedClaim.{u} (FactsChecked.{u,v} entries store witness.description + witness.block.source witness.block.recursor witness.block.mode)) := + let d := witness.description + let block := witness.block + if he : block.shape.shape = d.ordinary then + if hs : ∀ fact ∈ d.facts block.source, fact.Scope d.universes then + if hr : ∀ fact ∈ d.facts block.source, + fact.ReferencesIn (d.ordinary.publishedEnvironment entries block.source block.recursor block.mode) then do + let hb ← Ordinary.checkBlock.{u,v} fuel entries store block + let hf ← checkFields.{u,v} fuel d.universes entries d.level d.ordinary.parameterContext d.fields witness.fields + let hd ← verifyTelescope.{u,v} fuel d.universes + (d.ordinary.publishedEnvironment entries block.source block.recursor block.mode) none [] + (d.projectionDomains block.source) witness.domains + return ⟨⟨he ▸ hb.down, hf.down, hd.down.1, hs, hr⟩⟩ + else none + else none + else none + +def Description.etaRule (d : Description β) (source : β) : Signature.Rule β := + ⟨d.universes, .forallN (zeroCondition d.level) (d.projectionDomains source) + (d.ordinary.familyApp source 1 []), d.etaLhs source, d.etaRhs source⟩ + +def Description.iotaRule (d : Description β) (source : β) (i : Nat) (field : Field β) : Signature.Rule β := + ⟨d.universes, .forallN (zeroCondition field.level) (d.parameters ++ d.constructor.fields) + (field.domain.liftN (d.fields.length - i)), d.iotaLhs source i field, d.iotaRhs i field⟩ + +structure Witness (β : Type u) where + facts : FactsWitness β + eta : Signature.RuleWitness β + iota : List (Signature.RuleWitness β) + +structure Checked (entries : Environment β) (store : Store β) (d : Description β) + (source recursor : β) (mode : Inductive.ElimMode) : Prop where + facts : FactsChecked.{u,v} entries store d source recursor mode + eta : Signature.RuleFormed.{u,v} (d.factEnvironment entries source recursor mode) (d.etaRule source) + iota : ∀ field i, (field, i) ∈ d.fields.zipIdx → + Signature.RuleFormed.{u,v} (d.iotaEnvironment entries source recursor mode i) (d.iotaRule source i field) + +def checkIota (fuel : Nat) (entries : Environment β) (d : Description β) (source recursor : β) + (mode : Inductive.ElimMode) : + (fields : List (Field β × Nat)) → List (Signature.RuleWitness β) → + Option (CheckedClaim.{u} (∀ field i, (field, i) ∈ fields → + Signature.RuleFormed.{u,v} (d.iotaEnvironment entries source recursor mode i) (d.iotaRule source i field))) + | [], [] => some ⟨by simp⟩ + | (field, i) :: fields, witness :: witnesses => do + let ht ← Signature.checkRule.{u,v} fuel (d.iotaEnvironment entries source recursor mode i) (d.iotaRule source i field) witness + let rest ← checkIota fuel entries d source recursor mode fields witnesses + return ⟨by + intro field' j hj + rcases List.mem_cons.mp hj with he | hj + · cases he; exact ht.down + · exact rest.down field' j hj⟩ + | _, _ => none + +def check (fuel : Nat) (entries : Environment β) (store : Store β) (witness : Witness β) : + Option (CheckedClaim.{u} (Checked.{u,v} entries store witness.facts.description + witness.facts.block.source witness.facts.block.recursor witness.facts.block.mode)) := do + let facts ← checkFacts.{u,v} fuel entries store witness.facts + let d := witness.facts.description + let block := witness.facts.block + let stage := d.factEnvironment entries block.source block.recursor block.mode + let eta ← Signature.checkRule.{u,v} fuel stage (d.etaRule block.source) witness.eta + let iota ← checkIota.{u,v} fuel entries d block.source block.recursor block.mode d.fields.zipIdx witness.iota + return ⟨⟨facts.down, eta.down, iota.down⟩⟩ + +theorem check_sound {fuel : Nat} {entries : Environment β} {store : Store β} {witness : Witness β} + {result} (_ : check.{u,v} fuel entries store witness = some result) : + Checked.{u,v} entries store witness.facts.description witness.facts.block.source + witness.facts.block.recursor witness.facts.block.mode := result.down + +end Ix.Theory.Certified.Structure diff --git a/Ix/Theory/Certified/Structure/Computation.lean b/Ix/Theory/Certified/Structure/Computation.lean new file mode 100644 index 000000000..a6fffc68f --- /dev/null +++ b/Ix/Theory/Certified/Structure/Computation.lean @@ -0,0 +1,84 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Structure.Reading + +namespace Ix.Theory.Certified.Structure.Description + +open Model Model.SetTheory Model.SetTheory.Tower Model.SetModel Ordinary + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + {d : Description β} {entries : Environment β} {store : Store β} {source : β} + {constants reading : Assignment β V} {levels : List Nat} + +theorem constructorApp_interp (h : CheckedShape.{u,v} entries store source d.ordinary) + (hr : ConstructorReading entries d.ordinary source constants reading) (hM : Realizes constants entries) + (hn : levels.length = d.universes) {ps xs : List V} + (hps : FitsS (Telescope.interpret constants levels (fun _ => empty) d.parameters) ps) + (hxs : FitsS (Telescope.interpret constants levels (Telescope.extend (fun _ => empty) ps) d.constructor.fields) xs) + (env : Nat → V) (args : List (AExpr β)) (hargs : args.map (interp reading levels env) = ps ++ xs) : + interp reading levels env (.appN (.const (.ctor source 0 0) (VLevel.params d.universes)) args) = + d.ordinary.constructorValue constants levels (Telescope.extend (fun _ => empty) ps) d.constructor 0 xs [] := by + rw [AExpr.interp_appN, interp, eval_params hn, hr.constructor levels hn 0 d.constructor rfl, hargs] + simpa only [List.append_nil] using Shape.constructorClosedValue_apply h hM + (show d.ordinary.constructors[0]? = some d.constructor from rfl) hps hxs + (show d.ordinary.RecursiveValuesFit constants levels (Telescope.extend (fun _ => empty) ps) d.constructor xs [] from trivial) + +theorem eta_eq (h : CheckedShape.{u,v} entries store source d.ordinary) + (hF : FieldsFormed.{u,v} entries d.level d.ordinary.parameterContext d.fields) + (hr : ConstructorReading entries d.ordinary source constants reading) (hM : Realizes constants entries) + (hn : levels.length = d.universes) : + interp reading levels (fun _ => empty) (d.etaLhs source) = + interp reading levels (fun _ => empty) (d.etaRhs source) := by + simp only [etaLhs, etaRhs, projectionDomains, AExpr.lamN_append, AExpr.interp_lamN, + hr.agrees.telescope (fun A hA => h.references A (by simpa [ordinary] using hA))] + apply Telescope.curry_congr + intro ps hps + change lamR _ (interp reading levels _ (d.ordinary.familyApp source 0 [])) _ = lamR _ _ _ + apply lamR_congr + intro x hx + have he := Shape.familyApp_interp hr.toFamilyReading hn (extra := []) (indices := []) hps (by trivial) + have hx' : x ∈ˢ app (d.ordinary.carrier constants levels (Telescope.extend (fun _ => empty) ps)) pt := by + simpa only [List.length_nil, List.map_nil, mkTower, Telescope.extend] using he ▸ hx + have hΓ := h.parameters.valid constants hM levels (Context.valid_nil constants levels (fun _ => empty)) hps + have hxs := d.projections_fit h hF hM hΓ hx' + change interp reading levels (Valuation.cons x _) (.appN _ _) = x + rw [d.constructorApp_interp h hr hM hn hps hxs _ _ (by + rw [List.map_append, projections_interp, interp_parameterVars_skip, + Valuation.skip_succ_cons, Valuation.skip_zero, ← FitsS.length_eq hps, interp_parameterVars_extend] + rfl)] + exact d.constructor_eta h hM hΓ hx' + +theorem iota_eq (h : CheckedShape.{u,v} entries store source d.ordinary) + (hF : FieldsFormed.{u,v} entries d.level d.ordinary.parameterContext d.fields) + (hr : ConstructorReading entries d.ordinary source constants reading) (hM : Realizes constants entries) + (hn : levels.length = d.universes) {i : Nat} {field : Field β} (hi : d.fields[i]? = some field) : + interp reading levels (fun _ => empty) (d.iotaLhs source i field) = + interp reading levels (fun _ => empty) (d.iotaRhs i field) := by + simp only [iotaLhs, iotaRhs, AExpr.lamN_append, AExpr.interp_lamN, + hr.agrees.telescope (fun A hA => h.references A (by simpa [ordinary] using hA))] + apply Telescope.curry_congr + intro ps hps + rw [hr.agrees.telescope (fun A hA => (h.constructors d.constructor (by simp [ordinary])).1 A + (List.mem_append_left _ hA))] + apply Telescope.curry_congr + intro xs hxs + have hΓ := h.parameters.valid constants hM levels (Context.valid_nil constants levels (fun _ => empty)) hps + have hlen : xs.length = d.fields.length := by simpa [constructor] using FitsS.length_eq hxs + have hib := (List.getElem?_eq_some_iff.mp hi).1 + change projectValue i (interp reading levels _ (.appN _ _)) = _ + rw [d.constructorApp_interp h hr hM hn hps hxs _ _ (by + rw [← Telescope.extend_append] + have hlength : (ps ++ xs).length = d.parameters.length + d.fields.length := by + rw [List.length_append, FitsS.length_eq hps, hlen] + rw [← hlength, interp_parameterVars_extend])] + have he := congrArg (fun zs : List V => zs.getD i empty) (d.constructor_iota hF hM hΓ hxs) + rw [projectValues_getD _ _ _ hib] at he + rw [he] + symm + simpa only [interp, hlen] using Telescope.extend_getD (Telescope.extend (fun _ => empty) ps) xs i (by omega) + +end Ix.Theory.Certified.Structure.Description diff --git a/Ix/Theory/Certified/Structure/Publish.lean b/Ix/Theory/Certified/Structure/Publish.lean new file mode 100644 index 000000000..0360343c5 --- /dev/null +++ b/Ix/Theory/Certified/Structure/Publish.lean @@ -0,0 +1,161 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Structure.Checked + +namespace Ix.Theory.Certified.Structure + +open Model Model.SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +theorem ordinary_family_lookup {entries : Environment β} {store : Store β} + {source recursor : β} {shape : Ordinary.Shape β} {mode : Inductive.ElimMode} + (h : Ordinary.CheckedBlock.{u,v} entries store source recursor shape mode) : + shape.publishedEnvironment entries source recursor mode (.member source 0) = some shape.familyEntry := by + apply Environment.insert_old h.recursorChecked.fresh + simp [Ordinary.Shape.constructorEnvironment, Environment.overlay, Ordinary.Shape.constructorEntries, + Ordinary.Shape.familyEnvironment] + +namespace Description + +def publishedEntry (d : Description β) (source : β) : ConstantEntry β := + { d.factEntry source with equations := d.equations source } + +def publishedEnvironment (d : Description β) (entries : Environment β) (source recursor : β) + (mode : Inductive.ElimMode) : Environment β := + (d.ordinary.publishedEnvironment entries source recursor mode).insert (.member source 0) (d.publishedEntry source) + +variable {d : Description β} {entries : Environment β} {store : Store β} + {source recursor : β} {mode : Inductive.ElimMode} + +theorem iotaEnvironment_references {i : Nat} {e : AExpr β} + (h : e.ReferencesIn (d.iotaEnvironment entries source recursor mode i)) : + e.ReferencesIn (d.factEnvironment entries source recursor mode) := by + intro r hr + have he := h r hr + by_cases heq : r = .member source 0 + · simp [factEnvironment, Environment.insert, heq] + · simpa only [iotaEnvironment, factEnvironment, Environment.insert, if_neg heq] using he + +theorem factEnvironment_wf (h : FactsChecked.{u,v} entries store d source recursor mode) (hE : entries.WF) : + (d.factEnvironment entries source recursor mode).WF := by + have hbase := Ordinary.Shape.publishedEnvironment_wf h.block hE + have hfam := ordinary_family_lookup h.block + exact hbase.insert (hbase.typeScope _ d.ordinary.familyEntry hfam) (by simp [factEntry, Ordinary.Shape.familyEntry]) + (hbase.typeReferences _ d.ordinary.familyEntry hfam) (by simp [factEntry, Ordinary.Shape.familyEntry]) + (by simp [factEntry, Ordinary.Shape.familyEntry]) (by simp [factEntry, Ordinary.Shape.familyEntry]) + h.scope h.references + +theorem publishedEnvironment_wf (h : Checked.{u,v} entries store d source recursor mode) (hE : entries.WF) : + (d.publishedEnvironment entries source recursor mode).WF := by + have hbase := d.factEnvironment_wf h.facts hE + have hwf := hbase.insert (r := .member source 0) (entry := d.publishedEntry source) + (hbase.typeScope _ (d.factEntry source) (Environment.insert_same ..)) + (by simp [publishedEntry, factEntry, Ordinary.Shape.familyEntry]) + (hbase.typeReferences _ (d.factEntry source) (Environment.insert_same ..)) + (by simp [publishedEntry, factEntry, Ordinary.Shape.familyEntry]) + (by + intro law hl + rcases List.mem_cons.mp hl with he | hrest + · cases he; exact h.eta.scope.2 + · obtain ⟨⟨field, i⟩, hfi, he⟩ := List.mem_map.mp hrest + cases he + exact (h.iota field i hfi).scope.2) + (by + intro law hl + rcases List.mem_cons.mp hl with he | hrest + · cases he; exact h.eta.references.2 + · obtain ⟨⟨field, i⟩, hfi, he⟩ := List.mem_map.mp hrest + cases he + exact ⟨iotaEnvironment_references (h.iota field i hfi).references.2.1, + iotaEnvironment_references (h.iota field i hfi).references.2.2⟩) + h.facts.scope (fun fact hf => (h.facts.references fact hf).insert) + simpa only [publishedEnvironment, factEnvironment, Environment.insert_replace] using hwf + +theorem publishedEnvironment_old (h : Checked.{u,v} entries store d source recursor mode) + {r : ConstRef β} {entry : ConstantEntry β} (hr : entries r = some entry) : + d.publishedEnvironment entries source recursor mode r = some entry := by + simp only [publishedEnvironment, Environment.insert, + if_neg (fresh_ne (h.facts.block.shapeChecked.fresh _ (List.mem_cons_self ..)) hr)] + exact Ordinary.Shape.publishedEnvironment_old h.facts.block hr + +variable {V : Type v} [SetTheory V] + +theorem factAssignment_realizes (h : FactsChecked.{u,v} entries store d source recursor mode) + (hE : entries.WF) (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (d.ordinary.recursorAssignment constants source recursor mode) + (d.factEnvironment entries source recursor mode) := by + have hbase := Ordinary.Shape.publishedAssignment_realizes h.block hE constants hM + have hr := Ordinary.Shape.recursorAssignment_reading h.block.shapeChecked h.block.recursorChecked constants + apply hbase.insert + constructor + · exact hbase.typeValid _ d.ordinary.familyEntry (ordinary_family_lookup h.block) + · exact hbase.member _ d.ordinary.familyEntry (ordinary_family_lookup h.block) + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl; cases hl + · intro fact hf levels hn env + obtain ⟨⟨field, i⟩, hi, rfl⟩ := List.mem_map.mp hf + have hscope := h.scope _ (List.mem_map.mpr ⟨(field, i), hi, rfl⟩) + exact d.projection_meaning h.block.shapeChecked h.fields hr.toFamilyReading hM hn hbase h.domains + (List.mk_mem_zipIdx_iff_getElem?.mp hi) hscope env + +theorem publishedAssignment_realizes (h : Checked.{u,v} entries store d source recursor mode) + (hE : entries.WF) (constants : Assignment β V) (hM : Realizes constants entries) : + Realizes (d.ordinary.recursorAssignment constants source recursor mode) + (d.publishedEnvironment entries source recursor mode) := by + have hbase := d.factAssignment_realizes h.facts hE constants hM + have hr := Ordinary.Shape.recursorAssignment_reading h.facts.block.shapeChecked h.facts.block.recursorChecked constants + have hlocal : EntryRealization (d.ordinary.recursorAssignment constants source recursor mode) + (.member source 0) (d.publishedEntry source) := by + constructor + · exact hbase.typeValid _ (d.factEntry source) (Environment.insert_same ..) + · exact hbase.member _ (d.factEntry source) (Environment.insert_same ..) + · intro body hb; cases hb + · intro body hb; cases hb + · intro law hl levels hn env + rcases List.mem_cons.mp hl with he | hrest + · cases he + exact (interp_closed (d.etaLhs source) _ levels h.eta.scope.2.1 (fun _ => empty) env).symm.trans + ((d.eta_eq h.facts.block.shapeChecked h.facts.fields hr.toConstructorReading hM hn).trans + (interp_closed (d.etaRhs source) _ levels h.eta.scope.2.2 (fun _ => empty) env)) + · obtain ⟨⟨field, i⟩, hfi, he⟩ := List.mem_map.mp hrest + cases he + exact (interp_closed (d.iotaLhs source i field) _ levels (h.iota field i hfi).scope.2.1 (fun _ => empty) env).symm.trans + ((d.iota_eq h.facts.block.shapeChecked h.facts.fields hr.toConstructorReading hM hn + (List.mk_mem_zipIdx_iff_getElem?.mp hfi)).trans + (interp_closed (d.iotaRhs i field) _ levels (h.iota field i hfi).scope.2.2 (fun _ => empty) env)) + · exact hbase.factMeaning _ (d.factEntry source) (Environment.insert_same ..) + simpa only [publishedEnvironment, factEnvironment, Environment.insert_replace] using hbase.insert hlocal + +end Description + +/-- The enhanced family entry has an exact source shape and exact recursor; +the projection facts and equations are wholly computed from that shape. -/ +def EntrySource (store : Store β) (r : ConstRef β) (entry : ConstantEntry β) : Prop := + ∃ d : Description β, ∃ source recursor mode, + store.blocks source = some ⟨[d.ordinary.source source]⟩ ∧ + d.ordinary.RecursorSourceMatches store source recursor mode ∧ + r = .member source 0 ∧ entry = d.publishedEntry source + +theorem publishedEntry_source {entries : Environment β} {store : Store β} + {d : Description β} {source recursor : β} {mode : Inductive.ElimMode} + (h : Checked.{u,v} entries store d source recursor mode) {r : ConstRef β} {entry : ConstantEntry β} + (hr : d.publishedEnvironment entries source recursor mode r = some entry) : + entries r = some entry ∨ Ordinary.EntrySource store r entry ∨ EntrySource store r entry := by + unfold Description.publishedEnvironment Environment.insert at hr + split at hr + next he => + cases Option.some.inj hr + exact Or.inr (Or.inr ⟨d, source, recursor, mode, h.facts.block.shapeChecked.exactSource, + h.facts.block.recursorChecked.exactSource, he, rfl⟩) + next => + rcases Ordinary.publishedEntry_source h.facts.block hr with hold | hnew + · exact Or.inl hold + · exact Or.inr (Or.inl hnew) + +end Ix.Theory.Certified.Structure diff --git a/Ix/Theory/Certified/Structure/Reading.lean b/Ix/Theory/Certified/Structure/Reading.lean new file mode 100644 index 000000000..8d2c2b7ec --- /dev/null +++ b/Ix/Theory/Certified/Structure/Reading.lean @@ -0,0 +1,149 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Structure.Value + +namespace Ix.Theory.Certified.Structure + +open Model Model.SetTheory Model.SetTheory.Tower + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +theorem FieldsFormed.field_reading {entries : Environment β} {w : VLevel} {Γ : Context β} + {fields : List (Field β)} (h : FieldsFormed.{u,v} entries w Γ fields) + (constants : Assignment β V) (hM : Realizes constants entries) (levels : List Nat) + {env : Nat → V} (hΓ : Γ.Valid constants levels env) {xs : List V} + (hxs : FitsS (Telescope.interpret constants levels env (fields.map Field.domain)) xs) + {i : Nat} {field : Field β} (hf : fields[i]? = some field) : + WellDenoted constants levels (Telescope.extend env (xs.take i)) field.domain ∧ + interp constants levels (Telescope.extend env (xs.take i)) field.domain ∈ˢ + (univ (field.level.eval levels) : V) ∧ + xs.getD i empty ∈ˢ interp constants levels (Telescope.extend env (xs.take i)) field.domain := by + induction h generalizing env xs i with + | nil => simp at hf + | @cons Γ head rest hA hz htail ih => + cases xs with + | nil => exact hxs.elim + | cons x xs => + have ht := hA V constants hM levels env hΓ + cases i with + | zero => + cases Option.some.inj hf + exact ⟨ht.1, ht.2.2, hxs.1⟩ + | succ i => + exact ih (hΓ.push ht.1 hxs.1) hxs.2 hf + +theorem projections_interp (source : β) (count : Nat) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) : + (projections source count).map (interp constants levels env) = projectValues count (env 0) := by + apply List.ext_get (by simp [projections, projectValues_length]) + intro i hi hj + have hic : i < count := by simpa [projections] using hi + simpa only [List.get_eq_getElem, projections, List.getElem_map, List.getElem_range, interp, projectValue, projectValues] using + (projList_get count i (ssnd (sfst (env 0))) hic).symm + +theorem projectionValuation (env : Nat → V) (x : V) (i : Nat) : + Valuation.skip 1 i (Telescope.extend (Valuation.cons x env) (projectValues i x)) = + Telescope.extend env (projectValues i x) := by + simpa only [projectValues_length, Nat.add_zero, Valuation.skip_succ_cons, Valuation.skip_zero] using + Telescope.skip_extend_at (Valuation.cons x env) (projectValues i x) 1 0 + +theorem fieldResult_interp (source : β) (i : Nat) (field : Field β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (x : V) : + interp constants levels (Valuation.cons x env) (fieldResult source i field) = + interp constants levels (Telescope.extend env (projectValues i x)) field.domain := by + rw [fieldResult, AExpr.interp_instRev, projections_interp, interp_liftN] + exact congrArg (fun env => interp constants levels env field.domain) (projectionValuation env x i) + +theorem fieldResult_wellDenoted (source : β) (i : Nat) (field : Field β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (x : V) + (hf : WellDenoted constants levels (Telescope.extend env (projectValues i x)) field.domain) : + WellDenoted constants levels (Valuation.cons x env) (fieldResult source i field) := by + apply AExpr.wellDenoted_instRev + · intro e he + obtain ⟨j, _, rfl⟩ := List.mem_map.mp he + trivial + · rw [projections_interp, wellDenoted_liftN] + simpa only [Valuation.cons, projectionValuation] using hf + +namespace Description + +variable {d : Description β} {entries : Environment β} {store : Store β} {source : β} + {constants reading : Assignment β V} {levels : List Nat} + +/-- The dependent result uses the projections of the very same major value. +Its formation is derived from the checked field telescope in the old model. -/ +theorem fieldResult_meaning (h : Ordinary.CheckedShape.{u,v} entries store source d.ordinary) + (hF : FieldsFormed.{u,v} entries d.level d.ordinary.parameterContext d.fields) + (hr : Ordinary.FamilyReading entries d.ordinary source constants reading) + (hM : Realizes constants entries) {env : Nat → V} + (hΓ : d.ordinary.parameterContext.Valid constants levels env) {i : Nat} {field : Field β} + (hi : d.fields[i]? = some field) {x : V} + (hx : x ∈ˢ app (d.ordinary.carrier constants levels env) pt) : + WellDenoted reading levels (Valuation.cons x env) (fieldResult source i field) ∧ + interp reading levels (Valuation.cons x env) (fieldResult source i field) ∈ˢ + (univ (field.level.eval levels) : V) ∧ + projectValue i x ∈ˢ interp reading levels (Valuation.cons x env) (fieldResult source i field) := by + have hib := (List.getElem?_eq_some_iff.mp hi).1 + have hxs := d.projections_fit h hF hM hΓ hx + have ht := hF.field_reading constants hM levels hΓ hxs hi + rw [projectValues_take _ _ _ (Nat.le_of_lt hib), projectValues_getD _ _ _ hib] at ht + have href : field.domain.ReferencesIn entries := + (h.constructors d.constructor (by simp [ordinary])).1 field.domain + (by simpa [constructor] using List.mem_map.mpr ⟨field, List.mem_of_getElem? hi, rfl⟩) + refine ⟨fieldResult_wellDenoted source i field reading levels env x ?_, ?_, ?_⟩ + · exact (hr.agrees.wellDenoted href levels _).mpr ht.1 + · rw [fieldResult_interp, hr.agrees.interp href] + exact ht.2.1 + · rw [fieldResult_interp, hr.agrees.interp href] + exact ht.2.2 + +theorem projection_meaning (h : Ordinary.CheckedShape.{u,v} entries store source d.ordinary) + (hF : FieldsFormed.{u,v} entries d.level d.ordinary.parameterContext d.fields) + (hr : Ordinary.FamilyReading entries d.ordinary source constants reading) + (hM : Realizes constants entries) (hn : levels.length = d.universes) + {stage : Environment β} (hstage : Realizes reading stage) + (hD : Telescope.Formed.{u,v} stage [] (d.projectionDomains source)) + {i : Nat} {field : Field β} (hi : d.fields[i]? = some field) + (hs : (d.projection source i field).Scope d.universes 0 ∧ + (d.projectionType source i field).Scope d.universes 0) (env : Nat → V) : + (ConstantFact.typed (d.projection source i field) (d.projectionType source i field)).Meaning + reading (.member source 0) levels env := by + obtain ⟨_, _, ht⟩ := hD.lamN_semantics reading hstage levels + (.proj (.member source 0) i (.bvar 0)) (fieldResult source i field) field.level + have hm := ht (fun _ => empty) (Context.valid_nil reading levels (fun _ => empty)) (by + intro args hargs + obtain ⟨ps, zs, rfl, hps, hzs⟩ := (Telescope.fits_append_iff reading levels (fun _ => empty) + d.parameters [d.ordinary.familyApp source 0 []] args).mp hargs + have hp := hr.agrees.telescope (fun A hA => h.references A (by simpa [ordinary] using hA)) levels (fun _ => empty) + rw [hp] at hps + cases zs with + | nil => exact hzs.elim + | cons x rest => + cases rest with + | cons _ _ => exact hzs.2.elim + | nil => + have he := Ordinary.Shape.familyApp_interp hr hn (extra := []) (indices := []) hps (by trivial) + have hx : x ∈ˢ app (d.ordinary.carrier constants levels (Telescope.extend (fun _ => empty) ps)) pt := by + simpa only [List.length_nil, List.map_nil, mkTower, Telescope.extend] using he ▸ hzs.1 + have hΓ := h.parameters.valid constants hM levels (Context.valid_nil constants levels (fun _ => empty)) hps + have ht := d.fieldResult_meaning h hF hr hM hΓ hi hx + simpa only [Telescope.extend_append, Telescope.extend, interp, Valuation.cons_zero, WellDenoted] using + (show True ∧ WellDenoted reading levels (Valuation.cons x (Telescope.extend (fun _ => empty) ps)) + (fieldResult source i field) ∧ + projectValue i x ∈ˢ interp reading levels (Valuation.cons x (Telescope.extend (fun _ => empty) ps)) + (fieldResult source i field) ∧ + interp reading levels (Valuation.cons x (Telescope.extend (fun _ => empty) ps)) + (fieldResult source i field) ∈ˢ (univ (field.level.eval levels) : V) from + ⟨trivial, ht.1, ht.2.2, ht.2.1⟩)) + refine ⟨(wellDenoted_closed _ reading levels hs.1 (fun _ => empty) env).mp hm.1, + (wellDenoted_closed _ reading levels hs.2 (fun _ => empty) env).mp hm.2.1, ?_⟩ + rw [← interp_closed _ reading levels hs.1 (fun _ => empty) env, + ← interp_closed _ reading levels hs.2 (fun _ => empty) env] + exact hm.2.2.1 + +end Description +end Ix.Theory.Certified.Structure diff --git a/Ix/Theory/Certified/Structure/Syntax.lean b/Ix/Theory/Certified/Structure/Syntax.lean new file mode 100644 index 000000000..92d513150 --- /dev/null +++ b/Ix/Theory/Certified/Structure/Syntax.lean @@ -0,0 +1,111 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Ordinary.Checked +import Ix.Theory.Model.TelescopeSemantics + +namespace Ix.Theory.Certified.Structure + +open Model + +universe u v +variable {β : Type u} + +structure Field (β : Type u) where + domain : AExpr β + level : VLevel +deriving DecidableEq + +/-- A single nonrecursive constructor with dependent fields. The additional +field sorts license projections out of a proof-valued structure. -/ +structure Description (β : Type u) where + universes : Nat + parameters : List (AExpr β) + fields : List (Field β) + level : VLevel +deriving DecidableEq + +def Description.constructor (d : Description β) : Ordinary.Constructor β := + ⟨d.fields.map Field.domain, [], []⟩ + +def Description.ordinary (d : Description β) : Ordinary.Shape β := + ⟨d.universes, d.parameters, [], d.level, [d.constructor]⟩ + +def projections (source : β) (count : Nat) : List (AExpr β) := + (List.range count).map fun i => .proj (.member source 0) i (.bvar 0) + +/-- Insert the major premise below preceding fields, then substitute their +actual projections in outermost-first order. -/ +def fieldResult (source : β) (index : Nat) (field : Field β) : AExpr β := + (field.domain.liftN 1 index).instRev (projections source index) + +def Description.projectionDomains (d : Description β) (source : β) : List (AExpr β) := + d.parameters ++ [d.ordinary.familyApp source 0 []] + +def Description.projection (d : Description β) (source : β) (i : Nat) (field : Field β) : AExpr β := + .lamN (zeroCondition field.level) (d.projectionDomains source) (.proj (.member source 0) i (.bvar 0)) + +def Description.projectionType (d : Description β) (source : β) (i : Nat) (field : Field β) : AExpr β := + .forallN (zeroCondition field.level) (d.projectionDomains source) (fieldResult source i field) + +def Description.facts (d : Description β) (source : β) : List (ConstantFact β) := + d.fields.zipIdx.map fun (field, i) => .typed (d.projection source i field) (d.projectionType source i field) + +def Description.etaLhs (d : Description β) (source : β) : AExpr β := + .lamN (zeroCondition d.level) (d.projectionDomains source) + (.appN (.const (.ctor source 0 0) (VLevel.params d.universes)) + (Ordinary.parameterVars 1 d.parameters.length ++ projections source d.fields.length)) + +def Description.etaRhs (d : Description β) (source : β) : AExpr β := + .lamN (zeroCondition d.level) (d.projectionDomains source) (.bvar 0) + +def Description.iotaLhs (d : Description β) (source : β) (i : Nat) (field : Field β) : AExpr β := + .lamN (zeroCondition field.level) (d.parameters ++ d.constructor.fields) + (.proj (.member source 0) i (.appN (.const (.ctor source 0 0) (VLevel.params d.universes)) + (Ordinary.parameterVars 0 (d.parameters.length + d.fields.length)))) + +def Description.iotaRhs (d : Description β) (i : Nat) (field : Field β) : AExpr β := + .lamN (zeroCondition field.level) (d.parameters ++ d.constructor.fields) + (.bvar (d.fields.length - 1 - i)) + +def Description.equations (d : Description β) (source : β) : List (ConstantEquation β) := + ⟨d.etaLhs source, d.etaRhs source⟩ :: d.fields.zipIdx.map fun (field, i) => + ⟨d.iotaLhs source i field, d.iotaRhs i field⟩ + +inductive FieldsFormed (entries : Environment β) (w : VLevel) : Context β → List (Field β) → Prop + | nil {Γ} : FieldsFormed entries w Γ [] + | cons {Γ field rest} + (domain : TypingClaim.{u,v} entries Γ field.domain (.sort field.level)) + (proofField : ∀ levels, w.eval levels = 0 → field.level.eval levels = 0) + (tail : FieldsFormed entries w (Γ.push field.domain) rest) : + FieldsFormed entries w Γ (field :: rest) + +theorem FieldsFormed.formed {entries : Environment β} {w : VLevel} {Γ : Context β} + {fields : List (Field β)} (h : FieldsFormed.{u,v} entries w Γ fields) : + Telescope.Formed.{u,v} entries Γ (fields.map Field.domain) := by + induction h with + | nil => exact .nil + | cons hA _ _ ih => exact .cons _ hA ih + +theorem FieldsFormed.prop {entries : Environment β} {w : VLevel} {Γ : Context β} + {fields : List (Field β)} (h : FieldsFormed.{u,v} entries w Γ fields) : + TelescopeProp.{u,v} entries Γ (fields.map Field.domain) w := by + induction h with + | nil => exact TelescopeProp.nil entries _ w + | cons hA hz _ ih => exact TelescopeProp.cons hA hz ih + +def checkFields [DecidableEq β] (fuel n : Nat) (entries : Environment β) (w : VLevel) : + (Γ : Context β) → (fields : List (Field β)) → List (TypingWitness β) → + Option (CheckedClaim.{u} (FieldsFormed.{u,v} entries w Γ fields)) + | _, [], [] => some ⟨.nil⟩ + | Γ, field :: fields, witness :: witnesses => + if hz : checkZeroImplies w field.level = true then do + let hA ← verifyType.{u,v} fuel n entries Γ field.domain (.sort field.level) witness + let rest ← checkFields fuel n entries w (Γ.push field.domain) fields witnesses + return ⟨.cons hA.down (checkZeroImplies_sound hz) rest.down⟩ + else none + | _, _, _ => none + +end Ix.Theory.Certified.Structure diff --git a/Ix/Theory/Certified/Structure/Value.lean b/Ix/Theory/Certified/Structure/Value.lean new file mode 100644 index 000000000..0595f507a --- /dev/null +++ b/Ix/Theory/Certified/Structure/Value.lean @@ -0,0 +1,141 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Structure.Syntax + +namespace Ix.Theory.Certified.Structure + +open Model Model.SetTheory Model.SetTheory.Tower + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +noncomputable def projectValues (count : Nat) (x : V) : List V := + projList count (ssnd (sfst x)) + +theorem projectValues_length (count : Nat) (x : V) : + (projectValues count x).length = count := projList_length .. + +theorem projectValues_getD (count i : Nat) (x : V) (hi : i < count) : + (projectValues count x).getD i empty = projectValue i x := by + rw [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem + (show i < (projectValues count x).length by simpa only [projectValues_length] using hi), Option.getD_some] + exact projList_get count i (ssnd (sfst x)) hi + +theorem projectValues_take (count i : Nat) (x : V) (hi : i ≤ count) : + (projectValues count x).take i = projectValues i x := projList_take count i _ hi + +theorem projectValues_node (count : Nat) (xs : List V) (hlen : xs.length = count) (g : V) : + projectValues count (spair (inj 0 (mkTower xs)) g) = xs := by + simp only [projectValues, sfst_spair, ssnd_inj, projList_mkTower _ _ hlen] + +theorem projectValues_pt (count : Nat) : + projectValues count (pt : V) = List.replicate count pt := by + simp only [projectValues, sfst_pt, ssnd_pt, projList_pt] + +namespace Description + +variable (d : Description β) (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + +theorem positions_empty (xs : List V) (hlen : xs.length = d.constructor.fields.length) : + d.ordinary.positions constants levels env (inj 0 (mkTower xs)) = empty := by + apply ext + intro p + constructor + · intro hp + obtain ⟨j, field, _, hj, _, _⟩ := Ordinary.Shape.mem_positions + (show d.ordinary.constructors[0]? = some d.constructor from rfl) hlen hp + simp [constructor] at hj + · intro hp + exact (not_mem_empty p hp).elim + +theorem branches_empty (xs : List V) (hlen : xs.length = d.constructor.fields.length) : + d.ordinary.branches constants levels env d.constructor 0 xs [] = empty := by + rw [Ordinary.Shape.branches, d.positions_empty constants levels env xs hlen] + apply ext + intro p + constructor + · intro hp + obtain ⟨x, hx, _⟩ := mem_graph.mp hp + exact (not_mem_empty x hx).elim + · intro hp + exact (not_mem_empty p hp).elim + +theorem constructorValue_eq (xs : List V) (hlen : xs.length = d.constructor.fields.length) : + d.ordinary.constructorValue constants levels env d.constructor 0 xs [] = + IndexedContainer.node (d.level.eval levels) (inj 0 (mkTower xs)) empty := by + rw [Ordinary.Shape.constructorValue, d.branches_empty constants levels env xs hlen] + rfl + +variable {d constants levels env} {entries : Environment β} {store : Store β} {source : β} + +theorem carrier_member (h : Ordinary.CheckedShape.{u,v} entries store source d.ordinary) + (hM : Realizes constants entries) (hΓ : d.ordinary.parameterContext.Valid constants levels env) + {x : V} (hx : x ∈ˢ app (d.ordinary.carrier constants levels env) pt) : + ∃ xs, FitsS (Telescope.interpret constants levels env d.constructor.fields) xs ∧ + x = IndexedContainer.node (d.level.eval levels) (inj 0 (mkTower xs)) empty := by + rw [Ordinary.Shape.carrier, IndexedContainer.carrier_eq (Ordinary.Shape.container_wf h hM hΓ) + (show (pt : V) ∈ˢ (d.ordinary.container constants levels env).indices from pt_mem_unitSet)] at hx + obtain ⟨a, ha, g, hg, rfl⟩ := IndexedContainer.mem_fibre.mp hx + obtain ⟨i, ctor, xs, hc, hxs, rfl⟩ := Ordinary.Shape.mem_allShapes (mem_sep.mp ha).1 + have hi : i = 0 := by + have hi := (List.getElem?_eq_some_iff.mp hc).1 + simp only [ordinary, List.length_singleton] at hi + omega + subst i + have he : ctor = d.constructor := by simpa only [ordinary, List.getElem?_cons_zero, Option.some.injEq] using hc.symm + subst ctor + have hg' : g = empty := by + change g ∈ˢ piSet (d.ordinary.positions constants levels env _) _ at hg + rw [d.positions_empty constants levels env xs (FitsS.length_eq hxs)] at hg + rw [← eq_graph_app_of_mem_piSet hg] + apply ext + intro p + constructor + · intro hp + obtain ⟨x, hx, _⟩ := mem_graph.mp hp + exact (not_mem_empty x hx).elim + · intro hp + exact (not_mem_empty p hp).elim + exact ⟨xs, hxs, congrArg (IndexedContainer.node (d.level.eval levels) (inj 0 (mkTower xs))) hg'⟩ + +theorem projections_fit (h : Ordinary.CheckedShape.{u,v} entries store source d.ordinary) + (hF : FieldsFormed.{u,v} entries d.level d.ordinary.parameterContext d.fields) + (hM : Realizes constants entries) (hΓ : d.ordinary.parameterContext.Valid constants levels env) + {x : V} (hx : x ∈ˢ app (d.ordinary.carrier constants levels env) pt) : + FitsS (Telescope.interpret constants levels env d.constructor.fields) (projectValues d.fields.length x) := by + obtain ⟨xs, hxs, rfl⟩ := carrier_member h hM hΓ hx + have hlen : xs.length = d.fields.length := by simpa [constructor] using FitsS.length_eq hxs + by_cases hw : d.level.eval levels = 0 + · rw [IndexedContainer.node, if_pos hw, projectValues_pt] + simpa only [constructor, List.length_map] using fitsS_replicate_of_prop (hF.prop V constants hM levels env hΓ hw) hxs + · rw [IndexedContainer.node, if_neg hw, projectValues_node _ xs hlen] + exact hxs + +theorem constructor_eta (h : Ordinary.CheckedShape.{u,v} entries store source d.ordinary) + (hM : Realizes constants entries) (hΓ : d.ordinary.parameterContext.Valid constants levels env) + {x : V} (hx : x ∈ˢ app (d.ordinary.carrier constants levels env) pt) : + d.ordinary.constructorValue constants levels env d.constructor 0 (projectValues d.fields.length x) [] = x := by + obtain ⟨xs, hxs, rfl⟩ := carrier_member h hM hΓ hx + rw [d.constructorValue_eq constants levels env _ (by simp [constructor, projectValues_length])] + by_cases hw : d.level.eval levels = 0 + · simp only [IndexedContainer.node, if_pos hw] + · simp only [IndexedContainer.node, if_neg hw, + projectValues_node _ xs (by simpa [constructor] using FitsS.length_eq hxs)] + +theorem constructor_iota (hF : FieldsFormed.{u,v} entries d.level d.ordinary.parameterContext d.fields) + (hM : Realizes constants entries) (hΓ : d.ordinary.parameterContext.Valid constants levels env) + {xs : List V} (hxs : FitsS (Telescope.interpret constants levels env d.constructor.fields) xs) : + projectValues d.fields.length (d.ordinary.constructorValue constants levels env d.constructor 0 xs []) = xs := by + have hlen := FitsS.length_eq hxs + rw [d.constructorValue_eq constants levels env xs hlen] + by_cases hw : d.level.eval levels = 0 + · rw [IndexedContainer.node, if_pos hw, projectValues_pt] + exact Telescope.fits_unique_of_prop (hF.prop V constants hM levels env hΓ hw) + (by simpa only [List.length_map] using fitsS_replicate_of_prop (hF.prop V constants hM levels env hΓ hw) hxs) hxs + · rw [IndexedContainer.node, if_neg hw, projectValues_node _ xs (by simpa [constructor] using hlen)] + +end Description +end Ix.Theory.Certified.Structure diff --git a/Ix/Theory/Certified/Telescope.lean b/Ix/Theory/Certified/Telescope.lean new file mode 100644 index 000000000..06c831053 --- /dev/null +++ b/Ix/Theory/Certified/Telescope.lean @@ -0,0 +1,172 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Checker +import Ix.Theory.Model.Inductive.Telescope + +namespace Ix.Theory.Certified + +open Model Model.SetTheory Model.SetTheory.Tower + +universe u v +variable {β : Type u} [DecidableEq β] + +structure DomainWitness (β : Type u) where + level : VLevel + typing : TypingWitness β + +/-- A positive carrier bounds each field domain. Prop carriers may quantify +over larger domains; this does not by itself license large elimination. -/ +def checkDomainBound (n : Nat) (bound : Option VLevel) (level : VLevel) : Bool := + match bound with + | none => true + | some w => LevelEq.check n w .zero || LevelEq.check n (.max level w) w + +theorem checkDomainBound_sound {n : Nat} {bound : Option VLevel} {level : VLevel} + (h : checkDomainBound n bound level = true) : + ∀ w, bound = some w → ∀ levels, + w.eval levels ≠ 0 → level.eval levels ≤ w.eval levels := by + intro w hw levels hpos + subst bound + simp only [checkDomainBound, Bool.or_eq_true] at h + rcases h with h | h + · exact (hpos ((LevelEq.check_sound h).2.2 levels)).elim + · have he := (LevelEq.check_sound h).2.2 levels + change max (level.eval levels) (w.eval levels) = w.eval levels at he + exact he ▸ Nat.le_max_left _ _ + +/-- Bounds are consequences of checked field sorts, uniformly over every +compatible model and satisfying prefix. -/ +def TelescopeBound (entries : Environment β) (Γ : Context β) (domains : List (AExpr β)) + (bound : Option VLevel) : Prop := + ∀ w, bound = some w → ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + Realizes constants entries → ∀ levels env, Γ.Valid constants levels env → + w.eval levels ≠ 0 → BoundS (w.eval levels) (Telescope.interpret constants levels env domains) + +omit [DecidableEq β] in +theorem TelescopeBound.nil (entries : Environment β) (Γ : Context β) (bound : Option VLevel) : + TelescopeBound.{u,v} entries Γ [] bound := fun _ _ _ _ _ _ _ _ _ _ => trivial + +omit [DecidableEq β] in +theorem TelescopeBound.cons {entries : Environment β} {Γ : Context β} + {A : AExpr β} {rest : List (AExpr β)} {bound : Option VLevel} {l : VLevel} + (hA : TypingClaim.{u,v} entries Γ A (.sort l)) + (hl : ∀ w, bound = some w → ∀ levels, w.eval levels ≠ 0 → l.eval levels ≤ w.eval levels) + (hrest : TelescopeBound.{u,v} entries (Γ.push A) rest bound) : + TelescopeBound.{u,v} entries Γ (A :: rest) bound := by + intro w hw V _ constants hM levels env hΓ hpos + have htype := hA V constants hM levels env hΓ + refine ⟨univ_mono (hl w hw levels hpos) _ htype.2.2, ?_⟩ + intro x hx + exact hrest w hw V constants hM levels (Valuation.cons x env) (hΓ.push htype.1 hx) hpos + +/-- A finite witness contains only proposed sorts and typing rule choices. +Every domain is checked in the context extended by its actual predecessors. -/ +def verifyTelescope (fuel n : Nat) (entries : Environment β) (bound : Option VLevel) : + (Γ : Context β) → (domains : List (AExpr β)) → List (DomainWitness β) → + Option (CheckedClaim.{u} (Telescope.Formed.{u,v} entries Γ domains ∧ + TelescopeBound.{u,v} entries Γ domains bound)) + | Γ, [], [] => some ⟨⟨.nil, TelescopeBound.nil entries Γ bound⟩⟩ + | Γ, A :: rest, witness :: witnesses => + if hl : checkDomainBound n bound witness.level = true then do + let hA ← verifyType.{u,v} fuel n entries Γ A (.sort witness.level) witness.typing + let hrest ← verifyTelescope fuel n entries bound (Γ.push A) rest witnesses + return ⟨⟨.cons witness.level hA.down hrest.down.1, + TelescopeBound.cons hA.down (checkDomainBound_sound hl) hrest.down.2⟩⟩ + else none + | _, _, _ => none + +theorem verifyTelescope_sound {fuel n : Nat} {entries : Environment β} {bound : Option VLevel} + {Γ : Context β} {domains : List (AExpr β)} {witnesses : List (DomainWitness β)} + {result} (_ : verifyTelescope.{u,v} fuel n entries bound Γ domains witnesses = some result) : + Telescope.Formed.{u,v} entries Γ domains ∧ TelescopeBound.{u,v} entries Γ domains bound := + result.down + +/-- Indices are checked against their actual dependent telescope, with every +earlier argument substituted before the next check. -/ +def ArgumentsFit (entries : Environment β) (Γ : Context β) + (domains args : List (AExpr β)) : Prop := + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), Realizes constants entries → + ∀ levels env, Γ.Valid constants levels env → + FitsS (Telescope.interpret constants levels env domains) (args.map (interp constants levels env)) + +omit [DecidableEq β] in +theorem ArgumentsFit.nil (entries : Environment β) (Γ : Context β) : + ArgumentsFit.{u,v} entries Γ [] [] := fun _ _ _ _ _ _ _ => trivial + +omit [DecidableEq β] in +theorem ArgumentsFit.cons {entries : Environment β} {Γ : Context β} + {A a : AExpr β} {domains args : List (AExpr β)} + (ha : TypingClaim.{u,v} entries Γ a A) + (hrest : ArgumentsFit.{u,v} entries Γ (Telescope.inst a domains) args) : + ArgumentsFit.{u,v} entries Γ (A :: domains) (a :: args) := by + intro V _ constants hM levels env hΓ + refine ⟨(ha V constants hM levels env hΓ).2.2, ?_⟩ + have h := (Telescope.fits_inst constants levels env a domains 0 _).mp + (hrest V constants hM levels env hΓ) + simpa only [Valuation.skip_zero, Valuation.insert_zero] using h + +def verifyArguments (fuel n : Nat) (entries : Environment β) (Γ : Context β) : + (domains args : List (AExpr β)) → List (TypingWitness β) → + Option (CheckedClaim.{u} (ArgumentsFit.{u,v} entries Γ domains args)) + | [], [], [] => some ⟨ArgumentsFit.nil entries Γ⟩ + | A :: domains, a :: args, witness :: witnesses => do + let ha ← verifyType.{u,v} fuel n entries Γ a A witness + let hrest ← verifyArguments fuel n entries Γ (Telescope.inst a domains) args witnesses + return ⟨ArgumentsFit.cons ha.down hrest.down⟩ + | _, _, _ => none + +theorem verifyArguments_sound {fuel n : Nat} {entries : Environment β} {Γ : Context β} + {domains args : List (AExpr β)} {witnesses : List (TypingWitness β)} + {result} (_ : verifyArguments.{u,v} fuel n entries Γ domains args witnesses = some result) : + ArgumentsFit.{u,v} entries Γ domains args := result.down + +def checkZeroImplies (a b : VLevel) : Bool := + decide ((zeroCondition a).inter (zeroCondition b) = zeroCondition a) + +theorem checkZeroImplies_sound {a b : VLevel} (h : checkZeroImplies a b = true) + (levels : List Nat) (ha : a.eval levels = 0) : b.eval levels = 0 := by + have he : (zeroCondition a).inter (zeroCondition b) = zeroCondition a := of_decide_eq_true h + have hv := congrArg (PropWhen.holds (levels.getD · 0)) he + simpa only [PropWhen.holds_inter, zeroCondition_correct, ha, beq_self_eq_true, + Bool.true_and, beq_iff_eq] using hv + +def TelescopeProp (entries : Environment β) (Γ : Context β) (domains : List (AExpr β)) + (atLevel : VLevel) : Prop := + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), Realizes constants entries → + ∀ levels env, Γ.Valid constants levels env → atLevel.eval levels = 0 → + PropS (Telescope.interpret constants levels env domains) + +omit [DecidableEq β] in +theorem TelescopeProp.nil (entries : Environment β) (Γ : Context β) (atLevel : VLevel) : + TelescopeProp.{u,v} entries Γ [] atLevel := fun _ _ _ _ _ _ _ _ => trivial + +omit [DecidableEq β] in +theorem TelescopeProp.cons {entries : Environment β} {Γ : Context β} + {A : AExpr β} {rest : List (AExpr β)} {atLevel l : VLevel} + (hA : TypingClaim.{u,v} entries Γ A (.sort l)) + (hl : ∀ levels, atLevel.eval levels = 0 → l.eval levels = 0) + (htail : TelescopeProp.{u,v} entries (Γ.push A) rest atLevel) : + TelescopeProp.{u,v} entries Γ (A :: rest) atLevel := by + intro V _ constants hM levels env hΓ hz + have htype := hA V constants hM levels env hΓ + refine ⟨?_, fun x hx => htail V constants hM levels _ (hΓ.push htype.1 hx) hz⟩ + simpa only [interp, hl levels hz, univ_zero] using htype.2.2 + +/-- The singleton exception checks proof-valued ordinary fields. Merely +having one constructor is insufficient for large elimination from Prop. -/ +def verifyPropTelescope (fuel n : Nat) (entries : Environment β) (atLevel : VLevel) : + (Γ : Context β) → (domains : List (AExpr β)) → List (DomainWitness β) → + Option (CheckedClaim.{u} (TelescopeProp.{u,v} entries Γ domains atLevel)) + | Γ, [], [] => some ⟨TelescopeProp.nil entries Γ atLevel⟩ + | Γ, A :: rest, witness :: witnesses => + if hl : checkZeroImplies atLevel witness.level = true then do + let hA ← verifyType.{u,v} fuel n entries Γ A (.sort witness.level) witness.typing + let htail ← verifyPropTelescope fuel n entries atLevel (Γ.push A) rest witnesses + return ⟨TelescopeProp.cons hA.down (checkZeroImplies_sound hl) htail.down⟩ + else none + | _, _, _ => none + +end Ix.Theory.Certified diff --git a/Ix/Theory/Const.lean b/Ix/Theory/Const.lean new file mode 100644 index 000000000..59800d894 --- /dev/null +++ b/Ix/Theory/Const.lean @@ -0,0 +1,165 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Expr + +namespace Ix.Theory + +/-- Whether a declaration participates in the safe kernel fragment. -/ +inductive Safety where + | safe + | «unsafe» + | «partial» + deriving DecidableEq, Repr + +/-- The reduction behavior of a definition-like constant. -/ +inductive DefKind where + | definition + | theorem + | opaque + deriving DecidableEq, Repr + +/-- The four primitive constants that make up Lean's quotient interface. -/ +inductive QuotKind where + | type + | ctor + | lift + | ind + deriving DecidableEq, Repr + +/-- Trusted constructor metadata nested under its inductive family. -/ +structure Ctor (β : Type u) where + uvars : Nat + nparams : Nat + nfields : Nat + type : VExpr β + safety : Safety + deriving DecidableEq + +/-- One recursor reduction rule, positional in its constructor list. -/ +structure RecRule (β : Type u) where + nfields : Nat + rhs : VExpr β + deriving DecidableEq + +/-- Anonymous constant data stored in a content-addressed block. -/ +inductive Const (β : Type u) where + | axiom (uvars : Nat) (type : VExpr β) (safety : Safety) + | defn (uvars : Nat) (kind : DefKind) (type value : VExpr β) + (safety : Safety) + | quot (kind : QuotKind) (uvars : Nat) (type : VExpr β) + | induct (uvars nparams nindices : Nat) (type : VExpr β) + (ctors : List (Ctor β)) (safety : Safety) + | recursor (uvars nparams nindices nmotives nminors : Nat) (type : VExpr β) + (rules : List (RecRule β)) (k : Bool) (safety : Safety) + deriving DecidableEq + +/-- A content-addressed unit. Members are ordered and addressed positionally. -/ +structure Block (β : Type u) where + members : List (Const β) + deriving DecidableEq + +/-- A compact tag shared by ordinary members and nested constructors. -/ +inductive ConstKind where + | axiom + | defn (kind : DefKind) + | quot (kind : QuotKind) + | induct + | ctor + | recursor + deriving DecidableEq, Repr + +namespace Ctor + +def refs (ctor : Ctor β) : List (ConstRef β) := ctor.type.refs + +/-- Syntactic closure of a constructor declaration. -/ +def Closed (ctor : Ctor β) : Prop := ctor.type.Closed + +/-- The constructor's declared field telescope, excluding shared parameters. -/ +def fieldTypes (ctor : Ctor β) : List (VExpr β) := + (ctor.type.telN (ctor.nparams + ctor.nfields)).drop ctor.nparams + +/-- Whether a field type refers to any member of the indicated block. -/ +def recursiveInBlock [DecidableEq β] (ctor : Ctor β) (block : β) : Bool := + ctor.fieldTypes.any fun field => + field.refs.any fun ref => ref.block == block + +end Ctor + +namespace RecRule + +def refs (rule : RecRule β) : List (ConstRef β) := rule.rhs.refs + +/-- Syntactic closure of a stored recursor rule. -/ +def Closed (rule : RecRule β) : Prop := rule.rhs.Closed + +end RecRule + +namespace Const + +/-- Every trusted expression carried by a constant is term-variable closed. -/ +def Closed : Const β → Prop + | .axiom _ type _ => type.Closed + | .defn _ _ type value _ => type.Closed ∧ value.Closed + | .quot _ _ type => type.Closed + | .induct _ _ _ type ctors _ => + type.Closed ∧ ∀ ctor ∈ ctors, ctor.Closed + | .recursor _ _ _ _ _ type rules _ _ => + type.Closed ∧ ∀ rule ∈ rules, rule.Closed + +/-- Number of constructors contributed to a block's flattened rule order. -/ +def ctorCount : Const β → Nat + | .induct _ _ _ _ ctors _ => ctors.length + | _ => 0 + +def kind : Const β → ConstKind + | .axiom .. => .axiom + | .defn _ kind .. => .defn kind + | .quot kind .. => .quot kind + | .induct .. => .induct + | .recursor .. => .recursor + +def uvars : Const β → Nat + | .axiom uvars .. | .defn uvars .. | .induct uvars .. | + .recursor uvars .. => uvars + | .quot _ uvars _ => uvars + +def type : Const β → VExpr β + | .axiom _ type _ | .defn _ _ type _ _ | .quot _ _ type | + .induct _ _ _ type _ _ | .recursor _ _ _ _ _ type _ _ _ => type + +theorem Closed.type_closed {constant : Const β} + (closed : constant.Closed) : constant.type.Closed := by + cases constant <;> simp_all [Closed, type] + +/-- Every external reference occurring in a member's trusted expressions. -/ +def refs : Const β → List (ConstRef β) + | .axiom _ type _ => type.refs + | .defn _ _ type value _ => type.refs ++ value.refs + | .quot _ _ type => type.refs + | .induct _ _ _ type ctors _ => type.refs ++ ctors.flatMap Ctor.refs + | .recursor _ _ _ _ _ type rules _ _ => type.refs ++ rules.flatMap RecRule.refs + +end Const + +namespace Block + +/-- Every constant stored in a block is syntactically closed. -/ +def Closed (block : Block β) : Prop := + ∀ constant ∈ block.members, constant.Closed + +theorem Closed.member {block : Block β} (closed : block.Closed) + {index : Nat} {constant : Const β} + (found : block.members[index]? = some constant) : constant.Closed := + closed constant (List.mem_iff_getElem?.2 ⟨index, found⟩) + +/-- References from all member types, values, constructor types, and recursor rules. -/ +def refs (block : Block β) : List (ConstRef β) := + block.members.flatMap Const.refs + +end Block + +end Ix.Theory diff --git a/Ix/Theory/Expr.lean b/Ix/Theory/Expr.lean new file mode 100644 index 000000000..cfa7f5ba6 --- /dev/null +++ b/Ix/Theory/Expr.lean @@ -0,0 +1,284 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Ref +import Ix.Theory.VLevel + +/-! +# Anonymous kernel expressions + +`VExpr β` is the binder-name-free term syntax used by the Theory. Constants +refer to members of content-addressed blocks through `ConstRef β`; projections +and natural-number literals remain structural instead of being expanded by a +front-end translation. +-/ + +namespace Ix.Theory + +inductive VExpr (β : Type u) where + | bvar (deBruijnIndex : Nat) + | sort (u : VLevel) + | const (ref : ConstRef β) (levels : List VLevel) + | app (fn arg : VExpr β) + | lam (binderType body : VExpr β) + | forallE (binderType body : VExpr β) + | proj (ref : ConstRef β) (index : Nat) (expr : VExpr β) + | natLit (value : Nat) +deriving DecidableEq, Hashable + +instance : Inhabited (VExpr β) := ⟨.sort .zero⟩ + +/-- Shift a de Bruijn index by `n` when it is at or above cutoff `k`. -/ +def liftVar (n i : Nat) (k := 0) : Nat := if i < k then i else n + i + +namespace VExpr + +/-- Iterated application, with arguments ordered from left to right. -/ +def appN (f : VExpr β) : List (VExpr β) → VExpr β + | [] => f + | a :: as => (f.app a).appN as + +variable (n : Nat) in +/-- Insert `n` variables at cutoff `k`. -/ +def liftN : VExpr β → (k : _ := 0) → VExpr β + | .bvar i, k => .bvar (liftVar n i k) + | .sort u, _ => .sort u + | .const r us, _ => .const r us + | .app fn arg, k => .app (fn.liftN k) (arg.liftN k) + | .lam ty body, k => .lam (ty.liftN k) (body.liftN (k + 1)) + | .forallE ty body, k => .forallE (ty.liftN k) (body.liftN (k + 1)) + | .proj r i e, k => .proj r i (e.liftN k) + | .natLit value, _ => .natLit value + +abbrev lift (e : VExpr β) : VExpr β := liftN 1 e + +/-- Every free de Bruijn index in the expression is below `k`. -/ +def ClosedN : VExpr β → (k : _ := 0) → Prop + | .bvar i, k => i < k + | .sort .., _ | .const .., _ | .natLit .., _ => True + | .app fn arg, k => fn.ClosedN k ∧ arg.ClosedN k + | .lam ty body, k => ty.ClosedN k ∧ body.ClosedN (k + 1) + | .forallE ty body, k => ty.ClosedN k ∧ body.ClosedN (k + 1) + | .proj _ _ e, k => e.ClosedN k + +abbrev Closed (e : VExpr β) : Prop := ClosedN e + +variable (levels : List VLevel) in +/-- Instantiate the universe parameters in an expression. -/ +def instL : VExpr β → VExpr β + | .bvar i => .bvar i + | .sort u => .sort (u.inst levels) + | .const r us => .const r (us.map (VLevel.inst levels)) + | .app fn arg => .app fn.instL arg.instL + | .lam ty body => .lam ty.instL body.instL + | .forallE ty body => .forallE ty.instL body.instL + | .proj r i e => .proj r i e.instL + | .natLit value => .natLit value + +/-- Replace interpreted constant occurrences by closed values, instantiated +at the occurrence's universe arguments. Projection annotations remain store +references; only expression-position constants are interpreted. -/ +def substConst (interp : ConstRef β → Option (VExpr β)) : + VExpr β → VExpr β + | .bvar index => .bvar index + | .sort level => .sort level + | .const ref levels => + match interp ref with + | some value => value.instL levels + | none => .const ref levels + | .app function argument => + .app (function.substConst interp) (argument.substConst interp) + | .lam domain body => + .lam (domain.substConst interp) (body.substConst interp) + | .forallE domain body => + .forallE (domain.substConst interp) (body.substConst interp) + | .proj ref field expression => + .proj ref field (expression.substConst interp) + | .natLit value => .natLit value + +/-- All universe parameters in an expression are below `U`. -/ +def LevelWF (U : Nat) : VExpr β → Prop + | .bvar _ | .natLit _ => True + | .sort l => l.WF U + | .const _ levels => ∀ l ∈ levels, l.WF U + | .app e₁ e₂ | .lam e₁ e₂ | .forallE e₁ e₂ => e₁.LevelWF U ∧ e₂.LevelWF U + | .proj _ _ e => e.LevelWF U + +/-- Instantiate de Bruijn index `k` in a single variable occurrence. -/ +def instVar (i : Nat) (e : VExpr β) (k := 0) : VExpr β := + if i < k then .bvar i else if i = k then liftN k e else .bvar (i - 1) + +/-- Instantiate de Bruijn index `k` throughout an expression. -/ +def inst : VExpr β → VExpr β → (k : _ := 0) → VExpr β + | .bvar i, e, k => instVar i e k + | .sort u, _, _ => .sort u + | .const r us, _, _ => .const r us + | .app fn arg, e, k => .app (fn.inst e k) (arg.inst e k) + | .lam ty body, e, k => .lam (ty.inst e k) (body.inst e (k + 1)) + | .forallE ty body, e, k => .forallE (ty.inst e k) (body.inst e (k + 1)) + | .proj r i p, e, k => .proj r i (p.inst e k) + | .natLit value, _, _ => .natLit value + +/-- Remove `n` variables at cutoff `k`, using `default` for missing terms. -/ +def unliftN (e : VExpr β) (n k : Nat) : VExpr β := + match n with + | 0 => e + | n + 1 => unliftN (e.inst default k) n k + +/-- Structural form of `Skips`. -/ +def Skips' (n : Nat) : VExpr β → (k : _ := 0) → Prop + | .bvar i, k => i < k + n → i < k + | .sort .., _ | .const .., _ | .natLit .., _ => True + | .app fn arg, k => fn.Skips' n k ∧ arg.Skips' n k + | .lam ty body, k => ty.Skips' n k ∧ body.Skips' n (k + 1) + | .forallE ty body, k => ty.Skips' n k ∧ body.Skips' n (k + 1) + | .proj _ _ e, k => e.Skips' n k + +/-- `[bvar (off+m-1), ..., bvar off]`. -/ +def bvarRevRange (off : Nat) : Nat → List (VExpr β) + | 0 => [] + | m + 1 => .bvar (off + m) :: bvarRevRange off m + +/-- Iterated lambda; the binder list is outermost first. -/ +def lamN : List (VExpr β) → VExpr β → VExpr β + | [], e => e + | A :: As, e => .lam A (lamN As e) + +/-- Iterated pi; the binder list is outermost first. -/ +def forallN : List (VExpr β) → VExpr β → VExpr β + | [], e => e + | A :: As, e => .forallE A (forallN As e) + +/-- Insert `n` binders below a telescope at depth `k`. -/ +def liftTelN (n : Nat) : List (VExpr β) → Nat → List (VExpr β) + | [], _ => [] + | A :: As, k => A.liftN n k :: liftTelN n As (k + 1) + +/-- The first `n` binder types of an iterated pi, outermost first. -/ +def telN : Nat → VExpr β → List (VExpr β) + | 0, _ => [] + | n + 1, .forallE A rest => A :: telN n rest + | _ + 1, _ => [] + +/-- Strip up to `n` binders from an iterated pi. -/ +def dropN : Nat → VExpr β → VExpr β + | 0, e => e + | n + 1, .forallE _ rest => dropN n rest + | _ + 1, e => e + +/-- The result after all leading pi binders. -/ +def resultOf : VExpr β → VExpr β + | .forallE _ rest => resultOf rest + | e => e + +/-- Collect application arguments, outermost first. -/ +def appArgs : VExpr β → List (VExpr β) → List (VExpr β) + | .app f a, acc => appArgs f (a :: acc) + | _, acc => acc + +/-- Remove every application node and return its head. -/ +def appHead : VExpr β → VExpr β + | .app f _ => appHead f + | e => e + +/-- Instantiate a term under each entry of a telescope. -/ +def instTelN (a : VExpr β) : List (VExpr β) → Nat → List (VExpr β) + | [], _ => [] + | A :: As, k => A.inst a k :: instTelN a As (k + 1) + +/-- Consume an outermost-first argument list from a body. -/ +def instRev : VExpr β → List (VExpr β) → VExpr β + | C, [] => C + | C, e :: es => instRev (C.inst e es.length) es + +/-- Consume an outermost-first argument list above a fixed binder offset. -/ +def instRevAt : VExpr β → List (VExpr β) → Nat → VExpr β + | e, [], _ => e + | e, a :: as, k => instRevAt (e.inst a (k + as.length)) as k + +/-- Whether an expression mentions a particular constant reference. -/ +def mentions [DecidableEq β] : VExpr β → ConstRef β → Bool + | .bvar _, _ | .sort _, _ | .natLit _, _ => false + | .const r _, target => decide (r = target) + | .app e₁ e₂, target | .lam e₁ e₂, target | .forallE e₁ e₂, target => + e₁.mentions target || e₂.mentions target + | .proj r _ e, target => decide (r = target) || e.mentions target + +/-- All constant references occurring in an expression, including projection heads. -/ +def refs : VExpr β → List (ConstRef β) + | .bvar _ | .sort _ | .natLit _ => [] + | .const r _ => [r] + | .app e₁ e₂ | .lam e₁ e₂ | .forallE e₁ e₂ => e₁.refs ++ e₂.refs + | .proj r _ e => r :: e.refs + +end VExpr + +/-- A context embedding represented by skips and retained binders. -/ +inductive Lift : Type where + | refl + | skip (tail : Lift) + | cons (tail : Lift) + +namespace Lift + +@[simp] def skipN (l : Lift) : Nat → Lift + | 0 => l + | n + 1 => .skip (skipN l n) + +@[simp] def consN (l : Lift) : Nat → Lift + | 0 => l + | n + 1 => .cons (consN l n) + +@[simp] def comp (l₁ l₂ : Lift) : Lift := + match l₂, l₁ with + | .refl, l₁ => l₁ + | .skip l₂, l₁ => .skip (l₁.comp l₂) + | .cons l₂, .refl => .cons l₂ + | .cons l₂, .skip l₁ => .skip (l₁.comp l₂) + | .cons l₂, .cons l₁ => .cons (l₁.comp l₂) + +@[simp] def dom : Lift → Nat + | .refl => 0 + | .skip l => l.dom + | .cons l => l.dom + 1 + +@[simp] def size : Lift → Nat + | .refl => 0 + | .skip l | .cons l => l.size + 1 + +@[simp] def depth : Lift → Nat + | .refl => 0 + | .skip l => l.depth + 1 + | .cons l => l.depth + +@[simp] protected def liftVar : Lift → Nat → Nat + | .refl, n => n + | .skip l, n => l.liftVar n + 1 + | .cons _, 0 => 0 + | .cons l, n + 1 => l.liftVar n + 1 + +@[simp] def diff : Lift → Lift → Lift + | .refl, _ => .refl + | l, .refl => l + | .skip l₁, .skip l₂ | .cons l₁, .skip l₂ => diff l₁ l₂ + | .skip l₁, .cons l₂ => .skip (diff l₁ l₂) + | .cons l₁, .cons l₂ => .cons (l₁.diff l₂) + +end Lift + +namespace VExpr + +@[simp] def lift' : VExpr β → Lift → VExpr β + | .bvar i, ρ => .bvar (ρ.liftVar i) + | .sort u, _ => .sort u + | .const r us, _ => .const r us + | .app fn arg, ρ => .app (fn.lift' ρ) (arg.lift' ρ) + | .lam ty body, ρ => .lam (ty.lift' ρ) (body.lift' ρ.cons) + | .forallE ty body, ρ => .forallE (ty.lift' ρ) (body.lift' ρ.cons) + | .proj r i e, ρ => .proj r i (e.lift' ρ) + | .natLit value, _ => .natLit value + +end VExpr +end Ix.Theory diff --git a/Ix/Theory/Inductive/Levels.lean b/Ix/Theory/Inductive/Levels.lean new file mode 100644 index 000000000..5b54f8a4a --- /dev/null +++ b/Ix/Theory/Inductive/Levels.lean @@ -0,0 +1,124 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.VLevel + +/-! +The universe layout shared by recursor generation and its computation rules. +Large elimination reserves the first recursor universe for the motive; +constructors and source families receive only the remaining universes. +-/ + +namespace Ix.Theory + +namespace VLevel + +/-- `count` consecutive universe parameters beginning at `offset`. -/ +def params' (count offset : Nat) : List VLevel := + (List.range count).map fun index => .param (index + offset) + +@[simp] theorem params'_length : (params' count offset).length = count := by + simp [params'] + +end VLevel + +namespace Inductive + +/-- Whether a recursor may eliminate into a fresh universe or only into Prop. -/ +inductive ElimMode where + | large + | small + deriving DecidableEq, Repr + +namespace ElimMode + +def ofBool : Bool → ElimMode + | false => .small + | true => .large + +/-- Universe-slot offset occupied by the large-elimination motive. -/ +def offset : ElimMode → Nat + | .large => 1 + | .small => 0 + +def recUvars (mode : ElimMode) (sourceUvars : Nat) : Nat := + sourceUvars + mode.offset + +def motiveLevel : ElimMode → VLevel + | .large => .param 0 + | .small => .zero + +def sourceLevels (mode : ElimMode) (sourceUvars : Nat) : List VLevel := + VLevel.params' sourceUvars mode.offset + +def recLevels (mode : ElimMode) (sourceUvars : Nat) : List VLevel := + VLevel.params (mode.recUvars sourceUvars) + +/-- Actual arguments of the source family/constructor at a recursor instance. +The recursor and its rule RHS retain the complete argument list. -/ +def sourceArgs (mode : ElimMode) (levels : List α) : List α := + levels.drop mode.offset + +@[simp] theorem large_offset : ElimMode.large.offset = 1 := rfl +@[simp] theorem small_offset : ElimMode.small.offset = 0 := rfl + +@[simp] theorem large_recUvars (sourceUvars : Nat) : + ElimMode.large.recUvars sourceUvars = sourceUvars + 1 := rfl + +@[simp] theorem small_recUvars (sourceUvars : Nat) : + ElimMode.small.recUvars sourceUvars = sourceUvars := by + simp [recUvars, offset] + +@[simp] theorem small_sourceArgs (levels : List α) : + ElimMode.small.sourceArgs levels = levels := rfl + +@[simp] theorem large_sourceArgs_cons (motive : α) (levels : List α) : + ElimMode.large.sourceArgs (motive :: levels) = levels := rfl + +@[simp] theorem map_sourceArgs (mode : ElimMode) (f : α → β) (levels : List α) : + (mode.sourceArgs levels).map f = mode.sourceArgs (levels.map f) := by + simp [sourceArgs] + +theorem sourceArgs_length (mode : ElimMode) {levels : List α} {sourceUvars : Nat} + (h : levels.length = mode.recUvars sourceUvars) : + (mode.sourceArgs levels).length = sourceUvars := by + simp [sourceArgs, h, recUvars] + +theorem sourceArgs_wf (mode : ElimMode) {levels : List VLevel} + (h : ∀ level ∈ levels, level.WF U) : + ∀ level ∈ mode.sourceArgs levels, level.WF U := by + intro level hl + exact h level (List.mem_of_mem_drop hl) + +theorem sourceLevels_wf (mode : ElimMode) (sourceUvars : Nat) : + ∀ level ∈ mode.sourceLevels sourceUvars, level.WF (mode.recUvars sourceUvars) := by + simp [sourceLevels, VLevel.params', VLevel.WF, recUvars] + +/-- Generation's symbolic source map selects exactly the source arguments +of a concrete recursor instance. This also covers equal-arity small elimination. -/ +theorem sourceLevels_inst (mode : ElimMode) {levels : List VLevel} {sourceUvars : Nat} + (h : levels.length = mode.recUvars sourceUvars) : + (mode.sourceLevels sourceUvars).map (VLevel.inst levels) = mode.sourceArgs levels := by + apply List.ext_get (by simp [sourceLevels, sourceArgs_length mode h]) + intro i hi _ + have hi' : i < sourceUvars := by simpa [sourceLevels] using hi + have bound : i + mode.offset < levels.length := by + rw [h, recUvars] + omega + simp [sourceLevels, VLevel.params', VLevel.inst, sourceArgs, + List.getD_eq_getElem?_getD, List.getElem?_eq_getElem bound, Nat.add_comm] + +theorem sourceArgs_recLevels (mode : ElimMode) (sourceUvars : Nat) : + mode.sourceArgs (mode.recLevels sourceUvars) = mode.sourceLevels sourceUvars := by + have h := sourceLevels_inst mode (sourceUvars := sourceUvars) + (levels := mode.recLevels sourceUvars) + (by simp [recLevels]) + rw [← h] + exact (List.map_congr_left (g := id) fun level hl => + VLevel.inst_id (mode.sourceLevels_wf sourceUvars level hl)).trans (List.map_id _) + +end ElimMode +end Inductive +end Ix.Theory diff --git a/Ix/Theory/LICENSE b/Ix/Theory/LICENSE new file mode 100644 index 000000000..c13342b95 --- /dev/null +++ b/Ix/Theory/LICENSE @@ -0,0 +1,234 @@ +Lean4Ix licensing +================= + +Copyright (c) 2026 Argument Computer Corporation + +This file is derived from lean4lean and has been modified by Argument Computer Corporation. +The Apache License, Version 2.0 text reproduced below is unchanged. + +Except for third-party or upstream material that is separately identified, +Lean4Ix is licensed, at your option, under either: + + * the MIT License, as published in LICENSE-MIT; or + * the Apache License, Version 2.0, published in LICENSE-APACHE and + reproduced below. + +SPDX-License-Identifier: MIT OR Apache-2.0 + +This grant covers material copyrighted by Argument Computer Corporation and +any upstream material that its applicable license permits Argument Computer +Corporation to sublicense under these terms. Work derived from lean4lean or +other upstream projects may retain its original licensing, copyright, +attribution, notice, and modification requirements. + +To the maximum extent permitted by those upstream licenses, our intent is to +incorporate, distribute, and, where permitted, sublicense that work as part of +the unified Lean4Ix package under the MIT OR Apache-2.0 licensing choice. We +preserve all notices required by the applicable upstream licenses and comply +with every condition necessary to incorporate and redistribute that work. +Where an upstream license does not permit this unified dual licensing, its +terms continue to control the +affected material. Nothing in this notice grants rights beyond those provided +by the applicable upstream licenses. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Ix/Theory/LICENSE-APACHE b/Ix/Theory/LICENSE-APACHE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/Ix/Theory/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Ix/Theory/LICENSE-MIT b/Ix/Theory/LICENSE-MIT new file mode 100644 index 000000000..7590c7281 --- /dev/null +++ b/Ix/Theory/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Argument Computer Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Ix/Theory/Model/Annotated.lean b/Ix/Theory/Model/Annotated.lean new file mode 100644 index 000000000..cf7bc21af --- /dev/null +++ b/Ix/Theory/Model/Annotated.lean @@ -0,0 +1,221 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Level +import Ix.Theory.Rename + +/-! +# Annotated readings of exact anonymous expressions + +Every binder occurrence carries its own zero condition. These are structural +readings, not evidence of typing: the semantic checker must establish that +each condition describes the inferred codomain sort in the current context. + +The operations below preserve erasure exactly, including block/member and +constructor positions, level arguments, projection heads, and literals. +-/ + +namespace Ix.Theory.Model + +open Certified + +inductive AExpr (β : Type u) where + | bvar (index : Nat) + | sort (level : VLevel) + | const (ref : ConstRef β) (levels : List VLevel) + | app (fn arg : AExpr β) + | lam (condition : PropWhen) (domain body : AExpr β) + | forallE (condition : PropWhen) (domain body : AExpr β) + | proj (ref : ConstRef β) (field : Nat) (major : AExpr β) + | natLit (value : Nat) +deriving DecidableEq + +namespace AExpr + +def erase : AExpr β → VExpr β + | .bvar i => .bvar i + | .sort l => .sort l + | .const r ls => .const r ls + | .app f a => .app f.erase a.erase + | .lam _ a b => .lam a.erase b.erase + | .forallE _ a b => .forallE a.erase b.erase + | .proj r i e => .proj r i e.erase + | .natLit v => .natLit v + +theorem eq_const_of_erase_eq {e : AExpr β} {r : ConstRef β} {ls : List VLevel} + (h : e.erase = .const r ls) : e = .const r ls := by + cases e <;> simp_all [erase] + +/-- Scope of syntax and annotations, independently of semantic validity. -/ +def Scope (universes depth : Nat) : AExpr β → Prop + | .bvar i => i < depth + | .sort l => l.WF universes + | .const _ ls => ∀ l ∈ ls, l.WF universes + | .app f a => f.Scope universes depth ∧ a.Scope universes depth + | .lam p a b | .forallE p a b => + p.WF universes ∧ a.Scope universes depth ∧ b.Scope universes (depth + 1) + | .proj _ _ e => e.Scope universes depth + | .natLit _ => True + +instance decidableScope {n k : Nat} : ∀ {e : AExpr β}, Decidable (e.Scope n k) + | .bvar i => inferInstanceAs (Decidable (i < k)) + | .sort l => VLevel.decidable_WF (l := l) + | .const _ ls => inferInstanceAs (Decidable (∀ l ∈ ls, VLevel.WF n l)) + | .app f a => @instDecidableAnd _ _ (decidableScope (e := f)) (decidableScope (e := a)) + | .lam p A b | .forallE p A b => + @instDecidableAnd _ _ (inferInstanceAs (Decidable (p.WF n))) + (@instDecidableAnd _ _ (decidableScope (e := A)) (decidableScope (e := b))) + | .proj _ _ e => decidableScope (e := e) + | .natLit _ => instDecidableTrue + +theorem Scope.erase {u k : Nat} {e : AExpr β} (h : e.Scope u k) : + e.erase.LevelWF u ∧ e.erase.ClosedN k := by + induction e generalizing k with + | bvar i => exact ⟨trivial, h⟩ + | sort l => exact ⟨h, trivial⟩ + | const r ls => exact ⟨h, trivial⟩ + | app f a hf ha => + exact ⟨⟨(hf h.1).1, (ha h.2).1⟩, ⟨(hf h.1).2, (ha h.2).2⟩⟩ + | lam p a b ha hb | forallE p a b ha hb => + exact ⟨⟨(ha h.2.1).1, (hb h.2.2).1⟩, ⟨(ha h.2.1).2, (hb h.2.2).2⟩⟩ + | proj r i e ih => exact ih h + | natLit v => exact ⟨trivial, trivial⟩ + +def liftN (count : Nat) : AExpr β → (cutoff : Nat := 0) → AExpr β + | .bvar i, k => .bvar (liftVar count i k) + | .sort l, _ => .sort l + | .const r ls, _ => .const r ls + | .app f a, k => .app (f.liftN count k) (a.liftN count k) + | .lam p a b, k => .lam p (a.liftN count k) (b.liftN count (k + 1)) + | .forallE p a b, k => .forallE p (a.liftN count k) (b.liftN count (k + 1)) + | .proj r i e, k => .proj r i (e.liftN count k) + | .natLit v, _ => .natLit v + +@[simp] theorem erase_liftN (e : AExpr β) (n k : Nat) : + (e.liftN n k).erase = e.erase.liftN n k := by + induction e generalizing k <;> simp_all [liftN, erase, VExpr.liftN] + +def instVar (i : Nat) (a : AExpr β) (k : Nat) : AExpr β := + if i < k then .bvar i else if i = k then a.liftN k else .bvar (i - 1) + +def inst : AExpr β → AExpr β → (cutoff : Nat := 0) → AExpr β + | .bvar i, a, k => instVar i a k + | .sort l, _, _ => .sort l + | .const r ls, _, _ => .const r ls + | .app f a, e, k => .app (f.inst e k) (a.inst e k) + | .lam p a b, e, k => .lam p (a.inst e k) (b.inst e (k + 1)) + | .forallE p a b, e, k => .forallE p (a.inst e k) (b.inst e (k + 1)) + | .proj r i e, a, k => .proj r i (e.inst a k) + | .natLit v, _, _ => .natLit v + +@[simp] theorem erase_inst (e a : AExpr β) (k : Nat) : + (e.inst a k).erase = e.erase.inst a.erase k := by + induction e generalizing k with + | bvar i => + by_cases hi : i < k + · simp [inst, erase, VExpr.inst, instVar, VExpr.instVar, hi] + · by_cases he : i = k <;> + simp [inst, erase, VExpr.inst, instVar, VExpr.instVar, hi, he] + | _ => simp_all [inst, erase, VExpr.inst] + +def instL (levels : List VLevel) : AExpr β → AExpr β + | .bvar i => .bvar i + | .sort l => .sort (l.inst levels) + | .const r ls => .const r (ls.map (VLevel.inst levels)) + | .app f a => .app (f.instL levels) (a.instL levels) + | .lam p a b => .lam (instCondition levels p) (a.instL levels) (b.instL levels) + | .forallE p a b => .forallE (instCondition levels p) (a.instL levels) (b.instL levels) + | .proj r i e => .proj r i (e.instL levels) + | .natLit v => .natLit v + +@[simp] theorem erase_instL (e : AExpr β) (ls : List VLevel) : + (e.instL ls).erase = e.erase.instL ls := by + induction e <;> simp_all [instL, erase, VExpr.instL] + +theorem instL_instL (e : AExpr β) (ls ls' : List VLevel) : + (e.instL ls).instL ls' = e.instL (ls.map (VLevel.inst ls')) := by + induction e <;> + simp_all [instL, VLevel.inst_inst, instCondition_comp, List.map_map, Function.comp_def] + +def rename (mapping : β → γ) : AExpr β → AExpr γ + | .bvar i => .bvar i + | .sort l => .sort l + | .const r ls => .const (r.rename mapping) ls + | .app f a => .app (f.rename mapping) (a.rename mapping) + | .lam p a b => .lam p (a.rename mapping) (b.rename mapping) + | .forallE p a b => .forallE p (a.rename mapping) (b.rename mapping) + | .proj r i e => .proj (r.rename mapping) i (e.rename mapping) + | .natLit v => .natLit v + +@[simp] theorem erase_rename (e : AExpr β) (mapping : β → γ) : + (e.rename mapping).erase = e.erase.rename mapping := by + induction e <;> simp_all [rename, erase, VExpr.rename] + +end AExpr + +/-- Untrusted annotations are indexed by occurrence, not a shared node ID. +Leaf syntax comes from the source expression and cannot be changed here. -/ +inductive AnnotationTree where + | leaf + | app (fn arg : AnnotationTree) + | lam (condition : Option (List Nat)) (domain body : AnnotationTree) + | forallE (condition : Option (List Nat)) (domain body : AnnotationTree) + | proj (major : AnnotationTree) +deriving DecidableEq, Repr + +private def readCondition? (n : Nat) (raw : Option (List Nat)) : + Option { p : PropWhen // p.toRaw = raw ∧ p.WF n } := + match h : PropWhen.fromRaw? n raw with + | none => none + | some p => some ⟨p, PropWhen.fromRaw?_sound h⟩ + +universe u +variable {β : Type u} + +/-- Exact, scoped reading produced by the structural validator. -/ +abbrev Reading (n k : Nat) (source : VExpr β) := + { e : AExpr β // e.erase = source ∧ e.Scope n k } + +/-- Check shape, canonical conditions, and every term/universe index against +the exact input occurrence. Typing must subsequently validate binder meaning. +Proof fields are erased at runtime; every data check below is executable. -/ +def readAnnotations? (n k : Nat) (source : VExpr β) (tree : AnnotationTree) : + Option (Reading n k source) := + match source, tree with + | .bvar i, .leaf => if h : i < k then some ⟨.bvar i, rfl, h⟩ else none + | .sort l, .leaf => if h : l.WF n then some ⟨.sort l, rfl, h⟩ else none + | .const r ls, .leaf => + if h : ∀ l ∈ ls, l.WF n then some ⟨.const r ls, rfl, h⟩ else none + | .app f a, .app tf ta => do + let f' ← readAnnotations? n k f tf + let a' ← readAnnotations? n k a ta + return ⟨.app f'.val a'.val, + by simp [AExpr.erase, f'.property.1, a'.property.1], + f'.property.2, a'.property.2⟩ + | .lam a b, .lam raw ta tb => + match readCondition? n raw with + | none => none + | some p => do + let a' ← readAnnotations? n k a ta + let b' ← readAnnotations? n (k + 1) b tb + return ⟨.lam p.val a'.val b'.val, + by simp [AExpr.erase, a'.property.1, b'.property.1], + p.property.2, a'.property.2, b'.property.2⟩ + | .forallE a b, .forallE raw ta tb => + match readCondition? n raw with + | none => none + | some p => do + let a' ← readAnnotations? n k a ta + let b' ← readAnnotations? n (k + 1) b tb + return ⟨.forallE p.val a'.val b'.val, + by simp [AExpr.erase, a'.property.1, b'.property.1], + p.property.2, a'.property.2, b'.property.2⟩ + | .proj r i e, .proj te => do + let e' ← readAnnotations? n k e te + return ⟨.proj r i e'.val, by simp [AExpr.erase, e'.property.1], e'.property.2⟩ + | .natLit v, .leaf => some ⟨.natLit v, rfl, trivial⟩ + | _, _ => none + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Context.lean b/Ix/Theory/Model/Context.lean new file mode 100644 index 000000000..f4579d895 --- /dev/null +++ b/Ix/Theory/Model/Context.lean @@ -0,0 +1,56 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.WellDenoted + +namespace Ix.Theory.Model + +open SetTheory + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +/-- All entries are expressed in the full current context. Pushing a binder +lifts both its type and every existing entry. -/ +abbrev Context (β : Type u) := List (AExpr β) + +def Context.push (A : AExpr β) (Γ : Context β) : Context β := + A.liftN 1 :: Γ.map (AExpr.liftN 1 ·) + +def Context.Valid (constants : Assignment β V) (levels : List Nat) + (Γ : Context β) (env : Nat → V) : Prop := + ∀ i A, Γ[i]? = some A → + WellDenoted constants levels env A ∧ env i ∈ˢ interp constants levels env A + +theorem Context.valid_nil (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) : Context.Valid constants levels [] env := by + intro i A h + simp at h + +omit [SetTheory V] in +@[simp] theorem Valuation.skip_one_cons (x : V) (env : Nat → V) : + Valuation.skip 1 0 (Valuation.cons x env) = env := by + funext i + simp [Valuation.skip, Nat.add_comm 1 i] + +theorem Context.Valid.push {constants : Assignment β V} {levels : List Nat} + {Γ : Context β} {env : Nat → V} {A : AExpr β} {x : V} + (hΓ : Γ.Valid constants levels env) (hA : WellDenoted constants levels env A) + (hx : x ∈ˢ interp constants levels env A) : + (Γ.push A).Valid constants levels (Valuation.cons x env) := by + intro i B hi + cases i with + | zero => + simp only [Context.push, List.getElem?_cons_zero, Option.some.injEq] at hi + subst B + simpa only [wellDenoted_liftN, interp_liftN, Valuation.skip_one_cons, + Valuation.cons_zero] using And.intro hA hx + | succ i => + simp only [Context.push, List.getElem?_cons_succ, List.getElem?_map] at hi + obtain ⟨C, hC, rfl⟩ := Option.map_eq_some_iff.mp hi + simpa only [wellDenoted_liftN, interp_liftN, Valuation.skip_one_cons, + Valuation.cons_succ] using hΓ i C hC + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Environment.lean b/Ix/Theory/Model/Environment.lean new file mode 100644 index 000000000..7bd16fbcd --- /dev/null +++ b/Ix/Theory/Model/Environment.lean @@ -0,0 +1,76 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Context + +namespace Ix.Theory.Model + +open SetTheory + +universe u v + +/-- A closed equation includes the whole rule telescope as lambdas. Its data +does not authorize reduction; an admitted model must establish its equality. -/ +structure ConstantEquation (β : Type u) where + lhs : AExpr β + rhs : AExpr β +deriving DecidableEq + +/-- Data describing additional proved behavior of an admitted declaration. +Only semantic producers may publish these facts; the certificate supplies +no proof of their meaning. -/ +inductive ConstantFact (β : Type u) where + | typed (expression type : AExpr β) + | natural (zero succ : ConstRef β) +deriving DecidableEq + +structure NaturalMeaning {β : Type u} {V : Type v} [SetTheory V] + (constants : Assignment β V) (family zero succ : ConstRef β) : Prop where + member : ∀ n, Numeral.value n ∈ˢ constants family [] + zeroValue : constants zero [] = Numeral.value 0 + succValue : ∀ n, SetTheory.app (constants succ []) (Numeral.value n) = Numeral.value (n + 1) + +def ConstantFact.Meaning {β : Type u} {V : Type v} [SetTheory V] + (constants : Assignment β V) (owner : ConstRef β) (levels : List Nat) (env : Nat → V) : + ConstantFact β → Prop + | .typed e type => WellDenoted constants levels env e ∧ WellDenoted constants levels env type ∧ + interp constants levels env e ∈ˢ interp constants levels env type + | .natural zero succ => levels = [] ∧ NaturalMeaning constants owner zero succ + +/-- An entry becomes available to the checker only after admission of its +primitive realization, safe checked body, or atomic inductive realization. +An absent body does not license axioms or reduction equations. -/ +structure ConstantEntry (β : Type u) where + universes : Nat + type : AExpr β + body : Option (AExpr β) + equations : List (ConstantEquation β) := [] + facts : List (ConstantFact β) := [] + +abbrev Environment (β : Type u) := ConstRef β → Option (ConstantEntry β) + +/-- Meaning of an exact dependency interface. A declaration producer must +establish these facts for every universe instance and context valuation. -/ +structure Realizes {β : Type u} {V : Type v} [SetTheory V] + (constants : Assignment β V) (entries : Environment β) : Prop where + typeValid : ∀ r entry, entries r = some entry → ∀ levels, + levels.length = entry.universes → ∀ env, + WellDenoted constants levels env entry.type + member : ∀ r entry, entries r = some entry → ∀ levels, + levels.length = entry.universes → ∀ env, + constants r levels ∈ˢ interp constants levels env entry.type + bodyValid : ∀ r entry, entries r = some entry → ∀ body, entry.body = some body → + ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env body + bodyValue : ∀ r entry, entries r = some entry → ∀ body, entry.body = some body → + ∀ levels, levels.length = entry.universes → ∀ env, + constants r levels = interp constants levels env body + equationValue : ∀ r entry, entries r = some entry → ∀ equation ∈ entry.equations, + ∀ levels, levels.length = entry.universes → ∀ env, + interp constants levels env equation.lhs = interp constants levels env equation.rhs + factMeaning : ∀ r entry, entries r = some entry → ∀ fact ∈ entry.facts, + ∀ levels, levels.length = entry.universes → ∀ env, fact.Meaning constants r levels env + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Extension.lean b/Ix/Theory/Model/Extension.lean new file mode 100644 index 000000000..ca67eb91b --- /dev/null +++ b/Ix/Theory/Model/Extension.lean @@ -0,0 +1,346 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Support +import Ix.Theory.Model.Judgment + +namespace Ix.Theory.Model + +open SetTheory + +universe u v +variable {β : Type u} [DecidableEq β] + +def Environment.insert (entries : Environment β) (r : ConstRef β) + (entry : ConstantEntry β) : Environment β := + fun q => if q = r then some entry else entries q + +def Assignment.insert (constants : Assignment β V) (r : ConstRef β) + (value : List Nat → V) : Assignment β V := + fun q levels => if q = r then value levels else constants q levels + +/-- All exact old references retain their values at every universe instance. -/ +def Assignment.AgreesOn (entries : Environment β) (constants constants' : Assignment β V) : Prop := + ∀ r entry, entries r = some entry → ∀ levels, constants' r levels = constants r levels + +@[simp] theorem Environment.insert_same (entries : Environment β) (r : ConstRef β) + (entry : ConstantEntry β) : entries.insert r entry r = some entry := by + simp only [insert, ↓reduceIte] + +theorem Environment.insert_replace (entries : Environment β) (r : ConstRef β) + (old entry : ConstantEntry β) : (entries.insert r old).insert r entry = entries.insert r entry := by + funext q + by_cases h : q = r <;> simp [insert, h] + +@[simp] theorem Assignment.insert_same (constants : Assignment β V) (r : ConstRef β) + (value : List Nat → V) (levels : List Nat) : + constants.insert r value r levels = value levels := by + simp only [insert, ↓reduceIte] + +omit [DecidableEq β] in +theorem fresh_ne {entries : Environment β} {r q : ConstRef β} {entry : ConstantEntry β} + (fresh : entries r = none) (h : entries q = some entry) : q ≠ r := by + intro hqr + subst q + rw [fresh] at h + contradiction + +theorem Environment.insert_old {entries : Environment β} {r q : ConstRef β} + {entry old : ConstantEntry β} (fresh : entries r = none) (h : entries q = some old) : + entries.insert r entry q = some old := by + simp only [insert, if_neg (fresh_ne fresh h), h] + +theorem Assignment.insert_agrees {entries : Environment β} {r : ConstRef β} + (fresh : entries r = none) (constants : Assignment β V) (value : List Nat → V) : + Assignment.AgreesOn entries constants (constants.insert r value) := by + intro q entry h levels + simp only [Assignment.insert, if_neg (fresh_ne fresh h)] + +theorem AExpr.ReferencesIn.insert {entries : Environment β} {r : ConstRef β} + {entry : ConstantEntry β} {e : AExpr β} (h : e.ReferencesIn entries) : + e.ReferencesIn (entries.insert r entry) := by + intro q hq + unfold Environment.insert + split + · rfl + · exact h q hq + +theorem ConstantFact.ReferencesIn.insert {entries : Environment β} {r : ConstRef β} + {entry : ConstantEntry β} {fact : ConstantFact β} (h : fact.ReferencesIn entries) : + fact.ReferencesIn (entries.insert r entry) := by + intro q hq + unfold Environment.insert + split + · rfl + · exact h q hq + +theorem Environment.WF.insert {entries : Environment β} {r : ConstRef β} + {entry : ConstantEntry β} (hE : entries.WF) + (hTs : entry.type.Scope entry.universes 0) + (hBs : ∀ body, entry.body = some body → body.Scope entry.universes 0) + (hTr : entry.type.ReferencesIn entries) + (hBr : ∀ body, entry.body = some body → body.ReferencesIn entries) + (hQs : ∀ equation ∈ entry.equations, + equation.lhs.Scope entry.universes 0 ∧ equation.rhs.Scope entry.universes 0) + (hQr : ∀ equation ∈ entry.equations, + equation.lhs.ReferencesIn entries ∧ equation.rhs.ReferencesIn entries) + (hFs : ∀ fact ∈ entry.facts, fact.Scope entry.universes) + (hFr : ∀ fact ∈ entry.facts, fact.ReferencesIn entries) : + (entries.insert r entry).WF := by + constructor + · intro q old h + unfold Environment.insert at h + split at h + · cases Option.some.inj h; exact hTs + · exact hE.typeScope q old h + · intro q old h body hb + unfold Environment.insert at h + split at h + · cases Option.some.inj h; exact hBs body hb + · exact hE.bodyScope q old h body hb + · intro q old h + unfold Environment.insert at h + split at h + · cases Option.some.inj h; exact hTr.insert + · exact (hE.typeReferences q old h).insert + · intro q old h body hb + unfold Environment.insert at h + split at h + · cases Option.some.inj h; exact (hBr body hb).insert + · exact (hE.bodyReferences q old h body hb).insert + · intro q old h equation he + unfold Environment.insert at h + split at h + · cases Option.some.inj h; exact hQs equation he + · exact hE.equationScope q old h equation he + · intro q old h equation he + unfold Environment.insert at h + split at h + · cases Option.some.inj h + exact ⟨(hQr equation he).1.insert, (hQr equation he).2.insert⟩ + · exact ⟨(hE.equationReferences q old h equation he).1.insert, + (hE.equationReferences q old h equation he).2.insert⟩ + · intro q old h fact hf + unfold Environment.insert at h + split at h + · cases Option.some.inj h; exact hFs fact hf + · exact hE.factScope q old h fact hf + · intro q old h fact hf + unfold Environment.insert at h + split at h + · cases Option.some.inj h; exact (hFr fact hf).insert + · exact (hE.factReferences q old h fact hf).insert + +variable {V : Type v} [SetTheory V] + +omit [DecidableEq β] in +theorem Assignment.AgreesOn.interp {entries : Environment β} + {constants constants' : Assignment β V} + (h : Assignment.AgreesOn entries constants constants') + {e : AExpr β} (he : e.ReferencesIn entries) (levels : List Nat) (env : Nat → V) : + interp constants' levels env e = interp constants levels env e := by + apply interp_congr_constants + intro r hr ls + have hl := he r hr + cases hE : entries r with + | none => simp [hE] at hl + | some entry => exact h r entry hE ls + +omit [DecidableEq β] in +theorem Assignment.AgreesOn.wellDenoted {entries : Environment β} + {constants constants' : Assignment β V} + (h : Assignment.AgreesOn entries constants constants') + {e : AExpr β} (he : e.ReferencesIn entries) (levels : List Nat) (env : Nat → V) : + WellDenoted constants' levels env e ↔ WellDenoted constants levels env e := by + apply wellDenoted_congr_constants + intro r hr ls + have hl := he r hr + cases hE : entries r with + | none => simp [hE] at hl + | some entry => exact h r entry hE ls + +omit [DecidableEq β] in +theorem Assignment.AgreesOn.factMeaning {entries : Environment β} + {constants constants' : Assignment β V} (h : Assignment.AgreesOn entries constants constants') + {r : ConstRef β} {entry : ConstantEntry β} (hr : entries r = some entry) + {fact : ConstantFact β} (hf : fact.ReferencesIn entries) (levels : List Nat) (env : Nat → V) + (hm : fact.Meaning constants r levels env) : fact.Meaning constants' r levels env := by + have heq (q) (hq : q ∈ fact.references) (ls) : constants' q ls = constants q ls := by + have hv := hf q hq + cases he : entries q with + | none => simp [he] at hv + | some value => exact h q value he ls + cases fact with + | typed e type => + have her : e.ReferencesIn entries := fun q hq => hf q (List.mem_append_left _ hq) + have htr : type.ReferencesIn entries := fun q hq => hf q (List.mem_append_right _ hq) + simpa only [ConstantFact.Meaning, h.wellDenoted her, h.wellDenoted htr, + h.interp her, h.interp htr] using hm + | natural zero succ => + refine ⟨hm.1, ?_⟩ + have hz := heq zero (by simp [ConstantFact.references]) [] + have hs := heq succ (by simp [ConstantFact.references]) [] + constructor + · intro n; rw [h r entry hr []]; exact hm.2.member n + · rw [hz]; exact hm.2.zeroValue + · intro n; rw [hs]; exact hm.2.succValue n + +omit [DecidableEq β] in +theorem Realizes.of_agrees {entries : Environment β} {constants constants' : Assignment β V} + (hM : Realizes constants entries) (hE : entries.WF) + (h : Assignment.AgreesOn entries constants constants') : Realizes constants' entries where + typeValid r entry hr levels hn env := + (h.wellDenoted (hE.typeReferences r entry hr) levels env).mpr (hM.typeValid r entry hr levels hn env) + member r entry hr levels hn env := by + rw [h r entry hr levels, h.interp (hE.typeReferences r entry hr) levels env] + exact hM.member r entry hr levels hn env + bodyValid r entry hr body hb levels hn env := + (h.wellDenoted (hE.bodyReferences r entry hr body hb) levels env).mpr + (hM.bodyValid r entry hr body hb levels hn env) + bodyValue r entry hr body hb levels hn env := by + rw [h r entry hr levels, h.interp (hE.bodyReferences r entry hr body hb) levels env] + exact hM.bodyValue r entry hr body hb levels hn env + equationValue r entry hr law hl levels hn env := by + rw [h.interp (hE.equationReferences r entry hr law hl).1 levels env, + h.interp (hE.equationReferences r entry hr law hl).2 levels env] + exact hM.equationValue r entry hr law hl levels hn env + factMeaning r entry hr fact hf levels hn env := + h.factMeaning hr (hE.factReferences r entry hr fact hf) levels env + (hM.factMeaning r entry hr fact hf levels hn env) + +/-- Local mathematical realization package. Admission constructs every field; +certificate data cannot supply this proof package. -/ +structure EntryRealization (constants : Assignment β V) (r : ConstRef β) + (entry : ConstantEntry β) : Prop where + typeValid : ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env entry.type + member : ∀ levels, levels.length = entry.universes → ∀ env, + constants r levels ∈ˢ interp constants levels env entry.type + bodyValid : ∀ body, entry.body = some body → ∀ levels, levels.length = entry.universes → ∀ env, + WellDenoted constants levels env body + bodyValue : ∀ body, entry.body = some body → ∀ levels, levels.length = entry.universes → ∀ env, + constants r levels = interp constants levels env body + equationValue : ∀ law ∈ entry.equations, ∀ levels, levels.length = entry.universes → ∀ env, + interp constants levels env law.lhs = interp constants levels env law.rhs + factMeaning : ∀ fact ∈ entry.facts, ∀ levels, levels.length = entry.universes → ∀ env, + fact.Meaning constants r levels env + +theorem Realizes.insert {entries : Environment β} {constants : Assignment β V} + {r : ConstRef β} {entry : ConstantEntry β} (hM : Realizes constants entries) + (h : EntryRealization constants r entry) : Realizes constants (entries.insert r entry) := by + constructor + · intro q old hq + unfold Environment.insert at hq + split at hq + · cases Option.some.inj hq; exact h.typeValid + · exact hM.typeValid q old hq + · intro q old hq + unfold Environment.insert at hq + split at hq + next he => subst q; cases Option.some.inj hq; exact h.member + next => exact hM.member q old hq + · intro q old hq + unfold Environment.insert at hq + split at hq + · cases Option.some.inj hq; exact h.bodyValid + · exact hM.bodyValid q old hq + · intro q old hq + unfold Environment.insert at hq + split at hq + next he => subst q; cases Option.some.inj hq; exact h.bodyValue + next => exact hM.bodyValue q old hq + · intro q old hq + unfold Environment.insert at hq + split at hq + · cases Option.some.inj hq; exact h.equationValue + · exact hM.equationValue q old hq + · intro q old hq + unfold Environment.insert at hq + split at hq + next he => subst q; cases Option.some.inj hq; exact h.factMeaning + next => exact hM.factMeaning q old hq + +/-- Safe-definition admission extends every compatible old model. The new +value is constructed from the checked body in that very model. -/ +theorem extend_definition {entries : Environment β} {r : ConstRef β} + {entry : ConstantEntry β} {body : AExpr β} {level : VLevel} + (hE : entries.WF) (fresh : entries r = none) (hb : entry.body = some body) + (hq : entry.equations = []) (hf : entry.facts = []) + (hBs : body.Scope entry.universes 0) + (hTr : entry.type.ReferencesIn entries) (hBr : body.ReferencesIn entries) + (hT : TypingClaim.{u,v} entries [] entry.type (.sort level)) + (hB : TypingClaim.{u,v} entries [] body entry.type) + (constants : Assignment β V) (hM : Realizes constants entries) : + ∃ constants' : Assignment β V, + Realizes constants' (entries.insert r entry) ∧ + Assignment.AgreesOn entries constants constants' := by + let constants' := constants.insert r (fun levels => interp constants levels (fun _ => empty) body) + have hagree : Assignment.AgreesOn entries constants constants' := by + intro q old h levels + simp only [constants', Assignment.insert, if_neg (fresh_ne fresh h)] + have hnew (levels : List Nat) (env : Nat → V) : + constants' r levels = interp constants levels env body := by + simp only [constants', Assignment.insert, ↓reduceIte] + exact interp_closed body constants levels hBs _ env + refine ⟨constants', ?_, hagree⟩ + constructor + · intro q old h levels _ env + unfold Environment.insert at h + split at h + · cases Option.some.inj h + exact (hagree.wellDenoted hTr levels env).mpr + (hT V constants hM levels env (Context.valid_nil constants levels env)).1 + · exact (hagree.wellDenoted (hE.typeReferences q old h) levels env).mpr + (hM.typeValid q old h levels ‹_› env) + · intro q old h levels _ env + unfold Environment.insert at h + split at h + next hqr => + subst q + cases Option.some.inj h + rw [hnew levels env, hagree.interp hTr levels env] + exact (hB V constants hM levels env (Context.valid_nil constants levels env)).2.2 + next => + rw [hagree q old h levels, hagree.interp (hE.typeReferences q old h) levels env] + exact hM.member q old h levels ‹_› env + · intro q old h b hb' levels _ env + unfold Environment.insert at h + split at h + · cases Option.some.inj h + have he : body = b := Option.some.inj (hb.symm.trans hb') + subst b + exact (hagree.wellDenoted hBr levels env).mpr + (hB V constants hM levels env (Context.valid_nil constants levels env)).1 + · exact (hagree.wellDenoted (hE.bodyReferences q old h b hb') levels env).mpr + (hM.bodyValid q old h b hb' levels ‹_› env) + · intro q old h b hb' levels _ env + unfold Environment.insert at h + split at h + next hqr => + subst q + cases Option.some.inj h + have he : body = b := Option.some.inj (hb.symm.trans hb') + subst b + rw [hnew levels env, hagree.interp hBr levels env] + next => + rw [hagree q old h levels, hagree.interp (hE.bodyReferences q old h b hb') levels env] + exact hM.bodyValue q old h b hb' levels ‹_› env + · intro q old h equation he levels hn env + unfold Environment.insert at h + split at h + · cases Option.some.inj h + simp only [hq, List.not_mem_nil] at he + · rw [hagree.interp (hE.equationReferences q old h equation he).1 levels env, + hagree.interp (hE.equationReferences q old h equation he).2 levels env] + exact hM.equationValue q old h equation he levels hn env + · intro q old h fact hfact levels hn env + unfold Environment.insert at h + split at h + · cases Option.some.inj h + simp only [hf, List.not_mem_nil] at hfact + · exact hagree.factMeaning h (hE.factReferences q old h fact hfact) levels env + (hM.factMeaning q old h fact hfact levels hn env) + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Inductive/Codes.lean b/Ix/Theory/Model/Inductive/Codes.lean new file mode 100644 index 000000000..0f2551dce --- /dev/null +++ b/Ix/Theory/Model/Inductive/Codes.lean @@ -0,0 +1,43 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Inductive.Telescope +import Ix.Theory.Model.SetModel.TaggedSum + +namespace Ix.Theory.Model.InductiveCodes + +open SetTheory SetTheory.Tower + +universe u +variable {V : Type u} [SetTheory V] + +open Classical in +noncomputable def natIndex (x : V) : Nat := + if h : ∃ i, x = vnat i then Classical.choose h else 0 + +theorem natIndex_vnat (i : Nat) : natIndex (vnat i : V) = i := by + unfold natIndex + rw [dif_pos ⟨i, rfl⟩] + exact (vnat_inj (Classical.choose_spec (⟨i, rfl⟩ : ∃ j, (vnat i : V) = vnat j))).symm + +noncomputable def tag (x : V) : Nat := natIndex (sfst x) + +@[simp] theorem tag_inj (i : Nat) (x : V) : tag (inj i x) = i := by + simp only [tag, sfst_inj, natIndex_vnat] + +theorem sum_graph_mem {w : Nat} (hw : w ≠ 0) {f : Nat → V} + (hf : ∀ i, f i ∈ˢ (univ w : V)) : sumSet 1 f ∈ˢ (univ w : V) := by + cases w with + | zero => exact (hw rfl).elim + | succ w => + unfold sumSet + rw [sigmaSet_pos (by decide : 1 ≠ 0)] + apply (univ_isTGUniverse hw).sigmaPairs_mem (omega_mem_univ_succ w) + intro k hk + obtain ⟨i, rfl⟩ := mem_omega_iff.mp hk + rw [natFibre_vnat] + exact hf i + +end Ix.Theory.Model.InductiveCodes diff --git a/Ix/Theory/Model/Inductive/Container.lean b/Ix/Theory/Model/Inductive/Container.lean new file mode 100644 index 000000000..0b8ad1103 --- /dev/null +++ b/Ix/Theory/Model/Inductive/Container.lean @@ -0,0 +1,192 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.SetModel.Container + +/-! +Indexed strictly positive carriers over the explicit set-theory interface. +This supplies a carrier and its induction principle from shape/position data; +the source validator must construct the bounds and target-index proofs. +No field postulates a fixed point, constructor law, or recursor law. +-/ + +namespace Ix.Theory.Model + +open SetTheory + +universe u + +structure IndexedContainer (V : Type u) where + indices : V + shapes : V → V + positions : V → V + target : V → V → V + +namespace IndexedContainer + +variable {V : Type u} [SetTheory V] + +structure WF (D : IndexedContainer V) (w : Nat) : Prop where + shapes_mem : w ≠ 0 → ∀ i, i ∈ˢ D.indices → D.shapes i ∈ˢ (univ w : V) + positions_mem : w ≠ 0 → ∀ i a, i ∈ˢ D.indices → a ∈ˢ D.shapes i → + D.positions a ∈ˢ (univ w : V) + target_mem : ∀ i a p, i ∈ˢ D.indices → a ∈ˢ D.shapes i → p ∈ˢ D.positions a → + D.target a p ∈ˢ D.indices + +noncomputable def node (w : Nat) (a g : V) : V := + if w = 0 then pt else spair a g + +noncomputable def fibre (D : IndexedContainer V) (w : Nat) (X i : V) : V := + sigmaSet w (D.shapes i) fun a => piSet (D.positions a) fun p => app X (D.target a p) + +noncomputable def step (D : IndexedContainer V) (w : Nat) : V := + graph (fun X => graph (D.fibre w X) D.indices) (famSpace w D.indices) + +noncomputable def carrier (D : IndexedContainer V) (w : Nat) : V := + lfpFamSet w D.indices (D.step w) + +theorem node_mem_fibre {D : IndexedContainer V} {w : Nat} {X i a g : V} + (ha : a ∈ˢ D.shapes i) + (hg : g ∈ˢ piSet (D.positions a) (fun p => app X (D.target a p))) : + node w a g ∈ˢ D.fibre w X i := by + by_cases hw : w = 0 + · subst w + exact pt_mem_sigma ha hg + · simpa only [node, if_neg hw, fibre] using spair_mem hw ha hg + +theorem mem_fibre {D : IndexedContainer V} {w : Nat} {X i x : V} : + x ∈ˢ D.fibre w X i ↔ ∃ a, a ∈ˢ D.shapes i ∧ + ∃ g, g ∈ˢ piSet (D.positions a) (fun p => app X (D.target a p)) ∧ x = node w a g := by + constructor + · intro hx + obtain ⟨a, g, ha, hg, hz, hp⟩ := mem_sigma_elim hx + refine ⟨a, ha, g, hg, ?_⟩ + by_cases hw : w = 0 + · simpa only [node, if_pos hw] using hz hw + · simpa only [node, if_neg hw] using hp hw + · rintro ⟨a, ha, g, hg, rfl⟩ + exact node_mem_fibre ha hg + +theorem app_step {D : IndexedContainer V} {w : Nat} {X : V} + (hX : X ∈ˢ famSpace w D.indices) : + app (D.step w) X = graph (D.fibre w X) D.indices := app_graph hX + +theorem app_app_step {D : IndexedContainer V} {w : Nat} {X i : V} + (hX : X ∈ˢ famSpace w D.indices) (hi : i ∈ˢ D.indices) : + app (app (D.step w) X) i = D.fibre w X i := by + rw [app_step hX, app_graph hi] + +theorem piSet_mono {A : V} {B C : V → V} (h : ∀ a, a ∈ˢ A → B a ⊆ˢ C a) : + piSet A B ⊆ˢ piSet A C := by + intro g hg + obtain ⟨hsub, htotal⟩ := mem_piSet.mp hg + refine mem_piSet.mpr ⟨?_, htotal⟩ + intro q hq + obtain ⟨a, ha, b, hb, rfl⟩ := mem_sigmaPairs.mp (hsub q hq) + exact mem_sigmaPairs.mpr ⟨a, ha, b, h a ha b hb, rfl⟩ + +theorem step_maps {D : IndexedContainer V} {w : Nat} (hD : D.WF w) : + MapsFam w D.indices (D.step w) := by + intro X hX + rw [app_step hX] + refine graph_mem_famSpace fun i hi => ?_ + by_cases hw : w = 0 + · subst w + simpa only [fibre, sigmaSet_zero, univ_zero] using truthVal_mem_univZero + (∃ a, a ∈ˢ D.shapes i ∧ ∃ g, g ∈ˢ piSet (D.positions a) + (fun p => app X (D.target a p))) + · rw [fibre, sigmaSet_pos hw] + let hU := univ_isTGUniverse (V := V) hw + refine hU.sigmaPairs_mem (hD.shapes_mem hw i hi) fun a ha => ?_ + exact hU.piSet_mem (hD.positions_mem hw i a hi ha) fun p hp => + famSpace_app hX (hD.target_mem i a p hi ha hp) + +theorem step_mono {D : IndexedContainer V} {w : Nat} (hD : D.WF w) : + MonoFam w D.indices (D.step w) := by + intro X Y hX hY hXY i hi x hx + rw [app_app_step hX hi] at hx + rw [app_app_step hY hi] + obtain ⟨a, ha, g, hg, rfl⟩ := mem_fibre.mp hx + exact node_mem_fibre ha (piSet_mono + (fun p hp => hXY _ (hD.target_mem i a p hi ha hp)) g hg) + +/-- The closed member needed by the fixed-point theorem is constructed. +At Prop the top truth family suffices; positive sorts use accessible codes. -/ +theorem closed_exists {D : IndexedContainer V} {w : Nat} (hD : D.WF w) : + ∃ L, IsClosedFam w D.indices (D.step w) L := by + by_cases hw : w = 0 + · subst w + let L := graph (fun _ => (unitSet : V)) D.indices + have hL : L ∈ˢ famSpace 0 D.indices := + graph_mem_famSpace fun _ _ => unitSet_mem_univ 0 + refine ⟨L, hL, ?_⟩ + intro i hi x hx + rw [app_app_step hL hi] at hx + obtain ⟨a, _, g, _, rfl⟩ := mem_fibre.mp hx + simpa [L, app_graph hi, node] using (pt_mem_unitSet (V := V)) + · apply container_closed_exists hw (fun X => app (D.step w) X) + D.shapes D.positions D.target spair + (hD.shapes_mem hw) (hD.positions_mem hw) hD.target_mem + · intro i a g hi ha hg + let hU := univ_isTGUniverse (V := V) hw + simpa only [spair] using hU.kpair_mem (empty_mem_univ w) + (hU.transitive (hD.shapes_mem hw i hi) ha) hg + · intro X hX i hi x hx + rw [app_app_step hX hi] at hx + obtain ⟨a, ha, g, hg, h⟩ := mem_fibre.mp hx + exact ⟨a, ha, g, hg, by simpa only [node, if_neg hw] using h⟩ + +theorem carrier_mem (D : IndexedContainer V) (w : Nat) : + D.carrier w ∈ˢ famSpace w D.indices := lfpFamSet_mem _ _ _ + +theorem carrier_fibre_mem (D : IndexedContainer V) (w : Nat) {i : V} + (hi : i ∈ˢ D.indices) : app (D.carrier w) i ∈ˢ (univ w : V) := + famSpace_app (D.carrier_mem w) hi + +theorem carrier_eq {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + {i : V} (hi : i ∈ˢ D.indices) : + app (D.carrier w) i = D.fibre w (D.carrier w) i := by + rw [← app_app_step (D.carrier_mem w) hi] + exact (app_lfpFamSet_eq (closed_exists hD) (step_mono hD) (step_maps hD) hi).symm + +theorem node_mem_carrier {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + {i a g : V} (hi : i ∈ˢ D.indices) (ha : a ∈ˢ D.shapes i) + (hg : g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p))) : + node w a g ∈ˢ app (D.carrier w) i := by + rw [carrier_eq hD hi] + exact node_mem_fibre ha hg + +/-- Structural induction supplies hypotheses at every recursive position, +including all arguments of recursive function fields. -/ +theorem induction {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (P : V → V → Prop) + (hstep : ∀ i, i ∈ˢ D.indices → ∀ a, a ∈ˢ D.shapes i → ∀ g, + g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p)) → + (∀ p, p ∈ˢ D.positions a → P (D.target a p) (app g p)) → P i (node w a g)) : + ∀ i, i ∈ˢ D.indices → ∀ x, x ∈ˢ app (D.carrier w) i → P i x := by + apply lfpFamSet_induction (closed_exists hD) (step_mono hD) P + intro i hi x hx + let X := graph (fun i => sep (app (D.carrier w) i) (P i)) D.indices + have hX : X ∈ˢ famSpace w D.indices := + graph_mem_famSpace fun i hi => univ_sep_mem (D.carrier_fibre_mem w hi) + change x ∈ˢ app (app (D.step w) X) i at hx + rw [app_app_step hX hi] at hx + obtain ⟨a, ha, g, hg, rfl⟩ := mem_fibre.mp hx + have hchild (p : V) (hp : p ∈ˢ D.positions a) : + app g p ∈ˢ app (D.carrier w) (D.target a p) ∧ P (D.target a p) (app g p) := by + have h := app_mem_of_mem_piSet hg hp + rw [show X = graph (fun i => sep (app (D.carrier w) i) (P i)) D.indices from rfl, + app_graph (hD.target_mem i a p hi ha hp)] at h + exact mem_sep.mp h + apply hstep i hi a ha g + · apply piSet_mono (B := fun p => app X (D.target a p)) _ g hg + intro p hp y hy + rw [show X = graph (fun i => sep (app (D.carrier w) i) (P i)) D.indices from rfl, + app_graph (hD.target_mem i a p hi ha hp)] at hy + exact (mem_sep.mp hy).1 + · exact fun p hp => (hchild p hp).2 + +end IndexedContainer +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Inductive/Recursor.lean b/Ix/Theory/Model/Inductive/Recursor.lean new file mode 100644 index 000000000..0c3acc373 --- /dev/null +++ b/Ix/Theory/Model/Inductive/Recursor.lean @@ -0,0 +1,218 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Inductive.Container + +/-! +Recursion over indexed carriers. Large elimination requires recoverable +constructor data: automatic in positive sorts, and derived from singleton +shape fibres at Prop. Accessibility is proved by the carrier's induction +principle. No well-founded recursion or computation law is assumed. +-/ + +namespace Ix.Theory.Model.IndexedContainer + +open SetTheory + +universe u +variable {V : Type u} [SetTheory V] + +abbrev Element (D : IndexedContainer V) (w : Nat) := + { ix : V × V // ix.1 ∈ˢ D.indices ∧ ix.2 ∈ˢ app (D.carrier w) ix.1 } + +/-- At Prop every constructor value is the proof point. Large elimination +therefore needs at most one shape at each index. The source producer checks +this criterion; positive carriers need no singleton restriction. -/ +def LargeElim (D : IndexedContainer V) (w : Nat) : Prop := + w = 0 → ∀ i, i ∈ˢ D.indices → ∀ a b, + a ∈ˢ D.shapes i → b ∈ˢ D.shapes i → a = b + +theorem largeElim_of_pos (D : IndexedContainer V) {w : Nat} (hw : w ≠ 0) : + D.LargeElim w := fun h => False.elim (hw h) + +theorem node_inj {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) {i a b g h : V} + (hi : i ∈ˢ D.indices) (ha : a ∈ˢ D.shapes i) (hb : b ∈ˢ D.shapes i) + (hg : g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p))) + (hh : h ∈ˢ piSet (D.positions b) (fun p => app (D.carrier w) (D.target b p))) + (he : node w a g = node w b h) : a = b ∧ g = h := by + by_cases hw : w = 0 + · subst w + have hab := hlarge rfl i hi a b ha hb + subst b + refine ⟨rfl, eq_of_mem_piSet_app_eq hg hh ?_⟩ + intro p hp + have hP : app (D.carrier 0) (D.target a p) ∈ˢ (univZero : V) := by + simpa only [univ_zero] using D.carrier_fibre_mem 0 (hD.target_mem i a p hi ha hp) + exact (eq_pt_of_mem_univZero hP (app_mem_of_mem_piSet (a := p) hg hp)).trans + (eq_pt_of_mem_univZero hP (app_mem_of_mem_piSet (a := p) hh hp)).symm + · apply kpair_inj + simpa only [node, if_neg hw, spair] using he + +def Child (D : IndexedContainer V) (w : Nat) (child parent : D.Element w) : Prop := + ∃ a, a ∈ˢ D.shapes parent.val.1 ∧ ∃ g, + g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p)) ∧ + parent.val.2 = node w a g ∧ ∃ p, p ∈ˢ D.positions a ∧ + child.val = (D.target a p, app g p) + +theorem child_wellFounded {D : IndexedContainer V} {w : Nat} + (hD : D.WF w) (hlarge : D.LargeElim w) : WellFounded (D.Child w) := by + constructor + rintro ⟨⟨i, x⟩, hi, hx⟩ + apply D.induction hD (fun i x => ∀ h : i ∈ˢ D.indices ∧ x ∈ˢ app (D.carrier w) i, + Acc (D.Child w) ⟨(i, x), h⟩) ?_ i hi x hx ⟨hi, hx⟩ + intro i hi a ha g hg ih h + constructor + intro y hy + obtain ⟨b, hb, g', hg', he, p, hp, hyp⟩ := hy + obtain ⟨rfl, rfl⟩ := node_inj hD hlarge hi ha hb hg hg' he + have hy' : y = ⟨(D.target a p, app g p), + hD.target_mem i a p hi ha hp, app_mem_of_mem_piSet hg hp⟩ := Subtype.ext hyp + rw [hy'] + exact ih p hp ⟨hD.target_mem i a p hi ha hp, app_mem_of_mem_piSet hg hp⟩ + +structure NodeView (D : IndexedContainer V) (w : Nat) (z : D.Element w) where + shape : V + branches : V + shape_mem : shape ∈ˢ D.shapes z.val.1 + branches_mem : branches ∈ˢ piSet (D.positions shape) + (fun p => app (D.carrier w) (D.target shape p)) + equation : z.val.2 = node w shape branches + +noncomputable def view {D : IndexedContainer V} {w : Nat} + (hD : D.WF w) (z : D.Element w) : D.NodeView w z := + let ex := mem_fibre.mp ((carrier_eq hD z.property.1) ▸ z.property.2) + let a := Classical.choose ex + let ha := Classical.choose_spec ex + let g := Classical.choose ha.2 + let hg := Classical.choose_spec ha.2 + ⟨a, g, ha.1, hg.1, hg.2⟩ + +noncomputable def child {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + {i a g : V} (hi : i ∈ˢ D.indices) (ha : a ∈ˢ D.shapes i) + (hg : g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p))) + (p : V) (hp : p ∈ˢ D.positions a) : D.Element w := + ⟨(D.target a p, app g p), hD.target_mem i a p hi ha hp, app_mem_of_mem_piSet hg hp⟩ + +theorem child_rel {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + {z : D.Element w} (v : D.NodeView w z) {p : V} (hp : p ∈ˢ D.positions v.shape) : + D.Child w (child hD z.property.1 v.shape_mem v.branches_mem p hp) z := + ⟨v.shape, v.shape_mem, v.branches, v.branches_mem, v.equation, p, hp, rfl⟩ + +noncomputable def childResults {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + {i a g : V} (hi : i ∈ˢ D.indices) (ha : a ∈ˢ D.shapes i) + (hg : g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p))) + (r : D.Element w → V) : V := + open Classical in + graph (fun p => if hp : p ∈ˢ D.positions a then r (child hD hi ha hg p hp) else empty) + (D.positions a) + +theorem app_childResults {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + {i a g : V} (hi : i ∈ˢ D.indices) (ha : a ∈ˢ D.shapes i) + (hg : g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p))) + (r : D.Element w → V) {p : V} (hp : p ∈ˢ D.positions a) : + app (childResults hD hi ha hg r) p = r (child hD hi ha hg p hp) := by + simp only [childResults, app_graph hp, dif_pos hp] + +noncomputable def foldStep {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (algebra : V → V → V → V → V) (z : D.Element w) + (r : ∀ y, D.Child w y z → V) : V := + open Classical in + let v := view hD z + algebra z.val.1 v.shape v.branches + (graph (fun p => if hp : p ∈ˢ D.positions v.shape then + r (child hD z.property.1 v.shape_mem v.branches_mem p hp) (child_rel hD v hp) + else empty) (D.positions v.shape)) + +noncomputable def fold {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) (algebra : V → V → V → V → V) : D.Element w → V := + (child_wellFounded hD hlarge).fix (foldStep hD algebra) + +theorem fold_eq_view {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) (algebra : V → V → V → V → V) (z : D.Element w) : + fold hD hlarge algebra z = + algebra z.val.1 (view hD z).shape (view hD z).branches + (childResults hD z.property.1 (view hD z).shape_mem (view hD z).branches_mem + (fold hD hlarge algebra)) := by + rw [fold, WellFounded.fix_eq] + rfl + +theorem fold_node {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) (algebra : V → V → V → V → V) + {i a g : V} (hi : i ∈ˢ D.indices) (ha : a ∈ˢ D.shapes i) + (hg : g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p))) : + fold hD hlarge algebra ⟨(i, node w a g), hi, node_mem_carrier hD hi ha hg⟩ = + algebra i a g (childResults hD hi ha hg (fold hD hlarge algebra)) := by + let z : D.Element w := ⟨(i, node w a g), hi, node_mem_carrier hD hi ha hg⟩ + have inj := node_inj hD hlarge hi ha (view hD z).shape_mem hg + (view hD z).branches_mem (view hD z).equation + change fold hD hlarge algebra z = _ + rw [fold_eq_view] + simp only [← inj.1, ← inj.2] + rfl + +def AlgebraTyping (D : IndexedContainer V) (w : Nat) + (M : V → V → V) (algebra : V → V → V → V → V) : Prop := + ∀ i, i ∈ˢ D.indices → ∀ a, a ∈ˢ D.shapes i → ∀ g, + g ∈ˢ piSet (D.positions a) (fun p => app (D.carrier w) (D.target a p)) → + ∀ ih, ih ∈ˢ piSet (D.positions a) (fun p => M (D.target a p) (app g p)) → + algebra i a g ih ∈ˢ M i (node w a g) + +theorem fold_mem {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) {M : V → V → V} {algebra : V → V → V → V → V} + (ha : D.AlgebraTyping w M algebra) (z : D.Element w) : + fold hD hlarge algebra z ∈ˢ M z.val.1 z.val.2 := by + induction z using (child_wellFounded hD hlarge).induction with + | h z ih => + rw [fold_eq_view] + let v := view hD z + have hresults : childResults hD z.property.1 v.shape_mem v.branches_mem + (fold hD hlarge algebra) ∈ˢ + piSet (D.positions v.shape) (fun p => M (D.target v.shape p) (app v.branches p)) := by + apply graph_mem_piSet + intro p hp + simpa only [dif_pos hp, child] using + ih (child hD z.property.1 v.shape_mem v.branches_mem p hp) (child_rel hD v hp) + have hstep := ha z.val.1 z.property.1 v.shape v.shape_mem v.branches v.branches_mem + _ hresults + exact (congrArg (fun x => _ ∈ˢ M z.val.1 x) v.equation).mpr hstep + +/-- Total form used inside function graphs. Only typed domain elements reach +the recursive branch; the value outside that domain is irrelevant. -/ +noncomputable def foldAt {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) (algebra : V → V → V → V → V) (i x : V) : V := + open Classical in + if h : i ∈ˢ D.indices ∧ x ∈ˢ app (D.carrier w) i then + fold hD hlarge algebra ⟨(i, x), h⟩ else empty + +theorem foldAt_eq {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) (algebra : V → V → V → V → V) {i x : V} + (hi : i ∈ˢ D.indices) (hx : x ∈ˢ app (D.carrier w) i) : + foldAt hD hlarge algebra i x = fold hD hlarge algebra ⟨(i, x), hi, hx⟩ := by + simp only [foldAt, dif_pos (And.intro hi hx)] + +theorem foldAt_mem {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) {M : V → V → V} {algebra : V → V → V → V → V} + (ha : D.AlgebraTyping w M algebra) {i x : V} + (hi : i ∈ˢ D.indices) (hx : x ∈ˢ app (D.carrier w) i) : + foldAt hD hlarge algebra i x ∈ˢ M i x := by + rw [foldAt_eq hD hlarge algebra hi hx] + exact fold_mem hD hlarge ha _ + +/-- Small elimination does not need constructor injectivity. A Prop-valued +motive follows directly by structural induction, even for many constructors. -/ +theorem small_elim {D : IndexedContainer V} {w : Nat} (hD : D.WF w) + {M : V → V → V} {algebra : V → V → V → V → V} + (hM : ∀ i, i ∈ˢ D.indices → ∀ x, x ∈ˢ app (D.carrier w) i → M i x ∈ˢ (univZero : V)) + (ha : D.AlgebraTyping w M algebra) : + ∀ i, i ∈ˢ D.indices → ∀ x, x ∈ˢ app (D.carrier w) i → (pt : V) ∈ˢ M i x := by + apply D.induction hD (fun i x => (pt : V) ∈ˢ M i x) + intro i hi a ha' g hg ih + have hstep := ha i hi a ha' g hg (graph (fun _ => (pt : V)) (D.positions a)) + (graph_mem_piSet ih) + have he := eq_pt_of_mem_univZero (hM i hi _ (node_mem_carrier hD hi ha' hg)) hstep + rwa [he] at hstep + +end Ix.Theory.Model.IndexedContainer diff --git a/Ix/Theory/Model/Inductive/Telescope.lean b/Ix/Theory/Model/Inductive/Telescope.lean new file mode 100644 index 000000000..01d0ddf80 --- /dev/null +++ b/Ix/Theory/Model/Inductive/Telescope.lean @@ -0,0 +1,585 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Judgment +import Ix.Theory.Model.Support +import Ix.Theory.Model.SetModel.TupleTower + +/-! +Dependent telescopes used by inductive parameters, indices, constructor +fields, and recursive function domains. Curried functions and tuple codes +share the same fitting relation. Computation requires fitting arguments, +including when a function is represented by the proof point. +-/ + +namespace Ix.Theory.Model.Telescope + +open SetTheory SetTheory.Tower SetModel + +universe u v +variable {V : Type v} [SetTheory V] + +noncomputable def piN (w : Nat) : {n : Nat} → TeleS V n → (List V → V) → V + | _, .nil, R => R [] + | _, .cons A B, R => piR w A (fun x => piN w (B x) (fun xs => R (x :: xs))) + +noncomputable def curry (w : Nat) : {n : Nat} → TeleS V n → (List V → V) → V + | _, .nil, f => f [] + | _, .cons A B, f => lamR w A (fun x => curry w (B x) (fun xs => f (x :: xs))) + +noncomputable def applyN : V → List V → V + | f, [] => f + | f, x :: xs => applyN (app f x) xs + +theorem applyN_append (f : V) (xs ys : List V) : + applyN f (xs ++ ys) = applyN (applyN f xs) ys := by + induction xs generalizing f <;> simp_all [applyN] + +theorem curry_mem {w : Nat} : ∀ {n} (T : TeleS V n) {f R : List V → V}, + (∀ xs, FitsS T xs → f xs ∈ˢ R xs) → curry w T f ∈ˢ piN w T R + | _, .nil, _, _, hf => hf [] trivial + | _, .cons _ B, _, _, hf => + lamR_mem fun x hx => curry_mem (B x) (fun xs hxs => hf (x :: xs) ⟨hx, hxs⟩) + +theorem piN_zero_mem : ∀ {n} (T : TeleS V n) {R : List V → V}, + (∀ xs, FitsS T xs → R xs ∈ˢ (univZero : V)) → + piN 0 T R ∈ˢ (univZero : V) + | _, .nil, _, hR => hR [] trivial + | _, .cons _ _, _, _ => piR_zero_mem_univZero + +theorem applyN_mem {w : Nat} : ∀ {n} (T : TeleS V n) {f : V} {R : List V → V} + {xs : List V}, f ∈ˢ piN w T R → FitsS T xs → + (w = 0 → ∀ ys, FitsS T ys → R ys ∈ˢ (univZero : V)) → + applyN f xs ∈ˢ R xs + | _, .nil, _, _, [], hf, _, _ => hf + | _, .cons _ B, _, R, x :: xs, hf, hxs, hR => by + apply applyN_mem (B x) (R := fun ys => R (x :: ys)) + (app_mem_piR hf hxs.1 ?_) hxs.2 + · intro hw ys hys + exact hR hw (x :: ys) ⟨hxs.1, hys⟩ + · intro hw y hy + subst w + exact piN_zero_mem (B y) (fun ys hys => hR rfl (y :: ys) ⟨hy, hys⟩) + +theorem applyN_curry {w : Nat} : ∀ {n} (T : TeleS V n) {f R : List V → V} + {xs : List V}, FitsS T xs → + (∀ ys, FitsS T ys → f ys ∈ˢ R ys) → + (w = 0 → ∀ ys, FitsS T ys → R ys ∈ˢ (univZero : V)) → + applyN (curry w T f) xs = f xs + | _, .nil, _, _, [], _, _, _ => rfl + | _, .cons _ B, f, R, x :: xs, hxs, hf, hR => by + change applyN (app (lamR w _ _) x) xs = f (x :: xs) + rw [app_lamR hxs.1 (B := fun y => piN w (B y) (fun ys => R (y :: ys))) + (fun y hy => curry_mem (B y) (fun ys hys => hf (y :: ys) ⟨hy, hys⟩)) + (fun hw y hy => by + subst w + exact piN_zero_mem (B y) (fun ys hys => hR rfl (y :: ys) ⟨hy, hys⟩))] + exact applyN_curry (B x) hxs.2 + (fun ys hys => hf (x :: ys) ⟨hxs.1, hys⟩) + (fun hw ys hys => hR hw (x :: ys) ⟨hxs.1, hys⟩) + +theorem curry_congr {w : Nat} : ∀ {n} (T : TeleS V n) {f g : List V → V}, + (∀ xs, FitsS T xs → f xs = g xs) → curry w T f = curry w T g + | _, .nil, _, _, h => h [] trivial + | _, .cons _ B, _, _, h => + lamR_congr fun x hx => curry_congr (B x) (fun xs hxs => h (x :: xs) ⟨hx, hxs⟩) + +theorem piN_zero_agree {w w' : Nat} (hw : w = 0 ↔ w' = 0) : + ∀ {n} (T : TeleS V n) {R R' : List V → V}, + (∀ xs, FitsS T xs → R xs = R' xs) → piN w T R = piN w' T R' + | _, .nil, _, _, h => h [] trivial + | _, .cons _ B, _, _, h => + piR_zero_agree hw fun x hx => piN_zero_agree hw (B x) (fun xs hxs => h (x :: xs) ⟨hx, hxs⟩) + +theorem piN_congr {w : Nat} {n : Nat} (T : TeleS V n) {R R' : List V → V} + (h : ∀ xs, FitsS T xs → R xs = R' xs) : piN w T R = piN w T R' := + piN_zero_agree Iff.rfl T h + +theorem curry_zero_agree {w w' : Nat} (hw : w = 0 ↔ w' = 0) : + ∀ {n} (T : TeleS V n) {f f' : List V → V}, + (∀ xs, FitsS T xs → f xs = f' xs) → curry w T f = curry w' T f' + | _, .nil, _, _, h => h [] trivial + | _, .cons _ B, _, _, h => + lamR_zero_agree hw fun x hx => curry_zero_agree hw (B x) (fun xs hxs => h (x :: xs) ⟨hx, hxs⟩) + +theorem curry_point : ∀ {n} (T : TeleS V n), curry 0 T (fun _ => (pt : V)) = pt + | _, .nil => rfl + | _, .cons _ _ => lamR_zero + +theorem curry_applyN {w : Nat} : ∀ {n} (T : TeleS V n) {f : V} {R : List V → V}, + f ∈ˢ piN w T R → + (w = 0 → ∀ ys, FitsS T ys → R ys ∈ˢ (univZero : V)) → + curry w T (applyN f) = f + | _, .nil, _, _, _, _ => rfl + | _, .cons _ B, _, R, hf, hR => by + change lamR w _ (fun x => curry w (B x) (applyN (app _ x))) = _ + calc + _ = lamR w _ (fun x => app _ x) := by + apply lamR_congr + intro x hx + apply curry_applyN (B x) (R := fun ys => R (x :: ys)) + (app_mem_piR hf hx ?_) + · intro hw ys hys + exact hR hw (x :: ys) ⟨hx, hys⟩ + · intro hw y hy + subst w + exact piN_zero_mem (B y) (fun ys hys => hR rfl (y :: ys) ⟨hy, hys⟩) + _ = _ := lamR_eta hf + +/-- Tuple codes always preserve their fields, even when a family itself is +Prop-valued. The carrier bounds are needed only at positive sorts. -/ +theorem tower_graph_mem {w : Nat} (hw : w ≠ 0) : ∀ {n} (T : TeleS V n), + BoundS w T → towerSet 1 T ∈ˢ (univ w : V) + | _, .nil, _ => unitSet_mem_univ w + | _, .cons _ B, hB => by + change sigmaSet 1 _ _ ∈ˢ (univ w : V) + rw [sigmaSet_pos (by decide : 1 ≠ 0)] + exact (univ_isTGUniverse hw).sigmaPairs_mem hB.1 + (fun x hx => tower_graph_mem hw (B x) (hB.2 x hx)) + +theorem piN_mem_univ {w : Nat} : ∀ {n} (T : TeleS V n) {R : List V → V}, + (w ≠ 0 → BoundS w T) → (∀ xs, FitsS T xs → R xs ∈ˢ (univ w : V)) → + piN w T R ∈ˢ (univ w : V) + | _, .nil, _, _, hR => hR [] trivial + | _, .cons A B, R, hT, hR => by + by_cases hw : w = 0 + · subst w + exact univ_zero (V := V) ▸ piR_zero_mem_univZero + · change piR w A (fun x => piN w (B x) (fun xs => R (x :: xs))) ∈ˢ (univ w : V) + rw [piR_pos hw] + apply (univ_isTGUniverse hw).piSet_mem (hT hw).1 + intro x hx + exact piN_mem_univ (B x) (fun _ => (hT hw).2 x hx) + (fun xs hxs => hR (x :: xs) ⟨hx, hxs⟩) + +def simple : (domains : List V) → TeleS V domains.length + | [] => .nil + | A :: rest => .cons A (fun _ => simple rest) + +theorem fits_simple_getD : ∀ {domains xs : List V}, FitsS (simple domains) xs → + ∀ {i A}, domains[i]? = some A → xs.getD i empty ∈ˢ A + | [], [], _, _, _, h => by simp at h + | _ :: _, _ :: _, h, 0, _, hA => by + cases Option.some.inj hA + exact h.1 + | _ :: _, _ :: _, h, i + 1, _, hA => fits_simple_getD h.2 hA + +theorem fits_simple_of_getD : ∀ {domains xs : List V}, xs.length = domains.length → + (∀ i A, domains[i]? = some A → xs.getD i empty ∈ˢ A) → FitsS (simple domains) xs + | [], [], _, _ => trivial + | _ :: _, _ :: _, hlen, h => + ⟨h 0 _ rfl, fits_simple_of_getD (Nat.succ.inj hlen) (fun i A hA => h (i + 1) A hA)⟩ + +theorem fits_simple_map {α : Type u} (f : α → V) (domains : List α) (xs : List V) + (hlen : xs.length = domains.length) + (h : ∀ i a, domains[i]? = some a → xs.getD i empty ∈ˢ f a) : + FitsS (simple (domains.map f)) xs := by + apply fits_simple_of_getD (hlen.trans (List.length_map ..).symm) + intro i A hA + obtain ⟨a, ha, rfl⟩ := Option.map_eq_some_iff.mp + ((List.getElem?_map (l := domains) (f := f)).symm.trans hA) + exact h i a ha + +theorem fits_unique_of_prop : ∀ {n} {T : TeleS V n} {xs ys : List V}, + PropS T → FitsS T xs → FitsS T ys → xs = ys + | _, .nil, [], [], _, _, _ => rfl + | _, .cons _ B, x :: xs, y :: ys, hT, hx, hy => by + have he := subsingleton_of_mem_univZero hT.1 hx.1 hy.1 + subst y + exact congrArg (x :: ·) (fits_unique_of_prop (T := B x) (hT.2 x hx.1) hx.2 hy.2) + +variable {β : Type u} + +def context (Γ : Context β) : List (AExpr β) → Context β + | [] => Γ + | A :: rest => context (Γ.push A) rest + +def extend (env : Nat → V) : List V → Nat → V + | [] => env + | x :: xs => extend (Valuation.cons x env) xs + +omit [SetTheory V] in +theorem extend_beyond (env : Nat → V) (xs : List V) (i : Nat) : + extend env xs (xs.length + i) = env i := by + induction xs generalizing env i with + | nil => simp [extend] + | cons x xs ih => + simpa only [extend, List.length_cons, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, + Valuation.cons_succ] using ih (Valuation.cons x env) (i + 1) + +theorem extend_getD (env : Nat → V) (xs : List V) (i : Nat) (hi : i < xs.length) : + extend env xs (xs.length - 1 - i) = xs.getD i empty := by + induction xs generalizing env i with + | nil => simp at hi + | cons x xs ih => + cases i with + | zero => + simpa only [extend, List.length_cons, Nat.add_sub_cancel, Nat.sub_zero, + List.getD_cons_zero, Valuation.cons_zero, Nat.add_zero] using + extend_beyond (Valuation.cons x env) xs 0 + | succ i => + have hidx : (x :: xs).length - 1 - (i + 1) = xs.length - 1 - i := by simp; omega + rw [hidx] + exact ih (Valuation.cons x env) i (by simpa using hi) + +omit [SetTheory V] in +theorem skip_extend (env : Nat → V) (xs : List V) : + Valuation.skip xs.length 0 (extend env xs) = env := by + funext i + simpa only [Valuation.skip, Nat.not_lt_zero, ↓reduceIte] using extend_beyond env xs i + +omit [SetTheory V] in +theorem extend_append (env : Nat → V) (xs ys : List V) : + extend env (xs ++ ys) = extend (extend env xs) ys := by + induction xs generalizing env <;> simp_all [extend] + +omit [SetTheory V] in +theorem skip_extend_at (env : Nat → V) (xs : List V) (count cutoff : Nat) : + Valuation.skip count (xs.length + cutoff) (extend env xs) = + extend (Valuation.skip count cutoff env) xs := by + induction xs generalizing env cutoff with + | nil => simp only [List.length_nil, Nat.zero_add, extend] + | cons x xs ih => + simpa only [extend, List.length_cons, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, + Valuation.skip_cons] using ih (Valuation.cons x env) (cutoff + 1) + +omit [SetTheory V] in +theorem skip_middle (env : Nat → V) (middle tail : List V) : + Valuation.skip middle.length tail.length (extend (extend env middle) tail) = extend env tail := by + simpa only [Nat.add_zero, skip_extend] using skip_extend_at (extend env middle) tail middle.length 0 + +noncomputable def interpret (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) : (domains : List (AExpr β)) → TeleS V domains.length + | [] => .nil + | A :: rest => .cons (interp constants levels env A) + (fun x => interpret constants levels (Valuation.cons x env) rest) + +theorem piN_append (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (left right : List (AExpr β)) (w : Nat) (R : List V → V) : + piN w (interpret constants levels env (left ++ right)) R = + piN w (interpret constants levels env left) (fun xs => + piN w (interpret constants levels (extend env xs) right) (fun ys => R (xs ++ ys))) := by + induction left generalizing env R with + | nil => rfl + | cons A rest ih => + change piR w _ _ = piR w _ _ + congr 1 + funext x + exact ih (Valuation.cons x env) (fun xs => R (x :: xs)) + +theorem curry_append (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (left right : List (AExpr β)) (w : Nat) (f : List V → V) : + curry w (interpret constants levels env (left ++ right)) f = + curry w (interpret constants levels env left) (fun xs => + curry w (interpret constants levels (extend env xs) right) (fun ys => f (xs ++ ys))) := by + induction left generalizing env f with + | nil => rfl + | cons A rest ih => + change lamR w _ _ = lamR w _ _ + congr 1 + funext x + exact ih (Valuation.cons x env) (fun xs => f (x :: xs)) + +def lift (count : Nat) : List (AExpr β) → (cutoff : Nat := 0) → List (AExpr β) + | [], _ => [] + | A :: rest, k => A.liftN count k :: lift count rest (k + 1) + +def inst (arg : AExpr β) : List (AExpr β) → (cutoff : Nat := 0) → List (AExpr β) + | [], _ => [] + | A :: rest, k => A.inst arg k :: inst arg rest (k + 1) + +/-- A telescope of domains that all live in the same outer context. -/ +def independent : List (AExpr β) → (offset : Nat := 0) → List (AExpr β) + | [], _ => [] + | A :: rest, offset => A.liftN offset :: independent rest (offset + 1) + +theorem piN_independent (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (domains : List (AExpr β)) (previous : List V) (w : Nat) (R : List V → V) : + piN w (interpret constants levels (extend env previous) (independent domains previous.length)) R = + piN w (simple (domains.map (interp constants levels env))) R := by + induction domains generalizing previous R with + | nil => rfl + | cons A rest ih => + change piR w (interp constants levels (extend env previous) (A.liftN previous.length)) _ = piR w _ _ + rw [interp_liftN, skip_extend] + congr 1 + funext x + have ht := ih (previous ++ [x]) (fun xs => R (x :: xs)) + have hlen : (previous ++ [x]).length = previous.length + 1 := by simp + rw [hlen] at ht + simpa only [extend_append, extend] using ht + +theorem curry_independent (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (domains : List (AExpr β)) (previous : List V) (w : Nat) (f : List V → V) : + curry w (interpret constants levels (extend env previous) (independent domains previous.length)) f = + curry w (simple (domains.map (interp constants levels env))) f := by + induction domains generalizing previous f with + | nil => rfl + | cons A rest ih => + change lamR w (interp constants levels (extend env previous) (A.liftN previous.length)) _ = lamR w _ _ + rw [interp_liftN, skip_extend] + congr 1 + funext x + have ht := ih (previous ++ [x]) (fun xs => f (x :: xs)) + have hlen : (previous ++ [x]).length = previous.length + 1 := by simp + rw [hlen] at ht + simpa only [extend_append, extend] using ht + +@[simp] theorem length_lift (count : Nat) (domains : List (AExpr β)) (k : Nat) : + (lift count domains k).length = domains.length := by + induction domains generalizing k <;> simp_all [lift] + +@[simp] theorem length_inst (arg : AExpr β) (domains : List (AExpr β)) (k : Nat) : + (inst arg domains k).length = domains.length := by + induction domains generalizing k <;> simp_all [inst] + +theorem fits_lift (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (count : Nat) (domains : List (AExpr β)) (k : Nat) (xs : List V) : + FitsS (interpret constants levels env (lift count domains k)) xs ↔ + FitsS (interpret constants levels (Valuation.skip count k env) domains) xs := by + induction domains generalizing env k xs with + | nil => rfl + | cons A rest ih => + cases xs with + | nil => rfl + | cons x xs => + simp only [lift, interpret, FitsS, interp_liftN, ih, Valuation.skip_cons] + +theorem fits_inst (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (arg : AExpr β) (domains : List (AExpr β)) (k : Nat) (xs : List V) : + FitsS (interpret constants levels env (inst arg domains k)) xs ↔ + FitsS (interpret constants levels + (Valuation.insert k (interp constants levels (Valuation.skip k 0 env) arg) env) domains) xs := by + induction domains generalizing env k xs with + | nil => rfl + | cons A rest ih => + cases xs with + | nil => rfl + | cons x xs => + simp only [inst, interpret, FitsS, interp_inst, ih, + Valuation.skip_succ_cons, Valuation.insert_cons] + +theorem piN_lift (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (count : Nat) (domains : List (AExpr β)) (cutoff w : Nat) (R : List V → V) : + piN w (interpret constants levels env (lift count domains cutoff)) R = + piN w (interpret constants levels (Valuation.skip count cutoff env) domains) R := by + induction domains generalizing env cutoff R with + | nil => rfl + | cons A rest ih => + simp only [lift, interpret, piN, interp_liftN] + congr 1 + funext x + simpa only [Valuation.skip_cons] using ih (Valuation.cons x env) (cutoff + 1) (fun xs => R (x :: xs)) + +theorem curry_lift (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (count : Nat) (domains : List (AExpr β)) (cutoff w : Nat) (f : List V → V) : + curry w (interpret constants levels env (lift count domains cutoff)) f = + curry w (interpret constants levels (Valuation.skip count cutoff env) domains) f := by + induction domains generalizing env cutoff f with + | nil => rfl + | cons A rest ih => + simp only [lift, interpret, curry, interp_liftN] + congr 1 + funext x + simpa only [Valuation.skip_cons] using ih (Valuation.cons x env) (cutoff + 1) (fun xs => f (x :: xs)) + +theorem piN_instL (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (sourceLevels : List VLevel) (domains : List (AExpr β)) (w : Nat) (R : List V → V) : + piN w (interpret constants levels env (domains.map (AExpr.instL sourceLevels))) R = + piN w (interpret constants (sourceLevels.map (VLevel.eval levels)) env domains) R := by + induction domains generalizing env R with + | nil => rfl + | cons A rest ih => + change piR w (interp constants levels env (A.instL sourceLevels)) + (fun x => piN w (interpret constants levels (Valuation.cons x env) + (rest.map (AExpr.instL sourceLevels))) (fun xs => R (x :: xs))) = + piR w (interp constants (sourceLevels.map (VLevel.eval levels)) env A) _ + rw [interp_instL] + congr 1 + funext x + exact ih (Valuation.cons x env) (fun xs => R (x :: xs)) + +theorem curry_instL (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (sourceLevels : List VLevel) (domains : List (AExpr β)) (w : Nat) (f : List V → V) : + curry w (interpret constants levels env (domains.map (AExpr.instL sourceLevels))) f = + curry w (interpret constants (sourceLevels.map (VLevel.eval levels)) env domains) f := by + induction domains generalizing env f with + | nil => rfl + | cons A rest ih => + change lamR w (interp constants levels env (A.instL sourceLevels)) + (fun x => curry w (interpret constants levels (Valuation.cons x env) + (rest.map (AExpr.instL sourceLevels))) (fun xs => f (x :: xs))) = + lamR w (interp constants (sourceLevels.map (VLevel.eval levels)) env A) _ + rw [interp_instL] + congr 1 + funext x + exact ih (Valuation.cons x env) (fun xs => f (x :: xs)) + +theorem fits_instL (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (sourceLevels : List VLevel) (domains : List (AExpr β)) (xs : List V) : + FitsS (interpret constants levels env (domains.map (AExpr.instL sourceLevels))) xs ↔ + FitsS (interpret constants (sourceLevels.map (VLevel.eval levels)) env domains) xs := by + induction domains generalizing env xs with + | nil => rfl + | cons A rest ih => + cases xs with + | nil => rfl + | cons x xs => + change (x ∈ˢ interp constants levels env (A.instL sourceLevels) ∧ + FitsS (interpret constants levels (Valuation.cons x env) (rest.map (AExpr.instL sourceLevels))) xs) ↔ _ + simp only [interp_instL, ih, interpret, FitsS] + +/-- Every field sort is derived by the same semantic typing relation as an +ordinary term. The executable producer checks each successive context. -/ +inductive Formed (entries : Environment β) : Context β → List (AExpr β) → Prop + | nil {Γ} : Formed entries Γ [] + | cons {Γ A rest} (level : VLevel) + (domain : TypingClaim.{u,v} entries Γ A (.sort level)) + (tail : Formed entries (Γ.push A) rest) : Formed entries Γ (A :: rest) + +theorem Formed.valid {entries : Environment β} {Γ : Context β} {domains : List (AExpr β)} + (h : Formed.{u,v} entries Γ domains) (constants : Assignment β V) + (hM : Realizes constants entries) (levels : List Nat) : + ∀ {env xs}, Γ.Valid constants levels env → FitsS (interpret constants levels env domains) xs → + (context Γ domains).Valid constants levels (extend env xs) := by + induction h with + | nil => + intro env xs hΓ hxs + cases xs with + | nil => exact hΓ + | cons _ _ => exact hxs.elim + | cons l hA hrest ih => + intro env xs hΓ hxs + cases xs with + | nil => exact hxs.elim + | cons x xs => + exact ih (env := Valuation.cons x env) (xs := xs) + (hΓ.push (hA V constants hM levels env hΓ).1 hxs.1) hxs.2 + +theorem Formed.append {entries : Environment β} {Γ : Context β} {left right : List (AExpr β)} + (hl : Formed.{u,v} entries Γ left) (hr : Formed.{u,v} entries (context Γ left) right) : + Formed.{u,v} entries Γ (left ++ right) := by + induction hl with + | nil => exact hr + | cons l hA hrest ih => exact .cons l hA (ih hr) + +end Ix.Theory.Model.Telescope + +namespace Ix.Theory.Model.AExpr + +open Certified +universe u v +variable {β : Type u} + +def forallN (p : PropWhen) : List (AExpr β) → AExpr β → AExpr β + | [], B => B + | A :: rest, B => .forallE p A (forallN p rest B) + +def lamN (p : PropWhen) : List (AExpr β) → AExpr β → AExpr β + | [], body => body + | A :: rest, body => .lam p A (lamN p rest body) + +def appN (f : AExpr β) : List (AExpr β) → AExpr β + | [] => f + | x :: xs => appN (.app f x) xs + +theorem forallN_append (p : PropWhen) (left right : List (AExpr β)) (B : AExpr β) : + forallN p (left ++ right) B = forallN p left (forallN p right B) := by + induction left <;> simp_all [forallN] + +theorem lamN_append (p : PropWhen) (left right : List (AExpr β)) (body : AExpr β) : + lamN p (left ++ right) body = lamN p left (lamN p right body) := by + induction left <;> simp_all [lamN] + +theorem appN_append (f : AExpr β) (left right : List (AExpr β)) : + appN f (left ++ right) = appN (appN f left) right := by + induction left generalizing f <;> simp_all [appN] + +theorem ReferencesIn.forallN {entries : Environment β} {p : PropWhen} + {domains : List (AExpr β)} {B : AExpr β} + (hD : ∀ A ∈ domains, A.ReferencesIn entries) (hB : B.ReferencesIn entries) : + (forallN p domains B).ReferencesIn entries := by + induction domains with + | nil => exact hB + | cons A rest ih => + have hA := hD A (List.mem_cons_self ..) + have ht := ih (fun D h => hD D (List.mem_cons_of_mem A h)) + intro r hr + exact (List.mem_append.mp hr).elim (hA r) (ht r) + +theorem ReferencesIn.lamN {entries : Environment β} {p : PropWhen} + {domains : List (AExpr β)} {body : AExpr β} + (hD : ∀ A ∈ domains, A.ReferencesIn entries) (hb : body.ReferencesIn entries) : + (lamN p domains body).ReferencesIn entries := by + induction domains with + | nil => exact hb + | cons A rest ih => + have hA := hD A (List.mem_cons_self ..) + have ht := ih (fun D h => hD D (List.mem_cons_of_mem A h)) + intro r hr + exact (List.mem_append.mp hr).elim (hA r) (ht r) + +@[simp] theorem erase_forallN (p : PropWhen) (domains : List (AExpr β)) (B : AExpr β) : + (forallN p domains B).erase = VExpr.forallN (domains.map erase) B.erase := by + induction domains <;> simp_all [forallN, erase, VExpr.forallN] + +@[simp] theorem erase_lamN (p : PropWhen) (domains : List (AExpr β)) (B : AExpr β) : + (lamN p domains B).erase = VExpr.lamN (domains.map erase) B.erase := by + induction domains <;> simp_all [lamN, erase, VExpr.lamN] + +@[simp] theorem erase_appN (f : AExpr β) (args : List (AExpr β)) : + (appN f args).erase = VExpr.appN f.erase (args.map erase) := by + induction args generalizing f <;> simp_all [appN, erase, VExpr.appN] + +variable {V : Type v} [SetTheory V] + +theorem interp_forallN (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (p : PropWhen) (domains : List (AExpr β)) (B : AExpr β) : + interp constants levels env (forallN p domains B) = + Telescope.piN (regime p levels) (Telescope.interpret constants levels env domains) + (fun xs => interp constants levels (Telescope.extend env xs) B) := by + induction domains generalizing env with + | nil => rfl + | cons A rest ih => + simp only [forallN, interp, Telescope.interpret, Telescope.piN, Telescope.extend, ih] + +theorem interp_lamN (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (p : PropWhen) (domains : List (AExpr β)) (body : AExpr β) : + interp constants levels env (lamN p domains body) = + Telescope.curry (regime p levels) (Telescope.interpret constants levels env domains) + (fun xs => interp constants levels (Telescope.extend env xs) body) := by + induction domains generalizing env with + | nil => rfl + | cons A rest ih => + simp only [lamN, interp, Telescope.interpret, Telescope.curry, Telescope.extend, ih] + +theorem interp_appN (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (f : AExpr β) (args : List (AExpr β)) : + interp constants levels env (appN f args) = + Telescope.applyN (interp constants levels env f) (args.map (interp constants levels env)) := by + induction args generalizing f <;> simp_all [appN, interp, Telescope.applyN] + +end Ix.Theory.Model.AExpr + +namespace Ix.Theory.Model.Telescope + +open Certified +universe u v +variable {β : Type u} + +/-- Formed domains give formation of the entire product telescope. Every +outer binder has the zero condition of the final result sort. -/ +theorem Formed.forallN {entries : Environment β} {Γ : Context β} {domains : List (AExpr β)} + (h : Formed.{u,v} entries Γ domains) {B : AExpr β} {b : VLevel} + (hB : TypingClaim.{u,v} entries (context Γ domains) B (.sort b)) : + ∃ l, zeroCondition l = zeroCondition b ∧ + TypingClaim.{u,v} entries Γ (.forallN (zeroCondition b) domains B) (.sort l) := by + induction h with + | nil => exact ⟨b, rfl, hB⟩ + | cons a hA hrest ih => + obtain ⟨l, hl, htail⟩ := ih hB + exact ⟨.imax a l, hl, TypingClaim.forallE hA htail hl.symm⟩ + +end Ix.Theory.Model.Telescope diff --git a/Ix/Theory/Model/Instantiation.lean b/Ix/Theory/Model/Instantiation.lean new file mode 100644 index 000000000..dcaef4529 --- /dev/null +++ b/Ix/Theory/Model/Instantiation.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Inductive.Telescope + +namespace Ix.Theory.Model + +open SetTheory + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +omit [SetTheory V] in +theorem Valuation.insert_extend_at (env : Nat → V) (xs : List V) (a : V) (k : Nat) : + Valuation.insert (xs.length + k) a (Telescope.extend env xs) = + Telescope.extend (Valuation.insert k a env) xs := by + induction xs generalizing env k with + | nil => simp only [List.length_nil, Nat.zero_add, Telescope.extend] + | cons x xs ih => + simpa only [List.length_cons, Telescope.extend, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm, Valuation.insert_cons] using ih (Valuation.cons x env) (k + 1) + +omit [SetTheory V] in +theorem Valuation.insert_extend (env : Nat → V) (xs : List V) (a : V) : + Valuation.insert xs.length a (Telescope.extend env xs) = + Telescope.extend (Valuation.cons a env) xs := by + simpa only [Nat.add_zero, Valuation.insert_zero] using Valuation.insert_extend_at env xs a 0 + +namespace AExpr + +/-- Simultaneous substitution of an outermost-first field list. -/ +def instRev : AExpr β → List (AExpr β) → AExpr β + | e, [] => e + | e, a :: rest => instRev (e.inst a rest.length) rest + +theorem erase_instRev (e : AExpr β) (args : List (AExpr β)) : + (e.instRev args).erase = e.erase.instRev (args.map AExpr.erase) := by + induction args generalizing e <;> simp_all [instRev, VExpr.instRev] + +theorem interp_instRev (e : AExpr β) (args : List (AExpr β)) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) : + interp constants levels env (e.instRev args) = + interp constants levels (Telescope.extend env (args.map (interp constants levels env))) e := by + induction args generalizing e with + | nil => rfl + | cons a rest ih => + rw [instRev, ih, interp_inst] + have hlen : (rest.map (interp constants levels env)).length = rest.length := List.length_map .. + rw [← hlen, Telescope.skip_extend, Valuation.insert_extend] + rfl + +theorem wellDenoted_instRev (e : AExpr β) (args : List (AExpr β)) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) + (ha : ∀ a ∈ args, WellDenoted constants levels env a) + (he : WellDenoted constants levels + (Telescope.extend env (args.map (interp constants levels env))) e) : + WellDenoted constants levels env (e.instRev args) := by + induction args generalizing e with + | nil => exact he + | cons a rest ih => + apply ih (e.inst a rest.length) (fun b hb => ha b (List.mem_cons_of_mem _ hb)) + have hlen : (rest.map (interp constants levels env)).length = rest.length := List.length_map .. + apply wellDenoted_inst + · simpa only [← hlen, Telescope.skip_extend] using ha a List.mem_cons_self + · simpa only [← hlen, Telescope.skip_extend, Valuation.insert_extend, List.map_cons, Telescope.extend] using he + +end AExpr + +theorem wellDenoted_congr_env (e : AExpr β) (constants : Assignment β V) + (levels : List Nat) {n k : Nat} (hs : e.Scope n k) (env env' : Nat → V) + (h : ∀ i, i < k → env i = env' i) : + WellDenoted constants levels env e ↔ WellDenoted constants levels env' e := by + induction e generalizing k env env' with + | app f a hf ha => + simp only [WellDenoted, hf hs.1 env env' h, ha hs.2 env env' h, + interp_congr_env f constants levels hs.1 env env' h, + interp_congr_env a constants levels hs.2 env env' h] + | lam p A b hA hb | forallE p A b hA hb => + have hcons (x : V) : ∀ i, i < k + 1 → Valuation.cons x env i = Valuation.cons x env' i := by + intro i hi + cases i with + | zero => rfl + | succ i => exact h i (by omega) + simp only [WellDenoted, hA hs.2.1 env env' h, interp_congr_env A constants levels hs.2.1 env env' h, + hb hs.2.2 _ _ (hcons _), interp_congr_env b constants levels hs.2.2 _ _ (hcons _)] + | proj _ _ e ih => exact ih hs env env' h + | _ => rfl + +theorem wellDenoted_closed (e : AExpr β) (constants : Assignment β V) + (levels : List Nat) {n : Nat} (hs : e.Scope n 0) (env env' : Nat → V) : + WellDenoted constants levels env e ↔ WellDenoted constants levels env' e := + wellDenoted_congr_env e constants levels hs env env' (fun _ h => (Nat.not_lt_zero _ h).elim) + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Interpret.lean b/Ix/Theory/Model/Interpret.lean new file mode 100644 index 000000000..90b71cba6 --- /dev/null +++ b/Ix/Theory/Model/Interpret.lean @@ -0,0 +1,150 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Annotated +import Ix.Theory.Model.PrimitiveValues +import Ix.Theory.Model.Value + +/-! +# Total interpretation of annotated Ix syntax + +Constants are interpreted through an explicit assignment, whose compatibility +with checked declarations is a separate invariant. This definition does not +traverse store references. Projections use the uniform ordinary-node field +decoder, and literals use fixed numeral values. Typing either requires +additional facts whose meanings are constructed during declaration admission. +-/ + +namespace Ix.Theory.Model + +open SetTheory SetModel + +universe u v w + +namespace Valuation + +def cons (x : V) (env : Nat → V) : Nat → V + | 0 => x + | i + 1 => env i + +@[simp] theorem cons_zero (x : V) (env : Nat → V) : cons x env 0 = x := rfl +@[simp] theorem cons_succ (x : V) (env : Nat → V) (i : Nat) : cons x env (i + 1) = env i := rfl + +def skip (count cutoff : Nat) (env : Nat → V) : Nat → V := + fun i => if i < cutoff then env i else env (count + i) + +def insert (cutoff : Nat) (x : V) (env : Nat → V) : Nat → V := + fun i => if i < cutoff then env i else if i = cutoff then x else env (i - 1) + +@[simp] theorem skip_zero (env : Nat → V) : skip 0 0 env = env := by + funext i; simp [skip] + +@[simp] theorem skip_cons (n k : Nat) (x : V) (env : Nat → V) : + skip n (k + 1) (cons x env) = cons x (skip n k env) := by + funext i + cases i <;> simp [skip, cons] + +@[simp] theorem insert_cons (k : Nat) (x y : V) (env : Nat → V) : + insert (k + 1) x (cons y env) = cons y (insert k x env) := by + funext i + cases i with + | zero => simp [insert] + | succ i => + by_cases h : i < k + · simp [insert, h] + · by_cases e : i = k + · simp [insert, e] + · have hi : i ≠ 0 := by omega + cases i with + | zero => exact (hi rfl).elim + | succ i => simp [insert, h, e] + +@[simp] theorem insert_zero (x : V) (env : Nat → V) : insert 0 x env = cons x env := by + funext i; cases i <;> simp [insert] + +@[simp] theorem skip_succ_cons (n : Nat) (x : V) (env : Nat → V) : + skip (n + 1) 0 (cons x env) = skip n 0 env := by + funext i + simp [skip, show n + 1 + i = (n + i) + 1 by omega] + +end Valuation + +/-- A value for every exact reference and concrete universe argument list. -/ +abbrev Assignment (β : Type u) (V : Type v) := ConstRef β → List Nat → V + +variable {β : Type u} {V : Type v} [SetTheory V] + +noncomputable def interp (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) : AExpr β → V + | .bvar i => env i + | .sort l => univ (l.eval levels) + | .const r ls => constants r (ls.map (VLevel.eval levels)) + | .app f a => app (interp constants levels env f) (interp constants levels env a) + | .lam p a b => lamR (regime p levels) (interp constants levels env a) + (fun x => interp constants levels (Valuation.cons x env) b) + | .forallE p a b => piR (regime p levels) (interp constants levels env a) + (fun x => interp constants levels (Valuation.cons x env) b) + | .proj _ i e => projectValue i (interp constants levels env e) + | .natLit n => Numeral.value n + +theorem interp_liftN (e : AExpr β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (n k : Nat) : + interp constants levels env (e.liftN n k) = + interp constants levels (Valuation.skip n k env) e := by + induction e generalizing k env with + | bvar i => simp [AExpr.liftN, interp, liftVar, Valuation.skip]; split <;> rfl + | lam p a b ha hb | forallE p a b ha hb => + simp only [AExpr.liftN, interp, ha] + congr 1 + funext x + rw [hb, Valuation.skip_cons] + | _ => simp_all [AExpr.liftN, interp] + +theorem interp_inst (e a : AExpr β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (k : Nat) : + interp constants levels env (e.inst a k) = + interp constants levels + (Valuation.insert k (interp constants levels (Valuation.skip k 0 env) a) env) e := by + induction e generalizing k env with + | bvar i => + by_cases h : i < k + · simp [AExpr.inst, AExpr.instVar, interp, Valuation.insert, h] + · by_cases h' : i = k <;> + simp [AExpr.inst, AExpr.instVar, interp, Valuation.insert, h, h', interp_liftN] + | lam p A b hA hb | forallE p A b hA hb => + simp only [AExpr.inst, interp, hA] + congr 1 + funext x + rw [hb, Valuation.skip_succ_cons, Valuation.insert_cons] + | _ => simp_all [AExpr.inst, interp] + +theorem interp_instL (e : AExpr β) (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) (ls : List VLevel) : + interp constants levels env (e.instL ls) = + interp constants (ls.map (VLevel.eval levels)) env e := by + induction e generalizing env with + | const r us => + simp [AExpr.instL, interp, List.map_map, Function.comp_def, VLevel.eval_inst] + | lam p A b hA hb | forallE p A b hA hb => + simp only [AExpr.instL, interp, hA, regime_instCondition] + congr 1 + funext x + exact hb _ + | _ => simp_all [AExpr.instL, interp, VLevel.eval_inst] + +theorem interp_rename {γ : Type w} (e : AExpr β) (mapping : β → γ) + (constants : Assignment β V) (constants' : Assignment γ V) + (h : ∀ r ls, constants' (r.rename mapping) ls = constants r ls) + (levels : List Nat) (env : Nat → V) : + interp constants' levels env (e.rename mapping) = interp constants levels env e := by + induction e generalizing env with + | lam p A b hA hb | forallE p A b hA hb => + simp only [AExpr.rename, interp, hA] + congr 1 + funext x + exact hb _ + | _ => simp_all [AExpr.rename, interp] + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Judgment.lean b/Ix/Theory/Model/Judgment.lean new file mode 100644 index 000000000..17fe19535 --- /dev/null +++ b/Ix/Theory/Model/Judgment.lean @@ -0,0 +1,280 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Environment + +/-! +# Semantic contracts and their rule producers + +These specifications quantify over every compatible dependency assignment, +universe valuation, and satisfying context. The executable validator uses the +proved rules below to construct these propositions; they are never unchecked +witness fields supplied by its caller. +-/ + +namespace Ix.Theory.Model + +open SetTheory SetModel Certified + +universe u v +variable {β : Type u} + +/-- Membership together with the hereditary invariants for term and type. -/ +def TypingClaim (entries : Environment β) (Γ : Context β) (e A : AExpr β) : Prop := + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + Realizes constants entries → ∀ levels env, Γ.Valid constants levels env → + WellDenoted constants levels env e ∧ WellDenoted constants levels env A ∧ + interp constants levels env e ∈ˢ interp constants levels env A + +/-- Equality is a congruence on the total interpretation. Conversion does not +manufacture typing or hereditary validity of either endpoint. -/ +def ConversionClaim (entries : Environment β) (Γ : Context β) (a b : AExpr β) : Prop := + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + Realizes constants entries → ∀ levels env, Γ.Valid constants levels env → + interp constants levels env a = interp constants levels env b + +variable {entries : Environment β} {Γ : Context β} + +namespace TypingClaim + +theorem sort (l : VLevel) : TypingClaim.{u,v} entries Γ (.sort l) (.sort (.succ l)) := by + intro V _ constants _ levels env _ + exact ⟨trivial, trivial, univ_mem_univ _⟩ + +theorem bvar {i : Nat} {A : AExpr β} (h : Γ[i]? = some A) : + TypingClaim.{u,v} entries Γ (.bvar i) A := by + intro V _ constants _ levels env hΓ + exact ⟨trivial, hΓ i A h⟩ + +theorem const {r : ConstRef β} {entry : ConstantEntry β} {ls : List VLevel} + (h : entries r = some entry) (hn : ls.length = entry.universes) : + TypingClaim.{u,v} entries Γ (.const r ls) (entry.type.instL ls) := by + intro V _ constants hM levels env _ + have hlen : (ls.map (VLevel.eval levels)).length = entry.universes := by simpa using hn + refine ⟨trivial, (wellDenoted_instL ..).mpr (hM.typeValid r entry h _ hlen env), ?_⟩ + simpa only [interp, interp_instL] using hM.member r entry h _ hlen env + +theorem forallE {A B : AExpr β} {a b : VLevel} {p : PropWhen} + (hA : TypingClaim.{u,v} entries Γ A (.sort a)) + (hB : TypingClaim.{u,v} entries (Γ.push A) B (.sort b)) + (hp : p = zeroCondition b) : + TypingClaim.{u,v} entries Γ (.forallE p A B) (.sort (.imax a b)) := by + intro V _ constants hM levels env hΓ + obtain ⟨hAw, _, hAm⟩ := hA V constants hM levels env hΓ + have hBx x hx := hB V constants hM levels (Valuation.cons x env) (hΓ.push hAw hx) + have hz : regime p levels = 0 ↔ b.eval levels = 0 := by + rw [hp]; exact regime_zeroCondition .. + refine ⟨⟨hAw, fun x hx => (hBx x hx).1, + b.eval levels, hz, fun x hx => (hBx x hx).2.2⟩, trivial, ?_⟩ + exact annotated_pi_mem_univ hp hAm (fun x hx => (hBx x hx).2.2) + +theorem lam {A B body : AExpr β} {a b : VLevel} {p : PropWhen} + (hA : TypingClaim.{u,v} entries Γ A (.sort a)) + (hB : TypingClaim.{u,v} entries (Γ.push A) B (.sort b)) + (hbody : TypingClaim.{u,v} entries (Γ.push A) body B) + (hp : p = zeroCondition b) : + TypingClaim.{u,v} entries Γ (.lam p A body) (.forallE p A B) := by + intro V _ constants hM levels env hΓ + obtain ⟨hAw, _, _⟩ := hA V constants hM levels env hΓ + have hBx x hx := hB V constants hM levels (Valuation.cons x env) (hΓ.push hAw hx) + have hbodyx x hx := hbody V constants hM levels (Valuation.cons x env) (hΓ.push hAw hx) + have hz : regime p levels = 0 ↔ b.eval levels = 0 := by + rw [hp]; exact regime_zeroCondition .. + refine ⟨⟨hAw, fun x hx => (hbodyx x hx).1, b.eval levels, + (fun x => interp constants levels (Valuation.cons x env) B), hz, + fun x hx => ⟨(hbodyx x hx).2.2, (hBx x hx).2.2⟩⟩, ?_, ?_⟩ + · exact (forallE hA hB hp V constants hM levels env hΓ).1 + · exact lamR_mem (fun x hx => (hbodyx x hx).2.2) + +theorem app {f a A B : AExpr β} {p : PropWhen} + (hf : TypingClaim.{u,v} entries Γ f (.forallE p A B)) + (ha : TypingClaim.{u,v} entries Γ a A) : + TypingClaim.{u,v} entries Γ (.app f a) (B.inst a) := by + intro V _ constants hM levels env hΓ + obtain ⟨hfw, hpw, hfm⟩ := hf V constants hM levels env hΓ + obtain ⟨haw, _, ham⟩ := ha V constants hM levels env hΓ + obtain ⟨_, hBw, bv, hz, hBm⟩ := hpw + have hfm' : interp constants levels env f ∈ˢ + piR bv (interp constants levels env A) + (fun x => interp constants levels (Valuation.cons x env) B) := by + simpa only [interp, piR_zero_agree hz (fun _ _ => rfl)] using hfm + refine ⟨⟨hfw, haw, bv, interp constants levels env A, + (fun x => interp constants levels (Valuation.cons x env) B), hfm', ham, hBm⟩, + ?_, ?_⟩ + · apply wellDenoted_inst + · simpa using haw + · simpa using hBw _ ham + · simp only [interp_inst, Valuation.skip_zero, Valuation.insert_zero] + apply app_mem_piR hfm' ham + intro hzero x hx + simpa only [hzero, univ_zero] using hBm x hx + +theorem conv {e A B : AExpr β} {l : VLevel} + (he : TypingClaim.{u,v} entries Γ e A) + (hB : TypingClaim.{u,v} entries Γ B (.sort l)) + (hEq : ConversionClaim.{u,v} entries Γ A B) : + TypingClaim.{u,v} entries Γ e B := by + intro V _ constants hM levels env hΓ + obtain ⟨hew, _, hem⟩ := he V constants hM levels env hΓ + exact ⟨hew, (hB V constants hM levels env hΓ).1, + hEq V constants hM levels env hΓ ▸ hem⟩ + +/-- Closed typed facts come only from an admitted semantic producer. -/ +theorem fact {r : ConstRef β} {entry : ConstantEntry β} {e A : AExpr β} {ls : List VLevel} + (hr : entries r = some entry) (hf : .typed e A ∈ entry.facts) (hn : ls.length = entry.universes) : + TypingClaim.{u,v} entries Γ (e.instL ls) (A.instL ls) := by + intro V _ constants hM levels env _ + have hh := hM.factMeaning r entry hr (.typed e A) hf (ls.map (VLevel.eval levels)) + (by simpa using hn) env + simpa only [ConstantFact.Meaning, wellDenoted_instL, interp_instL] using hh + +theorem natLit {r zero succ : ConstRef β} {entry : ConstantEntry β} + (hr : entries r = some entry) (hf : .natural zero succ ∈ entry.facts) + (hn : entry.universes = 0) (value : Nat) : + TypingClaim.{u,v} entries Γ (.natLit value) (.const r []) := by + intro V _ constants hM _ env _ + have hh := hM.factMeaning r entry hr (.natural zero succ) hf [] (by simpa using hn.symm) env + exact ⟨trivial, trivial, hh.2.member value⟩ + +/-- A typed lambda application gives a typed result of beta reduction, +including the hereditary validity of that result. -/ +theorem betaResult {p : PropWhen} {D body arg B : AExpr β} + (hl : TypingClaim.{u,v} entries Γ (.lam p D body) (.forallE p D B)) + (ha : TypingClaim.{u,v} entries Γ arg D) : + TypingClaim.{u,v} entries Γ (body.inst arg) (B.inst arg) := by + intro V _ constants hM levels env hΓ + have hl' := hl V constants hM levels env hΓ + have ha' := ha V constants hM levels env hΓ + have happ := app hl ha V constants hM levels env hΓ + have hbeta := wellDenoted_beta hl'.1 ha'.1 ha'.2.2 + exact ⟨hbeta.1, happ.2.1, hbeta.2 ▸ happ.2.2⟩ + +end TypingClaim + +namespace ConversionClaim + +theorem natZero {r zero succ : ConstRef β} {entry : ConstantEntry β} + (hr : entries r = some entry) (hf : .natural zero succ ∈ entry.facts) (hn : entry.universes = 0) : + ConversionClaim.{u,v} entries Γ (.natLit 0) (.const zero []) := by + intro V _ constants hM _ env _ + have hh := hM.factMeaning r entry hr (.natural zero succ) hf [] (by simpa using hn.symm) env + exact hh.2.zeroValue.symm + +theorem natSucc {r zero succ : ConstRef β} {entry : ConstantEntry β} + (hr : entries r = some entry) (hf : .natural zero succ ∈ entry.facts) (hn : entry.universes = 0) (value : Nat) : + ConversionClaim.{u,v} entries Γ (.natLit (value + 1)) (.app (.const succ []) (.natLit value)) := by + intro V _ constants hM _ env _ + have hh := hM.factMeaning r entry hr (.natural zero succ) hf [] (by simpa using hn.symm) env + exact (hh.2.succValue value).symm + +theorem refl (e : AExpr β) : ConversionClaim.{u,v} entries Γ e e := by + intro V _ constants hM levels env hΓ + rfl + +theorem symm {a b : AExpr β} (h : ConversionClaim.{u,v} entries Γ a b) : + ConversionClaim.{u,v} entries Γ b a := by + intro V _ constants hM levels env hΓ + exact (h V constants hM levels env hΓ).symm + +theorem trans {a b c : AExpr β} (h : ConversionClaim.{u,v} entries Γ a b) + (h' : ConversionClaim.{u,v} entries Γ b c) : + ConversionClaim.{u,v} entries Γ a c := by + intro V _ constants hM levels env hΓ + exact (h V constants hM levels env hΓ).trans (h' V constants hM levels env hΓ) + +theorem app {f f' a a' : AExpr β} (hf : ConversionClaim.{u,v} entries Γ f f') + (ha : ConversionClaim.{u,v} entries Γ a a') : + ConversionClaim.{u,v} entries Γ (.app f a) (.app f' a') := by + intro V _ constants hM levels env hΓ + simp only [interp, hf V constants hM levels env hΓ, ha V constants hM levels env hΓ] + +theorem proj {r : ConstRef β} {i : Nat} {a b : AExpr β} + (h : ConversionClaim.{u,v} entries Γ a b) : + ConversionClaim.{u,v} entries Γ (.proj r i a) (.proj r i b) := by + intro V _ constants hM levels env hΓ + exact congrArg (projectValue i) (h V constants hM levels env hΓ) + +theorem lam {A A' b b' : AExpr β} {p : PropWhen} {l : VLevel} + (hA : TypingClaim.{u,v} entries Γ A (.sort l)) + (hdom : ConversionClaim.{u,v} entries Γ A A') + (hbody : ConversionClaim.{u,v} entries (Γ.push A) b b') : + ConversionClaim.{u,v} entries Γ (.lam p A b) (.lam p A' b') := by + intro V _ constants hM levels env hΓ + have hAw := (hA V constants hM levels env hΓ).1 + simp only [interp] + rw [← hdom V constants hM levels env hΓ] + apply lamR_congr + intro x hx + exact hbody V constants hM levels _ (hΓ.push hAw hx) + +theorem forallE {A A' B B' : AExpr β} {p : PropWhen} {l : VLevel} + (hA : TypingClaim.{u,v} entries Γ A (.sort l)) + (hdom : ConversionClaim.{u,v} entries Γ A A') + (hbody : ConversionClaim.{u,v} entries (Γ.push A) B B') : + ConversionClaim.{u,v} entries Γ (.forallE p A B) (.forallE p A' B') := by + intro V _ constants hM levels env hΓ + have hAw := (hA V constants hM levels env hΓ).1 + simp only [interp] + rw [← hdom V constants hM levels env hΓ] + apply piR_congr + intro x hx + exact hbody V constants hM levels _ (hΓ.push hAw hx) + +theorem beta {p : PropWhen} {A b a T : AExpr β} + (hl : TypingClaim.{u,v} entries Γ (.lam p A b) T) + (ha : TypingClaim.{u,v} entries Γ a A) : + ConversionClaim.{u,v} entries Γ (.app (.lam p A b) a) (b.inst a) := by + intro V _ constants hM levels env hΓ + have hl' := (hl V constants hM levels env hΓ).1 + obtain ⟨haw, _, ham⟩ := ha V constants hM levels env hΓ + exact (wellDenoted_beta hl' haw ham).2 + +theorem eta {p : PropWhen} {A B f : AExpr β} + (hf : TypingClaim.{u,v} entries Γ f (.forallE p A B)) : + ConversionClaim.{u,v} entries Γ (.lam p A (.app (f.liftN 1) (.bvar 0))) f := by + intro V _ constants hM levels env hΓ + have hfm := (hf V constants hM levels env hΓ).2.2 + simp only [interp, interp_liftN, Valuation.skip_one_cons, Valuation.cons_zero] + exact lamR_eta hfm + +theorem proofIrrel {A a b : AExpr β} + (hA : TypingClaim.{u,v} entries Γ A (.sort .zero)) + (ha : TypingClaim.{u,v} entries Γ a A) + (hb : TypingClaim.{u,v} entries Γ b A) : + ConversionClaim.{u,v} entries Γ a b := by + intro V _ constants hM levels env hΓ + have hAm := (hA V constants hM levels env hΓ).2.2 + have ham := (ha V constants hM levels env hΓ).2.2 + have hbm := (hb V constants hM levels env hΓ).2.2 + exact subsingleton_of_mem_univZero + (by simpa only [interp, VLevel.eval, univ_zero] using hAm) ham hbm + +theorem delta {r : ConstRef β} {entry : ConstantEntry β} {body : AExpr β} + {ls : List VLevel} (h : entries r = some entry) (hb : entry.body = some body) + (hn : ls.length = entry.universes) : + ConversionClaim.{u,v} entries Γ (.const r ls) (body.instL ls) := by + intro V _ constants hM levels env _ + have hlen : (ls.map (VLevel.eval levels)).length = entry.universes := by simpa using hn + simpa only [interp, interp_instL] using hM.bodyValue r entry h body hb _ hlen env + +theorem sort {l l' : VLevel} (h : ∀ values, l.eval values = l'.eval values) : + ConversionClaim.{u,v} entries Γ (.sort l) (.sort l') := by + intro V _ constants hM levels env hΓ + simp only [interp, h] + +/-- Only an equation of the selected admitted entry may be instantiated. +Typing of its applications remains a separate checker obligation. -/ +theorem equation {r : ConstRef β} {entry : ConstantEntry β} + {law : ConstantEquation β} {ls : List VLevel} + (h : entries r = some entry) (he : law ∈ entry.equations) + (hn : ls.length = entry.universes) : + ConversionClaim.{u,v} entries Γ (law.lhs.instL ls) (law.rhs.instL ls) := by + intro V _ constants hM levels env _ + have hlen : (ls.map (VLevel.eval levels)).length = entry.universes := by simpa using hn + simpa only [interp_instL] using hM.equationValue r entry h law he _ hlen env + +end ConversionClaim + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/PrimitiveValues.lean b/Ix/Theory/Model/PrimitiveValues.lean new file mode 100644 index 000000000..802f66b5f --- /dev/null +++ b/Ix/Theory/Model/PrimitiveValues.lean @@ -0,0 +1,38 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.SetModel.TaggedSum + +namespace Ix.Theory.Model + +open SetTheory SetTheory.Tower + +universe u +variable {V : Type u} [SetTheory V] + +/-- The ordinary container stores a tagged tuple as the first component of +its node. These total destructors also fix the proof point. Ownership and +field legality are obligations of the certified projection rule. -/ +noncomputable def projectValue (field : Nat) (value : V) : V := + projS field (ssnd (sfst value)) + +theorem projectValue_pt (field : Nat) : projectValue field (pt : V) = pt := by + simp only [projectValue, sfst_pt, ssnd_pt, projS_pt] + +theorem projectValue_node (field tag : Nat) (fields : List V) (branches : V) : + projectValue field (spair (inj tag (mkTower fields)) branches) = projS field (mkTower fields) := by + simp only [projectValue, sfst_spair, ssnd_inj] + +namespace Numeral + +noncomputable def zero : V := spair (inj 0 pt) empty +noncomputable def succ (n : V) : V := spair (inj 1 pt) (graph (fun _ => n) (sing (inj 0 pt))) +noncomputable def value : Nat → V + | 0 => zero + | n + 1 => succ (value n) + +end Numeral + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/ReferenceMap.lean b/Ix/Theory/Model/ReferenceMap.lean new file mode 100644 index 000000000..3e345d050 --- /dev/null +++ b/Ix/Theory/Model/ReferenceMap.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Support + +/-! Whole-reference substitution for independently checked model companions. +A constructor may map to a definition, so this operation is more general +than renaming a block address while retaining its member/constructor tag. -/ + +namespace Ix.Theory + +universe u v w x +variable {β : Type u} {γ : Type v} {δ : Type w} + +def VExpr.mapRefs (mapping : ConstRef β → ConstRef γ) : VExpr β → VExpr γ + | .bvar i => .bvar i + | .sort level => .sort level + | .const ref levels => .const (mapping ref) levels + | .app f a => .app (f.mapRefs mapping) (a.mapRefs mapping) + | .lam type body => .lam (type.mapRefs mapping) (body.mapRefs mapping) + | .forallE type body => .forallE (type.mapRefs mapping) (body.mapRefs mapping) + | .proj ref index major => .proj (mapping ref) index (major.mapRefs mapping) + | .natLit n => .natLit n + +namespace Model + +def AExpr.mapRefs (mapping : ConstRef β → ConstRef γ) : AExpr β → AExpr γ + | .bvar i => .bvar i + | .sort level => .sort level + | .const ref levels => .const (mapping ref) levels + | .app f a => .app (f.mapRefs mapping) (a.mapRefs mapping) + | .lam condition type body => .lam condition (type.mapRefs mapping) (body.mapRefs mapping) + | .forallE condition type body => .forallE condition (type.mapRefs mapping) (body.mapRefs mapping) + | .proj ref index major => .proj (mapping ref) index (major.mapRefs mapping) + | .natLit n => .natLit n + +@[simp] theorem AExpr.erase_mapRefs (e : AExpr β) (mapping : ConstRef β → ConstRef γ) : + (e.mapRefs mapping).erase = e.erase.mapRefs mapping := by + induction e <;> simp_all [AExpr.mapRefs, AExpr.erase, VExpr.mapRefs] + +@[simp] theorem AExpr.scope_mapRefs (e : AExpr β) (mapping : ConstRef β → ConstRef γ) (n k : Nat) : + (e.mapRefs mapping).Scope n k ↔ e.Scope n k := by + induction e generalizing k <;> simp_all [AExpr.mapRefs, AExpr.Scope] + +@[simp] theorem AExpr.references_mapRefs (e : AExpr β) (mapping : ConstRef β → ConstRef γ) : + (e.mapRefs mapping).references = e.references.map mapping := by + induction e <;> simp_all [AExpr.mapRefs, AExpr.references] + +@[simp] theorem AExpr.mapRefs_liftN (e : AExpr β) (mapping : ConstRef β → ConstRef γ) (n k : Nat) : + (e.liftN n k).mapRefs mapping = (e.mapRefs mapping).liftN n k := by + induction e generalizing k <;> simp_all [AExpr.mapRefs, AExpr.liftN] + +@[simp] theorem AExpr.mapRefs_inst (e a : AExpr β) (mapping : ConstRef β → ConstRef γ) (k : Nat) : + (e.inst a k).mapRefs mapping = (e.mapRefs mapping).inst (a.mapRefs mapping) k := by + induction e generalizing k with + | bvar i => + by_cases hi : i < k + · simp [AExpr.inst, AExpr.instVar, AExpr.mapRefs, hi] + · by_cases he : i = k <;> simp [AExpr.inst, AExpr.instVar, AExpr.mapRefs, hi, he] + | _ => simp_all [AExpr.inst, AExpr.mapRefs] + +@[simp] theorem AExpr.mapRefs_instL (e : AExpr β) (mapping : ConstRef β → ConstRef γ) (levels : List VLevel) : + (e.instL levels).mapRefs mapping = (e.mapRefs mapping).instL levels := by + induction e <;> simp_all [AExpr.instL, AExpr.mapRefs] + +@[simp] theorem AExpr.mapRefs_id (e : AExpr β) : e.mapRefs id = e := by + induction e <;> simp_all [AExpr.mapRefs] + +theorem AExpr.mapRefs_comp (e : AExpr β) (first : ConstRef β → ConstRef γ) (second : ConstRef γ → ConstRef δ) : + (e.mapRefs first).mapRefs second = e.mapRefs (second ∘ first) := by + induction e <;> simp_all [AExpr.mapRefs, Function.comp_def] + +theorem AExpr.mapRefs_congr (e : AExpr β) (first second : ConstRef β → ConstRef γ) + (h : ∀ ref ∈ e.references, first ref = second ref) : e.mapRefs first = e.mapRefs second := by + induction e with + | const ref levels => simp [AExpr.mapRefs, h ref (by simp [AExpr.references])] + | app f a hf ha | lam condition f a hf ha | forallE condition f a hf ha => + simp only [AExpr.mapRefs, + hf (fun ref hr => h ref (List.mem_append_left _ hr)), + ha (fun ref hr => h ref (List.mem_append_right _ hr))] + | proj ref index major ih => + simp only [AExpr.mapRefs, h ref (List.mem_cons_self), ih (fun ref hr => h ref (List.mem_cons_of_mem _ hr))] + | _ => rfl + +/-- Restoration needs an inverse only on the references actually used by +the restored expression. Unrelated auxiliaries are outside the premise. -/ +theorem AExpr.mapRefs_restore (e : AExpr β) (forward : ConstRef β → ConstRef γ) + (backward : ConstRef γ → ConstRef β) + (h : ∀ ref ∈ e.references, backward (forward ref) = ref) : + (e.mapRefs forward).mapRefs backward = e := by + rw [AExpr.mapRefs_comp, e.mapRefs_congr (backward ∘ forward) id h, AExpr.mapRefs_id] + +variable {V : Type x} [SetTheory V] + +theorem interp_mapRefs (e : AExpr β) (mapping : ConstRef β → ConstRef γ) + (constants : Assignment γ V) (levels : List Nat) (env : Nat → V) : + interp constants levels env (e.mapRefs mapping) = + interp (fun ref values => constants (mapping ref) values) levels env e := by + induction e generalizing env with + | lam condition type body ht hb | forallE condition type body ht hb => + simp only [AExpr.mapRefs, interp, ht] + congr 1 + funext value + exact hb _ + | _ => simp_all [AExpr.mapRefs, interp] + +theorem wellDenoted_mapRefs (e : AExpr β) (mapping : ConstRef β → ConstRef γ) + (constants : Assignment γ V) (levels : List Nat) (env : Nat → V) : + WellDenoted constants levels env (e.mapRefs mapping) ↔ + WellDenoted (fun ref values => constants (mapping ref) values) levels env e := by + induction e generalizing env with + | lam condition type body ht hb | forallE condition type body ht hb => + simp only [AExpr.mapRefs, WellDenoted, ht, hb, interp_mapRefs] + | _ => simp_all [AExpr.mapRefs, WellDenoted, interp_mapRefs] + +/-- A permutation changes addresses and pulls the assignment back through its +inverse. Only references actually used by the expression need an inverse. -/ +theorem interp_mapRefs_permutation (e : AExpr β) (forward : ConstRef β → ConstRef γ) + (backward : ConstRef γ → ConstRef β) (constants : Assignment β V) + (inverse : ∀ ref ∈ e.references, backward (forward ref) = ref) + (levels : List Nat) (env : Nat → V) : + interp (fun ref values => constants (backward ref) values) levels env (e.mapRefs forward) = + interp constants levels env e := by + rw [interp_mapRefs] + exact interp_congr_constants e _ constants + (fun ref hr values => congrArg (fun r => constants r values) (inverse ref hr)) levels env + +theorem wellDenoted_mapRefs_permutation (e : AExpr β) (forward : ConstRef β → ConstRef γ) + (backward : ConstRef γ → ConstRef β) (constants : Assignment β V) + (inverse : ∀ ref ∈ e.references, backward (forward ref) = ref) + (levels : List Nat) (env : Nat → V) : + WellDenoted (fun ref values => constants (backward ref) values) levels env (e.mapRefs forward) ↔ + WellDenoted constants levels env e := by + rw [wellDenoted_mapRefs] + exact wellDenoted_congr_constants e _ constants + (fun ref hr values => congrArg (fun r => constants r values) (inverse ref hr)) levels env + +/-- Restoring the retained reference support preserves the entire interpreted +expression, including binder annotations and both sides of a rule. -/ +theorem interp_mapRefs_restore (e : AExpr β) (forward : ConstRef β → ConstRef γ) + (backward : ConstRef γ → ConstRef β) (constants : Assignment β V) + (inverse : ∀ ref ∈ e.references, backward (forward ref) = ref) + (levels : List Nat) (env : Nat → V) : + interp constants levels env ((e.mapRefs forward).mapRefs backward) = interp constants levels env e := by + rw [e.mapRefs_restore forward backward inverse] + +/-- Equivalent model auxiliaries may share a representative. No injectivity +is needed: the checked consumer must establish agreement of their values. -/ +theorem interp_mapRefs_merge (e : AExpr β) (before : Assignment β V) (after : Assignment γ V) + (mapping : ConstRef β → ConstRef γ) + (agree : ∀ ref ∈ e.references, ∀ levels, before ref levels = after (mapping ref) levels) + (levels : List Nat) (env : Nat → V) : + interp before levels env e = interp after levels env (e.mapRefs mapping) := by + rw [interp_mapRefs] + exact interp_congr_constants e before _ agree levels env + +theorem wellDenoted_mapRefs_merge (e : AExpr β) (before : Assignment β V) (after : Assignment γ V) + (mapping : ConstRef β → ConstRef γ) + (agree : ∀ ref ∈ e.references, ∀ levels, before ref levels = after (mapping ref) levels) + (levels : List Nat) (env : Nat → V) : + WellDenoted before levels env e ↔ WellDenoted after levels env (e.mapRefs mapping) := by + rw [wellDenoted_mapRefs] + exact wellDenoted_congr_constants e before _ agree levels env + +end Model +end Ix.Theory diff --git a/Ix/Theory/Model/SetModel/Container.lean b/Ix/Theory/Model/SetModel/Container.lean new file mode 100644 index 000000000..de3a279a5 --- /dev/null +++ b/Ix/Theory/Model/SetModel/Container.lean @@ -0,0 +1,665 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetModel/Container.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetModel.RecGraph +public import Ix.Theory.Model.SetModel.Iter +public import Ix.Theory.Model.SetTheory.Derive.Choice + +@[expose] public section + +/-! +# The closure witness of a member container (task #202, Stage B) + +A recursive family with function-space slots (`WType`, `PSet`, …) is the +least fixed point of a functor whose fibres contain *functions* from +member domains into the family's own fibres. Its least pre-fixed point +(`lfpFamSet`) needs a CLOSED MEMBER family to be intersected from; for +finitary blocks that is the ω-iterate, for `Prop`-valued ones the top +family — with a function-space slot at `Sort w`, `w ≠ 0`, neither works +(the family's ranks are unbounded below the universe). + +This module exhibits the witness abstractly, for a functor `Φ` on +families over an index set `I` PRESENTED AS A CONTAINER: every element +of `Φ X` at `i` is `mk a g` for a shape `a ∈ A i` and a function `g` +from the shape's positions `B a` into the fibres of `X` at the targets +`tgt a p` (`helim`); shapes and position sets are members of `univ w`. +The witness is the family of DECODED TREE CODES: a code is a set of +labelled paths (a subset of a member `codeSpace t` built from the shapes +and positions reachable from `t`), decoding is the recursion theorem +(`RecGraph`) along the immediate-subcode relation on the accessible +codes, and the decoded family is closed because a constructor step on +decoded subcodes is the decoding of the assembled code (`mkCode`). +Membership comes from replacement (`image_mem`) alone — the fibres are +images of members — so no injection and no size argument beyond the +universe's own closure is needed. Everything here is over the bare +`SetTheory` interface; no syntax. + +The index set `I` need not be a member of any universe (an index type +may live above the family's sort): the reachable shapes are collected +by depth (`shapesN`) through the shapes and positions only, which ARE +members; no index is ever put inside a set. +-/ + +namespace Ix.Theory.Model.SetTheory + +open Ix.Theory.Model.SetTheory.Tower (natUnion mem_natUnion natUnion_mem_univ_pos) + +universe u + +variable {V : Type u} [SetTheory V] + +/-! ## Pair projections on `kpair` -/ + + +/-! ## The spaces reachable from an index -/ + +section Spaces + +variable (A B : V → V) (tgt : V → V → V) + +/-- The shapes reachable from `t` in exactly `n` steps. -/ +noncomputable def shapesN (t : V) : Nat → V + | 0 => A t + | n + 1 => sUnion (image (fun a => sUnion (image (fun p => A (tgt a p)) (B a))) (shapesN t n)) + +/-- The shapes reachable from `t`. -/ +noncomputable def shapes (t : V) : V := natUnion (shapesN A B tgt t) + +/-- The positions of the reachable shapes. -/ +noncomputable def positions (t : V) : V := sUnion (image B (shapes A B tgt t)) + +/-- Paths of length `n`: nested pairs of positions, the first step +outermost, `pt` the empty path. -/ +noncomputable def pathsN (t : V) : Nat → V + | 0 => unitSet + | n + 1 => sigmaPairs (positions A B tgt t) (fun _ => pathsN t n) + +/-- The paths from `t`. -/ +noncomputable def paths (t : V) : V := natUnion (pathsN A B tgt t) + +/-- The code space at `t`: the sets of labelled paths. -/ +noncomputable def codeSpace (t : V) : V := + power (sigmaPairs (paths A B tgt t) (fun _ => shapes A B tgt t)) + +variable {A B tgt} + +theorem mem_shapesN_succ {t x : V} {n : Nat} : + x ∈ˢ shapesN A B tgt t (n + 1) ↔ + ∃ a, a ∈ˢ shapesN A B tgt t n ∧ ∃ p, p ∈ˢ B a ∧ x ∈ˢ A (tgt a p) := by + show x ∈ˢ sUnion (image _ _) ↔ _ + rw [mem_sUnion] + constructor + · rintro ⟨y, hy, hxy⟩ + obtain ⟨a, ha, rfl⟩ := mem_image.mp hy + obtain ⟨z, hz, hxz⟩ := mem_sUnion.mp hxy + obtain ⟨p, hp, rfl⟩ := mem_image.mp hz + exact ⟨a, ha, p, hp, hxz⟩ + · rintro ⟨a, ha, p, hp, hx⟩ + exact ⟨_, mem_image.mpr ⟨a, ha, rfl⟩, mem_sUnion.mpr ⟨_, mem_image.mpr ⟨p, hp, rfl⟩, hx⟩⟩ + +theorem mem_shapes {t x : V} : x ∈ˢ shapes A B tgt t ↔ ∃ n, x ∈ˢ shapesN A B tgt t n := + mem_natUnion + +theorem mem_positions {t p : V} : + p ∈ˢ positions A B tgt t ↔ ∃ a, a ∈ˢ shapes A B tgt t ∧ p ∈ˢ B a := by + show p ∈ˢ sUnion (image B _) ↔ _ + rw [mem_sUnion] + constructor + · rintro ⟨y, hy, hpy⟩ + obtain ⟨a, ha, rfl⟩ := mem_image.mp hy + exact ⟨a, ha, hpy⟩ + · rintro ⟨a, ha, hp⟩ + exact ⟨B a, mem_image.mpr ⟨a, ha, rfl⟩, hp⟩ + +theorem mem_paths {t x : V} : x ∈ˢ paths A B tgt t ↔ ∃ n, x ∈ˢ pathsN A B tgt t n := + mem_natUnion + +theorem pt_mem_paths (t : V) : (pt : V) ∈ˢ paths A B tgt t := + mem_paths.mpr ⟨0, pt_mem_unitSet⟩ + +theorem mem_pathsN_succ {t x : V} {n : Nat} : + x ∈ˢ pathsN A B tgt t (n + 1) ↔ + ∃ p, p ∈ˢ positions A B tgt t ∧ ∃ q, q ∈ˢ pathsN A B tgt t n ∧ x = kpair p q := + mem_sigmaPairs + +/-- Paths are closed under consing a position. -/ +theorem kpair_mem_paths {t p q : V} (hp : p ∈ˢ positions A B tgt t) (hq : q ∈ˢ paths A B tgt t) : + kpair p q ∈ˢ paths A B tgt t := by + obtain ⟨n, hn⟩ := mem_paths.mp hq + exact mem_paths.mpr ⟨n + 1, mem_pathsN_succ.mpr ⟨p, hp, q, hn, rfl⟩⟩ + +/-- A path's tail is a path (and its head a position). -/ +theorem paths_uncons {t p q : V} (h : kpair p q ∈ˢ paths A B tgt t) : + p ∈ˢ positions A B tgt t ∧ q ∈ˢ paths A B tgt t := by + obtain ⟨n, hn⟩ := mem_paths.mp h + cases n with + | zero => + exact absurd (mem_unitSet_iff.mp hn).symm (pt_ne_kpair p q) + | succ n => + obtain ⟨p', hp', q', hq', heq⟩ := mem_pathsN_succ.mp hn + obtain ⟨rfl, rfl⟩ := kpair_inj heq + exact ⟨hp', mem_paths.mpr ⟨n, hq'⟩⟩ + +theorem mem_codeSpace {t S : V} : + S ∈ˢ codeSpace A B tgt t ↔ + ∀ x, x ∈ˢ S → ∃ q, q ∈ˢ paths A B tgt t ∧ ∃ a, a ∈ˢ shapes A B tgt t ∧ x = kpair q a := by + show S ∈ˢ power _ ↔ _ + rw [mem_power] + constructor + · intro h x hx + exact mem_sigmaPairs.mp (h x hx) + · intro h x hx + obtain ⟨q, hq, a, ha, rfl⟩ := h x hx + exact mem_sigmaPairs.mpr ⟨q, hq, a, ha, rfl⟩ + +/-! ### Membership in the universe -/ + +section Univ + +variable {w : Nat} (hw : w ≠ 0) {I : V} + (hA : ∀ i, i ∈ˢ I → A i ∈ˢ (univ w : V)) + (hB : ∀ i a, i ∈ˢ I → a ∈ˢ A i → B a ∈ˢ (univ w : V)) + (htgt : ∀ i a p, i ∈ˢ I → a ∈ˢ A i → p ∈ˢ B a → tgt a p ∈ˢ I) +include hw hA hB htgt + +omit hw hA hB in +/-- Every reachable shape is a shape at some index. -/ +theorem shapesN_sub {t : V} (ht : t ∈ˢ I) : + ∀ n a, a ∈ˢ shapesN A B tgt t n → ∃ i, i ∈ˢ I ∧ a ∈ˢ A i + | 0, a, ha => ⟨t, ht, ha⟩ + | n + 1, a, ha => by + obtain ⟨a', ha', p, hp, hx⟩ := mem_shapesN_succ.mp ha + obtain ⟨i, hi, hai⟩ := shapesN_sub ht n a' ha' + exact ⟨tgt a' p, htgt i a' p hi hai hp, hx⟩ + +theorem shapesN_mem {t : V} (ht : t ∈ˢ I) : ∀ n, shapesN A B tgt t n ∈ˢ (univ w : V) + | 0 => hA t ht + | n + 1 => by + have hU := univ_isTGUniverse (V := V) hw + show sUnion (image _ _) ∈ˢ _ + refine hU.famUnion_mem (shapesN_mem ht n) fun a ha => ?_ + obtain ⟨i, hi, hai⟩ := shapesN_sub htgt ht n a ha + refine hU.famUnion_mem (hB i a hi hai) fun p hp => ?_ + exact hA _ (htgt i a p hi hai hp) + +theorem shapes_mem {t : V} (ht : t ∈ˢ I) : shapes A B tgt t ∈ˢ (univ w : V) := + natUnion_mem_univ_pos hw (shapesN_mem hw hA hB htgt ht) + +omit hw hA hB in +theorem shapes_sub {t a : V} (ht : t ∈ˢ I) (ha : a ∈ˢ shapes A B tgt t) : + ∃ i, i ∈ˢ I ∧ a ∈ˢ A i := by + obtain ⟨n, hn⟩ := mem_shapes.mp ha + exact shapesN_sub htgt ht n a hn + +theorem positions_mem {t : V} (ht : t ∈ˢ I) : positions A B tgt t ∈ˢ (univ w : V) := by + have hU := univ_isTGUniverse (V := V) hw + refine hU.famUnion_mem (shapes_mem hw hA hB htgt ht) fun a ha => ?_ + obtain ⟨i, hi, hai⟩ := shapes_sub htgt ht ha + exact hB i a hi hai + +theorem pathsN_mem {t : V} (ht : t ∈ˢ I) : ∀ n, pathsN A B tgt t n ∈ˢ (univ w : V) + | 0 => unitSet_mem_univ w + | n + 1 => (univ_isTGUniverse hw).sigmaPairs_mem (positions_mem hw hA hB htgt ht) + fun _ _ => pathsN_mem ht n + +theorem paths_mem {t : V} (ht : t ∈ˢ I) : paths A B tgt t ∈ˢ (univ w : V) := + natUnion_mem_univ_pos hw (pathsN_mem hw hA hB htgt ht) + +theorem codeSpace_mem {t : V} (ht : t ∈ˢ I) : codeSpace A B tgt t ∈ˢ (univ w : V) := by + have hU := univ_isTGUniverse (V := V) hw + exact hU.power_mem (hU.sigmaPairs_mem (paths_mem hw hA hB htgt ht) + fun _ _ => shapes_mem hw hA hB htgt ht) + +end Univ + +/-! ### The spaces grow along a step -/ + +section Step + +variable {t a p : V} (ha : a ∈ˢ A t) (hp : p ∈ˢ B a) +include ha hp + +theorem shapesN_step_sub : ∀ n, shapesN A B tgt (tgt a p) n ⊆ˢ shapesN A B tgt t (n + 1) + | 0 => fun x hx => mem_shapesN_succ.mpr ⟨a, ha, p, hp, hx⟩ + | n + 1 => fun x hx => by + obtain ⟨a', ha', p', hp', hx'⟩ := mem_shapesN_succ.mp hx + exact mem_shapesN_succ.mpr ⟨a', shapesN_step_sub n a' ha', p', hp', hx'⟩ + +theorem shapes_step_sub : shapes A B tgt (tgt a p) ⊆ˢ shapes A B tgt t := by + intro x hx + obtain ⟨n, hn⟩ := mem_shapes.mp hx + exact mem_shapes.mpr ⟨n + 1, shapesN_step_sub ha hp n x hn⟩ + +theorem positions_step_sub : positions A B tgt (tgt a p) ⊆ˢ positions A B tgt t := by + intro x hx + obtain ⟨a', ha', hx'⟩ := mem_positions.mp hx + exact mem_positions.mpr ⟨a', shapes_step_sub ha hp a' ha', hx'⟩ + +theorem pathsN_step_sub : ∀ n, pathsN A B tgt (tgt a p) n ⊆ˢ pathsN A B tgt t n + | 0 => Subset.refl _ + | n + 1 => fun x hx => by + obtain ⟨p', hp', q, hq, rfl⟩ := mem_pathsN_succ.mp hx + exact mem_pathsN_succ.mpr ⟨p', positions_step_sub ha hp p' hp', q, pathsN_step_sub n q hq, rfl⟩ + +theorem paths_step_sub : paths A B tgt (tgt a p) ⊆ˢ paths A B tgt t := by + intro x hx + obtain ⟨n, hn⟩ := mem_paths.mp hx + exact mem_paths.mpr ⟨n, pathsN_step_sub ha hp n x hn⟩ + +/-- A position of a root shape is a position of the root's space. -/ +theorem mem_positions_of_root : p ∈ˢ positions A B tgt t := + mem_positions.mpr ⟨a, mem_shapes.mpr ⟨0, ha⟩, hp⟩ + +end Step + +end Spaces + +/-! ## Codes: the root label, the subcodes, the assembly -/ + +section Codes + +variable (B : V → V) + +/-- The labels at the empty path. -/ +noncomputable def rootLabels (S : V) : V := image ssnd (sep S fun pr => sfst pr = pt) + +/-- A code has a root: some label sits at the empty path. -/ +def HasRoot (S : V) : Prop := ∃ a, kpair pt a ∈ˢ S + +/-- The root label (a choice among the labels at the empty path). -/ +noncomputable def lab (S : V) : V := schoice (rootLabels S) + +/-- The subcode at position `p`: the labelled paths under `p`, the +first step stripped. -/ +noncomputable def subCode (S p : V) : V := + image (fun pr => kpair (ssnd (sfst pr)) (ssnd pr)) (sep S fun pr => ∃ q, sfst pr = kpair p q) + +/-- The code of a tree with root shape `a` and subcodes `app g p` at +the positions `p ∈ B a`: the root pair and every subcode's pairs with +the position prepended. -/ +noncomputable def mkCode (a g : V) : V := + binUnion (sing (kpair pt a)) + (sUnion (image (fun p => image (fun pr => kpair (kpair p (sfst pr)) (ssnd pr)) (app g p)) (B a))) + +variable {B} + +theorem mem_mkCode {a g x : V} : + x ∈ˢ mkCode B a g ↔ + x = kpair pt a ∨ ∃ p, p ∈ˢ B a ∧ ∃ pr, pr ∈ˢ app g p ∧ x = kpair (kpair p (sfst pr)) (ssnd pr) := by + unfold mkCode + rw [mem_binUnion, mem_sing, mem_sUnion] + refine or_congr Iff.rfl ⟨?_, ?_⟩ + · rintro ⟨y, hy, hxy⟩ + obtain ⟨p, hp, rfl⟩ := mem_image.mp hy + obtain ⟨pr, hpr, rfl⟩ := mem_image.mp hxy + exact ⟨p, hp, pr, hpr, rfl⟩ + · rintro ⟨p, hp, pr, hpr, rfl⟩ + exact ⟨_, mem_image.mpr ⟨p, hp, rfl⟩, mem_image.mpr ⟨pr, hpr, rfl⟩⟩ + +theorem mem_rootLabels {S x : V} : + x ∈ˢ rootLabels S ↔ ∃ pr, pr ∈ˢ S ∧ sfst pr = pt ∧ ssnd pr = x := by + unfold rootLabels + rw [mem_image] + constructor + · rintro ⟨pr, hpr, rfl⟩ + exact ⟨pr, (mem_sep.mp hpr).1, (mem_sep.mp hpr).2, rfl⟩ + · rintro ⟨pr, hpr, h1, rfl⟩ + exact ⟨pr, mem_sep.mpr ⟨hpr, h1⟩, rfl⟩ + +theorem hasRoot_mkCode (a g : V) : HasRoot (mkCode B a g) := + ⟨a, mem_mkCode.mpr (Or.inl rfl)⟩ + +theorem rootLabels_mkCode (a g : V) : rootLabels (mkCode B a g) = sing a := by + apply ext + intro x + rw [mem_rootLabels, mem_sing] + constructor + · rintro ⟨pr, hpr, h1, rfl⟩ + rcases mem_mkCode.mp hpr with rfl | ⟨p, -, pr', -, rfl⟩ + · exact ssnd_kpair _ _ + · rw [sfst_kpair] at h1 + exact absurd h1.symm (pt_ne_kpair _ _) + · rintro rfl + exact ⟨kpair pt x, mem_mkCode.mpr (Or.inl rfl), sfst_kpair _ _, ssnd_kpair _ _⟩ + +theorem lab_mkCode (a g : V) : lab (mkCode B a g) = a := by + unfold lab + rw [rootLabels_mkCode] + exact mem_sing.mp (schoice_mem (mem_sing.mpr rfl)) + +/-- The subcode of an assembled code at a position is the subcode put +there (the codes' elements being labelled paths). -/ +theorem subCode_mkCode {a g p : V} (hp : p ∈ˢ B a) + (hpairs : ∀ x, x ∈ˢ app g p → ∃ q b, x = kpair q b) : + subCode (mkCode B a g) p = app g p := by + apply ext + intro x + unfold subCode + rw [mem_image] + constructor + · rintro ⟨pr, hpr, rfl⟩ + obtain ⟨hmem, q, hq⟩ := mem_sep.mp hpr + rcases mem_mkCode.mp hmem with rfl | ⟨p', hp', pr', hpr', rfl⟩ + · rw [sfst_kpair] at hq + exact absurd hq (pt_ne_kpair _ _) + · rw [sfst_kpair] at hq + obtain ⟨rfl, rfl⟩ := kpair_inj hq + obtain ⟨q', b, rfl⟩ := hpairs pr' hpr' + simp only [sfst_kpair, ssnd_kpair] + exact hpr' + · intro hx + obtain ⟨q, b, rfl⟩ := hpairs x hx + refine ⟨kpair (kpair p q) b, mem_sep.mpr ⟨mem_mkCode.mpr (Or.inr ⟨p, hp, kpair q b, hx, ?_⟩), q, sfst_kpair _ _⟩, ?_⟩ + · rw [sfst_kpair, ssnd_kpair] + · rw [sfst_kpair, ssnd_kpair, ssnd_kpair] + +section InSpace + +variable {A : V → V} {tgt : V → V → V} + +theorem codeSpace_pairs {t S : V} (hS : S ∈ˢ codeSpace A B tgt t) : + ∀ x, x ∈ˢ S → ∃ q a, x = kpair q a := by + intro x hx + obtain ⟨q, -, a, -, rfl⟩ := mem_codeSpace.mp hS x hx + exact ⟨q, a, rfl⟩ + +/-- Subcodes stay in the code space. -/ +theorem subCode_mem_codeSpace {t S p : V} (hS : S ∈ˢ codeSpace A B tgt t) : + subCode S p ∈ˢ codeSpace A B tgt t := by + rw [mem_codeSpace] + intro x hx + unfold subCode at hx + obtain ⟨pr, hpr, rfl⟩ := mem_image.mp hx + obtain ⟨hmem, q, hq⟩ := mem_sep.mp hpr + obtain ⟨q', hq', a, ha, rfl⟩ := mem_codeSpace.mp hS pr hmem + rw [sfst_kpair] at hq + subst hq + rw [sfst_kpair, ssnd_kpair, ssnd_kpair] + exact ⟨q, (paths_uncons hq').2, a, ha, rfl⟩ + +/-- The assembled code of a root shape at `t` and subcodes at the +targets is in the code space at `t`. -/ +theorem mkCode_mem_codeSpace {t a g : V} (ha : a ∈ˢ A t) + (hg : ∀ p, p ∈ˢ B a → app g p ∈ˢ codeSpace A B tgt (tgt a p)) : + mkCode B a g ∈ˢ codeSpace A B tgt t := by + rw [mem_codeSpace] + intro x hx + rcases mem_mkCode.mp hx with rfl | ⟨p, hp, pr, hpr, rfl⟩ + · exact ⟨pt, pt_mem_paths t, a, mem_shapes.mpr ⟨0, ha⟩, rfl⟩ + · obtain ⟨q, hq, b, hb, rfl⟩ := mem_codeSpace.mp (hg p hp) pr hpr + rw [sfst_kpair, ssnd_kpair] + refine ⟨kpair p q, kpair_mem_paths (mem_positions_of_root ha hp) (paths_step_sub ha hp q hq), + b, shapes_step_sub ha hp b hb, rfl⟩ + +end InSpace + +end Codes + +/-! ## Decoding: the recursion theorem along the subcodes -/ + +section Decode + +variable (A B : V → V) (tgt : V → V → V) (I : V) (w : Nat) (mk : V → V → V) + +/-- All codes at all indices (a set; membership in a universe is not +needed for a recursion index set). -/ +noncomputable def allCodes : V := sUnion (image (codeSpace A B tgt) I) + +open Classical in +/-- The immediate subcodes of a code with a root. -/ +noncomputable def codePred (S : V) : V := + if HasRoot S then image (subCode S) (B (lab S)) else empty + +open Classical in +/-- The decoding step: the container's builder at the root label (a +shape at some index) and the decoded subcodes (the point off the +guard). -/ +noncomputable def codeStep (S g : V) : V := + if HasRoot S ∧ ∃ i, i ∈ˢ I ∧ lab S ∈ˢ A i then + mk (lab S) (graph (fun p => app g (subCode S p)) (B (lab S))) + else pt + +/-- The decoding graph: the recursion theorem's least fixed point at +level `w + 1`, bounded by `univ w`. -/ +noncomputable def decodeGraph : V := + recGraph (w + 1) (allCodes A B tgt I) (codePred B) (fun _ => univ w) (codeStep A B I mk) + +/-- The accessible codes. -/ +noncomputable def accCodes : V := accFam (allCodes A B tgt I) (codePred B) (fun _ => True) + +/-- The decoding: the selector of the decoding graph. -/ +noncomputable def decode (S : V) : V := recSel (decodeGraph A B tgt I w mk) S + +variable {A B tgt I w mk} + +theorem mem_allCodes {S : V} : S ∈ˢ allCodes A B tgt I ↔ ∃ t, t ∈ˢ I ∧ S ∈ˢ codeSpace A B tgt t := by + unfold allCodes + rw [mem_sUnion] + constructor + · rintro ⟨y, hy, hS⟩ + obtain ⟨t, ht, rfl⟩ := mem_image.mp hy + exact ⟨t, ht, hS⟩ + · rintro ⟨t, ht, hS⟩ + exact ⟨_, mem_image.mpr ⟨t, ht, rfl⟩, hS⟩ + +theorem codePred_of_root {S : V} (h : HasRoot S) : codePred B S = image (subCode S) (B (lab S)) := by + unfold codePred; exact if_pos h + +theorem codePred_of_not {S : V} (h : ¬ HasRoot S) : codePred B S = empty := by + unfold codePred; exact if_neg h + +theorem codePred_sub {S : V} (hS : S ∈ˢ allCodes A B tgt I) : codePred B S ⊆ˢ allCodes A B tgt I := by + intro x hx + by_cases h : HasRoot S + · rw [codePred_of_root h] at hx + obtain ⟨p, -, rfl⟩ := mem_image.mp hx + obtain ⟨t, ht, hSt⟩ := mem_allCodes.mp hS + exact mem_allCodes.mpr ⟨t, ht, subCode_mem_codeSpace hSt⟩ + · rw [codePred_of_not h] at hx + exact absurd hx (not_mem_empty x) + +/-- **Accessibility, unfolded**: a code is accessible iff its immediate +subcodes are. -/ +theorem accFam_iff {J : V} {pred : V → V} {Cond : V → Prop} (hpred : ∀ i, i ∈ˢ J → pred i ⊆ˢ J) + {i : V} (hi : i ∈ˢ J) : + (∃ y, y ∈ˢ app (accFam J pred Cond) i) ↔ + Cond i ∧ ∀ j, j ∈ˢ pred i → ∃ y, y ∈ˢ app (accFam J pred Cond) j := by + have h := app_lfpFamSet_eq (F := accStep J pred Cond) ⟨_, accStep_closed (pred := pred) (Cond := Cond)⟩ + (accStep_mono hpred) accStep_maps hi + unfold accFam + rw [← h, app_app_accStep (lfpFamSet_mem _ _ _) hi] + unfold accFibre + constructor + · rintro ⟨y, hy⟩ + exact (mem_truthVal.mp hy).1 + · intro hc + exact ⟨pt, mem_truthVal.mpr ⟨hc, rfl⟩⟩ + +theorem accCodes_iff {S : V} (hS : S ∈ˢ allCodes A B tgt I) : + (∃ y, y ∈ˢ app (accCodes A B tgt I) S) ↔ + ∀ S', S' ∈ˢ codePred B S → ∃ y, y ∈ˢ app (accCodes A B tgt I) S' := by + unfold accCodes + rw [accFam_iff (fun _ hS' => codePred_sub hS') hS] + exact ⟨fun h => h.2, fun h => ⟨trivial, h⟩⟩ + +section Facts + +variable {w : Nat} (hw : w ≠ 0) + (hB : ∀ i a, i ∈ˢ I → a ∈ˢ A i → B a ∈ˢ (univ w : V)) + (hmkU : ∀ i a g, i ∈ˢ I → a ∈ˢ A i → g ∈ˢ (univ w : V) → mk a g ∈ˢ (univ w : V)) +include hw hB hmkU + +omit hw hB hmkU in +theorem decodeGraph_hB : ∀ S, S ∈ˢ allCodes A B tgt I → (univ w : V) ∈ˢ (univ (w + 1) : V) := + fun _ _ => univ_mem_univ w + +/-- The step lands in the bound: the builder at members. -/ +theorem codeStep_mem {S g : V} (hS : S ∈ˢ allCodes A B tgt I) + (hg : g ∈ˢ piSet (codePred B S) fun j => app (decodeGraph A B tgt I w mk) j) : + codeStep A B I mk S g ∈ˢ (univ w : V) := by + have hU := univ_isTGUniverse (V := V) hw + unfold codeStep + split + · next h => + obtain ⟨hroot, i, hi, hlab⟩ := h + have hBl : B (lab S) ∈ˢ (univ w : V) := hB i _ hi hlab + refine hmkU i _ _ hi hlab ?_ + -- the graph of the decoded subcodes over the member position set + unfold graph + refine hU.image_mem hBl fun p hp => ?_ + refine hU.kpair_mem hBl (hU.transitive hBl hp) ?_ + -- the value: in the decoding graph's fibre, bounded by the universe + have hpred : subCode S p ∈ˢ codePred B S := by + rw [codePred_of_root hroot] + exact mem_image.mpr ⟨p, hp, rfl⟩ + have hv := app_mem_of_mem_piSet hg hpred + unfold decodeGraph at hv + rw [app_recGraph_eq decodeGraph_hB (fun _ hS' => codePred_sub hS') + (codePred_sub hS _ hpred)] at hv + exact (mem_recGraphFibre.mp hv).1 + · exact hU.pt_mem (empty_mem_univ w) + +theorem decodeGraph_hst : ∀ S, S ∈ˢ allCodes A B tgt I → + ∀ g, g ∈ˢ piSet (codePred B S) (fun j => app (decodeGraph A B tgt I w mk) j) → + codeStep A B I mk S g ∈ˢ (univ w : V) := + fun _ hS _ hg => codeStep_mem hw hB hmkU hS hg + +/-- **Accessible codes decode uniquely**: the decoding graph's fibre is +a singleton. -/ +theorem decode_unique {S : V} (hS : S ∈ˢ allCodes A B tgt I) + (hacc : ∃ y, y ∈ˢ app (accCodes A B tgt I) S) : + (∃ v, v ∈ˢ app (decodeGraph A B tgt I w mk) S) ∧ + ∀ v v', v ∈ˢ app (decodeGraph A B tgt I w mk) S → v' ∈ˢ app (decodeGraph A B tgt I w mk) S → + v = v' := + recGraph_exists_unique decodeGraph_hB (fun _ hS' => codePred_sub hS') + (decodeGraph_hst hw hB hmkU) S hS _ hacc.choose_spec + +/-- The decoding of an accessible code is a member. -/ +theorem decode_mem_univ {S : V} (hS : S ∈ˢ allCodes A B tgt I) + (hacc : ∃ y, y ∈ˢ app (accCodes A B tgt I) S) : + decode A B tgt I w mk S ∈ˢ (univ w : V) := by + have hv := recSel_mem (decode_unique hw hB hmkU hS hacc).1 + unfold decodeGraph at hv + rw [app_recGraph_eq decodeGraph_hB (fun _ hS' => codePred_sub hS') hS] at hv + exact (mem_recGraphFibre.mp hv).1 + +/-- **The decoding equation** at an accessible code with a root: the +builder at the root label and the decoded subcodes. -/ +theorem decode_eq {S : V} (hS : S ∈ˢ allCodes A B tgt I) + (hacc : ∃ y, y ∈ˢ app (accCodes A B tgt I) S) (hroot : HasRoot S) + (hlab : ∃ i, i ∈ˢ I ∧ lab S ∈ˢ A i) : + decode A B tgt I w mk S + = mk (lab S) (graph (fun p => decode A B tgt I w mk (subCode S p)) (B (lab S))) := by + have hP : ∀ j, j ∈ˢ codePred B S → + (∃ v, v ∈ˢ app (decodeGraph A B tgt I w mk) j) ∧ + ∀ v v', v ∈ˢ app (decodeGraph A B tgt I w mk) j → v' ∈ˢ app (decodeGraph A B tgt I w mk) j → + v = v' := + fun j hj => decode_unique hw hB hmkU (codePred_sub hS j hj) ((accCodes_iff hS).mp hacc j hj) + have heq := recSel_eq decodeGraph_hB (fun _ hS' => codePred_sub hS') hS + (decode_unique hw hB hmkU hS hacc).1 hP + unfold decode + unfold decodeGraph at heq ⊢ + rw [heq] + unfold codeStep + rw [if_pos ⟨hroot, hlab⟩] + congr 1 + refine graph_congr fun p hp => ?_ + rw [app_graph (show subCode S p ∈ˢ codePred B S from by + rw [codePred_of_root hroot]; exact mem_image.mpr ⟨p, hp, rfl⟩)] + +omit hw hB hmkU in +/-- An assembled code of accessible subcodes is accessible. -/ +theorem acc_mkCode {t a g : V} (ht : t ∈ˢ I) (ha : a ∈ˢ A t) + (hg : ∀ p, p ∈ˢ B a → app g p ∈ˢ codeSpace A B tgt (tgt a p)) + (hacc : ∀ p, p ∈ˢ B a → ∃ y, y ∈ˢ app (accCodes A B tgt I) (app g p)) : + ∃ y, y ∈ˢ app (accCodes A B tgt I) (mkCode B a g) := by + have hS : mkCode B a g ∈ˢ allCodes A B tgt I := + mem_allCodes.mpr ⟨t, ht, mkCode_mem_codeSpace ha hg⟩ + rw [accCodes_iff hS] + intro S' hS' + rw [codePred_of_root (hasRoot_mkCode a g), lab_mkCode] at hS' + obtain ⟨p, hp, rfl⟩ := mem_image.mp hS' + rw [subCode_mkCode hp (codeSpace_pairs (hg p hp))] + exact hacc p hp + +end Facts + +end Decode + +/-! ## The closure witness -/ + +/-- **A member container has a closed member family**: the family of +the decoded accessible codes. The functor `Φ` on families over `I` is +presented as a container by `helim` — every element of `Φ X` at `i` is +`mk a g` for a shape `a ∈ A i` and a function `g` from the positions +`B a` into the fibres of `X` at the targets `tgt a p`; shapes and +position sets are members of `univ w`, the builder keeps members. The +decoded family's fibres are images of members (replacement), and a +constructor step on decoded subcodes decodes the assembled code. -/ +theorem container_closed_exists {w : Nat} (hw : w ≠ 0) {I : V} (Φ : V → V) + (A B : V → V) (tgt : V → V → V) (mk : V → V → V) + (hA : ∀ i, i ∈ˢ I → A i ∈ˢ (univ w : V)) + (hB : ∀ i a, i ∈ˢ I → a ∈ˢ A i → B a ∈ˢ (univ w : V)) + (htgt : ∀ i a p, i ∈ˢ I → a ∈ˢ A i → p ∈ˢ B a → tgt a p ∈ˢ I) + (hmkU : ∀ i a g, i ∈ˢ I → a ∈ˢ A i → g ∈ˢ (univ w : V) → mk a g ∈ˢ (univ w : V)) + (helim : ∀ X, X ∈ˢ famSpace w I → ∀ i, i ∈ˢ I → ∀ x, x ∈ˢ app (Φ X) i → + ∃ a, a ∈ˢ A i ∧ ∃ g, g ∈ˢ piSet (B a) (fun p => app X (tgt a p)) ∧ x = mk a g) : + ∃ L, L ∈ˢ famSpace w I ∧ FamLe I (Φ L) L := by + have hU := univ_isTGUniverse (V := V) hw + let Lf : V → V := fun i => image (decode A B tgt I w mk) + (sep (codeSpace A B tgt i) fun S => + (∃ y, y ∈ˢ app (accCodes A B tgt I) S) ∧ HasRoot S ∧ lab S ∈ˢ A i) + have hLmem : graph Lf I ∈ˢ famSpace w I := by + refine graph_mem_famSpace fun i hi => ?_ + refine hU.image_mem (hU.sep_mem (codeSpace_mem hw hA hB htgt hi)) fun S hS => ?_ + obtain ⟨hSi, hacc, -, -⟩ := mem_sep.mp hS + exact decode_mem_univ hw hB hmkU (mem_allCodes.mpr ⟨i, hi, hSi⟩) hacc + refine ⟨graph Lf I, hLmem, ?_⟩ + intro i hi x hx + obtain ⟨a, ha, g, hg, rfl⟩ := helim _ hLmem i hi x hx + -- every subtree is the decoding of an accessible code at its target + have hsub : ∀ p, p ∈ˢ B a → ∃ S, S ∈ˢ codeSpace A B tgt (tgt a p) ∧ + (∃ y, y ∈ˢ app (accCodes A B tgt I) S) ∧ HasRoot S ∧ lab S ∈ˢ A (tgt a p) ∧ + decode A B tgt I w mk S = app g p := by + intro p hp + have hgp := app_mem_of_mem_piSet hg hp + rw [app_graph (htgt i a p hi ha hp)] at hgp + obtain ⟨S, hS, hdec⟩ := mem_image.mp hgp + obtain ⟨hSi, hacc, hroot, hlab⟩ := mem_sep.mp hS + exact ⟨S, hSi, hacc, hroot, hlab, hdec.symm⟩ + classical + let cs : V → V := fun p => if h : p ∈ˢ B a then Classical.choose (hsub p h) else empty + have hcs : ∀ p, p ∈ˢ B a → cs p ∈ˢ codeSpace A B tgt (tgt a p) ∧ + (∃ y, y ∈ˢ app (accCodes A B tgt I) (cs p)) ∧ HasRoot (cs p) ∧ lab (cs p) ∈ˢ A (tgt a p) ∧ + decode A B tgt I w mk (cs p) = app g p := by + intro p hp + have hcp : cs p = Classical.choose (hsub p hp) := by + show (if h : p ∈ˢ B a then Classical.choose (hsub p h) else empty) = _ + rw [dif_pos hp] + rw [hcp] + exact Classical.choose_spec (hsub p hp) + have hgS : ∀ p, p ∈ˢ B a → app (graph cs (B a)) p = cs p := fun p hp => app_graph hp + have hSmem : mkCode B a (graph cs (B a)) ∈ˢ codeSpace A B tgt i := + mkCode_mem_codeSpace ha fun p hp => by rw [hgS p hp]; exact (hcs p hp).1 + have hSacc : ∃ y, y ∈ˢ app (accCodes A B tgt I) (mkCode B a (graph cs (B a))) := + acc_mkCode hi ha (fun p hp => by rw [hgS p hp]; exact (hcs p hp).1) + (fun p hp => by rw [hgS p hp]; exact (hcs p hp).2.1) + rw [app_graph hi] + refine mem_image.mpr ⟨mkCode B a (graph cs (B a)), + mem_sep.mpr ⟨hSmem, hSacc, hasRoot_mkCode a _, by rw [lab_mkCode]; exact ha⟩, ?_⟩ + rw [decode_eq hw hB hmkU (mem_allCodes.mpr ⟨i, hi, hSmem⟩) hSacc (hasRoot_mkCode a _) + ⟨i, hi, by rw [lab_mkCode]; exact ha⟩, lab_mkCode] + congr 1 + refine (eq_graph_app_of_mem_piSet hg).symm.trans (graph_congr fun p hp => ?_) + rw [subCode_mkCode hp (fun x hx => codeSpace_pairs (hcs p hp).1 x (by rwa [hgS p hp] at hx)), + hgS p hp] + exact ((hcs p hp).2.2.2.2).symm + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetModel/Iter.lean b/Ix/Theory/Model/SetModel/Iter.lean new file mode 100644 index 000000000..ac009bc78 --- /dev/null +++ b/Ix/Theory/Model/SetModel/Iter.lean @@ -0,0 +1,107 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetModel/Iter.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetModel.TaggedSum + +@[expose] public section + +/-! +# The ω-iterate of a set functor (task #188) + +The one place iteration survives in the recursive-type model: the +carrier is the Knaster–Tarski least pre-fixed point +(`Ix.Theory/Model/SetTheory/Derive/Lfp.lean`), and every law about it assumes a +CLOSED MEMBER of the universe exists. For a *finitary* tower functor +that witness is the ω-iterate + + iterF Φ 0 = ∅, iterF Φ (n+1) = Φ (iterF Φ n), iterU Φ = ⋃ₙ iterF Φ n + +— a countable union of members of `univ w`, hence a member (`ω ∈ univ +w` at `w ≥ 1`, `omega_mem_univ_succ`; at `w = 0` truth values), and +closed under `Φ` whenever every member of `Φ (iterU Φ)` already lies in +some `Φ (iterF Φ n)` (`iterU_closed_of` — the finitary condition, +discharged for the tower functor in `Ix.Theory/Model/Semantics/Tower/FixLeaf.lean` +by bounding the ranks of a tuple's finitely many recursive fields). +The union is also where the recursor's semantic fixed point is built +by rank recursion. + +Everything here is over the bare `SetTheory` interface; no syntax. +-/ + +namespace Ix.Theory.Model.SetTheory.Tower + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The finite iterates of a set functor from the empty set. -/ +noncomputable def iterF (Φ : V → V) : Nat → V + | 0 => empty + | n + 1 => Φ (iterF Φ n) + +@[simp] theorem iterF_zero (Φ : V → V) : iterF Φ 0 = empty := rfl +@[simp] theorem iterF_succ (Φ : V → V) (n : Nat) : iterF Φ (n + 1) = Φ (iterF Φ n) := rfl + +/-- The union of a countable family `f 0 ∪ f 1 ∪ …` (the ω-indexed union +through the tag fibre). -/ +noncomputable def natUnion (f : Nat → V) : V := + sUnion (image (natFibre f) omega) + +theorem mem_natUnion {f : Nat → V} {x : V} : x ∈ˢ natUnion f ↔ ∃ n, x ∈ˢ f n := by + unfold natUnion + rw [mem_sUnion] + constructor + · rintro ⟨y, hy, hxy⟩ + obtain ⟨k, hk, rfl⟩ := mem_image.mp hy + obtain ⟨n, rfl, hfib⟩ := natFibre_of_mem f hk + rw [hfib] at hxy + exact ⟨n, hxy⟩ + · rintro ⟨n, hn⟩ + exact ⟨natFibre f (vnat n), mem_image.mpr ⟨vnat n, vnat_mem_omega n, rfl⟩, + by rw [natFibre_vnat]; exact hn⟩ + +/-- **Formation** (graph regime): a countable union of members of a +positive level is a member. -/ +theorem natUnion_mem_univ_pos {w : Nat} (hw : w ≠ 0) {f : Nat → V} + (h : ∀ n, f n ∈ˢ (univ w : V)) : natUnion f ∈ˢ (univ w : V) := by + obtain ⟨w', rfl⟩ : ∃ w', w = w' + 1 := ⟨w - 1, by omega⟩ + unfold natUnion + refine (univ_isTGUniverse (Nat.succ_ne_zero w')).famUnion_mem (omega_mem_univ_succ w') ?_ + intro k hk + obtain ⟨n, rfl, hfib⟩ := natFibre_of_mem f hk + rw [hfib] + exact h n + +/-- **Formation** (squash regime): a union of truth values is a truth +value. -/ +theorem natUnion_mem_univZero {f : Nat → V} (h : ∀ n, f n ∈ˢ (univZero : V)) : + natUnion f ∈ˢ (univZero : V) := by + rw [mem_univZero] + intro x hx + obtain ⟨n, hn⟩ := mem_natUnion.mp hx + exact (mem_univZero.mp (h n)) x hn + +/-- The ω-iterate: the union of the finite iterates. -/ +noncomputable def iterU (Φ : V → V) : V := natUnion (iterF Φ) + +theorem mem_iterU {Φ : V → V} {x : V} : x ∈ˢ iterU Φ ↔ ∃ n, x ∈ˢ iterF Φ n := + mem_natUnion + +/-- **Closure** under a finitary functor: if every member of +`Φ (iterU Φ)` lies in some finite stage's image, the ω-iterate is +closed. -/ +theorem iterU_closed_of {Φ : V → V} + (hfin : ∀ x, x ∈ˢ Φ (iterU Φ) → ∃ n, x ∈ˢ Φ (iterF Φ n)) : + Φ (iterU Φ) ⊆ˢ iterU Φ := by + intro x hx + obtain ⟨n, hn⟩ := hfin x hx + exact mem_iterU.mpr ⟨n + 1, hn⟩ + +end Ix.Theory.Model.SetTheory.Tower diff --git a/Ix/Theory/Model/SetModel/Ops.lean b/Ix/Theory/Model/SetModel/Ops.lean new file mode 100644 index 000000000..23d5d2b8a --- /dev/null +++ b/Ix/Theory/Model/SetModel/Ops.lean @@ -0,0 +1,366 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetModel/Ops.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Univ + +@[expose] public section + +/-! +# The two-regime product and abstraction (task #151, tier B) + +`piR`/`lamR` are the **annotation-driven** dependent product and +abstraction: they read a numeral — the codomain sort of the binder, +supplied by the annotation pass — and dispatch on it, rather than +inspecting the semantic value the way the domain-relative collapse +(`pcol`/`piC`/`lamC`, `Ix.Theory/Model/SetTheory/Derive/Pi.lean` — deleted at +task #221, unread since these operators replaced it) does. + +* **`v = 0` — the truth-value (squash) regime.** `piR 0 A B` is the + truth value `[∀ x ∈ A, B x inhabited]`, `lamR 0 A F` is the canonical + proof. Propositions are subsets of the canonical one-element set + `unitSet = {pt}`, so proof irrelevance and impredicativity are both + immediate: *a product landing in `Prop` is small whatever its domain + is* (`piR_zero_mem_univZero`), with no size or universe side + condition anywhere. +* **`v ≠ 0` — the graph regime.** `piR v A B` is `piSet A B`, the set + of total single-valued function graphs over `A`; `lamR v A F` is the + literal graph. **No collapse, no proof point**: a member of a + positive-regime product is a graph, is never `pt` + (`not_pt_mem_piR_pos`), determines its own domain + (`piR_dom_unique`, with *no* `≠ pt` side condition), and applies to + the canonical junk `∅` off that domain (`app_off_dom_piR_pos`). + +The operators are the pre-#100 `SetTheory.pi`/`SetTheory.lam` (see the +git history of `Derive/Pi.lean`), restated in this namespace so that +`Ix.Theory/Model/SetTheory/*` is untouched; the law battery below is that file's, +plus the *inversion* laws that only the annotation-driven definition can +have (`mem_piR_pos`, `piR_dom_unique`, `not_pt_mem_piR_pos`). + +**On `pt`.** The proof point appears in exactly one place: the `v = 0` +branch of `lamR`, as the canonical inhabitant of a true proposition. +That is forced — `SetTheory`'s `univ 0 = power unitSet` fixes the +canonical one-element set, so the unique element of a true truth value +*is* `pt` — and it is not a collapse: no clause here tests a value, and +the graph regime never produces, contains, or consults it. So `pt` is +*demoted, not deleted*: deleting it is not achievable — it would mean +re-deriving `univZero` over a different singleton, and renaming the +canonical point changes nothing — and not needed, because nothing here +tests for it. +-/ + +namespace Ix.Theory.Model.SetModel + +open SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The dependent product at codomain sort `v`: a truth value at `0`, +the set of function graphs above it. -/ +noncomputable def piR (v : Nat) (A : V) (B : V → V) : V := + if v = 0 then truthVal (∀ x, x ∈ˢ A → ∃ y, y ∈ˢ B x) else piSet A B + +/-- Abstraction at codomain sort `v`: the canonical proof at `0`, the +literal function graph above it. -/ +noncomputable def lamR (v : Nat) (A : V) (F : V → V) : V := + if v = 0 then pt else graph F A + +/-! ## The two branches -/ + +theorem piR_zero {A : V} {B : V → V} : + piR 0 A B = truthVal (∀ x, x ∈ˢ A → ∃ y, y ∈ˢ B x) := if_pos rfl + +theorem piR_pos {v : Nat} (hv : v ≠ 0) {A : V} {B : V → V} : + piR v A B = piSet A B := if_neg hv + +theorem lamR_zero {A : V} {F : V → V} : lamR 0 A F = (pt : V) := if_pos rfl + +theorem lamR_pos {v : Nat} (hv : v ≠ 0) {A : V} {F : V → V} : + lamR v A F = graph F A := if_neg hv + +/-! ## Congruence -/ + +theorem piR_congr {v : Nat} {A : V} {B B' : V → V} + (h : ∀ x, x ∈ˢ A → B x = B' x) : piR v A B = piR v A B' := by + rcases Nat.eq_zero_or_pos v with rfl | hv + · rw [piR_zero, piR_zero] + exact truthVal_congr + ⟨fun hi x hx => h x hx ▸ hi x hx, fun hi x hx => (h x hx).symm ▸ hi x hx⟩ + · rw [piR_pos (Nat.pos_iff_ne_zero.mp hv), piR_pos (Nat.pos_iff_ne_zero.mp hv)] + exact piSet_congr h + +theorem lamR_congr {v : Nat} {A : V} {F F' : V → V} + (h : ∀ x, x ∈ˢ A → F x = F' x) : lamR v A F = lamR v A F' := by + rcases Nat.eq_zero_or_pos v with rfl | hv + · rw [lamR_zero, lamR_zero] + · rw [lamR_pos (Nat.pos_iff_ne_zero.mp hv), lamR_pos (Nat.pos_iff_ne_zero.mp hv)] + exact graph_congr h + +/-! ## Zero-agreement + +`piR`/`lamR` read their numeral **only through the `v = 0` test**, so +annotations that agree on zero-ness are interchangeable. This is the +pre-#100 `pi_congr_zero_agree`/`lam_congr_zero_agree` pair, and it is +what lets a λ-tower carry its *result* sort at every binder rather than +the exact `imax` fold: in `(a₁ : A₁) → … → (aₙ : Aₙ) → T` the sort of +each suffix is `imax (…) r` with `r` the sort of `T`, and +`imax x y = 0 ↔ y = 0`. See `Interp/Value.lean`'s annotation +convention. -/ + +theorem piR_zero_agree {v v' : Nat} (hz : v = 0 ↔ v' = 0) {A : V} + {B B' : V → V} (h : ∀ x, x ∈ˢ A → B x = B' x) : piR v A B = piR v' A B' := by + by_cases hv : v = 0 + · rw [hv, hz.mp hv]; exact piR_congr h + · have hv' : v' ≠ 0 := fun h0 => hv (hz.mpr h0) + rw [piR_pos hv, piR_pos hv'] + exact piSet_congr h + +theorem lamR_zero_agree {v v' : Nat} (hz : v = 0 ↔ v' = 0) {A : V} + {F F' : V → V} (h : ∀ x, x ∈ˢ A → F x = F' x) : lamR v A F = lamR v' A F' := by + by_cases hv : v = 0 + · rw [hv, hz.mp hv, lamR_zero, lamR_zero] + · have hv' : v' ≠ 0 := fun h0 => hv (hz.mpr h0) + rw [lamR_pos hv, lamR_pos hv'] + exact graph_congr h + +/-- `imax`'s zero test is its codomain's — the arithmetic behind the +tower convention. -/ +theorem imax_eq_zero_iff (x y : Nat) : + (if y = 0 then 0 else Nat.max x y) = 0 ↔ y = 0 := by + by_cases hy : y = 0 + · simp [hy] + · rw [if_neg hy] + exact ⟨fun h => absurd (Nat.le_zero.mp (h ▸ Nat.le_max_right x y)) hy, + fun h => absurd h hy⟩ + +/-! ## Introduction, elimination, beta, eta -/ + +/-- Introduction: fibre-wise members abstract into the product. At +`v = 0` the premise itself witnesses every fibre inhabited. -/ +theorem lamR_mem {v : Nat} {A : V} {F B : V → V} + (hF : ∀ x, x ∈ˢ A → F x ∈ˢ B x) : lamR v A F ∈ˢ piR v A B := by + rcases Nat.eq_zero_or_pos v with rfl | hv + · rw [lamR_zero, piR_zero] + exact pt_mem_truthVal fun x hx => ⟨F x, hF x hx⟩ + · rw [lamR_pos (Nat.pos_iff_ne_zero.mp hv), piR_pos (Nat.pos_iff_ne_zero.mp hv)] + exact graph_mem_piSet hF + +/-- Introduction across zero-agreeing annotations: a tower annotated +with its result sort still inhabits the product annotated with the +exact `imax`. -/ +theorem lamR_mem_zero_agree {v v' : Nat} (hz : v = 0 ↔ v' = 0) {A : V} + {F B : V → V} (hF : ∀ x, x ∈ˢ A → F x ∈ˢ B x) : lamR v A F ∈ˢ piR v' A B := by + rw [lamR_zero_agree hz (fun _ _ => rfl) (F' := F)] + exact lamR_mem hF + +/-- **Proof irrelevance at products**: inhabitants of a `Prop`-valued +product are the canonical proof. -/ +theorem eq_pt_of_mem_piR_zero {A f : V} {B : V → V} (hf : f ∈ˢ piR 0 A B) : + f = pt := by + rw [piR_zero] at hf; exact eq_pt_of_mem_truthVal hf + +/-- **Squash-regime introduction from inhabitation.** At `v = 0` the +product is a truth value, so membership of the canonical proof needs +only that every fibre is *inhabited* — strictly weaker than +`lamR_mem`'s pointwise `F x ∈ˢ B x`, and the form every tower whose +value carries no regime tag has to use at kind `0` +(`Interp/BasisOk.lean`, the `psigmaMk` finding). -/ +theorem pt_mem_piR_zero {A : V} {B : V → V} + (h : ∀ x, x ∈ˢ A → ∃ y, y ∈ˢ B x) : (pt : V) ∈ˢ piR 0 A B := by + rw [piR_zero]; exact pt_mem_truthVal h + +/-- The pointwise form, matching the collapse lane's +`pt_mem_piC_iff.mpr` so the `pt`-valued towers port line for line. -/ +theorem pt_mem_piR_zero_of {A : V} {B : V → V} + (h : ∀ x, x ∈ˢ A → (pt : V) ∈ˢ B x) : (pt : V) ∈ˢ piR 0 A B := + pt_mem_piR_zero fun x hx => ⟨pt, h x hx⟩ + +/-- Elimination. The fibre premise is needed only at `v = 0`, where +the fibres must be truth values. -/ +theorem app_mem_piR {v : Nat} {A f a : V} {B : V → V} + (hf : f ∈ˢ piR v A B) (ha : a ∈ˢ A) + (hB0 : v = 0 → ∀ x, x ∈ˢ A → B x ∈ˢ (univZero : V)) : app f a ∈ˢ B a := by + rcases Nat.eq_zero_or_pos v with rfl | hv + · have hfp : f = pt := eq_pt_of_mem_piR_zero hf + rw [piR_zero] at hf + obtain ⟨y, hy⟩ := of_mem_truthVal hf a ha + rw [hfp, app_pt] + rwa [eq_pt_of_mem_univZero (hB0 rfl a ha) hy] at hy + · rw [piR_pos (Nat.pos_iff_ne_zero.mp hv)] at hf + exact app_mem_of_mem_piSet hf ha + +/-- Elimination in the graph regime: no fibre premise at all. -/ +theorem app_mem_piR_pos {v : Nat} {A f a : V} {B : V → V} (hv : v ≠ 0) + (hf : f ∈ˢ piR v A B) (ha : a ∈ˢ A) : app f a ∈ˢ B a := by + rw [piR_pos hv] at hf; exact app_mem_of_mem_piSet hf ha + +/-- Beta, conditional on domain membership (set-theoretic functions +have set domains). -/ +theorem app_lamR {v : Nat} {A a : V} {F B : V → V} + (ha : a ∈ˢ A) (hF : ∀ x, x ∈ˢ A → F x ∈ˢ B x) + (hB0 : v = 0 → ∀ x, x ∈ˢ A → B x ∈ˢ (univZero : V)) : + app (lamR v A F) a = F a := by + rcases Nat.eq_zero_or_pos v with rfl | hv + · rw [lamR_zero, app_pt] + exact (eq_pt_of_mem_univZero (hB0 rfl a ha) (hF a ha)).symm + · rw [lamR_pos (Nat.pos_iff_ne_zero.mp hv)] + exact app_graph ha + +/-- **Beta in the graph regime**: application of an abstraction on its +domain computes, with no typing premise whatsoever — it is literally +`app_graph`. -/ +theorem app_lamR_pos {v : Nat} {A a : V} {F : V → V} (hv : v ≠ 0) + (ha : a ∈ˢ A) : app (lamR v A F) a = F a := by + rw [lamR_pos hv]; exact app_graph ha + +/-- **Off-domain application in the graph regime** — `app_lamR_pos`'s +complement. The rigidity a *type former*'s application is inverted +with: off its domain a graph-regime abstraction applies to the +canonical junk `∅`, which has no members, so an inhabited application +forces its argument into the domain. Added for the caps tier's +pinned-pair η row (task #161). -/ +theorem app_lamR_of_not_mem {v : Nat} {A a : V} {F : V → V} (hv : v ≠ 0) + (ha : ¬ a ∈ˢ A) : app (lamR v A F) a = (empty : V) := by + rw [lamR_pos hv]; exact app_graph_of_not_mem ha + +/-- Graph-regime abstractions are graphs, never the proof point. -/ +theorem lamR_ne_pt {v : Nat} {A : V} {F : V → V} (hv : v ≠ 0) : + lamR v A F ≠ pt := by rw [lamR_pos hv]; exact graph_ne_pt + +/-- Eta: a member of a product is the abstraction of its +applications. -/ +theorem lamR_eta {v : Nat} {A f : V} {B : V → V} (hf : f ∈ˢ piR v A B) : + lamR v A (fun x => app f x) = f := by + rcases Nat.eq_zero_or_pos v with rfl | hv + · rw [lamR_zero, eq_pt_of_mem_piR_zero hf] + · have hv' : v ≠ 0 := Nat.pos_iff_ne_zero.mp hv + rw [piR_pos hv'] at hf + rw [lamR_pos hv'] + exact eq_graph_app_of_mem_piSet hf + +/-- Function extensionality for product members: on-domain agreement is +total agreement. At `v = 0` both sides are the canonical proof; above +it both are graphs over `A`, whose off-domain applications are the same +canonical junk. -/ +theorem eq_of_mem_piR_app_eq {v : Nat} {A f g : V} {B B' : V → V} + (hf : f ∈ˢ piR v A B) (hg : g ∈ˢ piR v A B') + (h : ∀ x, x ∈ˢ A → app f x = app g x) : f = g := by + rw [← lamR_eta hf, ← lamR_eta hg]; exact lamR_congr h + +/-! ## The graph regime: inversion and junk-freeness + +These are the laws the collapse cannot have. Under `piC` a product +member is either a graph *or* the proof point (`mem_piC_cases`), so +every consumer dispatches; here the annotation has already decided, and +membership in a positive-regime product is *by definition* graph-hood. -/ + +/-- **The prized inversion.** A member of a graph-regime product is a +graph whose domain is exactly the product's domain, whose applications +land pointwise in the fibres, which is never the proof point, and which +applies to the canonical junk `∅` off the domain. Every clause is by +definition of `piSet`; nothing about `B` is used. -/ +theorem mem_piR_pos {v : Nat} {A f : V} {B : V → V} (hv : v ≠ 0) + (hf : f ∈ˢ piR v A B) : + graph (fun x => app f x) A = f ∧ + (∀ x, x ∈ˢ A → app f x ∈ˢ B x) ∧ + (∀ a, ¬ a ∈ˢ A → app f a = empty) ∧ + f ≠ pt := by + rw [piR_pos hv] at hf + exact ⟨eq_graph_app_of_mem_piSet hf, fun x hx => app_mem_of_mem_piSet hf hx, + fun a ha => app_off_dom_of_mem_piSet hf ha, ne_pt_of_mem_piSet hf⟩ + +/-- The proof point never inhabits a graph-regime product — for *any* +domain and *any* fibre family, in particular a universe-valued one. +This is the removal of the collapse's universe-cohabitation wall, where +`pt ∈ˢ piC A (fun _ => univ 0)` holds at an unknown-empty domain. -/ +theorem not_pt_mem_piR_pos {v : Nat} {A : V} {B : V → V} (hv : v ≠ 0) : + ¬ (pt : V) ∈ˢ piR v A B := + fun h => (mem_piR_pos hv h).2.2.2 rfl + +/-- A graph-regime member applied off the domain is canonical junk — +never a proof point, never anything a consumer must dispatch on. -/ +theorem app_off_dom_piR_pos {v : Nat} {A f a : V} {B : V → V} (hv : v ≠ 0) + (hf : f ∈ˢ piR v A B) (ha : ¬ a ∈ˢ A) : app f a = empty := + (mem_piR_pos hv hf).2.2.1 a ha + +/-- **Domain uniqueness, unconditional.** A graph determines its own +domain, so membership in two graph-regime products identifies their +domains — with no `≠ pt` side condition (`piC_dom_unique` needs one, +and supplying it is what the collapse made hard). -/ +theorem piR_dom_unique {v v' : Nat} {A A' f : V} {B B' : V → V} + (hv : v ≠ 0) (hv' : v' ≠ 0) + (h1 : f ∈ˢ piR v A B) (h2 : f ∈ˢ piR v' A' B') : A = A' := by + rw [piR_pos hv] at h1 + rw [piR_pos hv'] at h2 + obtain ⟨hsub, htot⟩ := mem_piSet.mp h1 + obtain ⟨hsub', htot'⟩ := mem_piSet.mp h2 + refine ext fun x => ⟨fun hx => ?_, fun hx => ?_⟩ + · obtain ⟨y, hy, -⟩ := htot x hx + obtain ⟨x2, hx2, y2, -, hp⟩ := mem_sigmaPairs.mp (hsub' _ hy) + obtain ⟨rfl, rfl⟩ := kpair_inj hp + exact hx2 + · obtain ⟨y, hy, -⟩ := htot' x hx + obtain ⟨x2, hx2, y2, -, hp⟩ := mem_sigmaPairs.mp (hsub _ hy) + obtain ⟨rfl, rfl⟩ := kpair_inj hp + exact hx2 + +/-! ## The truth-value regime -/ + +/-- **Impredicativity.** A product landing in `Prop` is a truth value +— for an arbitrary domain `A` and arbitrary fibres, with no size +condition. This is the one place a set-theoretic model of Lean has to +say something, and here it is the `v = 0` branch of a numeral test. -/ +theorem piR_zero_mem_univZero {A : V} {B : V → V} : + piR 0 A B ∈ˢ (univZero : V) := by + rw [piR_zero]; exact truthVal_mem_univZero _ + +/-- Members of a truth value are all equal: the `v = 0` regime is +subsingleton-valued. -/ +theorem subsingleton_of_mem_univZero {T x y : V} (hT : T ∈ˢ (univZero : V)) + (hx : x ∈ˢ T) (hy : y ∈ˢ T) : x = y := + (eq_pt_of_mem_univZero hT hx).trans (eq_pt_of_mem_univZero hT hy).symm + +/-- Proof irrelevance for the squash regime, in subsingleton form. -/ +theorem piR_zero_subsingleton {A x y : V} {B : V → V} + (hx : x ∈ˢ piR 0 A B) (hy : y ∈ˢ piR 0 A B) : x = y := + (eq_pt_of_mem_piR_zero hx).trans (eq_pt_of_mem_piR_zero hy).symm + +/-- The empty-domain product is truth — in the graph regime too, where +it is the singleton `{∅}` of the empty graph rather than a collapsed +point. (Contrast `piC_empty`, where *every* empty-domain product is +`unitSet` and *every* empty-domain abstraction collapses to `pt` — the +countermodel that blocked the #100 flip.) -/ +theorem piR_pos_empty {v : Nat} (hv : v ≠ 0) (B : V → V) : + piR v (empty : V) B = sing (empty : V) := by + rw [piR_pos hv] + refine ext fun f => ?_ + rw [mem_sing, mem_piSet] + constructor + · rintro ⟨hsub, -⟩ + refine eq_empty fun z hz => ?_ + obtain ⟨x, hx, -⟩ := mem_sigmaPairs.mp (hsub z hz) + exact not_mem_empty x hx + · rintro rfl + exact ⟨fun z hz => absurd hz (not_mem_empty z), + fun x hx => absurd hx (not_mem_empty x)⟩ + +/-- Empty-domain abstraction in the graph regime is the empty graph, +**not** the proof point: the annotation, not the (vacuous) value test, +decides. This is exactly the clause whose collapse analogue +(`lamC_empty`) produced the #100 countermodel. -/ +theorem lamR_pos_empty {v : Nat} (hv : v ≠ 0) (F : V → V) : + lamR v (empty : V) F = (empty : V) := by + rw [lamR_pos hv] + refine eq_empty fun z hz => ?_ + obtain ⟨x, hx, -⟩ := mem_graph.mp hz + exact not_mem_empty x hx + +end Ix.Theory.Model.SetModel diff --git a/Ix/Theory/Model/SetModel/RecGraph.lean b/Ix/Theory/Model/SetModel/RecGraph.lean new file mode 100644 index 000000000..675de1d68 --- /dev/null +++ b/Ix/Theory/Model/SetModel/RecGraph.lean @@ -0,0 +1,270 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetModel/RecGraph.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.LfpFam +import Ix.Theory.Model.SetTheory.Derive.Pt +@[expose] public section + +/-! +# The recursion theorem by lfp induction (task #202, Stage A2) + +The recursive squash regime's large eliminator: the family lives at +`Prop` (its fibres are truth values, the sole proof the point) and the +recursor eliminates into `Sort ℓ`, `ℓ ≠ 0`. The recursor's value at an +index `i` is determined by the recursion equation `R i = st i (R on the +predecessors of i)` — well-founded along the family's least fixed +point, which is why it exists and is unique. + +This module states that abstractly, `Expr`-free: over an index set `I` +with predecessor sets `pred i ⊆ I`, a bound `B i ∈ univ ℓ` and a step +`st i g` (`g` a choice function of predecessor values), the GRAPH +functor `recGraphStep` sends a family `S` to the family of values +`st i g` for `g ∈ Π_{j ∈ pred i} S j` (within `B i`); it is monotone +and `B` is a closed family, so its least fixed point `recGraph` exists, +and at every index whose `Acc`-family fibre (`accFam`: inhabited iff +`Cond i` and every predecessor's fibre is) is inhabited, `recGraph`'s +fibre is a SINGLETON (`recGraph_exists_unique`) — by +`lfpFamSet_induction` on the `Acc` family: the predecessors' fibres +are singletons, the graph of their elements witnesses existence +(`app_lfpFamSet_eq`), and any element is the step at that same choice +function, by function extensionality on `piSet`. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +section RecGraph + +variable (ℓ : Nat) (I : V) (pred : V → V) (B : V → V) (st : V → V → V) + +/-- The graph functor's fibre at `i` over the family `S`. -/ +noncomputable def recGraphFibre (S i : V) : V := + sep (B i) fun v => ∃ g, g ∈ˢ piSet (pred i) (fun j => app S j) ∧ v = st i g + +/-- The graph functor on families over `I`, as a set-function on the +family space. -/ +noncomputable def recGraphStep : V := + graph (fun S => graph (fun i => recGraphFibre pred B st S i) I) (famSpace ℓ I) + +/-- **The recursor's graph**: the least fixed point of the graph +functor. -/ +noncomputable def recGraph : V := lfpFamSet ℓ I (recGraphStep ℓ I pred B st) + +variable {ℓ I pred B st} + +theorem app_recGraphStep {S : V} (hS : S ∈ˢ famSpace ℓ I) : + app (recGraphStep ℓ I pred B st) S = graph (fun i => recGraphFibre pred B st S i) I := + app_graph hS + +theorem app_app_recGraphStep {S i : V} (hS : S ∈ˢ famSpace ℓ I) (hi : i ∈ˢ I) : + app (app (recGraphStep ℓ I pred B st) S) i = recGraphFibre pred B st S i := by + rw [app_recGraphStep hS, app_graph hi] + +theorem mem_recGraphFibre {S i v : V} : + v ∈ˢ recGraphFibre pred B st S i ↔ + v ∈ˢ B i ∧ ∃ g, g ∈ˢ piSet (pred i) (fun j => app S j) ∧ v = st i g := + mem_sep + +/-- The functor maps the family space into itself. -/ +theorem recGraphStep_maps (hB : ∀ i, i ∈ˢ I → B i ∈ˢ (univ ℓ : V)) : + MapsFam ℓ I (recGraphStep ℓ I pred B st) := by + intro S hS + rw [app_recGraphStep hS] + exact graph_mem_famSpace fun i hi => univ_sep_mem (hB i hi) + +/-- The functor is monotone: more predecessor values, more steps. -/ +theorem recGraphStep_mono (hpred : ∀ i, i ∈ˢ I → pred i ⊆ˢ I) : + MonoFam ℓ I (recGraphStep ℓ I pred B st) := by + intro X Y hX hY hle i hi v hv + rw [app_app_recGraphStep hX hi] at hv + rw [app_app_recGraphStep hY hi] + obtain ⟨hvB, g, hg, rfl⟩ := mem_recGraphFibre.mp hv + refine mem_recGraphFibre.mpr ⟨hvB, g, ?_, rfl⟩ + obtain ⟨hsub, htot⟩ := mem_piSet.mp hg + refine mem_piSet.mpr ⟨fun p hp => ?_, htot⟩ + obtain ⟨j, hj, y, hy, rfl⟩ := mem_sigmaPairs.mp (hsub p hp) + exact mem_sigmaPairs.mpr ⟨j, hj, y, hle j (hpred i hi j hj) y hy, rfl⟩ + +/-- The bound is a closed family. -/ +theorem recGraphStep_closed (hB : ∀ i, i ∈ˢ I → B i ∈ˢ (univ ℓ : V)) : + IsClosedFam ℓ I (recGraphStep ℓ I pred B st) (graph B I) := by + refine ⟨graph_mem_famSpace hB, fun i hi v hv => ?_⟩ + rw [app_app_recGraphStep (graph_mem_famSpace hB) hi] at hv + rw [app_graph hi] + exact (mem_recGraphFibre.mp hv).1 + +/-- **The fixed-point equation**, fibrewise. -/ +theorem app_recGraph_eq (hB : ∀ i, i ∈ˢ I → B i ∈ˢ (univ ℓ : V)) + (hpred : ∀ i, i ∈ˢ I → pred i ⊆ˢ I) {i : V} (hi : i ∈ˢ I) : + app (recGraph ℓ I pred B st) i = recGraphFibre pred B st (recGraph ℓ I pred B st) i := by + unfold recGraph + rw [← app_lfpFamSet_eq ⟨_, recGraphStep_closed hB⟩ (recGraphStep_mono hpred) + (recGraphStep_maps hB) hi, app_app_recGraphStep (lfpFamSet_mem _ _ _) hi] + +end RecGraph + +/-! ## The `Acc` family -/ + +section AccFam + +variable (I : V) (pred : V → V) (Cond : V → Prop) + +/-- The `Acc` functor's fibre: inhabited iff the side condition holds +and every predecessor's fibre is inhabited. -/ +noncomputable def accFibre (X i : V) : V := + truthVal (Cond i ∧ ∀ j, j ∈ˢ pred i → ∃ y, y ∈ˢ app X j) + +noncomputable def accStep : V := + graph (fun X => graph (fun i => accFibre pred Cond X i) I) (famSpace 0 I) + +/-- **The `Acc` family**: the least fixed point of the `Acc` functor at +`Prop`. -/ +noncomputable def accFam : V := lfpFamSet 0 I (accStep I pred Cond) + +variable {I pred Cond} + +theorem app_app_accStep {X i : V} (hX : X ∈ˢ famSpace 0 I) (hi : i ∈ˢ I) : + app (app (accStep I pred Cond) X) i = accFibre pred Cond X i := by + unfold accStep + rw [app_graph hX, app_graph hi] + +theorem accStep_maps : MapsFam 0 I (accStep I pred Cond) := by + intro X hX + unfold accStep + rw [app_graph hX] + refine graph_mem_famSpace fun i _ => ?_ + rw [univ_zero] + exact truthVal_mem_univZero _ + +theorem accStep_mono (hpred : ∀ i, i ∈ˢ I → pred i ⊆ˢ I) : MonoFam 0 I (accStep I pred Cond) := by + intro X Y hX hY hle i hi x hx + rw [app_app_accStep hX hi] at hx + rw [app_app_accStep hY hi] + obtain ⟨⟨hc, hall⟩, rfl⟩ := mem_truthVal.mp hx + refine mem_truthVal.mpr ⟨⟨hc, fun j hj => ?_⟩, rfl⟩ + obtain ⟨y, hy⟩ := hall j hj + exact ⟨y, hle j (hpred i hi j hj) y hy⟩ + +theorem accStep_closed : IsClosedFam 0 I (accStep I pred Cond) (graph (fun _ => unitSet) I) := by + refine ⟨graph_mem_famSpace fun _ _ => by rw [univ_zero]; exact mem_univZero.mpr (Subset.refl _), + fun i hi x hx => ?_⟩ + rw [app_app_accStep (graph_mem_famSpace fun _ _ => by + rw [univ_zero]; exact mem_univZero.mpr (Subset.refl _)) hi] at hx + rw [app_graph hi] + obtain ⟨-, rfl⟩ := mem_truthVal.mp hx + exact pt_mem_unitSet + +end AccFam + +/-! ## The recursion theorem -/ + +section RecTheorem + +variable {ℓ : Nat} {I : V} {pred : V → V} {B : V → V} {st : V → V → V} {Cond : V → Prop} + +/-- **The local step**: at an index whose predecessors' fibres are all +singletons, the recursor's graph has exactly one value. -/ +theorem recGraph_singleton_of_preds (hB : ∀ i, i ∈ˢ I → B i ∈ˢ (univ ℓ : V)) + (hpred : ∀ i, i ∈ˢ I → pred i ⊆ˢ I) + {i : V} (hi : i ∈ˢ I) + (hst : ∀ g, g ∈ˢ piSet (pred i) (fun j => app (recGraph ℓ I pred B st) j) → st i g ∈ˢ B i) + (hP : ∀ j, j ∈ˢ pred i → (∃ v, v ∈ˢ app (recGraph ℓ I pred B st) j) ∧ + ∀ v v', v ∈ˢ app (recGraph ℓ I pred B st) j → v' ∈ˢ app (recGraph ℓ I pred B st) j → + v = v') : + (∃ v, v ∈ˢ app (recGraph ℓ I pred B st) i) ∧ + ∀ v v', v ∈ˢ app (recGraph ℓ I pred B st) i → v' ∈ˢ app (recGraph ℓ I pred B st) i → + v = v' := by + -- the choice function of the predecessors' values + have hchoice : ∀ j, ∃ v, j ∈ˢ pred i → v ∈ˢ app (recGraph ℓ I pred B st) j := fun j => + Classical.byCases (fun h : j ∈ˢ pred i => ⟨_, fun _ => Classical.choose_spec (hP j h).1⟩) + (fun h => ⟨pt, fun h' => absurd h' h⟩) + have hu : ∀ j, j ∈ˢ pred i → + Classical.choose (hchoice j) ∈ˢ app (recGraph ℓ I pred B st) j := + fun j hj => Classical.choose_spec (hchoice j) hj + have hg : graph (fun j => Classical.choose (hchoice j)) (pred i) + ∈ˢ piSet (pred i) (fun j => app (recGraph ℓ I pred B st) j) := graph_mem_piSet hu + -- any value at `i` is the step at that choice function + have key : ∀ v, v ∈ˢ app (recGraph ℓ I pred B st) i → + v = st i (graph (fun j => Classical.choose (hchoice j)) (pred i)) := by + intro v hv + rw [app_recGraph_eq hB hpred hi] at hv + obtain ⟨-, g', hg', rfl⟩ := mem_recGraphFibre.mp hv + congr 1 + rw [← eq_graph_app_of_mem_piSet hg'] + exact graph_congr fun j hj => (hP j hj).2 _ _ (app_mem_of_mem_piSet hg' hj) (hu j hj) + refine ⟨⟨st i (graph (fun j => Classical.choose (hchoice j)) (pred i)), ?_⟩, + fun v v' hv hv' => by rw [key v hv, key v' hv']⟩ + rw [app_recGraph_eq hB hpred hi] + exact mem_recGraphFibre.mpr ⟨hst _ hg, _, hg, rfl⟩ + +/-- The graph's selector: the fibre's element (the point off the graph). -/ +noncomputable def recSel (G : V) (i : V) : V := + open Classical in + if h : ∃ v, v ∈ˢ app G i then Classical.choose h else pt + +theorem recSel_mem {G i : V} (h : ∃ v, v ∈ˢ app G i) : recSel G i ∈ˢ app G i := by + unfold recSel + rw [dif_pos h] + exact Classical.choose_spec h + +/-- **The recursion equation** at an index whose fibre and whose +predecessors' fibres are singletons: the selector's value is the step +at the selector's graph over the predecessors. -/ +theorem recSel_eq (hB : ∀ i, i ∈ˢ I → B i ∈ˢ (univ ℓ : V)) + (hpred : ∀ i, i ∈ˢ I → pred i ⊆ˢ I) {i : V} (hi : i ∈ˢ I) + (hPi : ∃ v, v ∈ˢ app (recGraph ℓ I pred B st) i) + (hP : ∀ j, j ∈ˢ pred i → (∃ v, v ∈ˢ app (recGraph ℓ I pred B st) j) ∧ + ∀ v v', v ∈ˢ app (recGraph ℓ I pred B st) j → v' ∈ˢ app (recGraph ℓ I pred B st) j → + v = v') : + recSel (recGraph ℓ I pred B st) i + = st i (graph (fun j => recSel (recGraph ℓ I pred B st) j) (pred i)) := by + have hv := recSel_mem hPi + rw [app_recGraph_eq hB hpred hi] at hv + obtain ⟨-, g', hg', hst⟩ := mem_recGraphFibre.mp hv + rw [hst] + congr 1 + rw [← eq_graph_app_of_mem_piSet hg'] + exact graph_congr fun j hj => + (hP j hj).2 _ _ (app_mem_of_mem_piSet hg' hj) (recSel_mem (hP j hj).1) + +/-- **The recursion theorem by lfp induction**: at every index whose +`Acc`-family fibre is inhabited, the recursor's graph has exactly one +value. -/ +theorem recGraph_exists_unique (hB : ∀ i, i ∈ˢ I → B i ∈ˢ (univ ℓ : V)) + (hpred : ∀ i, i ∈ˢ I → pred i ⊆ˢ I) + (hst : ∀ i, i ∈ˢ I → ∀ g, g ∈ˢ piSet (pred i) (fun j => app (recGraph ℓ I pred B st) j) → + st i g ∈ˢ B i) : + ∀ i, i ∈ˢ I → ∀ x, x ∈ˢ app (accFam I pred Cond) i → + (∃ v, v ∈ˢ app (recGraph ℓ I pred B st) i) ∧ + ∀ v v', v ∈ˢ app (recGraph ℓ I pred B st) i → v' ∈ˢ app (recGraph ℓ I pred B st) i → + v = v' := by + refine lfpFamSet_induction ⟨_, accStep_closed (pred := pred) (Cond := Cond)⟩ (accStep_mono hpred) + (fun i _ => (∃ v, v ∈ˢ app (recGraph ℓ I pred B st) i) ∧ + ∀ v v', v ∈ˢ app (recGraph ℓ I pred B st) i → v' ∈ˢ app (recGraph ℓ I pred B st) i → + v = v') ?_ + intro i hi x hx + have hsubmem : graph (fun i => sep (app (lfpFamSet 0 I (accStep I pred Cond)) i) + (fun _ => (∃ v, v ∈ˢ app (recGraph ℓ I pred B st) i) ∧ + ∀ v v', v ∈ˢ app (recGraph ℓ I pred B st) i → v' ∈ˢ app (recGraph ℓ I pred B st) i → + v = v')) I ∈ˢ famSpace 0 I := + graph_mem_famSpace fun i hi => univ_sep_mem (famSpace_app (lfpFamSet_mem _ _ _) hi) + rw [app_app_accStep hsubmem hi] at hx + obtain ⟨⟨-, hall⟩, -⟩ := mem_truthVal.mp hx + refine recGraph_singleton_of_preds hB hpred hi (hst i hi) fun j hj => ?_ + obtain ⟨y, hy⟩ := hall j hj + rw [app_graph (hpred i hi j hj)] at hy + exact (mem_sep.mp hy).2 + +end RecTheorem + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetModel/TaggedSum.lean b/Ix/Theory/Model/SetModel/TaggedSum.lean new file mode 100644 index 000000000..83620708b --- /dev/null +++ b/Ix/Theory/Model/SetModel/TaggedSum.lean @@ -0,0 +1,186 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetModel/TaggedSum.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetModel.TupleTower + +@[expose] public section + +/-! +# The tagged disjoint union (task #175 sum-types) + +The semantic carrier of a directly-installed inductive with **any +number of constructors other than one**: a value is the pair of a +**numeral tag** — the constructor's index, a finite ordinal +`vnat i ∈ ω` — and that constructor's tuple tower +(`Ix.Theory/Model/SetModel/TupleTower.lean`): + + sumSet w f = sigmaSet w ω (natFibre f) f i = the i-th tower + inj i a = spair (vnat i) a + +`natFibre f` is the fibre function over `ω`: `f i` at `vnat i`, junk +(`empty`) off the numerals — never consulted there, since every member +of `ω` is a unique numeral (`mem_omega_iff`/`vnat_inj`). The same +function is the **case split** the recursor performs: on a member +`inj i a` the recursor reads `i` back through `natFibre` and applies +the `i`-th branch to `a` (`sumRec`). + +Both regimes ride one definition: `sigmaSet` reads `w` only through +its zero test, so at `w = 0` the carrier is the truth value "some +constructor's tower is inhabited" (`sumSet_zero_elim`) with every +member the proof point, and above `0` it is the set of tagged pairs +(`sumSet_elim`). The tag domain `ω` sits in `univ w` for every `w ≥ 1` +(`omega_mem_univ_succ` + cumulativity), which is where the carrier's +formation lands (`sumSet_mem_univ`); at `w = 0` no bound is needed +(`sumSet_zero_mem_univZero`). + +Everything here is over the bare `SetTheory` interface; no syntax. +-/ + +namespace Ix.Theory.Model.SetTheory.Tower + +universe u + +variable {V : Type u} [SetTheory V] + +open Classical in +/-- The fibre function over the numerals: `f i` at `vnat i`, junk off +the numerals. -/ +noncomputable def natFibre (f : Nat → V) (k : V) : V := + if h : ∃ i, k = vnat i then f (Classical.choose h) else empty + +theorem natFibre_vnat (f : Nat → V) (i : Nat) : natFibre f (vnat i) = f i := by + unfold natFibre + rw [dif_pos ⟨i, rfl⟩] + congr 1 + exact (vnat_inj (Classical.choose_spec (⟨i, rfl⟩ : ∃ i', (vnat i : V) = vnat i'))).symm + +/-- Every member of `ω` is a numeral, at which the fibre is the +named set. -/ +theorem natFibre_of_mem (f : Nat → V) {k : V} (hk : k ∈ˢ (omega : V)) : + ∃ i, k = vnat i ∧ natFibre f k = f i := by + obtain ⟨i, rfl⟩ := mem_omega_iff.mp hk + exact ⟨i, rfl, natFibre_vnat f i⟩ + +/-- Fibre functions agreeing on the numerals agree on `ω`. -/ +theorem natFibre_congr {f g : Nat → V} (h : ∀ i, f i = g i) (k : V) : + natFibre f k = natFibre g k := by + unfold natFibre + split + · rw [h] + · rfl + +/-- **The tagged sum carrier.** -/ +noncomputable def sumSet (w : Nat) (f : Nat → V) : V := + sigmaSet w omega (natFibre f) + +/-- **The injection** of constructor `i`. -/ +noncomputable def inj (i : Nat) (a : V) : V := spair (vnat i) a + +/-- The recursor's case split: the branch selected by the tag, applied +to the payload (`natFibre` over the branches). -/ +noncomputable def sumRec (r : Nat → V → V) (x : V) : V := + natFibre (fun i => r i (ssnd x)) (sfst x) + +/-! ## Laws -/ + +theorem sumSet_congr {w : Nat} {f g : Nat → V} (h : ∀ i, f i = g i) : + sumSet w f = sumSet w g := by + unfold sumSet + exact sigma_congr fun k _ => natFibre_congr h k + +/-- **Intro** (graph regime): the injection of a fitting payload is in +the carrier. -/ +theorem inj_mem {w : Nat} (hw : w ≠ 0) {f : Nat → V} {i : Nat} {a : V} + (ha : a ∈ˢ f i) : inj i a ∈ˢ sumSet w f := by + unfold inj sumSet + refine spair_mem hw (vnat_mem_omega i) ?_ + rw [natFibre_vnat] + exact ha + +/-- **Intro** (squash regime): the carrier at `w = 0` holds the point +whenever some constructor's tower is inhabited. -/ +theorem pt_mem_sumSet_zero {f : Nat → V} {i : Nat} {a : V} (ha : a ∈ˢ f i) : + (pt : V) ∈ˢ sumSet 0 f := by + unfold sumSet + exact pt_mem_sigma (a := vnat i) (b := a) (vnat_mem_omega i) + (by rw [natFibre_vnat]; exact ha) + +/-- **Elim** (graph regime): every carrier member is the injection of +a fitting payload. -/ +theorem sumSet_elim {w : Nat} (hw : w ≠ 0) {f : Nat → V} {x : V} + (hx : x ∈ˢ sumSet w f) : ∃ i a, a ∈ˢ f i ∧ x = inj i a := by + unfold sumSet at hx + obtain ⟨k, a, hk, ha, -, hpos⟩ := mem_sigma_elim hx + obtain ⟨i, rfl, hfib⟩ := natFibre_of_mem f hk + rw [hfib] at ha + exact ⟨i, a, ha, hpos hw⟩ + +/-- **Elim** (squash regime): a `w = 0` carrier member is the point, +and some constructor's tower is inhabited. -/ +theorem sumSet_zero_elim {f : Nat → V} {x : V} (hx : x ∈ˢ sumSet 0 f) : + x = pt ∧ ∃ i a, a ∈ˢ f i := by + unfold sumSet at hx + obtain ⟨k, a, hk, ha, hz, -⟩ := mem_sigma_elim hx + obtain ⟨i, rfl, hfib⟩ := natFibre_of_mem f hk + rw [hfib] at ha + exact ⟨hz rfl, i, a, ha⟩ + +/-- **Tag disjointness and injectivity**: equal injections have equal +tags and payloads. -/ +theorem inj_inj {i j : Nat} {a b : V} (h : inj i a = inj j b) : i = j ∧ a = b := by + unfold inj at h + have h1 := congrArg sfst h + have h2 := congrArg ssnd h + rw [sfst_spair, sfst_spair] at h1 + rw [ssnd_spair, ssnd_spair] at h2 + exact ⟨vnat_inj h1, h2⟩ + +theorem sfst_inj (i : Nat) (a : V) : sfst (inj i a) = vnat i := sfst_spair _ _ +theorem ssnd_inj (i : Nat) (a : V) : ssnd (inj i a) = a := ssnd_spair _ _ + +/-- **Formation** (graph regime): with every tower in `univ w`, the +carrier is too — the tag domain `ω` sits in every `univ w` above `0`. -/ +theorem sumSet_mem_univ {w : Nat} (hw : w ≠ 0) {f : Nat → V} + (hf : ∀ i, f i ∈ˢ (univ w : V)) : sumSet w f ∈ˢ (univ w : V) := by + obtain ⟨w', rfl⟩ : ∃ w', w = w' + 1 := ⟨w - 1, by omega⟩ + have hω : (omega : V) ∈ˢ univ (w' + 1) := omega_mem_univ_succ w' + have h := sigma_mem_univ (u := w' + 1) (v := w' + 1) (B := natFibre f) hω (fun k hk => by + obtain ⟨i, rfl, hfib⟩ := natFibre_of_mem f hk + rw [hfib] + exact hf i) + rwa [show Nat.max (w' + 1) (w' + 1) = w' + 1 from Nat.max_self _] at h + +/-- **Formation** (squash regime), unconditional. -/ +theorem sumSet_zero_mem_univZero (f : Nat → V) : sumSet 0 f ∈ˢ (univZero : V) := by + unfold sumSet + rw [sigmaSet_zero] + exact truthVal_mem_univZero _ + +/-- **Iota** for the case split — unconditional. -/ +theorem sumRec_inj (r : Nat → V → V) (i : Nat) (a : V) : sumRec r (inj i a) = r i a := by + unfold sumRec + rw [sfst_inj, ssnd_inj, natFibre_vnat] + +/-- **Storage hygiene**: the carrier is never the proof point. -/ +theorem sumSet_ne_pt {w : Nat} (f : Nat → V) : sumSet w f ≠ (pt : V) := sigmaSet_ne_pt + +/-! ## Degeneracy checks -/ + +/-- Zero constructors: the carrier is empty in the graph regime. -/ +example {w : Nat} (hw : w ≠ 0) {x : V} (hx : x ∈ˢ sumSet w (fun _ => (empty : V))) : False := by + obtain ⟨i, a, ha, -⟩ := sumSet_elim hw hx + exact not_mem_empty a ha + +/-- Two constructors: the two injections are distinct. -/ +example (a b : V) : inj 0 a ≠ inj 1 b := fun h => by + have := (inj_inj h).1 + omega + +end Ix.Theory.Model.SetTheory.Tower diff --git a/Ix/Theory/Model/SetModel/TupleTower.lean b/Ix/Theory/Model/SetModel/TupleTower.lean new file mode 100644 index 000000000..dd3b3283b --- /dev/null +++ b/Ix/Theory/Model/SetModel/TupleTower.lean @@ -0,0 +1,424 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetModel/TupleTower.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Sigma + +@[expose] public section + +/-! +# The uniform tuple model: unit-terminated pair towers (agent/tuple-model) + +The semantic carrier construction for directly-installed structures +(DESIGN.md, "AMENDMENT — the uniform tuple model"): every qualifying +structure's carrier is the **right-nested pair tower with unit +terminator** + + towerSet w ⟨F₀, …, F_{n−1}⟩ = F₀ ⋉ (F₁ ⋉ (… ⋉ (F_{n−1} ⋉ unitSet))) + +(each `⋉` a `sigmaSet w`, dependency right-nested along the field +telescope), the constructor is the uniform tupler `mkTower`, and the +semantic projection family is ONE definition depending only on the +index: + + projS i = sfst ∘ ssnd^i (structure-independent) + +The unit terminator is what buys index-only uniformity: with a bare +tail the last field would be read by `ssnd^{n−1}` (no `sfst`), making +the family depend on the arity — i.e. on the structure. It also +gives the 0/1-field degeneracies for free (`n = 0`: the carrier is +`unitSet`, members exactly `pt = mkTower []`; `n = 1`: members are +`spair a pt` and `projS 0 = sfst` is lawful). + +**ProjCoherence by uniform tupling**: the constructor is one +instantiation-independent function with global left inverses +(`kpair_inj` iterated), so the parked study's boundary predicate is +discharged by representation — tier form `mkTower_inj`, proved through +the iota law alone. + +**No `pw` datum — `pt` is separate from pairs** (user refinement, +2026-09-04): the interface keeps the proof point apart from every +Kuratowski pair (`pt_ne_kpair`, the `Derive/Pt.lean` selection +principle, surfaced as `sfst_pt`/`ssnd_pt`; the task-#109 pt-freshness +battery is the systematic form), so the destructors fix `pt` and +`projS i pt = pt` holds outright. A `Prop` structure's element +denotes `pt` and its proof fields denote `pt`, so projection-of-`pt` +is the *correct* answer by proof irrelevance — iota and membership +hold with one uniform `projS`, no per-structure variant. The squash +membership law carries the proof-field premise `PropS` (every field +set a truth value — the levelwise `structSort = 0 → fieldSort = 0` +bound); that is not a datum on the projection but the per-use +legality the checker's own `infer_proj` Prop restriction discharges. +The two regimes are disjoint by the same separation: graph-regime +members of a nonempty tower are never `pt` (`tower_mem_ne_pt`, from +`ptFresh_sigmaSet_pos`), squash members are exactly `pt`. + +Everything here is over the bare `SetTheory` interface; no syntax, no +environment. Kernel wiring is out of scope (post-B4; see the DESIGN +handoff record). +-/ + +namespace Ix.Theory.Model.SetTheory.Tower + +universe u + +/-- A dependent field-set telescope over `V`, indexed by its length: +field `i`'s set may depend on the values of fields `0..i−1`. -/ +inductive TeleS (V : Type u) : Nat → Type u where + | nil : TeleS V 0 + | cons {n : Nat} (A : V) (B : V → TeleS V n) : TeleS V (n + 1) + +variable {V : Type u} [SetTheory V] + +/-- `FitsS T as`: the value list `as` fits the telescope `T` — right +length, each value in its field's set at the earlier values. -/ +def FitsS : {n : Nat} → TeleS V n → List V → Prop + | _, .nil, [] => True + | _, .nil, _ :: _ => False + | _, .cons _ _, [] => False + | _, .cons A B, a :: as => a ∈ˢ A ∧ FitsS (B a) as + +/-- The carrier: the right-nested `sigmaSet w` tower over the +telescope, terminated by `unitSet`. -/ +noncomputable def towerSet (w : Nat) : {n : Nat} → TeleS V n → V + | _, .nil => unitSet + | _, .cons A B => sigmaSet w A (fun a => towerSet w (B a)) + +/-- The uniform tupler: the right-nested Kuratowski pair tower with +`pt` (the sole member of `unitSet`) as terminator. -/ +noncomputable def mkTower : List V → V + | [] => pt + | a :: as => spair a (mkTower as) + +/-- **The uniform semantic projection family**: `projS i = sfst ∘ +ssnd^i`. One definition for every structure and every index. -/ +noncomputable def projS : Nat → V → V + | 0, x => sfst x + | i + 1, x => projS i (ssnd x) + +/-- The first-`n` projection tuple of a value. -/ +noncomputable def projList : Nat → V → List V + | 0, _ => [] + | n + 1, x => sfst x :: projList n (ssnd x) + +/-- The `k`-fold second projection (task #210 Part A): the tuple tower +below `k` leading pair components — `projS (i + k) x = projS i (dropS k +x)`, so a projection table with offset `k` reads its fields off +`dropS k` of the subject (`k = 1` at the fixpoint route's tagged +tower, whose first component is the constructor tag). -/ +noncomputable def dropS : Nat → V → V + | 0, x => x + | k + 1, x => dropS k (ssnd x) + +theorem projS_add_dropS : ∀ (i k : Nat) (x : V), projS (i + k) x = projS i (dropS k x) + | _, 0, _ => rfl + | i, k + 1, x => by + show projS (i + k) (ssnd x) = projS i (dropS k (ssnd x)) + exact projS_add_dropS i k (ssnd x) + +theorem dropS_pt : ∀ k : Nat, dropS k (pt : V) = pt + | 0 => rfl + | k + 1 => by show dropS k (ssnd pt) = pt; rw [ssnd_pt, dropS_pt k] + +/-- The `i`-th field set of a telescope at a prefix valuation +(`empty` out of range — never consumed in range). -/ +noncomputable def teleNth : {n : Nat} → TeleS V n → Nat → List V → V + | _, .nil, _, _ => empty + | _, .cons A _, 0, _ => A + | _, .cons _ B, i + 1, a :: as => teleNth (B a) i as + | _, .cons _ _, _ + 1, [] => empty + +/-- `PropS T`: every field set is a truth value, hereditarily — the +levelwise `structSort = 0 → fieldSort = 0` bound, telescope-side. -/ +def PropS : {n : Nat} → TeleS V n → Prop + | _, .nil => True + | _, .cons A B => A ∈ˢ (univZero : V) ∧ ∀ a, a ∈ˢ A → PropS (B a) + +/-- `BoundS w T`: every field set lives in `univ w`, hereditarily — +the formation premise (per-field sorts `≤ w` via cumulativity). -/ +def BoundS (w : Nat) : {n : Nat} → TeleS V n → Prop + | _, .nil => True + | _, .cons A B => A ∈ˢ (univ w : V) ∧ ∀ a, a ∈ˢ A → BoundS w (B a) + +/-! ## Auxiliary lemmas -/ + +theorem FitsS.length_eq : ∀ {n} {T : TeleS V n} {as : List V}, + FitsS T as → as.length = n + | _, .nil, [], _ => rfl + | _, .cons _ _, _ :: _, h => + congrArg Nat.succ (FitsS.length_eq h.2) + +theorem projList_length : ∀ (n : Nat) (x : V), (projList n x).length = n + | 0, _ => rfl + | n + 1, x => congrArg Nat.succ (projList_length n (ssnd x)) + +theorem projList_get : ∀ (n i : Nat) (x : V) (h : i < n), + (projList n x)[i]'((projList_length n x).symm ▸ h) = projS i x + | _ + 1, 0, _, _ => rfl + | n + 1, i + 1, x, h => + projList_get n i (ssnd x) (Nat.lt_of_succ_lt_succ h) + +theorem projList_take : ∀ (n i : Nat) (x : V), i ≤ n → + (projList n x).take i = projList i x + | _, 0, _, _ => rfl + | n + 1, i + 1, x, h => by + show sfst x :: (projList n (ssnd x)).take i = sfst x :: projList i (ssnd x) + rw [projList_take n i (ssnd x) (Nat.le_of_succ_le_succ h)] + +theorem projList_mkTower : ∀ (n : Nat) (as : List V), as.length = n → + projList n (mkTower as) = as + | 0, [], _ => rfl + | n + 1, a :: as, h => by + show sfst (spair a (mkTower as)) :: projList n (ssnd (spair a (mkTower as))) + = a :: as + rw [sfst_spair, ssnd_spair, projList_mkTower n as (Nat.succ.inj h)] + +theorem projList_mkTower_append : ∀ (as bs : List V), projList as.length (mkTower (as ++ bs)) = as + | [], _ => rfl + | a :: as, bs => by + show sfst (spair a (mkTower (as ++ bs))) :: projList as.length (ssnd (spair a (mkTower (as ++ bs)))) + = a :: as + rw [sfst_spair, ssnd_spair, projList_mkTower_append as bs] + +theorem projList_pt : ∀ n : Nat, projList n (pt : V) = List.replicate n pt + | 0 => rfl + | n + 1 => by + show sfst (pt : V) :: projList n (ssnd (pt : V)) = pt :: List.replicate n pt + rw [sfst_pt, ssnd_pt, projList_pt n] + +/-- `projS` fixes `pt`: the interface's pt-vs-pair separation +(`sfst_pt`/`ssnd_pt`, from `pt_ne_kpair`) makes projection-of-`pt` +return `pt` — the correct proof-field answer, with no separate +`Prop`-structure variant. -/ +theorem projS_pt : ∀ i : Nat, projS i (pt : V) = pt + | 0 => sfst_pt + | i + 1 => by rw [projS, ssnd_pt, projS_pt i] + +/-- `FitsS` reads off `teleNth` membership: each fitting value is in +its field's set at the earlier values. -/ +theorem fitsS_mem_teleNth : ∀ {n} {T : TeleS V n} {as : List V}, + (hf : FitsS T as) → ∀ (i : Nat) (h : i < n), + as[i]'(FitsS.length_eq hf ▸ h) ∈ˢ teleNth T i (as.take i) + | _, .cons _ _, _ :: _, hf, 0, _ => hf.1 + | _, .cons _ B, a :: as, hf, i + 1, h => + fitsS_mem_teleNth (T := B a) (as := as) hf.2 i (Nat.lt_of_succ_lt_succ h) + +/-- `PropS` forces every fitting value to `pt`, so the all-`pt` list +fits whenever anything does. -/ +theorem fitsS_replicate_of_prop : ∀ {n} {T : TeleS V n} {as : List V}, + PropS T → FitsS T as → FitsS T (List.replicate n pt) + | _, .nil, [], _, _ => trivial + | _, .cons _ B, a :: as, hP, hf => by + have ha : a = pt := eq_pt_of_mem_univZero hP.1 hf.1 + show (pt : V) ∈ˢ _ ∧ FitsS (B pt) (List.replicate _ pt) + exact ⟨ha ▸ hf.1, ha ▸ fitsS_replicate_of_prop (hP.2 a hf.1) hf.2⟩ + +/-! ## The law families (frozen in the DESIGN amendment) -/ + +/-- **Intro** (graph regime): a fitting tuple's tower is in the +carrier. -/ +theorem mkTower_mem {w : Nat} (hw : w ≠ 0) : + ∀ {n} {T : TeleS V n} {as : List V}, + FitsS T as → mkTower as ∈ˢ towerSet w T + | _, .nil, [], _ => pt_mem_unitSet + | _, .cons _ B, a :: _, hf => + spair_mem hw hf.1 (mkTower_mem hw (T := B a) hf.2) + +/-- **Intro** (squash regime): the carrier at `w = 0` is the truth +value of fittability. -/ +theorem pt_mem_tower : ∀ {n} {T : TeleS V n} {as : List V}, + FitsS T as → (pt : V) ∈ˢ towerSet 0 T + | _, .nil, [], _ => pt_mem_unitSet + | _, .cons _ B, a :: _, hf => + pt_mem_sigma hf.1 (pt_mem_tower (T := B a) hf.2) + +/-- **Iota — UNCONDITIONAL**: no membership premise, no level. The +checker's `.proj`/`mk` reduction is denotation-sound with no typing of +the fields at all. -/ +theorem projS_mkTower : ∀ (i : Nat) (as : List V) (h : i < as.length), + projS i (mkTower as) = as[i] + | 0, a :: as, _ => by + show sfst (spair a (mkTower as)) = a + exact sfst_spair a (mkTower as) + | i + 1, a :: as, h => by + show projS i (ssnd (spair a (mkTower as))) = as[i]'(Nat.lt_of_succ_lt_succ h) + rw [ssnd_spair] + exact projS_mkTower i as (Nat.lt_of_succ_lt_succ h) + +/-- The projection list of a point-terminated tower is the fields' +prefix (task #210: the fixpoint route's constructor payload). -/ +theorem projList_mkTower_take {fs : List V} {i : Nat} (hi : i ≤ fs.length) : + projList i (mkTower (fs ++ [pt])) = fs.take i := by + have h1 : projList (fs.length + 1) (mkTower (fs ++ [pt])) = fs ++ [pt] := projList_mkTower _ _ (by simp) + have h2 := projList_take (fs.length + 1) i (mkTower (fs ++ [pt])) (by omega) + rw [h1, List.take_append_of_le_length hi] at h2 + exact h2.symm + +/-- A field projection of a point-terminated tower, `getD`-form. -/ +theorem projS_mkTower_getD {fs : List V} {i : Nat} (hi : i < fs.length) : + projS i (mkTower (fs ++ [pt])) = fs.getD i pt := by + rw [projS_mkTower i (fs ++ [pt]) (by simp; omega), List.getElem_append_left hi, + List.getD_eq_getElem?_getD, List.getElem?_eq_getElem hi, Option.getD_some] + +/-- **Eta + elim** (graph regime): every carrier member IS the tower +of its own projections, and those projections fit the telescope. -/ +theorem towerSet_elim {w : Nat} (hw : w ≠ 0) : + ∀ {n} (T : TeleS V n) {x : V}, x ∈ˢ towerSet w T → + FitsS T (projList n x) ∧ x = mkTower (projList n x) + | _, .nil, x, hx => ⟨trivial, mem_unitSet_iff.mp hx⟩ + | _, .cons A B, x, hx => by + obtain ⟨a, b, ha, hb, -, hpos⟩ := + mem_sigma_elim (A := A) (B := fun a => towerSet w (B a)) hx + have hx' : x = spair a b := hpos hw + subst hx' + obtain ⟨hfit, heta⟩ := towerSet_elim hw (B a) hb + constructor + · show sfst (spair a b) ∈ˢ A ∧ FitsS (B (sfst (spair a b))) + (projList _ (ssnd (spair a b))) + rw [sfst_spair, ssnd_spair] + exact ⟨ha, hfit⟩ + · show spair a b + = spair (sfst (spair a b)) (mkTower (projList _ (ssnd (spair a b)))) + rw [sfst_spair, ssnd_spair, ← heta] + +/-- **Elim** (squash regime): a `w = 0` carrier member is `pt`, and +some tuple fits. -/ +theorem towerSet_zero_elim : ∀ {n} (T : TeleS V n) {x : V}, + x ∈ˢ towerSet 0 T → x = pt ∧ ∃ as, FitsS T as + | _, .nil, x, hx => ⟨mem_unitSet_iff.mp hx, [], trivial⟩ + | _, .cons A B, x, hx => by + obtain ⟨a, b, ha, hb, hz, -⟩ := + mem_sigma_elim (A := A) (B := fun a => towerSet 0 (B a)) hx + obtain ⟨-, as, hfit⟩ := towerSet_zero_elim (B a) hb + exact ⟨hz rfl, a :: as, ha, hfit⟩ + +/-- **Membership** (graph regime): the `i`-th projection lands in the +`i`-th field set at the earlier projections. -/ +theorem projS_mem {w : Nat} (hw : w ≠ 0) {n} {T : TeleS V n} {x : V} + (hx : x ∈ˢ towerSet w T) (i : Nat) (h : i < n) : + projS i x ∈ˢ teleNth T i (projList i x) := by + obtain ⟨hfit, -⟩ := towerSet_elim hw T hx + have hm := fitsS_mem_teleNth hfit i h + rw [projList_take n i x (Nat.le_of_lt h)] at hm + rw [← projList_get n i x h] + exact hm + +/-- **Membership** (squash regime): the SAME statement, with the +proof-field premise `PropS` in place of `w ≠ 0` — every member is +`pt`, `projS` fixes it, and every truth-value field set at the +all-`pt` prefix contains it (proof irrelevance, semantically). -/ +theorem projS_mem_zero {n} {T : TeleS V n} {x : V} (hP : PropS T) + (hx : x ∈ˢ towerSet 0 T) (i : Nat) (h : i < n) : + projS i x ∈ˢ teleNth T i (projList i x) := by + obtain ⟨rfl, as, hfit⟩ := towerSet_zero_elim T hx + have hrep := fitsS_replicate_of_prop hP hfit + have hm := fitsS_mem_teleNth hrep i h + rw [List.take_replicate, Nat.min_eq_left (Nat.le_of_lt h), + List.getElem_replicate] at hm + rw [projS_pt, projList_pt] + exact hm + +/-- **Coherence by uniform tupling**: `ProjCoh` holds by +representation — equal towers of equal arity have equal components. +Proved through the iota law alone (`kpair_inj` iterated). -/ +theorem mkTower_inj {as bs : List V} (hlen : as.length = bs.length) + (h : mkTower as = mkTower bs) : as = bs := by + apply List.ext_getElem hlen + intro i h1 h2 + rw [← projS_mkTower i as h1, ← projS_mkTower i bs h2, h] + +/-- **The recursor, DERIVED** (graph regime): large-elimination typing +and iota for `r := m ∘ projList n`, with eta (`towerSet_elim`) as the +load-bearing step of the typing — the probe's `builtModel_recElimU2`, +promoted to every arity and dependency shape. -/ +theorem towerRec {w : Nat} (hw : w ≠ 0) {n} (T : TeleS V n) + (M : V → V) (m : List V → V) + (hm : ∀ as, FitsS T as → m as ∈ˢ M (mkTower as)) : + ∃ r : V → V, (∀ x, x ∈ˢ towerSet w T → r x ∈ˢ M x) ∧ + (∀ as, FitsS T as → r (mkTower as) = m as) := by + refine ⟨fun x => m (projList n x), fun x hx => ?_, fun as hf => ?_⟩ + · obtain ⟨hfit, heta⟩ := towerSet_elim hw T hx + have := hm _ hfit + rwa [← heta] at this + · show m (projList n (mkTower as)) = m as + rw [projList_mkTower n as hf.length_eq] + +/-- **The recursor at squash**: constant elimination is lawful — the +semantic form of subsingleton elimination (the minor's value must be +instantiation-independent, which all-proof-field instantiations +satisfy with `m = pt`). -/ +theorem towerRec_zero {n} (T : TeleS V n) (M : V → V) (m : V) + (hm : (∃ as, FitsS T as) → m ∈ˢ M pt) : + ∀ x, x ∈ˢ towerSet 0 T → m ∈ˢ M x := by + intro x hx + obtain ⟨rfl, hex⟩ := towerSet_zero_elim T hx + exact hm hex + +/-- **Formation**: the carrier lives at the structure's own level, +given the per-field bound (cumulativity is applied by the consumer +when a field's sort is `< w`). -/ +theorem towerSet_mem_univ {w : Nat} : ∀ {n} (T : TeleS V n), + BoundS w T → towerSet w T ∈ˢ (univ w : V) + | _, .nil, _ => unitSet_mem_univ w + | _, .cons A B, hb => by + simp only [towerSet] + have h := sigma_mem_univ (u := w) (v := w) hb.1 + (fun a ha => towerSet_mem_univ (B a) (hb.2 a ha)) + rwa [show Nat.max w w = w from Nat.max_self w] at h + +/-- **Formation, squash regime — UNCONDITIONAL**: at `w = 0` the +carrier is a truth value with no field bounds at all (`sigmaSet 0` +truncates whatever its arguments are), so definitely-`Prop` +structures with arbitrary-sorted data fields (`Exists`) still get a +lawful carrier; only their *projections* wait on `PropS`. -/ +theorem towerSet_zero_mem_univZero : ∀ {n} (T : TeleS V n), + towerSet 0 T ∈ˢ (univZero : V) + | _, .nil => univ_zero (V := V) ▸ unitSet_mem_univ 0 + | _, .cons _ B => by + show sigmaSet 0 _ (fun a => towerSet 0 (B a)) ∈ˢ (univZero : V) + rw [sigmaSet_zero] + exact truthVal_mem_univZero _ + +/-- **Storage hygiene**: a tower carrier is never the proof point +(the task-#100 collapse-era non-`pt`-ness of stored values). -/ +theorem towerSet_ne_pt {w : Nat} : ∀ {n} (T : TeleS V n), + towerSet w T ≠ (pt : V) + | _, .nil => fun h => + truthVal_ne_pt True ((truthVal_eq_unitSet trivial).trans h) + | _, .cons _ _ => sigmaSet_ne_pt + +/-- **The 0-field degeneracy**: the empty tower is `unitSet` at every +level — hence unit-likeness (next lemma) and, at `w = 0`, the correct +truth value `⟦True⟧`. -/ +theorem towerSet_nil {w : Nat} : towerSet w (.nil : TeleS V 0) = unitSet := by + rfl + +/-- Unit-likeness at `n = 0`: any two members are equal. -/ +theorem tower_nil_unitlike {w : Nat} {x y : V} + (hx : x ∈ˢ towerSet w (.nil : TeleS V 0)) + (hy : y ∈ˢ towerSet w (.nil : TeleS V 0)) : x = y := + (mem_unitSet_iff.mp hx).trans (mem_unitSet_iff.mp hy).symm + +/-! ## Degeneracy checks (build-time regressions) -/ + +/-- `n = 1`: the terminator makes `projS 0 = sfst` lawful — the sole +field of a one-field tower reads back. -/ +example (a : V) : projS 0 (mkTower [a]) = a := + projS_mkTower 0 [a] (by simp) + +/-- `n = 2`: both indices read back through the one uniform family. -/ +example (a b : V) : projS 0 (mkTower [a, b]) = a ∧ projS 1 (mkTower [a, b]) = b := + ⟨projS_mkTower 0 [a, b] (by simp), projS_mkTower 1 [a, b] (by simp)⟩ + +/-- `n = 0`: the empty tower's sole member is `mkTower []`. -/ +example {w : Nat} {x : V} (hx : x ∈ˢ towerSet w (.nil : TeleS V 0)) : + x = mkTower [] := + mem_unitSet_iff.mp hx + +end Ix.Theory.Model.SetTheory.Tower diff --git a/Ix/Theory/Model/SetTheory/Core.lean b/Ix/Theory/Model/SetTheory/Core.lean new file mode 100644 index 000000000..f6baf1797 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Core.lean @@ -0,0 +1,166 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Core.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +@[expose] public section + +/-! +# The axiomatic core: ZF⁻ plus an ω-chain of Grothendieck universes + +The `SetTheory` class below is the *entire* axiomatic interface of the +consistency proof; every operator and law the model construction uses +(`Ix.Theory/Model/SetTheory/Basic.lean`) is *derived* from it in +`Ix.Theory/Model/SetTheory/Derive/*`, never assumed. + +The set-theoretic axioms are **extensionality, pairing, union, power +set, regularity, the replacement scheme, and an ω-chain of +Grothendieck universes** `univChain 0 ∈ univChain 1 ∈ …` — +universehood stated as the matrix of Tarski's Axiom A (A. Tarski, +*Über unerreichbare Kardinalzahlen*, Fund. Math. 30 (1938), 68–89) +strengthened with a transitivity clause, i.e. as Grothendieck +universes (SGA 4, Exp. I, Appendix). Infinity and choice are +derivable and therefore absent. + +This calibrates the axiomatic strength to exactly what the checker +consumes — the ω-indexed tower `univ 0, univ 1, univ 2, …` — and to +the known consistency strength of Lean itself: ZFC plus a strictly +increasing ω-sequence of inaccessible cardinals — the +`OmegaInaccessibles` hypothesis +`∃ κ : ℕ → Cardinal, StrictMono κ ∧ ∀ n, (κ n).IsInaccessible` +of Mario Carneiro, *The Type Theory of Lean*, master's thesis, +Carnegie Mellon University, 2019, §1.2. Under that hypothesis the intended +model takes `univChain n := V_{κ n}`. This is strictly weaker than +full Tarski–Grothendieck set theory (Tarski's Axiom A places a +universe above *every* set, a proper class of inaccessibles; cf. the +Mizar axiomatics, A. Trybulec, *Tarski Grothendieck Set Theory*, +Formalized Mathematics 1(1), 1990). + +Deliberate deviations from a first-order presentation: + +* **Replacement** is a Lean-level scheme: the image operator takes an + arbitrary function `V → V`. This is the usual strengthening when the + ambient logic can quantify over class functions; `V_κ` for `κ` + inaccessible still satisfies it. +* **Choice is not a field.** A first-order axiomatization must assert + choice; here the ambient logic is Lean with `Classical.choice`, and + every set-level form of choice over `V` (the global selector + `schoice`, and the Jech-form choice-function statement, *Set Theory*, + §5) is a *theorem* — replacement applied to a classically chosen + selector. See `Ix.Theory/Model/SetTheory/Derive/Choice.lean`. Asserting it + here would add redundant axiomatic content; global choice is supplied + by the meta-logic, not by this class. +* **No `nonempty` field.** First-order logic's nonempty domain is + implied: `univChain` already exhibits elements of `V`. + +Everything else — the empty set, separation, ordered pairs, infinity, +function graphs, the universe tower, quotients — is constructed in +`Ix.Theory/Model/SetTheory/Derive/*`. +-/ + +namespace Ix.Theory.Model + +universe u + +/-- `y` and `u` are equinumerous: some (meta-level) function restricts to +a bijection from the members of `y` onto the members of `u`. This is the +notion Tarski's Axiom A is stated with; using a Lean-level function keeps +ordered pairs out of the core (a first-order presentation instead +describes set-level bijections by formulas). For the intended models this is +equivalent: a set-level bijection yields a meta-level one by choice, and +the axiom's disjunction is only ever *used* by refuting this side via a +diagonal argument (`Derive/Universe.lean`). -/ +def Equinumerous {V : Type u} (mem : V → V → Prop) (y u : V) : Prop := + ∃ f : V → V, + (∀ z, mem z y → mem (f z) u) ∧ + (∀ z z', mem z y → mem z' y → f z = f z' → z = z') ∧ + (∀ w, mem w u → ∃ z, mem z y ∧ f z = w) + +/-- The matrix of Tarski's Axiom A (Tarski 1938), strengthened with the +transitivity clause: `u` is a Grothendieck universe (SGA 4, Exp. I, +Appendix). The four clauses, in order: + +1. *transitivity*: members of members are members — the clause that + distinguishes a Grothendieck universe from a bare Tarski one, and + what makes the empty set fall out of regularity; +2. *subsets of members are members*; +3. *power sets stay inside*: some member contains all subsets of a + member (with clause 2 this makes `power y` itself a member); +4. *inaccessibility*: a subset of `u` is equinumerous with `u` or a + member. Dropping the equinumerosity disjunct is **inconsistent** + (`u ⊆ u` would force `u ∈ u`, against regularity). -/ +def IsTGUniverse {V : Type u} (mem : V → V → Prop) (u : V) : Prop := + (∀ y z, mem y u → mem z y → mem z u) ∧ + (∀ y z, mem y u → (∀ w, mem w z → mem w y) → mem z u) ∧ + (∀ y, mem y u → ∃ p, mem p u ∧ ∀ z, (∀ w, mem w z → mem w y) → mem z p) ∧ + (∀ y, (∀ w, mem w y → mem w u) → Equinumerous mem y u ∨ mem y u) + +/-- A model of set theory of exactly the strength the checker needs: +membership, the six ZF⁻ axioms (extensionality, pairing, union, power +set, regularity, Lean-level replacement), and an ω-chain of +Grothendieck universes. Infinity is derivable; choice is inherited +from the meta-logic (`Classical.choice`); see the module docstring. -/ +class SetTheory (V : Type u) where + /-- Set membership. -/ + Mem : V → V → Prop + /-- Extensionality: sets with the same members are equal. -/ + ext : ∀ {x y : V}, (∀ z, Mem z x ↔ Mem z y) → x = y + /-- Pairing: the unordered pair. -/ + upair : V → V → V + /-- Characterization of the unordered pair. -/ + mem_upair : ∀ {z a b : V}, Mem z (upair a b) ↔ z = a ∨ z = b + /-- Union: the union of the members. -/ + sUnion : V → V + /-- Characterization of the union. -/ + mem_sUnion : ∀ {z x : V}, Mem z (sUnion x) ↔ ∃ y, Mem y x ∧ Mem z y + /-- Power set. -/ + power : V → V + /-- Characterization of the power set: members are the subsets. -/ + mem_power : ∀ {z x : V}, Mem z (power x) ↔ ∀ w, Mem w z → Mem w x + /-- Regularity: every nonempty set has an `∈`-minimal member. -/ + regularity : ∀ x : V, (∃ y, Mem y x) → ∃ y, Mem y x ∧ ¬ ∃ z, Mem z y ∧ Mem z x + /-- Replacement, as a Lean-level scheme: the image of a set under an + arbitrary function `V → V`. -/ + image : (V → V) → V → V + /-- Characterization of the replacement image. -/ + mem_image : ∀ {f : V → V} {a z : V}, Mem z (image f a) ↔ ∃ w, Mem w a ∧ z = f w + /-- An ω-chain of Grothendieck universes: the sets interpreting the + universe tower (Carneiro's ω-many inaccessibles, op. cit.; + intended model `V_{κ n}`). -/ + univChain : Nat → V + /-- The chain increases strictly: each universe is a member of the + next. -/ + univChain_mem : ∀ n : Nat, Mem (univChain n) (univChain (n + 1)) + /-- Each chain member is a Grothendieck universe (Tarski's Axiom A + matrix with transitivity, `IsTGUniverse`). -/ + univChain_tg : ∀ n : Nat, IsTGUniverse Mem (univChain n) + +namespace SetTheory + +@[inherit_doc] scoped infix:50 " ∈ˢ " => Mem + +variable {V : Type u} [SetTheory V] + +/-- Subset, from membership. -/ +protected def Subset (x y : V) : Prop := ∀ z, z ∈ˢ x → z ∈ˢ y + +@[inherit_doc] scoped infix:50 " ⊆ˢ " => SetTheory.Subset + +theorem Subset.refl (x : V) : x ⊆ˢ x := fun _ hz => hz + +theorem Subset.trans {x y z : V} (h₁ : x ⊆ˢ y) (h₂ : y ⊆ˢ z) : x ⊆ˢ z := + fun w hw => h₂ w (h₁ w hw) + +theorem Subset.antisymm {x y : V} (h₁ : x ⊆ˢ y) (h₂ : y ⊆ˢ x) : x = y := + ext fun z => ⟨h₁ z, h₂ z⟩ + +theorem mem_power_iff_subset {z x : V} : z ∈ˢ power x ↔ z ⊆ˢ x := mem_power + +end SetTheory + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/SetTheory/Derive/Choice.lean b/Ix/Theory/Model/SetTheory/Derive/Choice.lean new file mode 100644 index 000000000..1b58066b5 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Choice.lean @@ -0,0 +1,75 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Choice.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Graphs + +@[expose] public section + +/-! +# Choice: the global selector, and the eighth axiom as a theorem + +A first-order development of Tarski–Grothendieck set theory asserts (or +derives from Axiom A) an axiom of choice, because it cannot reach the +meta-level. Here the meta-logic is Lean with `Classical.choice`, so +choice over `V` is *derived*: + +* `schoice : V → V` — a global selector, `schoice A ∈ A` whenever `A` + is inhabited (Lean-level choice on the membership predicate); +* `set_choice` — the Jech-form statement (*Set Theory*, §5): every + family has a *set* choice function, obtained as the replacement + graph of `schoice`, spelled through `kpair` as a single-valued set + of ordered pairs. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +open Classical in +/-- Global choice: a uniform selection from nonempty sets. On sets +without members (and only there) it returns the set itself. -/ +noncomputable def schoice (A : V) : V := + if h : ∃ x, x ∈ˢ A then Classical.choose h else A + +theorem schoice_mem {A x : V} (hx : x ∈ˢ A) : schoice A ∈ˢ A := by + unfold schoice + rw [dif_pos ⟨x, hx⟩] + exact Classical.choose_spec (⟨x, hx⟩ : ∃ x, x ∈ˢ A) + +/-- The axiom of choice, Jech-form, as a theorem: every family `X` has +a set-level choice function — a single-valued set of pairs, total on +`X`, selecting a member from every inhabited `A ∈ X`. -/ +theorem set_choice (X : V) : + ∃ f : V, + (∀ A c, kpair A c ∈ˢ f → A ∈ˢ X) ∧ + (∀ A, A ∈ˢ X → ∃ c, kpair A c ∈ˢ f ∧ ∀ c', kpair A c' ∈ˢ f → c' = c) ∧ + (∀ A c, kpair A c ∈ˢ f → (∃ x, x ∈ˢ A) → c ∈ˢ A) := by + refine ⟨graph schoice X, ?_, ?_, ?_⟩ + · intro A c hp + obtain ⟨A', hA', hp'⟩ := mem_graph.mp hp + obtain ⟨rfl, -⟩ := kpair_inj hp' + exact hA' + · intro A hA + refine ⟨schoice A, mem_graph.mpr ⟨A, hA, rfl⟩, ?_⟩ + intro c' hc' + obtain ⟨A', -, hp'⟩ := mem_graph.mp hc' + obtain ⟨rfl, rfl⟩ := kpair_inj hp' + rfl + · intro A c hp ⟨x, hx⟩ + obtain ⟨A', -, hp'⟩ := mem_graph.mp hp + obtain ⟨rfl, rfl⟩ := kpair_inj hp' + exact schoice_mem hx + +/- Opaque interface operator (see `Derive/Empty.lean`). -/ +attribute [irreducible] schoice + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Empty.lean b/Ix/Theory/Model/SetTheory/Derive/Empty.lean new file mode 100644 index 000000000..2c202a614 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Empty.lean @@ -0,0 +1,79 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Empty.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Core + +@[expose] public section + +/-! +# The empty set, derived + +The transitivity clause in `IsTGUniverse` makes this cheap — +`univChain 1` is inhabited (by `univChain 0`) and transitive, so +regularity's `∈`-minimal member of it has no members at all. + +Also here: the small consequences of regularity everything downstream +wants — `x ∉ x` and the impossibility of membership 2-cycles. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +theorem empty_exists : ∃ e : V, ∀ z, ¬ z ∈ˢ e := by + obtain ⟨htrans, -, -, -⟩ := univChain_tg (V := V) 1 + obtain ⟨y, hy, hmin⟩ := + regularity (univChain (V := V) 1) ⟨univChain 0, univChain_mem 0⟩ + exact ⟨y, fun z hz => hmin ⟨z, hz, htrans y z hy hz⟩⟩ + +/-- The empty set. -/ +noncomputable def empty : V := Classical.choose empty_exists + +theorem not_mem_empty (z : V) : ¬ z ∈ˢ (empty : V) := + Classical.choose_spec empty_exists z + +theorem eq_empty {x : V} (h : ∀ z, ¬ z ∈ˢ x) : x = empty := + ext fun z => ⟨fun hz => absurd hz (h z), fun hz => absurd hz (not_mem_empty z)⟩ + +theorem eq_empty_iff {x : V} : x = empty ↔ ∀ z, ¬ z ∈ˢ x := + ⟨fun h z => h ▸ not_mem_empty z, eq_empty⟩ + +theorem ne_empty_of_mem {x z : V} (h : z ∈ˢ x) : x ≠ empty := + fun he => not_mem_empty z (he ▸ h) + +theorem nonempty_of_ne_empty {x : V} (h : x ≠ empty) : ∃ z, z ∈ˢ x := + Classical.byContradiction fun hn => h (eq_empty fun z hz => hn ⟨z, hz⟩) + +theorem empty_subset (x : V) : (empty : V) ⊆ˢ x := + fun z hz => absurd hz (not_mem_empty z) + +/-- No set is a member of itself (regularity at `{x}`). -/ +theorem not_mem_self (x : V) : ¬ x ∈ˢ x := by + intro hx + obtain ⟨y, hy, hmin⟩ := regularity (upair x x) ⟨x, mem_upair.mpr (Or.inl rfl)⟩ + have hyx : y = x := by rcases mem_upair.mp hy with h | h <;> exact h + subst hyx + exact hmin ⟨y, hx, mem_upair.mpr (Or.inl rfl)⟩ + +/- Interface operators are opaque from here on (as the legacy class +projections were): consumers reason only through the laws, never by +unfolding. Everything above this line may use the definition. -/ +attribute [irreducible] empty + +/-- No membership 2-cycles (regularity at `{a, b}`). -/ +theorem no_two_cycle {a b : V} (hab : a ∈ˢ b) (hba : b ∈ˢ a) : False := by + obtain ⟨y, hy, hmin⟩ := regularity (upair a b) ⟨a, mem_upair.mpr (Or.inl rfl)⟩ + rcases mem_upair.mp hy with h | h <;> subst h + · exact hmin ⟨b, hba, mem_upair.mpr (Or.inr rfl)⟩ + · exact hmin ⟨a, hab, mem_upair.mpr (Or.inl rfl)⟩ + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Graphs.lean b/Ix/Theory/Model/SetTheory/Derive/Graphs.lean new file mode 100644 index 000000000..4449e747b --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Graphs.lean @@ -0,0 +1,252 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Graphs.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Pt + +@[expose] public section + +/-! +# Function graphs, application, and the raw dependent-function set + +* `graph F A = {⟨x, F x⟩ : x ∈ A}` — the set-theoretic function graph + (replacement); never equal to `pt`, since `pt`'s element `ptTag` has + an empty member and so is not a Kuratowski pair. +* `app f a = ⋃ {y : ⟨a, y⟩ ∈ f}` — untagged application on non-`pt` + arguments; `app pt a = pt` is the tag that makes proofs degenerate + (`app_pt` in the `SetTheory` interface). +* `sigmaPairs A B = {⟨x, y⟩ : x ∈ A, y ∈ B x}` — the raw dependent + pair set (also the `w ≠ 0` sigma). +* `piSet A B ⊆ power (sigmaPairs A B)` — the total single-valued + graphs: the `v ≠ 0` dependent product. + +The level-`0` truncations (`lam 0 = pt`, `pi 0` a truth value) were +layered on top in `Derive/Pi.lean`, deleted at task #221: the model +reads the *annotation-driven* `piR`/`lamR` (`SetModel/Ops.lean`), which +dispatch on the annotation instead of collapsing. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The function graph `{⟨x, F x⟩ : x ∈ A}`. -/ +noncomputable def graph (F : V → V) (A : V) : V := + image (fun x => kpair x (F x)) A + +theorem mem_graph {F : V → V} {A p : V} : + p ∈ˢ graph F A ↔ ∃ x, x ∈ˢ A ∧ p = kpair x (F x) := mem_image + +theorem graph_ne_pt {F : V → V} {A : V} : graph F A ≠ (pt : V) := by + intro h + obtain ⟨x, -, hx⟩ := + mem_graph.mp (h ▸ ptTag_mem_pt : (ptTag : V) ∈ˢ graph F A) + exact ptTag_ne_kpair x (F x) hx + +theorem graph_congr {F F' : V → V} {A : V} (h : ∀ x, x ∈ˢ A → F x = F' x) : + graph F A = graph F' A := + image_congr fun x hx => by rw [h x hx] + +open Classical in +/-- Tagged set-theoretic application: the union of the values paired +with `a` in `f` — except at the proof point, which applies to `pt` +again. -/ +noncomputable def app (f a : V) : V := + if f = pt then pt else sUnion (sep (sUnion (sUnion f)) (fun y => kpair a y ∈ˢ f)) + +theorem app_pt (a : V) : app (pt : V) a = pt := by + unfold app; exact if_pos rfl + +/-- Application computes on single-valued positions. -/ +theorem app_eq_of_unique {f a b : V} (hf : f ≠ pt) (hab : kpair a b ∈ˢ f) + (huniq : ∀ y, kpair a y ∈ˢ f → y = b) : app f a = b := by + unfold app + rw [if_neg hf] + have : sep (sUnion (sUnion f)) (fun y => kpair a y ∈ˢ f) = sing b := by + apply ext fun z => ?_ + rw [mem_sep, mem_sing] + constructor + · exact fun ⟨_, hz⟩ => huniq z hz + · rintro rfl + refine ⟨?_, hab⟩ + exact mem_sUnion.mpr ⟨upair a z, mem_sUnion.mpr ⟨kpair a z, hab, mem_upair_right _ _⟩, + mem_upair_right a z⟩ + rw [this, sUnion_sing] + +/-- Beta on graphs. -/ +theorem app_graph {F : V → V} {A a : V} (ha : a ∈ˢ A) : + app (graph F A) a = F a := by + refine app_eq_of_unique graph_ne_pt (mem_graph.mpr ⟨a, ha, rfl⟩) ?_ + intro y hy + obtain ⟨x, -, hx⟩ := mem_graph.mp hy + obtain ⟨rfl, rfl⟩ := kpair_inj hx + rfl + +/-- The raw dependent pair set `{⟨x, y⟩ : x ∈ A, y ∈ B x}`. -/ +noncomputable def sigmaPairs (A : V) (B : V → V) : V := + sUnion (image (fun x => image (fun y => kpair x y) (B x)) A) + +theorem mem_sigmaPairs {A p : V} {B : V → V} : + p ∈ˢ sigmaPairs A B ↔ ∃ x, x ∈ˢ A ∧ ∃ y, y ∈ˢ B x ∧ p = kpair x y := by + unfold sigmaPairs + rw [mem_sUnion] + constructor + · rintro ⟨s, hs, hps⟩ + obtain ⟨x, hx, rfl⟩ := mem_image.mp hs + obtain ⟨y, hy, rfl⟩ := mem_image.mp hps + exact ⟨x, hx, y, hy, rfl⟩ + · rintro ⟨x, hx, y, hy, rfl⟩ + exact ⟨image (fun y => kpair x y) (B x), mem_image.mpr ⟨x, hx, rfl⟩, + mem_image.mpr ⟨y, hy, rfl⟩⟩ + +theorem sigmaPairs_congr {A : V} {B B' : V → V} + (h : ∀ x, x ∈ˢ A → B x = B' x) : sigmaPairs A B = sigmaPairs A B' := by + unfold sigmaPairs + congr 1 + exact image_congr fun x hx => by rw [h x hx] + +theorem _root_.Ix.Theory.Model.IsTGUniverse.sigmaPairs_mem {U A : V} {B : V → V} + (hU : IsTGUniverse (Mem (V := V)) U) (hA : A ∈ˢ U) + (hB : ∀ x, x ∈ˢ A → B x ∈ˢ U) : sigmaPairs A B ∈ˢ U := + hU.famUnion_mem hA fun x hx => + hU.image_mem (hB x hx) fun _y hy => + hU.kpair_mem hA (hU.transitive hA hx) (hU.transitive (hB x hx) hy) + +/-- The set of total single-valued dependent graphs on `A` with fibres +`B`: the `v ≠ 0` dependent product. -/ +noncomputable def piSet (A : V) (B : V → V) : V := + sep (power (sigmaPairs A B)) + (fun f => ∀ x, x ∈ˢ A → ∃ y, kpair x y ∈ˢ f ∧ ∀ y', kpair x y' ∈ˢ f → y' = y) + +theorem mem_piSet {A f : V} {B : V → V} : + f ∈ˢ piSet A B ↔ f ⊆ˢ sigmaPairs A B ∧ + ∀ x, x ∈ˢ A → ∃ y, kpair x y ∈ˢ f ∧ ∀ y', kpair x y' ∈ˢ f → y' = y := by + unfold piSet + rw [mem_sep, mem_power_iff_subset] + +theorem piSet_congr {A : V} {B B' : V → V} + (h : ∀ x, x ∈ˢ A → B x = B' x) : piSet A B = piSet A B' := by + unfold piSet + rw [sigmaPairs_congr h] + +theorem _root_.Ix.Theory.Model.IsTGUniverse.piSet_mem {U A : V} {B : V → V} + (hU : IsTGUniverse (Mem (V := V)) U) (hA : A ∈ˢ U) + (hB : ∀ x, x ∈ˢ A → B x ∈ˢ U) : piSet A B ∈ˢ U := + hU.mem_of_subset_mem (hU.power_mem (hU.sigmaPairs_mem hA hB)) sep_subset + +theorem graph_mem_piSet {A : V} {B F : V → V} + (hF : ∀ x, x ∈ˢ A → F x ∈ˢ B x) : graph F A ∈ˢ piSet A B := by + rw [mem_piSet] + constructor + · intro p hp + obtain ⟨x, hx, rfl⟩ := mem_graph.mp hp + exact mem_sigmaPairs.mpr ⟨x, hx, F x, hF x hx, rfl⟩ + · intro x hx + refine ⟨F x, mem_graph.mpr ⟨x, hx, rfl⟩, ?_⟩ + intro y' hy' + obtain ⟨x', -, hx'⟩ := mem_graph.mp hy' + obtain ⟨rfl, rfl⟩ := kpair_inj hx' + rfl + +theorem ne_pt_of_mem_piSet {A f : V} {B : V → V} (hf : f ∈ˢ piSet A B) : + f ≠ pt := by + rintro rfl + have := (mem_piSet.mp hf).1 ptTag ptTag_mem_pt + obtain ⟨x, -, y, -, hy⟩ := mem_sigmaPairs.mp this + exact ptTag_ne_kpair x y hy + +theorem app_mem_of_mem_piSet {A f a : V} {B : V → V} + (hf : f ∈ˢ piSet A B) (ha : a ∈ˢ A) : app f a ∈ˢ B a := by + obtain ⟨hsub, htot⟩ := mem_piSet.mp hf + obtain ⟨y, hy, huniq⟩ := htot a ha + rw [app_eq_of_unique (ne_pt_of_mem_piSet hf) hy huniq] + obtain ⟨x', -, y', hy', hp⟩ := mem_sigmaPairs.mp (hsub _ hy) + obtain ⟨rfl, rfl⟩ := kpair_inj hp + exact hy' + +/-- Eta: a member of `piSet A B` is the graph of its own application. -/ +theorem eq_graph_app_of_mem_piSet {A f : V} {B : V → V} + (hf : f ∈ˢ piSet A B) : graph (fun x => app f x) A = f := by + obtain ⟨hsub, htot⟩ := mem_piSet.mp hf + apply ext fun p => ?_ + rw [mem_graph] + constructor + · rintro ⟨x, hx, rfl⟩ + obtain ⟨y, hy, huniq⟩ := htot x hx + rwa [app_eq_of_unique (ne_pt_of_mem_piSet hf) hy huniq] + · intro hp + obtain ⟨x, hx, y, -, rfl⟩ := mem_sigmaPairs.mp (hsub p hp) + obtain ⟨y', hy', huniq⟩ := htot x hx + refine ⟨x, hx, ?_⟩ + rw [app_eq_of_unique (ne_pt_of_mem_piSet hf) hy' huniq, huniq y hp] + +/-- Members of `piSet A' B` that are graphs over `A` pin the domain: +every `x ∈ A'` lies in `A`. -/ +theorem graph_dom_of_mem_piSet {A A' : V} {B F : V → V} + (hf : graph F A ∈ˢ piSet A' B) : ∀ x, x ∈ˢ A' → x ∈ˢ A := by + intro x hx + obtain ⟨y, hy, -⟩ := (mem_piSet.mp hf).2 x hx + obtain ⟨x', hx', hp⟩ := mem_graph.mp hy + obtain ⟨rfl, rfl⟩ := kpair_inj hp + exact hx' + +/-! ### Off-domain and junk behavior of `app` + +`app` is total: on a non-`pt` value with no pair at the argument — +in particular off a graph's domain, or on the canonical junk value +`empty` itself — it returns `empty`. These lemmas record that a +graph's off-domain behavior is *canonical*: two graphs over the same +domain that agree on the domain agree everywhere, which is what makes +a **total** equality between interpreted function towers equivalent to +pointwise agreement on fitting inputs (`eq_of_mem_piSet_app_eq`, and +`eq_of_mem_pi_app_eq`, deleted with `Derive/Pi.lean` at task #221). -/ + +theorem app_eq_empty_of_not_mem {f a : V} (hf : f ≠ pt) + (h : ∀ y, ¬ kpair a y ∈ˢ f) : app f a = empty := by + unfold app + rw [if_neg hf] + refine eq_empty fun z hz => ?_ + obtain ⟨y, hy, -⟩ := mem_sUnion.mp hz + exact h y (mem_sep.mp hy).2 + +/-- `app` off a graph's domain is the canonical junk value. -/ +theorem app_graph_of_not_mem {F : V → V} {A a : V} (ha : ¬ a ∈ˢ A) : + app (graph F A) a = empty := by + refine app_eq_empty_of_not_mem graph_ne_pt fun y hy => ?_ + obtain ⟨x, hx, hp⟩ := mem_graph.mp hy + obtain ⟨rfl, rfl⟩ := kpair_inj hp + exact ha hx + +/-- `app` on the canonical junk value returns junk: junk propagates +through applications. -/ +theorem app_empty (a : V) : app (empty : V) a = empty := + app_eq_empty_of_not_mem (Ne.symm pt_ne_empty) + (fun _y hy => not_mem_empty _ hy) + +/-- A member of `piSet` applied off the domain is junk. -/ +theorem app_off_dom_of_mem_piSet {A f a : V} {B : V → V} + (hf : f ∈ˢ piSet A B) (ha : ¬ a ∈ˢ A) : app f a = empty := by + rw [← eq_graph_app_of_mem_piSet hf, app_graph_of_not_mem ha] + +/-- Function extensionality for members of the raw dependent product: +two total single-valued graphs over the same domain that agree under +application on every domain member are equal (off the domain both +apply to canonical junk, so nothing else distinguishes them). -/ +theorem eq_of_mem_piSet_app_eq {A f g : V} {B B' : V → V} + (hf : f ∈ˢ piSet A B) (hg : g ∈ˢ piSet A B') + (h : ∀ x, x ∈ˢ A → app f x = app g x) : f = g := by + rw [← eq_graph_app_of_mem_piSet hf, ← eq_graph_app_of_mem_piSet hg] + exact graph_congr h + +/- Opaque interface operator (see `Derive/Empty.lean`). -/ +attribute [irreducible] app + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Lfp.lean b/Ix/Theory/Model/SetTheory/Derive/Lfp.lean new file mode 100644 index 000000000..be3793ea7 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Lfp.lean @@ -0,0 +1,162 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Lfp.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Univ + +@[expose] public section + +/-! +# Least pre-fixed points inside a universe (task #188) + +The carrier of a directly installed **recursive** inductive type is the +Knaster–Tarski least pre-fixed point of its constructor-tower functor, +taken *inside* a universe: + + lfpSet w F = ⋂ { X ∈ univ w | F X ⊆ X } + +where `F` is a set-level function (a graph over `univ w`, so `F X` is +`app F X`). The intersection is realised as a separation over a +(classically chosen) closed member — `{x ∈ L₀ | x lies in every +`F`-closed member of `univ w`}` — so it is a set, and a *subset of a +member* of `univ w`, hence a member. When NO closed member exists the +definition returns the empty set instead. That junk value is what +makes the operator **total** at the type `(Sort w → Sort w) → Sort w`: +`lfpSet w F ∈ univ w` for every `F` (`lfpSet_mem_univ`), so the basis +constant `lfp` needs no certificate argument. Every LAW below assumes +a closed member exists (`∃ L, IsClosedIn w F L`) — the semantic side +exhibits one (the ω-iterate of a finitary tower functor, +`Ix.Theory/Model/SetModel/Iter.lean`). + +Under that hypothesis and monotonicity the standard facts hold: the +least pre-fixed point is a fixed point (`lfpSet_closed`, +`lfpSet_fixed`), and it is contained in every closed member +(`lfpSet_subset`) — which IS structural induction (`lfpSet_induction`): +a property closed under the functor holds on the whole carrier. No +rank, no ordinal, no iteration is consulted by the recursor's laws. + +The RECURSOR of a recursive type needs no operator of its own: it is a +fixed point of its one-step unfolding, selected by the basis +`Classical.choice` from the (spelled) sigma type of fixed points +(`Ix.Theory/Model/Semantics/Tower/FixRec.lean`). + +Everything here is over the bare `SetTheory` interface; no syntax. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-! ## Universe helpers -/ + +/-- A subset of a member of `univ w` is a member: at `w = 0` members of +`univZero` are the subsets of `unitSet`; above, the Grothendieck +clause. -/ +theorem univ_mem_of_subset_mem {w : Nat} {y z : V} (hy : y ∈ˢ (univ w : V)) (hz : z ⊆ˢ y) : + z ∈ˢ (univ w : V) := by + rcases Nat.eq_zero_or_pos w with rfl | hw + · rw [univ_zero] at hy ⊢ + rw [mem_univZero] at hy ⊢ + exact hz.trans hy + · exact (univ_isTGUniverse (Nat.pos_iff_ne_zero.mp hw)).mem_of_subset_mem hy hz + +/-- Separation stays inside every level. -/ +theorem univ_sep_mem {w : Nat} {a : V} {p : V → Prop} (ha : a ∈ˢ (univ w : V)) : + sep a p ∈ˢ (univ w : V) := + univ_mem_of_subset_mem ha sep_subset + +/-! ## The least pre-fixed point -/ + +/-- An `F`-closed member of `univ w`: a pre-fixed point of `app F`. -/ +def IsClosedIn (w : Nat) (F X : V) : Prop := + X ∈ˢ (univ w : V) ∧ app F X ⊆ˢ X + +open Classical in +/-- **The least pre-fixed point of `F` inside `univ w`** — the +intersection of the `F`-closed members of `univ w` when there is one +(separated from a chosen closed member), the empty set otherwise (see +the module docstring). -/ +noncomputable def lfpSet (w : Nat) (F : V) : V := + if h : ∃ L, IsClosedIn w F L then + sep (Classical.choose h) (fun x => ∀ X, IsClosedIn w F X → x ∈ˢ X) + else empty + +theorem lfpSet_of_not {w : Nat} {F : V} (h : ¬ ∃ L, IsClosedIn w F L) : + lfpSet w F = empty := by + unfold lfpSet; exact dif_neg h + +theorem mem_lfpSet {w : Nat} {F x : V} (h : ∃ L, IsClosedIn w F L) : + x ∈ˢ lfpSet w F ↔ ∀ X, IsClosedIn w F X → x ∈ˢ X := by + unfold lfpSet + rw [dif_pos h, mem_sep] + exact ⟨fun hx => hx.2, fun hx => ⟨hx _ (Classical.choose_spec h), hx⟩⟩ + +/-- **Leastness**: the least pre-fixed point lies in every closed +member. -/ +theorem lfpSet_subset {w : Nat} {F X : V} (hX : IsClosedIn w F X) : lfpSet w F ⊆ˢ X := + fun _x hx => (mem_lfpSet ⟨X, hX⟩).mp hx X hX + +/-- **Formation, unconditional**: the least pre-fixed point is a member +of the universe — a subset of a closed member when there is one, the +empty set otherwise. -/ +theorem lfpSet_mem_univ (w : Nat) (F : V) : lfpSet w F ∈ˢ (univ w : V) := by + by_cases h : ∃ L, IsClosedIn w F L + · obtain ⟨L, hL⟩ := h + exact univ_mem_of_subset_mem hL.1 (lfpSet_subset hL) + · rw [lfpSet_of_not h]; exact empty_mem_univ w + +/-- Monotonicity of a set-level functor on the universe. -/ +def MonoIn (w : Nat) (F : V) : Prop := + ∀ X Y, X ∈ˢ (univ w : V) → Y ∈ˢ (univ w : V) → X ⊆ˢ Y → app F X ⊆ˢ app F Y + +/-- The functor maps the universe into itself. -/ +def MapsIn (w : Nat) (F : V) : Prop := + ∀ X, X ∈ˢ (univ w : V) → app F X ∈ˢ (univ w : V) + +/-- **Closure**: the least pre-fixed point is a pre-fixed point. -/ +theorem lfpSet_closed {w : Nat} {F : V} (h : ∃ L, IsClosedIn w F L) + (hmono : MonoIn w F) : app F (lfpSet w F) ⊆ˢ lfpSet w F := by + intro x hx + rw [mem_lfpSet h] + intro X hX + exact hX.2 x (hmono _ _ (lfpSet_mem_univ w F) hX.1 (lfpSet_subset hX) x hx) + +/-- **The fixed-point equation's other half**: the least pre-fixed +point is a post-fixed point, because its image is itself closed. -/ +theorem lfpSet_fixed {w : Nat} {F : V} (h : ∃ L, IsClosedIn w F L) + (hmono : MonoIn w F) (hmaps : MapsIn w F) : lfpSet w F ⊆ˢ app F (lfpSet w F) := by + refine lfpSet_subset ⟨hmaps _ (lfpSet_mem_univ w F), ?_⟩ + exact hmono _ _ (hmaps _ (lfpSet_mem_univ w F)) (lfpSet_mem_univ w F) + (lfpSet_closed h hmono) + +/-- The fixed-point equation. -/ +theorem lfpSet_eq {w : Nat} {F : V} (h : ∃ L, IsClosedIn w F L) + (hmono : MonoIn w F) (hmaps : MapsIn w F) : app F (lfpSet w F) = lfpSet w F := + Subset.antisymm (lfpSet_closed h hmono) (lfpSet_fixed h hmono hmaps) + +/-- **Structural induction**: a property closed under the functor on +the carrier holds on the whole carrier — the members of the carrier +satisfying it form a closed member of the universe, in which the +carrier lies by leastness. -/ +theorem lfpSet_induction {w : Nat} {F : V} (h : ∃ L, IsClosedIn w F L) + (hmono : MonoIn w F) (P : V → Prop) + (hP : ∀ x, x ∈ˢ app F (sep (lfpSet w F) P) → P x) : + ∀ x, x ∈ˢ lfpSet w F → P x := by + intro x hx + have hS : IsClosedIn w F (sep (lfpSet w F) P) := by + refine ⟨univ_sep_mem (lfpSet_mem_univ w F), fun y hy => ?_⟩ + rw [mem_sep] + refine ⟨?_, hP y hy⟩ + exact lfpSet_closed h hmono y + (hmono _ _ (univ_sep_mem (lfpSet_mem_univ w F)) (lfpSet_mem_univ w F) sep_subset y hy) + exact (mem_sep.mp (lfpSet_subset hS x hx)).2 + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/LfpFam.lean b/Ix/Theory/Model/SetTheory/Derive/LfpFam.lean new file mode 100644 index 000000000..7123ed505 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/LfpFam.lean @@ -0,0 +1,170 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/LfpFam.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Lfp +import Ix.Theory.Model.SetTheory.Derive.Graphs +@[expose] public section + +/-! +# Least pre-fixed points of family functors (task #188, indexed) + +The carrier of a directly installed recursive **family** `T : I → Sort w` +is the least pre-fixed point of its constructor-tower functor acting on +FAMILIES — graphs over the index-tuple set `I` with values in `univ w` +(`famSpace`), ordered pointwise (`FamLe`). This is `Lfp.lean` fibrewise: + + lfpFamSet w I F = i ↦ {x ∈ L₀ i | ∀ closed X, x ∈ X i} + +over a classically chosen closed family `L₀` (the empty family when +there is none — TOTAL, so the basis constant `lfpFam` needs no +certificate: `lfpFamSet_mem`). Under a closed member and monotonicity +the least pre-fixed family is a fixed point (`lfpFamSet_eq`) and +supports fibrewise structural induction (`lfpFamSet_induction`); the +closed member is exhibited by the semantics (the ω-iterate family, per +fibre — `Ix.Theory/Model/SetModel/Iter.lean`'s `natUnion`). + +Everything here is over the bare `SetTheory` interface; no syntax. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The family space over `I`: graphs into `univ w`. -/ +noncomputable def famSpace (w : Nat) (I : V) : V := piSet I fun _ => univ w + +/-- The pointwise order on families over `I`. -/ +def FamLe (I X Y : V) : Prop := ∀ i, i ∈ˢ I → app X i ⊆ˢ app Y i + +theorem FamLe.refl (I X : V) : FamLe I X X := fun _ _ => Subset.refl _ + +theorem FamLe.trans {I X Y Z : V} (h₁ : FamLe I X Y) (h₂ : FamLe I Y Z) : FamLe I X Z := + fun i hi => Subset.trans (h₁ i hi) (h₂ i hi) + +/-- An `F`-closed family: a pre-fixed point of `app F` in the family +space. -/ +def IsClosedFam (w : Nat) (I F X : V) : Prop := + X ∈ˢ famSpace w I ∧ FamLe I (app F X) X + +theorem famSpace_app {w : Nat} {I X i : V} (hX : X ∈ˢ famSpace w I) (hi : i ∈ˢ I) : + app X i ∈ˢ (univ w : V) := + app_mem_of_mem_piSet hX hi + +/-- Members of the family space agreeing pointwise are equal. -/ +theorem famSpace_ext {w : Nat} {I X Y : V} (hX : X ∈ˢ famSpace w I) (hY : Y ∈ˢ famSpace w I) + (h : ∀ i, i ∈ˢ I → app X i = app Y i) : X = Y := + eq_of_mem_piSet_app_eq hX hY h + +/-- A graph with fibres in `univ w` is in the family space. -/ +theorem graph_mem_famSpace {w : Nat} {I : V} {G : V → V} (h : ∀ i, i ∈ˢ I → G i ∈ˢ (univ w : V)) : + graph G I ∈ˢ famSpace w I := + graph_mem_piSet h + +open Classical in +/-- **The least pre-fixed family of `F` over `I`** — fibrewise the +intersection of the closed families when there is one (separated from +a chosen closed family), the empty family otherwise. -/ +noncomputable def lfpFamSet (w : Nat) (I F : V) : V := + if h : ∃ L, IsClosedFam w I F L then + graph (fun i => sep (app (Classical.choose h) i) + (fun x => ∀ X, IsClosedFam w I F X → x ∈ˢ app X i)) I + else graph (fun _ => empty) I + +theorem lfpFamSet_of_not {w : Nat} {I F : V} (h : ¬ ∃ L, IsClosedFam w I F L) : + lfpFamSet w I F = graph (fun _ => empty) I := by + unfold lfpFamSet; exact dif_neg h + +theorem mem_app_lfpFamSet {w : Nat} {I F i x : V} (h : ∃ L, IsClosedFam w I F L) (hi : i ∈ˢ I) : + x ∈ˢ app (lfpFamSet w I F) i ↔ ∀ X, IsClosedFam w I F X → x ∈ˢ app X i := by + unfold lfpFamSet + rw [dif_pos h, app_graph hi, mem_sep] + exact ⟨fun hx => hx.2, fun hx => ⟨hx _ (Classical.choose_spec h), hx⟩⟩ + +/-- **Leastness**: the least pre-fixed family lies in every closed +family. -/ +theorem lfpFamSet_le {w : Nat} {I F X : V} (hX : IsClosedFam w I F X) : + FamLe I (lfpFamSet w I F) X := + fun _ hi _x hx => (mem_app_lfpFamSet ⟨X, hX⟩ hi).mp hx X hX + +/-- **Formation, unconditional**: the least pre-fixed family is in the +family space. -/ +theorem lfpFamSet_mem (w : Nat) (I F : V) : lfpFamSet w I F ∈ˢ famSpace w I := by + by_cases h : ∃ L, IsClosedFam w I F L + · unfold lfpFamSet + rw [dif_pos h] + exact graph_mem_famSpace fun _ hi => + univ_sep_mem (famSpace_app (Classical.choose_spec h).1 hi) + · rw [lfpFamSet_of_not h] + exact graph_mem_famSpace fun _ _ => empty_mem_univ w + +/-- Monotonicity of a family functor on the family space. -/ +def MonoFam (w : Nat) (I F : V) : Prop := + ∀ X Y, X ∈ˢ famSpace w I → Y ∈ˢ famSpace w I → FamLe I X Y → FamLe I (app F X) (app F Y) + +/-- The functor maps the family space into itself. -/ +def MapsFam (w : Nat) (I F : V) : Prop := + ∀ X, X ∈ˢ famSpace w I → app F X ∈ˢ famSpace w I + +/-- **Closure**: the least pre-fixed family is a pre-fixed point. -/ +theorem lfpFamSet_closed {w : Nat} {I F : V} (h : ∃ L, IsClosedFam w I F L) + (hmono : MonoFam w I F) : FamLe I (app F (lfpFamSet w I F)) (lfpFamSet w I F) := by + intro i hi x hx + rw [mem_app_lfpFamSet h hi] + intro X hX + exact hX.2 i hi x (hmono _ _ (lfpFamSet_mem w I F) hX.1 (lfpFamSet_le hX) i hi x hx) + +/-- The least pre-fixed family is a post-fixed point. -/ +theorem lfpFamSet_fixed {w : Nat} {I F : V} (h : ∃ L, IsClosedFam w I F L) + (hmono : MonoFam w I F) (hmaps : MapsFam w I F) : + FamLe I (lfpFamSet w I F) (app F (lfpFamSet w I F)) := by + refine lfpFamSet_le ⟨hmaps _ (lfpFamSet_mem w I F), ?_⟩ + exact hmono _ _ (hmaps _ (lfpFamSet_mem w I F)) (lfpFamSet_mem w I F) + (lfpFamSet_closed h hmono) + +/-- The fixed-point equation, fibrewise. -/ +theorem app_lfpFamSet_eq {w : Nat} {I F : V} (h : ∃ L, IsClosedFam w I F L) + (hmono : MonoFam w I F) (hmaps : MapsFam w I F) {i : V} (hi : i ∈ˢ I) : + app (app F (lfpFamSet w I F)) i = app (lfpFamSet w I F) i := + Subset.antisymm (lfpFamSet_closed h hmono i hi) (lfpFamSet_fixed h hmono hmaps i hi) + +/-- The fixed-point equation. -/ +theorem lfpFamSet_eq {w : Nat} {I F : V} (h : ∃ L, IsClosedFam w I F L) + (hmono : MonoFam w I F) (hmaps : MapsFam w I F) : + app F (lfpFamSet w I F) = lfpFamSet w I F := + famSpace_ext (hmaps _ (lfpFamSet_mem w I F)) (lfpFamSet_mem w I F) + fun _ hi => app_lfpFamSet_eq h hmono hmaps hi + +/-- **Structural induction**, fibrewise: a property closed under the +functor on the carrier holds on the whole carrier. -/ +theorem lfpFamSet_induction {w : Nat} {I F : V} (h : ∃ L, IsClosedFam w I F L) + (hmono : MonoFam w I F) (P : V → V → Prop) + (hP : ∀ i, i ∈ˢ I → ∀ x, + x ∈ˢ app (app F (graph (fun i => sep (app (lfpFamSet w I F) i) (P i)) I)) i → P i x) : + ∀ i, i ∈ˢ I → ∀ x, x ∈ˢ app (lfpFamSet w I F) i → P i x := by + intro i hi x hx + have hSmem : graph (fun i => sep (app (lfpFamSet w I F) i) (P i)) I ∈ˢ famSpace w I := + graph_mem_famSpace fun i hi => univ_sep_mem (famSpace_app (lfpFamSet_mem w I F) hi) + have hSle : FamLe I (graph (fun i => sep (app (lfpFamSet w I F) i) (P i)) I) (lfpFamSet w I F) := by + intro i hi y hy + rw [app_graph hi] at hy + exact (mem_sep.mp hy).1 + have hS : IsClosedFam w I F (graph (fun i => sep (app (lfpFamSet w I F) i) (P i)) I) := by + refine ⟨hSmem, fun i hi y hy => ?_⟩ + rw [app_graph hi, mem_sep] + refine ⟨?_, hP i hi y hy⟩ + exact lfpFamSet_closed h hmono i hi y + (hmono _ _ hSmem (lfpFamSet_mem w I F) hSle i hi y hy) + have := lfpFamSet_le hS i hi x hx + rw [app_graph hi] at this + exact (mem_sep.mp this).2 + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Omega.lean b/Ix/Theory/Model/SetTheory/Derive/Omega.lean new file mode 100644 index 000000000..4eabed9d0 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Omega.lean @@ -0,0 +1,142 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Omega.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Universe + +@[expose] public section + +/-! +# Infinity, derived: the finite ordinals + +Infinity is derived from the universe chain + Replacement: an +*inhabited* Grothendieck universe is an inductive *set* — it contains +`∅` and is closed under the von Neumann successor `n ↦ n ∪ {n}` +(von Neumann 1923) by the pairing/union closures — so `ω` can be +separated out of one as the members of *every* inductive set. +Leastness is then definitional. The inductive universe used is +`univChain 1`: it is inhabited by `univChain 0` (note `univChain 0` +itself need not be — the empty set satisfies `IsTGUniverse` +vacuously). + +`vnat : Nat → V` names the members of `ω` from the meta-level; every +member of `ω` is a unique `vnat k` (`mem_omega_iff`, `vnat_inj`), +which is what makes recursion on `ω` cheap in `Derive/Natrec.lean`. + +`ω` itself is a *member* of any universe that has the inductive +universe `univChain 1` as a member — arranged for the tower in +`Derive/Univ.lean`. (Mere universehood does not suffice: `V_ω` is a +Tarski universe without `ω`.) +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The von Neumann successor `n ∪ {n}`. -/ +noncomputable def vsucc (n : V) : V := binUnion n (sing n) + +theorem mem_vsucc {z n : V} : z ∈ˢ vsucc n ↔ z ∈ˢ n ∨ z = n := by + rw [vsucc, mem_binUnion, mem_sing] + +theorem self_mem_vsucc (n : V) : n ∈ˢ vsucc n := mem_vsucc.mpr (Or.inr rfl) + +theorem vsucc_ne_empty (n : V) : vsucc n ≠ empty := + ne_empty_of_mem (self_mem_vsucc n) + +/-- An inductive set: contains `∅`, closed under the successor. -/ +def Inductive (I : V) : Prop := + (empty : V) ∈ˢ I ∧ ∀ n, n ∈ˢ I → vsucc n ∈ˢ I + +/-- An inhabited Grothendieck universe is an inductive set. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.inductive_self {U y : V} + (hU : IsTGUniverse (Mem (V := V)) U) (hy : y ∈ˢ U) : Inductive U := + ⟨hU.empty_mem hy, fun _n hn => + hU.binUnion_mem hy hn (hU.sing_mem hy hn)⟩ + +theorem univChain_one_inductive : Inductive (univChain 1 : V) := + (univChain_tg 1).inductive_self (univChain_mem 0) + +/-- The finite ordinals: the members of every inductive set, separated +from the inductive universe `univChain 1`. -/ +noncomputable def omega : V := + sep (univChain 1) (fun n => ∀ I : V, Inductive I → n ∈ˢ I) + +theorem mem_omega {n : V} : n ∈ˢ (omega : V) ↔ ∀ I : V, Inductive I → n ∈ˢ I := by + rw [omega, mem_sep] + exact ⟨fun h => h.2, fun h => ⟨h _ univChain_one_inductive, h⟩⟩ + +theorem omega_subset_inductive {I : V} (hI : Inductive I) : (omega : V) ⊆ˢ I := + fun _ hn => mem_omega.mp hn I hI + +theorem omega_inductive : Inductive (omega : V) := by + constructor + · exact mem_omega.mpr fun I hI => hI.1 + · intro n hn + exact mem_omega.mpr fun I hI => hI.2 n (mem_omega.mp hn I hI) + +theorem empty_mem_omega : (empty : V) ∈ˢ omega := omega_inductive.1 + +theorem vsucc_mem_omega {n : V} (hn : n ∈ˢ (omega : V)) : vsucc n ∈ˢ (omega : V) := + omega_inductive.2 n hn + +/-- The `k`-th von Neumann natural. -/ +noncomputable def vnat : Nat → V + | 0 => empty + | k + 1 => vsucc (vnat k) + +theorem vnat_mem_omega : ∀ k, (vnat k : V) ∈ˢ omega + | 0 => empty_mem_omega + | k + 1 => vsucc_mem_omega (vnat_mem_omega k) + +/-- Every finite ordinal is named by a meta-level natural. -/ +theorem mem_omega_iff {n : V} : n ∈ˢ (omega : V) ↔ ∃ k, n = vnat k := by + constructor + · intro hn + have hind : Inductive (sep (omega : V) (fun n => ∃ k, n = vnat k)) := by + constructor + · exact mem_sep.mpr ⟨empty_mem_omega, 0, rfl⟩ + · intro m hm + obtain ⟨hmo, k, rfl⟩ := mem_sep.mp hm + exact mem_sep.mpr ⟨vsucc_mem_omega hmo, k + 1, rfl⟩ + exact (mem_sep.mp (omega_subset_inductive hind n hn)).2 + · rintro ⟨k, rfl⟩ + exact vnat_mem_omega k + +theorem vnat_mem_vnat_of_lt : ∀ {k l : Nat}, k < l → (vnat k : V) ∈ˢ vnat l := by + intro k l hkl + induction l with + | zero => exact absurd hkl (Nat.not_lt_zero k) + | succ l ih => + rcases Nat.lt_succ_iff_lt_or_eq.mp hkl with h | rfl + · exact mem_vsucc.mpr (Or.inl (ih h)) + · exact self_mem_vsucc _ + +theorem vnat_inj {k l : Nat} (h : (vnat k : V) = vnat l) : k = l := by + rcases Nat.lt_trichotomy k l with hlt | heq | hgt + · exact absurd (h ▸ vnat_mem_vnat_of_lt (V := V) hlt) (not_mem_self _) + · exact heq + · exact absurd (h ▸ vnat_mem_vnat_of_lt (V := V) hgt) (not_mem_self _) + +theorem omega_subset_univChain_one : (omega : V) ⊆ˢ univChain 1 := sep_subset + +/-- `ω` is a member of any universe having the inductive universe +`univChain 1` as a member. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.omega_mem {U : V} + (hU : IsTGUniverse (Mem (V := V)) U) (h1 : (univChain 1 : V) ∈ˢ U) : + (omega : V) ∈ˢ U := + hU.mem_of_subset_mem h1 omega_subset_univChain_one + +/- Opaque interface operator (see `Derive/Empty.lean`). `vsucc` stays +reducible: `Derive/Natrec.lean` computes with it through `vnat`. -/ +attribute [irreducible] omega + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Pair.lean b/Ix/Theory/Model/SetTheory/Derive/Pair.lean new file mode 100644 index 000000000..cdaf20257 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Pair.lean @@ -0,0 +1,128 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Pair.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Sep + +@[expose] public section + +/-! +# Singletons, binary unions, and Kuratowski ordered pairs + +Singleton and ordered pair are derived from the unordered pair — the +Kuratowski pair `⟨a, b⟩ := {{a}, {a, b}}` (Kuratowski, Fund. Math. 2 +(1921)); binary union is the union of an unordered pair. The payoff +lemmas are the +injectivity of the Kuratowski pair and the fact that an ordered pair is +never `{∅}` — the tag that keeps the proof point `pt` apart from +function graphs (`Derive/Pt.lean`, `Derive/Graphs.lean`). +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The singleton `{a}`. -/ +noncomputable def sing (a : V) : V := upair a a + +theorem mem_sing {z a : V} : z ∈ˢ sing a ↔ z = a := by + rw [sing, mem_upair]; exact ⟨fun h => h.elim id id, Or.inl⟩ + +theorem sing_inj {a b : V} (h : sing a = sing b) : a = b := + mem_sing.mp (h ▸ mem_sing.mpr rfl) + +theorem sUnion_sing (a : V) : sUnion (sing a) = a := + ext fun z => by + rw [mem_sUnion] + constructor + · rintro ⟨y, hy, hz⟩; rwa [mem_sing.mp hy] at hz + · exact fun hz => ⟨a, mem_sing.mpr rfl, hz⟩ + +/-- Binary union `a ∪ b := ⋃ {a, b}`. -/ +noncomputable def binUnion (a b : V) : V := sUnion (upair a b) + +theorem mem_binUnion {z a b : V} : z ∈ˢ binUnion a b ↔ z ∈ˢ a ∨ z ∈ˢ b := by + rw [binUnion, mem_sUnion] + constructor + · rintro ⟨y, hy, hz⟩ + rcases mem_upair.mp hy with h | h <;> subst h + · exact Or.inl hz + · exact Or.inr hz + · rintro (hz | hz) + · exact ⟨a, mem_upair.mpr (Or.inl rfl), hz⟩ + · exact ⟨b, mem_upair.mpr (Or.inr rfl), hz⟩ + +/-- The Kuratowski ordered pair `⟨a, b⟩ = {{a}, {a, b}}`. -/ +noncomputable def kpair (a b : V) : V := upair (sing a) (upair a b) + +theorem upair_eq_sing {a b c : V} (h : upair a b = sing c) : a = c ∧ b = c := by + constructor + · exact mem_sing.mp (h ▸ mem_upair.mpr (Or.inl rfl)) + · exact mem_sing.mp (h ▸ mem_upair.mpr (Or.inr rfl)) + +theorem mem_upair_left (a b : V) : a ∈ˢ upair a b := mem_upair.mpr (Or.inl rfl) +theorem mem_upair_right (a b : V) : b ∈ˢ upair a b := mem_upair.mpr (Or.inr rfl) + +theorem upair_comm (a b : V) : upair a b = upair b a := + ext fun z => by rw [mem_upair, mem_upair]; exact Or.comm + +/-- First-component injectivity of the Kuratowski pair. -/ +theorem kpair_inj_left {a b c d : V} (h : kpair a b = kpair c d) : a = c := by + have hac : sing a ∈ˢ kpair c d := h ▸ mem_upair_left (sing a) (upair a b) + rcases mem_upair.mp hac with h1 | h1 + · exact sing_inj h1 + · -- `{a} = {c, d}`, so `c = a` (and `d = a`). + obtain ⟨hc, -⟩ := upair_eq_sing (h1.symm) + exact hc.symm + +theorem kpair_inj {a b c d : V} (h : kpair a b = kpair c d) : a = c ∧ b = d := by + obtain rfl : a = c := kpair_inj_left h + refine ⟨rfl, ?_⟩ + -- `{a, b} ∈ {{a}, {a, d}}` and `{a, d} ∈ {{a}, {a, b}}`. + have hb : upair a b ∈ˢ kpair a d := by + rw [← h]; exact mem_upair_right _ _ + have hd : upair a d ∈ˢ kpair a b := by + rw [h]; exact mem_upair_right _ _ + rcases mem_upair.mp hb with h1 | h1 + · -- `{a, b} = {a}`, so `b = a`; then `{a, d}` collapses too, so `d = a = b`. + obtain ⟨-, hba⟩ := upair_eq_sing h1 + rcases mem_upair.mp hd with h2 | h2 + · obtain ⟨-, hda⟩ := upair_eq_sing h2 + exact hba.trans hda.symm + · -- `{a, d} = {a, b}`: `d` is `a` or `b`, and `b = a` closes both. + rcases mem_upair.mp (h2 ▸ mem_upair_right a d) with hda | hdb + · exact hba.trans hda.symm + · exact hdb.symm + · -- `{a, b} = {a, d}`: `b` is `a` or `d`. + rcases mem_upair.mp (h1 ▸ mem_upair_right a b) with hba | hbd + · -- `b = a`; then `d ∈ {a, d} = {a, b} = {a, a}`, so `d = a = b`. + rcases mem_upair.mp (h1.symm ▸ mem_upair_right a d) with hda | hdb + · exact hba.trans hda.symm + · exact hdb.symm + · exact hbd + +theorem kpair_ne_empty {a b : V} : kpair a b ≠ empty := + ne_empty_of_mem (mem_upair_left (sing a) (upair a b)) + +/-- Every member of a Kuratowski pair is nonempty — the fact that keeps +`{∅}` (the proof point) out of the pair/graph world. -/ +theorem mem_kpair_nonempty {a b z : V} (hz : z ∈ˢ kpair a b) : ∃ w, w ∈ˢ z := by + rcases mem_upair.mp hz with h | h <;> subst h + · exact ⟨a, mem_sing.mpr rfl⟩ + · exact ⟨a, mem_upair_left a b⟩ + +theorem mem_sUnion_kpair_left (a b : V) : a ∈ˢ sUnion (kpair a b) := + mem_sUnion.mpr ⟨sing a, mem_upair_left _ _, mem_sing.mpr rfl⟩ + +theorem mem_sUnion_kpair_right (a b : V) : b ∈ˢ sUnion (kpair a b) := + mem_sUnion.mpr ⟨upair a b, mem_upair_right _ _, mem_upair_right a b⟩ + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Pt.lean b/Ix/Theory/Model/SetTheory/Derive/Pt.lean new file mode 100644 index 000000000..4b6bc036a --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Pt.lean @@ -0,0 +1,240 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Pt.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Universe + +@[expose] public section + +/-! +# The proof point, truth values, `univ 0`, and `eqv` + +* `pt := {ptTag}` with `ptTag := {∅, {{∅}}}` — the tagged proof + point: the canonical inhabitant of every true proposition. The tag + is chosen so that **no data-value encoding produces `pt`** (task + #109; the battery was `Derive/PtFresh.lean`, deleted at task #221 with +the collapse it served). Selection principle: + `pt` must be a singleton whose element (a) has an *empty* member — + so neither the tag nor `pt` is a Kuratowski pair, pair elements + being nonempty (the anti-pair tag `Derive/Graphs.lean` exploits, one + level up from the old `pt = {∅}`); (b) is *not a singleton* — else + `pt = {{a}} = kpair a a`, a writable pair value; (c) is not `∅` — + else `pt = {∅} = vnat 1`, a writable numeral (the old collision); + and (d) has members that **cohabit no writable type** — else `pt` is + a writable singleton quotient class (`{2}` = the class of + `Quot.mk (· = 2 ∧ · = 2) 2` killed the `{vnat 2}` candidate). + `ptTag`'s members `∅` and `{{∅}} = kpair ∅ ∅` live in `Nat` resp. + pair types only, and no writable type hosts both. +* `unitSet := {pt}` — the true truth value, and the model of `PUnit`. +* `univZero := power unitSet = {∅, {pt}}` — the set of truth values, + the `U₀ = {∅, {•}}` of Mario Carneiro, *The Type Theory of Lean*, + master's thesis, Carnegie Mellon University, 2019; stating it as a + power set makes + "members of `univ 0` are subsets of `{pt}`" definitional, and + propositional extensionality one application of `ext`. +* `truthVal p` — the truth value of a meta-level proposition, `{pt}` + if `p` holds and `∅` otherwise (classical); `eqv x y` is + `truthVal (x = y)`. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The proof-point tag `{∅, {{∅}}}` (see the module docstring for the +selection principle). -/ +noncomputable def ptTag : V := upair empty (sing (sing empty)) + +theorem mem_ptTag {z : V} : + z ∈ˢ (ptTag : V) ↔ z = empty ∨ z = sing (sing empty) := mem_upair + +theorem empty_mem_ptTag : (empty : V) ∈ˢ ptTag := + mem_ptTag.mpr (Or.inl rfl) + +theorem ptTag_ne_empty : (ptTag : V) ≠ empty := + ne_empty_of_mem empty_mem_ptTag + +/-- The tag is not a singleton: its two members `∅` and `{{∅}}` +differ. (Blocks `pt = kpair a a = {{a}}`.) -/ +theorem ptTag_ne_sing (a : V) : (ptTag : V) ≠ sing a := by + intro h + obtain ⟨h1, h2⟩ := upair_eq_sing h + exact ne_empty_of_mem (mem_sing.mpr rfl) (h2.trans h1.symm) + +/-- The tag is not a Kuratowski pair: `∅` is among its members, while +every member of a pair is nonempty. -/ +theorem ptTag_ne_kpair (a b : V) : (ptTag : V) ≠ kpair a b := by + intro h + obtain ⟨w, hw⟩ := mem_kpair_nonempty (h ▸ empty_mem_ptTag) + exact not_mem_empty w hw + +/-- The proof point `pt = {ptTag}`. -/ +noncomputable def pt : V := sing ptTag + +theorem mem_pt {z : V} : z ∈ˢ (pt : V) ↔ z = ptTag := mem_sing + +theorem ptTag_mem_pt : (ptTag : V) ∈ˢ pt := mem_pt.mpr rfl + +theorem pt_ne_empty : (pt : V) ≠ empty := + ne_empty_of_mem ptTag_mem_pt + +/-- `pt` is not a Kuratowski pair: `pt` is a singleton, so the pair +would be degenerate (`kpair a a = {{a}}`), forcing the tag to be the +singleton `{a}` — which it is not. -/ +theorem pt_ne_kpair (a b : V) : (pt : V) ≠ kpair a b := by + intro h + obtain ⟨h1, -⟩ := upair_eq_sing h.symm + exact ptTag_ne_sing a h1.symm + +/-- `pt` is not a member of its own tag (blocks the two-step membership +cycle `pt ∈ ptTag ∈ pt` that `not_mem_self` cannot see). -/ +theorem pt_not_mem_ptTag : ¬ (pt : V) ∈ˢ ptTag := by + intro h + rcases mem_ptTag.mp h with hpe | hps + · exact pt_ne_empty hpe + · have hm := ptTag_mem_pt (V := V) + rw [hps] at hm + exact ptTag_ne_sing empty (mem_sing.mp hm) + +/-- The canonical singleton `{pt}`: the true truth value. -/ +noncomputable def unitSet : V := sing pt + +theorem mem_unitSet_iff {z : V} : z ∈ˢ (unitSet : V) ↔ z = pt := mem_sing + +theorem pt_mem_unitSet : (pt : V) ∈ˢ unitSet := mem_unitSet_iff.mpr rfl + +theorem unitSet_ne_empty : (unitSet : V) ≠ empty := + ne_empty_of_mem pt_mem_unitSet + +/-- The interpretation of `Sort 0`: the set `{∅, {pt}}` of truth +values, stated as the power set of `{pt}`. -/ +noncomputable def univZero : V := power unitSet + +theorem mem_univZero {T : V} : T ∈ˢ (univZero : V) ↔ T ⊆ˢ unitSet := + mem_power_iff_subset + +/-- Members of `univ 0` have at most the proof point as element. -/ +theorem eq_pt_of_mem_univZero {T x : V} (hT : T ∈ˢ (univZero : V)) + (hx : x ∈ˢ T) : x = pt := + mem_unitSet_iff.mp (mem_univZero.mp hT x hx) + +/-- Propositional extensionality: truth values with the same +`pt`-membership are equal. -/ +theorem univZero_ext {A B : V} (hA : A ∈ˢ (univZero : V)) + (hB : B ∈ˢ (univZero : V)) (hab : pt ∈ˢ A → pt ∈ˢ B) + (hba : pt ∈ˢ B → pt ∈ˢ A) : A = B := + ext fun z => + ⟨fun hz => by + have h := eq_pt_of_mem_univZero hA hz; subst h; exact hab hz, + fun hz => by + have h := eq_pt_of_mem_univZero hB hz; subst h; exact hba hz⟩ + +open Classical in +/-- The truth value of a meta-level proposition: `{pt}` if it holds, +`∅` otherwise. -/ +noncomputable def truthVal (p : Prop) : V := if p then unitSet else empty + +theorem mem_truthVal {p : Prop} {z : V} : + z ∈ˢ (truthVal p : V) ↔ p ∧ z = pt := by + unfold truthVal + split + · next hp => exact ⟨fun hz => ⟨hp, mem_unitSet_iff.mp hz⟩, fun ⟨_, hz⟩ => hz ▸ pt_mem_unitSet⟩ + · next hp => + exact ⟨fun hz => absurd hz (not_mem_empty z), fun ⟨h, _⟩ => absurd h hp⟩ + +theorem pt_mem_truthVal {p : Prop} (hp : p) : (pt : V) ∈ˢ truthVal p := + mem_truthVal.mpr ⟨hp, rfl⟩ + +theorem of_mem_truthVal {p : Prop} {z : V} (hz : z ∈ˢ (truthVal p : V)) : p := + (mem_truthVal.mp hz).1 + +theorem eq_pt_of_mem_truthVal {p : Prop} {z : V} (hz : z ∈ˢ (truthVal p : V)) : + z = pt := + (mem_truthVal.mp hz).2 + +theorem truthVal_eq_unitSet {p : Prop} (hp : p) : (truthVal p : V) = unitSet := by + unfold truthVal; exact if_pos hp + +theorem truthVal_eq_empty {p : Prop} (hp : ¬ p) : (truthVal p : V) = empty := by + unfold truthVal; exact if_neg hp + +/-- Truth values are `∅` or `{pt}` — never the point `{∅}` itself. -/ +theorem truthVal_ne_pt (p : Prop) : (truthVal p : V) ≠ pt := by + intro h + by_cases hp : p + · rw [truthVal_eq_unitSet hp] at h + have hm := pt_mem_unitSet (V := V) + rw [h] at hm + exact not_mem_self (pt : V) hm + · rw [truthVal_eq_empty hp] at h + exact pt_ne_empty h.symm + +theorem truthVal_congr {p q : Prop} (h : p ↔ q) : + (truthVal p : V) = truthVal q := by + rcases Classical.em p with hp | hp + · rw [truthVal_eq_unitSet hp, truthVal_eq_unitSet (h.mp hp)] + · rw [truthVal_eq_empty hp, truthVal_eq_empty (fun hq => hp (h.mpr hq))] + +theorem truthVal_mem_univZero (p : Prop) : + (truthVal p : V) ∈ˢ univZero := by + rcases Classical.em p with hp | hp + · rw [truthVal_eq_unitSet hp] + exact mem_univZero.mpr (Subset.refl _) + · rw [truthVal_eq_empty hp] + exact mem_univZero.mpr (empty_subset _) + +/-- Every member of `univ 0` is the truth value of its own +inhabitedness. -/ +theorem mem_univZero_eq_truthVal {T : V} (hT : T ∈ˢ (univZero : V)) : + T = truthVal (pt ∈ˢ T) := by + rcases Classical.em ((pt : V) ∈ˢ T) with hp | hp + · rw [truthVal_eq_unitSet hp] + exact ext fun z => ⟨fun hz => eq_pt_of_mem_univZero hT hz ▸ pt_mem_unitSet, + fun hz => mem_unitSet_iff.mp hz ▸ hp⟩ + · rw [truthVal_eq_empty hp] + exact eq_empty fun z hz => hp (eq_pt_of_mem_univZero hT hz ▸ hz) + +/-- The truth value of an equality. -/ +noncomputable def eqv (x y : V) : V := truthVal (x = y) + +theorem eqv_mem_univZero (x y : V) : eqv x y ∈ˢ (univZero : V) := + truthVal_mem_univZero _ + +theorem eq_of_mem_eqv {a x y : V} (h : a ∈ˢ eqv x y) : x = y := + of_mem_truthVal h + +theorem pt_mem_eqv_self (x : V) : (pt : V) ∈ˢ eqv x x := + pt_mem_truthVal rfl + +/-- `pt`, `unitSet`, `univZero` and truth values live in every +(inhabited) Grothendieck universe. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.pt_mem {U y : V} + (hU : IsTGUniverse (Mem (V := V)) U) (hy : y ∈ˢ U) : (pt : V) ∈ˢ U := + hU.sing_mem hy (hU.upair_mem hy (hU.empty_mem hy) + (hU.sing_mem hy (hU.sing_mem hy (hU.empty_mem hy)))) + +theorem _root_.Ix.Theory.Model.IsTGUniverse.unitSet_mem {U y : V} + (hU : IsTGUniverse (Mem (V := V)) U) (hy : y ∈ˢ U) : (unitSet : V) ∈ˢ U := + hU.sing_mem hy (hU.pt_mem hy) + +theorem _root_.Ix.Theory.Model.IsTGUniverse.univZero_mem {U y : V} + (hU : IsTGUniverse (Mem (V := V)) U) (hy : y ∈ˢ U) : (univZero : V) ∈ˢ U := + hU.power_mem (hU.unitSet_mem hy) + +theorem _root_.Ix.Theory.Model.IsTGUniverse.truthVal_mem {U y : V} + (hU : IsTGUniverse (Mem (V := V)) U) (hy : y ∈ˢ U) (p : Prop) : + (truthVal p : V) ∈ˢ U := + hU.transitive (hU.univZero_mem hy) (truthVal_mem_univZero p) + +/- Opaque interface operators (see `Derive/Empty.lean`). -/ +attribute [irreducible] ptTag pt unitSet eqv + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Quot.lean b/Ix/Theory/Model/SetTheory/Derive/Quot.lean new file mode 100644 index 000000000..4e2355e72 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Quot.lean @@ -0,0 +1,234 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Quot.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Univ + +@[expose] public section + +/-! +# Quotients + +`quotSet u A R` is, for `u ≠ 0`, the set of equivalence classes of the +equivalence closure of "`app (app R a) b` is inhabited" on `A` (classes +by separation, the class set by replacement); for `u = 0` the base +lives in `Prop`, everything collapses to the proof point, and the +quotient is `image (fun _ => pt) A` — the truth value `[A inhabited]`. + +`quotLift` lifts `f` to the quotient as the graph of +`q ↦ app f (representative of q)` (representatives by choice) — except +when `f` is the proof point, where the lift is the proof point too. +That tag is what makes the beta law `app (quotLift …) (quotClass … a) = +app f a` hold with *no typing premise on `f`* (matching the interface): +a `pt`-tagged `f` beta-reduces to `pt` on both sides, any other `f` +goes through the representative and the invariance premise, with the +`u = 0` collapse handled by `A ⊆ {pt}` (from `A ∈ univ 0`). +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The equivalence closure, on `A`, of "`app (app R a) b` is +inhabited". -/ +inductive QuotRel (A R : V) : V → V → Prop where + | base {a b : V} : a ∈ˢ A → b ∈ˢ A → (∃ w, w ∈ˢ app (app R a) b) → + QuotRel A R a b + | refl {a : V} : a ∈ˢ A → QuotRel A R a a + | symm {a b : V} : QuotRel A R a b → QuotRel A R b a + | trans {a b c : V} : QuotRel A R a b → QuotRel A R b c → QuotRel A R a c + +theorem QuotRel.mem {A R a b : V} (h : QuotRel A R a b) : a ∈ˢ A ∧ b ∈ˢ A := by + induction h with + | base ha hb _ => exact ⟨ha, hb⟩ + | refl ha => exact ⟨ha, ha⟩ + | symm _ ih => exact ⟨ih.2, ih.1⟩ + | trans _ _ ih₁ ih₂ => exact ⟨ih₁.1, ih₂.2⟩ + +/-- The `QuotRel`-class of `a` in `A`. -/ +noncomputable def qclass (A R a : V) : V := sep A (fun b => QuotRel A R a b) + +theorem mem_qclass {A R a b : V} : + b ∈ˢ qclass A R a ↔ b ∈ˢ A ∧ QuotRel A R a b := mem_sep + +theorem self_mem_qclass {A R a : V} (ha : a ∈ˢ A) : a ∈ˢ qclass A R a := + mem_qclass.mpr ⟨ha, QuotRel.refl ha⟩ + +theorem qclass_eq_of_rel {A R a b : V} (h : QuotRel A R a b) : + qclass A R a = qclass A R b := + ext fun z => by + rw [mem_qclass, mem_qclass] + exact ⟨fun ⟨hz, hr⟩ => ⟨hz, (h.symm).trans hr⟩, + fun ⟨hz, hr⟩ => ⟨hz, h.trans hr⟩⟩ + +theorem rel_of_qclass_eq {A R a b : V} (ha : a ∈ˢ A) (_hb : b ∈ˢ A) + (h : qclass A R a = qclass A R b) : QuotRel A R a b := + (mem_qclass.mp (h ▸ self_mem_qclass ha)).2.symm + +open Classical in +/-- The quotient (see module docs). -/ +noncomputable def quotSet (u : Nat) (A R : V) : V := + if u = 0 then image (fun _ => pt) A else image (fun a => qclass A R a) A + +open Classical in +/-- The class of `a` in the quotient. -/ +noncomputable def quotClass (u : Nat) (A R a : V) : V := + if u = 0 then pt else qclass A R a + +theorem quotClass_mem {u : Nat} {A R a : V} (ha : a ∈ˢ A) : + quotClass u A R a ∈ˢ quotSet u A R := by + unfold quotClass quotSet + split + · exact mem_image.mpr ⟨a, ha, rfl⟩ + · exact mem_image.mpr ⟨a, ha, rfl⟩ + +theorem quotClass_surj {u : Nat} {A R q : V} (hq : q ∈ˢ quotSet u A R) : + ∃ a, a ∈ˢ A ∧ q = quotClass u A R a := by + unfold quotSet at hq + unfold quotClass + split at hq + · next h => + obtain ⟨a, ha, rfl⟩ := mem_image.mp hq + exact ⟨a, ha, (if_pos h).symm⟩ + · next h => + obtain ⟨a, ha, rfl⟩ := mem_image.mp hq + exact ⟨a, ha, (if_neg h).symm⟩ + +/-- A class formed at ONE pair of parameters that lands in the quotient +of ANOTHER: its representative lies in the second parameter's carrier, +and the class is the second quotient's class of that same +representative. Nothing relates the two parameter pairs — at a positive +level the first class is a `qclass` of the second's, and at level zero +both classes are the point and the second carrier is inhabited because +the quotient is. -/ +theorem quotClass_of_mem_quotSet {u : Nat} {Aset R A' R' a : V} + (hAset : Aset ∈ˢ (univ u : V)) (hA' : A' ∈ˢ (univ u : V)) (ha : a ∈ˢ A') + (hmem : quotClass u A' R' a ∈ˢ quotSet u Aset R) : + a ∈ˢ Aset ∧ quotClass u A' R' a = quotClass u Aset R a := by + obtain ⟨b, hb, hcls⟩ := quotClass_surj hmem + by_cases hu : u = 0 + · subst hu + refine ⟨?_, by unfold quotClass; rw [if_pos rfl, if_pos rfl]⟩ + rw [univ_zero] at hA' hAset + rw [eq_pt_of_mem_univZero hA' ha, ← eq_pt_of_mem_univZero hAset hb] + exact hb + · unfold quotClass at hcls ⊢ + rw [if_neg hu, if_neg hu] at hcls + rw [if_neg hu, if_neg hu] + have hab : a ∈ˢ qclass Aset R b := by rw [← hcls]; exact self_mem_qclass ha + obtain ⟨haA, hrel⟩ := mem_qclass.mp hab + exact ⟨haA, hcls.trans (qclass_eq_of_rel hrel)⟩ + +theorem quotSound {u : Nat} {A R a b w : V} (ha : a ∈ˢ A) (hb : b ∈ˢ A) + (hw : w ∈ˢ app (app R a) b) : quotClass u A R a = quotClass u A R b := by + unfold quotClass + split + · rfl + · exact qclass_eq_of_rel (QuotRel.base ha hb ⟨w, hw⟩) + +theorem quotSet_mem_univ {u : Nat} {A R : V} (hA : A ∈ˢ (univ u : V)) : + quotSet u A R ∈ˢ (univ u : V) := by + unfold quotSet + split + · next h => + subst h + rw [univ_zero] + refine mem_univZero.mpr fun z hz => ?_ + obtain ⟨-, -, rfl⟩ := mem_image.mp hz + exact pt_mem_unitSet + · next h => + refine (univ_isTGUniverse h).mem_of_subset_mem + ((univ_isTGUniverse h).power_mem hA) fun z hz => ?_ + obtain ⟨a, -, rfl⟩ := mem_image.mp hz + exact mem_power.mpr fun w hw => (mem_qclass.mp hw).1 + +open Classical in +/-- A representative of a quotient class, by choice. -/ +noncomputable def qrep (u : Nat) (A R q : V) : V := + if h : ∃ a, a ∈ˢ A ∧ q = quotClass u A R a then Classical.choose h else empty + +theorem qrep_spec {u : Nat} {A R q : V} (hq : q ∈ˢ quotSet u A R) : + qrep u A R q ∈ˢ A ∧ q = quotClass u A R (qrep u A R q) := by + unfold qrep + rw [dif_pos (quotClass_surj hq)] + exact Classical.choose_spec (quotClass_surj hq) + +/-- The invariance premise extends from the base relation to its +equivalence closure. -/ +theorem app_eq_of_rel {A R f a b : V} + (hinv : ∀ a' b', a' ∈ˢ A → b' ∈ˢ A → (∃ w, w ∈ˢ app (app R a') b') → + app f a' = app f b') + (h : QuotRel A R a b) : app f a = app f b := by + induction h with + | base ha hb hw => exact hinv _ _ ha hb hw + | refl _ => rfl + | symm _ ih => exact ih.symm + | trans _ _ ih₁ ih₂ => exact ih₁.trans ih₂ + +/-- Equal classes have equal `f`-values: by closure invariance at +`u ≠ 0`, and by the `A ⊆ {pt}` collapse at `u = 0`. -/ +theorem app_eq_of_quotClass_eq {u : Nat} {A R f a b : V} + (hA : A ∈ˢ (univ u : V)) (ha : a ∈ˢ A) (hb : b ∈ˢ A) + (hinv : ∀ a' b', a' ∈ˢ A → b' ∈ˢ A → (∃ w, w ∈ˢ app (app R a') b') → + app f a' = app f b') + (hq : quotClass u A R a = quotClass u A R b) : app f a = app f b := by + unfold quotClass at hq + split at hq + · next h => + subst h + rw [univ_zero] at hA + rw [eq_pt_of_mem_univZero hA ha, eq_pt_of_mem_univZero hA hb] + · exact app_eq_of_rel hinv (rel_of_qclass_eq ha hb hq) + +/-! ## pt-freshness refutation evidence (task #109) + +Quotient types are **not** unconditionally pt-fresh, for *any* +constructible proof point: classes are arbitrary nonempty subsets of +the base, so with base `ptTag` itself and a total relation the class +set is exactly `{ptTag} = pt`. Never resurrect a `quotSet_ne_pt`; the +#109 syntactic freshness guards exclude `Quot`-typed slots instead. +(The base `ptTag` is not the interpretation of any *writable* type — +the obstruction is semantic, in the ∀-A-R quantification of the model +lemmas. The old `pt = {∅}` was the unique choice immune to this — the +empty set is never a class — which is exactly what the re-choice +trades for data freshness.) -/ + +theorem quotSet_eq_pt_countermodel : + ∃ A R : V, quotSet 1 A R = pt := by + refine ⟨ptTag, graph (fun _ => graph (fun _ => unitSet) ptTag) ptTag, ?_⟩ + have hrel : ∀ a b : V, a ∈ˢ (ptTag : V) → b ∈ˢ (ptTag : V) → + QuotRel ptTag (graph (fun _ => graph (fun _ => unitSet) ptTag) ptTag) + a b := by + intro a b ha hb + refine QuotRel.base ha hb ⟨pt, ?_⟩ + rw [app_graph ha, app_graph hb] + exact pt_mem_unitSet + have hclass : ∀ a : V, a ∈ˢ (ptTag : V) → + qclass ptTag (graph (fun _ => graph (fun _ => unitSet) ptTag) ptTag) a + = ptTag := by + intro a ha + apply ext fun z => ?_ + rw [mem_qclass] + exact ⟨fun h => h.1, fun hz => ⟨hz, hrel a z ha hz⟩⟩ + unfold quotSet + rw [if_neg Nat.one_ne_zero] + apply ext fun z => ?_ + rw [mem_image, mem_pt] + constructor + · rintro ⟨a, ha, rfl⟩ + exact hclass a ha + · rintro rfl + exact ⟨empty, empty_mem_ptTag, (hclass empty empty_mem_ptTag).symm⟩ + +/- Opaque interface operators (see `Derive/Empty.lean`). -/ +attribute [irreducible] quotSet quotClass + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Sep.lean b/Ix/Theory/Model/SetTheory/Derive/Sep.lean new file mode 100644 index 000000000..71f78d3f0 --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Sep.lean @@ -0,0 +1,74 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Sep.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Empty + +@[expose] public section + +/-! +# Separation, derived from replacement + +The classical trick: to separate `{x ∈ a : p x}`, either the result is +empty (take `empty`), or some witness `w₀ ∈ a` with `p w₀` exists and +the total function `x ↦ if p x then x else w₀` replaces `a` onto +exactly the separated set (the default value `w₀` is already a member +of it). The detour is forced because replacement's antecedent demands +totality. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +open Classical in +/-- Separation: `{x ∈ a : p x}`, for an arbitrary meta-level predicate. -/ +noncomputable def sep (a : V) (p : V → Prop) : V := + if h : ∃ x, x ∈ˢ a ∧ p x then + image (fun x => if p x then x else Classical.choose h) a + else empty + +theorem mem_sep {a z : V} {p : V → Prop} : z ∈ˢ sep a p ↔ z ∈ˢ a ∧ p z := by + unfold sep + split + · next h => + obtain ⟨hw₀a, hw₀p⟩ := Classical.choose_spec h + rw [mem_image] + constructor + · rintro ⟨w, hw, rfl⟩ + split + · next hpw => exact ⟨hw, hpw⟩ + · exact ⟨hw₀a, hw₀p⟩ + · rintro ⟨hz, hp⟩ + exact ⟨z, hz, by simp [hp]⟩ + · next h => + constructor + · intro hz; exact absurd hz (not_mem_empty z) + · intro ⟨hz, hp⟩; exact absurd ⟨z, hz, hp⟩ h + +theorem sep_subset {a : V} {p : V → Prop} : sep a p ⊆ˢ a := + fun _ hz => (mem_sep.mp hz).1 + +theorem sep_congr {a : V} {p q : V → Prop} (h : ∀ x, x ∈ˢ a → (p x ↔ q x)) : + sep a p = sep a q := + ext fun z => by + rw [mem_sep, mem_sep] + exact ⟨fun ⟨hz, hp⟩ => ⟨hz, (h z hz).mp hp⟩, fun ⟨hz, hq⟩ => ⟨hz, (h z hz).mpr hq⟩⟩ + +/-- Image congruence, the companion fact. -/ +theorem image_congr {a : V} {f g : V → V} (h : ∀ x, x ∈ˢ a → f x = g x) : + image f a = image g a := + ext fun z => by + rw [mem_image, mem_image] + exact ⟨fun ⟨w, hw, hz⟩ => ⟨w, hw, hz.trans (h w hw)⟩, + fun ⟨w, hw, hz⟩ => ⟨w, hw, hz.trans (h w hw).symm⟩⟩ + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Sigma.lean b/Ix/Theory/Model/SetTheory/Derive/Sigma.lean new file mode 100644 index 000000000..5bbcd9e6f --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Sigma.lean @@ -0,0 +1,158 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Sigma.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Univ + +@[expose] public section + +/-! +# Dependent pairs, with the level-0 truncation + +`sigmaSet w A B` is, for `w ≠ 0`, the raw pair set `sigmaPairs A B` +(Kuratowski pairs `⟨a, b⟩` with `a ∈ A`, `b ∈ B a`); for `w = 0` the +truth value `[∃ a ∈ A, B a inhabited]` (the `Prop` collapse). + +`spair` is the Kuratowski pair; `sfst`/`ssnd` extract the components +classically (well-defined by `kpair_inj`) and default to `pt` on +non-pairs — in particular on `pt` itself, which is never a pair, so +`sfst pt = ssnd pt = pt` holds by the tag. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +open Classical in +/-- Dependent pair set at level `w` (see module docs). -/ +noncomputable def sigmaSet (w : Nat) (A : V) (B : V → V) : V := + if w = 0 then truthVal (∃ x, x ∈ˢ A ∧ ∃ y, y ∈ˢ B x) else sigmaPairs A B + +/-- Pairing: the Kuratowski pair. -/ +noncomputable def spair (a b : V) : V := kpair a b + +open Classical in +/-- First projection, `pt` on non-pairs. -/ +noncomputable def sfst (p : V) : V := + if h : ∃ a b, p = kpair a b then Classical.choose h else pt + +open Classical in +/-- Second projection, `pt` on non-pairs. -/ +noncomputable def ssnd (p : V) : V := + if h : ∃ a b, p = kpair a b then Classical.choose (Classical.choose_spec h) + else pt + +theorem sigmaSet_zero {A : V} {B : V → V} : + sigmaSet 0 A B = truthVal (∃ x, x ∈ˢ A ∧ ∃ y, y ∈ˢ B x) := by + unfold sigmaSet; exact if_pos rfl + +theorem sigmaSet_pos {w : Nat} (hw : w ≠ 0) {A : V} {B : V → V} : + sigmaSet w A B = sigmaPairs A B := by + unfold sigmaSet; exact if_neg hw + +theorem sigma_congr {w : Nat} {A : V} {B B' : V → V} + (h : ∀ x, x ∈ˢ A → B x = B' x) : sigmaSet w A B = sigmaSet w A B' := by + rcases Nat.eq_zero_or_pos w with rfl | hw + · rw [sigmaSet_zero, sigmaSet_zero] + refine truthVal_congr ⟨?_, ?_⟩ + · rintro ⟨x, hx, y, hy⟩; exact ⟨x, hx, y, h x hx ▸ hy⟩ + · rintro ⟨x, hx, y, hy⟩; exact ⟨x, hx, y, (h x hx).symm ▸ hy⟩ + · rw [sigmaSet_pos (Nat.pos_iff_ne_zero.mp hw), sigmaSet_pos (Nat.pos_iff_ne_zero.mp hw)] + exact sigmaPairs_congr h + +theorem spair_mem {w : Nat} {A : V} {B : V → V} {a b : V} (hw : w ≠ 0) + (ha : a ∈ˢ A) (hb : b ∈ˢ B a) : spair a b ∈ˢ sigmaSet w A B := by + rw [sigmaSet_pos hw] + exact mem_sigmaPairs.mpr ⟨a, ha, b, hb, rfl⟩ + +theorem pt_mem_sigma {A : V} {B : V → V} {a b : V} + (ha : a ∈ˢ A) (hb : b ∈ˢ B a) : (pt : V) ∈ˢ sigmaSet 0 A B := by + rw [sigmaSet_zero] + exact pt_mem_truthVal ⟨a, ha, b, hb⟩ + +theorem mem_sigma_elim {w : Nat} {A : V} {B : V → V} {t : V} + (ht : t ∈ˢ sigmaSet w A B) : + ∃ a b, a ∈ˢ A ∧ b ∈ˢ B a ∧ (w = 0 → t = pt) ∧ (w ≠ 0 → t = spair a b) := by + rcases Nat.eq_zero_or_pos w with rfl | hw + · rw [sigmaSet_zero] at ht + obtain ⟨a, ha, b, hb⟩ := of_mem_truthVal ht + exact ⟨a, b, ha, hb, fun _ => eq_pt_of_mem_truthVal ht, fun h0 => absurd rfl h0⟩ + · have hw' : w ≠ 0 := Nat.pos_iff_ne_zero.mp hw + rw [sigmaSet_pos hw'] at ht + obtain ⟨a, ha, b, hb, rfl⟩ := mem_sigmaPairs.mp ht + exact ⟨a, b, ha, hb, fun h0 => absurd h0 hw', fun _ => rfl⟩ + +theorem sfst_spair (a b : V) : sfst (spair a b) = a := by + unfold sfst spair + rw [dif_pos ⟨a, b, rfl⟩] + have hs := Classical.choose_spec + (⟨a, b, rfl⟩ : ∃ a' b', (kpair a b : V) = kpair a' b') + have hs2 := Classical.choose_spec hs + exact (kpair_inj hs2).1.symm + +theorem ssnd_spair (a b : V) : ssnd (spair a b) = b := by + unfold ssnd spair + rw [dif_pos ⟨a, b, rfl⟩] + have hs := Classical.choose_spec + (⟨a, b, rfl⟩ : ∃ a' b', (kpair a b : V) = kpair a' b') + have hs2 := Classical.choose_spec hs + exact (kpair_inj hs2).2.symm + +theorem spair_eq_kpair (a b : V) : spair a b = kpair a b := by unfold spair; rfl +theorem sfst_kpair (a b : V) : sfst (kpair a b) = a := by rw [← spair_eq_kpair]; exact sfst_spair a b +theorem ssnd_kpair (a b : V) : ssnd (kpair a b) = b := by rw [← spair_eq_kpair]; exact ssnd_spair a b + +theorem sfst_pt : sfst (pt : V) = pt := by + unfold sfst + rw [dif_neg] + rintro ⟨a, b, h⟩ + exact pt_ne_kpair a b h + +theorem ssnd_pt : ssnd (pt : V) = pt := by + unfold ssnd + rw [dif_neg] + rintro ⟨a, b, h⟩ + exact pt_ne_kpair a b h + +/-- A pair set is never the proof point: at level `0` it is a truth +value, at positive levels its members are Kuratowski pairs while `pt`'s +one member is `∅`. (The collapse-era replacement for tag-based +non-`pt`-ness of stored pair-set values, task #100.) -/ +theorem sigmaSet_ne_pt {w : Nat} {A : V} {B : V → V} : + sigmaSet w A B ≠ (pt : V) := by + rcases Nat.eq_zero_or_pos w with rfl | hw + · rw [sigmaSet_zero] + exact truthVal_ne_pt _ + · rw [sigmaSet_pos (Nat.pos_iff_ne_zero.mp hw)] + intro h + have hmem : (ptTag : V) ∈ˢ sigmaPairs A B := by + rw [h] + exact ptTag_mem_pt + obtain ⟨a, -, b, -, hp⟩ := mem_sigmaPairs.mp hmem + exact ptTag_ne_kpair a b hp + +/-- Formation along the tower, at the joint level `max u v`. -/ +theorem sigma_mem_univ {u v : Nat} {A : V} {B : V → V} + (hA : A ∈ˢ (univ u : V)) (hB : ∀ x, x ∈ˢ A → B x ∈ˢ (univ v : V)) : + sigmaSet (Nat.max u v) A B ∈ˢ (univ (Nat.max u v) : V) := by + rcases Nat.eq_zero_or_pos (Nat.max u v) with hw | hw + · rw [hw, sigmaSet_zero, univ_zero] + exact truthVal_mem_univZero _ + · have hw' : Nat.max u v ≠ 0 := Nat.pos_iff_ne_zero.mp hw + rw [sigmaSet_pos hw'] + exact (univ_isTGUniverse hw').sigmaPairs_mem + (univ_mono (Nat.le_max_left u v) A hA) + (fun x hx => univ_mono (Nat.le_max_right u v) _ (hB x hx)) + +/- Opaque interface operators (see `Derive/Empty.lean`). -/ +attribute [irreducible] sigmaSet spair sfst ssnd + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Univ.lean b/Ix/Theory/Model/SetTheory/Derive/Univ.lean new file mode 100644 index 000000000..75b8523cf --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Univ.lean @@ -0,0 +1,110 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Univ.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Graphs +public import Ix.Theory.Model.SetTheory.Derive.Omega + +@[expose] public section + +/-! +# The universe tower + +`univ 0` is the set of truth values (`univZero`, the `U₀` of Mario +Carneiro, *The Type Theory of Lean*, master's thesis, Carnegie Mellon +University, 2019); +`univ (n+1)` is the chain universe `univChain (n+2)`. The tower +starts two levels up the chain so that every positive level has the +inductive set `univChain 1` as a member — which is what puts `ω` +inside every positive level (a bare universe need not contain `ω`; +`V_ω` is one — and `univChain 0` need not be inhabited, the empty set +satisfying `IsTGUniverse` vacuously, so `univChain 1` is the first chain +member known to be inductive). `univ 0 ∈ univ 1` because `univZero` +is built from `∅` by pairing/power closure inside the inhabited +universe `univChain 1 ∈ univChain 2`. Cumulativity holds because +positive levels are transitive and each level is a member of the +next. +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +/-- The universe tower interpreting `Sort n`. -/ +noncomputable def univ : Nat → V + | 0 => univZero + | n + 1 => univChain (n + 2) + +theorem univ_zero : (univ 0 : V) = univZero := by rfl + +/-- Positive levels are Grothendieck universes. -/ +theorem univ_isTGUniverse {n : Nat} (hn : n ≠ 0) : + IsTGUniverse (Mem (V := V)) (univ n) := by + match n, hn with + | m + 1, _ => exact univChain_tg _ + +theorem univChain_one_mem_univ_succ (n : Nat) : + (univChain 1 : V) ∈ˢ univ (n + 1) := + univChain_mem_of_lt (Nat.succ_lt_succ n.succ_pos) + +theorem univ_mem_univ (n : Nat) : (univ n : V) ∈ˢ univ (n + 1) := by + match n with + | 0 => + exact (univChain_tg 2).transitive (univChain_mem 1) + ((univChain_tg 1).univZero_mem (univChain_mem 0)) + | m + 1 => exact univChain_mem (m + 2) + +theorem univ_subset_succ (n : Nat) : (univ n : V) ⊆ˢ univ (n + 1) := + (univ_isTGUniverse (Nat.succ_ne_zero n)).subset_of_mem (univ_mem_univ n) + +theorem univ_mono {m n : Nat} (h : m ≤ n) : (univ m : V) ⊆ˢ univ n := by + induction n with + | zero => cases Nat.le_zero.mp h; exact Subset.refl _ + | succ n ih => + rcases Nat.lt_succ_iff_lt_or_eq.mp (Nat.lt_succ_of_le h) with h' | rfl + · exact (ih (Nat.lt_succ_iff.mp h')).trans (univ_subset_succ n) + · exact Subset.refl _ + +/-- **The universe tower is injective.** `univ u ∈ˢ univ (u+1) ⊆ˢ univ v` +whenever `u < v`, so an equality of two levels' universes would put a set +inside itself, against regularity (`not_mem_self`). + +Note what this does *not* say, and what nothing can: the tower is +**cumulative** (`univ_mono`), so a *membership* `x ∈ˢ univ u` fixes only +a lower bound on `u` and two memberships of one value never determine a +level. Injectivity of `univ` itself is the only handle on levels the +tower offers, and every consumer that needs "the sort is `u`" has to +reach it through an equality of universes, not through a typing. -/ +theorem univ_inj {u v : Nat} (h : (univ u : V) = univ v) : u = v := by + rcases Nat.lt_trichotomy u v with hlt | heq | hgt + · exact absurd (h ▸ univ_mono (V := V) hlt _ (univ_mem_univ u)) + (not_mem_self (univ v : V)) + · exact heq + · exact absurd (h ▸ univ_mono (V := V) hgt _ (univ_mem_univ v)) + (not_mem_self (univ u : V)) + +theorem omega_mem_univ_succ (n : Nat) : (omega : V) ∈ˢ univ (n + 1) := + (univ_isTGUniverse (Nat.succ_ne_zero n)).omega_mem (univChain_one_mem_univ_succ n) + +theorem empty_mem_univ : ∀ n : Nat, (empty : V) ∈ˢ univ n + | 0 => mem_univZero.mpr (empty_subset _) + | n + 1 => + (univ_isTGUniverse (Nat.succ_ne_zero n)).empty_mem (univChain_one_mem_univ_succ n) + +theorem unitSet_mem_univ : ∀ n : Nat, (unitSet : V) ∈ˢ univ n + | 0 => mem_univZero.mpr (Subset.refl _) + | n + 1 => + (univ_isTGUniverse (Nat.succ_ne_zero n)).unitSet_mem (univChain_one_mem_univ_succ n) + +/- Opaque interface operator (see `Derive/Empty.lean`). -/ +attribute [irreducible] univ + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/SetTheory/Derive/Universe.lean b/Ix/Theory/Model/SetTheory/Derive/Universe.lean new file mode 100644 index 000000000..6ae805d1f --- /dev/null +++ b/Ix/Theory/Model/SetTheory/Derive/Universe.lean @@ -0,0 +1,175 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source: ConLeche/SetTheory/Derive/Universe.lean +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespace and import paths adapted to Ix.Theory.Model. +-/ + +module + +public import Ix.Theory.Model.SetTheory.Derive.Pair + +@[expose] public section + +/-! +# Grothendieck universes: the diagonal argument and the closure laws + +The engine room, recovering the Grothendieck-universe closure laws +(SGA 4, Exp. I, Appendix) from the Axiom-A matrix `IsTGUniverse` +(Tarski 1938) — applied downstream to the chain members `univChain n`. +The inaccessibility clause offers, for any subset `S ⊆ u`, the +disjunction `S ≈ u ∨ S ∈ u`; the single lemma `covered_mem` turns it +into a closure property by refuting the first disjunct with Cantor's +diagonal whenever `S` is covered by a function from a *member* of `u`. +Everything else — pairing, power, binary union, replacement images, +`⋃` of a member — reduces to it (`⋃` via a two-step surjection +argument ending in a membership 2-cycle). +-/ + +namespace Ix.Theory.Model.SetTheory + +universe u + +variable {V : Type u} [SetTheory V] + +section IsTGUniverse + +variable {U : V} (hU : IsTGUniverse (Mem (V := V)) U) + +include hU + +theorem _root_.Ix.Theory.Model.IsTGUniverse.transitive : ∀ {y z : V}, y ∈ˢ U → z ∈ˢ y → z ∈ˢ U := + fun {y z} hy hz => hU.1 y z hy hz + +theorem _root_.Ix.Theory.Model.IsTGUniverse.mem_of_subset_mem : ∀ {y z : V}, y ∈ˢ U → z ⊆ˢ y → z ∈ˢ U := + fun {y z} hy hz => hU.2.1 y z hy hz + +theorem _root_.Ix.Theory.Model.IsTGUniverse.subset_of_mem {y : V} (hy : y ∈ˢ U) : y ⊆ˢ U := + fun _ hz => hU.transitive hy hz + +theorem _root_.Ix.Theory.Model.IsTGUniverse.power_mem {y : V} (hy : y ∈ˢ U) : power y ∈ˢ U := by + obtain ⟨p, hp, hsub⟩ := hU.2.2.1 y hy + exact hU.mem_of_subset_mem hp fun z hz => hsub z (mem_power.mp hz) + +/-- Cantor's diagonal, in the form everything downstream uses: a subset +of `U` covered by the image of a *member* of `U` is itself a member. +The equinumerosity disjunct is refuted by diagonalizing the covering +composed with the would-be surjection onto `U`. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.covered_mem {I S : V} {F : V → V} + (hI : I ∈ˢ U) (hS : S ⊆ˢ U) + (hcov : ∀ b, b ∈ˢ S → ∃ x, x ∈ˢ I ∧ F x = b) : S ∈ˢ U := by + rcases hU.2.2.2 S hS with ⟨f, -, -, hsurj⟩ | hmem + · -- `f : S ↠ U`; diagonalize `x ↦ f (F x) : I ↠ U` at + -- `D := {x ∈ I : x ∉ f (F x)}`. + exfalso + have hDU : sep I (fun x => ¬ x ∈ˢ f (F x)) ∈ˢ U := + hU.mem_of_subset_mem hI sep_subset + obtain ⟨b, hbS, hfb⟩ := hsurj _ hDU + obtain ⟨j, hjI, hFj⟩ := hcov b hbS + have hGj : f (F j) = sep I (fun x => ¬ x ∈ˢ f (F x)) := by rw [hFj, hfb] + have hiff : j ∈ˢ sep I (fun x => ¬ x ∈ˢ f (F x)) ↔ + ¬ j ∈ˢ sep I (fun x => ¬ x ∈ˢ f (F x)) := by + constructor + · intro hj + have := (mem_sep.mp hj).2 + rwa [hGj] at this + · intro hn + exact mem_sep.mpr ⟨hjI, by rwa [hGj]⟩ + rcases Classical.em (j ∈ˢ sep I (fun x => ¬ x ∈ˢ f (F x))) with hj | hj + · exact hiff.mp hj hj + · exact hj (hiff.mpr hj) + · exact hmem + +/-- Replacement closure: the image of a member under a fibre-wise +member-valued function is a member. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.image_mem {A : V} {F : V → V} + (hA : A ∈ˢ U) (hF : ∀ x, x ∈ˢ A → F x ∈ˢ U) : image F A ∈ˢ U := + hU.covered_mem hA + (fun z hz => by + obtain ⟨w, hw, rfl⟩ := mem_image.mp hz + exact hF w hw) + (fun b hb => by + obtain ⟨w, hw, rfl⟩ := mem_image.mp hb + exact ⟨w, hw, rfl⟩) + +theorem _root_.Ix.Theory.Model.IsTGUniverse.empty_mem {y : V} (hy : y ∈ˢ U) : (empty : V) ∈ˢ U := + hU.mem_of_subset_mem hy (empty_subset y) + +open Classical in +/-- Pairing closure, via `covered_mem` from the two-element member +`power (power ∅) = {∅, {∅}}`. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.upair_mem {a b y : V} (hy : y ∈ˢ U) + (ha : a ∈ˢ U) (hb : b ∈ˢ U) : upair a b ∈ˢ U := by + have h2 : power (power (empty : V)) ∈ˢ U := + (hU.empty_mem hy |> hU.power_mem) |> hU.power_mem + refine hU.covered_mem (F := fun x => if x = empty then a else b) h2 ?_ ?_ + · intro z hz + rcases mem_upair.mp hz with h | h <;> subst h <;> assumption + · intro z hz + rcases mem_upair.mp hz with h | h <;> subst h + · exact ⟨empty, mem_power.mpr (empty_subset _), by simp⟩ + · refine ⟨power empty, mem_power.mpr (Subset.refl _), ?_⟩ + have hne : power (empty : V) ≠ empty := + ne_empty_of_mem (mem_power.mpr (Subset.refl _)) + simp [hne] + +theorem _root_.Ix.Theory.Model.IsTGUniverse.sing_mem {a y : V} (hy : y ∈ˢ U) (ha : a ∈ˢ U) : + sing a ∈ˢ U := hU.upair_mem hy ha ha + +/-- `⋃` closure. A surjection `f : ⋃s ↠ U` would make `U` the union +of the member `S = {f-image of w : w ∈ s}`, putting `S ∈ U ⊆ ⋃S` — a +2-cycle. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.sUnion_mem {s : V} (hs : s ∈ˢ U) : sUnion s ∈ˢ U := by + have hsub : sUnion s ⊆ˢ U := fun z hz => by + obtain ⟨y, hy, hzy⟩ := mem_sUnion.mp hz + exact hU.transitive (hU.transitive hs hy) hzy + rcases hU.2.2.2 (sUnion s) hsub with ⟨f, hinto, -, hsurj⟩ | hmem + · exfalso + -- For each `w ∈ s`, the `f`-image of `w` is a member of `U` … + have himg : ∀ w, w ∈ˢ s → image f w ∈ˢ U := fun w hw => + hU.image_mem (hU.transitive hs hw) fun x hx => + hinto x (mem_sUnion.mpr ⟨w, hw, hx⟩) + -- … so the set of all these images is a member too … + have hS : image (fun w => image f w) s ∈ˢ U := + hU.image_mem hs fun w hw => himg w hw + -- … but `U ⊆ ⋃(that set)`, giving `S ∈ U ⊆ ⋃S`: a 2-cycle. + obtain ⟨x, hx, hfx⟩ := hsurj _ hS + obtain ⟨w, hw, hxw⟩ := mem_sUnion.mp hx + have : image (fun w => image f w) s ∈ˢ image f w := + hfx ▸ mem_image.mpr ⟨x, hxw, rfl⟩ + exact no_two_cycle this (mem_image.mpr ⟨w, hw, rfl⟩) + · exact hmem + +theorem _root_.Ix.Theory.Model.IsTGUniverse.binUnion_mem {a b y : V} (hy : y ∈ˢ U) + (ha : a ∈ˢ U) (hb : b ∈ˢ U) : binUnion a b ∈ˢ U := + hU.sUnion_mem (hU.upair_mem hy ha hb) + +theorem _root_.Ix.Theory.Model.IsTGUniverse.kpair_mem {a b y : V} (hy : y ∈ˢ U) + (ha : a ∈ˢ U) (hb : b ∈ˢ U) : kpair a b ∈ˢ U := + hU.upair_mem hy (hU.sing_mem hy ha) (hU.upair_mem hy ha hb) + +theorem _root_.Ix.Theory.Model.IsTGUniverse.sep_mem {a : V} {p : V → Prop} (ha : a ∈ˢ U) : + sep a p ∈ˢ U := + hU.mem_of_subset_mem ha sep_subset + +/-- Union of a member-indexed family of members. -/ +theorem _root_.Ix.Theory.Model.IsTGUniverse.famUnion_mem {A : V} {F : V → V} + (hA : A ∈ˢ U) (hF : ∀ x, x ∈ˢ A → F x ∈ˢ U) : + sUnion (image F A) ∈ˢ U := + hU.sUnion_mem (hU.image_mem hA hF) + +end IsTGUniverse + +/-- Chain membership generalizes along the ordering, by transitivity +of the higher universe. -/ +theorem univChain_mem_of_lt {m n : Nat} (h : m < n) : + (univChain m : V) ∈ˢ univChain n := by + induction n with + | zero => exact absurd h (Nat.not_lt_zero m) + | succ n ih => + rcases Nat.lt_succ_iff_lt_or_eq.mp h with h' | rfl + · exact (univChain_tg (n + 1)).transitive (univChain_mem n) (ih h') + · exact univChain_mem m + +end Ix.Theory.Model.SetTheory diff --git a/Ix/Theory/Model/Signature.lean b/Ix/Theory/Model/Signature.lean new file mode 100644 index 000000000..fd69a8e35 --- /dev/null +++ b/Ix/Theory/Model/Signature.lean @@ -0,0 +1,159 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Extension + +namespace Ix.Theory.Model + +universe u v +variable {β : Type u} + +/-- An internal signature overlay does not by itself admit declarations. -/ +def Environment.overlay (entries additions : Environment β) : Environment β := + fun r => match additions r with + | some entry => some entry + | none => entries r + +def Assignment.overlay (constants values : Assignment β V) (additions : Environment β) : Assignment β V := + fun r levels => match additions r with + | some _ => values r levels + | none => constants r levels + +def Environment.Fresh (entries additions : Environment β) : Prop := + ∀ r entry, additions r = some entry → entries r = none + +theorem Environment.overlay_new {entries additions : Environment β} {r : ConstRef β} + {entry : ConstantEntry β} (h : additions r = some entry) : + entries.overlay additions r = some entry := by simp only [overlay, h] + +theorem Environment.overlay_old {entries additions : Environment β} + (hf : entries.Fresh additions) {r : ConstRef β} {entry : ConstantEntry β} + (h : entries r = some entry) : entries.overlay additions r = some entry := by + cases ha : additions r with + | none => simpa only [overlay, ha] using h + | some new => have he := hf r new ha; rw [h] at he; contradiction + +theorem Assignment.overlay_agrees {entries additions : Environment β} (hf : entries.Fresh additions) + (constants values : Assignment β V) : Assignment.AgreesOn entries constants (constants.overlay values additions) := by + intro r entry hr levels + cases ha : additions r with + | none => simp only [overlay, ha] + | some new => have he := hf r new ha; rw [hr] at he; contradiction + +theorem AExpr.ReferencesIn.overlay {entries additions : Environment β} {e : AExpr β} + (h : e.ReferencesIn entries) : e.ReferencesIn (entries.overlay additions) := by + intro r hr + cases ha : additions r with + | none => simpa only [Environment.overlay, ha] using h r hr + | some _ => simp only [Environment.overlay, ha, Option.isSome_some] + +theorem ConstantFact.ReferencesIn.overlay {entries additions : Environment β} {fact : ConstantFact β} + (h : fact.ReferencesIn entries) : fact.ReferencesIn (entries.overlay additions) := by + intro r hr + cases ha : additions r with + | none => simpa only [Environment.overlay, ha] using h r hr + | some _ => simp only [Environment.overlay, ha, Option.isSome_some] + +/-- The syntactic closure needed for a signature entry. Formation and the +value's membership are separate obligations and cannot be supplied by data. -/ +structure EntryClosed (entries : Environment β) (entry : ConstantEntry β) : Prop where + typeScope : entry.type.Scope entry.universes 0 + bodyScope : ∀ body, entry.body = some body → body.Scope entry.universes 0 + typeReferences : entry.type.ReferencesIn entries + bodyReferences : ∀ body, entry.body = some body → body.ReferencesIn entries + equationScope : ∀ law ∈ entry.equations, + law.lhs.Scope entry.universes 0 ∧ law.rhs.Scope entry.universes 0 + equationReferences : ∀ law ∈ entry.equations, + law.lhs.ReferencesIn entries ∧ law.rhs.ReferencesIn entries + factScope : ∀ fact ∈ entry.facts, fact.Scope entry.universes + factReferences : ∀ fact ∈ entry.facts, fact.ReferencesIn entries + +theorem Environment.WF.overlay {entries additions : Environment β} (hE : entries.WF) + (hN : ∀ r entry, additions r = some entry → EntryClosed entries entry) : + (entries.overlay additions).WF := by + constructor + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).typeScope + · exact hE.typeScope r entry hr + · intro r entry hr body hb + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).bodyScope body hb + · exact hE.bodyScope r entry hr body hb + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).typeReferences.overlay + · exact (hE.typeReferences r entry hr).overlay + · intro r entry hr body hb + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact ((hN _ _ ‹_›).bodyReferences body hb).overlay + · exact (hE.bodyReferences r entry hr body hb).overlay + · intro r entry hr law hl + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).equationScope law hl + · exact hE.equationScope r entry hr law hl + · intro r entry hr law hl + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr + exact ⟨((hN _ _ ‹_›).equationReferences law hl).1.overlay, + ((hN _ _ ‹_›).equationReferences law hl).2.overlay⟩ + · exact ⟨(hE.equationReferences r entry hr law hl).1.overlay, + (hE.equationReferences r entry hr law hl).2.overlay⟩ + · intro r entry hr fact hf + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).factScope fact hf + · exact hE.factScope r entry hr fact hf + · intro r entry hr fact hf + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact ((hN _ _ ‹_›).factReferences fact hf).overlay + · exact (hE.factReferences r entry hr fact hf).overlay + +variable {V : Type v} [SetTheory V] + +theorem Realizes.overlay {entries additions : Environment β} {constants : Assignment β V} + (hM : Realizes constants entries) + (hN : ∀ r entry, additions r = some entry → EntryRealization constants r entry) : + Realizes constants (entries.overlay additions) := by + constructor + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).typeValid + · exact hM.typeValid r entry hr + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).member + · exact hM.member r entry hr + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).bodyValid + · exact hM.bodyValid r entry hr + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).bodyValue + · exact hM.bodyValue r entry hr + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).equationValue + · exact hM.equationValue r entry hr + · intro r entry hr + unfold Environment.overlay at hr + split at hr + · cases Option.some.inj hr; exact (hN _ _ ‹_›).factMeaning + · exact hM.factMeaning r entry hr + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/Support.lean b/Ix/Theory/Model/Support.lean new file mode 100644 index 000000000..f6902993d --- /dev/null +++ b/Ix/Theory/Model/Support.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Environment + +namespace Ix.Theory.Model + +open SetTheory + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +namespace AExpr + +def references : AExpr β → List (ConstRef β) + | .bvar _ | .sort _ | .natLit _ => [] + | .const r _ => [r] + | .app f a | .lam _ f a | .forallE _ f a => f.references ++ a.references + | .proj r _ e => r :: e.references + +def ReferencesIn (entries : Environment β) (e : AExpr β) : Prop := + ∀ r ∈ e.references, (entries r).isSome = true + +instance {entries : Environment β} {e : AExpr β} : Decidable (e.ReferencesIn entries) := + inferInstanceAs (Decidable (∀ r ∈ e.references, (entries r).isSome = true)) + +end AExpr + +def ConstantFact.Scope (n : Nat) : ConstantFact β → Prop + | .typed e type => e.Scope n 0 ∧ type.Scope n 0 + | .natural .. => n = 0 + +def ConstantFact.references : ConstantFact β → List (ConstRef β) + | .typed e type => e.references ++ type.references + | .natural zero succ => [zero, succ] + +def ConstantFact.ReferencesIn (entries : Environment β) (fact : ConstantFact β) : Prop := + ∀ r ∈ fact.references, (entries r).isSome = true + +instance {n : Nat} {fact : ConstantFact β} : Decidable (fact.Scope n) := by + cases fact <;> unfold ConstantFact.Scope <;> infer_instance + +instance {entries : Environment β} {fact : ConstantFact β} : Decidable (fact.ReferencesIn entries) := + inferInstanceAs (Decidable (∀ r ∈ fact.references, (entries r).isSome = true)) + +theorem interp_congr_constants (e : AExpr β) (constants constants' : Assignment β V) + (h : ∀ r ∈ e.references, ∀ ls, constants r ls = constants' r ls) + (levels : List Nat) (env : Nat → V) : + interp constants levels env e = interp constants' levels env e := by + induction e generalizing env with + | const r ls => exact h r (by simp [AExpr.references]) _ + | app f a hf ha => + have hf' := hf (fun r hr => h r (List.mem_append_left _ hr)) env + have ha' := ha (fun r hr => h r (List.mem_append_right _ hr)) env + simp only [interp, hf', ha'] + | lam p A b hA hb | forallE p A b hA hb => + have hA' := hA (fun r hr => h r (List.mem_append_left _ hr)) env + simp only [interp, hA'] + congr 1 + funext x + exact hb (fun r hr => h r (List.mem_append_right _ hr)) _ + | proj r i e ih => + simp only [interp, ih (fun q hq => h q (List.mem_cons_of_mem _ hq)) env] + | _ => rfl + +theorem wellDenoted_congr_constants (e : AExpr β) (constants constants' : Assignment β V) + (h : ∀ r ∈ e.references, ∀ ls, constants r ls = constants' r ls) + (levels : List Nat) (env : Nat → V) : + WellDenoted constants levels env e ↔ WellDenoted constants' levels env e := by + induction e generalizing env with + | app f a hf ha => + have hfr := fun r hr => h r (List.mem_append_left _ hr) + have har := fun r hr => h r (List.mem_append_right _ hr) + simp only [WellDenoted, hf hfr, ha har, interp_congr_constants _ _ _ hfr, + interp_congr_constants _ _ _ har] + | lam p A b hA hb | forallE p A b hA hb => + have hAr := fun r hr => h r (List.mem_append_left _ hr) + have hbr := fun r hr => h r (List.mem_append_right _ hr) + simp only [WellDenoted, hA hAr, hb hbr, interp_congr_constants _ _ _ hAr, + interp_congr_constants _ _ _ hbr] + | proj r i e ih => exact ih (fun q hq => h q (List.mem_cons_of_mem _ hq)) env + | _ => rfl + +theorem interp_congr_env (e : AExpr β) (constants : Assignment β V) + (levels : List Nat) {n k : Nat} (hs : e.Scope n k) (env env' : Nat → V) + (h : ∀ i, i < k → env i = env' i) : + interp constants levels env e = interp constants levels env' e := by + induction e generalizing k env env' with + | bvar i => exact h i hs + | app f a hf ha => simp only [interp, hf hs.1 env env' h, ha hs.2 env env' h] + | lam p A b hA hb | forallE p A b hA hb => + simp only [interp, hA hs.2.1 env env' h] + congr 1 + funext x + apply hb hs.2.2 + intro i hi + cases i with + | zero => rfl + | succ i => exact h i (by omega) + | proj r i e ih => simp only [interp, ih hs env env' h] + | _ => rfl + +theorem interp_closed (e : AExpr β) (constants : Assignment β V) + (levels : List Nat) {n : Nat} (hs : e.Scope n 0) (env env' : Nat → V) : + interp constants levels env e = interp constants levels env' e := + interp_congr_env e constants levels hs env env' (fun _ h => (Nat.not_lt_zero _ h).elim) + +/-- Syntactic closure of an admitted interface. Semantic realizability remains +a separate, produced fact. -/ +structure Environment.WF (entries : Environment β) : Prop where + typeScope : ∀ r entry, entries r = some entry → entry.type.Scope entry.universes 0 + bodyScope : ∀ r entry, entries r = some entry → ∀ body, entry.body = some body → + body.Scope entry.universes 0 + typeReferences : ∀ r entry, entries r = some entry → entry.type.ReferencesIn entries + bodyReferences : ∀ r entry, entries r = some entry → ∀ body, entry.body = some body → + body.ReferencesIn entries + equationScope : ∀ r entry, entries r = some entry → ∀ equation ∈ entry.equations, + equation.lhs.Scope entry.universes 0 ∧ equation.rhs.Scope entry.universes 0 + equationReferences : ∀ r entry, entries r = some entry → ∀ equation ∈ entry.equations, + equation.lhs.ReferencesIn entries ∧ equation.rhs.ReferencesIn entries + factScope : ∀ r entry, entries r = some entry → ∀ fact ∈ entry.facts, fact.Scope entry.universes + factReferences : ∀ r entry, entries r = some entry → ∀ fact ∈ entry.facts, fact.ReferencesIn entries + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/TelescopeSemantics.lean b/Ix/Theory/Model/TelescopeSemantics.lean new file mode 100644 index 000000000..855662026 --- /dev/null +++ b/Ix/Theory/Model/TelescopeSemantics.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Instantiation + +namespace Ix.Theory.Model.Telescope + +open SetTheory SetTheory.Tower SetModel Certified + +universe u v +variable {β : Type u} {V : Type v} [SetTheory V] + +theorem fits_append_iff (constants : Assignment β V) (levels : List Nat) (env : Nat → V) + (left right : List (AExpr β)) (xs : List V) : + FitsS (interpret constants levels env (left ++ right)) xs ↔ + ∃ ys zs, xs = ys ++ zs ∧ FitsS (interpret constants levels env left) ys ∧ + FitsS (interpret constants levels (extend env ys) right) zs := by + induction left generalizing env xs with + | nil => + constructor + · intro h + exact ⟨[], xs, rfl, trivial, h⟩ + · rintro ⟨ys, zs, rfl, hy, hz⟩ + cases ys with + | nil => exact hz + | cons _ _ => exact hy.elim + | cons A rest ih => + constructor + · intro h + cases xs with + | nil => exact h.elim + | cons x xs => + obtain ⟨ys, zs, rfl, hy, hz⟩ := (ih (Valuation.cons x env) xs).mp h.2 + exact ⟨x :: ys, zs, rfl, ⟨h.1, hy⟩, hz⟩ + · rintro ⟨ys, zs, rfl, hy, hz⟩ + cases ys with + | nil => exact hy.elim + | cons y ys => exact ⟨hy.1, (ih (Valuation.cons y env) (ys ++ zs)).mpr ⟨ys, zs, rfl, hy.2, hz⟩⟩ + +/-- Close a pointwise semantic fact over a formed telescope. The result +includes hereditary validity of both complete endpoints and a uniform sort +for the resulting product. It does not assume a model for any new fact. -/ +theorem Formed.lamN_semantics {entries : Environment β} {Γ : Context β} + {domains : List (AExpr β)} (h : Formed.{u,v} entries Γ domains) + (constants : Assignment β V) (hM : Realizes constants entries) (levels : List Nat) + (body B : AExpr β) (b : VLevel) : + ∃ l, zeroCondition l = zeroCondition b ∧ ∀ env, Γ.Valid constants levels env → + (∀ xs, FitsS (interpret constants levels env domains) xs → + let env' := extend env xs + WellDenoted constants levels env' body ∧ WellDenoted constants levels env' B ∧ + interp constants levels env' body ∈ˢ interp constants levels env' B ∧ + interp constants levels env' B ∈ˢ (univ (b.eval levels) : V)) → + WellDenoted constants levels env (.lamN (zeroCondition b) domains body) ∧ + WellDenoted constants levels env (.forallN (zeroCondition b) domains B) ∧ + interp constants levels env (.lamN (zeroCondition b) domains body) ∈ˢ + interp constants levels env (.forallN (zeroCondition b) domains B) ∧ + interp constants levels env (.forallN (zeroCondition b) domains B) ∈ˢ + (univ (l.eval levels) : V) := by + induction h with + | nil => exact ⟨b, rfl, fun env _ hb => hb [] trivial⟩ + | @cons Γ A rest a hA hrest ih => + obtain ⟨l, hl, ih⟩ := ih + refine ⟨.imax a l, hl, ?_⟩ + intro env hΓ hb + have hAt := hA V constants hM levels env hΓ + have ht x hx := ih (Valuation.cons x env) (hΓ.push hAt.1 hx) + (fun xs hxs => hb (x :: xs) ⟨hx, hxs⟩) + have hz : regime (zeroCondition b) levels = 0 ↔ l.eval levels = 0 := by + rw [← hl] + exact regime_zeroCondition .. + refine ⟨⟨hAt.1, fun x hx => (ht x hx).1, l.eval levels, + (fun x => interp constants levels (Valuation.cons x env) (.forallN (zeroCondition b) rest B)), + hz, fun x hx => ⟨(ht x hx).2.2.1, (ht x hx).2.2.2⟩⟩, + ⟨hAt.1, fun x hx => (ht x hx).2.1, l.eval levels, hz, + fun x hx => (ht x hx).2.2.2⟩, ?_, ?_⟩ + · exact lamR_mem (fun x hx => (ht x hx).2.2.1) + · exact annotated_pi_mem_univ hl.symm hAt.2.2 (fun x hx => (ht x hx).2.2.2) + +end Ix.Theory.Model.Telescope diff --git a/Ix/Theory/Model/Value.lean b/Ix/Theory/Model/Value.lean new file mode 100644 index 000000000..b710b905f --- /dev/null +++ b/Ix/Theory/Model/Value.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.SetModel.Ops +import Ix.Theory.Certified.Level + +namespace Ix.Theory.Model + +open SetTheory SetModel Certified + +/-- Only zero versus positive matters to the set-theoretic binder operators. -/ +def regime (p : PropWhen) (values : List Nat) : Nat := + if p.holds (values.getD · 0) then 0 else 1 + +@[simp] theorem regime_zeroCondition (l : VLevel) (values : List Nat) : + regime (zeroCondition l) values = 0 ↔ l.eval values = 0 := by + unfold regime + rw [zeroCondition_correct] + by_cases h : l.eval values = 0 <;> simp [h] + +@[simp] theorem regime_always (values : List Nat) : regime .always values = 0 := rfl + +@[simp] theorem regime_never (values : List Nat) : regime .never values = 1 := rfl + +@[simp] theorem regime_instCondition (p : PropWhen) (ls : List VLevel) (values : List Nat) : + regime (instCondition ls p) values = regime p (ls.map (VLevel.eval values)) := by + unfold regime + rw [instCondition_correct] + +universe u +variable {V : Type u} [SetTheory V] + +/-- The universe bound for the actual product operator, including an +arbitrary-size domain when the codomain sort is zero. -/ +theorem piR_mem_univ {a b : Nat} {A : V} {B : V → V} + (hA : A ∈ˢ univ a) (hB : ∀ x, x ∈ˢ A → B x ∈ˢ univ b) : + piR b A B ∈ˢ univ (VLevel.natIMax a b) := by + cases b with + | zero => + change piR 0 A B ∈ˢ univ 0 + rw [univ_zero] + exact piR_zero_mem_univZero + | succ b => + have hn : Nat.max a (b + 1) ≠ 0 := + Nat.ne_of_gt (Nat.lt_of_lt_of_le (Nat.zero_lt_succ b) (Nat.le_max_right a (b + 1))) + simp only [VLevel.natIMax, Nat.add_one_ne_zero, ↓reduceIte] + rw [piR_pos (Nat.succ_ne_zero b)] + apply (univ_isTGUniverse hn).piSet_mem + · exact univ_mono (Nat.le_max_left ..) A hA + · intro x hx + exact univ_mono (Nat.le_max_right ..) (B x) (hB x hx) + +theorem annotated_pi_mem_univ {a : Nat} {b : VLevel} {p : PropWhen} + {values : List Nat} {A : V} {B : V → V} + (hp : p = zeroCondition b) + (hA : A ∈ˢ univ a) (hB : ∀ x, x ∈ˢ A → B x ∈ˢ univ (b.eval values)) : + piR (regime p values) A B ∈ˢ univ (VLevel.natIMax a (b.eval values)) := by + subst p + rw [piR_zero_agree (regime_zeroCondition b values) (fun _ _ => rfl)] + exact piR_mem_univ hA hB + +/-- The fixed empty proposition used by the certified primitive signature. -/ +noncomputable def falseValue : V := empty + +theorem falseValue_uninhabited (x : V) : ¬ x ∈ˢ (falseValue : V) := not_mem_empty x + +theorem falseValue_has_sort : (falseValue : V) ∈ˢ univ 0 := empty_mem_univ 0 + +/-- Type of dependent elimination from the empty proposition. -/ +noncomputable def falseElimType (level : Nat) : V := + piR level (piR (level + 1) empty (fun _ => univ level)) fun motive => + piR level empty (fun x => app motive x) + +/-- The empty eliminator is a function graph at positive sorts and the proof +point at sort zero. Its type is inhabited because its second domain is empty. -/ +noncomputable def falseElimValue (level : Nat) : V := + lamR level (piR (level + 1) empty (fun _ => univ level)) fun _ => + lamR level empty (fun _ => empty) + +theorem falseElimValue_mem (level : Nat) : + (falseElimValue level : V) ∈ˢ falseElimType level := by + apply lamR_mem + intro motive _ + apply lamR_mem + intro x hx + exact (not_mem_empty x hx).elim + +end Ix.Theory.Model diff --git a/Ix/Theory/Model/WellDenoted.lean b/Ix/Theory/Model/WellDenoted.lean new file mode 100644 index 000000000..2cfb83cb2 --- /dev/null +++ b/Ix/Theory/Model/WellDenoted.lean @@ -0,0 +1,148 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Interpret + +/-! +# Hereditary validity of annotated expressions + +Application carries domain membership, and both binder forms carry a +codomain universe whose zero test agrees with the annotation. The invariant +is a semantic specification, not input accepted on trust: checker rules must +construct it. Projection validity follows its major premise; literal validity +is structural. Their membership still requires admitted primitive facts. +-/ + +namespace Ix.Theory.Model + +open SetTheory SetModel + +universe u v w +variable {β : Type u} {V : Type v} [SetTheory V] + +def WellDenoted (constants : Assignment β V) (levels : List Nat) + (env : Nat → V) : AExpr β → Prop + | .bvar _ | .sort _ | .const .. => True + | .app f a => + WellDenoted constants levels env f ∧ WellDenoted constants levels env a ∧ + ∃ (v : Nat) (A : V) (B : V → V), + interp constants levels env f ∈ˢ piR v A B ∧ + interp constants levels env a ∈ˢ A ∧ + ∀ x, x ∈ˢ A → B x ∈ˢ univ v + | .lam p A b => + WellDenoted constants levels env A ∧ + (∀ x, x ∈ˢ interp constants levels env A → + WellDenoted constants levels (Valuation.cons x env) b) ∧ + ∃ (v : Nat) (B : V → V), (regime p levels = 0 ↔ v = 0) ∧ + ∀ x, x ∈ˢ interp constants levels env A → + interp constants levels (Valuation.cons x env) b ∈ˢ B x ∧ + B x ∈ˢ univ v + | .forallE p A B => + WellDenoted constants levels env A ∧ + (∀ x, x ∈ˢ interp constants levels env A → + WellDenoted constants levels (Valuation.cons x env) B) ∧ + ∃ v : Nat, (regime p levels = 0 ↔ v = 0) ∧ + ∀ x, x ∈ˢ interp constants levels env A → + interp constants levels (Valuation.cons x env) B ∈ˢ univ v + | .proj _ _ e => WellDenoted constants levels env e + | .natLit _ => True + +theorem wellDenoted_liftN (e : AExpr β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (n k : Nat) : + WellDenoted constants levels env (e.liftN n k) ↔ + WellDenoted constants levels (Valuation.skip n k env) e := by + induction e generalizing k env with + | lam p A b hA hb | forallE p A b hA hb => + simp only [AExpr.liftN, WellDenoted, hA, hb, interp_liftN, Valuation.skip_cons] + | _ => simp_all [AExpr.liftN, WellDenoted, interp_liftN] + +/-- Substitution also needs hereditary validity of the substituted argument. +Interpretation equality alone cannot supply this fact. -/ +theorem wellDenoted_inst (e a : AExpr β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (k : Nat) + (ha : WellDenoted constants levels (Valuation.skip k 0 env) a) + (he : WellDenoted constants levels + (Valuation.insert k (interp constants levels (Valuation.skip k 0 env) a) env) e) : + WellDenoted constants levels env (e.inst a k) := by + induction e generalizing k env with + | bvar i => + by_cases hi : i < k + · simp [AExpr.inst, AExpr.instVar, hi, WellDenoted] + · by_cases hik : i = k + · simpa [AExpr.inst, AExpr.instVar, hi, hik, wellDenoted_liftN] using ha + · simp [AExpr.inst, AExpr.instVar, hi, hik, WellDenoted] + | app f b hf hb => + rcases he with ⟨hfw, hbw, v, A, B, hfm, hbm, hB⟩ + exact ⟨hf env k ha hfw, hb env k ha hbw, v, A, B, + by simpa only [interp_inst] using hfm, + by simpa only [interp_inst] using hbm, hB⟩ + | lam p A b hA hb => + rcases he with ⟨hAw, hbw, v, B, hz, hB⟩ + refine ⟨hA env k ha hAw, ?_, v, B, hz, ?_⟩ + · intro x hx + apply hb (Valuation.cons x env) (k + 1) + · simpa only [Valuation.skip_succ_cons] using ha + · simp only [Valuation.skip_succ_cons, Valuation.insert_cons] + exact hbw x (by simpa only [interp_inst] using hx) + · intro x hx + simpa only [interp_inst, Valuation.skip_succ_cons, Valuation.insert_cons] using + hB x (by simpa only [interp_inst] using hx) + | forallE p A b hA hb => + rcases he with ⟨hAw, hbw, v, hz, hB⟩ + refine ⟨hA env k ha hAw, ?_, v, hz, ?_⟩ + · intro x hx + apply hb (Valuation.cons x env) (k + 1) + · simpa only [Valuation.skip_succ_cons] using ha + · simp only [Valuation.skip_succ_cons, Valuation.insert_cons] + exact hbw x (by simpa only [interp_inst] using hx) + · intro x hx + simpa only [interp_inst, Valuation.skip_succ_cons, Valuation.insert_cons] using + hB x (by simpa only [interp_inst] using hx) + | proj _ _ e ih => exact ih env k ha he + | _ => exact he + +theorem wellDenoted_instL (e : AExpr β) (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) (ls : List VLevel) : + WellDenoted constants levels env (e.instL ls) ↔ + WellDenoted constants (ls.map (VLevel.eval levels)) env e := by + induction e generalizing env with + | lam p A b hA hb | forallE p A b hA hb => + simp only [AExpr.instL, WellDenoted, hA, hb, interp_instL, regime_instCondition] + | _ => simp_all [AExpr.instL, WellDenoted, interp_instL] + +theorem wellDenoted_rename {γ : Type w} (e : AExpr β) (mapping : β → γ) + (constants : Assignment β V) (constants' : Assignment γ V) + (h : ∀ r ls, constants' (r.rename mapping) ls = constants r ls) + (levels : List Nat) (env : Nat → V) : + WellDenoted constants' levels env (e.rename mapping) ↔ + WellDenoted constants levels env e := by + induction e generalizing env with + | lam p A b hA hb | forallE p A b hA hb => + simp only [AExpr.rename, WellDenoted, hA, hb, interp_rename _ _ _ _ h] + | _ => simp_all [AExpr.rename, WellDenoted, interp_rename _ _ _ _ h] + +/-- Conservative beta uses the actual lambda domain even in the proof regime. +The application invariant's possibly different product domain is insufficient +for this step when the lambda's value is the proof point. -/ +theorem wellDenoted_beta {constants : Assignment β V} {levels : List Nat} + {env : Nat → V} {p : Certified.PropWhen} {A b a : AExpr β} + (hl : WellDenoted constants levels env (.lam p A b)) + (haw : WellDenoted constants levels env a) + (ha : interp constants levels env a ∈ˢ interp constants levels env A) : + WellDenoted constants levels env (b.inst a) ∧ + interp constants levels env (.app (.lam p A b) a) = + interp constants levels env (b.inst a) := by + rcases hl with ⟨_, hbw, v, B, hz, hB⟩ + constructor + · apply wellDenoted_inst + · simpa using haw + · simpa using hbw _ ha + · simp only [interp, interp_inst, Valuation.skip_zero, Valuation.insert_zero] + apply app_lamR ha (fun x hx => (hB x hx).1) + intro hp x hx + have hv := hz.mp hp + simpa only [hv, univ_zero] using (hB x hx).2 + +end Ix.Theory.Model diff --git a/Ix/Theory/NOTICE b/Ix/Theory/NOTICE new file mode 100644 index 000000000..60eaca747 --- /dev/null +++ b/Ix/Theory/NOTICE @@ -0,0 +1,51 @@ +Lean4Ix notices +================ + +Copyright (c) 2026 Argument Computer Corporation + +Lean4Ix is based on lean4lean: + + https://github.com/digama0/lean4lean + +The lean4lean-derived portions were received under the Apache License, +Version 2.0. Their original copyright, attribution, licensing, and +modification-notice requirements continue to apply. The repository history +and retained per-file notices provide the detailed provenance of those +portions. + +The executable kernel model is itself derived from the Lean 4 kernel. Certain +files also identify more specific Apache-2.0 sources in their headers: + + * Main.lean contains code copied from leanprover-community/import-graph. + * Lean4Lean/Std/ToExpr.lean contains code from mathlib. + * Lean4Lean/Verify/QSort.lean is adapted from Lean 4's qsort verification. + +Lean 4, Batteries, import-graph, and mathlib are distributed under the Apache +License, Version 2.0. When a Lean4Ix distribution includes their code or +artifacts, preserve the license and notice material shipped with them. + +Lean4Ix/Model/SetTheory and Lean4Ix/Model/SetModel contain a port of the +con-leche set-theoretic foundation, dependent-function operators, least +fixed points, tuple and container constructions, and recursor graphs, +received under the Apache License, Version 2.0: + + https://github.com/leanprover/con-leche + revision 86cd20a65660d757cedc81561a44579099b565d0 + +The port retains the upstream license in LICENSE-APACHE. Per-file headers +identify the original files and modifications. The exact source and ported +file hashes are recorded in docs/consistency/con-leche-port.json. This upstream +code remains subject to Apache-2.0; the repository's dual-license default does +not relicense it. + +The generated lake-manifest.json dependency lock and the single-value +lean-toolchain toolchain pin may differ from their lean4lean counterparts. +They are mechanical package metadata governed by the licensing and +modification notices distributed with this repository. + +Except where a contribution or upstream component is explicitly identified +under different terms, contributions intentionally submitted for inclusion in +Lean4Ix are accepted under the same MIT OR Apache-2.0 choice described in +LICENSE, LICENSE-MIT, and LICENSE-APACHE. + +This NOTICE is informational and does not modify any applicable license. diff --git a/Ix/Theory/Named/ConstructorValidityFixtures.lean b/Ix/Theory/Named/ConstructorValidityFixtures.lean new file mode 100644 index 000000000..7d5348b7b --- /dev/null +++ b/Ix/Theory/Named/ConstructorValidityFixtures.lean @@ -0,0 +1,176 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.InductiveFixtures + +open Ix.Theory (VLevel) + +/-! +# Constructor-validity parity fixtures + +Focused singleton declarations for Spec-05. The positive declarations retain +real kernel metadata while remaining inside the already-supported large- +elimination and non-K fragment. The failed declarations pin the nearest +Lean elaborator/kernel rejection for each neighboring positivity or universe +branch; `#guard_msgs` rolls every failed declaration back. +-/ + +namespace Ix.Theory.Named +namespace InductiveFixtures +open VInductDecl + +universe u + +/-! ## Type-valued dependency and positivity matrix -/ + +/-- A source-ordered constructor covering the non-Prop universe boundary, +dependent proof fields, direct recursion, a recursive function, and an +independent/dependent suffix after both recursive outer fields. -/ +inductive ConstructorValidityMatrix (α : Type u) (P : α → Prop) : Type u where + | mk (x : α) (proof : P x) + (direct : ConstructorValidityMatrix α P) + (function : (y : α) → ConstructorValidityMatrix α P) + (later : α) (laterProof : P later) : + ConstructorValidityMatrix α P + +def constructorValidityMatrixType : VInductiveType where + name := ``ConstructorValidityMatrix + uvars := 1 + type := vconst(type_of% @ConstructorValidityMatrix).type + ctors := [⟨vconst(type_of% @ConstructorValidityMatrix.mk), + ``ConstructorValidityMatrix.mk⟩] + +def constructorValidityMatrixDecl : VInductDecl := + ⟨1, 2, [constructorValidityMatrixType]⟩ + +example : constructorValidityMatrixDecl.stage3 = true := rfl + +def constructorValidityMatrixChecked : constructorValidityMatrixDecl.Checked := + constructorValidityMatrixDecl.checked?.get (by decide) + +def constructorValidityMatrixGenerationChecked : + GenerationChecked constructorValidityMatrixDecl := + (identityGeneration? constructorValidityMatrixDecl).get (by decide) + +private def spec05PermC (constant : VConstant) + (levels : List VLevel) : VConstant := + ⟨constant.uvars, constant.type.instL levels⟩ + +example : constructorValidityMatrixGenerationChecked.recursor = + spec05PermC (vconst(type_of% @ConstructorValidityMatrix.rec)) + [.param 1, .param 0] := rfl + +example : constructorValidityMatrixChecked.resultLevel = + .succ (.param 0) := rfl + +example : constructorValidityMatrixChecked.constructors[0].fields.length = 6 := + rfl + +example : constructorValidityMatrixChecked.constructors[0].recursive.map + (fun position => (position.fieldIndex, position.binders.length)) = + [(2, 0), (3, 1)] := rfl + +example : + constructorValidityMatrixGenerationChecked.generatedRules.length = 1 := + rfl + +/-! ## Prop-valued recursive-function universe boundary -/ + +/-- The ordinary field `a : α` reaches the impredicative-Prop constructor +universe branch. The varying recursive target prevents parameter promotion, +and the single constructor remains a legitimate non-K large eliminator. -/ +inductive PropRecursiveBoundary (α : Type u) : α → Prop where + | mk (a : α) (next : (b : α) → PropRecursiveBoundary α b) : + PropRecursiveBoundary α a + +def propRecursiveBoundaryType : VInductiveType where + name := ``PropRecursiveBoundary + uvars := 1 + type := vconst(type_of% @PropRecursiveBoundary).type + ctors := [⟨vconst(type_of% @PropRecursiveBoundary.mk), + ``PropRecursiveBoundary.mk⟩] + +def propRecursiveBoundaryDecl : VInductDecl := + ⟨1, 1, [propRecursiveBoundaryType]⟩ + +example : propRecursiveBoundaryDecl.stage3 = true := rfl + +def propRecursiveBoundaryChecked : propRecursiveBoundaryDecl.Checked := + propRecursiveBoundaryDecl.checked?.get (by decide) + +def propRecursiveBoundaryGenerationChecked : + GenerationChecked propRecursiveBoundaryDecl := + (identityGeneration? propRecursiveBoundaryDecl).get (by decide) + +example : propRecursiveBoundaryGenerationChecked.recursor = + spec05PermC (vconst(type_of% @PropRecursiveBoundary.rec)) + [.param 1, .param 0] := rfl + +example : propRecursiveBoundaryChecked.resultLevel = .zero := rfl + +example : propRecursiveBoundaryChecked.constructors[0].fields.length = 2 := rfl + +example : propRecursiveBoundaryChecked.constructors[0].recursive.map + (fun position => (position.fieldIndex, position.binders.length)) = + [(1, 1)] := rfl + +example : propRecursiveBoundaryGenerationChecked.generatedRules.length = 1 := + rfl + +/-! ## Nearest-kernel rejection matrix -/ + +namespace KernelDifferential + +opaque Spec05TypeBox : Type → Type +opaque Spec05ProofBox : Type → Prop +opaque Spec05DepProofBox (α : Type) : α → Prop + +/-- +error: (kernel) arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05NestedNegative.mk' has a non positive occurrence of the datatypes being declared +-/ +#guard_msgs (whitespace := lax) in +inductive Spec05NestedNegative : Type where + | mk : ((Spec05NestedNegative → Prop) → Spec05NestedNegative) → + Spec05NestedNegative + +/-- +error: (kernel) arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05FamilyNonrecursive.mk' contains a non valid occurrence of the datatypes being declared +-/ +#guard_msgs (whitespace := lax) in +inductive Spec05FamilyNonrecursive : Type where + | mk : Spec05TypeBox Spec05FamilyNonrecursive → Spec05FamilyNonrecursive + +/-- +error: (kernel) arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05FamilyProof.mk' contains a non valid occurrence of the datatypes being declared +-/ +#guard_msgs (whitespace := lax) in +inductive Spec05FamilyProof : Type where + | mk : Spec05ProofBox Spec05FamilyProof → Spec05FamilyProof + +/-- +error: (kernel) arg #2 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05RecursiveDependency.mk' contains a non valid occurrence of the datatypes being declared +-/ +#guard_msgs (whitespace := lax) in +inductive Spec05RecursiveDependency : Type where + | mk (recursive : Spec05RecursiveDependency) + (proof : Spec05DepProofBox Spec05RecursiveDependency recursive) : + Spec05RecursiveDependency + +/-- +error: Invalid universe level in constructor `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05UniverseReject.mk`: Parameter `α` has type + Type +at universe level + 2 +which is not less than or equal to the inductive type's resulting universe level + 1 +-/ +#guard_msgs (whitespace := lax) in +inductive Spec05UniverseReject : Type where + | mk (α : Type) : Spec05UniverseReject + +end KernelDifferential +end InductiveFixtures +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean b/Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean new file mode 100644 index 000000000..e5c89c2ca --- /dev/null +++ b/Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean @@ -0,0 +1,1307 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Meta +import Ix.Theory.Named.Projection +import Ix.Theory.Named.Typing.InductiveLemmas + +open Ix.Theory (VLevel) + +/-! +# Projection expressibility fixtures + +The main fixture is simultaneously parameterized, universe-polymorphic, and +dependent: the final field type mentions the preceding projection. It is +small enough that the complete recursor encoding remains definitionally +inspectable. +-/ + +namespace Ix.Theory.Named.Tests.ProjectionExpressibility + +open Ix.Theory.Named VInductDecl + +universe u v + +structure DependentRecord (α : Type u) (family : α → Type v) where + key : α + value : family key + +def dependentRecordCtor : VConstVal := + ⟨vconst(type_of% @DependentRecord.mk), ``DependentRecord.mk⟩ + +def dependentRecordType : VInductiveType where + name := ``DependentRecord + uvars := 2 + type := vconst(type_of% @DependentRecord).type + ctors := [dependentRecordCtor] + +def dependentRecordDecl : VInductDecl := + ⟨2, 2, [dependentRecordType]⟩ + +example : dependentRecordDecl.checked?.isSome = true := rfl + +def dependentRecordChecked : dependentRecordDecl.Checked := + dependentRecordDecl.checked?.get (by decide) + +def dependentRecordGeneration : dependentRecordDecl.GenerationChecked := + dependentRecordChecked.identityGeneration + +def dependentRecordView : VStructureView where + source := dependentRecordDecl + generation := dependentRecordGeneration + constructor := dependentRecordGeneration.block.ctorPairs[0] + constructor_eq := rfl + raw_indices_eq := rfl + checked_indices_eq := rfl + recursive_eq := rfl + fieldSorts := [.succ (.param 0), .succ (.param 1)] + fieldSorts_length := rfl + +def dependentRecordEnv : VEnv := + (VEnv.empty.addInductGeneration dependentRecordGeneration).get (by decide) + +theorem dependentRecord_add : + VEnv.empty.addInductGeneration dependentRecordGeneration = + some dependentRecordEnv := rfl + +theorem dependentRecord_trace : + Nonempty (VEnv.AddInductGenerationTrace VEnv.empty + dependentRecordEnv dependentRecordGeneration) := + VEnv.addInductGeneration_trace dependentRecord_add + +theorem dependentRecordDecl_wf : + dependentRecordDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = dependentRecordType := + List.mem_singleton.1 (by simpa [dependentRecordDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · exact ⟨⟨_, by type_tac⟩, ⟨⟨_, by type_tac⟩, trivial⟩⟩ + · intro c hc + have hc' : c = dependentRecordCtor := by + simpa [dependentRecordType] using hc + subst c + constructor + · simp [dependentRecordDecl, dependentRecordType, + dependentRecordCtor, VInductDecl.fieldsWF, + VInductDecl.ctorFields, VInductDecl.isRecField, + VInductDecl.recArg?, VInductDecl.recTarget?, + VInductDecl.recFieldIdxs, VInductDecl.sortLevel, + VExpr.dropN, VExpr.resultOf, VExpr.appHead, + VExpr.appArgs] + exact ⟨ + ⟨VLevel.succ (.param 0), by type_tac, VLevel.le_max_left⟩, + ⟨VLevel.succ (.param 1), by type_tac, VLevel.le_max_right⟩⟩ + · simp [dependentRecordDecl, dependentRecordType, + dependentRecordCtor, VInductDecl.ctorFields, + VInductDecl.recFieldIdxs, VInductDecl.sortLevel, + VExpr.dropN, VExpr.resultOf, VExpr.forallN, + VExpr.liftTelN, VExpr.appArgs] + exact .nil + +theorem dependentRecordGeneration_wf : + dependentRecordGeneration.WF VEnv.empty := + (dependentRecordChecked.wf_of_decl + dependentRecordDecl_wf).identityGeneration .empty + +theorem dependentRecordEnv_ordered : dependentRecordEnv.Ordered := + VEnv.addInductGeneration_WF .empty dependentRecordGeneration_wf + dependentRecord_add + +theorem dependentRecordEnv_wf : dependentRecordEnv.WF := + ⟨[.induct dependentRecordDecl], + .decl (.induct dependentRecordGeneration_wf dependentRecord_add) .empty⟩ + +theorem dependentRecord_generation_semantics : + dependentRecordView.GenerationSemantics dependentRecordEnv := by + rcases dependentRecord_trace with ⟨trace⟩ + exact .ofGenerationTrace dependentRecordGeneration_wf trace + +theorem dependentRecord_registered : + dependentRecordView.Registered dependentRecordEnv := by + rcases dependentRecord_trace with ⟨trace⟩ + refine { + family := trace.family_lookup + constructor := ?_ + recursor := trace.rec_lookup + rules := fun _ h => trace.rule_mem h } + apply trace.ctor_lookup + rw [← dependentRecordGeneration.rawCtors_eq] + exact List.mem_map.2 ⟨dependentRecordView.constructor, + by + change dependentRecordView.constructor ∈ + dependentRecordView.generation.block.ctorPairs + rw [dependentRecordView.constructor_eq] + simp, + rfl⟩ + +theorem dependentRecord_view_wf : + dependentRecordView.WF dependentRecordEnv := by + refine { + toRegistered := dependentRecord_registered + generationSemantics := dependentRecord_generation_semantics + parameters := ?_ + parameters_length := rfl + fieldTelescope := ?_ + smallFields := ?_ } + · exact ⟨⟨_, by type_tac⟩, ⟨⟨_, by type_tac⟩, trivial⟩⟩ + · exact .cons (by type_tac) (.cons (by type_tac) .nil) + · intro h + change VInductDecl.ElimMode.large = .small at h + contradiction + +/-- The checked artifact retains both parameters and exactly the two +dependent fields from the real kernel declaration. -/ +example : dependentRecordGeneration.block.rawParams = + [.sort (.succ (.param 0)), + .forallE (.bvar 0) (.sort (.succ (.param 1)))] := rfl + +example : dependentRecordView.fields = + [.bvar 1, .app (.bvar 1) (.bvar 0)] := rfl + +example : dependentRecordGeneration.elimination = .large := rfl + +private def permC (ci : VConstant) (levels : List VLevel) : VConstant := + ⟨ci.uvars, ci.type.instL levels⟩ + +example : dependentRecordGeneration.recursor = + permC (vconst(type_of% @DependentRecord.rec)) + [.param 1, .param 2, .param 0] := rfl + +def symbolicLevels : List VLevel := [.param 0, .param 1] + +/-- Parameters in the context `[family, α]`, outermost first. -/ +def symbolicParams : List VExpr := [.bvar 1, .bvar 0] + +def symbolicStructureType : VExpr := + dependentRecordView.structureType symbolicLevels symbolicParams + +example : dependentRecordView.specializedFields symbolicLevels symbolicParams = + [.bvar 1, .app (.bvar 1) (.bvar 0)] := rfl + +def keyCode : VStructureView.ProjectionCode := + (dependentRecordView.projectionCodes symbolicLevels symbolicParams)[0] + +def valueCode : VStructureView.ProjectionCode := + (dependentRecordView.projectionCodes symbolicLevels symbolicParams)[1] + +/-- Constructor reduction selects the first field for `key`. -/ +example : keyCode.minor = + .lam (.bvar 1) + (.lam (.app (.bvar 1) (.bvar 0)) (.bvar 1)) := rfl + +/-- Constructor reduction selects the second field for `value`. -/ +example : valueCode.minor = + .lam (.bvar 1) + (.lam (.app (.bvar 1) (.bvar 0)) (.bvar 0)) := rfl + +/-- The first field type is `α`. -/ +example : keyCode.typeFn = + .lam symbolicStructureType (.bvar 2) := rfl + +/-- The dependent second field type is `family (key major)`: the earlier +projection program occurs in the later motive, rather than being supplied by +an unconstrained witness. -/ +example : valueCode.typeFn = + .lam symbolicStructureType + (.app (.bvar 1) (.app keyCode.projector.lift (.bvar 0))) := rfl + +example : dependentRecordView.projectionLevels keyCode.fieldSort symbolicLevels = + [.succ (.param 0), .param 0, .param 1] := rfl + +example : dependentRecordView.projectionLevels valueCode.fieldSort symbolicLevels = + [.succ (.param 1), .param 0, .param 1] := rfl + +example : dependentRecordView.project? symbolicLevels symbolicParams 2 (.bvar 0) = + none := rfl + +/-- Eta reconstruction uses every generated projector in constructor-field +order, including the projector whose motive depends on the earlier field. -/ +example : dependentRecordView.etaRebuild symbolicLevels symbolicParams + (.bvar 0) = + VExpr.appN (.const ``DependentRecord.mk symbolicLevels) + (symbolicParams ++ + [.app keyCode.projector (.bvar 0), + .app valueCode.projector (.bvar 0)]) := rfl + +/-! A fully constrained `VEnv.TrProj` witness in a universe-polymorphic +local context. -/ + +def symbolicAlphaType : VExpr := .sort (.succ (.param 0)) + +def symbolicFamilyType : VExpr := + .forallE (.bvar 0) (.sort (.succ (.param 1))) + +/-- The major binder type is written over `[family, α]`. -/ +def symbolicMajorBinderType : VExpr := + dependentRecordView.structureType symbolicLevels [.bvar 1, .bvar 0] + +def symbolicContext : List VExpr := + [symbolicMajorBinderType, symbolicFamilyType, symbolicAlphaType] + +/-- The same parameters as seen under the major binder. -/ +def symbolicMajorParams : List VExpr := [.bvar 2, .bvar 1] + +def symbolicMajor : VExpr := .bvar 0 + +theorem symbolicLevels_wf : + ∀ level ∈ symbolicLevels, level.WF 2 := by + simp [symbolicLevels, VLevel.WF] + +theorem symbolicParams_spine : + ∃ resultLevel, dependentRecordEnv.SpineWF 2 symbolicContext + (dependentRecordView.familyType.instL symbolicLevels) + symbolicMajorParams (.sort resultLevel) := by + refine ⟨.max (.succ (.param 0)) (.succ (.param 1)), + .cons (by type_tac) ?_⟩ + exact .cons (by type_tac) .nil + +theorem symbolicMajor_hasType : + dependentRecordEnv.HasType 2 symbolicContext symbolicMajor + (dependentRecordView.structureType symbolicLevels symbolicMajorParams) := by + exact .bvar .zero + +def symbolicKeyCode : VStructureView.ProjectionCode := + (dependentRecordView.projectionCodes symbolicLevels symbolicMajorParams)[0] + +def symbolicValueCode : VStructureView.ProjectionCode := + (dependentRecordView.projectionCodes symbolicLevels symbolicMajorParams)[1] + +def symbolicFieldContext : List VExpr := + [.app (.bvar 3) (.bvar 0), .bvar 3, + dependentRecordView.structureType symbolicLevels symbolicMajorParams] ++ + symbolicContext + +def symbolicConstructorApp : VExpr := + dependentRecordView.projectionConstructorApp symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) + [.bvar 3, .app (.bvar 3) (.bvar 0)] + +def symbolicInnerStructureType : VExpr := + dependentRecordView.structureType symbolicLevels [.bvar 5, .bvar 4] + +theorem symbolicConstructor_hasType : + dependentRecordEnv.HasType 2 symbolicFieldContext symbolicConstructorApp + symbolicInnerStructureType := by + have hc := VEnv.HasType.const + (Γ := symbolicFieldContext) dependentRecord_view_wf.constructor + symbolicLevels_wf (by rfl) + have hα : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 5) (.sort (.succ (.param 0))) := by + type_tac + have hFamily : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 4) (.forallE (.bvar 5) (.sort (.succ (.param 1)))) := by + type_tac + have hKey : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 1) (.bvar 5) := by + type_tac + have hValue : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 0) (.app (.bvar 4) (.bvar 1)) := by + type_tac + have hcα := hc.app hα + have hcFamily := hcα.app hFamily + have hcKey := hcFamily.app hKey + have hcValue := hcKey.app hValue + change dependentRecordEnv.HasType 2 symbolicFieldContext + symbolicConstructorApp symbolicInnerStructureType at hcValue + exact hcValue + +private def takeLamDomains : Nat → VExpr → List VExpr + | 0, _ => [] + | n + 1, .lam A body => A :: takeLamDomains n body + | _ + 1, _ => [] + +private def dropLamBody : Nat → VExpr → VExpr + | 0, e => e + | n + 1, .lam _ body => dropLamBody n body + | _ + 1, e => e + +private def dropForallBody : Nat → VExpr → VExpr + | 0, e => e + | n + 1, .forallE _ body => dropForallBody n body + | _ + 1, e => e + +theorem symbolicStructure_isType : dependentRecordEnv.IsType 2 symbolicContext + (dependentRecordView.structureType symbolicLevels symbolicMajorParams) := by + obtain ⟨resultLevel, hspine⟩ := symbolicParams_spine + have hfamily := VEnv.HasType.const + (Γ := symbolicContext) dependentRecord_view_wf.family + symbolicLevels_wf (by rfl) + exact ⟨resultLevel, by + simpa [VStructureView.structureType] using hspine.hasType_appN hfamily⟩ + +theorem symbolicMajorBinder_isType : dependentRecordEnv.IsType 2 + [symbolicFamilyType, symbolicAlphaType] symbolicMajorBinderType := by + let resultLevel := VLevel.max (.succ (.param 0)) (.succ (.param 1)) + have hspine : dependentRecordEnv.SpineWF 2 + [symbolicFamilyType, symbolicAlphaType] + (dependentRecordView.familyType.instL symbolicLevels) + [.bvar 1, .bvar 0] (.sort resultLevel) := by + refine .cons (by type_tac) ?_ + exact .cons (by type_tac) .nil + have hfamily := VEnv.HasType.const + (Γ := [symbolicFamilyType, symbolicAlphaType]) + dependentRecord_view_wf.family symbolicLevels_wf (by rfl) + exact ⟨resultLevel, by + simpa [symbolicMajorBinderType, VStructureView.structureType] using + hspine.hasType_appN hfamily⟩ + +theorem symbolicFieldContext_wf : + OnCtx symbolicFieldContext (dependentRecordEnv.IsType 2) := by + refine ⟨?_, ⟨_, by type_tac⟩⟩ + refine ⟨?_, ⟨_, by type_tac⟩⟩ + refine ⟨?_, symbolicStructure_isType⟩ + refine ⟨?_, symbolicMajorBinder_isType⟩ + refine ⟨?_, ⟨_, by type_tac⟩⟩ + exact ⟨trivial, ⟨_, by type_tac⟩⟩ + +def symbolicKeyMotive : VExpr := symbolicKeyCode.typeFn.liftN 3 + +def symbolicKeyMinor : VExpr := symbolicKeyCode.minor.liftN 3 + +def symbolicKeyRuleLevels : List VLevel := + dependentRecordView.projectionLevels symbolicKeyCode.fieldSort symbolicLevels + +def symbolicKeyRule : VDefEq := dependentRecordGeneration.generatedRules[0] + +def symbolicKeyRuleType : VExpr := + .forallE (.sort (.succ (.param 0))) + (.forallE (.forallE (.bvar 0) (.sort (.succ (.param 1)))) + (.forallE + (.forallE + (dependentRecordView.structureType symbolicLevels [.bvar 1, .bvar 0]) + (.sort (.succ (.param 0)))) + (.forallE + (.forallE (.bvar 2) + (.forallE (.app (.bvar 2) (.bvar 0)) + (.app (.bvar 2) + (.app + (.app + (.app + (.app (.const ``DependentRecord.mk symbolicLevels) + (.bvar 4)) + (.bvar 3)) + (.bvar 1)) + (.bvar 0))))) + (.forallE (.bvar 3) + (.forallE (.app (.bvar 3) (.bvar 0)) + (.app (.bvar 3) + (.app + (.app + (.app + (.app (.const ``DependentRecord.mk symbolicLevels) + (.bvar 5)) + (.bvar 4)) + (.bvar 1)) + (.bvar 0)))))))) + +theorem symbolicKeyRuleType_eq : + symbolicKeyRule.type.instL symbolicKeyRuleLevels = + symbolicKeyRuleType := rfl + +def symbolicKeyRuleArgs : List VExpr := + [.bvar 5, .bvar 4, symbolicKeyMotive, symbolicKeyMinor, + .bvar 1, .bvar 0] + +def symbolicKeyRuleResult : VExpr := + VExpr.instRev (dropForallBody 6 symbolicKeyRuleType) symbolicKeyRuleArgs + +theorem symbolicKeyRule_spine : + dependentRecordEnv.SpineWF 2 symbolicFieldContext + (symbolicKeyRule.type.instL symbolicKeyRuleLevels) + symbolicKeyRuleArgs symbolicKeyRuleResult := by + rw [symbolicKeyRuleType_eq] + unfold symbolicKeyRuleArgs symbolicKeyRuleResult + refine .cons (by type_tac) ?_ + refine .cons (by type_tac) ?_ + refine .cons ?_ ?_ + · have hMotiveShape : symbolicKeyMotive = + .lam + ((dependentRecordView.structureType symbolicLevels + symbolicMajorParams).liftN 3) + (.bvar 6) := rfl + rw [hMotiveShape] + obtain ⟨structureLevel, hstructure⟩ := + symbolicStructure_isType.weakN dependentRecordEnv_ordered + (Ctx.LiftN.zero + [.app (.bvar 3) (.bvar 0), .bvar 3, + dependentRecordView.structureType symbolicLevels + symbolicMajorParams]) + exact VEnv.HasType.lam (u := structureLevel) hstructure (by type_tac) + · refine .cons ?_ ?_ + · change dependentRecordEnv.HasType 2 symbolicFieldContext + symbolicKeyMinor + (.forallE (.bvar 5) + (.forallE (.app (.bvar 5) (.bvar 0)) + (.app (symbolicKeyMotive.liftN 2) + (.app + (.app + (.app + (.app (.const ``DependentRecord.mk symbolicLevels) + (.bvar 7)) + (.bvar 6)) + (.bvar 1)) + (.bvar 0))))) + have hMinorShape : symbolicKeyMinor = + .lam (.bvar 5) + (.lam (.app (.bvar 5) (.bvar 0)) (.bvar 1)) := rfl + rw [hMinorShape] + refine .lam (by type_tac) ?_ + refine .lam (by type_tac) ?_ + have hMotiveLiftShape : symbolicKeyMotive.liftN 2 = + .lam + (dependentRecordView.structureType symbolicLevels + [.bvar 7, .bvar 6]) + (.bvar 8) := rfl + rw [hMotiveLiftShape] + let innerCtor : VExpr := + .app + (.app + (.app + (.app (.const ``DependentRecord.mk symbolicLevels) (.bvar 7)) + (.bvar 6)) + (.bvar 1)) + (.bvar 0) + let innerStructure : VExpr := + dependentRecordView.structureType symbolicLevels [.bvar 7, .bvar 6] + have hkey : dependentRecordEnv.HasType 2 + ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: symbolicFieldContext) + (.bvar 1) (.bvar 7) := by + type_tac + have hctor : dependentRecordEnv.HasType 2 + ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: symbolicFieldContext) + innerCtor innerStructure := by + have hc := VEnv.HasType.const + (Γ := ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: + symbolicFieldContext)) + dependentRecord_view_wf.constructor symbolicLevels_wf (by rfl) + have hα : dependentRecordEnv.HasType 2 + ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: symbolicFieldContext) + (.bvar 7) (.sort (.succ (.param 0))) := by + type_tac + have hFamily : dependentRecordEnv.HasType 2 + ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: symbolicFieldContext) + (.bvar 6) + (.forallE (.bvar 7) (.sort (.succ (.param 1)))) := by + type_tac + have hValue : dependentRecordEnv.HasType 2 + ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: symbolicFieldContext) + (.bvar 0) (.app (.bvar 6) (.bvar 1)) := by + type_tac + have hcValue := (((hc.app hα).app hFamily).app hkey).app hValue + change dependentRecordEnv.HasType 2 + ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: symbolicFieldContext) + innerCtor innerStructure at hcValue + exact hcValue + have hbody : dependentRecordEnv.HasType 2 + (innerStructure :: (.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: + symbolicFieldContext) + (.bvar 8) (.sort (.succ (.param 0))) := by + dsimp [innerStructure] + type_tac + have hbetaRaw := VEnv.IsDefEq.beta hbody hctor + have hbeta : dependentRecordEnv.IsDefEq 2 + ((.app (.bvar 5) (.bvar 0)) :: .bvar 5 :: symbolicFieldContext) + (.app (.lam innerStructure (.bvar 8)) innerCtor) + (.bvar 7) (.sort (.succ (.param 0))) := by + simpa [innerCtor, innerStructure, VExpr.inst, VExpr.instVar] using hbetaRaw + exact hbeta.symm.defeq hkey + · refine .cons (by type_tac) ?_ + exact .cons (by type_tac) .nil + +def symbolicKeyRuleBinders : List VExpr := + takeLamDomains 6 (symbolicKeyRule.lhs.instL symbolicKeyRuleLevels) + +def symbolicKeyRuleLhsBody : VExpr := + dropLamBody 6 (symbolicKeyRule.lhs.instL symbolicKeyRuleLevels) + +def symbolicKeyRuleRhsBody : VExpr := + dropLamBody 6 (symbolicKeyRule.rhs.instL symbolicKeyRuleLevels) + +def symbolicKeyRuleTypeBody : VExpr := + dropForallBody 6 (symbolicKeyRule.type.instL symbolicKeyRuleLevels) + +theorem symbolicKeyRule_lhs_shape : + symbolicKeyRule.lhs.instL symbolicKeyRuleLevels = + VExpr.lamN symbolicKeyRuleBinders symbolicKeyRuleLhsBody := rfl + +theorem symbolicKeyRule_rhs_shape : + symbolicKeyRule.rhs.instL symbolicKeyRuleLevels = + VExpr.lamN symbolicKeyRuleBinders symbolicKeyRuleRhsBody := rfl + +theorem symbolicKeyRule_type_shape : + symbolicKeyRule.type.instL symbolicKeyRuleLevels = + VExpr.forallN symbolicKeyRuleBinders symbolicKeyRuleTypeBody := rfl + +theorem symbolicKeyRuleBinders_length : symbolicKeyRuleBinders.length = 6 := rfl + +theorem symbolicKeyRuleArgs_length : symbolicKeyRuleArgs.length = 6 := rfl + +theorem symbolicKeyRule_registered : dependentRecordEnv.defeqs symbolicKeyRule := by + apply dependentRecord_view_wf.rules + decide + +theorem symbolicKeyRule_levels_wf : + ∀ level ∈ symbolicKeyRuleLevels, level.WF 2 := by + decide + +theorem symbolicKeyRule_levels_length : + symbolicKeyRuleLevels.length = symbolicKeyRule.uvars := by + decide + +theorem symbolicKeyRule_reduces : dependentRecordEnv.IsDefEqU 2 + symbolicFieldContext + (VExpr.instRev symbolicKeyRuleLhsBody symbolicKeyRuleArgs) + (VExpr.instRev symbolicKeyRuleRhsBody symbolicKeyRuleArgs) := by + have hextra : dependentRecordEnv.IsDefEq 2 symbolicFieldContext + (symbolicKeyRule.lhs.instL symbolicKeyRuleLevels) + (symbolicKeyRule.rhs.instL symbolicKeyRuleLevels) + (symbolicKeyRule.type.instL symbolicKeyRuleLevels) := + .extra symbolicKeyRule_registered symbolicKeyRule_levels_wf + symbolicKeyRule_levels_length + have happlied := hextra.appN_congr symbolicKeyRule_spine + have hlhsType := hextra.hasType.1 + rw [symbolicKeyRule_lhs_shape] at hlhsType + obtain ⟨hlhsTel, lhsType, hlhsBody⟩ := VEnv.HasType.lamN_wf + dependentRecordEnv_ordered symbolicFieldContext_wf hlhsType + have hlhsSpine := symbolicKeyRule_spine + rw [symbolicKeyRule_type_shape] at hlhsSpine + have hlhsRetarget := hlhsSpine.retarget + (symbolicKeyRuleArgs_length.trans symbolicKeyRuleBinders_length.symm) + lhsType + have hcollapseL := VEnv.IsDefEq.appN_lamN dependentRecordEnv_ordered + hlhsTel hlhsBody hlhsRetarget + (symbolicKeyRuleArgs_length.trans symbolicKeyRuleBinders_length.symm) + have hrhsType := hextra.hasType.2 + rw [symbolicKeyRule_rhs_shape] at hrhsType + obtain ⟨hrhsTel, rhsType, hrhsBody⟩ := VEnv.HasType.lamN_wf + dependentRecordEnv_ordered symbolicFieldContext_wf hrhsType + have hrhsSpine := symbolicKeyRule_spine + rw [symbolicKeyRule_type_shape] at hrhsSpine + have hrhsRetarget := hrhsSpine.retarget + (symbolicKeyRuleArgs_length.trans symbolicKeyRuleBinders_length.symm) + rhsType + have hcollapseR := VEnv.IsDefEq.appN_lamN dependentRecordEnv_ordered + hrhsTel hrhsBody hrhsRetarget + (symbolicKeyRuleArgs_length.trans symbolicKeyRuleBinders_length.symm) + rw [symbolicKeyRule_lhs_shape, symbolicKeyRule_rhs_shape] at happlied + exact VEnv.IsDefEqU.trans dependentRecordEnv_wf symbolicFieldContext_wf + ⟨_, hcollapseL.symm⟩ + (VEnv.IsDefEqU.trans dependentRecordEnv_wf symbolicFieldContext_wf + ⟨_, happlied⟩ ⟨_, hcollapseR⟩) + +theorem symbolicKeyProjector_hasType : + dependentRecordEnv.HasType 2 symbolicContext symbolicKeyCode.projector + (.forallE + (dependentRecordView.structureType symbolicLevels symbolicMajorParams) + (.app symbolicKeyCode.typeFn.lift (.bvar 0))) := by + obtain ⟨resultLevel, hspine⟩ := symbolicParams_spine + have hfamily := VEnv.HasType.const + (Γ := symbolicContext) dependentRecord_view_wf.family + symbolicLevels_wf (by rfl) + have hstructure : dependentRecordEnv.HasType 2 symbolicContext + (dependentRecordView.structureType symbolicLevels symbolicMajorParams) + (.sort resultLevel) := by + simpa [VStructureView.structureType] using hspine.hasType_appN hfamily + have W : Ctx.LiftN 1 0 symbolicContext + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) := .one + change dependentRecordEnv.HasType 2 symbolicContext (.lam _ _) + (.forallE _ _) + refine .lam hstructure ?_ + change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (VExpr.appN + (.const dependentRecordView.recursorName + (dependentRecordView.projectionLevels + symbolicKeyCode.fieldSort symbolicLevels)) + (symbolicMajorParams.map (VExpr.liftN 1) ++ + [symbolicKeyCode.typeFn.lift, symbolicKeyCode.minor.lift, + .bvar 0])) + (.app symbolicKeyCode.typeFn.lift (.bvar 0)) + apply dependentRecord_view_wf.recursorProjection_hasType + dependentRecordEnv_ordered symbolicLevels symbolicLevels_wf rfl + (symbolicMajorParams.map (VExpr.liftN 1)) (by rfl) + (fieldSort := symbolicKeyCode.fieldSort) + · refine ⟨resultLevel, ?_⟩ + have hfamilyClosed : + (dependentRecordView.familyType.instL symbolicLevels).ClosedN 0 := by + simpa using + (dependentRecordEnv_ordered.closedC + dependentRecord_view_wf.family).instL + have hspine' := hspine.weakN dependentRecordEnv_ordered W + rw [hfamilyClosed.liftN_eq (Nat.zero_le _)] at hspine' + simpa [VExpr.liftN] using hspine' + · change VLevel.WF 2 (.succ (.param 0)) + decide + · rfl + · exact ⟨resultLevel, by + simpa [VExpr.liftN] using hstructure.weakN dependentRecordEnv_ordered W⟩ + · change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.lam + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1))) + (.bvar 4)) + (.forallE + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1))) + (.sort (.succ (.param 0)))) + refine VEnv.HasType.lam (u := resultLevel) ?_ (by type_tac) + simpa [VExpr.liftN] using + hstructure.weakN dependentRecordEnv_ordered W + · change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.lam (.bvar 3) + (.lam (.app (.bvar 3) (.bvar 0)) (.bvar 1))) + (.forallE (.bvar 3) + (.forallE (.app (.bvar 3) (.bvar 0)) + (.app + (.lam + (.app + (.app (.const ``DependentRecord symbolicLevels) (.bvar 5)) + (.bvar 4)) + (.bvar 6)) + (.app + (.app + (.app + (.app (.const ``DependentRecord.mk symbolicLevels) + (.bvar 5)) + (.bvar 4)) + (.bvar 1)) + (.bvar 0))))) + refine .lam (by type_tac) ?_ + refine .lam (by type_tac) ?_ + have hkey : dependentRecordEnv.HasType 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 1) (.bvar 5) := by + type_tac + apply (show dependentRecordEnv.IsDefEq 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 5) + (.app + (.lam + (.app + (.app (.const ``DependentRecord symbolicLevels) (.bvar 5)) + (.bvar 4)) + (.bvar 6)) + (.app + (.app + (.app + (.app (.const ``DependentRecord.mk symbolicLevels) (.bvar 5)) + (.bvar 4)) + (.bvar 1)) + (.bvar 0))) + (.sort (.succ (.param 0))) from ?_).defeq hkey + let S : VExpr := + .app + (.app (.const ``DependentRecord symbolicLevels) (.bvar 5)) + (.bvar 4) + let ctorApp : VExpr := + .app + (.app + (.app + (.app (.const ``DependentRecord.mk symbolicLevels) (.bvar 5)) + (.bvar 4)) + (.bvar 1)) + (.bvar 0) + have hbody : dependentRecordEnv.HasType 2 + (S :: (.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 6) (.sort (.succ (.param 0))) := by + dsimp [S] + type_tac + have hctor : dependentRecordEnv.HasType 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + ctorApp S := by + have hc := VEnv.HasType.const + (Γ := ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext)) + dependentRecord_view_wf.constructor symbolicLevels_wf (by rfl) + have hα : dependentRecordEnv.HasType 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 5) (.sort (.succ (.param 0))) := by + type_tac + have hFamily : dependentRecordEnv.HasType 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 4) + (.forallE (.bvar 5) (.sort (.succ (.param 1)))) := by + type_tac + have hKey : dependentRecordEnv.HasType 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 1) (.bvar 5) := by + type_tac + have hValue : dependentRecordEnv.HasType 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 0) (.app (.bvar 4) (.bvar 1)) := by + type_tac + have hcα := hc.app hα + have hcFamily := hcα.app hFamily + have hcKey := hcFamily.app hKey + have hcValue := hcKey.app hValue + change dependentRecordEnv.HasType 2 + ((.app (.bvar 3) (.bvar 0)) :: .bvar 3 :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + ctorApp S at hcValue + exact hcValue + have hbeta := VEnv.IsDefEq.beta hbody hctor + simpa [S, ctorApp, VExpr.inst, VExpr.instVar] using hbeta.symm + · exact .bvar .zero + +def symbolicKeyProjectorBody : VExpr := + match symbolicKeyCode.projector.liftN 3 with + | .lam _ body => body + | expression => expression + +theorem symbolicKeyProjector_lift_shape : + symbolicKeyCode.projector.liftN 3 = + .lam symbolicInnerStructureType symbolicKeyProjectorBody := by + decide + +theorem symbolicKeyProjector_beta_shape : + symbolicKeyProjectorBody.inst symbolicConstructorApp = + VExpr.instRev symbolicKeyRuleLhsBody symbolicKeyRuleArgs := by + decide + +theorem symbolicKeyRule_rhs_result_shape : + VExpr.instRev symbolicKeyRuleRhsBody symbolicKeyRuleArgs = + .app (.app symbolicKeyMinor (.bvar 1)) (.bvar 0) := by + decide + +/-- The generated key projector computes on the generated constructor by +the registered recursor iota rule. -/ +theorem symbolicKey_constructor_defeq : dependentRecordEnv.IsDefEq 2 + symbolicFieldContext + (.app (symbolicKeyCode.projector.liftN 3) symbolicConstructorApp) + (.bvar 1) (.bvar 5) := by + have W3 : Ctx.LiftN 3 0 symbolicContext symbolicFieldContext := + .zero [.app (.bvar 3) (.bvar 0), .bvar 3, + dependentRecordView.structureType symbolicLevels symbolicMajorParams] + have hprojector := symbolicKeyProjector_hasType.weakN + dependentRecordEnv_ordered W3 + rw [symbolicKeyProjector_lift_shape] at hprojector + obtain ⟨_, ⟨projectorBodyType, hprojectorBody⟩⟩ := + hprojector.lam_inv dependentRecordEnv_ordered symbolicFieldContext_wf + have hprojectorBeta := VEnv.IsDefEq.beta hprojectorBody + symbolicConstructor_hasType + rw [← symbolicKeyProjector_lift_shape, + symbolicKeyProjector_beta_shape] at hprojectorBeta + have hprojectorToRule : dependentRecordEnv.IsDefEqU 2 + symbolicFieldContext + (.app (symbolicKeyCode.projector.liftN 3) symbolicConstructorApp) + (VExpr.instRev symbolicKeyRuleLhsBody symbolicKeyRuleArgs) := + ⟨projectorBodyType.inst symbolicConstructorApp, hprojectorBeta⟩ + + have houterBody : dependentRecordEnv.HasType 2 + ((.bvar 5) :: symbolicFieldContext) + (.lam (.app (.bvar 5) (.bvar 0)) (.bvar 1)) + (.forallE (.app (.bvar 5) (.bvar 0)) (.bvar 7)) := by + refine .lam (by type_tac) (by type_tac) + have hkey : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 1) (.bvar 5) := by + type_tac + have houterBeta := VEnv.IsDefEq.beta houterBody hkey + change dependentRecordEnv.IsDefEq 2 symbolicFieldContext + (.app symbolicKeyMinor (.bvar 1)) _ _ at houterBeta + have hvalue : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 0) (.app (.bvar 4) (.bvar 1)) := by + type_tac + have houterApplied := VEnv.IsDefEq.appDF houterBeta hvalue + have hinnerBody : dependentRecordEnv.HasType 2 + ((.app (.bvar 4) (.bvar 1)) :: symbolicFieldContext) + (.bvar 2) (.bvar 6) := by + type_tac + have hinnerBeta := VEnv.IsDefEq.beta hinnerBody hvalue + have hminorToKey := houterApplied.trans hinnerBeta + rw [← symbolicKeyRule_rhs_result_shape] at hminorToKey + have hresult := VEnv.IsDefEqU.trans dependentRecordEnv_wf + symbolicFieldContext_wf hprojectorToRule + (VEnv.IsDefEqU.trans dependentRecordEnv_wf symbolicFieldContext_wf + symbolicKeyRule_reduces ⟨_, hminorToKey⟩) + exact hresult.of_r dependentRecordEnv_wf symbolicFieldContext_wf hkey + +def symbolicValueTypeFnBody : VExpr := + .app (.bvar 5) + (.app (symbolicKeyCode.projector.liftN 4) (.bvar 0)) + +theorem symbolicValueTypeFn_lift_shape : + symbolicValueCode.typeFn.lift.liftN 2 = + .lam symbolicInnerStructureType symbolicValueTypeFnBody := by + decide + +theorem symbolicValueTypeFn_beta_shape : + symbolicValueTypeFnBody.inst symbolicConstructorApp = + .app (.bvar 4) + (.app (symbolicKeyCode.projector.liftN 3) + symbolicConstructorApp) := by + decide + +theorem symbolicValueTypeFnBody_hasType : dependentRecordEnv.HasType 2 + (symbolicInnerStructureType :: symbolicFieldContext) + symbolicValueTypeFnBody (.sort (.succ (.param 1))) := by + have W4 : Ctx.LiftN 4 0 symbolicContext + (symbolicInnerStructureType :: symbolicFieldContext) := + .zero [symbolicInnerStructureType, + .app (.bvar 3) (.bvar 0), .bvar 3, + dependentRecordView.structureType symbolicLevels symbolicMajorParams] + have hkeyProjector := symbolicKeyProjector_hasType.weakN + dependentRecordEnv_ordered W4 + have hkeyAtMajor := hkeyProjector.app (VEnv.HasType.bvar (.zero)) + change dependentRecordEnv.HasType 2 + (symbolicInnerStructureType :: symbolicFieldContext) _ + (.app + (.lam + (dependentRecordView.structureType symbolicLevels + [.bvar 6, .bvar 5]) + (.bvar 7)) + (.bvar 0)) at hkeyAtMajor + have hkeyBetaRaw : dependentRecordEnv.IsDefEq 2 + (symbolicInnerStructureType :: symbolicFieldContext) + (.app + (.lam + (dependentRecordView.structureType symbolicLevels + [.bvar 6, .bvar 5]) + (.bvar 7)) + (.bvar 0)) + ((VExpr.bvar 7).inst (.bvar 0)) + ((VExpr.sort (.succ (.param 0))).inst (.bvar 0)) := by + apply VEnv.IsDefEq.beta + · type_tac + · exact .bvar .zero + have hkeyBeta : dependentRecordEnv.IsDefEq 2 + (symbolicInnerStructureType :: symbolicFieldContext) + (.app + (.lam + (dependentRecordView.structureType symbolicLevels + [.bvar 6, .bvar 5]) + (.bvar 7)) + (.bvar 0)) + (.bvar 6) (.sort (.succ (.param 0))) := by + simpa [VExpr.inst, VExpr.instVar] using hkeyBetaRaw + have hkeyAtMajor' := hkeyBeta.defeq hkeyAtMajor + have hfamily : dependentRecordEnv.HasType 2 + (symbolicInnerStructureType :: symbolicFieldContext) + (.bvar 5) + (.forallE (.bvar 6) (.sort (.succ (.param 1)))) := by + type_tac + exact hfamily.app hkeyAtMajor' + +theorem symbolicValueProjector_hasType : + dependentRecordEnv.HasType 2 symbolicContext symbolicValueCode.projector + (.forallE + (dependentRecordView.structureType symbolicLevels symbolicMajorParams) + (.app symbolicValueCode.typeFn.lift (.bvar 0))) := by + obtain ⟨resultLevel, hspine⟩ := symbolicParams_spine + have hfamily := VEnv.HasType.const + (Γ := symbolicContext) dependentRecord_view_wf.family + symbolicLevels_wf (by rfl) + have hstructure : dependentRecordEnv.HasType 2 symbolicContext + (dependentRecordView.structureType symbolicLevels symbolicMajorParams) + (.sort resultLevel) := by + simpa [VStructureView.structureType] using hspine.hasType_appN hfamily + have W : Ctx.LiftN 1 0 symbolicContext + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) := .one + change dependentRecordEnv.HasType 2 symbolicContext (.lam _ _) + (.forallE _ _) + refine .lam hstructure ?_ + change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (VExpr.appN + (.const dependentRecordView.recursorName + (dependentRecordView.projectionLevels + symbolicValueCode.fieldSort symbolicLevels)) + (symbolicMajorParams.map (VExpr.liftN 1) ++ + [symbolicValueCode.typeFn.lift, symbolicValueCode.minor.lift, + .bvar 0])) + (.app symbolicValueCode.typeFn.lift (.bvar 0)) + apply dependentRecord_view_wf.recursorProjection_hasType + dependentRecordEnv_ordered symbolicLevels symbolicLevels_wf rfl + (symbolicMajorParams.map (VExpr.liftN 1)) (by rfl) + (fieldSort := symbolicValueCode.fieldSort) + · refine ⟨resultLevel, ?_⟩ + have hfamilyClosed : + (dependentRecordView.familyType.instL symbolicLevels).ClosedN 0 := by + simpa using + (dependentRecordEnv_ordered.closedC + dependentRecord_view_wf.family).instL + have hspine' := hspine.weakN dependentRecordEnv_ordered W + rw [hfamilyClosed.liftN_eq (Nat.zero_le _)] at hspine' + simpa [VExpr.liftN] using hspine' + · change VLevel.WF 2 (.succ (.param 1)) + decide + · rfl + · exact ⟨resultLevel, by + simpa [VExpr.liftN] using hstructure.weakN dependentRecordEnv_ordered W⟩ + · change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + symbolicValueCode.typeFn.lift + (.forallE + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1))) + (.sort (.succ (.param 1)))) + change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.lam + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1))) + (.app (.bvar 3) + (.app (symbolicKeyCode.projector.lift.liftN 1 1) (.bvar 0)))) + (.forallE + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1))) + (.sort (.succ (.param 1)))) + refine VEnv.HasType.lam (u := resultLevel) ?_ ?_ + · simpa [VExpr.liftN] using + hstructure.weakN dependentRecordEnv_ordered W + · have Wbody : Ctx.LiftN 1 0 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) := .one + have hkeyProjector := + (symbolicKeyProjector_hasType.weakN dependentRecordEnv_ordered W).weakN + dependentRecordEnv_ordered Wbody + have hkeyAtMajor := hkeyProjector.app (VEnv.HasType.bvar (.zero)) + have hkeyTypeFn : symbolicKeyCode.typeFn = + .lam + (dependentRecordView.structureType symbolicLevels symbolicMajorParams) + (.bvar 3) := rfl + rw [hkeyTypeFn] at hkeyAtMajor + change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + _ + (.app + (.lam + (dependentRecordView.structureType symbolicLevels + [.bvar 4, .bvar 3]) + (.bvar 5)) + (.bvar 0)) at hkeyAtMajor + have hkeyBetaRaw : dependentRecordEnv.IsDefEq 2 + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.app + (.lam + (dependentRecordView.structureType symbolicLevels + [.bvar 4, .bvar 3]) + (.bvar 5)) + (.bvar 0)) + ((VExpr.bvar 5).inst (.bvar 0)) + ((VExpr.sort (.succ (.param 0))).inst (.bvar 0)) := by + apply VEnv.IsDefEq.beta + · type_tac + · exact .bvar .zero + have hkeyBeta : dependentRecordEnv.IsDefEq 2 + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.app + (.lam + (dependentRecordView.structureType symbolicLevels + [.bvar 4, .bvar 3]) + (.bvar 5)) + (.bvar 0)) + (.bvar 4) (.sort (.succ (.param 0))) := by + simpa [VExpr.inst, VExpr.instVar] using hkeyBetaRaw + have hkeyAtMajor' := hkeyBeta.defeq hkeyAtMajor + have hprojectorLift : + VExpr.liftN 1 (VExpr.liftN 1 symbolicKeyCode.projector) = + symbolicKeyCode.projector.lift.liftN 1 1 := rfl + rw [hprojectorLift] at hkeyAtMajor' + have hfamilyAtMajor : dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) :: + dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.bvar 3) + (.forallE (.bvar 4) (.sort (.succ (.param 1)))) := by + type_tac + exact hfamilyAtMajor.app hkeyAtMajor' + · change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.lam (.bvar 3) + (.lam (.app (.bvar 3) (.bvar 0)) (.bvar 0))) + (dependentRecordView.projectionMinorType symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) + (dependentRecordView.specializedFields symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1))) + symbolicValueCode.typeFn.lift) + have hfields : dependentRecordView.specializedFields symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) = + [.bvar 3, .app (.bvar 3) (.bvar 0)] := rfl + rw [hfields] + change dependentRecordEnv.HasType 2 + (dependentRecordView.structureType symbolicLevels symbolicMajorParams :: + symbolicContext) + (.lam (.bvar 3) + (.lam (.app (.bvar 3) (.bvar 0)) (.bvar 0))) + (.forallE (.bvar 3) + (.forallE (.app (.bvar 3) (.bvar 0)) + (.app (symbolicValueCode.typeFn.lift.liftN 2) + (dependentRecordView.projectionConstructorApp symbolicLevels + (symbolicMajorParams.map (VExpr.liftN 1)) + [.bvar 3, .app (.bvar 3) (.bvar 0)])))) + refine .lam (by type_tac) ?_ + refine .lam (by type_tac) ?_ + have htargetBeta := VEnv.IsDefEq.beta + symbolicValueTypeFnBody_hasType symbolicConstructor_hasType + rw [← symbolicValueTypeFn_lift_shape, + symbolicValueTypeFn_beta_shape] at htargetBeta + have hfamily : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 4) + (.forallE (.bvar 5) (.sort (.succ (.param 1)))) := by + type_tac + have htargetToNatural := htargetBeta.trans + (VEnv.IsDefEq.appDF hfamily symbolicKey_constructor_defeq) + have hvalue : dependentRecordEnv.HasType 2 symbolicFieldContext + (.bvar 0) (.app (.bvar 4) (.bvar 1)) := by + type_tac + exact htargetToNatural.defeq' hvalue + · exact .bvar .zero + +def symbolicKeyResult : VExpr := + .app symbolicKeyCode.projector symbolicMajor + +def symbolicValueResult : VExpr := + .app symbolicValueCode.projector symbolicMajor + +theorem key_representable : + dependentRecordEnv.TrProj 2 symbolicContext dependentRecordView + symbolicLevels symbolicMajorParams 0 symbolicMajor symbolicKeyResult := by + refine { + viewWF := dependentRecord_view_wf + levelsWF := symbolicLevels_wf + levels_length := rfl + params_length := rfl + paramsSpine := symbolicParams_spine + majorType := symbolicMajor_hasType + program := ⟨symbolicKeyCode, rfl, rfl, + symbolicKeyProjector_hasType⟩ } + +theorem value_representable : + dependentRecordEnv.TrProj 2 symbolicContext dependentRecordView + symbolicLevels symbolicMajorParams 1 symbolicMajor symbolicValueResult := by + refine { + viewWF := dependentRecord_view_wf + levelsWF := symbolicLevels_wf + levels_length := rfl + params_length := rfl + paramsSpine := symbolicParams_spine + majorType := symbolicMajor_hasType + program := ⟨symbolicValueCode, rfl, rfl, + symbolicValueProjector_hasType⟩ } + +/-- The one generated iota equation used by both projection programs is +actually registered in the final Theory environment. -/ +example : dependentRecordGeneration.generatedRules.length = 1 := rfl + +theorem dependentRecord_rules_registered : + ∀ rule ∈ dependentRecordGeneration.generatedRules, + dependentRecordEnv.defeqs rule := + dependentRecord_view_wf.rules + +/-! ## Frozen legacy surface + +The seven fields below preserve the exact pre-Spec-13 theorem shapes. They +are intentionally only statement data: constructing this bundle would +reintroduce the old proof obligations. In particular, `wf` permits +unrelated contexts, `uniq` permits unrelated structure names, and every +field omits the environment, universe instantiation, and parameter spine. -/ + +abbrev LegacyTrProj := + List VExpr → Name → Nat → VExpr → VExpr → Prop + +structure LegacyProjectionLaws (R : LegacyTrProj) : Prop where + weak : ∀ {n Γ Γ' s i e e'}, + Ctx.Lift' n Γ Γ' → R Γ s i e e' → + R Γ' s i (e.lift' n) (e'.lift' n) + inverseWeakening : ∀ {env U l Γ Γ' s i e e'}, + VEnv.WF env → OnCtx Γ' (env.IsType U) → Ctx.Lift' l Γ Γ' → + R Γ' s i (e.lift' l) e' → ∃ result, R Γ s i e result + contextDefEq : ∀ {env U Γ₁ Γ₂ s i e₁ e₂ result}, + VEnv.WF env → env.IsDefEqCtx U [] Γ₁ Γ₂ → + env.IsDefEqU U Γ₁ e₁ e₂ → R Γ₁ s i e₁ result → + ∃ result', R Γ₂ s i e₂ result' + wellFormed : ∀ {env U Δ Γ s i e result}, + R Δ s i e result → VExpr.WF env U Γ e → + VExpr.WF env U Γ result + unique : ∀ {env U Γ₁ Γ₂ s₁ s₂ i e₁ e₂ result₁ result₂}, + VEnv.WF env → env.IsDefEqCtx U [] Γ₁ Γ₂ → + R Γ₁ s₁ i e₁ result₁ → R Γ₂ s₂ i e₂ result₂ → + env.IsDefEqU U Γ₁ e₁ e₂ → + env.IsDefEqU U Γ₁ result₁ result₂ + termSubstitution : ∀ {Γ₀ Γ₁ Γ s i e e' e₀ A₀ k}, + Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → R Γ₁ s i e e' → + R Γ s i (e.inst e₀ k) (e'.inst e₀ k) + universeInstantiation : ∀ {U' Γ s i e e'} {ls : List VLevel}, + (∀ level ∈ ls, level.WF U') → R Γ s i e e' → + R (Γ.map (VExpr.instL ls)) s i (e.instL ls) (e'.instL ls) + +/-! ## Zero-field behavior -/ + +universe w + +structure EmptyRecord (α : Type w) where + +def emptyRecordCtor : VConstVal := + ⟨vconst(type_of% @EmptyRecord.mk), ``EmptyRecord.mk⟩ + +def emptyRecordType : VInductiveType where + name := ``EmptyRecord + uvars := 1 + type := vconst(type_of% @EmptyRecord).type + ctors := [emptyRecordCtor] + +def emptyRecordDecl : VInductDecl := + ⟨1, 1, [emptyRecordType]⟩ + +example : emptyRecordDecl.checked?.isSome = true := rfl + +def emptyRecordChecked : emptyRecordDecl.Checked := + emptyRecordDecl.checked?.get (by decide) + +def emptyRecordGeneration : emptyRecordDecl.GenerationChecked := + emptyRecordChecked.identityGeneration + +def emptyRecordView : VStructureView where + source := emptyRecordDecl + generation := emptyRecordGeneration + constructor := emptyRecordGeneration.block.ctorPairs[0] + constructor_eq := rfl + raw_indices_eq := rfl + checked_indices_eq := rfl + recursive_eq := rfl + fieldSorts := [] + fieldSorts_length := rfl + +def emptyRecordEnv : VEnv := + (VEnv.empty.addInductGeneration emptyRecordGeneration).get (by decide) + +theorem emptyRecord_add : + VEnv.empty.addInductGeneration emptyRecordGeneration = + some emptyRecordEnv := rfl + +theorem emptyRecord_trace : + Nonempty (VEnv.AddInductGenerationTrace VEnv.empty + emptyRecordEnv emptyRecordGeneration) := + VEnv.addInductGeneration_trace emptyRecord_add + +theorem emptyRecordDecl_wf : emptyRecordDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = emptyRecordType := + List.mem_singleton.1 (by simpa [emptyRecordDecl] using hty) + subst ty + refine ⟨⟨⟨_, by type_tac⟩, trivial⟩, ?_⟩ + intro c hc + have hc' : c = emptyRecordCtor := by + simpa [emptyRecordType] using hc + subst c + constructor + · simp [emptyRecordDecl, emptyRecordType, emptyRecordCtor, + VInductDecl.fieldsWF, VInductDecl.ctorFields, + VExpr.dropN] + · simp [emptyRecordDecl, emptyRecordType, emptyRecordCtor, + VInductDecl.ctorFields, VInductDecl.recFieldIdxs, + VInductDecl.sortLevel, VExpr.dropN, VExpr.resultOf, + VExpr.forallN, VExpr.liftTelN, VExpr.appArgs] + exact .nil + +theorem emptyRecordGeneration_wf : + emptyRecordGeneration.WF VEnv.empty := + (emptyRecordChecked.wf_of_decl + emptyRecordDecl_wf).identityGeneration .empty + +theorem emptyRecord_generation_semantics : + emptyRecordView.GenerationSemantics emptyRecordEnv := by + rcases emptyRecord_trace with ⟨trace⟩ + exact .ofGenerationTrace emptyRecordGeneration_wf trace + +theorem emptyRecord_registered : emptyRecordView.Registered emptyRecordEnv := by + rcases emptyRecord_trace with ⟨trace⟩ + refine { + family := trace.family_lookup + constructor := ?_ + recursor := trace.rec_lookup + rules := fun _ h => trace.rule_mem h } + apply trace.ctor_lookup + rw [← emptyRecordGeneration.rawCtors_eq] + exact List.mem_map.2 ⟨emptyRecordView.constructor, + by + change emptyRecordView.constructor ∈ + emptyRecordView.generation.block.ctorPairs + rw [emptyRecordView.constructor_eq] + simp, + rfl⟩ + +theorem emptyRecord_view_wf : emptyRecordView.WF emptyRecordEnv := by + refine { + toRegistered := emptyRecord_registered + generationSemantics := emptyRecord_generation_semantics + parameters := ⟨⟨_, by type_tac⟩, trivial⟩ + parameters_length := rfl + fieldTelescope := .nil + smallFields := ?_ } + intro _ level hlevel + change level ∈ ([] : List VLevel) at hlevel + contradiction + +example : emptyRecordView.fields = [] := rfl + +example : emptyRecordView.projectionCodes [.param 0] [.bvar 0] = [] := rfl + +theorem emptyRecord_project_none (idx : Nat) (major : VExpr) : + emptyRecordView.project? [.param 0] [.bvar 0] idx major = none := by + simp [VStructureView.project?, show + emptyRecordView.projectionCodes [.param 0] [.bvar 0] = [] from rfl] + +#guard_named_axioms Ix.Theory.Named.Tests.ProjectionExpressibility.dependentRecord_view_wf [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.Tests.ProjectionExpressibility.key_representable [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.Tests.ProjectionExpressibility.value_representable [ + propext, + sorryAx, + Classical.choice, + Quot.sound] + +#guard_named_axioms Ix.Theory.Named.Tests.ProjectionExpressibility.emptyRecord_project_none [propext, Classical.choice, Quot.sound] + +end Ix.Theory.Named.Tests.ProjectionExpressibility diff --git a/Ix/Theory/Named/Inductive.lean b/Ix/Theory/Named/Inductive.lean new file mode 100644 index 000000000..2e67b9fd2 --- /dev/null +++ b/Ix/Theory/Named/Inductive.lean @@ -0,0 +1,3045 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.VDecl +import Ix.Theory.Named.Typing.Basic + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +deriving instance DecidableEq for VLevel +deriving instance DecidableEq for VExpr + +/-- Syntactic underapproximation of `VLevel.IsNeverZero`, +mirroring `Lean.Level.isNeverZero`. -/ +def _root_.Ix.Theory.VLevel.isNeverZero : VLevel → Bool + | .zero | .param _ => false + | .succ _ => true + | .max l₁ l₂ => l₁.isNeverZero || l₂.isNeverZero + | .imax _ l₂ => l₂.isNeverZero + +instance VExpr.decClosedN : ∀ (e : VExpr) (k : Nat), Decidable (e.ClosedN k) + | .bvar i, k => inferInstanceAs (Decidable (i < k)) + | .sort .., _ | .const .., _ => inferInstanceAs (Decidable True) + | .app e1 e2, k => @instDecidableAnd _ _ (decClosedN e1 k) (decClosedN e2 k) + | .lam e1 e2, k => @instDecidableAnd _ _ (decClosedN e1 k) (decClosedN e2 (k+1)) + | .forallE e1 e2, k => @instDecidableAnd _ _ (decClosedN e1 k) (decClosedN e2 (k+1)) + +instance VExpr.decLevelWF : ∀ (e : VExpr) (U : Nat), Decidable (e.LevelWF U) + | .bvar _, _ => inferInstanceAs (Decidable True) + | .sort l, U => VLevel.decidable_WF (n := U) (l := l) + | .const _ ls, U => inferInstanceAs (Decidable (∀ l ∈ ls, l.WF U)) + | .app e1 e2, U | .lam e1 e2, U | .forallE e1 e2, U => + @instDecidableAnd _ _ (decLevelWF e1 U) (decLevelWF e2 U) + +def VExpr.hasConst (n : Name) : VExpr → Bool + | .bvar _ | .sort _ => false + | .const c _ => c == n + | .app e1 e2 | .lam e1 e2 | .forallE e1 e2 => e1.hasConst n || e2.hasConst n + +/-- Context lifting changes only bound-variable indices and therefore +preserves the constants occurring in a Theory expression. -/ +@[simp] theorem VExpr.hasConst_lift' (expression : VExpr) (lift : Lift) + (name : Name) : + (expression.lift' lift).hasConst name = expression.hasConst name := by + induction expression generalizing lift <;> + simp [VExpr.hasConst, *] + +/-- `[.bvar (off+m-1), ..., .bvar off]`: the spine referring to the last `m` +binders, skipping the innermost `off`. -/ +def VExpr.bvarRevRange (off : Nat) : Nat → List VExpr + | 0 => [] + | m+1 => .bvar (off + m) :: bvarRevRange off m + +/-- Iterated lambda; the binder list is outermost first. -/ +def VExpr.lamN : List VExpr → VExpr → VExpr + | [], e => e + | A :: As, e => .lam A (lamN As e) + +/-- Iterated pi; the binder list is outermost first. -/ +def VExpr.forallN : List VExpr → VExpr → VExpr + | [], e => e + | A :: As, e => .forallE A (forallN As e) + +/-- Insert `n` binders below a telescope at depth `k`: the entry at depth +`j` within the telescope lifts by `n` at cutoff `k+j`. -/ +def VExpr.liftTelN (n : Nat) : List VExpr → Nat → List VExpr + | [], _ => [] + | A :: As, k => A.liftN n k :: liftTelN n As (k+1) + +/-- The first `n` binder types of an iterated pi, outermost first. -/ +def VExpr.telN : Nat → VExpr → List VExpr + | 0, _ => [] + | n+1, .forallE A rest => A :: telN n rest + | _+1, _ => [] + +/-- Strip `n` binders from an iterated pi. -/ +def VExpr.dropN : Nat → VExpr → VExpr + | 0, e => e + | n+1, .forallE _ rest => dropN n rest + | _+1, e => e + +/-- The result of an iterated pi. -/ +def VExpr.resultOf : VExpr → VExpr + | .forallE _ rest => resultOf rest + | e => e + +/-- The application spine arguments, outermost first. -/ +def VExpr.appArgs : VExpr → List VExpr → List VExpr + | .app f a, acc => appArgs f (a :: acc) + | _, acc => acc + +def VExpr.appHead : VExpr → VExpr + | .app f _ => appHead f + | e => e + +/-- The levels `[.param k, ..., .param (n+k-1)]`; `VLevel.params` shifted by `k`. +The recursor universe list is the elimination level (`.param 0`) followed by +the declaration's levels shifted by one, so declaration-world expressions +enter the recursor's universe context via `instL (params' n 1)`. -/ +def _root_.Ix.Theory.VLevel.params' (n k : Nat) : List VLevel := (List.range n).map fun i => .param (i + k) + +/-- Well-formedness of a binder telescope over a context. -/ +def VEnv.OnTel (env : VEnv) (U : Nat) : List VExpr → List VExpr → Prop + | _, [] => True + | Γ, A :: As => env.IsType U Γ A ∧ OnTel env U (A :: Γ) As + +/-- Pointwise definitional equality of two binder telescopes, checked in the +context generated by the left (raw) telescope. This is deliberately stronger +than whole-`forall` equality: it is the structural evidence a normalizer must +produce so mixed raw/view artifacts never need `forall` injectivity to recover +their binder alignment. -/ +def VEnv.TelDefEq (env : VEnv) (U : Nat) : + List VExpr → List VExpr → List VExpr → Prop + | _, [], [] => True + | Γ, A :: As, A' :: As' => + (∃ u, env.IsDefEq U Γ A A' (.sort u)) ∧ + TelDefEq env U (A :: Γ) As As' + | _, _, _ => False + +namespace VInductDecl + +variable (U : Nat) (T : Name) (np : Nat) + +/-- The result sort of an inductive type past its parameters and +indices. -/ +def sortLevel (ty : VInductiveType) : VLevel := + match VExpr.resultOf (VExpr.dropN np ty.type) with + | .sort l => l + | _ => .zero + +/-- Constructor field types, outermost first. -/ +def ctorFields : VExpr → List VExpr + | .forallE B rest => B :: ctorFields rest + | _ => [] + +/-- The block type applied to its parameters, seen from `off` binders past +the parameter telescope (declaration universes). -/ +def recApp (off : Nat) : VExpr := + VExpr.appN (.const T (VLevel.params U)) (VExpr.bvarRevRange off np) + +/-- Is `B` a direct recursive occurrence at field depth `j`: the block +constant applied to the parameter variables and `ni` block-free index +arguments. -/ +def isRecField (ni j : Nat) (B : VExpr) : Bool := + VExpr.appHead B == .const T (VLevel.params U) && + (VExpr.appArgs B []).length == np + ni && + (VExpr.appArgs B []).take np == VExpr.bvarRevRange j np && + ((VExpr.appArgs B []).drop np).all fun e => !e.hasConst T + +/-- The index arguments of a recursive occurrence (or of a constructor's +result). -/ +def recFieldIdxs (B : VExpr) : List VExpr := (VExpr.appArgs B []).drop np + +/-- One recursive constructor argument after normalization. `binders` is the +possibly empty Pi telescope leading to the recursive target. `fieldIndex` +addresses the constructor field itself, while target indices live under both +the preceding constructor fields and these binders. `targetType` is the +source-ordered family ordinal retained by block analysis; it remains zero in +the one-family compatibility analyzer. -/ +structure RecArg where + fieldIndex : Nat + binders : List VExpr + targetType : Nat + indices : List VExpr + +/-- Whether an expression mentions any family in a block. Mutual analysis +uses one block-wide name set in family formers, recursive-Pi domains, and +recursive indices; checking only the current family would miss negative +occurrences of its siblings. -/ +def _root_.Ix.Theory.Named.VExpr.hasAnyConst (names : List Name) (e : VExpr) : Bool := + names.any e.hasConst + +/-- The part of a family declaration needed to recognize a recursive target. +The position of a header in `familyHeaders` is the `RecArg.targetType` stored +by the block analyzer. -/ +structure FamilyHeader where + name : Name + indices : Nat + +/-- Family headers in declaration order. -/ +def familyHeaders (np : Nat) (types : List VInductiveType) : + List FamilyHeader := + types.map fun ty => + ⟨ty.name, (ctorFields (VExpr.dropN np ty.type)).length⟩ + +/-- Recognize an application of any family in a mutual block. The returned +ordinal is its exact position in `headers`; parameter arguments must be the +shared parameter variables and every index must be free of all block +families. -/ +def blockTarget? (U np j : Nat) (headers : List FamilyHeader) + (names : List Name) (B : VExpr) : Option (Nat × List VExpr) := + let head := B.appHead + let args := B.appArgs [] + let rec loop (target : Nat) : List FamilyHeader → + Option (Nat × List VExpr) + | [] => none + | header :: headers => + if head == .const header.name (VLevel.params U) && + args.length == np + header.indices && + args.take np == VExpr.bvarRevRange j np && + (args.drop np).all fun e => !e.hasAnyConst names then + some (target, args.drop np) + else + loop (target + 1) headers + loop 0 headers + +/-- Recognize a recursive mutual target below a possibly empty positive Pi +telescope. No block family may occur in a Pi domain. -/ +def blockRecTarget? (U np : Nat) (headers : List FamilyHeader) + (names : List Name) : Nat → VExpr → + Option (List VExpr × Nat × List VExpr) + | j, .forallE A rest => + if A.hasAnyConst names then none + else + match blockRecTarget? U np headers names (j+1) rest with + | some (binders, target, indices) => + some (A :: binders, target, indices) + | none => none + | j, B => + match blockTarget? U np j headers names B with + | some (target, indices) => some ([], target, indices) + | none => none + +/-- Analyze one constructor field against every family in a block. -/ +def blockRecArg? (U np : Nat) (headers : List FamilyHeader) + (names : List Name) (j : Nat) (B : VExpr) : Option RecArg := + match blockRecTarget? U np headers names j B with + | some (binders, targetType, indices) => + some { fieldIndex := j, binders, targetType, indices } + | none => none + +/-- Recursive arguments in source field order, with block-relative target +ordinals. -/ +def blockRecArgs (U np : Nat) (headers : List FamilyHeader) + (names : List Name) : List VExpr → (j : Nat := 0) → List RecArg + | [], _ => [] + | B :: Bs, j => + match blockRecArg? U np headers names j B with + | some r => r :: blockRecArgs U np headers names Bs (j+1) + | none => blockRecArgs U np headers names Bs (j+1) + +/-- Positional mutual recursive classification for every constructor field. +Unlike `blockRecArgs`, this list retains `none` entries, giving semantic +consumers an exact field-by-field alignment without rerunning the analyzer. -/ +def blockRecArgsAt (U np : Nat) (headers : List FamilyHeader) + (names : List Name) : List VExpr → (j : Nat := 0) → + List (Option RecArg) + | [], _ => [] + | B :: Bs, j => + blockRecArg? U np headers names j B :: + blockRecArgsAt U np headers names Bs (j + 1) + +/-- A mutual constructor field is either a positive recursive target of some +family in the block or is free of every block family. -/ +def blockStage3Field (U np : Nat) (headers : List FamilyHeader) + (names : List Name) (j : Nat) (B : VExpr) : Bool := + (blockRecArg? U np headers names j B).isSome || + !B.hasAnyConst names + +/-- Structural mutual constructor shape. Fields may target any family, but +the constructor result must target its owning family ordinal. -/ +def blockStage3Ctor (U np : Nat) (headers : List FamilyHeader) + (names : List Name) (owner : Nat) : Nat → VExpr → Bool + | j, .forallE B rest => + blockStage3Field U np headers names j B && + blockStage3Ctor U np headers names owner (j+1) rest + | j, result => + match blockTarget? U np j headers names result with + | some (target, _) => target == owner + | none => false + +/-- Recognize the kernel's one-family `isRecArg` shape in raw VExpr normal +form. Pi domains must be free of the family (the local strict-positivity +condition); the terminal target must be the family applied to the declaration +parameters and family-free indices. The returned telescope is outermost first. +-/ +def recTarget? (ni : Nat) : Nat → VExpr → Option (List VExpr × List VExpr) + | j, .forallE A rest => + if A.hasConst T then none + else + match recTarget? ni (j+1) rest with + | some (As, idxs) => some (A :: As, idxs) + | none => none + | j, B => + if isRecField U T np ni j B then some ([], recFieldIdxs np B) else none + +/-- Analyze a constructor field as a recursive argument, retaining its outer +field position and the complete binder telescope leading to the target. -/ +def recArg? (ni j : Nat) (B : VExpr) : Option RecArg := + match recTarget? U T np ni j B with + | some (binders, indices) => + some { fieldIndex := j, binders, targetType := 0, indices } + | none => none + +/-- Recursive arguments of a constructor field telescope, in field order. -/ +def recArgs (ni : Nat) : List VExpr → (j : Nat := 0) → List RecArg + | [], _ => [] + | B :: Bs, j => + match recArg? U T np ni j B with + | some r => r :: recArgs ni Bs (j+1) + | none => recArgs ni Bs (j+1) + +/-- Positional one-family recursive classification retained for compatibility +with the block-wide checked-constructor representation. -/ +def recArgsAt (ni : Nat) : List VExpr → (j : Nat := 0) → + List (Option RecArg) + | [], _ => [] + | B :: Bs, j => recArg? U T np ni j B :: recArgsAt ni Bs (j + 1) + +/-- Positions of the directly recursive fields, with their index +arguments (`j` counts binders past the parameters). -/ +def recPairs (ni : Nat) : List VExpr → (j : Nat := 0) → List (Nat × List VExpr) + | [], _ => [] + | B :: Bs, j => + if isRecField U T np ni j B then (j, recFieldIdxs np B) :: recPairs ni Bs (j+1) + else recPairs ni Bs (j+1) + +/-- Induction-hypothesis binder types for the recursive positions with +their (recursor-universe) index arguments, at depth `p` past the `m` +field binders in context `params ++ [motive]`: the `p`-th is +`motive idxs xⱼ`, the index arguments shifted from field depth `j` (past +the parameters, no motive) into position. -/ +def ihsFrom (m : Nat) : List (Nat × List VExpr) → Nat → List VExpr + | [], _ => [] + | (j, idxs) :: rs, p => + VExpr.appN (.bvar (m+p)) + ((idxs.map fun e => (e.liftN 1 j).liftN (m-j+p)) ++ [.bvar (m-1-j+p)]) :: + ihsFrom m rs (p+1) + +/-- A stage-3 field is either an analyzed recursive argument (possibly under +a strictly-positive Pi telescope) or a type not mentioning the block at all. +The analyzer rejects family occurrences in recursive-Pi domains and indices. +-/ +def stage3Field (ni j : Nat) (B : VExpr) : Bool := + (recArg? U T np ni j B).isSome || !B.hasConst T + +/-- Stage-3 constructor type past the parameters: a telescope of stage-3 +fields ending in the block's type constant applied to the parameters and +block-free index arguments. -/ +def stage3Ctor (ni : Nat) : Nat → VExpr → Bool + | j, .forallE B rest => stage3Field U T np ni j B && stage3Ctor ni (j+1) rest + | j, e => isRecField U T np ni j e + +/-- Levels that are structurally forced to evaluate to zero. This is the +environment-free fragment needed to recognize proof-valued constructor +fields; Verify supplies the exact ordinary-checker sort observations. -/ +def _root_.Ix.Theory.VLevel.isDefinitelyZero : VLevel → Bool + | .zero => true + | .max l₁ l₂ => l₁.isDefinitelyZero && l₂.isDefinitelyZero + | .imax _ l₂ => l₂.isDefinitelyZero + | .param _ | .succ _ => false + +/-- Partial local type synthesis used only to recognize fields whose inferred +sort is structurally `Prop`. Constants and terms requiring reduction remain +unknown and are conservatively treated as data. -/ +def inferLocalType? (Γ : List VExpr) : VExpr → Option VExpr + | .bvar i => Γ[i]? + | .sort l => some (.sort (.succ l)) + | .const _ _ => none + | .app f a => do + let .forallE _ body ← inferLocalType? Γ f | none + return body.inst a + | .lam A body => do + let bodyType ← inferLocalType? (A :: Γ) body + return .forallE A bodyType + | .forallE A body => do + let .sort u ← inferLocalType? Γ A | none + let .sort v ← inferLocalType? (A :: Γ) body | none + return .sort (.imax u v) + +/-- Whether the partial local synthesis proves that a binder is a proof. -/ +def knownProofField (Γ : List VExpr) (B : VExpr) : Bool := + match inferLocalType? Γ B with + | some (.sort l) => l.isDefinitelyZero + | _ => false + +/-- The kernel's singleton large-elimination criterion. Recursive arguments +and proof fields impose no recovery condition; every remaining data field +must occur literally in the constructor result's index spine. The proof-field +test is a conservative environment-free reflection here and is connected to +the exact checker result by Verify. -/ +def subsingletonOK (ni : Nat) (ct : VExpr) : Bool := + let Bs := ctorFields (VExpr.dropN np ct) + let m := Bs.length + let ridx := recFieldIdxs np (VExpr.resultOf (VExpr.dropN np ct)) + let rec loop (Γ : List VExpr) (j : Nat) : List VExpr → Bool + | [] => true + | B :: Bs => + ((recArg? U T np ni j B).isSome || knownProofField Γ B || + ridx.contains (.bvar (m-1-j))) && + loop (B :: Γ) (j+1) Bs + loop (VExpr.telN np ct).reverse 0 Bs + +/-- Large elimination: a never-zero result sort, or the (syntactic) +subsingleton criterion. -/ +def largeElim (ni : Nat) (ty : VInductiveType) : Bool := + (sortLevel np ty).isNeverZero || + match ty.ctors with + | [] => true + | [c] => subsingletonOK U T np ni c.type + | _ => false + +/-- The constructor-shape fragment of the kernel's K-target test. Only the +visible shared-parameter prefix may precede the constructor result. -/ +def isKTargetCtor (nparams : Nat) : Nat → VExpr → Bool + | i, .forallE _ body => + i < nparams && isKTargetCtor nparams (i + 1) body + | _, _ => true + +/-- Whether a checked one-family declaration receives the kernel's K-like +recursor reduction flag. This decision is deliberately independent of +`largeElim`: K eligibility must never be used to bypass the ordinary +large-elimination criterion. -/ +def isKTarget (np : Nat) (resultLevel : VLevel) + (ty : VInductiveType) : Bool := + resultLevel == .zero && + match ty.ctors with + | [ctor] => isKTargetCtor np 0 ctor.type + | _ => false + +/-- A family type is checked before its own constant is declared, so neither +its parameter nor index domains may already mention the family. This is the +one-family form of `checkInductiveTypes`' pre-environment type check. -/ +def typeFormerOK (np : Nat) (ty : VInductiveType) : Bool := + (VExpr.telN np ty.type).all (fun e => !e.hasConst ty.name) && + (ctorFields (VExpr.dropN np ty.type)).all (fun e => !e.hasConst ty.name) + +/-- The direct indexed recursion checks proved by the Stage-3 metatheory. -/ +def stage3DirectCore (U np : Nat) (ty : VInductiveType) : Bool := + let ni := (ctorFields (VExpr.dropN np ty.type)).length + ty.uvars == U && + (VExpr.telN np ty.type).length == np && + (match VExpr.resultOf (VExpr.dropN np ty.type) with + | .sort l => decide (l.WF U) + | _ => false) && + typeFormerOK np ty && + ty.ctors.all fun c => c.uvars == U && + VExpr.telN np c.type == VExpr.telN np ty.type && + stage3Ctor U ty.name np ni 0 (VExpr.dropN np c.type) + +/-- Names reserved by a one-family transaction, in insertion order. -/ +def generatedNames (ty : VInductiveType) : List Name := + ty.name :: (ty.ctors.map (fun c => c.name) ++ [.str ty.name "rec"]) + +/-- Internal duplicate/collision check, matching the sequential kernel name +reservations before any object becomes observable. -/ +def namesOK (ty : VInductiveType) : Bool := decide (generatedNames ty).Nodup + +/-- Kernel metadata types are closed before checking. Keeping this in the +computational descriptor prevents `addInduct` from accepting a hand-built +declaration with loose variables even when its result spine has the expected +head. -/ +def closedOK (ty : VInductiveType) : Bool := + decide (ty.type.ClosedN 0) && ty.ctors.all fun c => decide (c.type.ClosedN 0) + +/-- Every universe annotation in the family and constructor metadata must +refer to one of the declaration's universe parameters. The result-sort check +alone is insufficient: bad parameters or fields can hide an out-of-range +level while leaving the result universe valid. -/ +def levelsOK (U : Nat) (ty : VInductiveType) : Bool := + decide (ty.type.LevelWF U) && ty.ctors.all fun c => decide (c.type.LevelWF U) + +/-- The boolean core of the current one-family checker. Keeping this named +separately from `checked?` lets proofs unpack the accepted checks while all +consumers obtain their normalized data from the same descriptor. -/ +def stage3Core : VInductDecl → Bool + | ⟨U, np, [ty]⟩ => + stage3DirectCore U np ty && (namesOK ty && (closedOK ty && levelsOK U ty)) + | _ => false + +/-- Family names in exact declaration order. -/ +def familyNames (types : List VInductiveType) : List Name := + types.map (·.name) + +/-- The shared parameter telescope selected by the first family. Empty +blocks are rejected by `checkedBlock?`; defining this total function keeps the +dependent traversal itself free of a singleton/nonempty witness. -/ +def blockParams (np : Nat) : List VInductiveType → List VExpr + | [] => [] + | ty :: _ => VExpr.telN np ty.type + +/-- A family former in a mutual block is checked before any family constant +is staged, so every parameter and index domain must be free of every family +in the block. -/ +def blockTypeFormerOK (np : Nat) (names : List Name) + (ty : VInductiveType) : Bool := + (VExpr.telN np ty.type).all (fun e => !e.hasAnyConst names) && + (ctorFields (VExpr.dropN np ty.type)).all + (fun e => !e.hasAnyConst names) + +/-- Names reserved by the mutual pipeline: all families, then all constructors +in family/source order, then one recursor per family. Validation retains this +order as checked data, and the block transaction inserts the same three +constant phases before installing generated rules. -/ +def blockGeneratedNames (types : List VInductiveType) : List Name := + types.map (·.name) ++ + types.flatMap (fun ty => ty.ctors.map (·.name)) ++ + types.map (fun ty => .str ty.name "rec") + +/-- Block-wide duplicate/collision check for all future generated names. -/ +def blockNamesOK (types : List VInductiveType) : Bool := + decide (blockGeneratedNames types).Nodup + +/-- Environment-free structural representation check for one family in a +mutual block. It checks raw metadata anatomy and cross-family positivity. +Environment-sensitive normalization, shared-result-universe semantics, and +staging are supplied separately by `ValidatedBlock.WF` and +`ValidationCertificate`. -/ +def blockFamilyCore (source : VInductDecl) (params : List VExpr) + (owner : Nat) (ty : VInductiveType) : Bool := + let names := familyNames source.types + let headers := familyHeaders source.nparams source.types + ty.uvars == source.uvars && + params.length == source.nparams && + VExpr.telN source.nparams ty.type == params && + (match VExpr.resultOf (VExpr.dropN source.nparams ty.type) with + | .sort l => decide (l.WF source.uvars) + | _ => false) && + blockTypeFormerOK source.nparams names ty && + closedOK ty && levelsOK source.uvars ty && + ty.ctors.all fun c => + c.uvars == source.uvars && + VExpr.telN source.nparams c.type == params && + blockStage3Ctor source.uvars source.nparams headers names owner 0 + (VExpr.dropN source.nparams c.type) + +/-- Constructor identities retained across normalization. Types may change by +WHNF/definitional equality, but names, universe arities, order, and count may +not. -/ +def sameCtorHeaders : List VConstVal → List VConstVal → Bool + | [], [] => true + | c :: cs, c' :: cs' => + c.name == c'.name && c.uvars == c'.uvars && sameCtorHeaders cs cs' + | _, _ => false + +/-- Family identities retained across normalization. -/ +def sameTypeHeaders : List VInductiveType → List VInductiveType → Bool + | [], [] => true + | ty :: tys, ty' :: tys' => + ty.name == ty'.name && ty.uvars == ty'.uvars && + sameCtorHeaders ty.ctors ty'.ctors && sameTypeHeaders tys tys' + | _, _ => false + +/-- Computational coherence between stored kernel metadata and a normalized +analysis view. Normalization may change expression payloads only; declaration +arity and every generated identity remain fixed. -/ +def normalizationShape (source view : VInductDecl) : Bool := + source.uvars == view.uvars && + source.nparams == view.nparams && + sameTypeHeaders source.types view.types + +/-- Constructor headers are reflexively coherent. Kept computational so the +identity normalization below reduces without an external oracle. -/ +theorem sameCtorHeaders_refl : ∀ cs, sameCtorHeaders cs cs = true + | [] => rfl + | c :: cs => by + change ((c.name == c.name) && (c.uvars == c.uvars) && + sameCtorHeaders cs cs) = true + rw [beq_self_eq_true, beq_self_eq_true, sameCtorHeaders_refl] + rfl + +/-- Family headers are reflexively coherent. -/ +theorem sameTypeHeaders_refl : ∀ tys, sameTypeHeaders tys tys = true + | [] => rfl + | ty :: tys => by + change ((ty.name == ty.name) && (ty.uvars == ty.uvars) && + sameCtorHeaders ty.ctors ty.ctors && sameTypeHeaders tys tys) = true + rw [beq_self_eq_true, beq_self_eq_true, sameCtorHeaders_refl, + sameTypeHeaders_refl] + rfl + +theorem normalizationShape_refl (source : VInductDecl) : + normalizationShape source source = true := by + change ((source.uvars == source.uvars) && + (source.nparams == source.nparams) && + sameTypeHeaders source.types source.types) = true + rw [beq_self_eq_true, beq_self_eq_true, sameTypeHeaders_refl] + rfl + +/-- A named, environment-independent normalization boundary. `source` is the +stored declaration whose constants must be added to the Theory environment; +`view` is the WHNF/defeq-normalized syntax inspected by the inductive +analyzer. The boolean coherence proof prevents normalization from changing +declaration identities or ordering. -/ +structure Normalization (source : VInductDecl) where + view : VInductDecl + shape_eq : normalizationShape source view = true + +/-- Construct a normalization boundary by computation. -/ +def normalization? (source view : VInductDecl) : Option (Normalization source) := + if h : normalizationShape source view then some ⟨view, h⟩ else none + +/-- Identity normalization is the compatibility path for declarations already +in the analyzer's raw VExpr normal form. -/ +def Normalization.identity (source : VInductDecl) : Normalization source where + view := source + shape_eq := normalizationShape_refl source + +/-- Semantic validity of a one-family normalization view. The family type is +definitionally equal in the input environment; constructor types are +definitionally equal after the raw family constant has been introduced, which +matches the staging of the kernel's inductive check. `Normalization.BlockWF` +is the arbitrary-block counterpart. -/ +def Normalization.WF {source : VInductDecl} (norm : Normalization source) + (env : VEnv) : Prop := + ∃ raw view, + source.types = [raw] ∧ norm.view.types = [view] ∧ + env.IsDefEqU source.uvars [] raw.type view.type ∧ + ∀ envT, env.addConst raw.name raw.toVConstant = some envT → + List.Forall₂ + (fun rawCtor viewCtor => + envT.IsDefEqU source.uvars [] rawCtor.type viewCtor.type) + raw.ctors view.ctors + +/-- Stage every raw family constant, in source order, without adding any +constructors, recursors, or reduction rules. This is the Theory image of the +environment used by Lean between `declareInductiveTypes` and +`checkConstructors`; it is deliberately validation-only. -/ +def _root_.Ix.Theory.Named.VEnv.stageInductiveTypes (env : VEnv) + (types : List VInductiveType) : Option VEnv := + types.foldlM (fun env type => + env.addConst type.name type.toVConstant) env + +/-- Semantic validity of a normalization view for an arbitrary mutual block. + +Every family type is compared in the common input environment. The exact raw +family list is then staged as one source-ordered fold, and every constructor +comparison is performed in the resulting shared environment. The nested +`Forall₂` relations retain family and constructor order and cannot truncate a +reordered or shorter view. -/ +def Normalization.BlockWF {source : VInductDecl} + (norm : Normalization source) (env blockEnv : VEnv) : Prop := + env.stageInductiveTypes source.types = some blockEnv ∧ + List.Forall₂ + (fun raw view => + env.IsDefEqU source.uvars [] raw.type view.type ∧ + List.Forall₂ + (fun rawCtor viewCtor => + blockEnv.IsDefEqU source.uvars [] + rawCtor.type viewCtor.type) + raw.ctors view.ctors) + source.types norm.view.types + +/-- Whether the recursor may eliminate into a fresh universe or is confined +to `Prop`. -/ +inductive ElimMode where + | large + | small + deriving DecidableEq, Repr + +/-- Interpret the ordinary checker's Boolean large-elimination result in the +consumer-neutral Theory representation. -/ +def ElimMode.ofBool : Bool → ElimMode + | false => .small + | true => .large + +@[simp] theorem ElimMode.ofBool_false : ElimMode.ofBool false = .small := rfl +@[simp] theorem ElimMode.ofBool_true : ElimMode.ofBool true = .large := rfl + +/-- Universe-slot offset used by recursor metadata. Large elimination inserts +the fresh motive universe before the declaration universes; small elimination +adds no universe parameter. -/ +def ElimMode.offset : ElimMode → Nat + | .large => 1 + | .small => 0 + +/-- Universe arity of the generated recursor. -/ +abbrev ElimMode.recUvars (mode : ElimMode) (U : Nat) : Nat := U + mode.offset + +/-- The motive's result level in the recursor universe context. -/ +def ElimMode.motiveLevel : ElimMode → VLevel + | .large => .param 0 + | .small => .zero + +/-- Declaration universes as seen by the recursor. Large elimination shifts +them past the fresh motive level; small elimination retains their order. -/ +abbrev ElimMode.sourceLevels (mode : ElimMode) (U : Nat) : List VLevel := + VLevel.params' U mode.offset + +/-- Identity universe arguments for recursive calls to the generated +recursor. -/ +abbrev ElimMode.recLevels (mode : ElimMode) (U : Nat) : List VLevel := + VLevel.params (mode.recUvars U) + +@[simp] theorem ElimMode.large_offset : ElimMode.large.offset = 1 := rfl +@[simp] theorem ElimMode.small_offset : ElimMode.small.offset = 0 := rfl + +@[simp] theorem ElimMode.large_recUvars (U : Nat) : + ElimMode.large.recUvars U = U + 1 := rfl + +@[simp] theorem ElimMode.small_recUvars (U : Nat) : + ElimMode.small.recUvars U = U := by + simp [ElimMode.recUvars, ElimMode.offset] + +@[simp] theorem ElimMode.large_sourceLevels (U : Nat) : + ElimMode.large.sourceLevels U = VLevel.params' U 1 := rfl + +@[simp] theorem ElimMode.small_sourceLevels (U : Nat) : + ElimMode.small.sourceLevels U = VLevel.params U := rfl + +@[simp] theorem ElimMode.large_motiveLevel : + ElimMode.large.motiveLevel = .param 0 := rfl + +@[simp] theorem ElimMode.small_motiveLevel : + ElimMode.small.motiveLevel = .zero := rfl + +/-- Environment-free elimination analysis used by the raw compatibility +path. Verify's ordinary checker replay refines the singleton criterion with +the exact inferred field sorts. -/ +def eliminationMode (U : Nat) (T : Name) (np ni : Nat) + (ty : VInductiveType) : ElimMode := + if largeElim U T np ni ty then .large else .small + +/-- Normalized data for one constructor. -/ +structure CheckedCtor where + value : VConstVal + fields : List VExpr + recursive : List RecArg + recursiveAt : List (Option RecArg) + resultIndices : List VExpr + +def CheckedCtor.ofDirect (U : Nat) (T : Name) (np ni : Nat) + (c : VConstVal) : CheckedCtor where + value := c + fields := ctorFields (VExpr.dropN np c.type) + recursive := recArgs U T np ni (ctorFields (VExpr.dropN np c.type)) + recursiveAt := recArgsAt U T np ni (ctorFields (VExpr.dropN np c.type)) + resultIndices := recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type)) + +/-- Analyze one constructor against the complete source-ordered family block. +Unlike `ofDirect`, recursive descriptors retain the ordinal of a sibling +target instead of forcing `targetType := 0`. -/ +def CheckedCtor.ofBlock (source : VInductDecl) + (c : VConstVal) : CheckedCtor where + value := c + fields := ctorFields (VExpr.dropN source.nparams c.type) + recursive := blockRecArgs source.uvars source.nparams + (familyHeaders source.nparams source.types) (familyNames source.types) + (ctorFields (VExpr.dropN source.nparams c.type)) + recursiveAt := blockRecArgsAt source.uvars source.nparams + (familyHeaders source.nparams source.types) (familyNames source.types) + (ctorFields (VExpr.dropN source.nparams c.type)) + resultIndices := recFieldIdxs source.nparams + (VExpr.resultOf (VExpr.dropN source.nparams c.type)) + +/-- Checked representation of one family at its exact block ordinal. The +family itself is a type index rather than a replaceable field; this prevents a +descriptor from being reused for another position or declaration. -/ +structure CheckedFamily (source : VInductDecl) (params : List VExpr) + (ordinal : Nat) (type : VInductiveType) where + params_eq : VExpr.telN source.nparams type.type = params + indices : List VExpr + indices_eq : indices = ctorFields (VExpr.dropN source.nparams type.type) + resultLevel : VLevel + result_eq : VExpr.resultOf (VExpr.dropN source.nparams type.type) = + .sort resultLevel + constructors : List CheckedCtor + constructors_eq : constructors = type.ctors.map (CheckedCtor.ofBlock source) + accepted : blockFamilyCore source params ordinal type = true + +/-- Recover the source family indexing a checked family. -/ +def CheckedFamily.value {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {type : VInductiveType} + (_ : CheckedFamily source params ordinal type) : VInductiveType := + type + +/-- Recover the block-relative ordinal indexing a checked family. -/ +def CheckedFamily.ordinal {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {type : VInductiveType} + (_ : CheckedFamily source params ordinal type) : Nat := + ordinal + +/-- A genuinely dependent family spine. Its list index is the exact suffix +of `source.types`, and its natural-number index is the ordinal of that +suffix's head. Consequently neither family order nor recursive-target +numbering is represented by an unchecked parallel list. -/ +inductive CheckedFamilies (source : VInductDecl) (params : List VExpr) : + Nat → List VInductiveType → Type where + | nil {ordinal : Nat} : CheckedFamilies source params ordinal [] + | cons {ordinal : Nat} {type : VInductiveType} + {types : List VInductiveType} + (head : CheckedFamily source params ordinal type) + (tail : CheckedFamilies source params (ordinal + 1) types) : + CheckedFamilies source params ordinal (type :: types) + +namespace CheckedFamilies + +/-- Erase only the dependent evidence, retaining exact family source order. -/ +def values {source : VInductDecl} {params : List VExpr} : + {ordinal : Nat} → {types : List VInductiveType} → + CheckedFamilies source params ordinal types → List VInductiveType + | _, _, .nil => [] + | _, _, .cons head tail => head.value :: values tail + +/-- Erasing a dependent family spine recovers its exact source-list index. -/ +@[simp] theorem values_eq {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {types : List VInductiveType} + (families : CheckedFamilies source params ordinal types) : + families.values = types := by + induction families with + | nil => rfl + | cons head tail ih => + simp only [values, CheckedFamily.value] + rw [ih] + +/-- Family ordinals in the same order as `values`. -/ +def ordinals {source : VInductDecl} {params : List VExpr} : + {ordinal : Nat} → {types : List VInductiveType} → + CheckedFamilies source params ordinal types → List Nat + | _, _, .nil => [] + | _, _, .cons head tail => head.ordinal :: ordinals tail + +/-- Per-family index telescopes in declaration order. -/ +def indices {source : VInductDecl} {params : List VExpr} : + {ordinal : Nat} → {types : List VInductiveType} → + CheckedFamilies source params ordinal types → List (List VExpr) + | _, _, .nil => [] + | _, _, .cons head tail => head.indices :: indices tail + +/-- Per-family result levels in declaration order. -/ +def resultLevels {source : VInductDecl} {params : List VExpr} : + {ordinal : Nat} → {types : List VInductiveType} → + CheckedFamilies source params ordinal types → List VLevel + | _, _, .nil => [] + | _, _, .cons head tail => head.resultLevel :: resultLevels tail + +/-- Ordered constructor descriptors, grouped by source family. -/ +def constructors {source : VInductDecl} {params : List VExpr} : + {ordinal : Nat} → {types : List VInductiveType} → + CheckedFamilies source params ordinal types → List (List CheckedCtor) + | _, _, .nil => [] + | _, _, .cons head tail => head.constructors :: constructors tail + +/-- Family names projected from the dependent source spine. -/ +def names {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {types : List VInductiveType} + (families : CheckedFamilies source params ordinal types) : List Name := + families.values.map (·.name) + +/-- Constructor names retain both family order and within-family order. -/ +def constructorNames {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {types : List VInductiveType} + (families : CheckedFamilies source params ordinal types) : + List (List Name) := + families.constructors.map fun constructors => + constructors.map (·.value.name) + +/-- Recursive target ordinals retain family, constructor, and field order. -/ +def recursiveTargets {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {types : List VInductiveType} + (families : CheckedFamilies source params ordinal types) : + List (List (List Nat)) := + families.constructors.map fun constructors => + constructors.map fun constructor => + constructor.recursive.map (·.targetType) + +end CheckedFamilies + +/-- Check one family while retaining every computed representation component. +This is a pure structural pass; no environment or generated constant is an +input. -/ +def checkedFamily? (source : VInductDecl) (params : List VExpr) + (ordinal : Nat) (type : VInductiveType) : + Option (CheckedFamily source params ordinal type) := + let indices := ctorFields (VExpr.dropN source.nparams type.type) + match hresult : VExpr.resultOf (VExpr.dropN source.nparams type.type) with + | .sort resultLevel => + if hparams : VExpr.telN source.nparams type.type = params then + if haccepted : blockFamilyCore source params ordinal type then + some { + params_eq := hparams + indices + indices_eq := rfl + resultLevel + result_eq := hresult + constructors := type.ctors.map (CheckedCtor.ofBlock source) + constructors_eq := rfl + accepted := haccepted } + else none + else none + | _ => none + +/-- Analyze an arbitrary source-ordered family list into the dependent spine. +The ordinal advances together with the list index. -/ +def checkedFamilies? (source : VInductDecl) (params : List VExpr) : + (ordinal : Nat) → (types : List VInductiveType) → + Option (CheckedFamilies source params ordinal types) + | _, [] => some .nil + | ordinal, type :: types => do + let head ← checkedFamily? source params ordinal type + let tail ← checkedFamilies? source params (ordinal + 1) types + return .cons head tail + +/-- Source-indexed checked representation of a complete inductive block. +Shared parameters are stored once; every per-family component lives in the +dependent `families` spine indexed by `source.types` itself. This is the +Spec-08A analysis boundary and intentionally has no generation or insertion +projection. -/ +structure CheckedBlock (source : VInductDecl) where + params : List VExpr + params_eq : params = blockParams source.nparams source.types + params_length : params.length = source.nparams + families : CheckedFamilies source params 0 source.types + nonempty : source.types.isEmpty = false + names : List Name + names_eq : names = blockGeneratedNames source.types + names_nodup : names.Nodup + +/-- Analyze a complete block without singleton destructuring. Empty blocks, +inconsistent raw parameter surfaces, malformed families/constructors, and +block-wide generated-name collisions are rejected before a descriptor is +returned. -/ +def checkedBlock? (source : VInductDecl) : Option source.CheckedBlock := + let params := blockParams source.nparams source.types + if hnonempty : source.types.isEmpty = false then + if hparams : params.length = source.nparams then + if hnames : (blockGeneratedNames source.types).Nodup then + match checkedFamilies? source params 0 source.types with + | some families => some { + params + params_eq := rfl + params_length := hparams + families + nonempty := hnonempty + names := blockGeneratedNames source.types + names_eq := rfl + names_nodup := hnames } + | none => none + else none + else none + else none + +/-- Analyze the normalized view of an arbitrary source block. The +`Normalization` index fixes every family and constructor header while the +dependent `CheckedBlock` fixes the complete normalized family order. -/ +def Normalization.checkedBlock? {source : VInductDecl} + (norm : Normalization source) : Option norm.view.CheckedBlock := + norm.view.checkedBlock? + +/-- One accepted raw/view mutual block. Unlike the legacy +`NormalizedChecked`, this type performs no singleton projection and exposes no +generation operation. -/ +structure NormalizedCheckedBlock (source : VInductDecl) where + normalization : Normalization source + checked : normalization.view.CheckedBlock + checked_eq : normalization.checkedBlock? = some checked + +/-- Analyze one normalization boundary and retain the exact dependent block +descriptor that accepted its view. -/ +def Normalization.checkBlock? {source : VInductDecl} + (norm : Normalization source) : Option (NormalizedCheckedBlock source) := + match hchecked : norm.checkedBlock? with + | some checked => some ⟨norm, checked, hchecked⟩ + | none => none + +/-- Construct and analyze a raw/view mutual normalization in one +computational transaction. -/ +def normalizedCheckedBlock? (source view : VInductDecl) : + Option (NormalizedCheckedBlock source) := do + let norm ← normalization? source view + norm.checkBlock? + +/-- Compatibility analyzer for a block already in analyzer normal form. -/ +def identityCheckedBlock? (source : VInductDecl) : + Option (NormalizedCheckedBlock source) := + (Normalization.identity source).checkBlock? + +/-- The validator-owned shared result universe paired with one exact checked +normalization view. Universe equality is semantic (`VLevel.Equiv`) and is +therefore certified by `ValidatedBlock.WF`, not guessed by the structural +analyzer. -/ +structure ValidatedBlock (source : VInductDecl) where + block : NormalizedCheckedBlock source + resultLevel : VLevel + +/-- Data-bearing compatibility result for the one-family generation path. +`CheckedBlock` and `ValidatedBlock` provide the public block-wide analysis and +validation; this legacy singleton projection remains available for existing +one-family certificates. The descriptor is dependent on its source +declaration, so it cannot silently describe a different block. -/ +structure Checked (source : VInductDecl) where + type : VInductiveType + types_eq : source.types = [type] + params : List VExpr + params_eq : params = VExpr.telN source.nparams type.type + indices : List VExpr + indices_eq : indices = ctorFields (VExpr.dropN source.nparams type.type) + resultLevel : VLevel + result_eq : VExpr.resultOf (VExpr.dropN source.nparams type.type) = .sort resultLevel + elimination : ElimMode + elimination_eq : elimination = + eliminationMode source.uvars type.name source.nparams indices.length type + kTarget : Bool + kTarget_eq : kTarget = isKTarget source.nparams resultLevel type + names : List Name + names_eq : names = generatedNames type + constructors : List CheckedCtor + constructors_eq : constructors = type.ctors.map + (CheckedCtor.ofDirect source.uvars type.name source.nparams indices.length) + accepted : stage3Core source = true + +/-- Analyze the current direct-indexed class once and retain every normalized +component needed downstream. This is intentionally an `Option` rather than a +boolean so successful checking cannot discard the analysis it just computed. -/ +def checked? : (decl : VInductDecl) → Option decl.Checked + | ⟨U, np, [ty]⟩ => + match hresult : VExpr.resultOf (VExpr.dropN np ty.type) with + | .sort l => + if h : stage3Core ⟨U, np, [ty]⟩ then + let indices := ctorFields (VExpr.dropN np ty.type) + some { + type := ty + types_eq := rfl + params := VExpr.telN np ty.type + params_eq := rfl + indices + indices_eq := rfl + resultLevel := l + result_eq := hresult + elimination := eliminationMode U ty.name np indices.length ty + elimination_eq := rfl + kTarget := isKTarget np l ty + kTarget_eq := rfl + names := generatedNames ty + names_eq := rfl + constructors := ty.ctors.map (CheckedCtor.ofDirect U ty.name np indices.length) + constructors_eq := rfl + accepted := h } + else none + | _ => none + | _ => none + +/-- A checked descriptor is proof-irrelevantly unique for its source +declaration. Every data field is fixed by the equations stored in `Checked`; +the remaining fields are propositions. -/ +theorem Checked.unique {decl : VInductDecl} + (a b : decl.Checked) : a = b := by + have htype : a.type = b.type := by + have hb := b.types_eq + rw [a.types_eq] at hb + injection hb + have hparams : a.params = b.params := by + rw [a.params_eq, b.params_eq, htype] + have hindices : a.indices = b.indices := by + rw [a.indices_eq, b.indices_eq, htype] + have hlevel : a.resultLevel = b.resultLevel := by + have hb := b.result_eq + rw [← htype, a.result_eq] at hb + injection hb + have helim : a.elimination = b.elimination := by + rw [a.elimination_eq, b.elimination_eq, htype, hindices] + have hkTarget : a.kTarget = b.kTarget := by + rw [a.kTarget_eq, b.kTarget_eq, htype, hlevel] + have hnames : a.names = b.names := by + rw [a.names_eq, b.names_eq, htype] + have hctors : a.constructors = b.constructors := by + rw [a.constructors_eq, b.constructors_eq, htype, hindices] + cases a + cases b + simp_all + +/-- Possessing a checked descriptor proves that the analyzer succeeds. This +is kept separate from uniqueness because reducing the dependent match in +`checked?` only needs its Boolean success result. -/ +theorem Checked.analyzer_isSome {decl : VInductDecl} + (checked : decl.Checked) : decl.checked?.isSome = true := by + cases decl with + | mk U np types => + rcases checked with + ⟨type, types_eq, params, params_eq, + indices, indices_eq, resultLevel, result_eq, + elimination, elimination_eq, kTarget, kTarget_eq, names, names_eq, + constructors, constructors_eq, accepted⟩ + change types = [type] at types_eq + subst types + subst params + subst indices + subst kTarget + subst names + subst constructors + change (VExpr.dropN np type.type).resultOf = + .sort resultLevel at result_eq + simp only [VInductDecl.checked?] + split <;> simp_all + +/-- Every `Checked` value is the exact data-bearing result returned by the +analyzer. Consumers can therefore package an already-retained witness without +running or choosing a second analysis. -/ +theorem Checked.analyzer_eq {decl : VInductDecl} + (checked : decl.Checked) : decl.checked? = some checked := by + cases h : decl.checked? with + | none => + have his := checked.analyzer_isSome + simp [h] at his + | some actual => + exact congrArg some (actual.unique checked) + +/-- The layout fragment of `stage3DirectCore` needed to pair an identity +normalization position-for-position. -/ +theorem Checked.direct_layout {decl : VInductDecl} + (checked : decl.Checked) : + (VExpr.telN decl.nparams checked.type.type).length = decl.nparams ∧ + ∀ c ∈ checked.type.ctors, + (VExpr.telN decl.nparams c.type).length = decl.nparams := by + cases decl with + | mk U np types => + have htypes : types = [checked.type] := checked.types_eq + have hcore := checked.accepted + simp only [stage3Core, htypes, Bool.and_eq_true] at hcore + have hdirect := hcore.1 + simp only [stage3DirectCore, Bool.and_eq_true, beq_iff_eq, + List.all_eq_true] at hdirect + obtain ⟨⟨⟨⟨-, hparams⟩, -⟩, -⟩, hctors⟩ := hdirect + refine ⟨hparams, fun c hc => ?_⟩ + rw [(hctors c hc).1.2] + exact hparams + +/-- Analyze an explicit normalized view without consulting the environment. +Semantic soundness is supplied separately by `Normalization.WF`; this split +matches the existing `Checked`/`Checked.WF` contract. -/ +def Normalization.checked? {source : VInductDecl} (norm : Normalization source) : + Option norm.view.Checked := + norm.view.checked? + +/-- Acceptance of an explicit normalized view. -/ +def Normalization.accepted {source : VInductDecl} (norm : Normalization source) : Bool := + norm.checked?.isSome + +/-- One accepted raw/view pair. The raw declaration remains the index of this +object; every WHNF-sensitive decision is retained in the single checked view +that produced `checked_eq`. -/ +structure NormalizedChecked (source : VInductDecl) where + normalization : Normalization source + sourceType : VInductiveType + source_types_eq : source.types = [sourceType] + checked : normalization.view.Checked + checked_eq : normalization.checked? = some checked + +/-- Analyze a normalization once and retain the exact dependent checked +descriptor that drove acceptance. -/ +def Normalization.check? {source : VInductDecl} (norm : Normalization source) : + Option (NormalizedChecked source) := + match hsource : source.types with + | [sourceType] => + match hchecked : norm.checked? with + | some checked => some ⟨norm, sourceType, hsource, checked, hchecked⟩ + | none => none + | _ => none + +/-- Construct and analyze a raw/view pair in one computational transaction. -/ +def normalizedChecked? (source view : VInductDecl) : Option (NormalizedChecked source) := do + let norm ← normalization? source view + norm.check? + +/-- Compatibility analyzer for metadata already accepted in raw syntax. -/ +def identityChecked? (source : VInductDecl) : Option (NormalizedChecked source) := + (Normalization.identity source).check? + +/-- Repackage an already-retained analyzer witness through the identity +normalization boundary. This is the compatibility block used by the public +`Checked` artifact accessors. -/ +def Checked.identityBlock {decl : VInductDecl} + (checked : decl.Checked) : NormalizedChecked decl where + normalization := Normalization.identity decl + sourceType := checked.type + source_types_eq := checked.types_eq + checked := checked + checked_eq := checked.analyzer_eq + +/-- One raw constructor paired, by position, with the checked descriptor from +the normalized view. The raw value owns kernel-observable binder syntax; +`view` owns WHNF-sensitive recursive classification and result indices. -/ +structure NormalizedCtor where + raw : VConstVal + view : CheckedCtor + +/-- Positional pairing used by the mixed artifact layer. A separate layout +check below rejects unequal list lengths instead of relying on `zip`'s +truncation behavior. -/ +def pairNormalizedCtors : List VConstVal → List CheckedCtor → List NormalizedCtor + | raw :: raws, view :: views => + ⟨raw, view⟩ :: pairNormalizedCtors raws views + | _, _ => [] + +/-- Raw constructor fields, kept distinct from the normalized fields stored in +the checked view. -/ +def NormalizedCtor.rawFields (ctor : NormalizedCtor) (np : Nat) : List VExpr := + ctorFields (VExpr.dropN np ctor.raw.type) + +/-- All stored raw constructor binders, including the constructor's own +parameter prefix. -/ +def NormalizedCtor.declaredBinders (ctor : NormalizedCtor) (np : Nat) : + List VExpr := + VExpr.telN np ctor.raw.type ++ ctor.rawFields np + +/-- The result retained in the stored raw constructor type. -/ +def NormalizedCtor.rawResult (ctor : NormalizedCtor) (np : Nat) : VExpr := + VExpr.resultOf (VExpr.dropN np ctor.raw.type) + +/-- The structural facts required before raw binders and normalized recursive +facts may drive one artifact. Semantic defeq remains the responsibility of +`Normalization.WF`; this Boolean only certifies positional layout. -/ +def NormalizedCtor.generationShape (np : Nat) (ctor : NormalizedCtor) : Bool := + ctor.raw.name == ctor.view.value.name && + ctor.raw.uvars == ctor.view.value.uvars && + (VExpr.telN np ctor.raw.type).length == np && + (ctor.rawFields np).length == ctor.view.fields.length + +def NormalizedChecked.rawParams {source : VInductDecl} + (block : NormalizedChecked source) : List VExpr := + VExpr.telN source.nparams block.sourceType.type + +def NormalizedChecked.rawIndices {source : VInductDecl} + (block : NormalizedChecked source) : List VExpr := + ctorFields (VExpr.dropN source.nparams block.sourceType.type) + +/-- The raw family result after its parameter and index binders. -/ +def NormalizedChecked.rawResult {source : VInductDecl} + (block : NormalizedChecked source) : VExpr := + VExpr.resultOf (VExpr.dropN source.nparams block.sourceType.type) + +/-- Whether a stored parameter domain has one of the four top-level type +annotations consumed by Lean before it creates the common recursor parameter +telescope. Ordinary reducible constants are intentionally not inspected: +their raw syntax remains observable in generated kernel metadata. -/ +def _root_.Ix.Theory.Named.VExpr.hasTypeAnnotation : VExpr → Bool + | .app (.const name _) _ => + name == ``_root_.outParam || name == ``_root_.semiOutParam + | .app (.app (.const name _) _) _ => + name == ``_root_.optParam || name == ``_root_.autoParam + | _ => false + +/-- Parameter surface emitted by recursor generation. Annotation wrappers use +the analyzer-owned consumed view; every other parameter keeps the stored raw +domain even when its WHNF differs. -/ +def generationParam (raw view : VExpr) : VExpr := + if raw.hasTypeAnnotation then view else raw + +/-- Positional common-parameter telescope used by generated artifacts. -/ +def generationParams : List VExpr → List VExpr → List VExpr + | raw :: raws, view :: views => + generationParam raw view :: generationParams raws views + | _, _ => [] + +@[simp] theorem generationParams_self : + ∀ params, generationParams params params = params + | [] => rfl + | param :: params => by + simp [generationParams, generationParam, generationParams_self params] + +theorem generationParams_length_of_eq : + ∀ {raw view : List VExpr}, raw.length = view.length → + (generationParams raw view).length = raw.length + | [], [], _ => rfl + | _ :: _, _ :: _, h => by + simp only [generationParams, List.length_cons] + exact congrArg Nat.succ + (generationParams_length_of_eq (Nat.succ.inj h)) + +def NormalizedChecked.generationParams {source : VInductDecl} + (block : NormalizedChecked source) : List VExpr := + VInductDecl.generationParams block.rawParams block.checked.params + +def NormalizedChecked.ctorPairs {source : VInductDecl} + (block : NormalizedChecked source) : List NormalizedCtor := + pairNormalizedCtors block.sourceType.ctors block.checked.constructors + +/-- Executable layout gate for mixed raw/view generation. It proves that every +raw binder position has exactly one normalized analysis position without +claiming that their expression payloads are syntactically equal. -/ +def NormalizedChecked.generationShape {source : VInductDecl} + (block : NormalizedChecked source) : Bool := + block.rawParams.length == source.nparams && + block.rawParams.length == block.checked.params.length && + block.rawIndices.length == block.checked.indices.length && + block.ctorPairs.length == block.sourceType.ctors.length && + block.ctorPairs.length == block.checked.constructors.length && + block.ctorPairs.all (NormalizedCtor.generationShape source.nparams) + +/-- Pairing a constructor list with its direct checked analysis preserves its +length and satisfies every per-constructor identity-layout check. -/ +theorem pairNormalizedCtors_ofDirect_generationShape + (U : Nat) (T : Name) (np ni : Nat) : + ∀ (cs : List VConstVal), + (∀ c ∈ cs, (VExpr.telN np c.type).length = np) → + let pairs := pairNormalizedCtors cs + (cs.map (CheckedCtor.ofDirect U T np ni)) + pairs.length = cs.length ∧ + pairs.all (NormalizedCtor.generationShape np) = true + | [], _ => by simp [pairNormalizedCtors] + | c :: cs, h => by + have hc := h c (.head _) + have hcs : ∀ c ∈ cs, (VExpr.telN np c.type).length = np := + fun c hc => h c (.tail _ hc) + have ih := pairNormalizedCtors_ofDirect_generationShape + U T np ni cs hcs + simp [pairNormalizedCtors, NormalizedCtor.generationShape, + CheckedCtor.ofDirect, NormalizedCtor.rawFields, hc, ih] + +/-- A normalized checked block whose raw outer telescopes are positionally +usable by artifact generation. This is still analysis data, not semantic +normalization evidence; preservation additionally requires +`NormalizedChecked.WF`. -/ +structure GenerationChecked (source : VInductDecl) where + block : NormalizedChecked source + shape_eq : block.generationShape = true + +/-- Identity normalization always satisfies the mixed generator's positional +layout gate. The only non-reflexive facts are the parameter and constructor +parameter lengths already certified by Stage 3. -/ +theorem Checked.identityBlock_generationShape {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityBlock.generationShape = true := by + have hp : (VExpr.telN decl.nparams checked.type.type).length = + decl.nparams := checked.direct_layout.1 + have hcs : ∀ c ∈ checked.type.ctors, + (VExpr.telN decl.nparams c.type).length = decl.nparams := + checked.direct_layout.2 + have hpairs := pairNormalizedCtors_ofDirect_generationShape + decl.uvars checked.type.name decl.nparams checked.indices.length + checked.type.ctors hcs + simp only [NormalizedChecked.generationShape, Bool.and_eq_true, + beq_iff_eq, Checked.identityBlock, NormalizedChecked.rawParams, + NormalizedChecked.rawIndices, NormalizedChecked.ctorPairs] + rw [checked.params_eq, checked.indices_eq, checked.constructors_eq] + simp only [List.length_map] + exact ⟨⟨⟨⟨⟨hp, trivial⟩, trivial⟩, hpairs.1⟩, + hpairs.1⟩, hpairs.2⟩ + +/-- Canonical mixed-generation witness for a declaration already accepted in +raw analyzer normal form. -/ +def Checked.identityGeneration {decl : VInductDecl} + (checked : decl.Checked) : GenerationChecked decl where + block := checked.identityBlock + shape_eq := checked.identityBlock_generationShape + +@[simp] theorem Checked.identityGeneration_sourceType + {decl : VInductDecl} (checked : decl.Checked) : + checked.identityGeneration.block.sourceType = checked.type := rfl + +@[simp] theorem Checked.identityGeneration_checked + {decl : VInductDecl} (checked : decl.Checked) : + checked.identityGeneration.block.checked = checked := rfl + +def NormalizedChecked.generation? {source : VInductDecl} + (block : NormalizedChecked source) : Option (GenerationChecked source) := + if h : block.generationShape then some ⟨block, h⟩ else none + +def Normalization.generation? {source : VInductDecl} + (norm : Normalization source) : Option (GenerationChecked source) := do + let block ← norm.check? + block.generation? + +def normalizedGeneration? (source view : VInductDecl) : + Option (GenerationChecked source) := do + let block ← normalizedChecked? source view + block.generation? + +def identityGeneration? (source : VInductDecl) : + Option (GenerationChecked source) := do + let block ← identityChecked? source + block.generation? + +/-- Compatibility acceptance predicate for the legacy one-family checked +descriptor. The public block-wide predicate is `stage3`, defined once the +mutual generation descriptor is available below. -/ +def singletonStage3 (decl : VInductDecl) : Bool := decl.checked?.isSome + +/-- The parameter telescope in the recursor's universe context. -/ +def paramsTel (ty : VInductiveType) (mode : ElimMode := .large) : List VExpr := + (VExpr.telN np ty.type).map (VExpr.instL (mode.sourceLevels U)) + +/-- The index telescope in the recursor's universe context (at parameter +depth). -/ +def idxTel (ty : VInductiveType) (mode : ElimMode := .large) : List VExpr := + (ctorFields (VExpr.dropN np ty.type)).map + (VExpr.instL (mode.sourceLevels U)) + +/-- `recApp` in the recursor's universe context. -/ +def recApp' (off : Nat) (mode : ElimMode := .large) : VExpr := + VExpr.appN (.const T (mode.sourceLevels U)) (VExpr.bvarRevRange off np) + +/-- `motive : ∀ indices, T params indices → Sort u`, in context +`params`. -/ +def motiveType (ty : VInductiveType) (mode : ElimMode := .large) : VExpr := + let ni := (idxTel U np ty mode).length + VExpr.forallN (idxTel U np ty mode) + (.forallE (VExpr.appN (.const T (mode.sourceLevels U)) + (VExpr.bvarRevRange ni np ++ VExpr.bvarRevRange 0 ni)) + (.sort mode.motiveLevel)) + +/-- Constructor fields in the recursor's universe context (still at +parameter depth, no motive shift). -/ +def ctorFieldsR (c : VConstVal) (mode : ElimMode := .large) : List VExpr := + (ctorFields (VExpr.dropN np c.type)).map + (VExpr.instL (mode.sourceLevels U)) + +/-- The recursive positions of a constructor with their index arguments, +in the recursor's universe context. -/ +def recPairsR (ni : Nat) (c : VConstVal) + (mode : ElimMode := .large) : List (Nat × List VExpr) := + (recPairs U T np ni (ctorFields (VExpr.dropN np c.type))).map + fun (j, idxs) => (j, idxs.map (VExpr.instL (mode.sourceLevels U))) + +/-- A recursive-argument descriptor transported into the recursor's universe +context. Telescope dependency is preserved because universe instantiation does +not change term-variable indices. -/ +def RecArg.instL (r : RecArg) (ls : List VLevel) : RecArg where + fieldIndex := r.fieldIndex + binders := r.binders.map (VExpr.instL ls) + targetType := r.targetType + indices := r.indices.map (VExpr.instL ls) + +/-- Recursive constructor arguments, including recursive Pi arguments, in the +recursor universe context. -/ +def recArgsR (ni : Nat) (c : VConstVal) + (mode : ElimMode := .large) : List RecArg := + (recArgs U T np ni (ctorFields (VExpr.dropN np c.type))).map + fun r => r.instL (mode.sourceLevels U) + +/-- The result index arguments of a constructor, recursor universes (at +result depth: past the parameters and all fields, no motive). -/ +def ctorIdxs (c : VConstVal) (mode : ElimMode := .large) : List VExpr := + (recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type))).map + (VExpr.instL (mode.sourceLevels U)) + +/-- The minor premise for one constructor, in context `params ++ [motive]`: +`∀ fields, ∀ ihs, motive idxs (ctor params fields)`, with one induction +hypothesis per directly recursive field. The fields shift by one for the +interposed motive. -/ +def minorType (ty : VInductiveType) (c : VConstVal) + (mode : ElimMode := .large) : VExpr := + let Bs := ctorFieldsR U np c mode + let m := Bs.length + let ni := (idxTel U np ty mode).length + let rsP := recPairsR U T np ni c mode + let r := rsP.length + VExpr.forallN (VExpr.liftTelN 1 Bs 0) + (VExpr.forallN (ihsFrom m rsP 0) + (VExpr.appN (.bvar (m+r)) + (((ctorIdxs U np c mode).map fun e => (e.liftN 1 m).liftN r) ++ + [VExpr.appN (.const c.name (mode.sourceLevels U)) + (VExpr.bvarRevRange (r+m+1) np ++ VExpr.bvarRevRange r m)]))) + +/-- Binder telescope of a functional induction hypothesis. Starting from the +recursive argument's own telescope, insert the motive below the preceding +constructor fields, then insert the current/later fields and earlier induction +hypotheses above them. -/ +def RecArg.minorBinders (m p : Nat) (r : RecArg) : List VExpr := + VExpr.liftTelN (m - r.fieldIndex + p) + (VExpr.liftTelN 1 r.binders r.fieldIndex) 0 + +/-- The induction-hypothesis type generated for one recursive argument. For a +direct recursive field this reduces to `motive indices field`; under a Pi it +is `∀ xs, motive indices (field xs)`. -/ +def RecArg.minorIH (m p : Nat) (r : RecArg) : VExpr := + let n := r.binders.length + VExpr.forallN (r.minorBinders m p) + (VExpr.appN (.bvar (m+p+n)) + ((r.indices.map fun e => + (e.liftN 1 (r.fieldIndex+n)).liftN (m-r.fieldIndex+p) n) ++ + [VExpr.appN (.bvar (m-1-r.fieldIndex+p+n)) + (VExpr.bvarRevRange 0 n)])) + +/-- Functional induction-hypothesis telescope, one entry per recursive +constructor argument. -/ +def ihsFromRecArgs (m : Nat) : List RecArg → Nat → List VExpr + | [], _ => [] + | r :: rs, p => r.minorIH m p :: ihsFromRecArgs m rs (p+1) + +/-- General one-family minor premise, extending `minorType` to recursive +arguments beneath Pi telescopes. -/ +def minorTypeRec (ty : VInductiveType) (c : VConstVal) + (mode : ElimMode := .large) : VExpr := + let Bs := ctorFieldsR U np c mode + let m := Bs.length + let ni := (idxTel U np ty mode).length + let rs := recArgsR U T np ni c mode + let r := rs.length + VExpr.forallN (VExpr.liftTelN 1 Bs 0) + (VExpr.forallN (ihsFromRecArgs m rs 0) + (VExpr.appN (.bvar (m+r)) + (((ctorIdxs U np c mode).map fun e => (e.liftN 1 m).liftN r) ++ + [VExpr.appN (.const c.name (mode.sourceLevels U)) + (VExpr.bvarRevRange (r+m+1) np ++ VExpr.bvarRevRange r m)]))) + +def minorTypesRec (ty : VInductiveType) : List VConstVal → + (i : Nat := 0) → (mode : ElimMode := .large) → List VExpr + | [], _, _ => [] + | c :: cs, i, mode => + VExpr.liftN i (minorTypeRec U T np ty c mode) :: + minorTypesRec ty cs (i+1) mode + +def recTypeRec (ty : VInductiveType) + (mode : ElimMode := .large) : VExpr := + let k := ty.ctors.length + let ni := (idxTel U np ty mode).length + VExpr.forallN (paramsTel U np ty mode) <| + .forallE (motiveType U T np ty mode) <| + VExpr.forallN (minorTypesRec U T np ty ty.ctors (mode := mode)) <| + VExpr.forallN (VExpr.liftTelN (k+1) (idxTel U np ty mode) 0) <| + .forallE (VExpr.appN (.const T (mode.sourceLevels U)) + (VExpr.bvarRevRange (ni+k+1) np ++ VExpr.bvarRevRange 0 ni)) <| + .app (VExpr.appN (.bvar (ni+k+1)) (VExpr.bvarRevRange 1 ni)) (.bvar 0) + +def recConstRec (ty : VInductiveType) + (mode : ElimMode := .large) : VConstant := + ⟨mode.recUvars U, recTypeRec U T np ty mode⟩ + +/-- The telescope introduced around a functional recursive call in an iota +RHS. It is the source Pi telescope transported under the recursor's common +arguments and the complete constructor-field context. -/ +def RecArg.ruleBinders (m k : Nat) (r : RecArg) : List VExpr := + VExpr.liftTelN (m-r.fieldIndex) + (VExpr.liftTelN (k+1) r.binders r.fieldIndex) 0 + +/-- Recursive call contributed to an iota RHS. Direct recursion reduces to a +plain call; a recursive Pi argument produces a lambda applying the field to +the freshly bound arguments before recurring. -/ +def RecArg.ruleCall (m k : Nat) (recBase : VExpr) (r : RecArg) : VExpr := + let n := r.binders.length + VExpr.lamN (r.ruleBinders m k) + (VExpr.appN (recBase.liftN n) + ((r.indices.map fun e => + (e.liftN (k+1) (r.fieldIndex+n)).liftN (m-r.fieldIndex) n) ++ + [VExpr.appN (.bvar (m-1-r.fieldIndex+n)) + (VExpr.bvarRevRange 0 n)])) + +/-- The functional-IH type expected of `ruleCall` in the complete iota-rule +context. Keeping this normalization named makes the preservation proof and +the generated RHS share one de Bruijn convention. -/ +def RecArg.ruleIH (m k : Nat) (r : RecArg) : VExpr := + let n := r.binders.length + VExpr.forallN (r.ruleBinders m k) + (VExpr.appN (.bvar (k+m+n)) + ((r.indices.map fun e => + (e.liftN (k+1) (r.fieldIndex+n)).liftN (m-r.fieldIndex) n) ++ + [VExpr.appN (.bvar (m-1-r.fieldIndex+n)) + (VExpr.bvarRevRange 0 n)])) + +/-- Functional-IH telescope in an iota-rule context. Each entry is weakened +past the preceding IH binders, while its base type is exactly `ruleIH`. -/ +def ruleIHs (m k : Nat) : List RecArg → Nat → List VExpr + | [], _ => [] + | r :: rs, p => (r.ruleIH m k).liftN p :: ruleIHs m k rs (p+1) + +def ruleRec (ty : VInductiveType) (i : Nat) (c : VConstVal) + (mode : ElimMode := .large) : VDefEq := + let k := ty.ctors.length + let Bs := ctorFieldsR U np c mode + let m := Bs.length + let ni := (idxTel U np ty mode).length + let rs := recArgsR U T np ni c mode + let binders := paramsTel U np ty mode ++ + motiveType U T np ty mode :: + minorTypesRec U T np ty ty.ctors (mode := mode) ++ + VExpr.liftTelN (k+1) Bs 0 + let recBase := VExpr.appN (.const (.str T "rec") (mode.recLevels U)) + (VExpr.bvarRevRange m (np+k+1)) + let idxR := (ctorIdxs U np c mode).map fun e => e.liftN (k+1) m + let ctorApp := VExpr.appN (.const c.name (mode.sourceLevels U)) + (VExpr.bvarRevRange (m+k+1) np ++ VExpr.bvarRevRange 0 m) + let ihs := rs.map fun r => r.ruleCall m k recBase + { uvars := mode.recUvars U + lhs := VExpr.lamN binders (VExpr.appN recBase (idxR ++ [ctorApp])) + rhs := VExpr.lamN binders + (VExpr.appN (.bvar (k-1-i+m)) (VExpr.bvarRevRange 0 m ++ ihs)) + type := VExpr.forallN binders (VExpr.appN (.bvar (k+m)) (idxR ++ [ctorApp])) } + +def rulesRec (ty : VInductiveType) + (mode : ElimMode := .large) : List VDefEq := + ty.ctors.zipIdx.map fun (c, i) => ruleRec U T np ty i c mode + +/-- Minor premise types in position: the `i`-th lives under +`params ++ motive` and the previous `i` minors. -/ +def minorTypes (ty : VInductiveType) : List VConstVal → (i : Nat := 0) → List VExpr + | [], _ => [] + | c :: cs, i => VExpr.liftN i (minorType U T np ty c) :: minorTypes ty cs (i+1) + +/-- The recursor type `∀ params, ∀ (motive : ∀ indices, T params indices → +Sort u) (minors..) (indices..) (t : T params indices), motive indices t`. -/ +def recType (ty : VInductiveType) : VExpr := + let k := ty.ctors.length + let ni := (idxTel U np ty).length + VExpr.forallN (paramsTel U np ty) <| + .forallE (motiveType U T np ty) <| + VExpr.forallN (minorTypes U T np ty ty.ctors) <| + VExpr.forallN (VExpr.liftTelN (k+1) (idxTel U np ty) 0) <| + .forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (ni+k+1) np ++ VExpr.bvarRevRange 0 ni)) <| + .app (VExpr.appN (.bvar (ni+k+1)) (VExpr.bvarRevRange 1 ni)) (.bvar 0) + +def recConst (ty : VInductiveType) : VConstant := ⟨U + 1, recType U T np ty⟩ + +/-- The iota rule for the `i`-th constructor, as a closed defeq between +lambda telescopes over `params ++ motive :: minors ++ fields` (the same +shape as `quotDefEq`, and the same telescope the kernel's +`RecursorRule.rhs` binds). The left body is the `SimplePattern.iota` +spine: the recursor applied to the parameters, motive, minors and the +constructor's result indices, with a constructor-headed major. -/ +def rule (ty : VInductiveType) (i : Nat) (c : VConstVal) : VDefEq := + let k := ty.ctors.length + let Bs := ctorFieldsR U np c + let m := Bs.length + let ni := (idxTel U np ty).length + let rsP := recPairsR U T np ni c + let binders := paramsTel U np ty ++ + motiveType U T np ty :: minorTypes U T np ty ty.ctors ++ + VExpr.liftTelN (k+1) Bs 0 + let recBase := VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange m (np+k+1)) + let idxR := (ctorIdxs U np c).map fun e => e.liftN (k+1) m + let ctorApp := VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (m+k+1) np ++ VExpr.bvarRevRange 0 m) + let ihs := rsP.map fun (j, idxs) => + VExpr.appN recBase + ((idxs.map fun e => (e.liftN (k+1) j).liftN (m-j)) ++ [.bvar (m-1-j)]) + { uvars := U + 1 + lhs := VExpr.lamN binders (VExpr.appN recBase (idxR ++ [ctorApp])) + rhs := VExpr.lamN binders + (VExpr.appN (.bvar (k-1-i+m)) (VExpr.bvarRevRange 0 m ++ ihs)) + type := VExpr.forallN binders (VExpr.appN (.bvar (k+m)) (idxR ++ [ctorApp])) } + +def rules (ty : VInductiveType) : List VDefEq := + ty.ctors.zipIdx.map fun (c, i) => rule U T np ty i c + +namespace NormalizedCtor + +/-- Raw field binders transported to the recursor universe context. -/ +def fieldsR (ctor : NormalizedCtor) (U np : Nat) + (mode : ElimMode := .large) : List VExpr := + (ctor.rawFields np).map (VExpr.instL (mode.sourceLevels U)) + +/-- Normalized recursive classifications transported without re-peeling the +raw constructor type. -/ +def recArgsR (ctor : NormalizedCtor) (U : Nat) + (mode : ElimMode := .large) : List RecArg := + ctor.view.recursive.map fun r => r.instL (mode.sourceLevels U) + +/-- Normalized constructor-result indices in recursor universes. -/ +def resultIndicesR (ctor : NormalizedCtor) (U : Nat) + (mode : ElimMode := .large) : List VExpr := + ctor.view.resultIndices.map (VExpr.instL (mode.sourceLevels U)) + +end NormalizedCtor + +/-! ## Mixed raw/view artifacts + +These definitions are additive until their preservation theorem is complete. +Raw family/constructor telescopes supply emitted binder syntax; the checked +view supplies result indices and recursive-argument classification. No helper +below re-runs `recArg?` on raw metadata. +-/ + +namespace GenerationChecked + +/-- Elimination mode retained by the single checked analysis. -/ +abbrev elimination {source : VInductDecl} (gen : GenerationChecked source) : + ElimMode := + gen.block.checked.elimination + +/-- K-like reduction flag retained by the single checked analysis. It is +metadata for reduction and does not select the elimination mode. -/ +abbrev kTarget {source : VInductDecl} (gen : GenerationChecked source) : Bool := + gen.block.checked.kTarget + +/-- Universe arity of this generated recursor. -/ +abbrev recUvars {source : VInductDecl} (gen : GenerationChecked source) : Nat := + gen.elimination.recUvars source.uvars + +/-- Declaration universes in this recursor's universe context. -/ +abbrev sourceLevels {source : VInductDecl} + (gen : GenerationChecked source) : List VLevel := + gen.elimination.sourceLevels source.uvars + +/-- Result level of the motive. -/ +abbrev motiveLevel {source : VInductDecl} + (gen : GenerationChecked source) : VLevel := + gen.elimination.motiveLevel + +/-- Identity universe arguments of recursive recursor calls. -/ +abbrev recLevels {source : VInductDecl} + (gen : GenerationChecked source) : List VLevel := + gen.elimination.recLevels source.uvars + +/-- Kernel-observable family-parameter telescope in recursor universes. + +Lean consumes the four parameter annotations before emission, but otherwise +retains stored syntax rather than replacing reducible aliases by their WHNF. -/ +def paramsTel {source : VInductDecl} (gen : GenerationChecked source) : + List VExpr := + gen.block.generationParams.map + (VExpr.instL gen.sourceLevels) + +/-- Raw index-binder telescope in recursor universes. -/ +def idxTel {source : VInductDecl} (gen : GenerationChecked source) : + List VExpr := + gen.block.rawIndices.map (VExpr.instL gen.sourceLevels) + +/-- Mixed motive: raw index binders, normalized index arity, and the retained +raw family identity. -/ +def motiveType {source : VInductDecl} (gen : GenerationChecked source) : VExpr := + let ni := gen.idxTel.length + VExpr.forallN gen.idxTel + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name gen.sourceLevels) + (VExpr.bvarRevRange ni source.nparams ++ VExpr.bvarRevRange 0 ni)) + (.sort gen.motiveLevel)) + +/-- One mixed minor premise. Raw fields are bound verbatim, while induction +hypotheses and constructor result indices come from the checked view. -/ +def minorType {source : VInductDecl} (ctor : NormalizedCtor) + (mode : ElimMode := .large) : VExpr := + let Bs := ctor.fieldsR source.uvars source.nparams mode + let m := Bs.length + let rs := ctor.recArgsR source.uvars mode + let r := rs.length + VExpr.forallN (VExpr.liftTelN 1 Bs 0) + (VExpr.forallN (ihsFromRecArgs m rs 0) + (VExpr.appN (.bvar (m+r)) + ((ctor.resultIndicesR source.uvars mode |>.map fun e => + (e.liftN 1 m).liftN r) ++ + [VExpr.appN + (.const ctor.raw.name (mode.sourceLevels source.uvars)) + (VExpr.bvarRevRange (r+m+1) source.nparams ++ + VExpr.bvarRevRange r m)]))) + +def minorTypesAux {source : VInductDecl} (gen : GenerationChecked source) : + List NormalizedCtor → (i : Nat := 0) → List VExpr + | [], _ => [] + | ctor :: ctors, i => + VExpr.liftN i (minorType (source := source) ctor gen.elimination) :: + gen.minorTypesAux ctors (i+1) + +def minorTypes {source : VInductDecl} (gen : GenerationChecked source) : + List VExpr := + gen.minorTypesAux gen.block.ctorPairs + +/-- Mixed recursor type. Its binder surface is raw, but every +WHNF-sensitive choice was retained by the checked view. -/ +def recType {source : VInductDecl} (gen : GenerationChecked source) : VExpr := + let k := gen.block.ctorPairs.length + let ni := gen.idxTel.length + VExpr.forallN gen.paramsTel <| + .forallE gen.motiveType <| + VExpr.forallN gen.minorTypes <| + VExpr.forallN (VExpr.liftTelN (k+1) gen.idxTel 0) <| + .forallE + (VExpr.appN + (.const gen.block.sourceType.name + gen.sourceLevels) + (VExpr.bvarRevRange (ni+k+1) source.nparams ++ + VExpr.bvarRevRange 0 ni)) <| + .app + (VExpr.appN (.bvar (ni+k+1)) (VExpr.bvarRevRange 1 ni)) + (.bvar 0) + +def recursor {source : VInductDecl} (gen : GenerationChecked source) : + VConstant := + ⟨gen.recUvars, gen.recType⟩ + +/-- One mixed iota rule. Raw fields and constructor names are observable in +the rule telescope; normalized recursive descriptors determine recursive calls +and normalized result indices determine the major's index spine. -/ +def rule {source : VInductDecl} (gen : GenerationChecked source) + (i : Nat) (ctor : NormalizedCtor) : VDefEq := + let k := gen.block.ctorPairs.length + let Bs := ctor.fieldsR source.uvars source.nparams gen.elimination + let m := Bs.length + let rs := ctor.recArgsR source.uvars gen.elimination + let binders := gen.paramsTel ++ + gen.motiveType :: gen.minorTypes ++ + VExpr.liftTelN (k+1) Bs 0 + let recBase := VExpr.appN + (.const (.str gen.block.sourceType.name "rec") + gen.recLevels) + (VExpr.bvarRevRange m (source.nparams+k+1)) + let idxR := ctor.resultIndicesR source.uvars gen.elimination |>.map fun e => + e.liftN (k+1) m + let ctorApp := VExpr.appN + (.const ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (m+k+1) source.nparams ++ + VExpr.bvarRevRange 0 m) + let ihs := rs.map fun r => r.ruleCall m k recBase + { uvars := gen.recUvars + lhs := VExpr.lamN binders (VExpr.appN recBase (idxR ++ [ctorApp])) + rhs := VExpr.lamN binders + (VExpr.appN (.bvar (k-1-i+m)) (VExpr.bvarRevRange 0 m ++ ihs)) + type := VExpr.forallN binders + (VExpr.appN (.bvar (k+m)) (idxR ++ [ctorApp])) } + +def generatedRules {source : VInductDecl} (gen : GenerationChecked source) : + List VDefEq := + gen.block.ctorPairs.zipIdx.map fun (ctor, i) => gen.rule i ctor + +end GenerationChecked + +namespace Checked + +@[simp] theorem identityGeneration_elimination {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.elimination = checked.elimination := rfl + +@[simp] theorem identityGeneration_kTarget {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.kTarget = checked.kTarget := rfl + +@[simp] theorem identityGeneration_recUvars {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.recUvars = + checked.elimination.recUvars decl.uvars := rfl + +@[simp] theorem identityGeneration_sourceLevels {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.sourceLevels = + checked.elimination.sourceLevels decl.uvars := rfl + +@[simp] theorem identityGeneration_motiveLevel {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.motiveLevel = checked.elimination.motiveLevel := rfl + +@[simp] theorem identityGeneration_recLevels {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.recLevels = + checked.elimination.recLevels decl.uvars := rfl + +private theorem identity_paramsTel {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.paramsTel = + VInductDecl.paramsTel decl.uvars decl.nparams checked.type + checked.elimination := by + simp [GenerationChecked.paramsTel, VInductDecl.paramsTel, + GenerationChecked.sourceLevels, GenerationChecked.elimination, + NormalizedChecked.generationParams, NormalizedChecked.rawParams, + Checked.identityGeneration, Checked.identityBlock, checked.params_eq] + +private theorem identity_idxTel {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.idxTel = + VInductDecl.idxTel decl.uvars decl.nparams checked.type + checked.elimination := rfl + +private theorem identity_motiveType {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.motiveType = + VInductDecl.motiveType decl.uvars checked.type.name decl.nparams + checked.type checked.elimination := rfl + +private theorem identity_minorType {decl : VInductDecl} + (checked : decl.Checked) (c : VConstVal) : + GenerationChecked.minorType (source := decl) + ⟨c, CheckedCtor.ofDirect decl.uvars checked.type.name decl.nparams + checked.indices.length c⟩ checked.elimination = + VInductDecl.minorTypeRec decl.uvars checked.type.name decl.nparams + checked.type c checked.elimination := by + have hni : checked.indices.length = + (VInductDecl.idxTel decl.uvars decl.nparams checked.type + checked.elimination).length := by + rw [checked.indices_eq] + simp [VInductDecl.idxTel] + rw [hni] + rfl + +private theorem identity_minorTypesAux {decl : VInductDecl} + (checked : decl.Checked) : + ∀ (cs : List VConstVal) (i : Nat), + checked.identityGeneration.minorTypesAux + (pairNormalizedCtors cs + (cs.map (CheckedCtor.ofDirect decl.uvars checked.type.name + decl.nparams checked.indices.length))) i = + VInductDecl.minorTypesRec decl.uvars checked.type.name decl.nparams + checked.type cs i checked.elimination + | [], _ => rfl + | c :: cs, i => by + simp [pairNormalizedCtors, GenerationChecked.minorTypesAux, + VInductDecl.minorTypesRec, identity_minorType, + identity_minorTypesAux checked cs (i+1)] + +private theorem identity_minorTypes {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.minorTypes = + VInductDecl.minorTypesRec decl.uvars checked.type.name decl.nparams + checked.type checked.type.ctors (mode := checked.elimination) := by + unfold GenerationChecked.minorTypes + simp only [Checked.identityGeneration, Checked.identityBlock, + NormalizedChecked.ctorPairs] + rw [checked.constructors_eq] + exact identity_minorTypesAux checked checked.type.ctors 0 + +private theorem identity_recType {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.recType = + VInductDecl.recTypeRec decl.uvars checked.type.name decl.nparams + checked.type checked.elimination := by + simp only [GenerationChecked.recType, VInductDecl.recTypeRec] + rw [identity_paramsTel checked, identity_motiveType checked, + identity_minorTypes checked, identity_idxTel checked] + simp only [Checked.identityGeneration, Checked.identityBlock, + NormalizedChecked.ctorPairs] + rw [checked.constructors_eq, + pairNormalizedCtors_ofDirect_generationShape + decl.uvars checked.type.name decl.nparams checked.indices.length + checked.type.ctors checked.direct_layout.2 |>.1] + +private theorem identity_recursor {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.recursor = + VInductDecl.recConstRec decl.uvars checked.type.name decl.nparams + checked.type checked.elimination := by + unfold GenerationChecked.recursor VInductDecl.recConstRec + rw [identity_recType checked] + simp [GenerationChecked.recUvars, GenerationChecked.elimination, + Checked.identityGeneration, Checked.identityBlock] + +private theorem identity_rule {decl : VInductDecl} + (checked : decl.Checked) (i : Nat) (c : VConstVal) : + checked.identityGeneration.rule i + ⟨c, CheckedCtor.ofDirect decl.uvars checked.type.name decl.nparams + checked.indices.length c⟩ = + VInductDecl.ruleRec decl.uvars checked.type.name decl.nparams + checked.type i c checked.elimination := by + have hni : checked.indices.length = + (VInductDecl.idxTel decl.uvars decl.nparams checked.type + checked.elimination).length := by + rw [checked.indices_eq] + simp [VInductDecl.idxTel] + have hk : checked.identityGeneration.block.ctorPairs.length = + checked.type.ctors.length := by + simp only [Checked.identityGeneration, Checked.identityBlock, + NormalizedChecked.ctorPairs] + rw [checked.constructors_eq] + exact (pairNormalizedCtors_ofDirect_generationShape + decl.uvars checked.type.name decl.nparams checked.indices.length + checked.type.ctors checked.direct_layout.2).1 + unfold GenerationChecked.rule VInductDecl.ruleRec + rw [identity_paramsTel checked, identity_motiveType checked, + identity_minorTypes checked, hk, hni] + rfl + +private theorem identity_rulesAux {decl : VInductDecl} + (checked : decl.Checked) : + ∀ (cs : List VConstVal) (n : Nat), + List.map + (fun (ctor, i) => checked.identityGeneration.rule i ctor) + (List.zipIdx + (pairNormalizedCtors cs + (cs.map (CheckedCtor.ofDirect decl.uvars checked.type.name + decl.nparams checked.indices.length))) n) = + List.map + (fun (c, i) => + VInductDecl.ruleRec decl.uvars checked.type.name decl.nparams + checked.type i c checked.elimination) + (List.zipIdx cs n) + | [], _ => rfl + | c :: cs, n => by + simp [pairNormalizedCtors, List.zipIdx, identity_rule, + identity_rulesAux checked cs (n+1)] + +private theorem identity_generatedRules {decl : VInductDecl} + (checked : decl.Checked) : + checked.identityGeneration.generatedRules = + VInductDecl.rulesRec decl.uvars checked.type.name decl.nparams + checked.type checked.elimination := by + unfold GenerationChecked.generatedRules VInductDecl.rulesRec + simp only [Checked.identityGeneration, Checked.identityBlock, + NormalizedChecked.ctorPairs] + rw [checked.constructors_eq] + exact identity_rulesAux checked checked.type.ctors 0 + +/-- Public motive generation is the identity-normalization specialization of +the mixed raw/view implementation. -/ +def motiveType {decl : VInductDecl} (checked : decl.Checked) : VExpr := + checked.identityGeneration.motiveType + +/-- Public minor generation is the identity-normalization specialization of +the mixed raw/view implementation. -/ +def minorTypes {decl : VInductDecl} (checked : decl.Checked) : List VExpr := + checked.identityGeneration.minorTypes + +/-- Public recursor generation is the identity-normalization specialization +of the mixed raw/view implementation. -/ +def recursor {decl : VInductDecl} (checked : decl.Checked) : VConstant := + checked.identityGeneration.recursor + +/-- Public iota-rule generation is the identity-normalization specialization +of the mixed raw/view implementation. -/ +def generatedRules {decl : VInductDecl} (checked : decl.Checked) : List VDefEq := + checked.identityGeneration.generatedRules + +/-- The public motive retains the exact legacy identity-normal form. -/ +theorem motiveType_eq_legacy {decl : VInductDecl} + (checked : decl.Checked) : + checked.motiveType = + VInductDecl.motiveType decl.uvars checked.type.name decl.nparams + checked.type checked.elimination := + identity_motiveType checked + +/-- The public minor telescope retains the exact legacy identity-normal +form, including functional recursive arguments. -/ +theorem minorTypes_eq_legacy {decl : VInductDecl} + (checked : decl.Checked) : + checked.minorTypes = + VInductDecl.minorTypesRec decl.uvars checked.type.name decl.nparams + checked.type checked.type.ctors (mode := checked.elimination) := + identity_minorTypes checked + +/-- The public recursor retains the exact legacy identity-normal form while +being generated by the mixed implementation. -/ +theorem recursor_eq_legacy {decl : VInductDecl} + (checked : decl.Checked) : + checked.recursor = + VInductDecl.recConstRec decl.uvars checked.type.name decl.nparams + checked.type checked.elimination := + identity_recursor checked + +/-- The public iota-rule list retains the exact legacy identity-normal form +while being generated by the mixed implementation. -/ +theorem generatedRules_eq_legacy {decl : VInductDecl} + (checked : decl.Checked) : + checked.generatedRules = + VInductDecl.rulesRec decl.uvars checked.type.name decl.nparams + checked.type checked.elimination := + identity_generatedRules checked + +end Checked + +/-! ## Mutual raw/view artifacts + +The singleton generator above remains the compatibility proof surface while +the block generator below mirrors `AddInductive.mkRecInfos`: all motives are +introduced in family order, all constructor minors are then flattened in +family/constructor order, and every recursive descriptor selects its target +family by the ordinal retained by `CheckedCtor.ofBlock`. +-/ + +/-- Erased data for one member of the dependent checked-family spine. The +ordinal and normalized family value travel with the projections they index, +so later positional pairing does not manufacture a parallel family order. -/ +structure CheckedFamilyData where + ordinal : Nat + value : VInductiveType + indices : List VExpr + resultLevel : VLevel + constructors : List CheckedCtor + +namespace CheckedFamilies + +/-- Erase a dependent checked-family spine without changing its order. -/ +def data {source : VInductDecl} {params : List VExpr} : + {ordinal : Nat} → {types : List VInductiveType} → + CheckedFamilies source params ordinal types → List CheckedFamilyData + | _, _, .nil => [] + | _, _, .cons head tail => + { ordinal := head.ordinal + value := head.value + indices := head.indices + resultLevel := head.resultLevel + constructors := head.constructors } :: data tail + +end CheckedFamilies + +/-- One stored family paired positionally with the checked normalized family +that drove generation. Stored family/index syntax remains observable in +metadata; the view owns recursive classification and result indices. -/ +structure NormalizedFamily where + raw : VInductiveType + view : CheckedFamilyData + +/-- Positional family pairing. `blockGenerationShape` separately proves +that neither side is truncated. -/ +def pairNormalizedFamilies : + List VInductiveType → List CheckedFamilyData → List NormalizedFamily + | raw :: raws, view :: views => + ⟨raw, view⟩ :: pairNormalizedFamilies raws views + | _, _ => [] + +def NormalizedFamily.rawParams (family : NormalizedFamily) (np : Nat) : + List VExpr := + VExpr.telN np family.raw.type + +def NormalizedFamily.rawIndices (family : NormalizedFamily) (np : Nat) : + List VExpr := + ctorFields (VExpr.dropN np family.raw.type) + +def NormalizedFamily.ctorPairs (family : NormalizedFamily) : + List NormalizedCtor := + pairNormalizedCtors family.raw.ctors family.view.constructors + +/-- One flattened constructor together with its source-family identity. -/ +structure NormalizedBlockCtor where + owner : Nat + familyName : Name + familyIndices : List VExpr + ctor : NormalizedCtor + +def NormalizedFamily.blockCtors (family : NormalizedFamily) : + List NormalizedBlockCtor := + family.ctorPairs.map fun ctor => + { owner := family.view.ordinal + familyName := family.raw.name + familyIndices := family.view.indices + ctor } + +/-- Per-family layout gate for mutual mixed generation. -/ +def NormalizedFamily.generationShape (np : Nat) + (family : NormalizedFamily) : Bool := + family.raw.name == family.view.value.name && + family.raw.uvars == family.view.value.uvars && + (family.rawParams np).length == np && + (family.rawIndices np).length == family.view.indices.length && + family.ctorPairs.length == family.raw.ctors.length && + family.ctorPairs.length == family.view.constructors.length && + family.ctorPairs.all (NormalizedCtor.generationShape np) + +def NormalizedCheckedBlock.rawParams {source : VInductDecl} + (_block : NormalizedCheckedBlock source) : List VExpr := + blockParams source.nparams source.types + +def NormalizedCheckedBlock.familyPairs {source : VInductDecl} + (block : NormalizedCheckedBlock source) : List NormalizedFamily := + pairNormalizedFamilies source.types block.checked.families.data + +def NormalizedCheckedBlock.flatCtors {source : VInductDecl} + (block : NormalizedCheckedBlock source) : List NormalizedBlockCtor := + block.familyPairs.flatMap (·.blockCtors) + +/-- Executable positional gate for a complete normalized block. It checks +the shared parameter surface, every family/index position, and every +constructor position before raw and checked syntax are mixed. -/ +def NormalizedCheckedBlock.blockGenerationShape {source : VInductDecl} + (block : NormalizedCheckedBlock source) : Bool := + block.rawParams.length == source.nparams && + block.rawParams.length == block.checked.params.length && + block.familyPairs.length == source.types.length && + block.familyPairs.length == block.checked.families.data.length && + block.familyPairs.all + (NormalizedFamily.generationShape source.nparams) && + block.familyPairs.all fun family => + family.raw.uvars == source.uvars && + family.ctorPairs.all fun ctor => ctor.raw.uvars == source.uvars + +/-- A validator-owned mutual normalization whose raw/view positions are +usable by artifact generation. -/ +structure BlockGenerationChecked (source : VInductDecl) where + validated : ValidatedBlock source + shape_eq : validated.block.blockGenerationShape = true + +def ValidatedBlock.generation? {source : VInductDecl} + (validated : ValidatedBlock source) : + Option (BlockGenerationChecked source) := + if h : validated.block.blockGenerationShape then + some ⟨validated, h⟩ + else none + +/-- The common result level selected by an identity-normalized checked block. +The empty fallback is unreachable after `checkedBlock?`, but keeps the +executable analyzer total. -/ +def CheckedBlock.firstResultLevel {source : VInductDecl} + (checked : CheckedBlock source) : VLevel := + checked.families.resultLevels.head?.getD .zero + +/-- Analyze an already-normalized arbitrary block for mutual generation, +without any singleton destructuring. -/ +def identityBlockGeneration? (source : VInductDecl) : + Option (BlockGenerationChecked source) := do + let block ← identityCheckedBlock? source + let validated : ValidatedBlock source := + { block + resultLevel := block.checked.firstResultLevel } + validated.generation? + +/-- Public structural acceptance is exact block-generation readiness. This +retains the complete source-ordered mutual descriptor instead of projecting a +singleton family and then rebuilding generation data. -/ +def stage3 (source : VInductDecl) : Bool := + source.identityBlockGeneration?.isSome + +namespace BlockGenerationChecked + +abbrev block {source : VInductDecl} (gen : BlockGenerationChecked source) : + NormalizedCheckedBlock source := + gen.validated.block + +abbrev checked {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.block.normalization.view.CheckedBlock := + gen.block.checked + +def families {source : VInductDecl} (gen : BlockGenerationChecked source) : + List NormalizedFamily := + gen.block.familyPairs + +def flatCtors {source : VInductDecl} (gen : BlockGenerationChecked source) : + List NormalizedBlockCtor := + gen.block.flatCtors + +abbrev familyCount {source : VInductDecl} + (gen : BlockGenerationChecked source) : Nat := + gen.families.length + +abbrev minorCount {source : VInductDecl} + (gen : BlockGenerationChecked source) : Nat := + gen.flatCtors.length + +/-- Whether the accepted block contains any recursive constructor argument. +For a positive checked block this is the kernel's `inductInfo.isRec` decision +expressed through the analyzer-owned recursive descriptors. -/ +def isRec {source : VInductDecl} + (gen : BlockGenerationChecked source) : Bool := + gen.flatCtors.any fun constructor => + !constructor.ctor.view.recursive.isEmpty + +/-- Whether some recursive argument is hidden beneath a function telescope, +matching the kernel's `inductInfo.isReflexive` flag. -/ +def isReflexive {source : VInductDecl} + (gen : BlockGenerationChecked source) : Bool := + gen.flatCtors.any fun constructor => + constructor.ctor.view.recursive.any fun recursive => + !recursive.binders.isEmpty + +/-- The block large-elimination decision. A non-Prop common result admits +large elimination; at `Prop`, only the kernel's singleton exception can do +so. In particular every genuinely mutual Prop block is small. -/ +def elimination {source : VInductDecl} + (gen : BlockGenerationChecked source) : ElimMode := + if gen.validated.resultLevel.isNeverZero then .large + else + match gen.families with + | [family] => + if largeElim source.uvars family.raw.name source.nparams + family.view.indices.length family.view.value then .large else .small + | _ => .small + +/-- K-like reduction is a singleton-only kernel flag. -/ +def kTarget {source : VInductDecl} + (gen : BlockGenerationChecked source) : Bool := + match gen.families with + | [family] => + isKTarget source.nparams gen.validated.resultLevel family.view.value + | _ => false + +abbrev recUvars {source : VInductDecl} + (gen : BlockGenerationChecked source) : Nat := + gen.elimination.recUvars source.uvars + +abbrev sourceLevels {source : VInductDecl} + (gen : BlockGenerationChecked source) : List VLevel := + gen.elimination.sourceLevels source.uvars + +abbrev motiveLevel {source : VInductDecl} + (gen : BlockGenerationChecked source) : VLevel := + gen.elimination.motiveLevel + +abbrev recLevels {source : VInductDecl} + (gen : BlockGenerationChecked source) : List VLevel := + gen.elimination.recLevels source.uvars + +/-- Shared emitted parameters in recursor universes. -/ +def paramsTel {source : VInductDecl} + (gen : BlockGenerationChecked source) : List VExpr := + generationParams gen.block.rawParams gen.block.checked.params |>.map + (VExpr.instL gen.sourceLevels) + +def familyNameAt {source : VInductDecl} + (gen : BlockGenerationChecked source) (ordinal : Nat) : Name := + (gen.families[ordinal]?).map (fun family => family.raw.name) |>.getD .anonymous + +def idxTel {source : VInductDecl} (gen : BlockGenerationChecked source) + (family : NormalizedFamily) : List VExpr := + (family.rawIndices source.nparams).map (VExpr.instL gen.sourceLevels) + +/-- One family motive before preceding motives have been inserted. -/ +def motiveType {source : VInductDecl} + (gen : BlockGenerationChecked source) + (family : NormalizedFamily) : VExpr := + let indices := gen.idxTel family + let ni := indices.length + VExpr.forallN indices + (.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange ni source.nparams ++ + VExpr.bvarRevRange 0 ni)) + (.sort gen.motiveLevel)) + +/-- Motives in kernel order. Each later motive is weakened past all earlier +motives while retaining the shared parameter context. -/ +def motiveTypesAux {source : VInductDecl} + (gen : BlockGenerationChecked source) : + List NormalizedFamily → (i : Nat := 0) → List VExpr + | [], _ => [] + | family :: families, i => + (gen.motiveType family).liftN i :: + gen.motiveTypesAux families (i + 1) + +def motiveTypes {source : VInductDecl} + (gen : BlockGenerationChecked source) : List VExpr := + gen.motiveTypesAux gen.families + +/-- Binder telescope of one mutual functional induction hypothesis. -/ +def blockMinorBinders (d m p : Nat) (r : RecArg) : List VExpr := + VExpr.liftTelN (m - r.fieldIndex + p) + (VExpr.liftTelN d r.binders r.fieldIndex) 0 + +/-- Mutual induction hypothesis routed to the recursive argument's target +motive. -/ +def blockMinorIH (d m p : Nat) (r : RecArg) : VExpr := + let n := r.binders.length + VExpr.forallN (blockMinorBinders d m p r) + (VExpr.appN (.bvar (d - 1 - r.targetType + m + p + n)) + ((r.indices.map fun e => + (e.liftN d (r.fieldIndex + n)).liftN + (m - r.fieldIndex + p) n) ++ + [VExpr.appN (.bvar (m - 1 - r.fieldIndex + p + n)) + (VExpr.bvarRevRange 0 n)])) + +def blockIHsFromRecArgs (d m : Nat) : List RecArg → Nat → List VExpr + | [], _ => [] + | r :: rs, p => + blockMinorIH d m p r :: blockIHsFromRecArgs d m rs (p + 1) + +/-- One constructor minor in the context of all block motives. -/ +def minorType {source : VInductDecl} + (gen : BlockGenerationChecked source) + (constructor : NormalizedBlockCtor) : VExpr := + let d := gen.familyCount + let Bs := constructor.ctor.fieldsR source.uvars source.nparams gen.elimination + let m := Bs.length + let rs := constructor.ctor.recArgsR source.uvars gen.elimination + let r := rs.length + VExpr.forallN (VExpr.liftTelN d Bs 0) + (VExpr.forallN (blockIHsFromRecArgs d m rs 0) + (VExpr.appN (.bvar (d - 1 - constructor.owner + m + r)) + ((constructor.ctor.resultIndicesR source.uvars gen.elimination |>.map + fun e => (e.liftN d m).liftN r) ++ + [VExpr.appN (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (r + m + d) source.nparams ++ + VExpr.bvarRevRange r m)]))) + +/-- Globally flattened constructor minors in family/constructor order. -/ +def minorTypesAux {source : VInductDecl} + (gen : BlockGenerationChecked source) : + List NormalizedBlockCtor → (i : Nat := 0) → List VExpr + | [], _ => [] + | constructor :: constructors, i => + (gen.minorType constructor).liftN i :: + gen.minorTypesAux constructors (i + 1) + +def minorTypes {source : VInductDecl} + (gen : BlockGenerationChecked source) : List VExpr := + gen.minorTypesAux gen.flatCtors + +/-- One recursor type for the selected family, sharing every motive and minor +with the other family recursors. -/ +def recType {source : VInductDecl} + (gen : BlockGenerationChecked source) + (family : NormalizedFamily) : VExpr := + let d := gen.familyCount + let k := gen.minorCount + let indices := gen.idxTel family + let ni := indices.length + VExpr.forallN gen.paramsTel <| + VExpr.forallN gen.motiveTypes <| + VExpr.forallN gen.minorTypes <| + VExpr.forallN (VExpr.liftTelN (d + k) indices 0) <| + .forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (ni + d + k) source.nparams ++ + VExpr.bvarRevRange 0 ni)) <| + .app + (VExpr.appN + (.bvar (d - 1 - family.view.ordinal + k + ni + 1)) + (VExpr.bvarRevRange 1 ni)) + (.bvar 0) + +def recursor {source : VInductDecl} + (gen : BlockGenerationChecked source) + (family : NormalizedFamily) : VConstant := + ⟨gen.recUvars, gen.recType family⟩ + +/-- Named generated recursors in family order. -/ +def recursors {source : VInductDecl} + (gen : BlockGenerationChecked source) : List VConstVal := + gen.families.map fun family => + ⟨gen.recursor family, .str family.raw.name "rec"⟩ + +/-- Telescope introduced around a mutual recursive rule call. -/ +def blockRuleBinders (common m : Nat) (r : RecArg) : List VExpr := + VExpr.liftTelN (m - r.fieldIndex) + (VExpr.liftTelN common r.binders r.fieldIndex) 0 + +/-- Recursive iota-rule call routed to the target family's recursor. -/ +def blockRuleCall (common m : Nat) (recBase : VExpr) + (r : RecArg) : VExpr := + let n := r.binders.length + VExpr.lamN (blockRuleBinders common m r) + (VExpr.appN (recBase.liftN n) + ((r.indices.map fun e => + (e.liftN common (r.fieldIndex + n)).liftN + (m - r.fieldIndex) n) ++ + [VExpr.appN (.bvar (m - 1 - r.fieldIndex + n)) + (VExpr.bvarRevRange 0 n)])) + +def recBase {source : VInductDecl} + (gen : BlockGenerationChecked source) (m target : Nat) : VExpr := + VExpr.appN + (.const (.str (gen.familyNameAt target) "rec") gen.recLevels) + (VExpr.bvarRevRange m + (source.nparams + gen.familyCount + gen.minorCount)) + +/-- One mutual iota rule at its global flattened minor ordinal. -/ +def rule {source : VInductDecl} + (gen : BlockGenerationChecked source) + (minorIndex : Nat) (constructor : NormalizedBlockCtor) : VDefEq := + let d := gen.familyCount + let k := gen.minorCount + let common := d + k + let Bs := constructor.ctor.fieldsR source.uvars source.nparams gen.elimination + let m := Bs.length + let rs := constructor.ctor.recArgsR source.uvars gen.elimination + let binders := gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes ++ + VExpr.liftTelN common Bs 0 + let ownerRecBase := gen.recBase m constructor.owner + let idxR := constructor.ctor.resultIndicesR source.uvars gen.elimination |>.map + fun e => e.liftN common m + let ctorApp := VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (m + common) source.nparams ++ + VExpr.bvarRevRange 0 m) + let ihs := rs.map fun recursive => + blockRuleCall common m (gen.recBase m recursive.targetType) recursive + { uvars := gen.recUvars + lhs := VExpr.lamN binders + (VExpr.appN ownerRecBase (idxR ++ [ctorApp])) + rhs := VExpr.lamN binders + (VExpr.appN (.bvar (k - 1 - minorIndex + m)) + (VExpr.bvarRevRange 0 m ++ ihs)) + type := VExpr.forallN binders + (VExpr.appN + (.bvar (d - 1 - constructor.owner + k + m)) + (idxR ++ [ctorApp])) } + +def generatedRules {source : VInductDecl} + (gen : BlockGenerationChecked source) : List VDefEq := + gen.flatCtors.zipIdx.map fun (constructor, i) => + gen.rule i constructor + +end BlockGenerationChecked + +/-- Semantic evidence for a recursive argument beneath a Pi telescope. The +binder domains are checked over the constructor context before the recursive +field; its terminal index spine is checked underneath those binders. -/ +def RecArg.WF (r : RecArg) (env : VEnv) (l : VLevel) (Is : List VExpr) + (Γ : List VExpr) : Prop := + VEnv.OnTel env U Γ r.binders ∧ + env.SpineWF U (r.binders.reverse ++ Γ) + (VExpr.forallN (VExpr.liftTelN (r.fieldIndex + r.binders.length) Is 0) + (.sort l)) + r.indices (.sort l) + +/-- Semantic well-formedness of every constructor field in a mutual block. + +Recursive fields may end in any source-indexed family and may sit below a Pi +telescope. Their target ordinal selects the corresponding index telescope +from `familyIndices`. A non-recursive field must be a block-free type in the +pre-family environment and obey the common result-universe bound. -/ +def blockFieldsWF (source : VInductDecl) (env : VEnv) + (resultLevel : VLevel) (familyIndices : List (List VExpr)) : + List VExpr → Nat → List VExpr → Prop + | _, _, [] => True + | Γ, j, B :: Bs => + (match blockRecArg? source.uvars source.nparams + (familyHeaders source.nparams source.types) + (familyNames source.types) j B with + | some recursive => + match familyIndices[recursive.targetType]? with + | some indices => + recursive.WF source.uvars env resultLevel indices Γ + | none => False + | none => + ∃ u, env.HasType source.uvars Γ B (.sort u) ∧ + (resultLevel = .zero ∨ u ≤ resultLevel)) ∧ + blockFieldsWF source env resultLevel familyIndices + (B :: Γ) (j + 1) Bs + +/-- Interpret the analyzer-retained positional classifications rather than +recomputing recursive recognition from field syntax. The list lengths and +field indices are checked in the proposition, while each recursive target +selects its exact source-ordered family index telescope. -/ +def checkedBlockFieldsWF (env : VEnv) (U : Nat) + (resultLevel : VLevel) (familyIndices : List (List VExpr)) : + List VExpr → List (Option RecArg) → List VExpr → Nat → Prop + | [], [], _, _ => True + | B :: Bs, classification :: classifications, Γ, j => + (match classification with + | some recursive => + recursive.fieldIndex = j ∧ + match familyIndices[recursive.targetType]? with + | some indices => recursive.WF U env resultLevel indices Γ + | none => False + | none => + ∃ u, env.HasType U Γ B (.sort u) ∧ + (resultLevel = .zero ∨ u ≤ resultLevel)) ∧ + checkedBlockFieldsWF env U resultLevel familyIndices + Bs classifications (B :: Γ) (j + 1) + | _, _, _, _ => False + +/-- Interpret a dependent source-ordered family spine at one shared result +universe. Family formers and the block-free portions of constructor fields +are interpreted in the common pre-family environment. Recursive targets are +reduced to their selected family index telescopes, so this layer does not +pretend that generated constants or recursors already exist. -/ +def CheckedFamilies.WF {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {types : List VInductiveType} + (families : CheckedFamilies source params ordinal types) + (env : VEnv) (resultLevel : VLevel) + (familyIndices : List (List VExpr)) : Prop := + match families with + | .nil => True + | .cons head tail => + head.resultLevel ≈ resultLevel ∧ + VEnv.OnTel env source.uvars [] (params ++ head.indices) ∧ + (∀ constructor ∈ head.constructors, + blockFieldsWF source env resultLevel familyIndices + params.reverse 0 constructor.fields ∧ + env.SpineWF source.uvars + (constructor.fields.reverse ++ params.reverse) + (VExpr.forallN + (VExpr.liftTelN constructor.fields.length head.indices 0) + (.sort resultLevel)) + constructor.resultIndices (.sort resultLevel)) ∧ + tail.WF env resultLevel familyIndices + +/-- Erased semantic fold over the exact projections of a dependent checked +family spine. `CheckedBlock.WF` uses this presentation so concrete checked +descriptors obtained by computation reduce through their public projections +without exposing proof fields stored inside `Option.get`. -/ +def checkedFamilyListsWF (source : VInductDecl) (params : List VExpr) + (env : VEnv) (resultLevel : VLevel) + (familyIndices : List (List VExpr)) : + List VLevel → List (List VExpr) → List (List CheckedCtor) → Prop + | [], [], [] => True + | level :: levels, indices :: indicesTail, + constructors :: constructorsTail => + level ≈ resultLevel ∧ + VEnv.OnTel env source.uvars [] (params ++ indices) ∧ + (∀ constructor ∈ constructors, + checkedBlockFieldsWF env source.uvars resultLevel familyIndices + constructor.fields constructor.recursiveAt params.reverse 0 ∧ + env.SpineWF source.uvars + (constructor.fields.reverse ++ params.reverse) + (VExpr.forallN + (VExpr.liftTelN constructor.fields.length indices 0) + (.sort resultLevel)) + constructor.resultIndices (.sort resultLevel)) ∧ + checkedFamilyListsWF source params env resultLevel familyIndices + levels indicesTail constructorsTail + | _, _, _ => False + +/-- Environment-indexed semantics of a structurally checked mutual block. +The common `resultLevel` is explicit and every family result is required to be +semantically equivalent to it. -/ +def CheckedBlock.WF {source : VInductDecl} + (checked : source.CheckedBlock) (env : VEnv) + (resultLevel : VLevel) : Prop := + checkedFamilyListsWF source checked.params env resultLevel + checked.families.indices checked.families.resultLevels + checked.families.indices checked.families.constructors + +/-- Complete Theory semantics of one validator-owned mutual normalization. +Normalization compares raw family types before staging and raw constructor +types after all-family staging; the checked view supplies the block-wide +strict-positivity and result-spine interpretation. -/ +def ValidatedBlock.WF {source : VInductDecl} + (validated : ValidatedBlock source) (env blockEnv : VEnv) : Prop := + validated.block.normalization.BlockWF env blockEnv ∧ + validated.block.checked.WF env validated.resultLevel + +/-- Consumer-facing validation-only package. It deliberately contains no +generated motive, recursor, rule, or environment insertion beyond the +temporary all-family validation stage. -/ +structure ValidationCertificate (source : VInductDecl) (env : VEnv) where + validated : ValidatedBlock source + blockEnv : VEnv + wf : validated.WF env blockEnv + +/-- Semantic well-formedness of constructor fields over the pre-environment. +Direct recursive fields retain the Stage-3 spine contract. A recursive Pi +field additionally carries a well-formed binder telescope and the terminal +index spine below it. Non-recursive fields are well-formed types; non-Prop +families retain the universe bound, while Prop uses Lean's impredicative +exception. -/ +def fieldsWF (env : VEnv) (l : VLevel) (Is : List VExpr) : + List VExpr → Nat → List VExpr → Prop + | _, _, [] => True + | Γ, j, B :: Bs => + (isRecField U T np Is.length j B = true ∨ + (∃ r, recArg? U T np Is.length j B = some r ∧ r.binders ≠ [] ∧ + r.WF U env l Is Γ) ∨ + recArg? U T np Is.length j B = none ∧ + ∃ u, env.HasType U Γ B (.sort u) ∧ (l = .zero ∨ u ≤ l)) ∧ + (isRecField U T np Is.length j B = true → + env.SpineWF U Γ (VExpr.forallN (VExpr.liftTelN j Is 0) (.sort l)) + (recFieldIdxs np B) (.sort l)) ∧ + fieldsWF env l Is (B :: Γ) (j+1) Bs + +/-- Environment-indexed semantic evidence for a successful structural +analysis. This is the one-family counterpart of the kernel's `checkType` and +constructor checking passes: `Checked` owns normalized syntax, while +`Checked.WF` proves that syntax meaningful over the input environment. -/ +def Checked.WF {decl : VInductDecl} (checked : decl.Checked) (env : VEnv) : Prop := + VEnv.OnTel env decl.uvars [] (checked.params ++ checked.indices) ∧ + ∀ c ∈ checked.type.ctors, + fieldsWF decl.uvars checked.type.name decl.nparams env checked.resultLevel + checked.indices checked.params.reverse 0 + (ctorFields (VExpr.dropN decl.nparams c.type)) ∧ + env.SpineWF decl.uvars + ((ctorFields (VExpr.dropN decl.nparams c.type)).reverse ++ checked.params.reverse) + (VExpr.forallN + (VExpr.liftTelN (ctorFields (VExpr.dropN decl.nparams c.type)).length + checked.indices 0) + (.sort checked.resultLevel)) + (recFieldIdxs decl.nparams (VExpr.resultOf (VExpr.dropN decl.nparams c.type))) + (.sort checked.resultLevel) + +/-- Semantic certificate for an accepted raw/view pair. The normalization +justifies the raw metadata against the view, while `Checked.WF` justifies the +view's analyzer facts in the same input Theory environment. -/ +def NormalizedChecked.WF {source : VInductDecl} + (block : NormalizedChecked source) (env : VEnv) : Prop := + block.normalization.WF env ∧ block.checked.WF env + +/-- The binders emitted for one mixed minor/rule: the checked family +parameters followed by the stored raw constructor fields. + +Lean consumes parameter annotations while checking the family and uses those +checked locals when it builds the recursor. Constructor fields, by contrast, +retain their stored surface syntax. -/ +def NormalizedCtor.emittedBinders {source : VInductDecl} + (block : NormalizedChecked source) (ctor : NormalizedCtor) : List VExpr := + block.checked.params ++ ctor.rawFields source.nparams + +/-- The normalized binders whose semantic analysis drives the mixed artifact. +These expressions are never emitted in place of their raw partners. -/ +def NormalizedCtor.viewBinders {source : VInductDecl} + (block : NormalizedChecked source) (ctor : NormalizedCtor) : List VExpr := + block.checked.params ++ ctor.view.fields + +/-- The normalized constructor result reconstructed with the retained raw +family identity. It is interpreted in either of the raw contexts certified +below. -/ +def NormalizedCtor.resultTarget {source : VInductDecl} + (block : NormalizedChecked source) (ctor : NormalizedCtor) : VExpr := + VExpr.appN (.const block.sourceType.name (VLevel.params source.uvars)) + (VExpr.bvarRevRange (ctor.rawFields source.nparams).length source.nparams ++ + ctor.view.resultIndices) + +/-- Staged semantic evidence for one raw/view constructor pair. + +`declaredTel`/`declaredResult` validate the exact stored constructor type so it +can be inserted. `emittedTel`/`emittedResult` validate the binder context used +by mixed minors and rules. The two raw parameter prefixes may be merely +definitionally equal; recording both paths therefore anticipates the kernel's +constructor-parameter behavior without assuming syntactic equality. -/ +structure NormalizedCtor.WF {source : VInductDecl} + (block : NormalizedChecked source) (ctor : NormalizedCtor) + (env : VEnv) : Prop where + declaredTel : + env.TelDefEq source.uvars [] + (ctor.declaredBinders source.nparams) (ctor.viewBinders block) + declaredResult : + env.IsDefEq source.uvars (ctor.declaredBinders source.nparams).reverse + (ctor.rawResult source.nparams) (ctor.resultTarget block) + (.sort block.checked.resultLevel) + emittedTel : + env.TelDefEq source.uvars [] + (ctor.emittedBinders block) (ctor.viewBinders block) + emittedResult : + env.IsDefEq source.uvars (ctor.emittedBinders block).reverse + (ctor.rawResult source.nparams) (ctor.resultTarget block) + (.sort block.checked.resultLevel) + +/-- Semantic certificate for a generation-ready raw/view block. + +The family telescope/result are certified before family insertion. +Constructor certificates are quantified over the exact environment produced +by inserting the raw family constant. This staging is essential for aliases +whose constructor fields mention that family. No field of this structure is a +normalization oracle: every equality is an ordinary Theory derivation. -/ +structure GenerationChecked.WF {source : VInductDecl} + (gen : GenerationChecked source) (env : VEnv) : Prop where + blockWF : gen.block.WF env + familyTel : + env.TelDefEq source.uvars [] + (gen.block.rawParams ++ gen.block.rawIndices) + (gen.block.checked.params ++ gen.block.checked.indices) + familyResult : + env.IsDefEq source.uvars + (gen.block.rawParams ++ gen.block.rawIndices).reverse + gen.block.rawResult (.sort gen.block.checked.resultLevel) + (.sort (.succ gen.block.checked.resultLevel)) + ctors : + ∀ envT, env.addConst gen.block.sourceType.name + gen.block.sourceType.toVConstant = some envT → + ∀ ctor ∈ gen.block.ctorPairs, ctor.WF gen.block envT + +/-! ### Mutual generation certificates -/ + +def NormalizedFamily.rawResult (family : NormalizedFamily) (np : Nat) : + VExpr := + VExpr.resultOf (VExpr.dropN np family.raw.type) + +def NormalizedBlockCtor.declaredBinders {source : VInductDecl} + (constructor : NormalizedBlockCtor) : List VExpr := + constructor.ctor.declaredBinders source.nparams + +/-- Constructor binders used by generated mutual artifacts before universe +instantiation. -/ +def NormalizedBlockCtor.emittedBinders {source : VInductDecl} + (gen : BlockGenerationChecked source) + (constructor : NormalizedBlockCtor) : List VExpr := + gen.block.checked.params ++ constructor.ctor.rawFields source.nparams + +def NormalizedBlockCtor.viewBinders {source : VInductDecl} + (gen : BlockGenerationChecked source) + (constructor : NormalizedBlockCtor) : List VExpr := + gen.block.checked.params ++ constructor.ctor.view.fields + +def NormalizedBlockCtor.rawResult {source : VInductDecl} + (constructor : NormalizedBlockCtor) : VExpr := + constructor.ctor.rawResult source.nparams + +/-- Normalized constructor result reconstructed with the stored owner name. -/ +def NormalizedBlockCtor.resultTarget {source : VInductDecl} + (_gen : BlockGenerationChecked source) + (constructor : NormalizedBlockCtor) : VExpr := + VExpr.appN + (.const constructor.familyName (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (constructor.ctor.rawFields source.nparams).length source.nparams ++ + constructor.ctor.view.resultIndices) + +/-- Granular raw/view semantics for one mutual family. -/ +structure NormalizedFamily.WF {source : VInductDecl} + (gen : BlockGenerationChecked source) (family : NormalizedFamily) + (env : VEnv) : Prop where + familyTel : + env.TelDefEq source.uvars [] + (family.rawParams source.nparams ++ family.rawIndices source.nparams) + (gen.block.checked.params ++ family.view.indices) + familyResult : + env.IsDefEq source.uvars + (family.rawParams source.nparams ++ + family.rawIndices source.nparams).reverse + (family.rawResult source.nparams) + (.sort gen.validated.resultLevel) + (.sort (.succ gen.validated.resultLevel)) + +/-- Declaration-stage raw/view semantics for one constructor after every +family has been staged. -/ +structure NormalizedBlockCtor.WF {source : VInductDecl} + (gen : BlockGenerationChecked source) + (constructor : NormalizedBlockCtor) (env : VEnv) : Prop where + declaredTel : + env.TelDefEq source.uvars [] + (NormalizedBlockCtor.declaredBinders (source := source) constructor) + (NormalizedBlockCtor.viewBinders gen constructor) + declaredResult : + env.IsDefEq source.uvars + (NormalizedBlockCtor.declaredBinders + (source := source) constructor).reverse + (NormalizedBlockCtor.rawResult (source := source) constructor) + (NormalizedBlockCtor.resultTarget gen constructor) + (.sort gen.validated.resultLevel) + emittedTel : + env.TelDefEq source.uvars [] + (NormalizedBlockCtor.emittedBinders gen constructor) + (NormalizedBlockCtor.viewBinders gen constructor) + emittedResult : + env.IsDefEq source.uvars + (NormalizedBlockCtor.emittedBinders gen constructor).reverse + (NormalizedBlockCtor.rawResult (source := source) constructor) + (NormalizedBlockCtor.resultTarget gen constructor) + (.sort gen.validated.resultLevel) + owner : ∃ family ∈ gen.families, + family.view.ordinal = constructor.owner ∧ + family.raw.name = constructor.familyName ∧ + family.view.indices = constructor.familyIndices + recursive : ∀ recursive ∈ constructor.ctor.view.recursive, + ∃ family ∈ gen.families, + family.view.ordinal = recursive.targetType ∧ + (∃ B, + constructor.ctor.view.fields[recursive.fieldIndex]? = some B ∧ + B = VExpr.forallN recursive.binders + (VExpr.appN + (.const family.raw.name (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (recursive.fieldIndex + recursive.binders.length) + source.nparams ++ recursive.indices))) ∧ + recursive.WF source.uvars env gen.validated.resultLevel + family.view.indices + ((constructor.ctor.view.fields.take recursive.fieldIndex).reverse ++ + gen.block.checked.params.reverse) + resultSpine : + env.SpineWF source.uvars + (constructor.ctor.view.fields.reverse ++ + gen.block.checked.params.reverse) + (VExpr.forallN + (VExpr.liftTelN constructor.ctor.view.fields.length + constructor.familyIndices 0) + (.sort gen.validated.resultLevel)) + constructor.ctor.view.resultIndices + (.sort gen.validated.resultLevel) + +/-- Semantic input to block artifact preservation. No field assumes a +generated motive, minor, recursor, or rule typing judgment. -/ +structure BlockGenerationChecked.WF {source : VInductDecl} + (gen : BlockGenerationChecked source) (env blockEnv : VEnv) : Prop where + blockWF : gen.validated.WF env blockEnv + resultLevelWF : gen.validated.resultLevel.WF source.uvars + paramsTel : + env.TelDefEq source.uvars [] gen.block.rawParams + gen.block.checked.params + families : ∀ family ∈ gen.families, family.WF gen env + constructors : + ∀ constructor ∈ gen.flatCtors, + NormalizedBlockCtor.WF gen constructor blockEnv + +/-- Consumer-facing semantic package for one generation-ready inductive +declaration. The executable transaction inspects only `generation`; `wf` is +the ordinary Theory certificate used by preservation and is never a +normalization oracle. + +Verify can erase checker-specific candidate provenance to this boundary +before handing a normalized transaction to downstream consumers. -/ +structure GenerationCertificate (source : VInductDecl) (env : VEnv) where + generation : GenerationChecked source + wf : generation.WF env + +/-- Consumer-facing proof-carrying mutual generation package. -/ +structure BlockGenerationCertificate (source : VInductDecl) (env : VEnv) where + generation : BlockGenerationChecked source + blockEnv : VEnv + wf : generation.WF env blockEnv + +end VInductDecl + +/-- Legacy declaration-level semantic contract for one-family compatibility. +Block-wide preservation consumes `BlockGenerationChecked.WF` directly. -/ +def VInductDecl.WF (env : VEnv) (decl : VInductDecl) : Prop := + decl.singletonStage3 ∧ + ∀ ty ∈ decl.types, + VEnv.OnTel env decl.uvars [] + (VExpr.telN decl.nparams ty.type ++ + VInductDecl.ctorFields (VExpr.dropN decl.nparams ty.type)) ∧ + ∀ c ∈ ty.ctors, + VInductDecl.fieldsWF decl.uvars ty.name decl.nparams env + (VInductDecl.sortLevel decl.nparams ty) + (VInductDecl.ctorFields (VExpr.dropN decl.nparams ty.type)) + (VExpr.telN decl.nparams ty.type).reverse 0 + (VInductDecl.ctorFields (VExpr.dropN decl.nparams c.type)) ∧ + env.SpineWF decl.uvars + ((VInductDecl.ctorFields (VExpr.dropN decl.nparams c.type)).reverse ++ + (VExpr.telN decl.nparams ty.type).reverse) + (VExpr.forallN + (VExpr.liftTelN (VInductDecl.ctorFields (VExpr.dropN decl.nparams c.type)).length + (VInductDecl.ctorFields (VExpr.dropN decl.nparams ty.type)) 0) + (.sort (VInductDecl.sortLevel decl.nparams ty))) + (VInductDecl.recFieldIdxs decl.nparams + (VExpr.resultOf (VExpr.dropN decl.nparams c.type))) + (.sort (VInductDecl.sortLevel decl.nparams ty)) + +/-- Raw family constants of a block in source order. -/ +def VInductDecl.blockTypeConstants (source : VInductDecl) : + List VConstVal := + source.types.map (·.toVConstVal) + +/-- Raw constructor constants flattened in family/constructor order. -/ +def VInductDecl.blockConstructorConstants (source : VInductDecl) : + List VConstVal := + source.types.flatMap (·.ctors) + +/-- The single computational transaction for a generation-ready raw/view +block. Stored family and constructor constants come from the raw source; +recursor and rules come from the mixed artifact implementation. Semantic +validity is a theorem premise, never an input to this computation. -/ +def VEnv.addInductGeneration {source : VInductDecl} + (env : VEnv) (gen : source.GenerationChecked) : Option VEnv := do + let ty := gen.block.sourceType + let env ← env.addConst ty.name ty.toVConstant + let env ← ty.ctors.foldlM + (fun env c => env.addConst c.name c.toVConstant) env + let env ← env.addConst (.str ty.name "rec") gen.recursor + return gen.generatedRules.foldl VEnv.addDefEq env + +/-- The block-wide generation transaction. Its four phases deliberately +match the kernel's visibility boundaries: every family is present before any +constructor, every constructor before any recursor, and every recursor before +the first reduction rule. -/ +def VEnv.addInductBlockGeneration {source : VInductDecl} + (env : VEnv) (gen : source.BlockGenerationChecked) : Option VEnv := do + let env ← source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env + let env ← source.blockConstructorConstants.foldlM + (fun env constructor => env.addConst constructor.name constructor.toVConstant) env + let env ← gen.recursors.foldlM + (fun env recursor => env.addConst recursor.name recursor.toVConstant) env + return gen.generatedRules.foldl VEnv.addDefEq env + +/-- Public proof-carrying wrapper around `addInductGeneration`. + +The certificate's proof is erased and does not influence computation. This +entry point lets a verified producer expose a non-identity normalization +without exposing its checker trace or asking a consumer to remember a +separate preservation premise. -/ +def VEnv.addInductCertified {source : VInductDecl} + (env : VEnv) (certificate : source.GenerationCertificate env) : + Option VEnv := + env.addInductGeneration certificate.generation + +/-- Proof-carrying wrapper for a block-wide generation transaction. The +certificate is erased from computation. -/ +def VEnv.addInductBlockCertified {source : VInductDecl} + (env : VEnv) (certificate : source.BlockGenerationCertificate env) : + Option VEnv := + env.addInductBlockGeneration certificate.generation + +@[simp] theorem VEnv.addInductCertified_eq_addInductGeneration + {source : VInductDecl} (env : VEnv) + (certificate : source.GenerationCertificate env) : + env.addInductCertified certificate = + env.addInductGeneration certificate.generation := + rfl + +@[simp] theorem VEnv.addInductBlockCertified_eq_addInductBlockGeneration + {source : VInductDecl} (env : VEnv) + (certificate : source.BlockGenerationCertificate env) : + env.addInductBlockCertified certificate = + env.addInductBlockGeneration certificate.generation := + rfl + +/-- Exact intermediate states of a successful normalized inductive +transaction. Stable lookup, freshness, monotonicity, and preservation +consequences are derived from this one trace in the typing layer. -/ +structure VEnv.AddInductGenerationTrace {source : VInductDecl} + (env env' : VEnv) (gen : source.GenerationChecked) where + typeEnv : VEnv + ctorEnv : VEnv + recEnv : VEnv + addType : + env.addConst gen.block.sourceType.name + gen.block.sourceType.toVConstant = some typeEnv + addCtors : + gen.block.sourceType.ctors.foldlM + (fun env c => env.addConst c.name c.toVConstant) typeEnv = + some ctorEnv + addRec : + ctorEnv.addConst (.str gen.block.sourceType.name "rec") + gen.recursor = some recEnv + addRules : + gen.generatedRules.foldl VEnv.addDefEq recEnv = env' + +/-- Exact phase boundaries of a successful block-wide generation +transaction. -/ +structure VEnv.AddInductBlockGenerationTrace {source : VInductDecl} + (env env' : VEnv) (gen : source.BlockGenerationChecked) where + typeEnv : VEnv + ctorEnv : VEnv + recEnv : VEnv + addTypes : + source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env = + some typeEnv + addCtors : + source.blockConstructorConstants.foldlM + (fun env constructor => env.addConst constructor.name constructor.toVConstant) typeEnv = + some ctorEnv + addRecs : + gen.recursors.foldlM + (fun env recursor => env.addConst recursor.name recursor.toVConstant) + ctorEnv = some recEnv + addRules : + gen.generatedRules.foldl VEnv.addDefEq recEnv = env' + +/-- The raw-normal-form API analyzes and inserts a complete mutual block. -/ +def VEnv.addInduct (env : VEnv) (decl : VInductDecl) : Option VEnv := do + let generation ← decl.identityBlockGeneration? + env.addInductBlockGeneration generation + +/-- Compatibility wrapper for the pre-Spec-08C one-family raw transaction. + +Unlike `addInduct`, this deliberately projects the legacy `Checked` artifact +and therefore rejects every genuinely mutual declaration. It remains only +for a deprecation window so existing one-family consumers can separate their +API migration from the semantic switch to block-wide generation. -/ +@[deprecated VEnv.addInduct (since := "2026-08-07")] +def VEnv.addInductSingleton (env : VEnv) (decl : VInductDecl) : Option VEnv := do + let checked ← decl.checked? + env.addInductGeneration checked.identityGeneration + +/-- The compatibility wrapper is exactly the former identity-normalization +transaction; it is not a second block-generation path. -/ +@[simp, deprecated VEnv.addInduct (since := "2026-08-07")] +theorem VEnv.addInductSingleton_eq_addInductGeneration + (env : VEnv) (decl : VInductDecl) : + env.addInductSingleton decl = + decl.checked? >>= fun checked => + env.addInductGeneration checked.identityGeneration := + rfl + +/-- The raw public API is transparently the identity-normalization +specialization of the normalized block transaction. -/ +theorem VEnv.addInduct_eq_addInductBlockGeneration + (env : VEnv) (decl : VInductDecl) : + env.addInduct decl = + decl.identityBlockGeneration? >>= fun generation => + env.addInductBlockGeneration generation := + rfl + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductSingleton_eq_addInductGeneration [propext, Classical.choice, Quot.sound] + +/-- Stable, consumer-facing consequences of a successful `addInduct` +transaction. This deliberately hides the internal `foldlM` sequence: a +caller receives the complete output environment and all generated objects, or +`addInduct` returns `none` without exposing an intermediate environment. -/ +structure VEnv.AddInductSuccess (env env' : VEnv) (decl : VInductDecl) : Prop where + generation : ∃ generation, decl.identityBlockGeneration? = some generation + accepted : decl.stage3 = true + le : env ≤ env' + type_fresh : ∀ ty ∈ decl.types, env.constants ty.name = none + type_lookup : ∀ ty ∈ decl.types, env'.constants ty.name = some ty.toVConstant + ctor_fresh : ∀ ty ∈ decl.types, ∀ c ∈ ty.ctors, env.constants c.name = none + ctor_lookup : ∀ ty ∈ decl.types, ∀ c ∈ ty.ctors, + env'.constants c.name = some c.toVConstant + rec_fresh : ∀ generation, decl.identityBlockGeneration? = some generation → + ∀ recursor ∈ generation.recursors, env.constants recursor.name = none + rec_lookup : ∀ generation, decl.identityBlockGeneration? = some generation → + ∀ recursor ∈ generation.recursors, + env'.constants recursor.name = some recursor.toVConstant + rule_mem : ∀ generation, decl.identityBlockGeneration? = some generation → + ∀ df ∈ generation.generatedRules, env'.defeqs df diff --git a/Ix/Theory/Named/InductiveFixtures.lean b/Ix/Theory/Named/InductiveFixtures.lean new file mode 100644 index 000000000..f1b2ff3be --- /dev/null +++ b/Ix/Theory/Named/InductiveFixtures.lean @@ -0,0 +1,2897 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Inductive +import Ix.Theory.Named.Meta +import Ix.Theory.Named.Typing.InductiveLemmas +import Ix.Theory.Named.Typing.Meta + +open Ix.Theory (VLevel) + +/-! Adequacy fixtures for `VEnv.addInduct` (stage 3): run the generator on +hand-written declarations and check the output against the real kernel's +constants, translated by the `vconst`/`vdefeq` macros. A mismatch in +telescope order, universe conventions, or de Bruijn arithmetic fails these +`rfl`s. -/ + +namespace Ix.Theory.Named +namespace InductiveFixtures +open VInductDecl + +/-- Permute the universe parameters of a translated constant. The `vconst` +and `vdefeq` macros number universes by occurrence order (declaration +levels first), while the kernel's recursors put the elimination level +first; these fixtures compare via the explicit permutation. -/ +private def permC (ci : VConstant) (ls : List VLevel) : VConstant := + ⟨ci.uvars, ci.type.instL ls⟩ + +private def permE (df : VDefEq) (ls : List VLevel) : VDefEq := + ⟨df.uvars, df.lhs.instL ls, df.rhs.instL ls, df.type.instL ls⟩ + +/-! ## Nat -/ + +def natType : VInductiveType where + name := ``Nat + uvars := 0 + type := vexpr(Type) + ctors := [⟨vconst(type_of% @Nat.zero), ``Nat.zero⟩, ⟨vconst(type_of% @Nat.succ), ``Nat.succ⟩] + +def natDecl : VInductDecl := ⟨0, 0, [natType]⟩ + +example : natDecl.stage3 = true := rfl + +/-- The shared checked analysis retains the normalized declaration data that +generation and verification consume. -/ +def natChecked : natDecl.Checked := natDecl.checked?.get (by decide) + +/-- Identity normalization packages the existing raw-normal-form path without +changing its analyzer result. -/ +def natNormalizedChecked : NormalizedChecked natDecl := + (identityChecked? natDecl).get (by decide) + +def natGenerationChecked : GenerationChecked natDecl := + (identityGeneration? natDecl).get (by decide) + +/-- The public block descriptor specializes to the same singleton metadata. -/ +def natBlockGenerationChecked : BlockGenerationChecked natDecl := + (identityBlockGeneration? natDecl).get (by decide) + +example : natNormalizedChecked.normalization.view = natDecl := rfl +example : natNormalizedChecked.checked.type = natType := rfl +example : (normalizedChecked? natDecl natDecl).isSome = true := rfl +example : (identityChecked? natDecl).isSome = natDecl.checked?.isSome := + identityChecked?_isSome natDecl +example : natGenerationChecked.block = natNormalizedChecked := rfl +example : natGenerationChecked.block.ctorPairs.length = 2 := rfl +example : natGenerationChecked.motiveType = natChecked.motiveType := rfl +example : natGenerationChecked.minorTypes = natChecked.minorTypes := rfl +example : natGenerationChecked.recursor = natChecked.recursor := rfl +example : natGenerationChecked.generatedRules = natChecked.generatedRules := rfl + +example : natChecked.type = natType := rfl +example : natChecked.params = [] := rfl +example : natChecked.indices = [] := rfl +example : natChecked.resultLevel = .succ .zero := rfl +example : natChecked.elimination = .large := rfl +example : natChecked.kTarget = false := rfl +example : natGenerationChecked.kTarget = false := rfl +example : natChecked.constructors.length = 2 := rfl +example : natChecked.constructors[1].recursive.length = 1 := rfl +example : natChecked.constructors[1].recursive[0].fieldIndex = 0 := rfl +example : natChecked.constructors[1].recursive[0].binders = [] := rfl +example : natChecked.recursor = recConst 0 ``Nat 0 natType := rfl +example : natChecked.generatedRules = rules 0 ``Nat 0 natType := rfl +example : natChecked.type.type.LevelWF natDecl.uvars := natChecked.type_levelWF +example : ∀ c ∈ natChecked.type.ctors, c.type.LevelWF natDecl.uvars := + fun _ hc => natChecked.ctor_levelWF hc + +/-- The generated recursor is exactly the kernel's `Nat.rec`. -/ +example : recConst 0 ``Nat 0 natType = vconst(type_of% @Nat.rec) := rfl + +/-- The generated iota rules are exactly the kernel's reduction rules for +`Nat.rec`, phrased as closed lambda-telescope defeqs like `quotDefEq`. -/ +example : (rules 0 ``Nat 0 natType)[0]? = + some (vdefeq(motive z s => @Nat.rec motive z s .zero ≡ z)) := rfl + +example : (rules 0 ``Nat 0 natType)[1]? = + some (vdefeq(motive z s n => @Nat.rec motive z s (.succ n) ≡ s n (@Nat.rec motive z s n))) := + rfl + +example : (VEnv.empty.addInduct natDecl).isSome = true := rfl + +example : (VEnv.empty.addInduct natDecl).map (·.constants ``Nat) = + some (some natType.toVConstant) := rfl + +example : (VEnv.empty.addInduct natDecl).map (·.constants ``Nat.rec) = + some (some (recConst 0 ``Nat 0 natType)) := rfl + +/-- The successor iota rule is registered in the output environment. -/ +example : ∀ env', VEnv.empty.addInduct natDecl = some env' → + env'.defeqs (rule 0 ``Nat 0 natType 1 ⟨vconst(type_of% @Nat.succ), ``Nat.succ⟩) := by + rintro env' ⟨⟩; exact .inl rfl + +/-! ## Bool -/ + +def boolType : VInductiveType where + name := ``Bool + uvars := 0 + type := vexpr(Type) + ctors := [⟨vconst(type_of% @Bool.false), ``Bool.false⟩, ⟨vconst(type_of% @Bool.true), ``Bool.true⟩] + +def boolDecl : VInductDecl := ⟨0, 0, [boolType]⟩ + +example : boolDecl.stage3 = true := rfl + +example : recConst 0 ``Bool 0 boolType = vconst(type_of% @Bool.rec) := rfl + +example : (rules 0 ``Bool 0 boolType)[0]? = + some (vdefeq(motive f t => @Bool.rec motive f t .false ≡ f)) := rfl + +example : (rules 0 ``Bool 0 boolType)[1]? = + some (vdefeq(motive f t => @Bool.rec motive f t .true ≡ t)) := rfl + +/-! ## Unit/Empty edge shapes + +`Unit` is a reducible alias for `PUnit` on this Lean revision, so the actual +one-constructor kernel metadata is recorded under `PUnit`. Together with +`Empty`, these fixtures exercise the one- and zero-constructor generation +paths without inventing an alias-level recursor that the kernel does not +declare. -/ + +def punitType : VInductiveType where + name := ``PUnit + uvars := 1 + type := vconst(type_of% @PUnit).type + ctors := [⟨vconst(type_of% @PUnit.unit), ``PUnit.unit⟩] + +def punitDecl : VInductDecl := ⟨1, 0, [punitType]⟩ + +example : punitDecl.stage3 = true := rfl + +def punitChecked : punitDecl.Checked := punitDecl.checked?.get (by decide) + +def punitGenerationChecked : GenerationChecked punitDecl := + (identityGeneration? punitDecl).get (by decide) + +example : punitChecked.params = [] := rfl +example : punitChecked.indices = [] := rfl +example : punitChecked.resultLevel = .param 0 := rfl +example : punitChecked.elimination = .large := rfl +example : punitChecked.kTarget = false := rfl +example : punitChecked.constructors.length = 1 := rfl +example : punitChecked.constructors[0].fields = [] := rfl +example : punitChecked.constructors[0].recursive = [] := rfl +example : punitGenerationChecked.block.ctorPairs.length = 1 := rfl +example : punitGenerationChecked.minorTypes.length = 1 := rfl +example : punitGenerationChecked.generatedRules.length = 1 := rfl + +/-- The one-constructor recursor retains the fresh elimination universe before +the source universe, and its sole minor occurs before the major. -/ +example : punitGenerationChecked.recursor = + permC (vconst(type_of% @PUnit.rec)) [.param 1, .param 0] := rfl + +example : punitGenerationChecked.generatedRules[0]? = + some (permE + (vdefeq((motive : PUnit.{u} → Sort v) unit => + @PUnit.rec.{v, u} motive unit @PUnit.unit.{u} ≡ unit)) + [.param 1, .param 0]) := rfl + +theorem punitDecl_wf : punitDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = punitType := + List.mem_singleton.1 (by simpa [punitDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · change True + trivial + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + constructor + · change True + trivial + · exact .nil + +def punitEnv : VEnv := + (VEnv.empty.addInduct punitDecl).get (by decide) + +/-- The public checked transaction and the normalized generation core are the +same computation for this identity-normalized edge fixture. -/ +example : VEnv.empty.addInduct punitDecl = + VEnv.empty.addInductGeneration punitGenerationChecked := rfl + +theorem punitEnv_ordered : punitEnv.Ordered := + VEnv.addInductGeneration_WF .empty + ((punitChecked.wf_of_decl punitDecl_wf).identityGeneration .empty) rfl + +def emptyType : VInductiveType where + name := ``Empty + uvars := 0 + type := vconst(type_of% @Empty).type + ctors := [] + +def emptyDecl : VInductDecl := ⟨0, 0, [emptyType]⟩ + +example : emptyDecl.stage3 = true := rfl + +def emptyChecked : emptyDecl.Checked := emptyDecl.checked?.get (by decide) + +def emptyGenerationChecked : GenerationChecked emptyDecl := + (identityGeneration? emptyDecl).get (by decide) + +def emptyBlockGenerationChecked : BlockGenerationChecked emptyDecl := + (identityBlockGeneration? emptyDecl).get (by decide) + +example : emptyChecked.params = [] := rfl +example : emptyChecked.indices = [] := rfl +example : emptyChecked.resultLevel = .succ .zero := rfl +example : emptyChecked.elimination = .large := rfl +example : emptyChecked.kTarget = false := rfl +example : emptyChecked.constructors = [] := rfl +example : emptyGenerationChecked.block.ctorPairs = [] := rfl +example : emptyGenerationChecked.minorTypes = [] := rfl +example : emptyGenerationChecked.generatedRules = [] := rfl + +/-- Empty elimination has a motive and major but no constructor minor. -/ +example : emptyGenerationChecked.recursor = + vconst(type_of% @Empty.rec) := rfl + +theorem emptyDecl_wf : emptyDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = emptyType := + List.mem_singleton.1 (by simpa [emptyDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · change True + trivial + · intro c hc + simp [emptyType] at hc + +def emptyEnv : VEnv := + (VEnv.empty.addInduct emptyDecl).get (by decide) + +example : VEnv.empty.addInduct emptyDecl = + VEnv.empty.addInductGeneration emptyGenerationChecked := rfl + +theorem emptyEnv_ordered : emptyEnv.Ordered := + VEnv.addInductGeneration_WF .empty + ((emptyChecked.wf_of_decl emptyDecl_wf).identityGeneration .empty) rfl + +/-! ## List: one parameter, a dependent field, direct recursion -/ + +def listType : VInductiveType where + name := ``List + uvars := 1 + type := vconst(type_of% @List).type + ctors := [⟨vconst(type_of% @List.nil), ``List.nil⟩, ⟨vconst(type_of% @List.cons), ``List.cons⟩] + +def listDecl : VInductDecl := ⟨1, 1, [listType]⟩ + +example : listDecl.stage3 = true := rfl + +/-- The generated recursor is exactly the kernel's `List.rec`, with the +occurrence-ordered `vconst` universes permuted to the kernel's +elimination-level-first convention. -/ +example : recConst 1 ``List 1 listType = + permC (vconst(type_of% @List.rec)) [.param 1, .param 0] := rfl + +example : (rules 1 ``List 1 listType)[0]? = + some (permE (vdefeq(α motive n c => @List.rec α motive n c (@List.nil α) ≡ n)) + [.param 1, .param 0]) := rfl + +example : (rules 1 ``List 1 listType)[1]? = + some (permE (vdefeq(α motive n c hd tl => + @List.rec α motive n c (@List.cons α hd tl) ≡ + c hd tl (@List.rec α motive n c tl))) + [.param 1, .param 0]) := rfl + +example : (VEnv.empty.addInduct listDecl).isSome = true := rfl + +/-! ## Prod: two parameters, no recursion -/ + +def prodType : VInductiveType where + name := ``Prod + uvars := 2 + type := vconst(type_of% @Prod).type + ctors := [⟨vconst(type_of% @Prod.mk), ``Prod.mk⟩] + +def prodDecl : VInductDecl := ⟨2, 2, [prodType]⟩ + +example : prodDecl.stage3 = true := rfl + +example : recConst 2 ``Prod 2 prodType = + permC (vconst(type_of% @Prod.rec)) [.param 1, .param 2, .param 0] := rfl + +example : (rules 2 ``Prod 2 prodType)[0]? = + some (permE (vdefeq(α β motive mk a b => + @Prod.rec α β motive mk (@Prod.mk α β a b) ≡ mk a b)) + [.param 1, .param 2, .param 0]) := rfl + +/-! ## Option: one parameter, two constructors -/ + +def optionType : VInductiveType where + name := ``Option + uvars := 1 + type := vconst(type_of% @Option).type + ctors := [⟨vconst(type_of% @Option.none), ``Option.none⟩, + ⟨vconst(type_of% @Option.some), ``Option.some⟩] + +def optionDecl : VInductDecl := ⟨1, 1, [optionType]⟩ + +example : optionDecl.stage3 = true := rfl + +example : recConst 1 ``Option 1 optionType = + permC (vconst(type_of% @Option.rec)) [.param 1, .param 0] := rfl + +example : (rules 1 ``Option 1 optionType)[0]? = + some (permE (vdefeq(α motive n s => @Option.rec α motive n s (@Option.none α) ≡ n)) + [.param 1, .param 0]) := rfl + +example : (rules 1 ``Option 1 optionType)[1]? = + some (permE (vdefeq(α motive n s a => @Option.rec α motive n s (@Option.some α a) ≡ s a)) + [.param 1, .param 0]) := rfl + +/-! ## Eq: parameters, one index, Prop-valued with subsingleton +elimination -/ + +def eqType : VInductiveType where + name := ``Eq + uvars := 1 + type := vconst(type_of% @Eq).type + ctors := [⟨vconst(type_of% @Eq.refl), ``Eq.refl⟩] + +def eqDecl : VInductDecl := ⟨1, 2, [eqType]⟩ + +example : eqDecl.stage3 = true := rfl + +def eqChecked : eqDecl.Checked := eqDecl.checked?.get (by decide) + +def eqGenerationChecked : GenerationChecked eqDecl := + (identityGeneration? eqDecl).get (by decide) + +example : eqChecked.params = [.sort (.param 0), .bvar 0] := rfl +example : eqChecked.indices = [.bvar 1] := rfl +example : eqChecked.resultLevel = .zero := rfl +example : eqChecked.elimination = .large := rfl +example : eqChecked.kTarget = true := rfl +example : eqGenerationChecked.kTarget = true := rfl +example : eqChecked.constructors[0].resultIndices = [.bvar 0] := rfl +example : eqChecked.recursor = recConst 1 ``Eq 2 eqType := rfl +example : eqGenerationChecked.motiveType = eqChecked.motiveType := rfl +example : eqGenerationChecked.minorTypes = eqChecked.minorTypes := rfl +example : eqGenerationChecked.recursor = eqChecked.recursor := rfl +example : eqGenerationChecked.generatedRules = eqChecked.generatedRules := rfl + +/-- The generated recursor is exactly the kernel's `Eq.rec`. -/ +example : recConst 1 ``Eq 2 eqType = + permC (vconst(type_of% @Eq.rec)) [.param 1, .param 0] := rfl + +example : (rules 1 ``Eq 2 eqType)[0]? = + some (permE (vdefeq(α a motive r => + @Eq.rec α a motive r a (@Eq.refl α a) ≡ r)) [.param 1, .param 0]) := rfl + +example : (VEnv.empty.addInduct eqDecl).isSome = true := rfl + +/-! ## HEq: two indices, one of them a sort -/ + +def heqType : VInductiveType where + name := ``HEq + uvars := 1 + type := vconst(type_of% @HEq).type + ctors := [⟨vconst(type_of% @HEq.refl), ``HEq.refl⟩] + +def heqDecl : VInductDecl := ⟨1, 2, [heqType]⟩ + +example : heqDecl.stage3 = true := rfl + +example : recConst 1 ``HEq 2 heqType = + permC (vconst(type_of% @HEq.rec)) [.param 1, .param 0] := rfl + +example : (rules 1 ``HEq 2 heqType)[0]? = + some (permE (vdefeq((α : Sort u) (a : α) + (motive : {β : Sort u} → (b : β) → HEq a b → Sort v) + (r : @motive α a (@HEq.refl α a)) => + @HEq.rec α a (@motive) r α a (@HEq.refl α a) ≡ r)) [.param 1, .param 0]) := rfl + +/-! ## IndexedVec: recursive occurrence at a changing index -/ + +inductive IndexedVec (α : Type u) : Nat → Type u where + | nil : IndexedVec α Nat.zero + | cons {n} : α → IndexedVec α n → IndexedVec α (Nat.succ n) + +def indexedVecType : VInductiveType where + name := ``IndexedVec + uvars := 1 + type := vconst(type_of% @IndexedVec).type + ctors := [⟨vconst(type_of% @IndexedVec.nil), ``IndexedVec.nil⟩, + ⟨vconst(type_of% @IndexedVec.cons), ``IndexedVec.cons⟩] + +def indexedVecDecl : VInductDecl := ⟨1, 1, [indexedVecType]⟩ + +example : indexedVecDecl.stage3 = true := rfl + +def indexedVecChecked : indexedVecDecl.Checked := + indexedVecDecl.checked?.get (by decide) + +def indexedVecGenerationChecked : GenerationChecked indexedVecDecl := + (identityGeneration? indexedVecDecl).get (by decide) + +example : indexedVecChecked.params = [.sort (.succ (.param 0))] := rfl +example : indexedVecChecked.indices = [.const ``Nat []] := rfl +example : indexedVecChecked.resultLevel = .succ (.param 0) := rfl +example : indexedVecChecked.elimination = .large := rfl +example : indexedVecChecked.constructors.length = 2 := rfl +example : indexedVecChecked.constructors[1].fields.length = 3 := rfl +example : indexedVecChecked.constructors[1].recursive.length = 1 := rfl +example : indexedVecChecked.constructors[1].recursive[0].fieldIndex = 2 := rfl +example : indexedVecChecked.constructors[1].recursive[0].binders = [] := rfl +example : indexedVecChecked.constructors[1].recursive[0].targetType = 0 := rfl +example : indexedVecChecked.constructors[1].recursive[0].indices = [.bvar 1] := rfl +example : indexedVecChecked.constructors[1].resultIndices = + [VExpr.app (VExpr.const ``Nat.succ []) (VExpr.bvar 2)] := rfl +example : indexedVecChecked.recursor = + recConst 1 ``IndexedVec 1 indexedVecType := rfl +example : indexedVecChecked.generatedRules = + rules 1 ``IndexedVec 1 indexedVecType := rfl +example : indexedVecGenerationChecked.motiveType = + indexedVecChecked.motiveType := rfl +example : indexedVecGenerationChecked.minorTypes = + indexedVecChecked.minorTypes := rfl +example : indexedVecGenerationChecked.recursor = + indexedVecChecked.recursor := rfl +example : indexedVecGenerationChecked.generatedRules = + indexedVecChecked.generatedRules := rfl + +/-- Semantic clients can migrate from the legacy declaration-level contract +to the normalized descriptor without re-analyzing its syntax. -/ +example {env : VEnv} (h : indexedVecDecl.WF env) : + indexedVecChecked.WF env := + indexedVecChecked.wf_of_decl h + +/-- The descriptor contract remains definitionally compatible with existing +preservation clients while that migration is in progress. -/ +example {env : VEnv} (h : indexedVecChecked.WF env) : + indexedVecDecl.WF env := + indexedVecChecked.to_declWF rfl h + +example : recConst 1 ``IndexedVec 1 indexedVecType = + permC (vconst(type_of% @IndexedVec.rec)) [.param 1, .param 0] := rfl + +example : (rules 1 ``IndexedVec 1 indexedVecType)[0]? = + some (permE (vdefeq((α : Type u) + (motive : (n : Nat) → IndexedVec α n → Sort v) + (nil : motive Nat.zero (@IndexedVec.nil α)) + (cons : {n : Nat} → (a : α) → (as : IndexedVec α n) → + motive n as → motive (Nat.succ n) (@IndexedVec.cons α n a as)) => + @IndexedVec.rec α motive nil (@cons) Nat.zero (@IndexedVec.nil α) ≡ nil)) + [.param 1, .param 0]) := rfl + +example : (rules 1 ``IndexedVec 1 indexedVecType)[1]? = + some (permE (vdefeq((α : Type u) + (motive : (n : Nat) → IndexedVec α n → Sort v) + (nil : motive Nat.zero (@IndexedVec.nil α)) + (cons : {n : Nat} → (a : α) → (as : IndexedVec α n) → + motive n as → motive (Nat.succ n) (@IndexedVec.cons α n a as)) + (n : Nat) (a : α) (as : IndexedVec α n) => + @IndexedVec.rec α motive nil (@cons) (Nat.succ n) + (@IndexedVec.cons α n a as) ≡ + @cons n a as (@IndexedVec.rec α motive nil (@cons) n as))) + [.param 1, .param 0]) := rfl + +example : (VEnv.empty.addInduct indexedVecDecl).isSome = true := rfl + +/-- Consumers obtain constructor lookup without unfolding the transactional +constructor fold. -/ +example : ∀ env', VEnv.empty.addInduct indexedVecDecl = some env' → + env'.constants ``IndexedVec.cons = some indexedVecType.ctors[1].toVConstant := by + intro env' hadd + exact VEnv.addInduct_ctor_lookup hadd (.head _) (.tail _ (.head _)) + +/-- The complete all-or-nothing postcondition is available from the same +successful call. -/ +example : ∀ env', VEnv.empty.addInduct indexedVecDecl = some env' → + VEnv.AddInductSuccess VEnv.empty env' indexedVecDecl := + fun _ => VEnv.addInduct_success + +/-- The transaction certificate exposes the exact block-generation result for +ix-like consumers without re-running structural analysis. -/ +example : ∀ env', VEnv.empty.addInduct indexedVecDecl = some env' → + ∃ generation, + indexedVecDecl.identityBlockGeneration? = some generation := + fun _ => VEnv.addInduct_generation + +/-! ## Acc: recursive argument beneath a Pi telescope + +`Acc.intro`'s recursive field is a function taking two arguments, and its +induction hypothesis is itself a two-argument function. This fixture exercises +the complete public checked/generation/transaction path, not a side generator. -/ + +def accType : VInductiveType where + name := ``Acc + uvars := 1 + type := vconst(type_of% @Acc).type + ctors := [⟨vconst(type_of% @Acc.intro), ``Acc.intro⟩] + +def accDecl : VInductDecl := ⟨1, 2, [accType]⟩ + +example : accDecl.stage3 = true := rfl + +def accChecked : accDecl.Checked := accDecl.checked?.get (by decide) + +def accGenerationChecked : GenerationChecked accDecl := + (identityGeneration? accDecl).get (by decide) + +def accBlockGenerationChecked : BlockGenerationChecked accDecl := + (identityBlockGeneration? accDecl).get (by decide) + +def accRecArgs : List RecArg := + recArgs 1 ``Acc 2 1 (ctorFields (VExpr.dropN 2 accType.ctors[0].type)) + +example : (ctorFields (VExpr.dropN 2 accType.ctors[0].type)).length = 2 := rfl +example : accRecArgs.length = 1 := rfl +example : accRecArgs[0].fieldIndex = 1 := rfl +example : accRecArgs[0].binders.length = 2 := rfl +example : accRecArgs[0].targetType = 0 := rfl +example : accRecArgs[0].indices = [.bvar 1] := rfl +example : accChecked.type = accType := rfl +example : accChecked.constructors[0].recursive = accRecArgs := rfl +example : accChecked.recursor = recConstRec 1 ``Acc 2 accType := rfl +example : accChecked.generatedRules = rulesRec 1 ``Acc 2 accType := rfl +example : accGenerationChecked.motiveType = accChecked.motiveType := rfl +example : accGenerationChecked.minorTypes = accChecked.minorTypes := rfl +example : accGenerationChecked.recursor = accChecked.recursor := rfl +example : accGenerationChecked.generatedRules = accChecked.generatedRules := rfl + +/-- The generalized recursor type is definitionally the kernel's `Acc.rec`, +including its functional induction hypothesis. -/ +example : recConstRec 1 ``Acc 2 accType = + permC (vconst(type_of% @Acc.rec)) [.param 1, .param 0] := rfl + +/-- The generalized iota RHS recurs under both binders of the recursive +function argument, exactly as Lean's kernel rule does. -/ +example : (rulesRec 1 ``Acc 2 accType)[0]? = + some (permE (vdefeq((α : Sort u) (r : α → α → Prop) + (motive : (a : α) → Acc r a → Sort v) + (intro : (a : α) → (h : (b : α) → r b a → Acc r b) → + ((b : α) → (hba : r b a) → motive b (h b hba)) → + motive a (@Acc.intro α r a h)) + (a : α) (h : (b : α) → r b a → Acc r b) => + @Acc.rec α r motive intro a (@Acc.intro α r a h) ≡ + intro a h (fun b hba => @Acc.rec α r motive intro b (h b hba)))) + [.param 1, .param 0]) := rfl + +/-- Recursive-Pi declarations now run through the same all-or-nothing public +transaction as direct recursive declarations. -/ +example : (VEnv.empty.addInduct accDecl).isSome = true := rfl + +example : (VEnv.empty.addInduct accDecl).map (·.constants ``Acc.rec) = + some (some (recConstRec 1 ``Acc 2 accType)) := rfl + +example : ∀ env', VEnv.empty.addInduct accDecl = some env' → + env'.defeqs (ruleRec 1 ``Acc 2 accType 0 accType.ctors[0]) := by + intro env' hadd + apply VEnv.addInduct_rule_mem hadd + (generation := accBlockGenerationChecked) rfl + change ruleRec 1 ``Acc 2 accType 0 accType.ctors[0] ∈ + accBlockGenerationChecked.generatedRules + exact .head _ + +example : ∀ env', VEnv.empty.addInduct accDecl = some env' → + VEnv.AddInductSuccess VEnv.empty env' accDecl := + fun _ => VEnv.addInduct_success + +/-- `Acc` satisfies the semantic declaration contract, including the +impredicative-Prop exception for its universe-polymorphic index field and the +typed telescope beneath its recursive Pi argument. -/ +theorem accDecl_wf : accDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = accType := List.mem_singleton.1 (by simpa [accDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · change VEnv.empty.OnTel 1 [] + [.sort (.param 0), + .forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero)), + .bvar 1] + exact ⟨⟨_, by type_tac⟩, ⟨⟨_, by type_tac⟩, ⟨⟨_, by type_tac⟩, trivial⟩⟩⟩ + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + constructor + · change fieldsWF 1 ``Acc 2 VEnv.empty .zero [.bvar 1] + [.forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero)), .sort (.param 0)] 0 + [.bvar 1, + .forallE (.bvar 2) + (.forallE (.app (.app (.bvar 2) (.bvar 0)) (.bvar 1)) + (.app (.app (.app (.const ``Acc [.param 0]) (.bvar 4)) (.bvar 3)) + (.bvar 1)))] + refine ⟨?_, ?_, ?_⟩ + · exact .inr (.inr ⟨rfl, .param 0, by type_tac, .inl rfl⟩) + · intro h + change false = true at h + contradiction + · dsimp only [fieldsWF] + refine ⟨?_, ?_, trivial⟩ + · refine .inr (.inl ⟨accRecArgs[0], rfl, ?_, ?_⟩) + · decide + · change + VEnv.empty.OnTel 1 + [.bvar 1, + .forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero)), + .sort (.param 0)] + [.bvar 2, .app (.app (.bvar 2) (.bvar 0)) (.bvar 1)] ∧ + VEnv.empty.SpineWF 1 + [.app (.app (.bvar 2) (.bvar 0)) (.bvar 1), .bvar 2, + .bvar 1, + .forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero)), + .sort (.param 0)] + (.forallE (.bvar 4) (.sort .zero)) [.bvar 1] (.sort .zero) + constructor + · exact ⟨⟨_, by type_tac⟩, ⟨⟨_, by type_tac⟩, trivial⟩⟩ + · exact .cons (by type_tac) .nil + · intro h + change false = true at h + contradiction + · change VEnv.empty.SpineWF 1 + [.forallE (.bvar 2) + (.forallE (.app (.app (.bvar 2) (.bvar 0)) (.bvar 1)) + (.app (.app (.app (.const ``Acc [.param 0]) (.bvar 4)) (.bvar 3)) + (.bvar 1))), + .bvar 1, + .forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero)), + .sort (.param 0)] + (.forallE (.bvar 3) (.sort .zero)) [.bvar 1] (.sort .zero) + exact .cons (by type_tac) .nil + +/-- The concrete public Acc transaction preserves environment order. -/ +def accEnv : VEnv := (VEnv.empty.addInduct accDecl).get (by decide) + +example : accEnv.Ordered := + VEnv.addInductGeneration_WF .empty + ((accChecked.wf_of_decl accDecl_wf).identityGeneration .empty) rfl + +/-- A collision at the generated recursor name still rejects the whole Acc +transaction; no recursive-Pi special case bypasses freshness. -/ +def accRecCollisionEnv : VEnv := + (VEnv.empty.addConst ``Acc.rec ⟨0, .sort .zero⟩).get (by decide) + +example : accRecCollisionEnv.addInduct accDecl = none := + VEnv.addInduct_eq_none_of_rec_present + (generation := accBlockGenerationChecked) rfl (.head _) ⟨_, rfl⟩ + +/-! ## AnnotatedPi: recursive Pi normalization below a constructor field + +Lean retains `outParam` in the constructor's raw recursive-function domain, +while inductive analysis consumes it before recognizing the recursive target. +This fixture combines the annotation and recursive-Pi seams in one declaration +and keeps the raw binder syntax in generated artifacts. -/ + +inductive AnnotatedPi : Type where + | mk : ((p : outParam Prop) → AnnotatedPi) → AnnotatedPi + +def outParamDefEq : VDefEq := + vdefeq(@outParam ≡ fun (α : Sort u) => α) + +def outParamConstEnv : VEnv := + (VEnv.empty.addConst ``outParam (vconst(type_of% @outParam))).get + (by decide) + +def outParamEnv : VEnv := outParamConstEnv.addDefEq outParamDefEq + +theorem outParamConstant_wf : + (vconst(type_of% @outParam) : VConstant).WF VEnv.empty := by + exact ⟨_, VEnv.HasType.forallE + (VEnv.HasType.sort (by decide)) + (VEnv.HasType.sort (by decide))⟩ + +theorem outParamConstEnv_ordered : outParamConstEnv.Ordered := by + apply VEnv.Ordered.const VEnv.Ordered.empty + (ci := vconst(type_of% @outParam)) + · exact outParamConstant_wf + · rfl + +theorem outParamEnv_ordered : outParamEnv.Ordered := by + apply VEnv.Ordered.defeq outParamConstEnv_ordered + constructor + · exact VEnv.HasType.const0 rfl + (outParamConstant_wf.mono + (VEnv.addConst_le (by rfl : + VEnv.empty.addConst ``outParam (vconst(type_of% @outParam)) = + some outParamConstEnv))) + · exact VEnv.HasType.lam + (VEnv.HasType.sort (by decide)) + (VEnv.HasType.bvar .zero) + +def annotatedPiRawType : VInductiveType where + name := ``AnnotatedPi + uvars := 0 + type := vconst(type_of% @AnnotatedPi).type + ctors := [⟨vconst(type_of% @AnnotatedPi.mk), ``AnnotatedPi.mk⟩] + +def annotatedPiRawDecl : VInductDecl := ⟨0, 0, [annotatedPiRawType]⟩ + +def annotatedPiViewCtor : VConstVal where + name := ``AnnotatedPi.mk + uvars := 0 + type := .forallE + (.forallE (.sort .zero) (.const ``AnnotatedPi [])) + (.const ``AnnotatedPi []) + +def annotatedPiViewType : VInductiveType := + { annotatedPiRawType with ctors := [annotatedPiViewCtor] } + +def annotatedPiViewDecl : VInductDecl := ⟨0, 0, [annotatedPiViewType]⟩ + +example : annotatedPiRawType.ctors[0].type = + .forallE + (.forallE + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi [])) + (.const ``AnnotatedPi []) := rfl + +example : annotatedPiViewDecl.checked?.isSome = true := rfl +example : normalizationShape annotatedPiRawDecl annotatedPiViewDecl = true := + rfl + +def annotatedPiNormalization : Normalization annotatedPiRawDecl where + view := annotatedPiViewDecl + shape_eq := rfl + +def annotatedPiViewChecked : annotatedPiViewDecl.Checked := + annotatedPiViewDecl.checked?.get (by decide) + +def annotatedPiBlock : NormalizedChecked annotatedPiRawDecl := + annotatedPiNormalization.check?.get (by decide) + +def annotatedPiGenerationChecked : GenerationChecked annotatedPiRawDecl := + annotatedPiBlock.generation?.get (by decide) + +def annotatedPiRecArg : RecArg where + fieldIndex := 0 + binders := [.sort .zero] + targetType := 0 + indices := [] + +example : annotatedPiViewChecked.constructors[0].recursive = + [annotatedPiRecArg] := rfl + +example : annotatedPiGenerationChecked.block.ctorPairs[0].rawFields 0 = + [.forallE + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi [])] := rfl + +example : annotatedPiGenerationChecked.recursor = + vconst(type_of% @AnnotatedPi.rec) := rfl + +example : annotatedPiGenerationChecked.generatedRules[0].rhs = + (vdefeq((motive : AnnotatedPi → Sort u) + (mk : (f : (p : outParam Prop) → AnnotatedPi) → + ((p : Prop) → motive (f p)) → motive (@AnnotatedPi.mk f)) + (f : (p : outParam Prop) → AnnotatedPi) => + @AnnotatedPi.rec motive mk (@AnnotatedPi.mk f) ≡ + mk f (fun p => @AnnotatedPi.rec motive mk (f p)))).rhs := rfl + +/-- The normalized recursive-Pi view is semantically well formed without +using the annotation definition; the raw-to-view bridge is supplied later by +the exact checker candidate. -/ +theorem annotatedPiViewDecl_wf : annotatedPiViewDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = annotatedPiViewType := + List.mem_singleton.1 (by simpa [annotatedPiViewDecl] using hty) + subst ty + refine ⟨by trivial, ?_⟩ + intro c hc + have hc' : c = annotatedPiViewCtor := + List.mem_singleton.1 (by simpa [annotatedPiViewType] using hc) + subst c + constructor + · change fieldsWF 0 ``AnnotatedPi 0 VEnv.empty (.succ .zero) [] [] 0 + [.forallE (.sort .zero) (.const ``AnnotatedPi [])] + refine ⟨?_, ?_, trivial⟩ + · right + left + refine ⟨annotatedPiRecArg, ?_, ?_, ?_⟩ + · rfl + · simp [annotatedPiRecArg] + · exact ⟨⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩, .nil⟩ + · intro h + change false = true at h + contradiction + · change VEnv.empty.SpineWF 0 + [.forallE (.sort .zero) (.const ``AnnotatedPi [])] + (.sort (.succ .zero)) [] (.sort (.succ .zero)) + exact .nil + +theorem annotatedPiViewChecked_wf : + annotatedPiViewChecked.WF outParamEnv := by + apply VInductDecl.Checked.WF.mono + ((VEnv.addConst_le (by rfl : + VEnv.empty.addConst ``outParam (vconst(type_of% @outParam)) = + some outParamConstEnv)).trans VEnv.addDefEq_le) + exact annotatedPiViewChecked.wf_of_decl annotatedPiViewDecl_wf + +/-! ## AnnotatedParam: definitionally equal constructor parameters + +Family validation consumes the `outParam` annotation before recording its +parameter local. Constructor metadata retains the annotation, so the ordinary +validator must use definitional equality rather than syntax when it checks the +constructor's parameter prefix. -/ + +inductive AnnotatedParam (alpha : outParam Type) : Type where + | mk : AnnotatedParam alpha + +def annotatedParamRawType : VInductiveType where + name := ``AnnotatedParam + uvars := 0 + type := vconst(type_of% @AnnotatedParam).type + ctors := [⟨vconst(type_of% @AnnotatedParam.mk), ``AnnotatedParam.mk⟩] + +def annotatedParamRawDecl : VInductDecl := + ⟨0, 1, [annotatedParamRawType]⟩ + +def annotatedParamViewCtor : VConstVal where + name := ``AnnotatedParam.mk + uvars := 0 + type := .forallE (.sort (.succ .zero)) + (.app (.const ``AnnotatedParam []) (.bvar 0)) + +def annotatedParamViewType : VInductiveType where + name := ``AnnotatedParam + uvars := 0 + type := .forallE (.sort (.succ .zero)) (.sort (.succ .zero)) + ctors := [annotatedParamViewCtor] + +def annotatedParamViewDecl : VInductDecl := + ⟨0, 1, [annotatedParamViewType]⟩ + +example : annotatedParamRawType.type = + .forallE + (.app (.const ``outParam [.succ (.succ .zero)]) + (.sort (.succ .zero))) + (.sort (.succ .zero)) := rfl + +example : annotatedParamRawType.ctors[0].type = + .forallE + (.app (.const ``outParam [.succ (.succ .zero)]) + (.sort (.succ .zero))) + (.app (.const ``AnnotatedParam []) (.bvar 0)) := rfl + +example : annotatedParamViewDecl.checked?.isSome = true := rfl +example : normalizationShape annotatedParamRawDecl annotatedParamViewDecl = + true := rfl + +def annotatedParamNormalization : Normalization annotatedParamRawDecl where + view := annotatedParamViewDecl + shape_eq := rfl + +def annotatedParamViewChecked : annotatedParamViewDecl.Checked := + annotatedParamViewDecl.checked?.get (by decide) + +def annotatedParamBlock : NormalizedChecked annotatedParamRawDecl := + annotatedParamNormalization.check?.get (by decide) + +def annotatedParamGenerationChecked : + GenerationChecked annotatedParamRawDecl := + annotatedParamBlock.generation?.get (by decide) + +example : annotatedParamGenerationChecked.recursor = + vconst(type_of% @AnnotatedParam.rec) := rfl + +example : annotatedParamGenerationChecked.generatedRules[0]? = + some (vdefeq((alpha : Type) + (motive : AnnotatedParam alpha → Sort u) + (mk : motive (@AnnotatedParam.mk alpha)) => + @AnnotatedParam.rec alpha motive mk (@AnnotatedParam.mk alpha) ≡ mk)) := rfl + +/-- The raw parameter domain retained by kernel metadata before annotation +consumption. -/ +def annotatedParamRawDomain : VExpr := + .app (.const ``outParam [.succ (.succ .zero)]) + (.sort (.succ .zero)) + +/-- The stored `outParam Type` parameter and the checked `Type` parameter are +definitionally equal in the exact pre-declaration environment. -/ +theorem annotatedParamRawDomain_defeq : + outParamEnv.IsDefEq 0 [] annotatedParamRawDomain + (.sort (.succ .zero)) (.sort (.succ (.succ .zero))) := by + have hfn : outParamEnv.IsDefEq 0 [] + (.const ``outParam [.succ (.succ .zero)]) + (.lam (.sort (.succ (.succ .zero))) (.bvar 0)) + (.forallE (.sort (.succ (.succ .zero))) + (.sort (.succ (.succ .zero)))) := by + simpa [outParamDefEq, VExpr.instL, VLevel.inst] using + (VEnv.IsDefEq.extra (env := outParamEnv) (uvars := 0) (Γ := []) + (df := outParamDefEq) (ls := [.succ (.succ .zero)]) + (by simp [outParamEnv, VEnv.addDefEq]) + (by simp; decide) rfl) + have harg : outParamEnv.HasType 0 [] + (.sort (.succ .zero)) (.sort (.succ (.succ .zero))) := + VEnv.HasType.sort (by decide) + exact (VEnv.IsDefEq.appDF hfn harg).trans + (VEnv.IsDefEq.beta (VEnv.HasType.bvar .zero) harg) + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.annotatedParamRawDomain_defeq [propext, Quot.sound] + +/-- The annotation-consumed declaration accepted by the structural analyzer +has the ordinary direct semantic interpretation. -/ +theorem annotatedParamViewDecl_wf : + annotatedParamViewDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = annotatedParamViewType := + List.mem_singleton.1 (by + simpa [annotatedParamViewDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · change VEnv.OnTel VEnv.empty 0 [] [.sort (.succ .zero)] + exact ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩ + · intro c hc + have hc' : c = annotatedParamViewCtor := + List.mem_singleton.1 (by + simpa [annotatedParamViewType] using hc) + subst c + exact ⟨trivial, .nil⟩ + +/-- Exact Theory environment after staging the stored family constant. -/ +def annotatedParamTypeEnv : VEnv := + (outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant).get (by decide) + +theorem annotatedParamTypeEnv_ordered : + annotatedParamTypeEnv.Ordered := by + have hbody : outParamEnv.HasType 0 [annotatedParamRawDomain] + (.sort (.succ .zero)) (.sort (.succ (.succ .zero))) := + VEnv.HasType.sort (by decide) + apply VEnv.Ordered.const (n := annotatedParamRawType.name) + (ci := annotatedParamRawType.toVConstant) + outParamEnv_ordered + · exact ⟨.imax (.succ (.succ .zero)) (.succ (.succ .zero)), + VEnv.HasType.forallE + (VEnv.IsDefEq.hasType annotatedParamRawDomain_defeq).1 hbody⟩ + · rfl + +private theorem annotatedParamFamilyApp_hasType (domain : VExpr) + (hdomain : annotatedParamTypeEnv.HasType 0 [domain] + (.bvar 0) annotatedParamRawDomain) : + annotatedParamTypeEnv.HasType 0 [domain] + (.app (.const ``AnnotatedParam []) (.bvar 0)) + (.sort (.succ .zero)) := by + apply VEnv.HasType.app + (A := annotatedParamRawDomain) (B := .sort (.succ .zero)) + · simpa [annotatedParamRawType, annotatedParamRawDomain, + VExpr.instL, VLevel.inst] using + VEnv.HasType.const (env := annotatedParamTypeEnv) (U := 0) + (Γ := [domain]) (c := ``AnnotatedParam) + (ci := annotatedParamRawType.toVConstant) (ls := []) + (VEnv.addConst_self (show + outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant = + some annotatedParamTypeEnv from rfl)) + (by simp) rfl + · exact hdomain + +theorem annotatedParamRawCtorBody_hasType : + annotatedParamTypeEnv.HasType 0 [annotatedParamRawDomain] + (.app (.const ``AnnotatedParam []) (.bvar 0)) + (.sort (.succ .zero)) := by + apply annotatedParamFamilyApp_hasType + simpa [annotatedParamRawDomain, VExpr.liftN] using + (VEnv.HasType.bvar (env := annotatedParamTypeEnv) (U := 0) + (Lookup.zero (Γ := []) (ty := annotatedParamRawDomain))) + +theorem annotatedParamCheckedCtorBody_hasType : + annotatedParamTypeEnv.HasType 0 [.sort (.succ .zero)] + (.app (.const ``AnnotatedParam []) (.bvar 0)) + (.sort (.succ .zero)) := by + apply annotatedParamFamilyApp_hasType + have hb : annotatedParamTypeEnv.HasType 0 [.sort (.succ .zero)] + (.bvar 0) (.sort (.succ .zero)) := by + simpa [VExpr.liftN] using + (VEnv.HasType.bvar (env := annotatedParamTypeEnv) (U := 0) + (Lookup.zero (Γ := []) (ty := .sort (.succ .zero)))) + have hd := annotatedParamRawDomain_defeq.mono + (VEnv.addConst_le (show + outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant = + some annotatedParamTypeEnv from rfl)) + exact (hd.weak0 annotatedParamTypeEnv_ordered).symm.defeq hb + +/-- The raw family and constructor metadata are semantically related to the +annotation-consumed analyzer view at their exact declaration stages. -/ +theorem annotatedParamNormalization_wf : + annotatedParamNormalization.WF outParamEnv := by + refine ⟨annotatedParamRawType, annotatedParamViewType, + rfl, rfl, ?_, ?_⟩ + · have hbody : outParamEnv.HasType 0 [annotatedParamRawDomain] + (.sort (.succ .zero)) (.sort (.succ (.succ .zero))) := + VEnv.HasType.sort (by decide) + exact ⟨_, VEnv.IsDefEq.forallEDF + annotatedParamRawDomain_defeq hbody⟩ + · intro envT hadd + have henv : envT = annotatedParamTypeEnv := by + have : some envT = some annotatedParamTypeEnv := + hadd.symm.trans (show + outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant = + some annotatedParamTypeEnv from rfl) + exact Option.some.inj this + subst envT + exact .cons ⟨_, VEnv.IsDefEq.forallEDF + (annotatedParamRawDomain_defeq.mono + (VEnv.addConst_le (show + outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant = + some annotatedParamTypeEnv from rfl))) + annotatedParamRawCtorBody_hasType⟩ .nil + +theorem annotatedParamViewChecked_wf : + annotatedParamViewChecked.WF outParamEnv := by + apply VInductDecl.Checked.WF.mono + ((VEnv.addConst_le (by rfl : + VEnv.empty.addConst ``outParam (vconst(type_of% @outParam)) = + some outParamConstEnv)).trans VEnv.addDefEq_le) + exact annotatedParamViewChecked.wf_of_decl annotatedParamViewDecl_wf + +/-- The mixed generation value uses the checked parameter for emitted +recursor binders while retaining the raw constructor surface, and all four +raw/view telescope/result obligations hold in their respective contexts. -/ +theorem annotatedParamGenerationChecked_wf : + annotatedParamGenerationChecked.WF outParamEnv := by + refine { + blockWF := ⟨annotatedParamNormalization_wf, + annotatedParamViewChecked_wf⟩ + familyTel := ?_ + familyResult := ?_ + ctors := ?_ } + · change outParamEnv.TelDefEq 0 [] [annotatedParamRawDomain] + [.sort (.succ .zero)] + exact ⟨⟨_, annotatedParamRawDomain_defeq⟩, trivial⟩ + · exact VEnv.HasType.sort (by decide) + · intro envT hadd ctor hctor + have henv : envT = annotatedParamTypeEnv := by + have : some envT = some annotatedParamTypeEnv := + hadd.symm.trans (show + outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant = + some annotatedParamTypeEnv from rfl) + exact Option.some.inj this + subst envT + change ctor ∈ [⟨annotatedParamRawType.ctors[0], + annotatedParamViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + refine { + declaredTel := ⟨⟨_, annotatedParamRawDomain_defeq.mono + (VEnv.addConst_le (show + outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant = + some annotatedParamTypeEnv from rfl))⟩, trivial⟩ + declaredResult := annotatedParamRawCtorBody_hasType + emittedTel := ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩ + emittedResult := annotatedParamCheckedCtorBody_hasType } + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.annotatedParamGenerationChecked_wf [propext, Quot.sound] + +/-! ## Explicit normalization boundary + +Lean stores reducible aliases in inductive metadata even though +`checkInductiveTypes`, positivity, and recursive-argument recognition inspect +their WHNF. These kernel-accepted declarations demonstrate why raw metadata +cannot simply be assumed normalized. Their explicit views exercise the new +environment-independent `Normalization` boundary; semantic defeq evidence and +raw-syntax-preserving artifact generation remain separate obligations. +-/ + +abbrev TypeFamilyAlias := Type + +inductive AliasFormer : TypeFamilyAlias where + | mk : AliasFormer + +def aliasFormerRawType : VInductiveType where + name := ``AliasFormer + uvars := 0 + type := vconst(type_of% @AliasFormer).type + ctors := [⟨vconst(type_of% @AliasFormer.mk), ``AliasFormer.mk⟩] + +def aliasFormerRawDecl : VInductDecl := ⟨0, 0, [aliasFormerRawType]⟩ + +example : aliasFormerRawType.type = .const ``TypeFamilyAlias [] := rfl +example : aliasFormerRawDecl.checked? = none := rfl + +def aliasFormerViewType : VInductiveType := + { aliasFormerRawType with type := .sort (.succ .zero) } + +def aliasFormerViewDecl : VInductDecl := ⟨0, 0, [aliasFormerViewType]⟩ + +example : aliasFormerViewDecl.checked?.isSome = true := rfl +example : normalizationShape aliasFormerRawDecl aliasFormerViewDecl = true := rfl + +def aliasFormerNormalization : Normalization aliasFormerRawDecl where + view := aliasFormerViewDecl + shape_eq := rfl + +def aliasFormerViewChecked : aliasFormerViewDecl.Checked := + aliasFormerViewDecl.checked?.get (by decide) + +def aliasFormerBlock : NormalizedChecked aliasFormerRawDecl := + aliasFormerNormalization.check?.get (by decide) + +def aliasFormerGenerationChecked : GenerationChecked aliasFormerRawDecl := + aliasFormerBlock.generation?.get (by decide) + +example : aliasFormerNormalization.accepted = true := rfl +example : (normalizedChecked? aliasFormerRawDecl aliasFormerViewDecl).isSome = true := rfl +example : aliasFormerBlock.checked.type = aliasFormerViewType := rfl +example : aliasFormerGenerationChecked.recursor = + vconst(type_of% @AliasFormer.rec) := rfl +example : aliasFormerGenerationChecked.generatedRules[0]? = + some (vdefeq(motive mk => + @AliasFormer.rec motive mk AliasFormer.mk ≡ mk)) := rfl +example : ∃ raw, + aliasFormerRawDecl.types = [raw] ∧ + raw.name = aliasFormerBlock.checked.type.name ∧ + raw.uvars = aliasFormerBlock.checked.type.uvars ∧ + List.Forall₂ CtorHeaderEq raw.ctors aliasFormerBlock.checked.type.ctors := + aliasFormerBlock.source_anatomy + +def typeFamilyAliasDefEq : VDefEq := vdefeq(TypeFamilyAlias ≡ Type) + +def typeFamilyAliasConstEnv : VEnv := + (VEnv.empty.addConst ``TypeFamilyAlias + (vconst(type_of% @TypeFamilyAlias))).get (by decide) + +def typeFamilyAliasEnv : VEnv := + typeFamilyAliasConstEnv.addDefEq typeFamilyAliasDefEq + +theorem typeFamilyAliasConstant_wf : + (vconst(type_of% @TypeFamilyAlias) : VConstant).WF + VEnv.empty := by + exact ⟨_, VEnv.HasType.sort (by decide)⟩ + +theorem typeFamilyAliasConstEnv_ordered : + typeFamilyAliasConstEnv.Ordered := by + apply VEnv.Ordered.const VEnv.Ordered.empty + (ci := vconst(type_of% @TypeFamilyAlias)) + · exact typeFamilyAliasConstant_wf + · rfl + +theorem typeFamilyAliasEnv_ordered : + typeFamilyAliasEnv.Ordered := by + apply VEnv.Ordered.defeq typeFamilyAliasConstEnv_ordered + constructor + · exact VEnv.HasType.const0 rfl + (typeFamilyAliasConstant_wf.mono + (VEnv.addConst_le (by rfl : + VEnv.empty.addConst ``TypeFamilyAlias + (vconst(type_of% @TypeFamilyAlias)) = + some typeFamilyAliasConstEnv))) + · exact VEnv.HasType.sort (by decide) + +/-- The explicit family-type view is not merely shape-compatible: the stored +alias and its WHNF are definitionally equal in the pre-environment, and the +unchanged constructor remains equal after inserting the raw family constant. +-/ +theorem aliasFormerNormalization_wf : + aliasFormerNormalization.WF typeFamilyAliasEnv := by + refine ⟨aliasFormerRawType, aliasFormerViewType, rfl, rfl, ?_, ?_⟩ + · refine ⟨_, .extra (df := typeFamilyAliasDefEq) (ls := []) ?_ + (fun _ h => nomatch h) rfl⟩ + simp [typeFamilyAliasEnv, VEnv.addDefEq] + · intro envT hadd + exact .cons + ⟨_, .constDF (VEnv.addConst_self hadd) (by simp) (by simp) rfl .nil⟩ + .nil + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerNormalization_wf [propext, Quot.sound] + +/-- The normalized view is a semantically well-formed direct declaration in +the same pre-environment. -/ +theorem aliasFormerViewDecl_wf : + aliasFormerViewDecl.WF typeFamilyAliasEnv := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = aliasFormerViewType := + List.mem_singleton.1 (by simpa [aliasFormerViewDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · trivial + · intro c hc + have hc' : c = aliasFormerRawType.ctors[0] := + List.mem_singleton.1 (by + simpa [aliasFormerViewType, aliasFormerRawType] using hc) + subst c + exact ⟨trivial, .nil⟩ + +/-- The paired block carries both the semantic normalization certificate and +the checked normalized view required by downstream generation. -/ +theorem aliasFormerBlock_wf : aliasFormerBlock.WF typeFamilyAliasEnv := by + refine ⟨aliasFormerNormalization_wf, ?_⟩ + change aliasFormerViewChecked.WF typeFamilyAliasEnv + exact aliasFormerViewChecked.wf_of_decl aliasFormerViewDecl_wf + +theorem aliasFormerGenerationChecked_wf : + aliasFormerGenerationChecked.WF typeFamilyAliasEnv := by + refine { + blockWF := aliasFormerBlock_wf + familyTel := by trivial + familyResult := ?_ + ctors := ?_ } + · change typeFamilyAliasEnv.IsDefEq 0 [] + (.const ``TypeFamilyAlias []) (.sort (.succ .zero)) + (.sort (.succ (.succ .zero))) + exact .extra (df := typeFamilyAliasDefEq) (ls := []) + (by simp [typeFamilyAliasEnv, VEnv.addDefEq]) + (fun _ h => nomatch h) rfl + · intro envT hadd ctor hctor + change ctor ∈ + [⟨aliasFormerRawType.ctors[0], aliasFormerViewChecked.constructors[0]⟩] + at hctor + obtain rfl := List.mem_singleton.1 hctor + have hfamily₀ : envT.HasType 0 [] + (.const aliasFormerGenerationChecked.block.sourceType.name []) + (aliasFormerGenerationChecked.block.sourceType.type.instL []) := + .const (VEnv.addConst_self hadd) (by simp) (by rfl) + change envT.HasType 0 [] (.const ``AliasFormer []) + (.const ``TypeFamilyAlias []) at hfamily₀ + have halias₀ : typeFamilyAliasEnv.IsDefEq 0 [] + (.const ``TypeFamilyAlias []) (.sort (.succ .zero)) + (.sort (.succ (.succ .zero))) := + .extra (df := typeFamilyAliasDefEq) (ls := []) + (by simp [typeFamilyAliasEnv, VEnv.addDefEq]) + (fun _ h => nomatch h) rfl + have halias := halias₀.mono (VEnv.addConst_le hadd) + have hfamily : envT.IsDefEq 0 [] + (.const ``AliasFormer []) (.const ``AliasFormer []) + (.sort (.succ .zero)) := + halias.defeq hfamily₀ + exact { + declaredTel := by trivial + declaredResult := hfamily + emittedTel := by trivial + emittedResult := hfamily } + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerBlock_wf [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerGenerationChecked_wf [propext, Quot.sound] + +/-- The non-identity family-alias case executes the same normalized +transaction used by the public identity wrapper. -/ +def aliasFormerFinalEnv : VEnv := + (typeFamilyAliasEnv.addInductGeneration + aliasFormerGenerationChecked).get (by decide) + +theorem aliasFormer_addInductGeneration : + typeFamilyAliasEnv.addInductGeneration + aliasFormerGenerationChecked = + some aliasFormerFinalEnv := rfl + +theorem aliasFormerFinalEnv_trace : + Nonempty (VEnv.AddInductGenerationTrace + typeFamilyAliasEnv aliasFormerFinalEnv + aliasFormerGenerationChecked) := + VEnv.addInductGeneration_trace aliasFormer_addInductGeneration + +theorem aliasFormerFinalEnv_le : + typeFamilyAliasEnv ≤ aliasFormerFinalEnv := by + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.le + +theorem aliasFormerFinalEnv_family_fresh : + typeFamilyAliasEnv.constants ``AliasFormer = none := by + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.family_fresh + +theorem aliasFormerFinalEnv_family_lookup : + aliasFormerFinalEnv.constants ``AliasFormer = + some aliasFormerRawType.toVConstant := by + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.family_lookup + +theorem aliasFormerFinalEnv_ctor_fresh : + ∀ c ∈ aliasFormerRawType.ctors, + typeFamilyAliasEnv.constants c.name = none := by + intro c hc + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.ctor_fresh hc + +theorem aliasFormerFinalEnv_ctor_lookup : + ∀ c ∈ aliasFormerRawType.ctors, + aliasFormerFinalEnv.constants c.name = + some c.toVConstant := by + intro c hc + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.ctor_lookup hc + +theorem aliasFormerFinalEnv_rec_fresh : + typeFamilyAliasEnv.constants ``AliasFormer.rec = none := by + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.rec_fresh + +theorem aliasFormerFinalEnv_rec_lookup : + aliasFormerFinalEnv.constants ``AliasFormer.rec = + some (vconst(type_of% @AliasFormer.rec)) := by + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.rec_lookup + +theorem aliasFormerFinalEnv_rule_mem : + ∀ df ∈ aliasFormerGenerationChecked.generatedRules, + aliasFormerFinalEnv.defeqs df := by + intro df hdf + rcases aliasFormerFinalEnv_trace with ⟨H⟩ + exact H.rule_mem hdf + +theorem aliasFormerFinalEnv_iota_mem : + aliasFormerFinalEnv.defeqs + (vdefeq(motive mk => + @AliasFormer.rec motive mk AliasFormer.mk ≡ mk)) := by + apply aliasFormerFinalEnv_rule_mem + exact .head _ + +theorem aliasFormerFinalEnv_ordered : + aliasFormerFinalEnv.Ordered := + VEnv.addInductGeneration_WF + typeFamilyAliasEnv_ordered + aliasFormerGenerationChecked_wf + aliasFormer_addInductGeneration + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerFinalEnv_trace [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerFinalEnv_family_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerFinalEnv_ctor_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerFinalEnv_rec_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerFinalEnv_iota_mem [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasFormerFinalEnv_ordered [propext, Classical.choice, Quot.sound] + +abbrev RecAlias (α : Sort u) := α + +inductive AliasRec : Type where + | mk : RecAlias AliasRec → AliasRec + +def aliasRecRawType : VInductiveType where + name := ``AliasRec + uvars := 0 + type := vconst(type_of% @AliasRec).type + ctors := [⟨vconst(type_of% @AliasRec.mk), ``AliasRec.mk⟩] + +def aliasRecRawDecl : VInductDecl := ⟨0, 0, [aliasRecRawType]⟩ + +def aliasRecRawField : VExpr := + (VExpr.const ``RecAlias [.succ .zero]).app (VExpr.const ``AliasRec []) + +example : ctorFields aliasRecRawType.ctors[0].type = [aliasRecRawField] := rfl +example : aliasRecRawDecl.checked? = none := rfl + +def aliasRecViewCtor : VConstVal := + { aliasRecRawType.ctors[0] with + type := .forallE (.const ``AliasRec []) (.const ``AliasRec []) } + +def aliasRecViewType : VInductiveType := + { aliasRecRawType with ctors := [aliasRecViewCtor] } + +def aliasRecViewDecl : VInductDecl := ⟨0, 0, [aliasRecViewType]⟩ + +example : aliasRecViewDecl.checked?.isSome = true := rfl +example : normalizationShape aliasRecRawDecl aliasRecViewDecl = true := rfl + +def aliasRecNormalization : Normalization aliasRecRawDecl where + view := aliasRecViewDecl + shape_eq := rfl + +def aliasRecViewChecked : aliasRecViewDecl.Checked := + aliasRecViewDecl.checked?.get (by decide) + +def aliasRecBlock : NormalizedChecked aliasRecRawDecl := + aliasRecNormalization.check?.get (by decide) + +def aliasRecGenerationChecked : GenerationChecked aliasRecRawDecl := + aliasRecBlock.generation?.get (by decide) + +example : aliasRecNormalization.accepted = true := rfl +example : (normalizedChecked? aliasRecRawDecl aliasRecViewDecl).isSome = true := rfl +example : aliasRecBlock.checked.type = aliasRecViewType := rfl +example : ∃ raw, + aliasRecRawDecl.types = [raw] ∧ + raw.name = aliasRecBlock.checked.type.name ∧ + raw.uvars = aliasRecBlock.checked.type.uvars ∧ + List.Forall₂ CtorHeaderEq raw.ctors aliasRecBlock.checked.type.ctors := + aliasRecBlock.source_anatomy +example : aliasRecViewChecked.constructors[0].fields = [.const ``AliasRec []] := rfl +example : aliasRecViewChecked.constructors[0].recursive.length = 1 := rfl +example : aliasRecViewChecked.constructors[0].recursive[0].binders = [] := rfl +example : aliasRecGenerationChecked.block.ctorPairs[0].rawFields 0 = + [aliasRecRawField] := rfl +example : (ctorFields aliasRecGenerationChecked.minorTypes[0])[0]? = + some aliasRecRawField := rfl +example : aliasRecGenerationChecked.recursor = + vconst(type_of% @AliasRec.rec) := rfl +example : aliasRecGenerationChecked.generatedRules[0]? = + some (vdefeq(motive mk a => + @AliasRec.rec motive mk (@AliasRec.mk a) ≡ + mk a (@AliasRec.rec motive mk a))) := rfl + +def recAliasDefEq : VDefEq := + vdefeq(@RecAlias ≡ fun (α : Sort u) => α) + +def recAliasConstEnv : VEnv := + (VEnv.empty.addConst ``RecAlias (vconst(type_of% @RecAlias))).get (by decide) + +def recAliasEnv : VEnv := recAliasConstEnv.addDefEq recAliasDefEq + +theorem recAliasConstant_wf : + (vconst(type_of% @RecAlias) : VConstant).WF VEnv.empty := by + apply VEnv.IsType.forallE + · exact ⟨_, VEnv.HasType.sort (by decide)⟩ + · exact ⟨_, VEnv.HasType.sort (by decide)⟩ + +theorem recAliasConstEnv_ordered : + recAliasConstEnv.Ordered := by + apply VEnv.Ordered.const VEnv.Ordered.empty + (ci := vconst(type_of% @RecAlias)) + · exact recAliasConstant_wf + · rfl + +theorem recAliasEnv_ordered : + recAliasEnv.Ordered := by + apply VEnv.Ordered.defeq recAliasConstEnv_ordered + constructor + · exact VEnv.HasType.const0 rfl + (recAliasConstant_wf.mono + (VEnv.addConst_le (by rfl : + VEnv.empty.addConst ``RecAlias + (vconst(type_of% @RecAlias)) = + some recAliasConstEnv))) + · exact VEnv.HasType.lam + (VEnv.HasType.sort (by decide)) + (VEnv.HasType.bvar .zero) + +/-- The raw aliased field and the normalized recursive target are +definitionally equal after the raw family constant has been inserted. -/ +theorem aliasRecField_defeq {envT : VEnv} + (hadd : recAliasEnv.addConst ``AliasRec aliasRecRawType.toVConstant = + some envT) : + envT.IsDefEq 0 [] aliasRecRawField (.const ``AliasRec []) + (.sort (.succ .zero)) := by + have hlookup : + envT.constants ``AliasRec = some aliasRecRawType.toVConstant := + VEnv.addConst_self hadd + have hfamily : envT.HasType 0 [] (.const ``AliasRec []) + (.sort (.succ .zero)) := + .constDF hlookup (fun _ h => nomatch h) (fun _ h => nomatch h) rfl .nil + have hdelta : envT.IsDefEq 0 [] + (.const ``RecAlias [.succ .zero]) + (.lam (.sort (.succ .zero)) (.bvar 0)) + (.forallE (.sort (.succ .zero)) (.sort (.succ .zero))) := by + apply VEnv.IsDefEq.extra + (df := recAliasDefEq) (ls := [.succ .zero]) (Γ := []) + · exact (VEnv.addConst_le hadd).defeqs (by + simp [recAliasEnv, VEnv.addDefEq]) + · intro l hl + simp only [List.mem_singleton] at hl + subst l + decide + · rfl + have happ := VEnv.IsDefEq.appDF hdelta hfamily + have hbeta : envT.IsDefEq 0 [] + (.app (.lam (.sort (.succ .zero)) (.bvar 0)) (.const ``AliasRec [])) + (.const ``AliasRec []) (.sort (.succ .zero)) := + .beta (.bvar .zero) hfamily + exact happ.trans hbeta + +/-- The raw family result remains well typed under the raw aliased field +binder. -/ +theorem aliasRecResult_hasType {envT : VEnv} + (hadd : recAliasEnv.addConst ``AliasRec aliasRecRawType.toVConstant = + some envT) : + envT.HasType 0 [aliasRecRawField] (.const ``AliasRec []) + (.sort (.succ .zero)) := + .constDF (VEnv.addConst_self hadd) (fun _ h => nomatch h) + (fun _ h => nomatch h) rfl .nil + +/-- Field WHNF is also justified semantically. The constructor comparison is +staged after insertion of the raw `AliasRec` family constant, and derives +`RecAlias AliasRec ≡ AliasRec` by delta, application congruence, and beta. +-/ +theorem aliasRecNormalization_wf : + aliasRecNormalization.WF recAliasEnv := by + refine ⟨aliasRecRawType, aliasRecViewType, rfl, rfl, ?_, ?_⟩ + · exact ⟨_, by type_tac⟩ + · intro envT hadd + exact .cons + ⟨_, .forallEDF (aliasRecField_defeq hadd) + (aliasRecResult_hasType hadd)⟩ + .nil + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecNormalization_wf [propext, Quot.sound] + +/-- The normalized direct-recursive view satisfies the semantic declaration +contract independently of the raw aliased field syntax. -/ +theorem aliasRecViewDecl_wf : aliasRecViewDecl.WF recAliasEnv := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = aliasRecViewType := + List.mem_singleton.1 (by simpa [aliasRecViewDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · trivial + · intro c hc + have hc' : c = aliasRecViewCtor := + List.mem_singleton.1 (by simpa [aliasRecViewType] using hc) + subst c + refine ⟨?_, .nil⟩ + exact ⟨.inl rfl, fun _ => .nil, trivial⟩ + +/-- Recursive-field recognition is certified on the normalized view while the +paired block continues to retain the raw aliased constructor syntax. -/ +theorem aliasRecBlock_wf : aliasRecBlock.WF recAliasEnv := by + refine ⟨aliasRecNormalization_wf, ?_⟩ + change aliasRecViewChecked.WF recAliasEnv + exact aliasRecViewChecked.wf_of_decl aliasRecViewDecl_wf + +theorem aliasRecGenerationChecked_wf : + aliasRecGenerationChecked.WF recAliasEnv := by + refine { + blockWF := aliasRecBlock_wf + familyTel := by trivial + familyResult := by + exact .sortDF (by decide) (by decide) rfl + ctors := ?_ } + intro envT hadd ctor hctor + change recAliasEnv.addConst ``AliasRec aliasRecRawType.toVConstant = + some envT at hadd + change ctor ∈ + [⟨aliasRecRawType.ctors[0], aliasRecViewChecked.constructors[0]⟩] + at hctor + obtain rfl := List.mem_singleton.1 hctor + have hfield := aliasRecField_defeq hadd + have hresult := aliasRecResult_hasType hadd + exact { + declaredTel := ⟨⟨_, hfield⟩, trivial⟩ + declaredResult := hresult + emittedTel := ⟨⟨_, hfield⟩, trivial⟩ + emittedResult := hresult } + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecBlock_wf [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecGenerationChecked_wf [propext, Quot.sound] + +/-- The recursive-field alias case preserves the raw aliased constructor +binder while using the normalized view to generate recursion artifacts. -/ +def aliasRecFinalEnv : VEnv := + (recAliasEnv.addInductGeneration + aliasRecGenerationChecked).get (by decide) + +theorem aliasRec_addInductGeneration : + recAliasEnv.addInductGeneration aliasRecGenerationChecked = + some aliasRecFinalEnv := rfl + +theorem aliasRecFinalEnv_trace : + Nonempty (VEnv.AddInductGenerationTrace + recAliasEnv aliasRecFinalEnv aliasRecGenerationChecked) := + VEnv.addInductGeneration_trace aliasRec_addInductGeneration + +theorem aliasRecFinalEnv_le : + recAliasEnv ≤ aliasRecFinalEnv := by + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.le + +theorem aliasRecFinalEnv_family_fresh : + recAliasEnv.constants ``AliasRec = none := by + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.family_fresh + +theorem aliasRecFinalEnv_family_lookup : + aliasRecFinalEnv.constants ``AliasRec = + some aliasRecRawType.toVConstant := by + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.family_lookup + +theorem aliasRecFinalEnv_ctor_fresh : + ∀ c ∈ aliasRecRawType.ctors, + recAliasEnv.constants c.name = none := by + intro c hc + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.ctor_fresh hc + +theorem aliasRecFinalEnv_ctor_lookup : + ∀ c ∈ aliasRecRawType.ctors, + aliasRecFinalEnv.constants c.name = + some c.toVConstant := by + intro c hc + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.ctor_lookup hc + +theorem aliasRecFinalEnv_rec_fresh : + recAliasEnv.constants ``AliasRec.rec = none := by + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.rec_fresh + +theorem aliasRecFinalEnv_rec_lookup : + aliasRecFinalEnv.constants ``AliasRec.rec = + some (vconst(type_of% @AliasRec.rec)) := by + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.rec_lookup + +theorem aliasRecFinalEnv_rule_mem : + ∀ df ∈ aliasRecGenerationChecked.generatedRules, + aliasRecFinalEnv.defeqs df := by + intro df hdf + rcases aliasRecFinalEnv_trace with ⟨H⟩ + exact H.rule_mem hdf + +theorem aliasRecFinalEnv_iota_mem : + aliasRecFinalEnv.defeqs + (vdefeq(motive mk a => + @AliasRec.rec motive mk (@AliasRec.mk a) ≡ + mk a (@AliasRec.rec motive mk a))) := by + apply aliasRecFinalEnv_rule_mem + exact .head _ + +theorem aliasRecFinalEnv_ordered : + aliasRecFinalEnv.Ordered := + VEnv.addInductGeneration_WF + recAliasEnv_ordered + aliasRecGenerationChecked_wf + aliasRec_addInductGeneration + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecFinalEnv_trace [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecFinalEnv_family_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecFinalEnv_ctor_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecFinalEnv_rec_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecFinalEnv_iota_mem [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.aliasRecFinalEnv_ordered [propext, Classical.choice, Quot.sound] + +/-! ## Normalization differential matrix + +The isolated `AliasFormer` and `AliasRec` fixtures above establish that Lean +retains reducible aliases at family results and direct recursive targets. The +single indexed declaration below covers every remaining normalization +position in one real kernel payload: parameter and index domains, ordinary +fields, direct recursion, recursion hidden behind a Pi-producing alias, and +beta/let redexes retained in alias definitions. Its view is deliberately +written out so changes to either Lean's stored metadata or the Theory +normalizer fail by computation. +-/ + +abbrev MatrixBetaAlias (alpha : Sort u) := + (fun type : Sort u => type) alpha + +abbrev MatrixLetAlias (alpha : Sort u) := + let type := alpha + type + +abbrev MatrixPiAlias (alpha : Sort u) := (proof : Prop) → alpha + +abbrev MatrixIndexAlias + (index : TypeFamilyAlias) : TypeFamilyAlias := index + +inductive NormalizationMatrix (alpha : TypeFamilyAlias) : + TypeFamilyAlias → Type 1 where + | mk (index : TypeFamilyAlias) + (ordinary : RecAlias Prop) + (beta : MatrixBetaAlias Prop) + (letBound : MatrixLetAlias Prop) + (direct : RecAlias + (NormalizationMatrix alpha (MatrixIndexAlias index))) + (piHidden : MatrixPiAlias + (NormalizationMatrix alpha (MatrixIndexAlias index))) + (betaRecursive : MatrixBetaAlias + (NormalizationMatrix alpha (MatrixIndexAlias index))) + (letRecursive : MatrixLetAlias + (NormalizationMatrix alpha (MatrixIndexAlias index))) : + NormalizationMatrix alpha (MatrixIndexAlias index) + +def normalizationMatrixRawType : VInductiveType where + name := ``NormalizationMatrix + uvars := 0 + type := vconst(type_of% @NormalizationMatrix).type + ctors := [⟨vconst(type_of% @NormalizationMatrix.mk), + ``NormalizationMatrix.mk⟩] + +def normalizationMatrixRawDecl : VInductDecl := + ⟨0, 1, [normalizationMatrixRawType]⟩ + +def normalizationMatrixTarget (alpha index : VExpr) : VExpr := + (VExpr.const ``NormalizationMatrix []).app alpha |>.app + ((VExpr.const ``MatrixIndexAlias []).app index) + +def normalizationMatrixViewCtorType : VExpr := + .forallE (.sort (.succ .zero)) <| + .forallE (.sort (.succ .zero)) <| + .forallE (.sort .zero) <| + .forallE (.sort .zero) <| + .forallE (.sort .zero) <| + .forallE (normalizationMatrixTarget (.bvar 4) (.bvar 3)) <| + .forallE (.forallE (.sort .zero) + (normalizationMatrixTarget (.bvar 6) (.bvar 5))) <| + .forallE (normalizationMatrixTarget (.bvar 6) (.bvar 5)) <| + .forallE (normalizationMatrixTarget (.bvar 7) (.bvar 6)) <| + normalizationMatrixTarget (.bvar 8) (.bvar 7) + +def normalizationMatrixViewCtor : VConstVal := + { normalizationMatrixRawType.ctors[0] with + type := normalizationMatrixViewCtorType } + +def normalizationMatrixViewType : VInductiveType := + { normalizationMatrixRawType with + type := .forallE (.sort (.succ .zero)) + (.forallE (.sort (.succ .zero)) + (.sort (.succ (.succ .zero)))) + ctors := [normalizationMatrixViewCtor] } + +def normalizationMatrixViewDecl : VInductDecl := + ⟨0, 1, [normalizationMatrixViewType]⟩ + +example : normalizationMatrixRawType.type = + (VExpr.const ``TypeFamilyAlias []).forallE + ((VExpr.const ``TypeFamilyAlias []).forallE + (VExpr.sort (.succ (.succ .zero)))) := rfl + +example : normalizationMatrixRawType.ctors[0].type = + vconst(type_of% @NormalizationMatrix.mk).type := rfl + +example : normalizationMatrixRawDecl.checked? = none := rfl +example : normalizationMatrixViewDecl.checked?.isSome = true := rfl +example : normalizationShape normalizationMatrixRawDecl + normalizationMatrixViewDecl = true := rfl + +def normalizationMatrixNormalization : + Normalization normalizationMatrixRawDecl where + view := normalizationMatrixViewDecl + shape_eq := rfl + +def normalizationMatrixViewChecked : + normalizationMatrixViewDecl.Checked := + normalizationMatrixViewDecl.checked?.get (by decide) + +def normalizationMatrixBlock : + NormalizedChecked normalizationMatrixRawDecl := + normalizationMatrixNormalization.check?.get (by decide) + +def normalizationMatrixGenerationChecked : + GenerationChecked normalizationMatrixRawDecl := + normalizationMatrixBlock.generation?.get (by decide) + +example : normalizationMatrixNormalization.accepted = true := rfl +example : (normalizedChecked? normalizationMatrixRawDecl + normalizationMatrixViewDecl).isSome = true := rfl +example : normalizationMatrixBlock.checked.type = + normalizationMatrixViewType := rfl +example : normalizationMatrixViewChecked.params = + [.sort (.succ .zero)] := rfl +example : normalizationMatrixViewChecked.indices = + [.sort (.succ .zero)] := rfl +example : normalizationMatrixViewChecked.constructors[0].fields.length = 8 := + rfl +example : normalizationMatrixViewChecked.constructors[0].recursive.length = 4 := + rfl +example : normalizationMatrixViewChecked.constructors[0].recursive.map + (fun position => (position.fieldIndex, position.binders.length)) = + [(4, 0), (5, 1), (6, 0), (7, 0)] := rfl +example : normalizationMatrixGenerationChecked.recursor = + vconst(type_of% @NormalizationMatrix.rec) := rfl +example : normalizationMatrixGenerationChecked.generatedRules[0]? = + some (vdefeq(alpha motive mk index ordinary beta letBound direct + piHidden betaRecursive letRecursive => + @NormalizationMatrix.rec alpha motive mk (MatrixIndexAlias index) + (@NormalizationMatrix.mk alpha index ordinary beta letBound direct + piHidden betaRecursive letRecursive) ≡ + mk index ordinary beta letBound direct piHidden betaRecursive + letRecursive + (@NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) direct) + (fun proof => @NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) (piHidden proof)) + (@NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) betaRecursive) + (@NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) letRecursive))) := rfl +example : normalizationMatrixGenerationChecked.generatedRules.length = 1 := rfl + +/-! The semantic pre-environment contains the exact reducible definitions +whose WHNFs justify the normalized descriptor. Each abbreviation is added +as a constant followed by its delta equation so the final transaction uses +the same staged environment discipline as ordinary declarations. -/ + +def normalizationMatrixRecAliasConstEnv : VEnv := + (typeFamilyAliasEnv.addConst ``RecAlias + (vconst(type_of% @RecAlias))).get (by decide) + +def normalizationMatrixRecAliasEnv : VEnv := + normalizationMatrixRecAliasConstEnv.addDefEq recAliasDefEq + +theorem normalizationMatrixRecAliasEnv_ordered : + normalizationMatrixRecAliasEnv.Ordered := by + apply VEnv.Ordered.defeq + · apply VEnv.Ordered.const (n := ``RecAlias) + (ci := vconst(type_of% @RecAlias)) + (env' := normalizationMatrixRecAliasConstEnv) + typeFamilyAliasEnv_ordered + · exact ⟨_, by type_tac⟩ + · rfl + · have hlookup : normalizationMatrixRecAliasConstEnv.constants + ``RecAlias = some (vconst(type_of% @RecAlias)) := rfl + constructor <;> type_tac + +def matrixBetaAliasDefEq : VDefEq := + vdefeq(@MatrixBetaAlias ≡ fun (alpha : Sort u) => + (fun type : Sort u => type) alpha) + +def normalizationMatrixBetaAliasConstEnv : VEnv := + (normalizationMatrixRecAliasEnv.addConst ``MatrixBetaAlias + (vconst(type_of% @MatrixBetaAlias))).get (by decide) + +def normalizationMatrixBetaAliasEnv : VEnv := + normalizationMatrixBetaAliasConstEnv.addDefEq matrixBetaAliasDefEq + +theorem normalizationMatrixBetaAliasEnv_ordered : + normalizationMatrixBetaAliasEnv.Ordered := by + apply VEnv.Ordered.defeq + · apply VEnv.Ordered.const (n := ``MatrixBetaAlias) + (ci := vconst(type_of% @MatrixBetaAlias)) + (env' := normalizationMatrixBetaAliasConstEnv) + normalizationMatrixRecAliasEnv_ordered + · exact ⟨_, by type_tac⟩ + · rfl + · have hlookup : normalizationMatrixBetaAliasConstEnv.constants + ``MatrixBetaAlias = some (vconst(type_of% @MatrixBetaAlias)) := rfl + constructor <;> type_tac + +def matrixLetAliasDefEq : VDefEq := + vdefeq(@MatrixLetAlias ≡ fun (alpha : Sort u) => + let type := alpha + type) + +def normalizationMatrixLetAliasConstEnv : VEnv := + (normalizationMatrixBetaAliasEnv.addConst ``MatrixLetAlias + (vconst(type_of% @MatrixLetAlias))).get (by decide) + +def normalizationMatrixLetAliasEnv : VEnv := + normalizationMatrixLetAliasConstEnv.addDefEq matrixLetAliasDefEq + +theorem normalizationMatrixLetAliasEnv_ordered : + normalizationMatrixLetAliasEnv.Ordered := by + apply VEnv.Ordered.defeq + · apply VEnv.Ordered.const (n := ``MatrixLetAlias) + (ci := vconst(type_of% @MatrixLetAlias)) + (env' := normalizationMatrixLetAliasConstEnv) + normalizationMatrixBetaAliasEnv_ordered + · exact ⟨_, by type_tac⟩ + · rfl + · have hlookup : normalizationMatrixLetAliasConstEnv.constants + ``MatrixLetAlias = some (vconst(type_of% @MatrixLetAlias)) := rfl + constructor <;> type_tac + +def matrixPiAliasDefEq : VDefEq := + vdefeq(@MatrixPiAlias ≡ fun (alpha : Sort u) => + (proof : Prop) → alpha) + +def normalizationMatrixPiAliasConstEnv : VEnv := + (normalizationMatrixLetAliasEnv.addConst ``MatrixPiAlias + (vconst(type_of% @MatrixPiAlias))).get (by decide) + +def normalizationMatrixPiAliasEnv : VEnv := + normalizationMatrixPiAliasConstEnv.addDefEq matrixPiAliasDefEq + +theorem normalizationMatrixPiAliasEnv_ordered : + normalizationMatrixPiAliasEnv.Ordered := by + apply VEnv.Ordered.defeq + · apply VEnv.Ordered.const (n := ``MatrixPiAlias) + (ci := vconst(type_of% @MatrixPiAlias)) + (env' := normalizationMatrixPiAliasConstEnv) + normalizationMatrixLetAliasEnv_ordered + · exact ⟨_, by type_tac⟩ + · rfl + · have hlookup : normalizationMatrixPiAliasConstEnv.constants + ``MatrixPiAlias = some (vconst(type_of% @MatrixPiAlias)) := rfl + constructor + · type_tac + · apply VEnv.HasType.lam + · exact VEnv.HasType.sort (by decide) + · apply VEnv.IsDefEq.defeq + (VEnv.IsDefEq.sortDF + (l := .imax (.succ .zero) (.param 0)) + (l' := .param 0) (by decide) (by decide) (by + rw [VLevel.equiv_def] + intro ls + simp only [VLevel.eval, Nat.zero_add] + let n := ls.getD 0 0 + change Lean.Nat.imax 1 n = n + by_cases h : n = 0 + · simp [Lean.Nat.imax, h] + · have hn : 1 ≤ n := Nat.one_le_iff_ne_zero.mpr h + simp [Lean.Nat.imax, h, Nat.max_eq_right hn])) + exact VEnv.HasType.forallE + (VEnv.HasType.sort (by decide)) + (VEnv.HasType.bvar (.succ .zero)) + +def matrixIndexAliasDefEq : VDefEq := + vdefeq(MatrixIndexAlias ≡ fun index : TypeFamilyAlias => index) + +def normalizationMatrixIndexAliasConstEnv : VEnv := + (normalizationMatrixPiAliasEnv.addConst ``MatrixIndexAlias + (vconst(type_of% @MatrixIndexAlias))).get (by decide) + +def normalizationMatrixAliasEnv : VEnv := + normalizationMatrixIndexAliasConstEnv.addDefEq matrixIndexAliasDefEq + +theorem normalizationMatrixAliasEnv_ordered : + normalizationMatrixAliasEnv.Ordered := by + apply VEnv.Ordered.defeq + · apply VEnv.Ordered.const (n := ``MatrixIndexAlias) + (ci := vconst(type_of% @MatrixIndexAlias)) + (env' := normalizationMatrixIndexAliasConstEnv) + normalizationMatrixPiAliasEnv_ordered + · have hfamily : normalizationMatrixPiAliasEnv.constants + ``TypeFamilyAlias = some (vconst(type_of% @TypeFamilyAlias)) := rfl + exact ⟨_, by type_tac⟩ + · rfl + · have hfamily : normalizationMatrixIndexAliasConstEnv.constants + ``TypeFamilyAlias = some (vconst(type_of% @TypeFamilyAlias)) := rfl + have hlookup : normalizationMatrixIndexAliasConstEnv.constants + ``MatrixIndexAlias = some (vconst(type_of% @MatrixIndexAlias)) := rfl + constructor <;> type_tac + +theorem normalizationMatrixRecAliasEnv_le_betaAliasEnv : + normalizationMatrixRecAliasEnv ≤ normalizationMatrixBetaAliasEnv := + (VEnv.addConst_le (by rfl : normalizationMatrixRecAliasEnv.addConst + ``MatrixBetaAlias (vconst(type_of% @MatrixBetaAlias)) = + some normalizationMatrixBetaAliasConstEnv)).trans VEnv.addDefEq_le + +theorem normalizationMatrixBetaAliasEnv_le_letAliasEnv : + normalizationMatrixBetaAliasEnv ≤ normalizationMatrixLetAliasEnv := + (VEnv.addConst_le (by rfl : normalizationMatrixBetaAliasEnv.addConst + ``MatrixLetAlias (vconst(type_of% @MatrixLetAlias)) = + some normalizationMatrixLetAliasConstEnv)).trans VEnv.addDefEq_le + +theorem normalizationMatrixLetAliasEnv_le_piAliasEnv : + normalizationMatrixLetAliasEnv ≤ normalizationMatrixPiAliasEnv := + (VEnv.addConst_le (by rfl : normalizationMatrixLetAliasEnv.addConst + ``MatrixPiAlias (vconst(type_of% @MatrixPiAlias)) = + some normalizationMatrixPiAliasConstEnv)).trans VEnv.addDefEq_le + +theorem normalizationMatrixPiAliasEnv_le_aliasEnv : + normalizationMatrixPiAliasEnv ≤ normalizationMatrixAliasEnv := + (VEnv.addConst_le (by rfl : normalizationMatrixPiAliasEnv.addConst + ``MatrixIndexAlias (vconst(type_of% @MatrixIndexAlias)) = + some normalizationMatrixIndexAliasConstEnv)).trans VEnv.addDefEq_le + +theorem normalizationMatrixRecAliasEnv_le_aliasEnv : + normalizationMatrixRecAliasEnv ≤ normalizationMatrixAliasEnv := + normalizationMatrixRecAliasEnv_le_betaAliasEnv.trans <| + normalizationMatrixBetaAliasEnv_le_letAliasEnv.trans <| + normalizationMatrixLetAliasEnv_le_piAliasEnv.trans + normalizationMatrixPiAliasEnv_le_aliasEnv + +theorem typeFamilyAliasEnv_le_normalizationMatrixAliasEnv : + typeFamilyAliasEnv ≤ normalizationMatrixAliasEnv := by + exact ((VEnv.addConst_le (by rfl : typeFamilyAliasEnv.addConst ``RecAlias + (vconst(type_of% @RecAlias)) = + some normalizationMatrixRecAliasConstEnv)).trans VEnv.addDefEq_le).trans + normalizationMatrixRecAliasEnv_le_aliasEnv + +theorem normalizationMatrix_typeFamilyAliasDefEq_mem : + normalizationMatrixAliasEnv.defeqs typeFamilyAliasDefEq := + typeFamilyAliasEnv_le_normalizationMatrixAliasEnv.defeqs + VEnv.addDefEq_self + +theorem normalizationMatrix_recAliasDefEq_mem : + normalizationMatrixAliasEnv.defeqs recAliasDefEq := + normalizationMatrixRecAliasEnv_le_aliasEnv.defeqs VEnv.addDefEq_self + +theorem normalizationMatrix_betaAliasDefEq_mem : + normalizationMatrixAliasEnv.defeqs matrixBetaAliasDefEq := + (normalizationMatrixBetaAliasEnv_le_letAliasEnv.trans <| + normalizationMatrixLetAliasEnv_le_piAliasEnv.trans + normalizationMatrixPiAliasEnv_le_aliasEnv).defeqs VEnv.addDefEq_self + +theorem normalizationMatrix_letAliasDefEq_mem : + normalizationMatrixAliasEnv.defeqs matrixLetAliasDefEq := + (normalizationMatrixLetAliasEnv_le_piAliasEnv.trans + normalizationMatrixPiAliasEnv_le_aliasEnv).defeqs VEnv.addDefEq_self + +theorem normalizationMatrix_piAliasDefEq_mem : + normalizationMatrixAliasEnv.defeqs matrixPiAliasDefEq := + normalizationMatrixPiAliasEnv_le_aliasEnv.defeqs VEnv.addDefEq_self + +theorem normalizationMatrixTypeFamily_defeq {env : VEnv} {U : Nat} + {Γ : List VExpr} (henv : normalizationMatrixAliasEnv ≤ env) : + env.IsDefEq U Γ (VExpr.const ``TypeFamilyAlias []) + (VExpr.sort (.succ .zero)) + (VExpr.sort (.succ (.succ .zero))) := by + exact .extra (df := typeFamilyAliasDefEq) (ls := []) + (henv.defeqs normalizationMatrix_typeFamilyAliasDefEq_mem) + (fun _ h => nomatch h) rfl + +theorem normalizationMatrixRecAlias_app_defeq {env : VEnv} {U : Nat} + {Γ : List VExpr} {u : VLevel} {A : VExpr} (hu : u.WF U) + (henv : normalizationMatrixAliasEnv ≤ env) + (hA : env.HasType U Γ A (VExpr.sort u)) : + env.IsDefEq U Γ ((VExpr.const ``RecAlias [u]).app A) A + (VExpr.sort u) := by + have hdelta : env.IsDefEq U Γ (VExpr.const ``RecAlias [u]) + (VExpr.lam (VExpr.sort u) (VExpr.bvar 0)) + (VExpr.forallE (VExpr.sort u) (VExpr.sort u)) := + .extra (df := recAliasDefEq) (ls := [u]) + (henv.defeqs normalizationMatrix_recAliasDefEq_mem) + (by simpa using hu) rfl + have hbeta := VEnv.IsDefEq.beta (VEnv.IsDefEq.bvar .zero) hA + exact (VEnv.IsDefEq.appDF hdelta hA).trans (by + simpa [VExpr.inst, VExpr.instVar, VExpr.liftN] using hbeta) + +theorem normalizationMatrixBetaAlias_app_defeq {env : VEnv} {U : Nat} + {Γ : List VExpr} {u : VLevel} {A : VExpr} (hu : u.WF U) + (henv : normalizationMatrixAliasEnv ≤ env) + (hA : env.HasType U Γ A (VExpr.sort u)) : + env.IsDefEq U Γ ((VExpr.const ``MatrixBetaAlias [u]).app A) A + (VExpr.sort u) := by + have hdelta : env.IsDefEq U Γ (VExpr.const ``MatrixBetaAlias [u]) + (VExpr.lam (VExpr.sort u) + ((VExpr.lam (VExpr.sort u) (VExpr.bvar 0)).app (VExpr.bvar 0))) + (VExpr.forallE (VExpr.sort u) (VExpr.sort u)) := + .extra (df := matrixBetaAliasDefEq) (ls := [u]) + (henv.defeqs normalizationMatrix_betaAliasDefEq_mem) + (by simpa using hu) rfl + have hbody : env.HasType U (VExpr.sort u :: Γ) + ((VExpr.lam (VExpr.sort u) (VExpr.bvar 0)).app (VExpr.bvar 0)) + (VExpr.sort u) := + VEnv.HasType.app + (VEnv.HasType.lam (VEnv.HasType.sort hu) (VEnv.HasType.bvar .zero)) + (VEnv.HasType.bvar .zero) + have houterBeta := VEnv.IsDefEq.beta hbody hA + have houter := (VEnv.IsDefEq.appDF hdelta hA).trans (by + simpa [VExpr.inst, VExpr.instVar, VExpr.liftN] using houterBeta) + have hinnerBeta := VEnv.IsDefEq.beta (VEnv.IsDefEq.bvar .zero) hA + exact houter.trans (by + simpa [VExpr.inst, VExpr.instVar, VExpr.liftN] using hinnerBeta) + +theorem normalizationMatrixLetAlias_app_defeq {env : VEnv} {U : Nat} + {Γ : List VExpr} {u : VLevel} {A : VExpr} (hu : u.WF U) + (henv : normalizationMatrixAliasEnv ≤ env) + (hA : env.HasType U Γ A (VExpr.sort u)) : + env.IsDefEq U Γ ((VExpr.const ``MatrixLetAlias [u]).app A) A + (VExpr.sort u) := by + have hdelta : env.IsDefEq U Γ (VExpr.const ``MatrixLetAlias [u]) + (VExpr.lam (VExpr.sort u) (VExpr.bvar 0)) + (VExpr.forallE (VExpr.sort u) (VExpr.sort u)) := + .extra (df := matrixLetAliasDefEq) (ls := [u]) + (henv.defeqs normalizationMatrix_letAliasDefEq_mem) + (by simpa using hu) rfl + have hbeta := VEnv.IsDefEq.beta (VEnv.IsDefEq.bvar .zero) hA + exact (VEnv.IsDefEq.appDF hdelta hA).trans (by + simpa [VExpr.inst, VExpr.instVar, VExpr.liftN] using hbeta) + +private theorem normalizationMatrix_one_imax_equiv (u : VLevel) : + .imax (.succ .zero) u ≈ u := by + rw [VLevel.equiv_def] + intro ls + simp only [VLevel.eval, Nat.zero_add] + let n := u.eval ls + change Lean.Nat.imax 1 n = n + by_cases h : n = 0 + · simp [Lean.Nat.imax, h] + · have hn : 1 ≤ n := Nat.one_le_iff_ne_zero.mpr h + simp [Lean.Nat.imax, h, Nat.max_eq_right hn] + +theorem normalizationMatrixPiAlias_app_defeq {env : VEnv} {U : Nat} + {Γ : List VExpr} {u : VLevel} {A : VExpr} (hu : u.WF U) + (henv : normalizationMatrixAliasEnv ≤ env) + (hA : env.HasType U Γ A (VExpr.sort u)) : + env.IsDefEq U Γ ((VExpr.const ``MatrixPiAlias [u]).app A) + (VExpr.forallE (VExpr.sort .zero) A.lift) (VExpr.sort u) := by + have hdelta : env.IsDefEq U Γ (VExpr.const ``MatrixPiAlias [u]) + (VExpr.lam (VExpr.sort u) + (VExpr.forallE (VExpr.sort .zero) (VExpr.bvar 1))) + (VExpr.forallE (VExpr.sort u) (VExpr.sort u)) := + .extra (df := matrixPiAliasDefEq) (ls := [u]) + (henv.defeqs normalizationMatrix_piAliasDefEq_mem) + (by simpa using hu) rfl + have hbody : env.HasType U (VExpr.sort u :: Γ) + (VExpr.forallE (VExpr.sort .zero) (VExpr.bvar 1)) + (VExpr.sort u) := by + apply VEnv.IsDefEq.defeq + (VEnv.IsDefEq.sortDF + (l := .imax (.succ .zero) u) (l' := u) + ⟨trivial, hu⟩ hu (normalizationMatrix_one_imax_equiv u)) + exact VEnv.HasType.forallE (VEnv.HasType.sort (by trivial)) + (VEnv.HasType.bvar (.succ .zero)) + have hbeta := VEnv.IsDefEq.beta hbody hA + exact (VEnv.IsDefEq.appDF hdelta hA).trans (by + simpa [VExpr.inst, VExpr.instVar, VExpr.liftN] using hbeta) + +theorem normalizationMatrixIndexAlias_app_hasType {env : VEnv} {U : Nat} + {Γ : List VExpr} {index : VExpr} + (henv : normalizationMatrixAliasEnv ≤ env) + (hindex : env.HasType U Γ index (VExpr.sort (.succ .zero))) : + env.HasType U Γ ((VExpr.const ``MatrixIndexAlias []).app index) + (VExpr.sort (.succ .zero)) := by + have hfn : env.HasType U Γ (VExpr.const ``MatrixIndexAlias []) + ((VExpr.const ``TypeFamilyAlias []).forallE + (VExpr.const ``TypeFamilyAlias [])) := + .constDF (henv.constants (by rfl : normalizationMatrixAliasEnv.constants + ``MatrixIndexAlias = some (vconst(type_of% @MatrixIndexAlias)))) + (fun _ h => nomatch h) (fun _ h => nomatch h) rfl .nil + have hindexRaw := (normalizationMatrixTypeFamily_defeq henv).defeq' hindex + exact (normalizationMatrixTypeFamily_defeq henv).defeq + (VEnv.HasType.app hfn hindexRaw) + +theorem normalizationMatrixTarget_hasType {env : VEnv} {U : Nat} + {Γ : List VExpr} {alpha index : VExpr} + (henv : normalizationMatrixAliasEnv ≤ env) + (hfamily : env.constants ``NormalizationMatrix = + some normalizationMatrixRawType.toVConstant) + (halpha : env.HasType U Γ alpha (VExpr.const ``TypeFamilyAlias [])) + (hindex : env.HasType U Γ index (VExpr.const ``TypeFamilyAlias [])) : + env.HasType U Γ (normalizationMatrixTarget alpha index) + (VExpr.sort (.succ (.succ .zero))) := by + have hfn : env.HasType U Γ (VExpr.const ``NormalizationMatrix []) + (VExpr.forallE (VExpr.const ``TypeFamilyAlias []) + (VExpr.forallE (VExpr.const ``TypeFamilyAlias []) + (VExpr.sort (.succ (.succ .zero))))) := + .constDF hfamily (fun _ h => nomatch h) (fun _ h => nomatch h) + rfl .nil + have hindexFn : env.HasType U Γ (VExpr.const ``MatrixIndexAlias []) + ((VExpr.const ``TypeFamilyAlias []).forallE + (VExpr.const ``TypeFamilyAlias [])) := + .constDF (henv.constants (by rfl : normalizationMatrixAliasEnv.constants + ``MatrixIndexAlias = some (vconst(type_of% @MatrixIndexAlias)))) + (fun _ h => nomatch h) (fun _ h => nomatch h) rfl .nil + exact VEnv.HasType.app (VEnv.HasType.app hfn halpha) + (VEnv.HasType.app hindexFn hindex) + +theorem normalizationMatrixNormalization_wf : + normalizationMatrixNormalization.WF normalizationMatrixAliasEnv := by + refine ⟨normalizationMatrixRawType, normalizationMatrixViewType, + rfl, rfl, ?_, ?_⟩ + · refine ⟨VExpr.sort (.imax (.succ (.succ .zero)) + (.imax (.succ (.succ .zero)) + (.succ (.succ (.succ .zero))))), ?_⟩ + change normalizationMatrixAliasEnv.IsDefEq 0 [] + ((VExpr.const ``TypeFamilyAlias []).forallE + ((VExpr.const ``TypeFamilyAlias []).forallE + (VExpr.sort (.succ (.succ .zero))))) + ((VExpr.sort (.succ .zero)).forallE + ((VExpr.sort (.succ .zero)).forallE + (VExpr.sort (.succ (.succ .zero))))) + (VExpr.sort (.imax (.succ (.succ .zero)) + (.imax (.succ (.succ .zero)) + (.succ (.succ (.succ .zero)))))) + apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixTypeFamily_defeq .rfl + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixTypeFamily_defeq .rfl + · exact VEnv.IsDefEq.sortDF (by decide) (by decide) rfl + · intro envT hadd + have henv : normalizationMatrixAliasEnv ≤ envT := + VEnv.addConst_le hadd + have htypeFamily : envT.constants ``TypeFamilyAlias = + some (vconst(type_of% @TypeFamilyAlias)) := + henv.constants (by rfl) + have hrecAlias : envT.constants ``RecAlias = + some (vconst(type_of% @RecAlias)) := + henv.constants (by rfl) + have hbetaAlias : envT.constants ``MatrixBetaAlias = + some (vconst(type_of% @MatrixBetaAlias)) := + henv.constants (by rfl) + have hletAlias : envT.constants ``MatrixLetAlias = + some (vconst(type_of% @MatrixLetAlias)) := + henv.constants (by rfl) + have hpiAlias : envT.constants ``MatrixPiAlias = + some (vconst(type_of% @MatrixPiAlias)) := + henv.constants (by rfl) + have hindexAlias : envT.constants ``MatrixIndexAlias = + some (vconst(type_of% @MatrixIndexAlias)) := + henv.constants (by rfl) + have hfamily : envT.constants ``NormalizationMatrix = + some normalizationMatrixRawType.toVConstant := + VEnv.addConst_self hadd + exact .cons ⟨_, by + apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixTypeFamily_defeq henv + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixTypeFamily_defeq henv + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixRecAlias_app_defeq + (by decide) henv (by type_tac) + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixBetaAlias_app_defeq + (by decide) henv (by type_tac) + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixLetAlias_app_defeq + (by decide) henv (by type_tac) + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixRecAlias_app_defeq + (by decide) henv (by type_tac) + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixPiAlias_app_defeq + (by decide) henv (by type_tac) + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixBetaAlias_app_defeq + (by decide) henv (by type_tac) + · apply VEnv.IsDefEq.forallEDF + · exact normalizationMatrixLetAlias_app_defeq + (by decide) henv (by type_tac) + · type_tac⟩ .nil + +theorem normalizationMatrixViewChecked_wf : + normalizationMatrixViewChecked.WF normalizationMatrixAliasEnv := by + refine ⟨?_, ?_⟩ + · change normalizationMatrixAliasEnv.OnTel 0 [] + [VExpr.sort (.succ .zero), VExpr.sort (.succ .zero)] + exact ⟨⟨_, by type_tac⟩, ⟨⟨_, by type_tac⟩, trivial⟩⟩ + · intro c hc + change c ∈ [normalizationMatrixViewCtor] at hc + have hc' : c = normalizationMatrixViewCtor := + List.mem_singleton.1 hc + subst c + constructor + · change fieldsWF 0 ``NormalizationMatrix 1 + normalizationMatrixAliasEnv (.succ (.succ .zero)) + [VExpr.sort (.succ .zero)] [VExpr.sort (.succ .zero)] 0 + [VExpr.sort (.succ .zero), VExpr.sort .zero, + VExpr.sort .zero, VExpr.sort .zero, + normalizationMatrixTarget (.bvar 4) (.bvar 3), + (VExpr.sort .zero).forallE + (normalizationMatrixTarget (.bvar 6) (.bvar 5)), + normalizationMatrixTarget (.bvar 6) (.bvar 5), + normalizationMatrixTarget (.bvar 7) (.bvar 6)] + refine ⟨?_, ?_, ?_⟩ + · exact .inr (.inr ⟨rfl, .succ (.succ .zero), by type_tac, + .inr (VLevel.le_refl _)⟩) + · intro h + change false = true at h + contradiction + · refine ⟨?_, ?_, ?_⟩ + · exact .inr (.inr ⟨rfl, .succ .zero, by type_tac, + .inr VLevel.le_succ⟩) + · intro h + change false = true at h + contradiction + · refine ⟨?_, ?_, ?_⟩ + · exact .inr (.inr ⟨rfl, .succ .zero, by type_tac, + .inr VLevel.le_succ⟩) + · intro h + change false = true at h + contradiction + · refine ⟨?_, ?_, ?_⟩ + · exact .inr (.inr ⟨rfl, .succ .zero, by type_tac, + .inr VLevel.le_succ⟩) + · intro h + change false = true at h + contradiction + · refine ⟨?_, ?_, ?_⟩ + · exact .inl rfl + · intro _ + exact .cons + (normalizationMatrixIndexAlias_app_hasType .rfl + (by type_tac)) .nil + · refine ⟨?_, ?_, ?_⟩ + · refine .inr (.inl ⟨_, rfl, by decide, ?_⟩) + constructor + · exact ⟨⟨_, by type_tac⟩, trivial⟩ + · exact .cons + (normalizationMatrixIndexAlias_app_hasType .rfl + (by type_tac)) .nil + · intro h + change false = true at h + contradiction + · refine ⟨?_, ?_, ?_⟩ + · exact .inl rfl + · intro _ + exact .cons + (normalizationMatrixIndexAlias_app_hasType .rfl + (by type_tac)) .nil + · refine ⟨?_, ?_, trivial⟩ + · exact .inl rfl + · intro _ + exact .cons + (normalizationMatrixIndexAlias_app_hasType .rfl + (by type_tac)) .nil + · exact .cons + (normalizationMatrixIndexAlias_app_hasType .rfl (by type_tac)) .nil + +theorem normalizationMatrixBlock_wf : + normalizationMatrixBlock.WF normalizationMatrixAliasEnv := + ⟨normalizationMatrixNormalization_wf, + normalizationMatrixViewChecked_wf⟩ + +theorem normalizationMatrixGenerationChecked_wf : + normalizationMatrixGenerationChecked.WF normalizationMatrixAliasEnv := by + refine { + blockWF := normalizationMatrixBlock_wf + familyTel := ?_ + familyResult := ?_ + ctors := ?_ } + · refine ⟨⟨_, normalizationMatrixTypeFamily_defeq .rfl⟩, ?_⟩ + exact ⟨⟨_, normalizationMatrixTypeFamily_defeq .rfl⟩, trivial⟩ + · exact VEnv.IsDefEq.sortDF (by decide) (by decide) rfl + · intro envT hadd ctor hctor + change ctor ∈ + [⟨normalizationMatrixRawType.ctors[0], + normalizationMatrixViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + have henv : normalizationMatrixAliasEnv ≤ envT := + VEnv.addConst_le hadd + have hfamily : envT.constants ``NormalizationMatrix = + some normalizationMatrixRawType.toVConstant := + VEnv.addConst_self hadd + have hindexAlias : envT.constants ``MatrixIndexAlias = + some (vconst(type_of% @MatrixIndexAlias)) := + henv.constants (by rfl) + refine { + declaredTel := ?_ + declaredResult := ?_ + emittedTel := ?_ + emittedResult := ?_ } + · refine ⟨⟨_, normalizationMatrixTypeFamily_defeq henv⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixTypeFamily_defeq henv⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixRecAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixBetaAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixLetAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixRecAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixPiAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixBetaAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + exact ⟨⟨_, normalizationMatrixLetAlias_app_defeq + (by decide) henv (by type_tac)⟩, trivial⟩ + · exact normalizationMatrixTarget_hasType henv hfamily + (by type_tac) (by type_tac) + · refine ⟨⟨_, by type_tac⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixTypeFamily_defeq henv⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixRecAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixBetaAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixLetAlias_app_defeq + (by decide) henv (by type_tac)⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixRecAlias_app_defeq + (by decide) henv (by + exact normalizationMatrixTarget_hasType henv hfamily + ((normalizationMatrixTypeFamily_defeq henv).defeq' + (by type_tac)) + (by type_tac))⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixPiAlias_app_defeq + (by decide) henv (by + exact normalizationMatrixTarget_hasType henv hfamily + ((normalizationMatrixTypeFamily_defeq henv).defeq' + (by type_tac)) + (by type_tac))⟩, ?_⟩ + refine ⟨⟨_, normalizationMatrixBetaAlias_app_defeq + (by decide) henv (by + exact normalizationMatrixTarget_hasType henv hfamily + ((normalizationMatrixTypeFamily_defeq henv).defeq' + (by type_tac)) + (by type_tac))⟩, ?_⟩ + exact ⟨⟨_, normalizationMatrixLetAlias_app_defeq + (by decide) henv (by + exact normalizationMatrixTarget_hasType henv hfamily + ((normalizationMatrixTypeFamily_defeq henv).defeq' + (by type_tac)) + (by type_tac))⟩, trivial⟩ + · exact normalizationMatrixTarget_hasType henv hfamily + ((normalizationMatrixTypeFamily_defeq henv).defeq' + (by type_tac)) + (by type_tac) + +def normalizationMatrixFinalEnv : VEnv := + (normalizationMatrixAliasEnv.addInductGeneration + normalizationMatrixGenerationChecked).get (by decide) + +theorem normalizationMatrix_addInductGeneration : + normalizationMatrixAliasEnv.addInductGeneration + normalizationMatrixGenerationChecked = + some normalizationMatrixFinalEnv := rfl + +theorem normalizationMatrixFinalEnv_trace : + Nonempty (VEnv.AddInductGenerationTrace normalizationMatrixAliasEnv + normalizationMatrixFinalEnv normalizationMatrixGenerationChecked) := + VEnv.addInductGeneration_trace normalizationMatrix_addInductGeneration + +theorem normalizationMatrixFinalEnv_family_lookup : + normalizationMatrixFinalEnv.constants ``NormalizationMatrix = + some normalizationMatrixRawType.toVConstant := by + rcases normalizationMatrixFinalEnv_trace with ⟨H⟩ + exact H.family_lookup + +theorem normalizationMatrixFinalEnv_ctor_lookup : + normalizationMatrixFinalEnv.constants ``NormalizationMatrix.mk = + some normalizationMatrixRawType.ctors[0].toVConstant := by + rcases normalizationMatrixFinalEnv_trace with ⟨H⟩ + exact H.ctor_lookup (.head _) + +theorem normalizationMatrixFinalEnv_rec_lookup : + normalizationMatrixFinalEnv.constants ``NormalizationMatrix.rec = + some (vconst(type_of% @NormalizationMatrix.rec)) := by + rcases normalizationMatrixFinalEnv_trace with ⟨H⟩ + exact H.rec_lookup + +theorem normalizationMatrixFinalEnv_iota_mem : + normalizationMatrixFinalEnv.defeqs + (vdefeq(alpha motive mk index ordinary beta letBound direct + piHidden betaRecursive letRecursive => + @NormalizationMatrix.rec alpha motive mk (MatrixIndexAlias index) + (@NormalizationMatrix.mk alpha index ordinary beta letBound direct + piHidden betaRecursive letRecursive) ≡ + mk index ordinary beta letBound direct piHidden betaRecursive + letRecursive + (@NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) direct) + (fun proof => @NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) (piHidden proof)) + (@NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) betaRecursive) + (@NormalizationMatrix.rec alpha motive mk + (MatrixIndexAlias index) letRecursive))) := by + rcases normalizationMatrixFinalEnv_trace with ⟨H⟩ + apply H.rule_mem + exact .head _ + +theorem normalizationMatrixFinalEnv_ordered : + normalizationMatrixFinalEnv.Ordered := + VEnv.addInductGeneration_WF normalizationMatrixAliasEnv_ordered + normalizationMatrixGenerationChecked_wf + normalizationMatrix_addInductGeneration + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.normalizationMatrixNormalization_wf [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.normalizationMatrixViewChecked_wf [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.normalizationMatrixGenerationChecked_wf [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.normalizationMatrixFinalEnv_trace [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.normalizationMatrixFinalEnv_iota_mem [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.normalizationMatrixFinalEnv_ordered [propext, Classical.choice, Quot.sound] + +/-! ## Checked-analysis rejection fixtures -/ + +/- +The next three declarations are kernel-side differential fixtures for the +recursive-Pi rejection branches. `#guard_msgs` checks the actual elaborator / +kernel outcome while rolling the failed declaration back, so the VExpr +fixtures below can independently exercise the Theory analyzer and public +transaction. +-/ + +namespace KernelDifferential + +/-- +error: (kernel) arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.KernelRejectRecDomain.mk' has a non positive occurrence of the datatypes being declared +-/ +#guard_msgs (whitespace := lax) in +inductive KernelRejectRecDomain : Type where + | mk : (KernelRejectRecDomain → KernelRejectRecDomain) → KernelRejectRecDomain + +/-- +error: Mismatched inductive type parameter in + KernelRejectRecTarget β +The provided argument + β +is not definitionally equal to the expected parameter + α + +Note: The value of parameter `α` must be fixed throughout the inductive declaration. Consider making this parameter an index if it must vary. +-/ +#guard_msgs (whitespace := lax) in +inductive KernelRejectRecTarget (α : Type) : Type where + | mk : ((β : Type) → KernelRejectRecTarget β) → KernelRejectRecTarget α + +/-- +error: (kernel) arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.KernelRejectRecIndex.mk' contains a non valid occurrence of the datatypes being declared +-/ +#guard_msgs (whitespace := lax) in +inductive KernelRejectRecIndex : Type → Type where + | mk : ((n : Nat) → KernelRejectRecIndex (KernelRejectRecIndex Nat)) → + KernelRejectRecIndex Nat + +end KernelDifferential + +/-- A recursive function argument may not mention the family in one of its +binder domains. This is the raw-VExpr counterpart of +`KernelRejectRecDomain`. -/ +def recDomainTypeName : Name := .mkSimple "RecDomainFixture" + +def recDomainCtorName : Name := .str recDomainTypeName "mk" + +def recDomainField : VExpr := + .forallE (.const recDomainTypeName []) (.const recDomainTypeName []) + +def recDomainType : VInductiveType where + name := recDomainTypeName + uvars := 0 + type := .sort (.succ .zero) + ctors := [⟨⟨0, .forallE recDomainField (.const recDomainTypeName [])⟩, + recDomainCtorName⟩] + +def recDomainDecl : VInductDecl := ⟨0, 0, [recDomainType]⟩ + +example : namesOK recDomainType = true := rfl +example : closedOK recDomainType = true := rfl +example : levelsOK 0 recDomainType = true := rfl +example : typeFormerOK 0 recDomainType = true := rfl +example : largeElim 0 recDomainTypeName 0 0 recDomainType = true := rfl +example : recTarget? 0 recDomainTypeName 0 0 0 recDomainField = none := rfl +example : stage3Field 0 recDomainTypeName 0 0 0 recDomainField = false := rfl +example : stage3DirectCore 0 0 recDomainType = false := rfl +example : recDomainDecl.checked? = none := rfl +example : VEnv.empty.addInduct recDomainDecl = none := rfl + +/-- A recursive target below a Pi must retain the declaration's fixed +parameters. Here the terminal target uses the locally bound `β` instead of +the outer parameter, matching `KernelRejectRecTarget`. -/ +def recTargetTypeName : Name := .mkSimple "RecTargetFixture" + +def recTargetCtorName : Name := .str recTargetTypeName "mk" + +def recTargetField : VExpr := + .forallE (.sort (.succ .zero)) + ((VExpr.const recTargetTypeName []).app (VExpr.bvar 0)) + +def recTargetType : VInductiveType where + name := recTargetTypeName + uvars := 0 + type := .forallE (.sort (.succ .zero)) (.sort (.succ .zero)) + ctors := [⟨⟨0, + .forallE (.sort (.succ .zero)) + (.forallE recTargetField + ((VExpr.const recTargetTypeName []).app (VExpr.bvar 1)))⟩, + recTargetCtorName⟩] + +def recTargetDecl : VInductDecl := ⟨0, 1, [recTargetType]⟩ + +example : namesOK recTargetType = true := rfl +example : closedOK recTargetType = true := rfl +example : levelsOK 0 recTargetType = true := rfl +example : typeFormerOK 1 recTargetType = true := rfl +example : largeElim 0 recTargetTypeName 1 0 recTargetType = true := rfl +example : isRecField 0 recTargetTypeName 1 0 1 + ((VExpr.const recTargetTypeName []).app (VExpr.bvar 0)) = false := rfl +example : recTarget? 0 recTargetTypeName 1 0 0 recTargetField = none := rfl +example : stage3Field 0 recTargetTypeName 1 0 0 recTargetField = false := rfl +example : stage3DirectCore 0 1 recTargetType = false := rfl +example : recTargetDecl.checked? = none := rfl +example : VEnv.empty.addInduct recTargetDecl = none := rfl + +/-- Recursive target indices must be free of the family. The inner +`RecIndexFixture Nat` occurs inside the outer recursive target's index, +matching `KernelRejectRecIndex`. -/ +def recIndexTypeName : Name := .mkSimple "RecIndexFixture" + +def recIndexCtorName : Name := .str recIndexTypeName "mk" + +def recIndexTarget : VExpr := + (VExpr.const recIndexTypeName []).app + ((VExpr.const recIndexTypeName []).app (VExpr.const ``Nat [])) + +def recIndexField : VExpr := .forallE (VExpr.const ``Nat []) recIndexTarget + +def recIndexType : VInductiveType where + name := recIndexTypeName + uvars := 0 + type := .forallE (.sort (.succ .zero)) (.sort (.succ .zero)) + ctors := [⟨⟨0, + .forallE recIndexField + ((VExpr.const recIndexTypeName []).app (VExpr.const ``Nat []))⟩, + recIndexCtorName⟩] + +def recIndexDecl : VInductDecl := ⟨0, 0, [recIndexType]⟩ + +example : namesOK recIndexType = true := rfl +example : closedOK recIndexType = true := rfl +example : levelsOK 0 recIndexType = true := rfl +example : typeFormerOK 0 recIndexType = true := rfl +example : largeElim 0 recIndexTypeName 0 1 recIndexType = true := rfl +example : isRecField 0 recIndexTypeName 0 1 1 recIndexTarget = false := rfl +example : recTarget? 0 recIndexTypeName 0 1 0 recIndexField = none := rfl +example : stage3Field 0 recIndexTypeName 0 1 0 recIndexField = false := rfl +example : stage3DirectCore 0 0 recIndexType = false := rfl +example : recIndexDecl.checked? = none := rfl +example : VEnv.empty.addInduct recIndexDecl = none := rfl + +/-- The old direct-recursion shape alone admits duplicate constructor names; +the shared I2 descriptor rejects the block before a partial transaction. -/ +def duplicateCtorTypeName : Name := .mkSimple "DuplicateCtorFixture" + +def duplicateCtorName : Name := .str duplicateCtorTypeName "mk" + +def duplicateCtorType : VInductiveType where + name := duplicateCtorTypeName + uvars := 0 + type := VExpr.sort (.succ .zero) + ctors := [⟨⟨0, VExpr.const duplicateCtorTypeName []⟩, duplicateCtorName⟩, + ⟨⟨0, VExpr.const duplicateCtorTypeName []⟩, duplicateCtorName⟩] + +def duplicateCtorDecl : VInductDecl := ⟨0, 0, [duplicateCtorType]⟩ + +example : stage3DirectCore 0 0 duplicateCtorType = true := rfl +example : namesOK duplicateCtorType = false := rfl +example : duplicateCtorDecl.checked? = none := rfl +example : VEnv.empty.addInduct duplicateCtorDecl = none := rfl + +/-- Internal uniqueness covers collisions between different generated roles, +not only two constructors with the same name. -/ +def typeCtorAliasName : Name := .mkSimple "TypeCtorAliasFixture" + +def typeCtorAliasType : VInductiveType where + name := typeCtorAliasName + uvars := 0 + type := VExpr.sort (.succ .zero) + ctors := [⟨⟨0, VExpr.const typeCtorAliasName []⟩, typeCtorAliasName⟩] + +def typeCtorAliasDecl : VInductDecl := ⟨0, 0, [typeCtorAliasType]⟩ + +example : stage3DirectCore 0 0 typeCtorAliasType = true := rfl +example : namesOK typeCtorAliasType = false := rfl +example : typeCtorAliasDecl.checked? = none := rfl + +def ctorRecAliasTypeName : Name := .mkSimple "CtorRecAliasFixture" + +def ctorRecAliasType : VInductiveType where + name := ctorRecAliasTypeName + uvars := 0 + type := VExpr.sort (.succ .zero) + ctors := [⟨⟨0, VExpr.const ctorRecAliasTypeName []⟩, + .str ctorRecAliasTypeName "rec"⟩] + +def ctorRecAliasDecl : VInductDecl := ⟨0, 0, [ctorRecAliasType]⟩ + +example : stage3DirectCore 0 0 ctorRecAliasType = true := rfl +example : namesOK ctorRecAliasType = false := rfl +example : ctorRecAliasDecl.checked? = none := rfl + +/-- A constructor result with a loose index variable has the expected direct +head/spine shape, but is not legal closed kernel metadata. -/ +def looseIndexTypeName : Name := .mkSimple "LooseIndexFixture" + +def looseIndexCtorName : Name := .str looseIndexTypeName "mk" + +def looseIndexType : VInductiveType where + name := looseIndexTypeName + uvars := 0 + type := VExpr.forallE (VExpr.const ``Nat []) (VExpr.sort (.succ .zero)) + ctors := [⟨⟨0, (VExpr.const looseIndexTypeName []).app (.bvar 0)⟩, + looseIndexCtorName⟩] + +def looseIndexDecl : VInductDecl := ⟨0, 0, [looseIndexType]⟩ + +example : stage3DirectCore 0 0 looseIndexType = true := rfl +example : closedOK looseIndexType = false := rfl +example : looseIndexDecl.checked? = none := rfl +example : VEnv.empty.addInduct looseIndexDecl = none := rfl + +/-- The family type is checked before its own constant exists. A self +occurrence hidden in a parameter domain must therefore be rejected even when +the constructor result has the otherwise expected head and parameter spine. -/ +def selfParamTypeName : Name := .mkSimple "SelfParamFixture" + +def selfParamCtorName : Name := .str selfParamTypeName "mk" + +def selfParamType : VInductiveType where + name := selfParamTypeName + uvars := 0 + type := VExpr.forallE (VExpr.const selfParamTypeName []) (VExpr.sort (.succ .zero)) + ctors := [⟨⟨0, VExpr.forallE (VExpr.const selfParamTypeName []) + ((VExpr.const selfParamTypeName []).app (.bvar 0))⟩, selfParamCtorName⟩] + +def selfParamDecl : VInductDecl := ⟨0, 1, [selfParamType]⟩ + +example : typeFormerOK 1 selfParamType = false := rfl +example : closedOK selfParamType = true := rfl +example : levelsOK 0 selfParamType = true := rfl +example : selfParamDecl.checked? = none := rfl +example : VEnv.empty.addInduct selfParamDecl = none := rfl + +/-- An out-of-range universe can hide in a parameter while the result sort and +direct constructor shape remain valid. `levelsOK` checks the complete metadata +rather than only the result. -/ +def badParamLevelTypeName : Name := .mkSimple "BadParamLevelFixture" + +def badParamLevelCtorName : Name := .str badParamLevelTypeName "mk" + +def badParamLevelType : VInductiveType where + name := badParamLevelTypeName + uvars := 0 + type := VExpr.forallE (VExpr.sort (.param 0)) (VExpr.sort (.succ .zero)) + ctors := [⟨⟨0, VExpr.forallE (VExpr.sort (.param 0)) + ((VExpr.const badParamLevelTypeName []).app (.bvar 0))⟩, badParamLevelCtorName⟩] + +def badParamLevelDecl : VInductDecl := ⟨0, 1, [badParamLevelType]⟩ + +example : stage3DirectCore 0 1 badParamLevelType = true := rfl +example : closedOK badParamLevelType = true := rfl +example : levelsOK 0 badParamLevelType = false := rfl +example : badParamLevelDecl.checked? = none := rfl +example : VEnv.empty.addInduct badParamLevelDecl = none := rfl + +/-- Constructor fields receive the same full universe-range check. -/ +def badCtorLevelTypeName : Name := .mkSimple "BadCtorLevelFixture" + +def badCtorLevelCtorName : Name := .str badCtorLevelTypeName "mk" + +def badCtorLevelType : VInductiveType where + name := badCtorLevelTypeName + uvars := 0 + type := VExpr.sort (.succ .zero) + ctors := [⟨⟨0, VExpr.forallE (VExpr.sort (.param 0)) + (VExpr.const badCtorLevelTypeName [])⟩, badCtorLevelCtorName⟩] + +def badCtorLevelDecl : VInductDecl := ⟨0, 0, [badCtorLevelType]⟩ + +example : stage3DirectCore 0 0 badCtorLevelType = true := rfl +example : closedOK badCtorLevelType = true := rfl +example : levelsOK 0 badCtorLevelType = false := rfl +example : badCtorLevelDecl.checked? = none := rfl +example : VEnv.empty.addInduct badCtorLevelDecl = none := rfl + +/-- A non-sort family result never reaches descriptor construction. -/ +def nonSortResultTypeName : Name := .mkSimple "NonSortResultFixture" + +def nonSortResultType : VInductiveType where + name := nonSortResultTypeName + uvars := 0 + type := VExpr.const ``Nat [] + ctors := [] + +def nonSortResultDecl : VInductDecl := ⟨0, 0, [nonSortResultType]⟩ + +example : stage3DirectCore 0 0 nonSortResultType = false := rfl +example : nonSortResultDecl.checked? = none := rfl +example : VEnv.empty.addInduct nonSortResultDecl = none := rfl + +/-- A constructor must return the family being declared, not merely any +well-formed closed type. -/ +def wrongCtorHeadTypeName : Name := .mkSimple "WrongCtorHeadFixture" + +def wrongCtorHeadCtorName : Name := .str wrongCtorHeadTypeName "mk" + +def wrongCtorHeadType : VInductiveType where + name := wrongCtorHeadTypeName + uvars := 0 + type := VExpr.sort (.succ .zero) + ctors := [⟨⟨0, VExpr.const ``Nat []⟩, wrongCtorHeadCtorName⟩] + +def wrongCtorHeadDecl : VInductDecl := ⟨0, 0, [wrongCtorHeadType]⟩ + +example : stage3DirectCore 0 0 wrongCtorHeadType = false := rfl +example : wrongCtorHeadDecl.checked? = none := rfl +example : VEnv.empty.addInduct wrongCtorHeadDecl = none := rfl + +/-- Constructor result parameters must be the declaration's parameter +variables in order, not arbitrary closed expressions of a plausible shape. -/ +def wrongParamSpineTypeName : Name := .mkSimple "WrongParamSpineFixture" + +def wrongParamSpineCtorName : Name := .str wrongParamSpineTypeName "mk" + +def wrongParamSpineType : VInductiveType where + name := wrongParamSpineTypeName + uvars := 0 + type := VExpr.forallE (VExpr.sort (.succ .zero)) (VExpr.sort (.succ .zero)) + ctors := [⟨⟨0, VExpr.forallE (VExpr.sort (.succ .zero)) + ((VExpr.const wrongParamSpineTypeName []).app (.sort .zero))⟩, + wrongParamSpineCtorName⟩] + +def wrongParamSpineDecl : VInductDecl := ⟨0, 1, [wrongParamSpineType]⟩ + +example : stage3DirectCore 0 1 wrongParamSpineType = false := rfl +example : wrongParamSpineDecl.checked? = none := rfl +example : VEnv.empty.addInduct wrongParamSpineDecl = none := rfl + +/-- `nparams` cannot exceed the actual leading pi telescope. -/ +def shortParamDecl : VInductDecl := ⟨0, 1, [natType]⟩ + +example : stage3DirectCore 0 1 natType = false := rfl +example : shortParamDecl.checked? = none := rfl +example : VEnv.empty.addInduct shortParamDecl = none := rfl + +/-- Declaration, family, and constructor universe counts must agree even when +the expressions themselves happen not to mention a level parameter. -/ +def badTypeUvars : VInductiveType := { natType with uvars := 1 } +def badTypeUvarsDecl : VInductDecl := ⟨0, 0, [badTypeUvars]⟩ + +example : stage3DirectCore 0 0 badTypeUvars = false := rfl +example : badTypeUvarsDecl.checked? = none := rfl + +def badCtorUvarsType : VInductiveType := + { natType with ctors := [{ natType.ctors[0] with uvars := 1 }, natType.ctors[1]] } +def badCtorUvarsDecl : VInductDecl := ⟨0, 0, [badCtorUvarsType]⟩ + +example : stage3DirectCore 0 0 badCtorUvarsType = false := rfl +example : badCtorUvarsDecl.checked? = none := rfl + +/-! Environment-relative collisions are checked transactionally, after the +environment-independent descriptor has established internal `Nodup`. -/ + +def ctorCollisionEnv : VEnv := + (VEnv.empty.addConst ``Nat.zero ⟨0, .sort .zero⟩).get (by decide) + +example : ctorCollisionEnv.constants ``Nat.zero = some ⟨0, .sort .zero⟩ := rfl +example : ctorCollisionEnv.addInduct natDecl = none := + VEnv.addInduct_eq_none_of_ctor_present (.head _) (.head _) ⟨_, rfl⟩ + +def recCollisionEnv : VEnv := + (VEnv.empty.addConst ``Nat.rec ⟨0, .sort .zero⟩).get (by decide) + +example : recCollisionEnv.constants ``Nat.rec = some ⟨0, .sort .zero⟩ := rfl +example : recCollisionEnv.addInduct natDecl = none := + VEnv.addInduct_eq_none_of_rec_present + (generation := natBlockGenerationChecked) rfl (.head _) ⟨_, rfl⟩ + +/-! ## Small elimination -/ + +/-- `Or` is the canonical small-elimination family: its motive remains in +`Prop`, so the generated recursor introduces no fresh universe parameter. -/ +def orType : VInductiveType where + name := ``Or + uvars := 0 + type := vconst(type_of% @Or).type + ctors := [⟨vconst(type_of% @Or.inl), ``Or.inl⟩, + ⟨vconst(type_of% @Or.inr), ``Or.inr⟩] + +def orDecl : VInductDecl := ⟨0, 2, [orType]⟩ + +def orChecked : orDecl.Checked := orDecl.checked?.get (by decide) + +example : orDecl.stage3 = true := rfl +example : orChecked.elimination = .small := rfl +example : orChecked.kTarget = false := rfl +example : orChecked.recursor.uvars = 0 := rfl +example : orChecked.recursor = vconst(type_of% @Or.rec) := rfl +example : orChecked.generatedRules[0]? = + some (vdefeq(a b motive inl inr h => + @Or.rec a b motive inl inr (@Or.inl a b h) ≡ inl h)) := rfl +example : orChecked.generatedRules[1]? = + some (vdefeq(a b motive inl inr h => + @Or.rec a b motive inl inr (@Or.inr a b h) ≡ inr h)) := rfl +example : (VEnv.empty.addInduct orDecl).isSome = true := rfl + +/-- `And` is the canonical singleton-Prop exception: both constructor fields +are proofs, so Lean legitimately gives it a large eliminator with one fresh +universe parameter. -/ +def andType : VInductiveType where + name := ``And + uvars := 0 + type := vconst(type_of% @And).type + ctors := [⟨vconst(type_of% @And.intro), ``And.intro⟩] + +def andDecl : VInductDecl := ⟨0, 2, [andType]⟩ + +def andChecked : andDecl.Checked := andDecl.checked?.get (by decide) + +example : andDecl.stage3 = true := rfl +example : andChecked.elimination = .large := rfl +/-- Large elimination and K eligibility are independent: `And` has the +singleton-proof elimination exception, but its constructor has fields. -/ +example : andChecked.kTarget = false := rfl +example : andChecked.recursor.uvars = 1 := rfl +example : andChecked.recursor = vconst(type_of% @And.rec) := rfl +example : andChecked.generatedRules[0]? = + some (vdefeq(a b motive intro left right => + @And.rec a b motive intro (@And.intro a b left right) ≡ + intro left right)) := rfl +example : (VEnv.empty.addInduct andDecl).isSome = true := rfl + +/-! ## Conservativity: malformed declarations and name collisions refuse. -/ + +/-- A name collision rejects the whole transaction. -/ +example (env : VEnv) (h : env.contains ``Nat) : env.addInduct natDecl = none := + VEnv.addInduct_eq_none_of_type_present (.head _) h diff --git a/Ix/Theory/Named/LICENSE b/Ix/Theory/Named/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/Ix/Theory/Named/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Ix/Theory/Named/Literals.lean b/Ix/Theory/Named/Literals.lean new file mode 100644 index 000000000..47a31b000 --- /dev/null +++ b/Ix/Theory/Named/Literals.lean @@ -0,0 +1,682 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Inductive +import Ix.Theory.Named.Typing.Strong + +open Ix.Theory (VLevel) + +/-! # Theory encodings of Lean literals and primitive reflection + +This file contains only `VExpr`/`VEnv` semantics. Traversal of `Lean.Expr` +and `Literal.toConstructor` belongs to the Verify translation layer. +-/ + +namespace Ix.Theory.Named +open Lean + +def VEnv.ContainsLits (env : VEnv) : Literal → Prop + | .natVal _ => env.contains ``Nat + | .strVal _ => env.contains ``Char.ofNat ∧ env.contains ``String.ofList + +def VExpr.bool : VExpr := .const ``Bool [] +def VExpr.boolTrue : VExpr := .const ``Bool.true [] +def VExpr.boolFalse : VExpr := .const ``Bool.false [] +def VExpr.boolLit : Bool → VExpr + | .false => .boolFalse + | .true => .boolTrue + +def VExpr.nat : VExpr := .const ``Nat [] +def VExpr.natZero : VExpr := .const ``Nat.zero [] +def VExpr.natSucc : VExpr := .const ``Nat.succ [] +def VExpr.natLit : Nat → VExpr + | 0 => .natZero + | n+1 => .app .natSucc (.natLit n) + +def VExpr.char : VExpr := .const ``Char [] +def VExpr.string : VExpr := .const ``String [] +def VExpr.stringOfList : VExpr := .const ``String.ofList [] +def VExpr.listChar : VExpr := .app (.const ``List [.zero]) .char +def VExpr.listCharNil : VExpr := .app (.const ``List.nil [.zero]) .char +def VExpr.listCharCons : VExpr := .app (.const ``List.cons [.zero]) .char +def VExpr.charOfNat : VExpr := .const ``Char.ofNat [] +def VExpr.listCharLit : List Char → VExpr + | [] => .listCharNil + | a :: as => + .app (.app .listCharCons (.app .charOfNat (.natLit a.toNat))) (.listCharLit as) + +def VExpr.trLiteral : Literal → VExpr + | .natVal n => .natLit n + | .strVal s => .app .stringOfList (.listCharLit s.toList) + +def VExpr.literalType : Literal → VExpr + | .natVal _ => .nat + | .strVal _ => .string + +/-! ## Exact prelude artifacts + +`ContainsLits` deliberately records only name occurrence. The declarations +below describe the exact Theory artifacts that make those names meaningful. +The inductive recursors and iota rules are generated by the same +consumer-neutral Theory machinery used by `VEnv.addInduct`. +-/ + +namespace LiteralPrelude + +def boolFalse : VConstVal := + { name := ``Bool.false, uvars := 0, type := .bool } + +def boolTrue : VConstVal := + { name := ``Bool.true, uvars := 0, type := .bool } + +def boolType : VInductiveType where + name := ``Bool + uvars := 0 + type := .sort (.succ .zero) + ctors := [boolFalse, boolTrue] + +def boolRec : VConstant := VInductDecl.recConst 0 ``Bool 0 boolType +def boolIotas : List VDefEq := VInductDecl.rules 0 ``Bool 0 boolType + +def natZero : VConstVal := + { name := ``Nat.zero, uvars := 0, type := .nat } + +def natSucc : VConstVal := + { name := ``Nat.succ, uvars := 0, type := .forallE .nat .nat } + +def natType : VInductiveType where + name := ``Nat + uvars := 0 + type := .sort (.succ .zero) + ctors := [natZero, natSucc] + +def natRec : VConstant := VInductDecl.recConst 0 ``Nat 0 natType +def natIotas : List VDefEq := VInductDecl.rules 0 ``Nat 0 natType + +def char : VConstant := { uvars := 0, type := .sort (.succ .zero) } +def charOfNat : VConstant := { uvars := 0, type := .forallE .nat .char } + +def listNil : VConstVal where + name := ``List.nil + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) + (.app (.const ``List [.param 0]) (.bvar 0)) + +def listCons : VConstVal where + name := ``List.cons + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) <| + .forallE (.bvar 0) <| + .forallE (.app (.const ``List [.param 0]) (.bvar 1)) + (.app (.const ``List [.param 0]) (.bvar 2)) + +def listType : VInductiveType where + name := ``List + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := [listNil, listCons] + +def listRec : VConstant := VInductDecl.recConst 1 ``List 1 listType +def listIotas : List VDefEq := VInductDecl.rules 1 ``List 1 listType + +def string : VConstant := { uvars := 0, type := .sort (.succ .zero) } +def stringOfList : VConstant := + { uvars := 0, type := .forallE .listChar .string } + +end LiteralPrelude + +/-- The exact kernel-facing prelude fragment needed to interpret Theory +literals. In contrast with `ContainsLits`, this records declaration types, +recursors, iota rules, and an ordered construction history. -/ +structure VEnv.PreludeReady (env : VEnv) : Prop where + ordered : env.Ordered + bool : env.constants ``Bool = some LiteralPrelude.boolType.toVConstant + boolFalse : env.constants ``Bool.false = + some LiteralPrelude.boolFalse.toVConstant + boolTrue : env.constants ``Bool.true = + some LiteralPrelude.boolTrue.toVConstant + boolRec : env.constants ``Bool.rec = some LiteralPrelude.boolRec + boolIotas : ∀ df ∈ LiteralPrelude.boolIotas, env.defeqs df + nat : env.constants ``Nat = some LiteralPrelude.natType.toVConstant + natZero : env.constants ``Nat.zero = + some LiteralPrelude.natZero.toVConstant + natSucc : env.constants ``Nat.succ = + some LiteralPrelude.natSucc.toVConstant + natRec : env.constants ``Nat.rec = some LiteralPrelude.natRec + natIotas : ∀ df ∈ LiteralPrelude.natIotas, env.defeqs df + char : env.constants ``Char = some LiteralPrelude.char + charOfNat : env.constants ``Char.ofNat = some LiteralPrelude.charOfNat + list : env.constants ``List = some LiteralPrelude.listType.toVConstant + listNil : env.constants ``List.nil = + some LiteralPrelude.listNil.toVConstant + listCons : env.constants ``List.cons = + some LiteralPrelude.listCons.toVConstant + listRec : env.constants ``List.rec = some LiteralPrelude.listRec + listIotas : ∀ df ∈ LiteralPrelude.listIotas, env.defeqs df + string : env.constants ``String = some LiteralPrelude.string + stringOfList : env.constants ``String.ofList = some LiteralPrelude.stringOfList + +namespace VEnv.PreludeReady + +/-- Exact prelude artifacts transport across environment inclusion. The +target ordering premise is necessary because arbitrary `VEnv.LE` growth may +append an ill-typed declaration. -/ +theorem mono {env env' : VEnv} (H : env.PreludeReady) (henv : env ≤ env') + (hordered : env'.Ordered) : env'.PreludeReady where + ordered := hordered + bool := henv.constants H.bool + boolFalse := henv.constants H.boolFalse + boolTrue := henv.constants H.boolTrue + boolRec := henv.constants H.boolRec + boolIotas := fun df hdf => henv.defeqs (H.boolIotas df hdf) + nat := henv.constants H.nat + natZero := henv.constants H.natZero + natSucc := henv.constants H.natSucc + natRec := henv.constants H.natRec + natIotas := fun df hdf => henv.defeqs (H.natIotas df hdf) + char := henv.constants H.char + charOfNat := henv.constants H.charOfNat + list := henv.constants H.list + listNil := henv.constants H.listNil + listCons := henv.constants H.listCons + listRec := henv.constants H.listRec + listIotas := fun df hdf => henv.defeqs (H.listIotas df hdf) + string := henv.constants H.string + stringOfList := henv.constants H.stringOfList + +/-- Any successful well-formed constant insertion preserves readiness. It is +necessarily unrelated to the ready prelude: all of those names are already +occupied, while `addConst` succeeds only at a fresh name. -/ +theorem addConst {env env' : VEnv} (H : env.PreludeReady) + (hci : ci.WF env) (hadd : env.addConst name ci = some env') : + env'.PreludeReady := + H.mono (VEnv.addConst_le hadd) (.const H.ordered hci hadd) + +/-- Adding a well-formed unrelated definitional equation preserves prelude +readiness. -/ +theorem addDefEq {env : VEnv} (H : env.PreludeReady) (hdf : df.WF env) : + (env.addDefEq df).PreludeReady := + H.mono VEnv.addDefEq_le (.defeq H.ordered hdf) + +/-- A ready prelude contains every name used by the direct literal encoding. -/ +theorem containsLits {env : VEnv} (H : env.PreludeReady) : + ∀ l, env.ContainsLits l + | .natVal _ => ⟨_, H.nat⟩ + | .strVal _ => ⟨⟨_, H.charOfNat⟩, ⟨_, H.stringOfList⟩⟩ + +end VEnv.PreludeReady + +def VEnv.ReflectsNatNatNat (env : VEnv) (fc : Name) (f : Nat → Nat → Nat) := + env.contains fc → + ∀ a b, env.IsDefEqU 0 [] + (.app (.app (.const fc []) (.natLit a)) (.natLit b)) (.natLit (f a b)) + +def VEnv.ReflectsNatNatBool (env : VEnv) (fc : Name) (f : Nat → Nat → Bool) := + env.contains fc → + ∀ a b, env.IsDefEqU 0 [] + (.app (.app (.const fc []) (.natLit a)) (.natLit b)) (.boolLit (f a b)) + +structure VEnv.HasPrimitives (env : VEnv) : Prop where + bool : env.contains ``Bool → env.contains ``Bool.false ∧ env.contains ``Bool.true + boolFalse : env.constants ``Bool.false = some ci → ci = { uvars := 0, type := .bool } + boolTrue : env.constants ``Bool.true = some ci → ci = { uvars := 0, type := .bool } + nat : env.contains ``Nat → env.contains ``Nat.zero ∧ env.contains ``Nat.succ + natZero : env.constants ``Nat.zero = some ci → ci = { uvars := 0, type := .nat } + natSucc : env.constants ``Nat.succ = some ci → + ci = { uvars := 0, type := .forallE .nat .nat } + natAdd : env.ReflectsNatNatNat ``Nat.add Nat.add + natSub : env.ReflectsNatNatNat ``Nat.sub Nat.sub + natMul : env.ReflectsNatNatNat ``Nat.mul Nat.mul + natPow : env.ReflectsNatNatNat ``Nat.pow Nat.pow + natGcd : env.ReflectsNatNatNat ``Nat.gcd Nat.gcd + natMod : env.ReflectsNatNatNat ``Nat.mod Nat.mod + natDiv : env.ReflectsNatNatNat ``Nat.div Nat.div + natBEq : env.ReflectsNatNatBool ``Nat.beq Nat.beq + natBLE : env.ReflectsNatNatBool ``Nat.ble Nat.ble + natLAnd : env.ReflectsNatNatNat ``Nat.land Nat.land + natLOr : env.ReflectsNatNatNat ``Nat.lor Nat.lor + natXor : env.ReflectsNatNatNat ``Nat.xor Nat.xor + natShiftLeft : env.ReflectsNatNatNat ``Nat.shiftLeft Nat.shiftLeft + natShiftRight : env.ReflectsNatNatNat ``Nat.shiftRight Nat.shiftRight + charOfNat : env.constants ``Char.ofNat = some ci → + ci = { uvars := 0, type := .forallE .nat .char } + stringOfList : env.constants ``String.ofList = some ci → + ci = { uvars := 0, type := .forallE .listChar .string } ∧ + env.HasType 0 [] .listCharNil .listChar ∧ + env.HasType 0 [] .listCharCons (.forallE .char <| .forallE .listChar .listChar) + +/-- A well-formed Boolean literal can only occur when the corresponding +Boolean declaration is present. -/ +theorem VExpr.WF.boolLit_has_type (wf : env.Ordered) + (henv : env.HasPrimitives) (hΓ : OnCtx Γ (env.IsType U)) + (H : VExpr.WF env U Γ (.boolLit b)) : env.contains ``Bool := by + suffices env.HasType U Γ (.boolLit b) .bool by + have ⟨_, H⟩ := this.isType wf hΓ + have ⟨_, H, _⟩ := VEnv.HasType.const_inv wf hΓ H + exact ⟨_, H⟩ + cases b with + have ⟨_, h1, h2, h3⟩ := + let ⟨_, H⟩ := H + VEnv.HasType.const_inv wf hΓ H + | false => cases henv.boolFalse h1; exact .const h1 h2 h3 + | true => cases henv.boolTrue h1; exact .const h1 h2 h3 + +/-- The primitive constants whose Theory reflections are tracked by +`VEnv.HasPrimitives`. `Nat.pred` and `Nat.bitwise` are kernel primitive names +too, but they have no dedicated fields in that contract. -/ +def VEnv.reflectedPrimitiveNames : List Name := [ + ``Bool, ``Bool.false, ``Bool.true, + ``Nat, ``Nat.zero, ``Nat.succ, + ``Nat.add, ``Nat.sub, ``Nat.mul, ``Nat.pow, + ``Nat.gcd, ``Nat.mod, ``Nat.div, ``Nat.beq, ``Nat.ble, + ``Nat.land, ``Nat.lor, ``Nat.xor, + ``Nat.shiftLeft, ``Nat.shiftRight, + ``Char.ofNat, ``String.ofList] + +/-- An environment containing none of the hard-coded reflected primitive +names satisfies the primitive-reflection contract vacuously. -/ +theorem VEnv.HasPrimitives.of_avoids + {env : VEnv} + (h : ∀ n ∈ VEnv.reflectedPrimitiveNames, env.constants n = none) : + env.HasPrimitives := by + have noContains (n) (hn : n ∈ VEnv.reflectedPrimitiveNames) : + ¬env.contains n := by + rintro ⟨ci, hci⟩ + rw [h n hn] at hci + contradiction + have noLookup (n) (hn : n ∈ VEnv.reflectedPrimitiveNames) + {ci} (hci : env.constants n = some ci) : False := by + rw [h n hn] at hci + contradiction + exact { + bool := fun hc => + (noContains ``Bool (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + boolFalse := fun hci => + (noLookup ``Bool.false + (by simp [VEnv.reflectedPrimitiveNames]) hci).elim + boolTrue := fun hci => + (noLookup ``Bool.true + (by simp [VEnv.reflectedPrimitiveNames]) hci).elim + nat := fun hc => + (noContains ``Nat (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natZero := fun hci => + (noLookup ``Nat.zero + (by simp [VEnv.reflectedPrimitiveNames]) hci).elim + natSucc := fun hci => + (noLookup ``Nat.succ + (by simp [VEnv.reflectedPrimitiveNames]) hci).elim + natAdd := fun hc => + (noContains ``Nat.add + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natSub := fun hc => + (noContains ``Nat.sub + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natMul := fun hc => + (noContains ``Nat.mul + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natPow := fun hc => + (noContains ``Nat.pow + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natGcd := fun hc => + (noContains ``Nat.gcd + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natMod := fun hc => + (noContains ``Nat.mod + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natDiv := fun hc => + (noContains ``Nat.div + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natBEq := fun hc => + (noContains ``Nat.beq + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natBLE := fun hc => + (noContains ``Nat.ble + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natLAnd := fun hc => + (noContains ``Nat.land + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natLOr := fun hc => + (noContains ``Nat.lor + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natXor := fun hc => + (noContains ``Nat.xor + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natShiftLeft := fun hc => + (noContains ``Nat.shiftLeft + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + natShiftRight := fun hc => + (noContains ``Nat.shiftRight + (by simp [VEnv.reflectedPrimitiveNames]) hc).elim + charOfNat := fun hci => + (noLookup ``Char.ofNat + (by simp [VEnv.reflectedPrimitiveNames]) hci).elim + stringOfList := fun hci => + (noLookup ``String.ofList + (by simp [VEnv.reflectedPrimitiveNames]) hci).elim } + +/-- A fresh Theory constant leaves every other lookup unchanged. -/ +theorem VEnv.addConst_other + {env env' : VEnv} {name other : Name} {ci : VConstant} + (hadd : env.addConst name ci = some env') + (hne : name ≠ other) : + env'.constants other = env.constants other := by + unfold VEnv.addConst at hadd + split at hadd <;> cases hadd + simp [hne] + +/-- Inserting a non-reflected constant preserves the primitive-reflection +contract. -/ +theorem VEnv.HasPrimitives.addConst + {env env' : VEnv} {name : Name} {ci : VConstant} + (H : env.HasPrimitives) + (hname : name ∉ VEnv.reflectedPrimitiveNames) + (hadd : env.addConst name ci = some env') : + env'.HasPrimitives := by + have lookup (other : Name) (hother : other ∈ VEnv.reflectedPrimitiveNames) : + env'.constants other = env.constants other := + VEnv.addConst_other hadd (by + intro equality + apply hname + simpa only [equality] using hother) + have oldContains (other : Name) + (hother : other ∈ VEnv.reflectedPrimitiveNames) : + env'.contains other → env.contains other := by + rintro ⟨value, hvalue⟩ + exact ⟨value, by simpa only [lookup other hother] using hvalue⟩ + have newContains (other : Name) : + env.contains other → env'.contains other := by + rintro ⟨value, hvalue⟩ + exact ⟨value, (VEnv.addConst_le hadd).constants hvalue⟩ + have hle := VEnv.addConst_le hadd + exact { + bool := fun h => by + obtain ⟨hfalse, htrue⟩ := H.bool (oldContains ``Bool + (by simp [VEnv.reflectedPrimitiveNames]) h) + exact ⟨newContains _ hfalse, newContains _ htrue⟩ + boolFalse := fun h => H.boolFalse (by + simpa only [lookup ``Bool.false + (by simp [VEnv.reflectedPrimitiveNames])] using h) + boolTrue := fun h => H.boolTrue (by + simpa only [lookup ``Bool.true + (by simp [VEnv.reflectedPrimitiveNames])] using h) + nat := fun h => by + obtain ⟨hzero, hsucc⟩ := H.nat (oldContains ``Nat + (by simp [VEnv.reflectedPrimitiveNames]) h) + exact ⟨newContains _ hzero, newContains _ hsucc⟩ + natZero := fun h => H.natZero (by + simpa only [lookup ``Nat.zero + (by simp [VEnv.reflectedPrimitiveNames])] using h) + natSucc := fun h => H.natSucc (by + simpa only [lookup ``Nat.succ + (by simp [VEnv.reflectedPrimitiveNames])] using h) + natAdd := fun h a b => + (H.natAdd (oldContains ``Nat.add + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natSub := fun h a b => + (H.natSub (oldContains ``Nat.sub + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natMul := fun h a b => + (H.natMul (oldContains ``Nat.mul + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natPow := fun h a b => + (H.natPow (oldContains ``Nat.pow + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natGcd := fun h a b => + (H.natGcd (oldContains ``Nat.gcd + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natMod := fun h a b => + (H.natMod (oldContains ``Nat.mod + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natDiv := fun h a b => + (H.natDiv (oldContains ``Nat.div + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natBEq := fun h a b => + (H.natBEq (oldContains ``Nat.beq + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natBLE := fun h a b => + (H.natBLE (oldContains ``Nat.ble + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natLAnd := fun h a b => + (H.natLAnd (oldContains ``Nat.land + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natLOr := fun h a b => + (H.natLOr (oldContains ``Nat.lor + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natXor := fun h a b => + (H.natXor (oldContains ``Nat.xor + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natShiftLeft := fun h a b => + (H.natShiftLeft (oldContains ``Nat.shiftLeft + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + natShiftRight := fun h a b => + (H.natShiftRight (oldContains ``Nat.shiftRight + (by simp [VEnv.reflectedPrimitiveNames]) h) a b).mono hle + charOfNat := fun h => H.charOfNat (by + simpa only [lookup ``Char.ofNat + (by simp [VEnv.reflectedPrimitiveNames])] using h) + stringOfList := fun h => by + obtain ⟨hconstant, hnil, hcons⟩ := H.stringOfList (by + simpa only [lookup ``String.ofList + (by simp [VEnv.reflectedPrimitiveNames])] using h) + exact ⟨hconstant, hnil.mono hle, hcons.mono hle⟩ } + +variable! {env env' : VEnv} (henv : env ≤ env') in +theorem VEnv.ContainsLits.mono : ∀ {l}, env.ContainsLits l → env'.ContainsLits l + | .natVal _, ⟨_, H⟩ => ⟨_, henv.constants H⟩ + | .strVal _, ⟨⟨_, H1⟩, ⟨_, H2⟩⟩ => + ⟨⟨_, henv.constants H1⟩, ⟨_, henv.constants H2⟩⟩ + +namespace VEnv.PreludeReady + +theorem boolFalse_lookup {env : VEnv} (H : env.PreludeReady) : + env.constants ``Bool.false = some { uvars := 0, type := VExpr.bool } := by + simpa [LiteralPrelude.boolFalse] using H.boolFalse + +theorem boolTrue_lookup {env : VEnv} (H : env.PreludeReady) : + env.constants ``Bool.true = some { uvars := 0, type := VExpr.bool } := by + simpa [LiteralPrelude.boolTrue] using H.boolTrue + +theorem natZero_lookup {env : VEnv} (H : env.PreludeReady) : + env.constants ``Nat.zero = some { uvars := 0, type := VExpr.nat } := by + simpa [LiteralPrelude.natZero] using H.natZero + +theorem natSucc_lookup {env : VEnv} (H : env.PreludeReady) : + env.constants ``Nat.succ = + some { uvars := 0, type := VExpr.forallE .nat .nat } := by + simpa [LiteralPrelude.natSucc] using H.natSucc + +theorem char_lookup {env : VEnv} (H : env.PreludeReady) : + env.constants ``Char = + some { uvars := 0, type := VExpr.sort (.succ .zero) } := by + simpa [LiteralPrelude.char] using H.char + +theorem charOfNat_lookup {env : VEnv} (H : env.PreludeReady) : + env.constants ``Char.ofNat = + some { uvars := 0, type := VExpr.forallE .nat .char } := by + simpa [LiteralPrelude.charOfNat] using H.charOfNat + +theorem stringOfList_lookup {env : VEnv} (H : env.PreludeReady) : + env.constants ``String.ofList = + some { uvars := 0, type := VExpr.forallE .listChar .string } := by + simpa [LiteralPrelude.stringOfList] using H.stringOfList + +theorem boolLit_hasType {env : VEnv} (H : env.PreludeReady) (b : Bool) : + env.HasType U Γ (.boolLit b) .bool := by + cases b + · exact .const H.boolFalse_lookup nofun rfl + · exact .const H.boolTrue_lookup nofun rfl + +theorem natLit_hasType {env : VEnv} (H : env.PreludeReady) (n : Nat) : + env.HasType U Γ (.natLit n) .nat := by + induction n with + | zero => exact .const H.natZero_lookup nofun rfl + | succ n ih => + simpa [VExpr.natLit, VExpr.natSucc, VExpr.nat, VExpr.instL, VExpr.inst] using + VEnv.HasType.app + (VEnv.HasType.const (ls := []) H.natSucc_lookup (by simp) rfl) ih + +theorem charOfNat_hasType {env : VEnv} (H : env.PreludeReady) : + env.HasType U Γ .charOfNat (.forallE .nat .char) := + .const H.charOfNat_lookup nofun rfl + +theorem listCharNil_hasType {env : VEnv} (H : env.PreludeReady) : + env.HasType U Γ .listCharNil .listChar := by + have hnil : env.constants ``List.nil = some { + uvars := 1 + type := VExpr.forallE (.sort (.succ (.param 0))) + (.app (.const ``List [.param 0]) (.bvar 0)) } := by + simpa [LiteralPrelude.listNil] using H.listNil + exact .app (.const hnil (by simp [VLevel.WF]) rfl) + (.const H.char_lookup nofun rfl) + +theorem listCharCons_hasType {env : VEnv} (H : env.PreludeReady) : + env.HasType U Γ .listCharCons + (.forallE .char <| .forallE .listChar .listChar) := by + have hcons : env.constants ``List.cons = some { + uvars := 1 + type := VExpr.forallE (.sort (.succ (.param 0))) <| + .forallE (.bvar 0) <| + .forallE (.app (.const ``List [.param 0]) (.bvar 1)) + (.app (.const ``List [.param 0]) (.bvar 2)) } := by + simpa [LiteralPrelude.listCons] using H.listCons + exact .app (.const hcons (by simp [VLevel.WF]) rfl) + (.const H.char_lookup nofun rfl) + +theorem listCharLit_hasType {env : VEnv} (H : env.PreludeReady) + (cs : List Char) : env.HasType U Γ (.listCharLit cs) .listChar := by + induction cs with + | nil => exact H.listCharNil_hasType + | cons c cs ih => + exact (H.listCharCons_hasType.app + (H.charOfNat_hasType.app (H.natLit_hasType c.toNat))).app ih + +theorem trLiteral_hasType {env : VEnv} (H : env.PreludeReady) (l : Literal) : + env.HasType U Γ (.trLiteral l) (.literalType l) := by + cases l with + | natVal n => simpa [VExpr.trLiteral, VExpr.literalType] using H.natLit_hasType n + | strVal s => + simpa [VExpr.trLiteral, VExpr.literalType, VExpr.stringOfList, VExpr.string, + VExpr.instL, VExpr.inst] using + VEnv.HasType.app + (VEnv.HasType.const (ls := []) H.stringOfList_lookup (by simp) rfl) + (H.listCharLit_hasType s.toList) + +/-- Exact readiness, not name occurrence alone, makes a direct literal +encoding well-formed. Pattern matching the containment witness ensures the +literal-facing premise is checked against the exact ready lookup. -/ +theorem trLiteral_wf {env : VEnv} (H : env.PreludeReady) (l : Literal) + (hcontains : env.ContainsLits l) : + VExpr.WF env U [] (.trLiteral l) := by + cases l with + | natVal n => + obtain ⟨ci, hci⟩ := hcontains + have : ci = LiteralPrelude.natType.toVConstant := by + exact (Option.some.inj (H.nat.symm.trans hci)).symm + subst ci + exact ⟨_, H.trLiteral_hasType (.natVal n)⟩ + | strVal s => + obtain ⟨⟨charOfNat, hcharOfNat⟩, ⟨stringOfList, hstringOfList⟩⟩ := hcontains + have : charOfNat = LiteralPrelude.charOfNat := by + exact (Option.some.inj (H.charOfNat.symm.trans hcharOfNat)).symm + subst charOfNat + have : stringOfList = LiteralPrelude.stringOfList := by + exact (Option.some.inj (H.stringOfList.symm.trans hstringOfList)).symm + subst stringOfList + exact ⟨_, H.trLiteral_hasType (.strVal s)⟩ + +end VEnv.PreludeReady + +@[simp] theorem VExpr.instL_boolFalse : VExpr.boolFalse.instL ls = VExpr.boolFalse := by + simp [boolFalse, instL] + +@[simp] theorem VExpr.instL_boolTrue : VExpr.boolTrue.instL ls = VExpr.boolTrue := by + simp [boolTrue, instL] + +@[simp] theorem VExpr.instL_boolLit : (VExpr.boolLit b).instL ls = VExpr.boolLit b := by + cases b <;> simp [boolLit] + +@[simp] theorem VExpr.liftN_boolLit : (VExpr.boolLit b).liftN n k = VExpr.boolLit b := by + cases b <;> rfl + +@[simp] theorem VExpr.lift'_boolLit : (VExpr.boolLit b).lift' ρ = VExpr.boolLit b := by + cases b <;> rfl + +@[simp] theorem VExpr.inst_boolLit : (VExpr.boolLit b).inst e k = VExpr.boolLit b := by + cases b <;> rfl + +@[simp] theorem VExpr.instL_natZero : VExpr.natZero.instL ls = .natZero := by + simp [natZero, instL] + +@[simp] theorem VExpr.instL_natSucc : VExpr.natSucc.instL ls = .natSucc := by + simp [natSucc, instL] + +@[simp] theorem VExpr.instL_natLit : (VExpr.natLit n).instL ls = VExpr.natLit n := by + induction n <;> simp [*, natLit, instL] + +@[simp] theorem VExpr.liftN_natLit : (VExpr.natLit a).liftN n k = VExpr.natLit a := by + induction a <;> simp [natLit, natZero, natSucc, VExpr.liftN, *] + +@[simp] theorem VExpr.lift'_natLit : (VExpr.natLit a).lift' ρ = VExpr.natLit a := by + induction a <;> simp [natLit, natZero, natSucc, VExpr.lift', *] + +@[simp] theorem VExpr.inst_natLit : (VExpr.natLit a).inst e k = VExpr.natLit a := by + induction a <;> simp [natLit, natZero, natSucc, VExpr.inst, *] + +@[simp] theorem VExpr.liftN_listCharLit : + (VExpr.listCharLit cs).liftN n k = VExpr.listCharLit cs := by + induction cs <;> + simp [listCharLit, listCharNil, listCharCons, char, charOfNat, VExpr.liftN, *] + +@[simp] theorem VExpr.lift'_listCharLit : + (VExpr.listCharLit cs).lift' ρ = VExpr.listCharLit cs := by + induction cs <;> + simp [listCharLit, listCharNil, listCharCons, char, charOfNat, VExpr.lift', *] + +@[simp] theorem VExpr.inst_listCharLit : + (VExpr.listCharLit cs).inst e k = VExpr.listCharLit cs := by + induction cs <;> + simp [listCharLit, listCharNil, listCharCons, char, charOfNat, VExpr.inst, *] + +@[simp] theorem VExpr.instL_listCharLit : + (VExpr.listCharLit cs).instL ls = VExpr.listCharLit cs := by + induction cs <;> + simp [listCharLit, listCharNil, listCharCons, char, charOfNat, + VExpr.instL, VLevel.inst, *] + +@[simp] theorem VExpr.liftN_trLiteral : + (VExpr.trLiteral l).liftN n k = VExpr.trLiteral l := by + cases l <;> simp [trLiteral, stringOfList, VExpr.liftN] + +@[simp] theorem VExpr.lift'_trLiteral : + (VExpr.trLiteral l).lift' ρ = VExpr.trLiteral l := by + cases l <;> simp [trLiteral, stringOfList, VExpr.lift'] + +@[simp] theorem VExpr.inst_trLiteral : + (VExpr.trLiteral l).inst e k = VExpr.trLiteral l := by + cases l <;> simp [trLiteral, stringOfList, VExpr.inst] + +@[simp] theorem VExpr.instL_trLiteral : + (VExpr.trLiteral l).instL ls = VExpr.trLiteral l := by + cases l <;> simp [trLiteral, stringOfList, VExpr.instL] + +theorem VEnv.HasPrimitives.nat_of_charOfNat (wf : Ordered env) + (henv : env.HasPrimitives) (H : env.contains ``Char.ofNat) : env.contains ``Nat := by + let ⟨_, H⟩ := H + have ⟨_, H⟩ := wf.constWF (henv.charOfNat H ▸ H) + let ⟨⟨_, H⟩, _⟩ := H.forallE_inv wf + let ⟨_, H, _⟩ := H.const_inv (Γ := []) wf (by trivial) + exact ⟨_, H⟩ + +#guard_named_axioms Ix.Theory.Named.VEnv.PreludeReady.mono [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.PreludeReady.addConst [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.PreludeReady.addDefEq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.PreludeReady.trLiteral_wf [propext, Classical.choice, Quot.sound] + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/LocalContext.lean b/Ix/Theory/Named/LocalContext.lean new file mode 100644 index 000000000..43edc5356 --- /dev/null +++ b/Ix/Theory/Named/LocalContext.lean @@ -0,0 +1,150 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Typing.UniqueTyping + +open Ix.Theory (VLevel) + +/-! # Theory local declarations + +The implementation-independent core of a local context. `VLocalDecl` only +mentions Theory expressions; the `Lean.FVarId` bookkeeping used by the +verified Lean-expression translator remains in `Ix.Theory.Named.Verify.VLCtx`. +-/ + +namespace Ix.Theory.Named +open VEnv + +inductive VLocalDecl where + | vlam (type : VExpr) + | vlet (type value : VExpr) + +def VLocalDecl.depth : VLocalDecl → Nat + | .vlam .. => 1 + | .vlet .. => 0 + +def VLocalDecl.value : VLocalDecl → VExpr + | .vlam .. => .bvar 0 + | .vlet _ e => e + +def VLocalDecl.type' : VLocalDecl → VExpr + | .vlam A + | .vlet A _ => A + +def VLocalDecl.type : VLocalDecl → VExpr + | .vlam A => A.lift + | .vlet A _ => A + +def VLocalDecl.lift' : VLocalDecl → Lift → VLocalDecl + | .vlam A, n => .vlam (A.lift' n) + | .vlet A e, n => .vlet (A.lift' n) (e.lift' n) + +def VLocalDecl.liftN : VLocalDecl → Nat → Nat → VLocalDecl + | .vlam A, n, k => .vlam (A.liftN n k) + | .vlet A e, n, k => .vlet (A.liftN n k) (e.liftN n k) + +def VLocalDecl.inst : VLocalDecl → VExpr → (k : Nat := 0) → VLocalDecl + | .vlam A, e₀, k => .vlam (A.inst e₀ k) + | .vlet A e, e₀, k => .vlet (A.inst e₀ k) (e.inst e₀ k) + +def VLocalDecl.instL : VLocalDecl → List VLevel → VLocalDecl + | .vlam A, ls => .vlam (A.instL ls) + | .vlet A e, ls => .vlet (A.instL ls) (e.instL ls) + +def VLocalDecl.WF (env : VEnv) (U : Nat) (Γ : List VExpr) : VLocalDecl → Prop + | .vlam type => env.IsType U Γ type + | .vlet type value => env.HasType U Γ value type + +def VLocalDecl.ClosedN : VLocalDecl → (k : Nat := 0) → Prop + | .vlam A, k => A.ClosedN k + | .vlet A e, k => A.ClosedN k ∧ e.ClosedN k + +variable! (env : VEnv) (U : Nat) (Γ : List VExpr) in +inductive VLocalDecl.IsDefEq : VLocalDecl → VLocalDecl → Prop + | vlam : env.IsDefEq U Γ type₁ type₂ (.sort u) → + VLocalDecl.IsDefEq (.vlam type₁) (.vlam type₂) + | vlet : + env.IsDefEq U Γ value₁ value₂ type₁ → env.IsDefEq U Γ type₁ type₂ (.sort u) → + VLocalDecl.IsDefEq (.vlet type₁ value₁) (.vlet type₂ value₂) + +theorem VLocalDecl.lift'_consN_skipN {d : VLocalDecl} : + d.lift' (.consN (.skipN .refl n) k) = d.liftN n k := by + cases d <;> simp [VLocalDecl.lift', VLocalDecl.liftN, VExpr.lift'_consN_skipN] + +nonrec theorem VLocalDecl.WF.weakN (henv : env.Ordered) (W : Ctx.LiftN n k Γ Γ') : + ∀ {d}, WF env U Γ d → WF env U Γ' (d.liftN n k) + | .vlam _, H | .vlet .., H => H.weakN henv W + +nonrec theorem VLocalDecl.WF.instN (henv : env.Ordered) (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (h₀ : env.HasType U Γ₀ e₀ A₀) : ∀ {d}, WF env U Γ₁ d → WF env U Γ (d.inst e₀ k) + | .vlam _, H | .vlet .., H => H.instN henv W h₀ + +nonrec theorem VLocalDecl.WF.instL {env : VEnv} (hls : ∀ l ∈ ls, l.WF U') : + ∀ {d}, WF env ls.length Γ d → WF env U' (Γ.map (·.instL ls)) (d.instL ls) + | .vlam _, H | .vlet .., H => H.instL hls + +@[simp] theorem VLocalDecl.lift'_depth {d : VLocalDecl} : (d.lift' n).depth = d.depth := by + cases d <;> rfl + +theorem VLocalDecl.lift'_comp {d : VLocalDecl} : + d.lift' (.comp l₁ l₂) = (d.lift' l₁).lift' l₂ := by + cases d <;> simp [VLocalDecl.lift', VExpr.lift'_comp] + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) + (W : Ctx.Lift' n Γ Γ') in +theorem VLocalDecl.weak'_iff : + VLocalDecl.WF env U Γ' (d.lift' n) ↔ VLocalDecl.WF env U Γ d := + match d with + | .vlam .. => IsType.weak'_iff henv hΓ' W + | .vlet .. => HasType.weak'_iff henv hΓ' W + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) + (W : Ctx.LiftN n k Γ Γ') in +theorem VLocalDecl.weakN_iff : + VLocalDecl.WF env U Γ' (d.liftN n k) ↔ VLocalDecl.WF env U Γ d := + match d with + | .vlam .. => IsType.weakN_iff henv hΓ' W + | .vlet .. => HasType.weakN_iff henv hΓ' W + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (IsType env U)) in +theorem VLocalDecl.IsDefEq.refl : + ∀ {d}, VLocalDecl.WF env U Γ d → VLocalDecl.IsDefEq env U Γ d d + | .vlam _, ⟨_, h1⟩ => .vlam h1 + | .vlet .., h1 => let ⟨_, h2⟩ := h1.isType henv hΓ; .vlet h1 h2 + +theorem VLocalDecl.IsDefEq.wf : + VLocalDecl.IsDefEq env U Γ d₁ d₂ → VLocalDecl.WF env U Γ d₁ + | .vlam h3 => ⟨_, h3.hasType.1⟩ + | .vlet h3 _ => h3.hasType.1 + +theorem VLocalDecl.IsDefEq.mono (henv : env ≤ env') : + VLocalDecl.IsDefEq env U Γ d₁ d₂ → VLocalDecl.IsDefEq env' U Γ d₁ d₂ + | .vlam h => .vlam (h.mono henv) + | .vlet h₁ h₂ => .vlet (h₁.mono henv) (h₂.mono henv) + +theorem VLocalDecl.IsDefEq.symm : + VLocalDecl.IsDefEq env U Γ d₁ d₂ → VLocalDecl.IsDefEq env U Γ d₂ d₁ + | .vlam h1 => .vlam h1.symm + | .vlet h1 h2 => .vlet (h2.defeqDF h1.symm) h2.symm + +theorem VLocalDecl.IsDefEq.defeqDFC (henv : Ordered env) + (hΓ : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) : + VLocalDecl.IsDefEq env U Γ₁ d₁ d₂ → VLocalDecl.IsDefEq env U Γ₂ d₁ d₂ + | .vlam h1 => .vlam (h1.defeqDFC henv hΓ) + | .vlet h1 h2 => .vlet (h1.defeqDFC henv hΓ) (h2.defeqDFC henv hΓ) + +#guard_named_axioms Ix.Theory.Named.VLocalDecl.WF.weakN [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VLocalDecl.weakN_iff [ + propext, + sorryAx, + Classical.choice, + Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VLocalDecl.IsDefEq.defeqDFC [propext, Quot.sound] + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Meta.lean b/Ix/Theory/Named/Meta.lean new file mode 100644 index 000000000..eefcfc9b9 --- /dev/null +++ b/Ix/Theory/Named/Meta.lean @@ -0,0 +1,120 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Batteries.Lean.Expr +import Ix.Theory.Named.Std.Control +import Ix.Theory.Named.Std.ToExpr +import Ix.Theory.Named.VEnv +import Ix.Theory.Named.Reference.Inductive.Reduce + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +namespace Meta +open Lean Meta Elab Term + +def expandProj (structName : Name) (idx : Nat) (e : Expr) : MetaM Expr := do + let failed {α} : Unit → MetaM α := fun _ => do + throwError "invalid projection{indentExpr (mkProj structName idx e)}" + let ival ← getConstInfoInduct structName + let [ctor] := ival.ctors | failed () + let ctorInfo ← getConstInfoCtor ctor + unless idx < ctorInfo.numFields do failed () + let args : Array Term ← (Array.range ctorInfo.numFields).mapM fun _ => do + `($(mkIdent (← mkFreshId)):ident) + let args' ← args.mapM fun x => `(Lean.Parser.Term.funBinder| $x) + let casesOn := mkCIdent (mkCasesOnName structName) + TermElabM.run' do + let stx ← `($casesOn:ident $(← e.toSyntax) fun $args'* => $(args[idx]!)) + elabTerm stx (← inferType (.proj structName idx e)) + +partial def expandExpr (e : Expr) : MetaM Expr := + Meta.transform e + (pre := fun + | .mdata _ e => return .visit e + | .proj s i e => return .continue (← expandProj s i e) + | e@(.mvar _) => return .continue (← instantiateMVars e) + | _ => return .continue) + +variable (ls : List Name) (fvarToIdx : FVarIdMap Nat) in +partial def ofExpr : Expr → (k :_:= 0) → MetaM VExpr + | .bvar i, _ => return .bvar i + | .sort u, _ => return .sort (← VLevel.ofLevel ls u) + | .const c us, _ => return .const c (← liftM <| us.mapM (VLevel.ofLevel ls)) + | .app fn arg, k => return .app (← ofExpr fn k) (← ofExpr arg k) + | .lam _ ty body _, k => return .lam (← ofExpr ty k) (← ofExpr body (k+1)) + | .forallE _ ty body _, k => return .forallE (← ofExpr ty k) (← ofExpr body (k+1)) + | .mdata _ e, k => ofExpr e k + | .lit l, k => ofExpr l.toConstructor k + | .letE _ _ value body _, k => return (← ofExpr body (k+1)).inst (← ofExpr value k) + | e@(.proj ..), _ => throwError "invalid expression {e}" + | e@(.mvar ..), _ => throwError "expression contains metavariables {e}" + | .fvar e, k => do + if let some i := fvarToIdx.get? e then return .bvar (i+k) + let lctx ← getLCtx + let some e := (do (← lctx.find? e).value?) | throwError "undeclared free var {Expr.fvar e}" + ofExpr e + +deriving instance ToExpr for VLevel +deriving instance ToExpr for VExpr +deriving instance ToExpr for VConstant +deriving instance ToExpr for VDefEq + +def toVExprWrapper (bis : Option (TSyntaxArray ``Parser.Term.funBinder)) + (x : FVarIdMap Nat → TermElabM α) : TermElabM α := do + withLevelNames [] <| + elabFunBinders (bis.getD #[]) none fun xs _ => + withAutoBoundImplicit <| + x <| + xs.foldr (fun fvar (n, m) => (n+1, m.insert fvar.fvarId! n)) (0, ({}:FVarIdMap Nat)) |>.2 + +def elabForVExpr (e : Expr) : TermElabM Expr := do + let e ← levelMVarToParam e + if ← logUnassignedUsingErrorInfos (← getMVars e) then throwAbortCommand + expandExpr e + +def toVExprCore (bis : Option (TSyntaxArray ``Parser.Term.funBinder)) + (e : Term) : TermElabM (Nat × VExpr) := do + toVExprWrapper bis fun map => do + let e ← elabForVExpr (← elabTerm e none) + let ls := (← getLevelNames).reverse + return (ls.length, ← ofExpr ls map e) + +syntax "vexpr(" atomic(Parser.Term.funBinder* " ⊢ ")? term ")" : term + +elab_rules : term + | `(vexpr($[$bis* ⊢]? $e:term)) => return toExpr (← toVExprCore bis e).2 + +syntax "vconst(" atomic(Parser.Term.funBinder* " ⊢ ")? term ")" : term + +elab_rules : term + | `(vconst($[$bis* ⊢]? $e:term)) => do + let (n, ve) ← toVExprCore bis e + return toExpr (⟨n, ve⟩ : VConstant) + +syntax "vdefeq(" atomic(Parser.Term.funBinder* " ⊢ ")? + atomic(Parser.Term.funBinder* " => ")? term " ≡ " term ")" : term + +elab_rules : term + | `(vdefeq($[$bis* ⊢]? $[$args* =>]? $e₁:term ≡ $e₂:term)) => do + toVExprWrapper bis fun map => do + let (e₁, e₂) ← match args with + | some args => pure (← `(fun $args* => $e₁), ← `(fun $args* => $e₂)) + | none => pure (e₁, e₂) + let e₁ ← elabTerm e₁ none + let ty ← inferType e₁ + let e₂ ← elabTerm e₂ ty + let e₁ ← elabForVExpr e₁ + let e₂ ← elabForVExpr e₂ + let ty ← elabForVExpr ty + let ls := (← getLevelNames).reverse + return toExpr { + uvars := ls.length + lhs := ← ofExpr ls map e₁ + rhs := ← ofExpr ls map e₂ + type := ← ofExpr ls map ty + : VDefEq } diff --git a/Ix/Theory/Named/MutualInductiveFixtures.lean b/Ix/Theory/Named/MutualInductiveFixtures.lean new file mode 100644 index 000000000..23cfbdb48 --- /dev/null +++ b/Ix/Theory/Named/MutualInductiveFixtures.lean @@ -0,0 +1,199 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Inductive +import Ix.Theory.Named.Meta + +/-! +# Mutual public-generation fixtures + +These real kernel declarations pin shared parameters, per-family +indices/results, constructor order, and cross-family recursive target +ordinals at the `VInductDecl.CheckedBlock` boundary, then exercise the +block-wide public generation transaction added by Spec-08C. The Verify mutual +fixture supplies semantic preservation, complete kernel metadata comparison, +and environment replay. +-/ + +namespace Ix.Theory.Named.MutualInductiveFixtures + +open VInductDecl + +universe u + +/-! ## Unindexed Tree/TreeList -/ + +mutual + +inductive Tree (α : Type u) : Type u where + | leaf : α → Tree α + | node : TreeList α → Tree α + | branch : (α → TreeList α) → Tree α + +inductive TreeList (α : Type u) : Type u where + | nil : TreeList α + | cons : Tree α → TreeList α → TreeList α + +end + +def treeType : VInductiveType where + name := ``Tree + uvars := 1 + type := vconst(type_of% @Tree).type + ctors := [⟨vconst(type_of% @Tree.leaf), ``Tree.leaf⟩, + ⟨vconst(type_of% @Tree.node), ``Tree.node⟩, + ⟨vconst(type_of% @Tree.branch), ``Tree.branch⟩] + +def treeListType : VInductiveType where + name := ``TreeList + uvars := 1 + type := vconst(type_of% @TreeList).type + ctors := [⟨vconst(type_of% @TreeList.nil), ``TreeList.nil⟩, + ⟨vconst(type_of% @TreeList.cons), ``TreeList.cons⟩] + +def treeDecl : VInductDecl := + ⟨1, 1, [treeType, treeListType]⟩ + +def treeChecked : treeDecl.CheckedBlock := + treeDecl.checkedBlock?.get (by decide) + +/-- Block-wide generation data for the real unindexed mutual declaration. -/ +def treeGeneration : BlockGenerationChecked treeDecl := + treeDecl.identityBlockGeneration?.get (by decide) + +example : treeChecked.params = [.sort (.succ (.param 0))] := rfl +example : treeChecked.families.values = [treeType, treeListType] := rfl +example : treeChecked.families.ordinals = [0, 1] := rfl +example : treeChecked.families.names = [``Tree, ``TreeList] := rfl +example : treeChecked.families.indices = [[], []] := rfl +example : treeChecked.families.resultLevels = + [.succ (.param 0), .succ (.param 0)] := rfl +example : treeChecked.families.constructorNames = + [[``Tree.leaf, ``Tree.node, ``Tree.branch], + [``TreeList.nil, ``TreeList.cons]] := rfl +example : treeChecked.families.recursiveTargets = + [[[], [1], [1]], [[], [0, 1]]] := rfl +example : treeChecked.names = + [``Tree, ``TreeList, ``Tree.leaf, ``Tree.node, ``Tree.branch, + ``TreeList.nil, ``TreeList.cons, ``Tree.rec, ``TreeList.rec] := rfl + +example : treeGeneration.families.map (·.raw.name) = + [``Tree, ``TreeList] := rfl +example : treeGeneration.motiveTypes.length = 2 := rfl +example : treeGeneration.minorTypes.length = 5 := rfl +example : treeGeneration.recursors.map (·.name) = + [``Tree.rec, ``TreeList.rec] := rfl +example : treeGeneration.generatedRules.length = 5 := rfl + +example : treeChecked.families.constructors[0][1].recursive[0].fieldIndex = 0 := rfl +example : treeChecked.families.constructors[0][1].recursive[0].targetType = 1 := rfl +example : treeChecked.families.constructors[0][2].recursive[0].fieldIndex = 0 := rfl +example : treeChecked.families.constructors[0][2].recursive[0].binders.length = 1 := rfl +example : treeChecked.families.constructors[0][2].recursive[0].targetType = 1 := rfl +example : treeChecked.families.constructors[1][1].recursive[0].targetType = 0 := rfl +example : treeChecked.families.constructors[1][1].recursive[1].targetType = 1 := rfl + +/-! ## Indexed mutual block -/ + +mutual + +inductive IndexedTree (α : Type u) : Nat → Type u where + | leaf : α → IndexedTree α .zero + | node {n : Nat} : IndexedTreeList α n → IndexedTree α (.succ n) + +inductive IndexedTreeList (α : Type u) : Nat → Type u where + | nil : IndexedTreeList α .zero + | cons {n : Nat} : + IndexedTree α n → IndexedTreeList α n → IndexedTreeList α (.succ n) + +end + +def indexedTreeType : VInductiveType where + name := ``IndexedTree + uvars := 1 + type := vconst(type_of% @IndexedTree).type + ctors := [⟨vconst(type_of% @IndexedTree.leaf), ``IndexedTree.leaf⟩, + ⟨vconst(type_of% @IndexedTree.node), ``IndexedTree.node⟩] + +def indexedTreeListType : VInductiveType where + name := ``IndexedTreeList + uvars := 1 + type := vconst(type_of% @IndexedTreeList).type + ctors := [⟨vconst(type_of% @IndexedTreeList.nil), ``IndexedTreeList.nil⟩, + ⟨vconst(type_of% @IndexedTreeList.cons), ``IndexedTreeList.cons⟩] + +def indexedTreeDecl : VInductDecl := + ⟨1, 1, [indexedTreeType, indexedTreeListType]⟩ + +def indexedTreeChecked : indexedTreeDecl.CheckedBlock := + indexedTreeDecl.checkedBlock?.get (by decide) + +/-- Block-wide generation data for the real indexed mutual declaration. -/ +def indexedTreeGeneration : BlockGenerationChecked indexedTreeDecl := + indexedTreeDecl.identityBlockGeneration?.get (by decide) + +example : indexedTreeChecked.params = [.sort (.succ (.param 0))] := rfl +example : indexedTreeChecked.families.values = + [indexedTreeType, indexedTreeListType] := rfl +example : indexedTreeChecked.families.ordinals = [0, 1] := rfl +example : indexedTreeChecked.families.names = + [``IndexedTree, ``IndexedTreeList] := rfl +example : indexedTreeChecked.families.indices = + [[.const ``Nat []], [.const ``Nat []]] := rfl +example : indexedTreeChecked.families.resultLevels = + [.succ (.param 0), .succ (.param 0)] := rfl +example : indexedTreeChecked.families.constructorNames = + [[``IndexedTree.leaf, ``IndexedTree.node], + [``IndexedTreeList.nil, ``IndexedTreeList.cons]] := rfl +example : indexedTreeChecked.families.recursiveTargets = + [[[], [1]], [[], [0, 1]]] := rfl + +example : indexedTreeGeneration.families.map (·.raw.name) = + [``IndexedTree, ``IndexedTreeList] := rfl +example : indexedTreeGeneration.motiveTypes.length = 2 := rfl +example : indexedTreeGeneration.minorTypes.length = 4 := rfl +example : indexedTreeGeneration.recursors.map (·.name) = + [``IndexedTree.rec, ``IndexedTreeList.rec] := rfl +example : indexedTreeGeneration.generatedRules.length = 4 := rfl + +example : indexedTreeChecked.families.constructors[0][0].resultIndices = + [.const ``Nat.zero []] := rfl +example : indexedTreeChecked.families.constructors[0][1].resultIndices = + [.app (.const ``Nat.succ []) (.bvar 1)] := rfl +example : indexedTreeChecked.families.constructors[1][0].resultIndices = + [.const ``Nat.zero []] := rfl +example : indexedTreeChecked.families.constructors[1][1].resultIndices = + [.app (.const ``Nat.succ []) (.bvar 2)] := rfl +example : indexedTreeChecked.families.constructors[0][1].recursive[0].fieldIndex = 1 := rfl +example : indexedTreeChecked.families.constructors[0][1].recursive[0].targetType = 1 := rfl +example : indexedTreeChecked.families.constructors[0][1].recursive[0].indices = + [.bvar 0] := rfl +example : indexedTreeChecked.families.constructors[1][1].recursive[0].fieldIndex = 1 := rfl +example : indexedTreeChecked.families.constructors[1][1].recursive[0].targetType = 0 := rfl +example : indexedTreeChecked.families.constructors[1][1].recursive[1].fieldIndex = 2 := rfl +example : indexedTreeChecked.families.constructors[1][1].recursive[1].targetType = 1 := rfl + +/-! ## Public block-wide boundary -/ + +example : treeDecl.stage3 = true := rfl +example : indexedTreeDecl.stage3 = true := rfl +example : VEnv.empty.addInduct treeDecl = + VEnv.empty.addInductBlockGeneration treeGeneration := rfl +example : VEnv.empty.addInduct indexedTreeDecl = + VEnv.empty.addInductBlockGeneration indexedTreeGeneration := rfl +example : (VEnv.empty.addInduct treeDecl).isSome = true := rfl +example : (VEnv.empty.addInduct indexedTreeDecl).isSome = true := rfl + +#guard_named_axioms Ix.Theory.Named.VInductDecl.checkedBlock? [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveFixtures.treeChecked [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveFixtures.indexedTreeChecked [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CheckedFamilies.values_eq [propext, Quot.sound] + +end Ix.Theory.Named.MutualInductiveFixtures diff --git a/Ix/Theory/Named/NOTICE b/Ix/Theory/Named/NOTICE new file mode 100644 index 000000000..d1c829112 --- /dev/null +++ b/Ix/Theory/Named/NOTICE @@ -0,0 +1,116 @@ +Named kernel specification and implementation proof support +Derived from Lean4Lean (digama0/lean4lean) and the Argument Computer +development line (argumentcomputer/lean4ix), revision +a4188d7c2979378d85c6bb41fdd96c3a48a71371. +Original contributors retain their copyrights. Apache License 2.0; +see LICENSE in this directory. Modified for Ix namespace/import paths +and shared universe semantics. Only the transitive source dependency +closure of the existing kernel/compiler verification was retained. +The standalone checker application, build infrastructure, benchmarks, +and remaining test suite were not imported. + +Original module Local source Original SHA-256 +Lean4Lean.Declaration Ix/Theory/Named/Reference/Declaration.lean cefbf66e2134bec472aa9fd643122a3052bbbfd12ab04e6dbd85fe21e32fb0fa +Lean4Lean.Environment Ix/Theory/Named/Reference/Environment.lean 8de5b7407e225c96ed4116bc46e2e3bad5009b6bfb0cb4f68d4ce2799eff4f11 +Lean4Lean.Environment.Basic Ix/Theory/Named/Reference/Environment/Basic.lean cc39f3a7ae819fed332407c01239dc604a49c8a5dffb379564aade970ff1bcf9 +Lean4Lean.Expr Ix/Theory/Named/Reference/Expr.lean 6cb6f0e5df484973fc282bb86968bb51a1c73ec32d726010b1d7b2133229ac81 +Lean4Lean.ForEachExprV Ix/Theory/Named/Reference/ForEachExprV.lean 260167ef5e882a5bd2482734dd72749b809857dbe99bc2aa32e28c6b4b2fb37e +Lean4Lean.FuelConfig Ix/Theory/Named/Reference/FuelConfig.lean 3ab65df013711059ef867c2683a7516b77cea87a526cf47c1772e9c8a529d35a +Lean4Lean.Inductive.Add Ix/Theory/Named/Reference/Inductive/Add.lean 17dda89d60cac89cba4fc9a4db8233eee8199ce7aee4de337bcd677d076eceb6 +Lean4Lean.Inductive.EliminationTrace Ix/Theory/Named/Reference/Inductive/EliminationTrace.lean d14f7bc2aeb2037701ac12d0217f405b94812fdc441942458656bb543627d095 +Lean4Lean.Inductive.Reduce Ix/Theory/Named/Reference/Inductive/Reduce.lean c6daf4dcec4ffc6c27a64e1054500ec025646d6d15c7c2d61c1323e4928dcc17 +Lean4Lean.Inductive.ValidationTrace Ix/Theory/Named/Reference/Inductive/ValidationTrace.lean 7b4e36920a1286b319237a4db632acfac09e203cb3699835fa7440e31f52bbbd +Lean4Lean.Instantiate Ix/Theory/Named/Reference/Instantiate.lean ae08b31657faf3b54de22688ae287d0bff362c573d6a2dd09f12f417b1975ec2 +Lean4Lean.Level Ix/Theory/Named/Reference/Level.lean 75932c6c1d406cbbf75e60c56b75e4a9b33f743651f5aa50814c7c369edbed76 +Lean4Lean.List Ix/Theory/Named/Reference/List.lean 4ddde2232aff649a50a8d1bec44e9495e2387dd3fcc29833d4f9c67c514431a4 +Lean4Lean.LocalContext Ix/Theory/Named/Reference/LocalContext.lean 5baf7b6b379cbbd3902578c5da9d454558031b52f2af508481bc4647c0d91a1b +Lean4Lean.Primitive Ix/Theory/Named/Reference/Primitive.lean a8407d6fdb55c15225c5535b89a1c647af7b20729adb810b9887372b1a9ea745 +Lean4Lean.PtrEq Ix/Theory/Named/Reference/PtrEq.lean 395e6b6907e548582d9e40e37f5344d6919e597500608c597048e621f27f0aa2 +Lean4Lean.Quot Ix/Theory/Named/Reference/Quot.lean 79c51dae8b2ac0e09537aaabfb32075fe4a9d5dd34a1a78d47a88229a74926c5 +Lean4Lean.Std.Basic Ix/Theory/Named/Std/Basic.lean 885fd60674f7ceec447d20b56f34a2945dccc9d1193041d552162b7220ba6d67 +Lean4Lean.Std.Control Ix/Theory/Named/Std/Control.lean 71dd61bc6bb315f1590ae79e276ada1c0c5c8eb31e67b0f994ed29f92b05fcc2 +Lean4Lean.Std.HashMap Ix/Theory/Named/Std/HashMap.lean 67afa618c36314613b553eb95dafbbf7c5cca01b9e7d8749b4c024de966c37db +Lean4Lean.Std.NodupKeys Ix/Theory/Named/Std/NodupKeys.lean b0a5f079a7f034f0c436de4ca120fd07197775cba26c625d2a2e1c8054ef460e +Lean4Lean.Std.Ord Ix/Theory/Named/Std/Ord.lean 26380558d7e4fd742274d4f4d9396eb2d10feaa0ad945cfd57c0a37b12a04fa4 +Lean4Lean.Std.PersistentHashMap Ix/Theory/Named/Std/PersistentHashMap.lean c619b8962018a8b4fe3afb9fb0ee7c77bb92e75c323fc3f849ed4d8c199a4c59 +Lean4Lean.Std.SMap Ix/Theory/Named/Std/SMap.lean 574b0996076ccb5814ba381f13f288259fbb821abd33c20f9b891bac6c1e1fb0 +Lean4Lean.Std.ToExpr Ix/Theory/Named/Std/ToExpr.lean 5068adbd3d6c0b2d33ec84420efd66e8025dad2b6ed7171b7d10d1453db08e82 +Lean4Lean.Std.VariableBang Ix/Theory/Named/Std/VariableBang.lean 783456566db97120957903fc5beccf549507ed8e1f0fcd76cde4d0175f02a012 +Lean4Lean.Tests.ProjectionExpressibility Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean ee30b121ece1f5ea7ca2bb315b8e02557b75b5ef33a9986edb12b7b7dab76de0 +Lean4Lean.Theory.ConstructorValidityFixtures Ix/Theory/Named/ConstructorValidityFixtures.lean 4743314f7fd0e0323463cc7fd403a68792c5e0dabbdbcaaba9e1289136527cde +Lean4Lean.Theory.Inductive Ix/Theory/Named/Inductive.lean 5cf6f5c19b301396b35d141a90b6b0281ae984e0e64c502d657d6dc15fb5dc57 +Lean4Lean.Theory.InductiveFixtures Ix/Theory/Named/InductiveFixtures.lean 4e663484b880adc47045c4d3760456e3c9192951ff9b0f188eea34eff5adcc55 +Lean4Lean.Theory.Literals Ix/Theory/Named/Literals.lean cfb64f593c6e3643d83d479d29129d0e73522327529143ef41fd62e162d6998a +Lean4Lean.Theory.LocalContext Ix/Theory/Named/LocalContext.lean e31fe96e8ec2e2718c65bd2eb8a4b9c01286d54956d1a4a23ef47b83706c7d1f +Lean4Lean.Theory.Meta Ix/Theory/Named/Meta.lean 37f47b54a8b855ee7f0c4f2a322fb3c7ad319d1749861c386d9b966142f2c8b7 +Lean4Lean.Theory.MutualInductiveFixtures Ix/Theory/Named/MutualInductiveFixtures.lean 907e4cc7a7855eec5b32bf22457baf0eb482b15529e56d8eb2f2369eaaf79414 +Lean4Lean.Theory.NestedInductive Ix/Theory/Named/NestedInductive.lean c88720c864cd7a4c62d44b116779c7ddb93aacd2b9b51c2fea87e4c1afeddfaf +Lean4Lean.Theory.NestedInductiveFixtures Ix/Theory/Named/NestedInductiveFixtures.lean 2b31e2f7691a631007a5a3e4c83227515476c13d812c391e7ab111ceba4b8d99 +Lean4Lean.Theory.Projection Ix/Theory/Named/Projection.lean 9f5108d2192b951a2b8ee05f102fe03bea5c40563f4f10fa27b74c34853884e6 +Lean4Lean.Theory.Quot Ix/Theory/Named/Quot.lean 3742bc54150fb1b410d5807cd64355cc169fd6ea809dbb71662dc9d28a64c617 +Lean4Lean.Theory.SingletonParity Ix/Theory/Named/SingletonParity.lean 018c3ea29f04d2274bd47362ed09d959ab3873abf59f0ad23c79afb03f37eb52 +Lean4Lean.Theory.Typing.Basic Ix/Theory/Named/Typing/Basic.lean 24827047806ee6ffb9af8ed457143cbb6b0c57326557e0f433339840272114a5 +Lean4Lean.Theory.Typing.Env Ix/Theory/Named/Typing/Env.lean 72949fadf8565117631d4ce822a2d44ebd671843e52a70a8617f0c9c85411cfa +Lean4Lean.Theory.Typing.EnvLemmas Ix/Theory/Named/Typing/EnvLemmas.lean bd9f777d16b60d6bfa74e5e4e2dbf2423df1c1478c38970144a849078623e80b +Lean4Lean.Theory.Typing.InductiveCertificate Ix/Theory/Named/Typing/InductiveCertificate.lean ef4b4970be4680efda15c6ed921584f30d174a462c2643c6bb60c43d2248d353 +Lean4Lean.Theory.Typing.InductiveLemmas Ix/Theory/Named/Typing/InductiveLemmas.lean 90bb4f3964705de120018360d7bcf14ab81f05c621fd7c0c0c49539af301fa77 +Lean4Lean.Theory.Typing.InductivePattern Ix/Theory/Named/Typing/InductivePattern.lean 45480de8808c6311c0635ab0afc7fcdbe0c3534558cb1902f7d97d80886c423a +Lean4Lean.Theory.Typing.InductivePatternWF Ix/Theory/Named/Typing/InductivePatternWF.lean 884955ce4111aed9540b7d02ebc2469aa26168a8efa476b2ee1cdd01ee402926 +Lean4Lean.Theory.Typing.Injectivity Ix/Theory/Named/Typing/Injectivity.lean e7233bde95305b46aa1d22d3e13e21aea93f7e3f903eeb46865c226ffe0bba88 +Lean4Lean.Theory.Typing.Lemmas Ix/Theory/Named/Typing/Lemmas.lean f183e28ec58a52dadba983cb53a55537cb9a497d9e8e4f78d2c2ca4cc9427a38 +Lean4Lean.Theory.Typing.Meta Ix/Theory/Named/Typing/Meta.lean 16b0fb88d6719cdd1293108ca2520c1ef2c601819ef5562d0aa7c2d007021d9b +Lean4Lean.Theory.Typing.NestedInductiveLemmas Ix/Theory/Named/Typing/NestedInductiveLemmas.lean f1dcef8e876386abfbebc5a36ca751dafaa75257b7c6c9f506c7447c4be9cd49 +Lean4Lean.Theory.Typing.Pattern Ix/Theory/Named/Typing/Pattern.lean db05a0847000f4d3e2a69f4b053112bfca31dbc2b11082a804052bb44562f4e3 +Lean4Lean.Theory.Typing.QuotLemmas Ix/Theory/Named/Typing/QuotLemmas.lean 63abdab93b43679259fc25df480afa1b2086edc8cf52cca5b08b2f36be847309 +Lean4Lean.Theory.Typing.Strong Ix/Theory/Named/Typing/Strong.lean 266fbcb98287ad2f53c0c7ed11960aaa620471b71d4289def448ec259019d46a +Lean4Lean.Theory.Typing.UniqueTyping Ix/Theory/Named/Typing/UniqueTyping.lean c297cd16f1ec43d6ea4fba930ddd490555cf212d59389f39765beb986dde5a3f +Lean4Lean.Theory.VDecl Ix/Theory/Named/VDecl.lean 94f3032a2aa1e9e71056b1373fb456b242ede7405c88abe593e7f8432f760a66 +Lean4Lean.Theory.VEnv Ix/Theory/Named/VEnv.lean 16c9bb411f7482d5c08585a278b8ad8209eb8deb023bcb77f7bad675825a83a9 +Lean4Lean.Theory.VExpr Ix/Theory/Named/VExpr.lean 469c797a6eaee8883060470e0830dbe56b4b64f7ca91d9ae63304e288849ac8c +Lean4Lean.Theory.VLevel Ix/Theory/Named/VLevel.lean a570dff7d2065ca64acd1bb920628ec332b4e39f18a2dc423cbf3a7bd469ba58 +Lean4Lean.TypeChecker Ix/Theory/Named/Reference/TypeChecker.lean 40f99258932cfa5f2c99a2c2b5f7b59b467c10348cd238b70453f95e61dd7383 +Lean4Lean.Verify.Axioms Ix/Theory/Named/Verify/Axioms.lean 4c890728353a1df1b754b09bec3635b75bbfade362aff83a35005b2f316f5863 +Lean4Lean.Verify.Environment.Basic Ix/Theory/Named/Verify/Environment/Basic.lean 161d0abd5c8f4a8a8a09db2ab3bdcd988171aba2c7dcb4a997bd6a8cb32a89ae +Lean4Lean.Verify.Environment.ConstructorValidation Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean 2ce3772020b93feed5e88a0a27d3dcdcb32801b0aca24c7c1e5fb694d9cf382e +Lean4Lean.Verify.Environment.ConstructorValidityMatrix Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean 4245035c98958b93c3daefa2efd78f1f0c9779d5bd2a5633db0c2f60958b88b7 +Lean4Lean.Verify.Environment.Elimination Ix/Theory/Named/Verify/Environment/Elimination.lean 89365c4a39346bcd7b1f94b7f568a272e4e02b64ff1b897df38f598079890011 +Lean4Lean.Verify.Environment.EliminationFixturesCommon Ix/Theory/Named/Verify/Environment/EliminationFixturesCommon.lean 1a2dbd72b2538f673c5080abd023c639bee0c200f9d2fd832158f312f726e8b9 +Lean4Lean.Verify.Environment.EliminationFixturesEdges Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean 86aaa7338723cdc0005d3646b68c77099ad8e1c113ac283b9d6048783bda4910 +Lean4Lean.Verify.Environment.EliminationFixturesEq Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean 371f2bd76c849048b8c27b741af65214e6345374e09c1658e00eceef0bd5e9d4 +Lean4Lean.Verify.Environment.EliminationFixturesEqNat Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean 08d2a0352b9a7652ee0c3296b8e6de36e3f3d16b44c77fa962855b355412479a +Lean4Lean.Verify.Environment.EliminationFixturesNat Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean 5fc23bf4dacc65a476fa6416fbf548c75b563574aad7d1c670d28df5a27ce541 +Lean4Lean.Verify.Environment.EliminationFixturesOrAnd Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean 993466ee37f03b2f7494116d58dca184614f32308b851d0bceb275ddd4c3a79f +Lean4Lean.Verify.Environment.EliminationFixturesSmall Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean 65d5114cba03dbc1e25b5ec644f35d72ac27dc370a376a37536ffb8c9d4e1409 +Lean4Lean.Verify.Environment.IndexedVecCandidate Ix/Theory/Named/Verify/Environment/IndexedVecCandidate.lean ba5fc7e4d21f85c1fbd091bdcdecc51c7c252a00329c6e4ce41cf703cfbfb280 +Lean4Lean.Verify.Environment.IndexedVecConsReplay Ix/Theory/Named/Verify/Environment/IndexedVecConsReplay.lean 5fc8c9d63d58a208f0318894f9ba77d87cff021f2dc413575da4e8e5ae42d738 +Lean4Lean.Verify.Environment.IndexedVecConstructors Ix/Theory/Named/Verify/Environment/IndexedVecConstructors.lean effb4340d8f020607ef34f0bb0195ee5e4217f15385e0c690b354c1c2aa23b04 +Lean4Lean.Verify.Environment.IndexedVecOuterReplay Ix/Theory/Named/Verify/Environment/IndexedVecOuterReplay.lean b15ebd574638b1f728439045f06b85421402dabfcc1df1e92fda97198d7de7e8 +Lean4Lean.Verify.Environment.IndexedVecSemanticReplay Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean d2793f18d3052acac81951e18e01d5a5a20c3569cae1d831e3064c251bcf05c9 +Lean4Lean.Verify.Environment.InductiveFixtures Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean 5da7e485923a6e5d9db14361844d48c9628f22b7088072d861f9d24e01acd934 +Lean4Lean.Verify.Environment.Lemmas Ix/Theory/Named/Verify/Environment/Lemmas.lean fe1c3fcec718f780e29af9051b62a906b3f6aa53502ac8740d01f8477ab49576 +Lean4Lean.Verify.Environment.MutualInductiveFixtures Ix/Theory/Named/Verify/Environment/MutualInductiveFixtures.lean cab86779e590746367fb013f95ecb48f0a3f86b06a56ccf1ac43ae7fec78514d +Lean4Lean.Verify.Environment.NestedReplay Ix/Theory/Named/Verify/Environment/NestedReplay.lean c76e7291e064a68f64b3d545de4c887fd8321950d514b485832dce76108bfa28 +Lean4Lean.Verify.Environment.NestedRepresentation Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean 7e5cd82cf41d35a6844d2cbc1f5af67ab5ccad33f81e199984e4017348487b2d +Lean4Lean.Verify.Environment.NestedTransformation Ix/Theory/Named/Verify/Environment/NestedTransformation.lean fd1aefd95d4374e0ae87cff11b10c468b7743c822f0f4cbb1a4f3923baee0b0f +Lean4Lean.Verify.Environment.Normalization Ix/Theory/Named/Verify/Environment/Normalization.lean a9df5c28f597dc88f0cc496a1ad8a2c189ef82fddd194007e2bda7de15c27cdc +Lean4Lean.Verify.Environment.NormalizationMatrix Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean 0495afd91d4770ec0dc998431828b370c65b4cc1b894994c06b4a50525b44342 +Lean4Lean.Verify.Environment.SingletonParityMatrix Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean abc03daf11487f774a89f18506995d3e1f45e817f99dcc361219da73dd586322 +Lean4Lean.Verify.Environment.SingletonParityReplay Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean 19cf222cf463ad9882c7c2ce278150678310b00141fa712684cb68061d1761c2 +Lean4Lean.Verify.Expr Ix/Theory/Named/Verify/Expr.lean 520da96e974f708a15b738479cea37bdc3458adaca6523975f69b15f7bf52cd4 +Lean4Lean.Verify.Level Ix/Theory/Named/Verify/Level.lean 66f0ffcb59ae63498e8c6fb9cee87fa4003c67f1628fb87ec7661714975a4e02 +Lean4Lean.Verify.LevelStd Ix/Theory/Named/Verify/LevelStd.lean 8aada81455e9c6a88eba0dcce86e30daf34ec9215e26ae4dfc9f396a49b8f57c +Lean4Lean.Verify.LocalContext Ix/Theory/Named/Verify/LocalContext.lean 91718812c4d727d27f8723e039b5e7d490e03a7d8bb4163ffed26ee1df030fe8 +Lean4Lean.Verify.Name Ix/Theory/Named/Verify/Name.lean 8a3ae08cc776deba9354b28010327470f241e4c924c335dff142b3f8ec326c78 +Lean4Lean.Verify.NameGenerator Ix/Theory/Named/Verify/NameGenerator.lean 3d7305876fcfc487c625aaee8c737a4bdb1a80b62f70a4fc3cfeaf3cf39219af +Lean4Lean.Verify.NormLt Ix/Theory/Named/Verify/NormLt.lean 970149d18191ecbd889136507e6dd68ea43b833b6170ab825b69a90b4561e2f5 +Lean4Lean.Verify.QSort Ix/Theory/Named/Verify/QSort.lean 79cbf8f96fb223526690c12333a095aa87ecf7d889b4ba2abacd328609550b9a +Lean4Lean.Verify.TypeChecker Ix/Theory/Named/Verify/TypeChecker.lean 0a8441fa3354c7002b2b4b7491f04eaac94bd137d7eaaf8a1859bae0af6f58be +Lean4Lean.Verify.TypeChecker.Basic Ix/Theory/Named/Verify/TypeChecker/Basic.lean a9cc58cb6b86a6f84b30f41f520f3b9f26a30bdd56885107efc6f3e03b3df8dc +Lean4Lean.Verify.TypeChecker.InferType Ix/Theory/Named/Verify/TypeChecker/InferType.lean ddc9fa7ec80b958169d6515a92a723dbe6042ca4b3cdd7d6cfcc6fb859b1f90f +Lean4Lean.Verify.TypeChecker.IsDefEq Ix/Theory/Named/Verify/TypeChecker/IsDefEq.lean 3b9d09d09029eec24514e9905dd00c7435ba103717e506a46939818a80a39c9b +Lean4Lean.Verify.TypeChecker.Reduce Ix/Theory/Named/Verify/TypeChecker/Reduce.lean ddc6abecc09ad21769b83b857d11bbecd3859be58debab62360fa9d9a5ec31cf +Lean4Lean.Verify.TypeChecker.WHNF Ix/Theory/Named/Verify/TypeChecker/WHNF.lean 745637e76413130151c0fb21401a3ee10cbb420aa8c9de4203afff147c2bd9cd +Lean4Lean.Verify.Typing.ConditionallyTyped Ix/Theory/Named/Verify/Typing/ConditionallyTyped.lean 2df5d00a10e4497b631a4d2a90b93cf811ab13cbfb735234a5815963928c3255 +Lean4Lean.Verify.Typing.Expr Ix/Theory/Named/Verify/Typing/Expr.lean 2f9cb98009b6dcd0d45ec4b967e22756f4af1a32a4d45949ad5b4152b8e416c5 +Lean4Lean.Verify.Typing.Lemmas Ix/Theory/Named/Verify/Typing/Lemmas.lean ac1a2960dc945d5d9b5b998b438da6dd7ad6160b08a646f3e2c0b56cede54669 +Lean4Lean.Verify.VLCtx Ix/Theory/Named/Verify/VLCtx.lean f99f9fb85d79b2f9acd201323cc493f737285c34c064fc2bc68680c595878aa3 diff --git a/Ix/Theory/Named/NestedInductive.lean b/Ix/Theory/Named/NestedInductive.lean new file mode 100644 index 000000000..2b469231a --- /dev/null +++ b/Ix/Theory/Named/NestedInductive.lean @@ -0,0 +1,534 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Inductive + +open Ix.Theory (VLevel) + +/-! +# Nested-inductive flattening (Spec-09B) + +The Theory mirror of the kernel's `ElimNestedInductive` transformation, +following the committed Spec-09A design +(`Ix.Theory.Named/Verify/Environment/NestedRepresentation.lean`): the stored +payload of a nested declaration is the source `VInductDecl`, and nested +support flows through an additive artifact coupling + +1. the flattened mutual block, an ordinary `VInductDecl` handled by the + existing arbitrary-block analyzer, and +2. one auxiliary specification per auxiliary family — the Theory analog of + the kernel's `aux2nested` map. + +`nestedElimination?` computes both from the source declaration plus the +caller-supplied metadata of the previously declared inductives that are +nested into (`NestedTargetBlock`). Keeping the target metadata an explicit +input keeps this analyzer environment-free, exactly like `checked?`; +`NestedTargetBlock.WF` separately ties the supplied copy to a Theory +environment. + +The transformation mirrors the kernel phase for phase: + +- An application `I Ds is` is a nested occurrence when `I` is a family of a + supplied target block, the spine covers at least `I`'s parameters, and + the parametric arguments `Ds` mention a family of the growing flattened + block. Parametric arguments that also mention a constructor-local binder + reject the declaration (the kernel's "parameters cannot contain local + variables"), and matched occurrences are rewritten without descending + into the emitted replacement, exactly like `Expr.replace`. +- One auxiliary family is created per family of `I`'s block, in `all` + order, with `I`'s family and constructor types level-instantiated at the + occurrence's levels and parameter-instantiated at `Ds`; auxiliary + constructor bodies are queued and flattened by the same loop until the + block is stable. +- Auxiliary names are canonical: `(`_nested` ++ familyName).appendIndexAfter i` + with a global counter, matching the kernel's choice whenever the ambient + environment contains no colliding `_nested.*` constant. The Spec-09A + collision probe shows the choice is erased from all final artifacts, and + in-block collisions are rejected downstream by `blockNamesOK` exactly + where the kernel's `checkName` rejects its own collisions. + +Acceptance (`nestedStage3`) is flattening success plus generation +readiness of the flattened block through the unchanged Spec-08 machinery. +No generated recursor, rule, or environment replay is claimed at this +checkpoint; the restoration substitution over generation artifacts is +Spec-09C's obligation. +-/ + +namespace Ix.Theory.Named + +deriving instance DecidableEq for VConstant +deriving instance DecidableEq for VDefEq +deriving instance DecidableEq for VConstVal +deriving instance DecidableEq for VInductiveType +deriving instance DecidableEq for VInductDecl + +/-- Does `e` mention, through a loose bvar, one of the `k` binders directly +below its root? `d` counts binders passed inside `e` itself. -/ +def VExpr.hasLooseBelow (k : Nat) : VExpr → (d : Nat := 0) → Bool + | .bvar i, d => d ≤ i && i - d < k + | .sort _, _ | .const .., _ => false + | .app e1 e2, d => e1.hasLooseBelow k d || e2.hasLooseBelow k d + | .lam e1 e2, d | .forallE e1 e2, d => + e1.hasLooseBelow k d || e2.hasLooseBelow k (d+1) + +/-- Lower every loose bvar of `e` by `n`. Total; meaningful only when no +loose bvar lies below `n`, which callers establish with `hasLooseBelow`. -/ +def VExpr.lowerN (n : Nat) : VExpr → (d : Nat := 0) → VExpr + | .bvar i, d => if i < d then .bvar i else .bvar (i - n) + | .sort l, _ => .sort l + | .const c ls, _ => .const c ls + | .app e1 e2, d => .app (e1.lowerN n d) (e2.lowerN n d) + | .lam e1 e2, d => .lam (e1.lowerN n d) (e2.lowerN n (d+1)) + | .forallE e1 e2, d => .forallE (e1.lowerN n d) (e2.lowerN n (d+1)) + +namespace VInductDecl + +/-- Simultaneous outermost-first parameter substitution: the first list +element replaces the outermost of the `args.length` innermost loose bvars. +The same shape as `instantiateRev` on the implementation side. -/ +def instRevParams : VExpr → List VExpr → VExpr + | C, [] => C + | C, e :: es => instRevParams (C.inst e es.length) es + +/-- Substitute the leading `np`-binder telescope of `ty` simultaneously at +`args` (outermost parameter first), mirroring the kernel's +`instantiateForallParams`. Fails when `ty` exposes fewer than `np` +binders. -/ +def instTelescope (np : Nat) (ty : VExpr) (args : List VExpr) : + Option VExpr := do + guard (args.length == np) + guard ((VExpr.telN np ty).length == np) + return instRevParams (VExpr.dropN np ty) args + +/-- One previously declared mutual block that nested occurrences may point +into. `families` is the complete block in `all` order, in that block's own +universe parameters; a copy is supplied so the analyzer stays +environment-free, and `NestedTargetBlock.WF` ties the copy to an +environment. -/ +structure NestedTargetBlock where + nparams : Nat + families : List VInductiveType + +/-- The supplied target copy agrees with the environment's stored +constants. -/ +structure NestedTargetBlock.WF (env : VEnv) (block : NestedTargetBlock) : + Prop where + families : ∀ f ∈ block.families, + env.constants f.name = some f.toVConstVal.toVConstant + ctors : ∀ f ∈ block.families, ∀ c ∈ f.ctors, + env.constants c.name = some c.toVConstant + +def NestedTargetsWF (env : VEnv) (targets : List NestedTargetBlock) : Prop := + ∀ t ∈ targets, t.WF env + +/-- One auxiliary family created by nested elimination: the Theory analog +of one `aux2nested` binding. `values` are the parametric arguments `Ds`, +open over the block parameters (innermost bvar = last parameter), in +declaration level-world. -/ +structure NestedAuxSpec where + aux : Name + target : Name + levels : List VLevel + values : List VExpr + deriving DecidableEq + +/-- The nested occurrence this auxiliary family abbreviates: `I Ds`. -/ +def NestedAuxSpec.value (spec : NestedAuxSpec) : VExpr := + (VExpr.const spec.target spec.levels).appN spec.values + +/-- The flattening result: the flattened mutual block plus one auxiliary +specification per auxiliary family, in flattened family order. When the +source contains no nested occurrence, `flat` is the source itself and +`specs` is empty. -/ +structure NestedElimination (source : VInductDecl) where + flat : VInductDecl + specs : List NestedAuxSpec + +namespace ElimNested + +/-- Growing flattening state. `types` extends the source families with the +auxiliary families; `specs` aligns with `types.drop ntypes`. -/ +structure State where + types : Array VInductiveType + specs : Array NestedAuxSpec + nextIdx : Nat := 1 + +variable (targets : List NestedTargetBlock) (uvars np : Nat) + +/-- The target block owning family `c`, ignoring names that are currently +part of the flattened block itself (the kernel only recognizes previously +*declared* inductives). -/ +def findTarget? (st : State) (c : Name) : Option NestedTargetBlock := + if st.types.any (·.name == c) then none + else targets.find? fun t => t.families.any (·.name == c) + +/-- Register the auxiliary families for one first-seen nested occurrence +`I Ds` and return the auxiliary family name standing for `I` itself. +`doms` is the discovering constructor's parameter telescope, and `values` +are the parametric arguments in parameter-world. -/ +def registerAux (st : State) (block : NestedTargetBlock) (I : Name) + (ls : List VLevel) (doms values : List VExpr) : + Option (Name × State) := do + let mut st := st + let mut result := none + for J in block.families do + if J.uvars != ls.length then failure + let auxName := (`_nested ++ J.name).appendIndexAfter st.nextIdx + let auxType ← instTelescope block.nparams (J.type.instL ls) values + let mut auxCtors : List VConstVal := [] + for c in J.ctors do + let ctype ← instTelescope block.nparams (c.type.instL ls) values + auxCtors := auxCtors ++ + [⟨⟨uvars, VExpr.forallN doms ctype⟩, c.name.replacePrefix J.name auxName⟩] + let auxFamily : VInductiveType := + { name := auxName, uvars, type := VExpr.forallN doms auxType + ctors := auxCtors } + st := + { types := st.types.push auxFamily + specs := st.specs.push ⟨auxName, J.name, ls, values⟩ + nextIdx := st.nextIdx + 1 } + if J.name == I then result := some auxName + match result with + | some auxName => return (auxName, st) + | none => none + +/-- Rewrite one constructor-body subterm at binder depth `k`, mirroring +`replaceAllNested`: matched occurrences are replaced without descending +into the replacement; unmatched nodes recurse into their children. -/ +def replace (doms : List VExpr) : + VExpr → (k : Nat) → State → Option (VExpr × State) + | e@(.app f a), k, st => do + match rewrite? e k st with + | some result => result + | none => + let (f', st) ← replace doms f k st + let (a', st) ← replace doms a k st + return (.app f' a', st) + | e@(.const ..), k, st => (rewrite? e k st).getD (some (e, st)) + | .lam ty body, k, st => do + let (ty', st) ← replace doms ty k st + let (body', st) ← replace doms body (k+1) st + return (.lam ty' body', st) + | .forallE ty body, k, st => do + let (ty', st) ← replace doms ty k st + let (body', st) ← replace doms body (k+1) st + return (.forallE ty' body', st) + | e, _, st => some (e, st) + where + /-- `some (some ..)` rewrites the node, `some none` is a hard rejection, + `none` leaves the node to the structural recursion. -/ + rewrite? (e : VExpr) (k : Nat) (st : State) : + Option (Option (VExpr × State)) := do + let .const c ls := VExpr.appHead e | none + let args := e.appArgs [] + let block ← findTarget? targets st c + guard (block.nparams ≤ args.length) + guard (0 < block.nparams) + let ds := args.take block.nparams + let names := st.types.toList.map (·.name) + guard (ds.any (·.hasAnyConst names)) + -- the kernel's "nested inductive datatypes parameters cannot contain + -- local variables" rejection + if ds.any (·.hasLooseBelow k) then return none + let values := ds.map (·.lowerN k) + let key := (VExpr.const c ls).appN values + let rest := args.drop block.nparams + let recover (auxName : Name) (st : State) : VExpr × State := + ((VExpr.const auxName (VLevel.params uvars)).appN + (VExpr.bvarRevRange k np ++ rest), st) + match st.specs.find? (·.value == key) with + | some spec => return some (recover spec.aux st) + | none => + match registerAux uvars st block c ls doms values with + | some (auxName, st) => return some (recover auxName st) + | none => return none + +/-- Flatten every constructor of every block family, including the queued +auxiliary families, until the block is stable. `fuel` mirrors the +kernel's `inductiveFuel` bound on the same loop. -/ +def run (fuel : Nat) (i : Nat) (st : State) : Option State := + match fuel with + | 0 => none + | fuel+1 => + if h : i < st.types.size then + let ty := st.types[i] + let step := ty.ctors.foldlM (init := ([], st)) fun (acc, st) c => do + let doms := VExpr.telN np c.type + guard (doms.length == np) + let (body, st) ← replace targets uvars np doms (VExpr.dropN np c.type) 0 st + return (acc ++ [{ c with type := VExpr.forallN doms body }], st) + match step with + | some (ctors, st) => + run fuel (i+1) { st with types := st.types.set! i { ty with ctors } } + | none => none + else some st + +end ElimNested + +/-- Flatten one source declaration against the supplied target blocks. +Returns the flattened block plus the auxiliary specifications; the +identity result (`flat = source`, no specs) is returned when nothing is +nested. -/ +def nestedElimination? (targets : List NestedTargetBlock) + (source : VInductDecl) (fuel : Nat := 1000) : + Option (NestedElimination source) := do + let st ← ElimNested.run targets source.uvars source.nparams fuel 0 + { types := source.types.toArray, specs := #[] } + return { flat := { source with types := st.types.toList } + specs := st.specs.toList } + +/-- The number of auxiliary families, matching the stored +`InductiveVal.numNested` of an accepted nested declaration. -/ +def NestedElimination.numNested {source : VInductDecl} + (elim : NestedElimination source) : Nat := + elim.specs.length + +/-- A flattened declaration accepted by the unchanged arbitrary-block +machinery: the complete Spec-09B validation gate. Positivity, name, level, +anatomy, and generation-shape checking of the flattened block reuse the +Spec-08 analyzers verbatim. -/ +structure NestedBlockChecked (source : VInductDecl) where + elim : NestedElimination source + generation : BlockGenerationChecked elim.flat + +def nestedBlockChecked? (targets : List NestedTargetBlock) + (source : VInductDecl) (fuel : Nat := 1000) : + Option (NestedBlockChecked source) := do + let elim ← nestedElimination? targets source fuel + let generation ← elim.flat.identityBlockGeneration? + return ⟨elim, generation⟩ + +/-- Structural acceptance for a nested declaration. -/ +def nestedStage3 (targets : List NestedTargetBlock) + (source : VInductDecl) (fuel : Nat := 1000) : Bool := + (nestedBlockChecked? targets source fuel).isSome + +/-! ## Restoration (Spec-09C) + +The restoration substitution σ maps the flattened block's generation +artifacts back to the stored metadata surface: auxiliary family constants +become their nested values, auxiliary constructor constants become the +target block's constructors applied to the instantiated value's own +arguments, and auxiliary recursor constants are renamed onto the main +family's `appendIndexAfter` inventory. On an application spine headed by +an auxiliary family or constructor, the first `nparams` spine arguments +are consumed by the value instantiation, mirroring +`ElimNestedInductive.Result.restoreNested`; generated artifacts always +apply auxiliary constants to at least the block parameters (the kernel +asserts exactly this), so the identity fallback on an under-applied +auxiliary head is unreachable from real artifacts and merely keeps σ +total. -/ + +/-- One σ replacement entry. `value` is already in the level world of the +artifact being restored (`instL`-spliced by the caller for recursor-world +artifacts). -/ +structure RestoreEntry where + aux : Name + np : Nat + value : VExpr + deriving DecidableEq + +def findRestoreCtor (entries : List RestoreEntry) (c : Name) : + Option (RestoreEntry × Name) := + entries.findSome? fun entry => + if entry.aux.isPrefixOf c && c != entry.aux then + some (entry, c.replacePrefix entry.aux .anonymous) + else none + +/-- σ on one expression, bottom-up: a replacement fires at the innermost +spine node where an auxiliary head has collected exactly its block-parameter +count, and enclosing applications extend the already-restored value. On +generated artifacts — where auxiliary constants are always applied to at +least the block parameters and never occur inside another auxiliary spine's +arguments — this coincides with `restoreNested`'s top-down +replace-without-descending pass. `recMap` renames auxiliary recursor +constants and is consulted before the constructor-prefix case, exactly like +`restoreNested`'s `auxRec` map. -/ +def restoreExpr (entries : List RestoreEntry) (recMap : List (Name × Name)) : + VExpr → VExpr + | .bvar i => .bvar i + | .sort l => .sort l + | .lam ty body => .lam (restoreExpr entries recMap ty) (restoreExpr entries recMap body) + | .forallE ty body => + .forallE (restoreExpr entries recMap ty) (restoreExpr entries recMap body) + | .app f a => + let e := VExpr.app (restoreExpr entries recMap f) (restoreExpr entries recMap a) + (restoreSpine e).getD e + | e@(.const ..) => (restoreSpine e).getD e + where + /-- Fire one replacement at a completed spine. The head constant is + still unrestored exactly when no inner node completed its parameter + count. -/ + restoreSpine (e : VExpr) : Option VExpr := + match VExpr.appHead e with + | .const c ls => + let args := e.appArgs [] + match recMap.find? (·.1 == c) with + | some (_, newName) => + if args.isEmpty then some (VExpr.const newName ls) else none + | none => + match entries.find? (·.aux == c) with + | some entry => + if args.length == entry.np then + some (instRevParams entry.value args) + else none + | none => + match findRestoreCtor entries c with + | some (entry, suffix) => + if args.length == entry.np then + let value := instRevParams entry.value args + match VExpr.appHead value with + | .const iname ils => + some ((VExpr.const (iname ++ suffix) ils).appN (value.appArgs [])) + | _ => none + else none + | none => none + | _ => none + +namespace NestedBlockChecked + +variable {source : VInductDecl} + +/-- The main family name owning the restored recursor inventory. -/ +def mainName (_nested : NestedBlockChecked source) : Name := + match source.types with + | ty :: _ => ty.name + | [] => .anonymous + +/-- Auxiliary recursor renaming: the `i`-th auxiliary family's recursor +becomes `mainName.rec_(i+1)`, matching `mkAuxRecNameMap`. -/ +def recMap (nested : NestedBlockChecked source) : List (Name × Name) := + nested.elim.specs.mapIdx fun i spec => + (.str spec.aux "rec", ((.str nested.mainName "rec" : Name)).appendIndexAfter (i + 1)) + +/-- σ entries in declaration level-world (constructor-type restorations). -/ +def declEntries (nested : NestedBlockChecked source) : List RestoreEntry := + nested.elim.specs.map fun spec => + ⟨spec.aux, source.nparams, spec.value⟩ + +/-- σ entries spliced into recursor level-world by the elimination +offset. -/ +def recEntries (nested : NestedBlockChecked source) : List RestoreEntry := + nested.elim.specs.map fun spec => + ⟨spec.aux, source.nparams, + spec.value.instL (VLevel.params' source.uvars + (nested.generation.recUvars - source.uvars))⟩ + +/-- σ on a recursor-world artifact. -/ +def restoreRec (nested : NestedBlockChecked source) (e : VExpr) : VExpr := + restoreExpr nested.recEntries nested.recMap e + +/-- The restored recursor inventory: the flattened block's recursors with +auxiliary names renamed and every type restored. Source-family recursors +keep their `.str name "rec"` names. -/ +def recursors (nested : NestedBlockChecked source) : List VConstVal := + nested.generation.recursors.map fun r => + ⟨⟨r.uvars, nested.restoreRec r.type⟩, + ((nested.recMap.find? (·.1 == r.name)).map (·.2)).getD r.name⟩ + +/-- The restored rule inventory, in the flattened block's globally ordered +rule order. -/ +def generatedRules (nested : NestedBlockChecked source) : List VDefEq := + nested.generation.generatedRules.map fun df => + { df with + lhs := nested.restoreRec df.lhs + rhs := nested.restoreRec df.rhs + type := nested.restoreRec df.type } + +end NestedBlockChecked + +end VInductDecl + +/-- The nested transaction: the four-phase shape of +`addInductBlockGeneration` with the *source* families and constructors as +the stored payload and the *restored* recursors and rules as the generated +artifacts. No auxiliary constant enters the environment. -/ +def VEnv.addInductNested {source : VInductDecl} (env : VEnv) + (nested : source.NestedBlockChecked) : Option VEnv := do + let env ← source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env + let env ← source.blockConstructorConstants.foldlM + (fun env constructor => env.addConst constructor.name constructor.toVConstant) env + let env ← nested.recursors.foldlM + (fun env recursor => env.addConst recursor.name recursor.toVConstant) env + return nested.generatedRules.foldl VEnv.addDefEq env + +namespace VInductDecl + +/-- Chained constant well-formedness along an `addConst` fold: each +constant is well formed in the environment already holding every earlier +one. -/ +def NestedConstsWF (env : VEnv) : List VConstVal → Prop + | [] => True + | c :: cs => c.toVConstant.WF env ∧ + ∀ env', env.addConst c.name c.toVConstant = some env' → + NestedConstsWF env' cs + +/-- Chained rule well-formedness along an `addDefEq` fold. -/ +def NestedRulesWF (env : VEnv) : List VDefEq → Prop + | [] => True + | df :: dfs => df.WF env ∧ NestedRulesWF (env.addDefEq df) dfs + +/-- Semantic input to nested preservation: the four transaction phases are +well formed at their exact insertion environments. The phase environments +are determined by the deterministic constant folds, so each later field +takes the earlier folds as hypotheses; a fixture discharges them by +computation. Inhabiting this package from the flattened block's staged +semantic certificate is the σ-transport route recorded by the Spec-09A +design note; fixtures may equally inhabit it from direct checker +executions on the restored artifacts. -/ +structure NestedBlockChecked.WF {source : VInductDecl} + (nested : NestedBlockChecked source) (env : VEnv) : Prop where + types : NestedConstsWF env source.blockTypeConstants + ctors : ∀ {typeEnv}, + source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env = + some typeEnv → + NestedConstsWF typeEnv source.blockConstructorConstants + recs : ∀ {typeEnv ctorEnv}, + source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env = + some typeEnv → + source.blockConstructorConstants.foldlM + (fun env constructor => env.addConst constructor.name constructor.toVConstant) + typeEnv = some ctorEnv → + NestedConstsWF ctorEnv nested.recursors + rules : ∀ {typeEnv ctorEnv recEnv}, + source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env = + some typeEnv → + source.blockConstructorConstants.foldlM + (fun env constructor => env.addConst constructor.name constructor.toVConstant) + typeEnv = some ctorEnv → + nested.recursors.foldlM + (fun env recursor => env.addConst recursor.name recursor.toVConstant) + ctorEnv = some recEnv → + NestedRulesWF recEnv nested.generatedRules + +end VInductDecl + +/-- Exact phase boundaries of a successful nested transaction. -/ +structure VEnv.AddInductNestedTrace {source : VInductDecl} + (env env' : VEnv) (nested : source.NestedBlockChecked) where + typeEnv : VEnv + ctorEnv : VEnv + recEnv : VEnv + addTypes : + source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env = + some typeEnv + addCtors : + source.blockConstructorConstants.foldlM + (fun env constructor => env.addConst constructor.name constructor.toVConstant) + typeEnv = some ctorEnv + addRecs : + nested.recursors.foldlM + (fun env recursor => env.addConst recursor.name recursor.toVConstant) + ctorEnv = some recEnv + addRules : + nested.generatedRules.foldl VEnv.addDefEq recEnv = env' + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/NestedInductiveFixtures.lean b/Ix/Theory/Named/NestedInductiveFixtures.lean new file mode 100644 index 000000000..8ca84b912 --- /dev/null +++ b/Ix/Theory/Named/NestedInductiveFixtures.lean @@ -0,0 +1,329 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.NestedInductive + +/-! +# Nested flattening fixtures (Spec-09B) + +Executable pins for `nestedElimination?` on the two ladder fixtures — a +universe-polymorphic rose tree through `List` and a nested indexed family +through a `PVec`-style vector — plus the nearest structural rejections. +Every family, constructor, auxiliary specification, and acceptance bit is +compared against a hand-written expected descriptor. The kernel +differential for the same shapes lives in +`Ix.Theory.Named/Verify/Environment/NestedTransformation.lean`. +-/ + +namespace Ix.Theory.Named.NestedInductiveFixtures + +open VInductDecl + +/-! ## Target blocks + +Hand-written copies of the nested-into metadata, in each block's own +universe parameters; the Verify differential checks the same shapes +against Lean's stored metadata. -/ + +/-- `List` as a nested target: one family, one parameter. -/ +def listTarget : NestedTargetBlock where + nparams := 1 + families := + [{ name := `List + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := + [⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.app (.const `List [.param 0]) (.bvar 0))⟩, `List.nil⟩, + ⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) (.bvar 1)) + (.app (.const `List [.param 0]) (.bvar 2))))⟩, `List.cons⟩] }] + +/-- A `PVec`-style indexed vector as a nested target: one parameter, one +`Nat` index, indices spelled with `Nat.zero`/`Nat.succ`. -/ +def pvecTarget : NestedTargetBlock where + nparams := 1 + families := + [{ name := `PVec + uvars := 0 + type := .forallE (.sort (.succ .zero)) + (.forallE (.const `Nat []) (.sort (.succ .zero))) + ctors := + [⟨⟨0, .forallE (.sort (.succ .zero)) + (.app (.app (.const `PVec []) (.bvar 0)) (.const `Nat.zero []))⟩, + `PVec.nil⟩, + ⟨⟨0, .forallE (.sort (.succ .zero)) + (.forallE (.bvar 0) + (.forallE (.const `Nat []) + (.forallE (.app (.app (.const `PVec []) (.bvar 2)) (.bvar 0)) + (.app (.app (.const `PVec []) (.bvar 3)) + (.app (.const `Nat.succ []) (.bvar 1))))))⟩, + `PVec.cons⟩] }] + +/-! ## Rose tree through `List` -/ + +def roseAux : Lean.Name := (`_nested ++ `List).appendIndexAfter 1 + +/-- `inductive Rose (α : Type u) | node : α → List (Rose α) → Rose α` -/ +def roseSource : VInductDecl where + uvars := 1 + nparams := 1 + types := + [{ name := `Rose + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := + [⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) + (.app (.const `Rose [.param 0]) (.bvar 1))) + (.app (.const `Rose [.param 0]) (.bvar 2))))⟩, `Rose.node⟩] }] + +/-- The expected flattened rose block: the rewritten source family plus one +auxiliary family, exactly the shapes pinned against the kernel by the +Spec-09A probes. -/ +def roseFlat : VInductDecl where + uvars := 1 + nparams := 1 + types := + [{ name := `Rose + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := + [⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const roseAux [.param 0]) (.bvar 1)) + (.app (.const `Rose [.param 0]) (.bvar 2))))⟩, `Rose.node⟩] }, + { name := roseAux + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := + [⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.app (.const roseAux [.param 0]) (.bvar 0))⟩, roseAux ++ `nil⟩, + ⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.app (.const `Rose [.param 0]) (.bvar 0)) + (.forallE (.app (.const roseAux [.param 0]) (.bvar 1)) + (.app (.const roseAux [.param 0]) (.bvar 2))))⟩, + roseAux ++ `cons⟩] }] + +/-- The expected auxiliary specification: `List (Rose α)`, open over the +block parameter. -/ +def roseSpec : NestedAuxSpec where + aux := roseAux + target := `List + levels := [.param 0] + values := [.app (.const `Rose [.param 0]) (.bvar 0)] + +def roseElim? : Option (NestedElimination roseSource) := + nestedElimination? [listTarget] roseSource + +#guard roseElim?.isSome +#guard (roseElim?.map fun elim => elim.flat == roseFlat).getD false +#guard (roseElim?.map fun elim => elim.specs == [roseSpec]).getD false +#guard (roseElim?.map (·.numNested)).getD 0 == 1 +#guard roseFlat.stage3 +#guard nestedStage3 [listTarget] roseSource +-- acceptance behavior of the raw analyzers on the source is unchanged +#guard !roseSource.stage3 + +/-! ## Nested indexed family through `PVec` -/ + +def nvAux : Lean.Name := (`_nested ++ `PVec).appendIndexAfter 1 + +/-- `inductive NV | node : (n : Nat) → PVec NV n → NV` -/ +def nvSource : VInductDecl where + uvars := 0 + nparams := 0 + types := + [{ name := `NV + uvars := 0 + type := .sort (.succ .zero) + ctors := + [⟨⟨0, .forallE (.const `Nat []) + (.forallE (.app (.app (.const `PVec []) (.const `NV [])) + (.bvar 0)) + (.const `NV []))⟩, `NV.node⟩] }] + +/-- The expected flattened indexed block: the auxiliary family keeps the +`Nat` index, its `nil` instantiates the index at `Nat.zero`, and its +`cons` retains sibling recursion through `NV` plus the successor index. -/ +def nvFlat : VInductDecl where + uvars := 0 + nparams := 0 + types := + [{ name := `NV + uvars := 0 + type := .sort (.succ .zero) + ctors := + [⟨⟨0, .forallE (.const `Nat []) + (.forallE (.app (.const nvAux []) (.bvar 0)) + (.const `NV []))⟩, `NV.node⟩] }, + { name := nvAux + uvars := 0 + type := .forallE (.const `Nat []) (.sort (.succ .zero)) + ctors := + [⟨⟨0, .app (.const nvAux []) (.const `Nat.zero [])⟩, nvAux ++ `nil⟩, + ⟨⟨0, .forallE (.const `NV []) + (.forallE (.const `Nat []) + (.forallE (.app (.const nvAux []) (.bvar 0)) + (.app (.const nvAux []) + (.app (.const `Nat.succ []) (.bvar 1)))))⟩, + nvAux ++ `cons⟩] }] + +/-- The expected specification: the closed partial application `PVec NV`; +the index argument stays behind on each occurrence. -/ +def nvSpec : NestedAuxSpec where + aux := nvAux + target := `PVec + levels := [] + values := [.const `NV []] + +def nvElim? : Option (NestedElimination nvSource) := + nestedElimination? [pvecTarget] nvSource + +#guard nvElim?.isSome +#guard (nvElim?.map fun elim => elim.flat == nvFlat).getD false +#guard (nvElim?.map fun elim => elim.specs == [nvSpec]).getD false +#guard nvFlat.stage3 +#guard nestedStage3 [pvecTarget] nvSource +#guard !nvSource.stage3 + +/-! ## Nearest structural rejections -/ + +/-- A parametric argument mentioning a constructor-local binder: +`node : (n : Nat) → List (Loose n) → Loose` — the kernel's "parameters +cannot contain local variables" class. Flattening itself rejects. -/ +def looseSource : VInductDecl where + uvars := 0 + nparams := 0 + types := + [{ name := `Loose + uvars := 0 + type := .sort (.succ .zero) + ctors := + [⟨⟨0, .forallE (.const `Nat []) + (.forallE (.app (.const `List [.zero]) + (.app (.const `Loose []) (.bvar 0))) + (.const `Loose []))⟩, `Loose.node⟩] }] + +#guard (nestedElimination? [listTarget] looseSource).isNone +#guard !nestedStage3 [listTarget] looseSource + +/-- A well-scoped but ill-shaped parametric argument: +`node : Bad → List (Bad Nat.zero) → Bad` flattens, but the auxiliary +constructor then mentions `Bad` applied off the parameter spine, which the +unchanged block analyzer rejects. -/ +def badAppSource : VInductDecl where + uvars := 0 + nparams := 0 + types := + [{ name := `Bad + uvars := 0 + type := .sort (.succ .zero) + ctors := + [⟨⟨0, .forallE (.const `Bad []) + (.forallE (.app (.const `List [.zero]) + (.app (.const `Bad []) (.const `Nat.zero []))) + (.const `Bad []))⟩, `Bad.node⟩] }] + +#guard (nestedElimination? [listTarget] badAppSource).isSome +#guard !nestedStage3 [listTarget] badAppSource + +-- Without the `List` target metadata the occurrence is not recognized, +-- the flattened block is the source itself, and the unchanged analyzer +-- rejects the under-a-foreign-head family mention. +#guard (nestedElimination? [] roseSource).isSome +#guard ((nestedElimination? [] roseSource).map + fun elim => elim.flat == roseSource && elim.specs == []).getD false +#guard !nestedStage3 [] roseSource + +/-- A source family occupying the first canonical auxiliary name collides +with the created auxiliary family; `blockNamesOK` rejects the flattened +block exactly where the kernel's `checkName` rejects its own duplicate +insertion. -/ +def collisionSource : VInductDecl where + uvars := 1 + nparams := 1 + types := + [{ name := `Rose + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := + [⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) + (.app (.const `Rose [.param 0]) (.bvar 1))) + (.app (.const `Rose [.param 0]) (.bvar 2))))⟩, `Rose.node⟩] }, + { name := (`_nested ++ `List).appendIndexAfter 1 + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := [] }] + +#guard (nestedElimination? [listTarget] collisionSource).isSome +#guard !nestedStage3 [listTarget] collisionSource + +/-! ## Restoration pins (Spec-09C) + +Structural pins for the restored generation artifacts; the exact +comparison against Lean's stored recursor types and rule RHSs lives in the +Verify differential. -/ + +def roseNested? : Option (NestedBlockChecked roseSource) := + nestedBlockChecked? [listTarget] roseSource + +def nvNested? : Option (NestedBlockChecked nvSource) := + nestedBlockChecked? [pvecTarget] nvSource + +#guard roseNested?.isSome +#guard nvNested?.isSome + +-- the restored recursor inventory: one per source family plus one per +-- auxiliary family, on the main family's `appendIndexAfter` names +#guard (roseNested?.map fun n => n.recursors.map (·.name)).getD [] == + [`Rose.rec, ((.str `Rose "rec" : Lean.Name)).appendIndexAfter 1] +#guard (nvNested?.map fun n => n.recursors.map (·.name)).getD [] == + [`NV.rec, ((.str `NV "rec" : Lean.Name)).appendIndexAfter 1] + +def roseAuxConsts : List Lean.Name := + [roseAux, roseAux ++ `nil, roseAux ++ `cons, .str roseAux "rec"] + +def nvAuxConsts : List Lean.Name := + [nvAux, nvAux ++ `nil, nvAux ++ `cons, .str nvAux "rec"] + +/-- No auxiliary constant survives restoration in any recursor type or +rule component. -/ +def restoredClean {source : VInductDecl} (auxConsts : List Lean.Name) + (nested : NestedBlockChecked source) : Bool := + nested.recursors.all (fun r => !VExpr.hasAnyConst auxConsts r.type) && + nested.generatedRules.all fun df => + !VExpr.hasAnyConst auxConsts df.lhs && + !VExpr.hasAnyConst auxConsts df.rhs && + !VExpr.hasAnyConst auxConsts df.type + +#guard (roseNested?.map (restoredClean roseAuxConsts)).getD false +#guard (nvNested?.map (restoredClean nvAuxConsts)).getD false + +-- the globally flattened rule inventory: one node rule plus the two +-- restored `List`/`PVec` rules +#guard (roseNested?.map fun n => n.generatedRules.length).getD 0 == 3 +#guard (nvNested?.map fun n => n.generatedRules.length).getD 0 == 3 + +-- the nested transaction inserts the source payload and the restored +-- recursors, and no auxiliary constant +def roseNestedEnv? : Option VEnv := do + VEnv.empty.addInductNested (← roseNested?) + +#guard roseNestedEnv?.isSome +#guard (roseNestedEnv?.map fun env => + (env.constants `Rose).isSome && (env.constants `Rose.node).isSome && + (env.constants `Rose.rec).isSome && + (env.constants (((.str `Rose "rec" : Lean.Name)).appendIndexAfter 1)).isSome && + (env.constants roseAux).isNone && + (env.constants (roseAux ++ `cons)).isNone && + (env.constants (.str roseAux "rec")).isNone).getD false + +end Ix.Theory.Named.NestedInductiveFixtures diff --git a/Ix/Theory/Named/Projection.lean b/Ix/Theory/Named/Projection.lean new file mode 100644 index 000000000..b4ed1ed5c --- /dev/null +++ b/Ix/Theory/Named/Projection.lean @@ -0,0 +1,3518 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Typing.InductivePatternWF + +open Ix.Theory (VLevel) + +/-! +# Structure projections + +This module is the consumer-neutral projection boundary. A projection is +not determined by a structure name and field number alone: universe +instantiations, parameters, the constructor telescope, and the generated +recursor/iota package all affect its meaning. `VStructureView` retains that +data from the same checked artifact used by inductive generation. + +Projection terms are encoded with the generated recursor. Earlier +projections occur in the motive of a dependent later projection, so one view +determines both the projected term and its dependent result type. No +projection-function name map or unconstrained metadata witness is involved. +-/ + +namespace Ix.Theory.Named + +open VInductDecl + +/-- Instantiate an outermost-first argument list at a fixed offset. + +The `k` variables below the substituted telescope remain bound. Each +argument is lifted past them before it replaces the then-outermost variable. +This is the operation needed to specialize constructor parameters while +retaining the preceding dependent fields. -/ +def VExpr.instRevAt : VExpr → List VExpr → Nat → VExpr + | e, [], _ => e + | e, a :: as, k => instRevAt (e.inst a (k + as.length)) as k + +theorem VExpr.instRevAt_zero (e : VExpr) (args : List VExpr) : + e.instRevAt args 0 = e.instRev args := by + induction args generalizing e with + | nil => rfl + | cons arg args ih => + simp only [VExpr.instRevAt, VExpr.instRev] + simpa using ih (e := e.inst arg args.length) + +private theorem VExpr.instRevAt_closedN (args : List VExpr) + {C : VExpr} {k : Nat} (hC : C.ClosedN k) : + C.instRevAt args k = C := by + induction args generalizing C with + | nil => rfl + | cons arg args ih => + simp only [VExpr.instRevAt] + rw [hC.instN_eq (by omega)] + exact ih hC + +private theorem VExpr.instRev_forallE_projection + (A B : VExpr) (args : List VExpr) : + VExpr.instRev (.forallE A B) args = + .forallE (VExpr.instRev A args) + (VExpr.instRevAt B args 1) := by + induction args generalizing A B with + | nil => rfl + | cons arg args ih => + simp only [VExpr.instRev, VExpr.inst] + rw [ih] + congr 1 + simp only [VExpr.instRevAt] + rw [show 1 + args.length = args.length + 1 by omega] + +private theorem VExpr.instRevAt_forallE_projection + (A B : VExpr) (args : List VExpr) (k : Nat) : + VExpr.instRevAt (.forallE A B) args k = + .forallE (VExpr.instRevAt A args k) + (VExpr.instRevAt B args (k + 1)) := by + induction args generalizing A B with + | nil => rfl + | cons arg args ih => + simp only [VExpr.instRevAt, VExpr.inst] + rw [ih] + congr 1 + rw [show k + args.length + 1 = k + 1 + args.length by omega] + +private theorem VExpr.instRevAt_forallN_projection + (As : List VExpr) (B : VExpr) (args : List VExpr) (k : Nat) : + VExpr.instRevAt (VExpr.forallN As B) args k = + VExpr.forallN + (As.zipIdx k |>.map fun x => x.1.instRevAt args x.2) + (B.instRevAt args (k + As.length)) := by + induction As generalizing k with + | nil => rfl + | cons A As ih => + simp only [VExpr.forallN, VExpr.instRevAt_forallE_projection, + List.zipIdx, List.map_cons, List.length_cons] + rw [ih] + rw [show k + 1 + As.length = k + (As.length + 1) by omega] + +theorem VExpr.instRev_forallN_projection + (As : List VExpr) (B : VExpr) (args : List VExpr) : + VExpr.instRev (VExpr.forallN As B) args = + VExpr.forallN + (As.zipIdx.map fun x => x.1.instRevAt args x.2) + (B.instRevAt args As.length) := by + cases As with + | nil => simp [VExpr.forallN, VExpr.instRevAt_zero] + | cons A As => + simp only [VExpr.forallN, VExpr.instRev_forallE_projection, + List.zipIdx, List.map_cons, List.length_cons] + rw [VExpr.instRevAt_forallN_projection] + rw [VExpr.instRevAt_zero] + congr 2 + rw [Nat.add_comm] + +/-- Consume a syntactic prefix of dependent `forall` binders, instantiating +them outermost-first. -/ +def VExpr.consumeForalls? : VExpr → List VExpr → Option VExpr + | e, [] => some e + | .forallE _ body, arg :: args => consumeForalls? (body.inst arg) args + | _, _ :: _ => none + +theorem VExpr.consumeForalls?_append (e : VExpr) + (left right : List VExpr) : + e.consumeForalls? (left ++ right) = + (e.consumeForalls? left).bind fun cursor => + cursor.consumeForalls? right := by + induction left generalizing e with + | nil => rfl + | cons arg left ih => + cases e <;> simp [VExpr.consumeForalls?, ih] + +theorem VExpr.instTelN_getElem? (arg : VExpr) (fields : List VExpr) + (k i : Nat) : + (VExpr.instTelN arg fields k)[i]? = + fields[i]?.map fun field => field.inst arg (k + i) := by + induction fields generalizing k i with + | nil => simp [VExpr.instTelN] + | cons field fields ih => + cases i with + | zero => simp [VExpr.instTelN] + | succ i => + simp only [VExpr.instTelN, List.getElem?_cons_succ] + simpa only [Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using ih (k + 1) i + +/-- Consuming `args` from a telescope exposes the next original binder with +exactly those arguments substituted. -/ +theorem VExpr.consumeForalls?_forallN_domain + (fields : List VExpr) (result : VExpr) (args : List VExpr) + (hlen : args.length < fields.length) : + ∃ field body, + fields[args.length]? = some field ∧ + VExpr.consumeForalls? (VExpr.forallN fields result) args = + some (.forallE (field.instRevAt args 0) body) := by + induction args generalizing fields result with + | nil => + cases fields with + | nil => simp at hlen + | cons field fields => + exact ⟨field, VExpr.forallN fields result, rfl, rfl⟩ + | cons arg args ih => + cases fields with + | nil => simp at hlen + | cons field fields => + have hlen' : args.length < + (VExpr.instTelN arg fields 0).length := by + simpa [VExpr.instTelN_length] using hlen + obtain ⟨field', body, hfield', hconsume⟩ := + ih (VExpr.instTelN arg fields 0) + (result.inst arg fields.length) hlen' + rw [VExpr.instTelN_getElem?] at hfield' + obtain ⟨original, horiginal, rfl⟩ := Option.map_eq_some_iff.1 hfield' + refine ⟨original, body, by simpa using horiginal, ?_⟩ + simp only [VExpr.forallN, VExpr.consumeForalls?, + VExpr.instN_forallN] + simp only [Nat.zero_add] + simpa only [VExpr.instRevAt, Nat.zero_add] using hconsume + +@[simp] theorem VExpr.instL_instRevAt (e : VExpr) (as : List VExpr) + (k : Nat) : + (e.instRevAt as k).instL ls = + (e.instL ls).instRevAt (as.map (VExpr.instL ls)) k := by + induction as generalizing e with + | nil => rfl + | cons a as ih => + simp only [VExpr.instRevAt, List.map_cons] + simpa only [VExpr.instL_instN, List.length_map] using + ih (e := e.inst a (k + as.length)) + +private theorem VExpr.instL_lamN_projection (ls : List VLevel) : + ∀ (As : List VExpr) (e : VExpr), + (VExpr.lamN As e).instL ls = + VExpr.lamN (As.map (VExpr.instL ls)) (e.instL ls) + | [], _ => rfl + | _ :: As, e => by + simp only [VExpr.lamN, VExpr.instL, List.map_cons] + rw [VExpr.instL_lamN_projection ls As e] + +private theorem VExpr.liftN_lamN_projection (n : Nat) : + ∀ (As : List VExpr) (e : VExpr) (k : Nat), + (VExpr.lamN As e).liftN n k = + VExpr.lamN (VExpr.liftTelN n As k) + (e.liftN n (k + As.length)) + | [], _, _ => rfl + | _ :: As, e, k => by + simp only [VExpr.lamN, VExpr.liftN, VExpr.liftTelN, + List.length_cons] + rw [VExpr.liftN_lamN_projection n As e (k + 1)] + rw [show k + 1 + As.length = k + (As.length + 1) by omega] + +private theorem VExpr.instN_lamN_projection (a : VExpr) : + ∀ (As : List VExpr) (e : VExpr) (k : Nat), + (VExpr.lamN As e).inst a k = + VExpr.lamN (VExpr.instTelN a As k) + (e.inst a (k + As.length)) + | [], _, _ => rfl + | _ :: As, e, k => by + simp only [VExpr.lamN, VExpr.inst, VExpr.instTelN, + List.length_cons] + rw [VExpr.instN_lamN_projection a As e (k + 1)] + rw [show k + 1 + As.length = k + (As.length + 1) by omega] + +private theorem VExpr.liftN_lift_projection (e : VExpr) (n k : Nat) : + e.lift.liftN n (k + 1) = (e.liftN n k).lift := + (VExpr.lift_liftN' e k).symm + +private theorem VExpr.liftN_liftAt_projection + (e : VExpr) (n k i : Nat) : + (e.liftN 1 i).liftN n (k + 1 + i) = + (e.liftN n (k + i)).liftN 1 i := by + symm + simpa only [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + VExpr.liftN_liftN_comm e 1 n i (k + i) (by omega) + +private theorem VExpr.liftTelN_liftAt_projection (As : List VExpr) + (n k i : Nat) : + VExpr.liftTelN n (VExpr.liftTelN 1 As i) (k + 1 + i) = + VExpr.liftTelN 1 (VExpr.liftTelN n As (k + i)) i := by + induction As generalizing i with + | nil => rfl + | cons A As ih => + simp only [VExpr.liftTelN] + rw [VExpr.liftN_liftAt_projection A n k i] + congr 1 + simpa only [Nat.add_assoc] using ih (i + 1) + +private theorem VExpr.liftTelN_lift_projection (As : List VExpr) + (n k : Nat) : + VExpr.liftTelN n (VExpr.liftTelN 1 As 0) (k + 1) = + VExpr.liftTelN 1 (VExpr.liftTelN n As k) 0 := by + simpa using VExpr.liftTelN_liftAt_projection As n k 0 + +private theorem VExpr.instN_liftAt_projection + (e a : VExpr) (k i : Nat) : + (e.liftN 1 i).inst a (k + 1 + i) = + (e.inst a (k + i)).liftN 1 i := by + symm + simpa only [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + VExpr.liftN_instN_lo 1 e a (k + i) i (by omega) + +private theorem VExpr.instTelN_liftAt_projection (As : List VExpr) + (a : VExpr) (k i : Nat) : + VExpr.instTelN a (VExpr.liftTelN 1 As i) (k + 1 + i) = + VExpr.liftTelN 1 (VExpr.instTelN a As (k + i)) i := by + induction As generalizing i with + | nil => rfl + | cons A As ih => + simp only [VExpr.liftTelN, VExpr.instTelN] + rw [VExpr.instN_liftAt_projection A a k i] + congr 1 + simpa only [Nat.add_assoc] using ih (i + 1) + +private theorem VExpr.instTelN_lift_projection (As : List VExpr) + (a : VExpr) (k : Nat) : + VExpr.instTelN a (VExpr.liftTelN 1 As 0) (k + 1) = + VExpr.liftTelN 1 (VExpr.instTelN a As k) 0 := by + simpa using VExpr.instTelN_liftAt_projection As a k 0 + +private theorem VExpr.instN_instRevAt_lift_projection + (e : VExpr) (args : List VExpr) (a : VExpr) (i : Nat) : + ((e.liftN 1 i).instRevAt args (i + 1)).inst a i = + e.instRevAt args i := by + induction args generalizing e with + | nil => exact VExpr.inst_liftN1 e a i + | cons arg args ih => + simp only [VExpr.instRevAt] + rw [show i + 1 + args.length = args.length + 1 + i by omega, + VExpr.instN_liftAt_projection e arg args.length i] + simpa only [Nat.add_comm] using + ih (e := e.inst arg (args.length + i)) + +private theorem VExpr.instTelN_instRevAt_lift_projection + (fields : List VExpr) (args : List VExpr) (a : VExpr) + (start : Nat) : + VExpr.instTelN a + ((VExpr.liftTelN 1 fields start).zipIdx (start + 1) |>.map + fun x => x.1.instRevAt args x.2) + start = + (fields.zipIdx start |>.map + fun x => x.1.instRevAt args x.2) := by + induction fields generalizing start with + | nil => rfl + | cons field fields ih => + simp only [VExpr.liftTelN, List.zipIdx, List.map_cons, + VExpr.instTelN] + rw [VExpr.instN_instRevAt_lift_projection] + congr 1 + simpa only [Nat.add_assoc] using ih (start + 1) + +private theorem VExpr.inst_liftN_top (e a : VExpr) (n : Nat) : + (e.liftN (n + 1)).inst a n = e.liftN n := by + rw [← VExpr.liftN'_liftN' (e := e) (n1 := n) (n2 := 1) + (k1 := 0) (k2 := n) (Nat.zero_le _) (by omega)] + exact VExpr.inst_liftN (e.liftN n) a + +private theorem VExpr.instRevAt_liftN_len (args : List VExpr) + (e : VExpr) (k : Nat) : + (e.liftN (k + args.length)).instRevAt args k = e.liftN k := by + induction args with + | nil => rfl + | cons arg args ih => + simp only [List.length_cons, VExpr.instRevAt] + rw [show k + (args.length + 1) = (k + args.length) + 1 by omega, + VExpr.inst_liftN_top] + exact ih + +private theorem VExpr.instRevAt_bvar_lt_cons (args : List VExpr) + (arg : VExpr) (k i : Nat) (hi : i < k + args.length) : + (VExpr.bvar i).instRevAt (arg :: args) k = + (VExpr.bvar i).instRevAt args k := by + simp only [VExpr.instRevAt] + congr 1 + simp [VExpr.inst, VExpr.instVar, hi] + +private theorem VExpr.map_instRevAt_bvarRevRange + (args : List VExpr) (k : Nat) : + (VExpr.bvarRevRange k args.length).map + (fun e => e.instRevAt args k) = + args.map (VExpr.liftN k) := by + induction args with + | nil => rfl + | cons arg args ih => + simp only [List.length_cons, VExpr.bvarRevRange, + List.map_cons] + congr 1 + · simp only [VExpr.instRevAt] + rw [show (VExpr.bvar (k + args.length)).inst arg + (k + args.length) = arg.liftN (k + args.length) by + simp [VExpr.inst, VExpr.instVar]] + exact VExpr.instRevAt_liftN_len args arg k + · rw [← ih] + apply List.map_congr_left + intro e he + obtain ⟨i, rfl, _, hi⟩ := VExpr.mem_bvarRevRange he + exact VExpr.instRevAt_bvar_lt_cons args arg k i (by omega) + +private theorem VExpr.instRevAt_appN_projection + (f : VExpr) (es : List VExpr) (args : List VExpr) (k : Nat) : + (VExpr.appN f es).instRevAt args k = + VExpr.appN (f.instRevAt args k) + (es.map fun e => e.instRevAt args k) := by + induction args generalizing f es with + | nil => simp [VExpr.instRevAt, List.map_id'] + | cons arg args ih => + simp only [VExpr.instRevAt, VExpr.instN_appN] + rw [ih] + simp only [List.map_map, Function.comp_def] + +private theorem VExpr.map_instRevAt_closedN (args es : List VExpr) + (k : Nat) (hclosed : ∀ e ∈ es, e.ClosedN k) : + es.map (fun e => e.instRevAt args k) = es := by + induction es with + | nil => rfl + | cons e es ih => + simp only [List.map_cons] + rw [VExpr.instRevAt_closedN args (hclosed e (.head _))] + congr 1 + exact ih (fun e he => hclosed e (.tail _ he)) + +private theorem VExpr.map_instN_closedN (a : VExpr) (es : List VExpr) + (k : Nat) (hclosed : ∀ e ∈ es, e.ClosedN k) : + es.map (fun e => e.inst a k) = es := by + induction es with + | nil => rfl + | cons e es ih => + simp only [List.map_cons] + rw [(hclosed e (.head _)).instN_eq (Nat.le_refl _)] + congr 1 + exact ih (fun e he => hclosed e (.tail _ he)) + +private theorem VExpr.map_instN_liftN_top + (es : List VExpr) (a : VExpr) (n : Nat) : + (es.map (VExpr.liftN (n + 1))).map + (fun e => e.inst a n) = + es.map (VExpr.liftN n) := by + rw [List.map_map] + apply List.map_congr_left + intro e _ + exact VExpr.inst_liftN_top e a n + +private theorem VExpr.projectionMinorBody_shape + (constructorName : Name) (levels : List VLevel) + (params : List VExpr) (m : Nat) (typeFn : VExpr) : + ((VExpr.appN (.bvar m) + [VExpr.appN (.const constructorName levels) + (VExpr.bvarRevRange (m + 1) params.length ++ + VExpr.bvarRevRange 0 m)]).instRevAt params (m + 1)).inst + typeFn m = + .app (typeFn.liftN m) + (VExpr.appN (.const constructorName levels) + (params.map (VExpr.liftN m) ++ + VExpr.bvarRevRange 0 m)) := by + have hmotiveR : (VExpr.bvar m).instRevAt params (m + 1) = + .bvar m := VExpr.instRevAt_closedN params (by + exact Nat.lt_succ_self m) + have hconstR : (VExpr.const constructorName levels).instRevAt + params (m + 1) = .const constructorName levels := + VExpr.instRevAt_closedN params (by trivial) + have hfieldsR := VExpr.map_instRevAt_closedN params + (VExpr.bvarRevRange 0 m) (m + 1) + (bvarRevRange_closedN m 0 (m + 1) (by omega)) + have hmotiveI : (VExpr.bvar m).inst typeFn m = + typeFn.liftN m := by simp [VExpr.inst, VExpr.instVar] + have hconstI : (VExpr.const constructorName levels).inst typeFn m = + .const constructorName levels := by rfl + have hparamsI := VExpr.map_instN_liftN_top params typeFn m + have hfieldsI := VExpr.map_instN_closedN typeFn + (VExpr.bvarRevRange 0 m) m + (bvarRevRange_closedN m 0 m (by omega)) + rw [VExpr.instRevAt_appN_projection, hmotiveR] + simp only [List.map_singleton] + rw [VExpr.instRevAt_appN_projection, hconstR, List.map_append, + VExpr.map_instRevAt_bvarRevRange, hfieldsR] + rw [VExpr.instN_appN, hmotiveI] + simp only [List.map_singleton] + rw [VExpr.instN_appN, hconstI, List.map_append, + hparamsI, hfieldsI] + rfl + +private theorem VExpr.projectionMajorTail_shape + (familyName : Name) (levels : List VLevel) + (params : List VExpr) (typeFn : VExpr) : + (((VExpr.forallE + (VExpr.appN (.const familyName levels) + (VExpr.bvarRevRange 2 params.length)) + (.app (.appN (.bvar 2) []) (.bvar 0))).instRevAt + params 2).inst typeFn 1) = + VExpr.forallE + (VExpr.appN (.const familyName levels) + (params.map (VExpr.liftN 1))) + (.app (typeFn.liftN 2) (.bvar 0)) := by + have hconstR : (VExpr.const familyName levels).instRevAt + params 2 = .const familyName levels := + VExpr.instRevAt_closedN params (by trivial) + have hbodyR : + (VExpr.app (VExpr.appN (.bvar 2) []) (.bvar 0)).instRevAt + params 3 = + VExpr.app (VExpr.appN (.bvar 2) []) (.bvar 0) := + VExpr.instRevAt_closedN params (by + change 2 < 3 ∧ 0 < 3 + omega) + rw [VExpr.instRevAt_forallE_projection, + VExpr.instRevAt_appN_projection, hconstR, + VExpr.map_instRevAt_bvarRevRange, hbodyR] + simp only [VExpr.inst] + congr 1 + · rw [VExpr.instN_appN] + have hconstI : (VExpr.const familyName levels).inst typeFn 1 = + .const familyName levels := by rfl + rw [hconstI, VExpr.map_instN_liftN_top] + +theorem VExpr.liftN_instRevAt (e : VExpr) (as : List VExpr) + (i k n : Nat) : + (e.instRevAt as i).liftN n (k + i) = + (e.liftN n (k + i + as.length)).instRevAt + (as.map fun a => a.liftN n k) i := by + induction as generalizing e with + | nil => simp [VExpr.instRevAt] + | cons a as ih => + simp only [VExpr.instRevAt, List.map_cons] + rw [ih] + simp only [List.length_cons, List.length_map] + rw [show k + i + as.length = k + (i + as.length) by omega, + VExpr.liftN_instN_hi] + congr 3 <;> omega + +theorem VExpr.instN_instRevAt (e : VExpr) (as : List VExpr) + (i k : Nat) (a : VExpr) : + (e.instRevAt as i).inst a (k + i) = + (e.inst a (k + i + as.length)).instRevAt + (as.map fun arg => arg.inst a k) i := by + induction as generalizing e with + | nil => simp [VExpr.instRevAt] + | cons arg as ih => + simp only [VExpr.instRevAt, List.map_cons] + rw [ih] + simp only [List.length_cons, List.length_map] + rw [show k + i + as.length = k + (i + as.length) by omega, + VExpr.inst_inst_hi] + congr 3 <;> omega + +/-- A telescope whose entries have the exact retained sort levels. -/ +inductive VEnv.OnSortTel (env : VEnv) (U : Nat) : + List VExpr → List VExpr → List VLevel → Prop where + | nil : OnSortTel env U Γ [] [] + | cons : + env.HasType U Γ A (.sort u) → + OnSortTel env U (A :: Γ) As us → + OnSortTel env U Γ (A :: As) (u :: us) + +private theorem onCtx_levelWFProjection {env : VEnv} {U : Nat} : + ∀ {Γ : List VExpr}, OnCtx Γ (env.IsType U) → + OnCtx Γ fun _ A => A.LevelWF U + | [], _ => trivial + | _ :: _, ⟨hΓ, ⟨_, hA⟩⟩ => + let hΓ' := onCtx_levelWFProjection hΓ + ⟨hΓ', (hA.levelWF hΓ').1⟩ + +/-- Every retained sort selected from a checked sort telescope is a +well-formed universe at the ambient universe bound. -/ +theorem VEnv.OnSortTel.sortWF {env : VEnv} {U : Nat} + : ∀ {Γ : List VExpr} {As : List VExpr} {us : List VLevel}, + OnCtx Γ (env.IsType U) → env.OnSortTel U Γ As us → + ∀ {i : Nat} {u : VLevel}, us[i]? = some u → u.WF U + | _, [], [], _, .nil, _, _, h => by simp at h + | _, _ :: _, _ :: _, hΓ, .cons hA hT, 0, _, h => by + injection h with h + subst h + exact (hA.levelWF (onCtx_levelWFProjection hΓ)).2.2 + | Γ, A :: As, u₀ :: us, hΓ, .cons hA hT, i + 1, u, h => by + exact VEnv.OnSortTel.sortWF (env := env) (U := U) + (Γ := A :: Γ) (As := As) (us := us) + ⟨hΓ, ⟨u₀, hA⟩⟩ hT (by simpa using h) + +private theorem VEnv.OnTel.monoProjection {env env' : VEnv} + (henv : env ≤ env') (H : env.OnTel U Γ As) : env'.OnTel U Γ As := by + induction As generalizing Γ with + | nil => trivial + | cons _ _ ih => + exact ⟨H.1.mono henv, ih H.2⟩ + +theorem VEnv.OnSortTel.mono {env env' : VEnv} (henv : env ≤ env') + (H : env.OnSortTel U Γ As us) : env'.OnSortTel U Γ As us := by + induction H with + | nil => exact .nil + | cons hA _ ih => exact .cons (hA.mono henv) ih + +/-- Forget the retained sort labels, preserving the underlying telescope +well-formedness judgment. -/ +theorem VEnv.OnSortTel.toOnTel {env : VEnv} : + ∀ {U : Nat} {Γ As : List VExpr} {us : List VLevel}, + env.OnSortTel U Γ As us → env.OnTel U Γ As + | _, _, [], [], .nil => trivial + | _, _, _ :: _, _ :: _, .cons hA hT => + ⟨⟨_, hA⟩, VEnv.OnSortTel.toOnTel hT⟩ + +theorem VEnv.OnSortTel.instL {env : VEnv} {U U' : Nat} + (hlevels : ∀ level ∈ levels, level.WF U') : + ∀ {Γ As us}, env.OnSortTel U Γ As us → + env.OnSortTel U' (Γ.map (VExpr.instL levels)) + (As.map (VExpr.instL levels)) + (us.map (VLevel.inst levels)) + | _, [], [], .nil => .nil + | _, _ :: _, _ :: _, .cons hA hT => + .cons (hA.instL hlevels) (VEnv.OnSortTel.instL hlevels hT) + +theorem VEnv.OnSortTel.weakN {env : VEnv} (henv : env.Ordered) + {U n k : Nat} {Γ Γ' : List VExpr} (W : Ctx.LiftN n k Γ Γ') : + ∀ {As us}, env.OnSortTel U Γ As us → + env.OnSortTel U Γ' (VExpr.liftTelN n As k) us + | [], [], .nil => .nil + | _ :: _, _ :: _, .cons hA hT => + .cons (hA.weakN henv W) + (VEnv.OnSortTel.weakN henv W.succ hT) + +private theorem VEnv.OnSortTel.instN {env : VEnv} (henv : env.Ordered) + {U : Nat} {Γ₀ : List VExpr} {e₀ A₀ : VExpr} + (h₀ : env.HasType U Γ₀ e₀ A₀) : + ∀ {As : List VExpr} {us : List VLevel} {k : Nat} + {Γ Γ' : List VExpr}, + Ctx.InstN Γ₀ e₀ A₀ k Γ Γ' → + env.OnSortTel U Γ As us → + env.OnSortTel U Γ' (VExpr.instTelN e₀ As k) us + | [], [], _, _, _, _, .nil => .nil + | _ :: _, _ :: _, _, _, _, W, .cons hA hT => + .cons (hA.instN henv W h₀) + (VEnv.OnSortTel.instN henv h₀ W.succ hT) + +private theorem VExpr.instRevAt_instTelN_cons + (fields : List VExpr) (a : VExpr) (as : List VExpr) : + ((VExpr.instTelN a fields as.length).zipIdx.map fun (field, i) => + VExpr.instRevAt field as i) = + (fields.zipIdx.map fun (field, i) => + VExpr.instRevAt field (a :: as) i) := by + suffices ∀ (start k : Nat), k = as.length + start → + ((VExpr.instTelN a fields k).zipIdx start |>.map + fun (field, i) => VExpr.instRevAt field as i) = + (fields.zipIdx start |>.map fun (field, i) => + VExpr.instRevAt field (a :: as) i) by + simpa using this 0 as.length (by omega) + intro start k hk + induction fields generalizing start k with + | nil => rfl + | cons field fields ih => + simp only [VExpr.instTelN, List.zipIdx, List.map_cons, + VExpr.instRevAt] + rw [hk] + congr 1 + · congr 2 <;> omega + · exact ih (start + 1) (as.length + start + 1) (by omega) + +theorem VExpr.instRevAt_map_instL_zipIdx + (fields : List VExpr) (levels : List VLevel) + (params : List VExpr) (start : Nat := 0) : + ((fields.map (VExpr.instL levels)).zipIdx start |>.map + fun (field, i) => VExpr.instRevAt field params i) = + (fields.zipIdx start |>.map fun (field, i) => + VExpr.instRevAt (field.instL levels) params i) := by + induction fields generalizing start with + | nil => rfl + | cons field fields ih => + simp only [List.map_cons, List.zipIdx] + congr 1 + exact ih (start + 1) + +private theorem VEnv.OnSortTel.instRevParams {env : VEnv} + (henv : env.Ordered) {U : Nat} : + ∀ {Γ params args fields sorts resultLevel}, + env.SpineWF U Γ (VExpr.forallN params (.sort resultLevel)) + args (.sort resultLevel) → + args.length = params.length → + env.OnSortTel U (params.reverse ++ Γ) fields sorts → + env.OnSortTel U Γ + (fields.zipIdx.map fun (field, i) => + VExpr.instRevAt field args i) sorts + | _, [], [], fields, sorts, _, hspine, _, hfields => by + simpa [VExpr.instRevAt] using hfields + | _, [], _ :: _, _, _, _, _, hlen, _ => by simp at hlen + | Γ, param :: params, arg :: args, fields, sorts, resultLevel, + .cons harg hrest, hlen, hfields => by + have hparams : args.length = params.length := by simpa using hlen + have W := Ctx.InstN.consTel (Γ₀ := Γ) (e₀ := arg) + (A₀ := param) params (.zero) + have hfields' : env.OnSortTel U + ((VExpr.instTelN arg params 0).reverse ++ Γ) + (VExpr.instTelN arg fields params.length) sorts := by + apply VEnv.OnSortTel.instN henv harg W + simpa [List.append_assoc] using hfields + have hrest' : env.SpineWF U Γ + (VExpr.forallN (VExpr.instTelN arg params 0) + (.sort resultLevel)) args (.sort resultLevel) := by + simpa [VExpr.instN_forallN, VExpr.inst] using hrest + have hout := VEnv.OnSortTel.instRevParams henv + hrest' (by simpa [VExpr.instTelN_length] using hparams) hfields' + rw [← hparams, VExpr.instRevAt_instTelN_cons] at hout + exact hout + +/-- Extend a well-formed ambient context by a well-formed telescope. -/ +theorem VEnv.OnTel.toOnCtx {env : VEnv} {U : Nat} : + ∀ {As Γ}, env.OnTel U Γ As → OnCtx Γ (env.IsType U) → + OnCtx (As.reverse ++ Γ) (env.IsType U) + | [], _, _, hΓ => by simpa using hΓ + | A :: As, Γ, ⟨hA, hAs⟩, hΓ => by + simpa [List.append_assoc] using + VEnv.OnTel.toOnCtx hAs (Γ := A :: Γ) ⟨hΓ, hA⟩ + +private theorem VEnv.OnSortTel.closedAt {env : VEnv} {U : Nat} + (henv : env.Ordered) : + ∀ {As us Γ}, env.OnSortTel U Γ As us → CtxClosed Γ → + ∀ {i : Nat} {field : VExpr}, As[i]? = some field → + field.ClosedN (Γ.length + i) + | _, _, _, .nil, _, i, _, h => by simp at h + | _ :: _, _ :: _, Γ, .cons hA hAs, hΓ, 0, _, h => by + simp only [List.getElem?_cons_zero] at h + cases h + simpa using hA.closedN henv hΓ + | A :: As, _ :: _, Γ, .cons hA hAs, hΓ, i + 1, field, h => by + simp only [List.getElem?_cons_succ] at h + have hclosed : A.ClosedN Γ.length := hA.closedN henv hΓ + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + VEnv.OnSortTel.closedAt henv hAs ⟨hΓ, hclosed⟩ h + +private theorem VEnv.OnTel.liftTelN_eq {env : VEnv} {U : Nat} + (henv : env.Ordered) : + ∀ {As Γ}, env.OnTel U Γ As → CtxClosed Γ → ∀ n, + VExpr.liftTelN n As Γ.length = As + | [], _, _, _, _ => rfl + | A :: As, Γ, ⟨hA, hAs⟩, hΓ, n => by + obtain ⟨_, hA⟩ := hA + have hclosed : A.ClosedN Γ.length := hA.closedN henv hΓ + simp only [VExpr.liftTelN, hclosed.liftN_eq (Nat.le_refl _)] + simpa using VEnv.OnTel.liftTelN_eq henv hAs ⟨hΓ, hclosed⟩ n + +private theorem VEnv.OnSortTel.liftTelN_eq {env : VEnv} {U : Nat} + (henv : env.Ordered) : + ∀ {As us Γ}, env.OnSortTel U Γ As us → CtxClosed Γ → ∀ n, + VExpr.liftTelN n As Γ.length = As + | [], [], _, .nil, _, _ => rfl + | A :: As, _ :: us, Γ, .cons hA hAs, hΓ, n => by + have hclosed : A.ClosedN Γ.length := hA.closedN henv hΓ + simp only [VExpr.liftTelN, hclosed.liftN_eq (Nat.le_refl _)] + simpa using VEnv.OnSortTel.liftTelN_eq henv hAs ⟨hΓ, hclosed⟩ n + +/-- The checked, generated description of a nonrecursive structure. + +`generation` supplies the exact family, constructor, recursor, and iota rule +artifacts. The shape fields restrict that general one-family artifact to the +kernel class on which `.proj` is meaningful: no indices, exactly one +constructor, and no recursive constructor arguments. `fieldSorts` records +the motive universe required by each projection; `WF` below ties every entry +to the corresponding dependent constructor field type. -/ +structure VStructureView where + source : VInductDecl + generation : source.GenerationChecked + constructor : NormalizedCtor + constructor_eq : generation.block.ctorPairs = [constructor] + raw_indices_eq : generation.block.rawIndices = [] + checked_indices_eq : generation.block.checked.indices = [] + recursive_eq : constructor.view.recursive = [] + fieldSorts : List VLevel + fieldSorts_length : + fieldSorts.length = (constructor.rawFields source.nparams).length + +namespace VStructureView + +abbrev name (view : VStructureView) : Name := + view.generation.block.sourceType.name + +abbrev constructorName (view : VStructureView) : Name := + view.constructor.raw.name + +def recursorName (view : VStructureView) : Name := + .str view.name "rec" + +abbrev uvars (view : VStructureView) : Nat := view.source.uvars + +abbrev nparams (view : VStructureView) : Nat := view.source.nparams + +abbrev familyType (view : VStructureView) : VExpr := + view.generation.block.sourceType.type + +def constructorParams (view : VStructureView) : List VExpr := + VExpr.telN view.nparams view.constructor.raw.type + +def fields (view : VStructureView) : List VExpr := + view.constructor.rawFields view.nparams + +/-- The instantiated structure type `S.{levels} params`. -/ +def structureType (view : VStructureView) + (levels : List VLevel) (params : List VExpr) : VExpr := + VExpr.appN (.const view.name levels) params + +/-- Specialize declaration universes and constructor parameters, retaining +the preceding field binders of each dependent field. -/ +def specializedFields (view : VStructureView) + (levels : List VLevel) (params : List VExpr) : List VExpr := + view.fields.zipIdx.map fun (field, i) => + VExpr.instRevAt (field.instL levels) params i + +private theorem specializedFieldsAux_liftN + (rawFields : List VExpr) (levels : List VLevel) + (params : List VExpr) (p start n k : Nat) + (hparams : params.length = p) + (hclosed : ∀ (j : Nat) (field : VExpr), + rawFields[j]? = some field → + field.ClosedN (p + start + j)) : + (rawFields.zipIdx start |>.map fun (field, i) => + VExpr.instRevAt (field.instL levels) + (params.map fun param => param.liftN n k) i) = + VExpr.liftTelN n + (rawFields.zipIdx start |>.map fun (field, i) => + VExpr.instRevAt (field.instL levels) params i) + (k + start) := by + induction rawFields generalizing start with + | nil => rfl + | cons field rawFields ih => + have hfield : (field.instL levels).ClosedN (p + start + 0) := + VExpr.ClosedN.instL (ls := levels) (hclosed 0 field (by rfl)) + have hrawLift : + (field.instL levels).liftN n + (k + start + params.length) = field.instL levels := + hfield.liftN_eq (by rw [hparams]; omega) + have hhead := VExpr.liftN_instRevAt + (field.instL levels) params start k n + rw [hrawLift] at hhead + have htail := ih (start := start + 1) + (fun j tailField htailField => by + have := hclosed (j + 1) tailField (by simpa using htailField) + simpa only [Nat.add_assoc, Nat.add_left_comm, + Nat.add_comm] using this) + simp only [List.zipIdx, List.map_cons, VExpr.liftTelN] + rw [← hhead] + exact congrArg + (List.cons (VExpr.liftN n + ((field.instL levels).instRevAt params start) (k + start))) + (by simpa only [Nat.add_assoc] using htail) + +private theorem specializedFieldsAux_instN + (rawFields : List VExpr) (levels : List VLevel) + (params : List VExpr) (p start k : Nat) (a : VExpr) + (hparams : params.length = p) + (hclosed : ∀ (j : Nat) (field : VExpr), + rawFields[j]? = some field → + field.ClosedN (p + start + j)) : + (rawFields.zipIdx start |>.map fun (field, i) => + VExpr.instRevAt (field.instL levels) + (params.map fun param => param.inst a k) i) = + VExpr.instTelN a + (rawFields.zipIdx start |>.map fun (field, i) => + VExpr.instRevAt (field.instL levels) params i) + (k + start) := by + induction rawFields generalizing start with + | nil => rfl + | cons field rawFields ih => + have hfield : (field.instL levels).ClosedN (p + start + 0) := + VExpr.ClosedN.instL (ls := levels) (hclosed 0 field (by rfl)) + have hrawInst : + (field.instL levels).inst a + (k + start + params.length) = field.instL levels := + hfield.instN_eq (by rw [hparams]; omega) + have hhead := VExpr.instN_instRevAt + (field.instL levels) params start k a + rw [hrawInst] at hhead + have htail := ih (start := start + 1) + (fun j tailField htailField => by + have := hclosed (j + 1) tailField (by simpa using htailField) + simpa only [Nat.add_assoc, Nat.add_left_comm, + Nat.add_comm] using this) + simp only [List.zipIdx, List.map_cons, VExpr.instTelN] + rw [← hhead] + exact congrArg + (List.cons (VExpr.inst + ((field.instL levels).instRevAt params start) a (k + start))) + (by simpa only [Nat.add_assoc] using htail) + +/-- Universe arguments supplied to the generated recursor for a projection +whose result type inhabits `Sort fieldSort`. -/ +def projectionLevels (view : VStructureView) + (fieldSort : VLevel) (levels : List VLevel) : List VLevel := + match view.generation.elimination with + | .large => fieldSort :: levels + | .small => levels + +/-- The two expressions generated for one field. `typeFn` is the dependent +field type as a function of the structure value; `projector` is a recursor +program implementing the projection. -/ +structure ProjectionCode where + fieldSort : VLevel + typeFn : VExpr + minor : VExpr + projector : VExpr + +@[ext] theorem ProjectionCode.ext {left right : ProjectionCode} + (fieldSort : left.fieldSort = right.fieldSort) + (typeFn : left.typeFn = right.typeFn) + (minor : left.minor = right.minor) + (projector : left.projector = right.projector) : left = right := by + cases left + cases right + simp_all + +def ProjectionCode.liftN (code : ProjectionCode) + (n k : Nat) : ProjectionCode where + fieldSort := code.fieldSort + typeFn := code.typeFn.liftN n k + minor := code.minor.liftN n k + projector := code.projector.liftN n k + +def ProjectionCode.instN (code : ProjectionCode) + (a : VExpr) (k : Nat) : ProjectionCode where + fieldSort := code.fieldSort + typeFn := code.typeFn.inst a k + minor := code.minor.inst a k + projector := code.projector.inst a k + +def ProjectionCode.instL (code : ProjectionCode) + (ls : List VLevel) : ProjectionCode where + fieldSort := code.fieldSort.inst ls + typeFn := code.typeFn.instL ls + minor := code.minor.instL ls + projector := code.projector.instL ls + +/-- The constructor-headed major used by a projection minor after all fields +have been introduced. -/ +def projectionConstructorApp (view : VStructureView) + (levels : List VLevel) (params fields : List VExpr) : VExpr := + VExpr.appN (.const view.constructorName levels) + (params.map (VExpr.liftN fields.length) ++ + VExpr.bvarRevRange 0 fields.length) + +/-- The one-constructor, nonrecursive minor premise expected by the generated +recursor after parameters and a projection motive have been supplied. -/ +def projectionMinorType (view : VStructureView) + (levels : List VLevel) (params fields : List VExpr) + (typeFn : VExpr) : VExpr := + VExpr.forallN fields + (.app (typeFn.liftN fields.length) + (view.projectionConstructorApp levels params fields)) + +@[simp] theorem projectionLevels_instL (view : VStructureView) + (fieldSort : VLevel) (levels ls : List VLevel) : + (view.projectionLevels fieldSort levels).map (VLevel.inst ls) = + view.projectionLevels (fieldSort.inst ls) + (levels.map (VLevel.inst ls)) := by + unfold projectionLevels + split <;> rfl + +@[simp] theorem structureType_instL (view : VStructureView) + (levels : List VLevel) (params : List VExpr) (ls : List VLevel) : + (view.structureType levels params).instL ls = + view.structureType (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) := by + simp [structureType, VExpr.instL_appN, VExpr.instL] + +@[simp] theorem structureType_liftN (view : VStructureView) + (levels : List VLevel) (params : List VExpr) (n k : Nat) : + (view.structureType levels params).liftN n k = + view.structureType levels + (params.map fun param => param.liftN n k) := by + simp [structureType, VExpr.liftN_appN, VExpr.liftN] + +@[simp] theorem structureType_instN (view : VStructureView) + (levels : List VLevel) (params : List VExpr) (a : VExpr) (k : Nat) : + (view.structureType levels params).inst a k = + view.structureType levels + (params.map fun param => param.inst a k) := by + simp [structureType, VExpr.instN_appN, VExpr.inst] + +@[simp] theorem specializedFields_instL (view : VStructureView) + (levels : List VLevel) (params : List VExpr) (ls : List VLevel) : + (view.specializedFields levels params).map (VExpr.instL ls) = + view.specializedFields (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) := by + simp [specializedFields, VExpr.instL_instRevAt, VExpr.instL_instL, Function.comp_def] + +private def projectionCode (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType field : VExpr) (fieldSort : VLevel) (i : Nat) + (previous : List ProjectionCode) : ProjectionCode := + let previousAtMajor := previous.map fun code => + .app code.projector.lift (.bvar 0) + let motiveBody := VExpr.instRevAt + (field.liftN 1 i) previousAtMajor 0 + let typeFn := .lam structType motiveBody + let minor := VExpr.lamN allFields + (.bvar (allFields.length - 1 - i)) + let recursor := .const view.recursorName + (view.projectionLevels fieldSort levels) + let projector := .lam structType <| VExpr.appN recursor <| + params.map (VExpr.liftN 1) ++ + [typeFn.lift, minor.lift, .bvar 0] + { fieldSort, typeFn, minor, projector } + +private theorem projectionCode_liftN (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType field : VExpr) (fieldSort : VLevel) (i : Nat) + (previous : List ProjectionCode) (n k : Nat) + (hprevious : previous.length = i) + (hi : i < allFields.length) : + (projectionCode view levels params allFields structType field + fieldSort i previous).liftN n k = + projectionCode view levels + (params.map fun param => param.liftN n k) + (VExpr.liftTelN n allFields k) + (structType.liftN n k) (field.liftN n (k + i)) fieldSort i + (previous.map fun code => code.liftN n k) := by + have hfieldLift : + (field.liftN 1 i).liftN n (k + 1 + i) = + (field.liftN n (k + i)).liftN 1 i := + VExpr.liftN_liftAt_projection field n k i + have hpreviousLift : + (previous.map fun code => + VExpr.app code.projector.lift (.bvar 0)).map + (fun (e : VExpr) => e.liftN n (k + 1)) = + (previous.map fun code => code.liftN n k).map fun code => + VExpr.app code.projector.lift (.bvar 0) := by + simp [ProjectionCode.liftN, VExpr.liftN, + VExpr.liftN_lift_projection, List.map_map, + Function.comp_def] + have hmotive : + ((field.liftN 1 i).instRevAt + (previous.map fun code => + VExpr.app code.projector.lift (.bvar 0)) 0).liftN n (k + 1) = + ((field.liftN n (k + i)).liftN 1 i).instRevAt + ((previous.map fun code => code.liftN n k).map fun code => + VExpr.app code.projector.lift (.bvar 0)) 0 := by + rw [VExpr.liftN_instRevAt] + rw [List.length_map, hprevious, hfieldLift, hpreviousLift] + have hminorBody : + VExpr.liftN n (.bvar (allFields.length - 1 - i)) + (k + allFields.length) = + .bvar (allFields.length - 1 - i) := by + simp only [VExpr.liftN] + rw [liftVar_lt] + omega + have hminorVar : + liftVar n (allFields.length - 1 - i) + (k + allFields.length) = allFields.length - 1 - i := by + rw [liftVar_lt] + omega + have hminorNestedVar : + liftVar n (liftVar 1 (allFields.length - 1 - i) + allFields.length) (k + 1 + allFields.length) = + liftVar 1 (allFields.length - 1 - i) allFields.length := by + have hinner : liftVar 1 (allFields.length - 1 - i) + allFields.length = allFields.length - 1 - i := + liftVar_lt (by omega) + rw [hinner, liftVar_lt (by omega)] + have hmotiveLift : + (((field.liftN 1 i).instRevAt + (previous.map fun code => + VExpr.app code.projector.lift (.bvar 0)) 0).liftN 1 1).liftN + n (k + 1 + 1) = + (((field.liftN n (k + i)).liftN 1 i).instRevAt + ((previous.map fun code => code.liftN n k).map fun code => + VExpr.app code.projector.lift (.bvar 0)) 0).liftN 1 1 := by + rw [VExpr.liftN_liftAt_projection] + exact congrArg (fun e => e.liftN 1 1) hmotive + apply ProjectionCode.ext + · rfl + · simp [projectionCode, ProjectionCode.liftN, VExpr.liftN, + hmotive] + · simp [projectionCode, ProjectionCode.liftN, + VExpr.liftN_lamN_projection, VExpr.liftTelN_length, + hminorBody] + · simp [projectionCode, ProjectionCode.liftN, VExpr.liftN, + VExpr.liftN_appN, VExpr.liftN_lamN_projection, + VExpr.liftTelN_length, VExpr.liftN_lift_projection, + VExpr.liftTelN_lift_projection, List.map_append, + List.map_map, Function.comp_def, hmotive, hmotiveLift, + hminorNestedVar] + +private theorem projectionCode_instN (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType field : VExpr) (fieldSort : VLevel) (i : Nat) + (previous : List ProjectionCode) (a : VExpr) (k : Nat) + (hprevious : previous.length = i) + (hi : i < allFields.length) : + (projectionCode view levels params allFields structType field + fieldSort i previous).instN a k = + projectionCode view levels + (params.map fun param => param.inst a k) + (VExpr.instTelN a allFields k) + (structType.inst a k) (field.inst a (k + i)) fieldSort i + (previous.map fun code => code.instN a k) := by + have hfieldInst : + (field.liftN 1 i).inst a (k + 1 + i) = + (field.inst a (k + i)).liftN 1 i := + VExpr.instN_liftAt_projection field a k i + have hpreviousInst : + (previous.map fun code => + VExpr.app code.projector.lift (.bvar 0)).map + (fun (e : VExpr) => e.inst a (k + 1)) = + (previous.map fun code => code.instN a k).map fun code => + VExpr.app code.projector.lift (.bvar 0) := by + simp [ProjectionCode.instN, VExpr.inst, VExpr.instVar, + ← VExpr.lift_instN_lo, List.map_map, Function.comp_def] + have hmotive : + ((field.liftN 1 i).instRevAt + (previous.map fun code => + VExpr.app code.projector.lift (.bvar 0)) 0).inst a (k + 1) = + ((field.inst a (k + i)).liftN 1 i).instRevAt + ((previous.map fun code => code.instN a k).map fun code => + VExpr.app code.projector.lift (.bvar 0)) 0 := by + rw [VExpr.instN_instRevAt] + rw [List.length_map, hprevious, hfieldInst, hpreviousInst] + have hminorVar : + VExpr.instVar (allFields.length - 1 - i) a + (k + allFields.length) = + .bvar (allFields.length - 1 - i) := by + simp [VExpr.instVar, show + allFields.length - 1 - i < k + allFields.length by omega] + apply ProjectionCode.ext + · rfl + · simp [projectionCode, ProjectionCode.instN, VExpr.inst, hmotive] + · simp [projectionCode, ProjectionCode.instN, VExpr.inst, + VExpr.instN_lamN_projection, VExpr.instTelN_length, + hminorVar] + · simp [projectionCode, ProjectionCode.instN, VExpr.inst, VExpr.instN_appN, + VExpr.instN_lamN_projection, VExpr.instTelN_length, ← VExpr.lift_instN_lo, List.map_append, + List.map_map, Function.comp_def, hmotive, hminorVar] + +private def projectionCodes.go (view : VStructureView) + (levels : List VLevel) (params : List VExpr) + (allFields : List VExpr) (structType : VExpr) : + List VExpr → List VLevel → Nat → List ProjectionCode → + List ProjectionCode + | field :: fields, fieldSort :: fieldSorts, i, previous => + let code := projectionCode view levels params allFields structType + field fieldSort i previous + code :: projectionCodes.go view levels params allFields structType + fields fieldSorts (i + 1) (previous ++ [code]) + | _, _, _, _ => [] + +private theorem projectionCodes.go_instN (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType : VExpr) (fields : List VExpr) + (fieldSorts : List VLevel) (i : Nat) + (previous : List ProjectionCode) (a : VExpr) (k : Nat) + (hprevious : previous.length = i) + (hfields : i + fields.length = allFields.length) : + (projectionCodes.go view levels params allFields structType + fields fieldSorts i previous).map + (fun code => code.instN a k) = + projectionCodes.go view levels + (params.map fun param => param.inst a k) + (VExpr.instTelN a allFields k) (structType.inst a k) + (VExpr.instTelN a fields (k + i)) fieldSorts i + (previous.map fun code => code.instN a k) := by + induction fields generalizing fieldSorts i previous with + | nil => + cases fieldSorts <;> simp [projectionCodes.go, VExpr.instTelN] + | cons field fields ih => + cases fieldSorts with + | nil => simp [projectionCodes.go] + | cons fieldSort fieldSorts => + have hi : i < allFields.length := by + simp only [List.length_cons] at hfields + omega + have hcode := projectionCode_instN view levels params allFields + structType field fieldSort i previous a k hprevious hi + simp only [projectionCodes.go, List.map_cons, + VExpr.instTelN] + rw [hcode] + congr 1 + have hprevious' : + (previous ++ [projectionCode view levels params allFields + structType field fieldSort i previous]).length = i + 1 := by + simp [hprevious] + have hfields' : i + 1 + fields.length = allFields.length := by + simp only [List.length_cons] at hfields + omega + simpa only [List.map_append, List.map_singleton, + hcode, Nat.add_assoc] using + ih fieldSorts (i + 1) + (previous ++ [projectionCode view levels params allFields + structType field fieldSort i previous]) + hprevious' hfields' + +private theorem projectionCode_instL (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType field : VExpr) (fieldSort : VLevel) (i : Nat) + (previous : List ProjectionCode) (ls : List VLevel) : + (projectionCode view levels params allFields structType field + fieldSort i previous).instL ls = + projectionCode view + (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) + (allFields.map (VExpr.instL ls)) + (structType.instL ls) (field.instL ls) (fieldSort.inst ls) i + (previous.map fun code => code.instL ls) := by + simp [projectionCode, ProjectionCode.instL, VExpr.instL, + VExpr.instL_instRevAt, VExpr.instL_lamN_projection, + VExpr.instL_appN, VExpr.instL_liftN, + List.map_append, List.map_map, Function.comp_def] + +private theorem projectionCodes.go_instL (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType : VExpr) (fields : List VExpr) + (fieldSorts : List VLevel) (i : Nat) + (previous : List ProjectionCode) (ls : List VLevel) : + (projectionCodes.go view levels params allFields structType + fields fieldSorts i previous).map + (fun code => code.instL ls) = + projectionCodes.go view + (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) + (allFields.map (VExpr.instL ls)) + (structType.instL ls) + (fields.map (VExpr.instL ls)) + (fieldSorts.map (VLevel.inst ls)) i + (previous.map fun code => code.instL ls) := by + induction fields generalizing fieldSorts i previous with + | nil => simp [projectionCodes.go] + | cons field fields ih => + cases fieldSorts with + | nil => simp [projectionCodes.go] + | cons fieldSort fieldSorts => + simp only [projectionCodes.go, List.map_cons, + projectionCode_instL] + congr 1 + simpa only [List.map_append, List.map_singleton, + projectionCode_instL] using + ih fieldSorts (i + 1) + (previous ++ [projectionCode view levels params allFields + structType field fieldSort i previous]) + +private theorem projectionCodes.go_liftN (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType : VExpr) (fields : List VExpr) + (fieldSorts : List VLevel) (i : Nat) + (previous : List ProjectionCode) (n k : Nat) + (hprevious : previous.length = i) + (hfields : i + fields.length = allFields.length) : + (projectionCodes.go view levels params allFields structType + fields fieldSorts i previous).map + (fun code => code.liftN n k) = + projectionCodes.go view levels + (params.map fun param => param.liftN n k) + (VExpr.liftTelN n allFields k) (structType.liftN n k) + (VExpr.liftTelN n fields (k + i)) fieldSorts i + (previous.map fun code => code.liftN n k) := by + induction fields generalizing fieldSorts i previous with + | nil => + cases fieldSorts <;> simp [projectionCodes.go, VExpr.liftTelN] + | cons field fields ih => + cases fieldSorts with + | nil => simp [projectionCodes.go] + | cons fieldSort fieldSorts => + have hi : i < allFields.length := by + simp only [List.length_cons] at hfields + omega + have hcode := projectionCode_liftN view levels params allFields + structType field fieldSort i previous n k hprevious hi + simp only [projectionCodes.go, List.map_cons, + VExpr.liftTelN] + rw [hcode] + congr 1 + have hprevious' : + (previous ++ [projectionCode view levels params allFields + structType field fieldSort i previous]).length = i + 1 := by + simp [hprevious] + have hfields' : i + 1 + fields.length = allFields.length := by + simp only [List.length_cons] at hfields + omega + simpa only [List.map_append, List.map_singleton, + hcode, Nat.add_assoc] using + ih fieldSorts (i + 1) + (previous ++ [projectionCode view levels params allFields + structType field fieldSort i previous]) + hprevious' hfields' + +/-- All field projections, in constructor-field order. -/ +def projectionCodes (view : VStructureView) + (levels : List VLevel) (params : List VExpr) : List ProjectionCode := + let fields := view.specializedFields levels params + projectionCodes.go view levels params fields + (view.structureType levels params) fields + (view.fieldSorts.map (VLevel.inst levels)) 0 [] + +private theorem projectionCodes.go_length (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType : VExpr) : + ∀ (fields : List VExpr) (fieldSorts : List VLevel) + (i : Nat) (previous : List ProjectionCode), + fields.length = fieldSorts.length → + (projectionCodes.go view levels params allFields structType + fields fieldSorts i previous).length = fields.length + | [], [], _, _, _ => rfl + | [], _ :: _, _, _, h => by simp at h + | _ :: _, [], _, _, h => by simp at h + | field :: fields, fieldSort :: fieldSorts, i, previous, h => by + simp only [List.length_cons] at h ⊢ + simp only [projectionCodes.go, List.length_cons] + exact congrArg Nat.succ <| + projectionCodes.go_length view levels params allFields structType + fields fieldSorts (i + 1) + (previous ++ [projectionCode view levels params allFields + structType field fieldSort i previous]) (Nat.succ.inj h) + +@[simp] theorem projectionCodes_length (view : VStructureView) + (levels : List VLevel) (params : List VExpr) : + (view.projectionCodes levels params).length = + (view.specializedFields levels params).length := by + apply projectionCodes.go_length + simp [VStructureView.specializedFields, VStructureView.fields, + view.fieldSorts_length] + +/-- Semantic arguments substituted while walking to a later dependent +projection field. -/ +def projectionArgs (view : VStructureView) (levels : List VLevel) + (params : List VExpr) (count : Nat) (major : VExpr) : List VExpr := + (view.projectionCodes levels params).take count |>.map fun code => + .app code.projector major + +/-- Rebuild a structure value from all of its canonical generated +projections. This is syntax only: `ProgramsWF.projectionArgsSpine` below +supplies the rule-independent typing evidence, while any equality between +this term and `major` remains an explicit definitional-equality capability. -/ +def etaRebuild (view : VStructureView) (levels : List VLevel) + (params : List VExpr) (major : VExpr) : VExpr := + VExpr.appN (.const view.constructorName levels) + (params ++ view.projectionArgs levels params + (view.specializedFields levels params).length major) + +@[simp] theorem projectionArgs_length (view : VStructureView) + (levels : List VLevel) (params : List VExpr) (count : Nat) + (major : VExpr) (hcount : count ≤ + (view.projectionCodes levels params).length) : + (view.projectionArgs levels params count major).length = count := by + simp only [projectionArgs, List.length_map, List.length_take] + exact Nat.min_eq_left hcount + +theorem projectionArgs_succ (view : VStructureView) + (levels : List VLevel) (params : List VExpr) (count : Nat) + (major : VExpr) {code : ProjectionCode} + (hcode : (view.projectionCodes levels params)[count]? = some code) : + view.projectionArgs levels params (count + 1) major = + view.projectionArgs levels params count major ++ + [.app code.projector major] := by + simp only [projectionArgs, List.take_add_one, hcode, Option.toList_some, + List.map_append, List.map_singleton] + +private theorem projectionCodes.go_get?_typeFn (view : VStructureView) + (levels : List VLevel) (params allFields : List VExpr) + (structType : VExpr) : + ∀ {fields : List VExpr} {fieldSorts : List VLevel} + {i : Nat} {previous : List ProjectionCode} {j : Nat} + {code : ProjectionCode}, + (projectionCodes.go view levels params allFields structType + fields fieldSorts i previous)[j]? = some code → + ∃ field, + fields[j]? = some field ∧ + code.typeFn = .lam structType + ((field.liftN 1 (i + j)).instRevAt + ((previous ++ + (projectionCodes.go view levels params allFields structType + fields fieldSorts i previous).take j).map fun prior => + .app prior.projector.lift (.bvar 0)) 0) := by + intro fields + induction fields with + | nil => + intro fieldSorts i previous j code h + cases fieldSorts <;> simp [projectionCodes.go] at h + | cons field fields ih => + intro fieldSorts i previous j code h + cases fieldSorts with + | nil => simp [projectionCodes.go] at h + | cons fieldSort fieldSorts => + let head := projectionCode view levels params allFields structType + field fieldSort i previous + cases j with + | zero => + change some head = some code at h + injection h with hcode + subst code + refine ⟨field, rfl, ?_⟩ + simp [head, projectionCode] + | succ j => + simp only [projectionCodes.go, List.getElem?_cons_succ] at h + obtain ⟨tailField, htailField, htypeFn⟩ := + ih (fieldSorts := fieldSorts) (i := i + 1) + (previous := previous ++ [head]) h + refine ⟨tailField, by simpa using htailField, ?_⟩ + have hpref : + previous ++ + (projectionCodes.go view levels params allFields structType + (field :: fields) (fieldSort :: fieldSorts) i previous).take + (j + 1) = + (previous ++ [head]) ++ + (projectionCodes.go view levels params allFields structType + fields fieldSorts (i + 1) + (previous ++ [head])).take j := by + simp [head, projectionCodes.go, List.append_assoc] + rw [hpref] + simpa only [Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using htypeFn + +/-- The generated type function at field `idx` is the corresponding +specialized constructor field with all earlier generated projectors +substituted at the major premise. -/ +theorem projectionCodes_get?_typeFn (view : VStructureView) + (levels : List VLevel) (params : List VExpr) {idx : Nat} + {code : ProjectionCode} + (hcode : (view.projectionCodes levels params)[idx]? = some code) : + ∃ field, + (view.specializedFields levels params)[idx]? = some field ∧ + code.typeFn = .lam (view.structureType levels params) + ((field.liftN 1 idx).instRevAt + ((view.projectionCodes levels params).take idx |>.map fun prior => + .app prior.projector.lift (.bvar 0)) 0) := by + unfold projectionCodes at hcode ⊢ + simpa using projectionCodes.go_get?_typeFn view levels params + (view.specializedFields levels params) + (view.structureType levels params) hcode + +private theorem projectionCodes.go_get?_program_shape + (view : VStructureView) (levels : List VLevel) + (params allFields : List VExpr) (structType : VExpr) : + ∀ {fields : List VExpr} {fieldSorts : List VLevel} + {i : Nat} {previous : List ProjectionCode} {j : Nat} + {code : ProjectionCode}, + (projectionCodes.go view levels params allFields structType + fields fieldSorts i previous)[j]? = some code → + ∃ fieldSort, + fieldSorts[j]? = some fieldSort ∧ + code.fieldSort = fieldSort ∧ + code.minor = VExpr.lamN allFields + (.bvar (allFields.length - 1 - (i + j))) ∧ + code.projector = .lam structType + (VExpr.appN + (.const view.recursorName + (view.projectionLevels code.fieldSort levels)) + (params.map (VExpr.liftN 1) ++ + [code.typeFn.lift, code.minor.lift, .bvar 0])) := by + intro fields + induction fields with + | nil => + intro fieldSorts i previous j code h + cases fieldSorts <;> simp [projectionCodes.go] at h + | cons field fields ih => + intro fieldSorts i previous j code h + cases fieldSorts with + | nil => simp [projectionCodes.go] at h + | cons fieldSort fieldSorts => + let head := projectionCode view levels params allFields structType + field fieldSort i previous + cases j with + | zero => + change some head = some code at h + injection h with hcode + subst code + simp [head, projectionCode] + | succ j => + simp only [projectionCodes.go, List.getElem?_cons_succ] at h + have hout := ih (fieldSorts := fieldSorts) (i := i + 1) + (previous := previous ++ [head]) h + simpa only [List.getElem?_cons_succ, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hout + +/-- A selected projection code retains the exact selecting minor and +recursor program emitted by `projectionCodes`. -/ +theorem projectionCodes_get?_program_shape (view : VStructureView) + (levels : List VLevel) (params : List VExpr) {idx : Nat} + {code : ProjectionCode} + (hcode : (view.projectionCodes levels params)[idx]? = some code) : + ∃ fieldSort, + (view.fieldSorts.map (VLevel.inst levels))[idx]? = some fieldSort ∧ + code.fieldSort = fieldSort ∧ + code.minor = VExpr.lamN (view.specializedFields levels params) + (.bvar ((view.specializedFields levels params).length - 1 - idx)) ∧ + code.projector = .lam (view.structureType levels params) + (VExpr.appN + (.const view.recursorName + (view.projectionLevels code.fieldSort levels)) + (params.map (VExpr.liftN 1) ++ + [code.typeFn.lift, code.minor.lift, .bvar 0])) := by + unfold projectionCodes at hcode + simpa using projectionCodes.go_get?_program_shape view levels params + (view.specializedFields levels params) + (view.structureType levels params) hcode + +/-- Applying a generated projection's type function to its major premise +substitutes that major into every earlier generated projector. -/ +theorem projectionCodes_get?_typeFn_beta (view : VStructureView) + (levels : List VLevel) (params : List VExpr) {idx : Nat} + {code : ProjectionCode} + (hcode : (view.projectionCodes levels params)[idx]? = some code) + (major : VExpr) : + ∃ field typeBody, + (view.specializedFields levels params)[idx]? = some field ∧ + code.typeFn = .lam (view.structureType levels params) typeBody ∧ + typeBody.inst major = + field.instRevAt + ((view.projectionCodes levels params).take idx |>.map fun prior => + .app prior.projector major) 0 := by + obtain ⟨field, hfield, htypeFn⟩ := + view.projectionCodes_get?_typeFn levels params hcode + let codes := view.projectionCodes levels params + have hidx : idx < codes.length := + (List.getElem?_eq_some_iff.1 hcode).1 + have htake : (codes.take idx).length = idx := by + simp [List.length_take, Nat.min_eq_left (Nat.le_of_lt hidx)] + have htake' : + ((view.projectionCodes levels params).take idx).length = idx := by + simpa [codes] using htake + refine ⟨field, _, hfield, htypeFn, ?_⟩ + rw [VExpr.instN_instRevAt] + rw [List.length_map, htake'] + simp only [Nat.zero_add, VExpr.inst_liftN1] + congr 1 + induction (view.projectionCodes levels params).take idx with + | nil => rfl + | cons prior previous ih => + simp only [List.map_cons] + rw [ih] + simp only [VExpr.inst, VExpr.inst_lift, VExpr.instVar_zero] + +@[simp] theorem projectionCodes_instL (view : VStructureView) + (levels : List VLevel) (params : List VExpr) (ls : List VLevel) : + (view.projectionCodes levels params).map + (fun code => code.instL ls) = + view.projectionCodes (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) := by + simp [projectionCodes, projectionCodes.go_instL, + VLevel.inst_inst, List.map_map, Function.comp_def] + +/-- The dependent result type of projection `idx`, applied to `major`. -/ +def projectionType? (view : VStructureView) + (levels : List VLevel) (params : List VExpr) + (idx : Nat) (major : VExpr) : Option VExpr := do + let code ← (view.projectionCodes levels params)[idx]? + return .app code.typeFn major + +/-- The recursor encoding of projection `idx`, applied to `major`. -/ +def project? (view : VStructureView) + (levels : List VLevel) (params : List VExpr) + (idx : Nat) (major : VExpr) : Option VExpr := do + let code ← (view.projectionCodes levels params)[idx]? + return .app code.projector major + +/-- A proof-carrying boundary for the programs generated by +`projectionCodes`. Generation fixes the program syntax, while this +certificate records the remaining semantic fact needed by consumers: every +selected projector is well typed at every well-formed instantiation. + +This is intentionally separate from `VStructureView.WF`. The latter is the +certificate produced by ordinary inductive generation; accepting primitive +projection syntax is a later capability boundary and must not silently add a +structure-eta rule to Theory's definitional equality. -/ +def ProgramsWF (view : VStructureView) (env : VEnv) : Prop := + ∀ {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} {idx : Nat} {code : ProjectionCode}, + OnCtx Γ (env.IsType U) → + (∀ level ∈ levels, level.WF U) → + levels.length = view.uvars → + params.length = view.nparams → + (∃ resultLevel, env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) → + (view.projectionCodes levels params)[idx]? = some code → + env.HasType U Γ code.projector + (.forallE (view.structureType levels params) + (.app code.typeFn.lift (.bvar 0))) + +/-- A certified projector is typed by the exact constructor-telescope domain +exposed after substituting all earlier projections. -/ +theorem ProgramsWF.projector_hasType_field + {view : VStructureView} {env : VEnv} + (self : view.ProgramsWF env) (henv : env.WF) + {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} {idx : Nat} {code : ProjectionCode} + (hΓ : OnCtx Γ (env.IsType U)) + (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = view.uvars) + (hparamsLength : params.length = view.nparams) + (hparamsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + (hcode : (view.projectionCodes levels params)[idx]? = some code) + {major : VExpr} + (hmajor : env.HasType U Γ major (view.structureType levels params)) : + ∃ field typeBody, + (view.specializedFields levels params)[idx]? = some field ∧ + code.typeFn = .lam (view.structureType levels params) typeBody ∧ + env.HasType U Γ (.app code.projector major) + (field.instRevAt (view.projectionArgs levels params idx major) 0) := by + obtain ⟨field, typeBody, hfield, htypeFn, htypeBody⟩ := + view.projectionCodes_get?_typeFn_beta levels params hcode major + have hprojector := self hΓ hlevels hlevelsLength hparamsLength + hparamsSpine hcode + have happ : env.HasType U Γ (.app code.projector major) + (.app code.typeFn major) := by + simpa only [VExpr.inst, VExpr.inst_lift, VExpr.instVar_zero] using + hprojector.app hmajor + rw [htypeFn] at happ + obtain ⟨sortLevel, hredexType⟩ := happ.isType henv hΓ + obtain ⟨A, B, hlam, harg⟩ := hredexType.app_inv henv hΓ + obtain ⟨⟨_, hstructType⟩, _, hbodyType⟩ := + hlam.lam_inv henv hΓ + have hfunTypeEq := hlam.uniqU henv hΓ + (hstructType.lam hbodyType) + obtain ⟨⟨_, hdomainEq⟩, _⟩ := + hfunTypeEq.forallE_inv henv hΓ + have harg' := harg.defeqU_r henv hΓ ⟨_, hdomainEq⟩ + have hbeta : env.IsDefEqU U Γ + (.app (.lam (view.structureType levels params) typeBody) major) + (typeBody.inst major) := + ⟨_, VEnv.IsDefEq.beta hbodyType harg'⟩ + have hout := happ.defeqU_r henv hΓ hbeta + rw [htypeBody] at hout + refine ⟨field, typeBody, hfield, htypeFn, ?_⟩ + simpa [projectionArgs] using hout + +private theorem ProgramsWF.projectionArgsSpineAux + {view : VStructureView} {env : VEnv} + (self : view.ProgramsWF env) (henv : env.WF) + {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} + (hΓ : OnCtx Γ (env.IsType U)) + (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = view.uvars) + (hparamsLength : params.length = view.nparams) + (hparamsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + {major : VExpr} + (hmajor : env.HasType U Γ major (view.structureType levels params)) + (tailResult : VExpr) : + ∀ {count : Nat}, + count ≤ (view.specializedFields levels params).length → + ∃ cursor, + VExpr.consumeForalls? + (VExpr.forallN (view.specializedFields levels params) tailResult) + (view.projectionArgs levels params count major) = some cursor ∧ + env.SpineWF U Γ + (VExpr.forallN (view.specializedFields levels params) tailResult) + (view.projectionArgs levels params count major) cursor := by + intro count hcount + induction count with + | zero => + exact ⟨_, rfl, .nil⟩ + | succ count ih => + have hcountLt : count < + (view.specializedFields levels params).length := by omega + have hcodeIdx : count < + (view.projectionCodes levels params).length := by + simpa using hcountLt + let code := (view.projectionCodes levels params)[count] + have hcode : + (view.projectionCodes levels params)[count]? = some code := + List.getElem?_eq_getElem hcodeIdx + have hargsLength : + (view.projectionArgs levels params count major).length = count := + view.projectionArgs_length levels params count major + (Nat.le_of_lt hcodeIdx) + obtain ⟨cursor, hconsume, hspine⟩ := + ih (Nat.le_of_lt hcountLt) + obtain ⟨field, semanticBody, hfield, hconsumeDomain⟩ := + VExpr.consumeForalls?_forallN_domain + (view.specializedFields levels params) tailResult + (view.projectionArgs levels params count major) + (by simpa [hargsLength] using hcountLt) + have hcursorShape : cursor = + .forallE + (field.instRevAt + (view.projectionArgs levels params count major) 0) + semanticBody := + Option.some.inj (hconsume.symm.trans hconsumeDomain) + subst cursor + obtain ⟨field', _, hfield', _, hprojectorField⟩ := + self.projector_hasType_field henv hΓ hlevels hlevelsLength + hparamsLength hparamsSpine hcode hmajor + have hfieldEq : field' = field := + Option.some.inj + (hfield'.symm.trans (by simpa [hargsLength] using hfield)) + subst field' + refine ⟨semanticBody.inst (.app code.projector major), ?_, ?_⟩ + · rw [view.projectionArgs_succ levels params count major hcode] + rw [VExpr.consumeForalls?_append, hconsumeDomain] + rfl + · rw [view.projectionArgs_succ levels params count major hcode] + exact hspine.snoc hprojectorField + +/-- All canonical generated projections of a well-typed major form a single +well-typed dependent constructor-field spine. This theorem deliberately +stops at typing: it does not assert structure eta. -/ +theorem ProgramsWF.projectionArgsSpine + {view : VStructureView} {env : VEnv} + (self : view.ProgramsWF env) (henv : env.WF) + {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} + (hΓ : OnCtx Γ (env.IsType U)) + (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = view.uvars) + (hparamsLength : params.length = view.nparams) + (hparamsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + {major : VExpr} + (hmajor : env.HasType U Γ major (view.structureType levels params)) + (tailResult : VExpr) : + env.SpineWF U Γ + (VExpr.forallN (view.specializedFields levels params) tailResult) + (view.projectionArgs levels params + (view.specializedFields levels params).length major) + (VExpr.instRev tailResult + (view.projectionArgs levels params + (view.specializedFields levels params).length major)) := by + obtain ⟨_, _, hspine⟩ := self.projectionArgsSpineAux henv hΓ hlevels + hlevelsLength hparamsLength hparamsSpine hmajor tailResult + (Nat.le_refl _) + apply hspine.retarget + · exact view.projectionArgs_length levels params + (view.specializedFields levels params).length major (by simp) + +/-- Applying the complete canonical projection spine to a constructor prefix +is well typed. The constructor-prefix premise is kept explicit so this +lemma remains independent of any proposed structure-eta equality rule. -/ +theorem ProgramsWF.etaRebuild_hasType_of_constructorPrefix + {view : VStructureView} {env : VEnv} + (self : view.ProgramsWF env) (henv : env.WF) + {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} + (hΓ : OnCtx Γ (env.IsType U)) + (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = view.uvars) + (hparamsLength : params.length = view.nparams) + (hparamsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + {major : VExpr} + (hmajor : env.HasType U Γ major (view.structureType levels params)) + (hconstructorPrefix : env.HasType U Γ + (VExpr.appN (.const view.constructorName levels) params) + (VExpr.forallN (view.specializedFields levels params) + ((view.structureType levels params).liftN + (view.specializedFields levels params).length))) : + env.HasType U Γ (view.etaRebuild levels params major) + (view.structureType levels params) := by + have hfields := self.projectionArgsSpine henv hΓ hlevels hlevelsLength + hparamsLength hparamsSpine hmajor + ((view.structureType levels params).liftN + (view.specializedFields levels params).length) + have hrebuild := hfields.hasType_appN hconstructorPrefix + let args := view.projectionArgs levels params + (view.specializedFields levels params).length major + have hargsLength : + args.length = (view.specializedFields levels params).length := + view.projectionArgs_length levels params + (view.specializedFields levels params).length major (by simp) + have hlift : + (view.structureType levels params).liftN + (view.specializedFields levels params).length = + (view.structureType levels params).liftN args.length := + congrArg (view.structureType levels params).liftN hargsLength.symm + have hresult : + VExpr.instRev + ((view.structureType levels params).liftN + (view.specializedFields levels params).length) + args = + view.structureType levels params := by + calc + _ = VExpr.instRev + ((view.structureType levels params).liftN args.length) args := + congrArg (VExpr.instRev · args) hlift + _ = view.structureType levels params := + VExpr.instRev_liftN_len args _ + rw [hresult] at hrebuild + simpa [etaRebuild, VExpr.appN_append] using hrebuild + +/-- Exact registration of the checked structure artifact in a Theory +environment. These are concrete lookups and generated iota rules, not an +oracle supplied by a projection consumer. -/ +structure Registered (view : VStructureView) (env : VEnv) : Prop where + family : env.constants view.name = + some view.generation.block.sourceType.toVConstant + constructor : env.constants view.constructorName = + some view.constructor.raw.toVConstant + recursor : env.constants view.recursorName = + some view.generation.recursor + rules : ∀ rule ∈ view.generation.generatedRules, env.defeqs rule + +/-- The semantic fragment of `GenerationEnv` that remains monotone under an +arbitrary environment extension. Ordering is supplied by the structural-law +caller; exact constant/rule registration is carried separately by +`Registered`. -/ +structure GenerationSemantics (view : VStructureView) (env : VEnv) : Prop where + checked : view.generation.block.checked.WF env + familyTelescope : + env.TelDefEq view.uvars [] + (view.generation.block.rawParams ++ + view.generation.block.rawIndices) + (view.generation.block.checked.params ++ + view.generation.block.checked.indices) + familyResult : + env.IsDefEq view.uvars + (view.generation.block.rawParams ++ + view.generation.block.rawIndices).reverse + view.generation.block.rawResult + (.sort view.generation.block.checked.resultLevel) + (.sort (.succ view.generation.block.checked.resultLevel)) + constructor : view.constructor.WF view.generation.block env + +/-- Semantic well-formedness of one structure view in its registered +environment. The retained sort list is checked against the exact raw +dependent field telescope. -/ +structure WF (view : VStructureView) (env : VEnv) : Prop + extends VStructureView.Registered view env where + generationSemantics : VStructureView.GenerationSemantics view env + parameters : env.OnTel view.uvars [] + view.generation.block.checked.params + parameters_length : + view.generation.block.checked.params.length = view.nparams + fieldTelescope : env.OnSortTel view.uvars + view.generation.block.checked.params.reverse + view.fields view.fieldSorts + smallFields : view.generation.elimination = .small → + ∀ level ∈ view.fieldSorts, level = .zero + +theorem WF.rule_mem (self : VStructureView.WF view env) {df : VDefEq} + (h : df ∈ VInductDecl.GenerationChecked.generatedRules view.generation) : + VEnv.defeqs env df := + self.rules df h + +/-- The semantic capability required by structure-eta consumers. + +`VStructureView.WF` and `ProgramsWF` account for the registered structure +artifact and the typing of its generated projectors. This property records +only the additional equality that those rule-independent certificates do not +derive: rebuilding every canonical projection is definitionally equal to the +original major premise. Keeping it as an explicit environment capability +prevents checker verification from silently extending `VEnv.IsDefEq`. -/ +def _root_.Ix.Theory.Named.VEnv.HasStructureEta (env : VEnv) : Prop := + ∀ (view : VStructureView), view.WF env → view.ProgramsWF env → + ∀ {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} {major : VExpr}, + OnCtx Γ (env.IsType U) → + (∀ level ∈ levels, level.WF U) → + levels.length = view.uvars → + params.length = view.nparams → + (∃ resultLevel, env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) → + env.HasType U Γ major (view.structureType levels params) → + env.IsDefEq U Γ (view.etaRebuild levels params major) major + (view.structureType levels params) + +theorem Registered.mono {env env' : VEnv} (henv : env ≤ env') + (self : VStructureView.Registered view env) : + VStructureView.Registered view env' where + family := henv.1 self.family + constructor := henv.1 self.constructor + recursor := henv.1 self.recursor + rules := fun rule hrule => henv.2 (self.rules rule hrule) + +theorem GenerationSemantics.mono {env env' : VEnv} (henv : env ≤ env') + (self : VStructureView.GenerationSemantics view env) : + VStructureView.GenerationSemantics view env' where + checked := self.checked.mono henv + familyTelescope := self.familyTelescope.mono henv + familyResult := self.familyResult.mono henv + constructor := self.constructor.mono henv + +/-- Recover the monotone semantic fragment of a generated structure from the +ordinary generation certificate and the exact successful transaction trace. -/ +theorem GenerationSemantics.ofGenerationTrace {pre env : VEnv} + (hgen : view.generation.WF pre) + (trace : VEnv.AddInductGenerationTrace pre env view.generation) : + VStructureView.GenerationSemantics view env := by + have htypeFinal : trace.typeEnv ≤ env := by + have hctors := + (ctorFold_spec view.generation.block.sourceType.ctors + trace.addCtors).1 + have hrec := VEnv.addConst_le trace.addRec + have hrules : trace.recEnv ≤ env := by + simpa only [trace.addRules] using + (rulesFold_spec view.generation.generatedRules trace.recEnv).1 + exact hctors.trans (hrec.trans hrules) + have hpreFinal := trace.le + refine { + checked := hgen.blockWF.2.mono hpreFinal + familyTelescope := hgen.familyTel.mono hpreFinal + familyResult := hgen.familyResult.mono hpreFinal + constructor := ?_ } + have hconstructor : + view.constructor ∈ view.generation.block.ctorPairs := by + simp [view.constructor_eq] + exact (hgen.ctors trace.typeEnv trace.addType view.constructor + hconstructor).mono htypeFinal + +theorem WF.mono {env env' : VEnv} (henv : env ≤ env') + (self : VStructureView.WF view env) : VStructureView.WF view env' where + toRegistered := self.toRegistered.mono henv + generationSemantics := self.generationSemantics.mono henv + parameters := self.parameters.monoProjection henv + parameters_length := self.parameters_length + fieldTelescope := self.fieldTelescope.mono henv + smallFields := self.smallFields + +/-- Reassemble the standard generated-artifact invariant when an ordered +environment is available. -/ +theorem WF.toGenerationEnv (self : VStructureView.WF view env) + (henv : env.Ordered) : + VInductDecl.GenerationEnv view.generation env where + ord := henv + checked := self.generationSemantics.checked + familyTel := self.generationSemantics.familyTelescope + familyResult := self.generationSemantics.familyResult + ctorWF := by + intro ctor hctor + rw [view.constructor_eq] at hctor + simp only [List.mem_singleton] at hctor + subst ctor + exact self.generationSemantics.constructor + familyConst := self.family + ctorConst := by + intro ctor hctor + rw [view.constructor_eq] at hctor + simp only [List.mem_singleton] at hctor + subst ctor + exact self.constructor + +theorem WF.field_closed (self : VStructureView.WF view env) + (henv : env.Ordered) {i : Nat} {field : VExpr} + (hfield : view.fields[i]? = some field) : + field.ClosedN (view.nparams + i) := by + have hparamsCtx : OnCtx + view.generation.block.checked.params.reverse + (env.IsType view.uvars) := + by simpa using VEnv.OnTel.toOnCtx self.parameters (by trivial) + have hclosed := VEnv.OnSortTel.closedAt henv self.fieldTelescope + (VEnv.CtxWF.closed henv hparamsCtx) hfield + simpa [self.parameters_length] using hclosed + +theorem WF.specializedFields_liftN + (self : VStructureView.WF view env) (henv : env.Ordered) + (levels : List VLevel) (params : List VExpr) + (hparams : params.length = view.nparams) (n k : Nat) : + view.specializedFields levels + (params.map fun param => param.liftN n k) = + VExpr.liftTelN n (view.specializedFields levels params) k := by + simpa [specializedFields] using + specializedFieldsAux_liftN view.fields levels params view.nparams + 0 n k hparams + (fun j field hfield => by + simpa using self.field_closed henv hfield) + +theorem WF.specializedFields_instN + (self : VStructureView.WF view env) (henv : env.Ordered) + (levels : List VLevel) (params : List VExpr) + (hparams : params.length = view.nparams) (a : VExpr) (k : Nat) : + view.specializedFields levels + (params.map fun param => param.inst a k) = + VExpr.instTelN a (view.specializedFields levels params) k := by + simpa [specializedFields] using + specializedFieldsAux_instN view.fields levels params view.nparams + 0 k a hparams + (fun j field hfield => by + simpa using self.field_closed henv hfield) + +private theorem projectionLevels_length (view : VStructureView) + (fieldSort : VLevel) (levels : List VLevel) + (hlevels : levels.length = view.uvars) : + (view.projectionLevels fieldSort levels).length = + view.generation.recUvars := by + unfold projectionLevels + cases h : view.generation.elimination <;> + simp [VInductDecl.GenerationChecked.recUvars, + VInductDecl.ElimMode.recUvars, h, hlevels] + +private theorem projectionLevels_wf (view : VStructureView) + {U : Nat} (fieldSort : VLevel) (levels : List VLevel) + (hfieldSort : fieldSort.WF U) + (hlevels : ∀ level ∈ levels, level.WF U) : + ∀ level ∈ view.projectionLevels fieldSort levels, level.WF U := by + unfold projectionLevels + cases view.generation.elimination <;> simp_all + +private theorem sourceLevels_projectionLevels (view : VStructureView) + (fieldSort : VLevel) (levels : List VLevel) + (hlevels : levels.length = view.uvars) : + view.generation.sourceLevels.map + (VLevel.inst (view.projectionLevels fieldSort levels)) = levels := by + unfold VInductDecl.GenerationChecked.sourceLevels + unfold VInductDecl.ElimMode.sourceLevels projectionLevels + cases h : view.generation.elimination + · + change (VLevel.params' view.uvars 1).map + (VLevel.inst (fieldSort :: levels)) = levels + have hshift : + (VLevel.params' view.uvars 1).map + (VLevel.inst (fieldSort :: levels)) = + (VLevel.params view.uvars).map (VLevel.inst levels) := by + simp [VLevel.params', VLevel.params, List.map_map, + Function.comp_def, VLevel.inst, + List.getD_eq_getElem?_getD] + rw [hshift] + exact VLevel.inst_map_id hlevels + · + change (VLevel.params' view.uvars 0).map + (VLevel.inst levels) = levels + have hzero : VLevel.params' view.uvars 0 = + VLevel.params view.uvars := by + simp [VLevel.params', VLevel.params] + rw [hzero] + exact VLevel.inst_map_id hlevels + +private theorem motiveLevel_projectionLevels (view : VStructureView) + (fieldSort : VLevel) (levels : List VLevel) : + view.generation.motiveLevel.inst + (view.projectionLevels fieldSort levels) = + match view.generation.elimination with + | .large => fieldSort + | .small => .zero := by + unfold VInductDecl.GenerationChecked.motiveLevel + unfold VInductDecl.ElimMode.motiveLevel projectionLevels + cases view.generation.elimination <;> rfl + +private theorem WF.motiveLevel_projectionLevels + (self : VStructureView.WF view env) + (fieldSort : VLevel) (hfieldSort : fieldSort ∈ view.fieldSorts) + (levels : List VLevel) : + view.generation.motiveLevel.inst + (view.projectionLevels (fieldSort.inst levels) levels) = + fieldSort.inst levels := by + rw [VStructureView.motiveLevel_projectionLevels] + cases hmode : view.generation.elimination with + | large => rfl + | small => + rw [self.smallFields hmode fieldSort hfieldSort] + rfl + +@[simp] theorem WF.projectionCodes_liftN + (self : VStructureView.WF view env) (henv : env.Ordered) + (levels : List VLevel) (params : List VExpr) + (hparams : params.length = view.nparams) (n k : Nat) : + (view.projectionCodes levels params).map + (fun code => code.liftN n k) = + view.projectionCodes levels + (params.map fun param => param.liftN n k) := by + unfold projectionCodes + rw [self.specializedFields_liftN henv levels params hparams n k] + rw [← structureType_liftN] + apply projectionCodes.go_liftN + · rfl + · simp + +@[simp] theorem WF.projectionCodes_instN + (self : VStructureView.WF view env) (henv : env.Ordered) + (levels : List VLevel) (params : List VExpr) + (hparams : params.length = view.nparams) (a : VExpr) (k : Nat) : + (view.projectionCodes levels params).map + (fun code => code.instN a k) = + view.projectionCodes levels + (params.map fun param => param.inst a k) := by + unfold projectionCodes + rw [self.specializedFields_instN henv levels params hparams a k] + rw [← structureType_instN] + apply projectionCodes.go_instN + · rfl + · simp + +/-- The exact lower-layer structure-eta descriptor generated by a checked +structure view. Its projector syntax is the deterministic projector program +list already certified by the view; the proof fields are only the three +syntactic naturality laws required by Theory transport. -/ +def WF.toStructEta (self : VStructureView.WF view env) + (henv : env.Ordered) : VStructEta where + uvars := view.uvars + nparams := view.nparams + nfields := view.fields.length + familyName := view.name + familyType := view.familyType + constructorName := view.constructorName + projectors := fun levels params => + (view.projectionCodes levels params).map (·.projector) + projectors_length := by + intro levels params _ _ + simp [VStructureView.specializedFields, VStructureView.fields] + projectors_liftN := by + intro levels params n k hparams + have h := self.projectionCodes_liftN henv levels params hparams n k + simpa [List.map_map, ProjectionCode.liftN, Function.comp_def] using + congrArg (List.map (·.projector)) h + projectors_instN := by + intro levels params a k hparams + have h := self.projectionCodes_instN henv levels params hparams a k + simpa [List.map_map, ProjectionCode.instN, Function.comp_def] using + congrArg (List.map (·.projector)) h + projectors_instL := by + intro levels params ls + have h := projectionCodes_instL view levels params ls + simpa [List.map_map, ProjectionCode.instL, Function.comp_def] using + congrArg (List.map (·.projector)) h + +@[simp] theorem WF.toStructEta_structureType + (self : VStructureView.WF view env) (henv : env.Ordered) + (levels : List VLevel) (params : List VExpr) : + (self.toStructEta henv).structureType levels params = + view.structureType levels params := rfl + +@[simp] theorem WF.toStructEta_rebuild + (self : VStructureView.WF view env) (henv : env.Ordered) + (levels : List VLevel) (params : List VExpr) (major : VExpr) : + (self.toStructEta henv).rebuild levels params major = + view.etaRebuild levels params major := by + simp only [VStructEta.rebuild, VStructEta.projectionArgs, WF.toStructEta, + VStructureView.etaRebuild, VStructureView.projectionArgs] + rw [← view.projectionCodes_length levels params, List.take_length] + simp [List.map_map, Function.comp_def] + +end VStructureView + +namespace VEnv + +/-- Registered checked views supply the former semantic structure-eta +capability. The registry contributes only membership; subject reduction is +recovered from the ordered environment, and the equality itself is the +primitive `IsDefEq.structEta` step. -/ +theorem hasStructureEta_of_registry (henv : env.Ordered) + (registered : ∀ (view : VStructureView) + (hview : view.WF env) (_ : view.ProgramsWF env), + env.structEtas (hview.toStructEta henv)) : + env.HasStructureEta := by + intro view hview programs U Γ levels params major hΓ hlevels + hlevelsLength hparamsLength hparamsSpine hmajor + let rule := hview.toStructEta henv + have hregistered : env.structEtas rule := registered view hview programs + have hruleWF : rule.WF env := henv.structEtaWF hregistered + obtain ⟨resultLevel, hparamsSpine⟩ := hparamsSpine + have hrebuild := hruleWF.rebuild_hasType VEnv.LE.rfl hΓ hlevels + hlevelsLength hparamsLength ⟨resultLevel, hparamsSpine⟩ hmajor + have heta := IsDefEq.structEta hregistered hlevels hlevelsLength + hparamsLength hparamsSpine hmajor hrebuild + simpa [rule] using heta + +private theorem SpineWF.monoProjection {env env' : VEnv} + (henv : env ≤ env') : + ∀ {A es B}, env.SpineWF U Γ A es B → env'.SpineWF U Γ A es B + | _, _, _, h => h.mono henv + +/-- The view-facing direction of `TelDefEq.spine_sort`: arguments checked +against the retained raw telescope also consume its definitionally equal +view telescope. -/ +theorem TelDefEq.spine_sort_view + {env : VEnv} {U : Nat} (henv : env.Ordered) : + ∀ {Γ As As' es l}, env.TelDefEq U Γ As As' → + env.SpineWF U Γ (VExpr.forallN As (.sort l)) es (.sort l) → + es.length = As.length → + env.SpineWF U Γ (VExpr.forallN As' (.sort l)) es (.sort l) + | _, [], [], [], _, _, hspine, _ => by simpa using hspine + | _, [], [], _ :: _, _, _, _, hlen => by simp at hlen + | Γ, A :: As, A' :: As', e :: es, l, ⟨⟨_, hA⟩, hT⟩, + .cons he hrest, hlen => by + have heView : env.HasType U Γ e A' := hA.defeq he + have hTinst := TelDefEq.instN henv he (.zero) hT + have hrest' : env.SpineWF U Γ + (VExpr.forallN (VExpr.instTelN e As 0) (.sort l)) + es (.sort l) := by + simpa [VExpr.instN_forallN, VExpr.inst] using hrest + have hlen' : es.length = As.length := by simpa using hlen + have hlenInst : + es.length = (VExpr.instTelN e As 0).length := by + rw [VExpr.instTelN_length] + exact hlen' + have hout := TelDefEq.spine_sort_view henv + hTinst hrest' hlenInst + refine .cons heView ?_ + simpa [VExpr.instN_forallN, VExpr.inst] using hout + +/-- Parameters accepted by the structure family also consume the stored raw +constructor parameter prefix. This is the semantic bridge used by the +kernel projection checker before it traverses the constructor fields. -/ +theorem _root_.Ix.Theory.Named.VStructureView.WF.constructorParamsSpine + (self : VStructureView.WF view env) (henv : env.Ordered) + {U : Nat} {Γ : List VExpr} (levels : List VLevel) + (hlevels : ∀ level ∈ levels, level.WF U) + (_hlevelsLength : levels.length = view.uvars) + (params : List VExpr) (hparamsLength : params.length = view.nparams) + (paramsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + (target : VExpr) : + env.SpineWF U Γ + (VExpr.forallN + (view.constructorParams.map (VExpr.instL levels)) + target) params (VExpr.instRev target params) := by + let S := self.toGenerationEnv henv + obtain ⟨resultLevel, hspine⟩ := paramsSpine + have hrawLength : + view.generation.block.rawParams.length = view.nparams := + view.generation.shape.1 + have hspineShape : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.rawParams.map (VExpr.instL levels)) + (view.generation.block.rawResult.instL levels)) + params (.sort resultLevel) := by + simpa [VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + view.raw_indices_eq, VExpr.instL_forallN, + VExpr.forallN] using hspine + have hparamsRaw : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.rawParams.map (VExpr.instL levels)) + (.sort .zero)) params (.sort .zero) := by + have hout := hspineShape.retarget + (by simpa [hrawLength] using hparamsLength) (.sort .zero) + rw [VExpr.instRev_closedN params (by trivial)] at hout + exact hout + have hfamilyDefEq := S.rawParams_defeq.instL hlevels + have hrawLift : VExpr.liftTelN Γ.length + (view.generation.block.rawParams.map (VExpr.instL levels)) 0 = + view.generation.block.rawParams.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + hfamilyDefEq.raw_onTel (by trivial) Γ.length + have hcheckedLift : VExpr.liftTelN Γ.length + (view.generation.block.checked.params.map (VExpr.instL levels)) 0 = + view.generation.block.checked.params.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + (hfamilyDefEq.view_onTel henv) (by trivial) Γ.length + have hfamilyDefEqΓ := hfamilyDefEq.weakN henv + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hrawLift, hcheckedLift] at hfamilyDefEqΓ + simp only [List.append_nil] at hfamilyDefEqΓ + have hparamsChecked : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.checked.params.map (VExpr.instL levels)) + (.sort .zero)) params (.sort .zero) := + TelDefEq.spine_sort_view henv hfamilyDefEqΓ hparamsRaw + (by simpa [hrawLength] using hparamsLength) + have hconstructorMem : + view.constructor ∈ view.generation.block.ctorPairs := by + simp [view.constructor_eq] + have hconstructorShape := + view.generation.shape.2.2.2.2.2 view.constructor hconstructorMem + have hconstructorDefEq₀ := + ((S.ctorWF view.constructor hconstructorMem).declaredTel.take + view.nparams).instL hlevels + have hconstructorDefEq : env.TelDefEq U [] + (view.constructorParams.map (VExpr.instL levels)) + (view.generation.block.checked.params.map (VExpr.instL levels)) := by + simpa [VStructureView.constructorParams, + VInductDecl.NormalizedCtor.declaredBinders, + VInductDecl.NormalizedCtor.viewBinders, + hconstructorShape.2.2.1, self.parameters_length] using + hconstructorDefEq₀ + have hconstructorRawLift : VExpr.liftTelN Γ.length + (view.constructorParams.map (VExpr.instL levels)) 0 = + view.constructorParams.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + hconstructorDefEq.raw_onTel (by trivial) Γ.length + have hconstructorCheckedLift : VExpr.liftTelN Γ.length + (view.generation.block.checked.params.map (VExpr.instL levels)) 0 = + view.generation.block.checked.params.map (VExpr.instL levels) := + hcheckedLift + have hconstructorDefEqΓ := hconstructorDefEq.weakN henv + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hconstructorRawLift, hconstructorCheckedLift] at hconstructorDefEqΓ + simp only [List.append_nil] at hconstructorDefEqΓ + have hout := TelDefEq.spine_sort henv hconstructorDefEqΓ hparamsChecked + (by simpa [VStructureView.constructorParams] using + hparamsLength.trans hconstructorShape.2.2.1.symm) + exact hout.retarget + (by simpa [VStructureView.constructorParams] using + hparamsLength.trans hconstructorShape.2.2.1.symm) target + +/-- Recover the structure-family parameter spine from the corresponding +constructor-parameter prefix. This is the converse consumer bridge needed +when a checker recognizes a fully applied constructor before it knows the +family application carried by its result type. -/ +theorem _root_.Ix.Theory.Named.VStructureView.WF.familyParamsSpine_of_constructor + (self : VStructureView.WF view env) (henv : env.Ordered) + {U : Nat} {Γ : List VExpr} (levels : List VLevel) + (hlevels : ∀ level ∈ levels, level.WF U) + (_hlevelsLength : levels.length = view.uvars) + (params : List VExpr) (hparamsLength : params.length = view.nparams) + {target cursor : VExpr} + (constructorSpine : env.SpineWF U Γ + (VExpr.forallN + (view.constructorParams.map (VExpr.instL levels)) target) + params cursor) + (resultLevel : VLevel) + (hresult : view.generation.block.rawResult = .sort resultLevel) : + env.SpineWF U Γ (view.familyType.instL levels) params + (.sort (resultLevel.inst levels)) := by + let S := self.toGenerationEnv henv + have hrawLength : + view.generation.block.rawParams.length = view.nparams := + view.generation.shape.1 + have hconstructorMem : + view.constructor ∈ view.generation.block.ctorPairs := by + simp [view.constructor_eq] + have hconstructorShape := + view.generation.shape.2.2.2.2.2 view.constructor hconstructorMem + have hconstructorLength : params.length = + (view.constructorParams.map (VExpr.instL levels)).length := by + simpa [VStructureView.constructorParams] using + hparamsLength.trans hconstructorShape.2.2.1.symm + have hparamsConstructor : env.SpineWF U Γ + (VExpr.forallN + (view.constructorParams.map (VExpr.instL levels)) (.sort .zero)) + params (.sort .zero) := by + have hout := constructorSpine.retarget hconstructorLength (.sort .zero) + rw [VExpr.instRev_closedN params (by trivial)] at hout + exact hout + have hfamilyDefEq := S.rawParams_defeq.instL hlevels + have hrawLift : VExpr.liftTelN Γ.length + (view.generation.block.rawParams.map (VExpr.instL levels)) 0 = + view.generation.block.rawParams.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + hfamilyDefEq.raw_onTel (by trivial) Γ.length + have hcheckedLift : VExpr.liftTelN Γ.length + (view.generation.block.checked.params.map (VExpr.instL levels)) 0 = + view.generation.block.checked.params.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + (hfamilyDefEq.view_onTel henv) (by trivial) Γ.length + have hfamilyDefEqΓ := hfamilyDefEq.weakN henv + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hrawLift, hcheckedLift] at hfamilyDefEqΓ + simp only [List.append_nil] at hfamilyDefEqΓ + have hconstructorDefEq₀ := + ((S.ctorWF view.constructor hconstructorMem).declaredTel.take + view.nparams).instL hlevels + have hconstructorDefEq : env.TelDefEq U [] + (view.constructorParams.map (VExpr.instL levels)) + (view.generation.block.checked.params.map (VExpr.instL levels)) := by + simpa [VStructureView.constructorParams, + VInductDecl.NormalizedCtor.declaredBinders, + VInductDecl.NormalizedCtor.viewBinders, + hconstructorShape.2.2.1, self.parameters_length] using + hconstructorDefEq₀ + have hconstructorRawLift : VExpr.liftTelN Γ.length + (view.constructorParams.map (VExpr.instL levels)) 0 = + view.constructorParams.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + hconstructorDefEq.raw_onTel (by trivial) Γ.length + have hconstructorDefEqΓ := hconstructorDefEq.weakN henv + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hconstructorRawLift, hcheckedLift] at hconstructorDefEqΓ + simp only [List.append_nil] at hconstructorDefEqΓ + have hparamsChecked : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.checked.params.map (VExpr.instL levels)) + (.sort .zero)) params (.sort .zero) := + VEnv.TelDefEq.spine_sort_view henv hconstructorDefEqΓ + hparamsConstructor hconstructorLength + have hrawParamsLength : params.length = + (view.generation.block.rawParams.map (VExpr.instL levels)).length := by + simpa [hrawLength] using hparamsLength + have hparamsRaw : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.rawParams.map (VExpr.instL levels)) + (.sort .zero)) params (.sort .zero) := + VEnv.TelDefEq.spine_sort henv hfamilyDefEqΓ hparamsChecked + hrawParamsLength + have hout := hparamsRaw.retarget hrawParamsLength + (.sort (resultLevel.inst levels)) + rw [VExpr.instRev_closedN params (by trivial)] at hout + simpa [VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + view.raw_indices_eq, hresult, VExpr.instL_forallN, + VExpr.forallN, VExpr.instL] using hout + +theorem _root_.Ix.Theory.Named.VStructureView.WF.specializedFields_onSortTel + (self : VStructureView.WF view env) (henv : env.Ordered) + {U : Nat} {Γ : List VExpr} (levels : List VLevel) + (hlevels : ∀ level ∈ levels, level.WF U) + (_hlevelsLength : levels.length = view.uvars) + (params : List VExpr) (hparamsLength : params.length = view.nparams) + (paramsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) : + env.OnSortTel U Γ (view.specializedFields levels params) + (view.fieldSorts.map (VLevel.inst levels)) := by + let S := self.toGenerationEnv henv + obtain ⟨resultLevel, hspine⟩ := paramsSpine + have hrawLength : + view.generation.block.rawParams.length = view.nparams := + view.generation.shape.1 + have hspineShape : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.rawParams.map (VExpr.instL levels)) + (view.generation.block.rawResult.instL levels)) + params (.sort resultLevel) := by + simpa [VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + view.raw_indices_eq, VExpr.instL_forallN, + VExpr.forallN] using hspine + have hparamsRaw : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.rawParams.map (VExpr.instL levels)) + (.sort resultLevel)) params (.sort resultLevel) := by + have hout := hspineShape.retarget + (by simpa [hrawLength] using hparamsLength) + (.sort resultLevel) + rw [VExpr.instRev_closedN params (by trivial)] at hout + exact hout + have hrawChecked := S.rawParams_defeq.instL hlevels + have hrawLift := VEnv.OnTel.liftTelN_eq henv + hrawChecked.raw_onTel (by trivial) Γ.length + have hcheckedLift := VEnv.OnTel.liftTelN_eq henv + (hrawChecked.view_onTel henv) (by trivial) Γ.length + have hrawLift' : VExpr.liftTelN Γ.length + (view.generation.block.rawParams.map (VExpr.instL levels)) 0 = + view.generation.block.rawParams.map (VExpr.instL levels) := by + simpa using hrawLift + have hcheckedLift' : VExpr.liftTelN Γ.length + (view.generation.block.checked.params.map (VExpr.instL levels)) 0 = + view.generation.block.checked.params.map (VExpr.instL levels) := by + simpa using hcheckedLift + have hrawCheckedΓ := hrawChecked.weakN henv + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hrawLift', hcheckedLift'] at hrawCheckedΓ + simp only [List.append_nil] at hrawCheckedΓ + have hparamsChecked : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.checked.params.map + (VExpr.instL levels)) (.sort resultLevel)) + params (.sort resultLevel) := by + exact TelDefEq.spine_sort_view henv hrawCheckedΓ hparamsRaw + (by simpa [hrawLength] using hparamsLength) + have hfields := self.fieldTelescope.instL hlevels + have hcheckedParams := self.parameters.instL hlevels + have Wparams := Ctx.LiftN.consTel + (view.generation.block.checked.params.map (VExpr.instL levels)) + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hcheckedLift'] at Wparams + have hcheckedCtx : OnCtx + (view.generation.block.checked.params.reverse.map + (VExpr.instL levels)) (env.IsType U) := by + simpa [List.map_reverse] using + VEnv.OnTel.toOnCtx hcheckedParams (by trivial) + have hfieldLift := VEnv.OnSortTel.liftTelN_eq henv hfields + (VEnv.CtxWF.closed henv hcheckedCtx) Γ.length + have hfieldsΓ := VEnv.OnSortTel.weakN henv + (by simpa [List.map_reverse] using Wparams) hfields + simp only [List.length_reverse, List.length_map] at hfieldLift + rw [hfieldLift] at hfieldsΓ + have hspecialized := VEnv.OnSortTel.instRevParams henv + hparamsChecked (by simpa [self.parameters_length] using hparamsLength) + (by simpa [List.map_reverse] using hfieldsΓ) + rw [VExpr.instRevAt_map_instL_zipIdx] at hspecialized + simpa [VStructureView.specializedFields] using hspecialized + +private theorem _root_.Ix.Theory.Named.VStructureView.WF.generationParamsSpine + (self : VStructureView.WF view env) (henv : env.Ordered) + {U : Nat} {Γ : List VExpr} (levels : List VLevel) + (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = view.uvars) + (params : List VExpr) (hparamsLength : params.length = view.nparams) + (paramsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + (fieldSort : VLevel) : + env.SpineWF U Γ + (VExpr.forallN + (view.generation.paramsTel.map + (VExpr.instL + (view.projectionLevels fieldSort levels))) + (.sort fieldSort)) params (.sort fieldSort) := by + let S := self.toGenerationEnv henv + obtain ⟨resultLevel, hspine⟩ := paramsSpine + have hrawLength : + view.generation.block.rawParams.length = view.nparams := + view.generation.shape.1 + have hspineShape : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.rawParams.map (VExpr.instL levels)) + (view.generation.block.rawResult.instL levels)) + params (.sort resultLevel) := by + simpa [VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + view.raw_indices_eq, VExpr.instL_forallN, + VExpr.forallN] using hspine + have hparamsRaw : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.rawParams.map (VExpr.instL levels)) + (.sort fieldSort)) params (.sort fieldSort) := by + have hout := hspineShape.retarget + (by simpa [hrawLength] using hparamsLength) (.sort fieldSort) + rw [VExpr.instRev_closedN params (by trivial)] at hout + exact hout + have hrawChecked := S.rawParams_defeq.instL hlevels + have hrawLift : VExpr.liftTelN Γ.length + (view.generation.block.rawParams.map (VExpr.instL levels)) 0 = + view.generation.block.rawParams.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + hrawChecked.raw_onTel (by trivial) Γ.length + have hcheckedLift : VExpr.liftTelN Γ.length + (view.generation.block.checked.params.map (VExpr.instL levels)) 0 = + view.generation.block.checked.params.map (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + (hrawChecked.view_onTel henv) (by trivial) Γ.length + have hrawCheckedΓ := hrawChecked.weakN henv + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hrawLift, hcheckedLift] at hrawCheckedΓ + simp only [List.append_nil] at hrawCheckedΓ + have hparamsChecked : env.SpineWF U Γ + (VExpr.forallN + (view.generation.block.checked.params.map + (VExpr.instL levels)) (.sort fieldSort)) + params (.sort fieldSort) := + TelDefEq.spine_sort_view henv hrawCheckedΓ hparamsRaw + (by simpa [hrawLength] using hparamsLength) + have hgenerationChecked := S.generationParams_defeq.instL hlevels + have hgenerationLift : VExpr.liftTelN Γ.length + (view.generation.block.generationParams.map + (VExpr.instL levels)) 0 = + view.generation.block.generationParams.map + (VExpr.instL levels) := by + simpa using VEnv.OnTel.liftTelN_eq henv + hgenerationChecked.raw_onTel (by trivial) Γ.length + have hcheckedLift₂ : VExpr.liftTelN Γ.length + (view.generation.block.checked.params.map + (VExpr.instL levels)) 0 = + view.generation.block.checked.params.map + (VExpr.instL levels) := hcheckedLift + have hgenerationCheckedΓ := hgenerationChecked.weakN henv + (Ctx.LiftN.zero (n := Γ.length) (Γ := []) Γ) + rw [hgenerationLift, hcheckedLift₂] at hgenerationCheckedΓ + simp only [List.append_nil] at hgenerationCheckedΓ + have hparamsGeneration := TelDefEq.spine_sort henv + hgenerationCheckedΓ hparamsChecked + (by simpa [S.generationParams_length] using hparamsLength) + have hsource := VStructureView.sourceLevels_projectionLevels + view fieldSort levels + hlevelsLength + have hparamsTel : + view.generation.paramsTel.map + (VExpr.instL (view.projectionLevels fieldSort levels)) = + view.generation.block.generationParams.map + (VExpr.instL levels) := by + simp [VInductDecl.GenerationChecked.paramsTel, + List.map_map, Function.comp_def, VExpr.instL_instL, hsource] + rw [hparamsTel] + exact hparamsGeneration + +theorem _root_.Ix.Theory.Named.VStructureView.WF.recursorProjection_hasType + (self : VStructureView.WF view env) (henv : env.Ordered) + {U : Nat} {Γ : List VExpr} (levels : List VLevel) + (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = view.uvars) + (params : List VExpr) (hparamsLength : params.length = view.nparams) + (paramsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + (fieldSort : VLevel) + (hfieldSort : fieldSort.WF U) + (hmotiveLevel : + view.generation.motiveLevel.inst + (view.projectionLevels fieldSort levels) = fieldSort) + (_structIsType : env.IsType U Γ + (view.structureType levels params)) + {typeFn minor major : VExpr} + (typeFnType : env.HasType U Γ typeFn + (.forallE (view.structureType levels params) (.sort fieldSort))) + (minorType : env.HasType U Γ minor + (view.projectionMinorType levels params + (view.specializedFields levels params) typeFn)) + (majorType : env.HasType U Γ major + (view.structureType levels params)) : + env.HasType U Γ + (VExpr.appN (.const view.recursorName + (view.projectionLevels fieldSort levels)) + (params ++ [typeFn, minor, major])) + (.app typeFn major) := by + let gen := view.generation + let S := self.toGenerationEnv henv + let pLevels := view.projectionLevels fieldSort levels + let k := gen.block.ctorPairs.length + let ni := gen.idxTel.length + let recRest : VExpr := + VExpr.forallN gen.minorTypes <| + VExpr.forallN (VExpr.liftTelN (k + 1) gen.idxTel 0) <| + .forallE + (VExpr.appN (.const gen.block.sourceType.name gen.sourceLevels) + (VExpr.bvarRevRange (ni + k + 1) view.nparams ++ + VExpr.bvarRevRange 0 ni)) + (.app + (VExpr.appN (.bvar (ni + k + 1)) + (VExpr.bvarRevRange 1 ni)) + (.bvar 0)) + let recTail : VExpr := .forallE gen.motiveType recRest + have hrec : env.HasType U Γ + (.const view.recursorName pLevels) + ((VExpr.forallN gen.paramsTel recTail).instL pLevels) := by + have hout := VEnv.HasType.const (Γ := Γ) self.recursor + (VStructureView.projectionLevels_wf view fieldSort levels + hfieldSort hlevels) + (VStructureView.projectionLevels_length view fieldSort levels + hlevelsLength) + simpa [gen, pLevels, recTail, recRest, k, ni, + VStructureView.recursorName, + VInductDecl.GenerationChecked.recursor, + VInductDecl.GenerationChecked.recType] using hout + have hparams := self.generationParamsSpine henv levels hlevels + hlevelsLength params hparamsLength paramsSpine fieldSort + have hparamsTelLength : params.length = + (gen.paramsTel.map (VExpr.instL pLevels)).length := by + simp [gen, VInductDecl.GenerationChecked.paramsTel, + S.generationParams_length, hparamsLength] + have hparamsFull := hparams.retarget hparamsTelLength + (recTail.instL pLevels) + have hparamsFull' : env.SpineWF U Γ + ((VExpr.forallN gen.paramsTel recTail).instL pLevels) + params (VExpr.instRev (recTail.instL pLevels) params) := by + simpa [VExpr.instL_forallN] using hparamsFull + have hmotiveShape : + VExpr.instRev (recTail.instL pLevels) params = + .forallE + (.forallE (view.structureType levels params) (.sort fieldSort)) + (VExpr.instRevAt (recRest.instL pLevels) params 1) := by + change VExpr.instRev + (.forallE (gen.motiveType.instL pLevels) + (recRest.instL pLevels)) params = _ + have hconst : VExpr.instRev + (.const view.generation.block.sourceType.name levels) params = + .const view.generation.block.sourceType.name levels := + VExpr.instRev_closedN params (by trivial) + have hrange : + (VExpr.bvarRevRange 0 view.source.nparams).map + (VExpr.instRev · params) = params := by + have hparamsLength' : params.length = view.source.nparams := + hparamsLength + rw [← hparamsLength'] + exact VExpr.map_instRev_bvarRevRange params + have hrangeL : + (VExpr.bvarRevRange 0 view.source.nparams).map + (fun x => (x.instL pLevels).instRev params) = params := by + calc + _ = ((VExpr.bvarRevRange 0 view.source.nparams).map + (VExpr.instL pLevels)).map (VExpr.instRev · params) := by + rw [List.map_map] + rfl + _ = params := by + rw [VExpr.bvarRevRange_map_instL] + exact hrange + have hsort : + (VExpr.sort fieldSort).instRevAt params 1 = + .sort fieldSort := + VExpr.instRevAt_closedN params (by trivial) + rw [VExpr.instRev_forallE_projection] + congr 1 + simp [gen, pLevels, + VInductDecl.GenerationChecked.motiveType, + VInductDecl.GenerationChecked.idxTel, + view.raw_indices_eq, VExpr.forallN, VExpr.bvarRevRange, + VExpr.instL, VExpr.instL_appN, + VExpr.instRev_forallE_projection, + VExpr.instRev_appN, Function.comp_def, + hconst, hrangeL, hsort, hmotiveLevel, + VStructureView.structureType, + VStructureView.sourceLevels_projectionLevels view fieldSort levels + hlevelsLength] + rw [hmotiveShape] at hparamsFull' + have hwithMotive := hparamsFull'.snoc typeFnType + have hconstructorMem : + view.constructor ∈ view.generation.block.ctorPairs := by + simp [view.constructor_eq] + have hresultIndices : view.constructor.view.resultIndices = [] := by + apply List.length_eq_zero_iff.1 + rw [S.viewResultIndices_length hconstructorMem] + simp [view.checked_indices_eq] + have hminorShape : + ((VExpr.instRevAt (recRest.instL pLevels) params 1).inst typeFn) = + .forallE (view.projectionMinorType levels params + (view.specializedFields levels params) typeFn) + (.forallE (view.structureType levels params).lift + (.app (typeFn.liftN 2) (.bvar 0))) := by + simp [gen, pLevels, recRest, k, ni, VInductDecl.GenerationChecked.minorTypes, + VInductDecl.GenerationChecked.minorTypesAux, VInductDecl.GenerationChecked.minorType, + VInductDecl.GenerationChecked.idxTel, VInductDecl.NormalizedCtor.fieldsR, + VInductDecl.NormalizedCtor.recArgsR, VInductDecl.NormalizedCtor.resultIndicesR, + VInductDecl.ihsFromRecArgs, VStructureView.projectionMinorType, + VStructureView.projectionConstructorApp, view.constructor_eq, view.raw_indices_eq, + hresultIndices, view.recursive_eq, VExpr.instL_forallN, VExpr.instL_appN, + VExpr.liftTelN_instL, VExpr.instL_instL, VExpr.instN_forallN, VExpr.instTelN, + VExpr.instRevAt_forallN_projection, List.map_append, VExpr.bvarRevRange, List.map_append, + List.map_map, Function.comp_def, + VStructureView.sourceLevels_projectionLevels view fieldSort levels hlevelsLength] + change VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · have hfieldTel := + VExpr.instTelN_instRevAt_lift_projection + ((view.constructor.rawFields view.source.nparams).map + (VExpr.instL levels)) params typeFn 0 + rw [VExpr.instRevAt_map_instL_zipIdx] at hfieldTel + have hfieldTel' : + VExpr.instTelN typeFn + ((VExpr.liftTelN 1 + ((view.constructor.rawFields view.source.nparams).map + (VExpr.instL levels)) 0).zipIdx 1 |>.map + fun x => x.1.instRevAt params x.2) 0 = + view.specializedFields levels params := by + simpa [VStructureView.specializedFields, + VStructureView.fields] using hfieldTel + rw [hfieldTel'] + congr 1 + have hsourceLevels := + VStructureView.sourceLevels_projectionLevels view fieldSort levels + hlevelsLength + change + (VLevel.params' view.source.uvars + view.generation.elimination.offset).map + (VLevel.inst pLevels) = levels at hsourceLevels + have hliftedLength : + (VExpr.liftTelN 1 + ((view.constructor.rawFields view.source.nparams).map + (VExpr.instL levels)) 0).length = + (view.constructor.rawFields view.source.nparams).length := by + rw [VExpr.liftTelN_length] + simp + have hspecializedLength : + (view.specializedFields levels params).length = + (view.constructor.rawFields view.source.nparams).length := by + simp [VStructureView.specializedFields, + VStructureView.fields] + simp only [VExpr.forallN, VExpr.instL, VExpr.bvarRevRange_map_instL, hliftedLength, + hspecializedLength] + rw [hsourceLevels] + have hbody := + VExpr.projectionMinorBody_shape view.constructorName levels + params (view.constructor.rawFields view.source.nparams).length + typeFn + rw [hparamsLength] at hbody + simpa only [Nat.add_comm] using hbody + · have hsourceLevels := + VStructureView.sourceLevels_projectionLevels view fieldSort levels + hlevelsLength + change + (VLevel.params' view.source.uvars + view.generation.elimination.offset).map + (VLevel.inst pLevels) = levels at hsourceLevels + simp only [VExpr.forallN, VExpr.liftTelN, List.zipIdx_nil, List.map_nil, VExpr.instTelN, + VExpr.instL, VExpr.instL_appN, VExpr.bvarRevRange_map_instL, VExpr.instL] + rw [hsourceLevels] + simpa [gen, hparamsLength, VStructureView.structureType] using + (VExpr.projectionMajorTail_shape view.name levels params typeFn) + rw [hminorShape] at hwithMotive + have hwithMinor := hwithMotive.snoc minorType + have hwithMajor : env.SpineWF U Γ + ((VExpr.forallN gen.paramsTel recTail).instL pLevels) + (params ++ [typeFn, minor, major]) (.app typeFn major) := by + have majorType' : env.HasType U Γ major + ((view.structureType levels params).lift.inst minor) := by + rw [VExpr.inst_lift] + exact majorType + have hout := hwithMinor.snoc majorType' + have htypeFnMinor : + (typeFn.liftN 2).inst minor 1 = typeFn.lift := by + rw [← VExpr.liftN_liftN typeFn 1 1, + VExpr.instN_liftAt_projection, VExpr.inst_lift] + have hminorVar : VExpr.instVar 0 minor 1 = .bvar 0 := by + simp [VExpr.instVar] + have hresult : + (((typeFn.liftN 2).app (.bvar 0)).inst minor 1).inst major = + typeFn.app major := by + simp only [VExpr.inst] + rw [htypeFnMinor, VExpr.inst_lift] + rw [hminorVar] + simp only [VExpr.inst] + rw [VExpr.instVar_zero] + rw [hresult] at hout + simpa [List.append_assoc] using hout + exact hwithMajor.hasType_appN hrec + +theorem SpineWF.instNProjection {env : VEnv} {U k : Nat} + {Γ₀ Γ₁ Γ : List VExpr} {e₀ A₀ : VExpr} + (henv : env.Ordered) + (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (h₀ : env.HasType U Γ₀ e₀ A₀) : + ∀ {es : List VExpr} {A B : VExpr}, env.SpineWF U Γ₁ A es B → + env.SpineWF U Γ (A.inst e₀ k) + (es.map fun e => e.inst e₀ k) (B.inst e₀ k) + | _, _, _, h => h.instN henv W h₀ + +/-- A generated projector computes on the matching generated constructor +once the registered rule's capture spine has been checked. This is the +exact iota layer; constructor-head and parameter-prefix alignment are kept +outside this theorem. -/ +theorem _root_.Ix.Theory.Named.VStructureView.WF.projector_constructor_exact + (self : VStructureView.WF view env) (henv : env.WF) + {U : Nat} {Γ : List VExpr} (hΓ : OnCtx Γ (env.IsType U)) + {levels : List VLevel} (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = view.uvars) + {params : List VExpr} (hparamsLength : params.length = view.nparams) + (hparamsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel)) + {idx : Nat} {code : VStructureView.ProjectionCode} + (hcode : (view.projectionCodes levels params)[idx]? = some code) + (hprojector : env.HasType U Γ code.projector + (.forallE (view.structureType levels params) + (.app code.typeFn.lift (.bvar 0)))) + {fields : List VExpr} (hfieldsLength : + fields.length = (view.specializedFields levels params).length) + {field : VExpr} (hfield : fields[idx]? = some field) + (hctorType : env.HasType U Γ + (VExpr.appN (.const view.constructorName levels) (params ++ fields)) + (view.structureType levels params)) + (hfieldsSpine : env.SpineWF U Γ + (VExpr.forallN (view.specializedFields levels params) (.sort .zero)) + fields (.sort .zero)) + {B : VExpr} + (hcaps : env.SpineWF U Γ + ((view.generation.rule 0 view.constructor).type.instL + (view.projectionLevels code.fieldSort levels)) + (params ++ [code.typeFn, code.minor] ++ fields) B) : + env.IsDefEqU U Γ + (.app code.projector + (VExpr.appN (.const view.constructorName levels) (params ++ fields))) + field := by + obtain ⟨fieldSort, hfieldSort, hcodeSort, hminorShape, + hprojectorShape⟩ := + view.projectionCodes_get?_program_shape levels params hcode + have hsortTel := self.specializedFields_onSortTel henv.ordered + levels hlevels hlevelsLength params hparamsLength hparamsSpine + have hfieldSortWF : code.fieldSort.WF U := by + rw [hcodeSort] + exact hsortTel.sortWF hΓ hfieldSort + let pLevels := view.projectionLevels code.fieldSort levels + have hpLevelsWF : ∀ level ∈ pLevels, level.WF U := + VStructureView.projectionLevels_wf view code.fieldSort levels + hfieldSortWF hlevels + have hpLevelsLength : pLevels.length = view.generation.recUvars := + VStructureView.projectionLevels_length view code.fieldSort levels + hlevelsLength + have hruleMem : view.generation.rule 0 view.constructor ∈ + view.generation.generatedRules := by + simp [VInductDecl.GenerationChecked.generatedRules, + view.constructor_eq] + have hregistered := self.rule_mem hruleMem + have hruleWF := henv.ordered.defEqWF hregistered + rw [hprojectorShape] at hprojector + obtain ⟨_, ⟨projectorBodyType, hprojectorBody⟩⟩ := + hprojector.lam_inv henv.ordered hΓ + have hprojectorBeta := VEnv.IsDefEq.beta hprojectorBody hctorType + have hprojectorToRule : env.IsDefEqU U Γ + (.app code.projector + (VExpr.appN (.const view.constructorName levels) (params ++ fields))) + (VExpr.appN (.const view.recursorName pLevels) + (params ++ [code.typeFn, code.minor, + VExpr.appN (.const view.constructorName levels) + (params ++ fields)])) := by + refine ⟨projectorBodyType.inst + (VExpr.appN (.const view.constructorName levels) (params ++ fields)), ?_⟩ + rw [hprojectorShape] + simpa [pLevels, VExpr.inst, VExpr.instN_appN, VExpr.inst_lift, + VExpr.instVar_zero, + List.map_append, List.map_map, Function.comp_def] using + hprojectorBeta + let gen := view.generation + let Bs := view.constructor.fieldsR view.source.uvars view.source.nparams + gen.elimination + let m := Bs.length + let rs := view.constructor.recArgsR view.source.uvars gen.elimination + let binders := gen.paramsTel ++ gen.motiveType :: gen.minorTypes ++ + VExpr.liftTelN (gen.block.ctorPairs.length + 1) Bs 0 + let recBase := VExpr.appN + (.const (.str gen.block.sourceType.name "rec") gen.recLevels) + (VExpr.bvarRevRange m (view.source.nparams + + gen.block.ctorPairs.length + 1)) + let idxR := view.constructor.resultIndicesR view.source.uvars + gen.elimination |>.map fun expression => + expression.liftN (gen.block.ctorPairs.length + 1) m + let ctorApp := VExpr.appN + (.const view.constructor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (m + gen.block.ctorPairs.length + 1) + view.source.nparams ++ VExpr.bvarRevRange 0 m) + let ihs := rs.map fun recursive => + recursive.ruleCall m gen.block.ctorPairs.length recBase + let lhsBody := VExpr.appN recBase (idxR ++ [ctorApp]) + let rhsBody := VExpr.appN + (.bvar (gen.block.ctorPairs.length - 1 - 0 + m)) + (VExpr.bvarRevRange 0 m ++ ihs) + let typeBody := VExpr.appN + (.bvar (gen.block.ctorPairs.length + m)) (idxR ++ [ctorApp]) + have hlhs₀ := hruleWF.1 + change env.HasType gen.recUvars [] (VExpr.lamN binders lhsBody) + (VExpr.forallN binders typeBody) at hlhs₀ + have hrhs₀ := hruleWF.2 + change env.HasType gen.recUvars [] (VExpr.lamN binders rhsBody) + (VExpr.forallN binders typeBody) at hrhs₀ + have hlhs : env.HasType U Γ + ((VExpr.lamN binders lhsBody).instL pLevels) + ((VExpr.forallN binders typeBody).instL pLevels) := + (hlhs₀.instL hpLevelsWF).weak0 henv.ordered + have hrhs : env.HasType U Γ + ((VExpr.lamN binders rhsBody).instL pLevels) + ((VExpr.forallN binders typeBody).instL pLevels) := + (hrhs₀.instL hpLevelsWF).weak0 henv.ordered + rw [VExpr.instL_lamN, VExpr.instL_forallN] at hlhs hrhs + have hcaps' : env.SpineWF U Γ + (VExpr.forallN (binders.map (VExpr.instL pLevels)) + (typeBody.instL pLevels)) + (params ++ [code.typeFn, code.minor] ++ fields) B := by + change env.SpineWF U Γ + ((VExpr.forallN binders typeBody).instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields) B at hcaps + simpa only [VExpr.instL_forallN] using hcaps + let S := self.toGenerationEnv henv.ordered + have hparamsTelLength : gen.paramsTel.length = view.nparams := by + simp [gen, VInductDecl.GenerationChecked.paramsTel, + S.generationParams_length] + have hspecializedLength : + (view.specializedFields levels params).length = + (view.constructor.rawFields view.nparams).length := by + simp [VStructureView.specializedFields, VStructureView.fields] + have hBsLength : Bs.length = + (view.constructor.rawFields view.nparams).length := by + simpa [Bs] using + (VInductDecl.NormalizedCtor.fieldsR_length + (source := view.source) view.constructor + (mode := gen.elimination)) + have hcapturesLength : + (params ++ [code.typeFn, code.minor] ++ fields).length = + (binders.map (VExpr.instL pLevels)).length := by + simp only [List.length_append, List.length_cons, List.length_nil, + List.length_map, VExpr.liftTelN_length, binders] + rw [hparamsLength, hfieldsLength, hspecializedLength, + hparamsTelLength, gen.minorTypes_length, view.constructor_eq, + hBsLength] + simp + obtain ⟨hlhsTel, lhsType, hlhsBody⟩ := + VEnv.HasType.lamN_wf henv.ordered hΓ hlhs + obtain ⟨hrhsTel, rhsType, hrhsBody⟩ := + VEnv.HasType.lamN_wf henv.ordered hΓ hrhs + have hlhsSpine := hcaps'.retarget hcapturesLength lhsType + have hrhsSpine := hcaps'.retarget hcapturesLength rhsType + have hcollapseL := VEnv.IsDefEq.appN_lamN henv.ordered + hlhsTel hlhsBody hlhsSpine hcapturesLength + have hcollapseR := VEnv.IsDefEq.appN_lamN henv.ordered + hrhsTel hrhsBody hrhsSpine hcapturesLength + have hregisteredRule : env.IsDefEq U Γ + ((view.generation.rule 0 view.constructor).lhs.instL pLevels) + ((view.generation.rule 0 view.constructor).rhs.instL pLevels) + ((view.generation.rule 0 view.constructor).type.instL pLevels) := + .extra hregistered hpLevelsWF hpLevelsLength + have happlied := VEnv.IsDefEq.appN_congr hregisteredRule hcaps + rw [show (view.generation.rule 0 view.constructor).lhs = + VExpr.lamN binders lhsBody from rfl, + show (view.generation.rule 0 view.constructor).rhs = + VExpr.lamN binders rhsBody from rfl, + VExpr.instL_lamN] at happlied + simp only [VExpr.instL_lamN] at happlied + have hiotaBodies : env.IsDefEqU U Γ + (VExpr.instRev (lhsBody.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields)) + (VExpr.instRev (rhsBody.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields)) := + VEnv.IsDefEqU.trans henv hΓ ⟨_, hcollapseL.symm⟩ + (VEnv.IsDefEqU.trans henv hΓ ⟨_, happlied⟩ ⟨_, hcollapseR⟩) + have hconstructorMem : view.constructor ∈ + view.generation.block.ctorPairs := by + simp [view.constructor_eq] + have hresultIndices : view.constructor.view.resultIndices = [] := by + apply List.length_eq_zero_iff.1 + rw [S.viewResultIndices_length hconstructorMem] + simp [view.checked_indices_eq] + have hfieldsLengthRaw : fields.length = m := by + exact hfieldsLength.trans (hspecializedLength.trans hBsLength.symm) + have hprefixLength : + (params ++ [code.typeFn, code.minor]).length = view.nparams + 2 := by + simp [hparamsLength] + have hcapturesLength' : + (params ++ [code.typeFn, code.minor] ++ fields).length = + view.nparams + 2 + m := by + simp [hparamsLength, hfieldsLengthRaw] + omega + have hsegCommon : + (VExpr.bvarRevRange m (view.nparams + 2)).map + (VExpr.instRev · + (params ++ [code.typeFn, code.minor] ++ fields)) = + params ++ [code.typeFn, code.minor] := by + have h := VExpr.map_instRev_bvarRevRange_seg + (params ++ [code.typeFn, code.minor] ++ fields) + (view.nparams + 2) m (by rw [hcapturesLength']; omega) + rw [← hparamsLength] at h ⊢ + rw [show (params ++ [code.typeFn, code.minor] ++ fields).length - + m - (params.length + 2) = 0 by + simp only [List.length_append, List.length_cons, List.length_nil] + rw [hfieldsLengthRaw] + omega, + List.drop_zero] at h + rw [List.take_append, + show params.length + 2 = + (params ++ [code.typeFn, code.minor]).length by simp, + List.take_length] at h + simpa using h + have hsegParams : + (VExpr.bvarRevRange (m + 2) view.nparams).map + (VExpr.instRev · + (params ++ [code.typeFn, code.minor] ++ fields)) = params := by + have h := VExpr.map_instRev_bvarRevRange_seg + (params ++ [code.typeFn, code.minor] ++ fields) + view.nparams (m + 2) (by rw [hcapturesLength']; omega) + rw [← hparamsLength] at h ⊢ + rw [show (params ++ [code.typeFn, code.minor] ++ fields).length - + (m + 2) - params.length = 0 by + simp only [List.length_append, List.length_cons, List.length_nil] + rw [hfieldsLengthRaw] + omega, + List.drop_zero] at h + simpa using h + have hsegFields : + (VExpr.bvarRevRange 0 m).map + (VExpr.instRev · + (params ++ [code.typeFn, code.minor] ++ fields)) = fields := by + have h := VExpr.map_instRev_bvarRevRange_seg + (params ++ [code.typeFn, code.minor] ++ fields) m 0 + (by rw [hcapturesLength']; omega) + rw [show (params ++ [code.typeFn, code.minor] ++ fields).length - + 0 - m = view.nparams + 2 by rw [hcapturesLength']; omega, + show view.nparams + 2 = + (params ++ [code.typeFn, code.minor]).length by + exact hprefixLength.symm, + List.drop_left] at h + have htake : fields.take m = fields := + List.take_of_length_le (Nat.le_of_eq hfieldsLengthRaw) + rw [htake] at h + exact h + have hsourceLevels := VStructureView.sourceLevels_projectionLevels + view code.fieldSort levels hlevelsLength + have hrecLevels : gen.recLevels.map (VLevel.inst pLevels) = pLevels := by + exact VLevel.inst_map_id hpLevelsLength + have hrecConst : + VExpr.instRev + ((.const (.str gen.block.sourceType.name "rec") gen.recLevels : + VExpr).instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields) = + .const view.recursorName pLevels := by + rw [VExpr.instRev_closedN _ (by trivial)] + simp only [VExpr.instL] + rw [hrecLevels] + rfl + have hsegCommonL : + (VExpr.bvarRevRange m (view.nparams + 2)).map + (fun expression => VExpr.instRev (expression.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields)) = + params ++ [code.typeFn, code.minor] := by + calc + _ = ((VExpr.bvarRevRange m (view.nparams + 2)).map + (VExpr.instL pLevels)).map + (VExpr.instRev · + (params ++ [code.typeFn, code.minor] ++ fields)) := by + rw [List.map_map] + exact List.map_congr_left fun _ _ => rfl + _ = _ := by + rw [VExpr.bvarRevRange_map_instL] + exact hsegCommon + have hsegParamsL : + (VExpr.bvarRevRange (m + 2) view.nparams).map + (fun expression => VExpr.instRev (expression.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields)) = params := by + calc + _ = ((VExpr.bvarRevRange (m + 2) view.nparams).map + (VExpr.instL pLevels)).map + (VExpr.instRev · + (params ++ [code.typeFn, code.minor] ++ fields)) := by + rw [List.map_map] + exact List.map_congr_left fun _ _ => rfl + _ = _ := by + rw [VExpr.bvarRevRange_map_instL] + exact hsegParams + have hsegFieldsL : + (VExpr.bvarRevRange 0 m).map + (fun expression => VExpr.instRev (expression.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields)) = fields := by + calc + _ = ((VExpr.bvarRevRange 0 m).map + (VExpr.instL pLevels)).map + (VExpr.instRev · + (params ++ [code.typeFn, code.minor] ++ fields)) := by + rw [List.map_map] + exact List.map_congr_left fun _ _ => rfl + _ = _ := by + rw [VExpr.bvarRevRange_map_instL] + exact hsegFields + have hidxRNil : idxR = [] := by + simp [idxR, VInductDecl.NormalizedCtor.resultIndicesR, + hresultIndices] + have hrecBaseShape : + VExpr.instRev (recBase.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields) = + VExpr.appN (.const view.recursorName pLevels) + (params ++ [code.typeFn, code.minor]) := by + rw [show recBase = VExpr.appN + (.const (.str gen.block.sourceType.name "rec") gen.recLevels) + (VExpr.bvarRevRange m (view.nparams + 2)) by + unfold recBase + rw [view.constructor_eq] + rfl, + VExpr.instL_appN, VExpr.instRev_appN, hrecConst] + rw [List.map_map] + exact congrArg (VExpr.appN (.const view.recursorName pLevels)) + hsegCommonL + have hctorShape : + VExpr.instRev (ctorApp.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields) = + VExpr.appN (.const view.constructorName levels) + (params ++ fields) := by + rw [show ctorApp = VExpr.appN + (.const view.constructorName gen.sourceLevels) + (VExpr.bvarRevRange (m + 2) view.nparams ++ + VExpr.bvarRevRange 0 m) by + unfold ctorApp + rw [view.constructor_eq] + rfl, + VExpr.instL_appN, VExpr.instRev_appN] + rw [VExpr.instRev_closedN _ (by trivial)] + simp only [VExpr.instL] + rw [hsourceLevels] + simp only [List.map_append, List.map_map, Function.comp_def] + rw [hsegParamsL, hsegFieldsL] + have hleftShape : + VExpr.instRev (lhsBody.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields) = + VExpr.appN (.const view.recursorName pLevels) + (params ++ [code.typeFn, code.minor, + VExpr.appN (.const view.constructorName levels) + (params ++ fields)]) := by + rw [show lhsBody = VExpr.appN recBase (idxR ++ [ctorApp]) by + rfl, + VExpr.instL_appN, VExpr.instRev_appN, hrecBaseShape, hidxRNil, + List.nil_append] + simp only [List.map_cons, List.map_nil, hctorShape] + rw [← VExpr.appN_append] + simp only [List.append_assoc] + rfl + have hminorCapture : + VExpr.instRev (.bvar m) + (params ++ [code.typeFn, code.minor] ++ fields) = + code.minor := by + have h := VExpr.map_instRev_bvarRevRange_seg + (params ++ [code.typeFn, code.minor] ++ fields) 1 m + (by rw [hcapturesLength']; omega) + rw [show (params ++ [code.typeFn, code.minor] ++ fields).length - + m - 1 = params.length + 1 by + rw [hcapturesLength', hparamsLength] + omega] at h + simpa [VExpr.bvarRevRange] using h + have hrightBodyShape : + rhsBody = VExpr.appN (.bvar m) (VExpr.bvarRevRange 0 m) := by + simp [rhsBody, ihs, rs, gen, + VInductDecl.NormalizedCtor.recArgsR, view.recursive_eq, + view.constructor_eq] + have hrightShape : + VExpr.instRev (rhsBody.instL pLevels) + (params ++ [code.typeFn, code.minor] ++ fields) = + VExpr.appN code.minor fields := by + rw [hrightBodyShape, VExpr.instL_appN, + VExpr.bvarRevRange_map_instL, VExpr.instRev_appN] + simp only [VExpr.instL] + rw [hminorCapture, hsegFields] + rw [hleftShape, hrightShape] at hiotaBodies + obtain ⟨selectedType, hselectedType, -⟩ := + view.projectionCodes_get?_typeFn levels params hcode + have hidxLt : idx < (view.specializedFields levels params).length := + (List.getElem?_eq_some_iff.1 hselectedType).1 + let q := (view.specializedFields levels params).length - 1 - idx + have hqLt : q < (view.specializedFields levels params).length := by + simp only [q] + omega + have hselectedReverse : + (view.specializedFields levels params).reverse[q]? = + some selectedType := by + rw [List.getElem?_reverse hqLt, + show (view.specializedFields levels params).length - 1 - q = idx by + simp only [q] + omega, + hselectedType] + have hselectedCtx : + ((view.specializedFields levels params).reverse ++ Γ)[q]? = + some selectedType := by + rw [List.getElem?_append_left (by simpa using hqLt), + hselectedReverse] + have hminorBodyType : env.HasType U + ((view.specializedFields levels params).reverse ++ Γ) + (.bvar q) (selectedType.liftN (q + 1)) := + .bvar (Lookup.of_getElem? hselectedCtx) + have hminorSpine := hfieldsSpine.retarget hfieldsLength + (selectedType.liftN (q + 1)) + have hminorBetaRaw := VEnv.IsDefEq.appN_lamN henv.ordered + hsortTel.toOnTel hminorBodyType hminorSpine hfieldsLength + have hfieldInst : VExpr.instRev (.bvar q) fields = field := by + have h := VExpr.map_instRev_bvarRevRange_seg fields 1 q + (by rw [hfieldsLength]; exact Nat.add_one_le_iff.2 hqLt) + rw [show fields.length - q - 1 = idx by + rw [hfieldsLength] + simp only [q] + omega] at h + obtain ⟨hidxFields, hfieldGet⟩ := + List.getElem?_eq_some_iff.1 hfield + rw [List.drop_eq_getElem_cons hidxFields, hfieldGet, + List.take_succ_cons] at h + simpa [VExpr.bvarRevRange] using h + have hminorBeta : env.IsDefEqU U Γ + (VExpr.appN code.minor fields) field := by + refine ⟨VExpr.instRev (selectedType.liftN (q + 1)) fields, ?_⟩ + rw [hminorShape] + simpa only [hfieldInst] using hminorBetaRaw + exact VEnv.IsDefEqU.trans henv hΓ hprojectorToRule + (VEnv.IsDefEqU.trans henv hΓ hiotaBodies hminorBeta) + +/-- Environment-indexed projection semantics. + +The universe and parameter spines are explicit. The major premise must have +the exact instantiated structure type, and the result is the unique program +computed by the registered view. -/ +structure TrProj (env : VEnv) (U : Nat) (Γ : List VExpr) + (view : VStructureView) (levels : List VLevel) (params : List VExpr) + (idx : Nat) (major result : VExpr) : Prop where + viewWF : VStructureView.WF view env + levelsWF : ∀ level ∈ levels, level.WF U + levels_length : levels.length = view.uvars + params_length : params.length = view.nparams + paramsSpine : ∃ resultLevel, + env.SpineWF U Γ (view.familyType.instL levels) + params (.sort resultLevel) + majorType : env.HasType U Γ major (view.structureType levels params) + program : ∃ code : VStructureView.ProjectionCode, + (view.projectionCodes levels params)[idx]? = some code ∧ + result = .app code.projector major ∧ + env.HasType U Γ code.projector + (.forallE (view.structureType levels params) + (.app code.typeFn.lift (.bvar 0))) + +/-- The projection-specific output of registered constructor-head inversion. + +This package performs no iota computation. It only aligns a constructor +normal form and one selected runtime argument with the canonical registered +view, and supplies the typed spines needed by +`projector_constructor_exact`. -/ +structure ProjectionConstructorAlignment (env : VEnv) (U : Nat) + (Γ : List VExpr) (view : VStructureView) (levels : List VLevel) + (params : List VExpr) (idx : Nat) + (code : VStructureView.ProjectionCode) + (runtimeConstructorName : Name) (runtimeMajor runtimeField : VExpr) where + constructor_name_eq : runtimeConstructorName = view.constructorName + fields : List VExpr + field : VExpr + fields_length : + fields.length = (view.specializedFields levels params).length + field_get : fields[idx]? = some field + constructorType : env.HasType U Γ + (VExpr.appN (.const view.constructorName levels) (params ++ fields)) + (view.structureType levels params) + fieldsSpine : env.SpineWF U Γ + (VExpr.forallN (view.specializedFields levels params) (.sort .zero)) + fields (.sort .zero) + captures : ∃ B, env.SpineWF U Γ + ((view.generation.rule 0 view.constructor).type.instL + (view.projectionLevels code.fieldSort levels)) + (params ++ [code.typeFn, code.minor] ++ fields) B + major_eq : env.IsDefEqU U Γ runtimeMajor + (VExpr.appN (.const view.constructorName levels) (params ++ fields)) + field_eq : env.IsDefEqU U Γ runtimeField field + +/-- Consume registered-head alignment with the separately proved exact iota +theorem. This keeps the transitional injectivity boundary from hiding the +projection computation itself. -/ +theorem TrProj.projector_constructor_aligned + (self : VEnv.TrProj env U Γ view levels params idx major result) + (henv : env.WF) (hΓ : OnCtx Γ (env.IsType U)) + {code : VStructureView.ProjectionCode} + (hcode : (view.projectionCodes levels params)[idx]? = some code) + (hprojector : env.HasType U Γ code.projector + (.forallE (view.structureType levels params) + (.app code.typeFn.lift (.bvar 0)))) + {runtimeMajor runtimeField : VExpr} + {runtimeConstructorName : Name} + (alignment : ProjectionConstructorAlignment env U Γ view levels params idx + code runtimeConstructorName runtimeMajor runtimeField) : + env.IsDefEqU U Γ (.app code.projector runtimeMajor) runtimeField := by + have hmajorEq := alignment.major_eq.of_r henv hΓ + alignment.constructorType + have hmajorCongr : env.IsDefEqU U Γ + (.app code.projector runtimeMajor) + (.app code.projector + (VExpr.appN (.const view.constructorName levels) + (params ++ alignment.fields))) := + ⟨_, hprojector.appDF hmajorEq⟩ + obtain ⟨captureType, hcaptures⟩ := alignment.captures + have hiota := self.viewWF.projector_constructor_exact henv hΓ + self.levelsWF self.levels_length self.params_length self.paramsSpine + hcode hprojector alignment.fields_length alignment.field_get + alignment.constructorType alignment.fieldsSpine hcaptures + exact VEnv.IsDefEqU.trans henv hΓ hmajorCongr + (VEnv.IsDefEqU.trans henv hΓ hiota alignment.field_eq.symm) + +theorem TrProj.project_eq + (self : VEnv.TrProj env U Γ view levels params idx major result) : + VStructureView.project? view levels params idx major = some result := by + obtain ⟨code, hcode, rfl, -⟩ := self.program + simp [VStructureView.project?, hcode] + +theorem TrProj.type_eq + (self : VEnv.TrProj env U Γ view levels params idx major result) : + ∃ code : VStructureView.ProjectionCode, + VStructureView.projectionType? view levels params idx major = + some (VExpr.app code.typeFn major) := by + obtain ⟨code, hcode, _, -⟩ := self.program + exact ⟨code, by simp [VStructureView.projectionType?, hcode]⟩ + +/-- A fixed checked view, universe/parameter instantiation, field index, and +major determine the projection result syntactically. -/ +theorem TrProj.result_eq + (self : VEnv.TrProj env U Γ view levels params idx major result) + (other : VEnv.TrProj env U Γ view levels params idx major result') : + result = result' := + Option.some.inj (self.project_eq.symm.trans other.project_eq) + +/-- Projection evidence is stable when the registered environment is +extended without changing any existing constants or reduction rules. -/ +theorem TrProj.mono {env env' : VEnv} (henv : env ≤ env') + (self : VEnv.TrProj env U Γ view levels params idx major result) : + VEnv.TrProj env' U Γ view levels params idx major result where + viewWF := self.viewWF.mono henv + levelsWF := self.levelsWF + levels_length := self.levels_length + params_length := self.params_length + paramsSpine := self.paramsSpine.imp fun _ h => h.monoProjection henv + majorType := self.majorType.mono henv + program := self.program.imp fun _ ⟨hcode, hresult, htype⟩ => + ⟨hcode, hresult, htype.mono henv⟩ + +/-- Weakening acts pointwise on the explicit parameters, major, and computed +projection program. -/ +theorem TrProj.weakN (henv : env.Ordered) + (W : Ctx.LiftN n k Γ Γ') + (self : VEnv.TrProj env U Γ view levels params idx major result) : + VEnv.TrProj env U Γ' view levels + (params.map fun param => param.liftN n k) idx + (major.liftN n k) (result.liftN n k) := by + refine { + viewWF := self.viewWF + levelsWF := self.levelsWF + levels_length := self.levels_length + params_length := by simpa using self.params_length + paramsSpine := ?_ + majorType := by simpa using self.majorType.weakN henv W + program := ?_ } + · have hfamilyClosed : (view.familyType.instL levels).ClosedN 0 := by + simpa using (henv.closedC self.viewWF.family).instL + obtain ⟨resultLevel, hspine⟩ := self.paramsSpine + refine ⟨resultLevel, ?_⟩ + have hspine' := hspine.weakN henv W + rw [hfamilyClosed.liftN_eq (Nat.zero_le _)] at hspine' + simpa [VExpr.liftN] using hspine' + · obtain ⟨code, hcode, rfl, htype⟩ := self.program + refine ⟨code.liftN n k, ?_, rfl, ?_⟩ + rw [← self.viewWF.projectionCodes_liftN henv levels params + self.params_length n k] + simp only [List.getElem?_map, hcode, Option.map_some] + simpa [VStructureView.ProjectionCode.liftN, VExpr.liftN, + VExpr.liftN_lift_projection] using htype.weakN henv W + +/-- General context lifting, derived one inserted binder at a time from +`weakN`. -/ +theorem TrProj.weak' (henv : env.Ordered) + (W : Ctx.Lift' l Γ Γ') + (self : VEnv.TrProj env U Γ view levels params idx major result) : + VEnv.TrProj env U Γ' view levels + (params.map fun param => param.lift' l) idx + (major.lift' l) (result.lift' l) := by + generalize hdepth : l.depth = depth + induction depth generalizing l Γ' with + | zero => + have hctx := W.depth_zero hdepth + subst Γ' + simpa [VExpr.lift'_depth_zero (l := l) hdepth] using self + | succ depth ih => + obtain ⟨tail, k, rfl, rfl⟩ := Lift.depth_succ hdepth + obtain ⟨Γ₁, W₁, W₂⟩ := W.of_cons_skip + have h := (ih W₁ Lift.depth_consN).weakN henv W₂ + rw [Lift.consN_skip_eq] + have hlift : ∀ e : VExpr, + e.lift' ((tail.consN k).comp + (Lift.refl.skip.consN k)) = + (e.lift' (tail.consN k)).liftN 1 k := by + intro e + rw [VExpr.lift'_comp, ← Lift.skipN_one, + VExpr.lift'_consN_skipN] + have hparams : + params.map (fun param => param.lift' ((tail.consN k).comp + (Lift.refl.skip.consN k))) = + (params.map fun param => param.lift' (tail.consN k)).map + (fun param => param.liftN 1 k) := by + rw [List.map_map] + exact List.map_congr_left fun param _ => hlift param + rw [hparams, hlift major, hlift result] + exact h + +/-- Substitution acts pointwise on the explicit parameters, major, and +computed projection program. -/ +theorem TrProj.instN (henv : env.Ordered) + (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (h₀ : env.HasType U Γ₀ e₀ A₀) + (self : VEnv.TrProj env U Γ₁ view levels params idx major result) : + VEnv.TrProj env U Γ view levels + (params.map fun param => param.inst e₀ k) idx + (major.inst e₀ k) (result.inst e₀ k) := by + refine { + viewWF := self.viewWF + levelsWF := self.levelsWF + levels_length := self.levels_length + params_length := by simpa using self.params_length + paramsSpine := ?_ + majorType := by simpa using self.majorType.instN henv W h₀ + program := ?_ } + · have hfamilyClosed : (view.familyType.instL levels).ClosedN 0 := by + simpa using (henv.closedC self.viewWF.family).instL + obtain ⟨resultLevel, hspine⟩ := self.paramsSpine + refine ⟨resultLevel, ?_⟩ + have hspine' := hspine.instNProjection henv W h₀ + rw [hfamilyClosed.instN_eq (Nat.zero_le _)] at hspine' + simpa [VExpr.inst] using hspine' + · obtain ⟨code, hcode, rfl, htype⟩ := self.program + refine ⟨code.instN e₀ k, ?_, rfl, ?_⟩ + rw [← self.viewWF.projectionCodes_instN henv levels params + self.params_length e₀ k] + simp only [List.getElem?_map, hcode, Option.map_some] + simpa [VStructureView.ProjectionCode.instN, VExpr.inst, + ← VExpr.lift_instN_lo] using htype.instN henv W h₀ + +/-- Transport projection evidence to a definitionally equal context and a +new major already checked against the same instantiated structure type. -/ +theorem TrProj.defeqDFC (henv : env.Ordered) + (hΓ : env.IsDefEqCtx U Γ₀ Γ₁ Γ₂) + (majorType' : env.HasType U Γ₂ major' + (view.structureType levels params)) + (self : VEnv.TrProj env U Γ₁ view levels params idx major result) : + ∃ result', VEnv.TrProj env U Γ₂ view levels params idx major' result' := by + obtain ⟨code, hcode, -, htype⟩ := self.program + refine ⟨.app code.projector major', { + viewWF := self.viewWF + levelsWF := self.levelsWF + levels_length := self.levels_length + params_length := self.params_length + paramsSpine := self.paramsSpine.imp fun _ h => h.defeqDFC henv hΓ + majorType := majorType' + program := ⟨code, hcode, rfl, + htype.defeqDFC henv hΓ⟩ }⟩ + +/-- Universe instantiation acts pointwise on the explicit structure +universes and parameters, and on the recursor program they determine. -/ +theorem TrProj.instL {ls : List VLevel} + (hls : ∀ level ∈ ls, level.WF U') + (self : VEnv.TrProj env U Γ view levels params idx major result) : + VEnv.TrProj env U' (Γ.map (VExpr.instL ls)) view + (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) idx + (major.instL ls) (result.instL ls) := by + refine { + viewWF := self.viewWF + levelsWF := ?_ + levels_length := by simpa using self.levels_length + params_length := by simpa using self.params_length + paramsSpine := ?_ + majorType := by simpa using self.majorType.instL hls + program := ?_ } + · intro level hlevel + obtain ⟨sourceLevel, hsourceLevel, rfl⟩ := List.mem_map.1 hlevel + exact VLevel.WF.inst hls + · obtain ⟨resultLevel, hspine⟩ := self.paramsSpine + refine ⟨resultLevel.inst ls, ?_⟩ + simpa [VExpr.instL, VExpr.instL_instL] using hspine.instL hls + · obtain ⟨code, hcode, rfl, htype⟩ := self.program + refine ⟨code.instL ls, ?_, ?_, ?_⟩ + · rw [← VStructureView.projectionCodes_instL] + simp only [List.getElem?_map, hcode, Option.map_some] + · rfl + · simpa [VStructureView.ProjectionCode.instL, VExpr.instL, + VExpr.instL_liftN] using htype.instL hls + +/-- The registered-structure constant-head inversion boundary. + +The four conclusions are the projection-specific eliminators supplied by +constant-head injectivity: a type assigned to a syntactically weakened major +recovers an instantiation below the inserted context; definitionally equal +majors recover the same registered view/instantiation strongly enough for the +generated projector programs to be definitionally equal; a runtime +constructor head recovers the registered constructor name; and that head plus +one selected argument is aligned with the registered constructor and field. +The last conclusion deliberately provides only typed alignment—the iota step +remains the proved `projector_constructor_exact` theorem. + +Its eventual proof uses `IsDefEqU.weakN_iff` together with injectivity of +registered inductive heads. Keeping the boundary in Theory makes the +temporary Spec-16/17 dependency explicit instead of leaving Verify's +structural laws as local holes. -/ +structure RegisteredStructureHeadInversion (env : VEnv) : Prop where + weak'_inv : + ∀ {U : Nat} {Γ Γ' : List VExpr} {view : VStructureView} + {levels : List VLevel} {params : List VExpr} {idx : Nat} + {major result : VExpr} {lift : Lift}, + OnCtx Γ' (env.IsType U) → + Ctx.Lift' lift Γ Γ' → + env.TrProj U Γ' view levels params idx (major.lift' lift) result → + ∃ params' result', + env.TrProj U Γ view levels params' idx major result' + unique : + ∀ {U : Nat} {Γ₁ Γ₂ : List VExpr} + {view₁ view₂ : VStructureView} + {levels₁ levels₂ : List VLevel} {params₁ params₂ : List VExpr} + {idx : Nat} {major₁ major₂ result₁ result₂ : VExpr}, + env.IsDefEqCtx U [] Γ₁ Γ₂ → + env.TrProj U Γ₁ view₁ levels₁ params₁ idx major₁ result₁ → + env.TrProj U Γ₂ view₂ levels₂ params₂ idx major₂ result₂ → + env.IsDefEqU U Γ₁ major₁ major₂ → + env.IsDefEqU U Γ₁ result₁ result₂ + constructor_name_inv : + ∀ {U : Nat} {Γ : List VExpr} {view : VStructureView} + {levels : List VLevel} {params : List VExpr} {idx : Nat} + {major result runtimeMajor : VExpr} + {constructorName : Name} {constructorLevels : List VLevel} + {constructorArgs : List VExpr}, + OnCtx Γ (env.IsType U) → + env.TrProj U Γ view levels params idx major result → + runtimeMajor = VExpr.appN + (.const constructorName constructorLevels) constructorArgs → + env.IsDefEqU U Γ runtimeMajor major → + constructorName = view.constructorName + constructor_inv : + ∀ {U : Nat} {Γ : List VExpr} {view : VStructureView} + {levels : List VLevel} {params : List VExpr} {idx : Nat} + {major result : VExpr} {code : VStructureView.ProjectionCode} + {runtimeMajor runtimeField : VExpr} + {constructorName : Name} {constructorLevels : List VLevel} + {constructorArgs : List VExpr}, + OnCtx Γ (env.IsType U) → + env.TrProj U Γ view levels params idx major result → + (view.projectionCodes levels params)[idx]? = some code → + runtimeMajor = VExpr.appN + (.const constructorName constructorLevels) constructorArgs → + constructorArgs[view.nparams + idx]? = some runtimeField → + env.IsDefEqU U Γ runtimeMajor major → + Nonempty (ProjectionConstructorAlignment env U Γ view levels params idx + code constructorName runtimeMajor runtimeField) + +set_option warn.sorry false in +/-- Public Tier-R registered-head inversion statement. Spec-16/17 discharge +the underlying constant-head theorem; projection structural laws consume only +this stable interface and therefore shed `sorryAx` automatically when it is +proved. -/ +theorem WF.registeredStructureHeadInversion + (self : VEnv.WF env) : RegisteredStructureHeadInversion env := by + sorry + +#guard_named_axioms Ix.Theory.Named.VEnv.WF.registeredStructureHeadInversion [propext, sorryAx, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.TrProj.result_eq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.TrProj.mono [propext, Quot.sound] + +end VEnv + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Quot.lean b/Ix/Theory/Named/Quot.lean new file mode 100644 index 000000000..c509fcef0 --- /dev/null +++ b/Ix/Theory/Named/Quot.lean @@ -0,0 +1,27 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.VEnv +import Ix.Theory.Named.Meta + +namespace Ix.Theory.Named + +def eqConst := vconst(type_of% @Eq) +def quotConst := vconst(type_of% @Quot) +def quotMkConst := vconst(type_of% @Quot.mk) +def quotLiftConst := vconst(type_of% @Quot.lift) +def quotIndConst := vconst(type_of% @Quot.ind) +def quotDefEq := vdefeq(α r β f c a => @Quot.lift α r β f c (Quot.mk r a) ≡ f a) + +def VEnv.QuotReady (env : VEnv) : Prop := + env.constants ``Eq = some eqConst + +def VEnv.addQuot (env : VEnv) : Option VEnv := do + let env ← env.addConst ``Quot quotConst + let env ← env.addConst ``Quot.mk quotMkConst + let env ← env.addConst ``Quot.lift quotLiftConst + let env ← env.addConst ``Quot.ind quotIndConst + env.addDefEq quotDefEq diff --git a/Ix/Theory/Named/Reference/Declaration.lean b/Ix/Theory/Named/Reference/Declaration.lean new file mode 100644 index 000000000..5b9ed8970 --- /dev/null +++ b/Ix/Theory/Named/Reference/Declaration.lean @@ -0,0 +1,33 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Declaration + + +namespace Lean + +/-- +The value of a constant for the purpose of delta reduction: definitions and theorems have one, +opaques do not. This mirrors the C++ `constant_info::has_value()`/`get_value()` pair. + +This is deliberately *not* `ConstantInfo.value?`, whose meaning changed in lean4#12973: it now +excludes theorems, but `constant_info::has_value()` was left untouched by that PR, so the kernel +still delta-unfolds theorems: `type_checker::is_delta` uses this predicate to select candidates, +and `instantiate_value_lparams` uses it before reading their values. +-/ +def ConstantInfo.deltaValue? : ConstantInfo → Option Expr + | .defnInfo {value, ..} => some value + | .thmInfo {value, ..} => some value + | _ => none + +namespace ReducibilityHints + +def lt' : ReducibilityHints → ReducibilityHints → Bool -- lean4#2750 + | _, .opaque => false + | .abbrev, _ => false + | .opaque, _ => true + | _, .abbrev => true + | .regular d₁, .regular d₂ => d₁ < d₂ diff --git a/Ix/Theory/Named/Reference/Environment.lean b/Ix/Theory/Named/Reference/Environment.lean new file mode 100644 index 000000000..8bc74f3f6 --- /dev/null +++ b/Ix/Theory/Named/Reference/Environment.lean @@ -0,0 +1,125 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Reference.TypeChecker +import Ix.Theory.Named.Reference.Quot +import Ix.Theory.Named.Reference.Inductive.Add +import Ix.Theory.Named.Reference.Primitive + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open TypeChecker Kernel Environment + +open private Lean.Kernel.Environment.add from Lean.Environment + +def checkConstantVal (env : Environment) (v : ConstantVal) (allowPrimitive := false) : M Unit := do + checkName env v.name allowPrimitive + checkDuplicatedUnivParams v.levelParams + checkNoMVarNoFVar env v.name v.type + let sort ← checkType v.type + _ ← ensureSort sort v.type + +def addAxiom (env : Environment) (v : AxiomVal) (check := true) (fuel : FuelConfig := {}) : + Except Exception Environment := do + if check then + _ ← (checkConstantVal env v.toConstantVal).run env + (safety := if v.isUnsafe then .unsafe else .safe) (lparams := v.levelParams) (fuel := fuel) + return env.add (.axiomInfo v) + +def addDefinition (env : Environment) (v : DefinitionVal) + (check := true) (fuel : FuelConfig := {}) : Except Exception Environment := do + if let .unsafe := v.safety then + -- Meta definition can be recursive. + -- So, we check the header, add, and then type check the body. + if check then + _ ← (checkConstantVal env v.toConstantVal).run env + (safety := .unsafe) (lparams := v.levelParams) (fuel := fuel) + let env' := env.add (.axiomInfo { v with isUnsafe := true }) + if check then + checkNoMVarNoFVar env' v.name v.value + M.run env' (safety := .unsafe) (lctx := {}) (lparams := v.levelParams) (fuel := fuel) do + let valType ← TypeChecker.checkType v.value + if !(← isDefEq valType v.type) then + throw <| .declTypeMismatch env' (.defnDecl v) valType + else if check then + M.run env (safety := .safe) (lctx := {}) (lparams := v.levelParams) (fuel := fuel) do + checkConstantVal env v.toConstantVal (← checkPrimitiveDef v) + checkNoMVarNoFVar env v.name v.value + let valType ← TypeChecker.checkType v.value + if !(← isDefEq valType v.type) then + throw <| .declTypeMismatch env (.defnDecl v) valType + return env.add (.defnInfo v) + +def addTheorem (env : Environment) (v : TheoremVal) (check := true) (fuel : FuelConfig := {}) : + Except Exception Environment := do + if check then + -- TODO(Leo): we must add support for handling tasks here + M.run env (safety := .safe) (lctx := {}) (lparams := v.levelParams) (fuel := fuel) do + checkConstantVal env v.toConstantVal + if !(← isProp v.type) then + throw <| .thmTypeIsNotProp env v.name v.type + checkNoMVarNoFVar env v.name v.value + let valType ← TypeChecker.checkType v.value + if !(← isDefEq valType v.type) then + throw <| .declTypeMismatch env (.thmDecl v) valType + return env.add (.thmInfo v) + +def addOpaque (env : Environment) (v : OpaqueVal) (check := true) (fuel : FuelConfig := {}) : + Except Exception Environment := do + if check then + M.run env (safety := .safe) (lctx := {}) (lparams := v.levelParams) (fuel := fuel) do + checkConstantVal env v.toConstantVal + checkNoMVarNoFVar env v.name v.value + let valType ← TypeChecker.checkType v.value + if !(← isDefEq valType v.type) then + throw <| .declTypeMismatch env (.opaqueDecl v) valType + return env.add (.opaqueInfo v) + +def addMutual (env : Environment) (vs : List DefinitionVal) + (check := true) (fuel : FuelConfig := {}) : Except Exception Environment := do + let v₀ :: _ := vs | throw <| .other "invalid empty mutual definition" + if let .safe := v₀.safety then + throw <| .other "invalid mutual definition, declaration is not tagged as unsafe/partial" + if check then + M.run env (safety := v₀.safety) (lctx := {}) (lparams := v₀.levelParams) (fuel := fuel) do + let mut found : NameSet := {} + for v in vs do + if v.safety != v₀.safety then + throw <| .other + "invalid mutual definition, declarations must have the same safety annotation" + -- The whole block is checked under one set of level parameters, so they must agree; + -- lean4#14608 adds the same check to the C++ kernel. + if v.levelParams != v₀.levelParams then + throw <| .other + "invalid mutual definition, declarations must have the same universe level parameters" + if found.contains v.name then + throw <| .other s!"invalid mutual definition, duplicate declaration name '{v.name}'" + found := found.insert v.name + checkConstantVal env v.toConstantVal + let env' := vs.foldl (init := env) fun env' v => + env'.add (.axiomInfo { v with isUnsafe := v₀.safety == .unsafe }) + if check then + M.run env' (safety := v₀.safety) (lctx := {}) (lparams := v₀.levelParams) (fuel := fuel) do + for v in vs do + checkNoMVarNoFVar env' v.name v.value + let valType ← TypeChecker.checkType v.value + if !(← isDefEq valType v.type) then + throw <| .declTypeMismatch env' (.mutualDefnDecl vs) valType + return vs.foldl (fun env' v => env'.add (.defnInfo v)) env + +/-- Type check given declaration and add it to the environment -/ +def addDecl (env : Environment) (decl : Declaration) (check := true) (fuel : FuelConfig := {}) : + Except Exception Environment := do + match decl with + | .axiomDecl v => addAxiom env v check fuel + | .defnDecl v => addDefinition env v check fuel + | .thmDecl v => addTheorem env v check fuel + | .opaqueDecl v => addOpaque env v check fuel + | .mutualDefnDecl v => addMutual env v check fuel + | .quotDecl => addQuot env + | .inductDecl lparams nparams types isUnsafe => + let allowPrimitive ← checkPrimitiveInductive env lparams nparams types isUnsafe + addInductive env lparams nparams types isUnsafe allowPrimitive fuel diff --git a/Ix/Theory/Named/Reference/Environment/Basic.lean b/Ix/Theory/Named/Reference/Environment/Basic.lean new file mode 100644 index 000000000..9ac92b87c --- /dev/null +++ b/Ix/Theory/Named/Reference/Environment/Basic.lean @@ -0,0 +1,226 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Environment +import Batteries.Tactic.OpenPrivate + +namespace Lean.Kernel.Environment + +def contains (env : Environment) (n : Name) : Bool := + env.constants.contains n + +def get (env : Environment) (n : Name) : Except Exception ConstantInfo := + match env.find? n with + | some ci => pure ci + | none => throw <| .unknownConstant env n + +def checkDuplicatedUnivParams : List Name → Except Exception Unit + | [] => pure () + | p :: ls => do + if p ∈ ls then + throw <| .other + s!"failed to add declaration to environment, duplicate universe level parameter: '{p}'" + checkDuplicatedUnivParams ls + +def checkNoMVar (env : Environment) (n : Name) (e : Expr) : Except Exception Unit := do + if e.hasMVar then + throw <| .declHasMVars env n e + +def checkNoFVar (env : Environment) (n : Name) (e : Expr) : Except Exception Unit := do + if e.hasFVar then + throw <| .declHasFVars env n e + +def checkNoMVarNoFVar (env : Environment) (n : Name) (e : Expr) : Except Exception Unit := do + checkNoMVar env n e + checkNoFVar env n e + +def primitives : NameSet := .ofList [ + ``Bool, ``Bool.false, ``Bool.true, + ``Nat, ``Nat.zero, ``Nat.succ, + ``Nat.add, ``Nat.pred, ``Nat.sub, ``Nat.mul, ``Nat.pow, + ``Nat.gcd, ``Nat.mod, ``Nat.div, ``Nat.beq, ``Nat.ble, + ``Nat.bitwise, ``Nat.land, ``Nat.lor, ``Nat.xor, + ``Nat.shiftLeft, ``Nat.shiftRight, + ``String.ofList, ``Char.ofNat] + +/-- +Returns true iff `constName` is a non-recursive inductive datatype that has only one constructor and no indices. + +Such types have special kernel support (e.g. the eta rule). +This must be in sync with `is_non_rec_structure()`. +-/ +def isNonRecStructure (env : Environment) (constName : Name) : Bool := + match env.find? constName with + | some (.inductInfo { isRec := false, ctors := [_], numIndices := 0, .. }) => true + | _ => false + +/-- A one-constructor, unindexed structure whose constructor and generated +recursor have both reached the host environment. Family metadata is staged +before either artifact is inserted; projection verification may only demand a +registered Theory view at this later boundary. + +Unlike `isNonRecStructure`, projection readiness deliberately does not inspect +`InductiveVal.isRec`: Lean emits primitive projections for recursive structures +too (including nested-recursive structures in the Lean prelude). -/ +def isProjectionReadyStructure (env : Environment) (constName : Name) : Bool := + match env.constants.find?' constName with + | some (.inductInfo { ctors := [ctor], numIndices := 0, .. }) => + match env.constants.find?' ctor, + env.constants.find?' (mkRecName constName) with + | some (.ctorInfo _), some (.recInfo _) => true + | _, _ => false + | _ => false + +theorem isProjectionReadyStructure_false_of_no_ctorInfo + {env : Environment} {name : Name} {info : InductiveVal} + (hfind : env.constants.find?' name = some (.inductInfo info)) + (hnoCtor : ∀ ctor ctorInfo, + env.constants.find?' ctor ≠ some (.ctorInfo ctorInfo)) : + env.isProjectionReadyStructure name = false := by + cases info + rename_i constant numParams numIndices all ctors numNested isRec isUnsafe isReflexive + cases constant + unfold isProjectionReadyStructure + rw [hfind] + cases numIndices with + | succ _ => rfl + | zero => + cases ctors with + | nil => rfl + | cons ctor rest => + cases rest with + | cons _ _ => rfl + | nil => + cases hctor : env.constants.find?' ctor with + | none => simp [hctor] + | some info => + cases info <;> simp_all + +theorem isProjectionReadyStructure_false_of_numIndices_ne + {env : Environment} {name : Name} {info : InductiveVal} + (hfind : env.constants.find?' name = some (.inductInfo info)) + (hindices : info.numIndices ≠ 0) : + env.isProjectionReadyStructure name = false := by + cases info + simp_all [isProjectionReadyStructure] + +theorem isProjectionReadyStructure_false_of_not_found + {env : Environment} {name : Name} + (hfind : env.constants.find?' name = none) : + env.isProjectionReadyStructure name = false := by + simp [isProjectionReadyStructure, hfind] + +def checkName (env : Environment) (n : Name) + (allowPrimitive := false) : Except Exception Unit := do + if env.contains n then + throw <| .alreadyDeclared env n + unless allowPrimitive do + if primitives.contains n then + throw <| .other s!"unexpected use of primitive name {n}" + +open private subsumesInfo Kernel.Environment.mk EnvironmentHeader.mk moduleNames + moduleNameMap parts toEffectiveImport getData? from Lean.Environment + +def empty (mainModule : Name) (trustLevel : UInt32 := 0) : Environment := + Kernel.Environment.mk + (constants := {}) + (quotInit := false) + (diagnostics := {}) + (const2ModIdx := {}) + (extensions := #[]) + (irBaseExts := #[]) + (header := EnvironmentHeader.mk + (mainModule := mainModule) + (trustLevel := trustLevel) + (isModule := false) + (imports := #[]) + (regions := #[]) + (modules := #[]) + (moduleName2Idx := {}) + (importAllModules := #[]) + (moduleData := #[])) + +/-- A minimal kernel environment backed by an explicit constant map. + +This is used by verified staged checks (for example, while an inductive family +has been inserted but its constructors have not). Such states are real kernel +checking stages but are not importable modules, so they intentionally carry no +extensions or module metadata. -/ +def ofConstants (mainModule : Name) (constants : ConstMap) + (quotInit := false) (trustLevel : UInt32 := 0) : Environment := + Kernel.Environment.mk + (constants := constants) + (quotInit := quotInit) + (diagnostics := {}) + (const2ModIdx := {}) + (extensions := #[]) + (irBaseExts := #[]) + (header := EnvironmentHeader.mk + (mainModule := mainModule) + (trustLevel := trustLevel) + (isModule := false) + (imports := #[]) + (regions := #[]) + (modules := #[]) + (moduleName2Idx := {}) + (importAllModules := #[]) + (moduleData := #[])) + +def throwAlreadyImported (s : ImportState) (const2ModIdx : Std.HashMap Name ModuleIdx) + (modIdx : Nat) (cname : Name) : Except Exception α := do + let modName := (moduleNames s)[modIdx]! + let constModName := (moduleNames s)[const2ModIdx[cname]!.toNat]! + throw <| .other + s!"import {modName} failed, environment already contains '{cname}' from {constModName}" + +def finalizeImport (s : ImportState) (imports : Array Import) (mainModule : Name) + (trustLevel : UInt32 := 0) : Except Exception Environment := do + let modules := (moduleNames s).filterMap ((moduleNameMap s)[·]?) + let moduleData ← modules.mapM fun mod => do + let some data := getData? mod .private | + throw <| .other s!"missing data file for module {mod.module}" + return data + let numConsts := moduleData.foldl (init := 0) fun numConsts data => Id.run do + numConsts + data.constants.size + let mut const2ModIdx := .emptyWithCapacity (capacity := numConsts) + let mut constantMap := .emptyWithCapacity (capacity := numConsts) + for h : modIdx in *...moduleData.size do + let data := moduleData[modIdx] + for cname in data.constNames, cinfo in data.constants do + match constantMap.getThenInsertIfNew? cname cinfo with + | (cinfoPrev?, constantMap') => + constantMap := constantMap' + if let some cinfoPrev := cinfoPrev? then + -- Recall that the map has not been modified when `cinfoPrev? = some _`. + if subsumesInfo constantMap cinfo cinfoPrev then + constantMap := constantMap.insert cname cinfo + else if !subsumesInfo constantMap cinfoPrev cinfo then + throwAlreadyImported s const2ModIdx modIdx cname + const2ModIdx := const2ModIdx.insertIfNew cname modIdx + for cname in data.extraConstNames do + const2ModIdx := const2ModIdx.insertIfNew cname modIdx + let mut moduleName2Idx := {} + for _h : idx in [0:modules.size] do + let mod := modules[idx] + moduleName2Idx := moduleName2Idx.insert mod.module idx + + return Kernel.Environment.mk + (constants := SMap.fromHashMap constantMap false) + (quotInit := !imports.isEmpty) -- We assume `Init.Prelude` initializes quotient module + (diagnostics := {}) + (const2ModIdx := const2ModIdx) + (extensions := #[]) + (irBaseExts := #[]) + (header := EnvironmentHeader.mk + (mainModule := mainModule) + (trustLevel := trustLevel) + (isModule := false) + (imports := imports) + (regions := modules.flatMap (parts · |>.map (·.2))) + (modules := modules.map toEffectiveImport) + (moduleName2Idx := moduleName2Idx) + (importAllModules := #[]) + (moduleData := moduleData)) diff --git a/Ix/Theory/Named/Reference/Expr.lean b/Ix/Theory/Named/Reference/Expr.lean new file mode 100644 index 000000000..78a87bd2a --- /dev/null +++ b/Ix/Theory/Named/Reference/Expr.lean @@ -0,0 +1,138 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Environment + +namespace Lean +namespace Expr + +def prop : Expr := .sort .zero + +/-- Transparent structural equality with the non-strict binder behavior used +by kernel expression comparison. Unlike `Expr.eqv`, this definition is +available to the kernel evaluator, so checker branch proofs do not require an +opaque implementation equation. -/ +def structuralEq : Expr → Expr → Bool + | .bvar i, .bvar j + | .fvar i, .fvar j + | .mvar i, .mvar j + | .sort i, .sort j + | .lit i, .lit j => i == j + | .const name levels, .const name' levels' => + name == name' && levels == levels' + | .app fn arg, .app fn' arg' => + structuralEq fn fn' && structuralEq arg arg' + | .lam _ domain body _, .lam _ domain' body' _ + | .forallE _ domain body _, .forallE _ domain' body' _ => + structuralEq domain domain' && structuralEq body body' + | .letE _ type value body nondep, + .letE _ type' value' body' nondep' => + structuralEq type type' && structuralEq value value' && + structuralEq body body' && nondep == nondep' + | .mdata data expr, .mdata data' expr' => + structuralEq expr expr' && data.entries == data'.entries + | .proj typeName index struct, .proj typeName' index' struct' => + structuralEq struct struct' && typeName == typeName' && index == index' + | _, _ => false + +def arrow (d b : Expr) : Expr := .forallE `a d b .default + +def lam0 (ty e : Expr) : Expr := .lam `_ ty e default + +namespace ReplaceImpl + +unsafe abbrev ReplaceT := StateT (PtrMap Expr Expr) + +@[inline] +unsafe def cacheT [Monad m] (key : Expr) (result : Expr) : ReplaceT m Expr := do + modify (·.insert key result) + pure result + +@[specialize] +unsafe def replaceUnsafeT [Monad m] (f? : Expr → m (Option Expr)) (e : Expr) : ReplaceT m Expr := do + let rec @[specialize] visit (e : Expr) := do + if let some result := (← get).find? e then + return result + match ← f? e with + | some eNew => cacheT e eNew + | none => match e with + | Expr.forallE _ d b _ => cacheT e <| e.updateForallE! (← visit d) (← visit b) + | Expr.lam _ d b _ => cacheT e <| e.updateLambdaE! (← visit d) (← visit b) + | Expr.mdata _ b => cacheT e <| e.updateMData! (← visit b) + | Expr.letE _ t v b nd => cacheT e <| e.updateLet! (← visit t) (← visit v) (← visit b) nd + | Expr.app f a => cacheT e <| e.updateApp! (← visit f) (← visit a) + | Expr.proj _ _ b => cacheT e <| e.updateProj! (← visit b) + | e => pure e + visit e + +@[inline] +unsafe def replaceUnsafe' [Monad m] (f? : Expr → m (Option Expr)) (e : Expr) : m Expr := + (replaceUnsafeT f? e).run' mkPtrMap + +end ReplaceImpl + +/- TODO: use withPtrAddr, withPtrEq to avoid unsafe tricks above. + We also need an invariant at `State` and proofs for the `uget` operations. -/ + +@[specialize] +def replaceNoCacheT [Monad m] (f? : Expr → m (Option Expr)) (e : Expr) : m Expr := do + match ← f? e with + | some eNew => pure eNew + | none => match e with + | .forallE _ d b _ => + return e.updateForallE! (← replaceNoCacheT f? d) (← replaceNoCacheT f? b) + | .lam _ d b _ => + return e.updateLambdaE! (← replaceNoCacheT f? d) (← replaceNoCacheT f? b) + | .mdata _ b => + return e.updateMData! (← replaceNoCacheT f? b) + | .letE _ t v b nd => + return e.updateLet! + (← replaceNoCacheT f? t) (← replaceNoCacheT f? v) (← replaceNoCacheT f? b) nd + | .app f a => + return e.updateApp! (← replaceNoCacheT f? f) (← replaceNoCacheT f? a) + | .proj _ _ b => + return e.updateProj! (← replaceNoCacheT f? b) + | e => return e + +@[implemented_by ReplaceImpl.replaceUnsafe'] +partial def replaceM [Monad m] (f? : Expr → m (Option Expr)) (e : Expr) : m Expr := + e.replaceNoCacheT f? + +def natZero : Expr := .const ``Nat.zero [] +def natSucc : Expr := .const ``Nat.succ [] + +def isConstructorApp?' (env : Kernel.Environment) (e : Expr) : Option Name := do + let .const fn _ := e.getAppFn | none + let .ctorInfo _ ← env.find? fn | none + return fn + +def natLitToConstructor : Nat → Expr + | 0 => natZero + | n+1 => .app natSucc (.lit (.natVal n)) + +def strLitToConstructor (s : String) : Expr := + let char := .const ``Char [] + let listNil := .app (.const ``List.nil [.zero]) char + let listCons := .app (.const ``List.cons [.zero]) char + let stringMk := .const ``String.ofList [] + let charOfNat := .const ``Char.ofNat [] + .app stringMk <| s.toList.foldr (init := listNil) fun c e => -- TODO: use String.foldr + .app (.app listCons <| .app charOfNat (.lit (.natVal c.toNat))) e + +end Expr + +namespace Literal + +def toConstructor : Literal → Expr + | .natVal n => .natLitToConstructor n + | .strVal s => .strLitToConstructor s + +/-- Return the type of a literal value. -/ +def typeName : Literal → Name + | .natVal _ => ``Nat + | .strVal _ => ``String + +end Literal diff --git a/Ix/Theory/Named/Reference/ForEachExprV.lean b/Ix/Theory/Named/Reference/ForEachExprV.lean new file mode 100644 index 000000000..02bc56362 --- /dev/null +++ b/Ix/Theory/Named/Reference/ForEachExprV.lean @@ -0,0 +1,36 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Expr +import Lean.Util.MonadCache + +/-! +This is the same as `Expr.forEach` but it uses `StateT` instead of `StateRefT` to avoid opaques. +-/ +namespace Lean +variable {ω : Type} {m : Type → Type} [Monad m] + +namespace ForEachExprV +def visit (g : Expr → m Bool) (e : Expr) : MonadStateCacheT Expr Unit m Unit := + checkCache e fun _ => do + if (← g e) then + match e with + | Expr.forallE _ d b _ => do visit g d; visit g b + | Expr.lam _ d b _ => do visit g d; visit g b + | Expr.letE _ t v b _ => do visit g t; visit g v; visit g b + | Expr.app f a => do visit g f; visit g a + | Expr.mdata _ b => visit g b + | Expr.proj _ _ b => visit g b + | _ => pure () + +end ForEachExprV + +/-- Apply `f` to each sub-expression of `e`. If `f t` returns false, then t's children are not visited. -/ +@[inline] def Expr.forEachV' (e : Expr) (f : Expr → m Bool) : m Unit := + (ForEachExprV.visit f e).run + +@[inline] def Expr.forEachV (e : Expr) (f : Expr → m Unit) : m Unit := + e.forEachV' fun e => do f e; pure true diff --git a/Ix/Theory/Named/Reference/FuelConfig.lean b/Ix/Theory/Named/Reference/FuelConfig.lean new file mode 100644 index 000000000..88e8c02a4 --- /dev/null +++ b/Ix/Theory/Named/Reference/FuelConfig.lean @@ -0,0 +1,41 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Data.Json.FromToJson + +namespace Ix.Theory.Named + +/-- +Bounds for the various fixed-fuel loops inside the kernel. + +Every field is a positive `Nat`; on exhaustion the corresponding loop throws +`.deterministicTimeout` (whnf-family) or `.deepRecursion` (structural / +mutual-recursion loops). + +Defaults are set so mathlib passes. Since lean4#13956 the native kernel bounds +its mutually recursive type-checker entry points using `maxRecDepth`. +The named reference implementation instead keeps separate, explicit fuel for those calls and for loops +that need structural termination witnesses; these counters also provide a +deterministic defensive check against runaway reductions. +-/ +structure FuelConfig where + /-- `whnf'` unfold-loop, non-eager path (`TypeChecker.lean` whnf'). -/ + whnf : Nat := 100000 + /-- `whnf'` unfold-loop, `eagerReduce` path. -/ + whnfEager : Nat := 1000000 + /-- `lazyDeltaReduction.loop`. -/ + lazyDelta : Nat := 1000 + /-- `etaExpand.loop.loop2`. -/ + etaExpand : Nat := 1000 + /-- Starting fuel for `Methods.withFuel` (bounds mutual whnf/isDefEq depth). -/ + recDepth : Nat := 10000 + /-- Shared fuel for the structural loops in `Inductive/Add.lean`. -/ + inductiveFuel : Nat := 1000 + /-- Upper bound, in bytes, on the `Nat` numerals the kernel will accept or compute while + reducing `Nat` literals. Bounds the memory and time a single reduction can consume. The + native kernel spells this bound `LEAN_NAT_MAX_SIZE` and defaults it to the same 128 MB. -/ + natMaxSize : Nat := 134217728 -- 128 MB; a literal so `simp` cannot renormalize it + deriving Repr, Inhabited, Lean.FromJson, Lean.ToJson diff --git a/Ix/Theory/Named/Reference/Inductive/Add.lean b/Ix/Theory/Named/Reference/Inductive/Add.lean new file mode 100644 index 000000000..7a7c29a38 --- /dev/null +++ b/Ix/Theory/Named/Reference/Inductive/Add.lean @@ -0,0 +1,2941 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Batteries.Data.List.Basic +import Ix.Theory.Named.Reference.Environment.Basic +import Ix.Theory.Named.Reference.TypeChecker + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +open private Lean.Kernel.Environment.add from Lean.Environment + +namespace AddInductive +open TypeChecker + +structure RecInfo where + motive : Expr + minors : Array Expr + indices : Array Expr + major : Expr + deriving Inhabited + +structure InductiveStats where + lctx : LocalContext := {} + levels : List Level + resultLevel : Level + nindices : Array Nat := #[] + indConsts : Array Expr + params : Array Expr + isNotZero : Bool + deriving Inhabited + +/-- Explicit initial state for family validation. Naming this value keeps the +executable producer and its exact-result lemmas independent of the opaque +compiler-generated `Inhabited` instance. -/ +def InductiveStats.initial (levels : List Level) : InductiveStats where + levels := levels + resultLevel := .zero + indConsts := #[] + params := #[] + isNotZero := false + +structure Context where + env : Environment + lctx : LocalContext := {} + lparams : List Name + ngen : NameGenerator := { namePrefix := `_ind_fresh } + safety : DefinitionSafety + allowPrimitive : Bool + fuel : FuelConfig := {} + +/-- Checker context represented by an inductive-add context. Candidate traces +retain the latter so Verify can recover this exact former value. -/ +def Context.toTypeChecker (context : Context) : TypeChecker.Context where + env := context.env + lctx := context.lctx + safety := context.safety + lparams := context.lparams + fuel := context.fuel + +/-- The exact free variable allocated by the next `withLocalDecl` in an +inductive-add context. -/ +def Context.freshFVarId (context : Context) : FVarId := + ⟨context.ngen.curr⟩ + +def Context.freshExpr (context : Context) : Expr := + .fvar context.freshFVarId + +/-- Context seen by the body of the next `withLocalDecl`. Naming this update +lets candidate traces index a Pi body by the actual reader context used by the +producer, rather than retaining an unrelated context as unchecked data. -/ +def Context.pushLocalDecl (context : Context) + (name : Name) (binderInfo : BinderInfo) (type : Expr) : Context := + { context with + lctx := context.lctx.mkLocalDecl context.freshFVarId name type binderInfo + ngen := context.ngen.next } + +abbrev M := ReaderT Context <| Except Exception + +instance : MonadLocalNameGenerator M where + withFreshId f c := f c.ngen.curr { c with ngen := c.ngen.next } + +instance (priority := low) : MonadLift TypeChecker.M M where + monadLift x c := x.run c.env c.safety c.lctx c.lparams (fuel := c.fuel) + +@[simp] theorem liftTypeChecker_apply (x : TypeChecker.M α) (c : Context) : + (liftM x : M α) c = + x.run c.env c.safety c.lctx c.lparams (fuel := c.fuel) := + rfl + +@[simp] theorem liftExcept_apply (x : Except Exception α) (c : Context) : + (liftM x : M α) c = x := + rfl + +instance (priority := low+1) : MonadWithReaderOf LocalContext M where + withReader f x := withReader (fun c => { c with lctx := f c.lctx }) x + +instance : MonadLCtx M where + getLCtx := return (← read).lctx + +@[simp] theorem withLocalDecl_apply + (name : Name) (binderInfo : BinderInfo) (type : Expr) + (k : Expr → M α) (context : Context) : + withLocalDecl name binderInfo type k context = + k context.freshExpr + (context.pushLocalDecl name binderInfo type) := by + rfl + +@[inline] def withEnv (env : Environment) (x : M α) : M α := + withReader (fun c => { c with env }) x + +/-- Run an action under a different universe parameter list. The recursors are checked under +their own parameters, which carry the extra eliminator level the declaration itself lacks. -/ +@[inline] def withLParams (lparams : List Name) (x : M α) : M α := + withReader (fun c => { c with lparams }) x + +/-- Run a closed-metadata action without inheriting validation-local +declarations. All other reader fields, including the staged environment and +fuel, are preserved exactly. -/ +@[inline] def withEmptyLocalContext (x : M α) : M α := + withReader (fun c : Context => { c with lctx := {} }) x + +@[simp] theorem withEmptyLocalContext_apply (x : M α) (context : Context) : + withEmptyLocalContext x context = x { context with lctx := {} } := by + rfl + +def getType (fvar : Expr) : M Expr := + return ((← getLCtx).get! fvar.fvarId!).type + +/-- Transparent binder-annotation peeling used by inductive checking. + +Lean's `Expr.consumeTypeAnnotations` is an opaque partial implementation. A +kernel proof of an exact successful inductive pass cannot reduce through that +helper, so using it directly would require a separate contract axiom for every +annotated binder. This structural mirror covers the same four top-level +annotations and is regression-checked against Lean's helper below at the +candidate boundary. -/ +def consumeTypeAnnotations : (source : Expr) → Expr + | .app (.app (.const name levels) type) default => + if name = ``_root_.optParam then + consumeTypeAnnotations type + else if name = ``_root_.autoParam then + consumeTypeAnnotations type + else + .app (.app (.const name levels) type) default + | .app (.const name levels) type => + if name = ``_root_.outParam then + consumeTypeAnnotations type + else if name = ``_root_.semiOutParam then + consumeTypeAnnotations type + else + .app (.const name levels) type + | source => source +termination_by source => sizeOf source + +/-- Transparent structural equality used only as a fast path before the +normalization-based universe comparison. -/ +def levelStructEq : Level → Level → Bool + | .zero, .zero => true + | .succ u, .succ v => levelStructEq u v + | .max u₁ u₂, .max v₁ v₂ | .imax u₁ u₂, .imax v₁ v₂ => + levelStructEq u₁ v₁ && levelStructEq u₂ v₂ + | .param u, .param v => u == v + | .mvar u, .mvar v => u == v + | _, _ => false + +/-- Transparent sufficient comparison for the common structural universe +cases used by constructor fields. Every universe is at least zero, successor +is monotone, and otherwise exact structural equality is sufficient. Cases +outside this deliberately small relation continue to the standard +normalization-based `Level.geq` comparison below. -/ +def levelStructGe : Level → Level → Bool + | _, .zero => true + | .succ u, .succ v => levelStructGe u v + | u, v => levelStructEq u v + +def checkInductiveTypes + (nparams : Nat) (indTypes : Array InductiveType) + (k : InductiveStats → M α) : M α := do + let rec loopInd dIdx stats : M α := do + if _h : dIdx < indTypes.size then + let indType := indTypes[dIdx] + let env := (← read).env + let type := indType.type + env.checkNoMVarNoFVar indType.name type + _ ← checkType type + let rec loop stats type i nindices fuel k : M α := match fuel with + | 0 => throw .deepRecursion + | fuel+1 => do + if let .forallE name dom body bi := type then + if i < nparams then + if stats.indConsts.isEmpty then + withLocalDecl name bi (consumeTypeAnnotations dom) fun param => do + let stats := { stats with params := stats.params.push param } + let type := body.instantiate1 param + loop stats (← whnf type) (i + 1) nindices fuel k + else + let param := stats.params[i]! + unless ← isDefEq dom (← getType param) do + throw <| .other "parameters of all inductive datatypes must match" + let type := body.instantiate1 param + loop stats (← whnf type) (i + 1) nindices fuel k + else + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + let type := body.instantiate1 arg + loop stats (← whnf type) i (nindices + 1) fuel k + else + if i != nparams then + throw <| .other "number of parameters mismatch in inductive datatype declaration" + k type stats nindices + let fuel := (← readThe Context).fuel.inductiveFuel + loop stats (← whnf type) 0 0 fuel fun type stats nindices => show M α from do + let type ← ensureSort type + let mut stats := stats + let resultLevel := type.sortLevel! + if stats.indConsts.isEmpty then + let lctx := (← read).lctx + stats := { stats with lctx, resultLevel, isNotZero := resultLevel.isNeverZero } + else if !resultLevel.isEquiv stats.resultLevel then + throw <| .other "mutually inductive types must live in the same universe" + stats := { stats with + nindices := stats.nindices.push nindices + indConsts := stats.indConsts.push (.const indType.name stats.levels) } + loopInd (dIdx + 1) stats + else + k <| + assert! stats.levels.length == (← read).lparams.length + assert! stats.nindices.size == indTypes.size + assert! stats.indConsts.size == indTypes.size + assert! stats.params.size == nparams + stats + termination_by indTypes.size - dIdx + loopInd 0 (InductiveStats.initial ((← read).lparams.map .param)) + +/-- Exact singleton result of the family-validation pass when the family type +normalizes directly to a sort. This is the non-telescope producer seam used by +end-to-end candidate certificates: the executable pass selects every retained +statistic, while callers supply only the ordinary checker runs it consumed. -/ +def singletonInductiveStats (context : Context) + (indType : InductiveType) (resultLevel : Level) : InductiveStats where + lctx := context.lctx + levels := context.lparams.map .param + resultLevel := resultLevel + nindices := #[0] + indConsts := #[.const indType.name (context.lparams.map .param)] + params := #[] + isNotZero := resultLevel.isNeverZero + +theorem checkInductiveTypes_singleton_zero_of_whnf_sort + (context : Context) (indType : InductiveType) + (inferred : Expr) (resultLevel : Level) + (k : InductiveStats → M α) + (hfuel : 0 < context.fuel.inductiveFuel) + (hclosed : + context.env.checkNoMVarNoFVar indType.name indType.type = .ok ()) + (hcheck : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.checkType indType.type) = + .ok inferred) + (hwhnf : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf indType.type) = + .ok (.sort resultLevel)) + (hensure : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel + (TypeChecker.ensureSort (.sort resultLevel)) = + .ok (.sort resultLevel)) : + checkInductiveTypes 0 #[indType] k context = + k (singletonInductiveStats context indType resultLevel) context := by + cases hfuel_eq : context.fuel.inductiveFuel with + | zero => omega + | succ fuel => + simp [checkInductiveTypes, checkInductiveTypes.loopInd, checkInductiveTypes.loopInd.loop, + singletonInductiveStats, readThe, MonadReader.read, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, Except.bind, Except.pure, liftTypeChecker_apply, hclosed, + hcheck, hwhnf, hensure, hfuel_eq, InductiveStats.initial, Expr.sortLevel!] + +/-- Transparent occurrence test for constants in the inductive block. + +Lean's `Expr.find?` is an opaque native traversal. Using it here makes the +kernel's recursive-family and positivity decisions impossible to reduce in an +exact producer theorem without postulating a separate contract for that +traversal. This structural version follows the same expression children and +keeps those decisions computational in the logic as well as at runtime. -/ +def hasIndOcc (indConsts : Array Expr) : Expr → Bool + | .const name _ => indConsts.any fun I => I.constName! == name + | .app fn arg => hasIndOcc indConsts fn || hasIndOcc indConsts arg + | .lam _ domain body _ | .forallE _ domain body _ => + hasIndOcc indConsts domain || hasIndOcc indConsts body + | .letE _ type value body _ => + hasIndOcc indConsts type || hasIndOcc indConsts value || + hasIndOcc indConsts body + | .mdata _ body | .proj _ _ body => hasIndOcc indConsts body + | _ => false + +/-- Return true if declaration is recursive -/ +def isRec (indTypes : Array InductiveType) (indConsts : Array Expr) : Bool := + let rec loop + | .forallE _ dom body _ => hasIndOcc indConsts dom || loop body + | _ => false + indTypes.any fun indType => indType.ctors.any fun ctor => loop ctor.type + +/-- Return true if the given declaration is reflexive. + +Remark: We say an inductive type `T` is reflexive if it +contains at least one constructor that takes as an argument a +function returning `T'` where `T'` is another inductive datatype (possibly equal to `T`) +in the same mutual declaration. -/ +def isReflexive (indTypes : Array InductiveType) (indConsts : Array Expr) : Bool := + let rec loop + | .forallE _ dom body _ => dom.isForall && hasIndOcc indConsts dom || loop body + | _ => false + indTypes.any fun indType => indType.ctors.any fun ctor => loop ctor.type + +def declareInductiveTypes (stats : InductiveStats) (numParams : Nat) + (indTypes : Array InductiveType) (numNested : Nat) (isUnsafe : Bool) : M Environment := + fun c => + let all := indTypes.map (·.name) |>.toList + let infos := indTypes.zipWith (bs := stats.nindices) fun indType numIndices => + { indType with + numParams, numIndices, all, numNested, isUnsafe + levelParams := c.lparams + ctors := indType.ctors.map (·.name) + isRec := isRec indTypes stats.indConsts + isReflexive := isReflexive indTypes stats.indConsts } + infos.foldlM (init := c.env) fun env info => do + env.checkName info.name c.allowPrimitive + return env.add (.inductInfo info) + +/-- The exact kernel family record assembled for a singleton inductive block. +Naming it exposes the value installed by `declareInductiveTypes` without +asking a replay proof to duplicate the producer's record construction. -/ +def singletonDeclaredInfo (stats : InductiveStats) (numParams numIndices : Nat) + (indType : InductiveType) (numNested : Nat) (isUnsafe : Bool) + (context : Context) : InductiveVal := + { indType with + numParams, numIndices, all := [indType.name], numNested, isUnsafe + levelParams := context.lparams + ctors := indType.ctors.map (·.name) + isRec := isRec #[indType] stats.indConsts + isReflexive := isReflexive #[indType] stats.indConsts } + +/-- A successful singleton family declaration installs exactly the family +record assembled by the executable producer. The result equation supplies +the name-check evidence; replay callers provide only the validator's exact +singleton index count. -/ +theorem declareInductiveTypes_singleton_constants + (stats : InductiveStats) (numParams numIndices : Nat) + (indType : InductiveType) (numNested : Nat) (isUnsafe : Bool) + (context : Context) (familyEnv : Environment) + (hnindices : stats.nindices = #[numIndices]) + (hdeclare : + declareInductiveTypes stats numParams #[indType] numNested isUnsafe context = + .ok familyEnv) : + familyEnv.constants = + context.env.constants.insert indType.name + (.inductInfo <| singletonDeclaredInfo stats numParams numIndices + indType numNested isUnsafe context) := by + unfold declareInductiveTypes at hdeclare + rw [hnindices] at hdeclare + cases hcheck : context.env.checkName indType.name context.allowPrimitive with + | error error => + simp [hcheck, Bind.bind, Except.bind, Pure.pure, Except.pure] at hdeclare + | ok _ => + simp [hcheck, Bind.bind, Except.bind, Pure.pure, Except.pure] at hdeclare + exact congrArg Kernel.Environment.constants hdeclare.symm + +/-- A successful singleton family declaration changes only the constant map; +in particular it preserves the kernel's quotient-initialization flag. -/ +theorem declareInductiveTypes_singleton_quotInit + (stats : InductiveStats) (numParams numIndices : Nat) + (indType : InductiveType) (numNested : Nat) (isUnsafe : Bool) + (context : Context) (familyEnv : Environment) + (hnindices : stats.nindices = #[numIndices]) + (hdeclare : + declareInductiveTypes stats numParams #[indType] numNested isUnsafe context = + .ok familyEnv) : + familyEnv.quotInit = context.env.quotInit := by + unfold declareInductiveTypes at hdeclare + rw [hnindices] at hdeclare + cases hcheck : context.env.checkName indType.name context.allowPrimitive with + | error error => + simp [hcheck, Bind.bind, Except.bind, Pure.pure, Except.pure] at hdeclare + | ok _ => + simp [hcheck, Bind.bind, Except.bind, Pure.pure, Except.pure] at hdeclare + subst familyEnv + rfl + +/-- Family declaration observes only the environment, universe parameters, +and primitive-name policy of its reader context. In particular, the local +telescope and fresh-name generator retained by family validation do not alter +the staged environment it produces. -/ +theorem declareInductiveTypes_context_eq + (stats : InductiveStats) (numParams : Nat) + (indTypes : Array InductiveType) (numNested : Nat) + (isUnsafe : Bool) (left right : Context) + (henv : left.env = right.env) + (hlparams : left.lparams = right.lparams) + (hallow : left.allowPrimitive = right.allowPrimitive) : + declareInductiveTypes stats numParams indTypes numNested isUnsafe left = + declareInductiveTypes stats numParams indTypes numNested isUnsafe right := by + unfold declareInductiveTypes + rw [henv, hlparams, hallow] + +def isValidIndAppIdx (stats : InductiveStats) (t : Expr) (i : Nat) : Bool := + t.withApp fun I args => Id.run do + unless I == stats.indConsts[i]! && args.size == stats.params.size + stats.nindices[i]! do + return false + for i in [:stats.params.size] do + if stats.params[i]! != args[i]! then return false + for i in [stats.params.size:args.size] do + if hasIndOcc stats.indConsts args[i]! then return false + true + +def isValidIndApp? (stats : InductiveStats) (t : Expr) : Option Nat := do + for i in [:stats.indConsts.size] do + if isValidIndAppIdx stats t i then + return i + none + +theorem isValidIndApp?_singleton_zero + (stats : InductiveStats) (t : Expr) + (hsize : stats.indConsts.size = 1) + (hvalid : isValidIndAppIdx stats t 0 = true) : + isValidIndApp? stats t = some 0 := by + unfold isValidIndApp? + simp [hsize, hvalid] + +def isRecArg (stats : InductiveStats) (t : Expr) : M (Option Nat) := do + loop t (← readThe Context).fuel.inductiveFuel +where + loop t + | 0 => throw .deepRecursion + | fuel+1 => do + let t ← whnf t + let .forallE name dom body bi := t | return isValidIndApp? stats t + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + loop (body.instantiate1 arg) fuel + +def checkPositivity (stats : InductiveStats) (t : Expr) (ctor : Name) (idx : Nat) : + M Unit := do loop t (← readThe Context).fuel.inductiveFuel where + loop t + | 0 => throw .deepRecursion + | fuel+1 => do + let t ← whnf t + if !hasIndOcc stats.indConsts t then return + if let .forallE name dom body bi := t then + if hasIndOcc stats.indConsts dom then + throw <| .other s!"arg #{idx + 1} of '{ctor}' \ + has a non positive occurrence of the datatypes being declared" + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + loop (body.instantiate1 arg) fuel + else if let none := isValidIndApp? stats t then + throw <| .other s!"arg #{idx + 1} of '{ctor}' \ + has a non valid occurrence of the datatypes being declared" + +/-- Validate the parameter/field telescope and terminal family application of +one constructor. This is factored from the outer traversal so successful +executions can be retained without reproducing compiler-expanded `for` loops. -/ +def checkConstructorType (stats : InductiveStats) (isUnsafe : Bool) + (idx : Nat) (n : Name) (t : Expr) : M Unit := do + loop t 0 (← readThe Context).fuel.inductiveFuel +where + loop t i + | 0 => throw .deepRecursion + | fuel+1 => do + if let .forallE name dom body bi := t then + if let some param := stats.params[i]? then + unless ← isDefEq dom (← getType param) do + throw <| .other + s!"arg #{i + 1} of '{n}' does not match inductive datatype parameters" + loop (body.instantiate1 param) (i + 1) fuel + else + let s ← ensureType dom + -- Equal levels are reflexively admissible, so discharge that common + -- case before consulting the full normalization comparison. + if levelStructGe stats.resultLevel s.sortLevel! then + pure () + else + unless stats.resultLevel.isAlwaysZero || stats.resultLevel.geq s.sortLevel! do + throw <| .other s!"universe level of type_of(arg #{i + 1}) of '{n}' \ + is too big for the corresponding inductive datatype" + if !isUnsafe then + checkPositivity stats dom n i + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + loop (body.instantiate1 arg) (i + 1) fuel + else if !isValidIndAppIdx stats t idx then + throw <| .other s!"invalid return type for '{n}'" + +/-- Validate constructors in source order while retaining the duplicate-name +accumulator as the fold result. -/ +def checkConstructorFold (env : Environment) (stats : InductiveStats) + (isUnsafe : Bool) (idx : Nat) (seen : NameSet) + (ctors : List Constructor) : M NameSet := match ctors with + | [] => pure seen + | ctor :: ctors => do + let n := ctor.name + if seen.contains n then + throw <| .other s!"duplicate constructor name '{n}'" + let seen := seen.insert n + let t := ctor.type + env.checkNoMVarNoFVar n t + -- Constructor metadata has just been established to contain no free + -- variables. Its full closed-type check does not inherit family locals; + -- parameter matching in `checkConstructorType` deliberately does. + _ ← withEmptyLocalContext do checkType t + checkConstructorType stats isUnsafe idx n t + checkConstructorFold env stats isUnsafe idx seen ctors + +/-- The named family recursion of `checkConstructors`. Naming the loop keeps +the executable shell and its validation-trace mirror aligned without depending +on proof terms synthesized by `for` notation. -/ +def checkConstructorsLoop (env : Environment) (stats : InductiveStats) + (isUnsafe : Bool) : Nat → List InductiveType → M Unit + | _, [] => pure () + | idx, indType :: rest => do + _ ← checkConstructorFold env stats isUnsafe idx {} indType.ctors + checkConstructorsLoop env stats isUnsafe (idx + 1) rest + +def checkConstructors (indTypes : Array InductiveType) + (stats : InductiveStats) (isUnsafe : Bool) : M Unit := do + let env ← getEnv + checkConstructorsLoop env stats isUnsafe 0 indTypes.toList + +/-- One observed WHNF node in the executable normalization-candidate pass. +The complete `AddInductive.Context` is retained because Verify must replay the +same environment, safety mode, local context, level parameters, transparency, +and checker fuel before the observation acquires semantic authority. -/ +structure CandidateWhnfStep where + context : Context + source : Expr + result : Expr + +/-- Exact ordinary-checker execution represented by one retained step. -/ +def CandidateWhnfStep.Valid (step : CandidateWhnfStep) : Prop := + TypeChecker.M.run step.context.env step.context.safety + step.context.lctx step.context.lparams step.context.fuel + (TypeChecker.whnf step.source) = + .ok step.result + +/-- The result of evaluating one WHNF step together with the equality that +certifies the observation. -/ +structure CandidateWhnfObservation (context : Context) (source : Expr) where + result : Expr + valid : CandidateWhnfStep.Valid ⟨context, source, result⟩ + +def observeCandidateWhnf (context : Context) (source : Expr) : + Except Exception (CandidateWhnfObservation context source) := + match hrun : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf source) with + | .error err => .error err + | .ok result => .ok ⟨result, hrun⟩ + +theorem observeCandidateWhnf_of_run + (context : Context) (source result : Expr) + (hrun : CandidateWhnfStep.Valid ⟨context, source, result⟩) : + observeCandidateWhnf context source = .ok ⟨result, hrun⟩ := by + change + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf source) = + .ok result at hrun + unfold observeCandidateWhnf + split + · simp_all + · rename_i observed hobserved + have : observed = result := by simp_all + subst observed + rfl + +/-- Recover the state-bearing recursive checker execution erased by +`TypeChecker.M.run`. This is the exact `WhnfRun.run_eq` boundary used by +Verify; no final state is guessed or chosen. -/ +theorem CandidateWhnfStep.innerRun + (step : CandidateWhnfStep) (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel + 1) + (hvalid : step.Valid) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.whnf' step.source + (TypeChecker.Methods.withFuel recursionFuel) + step.context.toTypeChecker + ({} : TypeChecker.State) = + .ok (step.result, state) := by + unfold CandidateWhnfStep.Valid at hvalid + unfold TypeChecker.M.run TypeChecker.whnf TypeChecker.RecM.run at hvalid + simp [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, StateT.bind, Except.bind, Bind.bind, + StateT.pure, Except.pure, Pure.pure, + StateT.run', Functor.map, Except.map] at hvalid + rw [hdepth] at hvalid + simp only [TypeChecker.Methods.withFuel, + TypeChecker.Inner.whnf] at hvalid + cases hinner : + TypeChecker.Inner.whnf' step.source + (TypeChecker.Methods.withFuel recursionFuel) + { env := step.context.env + lctx := step.context.lctx + safety := step.context.safety + lparams := step.context.lparams + fuel := step.context.fuel } + ({} : TypeChecker.State) with + | error err => simp [hinner] at hvalid + | ok pair => + rcases pair with ⟨observed, state⟩ + have : observed = step.result := by + simpa [hinner] using hvalid + subst observed + exact ⟨state, by + simpa [Context.toTypeChecker] using hinner⟩ + +/-- One full, non-inference-only type-check observation retained by the +candidate producer. -/ +structure CandidateCheckTypeStep where + context : Context + source : Expr + inferred : Expr + +def CandidateCheckTypeStep.Valid + (step : CandidateCheckTypeStep) : Prop := + TypeChecker.M.run step.context.env step.context.safety + step.context.lctx step.context.lparams step.context.fuel + (TypeChecker.checkType step.source) = + .ok step.inferred + +structure CandidateCheckTypeObservation + (context : Context) (source : Expr) where + inferred : Expr + valid : CandidateCheckTypeStep.Valid ⟨context, source, inferred⟩ + +def observeCandidateCheckType (context : Context) (source : Expr) : + Except Exception (CandidateCheckTypeObservation context source) := + match hrun : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.checkType source) with + | .error err => .error err + | .ok inferred => .ok ⟨inferred, hrun⟩ + +theorem observeCandidateCheckType_of_run + (context : Context) (source inferred : Expr) + (hrun : CandidateCheckTypeStep.Valid + ⟨context, source, inferred⟩) : + observeCandidateCheckType context source = + .ok ⟨inferred, hrun⟩ := by + change + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.checkType source) = + .ok inferred at hrun + unfold observeCandidateCheckType + split + · simp_all + · rename_i observed hobserved + have : observed = inferred := by simp_all + subst observed + rfl + +/-- Recover the state-bearing full-check execution erased by `M.run`. -/ +theorem CandidateCheckTypeStep.innerRun + (step : CandidateCheckTypeStep) (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel) + (hvalid : step.Valid) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.inferType step.source false + (TypeChecker.Methods.withFuel recursionFuel) + step.context.toTypeChecker + ({} : TypeChecker.State) = + .ok (step.inferred, state) := by + unfold CandidateCheckTypeStep.Valid at hvalid + unfold TypeChecker.M.run TypeChecker.checkType + TypeChecker.RecM.run at hvalid + simp [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, StateT.bind, Except.bind, Bind.bind, + StateT.pure, Except.pure, Pure.pure, + StateT.run', Functor.map, Except.map] at hvalid + rw [hdepth] at hvalid + cases hinner : + TypeChecker.Inner.inferType step.source false + (TypeChecker.Methods.withFuel recursionFuel) + { env := step.context.env + lctx := step.context.lctx + safety := step.context.safety + lparams := step.context.lparams + fuel := step.context.fuel } + ({} : TypeChecker.State) with + | error err => simp [hinner] at hvalid + | ok pair => + rcases pair with ⟨observed, state⟩ + have : observed = step.inferred := by + simpa [hinner] using hvalid + subst observed + exact ⟨state, by + simpa [Context.toTypeChecker] using hinner⟩ + +/-- One exact successful definitional-equality observation retained by the +candidate producer. The result is fixed to `true`; a negative checker result +is not evidence and aborts candidate construction. -/ +structure CandidateIsDefEqStep where + context : Context + lhs : Expr + rhs : Expr + +def CandidateIsDefEqStep.Valid + (step : CandidateIsDefEqStep) : Prop := + TypeChecker.M.run step.context.env step.context.safety + step.context.lctx step.context.lparams step.context.fuel + (TypeChecker.isDefEq step.lhs step.rhs) = + .ok true + +structure CandidateIsDefEqObservation + (context : Context) (lhs rhs : Expr) : Type where + valid : CandidateIsDefEqStep.Valid ⟨context, lhs, rhs⟩ + +def observeCandidateIsDefEq + (context : Context) (lhs rhs : Expr) : + Except Exception (CandidateIsDefEqObservation context lhs rhs) := + match hrun : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.isDefEq lhs rhs) with + | .error err => .error err + | .ok false => + .error (.other "normalization candidate changed a binder domain") + | .ok true => .ok ⟨hrun⟩ + +theorem observeCandidateIsDefEq_of_run + (context : Context) (lhs rhs : Expr) + (hrun : CandidateIsDefEqStep.Valid ⟨context, lhs, rhs⟩) : + observeCandidateIsDefEq context lhs rhs = .ok ⟨hrun⟩ := by + change + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.isDefEq lhs rhs) = + .ok true at hrun + unfold observeCandidateIsDefEq + split + · simp_all + · simp_all + · rfl + +/-- Recover the state-bearing equality execution erased by `M.run`. -/ +theorem CandidateIsDefEqStep.innerRun + (step : CandidateIsDefEqStep) (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel) + (hvalid : step.Valid) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.isDefEq step.lhs step.rhs + (TypeChecker.Methods.withFuel recursionFuel) + step.context.toTypeChecker + ({} : TypeChecker.State) = + .ok (true, state) := by + unfold CandidateIsDefEqStep.Valid at hvalid + unfold TypeChecker.M.run TypeChecker.isDefEq + TypeChecker.RecM.run at hvalid + simp [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, StateT.bind, Except.bind, Bind.bind, + StateT.pure, Except.pure, Pure.pure, + StateT.run', Functor.map, Except.map] at hvalid + rw [hdepth] at hvalid + cases hinner : + TypeChecker.Inner.isDefEq step.lhs step.rhs + (TypeChecker.Methods.withFuel recursionFuel) + { env := step.context.env + lctx := step.context.lctx + safety := step.context.safety + lparams := step.context.lparams + fuel := step.context.fuel } + ({} : TypeChecker.State) with + | error err => simp [hinner] at hvalid + | ok pair => + rcases pair with ⟨observed, state⟩ + have : observed = true := by + simpa [hinner] using hvalid + subst observed + exact ⟨state, by + simpa [Context.toTypeChecker] using hinner⟩ + +/-- Source-indexed retained full-check execution. -/ +structure CandidateCheckTypeRun (source : Expr) where + step : CandidateCheckTypeStep + source_eq : step.source = source + valid : step.Valid + +def buildCandidateCheckType + (source : Expr) : M (CandidateCheckTypeRun source) := do + let context ← readThe Context + match observeCandidateCheckType context source with + | .error err => throw err + | .ok ⟨inferred, valid⟩ => + return ⟨⟨context, source, inferred⟩, rfl, valid⟩ + +/-- Structural certificate for the four top-level binder-domain annotations +peeled by `Expr.consumeTypeAnnotations`. + +The certificate exposes which application argument survives. Verify can +therefore recover a strict translation and free-variable facts for the +consumed domain from the translated raw domain, without assigning semantic +authority to Lean's opaque helper. -/ +inductive CandidateTypeAnnotationTrace : Expr → Expr → Type where + | identity (source : Expr) : + CandidateTypeAnnotationTrace source source + | outParam (levels : List Level) (type : Expr) + (inner : CandidateTypeAnnotationTrace type consumed) : + CandidateTypeAnnotationTrace + (.app (.const ``outParam levels) type) consumed + | semiOutParam (levels : List Level) (type : Expr) + (inner : CandidateTypeAnnotationTrace type consumed) : + CandidateTypeAnnotationTrace + (.app (.const ``semiOutParam levels) type) consumed + | optParam (levels : List Level) (type default : Expr) + (inner : CandidateTypeAnnotationTrace type consumed) : + CandidateTypeAnnotationTrace + (.app (.app (.const ``optParam levels) type) default) consumed + | autoParam (levels : List Level) (type tactic : Expr) + (inner : CandidateTypeAnnotationTrace type consumed) : + CandidateTypeAnnotationTrace + (.app (.app (.const ``autoParam levels) type) tactic) consumed + +namespace CandidateTypeAnnotationTrace + +/-- Transparent structural mirror of the top-level peeling algorithm. -/ +def build : (source : Expr) → Sigma (CandidateTypeAnnotationTrace source) + | .app (.app (.const name levels) type) default => + if hopt : name = ``_root_.optParam then by + subst name + let ⟨consumed, inner⟩ := build type + exact ⟨consumed, .optParam levels type default inner⟩ + else if hauto : name = ``_root_.autoParam then by + subst name + let ⟨consumed, inner⟩ := build type + exact ⟨consumed, .autoParam levels type default inner⟩ + else + ⟨.app (.app (.const name levels) type) default, .identity _⟩ + | .app (.const name levels) type => + if hout : name = ``_root_.outParam then by + subst name + let ⟨consumed, inner⟩ := build type + exact ⟨consumed, .outParam levels type inner⟩ + else if hsemi : name = ``_root_.semiOutParam then by + subst name + let ⟨consumed, inner⟩ := build type + exact ⟨consumed, .semiOutParam levels type inner⟩ + else + ⟨.app (.const name levels) type, .identity _⟩ + | source => ⟨source, .identity source⟩ +termination_by source => sizeOf source + +/-- The structural annotation builder computes the same transparent peeling +used by inductive validation. This deliberately relates two definitions in +this module, not Lean's opaque `Expr.consumeTypeAnnotations`. -/ +theorem build_consumed (source : Expr) : + (build source).1 = consumeTypeAnnotations source := by + fun_induction build source <;> simp_all [consumeTypeAnnotations] + +end CandidateTypeAnnotationTrace + +/-- A structural peeling certificate. Verify assigns semantic authority only +to the trace; compatibility with Lean's opaque helper is retained as a +differential executable check rather than a proof axiom. -/ +structure CandidateTypeAnnotations (source : Expr) where + consumed : Expr + trace : CandidateTypeAnnotationTrace source consumed + +def buildCandidateTypeAnnotations + (source : Expr) : Except Exception (CandidateTypeAnnotations source) := + let ⟨consumed, trace⟩ := CandidateTypeAnnotationTrace.build source + .ok ⟨consumed, trace⟩ + +namespace CandidateTypeAnnotations + +/-- Operational compatibility with this module's transparent annotation +peeling. Semantic consumers still rely on `trace` plus the retained +definitional-equality execution; `Matches` is used to replay the executable +family-validation path exactly. -/ +def Matches (annotations : CandidateTypeAnnotations source) : Prop := + annotations.consumed = consumeTypeAnnotations source + +theorem matches_of_build + (annotations : CandidateTypeAnnotations source) + (hbuild : buildCandidateTypeAnnotations source = .ok annotations) : + annotations.Matches := by + unfold buildCandidateTypeAnnotations at hbuild + cases htrace : CandidateTypeAnnotationTrace.build source with + | mk consumed trace => + simp only [Except.ok.injEq] at hbuild + subst annotations + simpa [Matches, htrace] using + CandidateTypeAnnotationTrace.build_consumed source + +end CandidateTypeAnnotations + +/-- Differential check pinning the transparent implementation to Lean's +opaque helper. This is executable regression evidence, not a logical premise +of the candidate producer. -/ +def candidateTypeAnnotationsAgree (source : Expr) : Bool := + let ⟨consumed, _⟩ := CandidateTypeAnnotationTrace.build source + consumed.equal source.consumeTypeAnnotations + +/-- Context- and source-indexed tree underlying one candidate expression. +The recursive indices are important: a Pi-domain trace uses the exact parent +context, while its body trace uses precisely `Context.pushLocalDecl` with the +structurally certified annotation-consumed domain and the corresponding fresh +free variable. The retained equality run relates that local declaration back +to the raw binder syntax. Thus expression position, annotation handling, and +checker-context provenance are enforced by the type rather than being +invariants of the producer alone. -/ +inductive CandidateExprTrace : Context → Expr → Type where + | terminal (context : Context) (source inferred result : Expr) + (checked : CandidateCheckTypeStep.Valid + ⟨context, source, inferred⟩) + (valid : CandidateWhnfStep.Valid ⟨context, source, result⟩) : + CandidateExprTrace context source + | forallE (context : Context) (source : Expr) + (inferred : Expr) + (name : Name) (domain body : Expr) + (binderInfo : BinderInfo) + (fresh : context.lctx.find? context.freshFVarId = none) + (annotations : CandidateTypeAnnotations domain) + (annotationsEq : CandidateIsDefEqStep.Valid + ⟨context, domain, annotations.consumed⟩) + (checked : CandidateCheckTypeStep.Valid + ⟨context, source, inferred⟩) + (valid : CandidateWhnfStep.Valid + ⟨context, source, .forallE name domain body binderInfo⟩) + (domainCandidate : CandidateExprTrace context domain) + (bodyCandidate : CandidateExprTrace + (context.pushLocalDecl name binderInfo annotations.consumed) + (body.instantiate1 context.freshExpr)) : + CandidateExprTrace context source + +namespace CandidateExprTrace + +/-- The main Pi spine exposed by candidate WHNF was already present in the +stored source syntax at every traversed body position. + +This is the structural precondition needed by mixed generation: it permits +normalization inside binder domains and at the terminal result, but it does +not let WHNF invent or remove the raw binders that generation must emit. -/ +def storedSpine : + {context : Context} → {source : Expr} → + CandidateExprTrace context source → Bool + | _, _, .terminal .. => true + | _, _, .forallE _ source _ name domain body binderInfo _ _ _ _ _ _ + bodyCandidate => + Expr.structuralEq source (.forallE name domain body binderInfo) && + storedSpine bodyCandidate + +/-- Number of stored Pi binders on the main (body) path of a candidate. -/ +def spineLength : + {context : Context} → {source : Expr} → + CandidateExprTrace context source → Nat + | _, _, .terminal .. => 0 + | _, _, .forallE _ _ _ _ _ _ _ _ _ _ _ _ _ bodyCandidate => + bodyCandidate.spineLength + 1 + +/-- The exact full-check observation at the root of a candidate trace. -/ +def rootCheck : + CandidateExprTrace context source → + CandidateCheckTypeObservation context source + | .terminal _ _ inferred _ checked _ => ⟨inferred, checked⟩ + | .forallE _ _ inferred _ _ _ _ _ _ _ checked _ _ _ => + ⟨inferred, checked⟩ + +/-- The exact WHNF result at the root, before recursively normalized domains +and bodies are reassembled into `view`. -/ +def rootWhnf : CandidateExprTrace context source → Expr + | .terminal _ _ _ result _ _ => result + | .forallE _ _ _ name domain body binderInfo _ _ _ _ _ _ _ => + .forallE name domain body binderInfo + +theorem rootWhnf_valid (candidate : CandidateExprTrace context source) : + CandidateWhnfStep.Valid ⟨context, source, candidate.rootWhnf⟩ := by + cases candidate <;> assumption + +/-- Reader context reached after following the complete main Π spine. -/ +def terminalContext : CandidateExprTrace context source → Context + | .terminal context _ _ _ _ _ => context + | .forallE _ _ _ _ _ _ _ _ _ _ _ _ _ bodyCandidate => + bodyCandidate.terminalContext + +theorem terminalContext_lparams + (candidate : CandidateExprTrace context source) : + candidate.terminalContext.lparams = context.lparams := by + induction candidate with + | terminal => rfl + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked valid domainCandidate bodyCandidate + domain_ih body_ih => + simpa [terminalContext, Context.pushLocalDecl] using body_ih + +/-- Following the main candidate Π spine preserves the kernel environment. -/ +theorem terminalContext_env + (candidate : CandidateExprTrace context source) : + candidate.terminalContext.env = context.env := by + induction candidate with + | terminal => rfl + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked valid domainCandidate bodyCandidate + domain_ih body_ih => + simpa [terminalContext, Context.pushLocalDecl] using body_ih + +/-- Following the main candidate Π spine preserves the primitive-name +policy used by family declaration. -/ +theorem terminalContext_allowPrimitive + (candidate : CandidateExprTrace context source) : + candidate.terminalContext.allowPrimitive = context.allowPrimitive := by + induction candidate with + | terminal => rfl + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked valid domainCandidate bodyCandidate + domain_ih body_ih => + simpa [terminalContext, Context.pushLocalDecl] using body_ih + +/-- Following the main candidate Π spine changes only the local context and +name generator; it preserves the checker safety mode. -/ +theorem terminalContext_safety + (candidate : CandidateExprTrace context source) : + candidate.terminalContext.safety = context.safety := by + induction candidate with + | terminal => rfl + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked valid domainCandidate bodyCandidate + domain_ih body_ih => + simpa [terminalContext, Context.pushLocalDecl] using body_ih + +/-- Following the main candidate Π spine preserves the checker fuel +configuration. -/ +theorem terminalContext_fuel + (candidate : CandidateExprTrace context source) : + candidate.terminalContext.fuel = context.fuel := by + induction candidate with + | terminal => rfl + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked valid domainCandidate bodyCandidate + domain_ih body_ih => + simpa [terminalContext, Context.pushLocalDecl] using body_ih + +/-- Non-Π result reached after following the complete main Π spine. -/ +def terminalResult : CandidateExprTrace context source → Expr + | .terminal _ _ _ result _ _ => result + | .forallE _ _ _ _ _ _ _ _ _ _ _ _ _ bodyCandidate => + bodyCandidate.terminalResult + +/-- The first `count` local expressions allocated along the main Π spine. +These are exactly the expressions accumulated as inductive parameters when +`count` is the declaration's `nparams`. -/ +def parameterList : + (count : Nat) → CandidateExprTrace context source → List Expr + | 0, _ => [] + | _ + 1, .terminal .. => [] + | count + 1, + .forallE context _ _ _ _ _ _ _ _ _ _ _ _ bodyCandidate => + context.freshExpr :: bodyCandidate.parameterList count + +theorem parameterList_length + (candidate : CandidateExprTrace context source) + (hcount : count ≤ candidate.spineLength) : + (candidate.parameterList count).length = count := by + induction candidate generalizing count with + | terminal => + simp [spineLength] at hcount + subst count + rfl + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked valid domainCandidate bodyCandidate + domain_ih body_ih => + cases count with + | zero => rfl + | succ count => + simp only [parameterList, List.length_cons] + rw [body_ih] + simpa [spineLength] using hcount + +/-- Every annotation choice on the main Π spine matches the transparent +peeling operation used by `checkInductiveTypes`. This is operational +provenance, separate from the semantic raw/consumed equality stored at each +candidate node. -/ +def validationAnnotations : + CandidateExprTrace context source → Prop + | .terminal .. => True + | .forallE _ _ _ _ _ _ _ _ annotations _ _ _ _ bodyCandidate => + annotations.Matches ∧ bodyCandidate.validationAnnotations + +/-- Replay the inner family-telescope validator from a candidate's exact main +Π spine. The first `remaining` binders extend `stats.params`; every later +binder contributes an index. The theorem is independent of any fixture and +preserves the exact terminal reader context reached by the executable loop. -/ +theorem checkInductiveTypes_loop_of_candidate + (candidate : CandidateExprTrace context source) + (stats : InductiveStats) (nparams i nindices fuel : Nat) + (remaining : Nat) (k : Expr → InductiveStats → Nat → M α) + (hi : i + remaining = nparams) + (hcount : remaining ≤ candidate.spineLength) + (hfuel : candidate.spineLength < fuel) + (hempty : stats.indConsts.isEmpty = true) + (hannotations : candidate.validationAnnotations) + (hterminal : candidate.terminalResult.isForall = false) : + checkInductiveTypes.loopInd.loop nparams stats candidate.rootWhnf + i nindices fuel k context = + k candidate.terminalResult + { stats with + params := stats.params ++ + (candidate.parameterList remaining).toArray } + (nindices + (candidate.spineLength - remaining)) + candidate.terminalContext := by + induction candidate generalizing i nindices fuel remaining stats with + | terminal context source inferred result checked valid => + simp only [spineLength] at hcount hfuel + have hremaining : remaining = 0 := by omega + subst remaining + have hi' : i = nparams := by omega + subst i + cases stats + cases fuel with + | zero => omega + | succ fuel => + cases result <;> + simp_all [rootWhnf, terminalResult, terminalContext, parameterList, + spineLength, checkInductiveTypes.loopInd.loop, Expr.isForall] + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked valid domainCandidate bodyCandidate + domain_ih body_ih => + rcases hannotations with ⟨hmatch, hbodyAnnotations⟩ + cases remaining with + | zero => + have hi' : i = nparams := by omega + subst i + have hbodyFuel : bodyCandidate.spineLength < fuel - 1 := by + simp only [spineLength] at hfuel + omega + have hbodyCount : 0 ≤ bodyCandidate.spineLength := Nat.zero_le _ + have hvalid := bodyCandidate.rootWhnf_valid + change TypeChecker.M.run _ _ _ _ _ + (TypeChecker.whnf (body.instantiate1 context.freshExpr)) = + .ok bodyCandidate.rootWhnf at hvalid + rw [show fuel = (fuel - 1) + 1 by omega] + simp only [rootWhnf, checkInductiveTypes.loopInd.loop, + Nat.lt_irrefl, if_false, withLocalDecl_apply] + rw [← hmatch] + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [hvalid] + simp only [Except.bind] + rw [body_ih stats nparams (nindices + 1) (fuel - 1) 0 rfl + hbodyCount hbodyFuel hempty hbodyAnnotations hterminal] + simp [terminalResult, terminalContext, parameterList, spineLength, + Nat.add_comm, Nat.add_assoc] + | succ remaining => + have hil : i < nparams := by omega + have hbodyCount : remaining ≤ bodyCandidate.spineLength := by + simp only [spineLength] at hcount + omega + have hbodyFuel : bodyCandidate.spineLength < fuel - 1 := by + simp only [spineLength] at hfuel + omega + have hvalid := bodyCandidate.rootWhnf_valid + change TypeChecker.M.run _ _ _ _ _ + (TypeChecker.whnf (body.instantiate1 context.freshExpr)) = + .ok bodyCandidate.rootWhnf at hvalid + rw [show fuel = (fuel - 1) + 1 by omega] + simp only [rootWhnf, checkInductiveTypes.loopInd.loop, hil, if_true, + hempty, withLocalDecl_apply] + rw [← hmatch] + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [hvalid] + simp only [Except.bind] + rw [body_ih { stats with + params := stats.params.push context.freshExpr } + (i + 1) nindices (fuel - 1) remaining (by omega) + hbodyCount hbodyFuel (by simpa using hempty) hbodyAnnotations + hterminal] + simp [terminalResult, terminalContext, parameterList, spineLength] + +/-- Exact singleton statistics selected by a candidate family spine with an +arbitrary parameter/index split. -/ +def singletonCandidateInductiveStats + (indType : InductiveType) + (candidate : CandidateExprTrace context indType.type) + (nparams : Nat) (resultLevel : Level) : InductiveStats where + lctx := candidate.terminalContext.lctx + levels := context.lparams.map .param + resultLevel := resultLevel + nindices := #[candidate.spineLength - nparams] + indConsts := #[.const indType.name (context.lparams.map .param)] + params := (candidate.parameterList nparams).toArray + isNotZero := resultLevel.isNeverZero + +/-- A source-indexed candidate family spine discharges the complete singleton +family-validation pass for any number of parameters and indices. The result +records the same local expressions, terminal context, index count, universe, +and family constant selected by the executable validator. -/ +theorem checkInductiveTypes_singleton_of_candidate + (indType : InductiveType) + (candidate : CandidateExprTrace context indType.type) + (nparams : Nat) (resultLevel : Level) + (k : InductiveStats → M α) + (hclosed : + context.env.checkNoMVarNoFVar indType.name indType.type = .ok ()) + (hcount : nparams ≤ candidate.spineLength) + (hfuel : candidate.spineLength < context.fuel.inductiveFuel) + (hannotations : candidate.validationAnnotations) + (hterminal : candidate.terminalResult = .sort resultLevel) + (hensure : + TypeChecker.M.run candidate.terminalContext.env + candidate.terminalContext.safety candidate.terminalContext.lctx + candidate.terminalContext.lparams candidate.terminalContext.fuel + (TypeChecker.ensureSort (.sort resultLevel)) = + .ok (.sort resultLevel)) : + checkInductiveTypes nparams #[indType] k context = + k (candidate.singletonCandidateInductiveStats + indType nparams resultLevel) candidate.terminalContext := by + have hcheck := candidate.rootCheck.valid + have hwhnf := candidate.rootWhnf_valid + change TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.checkType indType.type) = + .ok candidate.rootCheck.inferred at hcheck + change TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf indType.type) = + .ok candidate.rootWhnf at hwhnf + have hterminalForall : candidate.terminalResult.isForall = false := by + rw [hterminal] + rfl + have hterminalLparams : + candidate.terminalContext.lparams = context.lparams := + candidate.terminalContext_lparams + have hparameterLength := candidate.parameterList_length hcount + unfold checkInductiveTypes + simp only [readThe, MonadReader.read, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, Except.pure, Except.bind] + rw [checkInductiveTypes.loopInd.eq_1] + have hsize : 0 < #[indType].size := by simp + rw [dif_pos hsize] + rw [show #[indType][0] = indType by rfl] + simp only [readThe, MonadReader.read, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, Except.pure, Except.bind, + liftTypeChecker_apply, hclosed, hcheck, hwhnf] + rw [candidate.checkInductiveTypes_loop_of_candidate + (stats := InductiveStats.initial (context.lparams.map .param)) + (nparams := nparams) (i := 0) (nindices := 0) + (fuel := context.fuel.inductiveFuel) (remaining := nparams) + (hi := Nat.zero_add nparams) (hcount := hcount) (hfuel := hfuel) + (hempty := rfl) (hannotations := hannotations) + (hterminal := hterminalForall)] + rw [hterminal] + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [hensure] + simp only [Except.bind] + rw [if_pos (show ((InductiveStats.initial + (List.map Level.param context.lparams)).indConsts).isEmpty = true from + rfl)] + simp only [Expr.sortLevel!, InductiveStats.initial, Nat.zero_add] + simp only [ReaderT.bind, Bind.bind, Except.pure, Except.bind] + rw [checkInductiveTypes.loopInd.eq_1] + have hdone : ¬1 < #[indType].size := by simp + rw [dif_neg hdone] + simp only [readThe, MonadReader.read, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, Except.pure, Except.bind] + simp [singletonCandidateInductiveStats, hterminalLparams, + hparameterLength] + +/-- Exact successful singleton family-validation execution retained at the +candidate selected by `buildNormalizationCandidate`. + +The executable validator owns the parameter/index split, result universe, +statistics, and terminal reader context. Keeping the universally quantified +continuation equation makes this a decomposition of the real +`checkInductiveTypes` call rather than a fixture-specific success flag. The +semantic interpretation of the retained candidate remains in Verify. -/ +structure FamilyValidationRun + (indType : InductiveType) + {context : Context} + (candidate : CandidateExprTrace context indType.type) where + nparams : Nat + resultLevel : Level + stats : InductiveStats + stats_eq : stats = candidate.singletonCandidateInductiveStats + indType nparams resultLevel + terminal_eq : candidate.terminalResult = Expr.sort resultLevel + run : ∀ {α} (k : InductiveStats → M α), + checkInductiveTypes nparams #[indType] k context = + k stats candidate.terminalContext + +/-- The retained singleton validation run exposes exactly the candidate view +parameter expressions selected by the executable family pass. -/ +def FamilyValidationRun.parameters + (run : FamilyValidationRun indType candidate) : List Expr := + candidate.parameterList run.nparams + +/-- The retained singleton validation run exposes the number of candidate +view indices following the selected parameter prefix. -/ +def FamilyValidationRun.numIndices + (run : FamilyValidationRun indType candidate) : Nat := + candidate.spineLength - run.nparams + +/-- Candidate expression reconstructed from the traced WHNF/Pi tree. -/ +def view : CandidateExprTrace context source → Expr + | .terminal _ _ _ result _ _ => result + | .forallE context _ _ name _ _ binderInfo _ _ _ _ _ domain body => + .forallE name domain.view + (body.view.abstract #[context.freshExpr]) binderInfo + +/-- Preorder list of all retained checker observations. -/ +def steps : CandidateExprTrace context source → List CandidateWhnfStep + | .terminal context source _ result _ _ => [{ context, source, result }] + | .forallE context source _ name domain body binderInfo _ _ _ _ _ + domainCandidate bodyCandidate => + { context, source, + result := .forallE name domain body binderInfo } :: + domainCandidate.steps ++ bodyCandidate.steps + +/-- Preorder list of all retained full-check observations. -/ +def checkSteps : CandidateExprTrace context source → List CandidateCheckTypeStep + | .terminal context source inferred _ _ _ => + [{ context, source, inferred }] + | .forallE context source inferred _ _ _ _ _ _ _ _ _ + domainCandidate bodyCandidate => + { context, source, inferred } :: + domainCandidate.checkSteps ++ bodyCandidate.checkSteps + +/-- Preorder list of all retained binder-domain equality observations. -/ +def isDefEqSteps : + CandidateExprTrace context source → List CandidateIsDefEqStep + | .terminal .. => [] + | .forallE context _ _ _ domain _ _ _ annotations _ _ _ + domainCandidate bodyCandidate => + { context, lhs := domain, rhs := annotations.consumed } :: + domainCandidate.isDefEqSteps ++ bodyCandidate.isDefEqSteps + +/-- Every retained WHNF observation is an exact checker execution. -/ +theorem allValid : (candidate : CandidateExprTrace context source) → + ∀ step ∈ candidate.steps, step.Valid + | .terminal context source _ result _ valid, step, h => by + simp only [steps, List.mem_singleton] at h + subst step + exact valid + | .forallE _ _ _ _ _ _ _ _ _ _ _ valid domain body, step, h => by + simp only [steps, List.mem_cons, List.mem_append] at h + rcases h with (rfl | h) | h + · exact valid + · exact domain.allValid step h + · exact body.allValid step h + +/-- Every retained full-check observation is an exact checker execution. -/ +theorem allChecksValid : (candidate : CandidateExprTrace context source) → + ∀ step ∈ candidate.checkSteps, step.Valid + | .terminal context source inferred _ checked _, step, h => by + simp only [checkSteps, List.mem_singleton] at h + subst step + exact checked + | .forallE _ _ _ _ _ _ _ _ _ _ checked _ domain body, step, h => by + simp only [checkSteps, List.mem_cons, List.mem_append] at h + rcases h with (rfl | h) | h + · exact checked + · exact domain.allChecksValid step h + · exact body.allChecksValid step h + +/-- Every retained binder-domain equality is an exact successful checker +execution. -/ +theorem allIsDefEqValid : (candidate : CandidateExprTrace context source) → + ∀ step ∈ candidate.isDefEqSteps, step.Valid + | .terminal .., step, h => by simp [isDefEqSteps] at h + | .forallE _ _ _ _ _ _ _ _ _ annotationsEq _ _ domain body, + step, h => by + simp only [isDefEqSteps, List.mem_cons, List.mem_append] at h + rcases h with (rfl | h) | h + · exact annotationsEq + · exact domain.allIsDefEqValid step h + · exact body.allIsDefEqValid step h + +end CandidateExprTrace + +/-- Source-indexed trace for one candidate expression. The tree records the +full-check and WHNF observations at every inspected node and retains the exact +positional split through Pi domains and instantiated bodies. Every node +carries the exact checker-run equalities produced by +`observeCandidateCheckType` and `observeCandidateWhnf`; Theory translation and +semantic refinement are intentionally separate. -/ +structure CandidateExpr (source : Expr) where + context : Context + trace : CandidateExprTrace context source + +def CandidateExpr.view (candidate : CandidateExpr source) : Expr := + candidate.trace.view + +def CandidateExpr.steps + (candidate : CandidateExpr source) : List CandidateWhnfStep := + candidate.trace.steps + +def CandidateExpr.checkSteps + (candidate : CandidateExpr source) : + List CandidateCheckTypeStep := + candidate.trace.checkSteps + +def CandidateExpr.isDefEqSteps + (candidate : CandidateExpr source) : + List CandidateIsDefEqStep := + candidate.trace.isDefEqSteps + +theorem CandidateExpr.step_valid + (candidate : CandidateExpr source) + (hstep : step ∈ candidate.steps) : + step.Valid := + candidate.trace.allValid step hstep + +theorem CandidateExpr.checkStep_valid + (candidate : CandidateExpr source) + (hstep : step ∈ candidate.checkSteps) : + step.Valid := + candidate.trace.allChecksValid step hstep + +theorem CandidateExpr.isDefEqStep_valid + (candidate : CandidateExpr source) + (hstep : step ∈ candidate.isDefEqSteps) : + step.Valid := + candidate.trace.allIsDefEqValid step hstep + +/-- Normalize exactly the expression positions inspected by inductive +analysis. Each node is fully checked and then exposed with the ordinary +checker `whnf`; Pi domains retain their raw syntax, while bodies are traversed +under the structurally certified annotation-consumed local declarations used +by kernel checking. Every raw/consumed domain pair is also checked by an exact +successful ordinary-checker `isDefEq` run. The recursion budget is the +configured inductive fuel, while every checker run uses the configured +transparency/fuel. + +The returned trace is only a candidate analysis view and operational +provenance. It is not stored in the kernel environment and acquires semantic +authority only after Verify reconstructs and refines every retained checker +run. -/ +def buildCandidateExpr (e : Expr) : M (CandidateExpr e) := do + let context ← readThe Context + return ⟨context, ← loop context e context.fuel.inductiveFuel⟩ +where + loop (context : Context) (e : Expr) : + Nat → Except Exception (CandidateExprTrace context e) + | 0 => throw .deepRecursion + | fuel + 1 => do + match observeCandidateCheckType context e with + | .error err => throw err + | .ok ⟨inferred, checked⟩ => + match observeCandidateWhnf context e with + | .error err => throw err + | .ok ⟨view, valid⟩ => + match view, valid with + | .forallE name domain body binderInfo, valid => + match hfresh : context.lctx.find? context.freshFVarId with + | some _ => + throw (Exception.other + "normalization candidate generated a duplicate free variable") + | none => + let annotations ← buildCandidateTypeAnnotations domain + let ⟨annotationsEq⟩ ← observeCandidateIsDefEq + context domain annotations.consumed + let domainCandidate ← loop context domain fuel + let bodyContext := + context.pushLocalDecl name binderInfo + annotations.consumed + let bodyCandidate ← loop bodyContext + (body.instantiate1 context.freshExpr) fuel + return .forallE context e inferred name domain body + binderInfo hfresh annotations annotationsEq checked valid + domainCandidate bodyCandidate + | result, valid => + return .terminal context e inferred result checked valid + +/-- One terminal recursive step of `buildCandidateExpr`, with its traversal +budget made explicit. This is the reusable reduction seam for exact producer +fixtures; all semantic evidence remains the ordinary checker executions +stored in the resulting trace. -/ +theorem buildCandidateExpr_loop_of_whnf_nonForall + (context : Context) (e inferred view : Expr) (fuel : Nat) + (hcheck : CandidateCheckTypeStep.Valid + ⟨context, e, inferred⟩) + (hrun : CandidateWhnfStep.Valid ⟨context, e, view⟩) + (hview : view.isForall = false) : + buildCandidateExpr.loop context e (fuel + 1) = + .ok (.terminal context e inferred view hcheck hrun) := by + unfold buildCandidateExpr.loop + rw [observeCandidateCheckType_of_run context e inferred hcheck] + rw [observeCandidateWhnf_of_run context e view hrun] + cases view <;> + simp_all [Expr.isForall, Pure.pure, Except.pure] + +/-- One forall recursive step of `buildCandidateExpr`, exposing the exact +child executions used at the decremented traversal budget. -/ +theorem buildCandidateExpr_loop_of_whnf_forall + (context : Context) (e inferred : Expr) (fuel : Nat) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (hfresh : context.lctx.find? context.freshFVarId = none) + (annotations : CandidateTypeAnnotations domain) + (hannotations : + buildCandidateTypeAnnotations domain = .ok annotations) + (hannotationsEq : CandidateIsDefEqStep.Valid + ⟨context, domain, annotations.consumed⟩) + (hcheck : CandidateCheckTypeStep.Valid + ⟨context, e, inferred⟩) + (hrun : CandidateWhnfStep.Valid + ⟨context, e, .forallE name domain body binderInfo⟩) + (domainCandidate : CandidateExprTrace context domain) + (bodyCandidate : CandidateExprTrace + (context.pushLocalDecl name binderInfo annotations.consumed) + (body.instantiate1 context.freshExpr)) + (hdomain : + buildCandidateExpr.loop context domain fuel = + .ok domainCandidate) + (hbody : + buildCandidateExpr.loop + (context.pushLocalDecl name binderInfo annotations.consumed) + (body.instantiate1 context.freshExpr) fuel = + .ok bodyCandidate) : + buildCandidateExpr.loop context e (fuel + 1) = + .ok (.forallE context e inferred name domain body binderInfo + hfresh annotations hannotationsEq hcheck hrun + domainCandidate bodyCandidate) := by + unfold buildCandidateExpr.loop + simp only [observeCandidateCheckType_of_run context e inferred hcheck, + observeCandidateWhnf_of_run context e + (.forallE name domain body binderInfo) hrun] + split + · simp_all + · simp [Bind.bind, Except.bind, hannotations, + observeCandidateIsDefEq_of_run context domain + annotations.consumed hannotationsEq, + hdomain, hbody, Pure.pure, Except.pure] + +/-- Every annotation choice on a successfully built candidate main spine +comes from the transparent annotation builder used by the ordinary producer. +This recovers validator-replay provenance from the executable traversal +itself; callers do not supply an independent annotation premise. -/ +theorem CandidateExprTrace.validationAnnotations_of_loop + {context : Context} {source : Expr} {fuel : Nat} + {candidate : CandidateExprTrace context source} + (h : buildCandidateExpr.loop context source fuel = .ok candidate) : + candidate.validationAnnotations := by + fun_induction buildCandidateExpr.loop context source fuel <;> + simp_all + case case5 => + simp only [Bind.bind, Except.bind] at h + repeat' split at h + all_goals try simp_all [Functor.map, Except.map] + repeat' split at h + all_goals try simp_all + subst candidate + constructor + · apply CandidateTypeAnnotations.matches_of_build + assumption + · apply_assumption + assumption + case case6 => + simp only [Pure.pure, Except.pure, Except.ok.injEq] at h + subst candidate + trivial + +/-- A successful ordinary candidate-expression call carries the complete +annotation provenance needed to replay family validation. -/ +theorem CandidateExpr.validationAnnotations_of_build + {context : Context} {source : Expr} + {candidate : CandidateExpr source} + (h : buildCandidateExpr source context = .ok candidate) : + candidate.trace.validationAnnotations := by + unfold buildCandidateExpr at h + simp [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, Except.bind, Except.pure] at h + split at h <;> try simp_all + simp [ReaderT.pure, Pure.pure, Except.pure] at h + subst candidate + apply CandidateExprTrace.validationAnnotations_of_loop + assumption + +/-- The context stored at the root of a successful expression candidate is +the exact reader context in which the ordinary builder was executed. -/ +theorem CandidateExpr.context_eq_of_build + {context : Context} {source : Expr} + {candidate : CandidateExpr source} + (h : buildCandidateExpr source context = .ok candidate) : + candidate.context = context := by + unfold buildCandidateExpr at h + simp [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, Except.bind, Except.pure] at h + split at h <;> try simp_all + simp [ReaderT.pure, Pure.pure, Except.pure] at h + subst candidate + rfl + +/-- Erase the operational trace and retain only the analysis expression. -/ +def normalizeCandidateExpr (e : Expr) : M Expr := do + return (← buildCandidateExpr e).view + +/-- A successful ordinary WHNF run to a non-Pi expression is exactly one +terminal step of the candidate traversal. This exposes the operational seam +used by Verify without duplicating the `ReaderT`/checker lift plumbing in +every certificate. -/ +theorem buildCandidateExpr_of_whnf_nonForall + (context : Context) (e inferred view : Expr) + (hfuel : 0 < context.fuel.inductiveFuel) + (hcheck : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.checkType e) = + .ok inferred) + (hrun : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf e) = + .ok view) + (hview : view.isForall = false) : + buildCandidateExpr e context = + .ok ⟨context, .terminal context e inferred view hcheck hrun⟩ := by + cases hf : context.fuel.inductiveFuel with + | zero => omega + | succ fuel => + cases hresult : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf e) with + | error err => simp [hresult] at hrun + | ok result => + have : result = view := by simpa [hresult] using hrun + subst result + unfold buildCandidateExpr + unfold buildCandidateExpr.loop + simp [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, Except.bind, Except.pure, + hf, observeCandidateCheckType_of_run context e inferred hcheck, + observeCandidateWhnf_of_run context e view hrun] + cases view <;> + simp_all [ReaderT.pure, Pure.pure, Except.pure, Expr.isForall] + +theorem normalizeCandidateExpr_of_whnf_nonForall + (context : Context) (e inferred view : Expr) + (hfuel : 0 < context.fuel.inductiveFuel) + (hcheck : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.checkType e) = + .ok inferred) + (hrun : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf e) = + .ok view) + (hview : view.isForall = false) : + normalizeCandidateExpr e context = .ok view := by + simp [normalizeCandidateExpr, ReaderT.bind, Bind.bind, + ReaderT.pure, Pure.pure, Except.bind, Except.pure, + CandidateExpr.view, CandidateExprTrace.view, + buildCandidateExpr_of_whnf_nonForall context e inferred view + hfuel hcheck hrun hview] + +/-- A dependent list retains the exact source position of each candidate. -/ +inductive CandidateList {α : Type} (F : α → Type) : List α → Type + | nil : CandidateList F [] + | cons : F a → CandidateList F as → CandidateList F (a :: as) + +namespace CandidateList + +def toList (f : (a : α) → F a → β) : + CandidateList F source → List β + | .nil => [] + | .cons head tail => f _ head :: tail.toList f + +/-- Eliminate a source-indexed singleton without a partial list operation. -/ +def singleton : CandidateList F [source] → F source + | .cons head .nil => head + +/-- A source-indexed singleton list is completely determined by its total +singleton projection. This eta law lets retained producer witnesses be +reindexed at staged singleton APIs without inspecting or replacing their +candidate payload. -/ +theorem singleton_eta (candidates : CandidateList F [source]) : + candidates = .cons candidates.singleton .nil := by + cases candidates with + | cons head tail => + cases tail + rfl + +end CandidateList + +/-- Candidate for one constructor; its header is always taken from `source`. -/ +structure CandidateConstructor (source : Constructor) where + type : CandidateExpr source.type + +def CandidateConstructor.view + (candidate : CandidateConstructor source) : Constructor := + { source with type := candidate.type.view } + +/-- Candidate for one family type, computed before raw family insertion. -/ +structure CandidateFamilyType (source : InductiveType) where + type : CandidateExpr source.type + +/-- Complete candidate for one family, with constructor traces computed only +after raw family insertion. -/ +structure CandidateFamily (source : InductiveType) where + familyType : CandidateFamilyType source + constructors : + CandidateList CandidateConstructor source.ctors + +/-- Project the pre-family candidate spine from a complete dependent family +candidate list without erasing source indices or using a parallel list. -/ +def CandidateList.familyTypes : + {sources : List InductiveType} → + CandidateList CandidateFamily sources → + CandidateList CandidateFamilyType sources + | [], .nil => .nil + | _ :: _, .cons family families => + .cons family.familyType families.familyTypes + +def CandidateFamily.view (candidate : CandidateFamily source) : InductiveType := + { source with + type := candidate.familyType.type.view + ctors := candidate.constructors.toList fun _ ctor => ctor.view } + +def normalizeCandidateConstructor + (ctor : Constructor) : M (CandidateConstructor ctor) := do + return ⟨← buildCandidateExpr ctor.type⟩ + +/-- The root context stored by a successful constructor normalization is the +exact post-family reader context used for that traversal. -/ +theorem CandidateConstructor.context_eq_of_normalize + {context : Context} {source : Constructor} + {candidate : CandidateConstructor source} + (h : normalizeCandidateConstructor source context = .ok candidate) : + candidate.type.context = context := by + unfold normalizeCandidateConstructor at h + simp only [ReaderT.bind, Bind.bind] at h + cases hbuild : buildCandidateExpr source.type context with + | error error => + simp [Except.bind, hbuild] at h + | ok type => + simp [Except.bind, ReaderT.pure, Pure.pure, Except.pure, hbuild] at h + subst candidate + exact CandidateExpr.context_eq_of_build hbuild + +def normalizeCandidateFamilyType + (indType : InductiveType) : M (CandidateFamilyType indType) := do + return ⟨← buildCandidateExpr indType.type⟩ + +/-- A successful family-type normalization carries the annotation provenance +of its underlying executable expression traversal. -/ +theorem CandidateFamilyType.validationAnnotations_of_normalize + {context : Context} {source : InductiveType} + {candidate : CandidateFamilyType source} + (h : normalizeCandidateFamilyType source context = .ok candidate) : + candidate.type.trace.validationAnnotations := by + unfold normalizeCandidateFamilyType at h + simp only [ReaderT.bind, Bind.bind] at h + cases hbuild : buildCandidateExpr source.type context with + | error error => + simp [Except.bind, hbuild] at h + | ok type => + simp [Except.bind, ReaderT.pure, Pure.pure, Except.pure, hbuild] at h + subst candidate + exact type.validationAnnotations_of_build hbuild + +/-- The root context stored by a successful family-type normalization is the +exact pre-family reader context used for that traversal. -/ +theorem CandidateFamilyType.context_eq_of_normalize + {context : Context} {source : Lean.InductiveType} + {candidate : CandidateFamilyType source} + (h : normalizeCandidateFamilyType source context = .ok candidate) : + candidate.type.context = context := by + unfold normalizeCandidateFamilyType at h + simp only [ReaderT.bind, Bind.bind] at h + cases hbuild : buildCandidateExpr source.type context with + | error error => + simp [Except.bind, hbuild] at h + | ok type => + simp [Except.bind, ReaderT.pure, Pure.pure, Except.pure, hbuild] at h + subst candidate + exact CandidateExpr.context_eq_of_build hbuild + +def normalizeCandidateConstructorList : + (ctors : List Constructor) → + M (CandidateList CandidateConstructor ctors) + | [] => return .nil + | ctor :: ctors => do + return .cons (← normalizeCandidateConstructor ctor) + (← normalizeCandidateConstructorList ctors) + +def normalizeCandidateFamilyTypeList : + (types : List InductiveType) → + M (CandidateList CandidateFamilyType types) + | [] => return .nil + | indType :: types => do + return .cons (← normalizeCandidateFamilyType indType) + (← normalizeCandidateFamilyTypeList types) + +def normalizeCandidateFamilyList : + {types : List InductiveType} → + CandidateList CandidateFamilyType types → + M (CandidateList CandidateFamily types) + | [], .nil => return .nil + | indType :: _, .cons familyType tail => do + return .cons + { familyType, + constructors := ← + normalizeCandidateConstructorList indType.ctors } + (← normalizeCandidateFamilyList tail) + +/-- Exact successful traversal of an arbitrary source-indexed family-type +list. The dependent indices prevent a proof for one metadata position from +being reused at another position or from silently truncating the source. -/ +inductive CandidateFamilyTypeListProduced (context : Context) : + {sources : List InductiveType} → + CandidateList CandidateFamilyType sources → Prop where + | nil : CandidateFamilyTypeListProduced context .nil + | cons + (head : normalizeCandidateFamilyType source context = .ok candidate) + (tail : CandidateFamilyTypeListProduced context candidates) : + CandidateFamilyTypeListProduced context (.cons candidate candidates) + +/-- A source-indexed family-type traversal determines the complete executable +list result for any length, without a fixture-specific list reduction. -/ +theorem CandidateFamilyTypeListProduced.normalize + {sources : List InductiveType} + {candidates : CandidateList CandidateFamilyType sources} + (run : CandidateFamilyTypeListProduced context candidates) : + normalizeCandidateFamilyTypeList sources context = .ok candidates := by + induction run with + | nil => rfl + | cons head tail ih => + unfold normalizeCandidateFamilyTypeList + simp only [ReaderT.bind, Bind.bind] + rw [head, ih] + rfl + +/-- A successful singleton family-type traversal retains the annotation +provenance of the exact candidate selected at its sole source position. -/ +theorem CandidateFamilyTypeListProduced.singleton_validationAnnotations + {context : Context} {source : Lean.InductiveType} + {candidates : CandidateList CandidateFamilyType [source]} + (run : CandidateFamilyTypeListProduced context candidates) : + candidates.singleton.type.trace.validationAnnotations := by + cases run with + | cons head tail => + cases tail + exact CandidateFamilyType.validationAnnotations_of_normalize head + +/-- A successful singleton family-type traversal stores its exact traversal +context at the candidate root. -/ +theorem CandidateFamilyTypeListProduced.singleton_context_eq + {context : Context} {source : Lean.InductiveType} + {candidates : CandidateList CandidateFamilyType [source]} + (run : CandidateFamilyTypeListProduced context candidates) : + candidates.singleton.type.context = context := by + cases run with + | cons head tail => + cases tail + exact CandidateFamilyType.context_eq_of_normalize head + +/-- Exact successful traversal of an arbitrary source-indexed constructor +list in one post-family context. Every candidate remains indexed by its source +constructor, so ordering, length, and header provenance are preserved by the +type rather than recovered from an erased list equality. -/ +inductive CandidateConstructorListProduced (context : Context) : + {sources : List Constructor} → + CandidateList CandidateConstructor sources → Prop where + | nil : CandidateConstructorListProduced context .nil + | cons + (head : normalizeCandidateConstructor source context = .ok candidate) + (tail : CandidateConstructorListProduced context candidates) : + CandidateConstructorListProduced context (.cons candidate candidates) + +/-- A source-indexed constructor traversal determines the complete executable +list result for any length, with no `zip`, partial lookup, or fixture-specific +cons-chain reduction. -/ +theorem CandidateConstructorListProduced.normalize + {sources : List Constructor} + {candidates : CandidateList CandidateConstructor sources} + (run : CandidateConstructorListProduced context candidates) : + normalizeCandidateConstructorList sources context = .ok candidates := by + induction run with + | nil => rfl + | cons head tail ih => + unfold normalizeCandidateConstructorList + simp only [ReaderT.bind, Bind.bind] + rw [head, ih] + rfl + +/-- A successful singleton constructor traversal stores its exact traversal +context at the candidate root. -/ +theorem CandidateConstructorListProduced.singleton_context_eq + {context : Context} {source : Constructor} + {candidates : CandidateList CandidateConstructor [source]} + (run : CandidateConstructorListProduced context candidates) : + candidates.singleton.type.context = context := by + cases run with + | cons head tail => + cases tail + exact CandidateConstructor.context_eq_of_normalize head + +/-- Exact successful assembly of complete family candidates from an already +source-indexed family-type list. Each constructor traversal is tied to the +corresponding family source, and the tail remains tied to the remaining family +sources. This is the reusable ordered-list boundary needed before mutual-block +staging. -/ +inductive CandidateFamilyListProduced (context : Context) : + {sources : List InductiveType} → + CandidateList CandidateFamilyType sources → + CandidateList CandidateFamily sources → Prop where + | nil : CandidateFamilyListProduced context .nil .nil + | cons + (constructors : CandidateConstructorListProduced + context family.constructors) + (tail : CandidateFamilyListProduced context familyTypes families) : + CandidateFamilyListProduced context + (.cons family.familyType familyTypes) (.cons family families) + +/-- Source-indexed family assembly determines the exact executable family-list +result for arbitrary list lengths. -/ +theorem CandidateFamilyListProduced.normalize + {sources : List InductiveType} + {familyTypes : CandidateList CandidateFamilyType sources} + {families : CandidateList CandidateFamily sources} + (run : CandidateFamilyListProduced context familyTypes families) : + normalizeCandidateFamilyList familyTypes context = .ok families := by + induction run with + | nil => rfl + | cons constructors tail ih => + unfold normalizeCandidateFamilyList + simp only [ReaderT.bind, Bind.bind] + rw [constructors.normalize, ih] + rfl + +/-- Singleton family assembly reuses, without replacement, the family-type +candidate produced in the pre-family environment. -/ +theorem CandidateFamilyListProduced.singleton_familyType + {context : Context} {source : Lean.InductiveType} + {familyTypes : CandidateList CandidateFamilyType [source]} + {families : CandidateList CandidateFamily [source]} + (run : CandidateFamilyListProduced context familyTypes families) : + families.singleton.familyType = familyTypes.singleton := by + cases run with + | cons constructors tail => + cases tail + rfl + +/-- Singleton family assembly exposes the exact source-indexed constructor +traversal retained for its sole family. -/ +theorem CandidateFamilyListProduced.singleton_constructors + {context : Context} {source : Lean.InductiveType} + {familyTypes : CandidateList CandidateFamilyType [source]} + {families : CandidateList CandidateFamily [source]} + (run : CandidateFamilyListProduced context familyTypes families) : + CandidateConstructorListProduced context + families.singleton.constructors := by + cases run with + | cons constructors tail => + cases tail + exact constructors + +/-- A successful singleton family assembly can be reindexed directly by the +family-type payload retained in its assembled result. This dependent eta law +avoids rewriting the input list underneath the execution witness. -/ +theorem CandidateFamilyListProduced.singleton_reindex + {context : Context} {source : Lean.InductiveType} + {familyTypes : CandidateList CandidateFamilyType [source]} + {families : CandidateList CandidateFamily [source]} + (run : CandidateFamilyListProduced context familyTypes families) : + CandidateFamilyListProduced context + (.cons families.singleton.familyType .nil) families := by + cases run with + | cons constructors tail => + cases tail + exact .cons constructors .nil + +/-- Shape-preserving output of the executable normalization-candidate pass. +The dependent family/constructor lists prevent positional provenance from +being silently reused for a different inductive request. Names, ordering, and +record headers come from the indexed source; only expression payloads are +reconstructed from candidate traces. -/ +structure NormalizationCandidate (source : List InductiveType) where + families : CandidateList CandidateFamily source + +def NormalizationCandidate.view + (candidate : NormalizationCandidate source) : List InductiveType := + candidate.families.toList fun _ family => family.view + +/-- One exact family-type traversal result together with the source-indexed +operational witness that produced it. The witness is provenance for later +Verify staging; it carries no Theory semantics. -/ +structure CandidateFamilyTypeListExecution (context : Context) + (sources : List InductiveType) where + candidates : CandidateList CandidateFamilyType sources + produced : CandidateFamilyTypeListProduced context candidates + +/-- Run the existing family-type normalizer while retaining its exact +source-ordered traversal equations. Errors and candidate data are unchanged. -/ +def executeCandidateFamilyTypeList (context : Context) : + (sources : List InductiveType) → + Except Exception (CandidateFamilyTypeListExecution context sources) + | [] => .ok ⟨.nil, .nil⟩ + | source :: sources => + match hhead : normalizeCandidateFamilyType source context with + | .error error => .error error + | .ok head => + match executeCandidateFamilyTypeList context sources with + | .error error => .error error + | .ok tail => .ok { + candidates := .cons head tail.candidates + produced := .cons (by simpa using hhead) tail.produced } + +/-- One exact constructor traversal result together with its source-indexed +operational witness. -/ +structure CandidateConstructorListExecution (context : Context) + (sources : List Constructor) where + candidates : CandidateList CandidateConstructor sources + produced : CandidateConstructorListProduced context candidates + +/-- Run the existing constructor normalizer while retaining its exact +source-ordered traversal equations. -/ +def executeCandidateConstructorList (context : Context) : + (sources : List Constructor) → + Except Exception (CandidateConstructorListExecution context sources) + | [] => .ok ⟨.nil, .nil⟩ + | source :: sources => + match hhead : normalizeCandidateConstructor source context with + | .error error => .error error + | .ok head => + match executeCandidateConstructorList context sources with + | .error error => .error error + | .ok tail => .ok { + candidates := .cons head tail.candidates + produced := .cons (by simpa using hhead) tail.produced } + +/-- One exact family/constructor assembly result together with both dependent +source lists retained by the ordinary traversal. -/ +structure CandidateFamilyListExecution (context : Context) + {sources : List InductiveType} + (familyTypes : CandidateList CandidateFamilyType sources) where + candidates : CandidateList CandidateFamily sources + produced : CandidateFamilyListProduced context familyTypes candidates + +/-- Run the existing family assembler while retaining each constructor-list +execution. This is an operational refinement of +`normalizeCandidateFamilyList`, not an additional acceptance premise. -/ +def executeCandidateFamilyList (context : Context) : + {sources : List InductiveType} → + (familyTypes : CandidateList CandidateFamilyType sources) → + Except Exception (CandidateFamilyListExecution context familyTypes) + | [], .nil => .ok ⟨.nil, .nil⟩ + | source :: _, .cons familyType familyTypes => + match executeCandidateConstructorList context source.ctors with + | .error error => .error error + | .ok constructors => + match executeCandidateFamilyList context familyTypes with + | .error error => .error error + | .ok tail => + let family : CandidateFamily source := { + familyType + constructors := constructors.candidates } + .ok { + candidates := .cons family tail.candidates + produced := by + change CandidateFamilyListProduced context + (.cons family.familyType familyTypes) + (.cons family tail.candidates) + exact .cons constructors.produced tail.produced } + +/-- Detailed operational result of `buildNormalizationCandidate`. + +The ordinary result erases to `candidate`. The remaining fields retain the +validator-selected statistics, intermediate environment, and exact list +traversals already executed by the same call. Verify uses these equations as +staging provenance; all semantic authority still comes from the D1--D4 +interpreters. -/ +structure NormalizationCandidateExecution + (nparams : Nat) (types : List InductiveType) + (numNested : Nat) (isUnsafe : Bool) (candidateContext : Context) where + validationContext : Context + stats : InductiveStats + familyTypes : CandidateFamilyTypeListExecution + { candidateContext with lctx := {} } types + familyEnv : Environment + declareRun : declareInductiveTypes stats nparams types.toArray + numNested isUnsafe validationContext = .ok familyEnv + constructorRun : checkConstructors types.toArray stats isUnsafe + { validationContext with env := familyEnv } = .ok () + families : CandidateFamilyListExecution + { candidateContext with env := familyEnv, lctx := {} } + familyTypes.candidates + +def NormalizationCandidateExecution.candidate + (execution : NormalizationCandidateExecution nparams types numNested + isUnsafe candidateContext) : NormalizationCandidate types := + ⟨execution.families.candidates⟩ + +/-- The post-family half of the detailed ordinary execution. -/ +def buildNormalizationCandidateExecutionAfterValidation + (nparams : Nat) (types : List InductiveType) + (numNested : Nat) (isUnsafe : Bool) (candidateContext : Context) + (stats : InductiveStats) : + M (NormalizationCandidateExecution nparams types numNested isUnsafe + candidateContext) := + fun validationContext => + match executeCandidateFamilyTypeList + { candidateContext with lctx := {} } types with + | .error error => .error error + | .ok familyTypes => + match hdeclare : declareInductiveTypes stats nparams types.toArray + numNested isUnsafe validationContext with + | .error error => .error error + | .ok familyEnv => + match hconstructors : checkConstructors types.toArray stats isUnsafe + { validationContext with env := familyEnv } with + | .error error => .error error + | .ok () => + match executeCandidateFamilyList + { candidateContext with env := familyEnv, lctx := {} } + familyTypes.candidates with + | .error error => .error error + | .ok families => .ok { + validationContext + stats + familyTypes + familyEnv + declareRun := by simpa using hdeclare + constructorRun := by simpa using hconstructors + families } + +/-- A retained successful post-validation execution exposes exactly the +statistics and reader context supplied by the family validator. -/ +theorem NormalizationCandidateExecution.fields_of_afterValidation + (execution : NormalizationCandidateExecution nparams types numNested + isUnsafe candidateContext) + (stats : InductiveStats) (validationContext : Context) + (h : buildNormalizationCandidateExecutionAfterValidation nparams types + numNested isUnsafe candidateContext stats validationContext = + .ok execution) : + execution.stats = stats ∧ + execution.validationContext = validationContext := by + unfold buildNormalizationCandidateExecutionAfterValidation at h + repeat' split at h + all_goals try simp_all + subst execution + exact ⟨rfl, rfl⟩ + +/-- Execute the ordinary singleton/mutual candidate pass while retaining the +exact operational provenance erased by the public candidate result. -/ +def buildNormalizationCandidateExecution + (nparams : Nat) (types : List InductiveType) + (numNested : Nat) (isUnsafe : Bool) (candidateContext : Context) : + Except Exception (NormalizationCandidateExecution nparams types + numNested isUnsafe candidateContext) := + checkInductiveTypes nparams types.toArray (fun stats => + buildNormalizationCandidateExecutionAfterValidation nparams types + numNested isUnsafe candidateContext stats) candidateContext + +/-- Run the generic one-pass candidate producer at the same two environments +as kernel inductive checking: family types in the input environment, then +constructor types after insertion of every raw family constant. + +This repeats the ordinary family/constructor validity checks so a candidate +cannot be obtained from metadata already rejected at those stages. The Theory +analyzer and Verify semantic certificate remain separate downstream gates. -/ +def buildNormalizationCandidate + (nparams : Nat) (types : List InductiveType) + (numNested : Nat) (isUnsafe : Bool) : + M (NormalizationCandidate types) := + -- Family validation retains its parameter/index telescope while invoking + -- the continuation. That context is required by `checkConstructors`, whose + -- parameter checks refer to the free variables recorded in `stats`, but it + -- is not part of the closed metadata being normalized. Snapshot the entry + -- context so both candidate traversals use one stable fresh-name provenance + -- and an empty local context; only the staged kernel environment changes. + fun candidateContext => + let indTypes := types.toArray + checkInductiveTypes nparams indTypes (fun stats => do + let familyTypes ← + withReader (fun _ : Context => { candidateContext with lctx := {} }) do + normalizeCandidateFamilyTypeList types + let familyEnv ← + declareInductiveTypes stats nparams indTypes numNested isUnsafe + withEnv familyEnv do + checkConstructors indTypes stats isUnsafe + let families ← + withReader (fun _ : Context => + { candidateContext with env := familyEnv, lctx := {} }) do + normalizeCandidateFamilyList familyTypes + return ⟨families⟩) candidateContext + +/-- Erase a retained successful execution back to the unchanged public +candidate producer. The family-validation equation supplies the continuation +boundary selected by `checkInductiveTypes`; every later rewrite comes from an +operation already stored in `execution`. -/ +theorem NormalizationCandidateExecution.produces + (execution : NormalizationCandidateExecution nparams types numNested + isUnsafe candidateContext) + (validationRun : ∀ {α} (k : InductiveStats → M α), + checkInductiveTypes nparams types.toArray k candidateContext = + k execution.stats execution.validationContext) : + buildNormalizationCandidate nparams types numNested isUnsafe + candidateContext = .ok execution.candidate := by + unfold buildNormalizationCandidate + rw [validationRun] + simp only [ReaderT.bind, Bind.bind] + rw [show + (withReader (fun _ : Context => + { candidateContext with lctx := {} }) + (normalizeCandidateFamilyTypeList types)) execution.validationContext = + .ok execution.familyTypes.candidates by + change normalizeCandidateFamilyTypeList types + { candidateContext with lctx := {} } = _ + exact execution.familyTypes.produced.normalize] + simp only [Except.bind] + rw [execution.declareRun] + unfold withEnv + change (ReaderT.bind + (checkConstructors types.toArray execution.stats isUnsafe) + (fun _ => ReaderT.bind + (withReader (fun _ : Context => + { candidateContext with + env := execution.familyEnv, lctx := {} }) + (normalizeCandidateFamilyList execution.familyTypes.candidates)) + (fun families => pure + (⟨families⟩ : NormalizationCandidate types)))) + ({ execution.validationContext with + env := execution.familyEnv } : Context) = _ + simp only [ReaderT.bind, Bind.bind] + rw [execution.constructorRun] + simp only [Except.bind] + rw [show + (withReader (fun _ : Context => + { candidateContext with + env := execution.familyEnv, lctx := {} }) + (normalizeCandidateFamilyList execution.familyTypes.candidates)) + { execution.validationContext with env := execution.familyEnv } = + .ok execution.families.candidates by + change normalizeCandidateFamilyList execution.familyTypes.candidates + { candidateContext with env := execution.familyEnv, lctx := {} } = _ + exact execution.families.produced.normalize] + rfl + +#guard_named_axioms Ix.Theory.Named.AddInductive.buildCandidateExpr [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.observeCandidateIsDefEq_of_run [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.buildCandidateExpr_loop_of_whnf_nonForall [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.buildCandidateExpr_loop_of_whnf_forall [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateTypeAnnotationTrace.build [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateTypeAnnotationTrace.build_consumed [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.buildCandidateTypeAnnotations [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateTypeAnnotations.matches_of_build [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.buildCandidateCheckType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.buildNormalizationCandidate [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateFamilyTypeListProduced.normalize [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateConstructorListProduced.normalize [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateFamilyListProduced.normalize [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateList.singleton [] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.storedSpine [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.spineLength [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.rootWhnf_valid [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.terminalContext_lparams [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.parameterList_length [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.checkInductiveTypes_loop_of_candidate [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.checkInductiveTypes_singleton_of_candidate [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.FamilyValidationRun [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.FamilyValidationRun.parameters [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExprTrace.FamilyValidationRun.numIndices [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExpr.step_valid [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExpr.checkStep_valid [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateExpr.isDefEqStep_valid [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateWhnfStep.innerRun [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateCheckTypeStep.innerRun [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CandidateIsDefEqStep.innerRun [propext, Classical.choice, Quot.sound] + +def declareConstructors (stats : InductiveStats) + (indTypes : Array InductiveType) (isUnsafe : Bool) : M Environment := + fun c => indTypes.foldlM (init := c.env) fun env indType => do + let (_, env) ← indType.ctors.foldlM (init := (0, env)) fun (cidx, env) ctor => do + let type := ctor.type + let rec arity i + | .forallE _ _ body _ => arity (i+1) body + | _ => i + let arity := arity 0 type + env.checkName ctor.name c.allowPrimitive + pure (cidx + 1, env.add <| .ctorInfo { + type, cidx, isUnsafe + levelParams := c.lparams + name := ctor.name + induct := indType.name + numParams := stats.params.size + numFields := assert! arity ≥ stats.params.size; arity - stats.params.size + }) + pure env + +/-- Return true if recursor can map into any universe -/ +def isLargeEliminator (stats : InductiveStats) (indTypes : Array InductiveType) : M Bool := do + if stats.isNotZero then return true + let #[indType] := indTypes | return false + match indType.ctors with + | [] => return true + | [ctor] => + let rec loop type i toCheck + | 0 => throw .deepRecursion + | fuel+1 => do + if let .forallE name dom body bi := type then + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + let mut toCheck := toCheck + if i ≥ stats.params.size then + if !(← ensureType dom).sortLevel!.isAlwaysZero then + toCheck := toCheck.push arg + loop (body.instantiate1 arg) (i + 1) toCheck fuel + else + return toCheck.all type.getAppArgs.contains + loop ctor.type 0 #[] (← readThe Context).fuel.inductiveFuel + | _ => return false + +/-- Search the kernel's elimination-universe name sequence (`u`, `u_1`, …) +for its first entry not already used by the inductive declaration. Among +`lparams.length + 1` distinct candidates at least one is available; the +zero-fuel branch is therefore only a totality fallback. -/ +def getFreshElimParam.loop (lparams : List Name) (u : Name) (i : Nat) : + Nat → Name + | 0 => u + | fuel + 1 => + if lparams.contains u then + loop lparams ((`u).appendIndexAfter i) (i + 1) fuel + else + u + +def getFreshElimParam (lparams : List Name) : Name := + getFreshElimParam.loop lparams `u 1 (lparams.length + 1) + +def getElimLevel (stats : InductiveStats) (indTypes : Array InductiveType) : + M Level := do + unless ← isLargeEliminator stats indTypes do return .zero + let {lparams, ..} ← read + return .param (getFreshElimParam lparams) + +/-- The constructor-shape fragment of the kernel's K-target test. A visible +Pi is accepted only while it belongs to the shared parameter prefix; the +first visible field makes the target ineligible. -/ +def isKTargetCtor (nparams : Nat) : Nat → Expr → Bool + | i, .forallE _ _ body _ => i < nparams && isKTargetCtor nparams (i + 1) body + | _, _ => true + +def isKTarget (stats : InductiveStats) (indTypes : Array InductiveType) : M Bool := do + let #[indType] := indTypes | return false + unless stats.resultLevel.isAlwaysZero do return false + let [ctor] := indType.ctors | return false + return isKTargetCtor stats.params.size 0 ctor.type + +@[inline] def getIIndices (stats : InductiveStats) (t : Expr) : Nat × Array Expr := + ((isValidIndApp? stats t).get!, t.getAppArgs[stats.params.size:]) + +-- FIXME: The function below has been exploded into nested loops as standalone functions +-- because I couldn't get them all to compile together as `let rec`s. +namespace mkRecInfos + +def loopArgs1 (stats : InductiveStats) (type : Expr) (i : Nat) (indices : Array Expr) + (fuel : Nat) (k : Array Expr → M α) : M α := match fuel with + | 0 => throw .deepRecursion + | fuel+1 => do + if let .forallE name dom body bi := type then + if i < stats.params.size then + loopArgs1 stats (← whnf <| body.instantiate1 stats.params[i]!) (i + 1) indices fuel k + else + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + loopArgs1 stats (← whnf <| body.instantiate1 arg) i (indices.push arg) fuel k + else + k indices + +variable (stats : InductiveStats) (indTypes : Array InductiveType) (elimLevel : Level) in +def loopInd1 (dIdx : Nat) (recInfos : Array RecInfo) (k : Array RecInfo → M α) : M α := do + if _h : dIdx < indTypes.size then + let ctx ← readThe Context + loopArgs1 stats (← whnf indTypes[dIdx].type) 0 #[] ctx.fuel.inductiveFuel fun indices => + let tTy := mkAppN (mkAppN stats.indConsts[dIdx]! stats.params) indices + withLocalDecl `t .default (consumeTypeAnnotations tTy) fun major => do + let lctx ← getLCtx + let motiveTy := lctx.mkForall indices <| lctx.mkForall #[major] <| .sort elimLevel + let name := if indTypes.size > 1 then (`motive).appendIndexAfter (dIdx+1) else `motive + withLocalDecl name .default (consumeTypeAnnotations motiveTy) fun motive => do + loopInd1 (dIdx + 1) (recInfos.push { motive, minors := #[], indices, major }) k + else + k recInfos +termination_by indTypes.size - dIdx + +variable (stats : InductiveStats) in +def loopCtorArgs (t : Expr) (k : Expr → Array Expr → Array Expr → M α) : M α := do + loop t 0 #[] #[] (← readThe Context).fuel.inductiveFuel +where + loop t i bu u + | 0 => throw .deepRecursion + | fuel+1 => do + if let .forallE name dom body bi := t then + if let some param := stats.params[i]? then + loop (body.instantiate1 param) (i + 1) bu u fuel + else + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + let bu := bu.push arg + let u := if (← isRecArg stats dom).isSome then u.push arg else u + loop (body.instantiate1 arg) (i + 1) bu u fuel + else k t bu u + +def loopUArgs (ui : Expr) (k : Expr → Array Expr → M α) : M α := do + loop (← whnf (← inferType ui)) #[] (← readThe Context).fuel.inductiveFuel +where + loop uiTy xs + | 0 => throw .deepRecursion + | fuel+1 => do + if let .forallE name dom body bi := uiTy then + withLocalDecl name bi (consumeTypeAnnotations dom) fun arg => do + loop (← whnf <| body.instantiate1 arg) (xs.push arg) fuel + else + k uiTy xs + +variable (stats : InductiveStats) (u : Array Expr) (recInfos : Array RecInfo) in +def loopU (i : Nat) (v : Array Expr) (k : Array Expr → M α) : M α := do + if _h : i < u.size then + let ui := u[i] + let viTy ← loopUArgs ui fun uiTy xs => do + let (itIdx, itIndices) := getIIndices stats uiTy + return (← getLCtx).mkForall xs <| + .app (mkAppN recInfos[itIdx]!.motive itIndices) (mkAppN ui xs) + let vName := ((← getLCtx).get! ui.fvarId!).userName.appendAfter "_ih" + withLocalDecl vName .default (consumeTypeAnnotations viTy) fun vi => do + loopU (i + 1) (v.push vi) k + else + k v +termination_by u.size - i + +variable (stats : InductiveStats) (indTypeName : Name) (dIdx : Nat) in +def loopCtors (recInfos : Array RecInfo) + (ctors : List Constructor) (k : Array RecInfo → M α) : M α := match ctors with + | ctor::ctors => + loopCtorArgs stats ctor.type fun t bu u => do + let (itIdx, itIndices) := getIIndices stats t + let introApp := mkAppN (mkAppN (.const ctor.name stats.levels) stats.params) bu + let motiveApp := Expr.app (mkAppN recInfos[itIdx]!.motive itIndices) introApp + loopU stats u recInfos 0 #[] fun v => do + let lctx ← getLCtx + let minorTy := lctx.mkForall bu <| lctx.mkForall v motiveApp + let minorName := ctor.name.replacePrefix indTypeName .anonymous + withLocalDecl minorName .default (consumeTypeAnnotations minorTy) fun minor => do + let recInfos := recInfos.modify dIdx fun s => { s with minors := s.minors.push minor } + loopCtors recInfos ctors k + | [] => k recInfos + +variable (stats : InductiveStats) (indTypes : Array InductiveType) in +def loopInd2 (dIdx : Nat) (recInfos : Array RecInfo) (k : Array RecInfo → M α) : M α := do + if _h : dIdx < indTypes.size then + let indType := indTypes[dIdx] + let indTypeName := indType.name + loopCtors stats indTypeName dIdx recInfos indType.ctors fun recInfos => + loopInd2 (dIdx + 1) recInfos k + else + k recInfos +termination_by indTypes.size - dIdx + +end mkRecInfos + +def mkRecInfos (stats : InductiveStats) (indTypes : Array InductiveType) + (elimLevel : Level) (k : Array RecInfo → M α) : M α := + mkRecInfos.loopInd1 stats indTypes elimLevel 0 #[] fun recInfos => + mkRecInfos.loopInd2 stats indTypes 0 recInfos k + +def getRecLevels (elimLevel : Level) (levels : List Level) : List Level := + if elimLevel.isParam then elimLevel :: levels else levels + +def getRecLevelParams (elimLevel : Level) (lparams : List Name) : List Name := + if let .param u := elimLevel then u :: lparams else lparams + +def mkRecRules (indTypes : Array InductiveType) (elimLevel : Level) (stats : InductiveStats) + (dIdx : Nat) (motives : Array Expr) (minors : Array Expr) : + StateT Nat M (List RecursorRule) := do + let d := indTypes[dIdx]! + let lvls := getRecLevels elimLevel stats.levels + let mut rules := #[] + for ctor in d.ctors do + let rule ← fun minorIdx => mkRecInfos.loopCtorArgs stats ctor.type fun _ bu u => + let rec loopU i (v : Array Expr) k := do + if _h : i < u.size then + let ui := u[i] + let val ← mkRecInfos.loopUArgs ui fun uiTy xs => do + let (itIdx, itIndices) := getIIndices stats uiTy + let val := .const (mkRecName indTypes[itIdx]!.name) lvls + let val := mkAppN (mkAppN (mkAppN (mkAppN val stats.params) motives) minors) itIndices + return (← getLCtx).mkLambda xs <| val.app (mkAppN ui xs) + loopU (i + 1) (v.push val) k + else + k v + termination_by u.size - i + loopU 0 #[] fun v => do + let lctx ← getLCtx + let rule := { + ctor := ctor.name + nfields := bu.size + rhs := lctx.mkLambda stats.params <| lctx.mkLambda motives <| + lctx.mkLambda minors <| lctx.mkLambda bu <| + mkAppN (mkAppN minors[minorIdx]! bu) v + } + return (rule, minorIdx + 1) + rules := rules.push rule + return rules.toList + +/-- Defensively type-checks the generated recursors. + +`run` installs a recursor and its computation rules without re-checking them. This verifies that +(1) each recursor's type is well typed, and (2) each computation rule is type-preserving: reducing +the recursor applied to a constructor yields a term whose type is the recursor's declared result +type. This catches a recursor whose minor-premise type and reduction rule disagree; checking only +that a rule's right-hand side has *some* type is insufficient, because an under-applied minor +premise is still a well-typed (function) term. -/ +def checkRecursors (indTypes : Array InductiveType) (elimLevel : Level) + (stats : InductiveStats) (motives minors : Array Expr) : M Unit := do + let {lparams, ..} ← read + let lvls := getRecLevels elimLevel stats.levels + withLParams (getRecLevelParams elimLevel lparams) do + for h : dIdx in [:indTypes.size] do + let indType := indTypes[dIdx] + let recName := mkRecName indType.name + let recCi ← (← read).env.get recName + -- (1) The recursor type must be well typed. + _ ← (TypeChecker.checkType recCi.type : TypeChecker.M Expr) + let recPre := mkAppN (mkAppN (mkAppN (.const recName lvls) stats.params) motives) minors + -- (2) Each computation rule must preserve types. + for ctor in indType.ctors do + mkRecInfos.loopCtorArgs stats ctor.type fun t bu _ => do + let (_, itIndices) := getIIndices stats t + let introApp := mkAppN (mkAppN (.const ctor.name stats.levels) stats.params) bu + let lhs := (mkAppN recPre itIndices).app introApp + let expected ← inferType lhs + let reduct ← whnf lhs + let actual ← inferType reduct + unless ← isDefEq actual expected do + throw <| .other s!"generated recursor computation rule for '{ctor.name + }' is not type-preserving" + +def run (nparams : Nat) (types : List InductiveType) (numNested : Nat) : M Environment := do + let isUnsafe := (← read).safety != .safe + let indTypes := types.toArray + let {lparams, ..} ← read + Environment.checkDuplicatedUnivParams lparams + checkInductiveTypes nparams indTypes fun stats => do + withEnv (← declareInductiveTypes stats nparams indTypes numNested isUnsafe) do + checkConstructors indTypes stats isUnsafe + withEnv (← declareConstructors stats indTypes isUnsafe) do + let elimLevel ← getElimLevel stats indTypes + mkRecInfos stats indTypes elimLevel fun recInfos => do + let motives := recInfos.map (·.motive) + let minors := recInfos.flatMap (·.minors) + let numMinors := minors.size + let numMotives := motives.size + let all := indTypes.map (·.name) |>.toList + let lctx ← getLCtx + let k ← isKTarget stats indTypes + let isUnsafe := (← read).safety != .safe + StateT.run' (s := 0) do + let mut env ← getEnv + let {allowPrimitive, ..} ← read + for h : dIdx in [:indTypes.size] do + let indType := indTypes[dIdx] + let info := recInfos[dIdx]! + let ty := + lctx.mkForall stats.params <| + lctx.mkForall motives <| + lctx.mkForall minors <| + lctx.mkForall info.indices <| + lctx.mkForall #[info.major] <| + .app (mkAppN info.motive info.indices) info.major + let rules ← mkRecRules indTypes elimLevel stats dIdx motives minors + let name := mkRecName indType.name + env.checkName name allowPrimitive + env := env.add <| .recInfo { + levelParams := getRecLevelParams elimLevel lparams + type := ty.inferImplicit 1000 false -- note: flag has reversed polarity from C++ + numParams := stats.params.size + numIndices := stats.nindices[dIdx]! + name, all, numMotives, numMinors, rules, k, isUnsafe + } + withEnv env <| checkRecursors indTypes elimLevel stats motives minors + pure env + +end AddInductive + +namespace ElimNestedInductive + +structure Result where + ngen : NameGenerator + nparams : Nat + lctx : LocalContext + params : Array Expr -- the fvars declared in `lctx` + aux2nested : NameMap Expr -- exprs are open over `params`, like the C++ `m_aux2nested` + types : List InductiveType + +instance [MonadStateOf NameGenerator m] : MonadNameGenerator m where + getNGen := get + setNGen := set + +namespace Result + +def getNestedIfAuxCtor (r : Result) (env' : Environment) (c : Name) : Option (Expr × Name) := do + let .ctorInfo { induct, .. } ← env'.find? c | none + return (← r.aux2nested.find? induct, induct) + +def restoreCtorName (r : Result) (env' : Environment) (c : Name) : Name := Id.run do + let (e, name) := (r.getNestedIfAuxCtor env' c).get! + let .const I _ := e.getAppFn | unreachable! + c.replacePrefix name I + +def restoreNested (r : Result) (env' : Environment) (e : Expr) + (auxRec : NameMap Name := {}) : Expr := + Id.run <| StateT.run' (s := { namePrefix := `_nested_fresh : NameGenerator }) do + let pi := e.isForall + let mut e := e + let mut As := #[] + let mut lctx : LocalContext := {} + for _ in [:r.nparams] do + match e with + | .forallE name dom body bi | .lam name dom body bi => + let id := ⟨← mkFreshId⟩ + lctx := lctx.mkLocalDecl id name dom bi + let arg := .fvar id + e := body.instantiate1 arg + As := As.push arg + | _ => unreachable! + e := e.replace fun t => do + if let .const c ls := t then + if let some recName := auxRec.find? c then + return .const recName ls + let .const c _ := t.getAppFn | none + if let some nested := r.aux2nested.find? c then + let args := t.getAppArgs + assert! args.size ≥ r.nparams + return mkAppRange ((nested.abstract r.params).instantiateRev As) r.nparams args.size args + let (nested, auxI_name) ← r.getNestedIfAuxCtor env' c + let args := t.getAppArgs + assert! args.size ≥ r.nparams + let nested' := (nested.abstract r.params).instantiateRev As + nested'.withApp fun I I_args => do + let .const I_c I_ls := I | unreachable! + let c' := .const (c.replacePrefix auxI_name I_c) I_ls + return mkAppRange (mkAppN c' I_args) r.nparams args.size args + return if pi then lctx.mkForall As e else lctx.mkLambda As e + +end Result + +structure State where + ngen : NameGenerator := { namePrefix := `_nested_fresh } + nestedAux : Array (Expr × Name) := {} + lvls : List Level + newTypes : Array InductiveType + nextIdx : Nat := 1 + deriving Inhabited + +abbrev M := ReaderT Environment <| StateT State <| Except Exception + +instance : MonadNameGenerator M where + getNGen := return (← get).ngen + setNGen ngen := modify fun s => { s with ngen } + +-- TODO: remove partial +partial def mkUniqueName (n : Name) : M Name := fun env s => + let rec loop i := + let r := n.appendIndexAfter i + if env.contains r then + loop (i + 1) + else + pure (r, { s with nextIdx := i + 1 }) + loop s.nextIdx + +def illFormed : Exception := + .other "invalid nested inductive datatype, ill-formed declaration" + +def replaceParams (params : Array Expr) (e : Expr) (As : Array Expr) : M Expr := do + assert! As.size == params.size + return (e.abstract As).instantiateRev params + +/-- IF `e` is of the form `I Ds is` where + 1) `I` is a nested inductive datatype (i.e., a previously declared inductive datatype), + 2) the parametric arguments `Ds` do not contain loose bound variables, and do contain inductive datatypes in `m_new_types` +THEN return the `inductive_val` in the `constant_info` associated with `I`. +Otherwise, return none. -/ +def isNestedInductiveApp? (e : Expr) : M (Option InductiveVal) := do + if !e.isApp then return none + let .const fn _ := e.getAppFn | return none + let env ← read + let some (.inductInfo ci) := env.find? fn | return none + let args := e.getAppArgs + if ci.numParams > args.size then return none + let mut isNested := false + let mut looseBVars := false + for i in [0:ci.numParams] do + if args[i]!.hasLooseBVars then + looseBVars := true + let newTypes := (← get).newTypes + if let some _ := args[i]!.find? fun + | .const t _ => newTypes.any fun ty => t == ty.name + | _ => false + then + isNested := true + if !isNested then return none + if looseBVars then + throw <| .other s!"invalid nested inductive datatype '{fn}', \ + nested inductive datatypes parameters cannot contain local variables." + return some ci + +def instantiateForallParams (e : Expr) (hi : Nat) (params : Array Expr) : + Except Exception Expr := do + let mut e := e + for _ in [:hi] do + let .forallE _ _ body _ := e | throw illFormed + e := body + return e.instantiateRevRange 0 hi params + +/-- If `e` is a nested occurrence `I Ds is`, return `Iaux As is` -/ +def replaceIfNested (lctx : LocalContext) (params : Array Expr) (As : Array Expr) (e : Expr) : + M (Option Expr) := do + let some I_val ← isNestedInductiveApp? e | return none + e.withApp fun fn args => do + let .const I_name I_lvls := fn | unreachable! + let I_nparams := I_val.numParams + assert! I_nparams ≤ args.size + let IAs := mkAppRange fn 0 I_nparams args -- `I As` + let Iparams ← replaceParams params IAs As + let st ← get + if let some auxI_name := st.nestedAux.findSome? fun (e, n) => + if e == Iparams then some n else none + then + return mkAppRange (mkAppN (.const auxI_name st.lvls) As) I_nparams args.size args + let mut result := none + let env ← read + for J_name in I_val.all do + let .inductInfo J_info ← env.get J_name | unreachable! + let J := .const J_name I_lvls + let JAs := mkAppRange J 0 I_nparams args + let auxJ_name ← mkUniqueName (`_nested ++ J_name) + let auxJ_type := J_info.type.instantiateLevelParams J_info.levelParams I_lvls + let auxJ_type := lctx.mkForall As <| ← instantiateForallParams auxJ_type I_nparams args + let JAs' ← replaceParams params JAs As + modify fun st => { st with nestedAux := st.nestedAux.push (JAs', auxJ_name) } + if J_name == I_name then + result := some <| + mkAppRange (mkAppN (.const auxJ_name (← get).lvls) As) I_nparams args.size args + let auxJ_ctors ← J_info.ctors.mapM fun J_ctor_name => do + let J_ctor_info ← env.get J_ctor_name + -- auxJ_cnstr_type still has references to `J`, this will be fixed later when we process it. + let auxJ_ctor_name := J_ctor_name.replacePrefix J_name auxJ_name + let auxJ_ctor_type := J_ctor_info.type.instantiateLevelParams J_ctor_info.levelParams I_lvls + let auxJ_ctor_type ← instantiateForallParams auxJ_ctor_type I_nparams args + return { name := auxJ_ctor_name, type := lctx.mkForall As auxJ_ctor_type } + let newType := { name := auxJ_name, type := auxJ_type, ctors := auxJ_ctors } + modify fun st => { st with newTypes := st.newTypes.push newType } + assert! result.isSome + return result + +def replaceAllNested (lctx : LocalContext) (params : Array Expr) (As : Array Expr) (e : Expr) : + M Expr := e.replaceM (replaceIfNested lctx params As) + +def withParams (type : Expr) (nparams : Nat) + (k : LocalContext → Expr → Array Expr → M α) : M α := loop {} type #[] nparams where + loop lctx type params + | 0 => k lctx type params + | i+1 => do + let .forallE name dom body bi := type + | throw <| .other "invalid inductive datatype declaration, incorrect number of parameters" + let id := ⟨← mkFreshId⟩ + let lctx := lctx.mkLocalDecl id name dom bi + let arg := .fvar id + loop lctx (body.instantiate1 arg) (params.push arg) i + +def run (fuel nparams : Nat) (types : List InductiveType) : M Result := do + let I :: _ := types + | throw <| .other s!"invalid empty (mutual) inductive datatype declaration, \ + it must contain at least one inductive type." + withParams I.type nparams fun lctx _ params => do + let rec loop i + | 0 => throw <| .other "deep recursion: ElimNestedInductive.run.loop" + | fuel+1 => do + let s ← get + if _h : i < s.newTypes.size then + let indType := s.newTypes[i] + let ctors ← indType.ctors.mapM fun ctor => do + withParams ctor.type nparams fun lctx ctorType As => do + assert! As.size == nparams + return { ctor with type := lctx.mkForall As (← replaceAllNested lctx params As ctorType) } + modify fun s => { s with newTypes := s.newTypes.set! i { indType with ctors } } + loop (i+1) fuel + else + let aux2nested := s.nestedAux.foldl (fun m (e, n) => m.insert n e) {} + return { + ngen := s.ngen + nparams := params.size + lctx := lctx + params := params + aux2nested := aux2nested + types := s.newTypes.toList } + loop 0 fuel +end ElimNestedInductive + +def mkAuxRecNameMap (env' : Environment) (types : List InductiveType) : + List Name × NameMap Name := Id.run do + let mainType :: _ := types | unreachable! + let ntypes := types.length + let mainName := mainType.name + let some (.inductInfo mainInfo) := env'.find? mainName | unreachable! + let allNames := mainInfo.all + assert! allNames.length > ntypes + let mut oldRecNames := #[] + let mut recMap : NameMap Name := {} + let mut nextIdx := 1 + for indName in allNames.drop ntypes do + let oldRecName := mkRecName indName + let newRecName := (mkRecName mainName).appendIndexAfter nextIdx + nextIdx := nextIdx + 1 + recMap := recMap.insert oldRecName newRecName + oldRecNames := oldRecNames.push oldRecName + return (oldRecNames.toList, recMap) + +def checkNoNestedAux (n : Name) (e : Expr) : Except Exception Unit := do + if (e.find? fun + | .const c _ => (`_nested).isPrefixOf c + | .proj s _ _ => (`_nested).isPrefixOf s + | _ => false).isSome then + throw <| .other s!"invalid declaration '{n}', it uses the reserved prefix '_nested'" + +/-- Checks the occurrence of a datatype being declared at the head of `e`, if there is one. +Returns `true` when the occurrence was checked and `e`'s subterms need not be revisited. -/ +def checkUniformIndOcc (lvls : List Level) (indNames : List Name) (nparams : Nat) + (e : Expr) (offset : Nat) : Except Exception Bool := do + let .const c ls := e.getAppFn | return false + unless indNames.contains c do return false + let args := e.getAppArgs + -- Over-applied: descend, so that occurrences in the indices are checked too. The parameter + -- application itself is visited as a subterm of `e` and checked then. + if args.size > nparams then return false + let ok := args.size == nparams && offset ≥ nparams && ls == lvls + && (List.range nparams).all fun i => args[i]! == .bvar (offset - 1 - i) + unless ok do + throw <| .other s!"invalid occurrence of datatype '{c}' being declared: it must be applied \ + to the parameters and universe levels of the mutual declaration" + return true + +/-- Checks that every occurrence of a datatype being declared in `e` is applied to the +declaration's universe levels and to its parameters, which at binder depth `offset` are the bound +variables `#(offset-1) … #(offset-nparams)`. That those binders really are the parameters is +established later, by the parameter check in `checkConstructors`. -/ +def checkUniformIndOccsIn (lvls : List Level) (indNames : List Name) (nparams : Nat) : + Expr → Nat → Except Exception Unit + | e, offset => do + if ← checkUniformIndOcc lvls indNames nparams e offset then return + match e with + | .forallE _ d b _ | .lam _ d b _ => + checkUniformIndOccsIn lvls indNames nparams d offset + checkUniformIndOccsIn lvls indNames nparams b (offset + 1) + | .letE _ t v b _ => + checkUniformIndOccsIn lvls indNames nparams t offset + checkUniformIndOccsIn lvls indNames nparams v offset + checkUniformIndOccsIn lvls indNames nparams b (offset + 1) + | .app f a => + checkUniformIndOccsIn lvls indNames nparams f offset + checkUniformIndOccsIn lvls indNames nparams a offset + | .mdata _ b => checkUniformIndOccsIn lvls indNames nparams b offset + | .proj _ _ b => checkUniformIndOccsIn lvls indNames nparams b offset + | _ => pure () + +/-- Runs `checkUniformIndOccsIn` over every constructor type of the declaration. + +Later phases inspect the constructor types modulo `whnf`, which can erase an occurrence (as in +`(fun _ => Unit) (T Nat)`), and the parametric arguments of a nested occurrence are dropped from +the auxiliary declaration altogether, so a non-uniform occurrence could escape checking there. +Reduction never creates an occurrence of a datatype being declared, since those are not yet in the +environment, so checking the syntactic occurrences here covers all of them. -/ +def checkUniformIndOccs (lparams : List Name) (nparams : Nat) (types : List InductiveType) : + Except Exception Unit := do + let lvls := lparams.map Level.param + let indNames := types.map (·.name) + for indType in types do + for ctor in indType.ctors do + checkUniformIndOccsIn lvls indNames nparams ctor.type 0 + +def Environment.addInductive (env : Environment) (lparams : List Name) (nparams : Nat) + (types : List InductiveType) (isUnsafe allowPrimitive : Bool) (fuel : FuelConfig := {}) : + Except Exception Environment := do + for indType in types do + env.checkNoMVarNoFVar indType.name indType.type + for ctor in indType.ctors do + env.checkNoMVarNoFVar ctor.name ctor.type + checkNoNestedAux ctor.name ctor.type + checkUniformIndOccs lparams nparams types + let res ← ElimNestedInductive.run fuel.inductiveFuel nparams types env + |>.run' { lvls := lparams.map .param, newTypes := types.toArray } + let numNested := res.aux2nested.size + let safety := if isUnsafe then .unsafe else .safe + let env' ← AddInductive.run nparams res.types numNested + { env, allowPrimitive, lparams, fuel, safety } + if numNested = 0 then return env' + let allIndNames := types.map (·.name) + let (recNames', recNameMap') := mkAuxRecNameMap env' types + (·.2) <$> StateT.run (s := env) do + let processRec recName := do + let newRecName := recNameMap'.getD recName recName + let some (.recInfo recInfo) := env'.find? recName | unreachable! + let newRecType := res.restoreNested env' recInfo.type recNameMap' + let newRules ← recInfo.rules.mapM fun rule => do + let newRhs := res.restoreNested env' rule.rhs recNameMap' + let newCtorName := if newRecName == recName then rule.ctor else + res.restoreCtorName env' rule.ctor + return { rule with ctor := newCtorName, rhs := newRhs } + (← MonadState.get).checkName newRecName allowPrimitive + modify (·.add <| .recInfo { recInfo with + name := newRecName, type := newRecType, all := allIndNames, rules := newRules }) + for indType in types do + let some (.inductInfo ind) := env'.find? indType.name | unreachable! + (← get).checkName ind.name allowPrimitive + modify (·.add <| .inductInfo { ind with all := allIndNames }) + for ctorName in ind.ctors do + let some (.ctorInfo ctor) := env'.find? ctorName | unreachable! + let newType := res.restoreNested env' ctor.type + (← get).checkName ctor.name allowPrimitive + modify (·.add <| .ctorInfo { ctor with type := newType }) + processRec (mkRecName indType.name) + recNames'.forM processRec + TypeChecker.M.run (← get) (safety := safety) (lctx := res.lctx) + (lparams := lparams) (fuel := fuel) do + res.aux2nested.forM fun _ e => do _ ← TypeChecker.checkType e diff --git a/Ix/Theory/Named/Reference/Inductive/EliminationTrace.lean b/Ix/Theory/Named/Reference/Inductive/EliminationTrace.lean new file mode 100644 index 000000000..3295fdb18 --- /dev/null +++ b/Ix/Theory/Named/Reference/Inductive/EliminationTrace.lean @@ -0,0 +1,581 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Reference.Inductive.ValidationTrace + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +namespace AddInductive +open TypeChecker + +/-- Exact successful traversal of the singleton-constructor branch of +`isLargeEliminator`. Non-parameter fields retain the precise `ensureType` +observation used to decide whether their local is relevant to the terminal +index-occurrence check. -/ +inductive LargeEliminatorLoopTrace (stats : InductiveStats) : + (context : Context) → (source : Expr) → (argIdx : Nat) → + (toCheck : Array Expr) → (fuel : Nat) → (result : Bool) → Type where + | parameter + (context : Context) (fuel argIdx : Nat) (toCheck : Array Expr) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (isParameter : argIdx < stats.params.size) + (tail : LargeEliminatorLoopTrace stats + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) toCheck fuel result) : + LargeEliminatorLoopTrace stats context + (.forallE name domain body binderInfo) argIdx toCheck (fuel + 1) result + | proofField + (context : Context) (fuel argIdx : Nat) (toCheck : Array Expr) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (sortResult : Expr) + (isField : argIdx ≥ stats.params.size) + (ensureType : ConstructorEnsureTypeStep.Valid + ⟨context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain), domain, sortResult⟩) + (isProp : sortResult.sortLevel!.isAlwaysZero = true) + (tail : LargeEliminatorLoopTrace stats + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) toCheck fuel result) : + LargeEliminatorLoopTrace stats context + (.forallE name domain body binderInfo) argIdx toCheck (fuel + 1) result + | dataField + (context : Context) (fuel argIdx : Nat) (toCheck : Array Expr) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (sortResult : Expr) + (isField : argIdx ≥ stats.params.size) + (ensureType : ConstructorEnsureTypeStep.Valid + ⟨context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain), domain, sortResult⟩) + (isProp : sortResult.sortLevel!.isAlwaysZero = false) + (tail : LargeEliminatorLoopTrace stats + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) + (toCheck.push context.freshExpr) fuel result) : + LargeEliminatorLoopTrace stats context + (.forallE name domain body binderInfo) argIdx toCheck (fuel + 1) result + | terminal + (context : Context) (source : Expr) (fuel argIdx : Nat) + (toCheck : Array Expr) (notForall : source.isForall = false) : + LargeEliminatorLoopTrace stats context source argIdx toCheck (fuel + 1) + (toCheck.all source.getAppArgs.contains) + +namespace LargeEliminatorLoopTrace + +def parameterCount + (trace : LargeEliminatorLoopTrace stats context source argIdx toCheck + fuel result) : Nat := + match trace with + | .parameter (tail := tail) .. => tail.parameterCount + 1 + | .proofField (tail := tail) .. => tail.parameterCount + | .dataField (tail := tail) .. => tail.parameterCount + | .terminal .. => 0 + +def proofFieldCount + (trace : LargeEliminatorLoopTrace stats context source argIdx toCheck + fuel result) : Nat := + match trace with + | .parameter (tail := tail) .. => tail.proofFieldCount + | .proofField (tail := tail) .. => tail.proofFieldCount + 1 + | .dataField (tail := tail) .. => tail.proofFieldCount + | .terminal .. => 0 + +def dataFieldCount + (trace : LargeEliminatorLoopTrace stats context source argIdx toCheck + fuel result) : Nat := + match trace with + | .parameter (tail := tail) .. => tail.dataFieldCount + | .proofField (tail := tail) .. => tail.dataFieldCount + | .dataField (tail := tail) .. => tail.dataFieldCount + 1 + | .terminal .. => 0 + +/-- Erasing the retained singleton trace replays the exact ordinary checker +loop, including every `ensureType` call and local declaration. -/ +theorem run + (trace : LargeEliminatorLoopTrace stats context source argIdx toCheck + fuel result) : + isLargeEliminator.loop stats source argIdx toCheck fuel context = + .ok result := by + induction trace with + | parameter context fuel argIdx toCheck name domain body binderInfo + isParameter tail ih => + rw [show fuel + 1 = Nat.succ fuel by omega] + rw [isLargeEliminator.loop.eq_2, withLocalDecl_apply] + have notField : ¬ argIdx ≥ stats.params.size := + Nat.not_le.mpr isParameter + simp only [notField, if_false, Bind.bind] + exact ih + | proofField context fuel argIdx toCheck name domain body binderInfo + sortResult isField ensureStep isProp tail ih => + rw [show fuel + 1 = Nat.succ fuel by omega] + rw [isLargeEliminator.loop.eq_2, withLocalDecl_apply] + simp only [isField, if_true, ReaderT.bind, Bind.bind, + liftTypeChecker_apply] + rw [ensureStep] + simp only [Except.bind, isProp, Bool.not_true, Bool.false_eq_true, if_false] + exact ih + | dataField context fuel argIdx toCheck name domain body binderInfo + sortResult isField ensureStep isProp tail ih => + rw [show fuel + 1 = Nat.succ fuel by omega] + rw [isLargeEliminator.loop.eq_2, withLocalDecl_apply] + simp only [isField, if_true, ReaderT.bind, Bind.bind, + liftTypeChecker_apply] + rw [ensureStep] + simp only [Except.bind, isProp, Bool.not_false, if_true] + exact ih + | terminal context source fuel argIdx toCheck notForall => + cases source <;> + simp_all [isLargeEliminator.loop, ReaderT.pure, Pure.pure, + Except.pure, Expr.isForall] + +/-- Execute the singleton branch once while retaining the exact branch and +checker observations that produced its Boolean result. -/ +def buildExecution (stats : InductiveStats) (context : Context) + (source : Expr) (argIdx : Nat) (toCheck : Array Expr) : + (fuel : Nat) → Except Exception + (Sigma fun result => LargeEliminatorLoopTrace stats context source + argIdx toCheck fuel result) + | 0 => .error .deepRecursion + | fuel + 1 => + match hforall : source.isForall with + | false => .ok ⟨toCheck.all source.getAppArgs.contains, + .terminal context source fuel argIdx toCheck hforall⟩ + | true => + match source with + | .forallE name domain body binderInfo => + let nextContext := context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) + let nextSource := body.instantiate1 context.freshExpr + if isParameter : argIdx < stats.params.size then + match buildExecution stats nextContext nextSource (argIdx + 1) + toCheck fuel with + | .error error => .error error + | .ok ⟨result, tail⟩ => .ok ⟨result, + .parameter context fuel argIdx toCheck name domain body + binderInfo isParameter tail⟩ + else + match hensure : TypeChecker.M.run nextContext.env nextContext.safety + nextContext.lctx nextContext.lparams nextContext.fuel + (TypeChecker.ensureType domain) with + | .error error => .error error + | .ok sortResult => + if isProp : sortResult.sortLevel!.isAlwaysZero then + match buildExecution stats nextContext nextSource + (argIdx + 1) toCheck fuel with + | .error error => .error error + | .ok ⟨result, tail⟩ => .ok ⟨result, + .proofField context fuel argIdx toCheck name domain body + binderInfo sortResult (Nat.le_of_not_gt isParameter) + hensure isProp tail⟩ + else + match buildExecution stats nextContext nextSource + (argIdx + 1) (toCheck.push context.freshExpr) fuel with + | .error error => .error error + | .ok ⟨result, tail⟩ => .ok ⟨result, + .dataField context fuel argIdx toCheck name domain body + binderInfo sortResult (Nat.le_of_not_gt isParameter) + hensure (by + cases h : sortResult.sortLevel!.isAlwaysZero <;> simp_all) + tail⟩ + | _ => .error <| .other + "large-eliminator source shape disagrees with isForall" + +end LargeEliminatorLoopTrace + +/-- The source identity and exact loop retained when the singleton branch of +`isLargeEliminator` is selected. -/ +structure LargeEliminatorSingletonExecution + (stats : InductiveStats) (indTypes : Array InductiveType) + (context : Context) (result : Bool) where + indType : InductiveType + indTypes_eq : indTypes = #[indType] + ctor : Constructor + ctors_eq : indType.ctors = [ctor] + trace : LargeEliminatorLoopTrace stats context ctor.type 0 #[] + context.fuel.inductiveFuel result + +/-- One exact successful execution of `isLargeEliminator`. The ordinary +equation is always retained; the singleton payload additionally exposes all +field-sort observations made by the executable. -/ +structure LargeEliminatorExecution + (stats : InductiveStats) (indTypes : Array InductiveType) + (context : Context) where + result : Bool + singleton : Option + (LargeEliminatorSingletonExecution stats indTypes context result) + run_eq : isLargeEliminator stats indTypes context = .ok result + +namespace LargeEliminatorExecution + +/-- Execute the ordinary decision and retain a transparent refinement of its +singleton traversal. -/ +def buildExecution (stats : InductiveStats) (indTypes : Array InductiveType) + (context : Context) : + Except Exception (LargeEliminatorExecution stats indTypes context) := + match hrun : isLargeEliminator stats indTypes context with + | .error error => .error error + | .ok result => + if stats.isNotZero then + .ok { result, singleton := none, run_eq := hrun } + else + match htypes : indTypes with + | #[indType] => + match hctors : indType.ctors with + | [ctor] => + match LargeEliminatorLoopTrace.buildExecution stats context + ctor.type 0 #[] context.fuel.inductiveFuel with + | .error error => .error error + | .ok ⟨traceResult, trace⟩ => + if hsame : traceResult = result then + .ok { + result + singleton := some { + indType + indTypes_eq := rfl + ctor + ctors_eq := hctors + trace := hsame ▸ trace } + run_eq := by simpa only [htypes] using hrun } + else + .error <| .other + "large-eliminator trace disagrees with ordinary result" + | _ => .ok { + result + singleton := none + run_eq := by simpa only [htypes] using hrun } + | _ => .ok { + result + singleton := none + run_eq := by simpa only [htypes] using hrun } + +end LargeEliminatorExecution + +/-- Exact `getElimLevel` execution paired with the retained large-elimination +decision that controls it. `level_eq` exposes both the zero and fresh-parameter +branches without unfolding the monadic checker again. -/ +structure ElimLevelExecution + (stats : InductiveStats) (indTypes : Array InductiveType) + (context : Context) where + large : LargeEliminatorExecution stats indTypes context + level : Level + level_eq : level = if large.result then + .param (getFreshElimParam context.lparams) else .zero + run_eq : getElimLevel stats indTypes context = .ok level + +namespace ElimLevelExecution + +/-- Recompose `getElimLevel` from the retained exact large-elimination run. -/ +theorem run_of_large + (large : LargeEliminatorExecution stats indTypes context) : + getElimLevel stats indTypes context = .ok + (if large.result then .param (getFreshElimParam context.lparams) + else .zero) := by + unfold getElimLevel + simp only [ReaderT.bind, Bind.bind] + rw [large.run_eq] + cases large.result <;> rfl + +def buildExecution (stats : InductiveStats) (indTypes : Array InductiveType) + (context : Context) : + Except Exception (ElimLevelExecution stats indTypes context) := do + let large ← LargeEliminatorExecution.buildExecution stats indTypes context + let level := if large.result then + .param (getFreshElimParam context.lparams) else .zero + pure { + large + level + level_eq := rfl + run_eq := run_of_large large } + +theorem level_eq_zero (execution : ElimLevelExecution stats indTypes context) + (small : execution.large.result = false) : + execution.level = .zero := by + rw [execution.level_eq, small] + rfl + +theorem level_eq_param + (execution : ElimLevelExecution stats indTypes context) + (large : execution.large.result = true) : + execution.level = .param (getFreshElimParam context.lparams) := by + rw [execution.level_eq, large] + rfl + +/-- A small eliminator preserves the source universe-level order in recursor +applications. -/ +theorem recLevels_eq_small + (execution : ElimLevelExecution stats indTypes context) + (small : execution.large.result = false) (levels : List Level) : + getRecLevels execution.level levels = levels := by + rw [execution.level_eq_zero small] + rfl + +/-- A large eliminator prepends its fresh elimination level to every source +universe used by recursive calls. -/ +theorem recLevels_eq_large + (execution : ElimLevelExecution stats indTypes context) + (large : execution.large.result = true) (levels : List Level) : + getRecLevels execution.level levels = + .param (getFreshElimParam context.lparams) :: levels := by + rw [execution.level_eq_param large] + rfl + +/-- A small eliminator preserves the stored source level-parameter order. -/ +theorem recLevelParams_eq_small + (execution : ElimLevelExecution stats indTypes context) + (small : execution.large.result = false) (lparams : List Name) : + getRecLevelParams execution.level lparams = lparams := by + rw [execution.level_eq_zero small] + rfl + +/-- A large eliminator stores the fresh elimination parameter before every +source level parameter. -/ +theorem recLevelParams_eq_large + (execution : ElimLevelExecution stats indTypes context) + (large : execution.large.result = true) (lparams : List Name) : + getRecLevelParams execution.level lparams = + getFreshElimParam context.lparams :: lparams := by + rw [execution.level_eq_param large] + rfl + +end ElimLevelExecution + +/-- Exact traversal of the constructor-shape fragment of `isKTarget`. The +trace stops at the first visible non-parameter binder, just as the executable +does; it never treats K eligibility as evidence for large elimination. -/ +inductive KTargetCtorTrace (nparams : Nat) : + (source : Expr) → (argIdx : Nat) → (result : Bool) → Type where + | parameter + (argIdx : Nat) (name : Name) (domain body : Expr) + (binderInfo : BinderInfo) + (isParameter : argIdx < nparams) + (tail : KTargetCtorTrace nparams body (argIdx + 1) result) : + KTargetCtorTrace nparams (.forallE name domain body binderInfo) + argIdx result + | field + (argIdx : Nat) (name : Name) (domain body : Expr) + (binderInfo : BinderInfo) + (isField : argIdx ≥ nparams) : + KTargetCtorTrace nparams (.forallE name domain body binderInfo) + argIdx false + | terminal + (source : Expr) (argIdx : Nat) + (notForall : source.isForall = false) : + KTargetCtorTrace nparams source argIdx true + +namespace KTargetCtorTrace + +def parameterCount + (trace : KTargetCtorTrace nparams source argIdx result) : Nat := + match trace with + | .parameter (tail := tail) .. => tail.parameterCount + 1 + | .field .. => 0 + | .terminal .. => 0 + +/-- The K-target walk stops at the first visible constructor field, so this +count is either zero or one. -/ +def fieldCount + (trace : KTargetCtorTrace nparams source argIdx result) : Nat := + match trace with + | .parameter (tail := tail) .. => tail.fieldCount + | .field .. => 1 + | .terminal .. => 0 + +/-- Erasing the retained constructor trace yields the exact Boolean consumed +by `isKTarget`. -/ +theorem run + (trace : KTargetCtorTrace nparams source argIdx result) : + isKTargetCtor nparams argIdx source = result := by + induction trace with + | parameter argIdx name domain body binderInfo isParameter tail ih => + simp [isKTargetCtor, isParameter, ih] + | field argIdx name domain body binderInfo isField => + have notParameter : ¬ argIdx < nparams := Nat.not_lt.mpr isField + simp [isKTargetCtor, notParameter] + | terminal source argIdx notForall => + cases source <;> simp_all [isKTargetCtor, Expr.isForall] + +/-- Compute the K-target constructor branch while retaining the exact point +where the parameter prefix ends. -/ +def buildExecution (nparams : Nat) : + (source : Expr) → (argIdx : Nat) → + Sigma fun result => KTargetCtorTrace nparams source argIdx result + | .bvar i, argIdx => ⟨true, .terminal (.bvar i) argIdx rfl⟩ + | .fvar id, argIdx => ⟨true, .terminal (.fvar id) argIdx rfl⟩ + | .mvar id, argIdx => ⟨true, .terminal (.mvar id) argIdx rfl⟩ + | .sort level, argIdx => ⟨true, .terminal (.sort level) argIdx rfl⟩ + | .const name levels, argIdx => + ⟨true, .terminal (.const name levels) argIdx rfl⟩ + | .app fn arg, argIdx => ⟨true, .terminal (.app fn arg) argIdx rfl⟩ + | .lam name domain body binderInfo, argIdx => + ⟨true, .terminal (.lam name domain body binderInfo) argIdx rfl⟩ + | .forallE name domain body binderInfo, argIdx => + if isParameter : argIdx < nparams then + let ⟨result, tail⟩ := buildExecution nparams body (argIdx + 1) + ⟨result, .parameter argIdx name domain body binderInfo + isParameter tail⟩ + else + ⟨false, .field argIdx name domain body binderInfo + (Nat.le_of_not_gt isParameter)⟩ + | .letE name type value body nondep, argIdx => + ⟨true, .terminal (.letE name type value body nondep) argIdx rfl⟩ + | .lit literal, argIdx => ⟨true, .terminal (.lit literal) argIdx rfl⟩ + | .mdata data expr, argIdx => + ⟨true, .terminal (.mdata data expr) argIdx rfl⟩ + | .proj typeName idx struct, argIdx => + ⟨true, .terminal (.proj typeName idx struct) argIdx rfl⟩ + +end KTargetCtorTrace + +/-- The singleton-Prop branch data of one exact `isKTarget` execution. -/ +structure KTargetSingletonExecution + (stats : InductiveStats) (indTypes : Array InductiveType) + (result : Bool) where + indType : InductiveType + indTypes_eq : indTypes = #[indType] + resultLevelZero : stats.resultLevel.isAlwaysZero = true + ctor : Constructor + ctors_eq : indType.ctors = [ctor] + trace : KTargetCtorTrace stats.params.size ctor.type 0 result + +/-- One exact successful execution of `isKTarget`. The ordinary monadic +equation is always retained; a singleton candidate additionally exposes the +constructor-prefix trace that decided its flag. -/ +structure KTargetExecution + (stats : InductiveStats) (indTypes : Array InductiveType) + (context : Context) where + result : Bool + singleton : Option (KTargetSingletonExecution stats indTypes result) + run_eq : isKTarget stats indTypes context = .ok result + +namespace KTargetExecution + +def buildExecution (stats : InductiveStats) + (indTypes : Array InductiveType) (context : Context) : + Except Exception (KTargetExecution stats indTypes context) := + match hrun : isKTarget stats indTypes context with + | .error error => .error error + | .ok result => + match _htypes : indTypes with + | #[indType] => + if hzero : stats.resultLevel.isAlwaysZero then + match hctors : indType.ctors with + | [ctor] => + let ⟨traceResult, trace⟩ := + KTargetCtorTrace.buildExecution stats.params.size ctor.type 0 + if hsame : traceResult = result then + .ok { + result + singleton := some { + indType + indTypes_eq := rfl + resultLevelZero := hzero + ctor + ctors_eq := hctors + trace := hsame ▸ trace } + run_eq := hrun } + else + .error <| .other + "K-target trace disagrees with ordinary result" + | _ => .ok { result, singleton := none, run_eq := hrun } + else + .ok { result, singleton := none, run_eq := hrun } + | _ => .ok { result, singleton := none, run_eq := hrun } + +end KTargetExecution + +/-- The normalization/validation execution extended through constructor +declaration and the exact elimination-level and K-target decisions used by +`run`. This is an operational refinement only: erasing the added fields leaves the existing +normalization candidate and checker equations unchanged. -/ +structure NormalizationEliminationExecution + (nparams : Nat) (types : List InductiveType) + (numNested : Nat) (isUnsafe : Bool) (candidateContext : Context) where + normalization : NormalizationCandidateExecution nparams types numNested + isUnsafe candidateContext + constructorEnv : Environment + declareConstructorsRun : + declareConstructors normalization.stats types.toArray isUnsafe + { normalization.validationContext with + env := normalization.familyEnv } = .ok constructorEnv + elimination : ElimLevelExecution normalization.stats types.toArray + { normalization.validationContext with env := constructorEnv } + kTarget : KTargetExecution normalization.stats types.toArray + { normalization.validationContext with env := constructorEnv } + +namespace NormalizationEliminationExecution + +def candidate + (execution : NormalizationEliminationExecution nparams types numNested + isUnsafe candidateContext) : NormalizationCandidate types := + execution.normalization.candidate + +/-- Execute the existing detailed candidate producer, declare the already +validated constructors, and retain both recursor decisions at precisely the +post-constructor context used by `run`. -/ +def buildExecution + (nparams : Nat) (types : List InductiveType) + (numNested : Nat) (isUnsafe : Bool) (candidateContext : Context) : + Except Exception (NormalizationEliminationExecution nparams types + numNested isUnsafe candidateContext) := do + let normalization ← buildNormalizationCandidateExecution nparams types + numNested isUnsafe candidateContext + let constructorContext : Context := + { normalization.validationContext with env := normalization.familyEnv } + match hdeclare : declareConstructors normalization.stats types.toArray + isUnsafe constructorContext with + | .error error => .error error + | .ok constructorEnv => + let eliminationContext : Context := + { normalization.validationContext with env := constructorEnv } + match ElimLevelExecution.buildExecution normalization.stats + types.toArray eliminationContext with + | .error error => .error error + | .ok elimination => + match KTargetExecution.buildExecution normalization.stats + types.toArray eliminationContext with + | .error error => .error error + | .ok kTarget => .ok { + normalization + constructorEnv + declareConstructorsRun := by + simpa [constructorContext] using hdeclare + elimination := by simpa [eliminationContext] using elimination + kTarget := by simpa [eliminationContext] using kTarget } + +/-- The level list supplied to generated recursive calls. -/ +def recLevels + (execution : NormalizationEliminationExecution nparams types numNested + isUnsafe candidateContext) : List Level := + getRecLevels execution.elimination.level execution.normalization.stats.levels + +/-- The level-parameter list stored in generated recursor metadata. -/ +def recLevelParams + (execution : NormalizationEliminationExecution nparams types numNested + isUnsafe candidateContext) : List Name := + getRecLevelParams execution.elimination.level + execution.normalization.validationContext.lparams + +end NormalizationEliminationExecution + +#guard_named_axioms Ix.Theory.Named.AddInductive.KTargetCtorTrace.run [propext] + +#guard_named_axioms Ix.Theory.Named.AddInductive.KTargetExecution.buildExecution [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.LargeEliminatorLoopTrace.run [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.LargeEliminatorExecution.buildExecution [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ElimLevelExecution.run_of_large [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ElimLevelExecution.recLevelParams_eq_large [propext, Classical.choice, Quot.sound] + +end AddInductive +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Reference/Inductive/Reduce.lean b/Ix/Theory/Named/Reference/Inductive/Reduce.lean new file mode 100644 index 000000000..8ce22e259 --- /dev/null +++ b/Ix/Theory/Named/Reference/Inductive/Reduce.lean @@ -0,0 +1,120 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Structure +import Ix.Theory.Named.Reference.Expr +import Ix.Theory.Named.Reference.Environment.Basic + +namespace Ix.Theory.Named +open Lean hiding Environment +open Kernel + +section +variable [Monad m] (env : Environment) + (whnf : Expr → m Expr) (inferType : Expr → m Expr) (isDefEq : Expr → Expr → m Bool) + (isNeverProp : Expr → m Bool) + +def getFirstCtor (dName : Name) : Option Name := do + let some (.inductInfo info) := env.find? dName | none + info.ctors.head? + +def mkNullaryCtor (type : Expr) (nparams : Nat) : Option Expr := + type.withApp fun d args => do + let .const dName ls := d | none + let name ← getFirstCtor env dName + return mkAppRange (.const name ls) 0 nparams args + +/-- When `e` has the type of a K-like inductive, converts it into a constructor application. + +For instance if we have `e : Eq a a`, it is converted into `Eq.refl a` (which it is definitionally +equal to by proof irrelevance). Note that the indices of `e`'s type must match those of the +constructor application (for instance, `e : Eq a b` cannot be converted if `a` and `b` are not +defeq). -/ +def toCtorWhenK (rval : RecursorVal) (e : Expr) : m Expr := do + assert! rval.k + let appType ← whnf (← inferType e) + let .const appTypeI _ := appType.getAppFn | return e + if appTypeI != rval.getMajorInduct then return e + if appType.hasExprMVar then + let appTypeArgs := appType.getAppArgs + for h : i in [rval.numParams:appTypeArgs.size] do + if appTypeArgs[i].hasExprMVar then return e + let some newCtorApp := mkNullaryCtor env appType rval.numParams | return e + -- check that the indices of types of `e` and `newCtorApp` match + unless ← isDefEq appType (← inferType newCtorApp) do return e + return newCtorApp + +def expandEtaStruct (eType e : Expr) : Expr := + eType.withApp fun I args => Id.run do + let .const I ls := I | return e + let some ctor := getFirstCtor env I | return e + let some (.ctorInfo info) := env.find? ctor | unreachable! + let mut result := mkAppRange (.const ctor ls) 0 info.numParams args + for i in [:info.numFields] do + result := .app result (.proj I i e) + pure result + +/-- When `e` is of non-recursive structure type, and that type is not a proposition, converts `e` +into a constructor application using projections. + +For instance if we have `e : α × β`, it is converted into `Prod.mk α β e.1 e.2` (which is +definitionally equal to `e` by struct eta). -/ +def toCtorWhenStruct (inductName : Name) (e : Expr) : m Expr := do + if !env.isNonRecStructure inductName || (e.isConstructorApp?' env).isSome then + return e + let eType ← whnf (← inferType e) + if !eType.getAppFn.isConstOf inductName then return e + -- Lean tests `is_prop eType` and declines to expand when it holds; the named specification instead requires + -- the level to be *never* zero, so an uncertain level declines too (see `divergences.md`). + -- Either way the level comes from a sort-ensuring check, so a non-sort type raises a kernel + -- error rather than reaching an unreachable branch. + unless ← isNeverProp eType do return e + return expandEtaStruct env eType e + +def getRecRuleFor (rval : RecursorVal) (major : Expr) : Option RecursorRule := do + let .const fn _ := major.getAppFn | none + rval.rules.find? (·.ctor == fn) + +/-- Performs recursor reduction on `e` (returning `none` if not applicable). + +For recursor reduction to occur, `e` must be a recursor application where the major premise is +either a complete constructor application, a `Nat` or `String` literal, or of a K- or +structure-like inductive type (in each case it is converted into an equivalent constructor +application). The reduction is done by applying the `RecursorRule.rhs` associated with the +constructor to everything before the indices in the recursor application (its parameters, motives +and minor premises) and then to the fields of the constructor application; any arguments after the +major premise are re-applied to the result. -/ +def inductiveReduceRec [Monad m] (env : Environment) (e : Expr) + (whnf : Expr → m Expr) (inferType : Expr → m Expr) (isDefEq : Expr → Expr → m Bool) + (isNeverProp : Expr → m Bool) : + m (Option Expr) := do + let .const recFn ls := e.getAppFn | return none + let some (.recInfo info) := env.find? recFn | return none + let recArgs := e.getAppArgs + let majorIdx := info.getMajorIdx + let some major := recArgs[majorIdx]? | return none + let mut major := major + if info.k then + major ← toCtorWhenK env whnf inferType isDefEq info major + match ← whnf major with + | .lit (.natVal n) => major := .natLitToConstructor n + | .lit (.strVal s) => major ← whnf (.strLitToConstructor s) + | e => major ← toCtorWhenStruct env whnf inferType isNeverProp info.getMajorInduct e + let some rule := getRecRuleFor info major | return none + let majorArgs := major.getAppArgs + if rule.nfields > majorArgs.size then return none + if ls.length != info.levelParams.length then return none + let mut rhs := rule.rhs.instantiateLevelParams info.levelParams ls + -- get the parameters, motives and minor premises from the recursor application (recursor rules + -- don't need the indices, as these are determined by the constructor and its parameters/fields) + rhs := mkAppRange rhs 0 info.getFirstIndexIdx recArgs + -- get fields from constructor application + rhs := mkAppRange rhs (majorArgs.size - rule.nfields) majorArgs.size majorArgs + if majorIdx + 1 < recArgs.size then + rhs := mkAppRange rhs (majorIdx + 1) recArgs.size recArgs + return rhs + +end diff --git a/Ix/Theory/Named/Reference/Inductive/ValidationTrace.lean b/Ix/Theory/Named/Reference/Inductive/ValidationTrace.lean new file mode 100644 index 000000000..b757d208d --- /dev/null +++ b/Ix/Theory/Named/Reference/Inductive/ValidationTrace.lean @@ -0,0 +1,1600 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Reference.Inductive.Add + +set_option linter.unusedSimpArgs false + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +namespace AddInductive +open TypeChecker + +/-- The constructor root check runs with no validation-local declarations, +while retaining every other field of the post-family checker context. -/ +def Context.withEmptyLocalContext (context : Context) : Context := + { context with lctx := {} } + +/-- One exact successful `ensureType` execution used for an ordinary +constructor field. -/ +structure ConstructorEnsureTypeStep where + context : Context + source : Expr + result : Expr + +def ConstructorEnsureTypeStep.Valid + (step : ConstructorEnsureTypeStep) : Prop := + TypeChecker.M.run step.context.env step.context.safety + step.context.lctx step.context.lparams step.context.fuel + (TypeChecker.ensureType step.source) = + .ok step.result + +/-- The two successful universe branches of `checkConstructors`: either the +transparent structural comparison succeeds, or the exact fallback comparison +does. Keeping the branch choice prevents a trace from silently replacing the +executable universe test with a stronger premise. -/ +inductive ConstructorUniverseTrace (resultLevel fieldLevel : Level) : Type where + | structural + (valid : levelStructGe resultLevel fieldLevel = true) : + ConstructorUniverseTrace resultLevel fieldLevel + | fallback + (structuralFailed : levelStructGe resultLevel fieldLevel = false) + (valid : (resultLevel.isAlwaysZero || resultLevel.geq fieldLevel) = true) : + ConstructorUniverseTrace resultLevel fieldLevel + +namespace ConstructorUniverseTrace + +/-- A field rejected by both executable universe comparisons cannot have a +successful universe trace. -/ +theorem not_nonempty_of_rejected + (structuralRejected : levelStructGe resultLevel fieldLevel = false) + (fallbackRejected : + (resultLevel.isAlwaysZero || resultLevel.geq fieldLevel) = false) : + ¬ Nonempty (ConstructorUniverseTrace resultLevel fieldLevel) := by + rintro ⟨trace⟩ + cases trace with + | structural valid => simp_all + | fallback _ valid => simp_all + +end ConstructorUniverseTrace + +/-- Complete successful traversal of `checkPositivity.loop`, indexed by the +exact source expression, checker context, and remaining fuel. The recursive +constructor records the precise local declaration used by the executable +traversal; the terminal constructor records the accepted recursive target. -/ +inductive ConstructorPositivityTrace + (stats : InductiveStats) (ctor : Name) (argIdx : Nat) : + (context : Context) → (source : Expr) → (fuel : Nat) → Type where + | absent + (context : Context) (source result : Expr) (fuel : Nat) + (whnf : CandidateWhnfStep.Valid ⟨context, source, result⟩) + (occurs : hasIndOcc stats.indConsts result = false) : + ConstructorPositivityTrace stats ctor argIdx context source (fuel + 1) + | forallE + (context : Context) (source : Expr) (fuel : Nat) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (whnf : CandidateWhnfStep.Valid + ⟨context, source, .forallE name domain body binderInfo⟩) + (occurs : hasIndOcc stats.indConsts + (.forallE name domain body binderInfo) = true) + (domainFree : hasIndOcc stats.indConsts domain = false) + (tail : ConstructorPositivityTrace stats ctor argIdx + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel) : + ConstructorPositivityTrace stats ctor argIdx context source (fuel + 1) + | target + (context : Context) (source result : Expr) (fuel targetIdx : Nat) + (whnf : CandidateWhnfStep.Valid ⟨context, source, result⟩) + (occurs : hasIndOcc stats.indConsts result = true) + (terminal : result.isForall = false) + (valid : isValidIndApp? stats result = some targetIdx) : + ConstructorPositivityTrace stats ctor argIdx context source (fuel + 1) + +namespace ConstructorPositivityTrace + +/-- Observable recursive-target data retained by the positivity traversal. +`binderDepth` counts positive Pi domains traversed before the terminal family +application. -/ +structure Target where + familyIdx : Nat + binderDepth : Nat + deriving DecidableEq, Repr + +/-- Erase proof fields while retaining the exact sibling-family ordinal and +positive-Pi depth selected by the executable positivity run. -/ +def target? : + ConstructorPositivityTrace stats ctor argIdx context source fuel → + Option Target + | .absent _ _ _ _ _ _ => none + | .forallE _ _ _ _ _ _ _ _ _ _ tail => + tail.target?.map fun target => + { target with binderDepth := target.binderDepth + 1 } + | .target _ _ _ _ familyIdx _ _ _ _ => + some { familyIdx, binderDepth := 0 } + +/-- Erasing a positivity trace replays the exact executable traversal. -/ +theorem run + (trace : ConstructorPositivityTrace stats ctor argIdx context source fuel) : + checkPositivity.loop stats ctor argIdx source fuel context = .ok () := by + induction trace with + | absent context source result fuel whnf occurs => + unfold checkPositivity.loop + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [whnf] + simp only [Except.bind] + rw [occurs] + rfl + | forallE context source fuel name domain body binderInfo whnf occurs + domainFree tail ih => + unfold checkPositivity.loop + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [whnf] + simp only [Except.bind] + rw [occurs] + simp only [Bool.not_true, Bool.false_eq_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] + rw [domainFree] + simp only [Bool.false_eq_true, if_false, withLocalDecl_apply] + exact ih + | target context source result fuel targetIdx whnf occurs terminal valid => + unfold checkPositivity.loop + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [whnf] + simp only [Except.bind] + rw [occurs] + simp only [Bool.not_true, Bool.false_eq_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] + cases result <;> + simp_all [Expr.isForall, ReaderT.pure, Pure.pure, Except.pure] + +/-- Every successful executable positivity traversal decomposes into the +source-indexed trace above. -/ +theorem exists_of_run + (success : checkPositivity.loop stats ctor argIdx source fuel context = + .ok ()) : + Nonempty (ConstructorPositivityTrace stats ctor argIdx + context source fuel) := by + induction fuel generalizing context source with + | zero => + rw [checkPositivity.loop.eq_1] at success + change Except.error Exception.deepRecursion = Except.ok () at success + contradiction + | succ fuel ih => + rw [checkPositivity.loop.eq_2] at success + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] at success + cases hwhnf : TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf source) with + | error err => simp_all [Except.bind] + | ok result => + rw [hwhnf] at success + simp only [Except.bind] at success + cases hocc : hasIndOcc stats.indConsts result with + | false => exact ⟨.absent context source result fuel hwhnf hocc⟩ + | true => + rw [hocc] at success + simp only [Bool.not_true, Bool.false_eq_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] at success + cases result + case forallE name domain body binderInfo => + simp only at success + cases hdomain : hasIndOcc stats.indConsts domain with + | false => + rw [hdomain] at success + simp only [Bool.false_eq_true, if_false, + withLocalDecl_apply] at success + obtain ⟨tail⟩ := ih success + exact ⟨.forallE context source fuel name domain body + binderInfo hwhnf hocc hdomain tail⟩ + | true => + rw [hdomain] at success + change Except.error _ = Except.ok () at success + contradiction + all_goals + simp only at success + cases hvalid : isValidIndApp? stats _ with + | none => + rw [hvalid] at success + change Except.error _ = Except.ok () at success + contradiction + | some targetIdx => + exact ⟨.target context source _ fuel targetIdx + hwhnf hocc rfl hvalid⟩ + +/-- Execute the positivity traversal while retaining its exact dependent +trace as data. Unlike `exists_of_run`, this decomposition is transparent and +therefore remains available to later executable alignment audits; erasing the +result with `run` recovers the ordinary checker execution. -/ +def buildExecution (stats : InductiveStats) (ctor : Name) (argIdx : Nat) + (context : Context) (source : Expr) : + (fuel : Nat) → Except Exception + (ConstructorPositivityTrace stats ctor argIdx context source fuel) + | 0 => .error .deepRecursion + | fuel + 1 => + match hwhnf : TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.whnf source) with + | .error error => .error error + | .ok result => + match hoccurs : hasIndOcc stats.indConsts result with + | false => .ok (.absent context source result fuel hwhnf hoccurs) + | true => + match hforall : result.isForall with + | true => + match result with + | .forallE name domain body binderInfo => + match hdomain : hasIndOcc stats.indConsts domain with + | true => .error <| .other + s!"arg #{argIdx + 1} of '{ctor}' has a non positive occurrence of the datatypes being declared" + | false => + match buildExecution stats ctor argIdx + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel with + | .error error => .error error + | .ok tail => .ok (.forallE context source fuel name + domain body binderInfo hwhnf hoccurs hdomain tail) + | _ => .error <| .other + "positivity WHNF shape disagrees with isForall" + | false => + match hvalid : isValidIndApp? stats result with + | none => .error <| .other + s!"arg #{argIdx + 1} of '{ctor}' has a non valid occurrence of the datatypes being declared" + | some targetIdx => .ok (.target context source result fuel + targetIdx hwhnf hoccurs hforall hvalid) + +/-- The transparent decomposition succeeds on every input accepted by the +executable positivity traversal, so retained-trace construction needs no +choice principle. -/ +theorem buildExecution_ok_of_run + (success : checkPositivity.loop stats ctor argIdx source fuel context = + .ok ()) : + ∃ trace, buildExecution stats ctor argIdx context source fuel = + .ok trace := by + induction fuel generalizing context source with + | zero => + rw [checkPositivity.loop.eq_1] at success + change Except.error Exception.deepRecursion = Except.ok () at success + contradiction + | succ fuel ih => + rw [checkPositivity.loop.eq_2] at success + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] at success + unfold buildExecution + split + next error heq => + rw [heq] at success + simp [Except.bind] at success + next result heq => + rw [heq] at success + simp only [Except.bind] at success + split + next hoccurs => exact ⟨_, rfl⟩ + next hoccurs => + rw [hoccurs] at success + simp only [Bool.not_true, Bool.false_eq_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] at success + cases result <;> simp only [Expr.isForall] <;> simp only at success + case forallE name domain body binderInfo => + split + next hdomain => + rw [hdomain] at success + change Except.error _ = Except.ok () at success + contradiction + next hdomain => + rw [hdomain] at success + have tailSuccess : + checkPositivity.loop stats ctor argIdx + (body.instantiate1 context.freshExpr) fuel + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) = .ok () := success + obtain ⟨tail, htail⟩ := ih tailSuccess + rw [htail] + exact ⟨_, rfl⟩ + all_goals + split + next hvalid => + rw [hvalid] at success + change Except.error _ = Except.ok () at success + contradiction + next targetIdx hvalid => exact ⟨_, rfl⟩ + +/-- An exact positivity failure, including its diagnostic payload, excludes a +successful trace at precisely that source/context/fuel position. -/ +theorem not_nonempty_of_error + (failure : checkPositivity.loop stats ctor argIdx source fuel context = + .error err) : + ¬ Nonempty (ConstructorPositivityTrace stats ctor argIdx + context source fuel) := by + rintro ⟨trace⟩ + have success := trace.run + rw [failure] at success + contradiction + +end ConstructorPositivityTrace + +/-- Whether positivity was executed or skipped by the exact `isUnsafe` +branch of constructor validation. -/ +inductive ConstructorPositivityModeTrace + (stats : InductiveStats) (isUnsafe : Bool) + (ctor : Name) (argIdx : Nat) (context : Context) (source : Expr) : Type where + | skipped + (isUnsafe_eq : isUnsafe = true) : + ConstructorPositivityModeTrace stats isUnsafe ctor argIdx context source + | safe + (isUnsafe_eq : isUnsafe = false) + (trace : ConstructorPositivityTrace stats ctor argIdx context source + context.fuel.inductiveFuel) : + ConstructorPositivityModeTrace stats isUnsafe ctor argIdx context source + +namespace ConstructorPositivityModeTrace + +/-- Observable recursive target for the exact safe/unsafe positivity branch. +Unsafe validation deliberately exposes no positivity claim. -/ +def target? : + ConstructorPositivityModeTrace + stats isUnsafe ctor argIdx context source → + Option ConstructorPositivityTrace.Target + | .skipped _ => none + | .safe _ trace => trace.target? + +theorem run + (trace : ConstructorPositivityModeTrace + stats isUnsafe ctor argIdx context source) : + (if !isUnsafe then checkPositivity stats source ctor argIdx else pure ()) + context = .ok () := by + cases trace with + | skipped h => simp [h, ReaderT.pure, Pure.pure, Except.pure] + | safe h trace => + simp only [h, Bool.not_false, if_true] + unfold checkPositivity + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using trace.run + +/-- Execute the recorded positivity branch and then an exact continuation. -/ +theorem bind_run + (trace : ConstructorPositivityModeTrace + stats isUnsafe ctor argIdx context source) + (next : M α) (result : α) + (nextRun : next context = .ok result) : + (do + if !isUnsafe then checkPositivity stats source ctor argIdx + next) context = .ok result := by + cases trace with + | skipped h => + simp [h, nextRun, ReaderT.bind, Bind.bind, + ReaderT.pure, Pure.pure, Except.bind, Except.pure] + | safe h trace => + have positivityRun : + checkPositivity stats source ctor argIdx context = .ok () := by + unfold checkPositivity + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using trace.run + simp [h, positivityRun, nextRun, ReaderT.bind, Bind.bind, + ReaderT.pure, Pure.pure, Except.bind, Except.pure] + +/-- A successful executable positivity branch determines whether validation +was skipped for an unsafe declaration or supplies the full safe trace. -/ +theorem exists_of_run + (success : + (if !isUnsafe then checkPositivity stats source ctor argIdx else pure ()) + context = .ok ()) : + Nonempty (ConstructorPositivityModeTrace + stats isUnsafe ctor argIdx context source) := by + cases hUnsafe : isUnsafe with + | false => + simp only [hUnsafe, Bool.not_false, if_true] at success + unfold checkPositivity at success + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] at success + obtain ⟨trace⟩ := ConstructorPositivityTrace.exists_of_run success + exact ⟨.safe rfl trace⟩ + | true => exact ⟨.skipped rfl⟩ + +/-- Transparently retain the exact safe/unsafe positivity branch selected by +constructor validation. -/ +def buildExecution (stats : InductiveStats) (isUnsafe : Bool) + (ctor : Name) (argIdx : Nat) (context : Context) (source : Expr) : + Except Exception + (ConstructorPositivityModeTrace stats isUnsafe ctor argIdx context source) := + match isUnsafe with + | true => .ok (.skipped rfl) + | false => + match ConstructorPositivityTrace.buildExecution stats ctor argIdx + context source context.fuel.inductiveFuel with + | .error error => .error error + | .ok trace => .ok (.safe rfl trace) + +/-- The retained safe/unsafe branch decomposition succeeds whenever the +executable positivity branch does. -/ +theorem buildExecution_ok_of_run + (success : + (if !isUnsafe then checkPositivity stats source ctor argIdx else pure ()) + context = .ok ()) : + ∃ trace, buildExecution stats isUnsafe ctor argIdx context source = + .ok trace := by + cases isUnsafe with + | true => exact ⟨_, rfl⟩ + | false => + simp only [Bool.not_false, if_true] at success + unfold checkPositivity at success + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] at success + obtain ⟨trace, htrace⟩ := + ConstructorPositivityTrace.buildExecution_ok_of_run success + unfold buildExecution + rw [htrace] + exact ⟨_, rfl⟩ + +/-- Failure of the exact safe/unsafe positivity branch excludes its retained +mode trace without changing the executable diagnostic. -/ +theorem not_nonempty_of_error + (failure : + (if !isUnsafe then checkPositivity stats source ctor argIdx else pure ()) + context = .error err) : + ¬ Nonempty (ConstructorPositivityModeTrace + stats isUnsafe ctor argIdx context source) := by + rintro ⟨trace⟩ + have success := trace.run + rw [failure] at success + contradiction + +end ConstructorPositivityModeTrace + +/-- Exact successful validation of one constructor type from its root through +its parameter prefix, ordinary fields, positivity checks, and terminal family +application. Every recursive index is selected by the executable traversal. -/ +inductive ConstructorTypeValidationTrace + (stats : InductiveStats) (isUnsafe : Bool) + (familyIdx : Nat) (ctor : Name) : + (context : Context) → (source : Expr) → + (argIdx fuel : Nat) → Type where + | parameter + (context : Context) (fuel argIdx : Nat) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (param parameterType : Expr) + (parameterAt : stats.params[argIdx]? = some param) + (parameterTypeRun : getType param context = .ok parameterType) + (defeq : CandidateIsDefEqStep.Valid + ⟨context, domain, parameterType⟩) + (tail : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context (body.instantiate1 param) (argIdx + 1) fuel) : + ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context (.forallE name domain body binderInfo) argIdx (fuel + 1) + | ordinary + (context : Context) (fuel argIdx : Nat) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (sortResult : Expr) + (noParameter : stats.params[argIdx]? = none) + (ensureType : ConstructorEnsureTypeStep.Valid + ⟨context, domain, sortResult⟩) + (universeTrace : ConstructorUniverseTrace + stats.resultLevel sortResult.sortLevel!) + (positivity : ConstructorPositivityModeTrace + stats isUnsafe ctor argIdx context domain) + (tail : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) fuel) : + ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context (.forallE name domain body binderInfo) argIdx (fuel + 1) + | terminal + (context : Context) (source : Expr) (fuel argIdx : Nat) + (terminal : source.isForall = false) + (valid : isValidIndAppIdx stats source familyIdx = true) : + ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx (fuel + 1) + +namespace ConstructorTypeValidationTrace + +/-- Field-ordered recursive-target observations for one constructor. Parameter +binders are omitted; every ordinary constructor field contributes one slot. -/ +def targets : + ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel → + List (Option ConstructorPositivityTrace.Target) + | .parameter _ _ _ _ _ _ _ _ _ _ _ _ tail => tail.targets + | .ordinary _ _ _ _ _ _ _ _ _ _ _ positivity tail => + positivity.target? :: tail.targets + | .terminal _ _ _ _ _ _ => [] + +/-- Erasing one constructor-type trace replays the exact inner +`checkConstructorType.loop` execution. -/ +theorem run + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) : + checkConstructorType.loop stats isUnsafe familyIdx ctor source argIdx fuel + context = .ok () := by + induction trace with + | parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeRun defeq tail ih => + rw [show fuel + 1 = Nat.succ fuel by omega] + rw [checkConstructorType.loop.eq_2] + rw [parameterAt] + simp only [ReaderT.bind, Bind.bind] + rw [parameterTypeRun] + simp only [Except.bind, liftTypeChecker_apply] + rw [defeq] + simp only [if_true, ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] + exact ih + | ordinary context fuel argIdx name domain body binderInfo sortResult noParameter + ensureType universeTrace positivity tail ih => + rw [show fuel + 1 = Nat.succ fuel by omega] + rw [checkConstructorType.loop.eq_2] + rw [noParameter] + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [ensureType] + simp only [Except.bind] + let next : M PUnit := + withLocalDecl name binderInfo (consumeTypeAnnotations domain) fun arg => + checkConstructorType.loop stats isUnsafe familyIdx ctor + (body.instantiate1 arg) (argIdx + 1) fuel + have nextRun : next context = .ok () := by + simp only [next, withLocalDecl_apply] + exact ih + have restRun : + (do + if !isUnsafe then checkPositivity stats domain ctor argIdx + next) context = .ok () := + positivity.bind_run next () nextRun + cases universeTrace with + | structural valid => + rw [valid] + simp only [if_true, ReaderT.pure, Pure.pure, + ReaderT.bind, Bind.bind, Except.bind, Except.pure] + exact restRun + | fallback structuralFailed valid => + rw [structuralFailed, valid] + simp only [Bool.true_eq_false, Bool.not_true, if_false, + Bool.false_eq_true, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] + exact restRun + | terminal context source fuel argIdx terminal valid => + rw [show fuel + 1 = Nat.succ fuel by omega] + cases source <;> + simp_all [checkConstructorType.loop, Expr.isForall, + ReaderT.pure, Pure.pure, Except.pure] + +/-- Every successful one-constructor telescope traversal decomposes into the +exact parameter, field, universe, positivity, and terminal trace. -/ +theorem exists_of_run + (success : + checkConstructorType.loop stats isUnsafe familyIdx ctor source argIdx fuel + context = .ok ()) : + Nonempty (ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) := by + induction fuel generalizing context source argIdx with + | zero => + rw [checkConstructorType.loop.eq_1] at success + change Except.error Exception.deepRecursion = Except.ok () at success + contradiction + | succ fuel ih => + rw [show fuel + 1 = Nat.succ fuel by omega] at success + cases source + case forallE name domain body binderInfo => + rw [checkConstructorType.loop.eq_2] at success + simp only at success + cases hparam : stats.params[argIdx]? with + | some param => + rw [hparam] at success + simp only [ReaderT.bind, Bind.bind] at success + cases hget : getType param context with + | error err => simp_all [Except.bind] + | ok parameterType => + rw [hget] at success + simp only [Except.bind, liftTypeChecker_apply] at success + cases hdefeq : TypeChecker.M.run context.env context.safety + context.lctx context.lparams context.fuel + (TypeChecker.isDefEq domain parameterType) with + | error err => simp_all [Except.bind] + | ok equal => + rw [hdefeq] at success + simp only [Except.bind] at success + cases equal with + | false => + change Except.error _ = Except.ok () at success + contradiction + | true => + simp only [if_true, ReaderT.pure, Pure.pure, + ReaderT.bind, Bind.bind, Except.bind, + Except.pure] at success + obtain ⟨tail⟩ := ih success + exact ⟨.parameter context fuel argIdx name domain body + binderInfo param parameterType hparam hget hdefeq tail⟩ + | none => + rw [hparam] at success + simp only [ReaderT.bind, Bind.bind, + liftTypeChecker_apply] at success + cases hensure : TypeChecker.M.run context.env context.safety + context.lctx context.lparams context.fuel + (TypeChecker.ensureType domain) with + | error err => simp_all [Except.bind] + | ok sortResult => + rw [hensure] at success + simp only [Except.bind] at success + have finish + (universeTrace : ConstructorUniverseTrace + stats.resultLevel sortResult.sortLevel!) + (restSuccess : + (do + if !isUnsafe then + checkPositivity stats domain ctor argIdx + withLocalDecl name binderInfo + (consumeTypeAnnotations domain) fun arg => + checkConstructorType.loop stats isUnsafe familyIdx ctor + (body.instantiate1 arg) (argIdx + 1) fuel) + context = .ok ()) : + Nonempty (ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context + (.forallE name domain body binderInfo) argIdx (fuel + 1)) := by + cases isUnsafe with + | false => + simp only [Bool.not_false, if_true, + ReaderT.bind, Bind.bind] at restSuccess + cases hpos : checkPositivity stats domain ctor argIdx context with + | error err => simp_all [Except.bind] + | ok typeUnit => + cases typeUnit + rw [hpos] at restSuccess + simp only [Except.bind, withLocalDecl_apply] at restSuccess + have hposLoop : + checkPositivity.loop stats ctor argIdx domain + context.fuel.inductiveFuel context = .ok () := by + unfold checkPositivity at hpos + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using hpos + obtain ⟨positivityTrace⟩ := + ConstructorPositivityTrace.exists_of_run hposLoop + obtain ⟨tail⟩ := ih restSuccess + exact ⟨.ordinary context fuel argIdx name domain body + binderInfo sortResult hparam hensure universeTrace + (.safe rfl positivityTrace) tail⟩ + | true => + simp only [Bool.not_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure, + withLocalDecl_apply] at restSuccess + obtain ⟨tail⟩ := ih restSuccess + exact ⟨.ordinary context fuel argIdx name domain body + binderInfo sortResult hparam hensure universeTrace + (.skipped rfl) tail⟩ + cases hstruct : levelStructGe stats.resultLevel + sortResult.sortLevel! with + | true => + rw [hstruct] at success + simp only [if_true, ReaderT.pure, Pure.pure, + ReaderT.bind, Bind.bind, Except.bind, + Except.pure] at success + exact finish (.structural hstruct) success + | false => + rw [hstruct] at success + simp only [Bool.false_eq_true, if_false] at success + cases hfallback : + (stats.resultLevel.isAlwaysZero || + stats.resultLevel.geq sortResult.sortLevel!) with + | false => + rw [hfallback] at success + change Except.error _ = Except.ok () at success + contradiction + | true => + rw [hfallback] at success + simp only [Bool.true_eq_false, Bool.not_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] at success + exact finish (.fallback hstruct hfallback) success + all_goals + unfold checkConstructorType.loop at success + simp only at success + cases hvalid : isValidIndAppIdx stats _ familyIdx with + | false => + rw [hvalid] at success + change Except.error _ = Except.ok () at success + contradiction + | true => + exact ⟨.terminal context _ fuel argIdx rfl hvalid⟩ + +/-- Execute one constructor telescope while retaining the exact parameter, +universe, positivity, and terminal choices made by the ordinary validator. +The returned data is transparent, so later executable gates can inspect the +same trace without selecting it through `Classical.choice`. -/ +def buildExecution (stats : InductiveStats) (isUnsafe : Bool) + (familyIdx : Nat) (ctor : Name) (context : Context) (source : Expr) + (argIdx : Nat) : + (fuel : Nat) → Except Exception + (ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) + | 0 => .error .deepRecursion + | fuel + 1 => + match hforall : source.isForall with + | false => + match hvalid : isValidIndAppIdx stats source familyIdx with + | false => .error <| .other s!"invalid return type for '{ctor}'" + | true => .ok (.terminal context source fuel argIdx hforall hvalid) + | true => + match source with + | .forallE name domain body binderInfo => + match hparam : stats.params[argIdx]? with + | some param => + match hget : getType param context with + | .error error => .error error + | .ok parameterType => + match hdefeq : TypeChecker.M.run context.env + context.safety context.lctx context.lparams + context.fuel + (TypeChecker.isDefEq domain parameterType) with + | .error error => .error error + | .ok false => .error <| .other + s!"arg #{argIdx + 1} of '{ctor}' does not match inductive datatype parameters" + | .ok true => + match buildExecution stats isUnsafe familyIdx ctor + context (body.instantiate1 param) (argIdx + 1) + fuel with + | .error error => .error error + | .ok tail => .ok (.parameter context fuel argIdx + name domain body binderInfo param parameterType + hparam hget hdefeq tail) + | none => + match hensure : TypeChecker.M.run context.env context.safety + context.lctx context.lparams context.fuel + (TypeChecker.ensureType domain) with + | .error error => .error error + | .ok sortResult => + let finish (universeTrace : ConstructorUniverseTrace + stats.resultLevel sortResult.sortLevel!) := + match ConstructorPositivityModeTrace.buildExecution + stats isUnsafe ctor argIdx context domain with + | .error error => .error error + | .ok positivity => + match buildExecution stats isUnsafe familyIdx ctor + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) + (argIdx + 1) fuel with + | .error error => .error error + | .ok tail => .ok (.ordinary context fuel argIdx + name domain body binderInfo sortResult hparam + hensure universeTrace positivity tail) + match hstruct : levelStructGe stats.resultLevel + sortResult.sortLevel! with + | true => finish (.structural hstruct) + | false => + match hfallback : stats.resultLevel.isAlwaysZero || + stats.resultLevel.geq sortResult.sortLevel! with + | false => .error <| .other + s!"universe level of type_of(arg #{argIdx + 1}) of '{ctor}' is too big for the corresponding inductive datatype" + | true => finish (.fallback hstruct hfallback) + | _ => .error <| .other + "constructor source shape disagrees with isForall" + +/-- The transparent telescope decomposition succeeds on every constructor +type accepted by the inner executable validator. -/ +theorem buildExecution_ok_of_run + (success : + checkConstructorType.loop stats isUnsafe familyIdx ctor source argIdx fuel + context = .ok ()) : + ∃ trace, buildExecution stats isUnsafe familyIdx ctor context source + argIdx fuel = .ok trace := by + induction fuel generalizing context source argIdx with + | zero => + rw [checkConstructorType.loop.eq_1] at success + change Except.error Exception.deepRecursion = Except.ok () at success + contradiction + | succ fuel ih => + rw [show fuel + 1 = Nat.succ fuel by omega] at success + cases source + case forallE name domain body binderInfo => + rw [checkConstructorType.loop.eq_2] at success + simp only at success + unfold buildExecution + simp only [Expr.isForall] + split + next param hparam => + rw [hparam] at success + simp only [ReaderT.bind, Bind.bind] at success + split + next error heq => + rw [heq] at success + simp [Except.bind] at success + next parameterType heq => + rw [heq] at success + simp only [Except.bind, liftTypeChecker_apply] at success + split + next error heq2 => + rw [heq2] at success + simp [Except.bind] at success + next heq2 => + rw [heq2] at success + simp only [Except.bind] at success + change Except.error _ = Except.ok () at success + contradiction + next heq2 => + rw [heq2] at success + simp only [Except.bind, if_true, ReaderT.pure, Pure.pure, + ReaderT.bind, Bind.bind, Except.pure] at success + obtain ⟨tail, htail⟩ := ih success + rw [htail] + exact ⟨_, rfl⟩ + next hparam => + rw [hparam] at success + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] at success + split + next error heq => + rw [heq] at success + simp [Except.bind] at success + next sortResult heq => + rw [heq] at success + simp only [Except.bind] at success + have finish : + (do + if !isUnsafe then checkPositivity stats domain ctor argIdx + withLocalDecl name binderInfo (consumeTypeAnnotations domain) + fun arg => + checkConstructorType.loop stats isUnsafe familyIdx ctor + (body.instantiate1 arg) (argIdx + 1) fuel) + context = .ok () → + (∃ positivity, + ConstructorPositivityModeTrace.buildExecution stats isUnsafe + ctor argIdx context domain = .ok positivity) ∧ + ∃ tail, + buildExecution stats isUnsafe familyIdx ctor + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) fuel = + .ok tail := by + intro restSuccess + cases isUnsafe with + | false => + simp only [Bool.not_false, if_true, + ReaderT.bind, Bind.bind] at restSuccess + cases hpos : checkPositivity stats domain ctor argIdx + context with + | error err => simp_all [Except.bind] + | ok posUnit => + cases posUnit + rw [hpos] at restSuccess + simp only [Except.bind, + withLocalDecl_apply] at restSuccess + have hpmSuccess : + (if !false then + checkPositivity stats domain ctor argIdx + else pure ()) context = .ok () := by + simpa using hpos + exact ⟨ConstructorPositivityModeTrace.buildExecution_ok_of_run + hpmSuccess, ih restSuccess⟩ + | true => + simp only [Bool.not_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure, + withLocalDecl_apply] at restSuccess + have hpmSuccess : + (if !true then + checkPositivity stats domain ctor argIdx + else pure ()) context = .ok () := by + simp [ReaderT.pure, Pure.pure, Except.pure] + exact ⟨ConstructorPositivityModeTrace.buildExecution_ok_of_run + hpmSuccess, ih restSuccess⟩ + split + next hstruct => + rw [hstruct] at success + simp only [if_true, ReaderT.pure, Pure.pure, + ReaderT.bind, Bind.bind, Except.bind, Except.pure] at success + obtain ⟨⟨positivity, hpm⟩, tail, htail⟩ := finish success + rw [hpm, htail] + exact ⟨_, rfl⟩ + next hstruct => + rw [hstruct] at success + simp only [Bool.false_eq_true, if_false] at success + split + next hfallback => + rw [hfallback] at success + change Except.error _ = Except.ok () at success + contradiction + next hfallback => + rw [hfallback] at success + simp only [Bool.true_eq_false, Bool.not_true, if_false, + ReaderT.pure, Pure.pure, ReaderT.bind, Bind.bind, + Except.bind, Except.pure] at success + obtain ⟨⟨positivity, hpm⟩, tail, htail⟩ := finish success + rw [hpm, htail] + exact ⟨_, rfl⟩ + all_goals + unfold checkConstructorType.loop at success + simp only at success + unfold buildExecution + simp only [Expr.isForall] + split + next hvalid => + rw [hvalid] at success + change Except.error _ = Except.ok () at success + contradiction + next hvalid => exact ⟨_, rfl⟩ + +/-- Erasing the inner trace also replays the public one-constructor checker, +including its exact context-fuel read. -/ +theorem check_run + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source 0 context.fuel.inductiveFuel) : + checkConstructorType stats isUnsafe familyIdx ctor source context = .ok () := by + unfold checkConstructorType + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using trace.run + +/-- Any exact inner constructor-telescope failure excludes a trace at that +same parameter/field/terminal position and retains the original error value. -/ +theorem not_nonempty_of_error + (failure : + checkConstructorType.loop stats isUnsafe familyIdx ctor source argIdx fuel + context = .error err) : + ¬ Nonempty (ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) := by + rintro ⟨trace⟩ + have success := trace.run + rw [failure] at success + contradiction + +end ConstructorTypeValidationTrace + +/-- Source-ordered validation of a constructor list. The `seen` index makes +duplicate-name checks part of the trace and prevents reordering or omission. +Root closedness and full type checking are retained before the recursive type +trace, exactly as in `checkConstructors`. -/ +inductive ConstructorListValidationTrace + (stats : InductiveStats) (isUnsafe : Bool) + (familyIdx : Nat) (context : Context) : + NameSet → List Constructor → Type where + | nil (seen : NameSet) : + ConstructorListValidationTrace stats isUnsafe familyIdx context seen [] + | cons + (seen : NameSet) (head : Constructor) (tail : List Constructor) + (fresh : seen.contains head.name = false) + (closed : context.env.checkNoMVarNoFVar head.name head.type = .ok ()) + (rootCheck : CandidateCheckTypeObservation + context.withEmptyLocalContext head.type) + (typeTrace : ConstructorTypeValidationTrace + stats isUnsafe familyIdx head.name context head.type 0 + context.fuel.inductiveFuel) + (tailTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context (seen.insert head.name) tail) : + ConstructorListValidationTrace stats isUnsafe familyIdx context + seen (head :: tail) + +namespace ConstructorListValidationTrace + +/-- Constructor-ordered positivity observations for one family. -/ +def targets : + ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors → + List (List (Option ConstructorPositivityTrace.Target)) + | .nil _ => [] + | .cons _ _ _ _ _ _ typeTrace tailTrace => + typeTrace.targets :: tailTrace.targets + +/-- Execute the source-ordered constructor fold while retaining its exact +dependent validation trace. Every stored equation is obtained from the same +checker call made by `checkConstructorFold`; no semantic premise participates +in acceptance. -/ +def buildExecution (stats : InductiveStats) (isUnsafe : Bool) + (familyIdx : Nat) (context : Context) : + (seen : NameSet) → (constructors : List Constructor) → + Except Exception + (ConstructorListValidationTrace stats isUnsafe familyIdx context + seen constructors) + | seen, [] => .ok (.nil seen) + | seen, head :: tail => + match hfresh : seen.contains head.name with + | true => .error <| .other s!"duplicate constructor name '{head.name}'" + | false => + match hclosed : context.env.checkNoMVarNoFVar + head.name head.type with + | .error error => .error error + | .ok () => + match hroot : TypeChecker.M.run context.env context.safety {} + context.lparams context.fuel + (TypeChecker.checkType head.type) with + | .error error => .error error + | .ok inferred => + let rootCheck : CandidateCheckTypeObservation + context.withEmptyLocalContext head.type := + ⟨inferred, by + simpa only [CandidateCheckTypeStep.Valid, + Context.withEmptyLocalContext] using hroot⟩ + match ConstructorTypeValidationTrace.buildExecution stats + isUnsafe familyIdx head.name context head.type 0 + context.fuel.inductiveFuel with + | .error error => .error error + | .ok typeTrace => + match buildExecution stats isUnsafe familyIdx context + (seen.insert head.name) tail with + | .error error => .error error + | .ok tailTrace => .ok (.cons seen head tail hfresh + hclosed rootCheck typeTrace tailTrace) + +end ConstructorListValidationTrace + +/-- A transparent presentation of the constructor portion of the executable +validator, discarding only the final duplicate-name accumulator. -/ +def checkConstructorList + (stats : InductiveStats) (isUnsafe : Bool) (familyIdx : Nat) + (context : Context) (seen : NameSet) (ctors : List Constructor) : + Except Exception Unit := do + _ ← checkConstructorFold context.env stats isUnsafe familyIdx seen ctors context + pure () + +/-- For one family, the named list recursion is exactly the array/list shell +of the real constructor validator. -/ +theorem checkConstructors_singleton_eq_checkConstructorList + (indType : InductiveType) (stats : InductiveStats) + (isUnsafe : Bool) (context : Context) : + checkConstructors #[indType] stats isUnsafe context = + checkConstructorList stats isUnsafe 0 context {} indType.ctors := by + unfold checkConstructors + simp only [ReaderT.bind, Bind.bind] + rw [liftTypeChecker_apply] + have hget : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel TypeChecker.getEnv = + .ok context.env := by rfl + rw [hget] + simp only [Except.bind] + simp only [checkConstructorsLoop] + unfold checkConstructorList + simp only [ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + +namespace ConstructorListValidationTrace + +def finalSeen : NameSet → List Constructor → NameSet + | seen, [] => seen + | seen, head :: tail => finalSeen (seen.insert head.name) tail + +/-- Exact inversion for a nonempty source list. In particular the recursive +trace is indexed by the literal source tail and the accumulator obtained from +the literal source head, so omission, insertion, duplication, or reordering +cannot be hidden behind an unindexed traversal. -/ +theorem nonempty_cons_iff_exact_source : + Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context seen (head :: tail)) ↔ + seen.contains head.name = false ∧ + context.env.checkNoMVarNoFVar head.name head.type = .ok () ∧ + Nonempty (CandidateCheckTypeObservation + context.withEmptyLocalContext head.type) ∧ + Nonempty (ConstructorTypeValidationTrace stats isUnsafe familyIdx + head.name context head.type 0 context.fuel.inductiveFuel) ∧ + Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context (seen.insert head.name) tail) := by + constructor + · rintro ⟨trace⟩ + cases trace with + | cons _ _ _ fresh closed rootCheck typeTrace tailTrace => + exact ⟨fresh, closed, ⟨rootCheck⟩, ⟨typeTrace⟩, ⟨tailTrace⟩⟩ + · rintro ⟨fresh, closed, ⟨rootCheck⟩, ⟨typeTrace⟩, ⟨tailTrace⟩⟩ + exact ⟨.cons seen head tail fresh closed rootCheck typeTrace tailTrace⟩ + +/-- A duplicate at the current source position fails before all later +constructor phases, exactly as in the executable fold. -/ +theorem not_nonempty_of_duplicate + (duplicate : seen.contains head.name = true) : + ¬ Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context seen (head :: tail)) := by + intro trace + have fresh := (nonempty_cons_iff_exact_source.mp trace).1 + simp_all + +/-- A closedness error at the current source position excludes the trace before +the root type check or constructor telescope is entered. -/ +theorem not_nonempty_of_closedness_error + (failure : context.env.checkNoMVarNoFVar head.name head.type = .error err) : + ¬ Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context seen (head :: tail)) := by + intro trace + have closed := (nonempty_cons_iff_exact_source.mp trace).2.1 + rw [failure] at closed + contradiction + +/-- A closed-root `checkType` error excludes the trace at that exact source +constructor, before parameter and field validation. -/ +theorem not_nonempty_of_root_error + (failure : TypeChecker.M.run context.env context.safety {} + context.lparams context.fuel (TypeChecker.checkType head.type) = + .error err) : + ¬ Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context seen (head :: tail)) := by + intro trace + obtain ⟨rootCheck⟩ := + (nonempty_cons_iff_exact_source.mp trace).2.2.1 + have success := rootCheck.valid + change TypeChecker.M.run context.withEmptyLocalContext.env + context.withEmptyLocalContext.safety + context.withEmptyLocalContext.lctx + context.withEmptyLocalContext.lparams + context.withEmptyLocalContext.fuel + (TypeChecker.checkType head.type) = .ok rootCheck.inferred at success + simp only [Context.withEmptyLocalContext] at success + rw [failure] at success + contradiction + +/-- An inner parameter, field, universe, positivity, recursive-target, or +terminal-family error excludes the trace at the current constructor. -/ +theorem not_nonempty_of_type_error + (failure : checkConstructorType stats isUnsafe familyIdx + head.name head.type context = .error err) : + ¬ Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context seen (head :: tail)) := by + intro trace + obtain ⟨typeTrace⟩ := + (nonempty_cons_iff_exact_source.mp trace).2.2.2.1 + have success := typeTrace.check_run + rw [failure] at success + contradiction + +/-- Erasing an ordered trace replays the exact stateful constructor fold. -/ +theorem fold_run + (trace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen ctors) : + checkConstructorFold context.env stats isUnsafe familyIdx seen ctors context = + .ok (finalSeen seen ctors) := by + induction trace with + | nil => rfl + | cons seen head tail fresh closed rootCheck typeTrace tailTrace ih => + have hroot := rootCheck.valid + change TypeChecker.M.run context.withEmptyLocalContext.env + context.withEmptyLocalContext.safety + context.withEmptyLocalContext.lctx + context.withEmptyLocalContext.lparams + context.withEmptyLocalContext.fuel + (TypeChecker.checkType head.type) = + .ok rootCheck.inferred at hroot + simp only [Context.withEmptyLocalContext] at hroot + unfold checkConstructorFold + simp only + rw [fresh] + simp only [Bool.false_eq_true, if_false, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + rw [closed] + simp only [ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure, liftExcept_apply] + rw [withEmptyLocalContext_apply] + rw [liftTypeChecker_apply] + rw [hroot] + simp only [Except.bind, readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.pure, Pure.pure, Except.pure] + rw [typeTrace.check_run] + change checkConstructorFold context.env stats isUnsafe familyIdx + (seen.insert head.name) tail context = + .ok (finalSeen (seen.insert head.name) tail) + exact ih + +/-- Any successful stateful constructor fold decomposes into the complete +source-ordered list trace; the final accumulator value itself is irrelevant. -/ +theorem exists_of_fold_run + (success : checkConstructorFold context.env stats isUnsafe familyIdx + seen ctors context = .ok result) : + Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context seen ctors) := by + induction ctors generalizing seen result with + | nil => exact ⟨.nil seen⟩ + | cons head tail ih => + unfold checkConstructorFold at success + simp only at success + cases hfresh : seen.contains head.name with + | true => + rw [hfresh] at success + change Except.error _ = Except.ok result at success + contradiction + | false => + rw [hfresh] at success + simp only [Bool.false_eq_true, if_false, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] at success + cases hclosed : context.env.checkNoMVarNoFVar + head.name head.type with + | error err => simp_all [liftExcept_apply, Except.bind] + | ok closedResult => + cases closedResult + rw [hclosed] at success + simp only [liftExcept_apply, Except.bind] at success + rw [withEmptyLocalContext_apply, liftTypeChecker_apply] at success + cases hroot : TypeChecker.M.run context.env context.safety {} + context.lparams context.fuel + (TypeChecker.checkType head.type) with + | error err => simp_all [Except.bind] + | ok inferred => + rw [hroot] at success + simp only [Except.bind] at success + cases htype : checkConstructorType stats isUnsafe familyIdx + head.name head.type context with + | error err => simp_all [Except.bind] + | ok typeResult => + cases typeResult + rw [htype] at success + simp only [Except.bind, ReaderT.pure, Pure.pure, + Except.pure] at success + have htypeLoop : + checkConstructorType.loop stats isUnsafe familyIdx + head.name head.type 0 context.fuel.inductiveFuel + context = .ok () := by + unfold checkConstructorType at htype + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using htype + obtain ⟨typeTrace⟩ := + ConstructorTypeValidationTrace.exists_of_run htypeLoop + have rootCheck : CandidateCheckTypeObservation + context.withEmptyLocalContext head.type := + ⟨inferred, by + simpa only [CandidateCheckTypeStep.Valid, + Context.withEmptyLocalContext] using hroot⟩ + change checkConstructorFold context.env stats isUnsafe + familyIdx (seen.insert head.name) tail context = + .ok result at success + obtain ⟨tailTrace⟩ := ih success + exact ⟨.cons seen head tail hfresh hclosed rootCheck + typeTrace tailTrace⟩ + +/-- The transparent list decomposition succeeds on every constructor list +accepted by the executable stateful fold. -/ +theorem buildExecution_ok_of_fold_run + (success : checkConstructorFold context.env stats isUnsafe familyIdx + seen ctors context = .ok result) : + ∃ trace, buildExecution stats isUnsafe familyIdx context seen ctors = + .ok trace := by + induction ctors generalizing seen result with + | nil => exact ⟨_, rfl⟩ + | cons head tail ih => + unfold checkConstructorFold at success + simp only at success + unfold buildExecution + split + next hfresh => + rw [hfresh] at success + change Except.error _ = Except.ok result at success + contradiction + next hfresh => + rw [hfresh] at success + simp only [Bool.false_eq_true, if_false, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] at success + split + next error heq => + rw [heq] at success + simp [liftExcept_apply, Except.bind] at success + next heq => + rw [heq] at success + simp only [liftExcept_apply, Except.bind] at success + rw [withEmptyLocalContext_apply, liftTypeChecker_apply] at success + split + next error heq2 => + rw [heq2] at success + simp [Except.bind] at success + next inferred heq2 => + rw [heq2] at success + simp only [Except.bind] at success + cases htype : checkConstructorType stats isUnsafe familyIdx + head.name head.type context with + | error err => simp_all [Except.bind] + | ok typeResult => + cases typeResult + rw [htype] at success + simp only [Except.bind, ReaderT.pure, Pure.pure, + Except.pure] at success + have htypeLoop : + checkConstructorType.loop stats isUnsafe familyIdx + head.name head.type 0 context.fuel.inductiveFuel + context = .ok () := by + unfold checkConstructorType at htype + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using htype + obtain ⟨typeTrace, hT⟩ := + ConstructorTypeValidationTrace.buildExecution_ok_of_run + htypeLoop + rw [hT] + change checkConstructorFold context.env stats isUnsafe + familyIdx (seen.insert head.name) tail context = + .ok result at success + obtain ⟨tailTrace, htl⟩ := ih success + rw [htl] + exact ⟨_, rfl⟩ + +/-- The stateful list fold's exact error value excludes a complete trace for +that same source list and incoming duplicate-name accumulator. -/ +theorem not_nonempty_of_fold_error + (failure : checkConstructorFold context.env stats isUnsafe familyIdx + seen ctors context = .error err) : + ¬ Nonempty (ConstructorListValidationTrace stats isUnsafe familyIdx + context seen ctors) := by + rintro ⟨trace⟩ + have success := trace.fold_run + rw [failure] at success + contradiction + +/-- Erasing an ordered list trace replays the transparent list validator. -/ +theorem run + (trace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen ctors) : + checkConstructorList stats isUnsafe familyIdx context seen ctors = .ok () := by + unfold checkConstructorList + rw [trace.fold_run] + rfl + +end ConstructorListValidationTrace + +/-! ## Arbitrary mutual-block validation owners -/ + +/-- The exact result selected when the ordinary family validator reaches its +continuation. Retaining the reader context matters: later constructor +validation uses the shared parameters and local declarations installed by +that very run. -/ +structure FamilyValidationBlockResult where + stats : InductiveStats + validationContext : Context + +/-- Observe the successful continuation of `checkInductiveTypes` without +changing any validation branch or error. -/ +def observeFamilyValidationBlock (nparams : Nat) + (indTypes : List InductiveType) (context : Context) : + Except Exception FamilyValidationBlockResult := + checkInductiveTypes nparams indTypes.toArray + (fun stats => fun validationContext => + .ok ⟨stats, validationContext⟩) context + +/-- Complete retained family-validation run for an arbitrary source-ordered +block. + +`run` is the real validator execution, so every later family has already +passed the kernel's definitional parameter comparison and result-level +equivalence phase. The remaining equations expose the terminal invariants +which Lean asserts before invoking the continuation. -/ +structure FamilyValidationBlockRun (nparams : Nat) + (indTypes : List InductiveType) (context : Context) where + result : FamilyValidationBlockResult + run : observeFamilyValidationBlock nparams indTypes context = .ok result + params_size : result.stats.params.size = nparams + nindices_size : result.stats.nindices.size = indTypes.length + indConsts_size : result.stats.indConsts.size = indTypes.length + +namespace FamilyValidationBlockRun + +/-- Execute and retain the ordinary family validator. The explicit terminal +checks mirror its internal assertions and make malformed instrumentation fail +instead of yielding a weaker certificate. -/ +def buildExecution (nparams : Nat) (indTypes : List InductiveType) + (context : Context) : + Except Exception (FamilyValidationBlockRun nparams indTypes context) := + match hrun : observeFamilyValidationBlock nparams indTypes context with + | .error error => .error error + | .ok result => + if hparams : result.stats.params.size = nparams then + if hnindices : result.stats.nindices.size = indTypes.length then + if hconsts : result.stats.indConsts.size = indTypes.length then + .ok { + result + run := hrun + params_size := hparams + nindices_size := hnindices + indConsts_size := hconsts } + else .error (.other "family-validation constant-count invariant failed") + else .error (.other "family-validation index-count invariant failed") + else .error (.other "family-validation parameter-count invariant failed") + +/-- Shared parameters selected by the first family and definitionally checked +against every later family. -/ +def parameters (run : FamilyValidationBlockRun nparams indTypes context) : + Array Expr := + run.result.stats.params + +/-- Common result universe selected by the first family and equivalence- +checked against every later family. -/ +def resultLevel (run : FamilyValidationBlockRun nparams indTypes context) : + Level := + run.result.stats.resultLevel + +end FamilyValidationBlockRun + +/-- Source-indexed constructor traces for every family in a block. The +natural index advances with the source list, so a trace for one family cannot +be reused at another family ordinal. -/ +inductive ConstructorBlockValidationTraces + (stats : InductiveStats) (isUnsafe : Bool) (context : Context) : + Nat → List InductiveType → Type where + | nil {familyIdx : Nat} : + ConstructorBlockValidationTraces stats isUnsafe context familyIdx [] + | cons {familyIdx : Nat} {type : InductiveType} + {types : List InductiveType} + (head : ConstructorListValidationTrace stats isUnsafe familyIdx + context {} type.ctors) + (tail : ConstructorBlockValidationTraces stats isUnsafe context + (familyIdx + 1) types) : + ConstructorBlockValidationTraces stats isUnsafe context familyIdx + (type :: types) + +namespace ConstructorBlockValidationTraces + +/-- Family-, constructor-, and field-ordered recursive-target matrix selected +by the executable arbitrary-block validator. -/ +def targets : + ConstructorBlockValidationTraces stats isUnsafe context familyIdx types → + List (List (List (Option ConstructorPositivityTrace.Target))) + | .nil => [] + | .cons head tail => head.targets :: tail.targets + +/-- Execute each source-indexed list trace in the one shared post-family +context. -/ +def buildExecution (stats : InductiveStats) (isUnsafe : Bool) + (context : Context) : + (familyIdx : Nat) → (types : List InductiveType) → + Except Exception + (ConstructorBlockValidationTraces stats isUnsafe context + familyIdx types) + | _, [] => .ok .nil + | familyIdx, type :: types => + match ConstructorListValidationTrace.buildExecution stats isUnsafe + familyIdx context {} type.ctors with + | .error error => .error error + | .ok head => + match buildExecution stats isUnsafe context (familyIdx + 1) types with + | .error error => .error error + | .ok tail => .ok (.cons head tail) + +end ConstructorBlockValidationTraces + +/-- Complete operational constructor-validation owner for an arbitrary +mutual block. `run` is the actual block call; `traces` retains every +family/constructor/field branch, including cross-family target ordinals and +recursive-Pi paths. -/ +structure ConstructorBlockValidationRun + (indTypes : List InductiveType) (stats : InductiveStats) + (isUnsafe : Bool) (context : Context) where + traces : ConstructorBlockValidationTraces stats isUnsafe context 0 indTypes + run : checkConstructors indTypes.toArray stats isUnsafe context = .ok () + +namespace ConstructorBlockValidationRun + +/-- Execute the real block validator and retain the exact dependent trace +hierarchy for that same source list. -/ +def buildExecution (indTypes : List InductiveType) + (stats : InductiveStats) (isUnsafe : Bool) (context : Context) : + Except Exception + (ConstructorBlockValidationRun indTypes stats isUnsafe context) := + match hrun : checkConstructors indTypes.toArray stats isUnsafe context with + | .error error => .error error + | .ok () => + match ConstructorBlockValidationTraces.buildExecution stats isUnsafe + context 0 indTypes with + | .error error => .error error + | .ok traces => .ok ⟨traces, hrun⟩ + +end ConstructorBlockValidationRun + +/-- The complete retained operational constructor-validation run for one +singleton family. -/ +structure ConstructorValidationRun + (indType : InductiveType) (stats : InductiveStats) + (isUnsafe : Bool) (context : Context) where + trace : ConstructorListValidationTrace stats isUnsafe 0 context {} + indType.ctors + +namespace ConstructorValidationRun + +/-- Transparent decomposition of the ordinary singleton constructor +validator. Successful output is executable data rather than a +`Classical.choice`, which lets subsequent D2/D3 audits compute over the exact +retained branch structure. -/ +def buildExecution (indType : InductiveType) (stats : InductiveStats) + (isUnsafe : Bool) (context : Context) : + Except Exception + (ConstructorValidationRun indType stats isUnsafe context) := + match ConstructorListValidationTrace.buildExecution stats isUnsafe 0 + context {} indType.ctors with + | .error error => .error error + | .ok trace => .ok ⟨trace⟩ + +/-- The transparent singleton decomposition succeeds on every source family +accepted by the real constructor validator. -/ +theorem buildExecution_ok_of_run + (success : checkConstructors #[indType] stats isUnsafe context = .ok ()) : + ∃ validation, buildExecution indType stats isUnsafe context = + .ok validation := by + rw [checkConstructors_singleton_eq_checkConstructorList] at success + unfold checkConstructorList at success + cases hfold : checkConstructorFold context.env stats isUnsafe 0 {} + indType.ctors context with + | error err => simp_all [Functor.map, Except.map] + | ok result => + obtain ⟨trace, htrace⟩ := + ConstructorListValidationTrace.buildExecution_ok_of_fold_run hfold + unfold buildExecution + rw [htrace] + exact ⟨_, rfl⟩ + +/-- Recomposition: retained operational evidence replays the real singleton +`checkConstructors` execution exactly. -/ +theorem run + (validation : ConstructorValidationRun indType stats isUnsafe context) : + checkConstructors #[indType] stats isUnsafe context = .ok () := by + rw [checkConstructors_singleton_eq_checkConstructorList] + exact validation.trace.run + +/-- Decomposition: every successful real singleton `checkConstructors` run +has complete retained operational evidence. -/ +theorem nonempty_of_run + (success : checkConstructors #[indType] stats isUnsafe context = .ok ()) : + Nonempty (ConstructorValidationRun indType stats isUnsafe context) := by + rw [checkConstructors_singleton_eq_checkConstructorList] at success + unfold checkConstructorList at success + cases hfold : checkConstructorFold context.env stats isUnsafe 0 {} + indType.ctors context with + | error err => + simp_all [Functor.map, Except.map] + | ok result => + obtain ⟨trace⟩ := + ConstructorListValidationTrace.exists_of_fold_run hfold + exact ⟨⟨trace⟩⟩ + +/-- Choose the operational shape supplied by a successful run by replaying +the transparent decomposition. The success premise only discharges the +impossible error branch, so the retained evidence is computed by +`buildExecution` rather than selected through `Classical.choice`. -/ +def of_run + (success : checkConstructors #[indType] stats isUnsafe context = .ok ()) : + ConstructorValidationRun indType stats isUnsafe context := + match h : buildExecution indType stats isUnsafe context with + | .ok validation => validation + | .error _ => absurd (buildExecution_ok_of_run success) (by simp [h]) + +/-- Exact decomposition/recomposition contract for singleton constructor +validation. -/ +theorem nonempty_iff_checkConstructors_ok : + Nonempty (ConstructorValidationRun indType stats isUnsafe context) ↔ + checkConstructors #[indType] stats isUnsafe context = .ok () := by + constructor + · rintro ⟨validation⟩ + exact validation.run + · exact nonempty_of_run + +/-- Any phase-specific executable error excludes a successful retained run. -/ +theorem not_nonempty_of_error + (failure : checkConstructors #[indType] stats isUnsafe context = .error err) : + ¬ Nonempty (ConstructorValidationRun indType stats isUnsafe context) := by + intro validation + have success := nonempty_iff_checkConstructors_ok.mp validation + rw [failure] at success + contradiction + +end ConstructorValidationRun + +#guard_named_axioms Ix.Theory.Named.AddInductive.FamilyValidationBlockRun.buildExecution [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorBlockValidationRun.buildExecution [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorListValidationTrace.nonempty_cons_iff_exact_source [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorValidationRun.run [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorValidationRun.nonempty_of_run [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorValidationRun.of_run [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorValidationRun.nonempty_iff_checkConstructors_ok [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorValidationRun.not_nonempty_of_error [propext, Classical.choice, Quot.sound] + +end AddInductive +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Reference/Instantiate.lean b/Ix/Theory/Named/Reference/Instantiate.lean new file mode 100644 index 000000000..6319abab3 --- /dev/null +++ b/Ix/Theory/Named/Reference/Instantiate.lean @@ -0,0 +1,39 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Expr +import Lean.LocalContext +import Lean.Util.InstantiateLevelParams + +namespace Lean +namespace Expr + +/-- Beta-reduces an application `(fun x₁ ... xₙ => b) a₁ ... aₙ aₙ₊₁ ... aₘ` in the two cases where +no substitution is needed: to `b aₙ₊₁ ... aₘ` when `b` has no loose bound variables, and to +`aᵢ aₙ₊₁ ... aₘ` when `b` is the bound variable `xᵢ`. In any other case `e` is returned unchanged — +this is what makes it cheap. -/ +def cheapBetaReduce (e : Expr) : Expr := Id.run do + if !e.isApp then return e + let fn := e.getAppFn + if !fn.isLambda then return e + let args := e.getAppArgs + let rec cont i fn := + if !fn.hasLooseBVars then + mkAppRange fn i args.size args + else if let .bvar n := fn then + assert! n < i + mkAppRange args[i - n - 1]! i args.size args + else + e + let rec loop i fn := + if i < args.size then + match fn with + | .lam _ _ body .. => loop (i + 1) body + | _ => cont i fn + else cont i fn + return loop 0 fn + +end Expr diff --git a/Ix/Theory/Named/Reference/Level.lean b/Ix/Theory/Named/Reference/Level.lean new file mode 100644 index 000000000..b774b0555 --- /dev/null +++ b/Ix/Theory/Named/Reference/Level.lean @@ -0,0 +1,412 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean +import Ix.Theory.Named.Reference.List + +namespace Lean.Level + +def forEach [Monad m] (l : Level) (f : Level → m Bool) : m Unit := do + if !(← f l) then return + match l with + | .succ l => l.forEach f + | .max l₁ l₂ | .imax l₁ l₂ => l₁.forEach f; l₂.forEach f + | .zero | .param .. | .mvar .. => pure () + +/-- Returns `some n` if level parameter `n` appears in `l` and `n ∉ ps`. -/ +def getUndefParam (l : Level) (ps : List Name) : Option Name := Id.run do + (·.2) <$> StateT.run (s := none) do + l.forEach fun l => do + if !l.hasParam || (← get).isSome then + return false + if let .param n := l then + if n ∉ ps then + set (some n) + return true + +/-! +## Level normalization + +Based on Yoan Géran, "A Canonical Form for Universe Levels in Impredicative Type Theory" +. +-/ + +namespace Normalize + +local instance namedOrdName : Ord Name := ⟨Name.cmp⟩ + +/-- represents v+n -/ +structure VarNode where + var : Name + offset : Nat + deriving BEq, Ord, Repr + +/-- A key-value pair `vs => { const, var }` in NormLevel represents +the max of `C(vs, const)` and `V(vs, v, n)` for each `v+n ∈ var`, using the `C` and `V` sublevel +functions from . -/ +structure Node where + const : Nat := 0 + var : List VarNode := [] + deriving Repr, Inhabited + +instance : BEq Node where + beq n₁ n₂ := n₁.const == n₂.const && n₁.var == n₂.var +instance : Ord Node where + compare n₁ n₂ := compare n₁.const n₂.const |>.then <| compare n₁.var n₂.var + +def Node.isEmpty (n : Node) : Bool := n.const == 0 && n.var.isEmpty + +def subset (cmp : α → α → Ordering) : List α → List α → Bool + | [], _ => true + | _, [] => false + | x :: xs, y :: ys => + match cmp x y with + | .lt => false + | .eq => subset cmp xs ys + | .gt => subset cmp (x :: xs) ys + +def orderedInsert (cmp : α → α → Ordering) (a : α) : List α → Option (List α) + | [] => some [a] + | b :: l => + match cmp a b with + | .lt => some (a :: b :: l) + | .eq => none + | .gt => (orderedInsert cmp a l).map (b :: ·) + +@[reducible] def NormLevel := Std.TreeMap (List Name) Node compare + deriving Repr + +instance : BEq NormLevel where + beq l₁ l₂ := + (l₁.all fun p n => l₂.get? p == some n) && + (l₂.all fun p n => l₁.get? p == some n) + +def VarNode.addVar (v : Name) (k : Nat) : List VarNode → List VarNode + | [] => [⟨v, k⟩] + | v' :: l => + match Name.cmp v v'.var with + | .lt => ⟨v, k⟩ :: v' :: l + | .eq => ⟨v, v'.offset.max k⟩ :: l + | .gt => v' :: addVar v k l + +def NormLevel.addVar (v : Name) (k : Nat) (path' : List Name) (s : NormLevel) : NormLevel := + s.modify path' fun n => { n with var := VarNode.addVar v k n.var } + +def NormLevel.addNode (v : Name) (k : Nat) (path' : List Name) (s : NormLevel) : NormLevel := + s.alter path' fun + | none => some { var := [⟨v, k⟩] } + | some n => some { n with var := VarNode.addVar v k n.var } + +def NormLevel.addConst (k : Nat) (path : List Name) (acc : NormLevel) : NormLevel := + if k = 0 || k = 1 && !path.isEmpty then acc else + acc.alter path fun + | none => some { const := k } + | some n => some { n with const := k.max n.const } + +def normalizeAux (l : Level) (path : List Name) (k : Nat) (acc : NormLevel) : NormLevel := + match l with + | .zero | .imax _ .zero => acc.addConst k path + | .succ u => normalizeAux u path (k+1) acc + | .max u v => normalizeAux u path k acc |> normalizeAux v path k + | .imax u (.succ v) => normalizeAux u path k acc |> normalizeAux v path (k+1) + | .imax u (.max v w) => normalizeAux (.imax u v) path k acc |> normalizeAux (.imax u w) path k + | .imax u (.imax v w) => normalizeAux (.imax u w) path k acc |> normalizeAux (.imax v w) path k + | .imax u (.param v) => + match orderedInsert Name.cmp v path with + | some path' => acc.addConst k path |>.addNode v k path' |> normalizeAux u path' k + | none => + let acc := if k = 0 then acc else acc.addVar v k path + normalizeAux u path k acc + | .mvar _ | .imax _ (.mvar _) => acc -- unreachable + | .param v => + match orderedInsert Name.cmp v path with + | some path' => acc.addConst k path |>.addNode v k path' + | none => if k = 0 then acc else acc.addVar v k path + +def subsumeVars : List VarNode → List VarNode → List VarNode + | [], _ => [] + | xs, [] => xs + | x :: xs, y :: ys => + match Name.cmp x.var y.var with + | .lt => x :: subsumeVars xs (y :: ys) + | .eq => if x.offset ≤ y.offset then subsumeVars xs ys else x :: subsumeVars xs ys + | .gt => subsumeVars (x :: xs) ys + +/-- Remove from `n₁` the sublevels dominated by `n₂`, whose condition set is a subset of +`n₁`'s: `C(c)` is dominated by `C(c')` when `c ≤ c'` and by `V(x+k)` when `c ≤ k + 1`, and +`V(x+k)` is dominated by `V(x+k')` when `k ≤ k'`. + +`same` says the two sit at the *same* condition set, where a variable may still discharge the +constant but the variables must not discharge themselves. -/ +def Node.subsumeBy (same : Bool) (n₁ n₂ : Node) : Node := + let n₁ := + if n₁.const = 0 || + (same || n₁.const > n₂.const) && + (n₂.var.isEmpty || n₁.const > n₂.var.foldl (·.max ·.offset) 0 + 1) + then n₁ else { n₁ with const := 0 } + if same || n₂.var.isEmpty then n₁ else { n₁ with var := subsumeVars n₁.var n₂.var } + +/-- Remove the parts of the sublevels at `(p₁, n₁)` that are dominated by the sublevels +at `(p₂, n₂)`. -/ +def Node.subsume (p₁ : List Name) (n₁ : Node) (p₂ : List Name) (n₂ : Node) : Node := + if subset compare p₂ p₁ then n₁.subsumeBy (p₁.length == p₂.length) n₂ else n₁ + +/-- Remove the parts of the sublevels at `(p₁, n₁)` dominated by other entries of the map. -/ +def NormLevel.minimize (acc : NormLevel) (p₁ : List Name) (n₁ : Node) : Node := + acc.foldl (init := n₁) (Node.subsume p₁) + +def NormLevel.subsumption (acc : NormLevel) : NormLevel := + acc.foldl (init := acc) fun acc p₁ n₁ => + let n := acc.minimize p₁ n₁ + if n.isEmpty then acc.erase p₁ else acc.insert p₁ n + +def normalize (l : Level) : NormLevel := + Normalize.normalizeAux l [] 0 {} |>.subsumption + +/-- Sublevel comparison, following Theorem 39 of the paper: `l₁ ≤ l₂` iff every sublevel +of `l₁` is dominated by some sublevel of `l₂`, where +`C(E, L) ≤ C(F, K) ↔ F ⊆ E ∧ L ≤ K`, `C(E, L) ≤ V(F, x, K) ↔ F ⊆ E ∧ L ≤ K + 1`, +and `V(E, x, L) ≤ V(F, y, K) ↔ F ⊆ E ∧ x = y ∧ L ≤ K`. + +Each sublevel picks its own dominator, and a node bundles several of them, so it is not +enough to look for a single entry of `l₂` dominating a whole node of `l₁`: for +`imax 2 v ≤ max 2 v` the constant is dominated at `∅` and the variable at `{v}`. Instead +each entry of `l₂` discharges what it can from the sublevels of `n₁` that are still +outstanding, which is the same `subsumeBy` step minimization uses; the node is dominated +once nothing is left, and the fold stops there. -/ +def NormLevel.le (l₁ l₂ : NormLevel) : Bool := + l₁.all fun p₁ n₁ => + -- `none` means nothing is left to discharge, which stops the fold + Option.isNone <| l₂.foldlM (init := n₁) (m := Option) fun n p₂ n₂ => + if subset compare p₂ p₁ then + let n := n.subsumeBy false n₂ + if n.isEmpty then none else some n + else some n + +/-! +Reconstruction of a `Level` from a `NormLevel`. + +The paper's canonical form is a set of sublevels `C(S, k)`, `V(S, v+k)`; it does not address +which such sets are expressible as level expressions. Reifying a sublevel with conditions `S` +requires nesting it under an imax chain `imax (… imax (imax (_) v₁) …) vₙ` where +`{v₁, …, vₙ} = S`, and each edge of such a chain itself contributes the sublevel +`V(S', vᵢ, 0)` where `S'` is the set of conditions up to that point. So a chain order is +admissible only if each such edge contribution is dominated by the canonical form, i.e. +there is some `V(T, vᵢ+k)` with `T ⊆ S'` among the sublevels. Canonical forms produced by +`normalizeAux` always admit at least one such order for every key +(each key is the condition set of some `imax` chain suffix of the input, whose edges put +the required `V` entries at subsets of the key, and subsumption only moves coverage to +smaller sets). + +To make the output canonical, the choice of chain must depend only on the canonical +sublevels, not on incidental map keys (which record which `imax` chains appeared +syntactically in the input). For each key we take the lexicographically least admissible +chain, computed greedily. This is well-defined: domination of `V(S', v, 0)` is monotone +in `S'`, so extending the set of conditions added so far never invalidates other elements, +and a greedy choice never needs to be revisited (checking that the remainder stays +completable before committing to each element). -/ + +/-- Is the edge contribution `V(acc ∪ {a}, a, 0)` dominated by the normal form? +True iff some `V(T, a+k)` with `T ⊆ acc ∪ {a}` is present. -/ +def NormLevel.addable (s : NormLevel) (a : Name) (acc : List Name) : Bool := + s.any fun p n => n.var.any (·.var == a) && subset compare (p.erase a) acc + +/-- Can the elements of `rem` be added to the condition set `acc` one at a time, each +addition being `addable` at that point? Since `addable` is monotone in `acc`, adding any +addable element preserves completability, so a greedy check is complete. -/ +def NormLevel.feasible (s : NormLevel) (acc rem : List Name) : Bool := + go rem.length acc rem +where + go : Nat → List Name → List Name → Bool + | 0, _, rem => rem.isEmpty + | fuel+1, acc, rem => + match rem.find? (s.addable · acc) with + | none => rem.isEmpty + | some a => go fuel ((orderedInsert Name.cmp a acc).getD acc) (rem.erase a) + +/-- The lexicographically least admissible imax chain building the condition set `p`, +listed innermost (last-added) first: at each step, remove the least element that is +`addable` on top of the rest and whose remainder is still completable. +This depends only on the sublevels of `s`, not on its key set, so equal normal forms +reify to equal levels. (The fallback returns the remaining set in sorted order; +it is not reachable for normal forms produced by `normalizeAux`.) -/ +def NormLevel.lexChain (s : NormLevel) : Nat → List Name → List Name + | 0, p => p + | fuel+1, p => + match p.find? fun a => s.addable a (p.erase a) && s.feasible [] (p.erase a) with + | some a => a :: s.lexChain fuel (p.erase a) + | none => p + +structure Tree where + const : Nat + var : List VarNode + child : List (Name × Tree) + deriving Inhabited + +def modifyAt [Inhabited α] (f : α → α) (n : Name) : List (Name × α) → List (Name × α) + | [] => [(n, f default)] + | (x, v) :: l => + match Name.cmp n x with + | .lt => (n, f default) :: (x, v) :: l + | .eq => (x, f v) :: l + | .gt => (x, v) :: modifyAt f n l + +def Tree.modify (path : List Name) (f : Tree → Tree) (t : Tree) : Tree := + match path with + | [] => f t + | a :: p => modify p (t := t) fun t => { t with child := modifyAt f a t.child } + +def NormLevel.toTree (acc : NormLevel) : Tree := + acc.foldl (init := ⟨0, [], []⟩) fun t p n => + let path := acc.lexChain p.length p + -- the edge into this tree node already contributes `V(p, v, 0)` for the innermost + -- chain element `v`, so an explicit `v+0` entry would be redundant + let var := if let v :: _ := path then subsumeVars n.var [⟨v, 0⟩] else n.var + t.modify path fun t => { t with const := n.const, var } + +/-- If the subtree behind an edge labelled `a` holds nothing but the sublevel `V(_, a, k)`, +return `k`. + +Such an edge contributes `imax (a+k) a`, which differs from the plain `a+k` only at `a = 0`, +where the plain form gives `k` instead of `0`. So the guard may be dropped, and the child +written as just `a+k`, whenever the node's constant is at least `k` — and if the constant is +*exactly* `k`, it may then be dropped itself, since `a+k ≥ k`. Without this, `u+1` would reify +to `max 1 (imax (u+1) u)` rather than to itself, and the canonical form would be roughly twice +the size of the input on typical levels. -/ +def Tree.plainOffset? (a : Name) : Tree → Option Nat + | ⟨0, [], []⟩ => some 0 + | ⟨0, [v], []⟩ => if v.var == a then some v.offset else none + | _ => none + +def Tree.reify : Tree → Level + | { const, var, child } => + let l := child.foldr (mkChild const) none + let l := var.foldr (init := l) fun n r => + some (mkMax (addOffset (.param n.var) n.offset) r) + match l with + | none => ofNat const + | some l => + if const == 0 || child.any fun c => plainOffset? c.1 c.2 == some const then l + else max (ofNat const) l +where + mkMax (l : Level) : Option Level → Level + | none => l + | some u => max l u + mkChild (const : Nat) + | (n, t), r => + match plainOffset? n t with + | some k => + if k ≤ const then mkMax (addOffset (.param n) k) r + else mkMax (imax (reify t) (.param n)) r + | none => mkMax (imax (reify t) (.param n)) r + +/-! +### Fast path for levels without an essential `imax` + +Levels arising in practice are almost always built from `zero`, `succ`, `max` and `param` +alone: `mkLevelIMax'` already discharges `imax _ 0`, `imax _ (_+1)`, `imax a a` and +`imax ≤1 _` where the kernel builds levels, and in a census of the 522k level comparisons +performed while checking Lean+Std+Batteries, 99.8% of the levels reaching them were +`imax`-free. + +Such a level's canonical form is flat: its sublevels are `C(∅, K)` and one `V({x}, x, kₓ)` +per parameter, nothing is ever subsumed (a condition set is `∅` or a singleton, and the `C` +node carries no variables), and each `imax` chain is a single edge. So the whole `NormLevel` +can be replaced by a sorted merge, and the tree read off directly. Note that every parameter +occurrence contributes its offset to the constant as well, so `K` dominates every `kₓ` and +the reified children never need their `imax` guard. +-/ + +/-- The map a run of flat data stands for: the constant at the root (absent when zero) and +`V({x}, x, k)` at each singleton key. Note this inserts the keys in sorted order, whereas +`normalizeAux` inserts them in traversal order, so the two build the same entries in +differently balanced trees — everything downstream compares maps entry by entry. -/ +def toNormLevel (c : Nat) (vs : List VarNode) : NormLevel := + vs.foldl (fun s v => s.insert [v.var] ⟨0, [v]⟩) + (if c = 0 then {} else (∅ : NormLevel).insert [] ⟨c, []⟩) + +/-- Collect the largest constant and the largest offset of each parameter, throwing the +`NormLevel` built from what has been collected so far on reaching an `imax`, so that +`normalizeAux` picks up from there rather than retraversing. -/ +def flatAux : Level → Nat → Nat × List VarNode → Except NormLevel (Nat × List VarNode) + | .zero, k, (c, vs) => .ok (Nat.max c k, vs) + | .succ l, k, acc => flatAux l (k+1) acc + | .max a b, k, acc => + match flatAux a k acc with + | .ok acc => flatAux b k acc + | .error s => .error (normalizeAux b [] k s) + | .param x, k, (c, vs) => .ok (Nat.max c k, VarNode.addVar x k vs) + | .mvar _, _, acc => .ok acc + | l@(.imax ..), k, (c, vs) => .error (normalizeAux l [] k (toNormLevel c vs)) + +/-- The tree `toTree` builds for a flat level: the constant at the root, and one child per +parameter holding `V({x}, x, kₓ)` — dropped when `kₓ = 0`, as the edge already provides it. -/ +def flatTree (c : Nat) (vs : List VarNode) : Tree := + ⟨c, [], vs.map fun v => (v.var, ⟨0, if v.offset == 0 then [] else [v], []⟩)⟩ + +end Normalize + +def normalize' (l : Level) : Level := + match Normalize.flatAux l 0 (0, []) with + | .ok (c, vs) => (Normalize.flatTree c vs).reify + | .error s => s.subsumption.toTree.reify + +/-- A transparent structural equality test for levels. Unlike `Level.beq`, +this test has no opaque runtime contract, so its successful branch can be used +directly by the verified checker. -/ +def isStructEq : Level → Level → Bool + | .zero, .zero => true + | .succ u, .succ v => isStructEq u v + | .max u₁ u₂, .max v₁ v₂ + | .imax u₁ u₂, .imax v₁ v₂ => isStructEq u₁ v₁ && isStructEq u₂ v₂ + | .param u, .param v => u == v + | .mvar ⟨u⟩, .mvar ⟨v⟩ => u == v + | _, _ => false + +/-- Core's `isEquiv` is sound but incomplete, so it can be used as a fast path: when it +accepts, the levels really are equivalent, and when it rejects we fall back to the complete +check. Over the 261k level comparisons performed while checking Lean+Std+Batteries this +filter decided every single real equivalence, leaving only the genuinely inequivalent 0.1% +to the fallback — and it is roughly 20× cheaper than normalizing. -/ +def isEquiv' (u v : Level) : Bool := + isEquiv u v || Normalize.normalize u == Normalize.normalize v + +def isEquivList : List Level → List Level → Bool := List.all2 isEquiv' + +/-- Core's `geq` as a fast path, on the same grounds as `isEquiv'`. -/ +def geq' (u v : Level) : Bool := + geq u v || (Normalize.normalize v).le (Normalize.normalize u) + +-- local elab "normalize " l:level : command => do +-- Elab.Command.runTermElabM fun _ => do +-- logInfo m!"{normalize' (← Elab.Term.elabLevel l)}" +-- -- logInfo m!"{repr <| Normalize.normalize (← Elab.Term.elabLevel l) }" + +-- local elab "normalize " l:level " ≤ " l':level : command => do +-- Elab.Command.runTermElabM fun _ => do +-- logInfo m!"{geq' (← Elab.Term.elabLevel l') (← Elab.Term.elabLevel l)}" +-- -- logInfo m!"{repr <| Normalize.normalize (← Elab.Term.elabLevel l)}" +-- -- logInfo m!"{repr <| Normalize.normalize (← Elab.Term.elabLevel l')}" + +-- universe u v w +-- /-- info: max 1 u -/ +-- #guard_msgs (whitespace := lax) in normalize max u 1 +-- /-- info: u -/ +-- #guard_msgs (whitespace := lax) in normalize imax 1 u +-- /-- info: max 1 (imax (u + 1) u) -/ +-- #guard_msgs (whitespace := lax) in normalize u+1 +-- /-- info: imax 2 u -/ +-- #guard_msgs (whitespace := lax) in normalize imax 2 u +-- /-- info: max v (imax (imax u v) w) -/ +-- #guard_msgs (whitespace := lax) in normalize max w (imax (imax u w) v) +-- /-- info: max v (imax (imax u v) w) -/ +-- #guard_msgs (whitespace := lax) in normalize max (imax (imax u v) w) (imax (imax u w) v) +-- /-- info: u -/ +-- #guard_msgs (whitespace := lax) in normalize imax u u +-- /-- info: max 1 (imax (u + 1) u) -/ +-- #guard_msgs (whitespace := lax) in normalize imax u (u+1) +-- /-- info: max 1 (imax (max (v + 1) (imax (u + 1) u)) v) -/ +-- #guard_msgs (whitespace := lax) in normalize imax u v + 1 diff --git a/Ix/Theory/Named/Reference/List.lean b/Ix/Theory/Named/Reference/List.lean new file mode 100644 index 000000000..42447a15f --- /dev/null +++ b/Ix/Theory/Named/Reference/List.lean @@ -0,0 +1,11 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + + +@[specialize] def List.all2 (R : α → α → Bool) : List α → List α → Bool + | a1 :: as1, a2 :: as2 => R a1 a2 && all2 R as1 as2 + | [], [] => true + | _, _ => false diff --git a/Ix/Theory/Named/Reference/LocalContext.lean b/Ix/Theory/Named/Reference/LocalContext.lean new file mode 100644 index 000000000..7417de5e6 --- /dev/null +++ b/Ix/Theory/Named/Reference/LocalContext.lean @@ -0,0 +1,27 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.LocalContext + +namespace Ix.Theory.Named +open Lean + +class MonadLocalNameGenerator (m : Type u → Type v) where + withFreshId : (Name → m α) → m α +export MonadLocalNameGenerator (withFreshId) + +instance [MonadLocalNameGenerator m] : MonadLocalNameGenerator (ReaderT ρ m) where + withFreshId f c := withFreshId (f · c) + +@[inline] def withLocalDecl [Monad m] [MonadLocalNameGenerator m] [MonadWithReaderOf LocalContext m] + (name : Name) (bi : BinderInfo) (ty : Expr) (k : Expr → m α) : m α := + withFreshId fun id => do + withReader (·.mkLocalDecl ⟨id⟩ name ty bi) <| k <| .fvar ⟨id⟩ + +@[inline] def withLetDecl [Monad m] [MonadLocalNameGenerator m] [MonadWithReaderOf LocalContext m] + (name : Name) (ty val : Expr) (k : Expr → m α) : m α := + withFreshId fun id => do + withReader (·.mkLetDecl ⟨id⟩ name ty val) <| k <| .fvar ⟨id⟩ diff --git a/Ix/Theory/Named/Reference/Primitive.lean b/Ix/Theory/Named/Reference/Primitive.lean new file mode 100644 index 000000000..bfed975dd --- /dev/null +++ b/Ix/Theory/Named/Reference/Primitive.lean @@ -0,0 +1,498 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Reference.TypeChecker +import Ix.Theory.Named.Reference.Environment.Basic + +namespace Ix.Theory.Named +namespace Environment +open Lean hiding Environment Exception +open Kernel TypeChecker + +deriving instance ToExpr for LevelMVarId +deriving instance ToExpr for Level +deriving instance ToExpr for MVarId +deriving instance ToExpr for BinderInfo +deriving instance ToExpr for String.Pos.Raw +deriving instance ToExpr for Substring.Raw +deriving instance ToExpr for SourceInfo +deriving instance ToExpr for Syntax +deriving instance ToExpr for DataValue +deriving instance ToExpr for KVMap +deriving instance ToExpr for Expr + +elab (name := microQq) "q(" e:term ")" : term => + return toExpr (← instantiateMVars (← Elab.Term.elabTerm e none)) + +structure Reflection where + type : Expr + ofTrue : Expr + ofFalse : Expr + toDec : Expr + +def Reflection.defn₁ : Reflection where + type := q(fun p b => ∀ {q : Prop}, ((b = true → p) → (¬b = true → ¬p) → q) → q) + ofTrue := q(fun p (H : ∀ {q : Prop}, ((true = true → p) → (¬true = true → ¬p) → q) → q) => + H fun h _ => h rfl) + ofFalse := q(fun p (H : ∀ {q : Prop}, ((false = true → p) → (¬false = true → ¬p) → q) → q) => + H fun _ h => h Bool.noConfusion) + toDec := q(fun p b (H : ∀ {q : Prop}, ((b = true → p) → (¬b = true → ¬p) → q) → q) => + if h : b = true then isTrue (H fun h' _ => h' h) else isFalse (H fun _ h' => h' h)) + +def Reflection.defn₂ : Reflection where + type := q(fun p b => ∀ {q : Prop}, ((b = true → p) → (b = false → ¬p) → q) → q) + ofTrue := q(fun p (H : ∀ {q : Prop}, ((true = true → p) → (true = false → ¬p) → q) → q) => + H fun h _ => h rfl) + ofFalse := q(fun p (H : ∀ {q : Prop}, ((false = true → p) → (false = false → ¬p) → q) → q) => + H fun _ h => h rfl) + toDec := q(fun p b (H : ∀ {q : Prop}, ((b = true → p) → (b = false → ¬p) → q) → q) => + b.casesOn (motive := fun b' => b = b' → Decidable p) + (fun h => isFalse (H fun _ h' => h' h)) (fun h => isTrue (H fun h' _ => h' h)) rfl) + +def Reflection.check (r : Reflection) (fail : ∀ {α}, M α) : M Unit := do + unless ← isDefEq (← checkType r.type) q(Prop → Bool → Prop) do fail + +inductive ConditionImpl where + | bool + | reflectNatNat (asBool : Expr) (reflect : Reflection) (proof : Expr) + +structure Condition where + prop : Expr + dec : Expr + impl : ConditionImpl + +def Condition.natLE : Condition where + prop := q(@LE.le Nat _) + dec := q(Nat.decLe) + impl := .reflectNatNat + (asBool := q(Nat.ble)) + (reflect := .defn₁) + (proof := q(fun n m {q : Prop} (H : _ → _ → q) => + H (@Nat.le_of_ble_eq_true n m) (@Nat.not_le_of_not_ble_eq_true n m))) + +def Condition.natEq : Condition where + prop := q(@Eq Nat) + dec := q(Nat.decEq) + impl := .reflectNatNat + (asBool := q(Nat.beq)) + (reflect := .defn₂) + (proof := q(fun n m {q : Prop} (H : _ → _ → q) => + H (@Nat.eq_of_beq_eq_true n m) (@Nat.ne_of_beq_eq_false n m))) + +def Condition.bool : Condition where + prop := q(fun x : Bool => x = true) + dec := q(fun x => Bool.decEq x true) + impl := .bool + +def Reflection.ite (r : Reflection) : Expr := + .lam0 q(Prop) <| .lam0 q(Bool) <| .lam0 (mkApp2 r.type (.bvar 1) (.bvar 0)) <| + .lam0 q(Type) <| mkApp3 q(@_root_.ite.{1}) (.bvar 0) (.bvar 3) + (mkApp3 r.toDec (.bvar 3) (.bvar 2) (.bvar 1)) + +def Reflection.natDITE (r : Reflection) : Expr := + .lam0 q(Prop) <| .lam0 q(Bool) <| .lam0 (mkApp2 r.type (.bvar 1) (.bvar 0)) <| + mkApp2 q(@dite Nat) (.bvar 2) (mkApp3 r.toDec (.bvar 2) (.bvar 1) (.bvar 0)) + +def Reflection.checkITE (r : Reflection) (fail : ∀ {α}, M α) : M Unit := do + unless ← isDefEq (← checkType r.ite) (.arrow q(Prop) <| .arrow q(Bool) <| + .arrow (mkApp2 r.type (.bvar 1) (.bvar 0)) q(∀ α : Type, α → α → α)) do fail + withLocalDecl `p .default q(Prop) fun p => do + withLocalDecl `H .default (mkApp2 r.type p q(true)) fun H => do + unless ← isDefEq (mkApp3 r.ite p q(true) H) q(fun α : Type => fun a _ : α => a) do fail + withLocalDecl `H .default (mkApp2 r.type p q(false)) fun H => do + unless ← isDefEq (mkApp3 r.ite p q(false) H) q(fun α : Type => fun _ a : α => a) do fail + +def Reflection.checkNatDITE (r : Reflection) (fail : ∀ {α}, M α) : M Unit := do + unless ← isDefEq (← checkType q(Not)) q(Prop → Prop) do fail + unless ← isDefEq (← checkType r.natDITE) (.arrow q(Prop) <| .arrow q(Bool) <| + .arrow (mkApp2 r.type (.bvar 1) (.bvar 0)) <| + .arrow (.arrow (.bvar 2) q(Nat)) <| .arrow (.arrow (mkApp q(Not) (.bvar 3)) q(Nat)) <| + q(Nat)) do fail + unless ← isDefEq (← checkType r.ofTrue) (.arrow q(Prop) <| + .arrow (mkApp2 r.type (.bvar 0) q(true)) (.bvar 1)) do fail + unless ← isDefEq (← checkType r.ofFalse) (.arrow q(Prop) <| + .arrow (mkApp2 r.type (.bvar 0) q(false)) (mkApp q(Not) (.bvar 1))) do fail + withLocalDecl `p .default q(Prop) fun p => do + withLocalDecl `a .default (.arrow p q(Nat)) fun a => do + withLocalDecl `b .default (.arrow (mkApp q(Not) p) q(Nat)) fun b => do + withLocalDecl `H .default (mkApp2 r.type p q(true)) fun H => do + unless ← isDefEq (mkApp5 r.natDITE p q(true) H a b) (mkApp a (mkApp2 r.ofTrue p H)) do fail + withLocalDecl `H .default (mkApp2 r.type p q(false)) fun H => do + unless ← isDefEq (mkApp5 r.natDITE p q(false) H a b) (mkApp b (mkApp2 r.ofFalse p H)) do fail + +def Condition.check (cond : Condition) (fail : ∀ {α}, M α) + (ite := false) (dite := false) : M Unit := do + _ ← checkType cond.dec + match cond.impl with + | .reflectNatNat asBool reflect proof => + unless ← isDefEq (← inferType cond.prop) q(Nat → Nat → Prop) do fail + reflect.check fail + if ite then reflect.checkITE fail + if dite then reflect.checkNatDITE fail + let y := .bvar 0; let x := .bvar 1 + let e := .lam0 q(Nat) <| .lam0 q(Nat) <| mkApp3 reflect.toDec + (mkApp2 cond.prop x y) (mkApp2 asBool x y) (mkApp2 proof x y) + _ ← checkType e + unless ← isDefEq (← inferType asBool) q(Nat → Nat → Bool) do fail + unless ← isProp (← inferType proof) do fail + unless ← isDefEq e cond.dec do fail + | .bool => + unless ← isDefEq (← inferType cond.prop) q(Bool → Prop) do fail + let b := .bvar 0 + if ite then + let natITE := .lam0 q(Bool) <| + mkApp2 q(@_root_.ite Nat) (mkApp cond.prop b) (mkApp cond.dec b) + unless ← isDefEq (← checkType natITE) q(Bool → Nat → Nat → Nat) do fail + unless ← isDefEq (mkApp natITE q(true)) q(fun a _ : Nat => a) do fail + unless ← isDefEq (mkApp natITE q(false)) q(fun _ a : Nat => a) do fail + if dite then throw <| .other "unsupported" + +protected def Condition.ite (cond : Condition) (α : Expr) (args : Array Expr) (t e : Expr) : Expr := + mkApp5 q(@ite.{1}) α (mkAppN cond.prop args) (mkAppN cond.dec args) t e + +protected def Condition.dite (cond : Condition) (args: Array Expr) (t e : Expr) : Expr := + mkApp4 q(@dite Nat) (mkAppN cond.prop args) (mkAppN cond.dec args) + (.lam0 (mkAppN cond.prop args) t) + (.lam0 (mkApp q(Not) (mkAppN cond.prop args)) e) + +protected def Condition.decide (cond : Condition) (args : Array Expr) : Expr := + cond.ite q(Bool) args q(true) q(false) + +def unfoldWellFounded (e : Expr) (fvs : Array Expr) (eq_def : Expr) (fail : ∀ {α}, M α) : M Expr := do + let .app (.app _ lhs) rhs := eq_def.getForallBody.instantiateRev fvs | fail + let orig := lhs.getAppFn + let rhs := rhs.replace fun e' => if e' == orig then some e else none + let .app e1 wfn ← whnf (mkAppN e fvs) | fail + e1.withApp fun accRec args => do + let #[α,r,_,_,n] := args | fail + let .const ``Acc.rec [_, u] := accRec | fail + let .app wf _ := wfn | fail + let L := .lam0 α <| .lam0 (mkApp2 r (.bvar 0) n) (mkApp wf (.bvar 1)) + let wfn' := mkApp4 (.const ``Acc.intro [u]) α r n L + let p ← inferType wfn + unless ← isProp p do fail + unless ← isDefEq p (← checkType wfn') do fail + _ ← checkType rhs + unless ← isDefEq (e1.app wfn') rhs do fail + return (← getLCtx).mkLambda fvs rhs + +def lambdaTelescope (e : Expr) (k : Array Expr → Expr → M α) : M α := loop #[] e where + loop fvars + | .lam x dom body bi => + let d := dom.instantiateRev fvars + withLocalDecl x bi d fun fv => do + let fvars := fvars.push fv + loop fvars body + | e => k fvars (e.instantiateRev fvars) + +def forallTelescope (e : Expr) (k : Array Expr → Expr → M α) : M α := loop #[] e where + loop fvars + | .forallE x dom body bi => + let d := dom.instantiateRev fvars + withLocalDecl x bi d fun fv => do + let fvars := fvars.push fv + loop fvars body + | e => k fvars (e.instantiateRev fvars) + +def unfoldNatWellFounded (e : Expr) (fvs : Array Expr) (eq_def : Expr) (fail : ∀ {α}, M α) : M Expr := do + let succ := mkApp q(Nat.succ) + let defeq1 a b := isDefEq (.arrow q(Nat) a) (.arrow q(Nat) b) + let x := .bvar 0 + let .app (.app _ lhs) rhs := eq_def.getForallBody.instantiateRev fvs | fail + let orig := lhs.getAppFn + let rhs := rhs.replace fun e' => if e' == orig then some e else none + let e1 ← whnfCore (mkAppN e fvs) -- get _unary + let e1 ← unfoldDefinition e1 -- get fix + (← whnfCore e1).withApp fun fix args => do + let .const ``WellFounded.Nat.fix [_, _] := fix | fail + let #[α,motive,f,F,a₀] := args | fail + let fixFn := mkAppN fix #[α,motive,f,F] + withLocalDecl `a .default (← inferType a₀) fun a => do + -- prove |- fix α motive f F a ≡ go α motive f F (eager (f a)) a [proof] + let e1 ← unfoldDefinition (.app fixFn a) -- get fix.go + let e1 ← whnfCore e1 + e1.withApp fun fixGo args => do + let #[α',motive',f',F',fuel,a',_] := args | fail + unless (α, motive, f, F, a) == (α', motive', f', F', a') do fail + let .app eager n := fuel | fail + unless ← isDefEq n (succ (.app f a)) do fail + -- prove |- eager n = if beq n n = true then n else n + unless (← getEnv).contains ``Nat.beq do fail + let c := Condition.bool; c.check (fail) (ite := true) + unless ← defeq1 (mkApp eager x) (c.ite q(Nat) #[mkApp2 (.const ``Nat.beq []) x x] x x) do fail + -- prove |- go α motive f F (succ t) x hfuel ≡ F x fun y hy => go α motive f F t y [proof] + let go' ← unfoldDefinition fixGo -- get fix + lambdaTelescope go' fun fvs go' => do + let #[_,_,_,F,t] := fvs | fail + let .app natRec t' := go' | fail + unless !natRec.containsFVar t.fvarId! && t == t' do fail + _ ← checkType (succ t) + let gor ← whnfCore (.app natRec (succ t)) + lambdaTelescope gor fun fvs gor => do + let #[x,_] := fvs | fail + let .app Fx ih := gor | fail + unless .app F x == Fx do fail + lambdaTelescope ih fun fvs ih => do + let #[y,_] := fvs | fail + let .app ih _ := ih | fail + unless ih == .app (.app natRec t) y do fail + -- prove |- rhs ≡ F x fun y _ => fix α motive f F y + let .forallE _ dom _ _ ← inferType (.app F a₀) | fail + let ih' ← forallTelescope dom fun fvs _ => do + let #[y,_] := fvs | fail + return (← getLCtx).mkLambda fvs (.app fixFn y) + have rhs' := mkApp2 F a₀ ih' + _ ← checkType rhs' + unless ← isDefEq rhs rhs' do fail + return (← getLCtx).mkLambda fvs rhs + +def checkPrimitiveDef (v : DefinitionVal) : M Bool := do + unless v.safety == .safe do return false + let fail {α} : M α := throw <| .other s!"invalid form for primitive def {v.name}" + let tru := q(true) + let fal := q(false) + let zero := q(Nat.zero) + let succ := mkApp q(Nat.succ) + let pred := mkApp q(Nat.pred) + let add := mkApp2 q(Nat.add) + let sub := mkApp2 q(Nat.sub) + let mul := mkApp2 q(Nat.mul) + let mod := mkApp2 q(Nat.mod) + let div := mkApp2 q(Nat.div) + let one := succ zero + let two := succ one + let defeq1 a b := isDefEq (.arrow q(Nat) a) (.arrow q(Nat) b) + let defeq2 a b := defeq1 (.arrow q(Nat) a) (.arrow q(Nat) b) + let x := .bvar 0 + let y := .bvar 1 + let env ← getEnv + match v.name with + | ``Nat.add => + unless env.contains ``Nat && v.levelParams.isEmpty do fail + -- add : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let add := mkApp2 v.value + -- add x 0 ≡ x + unless ← defeq1 (add x zero) x do fail + -- add y (succ x) ≡ succ (add y x) + unless ← defeq2 (add y (succ x)) (succ (add y x)) do fail + | ``Nat.pred => + unless env.contains ``Nat && v.levelParams.isEmpty do fail + -- pred : Nat → Nat + unless ← isDefEq v.type q(Nat → Nat) do fail + let pred := mkApp v.value + unless ← isDefEq (pred zero) zero do fail + unless ← defeq1 (pred (succ x)) x do fail + | ``Nat.sub => + unless env.contains ``Nat.pred && v.levelParams.isEmpty do fail + -- sub : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let sub := mkApp2 v.value + unless ← defeq1 (sub x zero) x do fail + unless ← defeq2 (sub y (succ x)) (pred (sub y x)) do fail + | ``Nat.mul => + unless env.contains ``Nat.add && v.levelParams.isEmpty do fail + -- mul : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let mul := mkApp2 v.value + unless ← defeq1 (mul x zero) zero do fail + unless ← defeq2 (mul y (succ x)) (add (mul y x) y) do fail + | ``Nat.pow => + unless env.contains ``Nat.mul && v.levelParams.isEmpty do fail + -- pow : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let pow := mkApp2 v.value + unless ← defeq1 (pow x zero) one do fail + unless ← defeq2 (pow y (succ x)) (mul (pow y x) y) do fail + | ``Nat.mod => + unless env.contains ``Nat.sub && env.contains ``Bool && v.levelParams.isEmpty do fail + -- mod : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let mod := mkApp2 v.value + unless ← defeq1 (mod zero x) zero do fail + unless ← isDefEq (← checkType q(@LE.le Nat _)) q(Nat → Nat → Prop) do fail + let le := mkApp2 q(@LE.le Nat _) + unless ← isDefEq (← checkType q(Nat.modCore.go)) + q(∀ n, Nat.succ Nat.zero ≤ n → ∀ fuel x : Nat, Nat.succ x ≤ fuel → Nat) do fail + let go := mkApp5 q(Nat.modCore.go) + let c := Condition.natLE; c.check fail (ite := true) (dite := true) + withLocalDecl `x .default q(Nat) fun x => do + withLocalDecl `y .default q(Nat) fun y => do + let sx := succ x + let e := c.ite q(Nat) #[y, sx] (c.dite #[one, y] + (go y (.bvar 0) (succ sx) sx (mkApp q(Nat.lt_succ_self) sx)) sx) sx + _ ← checkType e + unless ← isDefEq (mod sx y) e do fail + withLocalDecl `hy .default (le one y) fun hy => do + withLocalDecl `fuel .default q(Nat) fun fuel => do + withLocalDecl `h .default (le (succ x) (succ fuel)) fun h => do + let e := c.dite #[y, x] (go y hy fuel (sub x y) + (mkApp6 q(@Nat.div_rec_fuel_lemma) x y fuel hy (.bvar 0) h)) x + _ ← checkType e + unless ← isDefEq (go y hy (succ fuel) x h) e do fail + | ``Nat.div => + unless env.contains ``Nat.sub && env.contains ``Bool && v.levelParams.isEmpty do fail + -- div : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let div := mkApp2 v.value + let c := Condition.natLE; c.check fail (dite := true) + unless ← isDefEq (← checkType q(@LE.le Nat _)) q(Nat → Nat → Prop) do fail + let le := mkApp2 q(@LE.le Nat _) + unless ← isDefEq (← checkType q(Nat.div.go)) + q(∀ y, Nat.succ Nat.zero ≤ y → ∀ fuel x : Nat, Nat.succ x ≤ fuel → Nat) do fail + let go := mkApp5 q(Nat.div.go) + withLocalDecl `x .default q(Nat) fun x => do + withLocalDecl `y .default q(Nat) fun y => do + let e := c.dite #[one, y] (go y (.bvar 0) (succ x) x (mkApp q(Nat.lt_succ_self) x)) zero + _ ← checkType e + unless ← isDefEq (div x y) e do fail + withLocalDecl `hy .default (le one y) fun hy => do + withLocalDecl `fuel .default q(Nat) fun fuel => do + withLocalDecl `h .default (le (succ x) (succ fuel)) fun h => do + let e := c.dite #[y, x] (succ (go y hy fuel (sub x y) + (mkApp6 q(@Nat.div_rec_fuel_lemma) x y fuel hy (.bvar 0) h))) zero + _ ← checkType e + unless ← isDefEq (go y hy (succ fuel) x h) e do fail + | ``Nat.gcd => + unless env.contains ``Nat.mod && v.levelParams.isEmpty do fail + -- gcd : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + withLocalDecl `m .default q(Nat) fun m => do + withLocalDecl `n .default q(Nat) fun n => do + let gcd' ← unfoldNatWellFounded v.value #[m, n] q(type_of% Nat.gcd.eq_def) fail + let gcd' := mkApp2 gcd' + let gcd := mkApp2 v.value + unless ← isDefEq (gcd' zero m) m do fail + unless ← isDefEq (gcd' (succ n) m) (gcd (mod m (succ n)) (succ n)) do fail + | ``Nat.beq => + unless env.contains ``Nat && env.contains ``Bool && v.levelParams.isEmpty do fail + -- beq : Nat → Nat → Bool + unless ← isDefEq v.type q(Nat → Nat → Bool) do fail + let beq := mkApp2 v.value + unless ← isDefEq (beq zero zero) tru do fail + unless ← defeq1 (beq zero (succ x)) fal do fail + unless ← defeq1 (beq (succ x) zero) fal do fail + unless ← defeq2 (beq (succ y) (succ x)) (beq y x) do fail + | ``Nat.ble => + unless env.contains ``Nat && env.contains ``Bool && v.levelParams.isEmpty do fail + -- ble : Nat → Nat → Bool + unless ← isDefEq v.type q(Nat → Nat → Bool) do fail + let ble := mkApp2 v.value + unless ← isDefEq (ble zero zero) tru do fail + unless ← defeq1 (ble zero (succ x)) tru do fail + unless ← defeq1 (ble (succ x) zero) fal do fail + unless ← defeq2 (ble (succ y) (succ x)) (ble y x) do fail + | ``Nat.bitwise => + unless env.contains ``Nat && env.contains ``Bool && v.levelParams.isEmpty do fail + -- bitwise : Nat → Nat → Nat + unless ← isDefEq v.type q((Bool → Bool → Bool) → Nat → Nat → Nat) do fail + withLocalDecl `f .default q(Bool → Bool → Bool) fun f => do + withLocalDecl `n .default q(Nat) fun n => do + withLocalDecl `m .default q(Nat) fun m => do + let bitwise' ← unfoldNatWellFounded v.value #[f, n, m] q(type_of% Nat.bitwise.eq_def) fail + let bitwise := mkApp3 v.value + let c := Condition.natEq; c.check fail (ite := true) + let bc := Condition.bool; bc.check fail (ite := true) + let e := + c.ite q(Nat) #[n, zero] (bc.ite q(Nat) #[mkApp2 f q(false) q(true)] m zero) <| + c.ite q(Nat) #[m, zero] (bc.ite q(Nat) #[mkApp2 f q(true) q(false)] n zero) <| + let n' := div n two + let m' := div m two + let b₁ := c.decide #[mod n two, one] + let b₂ := c.decide #[mod m two, one] + let r := bitwise f n' m' + bc.ite q(Nat) #[mkApp2 f b₁ b₂] (add (add r r) one) (add r r) + _ ← checkType e + unless ← isDefEq (mkApp3 bitwise' f n m) e do fail + | ``Nat.land => + unless env.contains ``Nat.bitwise && v.levelParams.isEmpty do fail + -- land : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let .app (.const ``Nat.bitwise []) and := v.value | fail + let and := mkApp2 and + unless ← defeq1 (and fal x) fal do fail + unless ← defeq1 (and tru x) x do fail + | ``Nat.lor => + unless env.contains ``Nat.bitwise && v.levelParams.isEmpty do fail + -- lor : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let .app (.const ``Nat.bitwise []) or := v.value | fail + let or := mkApp2 or + unless ← defeq1 (or fal x) x do fail + unless ← defeq1 (or tru x) tru do fail + | ``Nat.xor => + unless env.contains ``Nat.bitwise && v.levelParams.isEmpty do fail + -- xor : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let .app (.const ``Nat.bitwise []) xor := v.value | fail + let xor := mkApp2 xor + unless ← isDefEq (xor fal fal) fal do fail + unless ← isDefEq (xor tru fal) tru do fail + unless ← isDefEq (xor fal tru) tru do fail + unless ← isDefEq (xor tru tru) fal do fail + | ``Nat.shiftLeft => + unless env.contains ``Nat.mul && v.levelParams.isEmpty do fail + -- shiftLeft : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let shl := mkApp2 v.value + unless ← defeq1 (shl x zero) x do fail + unless ← defeq2 (shl x (succ y)) (shl (mul two x) y) do fail + | ``Nat.shiftRight => + unless env.contains ``Nat.div && v.levelParams.isEmpty do fail + -- shiftRight : Nat → Nat → Nat + unless ← isDefEq v.type q(Nat → Nat → Nat) do fail + let shr := mkApp2 v.value + unless ← defeq1 (shr x zero) x do fail + unless ← defeq2 (shr x (succ y)) (div (shr x y) two) do fail + | ``Char.ofNat => + unless env.contains ``Nat && v.levelParams.isEmpty do fail + -- Char : Type + _ ← ensureType q(Char) + -- @Char.ofNat : Nat → Char + unless ← isDefEq v.type q(Nat → Char) do fail + | ``String.ofList => + unless v.levelParams.isEmpty do fail + -- Char : Type + _ ← ensureType q(Char) + -- List Char : Type + _ ← ensureType q(List Char) + -- @List.nil.{0} Char : List Char + unless ← isDefEq (← checkType q(List.nil (α := Char))) q(List Char) do fail + -- @List.cons.{0} Char : Char → List Char → List Char + unless ← isDefEq (← checkType q(List.cons (α := Char))) q(Char → List Char → List Char) do fail + -- String.ofList : List Char → String + unless ← isDefEq v.type q(List Char → String) do fail + | _ => return false + return true + +def checkPrimitiveInductive (_env : Environment) (lparams : List Name) (nparams : Nat) + (types : List InductiveType) (isUnsafe : Bool) : Except Exception Bool := do + unless !isUnsafe && lparams.isEmpty && nparams == 0 do return false + let [type] := types | return false + unless type.type == .sort (.succ .zero) do return false + let fail {α} : Except Exception α := + throw <| .other s!"invalid form for primitive inductive {type.name}" + match type.name with + | ``Bool => + let [⟨``Bool.false, .const ``Bool []⟩, ⟨``Bool.true, .const ``Bool []⟩] := type.ctors | fail + | ``Nat => + let [ + ⟨``Nat.zero, .const ``Nat []⟩, + ⟨``Nat.succ, .forallE _ (.const ``Nat []) (.const ``Nat []) _⟩ + ] := type.ctors | fail + | _ => return false + return true + +-- Self-test to ensure that the primitives check at compile time +run_meta + let env ← Lean.getEnv + for c in Environment.primitives do + match env.find? c with + | some (.defnInfo v) => + let (.true, _) ← Elab.Term.TermElabM.run (checkPrimitiveDef { v with }) + | throwError "{v.name}" + | some (.inductInfo _) | some (.ctorInfo _) => pure () + | r => throwError "unexpected primitive: {r.map (·.name)}" diff --git a/Ix/Theory/Named/Reference/PtrEq.lean b/Ix/Theory/Named/Reference/PtrEq.lean new file mode 100644 index 000000000..36f715bbd --- /dev/null +++ b/Ix/Theory/Named/Reference/PtrEq.lean @@ -0,0 +1,28 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Declaration + +namespace Ix.Theory.Named +open Lean + +/-- +Pointer equality is not a safe function, but the kernel uses it anyway for some fast paths. +We cannot use `withPtrEq` because it is not a mere optimization before a true equality test - +the kernel actually has different behavior (will reject some inputs that it would not otherwise) +if identical objects spontaneously get different addresses. + +We use this function to try to isolate uses of pointer equality in the kernel, +and type-restrict it to avoid thorny questions about equality of closures or the like. +-/ +opaque ptrEqExpr (a b : Expr) : Bool := unsafe ptrAddrUnsafe a == ptrAddrUnsafe b + +axiom ptrEqExpr_eq : ptrEqExpr a b → a = b + +/-- See `ptrEqExpr`. -/ +opaque ptrEqConstantInfo (a b : ConstantInfo) : Bool := unsafe ptrAddrUnsafe a == ptrAddrUnsafe b + +axiom ptrEqConstantInfo_eq : ptrEqConstantInfo a b → a = b diff --git a/Ix/Theory/Named/Reference/Quot.lean b/Ix/Theory/Named/Reference/Quot.lean new file mode 100644 index 000000000..15f320647 --- /dev/null +++ b/Ix/Theory/Named/Reference/Quot.lean @@ -0,0 +1,126 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Batteries.Tactic.OpenPrivate +import Ix.Theory.Named.Reference.Environment.Basic +import Ix.Theory.Named.Reference.Expr +import Ix.Theory.Named.Reference.Instantiate +import Ix.Theory.Named.Reference.LocalContext + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +open private Lean.Kernel.Environment.add markQuotInit from Lean.Environment + +abbrev ExprBuildT (m) := ReaderT LocalContext <| ReaderT NameGenerator m + +def ExprBuildT.run [Monad m] (x : ExprBuildT m α) : m α := x {} {} + +instance : MonadLocalNameGenerator (ExprBuildT m) where + withFreshId x c ngen := x ngen.curr c ngen.next + +def checkEqType (env : Environment) : Except Exception Unit := do + let fail {α} (s : String) : Except Exception α := + throw <| .other s!"failed to initialize quot module, {s}" + let .inductInfo info ← env.get ``Eq | fail "environment does not have 'Eq' type" + let [u] := info.levelParams | fail "unexpected number of universe params at 'Eq' type" + let [eqRefl] := info.ctors | fail "unexpected number of constructors for 'Eq' type" + ExprBuildT.run do + withLocalDecl `α .implicit (.sort (.param u)) fun α => do + if info.type != ((← read).mkForall #[α] <| .arrow α <| .arrow α .prop) then + fail "'Eq' has an expected type" + let info ← env.get eqRefl + let [u] := info.levelParams + | fail "unexpected number of universe params at 'Eq' type constructor" + withLocalDecl `α .implicit (.sort (.param u)) fun α => do + withLocalDecl `a .default α fun a => do + if info.type != ((← read).mkForall #[α, a] <| mkApp3 (.const ``Eq [.param u]) α a a) then + fail "unexpected type for 'Eq' type constructor" + +def Environment.addQuot (env : Environment) : Except Exception Environment := do + if env.quotInit then return env + checkEqType env + env.checkName ``Quot + env.checkName ``Quot.mk + env.checkName ``Quot.lift + env.checkName ``Quot.ind + ExprBuildT.run do + let u := .param `u + withLocalDecl `α .implicit (.sort u) fun α => do + let env ← withLocalDecl `r .default (.arrow α (.arrow α .prop)) fun r => do + -- constant Quot.{u} {α : Sort u} (r : α → α → Prop) : Sort u + let env := env.add <| .quotInfo { + name := ``Quot, kind := .type, levelParams := [`u] + type := (← read).mkForall #[α, r] <| .sort u + } + withLocalDecl `a .default α fun a => do + -- constant Quot.mk.{u} {α : Sort u} (r : α → α → Prop) (a : α) : @Quot.{u} α r + return env.add <| .quotInfo { + name := ``Quot.mk, kind := .ctor, levelParams := [`u] + type := (← read).mkForall #[α, r, a] <| mkApp2 (.const ``Quot [u]) α r + } + withLocalDecl `r .implicit (.arrow α (.arrow α .prop)) fun r => do + let quot_r := mkApp2 (.const ``Quot [u]) α r + withLocalDecl `a .default α fun a => do + let v := .param `v + let env ← withLocalDecl `β .implicit (.sort v) fun β => do + withLocalDecl `f .default (.arrow α β) fun f => do + withLocalDecl `b .default α fun b => do + let rab := mkApp2 r a b + let fa_eq_fb := mkApp3 (.const ``Eq [v]) β (.app f a) (.app f b) + let sanity := (← read).mkForall #[a, b] <| .arrow rab fa_eq_fb + -- constant Quot.lift.{u, v} {α : Sort u} {r : α → α → Prop} {β : Sort v} (f : α → β) : + -- (∀ a b : α, r a b → f a = f b) → @Quot.{u} α r → β + return env.add <| .quotInfo { + name := ``Quot.lift, kind := .lift, levelParams := [`u, `v] + type := (← read).mkForall #[α, r, β, f] <| .arrow sanity <| .arrow quot_r β + } + let quotMk_a := mkApp3 (.const ``Quot.mk [u]) α r a + withLocalDecl `β .implicit (.arrow quot_r .prop) fun β => do + let all_quot := (← read).mkForall #[a] <| .app β quotMk_a + withLocalDecl `q .implicit quot_r fun q => do + -- constant Quot.ind.{u} {α : Sort u} {r : α → α → Prop} {β : @Quot.{u} α r → Prop} : + -- (∀ a : α, β (@Quot.mk.{u} α r a)) → ∀ q : @Quot.{u} α r, β q + let env := env.add <| .quotInfo { + name := ``Quot.ind, kind := .ind, levelParams := [`u] + type := (← read).mkForall #[α, r, β] <| + .forallE `mk all_quot ((← read).mkForall #[q] <| .app β q) .default + } + return markQuotInit env + +/-- Reduces the head application of a quotient eliminator as follows: + +``` +Quot.lift.{u, v} {α : Sort u} {r : α → α → Prop} {β : Sort v} (f : α → β) : + (∀ a b : α, r a b → f a = f b) → @Quot.{u} α r → β + +Quot.lift f h (Quot.mk r a) ... ⟶ f a ... +``` + +``` +Quot.ind.{u} {α : Sort u} {r : α → α → Prop} {β : @Quot.{u} α r → Prop} : + (∀ a : α, β (@Quot.mk.{u} α r a)) → ∀ q : @Quot.{u} α r, β q + +Quot.ind p (Quot.mk r a) ... ⟶ p a ... +``` +-/ +def quotReduceRec [Monad m] (e : Expr) (whnf : Expr → m Expr) : m (Option Expr) := do + let .const fn _ := e.getAppFn | return none + let cont mkPos argPos := do + let args := e.getAppArgs + if h : mkPos < args.size then + let mk ← whnf args[mkPos] + if !mk.isAppOfArity ``Quot.mk 3 then return none + let mut r := Expr.app args[argPos]! mk.appArg! + let elimArity := mkPos + 1 + if elimArity < args.size then + r := mkAppRange r elimArity args.size args + return some r + else return none + if fn == ``Quot.lift then cont 5 3 + else if fn == ``Quot.ind then cont 4 3 + else return none diff --git a/Ix/Theory/Named/Reference/TypeChecker.lean b/Ix/Theory/Named/Reference/TypeChecker.lean new file mode 100644 index 000000000..67027532e --- /dev/null +++ b/Ix/Theory/Named/Reference/TypeChecker.lean @@ -0,0 +1,1074 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Reference.Declaration +import Ix.Theory.Named.Reference.PtrEq +import Ix.Theory.Named.Reference.Level +import Ix.Theory.Named.Reference.Quot +import Ix.Theory.Named.Reference.Inductive.Reduce +import Ix.Theory.Named.Reference.Instantiate +import Ix.Theory.Named.Reference.ForEachExprV +import Ix.Theory.Named.Reference.FuelConfig + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +abbrev InferCache := ExprMap Expr + +structure TypeChecker.State where + ngen : NameGenerator := { namePrefix := `_kernel_fresh, idx := 0 } + inferTypeI : InferCache := {} + inferTypeC : InferCache := {} + whnfCoreCache : ExprMap Expr := {} + whnfCache : ExprMap Expr := {} + success : Std.HashSet (Expr × Expr) := {} + failure : Std.HashSet (Expr × Expr) := {} + unfold : ExprMap Expr := {} + +structure TypeChecker.Context where + env : Environment + lctx : LocalContext := {} + safety : DefinitionSafety := .safe + eagerReduce := false + lparams : List Name := [] + fuel : FuelConfig := {} + +namespace TypeChecker + +abbrev M := ReaderT Context <| StateT State <| Except Exception + +def M.run (env : Environment) (safety : DefinitionSafety := .safe) + (lctx : LocalContext := {}) (lparams : List Name := []) (fuel : FuelConfig := {}) + (x : M α) : Except Exception α := + x { env, safety, lctx, lparams, fuel } |>.run' {} + +def M.runTermElab (m : M α) (safety := DefinitionSafety.safe) : Elab.Term.TermElabM α := do + ofExceptKernelException <| m.run (env := (← getEnv).toKernelEnv) + (lctx := ← getLCtx) (safety := safety) (lparams := (← get).levelNames) + +instance : MonadLift M Elab.Term.TermElabM := ⟨M.runTermElab⟩ + +def getEnv : M Environment := return (← read).env + +instance : MonadLCtx M where + getLCtx := return (← read).lctx + +instance [Monad m] : MonadNameGenerator (StateT State m) where + getNGen := return (← get).ngen + setNGen ngen := modify fun s => { s with ngen } + +instance : MonadLocalNameGenerator M where + withFreshId x := do x (← mkFreshId) + +instance (priority := low) : MonadWithReaderOf LocalContext M where + withReader f := withReader fun s => { s with lctx := f s.lctx } + +structure Methods where + protected isDefEqCore : Expr → Expr → M Bool + protected whnfCore (e : Expr) (cheapProj := false) : M Expr + protected whnf (e : Expr) : M Expr + protected inferType (e : Expr) (inferOnly : Bool) : M Expr + +abbrev RecM := ReaderT Methods M + +inductive ReductionStatus where + | continue (tn sn : Expr) + | unknown (tn sn : Expr) + | bool (b : Bool) + +namespace Inner + +/-- Reduces `e` to its weak-head normal form. -/ +def whnf (e : Expr) : RecM Expr := fun m => m.whnf e + +@[inline] def withLCtx [MonadWithReaderOf LocalContext m] (lctx : LocalContext) (x : m α) : m α := + withReader (fun _ => lctx) x + +/-- Ensures that `e` is defeq to some `e' := .sort ..`, returning `e'`. If not, throws an error with +`s` (the expression required to be a sort). -/ +def ensureSortCore (e s : Expr) : RecM Expr := do + if e.isSort then return e + let e ← whnf e + if e.isSort then return e + throw <| .typeExpected (← getEnv) (← getLCtx) s + +/-- Ensures that `e` is defeq to some `e' := .forallE ..`, returning `e'`. If not, throws an error +with `s := f a` (the application requiring `f` to be of function type). -/ +def ensureForallCore (e s : Expr) : RecM Expr := do + if e.isForall then return e + let e ← whnf e + if e.isForall then return e + throw <| .funExpected (← getEnv) (← getLCtx) s + +/-- Upper bound on the size in bytes of `n`'s runtime representation, mirroring the kernel's +`lean_nat_size_in_bytes`: a scalar occupies one machine word, and a bignum occupies its GMP limb +count times the limb size. -/ +def natSizeInBytes (n : Nat) : Nat := + let bits := n.log2 + 1 + -- `n` is boxed once it no longer fits in a machine word minus its tag bit. + if bits ≤ 63 then 8 else 8 * ((bits + 63) / 64) + +/-- Rejects a `Nat` numeral whose size exceeds `natMaxSize`. `numBytes` is an upper bound on the +numeral's size, so this may be called before computing it. -/ +def checkNatSize (numBytes : Nat) : RecM Unit := do + if numBytes > (← readThe Context).fuel.natMaxSize then + throw <| .other "the kernel refused a `Nat` numeral because its size exceeds the maximum; \ + raise the `natMaxSize` bound to allow it" + +/-- `Nat.pow` and `Nat.shiftLeft` take their second argument (the exponent, resp. the shift +amount) as a machine `UInt32` in the kernel, so reject one that does not fit rather than +overflowing. -/ +def checkCountArg (count : Nat) (op : String) : RecM Unit := do + if count ≥ UInt32.size then + throw <| .other s!"the kernel refused to evaluate `{op}` because its second argument does \ + not fit in a 32-bit unsigned integer" + +/-- Bounds the numerals entering the kernel (e.g. source literals) by the same limit `reduceNat` +enforces on the ones it computes. -/ +def checkLitSize (l : Literal) : RecM Unit := do + if let .natVal n := l then checkNatSize (natSizeInBytes n) + +/-- `checkNatSize`, conditionally: the size check the binary `Nat` operations that can grow a +numeral without bound run on their result. -/ +def checkNatSizeIf (checkSize : Bool) (numBytes : Nat) : RecM Unit := do + if checkSize then checkNatSize numBytes + +/-- Rejects `base ^ exp` when it would exceed `natMaxSize`, without forming it: the result +occupies at most `natSizeInBytes base * exp` bytes (a `base` of `0` or `1` yields `0`/`1`), and +the bound is compared by division so the product is never formed either. -/ +def checkPowSize (base exp : Nat) : RecM Unit := do + checkCountArg exp "Nat.pow" + if base > 1 && exp != 0 && natSizeInBytes base > (← readThe Context).fuel.natMaxSize / exp then + throw <| .other "the kernel refused to evaluate `Nat.pow` because the result would exceed \ + the maximum numeral size; raise the `natMaxSize` bound to allow it" + +/-- Rejects `v <<< shift` when it would exceed `natMaxSize`, without forming it: the result is +`v * 2 ^ shift`, which occupies about `natSizeInBytes v + shift / 8` bytes. `0 <<< _` is `0`. -/ +def checkShiftLeftSize (v shift : Nat) : RecM Unit := do + if v != 0 then + checkCountArg shift "Nat.shiftLeft" + checkNatSize (natSizeInBytes v + shift / 8 + 1) + +/-- Checks that `l` does not contain any level parameters not found in the context `tc`. -/ +def checkLevel (tc : Context) (l : Level) : Except Exception Unit := do + if let some n2 := l.getUndefParam tc.lparams then + throw <| .other s!"invalid reference to undefined universe level parameter '{n2}'" + +def inferFVar (tc : Context) (name : FVarId) : Except Exception Expr := do + if let some decl := tc.lctx.find? name then + return decl.type + throw <| .other "unknown free variable" + +/-- Infers the type of `.const name ls`. -/ +def inferConstant (tc : Context) (name : Name) (ls : List Level) (inferOnly : Bool) : + Except Exception Expr := do + let e := Expr.const name ls + let info ← tc.env.get name + let ps := info.levelParams + if ps.length != ls.length then + throw <| .other s!"incorrect number of universe levels parameters for '{e + }', #{ps.length} expected, #{ls.length} provided" + if !inferOnly then + if info.isUnsafe && tc.safety != .unsafe then + throw <| .other s!"invalid declaration, it uses unsafe declaration '{e}'" + if let .defnInfo v := info then + if v.safety == .partial && tc.safety == .safe then + throw <| .other + s!"invalid declaration, safe declaration must not contain partial declaration '{e}'" + for l in ls do + checkLevel tc l + return info.instantiateTypeLevelParams ls + +/-- Infers the type of expression `e`. If `inferOnly := false`, this function throws an error +whenever `e` is not typeable according to Lean's algorithmic typing judgment (barring resource +exhaustion: it may also throw `.deterministicTimeout` or `.deepRecursion` on a typeable term). +Setting `inferOnly := true` optimizes to avoid unnecessary checks in the case that `e` is already +known to be well-typed. -/ +def inferType (e : Expr) (inferOnly := true) : RecM Expr := fun m => m.inferType e inferOnly + +/-- Infers the type of lambda expression `e`. -/ +def inferLambda (e : Expr) (inferOnly : Bool) : RecM Expr := loop #[] e where + loop fvars : Expr → RecM Expr + | .lam name dom body bi => do + let d := dom.instantiateRev fvars + if !inferOnly then + _ ← ensureSortCore (← inferType d inferOnly) d + withLocalDecl name bi d fun fv => do + let fvars := fvars.push fv + loop fvars body + | e => do + let r ← inferType (e.instantiateRev fvars) inferOnly + let r := r.cheapBetaReduce + return (← getLCtx).mkForall fvars r + +/-- Infers the type of for-all expression `e`. -/ +def inferForall (e : Expr) (inferOnly : Bool) : RecM Expr := loop #[] #[] e where + loop fvars us : Expr → RecM Expr + | .forallE name dom body bi => do + let d := dom.instantiateRev fvars + let t1 ← ensureSortCore (← inferType d inferOnly) d + let us := us.push t1.sortLevel! + withLocalDecl name bi d fun fv => + loop (fvars.push fv) us body + | e => do + let r ← inferType (e.instantiateRev fvars) inferOnly + let s ← ensureSortCore r e + return .sort <| us.foldr mkLevelIMax' s.sortLevel! + +/-- Whether `t` and `s` have already been found definitionally equal. + +The pair is keyed on the order of the two hashes, so a later query finds the entry whichever way +round it presents the pair. This is a plain set of pairs rather than an equivalence-closure +structure on purpose: `isDefEq` is a sound but incomplete semi-decision procedure and so is not +transitive, and taking the transitive closure of its successes would make its result depend on the +order in which pairs were checked (lean4#14806). -/ +def succeededBefore (success : Std.HashSet (Expr × Expr)) (t s : Expr) : Bool := + if t.hash < s.hash then + success.contains (t, s) + else if t.hash > s.hash then + success.contains (s, t) + else + success.contains (t, s) || success.contains (s, t) + +@[inherit_doc succeededBefore] +def cacheSuccess (t s : Expr) : M Unit := do + let k := if t.hash ≤ s.hash then (t, s) else (s, t) + modify fun st => { st with success := st.success.insert k } + +/-- Returns whether `t` and `s` are definitionally equal according to Lean's algorithmic +definitional equality judgment. + +NOTE: This function does not do any typechecking of its own on `t` and `s`. So, when this is used as +part of a typechecking routine, it is expected that they are already well-typed (that is, that +`checkType t` and `checkType s` did not/would not throw an error). This is what justifies the +internal uses of `inferType` at its default `inferOnly := true`: on a well-typed subterm the fast +path returns the same type the checking path would have. -/ +def isDefEqCore (t s : Expr) : RecM Bool := fun m => m.isDefEqCore t s + +@[inherit_doc isDefEqCore] +def isDefEq (t s : Expr) : RecM Bool := do + -- Syntactically equivalent expressions are definitionally equal without consulting or + -- extending the success cache. Besides avoiding needless work, this keeps exact checker + -- executions compositional when an application argument has precisely the declared domain + -- type. + if t == s then return true + let r ← isDefEqCore t s + if r then + cacheSuccess t s + pure r + +/-- Infers the type of application `e`, assuming that `e` is already well-typed. -/ +def inferApp (e : Expr) : RecM Expr := do + e.withApp fun f args => + let rec loop fType j i : RecM Expr := + if i < args.size then + match fType with + | .forallE _ _ body _ => loop body j (i+1) + | _ => do + let fType := fType.instantiateRevRange j i args + let fType := (← ensureForallCore fType e).bindingBody! + loop fType i (i+1) + else + return fType.instantiateRevRange j args.size args + do loop (← inferType f) 0 0 + +/-- Infers the type of let-expression `e`. -/ +def inferLet (e : Expr) (inferOnly : Bool) : RecM Expr := loop #[] e where + loop fvars : Expr → RecM Expr + | .letE name type val body _ => do + let type := type.instantiateRev fvars + let val := val.instantiateRev fvars + if !inferOnly then + _ ← ensureSortCore (← inferType type inferOnly) type + let valType ← inferType val inferOnly + if !(← isDefEq valType type) then + throw <| .letTypeMismatch (← getEnv) (← getLCtx) name valType type + withLetDecl name type val fun fv => + loop (fvars.push fv) body + | e => do + let r ← inferType (e.instantiateRev fvars) inferOnly + let r := r.cheapBetaReduce + return (← getLCtx).mkForall fvars r + +/-- Gets the universe level of the sort that `e`'s type is defeq to, failing if `e` is not +a type. -/ +def getSortLevel (e : Expr) : RecM Level := do + let .sort u ← ensureSortCore (← inferType e) e | unreachable! + return u + +/-- Checks if `e` is a proposition, that is, if its type is a sort whose level normalizes to +zero. -/ +def isProp (e : Expr) : RecM Bool := return (← getSortLevel e).isAlwaysZero + +/-- Checks if `e` is definitely not a proposition, that is, if its type is a sort whose level +cannot normalize to zero under any instantiation. This is strictly stronger than `!(← isProp e)`, +which also holds for the levels that could go either way. -/ +def isNeverProp (e : Expr) : RecM Bool := return (← getSortLevel e).isNeverZero + +def invalidProj (e : Expr) : RecM α := do + throw <| .invalidProj (← getEnv) (← getLCtx) e + +def inferProjParams (proj : Expr) : List Expr → Expr → RecM Expr + | [], r => pure r + | arg :: args, r => do + let .forallE _ _ body _ ← whnf r | invalidProj proj + inferProjParams proj args (body.instantiate1 arg) + +def inferProjFields (proj : Expr) (typeName : Name) + (struct : Expr) (maybePropType : Bool) : + Nat → Nat → Expr → RecM Expr + | _, 0, r => pure r + | fieldIdx, count + 1, r => do + let .forallE _ dom body _ ← whnf r | invalidProj proj + if body.hasLooseBVars && maybePropType then + -- prop structs cannot have non-prop dependent fields + if !(← isProp dom) then invalidProj proj + inferProjFields proj typeName struct maybePropType (fieldIdx + 1) count + (body.instantiate1 (.proj typeName fieldIdx struct)) + +/-- Infers the type of structure projection `e`. -/ +def inferProj (typeName : Name) (idx : Nat) (struct structType : Expr) : RecM Expr := do + let e := Expr.proj typeName idx struct + let type ← whnf structType + type.withApp fun I args => do + let env ← getEnv + let .const I_name I_levels := I | invalidProj e + if typeName != I_name then invalidProj e + let .inductInfo I_val ← env.get I_name | invalidProj e + let [c] := I_val.ctors | invalidProj e + unless env.isProjectionReadyStructure I_name do invalidProj e + if args.size != I_val.numParams + I_val.numIndices then invalidProj e + let c_info ← env.get c + let .ctorInfo ctorInfo := c_info | invalidProj e + unless idx < ctorInfo.numFields do invalidProj e + let r ← inferProjParams e (args.toList.take I_val.numParams) + (c_info.instantiateTypeLevelParams I_levels) + let maybePropType := !(← getSortLevel type).isNeverZero + let r ← inferProjFields e I_name struct maybePropType 0 idx r + let .forallE _ dom _ _ ← whnf r | invalidProj e + if maybePropType then if !(← isProp dom) then invalidProj e + return dom + +@[inherit_doc inferType] +def inferType' (e : Expr) (inferOnly : Bool) : RecM Expr := do + if e.hasLooseBVars then + throw <| .other + s!"type checker does not support loose bound variables, \ + replace them with free variables before invoking it" + let state ← get + if let some r := (cond inferOnly state.inferTypeI state.inferTypeC)[e]? then + return r + let r ← match e with + | .lit l => + checkLitSize l + if !inferOnly then + match l with + | .natVal _ => _ ← (← getEnv).get ``Nat + | .strVal _ => _ ← (← getEnv).get ``Char.ofNat; _ ← (← getEnv).get ``String.ofList + pure (mkConst l.typeName) + | .mdata _ e => inferType' e inferOnly + | .proj s idx e => inferProj s idx e (← inferType' e inferOnly) + | .fvar n => inferFVar (← readThe Context) n + | .mvar _ => throw <| .other "kernel type checker does not support meta variables" + | .bvar _ => unreachable! + | .sort l => + if !inferOnly then + checkLevel (← readThe Context) l + pure <| .sort (.succ l) + | .const c ls => inferConstant (← readThe Context) c ls inferOnly + | .lam .. => inferLambda e inferOnly + | .forallE .. => inferForall e inferOnly + | .app f a => + if inferOnly then + inferApp e + else + let fType ← ensureForallCore (← inferType' f inferOnly) e + let aType ← inferType' a inferOnly + let dType := fType.bindingDomain! + -- it can be shown that if `e` is typeable as `T`, then `T` is typeable as `Sort l` + -- for some universe level `l`, so this use of `isDefEq` is valid + let ok ← if a.isAppOfArity ``eagerReduce 2 then + withTheReader Context (fun s => {s with eagerReduce := true}) <| + isDefEq dType aType + else + isDefEq dType aType + if !ok then throw <| .appTypeMismatch (← getEnv) (← getLCtx) e fType aType + pure <| fType.bindingBody!.instantiate1 a + | .letE .. => inferLet e inferOnly + modify fun s => cond inferOnly + { s with inferTypeI := s.inferTypeI.insert e r } + { s with inferTypeC := s.inferTypeC.insert e r } + return r + +/-- Reduces `e` to its weak-head normal form, without unfolding definitions. This is a conservative +version of `whnf` (which does unfold definitions), to be used for efficiency purposes. + +Setting `cheapProj` to `true` will cause the struct argument to be reduced "lazily" (using +`whnfCore` rather than `whnf`) when reducing struct projections, and suppresses caching of the +result. This can be a useful optimization if we're checking the definitional equality of two struct +projections of the same projection, where we might save some work by directly checking if the struct +arguments are defeq (rather than eagerly applying a projection). + +The kernel has a companion `cheap_rec` flag doing the same for the major premise of a recursor, but +nothing has set it since lean4#9275 removed the old compiler, so it is omitted here. -/ +def whnfCore (e : Expr) (cheapProj := false) : RecM Expr := + fun m => m.whnfCore e cheapProj + +def reduceRecursor (e : Expr) : RecM (Option Expr) := do + let env ← getEnv + if env.quotInit then + if let some r ← quotReduceRec e whnf then + return r + if let some r ← inductiveReduceRec env e whnf inferType isDefEq isNeverProp then + return r + return none + +/-- Reduces the free variable `e`: to the `whnfCore` of its definition if `e` is a let variable, +and to itself if it is a lambda variable. -/ +def whnfFVar (e : Expr) (cheapProj : Bool) : RecM Expr := do + if let some (.ldecl (value := v) ..) := (← getLCtx).find? e.fvarId! then + return ← whnfCore v cheapProj + return e + +/-- Reduces a projection of `struct` at index `idx` (when `struct` is reducible to a constructor +application). -/ +def reduceProj (idx : Nat) (struct : Expr) (cheapProj : Bool) : RecM (Option Expr) := do + let mut c ← (if cheapProj then whnfCore struct cheapProj else whnf struct) + if let .lit (.strVal s) := c then + c ← whnf (.strLitToConstructor s) + c.withApp fun mk args => do + let .const mkC _ := mk | return none + let env ← getEnv + let .ctorInfo mkInfo ← env.get mkC | return none + return args[mkInfo.numParams + idx]? + +def isLetFVar (lctx : LocalContext) (fvar : FVarId) : Bool := + lctx.find? fvar matches some (.ldecl ..) + +@[inherit_doc whnfCore] +def whnfCore' (e : Expr) (cheapProj := false) : RecM Expr := do + match e with + | .bvar .. | .sort .. | .mvar .. | .forallE .. | .const .. | .lam .. | .lit .. => return e + | .mdata _ e => return ← whnfCore' e cheapProj + | .fvar id => if !isLetFVar (← getLCtx) id then return e + | .app .. | .letE .. | .proj .. => pure () + if let some r := (← get).whnfCoreCache[e]? then + return r + let rec save r := do + if !cheapProj then + modify fun s => { s with whnfCoreCache := s.whnfCoreCache.insert e r } + return r + match e with + | .bvar .. | .sort .. | .mvar .. | .forallE .. | .const .. | .lam .. | .lit .. + | .mdata .. => unreachable! + | .fvar _ => return ← whnfFVar e cheapProj + | .app .. => + -- beta-reduce at the head as much as possible, apply any remaining `rargs` + -- to the resulting expression, and re-run `whnfCore` + e.withAppRev fun f0 rargs => do + -- the head may still be a let variable/binding, projection, or mdata-wrapped expression + let f ← whnfCore f0 cheapProj + if let .lam _ _ body _ := f then + let rec loop m (f : Expr) : RecM Expr := + let rec cont := do + let r := f.instantiateRange (rargs.size - m) rargs.size rargs + let r := r.mkAppRevRange 0 (rargs.size - m) rargs + save <|← whnfCore r cheapProj + if let .lam _ _ body _ := f then + if m < rargs.size then loop (m + 1) body + else cont + else cont + loop 1 body + else if Expr.structuralEq f f0 then + if let some r ← reduceRecursor e then + whnfCore r cheapProj + else + pure e + else + let r := f.mkAppRevRange 0 rargs.size rargs + -- the recursive call re-decomposes `r` and reaches the `f == f0` branch above, so + -- `reduceRecursor` is still applied; adding arguments can only enable further normalization + -- if the head reduced to a partial recursor application + save <|← whnfCore r cheapProj + | .letE _ _ val body _ => + save <|← whnfCore (body.instantiate1 val) cheapProj + | .proj _ idx s => + if let some m ← reduceProj idx s cheapProj then + save <|← whnfCore m cheapProj + else + save e + +/-- Checks if the head of `e` is a constant that can be delta-reduced, applied to the right number +of universe levels, returning its `ConstantInfo` if so. See `ConstantInfo.deltaValue?` for which +constants qualify. -/ +def isDelta (env : Environment) (e : Expr) : Option ConstantInfo := do + if let .const c ls := e.getAppFn then + if let some ci := env.find? c then + if ci.deltaValue?.isSome && ls.length == ci.numLevelParams then + return ci + none + +def instantiateDeltaValue (ci : ConstantInfo) (ls : List Level) : Expr := + ci.deltaValue?.get!.instantiateLevelParams ci.levelParams ls + +/-- If `e` is itself a constant that can be delta-reduced, returns its value with the constant's +level parameters instantiated. Unlike `unfoldDefinition`, this does not look through applications: +`e` must be a `.const`. -/ +def unfoldDefinitionCore (e : Expr) : RecM (Option Expr) := do + let .const _ ls := e | return none + let env ← getEnv + let some d := isDelta env e | return none + unless 0 < ls.length do return some (instantiateDeltaValue d ls) + if let some r := (← get).unfold[e]? then return some r + let r := instantiateDeltaValue d ls + modify fun s => { s with unfold := s.unfold.insert e r } + return some r + +/-- Unfolds the definition at the head of the application `e` (or `e` itself if it is not an +application). -/ +def unfoldDefinition (e : Expr) : RecM (Option Expr) := do + if e.isApp then + let f0 := e.getAppFn + let some f ← unfoldDefinitionCore f0 | return none + let rargs := e.getAppRevArgs + return f.mkAppRevRange 0 rargs.size rargs + else + unfoldDefinitionCore e + +def reduceNative (_env : Environment) (e : Expr) : Except Exception (Option Expr) := do + let .app f (.const c _) := e | return none + if Expr.structuralEq f (.const ``reduceBool []) then + throw <| .other s!"the named specification does not support 'reduceBool {c}' reduction" + else if Expr.structuralEq f (.const ``reduceNat []) then + throw <| .other s!"the named specification does not support 'reduceNat {c}' reduction" + return none + +def rawNatLitExt? (e : Expr) : Option Nat := if e == .natZero then some 0 else e.rawNatLit? + +/-- Reduces the application `f a b` to a Nat literal if `a` and `b` can be reduced to Nat literals. + +`checkSize` bounds the size of the result, for the operations that can grow a numeral without +bound when iterated. Their operands are already bounded, so computing the result before checking +it is cheap. + +Note: `f` should have an (efficient) external implementation. -/ +def reduceBinNatOp (f : Nat → Nat → Nat) (a b : Expr) (checkSize := false) : RecM (Option Expr) := do + let some v1 := rawNatLitExt? (← whnf a) | return none + let some v2 := rawNatLitExt? (← whnf b) | return none + checkNatSizeIf checkSize (natSizeInBytes (f v1 v2)) + return some <| .lit <| .natVal <| f v1 v2 + +/-- Reduces `Nat.pow a b`. Unlike the other binary operations this bounds the result *before* +computing it, since a small exponent already denotes an unrepresentable numeral. -/ +def reducePow (a b : Expr) : RecM (Option Expr) := do + let some base := rawNatLitExt? (← whnf a) | return none + let some exp := rawNatLitExt? (← whnf b) | return none + checkPowSize base exp + return some <| .lit <| .natVal <| Nat.pow base exp + +/-- Reduces `Nat.shiftLeft a b`, bounding the result before computing it. -/ +def reduceShiftLeft (a b : Expr) : RecM (Option Expr) := do + let some v := rawNatLitExt? (← whnf a) | return none + let some shift := rawNatLitExt? (← whnf b) | return none + checkShiftLeftSize v shift + return some <| .lit <| .natVal <| v <<< shift + +/-- Reduces the application `f a b` to a boolean expression if `a` and `b` can be reduced to Nat +literals. + +Note: `f` should have an (efficient) external implementation. -/ +def reduceBinNatPred (f : Nat → Nat → Bool) (a b : Expr) : RecM (Option Expr) := do + let some v1 := rawNatLitExt? (← whnf a) | return none + let some v2 := rawNatLitExt? (← whnf b) | return none + return toExpr <| f v1 v2 + +/-- Reduces `e` to a literal if possible, where the unary operation `Nat.succ` and the binary +operations and predicates with an external implementation may be applied: `Nat.add`, `Nat.sub`, +`Nat.mul`, `Nat.pow`, `Nat.gcd`, `Nat.mod`, `Nat.div`, `Nat.land`, `Nat.lor`, `Nat.xor`, +`Nat.shiftLeft`, `Nat.shiftRight` produce a `Nat` literal, while the predicates `Nat.beq` and +`Nat.ble` produce a `Bool` literal. -/ +def reduceNat (e : Expr) : RecM (Option Expr) := do + let nargs := e.getAppNumArgs + if nargs == 1 then + let f := e.appFn! + if Expr.structuralEq f (.const ``Nat.succ []) then + let some v := rawNatLitExt? (← whnf e.appArg!) | return none + checkNatSize (natSizeInBytes (v + 1)) + return some <| .lit <| .natVal <| v + 1 + else if nargs == 2 then + let .app (.app (.const f _) a) b := e | return none + if f == ``Nat.add then return ← reduceBinNatOp Nat.add a b (checkSize := true) + if f == ``Nat.sub then return ← reduceBinNatOp Nat.sub a b (checkSize := true) + if f == ``Nat.mul then return ← reduceBinNatOp Nat.mul a b (checkSize := true) + if f == ``Nat.pow then return ← reducePow a b + if f == ``Nat.gcd then return ← reduceBinNatOp Nat.gcd a b + if f == ``Nat.mod then return ← reduceBinNatOp Nat.mod a b + if f == ``Nat.div then return ← reduceBinNatOp Nat.div a b + if f == ``Nat.beq then return ← reduceBinNatPred Nat.beq a b + if f == ``Nat.ble then return ← reduceBinNatPred Nat.ble a b + if f == ``Nat.land then return ← reduceBinNatOp Nat.land a b + if f == ``Nat.lor then return ← reduceBinNatOp Nat.lor a b + if f == ``Nat.xor then return ← reduceBinNatOp Nat.xor a b + if f == ``Nat.shiftLeft then return ← reduceShiftLeft a b + if f == ``Nat.shiftRight then return ← reduceBinNatOp Nat.shiftRight a b + return none + +@[inherit_doc whnf] +def whnf' (e : Expr) : RecM Expr := do + -- Do not cache easy cases + match e with + | .bvar .. | .sort .. | .mvar .. | .forallE .. | .lit .. => return e + | .mdata _ e => return ← whnf' e + | .fvar id => + if !isLetFVar (← getLCtx) id then + return e + | .lam .. | .app .. | .const .. | .letE .. | .proj .. => pure () + -- check cache + if let some r := (← get).whnfCache[e]? then + return r + let rec loop t + | 0 => throw .deterministicTimeout + | fuel+1 => do + let env ← getEnv + let t ← whnfCore' t + if let some t ← reduceNative env t then return t + if let some t ← reduceNat t then return t + let some t ← unfoldDefinition t | return t + loop t fuel + let ctx ← readThe Context + let r ← loop e <| if ctx.eagerReduce then ctx.fuel.whnfEager else ctx.fuel.whnf + modify fun s => { s with whnfCache := s.whnfCache.insert e r } + return r + +/-- If `t` and `s` are lambda expressions, checks that their domains are defeq and recurses on the +bodies, substituting in a new free variable for that binder (this substitution is delayed for +efficiency purposes using the `subst` parameter). Otherwise, does a normal defeq check. -/ +def isDefEqLambda (t s : Expr) (subst : Array Expr := #[]) : RecM Bool := + match t, s with + | .lam _ tDom tBody _, .lam name sDom sBody bi => do + let sType ← if tDom == sDom then pure none else + let sType := sDom.instantiateRev subst + let tType := tDom.instantiateRev subst + if !(← isDefEq tType sType) then return false + pure (some sType) + if tBody.hasLooseBVars || sBody.hasLooseBVars then + let sType := sType.getD (sDom.instantiateRev subst) + withLocalDecl name bi sType fun fv => do + isDefEqLambda tBody sBody (subst.push fv) + else + isDefEqLambda tBody sBody (subst.push default) + | t, s => isDefEq (t.instantiateRev subst) (s.instantiateRev subst) + +/-- If `t` and `s` are for-all expressions, checks that their domains are defeq and recurses on the +bodies, substituting in a new free variable for that binder (this substitution is delayed for +efficiency purposes using the `subst` parameter). Otherwise, does a normal defeq check. -/ +def isDefEqForall (t s : Expr) (subst : Array Expr := #[]) : RecM Bool := + match t, s with + | .forallE _ tDom tBody _, .forallE name sDom sBody bi => do + let sType ← if tDom == sDom then pure none else + let sType := sDom.instantiateRev subst + let tType := tDom.instantiateRev subst + if !(← isDefEq tType sType) then return false + pure (some sType) + if tBody.hasLooseBVars || sBody.hasLooseBVars then + let sType := sType.getD (sDom.instantiateRev subst) + withLocalDecl name bi sType fun fv => + isDefEqForall tBody sBody (subst.push fv) + else + isDefEqForall tBody sBody (subst.push default) + | t, s => isDefEq (t.instantiateRev subst) (s.instantiateRev subst) + +/-- Decides definitional equality of `t` and `s` in the cases that can be settled without +reduction, returning `.undef` to defer to the calling function otherwise. + +It returns `.true` if they are α-equivalent or have previously been checked for definitional +equality, and otherwise decides two sorts by level equivalence and two literals by equality, +returning `.false` where these disagree. Two lambdas or two for-alls are handed to +`isDefEqLambda`/`isDefEqForall`, which may return either. All remaining cases — including two +constants, two free variables, two applications and two projections — are deferred. -/ +def quickIsDefEq (t s : Expr) : RecM LBool := do + -- cheap structural check, plus the positive `isDefEq` cache + if t == s || succeededBefore (← get).success t s then return .true + match t, s with + | .lam .., .lam .. => toLBoolM <| isDefEqLambda t s + | .forallE .., .forallE .. => toLBoolM <| isDefEqForall t s + | .sort a1, .sort a2 => pure (a1.isEquiv' a2).toLBool + | .mdata _ a1, .mdata _ a2 => toLBoolM <| isDefEq a1 a2 + | .mvar .., .mvar .. => unreachable! + | .lit a1, .lit a2 => pure (a1 == a2).toLBool + | _, _ => return .undef + +/-- Assuming that `t` and `s` have the same function heads, returns true if they are applications +with definitionally equal arguments (in which case they are defeq), and false otherwise (deferring +further defeq checking to caller). -/ +def isDefEqArgs (t s : Expr) : RecM Bool := do + match t, s with + | .app tf ta, .app sf sa => + if !(← isDefEq ta sa) then return false + isDefEqArgs tf sf + | .app .., _ | _, .app .. => return false + | _, _ => return true + +/-- Assuming `t` and `s` are WHNF, checks if they are defeq on account of `t` being an η-expansion +of `s`. + +Assuming that `s` has a function type `(x : A) → B x`, it η-expands to `fun (x : A) => s x` +(which it is definitionally equal to by the η rule). -/ +def tryEtaExpansionCore (t s : Expr) : RecM Bool := do + if t.isLambda && !s.isLambda then + let .forallE name ty _ bi ← whnf (← inferType s) | return false + isDefEq t (.lam name ty (.app s (.bvar 0)) bi) + else return false + +@[inherit_doc tryEtaExpansionCore] +def tryEtaExpansion (t s : Expr) : RecM Bool := + tryEtaExpansionCore t s <||> tryEtaExpansionCore s t + +/-- One field comparison in the structure-eta fast path. Naming the +callback keeps the executable range loop and its verification aligned without +depending on proof terms synthesized by `for` notation. -/ +def tryEtaStructFieldStep (t : Expr) (induct : Name) (numParams : Nat) + (args : Array Expr) (i : Nat) (_ : i ∈ [numParams:args.size]) + (_ : Option Bool × PUnit) : + RecM (ForInStep (Option Bool × PUnit)) := do + let b ← isDefEq (.proj induct (i - numParams) t) args[i] + if b = true then + pure (.yield ⟨none, PUnit.unit⟩) + else + pure (.done ⟨some false, PUnit.unit⟩) + +/-- Assuming `t` and `s` in WHNF, checks if they are defeq on account of `s` being defeq to the +struct-η-expansion of `t`. + +Assuming that `t` has a non-recursive structure type `S` with constructor `S.mk` and projections +`pᵢ`, it struct-η-expands to `S.mk (p₁ t) ... (pₙ t)` (which it is definitionally equal to by the +struct-η rule). -/ +def tryEtaStructCore (t s : Expr) : RecM Bool := do + let .const f _ := s.getAppFn | return false + let env ← getEnv + let .ctorInfo fInfo ← env.get f | return false + unless s.getAppNumArgs == fInfo.numParams + fInfo.numFields do return false + unless env.isNonRecStructure fInfo.induct do return false + unless ← isDefEq (← inferType t) (← inferType s) do return false + let args := s.getAppArgs + -- since `t` is in WHNF, and assuming it is not a constructor application, this projection + -- cannot reduce (so we are directly checking if `s` is defeq to the struct-η-expansion of `t`) + let r ← forIn' [fInfo.numParams:args.size] ⟨none, PUnit.unit⟩ + (tryEtaStructFieldStep t fInfo.induct fInfo.numParams args) + match r.1 with + | none => return true + | some b => return b + +@[inherit_doc tryEtaStructCore] +def tryEtaStruct (t s : Expr) : RecM Bool := + -- when `t` and `s` are both constructor applications, `isDefEqApp` has already compared their + -- arguments and returned false, and the projections in `tryEtaStructCore` reduce back to those + -- same arguments, so both calls below merely redo that work. The kernel has the same redundancy. + tryEtaStructCore t s <||> tryEtaStructCore s t + +/-- Checks if applications `t` and `s` (should be WHNF) are defeq on account of their function heads +and arguments being defeq. -/ +def isDefEqApp (t s : Expr) : RecM Bool := do + unless t.isApp && s.isApp do return false + t.withApp fun tf tArgs => + s.withApp fun sf sArgs => do + if _h : tArgs.size = sArgs.size then + unless ← isDefEq tf sf do return false + let rec loop i := do + if _h : i < tArgs.size then + unless ← isDefEq tArgs[i] sArgs[i] do return false + loop (i+1) + else return true + loop 0 + else return false + +/-- Checks if `t` and `s` are definitionally equivalent according to proof irrelevance (that is, +they are proofs of the same proposition). -/ +def isDefEqProofIrrel (t s : Expr) : RecM LBool := do + let tType ← inferType t + if !(← isProp tType) then return .undef + toLBoolM <| isDefEq tType (← inferType s) + +def failedBefore (failure : Std.HashSet (Expr × Expr)) (t s : Expr) : Bool := + if t.hash < s.hash then + failure.contains (t, s) + else if t.hash > s.hash then + failure.contains (s, t) + else + failure.contains (t, s) || failure.contains (s, t) + +def cacheFailure (t s : Expr) : M Unit := do + let k := if t.hash ≤ s.hash then (t, s) else (s, t) + modify fun st => { st with failure := st.failure.insert k } + +def tryUnfoldProjApp (e : Expr) : RecM (Option Expr) := do + let f := e.getAppFn + if !f.isProj then return none + let e' ← whnfCore e + return if e' != e then e' else none + +/-- Performs a single step of δ-reduction on `tn`, `sn`, or both (according to optimizations) +followed by weak-head normalization (without further δ-reduction). Returns `.bool` if the resulting +terms are settled by `quickIsDefEq`, or if they are applications of the same defined constant with +defeq args. Otherwise returns `.continue`, indicating to the calling `lazyDeltaReduction` that +δ-reduction is to be continued. + +If neither side has a δ-reducible head, returns `.unknown` with the terms unchanged, leaving further +defeq-checking to `isDefEqCore'`. Note that these are weak-head normal forms with respect to +`cheapProj := true`, so a projection at the head may still be reducible. -/ +def lazyDeltaReductionStep (tn sn : Expr) : RecM ReductionStatus := do + let env ← getEnv + let delta e := do whnfCore (← unfoldDefinition e).get! (cheapProj := true) + let cont tn sn := + return match ← quickIsDefEq tn sn with + | .undef => .continue tn sn + | .true => .bool true + | .false => .bool false + match isDelta env tn, isDelta env sn with + | none, none => return .unknown tn sn + | some _, none => + -- `sn` was normalized with `cheapProj := true`, so a projection at its head may not have been + -- reduced; `tryUnfoldProjApp` retries it with the struct argument fully normalized + if let some sn' ← tryUnfoldProjApp sn then + cont tn sn' + else + cont (← delta tn) sn + | none, some _ => + if let some tn' ← tryUnfoldProjApp tn then + cont tn' sn + else + cont tn (← delta sn) + | some dt, some ds => + let ht := dt.hints + let hs := ds.hints + if ht.lt' hs then + cont tn (← delta sn) + else if hs.lt' ht then + cont (← delta tn) sn + else + if tn.isApp && sn.isApp && ptrEqConstantInfo dt ds && dt.hints.isRegular + && !failedBefore (← get).failure tn sn + then + if Level.isEquivList tn.getAppFn.constLevels! sn.getAppFn.constLevels! then + if ← isDefEqArgs tn sn then + return .bool true + cacheFailure tn sn + cont (← delta tn) (← delta sn) + +@[inline] def isNatZero (t : Expr) : Bool := + t == .natZero || t matches .lit (.natVal 0) + +def isNatSuccOf? : Expr → Option Expr + | .lit (.natVal (n+1)) => return .lit (.natVal n) + | .app (.const ``Nat.succ _) e => return e + | _ => none + +/-- Returns `.true` if `t` and `s` are both zero, either as a literal or as `Nat.zero`. If they are +both successors of natural numbers `t'` and `s'`, either as literals or `Nat.succ` applications, +checks that `t'` and `s'` are definitionally equal. Otherwise, defers to the calling function. -/ +def isDefEqOffset (t s : Expr) : RecM LBool := do + if isNatZero t && isNatZero s then + return .true + match isNatSuccOf? t, isNatSuccOf? s with + | some t', some s' => toLBoolM <| isDefEqCore t' s' + | _, _ => return .undef + +/-- Repeatedly δ-reduces the `cheapProj := true` weak-head normal forms `tn` and `sn` until the +question is settled. Returns `.bool` if: +- they are both zero or both natural number successors (as literals or `Nat.succ` applications) +- one of them can be converted to a natural number/boolean literal +- a `lazyDeltaReductionStep` settles them + +Otherwise returns `.unknown` with the reduced terms, deferring to the calling function. Throws +`.deterministicTimeout` after `FuelConfig.lazyDelta` steps. -/ +def lazyDeltaReduction (tn sn : Expr) : RecM ReductionStatus := do + loop tn sn (← readThe Context).fuel.lazyDelta +where + loop tn sn + | 0 => throw .deterministicTimeout + | fuel+1 => do + let r ← isDefEqOffset tn sn + if r != .undef then return .bool (r == .true) + if !tn.hasFVar && !sn.hasFVar || (← readThe Context).eagerReduce then + if let some tn' ← reduceNat tn then + return .bool (← isDefEqCore tn' sn) + else if let some sn' ← reduceNat sn then + return .bool (← isDefEqCore tn sn') + let env ← getEnv + if let some tn' ← reduceNative env tn then + return .bool (← isDefEqCore tn' sn) + else if let some sn' ← reduceNative env sn then + return .bool (← isDefEqCore tn sn') + match ← lazyDeltaReductionStep tn sn with + | .continue tn sn => loop tn sn fuel + | r => return r + +/-- If `t` is a string literal and `s` is a `String.ofList` application, checks that they are defeq +after expanding `t` into a `String.ofList` application of an explicit character list. Otherwise, +defers to the calling function. -/ +def tryStringLitExpansionCore (t s : Expr) : RecM LBool := do + let .lit (.strVal st) := t | return .undef + let .app sf _ := s | return .undef + unless sf == .const ``String.ofList [] do return .undef + toLBoolM <| isDefEqCore (.strLitToConstructor st) s + +@[inherit_doc tryStringLitExpansionCore] +def tryStringLitExpansion (t s : Expr) : RecM LBool := do + match ← tryStringLitExpansionCore t s with + | .undef => tryStringLitExpansionCore s t + | r => return r + +/-- Checks if `t` and `s` are defeq on account of both being of a unit type (a type with one +constructor without any fields or indices). -/ +def isDefEqUnitLike (t s : Expr) : RecM Bool := do + let tType ← whnf (← inferType t) + let .const I _ := tType.getAppFn | return false + let env ← getEnv + let .inductInfo { isRec := false, ctors := [c], numIndices := 0, .. } ← env.get I + | return false + let .ctorInfo { numFields := 0, .. } ← env.get c | return false + isDefEqCore tType (← inferType s) + +@[inherit_doc isDefEqCore] +def isDefEqCore' (t s : Expr) : RecM Bool := do + let r ← quickIsDefEq t s + if r != .undef then return r == .true + + if (!t.hasFVar || (← readThe Context).eagerReduce) && s.isConstOf ``true then + if (← whnf t).isConstOf ``true then return true + + let tn ← whnfCore t (cheapProj := true) + let sn ← whnfCore s (cheapProj := true) + + if !(ptrEqExpr tn t && ptrEqExpr sn s) then + let r ← quickIsDefEq tn sn + if r != .undef then return r == .true + + let r ← isDefEqProofIrrel tn sn + if r != .undef then return r == .true + + match ← lazyDeltaReduction tn sn with + | .continue .. => unreachable! + | .bool b => return b + | .unknown tn sn => + + match tn, sn with + | .const tf tl, .const sf sl => + if tf == sf && Level.isEquivList tl sl then return true + | .fvar tv, .fvar sv => if tv == sv then return true + | .proj _ ti te, .proj _ si se => + -- optimized by the previous reduction functions using `cheapProj := true` + if ti == si then if ← isDefEq te se then return true + | _, _ => pure () + + -- the previous reduction functions used `cheapProj := true`, so we may not have a complete WHNF + let tnn ← whnfCore tn + let snn ← whnfCore sn + if !(ptrEqExpr tnn tn && ptrEqExpr snn sn) then + -- if projection reduced, need to re-run (as we may not have a WHNF) + return ← isDefEqCore tnn snn + + -- tn and sn are both in WHNF + if ← isDefEqApp tn sn then return true + if ← tryEtaExpansion tn sn then return true + if ← tryEtaStruct tn sn then return true + let r ← tryStringLitExpansion tn sn + if r != .undef then return r == .true + if ← isDefEqUnitLike tn sn then return true + return false + +end Inner + +open Inner + +def Methods.withFuel : Nat → Methods + | 0 => + { isDefEqCore := fun _ _ => throw .deepRecursion + whnfCore := fun _ _ => throw .deepRecursion + whnf := fun _ => throw .deepRecursion + inferType := fun _ _ => throw .deepRecursion } + | n + 1 => + { isDefEqCore := fun t s => isDefEqCore' t s (withFuel n) + whnfCore := fun e p => whnfCore' e p (withFuel n) + whnf := fun e => whnf' e (withFuel n) + inferType := fun e i => inferType' e i (withFuel n) } + +/-- Runs `x` with a limit on the recursion depth, taken from `FuelConfig.recDepth`. -/ +def RecM.run (x : RecM α) : M α := do x (Methods.withFuel (← readThe Context).fuel.recDepth) + +def RecM.runTermElab (x : RecM α) (safety := DefinitionSafety.safe) : Elab.Term.TermElabM α := + x.run.runTermElab safety + +instance : MonadLift RecM Elab.Term.TermElabM := ⟨RecM.runTermElab⟩ + +@[inherit_doc whnf'] +def whnf (e : Expr) : M Expr := (Inner.whnf e).run + +def whnfCore (e : Expr) : M Expr := (Inner.whnfCore e).run + +def unfoldDefinition (e : Expr) : M Expr := return (← (Inner.unfoldDefinition e).run).getD e + +/-- Infers the type of expression `e`. Note that this uses the optimization `inferOnly := true`, and +so should only be used for the purpose of type inference on terms that are known to be well-typed. +To typecheck terms for the first time, use `checkType`. -/ +def inferType (e : Expr) : M Expr := (Inner.inferType e).run + +/-- Infers the type of expression `e` and checks that `e` is well-typed according to Lean's typing +judgment. + +Use `inferType` to infer type alone. -/ +def checkType (e : Expr) : M Expr := (Inner.inferType e (inferOnly := false)).run + +@[inherit_doc isDefEqCore] +def isDefEq (t s : Expr) : M Bool := (Inner.isDefEq t s).run + +@[inherit_doc Inner.isProp] +def isProp (t : Expr) : M Bool := (Inner.isProp t).run + +@[inherit_doc ensureSortCore] +def ensureSort (t : Expr) (s := t) : M Expr := (ensureSortCore t s).run + +@[inherit_doc ensureForallCore] +def ensureForall (t : Expr) (s := t) : M Expr := (ensureForallCore t s).run + +/-- Ensures that `e` is a type/proposition. If it is not, throws an error. -/ +def ensureType (e : Expr) : M Expr := do ensureSort (← inferType e) e + +def etaExpand (e : Expr) : M Expr := + let rec loop fvars + | .lam name dom body bi => do + let d := dom.instantiateRev fvars + withLocalDecl name bi d fun fv => do + let fvars := fvars.push fv + loop fvars body + | it => do + let itType ← whnf <| ← inferType <| it.instantiateRev fvars + if !itType.isForall then return e + let rec loop2 fvars args + | 0, _ => throw .deepRecursion + | fuel + 1, .forallE name dom body bi => do + let d := dom.instantiateRev fvars + withLocalDecl name bi d fun arg => do + let fvars := fvars.push arg + let args := args.push arg + loop2 fvars args fuel <| ← whnf <| body.instantiate1 arg + | _, it => return (← getLCtx).mkLambda fvars (mkAppN it args) + loop2 fvars #[] (← readThe Context).fuel.etaExpand itType + loop #[] e + +-- for testing: + +-- example : "hi" = sorry := by +-- run_tac +-- let env ← Lean.getEnv +-- let lctx ← getLCtx +-- let (_, lhs, _) := (← Elab.Tactic.getMainTarget).eq?.get! +-- logInfo lhs +-- let ty ← show M _ from withReader ({· with env := .empty `h}) (inferType lhs) +-- logInfo ty +-- let sort ← inferType ty +-- logInfo sort diff --git a/Ix/Theory/Named/SingletonParity.lean b/Ix/Theory/Named/SingletonParity.lean new file mode 100644 index 000000000..32a76e7d4 --- /dev/null +++ b/Ix/Theory/Named/SingletonParity.lean @@ -0,0 +1,186 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.InductiveFixtures + +open Ix.Theory (VLevel) + +/-! +# Complete singleton-family parity inputs + +This module is the Theory-side inventory for Spec-07. Each row owns the exact +raw declaration together with the one checked generation artifact consumed by +the kernel differential and environment-replay matrix. `Unit` is represented +honestly by the kernel's polymorphic `PUnit` family; the reducible `Unit` +definition itself is pinned on the Verify side. +-/ + +namespace Ix.Theory.Named.InductiveFixtures + +open VInductDecl + +private def permC07 (constant : VConstant) (levels : List VLevel) : + VConstant := + ⟨constant.uvars, constant.type.instL levels⟩ + +/-! ## Checked artifacts for the pre-existing fixed rows -/ + +def boolChecked : boolDecl.Checked := boolDecl.checked?.get (by decide) + +def boolGenerationChecked : GenerationChecked boolDecl := + (identityGeneration? boolDecl).get (by decide) + +def listChecked : listDecl.Checked := listDecl.checked?.get (by decide) + +def listGenerationChecked : GenerationChecked listDecl := + (identityGeneration? listDecl).get (by decide) + +def optionChecked : optionDecl.Checked := optionDecl.checked?.get (by decide) + +def optionGenerationChecked : GenerationChecked optionDecl := + (identityGeneration? optionDecl).get (by decide) + +def prodChecked : prodDecl.Checked := prodDecl.checked?.get (by decide) + +def prodGenerationChecked : GenerationChecked prodDecl := + (identityGeneration? prodDecl).get (by decide) + +def heqChecked : heqDecl.Checked := heqDecl.checked?.get (by decide) + +def heqGenerationChecked : GenerationChecked heqDecl := + (identityGeneration? heqDecl).get (by decide) + +def orGenerationChecked : GenerationChecked orDecl := + (identityGeneration? orDecl).get (by decide) + +def andGenerationChecked : GenerationChecked andDecl := + (identityGeneration? andDecl).get (by decide) + +/-! ## Fin -/ + +def finType : VInductiveType where + name := ``Fin + uvars := 0 + type := vconst(type_of% @Fin).type + ctors := [⟨vconst(type_of% @Fin.mk), ``Fin.mk⟩] + +def finDecl : VInductDecl := ⟨0, 1, [finType]⟩ + +def finChecked : finDecl.Checked := finDecl.checked?.get (by decide) + +def finGenerationChecked : GenerationChecked finDecl := + (identityGeneration? finDecl).get (by decide) + +example : finDecl.stage3 = true := rfl +example : finChecked.params = [.const ``Nat []] := rfl +example : finChecked.indices = [] := rfl +example : finChecked.resultLevel = .succ .zero := rfl +example : finChecked.elimination = .large := rfl +example : finChecked.kTarget = false := rfl +example : finChecked.constructors.length = 1 := rfl +example : finChecked.constructors[0].fields.length = 2 := rfl +example : finChecked.constructors[0].recursive = [] := rfl +example : finGenerationChecked.recursor = + vconst(type_of% @Fin.rec) := rfl + +/-! ## Vector -/ + +def vectorType : VInductiveType where + name := ``Vector + uvars := 1 + type := vconst(type_of% @Vector).type + ctors := [⟨vconst(type_of% @Vector.mk), ``Vector.mk⟩] + +def vectorDecl : VInductDecl := ⟨1, 2, [vectorType]⟩ + +def vectorChecked : vectorDecl.Checked := vectorDecl.checked?.get (by decide) + +def vectorGenerationChecked : GenerationChecked vectorDecl := + (identityGeneration? vectorDecl).get (by decide) + +example : vectorDecl.stage3 = true := rfl +example : vectorChecked.params = + [.sort (.succ (.param 0)), .const ``Nat []] := rfl +example : vectorChecked.indices = [] := rfl +example : vectorChecked.resultLevel = .succ (.param 0) := rfl +example : vectorChecked.elimination = .large := rfl +example : vectorChecked.kTarget = false := rfl +example : vectorChecked.constructors.length = 1 := rfl +example : vectorChecked.constructors[0].fields.length = 2 := rfl +example : vectorChecked.constructors[0].recursive = [] := rfl +example : vectorGenerationChecked.recursor = + permC07 (vconst(type_of% @Vector.rec)) [.param 1, .param 0] := rfl + +/-! ## One authoritative singleton artifact inventory -/ + +/-- A source-indexed singleton artifact. Merely constructing a row proves +that the public checked analyzer accepted that exact raw declaration and that +all downstream generation data came from the same checked path. -/ +structure SingletonParityArtifact where + label : Name + source : VInductDecl + generation : source.GenerationChecked + +namespace SingletonParityArtifact + +def typeName (artifact : SingletonParityArtifact) : Name := + artifact.generation.block.sourceType.name + +def constructorNames (artifact : SingletonParityArtifact) : List Name := + artifact.generation.block.sourceType.ctors.map (·.name) + +end SingletonParityArtifact + +/-- The fixed Spec-07 positive matrix, in roadmap order. The `Unit` row points +to `PUnit`, matching the actual v4.31 kernel representation rather than +inventing alias-level inductive metadata. -/ +def singletonPositiveArtifacts : List SingletonParityArtifact := + [⟨``Nat, natDecl, natGenerationChecked⟩, + ⟨``Bool, boolDecl, boolGenerationChecked⟩, + ⟨``List, listDecl, listGenerationChecked⟩, + ⟨``Option, optionDecl, optionGenerationChecked⟩, + ⟨``Prod, prodDecl, prodGenerationChecked⟩, + ⟨``Unit, punitDecl, punitGenerationChecked⟩, + ⟨``Empty, emptyDecl, emptyGenerationChecked⟩, + ⟨``Or, orDecl, orGenerationChecked⟩, + ⟨``And, andDecl, andGenerationChecked⟩, + ⟨``Eq, eqDecl, eqGenerationChecked⟩, + ⟨``HEq, heqDecl, heqGenerationChecked⟩, + ⟨``Fin, finDecl, finGenerationChecked⟩, + ⟨``Vector, vectorDecl, vectorGenerationChecked⟩, + ⟨``Acc, accDecl, accGenerationChecked⟩] + +/-- The focused non-identity normalization rows retained alongside the fixed +standard-library matrix. -/ +def singletonNormalizationArtifacts : List SingletonParityArtifact := + [⟨``AliasFormer, aliasFormerRawDecl, aliasFormerGenerationChecked⟩, + ⟨``AliasRec, aliasRecRawDecl, aliasRecGenerationChecked⟩, + ⟨``NormalizationMatrix, normalizationMatrixRawDecl, + normalizationMatrixGenerationChecked⟩, + ⟨``AnnotatedPi, annotatedPiRawDecl, annotatedPiGenerationChecked⟩, + ⟨``AnnotatedParam, annotatedParamRawDecl, + annotatedParamGenerationChecked⟩] + +example : singletonPositiveArtifacts.length = 14 := rfl +example : singletonPositiveArtifacts.map (·.label) = + [``Nat, ``Bool, ``List, ``Option, ``Prod, ``Unit, ``Empty, ``Or, ``And, + ``Eq, ``HEq, ``Fin, ``Vector, ``Acc] := rfl +example : singletonPositiveArtifacts.map (·.typeName) = + [``Nat, ``Bool, ``List, ``Option, ``Prod, ``PUnit, ``Empty, ``Or, ``And, + ``Eq, ``HEq, ``Fin, ``Vector, ``Acc] := rfl +example : singletonNormalizationArtifacts.length = 5 := rfl + +/-! +The inventory roots are trust-sensitive: pin their exact logical closure so +later fixture refactors cannot silently import a broader proof surface. +-/ + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.singletonPositiveArtifacts [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveFixtures.singletonNormalizationArtifacts [propext, Quot.sound] + +end Ix.Theory.Named.InductiveFixtures diff --git a/Ix/Theory/Named/Std/AxiomAudit.lean b/Ix/Theory/Named/Std/AxiomAudit.lean new file mode 100644 index 000000000..816ae3cbb --- /dev/null +++ b/Ix/Theory/Named/Std/AxiomAudit.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean.Elab.Command +import Lean.Util.FoldConsts + +/-! +# Exact axiom checks for named-specification proofs + +The checked sets use resolved declaration names, independent of pretty-print +width and dependency traversal order. Both missing and additional axioms fail +the check; a namespace migration cannot silently widen the recorded boundary. +-/ + +open Lean Elab Command + +namespace Ix.Theory.Named.AxiomAudit + +/-- Traverse checked declarations directly. Imported axiom summaries can +omit dependencies of mutually recursive declaration groups. -/ +def directConstants : ConstantInfo → Array Name + | .axiomInfo v => v.type.getUsedConstants + | .defnInfo v => v.type.getUsedConstants ++ v.value.getUsedConstants + | .thmInfo v => v.type.getUsedConstants ++ v.value.getUsedConstants + | .opaqueInfo v => v.type.getUsedConstants ++ v.value.getUsedConstants + | .quotInfo _ => #[] + | .ctorInfo v => v.type.getUsedConstants + | .recInfo v => v.type.getUsedConstants + | .inductInfo v => v.type.getUsedConstants ++ v.ctors + +structure State where + visited : NameSet := {} + names : Array Name := #[] + origins : Array Name := #[] + axioms : Array Name := #[] + +structure Node where + isAxiom : Bool := false + dependencies : Array Name := #[] + +/-- Direct dependencies may be reused across roots in one fixed environment. +Reachability and axiom sets are always computed afresh for each root. -/ +abbrev Cache := NameMap Node + +abbrev M := ReaderT Environment (StateM (State × Cache)) + +partial def visit (name : Name) : M Unit := do + let (state, cache) ← get + unless state.visited.contains name do + let env ← read + let (node, cache) := match cache.find? name with + | some node => (node, cache) + | none => + let node : Node := match env.checked.get.find? name with + | some info => + { isAxiom := (info matches .axiomInfo _) + dependencies := directConstants info } + | none => {} + (node, cache.insert name node) + let state := { state with + visited := state.visited.insert name + names := state.names.push name + axioms := if node.isAxiom then state.axioms.push name else state.axioms + origins := if name != ``sorryAx && node.dependencies.contains ``sorryAx then + state.origins.push name else state.origins } + set (state, cache) + node.dependencies.forM visit + +def collectCached (env : Environment) (root : Name) (cache : Cache) : State × Cache := + ((visit root).run env).run ({}, cache) |>.2 + +def collect (env : Environment) (root : Name) : State := + (collectCached env root {}).1 + +end Ix.Theory.Named.AxiomAudit + +syntax (name := guardNamedAxioms) + "#guard_named_axioms " ident " [" ident,* "]" : command + +elab_rules : command + | `(#guard_named_axioms $root:ident [$axioms:ident,*]) => do + let rootName ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo root + let expected ← axioms.getElems.mapM fun axiomSyntax => + liftCoreM <| realizeGlobalConstNoOverloadWithInfo axiomSyntax + let actual := (Ix.Theory.Named.AxiomAudit.collect (← getEnv) rootName).axioms + unless actual.qsort Name.lt == expected.qsort Name.lt do + let missing := expected.filter (!actual.contains ·) + let additional := actual.filter (!expected.contains ·) + throwError m!"axiom boundary changed for {rootName}\n\ + expected but absent: {missing}\nactual but unlisted: {additional}" + +-- Exercise both rejection directions as well as successful exact checks. +#guard_named_axioms Eq.refl [] +#guard_named_axioms propext [propext] + +-- A constructor depends on its full inductive definition, including siblings. +private inductive AuditFixture : Prop where + | plain + | withAxiom (proof : propext (Iff.rfl : True ↔ True) = rfl) + +#guard_named_axioms AuditFixture.plain [propext] + +run_cmd do + let env ← getEnv + let (first, cache) := Ix.Theory.Named.AxiomAudit.collectCached env + ``AuditFixture.plain {} + let (independent, cache) := Ix.Theory.Named.AxiomAudit.collectCached env ``Eq.refl cache + let (sibling, _) := Ix.Theory.Named.AxiomAudit.collectCached env + ``AuditFixture.withAxiom cache + unless first.axioms == #[``propext] && independent.axioms.isEmpty && + sibling.axioms == #[``propext] do + throwError "cached axiom traversal changed a root's dependency boundary" + +/-- +error: axiom boundary changed for propext +expected but absent: [] +actual but unlisted: [propext] +-/ +#guard_msgs (whitespace := lax) in +#guard_named_axioms propext [] + +/-- +error: axiom boundary changed for Eq.refl +expected but absent: [propext] +actual but unlisted: [] +-/ +#guard_msgs (whitespace := lax) in +#guard_named_axioms Eq.refl [propext] diff --git a/Ix/Theory/Named/Std/Basic.lean b/Ix/Theory/Named/Std/Basic.lean new file mode 100644 index 000000000..076320ac2 --- /dev/null +++ b/Ix/Theory/Named/Std/Basic.lean @@ -0,0 +1,269 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Batteries.CodeAction +import Batteries.Data.Array.Lemmas +import Batteries.Data.HashMap.Basic +import Batteries.Tactic.SeqFocus + +open Std + +/- +These are stdlib-shaped lemmas that live in the root namespace upstream (mathlib, or eventually +batteries/core). Declaring them under root here would make `import Mathlib` and `import Ix.Theory.Named` +conflict. + +So instead, we declare them in `namespace Ix.Theory.Named`. Consumers of this file need an +`open Ix.Theory.Named`, which is what keeps `h.length_eq`-style dot notation working. + +Beware also that `Ix.Theory.Named.List` now exists: an `open (scoped) List` under an `open Ix.Theory.Named` +resolves to it, so such opens are written `_root_.List`. +-/ +namespace Ix.Theory.Named +open List Ix.Theory.Named + +attribute [simp] Option.bind_eq_some_iff List.filterMap_cons + +theorem Option.beq_some_iff [BEq α] {a : Option α} {b : α} : + a == some b ↔ ∃ a', a = some a' ∧ a' == b := by cases a <;> simp + +protected theorem Nat.le_iff_exists_add {a b : Nat} : a ≤ b ↔ ∃ c, b = a + c := + ⟨fun h => ⟨_, (Nat.add_sub_cancel' h).symm⟩, fun ⟨_, h⟩ => h ▸ Nat.le_add_right ..⟩ + +protected theorem Nat.le_iff_exists_add' {a b : Nat} : a ≤ b ↔ ∃ c, b = c + a := by + simp [Nat.add_comm, Nat.le_iff_exists_add] + +protected theorem List.Forall₂.rfl + {R : α → α → Prop} {l : List α} (h : ∀ a ∈ l, R a a) : l.Forall₂ R l := by + induction l with + | nil => constructor + | cons _ _ ih => simp at h; exact .cons h.1 (ih h.2) + +@[simp] theorem List.forall₂_nil_left_iff {l} : Forall₂ R nil l ↔ l = nil := + ⟨fun H => by cases H; rfl, by rintro rfl; exact Forall₂.nil⟩ + +@[simp] theorem List.forall₂_nil_right_iff {l} : Forall₂ R l nil ↔ l = nil := + ⟨fun H => by cases H; rfl, by rintro rfl; exact Forall₂.nil⟩ + +theorem List.forall₂_cons_left_iff {a l u} : + Forall₂ R (a :: l) u ↔ ∃ b u', R a b ∧ Forall₂ R l u' ∧ u = b :: u' := + Iff.intro + (fun h => match u, h with | b :: u', Forall₂.cons h₁ h₂ => ⟨b, u', h₁, h₂, rfl⟩) + (fun h => match u, h with | _, ⟨_, _, h₁, h₂, rfl⟩ => Forall₂.cons h₁ h₂) + +theorem List.forall₂_cons_right_iff {b l u} : + Forall₂ R u (b :: l) ↔ ∃ a u', R a b ∧ Forall₂ R u' l ∧ u = a :: u' := + Iff.intro + (fun h => match u, h with | b :: u', Forall₂.cons h₁ h₂ => ⟨b, u', h₁, h₂, rfl⟩) + (fun h => match u, h with | _, ⟨_, _, h₁, h₂, rfl⟩ => Forall₂.cons h₁ h₂) + +theorem List.Forall₂.imp (H : ∀ a b, R a b → S a b) + {l₁ l₂} (h : Forall₂ R l₁ l₂) : Forall₂ S l₁ l₂ := by + induction h <;> constructor <;> [(apply H; assumption); assumption] + +theorem List.Forall₂.trans (H : ∀ a b c, R a b → S b c → T a c) + {l₁ l₂ l₃} (h₁ : Forall₂ R l₁ l₂) (h₂ : Forall₂ S l₂ l₃) : Forall₂ T l₁ l₃ := by + induction h₁ generalizing l₃ <;> cases h₂ <;> constructor <;> solve_by_elim + +theorem List.Forall₂.and {l₁ l₂} (h₁ : Forall₂ R l₁ l₂) (h₂ : Forall₂ S l₁ l₂) : + Forall₂ (fun x y => R x y ∧ S x y) l₁ l₂ := by induction h₁ <;> simp_all + +theorem List.Forall₂.and_mem {l₁ l₂} (H : Forall₂ R l₁ l₂) : + Forall₂ (fun x y => R x y ∧ x ∈ l₁ ∧ y ∈ l₂) l₁ l₂ := + .trans (fun _ _ _ h1 h2 => ⟨h1.1 ▸ h2.1, h1.2, h2.2⟩) + (.rfl (R := fun x y => x = y ∧ x ∈ l₁) fun _ h => ⟨rfl, h⟩) <| + .trans (T := fun x y => R x y ∧ y ∈ l₂) (fun _ _ _ h1 h2 => by exact ⟨h2.1 ▸ h1, h2.2⟩) H <| + .rfl (R := fun x y => x = y ∧ y ∈ l₂) fun _ h => ⟨rfl, h⟩ + +theorem List.Forall₂.zipWith_l {l₁ l₂} (H : ∀ a b, R a b → S a (f a b)) (h : Forall₂ R l₁ l₂) : + Forall₂ S l₁ (l₁.zipWith f l₂) := by induction h <;> simp [*] + +@[simp] theorem List.forall₂_map_left_iff {f : γ → α} : + ∀ {l u}, Forall₂ R (map f l) u ↔ Forall₂ (fun c b => R (f c) b) l u + | [], _ => by simp only [map, forall₂_nil_left_iff] + | a :: l, _ => by simp only [map, forall₂_cons_left_iff, forall₂_map_left_iff] + +@[simp] theorem List.forall₂_map_right_iff {f : γ → β} : + ∀ {l u}, Forall₂ R l (map f u) ↔ Forall₂ (fun a c => R a (f c)) l u + | _, [] => by simp only [map, forall₂_nil_right_iff] + | _, b :: u => by simp only [map, forall₂_cons_right_iff, forall₂_map_right_iff] + +theorem List.Forall₂.flip : ∀ {a b}, Forall₂ (flip R) b a → Forall₂ R a b + | _, _, .nil => .nil + | _, _, .cons h₁ h₂ => .cons h₁ (flip h₂) + +theorem List.Forall₂.forall_exists_l {l₁ l₂} (h : Forall₂ R l₁ l₂) : ∀ a ∈ l₁, ∃ b ∈ l₂, R a b := by + induction h with simp [*] | cons _ _ ih => exact fun a h => .inr (ih _ h) + +theorem List.Forall₂.forall_exists_r {l₁ l₂} (h : Forall₂ R l₁ l₂) : ∀ b ∈ l₂, ∃ a ∈ l₁, R a b := + h.flip.forall_exists_l + +theorem List.Forall₂.length_eq : ∀ {l₁ l₂}, Forall₂ R l₁ l₂ → length l₁ = length l₂ + | _, _, .nil => rfl + | _, _, .cons _ h₂ => congrArg Nat.succ <| Forall₂.length_eq h₂ + +theorem List.forall₂_eq {l₁ l₂ : List α} : Forall₂ Eq l₁ l₂ ↔ l₁ = l₂ := + ⟨fun h => by induction h <;> simp_all, (· ▸ .rfl fun _ _ => rfl)⟩ + +theorem List.Forall₂.append_of_left : ∀ {l₁ l₂ r₁ r₂}, length l₁ = length l₂ → + (Forall₂ R (l₁ ++ r₁) (l₂ ++ r₂) ↔ Forall₂ R l₁ l₂ ∧ Forall₂ R r₁ r₂) + | [], [], _, _, _ => by simp + | a::l₁, b::l₂, _, _, eq => by simp [append_of_left (Nat.succ_inj.1 eq), and_assoc] + +theorem List.Forall₂.append_of_right {l₁ l₂ r₁ r₂} (H : length r₁ = length r₂) : + Forall₂ R (l₁ ++ r₁) (l₂ ++ r₂) ↔ Forall₂ R l₁ l₂ ∧ Forall₂ R r₁ r₂ := by + refine ⟨fun h => (append_of_left ?_).1 h, fun h => (append_of_left h.1.length_eq).2 h⟩ + simpa [H] using h.length_eq + +theorem List.Forall₂.reverse : Forall₂ R l.reverse l'.reverse ↔ Forall₂ R l l' := by + induction l generalizing l' <;> cases l' <;> simp [List.Forall₂.append_of_right, and_comm, *] + +theorem List.map_id''' {f : α → α} (l : List α) (h : ∀ x ∈ l, f x = x) : map f l = l := by + induction l <;> simp_all + +theorem List.map_fst_lookup {f : α → β} [BEq β] (l : List α) (b : β) : + (l.map (fun a => (f a, a))).lookup b = l.find? fun a => b == f a := by + induction l <;> simp_all [lookup, find?] + +def List.All (P : α → Prop) : List α → Prop + | [] => True + | a::as => P a ∧ All P as + +theorem List.All.imp {P Q : α → Prop} (h : ∀ a, P a → Q a) : ∀ {l : List α}, l.All P → l.All Q + | [] => id + | _::_ => And.imp (h _) (List.All.imp h) + +theorem List.append_eq_append_of_length_le {a b c d : List α} (h : length a ≤ length c) : + a ++ b = c ++ d ↔ ∃ a', c = a ++ a' ∧ b = a' ++ d := by + rw [append_eq_append_iff, or_iff_left_iff_imp] + rintro ⟨c', rfl, rfl⟩ + rw [← Nat.add_zero c.length, length_append, + Nat.add_le_add_iff_left, Nat.le_zero, length_eq_zero_iff] at h + subst h; exact ⟨[], by simp⟩ + +@[simp] theorem List.nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l := + pairwise_reverse.trans <| by simp only [Nodup, Ne, eq_comm] + +theorem List.foldl_congr + (H : ∀ a, ∀ x ∈ l, f a x = g a x) : foldl f a l = foldl g a l := by + induction l generalizing a <;> simp_all + +theorem List.idxOf_eq_length_iff [BEq α] [LawfulBEq α] + {a : α} {l : List α} : idxOf a l = length l ↔ a ∉ l := by + induction l with + | nil => exact iff_of_true rfl not_mem_nil + | cons b l ih => + simp only [length, mem_cons, idxOf_cons] + rw [cond_eq_ite] + split <;> rename_i h <;> simp at h + · exact iff_of_false (by rintro ⟨⟩) fun H => H <| Or.inl h.symm + · simp only [Ne.symm h, false_or] + rw [← ih] + exact Nat.succ_inj + +theorem List.perm_cons_of_mem {l : List α} (h : a ∈ l) : ∃ l', l.Perm (a :: l') := by + obtain ⟨l₁, l₂, rfl⟩ := List.append_of_mem h; exact ⟨_, List.perm_middle⟩ + +instance [BEq α] [LawfulBEq α] : PartialEquivBEq α where + symm h := by simp at *; exact h.symm + trans h1 h2 := by simp at *; exact h1.trans h2 + +theorem beq_comm [BEq α] [PartialEquivBEq α] (a b : α) : (a == b) = (b == a) := + Bool.eq_iff_iff.2 ⟨PartialEquivBEq.symm, PartialEquivBEq.symm⟩ + +theorem List.mapM_eq_some {f : α → Option β} {l : List α} {l' : List β} : + l.mapM f = some l' ↔ List.Forall₂ (f · = some ·) l l' := by + induction l generalizing l' with + | nil => simp only [mapM_nil, pure, Option.some.injEq, forall₂_nil_left_iff, @eq_comm _ l'] + | cons x l ih => + simp [mapM_cons, Bind.bind, pure, Option.bind_eq_some_iff, Option.some.injEq, + forall₂_cons_left_iff, @eq_comm _ l', exists_and_left, ih] + +@[simp] theorem Option.bind_eq_none'' {o : Option α} {f : α → Option β} : + o.bind f = none ↔ ∀ a, o = some a → f a = none := by cases o <;> simp + +@[simp] theorem Option.forall_ne_some {o : Option α} : (∀ a, o ≠ some a) ↔ o = none := by + cases o <;> simp + +@[simp] theorem Option.orElse_eq_none {a : Option α} {b : Unit → Option α} : + a.orElse b = none ↔ a = none ∧ b () = none := by + cases a <;> simp [Option.orElse] + +inductive ReflTransGen (R : α → α → Prop) (a : α) : α → Prop where + | rfl : ReflTransGen R a a + | tail : ReflTransGen R a b → R b c → ReflTransGen R a c + +inductive ReflTransGen' (R : α → α → Prop) (c : α) : α → Prop where + | rfl : ReflTransGen' R c c + | head : R a b → ReflTransGen' R c b → ReflTransGen' R c a + +theorem ReflTransGen.trans + (H1 : ReflTransGen R a b) (H2 : ReflTransGen R b c) : ReflTransGen R a c := by + induction H2 with + | rfl => exact H1 + | tail h1 h2 ih => exact ih.tail h2 + +@[elab_as_elim] theorem ReflTransGen.headIndOn {P : (a : α) → ReflTransGen R a z → Prop} + (rfl : P z .rfl) + (head : ∀ {x y} (h1 : R x y) (h2 : ReflTransGen R y z), + P y h2 → P x (.trans (.tail .rfl h1) h2)) + (H : ReflTransGen R a z) : P a H := by + induction H with + | rfl => exact rfl + | tail h1 h2 ih => exact ih (head h2 .rfl rfl) fun a1 a2 => head a1 (.tail a2 h2) + +instance [BEq α] [PartialEquivBEq α] [BEq β] [PartialEquivBEq β] : PartialEquivBEq (α × β) where + symm := by simp [(· == ·)]; grind [BEq.symm] + trans := by simp [(· == ·)]; grind [BEq.trans] + +instance [BEq α] [EquivBEq α] [BEq β] [EquivBEq β] : EquivBEq (α × β) where + rfl := by simp [(· == ·)] + +instance [BEq α] [Hashable α] [LawfulHashable α] [BEq β] [Hashable β] [LawfulHashable β] : + LawfulHashable (α × β) where + hash_eq a b h := by + simp [(· == ·)] at h + simp [hash, LawfulHashable.hash_eq _ _ h.1, LawfulHashable.hash_eq _ _ h.2] + +instance [BEq α] [PartialEquivBEq α] : PartialEquivBEq (List α) where + symm := by + simp [(· == ·)]; intro a b + induction a generalizing b <;> cases b <;> simp [List.beq]; grind [BEq.symm] + trans := by + simp [(· == ·)]; intro a b c + induction a generalizing b c <;> cases b <;> simp [List.beq] + cases c <;> simp [List.beq]; grind [BEq.trans] + +instance [BEq α] [EquivBEq α] : EquivBEq (List α) where + rfl {a} := by simp [(· == ·)]; induction a <;> simp [List.beq, *] + +end Ix.Theory.Named + +namespace BitVec + +variable (n : Nat) + +instance : TransOrd (BitVec n) := + TransOrd.compareOfLessAndEq_of_antisymm_of_trans_of_total_of_not_le + BitVec.le_antisymm BitVec.le_trans BitVec.le_total BitVec.not_le + +instance : LawfulEqOrd (BitVec n) where + eq_of_compare := compareOfLessAndEq_eq_eq BitVec.le_refl BitVec.not_le |>.mp + +end BitVec + +namespace UInt64 + +variable (n : Nat) + +instance : TransOrd UInt64 := + TransOrd.compareOfLessAndEq_of_antisymm_of_trans_of_total_of_not_le + UInt64.le_antisymm UInt64.le_trans UInt64.le_total UInt64.not_le + +instance : LawfulEqOrd UInt64 where + eq_of_compare := compareOfLessAndEq_eq_eq UInt64.le_refl UInt64.not_le |>.mp + +end UInt64 diff --git a/Ix/Theory/Named/Std/Control.lean b/Ix/Theory/Named/Std/Control.lean new file mode 100644 index 000000000..b515508ac --- /dev/null +++ b/Ix/Theory/Named/Std/Control.lean @@ -0,0 +1,8 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + + +instance [Alternative m] : MonadLift Option m := ⟨fun | none => failure | some a => pure a⟩ diff --git a/Ix/Theory/Named/Std/HashMap.lean b/Ix/Theory/Named/Std/HashMap.lean new file mode 100644 index 000000000..4b24f52a2 --- /dev/null +++ b/Ix/Theory/Named/Std/HashMap.lean @@ -0,0 +1,105 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Std.Data.HashMap.Lemmas +import Lean + +namespace Std.Internal.List + +namespace Const + +def containsKey [BEq α] (a : α) : List (α × β) → Bool + | [] => false + | ⟨k, _⟩ :: l => k == a || containsKey a l + +def replaceEntry [BEq α] (k : α) (v : β) : List (α × β) → List (α × β) + | [] => [] + | ⟨k', v'⟩ :: l => bif k' == k then ⟨k, v⟩ :: l else ⟨k', v'⟩ :: replaceEntry k v l + +def insertEntry [BEq α] (k : α) (v : β) (l : List (α × β)) : List (α × β) := + bif containsKey k l then replaceEntry k v l else (k, v) :: l + +theorem insertEntry_perm_filter [BEq α] [PartialEquivBEq α] + (k : α) (v : β) {l : List (α × β)} (hl : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (insertEntry k v l).Perm <| (k, v) :: l.filter (¬k == ·.1) := by + unfold insertEntry + cases eq : containsKey k l <;> simp + · rw [List.filter_eq_self.2] + induction l <;> simp_all [containsKey, BEq.comm]; assumption + · induction l <;> simp_all [-List.pairwise_cons, containsKey, replaceEntry, List.filter, BEq.comm] + revert eq; cases h : k == _ <;> intro eq <;> simp_all + rename_i ih + · exact .trans (.cons _ ih) (.swap ..) + · rw [List.filter_eq_self.2] + intro ⟨a, b⟩ h' + have := hl.1 a b h' + refine Decidable.by_contra fun h2 => ?_ + simp at h2 + cases h2.symm.trans (BEq.congr_left h ▸ this) + +end Const + +theorem Const.containsKey_map [BEq α] (l : List ((_ : α) × β)) : + Const.containsKey k (l.map (fun x => (x.1, x.2))) = List.containsKey k l := by + induction l <;> simp [List.containsKey, Const.containsKey, *] + +theorem Const.replaceEntry_map [BEq α] (l : List ((_ : α) × β)) : + Const.replaceEntry k v (l.map (fun x => (x.1, x.2))) = + (List.replaceEntry k v l).map (fun x => (x.1, x.2)) := by + induction l <;> simp [List.replaceEntry, Const.replaceEntry, *] + cases _ == k <;> simp + +theorem Const.insertEntry_map [BEq α] (l : List ((_ : α) × β)) : + Const.insertEntry k v (l.map (fun x => (x.1, x.2))) = + (List.insertEntry k v l).map (fun x => (x.1, x.2)) := by + simp [List.insertEntry, Const.insertEntry, Const.containsKey_map, Const.replaceEntry_map] + cases List.containsKey k l <;> simp + +end Std.Internal.List + +namespace Std.DHashMap +open Std.Internal.List Internal.Raw Internal.Raw₀ + +variable [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] + +theorem insert_perm_insertEntry (m : DHashMap α β) (a b) : + (insert m a b).toList.Perm (insertEntry a b m.toList) := by + simp [toList, toList_eq_toListModel] + exact toListModel_insert (WF.out m.2) + +theorem Const.insert_perm_insertEntry (m : DHashMap α fun _ => β) (a b) : + (Const.toList (insert m a b)).Perm (Const.insertEntry a b (Const.toList m)) := by + simp [Const.toList, Const.toList_eq_toListModel_map, Const.insertEntry_map] + exact (toListModel_insert (WF.out m.2)).map _ + +end Std.DHashMap + +namespace Std.HashMap +open Internal.List + +variable [BEq α] [Hashable α] [LawfulHashable α] + +theorem insert_toList [EquivBEq α] (m : HashMap α β) : + (insert m a b).toList.Perm ((a, b) :: m.toList.filter (¬a == ·.1)) := by + refine (DHashMap.Const.insert_perm_insertEntry m.1 a b).trans ?_ + exact Const.insertEntry_perm_filter _ _ distinct_keys_toList + +theorem getElem?_eq_lookup_toList [LawfulBEq α] (m : HashMap α β) (a : α) : + m[a]? = m.toList.lookup a := by + apply Option.ext fun b => ?_ + rw [← mem_toList_iff_getElem?_eq_some] + have := distinct_keys_toList (m := m); revert this + induction m.toList <;> intro H <;> simp_all [List.lookup] + split <;> simp_all [Prod.ext_iff] + simp [eq_comm] + rw [List.lookup_eq_none_iff.2]; · simp + simp; exact H.1 + +theorem mem_of_getElem? [EquivBEq α] {m : HashMap α β} (h : m[a]? = some b) : a ∈ m := by + refine Decidable.by_contra fun h' => ?_ + cases (getElem?_eq_none h').symm.trans h + +end Std.HashMap diff --git a/Ix/Theory/Named/Std/NodupKeys.lean b/Ix/Theory/Named/Std/NodupKeys.lean new file mode 100644 index 000000000..62418056c --- /dev/null +++ b/Ix/Theory/Named/Std/NodupKeys.lean @@ -0,0 +1,45 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Batteries.Data.List.Perm +import Batteries.Tactic.SeqFocus + +namespace List +def NodupKeys (l : List (α × β)) : Prop := Nodup (l.map (·.1)) + +theorem nodupKeys_iff_pairwise {l : List (α × β)} : + NodupKeys l ↔ Pairwise (fun a b => a.1 ≠ b.1) l := pairwise_map + +theorem NodupKeys.filter {l : List (α × β)} (p : α × β → Bool) + (H : NodupKeys l) : NodupKeys (l.filter p) := pairwise_map.2 <| (pairwise_map.1 H).filter _ + +@[simp] theorem nodupKeys_cons : NodupKeys (a::l) ↔ (∀ a' ∈ l, a.1 ≠ a'.1) ∧ NodupKeys l := by + simp [nodupKeys_iff_pairwise] + +theorem Perm.nodupKeys_iff {l₁ l₂ : List (α × β)} (h : l₁ ~ l₂) : + NodupKeys l₁ ↔ NodupKeys l₂ := (h.map _).nodup_iff + +theorem Perm.lookup_eq [BEq α] [LawfulBEq α] + {l₁ l₂ : List (α × β)} (h : l₁ ~ l₂) (nd : l₁.NodupKeys) : l₁.lookup a = l₂.lookup a := by + induction h with + | nil => rfl + | cons _ _ ih => simp [lookup]; split <;> [rfl; exact ih (pairwise_cons.1 nd).2] + | swap _ h ih => + simp at nd + simp [lookup]; split <;> split <;> rename_i h1 _ h2 <;> try rfl + simp at h1 h2; cases nd.1.1 (by rw [← h1, h2]) + | trans h1 _ ih1 ih2 => exact (ih1 nd).trans (ih2 (h1.nodupKeys_iff.1 nd)) + +theorem NodupKeys.lookup_eq_some [BEq α] [LawfulBEq α] + {l : List (α × β)} (nd : l.NodupKeys) : l.lookup a = some b ↔ (a, b) ∈ l := by + induction l with + | nil => simp + | cons p l ih => + let (a', b') := p + simp [lookup] at nd ⊢; split <;> rename_i h + · simp at h; subst a'; simp [eq_comm] + exact (nomatch nd.1 _ _ · rfl) + · simp at h; simp [h, ih nd.2] diff --git a/Ix/Theory/Named/Std/Ord.lean b/Ix/Theory/Named/Std/Ord.lean new file mode 100644 index 000000000..ba02e49f8 --- /dev/null +++ b/Ix/Theory/Named/Std/Ord.lean @@ -0,0 +1,58 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Init.Data.Order.Ord + +/-! +A device for proving `Std.TransCmp` for comparisons defined by *lexicographic products*, used for +`Lean.Name.cmp` in `Ix.Theory.Named.Verify.Name` and for the level order in `Ix.Theory.Named.Verify.NormLt`. + +Transitivity of a lexicographic product needs more than transitivity of its components: when the +first components compare `.eq` one has to know they compare `.eq` *in both directions* before the +second components can be consulted. Recursive comparisons therefore do not prove `isLE_trans` at a +triple `(a, b, c)` from `isLE_trans` at the sub-triple alone; one needs its rotations too. `Rot` +below packages the three rotations, which is exactly the statement that goes through the induction. +-/ + +namespace Ix.Theory.Named +open Std + +/-- The three rotations of transitivity for a comparison at a triple `a`, `b`, `c`, where +`x = cmp a b`, `y = cmp b c`, `z = cmp a c`. Note that the second and third components are the +first one at the rotated triples `(c, a, b)` and `(b, c, a)`, rewritten with `Ordering.swap`. -/ +def Rot (x y z : Ordering) : Prop := + (x.isLE → y.isLE → z.isLE) ∧ + (z.swap.isLE → x.isLE → y.swap.isLE) ∧ + (y.isLE → z.swap.isLE → x.swap.isLE) + +/-- Lexicographic products satisfy `Rot` if the components do. The second component's rotations +are only required when the first components are all `.eq`; this matters when the second component +is a comparison that is only meaningful where the first component does not already decide, as for +the level order, whose structural component compares unrelated constructors as `.eq`. -/ +theorem Rot.then' : Rot x y z → (x = .eq → y = .eq → z = .eq → Rot x' y' z') → + Rot (x.then x') (y.then y') (z.then z') := by + cases x <;> cases y <;> simp_all [Rot]; cases z <;> simp + +theorem Rot.then {x y z x' y' z' : Ordering} + (R : Rot x y z) (R' : Rot x' y' z') : Rot (x.then x') (y.then y') (z.then z') := + R.then' fun _ _ _ => R' + +/-- Any `TransCmp` gives `Rot` at every triple: the rotations are `isLE_trans` at the rotated +triples, rewritten with `OrientedCmp.eq_swap`. -/ +theorem Rot.of_transCmp {α} {cmp : α → α → Ordering} [TransCmp cmp] (a b c : α) : + Rot (cmp a b) (cmp b c) (cmp a c) := by + refine ⟨fun h₁ h₂ => TransCmp.isLE_trans h₁ h₂, fun h₁ h₂ => ?_, fun h₁ h₂ => ?_⟩ <;> + rw [← OrientedCmp.eq_swap (cmp := cmp)] at * <;> + exact TransCmp.isLE_trans h₁ h₂ + +/-- `Rot` at every triple, plus orientedness, is exactly `TransCmp`. -/ +theorem TransCmp.of_rot {α} {cmp : α → α → Ordering} + (swap : ∀ a b : α, cmp a b = (cmp b a).swap) + (rot : ∀ a b c : α, Rot (cmp a b) (cmp b c) (cmp a c)) : TransCmp cmp where + eq_swap := swap .. + isLE_trans h₁ h₂ := (rot ..).1 h₁ h₂ + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Std/PersistentHashMap.lean b/Ix/Theory/Named/Std/PersistentHashMap.lean new file mode 100644 index 000000000..b5c3cff01 --- /dev/null +++ b/Ix/Theory/Named/Std/PersistentHashMap.lean @@ -0,0 +1,48 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Data.SMap +import Std.Data.HashMap.Lemmas +import Ix.Theory.Named.Verify.Axioms + +namespace Lean.PersistentHashMap + +@[simp] theorem toList'_empty [BEq α] [Hashable α] : + (.empty : PersistentHashMap α β).toList' = [] := by + have this n : @Node.toList' α β (.entries ⟨.replicate n .null⟩) = [] := by + simp [Node.toList'] + induction n <;> simp [*, List.replicate_succ] + apply this + +@[simp] theorem toList'_empty' [BEq α] [Hashable α] : + ({} : PersistentHashMap α β).toList' = [] := toList'_empty + +theorem find?_isSome {α β} [BEq α] [Hashable α] + (m : PersistentHashMap α β) (a : α) : m.contains a = (m.find? a).isSome := findAux_isSome .. + +theorem WF.nodupKeys [BEq α] [Hashable α] + [LawfulBEq α] [LawfulHashable α] + {m : PersistentHashMap α β} (h : WF m) : m.toList'.NodupKeys := by + induction h with + | empty => simp; exact .nil + | insert h1 ih => + refine (h1.toList'_insert ..).nodupKeys_iff.2 (List.nodupKeys_cons.2 ⟨?_, ih.filter _⟩) + rintro _ h3 rfl + simpa using (List.mem_filter.1 h3).2 + +variable [BEq α] [LawfulBEq α] [Hashable α] [LawfulHashable α] in +theorem WF.find?_insert {s : PersistentHashMap α β} (h : s.WF) : + (s.insert k v).find? x = if k == x then some v else s.find? x := by + rw [h.insert.find?_eq, h.find?_eq, BEq.comm, + (h.toList'_insert ..).lookup_eq h.insert.nodupKeys, List.lookup] + cases eq : x == k <;> simp + induction s.toList' with + | nil => rfl + | cons kv l ih => + simp [List.filter]; split <;> simp [List.lookup, *] + split <;> [skip; rfl] + rename_i h1 _ h2 + simp at h1 h2; simp [h1, h2] at eq diff --git a/Ix/Theory/Named/Std/SMap.lean b/Ix/Theory/Named/Std/SMap.lean new file mode 100644 index 000000000..592aacf7d --- /dev/null +++ b/Ix/Theory/Named/Std/SMap.lean @@ -0,0 +1,83 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Data.SMap +import Std.Data.HashMap.Lemmas +import Ix.Theory.Named.Std.HashMap +import Ix.Theory.Named.Std.PersistentHashMap + +namespace Lean.SMap + +variable [BEq α] [Hashable α] +structure WF (s : SMap α β) where + map₂ : s.map₂.WF + stage : s.stage₁ → s.map₂ = .empty + disjoint : s.map₂.contains a → ¬a ∈ s.map₁ + +theorem WF.empty : WF ({} : SMap α β) := ⟨.empty, fun _ => rfl, by simp⟩ + +protected nonrec theorem WF.insert [LawfulBEq α] [LawfulHashable α] {s : SMap α β} + (h : s.WF) (k : α) (v : β) (hn : s.find? k = none) : (s.insert k v).WF := by + unfold insert; split + · refine ⟨h.map₂, h.stage, fun _ h' => ?_⟩ + have := h.stage + simp_all [find?, PersistentHashMap.find?_isSome, PersistentHashMap.WF.empty.find?_eq] + · refine ⟨h.map₂.insert .., nofun, fun h1 => ?_⟩ + simp_all [PersistentHashMap.find?_isSome, h.map₂.find?_insert] + revert ‹_›; split + · simp_all [find?] + · exact h.disjoint ∘ by simp [PersistentHashMap.find?_isSome] + +variable [LawfulBEq α] [LawfulHashable α] in +theorem WF.find?_insert {s : SMap α β} (h : s.WF) : + (s.insert k v).find? x = if k == x then some v else s.find? x := by + unfold insert; split <;> simp [find?] + · exact Std.HashMap.getElem?_insert (α := α) + · rw [h.map₂.find?_insert]; split <;> rfl + +noncomputable def toList' [BEq α] [Hashable α] (m : SMap α β) : + List (α × β) := m.map₂.toList' ++ m.map₁.toList + +open scoped _root_.List in +theorem WF.toList'_insert {α β} [BEq α] [LawfulBEq α] [Hashable α] [LawfulHashable α] + {m : SMap α β} (wf : WF m) (a : α) (b : β) + (h : m.find? a = none) : + (m.insert a b).toList' ~ (a, b) :: m.toList' := by + unfold insert; split <;> simp [toList'] + · have : EquivBEq α := inferInstance; clear ‹LawfulBEq _› + have := wf.stage rfl; simp [find?] at this h; subst this; simp + refine (List.filter_eq_self.2 ?_ ▸ Std.HashMap.insert_toList (α := α) .. :) + rintro ⟨a', b⟩ h + refine Decidable.by_contra fun h2 => ?_ + simp at h2 + have := Std.HashMap.getElem?_eq_some_iff_exists_beq_and_mem_toList.2 ⟨_, h2, h⟩ + exact ‹¬_› (Std.HashMap.mem_of_getElem? this) + · refine .append_right (l₂ := _::_) _ ?_ + refine (List.filter_eq_self.2 ?_ ▸ wf.map₂.toList'_insert .. :) + rintro ⟨a', b⟩ h' + have := wf.map₂.find?_eq a + simp_all [find?]; rintro rfl + exact h.1 _ _ h' rfl + +theorem WF.find?_eq {α β} [BEq α] [Hashable α] [LawfulBEq α] [LawfulHashable α] + {m : SMap α β} (wf : WF m) (a : α) : m.find? a = m.toList'.lookup a := by + simp [find?]; split + · cases wf.stage rfl + simp [toList'] + exact Std.HashMap.getElem?_eq_lookup_toList .. + · simp [toList', List.lookup_append, wf.map₂.find?_eq] + cases List.lookup a .. <;> simp [Std.HashMap.getElem?_eq_lookup_toList] + +theorem WF.find?'_eq_find? {α β} [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] + {m : SMap α β} (wf : WF m) (a : α) : m.find?' a = m.find? a := by + simp [find?, find?']; split; · rfl + rename_i m₁ m₂ + cases e1 : m₁[a]? <;> cases e2 : m₂.find? a <;> simp + cases wf.disjoint (by simp [PersistentHashMap.find?_isSome, e2]) (Std.HashMap.mem_of_getElem? e1) + +theorem find?_isSome {α β} [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] + (m : SMap α β) (a : α) : m.contains a = (m.find? a).isSome := by + simp [find?, contains]; split <;> simp [← PersistentHashMap.find?_isSome, Bool.or_comm] diff --git a/Ix/Theory/Named/Std/ToExpr.lean b/Ix/Theory/Named/Std/ToExpr.lean new file mode 100644 index 000000000..10f05c232 --- /dev/null +++ b/Ix/Theory/Named/Std/ToExpr.lean @@ -0,0 +1,73 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +/- +Copyright (c) 2023 Kyle Miller. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kyle Miller +-/ +import Lean + +/-! # `ToExpr` instances for Mathlib + +This module should be imported by any module that intends to define `ToExpr` instances. +It provides necessary dependencies (the `Lean.ToLevel` class) and it also overrides the instances +that come from core Lean 4 that do not handle universe polymorphism. +(See the module `Lean.ToExpr` for the instances that are overridden.) + +In addition, we provide some additional `ToExpr` instances for core definitions. +-/ + +set_option autoImplicit true + +namespace Mathlib +open Lean + +deriving instance ToExpr for Int + +deriving instance ToExpr for ULift + +/-- Hand-written instance since `PUnit` is a `Sort` rather than a `Type`. -/ +instance [ToLevel.{u}] : ToExpr PUnit.{u+1} where + toExpr _ := mkConst ``PUnit.unit [toLevel.{u+1}] + toTypeExpr := mkConst ``PUnit [toLevel.{u+1}] + +deriving instance ToExpr for String.Pos.Raw +deriving instance ToExpr for Substring.Raw +deriving instance ToExpr for SourceInfo +deriving instance ToExpr for Syntax.Preresolved +deriving instance ToExpr for Syntax + +open DataValue in +/-- Core of a hand-written `ToExpr` handler for `MData`. +Uses the `KVMap.set*` functions rather than going into the internals +of the `KVMap` data structure. -/ +private def toExprMData (md : MData) : Expr := Id.run do + let mut e := mkConst ``MData.empty + for (k, v) in md do + let k := toExpr k + e := match v with + | ofString v => mkApp3 (mkConst ``KVMap.setString) e k (mkStrLit v) + | ofBool v => mkApp3 (mkConst ``KVMap.setBool) e k (toExpr v) + | ofName v => mkApp3 (mkConst ``KVMap.setName) e k (toExpr v) + | ofNat v => mkApp3 (mkConst ``KVMap.setNat) e k (mkNatLit v) + | ofInt v => mkApp3 (mkConst ``KVMap.setInt) e k (toExpr v) + | ofSyntax v => mkApp3 (mkConst ``KVMap.setSyntax) e k (toExpr v) + return e + +instance : ToExpr MData where + toExpr := toExprMData + toTypeExpr := mkConst ``MData + +deriving instance ToExpr for FVarId +deriving instance ToExpr for MVarId +deriving instance ToExpr for LevelMVarId +deriving instance ToExpr for Level +deriving instance ToExpr for BinderInfo +deriving instance ToExpr for Literal +deriving instance ToExpr for Expr + +end Mathlib diff --git a/Ix/Theory/Named/Std/VariableBang.lean b/Ix/Theory/Named/Std/VariableBang.lean new file mode 100644 index 000000000..6adf62d4d --- /dev/null +++ b/Ix/Theory/Named/Std/VariableBang.lean @@ -0,0 +1,22 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean + +macro "variable!" args:(ppSpace colGt bracketedBinder)+ " in" + cmd:ppDedent(command) : command => do + let mut incls := #[] + for a in args do + match a with + | `(bracketedBinder| ($as* $[: $_]?)) + | `(bracketedBinder| {$as* $[: $_]?}) + | `(bracketedBinder| ⦃$as* $[: $_]?⦄) => + for a in as do + match a with | `(_) => pure () | _ => incls := incls.push ⟨a.raw⟩ + | `(bracketedBinder| [$a : $_]) => + match a with | `(_) => pure () | _ => incls := incls.push ⟨a.raw⟩ + | _ => pure () + `(command| variable $args* in include $incls* in $(⟨cmd.raw⟩)) diff --git a/Ix/Theory/Named/Typing/Basic.lean b/Ix/Theory/Named/Typing/Basic.lean new file mode 100644 index 000000000..fe962ac82 --- /dev/null +++ b/Ix/Theory/Named/Typing/Basic.lean @@ -0,0 +1,141 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.VEnv + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Ix.Theory.Named + +inductive Lookup : List VExpr → Nat → VExpr → Prop where + | zero : Lookup (ty::Γ) 0 ty.lift + | succ : Lookup Γ n ty → Lookup (A::Γ) (n+1) ty.lift + +/-- A context-wide predicate, exposing each binder in its preceding context. -/ +def OnCtx (Γ : List VExpr) (P : List VExpr → VExpr → Prop) : Prop := + match Γ with + | [] => True + | A::Γ => OnCtx Γ P ∧ P Γ A + +namespace VEnv + +section +set_option hygiene false +local notation:65 Γ " ⊢ " e " : " A:30 => IsDefEq Γ e e A +local notation:65 Γ " ⊢ " e1 " ≡ " e2 " : " A:30 => IsDefEq Γ e1 e2 A +variable (env : VEnv) (uvars : Nat) + +mutual + +inductive IsDefEq : List VExpr → VExpr → VExpr → VExpr → Prop where + | bvar : Lookup Γ i A → Γ ⊢ .bvar i : A + | symm : Γ ⊢ e ≡ e' : A → Γ ⊢ e' ≡ e : A + | trans : Γ ⊢ e₁ ≡ e₂ : A → Γ ⊢ e₂ ≡ e₃ : A → Γ ⊢ e₁ ≡ e₃ : A + | sortDF : + l.WF uvars → l'.WF uvars → l ≈ l' → + Γ ⊢ .sort l ≡ .sort l' : .sort (.succ l) + | constDF : + env.constants c = some ci → + (∀ l ∈ ls, l.WF uvars) → + (∀ l ∈ ls', l.WF uvars) → + ls.length = ci.uvars → + List.Forall₂ (· ≈ ·) ls ls' → + Γ ⊢ .const c ls ≡ .const c ls' : ci.type.instL ls + | appDF : + Γ ⊢ f ≡ f' : .forallE A B → + Γ ⊢ a ≡ a' : A → + Γ ⊢ .app f a ≡ .app f' a' : B.inst a + | lamDF : + Γ ⊢ A ≡ A' : .sort u → + A::Γ ⊢ body ≡ body' : B → + Γ ⊢ .lam A body ≡ .lam A' body' : .forallE A B + | forallEDF : + Γ ⊢ A ≡ A' : .sort u → + A::Γ ⊢ body ≡ body' : .sort v → + Γ ⊢ .forallE A body ≡ .forallE A' body' : .sort (.imax u v) + | defeqDF : Γ ⊢ A ≡ B : .sort u → Γ ⊢ e1 ≡ e2 : A → Γ ⊢ e1 ≡ e2 : B + | beta : + A::Γ ⊢ e : B → Γ ⊢ e' : A → + Γ ⊢ .app (.lam A e) e' ≡ e.inst e' : B.inst e' + | eta : + Γ ⊢ e : .forallE A B → + Γ ⊢ .lam A (.app e.lift (.bvar 0)) ≡ e : .forallE A B + | structEta : + env.structEtas rule → + (∀ level ∈ levels, level.WF uvars) → + levels.length = rule.uvars → + params.length = rule.nparams → + SpineWF Γ (rule.familyType.instL levels) params (.sort resultLevel) → + Γ ⊢ major : rule.structureType levels params → + Γ ⊢ rule.rebuild levels params major : + rule.structureType levels params → + Γ ⊢ rule.rebuild levels params major ≡ major : + rule.structureType levels params + | proofIrrel : + Γ ⊢ p : .sort .zero → Γ ⊢ h : p → Γ ⊢ h' : p → + Γ ⊢ h ≡ h' : p + | extra : + env.defeqs df → (∀ l ∈ ls, l.WF uvars) → ls.length = df.uvars → + Γ ⊢ df.lhs.instL ls ≡ df.rhs.instL ls : df.type.instL ls + +/-- Typing of an application spine against an iterated pi type: peeling the +expressions of `es` off `A` one instantiation at a time ends at `B`. + +This judgment is mutually inductive with `IsDefEq` so rules whose validity +depends on an exact application spine retain induction hypotheses for every +argument typing derivation. -/ +inductive SpineWF : List VExpr → VExpr → List VExpr → VExpr → Prop where + | nil : SpineWF Γ A [] A + | cons : + IsDefEq Γ e e A₁ → + SpineWF Γ (A₂.inst e) es B → + SpineWF Γ (.forallE A₁ A₂) (e :: es) B + +end + +end + +def HasType (env : VEnv) (U : Nat) (Γ : List VExpr) (e A : VExpr) : Prop := + IsDefEq env U Γ e e A + +def IsType (env : VEnv) (U : Nat) (Γ : List VExpr) (A : VExpr) : Prop := + ∃ u, env.HasType U Γ A (.sort u) + +def IsDefEqU (env : VEnv) (U : Nat) (Γ : List VExpr) (e₁ e₂ : VExpr) := + ∃ A, env.IsDefEq U Γ e₁ e₂ A + +end VEnv + +def VExpr.WF (env : VEnv) (U : Nat) (Γ : List VExpr) (e : VExpr) := env.IsDefEqU U Γ e e + +def VConstant.WF (env : VEnv) (ci : VConstant) : Prop := env.IsType ci.uvars [] ci.type + +def VDefEq.WF (env : VEnv) (df : VDefEq) : Prop := + env.HasType df.uvars [] df.lhs df.type ∧ env.HasType df.uvars [] df.rhs df.type + +/-- Subject-reduction package attached to a registered structure-eta +descriptor. It consumes the exact family parameter spine but contains no +equality premise. -/ +structure VStructEta.WF (rule : VStructEta) (env : VEnv) : Prop where + /-- The retained family declaration is a closed constant type. This is the + syntactic fact which lets an exact parameter-spine certificate survive term + weakening and substitution. -/ + familyType_closed : rule.familyType.ClosedN + rebuild_hasType : + ∀ {env' : VEnv}, env ≤ env' → + ∀ {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} {major : VExpr}, + OnCtx Γ (env'.IsType U) → + (∀ level ∈ levels, level.WF U) → + levels.length = rule.uvars → + params.length = rule.nparams → + (∃ resultLevel, + env'.SpineWF U Γ (rule.familyType.instL levels) + params (.sort resultLevel)) → + env'.HasType U Γ major (rule.structureType levels params) → + env'.HasType U Γ (rule.rebuild levels params major) + (rule.structureType levels params) diff --git a/Ix/Theory/Named/Typing/Env.lean b/Ix/Theory/Named/Typing/Env.lean new file mode 100644 index 000000000..b3e009d29 --- /dev/null +++ b/Ix/Theory/Named/Typing/Env.lean @@ -0,0 +1,79 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Typing.Basic +import Ix.Theory.Named.VDecl +import Ix.Theory.Named.Quot +import Ix.Theory.Named.Inductive +import Ix.Theory.Named.NestedInductive + +namespace Ix.Theory.Named + +def VDefVal.WF (env : VEnv) (ci : VDefVal) : Prop := env.HasType ci.uvars [] ci.value ci.type + +/-- Add a block of constants, without their defining equations. -/ +def VEnv.addConsts (env : VEnv) (cis : List VDefVal) : Option VEnv := + cis.foldlM (fun env ci => env.addConst ci.name ci.toVConstant) env + +/-- Add the defining equations of a block, after all of its constants. -/ +def VEnv.addDefEqs (env : VEnv) (cis : List VDefVal) : VEnv := + cis.foldl (fun env ci => env.addDefEq ci.toDefEq) env + +inductive VDecl.WF : VEnv → VDecl → VEnv → Prop where + | axiom : + ci.WF env → + env.addConst ci.name ci.toVConstant = some env' → + VDecl.WF env (.axiom ci) env' + | def : + ci.WF env → + env.addConst ci.name ci.toVConstant = some env' → + VDecl.WF env (.def ci) (env'.addDefEq ci.toDefEq) + | mutualDef : + (∀ ci ∈ cis, ci.toVConstant.WF env) → + env.addConsts cis = some env' → + (∀ ci ∈ cis, ci.WF env') → + VDecl.WF env (.mutualDef cis) (env'.addDefEqs cis) + | opaque : + ci.WF env → + env.addConst ci.name ci.toVConstant = some env' → + VDecl.WF env (.opaque ci) env' + | example : + ci.WF env → + VDecl.WF env (.example ci) env + | quot : + env.QuotReady → + env.addQuot = some env' → + VDecl.WF env .quot env' + | induct {gen : decl.GenerationChecked} : + gen.WF env → + env.addInductGeneration gen = some env' → + VDecl.WF env (.induct decl) env' + | inductBlock {gen : decl.BlockGenerationChecked} : + gen.WF env blockEnv → + env.addInductBlockGeneration gen = some env' → + VDecl.WF env (.induct decl) env' + | inductNested {nested : decl.NestedBlockChecked} : + nested.WF env → + env.addInductNested nested = some env' → + VDecl.WF env (.induct decl) env' + +inductive VEnv.WF' : List VDecl → VEnv → Prop where + | empty : VEnv.WF' [] .empty + | decl {env} : VDecl.WF env d env' → env.WF' ds → env'.WF' (d::ds) + /-- A checked structure-eta descriptor is an environment capability, not a + source declaration. Keep it in the environment history without inventing + a `VDecl`; its subject-reduction certificate is exactly the premise used by + `Ordered.structEta`. -/ + | structEta {env : VEnv} {rule : VStructEta} : rule.WF env → env.WF' ds → + (env.addStructEta rule).WF' ds + +def VEnv.WF (env : VEnv) : Prop := ∃ ds, VEnv.WF' ds env + +/- A normalized inductive history entry carries only the standard Theory +logical baseline; in particular it cannot import Verify's implementation +axioms into `VEnv.WF`. -/ +#guard_named_axioms Ix.Theory.Named.VDecl.WF.induct [propext, Quot.sound] diff --git a/Ix/Theory/Named/Typing/EnvLemmas.lean b/Ix/Theory/Named/Typing/EnvLemmas.lean new file mode 100644 index 000000000..892e68530 --- /dev/null +++ b/Ix/Theory/Named/Typing/EnvLemmas.lean @@ -0,0 +1,120 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.Lemmas +import Ix.Theory.Named.Typing.Env +import Ix.Theory.Named.Typing.QuotLemmas +import Ix.Theory.Named.Typing.InductiveLemmas +import Ix.Theory.Named.Typing.NestedInductiveLemmas + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +theorem VEnv.addConsts_le {env env' : VEnv} : ∀ {cis}, env.addConsts cis = some env' → env ≤ env' + | [], h => by cases h; exact .rfl + | _ :: _, h => by + simp [VEnv.addConsts, Option.bind_eq_some_iff] at h + obtain ⟨_, h1, h2⟩ := h + exact (addConst_le h1).trans (addConsts_le h2) + +theorem VEnv.addConst_eq_none {env : VEnv} {name ci} + (h : env.constants name = none) : ∃ env', env.addConst name ci = some env' := by + unfold VEnv.addConst; rw [h]; exact ⟨_, rfl⟩ + +theorem VEnv.addConst_constants_eq {env env' : VEnv} {name ci} + (h : env.addConst name ci = some env') : + env'.constants = fun n => if name = n then some ci else env.constants n := by + unfold VEnv.addConst at h; split at h <;> cases h; rfl + +/-- A block of constants can be added as long as each name is fresh and the block has no +duplicates; the latter is what `addMutual`'s `found` set checks. -/ +theorem VEnv.exists_addConsts {env : VEnv} : ∀ {cis : List VDefVal}, + (∀ ci ∈ cis, env.constants ci.name = none) → (cis.map (·.name)).Nodup → + ∃ env', env.addConsts cis = some env' + | [], _, _ => ⟨_, rfl⟩ + | ci :: cis, hfresh, hnd => by + obtain ⟨env₁, h₁⟩ := VEnv.addConst_eq_none (ci := ci.toVConstant) (hfresh _ (.head _)) + rw [List.map_cons, List.nodup_cons] at hnd + have ⟨env₂, h₂⟩ := VEnv.exists_addConsts (env := env₁) (cis := cis) (fun c hc => ?_) hnd.2 + · exact ⟨env₂, by simp [VEnv.addConsts, h₁]; exact h₂⟩ + · rw [VEnv.addConst_constants_eq h₁] + have : ci.name ≠ c.name := fun h => hnd.1 (List.mem_map.2 ⟨c, hc, h.symm⟩) + simp [this, hfresh c (.tail _ hc)] + +theorem VEnv.addConsts_congr {env : VEnv} : ∀ {cis cis' : List VDefVal}, + List.Forall₂ (fun a b => a.toVConstVal = b.toVConstVal) cis cis' → + env.addConsts cis = env.addConsts cis' + | [], [], _ => rfl + | a :: _, b :: _, .cons h t => by + have h1 : a.name = b.name := congrArg VConstVal.name h + have h2 : a.toVConstant = b.toVConstant := congrArg VConstVal.toVConstant h + show (env.addConst a.name a.toVConstant).bind _ = (env.addConst b.name b.toVConstant).bind _ + rw [h1, h2] + cases env.addConst b.name b.toVConstant + · rfl + · exact VEnv.addConsts_congr t + +theorem VEnv.addConsts_ordered {env env' : VEnv} : ∀ {cis}, Ordered env → + (∀ ci ∈ cis, ci.toVConstant.WF env) → env.addConsts cis = some env' → Ordered env' + | [], h, _, e => by cases e; exact h + | _ :: _, h, hw, e => by + simp [VEnv.addConsts, Option.bind_eq_some_iff] at e + obtain ⟨_, h1, h2⟩ := e + refine VEnv.addConsts_ordered (.const h (hw _ (.head _)) h1) (fun c hc => ?_) h2 + exact (hw c (.tail _ hc)).mono (VEnv.addConst_le h1) + +theorem VEnv.addConsts_constants {env env' : VEnv} : ∀ {cis}, env.addConsts cis = some env' → + ∀ ci ∈ cis, env'.constants ci.name = some ci.toVConstant + | [], _, _, hc => nomatch hc + | _ :: _, e, c, hc => by + simp [VEnv.addConsts, Option.bind_eq_some_iff] at e + obtain ⟨_, h1, h2⟩ := e + cases hc with + | head => exact (VEnv.addConsts_le h2).constants (VEnv.addConst_self h1) + | tail _ hc => exact VEnv.addConsts_constants h2 c hc + +theorem VEnv.addDefEqs_ordered : ∀ {env : VEnv} {cis}, Ordered env → + (∀ ci ∈ cis, env.constants ci.name = some ci.toVConstant) → + (∀ ci ∈ cis, ci.WF env) → Ordered (env.addDefEqs cis) + | _, [], h, _, _ => h + | env, ci :: cis, h, hmem, hw => by + have hci : ci.WF env := hw _ (.head _) + have hord : Ordered (env.addDefEq ci.toDefEq) := by + refine .defeq h ⟨?_, hci⟩ + simp [VDefVal.toDefEq] + rw [← (hci.levelWF ⟨⟩).2.2.instL_id] + exact .const (hmem _ (.head _)) VLevel.id_WF (by simp) + show Ordered ((env.addDefEq ci.toDefEq).addDefEqs cis) + refine VEnv.addDefEqs_ordered hord (fun c hc => ?_) (fun c hc => ?_) + · exact (VEnv.addDefEq_le (df := ci.toDefEq)).constants (hmem c (.tail _ hc)) + · exact (hw c (.tail _ hc)).mono VEnv.addDefEq_le + +theorem VEnv.WF.ordered : WF env → Ordered env + | ⟨ds, H⟩ => by + induction H with + | empty => exact .empty + | decl h _ ih => + cases h with + | «axiom» h1 h2 => exact .const ih h1 h2 + | @«def» env env' ci h1 h2 => + refine .defeq (.const ih (h1.isType ih ⟨⟩) h2) ⟨?_, ?_⟩ + · simp [VDefVal.toDefEq] + rw [← (h1.levelWF ⟨⟩).2.2.instL_id] + exact .const (addConst_self h2) VLevel.id_WF (by simp) + · exact h1.mono (addConst_le h2) + | mutualDef h0 h1 h2 => + exact VEnv.addDefEqs_ordered (VEnv.addConsts_ordered ih h0 h1) + (VEnv.addConsts_constants h1) h2 + | «opaque» h1 h2 => exact .const ih (h1.isType ih ⟨⟩) h2 + | «example» _ => exact ih + | quot h1 h2 => exact addQuot_WF ih h1 h2 + | induct h1 h2 => exact addInductGeneration_WF ih h1 h2 + | inductBlock h1 h2 => exact addInductBlockGeneration_WF ih h1 h2 + | inductNested h1 h2 => exact VEnv.addInductNested_WF ih h1 h2 + | structEta hwf _ ih => exact .structEta ih hwf + +instance : CoeOut (VEnv.WF env) env.Ordered := ⟨(·.ordered)⟩ diff --git a/Ix/Theory/Named/Typing/InductiveCertificate.lean b/Ix/Theory/Named/Typing/InductiveCertificate.lean new file mode 100644 index 000000000..3f0afdf3e --- /dev/null +++ b/Ix/Theory/Named/Typing/InductiveCertificate.lean @@ -0,0 +1,514 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Typing.EnvLemmas +import Ix.Theory.Named.Typing.InductivePattern +import Ix.Theory.Named.Typing.NestedInductiveLemmas + +/-! +# Consumer certificates for completed inductive blocks + +`BlockGenerationCertificate` is the semantic input to the block transaction. +This module packages that input with one successful transaction and a +well-formed dependency environment, then exports the stable consequences a +consumer needs. The package contains only Theory values and proofs: no +implementation metadata, checker state, or normalization execution crosses +this boundary. + +In particular, `BlockCertificate.ruleClosure` derives the closed payload +required by the generated-pattern API from the registered, well-formed iota +rules in the completed environment. A consumer therefore does not need a +second closedness assumption in order to use `IotaPat`. +-/ + +namespace Ix.Theory.Named + +namespace VInductDecl + +/-- One successful proof-carrying block transaction over an explicit +dependency environment. -/ +structure BlockCertificate (source : VInductDecl) (before after : VEnv) where + semantic : source.BlockGenerationCertificate before + success : before.addInductBlockCertified semantic = some after + beforeWF : before.WF + +namespace BlockCertificate + +variable {source : VInductDecl} {before after : VEnv} + +/-- Package the ordinary raw `addInduct` entry point once its accepted block +descriptor and semantic proof are known. This is the compatibility bridge +for consumers that still execute `addInduct`; no second transaction is run. -/ +def ofAddInduct + (generation : source.BlockGenerationChecked) (blockEnv : VEnv) + (hidentity : source.identityBlockGeneration? = some generation) + (hwf : generation.WF before blockEnv) (hbefore : before.WF) + (hadd : before.addInduct source = some after) : + BlockCertificate source before after where + semantic := ⟨generation, blockEnv, hwf⟩ + success := by + unfold VEnv.addInduct at hadd + rw [hidentity] at hadd + exact hadd + beforeWF := hbefore + +/-- The exact generation descriptor retained by a completed block. -/ +abbrev generation (certificate : BlockCertificate source before after) : + source.BlockGenerationChecked := + certificate.semantic.generation + +/-- Recover the four exact insertion phases of the completed block. -/ +theorem trace (certificate : BlockCertificate source before after) : + Nonempty (VEnv.AddInductBlockGenerationTrace before after + certificate.generation) := + VEnv.addInductBlockCertified_trace certificate.success + +/-- The completed transaction is a genuine block declaration step. -/ +theorem declWF (certificate : BlockCertificate source before after) : + VDecl.WF before (.induct source) after := by + apply VDecl.WF.inductBlock certificate.semantic.wf + simpa only [VEnv.addInductBlockCertified_eq_addInductBlockGeneration] using + certificate.success + +/-- Extend the dependency-environment history with the certified block. -/ +theorem afterWF (certificate : BlockCertificate source before after) : + after.WF := by + rcases certificate.beforeWF with ⟨decls, hdecls⟩ + exact ⟨.induct source :: decls, hdecls.decl certificate.declWF⟩ + +/-- A completed block only grows its dependency environment. -/ +theorem envLE (certificate : BlockCertificate source before after) : + before ≤ after := by + rcases certificate.trace with ⟨trace⟩ + exact trace.le + +/-- Compatibility spelling for consumers of the historical +`addInduct_le` growth theorem. -/ +theorem addInduct_le (certificate : BlockCertificate source before after) : + before ≤ after := + certificate.envLE + +/-- Compatibility spelling for the preservation result traditionally +exported as `addInduct_WF`. -/ +theorem addInduct_WF (certificate : BlockCertificate source before after) : + after.WF := + certificate.afterWF + +/-- Recover success through the ordinary raw API when this certificate's +descriptor is the declaration's identity descriptor. -/ +theorem addInduct + (certificate : BlockCertificate source before after) + (hidentity : source.identityBlockGeneration? = + some certificate.generation) : + before.addInduct source = some after := by + unfold VEnv.addInduct + rw [hidentity] + simpa [VEnv.addInductBlockCertified] using certificate.success + +/-- Every source family has its exact stored Theory value in the completed +environment. -/ +theorem familyLookup (certificate : BlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) : + after.constants family.name = some family.toVConstant := by + rcases certificate.trace with ⟨trace⟩ + exact trace.family_lookup hfamily + +/-- Every flattened source constructor has its exact stored Theory value in +the completed environment. -/ +theorem constructorLookup + (certificate : BlockCertificate source before after) + {constructor : VConstVal} + (hconstructor : constructor ∈ source.blockConstructorConstants) : + after.constants constructor.name = some constructor.toVConstant := by + rcases certificate.trace with ⟨trace⟩ + exact trace.ctor_lookup hconstructor + +/-- Every generated family recursor has its exact Theory value in the +completed environment. -/ +theorem recursorLookup + (certificate : BlockCertificate source before after) + {recursor : VConstVal} + (hrecursor : recursor ∈ certificate.generation.recursors) : + after.constants recursor.name = some recursor.toVConstant := by + rcases certificate.trace with ⟨trace⟩ + exact trace.rec_lookup hrecursor + +/-- A source family name was fresh at the dependency boundary. -/ +theorem familyFresh (certificate : BlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) : + before.constants family.name = none := by + rcases certificate.trace with ⟨trace⟩ + exact trace.family_fresh hfamily + +/-- A flattened source constructor name was fresh at the dependency +boundary. -/ +theorem constructorFresh + (certificate : BlockCertificate source before after) + {constructor : VConstVal} + (hconstructor : constructor ∈ source.blockConstructorConstants) : + before.constants constructor.name = none := by + rcases certificate.trace with ⟨trace⟩ + exact trace.ctor_fresh hconstructor + +/-- A generated recursor name was fresh at the dependency boundary. -/ +theorem recursorFresh + (certificate : BlockCertificate source before after) + {recursor : VConstVal} + (hrecursor : recursor ∈ certificate.generation.recursors) : + before.constants recursor.name = none := by + rcases certificate.trace with ⟨trace⟩ + exact trace.rec_fresh hrecursor + +/-- Every generated rule is registered by the completed transaction. -/ +theorem ruleRegistered + (certificate : BlockCertificate source before after) + {rule : VDefEq} + (hrule : rule ∈ certificate.generation.generatedRules) : + after.defeqs rule := by + rcases certificate.trace with ⟨trace⟩ + exact trace.rule_mem hrule + +/-- Every generated rule is well formed in the completed environment. -/ +theorem ruleWF + (certificate : BlockCertificate source before after) + {rule : VDefEq} + (hrule : rule ∈ certificate.generation.generatedRules) : + rule.WF after := + certificate.afterWF.ordered.defEqWF (certificate.ruleRegistered hrule) + +/-- An exact family lookup is unique. This small eliminator is convenient +for consumers that translate their own family representation to a Theory +constant and then compare it with the certificate inventory. -/ +theorem familyLookup_unique + (certificate : BlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) + {constant : VConstant} + (hlookup : after.constants family.name = some constant) : + constant = family.toVConstant := by + exact Option.some.inj (hlookup.symm.trans (certificate.familyLookup hfamily)) + +/-- An exact constructor lookup is unique. -/ +theorem constructorLookup_unique + (certificate : BlockCertificate source before after) + {constructor : VConstVal} + (hconstructor : constructor ∈ source.blockConstructorConstants) + {constant : VConstant} + (hlookup : after.constants constructor.name = some constant) : + constant = constructor.toVConstant := by + exact Option.some.inj + (hlookup.symm.trans (certificate.constructorLookup hconstructor)) + +/-- An exact generated-recursor lookup is unique. -/ +theorem recursorLookup_unique + (certificate : BlockCertificate source before after) + {recursor : VConstVal} + (hrecursor : recursor ∈ certificate.generation.recursors) + {constant : VConstant} + (hlookup : after.constants recursor.name = some constant) : + constant = recursor.toVConstant := by + exact Option.some.inj + (hlookup.symm.trans (certificate.recursorLookup hrecursor)) + +private theorem rule_mem_generatedRules + (generation : source.BlockGenerationChecked) + {i : Nat} {constructor : NormalizedBlockCtor} + (hentry : generation.flatCtors[i]? = some constructor) : + generation.rule i constructor ∈ generation.generatedRules := by + apply List.mem_map.2 + refine ⟨(constructor, i), ?_, rfl⟩ + apply List.mem_of_getElem? (i := i) + rw [List.getElem?_zipIdx, hentry, Option.map_some, Nat.zero_add] + +private theorem closedN_lamN_body : + ∀ {binders : List VExpr} {body : VExpr} {k : Nat}, + (VExpr.lamN binders body).ClosedN k → + body.ClosedN (k + binders.length) + | [], _, _, h => by + simpa only [VExpr.lamN, List.length_nil, Nat.add_zero] using h + | _ :: binders, body, k, h => by + have hbody := closedN_lamN_body (binders := binders) + (body := body) (k := k + 1) h.2 + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hbody + +private theorem closedN_lamN_replace : + ∀ {binders : List VExpr} {body body' : VExpr} {k : Nat}, + (VExpr.lamN binders body).ClosedN k → + body'.ClosedN (k + binders.length) → + (VExpr.lamN binders body').ClosedN k + | [], _, _, _, _, hbody' => by + simpa only [VExpr.lamN, List.length_nil, Nat.add_zero] using hbody' + | _ :: binders, body, body', k, h, hbody' => by + refine ⟨h.1, closedN_lamN_replace (binders := binders) + (body := body) (body' := body') (k := k + 1) h.2 ?_⟩ + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hbody' + +private theorem closedN_appN_function : + ∀ {function : VExpr} {arguments : List VExpr} {k : Nat}, + (VExpr.appN function arguments).ClosedN k → function.ClosedN k + | _, [], _, h => by simpa only [VExpr.appN] using h + | function, argument :: arguments, k, h => + (closedN_appN_function (function := function.app argument) + (arguments := arguments) (k := k) h).1 + +private theorem closedN_appN_argument + {function : VExpr} {arguments : List VExpr} {k : Nat} + (hclosed : (VExpr.appN function arguments).ClosedN k) + {argument : VExpr} (hargument : argument ∈ arguments) : + argument.ClosedN k := by + induction arguments generalizing function with + | nil => simp at hargument + | cons head tail ih => + rcases List.mem_cons.1 hargument with heq | htail + · rw [heq] + exact (closedN_appN_function + (function := function.app head) (arguments := tail) + (k := k) hclosed).2 + · exact ih (function := function.app head) hclosed htail + +/-- The successful block transaction supplies the closedness bundle required +by `IotaPat`. Closedness is derived from the registered rules and the +completed environment's ordinary WF history; it is not an additional +consumer assumption. -/ +theorem ruleClosure + (certificate : BlockCertificate source before after) : + certificate.generation.RuleClosure := by + constructor + · intro i constructor hentry + have hmem := rule_mem_generatedRules certificate.generation hentry + exact (certificate.ruleWF hmem).2.closedN + certificate.afterWF.ordered trivial + · intro constructor hconstructor expression hexpression + obtain ⟨i, hentry⟩ := List.mem_iff_getElem?.1 hconstructor + have hmem := rule_mem_generatedRules certificate.generation hentry + have hlhs := (certificate.ruleWF hmem).1.closedN + certificate.afterWF.ordered trivial + rw [certificate.generation.rule_lhs i constructor] at hlhs + have hbody := closedN_lamN_body hlhs + have hexpression' : expression ∈ + certificate.generation.ruleIdx constructor ++ + [certificate.generation.ruleCtorApp constructor] := + List.mem_append.2 (.inl hexpression) + have hclosed : expression.ClosedN + (certificate.generation.ruleBinders constructor).length := by + apply closedN_appN_argument + (function := certificate.generation.recBase + (certificate.generation.ruleFieldCount constructor) + constructor.owner) + (arguments := certificate.generation.ruleIdx constructor ++ + [certificate.generation.ruleCtorApp constructor]) + · simpa only [BlockGenerationChecked.ruleLhsBody, List.length_nil, + Nat.zero_add] using hbody + · exact hexpression' + apply closedN_lamN_replace hlhs + simpa using hclosed + +/-- The exact generated pattern and payload associated with one flattened +rule entry. -/ +theorem recursorPattern + (certificate : BlockCertificate source before after) + {i : Nat} {constructor : NormalizedBlockCtor} + (hentry : certificate.generation.ruleEntry i constructor) : + certificate.generation.IotaPat certificate.ruleClosure + ((certificate.generation.rulePattern constructor).toPattern) + (certificate.generation.ruleRHS certificate.ruleClosure hentry, + certificate.generation.ruleCheck certificate.ruleClosure + (List.mem_of_getElem? hentry)) := + .mk hentry + +/-- Rule-level consumer bundle: exact global position, generated-list +membership, registration, well-formedness, and the corresponding Spec-10 +pattern all come from the same completed block. -/ +structure RecursorRuleFacts + (certificate : BlockCertificate source before after) + (i : Nat) (constructor : NormalizedBlockCtor) : Prop where + entry : certificate.generation.ruleEntry i constructor + member : certificate.generation.rule i constructor ∈ + certificate.generation.generatedRules + registered : after.defeqs (certificate.generation.rule i constructor) + wf : (certificate.generation.rule i constructor).WF after + pattern : certificate.generation.IotaPat certificate.ruleClosure + ((certificate.generation.rulePattern constructor).toPattern) + (certificate.generation.ruleRHS certificate.ruleClosure entry, + certificate.generation.ruleCheck certificate.ruleClosure + (List.mem_of_getElem? entry)) + +/-- Assemble all rule facts without a consumer-supplied semantic premise. -/ +theorem recursorRuleFacts + (certificate : BlockCertificate source before after) + {i : Nat} {constructor : NormalizedBlockCtor} + (hentry : certificate.generation.ruleEntry i constructor) : + certificate.RecursorRuleFacts i constructor := by + have hmember := rule_mem_generatedRules certificate.generation hentry + exact { + entry := hentry + member := hmember + registered := certificate.ruleRegistered hmember + wf := certificate.ruleWF hmember + pattern := certificate.recursorPattern hentry } + +end BlockCertificate + +/-! ## Completed nested transactions -/ + +/-- One successful proof-carrying nested transaction over an explicit +dependency environment. As with `BlockCertificate`, this package contains +only Theory artifacts. -/ +structure NestedBlockCertificate + (source : VInductDecl) (before after : VEnv) where + nested : source.NestedBlockChecked + semantic : nested.WF before + success : before.addInductNested nested = some after + beforeWF : before.WF + +namespace NestedBlockCertificate + +variable {source : VInductDecl} {before after : VEnv} + +/-- Recover the exact four-phase nested transaction trace. -/ +theorem trace (certificate : NestedBlockCertificate source before after) : + Nonempty (VEnv.AddInductNestedTrace before after certificate.nested) := + VEnv.addInductNested_trace certificate.success + +/-- The nested completion is a genuine inductive declaration step. -/ +theorem declWF (certificate : NestedBlockCertificate source before after) : + VDecl.WF before (.induct source) after := + .inductNested certificate.semantic certificate.success + +/-- Extend the dependency-environment history with the nested block. -/ +theorem afterWF (certificate : NestedBlockCertificate source before after) : + after.WF := by + rcases certificate.beforeWF with ⟨decls, hdecls⟩ + exact ⟨.induct source :: decls, hdecls.decl certificate.declWF⟩ + +/-- A completed nested transaction only grows its dependency environment. -/ +theorem envLE (certificate : NestedBlockCertificate source before after) : + before ≤ after := + VEnv.addInductNested_le certificate.success + +/-- Nested analogue of the public block growth result. -/ +theorem addInduct_le + (certificate : NestedBlockCertificate source before after) : + before ≤ after := + certificate.envLE + +/-- Nested analogue of the public block preservation result. -/ +theorem addInduct_WF + (certificate : NestedBlockCertificate source before after) : + after.WF := + certificate.afterWF + +/-- Every stored source family has its exact final value. -/ +theorem familyLookup (certificate : NestedBlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) : + after.constants family.name = some family.toVConstant := by + rcases certificate.trace with ⟨trace⟩ + exact trace.family_lookup hfamily + +/-- Every stored source constructor has its exact final value. -/ +theorem constructorLookup + (certificate : NestedBlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) + {constructor : VConstVal} (hconstructor : constructor ∈ family.ctors) : + after.constants constructor.name = some constructor.toVConstant := by + rcases certificate.trace with ⟨trace⟩ + exact trace.ctor_lookup hfamily hconstructor + +/-- Every restored recursor has its exact final value. -/ +theorem recursorLookup + (certificate : NestedBlockCertificate source before after) + {recursor : VConstVal} (hrecursor : recursor ∈ certificate.nested.recursors) : + after.constants recursor.name = some recursor.toVConstant := by + rcases certificate.trace with ⟨trace⟩ + exact trace.rec_lookup hrecursor + +/-- Every source family name was fresh at the dependency boundary. -/ +theorem familyFresh (certificate : NestedBlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) : + before.constants family.name = none := by + rcases certificate.trace with ⟨trace⟩ + exact trace.family_fresh hfamily + +/-- Every flattened source constructor name was fresh at the dependency +boundary. -/ +theorem constructorFresh + (certificate : NestedBlockCertificate source before after) + {constructor : VConstVal} + (hconstructor : constructor ∈ source.blockConstructorConstants) : + before.constants constructor.name = none := by + rcases certificate.trace with ⟨trace⟩ + exact trace.ctor_fresh hconstructor + +/-- Every restored recursor name was fresh at the dependency boundary. -/ +theorem recursorFresh + (certificate : NestedBlockCertificate source before after) + {recursor : VConstVal} (hrecursor : recursor ∈ certificate.nested.recursors) : + before.constants recursor.name = none := by + rcases certificate.trace with ⟨trace⟩ + exact trace.rec_fresh hrecursor + +/-- Every restored rule is registered in the completed environment. -/ +theorem ruleRegistered + (certificate : NestedBlockCertificate source before after) + {rule : VDefEq} (hrule : rule ∈ certificate.nested.generatedRules) : + after.defeqs rule := by + rcases certificate.trace with ⟨trace⟩ + exact trace.rule_mem hrule + +/-- Every registered restored rule is well formed. -/ +theorem ruleWF + (certificate : NestedBlockCertificate source before after) + {rule : VDefEq} (hrule : rule ∈ certificate.nested.generatedRules) : + rule.WF after := + certificate.afterWF.ordered.defEqWF (certificate.ruleRegistered hrule) + +/-- Exact family lookups are unique. -/ +theorem familyLookup_unique + (certificate : NestedBlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) + {constant : VConstant} + (hlookup : after.constants family.name = some constant) : + constant = family.toVConstant := + Option.some.inj (hlookup.symm.trans (certificate.familyLookup hfamily)) + +/-- Exact constructor lookups are unique. -/ +theorem constructorLookup_unique + (certificate : NestedBlockCertificate source before after) + {family : VInductiveType} (hfamily : family ∈ source.types) + {constructor : VConstVal} (hconstructor : constructor ∈ family.ctors) + {constant : VConstant} + (hlookup : after.constants constructor.name = some constant) : + constant = constructor.toVConstant := + Option.some.inj + (hlookup.symm.trans (certificate.constructorLookup hfamily hconstructor)) + +/-- Exact restored-recursor lookups are unique. -/ +theorem recursorLookup_unique + (certificate : NestedBlockCertificate source before after) + {recursor : VConstVal} (hrecursor : recursor ∈ certificate.nested.recursors) + {constant : VConstant} + (hlookup : after.constants recursor.name = some constant) : + constant = recursor.toVConstant := + Option.some.inj + (hlookup.symm.trans (certificate.recursorLookup hrecursor)) + +end NestedBlockCertificate + +end VInductDecl + +end Ix.Theory.Named + +/-! ## Exact Theory trust guards -/ + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockCertificate.afterWF [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockCertificate.ruleClosure [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockCertificate.recursorRuleFacts [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NestedBlockCertificate.afterWF [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NestedBlockCertificate.ruleWF [propext, Classical.choice, Quot.sound] diff --git a/Ix/Theory/Named/Typing/InductiveLemmas.lean b/Ix/Theory/Named/Typing/InductiveLemmas.lean new file mode 100644 index 000000000..398afdeec --- /dev/null +++ b/Ix/Theory/Named/Typing/InductiveLemmas.lean @@ -0,0 +1,14628 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Typing.Lemmas +import Ix.Theory.Named.Typing.Env +import Ix.Theory.Named.Typing.Meta +import Ix.Theory.Named.Typing.Strong + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +/- Lean 4.31 no longer unfolds these structural recursors implicitly in a +number of `simp`/`simpa` calls below. Keep the compatibility normalization +local to this proof module: all rules only reduce on a visible constructor. -/ +attribute [local simp] VExpr.appN VExpr.bvarRevRange VExpr.forallN VExpr.lamN + VExpr.liftTelN VExpr.liftN VExpr.inst VExpr.instL VLevel.inst + +/-! ## Basic facts about the stage-1 generation helpers -/ + +end Ix.Theory.Named + +namespace Ix.Theory.VLevel + +theorem params'_length : (params' n k).length = n := by simp [params'] + +theorem params'_wf : ∀ l ∈ params' n k, l.WF (n + k) := by + simp only [params', List.mem_map, List.mem_range] + rintro _ ⟨i, hi, rfl⟩; exact Nat.add_lt_add_right hi _ + +theorem params'_one_wf : ∀ l ∈ params' n 1, l.WF (n + 1) := params'_wf + +theorem params_map_inst_params' : + (params n).map (VLevel.inst (params' n k)) = params' n k := + inst_map_id params'_length + +end Ix.Theory.VLevel + +namespace Ix.Theory.Named + +attribute [local simp] VExpr.appN VExpr.bvarRevRange VExpr.forallN VExpr.lamN + VExpr.liftTelN VExpr.liftN VExpr.inst VExpr.instL VLevel.inst + +namespace VExpr + +theorem forallN_append (As Bs : List VExpr) (e : VExpr) : + forallN (As ++ Bs) e = forallN As (forallN Bs e) := by + induction As with + | nil => rfl + | cons A As ih => simp [forallN, ih] + +theorem instL_forallN (ls : List VLevel) (As : List VExpr) (e : VExpr) : + (forallN As e).instL ls = forallN (As.map (instL ls)) (e.instL ls) := by + induction As with + | nil => rfl + | cons A As ih => simp [forallN, instL, ih] + +/-- Substituting a variable for the sole loose variable is a lift. -/ +theorem inst_bvar_of_closedN (h : ClosedN e (k+1)) : + e.inst (.bvar n) k = e.liftN n k := by + induction e generalizing k with simp_all [ClosedN, inst, liftN] + | bvar i => + simp only [instVar] + rcases Nat.lt_trichotomy i k with h' | rfl | h' + · simp [h', liftVar_lt h'] + · simp [liftVar_le (Nat.le_refl _), liftN] + · omega + +theorem ClosedN.appN {f : VExpr} (hf : f.ClosedN k) {as : List VExpr} + (has : ∀ a ∈ as, ClosedN a k) : (appN f as).ClosedN k := by + induction as generalizing f with + | nil => exact hf + | cons a as ih => + exact ih ⟨hf, has _ (.head _)⟩ fun a h => has _ (.tail _ h) + +theorem LevelWF.appN {f : VExpr} (hf : f.LevelWF U) {as : List VExpr} + (has : ∀ a ∈ as, LevelWF U a) : (appN f as).LevelWF U := by + induction as generalizing f with + | nil => exact hf + | cons a as ih => + exact ih ⟨hf, has _ (.head _)⟩ fun a h => has _ (.tail _ h) + +theorem LevelWF.forallN {As : List VExpr} (hAs : ∀ A ∈ As, LevelWF U A) + {e : VExpr} (he : e.LevelWF U) : (forallN As e).LevelWF U := by + induction As with + | nil => exact he + | cons A As ih => + exact ⟨hAs _ (.head _), ih fun A h => hAs _ (.tail _ h)⟩ + +theorem LevelWF.lamN {As : List VExpr} (hAs : ∀ A ∈ As, LevelWF U A) + {e : VExpr} (he : e.LevelWF U) : (lamN As e).LevelWF U := by + induction As with + | nil => exact he + | cons A As ih => + exact ⟨hAs _ (.head _), ih fun A h => hAs _ (.tail _ h)⟩ + +theorem appN_append (f : VExpr) : ∀ (as bs : List VExpr), + f.appN (as ++ bs) = (f.appN as).appN bs + | [], _ => rfl + | a :: as, bs => appN_append (f.app a) as bs + +theorem bvarRevRange_liftN_low : ∀ (m off n : Nat), + (bvarRevRange off m).map (liftN n · 0) = bvarRevRange (n + off) m + | 0, _, _ => rfl + | m+1, off, n => by + show VExpr.bvar _ :: _ = VExpr.bvar _ :: _ + rw [bvarRevRange_liftN_low m off n] + congr 2 + show liftVar n (off + m) 0 = n + off + m + rw [liftVar_le (Nat.zero_le _)]; omega + +theorem bvarRevRange_liftN_high : ∀ (m off n k : Nat), off + m ≤ k → + (bvarRevRange off m).map (liftN n · k) = bvarRevRange off m + | 0, _, _, _, _ => rfl + | m+1, off, n, k, h => by + show VExpr.bvar _ :: _ = VExpr.bvar _ :: _ + rw [bvarRevRange_liftN_high m off n k (by omega)] + congr 2 + exact liftVar_lt (by omega) + +/-- Instantiating at a fresh (lifted-over) position is the identity. -/ +theorem inst_liftN1 : ∀ (e a : VExpr) (k : Nat), (e.liftN 1 k).inst a k = e := by + intro e + induction e with intro a k + | bvar j => + show VExpr.instVar (liftVar 1 j k) a k = .bvar j + unfold liftVar VExpr.instVar + split + · rfl + · next h => + rw [if_neg (by omega), if_neg (by omega)] + congr 1; omega + | sort | const => rfl + | app f b ihf ihb => simp [liftN, inst, ihf, ihb] + | lam A b ihA ihb | forallE A b ihA ihb => simp [liftN, inst, ihA, ihb] + +/-- Lifting a telescope of closed binders acts only on the body. -/ +theorem liftN_forallN_closed : ∀ {As : List VExpr}, (∀ A ∈ As, A.ClosedN 0) → + ∀ (e : VExpr) (n k : Nat), + (forallN As e).liftN n k = forallN As (e.liftN n (k + As.length)) + | [], _, e, n, k => rfl + | A :: As, hAs, e, n, k => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + rw [(hAs _ (.head _)).liftN_eq (Nat.zero_le _), + liftN_forallN_closed (fun A h => hAs _ (.tail _ h)) e n (k+1), + show k+1+As.length = k+(As.length+1) from by omega] + rfl + +/-- Lifting through a dependent telescope. -/ +theorem liftN_forallN (n : Nat) : ∀ (tel : List VExpr) (X : VExpr) (k : Nat), + (forallN tel X).liftN n k = forallN (liftTelN n tel k) (X.liftN n (k + tel.length)) + | [], _, _ => rfl + | A :: tel, X, k => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + rw [liftN_forallN n tel X (k+1), + show k+1+tel.length = k+(tel.length+1) from by omega] + rfl + +theorem liftTelN_length (n : Nat) : ∀ (tel : List VExpr) (k : Nat), + (liftTelN n tel k).length = tel.length + | [], _ => rfl + | _ :: tel, k => by simp [liftTelN, liftTelN_length n tel (k+1)] + +theorem liftTelN_liftTelN (a b : Nat) : ∀ (tel : List VExpr) (k : Nat), + liftTelN b (liftTelN a tel k) k = liftTelN (a+b) tel k + | [], _ => rfl + | A :: tel, k => by + show _ :: _ = _ :: _ + rw [liftN'_liftN_hi, liftTelN_liftTelN a b tel (k+1)] + +theorem liftTelN_getElem? (n : Nat) : ∀ (tel : List VExpr) (k q : Nat), + (liftTelN n tel k)[q]? = tel[q]?.map fun A => A.liftN n (k+q) + | [], _, q => by simp [liftTelN] + | A :: tel, k, 0 => by simp [liftTelN] + | A :: tel, k, q+1 => by + simp only [liftTelN, List.getElem?_cons_succ] + rw [liftTelN_getElem? n tel (k+1) q, show k+1+q = k+(q+1) from by omega] + +theorem liftTelN_take (n : Nat) : ∀ (tel : List VExpr) (k q : Nat), + (liftTelN n tel k).take q = liftTelN n (tel.take q) k + | [], _, q => by simp [liftTelN] + | A :: tel, k, 0 => rfl + | A :: tel, k, q+1 => by + show A.liftN n k :: (liftTelN n tel (k+1)).take q = _ + rw [liftTelN_take n tel (k+1) q] + rfl + +/-- Merging a telescope lift over another when the outer cutoff sits right +past the inner lift. -/ +theorem liftTelN_liftTelN_hi (a b : Nat) : ∀ (tel : List VExpr) (k : Nat), + liftTelN b (liftTelN a tel k) (k + a) = liftTelN (a + b) tel k + | [], _ => rfl + | A :: tel, k => by + show (A.liftN a k).liftN b (k+a) :: _ = _ + rw [liftN'_liftN' (Nat.le_add_right _ _) (by omega), + show k + a + 1 = (k+1) + a from by omega, + liftTelN_liftTelN_hi a b tel (k+1)] + rfl + +/-- `liftTelN_liftTelN_hi` with the outer cutoff generalized, for +syntactic rewriting. -/ +theorem liftTelN_liftTelN_hi' (a b : Nat) (tel : List VExpr) (k : Nat) {cut : Nat} + (hcut : cut = k + a) : + liftTelN b (liftTelN a tel k) cut = liftTelN (a + b) tel k := by + rw [hcut]; exact liftTelN_liftTelN_hi a b tel k + +/-- Merge telescope lifts when the outer cutoff lies anywhere inside the +range opened by the inner lift. This is the shape needed when new ambient +binders are inserted below a recursive argument's own Pi telescope. -/ +theorem liftTelN_liftTelN_mid (a b : Nat) : ∀ (tel : List VExpr) (k cut : Nat), + k ≤ cut → cut ≤ a + k → + liftTelN b (liftTelN a tel k) cut = liftTelN (a+b) tel k + | [], _, _, _, _ => rfl + | A :: tel, k, cut, h₁, h₂ => by + show (A.liftN a k).liftN b cut :: _ = _ + rw [VExpr.liftN'_liftN' h₁ h₂, + liftTelN_liftTelN_mid a b tel (k+1) (cut+1) + (Nat.succ_le_succ h₁) (by omega)] + rfl + +theorem liftTelN_instL (ls : List VLevel) (n : Nat) : ∀ (tel : List VExpr) (k : Nat), + (liftTelN n tel k).map (instL ls) = liftTelN n (tel.map (instL ls)) k + | [], _ => rfl + | A :: tel, k => by + show (A.liftN n k).instL ls :: _ = (A.instL ls).liftN n k :: _ + rw [instL_liftN, liftTelN_instL ls n tel (k+1)] + +/-- Pulling a lift out of the middle of a two-step lift: the outer lift at +the seam between the two inner ones lands on the variables the innermost +lift moved. -/ +theorem liftN_liftN_mid : ∀ (e : VExpr) {j c : Nat} (k d : Nat), c ≤ j → + ((e.liftN 1 j).liftN d c).liftN k (j + d) = (e.liftN (k+1) j).liftN d c := by + intro e + induction e with intro j c k d hc + | bvar i => + show VExpr.bvar (liftVar k (liftVar d (liftVar 1 i j) c) (j+d)) = + .bvar (liftVar d (liftVar (k+1) i j) c) + congr 1 + rcases Nat.lt_or_ge i j with h1 | h1 + · rw [liftVar_lt h1, liftVar_lt (show i < j from h1)] + rcases Nat.lt_or_ge i c with h2 | h2 + · rw [liftVar_lt h2, liftVar_lt (show i < j+d from by omega)] + · rw [liftVar_le h2, liftVar_lt (show d+i < j+d from by omega)] + · rw [liftVar_le h1, liftVar_le h1, + liftVar_le (show c ≤ 1+i from by omega), + liftVar_le (show c ≤ k+1+i from by omega), + liftVar_le (show j+d ≤ d+(1+i) from by omega)] + omega + | sort | const => intros; rfl + | app f a ihf iha => simp [liftN, ihf _ _ hc, iha _ _ hc] + | lam A b ihA ihb | forallE A b ihA ihb => + simp only [liftN] + refine congr (congrArg _ (ihA _ _ hc)) ?_ + have := ihb (j := j+1) (c := c+1) k d (by omega) + rwa [show j+1+d = j+d+1 from by omega] at this + +/-- Telescope form of `liftN_liftN_mid`. The outer lift is inserted at the +seam between the lift below the telescope and the lift that opened the +telescope's original ambient context. -/ +theorem liftTelN_liftN_mid : ∀ (tel : List VExpr) {j c : Nat} (k d : Nat), c ≤ j → + liftTelN k (liftTelN d (liftTelN 1 tel j) c) (j+d) = + liftTelN d (liftTelN (k+1) tel j) c + | [], _, _, _, _, _ => rfl + | A :: tel, j, c, k, d, hc => by + show ((A.liftN 1 j).liftN d c).liftN k (j+d) :: _ = + (A.liftN (k+1) j).liftN d c :: _ + rw [liftN_liftN_mid A k d hc] + congr 1 + rw [show j+d+1 = j+1+d from by omega] + exact liftTelN_liftN_mid tel k d (Nat.succ_le_succ hc) + +/-- Disjoint lifts commute: an outer lift below an inner one slides past +it, pushing the inner cutoff up. -/ +theorem liftN_liftN_comm : ∀ (e : VExpr) (n k c K : Nat), c ≤ K → + (e.liftN k K).liftN n c = (e.liftN n c).liftN k (K + n) := by + intro e + induction e with intro n k c K hc + | bvar i => + show VExpr.bvar (liftVar n (liftVar k i K) c) = .bvar (liftVar k (liftVar n i c) (K+n)) + congr 1 + rcases Nat.lt_or_ge i c with h2 | h2 + · rw [liftVar_lt (show i < K from by omega), liftVar_lt h2, + liftVar_lt (show i < K+n from by omega)] + · rcases Nat.lt_or_ge i K with h1 | h1 + · rw [liftVar_lt h1, liftVar_le h2, + liftVar_lt (show n+i < K+n from by omega)] + · rw [liftVar_le h1, liftVar_le (show c ≤ k+i from by omega), liftVar_le h2, + liftVar_le (show K+n ≤ n+i from by omega)] + omega + | sort | const => intros; rfl + | app f a ihf iha => simp [liftN, ihf _ _ _ _ hc, iha _ _ _ _ hc] + | lam A b ihA ihb | forallE A b ihA ihb => + simp only [liftN] + refine congr (congrArg _ (ihA _ _ _ _ hc)) ?_ + have := ihb n k (c+1) (K+1) (by omega) + rwa [show K+1+n = K+n+1 from by omega] at this + +/-- Generalized form of `liftN_liftN_mid`: expanding an arbitrary lift at +the seam above a disjoint lower lift adds the new width to that arbitrary +lift. -/ +theorem liftN_liftN_midN (e : VExpr) {j c : Nat} + (a k d : Nat) (hc : c ≤ j) : + ((e.liftN a j).liftN d c).liftN k (j+d) = + (e.liftN (a+k) j).liftN d c := by + rw [← liftN_liftN_comm (e.liftN a j) d k c j hc] + rw [liftN'_liftN_hi] + +/-- Telescope form of `liftN_liftN_midN`. -/ +theorem liftTelN_liftN_midN : + ∀ (tel : List VExpr) {j c : Nat} (a k d : Nat), c ≤ j → + liftTelN k (liftTelN d (liftTelN a tel j) c) (j+d) = + liftTelN d (liftTelN (a+k) tel j) c + | [], _, _, _, _, _, _ => rfl + | A :: tel, j, c, a, k, d, hc => by + show ((A.liftN a j).liftN d c).liftN k (j+d) :: _ = _ + rw [liftN_liftN_midN A a k d hc] + congr 1 + rw [show j+d+1 = j+1+d from by omega] + exact liftTelN_liftN_midN tel a k d (Nat.succ_le_succ hc) + +/-- Instantiation under a telescope: the entry at depth `q` instantiates +at `k+q`. -/ +def instTelN (a : VExpr) : List VExpr → Nat → List VExpr + | [], _ => [] + | A :: As, k => A.inst a k :: instTelN a As (k+1) + +attribute [local simp] instTelN + +theorem instTelN_length (a : VExpr) : ∀ (tel : List VExpr) (k : Nat), + (instTelN a tel k).length = tel.length + | [], _ => rfl + | _ :: tel, k => by simp [instTelN, instTelN_length a tel (k+1)] + +theorem instN_forallN (a : VExpr) : ∀ (tel : List VExpr) (X : VExpr) (k : Nat), + (forallN tel X).inst a k = forallN (instTelN a tel k) (X.inst a (k + tel.length)) + | [], _, _ => rfl + | A :: tel, X, k => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + rw [instN_forallN a tel X (k+1), + show k+1+tel.length = k+(tel.length+1) from by omega] + rfl + +/-- Iterated instantiation of a body under `es.length` binders, consuming +the spine outermost-first. -/ +def instRev : VExpr → List VExpr → VExpr + | C, [] => C + | C, e :: es => instRev (C.inst e es.length) es + +theorem instRev_closedN : ∀ (es : List VExpr) {C : VExpr}, C.ClosedN 0 → + instRev C es = C + | [], _, _ => rfl + | e :: es, C, hC => by + show instRev (C.inst e es.length) es = C + rw [hC.instN_eq (Nat.zero_le _)] + exact instRev_closedN es hC + +theorem instRev_bvar_ge : ∀ (es : List VExpr) {i : Nat}, es.length ≤ i → + instRev (.bvar i) es = .bvar (i - es.length) + | [], i, _ => by simp [instRev] + | e :: es, i, h => by + have h' : es.length < i := by + simp only [List.length_cons] at h + omega + show instRev ((VExpr.bvar i).inst e es.length) es = _ + rw [show (VExpr.bvar i).inst e es.length = .bvar (i-1) from by + show VExpr.instVar i e es.length = _ + unfold VExpr.instVar + rw [if_neg (by omega), if_neg (by omega)], + instRev_bvar_ge es (by omega)] + congr 1 + simp only [List.length_cons] + omega + +/-- The spine consumes a fully lifted body without a trace. -/ +theorem instRev_liftN_len : ∀ (es : List VExpr) (X : VExpr), + instRev (X.liftN es.length) es = X + | [], X => by simp [instRev, liftN_zero] + | e :: es, X => by + show instRev ((X.liftN (es.length+1)).inst e es.length) es = X + rw [show X.liftN (es.length+1) = (X.liftN es.length).liftN 1 es.length from + (liftN'_liftN' (Nat.zero_le _) (by omega)).symm, + inst_liftN] + exact instRev_liftN_len es X + +theorem instRev_bvar_lt_cons (es : List VExpr) (e : VExpr) {i : Nat} (hi : i < es.length) : + instRev (.bvar i) (e :: es) = instRev (.bvar i) es := by + show instRev ((VExpr.bvar i).inst e es.length) es = _ + congr 1 + show VExpr.instVar i e es.length = .bvar i + unfold VExpr.instVar + rw [if_pos hi] + +theorem mem_bvarRevRange : ∀ {m off : Nat} {x : VExpr}, x ∈ bvarRevRange off m → + ∃ i, x = .bvar i ∧ off ≤ i ∧ i < off + m + | m+1, off, x, h => by + rcases List.mem_cons.1 h with rfl | h + · exact ⟨off + m, rfl, by omega, by omega⟩ + · obtain ⟨i, rfl, h1, h2⟩ := mem_bvarRevRange h + exact ⟨i, rfl, h1, by omega⟩ + +/-- The last `es.length` variables consume to the spine itself. -/ +theorem map_instRev_bvarRevRange : ∀ (es : List VExpr), + (bvarRevRange 0 es.length).map (instRev · es) = es + | [] => rfl + | e :: es => by + show instRev (.bvar (0 + es.length)) (e :: es) :: + (bvarRevRange 0 es.length).map (instRev · (e :: es)) = e :: es + congr 1 + · show instRev ((VExpr.bvar (0 + es.length)).inst e es.length) es = e + rw [Nat.zero_add, + show (VExpr.bvar es.length).inst e es.length = e.liftN es.length from by + show VExpr.instVar es.length e es.length = _ + unfold VExpr.instVar + rw [if_neg (Nat.lt_irrefl _), if_pos rfl]] + exact instRev_liftN_len es e + · rw [List.map_congr_left fun x hx => ?_, map_instRev_bvarRevRange es] + obtain ⟨i, rfl, -, h2⟩ := mem_bvarRevRange hx + exact instRev_bvar_lt_cons es e (by omega) + +theorem map_instRev_bvarRevRange_ge (es : List VExpr) : ∀ (q off : Nat), + es.length ≤ off → + (bvarRevRange off q).map (instRev · es) = bvarRevRange (off - es.length) q + | 0, _, _ => rfl + | q+1, off, h => by + show instRev (.bvar (off+q)) es :: _ = _ + rw [instRev_bvar_ge es (by omega), map_instRev_bvarRevRange_ge es q off h] + congr 2 + omega + +theorem instRev_appN (es : List VExpr) : ∀ (f : VExpr) (as : List VExpr), + instRev (appN f as) es = appN (instRev f es) (as.map (instRev · es)) := by + induction es with intro f as + | nil => simp [instRev, List.map_id'] + | cons e es ih => + show instRev ((appN f as).inst e es.length) es = _ + rw [instN_appN, ih] + simp [instRev, List.map_map, Function.comp_def] + +theorem instRev_forallE_sort (u : VLevel) : ∀ (es : List VExpr) (D : VExpr), + instRev (.forallE D (.sort u)) es = .forallE (instRev D es) (.sort u) + | [], _ => rfl + | e :: es, D => instRev_forallE_sort u es (D.inst e es.length) + +theorem bvarRevRange_append : ∀ (m k : Nat), + bvarRevRange k m ++ bvarRevRange 0 k = bvarRevRange 0 (k + m) + | 0, k => by simp [bvarRevRange] + | m+1, k => by + show VExpr.bvar (k + m) :: (bvarRevRange k m ++ bvarRevRange 0 k) = _ + rw [bvarRevRange_append m k, show k + (m+1) = (k+m)+1 from rfl] + show _ = VExpr.bvar (0 + (k+m)) :: bvarRevRange 0 (k+m) + rw [Nat.zero_add] + +theorem appHead_appN : ∀ (as : List VExpr) (f : VExpr), (appN f as).appHead = f.appHead + | [], _ => rfl + | a :: as, f => appHead_appN as (f.app a) + +theorem appArgs_appN : ∀ (as acc : List VExpr) (f : VExpr), + (appN f as).appArgs acc = f.appArgs (as ++ acc) + | [], _, _ => rfl + | a :: as, acc, f => by + show (VExpr.appN (f.app a) as).appArgs acc = _ + rw [appArgs_appN as acc (f.app a)] + rfl + +theorem appN_appHead_appArgs : ∀ (e : VExpr) (acc : List VExpr), + appN e.appHead (e.appArgs acc) = appN e acc + | .app f a, acc => by + show appN f.appHead (f.appArgs (a :: acc)) = _ + rw [appN_appHead_appArgs f (a :: acc)] + rfl + | .bvar _, _ | .sort _, _ | .const _ _, _ | .lam _ _, _ | .forallE _ _, _ => rfl + +end VExpr + +/-! ## Anatomy of the stage-3 predicate -/ + +namespace VInductDecl + +/-- A constructor-type telescope splits as fields over the result. -/ +theorem forallN_ctorFields_resultOf : ∀ (e : VExpr), + VExpr.forallN (ctorFields e) e.resultOf = e + | .forallE B rest => congrArg (VExpr.forallE B) (forallN_ctorFields_resultOf rest) + | .bvar _ | .sort _ | .const _ _ | .app _ _ | .lam _ _ => rfl + +/-- Unpack a recursive-field check into its structural content. -/ +theorem isRecField_eq {U T np ni j B} (h : isRecField U T np ni j B = true) : + B = VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange j np ++ recFieldIdxs np B) ∧ + (recFieldIdxs np B).length = ni ∧ + ∀ e ∈ recFieldIdxs np B, e.hasConst T = false := by + simp only [isRecField, Bool.and_eq_true, beq_iff_eq, List.all_eq_true] at h + obtain ⟨⟨⟨h1, h2⟩, h3⟩, h4⟩ := h + refine ⟨?_, ?_, fun e he => by simpa [Bool.not_eq_true'] using h4 e he⟩ + · have hB : B = VExpr.appN B.appHead (B.appArgs []) := + (VExpr.appN_appHead_appArgs B []).symm + conv => lhs; rw [hB, h1, + show VExpr.appArgs B [] = + (VExpr.appArgs B []).take np ++ (VExpr.appArgs B []).drop np from + (List.take_append_drop ..).symm, + h3] + rfl + · simp only [recFieldIdxs, List.length_drop, h2] + omega + +/-- Unpack recursive-argument analysis beneath a possibly empty Pi telescope. +The terminal family application is seen under both the preceding constructor +fields (`j`) and the returned recursive binders. -/ +theorem recTarget?_eq {U T np ni j B As idxs} + (h : recTarget? U T np ni j B = some (As, idxs)) : + B = VExpr.forallN As + (VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange (j + As.length) np ++ idxs)) ∧ + idxs.length = ni ∧ + (∀ e ∈ idxs, e.hasConst T = false) ∧ + ∀ (q : Nat) (A : VExpr), As[q]? = some A → A.hasConst T = false := by + induction B generalizing j As idxs with + | forallE A rest _ ih => + simp only [recTarget?] at h + split at h + · contradiction + · next hA => + split at h + · next As' idxs' hrest => + simp only [Option.some.injEq, Prod.mk.injEq] at h + obtain ⟨rfl, rfl⟩ := h + obtain ⟨hshape, hlen, hfree, hbinders⟩ := ih hrest + refine ⟨?_, hlen, hfree, ?_⟩ + · show VExpr.forallE A rest = VExpr.forallE A _ + rw [hshape, show j + 1 + As'.length = j + (As'.length + 1) from by omega] + simp only [List.length_cons] + · intro q A' hq + match q, hq with + | 0, hq => + obtain rfl : A = A' := by simpa using hq + cases hAT : A.hasConst T with + | false => rfl + | true => exact (hA hAT).elim + | q+1, hq => exact hbinders q A' (by simpa using hq) + · contradiction + | bvar i | sort i | const i | app i i | lam i i => + simp only [recTarget?] at h + split at h + · next hrec => + simp only [Option.some.injEq, Prod.mk.injEq] at h + obtain ⟨rfl, rfl⟩ := h + obtain ⟨hshape, hlen, hfree⟩ := isRecField_eq hrec + exact ⟨by simpa using hshape, hlen, hfree, by simp⟩ + · contradiction + +/-- Public recursive-argument anatomy, including the stable field and +one-family target indices carried by the descriptor. -/ +theorem recArg?_eq {U T np ni j B r} + (h : recArg? U T np ni j B = some r) : + r.fieldIndex = j ∧ r.targetType = 0 ∧ + B = VExpr.forallN r.binders + (VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange (j + r.binders.length) np ++ r.indices)) ∧ + r.indices.length = ni ∧ + (∀ e ∈ r.indices, e.hasConst T = false) ∧ + ∀ (q : Nat) (A : VExpr), r.binders[q]? = some A → A.hasConst T = false := by + unfold recArg? at h + split at h + · next binders indices htarget => + simp only [Option.some.injEq] at h + subst r + obtain ⟨hshape, hlen, hfree, hbinders⟩ := recTarget?_eq htarget + exact ⟨rfl, rfl, hshape, hlen, hfree, hbinders⟩ + · contradiction + +/-- With no Pi binders, recursive-argument recognition is exactly the direct +recursive-field check. -/ +theorem recTarget?_nil {U T np ni j B idxs} + (h : recTarget? U T np ni j B = some ([], idxs)) : + isRecField U T np ni j B = true ∧ idxs = recFieldIdxs np B := by + cases B with + | forallE A rest => + simp only [recTarget?] at h + split at h + · contradiction + · cases hrest : recTarget? U T np ni (j+1) rest with + | none => simp [hrest] at h + | some out => + obtain ⟨As, is⟩ := out + simp [hrest] at h + | bvar i | sort i | const i | app i i | lam i i => + simp only [recTarget?] at h + split at h + · next hrec => + simp only [Option.some.injEq, Prod.mk.injEq] at h + exact ⟨hrec, h.2.symm⟩ + · contradiction + +theorem recArg?_nil {U T np ni j B r} + (h : recArg? U T np ni j B = some r) (hr : r.binders = []) : + isRecField U T np ni j B = true ∧ r.indices = recFieldIdxs np B := by + unfold recArg? at h + split at h + · next binders indices htarget => + simp only [Option.some.injEq] at h + subst r + simp only at hr + subst binders + exact recTarget?_nil htarget + · contradiction + +/-- A direct recursive-field success normalizes to the descriptor with an +empty binder telescope. -/ +theorem recArg?_of_isRecField {U T np ni j B} + (h : isRecField U T np ni j B = true) : + recArg? U T np ni j B = some + { fieldIndex := j, binders := [], targetType := 0, + indices := recFieldIdxs np B } := by + cases B with + | forallE A rest => simp [isRecField, VExpr.appHead] at h + | bvar i | sort i | const i | app i i | lam i i => + simp_all [recArg?, recTarget?] + +theorem stage3Ctor_eq {U T np ni} : ∀ {j₀ : Nat} {e : VExpr}, + stage3Ctor U T np ni j₀ e = true → + e = VExpr.forallN (ctorFields e) + (VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange (j₀ + (ctorFields e).length) np ++ + recFieldIdxs np e.resultOf)) ∧ + (recFieldIdxs np e.resultOf).length = ni ∧ + (∀ x ∈ recFieldIdxs np e.resultOf, x.hasConst T = false) ∧ + ∀ q B, (ctorFields e)[q]? = some B → stage3Field U T np ni (j₀ + q) B = true := by + intro j₀ e h + induction e generalizing j₀ with + | forallE B rest _ ih => + rw [show stage3Ctor U T np ni j₀ (.forallE B rest) = + (stage3Field U T np ni j₀ B && stage3Ctor U T np ni (j₀+1) rest) from rfl, + Bool.and_eq_true] at h + have ⟨ih1, ih2, ih3, ih4⟩ := ih h.2 + refine ⟨?_, ih2, ih3, ?_⟩ + · show VExpr.forallE _ _ = VExpr.forallE _ _ + conv => lhs; rw [ih1] + rw [show j₀+1+(ctorFields rest).length = j₀+((ctorFields rest).length+1) from by omega] + rfl + · intro q B' hB' + match q, hB' with + | 0, hB' => + obtain rfl : B = B' := by simpa [ctorFields] using hB' + exact h.1 + | q+1, hB' => + have := ih4 q B' (by simpa [ctorFields] using hB') + rwa [show j₀+1+q = j₀+(q+1) from by omega] at this + | bvar i => + exact ⟨(isRecField_eq h).1, (isRecField_eq h).2.1, (isRecField_eq h).2.2, + fun q B h' => by simp [ctorFields] at h'⟩ + | sort l => + exact ⟨(isRecField_eq h).1, (isRecField_eq h).2.1, (isRecField_eq h).2.2, + fun q B h' => by simp [ctorFields] at h'⟩ + | const c ls => + exact ⟨(isRecField_eq h).1, (isRecField_eq h).2.1, (isRecField_eq h).2.2, + fun q B h' => by simp [ctorFields] at h'⟩ + | app f a _ _ => + exact ⟨(isRecField_eq h).1, (isRecField_eq h).2.1, (isRecField_eq h).2.2, + fun q B h' => by simp [ctorFields] at h'⟩ + | lam A b _ _ => + exact ⟨(isRecField_eq h).1, (isRecField_eq h).2.1, (isRecField_eq h).2.2, + fun q B h' => by simp [ctorFields] at h'⟩ + +/-- Failure of the legacy singleton predicate is exactly failure to produce +the one-family checked descriptor. -/ +theorem checked?_eq_none_iff {decl : VInductDecl} : + decl.checked? = none ↔ decl.singletonStage3 = false := by + unfold singletonStage3 + cases decl.checked? <;> simp + +/-- Successful singleton acceptance retains the descriptor rather than +discarding it. -/ +theorem exists_checked_of_singletonStage3 {decl : VInductDecl} + (h : decl.singletonStage3 = true) : + ∃ checked, decl.checked? = some checked := by + unfold singletonStage3 at h + cases hc : decl.checked? with + | none => simp [hc] at h + | some checked => exact ⟨checked, rfl⟩ + +/-- Public Stage-3 rejection is exactly failure to retain a complete mutual +generation descriptor. -/ +theorem identityBlockGeneration?_eq_none_iff {decl : VInductDecl} : + decl.identityBlockGeneration? = none ↔ decl.stage3 = false := by + unfold stage3 + cases decl.identityBlockGeneration? <;> simp + +/-- Public Stage-3 acceptance retains the exact block descriptor used by the +transaction. -/ +theorem exists_blockGeneration_of_stage3 {decl : VInductDecl} + (h : decl.stage3 = true) : + ∃ generation, decl.identityBlockGeneration? = some generation := by + unfold stage3 at h + cases hgeneration : decl.identityBlockGeneration? with + | none => simp [hgeneration] at h + | some generation => exact ⟨generation, rfl⟩ + +/-- Proof-level constructor-header coherence exported from the computational +normalization-shape check. -/ +def CtorHeaderEq (source view : VConstVal) : Prop := + source.name = view.name ∧ source.uvars = view.uvars + +/-- Proof-level family-header coherence, including constructor order. -/ +def TypeHeaderEq (source view : VInductiveType) : Prop := + source.name = view.name ∧ source.uvars = view.uvars ∧ + List.Forall₂ CtorHeaderEq source.ctors view.ctors + +theorem sameCtorHeaders_iff_forall₂ : ∀ {source view}, + sameCtorHeaders source view = true ↔ + List.Forall₂ CtorHeaderEq source view + | [], [] => ⟨fun _ => .nil, fun _ => rfl⟩ + | [], _ :: _ => by + constructor + · intro h; exact Bool.noConfusion h + · intro h; nomatch h + | _ :: _, [] => by + constructor + · intro h; exact Bool.noConfusion h + · intro h; nomatch h + | source :: sources, view :: views => by + constructor + · intro h + simp only [sameCtorHeaders, Bool.and_eq_true, beq_iff_eq] at h + exact .cons ⟨h.1.1, h.1.2⟩ (sameCtorHeaders_iff_forall₂.1 h.2) + · intro h + obtain ⟨hhead, htail⟩ := List.forall₂_cons.1 h + simp only [sameCtorHeaders, Bool.and_eq_true, beq_iff_eq] + exact ⟨⟨hhead.1, hhead.2⟩, sameCtorHeaders_iff_forall₂.2 htail⟩ + +theorem sameTypeHeaders_iff_forall₂ : ∀ {source view}, + sameTypeHeaders source view = true ↔ + List.Forall₂ TypeHeaderEq source view + | [], [] => ⟨fun _ => .nil, fun _ => rfl⟩ + | [], _ :: _ => by + constructor + · intro h; exact Bool.noConfusion h + · intro h; nomatch h + | _ :: _, [] => by + constructor + · intro h; exact Bool.noConfusion h + · intro h; nomatch h + | source :: sources, view :: views => by + constructor + · intro h + simp only [sameTypeHeaders, Bool.and_eq_true, beq_iff_eq] at h + exact .cons + ⟨h.1.1.1, h.1.1.2, sameCtorHeaders_iff_forall₂.1 h.1.2⟩ + (sameTypeHeaders_iff_forall₂.1 h.2) + · intro h + obtain ⟨hhead, htail⟩ := List.forall₂_cons.1 h + simp only [sameTypeHeaders, Bool.and_eq_true, beq_iff_eq] + exact ⟨⟨⟨hhead.1, hhead.2.1⟩, + sameCtorHeaders_iff_forall₂.2 hhead.2.2⟩, + sameTypeHeaders_iff_forall₂.2 htail⟩ + +/-- Every accepted normalization preserves declaration arity and all +family/constructor identities in order. -/ +theorem Normalization.shape {source : VInductDecl} + (norm : Normalization source) : + source.uvars = norm.view.uvars ∧ + source.nparams = norm.view.nparams ∧ + List.Forall₂ TypeHeaderEq source.types norm.view.types := by + have h := norm.shape_eq + simp only [normalizationShape, Bool.and_eq_true, beq_iff_eq, + sameTypeHeaders_iff_forall₂] at h + exact ⟨h.1.1, h.1.2, h.2⟩ + +/-- The singleton source family paired with the checked singleton analysis +view. This is the raw payload future normalized generation must insert. -/ +theorem NormalizedChecked.source_anatomy {source : VInductDecl} + (block : NormalizedChecked source) : + ∃ raw, + source.types = [raw] ∧ + raw.name = block.checked.type.name ∧ + raw.uvars = block.checked.type.uvars ∧ + List.Forall₂ CtorHeaderEq raw.ctors block.checked.type.ctors := by + have htypes := block.normalization.shape.2.2 + rw [block.source_types_eq, block.checked.types_eq] at htypes + obtain ⟨htype, -⟩ := List.forall₂_cons.1 htypes + exact ⟨block.sourceType, block.source_types_eq, + htype.1, htype.2.1, htype.2.2⟩ + +theorem NormalizedChecked.uvars_eq {source : VInductDecl} + (block : NormalizedChecked source) : + source.uvars = block.normalization.view.uvars := + block.normalization.shape.1 + +theorem NormalizedChecked.nparams_eq {source : VInductDecl} + (block : NormalizedChecked source) : + source.nparams = block.normalization.view.nparams := + block.normalization.shape.2.1 + +/-- Unpack the complete executable layout certificate used by mixed +raw/view generation. -/ +theorem GenerationChecked.shape {source : VInductDecl} + (gen : GenerationChecked source) : + gen.block.rawParams.length = source.nparams ∧ + gen.block.rawParams.length = gen.block.checked.params.length ∧ + gen.block.rawIndices.length = gen.block.checked.indices.length ∧ + gen.block.ctorPairs.length = gen.block.sourceType.ctors.length ∧ + gen.block.ctorPairs.length = gen.block.checked.constructors.length ∧ + ∀ ctor ∈ gen.block.ctorPairs, + ctor.raw.name = ctor.view.value.name ∧ + ctor.raw.uvars = ctor.view.value.uvars ∧ + (VExpr.telN source.nparams ctor.raw.type).length = source.nparams ∧ + (ctor.rawFields source.nparams).length = ctor.view.fields.length := by + have h := gen.shape_eq + simp only [NormalizedChecked.generationShape, + NormalizedCtor.generationShape, Bool.and_eq_true, beq_iff_eq, + List.all_eq_true] at h + obtain ⟨⟨⟨⟨⟨hparams, hparams'⟩, hindices⟩, hraws⟩, hviews⟩, + hctors⟩ := h + refine ⟨hparams, hparams', hindices, hraws, hviews, ?_⟩ + intro ctor hctor + obtain ⟨⟨⟨hname, hU⟩, htel⟩, hfields⟩ := hctors ctor hctor + exact ⟨hname, hU, htel, hfields⟩ + +theorem pairNormalizedCtors_map_raw : + ∀ (raws : List VConstVal) (views : List CheckedCtor), + raws.length = views.length → + (pairNormalizedCtors raws views).map (·.raw) = raws + | [], [], _ => rfl + | raw :: raws, view :: views, h => by + simp only [pairNormalizedCtors, List.map_cons, List.cons.injEq, true_and] + apply pairNormalizedCtors_map_raw + simpa using h + +theorem pairNormalizedCtors_map_view : + ∀ (raws : List VConstVal) (views : List CheckedCtor), + raws.length = views.length → + (pairNormalizedCtors raws views).map (·.view) = views + | [], [], _ => rfl + | raw :: raws, view :: views, h => by + simp only [pairNormalizedCtors, List.map_cons, List.cons.injEq, true_and] + apply pairNormalizedCtors_map_view + simpa using h + +/-- Membership in an identity pairing recovers the single raw constructor +that supplied both sides of the pair. -/ +theorem pairNormalizedCtors_map_self_mem + {U : Nat} {T : Name} {np ni : Nat} : + ∀ {cs : List VConstVal} {ctor : NormalizedCtor}, + ctor ∈ pairNormalizedCtors cs + (cs.map (CheckedCtor.ofDirect U T np ni)) → + ∃ c ∈ cs, ctor = + ⟨c, CheckedCtor.ofDirect U T np ni c⟩ + | [], _, h => by simp [pairNormalizedCtors] at h + | c :: cs, ctor, h => by + simp only [List.map_cons, pairNormalizedCtors, List.mem_cons] at h + rcases h with rfl | h + · exact ⟨c, .head _, rfl⟩ + · obtain ⟨c', hc', rfl⟩ := + pairNormalizedCtors_map_self_mem h + exact ⟨c', .tail _ hc', rfl⟩ + +/-- Every raw constructor occurs in its canonical identity pair. -/ +theorem pairNormalizedCtors_map_self_contains + {U : Nat} {T : Name} {np ni : Nat} : + ∀ {cs : List VConstVal} {c : VConstVal}, + c ∈ cs → + (⟨c, CheckedCtor.ofDirect U T np ni c⟩ : + NormalizedCtor) ∈ + pairNormalizedCtors cs + (cs.map (CheckedCtor.ofDirect U T np ni)) + | _ :: _, _, .head _ => .head _ + | _ :: _, _, .tail _ hc => + .tail _ (pairNormalizedCtors_map_self_contains hc) + +/-- The identity generation path pairs each stored constructor with its own +direct analyzer descriptor. -/ +theorem Checked.identityGeneration_ctor + {source : VInductDecl} (checked : source.Checked) + {ctor : NormalizedCtor} + (hctor : ctor ∈ checked.identityGeneration.block.ctorPairs) : + ∃ c ∈ checked.type.ctors, ctor = + ⟨c, CheckedCtor.ofDirect source.uvars checked.type.name + source.nparams checked.indices.length c⟩ := by + apply pairNormalizedCtors_map_self_mem + simpa only [Checked.identityGeneration, Checked.identityBlock, + NormalizedChecked.ctorPairs, checked.constructors_eq] using hctor + +/-- Positional pairing neither drops nor reorders raw constructors. -/ +theorem GenerationChecked.rawCtors_eq {source : VInductDecl} + (gen : GenerationChecked source) : + gen.block.ctorPairs.map (·.raw) = gen.block.sourceType.ctors := by + apply pairNormalizedCtors_map_raw + exact gen.shape.2.2.2.1.symm.trans gen.shape.2.2.2.2.1 + +/-- Every checked constructor appears in the same paired position. -/ +theorem GenerationChecked.viewCtors_eq {source : VInductDecl} + (gen : GenerationChecked source) : + gen.block.ctorPairs.map (·.view) = gen.block.checked.constructors := by + apply pairNormalizedCtors_map_view + exact gen.shape.2.2.2.1.symm.trans gen.shape.2.2.2.2.1 + +/-! ### Block-generation positional facts -/ + +theorem pairNormalizedFamilies_map_raw : + ∀ (raws : List VInductiveType) (views : List CheckedFamilyData), + raws.length = views.length → + (pairNormalizedFamilies raws views).map (·.raw) = raws + | [], [], _ => rfl + | raw :: raws, view :: views, h => by + simp only [pairNormalizedFamilies, List.map_cons, + List.cons.injEq, true_and] + apply pairNormalizedFamilies_map_raw + simpa using h + +theorem pairNormalizedFamilies_map_view : + ∀ (raws : List VInductiveType) (views : List CheckedFamilyData), + raws.length = views.length → + (pairNormalizedFamilies raws views).map (·.view) = views + | [], [], _ => rfl + | raw :: raws, view :: views, h => by + simp only [pairNormalizedFamilies, List.map_cons, + List.cons.injEq, true_and] + apply pairNormalizedFamilies_map_view + simpa using h + +/-- Unpack the executable positional gate for mutual generation. -/ +theorem BlockGenerationChecked.shape {source : VInductDecl} + (gen : BlockGenerationChecked source) : + gen.block.rawParams.length = source.nparams ∧ + gen.block.rawParams.length = gen.block.checked.params.length ∧ + gen.families.length = source.types.length ∧ + gen.families.length = gen.block.checked.families.data.length ∧ + ∀ family ∈ gen.families, + family.raw.name = family.view.value.name ∧ + family.raw.uvars = family.view.value.uvars ∧ + (family.rawParams source.nparams).length = source.nparams ∧ + (family.rawIndices source.nparams).length = + family.view.indices.length ∧ + family.ctorPairs.length = family.raw.ctors.length ∧ + family.ctorPairs.length = family.view.constructors.length ∧ + ∀ ctor ∈ family.ctorPairs, + ctor.raw.name = ctor.view.value.name ∧ + ctor.raw.uvars = ctor.view.value.uvars ∧ + (VExpr.telN source.nparams ctor.raw.type).length = + source.nparams ∧ + (ctor.rawFields source.nparams).length = ctor.view.fields.length := by + have h := gen.shape_eq + simp only [NormalizedCheckedBlock.blockGenerationShape, + NormalizedFamily.generationShape, NormalizedCtor.generationShape, + Bool.and_eq_true, beq_iff_eq, List.all_eq_true] at h + obtain ⟨h, -⟩ := h + obtain ⟨⟨⟨⟨hparams, hparams'⟩, hraws⟩, hviews⟩, hfamilies⟩ := h + refine ⟨hparams, hparams', hraws, hviews, ?_⟩ + intro family hfamily + obtain ⟨⟨⟨⟨⟨⟨hname, hU⟩, htel⟩, hindices⟩, + hrawCtors⟩, hviewCtors⟩, hctors⟩ := hfamilies family hfamily + refine ⟨hname, hU, htel, hindices, hrawCtors, hviewCtors, ?_⟩ + intro ctor hctor + obtain ⟨⟨⟨hctorName, hctorU⟩, hctorTel⟩, hctorFields⟩ := + hctors ctor hctor + exact ⟨hctorName, hctorU, hctorTel, hctorFields⟩ + +theorem BlockGenerationChecked.family_uvars {source : VInductDecl} + (gen : BlockGenerationChecked source) {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + family.raw.uvars = source.uvars := by + have h := gen.shape_eq + simp only [NormalizedCheckedBlock.blockGenerationShape, + Bool.and_eq_true, beq_iff_eq, List.all_eq_true] at h + exact (h.2 family hfamily).1 + +theorem BlockGenerationChecked.ctor_uvars {source : VInductDecl} + (gen : BlockGenerationChecked source) {family : NormalizedFamily} + (hfamily : family ∈ gen.families) {ctor : NormalizedCtor} + (hctor : ctor ∈ family.ctorPairs) : + ctor.raw.uvars = source.uvars := by + have h := gen.shape_eq + simp only [NormalizedCheckedBlock.blockGenerationShape, + Bool.and_eq_true, beq_iff_eq, List.all_eq_true] at h + exact (h.2 family hfamily).2 ctor hctor + +theorem BlockGenerationChecked.families_map_raw {source : VInductDecl} + (gen : BlockGenerationChecked source) : + gen.families.map (·.raw) = source.types := by + apply pairNormalizedFamilies_map_raw + exact gen.shape.2.2.1.symm.trans gen.shape.2.2.2.1 + +theorem NormalizedFamily.ctorPairs_map_raw + {source : VInductDecl} {gen : BlockGenerationChecked source} + {family : NormalizedFamily} (hfamily : family ∈ gen.families) : + family.ctorPairs.map (·.raw) = family.raw.ctors := by + apply pairNormalizedCtors_map_raw + exact (gen.shape.2.2.2.2 family hfamily).2.2.2.2.1.symm.trans + (gen.shape.2.2.2.2 family hfamily).2.2.2.2.2.1 + +@[simp] theorem NormalizedFamily.blockCtors_map_raw + (family : NormalizedFamily) : + family.blockCtors.map (·.ctor.raw) = family.ctorPairs.map (·.raw) := by + unfold NormalizedFamily.blockCtors + induction family.ctorPairs with + | nil => rfl + | cons ctor ctors ih => + simp only [List.map_cons, List.cons.injEq, true_and] + exact ih + +theorem flatMap_congr_of_mem {α β : Type} (xs : List α) + (f g : α → List β) (h : ∀ x ∈ xs, f x = g x) : + xs.flatMap f = xs.flatMap g := by + induction xs with + | nil => rfl + | cons x xs ih => + simp only [List.flatMap_cons] + rw [h x (.head _), ih (fun y hy => h y (.tail _ hy))] + +theorem map_flatMap_eq {α β γ : Type} (xs : List α) + (f : α → List β) (g : β → γ) : + (xs.flatMap f).map g = xs.flatMap (fun x => (f x).map g) := by + induction xs with + | nil => rfl + | cons x xs ih => + simp only [List.flatMap_cons, List.map_append] + rw [ih] + +theorem BlockGenerationChecked.flatCtors_map_raw + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.flatCtors.map (·.ctor.raw) = source.blockConstructorConstants := by + rw [VInductDecl.blockConstructorConstants, ← gen.families_map_raw] + unfold BlockGenerationChecked.flatCtors NormalizedCheckedBlock.flatCtors + rw [map_flatMap_eq] + simp only [List.flatMap_map] + apply flatMap_congr_of_mem + intro family hfamily + rw [family.blockCtors_map_raw] + exact family.ctorPairs_map_raw hfamily + +theorem BlockGenerationChecked.flatCtor_uvars + {source : VInductDecl} (gen : BlockGenerationChecked source) + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + constructor.ctor.raw.uvars = source.uvars := by + simp only [BlockGenerationChecked.flatCtors, + NormalizedCheckedBlock.flatCtors, List.mem_flatMap] at hconstructor + obtain ⟨family, hfamily, hconstructor⟩ := hconstructor + simp only [NormalizedFamily.blockCtors, List.mem_map] at hconstructor + obtain ⟨ctor, hctor, rfl⟩ := hconstructor + exact gen.ctor_uvars hfamily hctor + +/-- The validation staging fold is definitionally the family-constant phase +of block generation, modulo the explicit `toVConstVal` map. -/ +theorem blockTypeConstants_foldlM_eq_stageInductiveTypes + (env : VEnv) (source : VInductDecl) : + source.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) env = + env.stageInductiveTypes source.types := by + unfold VInductDecl.blockTypeConstants VEnv.stageInductiveTypes + induction source.types generalizing env with + | nil => rfl + | cons type types ih => + simp only [List.map_cons, List.foldlM_cons] + apply Option.bind_congr + intro env' _ + exact ih env' + +/-- Identity normalization is computationally the legacy analyzer. -/ +theorem Normalization.identity_checked? (source : VInductDecl) : + (Normalization.identity source).checked? = source.checked? := rfl + +/-- A successful normalized analysis retains the exact normalization that was +analyzed; callers do not need to restate this projection as an unrelated +equality. -/ +theorem Normalization.check?_normalization + {source : VInductDecl} {norm : Normalization source} + {block : NormalizedChecked source} + (h : norm.check? = some block) : + block.normalization = norm := by + unfold Normalization.check? at h + split at h <;> try contradiction + split at h <;> try contradiction + cases h + rfl + +/-- A successful generation analysis is indexed by the same normalization +retained in its checked block. -/ +theorem Normalization.generation?_normalization + {source : VInductDecl} {norm : Normalization source} + {generation : GenerationChecked source} + (h : norm.generation? = some generation) : + generation.block.normalization = norm := by + unfold Normalization.generation? at h + obtain ⟨block, hblock, hgeneration⟩ := + Option.bind_eq_some_iff.mp h + have hnorm := Normalization.check?_normalization hblock + unfold NormalizedChecked.generation? at hgeneration + split at hgeneration + · have hgeneration' := Option.some.inj hgeneration + rw [← hgeneration'] + exact hnorm + · contradiction + +theorem identityChecked?_isSome (source : VInductDecl) : + (identityChecked? source).isSome = source.checked?.isSome := by + obtain ⟨U, np, types⟩ := source + cases types with + | nil => rfl + | cons type types => + cases types with + | nil => + unfold identityChecked? Normalization.check? + split + · next sourceType hsource => + have htype : type = sourceType := by simpa using hsource + subst sourceType + split + · next checked hchecked => + rw [← Normalization.identity_checked?] + exact (congrArg (fun x => x.isSome) hchecked).symm + · next hchecked => + rw [← Normalization.identity_checked?] + exact (congrArg (fun x => x.isSome) hchecked).symm + · next hsource => exact (hsource type rfl).elim + | cons type' types => rfl + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Normalization.shape [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizedChecked.source_anatomy [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationChecked.shape [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationChecked.rawCtors_eq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationChecked.viewCtors_eq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Normalization.check?_normalization [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Normalization.generation?_normalization [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.identityChecked?_isSome [propext, Classical.choice, Quot.sound] + +/- Identity-normalization compatibility is part of the public artifact +boundary. The conversion itself is computational; its proof fields inherit +the standard `Classical.choice` dependency already present in +`Normalization.identity`'s reflexive header check. -/ +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.analyzer_eq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.identityBlock_generationShape [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.motiveType_eq_legacy [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.minorTypes_eq_legacy [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.recursor_eq_legacy [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.generatedRules_eq_legacy [propext, Classical.choice, Quot.sound] + +/-- The four executable checks retained by a successful descriptor. Keeping +this bridge centralized lets the public proof API expose logical facts without +each consumer re-destructing `stage3Core`. -/ +theorem Checked.analysis_accepted {decl : VInductDecl} (checked : decl.Checked) : + stage3DirectCore decl.uvars decl.nparams checked.type = true ∧ + namesOK checked.type = true ∧ closedOK checked.type = true ∧ + levelsOK decl.uvars checked.type = true := by + cases decl with + | mk U np tys => + have htypes : tys = [checked.type] := checked.types_eq + have hcore := checked.accepted + simp only [stage3Core, htypes, Bool.and_eq_true] at hcore + exact ⟨hcore.1, hcore.2.1, hcore.2.2.1, hcore.2.2.2⟩ + +/-- Every successful descriptor has pairwise-distinct generated type, +constructor, and recursor names. Downstream proofs should consume this fact +instead of unfolding the boolean analyzer. -/ +theorem Checked.names_nodup {decl : VInductDecl} (checked : decl.Checked) : + checked.names.Nodup := by + rw [checked.names_eq] + exact of_decide_eq_true (by simpa [namesOK] using checked.analysis_accepted.2.1) + +/-- A checked family's type metadata has no loose term variables. -/ +theorem Checked.type_closed {decl : VInductDecl} (checked : decl.Checked) : + checked.type.type.ClosedN 0 := by + have hclosed := checked.analysis_accepted.2.2.1 + simp only [closedOK, Bool.and_eq_true, List.all_eq_true] at hclosed + exact of_decide_eq_true hclosed.1 + +/-- Every constructor type retained by a successful descriptor has no loose +term variables. -/ +theorem Checked.ctor_closed {decl : VInductDecl} (checked : decl.Checked) + {ctor : VConstVal} (hctor : ctor ∈ checked.type.ctors) : ctor.type.ClosedN 0 := by + have hclosed := checked.analysis_accepted.2.2.1 + simp only [closedOK, Bool.and_eq_true, List.all_eq_true] at hclosed + exact of_decide_eq_true (hclosed.2 ctor hctor) + +/-- Every universe annotation in a checked family's type is in range. -/ +theorem Checked.type_levelWF {decl : VInductDecl} (checked : decl.Checked) : + checked.type.type.LevelWF decl.uvars := by + have hlevels := checked.analysis_accepted.2.2.2 + simp only [levelsOK, Bool.and_eq_true, List.all_eq_true] at hlevels + exact of_decide_eq_true hlevels.1 + +/-- Every universe annotation in a checked constructor type is in range. -/ +theorem Checked.ctor_levelWF {decl : VInductDecl} (checked : decl.Checked) + {ctor : VConstVal} (hctor : ctor ∈ checked.type.ctors) : + ctor.type.LevelWF decl.uvars := by + have hlevels := checked.analysis_accepted.2.2.2 + simp only [levelsOK, Bool.and_eq_true, List.all_eq_true] at hlevels + exact of_decide_eq_true (hlevels.2 ctor hctor) + +/-- The direct one-family facts carried by the descriptor, including the +new pre-declaration prohibition on self-reference in parameter/index domains. -/ +theorem Checked.direct_anatomy {decl : VInductDecl} (checked : decl.Checked) : + checked.type.uvars = decl.uvars ∧ checked.params.length = decl.nparams ∧ + checked.resultLevel.WF decl.uvars ∧ + (∀ P ∈ checked.params, P.hasConst checked.type.name = false) ∧ + (∀ I ∈ checked.indices, I.hasConst checked.type.name = false) ∧ + ∀ c ∈ checked.type.ctors, c.uvars = decl.uvars ∧ + VExpr.telN decl.nparams c.type = VExpr.telN decl.nparams checked.type.type ∧ + stage3Ctor decl.uvars checked.type.name decl.nparams checked.indices.length 0 + (VExpr.dropN decl.nparams c.type) = true := by + have hdirect := checked.analysis_accepted.1 + simp only [stage3DirectCore, Bool.and_eq_true, beq_iff_eq, + List.all_eq_true] at hdirect + obtain ⟨⟨⟨⟨hU, hparams⟩, hresult⟩, hformer⟩, hctors⟩ := hdirect + simp only [typeFormerOK, Bool.and_eq_true, List.all_eq_true] at hformer + refine ⟨hU, by simpa [checked.params_eq] using hparams, ?_, ?_, ?_, ?_⟩ + · rw [checked.result_eq] at hresult + simpa using hresult + · simpa [checked.params_eq] using hformer.1 + · simpa [checked.indices_eq] using hformer.2 + · intro c hc + simpa [checked.indices_eq, and_assoc] using hctors c hc + +/-- The raw family payload has the source declaration's universe arity. -/ +theorem NormalizedChecked.sourceType_uvars_eq {source : VInductDecl} + (block : NormalizedChecked source) : + block.sourceType.uvars = source.uvars := by + obtain ⟨raw, hsource, _, hrawU, _⟩ := block.source_anatomy + have hraw : raw = block.sourceType := by + simpa using hsource.symm.trans block.source_types_eq + subst raw + exact hrawU.trans + (block.checked.direct_anatomy.1.trans block.uvars_eq.symm) + +/-- The raw and checked family identities agree. -/ +theorem NormalizedChecked.sourceType_name_eq {source : VInductDecl} + (block : NormalizedChecked source) : + block.sourceType.name = block.checked.type.name := by + obtain ⟨raw, hsource, hname, _, _⟩ := block.source_anatomy + have hraw : raw = block.sourceType := by + simpa using hsource.symm.trans block.source_types_eq + subst raw + exact hname + +/-- Every paired raw constructor has the source declaration's universe +arity. -/ +theorem GenerationChecked.ctor_uvars_eq {source : VInductDecl} + (gen : GenerationChecked source) {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + ctor.raw.uvars = source.uvars := by + have hview : ctor.view ∈ gen.block.checked.constructors := by + rw [← gen.viewCtors_eq] + exact List.mem_map.2 ⟨ctor, hctor, rfl⟩ + rw [gen.block.checked.constructors_eq] at hview + have hviewU : + ctor.view.value.uvars = gen.block.normalization.view.uvars := by + obtain ⟨c, hc, hcview⟩ := List.mem_map.1 hview + rw [← hcview] + exact (gen.block.checked.direct_anatomy.2.2.2.2.2 c hc).1 + have hpairU := (gen.shape.2.2.2.2.2 ctor hctor).2.1 + exact hpairU.trans (hviewU.trans gen.block.uvars_eq.symm) + +/-- A paired checked constructor is exactly the direct analyzer result for +the corresponding constructor in the normalized view. The statement is +rewritten to the raw block's public header, whose equality is certified by +normalization shape. -/ +theorem GenerationChecked.viewCtor_ofDirect {source : VInductDecl} + (gen : GenerationChecked source) {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + ∃ c ∈ gen.block.checked.type.ctors, + ctor.view = CheckedCtor.ofDirect source.uvars + gen.block.sourceType.name source.nparams + gen.block.checked.indices.length c := by + have hview : ctor.view ∈ gen.block.checked.constructors := by + rw [← gen.viewCtors_eq] + exact List.mem_map.2 ⟨ctor, hctor, rfl⟩ + rw [gen.block.checked.constructors_eq] at hview + obtain ⟨c, hc, hcview⟩ := List.mem_map.1 hview + refine ⟨c, hc, ?_⟩ + rw [gen.block.uvars_eq, gen.block.nparams_eq, + gen.block.sourceType_name_eq] + exact hcview.symm + +/-- Re-index declaration well-formedness onto the normalized checked data. -/ +theorem Checked.wf_of_decl {decl : VInductDecl} (checked : decl.Checked) + (hdecl : decl.WF env) : checked.WF env := by + obtain ⟨-, hwf⟩ := hdecl + obtain ⟨htel, hctors⟩ := hwf checked.type (by + rw [checked.types_eq] + exact .head _) + have hsort : sortLevel decl.nparams checked.type = checked.resultLevel := by + simp only [sortLevel, checked.result_eq] + unfold Checked.WF + refine ⟨?_, fun c hc => ?_⟩ + · simpa [checked.params_eq, checked.indices_eq] using htel + · simpa [checked.params_eq, checked.indices_eq, hsort] using hctors c hc + +/-- Normalized semantic evidence reconstructs the legacy declaration-level +`WF` contract. This is the compatibility direction used while clients migrate +to `Checked.WF`. -/ +theorem Checked.to_declWF {decl : VInductDecl} (checked : decl.Checked) + (hchecked : decl.checked? = some checked) (hwf : checked.WF env) : decl.WF env := by + refine ⟨by simp [singletonStage3, hchecked], ?_⟩ + intro ty hty + rw [checked.types_eq] at hty + obtain rfl := List.mem_singleton.1 hty + have hsort : sortLevel decl.nparams checked.type = checked.resultLevel := by + simp only [sortLevel, checked.result_eq] + unfold Checked.WF at hwf + simpa [checked.params_eq, checked.indices_eq, hsort] using hwf + +/-- The environment-indexed declaration contract is exactly the existence of +the analyzer result together with semantic evidence for its normalized data. -/ +theorem wf_iff_exists_checked {decl : VInductDecl} : + decl.WF env ↔ ∃ checked, decl.checked? = some checked ∧ checked.WF env := by + constructor + · intro hdecl + obtain ⟨checked, hchecked⟩ := exists_checked_of_singletonStage3 hdecl.1 + exact ⟨checked, hchecked, checked.wf_of_decl hdecl⟩ + · rintro ⟨checked, hchecked, hwf⟩ + exact checked.to_declWF hchecked hwf + +/- Keep the first exported descriptor invariants on the same accepted Theory +axiom baseline as the transaction API. -/ +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.names_nodup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.type_closed [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.ctor_closed [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.analysis_accepted [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.type_levelWF [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.ctor_levelWF [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.direct_anatomy [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.wf_of_decl [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.to_declWF [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.wf_iff_exists_checked [propext, Quot.sound] + +/-- Unpack `stage3` for a declaration already known (from `addInduct` +success) to have a singleton type list. -/ +theorem singletonStage3_anatomy {U np ty} + (h : singletonStage3 ⟨U, np, [ty]⟩ = true) : + ty.uvars = U ∧ (VExpr.telN np ty.type).length = np ∧ + (∃ l, VExpr.resultOf (VExpr.dropN np ty.type) = .sort l ∧ l.WF U) ∧ + (∀ I ∈ ctorFields (VExpr.dropN np ty.type), I.hasConst ty.name = false) ∧ + ∀ c ∈ ty.ctors, c.uvars = U ∧ + VExpr.telN np c.type = VExpr.telN np ty.type ∧ + stage3Ctor U ty.name np (ctorFields (VExpr.dropN np ty.type)).length 0 + (VExpr.dropN np c.type) = true := by + obtain ⟨checked, -⟩ := exists_checked_of_singletonStage3 h + have hcore := checked.accepted + simp only [stage3Core, Bool.and_eq_true] at hcore + have hdirect := hcore.1 + simp only [stage3DirectCore, Bool.and_eq_true, beq_iff_eq, + List.all_eq_true] at hdirect + obtain ⟨⟨⟨⟨h1, h2⟩, h3⟩, h4⟩, h6⟩ := hdirect + simp only [typeFormerOK, Bool.and_eq_true, List.all_eq_true] at h4 + refine ⟨h1, h2, ?_, fun I hI => by simpa [Bool.not_eq_true'] using h4.2 I hI, + fun c hc => by simpa [and_assoc] using h6 c hc⟩ + split at h3 + · next l heq => exact ⟨l, heq, by simpa using h3⟩ + · exact Bool.noConfusion h3 + +end VInductDecl + +/-! ## Context and spine lemmas -/ + +theorem Lookup.append {A : VExpr} : ∀ (Δ : List VExpr) {Γ}, + Lookup (Δ ++ A :: Γ) Δ.length (A.liftN (Δ.length + 1)) + | [], _ => .zero + | B :: Δ, Γ => by + simpa [← VExpr.liftN_succ] using (Lookup.append (A := A) Δ (Γ := Γ)).succ (A := B) + +theorem Lookup.append_closed {A : VExpr} (hA : A.ClosedN 0) (Δ : List VExpr) {Γ} : + Lookup (Δ ++ A :: Γ) Δ.length A := by + simpa [hA.liftN_eq (Nat.zero_le _)] using Lookup.append (A := A) Δ (Γ := Γ) + +theorem Lookup.of_getElem? : ∀ {Γ : List VExpr} {i : Nat} {A : VExpr}, + Γ[i]? = some A → Lookup Γ i (A.liftN (i+1)) + | B :: _, 0, A, h => by + obtain rfl : B = A := by simpa using h + exact .zero + | B :: Γ, i+1, A, h => by + have := Lookup.of_getElem? (Γ := Γ) (i := i) (A := A) (by simpa using h) + simpa [← VExpr.liftN_succ] using this.succ (A := B) + +theorem Lookup.of_getElem?_closed {Γ : List VExpr} {i : Nat} {A : VExpr} + (h : Γ[i]? = some A) (hA : A.ClosedN 0) : Lookup Γ i A := by + simpa [hA.liftN_eq (Nat.zero_le _)] using Lookup.of_getElem? h + +/-- Right-associated: the element right past a two-part prefix. -/ +theorem getElem?_rstack3 {α} (Δ mid : List α) (a : α) (Γ : List α) {i : Nat} + (h : i = Δ.length + mid.length) : (Δ ++ (mid ++ a :: Γ))[i]? = some a := by + rw [List.getElem?_append_right (by omega), List.getElem?_append_right (by omega), + show i - Δ.length - mid.length = 0 from by omega] + rfl + +/-- Right-associated: an element inside the middle block. -/ +theorem getElem?_rstack_mid {α} (Δ mid Γ : List α) {i : Nat} + (h1 : Δ.length ≤ i) (h2 : i - Δ.length < mid.length) : + (Δ ++ (mid ++ Γ))[i]? = mid[i - Δ.length]? := by + rw [List.getElem?_append_right h1, List.getElem?_append_left h2] + +/-- The element right past a two-part prefix. -/ +theorem getElem?_stack3 {α} (Δ mid Γ : List α) (a : α) {i : Nat} + (h : i = Δ.length + mid.length) : (Δ ++ mid ++ a :: Γ)[i]? = some a := by + rw [List.append_assoc, List.getElem?_append_right (by omega), + show i - Δ.length = mid.length from by omega, + List.getElem?_append_right (Nat.le_refl _), Nat.sub_self] + rfl + +/-- An element inside the middle block of a three-part context. -/ +theorem getElem?_stack_mid {α} (Δ mid Γ : List α) {i : Nat} + (h1 : Δ.length ≤ i) (h2 : i - Δ.length < mid.length) : + (Δ ++ mid ++ Γ)[i]? = mid[i - Δ.length]? := by + rw [List.append_assoc, List.getElem?_append_right h1, + List.getElem?_append_left h2] + +namespace VEnv + +/-- A typed Theory expression cannot mention a constant absent from its +environment. -/ +theorem HasType.hasConst_false_of_absent + {env : VEnv} {U : Nat} {Γ : List VExpr} + {name : Name} {e A : VExpr} + (henv : env.Ordered) (hΓ : OnCtx Γ (env.IsType U)) + (absent : env.constants name = none) + (typed : env.HasType U Γ e A) : + e.hasConst name = false := by + induction e generalizing Γ A with + | bvar | sort => rfl + | const constant levels => + by_cases equality : constant = name + · subst constant + obtain ⟨ci, present, levelWF, arity⟩ := + typed.const_inv henv hΓ + rw [absent] at present + contradiction + · simp [VExpr.hasConst, equality] + | app function argument functionIH argumentIH => + obtain ⟨domain, body, functionType, argumentType⟩ := + typed.app_inv henv hΓ + simp only [VExpr.hasConst, functionIH hΓ functionType, + argumentIH hΓ argumentType, Bool.false_or] + | lam domain body domainIH bodyIH => + obtain ⟨domainType, bodyWF⟩ := typed.lam_inv henv hΓ + obtain ⟨domainLevel, domainHasType⟩ := domainType + obtain ⟨bodyType, bodyHasType⟩ := bodyWF + have nextContextWF : OnCtx (domain :: Γ) (env.IsType U) := by + change OnCtx Γ (env.IsType U) ∧ env.IsType U Γ domain + exact ⟨hΓ, ⟨domainLevel, domainHasType⟩⟩ + simp only [VExpr.hasConst, domainIH hΓ domainHasType, + bodyIH nextContextWF bodyHasType, Bool.false_or] + | forallE domain body domainIH bodyIH => + obtain ⟨domainType, bodyType⟩ := typed.forallE_inv henv + obtain ⟨domainLevel, domainHasType⟩ := domainType + obtain ⟨bodyLevel, bodyHasType⟩ := bodyType + have nextContextWF : OnCtx (domain :: Γ) (env.IsType U) := by + change OnCtx Γ (env.IsType U) ∧ env.IsType U Γ domain + exact ⟨hΓ, ⟨domainLevel, domainHasType⟩⟩ + simp only [VExpr.hasConst, domainIH hΓ domainHasType, + bodyIH nextContextWF bodyHasType, Bool.false_or] + +/-- The spine `bvarRevRange Δ.length As.length` selects exactly the binders +`As` (reversed into the context past `Δ`), when all of `As` are closed. -/ +theorem hasType_bvarRevRange {env : VEnv} {U : Nat} : + ∀ {As : List VExpr}, (∀ A ∈ As, A.ClosedN 0) → ∀ {Δ Γ₀ : List VExpr}, + List.Forall₂ (env.HasType U (Δ ++ As.reverse ++ Γ₀)) + (VExpr.bvarRevRange Δ.length As.length) As + | [], _, _, _ => .nil + | A :: As, h, Δ, Γ₀ => by + refine .cons (.bvar ?_) ?_ + · have := Lookup.append_closed (h _ (.head _)) (Δ ++ As.reverse) (Γ := Γ₀) + simpa [List.append_assoc] using this + · have := hasType_bvarRevRange (env := env) (U := U) (As := As) + (fun A h' => h _ (.tail _ h')) (Δ := Δ) (Γ₀ := A :: Γ₀) + simpa [List.append_assoc] using this + +theorem ClosedN.forallN_of_all {As : List VExpr} (hAs : ∀ A ∈ As, A.ClosedN 0) + {B : VExpr} (hB : B.ClosedN 0) {k : Nat} : (VExpr.forallN As B).ClosedN k := by + induction As generalizing k with + | nil => exact hB.mono (Nat.zero_le _) + | cons A As ih => + exact ⟨(hAs _ (.head _)).mono (Nat.zero_le _), ih fun A h => hAs _ (.tail _ h)⟩ + +/-- Substituting a variable for the innermost binder of a lifted term is a +smaller lift: the telescope-self-application identity. Unconditional. -/ +theorem _root_.Ix.Theory.Named.VExpr.liftN_succ_inst_bvar (e : VExpr) : + ∀ (s k : Nat), (e.liftN (s+1) (k+1)).inst (.bvar s) k = e.liftN s k := by + induction e with intro s k + | bvar j => + show VExpr.instVar (liftVar (s+1) j (k+1)) (.bvar s) k = .bvar (liftVar s j k) + unfold liftVar + rcases Nat.lt_trichotomy j k with h | rfl | h + · rw [if_pos (Nat.lt_succ_of_lt h), if_pos h] + simp [VExpr.instVar, h] + · rw [if_pos (Nat.lt_succ_self _), if_neg (Nat.lt_irrefl _)] + show VExpr.instVar j (.bvar s) j = _ + rw [show VExpr.instVar j (.bvar s) j = (VExpr.bvar s).liftN j from by + unfold VExpr.instVar; rw [if_neg (Nat.lt_irrefl _), if_pos rfl]] + show VExpr.bvar (liftVar j s) = _ + rw [liftVar_base, Nat.add_comm] + · rw [if_neg (by omega), if_neg (by omega)] + simp only [VExpr.instVar] + rw [if_neg (by omega), if_neg (by omega)] + congr 1; omega + | sort | const => intros; rfl + | app f a ihf iha => simp [VExpr.liftN, VExpr.inst, ihf, iha] + | lam A b ihA ihb | forallE A b ihA ihb => + simp [VExpr.liftN, VExpr.inst, ihA s k, ihb s (k+1)] + +/-- Applying `f : (∀ As, B).liftN Δ.length` to the spine of variables +referring to its own binders, sitting in the context right below `Δ`. +The lift on the type in the hypothesis is what makes the invariant close +over the recursion; no closedness is needed. -/ +theorem HasType.appN_selfSpine {env : VEnv} {U : Nat} : + ∀ {As : List VExpr} {B : VExpr} {Δ Γ : List VExpr} {f}, + env.HasType U (Δ ++ As.reverse ++ Γ) f + ((VExpr.forallN As B).liftN (Δ.length + As.length)) → + env.HasType U (Δ ++ As.reverse ++ Γ) + (f.appN (VExpr.bvarRevRange Δ.length As.length)) (B.liftN Δ.length) + | [], B, Δ, Γ, f, hf => by simpa using hf + | A :: As, B, Δ, Γ, f, hf => by + have harg : env.HasType U (Δ ++ (A :: As).reverse ++ Γ) + (.bvar (Δ.length + As.length)) (A.liftN (Δ.length + As.length + 1)) := by + have := Lookup.append (A := A) (Δ ++ As.reverse) (Γ := Γ) + simp only [List.length_append, List.length_reverse] at this + exact .bvar (by simpa [List.append_assoc, Nat.add_assoc] using this) + have happ := HasType.app hf harg + simp only [List.length_cons, Nat.add_succ] at happ + rw [VExpr.liftN_succ_inst_bvar] at happ + have := HasType.appN_selfSpine (As := As) (B := B) (Δ := Δ) (Γ := A :: Γ) + (f := f.app (.bvar (Δ.length + As.length))) (by simpa [List.append_assoc] using happ) + simpa [List.append_assoc, VExpr.bvarRevRange] using this + +/-- The closed-telescope entry point for `appN_selfSpine`. -/ +theorem HasType.appN_selfSpine' {env : VEnv} {U : Nat} + {As : List VExpr} {B : VExpr} {Δ Γ : List VExpr} {f} + (hcl : (VExpr.forallN As B).ClosedN 0) + (hf : env.HasType U (Δ ++ As.reverse ++ Γ) f (VExpr.forallN As B)) : + env.HasType U (Δ ++ As.reverse ++ Γ) + (f.appN (VExpr.bvarRevRange Δ.length As.length)) (B.liftN Δ.length) := + HasType.appN_selfSpine (by rwa [hcl.liftN_eq (Nat.zero_le _)]) + +/-- Application of a closed non-dependent telescope. -/ +theorem HasType.appN_closed {env : VEnv} {U : Nat} {Γ : List VExpr} : + ∀ {As : List VExpr}, (∀ A ∈ As, A.ClosedN 0) → ∀ {B : VExpr}, B.ClosedN 0 → + ∀ {f args}, env.HasType U Γ f (VExpr.forallN As B) → + List.Forall₂ (env.HasType U Γ) args As → + env.HasType U Γ (f.appN args) B + | [], _, _, _, _, _, hf, .nil => hf + | A :: As, hAs, B, hB, f, a :: as, hf, .cons ha hargs => by + have h2 : env.HasType U Γ (f.app a) ((VExpr.forallN As B).inst a) := .app hf ha + rw [(ClosedN.forallN_of_all (fun A h => hAs _ (.tail _ h)) hB).instN_eq + (Nat.zero_le _)] at h2 + exact appN_closed (fun A h => hAs _ (.tail _ h)) hB (f := f.app a) h2 hargs + +theorem isType_forallN_free {env : VEnv} {U : Nat} {As : List VExpr} + (hAs : ∀ A ∈ As, ∀ Γ, env.IsType U Γ A) + {B : VExpr} (hB : ∀ Γ, env.IsType U Γ B) : ∀ Γ, env.IsType U Γ (VExpr.forallN As B) := by + induction As with + | nil => exact hB + | cons A As ih => + exact fun Γ => (hAs _ (.head _) Γ).forallE + (ih (fun A h => hAs _ (.tail _ h)) (A :: Γ)) + +theorem HasType.lamN {env : VEnv} {U : Nat} : ∀ {As Γ body B}, + OnTel env U Γ As → env.HasType U (As.reverse ++ Γ) body B → + env.HasType U Γ (VExpr.lamN As body) (VExpr.forallN As B) + | [], _, _, _, _, hb => hb + | A :: As, Γ, body, B, ⟨⟨_, hA⟩, hT⟩, hb => + HasType.lam hA (HasType.lamN hT (by simpa [List.append_assoc] using hb)) + +theorem IsType.forallN {env : VEnv} {U : Nat} : ∀ {As Γ B}, + OnTel env U Γ As → env.IsType U (As.reverse ++ Γ) B → + env.IsType U Γ (VExpr.forallN As B) + | [], _, _, _, hB => hB + | A :: As, Γ, B, ⟨hA, hT⟩, hB => + IsType.forallE hA (IsType.forallN hT (by simpa [List.append_assoc] using hB)) + +theorem onTel_of_free {env : VEnv} {U : Nat} : ∀ {As Γ}, + (∀ A ∈ As, ∀ Γ', env.IsType U Γ' A) → OnTel env U Γ As + | [], _, _ => trivial + | _ :: _, _, h => + ⟨h _ (.head _) _, onTel_of_free fun _ h' Γ' => h _ (.tail _ h') Γ'⟩ + +theorem OnTel.append {env : VEnv} {U : Nat} : ∀ {As Bs Γ}, + OnTel env U Γ As → OnTel env U (As.reverse ++ Γ) Bs → OnTel env U Γ (As ++ Bs) + | [], _, _, _, h2 => h2 + | _ :: As, Bs, Γ, ⟨hA, h1⟩, h2 => + ⟨hA, OnTel.append h1 (by simpa [List.append_assoc] using h2)⟩ + +theorem OnTel.of_append {env : VEnv} {U : Nat} : ∀ {As Bs Γ}, + OnTel env U Γ (As ++ Bs) → OnTel env U Γ As ∧ OnTel env U (As.reverse ++ Γ) Bs + | [], _, _, h => ⟨trivial, h⟩ + | A :: As, Bs, Γ, ⟨hA, hT⟩ => by + obtain ⟨h1, h2⟩ := OnTel.of_append (As := As) hT + exact ⟨⟨hA, h1⟩, by simpa [List.append_assoc] using h2⟩ + +/-- Push a context lift under a reversed telescope: inserting binders below +shifts each telescope entry at its own depth. -/ +theorem _root_.Ix.Theory.Named.Ctx.LiftN.consTel {n : Nat} : ∀ (As : List VExpr) {k : Nat} + {Γ Γ' : List VExpr}, Ctx.LiftN n k Γ Γ' → + Ctx.LiftN n (As.length + k) (As.reverse ++ Γ) + ((VExpr.liftTelN n As k).reverse ++ Γ') + | [], k, Γ, Γ', W => by simpa using W + | A :: As, k, Γ, Γ', W => by + have h := Ctx.LiftN.consTel As (Ctx.LiftN.succ (A := A) W) + rw [show As.length + (k+1) = (A :: As).length + k from by simp; omega] at h + simpa [VExpr.liftTelN, List.append_assoc] using h + +/-- Weakening a telescope: inserting binders at depth `k` of the context +shifts each entry at its own depth. -/ +theorem OnTel.weakN {env : VEnv} {U n : Nat} (henv : env.Ordered) : + ∀ {As Γ Γ' k}, Ctx.LiftN n k Γ Γ' → OnTel env U Γ As → + OnTel env U Γ' (VExpr.liftTelN n As k) + | [], _, _, _, _, _ => trivial + | _ :: _, _, _, _, W, ⟨hA, hT⟩ => + ⟨hA.weakN henv W, OnTel.weakN henv W.succ hT⟩ + +/-- Universe instantiation of a telescope. -/ +theorem OnTel.instL {env : VEnv} {U U' : Nat} {ls : List VLevel} + (hls : ∀ l ∈ ls, l.WF U') : + ∀ {As Γ}, OnTel env U Γ As → + OnTel env U' (Γ.map (VExpr.instL ls)) (As.map (VExpr.instL ls)) + | [], _, _ => trivial + | _ :: As, Γ, ⟨hA, hT⟩ => + ⟨hA.instL hls, by simpa using OnTel.instL hls (As := As) (Γ := _ :: Γ) hT⟩ + +/-! ### Spine typing -/ + +theorem SpineWF.hasType_appN {env : VEnv} {U : Nat} {Γ : List VExpr} : + ∀ {es : List VExpr} {A B f : VExpr}, env.SpineWF U Γ A es B → + env.HasType U Γ f A → env.HasType U Γ (f.appN es) B := by + intro es + induction es with intro A B f h hf + | nil => cases h; exact hf + | cons e es ih => + cases h with + | cons he hrest => + exact ih hrest (hf.app he) + +/-- Concatenate two adjacent, well-typed application spines. -/ +theorem SpineWF.append {env : VEnv} {U : Nat} {Γ : List VExpr} : + ∀ {es : List VExpr} {A B : VExpr}, env.SpineWF U Γ A es B → + ∀ {es' : List VExpr} {C : VExpr}, env.SpineWF U Γ B es' C → + env.SpineWF U Γ A (es ++ es') C + | [], _, _, .nil, _, _, h' => h' + | _ :: _, _, _, .cons he hrest, _, _, h' => + .cons he (SpineWF.append hrest h') + +/-- Split a well-typed application spine at an explicit list prefix. -/ +theorem SpineWF.split {env : VEnv} {U : Nat} {Γ : List VExpr} : + ∀ {front suffix : List VExpr} {A B : VExpr}, + env.SpineWF U Γ A (front ++ suffix) B → + ∃ cursor, env.SpineWF U Γ A front cursor ∧ + env.SpineWF U Γ cursor suffix B + | [], suffix, A, B, h => ⟨A, .nil, by simpa using h⟩ + | _ :: front, suffix, _, _, .cons he hrest => by + obtain ⟨cursor, hfront, hsuffix⟩ := SpineWF.split hrest + exact ⟨cursor, .cons he hfront, hsuffix⟩ + +/-- Extend a well-typed application spine by one final argument. -/ +theorem SpineWF.snoc {env : VEnv} {U : Nat} {Γ : List VExpr} {e D C : VExpr} : + ∀ {es : List VExpr} {A : VExpr}, env.SpineWF U Γ A es (.forallE D C) → + env.HasType U Γ e D → env.SpineWF U Γ A (es ++ [e]) (C.inst e) + | [], _, .nil, he => .cons he .nil + | _ :: _, _, .cons ha hrest, he => + .cons ha (SpineWF.snoc hrest he) + +/-- Retarget a spine judgment along a pi with the same domains: the +result is the iterated instantiation of the new codomain. -/ +theorem SpineWF.retarget {env : VEnv} {U : Nat} {Γ : List VExpr} {es : List VExpr} : + ∀ {Δ : List VExpr} {C B : VExpr}, env.SpineWF U Γ (VExpr.forallN Δ C) es B → + es.length = Δ.length → ∀ (C' : VExpr), + env.SpineWF U Γ (VExpr.forallN Δ C') es (VExpr.instRev C' es) := by + induction es with intro Δ C B h hlen C' + | nil => + obtain rfl : Δ = [] := by + cases Δ with + | nil => rfl + | cons _ _ => simp at hlen + cases h + exact .nil + | cons e es ih => + cases Δ with + | nil => simp at hlen + | cons A Δ => + cases h with + | cons he hrest => + have hlen' : es.length = Δ.length := by simpa using hlen + refine .cons he ?_ + rw [VExpr.instN_forallN] at hrest + have := ih hrest (by simp [VExpr.instTelN_length, hlen']) (C'.inst e Δ.length) + show env.SpineWF U Γ ((VExpr.forallN Δ C').inst e) es + (VExpr.instRev (C'.inst e es.length) es) + rw [VExpr.instN_forallN, Nat.zero_add, hlen'] + exact this + +/-- A spine consuming a full telescope and ending in the same sort has +exactly one argument per telescope binder. -/ +theorem SpineWF.forallN_sort_length + {env : VEnv} {U : Nat} {Γ : List VExpr} {l : VLevel} : + ∀ {As es}, env.SpineWF U Γ (VExpr.forallN As (.sort l)) es (.sort l) → + es.length = As.length + | [], [], _ => rfl + | [], _ :: _, h => by cases h + | _ :: _, [], h => by cases h + | A :: As, e :: es, h => by + cases h with + | cons he hrest => + rw [VExpr.instN_forallN] at hrest + have hlen := SpineWF.forallN_sort_length hrest + simpa [VExpr.instTelN_length] using congrArg Nat.succ hlen + +end VEnv + +/-! ## The induction-hypothesis telescope under lifting -/ + +namespace VInductDecl + +/-- `ihsFrom` after the motive-directed lift into the rule context. -/ +def ihsR (m k : Nat) : List (Nat × List VExpr) → Nat → List VExpr + | [], _ => [] + | (j, idxs) :: rs, p => + VExpr.appN (.bvar (k + (m + p))) + ((idxs.map fun e => ((e.liftN 1 j).liftN (m-j+p)).liftN k (m+p)) ++ + [.bvar (m-1-j+p)]) :: + ihsR m k rs (p+1) + +/-- Recursive-field positions are bounded by the field count. -/ +theorem recPairs_lt {U : Nat} {T : Name} {np ni : Nat} : ∀ {Bs : List VExpr} {j₀ : Nat}, + ∀ q ∈ recPairs U T np ni Bs j₀, q.1 < j₀ + Bs.length + | B :: Bs, j₀, q, h => by + unfold recPairs at h + split at h + · rcases List.mem_cons.1 h with rfl | h + · simp + · have := recPairs_lt _ h + simp only [List.length_cons]; omega + · have := recPairs_lt _ h + simp only [List.length_cons]; omega + +theorem recPairs_ge {U : Nat} {T : Name} {np ni : Nat} : ∀ {Bs : List VExpr} {j₀ : Nat}, + ∀ q ∈ recPairs U T np ni Bs j₀, j₀ ≤ q.1 + | _ :: Bs, j₀, q, h => by + unfold recPairs at h + split at h + · rcases List.mem_cons.1 h with rfl | h + · exact Nat.le_refl _ + · exact Nat.le_of_succ_le (recPairs_ge _ h) + · exact Nat.le_of_succ_le (recPairs_ge _ h) + +/-- Recursive positions really hold a recursive field, and the recorded +index arguments are its index arguments. -/ +theorem recPairs_getElem {U : Nat} {T : Name} {np ni : Nat} : ∀ {Bs : List VExpr} {j₀ : Nat}, + ∀ q ∈ recPairs U T np ni Bs j₀, ∃ B, Bs[q.1 - j₀]? = some B ∧ + isRecField U T np ni q.1 B = true ∧ q.2 = recFieldIdxs np B + | B :: Bs, j₀, q, h => by + unfold recPairs at h + split at h + · next heq => + rcases List.mem_cons.1 h with rfl | h + · exact ⟨B, by simp, heq, rfl⟩ + · have h1 := recPairs_ge _ h + obtain ⟨B', hB', hrec, hidx⟩ := recPairs_getElem _ h + refine ⟨B', ?_, hrec, hidx⟩ + rw [show q.1 - j₀ = (q.1 - (j₀+1)) + 1 from by omega] + simpa using hB' + · have h1 := recPairs_ge _ h + obtain ⟨B', hB', hrec, hidx⟩ := recPairs_getElem _ h + refine ⟨B', ?_, hrec, hidx⟩ + rw [show q.1 - j₀ = (q.1 - (j₀+1)) + 1 from by omega] + simpa using hB' + +/-- Every analyzed recursive argument names a field within the source +telescope. -/ +theorem recArgs_lt {U : Nat} {T : Name} {np ni : Nat} : ∀ {Bs : List VExpr} {j₀ : Nat}, + ∀ r ∈ recArgs U T np ni Bs j₀, r.fieldIndex < j₀ + Bs.length + | B :: Bs, j₀, r, h => by + unfold recArgs at h + split at h + · next r₀ hr₀ => + rcases List.mem_cons.1 h with rfl | h + · have hj := (recArg?_eq hr₀).1 + simp only [List.length_cons] + omega + · have := recArgs_lt _ h + simp only [List.length_cons]; omega + · have := recArgs_lt _ h + simp only [List.length_cons]; omega + +/-- Recursive-argument field positions never precede the starting depth. -/ +theorem recArgs_ge {U : Nat} {T : Name} {np ni : Nat} : ∀ {Bs : List VExpr} {j₀ : Nat}, + ∀ r ∈ recArgs U T np ni Bs j₀, j₀ ≤ r.fieldIndex + | _ :: Bs, j₀, r, h => by + unfold recArgs at h + split at h + · next r₀ hr₀ => + rcases List.mem_cons.1 h with rfl | h + · simp [(recArg?_eq hr₀).1] + · exact Nat.le_of_succ_le (recArgs_ge _ h) + · exact Nat.le_of_succ_le (recArgs_ge _ h) + +/-- An analyzed recursive argument is backed by the field at its recorded +position, and re-analysis returns the same normalized descriptor. -/ +theorem recArgs_getElem {U : Nat} {T : Name} {np ni : Nat} : + ∀ {Bs : List VExpr} {j₀ : Nat}, ∀ r ∈ recArgs U T np ni Bs j₀, + ∃ B, Bs[r.fieldIndex - j₀]? = some B ∧ + recArg? U T np ni r.fieldIndex B = some r + | B :: Bs, j₀, r, h => by + unfold recArgs at h + split at h + · next r₀ hr₀ => + rcases List.mem_cons.1 h with rfl | h + · have hj := (recArg?_eq hr₀).1 + subst hj + exact ⟨B, by simp, hr₀⟩ + · have hge := recArgs_ge _ h + obtain ⟨B', hB', hr⟩ := recArgs_getElem _ h + refine ⟨B', ?_, hr⟩ + rw [show r.fieldIndex - j₀ = (r.fieldIndex - (j₀+1)) + 1 from by omega] + simpa using hB' + · have hge := recArgs_ge _ h + obtain ⟨B', hB', hr⟩ := recArgs_getElem _ h + refine ⟨B', ?_, hr⟩ + rw [show r.fieldIndex - j₀ = (r.fieldIndex - (j₀+1)) + 1 from by omega] + simpa using hB' + +theorem ihsFrom_liftN (m k : Nat) : ∀ (rs : List (Nat × List VExpr)), + (∀ q ∈ rs, q.1 < m) → ∀ (p : Nat) (X : VExpr), + (VExpr.forallN (ihsFrom m rs p) X).liftN k (m + p) = + VExpr.forallN (ihsR m k rs p) (X.liftN k (m + p + rs.length)) + | [], _, _, _ => rfl + | (j, idxs) :: rs, hm, p, X => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN_appN, List.map_append, List.map_map, + show ((VExpr.bvar (m+p)).liftN k (m+p)) = .bvar (k+(m+p)) from by + show VExpr.bvar (liftVar k (m+p) (m+p)) = _ + rw [liftVar_le (Nat.le_refl _)], + show ([VExpr.bvar (m-1-j+p)]).map (VExpr.liftN k · (m+p)) = + [VExpr.bvar (m-1-j+p)] from by + show [VExpr.bvar (liftVar k (m-1-j+p) (m+p))] = _ + rw [liftVar_lt (show m-1-j+p < m+p from by + have := hm _ (List.Mem.head _); simp at this; omega)]] + rfl + · rw [show m + p + 1 = m + (p+1) from rfl, + ihsFrom_liftN m k rs (fun q h => hm q (.tail _ h)) (p+1) X, + show m + (p+1) + rs.length = m + p + (rs.length+1) from by omega] + rfl + +/-- `ihsFrom_liftN` with the cutoff generalized, for syntactic rewriting. -/ +theorem ihsFrom_liftN' (m k : Nat) (rs : List (Nat × List VExpr)) + (hm : ∀ q ∈ rs, q.1 < m) (p : Nat) (X : VExpr) {cut : Nat} (hcut : cut = m + p) : + (VExpr.forallN (ihsFrom m rs p) X).liftN k cut = + VExpr.forallN (ihsR m k rs p) (X.liftN k (m + p + rs.length)) := by + rw [hcut]; exact ihsFrom_liftN m k rs hm p X + +theorem ihsR_liftN1 (m k : Nat) : ∀ (rs : List (Nat × List VExpr)) (p c : Nat), c ≤ p → + (∀ q ∈ rs, q.1 < m) → ∀ (X : VExpr), + VExpr.forallN (ihsR m k rs (p+1)) (X.liftN 1 (c + rs.length)) = + (VExpr.forallN (ihsR m k rs p) X).liftN 1 c + | [], p, c, _, _, X => by simp [ihsR, VExpr.forallN] + | (j, idxs) :: rs, p, c, hc, hm, X => by + have hjm : j < m := by have := hm _ (List.Mem.head _); simpa using this + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN_appN, List.map_append, List.map_map, + show ((VExpr.bvar (k+(m+p))).liftN 1 c) = .bvar (k+(m+(p+1))) from by + show VExpr.bvar (liftVar 1 (k+(m+p)) c) = _ + rw [liftVar_le (by omega)] + congr 1; omega, + show ([VExpr.bvar (m-1-j+p)]).map (VExpr.liftN 1 · c) = + [VExpr.bvar (m-1-j+(p+1))] from by + show [VExpr.bvar (liftVar 1 (m-1-j+p) c)] = _ + rw [liftVar_le (by omega)] + congr 2; omega] + refine congrArg (VExpr.appN _) (congrArg (· ++ [VExpr.bvar (m-1-j+(p+1))]) ?_) + refine List.map_congr_left fun e _ => .symm ?_ + show (((e.liftN 1 j).liftN (m-j+p)).liftN k (m+p)).liftN 1 c = _ + rw [VExpr.liftN_liftN_comm _ 1 k c (m+p) (by omega), + show ((e.liftN 1 j).liftN (m-j+p)).liftN 1 c = + (e.liftN 1 j).liftN (m-j+(p+1)) from by + rw [VExpr.liftN'_liftN' (Nat.zero_le _) (by omega)] + rfl] + rfl + · rw [show c + ((j, idxs) :: rs).length = (c+1) + rs.length from by simp; omega] + exact ihsR_liftN1 m k rs (p+1) (c+1) (by omega) (fun q h => hm q (.tail _ h)) X + +theorem ihsFrom_length (m : Nat) : ∀ (rs : List (Nat × List VExpr)) (p : Nat), + (ihsFrom m rs p).length = rs.length + | [], _ => rfl + | (_, _) :: rs, p => by simp [ihsFrom, ihsFrom_length m rs (p+1)] + +theorem ihsFromRecArgs_length (m : Nat) : ∀ (rs : List RecArg) (p : Nat), + (ihsFromRecArgs m rs p).length = rs.length + | [], _ => rfl + | _ :: rs, p => by simp [ihsFromRecArgs, ihsFromRecArgs_length m rs (p+1)] + +theorem minorTypes_length (U : Nat) (T : Name) (np : Nat) (ty : VInductiveType) : + ∀ (cs : List VConstVal) (i : Nat), (minorTypes U T np ty cs i).length = cs.length + | [], _ => rfl + | _ :: cs, i => by simp [minorTypes, minorTypes_length U T np ty cs (i+1)] + +theorem minorTypesRec_length (U : Nat) (T : Name) (np : Nat) (ty : VInductiveType) : + ∀ (cs : List VConstVal) (i : Nat), (minorTypesRec U T np ty cs i).length = cs.length + | [], _ => rfl + | _ :: cs, i => by + simp [minorTypesRec, minorTypesRec_length U T np ty cs (i+1)] + +theorem bvarRevRange_liftN_ge : ∀ (m off n k : Nat), k ≤ off → + (VExpr.bvarRevRange off m).map (VExpr.liftN n · k) = VExpr.bvarRevRange (n + off) m + | 0, _, _, _, _ => rfl + | m+1, off, n, k, h => by + show VExpr.bvar _ :: _ = VExpr.bvar _ :: _ + rw [bvarRevRange_liftN_ge m off n k h] + congr 2 + show liftVar n (off + m) k = n + off + m + rw [liftVar_le (by omega)]; omega + +theorem bvarRevRange_instL : ∀ (m off : Nat) (ls : List VLevel), + (VExpr.bvarRevRange off m).map (VExpr.instL ls) = VExpr.bvarRevRange off m + | 0, _, _ => rfl + | m+1, off, ls => by + show _ :: _ = _ :: _ + rw [bvarRevRange_instL m off ls] + rfl + +/-- The transported type of an analyzed recursive field is exactly its +generated functional-IH domain telescope followed by the transported family +target. -/ +theorem recArg_minor_fieldType {U : Nat} {T : Name} {np ni : Nat} + {B : VExpr} {r₀ : RecArg} + (hr : recArg? U T np ni r₀.fieldIndex B = some r₀) + (m p : Nat) (hj : r₀.fieldIndex < m) + (mode : ElimMode := .large) : + let ls := mode.sourceLevels U + let r := r₀.instL ls + ((B.instL ls).liftN 1 r.fieldIndex).liftN + (m-r.fieldIndex+p) = + VExpr.forallN (r.minorBinders m p) + (VExpr.appN (.const T ls) + (VExpr.bvarRevRange (m+p+r.binders.length+1) np ++ + r.indices.map fun e => + (e.liftN 1 (r.fieldIndex+r.binders.length)).liftN + (m-r.fieldIndex+p) r.binders.length)) := by + dsimp only + obtain ⟨-, -, hB, -, -, -⟩ := recArg?_eq hr + conv => lhs; rw [hB] + simp only [RecArg.instL, VExpr.instL_forallN, VExpr.instL_appN, + List.map_append, bvarRevRange_instL, + show (VExpr.const T (VLevel.params U)).instL (mode.sourceLevels U) = + .const T (mode.sourceLevels U) from by + simp [VExpr.instL, ElimMode.sourceLevels, + VLevel.params_map_inst_params'], + VExpr.liftN_forallN, VExpr.liftN_appN] + simp only [List.length_map, VExpr.liftTelN_length, Nat.zero_add] + rw [bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + bvarRevRange_liftN_ge _ _ _ _ (by omega), + show + m - r₀.fieldIndex + p + (1 + (r₀.fieldIndex + r₀.binders.length)) = + m + p + r₀.binders.length + 1 from by omega] + simp only [List.map_map, RecArg.minorBinders] + apply congrArg (VExpr.forallN _) + apply congrArg (VExpr.appN (.const T (mode.sourceLevels U))) + apply congrArg (VExpr.bvarRevRange (m + p + r₀.binders.length + 1) np ++ ·) + apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + +/-- Rule-context analogue of `recArg_minor_fieldType`: transport a recursive +field beneath the motive and all constructor minors, then beneath the later +constructor fields. -/ +theorem recArg_rule_fieldType {U : Nat} {T : Name} {np ni : Nat} + {B : VExpr} {r₀ : RecArg} + (hr : recArg? U T np ni r₀.fieldIndex B = some r₀) + (m k : Nat) (hj : r₀.fieldIndex < m) + (mode : ElimMode := .large) : + let ls := mode.sourceLevels U + let r := r₀.instL ls + ((B.instL ls).liftN (k+1) r.fieldIndex).liftN + (m-r.fieldIndex) = + VExpr.forallN (r.ruleBinders m k) + (VExpr.appN (.const T ls) + (VExpr.bvarRevRange (m+k+r.binders.length+1) np ++ + r.indices.map fun e => + (e.liftN (k+1) (r.fieldIndex+r.binders.length)).liftN + (m-r.fieldIndex) r.binders.length)) := by + dsimp only + obtain ⟨-, -, hB, -, -, -⟩ := recArg?_eq hr + conv => lhs; rw [hB] + simp only [RecArg.instL, VExpr.instL_forallN, VExpr.instL_appN, + List.map_append, bvarRevRange_instL, + show (VExpr.const T (VLevel.params U)).instL (mode.sourceLevels U) = + .const T (mode.sourceLevels U) from by + simp [VExpr.instL, ElimMode.sourceLevels, + VLevel.params_map_inst_params'], + VExpr.liftN_forallN, VExpr.liftN_appN] + simp only [List.length_map, VExpr.liftTelN_length, Nat.zero_add] + rw [bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + bvarRevRange_liftN_ge _ _ _ _ (by omega), + show m - r₀.fieldIndex + (k + 1 + (r₀.fieldIndex + r₀.binders.length)) = + m + k + r₀.binders.length + 1 from by omega] + simp only [List.map_map, RecArg.ruleBinders] + apply congrArg (VExpr.forallN _) + apply congrArg (VExpr.appN (.const T (mode.sourceLevels U))) + apply congrArg (VExpr.bvarRevRange (m+k+r₀.binders.length+1) np ++ ·) + apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + +theorem RecArg.minorBinders_shift (r : RecArg) (m p : Nat) : + r.minorBinders m p = + VExpr.liftTelN p (r.minorBinders m 0) 0 := by + simp only [RecArg.minorBinders, Nat.add_zero] + rw [VExpr.liftTelN_liftTelN] + +/-- The `p` parameter of a minor IH is exactly weakening over the `p` +previous IH binders. -/ +theorem RecArg.minorIH_shift (r : RecArg) (m p : Nat) + (hj : r.fieldIndex < m) : + r.minorIH m p = (r.minorIH m 0).liftN p := by + simp only [RecArg.minorIH, VExpr.liftN_forallN] + rw [← r.minorBinders_shift m p] + rw [show (r.minorBinders m 0).length = r.binders.length by + simp [RecArg.minorBinders, VExpr.liftTelN_length], Nat.zero_add] + apply congrArg (VExpr.forallN _) + rw [VExpr.liftN_appN, List.map_append, List.map_map] + show VExpr.appN _ (_ ++ [_]) = VExpr.appN _ (_ ++ [_]) + congr 1 + · rw [show (VExpr.bvar (m + 0 + r.binders.length)).liftN + p r.binders.length = .bvar (m+p+r.binders.length) from by + simp only [VExpr.liftN] + rw [liftVar_le (by omega)] + congr 1 + omega] + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply, Nat.add_zero] + rw [VExpr.liftN'_liftN_hi] + · congr 1 + simp only [Nat.add_zero, VExpr.liftN_appN] + rw [show (VExpr.bvar (m - 1 - r.fieldIndex + r.binders.length)).liftN + p r.binders.length = + .bvar (m - 1 - r.fieldIndex + p + r.binders.length) from by + simp only [VExpr.liftN] + rw [liftVar_le (by omega)] + congr 1 + omega, + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + +/-- Lifting a base minor-IH through the constructor-minor stack produces the +normal form expected of the corresponding recursive call in an iota rule. -/ +theorem RecArg.minorIH_zero_lift_ruleIH (r : RecArg) (m k : Nat) + (hj : r.fieldIndex < m) : + (r.minorIH m 0).liftN k m = r.ruleIH m k := by + simp only [RecArg.minorIH, RecArg.ruleIH, VExpr.liftN_forallN, + VExpr.liftTelN_length, RecArg.minorBinders, RecArg.ruleBinders, Nat.add_zero] + congr 1 + · rw [show m = r.fieldIndex + (m-r.fieldIndex) from by omega] + rw [show r.fieldIndex + (m-r.fieldIndex) - r.fieldIndex = + m-r.fieldIndex from by omega] + rw [VExpr.liftTelN_liftN_mid r.binders k (m-r.fieldIndex) (Nat.zero_le _)] + · congr 1 + rw [VExpr.liftN_appN, List.map_append, List.map_map] + show VExpr.appN _ (_ ++ [_]) = VExpr.appN _ (_ ++ [_]) + congr 1 + · simp only [VExpr.liftN] + rw [liftVar_le (Nat.le_refl _)] + congr 1 + omega + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + rw [show m + r.binders.length = + (r.fieldIndex + r.binders.length) + (m-r.fieldIndex) from by omega, + VExpr.liftN_liftN_mid e k (m-r.fieldIndex) (by omega)] + · congr 1 + simp only [VExpr.liftN_appN] + rw [show (VExpr.bvar (m - 1 - r.fieldIndex + r.binders.length)).liftN + k (m + r.binders.length) = + .bvar (m - 1 - r.fieldIndex + r.binders.length) from by + simp only [VExpr.liftN] + rw [liftVar_lt (by omega)], + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + +/-- General normalization for a minor-IH already shifted past `p` earlier IH +binders. In rule context it is the base `ruleIH`, weakened by the same `p`. -/ +theorem RecArg.minorIH_lift_ruleIH (r : RecArg) (m k p : Nat) + (hj : r.fieldIndex < m) : + (r.minorIH m p).liftN k (m+p) = (r.ruleIH m k).liftN p := by + rw [r.minorIH_shift m p hj] + rw [← VExpr.liftN_liftN_comm (r.minorIH m 0) p k 0 m (Nat.zero_le _)] + rw [r.minorIH_zero_lift_ruleIH m k hj] + +theorem ruleIHs_length (m k : Nat) : ∀ (rs : List RecArg) (p : Nat), + (ruleIHs m k rs p).length = rs.length + | [], _ => rfl + | _ :: rs, p => by simp [ruleIHs, ruleIHs_length m k rs (p+1)] + +/-- Lifting the generalized minor-IH telescope into a rule context normalizes +each entry to `ruleIHs`; this is the list form of +`RecArg.minorIH_lift_ruleIH`. -/ +theorem ihsFromRecArgs_liftN (m k : Nat) : ∀ (rs : List RecArg), + (∀ r ∈ rs, r.fieldIndex < m) → ∀ (p : Nat) (X : VExpr), + (VExpr.forallN (ihsFromRecArgs m rs p) X).liftN k (m+p) = + VExpr.forallN (ruleIHs m k rs p) (X.liftN k (m+p+rs.length)) + | [], _, _, _ => rfl + | r :: rs, hm, p, X => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · exact r.minorIH_lift_ruleIH m k p (hm r (.head _)) + · rw [show m+p+1 = m+(p+1) from by omega, + ihsFromRecArgs_liftN m k rs (fun q hq => hm q (.tail _ hq)) (p+1) X, + show m+(p+1)+rs.length = m+p+((r :: rs).length) from by simp; omega] + +theorem ihsFromRecArgs_liftN' (m k : Nat) (rs : List RecArg) + (hm : ∀ r ∈ rs, r.fieldIndex < m) (p : Nat) (X : VExpr) + {cut : Nat} (hcut : cut = m+p) : + (VExpr.forallN (ihsFromRecArgs m rs p) X).liftN k cut = + VExpr.forallN (ruleIHs m k rs p) (X.liftN k (m+p+rs.length)) := by + rw [hcut] + exact ihsFromRecArgs_liftN m k rs hm p X + +/-- Weakening a normalized functional-IH telescope by one binder is the same +as incrementing its starting depth. -/ +theorem ruleIHs_liftN1 (m k : Nat) : ∀ (rs : List RecArg) (p c : Nat), c ≤ p → + ∀ (X : VExpr), + VExpr.forallN (ruleIHs m k rs (p+1)) (X.liftN 1 (c+rs.length)) = + (VExpr.forallN (ruleIHs m k rs p) X).liftN 1 c + | [], p, c, _, X => by simp [ruleIHs, VExpr.forallN] + | r :: rs, p, c, hc, X => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN'_liftN' (Nat.zero_le _) hc] + · rw [show c+(r :: rs).length = (c+1)+rs.length from by simp; omega] + exact ruleIHs_liftN1 m k rs (p+1) (c+1) (by omega) X + +/-- The key normalization: lifting a parameter spine past `off` binders. -/ +theorem recApp'_liftN {U : Nat} {T : Name} {np : Nat} {n k off : Nat} (h : k ≤ off) : + (recApp' U T np off).liftN n k = recApp' U T np (n + off) := by + simp only [recApp', VExpr.liftN_appN] + rw [bvarRevRange_liftN_ge _ _ _ _ h] + rfl + +theorem recApp_liftN {U : Nat} {T : Name} {np : Nat} {n k off : Nat} (h : k ≤ off) : + (recApp U T np off).liftN n k = recApp U T np (n + off) := by + simp only [recApp, VExpr.liftN_appN] + rw [bvarRevRange_liftN_ge _ _ _ _ h] + rfl + +theorem recApp_instL {U : Nat} {T : Name} {np off : Nat} : + (recApp U T np off).instL (VLevel.params' U 1) = recApp' U T np off := by + simp only [recApp, recApp', VExpr.instL_appN] + rw [bvarRevRange_instL] + simp [VExpr.instL, VLevel.params_map_inst_params', ElimMode.sourceLevels, + ElimMode.offset] + +theorem recApp'_congr {U : Nat} {T : Name} {np : Nat} {off off' : Nat} + (h : off = off') : recApp' U T np off = recApp' U T np off' := h ▸ rfl + +theorem _root_.Ix.Theory.Named.VExpr.bvarRevRange_congr {off off' : Nat} (m : Nat) + (h : off = off') : VExpr.bvarRevRange off m = VExpr.bvarRevRange off' m := h ▸ rfl + +theorem _root_.Ix.Theory.Named.VExpr.bvarRevRange_congr' {m m' : Nat} (off : Nat) + (h : m = m') : VExpr.bvarRevRange off m = VExpr.bvarRevRange off m' := h ▸ rfl + +theorem bvarRevRange_closedN : ∀ (m off k : Nat), off + m ≤ k → + ∀ e ∈ VExpr.bvarRevRange off m, e.ClosedN k + | 0, _, _, _, _, h => nomatch h + | m+1, off, k, hk, e, h => by + rcases List.mem_cons.1 h with rfl | h + · exact show off + m < k by omega + · exact bvarRevRange_closedN m off k (by omega) e h + +theorem bvarRevRange_levelWF {Uv : Nat} : ∀ (m off : Nat), + ∀ e ∈ VExpr.bvarRevRange off m, e.LevelWF Uv + | 0, _, _, h => nomatch h + | m+1, off, e, h => by + rcases List.mem_cons.1 h with rfl | h + · trivial + · exact bvarRevRange_levelWF m off e h + +theorem ihsFrom_levelWF {Uv : Nat} {m : Nat} : ∀ (rs : List (Nat × List VExpr)) (p : Nat), + (∀ q ∈ rs, ∀ e ∈ q.2, e.LevelWF Uv) → ∀ e ∈ ihsFrom m rs p, e.LevelWF Uv + | (j, idxs) :: rs, p, hidx, e, h => by + rcases List.mem_cons.1 h with rfl | h + · refine VExpr.LevelWF.appN (f := .bvar (m+p)) trivial fun e he => ?_ + rcases List.mem_append.1 he with he | he + · obtain ⟨e₀, he₀, rfl⟩ := List.mem_map.1 he + exact ((hidx _ (List.Mem.head _) e₀ he₀).liftN).liftN + · rcases List.mem_cons.1 he with rfl | he + · trivial + · cases he + · exact ihsFrom_levelWF rs (p+1) (fun q hq => hidx q (.tail _ hq)) e h + +/-- Closedness of a telescope of closed binders over an open body. -/ +theorem _root_.Ix.Theory.Named.VExpr.ClosedN.forallN_closed_binders : + ∀ {As : List VExpr}, (∀ A ∈ As, A.ClosedN 0) → + ∀ {X : VExpr} {k : Nat}, X.ClosedN (k + As.length) → + (VExpr.forallN As X).ClosedN k + | [], _, _, _, hX => hX + | _ :: As, hAs, X, k, hX => + ⟨(hAs _ (.head _)).mono (Nat.zero_le _), + VExpr.ClosedN.forallN_closed_binders (fun A h => hAs _ (.tail _ h)) + (by rw [show k+1+As.length = k+(As.length+1) from by omega]; exact hX)⟩ + +end VInductDecl + +namespace VExpr + +theorem forallN_telN_dropN : ∀ (n : Nat) (e : VExpr), + forallN (telN n e) (dropN n e) = e + | 0, _ => rfl + | n+1, .forallE A rest => congrArg (VExpr.forallE A) (forallN_telN_dropN n rest) + | _+1, .bvar _ | _+1, .sort _ | _+1, .const _ _ | _+1, .app _ _ | _+1, .lam _ _ => rfl + +theorem resultOf_forallN : ∀ (As : List VExpr) (B : VExpr), + resultOf (forallN As B) = resultOf B + | [], _ => rfl + | _ :: As, B => resultOf_forallN As B + +theorem resultOf_appN_app (f a : VExpr) : + ∀ es, resultOf ((f.app a).appN es) = (f.app a).appN es + | [] => rfl + | b :: bs => resultOf_appN_app (f.app a) b bs + +theorem resultOf_appN_const (T : Name) (ls : List VLevel) : + ∀ es, resultOf ((VExpr.const T ls).appN es) = + (VExpr.const T ls).appN es + | [] => rfl + | a :: as => resultOf_appN_app (VExpr.const T ls) a as + +end VExpr + +namespace VEnv + +theorem OnTel.mono {env env' : VEnv} {U : Nat} (henv : env ≤ env') : + ∀ {As Γ}, OnTel env U Γ As → OnTel env' U Γ As + | [], _, _ => trivial + | _ :: _, _, ⟨hA, hT⟩ => ⟨hA.mono henv, OnTel.mono henv hT⟩ + +/-- A well-formed telescope is pointwise definitionally equal to itself. -/ +theorem OnTel.telDefEq_refl {env : VEnv} {U : Nat} : + ∀ {Γ As}, OnTel env U Γ As → TelDefEq env U Γ As As + | _, [], _ => trivial + | _, _ :: _, ⟨⟨u, hA⟩, hT⟩ => + ⟨⟨u, hA⟩, OnTel.telDefEq_refl hT⟩ + +/-- A structural telescope equality has equal arity. -/ +theorem TelDefEq.length_eq {env : VEnv} {U : Nat} : + ∀ {Γ As As'}, TelDefEq env U Γ As As' → As.length = As'.length + | _, [], [], _ => rfl + | _, _ :: _, _ :: _, ⟨_, hT⟩ => + congrArg Nat.succ (TelDefEq.length_eq hT) + +/-- The raw side of a structural telescope equality is a well-formed +telescope. -/ +theorem TelDefEq.raw_onTel {env : VEnv} {U : Nat} : + ∀ {Γ As As'}, TelDefEq env U Γ As As' → OnTel env U Γ As + | _, [], [], _ => trivial + | _, _ :: _, _ :: _, ⟨⟨_, hA⟩, hT⟩ => + ⟨⟨_, hA.hasType.1⟩, TelDefEq.raw_onTel hT⟩ + +/-- Extend a structural telescope equality by an identical, well-formed +suffix. The suffix is checked in the completed left-hand context, exactly as +required by `TelDefEq`'s raw-context convention. -/ +theorem TelDefEq.append_refl {env : VEnv} {U : Nat} : + ∀ {Γ As As'}, TelDefEq env U Γ As As' → + ∀ {Bs}, OnTel env U (As.reverse ++ Γ) Bs → + TelDefEq env U Γ (As ++ Bs) (As' ++ Bs) + | _, [], [], _, _, hBs => by + simpa using hBs.telDefEq_refl + | Γ, A :: As, A' :: As', ⟨hA, hT⟩, Bs, hBs => by + refine ⟨hA, ?_⟩ + apply TelDefEq.append_refl hT + simpa [List.reverse_cons, List.append_assoc] using hBs + +/-- Structural telescope equality is monotone in the environment. -/ +theorem TelDefEq.mono {env env' : VEnv} {U : Nat} (henv : env ≤ env') : + ∀ {Γ As As'}, TelDefEq env U Γ As As' → TelDefEq env' U Γ As As' + | _, [], [], _ => trivial + | _, _ :: _, _ :: _, ⟨⟨u, hA⟩, hT⟩ => + ⟨⟨u, hA.mono henv⟩, TelDefEq.mono henv hT⟩ + +/-- Instantiate every universe in a structural telescope equality. -/ +theorem TelDefEq.instL {env : VEnv} {U U' : Nat} {ls : List VLevel} + (hls : ∀ l ∈ ls, l.WF U') : + ∀ {Γ As As'}, TelDefEq env U Γ As As' → + TelDefEq env U' (Γ.map (VExpr.instL ls)) + (As.map (VExpr.instL ls)) (As'.map (VExpr.instL ls)) + | _, [], [], _ => trivial + | _, _ :: As, _ :: As', ⟨⟨u, hA⟩, hT⟩ => by + refine ⟨⟨u.inst ls, hA.instL hls⟩, ?_⟩ + simpa using TelDefEq.instL hls hT + +/-- Extend an existing definitionally equal context by a structurally equal +raw/view telescope. -/ +theorem TelDefEq.extendCtx {env : VEnv} {U : Nat} {Γ₀ : List VExpr} : + ∀ {Γ Γ' As As'}, IsDefEqCtx env U Γ₀ Γ Γ' → + TelDefEq env U Γ As As' → + IsDefEqCtx env U Γ₀ (As.reverse ++ Γ) (As'.reverse ++ Γ') + | Γ, Γ', [], [], hΓ, _ => by simpa using hΓ + | Γ, Γ', _ :: As, _ :: As', hΓ, ⟨⟨_, hA⟩, hT⟩ => by + simpa [List.reverse_cons, List.append_assoc] using + TelDefEq.extendCtx (.succ hΓ hA) hT + +/-- The completed raw and view contexts of a structural telescope equality +are definitionally equal over their common prefix. -/ +theorem TelDefEq.ctx {env : VEnv} {U : Nat} {Γ As As' : List VExpr} + (h : TelDefEq env U Γ As As') : + IsDefEqCtx env U Γ (As.reverse ++ Γ) (As'.reverse ++ Γ) := + h.extendCtx .zero + +/-- Any aligned prefix remains a structural telescope equality. -/ +theorem TelDefEq.take {env : VEnv} {U : Nat} : + ∀ (n : Nat) {Γ As As'}, TelDefEq env U Γ As As' → + TelDefEq env U Γ (As.take n) (As'.take n) + | 0, _, _, _, _ => trivial + | _ + 1, _, [], [], _ => trivial + | n + 1, _, _ :: _, _ :: _, ⟨hA, hT⟩ => + ⟨hA, TelDefEq.take n hT⟩ + +/-- Drop an aligned prefix, retaining the exact raw context accumulated by +the removed binders. -/ +theorem TelDefEq.drop {env : VEnv} {U : Nat} : + ∀ (n : Nat) {Γ As As'}, TelDefEq env U Γ As As' → + TelDefEq env U ((As.take n).reverse ++ Γ) + (As.drop n) (As'.drop n) + | 0, _, _, _, h => by simpa using h + | _ + 1, _, [], [], _ => trivial + | n + 1, Γ, A :: As, _ :: As', ⟨_, hT⟩ => by + have h := TelDefEq.drop n hT + simpa [List.take_succ_cons, List.drop_succ_cons, + List.reverse_cons, List.append_assoc] using h + +/-- Recover the pointwise equality at one aligned binder position together +with its exact preceding raw context. -/ +theorem TelDefEq.getElem? {env : VEnv} {U : Nat} : + ∀ {Γ As As'}, TelDefEq env U Γ As As' → + ∀ {n A A'}, As[n]? = some A → As'[n]? = some A' → + ∃ u, env.IsDefEq U ((As.take n).reverse ++ Γ) A A' (.sort u) + | _, [], [], _, n, _, _, hA, _ => by simp at hA + | Γ, _ :: As, _ :: As', ⟨hhead, htail⟩, 0, A, A', hA, hA' => by + simp only [List.getElem?_cons_zero, Option.some.injEq] at hA hA' + subst A + subst A' + simpa using hhead + | Γ, A₀ :: As, A₀' :: As', ⟨_, htail⟩, n + 1, A, A', hA, hA' => by + simp only [List.getElem?_cons_succ] at hA hA' + have h := TelDefEq.getElem? htail hA hA' + simpa [List.take_succ_cons, List.reverse_cons, List.append_assoc] using h + +/-- Weakening preserves structural telescope equality and shifts both +surfaces at their binder-relative cutoffs. -/ +theorem TelDefEq.weakN {env : VEnv} {U n : Nat} (ord : env.Ordered) + {Γ Γ' : List VExpr} {k : Nat} (W : Ctx.LiftN n k Γ Γ') : + ∀ {As As'}, TelDefEq env U Γ As As' → + TelDefEq env U Γ' + (VExpr.liftTelN n As k) (VExpr.liftTelN n As' k) + | [], [], _ => trivial + | _ :: As, _ :: As', ⟨⟨u, hA⟩, hT⟩ => by + refine ⟨⟨u, hA.weakN ord W⟩, ?_⟩ + simpa [VExpr.liftTelN] using TelDefEq.weakN ord W.succ hT + +/-- Substitute one typed term through a structural telescope equality. -/ +theorem TelDefEq.instN {env : VEnv} {U : Nat} (ord : env.Ordered) + {Γ₀ : List VExpr} {e₀ A₀ : VExpr} + (h₀ : env.HasType U Γ₀ e₀ A₀) {k : Nat} {Γ₁ Γ : List VExpr} + (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) : + ∀ {As As'}, TelDefEq env U Γ₁ As As' → + TelDefEq env U Γ + (VExpr.instTelN e₀ As k) (VExpr.instTelN e₀ As' k) + | [], [], _ => trivial + | _ :: As, _ :: As', ⟨⟨u, hA⟩, hT⟩ => by + refine ⟨⟨u, by simpa using hA.instN ord h₀ W⟩, ?_⟩ + simpa [VExpr.instTelN] using + TelDefEq.instN ord h₀ W.succ hT + +/-- Pointwise telescope equality extends to the corresponding iterated Pi +types once their terminal bodies are definitionally equal in the completed +raw context. This is the construction-side counterpart of `spine_sort`; it +does not require Pi injectivity. -/ +theorem TelDefEq.forallN_defeq {env : VEnv} {U : Nat} : + ∀ {Γ As As' C C' u}, + TelDefEq env U Γ As As' → + env.IsDefEq U (As.reverse ++ Γ) C C' (.sort u) → + ∃ v, env.IsDefEq U Γ + (VExpr.forallN As C) (VExpr.forallN As' C') (.sort v) + | _, [], [], _, _, u, _, hC => ⟨u, hC⟩ + | Γ, A :: As, A' :: As', C, C', u, + ⟨⟨uA, hA⟩, hT⟩, hC => by + have hC' : env.IsDefEq U (As.reverse ++ A :: Γ) + C C' (.sort u) := by + simpa [List.reverse_cons, List.append_assoc] using hC + obtain ⟨v, hbody⟩ := + TelDefEq.forallN_defeq hT hC' + exact ⟨.imax uA v, .forallEDF hA hbody⟩ + +/-- A fully applied spine accepted by the view telescope is also accepted by +the raw telescope. This is the substitution-aware consumer of `TelDefEq`; +it avoids any appeal to whole-Pi injectivity. -/ +theorem TelDefEq.spine_sort {env : VEnv} {U : Nat} (ord : env.Ordered) : + ∀ {Γ As As' es l}, TelDefEq env U Γ As As' → + env.SpineWF U Γ (VExpr.forallN As' (.sort l)) es (.sort l) → + es.length = As.length → + env.SpineWF U Γ (VExpr.forallN As (.sort l)) es (.sort l) + | _, [], [], [], _, _, hsp, _ => by simpa using hsp + | _, [], [], _ :: _, _, _, _, hlen => by simp at hlen + | Γ, A :: As, A' :: As', e :: es, l, ⟨⟨_, hA⟩, hT⟩, + .cons he hrest, hlen => by + have heRaw : env.HasType U Γ e A := hA.defeq' he + have hTinst := TelDefEq.instN ord heRaw (.zero) hT + have hrest' : env.SpineWF U Γ + (VExpr.forallN (VExpr.instTelN e As' 0) (.sort l)) + es (.sort l) := by + simpa [VExpr.instN_forallN] using hrest + have hlen' : es.length = As.length := by simpa using hlen + have hlenInst : + es.length = (VExpr.instTelN e As 0).length := by + rw [VExpr.instTelN_length] + exact hlen' + have hout := TelDefEq.spine_sort ord hTinst hrest' hlenInst + refine .cons heRaw ?_ + simpa [VExpr.instN_forallN] using hout + +/-- Extend a definitionally equal context by the same well-formed telescope +on both sides. -/ +theorem OnTel.extendDefEqCtx {env : VEnv} {U : Nat} {Γ₀ Γ₁ Γ₂ : List VExpr} + (hΓ : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) : + ∀ {As}, OnTel env U Γ₁ As → + IsDefEqCtx env U Γ₀ (As.reverse ++ Γ₁) (As.reverse ++ Γ₂) + | [], _ => by simpa using hΓ + | _ :: As, ⟨⟨_, hA⟩, hT⟩ => by + simpa [List.reverse_cons, List.append_assoc] using + OnTel.extendDefEqCtx (.succ hΓ hA) hT + +/-- Transport a telescope across definitionally equal base contexts. -/ +theorem OnTel.defeqDFC {env : VEnv} {U : Nat} (ord : env.Ordered) + {Γ₀ Γ₁ Γ₂ : List VExpr} (hΓ : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) : + ∀ {As}, OnTel env U Γ₁ As → OnTel env U Γ₂ As + | [], _ => trivial + | _ :: As, ⟨hA, hT⟩ => by + obtain ⟨u, hAt⟩ := hA + exact ⟨⟨u, hAt.defeqDFC ord hΓ⟩, + OnTel.defeqDFC ord (.succ hΓ hAt) hT⟩ + +/-- The view side of a structural telescope equality is itself well formed. +Each tail is transported from the accumulated raw context to the accumulated +view context before recursion continues. -/ +theorem TelDefEq.view_onTel {env : VEnv} {U : Nat} (ord : env.Ordered) : + ∀ {Γ As As'}, TelDefEq env U Γ As As' → OnTel env U Γ As' + | _, [], [], _ => trivial + | _, _ :: _, _ :: _, ⟨⟨u, hA⟩, hT⟩ => + ⟨⟨u, hA.hasType.2⟩, + (TelDefEq.view_onTel ord hT).defeqDFC ord + (.succ .zero hA)⟩ + +/-- Transport a structural telescope equality across definitionally equal +base contexts while retaining its raw/view surfaces. -/ +theorem TelDefEq.defeqDFC {env : VEnv} {U : Nat} (ord : env.Ordered) + {Γ₀ Γ₁ Γ₂ : List VExpr} (hΓ : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) : + ∀ {As As'}, TelDefEq env U Γ₁ As As' → TelDefEq env U Γ₂ As As' + | [], [], _ => trivial + | A :: As, _ :: As', ⟨⟨u, hA⟩, hT⟩ => by + have hA' := hA.defeqDFC ord hΓ + refine ⟨⟨u, hA'⟩, ?_⟩ + exact TelDefEq.defeqDFC ord + (.succ hΓ hA.hasType.1) hT + +/-- Select Lean's kernel-observable parameter surface without losing the +structural equality to the analyzer-owned parameter telescope. Ordinary +parameters keep the raw domain; annotated parameters use the checked domain. +-/ +theorem TelDefEq.generationParams {env : VEnv} {U : Nat} + (ord : env.Ordered) : + ∀ {Γ raw view}, TelDefEq env U Γ raw view → + TelDefEq env U Γ (VInductDecl.generationParams raw view) view + | _, [], [], _ => trivial + | Γ, raw :: raws, view :: views, ⟨⟨u, head⟩, tail⟩ => by + simp only [VInductDecl.generationParams, + VInductDecl.generationParam] + split + · refine ⟨⟨u, head.hasType.2⟩, ?_⟩ + exact (TelDefEq.generationParams ord tail).defeqDFC ord + (.succ (.zero (Γ₀ := Γ)) head) + · exact ⟨⟨u, head⟩, TelDefEq.generationParams ord tail⟩ + +#guard_named_axioms Ix.Theory.Named.VEnv.TelDefEq.generationParams [propext, Quot.sound] + +/-- Transport application-spine typing across definitionally equal +contexts. -/ +theorem SpineWF.defeqDFC {env : VEnv} {U : Nat} (ord : env.Ordered) + {Γ₀ Γ₁ Γ₂ : List VExpr} (hΓ : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) : + ∀ {A es B}, SpineWF env U Γ₁ A es B → SpineWF env U Γ₂ A es B + | _, [], _, .nil => .nil + | _, _ :: _, _, .cons he hT => + .cons (he.defeqDFC ord hΓ) (SpineWF.defeqDFC ord hΓ hT) + +#guard_named_axioms Ix.Theory.Named.VEnv.TelDefEq.raw_onTel [propext] + +#guard_named_axioms Ix.Theory.Named.VEnv.TelDefEq.instL [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.TelDefEq.ctx [propext] + +end VEnv + +namespace VInductDecl +open VEnv + +/-- The exact raw family telescope accepted for generation is well formed in +the pre-environment. -/ +theorem GenerationChecked.WF.rawFamily_onTel {source : VInductDecl} + {gen : GenerationChecked source} {env : VEnv} (h : gen.WF env) : + env.OnTel source.uvars [] + (gen.block.rawParams ++ gen.block.rawIndices) := + h.familyTel.raw_onTel + +/-- The granular family telescope/result contract proves that the stored raw +family constant can be inserted without appealing to whole-`forall` +injectivity. -/ +theorem GenerationChecked.WF.rawFamily_isType {source : VInductDecl} + {gen : GenerationChecked source} {env : VEnv} (h : gen.WF env) : + env.IsType source.uvars [] gen.block.sourceType.type := by + rw [← VExpr.forallN_telN_dropN source.nparams gen.block.sourceType.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams gen.block.sourceType.type), + ← VExpr.forallN_append] + have hresult₀ : env.IsType source.uvars + (gen.block.rawParams ++ gen.block.rawIndices).reverse + gen.block.rawResult := + ⟨_, h.familyResult.hasType.1⟩ + have hresult : env.IsType source.uvars + ((gen.block.rawParams ++ gen.block.rawIndices).reverse ++ []) + gen.block.rawResult := by + simpa using hresult₀ + have hout := IsType.forallN h.rawFamily_onTel hresult + simpa [NormalizedChecked.rawParams, NormalizedChecked.rawIndices, + NormalizedChecked.rawResult] using hout + +/-- The exact raw telescope stored in a paired constructor is well formed in +the post-family environment. -/ +theorem NormalizedCtor.WF.rawDeclared_onTel {source : VInductDecl} + {block : NormalizedChecked source} {ctor : NormalizedCtor} {env : VEnv} + (h : ctor.WF block env) : + env.OnTel source.uvars [] (ctor.declaredBinders source.nparams) := + h.declaredTel.raw_onTel + +/-- The granular constructor telescope/result contract proves that the exact +stored raw constructor can be inserted. -/ +theorem NormalizedCtor.WF.rawDeclared_isType {source : VInductDecl} + {block : NormalizedChecked source} {ctor : NormalizedCtor} {env : VEnv} + (h : ctor.WF block env) : + env.IsType source.uvars [] ctor.raw.type := by + rw [← VExpr.forallN_telN_dropN source.nparams ctor.raw.type, + ← forallN_ctorFields_resultOf (VExpr.dropN source.nparams ctor.raw.type), + ← VExpr.forallN_append] + have hresult₀ : env.IsType source.uvars + (ctor.declaredBinders source.nparams).reverse + (ctor.rawResult source.nparams) := + ⟨_, h.declaredResult.hasType.1⟩ + have hresult : env.IsType source.uvars + ((ctor.declaredBinders source.nparams).reverse ++ []) + (ctor.rawResult source.nparams) := by + simpa using hresult₀ + have hout := IsType.forallN h.rawDeclared_onTel hresult + simpa [NormalizedCtor.declaredBinders, NormalizedCtor.rawFields, + NormalizedCtor.rawResult] using hout + +/-- The raw family/field telescope actually emitted in mixed artifacts is +well formed independently of the constructor's stored parameter surface. -/ +theorem NormalizedCtor.WF.rawEmitted_onTel {source : VInductDecl} + {block : NormalizedChecked source} {ctor : NormalizedCtor} {env : VEnv} + (h : ctor.WF block env) : + env.OnTel source.uvars [] (ctor.emittedBinders block) := + h.emittedTel.raw_onTel + +/-- A granular constructor certificate is monotone after its staged family +insertion. -/ +theorem NormalizedCtor.WF.mono {source : VInductDecl} + {block : NormalizedChecked source} {ctor : NormalizedCtor} + {env env' : VEnv} (henv : env ≤ env') (h : ctor.WF block env) : + ctor.WF block env' where + declaredTel := h.declaredTel.mono henv + declaredResult := h.declaredResult.mono henv + emittedTel := h.emittedTel.mono henv + emittedResult := h.emittedResult.mono henv + +/-- Retrieve the insertion-ready proof for any paired raw constructor in the +precise post-family environment named by the block certificate. -/ +theorem GenerationChecked.WF.rawCtor_isType {source : VInductDecl} + {gen : GenerationChecked source} {env envT : VEnv} (h : gen.WF env) + (hadd : env.addConst gen.block.sourceType.name + gen.block.sourceType.toVConstant = some envT) + {ctor : NormalizedCtor} (hctor : ctor ∈ gen.block.ctorPairs) : + envT.IsType source.uvars [] ctor.raw.type := + (h.ctors envT hadd ctor hctor).rawDeclared_isType + +/-! Mutual declaration-stage consequences. -/ + +theorem NormalizedFamily.WF.rawFamily_onTel {source : VInductDecl} + {gen : BlockGenerationChecked source} {family : NormalizedFamily} + {env : VEnv} (h : family.WF gen env) : + env.OnTel source.uvars [] + (family.rawParams source.nparams ++ + family.rawIndices source.nparams) := + h.familyTel.raw_onTel + +theorem NormalizedFamily.WF.rawFamily_isType {source : VInductDecl} + {gen : BlockGenerationChecked source} {family : NormalizedFamily} + {env : VEnv} (h : family.WF gen env) : + env.IsType source.uvars [] family.raw.type := by + rw [← VExpr.forallN_telN_dropN source.nparams family.raw.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams family.raw.type), + ← VExpr.forallN_append] + have hresult₀ : env.IsType source.uvars + (family.rawParams source.nparams ++ + family.rawIndices source.nparams).reverse + (family.rawResult source.nparams) := + ⟨_, h.familyResult.hasType.1⟩ + have hresult : env.IsType source.uvars + ((family.rawParams source.nparams ++ + family.rawIndices source.nparams).reverse ++ []) + (family.rawResult source.nparams) := by + simpa using hresult₀ + have hout := IsType.forallN h.rawFamily_onTel hresult + simpa [NormalizedFamily.rawParams, NormalizedFamily.rawIndices, + NormalizedFamily.rawResult] using hout + +theorem NormalizedFamily.WF.mono {source : VInductDecl} + {gen : BlockGenerationChecked source} {family : NormalizedFamily} + {env env' : VEnv} (henv : env ≤ env') (h : family.WF gen env) : + family.WF gen env' where + familyTel := h.familyTel.mono henv + familyResult := h.familyResult.mono henv + +theorem NormalizedBlockCtor.WF.rawDeclared_onTel + {source : VInductDecl} {gen : BlockGenerationChecked source} + {constructor : NormalizedBlockCtor} {env : VEnv} + (h : NormalizedBlockCtor.WF gen constructor env) : + env.OnTel source.uvars [] + (NormalizedBlockCtor.declaredBinders + (source := source) constructor) := + h.declaredTel.raw_onTel + +theorem NormalizedBlockCtor.WF.rawDeclared_isType + {source : VInductDecl} {gen : BlockGenerationChecked source} + {constructor : NormalizedBlockCtor} {env : VEnv} + (h : NormalizedBlockCtor.WF gen constructor env) : + env.IsType source.uvars [] constructor.ctor.raw.type := by + rw [← VExpr.forallN_telN_dropN source.nparams + constructor.ctor.raw.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams constructor.ctor.raw.type), + ← VExpr.forallN_append] + have hresult₀ : env.IsType source.uvars + (NormalizedBlockCtor.declaredBinders + (source := source) constructor).reverse + (NormalizedBlockCtor.rawResult + (source := source) constructor) := + ⟨_, h.declaredResult.hasType.1⟩ + have hresult : env.IsType source.uvars + ((NormalizedBlockCtor.declaredBinders + (source := source) constructor).reverse ++ []) + (NormalizedBlockCtor.rawResult + (source := source) constructor) := by + simpa using hresult₀ + have hout := IsType.forallN h.rawDeclared_onTel hresult + simpa [NormalizedBlockCtor.declaredBinders, + NormalizedBlockCtor.rawResult, NormalizedCtor.declaredBinders, + NormalizedCtor.rawFields, NormalizedCtor.rawResult] using hout + +theorem NormalizedBlockCtor.WF.rawEmitted_onTel + {source : VInductDecl} {gen : BlockGenerationChecked source} + {constructor : NormalizedBlockCtor} {env : VEnv} + (h : NormalizedBlockCtor.WF gen constructor env) : + env.OnTel source.uvars [] + (NormalizedBlockCtor.emittedBinders gen constructor) := + h.emittedTel.raw_onTel + +theorem NormalizedBlockCtor.WF.mono + {source : VInductDecl} {gen : BlockGenerationChecked source} + {constructor : NormalizedBlockCtor} {env env' : VEnv} + (henv : env ≤ env') (h : NormalizedBlockCtor.WF gen constructor env) : + NormalizedBlockCtor.WF gen constructor env' where + declaredTel := h.declaredTel.mono henv + declaredResult := h.declaredResult.mono henv + emittedTel := h.emittedTel.mono henv + emittedResult := h.emittedResult.mono henv + owner := h.owner + recursive := fun recursive hrecursive => by + obtain ⟨family, hfamily, hordinal, hfield, hwf⟩ := + h.recursive recursive hrecursive + exact ⟨family, hfamily, hordinal, hfield, + ⟨hwf.1.mono henv, hwf.2.mono henv⟩⟩ + resultSpine := h.resultSpine.mono henv + +theorem BlockGenerationChecked.WF.rawFamily_isType + {source : VInductDecl} {gen : BlockGenerationChecked source} + {env blockEnv : VEnv} (h : gen.WF env blockEnv) + {family : NormalizedFamily} (hfamily : family ∈ gen.families) : + env.IsType source.uvars [] family.raw.type := + (h.families family hfamily).rawFamily_isType + +theorem BlockGenerationChecked.WF.rawCtor_isType + {source : VInductDecl} {gen : BlockGenerationChecked source} + {env blockEnv : VEnv} (h : gen.WF env blockEnv) + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + blockEnv.IsType source.uvars [] constructor.ctor.raw.type := + (h.constructors constructor hconstructor).rawDeclared_isType + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationChecked.WF.rawFamily_isType [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationChecked.WF.rawCtor_isType [propext, Quot.sound] + +theorem RecArg.WF.mono {env env' : VEnv} {U : Nat} {l : VLevel} + {Is Γ : List VExpr} {r : RecArg} (henv : env ≤ env') + (h : r.WF U env l Is Γ) : r.WF U env' l Is Γ := + ⟨h.1.mono henv, h.2.mono henv⟩ + +/-- The checked recursive/non-recursive field interpretation is monotone in +the environment. -/ +theorem checkedBlockFieldsWF_mono {env env' : VEnv} {U : Nat} + {resultLevel : VLevel} {familyIndices : List (List VExpr)} + (henv : env ≤ env') : ∀ {fields classifications Γ j}, + checkedBlockFieldsWF env U resultLevel familyIndices + fields classifications Γ j → + checkedBlockFieldsWF env' U resultLevel familyIndices + fields classifications Γ j + | [], [], _, _, _ => trivial + | [], _ :: _, _, _, h => by + simp [checkedBlockFieldsWF] at h + | _ :: _, [], _, _, h => by + simp [checkedBlockFieldsWF] at h + | B :: Bs, none :: classifications, Γ, j, + ⟨⟨u, hB, hlevel⟩, htail⟩ => + ⟨⟨u, hB.mono henv, hlevel⟩, + checkedBlockFieldsWF_mono henv htail⟩ + | B :: Bs, some recursive :: classifications, Γ, j, h => by + simp only [checkedBlockFieldsWF] at h ⊢ + obtain ⟨⟨hfield, hrecursive⟩, htail⟩ := h + refine ⟨⟨hfield, ?_⟩, + checkedBlockFieldsWF_mono henv htail⟩ + cases htarget : familyIndices[recursive.targetType]? with + | none => simp [htarget] at hrecursive + | some indices => + rw [htarget] at hrecursive + exact hrecursive.mono henv + +/-- The erased family-spine semantics is monotone in the environment. -/ +theorem checkedFamilyListsWF_mono {source : VInductDecl} + {params : List VExpr} {env env' : VEnv} {resultLevel : VLevel} + {familyIndices : List (List VExpr)} (henv : env ≤ env') : + ∀ levels indices constructors, + checkedFamilyListsWF source params env resultLevel familyIndices + levels indices constructors → + checkedFamilyListsWF source params env' resultLevel familyIndices + levels indices constructors := by + intro levels + induction levels with + | nil => + intro indices constructors h + cases indices <;> cases constructors <;> + simp_all [checkedFamilyListsWF] + | cons level levels ih => + intro indices constructors h + cases indices with + | nil => simp [checkedFamilyListsWF] at h + | cons index indices => + cases constructors with + | nil => simp [checkedFamilyListsWF] at h + | cons familyConstructors constructors => + simp only [checkedFamilyListsWF] at h ⊢ + obtain ⟨hlevel, hindices, hconstructors, htail⟩ := h + exact ⟨hlevel, hindices.mono henv, + fun constructor hconstructor => + ⟨checkedBlockFieldsWF_mono henv + (hconstructors constructor hconstructor).1, + (hconstructors constructor hconstructor).2.mono henv⟩, + ih indices constructors htail⟩ + +theorem CheckedBlock.WF.mono {source : VInductDecl} + {checked : source.CheckedBlock} {env env' : VEnv} + {resultLevel : VLevel} (henv : env ≤ env') + (h : checked.WF env resultLevel) : + checked.WF env' resultLevel := + checkedFamilyListsWF_mono henv _ _ _ h + +/-- Transport recursive-argument evidence across definitionally equal base +contexts. The private binder telescope is transported first, then the +terminal family-index spine is transported beneath that same telescope. -/ +theorem RecArg.WF.defeqDFC {env : VEnv} {U : Nat} {l : VLevel} + {Is Γ₀ Γ₁ Γ₂ : List VExpr} {r : RecArg} (ord : env.Ordered) + (hΓ : env.IsDefEqCtx U Γ₀ Γ₁ Γ₂) + (h : r.WF U env l Is Γ₁) : r.WF U env l Is Γ₂ := by + have htel := h.1.defeqDFC ord hΓ + have hctx := h.1.extendDefEqCtx hΓ + exact ⟨htel, h.2.defeqDFC ord hctx⟩ + +theorem fieldsWF_mono {U : Nat} {T : Name} {np : Nat} {env env' : VEnv} {l : VLevel} + {Is : List VExpr} (henv : env ≤ env') : ∀ {Γ j Bs}, + fieldsWF U T np env l Is Γ j Bs → fieldsWF U T np env' l Is Γ j Bs + | _, _, [], _ => trivial + | _, _, _ :: _, ⟨hB, hSp, hT⟩ => by + refine ⟨?_, fun hrec => (hSp hrec).mono henv, fieldsWF_mono henv hT⟩ + rcases hB with hrec | hfun | ⟨hnone, u, h, hl⟩ + · exact .inl hrec + · obtain ⟨r, hr, hne, hwf⟩ := hfun + exact .inr (.inl ⟨r, hr, hne, hwf.mono henv⟩) + · exact .inr (.inr ⟨hnone, u, h.mono henv, hl⟩) + +/-- The checked-view semantic certificate is monotone in the environment. -/ +theorem Checked.WF.mono {decl : VInductDecl} {checked : decl.Checked} + {env env' : VEnv} (henv : env ≤ env') (h : checked.WF env) : + checked.WF env' := by + unfold Checked.WF at h ⊢ + refine ⟨h.1.mono henv, fun c hc => ?_⟩ + exact ⟨fieldsWF_mono henv (h.2 c hc).1, (h.2 c hc).2.mono henv⟩ + +/-- Exact syntactic decomposition of an accepted family view into its +parameter telescope, index telescope, and terminal sort. -/ +theorem Checked.type_eq + {source : VInductDecl} (checked : source.Checked) : + checked.type.type = + VExpr.forallN checked.params + (VExpr.forallN checked.indices (.sort checked.resultLevel)) := by + rw [← VExpr.forallN_telN_dropN source.nparams checked.type.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams checked.type.type), + checked.result_eq, checked.params_eq, checked.indices_eq] + +/-- The semantic checker contract types the family before that family is +inserted. This is the exact premise needed by the first transaction step. -/ +theorem Checked.WF.family_isType + {source : VInductDecl} {checked : source.Checked} + {env : VEnv} (h : checked.WF env) : + env.IsType source.uvars [] checked.type.type := by + rw [← VExpr.forallN_telN_dropN source.nparams checked.type.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams checked.type.type), + checked.result_eq, ← VExpr.forallN_append] + exact IsType.forallN + (by simpa [checked.params_eq, checked.indices_eq] using h.1) + ⟨_, HasType.sort checked.direct_anatomy.2.2.1⟩ + +/-- Once the retained family constant has the checked family type, the +checked constructor-result spine types the exact normalized family +application. This fact depends only on analyzer semantics and the constant's +ordinary typing judgment; callers do not need to restate result typing for +each constructor candidate. -/ +theorem GenerationChecked.checkedResultTarget_hasType + {source : VInductDecl} (gen : GenerationChecked source) + {env : VEnv} (henv : env.Ordered) + (hchecked : gen.block.checked.WF env) + (familyConst : env.HasType source.uvars [] + (.const gen.block.sourceType.name (VLevel.params source.uvars)) + gen.block.checked.type.type) + {ctor : NormalizedCtor} (hctor : ctor ∈ gen.block.ctorPairs) : + env.HasType source.uvars (ctor.viewBinders gen.block).reverse + (ctor.resultTarget gen.block) + (.sort gen.block.checked.resultLevel) := by + have htype := gen.block.checked.type_eq + have hfamily : env.HasType source.uvars + (ctor.view.fields.reverse ++ gen.block.checked.params.reverse) + (VExpr.appN + (.const gen.block.sourceType.name (VLevel.params source.uvars)) + (VExpr.bvarRevRange ctor.view.fields.length + gen.block.checked.params.length)) + (VExpr.forallN + (VExpr.liftTelN ctor.view.fields.length + gen.block.checked.indices 0) + (.sort gen.block.checked.resultLevel)) := by + have hconst : env.HasType source.uvars + (ctor.view.fields.reverse ++ + gen.block.checked.params.reverse ++ []) + (.const gen.block.sourceType.name (VLevel.params source.uvars)) + (VExpr.forallN gen.block.checked.params + (VExpr.forallN gen.block.checked.indices + (.sort gen.block.checked.resultLevel))) := by + simpa only [htype] using familyConst.weak0 henv + have happ := HasType.appN_selfSpine' + (As := gen.block.checked.params) + (B := VExpr.forallN gen.block.checked.indices + (.sort gen.block.checked.resultLevel)) + (Δ := ctor.view.fields.reverse) (Γ := []) + (by simpa only [← htype] using gen.block.checked.type_closed) + hconst + rw [List.length_reverse, VExpr.liftN_forallN] at happ + simpa using happ + have hspine : env.SpineWF source.uvars + (ctor.view.fields.reverse ++ gen.block.checked.params.reverse) + (VExpr.forallN + (VExpr.liftTelN ctor.view.fields.length + gen.block.checked.indices 0) + (.sort gen.block.checked.resultLevel)) + ctor.view.resultIndices + (.sort gen.block.checked.resultLevel) := by + obtain ⟨c, hc, hview⟩ := gen.viewCtor_ofDirect hctor + have h := (hchecked.2 c hc).2 + rw [hview] + simpa [CheckedCtor.ofDirect, gen.block.uvars_eq, + gen.block.nparams_eq] using h + have hresult := hspine.hasType_appN hfamily + rw [← VExpr.appN_append] at hresult + have hparams : gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hfields := (gen.shape.2.2.2.2.2 ctor hctor).2.2.2 + rw [hparams, ← hfields] at hresult + simpa [NormalizedCtor.viewBinders, + NormalizedCtor.resultTarget] using hresult + +/-- A paired checked constructor's stored view type is exactly its analyzed +binder telescope followed by the normalized family result application. -/ +theorem GenerationChecked.viewCtorType_eq + {source : VInductDecl} (gen : GenerationChecked source) + {ctor : NormalizedCtor} (hctor : ctor ∈ gen.block.ctorPairs) : + ctor.view.value.type = + VExpr.forallN (ctor.viewBinders gen.block) + (ctor.resultTarget gen.block) := by + obtain ⟨c, hc, hview⟩ := gen.viewCtor_ofDirect hctor + have hcAn := gen.block.checked.direct_anatomy.2.2.2.2.2 c hc + have htype := VExpr.forallN_telN_dropN + gen.block.normalization.view.nparams c.type + rw [hcAn.2.1, (stage3Ctor_eq hcAn.2.2).1] at htype + have hfields := (gen.shape.2.2.2.2.2 ctor hctor).2.2.2 + have hfields' : + (ctor.rawFields gen.block.normalization.view.nparams).length = + (ctorFields (VExpr.dropN + gen.block.normalization.view.nparams c.type)).length := by + simpa [gen.block.nparams_eq, hview, + CheckedCtor.ofDirect] using hfields + simpa [← VExpr.forallN_append, NormalizedCtor.viewBinders, + NormalizedCtor.resultTarget, hview, hfields', + CheckedCtor.ofDirect, gen.block.uvars_eq, + gen.block.nparams_eq, gen.block.sourceType_name_eq, + gen.block.checked.params_eq, Nat.zero_add] using htype.symm + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.type_eq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationChecked.viewCtorType_eq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationChecked.checkedResultTarget_hasType [propext, Quot.sound] + +/-- Final-environment invariant for mixed raw/view generation. It contains +only facts stable after the raw family and constructors have been inserted; +the staged pre-family/post-family split remains in `GenerationChecked.WF`. -/ +theorem GenerationChecked.sourceLevels_wf {source : VInductDecl} + (gen : GenerationChecked source) : + ∀ l ∈ gen.sourceLevels, l.WF gen.recUvars := + VLevel.params'_wf + +@[simp] theorem GenerationChecked.sourceLevels_eq {source : VInductDecl} + (gen : GenerationChecked source) : + gen.sourceLevels = + VLevel.params' source.uvars gen.elimination.offset := rfl + +@[simp] theorem GenerationChecked.recUvars_eq {source : VInductDecl} + (gen : GenerationChecked source) : + gen.recUvars = source.uvars + gen.elimination.offset := rfl + +@[simp] theorem GenerationChecked.recLevels_eq {source : VInductDecl} + (gen : GenerationChecked source) : + gen.recLevels = VLevel.params gen.recUvars := rfl + +theorem GenerationChecked.sourceLevels_length {source : VInductDecl} + (gen : GenerationChecked source) : + gen.sourceLevels.length = source.uvars := + VLevel.params'_length + +theorem GenerationChecked.motiveLevel_wf {source : VInductDecl} + (gen : GenerationChecked source) : + gen.motiveLevel.WF gen.recUvars := by + cases h : gen.elimination <;> + simp [GenerationChecked.motiveLevel, + GenerationChecked.recUvars, ElimMode.recUvars, + ElimMode.offset, ElimMode.motiveLevel, VLevel.WF, h] + +theorem GenerationChecked.recLevels_wf {source : VInductDecl} + (gen : GenerationChecked source) : + ∀ l ∈ gen.recLevels, l.WF gen.recUvars := + VLevel.params_wf + +theorem GenerationChecked.recLevels_length {source : VInductDecl} + (gen : GenerationChecked source) : + gen.recLevels.length = gen.recUvars := + VLevel.params_length + +structure GenerationEnv {source : VInductDecl} + (gen : GenerationChecked source) (env : VEnv) : Prop where + ord : env.Ordered + checked : gen.block.checked.WF env + familyTel : + env.TelDefEq source.uvars [] + (gen.block.rawParams ++ gen.block.rawIndices) + (gen.block.checked.params ++ gen.block.checked.indices) + familyResult : + env.IsDefEq source.uvars + (gen.block.rawParams ++ gen.block.rawIndices).reverse + gen.block.rawResult (.sort gen.block.checked.resultLevel) + (.sort (.succ gen.block.checked.resultLevel)) + ctorWF : + ∀ ctor ∈ gen.block.ctorPairs, ctor.WF gen.block env + familyConst : + env.constants gen.block.sourceType.name = + some gen.block.sourceType.toVConstant + ctorConst : + ∀ ctor ∈ gen.block.ctorPairs, + env.constants ctor.raw.name = some ctor.raw.toVConstant + +/-- Promote a staged generation certificate into the final invariant once the +transaction supplies environment growth and exact raw constant lookups. -/ +theorem GenerationChecked.WF.toGenerationEnv {source : VInductDecl} + {gen : GenerationChecked source} {pre envT env : VEnv} + (h : gen.WF pre) + (hadd : pre.addConst gen.block.sourceType.name + gen.block.sourceType.toVConstant = some envT) + (hlePre : pre ≤ env) (hleT : envT ≤ env) (ord : env.Ordered) + (hfamily : env.constants gen.block.sourceType.name = + some gen.block.sourceType.toVConstant) + (hctors : ∀ ctor ∈ gen.block.ctorPairs, + env.constants ctor.raw.name = some ctor.raw.toVConstant) : + GenerationEnv gen env where + ord := ord + checked := h.blockWF.2.mono hlePre + familyTel := h.familyTel.mono hlePre + familyResult := h.familyResult.mono hlePre + ctorWF := fun ctor hctor => (h.ctors envT hadd ctor hctor).mono hleT + familyConst := hfamily + ctorConst := hctors + +theorem BlockGenerationChecked.sourceLevels_wf {source : VInductDecl} + (gen : BlockGenerationChecked source) : + ∀ l ∈ gen.sourceLevels, l.WF gen.recUvars := + VLevel.params'_wf + +@[simp] theorem BlockGenerationChecked.sourceLevels_eq + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.sourceLevels = + VLevel.params' source.uvars gen.elimination.offset := rfl + +@[simp] theorem BlockGenerationChecked.recUvars_eq + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.recUvars = source.uvars + gen.elimination.offset := rfl + +@[simp] theorem BlockGenerationChecked.recLevels_eq + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.recLevels = VLevel.params gen.recUvars := rfl + +theorem BlockGenerationChecked.sourceLevels_length + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.sourceLevels.length = source.uvars := + VLevel.params'_length + +theorem BlockGenerationChecked.motiveLevel_wf + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.motiveLevel.WF gen.recUvars := by + cases h : gen.elimination <;> + simp [BlockGenerationChecked.motiveLevel, + BlockGenerationChecked.recUvars, ElimMode.recUvars, + ElimMode.offset, ElimMode.motiveLevel, VLevel.WF, h] + +theorem BlockGenerationChecked.recLevels_wf + {source : VInductDecl} (gen : BlockGenerationChecked source) : + ∀ l ∈ gen.recLevels, l.WF gen.recUvars := + VLevel.params_wf + +theorem BlockGenerationChecked.recLevels_length + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.recLevels.length = gen.recUvars := + VLevel.params_length + +/-- Stable final-environment invariant for mutual artifact generation. -/ +structure BlockGenerationEnv {source : VInductDecl} + (gen : BlockGenerationChecked source) (env : VEnv) : Prop where + ord : env.Ordered + resultLevelWF : gen.validated.resultLevel.WF source.uvars + checked : + gen.block.checked.WF env gen.validated.resultLevel + paramsTel : + env.TelDefEq source.uvars [] gen.block.rawParams + gen.block.checked.params + familyWF : ∀ family ∈ gen.families, family.WF gen env + ctorWF : ∀ constructor ∈ gen.flatCtors, + NormalizedBlockCtor.WF gen constructor env + familyConst : ∀ family ∈ gen.families, + env.constants family.raw.name = some family.raw.toVConstant + ctorConst : ∀ constructor ∈ gen.flatCtors, + env.constants constructor.ctor.raw.name = + some constructor.ctor.raw.toVConstant + +theorem BlockGenerationChecked.WF.toBlockGenerationEnv + {source : VInductDecl} {gen : BlockGenerationChecked source} + {pre blockEnv env : VEnv} (h : gen.WF pre blockEnv) + (hlePre : pre ≤ env) (hleBlock : blockEnv ≤ env) + (ord : env.Ordered) + (hfamilies : ∀ family ∈ gen.families, + env.constants family.raw.name = some family.raw.toVConstant) + (hctors : ∀ constructor ∈ gen.flatCtors, + env.constants constructor.ctor.raw.name = + some constructor.ctor.raw.toVConstant) : + BlockGenerationEnv gen env where + ord := ord + resultLevelWF := h.resultLevelWF + checked := h.blockWF.2.mono hlePre + paramsTel := h.paramsTel.mono hlePre + familyWF := fun family hfamily => + (h.families family hfamily).mono hlePre + ctorWF := fun constructor hconstructor => + (h.constructors constructor hconstructor).mono hleBlock + familyConst := hfamilies + ctorConst := hctors + +theorem NormalizedFamily.rawType_eq {source : VInductDecl} + (family : NormalizedFamily) : + family.raw.type = + VExpr.forallN (family.rawParams source.nparams) + (VExpr.forallN (family.rawIndices source.nparams) + (family.rawResult source.nparams)) := by + conv => lhs + rw [← VExpr.forallN_telN_dropN source.nparams family.raw.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams family.raw.type)] + rfl + +namespace BlockGenerationEnv + +variable {source : VInductDecl} {gen : BlockGenerationChecked source} + {env : VEnv} (S : BlockGenerationEnv gen env) +include S + +theorem mono {env' : VEnv} (henv : env ≤ env') (ord : env'.Ordered) : + BlockGenerationEnv gen env' where + ord := ord + resultLevelWF := S.resultLevelWF + checked := S.checked.mono henv + paramsTel := S.paramsTel.mono henv + familyWF := fun family hfamily => (S.familyWF family hfamily).mono henv + ctorWF := fun constructor hconstructor => + (S.ctorWF constructor hconstructor).mono henv + familyConst := fun family hfamily => + henv.constants (S.familyConst family hfamily) + ctorConst := fun constructor hconstructor => + henv.constants (S.ctorConst constructor hconstructor) + +theorem generationParams_defeq : + env.TelDefEq source.uvars [] + (generationParams gen.block.rawParams gen.block.checked.params) + gen.block.checked.params := + S.paramsTel.generationParams S.ord + +theorem generationParams_length : + (generationParams gen.block.rawParams + gen.block.checked.params).length = source.nparams := by + exact (generationParams_length_of_eq S.paramsTel.length_eq).trans + gen.shape.1 + +theorem generationParams_ctx : + env.IsDefEqCtx source.uvars [] + (generationParams gen.block.rawParams + gen.block.checked.params).reverse + gen.block.checked.params.reverse := by + simpa using S.generationParams_defeq.ctx + +theorem generationParams_ctx_rec : + env.IsDefEqCtx gen.recUvars [] gen.paramsTel.reverse + (gen.block.checked.params.map + (VExpr.instL gen.sourceLevels)).reverse := by + have h := S.generationParams_defeq.instL + (U' := gen.recUvars) gen.sourceLevels_wf + simpa [BlockGenerationChecked.paramsTel, List.map_reverse] using h.ctx + +theorem rawFamily_onTel {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.OnTel source.uvars [] + (family.rawParams source.nparams ++ + family.rawIndices source.nparams) := + (S.familyWF family hfamily).familyTel.raw_onTel + +theorem familyConst_decl {family : NormalizedFamily} + (hfamily : family ∈ gen.families) {Γ : List VExpr} : + env.HasType source.uvars Γ + (.const family.raw.name (VLevel.params source.uvars)) + family.raw.type := by + have hwf : family.raw.toVConstant.WF env := by + show env.IsType family.raw.uvars [] family.raw.type + rw [gen.family_uvars hfamily] + exact (S.familyWF family hfamily).rawFamily_isType + have h := HasType.const0 (S.familyConst family hfamily) hwf + rw [gen.family_uvars hfamily] at h + exact h.weak0 S.ord + +theorem ctorConst_decl {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) {Γ : List VExpr} : + env.HasType source.uvars Γ + (.const constructor.ctor.raw.name (VLevel.params source.uvars)) + constructor.ctor.raw.type := by + have hwf : constructor.ctor.raw.toVConstant.WF env := by + show env.IsType constructor.ctor.raw.uvars [] + constructor.ctor.raw.type + rw [gen.flatCtor_uvars hconstructor] + exact (S.ctorWF constructor hconstructor).rawDeclared_isType + have h := HasType.const0 (S.ctorConst constructor hconstructor) hwf + rw [gen.flatCtor_uvars hconstructor] at h + exact h.weak0 S.ord + +theorem rawParams_defeq {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.TelDefEq source.uvars [] + (family.rawParams source.nparams) gen.block.checked.params := by + have h := (S.familyWF family hfamily).familyTel.take source.nparams + have hraw : + (family.rawParams source.nparams ++ + family.rawIndices source.nparams).take source.nparams = + family.rawParams source.nparams := by + let Ps := family.rawParams source.nparams + let Is := family.rawIndices source.nparams + have hlen : Ps.length = source.nparams := + (gen.shape.2.2.2.2 family hfamily).2.2.1 + change (Ps ++ Is).take source.nparams = Ps + rw [← hlen, List.take_append, List.take_length] + simp + have hviewLen : gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hview : + (gen.block.checked.params ++ family.view.indices).take + source.nparams = gen.block.checked.params := by + rw [← hviewLen, List.take_append, List.take_length] + simp + rw [hraw, hview] at h + exact h + +theorem emittedFamilyTel {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.TelDefEq source.uvars [] + (family.rawParams source.nparams ++ family.rawIndices source.nparams) + (gen.block.checked.params ++ family.rawIndices source.nparams) := by + have hindices : env.OnTel source.uvars + (family.rawParams source.nparams).reverse + (family.rawIndices source.nparams) := by + simpa using (S.rawFamily_onTel hfamily).of_append.2 + exact (S.rawParams_defeq hfamily).append_refl (by simpa using hindices) + +theorem emittedFamily_onTel {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.OnTel source.uvars [] + (gen.block.checked.params ++ family.rawIndices source.nparams) := + (S.emittedFamilyTel hfamily).view_onTel S.ord + +theorem generationFamilyTel {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.TelDefEq source.uvars [] + (generationParams gen.block.rawParams gen.block.checked.params ++ + family.rawIndices source.nparams) + (gen.block.checked.params ++ family.rawIndices source.nparams) := by + have hindicesChecked : env.OnTel source.uvars + gen.block.checked.params.reverse (family.rawIndices source.nparams) := by + simpa using (S.emittedFamily_onTel hfamily).of_append.2 + have hindicesGeneration : env.OnTel source.uvars + (generationParams gen.block.rawParams + gen.block.checked.params).reverse + (family.rawIndices source.nparams) := + hindicesChecked.defeqDFC S.ord + (S.generationParams_ctx.symm S.ord) + exact S.generationParams_defeq.append_refl + (by simpa using hindicesGeneration) + +theorem generationFamily_onTel {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.OnTel source.uvars [] + (generationParams gen.block.rawParams gen.block.checked.params ++ + family.rawIndices source.nparams) := + (S.generationFamilyTel hfamily).raw_onTel + +theorem emittedFamily_ctx {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.IsDefEqCtx source.uvars [] + (family.rawParams source.nparams ++ + family.rawIndices source.nparams).reverse + (gen.block.checked.params ++ + family.rawIndices source.nparams).reverse := by + simpa using (S.emittedFamilyTel hfamily).ctx + +theorem generationFamily_ctx {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.IsDefEqCtx source.uvars [] + (generationParams gen.block.rawParams gen.block.checked.params ++ + family.rawIndices source.nparams).reverse + (gen.block.checked.params ++ + family.rawIndices source.nparams).reverse := by + simpa using (S.generationFamilyTel hfamily).ctx + +theorem familyConst_emitted_decl {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.HasType source.uvars [] + (.const family.raw.name (VLevel.params source.uvars)) + (VExpr.forallN + (gen.block.checked.params ++ family.rawIndices source.nparams) + (family.rawResult source.nparams)) := by + have hc : env.HasType source.uvars [] + (.const family.raw.name (VLevel.params source.uvars)) + (VExpr.forallN + (family.rawParams source.nparams ++ family.rawIndices source.nparams) + (family.rawResult source.nparams)) := by + rw [VExpr.forallN_append, ← family.rawType_eq] + exact S.familyConst_decl hfamily + obtain ⟨_, htel⟩ := (S.emittedFamilyTel hfamily).forallN_defeq + (by simpa [VEnv.HasType] using + (S.familyWF family hfamily).familyResult.hasType.1) + exact htel.defeq hc + +theorem familyConst_generation_decl {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.HasType source.uvars [] + (.const family.raw.name (VLevel.params source.uvars)) + (VExpr.forallN + (generationParams gen.block.rawParams gen.block.checked.params ++ + family.rawIndices source.nparams) + (family.rawResult source.nparams)) := by + have hresultChecked := + (S.familyWF family hfamily).familyResult.defeqDFC S.ord + (S.emittedFamily_ctx hfamily) + have hresultGeneration := hresultChecked.defeqDFC S.ord + ((S.generationFamily_ctx hfamily).symm S.ord) + obtain ⟨_, htel⟩ := (S.generationFamilyTel hfamily).forallN_defeq + (by simpa [VEnv.HasType] using hresultGeneration.hasType.1) + exact htel.defeq' (S.familyConst_emitted_decl hfamily) + +theorem familyApp_hasType {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.HasType gen.recUvars + ((gen.idxTel family).reverse ++ gen.paramsTel.reverse) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (gen.idxTel family).length source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + let ls := gen.sourceLevels + have hconst₀ := (S.familyConst_generation_decl hfamily).instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hconst₁ : env.HasType gen.recUvars [] + (.const family.raw.name ls) + (VExpr.forallN (gen.paramsTel ++ gen.idxTel family) + ((family.rawResult source.nparams).instL ls)) := by + simpa [ls, BlockGenerationChecked.paramsTel, + BlockGenerationChecked.idxTel, VExpr.instL_forallN, + VExpr.instL, VLevel.params_map_inst_params'] using hconst₀ + have hclosed : + (VExpr.forallN (gen.paramsTel ++ gen.idxTel family) + ((family.rawResult source.nparams).instL ls)).ClosedN 0 := + (hconst₁.closedN' S.ord.closed trivial).2.2 + have hconst : env.HasType gen.recUvars + ((gen.paramsTel ++ gen.idxTel family).reverse) + (.const family.raw.name ls) + (VExpr.forallN (gen.paramsTel ++ gen.idxTel family) + ((family.rawResult source.nparams).instL ls)) := + hconst₁.weak0 S.ord + have happ := HasType.appN_selfSpine' + (Δ := []) (Γ := []) hclosed (by simpa using hconst) + simp only [List.length_nil, VExpr.liftN_zero, List.nil_append, + List.append_nil] at happ + have hlen : (gen.paramsTel ++ gen.idxTel family).length = + (gen.idxTel family).length + source.nparams := by + simp only [List.length_append, BlockGenerationChecked.paramsTel, + BlockGenerationChecked.idxTel, List.length_map] + rw [S.generationParams_length] + omega + rw [VExpr.bvarRevRange_congr' 0 hlen, + ← VExpr.bvarRevRange_append] at happ + have hresult := (S.familyWF family hfamily).familyResult.instL + (U' := gen.recUvars) gen.sourceLevels_wf + simp only [List.map_reverse] at hresult + have hctxChecked := ((S.emittedFamilyTel hfamily).instL + (U' := gen.recUvars) gen.sourceLevels_wf).ctx + simp only [List.map_nil, List.append_nil] at hctxChecked + have hresultChecked := hresult.defeqDFC S.ord hctxChecked + have hctxGeneration := ((S.generationFamilyTel hfamily).instL + (U' := gen.recUvars) gen.sourceLevels_wf).ctx + simp only [List.map_nil, List.append_nil] at hctxGeneration + have hresultGeneration := hresultChecked.defeqDFC S.ord + (hctxGeneration.symm S.ord) + have hresult' : env.IsDefEq gen.recUvars + ((gen.idxTel family).reverse ++ gen.paramsTel.reverse) + ((family.rawResult source.nparams).instL ls) + (.sort (gen.validated.resultLevel.inst ls)) + (.sort (.succ (gen.validated.resultLevel.inst ls))) := by + simpa [ls, BlockGenerationChecked.paramsTel, + BlockGenerationChecked.idxTel, List.map_reverse, VLevel.inst] using + hresultGeneration + exact hresult'.defeq (by + simpa [List.reverse_append] using happ) + +theorem motive_isType {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.IsType gen.recUvars gen.paramsTel.reverse + (gen.motiveType family) := by + have htel₀ := (S.generationFamily_onTel hfamily).instL + (U' := gen.recUvars) gen.sourceLevels_wf + have htel : env.OnTel gen.recUvars [] + (gen.paramsTel ++ gen.idxTel family) := by + simpa [BlockGenerationChecked.paramsTel, + BlockGenerationChecked.idxTel] using htel₀ + have hidx : env.OnTel gen.recUvars gen.paramsTel.reverse + (gen.idxTel family) := by + simpa using htel.of_append.2 + refine IsType.forallN hidx ?_ + exact ⟨_, by + simpa [BlockGenerationChecked.motiveType] using + HasType.forallE (S.familyApp_hasType hfamily) + (HasType.sort gen.motiveLevel_wf)⟩ + +end BlockGenerationEnv + +/-- Exact decomposition of the stored raw family type. -/ +theorem NormalizedChecked.rawType_eq {source : VInductDecl} + (block : NormalizedChecked source) : + block.sourceType.type = + VExpr.forallN block.rawParams + (VExpr.forallN block.rawIndices block.rawResult) := by + conv => lhs + rw [← VExpr.forallN_telN_dropN source.nparams + block.sourceType.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams block.sourceType.type)] + rfl + +/-- Exact decomposition of a stored raw constructor type into its declared +parameter/field telescope and terminal result. -/ +theorem NormalizedCtor.rawType_eq {source : VInductDecl} + (ctor : NormalizedCtor) : + ctor.raw.type = + VExpr.forallN (ctor.declaredBinders source.nparams) + (ctor.rawResult source.nparams) := by + conv => lhs + rw [← VExpr.forallN_telN_dropN source.nparams + ctor.raw.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN source.nparams ctor.raw.type)] + rw [NormalizedCtor.declaredBinders, NormalizedCtor.rawFields, + NormalizedCtor.rawResult, ← VExpr.forallN_append] + +namespace GenerationEnv + +variable {source : VInductDecl} {gen : GenerationChecked source} + {env : VEnv} (S : GenerationEnv gen env) +include S +-- `S` is included throughout so every lemma below is reachable as `S.lemma`, +-- including those whose statement and proof never mention it. +set_option linter.unusedSectionVars false + +/-- The final mixed-generation invariant is monotone once the larger +environment is known to remain ordered. -/ +theorem mono {env' : VEnv} (henv : env ≤ env') (ord : env'.Ordered) : + GenerationEnv gen env' where + ord := ord + checked := S.checked.mono henv + familyTel := S.familyTel.mono henv + familyResult := S.familyResult.mono henv + ctorWF := fun ctor hctor => (S.ctorWF ctor hctor).mono henv + familyConst := henv.constants S.familyConst + ctorConst := fun ctor hctor => henv.constants (S.ctorConst ctor hctor) + +/-- The checked result universe is well formed at the source declaration's +universe arity. -/ +theorem resultLevel_WF : + gen.block.checked.resultLevel.WF source.uvars := by + rw [gen.block.uvars_eq] + exact gen.block.checked.direct_anatomy.2.2.1 + +theorem rawFamily_onTel : + env.OnTel source.uvars [] + (gen.block.rawParams ++ gen.block.rawIndices) := + S.familyTel.raw_onTel + +/-- The family parameter prefix is structurally definitionally equal to the +checked locals retained by validation. -/ +theorem rawParams_defeq : + env.TelDefEq source.uvars [] gen.block.rawParams + gen.block.checked.params := by + have h := S.familyTel.take source.nparams + have hraw : + (gen.block.rawParams ++ gen.block.rawIndices).take source.nparams = + gen.block.rawParams := by + rw [← gen.shape.1, List.take_append, List.take_length] + simp + have hviewLen : gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hview : + (gen.block.checked.params ++ gen.block.checked.indices).take + source.nparams = gen.block.checked.params := by + rw [← hviewLen, List.take_append, List.take_length] + simp + rw [hraw, hview] at h + exact h + +/-- Raw and checked parameter contexts denote the same local telescope. -/ +theorem rawParams_ctx : + env.IsDefEqCtx source.uvars [] gen.block.rawParams.reverse + gen.block.checked.params.reverse := + by simpa using S.rawParams_defeq.ctx + +/-- The exact parameter surface emitted in recursor metadata remains +definitionally equal to the analyzer-owned parameters. -/ +theorem generationParams_defeq : + env.TelDefEq source.uvars [] gen.block.generationParams + gen.block.checked.params := by + exact S.rawParams_defeq.generationParams S.ord + +theorem generationParams_ctx : + env.IsDefEqCtx source.uvars [] gen.block.generationParams.reverse + gen.block.checked.params.reverse := + by simpa using S.generationParams_defeq.ctx + +theorem generationParams_length : + gen.block.generationParams.length = source.nparams := by + have hrawView := S.rawParams_defeq.length_eq + exact (VInductDecl.generationParams_length_of_eq hrawView).trans + gen.shape.1 + +theorem generationParams_ctx_rec : + env.IsDefEqCtx (gen.recUvars) [] gen.paramsTel.reverse + (gen.block.checked.params.map + (VExpr.instL (gen.sourceLevels))).reverse := by + have h := S.generationParams_defeq.instL + (U' := gen.recUvars) gen.sourceLevels_wf + simpa [GenerationChecked.paramsTel, List.map_reverse] using h.ctx + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.generationParams_defeq [propext, Quot.sound] + +/-- Stored constructor fields are well formed over the exact generated +parameter surface after universe transport. -/ +theorem generationFields_onTel_rec {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.OnTel (gen.recUvars) gen.paramsTel.reverse + (ctor.fieldsR source.uvars source.nparams gen.elimination) := by + have hemitted := (S.ctorWF ctor hctor).rawEmitted_onTel + have hfields₀ := (OnTel.of_append + (As := gen.block.checked.params) hemitted).2 + have hfields₁ := hfields₀.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hfieldsChecked : env.OnTel (gen.recUvars) + (gen.block.checked.params.map + (VExpr.instL (gen.sourceLevels))).reverse + (ctor.fieldsR source.uvars source.nparams gen.elimination) := by + simpa [NormalizedCtor.fieldsR, List.map_reverse] using hfields₁ + exact hfieldsChecked.defeqDFC S.ord + (S.generationParams_ctx_rec.symm S.ord) + +theorem generationFieldPrefix_ctx_rec {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) (j : Nat) : + env.IsDefEqCtx (gen.recUvars) [] + ((ctor.fieldsR source.uvars source.nparams gen.elimination |>.take j).reverse ++ + gen.paramsTel.reverse) + ((ctor.fieldsR source.uvars source.nparams gen.elimination |>.take j).reverse ++ + (gen.block.checked.params.map + (VExpr.instL (gen.sourceLevels))).reverse) := by + have hfields := S.generationFields_onTel_rec hctor + rw [← List.take_append_drop j + (ctor.fieldsR source.uvars source.nparams gen.elimination)] at hfields + exact (hfields.of_append.1).extendDefEqCtx + S.generationParams_ctx_rec + +/-- The family telescope used by generated artifacts keeps raw index syntax +but uses the checked parameter prefix consumed by validation. -/ +theorem emittedFamilyTel : + env.TelDefEq source.uvars [] + (gen.block.rawParams ++ gen.block.rawIndices) + (gen.block.checked.params ++ gen.block.rawIndices) := by + have hindices : env.OnTel source.uvars gen.block.rawParams.reverse + gen.block.rawIndices := by + simpa using S.rawFamily_onTel.of_append.2 + exact S.rawParams_defeq.append_refl (by simpa using hindices) + +/-- The emitted mixed family telescope is well formed. -/ +theorem emittedFamily_onTel : + env.OnTel source.uvars [] + (gen.block.checked.params ++ gen.block.rawIndices) := + S.emittedFamilyTel.view_onTel S.ord + +/-- Replace the checked parameter prefix by the kernel-observable generation +surface while leaving the stored raw index telescope unchanged. -/ +theorem generationFamilyTel : + env.TelDefEq source.uvars [] + (gen.block.generationParams ++ gen.block.rawIndices) + (gen.block.checked.params ++ gen.block.rawIndices) := by + have hindicesChecked : env.OnTel source.uvars + gen.block.checked.params.reverse gen.block.rawIndices := by + simpa using S.emittedFamily_onTel.of_append.2 + have hindicesGeneration : env.OnTel source.uvars + gen.block.generationParams.reverse gen.block.rawIndices := + hindicesChecked.defeqDFC S.ord + (S.generationParams_ctx.symm S.ord) + exact S.generationParams_defeq.append_refl + (by simpa using hindicesGeneration) + +theorem generationFamily_onTel : + env.OnTel source.uvars [] + (gen.block.generationParams ++ gen.block.rawIndices) := + S.generationFamilyTel.raw_onTel + +theorem generationFamily_ctx : + env.IsDefEqCtx source.uvars [] + (gen.block.generationParams ++ gen.block.rawIndices).reverse + (gen.block.checked.params ++ gen.block.rawIndices).reverse := + by simpa using S.generationFamilyTel.ctx + +/-- Completed raw and emitted family contexts are definitionally equal. -/ +theorem emittedFamily_ctx : + env.IsDefEqCtx source.uvars [] + (gen.block.rawParams ++ gen.block.rawIndices).reverse + (gen.block.checked.params ++ gen.block.rawIndices).reverse := + by simpa using S.emittedFamilyTel.ctx + +theorem rawFamily_isType : + env.IsType source.uvars [] gen.block.sourceType.type := by + rw [gen.block.rawType_eq, ← VExpr.forallN_append] + have hresult₀ : env.IsType source.uvars + (gen.block.rawParams ++ gen.block.rawIndices).reverse + gen.block.rawResult := + ⟨_, S.familyResult.hasType.1⟩ + have hresult : env.IsType source.uvars + ((gen.block.rawParams ++ gen.block.rawIndices).reverse ++ []) + gen.block.rawResult := by + simpa using hresult₀ + exact IsType.forallN S.rawFamily_onTel hresult + +theorem rawCtor_isType {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.IsType source.uvars [] ctor.raw.type := + (S.ctorWF ctor hctor).rawDeclared_isType + +/-- The raw family constant at declaration universes, in any context. -/ +theorem familyConst_decl {Γ : List VExpr} : + env.HasType source.uvars Γ + (.const gen.block.sourceType.name (VLevel.params source.uvars)) + gen.block.sourceType.type := by + have hwf : gen.block.sourceType.toVConstant.WF env := by + show env.IsType gen.block.sourceType.uvars [] + gen.block.sourceType.type + rw [gen.block.sourceType_uvars_eq] + exact S.rawFamily_isType + have h := HasType.const0 S.familyConst hwf + rw [gen.block.sourceType_uvars_eq] at h + exact h.weak0 S.ord + +/-- A stored raw constructor constant at declaration universes, in any +context. -/ +theorem ctorConst_decl {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {Γ : List VExpr} : + env.HasType source.uvars Γ + (.const ctor.raw.name (VLevel.params source.uvars)) + ctor.raw.type := by + have hwf : ctor.raw.toVConstant.WF env := by + show env.IsType ctor.raw.uvars [] ctor.raw.type + rw [gen.ctor_uvars_eq hctor] + exact S.rawCtor_isType hctor + have h := HasType.const0 (S.ctorConst ctor hctor) hwf + rw [gen.ctor_uvars_eq hctor] at h + exact h.weak0 S.ord + +/-- The stored constructor constant applied to the checked-parameter/raw-field +self-spine emitted by mixed artifacts. The constructor's declared parameter +prefix need only be definitionally equal to this checked family prefix. -/ +theorem ctorApp_emitted_decl {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.HasType source.uvars + ((ctor.rawFields source.nparams).reverse ++ + gen.block.checked.params.reverse) + (VExpr.appN + (.const ctor.raw.name (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (ctor.rawFields source.nparams).length source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.rawFields source.nparams).length)) + (ctor.resultTarget gen.block) := by + let E := ctor.emittedBinders gen.block + let V := ctor.viewBinders gen.block + have hc : env.HasType source.uvars [] + (.const ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN (ctor.declaredBinders source.nparams) + (ctor.rawResult source.nparams)) := by + rw [← ctor.rawType_eq] + exact S.ctorConst_decl hctor + obtain ⟨_, hdecl⟩ := + (S.ctorWF ctor hctor).declaredTel.forallN_defeq + (by + simpa using (S.ctorWF ctor hctor).declaredResult) + have hview : env.HasType source.uvars [] + (.const ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN V (ctor.resultTarget gen.block)) := by + simpa [V] using hdecl.defeq hc + have hresult : env.HasType source.uvars E.reverse + (ctor.resultTarget gen.block) + (.sort gen.block.checked.resultLevel) := by + simpa [E] using + (S.ctorWF ctor hctor).emittedResult.hasType.2 + obtain ⟨_, hemit⟩ := + (S.ctorWF ctor hctor).emittedTel.forallN_defeq + (by simpa [E, VEnv.HasType] using hresult) + have hcE₀ : env.HasType source.uvars [] + (.const ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN E (ctor.resultTarget gen.block)) := by + exact hemit.defeq' (by simpa [V] using hview) + have hclosed : + (VExpr.forallN E (ctor.resultTarget gen.block)).ClosedN 0 := + (hcE₀.closedN' S.ord.closed trivial).2.2 + have hcE : env.HasType source.uvars E.reverse + (.const ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN E (ctor.resultTarget gen.block)) := + hcE₀.weak0 S.ord + have happ := HasType.appN_selfSpine' + (As := E) (B := ctor.resultTarget gen.block) + (Δ := []) (Γ := []) hclosed (by simpa using hcE) + simp only [List.length_nil, VExpr.liftN_zero, + List.nil_append, List.append_nil] at happ + have hEctx : + E.reverse = + (ctor.rawFields source.nparams).reverse ++ + gen.block.checked.params.reverse := by + simp [E, NormalizedCtor.emittedBinders, + List.reverse_append] + have hElen : + E.length = + (ctor.rawFields source.nparams).length + + source.nparams := by + have hp : gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + simp [E, NormalizedCtor.emittedBinders, hp] + omega + rw [hEctx, hElen, + ← VExpr.bvarRevRange_append source.nparams + (ctor.rawFields source.nparams).length] at happ + exact happ + +/-- The raw family constant instantiated into recursor universes. -/ +theorem familyConst_rec {Γ : List VExpr} : + env.HasType (gen.recUvars) Γ + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (gen.block.sourceType.type.instL + (gen.sourceLevels)) := by + have h := (S.familyConst_decl (Γ := [])).instL + (U' := gen.recUvars) gen.sourceLevels_wf + rw [show + (VExpr.const gen.block.sourceType.name + (VLevel.params source.uvars)).instL + (gen.sourceLevels) = + .const gen.block.sourceType.name + (gen.sourceLevels) by + simp [VExpr.instL, VLevel.params_map_inst_params']] at h + exact h.weak0 S.ord + +/-- The raw family type decomposed in recursor universes. -/ +theorem rawType_rec_eq : + gen.block.sourceType.type.instL (gen.sourceLevels) = + VExpr.forallN + (gen.block.rawParams.map + (VExpr.instL (gen.sourceLevels))) + (VExpr.forallN gen.idxTel + (gen.block.rawResult.instL + (gen.sourceLevels))) := by + rw [gen.block.rawType_eq, VExpr.instL_forallN, + VExpr.instL_forallN] + rfl + +/-- The family constant may be viewed through the checked-parameter/raw-index +telescope emitted by generated artifacts. -/ +theorem familyConst_emitted_decl : + env.HasType source.uvars [] + (.const gen.block.sourceType.name (VLevel.params source.uvars)) + (VExpr.forallN + (gen.block.checked.params ++ gen.block.rawIndices) + gen.block.rawResult) := by + have hc : env.HasType source.uvars [] + (.const gen.block.sourceType.name (VLevel.params source.uvars)) + (VExpr.forallN + (gen.block.rawParams ++ gen.block.rawIndices) + gen.block.rawResult) := by + rw [VExpr.forallN_append, ← gen.block.rawType_eq] + exact S.familyConst_decl + obtain ⟨_, htel⟩ := S.emittedFamilyTel.forallN_defeq + (by simpa [VEnv.HasType] using S.familyResult.hasType.1) + exact htel.defeq hc + +/-- The family constant viewed through the exact parameter syntax retained +by generated kernel metadata. -/ +theorem familyConst_generation_decl : + env.HasType source.uvars [] + (.const gen.block.sourceType.name (VLevel.params source.uvars)) + (VExpr.forallN + (gen.block.generationParams ++ gen.block.rawIndices) + gen.block.rawResult) := by + have hresultChecked := S.familyResult.defeqDFC S.ord + S.emittedFamily_ctx + have hresultGeneration := hresultChecked.defeqDFC S.ord + (S.generationFamily_ctx.symm S.ord) + obtain ⟨_, htel⟩ := S.generationFamilyTel.forallN_defeq + (by simpa [VEnv.HasType] using hresultGeneration.hasType.1) + exact htel.defeq' S.familyConst_emitted_decl + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.familyConst_generation_decl [propext, Quot.sound] + +/-- The family applied to its checked-parameter/raw-index self-spine has the +normalized result sort. -/ +theorem familyApp_hasType : + env.HasType (gen.recUvars) + (gen.idxTel.reverse ++ gen.paramsTel.reverse) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange gen.idxTel.length source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort + (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + let ls := gen.sourceLevels + have hconst₀ := S.familyConst_generation_decl.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hconst₁ : env.HasType (gen.recUvars) [] + (.const gen.block.sourceType.name ls) + (VExpr.forallN (gen.paramsTel ++ gen.idxTel) + (gen.block.rawResult.instL ls)) := by + simpa [ls, GenerationChecked.paramsTel, + GenerationChecked.idxTel, VExpr.instL_forallN, + VExpr.instL, VLevel.params_map_inst_params'] using hconst₀ + have hcanonicalClosed : + (VExpr.forallN (gen.paramsTel ++ gen.idxTel) + (gen.block.rawResult.instL ls)).ClosedN 0 := by + exact (hconst₁.closedN' S.ord.closed trivial).2.2 + have hconst : env.HasType (gen.recUvars) + ((gen.paramsTel ++ gen.idxTel).reverse) + (.const gen.block.sourceType.name ls) + (VExpr.forallN (gen.paramsTel ++ gen.idxTel) + (gen.block.rawResult.instL ls)) := + hconst₁.weak0 S.ord + have happ := HasType.appN_selfSpine' + (Δ := []) (Γ := []) hcanonicalClosed (by + simpa using hconst) + simp only [List.length_nil, VExpr.liftN_zero, List.nil_append, + List.append_nil] at happ + have hlen : + (gen.paramsTel ++ gen.idxTel).length = + gen.idxTel.length + source.nparams := by + simp only [List.length_append, GenerationChecked.paramsTel, + GenerationChecked.idxTel, List.length_map] + rw [S.generationParams_length] + omega + rw [VExpr.bvarRevRange_congr' 0 hlen, + ← VExpr.bvarRevRange_append] at happ + have hresult := S.familyResult.instL + (U' := gen.recUvars) gen.sourceLevels_wf + simp only [List.map_reverse] at hresult + have hctxChecked := (S.emittedFamilyTel.instL + (U' := gen.recUvars) gen.sourceLevels_wf).ctx + simp only [List.map_nil, List.append_nil] at hctxChecked + have hresultChecked := hresult.defeqDFC S.ord hctxChecked + have hctxGeneration := (S.generationFamilyTel.instL + (U' := gen.recUvars) gen.sourceLevels_wf).ctx + simp only [List.map_nil, List.append_nil] at hctxGeneration + have hresultGeneration := hresultChecked.defeqDFC S.ord + (hctxGeneration.symm S.ord) + have hresult' : env.IsDefEq (gen.recUvars) + (gen.idxTel.reverse ++ gen.paramsTel.reverse) + (gen.block.rawResult.instL ls) + (.sort (gen.block.checked.resultLevel.inst ls)) + (.sort (.succ (gen.block.checked.resultLevel.inst ls))) := by + simpa [ls, GenerationChecked.paramsTel, GenerationChecked.idxTel, + List.map_reverse, VLevel.inst] using hresultGeneration + exact hresult'.defeq (by + simpa [List.reverse_append] using happ) + +/-- The mixed motive is a well-formed type over the checked parameter +context. -/ +theorem motive_isType : + env.IsType (gen.recUvars) gen.paramsTel.reverse + gen.motiveType := by + have htel₀ := S.generationFamily_onTel.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have htel : + env.OnTel (gen.recUvars) [] + (gen.paramsTel ++ gen.idxTel) := by + simpa [GenerationChecked.paramsTel, GenerationChecked.idxTel] using htel₀ + have hidx : env.OnTel (gen.recUvars) gen.paramsTel.reverse + gen.idxTel := by + simpa using htel.of_append.2 + refine IsType.forallN hidx ?_ + exact ⟨_, by + simpa [GenerationChecked.motiveType] using + HasType.forallE S.familyApp_hasType + (HasType.sort gen.motiveLevel_wf)⟩ + +end GenerationEnv + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.motive_isType [propext, Quot.sound] + +theorem BlockGenerationChecked.motiveTypesAux_length + {source : VInductDecl} (gen : BlockGenerationChecked source) : + ∀ (families : List NormalizedFamily) (i : Nat), + (gen.motiveTypesAux families i).length = families.length + | [], _ => rfl + | _ :: families, i => by + simp only [BlockGenerationChecked.motiveTypesAux, List.length_cons] + rw [gen.motiveTypesAux_length families (i + 1)] + +theorem BlockGenerationChecked.motiveTypes_length + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.motiveTypes.length = gen.familyCount := by + unfold BlockGenerationChecked.motiveTypes + exact gen.motiveTypesAux_length gen.families 0 + +/-- Pairing arbitrary stored families with a dependent checked-family spine +does not change the checked ordinal at any surviving position. -/ +theorem CheckedFamilies.pairNormalizedFamilies_getElem?_ordinal + {source : VInductDecl} {params : List VExpr} + {ordinal : Nat} {types : List VInductiveType} + (families : CheckedFamilies source params ordinal types) : + ∀ {raws i family}, + (pairNormalizedFamilies raws families.data)[i]? = some family → + family.view.ordinal = ordinal + i := by + induction families with + | nil => + intro raws i family h + simp [CheckedFamilies.data, pairNormalizedFamilies] at h + | @cons ordinal type types head tail ih => + intro raws i family h + cases raws with + | nil => simp [pairNormalizedFamilies] at h + | cons raw raws => + cases i with + | zero => + simp only [CheckedFamilies.data, pairNormalizedFamilies, + List.getElem?_cons_zero] at h + injection h with hfamily + subst family + rfl + | succ i => + simp only [CheckedFamilies.data, pairNormalizedFamilies, + List.getElem?_cons_succ] at h + have hord := ih h + omega + +/-- Every retained family is found at its checked source ordinal. -/ +theorem BlockGenerationChecked.family_getElem?_ordinal + {source : VInductDecl} (gen : BlockGenerationChecked source) + {family : NormalizedFamily} (hfamily : family ∈ gen.families) : + gen.families[family.view.ordinal]? = some family := by + obtain ⟨i, hi⟩ := List.mem_iff_getElem?.1 hfamily + have hi' : + (pairNormalizedFamilies source.types + gen.block.checked.families.data)[i]? = some family := by + simpa [BlockGenerationChecked.families, + NormalizedCheckedBlock.familyPairs] using hi + have hord := + CheckedFamilies.pairNormalizedFamilies_getElem?_ordinal + gen.block.checked.families hi' + have hord' : family.view.ordinal = i := by + simpa using hord + rwa [hord'] + +theorem BlockGenerationChecked.family_ordinal_lt + {source : VInductDecl} (gen : BlockGenerationChecked source) + {family : NormalizedFamily} (hfamily : family ∈ gen.families) : + family.view.ordinal < gen.familyCount := by + obtain ⟨h, -⟩ := List.getElem?_eq_some_iff.1 + (gen.family_getElem?_ordinal hfamily) + exact h + +/-- Selecting a retained family by its checked ordinal recovers its exact +raw constant name. -/ +@[simp] theorem BlockGenerationChecked.familyNameAt_ordinal + {source : VInductDecl} (gen : BlockGenerationChecked source) + {family : NormalizedFamily} (hfamily : family ∈ gen.families) : + gen.familyNameAt family.view.ordinal = family.raw.name := by + simp [BlockGenerationChecked.familyNameAt, + gen.family_getElem?_ordinal hfamily] + +/-- Positional lookup through the progressively weakened mutual motive +telescope. -/ +theorem BlockGenerationChecked.motiveTypesAux_getElem? + {source : VInductDecl} (gen : BlockGenerationChecked source) : + ∀ (families : List NormalizedFamily) (i q : Nat), + (gen.motiveTypesAux families i)[q]? = + families[q]?.map fun family => + (gen.motiveType family).liftN (i + q) + | [], _, q => by simp [BlockGenerationChecked.motiveTypesAux] + | _ :: _, _, 0 => by simp [BlockGenerationChecked.motiveTypesAux] + | _ :: families, i, q + 1 => by + simp only [BlockGenerationChecked.motiveTypesAux, + List.getElem?_cons_succ] + rw [gen.motiveTypesAux_getElem? families (i + 1) q, + show i + 1 + q = i + (q + 1) by omega] + +theorem BlockGenerationChecked.motiveTypes_getElem?_ordinal + {source : VInductDecl} (gen : BlockGenerationChecked source) + {family : NormalizedFamily} (hfamily : family ∈ gen.families) : + gen.motiveTypes[family.view.ordinal]? = + some ((gen.motiveType family).liftN family.view.ordinal) := by + rw [show gen.motiveTypes = gen.motiveTypesAux gen.families 0 from rfl, + gen.motiveTypesAux_getElem?] + rw [gen.family_getElem?_ordinal hfamily] + simp + +/-- Paired block constructors retain the raw/view field arity certified by +normalization. -/ +theorem BlockGenerationChecked.flatCtor_fields_length + {source : VInductDecl} (gen : BlockGenerationChecked source) + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + (constructor.ctor.rawFields source.nparams).length = + constructor.ctor.view.fields.length := by + simp only [BlockGenerationChecked.flatCtors, + NormalizedCheckedBlock.flatCtors, List.mem_flatMap] at hconstructor + obtain ⟨family, hfamily, hconstructor⟩ := hconstructor + simp only [NormalizedFamily.blockCtors, List.mem_map] at hconstructor + obtain ⟨ctor, hctor, rfl⟩ := hconstructor + exact ((gen.shape.2.2.2.2 family hfamily).2.2.2.2.2.2 + ctor hctor).2.2.2 + +/-- Syntactic lifting law for any member of the mutual motive telescope. -/ +theorem BlockGenerationChecked.motiveType_liftN + {source : VInductDecl} (gen : BlockGenerationChecked source) + (family : NormalizedFamily) (n : Nat) : + (gen.motiveType family).liftN n = + VExpr.forallN (VExpr.liftTelN n (gen.idxTel family) 0) + (.forallE + (VExpr.appN + (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (n + (gen.idxTel family).length) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.sort gen.motiveLevel)) := by + rw [show gen.motiveType family = + VExpr.forallN (gen.idxTel family) + (.forallE + (VExpr.appN + (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (gen.idxTel family).length source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.sort gen.motiveLevel)) from rfl, + VExpr.liftN_forallN] + refine congrArg _ ?_ + show VExpr.forallE _ _ = VExpr.forallE _ _ + refine congr (congrArg _ ?_) rfl + rw [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + rfl + +/-- Apply a selected mutual motive variable to its target-family indices and +a typed major premise. -/ +theorem BlockGenerationChecked.motiveVarApp_hasType + {source : VInductDecl} (gen : BlockGenerationChecked source) + (family : NormalizedFamily) {env : VEnv} {l : VLevel} + {Γ : List VExpr} {K q : Nat} {idxs : List VExpr} {a : VExpr} + (hM : env.HasType gen.recUvars Γ (.bvar K) + ((gen.motiveType family).liftN (q + K + 1))) + (hidx : env.SpineWF gen.recUvars Γ + (VExpr.forallN + (VExpr.liftTelN (q + K + 1) (gen.idxTel family) 0) + (.sort l)) + idxs (.sort l)) + (hlen : idxs.length = (gen.idxTel family).length) + (ha : env.HasType gen.recUvars Γ a + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (q + K + 1) source.nparams ++ idxs))) : + env.HasType gen.recUvars Γ + (VExpr.appN (.bvar K) (idxs ++ [a])) + (.sort gen.motiveLevel) := by + rw [gen.motiveType_liftN family] at hM + have hshape := hidx.retarget + (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (q + K + 1 + (gen.idxTel family).length) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.sort gen.motiveLevel)) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ + (C := .const family.raw.name gen.sourceLevels) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by rw [hlen]; omega), + show q + K + 1 + (gen.idxTel family).length - idxs.length = + q + K + 1 from by rw [hlen]; omega, + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hApp := hshape.hasType_appN hM + rw [VExpr.appN_append] + exact HasType.app hApp (by simpa using ha) + +/-- A recursive raw field, after inserting the full mutual motive telescope +and the constructor-local binders, is the family application expected by its +generated induction hypothesis. -/ +theorem blockMinor_fieldType_of_eq + {source : VInductDecl} {familyName : Name} + {B : VExpr} {r₀ : RecArg} + (hB : B = VExpr.forallN r₀.binders + (VExpr.appN (.const familyName (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (r₀.fieldIndex + r₀.binders.length) source.nparams ++ + r₀.indices))) + (d m p : Nat) (hj : r₀.fieldIndex < m) + (mode : ElimMode := .large) : + let ls := mode.sourceLevels source.uvars + let r := r₀.instL ls + ((B.instL ls).liftN d r.fieldIndex).liftN + (m - r.fieldIndex + p) = + VExpr.forallN + (BlockGenerationChecked.blockMinorBinders d m p r) + (VExpr.appN (.const familyName ls) + (VExpr.bvarRevRange + (m + p + r.binders.length + d) source.nparams ++ + r.indices.map fun e => + (e.liftN d (r.fieldIndex + r.binders.length)).liftN + (m - r.fieldIndex + p) r.binders.length)) := by + dsimp only + conv => lhs; rw [hB] + simp only [RecArg.instL, VExpr.instL_forallN, VExpr.instL_appN, + List.map_append, bvarRevRange_instL, + show (VExpr.const familyName (VLevel.params source.uvars)).instL + (mode.sourceLevels source.uvars) = + .const familyName (mode.sourceLevels source.uvars) from by + simp [VExpr.instL, ElimMode.sourceLevels, + VLevel.params_map_inst_params'], + VExpr.liftN_forallN, VExpr.liftN_appN] + simp only [List.length_map, VExpr.liftTelN_length, Nat.zero_add] + rw [bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + bvarRevRange_liftN_ge _ _ _ _ (by omega), + show m - r₀.fieldIndex + p + + (d + (r₀.fieldIndex + r₀.binders.length)) = + m + p + r₀.binders.length + d from by omega] + simp only [List.map_map, + BlockGenerationChecked.blockMinorBinders] + apply congrArg (VExpr.forallN _) + apply congrArg (VExpr.appN + (.const familyName (mode.sourceLevels source.uvars))) + apply congrArg + (VExpr.bvarRevRange (m + p + r₀.binders.length + d) + source.nparams ++ ·) + apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + +/-- Raw mixed fields preserve their arity under recursor-universe +instantiation. -/ +theorem NormalizedCtor.fieldsR_length {source : VInductDecl} + (ctor : NormalizedCtor) {mode : ElimMode} : + (ctor.fieldsR source.uvars source.nparams mode).length = + (ctor.rawFields source.nparams).length := + List.length_map .. + +/-- Pointwise lookup through the raw mixed field universe transport. -/ +theorem NormalizedCtor.fieldsR_getElem? {source : VInductDecl} + {ctor : NormalizedCtor} {q : Nat} {mode : ElimMode} : + (ctor.fieldsR source.uvars source.nparams mode)[q]? = + (ctor.rawFields source.nparams)[q]?.map + (VExpr.instL (mode.sourceLevels source.uvars)) := + List.getElem?_map .. + +/-- Unpack one mixed recursive descriptor to the retained declaration-level +descriptor from the checked view. -/ +theorem NormalizedCtor.recArgsR_mem {source : VInductDecl} + {ctor : NormalizedCtor} {r : RecArg} {mode : ElimMode} + (hr : r ∈ ctor.recArgsR source.uvars mode) : + ∃ r₀, r₀ ∈ ctor.view.recursive ∧ + r = r₀.instL (mode.sourceLevels source.uvars) := by + obtain ⟨r₀, hr₀, rfl⟩ := List.mem_map.1 hr + exact ⟨r₀, hr₀, rfl⟩ + +theorem liftTelN_congr {a a' : Nat} (tel : List VExpr) (k : Nat) + (h : a = a') : + VExpr.liftTelN a tel k = VExpr.liftTelN a' tel k := h ▸ rfl + +theorem BlockGenerationChecked.blockIHsFromRecArgs_length (d m : Nat) : + ∀ (rs : List RecArg) (p : Nat), + (BlockGenerationChecked.blockIHsFromRecArgs d m rs p).length = rs.length + | [], _ => rfl + | _ :: rs, p => by + simp [BlockGenerationChecked.blockIHsFromRecArgs, + BlockGenerationChecked.blockIHsFromRecArgs_length d m rs (p + 1)] + +/-- Rule-context normal form of one mutual induction hypothesis. The +recursive result is routed to the motive selected by `targetType`. -/ +def BlockGenerationChecked.blockRuleIH + (d k m : Nat) (r : RecArg) : VExpr := + let n := r.binders.length + VExpr.forallN + (BlockGenerationChecked.blockRuleBinders (d+k) m r) + (VExpr.appN + (.bvar (d - 1 - r.targetType + k + m + n)) + ((r.indices.map fun e => + (e.liftN (d+k) (r.fieldIndex+n)).liftN + (m-r.fieldIndex) n) ++ + [VExpr.appN (.bvar (m-1-r.fieldIndex+n)) + (VExpr.bvarRevRange 0 n)])) + +/-- Rule-context induction hypotheses, weakened past their preceding +hypothesis binders. -/ +def BlockGenerationChecked.blockRuleIHs (d k m : Nat) : + List RecArg → Nat → List VExpr + | [], _ => [] + | r :: rs, p => + (BlockGenerationChecked.blockRuleIH d k m r).liftN p :: + BlockGenerationChecked.blockRuleIHs d k m rs (p+1) + +theorem BlockGenerationChecked.blockMinorBinders_shift + (d : Nat) (r : RecArg) (m p : Nat) : + BlockGenerationChecked.blockMinorBinders d m p r = + VExpr.liftTelN p + (BlockGenerationChecked.blockMinorBinders d m 0 r) 0 := by + simp only [BlockGenerationChecked.blockMinorBinders, Nat.add_zero] + rw [VExpr.liftTelN_liftTelN] + +/-- The shift parameter of a mutual minor IH is precisely weakening past +the preceding IH binders. -/ +theorem BlockGenerationChecked.blockMinorIH_shift + (d : Nat) (r : RecArg) (m p : Nat) (hj : r.fieldIndex < m) : + BlockGenerationChecked.blockMinorIH d m p r = + (BlockGenerationChecked.blockMinorIH d m 0 r).liftN p := by + simp only [BlockGenerationChecked.blockMinorIH, + VExpr.liftN_forallN] + rw [← BlockGenerationChecked.blockMinorBinders_shift d r m p] + rw [show + (BlockGenerationChecked.blockMinorBinders d m 0 r).length = + r.binders.length by + simp [BlockGenerationChecked.blockMinorBinders, + VExpr.liftTelN_length], + Nat.zero_add] + apply congrArg (VExpr.forallN _) + rw [VExpr.liftN_appN, List.map_append, List.map_map] + show VExpr.appN _ (_ ++ [_]) = VExpr.appN _ (_ ++ [_]) + congr 1 + · rw [show + (VExpr.bvar + (d - 1 - r.targetType + m + 0 + r.binders.length)).liftN + p r.binders.length = + .bvar (d - 1 - r.targetType + m + p + r.binders.length) from by + simp only [VExpr.liftN] + rw [liftVar_le (by omega)] + congr 1 + ac_rfl] + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply, Nat.add_zero] + rw [VExpr.liftN'_liftN_hi] + · congr 1 + simp only [Nat.add_zero, VExpr.liftN_appN] + rw [show + (VExpr.bvar + (m - 1 - r.fieldIndex + r.binders.length)).liftN + p r.binders.length = + .bvar (m - 1 - r.fieldIndex + p + r.binders.length) from by + simp only [VExpr.liftN] + rw [liftVar_le (by omega)] + congr 1 + omega, + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + +/-- Lifting a base mutual minor IH through all constructor minors yields the +rule-context normal form. -/ +theorem BlockGenerationChecked.blockMinorIH_zero_lift_ruleIH + (d : Nat) (r : RecArg) (m k : Nat) (hj : r.fieldIndex < m) : + (BlockGenerationChecked.blockMinorIH d m 0 r).liftN k m = + BlockGenerationChecked.blockRuleIH d k m r := by + simp only [BlockGenerationChecked.blockMinorIH, + BlockGenerationChecked.blockRuleIH, + BlockGenerationChecked.blockMinorBinders, + BlockGenerationChecked.blockRuleBinders, + VExpr.liftN_forallN, VExpr.liftTelN_length, Nat.add_zero] + congr 1 + · rw [show m = r.fieldIndex + (m-r.fieldIndex) by omega] + rw [show r.fieldIndex + (m-r.fieldIndex) - r.fieldIndex = + m-r.fieldIndex by omega] + rw [VExpr.liftTelN_liftN_midN r.binders d k + (m-r.fieldIndex) (Nat.zero_le _)] + · congr 1 + rw [VExpr.liftN_appN, List.map_append, List.map_map] + show VExpr.appN _ (_ ++ [_]) = VExpr.appN _ (_ ++ [_]) + congr 1 + · simp only [VExpr.liftN] + rw [liftVar_le (by omega)] + congr 1 + ac_rfl + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + rw [show m + r.binders.length = + (r.fieldIndex+r.binders.length) + (m-r.fieldIndex) by omega, + VExpr.liftN_liftN_midN e d k (m-r.fieldIndex) (by omega)] + · congr 1 + simp only [VExpr.liftN_appN] + rw [show + (VExpr.bvar + (m - 1 - r.fieldIndex + r.binders.length)).liftN + k (m+r.binders.length) = + .bvar (m - 1 - r.fieldIndex + r.binders.length) from by + simp only [VExpr.liftN] + rw [liftVar_lt (by omega)], + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + +/-- General mutual minor-IH normalization after `p` earlier hypotheses. -/ +theorem BlockGenerationChecked.blockMinorIH_lift_ruleIH + (d : Nat) (r : RecArg) (m k p : Nat) + (hj : r.fieldIndex < m) : + (BlockGenerationChecked.blockMinorIH d m p r).liftN k (m+p) = + (BlockGenerationChecked.blockRuleIH d k m r).liftN p := by + rw [BlockGenerationChecked.blockMinorIH_shift d r m p hj] + rw [← VExpr.liftN_liftN_comm + (BlockGenerationChecked.blockMinorIH d m 0 r) + p k 0 m (Nat.zero_le _)] + rw [BlockGenerationChecked.blockMinorIH_zero_lift_ruleIH d r m k hj] + +theorem BlockGenerationChecked.blockRuleIHs_length (d k m : Nat) : + ∀ (rs : List RecArg) (p : Nat), + (BlockGenerationChecked.blockRuleIHs d k m rs p).length = rs.length + | [], _ => rfl + | _ :: rs, p => by + simp [BlockGenerationChecked.blockRuleIHs, + BlockGenerationChecked.blockRuleIHs_length d k m rs (p+1)] + +/-- Lift the complete mutual minor-IH telescope into rule context. -/ +theorem BlockGenerationChecked.blockIHs_liftN (d m k : Nat) : + ∀ (rs : List RecArg), + (∀ r ∈ rs, r.fieldIndex < m) → ∀ (p : Nat) (X : VExpr), + (VExpr.forallN + (BlockGenerationChecked.blockIHsFromRecArgs d m rs p) X).liftN + k (m+p) = + VExpr.forallN + (BlockGenerationChecked.blockRuleIHs d k m rs p) + (X.liftN k (m+p+rs.length)) + | [], _, _, _ => rfl + | r :: rs, hm, p, X => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · exact BlockGenerationChecked.blockMinorIH_lift_ruleIH + d r m k p (hm r (.head _)) + · rw [show m+p+1 = m+(p+1) by omega, + BlockGenerationChecked.blockIHs_liftN d m k rs + (fun q hq => hm q (.tail _ hq)) (p+1) X, + show m+(p+1)+rs.length = + m+p+(r :: rs).length from by simp; omega] + +theorem BlockGenerationChecked.blockIHs_liftN' + (d m k : Nat) (rs : List RecArg) + (hm : ∀ r ∈ rs, r.fieldIndex < m) + (p : Nat) (X : VExpr) {cut : Nat} (hcut : cut = m+p) : + (VExpr.forallN + (BlockGenerationChecked.blockIHsFromRecArgs d m rs p) X).liftN + k cut = + VExpr.forallN + (BlockGenerationChecked.blockRuleIHs d k m rs p) + (X.liftN k (m+p+rs.length)) := by + rw [hcut] + exact BlockGenerationChecked.blockIHs_liftN d m k rs hm p X + +theorem BlockGenerationChecked.blockRuleIHs_liftN1 (d k m : Nat) : + ∀ (rs : List RecArg) (p c : Nat), c ≤ p → ∀ (X : VExpr), + VExpr.forallN + (BlockGenerationChecked.blockRuleIHs d k m rs (p+1)) + (X.liftN 1 (c+rs.length)) = + (VExpr.forallN + (BlockGenerationChecked.blockRuleIHs d k m rs p) X).liftN 1 c + | [], p, c, _, X => by + simp [BlockGenerationChecked.blockRuleIHs, VExpr.forallN] + | r :: rs, p, c, hc, X => by + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN'_liftN' (Nat.zero_le _) hc] + · rw [show c+(r :: rs).length = (c+1)+rs.length from by + simp + omega] + exact BlockGenerationChecked.blockRuleIHs_liftN1 + d k m rs (p+1) (c+1) (by omega) X + +/-- Consume one routed recursive-call term for every mutual rule IH. -/ +theorem hasType_appN_blockRuleIHs + {source : VInductDecl} {gen : BlockGenerationChecked source} + {env : VEnv} {Γ : List VExpr} {d m k : Nat} + {argOf : RecArg → VExpr} {Dfin : VExpr} : + ∀ {rs : List RecArg} {g : VExpr}, + (∀ r ∈ rs, env.HasType gen.recUvars Γ (argOf r) + (BlockGenerationChecked.blockRuleIH d k m r)) → + env.HasType gen.recUvars Γ g + (VExpr.forallN + (BlockGenerationChecked.blockRuleIHs d k m rs 0) + (Dfin.liftN rs.length)) → + env.HasType gen.recUvars Γ (g.appN (rs.map argOf)) Dfin + | [], g, _, hg => by + simpa [BlockGenerationChecked.blockRuleIHs] using hg + | r :: rs, g, hargs, hg => by + have happ := VEnv.HasType.app hg (by + simpa [BlockGenerationChecked.blockRuleIHs] using + hargs r (.head _)) + simp only [List.length_cons] at happ + rw [show Dfin.liftN (rs.length+1) = + (Dfin.liftN rs.length).liftN 1 (0+rs.length) from by + rw [Nat.zero_add, + VExpr.liftN'_liftN' (Nat.zero_le _) (by omega)], + BlockGenerationChecked.blockRuleIHs_liftN1 + d k m rs 0 0 (Nat.le_refl _) (Dfin.liftN rs.length), + VExpr.inst_liftN1] at happ + exact hasType_appN_blockRuleIHs + (rs := rs) (fun q hq => hargs q (.tail _ hq)) happ + +theorem BlockGenerationChecked.minorTypesAux_length + {source : VInductDecl} (gen : BlockGenerationChecked source) : + ∀ (constructors : List NormalizedBlockCtor) (i : Nat), + (gen.minorTypesAux constructors i).length = constructors.length + | [], _ => rfl + | _ :: constructors, i => by + simp [BlockGenerationChecked.minorTypesAux, + gen.minorTypesAux_length constructors (i + 1)] + +theorem BlockGenerationChecked.minorTypes_length + {source : VInductDecl} (gen : BlockGenerationChecked source) : + gen.minorTypes.length = gen.minorCount := by + simpa [BlockGenerationChecked.minorTypes] using + gen.minorTypesAux_length gen.flatCtors 0 + +/-- Positional lookup through the progressively weakened flattened mutual +minor telescope. -/ +theorem BlockGenerationChecked.minorTypesAux_getElem? + {source : VInductDecl} (gen : BlockGenerationChecked source) : + ∀ (constructors : List NormalizedBlockCtor) (i q : Nat), + (gen.minorTypesAux constructors i)[q]? = + constructors[q]?.map fun constructor => + (gen.minorType constructor).liftN (i+q) + | [], _, q => by simp [BlockGenerationChecked.minorTypesAux] + | _ :: _, _, 0 => by simp [BlockGenerationChecked.minorTypesAux] + | _ :: constructors, i, q+1 => by + simp only [BlockGenerationChecked.minorTypesAux, + List.getElem?_cons_succ] + rw [gen.minorTypesAux_getElem? constructors (i+1) q, + show i+1+q = i+(q+1) by omega] + +namespace BlockGenerationEnv + +variable {source : VInductDecl} {gen : BlockGenerationChecked source} + {env : VEnv} (S : BlockGenerationEnv gen env) +include S + +theorem paramsTel_onTel : + env.OnTel gen.recUvars [] gen.paramsTel := by + have h := S.generationParams_defeq.raw_onTel.instL + (U' := gen.recUvars) gen.sourceLevels_wf + simpa [BlockGenerationChecked.paramsTel] using h + +theorem motiveTypesAux_onTel + (families : List NormalizedFamily) + (hsub : ∀ family ∈ families, family ∈ gen.families) + (Δ : List VExpr) (i : Nat) (hΔ : Δ.length = i) : + env.OnTel gen.recUvars (Δ ++ gen.paramsTel.reverse) + (gen.motiveTypesAux families i) := by + induction families generalizing Δ i with + | nil => trivial + | cons family families ih => + exact ⟨by + rw [← hΔ] + exact (S.motive_isType (hsub family (.head _))).weakN S.ord + (.zero Δ), + ih (fun family hfamily => hsub family (.tail _ hfamily)) + (_ :: Δ) (i + 1) (by simp [hΔ])⟩ + +theorem motiveTypes_onTel : + env.OnTel gen.recUvars gen.paramsTel.reverse gen.motiveTypes := by + simpa [BlockGenerationChecked.motiveTypes] using + motiveTypesAux_onTel S gen.families (fun _ h => h) [] 0 rfl + +/-- Constructor fields instantiated for recursor generation are well typed +over the generation parameter telescope. -/ +theorem generationFields_onTel_rec + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + env.OnTel gen.recUvars gen.paramsTel.reverse + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) := by + have hemitted := (S.ctorWF constructor hconstructor).rawEmitted_onTel + have hfields₀ := (VEnv.OnTel.of_append + (As := gen.block.checked.params) hemitted).2 + have hfields₁ := hfields₀.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hfieldsChecked : env.OnTel gen.recUvars + (gen.block.checked.params.map + (VExpr.instL gen.sourceLevels)).reverse + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) := by + simpa [NormalizedCtor.fieldsR, List.map_reverse] using hfields₁ + exact hfieldsChecked.defeqDFC S.ord + (S.generationParams_ctx_rec.symm S.ord) + +/-- The checked and generation parameter contexts stay definitionally equal +beneath every instantiated constructor-field prefix. -/ +theorem generationFieldPrefix_ctx_rec + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) (j : Nat) : + env.IsDefEqCtx gen.recUvars [] + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination |>.take j).reverse ++ gen.paramsTel.reverse) + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination |>.take j).reverse ++ + (gen.block.checked.params.map + (VExpr.instL gen.sourceLevels)).reverse) := by + have hfields := S.generationFields_onTel_rec hconstructor + rw [← List.take_append_drop j + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination)] at hfields + exact (hfields.of_append.1).extendDefEqCtx + S.generationParams_ctx_rec + +/-- Definitionally equal raw/view contexts at any mutual constructor-field +prefix. -/ +theorem emittedPrefix_ctx {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) (j : Nat) : + env.IsDefEqCtx source.uvars [] + ((constructor.ctor.rawFields source.nparams |>.take j).reverse ++ + gen.block.checked.params.reverse) + ((constructor.ctor.view.fields.take j).reverse ++ + gen.block.checked.params.reverse) := by + have h := ((S.ctorWF constructor hconstructor).emittedTel.take + (source.nparams + j)).ctx + have hviewLen : + gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hraw : + (gen.block.checked.params ++ + constructor.ctor.rawFields source.nparams).take + (source.nparams + j) = + gen.block.checked.params ++ + (constructor.ctor.rawFields source.nparams).take j := by + rw [← hviewLen] + rw [List.take_append, List.take_of_length_le (by omega)] + simp + have hview : + (gen.block.checked.params ++ constructor.ctor.view.fields).take + (source.nparams + j) = + gen.block.checked.params ++ + constructor.ctor.view.fields.take j := by + rw [← hviewLen] + rw [List.take_append, List.take_of_length_le (by omega)] + simp + simp only [NormalizedBlockCtor.emittedBinders, + NormalizedBlockCtor.viewBinders] at h + rw [hraw, hview] at h + simpa [List.reverse_append] using h + +/-- Pointwise raw/view field-domain equality for a mutual constructor, in +the preceding raw context. -/ +theorem emittedField_defeq {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + {j : Nat} {B B' : VExpr} + (hB : (constructor.ctor.rawFields source.nparams)[j]? = some B) + (hB' : constructor.ctor.view.fields[j]? = some B') : + ∃ u, env.IsDefEq source.uvars + ((constructor.ctor.rawFields source.nparams |>.take j).reverse ++ + gen.block.checked.params.reverse) + B B' (.sort u) := by + have hviewLen : + gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hraw : + getElem? + (gen.block.checked.params ++ + constructor.ctor.rawFields source.nparams) + (source.nparams + j) = some B := by + rw [List.getElem?_append_right (by rw [hviewLen]; omega), hviewLen] + simpa using hB + have hview : + getElem? + (gen.block.checked.params ++ constructor.ctor.view.fields) + (source.nparams + j) = some B' := by + rw [List.getElem?_append_right (by rw [hviewLen]; omega), hviewLen] + simpa using hB' + obtain ⟨u, h⟩ := + (S.ctorWF constructor hconstructor).emittedTel.getElem? hraw hview + have htake : + (gen.block.checked.params ++ + constructor.ctor.rawFields source.nparams).take + (source.nparams + j) = + gen.block.checked.params ++ + (constructor.ctor.rawFields source.nparams).take j := by + rw [← hviewLen] + rw [List.take_append, List.take_of_length_le (by omega)] + simp + simp only [NormalizedBlockCtor.emittedBinders] at h + rw [htake, List.reverse_append] at h + exact ⟨u, by simpa using h⟩ + +/-- The generated and checked index telescopes of every family are +definitionally equal after universe instantiation. -/ +theorem familyIndexTel_defeq_rec {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.TelDefEq gen.recUvars gen.paramsTel.reverse + (gen.idxTel family) + (family.view.indices.map (VExpr.instL gen.sourceLevels)) := by + have h := (S.familyWF family hfamily).familyTel.drop source.nparams + have hrawTake : + (family.rawParams source.nparams ++ + family.rawIndices source.nparams).take source.nparams = + family.rawParams source.nparams := by + let Ps := family.rawParams source.nparams + let Is := family.rawIndices source.nparams + have hlen : Ps.length = source.nparams := + (gen.shape.2.2.2.2 family hfamily).2.2.1 + change (Ps ++ Is).take source.nparams = Ps + rw [← hlen, List.take_append, List.take_length] + simp + have hrawDrop : + (family.rawParams source.nparams ++ + family.rawIndices source.nparams).drop source.nparams = + family.rawIndices source.nparams := by + let Ps := family.rawParams source.nparams + let Is := family.rawIndices source.nparams + have hlen : Ps.length = source.nparams := + (gen.shape.2.2.2.2 family hfamily).2.2.1 + change (Ps ++ Is).drop source.nparams = Is + rw [← hlen, List.drop_append] + simp + have hviewLen : gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hviewDrop : + (gen.block.checked.params ++ family.view.indices).drop + source.nparams = family.view.indices := by + rw [← hviewLen, List.drop_append] + simp + rw [hrawTake, hrawDrop, hviewDrop] at h + simp only [List.append_nil] at h + have hparams : env.IsDefEqCtx source.uvars [] + (family.rawParams source.nparams).reverse + gen.block.checked.params.reverse := by + simpa using (S.rawParams_defeq hfamily).ctx + have hemitted := h.defeqDFC S.ord hparams + have hgeneration := hemitted.defeqDFC S.ord + (S.generationParams_ctx.symm S.ord) + have hrec := hgeneration.instL + (U' := gen.recUvars) gen.sourceLevels_wf + simpa [BlockGenerationChecked.paramsTel, + BlockGenerationChecked.idxTel, List.map_reverse] using hrec + +/-- Transport the analyzer's recursive-argument certificate from checked +source syntax to the generated field and target-family index telescopes, then +weaken it beneath arbitrary motive/local prefixes. -/ +theorem recArg_transport + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + {r₀ : RecArg} {family : NormalizedFamily} + (hfamily : family ∈ gen.families) + (hsem : r₀.WF source.uvars env gen.validated.resultLevel + family.view.indices + ((constructor.ctor.view.fields.take r₀.fieldIndex).reverse ++ + gen.block.checked.params.reverse)) + (hjlt : r₀.fieldIndex < constructor.ctor.view.fields.length) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + let r := r₀.instL gen.sourceLevels + let As := VExpr.liftTelN d + (VExpr.liftTelN g r.binders r.fieldIndex) 0 + env.OnTel gen.recUvars + (As₂ ++ ((VExpr.liftTelN g + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).take r.fieldIndex) 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) As ∧ + env.SpineWF gen.recUvars + (As.reverse ++ + (As₂ ++ ((VExpr.liftTelN g + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).take r.fieldIndex) 0).reverse ++ + (mid ++ gen.paramsTel.reverse)))) + (VExpr.forallN + (VExpr.liftTelN + (r.fieldIndex + r.binders.length + g + d) + (gen.idxTel family) 0) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels))) + (r.indices.map fun e => + (e.liftN g (r.fieldIndex + r.binders.length)).liftN d + r.binders.length) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + dsimp only + let ls := gen.sourceLevels + have hjraw : + r₀.fieldIndex < + (constructor.ctor.rawFields source.nparams).length := by + rw [gen.flatCtor_fields_length hconstructor] + exact hjlt + have hraw := hsem.defeqDFC S.ord + ((S.emittedPrefix_ctx hconstructor r₀.fieldIndex).symm S.ord) + have htel₁ := hraw.1.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hsp₁ := hraw.2.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have htelChecked : env.OnTel gen.recUvars + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination |>.take r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (r₀.binders.map (VExpr.instL ls)) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse, List.map_take] using htel₁ + have hspChecked : env.SpineWF gen.recUvars + ((r₀.binders.map (VExpr.instL ls)).reverse ++ + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination |>.take r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse)) + (VExpr.instL ls + (VExpr.forallN + (VExpr.liftTelN + (r₀.fieldIndex + r₀.binders.length) + family.view.indices 0) + (.sort gen.validated.resultLevel))) + (r₀.indices.map (VExpr.instL ls)) + (VExpr.instL ls (.sort gen.validated.resultLevel)) := by + simpa [List.map_append, List.map_reverse, + NormalizedCtor.fieldsR, List.map_take] using hsp₁ + have hprefix := + S.generationFieldPrefix_ctx_rec hconstructor r₀.fieldIndex + have htelGeneration := htelChecked.defeqDFC S.ord + (hprefix.symm S.ord) + have hfull := htelGeneration.extendDefEqCtx hprefix + have hspGeneration := hspChecked.defeqDFC S.ord (hfull.symm S.ord) + simp only [VExpr.instL_forallN, + VExpr.liftTelN_instL] at htelGeneration hspGeneration + have hjlen : + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).take r₀.fieldIndex).length = r₀.fieldIndex := by + simp only [NormalizedCtor.fieldsR, List.length_take, + List.length_map] + omega + have hidxField := (S.familyIndexTel_defeq_rec hfamily).weakN S.ord + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).take r₀.fieldIndex).reverse) + rw [List.length_reverse, hjlen] at hidxField + have hidxPrivate := hidxField.weakN S.ord + (Ctx.LiftN.zero + (Γ := ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).take r₀.fieldIndex).reverse ++ + gen.paramsTel.reverse) + (r₀.binders.map (VExpr.instL ls)).reverse) + simp only [List.length_reverse, List.length_map] at hidxPrivate + rw [VExpr.liftTelN_liftTelN, + VExpr.liftTelN_liftTelN] at hidxPrivate + have hidxLenView := hsem.2.forallN_sort_length + simp only [VExpr.liftTelN_length] at hidxLenView + have hidxLen : + (r₀.indices.map (VExpr.instL ls)).length = + (VExpr.liftTelN + (r₀.fieldIndex + r₀.binders.length) + (gen.idxTel family) 0).length := by + simp only [List.length_map, VExpr.liftTelN_length, + BlockGenerationChecked.idxTel] + exact hidxLenView.trans + (gen.shape.2.2.2.2 family hfamily).2.2.2.1.symm + have hspRaw := + hidxPrivate.spine_sort S.ord hspGeneration hidxLen + have W₁ := Ctx.LiftN.consTel (n := mid.length) + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).take r₀.fieldIndex) + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [hjlen, Nat.add_zero] at W₁ + have htel₂ := htelGeneration.weakN S.ord W₁ + have hsp₂ := hspRaw.weakN S.ord + (Ctx.LiftN.consTel + (r₀.binders.map (VExpr.instL ls)) W₁) + rw [hg] at htel₂ hsp₂ + have W₂ := Ctx.LiftN.zero + (Γ := (VExpr.liftTelN g + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).take r₀.fieldIndex) 0).reverse ++ + (mid ++ gen.paramsTel.reverse)) As₂ (h := hd) + have htel₃ := htel₂.weakN S.ord W₂ + have hsp₃ := hsp₂.weakN S.ord + (Ctx.LiftN.consTel + (VExpr.liftTelN g + (r₀.binders.map (VExpr.instL ls)) r₀.fieldIndex) W₂) + refine ⟨?_, ?_⟩ + · simpa [ls, RecArg.instL, List.append_assoc] using htel₃ + · simp only [List.length_map, VExpr.liftTelN_length, + Nat.add_zero] at hsp₃ + rw [VExpr.liftN_forallN, VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN_hi' + (r₀.fieldIndex + r₀.binders.length) g _ 0 (by omega), + VExpr.liftTelN_liftTelN_mid + (r₀.fieldIndex + r₀.binders.length + g) d _ 0 + r₀.binders.length (Nat.zero_le _) (by omega)] at hsp₃ + rw [show r₀.binders.length + r₀.fieldIndex = + r₀.fieldIndex + r₀.binders.length from Nat.add_comm _ _] at hsp₃ + simpa [ls, RecArg.instL, VExpr.instL, VExpr.liftN, + List.map_map, Function.comp_def, List.append_assoc] using hsp₃ + +theorem recArgMinor_isType {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) {r : RecArg} + (hrmem : r ∈ constructor.ctor.recArgsR source.uvars gen.elimination) + (Δ : List VExpr) (p : Nat) (hΔ : Δ.length = p) : + env.IsType gen.recUvars + (Δ ++ + (VExpr.liftTelN gen.familyCount + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) + (BlockGenerationChecked.blockMinorIH gen.familyCount + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length p r) := by + obtain ⟨r₀, hr₀, rfl⟩ := + NormalizedCtor.recArgsR_mem hrmem + obtain ⟨family, hfamily, hord, ⟨Bview, hBview, hshape⟩, hsem⟩ := + (S.ctorWF constructor hconstructor).recursive r₀ hr₀ + let ls := gen.sourceLevels + let r := r₀.instL ls + let d := gen.familyCount + let Bs := constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination + let m := Bs.length + let j := r₀.fieldIndex + let Fs := VExpr.liftTelN d Bs 0 + let As := BlockGenerationChecked.blockMinorBinders d m p r + let idxs := r.indices.map fun e => + (e.liftN d (r.fieldIndex + r.binders.length)).liftN + (m - r.fieldIndex + p) r.binders.length + let Γ := Δ ++ Fs.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse) + let q := family.view.ordinal + let K := d - 1 - r.targetType + m + p + r.binders.length + have hjview : r₀.fieldIndex < constructor.ctor.view.fields.length := + (List.getElem?_eq_some_iff.1 hBview).1 + have hjm : j < m := by + have hfields := gen.flatCtor_fields_length hconstructor + simp only [j, m, Bs, NormalizedCtor.fieldsR_length] + omega + have hjraw : + r₀.fieldIndex < + (constructor.ctor.rawFields source.nparams).length := by + simpa [j, m, Bs, NormalizedCtor.fieldsR_length] using hjm + let Braw := + (constructor.ctor.rawFields source.nparams)[r₀.fieldIndex] + have hBraw : + (constructor.ctor.rawFields source.nparams)[r₀.fieldIndex]? = + some Braw := + List.getElem?_eq_getElem hjraw + have hd : gen.motiveTypes.reverse.length = d := by + simp [d, gen.motiveTypes_length] + have hd' : gen.motiveTypes.length = d := by + simpa using hd + have hFsLen : Fs.length = m := by + simp [Fs, m, VExpr.liftTelN_length] + have hstackLen : + (Δ ++ (Fs.drop j).reverse).length = m - j + p := by + simp only [List.length_append, List.length_reverse, + List.length_drop, hFsLen, hΔ] + omega + have ht := S.recArg_transport hconstructor hfamily hsem hjview + gen.motiveTypes.reverse hd + (Δ ++ (Fs.drop j).reverse) hstackLen + simp only [RecArg.instL] at ht + have hctx : + (Δ ++ (Fs.drop j).reverse) ++ + ((VExpr.liftTelN d (Bs.take j) 0).reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) = Γ := by + dsimp only [Γ, Fs] + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc + ((VExpr.liftTelN d Bs 0).drop j).reverse, + ← List.reverse_append, List.take_append_drop, + ← List.append_assoc] + dsimp only [j] at ht hctx + have htel : env.OnTel gen.recUvars Γ As := by + rw [hctx] at ht + simpa [r, As, m, j, Bs, RecArg.instL, + BlockGenerationChecked.blockMinorBinders] using ht.1 + have hsp : env.SpineWF gen.recUvars + (As.reverse ++ Γ) + (VExpr.forallN + (VExpr.liftTelN + (m + p + r.binders.length + d) (gen.idxTel family) 0) + (.sort (gen.validated.resultLevel.inst ls))) + idxs + (.sort (gen.validated.resultLevel.inst ls)) := by + rw [hctx] at ht + simpa [r, As, idxs, m, j, Bs, d, ls, RecArg.instL, + BlockGenerationChecked.blockMinorBinders, + List.append_assoc, + show j + r₀.binders.length + d + (m - j + p) = + m + p + r₀.binders.length + d from by omega] using ht.2 + have hF : Γ[m - 1 - j + p]? = + some ((Braw.instL ls).liftN d j) := by + dsimp only [Γ, Fs] + rw [getElem?_stack_mid Δ + (VExpr.liftTelN d Bs 0).reverse + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse) + (i := m - 1 - j + p) (by rw [hΔ]; omega) + (by simp only [hΔ, List.length_reverse, + VExpr.liftTelN_length]; omega), + show m - 1 - j + p - Δ.length = m - 1 - j from by + rw [hΔ] + omega, + List.getElem?_reverse (by rw [hFsLen]; omega), + VExpr.liftTelN_length, + show m - 1 - (m - 1 - j) = j from by omega, + VExpr.liftTelN_getElem?, + NormalizedCtor.fieldsR_getElem?, hBraw] + simp [ls] + have hlu := Lookup.of_getElem? hF + rw [show m - 1 - j + p + 1 = m - j + p from by omega] at hlu + dsimp only [j, r] at hlu + have hf0 := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) hlu + obtain ⟨u, hdom₀⟩ := + S.emittedField_defeq hconstructor hBraw hBview + have hdom₁ := hdom₀.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hdomChecked : env.IsDefEq gen.recUvars + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination |>.take r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (Braw.instL ls) (Bview.instL ls) ((VExpr.sort u).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse, List.map_take] using hdom₁ + have hprefix := + S.generationFieldPrefix_ctx_rec hconstructor r₀.fieldIndex + have hdomGeneration := hdomChecked.defeqDFC S.ord + (hprefix.symm S.ord) + have hjlen : (Bs.take r₀.fieldIndex).length = + r₀.fieldIndex := by + simp only [Bs, NormalizedCtor.fieldsR, + List.length_take, List.length_map] + omega + have Wmid := Ctx.LiftN.consTel (n := d) + (Bs.take r₀.fieldIndex) + (Ctx.LiftN.zero (n := d) (Γ := gen.paramsTel.reverse) + gen.motiveTypes.reverse (h := hd)) + rw [hjlen, Nat.add_zero] at Wmid + have hdom₂ := hdomGeneration.weakN S.ord Wmid + have Wstack := Ctx.LiftN.zero + (Γ := (VExpr.liftTelN d (Bs.take j) 0).reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) + (Δ ++ (Fs.drop j).reverse) (h := hstackLen) + have hdom₃ := hdom₂.weakN S.ord Wstack + rw [hctx] at hdom₃ + have hfView := hdom₃.defeq hf0 + have hfield := blockMinor_fieldType_of_eq hshape d m p + (by simpa [j] using hjm) gen.elimination + simp only [RecArg.instL] at hfield + rw [hfield] at hfView + have hf := hfView.weakN S.ord + (Ctx.LiftN.zero (Γ := Γ) As.reverse) + have hmajor := VEnv.HasType.appN_selfSpine + (env := env) (U := gen.recUvars) + (As := As) + (B := VExpr.appN + (.const family.raw.name ls) + (VExpr.bvarRevRange + (m + p + r.binders.length + d) source.nparams ++ idxs)) + (Δ := []) (Γ := Γ) (by + simpa [As, r, idxs, j, d, ls, RecArg.instL, + List.length_reverse, List.map_map, + Function.comp_def] using hf) + simp only [List.length_nil, VExpr.liftN_zero, + List.nil_append] at hmajor + have hAsLen : As.length = r.binders.length := by + simp [As, BlockGenerationChecked.blockMinorBinders, + VExpr.liftTelN_length] + have hmajor' : env.HasType gen.recUvars (As.reverse ++ Γ) + ((VExpr.bvar (m - 1 - r.fieldIndex + p + As.length)).appN + (VExpr.bvarRevRange 0 As.length)) + (VExpr.appN + (.const family.raw.name ls) + (VExpr.bvarRevRange + (m + p + r.binders.length + d) source.nparams ++ idxs)) := by + simpa [As, d, r, RecArg.instL, + BlockGenerationChecked.blockMinorBinders, + VExpr.liftN, liftVar_le, Nat.add_comm] using hmajor + rw [hAsLen] at hmajor' + have hq : q < d := by + simpa [q, d] using gen.family_ordinal_lt hfamily + have hmot : gen.motiveTypes.reverse[d - 1 - q]? = + some ((gen.motiveType family).liftN q) := by + rw [List.getElem?_reverse (by rw [hd']; omega), + show gen.motiveTypes.length - 1 - (d - 1 - q) = q from by + rw [hd'] + omega, + gen.motiveTypes_getElem?_ordinal hfamily] + have hM0 := getElem?_rstack_mid + (As.reverse ++ (Δ ++ Fs.reverse)) + gen.motiveTypes.reverse gen.paramsTel.reverse + (i := K) + (by + simp only [List.length_append, List.length_reverse, + hAsLen, hΔ, hFsLen] + dsimp only [K, q, d, r] + simp only [RecArg.instL] + omega) + (by + simp only [List.length_append, List.length_reverse, + hAsLen, hΔ, hFsLen, hd] + dsimp only [K, q, d, r] + simp only [RecArg.instL] + omega) + have hdiff : + K - (As.reverse ++ (Δ ++ Fs.reverse)).length = d - 1 - q := by + simp only [List.length_append, List.length_reverse, + hAsLen, hΔ, hFsLen] + dsimp only [K, q, d, r] + simp only [RecArg.instL] + omega + rw [hdiff, hmot] at hM0 + have hMget : (As.reverse ++ Γ)[K]? = + some ((gen.motiveType family).liftN q) := by + simpa [Γ, List.append_assoc] using hM0 + have hMraw := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) + (Lookup.of_getElem? hMget) + have hM : env.HasType gen.recUvars (As.reverse ++ Γ) (.bvar K) + ((gen.motiveType family).liftN (q + K + 1)) := by + simpa [VExpr.liftN_liftN, Nat.add_assoc] using hMraw + have hlen : idxs.length = (gen.idxTel family).length := by + simp only [idxs, List.length_map, + BlockGenerationChecked.idxTel] + have hidx := hsem.2.forallN_sort_length + simp only [VExpr.liftTelN_length] at hidx + simpa [r, RecArg.instL] using hidx.trans + (gen.shape.2.2.2.2 family hfamily).2.2.2.1.symm + have hshift : q + K + 1 = m + p + r.binders.length + d := by + dsimp only [q, K, d, r] + simp only [RecArg.instL] + omega + have hbody := gen.motiveVarApp_hasType family + (q := q) (K := K) + hM (by simpa [hshift] using hsp) hlen + (by simpa [hshift] using hmajor') + refine VEnv.IsType.forallN htel ⟨gen.motiveLevel, ?_⟩ + simpa [BlockGenerationChecked.blockMinorIH, + r, As, idxs, m, d, K, q, Γ, Fs, Bs, + List.append_assoc] using hbody + +/-- The global mutual-IH telescope for one constructor is well formed at +every recursive suffix. -/ +theorem ihs_onTel {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + ∀ (rsSuf : List RecArg), + (∀ r ∈ rsSuf, + r ∈ constructor.ctor.recArgsR source.uvars gen.elimination) → + ∀ (Δ : List VExpr) (p : Nat), Δ.length = p → + env.OnTel gen.recUvars + (Δ ++ + (VExpr.liftTelN gen.familyCount + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) + (BlockGenerationChecked.blockIHsFromRecArgs gen.familyCount + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length rsSuf p) + | [], _, _, _, _ => trivial + | r :: rsSuf, hqs, Δ, p, hΔ => + ⟨S.recArgMinor_isType hconstructor + (hqs r (.head _)) Δ p hΔ, + BlockGenerationEnv.ihs_onTel hconstructor rsSuf + (fun q hq => hqs q (.tail _ hq)) + (_ :: Δ) (p + 1) (by simp [hΔ])⟩ + +theorem viewResultIndices_length + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + constructor.ctor.view.resultIndices.length = + constructor.familyIndices.length := by + have h := (S.ctorWF constructor hconstructor).resultSpine.forallN_sort_length + simpa only [VExpr.liftTelN_length] using h + +/-- Transport one mutual constructor's checked result spine to the selected +raw family-index telescope and through arbitrary middle/top binders. -/ +theorem result_transport + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + {family : NormalizedFamily} (hfamily : family ∈ gen.families) + (hindices : family.view.indices = constructor.familyIndices) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.SpineWF gen.recUvars + (As₂ ++ + ((VExpr.liftTelN g + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + g + d) + (gen.idxTel family) 0) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels))) + ((constructor.ctor.resultIndicesR source.uvars gen.elimination).map + fun e => + (e.liftN g + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length).liftN d) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + let ls := gen.sourceLevels + have hview := (S.ctorWF constructor hconstructor).resultSpine + rw [← hindices] at hview + have hctx := (S.ctorWF constructor hconstructor).emittedTel.ctx + simp only [NormalizedBlockCtor.emittedBinders, + NormalizedBlockCtor.viewBinders, List.reverse_append, + List.append_nil] at hctx + have hraw := hview.defeqDFC S.ord (hctx.symm S.ord) + have hfields := gen.flatCtor_fields_length hconstructor + rw [← hfields] at hraw + have h1 := hraw.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have h1Checked : env.SpineWF gen.recUvars + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (VExpr.instL ls + (VExpr.forallN + (VExpr.liftTelN + (constructor.ctor.rawFields source.nparams).length + family.view.indices 0) + (.sort gen.validated.resultLevel))) + (constructor.ctor.view.resultIndices.map (VExpr.instL ls)) + ((VExpr.sort gen.validated.resultLevel).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse] using h1 + have hfieldsCtx := + (S.generationFields_onTel_rec hconstructor).extendDefEqCtx + S.generationParams_ctx_rec + have h1Generation := h1Checked.defeqDFC S.ord + (hfieldsCtx.symm S.ord) + rw [VExpr.instL_forallN, VExpr.liftTelN_instL] at h1Generation + rw [← NormalizedCtor.fieldsR_length + (source := source) (mode := gen.elimination) constructor.ctor] at h1Generation + have hidx := (S.familyIndexTel_defeq_rec hfamily).weakN S.ord + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).reverse) + rw [List.length_reverse] at hidx + have hlen : + (constructor.ctor.view.resultIndices.map (VExpr.instL ls)).length = + (VExpr.liftTelN + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + (gen.idxTel family) 0).length := by + simp only [List.length_map, VExpr.liftTelN_length, + BlockGenerationChecked.idxTel] + exact (S.viewResultIndices_length hconstructor).trans + ((congrArg List.length hindices).symm.trans + (gen.shape.2.2.2.2 family hfamily).2.2.2.1.symm) + have h1Raw := hidx.spine_sort S.ord h1Generation hlen + have W₁ := Ctx.LiftN.consTel (n := mid.length) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [Nat.add_zero] at W₁ + have h2 := h1Raw.weakN S.ord W₁ + rw [VExpr.liftN_forallN, hg] at h2 + have h3 := h2.weakN S.ord + (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + rw [VExpr.liftN_forallN] at h3 + rw [VExpr.liftTelN_liftTelN_hi' + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length g _ 0 (by omega), + VExpr.liftTelN_liftTelN] at h3 + simpa [ls, NormalizedCtor.resultIndicesR, + VExpr.instL, VExpr.liftN, List.map_map, + Function.comp_def, List.append_assoc] using h3 + +/-- The raw mutual constructor applied to its emitted self-spine at source +universes. -/ +theorem ctorApp_emitted_decl + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + env.HasType source.uvars + ((constructor.ctor.rawFields source.nparams).reverse ++ + gen.block.checked.params.reverse) + (VExpr.appN + (.const constructor.ctor.raw.name (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (constructor.ctor.rawFields source.nparams).length + source.nparams ++ + VExpr.bvarRevRange 0 + (constructor.ctor.rawFields source.nparams).length)) + (NormalizedBlockCtor.resultTarget gen constructor) := by + let E := NormalizedBlockCtor.emittedBinders gen constructor + let V := NormalizedBlockCtor.viewBinders gen constructor + have hc : env.HasType source.uvars [] + (.const constructor.ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN + (NormalizedBlockCtor.declaredBinders + (source := source) constructor) + (NormalizedBlockCtor.rawResult + (source := source) constructor)) := by + rw [NormalizedBlockCtor.declaredBinders, + NormalizedBlockCtor.rawResult, + ← constructor.ctor.rawType_eq] + exact S.ctorConst_decl hconstructor + obtain ⟨_, hdecl⟩ := + (S.ctorWF constructor hconstructor).declaredTel.forallN_defeq + (by simpa using + (S.ctorWF constructor hconstructor).declaredResult) + have hview : env.HasType source.uvars [] + (.const constructor.ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN V + (NormalizedBlockCtor.resultTarget gen constructor)) := by + simpa [V] using hdecl.defeq hc + have hresult : env.HasType source.uvars E.reverse + (NormalizedBlockCtor.resultTarget gen constructor) + (.sort gen.validated.resultLevel) := by + simpa [E] using + (S.ctorWF constructor hconstructor).emittedResult.hasType.2 + obtain ⟨_, hemit⟩ := + (S.ctorWF constructor hconstructor).emittedTel.forallN_defeq + (by simpa [E, VEnv.HasType] using hresult) + have hcE₀ : env.HasType source.uvars [] + (.const constructor.ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN E + (NormalizedBlockCtor.resultTarget gen constructor)) := by + exact hemit.defeq' (by simpa [V] using hview) + have hclosed : + (VExpr.forallN E + (NormalizedBlockCtor.resultTarget gen constructor)).ClosedN 0 := + (hcE₀.closedN' S.ord.closed trivial).2.2 + have hcE : env.HasType source.uvars E.reverse + (.const constructor.ctor.raw.name (VLevel.params source.uvars)) + (VExpr.forallN E + (NormalizedBlockCtor.resultTarget gen constructor)) := + hcE₀.weak0 S.ord + have happ := VEnv.HasType.appN_selfSpine' + (As := E) + (B := NormalizedBlockCtor.resultTarget gen constructor) + (Δ := []) (Γ := []) hclosed (by simpa using hcE) + simp only [List.length_nil, VExpr.liftN_zero, + List.nil_append, List.append_nil] at happ + have hEctx : + E.reverse = + (constructor.ctor.rawFields source.nparams).reverse ++ + gen.block.checked.params.reverse := by + simp [E, NormalizedBlockCtor.emittedBinders, + List.reverse_append] + have hElen : + E.length = + (constructor.ctor.rawFields source.nparams).length + + source.nparams := by + have hp : gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + simp [E, NormalizedBlockCtor.emittedBinders, hp] + omega + rw [hEctx, hElen, + ← VExpr.bvarRevRange_append source.nparams + (constructor.ctor.rawFields source.nparams).length] at happ + exact happ + +/-- The exact emitted mutual-constructor application in recursor universes, +retargeted to its owner family. -/ +theorem ctorApp_emitted_rec + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + {family : NormalizedFamily} + (hname : family.raw.name = constructor.familyName) : + env.HasType gen.recUvars + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).reverse ++ gen.paramsTel.reverse) + (VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length source.nparams ++ + VExpr.bvarRevRange 0 + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length source.nparams ++ + constructor.ctor.resultIndicesR source.uvars gen.elimination)) := by + let ls := gen.sourceLevels + have h := (S.ctorApp_emitted_decl hconstructor).instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hChecked : env.HasType gen.recUvars + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + ((VExpr.appN + (.const constructor.ctor.raw.name (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (constructor.ctor.rawFields source.nparams).length + source.nparams ++ + VExpr.bvarRevRange 0 + (constructor.ctor.rawFields source.nparams).length)).instL ls) + ((NormalizedBlockCtor.resultTarget gen constructor).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse] using h + have hfieldsCtx := + (S.generationFields_onTel_rec hconstructor).extendDefEqCtx + S.generationParams_ctx_rec + have hGeneration := hChecked.defeqDFC S.ord + (hfieldsCtx.symm S.ord) + rw [← NormalizedCtor.fieldsR_length + (source := source) (mode := gen.elimination) constructor.ctor] at hGeneration + simpa [ls, hname, NormalizedCtor.fieldsR, + BlockGenerationChecked.paramsTel, + NormalizedBlockCtor.resultTarget, + NormalizedCtor.resultIndicesR, + VExpr.instL_appN, List.map_append, + bvarRevRange_instL, List.map_reverse, + VExpr.instL, VLevel.params_map_inst_params'] using hGeneration + +/-- Transport the emitted mutual-constructor application beneath arbitrary +middle and top binders. -/ +theorem ctorApp_transport + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + {family : NormalizedFamily} + (hname : family.raw.name = constructor.familyName) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.HasType gen.recUvars + (As₂ ++ + ((VExpr.liftTelN g + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) + (VExpr.appN (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (d + (g + + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) source.nparams ++ + VExpr.bvarRevRange d + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (d + (g + + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) source.nparams ++ + (constructor.ctor.resultIndicesR source.uvars gen.elimination).map + fun e => + (e.liftN g + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length).liftN d)) := by + let Bs := constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination + have W₁ := Ctx.LiftN.consTel (n := mid.length) Bs + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [Nat.add_zero] at W₁ + have h₁ := (S.ctorApp_emitted_rec hconstructor hname).weakN + S.ord W₁ + rw [hg] at h₁ + have hmid : env.HasType gen.recUvars + ((VExpr.liftTelN g Bs 0).reverse ++ + (mid ++ gen.paramsTel.reverse)) + (VExpr.appN (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (g + Bs.length) source.nparams ++ + VExpr.bvarRevRange 0 Bs.length)) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (g + Bs.length) source.nparams ++ + (constructor.ctor.resultIndicesR source.uvars + gen.elimination).map (VExpr.liftN g · Bs.length))) := by + simpa [Bs, VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + VExpr.bvarRevRange_liftN_high Bs.length 0 g Bs.length (by omega), + VExpr.liftN] using h₁ + have htop := hmid.weakN S.ord + (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + simpa [Bs, VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.liftN, List.map_map, Function.comp_def, + List.append_assoc] using htop + +/-- The raw field telescope of a mutual constructor is well formed after +inserting all block motives. -/ +theorem fields_onTel_minor + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + env.OnTel gen.recUvars + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse) + (VExpr.liftTelN gen.familyCount + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0) := by + have hd : gen.motiveTypes.reverse.length = gen.familyCount := by + simp [gen.motiveTypes_length] + have hout := (S.generationFields_onTel_rec hconstructor).weakN S.ord + (Ctx.LiftN.zero (n := gen.familyCount) + (Γ := gen.paramsTel.reverse) gen.motiveTypes.reverse (h := hd)) + simpa using hout + +/-- Every flattened mutual constructor minor is a type over the global +motive telescope. -/ +theorem minor_isType + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + env.IsType gen.recUvars + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse) + (gen.minorType constructor) := by + obtain ⟨family, hfamily, howner, hname, hindices⟩ := + (S.ctorWF constructor hconstructor).owner + let d := gen.familyCount + let Bs := constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination + let m := Bs.length + let rs := constructor.ctor.recArgsR source.uvars gen.elimination + let IHs := BlockGenerationChecked.blockIHsFromRecArgs d m rs 0 + let Fs := VExpr.liftTelN d Bs 0 + let Γ := IHs.reverse ++ + (Fs.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) + let q := family.view.ordinal + let K := d - 1 - constructor.owner + m + rs.length + simp only [BlockGenerationChecked.minorType] + refine VEnv.IsType.forallN (by + simpa [Bs, d] using S.fields_onTel_minor hconstructor) ?_ + refine VEnv.IsType.forallN (by + simpa [Bs, m, rs, IHs, Fs, d, List.append_assoc] using + S.ihs_onTel hconstructor rs (fun r hr => hr) [] 0 rfl) ?_ + have hrlen : IHs.reverse.length = rs.length := by + simp [IHs, BlockGenerationChecked.blockIHsFromRecArgs_length] + have hd : gen.motiveTypes.reverse.length = d := by + simp [d, gen.motiveTypes_length] + have hd' : gen.motiveTypes.length = d := by + simpa using hd + have hFsLen : Fs.length = m := by + simp [Fs, m, VExpr.liftTelN_length] + have hq : q < d := by + simpa [q, d] using gen.family_ordinal_lt hfamily + have hmot : gen.motiveTypes.reverse[d - 1 - q]? = + some ((gen.motiveType family).liftN q) := by + rw [List.getElem?_reverse (by rw [hd']; omega), + show gen.motiveTypes.length - 1 - (d - 1 - q) = q from by + rw [hd'] + omega, + gen.motiveTypes_getElem?_ordinal hfamily] + have hM0 := getElem?_rstack_mid + (IHs.reverse ++ Fs.reverse) + gen.motiveTypes.reverse gen.paramsTel.reverse + (i := K) + (by + simp only [List.length_append, List.length_reverse, + hrlen, hFsLen] + dsimp only [K, q, d] + omega) + (by + simp only [List.length_append, List.length_reverse, + hrlen, hFsLen, hd] + dsimp only [K, q, d] + omega) + have hdiff : + K - (IHs.reverse ++ Fs.reverse).length = d - 1 - q := by + simp only [List.length_append, List.length_reverse, + hrlen, hFsLen] + dsimp only [K, q, d] + omega + rw [hdiff, hmot] at hM0 + have hMget : Γ[K]? = + some ((gen.motiveType family).liftN q) := by + simpa [Γ, List.append_assoc] using hM0 + have hMraw := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) + (Lookup.of_getElem? hMget) + have hM : env.HasType gen.recUvars Γ (.bvar K) + ((gen.motiveType family).liftN (q + K + 1)) := by + simpa [VExpr.liftN_liftN, Nat.add_assoc] using hMraw + have hSp := S.result_transport hconstructor hfamily hindices + gen.motiveTypes.reverse hd IHs.reverse hrlen + have hSp' : env.SpineWF gen.recUvars Γ + (VExpr.forallN + (VExpr.liftTelN (m + d + rs.length) + (gen.idxTel family) 0) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels))) + ((constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + (e.liftN d m).liftN rs.length) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + simpa [Γ, Fs, Bs, m, d, List.append_assoc] using hSp + have hlen : + ((constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + (e.liftN d m).liftN rs.length).length = + (gen.idxTel family).length := by + simp only [List.length_map, NormalizedCtor.resultIndicesR, + BlockGenerationChecked.idxTel] + exact (S.viewResultIndices_length hconstructor).trans + ((congrArg List.length hindices).symm.trans + (gen.shape.2.2.2.2 family hfamily).2.2.2.1.symm) + have hctorApp := S.ctorApp_transport hconstructor hname + gen.motiveTypes.reverse hd IHs.reverse hrlen + have hctorApp' : env.HasType gen.recUvars Γ + (VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (m + d + rs.length) source.nparams ++ + VExpr.bvarRevRange rs.length m)) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (m + d + rs.length) source.nparams ++ + (constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + (e.liftN d m).liftN rs.length)) := by + simpa [Γ, Fs, Bs, m, d, IHs, rs, + List.append_assoc, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hctorApp + have hshift : q + K + 1 = m + d + rs.length := by + dsimp only [q, K, d] + omega + have hbody := gen.motiveVarApp_hasType family + (q := q) (K := K) + hM (by simpa [hshift, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hSp') hlen + (by simpa [hshift, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hctorApp') + exact ⟨gen.motiveLevel, by + simpa [Γ, Fs, Bs, m, rs, IHs, d, K, q, + BlockGenerationChecked.blockMinorIH, + List.append_assoc, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hbody⟩ + +/-- Any suffix of the globally flattened constructor list generates a +well-formed minor telescope at its positional depth. -/ +theorem minorTypesAux_onTel : + ∀ (constructors : List NormalizedBlockCtor), + (∀ constructor ∈ constructors, constructor ∈ gen.flatCtors) → + ∀ (Δ : List VExpr) (i : Nat), Δ.length = i → + env.OnTel gen.recUvars + (Δ ++ (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) + (gen.minorTypesAux constructors i) + | [], _, _, _, _ => trivial + | constructor :: constructors, hsub, Δ, i, hΔ => + ⟨by + rw [← hΔ] + exact (S.minor_isType + (hsub constructor (.head _))).weakN S.ord (.zero Δ), + BlockGenerationEnv.minorTypesAux_onTel constructors + (fun constructor hconstructor => hsub constructor (.tail _ hconstructor)) + (_ :: Δ) (i + 1) (by simp [hΔ])⟩ + +/-- The complete global constructor-minor telescope is well formed beneath +all mutual motives. -/ +theorem minorTypes_onTel : + env.OnTel gen.recUvars + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse) + gen.minorTypes := by + simpa [BlockGenerationChecked.minorTypes] using + S.minorTypesAux_onTel gen.flatCtors + (fun _ h => h) [] 0 rfl + +theorem idxTel_onTel {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.OnTel gen.recUvars gen.paramsTel.reverse + (gen.idxTel family) := by + have h := (S.generationFamily_onTel hfamily).instL + (U' := gen.recUvars) gen.sourceLevels_wf + have h' : env.OnTel gen.recUvars [] + (gen.paramsTel ++ gen.idxTel family) := by + simpa [BlockGenerationChecked.paramsTel, + BlockGenerationChecked.idxTel] using h + simpa using h'.of_append.2 + +/-- Transport a selected family applied to its index self-spine beneath +arbitrary middle and top binders. -/ +theorem familyApp_transport {family : NormalizedFamily} + (hfamily : family ∈ gen.families) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.HasType gen.recUvars + (As₂ ++ + ((VExpr.liftTelN g (gen.idxTel family) 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (d + (g + (gen.idxTel family).length)) source.nparams ++ + VExpr.bvarRevRange d (gen.idxTel family).length)) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + have W₁ := Ctx.LiftN.consTel (n := mid.length) (gen.idxTel family) + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [Nat.add_zero] at W₁ + have h₁ := (S.familyApp_hasType hfamily).weakN S.ord W₁ + rw [hg] at h₁ + have hmid : env.HasType gen.recUvars + ((VExpr.liftTelN g (gen.idxTel family) 0).reverse ++ + (mid ++ gen.paramsTel.reverse)) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (g + (gen.idxTel family).length) source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + simpa [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + VExpr.bvarRevRange_liftN_high + (gen.idxTel family).length 0 g (gen.idxTel family).length + (by omega), + VExpr.liftN] using h₁ + have htop := hmid.weakN S.ord + (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + simpa [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.liftN, List.append_assoc] using htop + +/-- The generated recursor type for every selected mutual family is well +formed over the empty context. -/ +theorem recType_isType {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + env.IsType gen.recUvars [] (gen.recType family) := by + let d := gen.familyCount + let k := gen.minorCount + let q := family.view.ordinal + let Is := gen.idxTel family + let ni := Is.length + let LiftedIs := VExpr.liftTelN (d + k) Is 0 + let A := VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (ni + d + k) source.nparams ++ + VExpr.bvarRevRange 0 ni) + let Base := gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse) + let Γ := A :: (LiftedIs.reverse ++ Base) + let K := d - 1 - q + k + ni + 1 + refine VEnv.IsType.forallN S.paramsTel_onTel ?_ + simp only [List.append_nil] + refine VEnv.IsType.forallN S.motiveTypes_onTel ?_ + refine VEnv.IsType.forallN S.minorTypes_onTel ?_ + have hdk : + (gen.minorTypes.reverse ++ gen.motiveTypes.reverse).length = d + k := by + simp only [List.length_append, List.length_reverse, + gen.minorTypes_length, gen.motiveTypes_length] + dsimp only [d, k] + omega + have hI : env.OnTel gen.recUvars Base LiftedIs := by + have h := (S.idxTel_onTel hfamily).weakN S.ord + (Ctx.LiftN.zero (n := d + k) + (Γ := gen.paramsTel.reverse) + (gen.minorTypes.reverse ++ gen.motiveTypes.reverse) + (h := hdk)) + simpa [Base, LiftedIs, Is, List.append_assoc] using h + refine VEnv.IsType.forallN hI ?_ + have hmaj₀ := S.familyApp_transport hfamily + (gen.minorTypes.reverse ++ gen.motiveTypes.reverse) + (g := d + k) hdk [] (d := 0) rfl + rw [VExpr.bvarRevRange_congr source.nparams + (show 0 + (d + k + Is.length) = ni + d + k by + dsimp only [ni] + omega)] at hmaj₀ + have hmaj : env.HasType gen.recUvars + (LiftedIs.reverse ++ Base) A + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + simpa [A, Base, LiftedIs, Is, List.append_assoc] using hmaj₀ + refine VEnv.IsType.forallE ⟨_, hmaj⟩ ?_ + have hILen : LiftedIs.length = ni := by + simp [LiftedIs, ni, VExpr.liftTelN_length] + have hq : q < d := by + simpa [q, d] using gen.family_ordinal_lt hfamily + have hd : gen.motiveTypes.length = d := by + simpa [d] using gen.motiveTypes_length + have hmot : gen.motiveTypes.reverse[d - 1 - q]? = + some ((gen.motiveType family).liftN q) := by + rw [List.getElem?_reverse (by rw [hd]; omega), + show gen.motiveTypes.length - 1 - (d - 1 - q) = q from by + rw [hd] + omega, + gen.motiveTypes_getElem?_ordinal hfamily] + have hM0 := getElem?_rstack_mid + ([A] ++ LiftedIs.reverse ++ gen.minorTypes.reverse) + gen.motiveTypes.reverse gen.paramsTel.reverse + (i := K) + (by + simp only [List.length_append, List.length_singleton, + List.length_reverse, hILen, gen.minorTypes_length] + dsimp only [K, q, d, k, ni, Is] + omega) + (by + simp only [List.length_append, List.length_singleton, + List.length_reverse, hILen, gen.minorTypes_length] + rw [hd] + dsimp only [K, q, d, k, ni, Is] + omega) + have hdiff : + K - ([A] ++ LiftedIs.reverse ++ gen.minorTypes.reverse).length = + d - 1 - q := by + simp only [List.length_append, List.length_singleton, + List.length_reverse, hILen, gen.minorTypes_length] + dsimp only [K, q, d, k, ni, Is] + omega + rw [hdiff, hmot] at hM0 + have hMget : Γ[K]? = + some ((gen.motiveType family).liftN q) := by + simpa [Γ, Base, List.append_assoc] using hM0 + have hmlu := Lookup.of_getElem? hMget + rw [show ((gen.motiveType family).liftN q).liftN (K + 1) = + ((gen.motiveType family).liftN (d + k)).liftN (ni + 1) from by + rw [VExpr.liftN_liftN, VExpr.liftN_liftN] + congr 1 + dsimp only [K, q, d, k] + omega, + gen.motiveType_liftN family] at hmlu + have hfun : env.HasType gen.recUvars Γ (.bvar K) + ((VExpr.forallN LiftedIs + (.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (d + k + ni) source.nparams ++ + VExpr.bvarRevRange 0 ni)) + (.sort gen.motiveLevel))).liftN + (1 + LiftedIs.length)) := by + exact .bvar (by + simpa [Γ, Base, LiftedIs, Is, ni, + VExpr.liftTelN_length, List.append_assoc, + Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using hmlu) + have hMapp := VEnv.HasType.appN_selfSpine + (As := LiftedIs) + (Δ := [A]) + (Γ := Base) + (f := .bvar K) hfun + have hMapp' : env.HasType gen.recUvars Γ + ((VExpr.bvar K).appN (VExpr.bvarRevRange 1 ni)) + (.forallE (A.liftN 1) (.sort gen.motiveLevel)) := by + simpa [Γ, Base, A, LiftedIs, Is, ni, hILen, + VExpr.liftN, List.append_assoc, + Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using hMapp + have h0 : Γ[0]? = some A := rfl + have harg := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) + (Lookup.of_getElem? h0) + have harg' : env.HasType gen.recUvars Γ (.bvar 0) (A.liftN 1) := by + simpa [Γ, List.append_assoc] using harg + have happ := VEnv.HasType.app hMapp' harg' + exact ⟨gen.motiveLevel, by + simpa [BlockGenerationChecked.recType, + Γ, Base, A, LiftedIs, Is, ni, d, k, q, K, + VExpr.liftTelN_length, VExpr.inst, List.append_assoc, + Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using happ⟩ + +/-- Every family-selected mutual recursor constant is well formed in the +environment containing the complete raw block. -/ +theorem recursor_wf {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + (gen.recursor family).WF env := + S.recType_isType hfamily + +theorem recType_levelWF {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + (gen.recType family).LevelWF gen.recUvars := by + obtain ⟨_, h⟩ := S.recType_isType hfamily + exact (h.levelWF trivial).1 + +theorem recType_closedN {family : NormalizedFamily} + (hfamily : family ∈ gen.families) : + (gen.recType family).ClosedN 0 := by + obtain ⟨_, h⟩ := S.recType_isType hfamily + exact VExpr.WF.closedN S.ord ⟨_, h⟩ trivial + +/-- The selected family recursor constant has its generated mutual recursor +type in every local context. -/ +theorem recursor_hasType {family : NormalizedFamily} + (hfamily : family ∈ gen.families) + (hrec : env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) {Γ : List VExpr} : + env.HasType gen.recUvars Γ + (.const (.str family.raw.name "rec") gen.recLevels) + (gen.recType family) := by + have h := VEnv.HasType.const (Γ := Γ) hrec + VLevel.params_wf VLevel.params_length + rw [show (gen.recursor family).uvars = gen.recUvars from rfl, + show (gen.recursor family).type = gen.recType family from rfl] at h + rwa [(S.recType_levelWF hfamily).instL_id] at h + +/-- Applying a selected recursor to the shared parameters, motives, and +flattened minors exposes its index-and-major spine. -/ +theorem recBase_hasType {family : NormalizedFamily} + (hfamily : family ∈ gen.families) + (hrec : env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) + (Δ : List VExpr) : + env.HasType gen.recUvars + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (gen.recBase Δ.length family.view.ordinal) + ((VExpr.forallN + (VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (gen.idxTel family) 0) + (.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.app + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length)) + (.bvar 0)))).liftN Δ.length) := by + have hf : env.HasType gen.recUvars + (Δ ++ + (gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes).reverse ++ []) + (.const (.str family.raw.name "rec") gen.recLevels) + ((VExpr.forallN + (gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes) + (VExpr.forallN + (VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (gen.idxTel family) 0) + (.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.app + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length)) + (.bvar 0))))).liftN + (Δ.length + + (gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes).length)) := by + rw [show VExpr.forallN + (gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes) + (VExpr.forallN + (VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (gen.idxTel family) 0) + (.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.app + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length)) + (.bvar 0)))) = gen.recType family from by + rw [VExpr.forallN_append, VExpr.forallN_append] + rfl, + (S.recType_closedN hfamily).liftN_eq (Nat.zero_le _)] + exact S.recursor_hasType hfamily hrec + have hspine := VEnv.HasType.appN_selfSpine + (env := env) (U := gen.recUvars) hf + simp only [List.reverse_append, List.append_nil, List.append_assoc, List.length_append, + gen.minorTypes_length, gen.motiveTypes_length] at hspine + rw [show gen.paramsTel.length = source.nparams from by + simpa [BlockGenerationChecked.paramsTel] using + S.generationParams_length, + VExpr.bvarRevRange_congr' Δ.length + (show source.nparams + (gen.familyCount + gen.minorCount) = + source.nparams + gen.familyCount + gen.minorCount by omega)] at hspine + simpa [BlockGenerationChecked.recBase, + gen.familyNameAt_ordinal hfamily, + List.append_assoc] using hspine + +/-- Applying a selected family recursor to indices and a major premise +returns the correspondingly selected motive application. -/ +theorem recApp_hasType {family : NormalizedFamily} + (hfamily : family ∈ gen.families) + (hrec : env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) + (Δ : List VExpr) {idxs : List VExpr} {a : VExpr} + (hidx : env.SpineWF gen.recUvars + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + (Δ.length + gen.familyCount + gen.minorCount) + (gen.idxTel family) 0) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels))) + idxs (.sort (gen.validated.resultLevel.inst gen.sourceLevels))) + (hlen : idxs.length = (gen.idxTel family).length) + (ha : env.HasType gen.recUvars + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + a + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (Δ.length + gen.familyCount + gen.minorCount) + source.nparams ++ idxs))) : + env.HasType gen.recUvars + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (VExpr.appN (gen.recBase Δ.length family.view.ordinal) + (idxs ++ [a])) + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + Δ.length)) + (idxs ++ [a])) := by + have hq := gen.family_ordinal_lt hfamily + have hb := S.recBase_hasType hfamily hrec Δ + rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ + (show gen.familyCount + gen.minorCount + Δ.length = + Δ.length + gen.familyCount + gen.minorCount by omega)] at hb + have hcod : + (VExpr.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.app + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length)) + (.bvar 0))).liftN Δ.length + (0 + (VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (gen.idxTel family) 0).length) = + VExpr.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + Δ.length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.app + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + + Δ.length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length)) + (.bvar 0)) := by + rw [VExpr.liftTelN_length, Nat.zero_add] + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + VExpr.bvarRevRange_congr source.nparams + (show Δ.length + + ((gen.idxTel family).length + + gen.familyCount + gen.minorCount) = + (gen.idxTel family).length + Δ.length + + gen.familyCount + gen.minorCount by omega)] + rfl + · show VExpr.app _ _ = VExpr.app _ _ + congr 1 + · rw [VExpr.liftN_appN, + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + show VExpr.appN + (.bvar (liftVar Δ.length + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + 1) + ((gen.idxTel family).length + 1))) _ = _ + rw [liftVar_le (by omega)] + congr 1 + ac_rfl + rw [hcod] at hb + have hshape := hidx.retarget + (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + Δ.length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)) + (.sort gen.motiveLevel)) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ + (C := .const family.raw.name gen.sourceLevels) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ + (by rw [hlen]; omega), + show (gen.idxTel family).length + Δ.length + + gen.familyCount + gen.minorCount - idxs.length = + Δ.length + gen.familyCount + gen.minorCount from by + rw [hlen] + omega, + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hfull := hshape.snoc ha + simp only [VExpr.inst] at hfull + change env.SpineWF gen.recUvars _ + (VExpr.forallN + (VExpr.liftTelN + (Δ.length + gen.familyCount + gen.minorCount) + (gen.idxTel family) 0) + (VExpr.forallN + [VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + Δ.length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)] + (.sort gen.motiveLevel))) + (idxs ++ [a]) (.sort gen.motiveLevel) at hfull + rw [← VExpr.forallN_append] at hfull + have hfullLen : (idxs ++ [a]).length = + (VExpr.liftTelN + (Δ.length + gen.familyCount + gen.minorCount) + (gen.idxTel family) 0 ++ + [VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((gen.idxTel family).length + Δ.length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.idxTel family).length)]).length := by + simp only [List.length_append, List.length_singleton, + VExpr.liftTelN_length, hlen] + have hactual := hfull.retarget hfullLen + (VExpr.app + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + + Δ.length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length)) + (.bvar 0)) + rw [VExpr.forallN_append] at hactual + have happ := hactual.hasType_appN hb + rw [show VExpr.app + (VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + + Δ.length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length)) + (.bvar 0) = + VExpr.appN + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + + Δ.length + 1)) + (VExpr.bvarRevRange 0 ((gen.idxTel family).length + 1)) from by + rw [VExpr.bvarRevRange_congr' 0 + (show (gen.idxTel family).length + 1 = + 1 + (gen.idxTel family).length by omega), + ← VExpr.bvarRevRange_append (gen.idxTel family).length 1] + simpa [VExpr.bvarRevRange, VExpr.appN] using + (VExpr.appN_append + (.bvar + (gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + + Δ.length + 1)) + (VExpr.bvarRevRange 1 (gen.idxTel family).length) + [VExpr.bvar 0]).symm, + VExpr.instRev_appN, + VExpr.instRev_bvar_ge _ (by + simp only [List.length_append, List.length_singleton] + rw [hlen] + omega), + VExpr.bvarRevRange_congr' 0 + (show (gen.idxTel family).length + 1 = + (idxs ++ [a]).length by simp [hlen]), + VExpr.map_instRev_bvarRevRange] at happ + rw [show gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + (gen.idxTel family).length + Δ.length + 1 - + (idxs ++ [a]).length = + gen.familyCount - 1 - family.view.ordinal + + gen.minorCount + Δ.length from by + simp only [List.length_append, List.length_singleton] + rw [hlen] + omega] at happ + simpa [List.length_append, hlen, + BlockGenerationChecked.recBase, + gen.familyNameAt_ordinal hfamily] using happ + +/-- The constructor application appearing in a mutual rule has the selected +owner-family application as its type. -/ +theorem ctorAppRule_hasType + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + {family : NormalizedFamily} (_hfamily : family ∈ gen.families) + (hname : family.raw.name = constructor.familyName) : + env.HasType gen.recUvars + ((VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) + (VExpr.appN (.const family.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + (constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + e.liftN (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) := by + have h := S.ctorApp_transport hconstructor hname + (gen.minorTypes.reverse ++ gen.motiveTypes.reverse) + (g := gen.familyCount + gen.minorCount) + (by + simp only [List.length_append, List.length_reverse, + gen.minorTypes_length, gen.motiveTypes_length] + omega) + [] (d := 0) rfl + rw [VExpr.bvarRevRange_congr source.nparams + (show + 0 + (gen.familyCount + gen.minorCount + + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length) = + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + + gen.familyCount + gen.minorCount by omega)] at h + simpa [List.append_assoc] using h + +/-- Parameters, every motive, every flattened minor, and the selected +constructor fields form the binder telescope of a mutual rule. -/ +theorem ruleBinders_onTel + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) : + env.OnTel gen.recUvars [] + (gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes ++ + VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0) := by + have hF₀ := S.fields_onTel_minor hconstructor + have hF := hF₀.weakN S.ord + (Ctx.LiftN.zero + (Γ := gen.motiveTypes.reverse ++ gen.paramsTel.reverse) + gen.minorTypes.reverse) + rw [VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ + (show gen.familyCount + gen.minorTypes.reverse.length = + gen.familyCount + gen.minorCount by + simp only [List.length_reverse, gen.minorTypes_length])] at hF + refine OnTel.append + (OnTel.append + (OnTel.append S.paramsTel_onTel + (by simpa only [List.append_nil] using S.motiveTypes_onTel)) + (by simpa only [List.append_nil, List.reverse_append, + List.append_assoc] using S.minorTypes_onTel)) ?_ + simpa only [List.append_nil, List.append_assoc, + List.reverse_append] using hF + +/-- The constructor-headed left side of a mutual iota rule has the owner +motive application as its type. -/ +theorem recRuleApp_hasType + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + (hrecs : ∀ family ∈ gen.families, + env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) : + env.HasType gen.recUvars + ((VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (VExpr.appN + (gen.recBase + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length constructor.owner) + (((constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + e.liftN (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length) ++ + [VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)])) + (VExpr.appN + (.bvar + (gen.familyCount - 1 - constructor.owner + + gen.minorCount + + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) + (((constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + e.liftN (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length) ++ + [VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + + gen.familyCount + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)])) := by + obtain ⟨family, hfamily, howner, hname, hindices⟩ := + (S.ctorWF constructor hconstructor).owner + let Bs := constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination + let common := gen.familyCount + gen.minorCount + let mid := gen.minorTypes.reverse ++ gen.motiveTypes.reverse + have hmid : mid.length = common := by + simp only [mid, common, List.length_append, List.length_reverse, + gen.minorTypes_length, gen.motiveTypes_length] + omega + have hSp₀ := S.result_transport hconstructor hfamily hindices + mid hmid [] (d := 0) rfl + have hSp : env.SpineWF gen.recUvars + ((VExpr.liftTelN common Bs 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN (Bs.length + common) + (gen.idxTel family) 0) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels))) + ((constructor.ctor.resultIndicesR source.uvars gen.elimination).map + fun e => e.liftN common Bs.length) + (.sort (gen.validated.resultLevel.inst gen.sourceLevels)) := by + simpa [Bs, common, mid, List.append_assoc, + Nat.add_assoc] using hSp₀ + have hidxLen : + ((constructor.ctor.resultIndicesR source.uvars gen.elimination).map + fun e => e.liftN common Bs.length).length = + (gen.idxTel family).length := by + have hlen := hSp.forallN_sort_length + simpa only [VExpr.liftTelN_length] using hlen + have ha := S.ctorAppRule_hasType hconstructor hfamily hname + have hout := S.recApp_hasType hfamily (hrecs family hfamily) + (VExpr.liftTelN common Bs 0).reverse + (by simpa [common, List.length_reverse, VExpr.liftTelN_length, + Nat.add_assoc] using hSp) + hidxLen + (by simpa only [Bs, common, List.length_reverse, + VExpr.liftTelN_length] using ha) + simpa only [Bs, common, howner, List.length_reverse, + VExpr.liftTelN_length] using hout + +/-- Every recursive field contributes a well-typed rule call to the +recursor selected by that field's certified target family. -/ +theorem blockRuleCall_hasType + {constructor : NormalizedBlockCtor} + (hconstructor : constructor ∈ gen.flatCtors) + (hrecs : ∀ family ∈ gen.families, + env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) + {r : RecArg} + (hr : r ∈ constructor.ctor.recArgsR source.uvars gen.elimination) : + env.HasType gen.recUvars + ((VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (BlockGenerationChecked.blockRuleCall + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + (gen.recBase + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length r.targetType) r) + (BlockGenerationChecked.blockRuleIH + gen.familyCount gen.minorCount + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length r) := by + obtain ⟨r₀, hr₀, rfl⟩ := NormalizedCtor.recArgsR_mem hr + obtain ⟨family, hfamily, hord, ⟨Bview, hBview, hshape⟩, hsem⟩ := + (S.ctorWF constructor hconstructor).recursive r₀ hr₀ + let ls := gen.sourceLevels + let r := r₀.instL ls + let d := gen.familyCount + let k := gen.minorCount + let common := d+k + let Bs := constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination + let m := Bs.length + let j := r₀.fieldIndex + let Fs := VExpr.liftTelN common Bs 0 + let As := BlockGenerationChecked.blockRuleBinders common m r + let idxs := r.indices.map fun e => + (e.liftN common (r.fieldIndex+r.binders.length)).liftN + (m-r.fieldIndex) r.binders.length + let Γ := Fs.reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) + have hjview : r₀.fieldIndex < constructor.ctor.view.fields.length := + (List.getElem?_eq_some_iff.1 hBview).1 + have hjm : j < m := by + have hfields := gen.flatCtor_fields_length hconstructor + simp only [j, m, Bs, NormalizedCtor.fieldsR_length] + omega + have hjraw : r₀.fieldIndex < + (constructor.ctor.rawFields source.nparams).length := by + simpa [j, m, Bs, NormalizedCtor.fieldsR_length] using hjm + let Braw := + (constructor.ctor.rawFields source.nparams)[r₀.fieldIndex] + have hBraw : + (constructor.ctor.rawFields source.nparams)[r₀.fieldIndex]? = + some Braw := + List.getElem?_eq_getElem hjraw + have hcommon : + (gen.minorTypes.reverse ++ gen.motiveTypes.reverse).length = + common := by + simp only [List.length_append, List.length_reverse, + gen.minorTypes_length, gen.motiveTypes_length] + dsimp only [common, d, k] + omega + have hFsLen : Fs.length = m := by + simp [Fs, m, VExpr.liftTelN_length] + have ht := S.recArg_transport hconstructor hfamily hsem hjview + (gen.minorTypes.reverse ++ gen.motiveTypes.reverse) hcommon + (Fs.drop j).reverse (d := m-j) (by + simp only [List.length_reverse, List.length_drop, hFsLen]) + dsimp only [r, j, RecArg.instL] at ht + have hctx : + (Fs.drop j).reverse ++ + ((VExpr.liftTelN common (Bs.take j) 0).reverse ++ + ((gen.minorTypes.reverse ++ gen.motiveTypes.reverse) ++ + gen.paramsTel.reverse)) = Γ := by + dsimp only [Γ, Fs] + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc + (((VExpr.liftTelN common Bs 0).drop j).reverse), + ← List.reverse_append, List.take_append_drop, + ← List.append_assoc] + have htel : env.OnTel gen.recUvars Γ As := by + rw [hctx] at ht + simpa [r, As, m, common, j, RecArg.instL, + BlockGenerationChecked.blockRuleBinders] using ht.1 + have hsp : env.SpineWF gen.recUvars + (As.reverse ++ Γ) + (VExpr.forallN + (VExpr.liftTelN + (m + r.binders.length + common) + (gen.idxTel family) 0) + (.sort (gen.validated.resultLevel.inst ls))) + idxs + (.sort (gen.validated.resultLevel.inst ls)) := by + rw [hctx] at ht + simpa [r, As, idxs, m, common, j, ls, + RecArg.instL, BlockGenerationChecked.blockRuleBinders, + List.append_assoc, + show j + r₀.binders.length + common + (m-j) = + m + r₀.binders.length + common by omega] using ht.2 + have hF : Γ[m-1-j]? = + some ((Braw.instL ls).liftN common j) := by + dsimp only [Γ, Fs] + rw [List.getElem?_append_left + (by + simp only [List.length_reverse, VExpr.liftTelN_length] + omega), + List.getElem?_reverse (by rw [hFsLen]; omega), + VExpr.liftTelN_length, + show m - 1 - (m - 1 - j) = j by omega, + VExpr.liftTelN_getElem?, + NormalizedCtor.fieldsR_getElem?, hBraw] + simp [ls] + have hlu := Lookup.of_getElem? hF + rw [show m-1-j+1 = m-j by omega] at hlu + dsimp only [j, r] at hlu + have hf0 := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) hlu + obtain ⟨u, hdom₀⟩ := + S.emittedField_defeq hconstructor hBraw hBview + have hdom₁ := hdom₀.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hdomChecked : env.IsDefEq gen.recUvars + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination |>.take r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (Braw.instL ls) (Bview.instL ls) ((VExpr.sort u).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse, List.map_take] using hdom₁ + have hprefix := + S.generationFieldPrefix_ctx_rec hconstructor r₀.fieldIndex + have hdomGeneration := hdomChecked.defeqDFC S.ord + (hprefix.symm S.ord) + have hjlen : (Bs.take r₀.fieldIndex).length = + r₀.fieldIndex := by + simp only [Bs, NormalizedCtor.fieldsR, + List.length_take, List.length_map] + omega + have Wmid := Ctx.LiftN.consTel (n := common) + (Bs.take r₀.fieldIndex) + (Ctx.LiftN.zero (n := common) (Γ := gen.paramsTel.reverse) + (gen.minorTypes.reverse ++ gen.motiveTypes.reverse) + (h := hcommon)) + rw [hjlen, Nat.add_zero] at Wmid + have hdom₂ := hdomGeneration.weakN S.ord Wmid + have Wstack := Ctx.LiftN.zero (n := m-j) + (Γ := (VExpr.liftTelN common (Bs.take j) 0).reverse ++ + ((gen.minorTypes.reverse ++ gen.motiveTypes.reverse) ++ + gen.paramsTel.reverse)) + (Fs.drop j).reverse + (h := by + simp only [List.length_reverse, List.length_drop, hFsLen]) + have hdom₃ := hdom₂.weakN S.ord Wstack + rw [hctx] at hdom₃ + have hfView := hdom₃.defeq hf0 + have hfield := blockMinor_fieldType_of_eq hshape common m 0 + (by simpa [j] using hjm) gen.elimination + simp only [RecArg.instL] at hfield + dsimp only [j] at hfView + simp only [Nat.add_zero] at hfield + rw [hfield] at hfView + have hf := hfView.weakN S.ord + (Ctx.LiftN.zero (Γ := Γ) As.reverse) + have hmajor := VEnv.HasType.appN_selfSpine + (env := env) (U := gen.recUvars) + (As := As) + (B := VExpr.appN (.const family.raw.name ls) + (VExpr.bvarRevRange + (m + r.binders.length + common) source.nparams ++ idxs)) + (Δ := []) (Γ := Γ) (by + simpa [As, r, idxs, j, common, ls, RecArg.instL, + BlockGenerationChecked.blockRuleBinders, + BlockGenerationChecked.blockMinorBinders, + List.length_reverse, List.map_map, + Function.comp_def] using hf) + simp only [List.length_nil, VExpr.liftN_zero, + List.nil_append] at hmajor + have hAsLen : As.length = r.binders.length := by + simp [As, BlockGenerationChecked.blockRuleBinders, + VExpr.liftTelN_length] + have hmajor' : env.HasType gen.recUvars (As.reverse ++ Γ) + ((VExpr.bvar (m-1-r.fieldIndex+As.length)).appN + (VExpr.bvarRevRange 0 As.length)) + (VExpr.appN (.const family.raw.name ls) + (VExpr.bvarRevRange + (m+r.binders.length+common) source.nparams ++ idxs)) := by + simpa [As, common, r, RecArg.instL, + BlockGenerationChecked.blockRuleBinders, + VExpr.liftN, liftVar_le, Nat.add_comm] using hmajor + rw [hAsLen] at hmajor' + have hlen : idxs.length = (gen.idxTel family).length := by + have hidx := hsem.2.forallN_sort_length + simp only [idxs, List.length_map, VExpr.liftTelN_length, + BlockGenerationChecked.idxTel] at hidx ⊢ + simpa [r, RecArg.instL] using hidx.trans + (gen.shape.2.2.2.2 family hfamily).2.2.2.1.symm + have hcall := S.recApp_hasType hfamily (hrecs family hfamily) + (As.reverse ++ Fs.reverse) + (by + simpa [Γ, List.append_assoc, hAsLen, hFsLen, + common, d, k, + Nat.add_comm, Nat.add_left_comm, + Nat.add_assoc] using hsp) + hlen + (by + simpa [Γ, List.append_assoc, hAsLen, hFsLen, + common, d, k, + Nat.add_comm, Nat.add_left_comm, + Nat.add_assoc] using hmajor') + have hbaseLift : + (gen.recBase m r.targetType).liftN r.binders.length = + gen.recBase (m+r.binders.length) r.targetType := by + simp only [BlockGenerationChecked.recBase, VExpr.liftN_appN, VExpr.liftN] + rw [bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _)] + apply congrArg (VExpr.appN _) + apply VExpr.bvarRevRange_congr + omega + have hlam := HasType.lamN htel (by + simpa [Γ, Fs, hAsLen, hFsLen, hbaseLift, + List.append_assoc, hord, r, RecArg.instL, + common, d, k, + Nat.add_comm, Nat.add_left_comm, + Nat.add_assoc] using hcall) + have hrecPos : r₀.binders.length + m = m + r₀.binders.length := by + omega + have hfieldPos : + r₀.binders.length + (m-1-r₀.fieldIndex) = + m-1-r₀.fieldIndex+r₀.binders.length := by + omega + have hmotivePos : + r₀.binders.length + + (gen.familyCount - 1 - r₀.targetType + (gen.minorCount+m)) = + gen.familyCount - 1 - r₀.targetType + gen.minorCount + m + + r₀.binders.length := by + ac_rfl + rw [hrecPos, hfieldPos, hmotivePos] at hlam + change env.HasType gen.recUvars Γ + (BlockGenerationChecked.blockRuleCall common m + (gen.recBase m r.targetType) r) + (VExpr.forallN As + (VExpr.appN + (.bvar (d - 1 - r.targetType + k + m + r.binders.length)) + (idxs ++ + [VExpr.appN + (.bvar (m - 1 - r.fieldIndex + r.binders.length)) + (VExpr.bvarRevRange 0 r.binders.length)]))) + have hcallEq : + BlockGenerationChecked.blockRuleCall common m + (gen.recBase m r.targetType) r = + VExpr.lamN As + (VExpr.appN + (gen.recBase (m+r.binders.length) r.targetType) + (idxs ++ + [VExpr.appN + (.bvar (m-1-r.fieldIndex+r.binders.length)) + (VExpr.bvarRevRange 0 r.binders.length)])) := by + simp [BlockGenerationChecked.blockRuleCall, As, idxs, hbaseLift] + rw [hcallEq] + simpa [r, RecArg.instL, List.length_map] using hlam + +/-- The selected flattened mutual minor applied to its fields and routed +recursive calls has the owner's motive as its result. -/ +theorem minorApp_hasType {i : Nat} + {constructor : NormalizedBlockCtor} + (hci : gen.flatCtors[i]? = some constructor) + (hrecs : ∀ family ∈ gen.families, + env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) : + env.HasType gen.recUvars + ((VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse))) + (VExpr.appN + (.bvar + (gen.minorCount - 1 - i + + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) + (VExpr.bvarRevRange 0 + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length ++ + (constructor.ctor.recArgsR source.uvars gen.elimination).map + fun r => + BlockGenerationChecked.blockRuleCall + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + (gen.recBase + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length r.targetType) r)) + (VExpr.appN + (.bvar + (gen.familyCount - 1 - constructor.owner + gen.minorCount + + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)) + (((constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + e.liftN (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length) ++ + [VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + ((constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length + gen.familyCount + + gen.minorCount) + source.nparams ++ + VExpr.bvarRevRange 0 + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination).length)])) := by + obtain ⟨hik, -⟩ := List.getElem?_eq_some_iff.1 hci + have hconstructor := List.mem_of_getElem? hci + obtain ⟨family, hfamily, howner, -, -⟩ := + (S.ctorWF constructor hconstructor).owner + let d := gen.familyCount + let k := gen.minorCount + let common := d+k + let Bs := constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination + let m := Bs.length + let rs := constructor.ctor.recArgsR source.uvars gen.elimination + let Fs := VExpr.liftTelN common Bs 0 + let D := VExpr.appN + (.bvar (d - 1 - constructor.owner + m + rs.length)) + (((constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => + (e.liftN d m).liftN rs.length) ++ + [VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (rs.length+m+d) source.nparams ++ + VExpr.bvarRevRange rs.length m)]) + let Dfin := VExpr.appN + (.bvar (d - 1 - constructor.owner + k + m)) + (((constructor.ctor.resultIndicesR source.uvars + gen.elimination).map fun e => e.liftN common m) ++ + [VExpr.appN + (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange (m+common) source.nparams ++ + VExpr.bvarRevRange 0 m)]) + have hownerLt : constructor.owner < d := by + rw [← howner] + simpa [d] using gen.family_ordinal_lt hfamily + have hrsLt : ∀ r ∈ rs, r.fieldIndex < m := by + intro r hr + obtain ⟨r₀, hr₀, rfl⟩ := + NormalizedCtor.recArgsR_mem (show + r ∈ constructor.ctor.recArgsR source.uvars gen.elimination from + by simpa [rs] using hr) + obtain ⟨family₀, hfamily₀, htarget, + ⟨Bview, hfield, hshape⟩, hsem⟩ := + (S.ctorWF constructor hconstructor).recursive r₀ hr₀ + have hj := (List.getElem?_eq_some_iff.1 hfield).1 + simp only [RecArg.instL] + dsimp only [m, Bs] + rw [NormalizedCtor.fieldsR_length] + rw [gen.flatCtor_fields_length hconstructor] + exact hj + have hik' : i < k := by + simpa [k] using hik + rw [VExpr.appN_append] + have hminorAt : + gen.minorTypes[i]? = + some ((gen.minorType constructor).liftN i) := by + simpa [BlockGenerationChecked.minorTypes, hci] using + (gen.minorTypesAux_getElem? gen.flatCtors 0 i) + have hlu0 : + (Fs.reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)))[ + k - 1 - i + m]? = + some ((gen.minorType constructor).liftN i) := by + rw [getElem?_rstack_mid _ _ _ + (by simp [Fs, m, VExpr.liftTelN_length] <;> omega) + (by simp [Fs, m, k, gen.minorTypes_length, + VExpr.liftTelN_length] <;> omega), + show k - 1 - i + m - Fs.reverse.length = k - 1 - i by + simp [Fs, m, VExpr.liftTelN_length], + List.getElem?_reverse (by + rw [gen.minorTypes_length] + omega), + show gen.minorTypes.length - 1 - (k - 1 - i) = i by + rw [gen.minorTypes_length] + dsimp only [k] + omega, + hminorAt] + have hlu := Lookup.of_getElem? hlu0 + rw [VExpr.liftN_liftN, + show i + (k - 1 - i + m + 1) = m+k by omega] at hlu + have hminorEq : + (gen.minorType constructor).liftN (m+k) = + (VExpr.forallN Fs + ((VExpr.forallN + (BlockGenerationChecked.blockIHsFromRecArgs d m rs 0) + D).liftN k m)).liftN m := by + simp only [BlockGenerationChecked.minorType] + conv => lhs; rw [VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ + (show d + (m+k) = common+m by + dsimp only [common] + omega), + show 0 + (VExpr.liftTelN d Bs 0).length = m by + simp [m, VExpr.liftTelN_length]] + conv => rhs; rw [VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN, + show 0 + Fs.length = m by + simp [Fs, m, VExpr.liftTelN_length], + VExpr.liftN'_liftN_hi, + Nat.add_comm k m] + have hfields := HasType.appN_selfSpine + (env := env) (U := gen.recUvars) + (As := Fs) + (B := (VExpr.forallN + (BlockGenerationChecked.blockIHsFromRecArgs d m rs 0) + D).liftN k m) + (Δ := []) + (Γ := gen.minorTypes.reverse ++ + (gen.motiveTypes.reverse ++ gen.paramsTel.reverse)) + (f := .bvar (k-1-i+m)) + (by + have hb := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) hlu + rw [hminorEq] at hb + simpa [Fs, VExpr.liftTelN_length] using hb) + simp only [List.length_nil, VExpr.liftN_zero] at hfields + rw [BlockGenerationChecked.blockIHs_liftN' + d m k rs hrsLt 0 D (cut := m) rfl] at hfields + have hD : D.liftN k (m+0+rs.length) = + Dfin.liftN rs.length := by + dsimp only [D, Dfin] + rw [VExpr.liftN_appN, VExpr.liftN_appN, + List.map_append, List.map_append, + List.map_map, List.map_map] + show VExpr.appN _ (_ ++ [_]) = VExpr.appN _ (_ ++ [_]) + congr 1 + · show + VExpr.bvar + (liftVar k + (d - 1 - constructor.owner + m + rs.length) + (m+0+rs.length)) = + VExpr.bvar + (liftVar rs.length + (d - 1 - constructor.owner + k + m) 0) + rw [liftVar_le (by omega), liftVar_le (Nat.zero_le _)] + congr 1 + omega + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + rw [show m+0+rs.length = m+rs.length by omega, + VExpr.liftN_liftN_midN e d k rs.length (Nat.zero_le _)] + · congr 1 + simp only [] + rw [show m+0+rs.length = m+rs.length by omega, + VExpr.liftN_appN, VExpr.liftN_appN, + List.map_append, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.bvarRevRange_congr source.nparams + (show k + (rs.length+m+d) = + rs.length + (m+common) by + dsimp only [common] + omega), + VExpr.bvarRevRange_congr m + (show rs.length = rs.length+0 by omega)] + rfl + rw [hD] at hfields + have hres := hasType_appN_blockRuleIHs + (env := env) (gen := gen) (d := d) (m := m) (k := k) + (rs := rs) + (argOf := fun r => + BlockGenerationChecked.blockRuleCall common m + (gen.recBase m r.targetType) r) + (Dfin := Dfin) + (fun r hr => by + simpa [d, k, common, m, Bs] using + S.blockRuleCall_hasType hconstructor hrecs + (show r ∈ constructor.ctor.recArgsR source.uvars + gen.elimination by simpa [rs] using hr)) + hfields + simpa [Fs, Bs, m, rs, d, k, common, Dfin, + VExpr.liftTelN_length, Nat.add_assoc] using hres + +/-- Every flattened mutual iota rule is well formed once all family +recursors are available. -/ +theorem rule_WF {i : Nat} + {constructor : NormalizedBlockCtor} + (hci : gen.flatCtors[i]? = some constructor) + (hrecs : ∀ family ∈ gen.families, + env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) : + (gen.rule i constructor).WF env := by + have hconstructor := List.mem_of_getElem? hci + refine ⟨?_, ?_⟩ + · show env.HasType gen.recUvars [] + (VExpr.lamN + (gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes ++ + VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0) + _) + (VExpr.forallN _ _) + refine HasType.lamN (S.ruleBinders_onTel hconstructor) ?_ + simp only [List.reverse_append, List.append_nil, + List.append_assoc] + simpa only [Nat.add_assoc] using + S.recRuleApp_hasType hconstructor hrecs + · show env.HasType gen.recUvars [] + (VExpr.lamN + (gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes ++ + VExpr.liftTelN + (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams + gen.elimination) 0) + _) + (VExpr.forallN _ _) + refine HasType.lamN (S.ruleBinders_onTel hconstructor) ?_ + simp only [List.reverse_append, List.append_nil, + List.append_assoc] + simpa only [Nat.add_assoc] using + S.minorApp_hasType hci hrecs + +end BlockGenerationEnv + +/-- The public inductive-declaration contract is monotone in its prefix +environment. This lets replay fixtures prepend independently verified +declarations without rebuilding the block's Stage-3 derivation. -/ +theorem WF.mono {env env' : VEnv} (henv : env ≤ env') + (H : VInductDecl.WF env decl) : VInductDecl.WF env' decl := by + refine ⟨H.1, fun ty hty => ?_⟩ + obtain ⟨htel, hctors⟩ := H.2 ty hty + exact ⟨htel.mono henv, fun c hc => + ⟨fieldsWF_mono henv (hctors c hc).1, (hctors c hc).2.mono henv⟩⟩ + +/-- Extract the carried index-spine typing of the recursive field at +position `q` from a `fieldsWF` chain. -/ +theorem fieldsWF_spine {U : Nat} {T : Name} {np : Nat} {env : VEnv} {l : VLevel} + {Is : List VExpr} : ∀ {Bs : List VExpr} {Γ₀ : List VExpr} {j₀ : Nat}, + fieldsWF U T np env l Is Γ₀ j₀ Bs → + ∀ q B, Bs[q]? = some B → isRecField U T np Is.length (j₀+q) B = true → + env.SpineWF U ((Bs.take q).reverse ++ Γ₀) + (VExpr.forallN (VExpr.liftTelN (j₀+q) Is 0) (.sort l)) (recFieldIdxs np B) (.sort l) + | [], _, _, _, q, B, hB, _ => by simp at hB + | B' :: Bs, Γ₀, j₀, ⟨_, hSp, hT⟩, 0, B, hB, hrec => by + obtain rfl : B' = B := by simpa using hB + simpa using hSp (by simpa using hrec) + | B' :: Bs, Γ₀, j₀, ⟨_, _, hT⟩, q+1, B, hB, hrec => by + have := fieldsWF_spine hT q B (by simpa using hB) + (by rwa [show j₀+1+q = j₀+(q+1) from by omega]) + rw [show j₀+1+q = j₀+(q+1) from by omega] at this + simpa [List.append_assoc] using this + +/-- Extract the uniform semantic evidence for any analyzed recursive +argument. Direct fields are re-expressed as the empty-telescope case; genuine +recursive Pi fields return the evidence stored by `fieldsWF`. -/ +theorem fieldsWF_recArg {U : Nat} {T : Name} {np : Nat} {env : VEnv} {l : VLevel} + {Is : List VExpr} : ∀ {Bs : List VExpr} {Γ₀ : List VExpr} {j₀ : Nat}, + fieldsWF U T np env l Is Γ₀ j₀ Bs → + ∀ q B r, Bs[q]? = some B → + recArg? U T np Is.length (j₀+q) B = some r → + r.WF U env l Is ((Bs.take q).reverse ++ Γ₀) + | [], _, _, _, q, B, r, hB, _ => by simp at hB + | B' :: Bs, Γ₀, j₀, ⟨hclass, hSp, htail⟩, 0, B, r, hB, hr => by + obtain rfl : B' = B := by simpa using hB + simp only [Nat.add_zero] at hr + rcases hclass with hdirect | hfun | ⟨hnone, -, -, -⟩ + · have hcanon := recArg?_of_isRecField hdirect + rw [hcanon] at hr + obtain rfl := Option.some.inj hr + exact ⟨trivial, by simpa [RecArg.WF] using hSp hdirect⟩ + · obtain ⟨r', hr', -, hwf⟩ := hfun + rw [hr'] at hr + obtain rfl := Option.some.inj hr + simpa using hwf + · rw [hnone] at hr + contradiction + | B' :: Bs, Γ₀, j₀, ⟨_, _, htail⟩, q+1, B, r, hB, hr => by + have h := fieldsWF_recArg htail q B r (by simpa using hB) + (by rwa [show j₀+1+q = j₀+(q+1) from by omega]) + simpa [List.append_assoc] using h + +namespace GenerationEnv + +variable {source : VInductDecl} {gen : GenerationChecked source} + {env : VEnv} (S : GenerationEnv gen env) +include S +-- `S` is included throughout so every lemma below is reachable as `S.lemma`, +-- including those whose statement and proof never mention it. +set_option linter.unusedSectionVars false + +/-- Checked field semantics for one paired constructor, re-indexed onto the +raw block header used by mixed generation. -/ +theorem viewFieldsWF {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + fieldsWF source.uvars gen.block.sourceType.name source.nparams env + gen.block.checked.resultLevel gen.block.checked.indices + gen.block.checked.params.reverse 0 ctor.view.fields := by + obtain ⟨c, hc, hview⟩ := gen.viewCtor_ofDirect hctor + have h := (S.checked.2 c hc).1 + rw [hview] + simpa [CheckedCtor.ofDirect, gen.block.uvars_eq, + gen.block.nparams_eq, gen.block.sourceType_name_eq] using h + +/-- Every retained recursive descriptor comes from re-analysis of the field +at its recorded position in the checked view. -/ +theorem viewRecArg_data {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {r : RecArg} + (hr : r ∈ ctor.view.recursive) : + ∃ B, ctor.view.fields[r.fieldIndex]? = some B ∧ + recArg? source.uvars gen.block.sourceType.name source.nparams + gen.block.checked.indices.length r.fieldIndex B = some r := by + obtain ⟨c, -, hview⟩ := gen.viewCtor_ofDirect hctor + rw [hview] at hr ⊢ + simp only [CheckedCtor.ofDirect] at hr ⊢ + obtain ⟨B, hB, hrec⟩ := recArgs_getElem r hr + exact ⟨B, by simpa using hB, hrec⟩ + +/-- Retained recursive descriptors have the checked family-index arity. -/ +theorem viewRecArg_indices_length {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {r : RecArg} + (hr : r ∈ ctor.view.recursive) : + r.indices.length = gen.block.checked.indices.length := by + obtain ⟨B, hB, hrec⟩ := S.viewRecArg_data hctor hr + exact (recArg?_eq hrec).2.2.2.1 + +/-- Retained recursive descriptors point inside the normalized field list. -/ +theorem viewRecArg_lt {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {r : RecArg} + (hr : r ∈ ctor.view.recursive) : + r.fieldIndex < ctor.view.fields.length := by + obtain ⟨c, -, hview⟩ := gen.viewCtor_ofDirect hctor + rw [hview] at hr ⊢ + simp only [CheckedCtor.ofDirect] at hr ⊢ + simpa using recArgs_lt r hr + +/-- The checked-view certificate supplies recursive-argument semantics in +the exact normalized prefix context. -/ +theorem viewRecArg_WF {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {r : RecArg} + (hr : r ∈ ctor.view.recursive) : + r.WF source.uvars env gen.block.checked.resultLevel + gen.block.checked.indices + ((ctor.view.fields.take r.fieldIndex).reverse ++ + gen.block.checked.params.reverse) := by + obtain ⟨B, hB, hrec⟩ := S.viewRecArg_data hctor hr + have h := fieldsWF_recArg (S.viewFieldsWF hctor) + r.fieldIndex B r hB (by simpa using hrec) + simpa using h + +/-- Definitionally equal raw/view contexts at any constructor-field prefix. +This is the structural bridge used before instantiation and weakening. -/ +theorem emittedPrefix_ctx {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) (j : Nat) : + env.IsDefEqCtx source.uvars [] + ((ctor.rawFields source.nparams |>.take j).reverse ++ + gen.block.checked.params.reverse) + ((ctor.view.fields.take j).reverse ++ + gen.block.checked.params.reverse) := by + have h := ((S.ctorWF ctor hctor).emittedTel.take + (source.nparams + j)).ctx + have hviewLen : + gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hraw : + (gen.block.checked.params ++ ctor.rawFields source.nparams).take + (source.nparams + j) = + gen.block.checked.params ++ + (ctor.rawFields source.nparams).take j := by + rw [← hviewLen] + rw [List.take_append, List.take_of_length_le (by omega)] + simp + have hview : + (gen.block.checked.params ++ ctor.view.fields).take + (source.nparams + j) = + gen.block.checked.params ++ ctor.view.fields.take j := by + rw [← hviewLen] + rw [List.take_append, List.take_of_length_le (by omega)] + simp + simp only [NormalizedCtor.emittedBinders, + NormalizedCtor.viewBinders] at h + rw [hraw, hview] at h + simpa [List.reverse_append] using h + +/-- The pointwise raw/view field-domain equality at a paired position, in +the preceding raw context. -/ +theorem emittedField_defeq {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {j : Nat} {B B' : VExpr} + (hB : (ctor.rawFields source.nparams)[j]? = some B) + (hB' : ctor.view.fields[j]? = some B') : + ∃ u, env.IsDefEq source.uvars + ((ctor.rawFields source.nparams |>.take j).reverse ++ + gen.block.checked.params.reverse) + B B' (.sort u) := by + have hviewLen : + gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hraw : + getElem? + (gen.block.checked.params ++ ctor.rawFields source.nparams) + (source.nparams + j) = some B := by + rw [List.getElem?_append_right (by + rw [hviewLen] + omega), hviewLen] + simpa using hB + have hview : + getElem? + (gen.block.checked.params ++ ctor.view.fields) + (source.nparams + j) = some B' := by + rw [List.getElem?_append_right (by + rw [hviewLen] + omega), hviewLen] + simpa using hB' + obtain ⟨u, h⟩ := + (S.ctorWF ctor hctor).emittedTel.getElem? hraw hview + have htake : + (gen.block.checked.params ++ ctor.rawFields source.nparams).take + (source.nparams + j) = + gen.block.checked.params ++ + (ctor.rawFields source.nparams).take j := by + rw [← hviewLen] + rw [List.take_append, List.take_of_length_le (by omega)] + simp + simp only [NormalizedCtor.emittedBinders] at h + rw [htake, List.reverse_append] at h + exact ⟨u, by simpa using h⟩ + +/-- Recursive-argument semantics transported from the checked view into the +raw constructor-field prefix that mixed artifacts actually bind. -/ +theorem rawRecArg_WF {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {r : RecArg} + (hr : r ∈ ctor.view.recursive) : + r.WF source.uvars env gen.block.checked.resultLevel + gen.block.checked.indices + ((ctor.rawFields source.nparams |>.take r.fieldIndex).reverse ++ + gen.block.checked.params.reverse) := by + exact (S.viewRecArg_WF hctor hr).defeqDFC S.ord + ((S.emittedPrefix_ctx hctor r.fieldIndex).symm S.ord) + +/-- The family telescope contract restricted to the index suffix. -/ +theorem rawIndexTel_defeq : + env.TelDefEq source.uvars gen.block.rawParams.reverse + gen.block.rawIndices gen.block.checked.indices := by + have h := S.familyTel.drop source.nparams + have hrawTake : + (gen.block.rawParams ++ gen.block.rawIndices).take source.nparams = + gen.block.rawParams := by + rw [← gen.shape.1, List.take_append, List.take_length] + simp + have hrawDrop : + (gen.block.rawParams ++ gen.block.rawIndices).drop source.nparams = + gen.block.rawIndices := by + rw [← gen.shape.1, List.drop_append] + simp + have hviewLen : + gen.block.checked.params.length = source.nparams := + gen.shape.2.1.symm.trans gen.shape.1 + have hviewDrop : + (gen.block.checked.params ++ gen.block.checked.indices).drop + source.nparams = + gen.block.checked.indices := by + rw [← hviewLen, List.drop_append] + simp + rw [hrawTake, hrawDrop, hviewDrop] at h + simpa using h + +/-- The raw/view index relation transported to the checked parameter base +used by generated artifacts. -/ +theorem emittedIndexTel_defeq : + env.TelDefEq source.uvars gen.block.checked.params.reverse + gen.block.rawIndices gen.block.checked.indices := + S.rawIndexTel_defeq.defeqDFC S.ord S.rawParams_ctx + +/-- The raw/view index telescope relation transported into recursor +universes. -/ +theorem rawIndexTel_defeq_rec : + env.TelDefEq (gen.recUvars) gen.paramsTel.reverse gen.idxTel + (gen.block.checked.indices.map + (VExpr.instL (gen.sourceLevels))) := by + have hdecl := S.emittedIndexTel_defeq.defeqDFC S.ord + (S.generationParams_ctx.symm S.ord) + have h := hdecl.instL + (U' := gen.recUvars) gen.sourceLevels_wf + simpa [GenerationChecked.paramsTel, GenerationChecked.idxTel, + List.map_reverse] using h + +/-- Transport all retained recursive-argument evidence into a mixed +minor/rule context. Raw constructor fields and raw family indices are the +emitted surfaces; recursive classification and index expressions remain the +checked-view data. -/ +theorem recArg_transport {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {r₀ : RecArg} + (hr₀ : r₀ ∈ ctor.view.recursive) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + let r := r₀.instL (gen.sourceLevels) + let As := VExpr.liftTelN d + (VExpr.liftTelN g r.binders r.fieldIndex) 0 + env.OnTel (gen.recUvars) + (As₂ ++ ((VExpr.liftTelN g + ((ctor.fieldsR source.uvars source.nparams gen.elimination).take + r.fieldIndex) 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) As ∧ + env.SpineWF (gen.recUvars) + (As.reverse ++ + (As₂ ++ ((VExpr.liftTelN g + ((ctor.fieldsR source.uvars source.nparams gen.elimination).take + r.fieldIndex) 0).reverse ++ + (mid ++ gen.paramsTel.reverse)))) + (VExpr.forallN + (VExpr.liftTelN + (r.fieldIndex + r.binders.length + g + d) gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + (r.indices.map fun e => + (e.liftN g (r.fieldIndex + r.binders.length)).liftN d + r.binders.length) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + dsimp only + let ls := gen.sourceLevels + have hjlt : + r₀.fieldIndex < (ctor.rawFields source.nparams).length := by + have hview := S.viewRecArg_lt hctor hr₀ + have hfields := + (gen.shape.2.2.2.2.2 ctor hctor).2.2.2 + omega + have hsem := S.rawRecArg_WF hctor hr₀ + have htel₁ := hsem.1.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hsp₁ := hsem.2.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have htelChecked : env.OnTel (gen.recUvars) + ((ctor.fieldsR source.uvars source.nparams gen.elimination |>.take + r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (r₀.binders.map (VExpr.instL ls)) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse, List.map_take] using htel₁ + have hspChecked : env.SpineWF (gen.recUvars) + ((r₀.binders.map (VExpr.instL ls)).reverse ++ + ((ctor.fieldsR source.uvars source.nparams gen.elimination |>.take + r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse)) + (VExpr.instL ls + (VExpr.forallN + (VExpr.liftTelN + (r₀.fieldIndex + r₀.binders.length) + gen.block.checked.indices 0) + (.sort gen.block.checked.resultLevel))) + (r₀.indices.map (VExpr.instL ls)) + (VExpr.instL ls (.sort gen.block.checked.resultLevel)) := by + simpa [List.map_append, List.map_reverse, + NormalizedCtor.fieldsR, List.map_take] using hsp₁ + have hprefix := S.generationFieldPrefix_ctx_rec hctor r₀.fieldIndex + have htelGeneration := htelChecked.defeqDFC S.ord + (hprefix.symm S.ord) + have hfull := htelGeneration.extendDefEqCtx hprefix + have hspGeneration := hspChecked.defeqDFC S.ord (hfull.symm S.ord) + simp only [VExpr.instL_forallN, VExpr.liftTelN_instL] at htelGeneration hspGeneration + have hjlen : + ((ctor.fieldsR source.uvars source.nparams gen.elimination).take + r₀.fieldIndex).length = r₀.fieldIndex := by + simp only [NormalizedCtor.fieldsR, List.length_take, + List.length_map] + omega + have hidxField := S.rawIndexTel_defeq_rec.weakN S.ord + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) + ((ctor.fieldsR source.uvars source.nparams gen.elimination).take + r₀.fieldIndex).reverse) + rw [List.length_reverse, hjlen] at hidxField + have hidxPrivate := hidxField.weakN S.ord + (Ctx.LiftN.zero + (Γ := ((ctor.fieldsR source.uvars source.nparams gen.elimination).take + r₀.fieldIndex).reverse ++ gen.paramsTel.reverse) + (r₀.binders.map (VExpr.instL ls)).reverse) + simp only [List.length_reverse, List.length_map] at hidxPrivate + rw [VExpr.liftTelN_liftTelN, + VExpr.liftTelN_liftTelN] at hidxPrivate + have hidxLen : + (r₀.indices.map (VExpr.instL ls)).length = + (VExpr.liftTelN + (r₀.fieldIndex + r₀.binders.length) gen.idxTel 0).length := by + simp only [List.length_map, VExpr.liftTelN_length, + GenerationChecked.idxTel] + exact (S.viewRecArg_indices_length hctor hr₀).trans + gen.shape.2.2.1.symm + have hspRaw := + hidxPrivate.spine_sort S.ord hspGeneration hidxLen + have W₁ := Ctx.LiftN.consTel (n := mid.length) + ((ctor.fieldsR source.uvars source.nparams gen.elimination).take + r₀.fieldIndex) + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [hjlen, Nat.add_zero] at W₁ + have htel₂ := htelGeneration.weakN S.ord W₁ + have hsp₂ := hspRaw.weakN S.ord + (Ctx.LiftN.consTel + (r₀.binders.map (VExpr.instL ls)) W₁) + rw [hg] at htel₂ hsp₂ + have W₂ := Ctx.LiftN.zero + (Γ := (VExpr.liftTelN g + ((ctor.fieldsR source.uvars source.nparams gen.elimination).take + r₀.fieldIndex) 0).reverse ++ + (mid ++ gen.paramsTel.reverse)) As₂ (h := hd) + have htel₃ := htel₂.weakN S.ord W₂ + have hsp₃ := hsp₂.weakN S.ord + (Ctx.LiftN.consTel + (VExpr.liftTelN g + (r₀.binders.map (VExpr.instL ls)) r₀.fieldIndex) W₂) + refine ⟨?_, ?_⟩ + · simpa [ls, RecArg.instL, List.append_assoc] using htel₃ + · simp only [List.length_map, VExpr.liftTelN_length, + Nat.add_zero] at hsp₃ + rw [VExpr.liftN_forallN, VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN_hi' + (r₀.fieldIndex + r₀.binders.length) g _ 0 (by omega), + VExpr.liftTelN_liftTelN_mid + (r₀.fieldIndex + r₀.binders.length + g) d _ 0 + r₀.binders.length (Nat.zero_le _) (by omega)] at hsp₃ + rw [show r₀.binders.length + r₀.fieldIndex = + r₀.fieldIndex + r₀.binders.length from Nat.add_comm _ _] at hsp₃ + simpa [ls, RecArg.instL, VExpr.instL, VExpr.liftN, + List.map_map, Function.comp_def, List.append_assoc] using hsp₃ + +end GenerationEnv + +/-- Syntactic lifting law for the mixed motive. -/ +theorem GenerationChecked.motiveType_liftN {source : VInductDecl} + (gen : GenerationChecked source) (n : Nat) : + gen.motiveType.liftN n = + VExpr.forallN (VExpr.liftTelN n gen.idxTel 0) + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange (n + gen.idxTel.length) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort gen.motiveLevel)) := by + rw [show gen.motiveType = + VExpr.forallN gen.idxTel + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange gen.idxTel.length source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort gen.motiveLevel)) from rfl, + VExpr.liftN_forallN] + refine congrArg _ ?_ + show VExpr.forallE _ _ = VExpr.forallE _ _ + refine congr (congrArg _ ?_) rfl + rw [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + rfl + +/-- Apply a mixed motive variable to a raw-index spine and a typed family +major. -/ +theorem GenerationChecked.motiveVarApp_hasType {source : VInductDecl} + (gen : GenerationChecked source) {env : VEnv} {l : VLevel} + {Γ : List VExpr} {K : Nat} {idxs : List VExpr} {a : VExpr} + (hM : env.HasType (gen.recUvars) Γ (.bvar K) + (gen.motiveType.liftN (K+1))) + (hidx : env.SpineWF (gen.recUvars) Γ + (VExpr.forallN (VExpr.liftTelN (K+1) gen.idxTel 0) + (.sort l)) + idxs (.sort l)) + (hlen : idxs.length = gen.idxTel.length) + (ha : env.HasType (gen.recUvars) Γ a + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange (K+1) source.nparams ++ idxs))) : + env.HasType (gen.recUvars) Γ + (VExpr.appN (.bvar K) (idxs ++ [a])) (.sort gen.motiveLevel) := by + rw [gen.motiveType_liftN] at hM + have hshape := hidx.retarget + (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange (K+1 + gen.idxTel.length) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort gen.motiveLevel)) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ + (C := .const gen.block.sourceType.name + (gen.sourceLevels)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by rw [hlen]; omega), + show K+1+gen.idxTel.length-idxs.length = K+1 from by + rw [hlen, Nat.add_sub_cancel], + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hApp := hshape.hasType_appN hM + rw [VExpr.appN_append] + exact HasType.app hApp (by simpa using ha) + +/-- Mixed minor generation preserves constructor-list arity at every suffix +depth. -/ +theorem GenerationChecked.minorTypesAux_length + {source : VInductDecl} (gen : GenerationChecked source) : + ∀ (ctors : List NormalizedCtor) (i : Nat), + (gen.minorTypesAux ctors i).length = ctors.length + | [], _ => rfl + | _ :: ctors, i => by + simp [GenerationChecked.minorTypesAux, + gen.minorTypesAux_length ctors (i+1)] + +/-- The complete mixed minor telescope has one entry per paired raw/view +constructor. -/ +theorem GenerationChecked.minorTypes_length + {source : VInductDecl} (gen : GenerationChecked source) : + gen.minorTypes.length = gen.block.ctorPairs.length := by + simpa [GenerationChecked.minorTypes] using + gen.minorTypesAux_length gen.block.ctorPairs 0 + +/-- Positional lookup through mixed minor generation. -/ +theorem GenerationChecked.minorTypesAux_getElem? + {source : VInductDecl} (gen : GenerationChecked source) : + ∀ (ctors : List NormalizedCtor) (i q : Nat), + (gen.minorTypesAux ctors i)[q]? = + ctors[q]?.map fun ctor => + VExpr.liftN (i+q) + (GenerationChecked.minorType + (source := source) ctor gen.elimination) + | [], _, q => by simp [GenerationChecked.minorTypesAux] + | _ :: _, _, 0 => by simp [GenerationChecked.minorTypesAux] + | _ :: ctors, i, q+1 => by + simp only [GenerationChecked.minorTypesAux, + List.getElem?_cons_succ] + rw [gen.minorTypesAux_getElem? ctors (i+1) q, + show i+1+q = i+(q+1) by omega] + +namespace GenerationEnv + +variable {source : VInductDecl} {gen : GenerationChecked source} + {env : VEnv} (S : GenerationEnv gen env) +include S +-- `S` is included throughout so every lemma below is reachable as `S.lemma`, +-- including those whose statement and proof never mention it. +set_option linter.unusedSectionVars false + +/-- One mixed generalized induction-hypothesis entry is a type. The bound +field keeps its raw domain; `emittedField_defeq` converts it to the retained +recursive-Pi view only at the semantic application point. -/ +theorem recArgMinor_isType {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) {r : RecArg} + (hrmem : r ∈ ctor.recArgsR source.uvars gen.elimination) + (Δ : List VExpr) (p : Nat) (hΔ : Δ.length = p) : + env.IsType (gen.recUvars) + (Δ ++ + (VExpr.liftTelN 1 + (ctor.fieldsR source.uvars source.nparams gen.elimination) 0).reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + (r.minorIH + (ctor.fieldsR source.uvars source.nparams gen.elimination).length p) := by + obtain ⟨r₀, hr₀, rfl⟩ := + NormalizedCtor.recArgsR_mem hrmem + obtain ⟨Bview, hBview, hrec⟩ := + S.viewRecArg_data hctor hr₀ + let ls := gen.sourceLevels + let r := r₀.instL ls + let Bs := ctor.fieldsR source.uvars source.nparams gen.elimination + let m := Bs.length + let j := r₀.fieldIndex + let Fs := VExpr.liftTelN 1 Bs 0 + let As := r.minorBinders m p + let idxs := r.indices.map fun e => + (e.liftN 1 (r.fieldIndex+r.binders.length)).liftN + (m-r.fieldIndex+p) r.binders.length + let Γ := Δ ++ Fs.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse) + have hjm : j < m := by + have hview := S.viewRecArg_lt hctor hr₀ + have hfields := + (gen.shape.2.2.2.2.2 ctor hctor).2.2.2 + simp only [j, m, Bs, NormalizedCtor.fieldsR_length] + omega + have hjraw : + r₀.fieldIndex < (ctor.rawFields source.nparams).length := by + simpa [j, m, Bs, NormalizedCtor.fieldsR_length] using hjm + let Braw := (ctor.rawFields source.nparams)[r₀.fieldIndex] + have hBraw : + (ctor.rawFields source.nparams)[r₀.fieldIndex]? = + some Braw := + List.getElem?_eq_getElem hjraw + have hFsLen : Fs.length = m := by + simp [Fs, m, VExpr.liftTelN_length] + have hstackLen : + (Δ ++ (Fs.drop j).reverse).length = m-j+p := by + simp only [List.length_append, List.length_reverse, + List.length_drop, hFsLen, hΔ] + omega + have ht := S.recArg_transport hctor hr₀ [gen.motiveType] rfl + (Δ ++ (Fs.drop j).reverse) hstackLen + simp only [List.length_singleton, RecArg.instL] at ht + have hctx : + (Δ ++ (Fs.drop j).reverse) ++ + ((VExpr.liftTelN 1 (Bs.take j) 0).reverse ++ + ([gen.motiveType] ++ gen.paramsTel.reverse)) = Γ := by + dsimp only [Γ, Fs] + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc + ((VExpr.liftTelN 1 Bs 0).drop j).reverse, + ← List.reverse_append, List.take_append_drop, + List.singleton_append, ← List.append_assoc] + dsimp only [j] at ht hctx + have htel : env.OnTel (gen.recUvars) Γ As := by + rw [hctx] at ht + simpa [r, As, m, j, Bs, RecArg.instL, + RecArg.minorBinders] using ht.1 + have hsp : env.SpineWF (gen.recUvars) + (As.reverse ++ Γ) + (VExpr.forallN + (VExpr.liftTelN + (m+p+r.binders.length+1) gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst ls))) + idxs + (.sort (gen.block.checked.resultLevel.inst ls)) := by + rw [hctx] at ht + simpa [r, As, idxs, m, j, Bs, ls, RecArg.instL, + RecArg.minorBinders, + List.append_assoc, + show j + r₀.binders.length + 1 + (m-j+p) = + m+p+r₀.binders.length+1 from by omega] using ht.2 + have hF : Γ[m-1-j+p]? = + some ((Braw.instL ls).liftN 1 j) := by + dsimp only [Γ, Fs] + rw [getElem?_stack_mid Δ + (VExpr.liftTelN 1 Bs 0).reverse + (gen.motiveType :: gen.paramsTel.reverse) + (i := m-1-j+p) (by rw [hΔ]; omega) + (by simp only [hΔ, List.length_reverse, + VExpr.liftTelN_length]; omega), + show m - 1 - j + p - Δ.length = m - 1 - j from by + rw [hΔ] + omega, + List.getElem?_reverse (by rw [hFsLen]; omega), + VExpr.liftTelN_length, + show m - 1 - (m - 1 - j) = j from by omega, + VExpr.liftTelN_getElem?, + NormalizedCtor.fieldsR_getElem?, hBraw] + simp [ls] + have hlu := Lookup.of_getElem? hF + rw [show m-1-j+p+1 = m-j+p from by omega] at hlu + dsimp only [j, r] at hlu + have hf0 := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) hlu + obtain ⟨u, hdom₀⟩ := + S.emittedField_defeq hctor hBraw hBview + have hdom₁ := hdom₀.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hdomChecked : env.IsDefEq (gen.recUvars) + ((ctor.fieldsR source.uvars source.nparams gen.elimination |>.take + r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (Braw.instL ls) (Bview.instL ls) ((VExpr.sort u).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse, List.map_take] using hdom₁ + have hprefix := S.generationFieldPrefix_ctx_rec hctor r₀.fieldIndex + have hdomGeneration := hdomChecked.defeqDFC S.ord + (hprefix.symm S.ord) + have hjlen : (Bs.take r₀.fieldIndex).length = + r₀.fieldIndex := by + simp only [Bs, NormalizedCtor.fieldsR, + List.length_take, List.length_map] + omega + have Wmid := Ctx.LiftN.consTel (n := 1) + (Bs.take r₀.fieldIndex) + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) + [gen.motiveType]) + rw [hjlen, Nat.add_zero] at Wmid + have hdom₂ := hdomGeneration.weakN S.ord Wmid + have Wstack := Ctx.LiftN.zero + (Γ := (VExpr.liftTelN 1 (Bs.take j) 0).reverse ++ + ([gen.motiveType] ++ gen.paramsTel.reverse)) + (Δ ++ (Fs.drop j).reverse) (h := hstackLen) + have hdom₃ := hdom₂.weakN S.ord Wstack + rw [hctx] at hdom₃ + have hfView := hdom₃.defeq hf0 + have hfield := recArg_minor_fieldType hrec m p + (by simpa [j] using hjm) gen.elimination + simp only [RecArg.instL] at hfield + rw [hfield] at hfView + have hf := hfView.weakN S.ord + (Ctx.LiftN.zero (Γ := Γ) As.reverse) + have hmajor := VEnv.HasType.appN_selfSpine + (env := env) (U := gen.recUvars) + (As := As) + (B := VExpr.appN + (.const gen.block.sourceType.name ls) + (VExpr.bvarRevRange + (m+p+r.binders.length+1) source.nparams ++ idxs)) + (Δ := []) (Γ := Γ) (by + simpa [As, r, idxs, j, ls, RecArg.instL, + List.length_reverse, List.map_map, + Function.comp_def] using hf) + simp only [List.length_nil, VExpr.liftN_zero, + List.nil_append] at hmajor + have hAsLen : As.length = r.binders.length := by + simp [As, RecArg.minorBinders, VExpr.liftTelN_length] + change env.HasType (gen.recUvars) (As.reverse ++ Γ) + ((VExpr.bvar (m-1-r.fieldIndex+p+As.length)).appN + (VExpr.bvarRevRange 0 As.length)) + (VExpr.appN + (.const gen.block.sourceType.name ls) + (VExpr.bvarRevRange + (m+p+r.binders.length+1) source.nparams ++ idxs)) at hmajor + rw [hAsLen] at hmajor + have hMget : + (As.reverse ++ Γ)[m+p+r.binders.length]? = + some gen.motiveType := by + have hM0 := getElem?_rstack3 As.reverse + (Δ ++ Fs.reverse) gen.motiveType gen.paramsTel.reverse + (i := m+p+r.binders.length) + (by + simp [As, RecArg.minorBinders, r, m, Fs, hΔ, + VExpr.liftTelN_length, RecArg.instL] + omega) + simpa [Γ, List.append_assoc] using hM0 + have hM := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) + (Lookup.of_getElem? hMget) + have hlen : idxs.length = gen.idxTel.length := by + simpa [idxs, r, RecArg.instL, + GenerationChecked.idxTel] using + (S.viewRecArg_indices_length hctor hr₀).trans + gen.shape.2.2.1.symm + have hbody := gen.motiveVarApp_hasType + (l := gen.block.checked.resultLevel.inst ls) + hM hsp hlen hmajor + refine IsType.forallN htel ⟨gen.motiveLevel, ?_⟩ + simpa [RecArg.minorIH, r, As, idxs, m, Γ, Fs, Bs, + List.append_assoc] using hbody + +/-- The complete mixed functional-IH telescope is well formed at any suffix +and depth. -/ +theorem ihs_onTel {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + ∀ (rsSuf : List RecArg), + (∀ r ∈ rsSuf, r ∈ ctor.recArgsR source.uvars gen.elimination) → + ∀ (Δ : List VExpr) (p : Nat), Δ.length = p → + env.OnTel (gen.recUvars) + (Δ ++ + (VExpr.liftTelN 1 + (ctor.fieldsR source.uvars source.nparams gen.elimination) 0).reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + (ihsFromRecArgs + (ctor.fieldsR source.uvars source.nparams gen.elimination).length rsSuf p) + | [], _, _, _, _ => trivial + | r :: rsSuf, hqs, Δ, p, hΔ => + ⟨S.recArgMinor_isType hctor + (hqs r (.head _)) Δ p hΔ, + GenerationEnv.ihs_onTel hctor rsSuf + (fun q hq => hqs q (.tail _ hq)) + (_ :: Δ) (p+1) (by simp [hΔ])⟩ + +/-- The retained constructor result has exactly the checked family-index +arity. -/ +theorem viewResultIndices_length {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + ctor.view.resultIndices.length = + gen.block.checked.indices.length := by + obtain ⟨c, hc, hview⟩ := gen.viewCtor_ofDirect hctor + have hstage := + (gen.block.checked.direct_anatomy.2.2.2.2.2 c hc).2.2 + have hlen := (stage3Ctor_eq hstage).2.1 + rw [hview] + rw [gen.block.nparams_eq] + simpa [CheckedCtor.ofDirect] using hlen + +/-- Checked result-index spine semantics for a paired constructor. -/ +theorem viewResultSpine {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.SpineWF source.uvars + (ctor.view.fields.reverse ++ + gen.block.checked.params.reverse) + (VExpr.forallN + (VExpr.liftTelN ctor.view.fields.length + gen.block.checked.indices 0) + (.sort gen.block.checked.resultLevel)) + ctor.view.resultIndices + (.sort gen.block.checked.resultLevel) := by + obtain ⟨c, hc, hview⟩ := gen.viewCtor_ofDirect hctor + have h := (S.checked.2 c hc).2 + rw [hview] + simpa [CheckedCtor.ofDirect, gen.block.uvars_eq, + gen.block.nparams_eq] using h + +/-- Constructor-result semantics transported to the exact emitted +checked-parameter/raw-field context and raw family-index telescope. -/ +theorem rawResultSpine {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.SpineWF source.uvars + ((ctor.rawFields source.nparams).reverse ++ + gen.block.checked.params.reverse) + (VExpr.forallN + (VExpr.liftTelN + (ctor.rawFields source.nparams).length + gen.block.rawIndices 0) + (.sort gen.block.checked.resultLevel)) + ctor.view.resultIndices + (.sort gen.block.checked.resultLevel) := by + have hctx := (S.ctorWF ctor hctor).emittedTel.ctx + simp only [NormalizedCtor.emittedBinders, + NormalizedCtor.viewBinders, List.reverse_append, + List.append_nil] at hctx + have hsp := (S.viewResultSpine hctor).defeqDFC S.ord + (hctx.symm S.ord) + have hfields := + (gen.shape.2.2.2.2.2 ctor hctor).2.2.2 + rw [← hfields] at hsp + have hidx := S.emittedIndexTel_defeq.weakN S.ord + (Ctx.LiftN.zero (Γ := gen.block.checked.params.reverse) + (ctor.rawFields source.nparams).reverse) + rw [List.length_reverse] at hidx + have hlen : + ctor.view.resultIndices.length = + (VExpr.liftTelN + (ctor.rawFields source.nparams).length + gen.block.rawIndices 0).length := by + simp only [VExpr.liftTelN_length] + exact (S.viewResultIndices_length hctor).trans + gen.shape.2.2.1.symm + exact hidx.spine_sort S.ord hsp hlen + +/-- Transport the mixed constructor result spine into a minor or rule +context. -/ +theorem result_transport {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.SpineWF (gen.recUvars) + (As₂ ++ + ((VExpr.liftTelN g + (ctor.fieldsR source.uvars source.nparams gen.elimination) 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + ((ctor.fieldsR source.uvars source.nparams gen.elimination).length + g + d) + gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN g + (ctor.fieldsR source.uvars source.nparams gen.elimination).length).liftN d) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + let ls := gen.sourceLevels + have h1 := (S.rawResultSpine hctor).instL + (U' := gen.recUvars) gen.sourceLevels_wf + have h1Checked : env.SpineWF (gen.recUvars) + ((ctor.fieldsR source.uvars source.nparams gen.elimination).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (VExpr.instL ls + (VExpr.forallN + (VExpr.liftTelN (ctor.rawFields source.nparams).length + gen.block.rawIndices 0) + (.sort gen.block.checked.resultLevel))) + (ctor.view.resultIndices.map (VExpr.instL ls)) + ((VExpr.sort gen.block.checked.resultLevel).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse] using h1 + have hfieldsCtx := (S.generationFields_onTel_rec hctor).extendDefEqCtx + S.generationParams_ctx_rec + have h1Generation := h1Checked.defeqDFC S.ord + (hfieldsCtx.symm S.ord) + rw [VExpr.instL_forallN, VExpr.liftTelN_instL, + show + (gen.block.rawIndices.map (VExpr.instL ls)) = + gen.idxTel by rfl] at h1Generation + rw [← NormalizedCtor.fieldsR_length + (source := source) (mode := gen.elimination) ctor] at h1Generation + have W₁ := Ctx.LiftN.consTel (n := mid.length) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [Nat.add_zero] at W₁ + have h2 := h1Generation.weakN S.ord W₁ + rw [VExpr.liftN_forallN, hg] at h2 + have h3 := h2.weakN S.ord + (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + rw [VExpr.liftN_forallN] at h3 + rw [VExpr.liftTelN_liftTelN_hi' + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + g _ 0 (by omega), + VExpr.liftTelN_liftTelN] at h3 + simpa [ls, NormalizedCtor.resultIndicesR, + VExpr.instL, VExpr.liftN, List.map_map, + Function.comp_def, List.append_assoc] using h3 + +/-- The exact emitted constructor application transported into recursor +universes, before inserting the motive or any induction-hypothesis stack. -/ +theorem ctorApp_emitted_rec {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.HasType (gen.recUvars) + ((ctor.fieldsR source.uvars source.nparams gen.elimination).reverse ++ + gen.paramsTel.reverse) + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR source.uvars source.nparams gen.elimination).length)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + source.nparams ++ + ctor.resultIndicesR source.uvars gen.elimination)) := by + let ls := gen.sourceLevels + have h := (S.ctorApp_emitted_decl hctor).instL + (U' := gen.recUvars) gen.sourceLevels_wf + have hChecked : env.HasType (gen.recUvars) + ((ctor.fieldsR source.uvars source.nparams gen.elimination).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + ((VExpr.appN + (.const ctor.raw.name (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (ctor.rawFields source.nparams).length source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.rawFields source.nparams).length)).instL ls) + ((ctor.resultTarget gen.block).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse] using h + have hfieldsCtx := (S.generationFields_onTel_rec hctor).extendDefEqCtx + S.generationParams_ctx_rec + have hGeneration := hChecked.defeqDFC S.ord + (hfieldsCtx.symm S.ord) + rw [← NormalizedCtor.fieldsR_length + (source := source) (mode := gen.elimination) ctor] at hGeneration + simpa [ls, NormalizedCtor.fieldsR, + GenerationChecked.paramsTel, + NormalizedCtor.resultTarget, + NormalizedCtor.resultIndicesR, + VExpr.instL_appN, List.map_append, + bvarRevRange_instL, List.map_reverse, + VExpr.instL, VLevel.params_map_inst_params'] using hGeneration + +/-- Transport the emitted constructor application under binders inserted +between parameters and fields, then under an arbitrary top stack. -/ +theorem ctorApp_transport {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.HasType (gen.recUvars) + (As₂ ++ + ((VExpr.liftTelN g + (ctor.fieldsR source.uvars source.nparams gen.elimination) 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (d + (g + + (ctor.fieldsR source.uvars source.nparams gen.elimination).length)) + source.nparams ++ + VExpr.bvarRevRange d + (ctor.fieldsR source.uvars source.nparams gen.elimination).length)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (d + (g + + (ctor.fieldsR source.uvars source.nparams gen.elimination).length)) + source.nparams ++ + (ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN g + (ctor.fieldsR source.uvars source.nparams gen.elimination).length).liftN d)) := by + let Bs := ctor.fieldsR source.uvars source.nparams gen.elimination + have W₁ := Ctx.LiftN.consTel (n := mid.length) Bs + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [Nat.add_zero] at W₁ + have h₁ := (S.ctorApp_emitted_rec hctor).weakN S.ord W₁ + rw [hg] at h₁ + have hmid : env.HasType (gen.recUvars) + ((VExpr.liftTelN g Bs 0).reverse ++ + (mid ++ gen.paramsTel.reverse)) + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange (g + Bs.length) source.nparams ++ + VExpr.bvarRevRange 0 Bs.length)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange (g + Bs.length) source.nparams ++ + (ctor.resultIndicesR source.uvars gen.elimination).map + (VExpr.liftN g · Bs.length))) := by + simpa [Bs, VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + VExpr.bvarRevRange_liftN_high + Bs.length 0 g Bs.length (by omega), + VExpr.liftN] using h₁ + have htop := hmid.weakN S.ord + (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + simpa [Bs, VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.liftN, List.map_map, Function.comp_def, + List.append_assoc] using htop + +/-- Constructor application in the exact mixed minor-premise context. -/ +theorem ctorAppMinor_hasType {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) (Δ : List VExpr) : + env.HasType (gen.recUvars) + (Δ ++ + (VExpr.liftTelN 1 + (ctor.fieldsR source.uvars source.nparams gen.elimination) 0).reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (Δ.length + + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + 1) + source.nparams ++ + VExpr.bvarRevRange Δ.length + (ctor.fieldsR source.uvars source.nparams gen.elimination).length)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (Δ.length + + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + 1) + source.nparams ++ + (ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN 1 + (ctor.fieldsR source.uvars source.nparams gen.elimination).length).liftN + Δ.length)) := by + have h := S.ctorApp_transport hctor [gen.motiveType] + (g := 1) rfl Δ (d := Δ.length) rfl + rw [VExpr.bvarRevRange_congr source.nparams + (show + Δ.length + + (1 + + (ctor.fieldsR source.uvars source.nparams gen.elimination).length) = + Δ.length + + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + 1 by + omega)] at h + simpa [List.append_assoc] using h + +/-- The exact raw field telescope used by a mixed minor is well formed after +universe instantiation and insertion of the motive. -/ +theorem fields_onTel_minor {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.OnTel (gen.recUvars) + (gen.motiveType :: gen.paramsTel.reverse) + (VExpr.liftTelN 1 + (ctor.fieldsR source.uvars source.nparams gen.elimination) 0) := by + have hout := (S.generationFields_onTel_rec hctor).weakN S.ord + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) + [gen.motiveType]) + simpa using hout + +/-- Every mixed constructor minor is a type over the checked parameter telescope +and mixed motive. Raw field syntax is preserved; recursive classifications +and result indices come from the checked view. -/ +theorem minor_isType {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.IsType (gen.recUvars) + (gen.motiveType :: gen.paramsTel.reverse) + (GenerationChecked.minorType + (source := source) ctor gen.elimination) := by + let Bs := ctor.fieldsR source.uvars source.nparams gen.elimination + let m := Bs.length + let rs := ctor.recArgsR source.uvars gen.elimination + let IHs := ihsFromRecArgs m rs 0 + let Fs := VExpr.liftTelN 1 Bs 0 + let Γ := IHs.reverse ++ + (Fs.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + simp only [GenerationChecked.minorType] + refine IsType.forallN (by + simpa [Bs] using S.fields_onTel_minor hctor) ?_ + refine IsType.forallN (by + simpa [Bs, m, rs, IHs, Fs, List.append_assoc] using + S.ihs_onTel hctor rs (fun r hr => hr) [] 0 rfl) ?_ + have hrlen : IHs.reverse.length = rs.length := by + simp [IHs, ihsFromRecArgs_length] + have hMget : Γ[m + rs.length]? = + some gen.motiveType := by + have h := getElem?_rstack3 IHs.reverse Fs.reverse + gen.motiveType gen.paramsTel.reverse + (i := m + rs.length) + (by + simp [IHs, Fs, m, ihsFromRecArgs_length, + VExpr.liftTelN_length] + omega) + simpa [Γ] using h + have hM : env.HasType (gen.recUvars) Γ + (.bvar (m + rs.length)) + (gen.motiveType.liftN (m + rs.length + 1)) := + VEnv.HasType.bvar (Lookup.of_getElem? hMget) + have hSp := S.result_transport hctor [gen.motiveType] + (g := 1) rfl IHs.reverse + (d := rs.length) hrlen + rw [show m + 1 + rs.length = + m + rs.length + 1 by omega] at hSp + have hSp' : env.SpineWF (gen.recUvars) Γ + (VExpr.forallN + (VExpr.liftTelN (m + rs.length + 1) + gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN 1 m).liftN rs.length) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + simpa [Γ, Fs, Bs, m, List.append_assoc] using hSp + have hlen : + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN 1 m).liftN rs.length).length = + gen.idxTel.length := by + simp only [List.length_map, NormalizedCtor.resultIndicesR, + GenerationChecked.idxTel] + exact (S.viewResultIndices_length hctor).trans + gen.shape.2.2.1.symm + have hctorApp := S.ctorAppMinor_hasType hctor IHs.reverse + rw [hrlen, + VExpr.bvarRevRange_congr source.nparams + (show rs.length + m + 1 = m + rs.length + 1 by omega)] at hctorApp + have hctorApp' : env.HasType (gen.recUvars) Γ + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (m + rs.length + 1) source.nparams ++ + VExpr.bvarRevRange rs.length m)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (m + rs.length + 1) source.nparams ++ + (ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN 1 m).liftN rs.length)) := by + simpa [Γ, Fs, Bs, m, IHs, rs, + List.append_assoc] using hctorApp + have hbody := gen.motiveVarApp_hasType hM hSp' hlen hctorApp' + rw [VExpr.bvarRevRange_congr source.nparams + (show m + rs.length + 1 = + rs.length + m + 1 by omega)] at hbody + exact ⟨gen.motiveLevel, by + simpa [Γ, Fs, Bs, m, rs, IHs, + List.append_assoc] using hbody⟩ + +/-- The checked parameter telescope is well formed in recursor universes. -/ +theorem paramsTel_onTel : + env.OnTel (gen.recUvars) [] gen.paramsTel := by + have h := S.generationFamily_onTel.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have h' : env.OnTel (gen.recUvars) [] + (gen.paramsTel ++ gen.idxTel) := by + simpa [GenerationChecked.paramsTel, + GenerationChecked.idxTel] using h + exact h'.of_append.1 + +/-- The raw index telescope is well formed over the checked parameters. -/ +theorem idxTel_onTel : + env.OnTel (gen.recUvars) + gen.paramsTel.reverse gen.idxTel := by + have h := S.generationFamily_onTel.instL + (U' := gen.recUvars) gen.sourceLevels_wf + have h' : env.OnTel (gen.recUvars) [] + (gen.paramsTel ++ gen.idxTel) := by + simpa [GenerationChecked.paramsTel, + GenerationChecked.idxTel] using h + simpa using h'.of_append.2 + +/-- Any suffix of paired constructors generates a well-formed mixed minor +telescope at its positional depth. -/ +theorem minorTypesAux_onTel : + ∀ (ctors : List NormalizedCtor), + (∀ ctor ∈ ctors, ctor ∈ gen.block.ctorPairs) → + ∀ (Δ : List VExpr) (i : Nat), Δ.length = i → + env.OnTel (gen.recUvars) + (Δ ++ + (gen.motiveType :: gen.paramsTel.reverse)) + (gen.minorTypesAux ctors i) + | [], _, _, _, _ => trivial + | ctor :: ctors, hsub, Δ, i, hΔ => + ⟨by + rw [← hΔ] + exact (S.minor_isType + (hsub ctor (.head _))).weakN S.ord + (.zero Δ), + GenerationEnv.minorTypesAux_onTel ctors + (fun ctor hctor => hsub ctor (.tail _ hctor)) + (_ :: Δ) (i+1) (by simp [hΔ])⟩ + +/-- The complete mixed minor telescope is well formed over parameters and +motive. -/ +theorem minorTypes_onTel : + env.OnTel (gen.recUvars) + (gen.motiveType :: gen.paramsTel.reverse) + gen.minorTypes := by + simpa [GenerationChecked.minorTypes] using + S.minorTypesAux_onTel gen.block.ctorPairs + (fun _ h => h) [] 0 rfl + +/-- Transport the fully applied raw family under binders inserted below its +indices and then under an arbitrary top stack. -/ +theorem familyApp_transport + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.HasType (gen.recUvars) + (As₂ ++ + ((VExpr.liftTelN g gen.idxTel 0).reverse ++ + (mid ++ gen.paramsTel.reverse))) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (d + (g + gen.idxTel.length)) + source.nparams ++ + VExpr.bvarRevRange d gen.idxTel.length)) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + have W₁ := Ctx.LiftN.consTel (n := mid.length) gen.idxTel + (Ctx.LiftN.zero (Γ := gen.paramsTel.reverse) mid) + rw [Nat.add_zero] at W₁ + have h₁ := S.familyApp_hasType.weakN S.ord W₁ + rw [hg] at h₁ + have hmid : env.HasType (gen.recUvars) + ((VExpr.liftTelN g gen.idxTel 0).reverse ++ + (mid ++ gen.paramsTel.reverse)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (g + gen.idxTel.length) source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + simpa [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + VExpr.bvarRevRange_liftN_high + gen.idxTel.length 0 g gen.idxTel.length (by omega), + VExpr.liftN] using h₁ + have htop := hmid.weakN S.ord + (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + simpa [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.liftN, List.append_assoc] using htop + +/-- The mixed recursor type is well formed. Its telescope retains raw +parameter and index syntax while its motive and minors use the checked +recursive classification. -/ +theorem recType_isType : + env.IsType (gen.recUvars) [] gen.recType := by + refine IsType.forallN S.paramsTel_onTel ?_ + simp only [List.append_nil] + refine IsType.forallE S.motive_isType ?_ + refine IsType.forallN S.minorTypes_onTel ?_ + have hI : env.OnTel (gen.recUvars) + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + (VExpr.liftTelN (gen.block.ctorPairs.length + 1) + gen.idxTel 0) := by + have h := S.idxTel_onTel.weakN S.ord + (Ctx.LiftN.zero + (n := gen.block.ctorPairs.length + 1) + (Γ := gen.paramsTel.reverse) + (gen.minorTypes.reverse ++ [gen.motiveType]) + (h := by simp [gen.minorTypes_length])) + simpa [List.append_assoc] using h + refine IsType.forallN hI ?_ + have hmaj₀ := S.familyApp_transport + (gen.minorTypes.reverse ++ [gen.motiveType]) + (g := gen.block.ctorPairs.length + 1) + (by simp [gen.minorTypes_length]) + [] (d := 0) rfl + rw [VExpr.bvarRevRange_congr source.nparams + (show + 0 + ((gen.block.ctorPairs.length + 1) + + gen.idxTel.length) = + gen.idxTel.length + gen.block.ctorPairs.length + 1 by omega)] at hmaj₀ + have hmaj : env.HasType (gen.recUvars) + ((VExpr.liftTelN (gen.block.ctorPairs.length + 1) + gen.idxTel 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + simpa [List.append_assoc] using hmaj₀ + refine IsType.forallE ⟨_, hmaj⟩ ?_ + have hM := getElem?_rstack3 + [VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)] + ((VExpr.liftTelN (gen.block.ctorPairs.length + 1) + gen.idxTel 0).reverse ++ + gen.minorTypes.reverse) + gen.motiveType gen.paramsTel.reverse + (i := gen.idxTel.length + + gen.block.ctorPairs.length + 1) + (by + simp only [List.length_singleton, List.length_append, + List.length_reverse, VExpr.liftTelN_length, + gen.minorTypes_length] + omega) + have hmlu := Lookup.of_getElem? (by + simpa only [List.singleton_append, + List.append_assoc] using hM) + rw [show gen.motiveType.liftN + (gen.idxTel.length + + gen.block.ctorPairs.length + 1 + 1) = + (gen.motiveType.liftN + (gen.block.ctorPairs.length + 1)).liftN + (gen.idxTel.length + 1) from by + rw [VExpr.liftN_liftN] + congr 1 + omega, + gen.motiveType_liftN] at hmlu + have hfun : env.HasType (gen.recUvars) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length) :: + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)))) + (.bvar + (gen.idxTel.length + + gen.block.ctorPairs.length + 1)) + ((VExpr.forallN + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.block.ctorPairs.length + 1 + + gen.idxTel.length) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort gen.motiveLevel))).liftN + (1 + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0).length)) := by + exact .bvar (by + simpa [List.append_assoc, VExpr.liftTelN_length, + Nat.add_comm] using hmlu) + have hMapp := HasType.appN_selfSpine + (As := VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (Δ := [VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)]) + (Γ := gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + (f := .bvar + (gen.idxTel.length + + gen.block.ctorPairs.length + 1)) + hfun + have h0 : + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length) :: + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))))[0]? = + some (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) := rfl + have harg := HasType.bvar + (env := env) (U := gen.recUvars) + (Lookup.of_getElem? h0) + have harg' : env.HasType (gen.recUvars) + ([VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)] ++ + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (.bvar 0) + ((VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.block.ctorPairs.length + 1 + + gen.idxTel.length) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)).liftN 1) := by + simpa [List.append_assoc, Nat.add_comm, + Nat.add_left_comm, Nat.add_assoc] using harg + have happ := HasType.app hMapp harg' + exact ⟨_, by + simpa [GenerationChecked.recType, List.append_assoc, + VExpr.liftTelN_length] using happ⟩ + +/-- The mixed generated recursor constant is well formed. -/ +theorem recursor_wf : gen.recursor.WF env := + S.recType_isType + +end GenerationEnv + +theorem minorTypes_getElem? {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} : + ∀ (cs : List VConstVal) (i₀ q : Nat), + (minorTypes U T np ty cs i₀)[q]? = + cs[q]?.map fun c => VExpr.liftN (i₀+q) (minorType U T np ty c) + | [], _, q => by simp [minorTypes] + | c :: cs, i₀, 0 => by simp [minorTypes] + | c :: cs, i₀, q+1 => by + simp only [minorTypes, List.getElem?_cons_succ] + rw [minorTypes_getElem? cs (i₀+1) q, show i₀+1+q = i₀+(q+1) from by omega] + +theorem minorTypesRec_getElem? {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} : + ∀ (cs : List VConstVal) (i₀ q : Nat), + (minorTypesRec U T np ty cs i₀)[q]? = + cs[q]?.map fun c => VExpr.liftN (i₀+q) (minorTypeRec U T np ty c) + | [], _, q => by simp [minorTypesRec] + | c :: cs, i₀, 0 => by simp [minorTypesRec] + | c :: cs, i₀, q+1 => by + simp only [minorTypesRec, List.getElem?_cons_succ] + rw [minorTypesRec_getElem? cs (i₀+1) q, + show i₀+1+q = i₀+(q+1) from by omega] + +theorem recApp'_levelWF {U : Nat} {T : Name} {np off : Nat} : + (recApp' U T np off).LevelWF (U+1) := + VExpr.LevelWF.appN (f := .const T (VLevel.params' U 1)) VLevel.params'_one_wf + (bvarRevRange_levelWF _ _) + +theorem idxTel_length {U np : Nat} {ty : VInductiveType} : + (idxTel U np ty).length = (ctorFields (VExpr.dropN np ty.type)).length := + List.length_map .. + +theorem idxTel_levelWF {U np : Nat} {ty : VInductiveType} : + ∀ A ∈ idxTel U np ty, A.LevelWF (U+1) := by + intro A hA + obtain ⟨A₀, -, rfl⟩ := List.mem_map.1 hA + exact VExpr.LevelWF.instL VLevel.params'_one_wf + +theorem ctorIdxs_length {U np : Nat} {c : VConstVal} : + (ctorIdxs U np c).length = + (recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type))).length := + List.length_map .. + +theorem ctorIdxs_levelWF {U np : Nat} {c : VConstVal} : + ∀ e ∈ ctorIdxs U np c, e.LevelWF (U+1) := by + intro e he + obtain ⟨e₀, -, rfl⟩ := List.mem_map.1 he + exact VExpr.LevelWF.instL VLevel.params'_one_wf + +theorem recPairsR_lt {U : Nat} {T : Name} {np ni : Nat} {c : VConstVal} : + ∀ q ∈ recPairsR U T np ni c, q.1 < (ctorFields (VExpr.dropN np c.type)).length := by + intro q hq + obtain ⟨⟨j, idxs⟩, hmem, rfl⟩ := List.mem_map.1 hq + simpa using recPairs_lt _ hmem + +theorem recPairsR_idx_levelWF {U : Nat} {T : Name} {np ni : Nat} {c : VConstVal} : + ∀ q ∈ recPairsR U T np ni c, ∀ e ∈ q.2, e.LevelWF (U+1) := by + intro q hq e he + obtain ⟨⟨j, idxs⟩, -, rfl⟩ := List.mem_map.1 hq + obtain ⟨e₀, -, rfl⟩ := List.mem_map.1 he + exact VExpr.LevelWF.instL VLevel.params'_one_wf + +/-- Unpack a recursor-universe recursive position: the underlying field and +its (declaration-universe) index arguments. -/ +theorem recPairsR_mem {U : Nat} {T : Name} {np ni : Nat} {c : VConstVal} {q} + (hq : q ∈ recPairsR U T np ni c) : + ∃ B, (ctorFields (VExpr.dropN np c.type))[q.1]? = some B ∧ + isRecField U T np ni q.1 B = true ∧ + q.2 = (recFieldIdxs np B).map (VExpr.instL (VLevel.params' U 1)) := by + obtain ⟨⟨j, idxs⟩, hmem, rfl⟩ := List.mem_map.1 hq + obtain ⟨B, hB, hrec, hidx⟩ := recPairs_getElem _ hmem + exact ⟨B, by simpa using hB, hrec, by + simpa using congrArg + (List.map (VExpr.instL (ElimMode.large.sourceLevels U))) hidx⟩ + +/-- Recursor-universe transport preserves each recursive argument's source +field position. -/ +theorem recArgsR_lt {U : Nat} {T : Name} {np ni : Nat} {c : VConstVal} : + ∀ r ∈ recArgsR U T np ni c, + r.fieldIndex < (ctorFields (VExpr.dropN np c.type)).length := by + intro r hr + obtain ⟨r₀, hr₀, rfl⟩ := List.mem_map.1 hr + simpa [RecArg.instL] using recArgs_lt _ hr₀ + +/-- Every generated recursive-target index is level-well-formed in the +recursor universe context. -/ +theorem recArgsR_idx_levelWF {U : Nat} {T : Name} {np ni : Nat} {c : VConstVal} : + ∀ r ∈ recArgsR U T np ni c, ∀ e ∈ r.indices, e.LevelWF (U+1) := by + intro r hr e he + obtain ⟨r₀, -, rfl⟩ := List.mem_map.1 hr + obtain ⟨e₀, -, rfl⟩ := List.mem_map.1 he + exact VExpr.LevelWF.instL VLevel.params'_one_wf + +/-- Every generated recursive-Pi domain is level-well-formed after universe +transport. -/ +theorem recArgsR_binder_levelWF {U : Nat} {T : Name} {np ni : Nat} {c : VConstVal} : + ∀ r ∈ recArgsR U T np ni c, ∀ A ∈ r.binders, A.LevelWF (U+1) := by + intro r hr A hA + obtain ⟨r₀, -, rfl⟩ := List.mem_map.1 hr + obtain ⟨A₀, -, rfl⟩ := List.mem_map.1 hA + exact VExpr.LevelWF.instL VLevel.params'_one_wf + +/-- Unpack a recursor-universe recursive descriptor to the source field and +its declaration-universe analysis result. -/ +theorem recArgsR_mem {U : Nat} {T : Name} {np ni : Nat} {c : VConstVal} {r} + (hr : r ∈ recArgsR U T np ni c) : + ∃ r₀ B, r = r₀.instL (VLevel.params' U 1) ∧ + (ctorFields (VExpr.dropN np c.type))[r₀.fieldIndex]? = some B ∧ + recArg? U T np ni r₀.fieldIndex B = some r₀ := by + obtain ⟨r₀, hr₀, rfl⟩ := List.mem_map.1 hr + obtain ⟨B, hB, hrec⟩ := recArgs_getElem _ hr₀ + exact ⟨r₀, B, rfl, by simpa using hB, hrec⟩ + +theorem motiveType_levelWF {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} : + (motiveType U T np ty).LevelWF (U+1) := by + refine VExpr.LevelWF.forallN idxTel_levelWF ⟨?_, Nat.succ_pos U⟩ + refine VExpr.LevelWF.appN (f := .const T (VLevel.params' U 1)) VLevel.params'_one_wf + fun e h => ?_ + rcases List.mem_append.1 h with h | h + · exact bvarRevRange_levelWF _ _ _ h + · exact bvarRevRange_levelWF _ _ _ h + +theorem motiveType_liftN {U : Nat} {T : Name} {np n : Nat} {ty : VInductiveType} : + (motiveType U T np ty).liftN n = + VExpr.forallN (VExpr.liftTelN n (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (n + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) := by + rw [show motiveType U T np ty = VExpr.forallN (idxTel U np ty) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (idxTel U np ty).length np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) from rfl, + VExpr.liftN_forallN] + refine congrArg _ ?_ + show VExpr.forallE _ _ = VExpr.forallE _ _ + refine congr (congrArg _ ?_) rfl + rw [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + rfl + +theorem liftTelN_levelWF {Uv n : Nat} : ∀ {tel : List VExpr} {k : Nat}, + (∀ A ∈ tel, A.LevelWF Uv) → ∀ A ∈ VExpr.liftTelN n tel k, A.LevelWF Uv + | [], _, _, _, h => nomatch h + | _ :: tel, k, hAs, A', h => by + rcases List.mem_cons.1 h with rfl | h + · exact (hAs _ (.head _)).liftN + · exact liftTelN_levelWF (fun A h => hAs _ (.tail _ h)) A' h + +theorem RecArg.minorBinders_levelWF {Uv m p : Nat} {r : RecArg} + (hbind : ∀ A ∈ r.binders, A.LevelWF Uv) : + ∀ A ∈ r.minorBinders m p, A.LevelWF Uv := + liftTelN_levelWF (liftTelN_levelWF hbind) + +theorem RecArg.minorIH_levelWF {Uv m p : Nat} {r : RecArg} + (hbind : ∀ A ∈ r.binders, A.LevelWF Uv) + (hidx : ∀ e ∈ r.indices, e.LevelWF Uv) : + (r.minorIH m p).LevelWF Uv := by + simp only [RecArg.minorIH] + refine VExpr.LevelWF.forallN (r.minorBinders_levelWF hbind) + (VExpr.LevelWF.appN (f := .bvar _) trivial fun e he => ?_) + rcases List.mem_append.1 he with he | he + · obtain ⟨e₀, he₀, rfl⟩ := List.mem_map.1 he + exact ((hidx e₀ he₀).liftN).liftN + · rcases List.mem_cons.1 he with rfl | he + · exact VExpr.LevelWF.appN (f := .bvar _) trivial (bvarRevRange_levelWF _ _) + · cases he + +theorem ihsFromRecArgs_levelWF {Uv m : Nat} : + ∀ (rs : List RecArg) (p : Nat), + (∀ r ∈ rs, ∀ A ∈ r.binders, A.LevelWF Uv) → + (∀ r ∈ rs, ∀ e ∈ r.indices, e.LevelWF Uv) → + ∀ e ∈ ihsFromRecArgs m rs p, e.LevelWF Uv + | [], _, _, _, _, h => nomatch h + | r :: rs, p, hbind, hidx, e, h => by + rcases List.mem_cons.1 h with rfl | h + · exact r.minorIH_levelWF + (hbind r (.head _)) (hidx r (.head _)) + · exact ihsFromRecArgs_levelWF rs (p+1) + (fun q hq => hbind q (.tail _ hq)) + (fun q hq => hidx q (.tail _ hq)) e h + +theorem minorType_levelWF {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} + {c : VConstVal} : (minorType U T np ty c).LevelWF (U+1) := by + simp only [minorType] + refine VExpr.LevelWF.forallN (liftTelN_levelWF fun B hB => ?_) + (VExpr.LevelWF.forallN (ihsFrom_levelWF _ _ recPairsR_idx_levelWF) ?_) + · obtain ⟨B₀, _, rfl⟩ := List.mem_map.1 hB + exact VExpr.LevelWF.instL VLevel.params'_one_wf + · refine VExpr.LevelWF.appN (f := .bvar _) trivial fun e h => ?_ + rcases List.mem_append.1 h with h | h + · obtain ⟨e₀, he₀, rfl⟩ := List.mem_map.1 h + exact ((ctorIdxs_levelWF _ he₀).liftN).liftN + · rcases List.mem_cons.1 h with rfl | h + · refine VExpr.LevelWF.appN (f := .const c.name (VLevel.params' U 1)) + VLevel.params'_one_wf fun e h => ?_ + rcases List.mem_append.1 h with h | h + · exact bvarRevRange_levelWF _ _ _ h + · exact bvarRevRange_levelWF _ _ _ h + · cases h + +theorem minorTypeRec_levelWF {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} + {c : VConstVal} : (minorTypeRec U T np ty c).LevelWF (U+1) := by + simp only [minorTypeRec] + refine VExpr.LevelWF.forallN (liftTelN_levelWF fun B hB => ?_) + (VExpr.LevelWF.forallN + (ihsFromRecArgs_levelWF _ _ recArgsR_binder_levelWF recArgsR_idx_levelWF) ?_) + · obtain ⟨B₀, _, rfl⟩ := List.mem_map.1 hB + exact VExpr.LevelWF.instL VLevel.params'_one_wf + · refine VExpr.LevelWF.appN (f := .bvar _) trivial fun e h => ?_ + rcases List.mem_append.1 h with h | h + · obtain ⟨e₀, he₀, rfl⟩ := List.mem_map.1 h + exact ((ctorIdxs_levelWF _ he₀).liftN).liftN + · rcases List.mem_cons.1 h with rfl | h + · refine VExpr.LevelWF.appN (f := .const c.name (VLevel.params' U 1)) + VLevel.params'_one_wf fun e h => ?_ + rcases List.mem_append.1 h with h | h + · exact bvarRevRange_levelWF _ _ _ h + · exact bvarRevRange_levelWF _ _ _ h + · cases h + +theorem minorTypes_levelWF {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} : + ∀ (cs : List VConstVal) (i : Nat), ∀ e ∈ minorTypes U T np ty cs i, e.LevelWF (U+1) + | _ :: cs, i, e, h => by + rcases List.mem_cons.1 h with rfl | h + · exact minorType_levelWF.liftN + · exact minorTypes_levelWF cs (i+1) e h + +theorem minorTypesRec_levelWF {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} : + ∀ (cs : List VConstVal) (i : Nat), + ∀ e ∈ minorTypesRec U T np ty cs i, e.LevelWF (U+1) + | _ :: cs, i, e, h => by + rcases List.mem_cons.1 h with rfl | h + · exact minorTypeRec_levelWF.liftN + · exact minorTypesRec_levelWF cs (i+1) e h + +theorem recType_levelWF {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} : + (recType U T np ty).LevelWF (U+1) := by + refine VExpr.LevelWF.forallN (fun A hA => ?_) + ⟨motiveType_levelWF, VExpr.LevelWF.forallN (minorTypes_levelWF _ _) + (VExpr.LevelWF.forallN (liftTelN_levelWF idxTel_levelWF) + ⟨?_, ?_, trivial⟩)⟩ + · obtain ⟨A₀, _, rfl⟩ := List.mem_map.1 hA + exact VExpr.LevelWF.instL VLevel.params'_one_wf + · refine VExpr.LevelWF.appN (f := .const T (VLevel.params' U 1)) VLevel.params'_one_wf + fun e h => ?_ + rcases List.mem_append.1 h with h | h + · exact bvarRevRange_levelWF _ _ _ h + · exact bvarRevRange_levelWF _ _ _ h + · exact VExpr.LevelWF.appN (f := .bvar _) trivial (bvarRevRange_levelWF _ _) + +theorem recTypeRec_levelWF {U : Nat} {T : Name} {np : Nat} {ty : VInductiveType} : + (recTypeRec U T np ty).LevelWF (U+1) := by + refine VExpr.LevelWF.forallN (fun A hA => ?_) + ⟨motiveType_levelWF, VExpr.LevelWF.forallN (minorTypesRec_levelWF _ _) + (VExpr.LevelWF.forallN (liftTelN_levelWF idxTel_levelWF) + ⟨?_, ?_, trivial⟩)⟩ + · obtain ⟨A₀, _, rfl⟩ := List.mem_map.1 hA + exact VExpr.LevelWF.instL VLevel.params'_one_wf + · refine VExpr.LevelWF.appN (f := .const T (VLevel.params' U 1)) VLevel.params'_one_wf + fun e h => ?_ + rcases List.mem_append.1 h with h | h + · exact bvarRevRange_levelWF _ _ _ h + · exact bvarRevRange_levelWF _ _ _ h + · exact VExpr.LevelWF.appN (f := .bvar _) trivial (bvarRevRange_levelWF _ _) + +/-- Consume the induction-hypothesis telescope with well-typed values. -/ +theorem hasType_appN_ihs {env : VEnv} {U : Nat} {Γ : List VExpr} {m k : Nat} + {argOf : Nat × List VExpr → VExpr} {Dfin : VExpr} : + ∀ {rs : List (Nat × List VExpr)} {g : VExpr}, (∀ q ∈ rs, q.1 < m) → + (∀ q ∈ rs, env.HasType U Γ (argOf q) + (VExpr.appN (.bvar (k + m)) + ((q.2.map fun e => ((e.liftN 1 q.1).liftN (m-q.1)).liftN k m) ++ + [.bvar (m-1-q.1)]))) → + env.HasType U Γ g (VExpr.forallN (ihsR m k rs 0) (Dfin.liftN rs.length)) → + env.HasType U Γ (g.appN (rs.map argOf)) Dfin + | [], g, _, _, hg => by simpa [ihsR] using hg + | (j, idxs) :: rs, g, hm, hargs, hg => by + have happ := VEnv.HasType.app hg (hargs (j, idxs) (.head _)) + simp only [List.length_cons] at happ + rw [show Dfin.liftN (rs.length+1) = + (Dfin.liftN rs.length).liftN 1 (0 + rs.length) from by + rw [Nat.zero_add, VExpr.liftN'_liftN' (Nat.zero_le _) (by omega)], + ihsR_liftN1 m k rs 0 0 (Nat.le_refl _) (fun q hq => hm q (.tail _ hq)) + (Dfin.liftN rs.length), + VExpr.inst_liftN1] at happ + exact hasType_appN_ihs (rs := rs) (fun q hq => hm q (.tail _ hq)) + (fun q hq => hargs q (.tail _ hq)) happ + +/-- Consume a normalized functional-IH telescope with one generated recursive +call per recursive argument. -/ +theorem hasType_appN_ruleIHs {env : VEnv} {U : Nat} {Γ : List VExpr} {m k : Nat} + {argOf : RecArg → VExpr} {Dfin : VExpr} : + ∀ {rs : List RecArg} {g : VExpr}, + (∀ r ∈ rs, env.HasType U Γ (argOf r) (r.ruleIH m k)) → + env.HasType U Γ g + (VExpr.forallN (ruleIHs m k rs 0) (Dfin.liftN rs.length)) → + env.HasType U Γ (g.appN (rs.map argOf)) Dfin + | [], g, _, hg => by simpa [ruleIHs] using hg + | r :: rs, g, hargs, hg => by + have happ := VEnv.HasType.app hg (by + simpa [ruleIHs] using hargs r (.head _)) + simp only [List.length_cons] at happ + rw [show Dfin.liftN (rs.length+1) = + (Dfin.liftN rs.length).liftN 1 (0+rs.length) from by + rw [Nat.zero_add, VExpr.liftN'_liftN' (Nat.zero_le _) (by omega)], + ruleIHs_liftN1 m k rs 0 0 (Nat.le_refl _) (Dfin.liftN rs.length), + VExpr.inst_liftN1] at happ + exact hasType_appN_ruleIHs (rs := rs) + (fun q hq => hargs q (.tail _ hq)) happ + +namespace GenerationEnv + +variable {source : VInductDecl} {gen : GenerationChecked source} + {env : VEnv} (S : GenerationEnv gen env) +include S +-- `S` is included throughout so every lemma below is reachable as `S.lemma`, +-- including those whose statement and proof never mention it. +set_option linter.unusedSectionVars false + +/-! ## Mixed iota-rule preservation -/ + +/-- Syntactic universe well-formedness follows from semantic well-formedness +of the closed mixed recursor type. -/ +theorem recType_levelWF : + gen.recType.LevelWF (gen.recUvars) := by + obtain ⟨_, h⟩ := S.recType_isType + exact (h.levelWF trivial).1 + +/-- The mixed recursor type is closed. -/ +theorem recType_closedN : gen.recType.ClosedN 0 := by + obtain ⟨_, h⟩ := S.recType_isType + exact VExpr.WF.closedN S.ord ⟨_, h⟩ trivial + +/-- The inserted mixed recursor constant at its identity universe list. -/ +theorem recursor_hasType + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) {Γ} : + env.HasType (gen.recUvars) Γ + (.const (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + gen.recType := by + have h := HasType.const (Γ := Γ) hrec + VLevel.params_wf VLevel.params_length + rw [show gen.recursor.uvars = + gen.recUvars from rfl, + show gen.recursor.type = gen.recType from rfl] at h + rwa [S.recType_levelWF.instL_id] at h + +/-- Apply the mixed recursor to parameters, motive, and every constructor +minor. The remaining type binds the indices and major premise. -/ +theorem recBase_hasType + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) + (Δ : List VExpr) : + env.HasType (gen.recUvars) + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (.const (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange Δ.length + (source.nparams + + gen.block.ctorPairs.length + 1))) + ((VExpr.forallN + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.app + (VExpr.appN + (.bvar + (gen.idxTel.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length)) + (.bvar 0)))).liftN Δ.length) := by + have hf : env.HasType (gen.recUvars) + (Δ ++ + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes).reverse ++ []) + (.const (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + ((VExpr.forallN + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes) + (VExpr.forallN + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.app + (VExpr.appN + (.bvar + (gen.idxTel.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length)) + (.bvar 0))))).liftN + (Δ.length + + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes).length)) := by + rw [show VExpr.forallN + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes) + (VExpr.forallN + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.app + (VExpr.appN + (.bvar + (gen.idxTel.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length)) + (.bvar 0)))) = + gen.recType from by + rw [VExpr.forallN_append] + rfl, + S.recType_closedN.liftN_eq (Nat.zero_le _)] + exact S.recursor_hasType hrec + have hspine := HasType.appN_selfSpine + (env := env) (U := gen.recUvars) hf + simp only [List.reverse_append, List.reverse_cons, List.append_nil, List.append_assoc, + List.singleton_append, List.length_append, List.length_cons, gen.minorTypes_length] at hspine + rw [show gen.paramsTel.length = source.nparams from by + simp [GenerationChecked.paramsTel, + S.generationParams_length], + VExpr.bvarRevRange_congr' Δ.length + (show source.nparams + + (gen.block.ctorPairs.length + 1) = + source.nparams + + gen.block.ctorPairs.length + 1 by omega)] at hspine + simpa [List.append_assoc] using hspine + +/-- Apply the inserted mixed recursor to a typed index spine and major. -/ +theorem recApp_hasType + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) + (Δ : List VExpr) {idxs : List VExpr} {a : VExpr} + (hidx : env.SpineWF (gen.recUvars) + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + (Δ.length + + gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + idxs + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + (hlen : idxs.length = gen.idxTel.length) + (ha : env.HasType (gen.recUvars) + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + a + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (Δ.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + idxs))) : + env.HasType (gen.recUvars) + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (VExpr.appN + (.const (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange Δ.length + (source.nparams + + gen.block.ctorPairs.length + 1))) + (idxs ++ [a])) + (VExpr.appN + (.bvar + (Δ.length + + gen.block.ctorPairs.length)) + (idxs ++ [a])) := by + have hb := S.recBase_hasType hrec Δ + rw [VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ + (show gen.block.ctorPairs.length + 1 + + Δ.length = + Δ.length + gen.block.ctorPairs.length + 1 by omega)] at hb + have hcod : + (VExpr.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.app + (VExpr.appN + (.bvar + (gen.idxTel.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length)) + (.bvar 0))).liftN Δ.length + (0 + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + gen.idxTel 0).length) = + VExpr.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.app + (VExpr.appN + (.bvar + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length)) + (.bvar 0)) := by + rw [VExpr.liftTelN_length, Nat.zero_add] + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + VExpr.bvarRevRange_congr source.nparams + (show Δ.length + + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) = + gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1 by omega)] + rfl + · show VExpr.app _ _ = VExpr.app _ _ + congr 1 + · rw [VExpr.liftN_appN, + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + show VExpr.appN + (.bvar (liftVar Δ.length + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) + (gen.idxTel.length + 1))) _ = _ + rw [liftVar_le (by omega), + show Δ.length + + (gen.idxTel.length + + gen.block.ctorPairs.length + 1) = + gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1 by omega] + rw [hcod] at hb + have hshape := hidx.retarget + (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)) + (.sort gen.motiveLevel)) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ + (C := .const gen.block.sourceType.name + (gen.sourceLevels)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ + (by rw [hlen]; omega), + show gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1 - idxs.length = + Δ.length + gen.block.ctorPairs.length + 1 from by + rw [hlen] + omega, + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hfull := hshape.snoc ha + simp only [VExpr.inst] at hfull + change env.SpineWF (gen.recUvars) _ + (VExpr.forallN + (VExpr.liftTelN + (Δ.length + gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (VExpr.forallN + [VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 gen.idxTel.length)] + (.sort gen.motiveLevel))) + (idxs ++ [a]) (.sort gen.motiveLevel) at hfull + rw [← VExpr.forallN_append] at hfull + have hfullLen : (idxs ++ [a]).length = + (VExpr.liftTelN + (Δ.length + + gen.block.ctorPairs.length + 1) + gen.idxTel 0 ++ + [VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + gen.idxTel.length)]).length := by + simp only [List.length_append, List.length_singleton, + VExpr.liftTelN_length, hlen] + have hactual := hfull.retarget hfullLen + (VExpr.app + (VExpr.appN + (.bvar + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length)) + (.bvar 0)) + rw [VExpr.forallN_append] at hactual + have happ := hactual.hasType_appN hb + rw [show VExpr.app + (VExpr.appN + (.bvar + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length)) + (.bvar 0) = + VExpr.appN + (.bvar + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 0 + (gen.idxTel.length + 1)) from by + rw [VExpr.bvarRevRange_congr' 0 + (show gen.idxTel.length + 1 = + 1 + gen.idxTel.length by omega), + ← VExpr.bvarRevRange_append + gen.idxTel.length 1] + simpa [VExpr.bvarRevRange, VExpr.appN] using + (VExpr.appN_append + (.bvar + (gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1)) + (VExpr.bvarRevRange 1 gen.idxTel.length) + [VExpr.bvar 0]).symm, + VExpr.instRev_appN, + VExpr.instRev_bvar_ge _ (by + simp only [List.length_append, + List.length_singleton] + rw [hlen] + omega), + VExpr.bvarRevRange_congr' 0 + (show gen.idxTel.length + 1 = + (idxs ++ [a]).length by simp [hlen]), + VExpr.map_instRev_bvarRevRange] at happ + rw [show gen.idxTel.length + Δ.length + + gen.block.ctorPairs.length + 1 - + (idxs ++ [a]).length = + Δ.length + gen.block.ctorPairs.length from by + simp only [List.length_append, List.length_singleton] + rw [hlen] + omega] at happ + simpa [List.length_append, hlen] using happ + +/-- The mixed motive variable applied to an index spine and major. -/ +theorem motiveApp_hasType + (Δ : List VExpr) {idxs : List VExpr} {a : VExpr} + (hidx : env.SpineWF (gen.recUvars) + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + (Δ.length + + gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + idxs + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + (hlen : idxs.length = gen.idxTel.length) + (ha : env.HasType (gen.recUvars) + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + a + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (Δ.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + idxs))) : + env.HasType (gen.recUvars) + (Δ ++ (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (.bvar + (Δ.length + + gen.block.ctorPairs.length)) + (idxs ++ [a])) + (.sort gen.motiveLevel) := by + have hM := getElem?_rstack3 Δ + gen.minorTypes.reverse gen.motiveType + gen.paramsTel.reverse + (i := Δ.length + gen.block.ctorPairs.length) + (by simp only [List.length_reverse, + gen.minorTypes_length]) + exact gen.motiveVarApp_hasType + (.bvar (Lookup.of_getElem? hM)) + hidx hlen ha + +/-- The raw constructor-headed major in the complete mixed rule context. -/ +theorem ctorAppRule_hasType {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.HasType (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + (ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) := by + have h := S.ctorApp_transport hctor + (gen.minorTypes.reverse ++ [gen.motiveType]) + (g := gen.block.ctorPairs.length + 1) + (by simp [gen.minorTypes_length]) + [] (d := 0) rfl + rw [VExpr.bvarRevRange_congr source.nparams + (show + 0 + (gen.block.ctorPairs.length + 1 + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1 by omega)] at h + simpa [List.append_assoc] using h + +/-- The complete mixed rule binder telescope is well formed. -/ +theorem ruleBinders_onTel {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.OnTel (gen.recUvars) [] + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes ++ + VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0) := by + have hF₀ := S.fields_onTel_minor hctor + have hF := hF₀.weakN S.ord + (Ctx.LiftN.zero + (Γ := gen.motiveType :: gen.paramsTel.reverse) + gen.minorTypes.reverse) + rw [VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ + (show 1 + gen.minorTypes.reverse.length = + gen.block.ctorPairs.length + 1 by + simp [gen.minorTypes_length, Nat.add_comm])] at hF + refine OnTel.append + (OnTel.append S.paramsTel_onTel ⟨?_, ?_⟩) ?_ + · simpa only [List.append_nil] using S.motive_isType + · simpa only [List.append_nil] using S.minorTypes_onTel + · simpa only [List.append_nil, List.append_assoc, + List.reverse_append, List.reverse_cons, + List.singleton_append] using hF + +/-- The type recorded on every mixed iota rule is itself a type. -/ +theorem ruleType_isType {i : Nat} {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) : + env.IsType (gen.recUvars) [] + ((gen.rule i ctor).type) := by + show env.IsType (gen.recUvars) [] + (VExpr.forallN + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes ++ + VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0) + (VExpr.appN + (.bvar + (gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)]))) + refine IsType.forallN (S.ruleBinders_onTel hctor) ?_ + simp only [List.reverse_append, List.reverse_cons, + List.append_nil, List.append_assoc, + List.singleton_append] + have hSp₀ := S.result_transport hctor + (gen.minorTypes.reverse ++ [gen.motiveType]) + (g := gen.block.ctorPairs.length + 1) + (by simp [gen.minorTypes_length]) + [] (d := 0) rfl + have hSp : env.SpineWF (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + simpa [List.append_assoc, Nat.add_assoc] using hSp₀ + have hidxLen : + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length).length = + gen.idxTel.length := by + simp only [List.length_map, + NormalizedCtor.resultIndicesR, + GenerationChecked.idxTel] + exact (S.viewResultIndices_length hctor).trans + gen.shape.2.2.1.symm + have hctorApp := S.ctorAppRule_hasType hctor + have hSp' : env.SpineWF (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0).reverse.length + + gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) + (.sort (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + simpa only [List.length_reverse, + VExpr.liftTelN_length] using hSp + have hctorApp' : env.HasType (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0).reverse.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + (ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) := by + simpa only [List.length_reverse, + VExpr.liftTelN_length] using hctorApp + refine ⟨gen.motiveLevel, ?_⟩ + have hm := S.motiveApp_hasType + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse + hSp' hidxLen hctorApp' + rw [List.length_reverse, VExpr.liftTelN_length, + show + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length = + gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length by omega, + show + gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + 1 = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1 by omega] at hm + exact hm + +/-- A retained recursive descriptor generates a well-typed direct or +lambda-valued recursive call in the complete mixed rule context. -/ +theorem ruleCall_hasType {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) + {r : RecArg} + (hr : r ∈ ctor.recArgsR source.uvars gen.elimination) : + env.HasType (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (r.ruleCall + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + gen.block.ctorPairs.length + (VExpr.appN + (.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + (source.nparams + + gen.block.ctorPairs.length + 1)))) + (r.ruleIH + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + gen.block.ctorPairs.length) := by + obtain ⟨r₀, hr₀, rfl⟩ := + NormalizedCtor.recArgsR_mem hr + obtain ⟨Bview, hBview, hrecArg⟩ := + S.viewRecArg_data hctor hr₀ + let ls := gen.sourceLevels + let r := r₀.instL ls + let Bs := ctor.fieldsR source.uvars source.nparams gen.elimination + let m := Bs.length + let k := gen.block.ctorPairs.length + let j := r₀.fieldIndex + let Fs := VExpr.liftTelN (k+1) Bs 0 + let As := r.ruleBinders m k + let idxs := r.indices.map fun e => + (e.liftN (k+1) + (r.fieldIndex+r.binders.length)).liftN + (m-r.fieldIndex) r.binders.length + let Γ := Fs.reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + have hjm : j < m := by + have hview := S.viewRecArg_lt hctor hr₀ + have hfields := + (gen.shape.2.2.2.2.2 ctor hctor).2.2.2 + simp only [j, m, Bs, NormalizedCtor.fieldsR_length] + omega + have hjraw : + r₀.fieldIndex < + (ctor.rawFields source.nparams).length := by + simpa [j, m, Bs, + NormalizedCtor.fieldsR_length] using hjm + let Braw := + (ctor.rawFields source.nparams)[r₀.fieldIndex] + have hBraw : + (ctor.rawFields source.nparams)[r₀.fieldIndex]? = + some Braw := + List.getElem?_eq_getElem hjraw + have hFsLen : Fs.length = m := by + simp [Fs, m, VExpr.liftTelN_length] + have ht := S.recArg_transport hctor hr₀ + (gen.minorTypes.reverse ++ [gen.motiveType]) + (g := k+1) (by simp [k, gen.minorTypes_length]) + (Fs.drop j).reverse (d := m-j) (by + simp only [List.length_reverse, List.length_drop, + hFsLen]) + dsimp only [r, j, RecArg.instL] at ht + have hctx : + (Fs.drop j).reverse ++ + ((VExpr.liftTelN (k+1) + (Bs.take j) 0).reverse ++ + ((gen.minorTypes.reverse ++ + [gen.motiveType]) ++ + gen.paramsTel.reverse)) = Γ := by + dsimp only [Γ, Fs] + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc + (((VExpr.liftTelN (k+1) Bs 0).drop j).reverse), + ← List.reverse_append, List.take_append_drop, + List.singleton_append, ← List.append_assoc] + have htel : env.OnTel + (gen.recUvars) Γ As := by + rw [hctx] at ht + simpa [r, As, m, k, j, RecArg.instL, + RecArg.ruleBinders] using ht.1 + have hsp : env.SpineWF (gen.recUvars) + (As.reverse ++ Γ) + (VExpr.forallN + (VExpr.liftTelN + (m+k+r.binders.length+1) + gen.idxTel 0) + (.sort (gen.block.checked.resultLevel.inst ls))) + idxs + (.sort (gen.block.checked.resultLevel.inst ls)) := by + rw [hctx] at ht + simpa [r, As, idxs, m, k, j, ls, + RecArg.instL, RecArg.ruleBinders, + List.append_assoc, + show j + r₀.binders.length + (k+1) + (m-j) = + m+k+r₀.binders.length+1 by omega] using ht.2 + have hF : Γ[m-1-j]? = + some ((Braw.instL ls).liftN (k+1) j) := by + dsimp only [Γ, Fs] + rw [List.getElem?_append_left + (by + simp only [List.length_reverse, + VExpr.liftTelN_length] + omega), + List.getElem?_reverse (by rw [hFsLen]; omega), + VExpr.liftTelN_length, + show m - 1 - (m - 1 - j) = j by omega, + VExpr.liftTelN_getElem?, + NormalizedCtor.fieldsR_getElem?, hBraw] + simp [ls] + have hlu := Lookup.of_getElem? hF + dsimp only [j, r] at hlu + rw [show m-1-r₀.fieldIndex+1 = + m-r₀.fieldIndex by omega] at hlu + have hf0 := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) hlu + obtain ⟨u, hdom₀⟩ := + S.emittedField_defeq hctor hBraw hBview + have hdom₁ := hdom₀.instL + (U' := gen.recUvars) + gen.sourceLevels_wf + have hdomChecked : env.IsDefEq (gen.recUvars) + ((ctor.fieldsR source.uvars source.nparams gen.elimination |>.take + r₀.fieldIndex).reverse ++ + (gen.block.checked.params.map (VExpr.instL ls)).reverse) + (Braw.instL ls) (Bview.instL ls) ((VExpr.sort u).instL ls) := by + simpa [NormalizedCtor.fieldsR, List.map_append, + List.map_reverse, List.map_take] using hdom₁ + have hprefix := S.generationFieldPrefix_ctx_rec hctor r₀.fieldIndex + have hdomGeneration := hdomChecked.defeqDFC S.ord + (hprefix.symm S.ord) + have hjlen : + (Bs.take r₀.fieldIndex).length = + r₀.fieldIndex := by + simp only [Bs, NormalizedCtor.fieldsR, + List.length_take, List.length_map] + omega + have Wmid := Ctx.LiftN.consTel + (n := k+1) + (Bs.take r₀.fieldIndex) + (Ctx.LiftN.zero + (n := k+1) + (Γ := gen.paramsTel.reverse) + (gen.minorTypes.reverse ++ + [gen.motiveType]) + (h := by simp [k, gen.minorTypes_length])) + rw [hjlen, Nat.add_zero] at Wmid + have hdom₂ := hdomGeneration.weakN S.ord Wmid + have Wstack := Ctx.LiftN.zero + (n := m-j) + (Γ := (VExpr.liftTelN (k+1) + (Bs.take j) 0).reverse ++ + ((gen.minorTypes.reverse ++ + [gen.motiveType]) ++ + gen.paramsTel.reverse)) + (Fs.drop j).reverse + (h := by + simp only [List.length_reverse, List.length_drop, + hFsLen]) + have hdom₃ := hdom₂.weakN S.ord Wstack + rw [hctx] at hdom₃ + have hfView := hdom₃.defeq hf0 + have hfield := recArg_rule_fieldType + hrecArg m k (by simpa [j] using hjm) gen.elimination + simp only [RecArg.instL] at hfield + dsimp only [j] at hfView + simp only [Nat.add_zero] at hfView + rw [hfield] at hfView + have hf := hfView.weakN S.ord + (Ctx.LiftN.zero (Γ := Γ) As.reverse) + have hmajor := VEnv.HasType.appN_selfSpine + (env := env) (U := gen.recUvars) + (As := As) + (B := VExpr.appN + (.const gen.block.sourceType.name ls) + (VExpr.bvarRevRange + (m+k+r.binders.length+1) + source.nparams ++ + idxs)) + (Δ := []) (Γ := Γ) (by + simpa [As, r, idxs, j, ls, + RecArg.instL, RecArg.ruleBinders, + List.length_reverse, List.map_map, + Function.comp_def] using hf) + simp only [List.length_nil, VExpr.liftN_zero, + List.nil_append] at hmajor + have hAsLen : + As.length = r.binders.length := by + simp [As, RecArg.ruleBinders, + VExpr.liftTelN_length] + change env.HasType (gen.recUvars) + (As.reverse ++ Γ) + ((VExpr.bvar + (m-1-r.fieldIndex+As.length)).appN + (VExpr.bvarRevRange 0 As.length)) + (VExpr.appN + (.const gen.block.sourceType.name ls) + (VExpr.bvarRevRange + (m+k+r.binders.length+1) + source.nparams ++ + idxs)) at hmajor + rw [hAsLen] at hmajor + have hlen : idxs.length = gen.idxTel.length := by + simpa [idxs, r, RecArg.instL, + GenerationChecked.idxTel] using + (S.viewRecArg_indices_length hctor hr₀).trans + gen.shape.2.2.1.symm + have hcall := S.recApp_hasType hrec + (As.reverse ++ Fs.reverse) + (by + simpa [Γ, List.append_assoc, hAsLen, hFsLen, + Nat.add_comm, Nat.add_left_comm, + Nat.add_assoc] using hsp) + hlen + (by + simpa [Γ, List.append_assoc, hAsLen, hFsLen, + Nat.add_comm, Nat.add_left_comm, + Nat.add_assoc] using hmajor) + have hbaseLift : + (VExpr.appN + (.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange m + (source.nparams+(k+1)))).liftN + r.binders.length = + VExpr.appN + (.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange + (m+r.binders.length) + (source.nparams+(1+k))) := by + rw [VExpr.liftN_appN] + simp only [VExpr.liftN] + rw [bvarRevRange_liftN_ge _ _ _ _ + (Nat.zero_le _)] + rw [show source.nparams+(k+1) = + source.nparams+(1+k) by omega] + apply congrArg (VExpr.appN _) + apply VExpr.bvarRevRange_congr + omega + have hbaseRange : + VExpr.appN + ((VExpr.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)).app + (VExpr.bvar + (source.nparams + + (k + (m + r.binders.length))))) + (VExpr.bvarRevRange + (m+r.binders.length) + (source.nparams+k)) = + VExpr.appN + (.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange + (m+r.binders.length) + (source.nparams+(1+k))) := by + rw [show source.nparams + (k + (m + r.binders.length)) = + (m+r.binders.length) + (source.nparams+k) by omega, + show source.nparams+(1+k) = (source.nparams+k)+1 by omega] + rfl + have hlam := HasType.lamN htel (by + simpa [Γ, Fs, hAsLen, hFsLen, + List.append_assoc, VExpr.liftN_appN, + bvarRevRange_liftN_ge _ _ _ _ + (Nat.zero_le _), + Nat.add_comm, Nat.add_left_comm, + Nat.add_assoc] using hcall) + simp only [VExpr.liftTelN_length] at hlam + rw [hbaseRange] at hlam + simpa only [RecArg.ruleCall, RecArg.ruleIH, + r, Bs, ls, As, idxs, m, k, Γ, Fs, hbaseLift, + VExpr.liftTelN_length, List.append_assoc, + Nat.add_assoc] using hlam + +/-- The selected mixed constructor minor applied to all raw fields and to one +generated direct or functional recursive call for every retained `RecArg`. -/ +theorem minorApp_hasType {i : Nat} {ctor : NormalizedCtor} + (hci : gen.block.ctorPairs[i]? = some ctor) + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) : + env.HasType (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (.bvar + (gen.block.ctorPairs.length - 1 - i + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (VExpr.bvarRevRange 0 + (ctor.fieldsR source.uvars source.nparams gen.elimination).length ++ + List.map (fun r => + r.ruleCall + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + gen.block.ctorPairs.length + (VExpr.appN + (.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + (source.nparams + + gen.block.ctorPairs.length + 1)))) + (ctor.recArgsR source.uvars gen.elimination))) + (VExpr.appN + (.bvar + (gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)])) := by + obtain ⟨hik, -⟩ := + List.getElem?_eq_some_iff.1 hci + have hctor := List.mem_of_getElem? hci + let rs := ctor.recArgsR source.uvars gen.elimination + have hrs : + rs = ctor.recArgsR source.uvars gen.elimination := rfl + have hrsLt : ∀ r ∈ rs, + r.fieldIndex < + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length := by + intro r hr + obtain ⟨r₀, hr₀, rfl⟩ := + NormalizedCtor.recArgsR_mem (hrs ▸ hr) + have hview := S.viewRecArg_lt hctor hr₀ + have hfields := + (gen.shape.2.2.2.2.2 ctor hctor).2.2.2 + simp only [RecArg.instL, + NormalizedCtor.fieldsR_length] + omega + rw [VExpr.appN_append] + have hminorAt : + gen.minorTypes[i]? = + some + (VExpr.liftN i + (GenerationChecked.minorType + (source := source) ctor gen.elimination)) := by + simpa [GenerationChecked.minorTypes, hci] using + gen.minorTypesAux_getElem? + gen.block.ctorPairs 0 i + have hlu0 : + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)))[ + gen.block.ctorPairs.length - 1 - i + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length]? = + some + (VExpr.liftN i + (GenerationChecked.minorType + (source := source) ctor gen.elimination)) := by + rw [getElem?_rstack_mid _ _ _ + (by + simp only [List.length_reverse, + VExpr.liftTelN_length] + omega) + (by + simp only [List.length_reverse, + VExpr.liftTelN_length, + gen.minorTypes_length] + omega), + show + gen.block.ctorPairs.length - 1 - i + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length - + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0).reverse.length = + gen.block.ctorPairs.length - 1 - i by + simp only [List.length_reverse, + VExpr.liftTelN_length] + omega, + List.getElem?_reverse + (by + simp only [gen.minorTypes_length] + omega), + show + gen.minorTypes.length - 1 - + (gen.block.ctorPairs.length - 1 - i) = + i by + simp only [gen.minorTypes_length] + omega, + hminorAt] + have hlu := Lookup.of_getElem? hlu0 + rw [VExpr.liftN_liftN, + show + i + + (gen.block.ctorPairs.length - 1 - i + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + 1) = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length by omega] at hlu + have hminorEq : + (GenerationChecked.minorType + (source := source) ctor gen.elimination).liftN + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length) = + (VExpr.forallN + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0) + ((VExpr.forallN + (ihsFromRecArgs + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + rs 0) + (VExpr.appN + (.bvar + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + rs.length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map + fun e => + (e.liftN 1 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length).liftN + rs.length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (rs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + 1) + source.nparams ++ + VExpr.bvarRevRange rs.length + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)]))).liftN + gen.block.ctorPairs.length + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)).liftN + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length := by + simp only [GenerationChecked.minorType, rs] + conv => lhs; rw [VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ + (show + (1 : Nat) + + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length) = + gen.block.ctorPairs.length + 1 + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length by + omega), + show + (0 : Nat) + + (VExpr.liftTelN 1 + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0).length = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length by + simp [VExpr.liftTelN_length]] + conv => rhs; rw [VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN, + show + (0 : Nat) + + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0).length = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length by + simp [VExpr.liftTelN_length], + VExpr.liftN'_liftN_hi, + Nat.add_comm gen.block.ctorPairs.length + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length] + have hfields := HasType.appN_selfSpine + (env := env) (U := gen.recUvars) + (As := VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0) + (B := + (VExpr.forallN + (ihsFromRecArgs + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + rs 0) + (VExpr.appN + (.bvar + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + rs.length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map + fun e => + (e.liftN 1 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length).liftN + rs.length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (rs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + 1) + source.nparams ++ + VExpr.bvarRevRange rs.length + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)]))).liftN + gen.block.ctorPairs.length + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) + (Δ := []) + (Γ := gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse)) + (f := .bvar + (gen.block.ctorPairs.length - 1 - i + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (by + have hb := VEnv.HasType.bvar + (env := env) (U := gen.recUvars) hlu + rw [hminorEq] at hb + simpa [VExpr.liftTelN_length] using hb) + simp only [List.length_nil, + VExpr.liftTelN_length, + VExpr.liftN_zero] at hfields + rw [ihsFromRecArgs_liftN' + (ctor.fieldsR source.uvars source.nparams gen.elimination).length + gen.block.ctorPairs.length rs hrsLt 0 + (VExpr.appN + (.bvar + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + rs.length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN 1 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length).liftN + rs.length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (rs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + 1) + source.nparams ++ + VExpr.bvarRevRange rs.length + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)])) + (cut := + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) + rfl] at hfields + have hD : + (VExpr.appN + (.bvar + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + rs.length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + (e.liftN 1 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length).liftN + rs.length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + (rs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + 1) + source.nparams ++ + VExpr.bvarRevRange rs.length + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)])).liftN + gen.block.ctorPairs.length + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + 0 + rs.length) = + (VExpr.appN + (.bvar + (gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)])).liftN + rs.length := by + rw [VExpr.liftN_appN, VExpr.liftN_appN, + List.map_append, List.map_append, + List.map_map, List.map_map] + show VExpr.appN _ (_ ++ [_]) = + VExpr.appN _ (_ ++ [_]) + congr 1 + · show + VExpr.bvar + (liftVar gen.block.ctorPairs.length + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + rs.length) + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + 0 + rs.length)) = + VExpr.bvar + (liftVar rs.length + (gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) + 0) + rw [liftVar_le (by omega), + liftVar_le (Nat.zero_le _)] + congr 1 + omega + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + rw [show + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + 0 + rs.length = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + rs.length by omega, + VExpr.liftN_liftN_mid e + gen.block.ctorPairs.length rs.length + (Nat.zero_le _)] + · congr 1 + simp only [] + rw [show + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + 0 + rs.length = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + rs.length by omega] + rw [VExpr.liftN_appN, + VExpr.liftN_appN, + List.map_append, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ + (by omega), + bvarRevRange_liftN_ge _ _ _ _ + (Nat.zero_le _), + bvarRevRange_liftN_ge _ _ _ _ + (Nat.zero_le _), + VExpr.bvarRevRange_congr source.nparams + (show + gen.block.ctorPairs.length + + (rs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + 1) = + rs.length + + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) by + omega), + VExpr.bvarRevRange_congr _ + (show rs.length = rs.length + 0 by omega)] + rfl + rw [hD] at hfields + have hres := hasType_appN_ruleIHs + (env := env) (U := gen.recUvars) + (m := + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) + (k := gen.block.ctorPairs.length) + (rs := rs) + (argOf := fun r => + r.ruleCall + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + gen.block.ctorPairs.length + (VExpr.appN + (.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + (source.nparams + + gen.block.ctorPairs.length + 1)))) + (fun r hr => + S.ruleCall_hasType hctor hrec (hrs ▸ hr)) + hfields + simpa only [hrs] using hres + +/-- The constructor-headed left side of a mixed iota rule. -/ +theorem recRuleApp_hasType {ctor : NormalizedCtor} + (hctor : ctor ∈ gen.block.ctorPairs) + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) : + env.HasType (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (VExpr.appN + (.const + (.str gen.block.sourceType.name "rec") + (gen.recLevels)) + (VExpr.bvarRevRange + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + (source.nparams + + gen.block.ctorPairs.length + 1))) + (((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)])) + (VExpr.appN + (.bvar + (gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) ++ + [VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)])) := by + have hSp₀ := S.result_transport hctor + (gen.minorTypes.reverse ++ [gen.motiveType]) + (g := gen.block.ctorPairs.length + 1) + (by simp [gen.minorTypes_length]) + [] (d := 0) rfl + have hSp : env.SpineWF (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.forallN + (VExpr.liftTelN + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0).reverse.length + + gen.block.ctorPairs.length + 1) + gen.idxTel 0) + (.sort + (gen.block.checked.resultLevel.inst + (gen.sourceLevels)))) + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length) + (.sort + (gen.block.checked.resultLevel.inst + (gen.sourceLevels))) := by + simpa [List.append_assoc, Nat.add_assoc, + List.length_reverse, VExpr.liftTelN_length] + using hSp₀ + have hidxLen : + ((ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length).length = + gen.idxTel.length := by + simp only [List.length_map, + NormalizedCtor.resultIndicesR, + GenerationChecked.idxTel] + exact (S.viewResultIndices_length hctor).trans + gen.shape.2.2.1.symm + have ha₀ := S.ctorAppRule_hasType hctor + have ha : env.HasType (gen.recUvars) + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse ++ + (gen.minorTypes.reverse ++ + (gen.motiveType :: gen.paramsTel.reverse))) + (VExpr.appN + (.const ctor.raw.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + VExpr.bvarRevRange 0 + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) + (VExpr.appN + (.const gen.block.sourceType.name + (gen.sourceLevels)) + (VExpr.bvarRevRange + ((VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0).reverse.length + + gen.block.ctorPairs.length + 1) + source.nparams ++ + (ctor.resultIndicesR source.uvars gen.elimination).map fun e => + e.liftN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length)) := by + simpa only [List.length_reverse, + VExpr.liftTelN_length] using ha₀ + have hr := S.recApp_hasType hrec + (VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR source.uvars source.nparams gen.elimination) + 0).reverse + hSp hidxLen ha + rw [List.length_reverse, VExpr.liftTelN_length, + show + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length = + gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length by + omega, + show + gen.block.ctorPairs.length + + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + 1 = + (ctor.fieldsR + source.uvars source.nparams gen.elimination).length + + gen.block.ctorPairs.length + 1 by + omega] at hr + exact hr + +/-- Every per-constructor mixed iota rule is well formed in an environment +containing the generated recursor constant. -/ +theorem rule_WF {i : Nat} {ctor : NormalizedCtor} + (hci : gen.block.ctorPairs[i]? = some ctor) + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) : + (gen.rule i ctor).WF env := by + have hctor := List.mem_of_getElem? hci + refine ⟨?_, ?_⟩ + · show env.HasType (gen.recUvars) [] + (VExpr.lamN + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes ++ + VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0) + _) + (VExpr.forallN _ _) + refine HasType.lamN + (S.ruleBinders_onTel hctor) ?_ + simp only [List.reverse_append, + List.reverse_cons, List.append_nil, + List.append_assoc, List.singleton_append] + exact S.recRuleApp_hasType hctor hrec + · show env.HasType (gen.recUvars) [] + (VExpr.lamN + (gen.paramsTel ++ + gen.motiveType :: gen.minorTypes ++ + VExpr.liftTelN + (gen.block.ctorPairs.length + 1) + (ctor.fieldsR + source.uvars source.nparams gen.elimination) + 0) + _) + (VExpr.forallN _ _) + refine HasType.lamN + (S.ruleBinders_onTel hctor) ?_ + simp only [List.reverse_append, + List.reverse_cons, List.append_nil, + List.append_assoc, List.singleton_append] + exact S.minorApp_hasType hci hrec + +end GenerationEnv + +theorem ctorFieldsR_length {U np : Nat} {c : VConstVal} : + (ctorFieldsR U np c).length = (ctorFields (VExpr.dropN np c.type)).length := + List.length_map .. + +theorem ctorFieldsR_getElem? {U np : Nat} {c : VConstVal} {q : Nat} : + (ctorFieldsR U np c)[q]? = + (ctorFields (VExpr.dropN np c.type))[q]?.map (VExpr.instL (VLevel.params' U 1)) := + List.getElem?_map .. + +/-! ## The post-family environment invariant -/ + +/-- The facts available immediately after inserting a checked family, +before any constructor has been installed. Constructor types may refer to the +family, so this is the precise staging invariant needed to validate them. -/ +structure DirectFamilyEnv (env : VEnv) (U : Nat) (T : Name) + (np : Nat) (l : VLevel) (ty : VInductiveType) : Prop where + ord : env.Ordered + hl : l.WF U + hsort : VExpr.resultOf (VExpr.dropN np ty.type) = .sort l + hlen : (VExpr.telN np ty.type).length = np + hT : env.constants T = some ⟨U, ty.type⟩ + hparams : + OnTel env U [] + (VExpr.telN np ty.type ++ + ctorFields (VExpr.dropN np ty.type)) + +section DirectFamily + +variable {env : VEnv} {U : Nat} {T : Name} {np : Nat} + {l : VLevel} {ty : VInductiveType} + (S : DirectFamilyEnv env U T np l ty) +include S + +theorem DirectFamilyEnv.tyType_eq : + ty.type = + VExpr.forallN (VExpr.telN np ty.type) + (VExpr.forallN + (ctorFields (VExpr.dropN np ty.type)) (.sort l)) := by + conv => lhs + rw [← VExpr.forallN_telN_dropN np ty.type, + ← forallN_ctorFields_resultOf + (VExpr.dropN np ty.type), S.hsort] + +theorem DirectFamilyEnv.tyType_isType : + env.IsType U [] ty.type := by + rw [S.tyType_eq, ← VExpr.forallN_append] + exact IsType.forallN S.hparams ⟨_, HasType.sort S.hl⟩ + +theorem DirectFamilyEnv.tconst_decl {Γ} : + env.HasType U Γ (.const T (VLevel.params U)) ty.type := + (HasType.const0 S.hT S.tyType_isType).weak0 S.ord + +/-- Applying the newly inserted family to its parameter self-spine exposes +the index telescope in any constructor-field context. -/ +theorem DirectFamilyEnv.recAppPi_hasType_decl (Δ : List VExpr) : + env.HasType U (Δ ++ (VExpr.telN np ty.type).reverse) + (recApp U T np Δ.length) + ((VExpr.forallN + (ctorFields (VExpr.dropN np ty.type)) (.sort l)).liftN + Δ.length) := by + have hcl : ty.type.ClosedN 0 := + Ordered.closedC (ci := ⟨U, ty.type⟩) S.ord S.hT + have hf : env.HasType U + (Δ ++ (VExpr.telN np ty.type).reverse ++ []) + (.const T (VLevel.params U)) + ((VExpr.forallN (VExpr.telN np ty.type) + (VExpr.forallN + (ctorFields (VExpr.dropN np ty.type)) (.sort l))).liftN + (Δ.length + (VExpr.telN np ty.type).length)) := by + rw [← S.tyType_eq, hcl.liftN_eq (Nat.zero_le _)] + exact S.tconst_decl + have hout := HasType.appN_selfSpine (env := env) (U := U) hf + rw [S.hlen] at hout + simpa [recApp, List.append_nil] using hout + +/-- Checked constructor fields form a telescope as soon as the family is +available; no constructor lookup is needed for recursive occurrences. -/ +theorem DirectFamilyEnv.fieldsWF_onTel_decl : + ∀ (Bs : List VExpr) (Δd : List VExpr) (j : Nat), + Δd.length = j → + fieldsWF U T np env l + (ctorFields (VExpr.dropN np ty.type)) + (Δd ++ (VExpr.telN np ty.type).reverse) j Bs → + OnTel env U + (Δd ++ (VExpr.telN np ty.type).reverse) Bs + | [], _, _, _, _ => trivial + | B :: Bs, Δd, j, hΔ, ⟨hB, hSp, hrest⟩ => by + refine ⟨?_, DirectFamilyEnv.fieldsWF_onTel_decl + Bs (B :: Δd) (j+1) (by simp [hΔ]) hrest⟩ + rcases hB with hrec | hfun | ⟨-, u, h, -⟩ + · obtain ⟨hBeq, -, -⟩ := isRecField_eq hrec + have hTapp := S.recAppPi_hasType_decl Δd + rw [hΔ, VExpr.liftN_forallN] at hTapp + have hgoal : env.HasType U + (Δd ++ (VExpr.telN np ty.type).reverse) + B (.sort l) := by + rw [hBeq, VExpr.appN_append] + exact (hSp hrec).hasType_appN hTapp + exact ⟨_, hgoal⟩ + · obtain ⟨r, hr, -, hrtel, hrsp⟩ := hfun + obtain ⟨hrj, -, hBeq, -, -, -⟩ := recArg?_eq hr + rw [hBeq] + refine IsType.forallN hrtel ⟨l, ?_⟩ + have hTapp := + S.recAppPi_hasType_decl (r.binders.reverse ++ Δd) + rw [VExpr.liftN_forallN] at hTapp + have hbase : env.HasType U + (r.binders.reverse ++ + (Δd ++ (VExpr.telN np ty.type).reverse)) + (recApp U T np (j + r.binders.length)) + (VExpr.forallN + (VExpr.liftTelN (j + r.binders.length) + (ctorFields (VExpr.dropN np ty.type)) 0) + (.sort l)) := by + simpa [List.append_assoc, hΔ, Nat.add_comm] using hTapp + rw [hrj] at hrsp + simpa [recApp, VExpr.appN_append] using + hrsp.hasType_appN hbase + · exact ⟨u, h⟩ + +/-- The analyzed result spine types the exact family application at the end +of a constructor declaration. -/ +theorem DirectFamilyEnv.ctorResult_hasType_decl + {c : VConstVal} + (hresult : env.SpineWF U + ((ctorFields (VExpr.dropN np c.type)).reverse ++ + (VExpr.telN np ty.type).reverse) + (VExpr.forallN + (VExpr.liftTelN + (ctorFields (VExpr.dropN np c.type)).length + (ctorFields (VExpr.dropN np ty.type)) 0) + (.sort l)) + (recFieldIdxs np + (VExpr.resultOf (VExpr.dropN np c.type))) + (.sort l)) : + env.HasType U + ((ctorFields (VExpr.dropN np c.type)).reverse ++ + (VExpr.telN np ty.type).reverse) + (VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange + (ctorFields (VExpr.dropN np c.type)).length np ++ + recFieldIdxs np + (VExpr.resultOf (VExpr.dropN np c.type)))) + (.sort l) := by + have hTapp := S.recAppPi_hasType_decl + ((ctorFields (VExpr.dropN np c.type)).reverse) + rw [List.length_reverse, VExpr.liftN_forallN] at hTapp + rw [VExpr.appN_append] + exact hresult.hasType_appN hTapp + +end DirectFamily + +/-- A checked family insertion constructs the post-family invariant directly +from the checker contract. -/ +theorem Checked.WF.toDirectFamilyEnv + {source : VInductDecl} {checked : source.Checked} + {pre envT : VEnv} (hpre : pre.Ordered) + (h : checked.WF pre) + (hadd : pre.addConst checked.type.name + checked.type.toVConstant = some envT) : + DirectFamilyEnv envT source.uvars checked.type.name + source.nparams checked.resultLevel checked.type where + ord := by + have hfamily : checked.type.toVConstant.WF pre := by + show pre.IsType checked.type.uvars [] checked.type.type + rw [checked.direct_anatomy.1] + exact h.family_isType + exact .const hpre hfamily hadd + hl := checked.direct_anatomy.2.2.1 + hsort := checked.result_eq + hlen := by simpa [checked.params_eq] using + checked.direct_anatomy.2.1 + hT := by + have hout := addConst_self hadd + change envT.constants checked.type.name = + some ⟨checked.type.uvars, checked.type.type⟩ at hout + rw [checked.direct_anatomy.1] at hout + exact hout + hparams := by + simpa [checked.params_eq, checked.indices_eq] using + h.1.mono (addConst_le hadd) + +/-! ## The stage-3 environment invariant -/ + +/-- Everything the piece-typing lemmas need about an environment that +already contains the block's type constant and constructors. -/ +structure Stage3Env (env : VEnv) (U : Nat) (T : Name) (np : Nat) (l : VLevel) + (ty : VInductiveType) : Prop where + ord : env.Ordered + hl : l.WF U + hsort : VExpr.resultOf (VExpr.dropN np ty.type) = .sort l + hlen : (VExpr.telN np ty.type).length = np + hT : env.constants T = some ⟨U, ty.type⟩ + hcs : ∀ c ∈ ty.ctors, env.constants c.name = some ⟨U, c.type⟩ + htel : ∀ c ∈ ty.ctors, VExpr.telN np c.type = VExpr.telN np ty.type + hs3 : ∀ c ∈ ty.ctors, stage3Ctor U T np (ctorFields (VExpr.dropN np ty.type)).length 0 + (VExpr.dropN np c.type) = true + hparams : OnTel env U [] (VExpr.telN np ty.type ++ ctorFields (VExpr.dropN np ty.type)) + hfields : ∀ c ∈ ty.ctors, fieldsWF U T np env l (ctorFields (VExpr.dropN np ty.type)) + (VExpr.telN np ty.type).reverse 0 (ctorFields (VExpr.dropN np c.type)) + hresult : ∀ c ∈ ty.ctors, env.SpineWF U + ((ctorFields (VExpr.dropN np c.type)).reverse ++ (VExpr.telN np ty.type).reverse) + (VExpr.forallN (VExpr.liftTelN (ctorFields (VExpr.dropN np c.type)).length + (ctorFields (VExpr.dropN np ty.type)) 0) (.sort l)) + (recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type))) (.sort l) + +variable {env : VEnv} {U : Nat} {T : Name} {np : Nat} {l : VLevel} {ty : VInductiveType} + (S : Stage3Env env U T np l ty) +include S +-- `S` is included throughout so every lemma below is reachable as `S.lemma`, +-- including those whose statement and proof never mention it. +set_option linter.unusedSectionVars false + +theorem Stage3Env.mono {env' : VEnv} (henv : env ≤ env') (ord' : env'.Ordered) : + Stage3Env env' U T np l ty where + ord := ord' + hl := S.hl + hsort := S.hsort + hlen := S.hlen + hT := henv.constants S.hT + hcs := fun c hc => henv.constants (S.hcs c hc) + htel := S.htel + hs3 := S.hs3 + hparams := S.hparams.mono henv + hfields := fun c hc => fieldsWF_mono henv (S.hfields c hc) + hresult := fun c hc => (S.hresult c hc).mono henv + +/-- The block's type split at the parameters and indices. -/ +theorem Stage3Env.tyType_eq : ty.type = + VExpr.forallN (VExpr.telN np ty.type) + (VExpr.forallN (ctorFields (VExpr.dropN np ty.type)) (.sort l)) := by + conv => lhs; rw [← VExpr.forallN_telN_dropN np ty.type, + ← forallN_ctorFields_resultOf (VExpr.dropN np ty.type), S.hsort] + +/-- The type of the block constant is a type. -/ +theorem Stage3Env.tyType_isType : env.IsType U [] ty.type := by + rw [S.tyType_eq, ← VExpr.forallN_append] + exact IsType.forallN S.hparams ⟨_, HasType.sort S.hl⟩ + +/-- The block constant at the declaration universes, in any context. -/ +theorem Stage3Env.tconst_decl {Γ} : + env.HasType U Γ (.const T (VLevel.params U)) ty.type := + (HasType.const0 S.hT S.tyType_isType).weak0 S.ord + +/-- The type of the block constant, instantiated to the recursor universes. -/ +theorem Stage3Env.tyType_instL : + ty.type.instL (VLevel.params' U 1) = + VExpr.forallN (paramsTel U np ty) + (VExpr.forallN (idxTel U np ty) (.sort (l.inst (VLevel.params' U 1)))) := by + conv => lhs; rw [S.tyType_eq] + rw [VExpr.instL_forallN, VExpr.instL_forallN] + rfl + +/-- The block constant at the recursor universes, in any context. -/ +theorem Stage3Env.tconst {Γ} : + env.HasType (U+1) Γ (.const T (VLevel.params' U 1)) (ty.type.instL (VLevel.params' U 1)) := by + have := (S.tconst_decl (Γ := [])).instL (U' := U+1) VLevel.params'_one_wf + rw [show (VExpr.const T (VLevel.params U)).instL (VLevel.params' U 1) = + .const T (VLevel.params' U 1) from by + simp [VExpr.instL, VLevel.params_map_inst_params']] at this + exact this.weak0 S.ord + +/-- The parameter spine applied to the block constant, `Δ` binders past +the parameter telescope (declaration universes): the index pi. -/ +theorem Stage3Env.recAppPi_hasType_decl (Δ : List VExpr) : + env.HasType U (Δ ++ (VExpr.telN np ty.type).reverse) (recApp U T np Δ.length) + ((VExpr.forallN (ctorFields (VExpr.dropN np ty.type)) (.sort l)).liftN Δ.length) := by + have hcl : ty.type.ClosedN 0 := Ordered.closedC (ci := ⟨U, ty.type⟩) S.ord S.hT + have hf : env.HasType U (Δ ++ (VExpr.telN np ty.type).reverse ++ []) + (.const T (VLevel.params U)) + ((VExpr.forallN (VExpr.telN np ty.type) + (VExpr.forallN (ctorFields (VExpr.dropN np ty.type)) (.sort l))).liftN + (Δ.length + (VExpr.telN np ty.type).length)) := by + rw [← S.tyType_eq, hcl.liftN_eq (Nat.zero_le _)] + exact S.tconst_decl + have := HasType.appN_selfSpine (env := env) (U := U) hf + rw [S.hlen] at this + simpa [recApp, List.append_nil] using this + +/-- The parameter spine at the recursor universes: the index pi. -/ +theorem Stage3Env.recAppPi_hasType (Δ : List VExpr) : + env.HasType (U+1) (Δ ++ (paramsTel U np ty).reverse) (recApp' U T np Δ.length) + ((VExpr.forallN (idxTel U np ty) + (.sort (l.inst (VLevel.params' U 1)))).liftN Δ.length) := by + have hcl : (ty.type.instL (VLevel.params' U 1)).ClosedN 0 := + (Ordered.closedC (ci := ⟨U, ty.type⟩) S.ord S.hT).instL + have hf : env.HasType (U+1) (Δ ++ (paramsTel U np ty).reverse ++ []) + (.const T (VLevel.params' U 1)) + ((VExpr.forallN (paramsTel U np ty) + (VExpr.forallN (idxTel U np ty) (.sort (l.inst (VLevel.params' U 1))))).liftN + (Δ.length + (paramsTel U np ty).length)) := by + rw [← S.tyType_instL, hcl.liftN_eq (Nat.zero_le _)] + exact S.tconst + have := HasType.appN_selfSpine (env := env) (U := U+1) hf + rw [show (paramsTel U np ty).length = np from by + simp [paramsTel, List.length_map, S.hlen]] at this + simpa [recApp', List.append_nil] using this + +/-- The block applied to the full parameter-and-index self-spine is a +sort, in the context of the indices over the parameters. -/ +theorem Stage3Env.motiveTApp_hasType : + env.HasType (U+1) ((idxTel U np ty).reverse ++ (paramsTel U np ty).reverse) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (idxTel U np ty).length np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (l.inst (VLevel.params' U 1))) := by + have hcl : (ty.type.instL (VLevel.params' U 1)).ClosedN 0 := + (Ordered.closedC (ci := ⟨U, ty.type⟩) S.ord S.hT).instL + have hf : env.HasType (U+1) + ([] ++ (paramsTel U np ty ++ idxTel U np ty).reverse ++ []) + (.const T (VLevel.params' U 1)) + ((VExpr.forallN (paramsTel U np ty ++ idxTel U np ty) + (.sort (l.inst (VLevel.params' U 1)))).liftN + (List.length ([] : List VExpr) + + (paramsTel U np ty ++ idxTel U np ty).length)) := by + rw [VExpr.forallN_append, ← S.tyType_instL, hcl.liftN_eq (Nat.zero_le _)] + exact S.tconst + have h2 := HasType.appN_selfSpine (env := env) (U := U+1) hf + rw [show List.length ([] : List VExpr) = 0 from rfl, + VExpr.bvarRevRange_congr' 0 (show (paramsTel U np ty ++ idxTel U np ty).length = + (idxTel U np ty).length + np from by + simp [paramsTel, List.length_map, S.hlen]; omega), + ← VExpr.bvarRevRange_append] at h2 + simpa [List.append_nil, List.reverse_append] using h2 + +/-- Field telescopes are well-formed in context, at the declaration +universes: recursive fields by the partial parameter application of the +block followed by the carried index-spine typing. -/ +theorem Stage3Env.fieldsWF_onTel_decl : + ∀ (Bs : List VExpr) (Δd : List VExpr) (j : Nat), Δd.length = j → + fieldsWF U T np env l (ctorFields (VExpr.dropN np ty.type)) + (Δd ++ (VExpr.telN np ty.type).reverse) j Bs → + OnTel env U (Δd ++ (VExpr.telN np ty.type).reverse) Bs + | [], _, _, _, _ => trivial + | B :: Bs, Δd, j, hΔ, ⟨hB, hSp, hT⟩ => by + refine ⟨?_, Stage3Env.fieldsWF_onTel_decl Bs (B :: Δd) (j+1) (by simp [hΔ]) hT⟩ + rcases hB with hrec | hfun | ⟨-, u, h, -⟩ + · obtain ⟨hBeq, -, -⟩ := isRecField_eq hrec + have hTapp := S.recAppPi_hasType_decl Δd + rw [hΔ, VExpr.liftN_forallN] at hTapp + have hgoal : env.HasType U (Δd ++ (VExpr.telN np ty.type).reverse) B (.sort l) := by + rw [hBeq, VExpr.appN_append] + exact (hSp hrec).hasType_appN hTapp + exact ⟨_, hgoal⟩ + · obtain ⟨r, hr, -, hrtel, hrsp⟩ := hfun + obtain ⟨hrj, -, hBeq, -, -, -⟩ := recArg?_eq hr + rw [hBeq] + refine IsType.forallN hrtel ⟨l, ?_⟩ + have hTapp := S.recAppPi_hasType_decl (r.binders.reverse ++ Δd) + rw [VExpr.liftN_forallN] at hTapp + have hbase : env.HasType U + (r.binders.reverse ++ (Δd ++ (VExpr.telN np ty.type).reverse)) + (recApp U T np (j + r.binders.length)) + (VExpr.forallN + (VExpr.liftTelN (j + r.binders.length) + (ctorFields (VExpr.dropN np ty.type)) 0) (.sort l)) := by + simpa [List.append_assoc, hΔ, Nat.add_comm] using hTapp + rw [hrj] at hrsp + simpa [recApp, VExpr.appN_append] using hrsp.hasType_appN hbase + · exact ⟨u, h⟩ + +/-- Field telescopes are well-formed in context, at the recursor +universes. -/ +theorem Stage3Env.fieldsWF_onTel : + ∀ (Bs : List VExpr) (Δd : List VExpr) (j : Nat), Δd.length = j → + fieldsWF U T np env l (ctorFields (VExpr.dropN np ty.type)) + (Δd ++ (VExpr.telN np ty.type).reverse) j Bs → + OnTel env (U+1) + ((Δd ++ (VExpr.telN np ty.type).reverse).map (VExpr.instL (VLevel.params' U 1))) + (Bs.map (VExpr.instL (VLevel.params' U 1))) + | Bs, Δd, j, hΔ, hfields => by + exact (S.fieldsWF_onTel_decl Bs Δd j hΔ hfields).instL VLevel.params'_one_wf + +/-- The constructor's type, split at the parameters. -/ +theorem Stage3Env.ctorType_eq {c : VConstVal} (hc : c ∈ ty.ctors) : + c.type = VExpr.forallN (VExpr.telN np ty.type) + (VExpr.forallN (ctorFields (VExpr.dropN np c.type)) + (VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type))))) := by + conv => lhs; rw [← VExpr.forallN_telN_dropN np c.type, S.htel c hc, + (stage3Ctor_eq (S.hs3 c hc)).1] + +theorem Stage3Env.ctorType_instL {c : VConstVal} (hc : c ∈ ty.ctors) : + c.type.instL (VLevel.params' U 1) = + VExpr.forallN (paramsTel U np ty) + (VExpr.forallN (ctorFieldsR U np c) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + ctorIdxs U np c))) := by + conv => lhs; rw [S.ctorType_eq hc, VExpr.instL_forallN, VExpr.instL_forallN, + VExpr.instL_appN, List.map_append, bvarRevRange_instL, + show (VExpr.const T (VLevel.params U)).instL (VLevel.params' U 1) = + .const T (VLevel.params' U 1) from by + simp [VExpr.instL, VLevel.params_map_inst_params']] + rfl + +/-- The constructor's result, typed by the partial parameter application +and the carried result-spine typing (declaration universes). -/ +theorem Stage3Env.ctorResult_hasType_decl {c : VConstVal} (hc : c ∈ ty.ctors) : + env.HasType U + ((ctorFields (VExpr.dropN np c.type)).reverse ++ (VExpr.telN np ty.type).reverse) + (VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type)))) + (.sort l) := by + have hTapp := S.recAppPi_hasType_decl ((ctorFields (VExpr.dropN np c.type)).reverse) + rw [List.length_reverse, VExpr.liftN_forallN] at hTapp + rw [VExpr.appN_append, + VExpr.bvarRevRange_congr np (show 0 + (ctorFields (VExpr.dropN np c.type)).length = + (ctorFields (VExpr.dropN np c.type)).length from by omega)] + exact (S.hresult c hc).hasType_appN hTapp + +/-- A constructor's declared type is well-formed (declaration universes). -/ +theorem Stage3Env.ctorType_isType {c : VConstVal} (hc : c ∈ ty.ctors) : + env.IsType U [] c.type := by + rw [S.ctorType_eq hc] + refine IsType.forallN (S.hparams.of_append.1) ?_ + simp only [List.append_nil] + refine IsType.forallN + (S.fieldsWF_onTel_decl _ [] 0 rfl (by simpa using S.hfields c hc)) ?_ + exact ⟨_, by simpa using S.ctorResult_hasType_decl hc⟩ + +/-- The constructor constant at the recursor universes, any context. -/ +theorem Stage3Env.cConst {c : VConstVal} (hc : c ∈ ty.ctors) {Γ} : + env.HasType (U+1) Γ (.const c.name (VLevel.params' U 1)) + (c.type.instL (VLevel.params' U 1)) := by + have h0 := HasType.const0 (S.hcs c hc) (S.ctorType_isType hc) + have := h0.instL (U' := U+1) VLevel.params'_one_wf + rw [show (VExpr.const c.name (VLevel.params U)).instL (VLevel.params' U 1) = + .const c.name (VLevel.params' U 1) from by + simp [VExpr.instL, VLevel.params_map_inst_params']] at this + exact this.weak0 S.ord + +/-- The index telescope is well-formed over the parameters, at the +recursor universes. -/ +theorem Stage3Env.idxTel_onTel : + OnTel env (U+1) (paramsTel U np ty).reverse (idxTel U np ty) := by + have h0 := (S.hparams.of_append.2).instL (U' := U+1) VLevel.params'_one_wf + simpa [paramsTel, idxTel, List.map_reverse] using h0 + +theorem Stage3Env.motive_isType : + env.IsType (U+1) (paramsTel U np ty).reverse (motiveType U T np ty) := by + refine IsType.forallN S.idxTel_onTel ?_ + exact ⟨_, HasType.forallE S.motiveTApp_hasType (HasType.sort (Nat.succ_pos U))⟩ + +/-- Transport a recursive field's index-spine typing into a rule or minor +context: instantiate the universes, insert `mid` (motive, or motive and +minors) at the field's depth `j`, and push a `d`-entry stack underneath. -/ +theorem Stage3Env.spine_transport {c : VConstVal} (hc : c ∈ ty.ctors) + {j : Nat} {B : VExpr} + (hBj : (ctorFields (VExpr.dropN np c.type))[j]? = some B) + (hrec : isRecField U T np (ctorFields (VExpr.dropN np ty.type)).length j B = true) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.SpineWF (U+1) + (As₂ ++ ((VExpr.liftTelN g ((ctorFieldsR U np c).take j) 0).reverse ++ + (mid ++ (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN (j + g + d) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + (((recFieldIdxs np B).map (VExpr.instL (VLevel.params' U 1))).map + fun e => (e.liftN g j).liftN d) + (.sort (l.inst (VLevel.params' U 1))) := by + have hjlen : ((ctorFieldsR U np c).take j).length = j := by + have h1 := (List.getElem?_eq_some_iff.1 hBj).1 + simp only [ctorFieldsR, List.length_take, List.length_map] + omega + -- (1) declaration-universe spine from the fieldsWF chain + have h0 := fieldsWF_spine (S.hfields c hc) j B (by simpa using hBj) + (by simpa using hrec) + rw [Nat.zero_add] at h0 + -- (2) universe instantiation + have h1 := h0.instL (U' := U+1) VLevel.params'_one_wf + rw [VExpr.instL_forallN, VExpr.liftTelN_instL, + show (((ctorFields (VExpr.dropN np c.type)).take j).reverse ++ + (VExpr.telN np ty.type).reverse).map (VExpr.instL (VLevel.params' U 1)) = + ((ctorFieldsR U np c).take j).reverse ++ (paramsTel U np ty).reverse from by + simp [ctorFieldsR, paramsTel, List.map_reverse, List.map_take]] at h1 + -- (3) insert `mid` at depth `j` + have W₁ := Ctx.LiftN.consTel (n := mid.length) ((ctorFieldsR U np c).take j) + (Ctx.LiftN.zero (Γ := (paramsTel U np ty).reverse) mid) + rw [hjlen, Nat.add_zero] at W₁ + have h2 := h1.weakN S.ord W₁ + rw [VExpr.liftN_forallN, hg] at h2 + -- (4) push the stack underneath + have h3 := h2.weakN S.ord (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + rw [VExpr.liftN_forallN] at h3 + rw [VExpr.liftTelN_liftTelN_hi' j g _ 0 (by omega), VExpr.liftTelN_liftTelN, + show (ctorFields (VExpr.dropN np ty.type)).map (VExpr.instL (VLevel.params' U 1)) = + idxTel U np ty from rfl] at h3 + simpa [VExpr.instL, VExpr.liftN, List.map_map, Function.comp_def, + List.append_assoc] using h3 + +/-- Transport all semantic evidence for a recursive argument beneath a Pi +telescope. This is the functional counterpart of `spine_transport`: it +transports both the argument telescope and the terminal family-index spine. +-/ +theorem Stage3Env.recArg_transport {c : VConstVal} (hc : c ∈ ty.ctors) + {r₀ : RecArg} {B : VExpr} + (hB : (ctorFields (VExpr.dropN np c.type))[r₀.fieldIndex]? = some B) + (hr : recArg? U T np (idxTel U np ty).length r₀.fieldIndex B = some r₀) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + let r := r₀.instL (VLevel.params' U 1) + let As := VExpr.liftTelN d (VExpr.liftTelN g r.binders r.fieldIndex) 0 + OnTel env (U+1) + (As₂ ++ ((VExpr.liftTelN g + ((ctorFieldsR U np c).take r.fieldIndex) 0).reverse ++ + (mid ++ (paramsTel U np ty).reverse))) As ∧ + env.SpineWF (U+1) + (As.reverse ++ + (As₂ ++ ((VExpr.liftTelN g + ((ctorFieldsR U np c).take r.fieldIndex) 0).reverse ++ + (mid ++ (paramsTel U np ty).reverse)))) + (VExpr.forallN + (VExpr.liftTelN + (r.fieldIndex + r.binders.length + g + d) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + (r.indices.map fun e => + (e.liftN g (r.fieldIndex + r.binders.length)).liftN d r.binders.length) + (.sort (l.inst (VLevel.params' U 1))) := by + dsimp only + have hjlt : r₀.fieldIndex < (ctorFields (VExpr.dropN np c.type)).length := + (List.getElem?_eq_some_iff.1 hB).1 + have hsem := fieldsWF_recArg (S.hfields c hc) r₀.fieldIndex B r₀ hB (by + simpa [idxTel_length] using hr) + have htel₁ := hsem.1.instL (U' := U+1) VLevel.params'_one_wf + have hsp₁ := hsem.2.instL (U' := U+1) VLevel.params'_one_wf + have hctx : + (((ctorFields (VExpr.dropN np c.type)).take r₀.fieldIndex).reverse ++ + (VExpr.telN np ty.type).reverse).map (VExpr.instL (VLevel.params' U 1)) = + ((ctorFieldsR U np c).take r₀.fieldIndex).reverse ++ + (paramsTel U np ty).reverse := by + simp [ctorFieldsR, paramsTel, List.map_reverse, List.map_take] + rw [hctx] at htel₁ + rw [List.map_append, List.map_reverse, hctx] at hsp₁ + simp only [VExpr.instL_forallN, VExpr.liftTelN_instL] at htel₁ hsp₁ + have hjlen : ((ctorFieldsR U np c).take r₀.fieldIndex).length = + r₀.fieldIndex := by + simp only [ctorFieldsR, List.length_take, List.length_map] + omega + have W₁ := Ctx.LiftN.consTel (n := mid.length) + ((ctorFieldsR U np c).take r₀.fieldIndex) + (Ctx.LiftN.zero (Γ := (paramsTel U np ty).reverse) mid) + rw [hjlen, Nat.add_zero] at W₁ + have htel₂ := htel₁.weakN S.ord W₁ + have hsp₂ := hsp₁.weakN S.ord + (Ctx.LiftN.consTel + (r₀.binders.map (VExpr.instL (VLevel.params' U 1))) W₁) + rw [hg] at htel₂ hsp₂ + have W₂ := Ctx.LiftN.zero + (Γ := (VExpr.liftTelN g + ((ctorFieldsR U np c).take r₀.fieldIndex) 0).reverse ++ + (mid ++ (paramsTel U np ty).reverse)) As₂ (h := hd) + have htel₃ := htel₂.weakN S.ord W₂ + have hsp₃ := hsp₂.weakN S.ord + (Ctx.LiftN.consTel + (VExpr.liftTelN g + (r₀.binders.map (VExpr.instL (VLevel.params' U 1))) r₀.fieldIndex) W₂) + refine ⟨?_, ?_⟩ + · simpa [RecArg.instL, List.append_assoc] using htel₃ + · simp only [List.length_map, VExpr.liftTelN_length, Nat.add_zero] at hsp₃ + rw [VExpr.liftN_forallN, VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN_hi' (r₀.fieldIndex + r₀.binders.length) g _ 0 + (by omega), + VExpr.liftTelN_liftTelN_mid + (r₀.fieldIndex + r₀.binders.length + g) d _ 0 r₀.binders.length + (Nat.zero_le _) (by omega), + show (ctorFields (VExpr.dropN np ty.type)).map + (VExpr.instL (VLevel.params' U 1)) = idxTel U np ty from rfl] at hsp₃ + rw [show r₀.binders.length + r₀.fieldIndex = + r₀.fieldIndex + r₀.binders.length from Nat.add_comm _ _] at hsp₃ + simpa [RecArg.instL, VExpr.instL, VExpr.liftN, List.map_map, + Function.comp_def, List.append_assoc] using hsp₃ + +omit S in +/-- Apply a motive variable to a typed family-index spine and major premise. +Unlike `Stage3Env.motiveApp_hasType`, this helper is independent of the +recursor's minor-premise stack, so it also applies under a recursive +argument's private Pi telescope. -/ +theorem motiveVarApp_hasType {Γ : List VExpr} {K : Nat} + {idxs : List VExpr} {a : VExpr} + (hM : env.HasType (U+1) Γ (.bvar K) + ((motiveType U T np ty).liftN (K+1))) + (hidx : env.SpineWF (U+1) Γ + (VExpr.forallN (VExpr.liftTelN (K+1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + idxs (.sort (l.inst (VLevel.params' U 1)))) + (hlen : idxs.length = (idxTel U np ty).length) + (ha : env.HasType (U+1) Γ a + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (K+1) np ++ idxs))) : + env.HasType (U+1) Γ + (VExpr.appN (.bvar K) (idxs ++ [a])) (.sort (.param 0)) := by + rw [motiveType_liftN] at hM + have hshape := hidx.retarget + (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (K+1 + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ (C := .const T (VLevel.params' U 1)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by rw [hlen]; omega), + show K+1+(idxTel U np ty).length-idxs.length = K+1 from by + rw [hlen, Nat.add_sub_cancel], + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hApp := hshape.hasType_appN hM + rw [VExpr.appN_append] + exact HasType.app hApp (by simpa using ha) + +/-- One generalized induction-hypothesis entry is a type in the minor +premise context. Recursive Pi arguments become Pi-valued hypotheses whose +body applies both the motive and the recursive field to the same private +self-spine. -/ +theorem Stage3Env.recArgMinor_isType {c : VConstVal} (hc : c ∈ ty.ctors) + {r : RecArg} + (hrmem : r ∈ recArgsR U T np (idxTel U np ty).length c) + (Δ : List VExpr) (p : Nat) (hΔ : Δ.length = p) : + env.IsType (U+1) + (Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (r.minorIH (ctorFieldsR U np c).length p) := by + obtain ⟨r₀, B, rfl, hB, hr₀⟩ := recArgsR_mem hrmem + let r := r₀.instL (VLevel.params' U 1) + let m := (ctorFieldsR U np c).length + let j := r₀.fieldIndex + let Fs := VExpr.liftTelN 1 (ctorFieldsR U np c) 0 + let As := r.minorBinders m p + let idxs := r.indices.map fun e => + (e.liftN 1 (r.fieldIndex+r.binders.length)).liftN (m-r.fieldIndex+p) r.binders.length + let Γ := Δ ++ Fs.reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse) + have hjm : j < m := by + simpa [j, m, RecArg.instL, ctorFieldsR_length] using recArgsR_lt _ hrmem + have hFsLen : Fs.length = m := by simp [Fs, m, VExpr.liftTelN_length] + have hstackLen : (Δ ++ (Fs.drop j).reverse).length = m-j+p := by + simp only [List.length_append, List.length_reverse, List.length_drop, hFsLen, hΔ] + omega + have ht := S.recArg_transport hc hB hr₀ [motiveType U T np ty] rfl + (Δ ++ (Fs.drop j).reverse) hstackLen + simp only [List.length_singleton, RecArg.instL] at ht + have hctx : + (Δ ++ (Fs.drop j).reverse) ++ + ((VExpr.liftTelN 1 ((ctorFieldsR U np c).take j) 0).reverse ++ + ([motiveType U T np ty] ++ (paramsTel U np ty).reverse)) = Γ := by + dsimp only [Γ, Fs] + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).drop j).reverse, + ← List.reverse_append, List.take_append_drop, List.singleton_append, + ← List.append_assoc] + dsimp only [j] at ht hctx + have htel : OnTel env (U+1) Γ As := by + rw [hctx] at ht + simpa [r, As, m, j, RecArg.instL, + RecArg.minorBinders] using ht.1 + have hsp : env.SpineWF (U+1) (As.reverse ++ Γ) + (VExpr.forallN + (VExpr.liftTelN (m+p+r.binders.length+1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + idxs (.sort (l.inst (VLevel.params' U 1))) := by + rw [hctx] at ht + simpa [r, As, idxs, m, j, RecArg.instL, + RecArg.minorBinders, List.append_assoc, + show j + r₀.binders.length + 1 + (m-j+p) = + m+p+r₀.binders.length+1 from by omega] using ht.2 + have hF : Γ[m-1-j+p]? = + some ((B.instL (VLevel.params' U 1)).liftN 1 j) := by + dsimp only [Γ, Fs] + rw [getElem?_stack_mid Δ + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse + (motiveType U T np ty :: (paramsTel U np ty).reverse) + (i := m-1-j+p) (by rw [hΔ]; omega) + (by simp only [hΔ, List.length_reverse, VExpr.liftTelN_length]; omega), + show m - 1 - j + p - Δ.length = m - 1 - j from by rw [hΔ]; omega, + List.getElem?_reverse (by rw [hFsLen]; omega), + VExpr.liftTelN_length, + show m - 1 - (m - 1 - j) = j from by omega, + VExpr.liftTelN_getElem?, ctorFieldsR_getElem?, hB] + simp + have hlu := Lookup.of_getElem? hF + rw [show m-1-j+p+1 = m-j+p from by omega] at hlu + dsimp only [j, r] at hlu + have hfield := recArg_minor_fieldType hr₀ m p (by simpa [j] using hjm) + simp only [RecArg.instL, ElimMode.large_sourceLevels] at hfield + rw [hfield] at hlu + have hf0 := VEnv.HasType.bvar (env := env) (U := U+1) hlu + have hf := hf0.weakN S.ord (Ctx.LiftN.zero (Γ := Γ) As.reverse) + have hmajor := VEnv.HasType.appN_selfSpine (env := env) (U := U+1) + (As := As) (B := VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (m+p+r.binders.length+1) np ++ idxs)) + (Δ := []) (Γ := Γ) (by + simpa [As, r, idxs, j, RecArg.instL, List.length_reverse, + List.map_map, Function.comp_def] using hf) + simp only [List.length_nil, VExpr.liftN_zero, List.nil_append] at hmajor + have hAsLen : As.length = r.binders.length := by + simp [As, RecArg.minorBinders, VExpr.liftTelN_length] + change env.HasType (U+1) (As.reverse ++ Γ) + ((VExpr.bvar (m-1-r.fieldIndex+p+As.length)).appN + (VExpr.bvarRevRange 0 As.length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (m+p+r.binders.length+1) np ++ idxs)) at hmajor + rw [hAsLen] at hmajor + have hMget : (As.reverse ++ Γ)[m+p+r.binders.length]? = + some (motiveType U T np ty) := by + have hM0 := getElem?_rstack3 As.reverse (Δ ++ Fs.reverse) + (motiveType U T np ty) (paramsTel U np ty).reverse + (i := m+p+r.binders.length) + (by simp [As, RecArg.minorBinders, r, m, Fs, hΔ, VExpr.liftTelN_length, + RecArg.instL]; omega) + simpa [Γ, List.append_assoc] using hM0 + have hM := VEnv.HasType.bvar (env := env) (U := U+1) + (Lookup.of_getElem? hMget) + have hlen : idxs.length = (idxTel U np ty).length := by + simpa [idxs, r, RecArg.instL] using (recArg?_eq hr₀).2.2.2.1 + have hbody := motiveVarApp_hasType (env := env) (U := U) (T := T) + (np := np) (l := l) (ty := ty) hM hsp hlen hmajor + refine IsType.forallN htel ⟨VLevel.param 0, ?_⟩ + simpa [RecArg.minorIH, r, As, idxs, m, Γ, Fs, List.append_assoc] using hbody + +/-- Well-formedness of the generalized induction-hypothesis telescope. Each +entry is supplied by `recArgMinor_isType`; recursive Pi arguments therefore +contribute one functional IH, not one IH per private binder. -/ +theorem Stage3Env.ihsRec_onTel {c : VConstVal} (hc : c ∈ ty.ctors) : + ∀ (rsSuf : List RecArg), + (∀ r ∈ rsSuf, r ∈ recArgsR U T np (idxTel U np ty).length c) → + ∀ (Δ : List VExpr) (p : Nat), Δ.length = p → + OnTel env (U+1) + (Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (ihsFromRecArgs (ctorFieldsR U np c).length rsSuf p) + | [], _, _, _, _ => trivial + | r :: rsSuf, hqs, Δ, p, hΔ => + ⟨S.recArgMinor_isType hc (hqs r (.head _)) Δ p hΔ, + Stage3Env.ihsRec_onTel hc rsSuf (fun q hq => hqs q (.tail _ hq)) + (_ :: Δ) (p+1) (by simp [hΔ])⟩ + +/-- Transport the constructor result's index-spine typing into a rule or +minor context, like `spine_transport` but at the bottom of the full field +telescope. -/ +theorem Stage3Env.result_transport {c : VConstVal} (hc : c ∈ ty.ctors) + (mid : List VExpr) {g : Nat} (hg : mid.length = g) + (As₂ : List VExpr) {d : Nat} (hd : As₂.length = d) : + env.SpineWF (U+1) + (As₂ ++ ((VExpr.liftTelN g (ctorFieldsR U np c) 0).reverse ++ + (mid ++ (paramsTel U np ty).reverse))) + (VExpr.forallN + (VExpr.liftTelN ((ctorFieldsR U np c).length + g + d) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + ((ctorIdxs U np c).map fun e => (e.liftN g (ctorFieldsR U np c).length).liftN d) + (.sort (l.inst (VLevel.params' U 1))) + := by + have hml : (ctorFieldsR U np c).length = + (ctorFields (VExpr.dropN np c.type)).length := ctorFieldsR_length + -- (1) the carried result spine, universes instantiated + have h1 := (S.hresult c hc).instL (U' := U+1) VLevel.params'_one_wf + rw [VExpr.instL_forallN, VExpr.liftTelN_instL, + show ((ctorFields (VExpr.dropN np c.type)).reverse ++ + (VExpr.telN np ty.type).reverse).map (VExpr.instL (VLevel.params' U 1)) = + (ctorFieldsR U np c).reverse ++ (paramsTel U np ty).reverse from by + simp [ctorFieldsR, paramsTel, List.map_reverse], + liftTelN_congr _ _ hml.symm] at h1 + -- (2) insert `mid` at the bottom of the fields + have W₁ := Ctx.LiftN.consTel (n := mid.length) (ctorFieldsR U np c) + (Ctx.LiftN.zero (Γ := (paramsTel U np ty).reverse) mid) + rw [Nat.add_zero] at W₁ + have h2 := h1.weakN S.ord W₁ + rw [VExpr.liftN_forallN, hg] at h2 + -- (3) push the stack underneath + have h3 := h2.weakN S.ord (Ctx.LiftN.zero (Γ := _) As₂ (h := hd)) + rw [VExpr.liftN_forallN] at h3 + rw [VExpr.liftTelN_liftTelN_hi' (ctorFieldsR U np c).length g _ 0 (by omega), + VExpr.liftTelN_liftTelN, + show (ctorFields (VExpr.dropN np ty.type)).map (VExpr.instL (VLevel.params' U 1)) = + idxTel U np ty from rfl] at h3 + simpa [ctorIdxs, VExpr.instL, VExpr.liftN, List.map_map, Function.comp_def, + List.append_assoc] using h3 + +/-- Well-formedness of the induction-hypothesis telescope of a minor +premise, at any suffix of the recursive positions and any depth. -/ +theorem Stage3Env.ihs_onTel {c : VConstVal} (hc : c ∈ ty.ctors) : + ∀ (rsSuf : List (Nat × List VExpr)), + (∀ q ∈ rsSuf, q ∈ recPairsR U T np (idxTel U np ty).length c) → + ∀ (Δ : List VExpr) (p : Nat), Δ.length = p → + OnTel env (U+1) + (Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (ihsFrom (ctorFieldsR U np c).length rsSuf p) + | [], _, _, _, _ => trivial + | (j, idxs) :: rsSuf, hqs, Δ, p, hΔ => by + have hq := hqs _ (List.Mem.head _) + obtain ⟨B, hBj0, hrec0, hidx0⟩ := recPairsR_mem hq + have hBj : (ctorFields (VExpr.dropN np c.type))[j]? = some B := hBj0 + have hrec : isRecField U T np (ctorFields (VExpr.dropN np ty.type)).length j B = + true := by + have h : isRecField U T np (idxTel U np ty).length j B = true := hrec0 + rwa [idxTel_length] at h + have hidx' : idxs = (recFieldIdxs np B).map (VExpr.instL (VLevel.params' U 1)) := hidx0 + have hjlt : j < (ctorFields (VExpr.dropN np c.type)).length := by + simpa using recPairsR_lt _ hq + have hml : (ctorFieldsR U np c).length = + (ctorFields (VExpr.dropN np c.type)).length := ctorFieldsR_length + have hml2 : (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length := VExpr.liftTelN_length .. + have hni : (recFieldIdxs np B).length = (ctorFields (VExpr.dropN np ty.type)).length := + (isRecField_eq hrec).2.1 + refine ⟨?_, Stage3Env.ihs_onTel hc rsSuf (fun q hq' => hqs q (.tail _ hq')) + (_ :: Δ) (p+1) (by simp [hΔ])⟩ + -- the motive variable + have hM := getElem?_stack3 Δ + ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse) + (paramsTel U np ty).reverse (motiveType U T np ty) + (i := (ctorFieldsR U np c).length + p) + (by simp only [hΔ, List.length_reverse, VExpr.liftTelN_length]; omega) + have hmlu := Lookup.of_getElem? hM + rw [motiveType_liftN] at hmlu + -- the transported index spine + have hSp := S.spine_transport hc hBj hrec [motiveType U T np ty] (g := 1) rfl + (Δ ++ ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).drop j).reverse) + (d := (ctorFieldsR U np c).length - j + p) + (by simp only [List.length_append, List.length_reverse, List.length_drop, + hml2, hΔ] + omega) + rw [show (Δ ++ ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).drop j).reverse) ++ + ((VExpr.liftTelN 1 ((ctorFieldsR U np c).take j) 0).reverse ++ + ([motiveType U T np ty] ++ (paramsTel U np ty).reverse)) = + Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse) from by + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc (((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).drop j).reverse), + ← List.reverse_append, List.take_append_drop, List.singleton_append, + ← List.append_assoc], + liftTelN_congr _ _ (show j + 1 + ((ctorFieldsR U np c).length - j + p) = + (ctorFieldsR U np c).length + p + 1 from by omega), + ← hidx'] at hSp + -- retarget onto the motive's pi and compute the instantiation + have hlen : (idxs.map fun e => (e.liftN 1 j).liftN + ((ctorFieldsR U np c).length - j + p)).length = + (VExpr.liftTelN ((ctorFieldsR U np c).length + p + 1) (idxTel U np ty) 0).length := by + simp only [List.length_map, VExpr.liftTelN_length, hidx', idxTel_length] + exact hni + have hRe := hSp.retarget hlen (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + p + 1 + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + rw [show VExpr.instRev (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + p + 1 + + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + (idxs.map fun e => (e.liftN 1 j).liftN ((ctorFieldsR U np c).length - j + p)) = + .forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + p + 1) np ++ + idxs.map fun e => (e.liftN 1 j).liftN ((ctorFieldsR U np c).length - j + p))) + (.sort (.param 0)) from by + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ (C := .const T (VLevel.params' U 1)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by + simp only [List.length_map] + rw [hidx', List.length_map, hni, ← idxTel_length (U := U) (ty := ty)] + omega), + show (ctorFieldsR U np c).length + p + 1 + (idxTel U np ty).length - + (idxs.map fun e => (e.liftN 1 j).liftN + ((ctorFieldsR U np c).length - j + p)).length = + (ctorFieldsR U np c).length + p + 1 from by + simp only [List.length_map] + rw [hidx', List.length_map, hni, ← idxTel_length (U := U) (ty := ty)] + omega, + VExpr.bvarRevRange_congr' 0 (show (idxTel U np ty).length = + (idxs.map fun e => (e.liftN 1 j).liftN + ((ctorFieldsR U np c).length - j + p)).length from by + simp only [List.length_map] + rw [hidx', List.length_map, hni, ← idxTel_length (U := U) (ty := ty)]), + VExpr.map_instRev_bvarRevRange]] at hRe + -- the motive applied to the index arguments + have hApp := hRe.hasType_appN (f := .bvar ((ctorFieldsR U np c).length + p)) (.bvar hmlu) + -- the recursive-field variable + have hF := getElem?_stack_mid Δ + ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse) + (motiveType U T np ty :: (paramsTel U np ty).reverse) + (i := (ctorFieldsR U np c).length - 1 - j + p) + (by rw [hΔ]; omega) + (by simp only [hΔ, List.length_reverse, VExpr.liftTelN_length]; omega) + rw [show (ctorFieldsR U np c).length - 1 - j + p - Δ.length = + (ctorFieldsR U np c).length - 1 - j from by rw [hΔ]; omega, + List.getElem?_reverse (by simp only [VExpr.liftTelN_length]; omega), + VExpr.liftTelN_length, + show (ctorFieldsR U np c).length - 1 - + ((ctorFieldsR U np c).length - 1 - j) = j from by omega, + VExpr.liftTelN_getElem?, ctorFieldsR_getElem?, hBj] at hF + simp only [Option.map_some] at hF + have hflu := Lookup.of_getElem? hF + rw [show (((B.instL (VLevel.params' U 1)).liftN 1 (0+j)).liftN + ((ctorFieldsR U np c).length - 1 - j + p + 1)) = + VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + p + 1) np ++ + idxs.map fun e => (e.liftN 1 j).liftN + ((ctorFieldsR U np c).length - j + p)) from by + conv => lhs; rw [(isRecField_eq hrec).1] + rw [VExpr.instL_appN, List.map_append, bvarRevRange_instL, + show (VExpr.const T (VLevel.params U)).instL (VLevel.params' U 1) = + .const T (VLevel.params' U 1) from by + simp [VExpr.instL, VLevel.params_map_inst_params'], + VExpr.liftN_appN, VExpr.liftN_appN, List.map_append, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.bvarRevRange_congr np (show (ctorFieldsR U np c).length - 1 - j + p + 1 + + (1 + j) = (ctorFieldsR U np c).length + p + 1 from by omega), + ← hidx', List.map_map] + refine congrArg (VExpr.appN _) (congrArg (VExpr.bvarRevRange _ np ++ ·) ?_) + refine List.map_congr_left fun e _ => ?_ + show (e.liftN 1 (0+j)).liftN ((ctorFieldsR U np c).length - 1 - j + p + 1) = _ + rw [show (0+j) = j from Nat.zero_add j, + show (ctorFieldsR U np c).length - 1 - j + p + 1 = + (ctorFieldsR U np c).length - j + p from by omega]] at hflu + have happ2 : env.HasType (U+1) + (Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + p)) + ((idxs.map fun e => (e.liftN 1 j).liftN + ((ctorFieldsR U np c).length - j + p)) ++ + [.bvar ((ctorFieldsR U np c).length - 1 - j + p)])) + ((VExpr.sort (.param 0)).inst + (.bvar ((ctorFieldsR U np c).length - 1 - j + p))) := by + rw [VExpr.appN_append] + exact HasType.app hApp (.bvar hflu) + exact ⟨_, happ2⟩ +theorem Stage3Env.ctorAppMin_hasType {c : VConstVal} (hc : c ∈ ty.ctors) + (Δ : List VExpr) : + env.HasType (U+1) + (Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange Δ.length (ctorFieldsR U np c).length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + (ctorFieldsR U np c).length + 1) np ++ + (ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN Δ.length)) := by + have hml : (ctorFieldsR U np c).length = + (ctorFields (VExpr.dropN np c.type)).length := ctorFieldsR_length + have hml2 : (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length := VExpr.liftTelN_length .. + have hcl : (c.type.instL (VLevel.params' U 1)).ClosedN 0 := + (Ordered.closedC (ci := ⟨U, c.type⟩) S.ord (S.hcs c hc)).instL + -- step A: consume the parameter telescope + have hfA : env.HasType (U+1) + ((Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + [motiveType U T np ty]) ++ (paramsTel U np ty).reverse ++ []) + (.const c.name (VLevel.params' U 1)) + ((VExpr.forallN (paramsTel U np ty) + (VExpr.forallN (ctorFieldsR U np c) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + ctorIdxs U np c)))).liftN + ((Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + [motiveType U T np ty]).length + (paramsTel U np ty).length)) := by + rw [← S.ctorType_instL hc, hcl.liftN_eq (Nat.zero_le _)] + exact S.cConst hc + have hA := HasType.appN_selfSpine (env := env) (U := U+1) hfA + -- step B: consume the field telescope + rw [VExpr.liftN_forallN] at hA + have hBeq : VExpr.forallN + (VExpr.liftTelN ((Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + [motiveType U T np ty]).length) (ctorFieldsR U np c) 0) + ((VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + ctorIdxs U np c)).liftN + ((Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + [motiveType U T np ty]).length) (0 + (ctorFieldsR U np c).length)) = + (VExpr.forallN (VExpr.liftTelN 1 (ctorFieldsR U np c) 0) + ((VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + ctorIdxs U np c)).liftN 1 (0 + (ctorFieldsR U np c).length))).liftN + (Δ.length + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length) := by + conv => rhs; rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + show (0:Nat) + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + 0 + (ctorFieldsR U np c).length from by rw [hml2], + VExpr.liftN'_liftN_hi] + rw [liftTelN_congr _ _ (show (1:Nat) + (Δ.length + + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length) = + (Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + [motiveType U T np ty]).length from by + simp only [List.length_append, List.length_reverse, VExpr.liftTelN_length, + List.length_singleton] + omega), + show (1 + (Δ.length + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length)) = + (Δ ++ (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + [motiveType U T np ty]).length from by + simp only [List.length_append, List.length_reverse, VExpr.liftTelN_length, + List.length_singleton] + omega] + rw [hBeq] at hA + have hB := HasType.appN_selfSpine (env := env) (U := U+1) + (Δ := Δ) (Γ := motiveType U T np ty :: (paramsTel U np ty).reverse) + (As := VExpr.liftTelN 1 (ctorFieldsR U np c) 0) + (B := (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + ctorIdxs U np c)).liftN 1 (0 + (ctorFieldsR U np c).length)) + (by simpa [List.append_assoc, List.append_nil] using hA) + rw [show (paramsTel U np ty).length = np from by + simp [paramsTel, List.length_map, S.hlen], + VExpr.bvarRevRange_congr np (show Δ.length + + ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length + 1) = + Δ.length + (ctorFieldsR U np c).length + 1 from by omega), + VExpr.liftTelN_length] at hB + rw [show ((VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + ctorIdxs U np c)).liftN 1 (0 + (ctorFieldsR U np c).length)).liftN Δ.length = + VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + (ctorFieldsR U np c).length + 1) np ++ + (ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN Δ.length) from by + rw [VExpr.liftN_appN, VExpr.liftN_appN, List.map_append, List.map_append, + Nat.zero_add ((ctorFieldsR U np c).length), + bvarRevRange_liftN_ge _ _ _ _ (by omega), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.bvarRevRange_congr np (show Δ.length + + (1 + (0 + (ctorFields (VExpr.dropN np c.type)).length)) = + Δ.length + (ctorFieldsR U np c).length + 1 from by omega), + List.map_map] + rfl] at hB + rw [show VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange Δ.length (ctorFieldsR U np c).length) = + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + (ctorFieldsR U np c).length + 1) np)).appN + (VExpr.bvarRevRange Δ.length (ctorFieldsR U np c).length) from + VExpr.appN_append ..] + exact hB + +/-- The minor premise for a constructor is a type over +`params ++ [motive]`. -/ +theorem Stage3Env.minor_isType {c : VConstVal} (hc : c ∈ ty.ctors) : + env.IsType (U+1) (motiveType U T np ty :: (paramsTel U np ty).reverse) + (minorType U T np ty c) := by + simp only [minorType] + refine IsType.forallN ?_ ?_ + · have h0 := S.fieldsWF_onTel _ [] 0 rfl (by simpa using S.hfields c hc) + have h1 := h0.weakN S.ord (.zero [motiveType U T np ty]) + simpa [ctorFieldsR, List.map_reverse, paramsTel] using h1 + · refine IsType.forallN (S.ihs_onTel hc _ (fun q hq => hq) [] 0 rfl) ?_ + have hml2 : (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length := VExpr.liftTelN_length .. + have hrlen : ((ihsFrom (ctorFieldsR U np c).length + (recPairsR U T np (idxTel U np ty).length c) 0).reverse).length = + (recPairsR U T np (idxTel U np ty).length c).length := by + simp [ihsFrom_length] + -- the motive variable + have hM := getElem?_rstack3 ((ihsFrom (ctorFieldsR U np c).length + (recPairsR U T np (idxTel U np ty).length c) 0).reverse) + ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse) + (motiveType U T np ty) (paramsTel U np ty).reverse + (i := (ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length) + (by simp only [List.length_reverse, ihsFrom_length, VExpr.liftTelN_length]; omega) + have hmlu := Lookup.of_getElem? hM + rw [motiveType_liftN] at hmlu + -- the transported result spine + have hSp := S.result_transport hc [motiveType U T np ty] (g := 1) rfl + ((ihsFrom (ctorFieldsR U np c).length + (recPairsR U T np (idxTel U np ty).length c) 0).reverse) + (d := (recPairsR U T np (idxTel U np ty).length c).length) hrlen + rw [liftTelN_congr _ _ (show (ctorFieldsR U np c).length + 1 + + (recPairsR U T np (idxTel U np ty).length c).length = + (ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1 from by omega)] at hSp + have hlen : ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recPairsR U T np (idxTel U np ty).length c).length).length = + (VExpr.liftTelN ((ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1) + (idxTel U np ty) 0).length := by + simp only [List.length_map, VExpr.liftTelN_length, ctorIdxs_length, idxTel_length] + have hc3 := stage3Ctor_eq (S.hs3 c hc) + exact hc3.2.1 + have hRe := hSp.retarget hlen (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1 + + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + rw [show VExpr.instRev (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1 + + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recPairsR U T np (idxTel U np ty).length c).length) = + .forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1) np ++ + (ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recPairsR U T np (idxTel U np ty).length c).length)) + (.sort (.param 0)) from by + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ (C := .const T (VLevel.params' U 1)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by + rw [hlen, VExpr.liftTelN_length]; omega), + show (ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1 + + (idxTel U np ty).length - + ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recPairsR U T np (idxTel U np ty).length c).length).length = + (ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1 from by + rw [hlen, VExpr.liftTelN_length] + omega, + VExpr.bvarRevRange_congr' 0 (show (idxTel U np ty).length = + ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recPairsR U T np (idxTel U np ty).length c).length).length from by + rw [hlen, VExpr.liftTelN_length]), + VExpr.map_instRev_bvarRevRange]] at hRe + -- the motive applied to the result indices + have hApp := hRe.hasType_appN (f := .bvar ((ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length)) (.bvar hmlu) + -- the constructor application + have hctor := S.ctorAppMin_hasType hc + ((ihsFrom (ctorFieldsR U np c).length + (recPairsR U T np (idxTel U np ty).length c) 0).reverse) + rw [hrlen] at hctor + rw [VExpr.bvarRevRange_congr np (show + (recPairsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1 from by omega)] at hctor + have happ2 : env.HasType (U+1) + ((ihsFrom (ctorFieldsR U np c).length + (recPairsR U T np (idxTel U np ty).length c) 0).reverse ++ + ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recPairsR U T np (idxTel U np ty).length c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((recPairsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange (recPairsR U T np (idxTel U np ty).length c).length + (ctorFieldsR U np c).length)])) + ((VExpr.sort (.param 0)).inst + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((recPairsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange (recPairsR U T np (idxTel U np ty).length c).length + (ctorFieldsR U np c).length))) := by + rw [VExpr.appN_append, + VExpr.bvarRevRange_congr np (show + (recPairsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + + (recPairsR U T np (idxTel U np ty).length c).length + 1 from by omega)] + exact HasType.app hApp (by simpa [List.append_assoc] using hctor) + exact ⟨_, by simpa [List.append_assoc] using happ2⟩ + +/-- The generalized minor premise is a type over `params ++ [motive]`. +This is the preservation theorem used by `minorTypeRec`; it differs from +`minor_isType` only in the functional-IH telescope supplied for recursive +Pi arguments. -/ +theorem Stage3Env.minor_isTypeRec {c : VConstVal} (hc : c ∈ ty.ctors) : + env.IsType (U+1) (motiveType U T np ty :: (paramsTel U np ty).reverse) + (minorTypeRec U T np ty c) := by + simp only [minorTypeRec] + refine IsType.forallN ?_ ?_ + · have h0 := S.fieldsWF_onTel _ [] 0 rfl (by simpa using S.hfields c hc) + have h1 := h0.weakN S.ord (.zero [motiveType U T np ty]) + simpa [ctorFieldsR, List.map_reverse, paramsTel] using h1 + · refine IsType.forallN (S.ihsRec_onTel hc _ (fun q hq => hq) [] 0 rfl) ?_ + have hml2 : (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length := VExpr.liftTelN_length .. + have hrlen : ((ihsFromRecArgs (ctorFieldsR U np c).length + (recArgsR U T np (idxTel U np ty).length c) 0).reverse).length = + (recArgsR U T np (idxTel U np ty).length c).length := by + simp [ihsFromRecArgs_length] + -- the motive variable + have hM := getElem?_rstack3 ((ihsFromRecArgs (ctorFieldsR U np c).length + (recArgsR U T np (idxTel U np ty).length c) 0).reverse) + ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse) + (motiveType U T np ty) (paramsTel U np ty).reverse + (i := (ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length) + (by simp only [List.length_reverse, ihsFromRecArgs_length, + VExpr.liftTelN_length]; omega) + have hmlu := Lookup.of_getElem? hM + rw [motiveType_liftN] at hmlu + -- the transported result spine + have hSp := S.result_transport hc [motiveType U T np ty] (g := 1) rfl + ((ihsFromRecArgs (ctorFieldsR U np c).length + (recArgsR U T np (idxTel U np ty).length c) 0).reverse) + (d := (recArgsR U T np (idxTel U np ty).length c).length) hrlen + rw [liftTelN_congr _ _ (show (ctorFieldsR U np c).length + 1 + + (recArgsR U T np (idxTel U np ty).length c).length = + (ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1 from by omega)] at hSp + have hlen : ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recArgsR U T np (idxTel U np ty).length c).length).length = + (VExpr.liftTelN ((ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1) + (idxTel U np ty) 0).length := by + simp only [List.length_map, VExpr.liftTelN_length, ctorIdxs_length, idxTel_length] + have hc3 := stage3Ctor_eq (S.hs3 c hc) + exact hc3.2.1 + have hRe := hSp.retarget hlen (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1 + + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + rw [show VExpr.instRev (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1 + + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recArgsR U T np (idxTel U np ty).length c).length) = + .forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1) np ++ + (ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recArgsR U T np (idxTel U np ty).length c).length)) + (.sort (.param 0)) from by + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ (C := .const T (VLevel.params' U 1)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by + rw [hlen, VExpr.liftTelN_length]; omega), + show (ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1 + + (idxTel U np ty).length - + ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recArgsR U T np (idxTel U np ty).length c).length).length = + (ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1 from by + rw [hlen, VExpr.liftTelN_length] + omega, + VExpr.bvarRevRange_congr' 0 (show (idxTel U np ty).length = + ((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recArgsR U T np (idxTel U np ty).length c).length).length from by + rw [hlen, VExpr.liftTelN_length]), + VExpr.map_instRev_bvarRevRange]] at hRe + -- the motive applied to the result indices + have hApp := hRe.hasType_appN (f := .bvar ((ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length)) (.bvar hmlu) + -- the constructor application + have hctor := S.ctorAppMin_hasType hc + ((ihsFromRecArgs (ctorFieldsR U np c).length + (recArgsR U T np (idxTel U np ty).length c) 0).reverse) + rw [hrlen] at hctor + rw [VExpr.bvarRevRange_congr np (show + (recArgsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1 from by omega)] at hctor + have happ2 : env.HasType (U+1) + ((ihsFromRecArgs (ctorFieldsR U np c).length + (recArgsR U T np (idxTel U np ty).length c) 0).reverse ++ + ((VExpr.liftTelN 1 (ctorFieldsR U np c) 0).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + (recArgsR U T np (idxTel U np ty).length c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((recArgsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange (recArgsR U T np (idxTel U np ty).length c).length + (ctorFieldsR U np c).length)])) + ((VExpr.sort (.param 0)).inst + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((recArgsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange (recArgsR U T np (idxTel U np ty).length c).length + (ctorFieldsR U np c).length))) := by + rw [VExpr.appN_append, + VExpr.bvarRevRange_congr np (show + (recArgsR U T np (idxTel U np ty).length c).length + + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + + (recArgsR U T np (idxTel U np ty).length c).length + 1 from by omega)] + exact HasType.app hApp (by simpa [List.append_assoc] using hctor) + exact ⟨_, by simpa [List.append_assoc] using happ2⟩ + +/-- The minor premises, in position, are a telescope over +`params ++ [motive]`. -/ +theorem Stage3Env.minorTypes_onTel : + ∀ (cs' : List VConstVal), (∀ c ∈ cs', c ∈ ty.ctors) → + ∀ (Δ : List VExpr) (i : Nat), Δ.length = i → + OnTel env (U+1) (Δ ++ (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (minorTypes U T np ty cs' i) + | [], _, _, _, _ => trivial + | c :: cs', hsub, Δ, i, hΔ => + ⟨by + rw [← hΔ] + exact (S.minor_isType (hsub c (.head _))).weakN S.ord (.zero Δ), + Stage3Env.minorTypes_onTel cs' (fun c h => hsub c (.tail _ h)) (_ :: Δ) (i+1) + (by simp [hΔ])⟩ + +/-- Generalized minor premises, including functional recursive hypotheses, +form a telescope over `params ++ [motive]`. -/ +theorem Stage3Env.minorTypesRec_onTel : + ∀ (cs' : List VConstVal), (∀ c ∈ cs', c ∈ ty.ctors) → + ∀ (Δ : List VExpr) (i : Nat), Δ.length = i → + OnTel env (U+1) (Δ ++ (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (minorTypesRec U T np ty cs' i) + | [], _, _, _, _ => trivial + | c :: cs', hsub, Δ, i, hΔ => + ⟨by + rw [← hΔ] + exact (S.minor_isTypeRec (hsub c (.head _))).weakN S.ord (.zero Δ), + Stage3Env.minorTypesRec_onTel cs' (fun c h => hsub c (.tail _ h)) (_ :: Δ) (i+1) + (by simp [hΔ])⟩ + +/-- The generated recursor type is well-formed. -/ +theorem Stage3Env.recType_isType : env.IsType (U+1) [] (recType U T np ty) := by + have hP : OnTel env (U+1) [] (paramsTel U np ty) := by + have := S.hparams.of_append.1.instL (U' := U+1) VLevel.params'_one_wf + simpa [paramsTel] using this + refine IsType.forallN hP ?_ + simp only [List.append_nil] + refine IsType.forallE S.motive_isType ?_ + refine IsType.forallN + (by simpa using S.minorTypes_onTel ty.ctors (fun _ h => h) [] 0 rfl) ?_ + have hI : OnTel env (U+1) + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) := by + have h := S.idxTel_onTel.weakN S.ord + (Ctx.LiftN.zero (n := ty.ctors.length + 1) + (Γ := (paramsTel U np ty).reverse) + ((minorTypes U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (h := by simp [minorTypes_length])) + simpa [List.append_assoc] using h + refine IsType.forallN hI ?_ + have hmaj : env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (l.inst (VLevel.params' U 1))) := by + have W := Ctx.LiftN.consTel (n := ty.ctors.length + 1) (idxTel U np ty) + (Ctx.LiftN.zero (n := ty.ctors.length + 1) + (Γ := (paramsTel U np ty).reverse) + ((minorTypes U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (h := by simp [minorTypes_length])) + have h := S.motiveTApp_hasType.weakN S.ord W + simp only [Nat.add_zero, VExpr.liftN_appN, VExpr.liftN, List.map_append] at h + rw [bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + VExpr.bvarRevRange_congr np (show + ty.ctors.length + 1 + (idxTel U np ty).length = + (idxTel U np ty).length + ty.ctors.length + 1 from by omega)] at h + simpa [List.append_assoc] using h + refine IsType.forallE ⟨_, hmaj⟩ ?_ + have hM := getElem?_rstack3 + [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)] + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + (minorTypes U T np ty ty.ctors).reverse) + (motiveType U T np ty) (paramsTel U np ty).reverse + (i := (idxTel U np ty).length + ty.ctors.length + 1) + (by simp only [List.length_singleton, List.length_append, List.length_reverse, + VExpr.liftTelN_length, minorTypes_length]; omega) + have hmlu := Lookup.of_getElem? (by + simpa only [List.singleton_append, List.append_assoc] using hM) + rw [show (motiveType U T np ty).liftN + ((idxTel U np ty).length + ty.ctors.length + 1 + 1) = + ((motiveType U T np ty).liftN (ty.ctors.length + 1)).liftN + ((idxTel U np ty).length + 1) from by + rw [VExpr.liftN_liftN] + congr 1 + omega, + motiveType_liftN] at hmlu + have hfun : env.HasType (U+1) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length) :: + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)))) + (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + ((VExpr.forallN + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (ty.ctors.length + 1 + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0)))).liftN + (1 + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).length)) := by + exact .bvar (by + simpa [List.append_assoc, VExpr.liftTelN_length, Nat.add_comm] using hmlu) + have hMapp := HasType.appN_selfSpine + (As := VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (Δ := [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)]) + (Γ := (minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (f := .bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + hfun + have h0 : + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length) :: + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))))[0]? = + some (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) := rfl + have harg := HasType.bvar (env := env) (U := U+1) (Lookup.of_getElem? h0) + have harg' : env.HasType (U+1) + ([VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)] ++ + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (.bvar 0) + ((VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (ty.ctors.length + 1 + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)).liftN + [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)].length) := by + simpa [List.append_assoc, Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using harg + have happ := HasType.app hMapp harg' + exact ⟨_, by + simpa [List.append_assoc, VExpr.liftTelN_length] using happ⟩ + +/-- The generalized recursor type, whose constructor minors include +functional IHs for recursive Pi arguments, is well-formed. -/ +theorem Stage3Env.recTypeRec_isType : env.IsType (U+1) [] (recTypeRec U T np ty) := by + have hP : OnTel env (U+1) [] (paramsTel U np ty) := by + have := S.hparams.of_append.1.instL (U' := U+1) VLevel.params'_one_wf + simpa [paramsTel] using this + refine IsType.forallN hP ?_ + simp only [List.append_nil] + refine IsType.forallE S.motive_isType ?_ + refine IsType.forallN + (by simpa using S.minorTypesRec_onTel ty.ctors (fun _ h => h) [] 0 rfl) ?_ + have hI : OnTel env (U+1) + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) := by + have h := S.idxTel_onTel.weakN S.ord + (Ctx.LiftN.zero (n := ty.ctors.length + 1) + (Γ := (paramsTel U np ty).reverse) + ((minorTypesRec U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (h := by simp [minorTypesRec_length])) + simpa [List.append_assoc] using h + refine IsType.forallN hI ?_ + have hmaj : env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (l.inst (VLevel.params' U 1))) := by + have W := Ctx.LiftN.consTel (n := ty.ctors.length + 1) (idxTel U np ty) + (Ctx.LiftN.zero (n := ty.ctors.length + 1) + (Γ := (paramsTel U np ty).reverse) + ((minorTypesRec U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (h := by simp [minorTypesRec_length])) + have h := S.motiveTApp_hasType.weakN S.ord W + simp only [Nat.add_zero, VExpr.liftN_appN, VExpr.liftN, List.map_append] at h + rw [bvarRevRange_liftN_ge _ _ _ _ (Nat.le_refl _), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + VExpr.bvarRevRange_congr np (show + ty.ctors.length + 1 + (idxTel U np ty).length = + (idxTel U np ty).length + ty.ctors.length + 1 from by omega)] at h + simpa [List.append_assoc] using h + refine IsType.forallE ⟨_, hmaj⟩ ?_ + have hM := getElem?_rstack3 + [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)] + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + (minorTypesRec U T np ty ty.ctors).reverse) + (motiveType U T np ty) (paramsTel U np ty).reverse + (i := (idxTel U np ty).length + ty.ctors.length + 1) + (by simp only [List.length_singleton, List.length_append, List.length_reverse, + VExpr.liftTelN_length, minorTypesRec_length]; omega) + have hmlu := Lookup.of_getElem? (by + simpa only [List.singleton_append, List.append_assoc] using hM) + rw [show (motiveType U T np ty).liftN + ((idxTel U np ty).length + ty.ctors.length + 1 + 1) = + ((motiveType U T np ty).liftN (ty.ctors.length + 1)).liftN + ((idxTel U np ty).length + 1) from by + rw [VExpr.liftN_liftN] + congr 1 + omega, + motiveType_liftN] at hmlu + have hfun : env.HasType (U+1) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length) :: + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)))) + (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + ((VExpr.forallN + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (ty.ctors.length + 1 + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0)))).liftN + (1 + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).length)) := by + exact .bvar (by + simpa [List.append_assoc, VExpr.liftTelN_length, Nat.add_comm] using hmlu) + have hMapp := HasType.appN_selfSpine + (As := VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (Δ := [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)]) + (Γ := (minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (f := .bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + hfun + have h0 : + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length) :: + ((VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))))[0]? = + some (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) := rfl + have harg := HasType.bvar (env := env) (U := U+1) (Lookup.of_getElem? h0) + have harg' : env.HasType (U+1) + ([VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)] ++ + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (.bvar 0) + ((VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (ty.ctors.length + 1 + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)).liftN + [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)].length) := by + simpa [List.append_assoc, Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using harg + have happ := HasType.app hMapp harg' + exact ⟨_, by + simpa [List.append_assoc, VExpr.liftTelN_length] using happ⟩ + +theorem Stage3Env.recConstRec_wf : (recConstRec U T np ty).WF env := + S.recTypeRec_isType + +theorem Stage3Env.recConst_wf : (recConst U T np ty).WF env := + S.recType_isType + +/-! ## The iota rules -/ + +/-- The recursor type is closed, by well-formedness. -/ +theorem Stage3Env.recType_closedN : (recType U T np ty).ClosedN 0 := by + obtain ⟨u, h⟩ := S.recType_isType + exact VExpr.WF.closedN S.ord ⟨_, h⟩ trivial + +theorem Stage3Env.recTypeRec_closedN : (recTypeRec U T np ty).ClosedN 0 := by + obtain ⟨u, h⟩ := S.recTypeRec_isType + exact VExpr.WF.closedN S.ord ⟨_, h⟩ trivial + +/-- The recursor constant at its own (identity) universe list. -/ +theorem Stage3Env.recConst_hasType + (hrec : env.constants (.str T "rec") = some (recConst U T np ty)) {Γ} : + env.HasType (U+1) Γ (.const (.str T "rec") (VLevel.params (U+1))) + (recType U T np ty) := by + have := HasType.const (Γ := Γ) hrec VLevel.params_wf VLevel.params_length + rw [show (recConst U T np ty).uvars = U + 1 from rfl, + show (recConst U T np ty).type = recType U T np ty from rfl] at this + rwa [recType_levelWF.instL_id] at this + +theorem Stage3Env.recConstRec_hasType + (hrec : env.constants (.str T "rec") = some (recConstRec U T np ty)) {Γ} : + env.HasType (U+1) Γ (.const (.str T "rec") (VLevel.params (U+1))) + (recTypeRec U T np ty) := by + have := HasType.const (Γ := Γ) hrec VLevel.params_wf VLevel.params_length + rw [show (recConstRec U T np ty).uvars = U + 1 from rfl, + show (recConstRec U T np ty).type = recTypeRec U T np ty from rfl] at this + rwa [recTypeRec_levelWF.instL_id] at this + +/-- The recursor applied to its parameter, motive, and minor-premise +spine. The remaining type is the (lifted) index telescope followed by +the major premise. -/ +theorem Stage3Env.recBase_hasType + (hrec : env.constants (.str T "rec") = some (recConst U T np ty)) + (Δ : List VExpr) : + env.HasType (U+1) + (Δ ++ ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange Δ.length (np + ty.ctors.length + 1))) + ((VExpr.forallN (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0)))).liftN Δ.length) := by + have hf : env.HasType (U+1) + (Δ ++ (paramsTel U np ty ++ + motiveType U T np ty :: minorTypes U T np ty ty.ctors).reverse ++ []) + (.const (.str T "rec") (VLevel.params (U+1))) + ((VExpr.forallN (paramsTel U np ty ++ + motiveType U T np ty :: minorTypes U T np ty ty.ctors) + (VExpr.forallN (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0))))).liftN + (Δ.length + (paramsTel U np ty ++ + motiveType U T np ty :: minorTypes U T np ty ty.ctors).length)) := by + rw [show VExpr.forallN (paramsTel U np ty ++ + motiveType U T np ty :: minorTypes U T np ty ty.ctors) + (VExpr.forallN (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0)))) = + recType U T np ty from by rw [VExpr.forallN_append]; rfl, + S.recType_closedN.liftN_eq (Nat.zero_le _)] + exact S.recConst_hasType hrec + have hspine := HasType.appN_selfSpine (env := env) (U := U+1) hf + simp only [List.reverse_append, List.reverse_cons, List.append_nil, List.append_assoc, + List.singleton_append, List.length_append, List.length_cons, minorTypes_length] at hspine + rw [show (paramsTel U np ty).length = np from by + simp [paramsTel, List.length_map, S.hlen], + VExpr.bvarRevRange_congr' Δ.length (show + np + (ty.ctors.length + 1) = np + ty.ctors.length + 1 from by omega)] at hspine + simpa [List.append_assoc] using hspine + +theorem Stage3Env.recBaseRec_hasType + (hrec : env.constants (.str T "rec") = some (recConstRec U T np ty)) + (Δ : List VExpr) : + env.HasType (U+1) + (Δ ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange Δ.length (np + ty.ctors.length + 1))) + ((VExpr.forallN (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0)))).liftN Δ.length) := by + have hf : env.HasType (U+1) + (Δ ++ (paramsTel U np ty ++ + motiveType U T np ty :: minorTypesRec U T np ty ty.ctors).reverse ++ []) + (.const (.str T "rec") (VLevel.params (U+1))) + ((VExpr.forallN (paramsTel U np ty ++ + motiveType U T np ty :: minorTypesRec U T np ty ty.ctors) + (VExpr.forallN (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0))))).liftN + (Δ.length + (paramsTel U np ty ++ + motiveType U T np ty :: minorTypesRec U T np ty ty.ctors).length)) := by + rw [show VExpr.forallN (paramsTel U np ty ++ + motiveType U T np ty :: minorTypesRec U T np ty ty.ctors) + (VExpr.forallN (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0)))) = + recTypeRec U T np ty from by rw [VExpr.forallN_append]; rfl, + S.recTypeRec_closedN.liftN_eq (Nat.zero_le _)] + exact S.recConstRec_hasType hrec + have hspine := HasType.appN_selfSpine (env := env) (U := U+1) hf + simp only [List.reverse_append, List.reverse_cons, List.append_nil, List.append_assoc, + List.singleton_append, List.length_append, List.length_cons, minorTypesRec_length] at hspine + rw [show (paramsTel U np ty).length = np from by + simp [paramsTel, List.length_map, S.hlen], + VExpr.bvarRevRange_congr' Δ.length (show + np + (ty.ctors.length + 1) = np + ty.ctors.length + 1 from by omega)] at hspine + simpa [List.append_assoc] using hspine + +/-- Apply the generated recursor to an index spine and its major premise. +This is shared by constructor-headed rule left sides and by the recursive +calls appearing in minor-premise right sides. -/ +theorem Stage3Env.recApp_hasType + (hrec : env.constants (.str T "rec") = some (recConst U T np ty)) + (Δ : List VExpr) {idxs : List VExpr} {a : VExpr} + (hidx : env.SpineWF (U+1) + (Δ ++ ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + idxs (.sort (l.inst (VLevel.params' U 1)))) + (hlen : idxs.length = (idxTel U np ty).length) + (ha : env.HasType (U+1) + (Δ ++ ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) a + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + ty.ctors.length + 1) np ++ idxs))) : + env.HasType (U+1) + (Δ ++ ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange Δ.length (np + ty.ctors.length + 1))) + (idxs ++ [a])) + (VExpr.appN (.bvar (Δ.length + ty.ctors.length)) (idxs ++ [a])) := by + have hb := S.recBase_hasType hrec Δ + rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ (show ty.ctors.length + 1 + Δ.length = + Δ.length + ty.ctors.length + 1 from by omega)] at hb + have hcod : + (VExpr.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0))).liftN Δ.length + (0 + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).length) = + VExpr.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0)) := by + rw [VExpr.liftTelN_length, Nat.zero_add] + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + VExpr.bvarRevRange_congr np (show Δ.length + + ((idxTel U np ty).length + ty.ctors.length + 1) = + (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 from by omega)] + rfl + · show VExpr.app _ _ = VExpr.app _ _ + congr 1 + · rw [VExpr.liftN_appN, + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + show VExpr.appN (.bvar (liftVar Δ.length + ((idxTel U np ty).length + ty.ctors.length + 1) + ((idxTel U np ty).length + 1))) _ = _ + rw [liftVar_le (by omega), show Δ.length + + ((idxTel U np ty).length + ty.ctors.length + 1) = + (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 from by omega] + rw [hcod] at hb + have hshape := hidx.retarget (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ (C := .const T (VLevel.params' U 1)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by rw [hlen]; omega), + show (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 - idxs.length = + Δ.length + ty.ctors.length + 1 from by rw [hlen]; omega, + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hfull := hshape.snoc ha + simp only [VExpr.inst] at hfull + change env.SpineWF (U+1) _ + (VExpr.forallN + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0) + (VExpr.forallN [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)] + (.sort (.param 0)))) + (idxs ++ [a]) (.sort (.param 0)) at hfull + rw [← VExpr.forallN_append] at hfull + have hfullLen : (idxs ++ [a]).length = + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0 ++ + [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)]).length := by + simp only [List.length_append, List.length_singleton, VExpr.liftTelN_length, hlen] + have hactual := hfull.retarget hfullLen + (VExpr.app + (VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) + (.bvar 0)) + rw [VExpr.forallN_append] at hactual + have happ := hactual.hasType_appN hb + rw [show VExpr.app + (VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) + (.bvar 0) = + VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) (VExpr.bvarRevRange 0 ((idxTel U np ty).length + 1)) from by + rw [VExpr.bvarRevRange_congr' 0 (show (idxTel U np ty).length + 1 = + 1 + (idxTel U np ty).length from by omega), + ← VExpr.bvarRevRange_append (idxTel U np ty).length 1] + simpa [VExpr.bvarRevRange, VExpr.appN] using (VExpr.appN_append + (.bvar ((idxTel U np ty).length + Δ.length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length) [VExpr.bvar 0]).symm, + VExpr.instRev_appN, + VExpr.instRev_bvar_ge _ (by + simp only [List.length_append, List.length_singleton] + rw [hlen] + omega), + VExpr.bvarRevRange_congr' 0 (show (idxTel U np ty).length + 1 = + (idxs ++ [a]).length from by simp [hlen]), + VExpr.map_instRev_bvarRevRange] at happ + rw [show (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 - + (idxs ++ [a]).length = Δ.length + ty.ctors.length from by + simp only [List.length_append, List.length_singleton] + rw [hlen] + omega] at happ + simpa [List.length_append, hlen] using happ + +theorem Stage3Env.recAppRec_hasType + (hrec : env.constants (.str T "rec") = some (recConstRec U T np ty)) + (Δ : List VExpr) {idxs : List VExpr} {a : VExpr} + (hidx : env.SpineWF (U+1) + (Δ ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + idxs (.sort (l.inst (VLevel.params' U 1)))) + (hlen : idxs.length = (idxTel U np ty).length) + (ha : env.HasType (U+1) + (Δ ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) a + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + ty.ctors.length + 1) np ++ idxs))) : + env.HasType (U+1) + (Δ ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange Δ.length (np + ty.ctors.length + 1))) + (idxs ++ [a])) + (VExpr.appN (.bvar (Δ.length + ty.ctors.length)) (idxs ++ [a])) := by + have hb := S.recBaseRec_hasType hrec Δ + rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ (show ty.ctors.length + 1 + Δ.length = + Δ.length + ty.ctors.length + 1 from by omega)] at hb + have hcod : + (VExpr.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0))).liftN Δ.length + (0 + (VExpr.liftTelN (ty.ctors.length + 1) (idxTel U np ty) 0).length) = + VExpr.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.app (VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) (.bvar 0)) := by + rw [VExpr.liftTelN_length, Nat.zero_add] + show VExpr.forallE _ _ = VExpr.forallE _ _ + congr 1 + · rw [VExpr.liftN_appN, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + VExpr.bvarRevRange_congr np (show Δ.length + + ((idxTel U np ty).length + ty.ctors.length + 1) = + (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 from by omega)] + rfl + · show VExpr.app _ _ = VExpr.app _ _ + congr 1 + · rw [VExpr.liftN_appN, + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] + show VExpr.appN (.bvar (liftVar Δ.length + ((idxTel U np ty).length + ty.ctors.length + 1) + ((idxTel U np ty).length + 1))) _ = _ + rw [liftVar_le (by omega), show Δ.length + + ((idxTel U np ty).length + ty.ctors.length + 1) = + (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 from by omega] + rw [hcod] at hb + have hshape := hidx.retarget (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ (C := .const T (VLevel.params' U 1)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by rw [hlen]; omega), + show (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 - idxs.length = + Δ.length + ty.ctors.length + 1 from by rw [hlen]; omega, + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hfull := hshape.snoc ha + simp only [VExpr.inst] at hfull + change env.SpineWF (U+1) _ + (VExpr.forallN + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0) + (VExpr.forallN [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)] + (.sort (.param 0)))) + (idxs ++ [a]) (.sort (.param 0)) at hfull + rw [← VExpr.forallN_append] at hfull + have hfullLen : (idxs ++ [a]).length = + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0 ++ + [VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)]).length := by + simp only [List.length_append, List.length_singleton, VExpr.liftTelN_length, hlen] + have hactual := hfull.retarget hfullLen + (VExpr.app + (VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) + (.bvar 0)) + rw [VExpr.forallN_append] at hactual + have happ := hactual.hasType_appN hb + rw [show VExpr.app + (VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length)) + (.bvar 0) = + VExpr.appN (.bvar ((idxTel U np ty).length + Δ.length + + ty.ctors.length + 1)) (VExpr.bvarRevRange 0 ((idxTel U np ty).length + 1)) from by + rw [VExpr.bvarRevRange_congr' 0 (show (idxTel U np ty).length + 1 = + 1 + (idxTel U np ty).length from by omega), + ← VExpr.bvarRevRange_append (idxTel U np ty).length 1] + simpa [VExpr.bvarRevRange, VExpr.appN] using (VExpr.appN_append + (.bvar ((idxTel U np ty).length + Δ.length + ty.ctors.length + 1)) + (VExpr.bvarRevRange 1 (idxTel U np ty).length) [VExpr.bvar 0]).symm, + VExpr.instRev_appN, + VExpr.instRev_bvar_ge _ (by + simp only [List.length_append, List.length_singleton] + rw [hlen] + omega), + VExpr.bvarRevRange_congr' 0 (show (idxTel U np ty).length + 1 = + (idxs ++ [a]).length from by simp [hlen]), + VExpr.map_instRev_bvarRevRange] at happ + rw [show (idxTel U np ty).length + Δ.length + ty.ctors.length + 1 - + (idxs ++ [a]).length = Δ.length + ty.ctors.length from by + simp only [List.length_append, List.length_singleton] + rw [hlen] + omega] at happ + simpa [List.length_append, hlen] using happ + +/-- The motive variable applied to a well-typed index spine and major +premise has the recursor's elimination sort. -/ +theorem Stage3Env.motiveApp_hasType + (Δ : List VExpr) {idxs : List VExpr} {a : VExpr} + (hidx : env.SpineWF (U+1) + (Δ ++ ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + idxs (.sort (l.inst (VLevel.params' U 1)))) + (hlen : idxs.length = (idxTel U np ty).length) + (ha : env.HasType (U+1) + (Δ ++ ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) a + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + ty.ctors.length + 1) np ++ idxs))) : + env.HasType (U+1) + (Δ ++ ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.bvar (Δ.length + ty.ctors.length)) (idxs ++ [a])) + (.sort (.param 0)) := by + have hM := getElem?_rstack3 Δ (minorTypes U T np ty ty.ctors).reverse + (motiveType U T np ty) (paramsTel U np ty).reverse + (i := Δ.length + ty.ctors.length) + (by simp only [List.length_reverse, minorTypes_length]) + have hmlu := Lookup.of_getElem? hM + rw [motiveType_liftN] at hmlu + have hshape := hidx.retarget (by simpa only [VExpr.liftTelN_length] using hlen) + (.forallE (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + ty.ctors.length + 1 + + (idxTel U np ty).length) np ++ + VExpr.bvarRevRange 0 (idxTel U np ty).length)) + (.sort (.param 0))) + rw [VExpr.instRev_forallE_sort, VExpr.instRev_appN, + VExpr.instRev_closedN _ (C := .const T (VLevel.params' U 1)) trivial, + List.map_append, + VExpr.map_instRev_bvarRevRange_ge _ _ _ (by rw [hlen]; omega), + show Δ.length + ty.ctors.length + 1 + (idxTel U np ty).length - idxs.length = + Δ.length + ty.ctors.length + 1 from by rw [hlen]; omega, + VExpr.bvarRevRange_congr' 0 hlen.symm, + VExpr.map_instRev_bvarRevRange] at hshape + rw [hlen] at hshape + have hfull := hshape.snoc ha + simp only [VExpr.inst] at hfull + exact hfull.hasType_appN (.bvar hmlu) + +theorem Stage3Env.motiveAppRec_hasType + (Δ : List VExpr) {idxs : List VExpr} {a : VExpr} + (hidx : env.SpineWF (U+1) + (Δ ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN + (VExpr.liftTelN (Δ.length + ty.ctors.length + 1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + idxs (.sort (l.inst (VLevel.params' U 1)))) + (hlen : idxs.length = (idxTel U np ty).length) + (ha : env.HasType (U+1) + (Δ ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) a + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (Δ.length + ty.ctors.length + 1) np ++ idxs))) : + env.HasType (U+1) + (Δ ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.bvar (Δ.length + ty.ctors.length)) (idxs ++ [a])) + (.sort (.param 0)) := by + have hM := getElem?_rstack3 Δ (minorTypesRec U T np ty ty.ctors).reverse + (motiveType U T np ty) (paramsTel U np ty).reverse + (i := Δ.length + ty.ctors.length) + (by simp only [List.length_reverse, minorTypesRec_length]) + exact motiveVarApp_hasType (env := env) (U := U) (T := T) (np := np) + (l := l) (ty := ty) (.bvar (Lookup.of_getElem? hM)) hidx hlen ha + +/-- The constructor-headed major of an iota rule, in the rule's binder +context (parameter spine past the motive, minors and fields). -/ +theorem Stage3Env.ctorAppRule_hasType {c : VConstVal} (hc : c ∈ ty.ctors) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + (ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length)) := by + have W := Ctx.LiftN.consTel (n := ty.ctors.length) + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0) + (Ctx.LiftN.zero (n := ty.ctors.length) + (Γ := motiveType U T np ty :: (paramsTel U np ty).reverse) + (minorTypes U T np ty ty.ctors).reverse + (h := by simp [minorTypes_length])) + have h := (S.ctorAppMin_hasType hc []).weakN S.ord W + have hlen : (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length := VExpr.liftTelN_length .. + rw [hlen] at h + simp only [List.length_nil, Nat.zero_add, VExpr.liftN_appN, VExpr.liftN, List.map_append, + List.map_map] at h + rw [VExpr.liftTelN_liftTelN, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] at h + simp only [Function.comp_def, VExpr.liftN_zero, Nat.add_zero] at h + have hmap : (ctorIdxs U np c).map (fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + ty.ctors.length (ctorFieldsR U np c).length) = + (ctorIdxs U np c).map (fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) := by + apply List.map_congr_left + intro e _ + rw [VExpr.liftN'_liftN_hi] + congr 1 + omega + rw [hmap] at h + simpa [List.append_assoc, Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using h + +theorem Stage3Env.ctorAppRuleRec_hasType {c : VConstVal} (hc : c ∈ ty.ctors) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + (ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length)) := by + have W := Ctx.LiftN.consTel (n := ty.ctors.length) + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0) + (Ctx.LiftN.zero (n := ty.ctors.length) + (Γ := motiveType U T np ty :: (paramsTel U np ty).reverse) + (minorTypesRec U T np ty ty.ctors).reverse + (h := by simp [minorTypesRec_length])) + have h := (S.ctorAppMin_hasType hc []).weakN S.ord W + have hlen : (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length := VExpr.liftTelN_length .. + rw [hlen] at h + simp only [List.length_nil, Nat.zero_add, VExpr.liftN_appN, VExpr.liftN, List.map_append, + List.map_map] at h + rw [VExpr.liftTelN_liftTelN, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega)] at h + simp only [Function.comp_def, VExpr.liftN_zero, Nat.add_zero] at h + have hmap : (ctorIdxs U np c).map (fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN + ty.ctors.length (ctorFieldsR U np c).length) = + (ctorIdxs U np c).map (fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) := by + apply List.map_congr_left + intro e _ + rw [VExpr.liftN'_liftN_hi] + congr 1 + omega + rw [hmap] at h + simpa [List.append_assoc, Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using h + +theorem Stage3Env.ruleBinders_onTel {c : VConstVal} (hc : c ∈ ty.ctors) : + OnTel env (U+1) [] + (paramsTel U np ty ++ motiveType U T np ty :: minorTypes U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) := by + have hP : OnTel env (U+1) [] (paramsTel U np ty) := by + have := S.hparams.of_append.1.instL (U' := U+1) VLevel.params'_one_wf + simpa [paramsTel] using this + have hF : OnTel env (U+1) + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) := by + have h0 := S.fieldsWF_onTel _ [] 0 rfl (by simpa using S.hfields c hc) + have h1 := h0.weakN S.ord + (.zero ((minorTypes U T np ty ty.ctors).reverse ++ [motiveType U T np ty])) + rw [liftTelN_congr _ _ (show ((minorTypes U T np ty ty.ctors).reverse ++ + [motiveType U T np ty]).length = ty.ctors.length + 1 from by + simp only [List.length_append, List.length_reverse, minorTypes_length, + List.length_singleton])] at h1 + simpa [ctorFieldsR, List.map_reverse, paramsTel, + List.append_assoc] using h1 + refine OnTel.append (OnTel.append hP ⟨?_, ?_⟩) ?_ + · simpa only [List.append_nil] using S.motive_isType + · have := S.minorTypes_onTel ty.ctors (fun _ h => h) [] 0 rfl + simpa only [List.nil_append, List.append_nil] using this + · simpa only [List.append_nil, List.append_assoc, List.reverse_append, + List.reverse_cons, List.singleton_append] using hF + +theorem Stage3Env.ruleBindersRec_onTel {c : VConstVal} (hc : c ∈ ty.ctors) : + OnTel env (U+1) [] + (paramsTel U np ty ++ motiveType U T np ty :: minorTypesRec U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) := by + have hP : OnTel env (U+1) [] (paramsTel U np ty) := by + have := S.hparams.of_append.1.instL (U' := U+1) VLevel.params'_one_wf + simpa [paramsTel] using this + have hF : OnTel env (U+1) + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) := by + have h0 := S.fieldsWF_onTel _ [] 0 rfl (by simpa using S.hfields c hc) + have h1 := h0.weakN S.ord + (.zero ((minorTypesRec U T np ty ty.ctors).reverse ++ [motiveType U T np ty])) + rw [liftTelN_congr _ _ (show ((minorTypesRec U T np ty ty.ctors).reverse ++ + [motiveType U T np ty]).length = ty.ctors.length + 1 from by + simp only [List.length_append, List.length_reverse, minorTypesRec_length, + List.length_singleton])] at h1 + simpa [ctorFieldsR, List.map_reverse, paramsTel, + List.append_assoc] using h1 + refine OnTel.append (OnTel.append hP ⟨?_, ?_⟩) ?_ + · simpa only [List.append_nil] using S.motive_isType + · have := S.minorTypesRec_onTel ty.ctors (fun _ h => h) [] 0 rfl + simpa only [List.nil_append, List.append_nil] using this + · simpa only [List.append_nil, List.append_assoc, List.reverse_append, + List.reverse_cons, List.singleton_append] using hF + +theorem Stage3Env.ruleType_isType {i : Nat} {c : VConstVal} + (hci : ty.ctors[i]? = some c) : + env.IsType (U+1) [] ((rule U T np ty i c).type) := by + have hc := List.mem_of_getElem? hci + show env.IsType (U+1) [] (VExpr.forallN + (paramsTel U np ty ++ motiveType U T np ty :: minorTypes U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)]))) + refine IsType.forallN (S.ruleBinders_onTel hc) ?_ + simp only [List.reverse_append, List.reverse_cons, List.append_nil, List.append_assoc, + List.singleton_append] + have hSp0 := S.result_transport hc + ((minorTypes U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (g := ty.ctors.length + 1) (by simp [minorTypes_length]) [] (d := 0) rfl + have hSp : env.SpineWF (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN + ((ctorFieldsR U np c).length + ty.ctors.length + 1) + (idxTel U np ty) 0) (.sort (l.inst (VLevel.params' U 1)))) + ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) + (.sort (l.inst (VLevel.params' U 1))) := by + simpa [List.append_assoc, Nat.add_assoc] using hSp0 + have hidxLen : ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length).length = + (idxTel U np ty).length := by + simp only [List.length_map, ctorIdxs_length, idxTel_length] + exact (stage3Ctor_eq (S.hs3 c hc)).2.1 + have hctor := S.ctorAppRule_hasType hc + have hSp' : env.SpineWF (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse.length + + ty.ctors.length + 1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) + (.sort (l.inst (VLevel.params' U 1))) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using hSp + have hctor' : env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse.length + + ty.ctors.length + 1) np ++ + (ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length)) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using hctor + refine ⟨.param 0, ?_⟩ + have hm := S.motiveApp_hasType + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse + hSp' hidxLen hctor' + rw [List.length_reverse, VExpr.liftTelN_length, + show (ctorFieldsR U np c).length + ty.ctors.length = + ty.ctors.length + (ctorFieldsR U np c).length from by omega, + show ty.ctors.length + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + ty.ctors.length + 1 from by omega] at hm + exact hm + +theorem Stage3Env.ruleTypeRec_isType {i : Nat} {c : VConstVal} + (hci : ty.ctors[i]? = some c) : + env.IsType (U+1) [] ((ruleRec U T np ty i c).type) := by + have hc := List.mem_of_getElem? hci + show env.IsType (U+1) [] (VExpr.forallN + (paramsTel U np ty ++ motiveType U T np ty :: minorTypesRec U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)]))) + refine IsType.forallN (S.ruleBindersRec_onTel hc) ?_ + simp only [List.reverse_append, List.reverse_cons, List.append_nil, List.append_assoc, + List.singleton_append] + have hSp0 := S.result_transport hc + ((minorTypesRec U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (g := ty.ctors.length + 1) (by simp [minorTypesRec_length]) [] (d := 0) rfl + have hSp : env.SpineWF (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN + ((ctorFieldsR U np c).length + ty.ctors.length + 1) + (idxTel U np ty) 0) (.sort (l.inst (VLevel.params' U 1)))) + ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) + (.sort (l.inst (VLevel.params' U 1))) := by + simpa [List.append_assoc, Nat.add_assoc] using hSp0 + have hidxLen : ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length).length = + (idxTel U np ty).length := by + simp only [List.length_map, ctorIdxs_length, idxTel_length] + exact (stage3Ctor_eq (S.hs3 c hc)).2.1 + have hctor := S.ctorAppRuleRec_hasType hc + have hSp' : env.SpineWF (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse.length + + ty.ctors.length + 1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) + (.sort (l.inst (VLevel.params' U 1))) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using hSp + have hctor' : env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse.length + + ty.ctors.length + 1) np ++ + (ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length)) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using hctor + refine ⟨.param 0, ?_⟩ + have hm := S.motiveAppRec_hasType + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse + hSp' hidxLen hctor' + rw [List.length_reverse, VExpr.liftTelN_length, + show (ctorFieldsR U np c).length + ty.ctors.length = + ty.ctors.length + (ctorFieldsR U np c).length from by omega, + show ty.ctors.length + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + ty.ctors.length + 1 from by omega] at hm + exact hm + +/-- A recursive field gives a well-typed recursive call in the full iota +rule context, carrying that field's own index arguments. -/ +theorem Stage3Env.recCallRule_hasType {c : VConstVal} (hc : c ∈ ty.ctors) + (hrec : env.constants (.str T "rec") = some (recConst U T np ty)) + {q : Nat × List VExpr} + (hq : q ∈ recPairsR U T np (idxTel U np ty).length c) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1))) + ((q.2.map fun e => + (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1)) ++ + [.bvar ((ctorFieldsR U np c).length - 1 - q.1)])) + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + ((q.2.map fun e => + (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1)) ++ + [.bvar ((ctorFieldsR U np c).length - 1 - q.1)])) := by + obtain ⟨B, hBj, hrecB0, hidx⟩ := recPairsR_mem hq + have hrecB : isRecField U T np + (ctorFields (VExpr.dropN np ty.type)).length q.1 B = true := by + rwa [← idxTel_length (U := U) (ty := ty)] + have hjm : q.1 < (ctorFieldsR U np c).length := by + simpa [ctorFieldsR_length] using recPairsR_lt _ hq + have hml2 : (VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).length = (ctorFieldsR U np c).length := + VExpr.liftTelN_length .. + have hSp0 := S.spine_transport hc hBj hrecB + ((minorTypes U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (g := ty.ctors.length + 1) (by simp [minorTypes_length]) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).drop q.1).reverse + (d := (ctorFieldsR U np c).length - q.1) (by + simp only [List.length_reverse, List.length_drop, hml2]) + rw [show + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).drop q.1).reverse ++ + ((VExpr.liftTelN (ty.ctors.length + 1) + ((ctorFieldsR U np c).take q.1) 0).reverse ++ + (((minorTypes U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) ++ + (paramsTel U np ty).reverse)) = + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) from by + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc + (((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).drop q.1).reverse), + ← List.reverse_append, List.take_append_drop, List.singleton_append, + ← List.append_assoc], + liftTelN_congr _ _ (show q.1 + (ty.ctors.length + 1) + + ((ctorFieldsR U np c).length - q.1) = + (ctorFieldsR U np c).length + ty.ctors.length + 1 from by omega), + ← hidx] at hSp0 + have hni : q.2.length = (idxTel U np ty).length := by + rw [hidx, List.length_map, idxTel_length] + exact (isRecField_eq hrecB).2.1 + have hSp : env.SpineWF (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse.length + ty.ctors.length + 1) + (idxTel U np ty) 0) (.sort (l.inst (VLevel.params' U 1)))) + (q.2.map fun e => (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1)) + (.sort (l.inst (VLevel.params' U 1))) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using hSp0 + have hSpLen : (q.2.map fun e => + (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1)).length = + (idxTel U np ty).length := by simpa using hni + have hF : ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)))[ + (ctorFieldsR U np c).length - 1 - q.1]? = + some ((B.instL (VLevel.params' U 1)).liftN + (ty.ctors.length + 1) q.1) := by + rw [List.getElem?_append_left + (by simp only [List.length_reverse, VExpr.liftTelN_length]; omega), + List.getElem?_reverse (by simp only [VExpr.liftTelN_length]; omega), + VExpr.liftTelN_length, + show (ctorFieldsR U np c).length - 1 - + ((ctorFieldsR U np c).length - 1 - q.1) = q.1 from by omega, + VExpr.liftTelN_getElem?, ctorFieldsR_getElem?, hBj] + simp only [Option.map_some, Nat.zero_add] + have hflu := Lookup.of_getElem? hF + rw [show (((B.instL (VLevel.params' U 1)).liftN + (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - 1 - q.1 + 1)) = + VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + q.2.map fun e => (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1)) from by + conv => lhs; rw [(isRecField_eq hrecB).1] + rw [VExpr.instL_appN, List.map_append, bvarRevRange_instL, + show (VExpr.const T (VLevel.params U)).instL (VLevel.params' U 1) = + .const T (VLevel.params' U 1) from by + simp [VExpr.instL, VLevel.params_map_inst_params'], + VExpr.liftN_appN, VExpr.liftN_appN, List.map_append, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.bvarRevRange_congr np (show + (ctorFieldsR U np c).length - 1 - q.1 + 1 + + (ty.ctors.length + 1 + q.1) = + (ctorFieldsR U np c).length + ty.ctors.length + 1 from by omega), + ← hidx, List.map_map] + apply congrArg (VExpr.appN (.const T (VLevel.params' U 1))) + apply congrArg (VExpr.bvarRevRange + ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ ·) + apply List.map_congr_left + intro e _ + rw [show (ctorFieldsR U np c).length - 1 - q.1 + 1 = + (ctorFieldsR U np c).length - q.1 from by omega] + simp only [Function.comp_apply] + ] at hflu + have ha : env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (.bvar ((ctorFieldsR U np c).length - 1 - q.1)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse.length + ty.ctors.length + 1) np ++ + q.2.map fun e => (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1))) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using + (VEnv.HasType.bvar (env := env) (U := U+1) hflu) + have hr := S.recApp_hasType hrec + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse + hSp hSpLen ha + rw [List.length_reverse, VExpr.liftTelN_length, + show (ctorFieldsR U np c).length + ty.ctors.length = + ty.ctors.length + (ctorFieldsR U np c).length from by omega] at hr + exact hr + +/-- A generalized recursive argument yields the direct or lambda-valued +recursive call required by its functional IH in the complete rule context. -/ +theorem Stage3Env.ruleCallRec_hasType {c : VConstVal} (hc : c ∈ ty.ctors) + (hrec : env.constants (.str T "rec") = some (recConstRec U T np ty)) + {r : RecArg} (hr : r ∈ recArgsR U T np (idxTel U np ty).length c) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (r.ruleCall (ctorFieldsR U np c).length ty.ctors.length + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1)))) + (r.ruleIH (ctorFieldsR U np c).length ty.ctors.length) := by + obtain ⟨r₀, B, rfl, hB, hr₀⟩ := recArgsR_mem hr + let r := r₀.instL (VLevel.params' U 1) + let m := (ctorFieldsR U np c).length + let k := ty.ctors.length + let j := r₀.fieldIndex + let Fs := VExpr.liftTelN (k+1) (ctorFieldsR U np c) 0 + let As := r.ruleBinders m k + let idxs := r.indices.map fun e => + (e.liftN (k+1) (r.fieldIndex+r.binders.length)).liftN + (m-r.fieldIndex) r.binders.length + let Γ := Fs.reverse ++ ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + have hjm : j < m := by + simpa [j, m, RecArg.instL, ctorFieldsR_length] using recArgsR_lt _ hr + have hFsLen : Fs.length = m := by + simp [Fs, m, VExpr.liftTelN_length] + have ht := S.recArg_transport hc hB hr₀ + ((minorTypesRec U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (g := k+1) (by simp [k, minorTypesRec_length]) + (Fs.drop j).reverse (d := m-j) (by + simp only [List.length_reverse, List.length_drop, hFsLen]) + dsimp only [r, j, RecArg.instL] at ht + have hctx : + (Fs.drop j).reverse ++ + ((VExpr.liftTelN (k+1) ((ctorFieldsR U np c).take j) 0).reverse ++ + (((minorTypesRec U T np ty ty.ctors).reverse ++ + [motiveType U T np ty]) ++ (paramsTel U np ty).reverse)) = Γ := by + dsimp only [Γ, Fs] + rw [← VExpr.liftTelN_take, List.append_assoc, + ← List.append_assoc + (((VExpr.liftTelN (k+1) (ctorFieldsR U np c) 0).drop j).reverse), + ← List.reverse_append, List.take_append_drop, List.singleton_append, + ← List.append_assoc] + have htel : OnTel env (U+1) Γ As := by + rw [hctx] at ht + simpa [r, As, m, k, j, RecArg.instL, RecArg.ruleBinders] using ht.1 + have hsp : env.SpineWF (U+1) (As.reverse ++ Γ) + (VExpr.forallN + (VExpr.liftTelN (m+k+r.binders.length+1) (idxTel U np ty) 0) + (.sort (l.inst (VLevel.params' U 1)))) + idxs (.sort (l.inst (VLevel.params' U 1))) := by + rw [hctx] at ht + simpa [r, As, idxs, m, k, j, RecArg.instL, RecArg.ruleBinders, + List.append_assoc, + show j + r₀.binders.length + (k+1) + (m-j) = + m+k+r₀.binders.length+1 from by omega] using ht.2 + have hF : Γ[m-1-j]? = + some ((B.instL (VLevel.params' U 1)).liftN (k+1) j) := by + dsimp only [Γ, Fs] + rw [List.getElem?_append_left + (by simp only [List.length_reverse, VExpr.liftTelN_length]; omega), + List.getElem?_reverse (by rw [hFsLen]; omega), + VExpr.liftTelN_length, + show m - 1 - (m - 1 - j) = j from by omega, + VExpr.liftTelN_getElem?, ctorFieldsR_getElem?, hB] + simp + have hlu := Lookup.of_getElem? hF + dsimp only [j, r] at hlu + rw [show m-1-r₀.fieldIndex+1 = m-r₀.fieldIndex from by omega] + at hlu + have hfield := recArg_rule_fieldType hr₀ m k (by simpa [j] using hjm) + simp only [RecArg.instL, ElimMode.large_sourceLevels] at hfield + rw [hfield] at hlu + have hf0 := VEnv.HasType.bvar (env := env) (U := U+1) hlu + have hf := hf0.weakN S.ord (Ctx.LiftN.zero (Γ := Γ) As.reverse) + have hmajor := VEnv.HasType.appN_selfSpine (env := env) (U := U+1) + (As := As) (B := VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (m+k+r.binders.length+1) np ++ idxs)) + (Δ := []) (Γ := Γ) (by + simpa [As, r, idxs, j, RecArg.instL, RecArg.ruleBinders, + List.length_reverse, List.map_map, Function.comp_def] using hf) + simp only [List.length_nil, VExpr.liftN_zero, List.nil_append] at hmajor + have hAsLen : As.length = r.binders.length := by + simp [As, RecArg.ruleBinders, VExpr.liftTelN_length] + change env.HasType (U+1) (As.reverse ++ Γ) + ((VExpr.bvar (m-1-r.fieldIndex+As.length)).appN + (VExpr.bvarRevRange 0 As.length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange (m+k+r.binders.length+1) np ++ idxs)) at hmajor + rw [hAsLen] at hmajor + have hlen : idxs.length = (idxTel U np ty).length := by + simpa [idxs, r, RecArg.instL] using (recArg?_eq hr₀).2.2.2.1 + have hcall := S.recAppRec_hasType hrec (As.reverse ++ Fs.reverse) + (by simpa [Γ, List.append_assoc, hAsLen, hFsLen, Nat.add_comm, + Nat.add_left_comm, Nat.add_assoc] using hsp) + hlen + (by simpa [Γ, List.append_assoc, hAsLen, hFsLen, Nat.add_comm, + Nat.add_left_comm, Nat.add_assoc] using hmajor) + have hbaseLift : + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange m (np+(k+1)))).liftN r.binders.length = + VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (m+r.binders.length) (np+(k+1))) := by + rw [VExpr.liftN_appN] + simp only [VExpr.liftN] + rw [bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _)] + apply congrArg (VExpr.appN _) + apply VExpr.bvarRevRange_congr + omega + have hbaseRange : + VExpr.appN + ((VExpr.const (.str T "rec") (VLevel.params (U+1))).app + (VExpr.bvar (np + (k + (m + r.binders.length))))) + (VExpr.bvarRevRange (m+r.binders.length) (np+k)) = + VExpr.appN + (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (m+r.binders.length) (np+(k+1))) := by + rw [show np + (k + (m + r.binders.length)) = + (m+r.binders.length) + (np+k) by omega, + show np+(k+1) = (np+k)+1 by omega] + rfl + have hlam := HasType.lamN htel (by + simpa [Γ, Fs, hAsLen, hFsLen, List.append_assoc, + VExpr.liftN_appN, bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using hcall) + rw [hbaseRange] at hlam + simpa only [RecArg.ruleCall, RecArg.ruleIH, r, As, idxs, m, k, Γ, Fs, + hbaseLift, List.append_assoc, Nat.add_assoc] using hlam + + +/-- The right-hand side of an indexed iota rule: the constructor's minor +premise applied to its fields and to one indexed recursive call per recursive +field. -/ +theorem Stage3Env.minorApp_hasType {i : Nat} {c : VConstVal} + (hci : ty.ctors[i]? = some c) + (hrec : env.constants (.str T "rec") = some (recConst U T np ty)) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.bvar (ty.ctors.length - 1 - i + (ctorFieldsR U np c).length)) + (VExpr.bvarRevRange 0 (ctorFieldsR U np c).length ++ + List.map (fun q => VExpr.appN + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1))) + ((q.2.map fun e => + (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1)) ++ + [.bvar ((ctorFieldsR U np c).length - 1 - q.1)])) + (recPairsR U T np (idxTel U np ty).length c))) + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])) := by + obtain ⟨hik, -⟩ := List.getElem?_eq_some_iff.1 hci + have hc := List.mem_of_getElem? hci + let rs := recPairsR U T np (idxTel U np ty).length c + have hrs : rs = recPairsR U T np (idxTel U np ty).length c := rfl + have hrsLt : ∀ q ∈ rs, q.1 < (ctorFieldsR U np c).length := by + intro q hq + simpa [hrs, ctorFieldsR_length] using recPairsR_lt _ hq + rw [VExpr.appN_append] + have hlu0 : ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)))[ + ty.ctors.length - 1 - i + (ctorFieldsR U np c).length]? = + some (VExpr.liftN i (minorType U T np ty c)) := by + rw [getElem?_rstack_mid _ _ _ + (by simp only [List.length_reverse, VExpr.liftTelN_length]; omega) + (by simp only [List.length_reverse, VExpr.liftTelN_length, minorTypes_length] + omega), + show ty.ctors.length - 1 - i + (ctorFieldsR U np c).length - + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse).length = + ty.ctors.length - 1 - i from by + simp only [List.length_reverse, VExpr.liftTelN_length] + omega, + List.getElem?_reverse (by simp only [minorTypes_length]; omega), + show (minorTypes U T np ty ty.ctors).length - 1 - + (ty.ctors.length - 1 - i) = i from by + simp only [minorTypes_length] + omega, + minorTypes_getElem?, hci, Nat.zero_add] + rfl + have hlu := Lookup.of_getElem? hlu0 + rw [VExpr.liftN_liftN, + show i + (ty.ctors.length - 1 - i + (ctorFieldsR U np c).length + 1) = + (ctorFieldsR U np c).length + ty.ctors.length from by omega] at hlu + have hminorEq : (minorType U T np ty c).liftN + ((ctorFieldsR U np c).length + ty.ctors.length) = + (VExpr.forallN + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) + ((VExpr.forallN (ihsFrom (ctorFieldsR U np c).length rs 0) + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)]))).liftN + ty.ctors.length (ctorFieldsR U np c).length)).liftN + (ctorFieldsR U np c).length := by + simp only [minorType, rs, ElimMode.large_sourceLevels] + conv => lhs; rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ (show (1:Nat) + + ((ctorFieldsR U np c).length + ty.ctors.length) = + ty.ctors.length + 1 + (ctorFieldsR U np c).length from by omega), + show (0:Nat) + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length from by simp [VExpr.liftTelN_length]] + conv => rhs; rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + show (0:Nat) + (VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).length = (ctorFieldsR U np c).length from by + simp [VExpr.liftTelN_length], + VExpr.liftN'_liftN_hi, + Nat.add_comm ty.ctors.length (ctorFieldsR U np c).length] + have hfields := HasType.appN_selfSpine (env := env) (U := U+1) + (As := VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) + (B := (VExpr.forallN (ihsFrom (ctorFieldsR U np c).length rs 0) + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)]))).liftN + ty.ctors.length (ctorFieldsR U np c).length) + (Δ := []) + (Γ := (minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (f := .bvar (ty.ctors.length - 1 - i + (ctorFieldsR U np c).length)) (by + have hb := VEnv.HasType.bvar (env := env) (U := U+1) hlu + rw [hminorEq] at hb + simpa [VExpr.liftTelN_length] using hb) + simp only [List.length_nil, VExpr.liftTelN_length, VExpr.liftN_zero] at hfields + rw [ihsFrom_liftN' (ctorFieldsR U np c).length ty.ctors.length rs + hrsLt 0 + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)])) + (cut := (ctorFieldsR U np c).length) rfl] at hfields + have hD : + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)])).liftN + ty.ctors.length ((ctorFieldsR U np c).length + 0 + rs.length) = + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])).liftN rs.length := by + rw [VExpr.liftN_appN, VExpr.liftN_appN, List.map_append, List.map_append, + List.map_map, List.map_map] + show VExpr.appN _ (_ ++ [_]) = VExpr.appN _ (_ ++ [_]) + congr 1 + · show VExpr.bvar (liftVar ty.ctors.length + ((ctorFieldsR U np c).length + rs.length) + ((ctorFieldsR U np c).length + 0 + rs.length)) = + VExpr.bvar (liftVar rs.length + (ty.ctors.length + (ctorFieldsR U np c).length) 0) + rw [liftVar_le (by omega), liftVar_le (Nat.zero_le _)] + congr 1 + omega + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + rw [show (ctorFieldsR U np c).length + 0 + rs.length = + (ctorFieldsR U np c).length + rs.length from by omega, + VExpr.liftN_liftN_mid e ty.ctors.length rs.length (Nat.zero_le _)] + · congr 1 + simp only [] + rw [show (ctorFieldsR U np c).length + 0 + rs.length = + (ctorFieldsR U np c).length + rs.length from by omega] + rw [VExpr.liftN_appN, VExpr.liftN_appN, List.map_append, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.bvarRevRange_congr np (show ty.ctors.length + + (rs.length + (ctorFieldsR U np c).length + 1) = + rs.length + ((ctorFieldsR U np c).length + ty.ctors.length + 1) from by + omega), + VExpr.bvarRevRange_congr _ (show rs.length = rs.length + 0 from by omega)] + rfl + rw [hD] at hfields + have hres := hasType_appN_ihs (env := env) (U := U+1) + (m := (ctorFieldsR U np c).length) (k := ty.ctors.length) + (rs := rs) + (argOf := fun (j, idxs) => + VExpr.appN + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1))) + ((idxs.map fun e => (e.liftN (ty.ctors.length + 1) j).liftN + ((ctorFieldsR U np c).length - j)) ++ + [.bvar ((ctorFieldsR U np c).length - 1 - j)])) + hrsLt (fun q hq => by + have hr := S.recCallRule_hasType hc hrec (hrs ▸ hq) + have hargs : (q.2.map fun e => + ((e.liftN 1 q.1).liftN ((ctorFieldsR U np c).length - q.1)).liftN + ty.ctors.length (ctorFieldsR U np c).length) = + q.2.map fun e => (e.liftN (ty.ctors.length + 1) q.1).liftN + ((ctorFieldsR U np c).length - q.1) := by + apply List.map_congr_left + intro e _ + rw [← VExpr.liftN_liftN_mid e ty.ctors.length + ((ctorFieldsR U np c).length - q.1) (Nat.zero_le _), + show q.1 + ((ctorFieldsR U np c).length - q.1) = + (ctorFieldsR U np c).length from by + have := hrsLt q hq + omega] + rw [hargs] + exact hr) + hfields + simpa only [hrs, List.nil_append] using hres + +/-- Generalized iota RHS: apply the selected constructor minor to every field +and then to the direct or functional recursive call generated for each +`RecArg`. -/ +theorem Stage3Env.minorAppRec_hasType {i : Nat} {c : VConstVal} + (hci : ty.ctors[i]? = some c) + (hrec : env.constants (.str T "rec") = some (recConstRec U T np ty)) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.bvar (ty.ctors.length - 1 - i + (ctorFieldsR U np c).length)) + (VExpr.bvarRevRange 0 (ctorFieldsR U np c).length ++ + List.map (fun r => r.ruleCall (ctorFieldsR U np c).length ty.ctors.length + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1)))) + (recArgsR U T np (idxTel U np ty).length c))) + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])) := by + obtain ⟨hik, -⟩ := List.getElem?_eq_some_iff.1 hci + have hc := List.mem_of_getElem? hci + let rs := recArgsR U T np (idxTel U np ty).length c + have hrs : rs = recArgsR U T np (idxTel U np ty).length c := rfl + have hrsLt : ∀ r ∈ rs, r.fieldIndex < (ctorFieldsR U np c).length := by + intro r hr + simpa [hrs, ctorFieldsR_length] using recArgsR_lt _ hr + rw [VExpr.appN_append] + have hlu0 : ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)))[ + ty.ctors.length - 1 - i + (ctorFieldsR U np c).length]? = + some (VExpr.liftN i (minorTypeRec U T np ty c)) := by + rw [getElem?_rstack_mid _ _ _ + (by simp only [List.length_reverse, VExpr.liftTelN_length]; omega) + (by simp only [List.length_reverse, VExpr.liftTelN_length, + minorTypesRec_length]; omega), + show ty.ctors.length - 1 - i + (ctorFieldsR U np c).length - + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse).length = + ty.ctors.length - 1 - i from by + simp only [List.length_reverse, VExpr.liftTelN_length] + omega, + List.getElem?_reverse (by simp only [minorTypesRec_length]; omega), + show (minorTypesRec U T np ty ty.ctors).length - 1 - + (ty.ctors.length - 1 - i) = i from by + simp only [minorTypesRec_length] + omega, + minorTypesRec_getElem?, hci, Nat.zero_add] + rfl + have hlu := Lookup.of_getElem? hlu0 + rw [VExpr.liftN_liftN, + show i + (ty.ctors.length - 1 - i + (ctorFieldsR U np c).length + 1) = + (ctorFieldsR U np c).length + ty.ctors.length from by omega] at hlu + have hminorEq : (minorTypeRec U T np ty c).liftN + ((ctorFieldsR U np c).length + ty.ctors.length) = + (VExpr.forallN + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) + ((VExpr.forallN (ihsFromRecArgs (ctorFieldsR U np c).length rs 0) + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)]))).liftN + ty.ctors.length (ctorFieldsR U np c).length)).liftN + (ctorFieldsR U np c).length := by + simp only [minorTypeRec, rs, ElimMode.large_sourceLevels] + conv => lhs; rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + liftTelN_congr _ _ (show (1:Nat) + + ((ctorFieldsR U np c).length + ty.ctors.length) = + ty.ctors.length + 1 + (ctorFieldsR U np c).length from by omega), + show (0:Nat) + (VExpr.liftTelN 1 (ctorFieldsR U np c) 0).length = + (ctorFieldsR U np c).length from by simp [VExpr.liftTelN_length]] + conv => rhs; rw [VExpr.liftN_forallN, VExpr.liftTelN_liftTelN, + show (0:Nat) + (VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).length = (ctorFieldsR U np c).length from by + simp [VExpr.liftTelN_length], + VExpr.liftN'_liftN_hi, + Nat.add_comm ty.ctors.length (ctorFieldsR U np c).length] + have hfields := HasType.appN_selfSpine (env := env) (U := U+1) + (As := VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) + (B := (VExpr.forallN (ihsFromRecArgs (ctorFieldsR U np c).length rs 0) + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)]))).liftN + ty.ctors.length (ctorFieldsR U np c).length) + (Δ := []) + (Γ := (minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse)) + (f := .bvar (ty.ctors.length - 1 - i + (ctorFieldsR U np c).length)) (by + have hb := VEnv.HasType.bvar (env := env) (U := U+1) hlu + rw [hminorEq] at hb + simpa [VExpr.liftTelN_length] using hb) + simp only [List.length_nil, VExpr.liftTelN_length, VExpr.liftN_zero] at hfields + rw [ihsFromRecArgs_liftN' (ctorFieldsR U np c).length ty.ctors.length rs + hrsLt 0 + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)])) + (cut := (ctorFieldsR U np c).length) rfl] at hfields + have hD : + (VExpr.appN (.bvar ((ctorFieldsR U np c).length + rs.length)) + (((ctorIdxs U np c).map fun e => + (e.liftN 1 (ctorFieldsR U np c).length).liftN rs.length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange (rs.length + (ctorFieldsR U np c).length + 1) np ++ + VExpr.bvarRevRange rs.length (ctorFieldsR U np c).length)])).liftN + ty.ctors.length ((ctorFieldsR U np c).length + 0 + rs.length) = + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])).liftN rs.length := by + rw [VExpr.liftN_appN, VExpr.liftN_appN, List.map_append, List.map_append, + List.map_map, List.map_map] + show VExpr.appN _ (_ ++ [_]) = VExpr.appN _ (_ ++ [_]) + congr 1 + · show VExpr.bvar (liftVar ty.ctors.length + ((ctorFieldsR U np c).length + rs.length) + ((ctorFieldsR U np c).length + 0 + rs.length)) = + VExpr.bvar (liftVar rs.length + (ty.ctors.length + (ctorFieldsR U np c).length) 0) + rw [liftVar_le (by omega), liftVar_le (Nat.zero_le _)] + congr 1 + omega + · congr 1 + · apply List.map_congr_left + intro e _ + simp only [Function.comp_apply] + rw [show (ctorFieldsR U np c).length + 0 + rs.length = + (ctorFieldsR U np c).length + rs.length from by omega, + VExpr.liftN_liftN_mid e ty.ctors.length rs.length (Nat.zero_le _)] + · congr 1 + simp only [] + rw [show (ctorFieldsR U np c).length + 0 + rs.length = + (ctorFieldsR U np c).length + rs.length from by omega] + rw [VExpr.liftN_appN, VExpr.liftN_appN, List.map_append, List.map_append, + bvarRevRange_liftN_ge _ _ _ _ (by omega), + VExpr.bvarRevRange_liftN_high _ _ _ _ (by omega), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + bvarRevRange_liftN_ge _ _ _ _ (Nat.zero_le _), + VExpr.bvarRevRange_congr np (show ty.ctors.length + + (rs.length + (ctorFieldsR U np c).length + 1) = + rs.length + ((ctorFieldsR U np c).length + ty.ctors.length + 1) from by + omega), + VExpr.bvarRevRange_congr _ (show rs.length = rs.length + 0 from by omega)] + rfl + rw [hD] at hfields + have hres := hasType_appN_ruleIHs (env := env) (U := U+1) + (m := (ctorFieldsR U np c).length) (k := ty.ctors.length) + (rs := rs) + (argOf := fun r => r.ruleCall (ctorFieldsR U np c).length ty.ctors.length + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1)))) + (fun r hr => S.ruleCallRec_hasType hc hrec (hrs ▸ hr)) hfields + simpa only [hrs] using hres + +/-- The constructor-headed left side of an indexed iota rule. -/ +theorem Stage3Env.recRuleApp_hasType {c : VConstVal} (hc : c ∈ ty.ctors) + (hrec : env.constants (.str T "rec") = some (recConst U T np ty)) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1))) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])) + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])) := by + have hSp0 := S.result_transport hc + ((minorTypes U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (g := ty.ctors.length + 1) (by simp [minorTypes_length]) [] (d := 0) rfl + have hSp : env.SpineWF (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse.length + ty.ctors.length + 1) + (idxTel U np ty) 0) (.sort (l.inst (VLevel.params' U 1)))) + ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) + (.sort (l.inst (VLevel.params' U 1))) := by + simpa [List.append_assoc, Nat.add_assoc, List.length_reverse, + VExpr.liftTelN_length] using hSp0 + have hidxLen : ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length).length = + (idxTel U np ty).length := by + simp only [List.length_map, ctorIdxs_length, idxTel_length] + exact (stage3Ctor_eq (S.hs3 c hc)).2.1 + have ha0 := S.ctorAppRule_hasType hc + have ha : env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypes U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse.length + ty.ctors.length + 1) np ++ + (ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length)) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using ha0 + have hr := S.recApp_hasType hrec + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse + hSp hidxLen ha + rw [List.length_reverse, VExpr.liftTelN_length, + show (ctorFieldsR U np c).length + ty.ctors.length = + ty.ctors.length + (ctorFieldsR U np c).length from by omega, + show ty.ctors.length + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + ty.ctors.length + 1 from by omega] at hr + exact hr + +/-- The constructor-headed left side of a generalized indexed iota rule. -/ +theorem Stage3Env.recRuleAppRec_hasType {c : VConstVal} (hc : c ∈ ty.ctors) + (hrec : env.constants (.str T "rec") = some (recConstRec U T np ty)) : + env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN + (VExpr.appN (.const (.str T "rec") (VLevel.params (U+1))) + (VExpr.bvarRevRange (ctorFieldsR U np c).length + (np + ty.ctors.length + 1))) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])) + (VExpr.appN (.bvar (ty.ctors.length + (ctorFieldsR U np c).length)) + (((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) ++ + [VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)])) := by + have hSp0 := S.result_transport hc + ((minorTypesRec U T np ty ty.ctors).reverse ++ [motiveType U T np ty]) + (g := ty.ctors.length + 1) (by simp [minorTypesRec_length]) [] (d := 0) rfl + have hSp : env.SpineWF (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.forallN (VExpr.liftTelN + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse.length + ty.ctors.length + 1) + (idxTel U np ty) 0) (.sort (l.inst (VLevel.params' U 1)))) + ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length) + (.sort (l.inst (VLevel.params' U 1))) := by + simpa [List.append_assoc, Nat.add_assoc, List.length_reverse, + VExpr.liftTelN_length] using hSp0 + have hidxLen : ((ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length).length = + (idxTel U np ty).length := by + simp only [List.length_map, ctorIdxs_length, idxTel_length] + exact (stage3Ctor_eq (S.hs3 c hc)).2.1 + have ha0 := S.ctorAppRuleRec_hasType hc + have ha : env.HasType (U+1) + ((VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse ++ + ((minorTypesRec U T np ty ty.ctors).reverse ++ + (motiveType U T np ty :: (paramsTel U np ty).reverse))) + (VExpr.appN (.const c.name (VLevel.params' U 1)) + (VExpr.bvarRevRange ((ctorFieldsR U np c).length + ty.ctors.length + 1) np ++ + VExpr.bvarRevRange 0 (ctorFieldsR U np c).length)) + (VExpr.appN (.const T (VLevel.params' U 1)) + (VExpr.bvarRevRange + ((VExpr.liftTelN (ty.ctors.length + 1) + (ctorFieldsR U np c) 0).reverse.length + ty.ctors.length + 1) np ++ + (ctorIdxs U np c).map fun e => + e.liftN (ty.ctors.length + 1) (ctorFieldsR U np c).length)) := by + simpa only [List.length_reverse, VExpr.liftTelN_length] using ha0 + have hr := S.recAppRec_hasType hrec + (VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0).reverse + hSp hidxLen ha + rw [List.length_reverse, VExpr.liftTelN_length, + show (ctorFieldsR U np c).length + ty.ctors.length = + ty.ctors.length + (ctorFieldsR U np c).length from by omega, + show ty.ctors.length + (ctorFieldsR U np c).length + 1 = + (ctorFieldsR U np c).length + ty.ctors.length + 1 from by omega] at hr + exact hr + +/-- Well-formedness of the iota rule for the `i`-th constructor. -/ +theorem Stage3Env.rule_WF {i : Nat} {c : VConstVal} + (hci : ty.ctors[i]? = some c) + (hrec : env.constants (.str T "rec") = some (recConst U T np ty)) : + (rule U T np ty i c).WF env := by + have hc := List.mem_of_getElem? hci + refine ⟨?_, ?_⟩ + · show env.HasType (U+1) [] (VExpr.lamN + (paramsTel U np ty ++ motiveType U T np ty :: minorTypes U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) _) + (VExpr.forallN _ _) + refine HasType.lamN (S.ruleBinders_onTel hc) ?_ + simp only [List.reverse_append, List.reverse_cons, List.append_nil, + List.append_assoc, List.singleton_append] + exact S.recRuleApp_hasType hc hrec + · show env.HasType (U+1) [] (VExpr.lamN + (paramsTel U np ty ++ motiveType U T np ty :: minorTypes U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) _) + (VExpr.forallN _ _) + refine HasType.lamN (S.ruleBinders_onTel hc) ?_ + simp only [List.reverse_append, List.reverse_cons, List.append_nil, + List.append_assoc, List.singleton_append] + exact S.minorApp_hasType hci hrec + +/-- Well-formedness of the generalized iota rule for the `i`-th constructor. -/ +theorem Stage3Env.ruleRec_WF {i : Nat} {c : VConstVal} + (hci : ty.ctors[i]? = some c) + (hrec : env.constants (.str T "rec") = some (recConstRec U T np ty)) : + (ruleRec U T np ty i c).WF env := by + have hc := List.mem_of_getElem? hci + refine ⟨?_, ?_⟩ + · show env.HasType (U+1) [] (VExpr.lamN + (paramsTel U np ty ++ motiveType U T np ty :: minorTypesRec U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) _) + (VExpr.forallN _ _) + refine HasType.lamN (S.ruleBindersRec_onTel hc) ?_ + simp only [List.reverse_append, List.reverse_cons, List.append_nil, + List.append_assoc, List.singleton_append] + exact S.recRuleAppRec_hasType hc hrec + · show env.HasType (U+1) [] (VExpr.lamN + (paramsTel U np ty ++ motiveType U T np ty :: minorTypesRec U T np ty ty.ctors ++ + VExpr.liftTelN (ty.ctors.length + 1) (ctorFieldsR U np c) 0) _) + (VExpr.forallN _ _) + refine HasType.lamN (S.ruleBindersRec_onTel hc) ?_ + simp only [List.reverse_append, List.reverse_cons, List.append_nil, + List.append_assoc, List.singleton_append] + exact S.minorAppRec_hasType hci hrec + +/-- `ctorType_eq` from the per-constructor facts directly (for use before +the constructor is in the environment). -/ +theorem Stage3Env.ctorType_eq' {c : VConstVal} + (htelc : VExpr.telN np c.type = VExpr.telN np ty.type) + (hs3c : stage3Ctor U T np + (ctorFields (VExpr.dropN np ty.type)).length 0 (VExpr.dropN np c.type)) : + c.type = VExpr.forallN (VExpr.telN np ty.type) + (VExpr.forallN (ctorFields (VExpr.dropN np c.type)) + (VExpr.appN (.const T (VLevel.params U)) + (VExpr.bvarRevRange (0 + (ctorFields (VExpr.dropN np c.type)).length) np ++ + recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type))))) := by + conv => lhs; rw [← VExpr.forallN_telN_dropN np c.type, htelc, + (stage3Ctor_eq hs3c).1] + +/-- `ctorType_isType` from the per-constructor facts directly. -/ +theorem Stage3Env.ctorType_isType' {c : VConstVal} + (htelc : VExpr.telN np c.type = VExpr.telN np ty.type) + (hs3c : stage3Ctor U T np + (ctorFields (VExpr.dropN np ty.type)).length 0 (VExpr.dropN np c.type)) + (hfc : fieldsWF U T np env l (ctorFields (VExpr.dropN np ty.type)) + (VExpr.telN np ty.type).reverse 0 (ctorFields (VExpr.dropN np c.type))) + (hresultc : env.SpineWF U + ((ctorFields (VExpr.dropN np c.type)).reverse ++ + (VExpr.telN np ty.type).reverse) + (VExpr.forallN (VExpr.liftTelN + (ctorFields (VExpr.dropN np c.type)).length + (ctorFields (VExpr.dropN np ty.type)) 0) (.sort l)) + (recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type))) (.sort l)) : + env.IsType U [] c.type := by + rw [S.ctorType_eq' htelc hs3c] + refine IsType.forallN S.hparams.of_append.1 ?_ + simp only [List.append_nil] + refine IsType.forallN + (S.fieldsWF_onTel_decl _ [] 0 rfl (by simpa using hfc)) ?_ + have hTapp := S.recAppPi_hasType_decl + ((ctorFields (VExpr.dropN np c.type)).reverse) + rw [List.length_reverse, VExpr.liftN_forallN] at hTapp + have hres := hresultc.hasType_appN hTapp + exact ⟨_, by + rw [VExpr.appN_append, Nat.zero_add] + exact hres⟩ + +omit S in +/-- In the identity path, each paired constructor receives the granular +raw/view certificate required immediately after the family insertion. -/ +theorem Checked.WF.identityCtorWF + {source : VInductDecl} {checked : source.Checked} + {pre envT : VEnv} (hpre : pre.Ordered) + (h : checked.WF pre) + (hadd : pre.addConst checked.type.name + checked.type.toVConstant = some envT) + {ctor : NormalizedCtor} + (hctor : ctor ∈ + checked.identityGeneration.block.ctorPairs) : + ctor.WF checked.identityGeneration.block envT := by + obtain ⟨c, hc, rfl⟩ := + checked.identityGeneration_ctor hctor + let S := h.toDirectFamilyEnv hpre hadd + have hcAn := checked.direct_anatomy.2.2.2.2.2 c hc + have hfields : fieldsWF source.uvars checked.type.name + source.nparams envT checked.resultLevel + (ctorFields (VExpr.dropN source.nparams checked.type.type)) + (VExpr.telN source.nparams checked.type.type).reverse 0 + (ctorFields (VExpr.dropN source.nparams c.type)) := by + simpa [checked.params_eq, checked.indices_eq] using + fieldsWF_mono (addConst_le hadd) (h.2 c hc).1 + have hfieldTel : OnTel envT source.uvars + (VExpr.telN source.nparams checked.type.type).reverse + (ctorFields (VExpr.dropN source.nparams c.type)) := + S.fieldsWF_onTel_decl _ [] 0 rfl hfields + have hbinders : OnTel envT source.uvars [] + (VExpr.telN source.nparams checked.type.type ++ + ctorFields (VExpr.dropN source.nparams c.type)) := + S.hparams.of_append.1.append (by simpa using hfieldTel) + have htelRefl := hbinders.telDefEq_refl + have hresultSpine : envT.SpineWF source.uvars + ((ctorFields + (VExpr.dropN source.nparams c.type)).reverse ++ + (VExpr.telN source.nparams checked.type.type).reverse) + (VExpr.forallN + (VExpr.liftTelN + (ctorFields + (VExpr.dropN source.nparams c.type)).length + (ctorFields + (VExpr.dropN source.nparams checked.type.type)) 0) + (.sort checked.resultLevel)) + (recFieldIdxs source.nparams + (VExpr.resultOf + (VExpr.dropN source.nparams c.type))) + (.sort checked.resultLevel) := by + simpa [checked.params_eq, checked.indices_eq] using + (h.2 c hc).2.mono (addConst_le hadd) + have hresultTyped := + S.ctorResult_hasType_decl hresultSpine + have hrawResult : + VExpr.resultOf (VExpr.dropN source.nparams c.type) = + VExpr.appN + (.const checked.type.name + (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (ctorFields + (VExpr.dropN source.nparams c.type)).length + source.nparams ++ + recFieldIdxs source.nparams + (VExpr.resultOf + (VExpr.dropN source.nparams c.type))) := by + have hout := congrArg VExpr.resultOf + (stage3Ctor_eq hcAn.2.2).1 + rw [VExpr.resultOf_forallN, + VExpr.resultOf_appN_const] at hout + simpa only [Nat.zero_add] using hout + have hresultDF : envT.IsDefEq source.uvars + ((ctorFields + (VExpr.dropN source.nparams c.type)).reverse ++ + (VExpr.telN source.nparams checked.type.type).reverse) + (VExpr.resultOf (VExpr.dropN source.nparams c.type)) + (VExpr.appN + (.const checked.type.name + (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (ctorFields + (VExpr.dropN source.nparams c.type)).length + source.nparams ++ + recFieldIdxs source.nparams + (VExpr.resultOf + (VExpr.dropN source.nparams c.type)))) + (.sort checked.resultLevel) := by + exact Eq.mpr + (congrArg + (fun e => envT.IsDefEq source.uvars + ((ctorFields + (VExpr.dropN source.nparams c.type)).reverse ++ + (VExpr.telN source.nparams + checked.type.type).reverse) + e + (VExpr.appN + (.const checked.type.name + (VLevel.params source.uvars)) + (VExpr.bvarRevRange + (ctorFields + (VExpr.dropN source.nparams c.type)).length + source.nparams ++ + recFieldIdxs source.nparams + (VExpr.resultOf + (VExpr.dropN source.nparams c.type)))) + (.sort checked.resultLevel)) + hrawResult) + hresultTyped + constructor + · simpa [NormalizedCtor.declaredBinders, + NormalizedCtor.rawFields, + NormalizedCtor.viewBinders, CheckedCtor.ofDirect, + checked.params_eq, hcAn.2.1] using htelRefl + · simpa [NormalizedCtor.declaredBinders, + NormalizedCtor.rawFields, NormalizedCtor.rawResult, + NormalizedCtor.resultTarget, CheckedCtor.ofDirect, + checked.params_eq, hcAn.2.1] using hresultDF + · simpa [NormalizedCtor.emittedBinders, + NormalizedCtor.rawFields, + NormalizedCtor.viewBinders, CheckedCtor.ofDirect, + Checked.identityGeneration, Checked.identityBlock, + NormalizedChecked.rawParams, checked.params_eq] using htelRefl + · simpa [NormalizedCtor.emittedBinders, + NormalizedCtor.rawFields, NormalizedCtor.rawResult, + NormalizedCtor.resultTarget, CheckedCtor.ofDirect, + Checked.identityGeneration, Checked.identityBlock, + NormalizedChecked.rawParams, checked.params_eq] using hresultDF + +omit S in +/-- Every semantically checked direct declaration admits the identity mixed +generation certificate. This is the public bridge from the legacy checker +contract to the normalized transaction. -/ +theorem Checked.WF.identityGeneration + {source : VInductDecl} {checked : source.Checked} + {env : VEnv} (h : checked.WF env) (henv : env.Ordered) : + checked.identityGeneration.WF env := by + have hfamily := h.family_isType + have hnorm : checked.identityGeneration.block.normalization.WF env := by + refine ⟨checked.type, checked.type, checked.types_eq, ?_, ?_, ?_⟩ + · simpa only [Checked.identityGeneration, Checked.identityBlock, + Normalization.identity] using checked.types_eq + · obtain ⟨u, hu⟩ := hfamily + exact ⟨.sort u, hu⟩ + · intro envT hadd + have hadd' : env.addConst checked.type.name + checked.type.toVConstant = some envT := by + simpa only [Checked.identityGeneration, + Checked.identityBlock] using hadd + have hall : ∀ c ∈ checked.type.ctors, + envT.IsDefEqU source.uvars [] c.type c.type := by + intro c hc + have hpair : + (⟨c, CheckedCtor.ofDirect source.uvars + checked.type.name source.nparams + checked.indices.length c⟩ : NormalizedCtor) ∈ + checked.identityGeneration.block.ctorPairs := by + simpa only [Checked.identityGeneration, + Checked.identityBlock, NormalizedChecked.ctorPairs, + checked.constructors_eq] using + (pairNormalizedCtors_map_self_contains hc : + (⟨c, CheckedCtor.ofDirect source.uvars + checked.type.name source.nparams + checked.indices.length c⟩ : + NormalizedCtor) ∈ + pairNormalizedCtors checked.type.ctors + (checked.type.ctors.map + (CheckedCtor.ofDirect source.uvars + checked.type.name source.nparams + checked.indices.length))) + obtain ⟨u, hu⟩ := + (h.identityCtorWF henv hadd' hpair).rawDeclared_isType + exact ⟨.sort u, hu⟩ + have hrel : List.Forall₂ + (fun c c' => envT.IsDefEqU source.uvars [] + c.type c'.type) + checked.type.ctors checked.type.ctors := by + let R : VConstVal → VConstVal → Prop := + fun c c' => envT.IsDefEqU source.uvars [] + c.type c'.type + let rec diagonal : + ∀ cs : List VConstVal, + (∀ c ∈ cs, R c c) → + List.Forall₂ R cs cs + | [], _ => .nil + | c :: cs, hs => + .cons (hs c (.head _)) + (diagonal cs fun c hc => hs c (.tail _ hc)) + exact diagonal checked.type.ctors hall + simpa only [Checked.identityGeneration, + Checked.identityBlock, Normalization.identity] using hrel + refine { + blockWF := ⟨hnorm, h⟩ + familyTel := ?_ + familyResult := ?_ + ctors := ?_ + } + · simpa only [Checked.identityGeneration, + Checked.identityBlock, NormalizedChecked.rawParams, + NormalizedChecked.rawIndices, checked.params_eq, + checked.indices_eq] using h.1.telDefEq_refl + · simpa only [Checked.identityGeneration, + Checked.identityBlock, NormalizedChecked.rawParams, + NormalizedChecked.rawIndices, NormalizedChecked.rawResult, + checked.params_eq, checked.indices_eq, + checked.result_eq] using + (VEnv.IsDefEq.sortDF + checked.direct_anatomy.2.2.1 + checked.direct_anatomy.2.2.1 rfl : + env.IsDefEq source.uvars + (checked.params ++ checked.indices).reverse + (.sort checked.resultLevel) + (.sort checked.resultLevel) + (.sort (.succ checked.resultLevel))) + · intro envT hadd ctor hctor + have hadd' : env.addConst checked.type.name + checked.type.toVConstant = some envT := by + simpa only [Checked.identityGeneration, + Checked.identityBlock] using hadd + exact h.identityCtorWF henv hadd' hctor + +end VInductDecl + +/-! ## `addInduct_WF` -/ + +theorem _root_.List.mem_zipIdx_getElem? {α} : ∀ {l : List α} {n : Nat} {a : α} {i : Nat}, + (a, i) ∈ l.zipIdx n → n ≤ i ∧ l[i - n]? = some a + | b :: l, n, a, i, h => by + simp only [List.zipIdx] at h + rcases List.mem_cons.1 h with h | h + · obtain ⟨rfl, rfl⟩ := Prod.mk.injEq .. ▸ h + simp + · obtain ⟨h1, h2⟩ := List.mem_zipIdx_getElem? h + refine ⟨by omega, ?_⟩ + rw [show i - n = (i - (n+1)) + 1 from by omega] + simpa using h2 + +namespace VInductDecl + +theorem rulesFold_WF : ∀ (dfs : List VDefEq) {env₃ : VEnv}, + env₃.Ordered → (∀ df ∈ dfs, df.WF env₃) → + (dfs.foldl VEnv.addDefEq env₃).Ordered + | [], _, ord, _ => ord + | df :: dfs, env₃, ord, hdfs => by + rw [List.foldl_cons] + exact rulesFold_WF dfs (.defeq ord (hdfs df (.head _))) + (fun df' hdf' => (hdfs df' (.tail _ hdf')).mono VEnv.addDefEq_le) + +/-- Every rule emitted from the paired constructor list is well formed in the +environment containing the mixed recursor. -/ +theorem GenerationEnv.generatedRules_WF + {source : VInductDecl} + {gen : GenerationChecked source} {env : VEnv} + (S : GenerationEnv gen env) + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) : + ∀ df ∈ gen.generatedRules, df.WF env := by + intro df hdf + change df ∈ + gen.block.ctorPairs.zipIdx.map + (fun (ctor, i) => gen.rule i ctor) at hdf + obtain ⟨⟨ctor, i⟩, hmem, rfl⟩ := + List.mem_map.1 hdf + obtain ⟨-, hci⟩ := + List.mem_zipIdx_getElem? hmem + rw [Nat.sub_zero] at hci + exact S.rule_WF hci hrec + +/-- Folding all mixed generated rules preserves environment ordering. -/ +theorem GenerationEnv.generatedRulesFold_ordered + {source : VInductDecl} + {gen : GenerationChecked source} {env : VEnv} + (S : GenerationEnv gen env) + (hrec : env.constants + (.str gen.block.sourceType.name "rec") = + some gen.recursor) : + (gen.generatedRules.foldl + VEnv.addDefEq env).Ordered := + rulesFold_WF gen.generatedRules S.ord + (S.generatedRules_WF hrec) + +/-- Every rule emitted from the flattened mutual constructor list is well +formed in an environment containing every generated family recursor. -/ +theorem BlockGenerationEnv.generatedRules_WF + {source : VInductDecl} + {gen : BlockGenerationChecked source} {env : VEnv} + (S : BlockGenerationEnv gen env) + (hrecs : ∀ family ∈ gen.families, + env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) : + ∀ df ∈ gen.generatedRules, df.WF env := by + intro df hdf + change df ∈ + gen.flatCtors.zipIdx.map + (fun (constructor, i) => gen.rule i constructor) at hdf + obtain ⟨⟨constructor, i⟩, hmem, rfl⟩ := List.mem_map.1 hdf + obtain ⟨-, hci⟩ := List.mem_zipIdx_getElem? hmem + rw [Nat.sub_zero] at hci + exact S.rule_WF hci hrecs + +/-- Folding every generated mutual rule preserves environment ordering. -/ +theorem BlockGenerationEnv.generatedRulesFold_ordered + {source : VInductDecl} + {gen : BlockGenerationChecked source} {env : VEnv} + (S : BlockGenerationEnv gen env) + (hrecs : ∀ family ∈ gen.families, + env.constants (.str family.raw.name "rec") = + some (gen.recursor family)) : + (gen.generatedRules.foldl VEnv.addDefEq env).Ordered := + rulesFold_WF gen.generatedRules S.ord + (S.generatedRules_WF hrecs) + +/-- Folding definitional equations only grows the environment and registers +every equation in the input list. -/ +theorem rulesFold_spec : ∀ (dfs : List VDefEq) (env : VEnv), + env ≤ dfs.foldl VEnv.addDefEq env ∧ + ∀ df ∈ dfs, (dfs.foldl VEnv.addDefEq env).defeqs df + | [], _ => ⟨.rfl, nofun⟩ + | df :: dfs, env => by + rw [List.foldl_cons] + obtain ⟨hle, hmem⟩ := rulesFold_spec dfs (env.addDefEq df) + refine ⟨VEnv.addDefEq_le.trans hle, fun df' hdf' => ?_⟩ + rcases List.mem_cons.1 hdf' with rfl | hdf' + · exact hle.defeqs VEnv.addDefEq_self + · exact hmem df' hdf' + +/-- A successful constructor fold grows the environment, registers every +constructor, and certifies that every constructor name was fresh in the +fold's input environment. -/ +theorem ctorFold_spec : ∀ (cs : List VConstVal) {env₀ env₁ : VEnv}, + List.foldlM (fun env (c : VConstVal) => env.addConst c.name c.toVConstant) env₀ cs = + some env₁ → + env₀ ≤ env₁ ∧ + (∀ c ∈ cs, env₁.constants c.name = some c.toVConstant) ∧ + ∀ c ∈ cs, env₀.constants c.name = none + | [], _, _, hfold => by + cases hfold + exact ⟨.rfl, nofun, nofun⟩ + | c :: cs, env₀, env₁, hfold => by + rw [List.foldlM_cons] at hfold + obtain ⟨env₀', hadd, hrest⟩ := Option.bind_eq_some_iff.1 hfold + obtain ⟨hle, hlook, hfresh⟩ := ctorFold_spec cs hrest + have haddLe := VEnv.addConst_le hadd + refine ⟨haddLe.trans hle, ?_, ?_⟩ + · intro c' hc' + rcases List.mem_cons.1 hc' with rfl | hc' + · exact hle.constants (VEnv.addConst_self hadd) + · exact hlook c' hc' + · intro c' hc' + rcases List.mem_cons.1 hc' with rfl | hc' + · exact VEnv.addConst_fresh hadd + · exact haddLe.constants_none (hfresh c' hc') + +/-- Sequentially inserting constants that are all well formed in the fold's +initial environment preserves ordering. Monotonicity transports the remaining +constant certificates after each insertion. -/ +theorem constFold_ordered : ∀ (cs : List VConstVal) {env₀ env₁ : VEnv}, + env₀.Ordered → + (∀ c ∈ cs, c.toVConstant.WF env₀) → + List.foldlM + (fun env (c : VConstVal) => env.addConst c.name c.toVConstant) + env₀ cs = some env₁ → + env₁.Ordered + | [], _, _, ord, _, hfold => by + cases hfold + exact ord + | c :: cs, env₀, env₁, ord, hwf, hfold => by + rw [List.foldlM_cons] at hfold + obtain ⟨env₀', hadd, hrest⟩ := Option.bind_eq_some_iff.1 hfold + have hle := VEnv.addConst_le hadd + have ord' : env₀'.Ordered := + .const ord (hwf c (.head _)) hadd + exact constFold_ordered cs ord' + (fun c' hc' => (hwf c' (.tail _ hc')).mono hle) hrest + +/-- Adding the constructors of a stage-3 block preserves order and records +their lookups. -/ +theorem ctorFold_WF {U : Nat} {T : Name} {np : Nat} {l : VLevel} {ty : VInductiveType} + (hsort : VExpr.resultOf (VExpr.dropN np ty.type) = .sort l) + (hlen : (VExpr.telN np ty.type).length = np) (hl : l.WF U) : + ∀ (cs' : List VConstVal) {env₀ env₁ : VEnv}, + env₀.Ordered → env₀.constants T = some ⟨U, ty.type⟩ → + VEnv.OnTel env₀ U [] + (VExpr.telN np ty.type ++ ctorFields (VExpr.dropN np ty.type)) → + (∀ c ∈ cs', c.uvars = U ∧ VExpr.telN np c.type = VExpr.telN np ty.type ∧ + stage3Ctor U T np (ctorFields (VExpr.dropN np ty.type)).length 0 + (VExpr.dropN np c.type) ∧ + fieldsWF U T np env₀ l (ctorFields (VExpr.dropN np ty.type)) + (VExpr.telN np ty.type).reverse 0 (ctorFields (VExpr.dropN np c.type)) ∧ + env₀.SpineWF U + ((ctorFields (VExpr.dropN np c.type)).reverse ++ + (VExpr.telN np ty.type).reverse) + (VExpr.forallN (VExpr.liftTelN + (ctorFields (VExpr.dropN np c.type)).length + (ctorFields (VExpr.dropN np ty.type)) 0) (.sort l)) + (recFieldIdxs np (VExpr.resultOf (VExpr.dropN np c.type))) (.sort l)) → + List.foldlM (fun env (c : VConstVal) => env.addConst c.name c.toVConstant) env₀ cs' = + some env₁ → + env₁.Ordered ∧ env₀ ≤ env₁ ∧ + ∀ c ∈ cs', env₁.constants c.name = some ⟨U, c.type⟩ + | [], env₀, env₁, ord, _, _, _, hfold => by + cases hfold + exact ⟨ord, .rfl, nofun⟩ + | c :: cs', env₀, env₁, ord, hT, hpar, hcs, hfold => by + rw [List.foldlM_cons] at hfold + obtain ⟨env₀', hadd, hrest⟩ := Option.bind_eq_some_iff.1 hfold + obtain ⟨hcU, htelc, hs3c, hfc, hresultc⟩ := hcs c (.head _) + have S₀ : Stage3Env env₀ U T np l ⟨⟨⟨ty.uvars, ty.type⟩, ty.name⟩, []⟩ := + ⟨ord, hl, hsort, hlen, hT, nofun, nofun, nofun, hpar, nofun, nofun⟩ + have hwfc : c.toVConstant.WF env₀ := by + show env₀.IsType c.toVConstant.uvars [] c.toVConstant.type + rw [show c.toVConstant.uvars = c.uvars from rfl, hcU] + exact S₀.ctorType_isType' htelc hs3c hfc hresultc + have ord' : env₀'.Ordered := .const ord hwfc hadd + have hle' := VEnv.addConst_le hadd + obtain ⟨ord₁, hle₁, hlook⟩ := ctorFold_WF hsort hlen hl cs' ord' + (hle'.constants hT) (hpar.mono hle') + (fun c' hc' => by + obtain ⟨h1, h2, h3, h4, h5⟩ := hcs c' (.tail _ hc') + exact ⟨h1, h2, h3, fieldsWF_mono hle' h4, h5.mono hle'⟩) + hrest + refine ⟨ord₁, hle'.trans hle₁, fun c' hc' => ?_⟩ + rcases List.mem_cons.1 hc' with rfl | hc' + · have hself := VEnv.addConst_self hadd + rw [show c'.toVConstant = ⟨U, c'.type⟩ from by rw [← hcU]] at hself + exact hle₁.constants hself + · exact hlook c' hc' + +end VInductDecl + +namespace VEnv +open VInductDecl + +/-- Recover the exact intermediate environments from a successful normalized +generation transaction. The data-bearing trace is wrapped in `Nonempty` so +proof consumers can eliminate it without adding a choice axiom merely to +recover bookkeeping states. -/ +theorem addInductGeneration_trace {source : VInductDecl} + {gen : source.GenerationChecked} + (hadd : addInductGeneration env gen = some env') : + Nonempty (AddInductGenerationTrace env env' gen) := by + unfold addInductGeneration at hadd + obtain ⟨typeEnv, addType, hadd⟩ := Option.bind_eq_some_iff.1 hadd + obtain ⟨ctorEnv, addCtors, hadd⟩ := Option.bind_eq_some_iff.1 hadd + obtain ⟨recEnv, addRec, hadd⟩ := Option.bind_eq_some_iff.1 hadd + cases hadd + exact ⟨⟨typeEnv, ctorEnv, recEnv, addType, addCtors, addRec, rfl⟩⟩ + +/-- The normalized core is atomic: failure returns no observable intermediate +environment, while success exposes one complete trace. -/ +theorem addInductGeneration_atomic {source : VInductDecl} + (env : VEnv) (gen : source.GenerationChecked) : + addInductGeneration env gen = none ∨ + ∃ env', addInductGeneration env gen = some env' ∧ + Nonempty (AddInductGenerationTrace env env' gen) := by + cases hadd : addInductGeneration env gen with + | none => exact .inl rfl + | some env' => + exact .inr ⟨env', rfl, addInductGeneration_trace hadd⟩ + +/-- A successful normalized generation transaction only grows its input +environment. -/ +theorem AddInductGenerationTrace.le {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) : env ≤ env' := by + have htype := addConst_le H.addType + have hctors := (ctorFold_spec gen.block.sourceType.ctors H.addCtors).1 + have hrec := addConst_le H.addRec + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact htype.trans (hctors.trans (hrec.trans hrules)) + +/-- The raw family name was fresh before a successful normalized +transaction. -/ +theorem AddInductGenerationTrace.family_fresh {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) : + env.constants gen.block.sourceType.name = none := + addConst_fresh H.addType + +/-- The final environment contains the exact raw family constant. -/ +theorem AddInductGenerationTrace.family_lookup {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) : + env'.constants gen.block.sourceType.name = + some gen.block.sourceType.toVConstant := by + have hctors := (ctorFold_spec gen.block.sourceType.ctors H.addCtors).1 + have hrec := addConst_le H.addRec + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact (hctors.trans (hrec.trans hrules)).constants + (addConst_self H.addType) + +/-- Every raw constructor name was fresh in the transaction's input +environment. -/ +theorem AddInductGenerationTrace.ctor_fresh {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + {ctor : VConstVal} (hctor : ctor ∈ gen.block.sourceType.ctors) : + env.constants ctor.name = none := by + have htype := addConst_le H.addType + have hfresh := + (ctorFold_spec gen.block.sourceType.ctors H.addCtors).2.2 ctor hctor + exact htype.constants_none hfresh + +/-- The final environment contains every exact raw constructor constant. -/ +theorem AddInductGenerationTrace.ctor_lookup {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + {ctor : VConstVal} (hctor : ctor ∈ gen.block.sourceType.ctors) : + env'.constants ctor.name = some ctor.toVConstant := by + have hlookup := + (ctorFold_spec gen.block.sourceType.ctors H.addCtors).2.1 ctor hctor + have hrec := addConst_le H.addRec + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact (hrec.trans hrules).constants hlookup + +/-- The generated recursor name was fresh before a successful normalized +transaction. -/ +theorem AddInductGenerationTrace.rec_fresh {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) : + env.constants (.str gen.block.sourceType.name "rec") = none := by + have htype := addConst_le H.addType + have hctors := (ctorFold_spec gen.block.sourceType.ctors H.addCtors).1 + exact (htype.trans hctors).constants_none (addConst_fresh H.addRec) + +/-- The final environment contains the exact mixed generated recursor. -/ +theorem AddInductGenerationTrace.rec_lookup {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) : + env'.constants (.str gen.block.sourceType.name "rec") = + some gen.recursor := by + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact hrules.constants (addConst_self H.addRec) + +/-- The final environment registers every mixed generated iota rule. -/ +theorem AddInductGenerationTrace.rule_mem {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + {df : VDefEq} (hdf : df ∈ gen.generatedRules) : + env'.defeqs df := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).2 df hdf + +/-! ### Block-wide transaction facts -/ + +/-- Recover every phase boundary from a successful block-wide transaction. -/ +theorem addInductBlockGeneration_trace {source : VInductDecl} + {gen : source.BlockGenerationChecked} + (hadd : addInductBlockGeneration env gen = some env') : + Nonempty (AddInductBlockGenerationTrace env env' gen) := by + unfold addInductBlockGeneration at hadd + obtain ⟨typeEnv, addTypes, hadd⟩ := Option.bind_eq_some_iff.1 hadd + obtain ⟨ctorEnv, addCtors, hadd⟩ := Option.bind_eq_some_iff.1 hadd + obtain ⟨recEnv, addRecs, hadd⟩ := Option.bind_eq_some_iff.1 hadd + cases hadd + exact ⟨⟨typeEnv, ctorEnv, recEnv, addTypes, addCtors, addRecs, rfl⟩⟩ + +/-- The block-wide transaction is atomic at its public `Option` boundary. -/ +theorem addInductBlockGeneration_atomic {source : VInductDecl} + (env : VEnv) (gen : source.BlockGenerationChecked) : + addInductBlockGeneration env gen = none ∨ + ∃ env', addInductBlockGeneration env gen = some env' ∧ + Nonempty (AddInductBlockGenerationTrace env env' gen) := by + cases hadd : addInductBlockGeneration env gen with + | none => exact .inl rfl + | some env' => + exact .inr ⟨env', rfl, addInductBlockGeneration_trace hadd⟩ + +/-- Every phase of a successful block transaction only grows the Theory +environment. -/ +theorem AddInductBlockGenerationTrace.le {source : VInductDecl} + {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) : env ≤ env' := by + have htypes := + (ctorFold_spec source.blockTypeConstants H.addTypes).1 + have hctors := + (ctorFold_spec source.blockConstructorConstants H.addCtors).1 + have hrecs := (ctorFold_spec gen.recursors H.addRecs).1 + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact htypes.trans (hctors.trans (hrecs.trans hrules)) + +/-- Every source family name was fresh before a successful block +transaction. -/ +theorem AddInductBlockGenerationTrace.family_fresh + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {type : VInductiveType} (htype : type ∈ source.types) : + env.constants type.name = none := by + have hmem : type.toVConstVal ∈ source.blockTypeConstants := by + exact List.mem_map.2 ⟨type, htype, rfl⟩ + simpa [VInductDecl.blockTypeConstants] using + (ctorFold_spec source.blockTypeConstants H.addTypes).2.2 + type.toVConstVal hmem + +/-- The final environment contains every exact raw family constant. -/ +theorem AddInductBlockGenerationTrace.family_lookup + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {type : VInductiveType} (htype : type ∈ source.types) : + env'.constants type.name = some type.toVConstant := by + have hmem : type.toVConstVal ∈ source.blockTypeConstants := by + exact List.mem_map.2 ⟨type, htype, rfl⟩ + have hlookup := + (ctorFold_spec source.blockTypeConstants H.addTypes).2.1 + type.toVConstVal hmem + have hctors := + (ctorFold_spec source.blockConstructorConstants H.addCtors).1 + have hrecs := (ctorFold_spec gen.recursors H.addRecs).1 + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact (hctors.trans (hrecs.trans hrules)).constants hlookup + +/-- Every flattened raw constructor name was fresh in the transaction's +input environment. -/ +theorem AddInductBlockGenerationTrace.ctor_fresh + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {constructor : VConstVal} + (hconstructor : constructor ∈ source.blockConstructorConstants) : + env.constants constructor.name = none := by + have htypes := + (ctorFold_spec source.blockTypeConstants H.addTypes).1 + have hfresh := + (ctorFold_spec source.blockConstructorConstants H.addCtors).2.2 + constructor hconstructor + exact htypes.constants_none hfresh + +/-- The final environment contains every exact raw constructor constant. -/ +theorem AddInductBlockGenerationTrace.ctor_lookup + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {constructor : VConstVal} + (hconstructor : constructor ∈ source.blockConstructorConstants) : + env'.constants constructor.name = some constructor.toVConstant := by + have hlookup := + (ctorFold_spec source.blockConstructorConstants H.addCtors).2.1 + constructor hconstructor + have hrecs := (ctorFold_spec gen.recursors H.addRecs).1 + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact (hrecs.trans hrules).constants hlookup + +/-- Every generated recursor name was fresh before the block transaction. -/ +theorem AddInductBlockGenerationTrace.rec_fresh + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {recursor : VConstVal} (hrecursor : recursor ∈ gen.recursors) : + env.constants recursor.name = none := by + have htypes := + (ctorFold_spec source.blockTypeConstants H.addTypes).1 + have hctors := + (ctorFold_spec source.blockConstructorConstants H.addCtors).1 + have hfresh := + (ctorFold_spec gen.recursors H.addRecs).2.2 recursor hrecursor + exact (htypes.trans hctors).constants_none hfresh + +/-- The final environment contains every generated recursor. -/ +theorem AddInductBlockGenerationTrace.rec_lookup + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {recursor : VConstVal} (hrecursor : recursor ∈ gen.recursors) : + env'.constants recursor.name = some recursor.toVConstant := by + have hlookup := + (ctorFold_spec gen.recursors H.addRecs).2.1 recursor hrecursor + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).1 + exact hrules.constants hlookup + +/-- The final environment registers every block-generated iota rule. -/ +theorem AddInductBlockGenerationTrace.rule_mem + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {df : VDefEq} (hdf : df ∈ gen.generatedRules) : + env'.defeqs df := by + simpa only [H.addRules] using + (rulesFold_spec gen.generatedRules H.recEnv).2 df hdf + +/-- Preserve ordering through the all-families phase. -/ +private theorem addInductBlockGeneration_families_ordered + {source : VInductDecl} {gen : source.BlockGenerationChecked} + {blockEnv : VEnv} + (H : AddInductBlockGenerationTrace env env' gen) + (henv : env.Ordered) (hgen : gen.WF env blockEnv) : + H.typeEnv.Ordered := by + apply constFold_ordered source.blockTypeConstants henv ?_ H.addTypes + intro type htype + simp only [VInductDecl.blockTypeConstants, List.mem_map] at htype + obtain ⟨raw, hraw, rfl⟩ := htype + have hraw' : raw ∈ gen.families.map (·.raw) := by + rw [gen.families_map_raw] + exact hraw + obtain ⟨family, hfamily, rfl⟩ := List.mem_map.1 hraw' + show env.IsType family.raw.uvars [] family.raw.type + rw [gen.family_uvars hfamily] + exact hgen.rawFamily_isType hfamily + +/-- Preserve ordering through the globally flattened constructor phase. -/ +private theorem addInductBlockGeneration_constructors_ordered + {source : VInductDecl} {gen : source.BlockGenerationChecked} + {blockEnv : VEnv} + (H : AddInductBlockGenerationTrace env env' gen) + (hgen : gen.WF env blockEnv) (ordT : H.typeEnv.Ordered) : + H.ctorEnv.Ordered := by + have hstage : env.stageInductiveTypes source.types = some blockEnv := + hgen.blockWF.1.1 + rw [← blockTypeConstants_foldlM_eq_stageInductiveTypes env source, + H.addTypes] at hstage + have htypeEnv : H.typeEnv = blockEnv := Option.some.inj hstage + subst blockEnv + apply constFold_ordered source.blockConstructorConstants ordT ?_ H.addCtors + intro ctor hctor + have hctor' : ctor ∈ gen.flatCtors.map (·.ctor.raw) := by + rw [gen.flatCtors_map_raw] + exact hctor + obtain ⟨constructor, hconstructor, rfl⟩ := List.mem_map.1 hctor' + show H.typeEnv.IsType constructor.ctor.raw.uvars [] + constructor.ctor.raw.type + rw [gen.flatCtor_uvars hconstructor] + exact hgen.rawCtor_isType hconstructor + +/-- Assemble the mutual generation invariant once every raw family and every +globally flattened constructor has been inserted. -/ +private theorem addInductBlockGeneration_constructor_generationEnv + {source : VInductDecl} {gen : source.BlockGenerationChecked} + {blockEnv : VEnv} + (H : AddInductBlockGenerationTrace env env' gen) + (hgen : gen.WF env blockEnv) (ordC : H.ctorEnv.Ordered) : + BlockGenerationEnv gen H.ctorEnv := by + obtain ⟨hleET, hfamilyLookup, -⟩ := + ctorFold_spec source.blockTypeConstants H.addTypes + obtain ⟨hleTC, hctorLookup, -⟩ := + ctorFold_spec source.blockConstructorConstants H.addCtors + have hstage : env.stageInductiveTypes source.types = some blockEnv := + hgen.blockWF.1.1 + rw [← blockTypeConstants_foldlM_eq_stageInductiveTypes env source, + H.addTypes] at hstage + have htypeEnv : H.typeEnv = blockEnv := Option.some.inj hstage + rw [htypeEnv] at hleET hfamilyLookup hleTC + have hfamilies : ∀ family ∈ gen.families, + H.ctorEnv.constants family.raw.name = + some family.raw.toVConstant := by + intro family hfamily + apply hleTC.constants + apply hfamilyLookup family.raw.toVConstVal + simp only [VInductDecl.blockTypeConstants, List.mem_map] + refine ⟨family.raw, ?_, rfl⟩ + rw [← gen.families_map_raw] + exact List.mem_map.2 ⟨family, hfamily, rfl⟩ + have hctors : ∀ constructor ∈ gen.flatCtors, + H.ctorEnv.constants constructor.ctor.raw.name = + some constructor.ctor.raw.toVConstant := by + intro constructor hconstructor + apply hctorLookup constructor.ctor.raw + rw [← gen.flatCtors_map_raw] + exact List.mem_map.2 ⟨constructor, hconstructor, rfl⟩ + exact hgen.toBlockGenerationEnv (hleET.trans hleTC) hleTC ordC + hfamilies hctors + +/-- Preserve ordering while inserting the family-indexed recursor list. -/ +private theorem addInductBlockGeneration_recursors_ordered + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + (S : BlockGenerationEnv gen H.ctorEnv) : + H.recEnv.Ordered := by + apply constFold_ordered gen.recursors S.ord ?_ H.addRecs + intro recursor hrecursor + simp only [BlockGenerationChecked.recursors, List.mem_map] at hrecursor + obtain ⟨family, hfamily, rfl⟩ := hrecursor + exact S.recursor_wf hfamily + +/-- The recursor fold stores the exact generated recursor selected by every +family ordinal. -/ +private theorem addInductBlockGeneration_recursor_lookup + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + {family : NormalizedFamily} (hfamily : family ∈ gen.families) : + H.recEnv.constants (.str family.raw.name "rec") = + some (gen.recursor family) := by + let recursor : VConstVal := + ⟨gen.recursor family, .str family.raw.name "rec"⟩ + have hrecursor : recursor ∈ gen.recursors := + List.mem_map.2 ⟨family, hfamily, rfl⟩ + simpa [recursor] using + (ctorFold_spec gen.recursors H.addRecs).2.1 recursor hrecursor + +/-- Preserve ordering through the block-wide generated-rule fold. -/ +private theorem addInductBlockGeneration_rules_ordered + {source : VInductDecl} {gen : source.BlockGenerationChecked} + (H : AddInductBlockGenerationTrace env env' gen) + (S : BlockGenerationEnv gen H.recEnv) : env'.Ordered := by + have hout := S.generatedRulesFold_ordered + (fun family hfamily => + addInductBlockGeneration_recursor_lookup H hfamily) + simpa only [H.addRules] using hout + +/-- The block-wide transaction preserves ordering through all families, +constructors, family-indexed recursors, and flattened iota rules. -/ +theorem addInductBlockGeneration_WF + {source : VInductDecl} {gen : source.BlockGenerationChecked} + {blockEnv : VEnv} + (henv : env.Ordered) (hgen : gen.WF env blockEnv) + (hadd : addInductBlockGeneration env gen = some env') : + env'.Ordered := by + rcases addInductBlockGeneration_trace hadd with ⟨H⟩ + have ordT : H.typeEnv.Ordered := + addInductBlockGeneration_families_ordered H henv hgen + have ordC : H.ctorEnv.Ordered := + addInductBlockGeneration_constructors_ordered H hgen ordT + have S : BlockGenerationEnv gen H.ctorEnv := + addInductBlockGeneration_constructor_generationEnv H hgen ordC + have ordR : H.recEnv.Ordered := + addInductBlockGeneration_recursors_ordered H S + have hleCR := (ctorFold_spec gen.recursors H.addRecs).1 + have SR : BlockGenerationEnv gen H.recEnv := + S.mono hleCR ordR + exact addInductBlockGeneration_rules_ordered H SR + +/-- Preserve ordering across the raw family insertion, the first generated +component of an inductive transaction. -/ +private theorem addInductGeneration_family_ordered {source : VInductDecl} + {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + (henv : env.Ordered) (hgen : gen.WF env) : H.typeEnv.Ordered := by + have hfamilyWF : gen.block.sourceType.toVConstant.WF env := by + show env.IsType gen.block.sourceType.uvars [] + gen.block.sourceType.type + rw [gen.block.sourceType_uvars_eq] + exact hgen.rawFamily_isType + exact .const henv hfamilyWF H.addType + +/-- Preserve ordering across the complete raw constructor fold. The proof is +uniform in the source list, so the empty-constructor case is the ordinary +zero-step fold rather than a separate preservation path. -/ +private theorem addInductGeneration_constructors_ordered + {source : VInductDecl} {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + (hgen : gen.WF env) (ordT : H.typeEnv.Ordered) : + H.ctorEnv.Ordered := by + have hctorWF : + ∀ c ∈ gen.block.sourceType.ctors, + c.toVConstant.WF H.typeEnv := by + intro c hc + have hc' : c ∈ gen.block.ctorPairs.map (·.raw) := by + rw [gen.rawCtors_eq] + exact hc + obtain ⟨ctor, hctor, rfl⟩ := List.mem_map.1 hc' + show H.typeEnv.IsType ctor.raw.uvars [] ctor.raw.type + rw [gen.ctor_uvars_eq hctor] + exact hgen.rawCtor_isType H.addType hctor + exact constFold_ordered gen.block.sourceType.ctors ordT hctorWF + H.addCtors + +/-- Assemble the mixed-generation invariant after the exact family and +constructor components have been inserted. -/ +private theorem addInductGeneration_constructor_generationEnv + {source : VInductDecl} {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + (hgen : gen.WF env) (ordC : H.ctorEnv.Ordered) : + GenerationEnv gen H.ctorEnv := by + obtain ⟨hleTC, hctorLookup, -⟩ := + ctorFold_spec gen.block.sourceType.ctors H.addCtors + have hlePreT := addConst_le H.addType + have hlePreC := hlePreT.trans hleTC + have hfamily : + H.ctorEnv.constants gen.block.sourceType.name = + some gen.block.sourceType.toVConstant := + hleTC.constants (addConst_self H.addType) + have hctors : + ∀ ctor ∈ gen.block.ctorPairs, + H.ctorEnv.constants ctor.raw.name = + some ctor.raw.toVConstant := by + intro ctor hctor + apply hctorLookup ctor.raw + rw [← gen.rawCtors_eq] + exact List.mem_map.2 ⟨ctor, hctor, rfl⟩ + exact hgen.toGenerationEnv H.addType hlePreC hleTC ordC hfamily + hctors + +/-- Preserve ordering across the single generated recursor component. -/ +private theorem addInductGeneration_recursor_ordered + {source : VInductDecl} {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + (S : GenerationEnv gen H.ctorEnv) : H.recEnv.Ordered := + .const S.ord S.recursor_wf H.addRec + +/-- Preserve ordering across the generated rule fold. Empty families supply +no rules, so this is again the same zero-step component fold used generally. -/ +private theorem addInductGeneration_rules_ordered + {source : VInductDecl} {gen : source.GenerationChecked} + (H : AddInductGenerationTrace env env' gen) + (S : GenerationEnv gen H.recEnv) : env'.Ordered := by + have hout := + S.generatedRulesFold_ordered (addConst_self H.addRec) + simpa only [H.addRules] using hout + +/-- The normalized transaction preserves environment ordering from the +semantic raw/view generation certificate. Stored constants are checked in +their exact raw syntax; the mixed recursor and rules are checked only after +all raw constants are present. -/ +theorem addInductGeneration_WF {source : VInductDecl} + {gen : source.GenerationChecked} + (henv : env.Ordered) (hgen : gen.WF env) + (hadd : addInductGeneration env gen = some env') : + env'.Ordered := by + rcases addInductGeneration_trace hadd with ⟨H⟩ + have ordT : H.typeEnv.Ordered := + addInductGeneration_family_ordered H henv hgen + have ordC : H.ctorEnv.Ordered := + addInductGeneration_constructors_ordered H hgen ordT + have S : GenerationEnv gen H.ctorEnv := + addInductGeneration_constructor_generationEnv H hgen ordC + have ordR : H.recEnv.Ordered := + addInductGeneration_recursor_ordered H S + have hleCR := addConst_le H.addRec + have SR : GenerationEnv gen H.recEnv := + S.mono hleCR ordR + exact addInductGeneration_rules_ordered H SR + +/-- Recover the ordinary normalized transaction trace from the +proof-carrying public entry point. The conclusion contains only Theory data; +the producer that established the certificate is deliberately absent. -/ +theorem addInductCertified_trace {source : VInductDecl} + {certificate : source.GenerationCertificate env} + (hadd : addInductCertified env certificate = some env') : + Nonempty + (AddInductGenerationTrace env env' certificate.generation) := by + apply addInductGeneration_trace + simpa only [addInductCertified_eq_addInductGeneration] using hadd + +/-- The proof-carrying wrapper has the same atomic success/failure behavior as +the underlying normalized transaction. -/ +theorem addInductCertified_atomic {source : VInductDecl} + (env : VEnv) (certificate : source.GenerationCertificate env) : + addInductCertified env certificate = none ∨ + ∃ env', addInductCertified env certificate = some env' ∧ + Nonempty + (AddInductGenerationTrace env env' certificate.generation) := by + simpa only [addInductCertified_eq_addInductGeneration] using + addInductGeneration_atomic env certificate.generation + +/-- Ordering preservation for the public certified transaction. Its +semantic premise is carried by the certificate rather than repeated at every +call site. -/ +theorem addInductCertified_WF {source : VInductDecl} + {certificate : source.GenerationCertificate env} + (henv : env.Ordered) + (hadd : addInductCertified env certificate = some env') : + env'.Ordered := by + apply addInductGeneration_WF henv certificate.wf + simpa only [addInductCertified_eq_addInductGeneration] using hadd + +/-- Recover the exact block-wide transaction phases through the public +proof-carrying entry point. -/ +theorem addInductBlockCertified_trace {source : VInductDecl} + {certificate : source.BlockGenerationCertificate env} + (hadd : addInductBlockCertified env certificate = some env') : + Nonempty + (AddInductBlockGenerationTrace env env' + certificate.generation) := by + apply addInductBlockGeneration_trace + simpa only [addInductBlockCertified_eq_addInductBlockGeneration] using hadd + +/-- The public block certificate wrapper has the same atomic behavior as its +underlying block transaction. -/ +theorem addInductBlockCertified_atomic {source : VInductDecl} + (env : VEnv) (certificate : source.BlockGenerationCertificate env) : + addInductBlockCertified env certificate = none ∨ + ∃ env', addInductBlockCertified env certificate = some env' ∧ + Nonempty + (AddInductBlockGenerationTrace env env' + certificate.generation) := by + simpa only [addInductBlockCertified_eq_addInductBlockGeneration] using + addInductBlockGeneration_atomic env certificate.generation + +/-- Ordering preservation for the public proof-carrying mutual-block +transaction. -/ +theorem addInductBlockCertified_WF {source : VInductDecl} + {certificate : source.BlockGenerationCertificate env} + (henv : env.Ordered) + (hadd : addInductBlockCertified env certificate = some env') : + env'.Ordered := by + apply addInductBlockGeneration_WF henv certificate.wf + simpa only [addInductBlockCertified_eq_addInductBlockGeneration] using hadd + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductBlockGeneration_trace [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductBlockGeneration_atomic [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductBlockGenerationTrace.le [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductBlockGenerationTrace.family_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductBlockGenerationTrace.ctor_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductBlockGenerationTrace.rec_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductBlockGenerationTrace.rule_mem [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductBlockGeneration_WF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductBlockCertified_eq_addInductBlockGeneration [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductBlockCertified_trace [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductBlockCertified_atomic [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductBlockCertified_WF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductGeneration_trace [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductGeneration_atomic [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductGenerationTrace.le [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductGenerationTrace.family_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductGenerationTrace.ctor_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductGenerationTrace.rec_lookup [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.AddInductGenerationTrace.rule_mem [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductGeneration_WF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductCertified_eq_addInductGeneration [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductCertified_trace [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductCertified_atomic [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInductCertified_WF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInduct_eq_addInductBlockGeneration [propext, Classical.choice, Quot.sound] + +/-- Elimination of a successful `addInduct` transaction into its stable +consumer-facing postcondition. -/ +theorem addInduct_success (hadd : addInduct env decl = some env') : + AddInductSuccess env env' decl := by + unfold addInduct at hadd + obtain ⟨generation, hgeneration, hgen⟩ := + Option.bind_eq_some_iff.1 hadd + rcases addInductBlockGeneration_trace hgen with ⟨H⟩ + refine { + generation := ⟨generation, hgeneration⟩ + accepted := by simp [stage3, hgeneration] + le := H.le + type_fresh := ?_ + type_lookup := ?_ + ctor_fresh := ?_ + ctor_lookup := ?_ + rec_fresh := ?_ + rec_lookup := ?_ + rule_mem := ?_ + } + · intro ty hty + exact H.family_fresh hty + · intro ty hty + exact H.family_lookup hty + · intro ty hty c hc + apply H.ctor_fresh + simp only [VInductDecl.blockConstructorConstants, List.mem_flatMap] + exact ⟨ty, hty, hc⟩ + · intro ty hty c hc + apply H.ctor_lookup + simp only [VInductDecl.blockConstructorConstants, List.mem_flatMap] + exact ⟨ty, hty, hc⟩ + · intro generation' hgeneration' recursor hrecursor + have heq : generation = generation' := + Option.some.inj (hgeneration.symm.trans hgeneration') + exact H.rec_fresh (by simpa [heq] using hrecursor) + · intro generation' hgeneration' recursor hrecursor + have heq : generation = generation' := + Option.some.inj (hgeneration.symm.trans hgeneration') + exact H.rec_lookup (by simpa [heq] using hrecursor) + · intro generation' hgeneration' df hdf + have heq : generation = generation' := + Option.some.inj (hgeneration.symm.trans hgeneration') + exact H.rule_mem (by simpa [heq] using hdf) + +/-- Successful inductive addition is monotone. -/ +theorem addInduct_le (hadd : addInduct env decl = some env') : env ≤ env' := + (addInduct_success hadd).le + +/-- Successful environment extension exposes the exact block descriptor that +drove generation, so consumers never need to re-run acceptance analysis. -/ +theorem addInduct_generation (hadd : addInduct env decl = some env') : + ∃ generation, decl.identityBlockGeneration? = some generation := + (addInduct_success hadd).generation + +theorem addInduct_type_fresh (hadd : addInduct env decl = some env') + (hty : ty ∈ decl.types) : env.constants ty.name = none := + (addInduct_success hadd).type_fresh ty hty + +theorem addInduct_type_lookup (hadd : addInduct env decl = some env') + (hty : ty ∈ decl.types) : env'.constants ty.name = some ty.toVConstant := + (addInduct_success hadd).type_lookup ty hty + +theorem addInduct_ctor_fresh (hadd : addInduct env decl = some env') + (hty : ty ∈ decl.types) (hc : c ∈ ty.ctors) : env.constants c.name = none := + (addInduct_success hadd).ctor_fresh ty hty c hc + +theorem addInduct_ctor_lookup (hadd : addInduct env decl = some env') + (hty : ty ∈ decl.types) (hc : c ∈ ty.ctors) : + env'.constants c.name = some c.toVConstant := + (addInduct_success hadd).ctor_lookup ty hty c hc + +theorem addInduct_rec_fresh (hadd : addInduct env decl = some env') + {generation : decl.BlockGenerationChecked} + (hgeneration : decl.identityBlockGeneration? = some generation) + {recursor : VConstVal} (hrecursor : recursor ∈ generation.recursors) : + env.constants recursor.name = none := + (addInduct_success hadd).rec_fresh generation hgeneration recursor hrecursor + +theorem addInduct_rec_lookup (hadd : addInduct env decl = some env') + {generation : decl.BlockGenerationChecked} + (hgeneration : decl.identityBlockGeneration? = some generation) + {recursor : VConstVal} (hrecursor : recursor ∈ generation.recursors) : + env'.constants recursor.name = some recursor.toVConstant := + (addInduct_success hadd).rec_lookup generation hgeneration recursor hrecursor + +theorem addInduct_rule_mem (hadd : addInduct env decl = some env') + {generation : decl.BlockGenerationChecked} + (hgeneration : decl.identityBlockGeneration? = some generation) + (hdf : df ∈ generation.generatedRules) : + env'.defeqs df := + (addInduct_success hadd).rule_mem generation hgeneration df hdf + +/-- `addInduct` is an all-or-nothing transaction: every evaluation either +returns no environment or returns an environment satisfying the complete +success contract. -/ +theorem addInduct_atomic : + addInduct env decl = none ∨ + ∃ env', addInduct env decl = some env' ∧ AddInductSuccess env env' decl := by + cases hadd : addInduct env decl with + | none => exact .inl rfl + | some env' => exact .inr ⟨env', rfl, addInduct_success hadd⟩ + +/-- The Stage-3 guard is an exact early-rejection condition. -/ +theorem addInduct_eq_none_of_stage3_false (h : decl.stage3 = false) : + addInduct env decl = none := by + have hgeneration : decl.identityBlockGeneration? = none := + identityBlockGeneration?_eq_none_iff.2 h + simp [addInduct, hgeneration] + +/-- A pre-existing type name rejects the transaction before any generated +object is observable. -/ +theorem addInduct_eq_none_of_type_present (hty : ty ∈ decl.types) + (hcontains : env.contains ty.name) : addInduct env decl = none := by + cases hadd : addInduct env decl with + | none => rfl + | some env' => + have hfresh := (addInduct_success hadd).type_fresh ty hty + obtain ⟨ci, hci⟩ := hcontains + rw [hci] at hfresh + contradiction + +/-- A pre-existing constructor name rejects the complete transaction. The +proof is stated through the stable success certificate, not the position of +the constructor in the internal `foldlM`. -/ +theorem addInduct_eq_none_of_ctor_present (hty : ty ∈ decl.types) + (hctor : ctor ∈ ty.ctors) (hcontains : env.contains ctor.name) : + addInduct env decl = none := by + cases hadd : addInduct env decl with + | none => rfl + | some env' => + have hfresh := (addInduct_success hadd).ctor_fresh ty hty ctor hctor + obtain ⟨ci, hci⟩ := hcontains + rw [hci] at hfresh + contradiction + +/-- A pre-existing generated recursor name likewise rejects the complete +transaction. -/ +theorem addInduct_eq_none_of_rec_present + {generation : decl.BlockGenerationChecked} + (hgeneration : decl.identityBlockGeneration? = some generation) + (hrecursor : recursor ∈ generation.recursors) + (hcontains : env.contains recursor.name) : addInduct env decl = none := by + cases hadd : addInduct env decl with + | none => rfl + | some env' => + have success := addInduct_success hadd + have hfresh := success.rec_fresh generation hgeneration recursor hrecursor + obtain ⟨ci, hci⟩ := hcontains + rw [hci] at hfresh + contradiction + +theorem addInduct_WF {generation : decl.BlockGenerationChecked} + {blockEnv : VEnv} (henv : Ordered env) + (hgeneration : decl.identityBlockGeneration? = some generation) + (hgen : generation.WF env blockEnv) + (hadd : addInduct env decl = some env') : Ordered env' := by + unfold addInduct at hadd + rw [hgeneration] at hadd + exact addInductBlockGeneration_WF henv hgen hadd + +end VEnv + +/- Mixed raw/view generation must stay within Lean's standard logical +baseline. Guard each proof-critical boundary separately so a dependency change +identifies the first affected layer. -/ +#guard_named_axioms Ix.Theory.Named.VInductDecl.Checked.WF.identityGeneration [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.minor_isType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.minorTypes_onTel [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.familyApp_transport [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.recType_isType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.recursor_wf [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.ruleCall_hasType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.rule_WF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.generatedRules_WF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationEnv.generatedRulesFold_ordered [propext, Classical.choice, Quot.sound] + +/- The generalized recursive-Pi artifact path must remain within the same +standard logical baseline as the public preservation theorem. These guards +make every proof-critical boundary independently auditable. -/ +#guard_named_axioms Ix.Theory.Named.VInductDecl.Stage3Env.recTypeRec_isType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Stage3Env.recConstRec_wf [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Stage3Env.ruleCallRec_hasType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Stage3Env.minorAppRec_hasType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Stage3Env.recRuleAppRec_hasType [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.Stage3Env.ruleRec_WF [propext, Classical.choice, Quot.sound] + +/- The indexed-inductive preservation proof stays within Lean's standard +logical axiom baseline. Keep this guard adjacent to the theorem so a new +dependency fails during ordinary module compilation. -/ +#guard_named_axioms Ix.Theory.Named.VEnv.addInduct_success [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInduct_generation [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInduct_eq_none_of_ctor_present [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInduct_eq_none_of_rec_present [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.addInduct_WF [propext, Classical.choice, Quot.sound] diff --git a/Ix/Theory/Named/Typing/InductivePattern.lean b/Ix/Theory/Named/Typing/InductivePattern.lean new file mode 100644 index 000000000..b853952d7 --- /dev/null +++ b/Ix/Theory/Named/Typing/InductivePattern.lean @@ -0,0 +1,761 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Typing.InductiveLemmas +import Ix.Theory.Named.Typing.Pattern + +open Ix.Theory (VLevel) + +/-! # Generated iota rules as patterns + +Every iota rule generated for a certified mutual block +(`BlockGenerationChecked.rule`) is a closed defeq between lambda telescopes +whose left body is a `SimplePattern.iota` spine: the owning family's recursor +applied to the shared parameters, all motives, all minors, and the +constructor's result indices, with a constructor-headed major premise. This +module makes that connection exact and proves the generic pattern facts the +Church–Rosser `Params` interface demands of one certified block: + +* `rulePattern` is the `SimplePattern` of one flattened constructor's rule, + and `ruleLhsBody_matches` matches the exact generated left body against it + at the rule's recursor levels. +* `IotaPat` is the block's pattern set, associating each rule's pattern with + an RHS template (the registered right tower applied to the captured common + arguments and fields) and a check list (parameter and result-index + agreement between the recursor spine and the major premise). +* `pat_simple`, `pat_uniq`, `pat_app_l`, `pat_app_l_uniq`, and + `pat_app_uniq` are exactly the `Params` obligations, specialized to + `IotaPat`; their name-freshness inputs come from the certified block's + `blockGeneratedNames` nodup bit, and the major-arity agreement between + same-recursor rules comes from the analyzer's terminal `blockTarget?` + arity equation. + +No open-environment `Params` instance is installed here; the block supplies +the facts, and soundness (`pat_wf`) plus the block-local environment +assembler belong to the pattern-soundness milestone. -/ + +namespace Ix.Theory.Named + +open VExpr + +namespace VExpr + +@[simp] theorem bvarRevRange_length : ∀ (off m : Nat), + (bvarRevRange off m).length = m + | _, 0 => rfl + | off, m+1 => by simp [bvarRevRange, bvarRevRange_length off m] + +end VExpr + +/-- Extending a `HeadConstN` spine by an application spine. -/ +theorem HeadConstN.appN {c : Name} {ls : List VLevel} : + ∀ (as : List VExpr) {n : Nat} {f : VExpr}, HeadConstN c ls n f → + HeadConstN c ls (n + as.length) (VExpr.appN f as) + | [], _, _, h => h + | a :: as, n, f, h => by + have := HeadConstN.appN as (h.app (a := a)) + show HeadConstN c ls (n + (as.length + 1)) (VExpr.appN (f.app a) as) + rwa [(by omega : n + (as.length + 1) = n + 1 + as.length)] + +namespace VInductDecl + +/-! ## Positional facts about the checked pairings -/ + +theorem pairNormalizedFamilies_getElem? : + ∀ (raws : List VInductiveType) (views : List CheckedFamilyData) (t : Nat) + {family : NormalizedFamily}, + (pairNormalizedFamilies raws views)[t]? = some family → + raws[t]? = some family.raw ∧ views[t]? = some family.view + | raw :: raws, view :: views, 0, family => by + intro h + cases h + exact ⟨rfl, rfl⟩ + | raw :: raws, view :: views, t+1, family => by + intro h + simpa using pairNormalizedFamilies_getElem? raws views t + (by simpa [pairNormalizedFamilies] using h) + | [], _, t, _ => by intro h; simp [pairNormalizedFamilies] at h + | _ :: _, [], t, _ => by intro h; simp [pairNormalizedFamilies] at h + +theorem pairNormalizedCtors_getElem? : + ∀ (raws : List VConstVal) (views : List CheckedCtor) (t : Nat) + {ctor : NormalizedCtor}, + (pairNormalizedCtors raws views)[t]? = some ctor → + raws[t]? = some ctor.raw ∧ views[t]? = some ctor.view + | raw :: raws, view :: views, 0, ctor => by + intro h + cases h + exact ⟨rfl, rfl⟩ + | raw :: raws, view :: views, t+1, ctor => by + intro h + simpa using pairNormalizedCtors_getElem? raws views t + (by simpa [pairNormalizedCtors] using h) + | [], _, t, _ => by intro h; simp [pairNormalizedCtors] at h + | _ :: _, [], t, _ => by intro h; simp [pairNormalizedCtors] at h + +/-- The erased family-data spine reads back its exact member facts: ordinal +consecutiveness, the indexing family, the analyzer equations, and the +per-family acceptance bit. -/ +theorem CheckedFamilies.data_getElem? {source : VInductDecl} {params : List VExpr} : + ∀ {ord : Nat} {types : List VInductiveType} + (fs : CheckedFamilies source params ord types) (t : Nat) + {fd : CheckedFamilyData}, + fs.data[t]? = some fd → + ∃ type, types[t]? = some type ∧ fd.ordinal = ord + t ∧ fd.value = type ∧ + fd.indices = ctorFields (VExpr.dropN source.nparams type.type) ∧ + fd.constructors = type.ctors.map (CheckedCtor.ofBlock source) ∧ + blockFamilyCore source params (ord + t) type = true + | _, _, .nil, t, fd => by intro h; simp [CheckedFamilies.data] at h + | ord, _, .cons head tail, 0, fd => by + intro h + cases h + exact ⟨_, rfl, rfl, rfl, head.indices_eq, head.constructors_eq, head.accepted⟩ + | ord, _, .cons head tail, t+1, fd => by + intro h + obtain ⟨type, h1, h2, h3, h4, h5, h6⟩ := + CheckedFamilies.data_getElem? tail t (by simpa [CheckedFamilies.data] using h) + exact ⟨type, by simpa using h1, by omega, h3, h4, h5, + by rw [(by omega : ord + (t + 1) = ord + 1 + t)]; exact h6⟩ + +/-! ## Arity extraction from the analyzer's terminal target check -/ + +theorem blockTarget?_loop_length {U np j : Nat} {names : List Name} + {head : VExpr} {args : List VExpr} : + ∀ (headers : List FamilyHeader) (t : Nat) {target : Nat} {idxs : List VExpr}, + blockTarget?.loop U np j names head args t headers = some (target, idxs) → + t ≤ target ∧ ∃ header, headers[target - t]? = some header ∧ + args.length = np + header.indices ∧ idxs = args.drop np + | [], t, target, idxs => by intro h; simp [blockTarget?.loop] at h + | header :: headers, t, target, idxs => by + intro h + rw [blockTarget?.loop] at h + split at h + · rename_i hcond + cases h + simp only [Bool.and_eq_true, beq_iff_eq] at hcond + exact ⟨Nat.le_refl _, header, by simp, hcond.1.1.2, rfl⟩ + · obtain ⟨hle, header', h1, h2, h3⟩ := + blockTarget?_loop_length headers (t+1) h + refine ⟨Nat.le_of_succ_le hle, header', ?_, h2, h3⟩ + rw [(by omega : target - t = (target - (t+1)) + 1)] + simpa using h1 + +/-- A successful mutual target recognition pins the target's index arity to +its family header. -/ +theorem blockTarget?_length {U np j : Nat} {headers : List FamilyHeader} + {names : List Name} {B : VExpr} {target : Nat} {idxs : List VExpr} + (h : blockTarget? U np j headers names B = some (target, idxs)) : + ∃ header, headers[target]? = some header ∧ + (VExpr.appArgs B []).length = np + header.indices ∧ + idxs = (VExpr.appArgs B []).drop np := by + rw [blockTarget?] at h + obtain ⟨hle, header, h1, h2, h3⟩ := blockTarget?_loop_length headers 0 h + exact ⟨header, by simpa using h1, h2, h3⟩ + +/-- The terminal of an accepted mutual constructor shape is a successful +`blockTarget?` recognition of the owner family, past all fields. -/ +theorem blockStage3Ctor_result {U np : Nat} {headers : List FamilyHeader} + {names : List Name} {owner : Nat} : + ∀ (B : VExpr) (j : Nat), blockStage3Ctor U np headers names owner j B = true → + ∃ idxs, blockTarget? U np (j + (ctorFields B).length) headers names + (VExpr.resultOf B) = some (owner, idxs) := by + intro B + induction B with + (intro j h + simp only [blockStage3Ctor] at h + try (split at h + · rename_i target idxs heq + refine ⟨idxs, ?_⟩ + simp only [ctorFields, List.length_nil, Nat.add_zero, VExpr.resultOf] + rwa [(by simpa using h : target = owner)] at heq + · cases h)) + | forallE A rest _ ihR => + rw [Bool.and_eq_true] at h + obtain ⟨-, h2⟩ := h + obtain ⟨idxs, hidx⟩ := ihR (j+1) h2 + refine ⟨idxs, ?_⟩ + simp only [ctorFields, List.length_cons, VExpr.resultOf] + rwa [(by omega : j + ((ctorFields rest).length + 1) = j + 1 + (ctorFields rest).length)] + +/-! ## Name transport across the normalization boundary -/ + +theorem sameCtorHeaders_names : ∀ {cs cs' : List VConstVal}, + sameCtorHeaders cs cs' = true → cs.map (·.name) = cs'.map (·.name) + | [], [], _ => rfl + | c :: cs, c' :: cs', h => by + simp only [sameCtorHeaders, Bool.and_eq_true, beq_iff_eq] at h + simp only [List.map_cons, h.1.1, sameCtorHeaders_names h.2] + | [], _ :: _, h => by simp [sameCtorHeaders] at h + | _ :: _, [], h => by simp [sameCtorHeaders] at h + +theorem sameTypeHeaders_names : ∀ {tys tys' : List VInductiveType}, + sameTypeHeaders tys tys' = true → + tys.map (·.name) = tys'.map (·.name) ∧ + tys.flatMap (fun ty => ty.ctors.map (·.name)) = + tys'.flatMap (fun ty => ty.ctors.map (·.name)) + | [], [], _ => ⟨rfl, rfl⟩ + | ty :: tys, ty' :: tys', h => by + simp only [sameTypeHeaders, Bool.and_eq_true, beq_iff_eq] at h + have ih := sameTypeHeaders_names h.2 + simp only [List.map_cons, List.flatMap_cons, h.1.1.1, ih.1, ih.2, + sameCtorHeaders_names h.1.2, and_self] + | [], _ :: _, h => by simp [sameTypeHeaders] at h + | _ :: _, [], h => by simp [sameTypeHeaders] at h + +/-- The reserved generated names are unchanged by normalization: they are +computed from family and constructor identities only. -/ +theorem blockGeneratedNames_eq_of_sameTypeHeaders + {tys tys' : List VInductiveType} (h : sameTypeHeaders tys tys' = true) : + blockGeneratedNames tys = blockGeneratedNames tys' := by + obtain ⟨h1, h2⟩ := sameTypeHeaders_names h + have h3 : tys.map (fun ty => (.str ty.name "rec" : Name)) = + tys'.map (fun ty => (.str ty.name "rec" : Name)) := by + have := congrArg (List.map (fun n => (.str n "rec" : Name))) h1 + simpa [List.map_map, Function.comp_def] using this + simp only [blockGeneratedNames, h1, h2, h3] + +namespace BlockGenerationChecked + +variable {source : VInductDecl} (gen : source.BlockGenerationChecked) + +/-! ## Inventory facts from the certified block -/ + +include gen in +/-- The reserved generated names of the raw source are collision-free: the +analyzer certifies the view's inventory, and normalization retains every +identity. -/ +theorem blockGeneratedNames_nodup : + (blockGeneratedNames source.types).Nodup := by + have hshape := gen.block.normalization.shape_eq + simp only [normalizationShape, Bool.and_eq_true, beq_iff_eq] at hshape + rw [blockGeneratedNames_eq_of_sameTypeHeaders hshape.2] + have h := gen.block.checked.names_nodup + rwa [gen.block.checked.names_eq] at h + +/-! ## Named components of one generated iota rule -/ + +/-- Field count of one flattened constructor, as bound by its iota rule. -/ +def ruleFieldCount (constructor : NormalizedBlockCtor) : Nat := + (constructor.ctor.fieldsR source.uvars source.nparams gen.elimination).length + +/-- The result-index spine of one iota rule body, in the rule's binder +context. -/ +def ruleIdx (constructor : NormalizedBlockCtor) : List VExpr := + constructor.ctor.resultIndicesR source.uvars gen.elimination |>.map + fun e => e.liftN (gen.familyCount + gen.minorCount) + (gen.ruleFieldCount constructor) + +/-- The binder telescope shared by both towers of one iota rule. -/ +def ruleBinders (constructor : NormalizedBlockCtor) : List VExpr := + gen.paramsTel ++ gen.motiveTypes ++ gen.minorTypes ++ + VExpr.liftTelN (gen.familyCount + gen.minorCount) + (constructor.ctor.fieldsR source.uvars source.nparams gen.elimination) 0 + +/-- The constructor-headed major premise of one iota rule body. -/ +def ruleCtorApp (constructor : NormalizedBlockCtor) : VExpr := + VExpr.appN (.const constructor.ctor.raw.name gen.sourceLevels) + (VExpr.bvarRevRange + (gen.ruleFieldCount constructor + (gen.familyCount + gen.minorCount)) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.ruleFieldCount constructor)) + +/-- The exact left body of one generated iota rule: the owner's recursor +applied to the common arguments, the constructor's result indices, and the +constructor-headed major premise. -/ +def ruleLhsBody (constructor : NormalizedBlockCtor) : VExpr := + VExpr.appN (gen.recBase (gen.ruleFieldCount constructor) constructor.owner) + (gen.ruleIdx constructor ++ [gen.ruleCtorApp constructor]) + +/-- The generated rule's left side is exactly the shared binder telescope +over the `SimplePattern.iota` spine. -/ +theorem rule_lhs (i : Nat) (constructor : NormalizedBlockCtor) : + (gen.rule i constructor).lhs = + VExpr.lamN (gen.ruleBinders constructor) (gen.ruleLhsBody constructor) := rfl + +/-! ## The pattern of one generated iota rule -/ + +/-- The recursor constant owning one flattened constructor's iota rule. -/ +def ruleRecName (constructor : NormalizedBlockCtor) : Name := + .str (gen.familyNameAt constructor.owner) "rec" + +/-- Major-argument arity of one iota rule: shared parameters, all motives, +all minors, and the constructor's result indices. -/ +def ruleMajorArity (constructor : NormalizedBlockCtor) : Nat := + source.nparams + gen.familyCount + gen.minorCount + + (constructor.ctor.resultIndicesR source.uvars gen.elimination).length + +/-- Argument arity of one iota rule's constructor-headed major premise. -/ +def ruleArgArity (constructor : NormalizedBlockCtor) : Nat := + source.nparams + gen.ruleFieldCount constructor + +/-- The `SimplePattern` of one generated iota rule. -/ +@[reducible] def rulePattern (constructor : NormalizedBlockCtor) : SimplePattern := + .iota (gen.ruleRecName constructor) (gen.ruleMajorArity constructor) + constructor.ctor.raw.name (gen.ruleArgArity constructor) + +/-- The generated left body is matched by the rule's pattern, at exactly the +rule's recursor levels. -/ +theorem ruleLhsBody_matches (constructor : NormalizedBlockCtor) : + ∃ m2, ((gen.rulePattern constructor).toPattern).Matches + (gen.ruleLhsBody constructor) gen.recLevels m2 := by + rw [rulePattern, SimplePattern.toPattern_iota] + have hleft : HeadConstN (gen.ruleRecName constructor) gen.recLevels + (gen.ruleMajorArity constructor) + (VExpr.appN (gen.recBase (gen.ruleFieldCount constructor) constructor.owner) + (gen.ruleIdx constructor)) := by + have h0 : HeadConstN (gen.ruleRecName constructor) gen.recLevels 0 + (.const (gen.ruleRecName constructor) gen.recLevels) := .const + have h1 := (h0.appN (VExpr.bvarRevRange (gen.ruleFieldCount constructor) + (source.nparams + gen.familyCount + gen.minorCount))) + have h2 := h1.appN (as := gen.ruleIdx constructor) + rw [VExpr.bvarRevRange_length] at h2 + have harity : 0 + (source.nparams + gen.familyCount + gen.minorCount) + + (gen.ruleIdx constructor).length = gen.ruleMajorArity constructor := by + simp only [ruleIdx, ruleMajorArity, List.length_map]; omega + rwa [harity] at h2 + have hright : HeadConstN constructor.ctor.raw.name gen.sourceLevels + (gen.ruleArgArity constructor) (gen.ruleCtorApp constructor) := by + have h0 : HeadConstN constructor.ctor.raw.name gen.sourceLevels 0 + (.const constructor.ctor.raw.name gen.sourceLevels) := .const + have h1 := h0.appN (as := VExpr.bvarRevRange + (gen.ruleFieldCount constructor + (gen.familyCount + gen.minorCount)) + source.nparams ++ VExpr.bvarRevRange 0 (gen.ruleFieldCount constructor)) + rw [List.length_append, VExpr.bvarRevRange_length, VExpr.bvarRevRange_length] at h1 + have harity : 0 + (source.nparams + gen.ruleFieldCount constructor) = + gen.ruleArgArity constructor := by simp only [ruleArgArity]; omega + rwa [harity] at h1 + have hbody : gen.ruleLhsBody constructor = + .app (VExpr.appN (gen.recBase (gen.ruleFieldCount constructor) constructor.owner) + (gen.ruleIdx constructor)) + (gen.ruleCtorApp constructor) := by + rw [ruleLhsBody, VExpr.appN_append] + rfl + rw [hbody] + exact RecursorIotaPattern.matches_of hleft hright + +/-! ## Positional anatomy of the flattened constructors -/ + +/-- The checked spine assigns family ordinals positionally. -/ +theorem families_getElem?_ordinal {t : Nat} {family : NormalizedFamily} + (h : gen.families[t]? = some family) : family.view.ordinal = t := by + have h' : (pairNormalizedFamilies source.types + gen.block.checked.families.data)[t]? = some family := h + obtain ⟨-, hview⟩ := pairNormalizedFamilies_getElem? _ _ t h' + obtain ⟨type, -, hord, -, -, -, -⟩ := CheckedFamilies.data_getElem? _ t hview + simpa using hord + +/-- Position `t` of the paired family list is the `t`-th source family. -/ +theorem families_getElem?_raw {t : Nat} {family : NormalizedFamily} + (h : gen.families[t]? = some family) : source.types[t]? = some family.raw := + (pairNormalizedFamilies_getElem? source.types + gen.block.checked.families.data t h).1 + +/-- A family lookup names the owning recursor's family. -/ +theorem familyNameAt_eq {t : Nat} {family : NormalizedFamily} + (h : gen.families[t]? = some family) : + gen.familyNameAt t = family.raw.name := by + simp [familyNameAt, h] + +/-- One flattened constructor decomposes into its owner family lookup and +its position inside that family's pairing. -/ +theorem flatCtors_anatomy {constructor : NormalizedBlockCtor} + (hc : constructor ∈ gen.flatCtors) : + ∃ t family, gen.families[t]? = some family ∧ + constructor.owner = t ∧ + constructor.familyName = family.raw.name ∧ + constructor.familyIndices = family.view.indices ∧ + constructor.ctor ∈ family.ctorPairs := by + have hc' : constructor ∈ gen.families.flatMap (·.blockCtors) := hc + rw [List.mem_flatMap] at hc' + obtain ⟨family, hfamily, hmem⟩ := hc' + obtain ⟨t, ht⟩ := List.mem_iff_getElem?.1 hfamily + simp only [NormalizedFamily.blockCtors, List.mem_map] at hmem + obtain ⟨ctor, hctor, rfl⟩ := hmem + exact ⟨t, family, ht, gen.families_getElem?_ordinal ht, rfl, rfl, hctor⟩ + +/-! ## The analyzer's arity equation for pattern majors -/ + +/-- Every flattened constructor's checked result-index spine has exactly its +owner family's index arity: the analyzer's terminal `blockTarget?` equation +transports through the checked spine. -/ +theorem view_resultIndices_length {constructor : NormalizedBlockCtor} + (hc : constructor ∈ gen.flatCtors) : + constructor.ctor.view.resultIndices.length = + constructor.familyIndices.length := by + obtain ⟨t, family, ht, -, -, hindices, hmem⟩ := gen.flatCtors_anatomy hc + have ht' : (pairNormalizedFamilies source.types + gen.block.checked.families.data)[t]? = some family := ht + obtain ⟨-, hview⟩ := pairNormalizedFamilies_getElem? _ _ t ht' + obtain ⟨vtype, hvty, -, -, hvindices, hvctors, hvcore⟩ := + CheckedFamilies.data_getElem? _ t hview + rw [Nat.zero_add] at hvcore + obtain ⟨s, hs⟩ := List.mem_iff_getElem?.1 hmem + have hs' : (pairNormalizedCtors family.raw.ctors + family.view.constructors)[s]? = some constructor.ctor := hs + obtain ⟨-, hviewCtor⟩ := pairNormalizedCtors_getElem? _ _ s hs' + rw [hvctors, List.getElem?_map] at hviewCtor + obtain ⟨c₀, hc₀, hview_eq⟩ : ∃ c₀, vtype.ctors[s]? = some c₀ ∧ + CheckedCtor.ofBlock _ c₀ = constructor.ctor.view := by + cases h0 : vtype.ctors[s]? with + | none => rw [h0] at hviewCtor; cases hviewCtor + | some c₀ => rw [h0] at hviewCtor; exact ⟨c₀, rfl, by simpa using hviewCtor⟩ + simp only [blockFamilyCore, Bool.and_eq_true, beq_iff_eq, + List.all_eq_true] at hvcore + have hstage := (hvcore.2 c₀ (List.mem_of_getElem? hc₀)).2 + obtain ⟨idxs, htarget⟩ := blockStage3Ctor_result _ 0 hstage + obtain ⟨header, hheader, hlen, -⟩ := blockTarget?_length htarget + rw [familyHeaders, List.getElem?_map, hvty, Option.map_some] at hheader + have hri : constructor.ctor.view.resultIndices = + (VExpr.appArgs (VExpr.resultOf (VExpr.dropN + gen.block.normalization.view.nparams c₀.type)) []).drop + gen.block.normalization.view.nparams := by + rw [← hview_eq]; rfl + rw [hri, hindices, hvindices, List.length_drop, hlen] + cases hheader + show gen.block.normalization.view.nparams + + (ctorFields (VExpr.dropN gen.block.normalization.view.nparams + vtype.type)).length - + gen.block.normalization.view.nparams = + (ctorFields (VExpr.dropN gen.block.normalization.view.nparams + vtype.type)).length + omega + +/-- Pattern major arity through the owner family's index count. -/ +theorem ruleMajorArity_eq {constructor : NormalizedBlockCtor} + (hc : constructor ∈ gen.flatCtors) : + gen.ruleMajorArity constructor = + source.nparams + gen.familyCount + gen.minorCount + + constructor.familyIndices.length := by + simp only [ruleMajorArity, NormalizedCtor.resultIndicesR, List.length_map, + gen.view_resultIndices_length hc] + +/-! ## Name freshness of the generated inventory -/ + +include gen in +private theorem nodup_parts : + (source.types.map (·.name)).Nodup ∧ + (source.types.flatMap fun ty => ty.ctors.map (·.name)).Nodup ∧ + ∀ a ∈ (source.types.flatMap fun ty => ty.ctors.map (·.name)), + ∀ b ∈ source.types.map (fun ty => (.str ty.name "rec" : Name)), a ≠ b := by + have h := gen.blockGeneratedNames_nodup + rw [blockGeneratedNames, List.nodup_append] at h + obtain ⟨hAB, -, hdisj⟩ := h + rw [List.nodup_append] at hAB + exact ⟨hAB.1, hAB.2.1, fun a ha b hb => + hdisj a (List.mem_append.2 (.inr ha)) b hb⟩ + +/-- Family positions are recoverable from raw family names. -/ +theorem families_name_inj {t t' : Nat} {family family' : NormalizedFamily} + (h : gen.families[t]? = some family) (h' : gen.families[t']? = some family') + (hname : family.raw.name = family'.raw.name) : t = t' := by + have h1 := gen.families_getElem?_raw h + have h1' := gen.families_getElem?_raw h' + have hm : (source.types.map (·.name))[t]? = some family.raw.name := by + rw [List.getElem?_map, h1, Option.map_some] + have hm' : (source.types.map (·.name))[t']? = some family.raw.name := by + rw [List.getElem?_map, h1', Option.map_some, hname] + obtain ⟨hlt, -⟩ := List.getElem?_eq_some_iff.1 hm + exact (List.getElem?_inj hlt gen.nodup_parts.1).1 (hm.trans hm'.symm) + +/-- Flattened positions are recoverable from raw constructor names. -/ +theorem flatCtors_name_inj {i i' : Nat} {c c' : NormalizedBlockCtor} + (h : gen.flatCtors[i]? = some c) (h' : gen.flatCtors[i']? = some c') + (hname : c.ctor.raw.name = c'.ctor.raw.name) : i = i' ∧ c = c' := by + have hnodup : ((source.blockConstructorConstants).map (·.name)).Nodup := by + rw [VInductDecl.blockConstructorConstants, List.map_flatMap] + exact gen.nodup_parts.2.1 + have hm : ((source.blockConstructorConstants).map (·.name))[i]? = + some c.ctor.raw.name := by + rw [List.getElem?_map, ← gen.flatCtors_map_raw, List.getElem?_map, h] + rfl + have hm' : ((source.blockConstructorConstants).map (·.name))[i']? = + some c.ctor.raw.name := by + rw [List.getElem?_map, ← gen.flatCtors_map_raw, List.getElem?_map, h', + hname] + rfl + obtain ⟨hlt, -⟩ := List.getElem?_eq_some_iff.1 hm + have hii : i = i' := (List.getElem?_inj hlt hnodup).1 (hm.trans hm'.symm) + subst hii + exact ⟨rfl, Option.some.inj (h.symm.trans h')⟩ + +/-- No family's recursor name collides with any flattened constructor's +name. -/ +theorem recName_ne_ctorName {family : NormalizedFamily} + (hfam : family ∈ gen.families) {constructor : NormalizedBlockCtor} + (hc : constructor ∈ gen.flatCtors) : + (.str family.raw.name "rec" : Name) ≠ constructor.ctor.raw.name := by + have hmemC : constructor.ctor.raw.name ∈ + source.types.flatMap fun ty => ty.ctors.map (·.name) := by + have h1 : constructor.ctor.raw ∈ source.blockConstructorConstants := by + rw [← gen.flatCtors_map_raw] + exact List.mem_map_of_mem hc + rw [VInductDecl.blockConstructorConstants, List.mem_flatMap] at h1 + obtain ⟨ty, hty, hmem⟩ := h1 + rw [List.mem_flatMap] + exact ⟨ty, hty, List.mem_map_of_mem hmem⟩ + have hmemR : (.str family.raw.name "rec" : Name) ∈ + source.types.map (fun ty => (.str ty.name "rec" : Name)) := by + have h1 : family.raw ∈ source.types := by + rw [← gen.families_map_raw] + exact List.mem_map_of_mem hfam + exact List.mem_map_of_mem h1 + intro heq + exact gen.nodup_parts.2.2 _ hmemC _ hmemR heq.symm + +/-- Two flattened constructors with the same owning recursor name share +their owner and their family's index telescope. -/ +theorem ruleRecName_inj {c c' : NormalizedBlockCtor} + (hc : c ∈ gen.flatCtors) (hc' : c' ∈ gen.flatCtors) + (h : gen.ruleRecName c = gen.ruleRecName c') : + c.owner = c'.owner ∧ c.familyIndices = c'.familyIndices := by + obtain ⟨t, family, ht, ho, -, hi, -⟩ := gen.flatCtors_anatomy hc + obtain ⟨t', family', ht', ho', -, hi', -⟩ := gen.flatCtors_anatomy hc' + rw [ruleRecName, ruleRecName, ho, ho', gen.familyNameAt_eq ht, + gen.familyNameAt_eq ht'] at h + have hnames : family.raw.name = family'.raw.name := by + injection h with h1 h2 + have ht2 : t = t' := gen.families_name_inj ht ht' hnames + subst ht2 + cases Option.some.inj (ht.symm.trans ht') + exact ⟨ho.trans ho'.symm, hi.trans hi'.symm⟩ + +/-- Rule distinctness: distinct flattened positions carry distinct +patterns. -/ +theorem rulePattern_inj {i i' : Nat} {c c' : NormalizedBlockCtor} + (h : gen.flatCtors[i]? = some c) (h' : gen.flatCtors[i']? = some c') + (heq : gen.rulePattern c = gen.rulePattern c') : i = i' ∧ c = c' := by + injection heq with h1 h2 h3 h4 + exact gen.flatCtors_name_inj h h' h3 + +/-! ## Rule payloads: RHS templates and agreement checks -/ + +/-- Closedness inputs for one certified block's rule payloads: the towers a +rule's RHS template and checks embed as fixed template constants. Concrete +fixtures discharge this bundle by `decide`; the pattern-soundness milestone +derives it from the staged environment's rule well-formedness. -/ +structure RuleClosure : Prop where + rhs_closed : ∀ ⦃i : Nat⦄ ⦃constructor : NormalizedBlockCtor⦄, + gen.flatCtors[i]? = some constructor → + ((gen.rule i constructor).rhs).ClosedN 0 + idxTower_closed : ∀ ⦃constructor : NormalizedBlockCtor⦄, + constructor ∈ gen.flatCtors → ∀ e ∈ gen.ruleIdx constructor, + (VExpr.lamN (gen.ruleBinders constructor) e).ClosedN 0 + +/-- The template capture list shared by every payload tower: the recursor +side's parameters, motives, and minors, then the major premise's fields. -/ +def captureArgs (constructor : NormalizedBlockCtor) : + List (((gen.rulePattern constructor).toPattern).RHS) := + ((Pattern.varNPaths (.const (gen.ruleRecName constructor)) + (gen.ruleMajorArity constructor)).take + (source.nparams + gen.familyCount + gen.minorCount)).map + (fun path => .var (.inl path)) ++ + ((Pattern.varNPaths (.const constructor.ctor.raw.name) + (gen.ruleArgArity constructor)).drop source.nparams).map + (fun path => .var (.inr path)) + +/-- The RHS template of one rule: the registered right tower applied to the +captured common arguments and fields. -/ +def ruleRHS (hcl : gen.RuleClosure) {i : Nat} {constructor : NormalizedBlockCtor} + (h : gen.flatCtors[i]? = some constructor) : + ((gen.rulePattern constructor).toPattern).RHS := + Pattern.RHS.appN (.fixed ((gen.rule i constructor).rhs) (hcl.rhs_closed h)) + (gen.captureArgs constructor) + +/-- The check list of one rule: the major premise's parameters must agree +with the recursor side's parameters, and the recursor side's index arguments +must agree with the constructor's computed result indices (as fixed index +towers applied to the captures). -/ +def ruleCheck (hcl : gen.RuleClosure) {constructor : NormalizedBlockCtor} + (hc : constructor ∈ gen.flatCtors) : + ((gen.rulePattern constructor).toPattern).Check := + let recPaths := Pattern.varNPaths (.const (gen.ruleRecName constructor)) + (gen.ruleMajorArity constructor) + let ctorPaths := Pattern.varNPaths (.const constructor.ctor.raw.name) + (gen.ruleArgArity constructor) + let common := source.nparams + gen.familyCount + gen.minorCount + let idxChecks := + ((gen.ruleIdx constructor).attach.zip (recPaths.drop common)).foldr + (fun ep rest => + .defeq (.var (.inl ep.2)) + (Pattern.RHS.appN + (.fixed (VExpr.lamN (gen.ruleBinders constructor) ep.1.1) + (hcl.idxTower_closed hc ep.1.1 ep.1.2)) + (gen.captureArgs constructor)) rest) + .true + ((ctorPaths.take source.nparams).zip (recPaths.take source.nparams)).foldr + (fun pr rest => .defeq (.var (.inr pr.1)) (.var (.inl pr.2)) rest) + idxChecks + +/-- Position `i` of the certified block's flattened constructor list. -/ +abbrev ruleEntry (i : Nat) (constructor : NormalizedBlockCtor) : Prop := + gen.flatCtors[i]? = some constructor + +/-- A decidable sufficient condition for `RuleClosure`, discharging concrete +fixtures by evaluation. -/ +theorem RuleClosure.of_all + (h1 : gen.flatCtors.zipIdx.all (fun ic => + decide (((gen.rule ic.2 ic.1).rhs).ClosedN 0)) = true) + (h2 : gen.flatCtors.all (fun c => (gen.ruleIdx c).all fun e => + decide ((VExpr.lamN (gen.ruleBinders c) e).ClosedN 0)) = true) : + gen.RuleClosure := by + constructor + · intro i constructor h + have hmem : (constructor, i) ∈ gen.flatCtors.zipIdx := by + apply List.mem_of_getElem? (i := i) + rw [List.getElem?_zipIdx, h, Option.map_some, Nat.zero_add] + exact of_decide_eq_true (List.all_eq_true.1 h1 _ hmem) + · intro constructor hc e he + exact of_decide_eq_true (List.all_eq_true.1 (List.all_eq_true.1 h2 _ hc) _ he) + +/-- The pattern set of one certified block: each flattened constructor's +rule pattern with its template and checks. -/ +inductive IotaPat (hcl : gen.RuleClosure) : + (p : Pattern) → p.RHS × p.Check → Prop where + | mk {i : Nat} {constructor : NormalizedBlockCtor} + (h : gen.ruleEntry i constructor) : + IotaPat hcl ((gen.rulePattern constructor).toPattern) + (gen.ruleRHS hcl h, gen.ruleCheck hcl (List.mem_of_getElem? h)) + +/-! ## The `Params` obligations for one certified block -/ + +/-- `Params.pat_simple` for the block's pattern set. -/ +theorem IotaPat.pat_simple {hcl : gen.RuleClosure} {p : Pattern} + {r : p.RHS × p.Check} (H : gen.IotaPat hcl p r) : + ∃ sp : SimplePattern, p = sp.toPattern := by + cases H with | mk h => exact ⟨_, rfl⟩ + +/-- Rule recovery: a pattern in the block's set determines its flattened +rule position and constructor. -/ +theorem IotaPat.recover {hcl : gen.RuleClosure} {p : Pattern} + {r : p.RHS × p.Check} (H : gen.IotaPat hcl p r) : + ∃ (i : Nat) (constructor : NormalizedBlockCtor), + gen.flatCtors[i]? = some constructor ∧ + p = (gen.rulePattern constructor).toPattern ∧ + ∀ (i' : Nat) (constructor' : NormalizedBlockCtor), + gen.flatCtors[i']? = some constructor' → + (gen.rulePattern constructor').toPattern = p → + i' = i ∧ constructor' = constructor := by + cases H with | @mk i constructor h => + refine ⟨i, constructor, h, rfl, ?_⟩ + intro i' constructor' h' heq + have := RecursorIotaPattern.inj heq + exact gen.flatCtors_name_inj h' h this.2.2.1 + +/-- `Params.pat_uniq` for the block's pattern set. -/ +theorem IotaPat.pat_uniq {hcl : gen.RuleClosure} {p₁ p₂ p₃ p₄ : Pattern} + {r : p₁.RHS × p₁.Check} {r' : p₂.RHS × p₂.Check} + (H1 : gen.IotaPat hcl p₁ r) (H2 : gen.IotaPat hcl p₂ r') + (H3 : Subpattern p₃ p₁) (H4 : p₂.inter p₃ = some p₄) : + p₁ = p₂ ∧ p₂ = p₃ ∧ r ≍ r' := by + cases H1 with | @mk i c h => + cases H2 with | @mk i' c' h' => + rcases RecursorIotaPattern.subpattern_inv H3 with rfl | ⟨j, hj, rfl⟩ | ⟨j, hj, rfl⟩ + · obtain ⟨hR, hM, hC, hN, rfl⟩ := RecursorIotaPattern.inter_some H4 + obtain ⟨rfl, rfl⟩ := gen.flatCtors_name_inj h' h hC + exact ⟨rfl, rfl, HEq.rfl⟩ + · obtain ⟨hb, hj'⟩ := RecursorIotaPattern.inter_varN_const_some H4 + obtain ⟨-, hIdx⟩ := gen.ruleRecName_inj (List.mem_of_getElem? h) + (List.mem_of_getElem? h') hb + have hM : gen.ruleMajorArity c' = gen.ruleMajorArity c := by + rw [gen.ruleMajorArity_eq (List.mem_of_getElem? h'), + gen.ruleMajorArity_eq (List.mem_of_getElem? h), hIdx] + omega + · obtain ⟨hb, -⟩ := RecursorIotaPattern.inter_varN_const_some H4 + obtain ⟨t', family', ht', ho', -, -, -⟩ := + gen.flatCtors_anatomy (List.mem_of_getElem? h') + have hrec : gen.ruleRecName c' = (.str family'.raw.name "rec" : Name) := by + rw [ruleRecName, ho', gen.familyNameAt_eq ht'] + refine absurd ?_ (gen.recName_ne_ctorName (List.mem_of_getElem? ht') + (List.mem_of_getElem? h)) + rw [← hrec, hb] + +/-- `Params.pat_app_l` for the block's pattern set. -/ +theorem IotaPat.pat_app_l {hcl : gen.RuleClosure} {p : Pattern} + {r : p.RHS × p.Check} {p₁ p₂ p₃ p₄ : Pattern} + (H : gen.IotaPat hcl p r) (h : Subpattern (.app p₁ p₂) p) : + ¬Subpattern (.app p₃ p₄) p₁ := by + cases H with | @mk i c hi => + obtain ⟨rfl, -⟩ := RecursorIotaPattern.app_subpattern h + intro hsub + obtain ⟨j', hj', heq'⟩ := hsub.varN_const_le + cases j' <;> exact absurd heq' (by simp [Pattern.varN]) + +/-- `Params.pat_app_l_uniq` for the block's pattern set. -/ +theorem IotaPat.pat_app_l_uniq {hcl : gen.RuleClosure} {p p' : Pattern} + {r : p.RHS × p.Check} {r' : p'.RHS × p'.Check} {p₁ p₂ p₁' p₂' p₃ : Pattern} + (H : gen.IotaPat hcl p r) (H' : gen.IotaPat hcl p' r') + (h : Subpattern (.app p₁ p₂) p) (h' : Subpattern (.app p₁' p₂') p') + (h₃ : Subpattern (.var p₃) p₁) : p₁'.inter p₃ = none := by + cases H with | @mk i c hi => + cases H' with | @mk i' c' hi' => + obtain ⟨rfl, -⟩ := RecursorIotaPattern.app_subpattern h + obtain ⟨rfl, -⟩ := RecursorIotaPattern.app_subpattern h' + obtain ⟨j, hj, heq⟩ := h₃.varN_const_le + cases j with + | zero => exact absurd heq (by simp [Pattern.varN]) + | succ j'' => + rw [show Pattern.varN (.const (gen.ruleRecName c)) (j'' + 1) = + .var (Pattern.varN (.const (gen.ruleRecName c)) j'') from rfl] at heq + injection heq with heq' + subst heq' + by_cases hname : gen.ruleRecName c' = gen.ruleRecName c + · obtain ⟨-, hIdx⟩ := gen.ruleRecName_inj (List.mem_of_getElem? hi') + (List.mem_of_getElem? hi) hname + have hM : gen.ruleMajorArity c' = gen.ruleMajorArity c := by + rw [gen.ruleMajorArity_eq (List.mem_of_getElem? hi'), + gen.ruleMajorArity_eq (List.mem_of_getElem? hi), hIdx] + rw [hname] + exact Pattern.varN_const_inter_of_ne_arity (by omega) _ _ + · exact Pattern.varN_const_inter_of_ne_name hname _ _ + +/-- `Params.pat_app_uniq` for the block's pattern set. -/ +theorem IotaPat.pat_app_uniq {hcl : gen.RuleClosure} {p p' : Pattern} + {r : p.RHS × p.Check} {r' : p'.RHS × p'.Check} + {p₁ p₂ p₁' p₂' p₃ p₃' : Pattern} + (H : gen.IotaPat hcl p r) (H' : gen.IotaPat hcl p' r') + (h : Subpattern (.app p₁ p₂) p) (h' : Subpattern (.app p₁' p₂') p') + (h₃ : Subpattern p₃ p₁) (h₃' : Subpattern p₃' p₂') : p₃.inter p₃' = none := by + cases H with | @mk i c hi => + cases H' with | @mk i' c' hi' => + obtain ⟨rfl, -⟩ := RecursorIotaPattern.app_subpattern h + obtain ⟨-, rfl⟩ := RecursorIotaPattern.app_subpattern h' + obtain ⟨j, hj, rfl⟩ := h₃.varN_const_le + obtain ⟨j', hj', rfl⟩ := h₃'.varN_const_le + refine Pattern.varN_const_inter_of_ne_name ?_ _ _ + obtain ⟨t, family, ht, ho, -, -, -⟩ := + gen.flatCtors_anatomy (List.mem_of_getElem? hi) + have hrec : gen.ruleRecName c = (.str family.raw.name "rec" : Name) := by + rw [ruleRecName, ho, gen.familyNameAt_eq ht] + rw [hrec] + exact gen.recName_ne_ctorName (List.mem_of_getElem? ht) + (List.mem_of_getElem? hi') + +/-! ## Axiom closures of the generic pattern facts -/ + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.ruleLhsBody_matches [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.view_resultIndices_length [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.rulePattern_inj [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.IotaPat.pat_simple [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.IotaPat.recover [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.IotaPat.pat_uniq [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.IotaPat.pat_app_l [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.IotaPat.pat_app_l_uniq [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.IotaPat.pat_app_uniq [propext, Quot.sound] + +end BlockGenerationChecked + +end VInductDecl + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Typing/InductivePatternWF.lean b/Ix/Theory/Named/Typing/InductivePatternWF.lean new file mode 100644 index 000000000..d01b7305a --- /dev/null +++ b/Ix/Theory/Named/Typing/InductivePatternWF.lean @@ -0,0 +1,943 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Typing.InductivePattern +import Ix.Theory.Named.Typing.UniqueTyping + +open Ix.Theory (VLevel) + +/-! # Pattern soundness for generated iota rules + +The typed β-collapse layer for Spec-10B: applying a lambda tower to a +well-typed argument spine is definitionally equal to the iterated +instantiation of its body (`IsDefEq.appN_lamN`), applications are +congruent along spines (`IsDefEq.appN_congr`, `IsDefEq.appN_defEq` over +`SpineDefEq`), and a matched pattern's captures are exactly the spine +arguments (`varN_matches_paths`). `pat_wf` then proves that a successful +match whose checks hold is definitionally equal to its RHS template — by +applying the registered `addInduct` rule tower to the captured arguments +and β-collapsing both readings. -/ + +namespace Ix.Theory.Named + +open VExpr + +namespace VExpr + +/-- Instantiation pushes under a lambda telescope, mirroring +`instN_forallN`. -/ +theorem instN_lamN (a : VExpr) : ∀ (tel : List VExpr) (X : VExpr) (k : Nat), + (lamN tel X).inst a k = lamN (instTelN a tel k) (X.inst a (k + tel.length)) + | [], _, _ => rfl + | A :: tel, X, k => by + show VExpr.lam _ _ = VExpr.lam _ _ + rw [instN_lamN a tel X (k+1), + show k+1+tel.length = k+(tel.length+1) from by omega] + rfl + +/-- Universe instantiation pushes under a lambda telescope. -/ +theorem instL_lamN (ls : List VLevel) : ∀ (As : List VExpr) (e : VExpr), + (lamN As e).instL ls = lamN (As.map (instL ls)) (e.instL ls) + | [], _ => rfl + | A :: As, e => by + show VExpr.lam _ _ = VExpr.lam _ _ + rw [instL_lamN ls As e] + +end VExpr + +/-- Matching a constant `varN` tower captures exactly the spine arguments: +the `varNPaths` read back the argument list. -/ +theorem Pattern.varN_matches_paths {c : Name} {m1 : List VLevel} : + ∀ (n : Nat) (as : List VExpr) {f : VExpr} {m2}, + (Pattern.varN (.const c) n).Matches (VExpr.appN f as) m1 m2 → + as.length = n → + (Pattern.varNPaths (.const c) n).map m2 = as := by + intro n + induction n with + | zero => + intro as f m2 H hlen + obtain rfl : as = [] := List.length_eq_zero_iff.1 hlen + rfl + | succ n ih => + intro as f m2 H hlen + have hne : as ≠ [] := by rintro rfl; simp at hlen + obtain ⟨as', a, rfl⟩ : ∃ as' a, as = as' ++ [a] := + ⟨as.dropLast, as.getLast hne, (List.dropLast_concat_getLast hne).symm⟩ + rw [VExpr.appN_append] at H + have has : as'.length = n := by simpa using hlen + cases H with + | var h => + show ((Pattern.varNPaths (.const c) n).map some ++ [none]).map _ = + as' ++ [a] + rw [List.map_append, List.map_map] + exact congrArg (· ++ [a]) (ih as' h has) + +/-- Applying an RHS template spine computes to the applied template +values. -/ +theorem Pattern.RHS.appN_apply {p : Pattern} (m1 : List VLevel) + (m2 : p.Path → VExpr) : + ∀ (f : p.RHS) (as : List (p.RHS)), + (Pattern.RHS.appN f as).apply m1 m2 = + VExpr.appN (f.apply m1 m2) (as.map (Pattern.RHS.apply m1 m2)) + | _, [] => rfl + | f, a :: as => by + show (Pattern.RHS.appN (.app f a) as).apply m1 m2 = _ + rw [Pattern.RHS.appN_apply m1 m2 (.app f a) as] + rfl + +/-- A `HeadConstN` spine names its argument list. -/ +theorem HeadConstN.exists_appN {c : Name} {ls : List VLevel} : + ∀ {n : Nat} {e : VExpr}, HeadConstN c ls n e → + ∃ as : List VExpr, e = VExpr.appN (.const c ls) as ∧ as.length = n + | _, _, .const => ⟨[], rfl, rfl⟩ + | _, _, .app (a := a) h => + let ⟨as, he, hl⟩ := h.exists_appN + ⟨as ++ [a], by rw [VExpr.appN_append, ← he]; rfl, by simp [hl]⟩ + +namespace VExpr + +/-- The value of a bound variable under iterated instantiation: the spine +argument at its reverse position. -/ +theorem instRev_bvar_lt : ∀ (es : List VExpr) {i : Nat} (h : i < es.length), + instRev (.bvar i) es = es[es.length - 1 - i]'(by omega) + | e :: es, i, h => by + rcases Nat.lt_or_ge i es.length with h' | h' + · rw [show instRev (.bvar i) (e :: es) = instRev (.bvar i) es from + instRev_bvar_lt_cons es e h', instRev_bvar_lt es h'] + simp only [show (e :: es).length - 1 - i = (es.length - 1 - i) + 1 from by + simp only [List.length_cons]; omega, List.getElem_cons_succ] + · obtain rfl : i = es.length := by + simp only [List.length_cons] at h; omega + show instRev (instVar es.length e es.length) es = _ + rw [show instVar es.length e es.length = liftN es.length e from by + simp [instVar]] + rw [instRev_liftN_len] + simp only [show (e :: es).length - 1 - es.length = 0 from by + simp only [List.length_cons]; omega, List.getElem_cons_zero] + +/-- Iterated instantiation of a reverse bound-variable segment reads back +the corresponding spine segment. -/ +theorem map_instRev_bvarRevRange_seg (es : List VExpr) : + ∀ (q off : Nat), off + q ≤ es.length → + (bvarRevRange off q).map (instRev · es) = + (es.drop (es.length - off - q)).take q := by + intro q + induction q with + | zero => intro off h; simp [VExpr.bvarRevRange] + | succ q ih => + intro off h + show instRev (.bvar (off + q)) es :: (bvarRevRange off q).map (instRev · es) = _ + rw [instRev_bvar_lt es (by omega), ih off (by omega)] + have hd : es.length - off - (q + 1) < es.length := by omega + simp only [show es.length - 1 - (off + q) = es.length - off - (q + 1) from by + omega, show es.length - off - q = (es.length - off - (q + 1)) + 1 from by + omega] + rw [List.drop_eq_getElem_cons hd, List.take_succ_cons] + +end VExpr + +/-! ## Typed β-collapse of applied telescopes -/ + +/-- Instantiating below a reversed telescope, mirroring +`Ctx.LiftN.consTel`. -/ +theorem Ctx.InstN.consTel {Γ₀ : List VExpr} {e₀ A₀ : VExpr} : + ∀ (As : List VExpr) {k : Nat} {Γ Γ' : List VExpr}, + Ctx.InstN Γ₀ e₀ A₀ k Γ Γ' → + Ctx.InstN Γ₀ e₀ A₀ (As.length + k) (As.reverse ++ Γ) + ((VExpr.instTelN e₀ As k).reverse ++ Γ') + | [], k, Γ, Γ', W => by simpa [VExpr.instTelN] using W + | A :: As, k, Γ, Γ', W => by + have h := Ctx.InstN.consTel As (Ctx.InstN.succ (A := A) W) + rw [show As.length + (k+1) = (A :: As).length + k from by simp; omega] at h + simpa [VExpr.instTelN, List.append_assoc] using h + +/-- Instantiating a telescope's context. -/ +theorem VEnv.OnTel.instN {env : VEnv} (henv : env.Ordered) {U : Nat} + {Γ₀ : List VExpr} {e₀ A₀ : VExpr} (h₀ : env.HasType U Γ₀ e₀ A₀) : + ∀ {As : List VExpr} {k : Nat} {Γ Γ' : List VExpr}, + Ctx.InstN Γ₀ e₀ A₀ k Γ Γ' → VEnv.OnTel env U Γ As → + VEnv.OnTel env U Γ' (VExpr.instTelN e₀ As k) + | [], _, _, _, _, _ => trivial + | _ :: _, _, _, _, W, ⟨⟨u, hA⟩, hT⟩ => + ⟨⟨u, hA.instN henv W h₀⟩, VEnv.OnTel.instN henv h₀ W.succ hT⟩ + +/-- Pointwise defeq of two application spines against a peeled pi type. -/ +inductive VEnv.SpineDefEq (env : VEnv) (U : Nat) (Γ : List VExpr) : + VExpr → List VExpr → List VExpr → VExpr → Prop where + | nil : VEnv.SpineDefEq env U Γ A [] [] A + | cons : env.IsDefEq U Γ a a' A₁ → + VEnv.SpineDefEq env U Γ (A₂.inst a) es es' B → + VEnv.SpineDefEq env U Γ (.forallE A₁ A₂) (a :: es) (a' :: es') B + +/-- Iterated application congruence along a pointwise defeq spine. -/ +theorem VEnv.IsDefEq.appN_defEq {env : VEnv} {U : Nat} {Γ : List VExpr} : + ∀ {es es' : List VExpr} {F B X Y : VExpr}, + env.IsDefEq U Γ X Y F → VEnv.SpineDefEq env U Γ F es es' B → + env.IsDefEq U Γ (VExpr.appN X es) (VExpr.appN Y es') B + | [], _, _, _, _, _, h, .nil => h + | a :: _, a' :: _, _, _, X, Y, h, .cons ha hrest => + VEnv.IsDefEq.appN_defEq (X := X.app a) (Y := Y.app a') (h.appDF ha) hrest + +/-- A well-typed spine is a reflexive defeq spine. -/ +theorem VEnv.SpineWF.toSpineDefEq {env : VEnv} {U : Nat} {Γ : List VExpr} : + ∀ {es : List VExpr} {F B : VExpr}, env.SpineWF U Γ F es B → + VEnv.SpineDefEq env U Γ F es es B + | [], _, _, .nil => .nil + | _ :: _, _, _, .cons ha hrest => .cons ha hrest.toSpineDefEq + +/-- Iterated application congruence in the function position. -/ +theorem VEnv.IsDefEq.appN_congr {env : VEnv} {U : Nat} {Γ : List VExpr} + {es : List VExpr} {F B X Y : VExpr} + (h : env.IsDefEq U Γ X Y F) (hs : env.SpineWF U Γ F es B) : + env.IsDefEq U Γ (VExpr.appN X es) (VExpr.appN Y es) B := + h.appN_defEq hs.toSpineDefEq + +/-- A registered equation remains available after environment growth. + +This is the primitive transport operation for consumer-certified extension +rules: `VEnv.LE` transports registration, while the core `.extra` constructor +still requires the exact universe instantiation side conditions. -/ +theorem VEnv.LE.extra {env env' : VEnv} (henv : env ≤ env') {U : Nat} + {Γ : List VExpr} {df : VDefEq} {ls : List VLevel} + (hreg : env.defeqs df) (hlevels : ∀ l ∈ ls, l.WF U) + (hlevelsLength : ls.length = df.uvars) : + env'.IsDefEq U Γ (df.lhs.instL ls) (df.rhs.instL ls) + (df.type.instL ls) := + .extra (henv.defeqs hreg) hlevels hlevelsLength + +/-- Transport a registered equation through environment growth and then +apply it to a well-typed spine. This is the beta-tower consumer boundary: +registration supplies only the tower equality; application congruence and +spine typing remain explicit proof obligations. -/ +theorem VEnv.LE.extra_appN {env env' : VEnv} (henv : env ≤ env') {U : Nat} + {Γ : List VExpr} {df : VDefEq} {ls : List VLevel} {args : List VExpr} + {B : VExpr} (hreg : env.defeqs df) + (hlevels : ∀ l ∈ ls, l.WF U) (hlevelsLength : ls.length = df.uvars) + (hspine : env.SpineWF U Γ (df.type.instL ls) args B) : + env'.IsDefEq U Γ + (VExpr.appN (df.lhs.instL ls) args) + (VExpr.appN (df.rhs.instL ls) args) B := + (henv.extra hreg hlevels hlevelsLength).appN_congr (hspine.mono henv) + +/-- The symmetric applied transport is derived, not a second trusted +extension direction. -/ +theorem VEnv.LE.extra_appN_symm {env env' : VEnv} (henv : env ≤ env') + {U : Nat} {Γ : List VExpr} {df : VDefEq} {ls : List VLevel} + {args : List VExpr} {B : VExpr} (hreg : env.defeqs df) + (hlevels : ∀ l ∈ ls, l.WF U) (hlevelsLength : ls.length = df.uvars) + (hspine : env.SpineWF U Γ (df.type.instL ls) args B) : + env'.IsDefEq U Γ + (VExpr.appN (df.rhs.instL ls) args) + (VExpr.appN (df.lhs.instL ls) args) B := + (henv.extra_appN hreg hlevels hlevelsLength hspine).symm + +/-- Applying a lambda telescope to a full well-typed spine collapses to the +iterated instantiation of its body. -/ +theorem VEnv.IsDefEq.appN_lamN {env : VEnv} (henv : env.Ordered) {U : Nat} : + ∀ {As : List VExpr} {Γ : List VExpr} {body T B : VExpr} {es : List VExpr}, + VEnv.OnTel env U Γ As → + env.HasType U (As.reverse ++ Γ) body T → + env.SpineWF U Γ (VExpr.forallN As T) es B → + es.length = As.length → + env.IsDefEq U Γ (VExpr.appN (VExpr.lamN As body) es) + (VExpr.instRev body es) B + | [], Γ, body, T, B, es, _, hb, hs, hlen => by + obtain rfl : es = [] := List.length_eq_zero_iff.1 hlen + obtain rfl : T = B := hs.nil_inv + exact hb + | A :: As, Γ, body, T, B, e :: es, ⟨⟨u, hA⟩, hT⟩, hb, + .cons he hrest, hlen => by + have hb' : env.HasType U (As.reverse ++ (A :: Γ)) body T := by + simpa [List.append_assoc] using hb + have hlam : env.HasType U (A :: Γ) (VExpr.lamN As body) + (VExpr.forallN As T) := VEnv.HasType.lamN hT hb' + have hbeta := VEnv.IsDefEq.beta hlam he + rw [VExpr.instN_lamN, Nat.zero_add] at hbeta + have hlen2 : es.length = As.length := by simpa using hlen + have hT' : VEnv.OnTel env U Γ (VExpr.instTelN e As 0) := + VEnv.OnTel.instN henv he .zero hT + have hb'' : env.HasType U ((VExpr.instTelN e As 0).reverse ++ Γ) + (body.inst e As.length) (T.inst e As.length) := by + have W := Ctx.InstN.consTel (Γ₀ := Γ) (e₀ := e) (A₀ := A) As .zero + have := hb'.instN henv W he + simpa using this + have hrest' : env.SpineWF U Γ + (VExpr.forallN (VExpr.instTelN e As 0) (T.inst e As.length)) es B := by + rw [VExpr.instN_forallN] at hrest + simpa using hrest + have hlen' : es.length = (VExpr.instTelN e As 0).length := by + rw [VExpr.instTelN_length]; exact hlen2 + have IH := VEnv.IsDefEq.appN_lamN henv hT' hb'' hrest' hlen' + have hstep := VEnv.IsDefEq.appN_congr hbeta hrest + show env.IsDefEq U Γ + (VExpr.appN ((VExpr.lam A (VExpr.lamN As body)).app e) es) + (VExpr.instRev (body.inst e es.length) es) B + rw [hlen2] + exact hstep.trans IH + +/-- Instantiate a terminal definitional equality through a saturated telescope spine. -/ +theorem VEnv.SpineWF.instRev_defeq + {env : VEnv} (henv : env.Ordered) {U : Nat} {Γ : List VExpr} : + ∀ {As : List VExpr} {C C' T : VExpr} {es : List VExpr} {B : VExpr}, + env.SpineWF U Γ (VExpr.forallN As C) es B → + es.length = As.length → + env.IsDefEq U (As.reverse ++ Γ) C C' T → + env.IsDefEq U Γ (VExpr.instRev C es) (VExpr.instRev C' es) + (VExpr.instRev T es) + | [], C, C', T, [], B, hspine, _, hterminal => by + simpa [VExpr.instRev] using hterminal + | [], _, _, _, _ :: _, _, _, hlen, _ => by simp at hlen + | _ :: _, _, _, _, [], _, _, hlen, _ => by simp at hlen + | A :: As, C, C', T, e :: es, B, + .cons he hrest, hlen, hterminal => by + have hlen' : es.length = As.length := by simpa using hlen + have W := Ctx.InstN.consTel (Γ₀ := Γ) (e₀ := e) (A₀ := A) As .zero + have hterminal₀ : env.IsDefEq U (As.reverse ++ A :: Γ) C C' T := by + simpa [List.reverse_cons, List.append_assoc] using hterminal + have hterminal' := hterminal₀.instN henv he W + have hrest' : env.SpineWF U Γ + (VExpr.forallN (VExpr.instTelN e As 0) + (C.inst e As.length)) es B := by + rw [VExpr.instN_forallN] at hrest + simpa using hrest + have hout := VEnv.SpineWF.instRev_defeq henv hrest' + (by simpa [VExpr.instTelN_length] using hlen') hterminal' + simpa [VExpr.instRev, hlen'] using hout + +/-- Iterated inversion of a lambda tower's typing: the telescope is +well-formed and the body is typed under it. -/ +theorem VEnv.HasType.lamN_wf {env : VEnv} {U : Nat} (henv : env.Ordered) : + ∀ {As : List VExpr} {Γ : List VExpr} {body V : VExpr}, + OnCtx Γ (env.IsType U) → + env.HasType U Γ (VExpr.lamN As body) V → + VEnv.OnTel env U Γ As ∧ + ∃ T₀, env.HasType U (As.reverse ++ Γ) body T₀ + | [], Γ, body, V, _, H => ⟨trivial, V, H⟩ + | A :: As, Γ, body, V, hΓ, H => by + obtain ⟨⟨u, hA⟩, W, hrest⟩ := VEnv.HasType.lam_inv henv hΓ H + obtain ⟨hT, T₀, hbody⟩ := + VEnv.HasType.lamN_wf henv (As := As) (Γ := A :: Γ) ⟨hΓ, u, hA⟩ hrest + exact ⟨⟨⟨u, hA⟩, hT⟩, T₀, by simpa [List.append_assoc] using hbody⟩ + +/-- The levels of a `HeadConstN` spine are unique. -/ +theorem HeadConstN.levels_uniq {c : Name} : + ∀ {n : Nat} {e : VExpr} {ls ls' : List VLevel}, + HeadConstN c ls n e → HeadConstN c ls' n e → ls = ls' + | _, _, _, _, .const, .const => rfl + | _, _, _, _, .app h, .app h' => h.levels_uniq h' + +/-- Zip a well-typed spine with pointwise defeqs into a defeq spine. +Reflexive entries need no defeq evidence. -/ +theorem VEnv.SpineWF.defEq_of_pointwise {env : VEnv} (henv : env.WF) + {U : Nat} {Γ : List VExpr} (hΓ : OnCtx Γ (env.IsType U)) : + ∀ {es es' : List VExpr} {F B : VExpr}, + env.SpineWF U Γ F es B → + List.Forall₂ (fun a a' => a = a' ∨ env.IsDefEqU U Γ a a') es es' → + VEnv.SpineDefEq env U Γ F es es' B + | [], [], _, _, .nil, .nil => .nil + | _ :: _, _ :: _, _, _, .cons he hrest, .cons hd htl => by + refine .cons ?_ (hrest.defEq_of_pointwise henv hΓ htl) + rcases hd with rfl | hd + · exact he + · exact VEnv.IsDefEqU.of_l henv hΓ hd he + +/-- Unfold the `OK` predicate through a folded list of defeq checks. -/ +theorem Pattern.Check.OK.of_foldr {p : Pattern} {α : Type _} + {df : VExpr → VExpr → Prop} {m1 : List VLevel} {m2 : p.Path → VExpr} + (f g : α → p.RHS) : + ∀ {xs : List α} {rest : p.Check}, + ((xs.foldr (fun x acc => Pattern.Check.defeq (f x) (g x) acc) + rest).OK df m1 m2) → + (∀ x ∈ xs, df ((f x).apply m1 m2) ((g x).apply m1 m2)) ∧ + rest.OK df m1 m2 + | [], _, h => ⟨nofun, h⟩ + | _ :: xs, rest, h => by + obtain ⟨h1, h2⟩ := h + obtain ⟨h3, h4⟩ := Pattern.Check.OK.of_foldr f g (xs := xs) h2 + refine ⟨fun x hx => ?_, h4⟩ + rcases List.mem_cons.1 hx with rfl | hx + · exact h1 + · exact h3 x hx + +/-- Build a pointwise relation between two mapped lists from their zip. -/ +private theorem forall₂_zip_map {α β : Type _} (F : α → VExpr) (G : β → VExpr) + (R : VExpr → VExpr → Prop) : + ∀ (xs : List α) (ys : List β), xs.length = ys.length → + (∀ p ∈ xs.zip ys, R (F p.1) (G p.2)) → + List.Forall₂ R (xs.map F) (ys.map G) + | [], [], _, _ => .nil + | x :: xs, y :: ys, hlen, hall => + .cons (hall (x, y) (.head _)) + (forall₂_zip_map F G R xs ys (by simpa using hlen) + fun p hp => hall p (.tail _ hp)) + | [], _ :: _, hlen, _ => by simp at hlen + | _ :: _, [], hlen, _ => by simp at hlen + +/-- Universe instantiation fixes a reverse bound-variable range. -/ +theorem VExpr.bvarRevRange_map_instL (ls : List VLevel) : + ∀ (off m : Nat), + (VExpr.bvarRevRange off m).map (VExpr.instL ls) = + VExpr.bvarRevRange off m + | _, 0 => rfl + | off, m+1 => by + simp only [VExpr.bvarRevRange, List.map_cons, VExpr.instL, + VExpr.bvarRevRange_map_instL ls off m] + +/-- A well-formed telescope extends a well-formed context. -/ +theorem VEnv.OnTel.onCtx {env : VEnv} {U : Nat} : + ∀ {As Γ : List VExpr}, OnCtx Γ (env.IsType U) → + VEnv.OnTel env U Γ As → OnCtx (As.reverse ++ Γ) (env.IsType U) + | [], _, hΓ, _ => hΓ + | A :: As, Γ, hΓ, ⟨hA, hT⟩ => by + simpa [List.append_assoc] using + VEnv.OnTel.onCtx (As := As) (Γ := A :: Γ) ⟨hΓ, hA⟩ hT + +/-- Every argument of a well-typed application spine is well-typed. -/ +theorem VEnv.HasType.appN_args_wf {env : VEnv} (henv : env.WF) {U : Nat} + {Γ : List VExpr} (hΓ : OnCtx Γ (env.IsType U)) : + ∀ (n : Nat) (es : List VExpr), es.length = n → ∀ {f B : VExpr}, + env.HasType U Γ (VExpr.appN f es) B → + ∀ e ∈ es, ∃ T, env.HasType U Γ e T := by + intro n + induction n with + | zero => + intro es hlen f B H e he + obtain rfl := List.length_eq_zero_iff.1 hlen + cases he + | succ n ih => + intro es hlen f B H e he + have hne : es ≠ [] := by rintro rfl; simp at hlen + obtain ⟨es', a, rfl⟩ : ∃ es' a, es = es' ++ [a] := + ⟨es.dropLast, es.getLast hne, (List.dropLast_concat_getLast hne).symm⟩ + rw [VExpr.appN_append] at H + have H' : env.HasType U Γ ((VExpr.appN f es').app a) B := H + obtain ⟨A₁, B₁, hf, ha⟩ := H'.app_inv henv hΓ + rcases List.mem_append.1 he with he' | he' + · exact ih es' (by simpa using hlen) hf e he' + · obtain rfl : e = a := by simpa using he' + exact ⟨A₁, ha⟩ + +/-- Iterated inversion of a pi tower's typing: the telescope is well formed +and the body is typed under it. -/ +theorem VEnv.HasType.forallN_wf {env : VEnv} {U : Nat} (henv : env.Ordered) : + ∀ {As : List VExpr} {Γ : List VExpr} {body V : VExpr}, + env.HasType U Γ (VExpr.forallN As body) V → + VEnv.OnTel env U Γ As ∧ ∃ V', env.HasType U (As.reverse ++ Γ) body V' + | [], _, _, V, H => ⟨trivial, V, H⟩ + | A :: As, Γ, body, V, H => by + obtain ⟨⟨u, hA⟩, v, hB⟩ := VEnv.HasType.forallE_inv henv H + obtain ⟨hT, V', hbody⟩ := VEnv.HasType.forallN_wf henv (As := As) hB + exact ⟨⟨⟨u, hA⟩, hT⟩, V', by simpa [List.append_assoc] using hbody⟩ + +private theorem forall₂_refl_or {R : VExpr → VExpr → Prop} : + ∀ (l : List VExpr), List.Forall₂ (fun a a' => a = a' ∨ R a a') l l + | [] => .nil + | _ :: l => .cons (Or.inl rfl) (forall₂_refl_or l) + +private theorem forall₂_append {R : VExpr → VExpr → Prop} : + ∀ {l₁ l₂ l₁' l₂' : List VExpr}, List.Forall₂ R l₁ l₂ → + List.Forall₂ R l₁' l₂' → List.Forall₂ R (l₁ ++ l₁') (l₂ ++ l₂') + | [], [], _, _, .nil, h => h + | _ :: _, _ :: _, _, _, .cons hd htl, h => .cons hd (forall₂_append htl h) + +namespace VInductDecl + +namespace BlockGenerationChecked + +variable {source : VInductDecl} (gen : source.BlockGenerationChecked) + +/-! ## Named shapes of one generated rule -/ + +theorem rule_type (i : Nat) (c : NormalizedBlockCtor) : + (gen.rule i c).type = + VExpr.forallN (gen.ruleBinders c) + (VExpr.appN + (.bvar (gen.familyCount - 1 - c.owner + gen.minorCount + + gen.ruleFieldCount c)) + (gen.ruleIdx c ++ [gen.ruleCtorApp c])) := rfl + +theorem rule_uvars (i : Nat) (c : NormalizedBlockCtor) : + (gen.rule i c).uvars = gen.recUvars := rfl + +theorem paramsTel_length : gen.paramsTel.length = source.nparams := by + show ((generationParams gen.block.rawParams gen.block.checked.params).map + (VExpr.instL gen.sourceLevels)).length = _ + rw [List.length_map] + exact (generationParams_length_of_eq gen.shape.2.1).trans gen.shape.1 + +theorem ruleBinders_length (c : NormalizedBlockCtor) : + (gen.ruleBinders c).length = + source.nparams + gen.familyCount + gen.minorCount + + gen.ruleFieldCount c := by + simp only [ruleBinders, List.length_append, gen.paramsTel_length, + motiveTypes, gen.motiveTypesAux_length, minorTypes, + gen.minorTypesAux_length, VExpr.liftTelN_length, ruleFieldCount] + try omega + +/-- The instantiated left body as one flattened application spine. -/ +theorem ruleLhsBody_instL (c : NormalizedBlockCtor) {m1 : List VLevel} + (hlen1 : m1.length = gen.recUvars) : + (gen.ruleLhsBody c).instL m1 = + VExpr.appN (.const (gen.ruleRecName c) m1) + (VExpr.bvarRevRange (gen.ruleFieldCount c) + (source.nparams + gen.familyCount + gen.minorCount) ++ + (gen.ruleIdx c).map (VExpr.instL m1) ++ + [(gen.ruleCtorApp c).instL m1]) := by + show (VExpr.appN + (VExpr.appN (.const (gen.ruleRecName c) gen.recLevels) + (VExpr.bvarRevRange (gen.ruleFieldCount c) + (source.nparams + gen.familyCount + gen.minorCount))) + (gen.ruleIdx c ++ [gen.ruleCtorApp c])).instL m1 = _ + rw [← VExpr.appN_append, VExpr.instL_appN] + show VExpr.appN (.const (gen.ruleRecName c) + (gen.recLevels.map (VLevel.inst m1))) _ = _ + rw [show gen.recLevels.map (VLevel.inst m1) = m1 from + VLevel.inst_map_id hlen1] + rw [List.map_append, List.map_append, VExpr.bvarRevRange_map_instL, + List.append_assoc] + rfl + +/-- The instantiated major premise of the rule body. -/ +theorem ruleCtorApp_instL (c : NormalizedBlockCtor) (m1 : List VLevel) : + (gen.ruleCtorApp c).instL m1 = + VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) + (VExpr.bvarRevRange + (gen.ruleFieldCount c + (gen.familyCount + gen.minorCount)) + source.nparams ++ + VExpr.bvarRevRange 0 (gen.ruleFieldCount c)) := by + show (VExpr.appN (.const c.ctor.raw.name gen.sourceLevels) _).instL m1 = _ + rw [VExpr.instL_appN, List.map_append, VExpr.bvarRevRange_map_instL, + VExpr.bvarRevRange_map_instL] + rfl + +/-- The captured template values are exactly the shared prefix of the +recursor spine and the field suffix of the major premise. -/ +private theorem captureArgs_apply {c : NormalizedBlockCtor} {m1 : List VLevel} + {g1 : Pattern.Path + (Pattern.varN (.const (gen.ruleRecName c)) (gen.ruleMajorArity c)) → VExpr} + {g2 : Pattern.Path + (Pattern.varN (.const c.ctor.raw.name) (gen.ruleArgArity c)) → VExpr} + {fArgs aArgs : List VExpr} + (hg1 : (Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c)).map g1 = fArgs) + (hg2 : (Pattern.varNPaths (.const c.ctor.raw.name) + (gen.ruleArgArity c)).map g2 = aArgs) : + (gen.captureArgs c).map + (Pattern.RHS.apply (p := (gen.rulePattern c).toPattern) m1 + (Sum.elim g1 g2)) = + fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams := by + rw [captureArgs, List.map_append, List.map_map, List.map_map] + show List.map g1 (List.take + (source.nparams + gen.familyCount + gen.minorCount) + (Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c))) ++ + List.map g2 (List.drop source.nparams + (Pattern.varNPaths (.const c.ctor.raw.name) + (gen.ruleArgArity c))) = _ + rw [List.map_take, List.map_drop, hg1, hg2] + +/-- Pattern soundness for one certified block (`pat_wf`): a successful match +of a rule's pattern whose checks hold is definitionally equal to the +instantiated RHS template, derived from the rule defeq registered by +`addInduct` via typed β-collapse. The redex arrives decomposed into its +recursor and constructor spines with spine-form typing, and the major +premise's levels pinned to the rule's source levels; both are exactly what +a verified reduction site holds. -/ +theorem pat_wf {env : VEnv} (henv : env.WF) {univs : Nat} {Γ : List VExpr} + (hΓ : OnCtx Γ (env.IsType univs)) + (hcl : gen.RuleClosure) + {i : Nat} {c : NormalizedBlockCtor} (h : gen.ruleEntry i c) + (hreg : env.defeqs (gen.rule i c)) + (hwf : (gen.rule i c).WF env) + {m1 : List VLevel} {m2} + (hm1 : ∀ l ∈ m1, l.WF univs) (hlen1 : m1.length = gen.recUvars) + {fArgs aArgs : List VExpr} + (hMlen : fArgs.length = gen.ruleMajorArity c) + (hNlen : aArgs.length = gen.ruleArgArity c) + (hm : ((gen.rulePattern c).toPattern).Matches + (.app (VExpr.appN (.const (gen.ruleRecName c) m1) fArgs) + (VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) aArgs)) m1 m2) + (hck : (gen.ruleCheck hcl (List.mem_of_getElem? h)).OK + (env.IsDefEqU univs Γ) m1 m2) + {Frec Ae : VExpr} + (hehead : env.HasType univs Γ (.const (gen.ruleRecName c) m1) Frec) + (hespine : env.SpineWF univs Γ Frec + (fArgs ++ [VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) aArgs]) Ae) + {Fctor Actor : VExpr} + (hctorhead : env.HasType univs Γ + (.const c.ctor.raw.name (gen.sourceLevels.map (VLevel.inst m1))) Fctor) + (hctorspine : env.SpineWF univs Γ Fctor aArgs Actor) + {B : VExpr} + (hcaps : env.SpineWF univs Γ ((gen.rule i c).type.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams) B) : + env.IsDefEqU univs Γ + (.app (VExpr.appN (.const (gen.ruleRecName c) m1) fArgs) + (VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) aArgs)) + ((gen.ruleRHS hcl h).apply m1 m2) := by + have henvo := henv.ordered + have hc := List.mem_of_getElem? h + cases hm with + | @app _ _ _ g1 _ _ f2 g2 h1 h2 => + -- canonical captures + have hg1 : (Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c)).map g1 = fArgs := + Pattern.varN_matches_paths _ fArgs h1 hMlen + have hg2 : (Pattern.varNPaths (.const c.ctor.raw.name) + (gen.ruleArgArity c)).map g2 = aArgs := + Pattern.varN_matches_paths _ aArgs h2 hNlen + have hcapsVals := gen.captureArgs_apply (m1 := m1) hg1 hg2 + -- length bookkeeping + have hcommon_le : source.nparams + gen.familyCount + gen.minorCount ≤ + gen.ruleMajorArity c := Nat.le_add_right _ _ + have hnp_le : source.nparams ≤ gen.ruleArgArity c := Nat.le_add_right _ _ + have htakelen : (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount)).length = + source.nparams + gen.familyCount + gen.minorCount := by + rw [List.length_take, hMlen]; omega + have hdroplen : (aArgs.drop source.nparams).length = + gen.ruleFieldCount c := by + rw [List.length_drop, hNlen] + show gen.ruleArgArity c - source.nparams = _ + simp only [ruleArgArity]; omega + have hcapslen : (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams).length = + ((gen.ruleBinders c).map (VExpr.instL m1)).length := by + rw [List.length_append, htakelen, hdroplen, List.length_map, + gen.ruleBinders_length] + -- tower shapes + have htype' : (gen.rule i c).type.instL m1 = + VExpr.forallN ((gen.ruleBinders c).map (VExpr.instL m1)) + ((VExpr.appN + (.bvar (gen.familyCount - 1 - c.owner + gen.minorCount + + gen.ruleFieldCount c)) + (gen.ruleIdx c ++ [gen.ruleCtorApp c])).instL m1) := by + rw [gen.rule_type, VExpr.instL_forallN] + have hlhs' : (gen.rule i c).lhs.instL m1 = + VExpr.lamN ((gen.ruleBinders c).map (VExpr.instL m1)) + ((gen.ruleLhsBody c).instL m1) := by + rw [gen.rule_lhs, VExpr.instL_lamN] + -- tower typing at the working context + have hlhsT : env.HasType univs Γ + (VExpr.lamN ((gen.ruleBinders c).map (VExpr.instL m1)) + ((gen.ruleLhsBody c).instL m1)) + ((gen.rule i c).type.instL m1) := by + rw [← hlhs'] + exact (hwf.1.instL hm1).weak0 henvo + obtain ⟨hTel, T₀, hbody⟩ := VEnv.HasType.lamN_wf henvo hΓ hlhsT + -- β-collapse of the applied left tower + have hcapsF : env.SpineWF univs Γ + (VExpr.forallN ((gen.ruleBinders c).map (VExpr.instL m1)) + ((VExpr.appN + (.bvar (gen.familyCount - 1 - c.owner + gen.minorCount + + gen.ruleFieldCount c)) + (gen.ruleIdx c ++ [gen.ruleCtorApp c])).instL m1)) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams) B := htype' ▸ hcaps + have hretT0 := (VEnv.SpineWF.retarget hcapsF hcapslen) T₀ + have hcollapseL := VEnv.IsDefEq.appN_lamN henvo hTel hbody hretT0 hcapslen + -- the registered defeq, applied + have hex : env.IsDefEq univs Γ ((gen.rule i c).lhs.instL m1) + ((gen.rule i c).rhs.instL m1) ((gen.rule i c).type.instL m1) := + .extra hreg hm1 hlen1 + rw [hlhs'] at hex + have happlied := VEnv.IsDefEq.appN_congr hex hcaps + -- conclusion-side template computation + have hRHS : Pattern.RHS.apply (p := (gen.rulePattern c).toPattern) m1 + (Sum.elim g1 g2) (gen.ruleRHS hcl h) = + VExpr.appN ((gen.rule i c).rhs.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams) := by + rw [ruleRHS] + simp only [Pattern.RHS.appN_apply, hcapsVals] + rfl + -- typing of the rule type's index spine + obtain ⟨u₀, htypeT⟩ := hlhsT.isType henvo hΓ + rw [htype'] at htypeT + obtain ⟨-, V', htypeBody⟩ := VEnv.HasType.forallN_wf henvo htypeT + have hCtxTel : OnCtx (((gen.ruleBinders c).map (VExpr.instL m1)).reverse ++ Γ) + (env.IsType univs) := VEnv.OnTel.onCtx hΓ hTel + rw [show ((VExpr.appN + (.bvar (gen.familyCount - 1 - c.owner + gen.minorCount + + gen.ruleFieldCount c)) + (gen.ruleIdx c ++ [gen.ruleCtorApp c])).instL m1) = + VExpr.appN (.bvar (gen.familyCount - 1 - c.owner + gen.minorCount + + gen.ruleFieldCount c)) + ((gen.ruleIdx c ++ [gen.ruleCtorApp c]).map (VExpr.instL m1)) from by + rw [VExpr.instL_appN]; rfl] at htypeBody + have hargsWF := VEnv.HasType.appN_args_wf henv hCtxTel _ _ rfl htypeBody + -- check extraction + unfold ruleCheck at hck + obtain ⟨hparams, hidxOK⟩ := Pattern.Check.OK.of_foldr _ _ hck + obtain ⟨hidxs, -⟩ := Pattern.Check.OK.of_foldr _ _ hidxOK + -- per-index tower collapse and check composition + have hidxLink : ∀ x ∈ (gen.ruleIdx c).attach.zip + ((Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c)).drop + (source.nparams + gen.familyCount + gen.minorCount)), + env.IsDefEqU univs Γ (Sum.elim g1 g2 (Sum.inl x.2)) + (VExpr.instRev (x.1.1.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) := by + intro x hx + have hfact := hidxs x hx + simp only [Pattern.RHS.appN_apply, hcapsVals] at hfact + have htower : Pattern.RHS.apply (p := (gen.rulePattern c).toPattern) m1 + (Sum.elim g1 g2) + (.fixed (VExpr.lamN (gen.ruleBinders c) x.1.1) + (hcl.idxTower_closed hc x.1.1 x.1.2)) = + VExpr.lamN ((gen.ruleBinders c).map (VExpr.instL m1)) + (x.1.1.instL m1) := by + show (VExpr.lamN (gen.ruleBinders c) x.1.1).instL m1 = _ + rw [VExpr.instL_lamN] + rw [htower] at hfact + obtain ⟨Tx, hTx⟩ := hargsWF (x.1.1.instL m1) + (by + rw [List.map_append] + exact List.mem_append.2 (.inl (List.mem_map_of_mem x.1.2))) + have hretTx := (VEnv.SpineWF.retarget hcapsF hcapslen) Tx + have hcollapseX := VEnv.IsDefEq.appN_lamN henvo hTel hTx hretTx hcapslen + exact VEnv.IsDefEqU.trans henv hΓ hfact ⟨_, hcollapseX⟩ + -- major premise: constructor spine against its rebuilt form + have hparamsF₂ : List.Forall₂ + (fun a a' => a = a' ∨ env.IsDefEqU univs Γ a a') + aArgs + (fArgs.take source.nparams ++ aArgs.drop source.nparams) := by + have hb := forall₂_zip_map (α := Pattern.Path + (Pattern.varN (.const c.ctor.raw.name) (gen.ruleArgArity c))) + (β := Pattern.Path + (Pattern.varN (.const (gen.ruleRecName c)) (gen.ruleMajorArity c))) + g2 g1 (fun a a' => a = a' ∨ env.IsDefEqU univs Γ a a') + ((Pattern.varNPaths (.const c.ctor.raw.name) + (gen.ruleArgArity c)).take source.nparams) + ((Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c)).take source.nparams) + (by + rw [List.length_take, List.length_take, + Pattern.varNPaths_length, Pattern.varNPaths_length] + omega) + (fun p hp => Or.inr (hparams p hp)) + rw [List.map_take, List.map_take, hg1, hg2] at hb + have hall := forall₂_append hb + (forall₂_refl_or (R := env.IsDefEqU univs Γ) + (aArgs.drop source.nparams)) + rwa [List.take_append_drop] at hall + have hmajorLink : env.IsDefEqU univs Γ + (VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) aArgs) + (VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) + (fArgs.take source.nparams ++ aArgs.drop source.nparams)) := + ⟨_, VEnv.IsDefEq.appN_defEq hctorhead + (VEnv.SpineWF.defEq_of_pointwise henv hΓ hctorspine hparamsF₂)⟩ + -- the collapsed left spine, computed + have hL : (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams).length = + gen.ruleFieldCount c + + (source.nparams + gen.familyCount + gen.minorCount) := by + rw [List.length_append, htakelen, hdroplen]; omega + have hcapsTake : (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams).take + (source.nparams + gen.familyCount + gen.minorCount) = + fArgs.take (source.nparams + gen.familyCount + gen.minorCount) := by + rw [List.take_append_of_le_length (by omega : _ ≤ (fArgs.take + (source.nparams + gen.familyCount + gen.minorCount)).length)] + exact List.take_of_length_le (Nat.le_of_eq htakelen) + have hcapsTakeNp : (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams).take source.nparams = + fArgs.take source.nparams := by + rw [List.take_append_of_le_length (by omega : _ ≤ (fArgs.take + (source.nparams + gen.familyCount + gen.minorCount)).length)] + rw [List.take_take] + congr 1 + omega + have hcapsDrop : (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams).drop + (source.nparams + gen.familyCount + gen.minorCount) = + aArgs.drop source.nparams := by + have hdl := List.drop_left (l₁ := fArgs.take (source.nparams + gen.familyCount + gen.minorCount)) (l₂ := aArgs.drop source.nparams) + rwa [htakelen] at hdl + have hsegNp : (VExpr.bvarRevRange + (gen.ruleFieldCount c + (gen.familyCount + gen.minorCount)) + source.nparams).map (VExpr.instRev · + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) = fArgs.take source.nparams := by + rw [VExpr.map_instRev_bvarRevRange_seg _ source.nparams _ (by omega)] + rw [show (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams).length - + (gen.ruleFieldCount c + (gen.familyCount + gen.minorCount)) - + source.nparams = 0 from by omega, List.drop_zero] + exact hcapsTakeNp + have hsegFld : (VExpr.bvarRevRange 0 (gen.ruleFieldCount c)).map + (VExpr.instRev · + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) = aArgs.drop source.nparams := by + rw [VExpr.map_instRev_bvarRevRange_seg _ (gen.ruleFieldCount c) 0 + (by omega)] + rw [show (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams).length - 0 - + gen.ruleFieldCount c = + source.nparams + gen.familyCount + gen.minorCount from by omega] + rw [hcapsDrop] + exact List.take_of_length_le (Nat.le_of_eq hdroplen) + have hsegCommon : (VExpr.bvarRevRange (gen.ruleFieldCount c) + (source.nparams + gen.familyCount + gen.minorCount)).map + (VExpr.instRev · + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) = + fArgs.take (source.nparams + gen.familyCount + gen.minorCount) := by + rw [VExpr.map_instRev_bvarRevRange_seg _ + (source.nparams + gen.familyCount + gen.minorCount) + (gen.ruleFieldCount c) (by omega)] + rw [show (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams).length - + gen.ruleFieldCount c - + (source.nparams + gen.familyCount + gen.minorCount) = 0 from by + omega, List.drop_zero] + exact hcapsTake + have hctorImg : VExpr.instRev ((gen.ruleCtorApp c).instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams) = + VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) + (fArgs.take source.nparams ++ aArgs.drop source.nparams) := by + rw [gen.ruleCtorApp_instL, VExpr.instRev_appN, + VExpr.instRev_closedN (C := .const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) _ trivial, List.map_append, + hsegNp, hsegFld] + have hcollapsedEq : VExpr.instRev ((gen.ruleLhsBody c).instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams) = + VExpr.appN (.const (gen.ruleRecName c) m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + ((gen.ruleIdx c).map (fun x => VExpr.instRev (x.instL m1) + (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams)) ++ + [VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) + (fArgs.take source.nparams ++ aArgs.drop source.nparams)])) := by + rw [gen.ruleLhsBody_instL c hlen1, VExpr.instRev_appN, + VExpr.instRev_closedN (C := .const (gen.ruleRecName c) m1) _ trivial, + List.map_append, List.map_append, hsegCommon, List.map_map] + rw [show ((gen.ruleCtorApp c).instL m1 :: + ([] : List VExpr)).map (VExpr.instRev · + (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams)) = + [VExpr.instRev ((gen.ruleCtorApp c).instL m1) + (fArgs.take (source.nparams + gen.familyCount + + gen.minorCount) ++ aArgs.drop source.nparams)] from rfl] + rw [hctorImg] + simp only [Function.comp_def] + rw [List.append_assoc] + -- pointwise defeq between the redex spine and the collapsed spine + have hidxF₂ : List.Forall₂ (fun a a' => a = a' ∨ env.IsDefEqU univs Γ a a') + (fArgs.drop (source.nparams + gen.familyCount + gen.minorCount)) + ((gen.ruleIdx c).map (fun x => VExpr.instRev (x.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams))) := by + have hb := forall₂_zip_map + (α := {x // x ∈ gen.ruleIdx c}) + (β := Pattern.Path (Pattern.varN (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c))) + (fun s => VExpr.instRev (s.1.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) + (fun p => Sum.elim g1 g2 (Sum.inl p)) + (fun t v => v = t ∨ env.IsDefEqU univs Γ v t) + (gen.ruleIdx c).attach + ((Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c)).drop + (source.nparams + gen.familyCount + gen.minorCount)) + (by + rw [List.length_attach, List.length_drop, Pattern.varNPaths_length] + show (gen.ruleIdx c).length = gen.ruleMajorArity c - _ + simp only [ruleIdx, ruleMajorArity, List.length_map] + omega) + (fun p hp => Or.inr (hidxLink p hp)) + have hflip := List.Forall₂.flip hb + have hmapG : ((Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c)).drop + (source.nparams + gen.familyCount + gen.minorCount)).map + (fun p => Sum.elim g1 g2 (Sum.inl p)) = + fArgs.drop (source.nparams + gen.familyCount + gen.minorCount) := by + show ((Pattern.varNPaths (.const (gen.ruleRecName c)) + (gen.ruleMajorArity c)).drop + (source.nparams + gen.familyCount + gen.minorCount)).map g1 = _ + rw [List.map_drop, hg1] + have hmapF : ((gen.ruleIdx c).attach).map + (fun s => VExpr.instRev (s.1.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) = + (gen.ruleIdx c).map (fun x => VExpr.instRev (x.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) := by + exact List.attach_map_val + (f := fun x : VExpr => VExpr.instRev (x.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) .. + rw [hmapG, hmapF] at hflip + exact hflip + have hbigF₂ : List.Forall₂ (fun a a' => a = a' ∨ env.IsDefEqU univs Γ a a') + (fArgs ++ [VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) aArgs]) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + ((gen.ruleIdx c).map (fun x => VExpr.instRev (x.instL m1) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount) ++ + aArgs.drop source.nparams)) ++ + [VExpr.appN (.const c.ctor.raw.name + (gen.sourceLevels.map (VLevel.inst m1))) + (fArgs.take source.nparams ++ aArgs.drop source.nparams)])) := by + have hres := forall₂_append + (forall₂_refl_or (R := env.IsDefEqU univs Γ) + (fArgs.take (source.nparams + gen.familyCount + gen.minorCount))) + (forall₂_append hidxF₂ (.cons (Or.inr hmajorLink) .nil)) + rwa [← List.append_assoc, List.take_append_drop] at hres + -- the redex is defeq to the collapsed left spine + have hE := VEnv.IsDefEq.appN_defEq hehead + (VEnv.SpineWF.defEq_of_pointwise henv hΓ hespine hbigF₂) + rw [← hcollapsedEq, VExpr.appN_append] at hE + -- assemble + rw [hRHS] + exact VEnv.IsDefEqU.trans henv hΓ ⟨_, hE⟩ + (VEnv.IsDefEqU.trans henv hΓ ⟨_, hcollapseL.symm⟩ ⟨_, happlied⟩) + +end BlockGenerationChecked + +end VInductDecl + +end Ix.Theory.Named + +/-! ## Axiom closures + +The typed β-collapse layer is sorry-free. `pat_wf` composes typed defeqs +through `IsDefEqU.of_l`/`IsDefEqU.trans` and therefore carries exactly the +transitional unique-typing closure the Church–Rosser development itself +carries; it sheds `sorryAx` automatically when the Spec-16/17 inversion +milestones land, with no restatement. -/ + +#guard_named_axioms Ix.Theory.Named.VEnv.IsDefEq.appN_lamN [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VEnv.IsDefEq.appN_defEq [propext] + +#guard_named_axioms Ix.Theory.Named.VEnv.LE.extra [propext] + +#guard_named_axioms Ix.Theory.Named.VEnv.LE.extra_appN [propext] + +#guard_named_axioms Ix.Theory.Named.VEnv.LE.extra_appN_symm [propext] + +#guard_named_axioms Ix.Theory.Named.Pattern.varN_matches_paths [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.BlockGenerationChecked.pat_wf [ + propext, + sorryAx, + Classical.choice, + Quot.sound] diff --git a/Ix/Theory/Named/Typing/Injectivity.lean b/Ix/Theory/Named/Typing/Injectivity.lean new file mode 100644 index 000000000..6a69aad14 --- /dev/null +++ b/Ix/Theory/Named/Typing/Injectivity.lean @@ -0,0 +1,43 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.EnvLemmas +import Ix.Theory.Named.Typing.Strong + +/-! +A bunch of important structural theorems which we can't prove :( +-/ + +namespace Ix.Theory.Named +namespace VEnv + +set_option warn.sorry false in +theorem IsDefEqU.sort_inv (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ (.sort u) (.sort v)) : u ≈ v := sorry + +set_option warn.sorry false in +theorem IsDefEqU.forallE_inv_stratified (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ (.forallE A B) (.forallE A' B')) + (h2 : env.HasTypeStratified U Γ (.forallE A B) V true n) + (h3 : env.HasTypeStratified U Γ (.forallE A' B') V' true n') : + (∃ u, env.IsDefEq U Γ A A' (.sort u) ∧ env.HasTypeStratified U Γ A (.sort u) true n) ∧ + ∃ u, env.IsDefEq U (A::Γ) B B' (.sort u) ∧ + env.HasTypeStratified U (A::Γ) B (.sort u) true n ∧ + env.HasTypeStratified U (A'::Γ) B' (.sort u) true n' := sorry + +theorem IsDefEqU.forallE_inv (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ (.forallE A B) (.forallE A' B')) : + (∃ u, env.IsDefEq U Γ A A' (.sort u)) ∧ ∃ u, env.IsDefEq U (A::Γ) B B' (.sort u) := + let ⟨_, eq⟩ := h1 + let ⟨h2, h3⟩ := (eq.strong henv hΓ).hasType' + let ⟨_, h2⟩ := h2.stratify + let ⟨_, h3⟩ := h3.stratify + let ⟨⟨_, a1, _⟩, _, a2, _⟩ := IsDefEqU.forallE_inv_stratified henv hΓ h1 h2 h3 + ⟨⟨_, a1⟩, _, a2⟩ + +set_option warn.sorry false in +theorem IsDefEqU.sort_forallE_inv (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) : + ¬env.IsDefEqU U Γ (.sort u) (.forallE A B) := sorry diff --git a/Ix/Theory/Named/Typing/Lemmas.lean b/Ix/Theory/Named/Typing/Lemmas.lean new file mode 100644 index 000000000..36e44bafb --- /dev/null +++ b/Ix/Theory/Named/Typing/Lemmas.lean @@ -0,0 +1,1115 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.Basic +import Ix.Theory.Named.Std.VariableBang + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +open Ix.Theory.Named VExpr + +inductive Ctx.LiftN (n : Nat) : Nat → List VExpr → List VExpr → Prop where + | zero (As) (h : As.length = n := by rfl) : Ctx.LiftN n 0 Γ (As ++ Γ) + | succ : Ctx.LiftN n k Γ Γ' → Ctx.LiftN n (k+1) (A::Γ) (A.liftN n k :: Γ') + +theorem Ctx.LiftN.one : Ctx.LiftN 1 0 Γ (A::Γ) := .zero [_] + +theorem Ctx.LiftN.isSuffix (H : Ctx.LiftN n k Γ Γ') : + ∃ Γ₀ As Δ Δ', + As.length = n ∧ Δ.length = k ∧ Δ'.length = k ∧ + Γ = Δ ++ Γ₀ ∧ Γ' = Δ' ++ As ++ Γ₀ := by + induction H with + | @zero Γ As h => exact ⟨Γ, As, [], [], h, rfl, rfl, rfl, rfl⟩ + | succ _ ih => + obtain ⟨_, _, Δ, Δ', hn, hΔ, hΔ', rfl, rfl⟩ := ih + exact ⟨_, _, _ :: Δ, _ :: Δ', hn, by simp [hΔ], by simp [hΔ'], rfl, rfl⟩ + +theorem Ctx.LiftN.comp (h1 : k1 ≤ k2) (h2 : k2 ≤ n1 + k1) : + Ctx.LiftN n1 k1 Γ₀ Γ₁ → Ctx.LiftN n2 k2 Γ₁ Γ₂ → Ctx.LiftN (n1+n2) k1 Γ₀ Γ₂ + | .zero As h, H2 => by + obtain ⟨Γ₀', _, Δ, Δ', hn, hΔ, hΔ', eq, rfl⟩ := H2.isSuffix + obtain ⟨As, rfl, rfl⟩ := (List.append_eq_append_of_length_le (by rwa [h, hΔ])).1 eq.symm + rw [← List.append_assoc] + exact .zero _ (by simp [← h, hΔ, hΔ', hn, Nat.add_left_comm, Nat.add_comm]) + | .succ H1, .succ H2 => + have h1 := Nat.le_of_succ_le_succ h1 + have h2 := Nat.le_of_succ_le_succ h2 + liftN'_liftN' h1 h2 ▸ (H1.comp h1 h2 H2).succ + +inductive Ctx.Lift' : Lift → List VExpr → List VExpr → Prop where + | refl : Ctx.Lift' .refl Γ Γ + | skip : Ctx.Lift' l Γ Γ' → Ctx.Lift' (.skip l) Γ (A :: Γ') + | cons : Ctx.Lift' l Γ Γ' → Ctx.Lift' (.cons l) (A::Γ) (A.lift' l :: Γ') + +theorem Ctx.liftN_iff_lift' : Ctx.LiftN n k Γ Γ' ↔ Ctx.Lift' (.consN (.skipN .refl n) k) Γ Γ' := by + constructor <;> intro h + · induction h with + | zero As => + subst n + induction As with + | nil => simp [Lift'.refl] + | cons _ _ ih => exact .skip ih + | succ _ ih => rw [← lift'_consN_skipN]; exact .cons ih + · induction k generalizing Γ Γ' with + | zero => + obtain ⟨_, rfl, eq⟩ : ∃ As, Γ' = As ++ Γ ∧ As.length = n := by + induction n generalizing Γ' with + | zero => cases h; exact ⟨[], rfl, rfl⟩ + | succ n ih => let .skip h := h; obtain ⟨_, rfl, rfl⟩ := ih h; exact ⟨_::_, rfl, rfl⟩ + exact .zero _ eq + | succ k ih => let .cons h := h; rw [lift'_consN_skipN]; exact .succ (ih h) + +theorem Ctx.Lift'.comp (H1 : Ctx.Lift' l₁ Γ₁ Γ₂) (H2 : Ctx.Lift' l₂ Γ₂ Γ₃) : + Ctx.Lift' (.comp l₁ l₂) Γ₁ Γ₃ := by + induction H2 generalizing l₁ Γ₁ with + | refl => exact H1 + | skip _ ih => exact .skip (ih H1) + | cons H2 ih => + cases H1 with + | refl => exact .cons H2 + | skip H1 => exact .skip (ih H1) + | cons H1 => rw [← VExpr.lift'_comp]; exact .cons (ih H1) + +theorem Ctx.Lift'.of_cons_skip (H : Ctx.Lift' (Lift.consN (.skip l) k) Γ₁ Γ₃) : + ∃ Γ₂, Ctx.Lift' (Lift.consN l k) Γ₁ Γ₂ ∧ Ctx.LiftN 1 k Γ₂ Γ₃ := by + induction k generalizing Γ₁ Γ₃ with + | zero => let .skip H := H; exact ⟨_, H, .one⟩ + | succ k ih => + let .cons (A := A) H := H + let ⟨_, h1, h2⟩ := ih H + refine ⟨_, .cons h1, ?_⟩ + simp only [Ctx.liftN_iff_lift'] at h2 ⊢ + simpa [← VExpr.lift'_comp, ← Lift.consN_comp] using h2.cons (A := lift' A (.consN l k)) + +theorem Ctx.Lift'.depth_zero (h : l.depth = 0) : Ctx.Lift' l Γ Γ' → Γ = Γ' + | .refl => rfl + | .cons (l := l) H => by rw [VExpr.lift'_depth_zero (l := l) h, H.depth_zero (l := l) h] + +variable (Γ₀ : List VExpr) (e₀ A₀ : VExpr) in +inductive Ctx.InstN : Nat → List VExpr → List VExpr → Prop where + | zero : Ctx.InstN 0 (A₀ :: Γ₀) Γ₀ + | succ : Ctx.InstN k Γ Γ' → Ctx.InstN (k+1) (A::Γ) (A.inst e₀ k :: Γ') + +theorem Lookup.lt (H : Lookup Γ i A) : i < Γ.length := by + induction H with + | zero => apply Nat.succ_pos + | succ _ ih => apply Nat.succ_lt_succ ih + +def Lookup.ofLt (hi : i < Γ.length) : {A // Lookup Γ i A} := + match Γ, i with + | _::_, 0 => ⟨_, .zero⟩ + | _::_, _+1 => let ⟨_, h⟩ := ofLt (Nat.lt_of_succ_lt_succ hi); ⟨_, .succ h⟩ + +theorem Lookup.uniq (hA : Lookup Γ i A) (hB : Lookup Γ i B) : A = B := + match hA, hB with + | .zero, .zero => rfl + | .succ hA, .succ hB => Lookup.uniq hA hB ▸ rfl + +theorem Lookup.weak' (W : Ctx.Lift' ρ Γ Γ') (H : Lookup Γ i A) : + Lookup Γ' (ρ.liftVar i) (A.lift' ρ) := by + induction W generalizing i A with + | refl => simp; exact H + | skip W ih => have' := (ih H).succ; rwa [VExpr.lift_eq_lift', ← VExpr.lift'_comp] at this + | cons W ih => + cases H with + | zero => refine' cast _ Lookup.zero; congr 1; simp [VExpr.lift_eq_lift', ← VExpr.lift'_comp] + | succ H => refine' cast _ (ih H).succ; congr 1; simp [VExpr.lift_eq_lift', ← VExpr.lift'_comp] + +theorem Lookup.weakN (W : Ctx.LiftN n k Γ Γ') (H : Lookup Γ i A) : + Lookup Γ' (liftVar n i k) (A.liftN n k) := by + simp [← Lift.liftVar_consN_skipN, ← VExpr.lift'_consN_skipN] + exact H.weak' (Ctx.liftN_iff_lift'.1 W) + +theorem Lookup.weakU_inv (W : Ctx.Lift' ρ Γ Γ') + (H : Lookup Γ' (ρ.liftVar i) A') : ∃ A, A' = A.lift' ρ ∧ Lookup Γ i A := by + induction W generalizing i A' with + | refl => simpa using H + | @skip ρ W _ _ _ ih => + simp at H; let .succ H := H + obtain ⟨_, rfl, h2⟩ := ih H; refine ⟨_, ?_, h2⟩ + rw [VExpr.lift_eq_lift', ← VExpr.lift'_comp]; rfl + | @cons ρ Γ Δ B W ih => + cases i with + | zero => cases H; exact ⟨_, by simp [VExpr.lift_eq_lift', ← VExpr.lift'_comp], .zero⟩ + | succ i => + let .succ (ty := C) H := H + obtain ⟨C, rfl, h⟩ := ih H + refine ⟨_, ?_, .succ h⟩ + simp [VExpr.lift_eq_lift', ← VExpr.lift'_comp] + +theorem Lookup.weak'_iff (W : Ctx.Lift' ρ Γ Γ') : + Lookup Γ' (ρ.liftVar i) (A.lift' ρ) ↔ Lookup Γ i A := by + refine ⟨fun H => ?_, fun H => H.weak' W⟩ + let ⟨_, h1, h2⟩ := H.weakU_inv W + exact VExpr.lift'_inj.1 h1 ▸ h2 + +theorem Lookup.weakN_iff (W : Ctx.LiftN n k Γ Γ') : + Lookup Γ' (liftVar n i k) (A.liftN n k) ↔ Lookup Γ i A := by + simp [← Lift.liftVar_consN_skipN, ← VExpr.lift'_consN_skipN] + exact weak'_iff (Ctx.liftN_iff_lift'.1 W) + +theorem Lookup.instL : Lookup Γ i A → Lookup (Γ.map (VExpr.instL ls)) i (A.instL ls) + | .zero => instL_liftN ▸ .zero + | .succ h => instL_liftN ▸ .succ h.instL + +theorem OnCtx.lookup (h : OnCtx Γ P) (hL : Lookup Γ n A) + (hP : ∀ {Γ A B}, P Γ A → P (B::Γ) A.lift) : P Γ A := + match hL, h with + | .zero, ⟨h1, h2⟩ => hP h2 + | .succ hL, ⟨h1, h2⟩ => hP (h1.lookup hL hP) + +theorem OnCtx.mono (H : ∀ {Γ A}, P Γ A → Q Γ A) : ∀ {Γ}, OnCtx Γ P → OnCtx Γ Q + | [], h => h + | _::_, ⟨h1, h2⟩ => ⟨mono H h1, H h2⟩ + +def CtxClosed : List VExpr → Prop := (OnCtx · fun Γ A => A.ClosedN Γ.length) + +theorem CtxClosed.lookup (h : CtxClosed Γ) (hL : Lookup Γ n A) : A.ClosedN Γ.length := + match hL, h with + | .zero, ⟨h1, h2⟩ => h2.liftN + | .succ hL, ⟨h1, h2⟩ => (CtxClosed.lookup h1 hL).liftN + +theorem Ctx.LiftN.right (h : CtxClosed Γ) (Γ') : Ctx.LiftN Γ'.length Γ.length Γ (Γ ++ Γ') := + match Γ, h with + | [], _ => by simpa using LiftN.zero (Γ := []) Γ' + | A :: Γ, ⟨h1, h2⟩ => by + simpa [h2.liftN_eq (Nat.le_refl _)] using LiftN.succ (LiftN.right h1 Γ') (A := A) + +theorem VStructEta.WF.mono {rule : VStructEta} {env env' : VEnv} + (henv : env ≤ env') (self : VStructEta.WF rule env) : + VStructEta.WF rule env' where + familyType_closed := self.familyType_closed + rebuild_hasType hle := self.rebuild_hasType (henv.trans hle) + +inductive VObject where + | const (n : Name) (ci : VConstant) + | defeq (df : VDefEq) + +namespace VEnv + +theorem addConst_le {env env' : VEnv} (h : env.addConst n ci = some env') : env ≤ env' := by + unfold addConst at h; split at h <;> cases h + exact ⟨fun _ => by simp; split <;> simp_all, by simp [*], by simp [*]⟩ + +theorem addConst_self {env env' : VEnv} (h : env.addConst n ci = some env') : + env'.constants n = some ci := by + unfold addConst at h; split at h <;> cases h; simp + +/-- A successful insertion certifies that its name was fresh in the input +environment. -/ +theorem addConst_fresh {env env' : VEnv} (h : env.addConst n ci = some env') : + env.constants n = none := by + unfold addConst at h + split at h <;> simp_all + +/-- Environment inclusion is preserved when the same fresh constant is +inserted on both sides. This is the commuting square needed to replay a +declaration after an unrelated prefix environment. -/ +theorem LE.addConst {env₁ env₂ env₁' env₂' : VEnv} (henv : env₁ ≤ env₂) + (h₁ : env₁.addConst n ci = some env₁') + (h₂ : env₂.addConst n ci = some env₂') : env₁' ≤ env₂' := by + unfold VEnv.addConst at h₁ h₂ + split at h₁ <;> cases h₁ + split at h₂ <;> cases h₂ + exact { + constants := fun h => by + simp at h ⊢ + split at h <;> split <;> simp_all + exact henv.constants h + defeqs := henv.defeqs + structEtas := henv.structEtas } + +/-- Absence of a constant pulls back along environment growth. -/ +theorem LE.constants_none {env env' : VEnv} (henv : env ≤ env') + (h : env'.constants n = none) : env.constants n = none := by + cases h₀ : env.constants n with + | none => rfl + | some ci => + have := henv.constants h₀ + rw [h] at this + contradiction + +theorem addDefEq_le {env : VEnv} : env ≤ env.addDefEq df := ⟨id, .inr, id⟩ + +theorem addDefEq_self {env : VEnv} : (env.addDefEq df).defeqs df := .inl rfl + +theorem addStructEta_le {env : VEnv} : env ≤ env.addStructEta rule := + ⟨id, id, .inr⟩ + +theorem addStructEta_self {env : VEnv} : + (env.addStructEta rule).structEtas rule := .inl rfl + +def HasObjects (env : VEnv) : List VObject → Prop + | [] => True + | .const n ci :: ls => env.constants n = some ci ∧ env.HasObjects ls + | .defeq df :: ls => env.defeqs df ∧ env.HasObjects ls + +theorem HasObjects.mono {env env' : VEnv} (henv : env ≤ env') : + ∀ {ls}, HasObjects env ls → HasObjects env' ls + | [] => id + | .const .. :: _ => .imp henv.1 (mono henv) + | .defeq .. :: _ => .imp henv.2 (mono henv) + +theorem HasObjects.const {env env' : VEnv} (hls : env.HasObjects ls) + (h : env.addConst n ci = some env') : env'.HasObjects (.const n ci :: ls) := + ⟨addConst_self h, hls.mono (addConst_le h)⟩ + +theorem HasObjects.defeq {env : VEnv} (hls : env.HasObjects ls) : + (addDefEq env df).HasObjects (.defeq df :: ls) := ⟨addDefEq_self, hls.mono addDefEq_le⟩ + +theorem HasObjects.bind_const {env env' : VEnv} (hls : env.HasObjects ls) + (h : env.addConst n ci >>= f = some env') : + ∃ env1, env1.HasObjects (.const n ci :: ls) ∧ f env1 = some env' := + let ⟨env1, h1, henv1⟩ := Option.bind_eq_some_iff.1 h; ⟨env1, hls.const h1, henv1⟩ + +nonrec theorem HasType.bvar (h : Lookup Γ i A): HasType env U Γ (.bvar i) A := .bvar h +theorem HasType.sort (h : l.WF U) : HasType env U Γ (.sort l) (.sort (.succ l)) := + .sortDF h h rfl +theorem HasType.const + (h1 : env.constants c = some ci) (h2 : ∀ l ∈ ls, l.WF U) (h3 : ls.length = ci.uvars) : + HasType env U Γ (.const c ls) (ci.type.instL ls) := + .constDF h1 h2 h2 h3 (.rfl fun _ _ => rfl) +theorem HasType.app (h1 : HasType env U Γ f (.forallE A B)) (h2 : HasType env U Γ a A) : + HasType env U Γ (.app f a) (B.inst a) := .appDF h1 h2 +theorem HasType.lam (h1 : HasType env U Γ A (.sort u)) (h2 : HasType env U (A::Γ) body B) : + HasType env U Γ (.lam A body) (.forallE A B) := .lamDF h1 h2 +theorem HasType.forallE + (h1 : HasType env U Γ A (.sort u)) (h2 : HasType env U (A::Γ) body (.sort v)) : + HasType env U Γ (.forallE A body) (.sort (.imax u v)) := .forallEDF h1 h2 +theorem IsDefEq.defeq (h1 : IsDefEq env U Γ A B (.sort u)) + (h2 : HasType env U Γ e A) : HasType env U Γ e B := .defeqDF h1 h2 +theorem IsDefEq.defeq' (h1 : IsDefEq env U Γ A B (.sort u)) + (h2 : HasType env U Γ e B) : HasType env U Γ e A := .defeq h1.symm h2 + +theorem IsType.forallE : IsType env U Γ A → IsType env U (A::Γ) body → + IsType env U Γ (.forallE A body) + | ⟨_, h1⟩, ⟨_, h2⟩ => ⟨_, .forallE h1 h2⟩ + +theorem IsDefEq.hasType {env : VEnv} (H : env.IsDefEq U Γ e1 e2 A) : + env.HasType U Γ e1 A ∧ env.HasType U Γ e2 A := ⟨H.trans H.symm, H.symm.trans H⟩ + +theorem IsDefEq.toU {env : VEnv} (H : env.IsDefEq U Γ e1 e2 A) : env.IsDefEqU U Γ e1 e2 := ⟨_, H⟩ + +theorem IsDefEqU.refl {env : VEnv} (h1 : e.WF env U Γ) : env.IsDefEqU U Γ e e := h1 +theorem IsDefEqU.symm {env : VEnv} (h1 : env.IsDefEqU U Γ e₁ e₂) : env.IsDefEqU U Γ e₂ e₁ := + h1.imp fun _ => (·.symm) + +inductive Ordered : VEnv → Prop where + | empty : Ordered ∅ + | const : + Ordered env → ci.WF env → + env.addConst n ci = some env' → Ordered env' + | defeq : Ordered env → df.WF env → Ordered (env.addDefEq df) + | structEta : Ordered env → rule.WF env → Ordered (env.addStructEta rule) + +def OnTypes (env : VEnv) (P : Nat → VExpr → VExpr → Prop) : Prop := + (∀ {n ci}, env.constants n = some ci → ∃ u, P ci.uvars ci.type (.sort u)) ∧ + (∀ {df}, env.defeqs df → P df.uvars df.lhs df.type ∧ P df.uvars df.rhs df.type) + +theorem OnTypes.mono (henv : env' ≤ env) (hP : ∀ {U e A}, P U e A → P' U e A) + (H : OnTypes env P) : OnTypes env' P' := + ⟨fun hci => (H.1 (henv.1 hci)).imp fun _ => hP, fun hdf => (H.2 (henv.2 hdf)).imp hP hP⟩ + +theorem Ordered.induction (motive : VEnv → Nat → VExpr → VExpr → Prop) + (mono : ∀ {env env' U e A}, env ≤ env' → motive env U e A → motive env' U e A) + (type : ∀ {env U e A}, + Ordered env → OnTypes env (motive env) → HasType env U [] e A → motive env U e A) + (H : Ordered env) : OnTypes env (motive env) := by + induction H with + | empty => exact ⟨nofun, nofun⟩ + | const h1 h2 h3 ih => + apply OnTypes.mono .rfl (mono (addConst_le h3)) + unfold addConst at h3; split at h3 <;> cases h3 + refine ⟨fun h => ?_, ih.2⟩ + simp at h; split at h + · cases h + let ⟨_, ht⟩ := h2 + exact ⟨_, type h1 ih ht⟩ + · exact ih.1 h + | defeq h1 h2 ih => + apply OnTypes.mono .rfl (mono addDefEq_le) + refine ⟨ih.1, fun hdf => ?_⟩ + simp [addDefEq] at hdf + obtain rfl | hdf := hdf + · let ⟨hl, hr⟩ := h2 + exact ⟨type h1 ih hl, type h1 ih hr⟩ + · exact ih.2 hdf + | structEta _ _ ih => + exact OnTypes.mono .rfl (mono addStructEta_le) ih + +variable (env : VEnv) (U : Nat) (Γ₀ : List VExpr) in +inductive IsDefEqCtx : List VExpr → List VExpr → Prop + | zero : IsDefEqCtx Γ₀ Γ₀ + | succ : IsDefEqCtx Γ₁ Γ₂ → env.IsDefEq U Γ₁ A₁ A₂ (.sort u) → IsDefEqCtx (A₁ :: Γ₁) (A₂ :: Γ₂) + +theorem IsDefEqCtx.length_eq : IsDefEqCtx env U Γ₀ Γ₁ Γ₂ → Γ₁.length = Γ₂.length + | .zero => rfl + | .succ h _ => congrArg Nat.succ h.length_eq + +theorem IsDefEqCtx.isSuffix : IsDefEqCtx env U Γ₀ Γ₁ Γ₂ → Γ₀ <:+ Γ₁ ∧ Γ₀ <:+ Γ₂ + | .zero => ⟨List.suffix_refl _, List.suffix_refl _⟩ + | .succ h _ => + let ⟨h1, h2⟩ := h.isSuffix + ⟨h1.trans (List.suffix_cons _ _), h2.trans (List.suffix_cons _ _)⟩ + +variable! (H₀ : OnCtx Γ₀ (IsType env U)) in +theorem IsDefEqCtx.isType' : IsDefEqCtx env U Γ₀ Γ₁ Γ₂ → OnCtx Γ₁ (env.IsType U) + | .zero => H₀ + | .succ h1 h2 => ⟨h1.isType', _, h2.hasType.1⟩ + +theorem IsDefEqCtx.isType (H : IsDefEqCtx env U [] Γ₁ Γ₂) : OnCtx Γ₁ (env.IsType U) := + H.isType' (by trivial) + +theorem IsDefEqCtx.refl : ∀ {Γ}, OnCtx Γ (env.IsType U) → IsDefEqCtx env U [] Γ Γ + | [], _ => .zero + | _::_, ⟨h1, _, h2⟩ => .succ (.refl h1) h2 + +variable! (henv : OnTypes env fun _ e A => e.ClosedN ∧ A.ClosedN) in +theorem IsDefEq.closedN' (H : env.IsDefEq U Γ e1 e2 A) (hΓ : CtxClosed Γ) : + e1.ClosedN Γ.length ∧ e2.ClosedN Γ.length ∧ A.ClosedN Γ.length := by + induction H using IsDefEq.rec + (motive_2 := fun _ _ _ _ _ => True) with + | bvar h => exact ⟨h.lt, h.lt, hΓ.lookup h⟩ + | constDF h1 => + let ⟨_, h, _⟩ := henv.1 h1 + exact ⟨trivial, trivial, h.instL.mono (Nat.zero_le _)⟩ + | sortDF => exact ⟨trivial, trivial, trivial⟩ + | symm _ ih => let ⟨h1, h2, h3⟩ := ih hΓ; exact ⟨h2, h1, h3⟩ + | trans _ _ ih1 ih2 => exact ⟨(ih1 hΓ).1, (ih2 hΓ).2.1, (ih1 hΓ).2.2⟩ + | appDF _ _ ih1 ih2 => + let ⟨hf, hf', _, hB⟩ := ih1 hΓ + let ⟨ha, ha', _⟩ := ih2 hΓ + exact ⟨⟨hf, ha⟩, ⟨hf', ha'⟩, hB.inst ha⟩ + | lamDF _ _ ih1 ih2 => + let ⟨hA, hA', _⟩ := ih1 hΓ + let ⟨hb, hb', hB⟩ := ih2 ⟨hΓ, hA⟩ + exact ⟨⟨hA, hb⟩, ⟨hA', hb'⟩, hA, hB⟩ + | forallEDF _ _ ih1 ih2 => + let ⟨hA, hA', _⟩ := ih1 hΓ + let ⟨hb, hb', _⟩ := ih2 ⟨hΓ, hA⟩ + exact ⟨⟨hA, hb⟩, ⟨hA', hb'⟩, trivial⟩ + | defeqDF _ _ ih1 ih2 => exact ⟨(ih2 hΓ).1, (ih2 hΓ).2.1, (ih1 hΓ).2.1⟩ + | beta _ _ ih1 ih2 => + let ⟨he', _, hA⟩ := ih2 hΓ + let ⟨he, _, hB⟩ := ih1 ⟨hΓ, hA⟩ + exact ⟨⟨⟨hA, he⟩, he'⟩, he.inst he', hB.inst he'⟩ + | eta _ ih => + let ⟨he, _, hA, hB⟩ := ih hΓ + exact ⟨⟨hA, he.liftN, Nat.succ_pos _⟩, he, hA, hB⟩ + | structEta _ _ _ _ _ _ _ _ ihMajor ihRebuild => + let ⟨hmajor, _, htype⟩ := ihMajor hΓ + let ⟨hrebuild, _, _⟩ := ihRebuild hΓ + exact ⟨hrebuild, hmajor, htype⟩ + | proofIrrel _ _ _ _ ih2 ih3 => + let ⟨hh, _, _⟩ := ih2 hΓ + let ⟨hh', _, hp⟩ := ih3 hΓ + exact ⟨hh, hh', hp⟩ + | extra h1 _ _ => + let ⟨⟨hl, _⟩, ⟨hr, hA⟩⟩ := henv.2 h1 + exact ⟨ + hl.instL.mono (Nat.zero_le _), + hr.instL.mono (Nat.zero_le _), + hA.instL.mono (Nat.zero_le _)⟩ + | nil | cons => trivial + +theorem Ordered.closed (H : Ordered env) : env.OnTypes fun _ e A => e.ClosedN ∧ A.ClosedN := + H.induction _ (fun _ => id) fun _ ih h => (IsDefEq.closedN' ih h trivial).2 + +theorem Ordered.closedC (H : Ordered env) + (h : env.constants n = some ci) : ci.type.ClosedN := + let ⟨_, h⟩ := H.closed.1 h; h.1 + +theorem IsDefEq.closedN {env : VEnv} (henv : env.Ordered) + (H : env.IsDefEq U Γ e1 e2 A) (hΓ : CtxClosed Γ) : e1.ClosedN Γ.length := + (H.closedN' henv.closed hΓ).1 + +theorem _root_.Ix.Theory.Named.VExpr.WF.closedN {env : VEnv} (henv : env.Ordered) + (H : VExpr.WF env U Γ e) (hΓ : CtxClosed Γ) : e.ClosedN Γ.length := + let ⟨_, h⟩ := H; h.closedN henv hΓ + +variable! (henv : Ordered env) in +theorem IsDefEqCtx.closed (H : CtxClosed Γ₀) : + IsDefEqCtx env U Γ₀ Γ₁ Γ₂ → CtxClosed Γ₁ ∧ CtxClosed Γ₂ + | .zero => ⟨H, H⟩ + | .succ h1 h2 => + have ⟨c1, c2⟩ := h1.closed H + ⟨⟨c1, h2.closedN henv c1⟩, ⟨c2, by simpa [h1.length_eq] using h2.symm.closedN henv c1⟩⟩ + +variable! {env env' : VEnv} (henv : env ≤ env') in +theorem IsDefEq.mono (H : env.IsDefEq U Γ e1 e2 A) : env'.IsDefEq U Γ e1 e2 A := by + induction H using IsDefEq.rec + (motive_2 := fun Γ A es B _ => env'.SpineWF U Γ A es B) with + | bvar h => exact .bvar h + | constDF h1 h2 h3 h4 h5 => exact .constDF (henv.1 h1) h2 h3 h4 h5 + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | symm _ ih => exact .symm ih + | trans _ _ ih1 ih2 => exact .trans ih1 ih2 + | appDF _ _ ih1 ih2 => exact .appDF ih1 ih2 + | lamDF _ _ ih1 ih2 => exact .lamDF ih1 ih2 + | forallEDF _ _ ih1 ih2 => exact .forallEDF ih1 ih2 + | defeqDF _ _ ih1 ih2 => exact .defeqDF ih1 ih2 + | beta _ _ ih1 ih2 => exact .beta ih1 ih2 + | eta _ ih => exact .eta ih + | structEta hreg hlevels hlevelsLength hparamsLength _ _ _ + ihSpine ihMajor ihRebuild => + exact .structEta (henv.structEtas hreg) hlevels hlevelsLength + hparamsLength ihSpine ihMajor ihRebuild + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel ih1 ih2 ih3 + | extra h1 h2 h3 => exact .extra (henv.2 h1) h2 h3 + | nil => exact .nil + | cons _ _ ihType ihRest => exact .cons ihType ihRest + +theorem HasType.mono {env env' : VEnv} (henv : env ≤ env') : + env.HasType U Γ e A → env'.HasType U Γ e A := IsDefEq.mono henv + +theorem SpineWF.mono {env env' : VEnv} (henv : env ≤ env') {U : Nat} + {Γ : List VExpr} : ∀ {es A B}, env.SpineWF U Γ A es B → + env'.SpineWF U Γ A es B + | [], _, _, .nil => .nil + | _ :: _, _, _, .cons he hrest => + .cons (he.mono henv) (SpineWF.mono henv hrest) + +theorem SpineWF.nil_inv {env : VEnv} (h : env.SpineWF U Γ A [] B) : A = B := by + cases h + rfl + +theorem SpineWF.cons_inv {env : VEnv} + (h : env.SpineWF U Γ A (e :: es) B) : + ∃ A₁ A₂, A = .forallE A₁ A₂ ∧ + env.HasType U Γ e A₁ ∧ env.SpineWF U Γ (A₂.inst e) es B := by + cases h with + | cons he hrest => exact ⟨_, _, rfl, he, hrest⟩ + +theorem IsType.mono {env env' : VEnv} (henv : env ≤ env') : env.IsType U Γ A → env'.IsType U Γ A + | ⟨u, h⟩ => ⟨u, h.mono henv⟩ + +theorem IsDefEqU.mono {env env' : VEnv} (henv : env ≤ env') : + env.IsDefEqU U Γ e1 e2 → env'.IsDefEqU U Γ e1 e2 + | ⟨u, h⟩ => ⟨u, h.mono henv⟩ + +end VEnv + +theorem VExpr.WF.mono {env env' : VEnv} (henv : env ≤ env') {e : VExpr} : + e.WF env U Γ → e.WF env' U Γ + | ⟨u, h⟩ => ⟨u, h.mono henv⟩ + +theorem VConstant.WF.mono {env env' : VEnv} (henv : env ≤ env') {ci : VConstant} : + ci.WF env → ci.WF env' + | ⟨u, h⟩ => ⟨u, h.mono henv⟩ + +theorem VDefEq.WF.mono {env env' : VEnv} (henv : env ≤ env') {df : VDefEq} : df.WF env → df.WF env' + | ⟨h1, h2⟩ => ⟨h1.mono henv, h2.mono henv⟩ + +namespace VEnv + +theorem Ordered.constWF (H : Ordered env) (h : env.constants n = some ci) : ci.WF env := by + induction H with + | empty => cases h + | const _ h2 h3 ih => + refine .mono (addConst_le h3) ?_ + unfold addConst at h3; split at h3 <;> cases h3 + simp at h; split at h + · cases h; exact h2 + · exact ih h + | defeq _ _ ih => exact .mono addDefEq_le (ih h) + | structEta _ _ ih => exact .mono addStructEta_le (ih h) + +theorem Ordered.defEqWF (H : Ordered env) (h : env.defeqs df) : df.WF env := by + induction H with + | empty => cases h + | const _ _ h3 ih => + refine .mono (addConst_le h3) (ih ?_) + unfold addConst at h3; split at h3 <;> cases h3; exact h + | defeq _ _ ih => + refine .mono addDefEq_le ?_ + obtain rfl | h := h + · assumption + · exact ih h + | structEta _ _ ih => exact .mono addStructEta_le (ih h) + +theorem Ordered.structEtaWF (H : Ordered env) (h : env.structEtas rule) : + VStructEta.WF rule env := by + induction H with + | empty => cases h + | const _ _ hadd ih => + refine VStructEta.WF.mono (addConst_le hadd) (ih ?_) + unfold VEnv.addConst at hadd + split at hadd <;> cases hadd + exact h + | defeq _ _ ih => exact VStructEta.WF.mono addDefEq_le (ih h) + | structEta _ hwf ih => + obtain rfl | h := h + · exact VStructEta.WF.mono addStructEta_le hwf + · exact VStructEta.WF.mono addStructEta_le (ih h) + +variable! (henv : Ordered env) in +theorem CtxWF.closed (h : OnCtx Γ (IsType env U)) : CtxClosed Γ := + match Γ, h with + | [], _ => trivial + | _::_, ⟨h1, _, h2⟩ => ⟨closed h1, h2.closedN henv (closed h1)⟩ + +variable {env : VEnv} in +theorem IsDefEq.levelWF (H : env.IsDefEq U Γ e1 e2 A) (W : OnCtx Γ fun _ A => A.LevelWF U) : + e1.LevelWF U ∧ e2.LevelWF U ∧ A.LevelWF U := by + induction H using IsDefEq.rec + (motive_2 := fun _ _ _ _ _ => True) with + | bvar h => + refine ⟨⟨⟩, ⟨⟩, ?_⟩ + induction h with + | zero => exact W.2.liftN + | succ _ ih => exact (ih W.1).liftN + | symm _ ih => let ⟨he, he', hA⟩ := ih W; exact ⟨he', he, hA⟩ + | trans _ _ ih1 ih2 => let ⟨he1, _, hA⟩ := ih1 W; let ⟨_, he3, _⟩ := ih2 W; exact ⟨he1, he3, hA⟩ + | sortDF h1 h2 => exact ⟨h1, h2, h1⟩ + | constDF _ h2 h3 => exact ⟨h2, h3, .instL h2⟩ + | appDF _ _ ih1 ih2 => + let ⟨hf, hf', _, hB⟩ := ih1 W; let ⟨ha, ha', _⟩ := ih2 W + exact ⟨⟨hf, ha⟩, ⟨hf', ha'⟩, hB.inst ha⟩ + | lamDF _ _ ih1 ih2 => + let ⟨hA, hA', _⟩ := ih1 W; let ⟨hb, hb', hB⟩ := ih2 ⟨W, hA⟩ + exact ⟨⟨hA, hb⟩, ⟨hA', hb'⟩, hA, hB⟩ + | forallEDF _ _ ih1 ih2 => + let ⟨hA, hA', hu⟩ := ih1 W; let ⟨hb, hb', hv⟩ := ih2 ⟨W, hA⟩ + exact ⟨⟨hA, hb⟩, ⟨hA', hb'⟩, hu, hv⟩ + | defeqDF _ _ ih1 ih2 => let ⟨_, hB, _⟩ := ih1 W; let ⟨he1, he2, _⟩ := ih2 W; exact ⟨he1, he2, hB⟩ + | beta _ _ ih1 ih2 => + let ⟨he', _, hA⟩ := ih2 W; let ⟨he, _, hB⟩ := ih1 ⟨W, hA⟩ + exact ⟨⟨⟨hA, he⟩, he'⟩, he.inst he', hB.inst he'⟩ + | eta _ ih => let ⟨he, _, hA, hB⟩ := ih W; exact ⟨⟨hA, he.liftN, ⟨⟩⟩, he, hA, hB⟩ + | structEta _ _ _ _ _ _ _ _ ihMajor ihRebuild => + let ⟨hmajor, _, htype⟩ := ihMajor W + let ⟨hrebuild, _, _⟩ := ihRebuild W + exact ⟨hrebuild, hmajor, htype⟩ + | proofIrrel _ _ _ _ ih2 ih3 => + let ⟨hh, _, hp⟩ := ih2 W; let ⟨hh', _, _⟩ := ih3 W + exact ⟨hh, hh', hp⟩ + | extra _ h2 => exact ⟨.instL h2, .instL h2, .instL h2⟩ + | nil | cons => trivial + +theorem HasType.const0 (H : env.constants c = some ci) (wf : ci.WF env) : + HasType env ci.uvars [] (.const c (VLevel.params ci.uvars)) ci.type := by + have := const H (ls := VLevel.params ci.uvars) VLevel.params_wf VLevel.params_length (Γ := []) + have ⟨_, h⟩ := wf + rwa [(IsDefEq.levelWF h trivial).1.instL_id] at this + +theorem IsDefEq.extra0 (H : env.defeqs df) (wf : df.WF env) : + IsDefEq env df.uvars [] df.lhs df.rhs df.type := by + have := extra H (ls := VLevel.params df.uvars) VLevel.params_wf VLevel.params_length (Γ := []) + let ⟨_, h2, h3⟩ := IsDefEq.levelWF wf.2 trivial + rwa [(IsDefEq.levelWF wf.1 trivial).1.instL_id, h2.instL_id, h3.instL_id] at this + +variable! (henv : Ordered env) in +theorem IsDefEq.weakN (W : Ctx.LiftN n k Γ Γ') (H : env.IsDefEq U Γ e1 e2 A) : + env.IsDefEq U Γ' (e1.liftN n k) (e2.liftN n k) (A.liftN n k) := by + induction H using IsDefEq.rec + (motive_2 := fun Γ A es B _ => ∀ {k Γ'}, Ctx.LiftN n k Γ Γ' → + env.SpineWF U Γ' (A.liftN n k) + (es.map fun e => e.liftN n k) (B.liftN n k)) + generalizing k Γ' with + | bvar h => refine .bvar (h.weakN W) + | symm _ ih => exact .symm (ih W) + | trans _ _ ih1 ih2 => exact .trans (ih1 W) (ih2 W) + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | constDF h1 h2 h3 h4 h5 => + rw [(henv.closedC h1).instL.liftN_eq (Nat.zero_le _)] + exact .constDF h1 h2 h3 h4 h5 + | appDF _ _ ih1 ih2 => exact liftN_inst_hi .. ▸ .appDF (ih1 W) (ih2 W) + | lamDF _ _ ih1 ih2 => exact .lamDF (ih1 W) (ih2 W.succ) + | forallEDF _ _ ih1 ih2 => exact .forallEDF (ih1 W) (ih2 W.succ) + | defeqDF _ _ ih1 ih2 => exact .defeqDF (ih1 W) (ih2 W) + | beta _ _ ih1 ih2 => + exact VExpr.liftN_inst_hi .. ▸ VExpr.liftN_instN_hi .. ▸ .beta (ih1 W.succ) (ih2 W) + | eta _ ih => + have := IsDefEq.eta (ih W) + simp [liftN]; rwa [← lift_liftN'] + | @structEta rule levels _ params _ major hreg hlevels + hlevelsLength hparamsLength _ _ _ + ihSpine ihMajor ihRebuild => + have hparamsSpine := ihSpine W + rw [(henv.structEtaWF hreg).familyType_closed.instL.liftN_eq + (Nat.zero_le _)] at hparamsSpine + have hmajor := ihMajor W + rw [VStructEta.structureType_liftN] at hmajor + have hrebuild := ihRebuild W + rw [VStructEta.rebuild_liftN rule levels params major + hparamsLength n k, VStructEta.structureType_liftN] at hrebuild + have hout := IsDefEq.structEta hreg hlevels hlevelsLength + (by simpa using hparamsLength) hparamsSpine hmajor hrebuild + simpa only [VStructEta.rebuild_liftN rule levels params major + hparamsLength n k, VStructEta.structureType_liftN] using hout + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel (ih1 W) (ih2 W) (ih3 W) + | extra h1 h2 h3 => + have ⟨⟨hA1, _⟩, hA2, hA3⟩ := henv.closed.2 h1 + rw [ + hA1.instL.liftN_eq (Nat.zero_le _), + hA2.instL.liftN_eq (Nat.zero_le _), + hA3.instL.liftN_eq (Nat.zero_le _)] + exact .extra h1 h2 h3 + | nil => exact .nil + | cons _ _ ihType ihRest => + exact .cons (ihType (by assumption)) (by + simpa only [VExpr.liftN_inst_hi] using ihRest (by assumption)) + +variable! (henv : Ordered env) in +theorem HasType.weakN (W : Ctx.LiftN n k Γ Γ') (H : env.HasType U Γ e A) : + env.HasType U Γ' (e.liftN n k) (A.liftN n k) := IsDefEq.weakN henv W H + +theorem SpineWF.weakN {env : VEnv} (henv : env.Ordered) + (W : Ctx.LiftN n k Γ Γ') : + ∀ {es A B}, env.SpineWF U Γ A es B → + env.SpineWF U Γ' (A.liftN n k) + (es.map fun e => e.liftN n k) (B.liftN n k) + | [], _, _, .nil => .nil + | _ :: _, _, _, .cons he hrest => + .cons (he.weakN henv W) (by + simpa only [VExpr.liftN_inst_hi] using SpineWF.weakN henv W hrest) + +variable! (henv : Ordered env) in +theorem IsType.weakN (W : Ctx.LiftN n k Γ Γ') (H : env.IsType U Γ A) : + env.IsType U Γ' (A.liftN n k) := let ⟨_, h⟩ := H; ⟨_, h.weakN henv W⟩ + +variable! (henv : Ordered env) in +theorem IsDefEq.weak (H : env.IsDefEq U Γ e1 e2 A) : + env.IsDefEq U (B::Γ) e1.lift e2.lift A.lift := H.weakN henv .one + +variable! (henv : Ordered env) in +theorem IsDefEqU.weak (H : env.IsDefEqU U Γ e1 e2) : + env.IsDefEqU U (B::Γ) e1.lift e2.lift := let ⟨_, H⟩ := H; ⟨_, H.weak henv⟩ + +variable! (henv : Ordered env) in +theorem IsDefEqU.weakN (W : Ctx.LiftN n k Γ Γ') (H : env.IsDefEqU U Γ e1 e2) : + env.IsDefEqU U Γ' (e1.liftN n k) (e2.liftN n k) := let ⟨_, H⟩ := H; ⟨_, H.weakN henv W⟩ + +variable! (henv : Ordered env) in +theorem IsDefEq.weakR (hΓ : CtxClosed Γ) (H : env.IsDefEq U Γ e1 e2 A) (Γ') : + env.IsDefEq U (Γ ++ Γ') e1 e2 A := by + have ⟨h1, h2, h3⟩ := H.closedN' henv.closed hΓ + simpa [h1.liftN_eq, h2.liftN_eq, h3.liftN_eq] using H.weakN henv (.right hΓ Γ') + +variable! (henv : Ordered env) in +theorem IsDefEq.weak0 (H : env.IsDefEq U [] e1 e2 A) : env.IsDefEq U Γ e1 e2 A := + H.weakR henv (Γ := []) ⟨⟩ _ + +variable! (henv : Ordered env) in +nonrec theorem HasType.weak0 (H : env.HasType U [] e A) : env.HasType U Γ e A := H.weak0 henv + +variable! (henv : Ordered env) in +theorem IsDefEqU.weak0 (H : env.IsDefEqU U [] e1 e2) : env.IsDefEqU U Γ e1 e2 := + let ⟨_, H⟩ := H; ⟨_, H.weak0 henv⟩ + +variable! (henv : Ordered env) in +theorem IsDefEq.weak' (W : Ctx.Lift' l Γ Γ') (H : env.IsDefEq U Γ e1 e2 A) : + env.IsDefEq U Γ' (e1.lift' l) (e2.lift' l) (A.lift' l) := by + generalize e : l.depth = n + induction n generalizing l Γ' with + | zero => simpa [lift'_depth_zero e, W.depth_zero e] using H + | succ n ih => + obtain ⟨l, k, rfl, rfl⟩ := Lift.depth_succ e + have ⟨Γ₁, W1, W2⟩ := W.of_cons_skip + rw [Lift.consN_skip_eq, lift'_comp, lift'_comp, lift'_comp, ← Lift.skipN_one, + lift'_consN_skipN, lift'_consN_skipN, lift'_consN_skipN] + exact (ih W1 Lift.depth_consN).weakN henv W2 + +variable! (henv : Ordered env) in +theorem HasType.weak' (W : Ctx.Lift' l Γ Γ') (H : env.HasType U Γ e A) : + env.HasType U Γ' (e.lift' l) (A.lift' l) := IsDefEq.weak' henv W H + +variable! (henv : Ordered env) in +theorem IsType.weak' (W : Ctx.Lift' l Γ Γ') (H : env.IsType U Γ A) : + env.IsType U Γ' (A.lift' l) := let ⟨_, h⟩ := H; ⟨_, h.weak' henv W⟩ + +variable! (henv : Ordered env) in +theorem IsDefEqU.weak' (W : Ctx.Lift' n Γ Γ') (H : env.IsDefEqU U Γ e1 e2) : + env.IsDefEqU U Γ' (e1.lift' n) (e2.lift' n) := let ⟨_, H⟩ := H; ⟨_, H.weak' henv W⟩ + +theorem IsType.lookup (henv : Ordered env) (h : OnCtx Γ (IsType env U)) (hL : Lookup Γ n A) : + env.IsType U Γ A := h.lookup hL <| .weakN henv .one + +variable! {env : VEnv} {ls : List VLevel} (hls : ∀ l ∈ ls, l.WF U') in +theorem IsDefEq.instL (H : env.IsDefEq U Γ e1 e2 A) : + env.IsDefEq U' (Γ.map (VExpr.instL ls)) (e1.instL ls) (e2.instL ls) (A.instL ls) := by + induction H using IsDefEq.rec + (motive_2 := fun Γ A es B _ => + env.SpineWF U' (Γ.map (VExpr.instL ls)) (A.instL ls) + (es.map (VExpr.instL ls)) (B.instL ls)) with + | bvar h => refine .bvar h.instL + | symm _ ih => exact .symm ih + | trans _ _ ih1 ih2 => exact .trans ih1 ih2 + | sortDF _ _ h3 => + exact .sortDF (VLevel.WF.inst hls) (VLevel.WF.inst hls) (VLevel.inst_congr_l h3) + | @constDF _ _ ls₁ ls₂ _ h1 h2 h3 h4 h5 => + simp [VExpr.instL, VExpr.instL_instL] + exact .constDF h1 (by simp [VLevel.WF.inst hls]) (by simp [VLevel.WF.inst hls]) + (by simp [h4]) (by simpa using h5.imp fun _ _ => VLevel.inst_congr_l) + | appDF _ _ ih1 ih2 => exact VExpr.instL_instN ▸ .appDF ih1 ih2 + | lamDF _ _ ih1 ih2 => exact .lamDF ih1 ih2 + | forallEDF _ _ ih1 ih2 => exact .forallEDF ih1 ih2 + | defeqDF _ _ ih1 ih2 => exact .defeqDF ih1 ih2 + | beta _ _ ih1 ih2 => simpa using .beta ih1 ih2 + | eta _ ih => simpa [VExpr.instL] using .eta ih + | @structEta rule levels _ params _ major hreg hlevels + hlevelsLength hparamsLength _ _ _ + ihSpine ihMajor ihRebuild => + have hlevels' : ∀ level ∈ levels.map (VLevel.inst ls), + level.WF U' := by + intro level hlevel + obtain ⟨source, hsource, heq⟩ := List.mem_map.1 hlevel + rw [← heq] + exact VLevel.WF.inst hls + rw [VStructEta.structureType_instL] at ihMajor + rw [VStructEta.rebuild_instL, + VStructEta.structureType_instL] at ihRebuild + rw [VExpr.instL_instL] at ihSpine + have hout := IsDefEq.structEta hreg hlevels' + (by simpa using hlevelsLength) + (by simpa using hparamsLength) ihSpine ihMajor ihRebuild + simpa only [VStructEta.rebuild_instL, + VStructEta.structureType_instL] using hout + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel ih1 ih2 ih3 + | extra h1 h2 h3 => + simp [VExpr.instL_instL] + exact .extra h1 (by simp [VLevel.WF.inst hls]) (by simp [h3]) + | nil => exact .nil + | cons _ _ ihType ihRest => + exact .cons ihType (by simpa using ihRest) + +theorem HasType.instL {env : VEnv} (hls : ∀ l ∈ ls, l.WF U') (H : env.HasType U Γ e A) : + env.HasType U' (Γ.map (VExpr.instL ls)) (e.instL ls) (A.instL ls) := IsDefEq.instL hls H + +theorem SpineWF.instL {env : VEnv} (hls : ∀ l ∈ ls, l.WF U') : + ∀ {es A B}, env.SpineWF U Γ A es B → + env.SpineWF U' (Γ.map (VExpr.instL ls)) (A.instL ls) + (es.map (VExpr.instL ls)) (B.instL ls) + | [], _, _, .nil => .nil + | _ :: _, _, _, .cons he hrest => + .cons (he.instL hls) (by + simpa using SpineWF.instL hls hrest) + +theorem IsType.instL {env : VEnv} (hls : ∀ l ∈ ls, l.WF U') (H : env.IsType U Γ A) : + env.IsType U' (Γ.map (VExpr.instL ls)) (A.instL ls) := let ⟨_, h⟩ := H; ⟨_, h.instL hls⟩ + +theorem IsDefEqU.instL {env : VEnv} (hls : ∀ l ∈ ls, l.WF U') (H : env.IsDefEqU U Γ e1 e2) : + env.IsDefEqU U' (Γ.map (VExpr.instL ls)) (e1.instL ls) (e2.instL ls) := + let ⟨_, h⟩ := H; ⟨_, h.instL hls⟩ + +theorem _root_.Ix.Theory.Named.OnCtx.instL {env : VEnv} (hls : ∀ l ∈ ls, l.WF U') : + ∀ {Γ}, OnCtx Γ (env.IsType U) → OnCtx (Γ.map (VExpr.instL ls)) (env.IsType U') + | [], _ => trivial + | _::_, ⟨H1, H2⟩ => ⟨H1.instL hls, IsType.instL hls H2⟩ + +variable! (henv : Ordered env) (h₀ : env.HasType U Γ₀ e₀ A₀) in +theorem IsDefEq.instN (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) (H : env.IsDefEq U Γ₁ e1 e2 A) : + env.IsDefEq U Γ (e1.inst e₀ k) (e2.inst e₀ k) (A.inst e₀ k) := by + induction H using IsDefEq.rec + (motive_2 := fun Γ₁ A es B _ => ∀ {Γ k}, Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → + env.SpineWF U Γ (A.inst e₀ k) + (es.map fun e => e.inst e₀ k) (B.inst e₀ k)) + generalizing Γ k with + | @bvar _ i ty h => + dsimp [inst] + induction W generalizing i ty with + | zero => + cases h with simp [inst_lift] + | zero => exact h₀ + | succ h => exact .bvar h + | succ _ ih => + cases h with (simp; rw [Nat.add_comm, ← VExpr.liftN_instN_lo (hj := Nat.zero_le _)]) + | zero => exact .bvar .zero + | succ h => exact (ih h).weak henv + | symm _ ih => exact .symm (ih W) + | trans _ _ ih1 ih2 => exact .trans (ih1 W) (ih2 W) + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | constDF h1 h2 h3 h4 h5 => + rw [(henv.closedC h1).instL.instN_eq (Nat.zero_le _)] + exact .constDF h1 h2 h3 h4 h5 + | appDF _ _ ih1 ih2 => exact VExpr.inst_inst_hi .. ▸ .appDF (ih1 W) (ih2 W) + | lamDF _ _ ih1 ih2 => exact .lamDF (ih1 W) (ih2 W.succ) + | forallEDF _ _ ih1 ih2 => exact .forallEDF (ih1 W) (ih2 W.succ) + | defeqDF _ _ ih1 ih2 => exact .defeqDF (ih1 W) (ih2 W) + | beta _ _ ih1 ih2 => + exact VExpr.inst_inst_hi .. ▸ VExpr.inst_inst_hi .. ▸ .beta (ih1 W.succ) (ih2 W) + | eta _ ih => + have := IsDefEq.eta (ih W) + rw [lift, VExpr.liftN_instN_lo (hj := Nat.zero_le _), Nat.add_comm] at this + simpa [inst] + | @structEta rule levels _ params _ major hreg hlevels + hlevelsLength hparamsLength _ _ _ + ihSpine ihMajor ihRebuild => + have hparamsSpine := ihSpine W + rw [(henv.structEtaWF hreg).familyType_closed.instL.instN_eq + (Nat.zero_le _)] at hparamsSpine + have hmajor := ihMajor W + rw [VStructEta.structureType_instN] at hmajor + have hrebuild := ihRebuild W + rw [VStructEta.rebuild_instN rule levels params major e₀ + hparamsLength k, VStructEta.structureType_instN] at hrebuild + have hout := IsDefEq.structEta hreg hlevels hlevelsLength + (by simpa using hparamsLength) hparamsSpine hmajor hrebuild + simpa only [VStructEta.rebuild_instN rule levels params major e₀ + hparamsLength k, VStructEta.structureType_instN] using hout + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel (ih1 W) (ih2 W) (ih3 W) + | extra h1 h2 h3 => + have ⟨⟨hA1, _⟩, hA2, hA3⟩ := henv.closed.2 h1 + rw [ + hA1.instL.instN_eq (Nat.zero_le _), + hA2.instL.instN_eq (Nat.zero_le _), + hA3.instL.instN_eq (Nat.zero_le _)] + exact .extra h1 h2 h3 + | nil => exact .nil + | cons _ _ ihType ihRest => + exact .cons (ihType (by assumption)) (by + simpa only [VExpr.inst0_inst_hi] using ihRest (by assumption)) + +theorem SpineWF.instN {env : VEnv} (henv : env.Ordered) + (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (h₀ : env.HasType U Γ₀ e₀ A₀) : + ∀ {es A B}, env.SpineWF U Γ₁ A es B → + env.SpineWF U Γ (A.inst e₀ k) + (es.map fun e => e.inst e₀ k) (B.inst e₀ k) + | [], _, _, .nil => .nil + | _ :: _, _, _, .cons he hrest => + .cons (IsDefEq.instN henv h₀ W he) (by + simpa only [VExpr.inst0_inst_hi] using + SpineWF.instN henv W h₀ hrest) + +theorem HasType.instN {env : VEnv} (henv : env.Ordered) (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (H : env.HasType U Γ₁ e A) (h₀ : env.HasType U Γ₀ e₀ A₀) : + env.HasType U Γ (e.inst e₀ k) (A.inst e₀ k) := IsDefEq.instN henv h₀ W H + +theorem IsType.instN {env : VEnv} (henv : env.Ordered) (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (H : env.IsType U Γ₁ A) (h₀ : env.HasType U Γ₀ e₀ A₀) : + env.IsType U Γ (A.inst e₀ k) := let ⟨_, h⟩ := H; ⟨_, h.instN henv W h₀⟩ + +theorem IsDefEqU.instN {env : VEnv} (henv : env.Ordered) (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (H : env.IsDefEqU U Γ₁ e1 e2) (h₀ : env.HasType U Γ₀ e₀ A₀) : + env.IsDefEqU U Γ (e1.inst e₀ k) (e2.inst e₀ k) := let ⟨_, h⟩ := H; ⟨_, h.instN henv h₀ W⟩ + +theorem _root_.Ix.Theory.Named.Ctx.InstN.wf (henv : Ordered env) (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (h₀ : env.HasType U Γ₀ e₀ A₀) (H : OnCtx Γ₁ (env.IsType U)) : + OnCtx Γ₀ (env.IsType U) ∧ OnCtx Γ (env.IsType U) := by + induction W with + | zero => exact ⟨H.1, H.1⟩ + | succ W ih => let ⟨h1, h2⟩ := ih H.1; exact ⟨h1, h2, .instN henv W H.2 h₀⟩ + +theorem IsDefEq.defeqDF_l' (henv : Ordered env) (h1 : env.IsDefEq U Γ A A' (.sort u)) + (h2 : env.IsDefEq U (Δ++A::Γ) e1 e2 B) : env.IsDefEq U (Δ++A'::Γ) e1 e2 B := by + have ⟨_, H1, H2⟩ : ∃ Γ', Ctx.LiftN 1 (Δ.length + 1) (Δ ++ A :: Γ) Γ' ∧ + Ctx.InstN (A' :: Γ) (VExpr.bvar 0) (liftN 1 A) Δ.length Γ' (Δ ++ A' :: Γ) := by + clear h1 h2 + induction Δ with + | nil => exact ⟨_, .succ (.one (A := A')), .zero⟩ + | cons B Δ ih => + have ⟨Γ', h1, h2⟩ := ih + exact ⟨_, .succ h1, by simpa [instN_bvar0] using h2.succ (A := liftN 1 B (Δ.length + 1))⟩ + simpa [instN_bvar0] using + instN henv (h1.weakN henv (.one (A := A')) |>.symm.defeq (.bvar .zero)) H2 (.weakN henv H1 h2) + +theorem IsDefEq.defeqDF_l (henv : Ordered env) (h1 : env.IsDefEq U Γ A A' (.sort u)) + (h2 : env.IsDefEq U (A::Γ) e1 e2 B) : env.IsDefEq U (A'::Γ) e1 e2 B := + .defeqDF_l' (Δ := []) henv h1 h2 + +theorem HasType.defeq_l (henv : Ordered env) (h1 : env.IsDefEq U Γ A A' (.sort u)) + (h2 : env.HasType U (A::Γ) e B) : env.HasType U (A'::Γ) e B := h1.defeqDF_l henv h2 + +theorem IsDefEq.defeqDFC' (henv : Ordered env) (h1 : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) + (h2 : env.IsDefEq U (Δ ++ Γ₁) e₁ e₂ A) : env.IsDefEq U (Δ ++ Γ₂) e₁ e₂ A := by + induction h1 generalizing e₁ e₂ A Δ with + | zero => exact h2 + | @succ _ _ _ A₂ _ _ AA ih => + simpa using ih (Δ := Δ ++ [A₂]) (by simpa using AA.defeqDF_l' henv h2) + +theorem IsDefEq.defeqDFC (henv : Ordered env) (h1 : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) + (h2 : env.IsDefEq U Γ₁ e₁ e₂ A) : env.IsDefEq U Γ₂ e₁ e₂ A := .defeqDFC' (Δ := []) henv h1 h2 + +theorem HasType.defeqDFC (henv : Ordered env) (h1 : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) + (h2 : env.HasType U Γ₁ e A) : env.HasType U Γ₂ e A := IsDefEq.defeqDFC henv h1 h2 + +theorem IsType.defeqDFC (henv : Ordered env) (h1 : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) + (h2 : env.IsType U Γ₁ A) : env.IsType U Γ₂ A := h2.imp fun _ => (·.defeqDFC henv h1) + +theorem IsDefEqU.defeqDFC (henv : Ordered env) (h1 : IsDefEqCtx env U Γ₀ Γ₁ Γ₂) + (h2 : env.IsDefEqU U Γ₁ e₁ e₂) : env.IsDefEqU U Γ₂ e₁ e₂ := + let ⟨_, h2⟩ := h2; ⟨_, h2.defeqDFC henv h1⟩ + +theorem IsDefEqCtx.symm (henv : Ordered env) : + IsDefEqCtx env U Γ₀ Γ₁ Γ₂ → IsDefEqCtx env U Γ₀ Γ₂ Γ₁ + | .zero => .zero + | .succ h1 h2 => .succ (h1.symm henv) (h2.symm.defeqDFC henv h1) + +variable! (henv : Ordered env) + (envIH : env.OnTypes fun U e _ => ∀ A B, e = A.forallE B → + env.IsType U [] A ∧ env.IsType U [A] B) in +theorem IsDefEq.forallE_inv' + (H : env.IsDefEq U Γ e1 e2 V) (eq : e1 = A.forallE B ∨ e2 = A.forallE B) : + env.IsType U Γ A ∧ env.IsType U (A::Γ) B := by + induction H using IsDefEq.rec + (motive_2 := fun _ _ _ _ _ => True) + generalizing A B with + | symm _ ih => exact ih eq.symm + | trans _ _ ih1 ih2 + | proofIrrel _ _ _ _ ih1 ih2 => + obtain eq | eq := eq + · exact ih1 (.inl eq) + · exact ih2 (.inr eq) + | forallEDF h1 h2 => + obtain ⟨⟨⟩⟩ | ⟨⟨⟩⟩ := eq + · exact ⟨⟨_, h1.hasType.1⟩, _, h2.hasType.1⟩ + · exact ⟨⟨_, h1.hasType.2⟩, _, h2.hasType.2.defeq_l henv h1⟩ + | defeqDF _ _ _ ih2 => exact ih2 eq + | @beta _ _ e _ _ h1 h2 ih1 ih2 => + obtain ⟨⟨⟩⟩ | eq := eq + cases e with + | bvar i => + cases i with simp [inst] at eq + | zero => exact ih2 (.inl eq) + | forallE A B => + cases eq + let ⟨A1, A2⟩ := ih1 (.inl rfl) + exact ⟨A1.instN henv .zero h2, A2.instN henv (.succ .zero) h2⟩ + | _ => cases eq + | eta _ ih => + obtain ⟨⟨⟩⟩ | eq := eq + exact ih (.inl eq) + | structEta _ _ _ _ _ _ _ _ ihMajor ihRebuild => + obtain eq | eq := eq + · exact ihRebuild (.inl eq) + · exact ihMajor (.inl eq) + | @extra df ls Γ h1 h2 => + suffices ∀ e, VExpr.instL ls e = VExpr.forallE A B → + (∀ A B, e = VExpr.forallE A B → IsType env df.uvars [] A ∧ IsType env df.uvars [A] B) → + IsType env U Γ A ∧ IsType env U (A :: Γ) B by + have ⟨A1, A2⟩ := envIH.2 h1 + cases eq <;> exact this _ ‹_› ‹_› + intro e eq IH + cases e <;> cases eq; rename_i A B + let ⟨⟨_, A1⟩, v, A2⟩ := IH _ _ rfl + refine ⟨⟨_, (A1.instL h2).weak0 henv⟩, v.inst ls, ?_⟩ + have := (A2.instL h2).weakN henv (.succ (.zero Γ)) + have C1 := (A1.instL h2).closedN henv ⟨⟩ + have C2 := (A2.instL h2).closedN henv ⟨⟨⟩, C1⟩ + rw [C1.liftN_eq (Nat.zero_le _), C2.liftN_eq (by exact Nat.le_refl _)] at this + simpa [liftN] + | nil | cons => trivial + | _ => nomatch eq + +theorem HasType.forallE_inv (henv : Ordered env) (H : env.HasType U Γ (A.forallE B) V) : + env.IsType U Γ A ∧ env.IsType U (A::Γ) B := by + refine H.forallE_inv' henv ?_ (.inl rfl) + exact henv.induction + (fun env U e _ => ∀ A B, e = .forallE A B → IsType env U [] A ∧ IsType env U [A] B) + (fun le H A B eq => (H A B eq).imp (.mono le) (.mono le)) + (fun henv IH H A B eq => H.forallE_inv' henv IH (.inl eq)) + +theorem IsType.forallE_inv (henv : Ordered env) (H : env.IsType U Γ (A.forallE B)) : + env.IsType U Γ A ∧ env.IsType U (A::Γ) B := let ⟨_, h⟩ := H; h.forallE_inv henv + +variable! (henv : Ordered env) in +theorem IsDefEq.sort_inv' + (H : env.IsDefEq U Γ e1 e2 V) (eq : e1 = .sort u ∨ e2 = .sort u) : u.WF U := by + induction H using IsDefEq.rec + (motive_2 := fun _ _ _ _ _ => True) with + | symm _ ih => exact ih eq.symm + | trans _ _ ih1 ih2 + | proofIrrel _ _ _ _ ih1 ih2 => + obtain eq | eq := eq <;> [exact ih1 (.inl eq); exact ih2 (.inr eq)] + | sortDF => obtain ⟨⟨⟩⟩ | ⟨⟨⟩⟩ := eq <;> assumption + | defeqDF _ _ _ ih2 => exact ih2 eq + | @beta _ _ e _ _ h1 _ ih1 ih2 => + obtain ⟨⟨⟩⟩ | eq := eq + cases e with + | bvar i => + cases i with simp [inst] at eq + | zero => exact ih2 (.inl eq) + | _ => cases eq <;> exact ih1 (.inl rfl) + | eta _ ih => + obtain ⟨⟨⟩⟩ | eq := eq + exact ih (.inl eq) + | structEta _ _ _ _ _ _ _ _ ihMajor ihRebuild => + obtain eq | eq := eq + · exact ihRebuild (.inl eq) + · exact ihMajor (.inl eq) + | @extra df ls _ h1 h2 => + suffices ∀ e, VExpr.instL ls e = .sort u → HasType env df.uvars [] e df.type → u.WF U by + have ⟨A1, A2⟩ := henv.defEqWF h1 + cases eq <;> exact this _ ‹_› ‹_› + intro e eq IH + cases e <;> cases eq; rename_i u + exact VLevel.WF.inst h2 + | nil | cons => trivial + | _ => nomatch eq + +theorem IsDefEq.sort_inv_l (henv : Ordered env) (H : env.IsDefEq U Γ (.sort u) e2 V) : u.WF U := + H.sort_inv' henv (.inl rfl) + +theorem IsDefEq.sort_inv_r (henv : Ordered env) (H : env.IsDefEq U Γ e2 (.sort u) V) : u.WF U := + H.sort_inv' henv (.inr rfl) + +theorem HasType.sort_inv (henv : Ordered env) (H : env.HasType U Γ (.sort u) V) : u.WF U := + H.sort_inv_l henv + +theorem IsType.sort_inv (henv : Ordered env) (H : env.IsType U Γ (.sort u)) : u.WF U := + let ⟨_, h⟩ := H; h.sort_inv henv + +variable! (henv : Ordered env) + (envIH : env.OnTypes fun U e A => env.HasType U [] e A ∧ env.IsType U [] A) in +theorem IsDefEq.isType' (hΓ : OnCtx Γ (env.IsType U)) (H : env.IsDefEq U Γ e1 e2 A) : + env.IsType U Γ A := by + induction H using IsDefEq.rec + (motive_2 := fun _ _ _ _ _ => True) with + | bvar h => exact .lookup henv hΓ h + | proofIrrel h1 => exact ⟨_, h1⟩ + | extra h1 h2 => + have ⟨_, _, _, h⟩ := envIH.2 h1 + exact ⟨_, (h.instL h2).weak0 henv⟩ + | sortDF h1 => exact ⟨_, .sort h1⟩ + | constDF h1 h2 => + let ⟨_, h, _⟩ := envIH.1 h1 + exact ⟨_, (h.instL h2).weak0 henv⟩ + | symm _ ih => exact ih hΓ + | trans _ _ ih1 => exact ih1 hΓ + | appDF _ h2 ih1 => exact ((ih1 hΓ).forallE_inv henv).2.instN henv .zero h2.hasType.1 + | lamDF h1 _ _ ih2 => + let ⟨_, h⟩ := ih2 ⟨hΓ, _, h1.hasType.1⟩ + exact ⟨_, .forallE h1.hasType.1 h⟩ + | forallEDF h1 _ ih1 ih2 => + exact ⟨_, .sort ⟨(ih1 hΓ).sort_inv henv, (ih2 ⟨hΓ, _, h1.hasType.1⟩).sort_inv henv⟩⟩ + | defeqDF h1 => exact ⟨_, h1.hasType.2⟩ + | beta _ h2 ih1 ih2 => + have ⟨_, h⟩ := ih2 hΓ + exact (ih1 ⟨hΓ, _, h.hasType.2⟩).instN henv .zero h2 + | eta _ ih => exact ih hΓ + | structEta _ _ _ _ _ _ _ _ ihMajor _ => exact ihMajor hΓ + | nil | cons => trivial + +theorem Ordered.isType (H : Ordered env) : + env.OnTypes fun U e A => env.HasType U [] e A ∧ env.IsType U [] A := + H.induction (fun env U e A => env.HasType U [] e A ∧ env.IsType U [] A) + (fun h1 h2 => h2.imp (.mono h1) (.mono h1)) + (fun henv ih h => ⟨h, h.isType' henv ih trivial⟩) + +theorem IsDefEq.isType (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) + (H : env.IsDefEq U Γ e1 e2 A) : env.IsType U Γ A := H.isType' henv henv.isType hΓ + +theorem IsDefEq.sort_r (henv : Ordered env) + (hΓ : OnCtx Γ (env.IsType U)) (H : env.IsDefEq U Γ e1 e2 (.sort u)) : u.WF U := + (H.isType henv hΓ).sort_inv henv + +theorem IsDefEq.instDF + (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) + (hf : env.IsDefEq U (A::Γ) f f' B) (ha : env.IsDefEq U Γ a a' A) : + env.IsDefEq U Γ (f.inst a) (f'.inst a') (B.inst a) := + have ⟨_, hA⟩ := ha.isType henv hΓ + have ⟨_, hB⟩ := hf.isType henv (Γ := _::_) ⟨hΓ, _, hA⟩ + have H2 {f f' B v} + (hf : env.IsDefEq U (A::Γ) f f' B) + (hi : IsDefEq env U Γ (inst B a) (inst B a') (.sort v)) : + env.IsDefEq U Γ (f.inst a) (f'.inst a') (B.inst a) := + (IsDefEq.beta hf.hasType.1 ha.hasType.1).symm.trans <| + .trans (.appDF (.lamDF hA hf) ha) <| + .defeqDF (.symm hi) (.beta hf.hasType.2 ha.hasType.2) + H2 hf <| H2 hB (HasType.sort (hB.sort_r henv (Γ := _::_) ⟨hΓ, _, hA⟩)) diff --git a/Ix/Theory/Named/Typing/Meta.lean b/Ix/Theory/Named/Typing/Meta.lean new file mode 100644 index 000000000..f17cc9a5a --- /dev/null +++ b/Ix/Theory/Named/Typing/Meta.lean @@ -0,0 +1,54 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.Lemmas + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +namespace VEnv + +theorem with_addConst {P : Prop} {env env' : VEnv} {cis : List VObject} + (henv : Ordered env) + (hci : env.HasObjects cis → ci.WF env) + (IH : ∀ {env1}, Ordered env1 → + env1.HasObjects (.const n ci :: cis) → f env1 = some env' → P) + (hcis : env.HasObjects cis) + (H : (env.addConst n ci >>= f) = some env') : P := by + let ⟨env1, h1, henv1⟩ := Option.bind_eq_some_iff.1 H + refine IH (.const henv (hci hcis) h1) (hcis.const h1) henv1 + +theorem Lookup.zero' (eq : A.lift = ty') : + Lookup (A::Γ) 0 ty' := eq ▸ .zero +theorem Lookup.succ' (h : Lookup Γ n ty) (eq : ty.lift = ty') : + Lookup (A::Γ) (n+1) ty' := eq ▸ .succ h + +syntax "lookup_tac" : tactic +macro_rules | `(tactic| lookup_tac) => `(tactic| + first + | refine Lookup.zero' ?_; exact rfl + | refine Lookup.succ' (ty := ?_) ?_ ?_ <;> [skip; lookup_tac; exact rfl] +) + +theorem HasType.app' (h1 : HasType env U Γ f (.forallE A B)) (h2 : HasType env U Γ a A) + (eq : B.inst a = B') : HasType env U Γ (.app f a) B' := eq ▸ .appDF h1 h2 +theorem HasType.const' + (h1 : constants env c = some ci) + (h2 : ∀ (l : VLevel), l ∈ ls → VLevel.WF uvars l) + (h3 : List.length ls = ci.uvars) + (eq : .instL ls ci.type = ty') : + HasType env uvars Γ (.const c ls) ty' := eq ▸ .const h1 h2 h3 + +syntax "type_tac" : tactic -- TODO: write an actual tactic +macro_rules | `(tactic| type_tac) => `(tactic| + first + | refine HasType.forallE (u := ?_) (v := ?_) ?_ ?_ <;> [skip; skip; type_tac; type_tac] + | refine HasType.sort ?_; decide + | refine HasType.bvar ?_; lookup_tac + | refine HasType.app' (A := ?_) (B := ?_) ?_ ?_ ?_ <;> [skip; skip; type_tac; type_tac; exact rfl] + | refine HasType.const' (ci := ?_) ?_ ?_ ?_ ?_ <;> [skip; assumption; decide; decide; exact rfl] + | refine HasType.lam (u := ?_) ?_ ?_ <;> [skip; type_tac; type_tac] +) diff --git a/Ix/Theory/Named/Typing/NestedInductiveLemmas.lean b/Ix/Theory/Named/Typing/NestedInductiveLemmas.lean new file mode 100644 index 000000000..1a8ad71d8 --- /dev/null +++ b/Ix/Theory/Named/Typing/NestedInductiveLemmas.lean @@ -0,0 +1,190 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.NestedInductive +import Ix.Theory.Named.Typing.InductiveLemmas + +/-! +# Nested transaction facts and preservation (Spec-09C) + +The `addInductNested` analog of the block-wide transaction lemma suite: +exact phase recovery, atomicity, monotonicity, freshness, lookup and rule +membership through `ctorFold_spec`/`rulesFold_spec`, and `Ordered` +preservation from the `NestedBlockChecked.WF` package. +-/ + +namespace Ix.Theory.Named + +open VInductDecl + +namespace VEnv + +/-- Recover every phase boundary from a successful nested transaction. -/ +theorem addInductNested_trace {source : VInductDecl} + {nested : source.NestedBlockChecked} + (hadd : addInductNested env nested = some env') : + Nonempty (AddInductNestedTrace env env' nested) := by + unfold addInductNested at hadd + obtain ⟨typeEnv, addTypes, hadd⟩ := Option.bind_eq_some_iff.1 hadd + obtain ⟨ctorEnv, addCtors, hadd⟩ := Option.bind_eq_some_iff.1 hadd + obtain ⟨recEnv, addRecs, hadd⟩ := Option.bind_eq_some_iff.1 hadd + cases hadd + exact ⟨⟨typeEnv, ctorEnv, recEnv, addTypes, addCtors, addRecs, rfl⟩⟩ + +/-- The nested transaction is atomic at its public `Option` boundary. -/ +theorem addInductNested_atomic {source : VInductDecl} + (env : VEnv) (nested : source.NestedBlockChecked) : + addInductNested env nested = none ∨ + ∃ env', addInductNested env nested = some env' ∧ + Nonempty (AddInductNestedTrace env env' nested) := by + cases hadd : addInductNested env nested with + | none => exact .inl rfl + | some env' => exact .inr ⟨env', rfl, addInductNested_trace hadd⟩ + +namespace AddInductNestedTrace + +variable {source : VInductDecl} {nested : source.NestedBlockChecked} + +/-- Every phase of a successful nested transaction only grows the Theory +environment. -/ +theorem le (H : AddInductNestedTrace env env' nested) : env ≤ env' := by + have htypes := (ctorFold_spec source.blockTypeConstants H.addTypes).1 + have hctors := (ctorFold_spec source.blockConstructorConstants H.addCtors).1 + have hrecs := (ctorFold_spec nested.recursors H.addRecs).1 + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec nested.generatedRules H.recEnv).1 + exact htypes.trans (hctors.trans (hrecs.trans hrules)) + +/-- Every source family name was fresh before the transaction. -/ +theorem family_fresh (H : AddInductNestedTrace env env' nested) + {type : VInductiveType} (htype : type ∈ source.types) : + env.constants type.name = none := by + have hmem : type.toVConstVal ∈ source.blockTypeConstants := + List.mem_map.2 ⟨type, htype, rfl⟩ + simpa [VInductDecl.blockTypeConstants] using + (ctorFold_spec source.blockTypeConstants H.addTypes).2.2 + type.toVConstVal hmem + +/-- The final environment stores every exact source family constant. -/ +theorem family_lookup (H : AddInductNestedTrace env env' nested) + {type : VInductiveType} (htype : type ∈ source.types) : + env'.constants type.name = some type.toVConstant := by + have hmem : type.toVConstVal ∈ source.blockTypeConstants := + List.mem_map.2 ⟨type, htype, rfl⟩ + have hlookup := + (ctorFold_spec source.blockTypeConstants H.addTypes).2.1 + type.toVConstVal hmem + have hctors := (ctorFold_spec source.blockConstructorConstants H.addCtors).1 + have hrecs := (ctorFold_spec nested.recursors H.addRecs).1 + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec nested.generatedRules H.recEnv).1 + exact (hctors.trans (hrecs.trans hrules)).constants hlookup + +/-- Every flattened source constructor name was fresh before the nested +transaction. -/ +theorem ctor_fresh (H : AddInductNestedTrace env env' nested) + {c : VConstVal} (hc : c ∈ source.blockConstructorConstants) : + env.constants c.name = none := by + have htypes := (ctorFold_spec source.blockTypeConstants H.addTypes).1 + have hfresh := + (ctorFold_spec source.blockConstructorConstants H.addCtors).2.2 c hc + exact htypes.constants_none hfresh + +/-- The final environment stores every exact source constructor +constant. -/ +theorem ctor_lookup (H : AddInductNestedTrace env env' nested) + {type : VInductiveType} (htype : type ∈ source.types) + {c : VConstVal} (hc : c ∈ type.ctors) : + env'.constants c.name = some c.toVConstant := by + have hmem : c ∈ source.blockConstructorConstants := + List.mem_flatMap.2 ⟨type, htype, hc⟩ + have hlookup := + (ctorFold_spec source.blockConstructorConstants H.addCtors).2.1 c hmem + have hrecs := (ctorFold_spec nested.recursors H.addRecs).1 + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec nested.generatedRules H.recEnv).1 + exact (hrecs.trans hrules).constants hlookup + +/-- The final environment stores every restored recursor constant. -/ +theorem rec_lookup (H : AddInductNestedTrace env env' nested) + {recursor : VConstVal} (hrec : recursor ∈ nested.recursors) : + env'.constants recursor.name = some recursor.toVConstant := by + have hlookup := (ctorFold_spec nested.recursors H.addRecs).2.1 recursor hrec + have hrules : H.recEnv ≤ env' := by + simpa only [H.addRules] using + (rulesFold_spec nested.generatedRules H.recEnv).1 + exact hrules.constants hlookup + +/-- Every restored recursor name was fresh before the nested transaction. -/ +theorem rec_fresh (H : AddInductNestedTrace env env' nested) + {recursor : VConstVal} (hrec : recursor ∈ nested.recursors) : + env.constants recursor.name = none := by + have htypes := (ctorFold_spec source.blockTypeConstants H.addTypes).1 + have hctors := + (ctorFold_spec source.blockConstructorConstants H.addCtors).1 + have hfresh := (ctorFold_spec nested.recursors H.addRecs).2.2 recursor hrec + exact (htypes.trans hctors).constants_none hfresh + +/-- The final environment registers every restored rule. -/ +theorem rule_mem (H : AddInductNestedTrace env env' nested) + {df : VDefEq} (hdf : df ∈ nested.generatedRules) : + env'.defeqs df := by + simpa only [H.addRules] using + (rulesFold_spec nested.generatedRules H.recEnv).2 df hdf + +end AddInductNestedTrace + +nonrec theorem addInductNested_le {source : VInductDecl} + {nested : source.NestedBlockChecked} + (hadd : addInductNested env nested = some env') : env ≤ env' := by + obtain ⟨H⟩ := addInductNested_trace hadd + exact H.le + +end VEnv + +/-- A chained constant package folds into `Ordered` preservation. -/ +theorem NestedConstsWF.fold_ordered : + ∀ {cs : List VConstVal} {env env' : VEnv}, + VEnv.Ordered env → NestedConstsWF env cs → + cs.foldlM (fun env c => env.addConst c.name c.toVConstant) env = + some env' → + VEnv.Ordered env' + | [], _, _, h, _, hf => by cases hf; exact h + | c :: cs, env, env', h, hwf, hf => by + rw [List.foldlM_cons] at hf + obtain ⟨env₁, hadd, htail⟩ := Option.bind_eq_some_iff.1 hf + exact NestedConstsWF.fold_ordered (.const h hwf.1 hadd) + (hwf.2 env₁ hadd) htail + +/-- A chained rule package folds into `Ordered` preservation. -/ +theorem NestedRulesWF.fold_ordered : + ∀ {dfs : List VDefEq} {env : VEnv}, + VEnv.Ordered env → NestedRulesWF env dfs → + VEnv.Ordered (dfs.foldl VEnv.addDefEq env) + | [], _, h, _ => h + | df :: dfs, env, h, hwf => by + rw [List.foldl_cons] + exact NestedRulesWF.fold_ordered (.defeq h hwf.1) hwf.2 + +/-- `Ordered` preservation for the nested transaction. -/ +theorem VEnv.addInductNested_WF {source : VInductDecl} + {nested : source.NestedBlockChecked} + (ih : VEnv.Ordered env) (h1 : nested.WF env) + (h2 : addInductNested env nested = some env') : VEnv.Ordered env' := by + unfold addInductNested at h2 + obtain ⟨typeEnv, addTypes, h2⟩ := Option.bind_eq_some_iff.1 h2 + obtain ⟨ctorEnv, addCtors, h2⟩ := Option.bind_eq_some_iff.1 h2 + obtain ⟨recEnv, addRecs, h2⟩ := Option.bind_eq_some_iff.1 h2 + cases h2 + have hT := NestedConstsWF.fold_ordered ih h1.types addTypes + have hC := NestedConstsWF.fold_ordered hT (h1.ctors addTypes) addCtors + have hR := NestedConstsWF.fold_ordered hC (h1.recs addTypes addCtors) addRecs + exact NestedRulesWF.fold_ordered hR (h1.rules addTypes addCtors addRecs) + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Typing/Pattern.lean b/Ix/Theory/Named/Typing/Pattern.lean new file mode 100644 index 000000000..7927638e6 --- /dev/null +++ b/Ix/Theory/Named/Typing/Pattern.lean @@ -0,0 +1,466 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.VExpr + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +open VExpr + +inductive Pattern where + | const (c : Name) + | app (f a : Pattern) + | var (f : Pattern) + +@[reducible] def Pattern.varN (p : Pattern) : Nat → Pattern + | 0 => p + | n+1 => (p.varN n).var + +inductive Subpattern (p : Pattern) : Pattern → Prop where + | refl : Subpattern p p + | appL : Subpattern p f → Subpattern p (.app f a) + | appR : Subpattern p a → Subpattern p (.app f a) + | varL : Subpattern p f → Subpattern p (.var f) + +theorem Subpattern.varN (h : Subpattern p f) : ∀ {n}, Subpattern p (.varN f n) + | 0 => h + | _+1 => .varL (.varN h) + +theorem Subpattern.trans {p₁ p₂ p₃} (H₁ : Subpattern p₁ p₂) (H₂ : Subpattern p₂ p₃) : Subpattern p₁ p₃ := by + induction H₂ with + | refl => exact H₁ + | appL _ ih => exact .appL ih + | appR _ ih => exact .appR ih + | varL _ ih => exact .varL ih + +theorem Subpattern.sizeOf_le {p₁ p₂} (H₁ : Subpattern p₁ p₂) : sizeOf p₁ ≤ sizeOf p₂ := by + induction H₁ <;> simp <;> omega + +theorem Subpattern.antisymm {p₁ p₂} (H₁ : Subpattern p₁ p₂) (H₂ : Subpattern p₂ p₁) : p₂ = p₁ := by + cases id H₂ with + | refl => rfl + | _ h₂ => + have H₁ := H₁.sizeOf_le + have h₂ := h₂.sizeOf_le + simp at H₁; omega + +inductive Arity (p : Pattern) : Nat → Pattern → Prop where + | refl : Arity p 0 p + | app : Arity p n f → Arity p (n+1) (.app f a) + | var : Arity p n f → Arity p (n+1) (.var f) + +theorem Arity.subpattern : Arity p n p' → Subpattern p p' + | .refl => .refl + | .app h => .appL h.subpattern + | .var h => .varL h.subpattern + +def Pattern.inter : Pattern → Pattern → Option Pattern + | .const c, .const c' => if c = c' then some (.const c) else none + | .app f a, .app f' a' => return .app (← f.inter f') (← a.inter a') + | .var f, .var f' => return .var (← f.inter f') + | .app f a, .var f' => return .app (← f.inter f') a + | .var f, .app f' a' => return .app (← f.inter f') a' + | _, _ => none + +theorem Pattern.inter_self (p : Pattern) : p.inter p = some p := by induction p <;> simp [*, inter] + +theorem Pattern.inter_comm (p q : Pattern) : p.inter q = q.inter p := by + induction p generalizing q <;> cases q <;> simp [*, eq_comm, inter] <;> split <;> simp [*] + +inductive Pattern.LE : Pattern → Pattern → Prop where + | refl : LE p p + | var : LE f f' → LE (.var f) (.var f') + | app : LE f f' → LE a a' → LE (.app f a) (.app f' a') + | app_var : LE f f' → LE (.app f a) (.var f') + +@[reducible] def Pattern.Path : Pattern → Type + | .const _ => Empty + | .app f a => f.Path ⊕ a.Path + | .var f => Option f.Path + +inductive Pattern.Matches : (p : Pattern) → VExpr → List VLevel → (p.Path → VExpr) → Prop + | const : Matches (.const c) (.const c ls) ls nofun + | var : Matches f f' f1 g1 → Matches (.var f) (.app f' a') f1 (·.elim a' g1) + | app : Matches f f' f1 g1 → Matches a a' f2 g2 → + Matches (.app f a) (.app f' a') f1 (Sum.elim g1 g2) + +theorem Pattern.Matches.uniq {p : Pattern} {e : VExpr} {m1 m2 m1' m2'} + (H1 : Pattern.Matches p e m1 m2) (H2 : Pattern.Matches p e m1' m2') : m1 = m1' ∧ m2 = m2' := by + induction H1 generalizing m1' with cases H2 + | const => simp + | var _ ih => rename_i h; simp [ih h] + | app _ _ ih1 ih2 => rename_i h2 h1; simp [ih1 h1, ih2 h2] + +def Pattern.OnArgs (P : VExpr → Prop) : Pattern → Prop + | .const .. => True + | .var f => f.OnArgs P + | .app f a => f.OnArgs P ∧ a.OnArgs P ∧ ∀ e m1 m2, a.Matches e m1 m2 → P e + +inductive Pattern.RHS (p : Pattern) where + | fixed (c : VExpr) (_ : c.Closed) + | app (f a : RHS p) + | var (e : p.Path) + +inductive Pattern.Check (p : Pattern) where + | true + | defeq (x y : RHS p) (rest : Check p) + +def Pattern.RHS.apply {p : Pattern} (m1 : List VLevel) (m2 : p.Path → VExpr) : p.RHS → VExpr + | .fixed c _ => c.instL m1 + | .var path => m2 path + | .app f a => .app (f.apply m1 m2) (a.apply m1 m2) + +theorem Pattern.RHS.lift'_apply {p : Pattern} {m1 m2} (r : p.RHS) : + (r.apply m1 m2).lift' ρ = (r.apply m1 fun x => (m2 x).lift' ρ) := by + induction r <;> simp [*, apply, lift', ← instL_lift'] + rw [ClosedN.lift'_eq ‹_› (by trivial)] + +theorem Pattern.RHS.liftN_apply {p : Pattern} {m1 m2} (r : p.RHS) : + (r.apply m1 m2).liftN n k = (r.apply m1 fun x => (m2 x).liftN n k) := by + simp [← lift'_consN_skipN, lift'_apply] + +theorem Pattern.matches_lift' {p : Pattern} {e : VExpr} {m1 m2'} : + p.Matches (e.lift' ρ) m1 m2' ↔ + ∃ m2, p.Matches e m1 m2 ∧ ∀ x, m2' x = (m2 x).lift' ρ := by + constructor + · intro h; generalize eq : e.lift' ρ = e' at h + induction h generalizing e with + | const => cases e <;> cases eq; exact ⟨_, .const, nofun⟩ + | var _ ih => + cases e <;> cases eq + have ⟨_, l1, l2⟩ := ih rfl + refine ⟨_, .var l1, ?_⟩ + rintro (_|_) <;> solve_by_elim + | app _ _ ih1 ih2 => + cases e <;> cases eq + have ⟨_, l1, l2⟩ := ih1 rfl + have ⟨_, r1, r2⟩ := ih2 rfl + refine ⟨_, .app l1 r1, ?_⟩ + rintro (_|_) <;> solve_by_elim + · intro ⟨m2, h1, h2⟩ + induction h1 with + | const => exact (show m2' = _ by ext ⟨⟩) ▸ .const + | var _ ih => + have := (ih (h2 <| some ·)).var (a' := ?_) + rwa [(_ : m2' = _)]; ext (_|_) <;> simp [h2 none] + | app _ _ ih1 ih2 => + have := (ih1 (h2 <| .inl ·)).app (ih2 (h2 <| .inr ·)) + rwa [(_ : m2' = _)]; ext (_|_) <;> rfl + +theorem Pattern.matches_liftN {p : Pattern} {e : VExpr} {m1 m2'} : + p.Matches (e.liftN n k) m1 m2' ↔ ∃ m2, p.Matches e m1 m2 ∧ ∀ x, m2' x = (m2 x).liftN n k := by + simp only [← lift'_consN_skipN]; exact p.matches_lift' + +theorem Pattern.RHS.instN_apply {p : Pattern} {m1 m2} (r : p.RHS) : + (r.apply m1 m2).inst e₀ k = (r.apply m1 fun x => (m2 x).inst e₀ k) := by + induction r <;> simp [*, apply, inst] + rw [(ClosedN.instL ‹_›).instN_eq (Nat.zero_le _)] + +theorem Pattern.matches_instN {p : Pattern} {e : VExpr} {m1 m2} (H : p.Matches e m1 m2) : + p.Matches (e.inst e₀ k) m1 fun x => (m2 x).inst e₀ k := by + induction H with + | const => erw [show (fun _ : Empty => _) = _ by ext ⟨⟩]; exact .const + | var _ ih => + rw [(_ : (fun _ => _) = _)]; exact ih.var + ext (_|_) <;> rfl + | app _ _ ih1 ih2 => + rw [(_ : (fun _ => _) = _)]; exact ih1.app ih2 + ext (_|_) <;> rfl + +/-- Universe instantiation preserves a successful match. The universe +capture is instantiated pointwise and every expression capture is +instantiated by the same level substitution. -/ +theorem Pattern.Matches.instL {p : Pattern} {e : VExpr} {m1 m2} + (H : p.Matches e m1 m2) (ls : List VLevel) : + p.Matches (e.instL ls) (m1.map (VLevel.inst ls)) + fun x => (m2 x).instL ls := by + induction H with + | const => erw [show (fun _ : Empty => _) = _ by ext ⟨⟩]; exact .const + | var _ ih => + rw [(_ : (fun _ => _) = _)]; exact ih.var + ext (_|_) <;> rfl + | app _ _ ih1 ih2 => + rw [(_ : (fun _ => _) = _)]; exact ih1.app ih2 + ext (_|_) <;> rfl + +theorem Pattern.matches_inter {p q : Pattern} {e : VExpr} : + (∃ m1 m2, p.Matches e m1 m2) ∧ (∃ m1 m2, q.Matches e m1 m2) ↔ + (∃ r m1 m2, p.inter q = some r ∧ r.Matches e m1 m2) := by + constructor + · rintro ⟨⟨m1, m2, hp⟩, ⟨m3, m4, hq⟩⟩ + induction hp generalizing q m3 <;> cases hq <;> simp [inter] + · case const.const => exact ⟨_, _, .const⟩ + · case var.var ih _ _ ih' => + have ⟨rf, mf1, mf2, hf1, hf2⟩ := ih _ _ ih' + exact ⟨_, ⟨_, hf1, rfl⟩, _, _, .var hf2⟩ + · case var.app ihf _ _ _ _ _ ha2 ihf' => + have ⟨rf, mf1, mf2, hf1, hf2⟩ := ihf _ _ ihf' + exact ⟨_, ⟨_, hf1, rfl⟩, _, _, .app hf2 ha2⟩ + · case app.var ha2 ihf _ _ _ ihf' => + have ⟨rf, mf1, mf2, hf1, hf2⟩ := ihf _ _ ihf' + exact ⟨_, ⟨_, hf1, rfl⟩, _, _, .app hf2 ha2⟩ + · case app.app ihf iha _ _ _ _ _ iha' ihf' => + have ⟨rf, mf1, mf2, hf1, hf2⟩ := ihf _ _ ihf' + have ⟨ra, ma1, ma2, ha1, ha2⟩ := iha _ _ iha' + exact ⟨_, ⟨_, hf1, _, ha1, rfl⟩, _, _, .app hf2 ha2⟩ + · rintro ⟨r, m1, m2, h1, h2⟩ + induction p generalizing q e r m1 <;> cases q <;> simp [inter] at h1 <;> [ + obtain ⟨rfl, rfl⟩ := h1; obtain ⟨_, wf, _, wa, rfl⟩ := h1; + obtain ⟨_, wf, rfl⟩ := h1; obtain ⟨_, wf, rfl⟩ := h1; obtain ⟨_, wf, rfl⟩ := h1 + ] <;> cases h2 + · exact ⟨⟨_, _, .const⟩, ⟨_, _, .const⟩⟩ + · next ihf iha _ _ _ _ _ _ _ _ _ ha hf => + have ⟨⟨mf1, mf2, hf⟩, ⟨mf1', mf2', hf'⟩⟩ := ihf _ _ _ wf hf + have ⟨⟨ma1, ma2, ha⟩, ⟨ma1', ma2', ha'⟩⟩ := iha _ _ _ wa ha + exact ⟨⟨_, _, .app hf ha⟩, ⟨_, _, .app hf' ha'⟩⟩ + · next ihf _ _ _ _ _ _ _ _ ha hf => + have ⟨⟨mf1, mf2, hf⟩, ⟨mf1', mf2', hf'⟩⟩ := ihf _ _ _ wf hf + exact ⟨⟨_, _, .app hf ha⟩, ⟨_, _, .var hf'⟩⟩ + · next ihf _ _ _ _ _ _ _ _ ha' hf => + have ⟨⟨mf1, mf2, hf⟩, ⟨mf1', mf2', hf'⟩⟩ := ihf _ _ _ wf hf + exact ⟨⟨_, _, .var hf⟩, ⟨_, _, .app hf' ha'⟩⟩ + · next ihf _ _ _ _ _ hf => + have ⟨⟨mf1, mf2, hf⟩, ⟨mf1', mf2', hf'⟩⟩ := ihf _ _ _ wf hf + exact ⟨⟨_, _, .var hf⟩, ⟨_, _, .var hf'⟩⟩ + +theorem Pattern.matches_determ + (h1 : Matches p e m1 m2) (h2 : Matches p e m1' m2') : m1 = m1' ∧ m2 = m2' := by + induction h1 generalizing m1' with + | const => let .const := h2; simp + | app l1 l2 ih1 ih2 => let .app r1 r2 := h2; simp [ih1 r1, ih2 r2] + | var l1 ih1 => let .var r1 := h2; simp [ih1 r1] + +def Pattern.Check.OK (defeq : VExpr → VExpr → Prop) {p : Pattern} + (m1 : List VLevel) (m2 : p.Path → VExpr) : p.Check → Prop + | .true => True + | .defeq a b rest => defeq (RHS.apply m1 m2 a) (RHS.apply m1 m2 b) ∧ rest.OK defeq m1 m2 + +theorem Pattern.Check.OK.map + {df df' : VExpr → VExpr → Prop} {p : Pattern} {ck : p.Check} {m1 m2 m1' m2'} + (h : ∀ a b : p.RHS, + df (a.apply m1 m2) (b.apply m1 m2) → df' (a.apply m1' m2') (b.apply m1' m2')) + (H : ck.OK df m1 m2) : ck.OK df' m1' m2' := by + induction ck <;> simp [OK, *] at H ⊢; cases H; constructor <;> solve_by_elim + +inductive SimplePattern where + | iota (recursor : Name) (major : Nat) (constr : Name) (args : Nat) + | defn (head : Name) + +@[reducible] def SimplePattern.toPattern : SimplePattern → Pattern + | .defn c => .const c + | .iota r m c n => .app (.varN (.const r) m) (.varN (.const c) n) + +/-! ## Shape helpers for generated recursor patterns + +`HeadConstN`, `HeadConst`, `of_varN_matches`, `RecursorIotaPattern`, and +`matches_shape` form the implementation-independent shape layer consumed by +the generated iota patterns of a certified inductive block +(`Theory/Typing/InductivePattern.lean`). They characterize matching against +`Pattern.varN` towers and `SimplePattern.iota` patterns without referring to +any generator data. -/ + +/-- `HeadConstN c ls n e`: `e` is the constant `c` at levels `ls` applied to +exactly `n` arguments. This is the expression shape captured by matching the +pattern `Pattern.varN (.const c) n`. -/ +inductive HeadConstN (c : Name) (ls : List VLevel) : Nat → VExpr → Prop where + | const : HeadConstN c ls 0 (.const c ls) + | app : HeadConstN c ls n f → HeadConstN c ls (n+1) (.app f a) + +/-- `e` is an application spine headed by the constant `c`. -/ +def HeadConst (c : Name) (e : VExpr) : Prop := ∃ ls n, HeadConstN c ls n e + +/-- Matching a `varN` tower of a constant captures exactly a `HeadConstN` +spine whose head levels are the pattern's level assignment. -/ +theorem Pattern.of_varN_matches {c : Name} : + ∀ {n : Nat} {e : VExpr} {m2}, (Pattern.varN (.const c) n).Matches e m1 m2 → + HeadConstN c m1 n e := by + intro n + induction n with + | zero => intro e m2 H; cases H; exact .const + | succ n ih => intro e m2 H; cases H with | var h => exact .app (ih h) + +/-- Every `HeadConstN` spine matches its `varN` tower. -/ +theorem HeadConstN.matches : HeadConstN c ls n e → + ∃ m2, (Pattern.varN (.const c) n).Matches e ls m2 + | .const => ⟨_, .const⟩ + | .app h => let ⟨_, h'⟩ := h.matches; ⟨_, .var h'⟩ + +/-- The capture paths of an `n`-ary `varN` tower in argument order (outermost +application first): matching assigns the `t`-th entry the `t`-th spine +argument. -/ +def Pattern.varNPaths (p : Pattern) : ∀ n, List (Pattern.Path (p.varN n)) + | 0 => [] + | n+1 => (varNPaths p n).map some ++ [none] + +@[simp] theorem Pattern.varNPaths_length (p : Pattern) : + ∀ n, (varNPaths p n).length = n + | 0 => rfl + | n+1 => by + show ((varNPaths p n).map some ++ [none]).length = n + 1 + rw [List.length_append, List.length_map, varNPaths_length p n]; rfl + +/-- The exact pattern of one generated iota rule: the recursor constant +applied to `major` arguments (parameters, motives, minors, and the +constructor's result indices), with a `ctor`-headed major premise carrying +`args` arguments. Definitionally `(SimplePattern.iota recursor major ctor +args).toPattern`. -/ +def RecursorIotaPattern (recursor : Name) (major : Nat) + (ctor : Name) (args : Nat) : Pattern := + .app (.varN (.const recursor) major) (.varN (.const ctor) args) + +theorem SimplePattern.toPattern_iota : + (SimplePattern.iota r m c n).toPattern = RecursorIotaPattern r m c n := rfl + +/-- Match inversion for an iota pattern: the expression is exactly a +recursor-headed spine at the pattern's level assignment whose last argument +is a constructor-headed spine (at unconstrained levels). -/ +theorem RecursorIotaPattern.matches_shape + (H : (RecursorIotaPattern r mj c n).Matches e m1 m2) : + ∃ f a ls, e = .app f a ∧ HeadConstN r m1 mj f ∧ HeadConstN c ls n a := by + cases H with + | app h1 h2 => + exact ⟨_, _, _, rfl, Pattern.of_varN_matches h1, Pattern.of_varN_matches h2⟩ + +/-- Match construction for an iota pattern from the two head spines. -/ +theorem RecursorIotaPattern.matches_of + (h1 : HeadConstN r ls mj f) (h2 : HeadConstN c ls' n a) : + ∃ m2, (RecursorIotaPattern r mj c n).Matches (.app f a) ls m2 := + let ⟨_, hf⟩ := h1.matches + let ⟨_, ha⟩ := h2.matches + ⟨_, .app hf ha⟩ + +/-- Subpatterns of a constant `varN` tower are exactly its shorter towers. -/ +theorem Subpattern.varN_const_le : + ∀ {n}, Subpattern p (Pattern.varN (.const c) n) → + ∃ j, j ≤ n ∧ p = Pattern.varN (.const c) j := by + intro n + induction n with + | zero => intro H; cases H; exact ⟨0, Nat.le_refl _, rfl⟩ + | succ n ih => + intro H + cases H with + | refl => exact ⟨n+1, Nat.le_refl _, rfl⟩ + | varL h => + let ⟨j, hj, hp⟩ := ih h + exact ⟨j, Nat.le_succ_of_le hj, hp⟩ + +/-- Subpattern classification for an iota pattern: the whole pattern, a +prefix of the recursor head, or a prefix of the constructor spine. -/ +theorem RecursorIotaPattern.subpattern_inv + (H : Subpattern p (RecursorIotaPattern r mj c n)) : + p = RecursorIotaPattern r mj c n ∨ + (∃ j, j ≤ mj ∧ p = .varN (.const r) j) ∨ + (∃ j, j ≤ n ∧ p = .varN (.const c) j) := by + cases H with + | refl => exact .inl rfl + | appL h => exact .inr (.inl h.varN_const_le) + | appR h => exact .inr (.inr h.varN_const_le) + +/-- Two constant `varN` towers intersect only when they agree exactly. -/ +theorem Pattern.varN_const_inter_some : + ∀ {n n' p}, (Pattern.varN (.const c) n).inter (Pattern.varN (.const c') n') = some p → + c = c' ∧ n = n' ∧ p = Pattern.varN (.const c) n := by + intro n + induction n with + | zero => + intro n' p h + cases n' with + | zero => + simp [Pattern.inter] at h + exact ⟨h.1, rfl, h.2.symm⟩ + | succ n' => simp [Pattern.inter] at h + | succ n ih => + intro n' p h + cases n' with + | zero => simp [Pattern.inter] at h + | succ n' => + simp only [Pattern.inter, bind, Option.bind_eq_some_iff, Option.pure_def, Option.some.injEq] at h + obtain ⟨q, hq, rfl⟩ := h + obtain ⟨rfl, rfl, rfl⟩ := ih hq + exact ⟨rfl, rfl, rfl⟩ + +theorem Pattern.varN_const_inter_of_ne_name (h : c ≠ c') (n n' : Nat) : + (Pattern.varN (.const c) n).inter (Pattern.varN (.const c') n') = none := by + cases e : (Pattern.varN (.const c) n).inter (Pattern.varN (.const c') n') with + | none => rfl + | some p => exact absurd (varN_const_inter_some e).1 h + +theorem Pattern.varN_const_inter_of_ne_arity (h : n ≠ n') (c c' : Name) : + (Pattern.varN (.const c) n).inter (Pattern.varN (.const c') n') = none := by + cases e : (Pattern.varN (.const c) n).inter (Pattern.varN (.const c') n') with + | none => rfl + | some p => exact absurd (varN_const_inter_some e).2.1 h + +/-- An application pattern intersects a constant `varN` tower only through a +positive tower whose inner tower intersects the function part. -/ +theorem Pattern.app_inter_varN_const_some {f a : Pattern} + (h : (Pattern.app f a).inter (Pattern.varN (.const c) n) = some p) : + ∃ n' q, n = n' + 1 ∧ f.inter (Pattern.varN (.const c) n') = some q ∧ + p = .app q a := by + cases n with + | zero => simp [Pattern.inter] at h + | succ n' => + simp only [Pattern.inter, bind, Option.bind_eq_some_iff, Option.pure_def, Option.some.injEq] at h + obtain ⟨q, hq, rfl⟩ := h + exact ⟨n', q, rfl, hq, rfl⟩ + +/-- Two iota patterns intersect only when they agree exactly. -/ +theorem RecursorIotaPattern.inter_some + (h : (RecursorIotaPattern r mj c n).inter (RecursorIotaPattern r' mj' c' n') = some p) : + r = r' ∧ mj = mj' ∧ c = c' ∧ n = n' ∧ p = RecursorIotaPattern r mj c n := by + simp only [RecursorIotaPattern, Pattern.inter, bind, Option.bind_eq_some_iff, + Option.pure_def, Option.some.injEq] at h + obtain ⟨q1, h1, q2, h2, rfl⟩ := h + obtain ⟨rfl, rfl, rfl⟩ := Pattern.varN_const_inter_some h1 + obtain ⟨rfl, rfl, rfl⟩ := Pattern.varN_const_inter_some h2 + exact ⟨rfl, rfl, rfl, rfl, rfl⟩ + +/-- An iota pattern intersects a constant `varN` tower only at a tower whose +inner arity is the pattern's major arity with the recursor's name. -/ +theorem RecursorIotaPattern.inter_varN_const_some + (h : (RecursorIotaPattern r mj c n).inter (Pattern.varN (.const b) j) = some p) : + b = r ∧ j = mj + 1 := by + obtain ⟨j', q, rfl, hq, rfl⟩ := Pattern.app_inter_varN_const_some h + obtain ⟨rfl, rfl, rfl⟩ := Pattern.varN_const_inter_some hq + exact ⟨rfl, rfl⟩ + +/-- Constant `varN` towers are injective in the head name and the arity. -/ +theorem Pattern.varN_const_inj {c c' : Name} : + ∀ {n n' : Nat}, Pattern.varN (.const c) n = Pattern.varN (.const c') n' → + c = c' ∧ n = n' + | 0, 0, h => by cases h; exact ⟨rfl, rfl⟩ + | 0, n'+1, h => absurd h (by simp [Pattern.varN]) + | n+1, 0, h => absurd h (by simp [Pattern.varN]) + | n+1, n'+1, h => by + injection h with h1 + obtain ⟨rfl, rfl⟩ := Pattern.varN_const_inj h1 + exact ⟨rfl, rfl⟩ + +/-- Iota patterns are injective in all four components. -/ +theorem RecursorIotaPattern.inj + (h : RecursorIotaPattern r mj c n = RecursorIotaPattern r' mj' c' n') : + r = r' ∧ mj = mj' ∧ c = c' ∧ n = n' := by + injection h with h1 h2 + obtain ⟨rfl, rfl⟩ := Pattern.varN_const_inj h1 + obtain ⟨rfl, rfl⟩ := Pattern.varN_const_inj h2 + exact ⟨rfl, rfl, rfl, rfl⟩ + +/-- The only application subpattern of an iota pattern is the pattern +itself. -/ +theorem RecursorIotaPattern.app_subpattern + (H : Subpattern (.app p₁ p₂) (RecursorIotaPattern r mj c n)) : + p₁ = .varN (.const r) mj ∧ p₂ = .varN (.const c) n := by + rcases RecursorIotaPattern.subpattern_inv H with heq | ⟨j, hj, heq⟩ | ⟨j, hj, heq⟩ + · injection heq with h1 h2; exact ⟨h1, h2⟩ + · cases j <;> exact absurd heq (by simp [Pattern.varN]) + · cases j <;> exact absurd heq (by simp [Pattern.varN]) + +/-- Apply an RHS template head to a list of template arguments. -/ +def Pattern.RHS.appN {p : Pattern} (f : p.RHS) : List p.RHS → p.RHS + | [] => f + | a :: as => Pattern.RHS.appN (.app f a) as diff --git a/Ix/Theory/Named/Typing/QuotLemmas.lean b/Ix/Theory/Named/Typing/QuotLemmas.lean new file mode 100644 index 000000000..1f69ed1ba --- /dev/null +++ b/Ix/Theory/Named/Typing/QuotLemmas.lean @@ -0,0 +1,39 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.Env +import Ix.Theory.Named.Typing.Meta + +namespace Ix.Theory.Named +namespace VEnv + +theorem addQuot_WF (henv : Ordered env) (hq : QuotReady env) : + addQuot env = some env' → Ordered env' := by + refine with_addConst (cis := [.const _ eqConst]) (hcis := ⟨hq, ⟨⟩⟩) henv + (fun _ => ⟨_, by type_tac⟩) fun henv => ?_ + refine with_addConst henv (fun ⟨quot, _⟩ => ⟨_, by type_tac⟩) fun henv => ?_ + refine with_addConst henv (fun ⟨_, quot, eq, _⟩ => ⟨_, by type_tac⟩) fun henv => ?_ + refine with_addConst henv (fun ⟨_, _, quot, _⟩ => ⟨_, by type_tac⟩) fun henv => ?_ + rintro ⟨_, _, _, _, eq, _⟩ ⟨⟩; exact .defeq henv ⟨by type_tac, by type_tac⟩ + +section +variable (henv : addQuot env = some env') include henv + +theorem addQuot_objs : env'.HasObjects [.defeq quotDefEq, .const `Quot.ind quotIndConst, + .const `Quot.lift quotLiftConst, .const `Quot.mk quotMkConst, .const `Quot quotConst] := by + let ⟨env, h, henv⟩ := HasObjects.bind_const (ls := []) trivial henv + let ⟨env, h, henv⟩ := HasObjects.bind_const h henv + let ⟨env, h, henv⟩ := HasObjects.bind_const h henv + obtain ⟨env, h, ⟨⟩⟩ := HasObjects.bind_const h henv + exact HasObjects.defeq (df := quotDefEq) h + +theorem addQuot_quot : env'.constants ``Quot = quotConst := (addQuot_objs henv).2.2.2.2.1 +theorem addQuot_quotMk : env'.constants ``Quot.mk = quotMkConst := (addQuot_objs henv).2.2.2.1 +theorem addQuot_quotLift : env'.constants ``Quot.lift = quotLiftConst := (addQuot_objs henv).2.2.1 +theorem addQuot_quotInd : env'.constants ``Quot.ind = quotIndConst := (addQuot_objs henv).2.1 +theorem addQuot_defeq : env'.defeqs quotDefEq := (addQuot_objs henv).1 + +end diff --git a/Ix/Theory/Named/Typing/Strong.lean b/Ix/Theory/Named/Typing/Strong.lean new file mode 100644 index 000000000..f79f27dc7 --- /dev/null +++ b/Ix/Theory/Named/Typing/Strong.lean @@ -0,0 +1,1031 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.Lemmas + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Ix.Theory.Named + +namespace VEnv + +open VExpr + +section +set_option hygiene false +variable (env : VEnv) (uvars : Nat) + +section +local notation:65 Γ " ⊢ " e " : " A:30 => IsDefEqStrong Γ e e A +local notation:65 Γ " ⊢ " e1 " ≡ " e2 " : " A:30 => IsDefEqStrong Γ e1 e2 A + +inductive IsDefEqStrong : List VExpr → VExpr → VExpr → VExpr → Prop where + | bvar : Lookup Γ i A → u.WF uvars → Γ ⊢ A : .sort u → Γ ⊢ .bvar i : A + | symm : Γ ⊢ e ≡ e' : A → Γ ⊢ e' ≡ e : A + | trans : Γ ⊢ e₁ ≡ e₂ : A → Γ ⊢ e₂ ≡ e₃ : A → Γ ⊢ e₁ ≡ e₃ : A + | sortDF : + l.WF uvars → l'.WF uvars → l ≈ l' → + Γ ⊢ .sort l ≡ .sort l' : .sort (.succ l) + | constDF : + env.constants c = some ci → + (∀ l ∈ ls, l.WF uvars) → + (∀ l ∈ ls', l.WF uvars) → + ls.length = ci.uvars → + List.Forall₂ (· ≈ ·) ls ls' → + u.WF uvars → + [] ⊢ ci.type.instL ls ≡ ci.type.instL ls' : .sort u → + Γ ⊢ ci.type.instL ls ≡ ci.type.instL ls' : .sort u → + Γ ⊢ .const c ls ≡ .const c ls' : ci.type.instL ls + | appDF : + u.WF uvars → v.WF uvars → + Γ ⊢ A : .sort u → + A::Γ ⊢ B : .sort v → + Γ ⊢ f ≡ f' : .forallE A B → + Γ ⊢ a ≡ a' : A → + Γ ⊢ B.inst a ≡ B.inst a' : .sort v → + Γ ⊢ .app f a ≡ .app f' a' : B.inst a + | lamDF : + u.WF uvars → v.WF uvars → + Γ ⊢ A ≡ A' : .sort u → + A::Γ ⊢ B : .sort v → + A'::Γ ⊢ B : .sort v → + A::Γ ⊢ body ≡ body' : B → + A'::Γ ⊢ body ≡ body' : B → + Γ ⊢ .lam A body ≡ .lam A' body' : .forallE A B + | forallEDF : + u.WF uvars → v.WF uvars → + Γ ⊢ A ≡ A' : .sort u → + A::Γ ⊢ body ≡ body' : .sort v → + A'::Γ ⊢ body ≡ body' : .sort v → + Γ ⊢ .forallE A body ≡ .forallE A' body' : .sort (.imax u v) + | defeqDF : + u.WF uvars → Γ ⊢ A ≡ B : .sort u → Γ ⊢ e1 ≡ e2 : A → Γ ⊢ e1 ≡ e2 : B + | beta : + u.WF uvars → v.WF uvars → Γ ⊢ A : .sort u → A::Γ ⊢ B : .sort v → + A::Γ ⊢ e : B → Γ ⊢ e' : A → + Γ ⊢ B.inst e' : .sort v → + Γ ⊢ e.inst e' : B.inst e' → + Γ ⊢ .app (.lam A e) e' ≡ e.inst e' : B.inst e' + | eta : + u.WF uvars → v.WF uvars → + Γ ⊢ A : .sort u → + A::Γ ⊢ B : .sort v → + A.lift::A::Γ ⊢ B.liftN 1 1 : .sort v → + Γ ⊢ e : .forallE A B → + A::Γ ⊢ e.lift : .forallE A.lift (B.liftN 1 1) → + A::Γ ⊢ A.lift : .sort u → + Γ ⊢ .lam A (.app e.lift (.bvar 0)) ≡ e : .forallE A B + | structEta : + env.structEtas rule → + (∀ level ∈ levels, level.WF uvars) → + levels.length = rule.uvars → + params.length = rule.nparams → + env.SpineWF uvars Γ (rule.familyType.instL levels) + params (.sort resultLevel) → + u.WF uvars → + Γ ⊢ rule.structureType levels params : .sort u → + Γ ⊢ major : rule.structureType levels params → + Γ ⊢ rule.rebuild levels params major : + rule.structureType levels params → + Γ ⊢ rule.rebuild levels params major ≡ major : + rule.structureType levels params + | proofIrrel : + Γ ⊢ p : .sort .zero → Γ ⊢ h : p → Γ ⊢ h' : p → + Γ ⊢ h ≡ h' : p + | extra : + env.defeqs df → (∀ l ∈ ls, l.WF uvars) → ls.length = df.uvars → + u.WF uvars → + [] ⊢ df.type.instL ls : .sort u → + [] ⊢ df.lhs.instL ls : df.type.instL ls → + [] ⊢ df.rhs.instL ls : df.type.instL ls → + Γ ⊢ df.lhs.instL ls : df.type.instL ls → + Γ ⊢ df.rhs.instL ls : df.type.instL ls → + Γ ⊢ df.lhs.instL ls ≡ df.rhs.instL ls : df.type.instL ls + +end + +section +local notation:65 Γ " ⊢ " e " : " A:30 => HasTypeStrong Γ e A true +local notation:65 Γ " ⊢ " e " :! " A:30 => HasTypeStrong Γ e A false +local notation:65 Γ " ⊢ " e1 " ≡ " e2 " : " A:30 => IsDefEqStrong env uvars Γ e1 e2 A + +/-- +This is functionally a mutual inductive type, +but using a bool index makes it easier to do induction in lean. +The defeq rule is separated from the structural rules for easy inversion. +-/ +inductive HasTypeStrong : List VExpr → VExpr → VExpr → Bool → Prop where + | bvar : Lookup Γ i A → u.WF uvars → Γ ⊢ A : .sort u → Γ ⊢ .bvar i :! A + | sort' : l.WF uvars → l'.WF uvars → l ≈ l' → Γ ⊢ .sort l :! .sort (.succ l') + | const : + env.constants c = some ci → + (∀ l ∈ ls, l.WF uvars) → + ls.length = ci.uvars → + u.WF uvars → + [] ⊢ ci.type.instL ls : .sort u → + Γ ⊢ ci.type.instL ls : .sort u → + Γ ⊢ .const c ls :! ci.type.instL ls + | app : + u.WF uvars → v.WF uvars → + Γ ⊢ A : .sort u → + A::Γ ⊢ B : .sort v → + Γ ⊢ .forallE A B : .sort (.imax u v) → + Γ ⊢ f : .forallE A B → + Γ ⊢ a : A → + Γ ⊢ B.inst a : .sort v → + Γ ⊢ .app f a :! B.inst a + | lam : + u.WF uvars → v.WF uvars → + Γ ⊢ A : .sort u → + A::Γ ⊢ B : .sort v → + A::Γ ⊢ body : B → + Γ ⊢ .forallE A B : .sort (.imax u v) → + Γ ⊢ .lam A body :! .forallE A B + | forallE : + u.WF uvars → v.WF uvars → + Γ ⊢ A : .sort u → + A::Γ ⊢ body : .sort v → + Γ ⊢ .forallE A body :! .sort (.imax u v) + | base : Γ ⊢ e :! A → Γ ⊢ e : A + | defeq : u.WF uvars → Γ ⊢ A ≡ B : .sort u → + Γ ⊢ A : .sort u → Γ ⊢ B : .sort u → Γ ⊢ e : A → Γ ⊢ e : B +end + +end + +theorem IsDefEqStrong.hasType {env : VEnv} + (H : env.IsDefEqStrong U Γ e1 e2 A) : + env.IsDefEqStrong U Γ e1 e1 A ∧ env.IsDefEqStrong U Γ e2 e2 A := + ⟨H.trans H.symm, H.symm.trans H⟩ + +variable! (henv : Ordered env) in +theorem IsDefEqStrong.weakN (W : Ctx.LiftN n k Γ Γ') (H : env.IsDefEqStrong U Γ e1 e2 A) : + env.IsDefEqStrong U Γ' (e1.liftN n k) (e2.liftN n k) (A.liftN n k) := by + induction H generalizing k Γ' with + | bvar h1 h2 _ ih3 => refine .bvar (h1.weakN W) h2 (ih3 W) + | symm _ ih => exact .symm (ih W) + | trans _ _ ih1 ih2 => exact .trans (ih1 W) (ih2 W) + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | constDF h1 h2 h3 h4 h5 h6 h7 _ _ ih2 => + simp [(henv.closedC h1).instL.liftN_eq (Nat.zero_le _)] at ih2 ⊢ + exact .constDF h1 h2 h3 h4 h5 h6 h7 (ih2 W) + | appDF h1 h2 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + refine liftN_inst_hi .. ▸ .appDF h1 h2 (ih1 W) (ih2 W.succ) (ih3 W) (ih4 W) ?_ + exact liftN_inst_hi .. ▸ liftN_inst_hi .. ▸ ih5 W + | lamDF h1 h2 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + exact .lamDF h1 h2 (ih1 W) (ih2 W.succ) (ih3 W.succ) (ih4 W.succ) (ih5 W.succ) + | forallEDF h1 h2 _ _ _ ih1 ih2 ih3 => exact .forallEDF h1 h2 (ih1 W) (ih2 W.succ) (ih3 W.succ) + | defeqDF h1 _ _ ih1 ih2 => exact .defeqDF h1 (ih1 W) (ih2 W) + | beta h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + refine liftN_inst_hi .. ▸ liftN_instN_hi .. ▸ .beta h1 h2 + (ih1 W) (ih2 W.succ) (ih3 W.succ) (ih4 W) + (liftN_instN_hi .. ▸ ih5 W :) + (liftN_instN_hi .. ▸ liftN_instN_hi .. ▸ ih6 W :) + | @eta Γ a u B v e h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + have := IsDefEqStrong.eta h1 h2 (ih1 W) (ih2 W.succ) ?_ (ih4 W) ?_ ?_ + · simp [liftN]; rwa [← lift_liftN'] + · specialize ih3 W.succ.succ + have := liftN'_comm B n 1 (k+1) 1 (Nat.le_add_left ..) + rw [Nat.add_comm 1] at this; rwa [← this, ← lift_liftN'] at ih3 + · have ih5 : IsDefEqStrong _ _ _ _ _ (liftN n (lift (forallE ..)) _) := ih5 W.succ + rwa [← lift_liftN', ← lift_liftN'] at ih5 + · have ih6 := ih6 W.succ + rwa [← lift_liftN'] at ih6 + | @structEta rule levels _ params _ u major hreg hlevels + hlevelsLength hparamsLength hparamsSpine hu _ _ _ ihType ihMajor ihRebuild => + have hparamsSpine' := hparamsSpine.weakN henv W + rw [(henv.structEtaWF hreg).familyType_closed.instL.liftN_eq + (Nat.zero_le _)] at hparamsSpine' + have htype := ihType W + rw [VStructEta.structureType_liftN] at htype + have hmajor := ihMajor W + rw [VStructEta.structureType_liftN] at hmajor + have hrebuild := ihRebuild W + rw [VStructEta.rebuild_liftN rule levels params major + hparamsLength n k, VStructEta.structureType_liftN] at hrebuild + have hout := IsDefEqStrong.structEta hreg hlevels hlevelsLength + (by simpa using hparamsLength) hparamsSpine' hu htype hmajor hrebuild + simpa only [VStructEta.rebuild_liftN rule levels params major + hparamsLength n k, VStructEta.structureType_liftN] using hout + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel (ih1 W) (ih2 W) (ih3 W) + | extra h1 h2 h3 h4 h5 h6 h7 _ _ _ _ _ ih4 ih5 => + have ⟨⟨hA1, _⟩, hA2, hA3⟩ := henv.closed.2 h1 + simp [ + hA1.instL.liftN_eq (Nat.zero_le _), + hA2.instL.liftN_eq (Nat.zero_le _), + hA3.instL.liftN_eq (Nat.zero_le _)] at ih4 ih5 ⊢ + exact IsDefEqStrong.extra h1 h2 h3 h4 h5 h6 h7 (ih4 W) (ih5 W) + +theorem IsDefEqStrong.defeq (H : IsDefEqStrong env U Γ e1 e2 A) : env.IsDefEq U Γ e1 e2 A := by + induction H with + | bvar h => exact .bvar h + | symm _ ih => exact .symm ih + | trans _ _ ih1 ih2 => exact .trans ih1 ih2 + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | constDF h1 h2 h3 h4 h5 => exact .constDF h1 h2 h3 h4 h5 + | appDF _ _ _ _ _ _ _ _ _ ih1 ih2 => exact .appDF ih1 ih2 + | lamDF _ _ _ _ _ _ _ ih1 _ _ ih2 => exact .lamDF ih1 ih2 + | forallEDF _ _ _ _ _ ih1 ih2 => exact .forallEDF ih1 ih2 + | defeqDF _ _ _ ih1 ih2 => exact .defeqDF ih1 ih2 + | beta _ _ _ _ _ _ _ _ _ _ ih1 ih2 => exact .beta ih1 ih2 + | eta _ _ _ _ _ _ _ _ _ _ _ ih => exact .eta ih + | structEta hreg hlevels hlevelsLength hparamsLength hparamsSpine + _ _ _ _ _ ihMajor ihRebuild => + exact .structEta hreg hlevels hlevelsLength hparamsLength + hparamsSpine ihMajor ihRebuild + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel ih1 ih2 ih3 + | extra h1 h2 h3 => exact .extra h1 h2 h3 + +variable! {env env' : VEnv} (henv : env ≤ env') in +theorem IsDefEqStrong.mono + (H : env.IsDefEqStrong U Γ e1 e2 A) : env'.IsDefEqStrong U Γ e1 e2 A := by + induction H with + | bvar h1 h2 _ ih => exact .bvar h1 h2 ih + | symm _ ih => exact .symm ih + | trans _ _ ih1 ih2 => exact .trans ih1 ih2 + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | constDF h1 h2 h3 h4 h5 h6 _ _ ih1 ih2 => + exact .constDF (henv.1 h1) h2 h3 h4 h5 h6 ih1 ih2 + | appDF h1 h2 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => exact .appDF h1 h2 ih1 ih2 ih3 ih4 ih5 + | lamDF h1 h2 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => exact .lamDF h1 h2 ih1 ih2 ih3 ih4 ih5 + | forallEDF h1 h2 _ _ _ ih1 ih2 ih3 => exact .forallEDF h1 h2 ih1 ih2 ih3 + | defeqDF h1 _ _ ih1 ih2 => exact .defeqDF h1 ih1 ih2 + | beta h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => exact .beta h1 h2 ih1 ih2 ih3 ih4 ih5 ih6 + | eta h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => exact .eta h1 h2 ih1 ih2 ih3 ih4 ih5 ih6 + | structEta hreg hlevels hlevelsLength hparamsLength hparamsSpine + hu _ _ _ ihType ihMajor ihRebuild => + exact .structEta (henv.structEtas hreg) hlevels hlevelsLength + hparamsLength (hparamsSpine.mono henv) hu ihType ihMajor ihRebuild + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel ih1 ih2 ih3 + | extra h1 h2 h3 h4 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + exact .extra (henv.2 h1) h2 h3 h4 ih1 ih2 ih3 ih4 ih5 + +variable! (henv : Ordered env) in +theorem IsDefEqStrong.weak0 (H : env.IsDefEqStrong U [] e1 e2 A) : + env.IsDefEqStrong U Γ e1 e2 A := by + have ⟨h1, h2, h3⟩ := H.defeq.closedN' henv.closed ⟨⟩ + simpa [h1.liftN_eq (Nat.zero_le _), h2.liftN_eq (Nat.zero_le _), + h3.liftN_eq (Nat.zero_le _)] using H.weakN henv (.zero Γ rfl) + +inductive EqUpToLevels (U : Nat) : VExpr → VExpr → Prop + | bvar : EqUpToLevels U (.bvar i) (.bvar i) + | const : (∀ l ∈ ls, l.WF U) → (∀ l ∈ ls', l.WF U) → List.Forall₂ (· ≈ ·) ls ls' → + EqUpToLevels U (.const c ls) (.const c ls') + | sort : l.WF U → l'.WF U → l ≈ l' → EqUpToLevels U (.sort l) (.sort l') + | app : EqUpToLevels U f f' → EqUpToLevels U a a' → EqUpToLevels U (.app f a) (.app f' a') + | lam : EqUpToLevels U A A' → EqUpToLevels U e e' → EqUpToLevels U (.lam A e) (.lam A' e') + | forallE : EqUpToLevels U A A' → EqUpToLevels U B B' → EqUpToLevels U (.forallE A B) (.forallE A' B') + +variable! {env : VEnv} {ls ls' : List VLevel} + (hls : ∀ l ∈ ls, l.WF U) (hls' : ∀ l ∈ ls', l.WF U) (heq : List.Forall₂ (· ≈ ·) ls ls') in +theorem EqUpToLevels.instL (H : env.IsDefEqStrong U' Γ e1 e2 A) : + EqUpToLevels U (e1.instL ls) (e1.instL ls') ∧ EqUpToLevels U (e2.instL ls) (e2.instL ls') := by + induction H with + | bvar => exact ⟨.bvar, .bvar⟩ + | symm _ ih => exact ih.symm + | trans _ _ ih1 ih2 | proofIrrel _ _ _ _ ih1 ih2 + | extra _ _ _ _ _ _ _ _ _ _ ih1 ih2 => exact ⟨ih1.1, ih2.2⟩ + | sortDF h1 h2 h3 => + constructor <;> exact .sort (.inst hls) (.inst hls') (VLevel.inst_congr rfl heq) + | constDF h1 h2 h3 h4 h5 => + constructor <;> exact .const + (List.forall_mem_map.2 fun _ _ => .inst hls) + (List.forall_mem_map.2 fun _ _ => .inst hls') + (List.forall₂_map_left_iff.2 <| List.forall₂_map_right_iff.2 <| + .rfl fun _ _ => VLevel.inst_congr rfl heq) + | appDF _ _ _ _ _ _ _ _ _ ih1 ih2 => exact ⟨.app ih1.1 ih2.1, .app ih1.2 ih2.2⟩ + | lamDF _ _ _ _ _ _ _ ih1 _ _ ih2 => exact ⟨.lam ih1.1 ih2.1, .lam ih1.2 ih2.2⟩ + | forallEDF _ _ _ _ _ ih1 ih2 => exact ⟨.forallE ih1.1 ih2.1, .forallE ih1.2 ih2.2⟩ + | defeqDF _ _ _ _ ih => exact ih + | beta _ _ _ _ _ _ _ _ ih1 _ ih3 ih4 _ ih6 => exact ⟨.app (.lam ih1.1 ih3.1) ih4.1, ih6.2⟩ + | eta _ _ _ _ _ _ _ _ ih1 _ _ ih4 ih5 => exact ⟨.lam ih1.1 (.app ih5.1 .bvar), ih4.1⟩ + | structEta _ _ _ _ _ _ _ _ _ _ ihMajor ihRebuild => + exact ⟨ihRebuild.1, ihMajor.2⟩ + + +variable! {env : VEnv} (W : OnCtx Γ fun _ A => A.LevelWF U) in +theorem EqUpToLevels.refl (H : env.IsDefEqStrong U Γ e1 e2 A) : + EqUpToLevels U e1 e1 ∧ EqUpToLevels U e2 e2 := by + have := IsDefEq.levelWF H.defeq W + exact LevelWF.instL_id this.1 ▸ LevelWF.instL_id this.2.1 ▸ + EqUpToLevels.instL VLevel.params_wf VLevel.params_wf (.rfl fun _ _ => rfl) H + +theorem EqUpToLevels.weakN (H : EqUpToLevels U e e') : + EqUpToLevels U (e.liftN n k) (e'.liftN n k) := by + induction H generalizing k with + | bvar => exact .bvar + | const h1 h2 h3 => exact .const h1 h2 h3 + | sort h1 h2 h3 => exact .sort h1 h2 h3 + | app _ _ ih1 ih2 => exact .app ih1 ih2 + | lam _ _ ih1 ih2 => exact .lam ih1 ih2 + | forallE _ _ ih1 ih2 => exact .forallE ih1 ih2 + +variable! (h₀ : EqUpToLevels U e₀ e₀') in +theorem EqUpToLevels.instN (H : EqUpToLevels U e e') : + EqUpToLevels U (e.inst e₀ k) (e'.inst e₀' k) := by + induction H generalizing k with + | bvar => simp [inst, instVar]; split <;> [exact .bvar; split] <;> [exact h₀.weakN; exact .bvar] + | const h1 h2 h3 => exact .const h1 h2 h3 + | sort h1 h2 h3 => exact .sort h1 h2 h3 + | app _ _ ih1 ih2 => exact .app ih1 ih2 + | lam _ _ ih1 ih2 => exact .lam ih1 ih2 + | forallE _ _ ih1 ih2 => exact .forallE ih1 ih2 + +def EnvStrong (env : VEnv) (U : Nat) (e A : VExpr) : Prop := + env.IsDefEqStrong U [] e e A ∧ + (∃ u, env.IsDefEqStrong U [] A A (.sort u)) ∧ + (∀ U' ls ls', (∀ l ∈ ls, l.WF U') → (∀ l ∈ ls', l.WF U') → List.Forall₂ (· ≈ ·) ls ls' → + env.IsDefEqStrong U' [] (e.instL ls) (e.instL ls') (A.instL ls)) ∧ + ∀ A B, e = A.forallE B → + (∃ u, env.IsDefEqStrong U [] A A (.sort u)) ∧ + (∃ u, env.IsDefEqStrong U [A] B B (.sort u)) + +variable! {env : VEnv} {ls : List VLevel} (hls : ∀ l ∈ ls, l.WF U') in +theorem IsDefEqStrong.instL (H : env.IsDefEqStrong U Γ e1 e2 A) : + env.IsDefEqStrong U' (Γ.map (VExpr.instL ls)) (e1.instL ls) (e2.instL ls) (A.instL ls) := by + induction H with + | bvar h _ _ ih => + exact .bvar h.instL (.inst hls) ih + | constDF h1 h2 h3 h4 h5 _ _ _ ih1 ih2 => + simp [VExpr.instL, VExpr.instL_instL] at ih1 ih2 ⊢ + exact .constDF h1 + (by simp [VLevel.WF.inst hls]) (by simp [VLevel.WF.inst hls]) (by simp [h4]) + (by simpa using h5.imp fun _ _ => VLevel.inst_congr_l) (.inst hls) ih1 ih2 + | symm _ ih => exact .symm ih + | trans _ _ ih1 ih2 => exact .trans ih1 ih2 + | sortDF _ _ h3 => + exact .sortDF (VLevel.WF.inst hls) (VLevel.WF.inst hls) (VLevel.inst_congr_l h3) + | appDF _ _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + exact instL_instN ▸ .appDF (.inst hls) (.inst hls) + ih1 ih2 ih3 ih4 (instL_instN ▸ instL_instN ▸ ih5) + | lamDF _ _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + exact .lamDF (.inst hls) (.inst hls) ih1 ih2 ih3 ih4 ih5 + | forallEDF _ _ _ _ _ ih1 ih2 ih3 => + exact .forallEDF (.inst hls) (.inst hls) ih1 ih2 ih3 + | defeqDF _ _ _ ih1 ih2 => + exact .defeqDF (.inst hls) ih1 ih2 + | beta _ _ _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + simpa using .beta (.inst hls) (.inst hls) ih1 ih2 ih3 ih4 + (by simpa [VExpr.instL] using ih5) (by simpa [VExpr.instL] using ih6) + | eta _ _ _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + simpa [VExpr.instL] using .eta (.inst hls) (.inst hls) ih1 ih2 + (by simpa [VExpr.instL] using ih3) ih4 + (by simpa [VExpr.instL] using ih5) (by simpa [VExpr.instL] using ih6) + | @structEta rule levels _ params _ u major hreg hlevels + hlevelsLength hparamsLength hparamsSpine _ _ _ _ ihType ihMajor ihRebuild => + have hlevels' : ∀ level ∈ levels.map (VLevel.inst ls), + level.WF U' := by + intro level hlevel + obtain ⟨source, _, heq⟩ := List.mem_map.1 hlevel + rw [← heq] + exact VLevel.WF.inst hls + rw [VStructEta.structureType_instL] at ihType ihMajor + rw [VStructEta.rebuild_instL, + VStructEta.structureType_instL] at ihRebuild + have hparamsSpine' := hparamsSpine.instL hls + rw [VExpr.instL_instL] at hparamsSpine' + have hout := IsDefEqStrong.structEta hreg hlevels' + (by simpa using hlevelsLength) (by simpa using hparamsLength) + hparamsSpine' (VLevel.WF.inst hls) ihType ihMajor ihRebuild + simpa only [VStructEta.rebuild_instL, + VStructEta.structureType_instL] using hout + | proofIrrel _ _ _ ih1 ih2 ih3 => + exact .proofIrrel ih1 ih2 ih3 + | extra h1 h2 h3 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + simp [VExpr.instL, VExpr.instL_instL] at ih1 ih2 ih3 ih4 ih5 ⊢ + exact .extra h1 (by simp [VLevel.WF.inst hls]) (by simp [h3]) + (.inst hls) ih1 ih2 ih3 ih4 ih5 + +def CtxStrong (env : VEnv) (U Γ) := + OnCtx Γ fun Γ A => ∃ u, env.IsDefEqStrong U Γ A A (.sort u) + +variable! (henv : Ordered env) in +nonrec theorem CtxStrong.lookup {Γ} (H : CtxStrong env U Γ) (h : Lookup Γ i A) : + ∃ u, env.IsDefEqStrong U Γ A A (.sort u) := + H.lookup h fun ⟨_, h⟩ => ⟨_, h.weakN henv .one⟩ + +theorem CtxStrong.defeq {Γ} (H : CtxStrong env U Γ) : OnCtx Γ (env.IsType U) := + H.mono fun ⟨_, h⟩ => ⟨_, h.defeq⟩ + +theorem CtxStrong.levelWF : ∀ {Γ}, CtxStrong env U Γ → OnCtx Γ fun _ A => A.LevelWF U + | [], h => h + | _::_, ⟨h1, _, h2⟩ => ⟨levelWF h1, (h2.defeq.levelWF (levelWF h1)).1⟩ + +variable! (henv : Ordered env) (h₀ : env.IsDefEqStrong U Γ₀ e₀ e₀ A₀) (hΓ₀ : CtxStrong env U Γ₀) in +theorem IsDefEqStrong.instN (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) (H : env.IsDefEqStrong U Γ₁ e1 e2 A) + (hΓ : CtxStrong env U Γ) : + env.IsDefEqStrong U Γ (e1.inst e₀ k) (e2.inst e₀ k) (A.inst e₀ k) := by + induction H generalizing Γ k with + | @bvar _ i ty _ h _ h2 ih => + dsimp [inst]; clear h2 ih + induction W generalizing i ty with + | zero => + cases h with simp [inst_lift] + | zero => exact h₀ + | succ h => + let ⟨u, hty⟩ := hΓ₀.lookup henv h + exact .bvar h (hty.defeq.sort_r henv hΓ₀.defeq) hty + | succ _ ih => + cases h with (simp; rw [Nat.add_comm, ← liftN_instN_lo (hj := Nat.zero_le _)]) + | zero => + let ⟨u, hty⟩ := hΓ.lookup henv .zero + exact .bvar .zero (hty.defeq.sort_r henv hΓ.defeq) hty + | succ h => exact (ih h hΓ.1).weakN henv .one + | symm _ ih => exact .symm (ih W hΓ) + | trans _ _ ih1 ih2 => exact .trans (ih1 W hΓ) (ih2 W hΓ) + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | constDF h1 h2 h3 h4 h5 h6 h7 _ _ ih2 => + simp [(henv.closedC h1).instL.instN_eq (Nat.zero_le _)] at ih2 ⊢ + exact .constDF h1 h2 h3 h4 h5 h6 h7 (ih2 W hΓ) + | appDF h1 h2 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + exact inst0_inst_hi .. ▸ .appDF h1 h2 + (ih1 W hΓ) (ih2 W.succ ⟨hΓ, _, ih1 W hΓ⟩) + (ih3 W hΓ) (ih4 W hΓ) (inst0_inst_hi .. ▸ inst0_inst_hi .. ▸ ih5 W hΓ) + | lamDF h1 h2 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + exact + have hΓ' := ⟨hΓ, _, (ih1 W hΓ).hasType.1⟩ + have hΓ'' := ⟨hΓ, _, (ih1 W hΓ).hasType.2⟩ + .lamDF h1 h2 (ih1 W hΓ) (ih2 W.succ hΓ') (ih3 W.succ hΓ'') (ih4 W.succ hΓ') (ih5 W.succ hΓ'') + | forallEDF h1 h2 _ _ _ ih1 ih2 ih3 => + exact .forallEDF h1 h2 (ih1 W hΓ) + (ih2 W.succ ⟨hΓ, _, (ih1 W hΓ).hasType.1⟩) (ih3 W.succ ⟨hΓ, _, (ih1 W hΓ).hasType.2⟩) + | defeqDF h1 _ _ ih1 ih2 => exact .defeqDF h1 (ih1 W hΓ) (ih2 W hΓ) + | beta h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + rw [inst0_inst_hi, inst0_inst_hi]; exact + have hΓ' := ⟨hΓ, _, ih1 W hΓ⟩ + .beta h1 h2 + (ih1 W hΓ) (ih2 W.succ hΓ') (ih3 W.succ hΓ') (ih4 W hΓ) + (inst0_inst_hi .. ▸ ih5 W hΓ) (inst0_inst_hi .. ▸ inst0_inst_hi .. ▸ ih6 W hΓ) + | eta h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + have := + have hΓ' := ⟨hΓ, _, (ih1 W hΓ).hasType.1⟩ + IsDefEqStrong.eta h1 h2 (ih1 W hΓ) (ih2 W.succ hΓ') + (by + have := ih3 W.succ.succ ⟨hΓ', _, by + rw [← lift_instN_lo]; exact (ih1 W hΓ).hasType.1.weakN henv .one⟩ + rwa [lift_instN_lo, liftN_instN_lo (hj := Nat.le_add_left ..), Nat.add_comm 1]) + (ih4 W hΓ) + (by + have := ih5 W.succ hΓ' + simp only [inst, ← lift_instN_lo] at this + rwa [liftN_instN_lo (hj := Nat.le_add_left ..), Nat.add_comm 1]) + (by simpa [inst, ← lift_instN_lo] using ih6 W.succ hΓ') + rw [lift, liftN_instN_lo (hj := Nat.zero_le _), Nat.add_comm] at this + simpa [inst] + | @structEta rule levels _ params _ u major hreg hlevels + hlevelsLength hparamsLength hparamsSpine hu _ _ _ ihType ihMajor ihRebuild => + have hparamsSpine' := SpineWF.instN henv W h₀.defeq hparamsSpine + rw [(henv.structEtaWF hreg).familyType_closed.instL.instN_eq + (Nat.zero_le _)] at hparamsSpine' + have htype := ihType W hΓ + rw [VStructEta.structureType_instN] at htype + have hmajor := ihMajor W hΓ + rw [VStructEta.structureType_instN] at hmajor + have hrebuild := ihRebuild W hΓ + rw [VStructEta.rebuild_instN rule levels params major e₀ + hparamsLength k, VStructEta.structureType_instN] at hrebuild + have hout := IsDefEqStrong.structEta hreg hlevels hlevelsLength + (by simpa using hparamsLength) hparamsSpine' hu htype hmajor hrebuild + simpa only [VStructEta.rebuild_instN rule levels params major e₀ + hparamsLength k, VStructEta.structureType_instN] using hout + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel (ih1 W hΓ) (ih2 W hΓ) (ih3 W hΓ) + | extra h1 h2 h3 h4 h5 h6 h7 _ _ _ _ _ ih4 ih5 => + have ⟨⟨hA1, _⟩, hA2, hA3⟩ := henv.closed.2 h1 + simp [ + hA1.instL.instN_eq (Nat.zero_le _), + hA2.instL.instN_eq (Nat.zero_le _), + hA3.instL.instN_eq (Nat.zero_le _)] at ih4 ih5 ⊢ + exact .extra h1 h2 h3 h4 h5 h6 h7 (ih4 W hΓ) (ih5 W hΓ) + +theorem IsDefEqStrong.defeqDF_l (henv : Ordered env) (hΓ : CtxStrong env U Γ) + (h1 : env.IsDefEqStrong U Γ A A' (.sort u)) + (h2 : env.IsDefEqStrong U (A::Γ) e1 e2 B) : env.IsDefEqStrong U (A'::Γ) e1 e2 B := by + simpa [instN_bvar0] using + have hu := h1.defeq.sort_r henv hΓ.defeq + have hΓ' := ⟨hΓ, _, h1.hasType.2⟩ + h1.weakN henv (.one (A := A')) + |>.symm.defeqDF hu (.bvar .zero hu (h1.hasType.2.weakN henv .one)) + |>.instN henv hΓ' .zero (h2.weakN henv (.succ (.one (A := A')))) hΓ' + +variable! (henv : Ordered env) (envIH : env.OnTypes (EnvStrong env)) in +theorem IsDefEqStrong.forallE_inv' (hΓ : CtxStrong env U Γ) + (H : env.IsDefEqStrong U Γ e1 e2 V) (eq : e1 = A.forallE B ∨ e2 = A.forallE B) : + (∃ u, env.IsDefEqStrong U Γ A A (.sort u)) ∧ ∃ v, env.IsDefEqStrong U (A::Γ) B B (.sort v) := by + induction H generalizing A B with + | symm _ ih => exact ih hΓ eq.symm + | trans _ _ ih1 ih2 + | proofIrrel _ _ _ _ ih1 ih2 => + obtain eq | eq := eq + · exact ih1 hΓ (.inl eq) + · exact ih2 hΓ (.inr eq) + | forallEDF _ _ h1 h2 => + obtain ⟨⟨⟩⟩ | ⟨⟨⟩⟩ := eq + · exact ⟨⟨_, h1.hasType.1⟩, _, h2.hasType.1⟩ + · exact ⟨⟨_, h1.hasType.2⟩, _, h1.defeqDF_l henv hΓ h2.hasType.2⟩ + | defeqDF _ _ _ _ ih2 => exact ih2 hΓ eq + | @beta _ _ _ _ _ e _ _ _ h1 _ _ h4 _ _ _ _ ih3 ih4 => + obtain ⟨⟨⟩⟩ | eq := eq + cases e with + | bvar i => + cases i with simp [inst] at eq + | zero => exact ih4 hΓ (.inl eq) + | forallE A B => + cases eq + let ⟨⟨_, A1⟩, _, A2⟩ := ih3 ⟨hΓ, _, h1⟩ (.inl rfl) + refine ⟨⟨_, h4.instN henv hΓ .zero A1 hΓ⟩, _, h4.instN henv hΓ (.succ .zero) A2 ?_⟩ + exact ⟨hΓ, _, h4.instN henv hΓ .zero A1 hΓ⟩ + | _ => cases eq + | eta _ _ _ _ _ _ _ _ _ _ _ ih => + obtain ⟨⟨⟩⟩ | eq := eq + exact ih hΓ (.inl eq) + | structEta _ _ _ _ _ _ _ _ _ _ ihMajor ihRebuild => + obtain eq | eq := eq + · exact ihRebuild hΓ (.inl eq) + · exact ihMajor hΓ (.inl eq) + | @extra df ls _ Γ h1 h2 => + suffices ∀ e, VExpr.instL ls e = VExpr.forallE A B → + EnvStrong env df.uvars e df.type → + (∃ u, IsDefEqStrong env U Γ A A (.sort u)) ∧ + (∃ u, IsDefEqStrong env U (A :: Γ) B B (.sort u)) by + have ⟨A1, A2⟩ := envIH.2 h1 + cases eq <;> exact this _ ‹_› ‹_› + intro e eq IH + cases e <;> cases eq; rename_i A B + let ⟨⟨_, A1⟩, v, A2⟩ := IH.2.2.2 _ _ rfl + refine ⟨⟨_, (A1.instL h2).weak0 henv⟩, v.inst ls, ?_⟩ + have := (A2.instL h2).weakN henv (.succ (.zero Γ)) + have C1 := (A1.instL h2).defeq.closedN henv ⟨⟩ + have C2 := (A2.instL h2).defeq.closedN henv ⟨⟨⟩, C1⟩ + rw [C1.liftN_eq (Nat.zero_le _), C2.liftN_eq (by exact Nat.le_refl _)] at this + simpa [liftN] + | _ => nomatch eq + +variable! (henv : Ordered env) (envIH : env.OnTypes (EnvStrong env)) in +theorem IsDefEqStrong.isType' (hΓ : CtxStrong env U Γ) (H : env.IsDefEqStrong U Γ e1 e2 A) : + ∃ u, env.IsDefEqStrong U Γ A A (.sort u) := by + induction H with + | bvar h => exact hΓ.lookup henv h + | symm _ ih => exact ih hΓ + | trans _ _ ih1 => exact ih1 hΓ + | sortDF h1 => exact ⟨_, .sortDF h1 h1 rfl⟩ + | constDF h1 h2 => + let ⟨_, h⟩ := envIH.1 h1 + exact ⟨_, (h.1.instL h2).weak0 henv⟩ + | appDF _ _ _ _ _ h4 _ _ _ ih3 => + let ⟨_, ih3⟩ := ih3 hΓ + have ⟨_, _, ih3⟩ := ih3.forallE_inv' henv envIH hΓ (.inl rfl) + exact ⟨_, h4.hasType.1.instN henv hΓ .zero ih3 hΓ⟩ + | lamDF h1 h2 h3 h4 => exact ⟨_, .forallEDF h1 h2 h3.hasType.1 h4 h4⟩ + | forallEDF h1 h2 => exact ⟨_, .sortDF ⟨h1, h2⟩ ⟨h1, h2⟩ rfl⟩ + | defeqDF _ h2 => exact ⟨_, h2.hasType.2⟩ + | beta _ _ _ h4 _ h6 => exact ⟨_, h6.hasType.1.instN henv hΓ .zero h4 hΓ⟩ + | eta _ _ _ _ _ _ _ _ _ _ _ ih => exact ih hΓ + | @structEta _ _ _ _ _ u _ _ _ _ _ _ _ htype _ _ _ _ _ => + exact ⟨u, htype⟩ + | proofIrrel h1 => exact ⟨_, h1⟩ + | extra h1 h2 => + have ⟨_, h⟩ := (envIH.2 h1).2.2.1 + exact ⟨_, (h.instL h2).weak0 henv⟩ + +theorem IsDefEqStrong.instDF + (henv : Ordered env) (hΓ : CtxStrong env U Γ) (hu : u.WF U) (hv : v.WF U) + (hA : env.IsDefEqStrong U Γ A A (.sort u)) + (hB : env.IsDefEqStrong U (A::Γ) B B (.sort v)) + (hf : env.IsDefEqStrong U (A::Γ) f f' B) + (ha : env.IsDefEqStrong U Γ a a' A) : + env.IsDefEqStrong U Γ (f.inst a) (f'.inst a') (B.inst a) := + have H2 {f f' B v} + (hv : v.WF U) + (hB : env.IsDefEqStrong U (A::Γ) B B (.sort v)) + (hf : env.IsDefEqStrong U (A::Γ) f f' B) + (hi : IsDefEqStrong env U Γ (inst B a) (inst B a') (sort v)) : + env.IsDefEqStrong U Γ (f.inst a) (f'.inst a') (B.inst a) := + have H1 {a f} + (hf : env.IsDefEqStrong U (A::Γ) f f' B) + (ha : IsDefEqStrong env U Γ a a A) : + env.IsDefEqStrong U Γ (.app (.lam A f) a) (f.inst a) (B.inst a) := + IsDefEqStrong.beta hu hv hA hB hf.hasType.1 ha + (ha.hasType.1.instN henv hΓ .zero hB hΓ) + (ha.hasType.1.instN henv hΓ .zero hf.hasType.1 hΓ) + (H1 hf ha.hasType.1).symm.trans <| + .trans (.appDF hu hv hA hB (.lamDF hu hv hA hB hB hf hf) ha hi) <| + .defeqDF hv (.symm hi) (H1 hf.hasType.2 ha.hasType.2) + H2 hv hB hf <| H2 (v := v.succ) hv (.sortDF hv hv rfl) hB (.sortDF hv hv rfl) + +variable! (henv : Ordered env) (envIH : env.OnTypes (EnvStrong env)) + (W : CtxStrong env U Γ) in +theorem EqUpToLevels.defeq (H : env.IsDefEqStrong U Γ e1 e2 A) + (H1 : EqUpToLevels U e1 e1') (H2 : EqUpToLevels U e2 e2') : + env.IsDefEqStrong U Γ e1' e2' A := by + induction H generalizing e1' e2' with + | bvar h1 h2 h3 => let .bvar := H1; let .bvar := H2; exact .bvar h1 h2 h3 + | constDF h1 h2 h3 h4 h5 h6 _ _ ih1 ih2 => + let .const a1 a2 a3 := H1 + let .const b1 b2 b3 := H2 + let ⟨_, c1⟩ := envIH.1 h1 + have c2 := a3.flip.trans (T := (· ≈ ·)) (fun _ _ _ => (·.symm.trans)) <| + h5.trans (T := (· ≈ ·)) (fun _ _ _ => Eq.trans) b3 + have := c1.2.2.1 _ _ _ a2 b2 c2 + exact .defeqDF (.inst a1) (.symm ((c1.2.2.1 _ _ _ a1 a2 a3).weak0 henv)) <| + .constDF h1 a2 b2 (a3.length_eq.symm.trans h4) c2 (.inst a2) this (this.weak0 henv) + | symm _ ih => exact (ih W H2 H1).symm + | trans h1 _ ih1 ih2 => + have H3 := (EqUpToLevels.refl W.levelWF h1).2; exact (ih1 W H1 H3).trans (ih2 W H3 H2) + | sortDF h1 h2 h3 => + let .sort a1 a2 a3 := H1 + let .sort b1 b2 b3 := H2 + exact .defeqDF (by exact a1) + (.symm <| .sortDF (by exact a1) (by exact a2) (VLevel.succ_congr a3)) + (.sortDF a2 b2 (a3.symm.trans <| h3.trans b3)) + | appDF h1 h2 h3 h4 h5 h6 _ ih1 ih2 ih3 ih4 ih5 => + let .app a1 a2 := H1 + let .app b1 b2 := H2 + have := ih4 W a2 (EqUpToLevels.refl W.levelWF h6).2 |>.trans h6.symm + exact .defeqDF h2 (.instDF henv W h1 (by exact h2) h3 (.sortDF h2 h2 rfl) h4 this) <| + .appDF h1 h2 h3 h4 (ih3 W a1 b1) (ih4 W a2 b2) <| + .instDF henv W h1 (by exact h2) h3 (.sortDF h2 h2 rfl) h4 (ih4 W a2 b2) + | lamDF h1 h2 h3 h4 h5 h6 h7 ih1 ih2 ih3 ih4 => + let .lam a1 a2 := H1 + let .lam b1 b2 := H2 + have c1 := ih1 W a1 (EqUpToLevels.refl W.levelWF h3).2 |>.trans h3.symm + have c2 := ih1 W (EqUpToLevels.refl W.levelWF h3).1 b1 + have h4' := c1.symm.defeqDF_l henv W h4 + exact have ih := ih4 ⟨W, _, h3.hasType.1⟩ a2 b2 + .defeqDF (by exact ⟨h1, h2⟩) (.forallEDF h1 h2 c1 h4' h4) <| + .lamDF h1 h2 (ih1 W a1 b1) h4' (.defeqDF_l henv W c2 h4) + (.defeqDF_l henv W c1.symm ih) (.defeqDF_l henv W c2 ih) + | forallEDF h1 h2 h3 _ _ ih1 ih2 => + let .forallE a1 a2 := H1 + let .forallE b1 b2 := H2 + have c1 := ih1 W a1 (EqUpToLevels.refl W.levelWF h3).2 |>.trans h3.symm + have c2 := ih1 W (EqUpToLevels.refl W.levelWF h3).1 b1 + exact .forallEDF h1 h2 (ih1 W a1 b1) + (.defeqDF_l henv W c1.symm <| ih2 ⟨W, _, h3.hasType.1⟩ a2 b2) + (.defeqDF_l henv W c2 <| ih2 ⟨W, _, h3.hasType.1⟩ a2 b2) + | defeqDF h1 h2 _ _ ih => exact .defeqDF h1 h2 (ih W H1 H2) + | beta h1 h2 h3 h4 h5 h6 h7 _ ih1 _ ih3 ih4 ih5 ih6 => + let .app a1 a3 := H1; let .lam a1 a2 := a1 + have c1 := ih1 W a1 (EqUpToLevels.refl W.levelWF h3).2 |>.trans h3.symm + have c2 := ih4 W a3 (EqUpToLevels.refl W.levelWF h6).2 |>.trans h6.symm + have c3 := ih3 ⟨W, _, h3⟩ a2 a2 + have hb := (EqUpToLevels.refl (CtxStrong.levelWF (by exact ⟨W, _, h3⟩)) h4).2 + have c4 := ih5 W (.instN a3 hb) (EqUpToLevels.refl W.levelWF h7).2 + refine .trans ?_ (ih6 W (.instN a3 a2) H2) + refine .defeqDF h2 (.instDF henv W h1 (by exact h2) h3 (.sortDF h2 h2 rfl) h4 c2) ?_ + exact .beta h1 h2 c1.hasType.1 (.defeqDF_l henv W c1.symm h4) + (.defeqDF_l henv W c1.symm c3) (.defeqDF h1 c1.symm c2.hasType.1) + c4.hasType.1 (.instN henv c2.hasType.1 W .zero c3 W) + | eta h1 h2 h3 h4 h5 h6 h7 h8 ih1 ih2 ih3 ih4 ih5 => + let .lam a1 a3 := H1; let .app a2 a3 := a3; let .bvar := a3 + have c1 := ih1 W a1 (EqUpToLevels.refl W.levelWF h3).2 |>.trans h3.symm + have c2 := have W' := ⟨W, _, h3⟩; ih5 W' a2 (EqUpToLevels.refl W'.levelWF h7).2 + have c3 := IsDefEqStrong.appDF h1 h2 h8 h5 c2 (.bvar .zero h1 h8) + rw [instN_bvar0] at c3; specialize c3 h4 + refine .trans + (.symm <| .lamDF h1 h2 c1.symm h4 (.defeqDF_l henv W c1.symm h4) c3.symm + (.defeqDF_l henv W c1.symm c3.symm)) ?_ + exact .trans (.eta h1 h2 h3 h4 h5 h6 h7 h8) (ih4 W (EqUpToLevels.refl W.levelWF h6).1 H2) + | structEta hreg hlevels hlevelsLength hparamsLength hparamsSpine hu htype hmajor + hrebuild _ ihMajor ihRebuild => + have hrebuildRefl := (EqUpToLevels.refl W.levelWF hrebuild).2 + have hmajorRefl := (EqUpToLevels.refl W.levelWF hmajor).1 + exact (ihRebuild W H1 hrebuildRefl).trans <| + (IsDefEqStrong.structEta hreg hlevels hlevelsLength hparamsLength + hparamsSpine hu htype hmajor hrebuild).trans + (ihMajor W hmajorRefl H2) + | proofIrrel h1 _ _ _ ih1 ih2 => exact .proofIrrel h1 (ih1 W H1 H1) (ih2 W H2 H2) + | extra h1 h2 h3 h4 h5 h6 h7 h8 h9 _ ih1 ih2 => + have c1 := ih1 trivial H1 (EqUpToLevels.refl (by trivial) h6).2 + have c2 := ih2 trivial H2 (EqUpToLevels.refl (by trivial) h7).2 + refine .weak0 henv <| c1.trans <| .trans ?_ c2.symm + exact .extra h1 h2 h3 h4 h5 h6 h7 h6 h7 + +variable! (henv : Ordered env) (envIH : env.OnTypes (EnvStrong env)) in +theorem IsDefEq.strong' (hΓ : CtxStrong env U Γ) + (H : env.IsDefEq U Γ e1 e2 A) : env.IsDefEqStrong U Γ e1 e2 A := by + have hctx {Γ} (H : OnCtx Γ fun Γ A => ∃ u, env.IsDefEqStrong U Γ A A (.sort u)) : + OnCtx Γ (env.IsType U) := H.mono fun ⟨_, h⟩ => ⟨_, h.defeq⟩ + induction H using IsDefEq.rec + (motive_2 := fun _ _ _ _ _ => True) with + | bvar h => + let ⟨u, hA⟩ := hΓ.lookup henv h + exact .bvar h (hA.defeq.sort_r henv (hctx hΓ)) hA + | symm _ ih => exact (ih hΓ).symm + | trans _ _ ih1 ih2 => exact (ih1 hΓ).trans (ih2 hΓ) + | sortDF h1 h2 h3 => exact .sortDF h1 h2 h3 + | @constDF _ _ ls₁ ls₂ _ h1 h2 h3 h4 h5 => + let ⟨u, h6⟩ := envIH.1 h1 + have := h6.2.2.1 _ _ _ h2 h3 h5 + exact .constDF h1 h2 h3 h4 h5 (.inst h2) this (this.weak0 henv) + | appDF _ _ ih1 ih2 => + let ⟨_, h3⟩ := (ih1 hΓ).isType' henv envIH hΓ + let ⟨⟨u, hA⟩, ⟨v, hB⟩⟩ := h3.forallE_inv' henv envIH hΓ (.inl rfl) + have hu := hA.defeq.sort_r henv hΓ.defeq + have hΓ' : CtxStrong env U (_::_) := ⟨hΓ, _, hA⟩ + have hv := hB.defeq.sort_r henv hΓ'.defeq + exact .appDF hu hv hA hB (ih1 hΓ) (ih2 hΓ) <| + .instDF (v := v.succ) henv hΓ hu hv hA (.sortDF hv hv rfl) hB (ih2 hΓ) + | lamDF hA _ ih1 ih2 => + have hu := hA.sort_r henv hΓ.defeq + have hΓ' : CtxStrong env U (_::_) := ⟨hΓ, _, (ih1 hΓ).hasType.1⟩ + let ⟨_, hB⟩ := (ih2 hΓ').isType' henv envIH hΓ' + exact .lamDF hu (hB.defeq.sort_r henv hΓ'.defeq) (ih1 hΓ) + hB ((ih1 hΓ).defeqDF_l henv hΓ hB) (ih2 hΓ') ((ih1 hΓ).defeqDF_l henv hΓ (ih2 hΓ')) + | forallEDF hA hb ih1 ih2 => + have hu := hA.sort_r henv hΓ.defeq + have hΓ' : CtxStrong env U (_::_) := ⟨hΓ, _, (ih1 hΓ).hasType.1⟩ + exact .forallEDF hu (hb.sort_r henv hΓ'.defeq) + (ih1 hΓ) (ih2 hΓ') ((ih1 hΓ).defeqDF_l henv hΓ (ih2 hΓ')) + | defeqDF hAB _ ih1 ih2 => + exact .defeqDF (hAB.sort_r henv hΓ.defeq) (ih1 hΓ) (ih2 hΓ) + | beta _ _ ih1 ih2 => + have he' := ih2 hΓ + have ⟨_, hA⟩ := he'.isType' henv envIH hΓ + have hΓ' : CtxStrong env U (_::_) := ⟨hΓ, _, hA⟩ + have he := ih1 hΓ' + have ⟨_, hB⟩ := he.isType' henv envIH hΓ' + exact .beta (hA.defeq.sort_r henv hΓ.defeq) (hB.defeq.sort_r henv hΓ'.defeq) + hA hB he he' (he'.instN henv hΓ .zero hB hΓ) (he'.instN henv hΓ .zero he hΓ) + | eta _ ih => + have he := ih hΓ + let ⟨_, hAB⟩ := he.isType' henv envIH hΓ + let ⟨⟨u, hA⟩, ⟨v, hB⟩⟩ := hAB.forallE_inv' henv envIH hΓ (.inl rfl) + have hΓ' : CtxStrong env U (_::_) := ⟨hΓ, _, hA⟩ + exact .eta (hA.defeq.sort_r henv hΓ.defeq) (hB.defeq.sort_r henv hΓ'.defeq) + hA hB (hB.weakN henv (.succ .one)) he (he.weakN henv .one) (hA.weakN henv .one) + | structEta hreg hlevels hlevelsLength hparamsLength hparamsSpine + _ _ _ ihMajor ihRebuild => + have hmajor := ihMajor hΓ + have hrebuild := ihRebuild hΓ + let ⟨u, htype⟩ := hmajor.isType' henv envIH hΓ + exact .structEta hreg hlevels hlevelsLength hparamsLength + hparamsSpine (htype.defeq.sort_r henv hΓ.defeq) htype hmajor hrebuild + | proofIrrel _ _ _ ih1 ih2 ih3 => exact .proofIrrel (ih1 hΓ) (ih2 hΓ) (ih3 hΓ) + | extra h1 h2 h3 => + let ⟨⟨hl, ⟨_, ht⟩, _⟩, hr, _, _⟩ := envIH.2 h1 + exact .extra h1 h2 h3 (.inst h2) (ht.instL h2) + (hl.instL h2) (hr.instL h2) ((hl.instL h2).weak0 henv) ((hr.instL h2).weak0 henv) + | nil | cons => trivial + +theorem CtxStrong.strong' (henv : Ordered env) (envIH : env.OnTypes (EnvStrong env)) + (hΓ : OnCtx Γ (env.IsType U)) : CtxStrong env U Γ := by + induction Γ with + | nil => trivial + | cons _ _ ih => let ⟨hΓ, _, hA⟩ := hΓ; exact ⟨ih hΓ, _, hA.strong' henv envIH (ih hΓ)⟩ + +theorem Ordered.strong (henv : Ordered env) : OnTypes env (EnvStrong env) := by + refine henv.induction _ (fun le ⟨h1, ⟨_, h2⟩, h3, h4⟩ => ?_) (fun henv IH H => ?_) + · refine ⟨h1.mono le, ⟨_, h2.mono le⟩, ?_, ?_⟩ + · exact fun _ _ _ h4 h5 h6 => (h3 _ _ _ h4 h5 h6).mono le + · exact fun _ _ eq => let ⟨⟨_, h4⟩, ⟨_, h5⟩⟩ := h4 _ _ eq; ⟨⟨_, h4.mono le⟩, ⟨_, h5.mono le⟩⟩ + · have H' := H.strong' henv IH (Γ := []) ⟨⟩ + refine ⟨H', H'.isType' henv IH ⟨⟩, fun _ _ _ h1 h2 h3 => ?_, ?_⟩ + · exact EqUpToLevels.defeq henv IH (by trivial) (.instL h1 H') + (EqUpToLevels.refl (by trivial) (.instL h1 H')).1 (EqUpToLevels.instL h1 h2 h3 H').1 + · exact fun _ _ eq => H'.forallE_inv' henv IH ⟨⟩ (.inl eq) + +theorem CtxStrong.strong (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) : CtxStrong env U Γ := + .strong' henv henv.strong hΓ + +theorem IsDefEq.strong (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) + (H : env.IsDefEq U Γ e1 e2 A) : env.IsDefEqStrong U Γ e1 e2 A := + H.strong' henv henv.strong (.strong henv hΓ) + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem IsDefEq.eqUpToLevels (H : env.IsDefEq U Γ e1 e2 A) + (H1 : EqUpToLevels U e2 e2') : env.IsDefEq U Γ e1 e2' A := + have W := .strong' henv henv.strong hΓ + have := H.strong henv hΓ + (EqUpToLevels.defeq henv henv.strong W (H.strong henv hΓ) + (EqUpToLevels.refl W.levelWF this).1 H1).defeq + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U')) {ls ls' : List VLevel} + (hls : ∀ l ∈ ls, l.WF U) (hls' : ∀ l ∈ ls', l.WF U) (heq : List.Forall₂ (· ≈ ·) ls ls') in +theorem IsDefEq.instL_r (H : env.IsDefEq U' Γ e1 e2 A) : + env.IsDefEq U (Γ.map (VExpr.instL ls)) (e1.instL ls) (e2.instL ls') (A.instL ls) := + have := H.strong henv hΓ + IsDefEq.eqUpToLevels henv (hΓ.instL hls) (this.instL hls).defeq + (EqUpToLevels.instL hls hls' heq this).2 + +theorem IsDefEqStrong.hasType' {env : VEnv} + (H : env.IsDefEqStrong U Γ e1 e2 A) : + env.HasTypeStrong U Γ e1 A true ∧ env.HasTypeStrong U Γ e2 A true := by + induction H with + | bvar h1 h2 _ ih3 => refine and_self_iff.2 <| .base <| .bvar h1 h2 ih3.1 + | symm _ ih => exact ih.symm + | trans _ _ ih1 ih2 | proofIrrel _ _ _ _ ih1 ih2 => exact ⟨ih1.1, ih2.2⟩ + | sortDF h1 h2 h3 => exact ⟨.base <| .sort' h1 h1 rfl, .base <| .sort' h2 h1 h3.symm⟩ + | constDF h1 h2 h3 h4 h5 h6 h7 h8 ih1 ih2 => + exact ⟨.base <| .const h1 h2 h4 h6 ih1.1 ih2.1, + .defeq h6 h8.symm ih2.2 ih2.1 <| .base <| + .const h1 h3 (h5.length_eq.symm.trans h4) h6 ih1.2 ih2.2⟩ + | appDF h1 h2 h3 h4 h5 h6 h7 ih1 ih2 ih3 ih4 ih5 => + have := HasTypeStrong.base <| .forallE h1 h2 ih1.1 ih2.1 + exact ⟨.base <| .app h1 h2 ih1.1 ih2.1 this ih3.1 ih4.1 ih5.1, + .defeq h2 h7.symm ih5.2 ih5.1 <| .base <| .app h1 h2 ih1.2 ih2.2 this ih3.2 ih4.2 ih5.2⟩ + | lamDF h1 h2 h3 h4 h5 h6 h7 ih1 ih2 ih3 ih4 ih5 => + refine ⟨.base <| .lam h1 h2 ih1.1 ih2.1 ih4.1 ?a, + .defeq (by exact ⟨h1, h2⟩) (.symm <| .forallEDF h1 h2 h3 h4 h5) ?b ?a ?_⟩ + · exact .base <| .forallE h1 h2 ih1.1 ih2.1 + · exact .base <| .forallE h1 h2 ih1.2 ih3.1 + · exact .base <| .lam h1 h2 ih1.2 ih3.1 ih5.2 ?b + | forallEDF h1 h2 h3 h4 h5 ih1 ih2 ih3 => + exact ⟨.base <| .forallE h1 h2 ih1.1 ih2.1, .base <| .forallE h1 h2 ih1.2 ih3.2⟩ + | defeqDF h1 h2 h3 ih1 ih2 => + exact ⟨.defeq h1 h2 ih1.1 ih1.2 ih2.1, .defeq h1 h2 ih1.1 ih1.2 ih2.2⟩ + | beta h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + have := HasTypeStrong.base <| .forallE h1 h2 ih1.1 ih2.1 + refine ⟨.base <| .app h1 h2 ih1.1 ih2.1 this ?_ ih4.1 ih5.1, ih6.1⟩ + refine .base <| .lam h1 h2 ih1.1 ih2.1 ih3.1 ?_ + exact .base <| .forallE h1 h2 ih1.1 ih2.1 + | @eta Γ A u B v e h1 h2 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 => + refine have a1 := .base <| .forallE h1 h2 ih6.1 ih3.1 + have := ih6.1.app h1 h2 ih3.1 a1 ih5.1 (.base <| .bvar .zero h1 ih6.1); ?_ + rw [instN_bvar0] at this; specialize this ih2.1 + refine ⟨.base <| .lam h1 h2 ih1.1 ih2.1 (.base this) ?_, ih4.1⟩ + exact .base <| .forallE h1 h2 ih1.1 ih2.1 + | structEta _ _ _ _ _ _ _ _ _ _ ihMajor ihRebuild => + exact ⟨ihRebuild.1, ihMajor.1⟩ + | extra h1 h2 h3 h4 h5 h6 h7 _ _ _ _ _ ih4 ih5 => exact ⟨ih4.1, ih5.1⟩ + +theorem HasTypeStrong.refl {env : VEnv} + (H : env.HasTypeStrong U Γ e A b) : env.IsDefEqStrong U Γ e e A := by + induction H with + | bvar h1 h2 _ ih1 => refine .bvar h1 h2 ih1 + | sort' h1 h2 h3 => + refine .defeqDF ?_ (.sortDF ?_ ?_ (VLevel.succ_congr h3)) (.sortDF h1 h1 rfl) <;> assumption + | const h1 h2 h3 h4 h5 h6 ih1 ih2 => + exact .constDF h1 h2 h2 h3 (.rfl fun _ _ => rfl) h4 ih1 ih2 + | app h1 h2 h3 h4 _ h5 h6 h7 ih1 ih2 _ ih3 ih4 ih5 => + exact .appDF h1 h2 ih1 ih2 ih3 ih4 ih5 + | lam h1 h2 h3 h4 h5 _ ih1 ih2 ih3 => + exact .lamDF h1 h2 ih1 ih2 ih2 ih3 ih3 + | forallE h1 h2 h3 h4 ih1 ih2 => + exact .forallEDF h1 h2 ih1 ih2 ih2 + | base _ ih => exact ih + | defeq h1 h2 h3 h4 h5 ih1 ih2 ih3 => exact .defeqDF h1 h2 ih3 + +theorem HasTypeStrong.hasType {env : VEnv} + (H : env.HasTypeStrong U Γ e A b) : env.HasType U Γ e A := H.refl.defeq.hasType.1 + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem HasType.app_inv (H : env.HasType U Γ (.app f a) V) : + ∃ A B, env.HasType U Γ f (.forallE A B) ∧ env.HasType U Γ a A := by + replace H := (H.strong henv hΓ).hasType'.1 + generalize eq : true = b, eq' : f.app a = e' at H + induction H with cases eq + | defeq _ _ _ _ _ _ _ ih => exact ih hΓ rfl eq' + | base H => + subst eq'; let .app _ _ _ _ _ h1 h2 _ := H; exact ⟨_, _, h1.hasType, h2.hasType⟩ + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem _root_.Ix.Theory.Named.VExpr.WF.app_inv (H : VExpr.WF env U Γ (.app f a)) : + ∃ A B, env.HasType U Γ f (.forallE A B) ∧ env.HasType U Γ a A := + let ⟨_, H⟩ := H; HasType.app_inv henv hΓ H + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem HasType.lam_inv (H : env.HasType U Γ (.lam A body) V) : + env.IsType U Γ A ∧ body.WF env U (A::Γ) := by + replace H := (H.strong henv hΓ).hasType'.1 + generalize eq : true = b, eq' : A.lam body = e' at H + induction H with cases eq + | defeq _ _ _ _ _ _ _ ih => exact ih hΓ rfl eq' + | base H => subst eq'; let .lam _ _ h1 _ h2 _ := H; exact ⟨⟨_, h1.hasType⟩, _, h2.hasType⟩ + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem _root_.Ix.Theory.Named.VExpr.WF.lam_inv (H : VExpr.WF env U Γ (.lam A body)) : + env.IsType U Γ A ∧ body.WF env U (A::Γ) := + let ⟨_, H⟩ := H; HasType.lam_inv henv hΓ H + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem HasType.const_inv (H : env.HasType U Γ (.const c ls) V) : + ∃ ci, env.constants c = some ci ∧ (∀ l ∈ ls, l.WF U) ∧ ls.length = ci.uvars := by + replace H := (H.strong henv hΓ).hasType'.1 + generalize eq : true = b, eq' : VExpr.const c ls = e' at H + induction H with cases eq + | defeq _ _ _ _ _ _ _ ih => exact ih hΓ rfl eq' + | base H => subst eq'; let .const h1 h2 h3 .. := H; exact ⟨_, h1, h2, h3⟩ + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem _root_.Ix.Theory.Named.VExpr.WF.const_inv (H : VExpr.WF env U Γ (.const c ls)) : + ∃ ci, env.constants c = some ci ∧ (∀ l ∈ ls, l.WF U) ∧ ls.length = ci.uvars := + let ⟨_, H⟩ := H; HasType.const_inv henv hΓ H + +variable! (henv : Ordered env) (hΓ : OnCtx Γ (env.IsType U)) in +theorem HasType.bvar_inv (H : env.HasType U Γ (.bvar i) V) : ∃ A, Lookup Γ i A := by + replace H := (H.strong henv hΓ).hasType'.1 + generalize eq : true = b, eq' : VExpr.bvar i = e' at H + induction H with cases eq + | defeq _ _ _ _ _ _ _ ih => exact ih hΓ rfl eq' + | base H => subst eq'; let .bvar h1 .. := H; exact ⟨_, h1⟩ + +set_option hygiene false +local notation:65 Γ " ⊢ " e " : " A:36 => HasType env U Γ e A +local notation:65 Γ " ⊢ " e1 " ≡ " e2 " : " A:36 => IsDefEq env U Γ e1 e2 A +section +local notation:65 Γ " ⊢ " e " : " A " !! " n:30 => HasTypeStratified Γ e A true n +local notation:65 Γ " ⊢ " e " :! " A " !! " n:30 => HasTypeStratified Γ e A false n + +variable (env : VEnv) (U : Nat) in +inductive HasTypeStratified : List VExpr → VExpr → VExpr → Bool → Nat → Prop where + | bvar : Lookup Γ i A → Γ ⊢ A : .sort u !! n → Γ ⊢ .bvar i :! A !! n+1 + | sort' : l.WF U → l'.WF U → l ≈ l' → Γ ⊢ .sort l :! .sort (.succ l') !! n + | const : + env.constants c = some ci → + (∀ l ∈ ls, l.WF U) → + ls.length = ci.uvars → + Γ ⊢ ci.type.instL ls : .sort u !! n → + Γ ⊢ .const c ls :! ci.type.instL ls !! n+1 + | app : + u.WF U → v.WF U → + Γ ⊢ A : .sort u !! n → + A::Γ ⊢ B : .sort v !! n → + Γ ⊢ f : .forallE A B !! n → + Γ ⊢ a : A !! n → + Γ ⊢ B.inst a : .sort v !! n → + Γ ⊢ .app f a :! B.inst a !! n+1 + | lam : + Γ ⊢ A : .sort u !! n → + A::Γ ⊢ B : .sort v !! n → + A::Γ ⊢ body : B !! n → + Γ ⊢ .forallE A B : .sort (.imax u v) !! n → + Γ ⊢ .lam A body :! .forallE A B !! n+1 + | forallE : + u.WF U → v.WF U → + Γ ⊢ A : .sort u !! n → + A::Γ ⊢ body : .sort v !! n → + Γ ⊢ .forallE A body :! .sort (.imax u v) !! n+1 + | base : Γ ⊢ e :! A !! n → Γ ⊢ e : A !! n + | defeq : u.WF U → Γ ⊢ A ≡ B : .sort u → + Γ ⊢ A : .sort u !! n → Γ ⊢ B : .sort u !! n → Γ ⊢ e : A !! n → Γ ⊢ e : B !! n+1 +end + +theorem HasTypeStratified.hasType (H : env.HasTypeStratified U Γ e A b n) : Γ ⊢ e : A := by + induction H with + | bvar h1 h2 ih1 => refine .bvar h1 + | sort' h1 h2 h3 => + exact IsDefEq.defeq (.sortDF (by exact h1) h2 (VLevel.succ_congr h3)) (.sort h1) + | const h1 h2 h3 => exact .const h1 h2 h3 + | app _ _ _ _ _ _ _ _ _ ih3 ih4 => exact .app ih3 ih4 + | lam _ _ _ _ ih1 _ ih3 => exact .lam ih1 ih3 + | forallE _ _ _ _ ih1 ih2 => exact .forallE ih1 ih2 + | base _ ih => exact ih + | defeq _ h2 _ _ _ _ _ ih3 => exact h2.defeq ih3 + +theorem HasTypeStratified.mono (le : m ≤ n) (H : HasTypeStratified env U Γ e A b m) : + env.HasTypeStratified U Γ e A b n := by + induction H generalizing n with try let n+1 := n; replace le := Nat.le_of_succ_le_succ le + | bvar h1 h2 ih1 => exact .bvar h1 (ih1 le) + | sort' h1 h2 h3 => exact .sort' h1 h2 h3 + | const h1 h2 h3 _ ih1 => exact .const h1 h2 h3 (ih1 le) + | app h1 h2 _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 => + exact .app h1 h2 (ih1 le) (ih2 le) (ih3 le) (ih4 le) (ih5 le) + | lam _ _ _ _ ih1 ih2 ih3 ih4 => exact .lam (ih1 le) (ih2 le) (ih3 le) (ih4 le) + | forallE h1 h2 _ _ ih1 ih2 => exact .forallE h1 h2 (ih1 le) (ih2 le) + | base _ ih => exact .base (ih le) + | defeq h1 h2 _ _ _ ih1 ih2 ih3 => exact .defeq h1 h2 (ih1 le) (ih2 le) (ih3 le) + +theorem HasTypeStrong.stratify (H : HasTypeStrong env U Γ e A b) : + ∃ n, HasTypeStratified env U Γ e A b n := by + generalize true = b at H ⊢ + induction H with + | bvar h1 h2 _ ih1 => let ⟨n, ih1⟩ := ih1; exact ⟨_, .bvar h1 ih1⟩ + | sort' h1 h2 h3 => exact ⟨0, .sort' h1 h2 h3⟩ + | const h1 h2 h3 _ _ _ _ ih1 => let ⟨_, ih1⟩ := ih1; exact ⟨_, .const h1 h2 h3 ih1⟩ + | app h1 h2 _ _ _ _ _ _ ih1 ih2 _ ih3 ih4 ih5 => + let ⟨n₁, ih1⟩ := ih1; let ⟨n₂, ih2⟩ := ih2; let ⟨n₃, ih3⟩ := ih3 + let ⟨n₄, ih4⟩ := ih4; let ⟨n₅, ih5⟩ := ih5 + refine ⟨max n₁ (max n₂ (max n₃ (max n₄ n₅))) + 1, + .app h1 h2 (ih1.mono ?_) (ih2.mono ?_) (ih3.mono ?_) (ih4.mono ?_) (ih5.mono ?_)⟩ <;> omega + | lam _ _ _ _ _ _ ih1 ih2 ih3 ih4 => + let ⟨n₁, ih1⟩ := ih1; let ⟨n₂, ih2⟩ := ih2; let ⟨n₃, ih3⟩ := ih3; let ⟨n₄, ih4⟩ := ih4 + refine ⟨max n₁ (max n₂ (max n₃ n₄)) + 1, + .lam (ih1.mono ?_) (ih2.mono ?_) (ih3.mono ?_) (ih4.mono ?_)⟩ <;> omega + | forallE h1 h2 _ _ ih1 ih2 => + let ⟨n₁, ih1⟩ := ih1; let ⟨n₂, ih2⟩ := ih2 + refine ⟨max n₁ n₂ + 1, .forallE h1 h2 (ih1.mono ?_) (ih2.mono ?_)⟩ <;> omega + | base _ ih => let ⟨_, ih⟩ := ih; exact ⟨_, .base ih⟩ + | defeq h1 h2 _ _ _ ih1 ih2 ih3 => + let ⟨n₁, ih1⟩ := ih1; let ⟨n₂, ih2⟩ := ih2; let ⟨n₃, ih3⟩ := ih3 + refine ⟨max n₁ (max n₂ n₃) + 1, + .defeq h1 h2.defeq (ih1.mono ?_) (ih2.mono ?_) (ih3.mono ?_)⟩ <;> omega + +theorem HasTypeStratified.to_core (H : HasTypeStratified env U Γ e A true n) : + ∃ A', HasTypeStratified env U Γ e A' false n := by + generalize hb : true = b at H + induction H with cases hb + | base h _ => exact ⟨_, h⟩ + | defeq _ _ _ _ _ _ _ ih3 => obtain ⟨A', hA'⟩ := ih3 rfl; exact ⟨A', hA'.mono (Nat.le_succ _)⟩ + +theorem HasTypeStratified.isType (H : HasTypeStratified env U Γ e A b n) : + ∃ u, HasTypeStratified env U Γ A (.sort u) true (n - 1) := by + induction H with + | base _ ih => exact ih + | bvar _ h | const _ _ _ h | app _ _ _ _ _ _ h | lam _ _ _ h | defeq _ _ _ h => exact ⟨_, h⟩ + | @sort' _ l _ _ _ h _ => exact ⟨_, .base (.sort' (l := l.succ) (l' := l.succ) h h rfl)⟩ + | @forallE _ _ u _ _ v h1 h2 => + exact ⟨_, .base (.sort' (l := .imax u v) (l' := .imax u v) ⟨h1, h2⟩ ⟨h1, h2⟩ rfl)⟩ diff --git a/Ix/Theory/Named/Typing/UniqueTyping.lean b/Ix/Theory/Named/Typing/UniqueTyping.lean new file mode 100644 index 000000000..66579ab3b --- /dev/null +++ b/Ix/Theory/Named/Typing/UniqueTyping.lean @@ -0,0 +1,377 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.Injectivity +import Ix.Theory.Named.Typing.Pattern + +open Ix.Theory (VLevel) + +/-! # Unique typing and its consequences. -/ + +namespace Ix.Theory.Named +namespace VEnv + +variable {env : VEnv} {U : Nat} +local notation:65 Γ " ⊢ " e " : " A:36 => HasType env U Γ e A +local notation:65 Γ " ⊢ " e1 " ≡ " e2 " : " A:36 => IsDefEq env U Γ e1 e2 A + +theorem IsDefEq.uniq (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : Γ ⊢ e₁ ≡ e₂ : A) (h2 : Γ ⊢ e₂ ≡ e₃ : B) : ∃ u, Γ ⊢ A ≡ B : .sort u := by + suffices ∀ {e A B b n₁ n₂ n}, n₁ ≤ n → n₂ ≤ n → + env.HasTypeStratified U Γ e A b n₁ → env.HasTypeStratified U Γ e B b n₂ → + ∃ u, Γ ⊢ A ≡ B : .sort u ∧ ∃ v, u ≈ v ∧ + env.HasTypeStratified U Γ A (.sort u) true (n-1) ∧ + env.HasTypeStratified U Γ B (.sort v) true (n-1) from + let ⟨n₁, h1⟩ := (h1.strong henv hΓ).hasType'.2.stratify + let ⟨n₂, h2⟩ := (h2.strong henv hΓ).hasType'.1.stratify + have ⟨_, h, _⟩ := this (Nat.le_max_left ..) (Nat.le_max_right ..) h1 h2 + ⟨_, h⟩ + clear h1 h2; intro e A B b n₁ n₂ n le₁ le₂ H1 + induction n using WellFounded.induction Nat.lt_wfRel.2 + generalizing n₁ n₂ Γ e A B b with | _ n IH + induction H1 generalizing B n₂ n with + | bvar a1 a2 => + intro (.bvar b1 b2); cases a1.uniq b1 + exact ⟨_, b2.hasType, _, rfl, b2.mono (by omega), b2.mono (by omega)⟩ + | sort' a1 a2 a3 => + intro (.sort' b1 b2 b3) + have := VLevel.succ_congr (b3.symm.trans a3) + exact ⟨_, .symm <| .sortDF b2 a2 this, _, VLevel.succ_congr this, + .base <| .sort' a2 b2 this.symm, .base <| .sort' b2 a2 this⟩ + | const a1 a2 a3 a4 => + intro (.const b1 b2 b3 b4); cases a1.symm.trans b1 + replace le₁ := Nat.sub_le_sub_right le₁ 1 + exact ⟨_, a4.hasType, _, rfl, a4.mono le₁, a4.mono le₁⟩ + | app _ a2 a3 a4 _ a6 a7 _ _ ih3 => + intro (.app _ _ b3 b4 b5 _ b7) + have ⟨_, c1, _, _, c3, c4⟩ := ih3 n IH hΓ (Nat.le_of_succ_le le₁) (Nat.le_of_succ_le le₂) b5 + have ⟨_, _, d3, d4, d5⟩ := IsDefEqU.forallE_inv_stratified henv hΓ ⟨_, c1⟩ c3 c4 + let n+1 := n + replace le₁ := Nat.le_of_succ_le_succ le₁ + replace le₂ := Nat.le_of_succ_le_succ le₂ + have e1 := have ⟨_, h⟩ := a3.hasType.isType henv hΓ; h.sort_inv henv + refine have hΓ₁ := ⟨hΓ, _, a3.hasType⟩ + have ⟨_, h, _⟩ := IH _ (Nat.lt_succ_self _) hΓ₁ le₁ (Nat.le_refl _) a4 d4; ?_ + have e3 := IsDefEqU.sort_inv henv hΓ₁ ⟨_, h⟩ + have e4 := have ⟨_, h⟩ := d4.hasType.isType henv hΓ₁; h.sort_inv henv + refine have hΓ₂ := ⟨hΓ, _, b3.hasType⟩ + have ⟨_, h, _⟩ := IH _ (Nat.lt_succ_self _) hΓ₂ le₂ (Nat.le_refl _) b4 d5; ?_ + have e5 := IsDefEqU.sort_inv henv hΓ₂ ⟨_, h⟩ + exact ⟨_, .defeqDF (.sortDF e4 a2 e3.symm) (d3.instN henv a6.hasType .zero), _, + e3.trans e5.symm, a7.mono le₁, b7.mono le₂⟩ + | lam a1 a2 _ a4 _ _ ih3 => + intro (.lam b1 b2 b3 b4) + have ⟨_, c1, _, c2, c3, c4⟩ := ih3 n IH ⟨hΓ, _, a1.hasType⟩ + (Nat.le_of_succ_le le₁) (Nat.le_of_succ_le le₂) b3 + let n+1 := n + replace le₁ := Nat.le_of_succ_le_succ le₁ + replace le₂ := Nat.le_of_succ_le_succ le₂ + have ⟨_, h, _⟩ := IH _ (Nat.lt_succ_self _) hΓ le₁ le₂ a1 b1 + have e1 := IsDefEqU.sort_inv henv hΓ ⟨_, h⟩ + refine have hΓ' := ⟨hΓ, _, a1.hasType⟩ + have ⟨_, h, _⟩ := IH _ (Nat.lt_succ_self _) hΓ' le₁ (Nat.le_refl _) a2 c3; ?_ + have f1 := h.sort_inv_l henv; have f2 := h.sort_inv_r henv + have e2 := IsDefEqU.sort_inv henv hΓ' ⟨_, h⟩ + have ⟨_, h, _⟩ := IH _ (Nat.lt_succ_self _) hΓ' le₂ (Nat.le_refl _) b2 c4 + have e3 := IsDefEqU.sort_inv henv hΓ' ⟨_, h⟩ + exact ⟨_, .forallEDF a1.hasType (.defeqDF (.symm <| .sortDF f1 f2 e2) c1), + _, VLevel.imax_congr e1 (e2.trans <| c2.trans e3.symm), a4.mono le₁, b4.mono le₂⟩ + | forallE a1 a2 a3 a4 => + intro (.forallE b1 b2 b3 b4) + let n+1 := n + replace le₁ := Nat.le_of_succ_le_succ le₁ + replace le₂ := Nat.le_of_succ_le_succ le₂ + have ⟨_, h, _⟩ := IH _ (Nat.lt_succ_self _) hΓ le₁ le₂ a3 b3 + have e1 := IsDefEqU.sort_inv henv hΓ ⟨_, h⟩ + refine have hΓ' := ⟨hΓ, _, a3.hasType⟩ + have ⟨_, h, _⟩ := IH _ (Nat.lt_succ_self _) hΓ' le₁ le₂ a4 b4; ?_ + have e2 := IsDefEqU.sort_inv henv hΓ' ⟨_, h⟩ + have := VLevel.imax_congr e1 e2 + exact ⟨_, .sortDF ⟨a1, a2⟩ ⟨b1, b2⟩ this, _, rfl, + .base <| .sort' ⟨a1, a2⟩ ⟨a1, a2⟩ rfl, .base <| .sort' ⟨b1, b2⟩ ⟨a1, a2⟩ this.symm⟩ + | @base Γ e A n₁ a1 ih => + intro H2 + replace ih {n'} le := @ih n' (fun y h1 => IH y (Nat.lt_of_lt_of_le h1 le)) hΓ + generalize eq : true = b at H2 + induction H2 with cases eq + | @base _ _ _ n' b1 => exact ih (Nat.le_refl _) le₁ le₂ b1 + | @defeq Γ B' B u n' _ b1 b2 b3 b4 b5 _ _ ih' => + have ⟨u₁, c1, u₂, c2, c3, c4⟩ := ih' a1 hΓ (Nat.le_of_succ_le le₂) ih rfl + let n+1 := n + replace le₂ := Nat.le_of_succ_le_succ le₂ + have ⟨v₁, d1, v₂, _⟩ := IH _ (Nat.lt_succ_self _) hΓ le₂ (Nat.le_refl _) b3 c4 + have e1 := IsDefEqU.sort_inv henv hΓ ⟨_, d1⟩ + have e2 := have ⟨_, h⟩ := c3.hasType.isType henv hΓ; h.sort_inv henv + have eq : u₁ ≈ u := c2.trans e1.symm + exact ⟨_, c1.trans (.defeqDF (.symm <| .sortDF e2 b1 eq) b2), _, eq, c3, b4.mono le₂⟩ + | @defeq Γ A' A u n' _ a1 a2 a3 a4 a5 ih1 ih2 ih' => + intro H2 + have ⟨_, c1, u₂, c2, c3, c4⟩ := ih' _ IH hΓ (Nat.le_of_succ_le le₁) le₂ H2 + let n+1 := n + replace le₁ := Nat.le_of_succ_le_succ le₁ + have ⟨_, d1, _, _⟩ := IH _ (Nat.lt_succ_self _) hΓ le₁ (Nat.le_refl _) a3 c3 + have e1 := IsDefEqU.sort_inv henv hΓ ⟨_, d1⟩ + have e2 := have ⟨_, h⟩ := c3.hasType.isType henv hΓ; h.sort_inv henv + have eq : u ≈ u₂ := e1.trans c2 + exact ⟨_, a2.symm.trans (.defeqDF (.symm <| .sortDF a1 e2 e1) c1), _, eq, a4.mono le₁, c4⟩ + +theorem IsDefEq.uniqU (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEq U Γ e₁ e₂ A) (h2 : env.IsDefEq U Γ e₂ e₃ B) : + env.IsDefEqU U Γ A B := let ⟨_, h⟩ := h1.uniq henv hΓ h2; ⟨_, h⟩ + +theorem isDefEq_iff (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) : + env.IsDefEq U Γ e₁ e₂ A ↔ + env.HasType U Γ e₁ A ∧ env.HasType U Γ e₂ A ∧ env.IsDefEqU U Γ e₁ e₂ := by + refine ⟨fun h => ⟨h.hasType.1, h.hasType.2, _, h⟩, fun ⟨_, h2, _, h3⟩ => ?_⟩ + have ⟨_, h⟩ := h3.uniq henv hΓ h2 + exact h.defeqDF h3 + +theorem IsDefEq.trans_r (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h₁ : env.IsDefEq U Γ e₁ e₂ A) (h₂ : env.IsDefEq U Γ e₂ e₃ B) : + env.IsDefEq U Γ e₁ e₃ B := have ⟨_, h⟩ := h₁.uniq henv hΓ h₂; .trans (.defeqDF h h₁) h₂ + +theorem IsDefEq.trans_l (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h₁ : env.IsDefEq U Γ e₁ e₂ A) (h₂ : env.IsDefEq U Γ e₂ e₃ B) : + env.IsDefEq U Γ e₁ e₃ A := have ⟨_, h⟩ := h₁.uniq henv hΓ h₂; h₁.trans (.defeqDF (.symm h) h₂) + +theorem IsDefEq.transU_r (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h₁ : env.IsDefEqU U Γ e₁ e₂) (h₂ : env.IsDefEq U Γ e₂ e₃ A) : + env.IsDefEq U Γ e₁ e₃ A := have ⟨_, h₁⟩ := h₁; .trans_r henv hΓ h₁ h₂ + +theorem IsDefEq.transU_l (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h₁ : env.IsDefEq U Γ e₁ e₂ A) (h₂ : env.IsDefEqU U Γ e₂ e₃) : + env.IsDefEq U Γ e₁ e₃ A := have ⟨_, h₂⟩ := h₂; .trans_l henv hΓ h₁ h₂ + +theorem IsDefEqU.defeqDF (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h₁ : env.IsDefEqU U Γ A B) (h₂ : env.IsDefEq U Γ e₁ e₂ A) : + env.IsDefEq U Γ e₁ e₂ B := by + have ⟨_, h₁⟩ := h₁ + have ⟨_, hA⟩ := h₂.isType henv hΓ + exact .defeqDF (hA.trans_l henv hΓ h₁) h₂ + +theorem IsDefEqU.of_l (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ e₁ e₂) (h2 : env.HasType U Γ e₁ A) : + env.IsDefEq U Γ e₁ e₂ A := let ⟨_, h⟩ := h1; h2.trans_l henv hΓ h + +theorem HasType.defeqU_l (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ e₁ e₂) (h2 : env.HasType U Γ e₁ A) : + env.HasType U Γ e₂ A := (h1.of_l henv hΓ h2).hasType.2 + +theorem IsType.defeqU_l (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ A₁ A₂) (h2 : env.IsType U Γ A₁) : + env.IsType U Γ A₂ := h2.imp fun _ h2 => h2.defeqU_l henv hΓ h1 + +theorem IsDefEqU.of_r (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ e₁ e₂) (h2 : env.HasType U Γ e₂ A) : + env.IsDefEq U Γ e₁ e₂ A := (h1.symm.of_l henv hΓ h2).symm + +theorem HasType.defeqU_r (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ A₁ A₂) (h2 : env.HasType U Γ e A₁) : + env.HasType U Γ e A₂ := h1.defeqDF henv hΓ h2 + +theorem IsDefEqU.trans (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (h1 : env.IsDefEqU U Γ e₁ e₂) (h2 : env.IsDefEqU U Γ e₂ e₃) : + env.IsDefEqU U Γ e₁ e₃ := h1.imp fun _ h1 => let ⟨_, h2⟩ := h2; h1.trans_l henv hΓ h2 + +set_option warn.sorry false in +variable! (henv : VEnv.WF env) (hΓ : OnCtx Γ' (env.IsType U)) in +theorem IsDefEqU.weakN_iff (W : Ctx.LiftN n k Γ Γ') : + env.IsDefEqU U Γ' (e1.liftN n k) (e2.liftN n k) ↔ env.IsDefEqU U Γ e1 e2 := by + refine ⟨fun h => have := henv; have := hΓ; sorry, fun h => h.weakN henv W⟩ + +variable! (henv : VEnv.WF env) (hΓ : OnCtx Γ' (env.IsType U)) in +theorem _root_.Ix.Theory.Named.VExpr.WF.weakN_iff (W : Ctx.LiftN n k Γ Γ') : + VExpr.WF env U Γ' (e.liftN n k) ↔ VExpr.WF env U Γ e := IsDefEqU.weakN_iff henv hΓ W + +theorem IsDefEq.skips (henv : VEnv.WF env) (hΓ : OnCtx Γ' (env.IsType U)) + (W : Ctx.LiftN n k Γ Γ') + (H : env.IsDefEq U Γ' e₁ e₂ A) (h1 : e₁.Skips n k) (h2 : e₂.Skips n k) : + ∃ B, env.IsDefEq U Γ' e₁ e₂ B ∧ B.Skips n k := by + obtain ⟨e₁, rfl⟩ := VExpr.skips_iff_exists.1 h1 + obtain ⟨e₂, rfl⟩ := VExpr.skips_iff_exists.1 h2 + have ⟨_, H⟩ := (IsDefEqU.weakN_iff henv hΓ W).1 ⟨_, H⟩ + exact ⟨_, H.weakN henv W, .liftN⟩ + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) (hΓ : OnCtx Γ (env.IsType U)) in +theorem IsDefEq.weakN_iff' (W : Ctx.LiftN n k Γ Γ') : + env.IsDefEq U Γ' (e1.liftN n k) (e2.liftN n k) (A.liftN n k) ↔ env.IsDefEq U Γ e1 e2 A := by + refine ⟨fun h => ?_, fun h => h.weakN henv W⟩ + have ⟨_, H⟩ := (IsDefEqU.weakN_iff henv hΓ' W).1 ⟨_, h⟩ + refine IsDefEqU.defeqDF henv hΓ ?_ H + exact (IsDefEqU.weakN_iff henv hΓ' W).1 <| (H.weakN henv W).uniqU henv hΓ' h.symm + +variable! (henv : VEnv.WF env) in +theorem _root_.Ix.Theory.Named.OnCtx.weakN_inv + (W : Ctx.LiftN n k Γ Γ') (H : OnCtx Γ' (env.IsType U)) : OnCtx Γ (env.IsType U) := by + induction W with + | zero As h => + clear h + induction As with + | nil => exact H + | cons A As ih => exact ih H.1 + | succ W ih => + let ⟨H1, _, H2⟩ := H + exact ⟨ih H1, _, (IsDefEq.weakN_iff' henv H1 (ih H1) W).1 H2⟩ + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem IsDefEq.weakN_iff (W : Ctx.LiftN n k Γ Γ') : + env.IsDefEq U Γ' (e1.liftN n k) (e2.liftN n k) (A.liftN n k) ↔ env.IsDefEq U Γ e1 e2 A := + IsDefEq.weakN_iff' henv hΓ' (hΓ'.weakN_inv henv W) W + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem HasType.weakN_iff (W : Ctx.LiftN n k Γ Γ') : + env.HasType U Γ' (e.liftN n k) (A.liftN n k) ↔ env.HasType U Γ e A := + IsDefEq.weakN_iff henv hΓ' W + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem IsType.weakN_iff (W : Ctx.LiftN n k Γ Γ') : + env.IsType U Γ' (A.liftN n k) ↔ env.IsType U Γ A := + exists_congr fun _ => HasType.weakN_iff henv hΓ' W (A := .sort _) + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem HasType.skips (W : Ctx.LiftN n k Γ Γ') + (h1 : env.HasType U Γ' e A) (h2 : e.Skips n k) : ∃ B, env.HasType U Γ' e B ∧ B.Skips n k := + IsDefEq.skips henv hΓ' W h1 h2 h2 + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem IsDefEqU.weak'_iff (W : Ctx.Lift' l Γ Γ') : + env.IsDefEqU U Γ' (e1.lift' l) (e2.lift' l) ↔ env.IsDefEqU U Γ e1 e2 := by + generalize e : l.depth = n + induction n generalizing l Γ' with + | zero => simp [VExpr.lift'_depth_zero e, W.depth_zero e] + | succ n ih => + obtain ⟨l, k, rfl, rfl⟩ := Lift.depth_succ e + have ⟨Γ₁, W1, W2⟩ := W.of_cons_skip + rw [Lift.consN_skip_eq, VExpr.lift'_comp, VExpr.lift'_comp, + ← Lift.skipN_one, VExpr.lift'_consN_skipN, VExpr.lift'_consN_skipN, + weakN_iff henv hΓ' W2, ih (hΓ'.weakN_inv henv W2) W1 Lift.depth_consN] + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem IsDefEq.weak'_iff (W : Ctx.Lift' l Γ Γ') : + env.IsDefEq U Γ' (e1.lift' l) (e2.lift' l) (A.lift' l) ↔ env.IsDefEq U Γ e1 e2 A := by + generalize e : l.depth = n + induction n generalizing l Γ' with + | zero => simp [VExpr.lift'_depth_zero e, W.depth_zero e] + | succ n ih => + obtain ⟨l, k, rfl, rfl⟩ := Lift.depth_succ e + have ⟨Γ₁, W1, W2⟩ := W.of_cons_skip + rw [Lift.consN_skip_eq, VExpr.lift'_comp, VExpr.lift'_comp, VExpr.lift'_comp, + ← Lift.skipN_one, VExpr.lift'_consN_skipN, VExpr.lift'_consN_skipN, VExpr.lift'_consN_skipN, + weakN_iff henv hΓ' W2, ih (hΓ'.weakN_inv henv W2) W1 Lift.depth_consN] + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem HasType.weak'_iff (W : Ctx.Lift' l Γ Γ') : + env.HasType U Γ' (e.lift' l) (A.lift' l) ↔ env.HasType U Γ e A := + IsDefEq.weak'_iff henv hΓ' W + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem IsType.weak'_iff (W : Ctx.Lift' l Γ Γ') : + env.IsType U Γ' (e.lift' l) ↔ env.IsType U Γ e := + exists_congr fun _ => HasType.weak'_iff henv hΓ' W (A := .sort _) + +variable! (henv : VEnv.WF env) (hΓ : OnCtx Γ' (env.IsType U)) in +theorem _root_.Ix.Theory.Named.VExpr.WF.weak'_iff (W : Ctx.Lift' l Γ Γ') : + VExpr.WF env U Γ' (e.lift' l) ↔ VExpr.WF env U Γ e := IsDefEqU.weak'_iff henv hΓ W + +/-! ### Application-spine weakening and inversion -/ + +/-- General context weakening for an application spine. -/ +theorem SpineWF.weak' {env : VEnv} (henv : env.Ordered) + {U : Nat} {lift : Lift} {Γ Γ' : List VExpr} + (W : Ctx.Lift' lift Γ Γ') : + ∀ {es : List VExpr} {A B : VExpr}, env.SpineWF U Γ A es B → + env.SpineWF U Γ' (A.lift' lift) + (es.map fun e => e.lift' lift) (B.lift' lift) := by + intro es + induction es with + | nil => + intro A B h + cases h + exact .nil + | cons e es ih => + intro A B h + obtain ⟨A₁, A₂, rfl, he, hrest⟩ := h.cons_inv + refine .cons (he.weak' henv W) ?_ + have weakened := ih hrest + rwa [VExpr.lift'_inst_hi] at weakened + +/-- Invert weakening of every component of an application-spine judgment +when the enlarged context is well formed. -/ +theorem SpineWF.weakN_inv {env : VEnv} {U n k : Nat} {Γ Γ' : List VExpr} + (henv : env.WF) (hΓ' : OnCtx Γ' (env.IsType U)) + (W : Ctx.LiftN n k Γ Γ') : + ∀ {es : List VExpr} {A B : VExpr}, + env.SpineWF U Γ' (A.liftN n k) + (es.map fun e => e.liftN n k) (B.liftN n k) → + env.SpineWF U Γ A es B := by + intro es + induction es with + | nil => + intro A B h + have hab := VExpr.liftN_inj.1 h.nil_inv + subst B + exact .nil + | cons e es ih => + intro A B h + obtain ⟨A₁', A₂', sourceEq, he, hrest⟩ := h.cons_inv + cases A with + | bvar index => cases sourceEq + | sort level => cases sourceEq + | const name levels => cases sourceEq + | app fn argument => cases sourceEq + | lam domain body => cases sourceEq + | forallE A₁ A₂ => + injection sourceEq with domainEq bodyEq + subst A₁' + subst A₂' + refine .cons ((HasType.weakN_iff henv hΓ' W).1 he) ?_ + rw [← VExpr.liftN_inst_hi] at hrest + exact ih hrest + +/-- Invert a general context lift componentwise across an application-spine +judgment. -/ +theorem SpineWF.weak'_inv {env : VEnv} {U : Nat} {lift : Lift} + {Γ Γ' : List VExpr} + (henv : env.WF) (hΓ' : OnCtx Γ' (env.IsType U)) + (W : Ctx.Lift' lift Γ Γ') : + ∀ {es : List VExpr} {A B : VExpr}, + env.SpineWF U Γ' (A.lift' lift) + (es.map fun e => e.lift' lift) (B.lift' lift) → + env.SpineWF U Γ A es B := by + intro es + induction es with + | nil => + intro A B h + have hab := VExpr.lift'_inj.1 h.nil_inv + subst B + exact .nil + | cons e es ih => + intro A B h + obtain ⟨A₁', A₂', sourceEq, he, hrest⟩ := h.cons_inv + cases A with + | bvar index => cases sourceEq + | sort level => cases sourceEq + | const name levels => cases sourceEq + | app fn argument => cases sourceEq + | lam domain body => cases sourceEq + | forallE A₁ A₂ => + injection sourceEq with domainEq bodyEq + subst A₁' + subst A₂' + refine .cons ((HasType.weak'_iff henv hΓ' W).1 he) ?_ + rw [← VExpr.lift'_inst_hi] at hrest + exact ih hrest + +variable! (henv : VEnv.WF env) in +theorem _root_.Ix.Theory.Named.OnCtx.weak'_inv + (W : Ctx.Lift' ρ Γ Γ') (H : OnCtx Γ' (env.IsType U)) : OnCtx Γ (env.IsType U) := by + generalize e : ρ.depth = n + induction n generalizing ρ Γ' with + | zero => simp [W.depth_zero e, H] + | succ n ih => + obtain ⟨l, k, rfl, rfl⟩ := Lift.depth_succ e + have ⟨Γ₁, W1, W2⟩ := W.of_cons_skip + exact ih W1 (.weakN_inv henv W2 H) (by simp) diff --git a/Ix/Theory/Named/VDecl.lean b/Ix/Theory/Named/VDecl.lean new file mode 100644 index 000000000..f18cb5ff9 --- /dev/null +++ b/Ix/Theory/Named/VDecl.lean @@ -0,0 +1,37 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.VEnv + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +structure VConstVal extends VConstant where + name : Name + +structure VDefVal extends VConstVal where + value : VExpr + +def VDefVal.toDefEq (v : VDefVal) : VDefEq := + ⟨v.uvars, .const v.name (VLevel.params v.uvars), v.value, v.type⟩ + +structure VInductiveType extends VConstVal where + ctors : List VConstVal + +structure VInductDecl where + uvars : Nat + nparams : Nat + types : List VInductiveType + +inductive VDecl where + | axiom (_ : VConstVal) + | def (_ : VDefVal) + | opaque (_ : VDefVal) + | example (_ : VDefVal) + | quot + | induct (_ : VInductDecl) + | mutualDef (_ : List VDefVal) diff --git a/Ix/Theory/Named/VEnv.lean b/Ix/Theory/Named/VEnv.lean new file mode 100644 index 000000000..2bcff284c --- /dev/null +++ b/Ix/Theory/Named/VEnv.lean @@ -0,0 +1,214 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.VExpr + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +structure VConstant where + uvars : Nat + type : VExpr + +structure VDefEq where + uvars : Nat + lhs : VExpr + rhs : VExpr + type : VExpr + +/-- Syntax of one registered nonrecursive-structure eta rule. + +The projector family is fixed by the checked structure artifact. Its three +naturality fields are syntactic equations, not semantic assumptions; they +are exactly what weakening and substitution need in order to reconstruct the +same registered eta redex. -/ +structure VStructEta where + uvars : Nat + nparams : Nat + nfields : Nat + familyName : Name + familyType : VExpr + constructorName : Name + projectors : List VLevel → List VExpr → List VExpr + projectors_length : ∀ levels params, + levels.length = uvars → params.length = nparams → + (projectors levels params).length = nfields + projectors_liftN : ∀ levels params n k, + params.length = nparams → + (projectors levels params).map (fun projector => + projector.liftN n k) = + projectors levels (params.map fun param => param.liftN n k) + projectors_instN : ∀ levels params a k, + params.length = nparams → + (projectors levels params).map (fun projector => + projector.inst a k) = + projectors levels (params.map fun param => param.inst a k) + projectors_instL : ∀ levels params ls, + (projectors levels params).map (fun projector => + projector.instL ls) = + projectors (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) + +namespace VStructEta + +/-- The instantiated family type governed by a structure-eta descriptor. -/ +def structureType (rule : VStructEta) (levels : List VLevel) + (params : List VExpr) : VExpr := + VExpr.appN (.const rule.familyName levels) params + +/-- Canonical projected fields of one major premise. -/ +def projectionArgs (rule : VStructEta) (levels : List VLevel) + (params : List VExpr) (major : VExpr) : List VExpr := + (rule.projectors levels params).map fun projector => .app projector major + +/-- Constructor reconstruction contracted by the primitive eta rule. -/ +def rebuild (rule : VStructEta) (levels : List VLevel) + (params : List VExpr) (major : VExpr) : VExpr := + VExpr.appN (.const rule.constructorName levels) + (params ++ rule.projectionArgs levels params major) + +@[simp] theorem structureType_liftN (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (n k : Nat) : + (rule.structureType levels params).liftN n k = + rule.structureType levels + (params.map fun param => param.liftN n k) := by + unfold structureType + rw [VExpr.liftN_appN] + rfl + +@[simp] theorem structureType_instN (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (a : VExpr) (k : Nat) : + (rule.structureType levels params).inst a k = + rule.structureType levels + (params.map fun param => param.inst a k) := by + unfold structureType + rw [VExpr.instN_appN] + rfl + +@[simp] theorem structureType_instL (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (ls : List VLevel) : + (rule.structureType levels params).instL ls = + rule.structureType (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) := by + unfold structureType + rw [VExpr.instL_appN] + rfl + +@[simp] theorem projectionArgs_length (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (major : VExpr) + (hlevels : levels.length = rule.uvars) + (hparams : params.length = rule.nparams) : + (rule.projectionArgs levels params major).length = rule.nfields := by + simp [projectionArgs, + rule.projectors_length levels params hlevels hparams] + +@[simp] theorem projectionArgs_liftN (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (major : VExpr) + (hparams : params.length = rule.nparams) (n k : Nat) : + (rule.projectionArgs levels params major).map + (fun arg => arg.liftN n k) = + rule.projectionArgs levels + (params.map fun param => param.liftN n k) (major.liftN n k) := by + simpa [projectionArgs, VExpr.liftN, List.map_map, Function.comp_def] using + congrArg (List.map fun projector => + projector.app (major.liftN n k)) + (rule.projectors_liftN levels params n k hparams) + +@[simp] theorem projectionArgs_instN (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (major a : VExpr) + (hparams : params.length = rule.nparams) (k : Nat) : + (rule.projectionArgs levels params major).map + (fun arg => arg.inst a k) = + rule.projectionArgs levels + (params.map fun param => param.inst a k) (major.inst a k) := by + simpa [projectionArgs, VExpr.inst, List.map_map, Function.comp_def] using + congrArg (List.map fun projector => projector.app (major.inst a k)) + (rule.projectors_instN levels params a k hparams) + +@[simp] theorem projectionArgs_instL (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (major : VExpr) + (ls : List VLevel) : + (rule.projectionArgs levels params major).map + (fun arg => arg.instL ls) = + rule.projectionArgs (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) (major.instL ls) := by + simpa [projectionArgs, VExpr.instL, List.map_map, Function.comp_def] using + congrArg (List.map fun projector => projector.app (major.instL ls)) + (rule.projectors_instL levels params ls) + +@[simp] theorem rebuild_liftN (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (major : VExpr) + (hparams : params.length = rule.nparams) (n k : Nat) : + (rule.rebuild levels params major).liftN n k = + rule.rebuild levels (params.map fun param => param.liftN n k) + (major.liftN n k) := by + unfold rebuild + rw [VExpr.liftN_appN, List.map_append, + rule.projectionArgs_liftN levels params major hparams n k] + rfl + +@[simp] theorem rebuild_instN (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (major a : VExpr) + (hparams : params.length = rule.nparams) (k : Nat) : + (rule.rebuild levels params major).inst a k = + rule.rebuild levels (params.map fun param => param.inst a k) + (major.inst a k) := by + unfold rebuild + rw [VExpr.instN_appN, List.map_append, + rule.projectionArgs_instN levels params major a hparams k] + rfl + +@[simp] theorem rebuild_instL (rule : VStructEta) + (levels : List VLevel) (params : List VExpr) (major : VExpr) + (ls : List VLevel) : + (rule.rebuild levels params major).instL ls = + rule.rebuild (levels.map (VLevel.inst ls)) + (params.map (VExpr.instL ls)) (major.instL ls) := by + unfold rebuild + rw [VExpr.instL_appN, List.map_append, + rule.projectionArgs_instL levels params major ls] + rfl + +end VStructEta + +@[ext] structure VEnv where + constants : Name → Option VConstant + defeqs : VDefEq → Prop + structEtas : VStructEta → Prop + +def VEnv.empty : VEnv where + constants _ := none + defeqs _ := False + structEtas _ := False + +instance : EmptyCollection VEnv := ⟨.empty⟩ + +def VEnv.contains (env : VEnv) (name : Name) := ∃ ci, env.constants name = some ci + +def VEnv.addConst (env : VEnv) (name : Name) (ci : VConstant) : Option VEnv := + match env.constants name with + | some _ => none + | none => some { env with constants := fun n => if name = n then some ci else env.constants n } + +def VEnv.addDefEq (env : VEnv) (df : VDefEq) : VEnv := + { env with defeqs := fun x => x = df ∨ env.defeqs x } + +/-- Register one checked structure-eta descriptor. -/ +def VEnv.addStructEta (env : VEnv) (rule : VStructEta) : VEnv := + { env with structEtas := fun x => x = rule ∨ env.structEtas x } + +structure VEnv.LE (env1 env2 : VEnv) : Prop where + constants : env1.constants n = some a → env2.constants n = some a + defeqs : env1.defeqs df → env2.defeqs df + structEtas : env1.structEtas rule → env2.structEtas rule + +instance : LE VEnv := ⟨VEnv.LE⟩ + +theorem VEnv.LE.rfl {env : VEnv} : env ≤ env := ⟨id, id, id⟩ + +theorem VEnv.LE.trans {a b c : VEnv} (h1 : a ≤ b) (h2 : b ≤ c) : a ≤ c := + ⟨h2.1 ∘ h1.1, h2.2 ∘ h1.2, h2.3 ∘ h1.3⟩ diff --git a/Ix/Theory/Named/VExpr.lean b/Ix/Theory/Named/VExpr.lean new file mode 100644 index 000000000..ad7108342 --- /dev/null +++ b/Ix/Theory/Named/VExpr.lean @@ -0,0 +1,831 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean +import Ix.Theory.Named.VLevel + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Ix.Theory.Named + +inductive VExpr where + | bvar (deBruijnIndex : Nat) + | sort (u : VLevel) + | const (declName : Name) (us : List VLevel) + | app (fn arg : VExpr) + | lam (binderType body : VExpr) + | forallE (binderType body : VExpr) + +instance : Inhabited VExpr := ⟨.sort .zero⟩ + +def liftVar (n i : Nat) (k := 0) : Nat := if i < k then i else n + i + +theorem liftVar_lt (h : i < k) : liftVar n i k = i := if_pos h +theorem liftVar_le (h : k ≤ i) : liftVar n i k = n + i := if_neg (Nat.not_lt.2 h) + +theorem liftVar_base : liftVar n i = n + i := liftVar_le (Nat.zero_le _) +@[simp] theorem liftVar_base' : liftVar n i = i + n := Nat.add_comm .. ▸ liftVar_le (Nat.zero_le _) + +@[simp] theorem liftVar_zero : liftVar n 0 (k+1) = 0 := by simp [liftVar] +@[simp] theorem liftVar_succ : liftVar n (i+1) (k+1) = liftVar n i k + 1 := by + simp [liftVar, Nat.succ_lt_succ_iff]; split <;> simp [Nat.add_assoc] + +theorem liftVar_lt_add (self : i < k) : liftVar n i j < k + n := by + simp [liftVar] + split <;> rename_i h + · exact Nat.lt_of_lt_of_le self (Nat.le_add_right ..) + · rw [Nat.add_comm]; exact Nat.add_lt_add_right self _ + +namespace VExpr + +/-- Iterated application, with arguments ordered from left to right. -/ +def appN (f : VExpr) : List VExpr → VExpr + | [] => f + | a :: as => (f.app a).appN as + +variable (n : Nat) in +def liftN : VExpr → (k :_:= 0) → VExpr + | .bvar i, k => .bvar (liftVar n i k) + | .sort u, _ => .sort u + | .const c us, _ => .const c us + | .app fn arg, k => .app (fn.liftN k) (arg.liftN k) + | .lam ty body, k => .lam (ty.liftN k) (body.liftN (k+1)) + | .forallE ty body, k => .forallE (ty.liftN k) (body.liftN (k+1)) + +abbrev lift := liftN 1 + +@[simp] theorem liftN_zero (e : VExpr) (k : Nat) : liftN 0 e k = e := by + induction e generalizing k <;> simp [liftN, liftVar, *] + +theorem liftN'_liftN' {e : VExpr} {n1 n2 k1 k2 : Nat} (h1 : k1 ≤ k2) (h2 : k2 ≤ n1 + k1) : + liftN n2 (liftN n1 e k1) k2 = liftN (n1+n2) e k1 := by + induction e generalizing k1 k2 with simp [liftN, liftVar, Nat.add_assoc, *] + | bvar i => + split <;> rename_i h + · rw [if_pos (Nat.lt_of_lt_of_le h h1)] + · rw [if_neg (mt (fun h => ?_) h), Nat.add_left_comm] + exact (Nat.add_lt_add_iff_left ..).1 (Nat.lt_of_lt_of_le h h2) + | lam _ _ _ IH2 | forallE _ _ _ IH2 => + rw [IH2 (Nat.succ_le_succ h1) (Nat.succ_le_succ h2)] + +theorem liftN'_liftN_lo (e : VExpr) (n k : Nat) : liftN n (liftN k e) k = liftN (n+k) e := by + simpa [Nat.add_comm] using liftN'_liftN' (n1 := k) (n2 := n) (Nat.zero_le _) (Nat.le_refl _) + +theorem liftN'_liftN_hi (e : VExpr) (n1 n2 k : Nat) : + liftN n2 (liftN n1 e k) k = liftN (n1+n2) e k := + liftN'_liftN' (Nat.le_refl _) (Nat.le_add_left ..) + +theorem liftN_liftN (e : VExpr) (n1 n2 : Nat) : liftN n2 (liftN n1 e) = liftN (n1+n2) e := by + simpa using liftN'_liftN' (Nat.zero_le _) (Nat.zero_le _) + +theorem liftN_succ (e : VExpr) (n : Nat) : liftN (n+1) e = lift (liftN n e) := + (liftN_liftN ..).symm + +theorem liftN'_comm (e : VExpr) (n1 n2 k1 k2 : Nat) (h : k2 ≤ k1) : + liftN n2 (liftN n1 e k1) k2 = liftN n1 (liftN n2 e k2) (n2+k1) := by + induction e generalizing k1 k2 with + simp [liftN, liftVar, Nat.add_assoc, Nat.succ_le_succ, *] + | bvar i => + split <;> rename_i h' + · rw [if_pos (c := _ < n2 + k1)]; split + · exact Nat.lt_add_left _ h' + · exact Nat.add_lt_add_left h' _ + · have := mt (Nat.lt_of_lt_of_le · h) h' + rw [if_neg (mt (Nat.lt_of_le_of_lt (Nat.le_add_left _ n1)) this), + if_neg this, if_neg (mt (Nat.add_lt_add_iff_left ..).1 h'), Nat.add_left_comm] + +theorem lift_liftN' (e : VExpr) (k : Nat) : lift (liftN n e k) = liftN n (lift e) (k+1) := + Nat.add_comm .. ▸ liftN'_comm (h := Nat.zero_le _) .. + +theorem sizeOf_liftN (e : VExpr) (k : Nat) : sizeOf e ≤ sizeOf (liftN n e k) := by + induction e generalizing k with simp [liftN, Nat.add_assoc, Nat.add_le_add_iff_left] + | bvar => simp [liftVar]; split <;> simp [Nat.le_add_left] + | _ => rename_i ih1 ih2; exact Nat.add_le_add (ih1 _) (ih2 _) + +@[simp] theorem liftN_default (n k : Nat) : liftN n default k = default := rfl +@[simp] theorem lift_default : lift default = default := rfl + +def ClosedN : VExpr → (k :_:= 0) → Prop + | .bvar i, k => i < k + | .sort .., _ | .const .., _ => True + | .app fn arg, k => fn.ClosedN k ∧ arg.ClosedN k + | .lam ty body, k => ty.ClosedN k ∧ body.ClosedN (k+1) + | .forallE ty body, k => ty.ClosedN k ∧ body.ClosedN (k+1) + +abbrev Closed := ClosedN + +@[simp] theorem ClosedN.default : ClosedN default k := trivial + +theorem ClosedN.mono (h : k ≤ k') (self : ClosedN e k) : ClosedN e k' := by + induction e generalizing k k' with (simp [ClosedN] at self ⊢; try simp [self, *]) + | bvar i => exact Nat.lt_of_lt_of_le self h + | app _ _ ih1 ih2 => exact ⟨ih1 h self.1, ih2 h self.2⟩ + | lam _ _ ih1 ih2 | forallE _ _ ih1 ih2 => + exact ⟨ih1 h self.1, ih2 (Nat.succ_le_succ h) self.2⟩ + +theorem ClosedN.liftN_eq (self : ClosedN e k) (h : k ≤ j) : liftN n e j = e := by + induction e generalizing k j with + (simp [ClosedN] at self; simp [liftN, *]) + | bvar i => exact liftVar_lt (Nat.lt_of_lt_of_le self h) + | app _ _ ih1 ih2 => exact ⟨ih1 self.1 h, ih2 self.2 h⟩ + | lam _ _ ih1 ih2 | forallE _ _ ih1 ih2 => + exact ⟨ih1 self.1 h, ih2 self.2 (Nat.succ_le_succ h)⟩ + +theorem ClosedN.lift_eq (self : ClosedN e) : lift e = e := self.liftN_eq (Nat.zero_le _) + +protected theorem ClosedN.liftN (self : ClosedN e k) : ClosedN (e.liftN n j) (k+n) := by + induction e generalizing k j with + (simp [ClosedN] at self; simp [VExpr.liftN, ClosedN, *]) + | bvar i => exact liftVar_lt_add self + | lam _ _ _ ih2 | forallE _ _ _ ih2 => exact Nat.add_right_comm .. ▸ ih2 self.2 + +theorem ClosedN.liftN_eq_rev (self : ClosedN (liftN n e j) k) (h : k ≤ j) : liftN n e j = e := by + induction e generalizing k j with + (simp [liftN, ClosedN] at self; simp [liftN, *]) + | bvar i => + refine liftVar_lt (Nat.lt_of_lt_of_le ?_ h) + unfold liftVar at self; split at self <;> + [exact self; exact Nat.lt_of_le_of_lt (Nat.le_add_left ..) self] + | app _ _ ih1 ih2 => exact ⟨ih1 self.1 h, ih2 self.2 h⟩ + | lam _ _ ih1 ih2 | forallE _ _ ih1 ih2 => + exact ⟨ih1 self.1 h, ih2 self.2 (Nat.succ_le_succ h)⟩ + +variable (ls : List VLevel) in +def instL : VExpr → VExpr + | .bvar i => .bvar i + | .sort u => .sort (u.inst ls) + | .const c us => .const c (us.map (VLevel.inst ls)) + | .app fn arg => .app fn.instL arg.instL + | .lam ty body => .lam ty.instL body.instL + | .forallE ty body => .forallE ty.instL body.instL + +theorem ClosedN.instL : ∀ {e}, ClosedN e k → ClosedN (e.instL ls) k + | .bvar .., h | .sort .., h | .const .., h => h + | .app .., h | .lam .., h | .forallE .., h => ⟨h.1.instL, h.2.instL⟩ + +theorem ClosedN.instL_rev : ∀ {e}, ClosedN (e.instL ls) k → ClosedN e k + | .bvar .., h | .sort .., h | .const .., h => h + | .app .., h | .lam .., h | .forallE .., h => ⟨h.1.instL_rev, h.2.instL_rev⟩ + +@[simp] theorem instL_default : instL ls default = default := rfl + +@[simp] theorem instL_liftN : (liftN n e k).instL ls = liftN n (e.instL ls) k := by + cases e <;> simp [liftN, instL, instL_liftN] + +theorem instL_instL {e : VExpr} : (e.instL ls).instL ls' = e.instL (ls.map (VLevel.inst ls')) := by + cases e <;> simp [instL, instL_instL, Function.comp_def, VLevel.inst_inst] + +def LevelWF (U : Nat) : VExpr → Prop + | .bvar _ => True + | .sort l => l.WF U + | .const _ ls => ∀ l ∈ ls, l.WF U + | .app e1 e2 | .lam e1 e2 | .forallE e1 e2 => e1.LevelWF U ∧ e2.LevelWF U + +theorem LevelWF.instL_id {e : VExpr} (h : e.LevelWF U) : e.instL (VLevel.params U) = e := by + induction e <;> simp_all [instL, LevelWF, VLevel.inst_id] + case const => exact List.map_id''' _ fun _ h1 => VLevel.inst_id (h _ h1) + +theorem levelWF_liftN : (liftN n e k).LevelWF U ↔ e.LevelWF U := by + induction e generalizing k <;> simp [liftN, LevelWF, *] + +theorem LevelWF.instL (h : ∀ l ∈ ls, l.WF U) : (instL ls e).LevelWF U := by + induction e <;> simp [VExpr.instL, VLevel.WF.inst h, LevelWF, *] + +alias ⟨LevelWF.liftN_rev, LevelWF.liftN⟩ := levelWF_liftN + +def instVar (i : Nat) (e : VExpr) (k := 0) : VExpr := + if i < k then .bvar i else if i = k then liftN k e else .bvar (i - 1) + +@[simp] theorem instVar_zero : instVar 0 e = e := liftN_zero .. +@[simp] theorem instVar_upper : instVar (i+1) e = .bvar i := rfl +@[simp] theorem instVar_lower : instVar 0 e (k+1) = .bvar 0 := by simp [instVar] +@[simp] theorem instVar_succ : instVar (i+1) e (k+1) = (instVar i e k).lift := by + simp [instVar, Nat.succ_lt_succ_iff]; split <;> simp [lift, liftN] + split <;> simp [liftN_liftN, liftN] + have := Nat.lt_of_le_of_ne (Nat.not_lt.1 ‹_›) (Ne.symm ‹_›) + let i+1 := i; rfl + +theorem liftN_instVar_lo (n : Nat) (e : VExpr) (j k : Nat) (hj : k ≤ j) : + liftN n (instVar i e j) k = instVar (liftVar n i k) e (n+j) := by + simp [instVar]; split <;> rename_i h + · rw [if_pos]; · rfl + simp only [liftVar]; split <;> rename_i hk + · exact Nat.lt_add_left _ h + · exact Nat.add_lt_add_left h _ + split <;> rename_i h' + · subst i + rw [liftN'_liftN' (h1 := Nat.zero_le _) (h2 := hj), liftVar_le hj, + if_neg (by simp), if_pos rfl, Nat.add_comm] + · rw [Nat.not_lt] at h; rw [liftVar_le (Nat.le_trans hj h)] + have hk := Nat.lt_of_le_of_ne h (Ne.symm h') + let i+1 := i + have := Nat.add_lt_add_left hk n + rw [if_neg (Nat.lt_asymm this), if_neg (Nat.ne_of_gt this)] + simp only [liftN] + rw [liftVar_le (Nat.le_trans hj <| by exact Nat.le_of_lt_succ hk)]; rfl + +theorem liftN_instVar_hi (i : Nat) (e2 : VExpr) (n k j : Nat) : + liftN n (instVar i e2 j) (k+j) = instVar (liftVar n i (k+j+1)) (liftN n e2 k) j := by + simp [instVar]; split <;> rename_i h + · have := Nat.lt_add_left k h + rw [liftVar_lt <| Nat.lt_succ_of_lt this, if_pos h] + simp [liftN, liftVar_lt this] + split <;> rename_i h' + · subst i + have := Nat.le_add_left j k + simp [liftVar_lt (by exact Nat.lt_succ_of_le this)] + rw [liftN'_comm (h := Nat.zero_le _), Nat.add_comm] + · have hk := Nat.lt_of_le_of_ne (Nat.not_lt.1 h) (Ne.symm h') + let i+1 := i + simp [liftVar, Nat.succ_lt_succ_iff]; split <;> rename_i hi + · simp [liftN, liftVar_lt hi] + · have := Nat.lt_add_left n hk + rw [if_neg (Nat.lt_asymm this), if_neg (Nat.ne_of_gt this)] + simp [liftN]; rw [liftVar_le (Nat.not_lt.1 hi)] + +@[simp] theorem instL_instVar : (instVar i e k).instL ls = instVar i (e.instL ls) k := by + simp [instVar]; split <;> [skip; split] <;> simp [instL, instL_liftN] + +def inst : VExpr → VExpr → (k :_:= 0) → VExpr + | .bvar i, e, k => instVar i e k + | .sort u, _, _ => .sort u + | .const c us, _, _ => .const c us + | .app fn arg, e, k => .app (fn.inst e k) (arg.inst e k) + | .lam ty body, e, k => .lam (ty.inst e k) (body.inst e (k+1)) + | .forallE ty body, e, k => .forallE (ty.inst e k) (body.inst e (k+1)) + +theorem instL_appN (ls : List VLevel) (as : List VExpr) (f : VExpr) : + (appN f as).instL ls = appN (f.instL ls) (as.map (instL ls)) := by + induction as generalizing f with + | nil => rfl + | cons a as ih => simp [appN, instL, ih] + +theorem liftN_appN (n k : Nat) (f : VExpr) : ∀ (as : List VExpr), + (f.appN as).liftN n k = appN (f.liftN n k) (as.map (liftN n · k)) + | [] => rfl + | a :: as => by + show (VExpr.appN (f.app a) as).liftN n k = _ + rw [liftN_appN n k (f.app a) as] + rfl + +theorem instN_appN (a : VExpr) (k : Nat) (f : VExpr) : ∀ (as : List VExpr), + (f.appN as).inst a k = appN (f.inst a k) (as.map (·.inst a k)) + | [] => rfl + | e :: as => by + show (VExpr.appN (f.app e) as).inst a k = _ + rw [instN_appN a k (f.app e) as] + rfl + +@[simp] theorem inst_default : inst default e k = default := rfl + +theorem liftN_instN_lo (n : Nat) (e1 e2 : VExpr) (j k : Nat) (hj : k ≤ j) : + liftN n (e1.inst e2 j) k = (liftN n e1 k).inst e2 (n+j) := by + induction e1 generalizing k j with + simp [liftN, inst, instVar, Nat.add_le_add_iff_right, *] + | bvar i => apply liftN_instVar_lo (hj := hj) + | _ => rfl + +theorem liftN_instN_hi (e1 e2 : VExpr) (n k j : Nat) : + liftN n (e1.inst e2 j) (k+j) = (liftN n e1 (k+j+1)).inst (liftN n e2 k) j := by + induction e1 generalizing j with simp [liftN, inst, instVar, *] + | bvar i => apply liftN_instVar_hi + | _ => rename_i IH; apply IH + +theorem liftN_inst_hi (e1 e2 : VExpr) (n k : Nat) : + liftN n (e1.inst e2) k = (liftN n e1 (k+1)).inst (liftN n e2 k) := liftN_instN_hi .. + +theorem lift_instN_lo (e1 e2 : VExpr) : lift (e1.inst e2 k) = (lift e1).inst e2 (k + 1) := + Nat.add_comm .. ▸ liftN_instN_lo (hj := Nat.zero_le _) .. + +theorem lift_inst_hi (e1 e2 : VExpr) : lift (e1.inst e2) = (liftN 1 e1 1).inst (lift e2) := + liftN_instN_hi .. + +theorem inst_liftN (e1 e2 : VExpr) : (liftN 1 e1 k).inst e2 k = e1 := by + induction e1 generalizing k with simp [liftN, inst, *] + | bvar i => + simp only [liftVar, instVar, Nat.add_comm 1]; split <;> [rfl; rename_i h] + rw [if_neg (mt (Nat.lt_of_le_of_lt (Nat.le_succ _)) h), + if_neg (mt (by rintro rfl; apply Nat.lt_succ_self) h)]; rfl + +theorem inst_liftN' (e1 e2 : VExpr) : (liftN (n+1) e1 k).inst e2 k = liftN n e1 k := by + rw [← liftN'_liftN_hi, inst_liftN] + +theorem inst_lift (e1 e2 : VExpr) : (lift e1).inst e2 = e1 := inst_liftN .. + +protected theorem LevelWF.inst + (h1 : e1.LevelWF U) (h2 : e2.LevelWF U) : (inst e1 e2 k).LevelWF U := by + induction e1 generalizing k <;> simp_all [inst, instVar, LevelWF] + case bvar => split <;> [trivial; split <;> [exact h2.liftN; trivial]] + +def unliftN (e : VExpr) (n k : Nat) : VExpr := + match n with + | 0 => e + | n+1 => unliftN (e.inst default k) n k + +@[simp] theorem unliftN_liftN : unliftN (liftN n e k) n k = e := by + induction n <;> simp [unliftN, inst_liftN', *] + +theorem unliftN_add : unliftN e (n1+n2) k = unliftN (unliftN e n1 k) n2 k := by + induction n1 generalizing e <;> simp [unliftN, Nat.succ_add, *] + +theorem unliftN_succ' : unliftN e (n+1) k = (unliftN e n k).inst default k := by + rw [unliftN_add]; rfl + +theorem liftN_unliftN_hi (h : k2 ≤ k1) : + liftN n1 (unliftN e n2 k2) k1 = unliftN (liftN n1 e (k1+n2)) n2 k2 := by + obtain ⟨k1, rfl⟩ := Nat.le_iff_exists_add'.1 h + induction n2 generalizing e with simp [unliftN] + | succ n2 ih => + rw [ih, Nat.add_right_comm, liftN_instN_hi e default n1 (k1+n2) k2, + Nat.add_right_comm k1]; rfl + +def Skips (e : VExpr) (n k : Nat) : Prop := liftN n (unliftN e n k) k = e + +protected theorem Skips.liftN : Skips (liftN n e k) n k := by simp [Skips] + +theorem skips_iff_exists : Skips e n k ↔ ∃ e', e = liftN n e' k := + ⟨fun h => ⟨_, h.symm⟩, fun ⟨_, h⟩ => h ▸ .liftN⟩ + +theorem Skips.zero : Skips e 0 k := by simp [Skips, unliftN] + +theorem liftN_inj : liftN n e1 k = liftN n e2 k ↔ e1 = e2 := + ⟨fun H => by rw [← unliftN_liftN (e := e1), H, unliftN_liftN], (· ▸ rfl)⟩ + +theorem liftVar_inj : liftVar n i k = liftVar n i' k ↔ i = i' := by + simpa [liftN] using @liftN_inj n (.bvar i) k (.bvar i') + +theorem Skips.of_liftN_hi (self : (liftN n1 e k1).Skips n2 k2) (h : n2 + k2 ≤ k1) : + e.Skips n2 k2 := by + obtain ⟨k1, rfl⟩ := Nat.le_iff_exists_add'.1 h + rwa [Skips, Nat.add_comm n2, ← Nat.add_assoc, ← liftN_unliftN_hi (Nat.le_add_left ..), + liftN'_comm (h := Nat.le_add_left ..), Nat.add_comm, liftN_inj] at self + +theorem skips_add : Skips e (n1+n2) k ↔ ∃ e', Skips e' n1 k ∧ e = liftN n2 e' k := by + simp [skips_iff_exists, ← liftN'_liftN_hi] + exact ⟨fun ⟨_, h⟩ => ⟨_, ⟨_, rfl⟩, h⟩, fun ⟨_, ⟨_, rfl⟩, h⟩ => ⟨_, h⟩⟩ + +def Skips' (n : Nat) : VExpr → (k :_:= 0) → Prop + | .bvar i, k => i < k + n → i < k + | .sort .., _ | .const .., _ => True + | .app fn arg, k => fn.Skips' n k ∧ arg.Skips' n k + | .lam ty body, k => ty.Skips' n k ∧ body.Skips' n (k+1) + | .forallE ty body, k => ty.Skips' n k ∧ body.Skips' n (k+1) + +theorem skips_iff : Skips e n k ↔ Skips' n e k := by + induction n generalizing e with + | zero => simp [Skips, unliftN]; induction e generalizing k <;> simp [Skips', *] + | succ n ih => + simp [skips_add, ih]; clear ih + induction e generalizing k with + | bvar i => + refine ⟨fun ⟨e', h1, h2⟩ => ?_, fun h => ?_⟩ + · cases e' <;> cases h2; simp [Skips', liftVar]; split + · intro; assumption + · next h2 => + rw [Nat.add_comm, ← Nat.add_assoc, Nat.succ_lt_succ_iff] + exact fun h => h2.elim (h1 h) + · simp [Skips'] at h + if h' : i < k + n + 1 then + exact ⟨.bvar i, fun _ => h h', by simp [liftN, liftVar, h h']⟩ + else + have := Nat.not_lt.1 h' + let i+1 := i; rw [Nat.add_lt_add_iff_right] at h' + have := mt (Nat.lt_of_lt_of_le · (Nat.le_add_right ..)) h' + exact ⟨.bvar i, h'.elim, by simp [liftN, liftVar]; rw [if_neg this, Nat.add_comm]⟩ + | sort u => + refine ⟨fun ⟨e', h1, h2⟩ => ?_, fun _ => ⟨.sort u, by simp [Skips', liftN]⟩⟩ + cases e' <;> cases h2; simp [Skips'] + | const c ls => + refine ⟨fun ⟨e', h1, h2⟩ => ?_, fun _ => ⟨.const c ls, by simp [Skips', liftN]⟩⟩ + cases e' <;> cases h2; simp [Skips'] + | app f a fIH aIH => + simp [Skips', ← fIH, ← aIH]; refine ⟨fun ⟨e', h1, h2⟩ => ?_, ?_⟩ + · cases e' <;> cases h2; exact ⟨⟨_, h1.1, rfl⟩, ⟨_, h1.2, rfl⟩⟩ + · rintro ⟨⟨e1, h1, rfl⟩, ⟨e2, h2, rfl⟩⟩; exact ⟨.app .., ⟨h1, h2⟩, rfl⟩ + | forallE f a fIH aIH => + simp [Skips', ← fIH, ← aIH]; refine ⟨fun ⟨e', h1, h2⟩ => ?_, ?_⟩ + · cases e' <;> cases h2; exact ⟨⟨_, h1.1, rfl⟩, ⟨_, h1.2, rfl⟩⟩ + · rintro ⟨⟨e1, h1, rfl⟩, ⟨e2, h2, rfl⟩⟩; exact ⟨.forallE .., ⟨h1, h2⟩, rfl⟩ + | lam f a fIH aIH => + simp [Skips', ← fIH, ← aIH]; refine ⟨fun ⟨e', h1, h2⟩ => ?_, ?_⟩ + · cases e' <;> cases h2; exact ⟨⟨_, h1.1, rfl⟩, ⟨_, h1.2, rfl⟩⟩ + · rintro ⟨⟨e1, h1, rfl⟩, ⟨e2, h2, rfl⟩⟩; exact ⟨.lam .., ⟨h1, h2⟩, rfl⟩ + +theorem of_liftN_eq_liftN (h : liftN n1 e1 (k1+n2+k2) = liftN n2 e2 k2) : + ∃ e', e1 = liftN n2 e' k2 ∧ e2 = liftN n1 e' (k1+k2) := by + have : (liftN n1 e1 (k1+n2+k2)).Skips n2 k2 := h ▸ .liftN + obtain ⟨e', rfl⟩ := skips_iff_exists.1 <| + this.of_liftN_hi (Nat.add_assoc .. ▸ Nat.le_add_left ..) + refine ⟨e', rfl, ?_⟩ + rw [← liftN_inj, ← h, liftN'_comm (n1 := n1) (h := Nat.le_add_left ..), + Nat.add_left_comm, Nat.add_assoc] + +@[simp] theorem instL_instN {e1 e2 : VExpr} : + (e1.inst e2 k).instL ls = (e1.instL ls).inst (e2.instL ls) k := by + induction e1 generalizing k <;> simp [instL, inst, *] + +theorem instL_unliftN : instL ls (unliftN e n k) = unliftN (instL ls e) n k := by + induction n generalizing e with simp [unliftN] + | succ _ ih => rw [ih, instL_instN]; rfl + +theorem Skips.of_instL (self : (instL ls e).Skips n k) : e.Skips n k := by + rw [skips_iff] at self ⊢ + induction e generalizing k <;> simp_all [Skips', instL] + +theorem of_liftN_eq_instL (h : liftN n e1 k = instL ls e2) : + ∃ e', e1 = instL ls e' ∧ e2 = liftN n e' k := by + have : (instL ls e2).Skips n k := h ▸ .liftN + obtain ⟨e', rfl⟩ := skips_iff_exists.1 this.of_instL + refine ⟨e', ?_, rfl⟩ + rw [← liftN_inj, h, instL_liftN] + +theorem ClosedN.instN_eq (self : ClosedN e1 k) (h : k ≤ j) : e1.inst e2 j = e1 := by + conv => lhs; rw [← self.liftN_eq (n := 1) h] + rw [inst_liftN] + +theorem ClosedN.instN (h1 : ClosedN e (k+j+1)) (h2 : ClosedN e2 k) : ClosedN (e.inst e2 j) (k+j) := + match e, h1 with + | .bvar i, h => by + simp [inst, instVar]; split <;> rename_i h1 + · exact Nat.lt_of_lt_of_le h1 (Nat.le_add_left ..) + split <;> rename_i h1' + · exact h2.liftN + · have hk := Nat.lt_of_le_of_ne (Nat.not_lt.1 h1) (Ne.symm h1') + let i+1 := i + exact Nat.lt_of_succ_lt_succ h + | .sort .., h | .const .., h => h + | .app .., h => ⟨h.1.instN h2, h.2.instN h2⟩ + | .lam .., h | .forallE .., h => ⟨h.1.instN h2, h.2.instN (j := j+1) h2⟩ + +theorem ClosedN.inst (h1 : ClosedN e (k+1)) (h2 : ClosedN e2 k) : ClosedN (e.inst e2) k := + h1.instN (j := 0) h2 + +theorem inst_instVar_hi (i : Nat) (e2 e3 : VExpr) (k j : Nat) : + inst (instVar i e2 k) e3 (j+k) = (instVar i e3 (j+k+1)).inst (e2.inst e3 j) k := by + simp [instVar]; split <;> rename_i h + · simp [Nat.lt_succ_of_lt, inst, instVar, h, Nat.lt_of_lt_of_le h (Nat.le_add_left k j)] + split <;> rename_i h' + · subst i + simp [Nat.lt_succ_of_le, Nat.le_add_left, inst, instVar] + rw [liftN_instN_lo k e2 e3 j _ (Nat.zero_le _), Nat.add_comm] + · have hk := Nat.lt_of_le_of_ne (Nat.not_lt.1 h) (Ne.symm h') + let i+1 := i + simp [inst, instVar]; split <;> rename_i hi + · simp [inst, instVar, h, h'] + split <;> rename_i hi' + · subst i + suffices liftN (j+k+1) .. = _ by rw [this]; exact (inst_liftN ..).symm + exact (liftN'_liftN' (Nat.zero_le _) (Nat.le_add_left k j)).symm + · have hk := Nat.lt_of_le_of_ne (Nat.not_lt.1 hi) (Ne.symm hi') + let i+1 := i + simp [inst, instVar] + have := Nat.lt_of_le_of_lt (Nat.le_add_left ..) hk + rw [if_neg (Nat.lt_asymm this), if_neg (Nat.ne_of_gt this)] + +theorem inst_inst_hi (e1 e2 e3 : VExpr) (k j : Nat) : + inst (e1.inst e2 k) e3 (j+k) = (e1.inst e3 (j+k+1)).inst (e2.inst e3 j) k := by + induction e1 generalizing k with simp [inst, instVar, *] + | bvar i => apply inst_instVar_hi + | _ => rename_i IH; apply IH + +theorem inst0_inst_hi (e1 e2 e3 : VExpr) (j : Nat) : + inst (e1.inst e2) e3 j = (e1.inst e3 (j+1)).inst (e2.inst e3 j) := inst_inst_hi .. + +theorem inst_instVar_lo (i : Nat) (e2 e3 : VExpr) (k j : Nat) : + inst (instVar i e2 (k+j+1)) e3 j = + (instVar i (e3.liftN 1 k) j).inst e2 (k+j) := by + simp [instVar]; split <;> rename_i h + · split <;> rename_i h1 + · simp only [inst, instVar, h1, reduceIte] + rw [if_pos (Nat.lt_of_lt_of_le h1 (Nat.le_add_left ..))] + split <;> rename_i h1' + · subst i + simp [inst, instVar]; rw [liftN'_comm (h := Nat.zero_le _), Nat.add_comm] + exact (inst_liftN ..).symm + · have hj := Nat.lt_of_le_of_ne (Nat.not_lt.1 h1) (Ne.symm h1') + let i+1 := i + simp [inst, instVar, h1, h1', Nat.lt_of_succ_lt_succ h] + split <;> rename_i h' + · subst i + have := Nat.lt_succ_of_le (Nat.le_add_left j k) + rw [if_neg (Nat.lt_asymm this), if_neg (Nat.ne_of_gt this)] + simp [inst, instVar] + suffices liftN (k+j+1) .. = _ by rw [this]; exact inst_liftN .. + exact (liftN'_liftN' (Nat.zero_le _) (Nat.le_add_left j k)).symm + · have hk := Nat.lt_of_le_of_ne (Nat.not_lt.1 h) (Ne.symm h') + let i+1 := i + have hk := Nat.lt_of_add_lt_add_right hk + simp [inst, instVar] + have := Nat.lt_of_le_of_lt (Nat.le_add_left ..) hk + rw [if_neg (Nat.lt_asymm this), if_neg (Nat.ne_of_gt this)] + have := Nat.lt_succ_of_lt this + rw [if_neg (Nat.lt_asymm this), if_neg (Nat.ne_of_gt this)] + simp [inst, instVar] + rw [if_neg (Nat.lt_asymm hk), if_neg (Nat.ne_of_gt hk)] + +theorem inst_inst_lo (e1 e2 e3 : VExpr) (k j : Nat) : + inst (e1.inst e2 (k+j+1)) e3 j = + (e1.inst (e3.liftN 1 k) j).inst e2 (k+j) := by + induction e1 generalizing j with simp [inst, instVar, *] + | bvar i => apply inst_instVar_lo + | _ => rename_i IH; exact IH (j+1) + +theorem instN_bvar0 (e : VExpr) (k : Nat) : + inst (e.liftN 1 (k+1)) (.bvar 0) k = e := by + induction e generalizing k with simp [liftN, inst, *] + | bvar i => induction i generalizing k <;> cases k <;> simp [*, lift, liftN] + +end VExpr + +inductive Lift : Type where + | refl : Lift + | skip : Lift → Lift + | cons : Lift → Lift + +namespace Lift + +@[simp] def skipN (l : Lift) : Nat → Lift + | 0 => l + | n+1 => .skip (skipN l n) + +theorem skipN_one : skipN l 1 = .skip l := rfl + +theorem skipN_skipN : skipN (skipN l n) k = skipN l (n + k) := by induction k <;> simp [*] + +@[simp] def consN (l : Lift) : Nat → Lift + | 0 => l + | k+1 => .cons (consN l k) + +theorem consN_consN : consN (.consN l a) b = .consN l (a + b) := by + induction b <;> simp [*] + +@[simp] def comp (l₁ l₂ : Lift) : Lift := + match l₂, l₁ with + | .refl, l₁ => l₁ + | .skip l₂, l₁ => .skip (l₁.comp l₂) + | .cons l₂, .refl => .cons l₂ + | .cons l₂, .skip l₁ => .skip (l₁.comp l₂) + | .cons l₂, .cons l₁ => .cons (l₁.comp l₂) + +@[simp] theorem refl_comp : comp refl l = l := by induction l <;> simp [*] + +theorem consN_comp : consN (.comp l₁ l₂) n = .comp (.consN l₁ n) (.consN l₂ n) := by + induction n <;> simp [*] + +@[simp] def dom : Lift → Nat + | .refl => 0 + | .skip l => l.dom + | .cons l => l.dom + 1 + +@[simp] def size : Lift → Nat + | .refl => 0 + | .skip l => l.size + 1 + | .cons l => l.size + 1 + +@[simp] def depth : Lift → Nat + | .refl => 0 + | .skip l => l.depth + 1 + | .cons l => l.depth + +theorem dom_add_depth : dom l + depth l = size l := by induction l <;> simp! <;> omega + +theorem depth_comp : depth (.comp l₁ l₂) = l₁.depth + l₂.depth := + match l₂, l₁ with + | .refl, _ => rfl + | .skip _, _ => congrArg Nat.succ depth_comp + | .cons _, .refl => (Nat.zero_add _).symm + | .cons _, .skip _ => (congrArg Nat.succ depth_comp).trans (Nat.succ_add ..).symm + | .cons l₂, .cons l₁ => @depth_comp l₁ l₂ + +@[simp] theorem depth_consN : depth (.consN l n) = l.depth := by induction n <;> simp [*] + +@[simp] theorem depth_skipN : depth (.skipN l n) = l.depth + n := by + induction n <;> simp [Nat.add_assoc, *] + +theorem consN_skip_eq : consN (skip l) k = comp (consN l k) (consN (skip refl) k) := by + rw [← consN_comp]; rfl + +theorem depth_succ (H : l.depth = n + 1) : + ∃ l' k, depth l' = n ∧ l = consN (.skip l') k := by + match l with + | .skip l => cases H; exact ⟨l, 0, rfl, rfl⟩ + | .cons l => + obtain ⟨l, k, rfl, ⟨⟩⟩ := depth_succ (l := l) H + exact ⟨l, k+1, rfl, rfl⟩ + +theorem depth_succ' (H : l.depth = n + 1) : + ∃ l' k, depth l' = n ∧ l = comp l' (.consN (.skip refl) k) := by + let ⟨l', k, h1, h2⟩ := depth_succ H + exact ⟨.consN l' k, k, by simp [h1], by rwa [← consN_skip_eq]⟩ + +theorem comp_skipN : comp l₁ (skipN l₂ k) = skipN (comp l₁ l₂) k := by + induction k <;> simp [*] + +theorem skipN_comp_consN : comp (skipN l₁ k) (consN l₂ k) = skipN (comp l₁ l₂) k := by + induction k <;> simp [*] + +@[simp] protected def liftVar : Lift → Nat → Nat + | .refl, n => n + | .skip l, n => l.liftVar n + 1 + | .cons _, 0 => 0 + | .cons l, n+1 => l.liftVar n + 1 + +theorem liftVar_comp : (comp l₁ l₂).liftVar n = l₂.liftVar (l₁.liftVar n) := by + induction l₂ generalizing l₁ n <;> [skip; skip; cases l₁ <;> [skip; skip; cases n]] <;> simp [*] + +theorem liftVar_skipN : (skipN l n).liftVar i = l.liftVar i + n := by + induction n generalizing i with + | zero => rfl + | succ _ ih => simp [ih]; rfl + +theorem liftVar_consN_skipN : (consN (skipN refl n) k).liftVar i = liftVar n i k := by + induction k generalizing i with + | zero => simp [liftVar_skipN] + | succ k ih => + cases i with simp [liftVar, Nat.succ_lt_succ_iff, ih] + | succ i => split <;> rfl + +theorem liftVar_depth_zero (H : depth l = 0) : l.liftVar n = n := by + induction l generalizing n <;> [skip; skip; cases n] <;> simp_all [depth] + +theorem le_liftVar {l : Lift} : n ≤ l.liftVar n := by + induction l generalizing n <;> [skip; skip; cases n] <;> simp_all; grind + +def inter : Lift → Lift → Lift + | refl, l | l, refl => l + | skip l₁, skip l₂ | skip l₁, cons l₂ | cons l₁, skip l₂ => skip (l₁.inter l₂) + | cons l₁, cons l₂ => cons (l₁.inter l₂) + +theorem inter_self : inter l l = l := by induction l <;> simp! [*] + +theorem inter_comm : inter l₁ l₂ = inter l₂ l₁ := by + induction l₁ generalizing l₂ <;> cases l₂ <;> simp! [*] + +theorem inter_assoc : inter (inter l₁ l₂) l₃ = inter l₁ (inter l₂ l₃) := by + induction l₁ generalizing l₂ l₃ <;> cases l₂ <;> cases l₃ <;> simp! [*] + +@[simp] def diff : Lift → Lift → Lift + | refl, _ => refl + | l, refl => l + | skip l₁, skip l₂ | cons l₁, skip l₂ => diff l₁ l₂ + | skip l₁, cons l₂ => skip (diff l₁ l₂) + | cons l₁, cons l₂ => cons (l₁.diff l₂) + +@[simp] theorem diff_refl : diff l refl = l := by cases l <;> simp! + +theorem diff_comp : comp (diff l₁ l₂) l₂ = inter l₁ l₂ := by + induction l₁ generalizing l₂ <;> cases l₂ <;> simp! [*] + +def Fixes : Nat → Lift → Prop + | 0, _ => True + | _, .refl => True + | _+1, .skip _ => False + | n+1, .cons l => Fixes n l + +theorem Fixes.zero : Fixes 0 ρ := by simp [Fixes] + +theorem Fixes.liftVar_eq {ρ : Lift} (H : ρ.Fixes k) (h2 : i < k) : ρ.liftVar i = i := by + induction ρ generalizing i k with + | refl => rfl + | skip => let k+1 := k; cases H + | cons ρ ih => + let k+1 := k + cases i with + | zero => rfl + | succ k => exact congrArg Nat.succ <| ih H (Nat.lt_of_succ_lt_succ h2) + +end Lift + +namespace VExpr + +@[simp] def lift' : VExpr → Lift → VExpr + | .bvar i, k => .bvar (k.liftVar i) + | .sort u, _ => .sort u + | .const c us, _ => .const c us + | .app fn arg, k => .app (fn.lift' k) (arg.lift' k) + | .lam ty body, k => .lam (ty.lift' k) (body.lift' k.cons) + | .forallE ty body, k => .forallE (ty.lift' k) (body.lift' k.cons) + +theorem lift'_consN_skipN : e.lift' (.consN (.skipN .refl n) k) = liftN n e k := Eq.symm <| by + induction e generalizing k <;> simp [liftN, Lift.liftVar_consN_skipN, *] + +theorem lift'_comp {e : VExpr} : e.lift' (.comp l₁ l₂) = (e.lift' l₁).lift' l₂ := Eq.symm <| by + induction e generalizing l₁ l₂ <;> simp [Lift.liftVar_comp, *] + +theorem lift'_depth_zero {e : VExpr} (H : l.depth = 0) : e.lift' l = e := by + induction e generalizing l <;> simp_all [Lift.liftVar_depth_zero] + +@[simp] theorem lift'_refl {e : VExpr} : e.lift' .refl = e := lift'_depth_zero rfl + +theorem lift_eq_lift' {e : VExpr} : e.lift = e.lift' (.skip .refl) := by + rw [lift, ← lift'_consN_skipN]; rfl + +@[simp] theorem instL_lift' : (lift' e ρ).instL ls = lift' (e.instL ls) ρ := by + cases e <;> simp [lift', instL, instL_lift'] + +theorem ClosedN.lift'_eq (self : ClosedN e k) (h : ρ.Fixes k) : lift' e ρ = e := by + induction e generalizing k ρ with (simp [ClosedN] at self; simp [*]) + | bvar i => exact h.liftVar_eq self + | app _ _ ih1 ih2 => exact ⟨ih1 self.1 h, ih2 self.2 h⟩ + | lam _ _ ih1 ih2 | forallE _ _ ih1 ih2 => exact ⟨ih1 self.1 h, ih2 self.2 h⟩ + +def Subst := Nat → VExpr + +def Subst.Depth (σ : Subst) (n n' : Nat) := ∀ i, σ (i + n') = .bvar (i + n) + +def Subst.lift (σ : Subst) : Subst + | 0 => .bvar 0 + | i+1 => (σ i).lift + +def Subst.liftN (σ : Subst) : Nat → Subst + | 0 => σ + | k+1 => (σ.liftN k).lift + +def subst : VExpr → Subst → VExpr + | .bvar i, σ => σ i + | .sort u, _ => .sort u + | .const c us, _ => .const c us + | .app fn arg, σ => .app (fn.subst σ) (arg.subst σ) + | .lam ty body, σ => .lam (ty.subst σ) (body.subst σ.lift) + | .forallE ty body, σ => .forallE (ty.subst σ) (body.subst σ.lift) + +def Subst.lift_r (σ : Subst) (ρ : Lift) : Subst := fun x => (σ x).lift' ρ +def Subst.lift_l (ρ : Lift) (σ : Subst) : Subst := fun x => σ (ρ.liftVar x) + +theorem Subst.lift_l_lift {σ : Subst} {ρ} : (σ.lift_l ρ).lift = σ.lift.lift_l ρ.cons := by + funext i; cases i <;> simp! [lift_l] + +theorem Subst.lift_r_lift {σ : Subst} {ρ} : (σ.lift_r ρ).lift = σ.lift.lift_r ρ.cons := by + funext i; cases i <;> simp! [lift, lift_r, ← lift'_comp, lift_eq_lift'] + +theorem subst_lift' {e : VExpr} : (e.lift' ρ).subst σ = subst e (.lift_l ρ σ) := by + induction e generalizing ρ σ <;> simp! [*, Subst.lift_l_lift]; rfl + +theorem lift'_subst {e : VExpr} : (e.subst σ).lift' ρ = subst e (.lift_r σ ρ) := by + induction e generalizing ρ σ <;> simp! [*, Subst.lift_r, Subst.lift_r_lift] + +def Subst.id : Subst := .bvar +def Subst.head (σ : Subst) : VExpr := σ 0 +def Subst.tail (σ : Subst) : Subst := fun n => σ (n+1) + +theorem Subst.Depth.id : Subst.id.Depth 0 0 := fun _ => rfl + +@[simp] theorem id_lift : Subst.id.lift = Subst.id := by + funext i; cases i <;> simp [Subst.id, Subst.lift, liftN] + +@[simp] theorem subst_id {e : VExpr} : e.subst .id = e := by + induction e <;> simp! [*, id_lift]; rfl + +def Subst.cons (σ : Subst) (e : VExpr) : Subst + | 0 => e + | i+1 => σ i + +abbrev Subst.one (e : VExpr) : Subst := .cons .id e + +theorem Subst.Depth.one : (Subst.one e).Depth 0 1 := .id + +def _root_.Ix.Theory.Named.Lift.inv : Lift → Subst + | .refl => .id + | .skip ρ => ρ.inv.cons default + | .cons ρ => ρ.inv.lift + +theorem lift_l_inv {ρ : Lift} : .lift_l ρ ρ.inv = Subst.id := by + funext i; simp [Subst.lift_l, Subst.id] + induction ρ generalizing i with + | refl => rfl + | skip ρ ih => simp [Lift.inv, Subst.cons, ih] + | cons ρ ih => cases i <;> simp [Lift.inv, Subst.lift, ih, lift_eq_lift'] + +theorem lift'_inj {e e' : VExpr} {ρ : Lift} : e.lift' ρ = e'.lift' ρ ↔ e = e' := + ⟨(by simpa [subst_lift', lift_l_inv] using congrArg (·.subst ρ.inv) ·), (· ▸ rfl)⟩ + +theorem instN_eq (e a : VExpr) : e.inst a k = e.subst (.liftN (.one a) k) := by + induction e generalizing k with simp_all [inst, subst, Subst.liftN] | bvar i + induction k generalizing i <;> cases i <;> simp [Subst.liftN, Subst.lift, Subst.cons, Subst.id, *] + +theorem inst_eq (e a : VExpr) : e.inst a = e.subst (.one a) := instN_eq .. + +def Subst.trunc (σ : Subst) (n n' : Nat) : Subst := + fun i => if n' ≤ i then .bvar (i - n' + n) else σ i + +theorem Subst.lift_r_comm (σ : Subst) (ρ : Lift) (H : Subst.Depth σ 0 n) : + σ.lift_r ρ = .lift_l (ρ.consN n) ((σ.lift_r ρ).trunc 0 n) := by + funext i; simp [Subst.lift_l, Subst.lift_r, Subst.trunc] + have : (ρ.consN n).liftVar i = if n ≤ i then ρ.liftVar (i-n) + n else i := by + clear H; induction n generalizing i <;> [skip; cases i] <;> simp! [*]; split <;> rfl + rw [this]; split <;> simp + have := H (i - n); rw [Nat.sub_add_cancel ‹_›] at this; simp [this] + +theorem lift_r_one (e : VExpr) (ρ : Lift) : + (Subst.one e).lift_r ρ = .lift_l ρ.cons (Subst.one (e.lift' ρ)) := by + refine (Subst.lift_r_comm (Subst.one e) ρ .one).trans ?_; congr 1 + funext i; simp [Subst.trunc] + cases i <;> simp [Subst.one, Subst.cons, Subst.lift_r, Subst.id] + +theorem lift'_inst_hi (e1 e2 : VExpr) (ρ : Lift) : + lift' (e1.inst e2) ρ = (lift' e1 ρ.cons).inst (lift' e2 ρ) := by + simp [subst_lift', lift'_subst, lift_r_one, inst_eq] diff --git a/Ix/Theory/Named/VLevel.lean b/Ix/Theory/Named/VLevel.lean new file mode 100644 index 000000000..e2c9b26bf --- /dev/null +++ b/Ix/Theory/Named/VLevel.lean @@ -0,0 +1,99 @@ +/- +Adapted for Ix: shared universe semantics and additional proof support. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.VLevel +import Ix.Theory.Named.Std.Basic + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +export Lean (Name) +end Ix.Theory.Named + +namespace Ix.Theory.VLevel +open Ix.Theory.Named + +theorem le_trans {a b c : VLevel} (h1 : a ≤ b) (h2 : b ≤ c) : a ≤ c := + fun _ => Nat.le_trans (h1 _) (h2 _) + +theorem zero_le : zero ≤ a := fun _ => Nat.zero_le _ + +theorem le_succ : a ≤ succ a := fun _ => Nat.le_succ _ + +theorem succ_le_succ (h : a ≤ b) : succ a ≤ succ b := fun _ => Nat.succ_le_succ (h _) + +theorem le_max_left : a ≤ max a b := fun _ => Nat.le_max_left .. +theorem le_max_right : b ≤ max a b := fun _ => Nat.le_max_right .. + +theorem equiv_def' {a b : VLevel} : a ≈ b ↔ a.eval = b.eval := .rfl +theorem equiv_congr_left {a b c : VLevel} (h : a ≈ b) : a ≈ c ↔ b ≈ c := + iff_of_eq (congrArg (· = _) h) + +theorem equiv_congr_right {a b c : VLevel} (h : a ≈ b) : c ≈ a ↔ c ≈ b := + iff_of_eq (congrArg (_ = ·) h) + +theorem succ_congr_iff {a b : VLevel} : succ a ≈ succ b ↔ a ≈ b := by + simp [equiv_def, eval] + +theorem max_congr (h₁ : a₁ ≈ b₁) (h₂ : a₂ ≈ b₂) : max a₁ a₂ ≈ max b₁ b₂ := by + simp_all [equiv_def, eval] + +theorem max_comm : max a b ≈ max b a := by simp [equiv_def, eval, Nat.max_comm] + +theorem LE.max_eq_left (h : b.LE a) : max a b ≈ a := by + simp [equiv_def, eval, Nat.max_eq_left (h _)] + +theorem LE.max_eq_right (h : a.LE b) : max a b ≈ b := by + simp [equiv_def, eval, Nat.max_eq_right (h _)] + +theorem max_self : max a a ≈ a := by simp [equiv_def, eval] + +theorem zero_imax : imax zero a ≈ a := by + simp [equiv_def, eval, natIMax, eq_comm (b := 0)] + +theorem imax_zero : imax a zero ≈ zero := by simp [equiv_def, eval, natIMax] + +theorem imax_eq_zero : imax a b ≈ zero ↔ b ≈ zero := by + simp [equiv_def, eval, natIMax] + refine ⟨fun H ls => ?_, fun H ls hn => nomatch hn (H ls)⟩ + exact Decidable.byContradiction fun h => h (H ls h).2 + +def IsNeverZero (a : VLevel) : Prop := ∀ ls, a.eval ls ≠ 0 + +theorem IsNeverZero.imax_eq_max (h : IsNeverZero b) : imax a b ≈ max a b := by + simp_all [equiv_def, eval, natIMax, IsNeverZero] + +theorem id_WF : ∀ l ∈ (List.range u).map param, l.WF u := by simp [WF] + +variable (ls : List Name) in +def ofLevel : Lean.Level → Option VLevel + | .zero => return .zero + | .succ l => return .succ (← ofLevel l) + | .max l₁ l₂ => return .max (← ofLevel l₁) (← ofLevel l₂) + | .imax l₁ l₂ => return .imax (← ofLevel l₁) (← ofLevel l₂) + | .param n => + let i := ls.idxOf n + if i < ls.length then some (.param i) else none + | .mvar _ => none + +theorem WF.of_ofLevel (h : ofLevel ls l = some l') : l'.WF ls.length := by + induction l generalizing l' with simp [ofLevel, bind] at h + | zero => cases h; trivial + | succ _ ih => obtain ⟨l', h, ⟨⟩⟩ := h; exact @ih l' h + | max _ _ ih1 ih2 | imax _ _ ih1 ih2 => obtain ⟨_, h1, _, h2, ⟨⟩⟩ := h; exact ⟨ih1 h1, ih2 h2⟩ + | param n => exact h.2 ▸ h.1 + +theorem WF.of_mapM_ofLevel (h : List.mapM (VLevel.ofLevel Us) us = some us') + (a) (hl : a ∈ us') : VLevel.WF Us.length a := by + rw [List.mapM_eq_some] at h + have ⟨_, _, h⟩ := h.forall_exists_r _ hl; exact .of_ofLevel h + +end Ix.Theory.VLevel + +/-- The internal universe operation agrees definitionally with Lean's +natural-number operation used by the reference implementation proofs. -/ +@[simp] theorem Ix.Theory.VLevel.natIMax_eq_core (a b : Nat) : + Ix.Theory.VLevel.natIMax a b = Lean.Nat.imax a b := rfl diff --git a/Ix/Theory/Named/Verify/Axioms.lean b/Ix/Theory/Named/Verify/Axioms.lean new file mode 100644 index 000000000..7638841fc --- /dev/null +++ b/Ix/Theory/Named/Verify/Axioms.lean @@ -0,0 +1,516 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Batteries.Tactic.OpenPrivate +import Ix.Theory.Named.Std.Basic +import Ix.Theory.Named.Std.NodupKeys + +namespace Std.TreeMap + +variable {α : Type u} {β : Type v} {cmp : α → α → Ordering} {t : TreeMap α β cmp} + +/-- https://github.com/leanprover/lean4/issues/12798 -/ +axiom all_eq_all_toList {p : α → β → Bool} : + t.all p = t.toList.all fun a => p a.1 a.2 + +/-- https://github.com/leanprover/lean4/issues/12798 -/ +axiom any_eq_any_toList {p : α → β → Bool} : + t.any p = t.toList.any fun a => p a.1 a.2 + +end Std.TreeMap + +open scoped _root_.List +namespace Lean + +noncomputable def PersistentArrayNode.toList' : PersistentArrayNode α → List α := + PersistentArrayNode.rec + (motive_1 := fun _ => List α) (motive_2 := fun _ => List α) (motive_3 := fun _ => List α) + (node := fun _ => id) (leaf := (·.toList)) (fun _ => id) [] (fun _ _ a b => a ++ b) + +namespace PersistentArray + +inductive WF : PersistentArray α → Prop where + | empty : WF .empty + | push : WF arr → WF (arr.push x) + +noncomputable def toList' (arr : PersistentArray α) : List α := + arr.root.toList' ++ arr.tail.toList + +@[simp] theorem toList'_empty : (.empty : PersistentArray α).toList' = [] := rfl + +/-- We cannot prove this because `insertNewLeaf` is partial -/ +@[simp] axiom toList'_push {α} (arr : PersistentArray α) (x : α) : + (arr.push x).toList' = arr.toList' ++ [x] + +@[simp] theorem size_empty : (.empty : PersistentArray α).size = 0 := rfl + +@[simp] theorem size_push {α} (arr : PersistentArray α) (x : α) : + (arr.push x).size = arr.size + 1 := by + simp [push]; split <;> [rfl; (simp [mkNewTail]; split <;> rfl)] + +@[simp] theorem WF.toList'_length (h : WF arr) : arr.toList'.length = arr.size := by + induction h <;> simp [*] + +end PersistentArray + +namespace PersistentHashMap + +noncomputable def Node.toList' : Node α β → List (α × β) := + Node.rec + (motive_1 := fun _ => List (α × β)) (motive_2 := fun _ => List (α × β)) + (motive_3 := fun _ => List (α × β)) (motive_4 := fun _ => List (α × β)) + (entries := fun _ => id) (collision := fun ks xs _ => ks.toList.zip xs.toList) + (mk := fun _ => id) + (nil := []) (cons := fun _ _ l1 l2 => l1 ++ l2) + (entry := fun a b => [(a, b)]) (ref := fun _ => id) (null := []) + +noncomputable def toList' [BEq α] [Hashable α] (m : PersistentHashMap α β) : + List (α × β) := m.root.toList' + +inductive WF [BEq α] [Hashable α] : PersistentHashMap α β → Prop where + | empty : WF .empty + | insert : WF m → WF (m.insert a b) + +/-- We can't prove this because `Lean.PersistentHashMap.insertAux` is opaque -/ +axiom WF.toList'_insert {α β} [BEq α] [Hashable α] + [PartialEquivBEq α] [LawfulHashable α] + {m : PersistentHashMap α β} (_ : WF m) (a : α) (b : β) : + (m.insert a b).toList' ~ (a, b) :: m.toList'.filter (¬a == ·.1) + +/-- We can't prove this because `Lean.PersistentHashMap.findAux` is opaque -/ +axiom WF.find?_eq {α β} [BEq α] [Hashable α] + [PartialEquivBEq α] [LawfulHashable α] + {m : PersistentHashMap α β} (_ : WF m) (a : α) : m.find? a = m.toList'.lookup a + +/-- We can't prove this because `Lean.PersistentHashMap.{findAux, containsAux}` are opaque -/ +axiom findAux_isSome {α β} [BEq α] {node : Node α β} (i : USize) (a : α) : + containsAux node i a = (findAux node i a).isSome + +end PersistentHashMap + +namespace Syntax + +def structEq' : Syntax → Syntax → Bool + | .missing, .missing => true + | .node _ k args, .node _ k' args' => k == k' && + (args.size == args'.size && + (args.toList.attach.zip args'.toList.attach).all fun (a, b) => + have := Array.mem_toList_iff.1 a.2; structEq' a b) + | .atom _ val, .atom _ val' => val == val' + | .ident _ rawVal val preresolved, Syntax.ident _ rawVal' val' preresolved' => + rawVal == rawVal' && val == val' && preresolved == preresolved' + | _, _ => false +termination_by x _ => x + +theorem structEq'_node : + structEq' (.node _x k args) (.node _y k' args') = (k == k' && args.isEqv args' structEq') := by + unfold structEq'; simp; congr 1 + by_cases h : args.size = args'.size <;> [simp [h]; simp [Array.isEqv, h]] + let ⟨args⟩ := args; let ⟨args'⟩ := args'; simp at h ⊢ + have' : ((args.attach.map (·.1)).zip (args'.attach.map (·.1))).all + (fun x => x.1.structEq' x.2) = _ := by + simp only [List.zip_map_left, List.zip_map_right]; simp [Function.comp_def]; rfl + rw [← this]; simp; clear this + induction args generalizing args' <;> cases args' <;> simp at h <;> simp [List.isEqv, *] + +/-- This is a `partial` because it is not obviously terminating. The `structEq'_node` theorem +shows that a definition with the same clauses can be defined manually. -/ +@[simp] axiom structEq_eq : structEq a b = structEq' a b +end Syntax + +namespace Level + +/-! +### A total copy of `Lean.Level.normalize` + +`Lean.Level.normalize` and four of its helpers are `partial def`s, so they are opaque and nothing +can be proved about them. The `Total` namespace below is a clause-by-clause copy of +[Lean's `Lean/Level.lean`](https://github.com/leanprover/lean4/blob/v4.33.1/src/Lean/Level.lean#L319-L404), +under the same names, with the termination proofs supplied. That makes `normalize_eq` below a +purely syntactic trust assumption, checkable by reading the two definitions side by side; +`Ix.Theory.Named.Tests.LevelStd` also checks it on a finite corpus of levels. +-/ +namespace Total + +/-- The structural size of a level, used as the termination measure for `normalize`. -/ +def size : Level → Nat + | .zero | .param _ | .mvar _ => 1 + | .succ l => size l + 1 + | .max l₁ l₂ => size l₁ + size l₂ + 1 + | .imax l₁ l₂ => size l₁ + size l₂ + 2 + +/-- Secondary termination measure for `normalize`: in the `imax` branch it recurses on +`mkLevelMax l₁ l₂`, which has the same `size` as `imax l₁ l₂` but a smaller `tag`. -/ +private def tag (l : Level) : Nat := + match l.getLevelOffset with + | .imax .. => 1 + | _ => 0 + +private theorem tag_le (l : Level) : tag l ≤ 1 := by unfold tag; split <;> omega + +theorem one_le_size (l : Level) : 1 ≤ size l := by cases l <;> simp [size] + +private theorem getOffsetAux_eq (l : Level) (k) : getOffsetAux l k = getOffsetAux l 0 + k := by + induction l generalizing k with + | succ l ih => rw [getOffsetAux, ih (k+1), getOffsetAux, ih 1]; omega + | _ => simp [getOffsetAux] + +theorem size_getLevelOffset (l : Level) : + size l.getLevelOffset + l.getOffset = size l := by + simp only [getOffset] + induction l with | succ l ih => ?_ | _ => rfl + show size l.getLevelOffset + getOffsetAux l 1 = size l + 1 + rw [getOffsetAux_eq l 1]; omega + +end Total +open private accMax mkIMaxAux mkMaxAux skipExplicit isExplicitSubsumedAux + isExplicitSubsumed from Lean.Level + +def Total.mkMaxAux (lvls : Array Level) (extraK : Nat) (i : Nat) + (prev : Level) (prevK : Nat) (result : Level) : Level := + if h : i < lvls.size then + let lvl := lvls[i] + let curr := lvl.getLevelOffset + let currK := lvl.getOffset + if curr == prev then mkMaxAux lvls extraK (i+1) curr currK result + else mkMaxAux lvls extraK (i+1) curr currK (accMax result prev (extraK + prevK)) + else accMax result prev (extraK + prevK) + +/-- Patch for `partial def Lean.Level.mkMaxAux`. -/ +@[simp] axiom mkMaxAux_eq : mkMaxAux = Total.mkMaxAux + +def Total.skipExplicit (lvls : Array Level) (i : Nat) : Nat := + if h : i < lvls.size then + if lvls[i].getLevelOffset.isZero then skipExplicit lvls (i+1) else i + else i + +/-- Patch for `partial def Lean.Level.skipExplicit`. -/ +@[simp] axiom skipExplicit_eq : skipExplicit = Total.skipExplicit + +def Total.isExplicitSubsumedAux (lvls : Array Level) (maxExplicit : Nat) (i : Nat) : Bool := + if h : i < lvls.size then + if lvls[i].getOffset ≥ maxExplicit then true + else isExplicitSubsumedAux lvls maxExplicit (i+1) + else false + +/-- Patch for `partial def Lean.Level.isExplicitSubsumedAux`. -/ +@[simp] axiom isExplicitSubsumedAux_eq : isExplicitSubsumedAux = Total.isExplicitSubsumedAux + +mutual + +/-- A total copy of `partial def Lean.Level.normalize`. -/ +def Total.normalize (l : Level) : Level := + if isAlreadyNormalizedCheap l then l else + let k := l.getOffset + match h : l.getLevelOffset with + | .max l₁ l₂ => + let lvls := getMaxArgsAux l₁ false #[] + let lvls := getMaxArgsAux l₂ false lvls + let lvls := lvls.qsort normLt + let firstNonExplicit := skipExplicit lvls 0 + let i := if isExplicitSubsumed lvls firstNonExplicit then firstNonExplicit + else firstNonExplicit - 1 + let lvl₁ := lvls[i]! + let prev := lvl₁.getLevelOffset + let prevK := lvl₁.getOffset + mkMaxAux lvls k (i+1) prev prevK Level.zero + | .imax l₁ l₂ => + if l₂.isNeverZero then addOffset (normalize (mkLevelMax l₁ l₂)) k + else addOffset (mkIMaxAux (normalize l₁) (normalize l₂)) k + | _ => unreachable! +termination_by (1, 3 * size l + tag l) +decreasing_by all_goals + refine .right _ ?_ + have hsz := size_getLevelOffset l + rw [h] at hsz + simp only [size] at hsz + have := one_le_size l₁ + have := one_le_size l₂ + have := tag_le l₁ + have := tag_le l₂ + first + | omega + | have ht : tag l = 1 := by simp [tag, h] + have e1 : size (mkLevelMax l₁ l₂) = size l₁ + size l₂ + 1 := rfl + have e2 : tag (mkLevelMax l₁ l₂) = 0 := rfl + omega + +def Total.getMaxArgsAux : Level → Bool → Array Level → Array Level + | .max l₁ l₂, norm, lvls => getMaxArgsAux l₂ norm (getMaxArgsAux l₁ norm lvls) + | l, false, lvls => getMaxArgsAux (normalize l) true lvls + | l, true, lvls => lvls.push l +termination_by l b => (if b then 0 else 1, 3 * size l + tag l + 1) +decreasing_by + any_goals cases norm + any_goals first | refine .right _ ?_ | exact .left _ _ (by decide) + all_goals first + | omega + | have e1 : size (Level.max l₁ l₂) = size l₁ + size l₂ + 1 := rfl + have e2 : tag (Level.max l₁ l₂) = 0 := rfl + have := one_le_size l₁ + have := one_le_size l₂ + have := tag_le l₁ + have := tag_le l₂ + omega + +end + +/-- `Lean.Level.normalize` is a `partial def`, so it is opaque; +`Total.normalize` above is a total copy of it. -/ +axiom normalize_eq : normalize = Total.normalize + +def mkData' (h : UInt64) (depth : Nat := 0) (hasMVar hasParam : Bool := false) : Level.Data := + if depth > Nat.pow 2 24 - 1 then panic! "universe level depth is too big" + else + h.toUInt32.toUInt64 + + hasMVar.toUInt64.shiftLeft 32 + + hasParam.toUInt64.shiftLeft 33 + + depth.toUInt64.shiftLeft 40 + +/-- This exists only for the bit-twiddling proofs, it shouldn't appear +in the main results, which use the functions below instead -/ +axiom mkData_eq : @mkData = @mkData' + +def hasParam' : Level → Bool + | .param .. => true + | .zero | .mvar .. => false + | .succ l => l.hasParam' + | .max l₁ l₂ | .imax l₁ l₂ => l₁.hasParam' || l₂.hasParam' + +/-- This was false prior to the fix of lean4#8554; it should now be provable +using `mkData_eq` and friends, but this has not been done yet -/ +@[simp] axiom hasParam_eq (l : Level) : l.hasParam = l.hasParam' + +def hasMVar' : Level → Bool + | .mvar .. => true + | .zero | .param .. => false + | .succ l => l.hasMVar' + | .max l₁ l₂ | .imax l₁ l₂ => l₁.hasMVar' || l₂.hasMVar' + +/-- This was false prior to the fix of lean4#8554; it should now be provable +using `mkData_eq` and friends, but this has not been done yet -/ +@[simp] axiom hasMVar_eq (l : Level) : l.hasMVar = l.hasMVar' + +/-- This is because the `BEq` instance is implemented in C++ -/ +@[instance] axiom instLawfulBEqLevel : LawfulBEq Level + +@[inline] private def mkIMaxCore (u v : Level) (elseK : Unit → Level) : Level := + if v.isNeverZero then mkLevelMax' u v + else if v.isZero then v + else if u.isZero || u matches .succ .zero then v + else if u == v then u + else elseK () + +open private mkLevelIMaxCore from Lean.Level in +/-- Workaround for https://github.com/leanprover/lean4/pull/7631#issuecomment-3289800246 -/ +@[simp] axiom mkLevelIMaxCore_eq (e : Expr) (n : Nat) : mkLevelIMaxCore = mkIMaxCore + +end Level + +namespace Expr + +def mkData' + (h : UInt64) (looseBVarRange : Nat := 0) (approxDepth : UInt32 := 0) + (hasFVar hasExprMVar hasLevelMVar hasLevelParam : Bool := false) + : Expr.Data := + let approxDepth : UInt8 := if approxDepth > 255 then 255 else approxDepth.toUInt8 + assert! (looseBVarRange ≤ Nat.pow 2 20 - 1) + h.toUInt32.toUInt64 + + approxDepth.toUInt64.shiftLeft 32 + + hasFVar.toUInt64.shiftLeft 40 + + hasExprMVar.toUInt64.shiftLeft 41 + + hasLevelMVar.toUInt64.shiftLeft 42 + + hasLevelParam.toUInt64.shiftLeft 43 + + looseBVarRange.toUInt64.shiftLeft 44 + +/-- This exists only for the bit-twiddling proofs, it shouldn't appear +in the main results, which use the functions below instead -/ +axiom mkData_eq : @mkData = @mkData' + +@[inline] def mkAppData' (fData : Data) (aData : Data) : Data := + let depth := max fData.approxDepth.toUInt16 aData.approxDepth.toUInt16 + 1 + let approxDepth := if depth > 255 then 255 else depth.toUInt8 + let looseBVarRange := max fData.looseBVarRange aData.looseBVarRange + let hash := mixHash fData aData + let fData : UInt64 := fData + let aData : UInt64 := aData + assert! looseBVarRange ≤ (Nat.pow 2 20 - 1).toUInt32 + (fData ||| aData) &&& (15 : UInt64) <<< (40 : UInt64) ||| + hash.toUInt32.toUInt64 ||| + approxDepth.toUInt64 <<< (32 : UInt64) ||| + looseBVarRange.toUInt64 <<< (44 : UInt64) + +/-- This exists only for the bit-twiddling proofs, it shouldn't appear +in the main results, which use the functions below instead -/ +axiom mkAppData_eq : @mkAppData = @mkAppData' + +def looseBVarRange' : Expr → Nat + | .bvar i => i + 1 + | .const .. + | .sort _ + | .fvar _ + | .mvar _ + | .lit _ => 0 + | .mdata _ e + | .proj _ _ e => e.looseBVarRange' + | .app e1 e2 => max e1.looseBVarRange' e2.looseBVarRange' + | .lam _ e1 e2 _ + | .forallE _ e1 e2 _ => max e1.looseBVarRange' (e2.looseBVarRange' - 1) + | .letE _ e1 e2 e3 _ => max (max e1.looseBVarRange' e2.looseBVarRange') (e3.looseBVarRange' - 1) + +/-- This was false prior to the fix of lean4#8554; it should now be provable +using `mkData_eq` and friends, but this has not been done yet -/ +@[simp] axiom looseBVarRange_eq (e : Expr) : e.looseBVarRange = e.looseBVarRange' + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom replace_eq (e : Expr) (f) : e.replace f = e.replaceNoCache f + +def liftLooseBVars' (e : @& Expr) (s d : @& Nat) : Expr := + match e with + | .bvar i => .bvar (if i < s then i else i + d) + | .mdata m e => .mdata m (liftLooseBVars' e s d) + | .proj n i e => .proj n i (liftLooseBVars' e s d) + | .app f a => .app (liftLooseBVars' f s d) (liftLooseBVars' a s d) + | .lam n t b bi => .lam n (liftLooseBVars' t s d) (liftLooseBVars' b (s+1) d) bi + | .forallE n t b bi => .forallE n (liftLooseBVars' t s d) (liftLooseBVars' b (s+1) d) bi + | .letE n t v b bi => + .letE n (liftLooseBVars' t s d) (liftLooseBVars' v s d) (liftLooseBVars' b (s+1) d) bi + | e@(.const ..) + | e@(.sort _) + | e@(.fvar _) + | e@(.mvar _) + | e@(.lit _) => e + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom liftLooseBVars_eq (e : Expr) (s d) : e.liftLooseBVars s d = e.liftLooseBVars' s d + +def lowerLooseBVars' (e : @& Expr) (s d : @& Nat) : Expr := + if s < d then e else + match e with + | .bvar i => .bvar (if i < s then i else i - d) + | .mdata m e => .mdata m (lowerLooseBVars' e s d) + | .proj n i e => .proj n i (lowerLooseBVars' e s d) + | .app f a => .app (lowerLooseBVars' f s d) (lowerLooseBVars' a s d) + | .lam n t b bi => .lam n (lowerLooseBVars' t s d) (lowerLooseBVars' b (s+1) d) bi + | .forallE n t b bi => .forallE n (lowerLooseBVars' t s d) (lowerLooseBVars' b (s+1) d) bi + | .letE n t v b bi => + .letE n (lowerLooseBVars' t s d) (lowerLooseBVars' v s d) (lowerLooseBVars' b (s+1) d) bi + | e@(.const ..) + | e@(.sort _) + | e@(.fvar _) + | e@(.mvar _) + | e@(.lit _) => e + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom lowerLooseBVars_eq (e : Expr) (s d) : e.lowerLooseBVars s d = e.lowerLooseBVars' s d + +def instantiate1' (e : Expr) (subst : Expr) (d := 0) : Expr := + match e with + | .bvar i => if i < d then e else if i = d then subst.liftLooseBVars' 0 d else .bvar (i - 1) + | .mdata m e => .mdata m (instantiate1' e subst d) + | .proj s i e => .proj s i (instantiate1' e subst d) + | .app f a => .app (instantiate1' f subst d) (instantiate1' a subst d) + | .lam n t b bi => .lam n (instantiate1' t subst d) (instantiate1' b subst (d+1)) bi + | .forallE n t b bi => .forallE n (instantiate1' t subst d) (instantiate1' b subst (d+1)) bi + | .letE n t v b bi => + .letE n (instantiate1' t subst d) (instantiate1' v subst d) (instantiate1' b subst (d+1)) bi + | .const .. + | .sort _ + | .fvar _ + | .mvar _ + | .lit _ => e + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom instantiate1_eq (e : Expr) (subst) : e.instantiate1 subst = e.instantiate1' subst + +@[simp] def instantiateList : Expr → List Expr → (k :_:= 0) → Expr + | e, [], _ => e + | e, a :: as, k => instantiateList (instantiate1' e a k) as k + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom instantiate_eq (e : Expr) (subst) : + e.instantiate subst = e.instantiateList subst.toList + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom instantiateRev_eq (e : Expr) (subst) : + e.instantiateRev subst = e.instantiate subst.reverse + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom instantiateRange_eq (e : Expr) (subst) : + e.instantiateRange start stop subst = e.instantiate (subst.extract start stop) + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom instantiateRevRange_eq (e : Expr) (subst) : + e.instantiateRevRange start stop subst = e.instantiateRev (subst.extract start stop) + +def abstract1 (v : FVarId) : Expr → (k :_:= 0) → Expr + | .bvar i, d => .bvar (if i < d then i else i + 1) + | e@(.fvar v'), d => if v == v' then .bvar d else e + | .mdata m e, d => .mdata m (abstract1 v e d) + | .proj s i e, d => .proj s i (abstract1 v e d) + | .app f a, d => .app (abstract1 v f d) (abstract1 v a d) + | .lam n t b bi, d => .lam n (abstract1 v t d) (abstract1 v b (d+1)) bi + | .forallE n t b bi, d => .forallE n (abstract1 v t d) (abstract1 v b (d+1)) bi + | .letE n t val b bi, d => + .letE n (abstract1 v t d) (abstract1 v val d) (abstract1 v b (d+1)) bi + | e@(.const ..), _ + | e@(.sort _), _ + | e@(.mvar _), _ + | e@(.lit _), _ => e + +@[simp] def abstractList : Expr → List FVarId → (k :_:= 0) → Expr + | e, [], _ => e + | e, a :: as, k => abstractList (abstract1 a e k) as k + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom abstract_eq (e : Expr) (xs : List FVarId) : + e.abstract ⟨xs.map .fvar⟩ = e.abstractList xs + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom abstractRange_eq (e : Expr) (n : Nat) (xs : Array Expr) : + e.abstractRange n xs = e.abstract (xs.extract 0 n) + +def hasLooseBVar' : (e : @& Expr) → (bvarIdx : @& Nat) → Bool + | .bvar i, d => i = d + | .mdata _ e, d + | .proj _ _ e, d => hasLooseBVar' e d + | .app f a, d => hasLooseBVar' f d || hasLooseBVar' a d + | .lam _ t b _, d + | .forallE _ t b _, d => hasLooseBVar' t d || hasLooseBVar' b (d+1) + | .letE _ t v b _, d => hasLooseBVar' t d || hasLooseBVar' v d || hasLooseBVar' b (d+1) + | .const .., _ + | .sort _, _ + | .fvar _, _ + | .mvar _, _ + | .lit _, _ => false + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom hasLooseBVar_eq (e : Expr) (n : Nat) : e.hasLooseBVar n = e.hasLooseBVar' n + +def eqv' : (e1 e2 : Expr) → (strict : Bool := false) → Bool + | .bvar i, .bvar i', _ + | .lit i, .lit i', _ + | .mvar i, .mvar i', _ + | .fvar i, .fvar i', _ + | .sort i, .sort i', _ => i == i' + | .mdata d e, .mdata d' e', st => e.eqv' e' st && d.entries == d'.entries + | .proj s i e, .proj s' i' e', st => e.eqv' e' st && s == s' && i == i' + | .const n ls, .const n' ls', _ => n == n' && ls == ls' + | .app f a, .app f' a', st => f.eqv' f' st && a.eqv' a' st + | .lam n t b bi, .lam n' t' b' bi', st + | .forallE n t b bi, .forallE n' t' b' bi', st => + t.eqv' t' st && b.eqv' b' st && (!st || (n == n' && bi == bi')) + | .letE n t v b nd, .letE n' t' v' b' nd', st => + t.eqv' t' st && v.eqv' v' st && b.eqv' b' st && nd == nd' && (!st || n == n') + | _, _, _ => false + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom eqv_eq (e1 e2 : Expr) : e1.eqv e2 = e1.eqv' e2 + +/-- This could be an `@[implemented_by]` -/ +@[simp] axiom equal_eq (e1 e2 : Expr) : e1.equal e2 = e1.eqv' e2 (strict := true) + +end Expr diff --git a/Ix/Theory/Named/Verify/Environment/Basic.lean b/Ix/Theory/Named/Verify/Environment/Basic.lean new file mode 100644 index 000000000..3166422c0 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/Basic.lean @@ -0,0 +1,555 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.LocalContext +import Ix.Theory.Named.Typing.EnvLemmas + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +theorem ConstantInfo.hasValue_eq (ci : ConstantInfo) : ci.hasValue = ci.value?.isSome := by + cases ci <;> rfl + +theorem ConstantInfo.value!_eq (ci : ConstantInfo) : ci.value! = ci.value?.get! := by + cases ci <;> simp [ConstantInfo.value?, ConstantInfo.value!] + +def _root_.Lean.ConstantInfo.safety (ci : ConstantInfo) : DefinitionSafety := + if ci.isUnsafe then .unsafe else if ci.isPartial then .partial else .safe + +variable (safety : DefinitionSafety) (env : VEnv) in +def TrConstant (ci : ConstantInfo) (ci' : VConstant) : Prop := + safety ≤ ci.safety ∧ ci.levelParams.length = ci'.uvars ∧ + TrExprS env ci.levelParams [] ci.type ci'.type + +variable (safety : DefinitionSafety) (env : VEnv) in +def TrConstVal (ci : ConstantInfo) (ci' : VConstVal) : Prop := + TrConstant safety env ci ci'.toVConstant ∧ ci.name = ci'.name + +variable (safety : DefinitionSafety) (env : VEnv) in +def TrDefVal (ci : ConstantInfo) (ci' : VDefVal) : Prop := + TrConstVal safety env ci ci'.toVConstVal ∧ + TrExprS env ci.levelParams [] (ci.value! (allowOpaque := true)) ci'.value + +/-- The step an abstract environment takes when `ci`, modelled by `ci'`, is added. + +At safety levels where the declaration is visible the constant is added; where it is not, the +environment is unchanged, matching `TrEnv'.ignore`. Stating this rather than just `venv ≤ venv'` +is what lets a caller see *which* constant a step added. -/ +def VEnv.AddConst (venv : VEnv) (safety : DefinitionSafety) (ci : ConstantInfo) + (ci' : VConstant) (venv' : VEnv) : Prop := + if safety ≤ ci.safety then + TrConstant safety venv ci ci' ∧ ci'.WF venv ∧ venv.addConst ci.name ci' = some venv' + else + venv' = venv + +theorem VEnv.AddConst.le {venv venv' : VEnv} {ci ci'} + (H : VEnv.AddConst venv safety ci ci' venv') : venv ≤ venv' := by + unfold VEnv.AddConst at H; split at H + · exact addConst_le H.2.2 + · exact H ▸ VEnv.LE.rfl + +/-- As `VEnv.AddConst`, for a definition: the constant is added and then its defining equation, +matching `TrEnv'.defn`. -/ +def VEnv.AddDef (venv : VEnv) (safety : DefinitionSafety) (ci : ConstantInfo) + (ci' : VDefVal) (venv' : VEnv) : Prop := + if safety ≤ ci.safety then + ∃ base, TrDefVal safety venv ci ci' ∧ ci'.WF venv ∧ + venv.addConst ci.name ci'.toVConstant = some base ∧ + venv' = base.addDefEq ci'.toDefEq + else + venv' = venv + +theorem VEnv.AddDef.le {venv venv' : VEnv} {ci ci'} + (H : VEnv.AddDef venv safety ci ci' venv') : venv ≤ venv' := by + unfold VEnv.AddDef at H; split at H + · obtain ⟨base, _, _, hadd, rfl⟩ := H + exact (addConst_le hadd).trans (VEnv.addDefEq_le ..) + · exact H ▸ VEnv.LE.rfl + +def AddQuot1 (name : Name) (kind : QuotKind) (ci' : VConstant) (P : ConstMap → VEnv → Prop) + (m : ConstMap) (env : VEnv) : Prop := + ∃ levelParams type env', + let ci := .quotInfo { name, kind, levelParams, type } + TrConstant .safe env ci ci' ∧ + m.find? name = none ∧ + env.addConst name ci' = some env' ∧ + P (m.insert name ci) env' + +theorem AddQuot1.to_addQuot + (H1 : ∀ m env, P m env → f env = some env') + (m env) (H : AddQuot1 name kind ci' P m env) : + env.addConst name ci' >>= f = some env' := by + let ⟨_, _, _, h1, _, h2, h3⟩ := H + simpa using ⟨_, h2, H1 _ _ h3⟩ + +theorem AddQuot1.le + (H1 : ∀ m env, P m env → env ≤ env₀) + (m env) (H : AddQuot1 name kind ci' P m env) : env ≤ env₀ := + let ⟨_, _, _, _, _, h2, h3⟩ := H + .trans (VEnv.addConst_le h2) (H1 _ _ h3) + +def AddQuot (m₁ m₂ : ConstMap) (env₁ env₂ : VEnv) : Prop := + AddQuot1 ``Quot .type quotConst (m := m₁) (env := env₁) <| + AddQuot1 ``Quot.mk .ctor quotMkConst <| + AddQuot1 ``Quot.lift .lift quotLiftConst <| + AddQuot1 ``Quot.ind .ind quotIndConst (· = m₂ ∧ ·.addDefEq quotDefEq = env₂) + +nonrec theorem AddQuot.to_addQuot (H : AddQuot m₁ m₂ env₁ env₂) : env₁.addQuot = some env₂ := + open AddQuot1 in (to_addQuot <| to_addQuot <| to_addQuot <| to_addQuot (by simp)) _ _ H + +nonrec theorem AddQuot.le (H : AddQuot m₁ m₂ env₁ env₂) : env₁ ≤ env₂ := + open AddQuot1 in (le <| le <| le <| le fun _ _ h => h.2 ▸ VEnv.addDefEq_le) _ _ H + +/-! ## Inductive-environment alignment -/ + +/-- The three kinds of constants emitted by an inductive declaration. The +role is tracked explicitly so an alignment witness cannot stand in a +definition or axiom where the kernel emits inductive metadata. -/ +inductive InductConstantKind where + | induct + | ctor + | recursor + +def InductConstantKind.Matches : InductConstantKind → ConstantInfo → Prop + | .induct, .inductInfo _ => True + | .ctor, .ctorInfo _ => True + | .recursor, .recInfo _ => True + | _, _ => False + +theorem InductConstantKind.Matches.value?_eq_none + {kind : InductConstantKind} {ci : ConstantInfo} + (H : InductConstantKind.Matches kind ci) : ci.value? = none := by + cases kind <;> cases ci <;> simp_all [InductConstantKind.Matches, ConstantInfo.value?] + +/-- One insertion shared by the implementation `ConstMap` and Theory `VEnv`. +The translated constant is checked in the Theory environment immediately +before insertion. -/ +structure AddInductConstant (kind : InductConstantKind) + (m₁ : ConstMap) (env₁ : VEnv) (ci' : VConstVal) + (m₂ : ConstMap) (env₂ : VEnv) where + info : ConstantInfo + kind_eq : kind.Matches info + tr : TrConstVal .safe env₁ info ci' + map_fresh : m₁.find? ci'.name = none + env_add : env₁.addConst ci'.name ci'.toVConstant = some env₂ + map_add : m₂ = m₁.insert ci'.name info + +/-- List-fold alignment for the constructor constants of a block. -/ +inductive AddInductConstants (kind : InductConstantKind) : + ConstMap → VEnv → List VConstVal → ConstMap → VEnv → Type where + | nil : AddInductConstants kind m env [] m env + | cons : + AddInductConstant kind m₁ env₁ ci m₂ env₂ → + AddInductConstants kind m₂ env₂ cis m₃ env₃ → + AddInductConstants kind m₁ env₁ (ci :: cis) m₃ env₃ + +/-- A reusable witness for the defeq tail of an environment transaction. -/ +structure AddDefEqs (env₁ : VEnv) (dfs : List VDefEq) (env₂ : VEnv) : Prop where + fold_eq : dfs.foldl VEnv.addDefEq env₁ = env₂ + +/-- The generated recursor represented as a named Theory constant. -/ +def inductRecVal (decl : VInductDecl) (ty : VInductiveType) : VConstVal := + ⟨VInductDecl.recConstRec decl.uvars ty.name decl.nparams ty, .str ty.name "rec"⟩ + +/-- The exact mixed recursor represented as a named Theory constant. -/ +def inductGenerationRecVal {decl : VInductDecl} + (generation : decl.GenerationChecked) : VConstVal := + ⟨generation.recursor, .str generation.block.sourceType.name "rec"⟩ + +/-- The implementation recursor metadata carries the same K-like reduction +flag retained by Theory generation. Keeping this separate from `TrConstant` +prevents a type-correct recursor with the wrong reduction behavior from +satisfying an inductive alignment trace. -/ +def RecursorKMatches (info : ConstantInfo) (kTarget : Bool) : Prop := + match info with + | .recInfo rec => rec.k = kTarget + | _ => False + +instance (info : ConstantInfo) (kTarget : Bool) : + Decidable (RecursorKMatches info kTarget) := by + cases info <;> simp [RecursorKMatches] <;> infer_instance + +/-- Data-bearing trace of a complete normalized inductive transaction: one +`inductInfo`, the constructor `ctorInfo`s in declaration order, one `recInfo`, +and finally the generated Theory iota equations. The retained generation +certificate owns both the raw declaration inserted into the Theory environment +and the checked normalization view used to generate the recursor and rules. -/ +structure AddInductTrace (m₁ : ConstMap) (env₁ : VEnv) (decl : VInductDecl) + (m₂ : ConstMap) (env₂ : VEnv) where + generation : decl.GenerationChecked + generation_wf : generation.WF env₁ + typeMap : ConstMap + typeEnv : VEnv + ctorMap : ConstMap + ctorEnv : VEnv + recEnv : VEnv + addType : AddInductConstant .induct m₁ env₁ + generation.block.sourceType.toVConstVal typeMap typeEnv + addCtors : AddInductConstants .ctor typeMap typeEnv + generation.block.sourceType.ctors ctorMap ctorEnv + addRec : AddInductConstant .recursor ctorMap ctorEnv + (inductGenerationRecVal generation) m₂ recEnv + recK : RecursorKMatches addRec.info generation.kTarget + addRules : AddDefEqs recEnv generation.generatedRules env₂ + +/-- Proposition-valued environment alignment, preserving the public shape of +the original placeholder while hiding the intermediate transaction states. -/ +def AddInduct (m₁ : ConstMap) (env₁ : VEnv) (decl : VInductDecl) + (m₂ : ConstMap) (env₂ : VEnv) : Prop := + Nonempty (AddInductTrace m₁ env₁ decl m₂ env₂) + +/-- Every implementation recursor stored by a block replay retains the +K-like flag computed by the block generator. -/ +def RecursorMapKMatches (m : ConstMap) (recursors : List VConstVal) + (kTarget : Bool) : Prop := + ∀ recursor ∈ recursors, ∃ info, + m.find? recursor.name = some info ∧ RecursorKMatches info kTarget + +/-- Data-bearing alignment trace for a complete mutual inductive block. +Families, globally flattened constructors, and recursors are each inserted +as a list phase, followed only after all recursors exist by the flattened +rule phase. -/ +structure AddInductBlockTrace + (m₁ : ConstMap) (env₁ : VEnv) (decl : VInductDecl) + (m₂ : ConstMap) (env₂ : VEnv) where + generation : decl.BlockGenerationChecked + blockEnv : VEnv + generation_wf : generation.WF env₁ blockEnv + typeMap : ConstMap + typeEnv : VEnv + ctorMap : ConstMap + ctorEnv : VEnv + recEnv : VEnv + addTypes : AddInductConstants .induct m₁ env₁ + decl.blockTypeConstants typeMap typeEnv + addCtors : AddInductConstants .ctor typeMap typeEnv + decl.blockConstructorConstants ctorMap ctorEnv + addRecs : AddInductConstants .recursor ctorMap ctorEnv + generation.recursors m₂ recEnv + recK : RecursorMapKMatches m₂ generation.recursors generation.kTarget + addRules : AddDefEqs recEnv generation.generatedRules env₂ + +/-- Proposition-valued alignment for a complete mutual block. -/ +def AddInductBlock (m₁ : ConstMap) (env₁ : VEnv) (decl : VInductDecl) + (m₂ : ConstMap) (env₂ : VEnv) : Prop := + Nonempty (AddInductBlockTrace m₁ env₁ decl m₂ env₂) + +/-- Data-bearing alignment trace for a nested inductive declaration: the +source families and constructors are the stored payload, followed by the +restored recursors and restored rules. The implementation map receives +only restored metadata; no auxiliary constant appears in either the map or +the Theory environment. -/ +structure AddInductNestedTrace + (m₁ : ConstMap) (env₁ : VEnv) (decl : VInductDecl) + (m₂ : ConstMap) (env₂ : VEnv) where + nested : decl.NestedBlockChecked + nested_wf : nested.WF env₁ + typeMap : ConstMap + typeEnv : VEnv + ctorMap : ConstMap + ctorEnv : VEnv + recEnv : VEnv + addTypes : AddInductConstants .induct m₁ env₁ + decl.blockTypeConstants typeMap typeEnv + addCtors : AddInductConstants .ctor typeMap typeEnv + decl.blockConstructorConstants ctorMap ctorEnv + addRecs : AddInductConstants .recursor ctorMap ctorEnv + nested.recursors m₂ recEnv + recK : RecursorMapKMatches m₂ nested.recursors nested.generation.kTarget + addRules : AddDefEqs recEnv nested.generatedRules env₂ + +/-- Proposition-valued alignment for a nested declaration. -/ +def AddInductNested (m₁ : ConstMap) (env₁ : VEnv) (decl : VInductDecl) + (m₂ : ConstMap) (env₂ : VEnv) : Prop := + Nonempty (AddInductNestedTrace m₁ env₁ decl m₂ env₂) + +theorem AddInductConstants.to_foldlM : + AddInductConstants kind m₁ env₁ cis m₂ env₂ → + List.foldlM (fun env (ci : VConstVal) => env.addConst ci.name ci.toVConstant) env₁ cis = + some env₂ + | .nil => rfl + | .cons h hrest => by + rw [List.foldlM_cons, h.env_add] + exact hrest.to_foldlM + +theorem AddInductConstant.fresh + (H : AddInductConstant kind m₁ env₁ ci m₂ env₂) : env₁.constants ci.name = none := + VEnv.addConst_fresh H.env_add + +theorem AddInductConstant.lookup + (H : AddInductConstant kind m₁ env₁ ci m₂ env₂) : + env₂.constants ci.name = some ci.toVConstant := + VEnv.addConst_self H.env_add + +theorem AddInductConstant.le + (H : AddInductConstant kind m₁ env₁ ci m₂ env₂) : env₁ ≤ env₂ := + VEnv.addConst_le H.env_add + +theorem AddInductConstants.le : + AddInductConstants kind m₁ env₁ cis m₂ env₂ → env₁ ≤ env₂ + | .nil => .rfl + | .cons h hrest => h.le.trans hrest.le + +theorem AddInductConstants.lookup : + (H : AddInductConstants kind m₁ env₁ cis m₂ env₂) → + ∀ ci ∈ cis, env₂.constants ci.name = some ci.toVConstant + | .nil, _, hmem => nomatch hmem + | .cons h hrest, ci, hmem => by + rcases List.mem_cons.1 hmem with rfl | hmem + · exact hrest.le.constants h.lookup + · exact hrest.lookup ci hmem + +theorem AddInductConstants.fresh : + (H : AddInductConstants kind m₁ env₁ cis m₂ env₂) → + ∀ ci ∈ cis, env₁.constants ci.name = none + | .nil, _, hmem => nomatch hmem + | .cons h hrest, ci, hmem => by + rcases List.mem_cons.1 hmem with rfl | hmem + · exact h.fresh + · exact h.le.constants_none (hrest.fresh ci hmem) + +theorem AddDefEqs.to_add (H : AddDefEqs env₁ dfs env₂) : + dfs.foldl VEnv.addDefEq env₁ = env₂ := H.fold_eq + +theorem AddDefEqs.le (H : AddDefEqs env₁ dfs env₂) : env₁ ≤ env₂ := by + rw [← H.fold_eq] + exact (VInductDecl.rulesFold_spec dfs env₁).1 + +theorem AddDefEqs.lookup (H : AddDefEqs env₁ dfs env₂) + (hdf : df ∈ dfs) : env₂.defeqs df := by + rw [← H.fold_eq] + exact (VInductDecl.rulesFold_spec dfs env₁).2 df hdf + +theorem AddInductTrace.to_addInductGeneration + (H : AddInductTrace m₁ env₁ decl m₂ env₂) : + env₁.addInductGeneration H.generation = some env₂ := by + have hrec : + H.ctorEnv.addConst + (.str H.generation.block.sourceType.name "rec") + H.generation.recursor = some H.recEnv := by + simpa [inductGenerationRecVal] using H.addRec.env_add + simp [VEnv.addInductGeneration, H.addType.env_add, + H.addCtors.to_foldlM, hrec, H.addRules.to_add] + +theorem AddInductBlockTrace.to_addInductBlockGeneration + (H : AddInductBlockTrace m₁ env₁ decl m₂ env₂) : + env₁.addInductBlockGeneration H.generation = some env₂ := by + simp [VEnv.addInductBlockGeneration, H.addTypes.to_foldlM, + H.addCtors.to_foldlM, H.addRecs.to_foldlM, H.addRules.to_add] + +theorem AddInductNestedTrace.to_addInductNested + (H : AddInductNestedTrace m₁ env₁ decl m₂ env₂) : + env₁.addInductNested H.nested = some env₂ := by + simp [VEnv.addInductNested, H.addTypes.to_foldlM, + H.addCtors.to_foldlM, H.addRecs.to_foldlM, H.addRules.to_add] + +/-- Recover the exact certified normalized Theory transaction represented by +an implementation metadata replay. This replaces the old, false-for-aliases +claim that every replay must pass the identity-only `VEnv.addInduct` wrapper. -/ +nonrec theorem AddInduct.to_addInduct + (H : AddInduct m₁ env₁ decl m₂ env₂) : + ∃ generation : decl.GenerationChecked, + generation.WF env₁ ∧ + env₁.addInductGeneration generation = some env₂ := by + rcases H with ⟨H⟩ + exact ⟨H.generation, H.generation_wf, H.to_addInductGeneration⟩ + +nonrec theorem AddInduct.le (H : AddInduct m₁ env₁ decl m₂ env₂) : env₁ ≤ env₂ := by + obtain ⟨generation, -, hadd⟩ := H.to_addInduct + rcases VEnv.addInductGeneration_trace hadd with ⟨trace⟩ + exact trace.le + +/-- Recover the exact block-wide Theory transaction represented by an +implementation metadata replay. -/ +theorem AddInductBlock.to_addInductBlock + (H : AddInductBlock m₁ env₁ decl m₂ env₂) : + ∃ (generation : decl.BlockGenerationChecked) (blockEnv : VEnv), + generation.WF env₁ blockEnv ∧ + env₁.addInductBlockGeneration generation = some env₂ := by + rcases H with ⟨H⟩ + exact ⟨H.generation, H.blockEnv, H.generation_wf, + H.to_addInductBlockGeneration⟩ + +theorem AddInductBlock.le + (H : AddInductBlock m₁ env₁ decl m₂ env₂) : env₁ ≤ env₂ := by + obtain ⟨generation, -, -, hadd⟩ := H.to_addInductBlock + rcases VEnv.addInductBlockGeneration_trace hadd with ⟨trace⟩ + exact trace.le + +/-- Recover the exact nested Theory transaction represented by an +implementation metadata replay. -/ +theorem AddInductNested.to_addInductNested + (H : AddInductNested m₁ env₁ decl m₂ env₂) : + ∃ nested : decl.NestedBlockChecked, + nested.WF env₁ ∧ env₁.addInductNested nested = some env₂ := by + rcases H with ⟨H⟩ + exact ⟨H.nested, H.nested_wf, H.to_addInductNested⟩ + +theorem AddInductNested.le + (H : AddInductNested m₁ env₁ decl m₂ env₂) : env₁ ≤ env₂ := by + obtain ⟨nested, -, hadd⟩ := H.to_addInductNested + exact VEnv.addInductNested_le hadd + +/- The projection relation is now a concrete Theory proposition, so merely +mentioning `TrExprS` no longer contaminates these projection-free roots with +the deferred structural-law sorries. -/ +#guard_named_axioms Ix.Theory.Named.AddInductTrace.to_addInductGeneration [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInduct.to_addInduct [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInduct.le [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductBlockTrace.to_addInductBlockGeneration [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductBlock.to_addInductBlock [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductBlock.le [propext, Classical.choice, Quot.sound] + +/-- Insert a whole block of definitions into the constant map. -/ +def insertDefs (C : ConstMap) (cis : List DefinitionVal) : ConstMap := + cis.foldl (fun C ci => C.insert ci.name (.defnInfo ci)) C + +variable (safety : DefinitionSafety) (env env' : VEnv) in +/-- Translation data for a mutual block: the headers are translated against the environment +before the block is added, the values against the environment that already has every constant +of the block, mirroring the kernel adding them all as axioms first. -/ +def TrDefBlock (cis : List DefinitionVal) (cis' : List VDefVal) : Prop := + List.Forall₂ (fun ci ci' => + TrConstVal safety env (.defnInfo ci) ci'.toVConstVal ∧ + TrExprS env' ci.levelParams [] ci.value ci'.value) cis cis' + +variable (safety : DefinitionSafety) in +inductive TrEnv' : ConstMap → Bool → VEnv → Prop where + | empty : TrEnv' {} false .empty + | ignore : + C.find? ci.name = none → ¬safety ≤ ci.safety → + TrEnv' C Q env → + TrEnv' (C.insert ci.name ci) Q env + | axiom : + TrConstant safety env (.axiomInfo ci) ci' → + C.find? ci.name = none → ci'.WF env → + env.addConst ci.name ci' = some env' → + TrEnv' C Q env → + TrEnv' (C.insert ci.name (.axiomInfo ci)) Q env' + | defn {ci' : VDefVal} : + TrDefVal safety env (.defnInfo ci) ci' → + C.find? ci.name = none → ci'.WF env → + env.addConst ci.name ci'.toVConstant = some env' → + TrEnv' C Q env → + TrEnv' (C.insert ci.name (.defnInfo ci)) Q (env'.addDefEq ci'.toDefEq) + /-- A mutual block, and an unsafe definition as the one-element case. -/ + | mutualDef {cis : List DefinitionVal} {cis' : List VDefVal} : + TrDefBlock safety env env' cis cis' → + -- the block's names are distinct; `addMutual` checks this, as does lean4#14632 + (cis.map (·.name)).Nodup → + (∀ ci ∈ cis, C.find? ci.name = none) → + (∀ ci' ∈ cis', ci'.toVConstant.WF env) → + env.addConsts cis' = some env' → + (∀ ci' ∈ cis', ci'.WF env') → + TrEnv' C Q env → + TrEnv' (insertDefs C cis) Q (env'.addDefEqs cis') + | thm {ci' : VDefVal} : + TrDefVal safety env (.thmInfo ci) ci' → + C.find? ci.name = none → ci'.WF env → + env.HasType ci'.uvars [] ci'.type (.sort .zero) → + env.addConst ci.name ci'.toVConstant = some env' → + TrEnv' C Q env → + TrEnv' (C.insert ci.name (.thmInfo ci)) Q env' + | opaque {ci' : VDefVal} : + TrDefVal safety env (.opaqueInfo ci) ci' → + C.find? ci.name = none → ci'.WF env → + env.addConst ci.name ci'.toVConstant = some env' → + TrEnv' C Q env → + TrEnv' (C.insert ci.name (.opaqueInfo ci)) Q env' + | quot : + env.QuotReady → + AddQuot C C' env env' → + TrEnv' C false env → + TrEnv' C' true env' + /-- Internal kernel-checking stage for one inductive metadata constant. + Lean checks a family and its constructors in environments that exist before + the complete block transaction. Keeping this stage explicit lets the + verified WHNF/defeq checker run in exactly those environments; final + environment replay continues to use the atomic `induct` constructor below. + -/ + | inductStaging {ci' : VConstVal} : + AddInductConstant kind C env ci' C' env' → + ci'.toVConstant.WF env → + TrEnv' C Q env → + TrEnv' C' Q env' + | induct : + AddInduct C env decl C' env' → + TrEnv' C Q env → + TrEnv' C' Q env' + | inductBlock : + AddInductBlock C env decl C' env' → + TrEnv' C Q env → + TrEnv' C' Q env' + | inductNested : + AddInductNested C env decl C' env' → + TrEnv' C Q env → + TrEnv' C' Q env' + /-- Register a Theory structure-eta descriptor without changing the host + constant map. Host eligibility and exact view alignment are retained by + `StructureEtaArtifact`; this history step records only the checked Theory + capability and its subject-reduction certificate. -/ + | structEta : + rule.WF env → + TrEnv' C Q env → + TrEnv' C Q (env.addStructEta rule) + +def TrEnv (safety : DefinitionSafety) (env : Environment) (venv : VEnv) : Prop := + TrEnv' safety env.constants env.quotInit venv + +theorem TrEnv'.wf (H : TrEnv' safety C Q venv) : venv.WF := by + induction H with + | empty => exact ⟨_, .empty⟩ + | ignore _ _ _ ih => exact ih + | «axiom» _ _ h1 h2 _ ih => + have ⟨_, H⟩ := ih + exact ⟨_, H.decl <| .axiom (ci := ⟨_, _⟩) h1 h2⟩ + | defn h1 _ h2 h3 _ ih => + have ⟨_, H⟩ := ih + have := h1.1.2; dsimp [ConstantInfo.name, ConstantInfo.toConstantVal] at this + exact ⟨_, H.decl <| .def h2 (this ▸ h3)⟩ + | mutualDef _ _ _ h2 h3 h4 _ ih => + have ⟨_, H⟩ := ih + exact ⟨_, H.decl <| .mutualDef h2 h3 h4⟩ + | thm h1 _ h2 h3 h4 _ ih => + have ⟨_, H⟩ := ih + have hn := h1.1.2 + dsimp [ConstantInfo.name, ConstantInfo.toConstantVal] at hn + exact ⟨_, (H.decl (.example h2)).decl (.axiom ⟨_, h3⟩ (hn ▸ h4))⟩ + | «opaque» h1 _ h2 h3 _ ih => + have ⟨_, H⟩ := ih + have := h1.1.2; dsimp [ConstantInfo.name, ConstantInfo.toConstantVal] at this + exact ⟨_, H.decl <| .opaque h2 (this ▸ h3)⟩ + | quot h1 h2 _ ih => + have ⟨_, H⟩ := ih + exact ⟨_, H.decl <| .quot h1 h2.to_addQuot⟩ + | inductStaging h1 h2 _ ih => + have ⟨_, H⟩ := ih + exact ⟨_, H.decl <| .axiom h2 h1.env_add⟩ + | induct h1 _ ih => + have ⟨_, H⟩ := ih + obtain ⟨generation, hgen, hadd⟩ := h1.to_addInduct + exact ⟨_, H.decl <| .induct hgen hadd⟩ + | inductBlock h1 _ ih => + have ⟨_, H⟩ := ih + obtain ⟨generation, blockEnv, hgen, hadd⟩ := + h1.to_addInductBlock + exact ⟨_, H.decl <| .inductBlock (blockEnv := blockEnv) hgen hadd⟩ + | inductNested h1 _ ih => + have ⟨_, H⟩ := ih + obtain ⟨nested, hwf, hadd⟩ := h1.to_addInductNested + exact ⟨_, H.decl <| .inductNested hwf hadd⟩ + | structEta hrule _ ih => + have ⟨_, H⟩ := ih + exact ⟨_, H.structEta hrule⟩ + +#guard_named_axioms Ix.Theory.Named.TrEnv'.wf [propext, Classical.choice, Quot.sound] diff --git a/Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean b/Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean new file mode 100644 index 000000000..78ff92f85 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean @@ -0,0 +1,9028 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.Normalization + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +namespace AddInductive +open TypeChecker + +/-! +# Semantic interpretation of constructor validation + +This module interprets the operational trace retained by +`Inductive.ValidationTrace`. It deliberately sits above both the verified +checker and candidate normalization: validation supplies the accepted kernel +path, while normalization supplies the exact analyzer-owned Theory view. +-/ + +/-- Structural equality of kernel levels is sound after strict translation. -/ +theorem levelStructEq_ofLevel + (equal : levelStructEq lhs rhs = true) + (lhs_tr : VLevel.ofLevel Us lhs = some lhs') + (rhs_tr : VLevel.ofLevel Us rhs = some rhs') : + lhs' = rhs' := by + induction lhs generalizing rhs lhs' rhs' with + | zero => + cases rhs <;> simp_all [levelStructEq, VLevel.ofLevel] + | succ lhs ih => + cases rhs with + | succ rhs => + simp only [levelStructEq] at equal + simp only [VLevel.ofLevel, Option.bind_eq_bind] at lhs_tr rhs_tr + obtain ⟨lhs'', lhs_inner_tr, lhs'_eq⟩ := + Option.bind_eq_some_iff.mp lhs_tr + obtain ⟨rhs'', rhs_inner_tr, rhs'_eq⟩ := + Option.bind_eq_some_iff.mp rhs_tr + change some lhs''.succ = some lhs' at lhs'_eq + change some rhs''.succ = some rhs' at rhs'_eq + injection lhs'_eq with lhs'_eq + injection rhs'_eq with rhs'_eq + subst lhs' + subst rhs' + rw [ih equal lhs_inner_tr rhs_inner_tr] + | zero | max _ _ | imax _ _ | param _ | mvar _ => + simp_all [levelStructEq] + | max lhs₁ lhs₂ ih₁ ih₂ => + cases rhs with + | max rhs₁ rhs₂ => + simp only [levelStructEq, Bool.and_eq_true] at equal + simp only [VLevel.ofLevel, Option.bind_eq_bind] at lhs_tr rhs_tr + obtain ⟨lhs₁', lhs₁_tr, lhsTail⟩ := + Option.bind_eq_some_iff.mp lhs_tr + obtain ⟨lhs₂', lhs₂_tr, lhs'_eq⟩ := + Option.bind_eq_some_iff.mp lhsTail + obtain ⟨rhs₁', rhs₁_tr, rhsTail⟩ := + Option.bind_eq_some_iff.mp rhs_tr + obtain ⟨rhs₂', rhs₂_tr, rhs'_eq⟩ := + Option.bind_eq_some_iff.mp rhsTail + change some (.max lhs₁' lhs₂') = some lhs' at lhs'_eq + change some (.max rhs₁' rhs₂') = some rhs' at rhs'_eq + injection lhs'_eq with lhs'_eq + injection rhs'_eq with rhs'_eq + subst lhs' + subst rhs' + rw [ih₁ equal.1 lhs₁_tr rhs₁_tr, + ih₂ equal.2 lhs₂_tr rhs₂_tr] + | zero | succ _ | imax _ _ | param _ | mvar _ => + simp_all [levelStructEq] + | imax lhs₁ lhs₂ ih₁ ih₂ => + cases rhs with + | imax rhs₁ rhs₂ => + simp only [levelStructEq, Bool.and_eq_true] at equal + simp only [VLevel.ofLevel, Option.bind_eq_bind] at lhs_tr rhs_tr + obtain ⟨lhs₁', lhs₁_tr, lhsTail⟩ := + Option.bind_eq_some_iff.mp lhs_tr + obtain ⟨lhs₂', lhs₂_tr, lhs'_eq⟩ := + Option.bind_eq_some_iff.mp lhsTail + obtain ⟨rhs₁', rhs₁_tr, rhsTail⟩ := + Option.bind_eq_some_iff.mp rhs_tr + obtain ⟨rhs₂', rhs₂_tr, rhs'_eq⟩ := + Option.bind_eq_some_iff.mp rhsTail + change some (.imax lhs₁' lhs₂') = some lhs' at lhs'_eq + change some (.imax rhs₁' rhs₂') = some rhs' at rhs'_eq + injection lhs'_eq with lhs'_eq + injection rhs'_eq with rhs'_eq + subst lhs' + subst rhs' + rw [ih₁ equal.1 lhs₁_tr rhs₁_tr, + ih₂ equal.2 lhs₂_tr rhs₂_tr] + | zero | succ _ | max _ _ | param _ | mvar _ => + simp_all [levelStructEq] + | param lhsName => + cases rhs <;> simp_all [levelStructEq, VLevel.ofLevel] + | mvar lhsId => + simp [VLevel.ofLevel] at lhs_tr + +/-- The transparent fast path used by constructor validation implies the +Theory universe inequality required by `fieldsWF`. -/ +theorem levelStructGe_ofLevel + (greater : levelStructGe result field = true) + (result_tr : VLevel.ofLevel Us result = some result') + (field_tr : VLevel.ofLevel Us field = some field') : + field' ≤ result' := by + induction result generalizing field result' field' with + | zero => + cases field with + | zero => + change some (.zero : VLevel) = some result' at result_tr + change some (.zero : VLevel) = some field' at field_tr + injection result_tr with result_tr + injection field_tr with field_tr + subst result' + subst field' + exact VLevel.le_refl _ + | succ _ | max _ _ | imax _ _ | param _ | mvar _ => + simp_all [levelStructGe, levelStructEq] + | succ result ih => + cases field with + | zero => + change some (.zero : VLevel) = some field' at field_tr + injection field_tr with field_tr + subst field' + exact VLevel.zero_le + | succ field => + simp only [levelStructGe] at greater + simp only [VLevel.ofLevel, Option.bind_eq_bind] at result_tr field_tr + obtain ⟨result'', result_inner_tr, result'_eq⟩ := + Option.bind_eq_some_iff.mp result_tr + obtain ⟨field'', field_inner_tr, field'_eq⟩ := + Option.bind_eq_some_iff.mp field_tr + change some result''.succ = some result' at result'_eq + change some field''.succ = some field' at field'_eq + injection result'_eq with result'_eq + injection field'_eq with field'_eq + subst result' + subst field' + exact VLevel.succ_le_succ + (ih greater result_inner_tr field_inner_tr) + | max _ _ | imax _ _ | param _ | mvar _ => + have equal := levelStructEq_ofLevel (Us := Us) + (by simpa [levelStructGe] using greater) result_tr field_tr + cases equal + exact VLevel.le_refl _ + | max result₁ result₂ ih₁ ih₂ => + cases field with + | zero => + change some (.zero : VLevel) = some field' at field_tr + injection field_tr with field_tr + subst field' + exact VLevel.zero_le + | succ _ | max _ _ | imax _ _ | param _ | mvar _ => + have equal := levelStructEq_ofLevel (Us := Us) + (by simpa [levelStructGe] using greater) result_tr field_tr + cases equal + exact VLevel.le_refl _ + | imax result₁ result₂ ih₁ ih₂ => + cases field with + | zero => + change some (.zero : VLevel) = some field' at field_tr + injection field_tr with field_tr + subst field' + exact VLevel.zero_le + | succ _ | max _ _ | imax _ _ | param _ | mvar _ => + have equal := levelStructEq_ofLevel (Us := Us) + (by simpa [levelStructGe] using greater) result_tr field_tr + cases equal + exact VLevel.le_refl _ + | param resultName => + cases field with + | zero => + change some (.zero : VLevel) = some field' at field_tr + injection field_tr with field_tr + subst field' + exact VLevel.zero_le + | succ _ | max _ _ | imax _ _ | param _ | mvar _ => + have equal := levelStructEq_ofLevel (Us := Us) + (by simpa [levelStructGe] using greater) result_tr field_tr + cases equal + exact VLevel.le_refl _ + | mvar resultId => + simp [VLevel.ofLevel] at result_tr + +/-- The impredicative fallback is exact: a kernel level recognized as zero +translates to Theory's zero level. -/ +theorem ofLevel_eq_zero_of_isZero + (zero : level.isZero = true) + (level_tr : VLevel.ofLevel Us level = some level') : + level' = .zero := by + cases level <;> simp_all [Level.isZero, VLevel.ofLevel] + +/-- Executable universe comparison supported by the semantic proof. + +The structural and impredicative `Prop` branches mirror the ordinary +validator directly. A normalized non-`Prop` comparison is admitted only +when Lean's ordinary `Level.geq` decision and the verified project `geq'` +decision both succeed. The former preserves the kernel-facing acceptance +boundary; the latter supplies the semantic inequality without trusting +Lean's opaque normalizer. -/ +def constructorUniverseSemanticGe (resultLevel fieldLevel : Level) : Bool := + levelStructGe resultLevel fieldLevel || + (resultLevel.isZero || + (resultLevel.geq fieldLevel && resultLevel.geq' fieldLevel)) + +/-- Replay just the universe-bearing part of one constructor telescope. + +The traversal deliberately follows the validator's parameter substitution, +ordinary-field local contexts, annotation consumption, and recursion fuel. +Unlike `checkConstructorType`, its normalized fallback also requires the +proved project comparison above. Running this audit in addition to the +ordinary validator is therefore an executable verified intersection, not a +replacement validator and not a proof-only semantic premise. -/ +def checkConstructorUniverseSemantics (stats : InductiveStats) (t : Expr) : + M Unit := do + loop t 0 (← readThe Context).fuel.inductiveFuel +where + loop (t : Expr) (i : Nat) : Nat → M Unit + | 0 => throw .deepRecursion + | fuel + 1 => do + if let .forallE name domain body binderInfo := t then + if let some parameter := stats.params[i]? then + loop (body.instantiate1 parameter) (i + 1) fuel + else + let sortResult ← ensureType domain + unless constructorUniverseSemanticGe stats.resultLevel + sortResult.sortLevel! do + throw <| .other + "constructor universe lies outside the verified semantic subset" + withLocalDecl name binderInfo (consumeTypeAnnotations domain) fun arg => + loop (body.instantiate1 arg) (i + 1) fuel + +/-- Source-ordered universe audit for every constructor in one singleton +family. Constructor names and types come from the same indexed source list +as `ConstructorListValidationTrace`; all non-universe validation remains in +that retained ordinary trace. -/ +def checkConstructorUniverseListSemantics (stats : InductiveStats) : + List Constructor → M Unit + | [] => pure () + | constructor :: constructors => do + checkConstructorUniverseSemantics stats constructor.type + checkConstructorUniverseListSemantics stats constructors + +/-- The executable semantic decision at the exact universe node retained by +ordinary constructor validation. -/ +def ConstructorUniverseTrace.semantic + (_trace : ConstructorUniverseTrace resultLevel fieldLevel) : Bool := + constructorUniverseSemanticGe resultLevel fieldLevel + +/-- Conjunction of the semantic universe decisions in one exact constructor +telescope. Parameter and terminal nodes contribute no universe obligation. -/ +def ConstructorTypeValidationTrace.universeSemantics + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) : Bool := + match trace with + | .parameter _ _ _ _ _ _ _ _ _ _ _ _ tail => + tail.universeSemantics + | .ordinary _ _ _ _ _ _ _ _ _ _ universeTrace _ tail => + universeTrace.semantic && tail.universeSemantics + | .terminal _ _ _ _ _ _ => true + +/-- Source-ordered conjunction of every constructor telescope's semantic +universe decisions. -/ +def ConstructorListValidationTrace.universeSemantics + (trace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) : Bool := + match trace with + | .nil _ => true + | .cons _ _ _ _ _ _ typeTrace tailTrace => + typeTrace.universeSemantics && tailTrace.universeSemantics + +/-- The complete semantic-universe gate attached to one retained ordinary +constructor-validation run. -/ +def ConstructorValidationRun.universeSemantics + (validation : ConstructorValidationRun indType stats isUnsafe context) : + Bool := + validation.trace.universeSemantics + +/-- Recover the state-bearing verified-checker execution erased by the +ordinary constructor validator's `ensureType` observation. -/ +theorem ConstructorEnsureTypeStep.innerRun + (step : ConstructorEnsureTypeStep) (hvalid : step.Valid) : + ∃ state : TypeChecker.State, + TypeChecker.ensureType step.source step.context.toTypeChecker + ({} : TypeChecker.State) = .ok (step.result, state) := by + unfold ConstructorEnsureTypeStep.Valid TypeChecker.M.run at hvalid + cases hrun : TypeChecker.ensureType step.source + { env := step.context.env + lctx := step.context.lctx + safety := step.context.safety + lparams := step.context.lparams + fuel := step.context.fuel } + ({} : TypeChecker.State) with + | error err => + simp [StateT.run', Functor.map, Except.map, hrun] at hvalid + | ok pair => + rcases pair with ⟨result, state⟩ + have result_eq : result = step.result := by + simpa [StateT.run', Functor.map, Except.map, hrun] using hvalid + subst result + exact ⟨state, by simpa [Context.toTypeChecker] using hrun⟩ + +/-- Theory interpretation of the exact `ensureType` execution retained for +an ordinary constructor field. -/ +structure TypeChecker.EnsureTypeRun (env : VEnv) (Us : List Name) + (Δ : VLCtx) (source result : Expr) (source' : VExpr) where + context : VContext + venv_eq : context.venv = env + lparams_eq : context.lparams = Us + vlctx_eq : context.vlctx = Δ + state_wf : VState.WF context {} + source_tr : TrExprS env Us Δ source source' + resultLevel : Level + resultLevel' : VLevel + result_eq : result = .sort resultLevel + resultLevel_tr : VLevel.ofLevel Us resultLevel = some resultLevel' + source_type : env.HasType Us.length Δ.toCtx source' (.sort resultLevel') + run_eq : ∃ state : State, + ensureType source context.toContext ({} : State) = .ok (result, state) + +/-- Attach verified Theory meaning to one retained ordinary-field +`ensureType` step in its exact post-family context. -/ +theorem TypeChecker.EnsureTypeRun.exists_ofConstructorStep + (step : ConstructorEnsureTypeStep) (hvalid : step.Valid) + (contextRun : CandidateContextRun step.context) + (source' : VExpr) + (source_tr : contextRun.context.TrExprS step.source source') : + Nonempty (EnsureTypeRun contextRun.context.venv + contextRun.context.lparams contextRun.context.vlctx + step.source step.result source') := by + obtain ⟨state, run⟩ := step.innerRun hvalid + rw [← contextRun.context_eq] at run + obtain ⟨_, _, _, _, translated, translated_tr, u, u', result_eq, + level_tr, source_type⟩ := + (ensureType.WF source_tr) contextRun.state_wf step.result state run + have translated_def := translated_tr.uniq contextRun.context.Ewf + (.refl contextRun.context.Ewf contextRun.context.Δwf) source_tr + have source_type' := source_type.defeqU_l contextRun.context.Ewf + contextRun.context.Δwf translated_def + exact ⟨{ + context := contextRun.context + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + state_wf := contextRun.state_wf + source_tr := source_tr + resultLevel := u + resultLevel' := u' + result_eq := result_eq + resultLevel_tr := level_tr + source_type := source_type' + run_eq := ⟨state, run⟩ }⟩ + +/-! +## Exact post-family view alignment + +Constructor validation and constructor-candidate construction deliberately +allocate their ordinary-field free variables from different reader states. +The following audit therefore never compares those identifiers. It follows +the already-retained validation trace and instantiates the exact candidate +view with the *validation* parameter/field expression at each position. +Every comparison consequently happens in the real post-family local context, +while the candidate itself still owns the view being inspected. +-/ + +/-- Number of parameter/ordinary binders consumed by one exact constructor +validation trace. -/ +def ConstructorTypeValidationTrace.spineLength + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) : Nat := + match trace with + | .parameter _ _ _ _ _ _ _ _ _ _ _ _ tail => tail.spineLength + 1 + | .ordinary _ _ _ _ _ _ _ _ _ _ _ _ tail => tail.spineLength + 1 + | .terminal .. => 0 + +/-- Every local declaration entered by a retained positivity traversal uses +an identifier absent from the exact incoming local context. This is an +executable structural condition, not a semantic premise. -/ +def ConstructorPositivityTrace.freshNames + (trace : ConstructorPositivityTrace stats ctor argIdx context source fuel) : + Bool := + match trace with + | .absent .. => true + | .forallE context _ _ _ _ _ _ _ _ _ tail => + (context.lctx.find? context.freshFVarId).isNone && tail.freshNames + | .target .. => true + +def ConstructorPositivityModeTrace.freshNames + (trace : ConstructorPositivityModeTrace stats isUnsafe ctor argIdx + context source) : Bool := + match trace with + | .skipped .. => true + | .safe _ trace => trace.freshNames + +/-- One exact full-check observation together with the syntactic premise used +by the verified checker refinement. Keeping the premise at the operational +boundary avoids reconstructing free-variable membership later from binder +names or from a parallel telescope. -/ +structure ConstructorCheckedExpr (context : Context) (source : Expr) where + fvars : source.FVarsIn + (fun fv => (context.lctx.find? fv).isSome = true) + observation : CandidateCheckTypeObservation context source + +/-- Retain an already verified full-check execution together with a structural +scope proof for its exact source expression. -/ +def ConstructorCheckedExpr.ofRun + (fvars : source.FVarsIn + (fun fv => (context.lctx.find? fv).isSome = true)) + (run : CandidateCheckTypeStep.Valid ⟨context, source, inferred⟩) : + ConstructorCheckedExpr context source := + ⟨fvars, ⟨inferred, run⟩⟩ + +private theorem constructorClosed_hasMVar_false + {env : Kernel.Environment} {name : Name} {source : Expr} + (closed : env.checkNoMVarNoFVar name source = .ok ()) : + source.hasMVar = false := by + unfold Kernel.Environment.checkNoMVarNoFVar + Kernel.Environment.checkNoMVar Kernel.Environment.checkNoFVar at closed + cases hmvars : source.hasMVar + · rfl + · simp [hmvars, Bind.bind, Except.bind] at closed + +private theorem constructorClosed_hasFVar_false + {env : Kernel.Environment} {name : Name} {source : Expr} + (closed : env.checkNoMVarNoFVar name source = .ok ()) : + source.hasFVar = false := by + have hmvars := constructorClosed_hasMVar_false closed + unfold Kernel.Environment.checkNoMVarNoFVar + Kernel.Environment.checkNoMVar Kernel.Environment.checkNoFVar at closed + cases hfvars : source.hasFVar + · rfl + · simp [hmvars, hfvars, Bind.bind, Except.bind, Pure.pure, + Except.pure] at closed + +/-- Constructor metadata accepted by the validator is closed, so its retained +empty-context full-check observation directly supplies the D2 root scope. -/ +def ConstructorCheckedExpr.ofClosedRoot + {context : Context} {name : Name} {source : Expr} + (closed : context.env.checkNoMVarNoFVar name source = .ok ()) + (observation : CandidateCheckTypeObservation + context.withEmptyLocalContext source) : + ConstructorCheckedExpr context.withEmptyLocalContext source where + fvars := fvarsIn_iff.2 ⟨by + intro fv present + have empty := fvarsList_eq_nil.mpr + (constructorClosed_hasFVar_false closed) + rw [empty] at present + contradiction, + fvarsIn_iff_hasMVar.2 (constructorClosed_hasMVar_false closed)⟩ + observation := observation + +/-- Execute a full check only after confirming that every free variable of +the exact source belongs to the retained implementation context. -/ +def checkConstructorAlignedExpr (context : Context) (source : Expr) : + Except Exception (ConstructorCheckedExpr context source) := do + if hfvars : source.fvarsList.all + (fun fv => (context.lctx.find? fv).isSome) = true then + if hmvars : source.hasMVar = false then + have fvars : source.FVarsIn + (fun fv => (context.lctx.find? fv).isSome = true) := + fvarsIn_iff.2 ⟨by + intro fv hfv + have h := List.all_eq_true.mp hfvars fv hfv + exact h, + fvarsIn_iff_hasMVar.2 hmvars⟩ + let observation ← observeCandidateCheckType context source + pure ⟨fvars, observation⟩ + else + throw <| .other "constructor alignment source contains a metavariable" + else + throw <| .other "constructor alignment source escaped its local context" + +/-- Reuse an exact full-check execution to expose the successful result of +the supplemental scope-aware checker boundary. -/ +theorem checkConstructorAlignedExpr.exists_of_run + (hfvars : source.fvarsList.all + (fun fv => (context.lctx.find? fv).isSome) = true) + (hmvars : source.hasMVar = false) + (hrun : CandidateCheckTypeStep.Valid ⟨context, source, inferred⟩) : + ∃ checked : ConstructorCheckedExpr context source, + checkConstructorAlignedExpr context source = .ok checked := by + unfold checkConstructorAlignedExpr + rw [dif_pos hfvars, dif_pos hmvars] + rw [observeCandidateCheckType_of_run context source inferred hrun] + exact ⟨_, rfl⟩ + +/-- Re-executing the supplemental scope/full-check boundary reproduces any +retained successful observation. The only reconstructed fields are proofs, +so proof irrelevance identifies the executable result with the retained +value itself. -/ +theorem ConstructorCheckedExpr.check_eq + (checked : ConstructorCheckedExpr context source) : + checkConstructorAlignedExpr context source = .ok checked := by + have hfvars : source.fvarsList.all + (fun fv => (context.lctx.find? fv).isSome) = true := by + apply List.all_eq_true.mpr + intro fv present + exact (fvarsIn_iff.mp checked.fvars).1 fv present + have hmvars : source.hasMVar = false := + fvarsIn_iff_hasMVar.mp (fvarsIn_iff.mp checked.fvars).2 + unfold checkConstructorAlignedExpr + rw [dif_pos hfvars, dif_pos hmvars] + rw [observeCandidateCheckType_of_run context source + checked.observation.inferred checked.observation.valid] + cases checked + rfl + +/-- Determinism of the erased implementation run pins a retained full-check +observation to any independently proved result of that same exact check. -/ +theorem ConstructorCheckedExpr.inferred_eq_of_run + (checked : ConstructorCheckedExpr context source) + (hrun : CandidateCheckTypeStep.Valid ⟨context, source, inferred⟩) : + checked.observation.inferred = inferred := by + have retained := checked.observation.valid + unfold CandidateCheckTypeStep.Valid at retained hrun + rw [hrun] at retained + exact (Except.ok.inj retained).symm + +/-- Re-executing a retained equality observation returns that same +observation; its sole field is proof-valued. -/ +theorem CandidateIsDefEqObservation.observe_eq + (observation : CandidateIsDefEqObservation context lhs rhs) : + observeCandidateIsDefEq context lhs rhs = .ok observation := by + rw [observeCandidateIsDefEq_of_run context lhs rhs observation.valid] + +/-- The verified implementation equality checker accepts a syntactically +identical pair without inspecting or extending its success cache. -/ +theorem candidateIsDefEqRefl + (context : Context) (source : Expr) : + CandidateIsDefEqStep.Valid ⟨context, source, source⟩ := by + unfold CandidateIsDefEqStep.Valid TypeChecker.M.run TypeChecker.isDefEq + TypeChecker.RecM.run TypeChecker.Inner.isDefEq + simp [readThe, MonadReaderOf.read, ReaderT.read, ReaderT.bind, Bind.bind, + StateT.bind, Except.bind, StateT.pure, Except.pure, Pure.pure, + StateT.run', Functor.map, Except.map] + rfl + +/-- Convert the executable implementation-context scope check to the exact +Theory free-variable premise used by verified `checkType` refinement. -/ +theorem ConstructorCheckedExpr.fvarsIn + (checked : ConstructorCheckedExpr context source) + (contextRun : TypeChecker.CandidateContextRun context) : + source.FVarsIn (· ∈ contextRun.context.vlctx.fvars) := by + apply checked.fvars.mono + intro fv present + have implementationPresent : + ∃ declaration, context.lctx.find? fv = some declaration := by + simpa only [Option.isSome_iff_exists] using present + have verifiedPresent : + ∃ declaration, contextRun.context.lctx.find? fv = some declaration := by + simpa only [contextRun.context_lctx] using implementationPresent + apply contextRun.context.trlctx.find?_eq_some.mp + change ∃ declaration, + contextRun.context.mlctx.lctx.find? fv = some declaration + rw [contextRun.context.lctx_eq] + exact verifiedPresent + +/-- Verified meaning of one full check retained by the alignment audit. Both +Theory endpoints are selected by the checker refinement; callers cannot +substitute an unrelated translation for the exact source position. -/ +structure ConstructorCheckedExpr.Run + (checked : ConstructorCheckedExpr context source) + (contextRun : TypeChecker.CandidateContextRun context) where + source' : VExpr + inferred' : VExpr + check : TypeChecker.CheckTypeRun contextRun.context.venv + contextRun.context.lparams contextRun.context.vlctx source + checked.observation.inferred source' inferred' + +/-- Interpret an aligned full-check observation in its exact verified +post-family context. -/ +theorem ConstructorCheckedExpr.Run.exists + (checked : ConstructorCheckedExpr context source) + (contextRun : TypeChecker.CandidateContextRun context) : + Nonempty (ConstructorCheckedExpr.Run checked contextRun) := by + obtain ⟨source', inferred', ⟨check⟩⟩ := + TypeChecker.CheckTypeRun.exists_ofCandidateStepFVars + ⟨context, source, checked.observation.inferred⟩ + checked.observation.valid contextRun (checked.fvarsIn contextRun) + exact ⟨⟨source', inferred', check⟩⟩ + +/-- A retained full check whose implementation result is syntactically a +sort supplies the exact Theory `IsType` premise needed to extend the local +context. -/ +theorem ConstructorCheckedExpr.Run.isType_of_inferredSort + (run : ConstructorCheckedExpr.Run checked contextRun) + (inferred_eq : checked.observation.inferred = .sort u) : + contextRun.context.IsType run.source' := by + rcases run with ⟨source', inferred', check⟩ + have inferred_tr := check.inferred_tr + rw [inferred_eq] at inferred_tr + cases inferred_tr + exact check.isType + +/-- Reuse a proved scope boundary with the exact full-check observation owned +by another retained execution of the same source expression. -/ +def ConstructorCheckedExpr.withObservation + (scope : ConstructorCheckedExpr context source) + (observation : CandidateCheckTypeObservation context source) : + ConstructorCheckedExpr context source := + ⟨scope.fvars, observation⟩ + +/-- Interpret one retained equality observation at the exact Theory +translations selected by the two aligned full checks. -/ +def ConstructorCheckedExpr.Run.isDefEq + {context : Context} {lhs rhs : Expr} + {lhsCheck : ConstructorCheckedExpr context lhs} + {rhsCheck : ConstructorCheckedExpr context rhs} + {contextRun : TypeChecker.CandidateContextRun context} + (lhsRun : ConstructorCheckedExpr.Run lhsCheck contextRun) + (rhsRun : ConstructorCheckedExpr.Run rhsCheck contextRun) + (observation : CandidateIsDefEqObservation context lhs rhs) : + TypeChecker.IsDefEqRun contextRun.context.venv + contextRun.context.lparams contextRun.context.vlctx lhs rhs + lhsRun.source' rhsRun.source' := + TypeChecker.IsDefEqRun.ofCandidateStep + ⟨context, lhs, rhs⟩ observation.valid contextRun.context + contextRun.context_eq rfl rfl rfl contextRun.state_wf + lhsRun.check.expr_tr rhsRun.check.expr_tr context.fuel.recDepth rfl + +/-- A validation-local verified context pinned to the one post-family Theory +environment and universe-parameter list used by the whole constructor list. -/ +structure ConstructorContextRun (env : VEnv) (Us : List Name) + (context : Context) where + candidate : TypeChecker.CandidateContextRun context + venv_eq : candidate.context.venv = env + lparams_eq : candidate.context.lparams = Us + +def ConstructorContextRun.withEmptyLocalContext + (run : ConstructorContextRun env Us context) : + ConstructorContextRun env Us context.withEmptyLocalContext where + candidate := run.candidate.withEmptyLocalContext + venv_eq := run.venv_eq + lparams_eq := run.lparams_eq + +/-- Extend the actual post-family verified context by exactly one retained +validation local declaration. -/ +def ConstructorContextRun.pushLocalDecl + (run : ConstructorContextRun env Us context) + (name : Name) (binderInfo : BinderInfo) (domain : Expr) + (fresh : context.lctx.find? context.freshFVarId = none) + (domain' : VExpr) + (domain_tr : run.candidate.context.TrExprS domain domain') + (domain_type : run.candidate.context.IsType domain') : + ConstructorContextRun env Us + (context.pushLocalDecl name binderInfo domain) := by + let candidate := run.candidate.pushLocalDecl name binderInfo domain fresh + domain' domain_tr domain_type + refine ⟨candidate, ?_, ?_⟩ + · calc + candidate.context.venv = run.candidate.context.venv := by + simp [candidate] + _ = env := run.venv_eq + · calc + candidate.context.lparams = run.candidate.context.lparams := by + simp [candidate, AddInductive.Context.pushLocalDecl] + _ = Us := run.lparams_eq + +/-- Verified interpretation of one exact retained WHNF operation, sharing the +source translation already selected by its aligned full check. -/ +structure ConstructorWhnfRun + {context : Context} {source : Expr} + {sourceCheck : ConstructorCheckedExpr context source} + (contextRun : TypeChecker.CandidateContextRun context) + (sourceRun : ConstructorCheckedExpr.Run sourceCheck contextRun) + (result : Expr) where + result' : VExpr + result_tr : contextRun.context.TrExprS result result' + whnf : TypeChecker.WhnfRun contextRun.context.venv + contextRun.context.lparams contextRun.context.vlctx source result + sourceRun.source' result' + +theorem ConstructorWhnfRun.exists + {context : Context} {source result : Expr} + {sourceCheck : ConstructorCheckedExpr context source} + (contextRun : TypeChecker.CandidateContextRun context) + (sourceRun : ConstructorCheckedExpr.Run sourceCheck contextRun) + (valid : CandidateWhnfStep.Valid ⟨context, source, result⟩) + (recursionFuel : Nat) + (depth : context.fuel.recDepth = recursionFuel + 1) : + Nonempty (ConstructorWhnfRun contextRun sourceRun result) := by + obtain ⟨result', result_tr, ⟨whnf⟩⟩ := + TypeChecker.WhnfRun.exists_ofCandidateStep + ⟨context, source, result⟩ valid contextRun sourceRun.source' + sourceRun.check.expr_tr recursionFuel depth + exact ⟨⟨result', result_tr, whnf⟩⟩ + +/-- Retained operational evidence for the supplemental nested-positivity +alignment. The ordinary positivity trace continues to own every WHNF, +occurrence decision, and accepted recursive target. This trace adds the full +checks and annotation equality needed to interpret those exact operations in +the verified checker. -/ +inductive ConstructorPositivityAlignmentTrace : + {stats : InductiveStats} → {ctor : Name} → {argIdx : Nat} → + {context : Context} → {source : Expr} → {fuel : Nat} → + ConstructorPositivityTrace stats ctor argIdx context source fuel → Type where + | absent + (sourceCheck : ConstructorCheckedExpr context source) : + ConstructorPositivityAlignmentTrace + (.absent context source result fuel whnfStep occurs) + | forallE + (sourceCheck : ConstructorCheckedExpr context source) + (domainCheck : ConstructorCheckedExpr context domain) + (consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)) + (consumedLevel : Level) + (consumedInferred : consumedCheck.observation.inferred = + .sort consumedLevel) + (fresh : context.lctx.find? context.freshFVarId = none) + (annotations : CandidateIsDefEqObservation context domain + (consumeTypeAnnotations domain)) + (tailTrace : ConstructorPositivityTrace stats ctor argIdx + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel) + (tail : ConstructorPositivityAlignmentTrace tailTrace) : + ConstructorPositivityAlignmentTrace + (.forallE context source fuel name domain body binderInfo whnfStep occurs + domainFree tailTrace) + | target + (sourceCheck : ConstructorCheckedExpr context source) : + ConstructorPositivityAlignmentTrace + (.target context source result fuel targetIdx whnfStep occurs terminal + valid) + +namespace ConstructorPositivityAlignmentTrace + +def build : + (positivityTrace : ConstructorPositivityTrace stats ctor argIdx context + source fuel) → + Except Exception (ConstructorPositivityAlignmentTrace positivityTrace) + | .absent context source _ fuel whnfStep occurs => do + let sourceCheck ← checkConstructorAlignedExpr context source + pure <| .absent sourceCheck + | .forallE context source fuel _ domain _ _ _ occurs + domainFree tailTrace => do + let sourceCheck ← checkConstructorAlignedExpr context source + let domainCheck ← checkConstructorAlignedExpr context domain + let consumedCheck ← checkConstructorAlignedExpr context + (consumeTypeAnnotations domain) + match consumedInferred : consumedCheck.observation.inferred with + | .sort consumedLevel => + if fresh : context.lctx.find? context.freshFVarId = none then + let annotations ← observeCandidateIsDefEq context domain + (consumeTypeAnnotations domain) + let tail ← build tailTrace + pure <| .forallE sourceCheck domainCheck consumedCheck consumedLevel + consumedInferred fresh annotations tailTrace tail + else + throw <| .other "positivity traversal reused a local identifier" + | _ => + throw <| .other + "consumed positivity domain did not check as a type" + | .target context source _ fuel _ _ occurs terminal + valid => do + let sourceCheck ← checkConstructorAlignedExpr context source + pure <| .target sourceCheck + +/-- Executable erasure of the retained positivity alignment. -/ +def check (positivityTrace : ConstructorPositivityTrace stats ctor argIdx + context source fuel) : M Unit := fun _ => + (ConstructorPositivityAlignmentTrace.build positivityTrace).map fun _ => () + +theorem nonempty_of_check + {positivityTrace : ConstructorPositivityTrace stats ctor argIdx context + source fuel} + (success : ConstructorPositivityAlignmentTrace.check positivityTrace + context = .ok ()) : + Nonempty (ConstructorPositivityAlignmentTrace positivityTrace) := by + unfold check at success + cases h : ConstructorPositivityAlignmentTrace.build positivityTrace with + | error error => + rw [h] at success + change Except.error error = Except.ok () at success + contradiction + | ok alignment => exact ⟨alignment⟩ + +end ConstructorPositivityAlignmentTrace + +inductive ConstructorPositivityModeAlignmentTrace : + {stats : InductiveStats} → {isUnsafe : Bool} → {ctor : Name} → + {argIdx : Nat} → {context : Context} → {source : Expr} → + ConstructorPositivityModeTrace stats isUnsafe ctor argIdx context source → + Type where + | skipped : ConstructorPositivityModeAlignmentTrace (.skipped unsafeEq) + | safe (alignment : ConstructorPositivityAlignmentTrace positivityTrace) : + ConstructorPositivityModeAlignmentTrace (.safe unsafeEq positivityTrace) + +namespace ConstructorPositivityModeAlignmentTrace + +def build : + (positivityTrace : ConstructorPositivityModeTrace stats isUnsafe ctor + argIdx context source) → + Except Exception + (ConstructorPositivityModeAlignmentTrace positivityTrace) + | .skipped _ => pure <| .skipped + | .safe _ positivityTrace => do + let alignment ← ConstructorPositivityAlignmentTrace.build + positivityTrace + pure <| .safe alignment + +def check (positivityTrace : ConstructorPositivityModeTrace stats isUnsafe + ctor argIdx context source) : M Unit := fun _ => + (ConstructorPositivityModeAlignmentTrace.build positivityTrace).map fun _ => () + +theorem nonempty_of_check + {positivityTrace : ConstructorPositivityModeTrace stats isUnsafe ctor + argIdx context source} + (success : ConstructorPositivityModeAlignmentTrace.check positivityTrace + context = .ok ()) : + Nonempty (ConstructorPositivityModeAlignmentTrace positivityTrace) := by + unfold check at success + cases h : ConstructorPositivityModeAlignmentTrace.build positivityTrace with + | error error => + rw [h] at success + change Except.error error = Except.ok () at success + contradiction + | ok alignment => exact ⟨alignment⟩ + +end ConstructorPositivityModeAlignmentTrace + +/-- Exact operational alignment between one retained validation telescope and +the analyzer-owned kernel view. The recursive indices instantiate the view +with validation-owned parameters and fields, so no equality between the +producer's and validator's fresh free-variable identifiers is assumed. -/ +inductive ConstructorViewAlignmentTrace : + {stats : InductiveStats} → {isUnsafe : Bool} → {familyIdx : Nat} → + {ctor : Name} → {context : Context} → {source : Expr} → + {argIdx fuel : Nat} → + ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor context + source argIdx fuel → + (view : Expr) → Type where + | parameter + (domainCheck : ConstructorCheckedExpr context domain) + (viewDomainCheck : ConstructorCheckedExpr context viewDomain) + (parameterTypeCheck : ConstructorCheckedExpr context parameterType) + (parameterShape : param = .fvar fv) + (parameterPresent : (context.lctx.find? fv).isSome = true) + (tailTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context (body.instantiate1 param) (argIdx + 1) fuel) + (tail : ConstructorViewAlignmentTrace tailTrace + (viewBody.instantiate1 param)) : + ConstructorViewAlignmentTrace + (.parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeRun validationDefEq tailTrace) + (.forallE viewName viewDomain viewBody viewBinderInfo) + | ordinary + (domainCheck : ConstructorCheckedExpr context domain) + (viewDomainCheck : ConstructorCheckedExpr context viewDomain) + (viewEquality : CandidateIsDefEqObservation context domain viewDomain) + (consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)) + (positivityTrace : ConstructorPositivityModeTrace stats isUnsafe ctor + argIdx context domain) + (positivityAlignment : + ConstructorPositivityModeAlignmentTrace positivityTrace) + (fresh : context.lctx.find? context.freshFVarId = none) + (annotations : CandidateIsDefEqObservation context domain + (consumeTypeAnnotations domain)) + (tailTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) fuel) + (tail : ConstructorViewAlignmentTrace tailTrace + (viewBody.instantiate1 context.freshExpr)) : + ConstructorViewAlignmentTrace + (.ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureTypeStep universeTrace positivityTrace tailTrace) + (.forallE viewName viewDomain viewBody viewBinderInfo) + | terminal + (sourceCheck : ConstructorCheckedExpr context source) + (viewCheck : ConstructorCheckedExpr context view) + (viewTerminal : view.isForall = false) + (viewValid : isValidIndAppIdx stats view familyIdx = true) : + ConstructorViewAlignmentTrace + (.terminal context source fuel argIdx sourceTerminal sourceValid) view + +namespace ConstructorViewAlignmentTrace + +/-- Execute the exact component audit and retain every successful checker +observation. This is intentionally not a second `checkConstructors` run: the +raw branch shape, parameter selection, universe decision, positivity target, +and raw terminal acceptance remain owned by the ordinary validation trace. -/ +def build : + (validationTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx + ctor context source argIdx fuel) → + (view : Expr) → + Except Exception (ConstructorViewAlignmentTrace validationTrace view) + | .parameter context parameterFuel parameterArgIdx parameterName domain + parameterBody parameterBinderInfo param parameterType _ + _ _ tailTrace, + .forallE viewName viewDomain viewBody viewBinderInfo => do + let domainCheck ← checkConstructorAlignedExpr context domain + let viewDomainCheck ← checkConstructorAlignedExpr context viewDomain + let parameterTypeCheck ← checkConstructorAlignedExpr context + parameterType + match hparam : param with + | .fvar fv => + if parameterPresent : (context.lctx.find? fv).isSome = true then + let tail ← build tailTrace + (viewBody.instantiate1 param) + pure <| .parameter domainCheck viewDomainCheck parameterTypeCheck + hparam parameterPresent tailTrace tail + else + throw <| .other + "constructor parameter is absent from validation context" + | _ => + throw <| .other "constructor parameter is not a local variable" + | .parameter .., _ => + throw <| .other "candidate and validation constructor telescopes differ" + | .ordinary context ordinaryFuel ordinaryArgIdx name domain body binderInfo + _ _ _ _ positivityTrace tailTrace, + .forallE viewName viewDomain viewBody viewBinderInfo => do + let domainCheck ← checkConstructorAlignedExpr context domain + let viewDomainCheck ← checkConstructorAlignedExpr context viewDomain + let viewEquality ← observeCandidateIsDefEq context domain viewDomain + let consumedCheck ← checkConstructorAlignedExpr context + (consumeTypeAnnotations domain) + let positivityAlignment ← + ConstructorPositivityModeAlignmentTrace.build positivityTrace + if fresh : context.lctx.find? context.freshFVarId = none then + let annotations ← observeCandidateIsDefEq context domain + (consumeTypeAnnotations domain) + let tail ← build tailTrace + (viewBody.instantiate1 context.freshExpr) + pure <| .ordinary domainCheck viewDomainCheck viewEquality consumedCheck + positivityTrace positivityAlignment fresh annotations tailTrace tail + else + throw <| .other "constructor validation reused a local identifier" + | .ordinary .., _ => + throw <| .other "candidate and validation constructor telescopes differ" + | .terminal context source fuel argIdx sourceTerminal sourceValid, view => do + let sourceCheck ← checkConstructorAlignedExpr context source + let viewCheck ← checkConstructorAlignedExpr context view + if viewTerminal : view.isForall = false then + if viewValid : isValidIndAppIdx stats view familyIdx = true then + pure <| .terminal sourceCheck viewCheck viewTerminal viewValid + else + throw <| .other + "candidate view changed the terminal family application" + else + throw <| .other "candidate view has an extra constructor field" + +def check (validationTrace : ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context source argIdx fuel) (view : Expr) : M Unit := + fun _ => (build validationTrace view).map fun _ => () + +theorem nonempty_of_check + {validationTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx + ctor context source argIdx fuel} + (success : check validationTrace view context = .ok ()) : + Nonempty (ConstructorViewAlignmentTrace validationTrace view) := by + unfold check at success + cases h : build validationTrace view with + | error error => + rw [h] at success + change Except.error error = Except.ok () at success + contradiction + | ok alignment => exact ⟨alignment⟩ + +end ConstructorViewAlignmentTrace + +/-- Supplemental checker audit for the exact analyzer-owned view of one +constructor. It follows the validation telescope and instantiates the view +with validation-owned locals; successful execution retains no rewritten +declaration and claims no independent view acceptance. -/ +def ConstructorTypeValidationTrace.checkViewAlignment + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) (view : Expr) : M Unit := + ConstructorViewAlignmentTrace.check trace view + +/-- Source-ordered retained alignment for the complete constructor list. +The source indices make omission, duplication, and reordering unrepresentable. +Each node also retains the closed-root scope check needed to interpret the +validator's original empty-local-context `checkType` observation. -/ +inductive ConstructorCandidateAlignmentTrace + (stats : InductiveStats) (isUnsafe : Bool) (familyIdx : Nat) + (context : Context) : + {seen : NameSet} → {constructors : List Constructor} → + (validationTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) → + AddInductive.CandidateList AddInductive.CandidateConstructor constructors → + Type where + | nil (seen : NameSet) : + ConstructorCandidateAlignmentTrace stats isUnsafe familyIdx context + (.nil seen) .nil + | cons + {seen : NameSet} {head : Constructor} {tail : List Constructor} + {fresh : seen.contains head.name = false} + {closed : context.env.checkNoMVarNoFVar head.name head.type = .ok ()} + {rootCheck : CandidateCheckTypeObservation + context.withEmptyLocalContext head.type} + {typeTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx + head.name context head.type 0 context.fuel.inductiveFuel} + {tailTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context (seen.insert head.name) tail} + {candidate : AddInductive.CandidateConstructor head} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor tail} + (rootScope : ConstructorCheckedExpr context.withEmptyLocalContext + head.type) + (storedSpine : candidate.type.trace.storedSpine = true) + (spineLength : candidate.type.trace.spineLength = + typeTrace.spineLength) + (candidateDepth : candidate.type.context.fuel.recDepth = + context.fuel.recDepth) + (headAlignment : ConstructorViewAlignmentTrace typeTrace + candidate.type.view) + (tailAlignment : ConstructorCandidateAlignmentTrace stats isUnsafe + familyIdx context tailTrace candidates) : + ConstructorCandidateAlignmentTrace stats isUnsafe familyIdx context + (.cons seen head tail fresh closed rootCheck typeTrace tailTrace) + (.cons candidate candidates) + +namespace ConstructorCandidateAlignmentTrace + +/-- Execute the source-ordered constructor alignment and retain all successful +component checks. The candidate list's dependent source index selects the +same constructor at every recursive position as the validation trace. -/ +def build : + (validationTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) → + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) → + Except Exception + (ConstructorCandidateAlignmentTrace stats isUnsafe familyIdx context + validationTrace candidates) + | .nil seen, .nil => pure <| .nil seen + | .cons seen head tail _ _ _ typeTrace tailTrace, + .cons candidate candidates => do + let rootScope ← checkConstructorAlignedExpr + context.withEmptyLocalContext head.type + if storedSpine : candidate.type.trace.storedSpine = true then + if spineLength : candidate.type.trace.spineLength = + typeTrace.spineLength then + if candidateDepth : candidate.type.context.fuel.recDepth = + context.fuel.recDepth then + let headAlignment ← ConstructorViewAlignmentTrace.build typeTrace + candidate.type.view + let tailAlignment ← build tailTrace candidates + pure <| .cons rootScope storedSpine spineLength candidateDepth + headAlignment tailAlignment + else + throw <| .other + "candidate and validation checker depths differ" + else + throw <| .other + "candidate and validation constructor lengths differ" + else + throw <| .other + "candidate constructor did not preserve its stored spine" + +def check + (validationTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) : M Unit := + fun _ => (build validationTrace candidates).map fun _ => () + +theorem nonempty_of_check + {validationTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors} + (success : check validationTrace candidates context = .ok ()) : + Nonempty (ConstructorCandidateAlignmentTrace stats isUnsafe familyIdx + context validationTrace candidates) := by + unfold check at success + cases h : build validationTrace candidates with + | error error => + rw [h] at success + change Except.error error = Except.ok () at success + contradiction + | ok alignment => exact ⟨alignment⟩ + +/-- A successful alignment audit guarantees the retained builder returns its +trace, so audit owners can replay `build` instead of choosing from +`Nonempty`. -/ +theorem build_ok_of_check + {validationTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors} + (success : check validationTrace candidates context = .ok ()) : + ∃ alignment, build validationTrace candidates = .ok alignment := by + unfold check at success + cases h : build validationTrace candidates with + | error error => + rw [h] at success + change Except.error error = Except.ok () at success + contradiction + | ok alignment => exact ⟨alignment, rfl⟩ + +end ConstructorCandidateAlignmentTrace + +/-- Source-ordered supplemental alignment audit for every exact constructor +candidate selected by the producer. The dependent list indices rule out +truncation, reordering, duplication, or a view from another source position. +The Boolean gates additionally pin the candidate main-spine length to the +retained validation telescope. -/ +def ConstructorListValidationTrace.checkCandidateAlignment + (trace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) : M Unit := + ConstructorCandidateAlignmentTrace.check trace candidates + +/-! +## Verified interpretation of the aligned validation telescope + +The following semantic traces contain only executions refined by the verified +checker. Their indices still carry the ordinary validator's branch choices +and exact candidate view, while `ConstructorContextRun` fixes every recursive +local context to the actual post-family Theory environment. +-/ + +/-- Verified interpretation of every exact WHNF and nested binder visited by +one retained positivity traversal. -/ +inductive ConstructorPositivitySemanticRun + (env : VEnv) (Us : List Name) (whnfFuel : Nat) : + {stats : InductiveStats} → {ctor : Name} → {argIdx : Nat} → + {context : Context} → {source : Expr} → {fuel : Nat} → + (contextRun : ConstructorContextRun env Us context) → + ConstructorPositivityTrace stats ctor argIdx context source fuel → Type where + | absent + {stats : InductiveStats} {ctor : Name} {argIdx : Nat} + {context : Context} {source result : Expr} {fuel : Nat} + {whnfStep : CandidateWhnfStep.Valid ⟨context, source, result⟩} + {occurs : hasIndOcc stats.indConsts result = false} + {sourceCheck : ConstructorCheckedExpr context source} + {contextRun : ConstructorContextRun env Us context} + (depth : context.fuel.recDepth = whnfFuel + 1) + (sourceRun : ConstructorCheckedExpr.Run sourceCheck + contextRun.candidate) + (whnfRun : ConstructorWhnfRun contextRun.candidate sourceRun result) : + ConstructorPositivitySemanticRun env Us whnfFuel contextRun + (.absent context source result fuel whnfStep occurs) + | forallE + {stats : InductiveStats} {ctor : Name} {argIdx : Nat} + {context : Context} {source : Expr} {fuel : Nat} + {name : Name} {domain body : Expr} {binderInfo : BinderInfo} + {whnfStep : CandidateWhnfStep.Valid + ⟨context, source, .forallE name domain body binderInfo⟩} + {occurs : hasIndOcc stats.indConsts + (.forallE name domain body binderInfo) = true} + {domainFree : hasIndOcc stats.indConsts domain = false} + {tailTrace : ConstructorPositivityTrace stats ctor argIdx + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel} + {sourceCheck : ConstructorCheckedExpr context source} + {domainCheck : ConstructorCheckedExpr context domain} + {consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)} + {consumedLevel : Level} + {consumedInferred : consumedCheck.observation.inferred = + .sort consumedLevel} + {fresh : context.lctx.find? context.freshFVarId = none} + {contextRun : ConstructorContextRun env Us context} + (depth : context.fuel.recDepth = whnfFuel + 1) + (sourceRun : ConstructorCheckedExpr.Run sourceCheck + contextRun.candidate) + (whnfRun : ConstructorWhnfRun contextRun.candidate sourceRun + (.forallE name domain body binderInfo)) + (domainRun : ConstructorCheckedExpr.Run domainCheck + contextRun.candidate) + (consumedRun : ConstructorCheckedExpr.Run consumedCheck + contextRun.candidate) + (annotationsRun : TypeChecker.IsDefEqRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain + (consumeTypeAnnotations domain) domainRun.source' + consumedRun.source') + (consumedType : contextRun.candidate.context.IsType + consumedRun.source') + (tail : ConstructorPositivitySemanticRun env Us whnfFuel + (contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType) + tailTrace) : + ConstructorPositivitySemanticRun env Us whnfFuel contextRun + (.forallE context source fuel name domain body binderInfo whnfStep + occurs domainFree tailTrace) + | target + {stats : InductiveStats} {ctor : Name} {argIdx : Nat} + {context : Context} {source result : Expr} {fuel targetIdx : Nat} + {whnfStep : CandidateWhnfStep.Valid ⟨context, source, result⟩} + {occurs : hasIndOcc stats.indConsts result = true} + {terminal : result.isForall = false} + {valid : isValidIndApp? stats result = some targetIdx} + {sourceCheck : ConstructorCheckedExpr context source} + {contextRun : ConstructorContextRun env Us context} + (depth : context.fuel.recDepth = whnfFuel + 1) + (sourceRun : ConstructorCheckedExpr.Run sourceCheck + contextRun.candidate) + (whnfRun : ConstructorWhnfRun contextRun.candidate sourceRun result) : + ConstructorPositivitySemanticRun env Us whnfFuel contextRun + (.target context source result fuel targetIdx whnfStep occurs terminal + valid) + +namespace ConstructorPositivitySemanticRun + +theorem nonempty_of_alignment + (contextRun : ConstructorContextRun env Us context) + (depth : context.fuel.recDepth = whnfFuel + 1) + {trace : ConstructorPositivityTrace stats ctor argIdx context source fuel} + (alignment : ConstructorPositivityAlignmentTrace trace) : + Nonempty (ConstructorPositivitySemanticRun env Us whnfFuel contextRun + trace) := by + induction trace with + | absent context source result fuel whnfStep occurs => + cases alignment with + | absent sourceCheck => + obtain ⟨sourceRun⟩ := + ConstructorCheckedExpr.Run.exists sourceCheck contextRun.candidate + obtain ⟨whnfRun⟩ := ConstructorWhnfRun.exists + contextRun.candidate sourceRun whnfStep whnfFuel depth + exact ⟨ConstructorPositivitySemanticRun.absent + (stats := stats) (ctor := ctor) (argIdx := argIdx) + depth sourceRun whnfRun⟩ + | forallE context source fuel name domain body binderInfo whnfStep occurs + domainFree tailTrace ih => + cases alignment with + | forallE sourceCheck domainCheck consumedCheck consumedLevel + consumedInferred fresh annotations _ tailAlignment => + obtain ⟨sourceRun⟩ := + ConstructorCheckedExpr.Run.exists sourceCheck contextRun.candidate + obtain ⟨whnfRun⟩ := ConstructorWhnfRun.exists + contextRun.candidate sourceRun whnfStep whnfFuel depth + obtain ⟨domainRun⟩ := + ConstructorCheckedExpr.Run.exists domainCheck contextRun.candidate + obtain ⟨consumedRun⟩ := + ConstructorCheckedExpr.Run.exists consumedCheck + contextRun.candidate + let annotationsRun := domainRun.isDefEq consumedRun annotations + have consumedType : contextRun.candidate.context.IsType + consumedRun.source' := + consumedRun.isType_of_inferredSort consumedInferred + let tailContext := contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType + have tailDepth : + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)).fuel.recDepth = + whnfFuel + 1 := by + simpa [AddInductive.Context.pushLocalDecl] using depth + obtain ⟨tail⟩ := ih tailContext tailDepth tailAlignment + exact ⟨ConstructorPositivitySemanticRun.forallE + (stats := stats) (ctor := ctor) (argIdx := argIdx) + (consumedLevel := consumedLevel) + (consumedInferred := consumedInferred) + depth sourceRun whnfRun domainRun consumedRun annotationsRun + consumedType tail⟩ + | target context source result fuel targetIdx whnfStep occurs terminal valid => + cases alignment with + | target sourceCheck => + obtain ⟨sourceRun⟩ := + ConstructorCheckedExpr.Run.exists sourceCheck contextRun.candidate + obtain ⟨whnfRun⟩ := ConstructorWhnfRun.exists + contextRun.candidate sourceRun whnfStep whnfFuel depth + exact ⟨ConstructorPositivitySemanticRun.target + (stats := stats) (ctor := ctor) (argIdx := argIdx) + depth sourceRun whnfRun⟩ + +end ConstructorPositivitySemanticRun + +/-- Verified meaning of the exact safe/unsafe positivity branch retained by +ordinary constructor validation. -/ +inductive ConstructorPositivityModeSemanticRun + (env : VEnv) (Us : List Name) (whnfFuel : Nat) : + {stats : InductiveStats} → {isUnsafe : Bool} → {ctor : Name} → + {argIdx : Nat} → {context : Context} → {source : Expr} → + (contextRun : ConstructorContextRun env Us context) → + ConstructorPositivityModeTrace stats isUnsafe ctor argIdx context source → + Type where + | skipped : + {stats : InductiveStats} → {isUnsafe : Bool} → {ctor : Name} → + {argIdx : Nat} → {context : Context} → {source : Expr} → + {unsafeEq : isUnsafe = true} → + {contextRun : ConstructorContextRun env Us context} → + ConstructorPositivityModeSemanticRun env Us whnfFuel contextRun + (@ConstructorPositivityModeTrace.skipped stats isUnsafe ctor argIdx + context source unsafeEq) + | safe + {stats : InductiveStats} {isUnsafe : Bool} {ctor : Name} + {argIdx : Nat} {context : Context} {source : Expr} + {unsafeEq : isUnsafe = false} + {positivityTrace : ConstructorPositivityTrace stats ctor argIdx context + source context.fuel.inductiveFuel} + {contextRun : ConstructorContextRun env Us context} + (semantic : ConstructorPositivitySemanticRun env Us whnfFuel contextRun + positivityTrace) : + ConstructorPositivityModeSemanticRun env Us whnfFuel contextRun + (@ConstructorPositivityModeTrace.safe stats isUnsafe ctor argIdx + context source unsafeEq positivityTrace) + +namespace ConstructorPositivityModeSemanticRun + +theorem nonempty_of_alignment + (contextRun : ConstructorContextRun env Us context) + (depth : context.fuel.recDepth = whnfFuel + 1) + {trace : ConstructorPositivityModeTrace stats isUnsafe ctor argIdx + context source} + (alignment : ConstructorPositivityModeAlignmentTrace trace) : + Nonempty (ConstructorPositivityModeSemanticRun env Us whnfFuel contextRun + trace) := by + cases alignment with + | @skipped unsafeEq => + exact ⟨ConstructorPositivityModeSemanticRun.skipped + (env := env) (Us := Us) (whnfFuel := whnfFuel) + (stats := stats) (isUnsafe := isUnsafe) (ctor := ctor) + (argIdx := argIdx) (context := context) (source := source) + (unsafeEq := unsafeEq) (contextRun := contextRun)⟩ + | safe positivityAlignment => + obtain ⟨semantic⟩ := + ConstructorPositivitySemanticRun.nonempty_of_alignment contextRun depth + positivityAlignment + exact ⟨.safe semantic⟩ + +end ConstructorPositivityModeSemanticRun + +/-- Verified, componentwise interpretation of one aligned constructor +telescope. The view is followed at validation-owned parameter and field +locals; no equality between candidate and validator fresh identifiers is +required or asserted. -/ +inductive ConstructorViewSemanticRun + (env : VEnv) (Us : List Name) (whnfFuel : Nat) : + {stats : InductiveStats} → {isUnsafe : Bool} → {familyIdx : Nat} → + {ctor : Name} → {context : Context} → {source : Expr} → + {argIdx fuel : Nat} → + (contextRun : ConstructorContextRun env Us context) → + ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor context + source argIdx fuel → + (view : Expr) → Type where + | parameter + {stats : InductiveStats} {isUnsafe : Bool} {familyIdx : Nat} + {ctor : Name} {context : Context} {fuel argIdx : Nat} + {name : Name} {domain body : Expr} {binderInfo : BinderInfo} + {param parameterType : Expr} + {parameterAt : stats.params[argIdx]? = some param} + {parameterTypeGet : getType param context = .ok parameterType} + {validationDefEq : CandidateIsDefEqStep.Valid + ⟨context, domain, parameterType⟩} + {tailTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context (body.instantiate1 param) (argIdx + 1) fuel} + {viewName : Name} {viewDomain viewBody : Expr} + {viewBinderInfo : BinderInfo} + {domainCheck : ConstructorCheckedExpr context domain} + {viewDomainCheck : ConstructorCheckedExpr context viewDomain} + {parameterTypeCheck : ConstructorCheckedExpr context parameterType} + {contextRun : ConstructorContextRun env Us context} + (domainRun : ConstructorCheckedExpr.Run domainCheck + contextRun.candidate) + (viewDomainRun : ConstructorCheckedExpr.Run viewDomainCheck + contextRun.candidate) + (parameterTypeSemantic : ConstructorCheckedExpr.Run parameterTypeCheck + contextRun.candidate) + (validationRun : TypeChecker.IsDefEqRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain parameterType + domainRun.source' parameterTypeSemantic.source') + (tail : ConstructorViewSemanticRun env Us whnfFuel contextRun tailTrace + (viewBody.instantiate1 param)) : + ConstructorViewSemanticRun env Us whnfFuel contextRun + (.parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeGet validationDefEq tailTrace) + (.forallE viewName viewDomain viewBody viewBinderInfo) + | ordinary + {stats : InductiveStats} {isUnsafe : Bool} {familyIdx : Nat} + {ctor : Name} {context : Context} {fuel argIdx : Nat} + {name : Name} {domain body : Expr} {binderInfo : BinderInfo} + {sortResult : Expr} {noParameter : stats.params[argIdx]? = none} + {ensureTypeStep : ConstructorEnsureTypeStep.Valid + ⟨context, domain, sortResult⟩} + {universeTrace : ConstructorUniverseTrace stats.resultLevel + sortResult.sortLevel!} + {positivityTrace : ConstructorPositivityModeTrace stats isUnsafe ctor + argIdx context domain} + {tailTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) fuel} + {viewName : Name} {viewDomain viewBody : Expr} + {viewBinderInfo : BinderInfo} + {domainCheck : ConstructorCheckedExpr context domain} + {viewDomainCheck : ConstructorCheckedExpr context viewDomain} + {viewEquality : CandidateIsDefEqObservation context domain viewDomain} + {consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)} + {fresh : context.lctx.find? context.freshFVarId = none} + {contextRun : ConstructorContextRun env Us context} + (domainRun : ConstructorCheckedExpr.Run domainCheck + contextRun.candidate) + (viewDomainRun : ConstructorCheckedExpr.Run viewDomainCheck + contextRun.candidate) + (viewEqualityRun : TypeChecker.IsDefEqRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain viewDomain + domainRun.source' viewDomainRun.source') + (consumedRun : ConstructorCheckedExpr.Run consumedCheck + contextRun.candidate) + (ensureTypeRun : TypeChecker.EnsureTypeRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain sortResult + domainRun.source') + (positivity : ConstructorPositivityModeSemanticRun env Us whnfFuel + contextRun positivityTrace) + (annotationsRun : TypeChecker.IsDefEqRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain + (consumeTypeAnnotations domain) domainRun.source' + consumedRun.source') + (consumedType : contextRun.candidate.context.IsType + consumedRun.source') + (tail : ConstructorViewSemanticRun env Us whnfFuel + (contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType) + tailTrace (viewBody.instantiate1 context.freshExpr)) : + ConstructorViewSemanticRun env Us whnfFuel contextRun + (.ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureTypeStep universeTrace positivityTrace tailTrace) + (.forallE viewName viewDomain viewBody viewBinderInfo) + | terminal + {stats : InductiveStats} {isUnsafe : Bool} {familyIdx : Nat} + {ctor : Name} {context : Context} {source view : Expr} + {fuel argIdx : Nat} {sourceTerminal : source.isForall = false} + {sourceValid : isValidIndAppIdx stats source familyIdx = true} + {sourceCheck : ConstructorCheckedExpr context source} + {viewCheck : ConstructorCheckedExpr context view} + {contextRun : ConstructorContextRun env Us context} + (sourceRun : ConstructorCheckedExpr.Run sourceCheck + contextRun.candidate) + (viewRun : ConstructorCheckedExpr.Run viewCheck contextRun.candidate) : + ConstructorViewSemanticRun env Us whnfFuel contextRun + (.terminal context source fuel argIdx sourceTerminal sourceValid) view + +namespace ConstructorViewSemanticRun + +theorem nonempty_of_alignment + (contextRun : ConstructorContextRun env Us context) + (depth : context.fuel.recDepth = whnfFuel + 1) + {validationTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx + ctor context source argIdx fuel} + {view : Expr} + (alignment : ConstructorViewAlignmentTrace validationTrace view) : + Nonempty (ConstructorViewSemanticRun env Us whnfFuel contextRun + validationTrace view) := by + induction validationTrace generalizing view with + | parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeGet validationDefEq tailTrace ih => + cases alignment with + | parameter domainCheck viewDomainCheck parameterTypeCheck + parameterShape parameterPresent _ tailAlignment => + obtain ⟨domainRun⟩ := + ConstructorCheckedExpr.Run.exists domainCheck contextRun.candidate + obtain ⟨viewDomainRun⟩ := + ConstructorCheckedExpr.Run.exists viewDomainCheck + contextRun.candidate + obtain ⟨parameterTypeSemantic⟩ := + ConstructorCheckedExpr.Run.exists parameterTypeCheck + contextRun.candidate + let validationRun := TypeChecker.IsDefEqRun.ofCandidateStep + ⟨context, domain, parameterType⟩ validationDefEq + contextRun.candidate.context contextRun.candidate.context_eq + rfl rfl rfl contextRun.candidate.state_wf + domainRun.check.expr_tr parameterTypeSemantic.check.expr_tr + context.fuel.recDepth rfl + obtain ⟨tail⟩ := ih contextRun depth tailAlignment + exact ⟨ConstructorViewSemanticRun.parameter + domainRun viewDomainRun parameterTypeSemantic validationRun tail⟩ + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureTypeStep universeTrace positivityTrace tailTrace ih => + cases alignment with + | ordinary domainCheck viewDomainCheck viewEquality consumedCheck _ + positivityAlignment fresh annotations _ tailAlignment => + obtain ⟨domainRun⟩ := + ConstructorCheckedExpr.Run.exists domainCheck contextRun.candidate + obtain ⟨viewDomainRun⟩ := + ConstructorCheckedExpr.Run.exists viewDomainCheck + contextRun.candidate + let viewEqualityRun := domainRun.isDefEq viewDomainRun viewEquality + obtain ⟨consumedRun⟩ := + ConstructorCheckedExpr.Run.exists consumedCheck + contextRun.candidate + obtain ⟨ensureTypeRun⟩ := + TypeChecker.EnsureTypeRun.exists_ofConstructorStep + ⟨context, domain, sortResult⟩ ensureTypeStep + contextRun.candidate domainRun.source' domainRun.check.expr_tr + obtain ⟨positivity⟩ := + ConstructorPositivityModeSemanticRun.nonempty_of_alignment + contextRun depth positivityAlignment + let annotationsRun := domainRun.isDefEq consumedRun annotations + have consumedType : contextRun.candidate.context.IsType + consumedRun.source' := by + have annotationDef := annotationsRun.isDefEqU.of_l + contextRun.candidate.context.Ewf + contextRun.candidate.context.Δwf.toCtx + ensureTypeRun.source_type + exact ⟨ensureTypeRun.resultLevel', annotationDef.hasType.2⟩ + let tailContext := contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType + have tailDepth : + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)).fuel.recDepth = + whnfFuel + 1 := by + simpa [AddInductive.Context.pushLocalDecl] using depth + obtain ⟨tail⟩ := ih tailContext tailDepth tailAlignment + exact ⟨ConstructorViewSemanticRun.ordinary + (viewEquality := viewEquality) + domainRun viewDomainRun viewEqualityRun consumedRun ensureTypeRun + positivity annotationsRun consumedType tail⟩ + | terminal context source fuel argIdx sourceTerminal sourceValid => + cases alignment with + | terminal sourceCheck viewCheck viewTerminal viewValid => + obtain ⟨sourceRun⟩ := + ConstructorCheckedExpr.Run.exists sourceCheck contextRun.candidate + obtain ⟨viewRun⟩ := + ConstructorCheckedExpr.Run.exists viewCheck contextRun.candidate + exact ⟨ConstructorViewSemanticRun.terminal + (stats := stats) (isUnsafe := isUnsafe) + (familyIdx := familyIdx) (ctor := ctor) + sourceRun viewRun⟩ + +end ConstructorViewSemanticRun + +/-! +## Source-ordered post-family constructor semantics + +The alignment trace connects the validator's exact source telescope to the +analyzer-owned candidate view. The semantic list below interprets that trace +alongside the already-produced constructor semantic hierarchy. Its indices +keep source order, raw constructor order, and the exact candidate view fixed; +its payload retains both validation-local checks and Theory telescope/result +evidence selected by the candidate's recursive checker run. +-/ + +/-- Complete post-family meaning for every constructor position selected by +one exact validation/candidate alignment. + +`root` interprets the validator-owned root `checkType` observation (the +supplemental audit contributes only its scope proof). `telescope` interprets +parameter equality, ordinary-field typing, positivity, and the terminal +family application while following the exact candidate view at +validation-owned locals. `spine` exposes the exact Theory view binders and +terminal result selected by the candidate semantic root. -/ +inductive ConstructorPostFamilySemanticListRun + (env : VEnv) (Us : List Name) + (stats : InductiveStats) (isUnsafe : Bool) (familyIdx : Nat) + (context : Context) (contextRun : ConstructorContextRun env Us context) : + {seen : NameSet} → {constructors : List Constructor} → + (validationTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) → + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) → + {raws : List VConstVal} → + ConstructorCandidateAlignmentTrace stats isUnsafe familyIdx context + validationTrace candidates → + VInductDecl.CandidateConstructorSemanticListRun env Us candidates raws → + Type where + | nil (seen : NameSet) : + ConstructorPostFamilySemanticListRun env Us stats isUnsafe familyIdx + context contextRun (.nil seen) .nil (.nil seen) .nil + | cons + {seen : NameSet} {head : Constructor} {tail : List Constructor} + {freshName : seen.contains head.name = false} + {closed : context.env.checkNoMVarNoFVar head.name head.type = .ok ()} + {rootCheck : CandidateCheckTypeObservation + context.withEmptyLocalContext head.type} + {typeTrace : ConstructorTypeValidationTrace stats isUnsafe familyIdx + head.name context head.type 0 context.fuel.inductiveFuel} + {tailTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context (seen.insert head.name) tail} + {candidate : AddInductive.CandidateConstructor head} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor tail} + {raw : VConstVal} {raws : List VConstVal} + {rootScope : ConstructorCheckedExpr context.withEmptyLocalContext + head.type} + {storedSpine : candidate.type.trace.storedSpine = true} + {spineLength : candidate.type.trace.spineLength = + typeTrace.spineLength} + {candidateDepth : candidate.type.context.fuel.recDepth = + context.fuel.recDepth} + {headAlignment : ConstructorViewAlignmentTrace typeTrace + candidate.type.view} + {tailAlignment : ConstructorCandidateAlignmentTrace stats isUnsafe + familyIdx context tailTrace candidates} + {headSemantic : VInductDecl.CandidateConstructorSemanticRun env Us + candidate raw} + {tailSemantic : VInductDecl.CandidateConstructorSemanticListRun env Us + candidates raws} + (root : ConstructorCheckedExpr.Run + (rootScope.withObservation rootCheck) + contextRun.withEmptyLocalContext.candidate) + (telescope : ConstructorViewSemanticRun env Us + headSemantic.type.whnfFuel contextRun typeTrace candidate.type.view) + (spine : ∃ resultType, + TypeChecker.TelResultDefEqEvidence env Us.length [] + (VExpr.telN candidate.type.trace.spineLength raw.type) + (VExpr.telN candidate.type.trace.spineLength + headSemantic.type.view) + (VExpr.dropN candidate.type.trace.spineLength raw.type) + (VExpr.dropN candidate.type.trace.spineLength + headSemantic.type.view) + resultType) + (tailRun : ConstructorPostFamilySemanticListRun env Us stats isUnsafe + familyIdx context contextRun tailTrace candidates + tailAlignment tailSemantic) : + ConstructorPostFamilySemanticListRun env Us stats isUnsafe familyIdx + context contextRun + (.cons seen head tail freshName closed rootCheck typeTrace tailTrace) + (.cons candidate candidates) + (.cons rootScope storedSpine spineLength candidateDepth headAlignment + tailAlignment) + (.cons headSemantic tailSemantic) + +namespace ConstructorPostFamilySemanticListRun + +/-- Interpret an exact source-ordered alignment together with the exact +candidate semantic list produced for the same raw constructor positions. -/ +theorem nonempty_of_alignment + (contextRun : ConstructorContextRun env Us context) + {validationTrace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors} + {raws : List VConstVal} + (alignment : ConstructorCandidateAlignmentTrace stats isUnsafe familyIdx + context validationTrace candidates) + (semantics : VInductDecl.CandidateConstructorSemanticListRun env Us + candidates raws) : + Nonempty (ConstructorPostFamilySemanticListRun env Us stats isUnsafe + familyIdx context contextRun validationTrace candidates alignment + semantics) := by + induction alignment generalizing raws with + | nil seen => + cases semantics + exact ⟨.nil seen⟩ + | @cons seen head tail freshName closed rootCheck typeTrace tailTrace + candidate candidates rootScope storedSpine spineLength candidateDepth + headAlignment tailAlignment ih => + cases semantics with + | cons headSemantic tailSemantic => + obtain ⟨root⟩ := ConstructorCheckedExpr.Run.exists + (rootScope.withObservation rootCheck) + contextRun.withEmptyLocalContext.candidate + have depth : context.fuel.recDepth = + headSemantic.type.whnfFuel + 1 := by + calc + context.fuel.recDepth = + candidate.type.context.fuel.recDepth := candidateDepth.symm + _ = headSemantic.type.whnfFuel + 1 := + headSemantic.type.whnfDepth + obtain ⟨telescope⟩ := + ConstructorViewSemanticRun.nonempty_of_alignment contextRun depth + headAlignment + have spine := TypeChecker.CandidateExprSpineRun.evidence + (headSemantic.type.spine storedSpine) + obtain ⟨tailRun⟩ := ih tailSemantic + exact ⟨.cons root telescope spine tailRun⟩ + +end ConstructorPostFamilySemanticListRun + +/-- A retained constructor telescope whose strengthened universe decisions are +all true replays the exact executable universe traversal. This is the +converse of `universeSemantics_of_loop`: the trace supplies the same parameter +choices and `ensureType` results, while the Boolean supplies only the +additional verified comparison at ordinary fields. -/ +theorem ConstructorTypeValidationTrace.universeLoop_of_semantics + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) + (semantic : trace.universeSemantics = true) : + checkConstructorUniverseSemantics.loop stats source argIdx fuel context = + .ok () := by + induction trace with + | parameter context fuel argIdx name domain body binderInfo parameter + parameterType parameterAt parameterTypeRun defeq tail ih => + simp only [universeSemantics] at semantic + rw [show fuel + 1 = Nat.succ fuel by rfl] + rw [checkConstructorUniverseSemantics.loop.eq_2] + rw [parameterAt] + exact ih semantic + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureType universeTrace positivity tail ih => + simp only [universeSemantics, Bool.and_eq_true] at semantic + rw [show fuel + 1 = Nat.succ fuel by rfl] + rw [checkConstructorUniverseSemantics.loop.eq_2] + rw [noParameter] + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] + rw [ensureType] + simp only [Except.bind] + have valid : constructorUniverseSemanticGe stats.resultLevel + sortResult.sortLevel! = true := by + simpa only [ConstructorUniverseTrace.semantic] using semantic.1 + rw [valid] + simp only [] + exact ih semantic.2 + | terminal context source fuel argIdx terminal valid => + cases source <;> try rfl + case forallE => + change true = false at terminal + contradiction + +/-- Root form of `universeLoop_of_semantics`, initialized from the same +context fuel as ordinary constructor validation. -/ +theorem ConstructorTypeValidationTrace.universeRun_of_semantics + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source 0 context.fuel.inductiveFuel) + (semantic : trace.universeSemantics = true) : + checkConstructorUniverseSemantics stats source context = .ok () := by + unfold checkConstructorUniverseSemantics + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using trace.universeLoop_of_semantics semantic + +/-- A retained source-ordered constructor list whose strengthened universe +decisions are all true replays the exact executable list audit. -/ +theorem ConstructorListValidationTrace.universeRun_of_semantics + (trace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) + (semantic : trace.universeSemantics = true) : + checkConstructorUniverseListSemantics stats constructors context = + .ok () := by + induction trace with + | nil => rfl + | cons seen head tail fresh closed rootCheck typeTrace tailTrace ih => + simp only [universeSemantics, Bool.and_eq_true] at semantic + simp only [checkConstructorUniverseListSemantics, + ReaderT.bind, Bind.bind] + rw [typeTrace.universeRun_of_semantics semantic.1] + simp only [Except.bind] + exact ih semantic.2 + +/-- Impredicative `Prop` makes every strengthened constructor-universe node +true, independently of the field level selected by the retained checker run. -/ +theorem ConstructorUniverseTrace.semantic_of_resultLevel_isZero + (trace : ConstructorUniverseTrace resultLevel fieldLevel) + (zero : resultLevel.isZero = true) : trace.semantic = true := by + simp [ConstructorUniverseTrace.semantic, constructorUniverseSemanticGe, + zero] + +/-- Every universe node in a retained constructor telescope is admitted by +the strengthened audit when the family result is `Prop`. -/ +theorem ConstructorTypeValidationTrace.universeSemantics_of_resultLevel_isZero + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) + (zero : stats.resultLevel.isZero = true) : + trace.universeSemantics = true := by + induction trace with + | parameter context fuel argIdx name domain body binderInfo parameter + parameterType parameterAt parameterTypeRun defeq tail ih => + simpa only [universeSemantics] using ih + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureType universeTrace positivity tail ih => + simp only [universeSemantics, Bool.and_eq_true] + exact ⟨universeTrace.semantic_of_resultLevel_isZero zero, ih⟩ + | terminal => rfl + +/-- Source-list form of +`ConstructorTypeValidationTrace.universeSemantics_of_resultLevel_isZero`. -/ +theorem ConstructorListValidationTrace.universeSemantics_of_resultLevel_isZero + (trace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) + (zero : stats.resultLevel.isZero = true) : + trace.universeSemantics = true := by + induction trace with + | nil => rfl + | cons seen head tail fresh closed rootCheck typeTrace tailTrace ih => + simp only [universeSemantics, Bool.and_eq_true] + exact ⟨typeTrace.universeSemantics_of_resultLevel_isZero zero, ih⟩ + +/-- A successful executable universe audit marks every universe node in an +arbitrary retained constructor telescope. The proof uses determinism of the +same `ensureType` execution retained by the ordinary trace; it cannot change a +field level or skip a source position. -/ +theorem ConstructorTypeValidationTrace.universeSemantics_of_loop + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel) + (success : checkConstructorUniverseSemantics.loop stats source argIdx fuel + context = .ok ()) : + trace.universeSemantics = true := by + induction trace with + | parameter context fuel argIdx name domain body binderInfo parameter + parameterType parameterAt parameterTypeRun defeq tail ih => + simp only [universeSemantics] + rw [show fuel + 1 = Nat.succ fuel by rfl] at success + rw [checkConstructorUniverseSemantics.loop.eq_2] at success + rw [parameterAt] at success + exact ih success + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureType universeTrace positivity tail ih => + simp only [universeSemantics, Bool.and_eq_true] + rw [show fuel + 1 = Nat.succ fuel by rfl] at success + rw [checkConstructorUniverseSemantics.loop.eq_2] at success + rw [noParameter] at success + simp only [ReaderT.bind, Bind.bind, liftTypeChecker_apply] at success + rw [ensureType] at success + simp only [Except.bind] at success + cases valid : constructorUniverseSemanticGe stats.resultLevel + sortResult.sortLevel! with + | false => + rw [valid] at success + change Except.error _ = Except.ok () at success + cases success + | true => + rw [valid] at success + simp only [] at success + exact ⟨valid, ih success⟩ + | terminal => rfl + +/-- Root form of `universeSemantics_of_loop`, with the audit initialized from +the exact context fuel just like ordinary constructor validation. -/ +theorem ConstructorTypeValidationTrace.universeSemantics_of_run + (trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source 0 context.fuel.inductiveFuel) + (success : checkConstructorUniverseSemantics stats source context = + .ok ()) : + trace.universeSemantics = true := by + apply trace.universeSemantics_of_loop + simpa only [checkConstructorUniverseSemantics, readThe, + MonadReaderOf.read, ReaderT.read, ReaderT.bind, Bind.bind, + ReaderT.pure, Pure.pure, Except.bind, Except.pure] using success + +/-- A successful source-list audit marks every retained constructor position; +the dependent list indices prevent omission, duplication, or reordering. -/ +theorem ConstructorListValidationTrace.universeSemantics_of_run + (trace : ConstructorListValidationTrace stats isUnsafe familyIdx + context seen constructors) + (success : checkConstructorUniverseListSemantics stats constructors + context = .ok ()) : + trace.universeSemantics = true := by + induction trace with + | nil => rfl + | cons seen head tail fresh closed rootCheck typeTrace tailTrace ih => + simp only [universeSemantics, Bool.and_eq_true] + simp only [checkConstructorUniverseListSemantics, + ReaderT.bind, Bind.bind] at success + cases headRun : checkConstructorUniverseSemantics stats head.type + context with + | error error => + rw [headRun] at success + cases success + | ok result => + cases result + rw [headRun] at success + simp only [Except.bind] at success + exact ⟨typeTrace.universeSemantics_of_run headRun, ih success⟩ + +/-- Ordinary constructor validation paired with the executable semantic +universe audit over the identical singleton source list. This record narrows +the accepted package boundary while preserving the ordinary validator result +and every retained non-universe check unchanged. -/ +structure ConstructorSemanticValidationRun + (indType : InductiveType) (stats : InductiveStats) + (isUnsafe : Bool) (context : Context) where + validation : ConstructorValidationRun indType stats isUnsafe context + universeRun : checkConstructorUniverseListSemantics stats indType.ctors + context = .ok () + +namespace ConstructorSemanticValidationRun + +/-- Forgetting the semantic audit replays the exact ordinary validator, so +the strengthened run cannot widen kernel acceptance. -/ +theorem run + (semantic : ConstructorSemanticValidationRun indType stats isUnsafe + context) : + checkConstructors #[indType] stats isUnsafe context = .ok () := + semantic.validation.run + +/-- Every universe-bearing node of the retained ordinary trace passed the +executable verified universe gate. -/ +theorem universeSemantics + (semantic : ConstructorSemanticValidationRun indType stats isUnsafe + context) : + semantic.validation.universeSemantics = true := + semantic.validation.trace.universeSemantics_of_run semantic.universeRun + +end ConstructorSemanticValidationRun + +/-- The semantic universe gate only accepts branches already accepted by the +ordinary constructor validator. It therefore narrows package construction +without widening kernel validation behavior. -/ +theorem ConstructorUniverseTrace.nonempty_of_semanticGe + (valid : constructorUniverseSemanticGe resultLevel fieldLevel = true) : + Nonempty (ConstructorUniverseTrace resultLevel fieldLevel) := by + unfold constructorUniverseSemanticGe at valid + simp only [Bool.or_eq_true, Bool.and_eq_true] at valid + rcases valid with structural | prop | ⟨core, _verified⟩ + · exact ⟨.structural structural⟩ + · cases hstruct : levelStructGe resultLevel fieldLevel with + | true => exact ⟨.structural hstruct⟩ + | false => + exact ⟨.fallback hstruct + (by cases resultLevel <;> simp_all [Level.isZero, Level.isAlwaysZero])⟩ + · cases hstruct : levelStructGe resultLevel fieldLevel with + | true => exact ⟨.structural hstruct⟩ + | false => + exact ⟨.fallback hstruct (by simp [core])⟩ + +/-- The executable semantic subset implies exactly the disjunct required for +a non-recursive field in `VInductDecl.fieldsWF`: either the family is Prop or +the field universe is bounded by the family universe. -/ +theorem constructorUniverseSemanticGe_ofLevel + (valid : constructorUniverseSemanticGe resultLevel fieldLevel = true) + (result_tr : VLevel.ofLevel Us resultLevel = some result') + (field_tr : VLevel.ofLevel Us fieldLevel = some field') : + result' = .zero ∨ field' ≤ result' := by + unfold constructorUniverseSemanticGe at valid + simp only [Bool.or_eq_true, Bool.and_eq_true] at valid + rcases valid with structural | prop | ⟨_core, verified⟩ + · exact .inr (levelStructGe_ofLevel structural result_tr field_tr) + · exact .inl (ofLevel_eq_zero_of_isZero prop result_tr) + · exact .inr (Level.geq'_wf result_tr field_tr verified) + +/-- Agreement between the ordinary and verified normalized comparisons opens +the semantic fallback without weakening the ordinary acceptance boundary. -/ +theorem constructorUniverseSemanticGe_eq_true_of_geq_agreement + (core : resultLevel.geq fieldLevel = true) + (verified : resultLevel.geq' fieldLevel = true) : + constructorUniverseSemanticGe resultLevel fieldLevel = true := by + simp [constructorUniverseSemanticGe, core, verified] + +private def constructorUniverseComparisonSamples : List Level := + [.zero, + .succ .zero, + .succ (.succ .zero), + .param `u, + .param `v, + .succ (.param `u), + .max (.param `u) (.param `v), + .max (.succ (.param `u)) (.param `v), + .imax (.param `u) (.param `v), + .imax (.param `u) (.succ (.param `v)), + .imax (.max (.param `u) (.param `v)) (.succ .zero), + .max (.imax (.param `u) (.param `v)) (.succ (.param `v))] + +/- Differential audit for the mvar-free surface accepted by constructors. +Every pair in this matrix compares Lean v4.31's core decision with the proved +project decision; the samples exercise zero, successor, maximum, impredicative +maximum, parameters, and nested combinations. -/ +#guard constructorUniverseComparisonSamples.all fun resultLevel => + constructorUniverseComparisonSamples.all fun fieldLevel => + resultLevel.geq fieldLevel == resultLevel.geq' fieldLevel + +/- Regression for the former D1 gap: the structural and `Prop` branches both +miss a parameter below a `max`, while core/project normalized comparison +agrees and the verified semantic fallback now accepts it. -/ +private def constructorUniverseNormalizedResult : Level := + .max (.param `u) (.param `v) + +#guard !levelStructGe constructorUniverseNormalizedResult (.param `u) +#guard !constructorUniverseNormalizedResult.isZero +#guard constructorUniverseNormalizedResult.geq (.param `u) +#guard constructorUniverseNormalizedResult.geq' (.param `u) +#guard constructorUniverseSemanticGe constructorUniverseNormalizedResult + (.param `u) + +/- The universe bridge stays within Lean's standard logical basis. In +particular it does not inherit the project's pending sorries, a custom axiom, +or a semantic premise for Lean's opaque `Level.geq` implementation. -/ +#guard_named_axioms Ix.Theory.Named.AddInductive.levelStructEq_ofLevel [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.levelStructGe_ofLevel [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.constructorUniverseSemanticGe_ofLevel [ + propext, + Classical.choice, + Quot.sound, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Std.TreeMap.all_eq_all_toList] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorUniverseTrace.nonempty_of_semanticGe [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorSemanticValidationRun.universeSemantics [propext, Classical.choice, Quot.sound] + +/- The reverse executable bridge and its impredicative-Prop specialization +have the same standard-only closure as the forward universe interpretation. +In particular, replaying a retained validator trace does not inherit a +fixture computation oracle. -/ +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorTypeValidationTrace.universeLoop_of_semantics [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorTypeValidationTrace.universeRun_of_semantics [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorListValidationTrace.universeRun_of_semantics [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorUniverseTrace.semantic_of_resultLevel_isZero [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorTypeValidationTrace.universeSemantics_of_resultLevel_isZero [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.ConstructorListValidationTrace.universeSemantics_of_resultLevel_isZero [propext, Classical.choice, Quot.sound] + +/-! +## Executable pre-family safety and replay + +The post-family validator introduces a local declaration for every constructor +field. A recursive field's local type mentions the family being defined, so +that declaration cannot be reproduced in the pre-family verifier context. +For the current singleton subset we omit such locals, advance the validator's +fresh-name supply, and permit later checks only when their source expressions +do not mention an omitted identifier. Independent ordinary fields may still +follow recursive fields; genuinely dependent uses remain outside this replay. + +The traces below are outputs of executable builders. Their proof fields are +exact `checkType`, `ensureType`, and `isDefEq` executions; they are operational +evidence, not caller-supplied Theory judgments. +-/ + +/-- Executable fragment on which strict kernel-to-Theory translation has a +syntactically unique endpoint. Projections are excluded because the current +`TrProj` contract determines their result only up to definitional equality; +projection-bearing inductives remain outside the singleton subset until the +projection milestones establish an exact structural API. -/ +def theoryTranslationUnique : Expr → Bool + | .bvar _ + | .fvar _ + | .sort _ + | .const .. + | .mvar .. + | .lit _ => true + | .app fn argument => + theoryTranslationUnique fn && theoryTranslationUnique argument + | .lam _ domain body _ + | .forallE _ domain body _ => + theoryTranslationUnique domain && theoryTranslationUnique body + | .letE _ _ value body _ => + theoryTranslationUnique value && theoryTranslationUnique body + | .mdata _ expression => theoryTranslationUnique expression + | .proj .. => false + +/-- The executable predicate is exactly the structural proposition used by +strict-translation uniqueness. -/ +theorem theoryTranslationUnique_sound + (success : theoryTranslationUnique expression = true) : + TrExprS.IsUnique expression := by + induction expression <;> + simp_all [theoryTranslationUnique, TrExprS.IsUnique] + +/-- Abstracting one free variable preserves the projection-free fragment: +the operation changes only free/bound-variable identities and recursively +retains every expression constructor. -/ +theorem theoryTranslationUnique_abstract1 + (expression : Expr) (id : FVarId) (depth : Nat) : + theoryTranslationUnique (Expr.abstract1 id expression depth) = + theoryTranslationUnique expression := by + induction expression generalizing depth <;> + simp [Expr.abstract1, theoryTranslationUnique, *] + split <;> rfl + +/-- Iterated free-variable abstraction likewise preserves the executable +strict-translation fragment. -/ +theorem theoryTranslationUnique_abstractList + (expression : Expr) (ids : List FVarId) (depth : Nat) : + theoryTranslationUnique (Expr.abstractList expression ids depth) = + theoryTranslationUnique expression := by + induction ids generalizing expression with + | nil => rfl + | cons id ids ih => + simp only [Expr.abstractList, ih, + theoryTranslationUnique_abstract1] + +/-- Array-form abstraction over an explicit list of free variables preserves +the projection-free fragment. -/ +theorem theoryTranslationUnique_abstractFVars + (expression : Expr) (ids : List FVarId) : + theoryTranslationUnique + (expression.abstract ⟨ids.map Expr.fvar⟩) = + theoryTranslationUnique expression := by + rw [Expr.abstract_eq] + exact theoryTranslationUnique_abstractList expression ids 0 + +/-- Every syntax fragment contributing to a recursively reconstructed +candidate view has a unique strict Theory endpoint. Checking recursive body +views as well as their stored abstractions supplies precisely the induction +hypotheses consumed by `CandidateExprRun.view_tr_strict`. -/ +def CandidateExprTrace.viewTranslationUnique : + {context : Context} → {source : Expr} → + CandidateExprTrace context source → Bool + | _, _, .terminal _ _ _ result _ _ => theoryTranslationUnique result + | _, _, .forallE context _ _ _ _ _ _ _ _ _ _ _ domain body => + domain.viewTranslationUnique && + (body.viewTranslationUnique && + theoryTranslationUnique + (body.view.abstract #[context.freshExpr])) + +/-- The recursive check is extensionally the projection-free check on the +reconstructed analyzer view. Its explicit body clause supplies the induction +hypothesis consumed by the strict-view proof. -/ +theorem CandidateExprTrace.viewTranslationUnique_eq + (trace : CandidateExprTrace context source) : + trace.viewTranslationUnique = theoryTranslationUnique trace.view := by + induction trace with + | terminal => rfl + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized domainTrace bodyTrace + domainIH bodyIH => + simp only [viewTranslationUnique, CandidateExprTrace.view, + theoryTranslationUnique, domainIH, bodyIH] + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl, + theoryTranslationUnique_abstractFVars] + simp + +/-- A successful recursive executable check supplies the exact proposition +required by strict candidate-view translation. -/ +theorem CandidateExprTrace.viewTranslationUnique_sound + (trace : CandidateExprTrace context source) + (success : trace.viewTranslationUnique = true) : + TypeChecker.CandidateExprTraceViewIsUnique trace := by + induction trace with + | terminal => exact theoryTranslationUnique_sound success + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized domainTrace bodyTrace + domainIH bodyIH => + simp only [viewTranslationUnique, Bool.and_eq_true] at success + exact ⟨domainIH success.1, bodyIH success.2.1, + theoryTranslationUnique_sound success.2.2⟩ + +/-- Source-ordered strict-view check for an exact dependent constructor +candidate list. -/ +def CandidateList.viewTranslationUnique : + {constructors : List Constructor} → + CandidateList CandidateConstructor constructors → Bool + | _, .nil => true + | _, .cons candidate candidates => + candidate.type.trace.viewTranslationUnique && + candidates.viewTranslationUnique + +/-- Proof-level source-ordered counterpart of +`CandidateList.viewTranslationUnique`. -/ +def CandidateList.ViewTranslationUnique : + {constructors : List Constructor} → + CandidateList CandidateConstructor constructors → Prop + | _, .nil => True + | _, .cons candidate candidates => + TypeChecker.CandidateExprTraceViewIsUnique candidate.type.trace ∧ + candidates.ViewTranslationUnique + +theorem CandidateList.viewTranslationUnique_sound + (candidates : CandidateList CandidateConstructor constructors) + (success : candidates.viewTranslationUnique = true) : + candidates.ViewTranslationUnique := by + induction candidates with + | nil => trivial + | cons candidate candidates ih => + simp only [viewTranslationUnique, Bool.and_eq_true] at success + exact ⟨candidate.type.trace.viewTranslationUnique_sound success.1, + ih success.2⟩ + +/-- Advance the constructor traversal's fresh-name supply without adding the +family-dependent local declaration for a recursive outer field. -/ +def Context.advanceFresh (context : Context) : Context := + { context with ngen := context.ngen.next } + +/-- Advancing an omitted recursive field changes only the candidate name +generator. The verified checker context and its empty-state certificate remain +the same because `Context.toTypeChecker` deliberately has no name-generator +field. -/ +def advanceCandidateContextRun + (run : TypeChecker.CandidateContextRun context) : + TypeChecker.CandidateContextRun context.advanceFresh := by + refine ⟨run.context, ?_, run.state_wf, ?_⟩ + · simpa [Context.advanceFresh, Context.toTypeChecker] using run.context_eq + · simpa [Context.advanceFresh, NameGenerator.next] using run.namePrefix_ne + +/-- Keep the fixed pre-family Theory environment/universe indices while the +operational traversal advances past an omitted recursive outer field. -/ +def ConstructorContextRun.advanceFresh + (run : ConstructorContextRun env Us context) : + ConstructorContextRun env Us context.advanceFresh where + candidate := advanceCandidateContextRun run.candidate + venv_eq := run.venv_eq + lparams_eq := run.lparams_eq + +/-- Syntactic independence from the recursive outer-field locals omitted by +the pre-family replay context. -/ +def constructorIndependentOf (source : Expr) (removed : List FVarId) : Bool := + source.fvarsList.all fun fv => !removed.contains fv + +/-- Instantiate the analyzer-owned family view with the exact parameter FVars +selected by family validation, leaving the index telescope exposed. -/ +def instantiateFamilyParameters : Expr → List Expr → Except Exception Expr + | familyType, [] => pure familyType + | .forallE _ _ body _, parameter :: parameters => + instantiateFamilyParameters (body.instantiate1 parameter) parameters + | _, _ :: _ => + throw <| .other + "candidate family view has fewer binders than retained parameters" + +/-- Exact successful pre-family `ensureType` observation. -/ +structure ConstructorEnsureTypeObservation + (context : Context) (source : Expr) where + result : Expr + valid : ConstructorEnsureTypeStep.Valid ⟨context, source, result⟩ + +def observeConstructorEnsureType (context : Context) (source : Expr) : + Except Exception (ConstructorEnsureTypeObservation context source) := + match hrun : TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.ensureType source) with + | .error error => .error error + | .ok result => .ok ⟨result, hrun⟩ + +theorem observeConstructorEnsureType_of_run + (run : ConstructorEnsureTypeStep.Valid ⟨context, source, result⟩) : + observeConstructorEnsureType context source = .ok ⟨result, run⟩ := by + change TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.ensureType source) = + .ok result at run + unfold observeConstructorEnsureType + split + · simp_all + · rename_i observed hobserved + have : observed = result := by simp_all + subst observed + rfl + +theorem ConstructorEnsureTypeObservation.observe_eq + (observation : ConstructorEnsureTypeObservation context source) : + observeConstructorEnsureType context source = .ok observation := by + rw [observeConstructorEnsureType_of_run observation.valid] + +/-- One pre-family index argument checked against the corresponding binder of +the parameter-instantiated family view. -/ +structure ConstructorPreFamilyIndexStep + (context : Context) (argument expected : Expr) where + argumentCheck : ConstructorCheckedExpr context argument + expectedCheck : ConstructorCheckedExpr context expected + comparison : CandidateIsDefEqObservation context + argumentCheck.observation.inferred expected + +/-- Source-ordered executable replay of a constructor result/recursive-target +index spine against the analyzer-owned family index telescope. -/ +inductive ConstructorPreFamilyIndexSpineTrace : + (context : Context) → (expected : Expr) → List Expr → Type where + | nil + (context : Context) (expected : Expr) + (expectedCheck : ConstructorCheckedExpr context expected) + (terminal : expected.isForall = false) : + ConstructorPreFamilyIndexSpineTrace context expected [] + | cons + (context : Context) (name : Name) (domain body : Expr) + (binderInfo : BinderInfo) (argument : Expr) (arguments : List Expr) + (expectedCheck : ConstructorCheckedExpr context + (.forallE name domain body binderInfo)) + (step : ConstructorPreFamilyIndexStep context argument domain) + (tail : ConstructorPreFamilyIndexSpineTrace context + (body.instantiate1 argument) arguments) : + ConstructorPreFamilyIndexSpineTrace context + (.forallE name domain body binderInfo) (argument :: arguments) + +namespace ConstructorPreFamilyIndexSpineTrace + +def build : (context : Context) → (expected : Expr) → + (arguments : List Expr) → + Except Exception + (ConstructorPreFamilyIndexSpineTrace context expected arguments) + | context, expected, [] => + if terminal : expected.isForall = false then do + let expectedCheck ← checkConstructorAlignedExpr context expected + pure <| .nil context expected expectedCheck terminal + else + throw <| .other + "constructor target supplies too few family indices" + | context, .forallE name domain body binderInfo, argument :: arguments => do + let telescopeCheck ← checkConstructorAlignedExpr context + (.forallE name domain body binderInfo) + let argumentCheck ← checkConstructorAlignedExpr context argument + let domainCheck ← checkConstructorAlignedExpr context domain + let comparison ← observeCandidateIsDefEq context + argumentCheck.observation.inferred domain + let tail ← build context (body.instantiate1 argument) arguments + pure <| .cons context name domain body binderInfo argument arguments + telescopeCheck ⟨argumentCheck, domainCheck, comparison⟩ tail + | _, _, _ :: _ => + throw <| .other + "constructor target supplies too many family indices" + +end ConstructorPreFamilyIndexSpineTrace + +theorem ConstructorPreFamilyIndexSpineTrace.build_eq + (trace : ConstructorPreFamilyIndexSpineTrace context expected arguments) : + ConstructorPreFamilyIndexSpineTrace.build context expected arguments = + .ok trace := by + induction trace with + | nil expected expectedCheck terminal => + simp only [ConstructorPreFamilyIndexSpineTrace.build] + rw [dif_pos terminal, expectedCheck.check_eq] + rfl + | cons name domain body binderInfo argument arguments + expectedCheck step tail ih => + simp only [ConstructorPreFamilyIndexSpineTrace.build] + rw [expectedCheck.check_eq, step.argumentCheck.check_eq, + step.expectedCheck.check_eq] + simp only [Bind.bind, Except.bind] + rw [step.comparison.observe_eq, ih] + rfl + +/-- The exact full check retained at the root of an index-spine replay. -/ +def ConstructorPreFamilyIndexSpineTrace.expectedCheck : + (trace : ConstructorPreFamilyIndexSpineTrace context expected arguments) → + ConstructorCheckedExpr context expected + | .nil _ _ expectedCheck _ => expectedCheck + | .cons _ _ _ _ _ _ _ expectedCheck _ _ => expectedCheck + +/-! +### Verified pre-family index spines + +The operational trace checks the complete expected family-index telescope at +every recursive position. Its semantic interpretation follows the strict +translation selected at the root, instantiates the translated Pi body with the +translated argument, and therefore constructs an actual Theory `SpineWF` +rather than a pointwise list whose dependencies have been forgotten. +-/ + +/-- Verified meaning of one pre-family index-spine replay. `expected'` is a +strict translation of the exact parameter-instantiated family telescope in the +current context; `arguments'` and `result'` are forced by the retained checker +executions and dependent Pi instantiation. -/ +structure ConstructorPreFamilyIndexSpineSemanticRun + (env : VEnv) (Us : List Name) + (context : Context) (contextRun : ConstructorContextRun env Us context) + {expected : Expr} {arguments : List Expr} + (trace : ConstructorPreFamilyIndexSpineTrace context expected arguments) + (expected' : VExpr) where + expectedInferred' : VExpr + expectedRun : TypeChecker.CheckTypeRun env Us + contextRun.candidate.context.vlctx expected + trace.expectedCheck.observation.inferred expected' expectedInferred' + arguments' : List VExpr + result' : VExpr + arguments_tr : List.Forall₂ + (TrExprS env Us contextRun.candidate.context.vlctx) + arguments arguments' + spine : env.SpineWF Us.length contextRun.candidate.context.vlctx.toCtx + expected' arguments' result' + +namespace ConstructorPreFamilyIndexSpineSemanticRun + +/-- Interpret a spine at a caller-fixed strict translation of its expected +telescope. Recursive calls receive the translated Pi body instantiated with +the exact checker-selected argument translation. -/ +theorem nonempty_at + (contextRun : ConstructorContextRun env Us context) + (trace : ConstructorPreFamilyIndexSpineTrace context expected arguments) + (expected' : VExpr) + (expected_tr : TrExprS env Us + contextRun.candidate.context.vlctx expected expected') : + Nonempty (ConstructorPreFamilyIndexSpineSemanticRun env Us context + contextRun trace expected') := by + induction trace generalizing expected' with + | nil expected expectedCheck terminal => + have expected_tr' : contextRun.candidate.context.TrExprS expected + expected' := by + simpa only [VContext.TrExprS, contextRun.venv_eq, + contextRun.lparams_eq] using expected_tr + obtain ⟨expectedInferred', ⟨expectedRun⟩⟩ := + TypeChecker.CheckTypeRun.exists_ofCandidateStep + ⟨context, expected, expectedCheck.observation.inferred⟩ + expectedCheck.observation.valid contextRun.candidate expected' + expected_tr' + exact ⟨{ + expectedInferred' := expectedInferred' + expectedRun := by + simpa only [ConstructorPreFamilyIndexSpineTrace.expectedCheck, + contextRun.venv_eq, contextRun.lparams_eq] using expectedRun + arguments' := [] + result' := expected' + arguments_tr := .nil + spine := .nil }⟩ + | cons name domain body binderInfo argument arguments telescopeCheck + step tail ih => + obtain ⟨domain', body', rfl, domainType, bodyType, domain_tr, + body_tr⟩ := TypeChecker.TrExprS.forallE_components expected_tr + have telescope_tr' : contextRun.candidate.context.TrExprS + (.forallE name domain body binderInfo) (.forallE domain' body') := by + simpa only [VContext.TrExprS, contextRun.venv_eq, + contextRun.lparams_eq] using expected_tr + obtain ⟨expectedInferred', ⟨expectedRun⟩⟩ := + TypeChecker.CheckTypeRun.exists_ofCandidateStep + ⟨context, .forallE name domain body binderInfo, + telescopeCheck.observation.inferred⟩ + telescopeCheck.observation.valid contextRun.candidate + (.forallE domain' body') telescope_tr' + have domain_tr' : contextRun.candidate.context.TrExprS domain domain' := by + simpa only [VContext.TrExprS, contextRun.venv_eq, + contextRun.lparams_eq] using domain_tr + obtain ⟨domainInferred', ⟨domainCheck⟩⟩ := + TypeChecker.CheckTypeRun.exists_ofCandidateStep + ⟨context, domain, step.expectedCheck.observation.inferred⟩ + step.expectedCheck.observation.valid contextRun.candidate domain' + domain_tr' + let domainRun : ConstructorCheckedExpr.Run step.expectedCheck + contextRun.candidate := ⟨domain', domainInferred', domainCheck⟩ + obtain ⟨argumentRun⟩ := ConstructorCheckedExpr.Run.exists + step.argumentCheck contextRun.candidate + let comparisonRun := TypeChecker.IsDefEqRun.ofCandidateStep + ⟨context, step.argumentCheck.observation.inferred, domain⟩ + step.comparison.valid contextRun.candidate.context + contextRun.candidate.context_eq rfl rfl rfl + contextRun.candidate.state_wf argumentRun.check.inferred_tr + domainRun.check.expr_tr context.fuel.recDepth rfl + have argumentType' : contextRun.candidate.context.HasType + argumentRun.source' domain' := + argumentRun.check.hasType.defeqU_r + contextRun.candidate.context.Ewf + contextRun.candidate.context.Δwf.toCtx comparisonRun.isDefEqU + have argumentType : env.HasType Us.length + contextRun.candidate.context.vlctx.toCtx argumentRun.source' + domain' := by + simpa only [VContext.HasType, contextRun.venv_eq, + contextRun.lparams_eq] using argumentType' + have argument_tr : TrExprS env Us + contextRun.candidate.context.vlctx argument argumentRun.source' := by + simpa only [contextRun.venv_eq, contextRun.lparams_eq] using + argumentRun.check.expr_tr + have henv : VEnv.WF env := by + simpa only [contextRun.venv_eq] using + contextRun.candidate.context.Ewf + have instantiatedBody_tr : TrExprS env Us + contextRun.candidate.context.vlctx + (body.instantiate1 argument) (body'.inst argumentRun.source') := by + simpa only [Expr.instantiate1_eq] using + body_tr.inst henv.ordered argumentType argument_tr + obtain ⟨tailRun⟩ := ih (body'.inst argumentRun.source') + instantiatedBody_tr + exact ⟨{ + expectedInferred' := expectedInferred' + expectedRun := by + simpa only [ConstructorPreFamilyIndexSpineTrace.expectedCheck, + contextRun.venv_eq, contextRun.lparams_eq] using expectedRun + arguments' := argumentRun.source' :: tailRun.arguments' + result' := tailRun.result' + arguments_tr := .cons argument_tr tailRun.arguments_tr + spine := .cons argumentType tailRun.spine }⟩ + +/-- Every successful operational spine trace has a verified interpretation; +the initial strict endpoint is selected by the trace's own root `checkType`. -/ +theorem nonempty + (contextRun : ConstructorContextRun env Us context) + (trace : ConstructorPreFamilyIndexSpineTrace context expected arguments) : + ∃ expected', Nonempty + (ConstructorPreFamilyIndexSpineSemanticRun env Us context contextRun + trace expected') := by + obtain ⟨expectedRun⟩ := ConstructorCheckedExpr.Run.exists + trace.expectedCheck contextRun.candidate + have expected_tr : TrExprS env Us + contextRun.candidate.context.vlctx expected expectedRun.source' := by + simpa only [contextRun.venv_eq, contextRun.lparams_eq] using + expectedRun.check.expr_tr + exact ⟨expectedRun.source', nonempty_at contextRun trace _ expected_tr⟩ + +/-- Strict family translation fixes the expected endpoint chosen by an exact +pre-family index replay, even when the replay context contains a later prefix +of fresh locals. -/ +theorem expected_eq_of_family + {env : VEnv} {Us : List Name} {context : Context} + {contextRun : ConstructorContextRun env Us context} + {expected : Expr} {arguments : List Expr} + {trace : ConstructorPreFamilyIndexSpineTrace context expected arguments} + {expected' : VExpr} + (run : ConstructorPreFamilyIndexSpineSemanticRun env Us context + contextRun trace expected') + {parameterΔ viewΔ : VLCtx} {expectedBase : VExpr} {n : Nat} + (familyTr : TrExprS env Us parameterΔ expected expectedBase) + (unique : TrExprS.IsUnique expected) + (viewLift : VLCtx.FVLift' parameterΔ viewΔ 0 + (.skipN .refl n) 0) + (viewDefEq : VLCtx.IsDefEq env Us.length + contextRun.candidate.context.vlctx viewΔ) + (viewUnique : TrExprS.IsUniqueCtx + contextRun.candidate.context.vlctx viewΔ) : + expected' = expectedBase.liftN n 0 := by + have henv : VEnv.Ordered env := by + simpa only [contextRun.venv_eq] using + contextRun.candidate.context.Ewf.ordered + have viewWF : VLCtx.WF env Us.length viewΔ := + (viewDefEq.symm henv).wf + have familyAtView : TrExprS env Us viewΔ expected + (expectedBase.liftN n 0) := by + simpa only [VExpr.lift'_consN_skipN] using + familyTr.weakFV' henv viewLift viewWF + have retained : TrExprS env Us contextRun.candidate.context.vlctx + expected expected' := run.expectedRun.expr_tr + exact retained.unique' viewUnique unique familyAtView + +/-- Transport the exact pre-family index judgment below an arbitrary later +prefix. This is the proved context weakening used when D4 places the same +spine beneath the remaining constructor fields. -/ +theorem spine_weakPrefix + {expected : Expr} {arguments : List Expr} + {replay : ConstructorPreFamilyIndexSpineTrace context expected arguments} + {expected' : VExpr} + (run : ConstructorPreFamilyIndexSpineSemanticRun env Us context contextRun + replay expected') (Bs : List VExpr) : + env.SpineWF Us.length + (Bs ++ contextRun.candidate.context.vlctx.toCtx) + (expected'.liftN Bs.length 0) + (run.arguments'.map fun argument => + argument.liftN Bs.length 0) + (run.result'.liftN Bs.length 0) := by + have henv : VEnv.WF env := by + simpa only [contextRun.venv_eq] using contextRun.candidate.context.Ewf + exact run.spine.weakN henv.ordered + (Ctx.LiftN.zero (n := Bs.length) + (Γ := contextRun.candidate.context.vlctx.toCtx) Bs) + +end ConstructorPreFamilyIndexSpineSemanticRun + +/-- Pre-family replay of the family-free pieces of one recursive field. Π +domains are checked and introduced normally; the terminal family application +is replaced by an index-spine replay, so the absent family constant is never +looked up. -/ +inductive ConstructorPreFamilyRecursiveTrace + (stats : InductiveStats) (familyIdx : Nat) (familyIndices : Expr) : + (context : Context) → (source : Expr) → (fuel : Nat) → Type where + | forallE + (context : Context) (name : Name) (domain body : Expr) + (binderInfo : BinderInfo) + (domainCheck : ConstructorCheckedExpr context domain) + (ensureType : ConstructorEnsureTypeObservation context domain) + (consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)) + (annotations : CandidateIsDefEqObservation context domain + (consumeTypeAnnotations domain)) + (fresh : context.lctx.find? context.freshFVarId = none) + (tail : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel) : + ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices context + (.forallE name domain body binderInfo) (fuel + 1) + | target + (context : Context) (source : Expr) + (valid : isValidIndAppIdx stats source familyIdx = true) + (spine : ConstructorPreFamilyIndexSpineTrace context familyIndices + (source.getAppArgs.toList.drop stats.params.size)) : + ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices context + source (fuel + 1) + +namespace ConstructorPreFamilyRecursiveTrace + +def build (stats : InductiveStats) (familyIdx : Nat) + (familyIndices : Expr) : + (context : Context) → (source : Expr) → (fuel : Nat) → + Except Exception + (ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel) + | _, _, 0 => throw .deepRecursion + | context, .forallE name domain body binderInfo, fuel + 1 => do + let domainCheck ← checkConstructorAlignedExpr context domain + let ensureType ← observeConstructorEnsureType context domain + let consumedCheck ← checkConstructorAlignedExpr context + (consumeTypeAnnotations domain) + let annotations ← observeCandidateIsDefEq context domain + (consumeTypeAnnotations domain) + if fresh : context.lctx.find? context.freshFVarId = none then + let tail ← build stats familyIdx familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel + pure <| .forallE context name domain body binderInfo domainCheck + ensureType consumedCheck annotations fresh tail + else + throw <| .other + "pre-family recursive replay reused a local identifier" + | context, source, _ + 1 => do + if valid : isValidIndAppIdx stats source familyIdx = true then + let spine ← ConstructorPreFamilyIndexSpineTrace.build context + familyIndices + (source.getAppArgs.toList.drop stats.params.size) + pure <| .target context source valid spine + else + throw <| .other + "pre-family recursive replay reached a non-family target" + +end ConstructorPreFamilyRecursiveTrace + +theorem ConstructorPreFamilyRecursiveTrace.forallE_build_eq + (domainCheck : ConstructorCheckedExpr context domain) + (ensureType : ConstructorEnsureTypeObservation context domain) + (consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)) + (annotations : CandidateIsDefEqObservation context domain + (consumeTypeAnnotations domain)) + (fresh : context.lctx.find? context.freshFVarId = none) + (tail : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel) + (tailRun : ConstructorPreFamilyRecursiveTrace.build stats familyIdx + familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel = .ok tail) : + ConstructorPreFamilyRecursiveTrace.build stats familyIdx familyIndices + context (.forallE name domain body binderInfo) (fuel + 1) = + .ok (.forallE context name domain body binderInfo domainCheck ensureType + consumedCheck annotations fresh tail) := by + simp only [ConstructorPreFamilyRecursiveTrace.build] + rw [domainCheck.check_eq, ensureType.observe_eq, consumedCheck.check_eq] + simp only [Bind.bind, Except.bind] + rw [annotations.observe_eq] + simp only [] + rw [dif_pos fresh, tailRun] + rfl + +theorem ConstructorPreFamilyRecursiveTrace.target_build_eq + (terminal : source.isForall = false) + (valid : isValidIndAppIdx stats source familyIdx = true) + (spine : ConstructorPreFamilyIndexSpineTrace context familyIndices + (source.getAppArgs.toList.drop stats.params.size)) : + ConstructorPreFamilyRecursiveTrace.build stats familyIdx familyIndices + context source (fuel + 1) = + .ok (.target context source valid spine) := by + cases source <;> simp only [ConstructorPreFamilyRecursiveTrace.build] + case forallE => simp [Expr.isForall] at terminal + all_goals + rw [dif_pos valid, spine.build_eq] + rfl + +/-! +### Verified pre-family recursive fields + +Recursive outer-field locals are intentionally absent here. Nested Pi binders +inside the field are family-free, so they are checked, interpreted, and pushed +normally. The terminal family application contributes only its already-verified +index spine. +-/ + +/-- Componentwise verified interpretation of a recursive field replay. -/ +inductive ConstructorPreFamilyRecursiveSemanticRun + (env : VEnv) (Us : List Name) + (stats : InductiveStats) (familyIdx : Nat) (familyIndices : Expr) : + {context : Context} → {source : Expr} → {fuel : Nat} → + (contextRun : ConstructorContextRun env Us context) → + ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices context + source fuel → Type where + | forallE + {context : Context} {name : Name} {domain body : Expr} + {binderInfo : BinderInfo} {fuel : Nat} + {domainCheck : ConstructorCheckedExpr context domain} + {ensureType : ConstructorEnsureTypeObservation context domain} + {consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)} + {annotations : CandidateIsDefEqObservation context domain + (consumeTypeAnnotations domain)} + {fresh : context.lctx.find? context.freshFVarId = none} + {tailTrace : ConstructorPreFamilyRecursiveTrace stats familyIdx + familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) fuel} + {contextRun : ConstructorContextRun env Us context} + (domainRun : ConstructorCheckedExpr.Run domainCheck + contextRun.candidate) + (consumedRun : ConstructorCheckedExpr.Run consumedCheck + contextRun.candidate) + (ensureTypeRun : TypeChecker.EnsureTypeRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain ensureType.result + domainRun.source') + (annotationsRun : TypeChecker.IsDefEqRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain + (consumeTypeAnnotations domain) domainRun.source' + consumedRun.source') + (consumedType : contextRun.candidate.context.IsType + consumedRun.source') + (tail : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices + (contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType) + tailTrace) : + ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun + (.forallE context name domain body binderInfo domainCheck ensureType + consumedCheck annotations fresh tailTrace) + | target + {context : Context} {source : Expr} {fuel : Nat} + {valid : isValidIndAppIdx stats source familyIdx = true} + {spineTrace : ConstructorPreFamilyIndexSpineTrace context familyIndices + (source.getAppArgs.toList.drop stats.params.size)} + {contextRun : ConstructorContextRun env Us context} + (expected' : VExpr) + (spine : ConstructorPreFamilyIndexSpineSemanticRun env Us context + contextRun spineTrace expected') : + ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun (.target context source valid spineTrace) + +namespace ConstructorPreFamilyRecursiveSemanticRun + +/-- Interpret every retained nested-binder and terminal-index operation in the +exact verified pre-family context. -/ +theorem nonempty + (contextRun : ConstructorContextRun env Us context) + (trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel) : + Nonempty (ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) := by + induction trace with + | forallE context name domain body binderInfo domainCheck ensureType + consumedCheck annotations fresh tailTrace ih => + obtain ⟨domainRun⟩ := ConstructorCheckedExpr.Run.exists domainCheck + contextRun.candidate + obtain ⟨consumedRun⟩ := ConstructorCheckedExpr.Run.exists consumedCheck + contextRun.candidate + obtain ⟨ensureTypeRun⟩ := + TypeChecker.EnsureTypeRun.exists_ofConstructorStep + ⟨context, domain, ensureType.result⟩ ensureType.valid + contextRun.candidate domainRun.source' domainRun.check.expr_tr + let annotationsRun := domainRun.isDefEq consumedRun annotations + have consumedType : contextRun.candidate.context.IsType + consumedRun.source' := by + have annotationDef := annotationsRun.isDefEqU.of_l + contextRun.candidate.context.Ewf + contextRun.candidate.context.Δwf.toCtx ensureTypeRun.source_type + exact ⟨ensureTypeRun.resultLevel', annotationDef.hasType.2⟩ + let tailContext := contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType + obtain ⟨tail⟩ := ih tailContext + exact ⟨.forallE domainRun consumedRun ensureTypeRun annotationsRun + consumedType tail⟩ + | @target traceFuel context source valid spineTrace => + obtain ⟨expected', ⟨spine⟩⟩ := + ConstructorPreFamilyIndexSpineSemanticRun.nonempty contextRun spineTrace + exact ⟨@ConstructorPreFamilyRecursiveSemanticRun.target + env Us stats familyIdx familyIndices traceFuel + context source (traceFuel + 1) valid spineTrace contextRun expected' spine⟩ + +/-- The verified nested Π-binder telescope retained by the recursive field. -/ +def binders + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) : List VExpr := + match run with + | .forallE _ consumedRun _ _ _ tail => consumedRun.source' :: tail.binders + | .target _ _ => [] + +/-- Translation selected for the analyzer-owned family-index telescope. -/ +def expected' + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) : VExpr := + match run with + | .forallE _ _ _ _ _ tail => tail.expected' + | .target expected' _ => expected' + +/-- Translated terminal recursive indices, in source order. -/ +def indices' + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) : List VExpr := + match run with + | .forallE _ _ _ _ _ tail => tail.indices' + | .target _ spine => spine.arguments' + +/-- Translated result type of the terminal recursive index application. -/ +def result' + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) : VExpr := + match run with + | .forallE _ _ _ _ _ tail => tail.result' + | .target _ spine => spine.result' + +/-- The retained recursive Π domains form a verified Theory telescope in the +exact pre-family context. -/ +theorem onTel + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) : + env.OnTel Us.length contextRun.candidate.context.vlctx.toCtx run.binders := by + induction run with + | @forallE context name domain body binderInfo fuel domainCheck ensureType + consumedCheck annotations fresh tailTrace branchContextRun domainRun + consumedRun ensureTypeRun annotationsRun consumedType tail ih => + constructor + · simpa only [VContext.IsType, branchContextRun.venv_eq, + branchContextRun.lparams_eq] using consumedType + · simpa only [binders, ConstructorContextRun.pushLocalDecl, + CandidateContextRun.pushLocalDecl_vlctx, VLCtx.toCtx] using ih + | target => trivial + +/-- The terminal recursive indices have the expected analyzer-owned family +index telescope, below all retained nested Π binders. -/ +theorem spine + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) : + env.SpineWF Us.length + (run.binders.reverse ++ contextRun.candidate.context.vlctx.toCtx) + run.expected' run.indices' run.result' := by + induction run with + | forallE domainRun consumedRun ensureTypeRun annotationsRun consumedType tail ih => + simpa only [binders, expected', indices', result', List.reverse_cons, + List.singleton_append, List.append_assoc, + ConstructorContextRun.pushLocalDecl, + CandidateContextRun.pushLocalDecl_vlctx, VLCtx.toCtx] using ih + | target expectedType spine => + simpa only [binders, expected', indices', result', List.reverse_nil, + List.nil_append] using spine.spine + +/-- Weaken the retained recursive Π telescope over a later prefix of omitted +outer recursive fields. -/ +theorem onTel_weakPrefix + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) (Bs : List VExpr) : + env.OnTel Us.length + (Bs ++ contextRun.candidate.context.vlctx.toCtx) + (VExpr.liftTelN Bs.length run.binders 0) := by + have henv : VEnv.WF env := by + simpa only [contextRun.venv_eq] using contextRun.candidate.context.Ewf + exact run.onTel.weakN henv.ordered + (Ctx.LiftN.zero (n := Bs.length) + (Γ := contextRun.candidate.context.vlctx.toCtx) Bs) + +/-- Weaken the terminal recursive index judgment below the same omitted outer +field prefix, preserving the nested Π-binder depths. -/ +theorem spine_weakPrefix + {context : Context} {source : Expr} {fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyRecursiveTrace stats familyIdx familyIndices + context source fuel} + (run : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun trace) (Bs : List VExpr) : + env.SpineWF Us.length + ((VExpr.liftTelN Bs.length run.binders 0).reverse ++ + Bs ++ contextRun.candidate.context.vlctx.toCtx) + (run.expected'.liftN Bs.length run.binders.length) + (run.indices'.map fun index => + index.liftN Bs.length run.binders.length) + (run.result'.liftN Bs.length run.binders.length) := by + have henv : VEnv.WF env := by + simpa only [contextRun.venv_eq] using contextRun.candidate.context.Ewf + simpa only [List.append_assoc, Nat.add_zero] using + run.spine.weakN henv.ordered + (Ctx.LiftN.consTel run.binders + (Ctx.LiftN.zero (n := Bs.length) + (Γ := contextRun.candidate.context.vlctx.toCtx) Bs)) + +end ConstructorPreFamilyRecursiveSemanticRun + +/-- Exact executable pre-family replay for one analyzer-owned constructor view. + +`removed` contains precisely the validation FVars allocated for recursive +outer fields that were not inserted into the pre-family checker context. +`recursiveStarted` records whether such a field has been crossed; later +ordinary fields are admitted exactly when they are independent of `removed`. -/ +inductive ConstructorPreFamilyViewTrace + (stats : InductiveStats) (familyIdx : Nat) (familyIndices : Expr) : + (context : Context) → (view : Expr) → (argIdx : Nat) → + (removed : List FVarId) → (recursiveStarted : Bool) → Type where + | parameter + (context : Context) (argIdx : Nat) (removed : List FVarId) + (recursiveStarted : Bool) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (parameter : Expr) + (parameterAt : stats.params[argIdx]? = some parameter) + (tail : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + context (body.instantiate1 parameter) (argIdx + 1) removed + recursiveStarted) : + ConstructorPreFamilyViewTrace stats familyIdx familyIndices context + (.forallE name domain body binderInfo) argIdx removed recursiveStarted + | ordinary + (context : Context) (argIdx : Nat) (removed : List FVarId) + (recursiveStarted : Bool) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (noParameter : stats.params[argIdx]? = none) + (nonrecursive : hasIndOcc stats.indConsts domain = false) + (independent : constructorIndependentOf domain removed = true) + (domainCheck : ConstructorCheckedExpr context domain) + (ensureType : ConstructorEnsureTypeObservation context domain) + (consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)) + (annotations : CandidateIsDefEqObservation context domain + (consumeTypeAnnotations domain)) + (fresh : context.lctx.find? context.freshFVarId = none) + (tail : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) removed + recursiveStarted) : + ConstructorPreFamilyViewTrace stats familyIdx familyIndices context + (.forallE name domain body binderInfo) argIdx removed recursiveStarted + | recursive + (context : Context) (argIdx : Nat) (removed : List FVarId) + (recursiveStarted : Bool) + (name : Name) (domain body : Expr) (binderInfo : BinderInfo) + (noParameter : stats.params[argIdx]? = none) + (isRecursive : hasIndOcc stats.indConsts domain = true) + (independent : constructorIndependentOf domain removed = true) + (field : ConstructorPreFamilyRecursiveTrace stats familyIdx + familyIndices context domain context.fuel.inductiveFuel) + (fresh : context.lctx.find? context.freshFVarId = none) + (tail : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + context.advanceFresh (body.instantiate1 context.freshExpr) + (argIdx + 1) (context.freshFVarId :: removed) true) : + ConstructorPreFamilyViewTrace stats familyIdx familyIndices context + (.forallE name domain body binderInfo) argIdx removed recursiveStarted + | terminal + (context : Context) (source : Expr) (argIdx : Nat) + (removed : List FVarId) (recursiveStarted : Bool) + (valid : isValidIndAppIdx stats source familyIdx = true) + (independent : constructorIndependentOf source removed = true) + (spine : ConstructorPreFamilyIndexSpineTrace context familyIndices + (source.getAppArgs.toList.drop stats.params.size)) : + ConstructorPreFamilyViewTrace stats familyIdx familyIndices context + source argIdx removed recursiveStarted + +namespace ConstructorPreFamilyViewTrace + +def build (stats : InductiveStats) (familyIdx : Nat) + (familyIndices : Expr) : + (context : Context) → (view : Expr) → (argIdx : Nat) → + (removed : List FVarId) → (recursiveStarted : Bool) → (fuel : Nat) → + Except Exception + (ConstructorPreFamilyViewTrace stats familyIdx familyIndices context view + argIdx removed recursiveStarted) + | _, _, _, _, _, 0 => throw .deepRecursion + | context, .forallE name domain body binderInfo, argIdx, removed, + recursiveStarted, fuel + 1 => + match parameterAt : stats.params[argIdx]? with + | some param => do + let tail ← build stats familyIdx familyIndices context + (body.instantiate1 param) (argIdx + 1) removed + recursiveStarted fuel + pure <| .parameter context argIdx removed recursiveStarted name domain + body binderInfo param parameterAt tail + | none => do + match recursive : hasIndOcc stats.indConsts domain with + | false => + if independent : constructorIndependentOf domain removed = true then + let domainCheck ← checkConstructorAlignedExpr context domain + let ensureType ← observeConstructorEnsureType context domain + let consumedCheck ← checkConstructorAlignedExpr context + (consumeTypeAnnotations domain) + let annotations ← observeCandidateIsDefEq context domain + (consumeTypeAnnotations domain) + if fresh : context.lctx.find? context.freshFVarId = none then + let tail ← build stats familyIdx familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) + removed recursiveStarted fuel + pure <| .ordinary context argIdx removed recursiveStarted + name domain body binderInfo parameterAt recursive independent domainCheck + ensureType consumedCheck annotations fresh tail + else + throw <| .other + "pre-family ordinary replay reused a local identifier" + else + throw <| .other + "constructor depends on an omitted recursive local" + | true => + if independent : constructorIndependentOf domain removed = true then + let field ← ConstructorPreFamilyRecursiveTrace.build stats + familyIdx familyIndices context domain + context.fuel.inductiveFuel + if fresh : context.lctx.find? context.freshFVarId = none then + let tail ← build stats familyIdx familyIndices + context.advanceFresh + (body.instantiate1 context.freshExpr) (argIdx + 1) + (context.freshFVarId :: removed) true fuel + pure <| .recursive context argIdx removed recursiveStarted + name domain body binderInfo parameterAt recursive independent + field fresh tail + else + throw <| .other + "pre-family recursive replay reused a local identifier" + else + throw <| .other + "constructor depends on an omitted recursive local" + | context, source, argIdx, removed, recursiveStarted, _ + 1 => do + if valid : isValidIndAppIdx stats source familyIdx = true then + if independent : constructorIndependentOf source removed = true then + let spine ← ConstructorPreFamilyIndexSpineTrace.build context + familyIndices + (source.getAppArgs.toList.drop stats.params.size) + pure <| .terminal context source argIdx removed recursiveStarted valid + independent spine + else + throw <| .other + "constructor result depends on an omitted recursive local" + else + throw <| .other + "pre-family replay reached a non-family constructor result" + +end ConstructorPreFamilyViewTrace + +theorem ConstructorPreFamilyViewTrace.terminal_build_eq + (terminal : source.isForall = false) + (valid : isValidIndAppIdx stats source familyIdx = true) + (independent : constructorIndependentOf source removed = true) + (spine : ConstructorPreFamilyIndexSpineTrace context familyIndices + (source.getAppArgs.toList.drop stats.params.size)) : + ConstructorPreFamilyViewTrace.build stats familyIdx familyIndices + context source argIdx removed recursiveStarted (fuel + 1) = + .ok (.terminal context source argIdx removed recursiveStarted valid + independent spine) := by + cases source <;> simp only [ConstructorPreFamilyViewTrace.build] + case forallE => simp [Expr.isForall] at terminal + all_goals + rw [dif_pos valid, dif_pos independent, spine.build_eq] + rfl + +/-! +### Verified pre-family constructor views + +This interpretation follows the exact executable D3 trace. Ordinary fields +are checked and pushed in the pre-family context, recursive outer fields are +omitted while their family-free nested binders and indices are retained, and +the terminal result contributes its verified index spine. +-/ + +/-- Verified meaning of every family-free operation retained by one exact +pre-family constructor-view replay. -/ +inductive ConstructorPreFamilyViewSemanticRun + (env : VEnv) (Us : List Name) + (stats : InductiveStats) (familyIdx : Nat) (familyIndices : Expr) : + {context : Context} → {view : Expr} → {argIdx : Nat} → + {removed : List FVarId} → {recursiveStarted : Bool} → + (contextRun : ConstructorContextRun env Us context) → + ConstructorPreFamilyViewTrace stats familyIdx familyIndices context view + argIdx removed recursiveStarted → Type where + | parameter + {context : Context} {argIdx : Nat} {removed : List FVarId} + {recursiveStarted : Bool} + {name : Name} {domain body : Expr} {binderInfo : BinderInfo} + {parameter : Expr} + {parameterAt : stats.params[argIdx]? = some parameter} + {tailTrace : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + context (body.instantiate1 parameter) (argIdx + 1) removed + recursiveStarted} + {contextRun : ConstructorContextRun env Us context} + (tail : ConstructorPreFamilyViewSemanticRun env Us stats familyIdx + familyIndices contextRun tailTrace) : + ConstructorPreFamilyViewSemanticRun env Us stats familyIdx familyIndices + contextRun + (.parameter context argIdx removed recursiveStarted name domain body + binderInfo parameter parameterAt tailTrace) + | ordinary + {context : Context} {argIdx : Nat} {removed : List FVarId} + {recursiveStarted : Bool} + {name : Name} {domain body : Expr} {binderInfo : BinderInfo} + {noParameter : stats.params[argIdx]? = none} + {nonrecursive : hasIndOcc stats.indConsts domain = false} + {independent : constructorIndependentOf domain removed = true} + {domainCheck : ConstructorCheckedExpr context domain} + {ensureType : ConstructorEnsureTypeObservation context domain} + {consumedCheck : ConstructorCheckedExpr context + (consumeTypeAnnotations domain)} + {annotations : CandidateIsDefEqObservation context domain + (consumeTypeAnnotations domain)} + {fresh : context.lctx.find? context.freshFVarId = none} + {tailTrace : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + (body.instantiate1 context.freshExpr) (argIdx + 1) removed + recursiveStarted} + {contextRun : ConstructorContextRun env Us context} + (domainRun : ConstructorCheckedExpr.Run domainCheck + contextRun.candidate) + (consumedRun : ConstructorCheckedExpr.Run consumedCheck + contextRun.candidate) + (ensureTypeRun : TypeChecker.EnsureTypeRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain ensureType.result + domainRun.source') + (annotationsRun : TypeChecker.IsDefEqRun + contextRun.candidate.context.venv + contextRun.candidate.context.lparams + contextRun.candidate.context.vlctx domain + (consumeTypeAnnotations domain) domainRun.source' + consumedRun.source') + (consumedType : contextRun.candidate.context.IsType + consumedRun.source') + (tail : ConstructorPreFamilyViewSemanticRun env Us stats familyIdx + familyIndices + (contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType) + tailTrace) : + ConstructorPreFamilyViewSemanticRun env Us stats familyIdx familyIndices + contextRun + (.ordinary context argIdx removed recursiveStarted name domain body + binderInfo noParameter nonrecursive independent domainCheck ensureType + consumedCheck annotations fresh tailTrace) + | recursive + {context : Context} {argIdx : Nat} {removed : List FVarId} + {recursiveStarted : Bool} + {name : Name} {domain body : Expr} {binderInfo : BinderInfo} + {noParameter : stats.params[argIdx]? = none} + {isRecursive : hasIndOcc stats.indConsts domain = true} + {independent : constructorIndependentOf domain removed = true} + {fieldTrace : ConstructorPreFamilyRecursiveTrace stats familyIdx + familyIndices context domain context.fuel.inductiveFuel} + {fresh : context.lctx.find? context.freshFVarId = none} + {tailTrace : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + context.advanceFresh (body.instantiate1 context.freshExpr) + (argIdx + 1) (context.freshFVarId :: removed) true} + {contextRun : ConstructorContextRun env Us context} + (field : ConstructorPreFamilyRecursiveSemanticRun env Us stats familyIdx + familyIndices contextRun fieldTrace) + (tail : ConstructorPreFamilyViewSemanticRun env Us stats familyIdx + familyIndices contextRun.advanceFresh tailTrace) : + ConstructorPreFamilyViewSemanticRun env Us stats familyIdx familyIndices + contextRun + (.recursive context argIdx removed recursiveStarted name domain body + binderInfo noParameter isRecursive independent fieldTrace fresh + tailTrace) + | terminal + {context : Context} {source : Expr} {argIdx : Nat} + {removed : List FVarId} {recursiveStarted : Bool} + {valid : isValidIndAppIdx stats source familyIdx = true} + {independent : constructorIndependentOf source removed = true} + {spineTrace : ConstructorPreFamilyIndexSpineTrace context familyIndices + (source.getAppArgs.toList.drop stats.params.size)} + {contextRun : ConstructorContextRun env Us context} + (expected' : VExpr) + (spine : ConstructorPreFamilyIndexSpineSemanticRun env Us context + contextRun spineTrace expected') : + ConstructorPreFamilyViewSemanticRun env Us stats familyIdx familyIndices + contextRun + (.terminal context source argIdx removed recursiveStarted valid + independent spineTrace) + +namespace ConstructorPreFamilyViewSemanticRun + +/-- Interpret every exact family-free checker observation in a successful +constructor-view replay. -/ +theorem nonempty + (contextRun : ConstructorContextRun env Us context) + (trace : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + context view argIdx removed recursiveStarted) : + Nonempty (ConstructorPreFamilyViewSemanticRun env Us stats familyIdx + familyIndices contextRun trace) := by + induction trace with + | parameter context argIdx removed recursiveStarted name domain body + binderInfo parameter parameterAt tailTrace ih => + obtain ⟨tail⟩ := ih contextRun + exact ⟨.parameter tail⟩ + | ordinary context argIdx removed recursiveStarted name domain body + binderInfo noParameter nonrecursive independent domainCheck ensureType + consumedCheck annotations fresh tailTrace ih => + obtain ⟨domainRun⟩ := ConstructorCheckedExpr.Run.exists domainCheck + contextRun.candidate + obtain ⟨consumedRun⟩ := ConstructorCheckedExpr.Run.exists consumedCheck + contextRun.candidate + obtain ⟨ensureTypeRun⟩ := + TypeChecker.EnsureTypeRun.exists_ofConstructorStep + ⟨context, domain, ensureType.result⟩ ensureType.valid + contextRun.candidate domainRun.source' domainRun.check.expr_tr + let annotationsRun := domainRun.isDefEq consumedRun annotations + have consumedType : contextRun.candidate.context.IsType + consumedRun.source' := by + have annotationDef := annotationsRun.isDefEqU.of_l + contextRun.candidate.context.Ewf + contextRun.candidate.context.Δwf.toCtx ensureTypeRun.source_type + exact ⟨ensureTypeRun.resultLevel', annotationDef.hasType.2⟩ + let tailContext := contextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedType + obtain ⟨tail⟩ := ih tailContext + exact ⟨.ordinary domainRun consumedRun ensureTypeRun annotationsRun + consumedType tail⟩ + | recursive context argIdx removed recursiveStarted name domain body + binderInfo noParameter isRecursive independent fieldTrace fresh + tailTrace tailIH => + obtain ⟨field⟩ := + ConstructorPreFamilyRecursiveSemanticRun.nonempty contextRun fieldTrace + obtain ⟨tail⟩ := tailIH contextRun.advanceFresh + exact ⟨.recursive field tail⟩ + | terminal context source argIdx removed recursiveStarted valid independent + spineTrace => + obtain ⟨expected', ⟨spine⟩⟩ := + ConstructorPreFamilyIndexSpineSemanticRun.nonempty contextRun spineTrace + exact ⟨.terminal expected' spine⟩ + +end ConstructorPreFamilyViewSemanticRun + +private theorem drop_eq_cons_of_getElem?_eq_some + {values : List α} {index : Nat} {value : α} + (atIndex : values[index]? = some value) : + values.drop index = value :: values.drop (index + 1) := by + induction values generalizing index with + | nil => simp at atIndex + | cons head tail ih => + cases index with + | zero => + simp at atIndex + simp [atIndex] + | succ index => + simp at atIndex ⊢ + simpa [Nat.add_assoc, Nat.add_comm 1] using ih atIndex + +private theorem eq_length_of_getElem?_eq_none + {values : List α} {index : Nat} + (atIndex : values[index]? = none) + (indexLe : index ≤ values.length) : + index = values.length := by + induction values generalizing index with + | nil => simp_all + | cons head tail ih => + cases index with + | zero => simp at atIndex + | succ index => + simp at atIndex + simp only [List.length_cons, Nat.succ_le_succ_iff] at indexLe + have indexEq : index = tail.length := + Nat.le_antisymm indexLe atIndex + simp [indexEq] + +/-- The exact D3 suffix after consuming every validator-owned parameter. +The context is unchanged because parameter branches instantiate existing +locals rather than pushing constructor fields. -/ +structure ConstructorPreFamilyParameterSuffix + {env : VEnv} {Us : List Name} + {stats : InductiveStats} {familyIndices : Expr} + {context : Context} + {removed : List FVarId} {recursiveStarted : Bool} + {contextRun : ConstructorContextRun env Us context} + (rest : Expr) where + trace : ConstructorPreFamilyViewTrace stats 0 familyIndices + context rest stats.params.size removed recursiveStarted + semantic : ConstructorPreFamilyViewSemanticRun env Us stats 0 + familyIndices contextRun trace + +namespace ConstructorPreFamilyViewSemanticRun + +/-- Strip the exact validator-owned parameter prefix from a verified D3 +view trace. The successful executable instantiation equation excludes an +early terminal, while the indexed parameter lookups exclude an early field. -/ +theorem afterParameters + {env : VEnv} {Us : List Name} + {stats : InductiveStats} {familyIndices : Expr} + {familyName : Name} {levels : List Level} + {context : Context} {view rest : Expr} {argIdx : Nat} + {removed : List FVarId} {recursiveStarted : Bool} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorPreFamilyViewTrace stats 0 familyIndices + context view argIdx removed recursiveStarted} + (semantic : ConstructorPreFamilyViewSemanticRun env Us stats 0 + familyIndices contextRun trace) + (indConsts : stats.indConsts = #[.const familyName levels]) + (argIdxLe : argIdx ≤ stats.params.size) + (instantiation : instantiateFamilyParameters view + (stats.params.toList.drop argIdx) = .ok rest) : + Nonempty (ConstructorPreFamilyParameterSuffix + (env := env) (Us := Us) (stats := stats) + (familyIndices := familyIndices) (context := context) + (removed := removed) (recursiveStarted := recursiveStarted) + (contextRun := contextRun) rest) := by + induction semantic generalizing rest with + | @parameter context argIdx removed recursiveStarted name domain body + binderInfo parameter parameterAt tailTrace contextRun tail ih => + have atList : stats.params.toList[argIdx]? = some parameter := by + simpa only [← Array.getElem?_toList] using parameterAt + have dropped := drop_eq_cons_of_getElem?_eq_some atList + rw [dropped] at instantiation + simp only [instantiateFamilyParameters] at instantiation + have argIdxLt : argIdx < stats.params.size := by + by_contra notLt + have argIdxEq : argIdx = stats.params.size := by omega + subst argIdx + simp at parameterAt + exact ih (by omega) instantiation + | @ordinary context argIdx removed recursiveStarted name domain body + binderInfo noParameter nonrecursive independent domainCheck ensureType + consumedCheck annotations fresh tailTrace contextRun domainRun consumedRun + ensureTypeRun annotationsRun consumedType tail => + have noParameterList : stats.params.toList[argIdx]? = none := by + simpa only [← Array.getElem?_toList] using noParameter + have argIdxEq : argIdx = stats.params.toList.length := + eq_length_of_getElem?_eq_none noParameterList (by simpa using argIdxLe) + have sizeEq : stats.params.toList.length = stats.params.size := by simp + rw [sizeEq] at argIdxEq + subst argIdx + have dropEq : stats.params.toList.drop stats.params.size = [] := by + simp + rw [dropEq] at instantiation + have viewEq : (.forallE name domain body binderInfo) = rest := + Except.ok.inj (by + change Except.ok (.forallE name domain body binderInfo) = + Except.ok rest at instantiation + exact instantiation) + subst rest + let suffixTrace := ConstructorPreFamilyViewTrace.ordinary context + stats.params.size removed recursiveStarted name domain body binderInfo + noParameter nonrecursive independent domainCheck ensureType consumedCheck + annotations fresh tailTrace + exact ⟨⟨suffixTrace, + ConstructorPreFamilyViewSemanticRun.ordinary domainRun consumedRun + ensureTypeRun annotationsRun consumedType tail⟩⟩ + | @recursive context argIdx removed recursiveStarted name domain body + binderInfo noParameter isRecursive independent fieldTrace fresh tailTrace + contextRun field tail => + have noParameterList : stats.params.toList[argIdx]? = none := by + simpa only [← Array.getElem?_toList] using noParameter + have argIdxEq : argIdx = stats.params.toList.length := + eq_length_of_getElem?_eq_none noParameterList (by simpa using argIdxLe) + have sizeEq : stats.params.toList.length = stats.params.size := by simp + rw [sizeEq] at argIdxEq + subst argIdx + have dropEq : stats.params.toList.drop stats.params.size = [] := by + simp + rw [dropEq] at instantiation + have viewEq : (.forallE name domain body binderInfo) = rest := + Except.ok.inj (by + change Except.ok (.forallE name domain body binderInfo) = + Except.ok rest at instantiation + exact instantiation) + subst rest + let suffixTrace := ConstructorPreFamilyViewTrace.recursive context + stats.params.size removed recursiveStarted name domain body binderInfo + noParameter isRecursive independent fieldTrace fresh tailTrace + exact ⟨⟨suffixTrace, + ConstructorPreFamilyViewSemanticRun.recursive field tail⟩⟩ + | @terminal context source argIdx removed recursiveStarted valid independent + spineTrace contextRun expected spine => + by_cases argIdxEq : argIdx = stats.params.size + · subst argIdx + have dropEq : stats.params.toList.drop stats.params.size = [] := by + simp + rw [dropEq] at instantiation + have viewEq : source = rest := + Except.ok.inj (by + change Except.ok source = Except.ok rest at instantiation + exact instantiation) + subst rest + let suffixTrace := ConstructorPreFamilyViewTrace.terminal context source + stats.params.size removed recursiveStarted valid independent + spineTrace + exact ⟨⟨suffixTrace, + ConstructorPreFamilyViewSemanticRun.terminal expected spine⟩⟩ + · have argIdxLt : argIdx < stats.params.size := by omega + obtain ⟨parameter, parameterAt⟩ : + ∃ parameter, stats.params.toList[argIdx]? = some parameter := by + have listLt : argIdx < stats.params.toList.length := by + simpa using argIdxLt + exact ⟨stats.params.toList[argIdx], by + simp only [List.getElem?_eq_getElem listLt]⟩ + have dropped := drop_eq_cons_of_getElem?_eq_some parameterAt + rw [dropped] at instantiation + cases source <;> + simp only [instantiateFamilyParameters] at instantiation + case forallE binderName binderType body binderInfo => + unfold isValidIndAppIdx at valid + rw [indConsts] at valid + simp only [Expr.withApp_eq, Expr.getAppFn] at valid + cases headEq : + ((.forallE binderName binderType body binderInfo : Expr) == + .const familyName levels) with + | false => simp [headEq] at valid + | true => + change Expr.eqv + (.forallE binderName binderType body binderInfo) + (.const familyName levels) = true at headEq + rw [Expr.eqv_eq] at headEq + simp [Expr.eqv'] at headEq + all_goals exact nomatch instantiation + +end ConstructorPreFamilyViewSemanticRun + +/-- The exact D2 suffix after consuming every validator-owned parameter. +Both the executable alignment and its verified semantic interpretation are +retained at the first ordinary field or terminal result. -/ +structure ConstructorViewParameterSuffix + {env : VEnv} {Us : List Name} {whnfFuel : Nat} + {stats : InductiveStats} {isUnsafe : Bool} {familyIdx : Nat} + {ctor : Name} {context : Context} + {contextRun : ConstructorContextRun env Us context} + (rest : Expr) where + source : Expr + fuel : Nat + trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source stats.params.size fuel + alignment : ConstructorViewAlignmentTrace trace rest + semantic : ConstructorViewSemanticRun env Us whnfFuel contextRun trace rest + +namespace ConstructorViewSemanticRun + +/-- Strip the exact parameter prefix shared by D2's validation trace and +analyzer view alignment. Parameter lookups exclude an early ordinary field; +the alignment's retained non-Pi fact excludes an early terminal. -/ +theorem afterParameters + {env : VEnv} {Us : List Name} {whnfFuel : Nat} + {stats : InductiveStats} {isUnsafe : Bool} {familyIdx : Nat} + {ctor : Name} {context : Context} {source view rest : Expr} + {argIdx fuel : Nat} + {contextRun : ConstructorContextRun env Us context} + {trace : ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context source argIdx fuel} + (alignment : ConstructorViewAlignmentTrace trace view) + (semantic : ConstructorViewSemanticRun env Us whnfFuel contextRun trace + view) + (argIdxLe : argIdx ≤ stats.params.size) + (instantiation : instantiateFamilyParameters view + (stats.params.toList.drop argIdx) = .ok rest) : + ∃ suffix : ConstructorViewParameterSuffix + (env := env) (Us := Us) (whnfFuel := whnfFuel) + (stats := stats) (isUnsafe := isUnsafe) (familyIdx := familyIdx) + (ctor := ctor) (context := context) (contextRun := contextRun) rest, + suffix.trace.universeSemantics = trace.universeSemantics := by + induction trace generalizing view rest with + | parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeRun validationDefEq tailTrace ih => + cases alignment with + | parameter domainCheck viewDomainCheck parameterTypeCheck + parameterShape parameterPresent _ tailAlignment => + cases semantic with + | parameter domainRun viewDomainRun parameterTypeSemantic validationRun + tail => + have atList : stats.params.toList[argIdx]? = some param := by + simpa only [← Array.getElem?_toList] using parameterAt + have dropped := drop_eq_cons_of_getElem?_eq_some atList + rw [dropped] at instantiation + simp only [instantiateFamilyParameters] at instantiation + obtain ⟨suffix, suffixUniverse⟩ := ih tailAlignment tail (by + have argIdxLt : argIdx < stats.params.size := by + by_contra notLt + have argIdxEq : argIdx = stats.params.size := by omega + subst argIdx + simp at parameterAt + omega) instantiation + exact ⟨suffix, by + simpa only [ConstructorTypeValidationTrace.universeSemantics] + using suffixUniverse⟩ + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureTypeStep universeTrace positivityTrace tailTrace ih => + cases alignment with + | @ordinary _ _ viewDomain _ _ _ _ _ _ _ _ _ _ _ _ _ viewName + viewBody viewBinderInfo domainCheck viewDomainCheck viewEquality + consumedCheck _ positivityAlignment fresh annotations _ + tailAlignment => + cases semantic with + | ordinary domainRun viewDomainRun viewEqualityRun consumedRun + ensureTypeRun positivity annotationsRun consumedType tail => + have noParameterList : stats.params.toList[argIdx]? = none := by + simpa only [← Array.getElem?_toList] using noParameter + have argIdxEq : argIdx = stats.params.toList.length := + eq_length_of_getElem?_eq_none noParameterList + (by simpa using argIdxLe) + have sizeEq : stats.params.toList.length = stats.params.size := by + simp + rw [sizeEq] at argIdxEq + subst argIdx + have dropEq : stats.params.toList.drop stats.params.size = [] := by + simp + rw [dropEq] at instantiation + injection instantiation with restEq + subst rest + let suffixTrace := ConstructorTypeValidationTrace.ordinary context + fuel stats.params.size name domain body binderInfo sortResult + noParameter ensureTypeStep universeTrace positivityTrace tailTrace + have suffixAlignment : ConstructorViewAlignmentTrace suffixTrace + (.forallE viewName viewDomain viewBody viewBinderInfo) := + ConstructorViewAlignmentTrace.ordinary domainCheck + viewDomainCheck viewEquality consumedCheck positivityTrace + positivityAlignment fresh annotations tailTrace tailAlignment + have suffixSemantic : ConstructorViewSemanticRun env Us whnfFuel + contextRun suffixTrace + (.forallE viewName viewDomain viewBody viewBinderInfo) := + ConstructorViewSemanticRun.ordinary + (viewEquality := viewEquality) domainRun viewDomainRun + viewEqualityRun consumedRun ensureTypeRun positivity + annotationsRun consumedType tail + exact ⟨⟨_, fuel + 1, suffixTrace, suffixAlignment, + suffixSemantic⟩, rfl⟩ + | terminal context source fuel argIdx sourceTerminal sourceValid => + cases alignment with + | terminal sourceCheck viewCheck viewTerminal viewValid => + cases semantic with + | terminal sourceRun viewRun => + by_cases argIdxEq : argIdx = stats.params.size + · subst argIdx + have dropEq : stats.params.toList.drop stats.params.size = [] := by + simp + rw [dropEq] at instantiation + have viewEq : view = rest := Except.ok.inj instantiation + subst rest + let suffixTrace : ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context source stats.params.size (fuel + 1) := + ConstructorTypeValidationTrace.terminal context source fuel + stats.params.size sourceTerminal sourceValid + have suffixAlignment : ConstructorViewAlignmentTrace suffixTrace + view := + ConstructorViewAlignmentTrace.terminal sourceCheck viewCheck + viewTerminal viewValid + have suffixSemantic : ConstructorViewSemanticRun env Us whnfFuel + contextRun suffixTrace view := + ConstructorViewSemanticRun.terminal (isUnsafe := isUnsafe) + (ctor := ctor) sourceRun viewRun + exact ⟨⟨source, fuel + 1, suffixTrace, suffixAlignment, + suffixSemantic⟩, rfl⟩ + · have argIdxLt : argIdx < stats.params.size := by omega + obtain ⟨parameter, parameterAt⟩ : + ∃ parameter, stats.params.toList[argIdx]? = some parameter := by + have listLt : argIdx < stats.params.toList.length := by + simpa using argIdxLt + exact ⟨stats.params.toList[argIdx], by + simp only [List.getElem?_eq_getElem listLt]⟩ + have dropped := drop_eq_cons_of_getElem?_eq_some parameterAt + rw [dropped] at instantiation + cases view <;> + simp_all [instantiateFamilyParameters, Expr.isForall] + +end ConstructorViewSemanticRun + +private def candidateForallDepth : Expr → Nat + | .forallE _ _ body _ => candidateForallDepth body + 1 + | _ => 0 + +private theorem candidateForallDepth_le_instantiate1' + (expression argument : Expr) (depth : Nat) : + candidateForallDepth expression ≤ + candidateForallDepth (expression.instantiate1' argument depth) := by + induction expression generalizing depth <;> + simp [candidateForallDepth, Expr.instantiate1', *] + +private theorem candidateForallDepth_abstract1 + (expression : Expr) (id : FVarId) (depth : Nat) : + candidateForallDepth (Expr.abstract1 id expression depth) = + candidateForallDepth expression := by + induction expression generalizing depth <;> + simp [candidateForallDepth, Expr.abstract1, *] + split <;> rfl + +private theorem candidateForallDepth_abstractList + (expression : Expr) (ids : List FVarId) (depth : Nat) : + candidateForallDepth (Expr.abstractList expression ids depth) = + candidateForallDepth expression := by + induction ids generalizing expression with + | nil => rfl + | cons id ids ih => + simp only [Expr.abstractList, ih, candidateForallDepth_abstract1] + +private theorem candidateForallDepth_abstract + (expression : Expr) (ids : List FVarId) : + candidateForallDepth (expression.abstract ⟨ids.map Expr.fvar⟩) = + candidateForallDepth expression := by + rw [Expr.abstract_eq] + exact candidateForallDepth_abstractList expression ids 0 + +private theorem candidateView_forallDepth + (trace : CandidateExprTrace context source) : + trace.spineLength ≤ candidateForallDepth trace.view := by + induction trace with + | terminal => exact Nat.zero_le _ + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized domainCandidate + bodyCandidate domainIH bodyIH => + simp only [CandidateExprTrace.view, candidateForallDepth, + CandidateExprTrace.spineLength] + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl, + candidateForallDepth_abstract] + omega + +private theorem instantiateFamilyParameters_exists_of_forallDepth + (length : parameters.length ≤ candidateForallDepth source) : + ∃ rest, instantiateFamilyParameters source parameters = .ok rest := by + induction parameters generalizing source with + | nil => exact ⟨source, rfl⟩ + | cons parameter parameters ih => + cases source <;> simp [candidateForallDepth] at length + case forallE name domain body binderInfo => + have bodyLength : parameters.length ≤ candidateForallDepth + (body.instantiate1 parameter) := by + rw [Expr.instantiate1_eq] + exact Nat.le_trans + (by omega : parameters.length ≤ candidateForallDepth body) + (candidateForallDepth_le_instantiate1' body parameter 0) + obtain ⟨rest, restEq⟩ := ih bodyLength + exact ⟨rest, restEq⟩ + +/-- A reconstructed candidate view can instantiate any parameter list no +longer than its retained main Pi spine. This is only a syntactic success +fact; the exact Theory endpoint is supplied separately by strict translation. -/ +theorem CandidateExprTrace.instantiateViewParameters + (trace : CandidateExprTrace context source) + (parameters : List Expr) + (length : parameters.length ≤ trace.spineLength) : + ∃ rest, instantiateFamilyParameters trace.view parameters = .ok rest := by + apply instantiateFamilyParameters_exists_of_forallDepth + exact Nat.le_trans length (candidateView_forallDepth trace) + +namespace ConstructorPreFamilyViewSemanticRun + +/-- Weaken an exact ordinary-field type over any later field prefix. -/ +theorem ordinaryType_weakPrefix + (contextRun : ConstructorContextRun env Us context) + {fieldType : VExpr} + (fieldTypeWF : contextRun.candidate.context.IsType fieldType) + (Bs : List VExpr) : + env.IsType Us.length + (Bs ++ contextRun.candidate.context.vlctx.toCtx) + (fieldType.liftN Bs.length 0) := by + have henv : VEnv.WF env := by + simpa only [contextRun.venv_eq] using contextRun.candidate.context.Ewf + have fieldTypeWF' : env.IsType Us.length + contextRun.candidate.context.vlctx.toCtx fieldType := by + simpa only [VContext.IsType, contextRun.venv_eq, + contextRun.lparams_eq] using fieldTypeWF + exact fieldTypeWF'.weakN henv.ordered + (Ctx.LiftN.zero (n := Bs.length) + (Γ := contextRun.candidate.context.vlctx.toCtx) Bs) + +end ConstructorPreFamilyViewSemanticRun + +/-- Source-ordered D3 traces for the exact dependent constructor candidate +list selected by the producer. -/ +inductive ConstructorPreFamilyListTrace + (stats : InductiveStats) (familyIdx : Nat) (familyIndices : Expr) + (context : Context) : + {constructors : List Constructor} → + AddInductive.CandidateList AddInductive.CandidateConstructor constructors → + Type where + | nil : ConstructorPreFamilyListTrace stats familyIdx familyIndices context + .nil + | cons + (head : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + context candidate.type.view 0 [] false) + (tail : ConstructorPreFamilyListTrace stats familyIdx familyIndices + context candidates) : + ConstructorPreFamilyListTrace stats familyIdx familyIndices context + (.cons candidate candidates) + +namespace ConstructorPreFamilyListTrace + +def build (stats : InductiveStats) (familyIdx : Nat) + (familyIndices : Expr) (context : Context) : + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) → + Except Exception + (ConstructorPreFamilyListTrace stats familyIdx familyIndices context + candidates) + | .nil => pure .nil + | .cons head tail => do + let headTrace ← ConstructorPreFamilyViewTrace.build stats familyIdx + familyIndices context head.type.view 0 [] false + context.fuel.inductiveFuel + let tailTrace ← build stats familyIdx familyIndices context tail + pure <| .cons headTrace tailTrace + +end ConstructorPreFamilyListTrace + +theorem ConstructorPreFamilyListTrace.cons_build_eq + (head : ConstructorPreFamilyViewTrace stats familyIdx familyIndices context + candidate.type.view 0 [] false) + (headRun : ConstructorPreFamilyViewTrace.build stats familyIdx + familyIndices context candidate.type.view 0 [] false + context.fuel.inductiveFuel = .ok head) + (tail : ConstructorPreFamilyListTrace stats familyIdx familyIndices context + candidates) + (tailRun : ConstructorPreFamilyListTrace.build stats familyIdx + familyIndices context candidates = .ok tail) : + ConstructorPreFamilyListTrace.build stats familyIdx familyIndices context + (.cons candidate candidates) = .ok (.cons head tail) := by + simp only [ConstructorPreFamilyListTrace.build] + rw [headRun] + simp only [Bind.bind, Except.bind] + rw [tailRun] + rfl + +/-- Source-ordered verified pre-family meaning for every analyzer-owned +constructor candidate selected by the executable D3 gate. -/ +inductive ConstructorPreFamilyListSemanticRun + (env : VEnv) (Us : List Name) + (stats : InductiveStats) (familyIdx : Nat) (familyIndices : Expr) + (context : Context) (contextRun : ConstructorContextRun env Us context) : + {constructors : List Constructor} → + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors} → + ConstructorPreFamilyListTrace stats familyIdx familyIndices context + candidates → Type where + | nil : ConstructorPreFamilyListSemanticRun env Us stats familyIdx + familyIndices context contextRun (.nil) + | cons + {candidate : AddInductive.CandidateConstructor constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors} + {headTrace : ConstructorPreFamilyViewTrace stats familyIdx familyIndices + context candidate.type.view 0 [] false} + {tailTrace : ConstructorPreFamilyListTrace stats familyIdx familyIndices + context candidates} + (head : ConstructorPreFamilyViewSemanticRun env Us stats familyIdx + familyIndices contextRun headTrace) + (tail : ConstructorPreFamilyListSemanticRun env Us stats familyIdx + familyIndices context contextRun tailTrace) : + ConstructorPreFamilyListSemanticRun env Us stats familyIdx + familyIndices context contextRun (.cons headTrace tailTrace) + +namespace ConstructorPreFamilyListSemanticRun + +/-- Interpret every constructor position retained by a successful executable +D3 list trace in the same verified pre-family context. -/ +theorem nonempty + (contextRun : ConstructorContextRun env Us context) + (trace : ConstructorPreFamilyListTrace stats familyIdx familyIndices + context candidates) : + Nonempty (ConstructorPreFamilyListSemanticRun env Us stats familyIdx + familyIndices context contextRun trace) := by + induction trace with + | nil => exact ⟨.nil⟩ + | cons headTrace tailTrace ih => + obtain ⟨head⟩ := ConstructorPreFamilyViewSemanticRun.nonempty contextRun + headTrace + obtain ⟨tail⟩ := ih + exact ⟨.cons head tail⟩ + +end ConstructorPreFamilyListSemanticRun + +/-- Exact output of the executable D3 gate. -/ +structure ConstructorPreFamilySafetyTrace + (stats : InductiveStats) (familyView : Expr) + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) + (context : Context) where + translationUnique : + (theoryTranslationUnique familyView && + candidates.viewTranslationUnique) = true + familyIndices : Expr + parameters : instantiateFamilyParameters familyView stats.params.toList = + .ok familyIndices + constructors : ConstructorPreFamilyListTrace stats 0 familyIndices context + candidates + +theorem ConstructorPreFamilySafetyTrace.familyTranslationUnique + (trace : ConstructorPreFamilySafetyTrace stats familyView candidates + context) : + TrExprS.IsUnique familyView := + by + have unique := trace.translationUnique + simp only [Bool.and_eq_true] at unique + exact theoryTranslationUnique_sound unique.1 + +theorem ConstructorPreFamilySafetyTrace.constructorTranslationUnique + (trace : ConstructorPreFamilySafetyTrace stats familyView candidates + context) : + candidates.ViewTranslationUnique := + by + have unique := trace.translationUnique + simp only [Bool.and_eq_true] at unique + exact candidates.viewTranslationUnique_sound unique.2 + +/-- Build the complete D3 trace or return the first structural/checker +failure. -/ +def buildConstructorPreFamilySafety + (stats : InductiveStats) (familyView : Expr) + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) + (context : Context) : + Except Exception + (ConstructorPreFamilySafetyTrace stats familyView candidates context) := + match translationUnique : + theoryTranslationUnique familyView && + candidates.viewTranslationUnique with + | false => throw <| .other + "candidate view contains a projection with no exact Theory endpoint" + | true => + match parameters : + instantiateFamilyParameters familyView stats.params.toList with + | .error error => .error error + | .ok familyIndices => do + let constructors ← ConstructorPreFamilyListTrace.build stats 0 + familyIndices context candidates + pure ⟨translationUnique, familyIndices, parameters, constructors⟩ + +/-! ### Executable pre-family rejection fixtures -/ + +private def preFamilyNegativeStats : InductiveStats where + levels := [] + resultLevel := .zero + nindices := #[0] + indConsts := #[.const `PreFamilyNegative []] + params := #[] + isNotZero := true + +private def preFamilyNegativeContext : Context where + env := Kernel.Environment.ofConstants `_preFamilyNegative + ({} : ConstMap) + lparams := [] + safety := .safe + allowPrimitive := false + +/- The traversal begins from the public gate's initial state. Its first +recursive field is omitted from the pre-family context, while the following +ordinary field is independent of that local and is therefore admissible. -/ +private def preFamilyOrdinaryAfterRecursiveView : Expr := + .forallE `recursive (.const `PreFamilyNegative []) + (.forallE `ordinary (.sort .zero) + (.const `PreFamilyNegative []) .default) + .default + +private def preFamilyOrdinaryAfterRecursiveAccepted : Bool := + match ConstructorPreFamilyViewTrace.build preFamilyNegativeStats 0 + (.sort (.succ .zero)) preFamilyNegativeContext + preFamilyOrdinaryAfterRecursiveView 0 [] false + preFamilyNegativeContext.fuel.inductiveFuel with + | .ok _ => true + | .error _ => false + +#guard preFamilyOrdinaryAfterRecursiveAccepted + +/- The first recursive local is deliberately omitted. Instantiating the next +recursive field exposes that FVar in its domain, so the dependency gate must +reject it before attempting the recursive-field replay. -/ +private def preFamilyRecursiveLocalDependencyView : Expr := + .forallE `recursive (.const `PreFamilyNegative []) + (.forallE `dependent + (.app (.const `PreFamilyNegative []) (.bvar 0)) + (.const `PreFamilyNegative []) .default) + .default + +private def preFamilyRecursiveLocalDependencyRejected : Bool := + match ConstructorPreFamilyViewTrace.build preFamilyNegativeStats 0 + (.sort (.succ .zero)) preFamilyNegativeContext + preFamilyRecursiveLocalDependencyView 0 [] false + preFamilyNegativeContext.fuel.inductiveFuel with + | .error (.other message) => + message == "constructor depends on an omitted recursive local" + | _ => false + +#guard preFamilyRecursiveLocalDependencyRejected + +/-- One executable D3 gate for the complete singleton constructor list. It +both enforces the recursive-suffix/dependency subset and re-runs every +family-free checker operation in the supplied pre-family context. -/ +def checkConstructorPreFamilySafety + (stats : InductiveStats) (familyView : Expr) + (candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors) : M Unit := fun context => + if theoryTranslationUnique familyView && + candidates.viewTranslationUnique then do + let familyIndices ← instantiateFamilyParameters familyView + stats.params.toList + let _ ← ConstructorPreFamilyListTrace.build stats 0 familyIndices context + candidates + pure () + else + throw <| .other + "candidate view contains a projection with no exact Theory endpoint" + +/-- A successful executable D3 gate returns its exact parameter-instantiated +family telescope and source-ordered replay trace. -/ +theorem ConstructorPreFamilyListTrace.nonempty_of_check + (success : checkConstructorPreFamilySafety stats familyView candidates + context = .ok ()) : + Nonempty (ConstructorPreFamilySafetyTrace stats familyView candidates + context) := by + unfold checkConstructorPreFamilySafety at success + cases translationUnique : + theoryTranslationUnique familyView && + candidates.viewTranslationUnique with + | false => simp [translationUnique] at success + | true => + cases parameters : instantiateFamilyParameters familyView + stats.params.toList with + | error error => + simp [translationUnique, parameters, Bind.bind, Except.bind] at success + | ok familyIndices => + cases constructorsRun : ConstructorPreFamilyListTrace.build stats 0 + familyIndices context candidates with + | error error => + simp [translationUnique, parameters, constructorsRun, + Bind.bind, Except.bind] at success + | ok constructors => + exact ⟨⟨translationUnique, familyIndices, parameters, + constructors⟩⟩ + +/-- A successful executable D3 gate guarantees the retained builder returns +its trace, so gate owners can replay `buildConstructorPreFamilySafety` +instead of choosing from `Nonempty`. -/ +theorem buildConstructorPreFamilySafety_ok_of_check + (success : checkConstructorPreFamilySafety stats familyView candidates + context = .ok ()) : + ∃ trace, buildConstructorPreFamilySafety stats familyView candidates + context = .ok trace := by + unfold checkConstructorPreFamilySafety at success + unfold buildConstructorPreFamilySafety + split + next translationUnique => + simp [translationUnique] at success + next translationUnique => + split + next error parameters => + simp [translationUnique, parameters, Bind.bind, Except.bind] at success + next familyIndices parameters => + cases hbuild : ConstructorPreFamilyListTrace.build stats 0 familyIndices + context candidates with + | error error => + simp [translationUnique, parameters, hbuild, + Bind.bind, Except.bind] at success + | ok constructors => + exact ⟨_, rfl⟩ + +end AddInductive + +namespace TypeChecker +open AddInductive + +private theorem abstract1_instantiate_self + (expression : Expr) (id : FVarId) (depth : Nat) : + Closed expression depth → + (expression.abstract1 id depth).instantiate1' (.fvar id) depth = + expression := by + induction expression generalizing depth <;> + simp_all [Closed, Expr.abstract1, Expr.instantiate1', beq_iff_eq] + split <;> + simp_all [Expr.instantiate1', Expr.liftLooseBVars'] + +private theorem abstract_instantiate_self + (expression : Expr) (id : FVarId) (closed : Closed expression) : + (expression.abstract #[.fvar id]).instantiate1 (.fvar id) = + expression := by + rw [show #[Expr.fvar id] = ⟨[id].map Expr.fvar⟩ by rfl] + simp only [Expr.abstract_eq, Expr.abstractList, Expr.instantiate1_eq] + exact abstract1_instantiate_self expression id 0 closed + +/-- A source-ordered list of kernel parameter FVars builds an exact verified +local telescope. The final context is obtained by pushing each parameter in +order; dependency metadata is retained but never guessed by consumers. -/ +inductive CandidateParameterContext : + VLCtx → List Expr → List VExpr → VLCtx → Prop where + | nil : CandidateParameterContext base [] [] base + | cons + (tail : CandidateParameterContext + ((some (fv, deps), .vlam A) :: base) parameters types final) : + CandidateParameterContext base (.fvar fv :: parameters) + (A :: types) final + +/-- A completed analyzer-owned parameter telescope also certifies every +earlier context in that telescope. -/ +theorem CandidateParameterContext.initialWF + (params : CandidateParameterContext base parameters types final) + (finalWF : VLCtx.WF env U final) : + VLCtx.WF env U base := by + induction params with + | nil => exact finalWF + | cons tail ih => exact (ih finalWF).1 + +/-- The source parameter list and analyzer telescope carried by an exact +parameter context have the same number of entries. -/ +theorem CandidateParameterContext.length_eq + (params : CandidateParameterContext base parameters types final) : + parameters.length = types.length := by + induction params with + | nil => rfl + | cons tail ih => simp only [List.length_cons, ih] + +/-- Replay a successful kernel parameter instantiation against the exact +analyzer-owned Theory parameter telescope. Each source Pi body is opened by +the corresponding retained FVar; no whole-Pi injectivity or caller-selected +endpoint is used. -/ +theorem CandidateParameterContext.instantiateForall + (params : CandidateParameterContext base parameters types final) + (henv : VEnv.Ordered env) + (finalWF : VLCtx.WF env Us.length final) + (instantiation : instantiateFamilyParameters source parameters = .ok rest) + (tr : TrExprS env Us base source (VExpr.forallN types result)) : + TrExprS env Us final rest result := by + induction params generalizing source rest with + | nil => + have source_eq : source = rest := Except.ok.inj instantiation + subst rest + simpa only [VExpr.forallN] using tr + | @cons fv deps A base parameters types final tail ih => + cases source <;> simp only [instantiateFamilyParameters] at instantiation + case forallE name domain body binderInfo => + obtain ⟨domain', body', targetEq, domainType, bodyType, domainTr, + bodyTr⟩ := TrExprS.forallE_components tr + simp only [VExpr.forallN, VExpr.forallE.injEq] at targetEq + obtain ⟨rfl, rfl⟩ := targetEq + have nextWF : VLCtx.WF env Us.length + ((some (fv, deps), .vlam A) :: base) := + tail.initialWF finalWF + exact ih finalWF instantiation (by + simpa only [Expr.instantiate1_eq] using + bodyTr.inst_fvar henv nextWF) + all_goals exact nomatch instantiation + +/-- Consume an exact prefix of a strictly translated candidate view and keep +the terminal candidate context tied to the corresponding view telescope. + +The resulting `parameterContext` is the analyzer-owned prefix context. The +final `FVLift'` is over precisely the unconsumed suffix, so a strict +translation in the parameter context can be weakened to the same terminal +context used by pre-family constructor replay. -/ +theorem CandidateExprRun.parameterViewTerminal + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') + (contextRun : CandidateContextRun candidateContext) + (venv_eq : contextRun.context.venv = env) + (lparams_eq : contextRun.context.lparams = Us) + (vlctx_eq : contextRun.context.vlctx = Δ) + (unique : CandidateExprTraceViewIsUnique trace) + (count : Nat) (hcount : count ≤ trace.spineLength) + {viewΔ : VLCtx} + (viewDefEq : VLCtx.IsDefEq env Us.length Δ viewΔ) + (viewContext : TrExprS.IsUniqueCtx Δ viewΔ) + (noBV : Δ.NoBV) : + ∃ (parameterΔ : VLCtx) (rest : Expr) + (terminalRun : CandidateContextRun trace.terminalContext) + (viewTerminal : VLCtx), + instantiateFamilyParameters trace.view (trace.parameterList count) = + .ok rest ∧ + TrExprS env Us parameterΔ rest (VExpr.dropN count view') ∧ + parameterΔ.toCtx = + (VExpr.telN count view').reverse ++ viewΔ.toCtx ∧ + CandidateParameterContext viewΔ (trace.parameterList count) + (VExpr.telN count view') parameterΔ ∧ + parameterΔ.fvars.map Expr.fvar = + (trace.parameterList count).reverse ++ + viewΔ.fvars.map Expr.fvar ∧ + parameterΔ.NoBV ∧ + VLCtx.WF env Us.length parameterΔ ∧ + terminalRun.context.venv = env ∧ + terminalRun.context.lparams = Us ∧ + VLCtx.IsDefEq env Us.length terminalRun.context.vlctx viewTerminal ∧ + TrExprS.IsUniqueCtx terminalRun.context.vlctx viewTerminal ∧ + VLCtx.FVLift' parameterΔ viewTerminal 0 + (.skipN .refl (trace.spineLength - count)) 0 ∧ + viewTerminal.toCtx = + (VExpr.telN (trace.spineLength - count) + (VExpr.dropN count view')).reverse ++ parameterΔ.toCtx := by + induction run generalizing count viewΔ with + | @terminal Δ context source inferred result source' result' inferred' + checked normalized node => + simp only [AddInductive.CandidateExprTrace.spineLength] at hcount + have count_eq : count = 0 := Nat.eq_zero_of_le_zero hcount + subst count + have strict := + CandidateExprRun.view_tr_strict + (CandidateExprRun.terminal node) unique + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + obtain ⟨moved, movedTr⟩ := strict.defeqDFC henv viewDefEq + have moved_eq : result' = moved := + strict.unique' viewContext unique movedTr + subst moved + obtain ⟨terminalRun, viewTerminal, terminalVenv, terminalLparams, + terminalViewDefEq, terminalViewContext, terminalViewLift, + terminalViewEq⟩ := + (CandidateExprRun.terminal node).terminalContextRunView contextRun + venv_eq lparams_eq vlctx_eq viewDefEq viewContext + exact ⟨viewΔ, result, terminalRun, viewTerminal, rfl, movedTr, rfl, .nil, + by simp [AddInductive.CandidateExprTrace.parameterList], + by simpa only [VLCtx.NoBV, ← viewDefEq.bvars] using noBV, + (viewDefEq.symm henv.ordered).wf, + terminalVenv, terminalLparams, terminalViewDefEq, terminalViewContext, + by simpa only [Nat.sub_zero] using terminalViewLift, + by simpa only [Nat.sub_zero, VExpr.dropN] using terminalViewEq⟩ + | @forallE domain context name binderInfo Δ source inferred body + source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyΔ storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate + bodyCandidate node domainRun annotationsRun bodyRun domainType bodyType + bodySource bodyContext domainIH bodyIH => + have currentRun := CandidateExprRun.forallE + (fresh := fresh) (checked := checked) (normalized := normalized) + annotations annotationsEq domainCandidate bodyCandidate node domainRun + annotationsRun bodyRun domainType bodyType bodySource bodyContext + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + have hΔ : VLCtx.WF env Us.length Δ := by + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + have allUnique := unique + rcases unique with ⟨domainUnique, bodyUnique, abstractUnique⟩ + cases count with + | zero => + have strict := currentRun.view_tr_strict allUnique + obtain ⟨moved, movedTr⟩ := strict.defeqDFC henv viewDefEq + have moved_eq : VExpr.forallE domainView' bodyView' = moved := + strict.unique' viewContext allUnique.view movedTr + subst moved + obtain ⟨terminalRun, viewTerminal, terminalVenv, terminalLparams, + terminalViewDefEq, terminalViewContext, terminalViewLift, + terminalViewEq⟩ := + currentRun.terminalContextRunView contextRun venv_eq lparams_eq + vlctx_eq viewDefEq viewContext + exact ⟨viewΔ, _, terminalRun, viewTerminal, rfl, movedTr, rfl, .nil, + by simp [AddInductive.CandidateExprTrace.parameterList], + by simpa only [VLCtx.NoBV, ← viewDefEq.bvars] using noBV, + (viewDefEq.symm henv.ordered).wf, + terminalVenv, terminalLparams, terminalViewDefEq, + terminalViewContext, + by simpa only [Nat.sub_zero] using terminalViewLift, + by simpa only [Nat.sub_zero, VExpr.dropN] using terminalViewEq⟩ + | succ count => + simp only [AddInductive.CandidateExprTrace.spineLength, + Nat.succ_le_succ_iff] at hcount + have domainDef : env.IsDefEq Us.length Δ.toCtx + domain' domainView' (.sort u) := + domainRun.evidence.isDefEq.toU.of_l henv hΔ.toCtx domainType + have annotationDef : env.IsDefEq Us.length Δ.toCtx + domain' storedDomain' (.sort u) := + annotationsRun.isDefEqU.of_l henv hΔ.toCtx domainType + have storedToView : env.IsDefEq Us.length Δ.toCtx + storedDomain' domainView' (.sort u) := + annotationDef.symm.trans domainDef + have storedDomain_tr : contextRun.context.TrExprS + annotations.consumed storedDomain' := by + simpa only [VContext.TrExprS, venv_eq, lparams_eq, vlctx_eq] using + annotationsRun.rhs_tr + have storedDomain_type : env.IsType Us.length Δ.toCtx storedDomain' := + ⟨u, annotationDef.hasType.2⟩ + let nextContextRun := contextRun.pushLocalDecl name binderInfo + annotations.consumed fresh storedDomain' storedDomain_tr (by + change contextRun.context.venv.IsType + contextRun.context.lparams.length + contextRun.context.vlctx.toCtx storedDomain' + rw [venv_eq, lparams_eq, vlctx_eq] + exact storedDomain_type) + have nextVenv : nextContextRun.context.venv = env := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_venv, + venv_eq] + have nextLparams : nextContextRun.context.lparams = Us := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_lparams, + lparams_eq] + have nextVlctx : nextContextRun.context.vlctx = bodyΔ := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_vlctx] + rw [vlctx_eq, bodyContext] + let viewBodyΔ : VLCtx := + (some (context.freshFVarId, annotations.consumed.fvarsList), + .vlam domainView') :: viewΔ + have bodyWF := bodyRun.context_wf + rw [bodyContext] at bodyWF + have bodyViewDefEq : VLCtx.IsDefEq env Us.length bodyΔ viewBodyΔ := by + rw [bodyContext] + exact .cons viewDefEq bodyWF.2.1 (.vlam storedToView) + have bodyViewContext : TrExprS.IsUniqueCtx bodyΔ viewBodyΔ := by + rw [bodyContext] + exact viewContext.cons .vlam + have bodyNoBV : bodyΔ.NoBV := by + rw [bodyContext] + simpa only [VLCtx.NoBV, VLCtx.bvars] using noBV + obtain ⟨parameterΔ, rest, terminalRun, viewTerminal, restEq, + restTr, parameterCtx, parameterContext, parameterFVars, + parameterNoBV, parameterWF, terminalVenv, + terminalLparams, terminalViewDefEq, terminalViewContext, + terminalViewLift, terminalViewEq⟩ := + bodyIH nextContextRun nextVenv nextLparams nextVlctx bodyUnique + count hcount bodyViewDefEq bodyViewContext bodyNoBV + have bodyClosed : Closed bodyCandidate.view := by + have closed := (bodyRun.view_tr_strict bodyUnique).closed + simpa only [bodyNoBV] using closed + refine ⟨parameterΔ, rest, terminalRun, viewTerminal, ?_, ?_, ?_, + ?_, ?_, parameterNoBV, parameterWF, terminalVenv, terminalLparams, + ?_, ?_, ?_, ?_⟩ + · simp only [AddInductive.CandidateExprTrace.view, + AddInductive.CandidateExprTrace.parameterList, + instantiateFamilyParameters] + change instantiateFamilyParameters + ((bodyCandidate.view.abstract + #[.fvar context.freshFVarId]).instantiate1 + (.fvar context.freshFVarId)) _ = _ + rw [abstract_instantiate_self _ _ bodyClosed] + exact restEq + · simpa only [VExpr.dropN] using restTr + · simpa only [AddInductive.CandidateExprTrace.spineLength, + VExpr.telN, List.reverse_cons, List.singleton_append, + List.append_assoc, viewBodyΔ, VLCtx.toCtx] using parameterCtx + · simpa only [AddInductive.CandidateExprTrace.parameterList, + VExpr.telN, viewBodyΔ, AddInductive.Context.freshExpr] using + CandidateParameterContext.cons parameterContext + · simpa [AddInductive.CandidateExprTrace.parameterList, + List.reverse_cons, List.singleton_append, List.append_assoc, + viewBodyΔ, VLCtx.fvars, AddInductive.Context.freshExpr] using + parameterFVars + · simpa only [AddInductive.CandidateExprTrace.terminalContext] using + terminalViewDefEq + · simpa only [AddInductive.CandidateExprTrace.terminalContext] using + terminalViewContext + · simpa only [AddInductive.CandidateExprTrace.spineLength, + Nat.succ_sub_succ_eq_sub] using terminalViewLift + · simpa only [AddInductive.CandidateExprTrace.spineLength, + Nat.succ_sub_succ_eq_sub, VExpr.dropN] using terminalViewEq + +end TypeChecker + +namespace VInductDecl + +/-! +## Staged ownership + +The ordinary outer producer deliberately remains unchanged: its successful +equation records kernel validation, while this additive wrapper retains the +verified universe-semantic audit introduced by Spec-01D1 and extended by +Spec-02C. The normalized branch intersects the ordinary core decision with +the proved project comparison, without making bare +`buildNormalizationCandidate` success carry Theory meaning. +-/ + +/-- A staged singleton semantic input together with the exact executable +constructor-universe audit for the same source list, family-validation stats, +and post-family checker context. + +Keeping the ordinary staged input as data preserves the established candidate +and semantic hierarchy. The dependent `universeRun` field prevents an audit +for another family, constructor ordering, parameter split, or environment from +being reused here. -/ +structure StagedNormalizationCandidateUniverseInput + (familyContext constructorContext : AddInductive.Context) + (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + staged : StagedNormalizationCandidateSemanticInput familyContext + constructorContext env Us candidate rawDecl + universeRun : + AddInductive.checkConstructorUniverseListSemantics + staged.family.validation.stats source.ctors + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } = .ok () + +/-- Pair the retained ordinary validation trace with its source-indexed +universe audit. This is the strengthened D1 validation object; forgetting it +recovers exactly the pre-existing staged owner. -/ +def StagedNormalizationCandidateUniverseInput.semanticValidation + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidateUniverseInput familyContext + constructorContext env Us candidate rawDecl) : + AddInductive.ConstructorSemanticValidationRun source + input.staged.family.validation.stats false + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } where + validation := input.staged.constructorValidation + universeRun := input.universeRun + +/-- Every universe-bearing node in the staged source-ordered validation trace +passes the verified semantic universe gate. -/ +theorem StagedNormalizationCandidateUniverseInput.universeSemantics + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidateUniverseInput familyContext + constructorContext env Us candidate rawDecl) : + input.staged.constructorValidation.universeSemantics = true := + input.semanticValidation.universeSemantics + +/-- Preserve the existing automatic semantic-hierarchy construction while +retaining the strengthened universe gate in its staged owner. -/ +theorem StagedNormalizationCandidateUniverseInput.exists + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidateUniverseInput familyContext + constructorContext env Us candidate rawDecl) : + Nonempty (ProducedNormalizationCandidateSemanticRun familyContext + constructorContext env Us candidate rawDecl) := + input.staged.exists + +/-! +## Post-family constructor ownership + +This additive D2 owner keeps D1's universe gate and adds the exact executable +alignment between the retained validation telescope and every analyzer-owned +constructor candidate. It does not replay `checkConstructors` on the view or +claim any pre-family field judgment. +-/ + +/-- The staged semantic/universe owner together with the source-ordered +post-family constructor alignment audit. -/ +structure StagedNormalizationCandidatePostFamilyInput + (familyContext constructorContext : AddInductive.Context) + (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + universeInput : StagedNormalizationCandidateUniverseInput familyContext + constructorContext env Us candidate rawDecl + alignment : AddInductive.ConstructorCandidateAlignmentTrace + universeInput.staged.family.validation.stats false 0 + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } + universeInput.staged.constructorValidation.trace + candidate.families.singleton.constructors + +/-- Package a successful executable alignment audit into the staged D2 owner. +The direct `alignment` field also permits proof-oriented clients to assemble +the same indexed trace from already-retained checker observations. The +retained trace is computed by replaying the alignment builder; the audit +premise only discharges its impossible error branch. -/ +def StagedNormalizationCandidatePostFamilyInput.ofRun + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (universeInput : StagedNormalizationCandidateUniverseInput familyContext + constructorContext env Us candidate rawDecl) + (alignmentRun : + universeInput.staged.constructorValidation.trace.checkCandidateAlignment + candidate.families.singleton.constructors + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } = .ok ()) : + StagedNormalizationCandidatePostFamilyInput familyContext + constructorContext env Us candidate rawDecl where + universeInput := universeInput + alignment := + match h : AddInductive.ConstructorCandidateAlignmentTrace.build + universeInput.staged.constructorValidation.trace + candidate.families.singleton.constructors with + | .ok alignment => alignment + | .error _ => + absurd + (AddInductive.ConstructorCandidateAlignmentTrace.build_ok_of_check + alignmentRun) + (by simp [h]) + +/-- The exact output of D2: the established produced semantic hierarchy plus +the actual post-family validation context, retained source/candidate +alignment, and a positional semantic interpretation of every exact candidate +view binder and terminal result. -/ +structure ProducedNormalizationCandidatePostFamilySemanticRun + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePostFamilyInput familyContext + constructorContext env Us candidate rawDecl) where + produced : ProducedNormalizationCandidateSemanticRun familyContext + constructorContext env Us candidate rawDecl + contextRun : AddInductive.ConstructorContextRun + produced.semantic.family.typeEnv Us + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } + alignment : AddInductive.ConstructorCandidateAlignmentTrace + input.universeInput.staged.family.validation.stats false 0 + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } + input.universeInput.staged.constructorValidation.trace + candidate.families.singleton.constructors + constructors : AddInductive.ConstructorPostFamilySemanticListRun + produced.semantic.family.typeEnv Us + input.universeInput.staged.family.validation.stats false 0 + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } + contextRun input.universeInput.staged.constructorValidation.trace + candidate.families.singleton.constructors alignment + produced.semantic.family.constructors + +/-- Interpret D2's executable alignment in the exact post-family Theory +environment obtained by the retained raw-family insertion. The only +existential selections are checker-produced Theory translations already +encapsulated by `Nonempty`; no caller supplies a view. -/ +theorem StagedNormalizationCandidatePostFamilyInput.exists + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePostFamilyInput familyContext + constructorContext env Us candidate rawDecl) : + Nonempty (ProducedNormalizationCandidatePostFamilySemanticRun input) := by + obtain ⟨familySemantic⟩ := + input.universeInput.staged.semanticInput.family.exists + let semantic : NormalizationCandidateSemanticRun env Us candidate rawDecl := + { raw := input.universeInput.staged.raw + raw_types_eq := input.universeInput.staged.raw_types_eq + uvars_eq := input.universeInput.staged.declaration_uvars_eq + family := familySemantic } + let produced : ProducedNormalizationCandidateSemanticRun familyContext + constructorContext env Us candidate rawDecl := + { semantic := semantic + familyTypesProduced := + input.universeInput.staged.familyTypesProduced + familiesProduced := input.universeInput.staged.familiesProduced } + have typeEnv_eq : familySemantic.typeEnv = + input.universeInput.staged.family.typeEnv := by + exact Option.some.inj <| + familySemantic.addType.symm.trans + input.universeInput.staged.family.addInduct.env_add + obtain ⟨candidateContext, venv_eq, lparams_eq⟩ := + input.universeInput.staged.family.validationContextRun + familySemantic.type + let contextRun : AddInductive.ConstructorContextRun + produced.semantic.family.typeEnv Us + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } := + ⟨candidateContext, venv_eq.trans typeEnv_eq.symm, lparams_eq⟩ + let alignment := input.alignment + obtain ⟨constructors⟩ := + AddInductive.ConstructorPostFamilySemanticListRun.nonempty_of_alignment + contextRun alignment produced.semantic.family.constructors + exact ⟨⟨produced, contextRun, alignment, constructors⟩⟩ + +/-! +## Pre-family constructor ownership + +The D3 owner extends the staged D2 package with the output of one executable +pre-family safety gate. Its semantic result is reconstructed from that exact +trace in the verified context reached by family normalization before the raw +family constant is inserted. +-/ + +/-- The staged D2 owner together with the exact executable pre-family safety +trace for the same singleton family view and dependent constructor list. -/ +structure StagedNormalizationCandidatePreFamilyInput + (familyContext constructorContext : AddInductive.Context) + (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + postFamilyInput : StagedNormalizationCandidatePostFamilyInput familyContext + constructorContext env Us candidate rawDecl + safety : AddInductive.ConstructorPreFamilySafetyTrace + postFamilyInput.universeInput.staged.family.validation.stats + candidate.families.singleton.familyType.type.view + candidate.families.singleton.constructors + candidate.families.singleton.familyType.type.trace.terminalContext + +/-- Package a successful executable D3 gate into the staged owner. The gate +itself, rather than a caller-supplied Theory premise, selects the retained +parameter-instantiated family telescope and constructor traces. The trace +is computed by replaying the safety builder; the gate premise only +discharges its impossible error branch. -/ +def StagedNormalizationCandidatePreFamilyInput.ofRun + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (postFamilyInput : StagedNormalizationCandidatePostFamilyInput + familyContext constructorContext env Us candidate rawDecl) + (safetyRun : AddInductive.checkConstructorPreFamilySafety + postFamilyInput.universeInput.staged.family.validation.stats + candidate.families.singleton.familyType.type.view + candidate.families.singleton.constructors + candidate.families.singleton.familyType.type.trace.terminalContext = + .ok ()) : + StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl where + postFamilyInput := postFamilyInput + safety := + match h : AddInductive.buildConstructorPreFamilySafety + postFamilyInput.universeInput.staged.family.validation.stats + candidate.families.singleton.familyType.type.view + candidate.families.singleton.constructors + candidate.families.singleton.familyType.type.trace.terminalContext with + | .ok safety => safety + | .error _ => + absurd + (AddInductive.buildConstructorPreFamilySafety_ok_of_check safetyRun) + (by simp [h]) + +/-- D3's produced meaning: D2's post-family semantics together with the exact +verified pre-family context and source-ordered family-free replay selected by +the executable safety trace. -/ +structure ProducedNormalizationCandidatePreFamilySemanticRun + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl) where + postFamily : ProducedNormalizationCandidatePostFamilySemanticRun + input.postFamilyInput + contextRun : AddInductive.ConstructorContextRun env Us + candidate.families.singleton.familyType.type.trace.terminalContext + constructors : AddInductive.ConstructorPreFamilyListSemanticRun env Us + input.postFamilyInput.universeInput.staged.family.validation.stats 0 + input.safety.familyIndices + candidate.families.singleton.familyType.type.trace.terminalContext + contextRun input.safety.constructors + +/-- Interpret the executable D3 safety trace in the exact verified pre-family +context recovered from the retained family semantic normalization run. -/ +theorem StagedNormalizationCandidatePreFamilyInput.exists + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl) : + Nonempty (ProducedNormalizationCandidatePreFamilySemanticRun input) := by + obtain ⟨postFamily⟩ := input.postFamilyInput.exists + have raw_eq : postFamily.produced.semantic.raw = + input.postFamilyInput.universeInput.staged.raw := by + have singleton_eq := + postFamily.produced.semantic.raw_types_eq.symm.trans + input.postFamilyInput.universeInput.staged.raw_types_eq + injection singleton_eq + have familyType : TypeChecker.CandidateExprSemanticRootRun env Us + candidate.families.singleton.familyType.type + input.postFamilyInput.universeInput.staged.raw.type := by + rw [← raw_eq] + exact postFamily.produced.semantic.family.type + obtain ⟨candidateContext, venv_eq, lparams_eq⟩ := + input.postFamilyInput.universeInput.staged.family.preValidationContextRun + familyType + let contextRun : AddInductive.ConstructorContextRun env Us + candidate.families.singleton.familyType.type.trace.terminalContext := + ⟨candidateContext, venv_eq, lparams_eq⟩ + obtain ⟨constructors⟩ := + AddInductive.ConstructorPreFamilyListSemanticRun.nonempty contextRun + input.safety.constructors + exact ⟨⟨postFamily, contextRun, constructors⟩⟩ + +/-- Invert a verified iterated Pi type into its exact source-ordered +telescope and terminal type. -/ +private theorem isType_forallN_inv + (henv : VEnv.Ordered env) : + ∀ {As : List VExpr} {U : Nat} {Γ : List VExpr} {B : VExpr}, + env.IsType U Γ (VExpr.forallN As B) → + env.OnTel U Γ As ∧ + env.IsType U (As.reverse ++ Γ) B + | [], U, Γ, B, h => by + change env.IsType _ _ B at h + exact ⟨trivial, h⟩ + | A :: As, U, Γ, B, h => by + obtain ⟨hA, hrest⟩ := h.forallE_inv henv + obtain ⟨hAs, hB⟩ := isType_forallN_inv henv hrest + exact ⟨⟨hA, hAs⟩, by + simpa [List.reverse_cons, List.append_assoc] using hB⟩ + +/-- The family normalization trace and the analyzer's exact generation +equation derive the checked parameter/index telescope. No checked- or +view-well-formedness premise is accepted. -/ +theorem StagedNormalizationCandidatePreFamilyInput.familyOnTel + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl) + (normalization : NormalizationCandidateSemanticRun env Us candidate rawDecl) + (generation : GenerationChecked rawDecl) + (analysis : normalization.root.normalization.generation? = + some generation) : + env.OnTel rawDecl.uvars [] + (generation.block.checked.params ++ generation.block.checked.indices) := by + obtain ⟨_, recursive⟩ := normalization.family.type.recursive + have familyType : env.IsType Us.length [] normalization.family.type.view := + recursive.view_isType_of_terminalSort + input.postFamilyInput.universeInput.staged.family.validation.terminal_eq + have view_eq : normalization.family.type.view = + generation.block.checked.type.type := by + exact (congrArg (fun ty : VInductiveType => ty.type) + (normalization.root.familyViewType_eq analysis)).symm + rw [view_eq, generation.block.checked.type_eq, + ← VExpr.forallN_append] at familyType + have henv : VEnv.Ordered env := by + simpa only [normalization.family.type.venv_eq] using + normalization.family.type.contextRun.context.Ewf.ordered + have htel := (isType_forallN_inv henv familyType).1 + simpa only [normalization.uvars_eq] using htel + +open AddInductive TypeChecker + +private theorem familyTelNForallNLength : + ∀ (As : List VExpr) (B : VExpr), + VExpr.telN As.length (VExpr.forallN As B) = As + | [], _ => rfl + | _ :: As, B => by + simp only [List.length_cons, VExpr.forallN, VExpr.telN, + familyTelNForallNLength As B] + +private theorem familyDropNForallNLength : + ∀ (As : List VExpr) (B : VExpr), + VExpr.dropN As.length (VExpr.forallN As B) = B + | [], _ => rfl + | _ :: As, B => by + simp only [List.length_cons, VExpr.forallN, VExpr.dropN, + familyDropNForallNLength As B] + +/-- Consume the validator-owned parameter prefix of the retained family +candidate and identify both resulting contexts with the analyzer telescope. + +The executable D3 gate selects the residual kernel family expression. Strict +translation uniqueness, the exact generation shape, and dependent analysis +then identify its Theory endpoint and the terminal local context; neither a +view nor a view-context premise is supplied by the caller. -/ +theorem StagedNormalizationCandidatePreFamilyInput.familyParameterTerminal + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl) + (normalization : NormalizationCandidateSemanticRun env Us candidate rawDecl) + (generation : GenerationChecked rawDecl) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + let trace := candidate.families.singleton.familyType.type.trace + ∃ (parameterΔ : VLCtx) (rest : Expr) + (terminalRun : CandidateContextRun trace.terminalContext) + (viewTerminal : VLCtx), + instantiateFamilyParameters trace.view + (trace.parameterList rawDecl.nparams) = .ok rest ∧ + TrExprS env Us parameterΔ rest + (VExpr.dropN rawDecl.nparams normalization.family.type.view) ∧ + parameterΔ.toCtx = + (VExpr.telN rawDecl.nparams normalization.family.type.view).reverse ∧ + CandidateParameterContext [] (trace.parameterList rawDecl.nparams) + (VExpr.telN rawDecl.nparams normalization.family.type.view) + parameterΔ ∧ + parameterΔ.fvars.map Expr.fvar = + (trace.parameterList rawDecl.nparams).reverse ∧ + parameterΔ.NoBV ∧ + VLCtx.WF env Us.length parameterΔ ∧ + terminalRun.context.venv = env ∧ + terminalRun.context.lparams = Us ∧ + VLCtx.IsDefEq env Us.length terminalRun.context.vlctx viewTerminal ∧ + TrExprS.IsUniqueCtx terminalRun.context.vlctx viewTerminal ∧ + VLCtx.FVLift' parameterΔ viewTerminal 0 + (.skipN .refl generation.block.checked.indices.length) 0 ∧ + viewTerminal.toCtx = + generation.block.checked.indices.reverse ++ parameterΔ.toCtx := by + dsimp only + have familyShape := shape + simp only [NormalizationCandidateSemanticRun.generationShape, + normalizationCandidateGenerationShape, Bool.and_eq_true, + beq_iff_eq] at familyShape + have spineLength_eq : + candidate.families.singleton.familyType.type.trace.spineLength = + (generation.block.checked.params ++ + generation.block.checked.indices).length := by + calc + _ = (VExpr.telN rawDecl.nparams normalization.raw.type ++ + ctorFields (VExpr.dropN rawDecl.nparams normalization.raw.type)).length := + familyShape.1.2 + _ = (generation.block.rawParams ++ + generation.block.rawIndices).length := by + simp only [NormalizedChecked.rawParams, NormalizedChecked.rawIndices, + NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] + _ = (generation.block.checked.params ++ + generation.block.checked.indices).length := by + simp only [List.length_append] + rw [generation.shape.2.1, generation.shape.2.2.1] + have parameterLength : generation.block.checked.params.length = + rawDecl.nparams := + generation.block.checked.direct_anatomy.2.1.trans + generation.block.nparams_eq.symm + have hcount : rawDecl.nparams ≤ + candidate.families.singleton.familyType.type.trace.spineLength := by + rw [spineLength_eq] + simpa only [List.length_append, parameterLength] using + Nat.le_add_right rawDecl.nparams + generation.block.checked.indices.length + have unique : CandidateExprTraceViewIsUnique + candidate.families.singleton.familyType.type.trace := by + apply CandidateExprTrace.viewTranslationUnique_sound + rw [CandidateExprTrace.viewTranslationUnique_eq] + have uniqueGate := input.safety.translationUnique + simp only [Bool.and_eq_true] at uniqueGate + exact uniqueGate.1 + obtain ⟨inferred, recursive⟩ := normalization.family.type.recursive + have rootWF : VLCtx.WF env Us.length ([] : VLCtx) := by + simpa only [normalization.family.type.venv_eq, + normalization.family.type.lparams_eq, + normalization.family.type.vlctx_eq] using + normalization.family.type.contextRun.context.Δwf + have henv : VEnv.Ordered env := by + simpa only [normalization.family.type.venv_eq] using + normalization.family.type.contextRun.context.Ewf.ordered + obtain ⟨parameterΔ, rest, terminalRun, viewTerminal, restEq, restTr, + parameterCtx, parameterContext, parameterFVars, parameterNoBV, + parameterWF, terminalVenv, terminalLparams, + terminalViewDefEq, terminalViewContext, terminalViewLift, + terminalViewEq⟩ := + recursive.parameterViewTerminal normalization.family.type.contextRun + normalization.family.type.venv_eq normalization.family.type.lparams_eq + normalization.family.type.vlctx_eq unique rawDecl.nparams hcount + (.refl henv rootWF) .base (by rfl) + have remaining_eq : + candidate.families.singleton.familyType.type.trace.spineLength - + rawDecl.nparams = generation.block.checked.indices.length := by + rw [spineLength_eq, List.length_append, + parameterLength, Nat.add_sub_cancel_left] + have view_eq : normalization.family.type.view = + generation.block.checked.type.type := + (congrArg (fun ty : VInductiveType => ty.type) + (normalization.root.familyViewType_eq analysis)).symm + have viewDrop_eq : + VExpr.dropN rawDecl.nparams normalization.family.type.view = + VExpr.forallN generation.block.checked.indices + (.sort generation.block.checked.resultLevel) := by + rw [view_eq, generation.block.checked.type_eq, ← parameterLength] + exact familyDropNForallNLength _ _ + refine ⟨parameterΔ, rest, terminalRun, viewTerminal, restEq, restTr, ?_, + parameterContext, ?_, parameterNoBV, parameterWF, terminalVenv, + terminalLparams, + terminalViewDefEq, + terminalViewContext, ?_, ?_⟩ + · simpa only [VLCtx.toCtx, List.append_nil] using parameterCtx + · simpa [VLCtx.fvars] using parameterFVars + · simpa only [remaining_eq] using terminalViewLift + · rw [remaining_eq, viewDrop_eq, + familyTelNForallNLength] at terminalViewEq + exact terminalViewEq + +/-- The analyzer-owned family prefix and D3's pre-family terminal context, +with the residual kernel expression fixed to the exact executable safety +trace and every Theory telescope component fixed to dependent analysis. -/ +theorem StagedNormalizationCandidatePreFamilyInput.familyContext + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl) + (normalization : NormalizationCandidateSemanticRun env Us candidate rawDecl) + (generation : GenerationChecked rawDecl) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + let trace := candidate.families.singleton.familyType.type.trace + ∃ (parameterΔ : VLCtx) + (terminalRun : CandidateContextRun trace.terminalContext) + (viewTerminal : VLCtx), + instantiateFamilyParameters trace.view + (trace.parameterList rawDecl.nparams) = + .ok input.safety.familyIndices ∧ + TrExprS env Us parameterΔ input.safety.familyIndices + (VExpr.forallN generation.block.checked.indices + (.sort generation.block.checked.resultLevel)) ∧ + parameterΔ.toCtx = generation.block.checked.params.reverse ∧ + CandidateParameterContext [] (trace.parameterList rawDecl.nparams) + generation.block.checked.params parameterΔ ∧ + parameterΔ.fvars.map Expr.fvar = + (trace.parameterList rawDecl.nparams).reverse ∧ + parameterΔ.NoBV ∧ + VLCtx.WF env Us.length parameterΔ ∧ + terminalRun.context.venv = env ∧ + terminalRun.context.lparams = Us ∧ + VLCtx.IsDefEq env Us.length terminalRun.context.vlctx viewTerminal ∧ + TrExprS.IsUniqueCtx terminalRun.context.vlctx viewTerminal ∧ + VLCtx.FVLift' parameterΔ viewTerminal 0 + (.skipN .refl generation.block.checked.indices.length) 0 ∧ + viewTerminal.toCtx = + generation.block.checked.indices.reverse ++ + generation.block.checked.params.reverse := by + dsimp only + obtain ⟨parameterΔ, rest, terminalRun, viewTerminal, restEq, restTr, + parameterCtx, parameterContext, parameterFVars, parameterNoBV, + parameterWF, terminalVenv, terminalLparams, + terminalViewDefEq, terminalViewContext, terminalViewLift, + terminalViewEq⟩ := input.familyParameterTerminal normalization + generation analysis shape + let validation := + input.postFamilyInput.universeInput.staged.family.validation + have statsParams : validation.stats.params.toList = + candidate.families.singleton.familyType.type.trace.parameterList + rawDecl.nparams := by + rw [validation.stats_eq] + simp only [CandidateExprTrace.singletonCandidateInductiveStats, + validation, input.postFamilyInput.universeInput.staged.validation_nparams_eq] + have safetyParameters := input.safety.parameters + rw [statsParams] at safetyParameters + have rest_eq : rest = input.safety.familyIndices := by + exact Except.ok.inj (restEq.symm.trans safetyParameters) + subst rest + have parameterLength : generation.block.checked.params.length = + rawDecl.nparams := + generation.block.checked.direct_anatomy.2.1.trans + generation.block.nparams_eq.symm + have view_eq : normalization.family.type.view = + generation.block.checked.type.type := + (congrArg (fun ty : VInductiveType => ty.type) + (normalization.root.familyViewType_eq analysis)).symm + have viewDrop_eq : + VExpr.dropN rawDecl.nparams normalization.family.type.view = + VExpr.forallN generation.block.checked.indices + (.sort generation.block.checked.resultLevel) := by + rw [view_eq, generation.block.checked.type_eq, ← parameterLength] + exact familyDropNForallNLength _ _ + have parameterTel_eq : + VExpr.telN rawDecl.nparams normalization.family.type.view = + generation.block.checked.params := by + rw [view_eq, generation.block.checked.type_eq, ← parameterLength] + exact familyTelNForallNLength _ _ + refine ⟨parameterΔ, terminalRun, viewTerminal, restEq, ?_, ?_, + ?_, parameterFVars, parameterNoBV, parameterWF, terminalVenv, + terminalLparams, + terminalViewDefEq, + terminalViewContext, terminalViewLift, ?_⟩ + · simpa only [viewDrop_eq] using restTr + · simpa only [parameterTel_eq] using parameterCtx + · simpa only [parameterTel_eq] using parameterContext + · simpa only [parameterCtx, parameterTel_eq] using terminalViewEq + +/-- Peeling at most `n` binders cannot expose more than `n` telescope +entries. -/ +private theorem constructorTelN_length_le (n : Nat) (expression : VExpr) : + (VExpr.telN n expression).length ≤ n := by + induction n generalizing expression with + | zero => simp [VExpr.telN] + | succ n ih => cases expression <;> simp [VExpr.telN, ih] + +/-- Strip the validator-owned parameter prefix from one analyzer-selected +constructor and retain the exact D3 suffix together with its strict Theory +translation. + +The source parameter list is fixed by the family validation statistics, the +Theory parameter telescope is fixed by dependent analysis, and the complete +constructor endpoint is fixed by the analyzer-owned raw/view pairing. Thus +the residual endpoint is precisely the stored view fields followed by the +analyzed result target; no whole-Pi injectivity or caller-selected view is +used. -/ +theorem CandidateSemanticNormalizedCtorRun.preFamilySuffix + {env typeEnv : VEnv} {Us : List Name} + {source : VInductDecl} {generation : GenerationChecked source} + {kernelCtor : Constructor} + {candidateCtor : AddInductive.CandidateConstructor kernelCtor} + {rawCtor : VConstVal} + {root : CandidateConstructorSemanticRun typeEnv Us candidateCtor rawCtor} + {ctor : NormalizedCtor} + {stats : InductiveStats} {familyIndices : Expr} + {context : AddInductive.Context} + {contextRun : AddInductive.ConstructorContextRun env Us context} + {d3Trace : AddInductive.ConstructorPreFamilyViewTrace stats 0 + familyIndices context candidateCtor.type.view 0 [] false} + {parameterΔ : VLCtx} {parameters : List Expr} + (genRun : CandidateSemanticNormalizedCtorRun generation.block typeEnv Us + root ctor) + (addType : env ≤ typeEnv) + (parameterContext : CandidateParameterContext [] parameters + generation.block.checked.params parameterΔ) + (parameterWF : VLCtx.WF env Us.length parameterΔ) + (unique : CandidateExprTraceViewIsUnique candidateCtor.type.trace) + (d3 : AddInductive.ConstructorPreFamilyViewSemanticRun env Us stats 0 + familyIndices contextRun d3Trace) + (hctor : ctor ∈ generation.block.ctorPairs) + (parametersEq : stats.params.toList = parameters) + {familyName : Name} {levels : List Level} + (indConsts : stats.indConsts = #[.const familyName levels]) : + ∃ rest, + instantiateFamilyParameters candidateCtor.type.view stats.params.toList = + .ok rest ∧ + Nonempty (AddInductive.ConstructorPreFamilyParameterSuffix + (env := env) (Us := Us) (stats := stats) + (familyIndices := familyIndices) (context := context) + (removed := []) (recursiveStarted := false) + (contextRun := contextRun) rest) ∧ + TrExprS typeEnv Us parameterΔ rest + (VExpr.forallN ctor.view.fields + (ctor.resultTarget generation.block)) := by + have viewTel := genRun.run.viewTel_eq hctor + simp only [CandidateConstructorSemanticRun.root, + NormalizedCtor.viewBinders] at viewTel + have parameterLengthLe : generation.block.checked.params.length ≤ + candidateCtor.type.trace.spineLength := by + apply Nat.le_trans (Nat.le_add_right _ ctor.view.fields.length) + rw [← List.length_append, ← viewTel] + exact constructorTelN_length_le _ _ + have sourceParameterLength : stats.params.toList.length ≤ + candidateCtor.type.trace.spineLength := by + rw [parametersEq, parameterContext.length_eq] + exact parameterLengthLe + obtain ⟨rest, instantiation⟩ := + candidateCtor.type.trace.instantiateViewParameters stats.params.toList + sourceParameterLength + obtain ⟨inferred, recursive⟩ := root.type.recursive + have wholeTr : TrExprS typeEnv Us [] candidateCtor.type.view + (VExpr.forallN generation.block.checked.params + (VExpr.forallN ctor.view.fields + (ctor.resultTarget generation.block))) := by + have strict := recursive.view_tr_strict unique + have viewTypeEq : root.type.view = ctor.view.value.type := by + simpa only [CandidateConstructorSemanticRun.root, + CandidateConstructorRun.view] using + (congrArg (fun value : VConstVal => value.type) genRun.view_eq).symm + rw [viewTypeEq, generation.viewCtorType_eq hctor, + NormalizedCtor.viewBinders] at strict + simpa only [CandidateExpr.view, VExpr.forallN_append] using strict + have parameterWF' : VLCtx.WF typeEnv Us.length parameterΔ := + parameterWF.mono addType + have typeEnvOrdered : typeEnv.Ordered := by + simpa only [root.type.venv_eq] using + root.type.contextRun.context.Ewf.ordered + have suffixTr : TrExprS typeEnv Us parameterΔ rest + (VExpr.forallN ctor.view.fields + (ctor.resultTarget generation.block)) := by + apply parameterContext.instantiateForall typeEnvOrdered parameterWF' + · simpa only [← parametersEq] using instantiation + · exact wholeTr + obtain ⟨suffix⟩ := + d3.afterParameters indConsts (by simp) (by + simpa only [CandidateExpr.view, List.drop_zero] using instantiation) + exact ⟨rest, instantiation, ⟨suffix⟩, suffixTr⟩ + +end VInductDecl + +namespace ConstructorValidation +open AddInductive TypeChecker VEnv + +theorem TrExprS.IsUnique.liftLooseBVars + (unique : TrExprS.IsUnique expression) : + TrExprS.IsUnique (expression.liftLooseBVars' start amount) := by + induction expression generalizing start with + | bvar index => trivial + | fvar | mvar | sort | const | lit => trivial + | app function argument functionIH argumentIH => + exact ⟨functionIH unique.1, argumentIH unique.2⟩ + | lam name domain body binderInfo domainIH bodyIH + | forallE name domain body binderInfo domainIH bodyIH => + exact ⟨domainIH unique.1, bodyIH unique.2⟩ + | letE name type value body nondep typeIH valueIH bodyIH => + exact ⟨valueIH unique.1, bodyIH unique.2⟩ + | mdata data expression ih => exact ih unique + | proj => cases unique + +theorem TrExprS.IsUnique.instantiate1' + (expressionUnique : TrExprS.IsUnique expression) + (argumentUnique : TrExprS.IsUnique argument) : + TrExprS.IsUnique (expression.instantiate1' argument depth) := by + induction expression generalizing depth with + | bvar index => + simp only [Expr.instantiate1'] + split + · trivial + · split + · exact liftLooseBVars argumentUnique + · trivial + | fvar | mvar | sort | const | lit => trivial + | app function argument functionIH argumentIH => + exact ⟨functionIH expressionUnique.1, + argumentIH expressionUnique.2⟩ + | lam name domain body binderInfo domainIH bodyIH + | forallE name domain body binderInfo domainIH bodyIH => + exact ⟨domainIH expressionUnique.1, + bodyIH expressionUnique.2⟩ + | letE name type value body nondep typeIH valueIH bodyIH => + exact ⟨valueIH expressionUnique.1, + bodyIH expressionUnique.2⟩ + | mdata data expression ih => exact ih expressionUnique + | proj => cases expressionUnique + +theorem TrExprS.IsUnique.instantiate1 + (expressionUnique : TrExprS.IsUnique expression) + (argumentUnique : TrExprS.IsUnique argument) : + TrExprS.IsUnique (expression.instantiate1 argument) := by + rw [Expr.instantiate1_eq] + exact instantiate1' expressionUnique argumentUnique + +theorem FVarsIn.consumeTypeAnnotations + (scope : FVarsIn predicate source) : + FVarsIn predicate (AddInductive.consumeTypeAnnotations source) := by + fun_induction AddInductive.consumeTypeAnnotations source <;> + simp_all [FVarsIn] + +theorem instantiateFamilyParameters_unique + (sourceUnique : TrExprS.IsUnique source) + (parametersUnique : ∀ parameter ∈ parameters, + TrExprS.IsUnique parameter) + (run : AddInductive.instantiateFamilyParameters source parameters = + .ok rest) : + TrExprS.IsUnique rest := by + induction parameters generalizing source with + | nil => + have source_eq : source = rest := Except.ok.inj run + simpa only [source_eq] using sourceUnique + | cons parameter parameters ih => + cases source <;> + simp only [AddInductive.instantiateFamilyParameters] at run + case forallE name domain body binderInfo => + exact ih (ConstructorValidation.TrExprS.IsUnique.instantiate1 sourceUnique.2 + (parametersUnique parameter (.head parameters))) + (fun candidate member => + parametersUnique candidate (.tail parameter member)) run + all_goals exact nomatch run + +theorem CandidateParameterContext.parametersUnique + (parameters : CandidateParameterContext base sources types final) : + ∀ source ∈ sources, TrExprS.IsUnique source := by + induction parameters with + | nil => simp + | cons tail ih => + intro source member + simp only [List.mem_cons] at member + rcases member with rfl | member + · trivial + · exact ih source member + +/-- The semantic context invariants shared while D3 and D2 consume the +ordinary prefix of one analyzer-owned constructor view. -/ +structure ConstructorOrdinaryContextState + (env typeEnv : VEnv) (Us : List Name) + (base actual view postActual : VLCtx) (lift : Lift) where + baseWF : VLCtx.WF env Us.length base + actualWF : VLCtx.WF env Us.length actual + postWF : VLCtx.WF typeEnv Us.length postActual + postRelation : VLCtx.IsDefEqFVars typeEnv Us.length actual postActual + viewDefEq : VLCtx.IsDefEq env Us.length actual view + viewUnique : TrExprS.IsUniqueCtx actual view + viewLift : VLCtx.FVLift' base view 0 lift 0 + +/-- Extend the synchronized ordinary-prefix invariant by the exact analyzer +field selected by strict translation. D3 and D2 may retain different +dependency metadata, but use the same operational fresh identifier. -/ +theorem ConstructorOrdinaryContextState.push + {env typeEnv : VEnv} {Us : List Name} + {base actual view postActual : VLCtx} {lift : Lift} + (state : ConstructorOrdinaryContextState env typeEnv Us + base actual view postActual lift) + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + {source : Expr} {analyzer actualSource actualConsumed postConsumed : VExpr} + {fieldLevel consumedLevel : VLevel} {fv : FVarId} + {deps actualDeps postDeps : List FVarId} + (sourceUnique : TrExprS.IsUnique source) + (sourceTr : TrExprS typeEnv Us base source analyzer) + (actualTr : TrExprS env Us actual source actualSource) + (actualAnnotations : env.IsDefEqU Us.length actual.toCtx + actualSource actualConsumed) + (actualConsumedType : env.HasType Us.length actual.toCtx actualConsumed + (.sort consumedLevel)) + (analyzerType : env.HasType Us.length base.toCtx analyzer + (.sort fieldLevel)) + (depsSubset : deps ⊆ base.fvars) + (actualTailWF : VLCtx.WF env Us.length + ((some (fv, actualDeps), .vlam actualConsumed) :: actual)) + (actualDeps_eq : actualDeps = deps) + (postTailWF : VLCtx.WF typeEnv Us.length + ((some (fv, postDeps), .vlam postConsumed) :: postActual)) + (consumedEq : typeEnv.IsDefEq Us.length actual.toCtx + actualConsumed postConsumed (.sort consumedLevel)) : + ConstructorOrdinaryContextState env typeEnv Us + ((some (fv, deps), .vlam analyzer) :: base) + ((some (fv, actualDeps), .vlam actualConsumed) :: actual) + ((some (fv, deps), .vlam (analyzer.lift' lift)) :: view) + ((some (fv, postDeps), .vlam postConsumed) :: postActual) + (.consN lift 1) := by + subst actualDeps + have viewWF : VLCtx.WF env Us.length view := + (state.viewDefEq.symm henv.ordered).wf + have analyzerAtView : TrExprS typeEnv Us view source + (analyzer.lift' lift) := + sourceTr.weakFV' typeEnvWF.ordered state.viewLift + (viewWF.mono addType) + have actualSource_eq : actualSource = + analyzer.lift' lift := + (actualTr.mono addType).unique' state.viewUnique sourceUnique + analyzerAtView + have consumedToAnalyzer : env.IsDefEq Us.length actual.toCtx + actualConsumed (analyzer.lift' lift) + (.sort consumedLevel) := by + rw [← actualSource_eq] + exact (actualAnnotations.of_r henv state.actualWF.toCtx + actualConsumedType).symm + have freshBase : fv ∉ base.fvars := by + intro present + have presentView : fv ∈ view.fvars := + state.viewLift.fvars_sublist.subset present + have presentActual : fv ∈ actual.fvars := by + simpa only [state.viewDefEq.fvars] using presentView + exact (actualTailWF.2.1 fv deps rfl).1 presentActual + have baseTailWF : VLCtx.WF env Us.length + ((some (fv, deps), .vlam analyzer) :: base) := + ⟨state.baseWF, + fun _ _ equality => by + cases equality + exact ⟨freshBase, depsSubset⟩, + ⟨fieldLevel, analyzerType⟩⟩ + have nextViewDefEq : VLCtx.IsDefEq env Us.length + ((some (fv, deps), .vlam actualConsumed) :: actual) + ((some (fv, deps), .vlam (analyzer.lift' lift)) :: view) := + .cons state.viewDefEq actualTailWF.2.1 (.vlam consumedToAnalyzer) + exact { + baseWF := baseTailWF + actualWF := actualTailWF + postWF := postTailWF + postRelation := .cons_fvar state.postRelation (.vlam consumedEq) + viewDefEq := nextViewDefEq + viewUnique := state.viewUnique.cons .vlam + viewLift := state.viewLift.cons_fvar (fv, deps) (.vlam analyzer) + depsSubset } + +private theorem vexpr_appArgs_acc (expression : VExpr) (suffix : List VExpr) : + VExpr.appArgs expression suffix = + VExpr.appArgs expression [] ++ suffix := by + induction expression generalizing suffix with + | app function argument ihFunction ihArgument => + simp only [VExpr.appArgs] + rw [ihFunction, ihFunction (suffix := [argument])] + simp + | bvar | sort | const | lam | forallE => simp [VExpr.appArgs] + +private theorem expr_getAppArgsList_acc (expression : Expr) + (suffix : List Expr) : + expression.getAppArgsList suffix = + expression.getAppArgsList [] ++ suffix := by + induction expression generalizing suffix with + | app function argument ihFunction ihArgument => + simp only [Expr.getAppArgsList] + rw [ihFunction, ihFunction (suffix := [argument])] + simp + | bvar | fvar | mvar | sort | const | lit | mdata | proj | lam | forallE | + letE => simp [Expr.getAppArgsList] + +theorem TrExprS.IsUnique.getAppArgsList + (unique : TrExprS.IsUnique expression) : + ∀ argument ∈ expression.getAppArgsList, + TrExprS.IsUnique argument := by + induction expression with + | app function argument functionIH argumentIH => + intro candidate member + rw [Expr.getAppArgsList, expr_getAppArgsList_acc] at member + simp only [List.mem_append, List.mem_singleton] at member + rcases member with member | rfl + · exact functionIH unique.1 candidate member + · exact unique.2 + | bvar | fvar | mvar | sort | const | lit | mdata | proj | lam | forallE | + letE => simp [Expr.getAppArgsList] + +theorem Closed.getAppArgsList + (closed : Closed expression depth) : + ∀ argument ∈ expression.getAppArgsList, + Closed argument depth := by + induction expression with + | app function argument functionIH argumentIH => + intro candidate member + rw [Expr.getAppArgsList, expr_getAppArgsList_acc] at member + simp only [List.mem_append, List.mem_singleton] at member + rcases member with member | rfl + · exact functionIH closed.1 candidate member + · exact closed.2 + | bvar | fvar | mvar | sort | const | lit | mdata | proj | lam | forallE | + letE => simp [Expr.getAppArgsList] + +private theorem vexpr_appHead_appN (head : VExpr) (arguments : List VExpr) : + VExpr.appHead (VExpr.appN head arguments) = VExpr.appHead head := by + induction arguments generalizing head with + | nil => rfl + | cons argument arguments ih => + simp only [VExpr.appN] + rw [ih] + rfl + +private def vexprLiftTel (lift : Lift) : List VExpr → List VExpr + | [] => [] + | domain :: domains => + domain.lift' lift :: vexprLiftTel lift.cons domains + +private theorem vexpr_lift'_forallN (lift : Lift) : + ∀ (domains : List VExpr) (body : VExpr), + (VExpr.forallN domains body).lift' lift = + VExpr.forallN (vexprLiftTel lift domains) + (body.lift' (lift.consN domains.length)) + | [], _ => rfl + | domain :: domains, body => by + simp only [VExpr.forallN, VExpr.lift', vexprLiftTel, + List.length_cons] + rw [vexpr_lift'_forallN lift.cons domains body] + congr 2 + rw [show domains.length + 1 = 1 + domains.length by omega, + ← Lift.consN_consN] + rfl + +private theorem vexprLiftTel_length (lift : Lift) : + ∀ domains : List VExpr, + (vexprLiftTel lift domains).length = domains.length + | [] => rfl + | _ :: domains => by + simp only [vexprLiftTel, List.length_cons, + vexprLiftTel_length lift.cons domains] + +private theorem forall₂_append + (left : List.Forall₂ relation leftSources leftTargets) + (right : List.Forall₂ relation rightSources rightTargets) : + List.Forall₂ relation (leftSources ++ rightSources) + (leftTargets ++ rightTargets) := by + induction left with + | nil => exact right + | cons head tail ih => exact .cons head ih + +private theorem forall₂_length + (run : List.Forall₂ relation sources targets) : + sources.length = targets.length := by + induction run with + | nil => rfl + | cons _ _ ih => exact congrArg Nat.succ ih + +theorem forall₂_translation_unique + (left : List.Forall₂ (TrExprS env Us context) sources leftTargets) + (right : List.Forall₂ (TrExprS env Us context) sources rightTargets) + (unique : ∀ source ∈ sources, TrExprS.IsUnique source) : + leftTargets = rightTargets := by + induction left generalizing rightTargets with + | nil => cases right; rfl + | @cons source leftTarget sources leftTargets leftHead leftTail ih => + cases right with + | cons rightHead rightTail => + rw [leftHead.unique (unique source (.head sources)) rightHead, + ih rightTail (fun candidate member => + unique candidate (.tail source member))] + +theorem forall₂_drop + (run : List.Forall₂ relation sources targets) (n : Nat) : + List.Forall₂ relation (sources.drop n) (targets.drop n) := by + induction n generalizing sources targets with + | zero => simpa using run + | succ n ih => + cases run with + | nil => exact .nil + | cons head tail => simpa using ih tail + +theorem forall₂_tr_weakFV' + {env : VEnv} {Us : List Name} {base full : VLCtx} + {lift : Lift} (henv : VEnv.Ordered env) + (extension : VLCtx.FVLift' base full 0 lift 0) + (fullWF : VLCtx.WF env Us.length full) + (run : List.Forall₂ (TrExprS env Us base) sources targets) : + List.Forall₂ (TrExprS env Us full) sources + (targets.map fun target => target.lift' lift) := by + induction run with + | nil => exact .nil + | cons head tail ih => + exact .cons (by simpa using head.weakFV' henv extension fullWF) ih + +theorem forall₂_tr_mono + (add : env ≤ env') + (run : List.Forall₂ (TrExprS env Us context) sources targets) : + List.Forall₂ (TrExprS env' Us context) sources targets := by + induction run with + | nil => exact .nil + | cons head tail ih => exact .cons (head.mono add) ih + +theorem isValidIndAppIdx_shape + {stats : AddInductive.InductiveStats} {source : Expr} + {familyIdx : Nat} + (valid : AddInductive.isValidIndAppIdx stats source familyIdx = true) : + (source.getAppFn == stats.indConsts[familyIdx]!) = true ∧ + source.getAppArgs.size = + stats.params.size + stats.nindices[familyIdx]! := by + unfold AddInductive.isValidIndAppIdx at valid + rw [Expr.withApp_eq] at valid + simp only [Id.run] at valid + split at valid + · rename_i shape + simpa only [Bool.and_eq_true, beq_iff_eq] using shape + · simp_all + +theorem isValidIndAppIdx_indexArgs_length + {stats : AddInductive.InductiveStats} {source : Expr} + {familyIdx : Nat} + (valid : AddInductive.isValidIndAppIdx stats source familyIdx = true) : + (source.getAppArgs.toList.drop stats.params.size).length = + stats.nindices[familyIdx]! := by + have shape := isValidIndAppIdx_shape valid + rw [List.length_drop, Array.length_toList, shape.2] + omega + +theorem constructorIndependentOf_fvars + {source : Expr} {full base removed : List FVarId} + (scope : FVarsIn (· ∈ full) source) + (independent : AddInductive.constructorIndependentOf source removed = true) + (remaining : ∀ fv, fv ∈ full → fv ∉ removed → fv ∈ base) : + FVarsIn (· ∈ base) source := by + rw [fvarsIn_iff] at scope ⊢ + refine ⟨?_, scope.2⟩ + intro fv member + apply remaining fv (scope.1 fv member) + unfold AddInductive.constructorIndependentOf at independent + simp only [List.all_eq_true] at independent + have omitted := independent fv member + simpa using omitted + +/-- Strict translation preserves a constant-headed application spine and +translates its arguments position-for-position. -/ +theorem TrExprS.constApp_components + {env : VEnv} {Us : List Name} {context : VLCtx} + {source : Expr} {target : VExpr} {name : Name} {levels : List Level} + (run : TrExprS env Us context source target) + (head : source.getAppFn = .const name levels) : + ∃ levels', + VExpr.appHead target = .const name levels' ∧ + List.Forall₂ (TrExprS env Us context) + source.getAppArgsList (VExpr.appArgs target []) := by + induction source generalizing target with + | const sourceName sourceLevels => + cases run with + | const lookup levelsTr arity => + simp only [Expr.getAppFn] at head + obtain ⟨rfl, rfl⟩ := head + exact ⟨_, rfl, .nil⟩ + | app function argument functionIH argumentIH => + cases run with + | app => + rename_i function' domain' body' argument' functionType argumentType + functionTr argumentTr + have functionHead : function.getAppFn = .const name levels := by + simpa only [Expr.getAppFn] using head + obtain ⟨levels', targetHead, argumentsTr⟩ := + functionIH functionTr functionHead + refine ⟨levels', ?_, ?_⟩ + · simpa only [VExpr.appHead] using targetHead + · rw [show VExpr.appArgs (.app function' argument') [] = + VExpr.appArgs function' [] ++ [argument'] by + rw [VExpr.appArgs, vexpr_appArgs_acc]] + simp only [Expr.getAppArgsList] at * + rw [expr_getAppArgsList_acc] + exact forall₂_append argumentsTr (.cons argumentTr .nil) + | bvar => cases run; simp [Expr.getAppFn] at head + | fvar => cases run; simp [Expr.getAppFn] at head + | mvar => cases run + | sort => cases run; simp [Expr.getAppFn] at head + | lam => cases run; simp [Expr.getAppFn] at head + | forallE => cases run; simp [Expr.getAppFn] at head + | letE => cases run; simp [Expr.getAppFn] at head + | lit => cases run; simp [Expr.getAppFn] at head + | mdata => cases run; simp [Expr.getAppFn] at head + | proj => cases run; simp [Expr.getAppFn] at head + +/-- Remove one verified free-variable context extension from a list of strict +translations, retaining the exact lifted endpoints. -/ +theorem TrExprS.forall₂_weakFV_inv + {env : VEnv} {Us : List Name} {base full : VLCtx} + {sources : List Expr} {targets : List VExpr} {n : Lift} + (henv : VEnv.WF env) (fullWF : VLCtx.WF env Us.length full) + (extension : VLCtx.FVLift' base full 0 n 0) + (runs : List.Forall₂ (TrExprS env Us full) sources targets) + (closed : ∀ source ∈ sources, Closed source) + (fvars : ∀ source ∈ sources, FVarsIn (· ∈ base.fvars) source) + (unique : ∀ source ∈ sources, TrExprS.IsUnique source) : + ∃ baseTargets, + List.Forall₂ (TrExprS env Us base) sources baseTargets ∧ + targets = baseTargets.map (fun target => target.lift' (n.consN 0)) := by + induction runs with + | nil => exact ⟨[], .nil, rfl⟩ + | @cons source target sources targets headRun tailRuns ih => + have headClosed := closed source (.head sources) + have headFVars := fvars source (.head sources) + have headUnique := unique source (.head sources) + have tailClosed : ∀ expression ∈ sources, Closed expression := + fun expression member => closed expression (.tail source member) + have tailFVars : ∀ expression ∈ sources, + FVarsIn (· ∈ base.fvars) expression := + fun expression member => fvars expression (.tail source member) + have tailUnique : ∀ expression ∈ sources, + TrExprS.IsUnique expression := + fun expression member => unique expression (.tail source member) + obtain ⟨headBase, headBaseRun⟩ := + headRun.weakFV'_inv henv extension (.refl henv fullWF) + headClosed headFVars + obtain ⟨tailBase, tailBaseRuns, tailEq⟩ := + ih tailClosed tailFVars tailUnique + have headEq : target = headBase.lift' (n.consN 0) := + headRun.unique headUnique + (headBaseRun.weakFV' henv.ordered extension fullWF) + subst target + exact ⟨headBase :: tailBase, .cons headBaseRun tailBaseRuns, by + simp only [List.map_cons, tailEq]⟩ + +/-- Remove a free-variable extension modulo the verified context equality +used by the retained checker run. -/ +theorem TrExprS.forall₂_weakFV_inv_defeq + {env : VEnv} {Us : List Name} {base actual view : VLCtx} + {sources : List Expr} {targets : List VExpr} {n : Lift} + (henv : VEnv.WF env) + (viewDefEq : VLCtx.IsDefEq env Us.length actual view) + (viewUnique : TrExprS.IsUniqueCtx actual view) + (extension : VLCtx.FVLift' base view 0 n 0) + (runs : List.Forall₂ (TrExprS env Us actual) sources targets) + (closed : ∀ source ∈ sources, Closed source) + (fvars : ∀ source ∈ sources, FVarsIn (· ∈ base.fvars) source) + (unique : ∀ source ∈ sources, TrExprS.IsUnique source) : + ∃ baseTargets, + List.Forall₂ (TrExprS env Us base) sources baseTargets ∧ + targets = baseTargets.map (fun target => target.lift' (n.consN 0)) := by + have viewWF : VLCtx.WF env Us.length view := + (viewDefEq.symm henv.ordered).wf + induction runs with + | nil => exact ⟨[], .nil, rfl⟩ + | @cons source target sources targets headRun tailRuns ih => + have headClosed := closed source (.head sources) + have headFVars := fvars source (.head sources) + have headUnique := unique source (.head sources) + have tailClosed : ∀ expression ∈ sources, Closed expression := + fun expression member => closed expression (.tail source member) + have tailFVars : ∀ expression ∈ sources, + FVarsIn (· ∈ base.fvars) expression := + fun expression member => fvars expression (.tail source member) + have tailUnique : ∀ expression ∈ sources, + TrExprS.IsUnique expression := + fun expression member => unique expression (.tail source member) + obtain ⟨headBase, headBaseRun⟩ := + headRun.weakFV'_inv henv extension viewDefEq + headClosed headFVars + obtain ⟨tailBase, tailBaseRuns, tailEq⟩ := + ih tailClosed tailFVars tailUnique + have headEq : target = headBase.lift' (n.consN 0) := + headRun.unique' viewUnique headUnique + (headBaseRun.weakFV' henv.ordered extension viewWF) + subst target + exact ⟨headBase :: tailBase, .cons headBaseRun tailBaseRuns, by + simp only [List.map_cons, tailEq]⟩ + +theorem ConstructorPreFamilyIndexSpineSemanticRun.expected_eq_of_family_lift + {env : VEnv} {Us : List Name} {context : AddInductive.Context} + {contextRun : AddInductive.ConstructorContextRun env Us context} + {expected : Expr} {arguments : List Expr} + {trace : AddInductive.ConstructorPreFamilyIndexSpineTrace context expected + arguments} + {expected' : VExpr} + (run : AddInductive.ConstructorPreFamilyIndexSpineSemanticRun env Us + context contextRun trace expected') + {base view : VLCtx} {expectedBase : VExpr} {lift : Lift} + (familyTr : TrExprS env Us base expected expectedBase) + (unique : TrExprS.IsUnique expected) + (extension : VLCtx.FVLift' base view 0 lift 0) + (viewDefEq : VLCtx.IsDefEq env Us.length + contextRun.candidate.context.vlctx view) + (viewUnique : TrExprS.IsUniqueCtx + contextRun.candidate.context.vlctx view) : + expected' = expectedBase.lift' (lift.consN 0) := by + have henv : VEnv.Ordered env := by + simpa only [contextRun.venv_eq] using + contextRun.candidate.context.Ewf.ordered + have viewWF : VLCtx.WF env Us.length view := + (viewDefEq.symm henv).wf + have familyAtView : TrExprS env Us view expected + (expectedBase.lift' (lift.consN 0)) := + familyTr.weakFV' henv extension viewWF + have retained : TrExprS env Us contextRun.candidate.context.vlctx + expected expected' := run.expectedRun.expr_tr + exact retained.unique' viewUnique unique familyAtView + +theorem VLCtx.FVLift'.toCtxLiftN + {base view : VLCtx} {n : Nat} + (extension : VLCtx.FVLift' base view 0 (.skipN .refl n) 0) : + Ctx.LiftN n 0 base.toCtx view.toCtx := by + exact Ctx.liftN_iff_lift'.2 extension.toCtx + +/-- Transport a spine to the canonical view context and then remove the +free-variable extension from all of its endpoints. -/ +theorem VEnv.SpineWF.fvLift_inv + {env : VEnv} {U n : Nat} {base actual view : VLCtx} + {arguments : List VExpr} {source target : VExpr} + (henv : VEnv.WF env) + (viewDefEq : VLCtx.IsDefEq env U actual view) + (extension : VLCtx.FVLift' base view 0 (.skipN .refl n) 0) + (run : env.SpineWF U actual.toCtx (source.liftN n 0) + (arguments.map fun argument => argument.liftN n 0) + (target.liftN n 0)) : + env.SpineWF U base.toCtx source arguments target := by + have viewWF : VLCtx.WF env U view := + (viewDefEq.symm henv.ordered).wf + have viewRun : env.SpineWF U view.toCtx (source.liftN n 0) + (arguments.map fun argument => argument.liftN n 0) + (target.liftN n 0) := + run.defeqDFC henv.ordered viewDefEq.defeqCtx + exact VEnv.SpineWF.weakN_inv henv viewWF.toCtx + (Ctx.liftN_iff_lift'.2 extension.toCtx) viewRun + +theorem VEnv.SpineWF.fvLift'_inv + {env : VEnv} {U : Nat} {lift : Lift} {base actual view : VLCtx} + {arguments : List VExpr} {source target : VExpr} + (henv : VEnv.WF env) + (viewDefEq : VLCtx.IsDefEq env U actual view) + (extension : VLCtx.FVLift' base view 0 lift 0) + (run : env.SpineWF U actual.toCtx (source.lift' (lift.consN 0)) + (arguments.map fun argument => argument.lift' (lift.consN 0)) + (target.lift' (lift.consN 0))) : + env.SpineWF U base.toCtx source arguments target := by + have viewWF : VLCtx.WF env U view := + (viewDefEq.symm henv.ordered).wf + have viewRun : env.SpineWF U view.toCtx + (source.lift' (lift.consN 0)) + (arguments.map fun argument => argument.lift' (lift.consN 0)) + (target.lift' (lift.consN 0)) := + run.defeqDFC henv.ordered viewDefEq.defeqCtx + exact VEnv.SpineWF.weak'_inv henv viewWF.toCtx extension.toCtx viewRun + +/-- Identify a pre-family index replay with the analyzer family telescope, +remove the family-index locals, and retarget its terminal to the family sort. -/ +theorem ConstructorPreFamilyIndexSpineSemanticRun.baseSpine + {env : VEnv} {Us : List Name} {context : AddInductive.Context} + {contextRun : AddInductive.ConstructorContextRun env Us context} + {expected : Expr} {arguments : List Expr} + {trace : AddInductive.ConstructorPreFamilyIndexSpineTrace context expected + arguments} + {expected' : VExpr} {base view : VLCtx} {indices : List VExpr} + {level : VLevel} {n : Nat} + (run : AddInductive.ConstructorPreFamilyIndexSpineSemanticRun env Us + context contextRun trace expected') + (familyTr : TrExprS env Us base expected + (VExpr.forallN indices (.sort level))) + (expectedUnique : TrExprS.IsUnique expected) + (viewDefEq : VLCtx.IsDefEq env Us.length + contextRun.candidate.context.vlctx view) + (viewUnique : TrExprS.IsUniqueCtx + contextRun.candidate.context.vlctx view) + (extension : VLCtx.FVLift' base view 0 (.skipN .refl n) 0) + (argumentClosed : ∀ argument ∈ arguments, Closed argument) + (argumentFVars : ∀ argument ∈ arguments, + FVarsIn (· ∈ base.fvars) argument) + (argumentUnique : ∀ argument ∈ arguments, + TrExprS.IsUnique argument) + (argumentLength : arguments.length = indices.length) : + ∃ indices', + List.Forall₂ (TrExprS env Us base) arguments indices' ∧ + env.SpineWF Us.length base.toCtx + (VExpr.forallN indices (.sort level)) indices' (.sort level) := by + have henv : VEnv.WF env := by + simpa only [contextRun.venv_eq] using + contextRun.candidate.context.Ewf + have expectedEq : expected' = + (VExpr.forallN indices (.sort level)).liftN n 0 := + run.expected_eq_of_family familyTr expectedUnique extension viewDefEq + viewUnique + subst expected' + obtain ⟨indices', indicesTr, indicesEq⟩ := + TrExprS.forall₂_weakFV_inv_defeq henv viewDefEq viewUnique + extension run.arguments_tr argumentClosed argumentFVars argumentUnique + have translatedLength : run.arguments'.length = + (VExpr.liftTelN n indices 0).length := by + rw [← forall₂_length run.arguments_tr, argumentLength, + VExpr.liftTelN_length] + have liftedSpine : env.SpineWF Us.length + contextRun.candidate.context.vlctx.toCtx + ((VExpr.forallN indices (.sort level)).liftN n 0) + run.arguments' (.sort level) := by + have sourceEq : + (VExpr.forallN indices (.sort level)).liftN n 0 = + VExpr.forallN (VExpr.liftTelN n indices 0) (.sort level) := by + rw [VExpr.liftN_forallN] + rfl + have spine : env.SpineWF Us.length + contextRun.candidate.context.vlctx.toCtx + (VExpr.forallN (VExpr.liftTelN n indices 0) (.sort level)) + run.arguments' run.result' := + sourceEq ▸ run.spine + have retargeted := spine.retarget translatedLength (.sort level) + have sortClosed : (VExpr.sort level).ClosedN 0 := by trivial + have targetEq : (VExpr.sort level).instRev run.arguments' = + .sort level := VExpr.instRev_closedN run.arguments' sortClosed + rw [targetEq] at retargeted + exact Eq.mpr (congrArg (fun source => env.SpineWF Us.length + contextRun.candidate.context.vlctx.toCtx source run.arguments' + (.sort level)) sourceEq) retargeted + simp only [VExpr.lift'_consN_skipN] at indicesEq + rw [indicesEq] at liftedSpine + exact ⟨indices', indicesTr, by + apply VEnv.SpineWF.fvLift_inv henv viewDefEq extension + simpa only [VExpr.liftN] using liftedSpine⟩ + +theorem ConstructorPreFamilyIndexSpineSemanticRun.baseSpine_lift + {env : VEnv} {Us : List Name} {context : AddInductive.Context} + {contextRun : AddInductive.ConstructorContextRun env Us context} + {expected : Expr} {arguments : List Expr} + {trace : AddInductive.ConstructorPreFamilyIndexSpineTrace context expected + arguments} + {expected' : VExpr} {base view : VLCtx} {indices : List VExpr} + {level : VLevel} {lift : Lift} + (run : AddInductive.ConstructorPreFamilyIndexSpineSemanticRun env Us + context contextRun trace expected') + (familyTr : TrExprS env Us base expected + (VExpr.forallN indices (.sort level))) + (expectedUnique : TrExprS.IsUnique expected) + (viewDefEq : VLCtx.IsDefEq env Us.length + contextRun.candidate.context.vlctx view) + (viewUnique : TrExprS.IsUniqueCtx + contextRun.candidate.context.vlctx view) + (extension : VLCtx.FVLift' base view 0 lift 0) + (argumentClosed : ∀ argument ∈ arguments, Closed argument) + (argumentFVars : ∀ argument ∈ arguments, + FVarsIn (· ∈ base.fvars) argument) + (argumentUnique : ∀ argument ∈ arguments, + TrExprS.IsUnique argument) + (argumentLength : arguments.length = indices.length) : + ∃ indices', + List.Forall₂ (TrExprS env Us base) arguments indices' ∧ + env.SpineWF Us.length base.toCtx + (VExpr.forallN indices (.sort level)) indices' (.sort level) := by + have henv : VEnv.WF env := by + simpa only [contextRun.venv_eq] using + contextRun.candidate.context.Ewf + have expectedEq : expected' = + (VExpr.forallN indices (.sort level)).lift' (lift.consN 0) := + expected_eq_of_family_lift run familyTr expectedUnique extension + viewDefEq viewUnique + subst expected' + obtain ⟨indices', indicesTr, indicesEq⟩ := + TrExprS.forall₂_weakFV_inv_defeq henv viewDefEq viewUnique + extension run.arguments_tr argumentClosed argumentFVars argumentUnique + have translatedLength : run.arguments'.length = + (vexprLiftTel (lift.consN 0) indices).length := by + rw [← forall₂_length run.arguments_tr, argumentLength, + vexprLiftTel_length] + have liftedSpine : env.SpineWF Us.length + contextRun.candidate.context.vlctx.toCtx + ((VExpr.forallN indices (.sort level)).lift' (lift.consN 0)) + run.arguments' (.sort level) := by + have sourceEq : + (VExpr.forallN indices (.sort level)).lift' (lift.consN 0) = + VExpr.forallN (vexprLiftTel (lift.consN 0) indices) + (.sort level) := by + rw [vexpr_lift'_forallN] + rfl + have spine : env.SpineWF Us.length + contextRun.candidate.context.vlctx.toCtx + (VExpr.forallN (vexprLiftTel (lift.consN 0) indices) (.sort level)) + run.arguments' run.result' := + sourceEq ▸ run.spine + have retargeted := spine.retarget translatedLength (.sort level) + have sortClosed : (VExpr.sort level).ClosedN 0 := by trivial + have targetEq : (VExpr.sort level).instRev run.arguments' = + .sort level := VExpr.instRev_closedN run.arguments' sortClosed + rw [targetEq] at retargeted + exact Eq.mpr (congrArg (fun source => env.SpineWF Us.length + contextRun.candidate.context.vlctx.toCtx source run.arguments' + (.sort level)) sourceEq) retargeted + rw [indicesEq] at liftedSpine + exact ⟨indices', indicesTr, by + apply VEnv.SpineWF.fvLift'_inv henv viewDefEq extension + simpa only [VExpr.lift'] using liftedSpine⟩ + +/-- Recover the exact analyzer-selected source type and its checker-selected +sort after removing a verified free-variable context extension. -/ +theorem ensureTypeRun_baseType + {env typeEnv : VEnv} {Us : List Name} + {base actual view : VLCtx} {source : Expr} + {source' actual' : VExpr} {fieldLevel : VLevel} {n : Lift} + (henv : VEnv.WF env) (typeEnvOrdered : VEnv.Ordered typeEnv) + (addType : env ≤ typeEnv) + (_baseWF : VLCtx.WF env Us.length base) + (viewDefEq : VLCtx.IsDefEq env Us.length actual view) + (viewUnique : TrExprS.IsUniqueCtx actual view) + (viewLift : VLCtx.FVLift' base view 0 n 0) + (sourceUnique : TrExprS.IsUnique source) + (sourceClosed : Closed source) + (sourceFVars : FVarsIn (· ∈ base.fvars) source) + (sourceTr : TrExprS typeEnv Us base source source') + (actualTr : TrExprS env Us actual source actual') + (actualType : env.HasType Us.length actual.toCtx actual' (.sort fieldLevel)) : + env.HasType Us.length base.toCtx source' (.sort fieldLevel) := by + obtain ⟨base', baseTr⟩ := + actualTr.weakFV'_inv henv viewLift viewDefEq sourceClosed sourceFVars + have baseEq : base' = source' := + (baseTr.mono addType).unique sourceUnique sourceTr + subst base' + have viewWF : VLCtx.WF env Us.length view := + (viewDefEq.symm henv.ordered).wf + have sourceAtView := sourceTr + have sourceAtView' : TrExprS typeEnv Us view source + (source'.lift' (n.consN 0)) := + sourceAtView.weakFV' typeEnvOrdered viewLift (viewWF.mono addType) + have actualEq : actual' = source'.lift' (n.consN 0) := by + exact (actualTr.mono addType).unique' viewUnique sourceUnique sourceAtView' + have sourceTypeAtView : env.HasType Us.length view.toCtx + actual' (.sort fieldLevel) := + actualType.defeqDFC henv.ordered viewDefEq.defeqCtx + rw [actualEq] at sourceTypeAtView + exact (HasType.weak'_iff henv viewWF.toCtx viewLift.toCtx).1 (by + simpa using sourceTypeAtView) + +theorem ensureTypeRun_baseType_mono + {env typeEnv : VEnv} {Us : List Name} + {base actual view : VLCtx} {source : Expr} + {source' actual' : VExpr} {fieldLevel : VLevel} {n : Lift} + (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + (baseWF : VLCtx.WF env Us.length base) + (viewDefEq : VLCtx.IsDefEq env Us.length actual view) + (viewUnique : TrExprS.IsUniqueCtx actual view) + (viewLift : VLCtx.FVLift' base view 0 n 0) + (sourceUnique : TrExprS.IsUnique source) + (sourceClosed : Closed source) + (sourceFVars : FVarsIn (· ∈ base.fvars) source) + (sourceTr : TrExprS typeEnv Us base source source') + (actualTr : TrExprS env Us actual source actual') + (actualType : typeEnv.HasType Us.length actual.toCtx actual' + (.sort fieldLevel)) : + typeEnv.HasType Us.length base.toCtx source' (.sort fieldLevel) := by + exact ensureTypeRun_baseType typeEnvWF + typeEnvWF.ordered VEnv.LE.rfl + (baseWF.mono addType) (viewDefEq.mono addType) viewUnique viewLift + sourceUnique sourceClosed sourceFVars sourceTr (actualTr.mono addType) + actualType + +/-- Recover a family-free base endpoint when the analyzer translation lives +under a different prefix than D3's index-extended replay context. -/ +theorem ensureTypeRun_commonType + {env typeEnv : VEnv} {Us : List Name} + {base full actual view : VLCtx} {source : Expr} + {fullTarget actualTarget : VExpr} {fieldLevel : VLevel} + {fullLift viewLift : Lift} + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + (baseWF : VLCtx.WF env Us.length base) + (fullWF : VLCtx.WF typeEnv Us.length full) + (fullExtension : VLCtx.FVLift' base full 0 fullLift 0) + (viewDefEq : VLCtx.IsDefEq env Us.length actual view) + (viewUnique : TrExprS.IsUniqueCtx actual view) + (viewExtension : VLCtx.FVLift' base view 0 viewLift 0) + (sourceUnique : TrExprS.IsUnique source) + (sourceClosed : Closed source) + (sourceFVars : FVarsIn (· ∈ base.fvars) source) + (fullTr : TrExprS typeEnv Us full source fullTarget) + (actualTr : TrExprS env Us actual source actualTarget) + (actualType : env.HasType Us.length actual.toCtx actualTarget + (.sort fieldLevel)) : + ∃ baseTarget, + TrExprS typeEnv Us base source baseTarget ∧ + fullTarget = baseTarget.lift' fullLift ∧ + env.HasType Us.length base.toCtx baseTarget (.sort fieldLevel) := by + obtain ⟨baseTarget, baseTr⟩ := fullTr.weakFV'_inv typeEnvWF + fullExtension (.refl typeEnvWF.ordered fullWF) sourceClosed sourceFVars + have fullEq : fullTarget = baseTarget.lift' fullLift := + fullTr.unique sourceUnique + (baseTr.weakFV' typeEnvWF.ordered fullExtension fullWF) + have baseType := ensureTypeRun_baseType + henv typeEnvWF.ordered + addType baseWF viewDefEq viewUnique viewExtension sourceUnique + sourceClosed sourceFVars baseTr actualTr actualType + exact ⟨baseTarget, baseTr, fullEq, baseType⟩ + +/-- D2 types the exact analyzer-owned field in the synthetic full field +context and relates it to the declaration actually pushed by validation. -/ +theorem analyzerField_postType + {typeEnv : VEnv} {Us : List Name} + {full postActual : VLCtx} {source : Expr} + {analyzer postRaw postView postConsumed : VExpr} + {rawLevel : VLevel} + (typeEnvWF : VEnv.WF typeEnv) + (fullWF : VLCtx.WF typeEnv Us.length full) + (postWF : VLCtx.WF typeEnv Us.length postActual) + (relation : VLCtx.IsDefEqFVars typeEnv Us.length full postActual) + (analyzerTr : TrExprS typeEnv Us full source analyzer) + (postViewTr : TrExprS typeEnv Us postActual source postView) + (postRawType : typeEnv.HasType Us.length postActual.toCtx postRaw + (.sort rawLevel)) + (postRawView : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw postView) + (postAnnotations : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw postConsumed) : + typeEnv.HasType Us.length full.toCtx analyzer (.sort rawLevel) ∧ + typeEnv.IsDefEq Us.length full.toCtx analyzer postConsumed + (.sort rawLevel) := by + have postViewType : typeEnv.HasType Us.length postActual.toCtx postView + (.sort rawLevel) := + postRawType.defeqU_l typeEnvWF postWF.toCtx postRawView + have postViewAtFull : typeEnv.HasType Us.length full.toCtx postView + (.sort rawLevel) := + postViewType.defeqDFC typeEnvWF.ordered + (relation.defeqCtx.symm typeEnvWF.ordered) + have analyzerViewU : typeEnv.IsDefEqU Us.length full.toCtx + analyzer postView := + analyzerTr.uniqFVars typeEnvWF relation fullWF postViewTr + have analyzerView := analyzerViewU.of_r typeEnvWF fullWF.toCtx + postViewAtFull + have rawViewAtFull := postRawView.defeqDFC typeEnvWF.ordered + (relation.defeqCtx.symm typeEnvWF.ordered) + have rawConsumedAtFull := postAnnotations.defeqDFC typeEnvWF.ordered + (relation.defeqCtx.symm typeEnvWF.ordered) + have rawTypeAtFull := postRawType.defeqDFC typeEnvWF.ordered + (relation.defeqCtx.symm typeEnvWF.ordered) + have rawConsumed := rawConsumedAtFull.of_l typeEnvWF fullWF.toCtx + rawTypeAtFull + have analyzerConsumed := analyzerView.trans + ((rawViewAtFull.of_l typeEnvWF fullWF.toCtx rawTypeAtFull).symm.trans + rawConsumed) + exact ⟨analyzerView.hasType.1, analyzerConsumed⟩ + +structure AnalyzerPostContextState + (typeEnv : VEnv) (Us : List Name) + (full postActual postView : VLCtx) (viewLift : Lift) where + fullWF : VLCtx.WF typeEnv Us.length full + postWF : VLCtx.WF typeEnv Us.length postActual + viewWF : VLCtx.WF typeEnv Us.length postView + viewDefEq : VLCtx.IsDefEqFVars typeEnv Us.length postActual postView + viewExtension : VLCtx.FVLift' full postView 0 viewLift 0 + +def vlctxCons + (entry : Option (FVarId × List FVarId) × VLocalDecl) + (tail : VLCtx) : VLCtx := + entry :: tail + +theorem VLCtx.IsDefEqFVars.fvars + (relation : VLCtx.IsDefEqFVars env U left right) : + left.fvars = right.fvars := by + induction relation with + | nil => rfl + | cons_bvar relation declaration ih => + change _ = _ + exact ih + | cons_fvar relation declaration ih => + change _ :: _ = _ :: _ + exact congrArg (fun tail => _ :: tail) ih + +theorem VLCtx.IsDefEqFVars.mono + (add : env ≤ env') : + VLCtx.IsDefEqFVars env U left right → + VLCtx.IsDefEqFVars env' U left right := by + intro relation + induction relation with + | nil => exact .nil + | cons_bvar relation declaration ih => + exact .cons_bvar ih (declaration.mono add) + | cons_fvar relation declaration ih => + exact .cons_fvar ih (declaration.mono add) + +theorem VLCtx.IsDefEqFVars.symm + (henv : VEnv.Ordered env) : + VLCtx.IsDefEqFVars env U left right → + VLCtx.IsDefEqFVars env U right left := by + intro relation + induction relation with + | nil => exact .nil + | cons_bvar relation declaration ih => + exact .cons_bvar ih + (declaration.symm.defeqDFC henv relation.defeqCtx) + | cons_fvar relation declaration ih => + exact .cons_fvar ih + (declaration.symm.defeqDFC henv relation.defeqCtx) + +def FullFreshInvariant (context : AddInductive.Context) + (common full : VLCtx) : Prop := + ∀ fv ∈ full.fvars, + fv ∈ common.fvars ∨ context.ngen.Reserves fv + +theorem FullFreshInvariant.fresh + (invariant : FullFreshInvariant context common full) + (freshCommon : context.freshFVarId ∉ common.fvars) : + context.freshFVarId ∉ full.fvars := by + intro present + rcases invariant context.freshFVarId present with common | reserved + · exact freshCommon common + · exact NameGenerator.not_reserves_self reserved + +theorem FullFreshInvariant.push + (invariant : FullFreshInvariant context common full) + {commonDomain fullDomain : VLocalDecl} + {commonDeps fullDeps : List FVarId} : + FullFreshInvariant + (context.pushLocalDecl name binderInfo sourceDomain) + (vlctxCons + (some (context.freshFVarId, commonDeps), commonDomain) common) + (vlctxCons + (some (context.freshFVarId, fullDeps), fullDomain) full) := by + intro fv present + simp only [vlctxCons, VLCtx.fvars_cons_some, List.mem_cons] at present + rcases present with rfl | present + · exact .inl (by simp [vlctxCons]) + · rcases invariant fv present with commonMem | reserved + · exact .inl (by + simp only [vlctxCons, VLCtx.fvars_cons_some, List.mem_cons] + exact .inr commonMem) + · exact .inr (reserved.mono NameGenerator.LE.next) + +theorem FullFreshInvariant.skip + (invariant : FullFreshInvariant context common full) + {fullDomain : VLocalDecl} {fullDeps : List FVarId} : + FullFreshInvariant context.advanceFresh common + (vlctxCons + (some (context.freshFVarId, fullDeps), fullDomain) full) := by + intro fv present + simp only [vlctxCons, VLCtx.fvars_cons_some, List.mem_cons] at present + rcases present with rfl | present + · exact .inr NameGenerator.next_reserves_self + · rcases invariant fv present with common | reserved + · exact .inl common + · exact .inr (reserved.mono NameGenerator.LE.next) + +structure D3FullContextState + (env typeEnv : VEnv) (Us : List Name) + (context : AddInductive.Context) + (common full actual view : VLCtx) (fullLift viewLift : Lift) where + commonWF : VLCtx.WF env Us.length common + commonNoBV : common.NoBV + fullWF : VLCtx.WF typeEnv Us.length full + fullExtension : VLCtx.FVLift' common full 0 fullLift 0 + actualWF : VLCtx.WF env Us.length actual + viewDefEq : VLCtx.IsDefEq env Us.length actual view + viewUnique : TrExprS.IsUniqueCtx actual view + viewExtension : VLCtx.FVLift' common view 0 viewLift 0 + freshInvariant : FullFreshInvariant context common full + +/-- Push one family-free D3 binder through both the analyzer's full context +and D3's index-extended context. -/ +theorem D3FullContextState.push + {env typeEnv : VEnv} {Us : List Name} + {context : AddInductive.Context} + {common full actual view : VLCtx} {fullLift viewLift : Lift} + (state : D3FullContextState env typeEnv Us context + common full actual view fullLift viewLift) + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + {source : Expr} + {fullTarget actualSource actualConsumed : VExpr} + {fieldLevel consumedLevel : VLevel} + (sourceUnique : TrExprS.IsUnique source) + (sourceClosed : Closed source) + (sourceFVars : FVarsIn (· ∈ common.fvars) source) + (fullTr : TrExprS typeEnv Us full source fullTarget) + (actualTr : TrExprS env Us actual source actualSource) + (actualType : env.HasType Us.length actual.toCtx actualSource + (.sort fieldLevel)) + (actualAnnotations : env.IsDefEqU Us.length actual.toCtx + actualSource actualConsumed) + (actualConsumedType : env.HasType Us.length actual.toCtx actualConsumed + (.sort consumedLevel)) + (actualTailWF : VLCtx.WF env Us.length + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam actualConsumed) actual)) : + ∃ commonTarget, + TrExprS typeEnv Us common source commonTarget ∧ + fullTarget = commonTarget.lift' fullLift ∧ + env.HasType Us.length common.toCtx commonTarget (.sort fieldLevel) ∧ + D3FullContextState env typeEnv Us + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations source)) + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam commonTarget) common) + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam fullTarget) full) + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam actualConsumed) actual) + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam (commonTarget.lift' viewLift)) view) + (.consN fullLift 1) (.consN viewLift 1) := by + obtain ⟨commonTarget, commonTr, fullEq, commonType⟩ := + ensureTypeRun_commonType henv typeEnvWF addType state.commonWF + state.fullWF state.fullExtension state.viewDefEq state.viewUnique + state.viewExtension sourceUnique sourceClosed sourceFVars fullTr + actualTr actualType + have viewWF : VLCtx.WF env Us.length view := + (state.viewDefEq.symm henv.ordered).wf + have commonAtView : TrExprS typeEnv Us view source + (commonTarget.lift' viewLift) := + commonTr.weakFV' typeEnvWF.ordered state.viewExtension + (viewWF.mono addType) + have actualSource_eq : actualSource = commonTarget.lift' viewLift := + (actualTr.mono addType).unique' state.viewUnique sourceUnique commonAtView + have consumedToCommon : env.IsDefEq Us.length actual.toCtx + actualConsumed (commonTarget.lift' viewLift) + (.sort consumedLevel) := by + rw [← actualSource_eq] + exact (actualAnnotations.of_r henv state.actualWF.toCtx + actualConsumedType).symm + have depsSubset : (consumeTypeAnnotations source).fvarsList ⊆ + common.fvars := + (FVarsIn.consumeTypeAnnotations sourceFVars |> fvarsIn_iff.mp).1 + have freshCommon : context.freshFVarId ∉ common.fvars := by + intro present + have presentView := state.viewExtension.fvars_sublist.subset present + have presentActual : context.freshFVarId ∈ actual.fvars := by + simpa only [state.viewDefEq.fvars] using presentView + exact (actualTailWF.2.1 _ _ rfl).1 presentActual + have freshFull := state.freshInvariant.fresh freshCommon + have commonTailWF : VLCtx.WF env Us.length + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam commonTarget) common) := by + refine ⟨state.commonWF, ?_, ⟨fieldLevel, commonType⟩⟩ + intro fv deps equality + cases equality + exact ⟨freshCommon, depsSubset⟩ + have fullType : typeEnv.HasType Us.length full.toCtx fullTarget + (.sort fieldLevel) := by + rw [fullEq] + exact (commonType.weak' henv.ordered state.fullExtension.toCtx).mono addType + have fullTailWF : VLCtx.WF typeEnv Us.length + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam fullTarget) full) := by + refine ⟨state.fullWF, ?_, ⟨fieldLevel, fullType⟩⟩ + intro fv deps equality + cases equality + exact ⟨freshFull, fun fv member => + state.fullExtension.fvars_sublist.subset (depsSubset member)⟩ + have nextViewDefEq : VLCtx.IsDefEq env Us.length + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam actualConsumed) actual) + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam (commonTarget.lift' viewLift)) view) := by + exact .cons state.viewDefEq actualTailWF.2.1 + (.vlam consumedToCommon) + refine ⟨commonTarget, commonTr, fullEq, commonType, { + commonWF := commonTailWF + commonNoBV := by + simpa only [vlctxCons, VLCtx.NoBV, VLCtx.bvars] using + state.commonNoBV + fullWF := fullTailWF + fullExtension := ?_ + actualWF := actualTailWF + viewDefEq := nextViewDefEq + viewUnique := state.viewUnique.cons .vlam + viewExtension := state.viewExtension.cons_fvar + (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList) + (.vlam commonTarget) depsSubset + freshInvariant := state.freshInvariant.push }⟩ + simpa only [fullEq, vlctxCons, VLocalDecl.lift', + VLocalDecl.depth] using state.fullExtension.cons_fvar + (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList) + (.vlam commonTarget) depsSubset + +/-- Skip one family-dependent outer field in D3's family-free replay while +retaining that exact analyzer field in the full context. -/ +theorem D3FullContextState.skip + {env typeEnv : VEnv} {Us : List Name} + {context : AddInductive.Context} + {common full actual view : VLCtx} {fullLift viewLift : Lift} + (state : D3FullContextState env typeEnv Us context + common full actual view fullLift viewLift) + {source : Expr} {field : VExpr} + (nextFullWF : VLCtx.WF typeEnv Us.length + ((some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam field) :: full)) : + D3FullContextState env typeEnv Us context.advanceFresh common + ((some (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList), + .vlam field) :: full) + actual view (.skipN fullLift 1) viewLift where + commonWF := state.commonWF + commonNoBV := state.commonNoBV + fullWF := nextFullWF + fullExtension := by + simpa only [VLocalDecl.depth] using state.fullExtension.skip_fvar + (context.freshFVarId, + (consumeTypeAnnotations source).fvarsList) (.vlam field) + actualWF := state.actualWF + viewDefEq := state.viewDefEq + viewUnique := state.viewUnique + viewExtension := state.viewExtension + freshInvariant := state.freshInvariant.skip + +/-- Exact analyzer syntax and pre-family semantic evidence for one recursive +field. The family telescope is tracked at the analyzer's current full +context; nested binders lift it in the ordinary de Bruijn way. -/ +def RecursiveFieldRunResult + (env : VEnv) (Us : List Name) (full : VLCtx) + (familyTarget fieldTarget : VExpr) (level : VLevel) + (familyName : Name) (parameterCount : Nat) : Prop := + ∃ binders indices terminal, + fieldTarget = VExpr.forallN binders terminal ∧ + env.OnTel Us.length full.toCtx binders ∧ + env.SpineWF Us.length + (binders.reverse ++ full.toCtx) + (familyTarget.liftN binders.length 0) indices (.sort level) ∧ + (∃ levels, VExpr.appHead terminal = .const familyName levels) ∧ + (VExpr.appArgs terminal []).drop parameterCount = indices + +/-- Synchronize the recursive D3 replay with the analyzer's exact strict +translation. D3 supplies all family-free typing and the terminal index +spine; strict translation uniqueness fixes the analyzer-owned domains and +terminal arguments componentwise. -/ +theorem recursiveField_exactAnalyzer + {env typeEnv : VEnv} {Us : List Name} + {stats : AddInductive.InductiveStats} {familyIdx : Nat} + {familyIndices : Expr} {context : AddInductive.Context} + {contextRun : AddInductive.ConstructorContextRun env Us context} + {source : Expr} {fuel : Nat} + {trace : AddInductive.ConstructorPreFamilyRecursiveTrace stats familyIdx + familyIndices context source fuel} + (run : AddInductive.ConstructorPreFamilyRecursiveSemanticRun env Us stats + familyIdx familyIndices contextRun trace) + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + {common full view : VLCtx} {fullLift viewLift : Lift} + (state : D3FullContextState env typeEnv Us context common full + contextRun.candidate.context.vlctx view fullLift viewLift) + {commonIndices : List VExpr} {familyTarget fieldTarget : VExpr} + {level : VLevel} {familyName : Name} {familyLevels : List Level} + (familyCommonTr : TrExprS env Us common familyIndices + (VExpr.forallN commonIndices (.sort level))) + (familyFullTr : TrExprS typeEnv Us full familyIndices familyTarget) + (familyUnique : TrExprS.IsUnique familyIndices) + (indexLength : commonIndices.length = stats.nindices[familyIdx]!) + (familyHead : stats.indConsts[familyIdx]! = + .const familyName familyLevels) + (sourceUnique : TrExprS.IsUnique source) + (sourceClosed : Closed source) + (sourceFVars : FVarsIn (· ∈ common.fvars) source) + (fullTr : TrExprS typeEnv Us full source fieldTarget) : + RecursiveFieldRunResult env Us full familyTarget fieldTarget level + familyName stats.params.size := by + induction run generalizing common full view fullLift viewLift commonIndices + familyTarget fieldTarget with + | @target _ context source fuel valid spineTrace branchContextRun expected' + spine => + have argumentClosed : ∀ argument ∈ + source.getAppArgs.toList.drop stats.params.size, + Closed argument := by + intro argument member + apply Closed.getAppArgsList sourceClosed + rw [← Expr.getAppArgs_toList] + exact List.mem_of_mem_drop member + have argumentFVars : ∀ argument ∈ + source.getAppArgs.toList.drop stats.params.size, + FVarsIn (· ∈ common.fvars) argument := by + intro argument member + apply FVarsIn.getAppArgsList sourceFVars + rw [← Expr.getAppArgs_toList] + exact List.mem_of_mem_drop member + have argumentUnique : ∀ argument ∈ + source.getAppArgs.toList.drop stats.params.size, + TrExprS.IsUnique argument := by + intro argument member + apply TrExprS.IsUnique.getAppArgsList sourceUnique + rw [← Expr.getAppArgs_toList] + exact List.mem_of_mem_drop member + have argumentLength : + (source.getAppArgs.toList.drop stats.params.size).length = + commonIndices.length := + (isValidIndAppIdx_indexArgs_length valid).trans + indexLength.symm + obtain ⟨baseIndices, baseIndicesTr, baseSpine⟩ := + ConstructorPreFamilyIndexSpineSemanticRun.baseSpine_lift spine + familyCommonTr familyUnique + state.viewDefEq state.viewUnique state.viewExtension + argumentClosed argumentFVars argumentUnique argumentLength + have commonFamilyAtFull : TrExprS typeEnv Us full familyIndices + ((VExpr.forallN commonIndices (.sort level)).lift' fullLift) := by + simpa using (familyCommonTr.mono addType).weakFV' + typeEnvWF.ordered state.fullExtension state.fullWF + have familyEq : familyTarget = + (VExpr.forallN commonIndices (.sort level)).lift' fullLift := + familyFullTr.unique familyUnique commonFamilyAtFull + have shape := isValidIndAppIdx_shape valid + have sourceHead : source.getAppFn = + .const familyName familyLevels := by + rw [familyHead] at shape + change source.getAppFn.eqv (.const familyName familyLevels) = true ∧ + _ at shape + rw [Expr.eqv_eq] at shape + generalize headEq : source.getAppFn = head at shape + cases head <;> simp_all [Expr.eqv'] + obtain ⟨targetLevels, targetHead, allArgumentsTr⟩ := + TrExprS.constApp_components fullTr sourceHead + have droppedArgumentsTr := + forall₂_drop allArgumentsTr stats.params.size + have baseIndicesAtFull : List.Forall₂ + (TrExprS typeEnv Us full) + (source.getAppArgsList.drop stats.params.size) + (baseIndices.map fun index => index.lift' fullLift) := by + have baseMono := forall₂_tr_mono addType baseIndicesTr + have baseWeak := forall₂_tr_weakFV' typeEnvWF.ordered + state.fullExtension state.fullWF baseMono + simpa only [Expr.getAppArgs_toList] using baseWeak + have translatedIndicesEq : + (VExpr.appArgs fieldTarget []).drop stats.params.size = + baseIndices.map fun index => index.lift' fullLift := + forall₂_translation_unique droppedArgumentsTr + baseIndicesAtFull (fun argument member => + TrExprS.IsUnique.getAppArgsList sourceUnique argument + (List.mem_of_mem_drop member)) + have fullSpine : env.SpineWF Us.length full.toCtx + ((VExpr.forallN commonIndices (.sort level)).lift' fullLift) + (baseIndices.map fun index => index.lift' fullLift) + (.sort level) := by + simpa using VEnv.SpineWF.weak' henv.ordered + state.fullExtension.toCtx baseSpine + rw [← familyEq, ← translatedIndicesEq] at fullSpine + exact ⟨[], (VExpr.appArgs fieldTarget []).drop stats.params.size, + fieldTarget, rfl, trivial, by simpa using fullSpine, + ⟨targetLevels, targetHead⟩, rfl⟩ + | @forallE context name domain body binderInfo fuel domainCheck ensureType + consumedCheck annotations fresh tailTrace branchContextRun domainRun + consumedRun ensureTypeRun annotationsRun consumedType tail ih => + obtain ⟨fullDomain, fullBody, rfl, fullDomainType, fullBodyType, + domainTr, bodyTr⟩ := TrExprS.forallE_components fullTr + have actualDomainTr : TrExprS env Us + branchContextRun.candidate.context.vlctx domain + domainRun.source' := by + simpa only [branchContextRun.venv_eq, + branchContextRun.lparams_eq] using domainRun.check.expr_tr + have actualDomainType : env.HasType Us.length + branchContextRun.candidate.context.vlctx.toCtx domainRun.source' + (.sort ensureTypeRun.resultLevel') := by + simpa only [branchContextRun.venv_eq, + branchContextRun.lparams_eq] using ensureTypeRun.source_type + have actualAnnotations : env.IsDefEqU Us.length + branchContextRun.candidate.context.vlctx.toCtx domainRun.source' + consumedRun.source' := by + simpa only [branchContextRun.venv_eq, + branchContextRun.lparams_eq] using annotationsRun.isDefEqU + have consumedTypeCopy := consumedType + obtain ⟨consumedLevel, consumedHasType⟩ := consumedType + have actualConsumedType : env.HasType Us.length + branchContextRun.candidate.context.vlctx.toCtx consumedRun.source' + (.sort consumedLevel) := by + simpa only [branchContextRun.venv_eq, + branchContextRun.lparams_eq] using consumedHasType + let nextContextRun := branchContextRun.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain) fresh consumedRun.source' + consumedRun.check.expr_tr consumedTypeCopy + have actualTailWF : VLCtx.WF env Us.length + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam consumedRun.source') + branchContextRun.candidate.context.vlctx) := by + have nextWF := nextContextRun.candidate.context.Δwf + rw [nextContextRun.venv_eq, nextContextRun.lparams_eq] at nextWF + simpa only [vlctxCons, nextContextRun, + AddInductive.ConstructorContextRun.pushLocalDecl, + CandidateContextRun.pushLocalDecl_vlctx] using nextWF + obtain ⟨commonDomain, commonDomainTr, fullDomainEq, + commonDomainType, nextState⟩ := + state.push henv typeEnvWF addType sourceUnique.1 sourceClosed.1 + sourceFVars.1 domainTr actualDomainTr actualDomainType + actualAnnotations actualConsumedType actualTailWF + have bodyOpened : TrExprS typeEnv Us + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam fullDomain) full) + (body.instantiate1 context.freshExpr) fullBody := by + simpa only [vlctxCons, AddInductive.Context.freshExpr, + Expr.instantiate1_eq] using + bodyTr.inst_fvar typeEnvWF.ordered nextState.fullWF + have familyCommonNext : TrExprS env Us + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam commonDomain) common) + familyIndices + (VExpr.forallN (VExpr.liftTelN 1 commonIndices 0) + (.sort level)) := by + have weakened := familyCommonTr.weakFV henv.ordered + (VLCtx.FVLift.skip_fvar + (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList) + (.vlam commonDomain) .refl) + nextState.commonWF + simpa [vlctxCons, VLocalDecl.depth, + VExpr.liftN_forallN, VExpr.liftN] using weakened + have familyFullNext : TrExprS typeEnv Us + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam fullDomain) full) + familyIndices (familyTarget.liftN 1 0) := by + have weakened := familyFullTr.weakFV typeEnvWF.ordered + (VLCtx.FVLift.skip_fvar + (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList) + (.vlam fullDomain) .refl) + nextState.fullWF + simpa [vlctxCons, VLocalDecl.depth] using weakened + have nextIndexLength : + (VExpr.liftTelN 1 commonIndices 0).length = + stats.nindices[familyIdx]! := by + simpa only [VExpr.liftTelN_length] using indexLength + have tailUnique : TrExprS.IsUnique + (body.instantiate1 context.freshExpr) := by + apply TrExprS.IsUnique.instantiate1 sourceUnique.2 + simp only [AddInductive.Context.freshExpr] + trivial + have nextFullNoBV : + (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam fullDomain) full).bvars = 0 := + nextState.fullExtension.bvars_eq.trans nextState.commonNoBV + have tailClosed : Closed (body.instantiate1 context.freshExpr) := by + have closed := bodyOpened.closed + rw [nextFullNoBV] at closed + exact closed + have tailFVars : FVarsIn + (· ∈ (vlctxCons + (some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam commonDomain) common).fvars) + (body.instantiate1 context.freshExpr) := by + rw [Expr.instantiate1_eq] + apply FVarsIn.instantiate1 + · exact sourceFVars.2.mono (fun fv member => by + simp only [vlctxCons, VLCtx.fvars_cons_some, + List.mem_cons] + exact .inr member) + · simp [AddInductive.Context.freshExpr, vlctxCons, FVarsIn] + obtain ⟨tailBinders, indices, terminal, tailTargetEq, tailOnTel, + tailSpine, terminalHead, terminalIndices⟩ := + ih nextState familyCommonNext familyFullNext nextIndexLength + tailUnique tailClosed tailFVars bodyOpened + refine ⟨fullDomain :: tailBinders, indices, terminal, ?_, ?_, ?_, + terminalHead, terminalIndices⟩ + · simp only [VExpr.forallN, VExpr.forallE.injEq, true_and] + exact tailTargetEq + · exact ⟨by + rw [fullDomainEq] + exact ⟨ensureTypeRun.resultLevel', by + simpa using commonDomainType.weak' henv.ordered + state.fullExtension.toCtx⟩, + by + simpa only [vlctxCons, VLCtx.toCtx] using tailOnTel⟩ + · simpa only [List.reverse_cons, List.singleton_append, + List.append_assoc, vlctxCons, VLCtx.toCtx, + List.length_cons, VExpr.liftN_liftN, Nat.add_comm] using tailSpine + +private theorem forallN_inj_of_terminal_ne_forall + (leftNot : ∀ domain body, leftTerminal ≠ .forallE domain body) + (rightNot : ∀ domain body, rightTerminal ≠ .forallE domain body) + (equality : VExpr.forallN leftBinders leftTerminal = + VExpr.forallN rightBinders rightTerminal) : + leftBinders = rightBinders ∧ leftTerminal = rightTerminal := by + induction leftBinders generalizing rightBinders with + | nil => + cases rightBinders with + | nil => exact ⟨rfl, equality⟩ + | cons domain binders => + exact (leftNot domain (VExpr.forallN binders rightTerminal) + equality).elim + | cons domain binders ih => + cases rightBinders with + | nil => + exact (rightNot domain (VExpr.forallN binders leftTerminal) + equality.symm).elim + | cons rightDomain rightBinders => + simp only [VExpr.forallN, VExpr.forallE.injEq] at equality + obtain ⟨domainEq, tailEq⟩ := equality + obtain ⟨bindersEq, terminalEq⟩ := + ih tailEq + cases domainEq + cases bindersEq + exact ⟨rfl, terminalEq⟩ + +private theorem terminal_ne_forall_of_appHead_const + (head : VExpr.appHead terminal = .const familyName levels) : + ∀ domain body, terminal ≠ .forallE domain body := by + intro domain body equality + subst terminal + simp only [VExpr.appHead] at head + exact VExpr.noConfusion head + +private theorem hasConst_of_appHead_const + (head : VExpr.appHead terminal = .const familyName levels) : + terminal.hasConst familyName = true := by + induction terminal with + | app function argument functionIH argumentIH => + simp only [VExpr.appHead] at head + simp only [VExpr.hasConst, Bool.or_eq_true] + exact .inl (functionIH head) + | const name levels => + simp only [VExpr.appHead, VExpr.const.injEq] at head + exact (beq_iff_eq).2 head.1 + | bvar | sort | lam | forallE => simp [VExpr.appHead] at head + +private theorem forallN_hasConst_of_terminal + (terminalHasConst : terminal.hasConst familyName = true) : + (VExpr.forallN binders terminal).hasConst familyName = true := by + induction binders with + | nil => exact terminalHasConst + | cons binder binders ih => + simp only [VExpr.forallN, VExpr.hasConst, Bool.or_eq_true] + exact .inr ih + +theorem recArg?_eq_none_of_hasConst_false + (free : field.hasConst familyName = false) : + VInductDecl.recArg? U familyName np ni fieldIndex field = none := by + cases recursiveEq : VInductDecl.recArg? U familyName np ni fieldIndex field with + | none => rfl + | some recursive => + have anatomy := VInductDecl.recArg?_eq recursiveEq + have terminalHead : + VExpr.appHead + (VExpr.appN (.const familyName (VLevel.params U)) + (VExpr.bvarRevRange + (fieldIndex + recursive.binders.length) np ++ + recursive.indices)) = + .const familyName (VLevel.params U) := + VExpr.appHead_appN _ _ + have terminalHasConst := + hasConst_of_appHead_const terminalHead + have recursiveHasConst := + forallN_hasConst_of_terminal + (binders := recursive.binders) terminalHasConst + rw [← anatomy.2.2.1, free] at recursiveHasConst + contradiction + +private theorem drop_bvarRevRange_append + (offset count : Nat) (suffix : List VExpr) : + (VExpr.bvarRevRange offset count ++ suffix).drop count = suffix := by + induction count with + | zero => rfl + | succ count ih => + simp only [VExpr.bvarRevRange, List.cons_append, List.drop_succ_cons] + exact ih + +/-- A recursive-field synchronization certificate is exactly the semantic +payload required by the analyzer's `RecArg` descriptor. -/ +theorem recursiveFieldResult_recArgWF + {env : VEnv} {Us : List Name} {full : VLCtx} + {familyTarget fieldTarget : VExpr} {level : VLevel} + {familyName : Name} {np ni fieldIndex : Nat} + {familyIndices : List VExpr} + (result : RecursiveFieldRunResult env Us full familyTarget + fieldTarget level familyName np) + (familyTargetEq : familyTarget = + VExpr.forallN (VExpr.liftTelN fieldIndex familyIndices 0) + (.sort level)) + (stage : VInductDecl.stage3Field Us.length familyName np ni fieldIndex + fieldTarget = true) : + ∃ recursive, + VInductDecl.recArg? Us.length familyName np ni fieldIndex fieldTarget = + some recursive ∧ + recursive.WF Us.length env level familyIndices full.toCtx := by + obtain ⟨binders, indices, terminal, targetEq, onTel, spine, + ⟨terminalLevels, terminalHead⟩, terminalIndices⟩ := result + have terminalHasConst : terminal.hasConst familyName = true := + hasConst_of_appHead_const terminalHead + have fieldHasConst : fieldTarget.hasConst familyName = true := by + rw [targetEq] + exact forallN_hasConst_of_terminal terminalHasConst + have recursiveSome : + (VInductDecl.recArg? Us.length familyName np ni fieldIndex + fieldTarget).isSome = true := by + simpa only [VInductDecl.stage3Field, fieldHasConst, Bool.not_true, + Bool.or_false] using stage + cases recursiveEq : VInductDecl.recArg? Us.length familyName np ni + fieldIndex fieldTarget with + | none => simp [recursiveEq] at recursiveSome + | some recursive => + have anatomy := VInductDecl.recArg?_eq recursiveEq + let recursiveTerminal := VExpr.appN + (.const familyName (VLevel.params Us.length)) + (VExpr.bvarRevRange (fieldIndex + recursive.binders.length) np ++ + recursive.indices) + have telescopesEq : VExpr.forallN binders terminal = + VExpr.forallN recursive.binders recursiveTerminal := by + exact targetEq.symm.trans anatomy.2.2.1 + have recursiveTerminalHead : + VExpr.appHead recursiveTerminal = + .const familyName (VLevel.params Us.length) := by + exact VExpr.appHead_appN _ _ + obtain ⟨bindersEq, terminalEq⟩ := + forallN_inj_of_terminal_ne_forall + (terminal_ne_forall_of_appHead_const terminalHead) + (terminal_ne_forall_of_appHead_const recursiveTerminalHead) + telescopesEq + have indicesEq : indices = recursive.indices := by + rw [terminalEq, VExpr.appArgs_appN] at terminalIndices + simp only [VExpr.appArgs, List.append_nil] at terminalIndices + rw [drop_bvarRevRange_append] at terminalIndices + exact terminalIndices.symm + refine ⟨recursive, rfl, ?_⟩ + unfold VInductDecl.RecArg.WF + refine ⟨?_, ?_⟩ + · rw [← bindersEq] + exact onTel + · rw [anatomy.1, ← bindersEq, ← indicesEq] + rw [familyTargetEq, VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN] at spine + simpa [VExpr.liftN] using spine + +theorem AnalyzerPostContextState.push + {typeEnv : VEnv} {Us : List Name} + {full postActual postViewContext : VLCtx} {viewLift : Lift} + (state : AnalyzerPostContextState typeEnv Us full postActual + postViewContext viewLift) + (typeEnvWF : VEnv.WF typeEnv) + {source : Expr} {analyzer postRaw postView postConsumed : VExpr} + {rawLevel : VLevel} {fv : FVarId} {postDeps : List FVarId} + (_sourceUnique : TrExprS.IsUnique source) + (_sourceClosed : Closed source) + (analyzerTr : TrExprS typeEnv Us full source analyzer) + (postViewTr : TrExprS typeEnv Us postActual source postView) + (postRawType : typeEnv.HasType Us.length postActual.toCtx postRaw + (.sort rawLevel)) + (postRawView : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw postView) + (postAnnotations : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw postConsumed) + (postTailWF : VLCtx.WF typeEnv Us.length + ((some (fv, postDeps), .vlam postConsumed) :: postActual)) : + let deps := (AddInductive.consumeTypeAnnotations source).fvarsList + typeEnv.HasType Us.length full.toCtx analyzer (.sort rawLevel) ∧ + AnalyzerPostContextState typeEnv Us + ((some (fv, deps), .vlam analyzer) :: full) + ((some (fv, postDeps), .vlam postConsumed) :: postActual) + ((some (fv, deps), .vlam (analyzer.lift' viewLift)) :: + postViewContext) + (.consN viewLift 1) := by + dsimp only + have postViewType : typeEnv.HasType Us.length postActual.toCtx postView + (.sort rawLevel) := + postRawType.defeqU_l typeEnvWF state.postWF.toCtx postRawView + have postViewContextWF : VLCtx.WF typeEnv Us.length postViewContext := + state.viewWF + have analyzerAtView : TrExprS typeEnv Us postViewContext source + (analyzer.lift' viewLift) := + analyzerTr.weakFV' typeEnvWF.ordered state.viewExtension + postViewContextWF + have postViewAnalyzer : typeEnv.IsDefEqU Us.length postActual.toCtx + postView (analyzer.lift' viewLift) := + postViewTr.uniqFVars typeEnvWF state.viewDefEq state.postWF + analyzerAtView + have analyzerAtPostType : typeEnv.HasType Us.length postActual.toCtx + (analyzer.lift' viewLift) (.sort rawLevel) := + (postViewAnalyzer.of_l typeEnvWF state.postWF.toCtx postViewType).hasType.2 + have analyzerAtViewType : typeEnv.HasType Us.length postViewContext.toCtx + (analyzer.lift' viewLift) (.sort rawLevel) := + analyzerAtPostType.defeqDFC typeEnvWF.ordered + state.viewDefEq.defeqCtx + have analyzerType : typeEnv.HasType Us.length full.toCtx analyzer + (.sort rawLevel) := + (HasType.weak'_iff typeEnvWF postViewContextWF.toCtx + state.viewExtension.toCtx).1 (by simpa using analyzerAtViewType) + have rawView := postRawView.of_l typeEnvWF state.postWF.toCtx postRawType + have rawConsumed := + postAnnotations.of_l typeEnvWF state.postWF.toCtx postRawType + have analyzerConsumed : typeEnv.IsDefEq Us.length postActual.toCtx + postConsumed (analyzer.lift' viewLift) (.sort rawLevel) := + (rawConsumed.symm.trans rawView).trans + (postViewAnalyzer.of_l typeEnvWF state.postWF.toCtx postViewType) + have depsSubset : (AddInductive.consumeTypeAnnotations source).fvarsList ⊆ + full.fvars := + (FVarsIn.consumeTypeAnnotations analyzerTr.fvarsIn + |> fvarsIn_iff.mp).1 + have freshFull : fv ∉ full.fvars := by + intro present + have presentView := state.viewExtension.fvars_sublist.subset present + have presentPost : fv ∈ postActual.fvars := by + simpa only [ConstructorValidation.VLCtx.IsDefEqFVars.fvars state.viewDefEq] + using presentView + exact (postTailWF.2.1 fv postDeps rfl).1 presentPost + have freshView : fv ∉ postViewContext.fvars := by + intro present + have presentPost : fv ∈ postActual.fvars := by + simpa only [ConstructorValidation.VLCtx.IsDefEqFVars.fvars state.viewDefEq] + using present + exact (postTailWF.2.1 fv postDeps rfl).1 presentPost + have depsSubsetView : + (AddInductive.consumeTypeAnnotations source).fvarsList ⊆ + postViewContext.fvars := fun _ member => + state.viewExtension.fvars_sublist.subset (depsSubset member) + have fullTailWF : VLCtx.WF typeEnv Us.length + ((some (fv, (AddInductive.consumeTypeAnnotations source).fvarsList), + .vlam analyzer) :: full) := + ⟨state.fullWF, + fun _ _ equality => by + cases equality + exact ⟨freshFull, depsSubset⟩, + ⟨rawLevel, analyzerType⟩⟩ + have viewTailWF : VLCtx.WF typeEnv Us.length + ((some (fv, (AddInductive.consumeTypeAnnotations source).fvarsList), + .vlam (analyzer.lift' viewLift)) :: postViewContext) := + ⟨state.viewWF, + fun _ _ equality => by + cases equality + exact ⟨freshView, depsSubsetView⟩, + ⟨rawLevel, analyzerAtViewType⟩⟩ + exact ⟨analyzerType, { + fullWF := fullTailWF + postWF := postTailWF + viewWF := viewTailWF + viewDefEq := .cons_fvar state.viewDefEq (.vlam analyzerConsumed) + viewExtension := state.viewExtension.cons_fvar + (fv, (AddInductive.consumeTypeAnnotations source).fvarsList) + (.vlam analyzer) depsSubset }⟩ + +theorem ordinaryField_baseTypes + {env typeEnv : VEnv} {Us : List Name} + {base actual view postActual : VLCtx} {source : Expr} + {source' actual' postRaw' postView' : VExpr} + {fieldLevel rawLevel resultLevel : VLevel} {n : Lift} + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + (baseWF : VLCtx.WF env Us.length base) + (actualWF : VLCtx.WF env Us.length actual) + (postWF : VLCtx.WF typeEnv Us.length postActual) + (postRelation : VLCtx.IsDefEqFVars typeEnv Us.length actual postActual) + (viewDefEq : VLCtx.IsDefEq env Us.length actual view) + (viewUnique : TrExprS.IsUniqueCtx actual view) + (viewLift : VLCtx.FVLift' base view 0 n 0) + (sourceUnique : TrExprS.IsUnique source) + (sourceClosed : Closed source) + (sourceFVars : FVarsIn (· ∈ base.fvars) source) + (sourceTr : TrExprS typeEnv Us base source source') + (actualTr : TrExprS env Us actual source actual') + (actualType : env.HasType Us.length actual.toCtx actual' + (.sort fieldLevel)) + (postViewTr : TrExprS typeEnv Us postActual source postView') + (postRawType : typeEnv.HasType Us.length postActual.toCtx postRaw' + (.sort rawLevel)) + (postRawView : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw' postView') + (rawBound : resultLevel = .zero ∨ rawLevel ≤ resultLevel) : + env.HasType Us.length base.toCtx source' (.sort fieldLevel) ∧ + fieldLevel ≈ rawLevel ∧ + (resultLevel = .zero ∨ fieldLevel ≤ resultLevel) := by + have baseField := ensureTypeRun_baseType henv + typeEnvWF.ordered addType baseWF viewDefEq viewUnique viewLift + sourceUnique sourceClosed sourceFVars sourceTr actualTr actualType + have postViewType : typeEnv.HasType Us.length postActual.toCtx postView' + (.sort rawLevel) := + postRawType.defeqU_l typeEnvWF postWF.toCtx postRawView + have postViewTypeAtActual : typeEnv.HasType Us.length actual.toCtx + postView' (.sort rawLevel) := + postViewType.defeqDFC typeEnvWF.ordered + (postRelation.defeqCtx.symm typeEnvWF.ordered) + have translatedDefEq : typeEnv.IsDefEqU Us.length actual.toCtx + actual' postView' := + (actualTr.mono addType).uniqFVars typeEnvWF postRelation + (actualWF.mono addType) postViewTr + have actualRawType : typeEnv.HasType Us.length actual.toCtx actual' + (.sort rawLevel) := + (translatedDefEq.of_r typeEnvWF (actualWF.mono addType).toCtx + postViewTypeAtActual).hasType.1 + have baseRaw := ensureTypeRun_baseType_mono typeEnvWF addType baseWF + viewDefEq viewUnique viewLift sourceUnique sourceClosed sourceFVars + sourceTr actualTr actualRawType + have levelEq : fieldLevel ≈ rawLevel := + (baseField.mono addType).uniqU typeEnvWF (baseWF.mono addType).toCtx + baseRaw |>.sort_inv typeEnvWF (baseWF.mono addType).toCtx + refine ⟨baseField, levelEq, ?_⟩ + rcases rawBound with prop | bound + · exact .inl prop + · exact .inr (VLevel.le_trans + (VLevel.le_antisymm_iff.mp levelEq).1 bound) + +theorem ordinaryConsumed_defeq + {env typeEnv : VEnv} {Us : List Name} + {actual postActual : VLCtx} {source _rawSource _rawConsumed _sourceConsumed : Expr} + {actualSource' actualConsumed' postRaw' postView' postConsumed' : VExpr} + (typeEnvWF : VEnv.WF typeEnv) (addType : env ≤ typeEnv) + (actualWF : VLCtx.WF env Us.length actual) + (relation : VLCtx.IsDefEqFVars typeEnv Us.length actual postActual) + (actualSourceTr : TrExprS env Us actual source actualSource') + (actualAnnotations : env.IsDefEqU Us.length actual.toCtx + actualSource' actualConsumed') + (actualConsumedType : env.IsType Us.length actual.toCtx actualConsumed') + (postViewTr : TrExprS typeEnv Us postActual source postView') + (postRawView : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw' postView') + (postAnnotations : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw' postConsumed') : + ∃ level, typeEnv.IsDefEq Us.length actual.toCtx + actualConsumed' postConsumed' (.sort level) := by + have actualWF' := actualWF.mono addType + have sourceEq : typeEnv.IsDefEqU Us.length actual.toCtx + actualSource' postView' := + (actualSourceTr.mono addType).uniqFVars typeEnvWF relation actualWF' + postViewTr + have postToActual := relation.defeqCtx.symm typeEnvWF.ordered + have rawView := postRawView.defeqDFC typeEnvWF.ordered postToActual + have rawConsumed := postAnnotations.defeqDFC typeEnvWF.ordered postToActual + have consumedEq := (actualAnnotations.mono addType).symm.trans typeEnvWF + actualWF'.toCtx (sourceEq.trans typeEnvWF actualWF'.toCtx + (rawView.symm.trans typeEnvWF actualWF'.toCtx rawConsumed)) + obtain ⟨level, consumedType⟩ := actualConsumedType + exact ⟨level, consumedEq.of_l typeEnvWF actualWF'.toCtx + (consumedType.mono addType)⟩ + +/-- The terminal kernel sort retained by a candidate recursion translates to +the exact terminal Theory sort exposed by its analyzer-owned view telescope. -/ +theorem CandidateExprRun.terminalLevel_tr + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {context : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace context source' view' inferred') + {resultLevel : Level} {resultLevel' : VLevel} {binders : List VExpr} + (terminal : trace.terminalResult = .sort resultLevel) + (viewEq : view' = VExpr.forallN binders (.sort resultLevel')) + (lengthEq : trace.spineLength = binders.length) : + VLevel.ofLevel Us resultLevel = some resultLevel' := by + induction run generalizing binders with + | terminal node => + simp only [AddInductive.CandidateExprTrace.spineLength] at lengthEq + have bindersEq : binders = [] := List.eq_nil_of_length_eq_zero + lengthEq.symm + subst binders + simp only [VExpr.forallN] at viewEq + simp only [AddInductive.CandidateExprTrace.terminalResult] at terminal + rw [terminal, viewEq] at node + cases node.whnf.rhs_tr with + | sort levelTr => exact levelTr + | @forallE domain candidateContext name binderInfo context source inferred + body source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyContext storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate bodyCandidate + node domainRun annotationsRun bodyRun domainType bodyType bodySource + bodyContextEq domainIH bodyIH => + simp only [AddInductive.CandidateExprTrace.spineLength] at lengthEq + cases binders with + | nil => simp at lengthEq + | cons binder binders => + simp only [VExpr.forallN, VExpr.forallE.injEq] at viewEq + obtain ⟨_, bodyViewEq⟩ := viewEq + apply bodyIH terminal bodyViewEq + simpa only [List.length_cons] using Nat.succ.inj lengthEq + +end ConstructorValidation + + +namespace ConstructorValidation +open AddInductive TypeChecker +-- `VEnv` here resolves to these two namespaces; `_root_.Ix.Theory.Named.VEnv` is +-- shadowed by the enclosing namespace, so name both explicitly. +open _root_.Ix.Theory.Named.ConstructorValidation.VEnv _root_.Ix.Theory.Named.TypeChecker.VEnv + +/-- Every full-context free variable not deliberately omitted by D3 is still +present in the family-free common context. -/ +def FullRemovedInvariant (common full : VLCtx) + (removed : List FVarId) : Prop := + ∀ fv, fv ∈ full.fvars → fv ∉ removed → fv ∈ common.fvars + +theorem FullRemovedInvariant.push + (invariant : FullRemovedInvariant common full removed) : + FullRemovedInvariant + ((some (fv, commonDeps), commonDomain) :: common) + ((some (fv, fullDeps), fullDomain) :: full) removed := by + intro candidate present notRemoved + simp only [VLCtx.fvars_cons_some, List.mem_cons] at present ⊢ + rcases present with rfl | present + · exact .inl rfl + · exact .inr (invariant candidate present notRemoved) + +theorem FullRemovedInvariant.skip + (invariant : FullRemovedInvariant common full removed) + (fresh : fv ∉ full.fvars) : + FullRemovedInvariant common + ((some (fv, fullDeps), fullDomain) :: full) (fv :: removed) := by + intro candidate present notRemoved + simp only [VLCtx.fvars_cons_some, List.mem_cons] at present + rcases present with rfl | present + · exact (notRemoved (by simp)).elim + · exact invariant candidate present (fun old => notRemoved (by simp [old])) + +theorem Context.freshFVarId_eq_of_ngen_eq + {left right : AddInductive.Context} + (equal : left.ngen = right.ngen) : + left.freshFVarId = right.freshFVarId := by + simp only [AddInductive.Context.freshFVarId, equal] + +theorem Context.push_advance_ngen_eq + {left right : AddInductive.Context} + (equal : left.ngen = right.ngen) : + (left.pushLocalDecl name binderInfo domain).ngen = + right.advanceFresh.ngen := by + simp only [AddInductive.Context.pushLocalDecl, + AddInductive.Context.advanceFresh, equal] + +theorem ordinaryConsumed_defeqAt + {env typeEnv : VEnv} {Us : List Name} + {actual postActual : VLCtx} {source : Expr} + {actualSource' actualConsumed' postRaw' postView' postConsumed' : VExpr} + {consumedLevel : VLevel} + (typeEnvWF : VEnv.WF typeEnv) (addType : env ≤ typeEnv) + (actualWF : VLCtx.WF env Us.length actual) + (relation : VLCtx.IsDefEqFVars typeEnv Us.length actual postActual) + (actualSourceTr : TrExprS env Us actual source actualSource') + (actualAnnotations : env.IsDefEqU Us.length actual.toCtx + actualSource' actualConsumed') + (actualConsumedType : env.HasType Us.length actual.toCtx actualConsumed' + (.sort consumedLevel)) + (postViewTr : TrExprS typeEnv Us postActual source postView') + (postRawView : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw' postView') + (postAnnotations : typeEnv.IsDefEqU Us.length postActual.toCtx + postRaw' postConsumed') : + typeEnv.IsDefEq Us.length actual.toCtx + actualConsumed' postConsumed' (.sort consumedLevel) := by + have actualWF' := actualWF.mono addType + have sourceEq : typeEnv.IsDefEqU Us.length actual.toCtx + actualSource' postView' := + (actualSourceTr.mono addType).uniqFVars typeEnvWF relation actualWF' + postViewTr + have postToActual := relation.defeqCtx.symm typeEnvWF.ordered + have rawView := postRawView.defeqDFC typeEnvWF.ordered postToActual + have rawConsumed := postAnnotations.defeqDFC typeEnvWF.ordered postToActual + have consumedEq := (actualAnnotations.mono addType).symm.trans typeEnvWF + actualWF'.toCtx (sourceEq.trans typeEnvWF actualWF'.toCtx + (rawView.symm.trans typeEnvWF actualWF'.toCtx rawConsumed)) + exact consumedEq.of_l typeEnvWF actualWF'.toCtx + (actualConsumedType.mono addType) + +theorem ConstructorUniverseTrace.bound + {stats : AddInductive.InductiveStats} + {sortResult : Expr} + (trace : AddInductive.ConstructorUniverseTrace stats.resultLevel + sortResult.sortLevel!) + (valid : trace.semantic = true) + (resultLevelTr : VLevel.ofLevel Us stats.resultLevel = some resultLevel) + (ensureTypeRun : TypeChecker.EnsureTypeRun typeEnv Us postContext + source sortResult source') : + resultLevel = .zero ∨ ensureTypeRun.resultLevel' ≤ resultLevel := by + apply AddInductive.constructorUniverseSemanticGe_ofLevel valid resultLevelTr + have sortLevelEq : sortResult.sortLevel! = ensureTypeRun.resultLevel := by + simpa only [Expr.sortLevel!] using + congrArg Expr.sortLevel! ensureTypeRun.result_eq + rw [sortLevelEq] + exact ensureTypeRun.resultLevel_tr + +/-- D3's terminal index replay transported to the analyzer's exact full +context and exact translated result target. -/ +theorem terminal_exactAnalyzer + {env typeEnv : VEnv} {Us : List Name} + {stats : AddInductive.InductiveStats} {familyIdx : Nat} + {familyIndices : Expr} {context : AddInductive.Context} + {contextRun : AddInductive.ConstructorContextRun env Us context} + {source : Expr} + {valid : AddInductive.isValidIndAppIdx stats source familyIdx = true} + {spineTrace : AddInductive.ConstructorPreFamilyIndexSpineTrace context + familyIndices (source.getAppArgs.toList.drop stats.params.size)} + {expected' : VExpr} + (spine : AddInductive.ConstructorPreFamilyIndexSpineSemanticRun env Us + context contextRun spineTrace expected') + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + {common full view : VLCtx} {fullLift viewLift : Lift} + (state : D3FullContextState env typeEnv Us context common full + contextRun.candidate.context.vlctx view fullLift viewLift) + {commonIndices : List VExpr} {familyTarget resultTarget : VExpr} + {level : VLevel} {familyName : Name} {familyLevels : List Level} + (familyCommonTr : TrExprS env Us common familyIndices + (VExpr.forallN commonIndices (.sort level))) + (familyFullTr : TrExprS typeEnv Us full familyIndices familyTarget) + (familyUnique : TrExprS.IsUnique familyIndices) + (indexLength : commonIndices.length = stats.nindices[familyIdx]!) + (familyHead : stats.indConsts[familyIdx]! = + .const familyName familyLevels) + (sourceUnique : TrExprS.IsUnique source) + (sourceClosed : Closed source) + (sourceFVars : FVarsIn (· ∈ common.fvars) source) + (fullTr : TrExprS typeEnv Us full source resultTarget) : + env.SpineWF Us.length full.toCtx familyTarget + (VInductDecl.recFieldIdxs stats.params.size resultTarget) + (.sort level) := by + have argumentClosed : ∀ argument ∈ + source.getAppArgs.toList.drop stats.params.size, + Closed argument := by + intro argument member + apply Closed.getAppArgsList sourceClosed + rw [← Expr.getAppArgs_toList] + exact List.mem_of_mem_drop member + have argumentFVars : ∀ argument ∈ + source.getAppArgs.toList.drop stats.params.size, + FVarsIn (· ∈ common.fvars) argument := by + intro argument member + apply FVarsIn.getAppArgsList sourceFVars + rw [← Expr.getAppArgs_toList] + exact List.mem_of_mem_drop member + have argumentUnique : ∀ argument ∈ + source.getAppArgs.toList.drop stats.params.size, + TrExprS.IsUnique argument := by + intro argument member + apply TrExprS.IsUnique.getAppArgsList sourceUnique + rw [← Expr.getAppArgs_toList] + exact List.mem_of_mem_drop member + have argumentLength : + (source.getAppArgs.toList.drop stats.params.size).length = + commonIndices.length := + (isValidIndAppIdx_indexArgs_length valid).trans indexLength.symm + obtain ⟨baseIndices, baseIndicesTr, baseSpine⟩ := + ConstructorPreFamilyIndexSpineSemanticRun.baseSpine_lift + spine familyCommonTr familyUnique state.viewDefEq state.viewUnique + state.viewExtension argumentClosed argumentFVars argumentUnique + argumentLength + have commonFamilyAtFull : TrExprS typeEnv Us full familyIndices + ((VExpr.forallN commonIndices (.sort level)).lift' fullLift) := by + simpa using (familyCommonTr.mono addType).weakFV' + typeEnvWF.ordered state.fullExtension state.fullWF + have familyEq : familyTarget = + (VExpr.forallN commonIndices (.sort level)).lift' fullLift := + familyFullTr.unique familyUnique commonFamilyAtFull + have shape := isValidIndAppIdx_shape valid + have sourceHead : source.getAppFn = .const familyName familyLevels := by + rw [familyHead] at shape + change source.getAppFn.eqv (.const familyName familyLevels) = true ∧ _ + at shape + rw [Expr.eqv_eq] at shape + generalize headEq : source.getAppFn = head at shape + cases head <;> simp_all [Expr.eqv'] + obtain ⟨targetLevels, targetHead, allArgumentsTr⟩ := + TrExprS.constApp_components fullTr sourceHead + have droppedArgumentsTr := + forall₂_drop allArgumentsTr stats.params.size + have baseIndicesAtFull : List.Forall₂ (TrExprS typeEnv Us full) + (source.getAppArgsList.drop stats.params.size) + (baseIndices.map fun index => index.lift' fullLift) := by + have baseMono := forall₂_tr_mono addType baseIndicesTr + have baseWeak := forall₂_tr_weakFV' typeEnvWF.ordered + state.fullExtension state.fullWF baseMono + simpa only [Expr.getAppArgs_toList] using baseWeak + have translatedIndicesEq : + (VExpr.appArgs resultTarget []).drop stats.params.size = + baseIndices.map fun index => index.lift' fullLift := + forall₂_translation_unique droppedArgumentsTr baseIndicesAtFull + (fun argument member => + TrExprS.IsUnique.getAppArgsList sourceUnique argument + (List.mem_of_mem_drop member)) + have fullSpine : env.SpineWF Us.length full.toCtx + ((VExpr.forallN commonIndices (.sort level)).lift' fullLift) + (baseIndices.map fun index => index.lift' fullLift) (.sort level) := by + simpa using VEnv.SpineWF.weak' henv.ordered + state.fullExtension.toCtx baseSpine + rw [← familyEq, ← translatedIndicesEq] at fullSpine + simpa only [VInductDecl.recFieldIdxs] using fullSpine + +def ConstructorFieldsRunResult + (env : VEnv) (Us : List Name) (full : VLCtx) + (familyTarget : VExpr) (level : VLevel) (familyName : Name) + (parameters : Nat) (familyIndices fields : List VExpr) + (fieldIndex : Nat) (resultTarget : VExpr) : Prop := + VInductDecl.fieldsWF Us.length familyName parameters env level familyIndices + full.toCtx fieldIndex fields ∧ + env.SpineWF Us.length (fields.reverse ++ full.toCtx) + (familyTarget.liftN fields.length 0) + (VInductDecl.recFieldIdxs parameters resultTarget) (.sort level) + +/-- Synchronize the exact D3 family-free replay with D2's analyzer-owned +constructor view, deriving every field judgment and the terminal index spine. -/ +theorem constructorFields_exactAnalyzer + {env typeEnv : VEnv} {Us : List Name} + {stats : AddInductive.InductiveStats} {familyIdx : Nat} + {familyIndices : Expr} + {d3Context d2Context : AddInductive.Context} + {d3ContextRun : AddInductive.ConstructorContextRun env Us d3Context} + {d2ContextRun : AddInductive.ConstructorContextRun typeEnv Us d2Context} + {view : Expr} {argIdx : Nat} {removed : List FVarId} + {recursiveStarted : Bool} + {d3Trace : AddInductive.ConstructorPreFamilyViewTrace stats familyIdx + familyIndices d3Context view argIdx removed recursiveStarted} + (d3 : AddInductive.ConstructorPreFamilyViewSemanticRun env Us stats + familyIdx familyIndices d3ContextRun d3Trace) + {isUnsafe : Bool} {ctorName : Name} {rawSource : Expr} + {d2Fuel whnfFuel : Nat} + {d2Trace : AddInductive.ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctorName d2Context rawSource argIdx d2Fuel} + (d2Alignment : AddInductive.ConstructorViewAlignmentTrace d2Trace view) + (d2 : AddInductive.ConstructorViewSemanticRun typeEnv Us whnfFuel + d2ContextRun d2Trace view) + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + {common full d3ViewContext analyzerViewContext : VLCtx} + {fullLift viewLift analyzerViewLift : Lift} + (d3State : D3FullContextState env typeEnv Us d3Context common full + d3ContextRun.candidate.context.vlctx d3ViewContext fullLift viewLift) + (analyzerState : AnalyzerPostContextState typeEnv Us full + d2ContextRun.candidate.context.vlctx analyzerViewContext + analyzerViewLift) + (removedInvariant : FullRemovedInvariant common full removed) + (ngenEq : d3Context.ngen = d2Context.ngen) + {commonIndices checkedIndices fields : List VExpr} + {familyTarget resultTarget : VExpr} {level : VLevel} + {familyName : Name} {familyLevels : List Level} + (familyCommonTr : TrExprS env Us common familyIndices + (VExpr.forallN commonIndices (.sort level))) + (familyFullTr : TrExprS typeEnv Us full familyIndices familyTarget) + (familyUnique : TrExprS.IsUnique familyIndices) + (indexLength : commonIndices.length = stats.nindices[familyIdx]!) + (familyHead : stats.indConsts[familyIdx]! = + .const familyName familyLevels) + (familyTargetEq : familyTarget = + VExpr.forallN (VExpr.liftTelN fieldIndex checkedIndices 0) + (.sort level)) + (resultNotForall : ∀ domain body, resultTarget ≠ .forallE domain body) + (resultLevelTr : VLevel.ofLevel Us stats.resultLevel = some level) + (absent : env.constants familyName = none) + (sourceUnique : TrExprS.IsUnique view) + (sourceClosed : Closed view) + (wholeTr : TrExprS typeEnv Us full view + (VExpr.forallN fields resultTarget)) + (parametersDone : stats.params.size ≤ argIdx) + (universeSemantics : d2Trace.universeSemantics = true) + (stageFields : ∀ q field, fields[q]? = some field → + VInductDecl.stage3Field Us.length familyName stats.params.size + checkedIndices.length (fieldIndex + q) field = true) : + ConstructorFieldsRunResult env Us full familyTarget level familyName + stats.params.size checkedIndices fields fieldIndex resultTarget := by + induction d3 generalizing d2Context d2ContextRun rawSource d2Fuel + common full d3ViewContext fullLift viewLift commonIndices familyTarget + analyzerViewContext analyzerViewLift fields fieldIndex with + | @parameter context parameterArgIdx removed recursiveStarted name domain + body binderInfo parameter parameterAt tailTrace contextRun tail ih => + have parameterLt : parameterArgIdx < stats.params.size := by + exact Array.getElem?_eq_some_iff.mp parameterAt |>.1 + omega + | @ordinary context ordinaryArgIdx removed recursiveStarted name domain body + binderInfo noParameter nonrecursive independent domainCheck ensureType + consumedCheck annotations fresh tailTrace contextRun domainRun + consumedRun ensureTypeRun annotationsRun consumedType tail ih => + cases d2 with + | @parameter _ _ _ _ d2Context d2Fuel ordinaryArgIdx name₂ + rawDomain rawBody + binderInfo₂ parameter parameterType parameterAt parameterTypeGet + validationDefEq d2TailTrace viewName viewDomain viewBody + viewBinderInfo domainCheck₂ viewDomainCheck₂ parameterTypeCheck + d2ContextRun domainRun₂ viewDomainRun₂ parameterTypeSemantic + validationRun tail₂ => + rw [noParameter] at parameterAt + contradiction + | @ordinary _ _ _ _ d2Context d2Fuel ordinaryArgIdx name₂ + rawDomain rawBody + binderInfo₂ sortResult noParameter₂ ensureTypeStep universeTrace + positivityTrace d2TailTrace viewName viewDomain viewBody + viewBinderInfo domainCheck₂ viewDomainCheck₂ viewEquality + consumedCheck₂ fresh₂ d2ContextRun domainRun₂ viewDomainRun₂ + viewEqualityRun₂ + consumedRun₂ ensureTypeRun₂ positivity₂ annotationsRun₂ + consumedType₂ tail₂ => + cases d2Alignment with + | ordinary _ _ _ _ _ positivityAlignment _ _ _ tailAlignment => + obtain ⟨fieldTarget, bodyTarget, targetEq, fieldType, + bodyType, fieldTr, bodyTr⟩ := + TrExprS.forallE_components wholeTr + cases fields with + | nil => + exact (resultNotForall fieldTarget bodyTarget targetEq).elim + | cons field fields => + simp only [VExpr.forallN, VExpr.forallE.injEq] at targetEq + obtain ⟨rfl, rfl⟩ := targetEq + have actualFieldTr : TrExprS env Us + contextRun.candidate.context.vlctx domain + domainRun.source' := by + simpa only [contextRun.venv_eq, contextRun.lparams_eq] + using domainRun.check.expr_tr + have actualFieldType : env.HasType Us.length + contextRun.candidate.context.vlctx.toCtx + domainRun.source' (.sort ensureTypeRun.resultLevel') := by + simpa only [contextRun.venv_eq, contextRun.lparams_eq] + using ensureTypeRun.source_type + have actualAnnotations : env.IsDefEqU Us.length + contextRun.candidate.context.vlctx.toCtx + domainRun.source' consumedRun.source' := by + simpa only [contextRun.venv_eq, contextRun.lparams_eq] + using annotationsRun.isDefEqU + obtain ⟨consumedLevel, actualConsumedType⟩ := consumedType + have actualConsumedType' : env.HasType Us.length + contextRun.candidate.context.vlctx.toCtx + consumedRun.source' (.sort consumedLevel) := by + simpa only [contextRun.venv_eq, contextRun.lparams_eq] + using actualConsumedType + let nextD3ContextRun := contextRun.pushLocalDecl name + binderInfo (consumeTypeAnnotations domain) fresh + consumedRun.source' consumedRun.check.expr_tr + ⟨consumedLevel, actualConsumedType⟩ + have actualTailWF : VLCtx.WF env Us.length + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam consumedRun.source') :: + contextRun.candidate.context.vlctx) := by + have nextWF := nextD3ContextRun.candidate.context.Δwf + rw [nextD3ContextRun.venv_eq, + nextD3ContextRun.lparams_eq] at nextWF + exact nextWF + have postViewTr : TrExprS typeEnv Us + d2ContextRun.candidate.context.vlctx domain + viewDomainRun₂.source' := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using + viewDomainRun₂.check.expr_tr + have postRawType : typeEnv.HasType Us.length + d2ContextRun.candidate.context.vlctx.toCtx + domainRun₂.source' (.sort ensureTypeRun₂.resultLevel') := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using ensureTypeRun₂.source_type + have postRawView : typeEnv.IsDefEqU Us.length + d2ContextRun.candidate.context.vlctx.toCtx + domainRun₂.source' viewDomainRun₂.source' := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using + viewEqualityRun₂.isDefEqU + have postAnnotations : typeEnv.IsDefEqU Us.length + d2ContextRun.candidate.context.vlctx.toCtx + domainRun₂.source' consumedRun₂.source' := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using + annotationsRun₂.isDefEqU + let nextD2ContextRun := d2ContextRun.pushLocalDecl name₂ + binderInfo₂ (consumeTypeAnnotations rawDomain) fresh₂ + consumedRun₂.source' consumedRun₂.check.expr_tr + consumedType₂ + have postTailWF : VLCtx.WF typeEnv Us.length + ((some (d2Context.freshFVarId, + (consumeTypeAnnotations rawDomain).fvarsList), + .vlam consumedRun₂.source') :: + d2ContextRun.candidate.context.vlctx) := by + have nextWF := nextD2ContextRun.candidate.context.Δwf + rw [nextD2ContextRun.venv_eq, + nextD2ContextRun.lparams_eq] at nextWF + simpa only [nextD2ContextRun, + AddInductive.ConstructorContextRun.pushLocalDecl, + CandidateContextRun.pushLocalDecl_vlctx] using nextWF + simp only [AddInductive.ConstructorTypeValidationTrace.universeSemantics, + Bool.and_eq_true] at universeSemantics + have sortLevelEq : sortResult.sortLevel! = + ensureTypeRun₂.resultLevel := by + simpa only [Expr.sortLevel!] using + congrArg Expr.sortLevel! ensureTypeRun₂.result_eq + have fieldLevelTr : VLevel.ofLevel Us + sortResult.sortLevel! = + some ensureTypeRun₂.resultLevel' := by + rw [sortLevelEq] + simpa only [d2ContextRun.lparams_eq] using + ensureTypeRun₂.resultLevel_tr + have rawBound := + AddInductive.constructorUniverseSemanticGe_ofLevel + universeSemantics.1 resultLevelTr fieldLevelTr + have freshEq : context.freshFVarId = + d2Context.freshFVarId := + Context.freshFVarId_eq_of_ngen_eq ngenEq + have domainFVars : FVarsIn (· ∈ common.fvars) domain := + constructorIndependentOf_fvars fieldTr.fvarsIn + independent removedInvariant + obtain ⟨commonDomain, commonDomainTr, fieldEq, + commonDomainType, nextD3State⟩ := + d3State.push (name := name) (binderInfo := binderInfo) + henv typeEnvWF addType sourceUnique.1 + sourceClosed.1 domainFVars fieldTr actualFieldTr + actualFieldType actualAnnotations actualConsumedType' + actualTailWF + obtain ⟨postAnalyzerType, nextAnalyzerState⟩ := + analyzerState.push typeEnvWF sourceUnique.1 sourceClosed.1 + fieldTr postViewTr postRawType postRawView + postAnnotations postTailWF + have fieldBaseType : env.HasType Us.length full.toCtx field + (.sort ensureTypeRun.resultLevel') := by + rw [fieldEq] + exact commonDomainType.weak' henv.ordered + d3State.fullExtension.toCtx + have levelEq : ensureTypeRun.resultLevel' ≈ + ensureTypeRun₂.resultLevel' := + (fieldBaseType.mono addType).uniqU typeEnvWF + d3State.fullWF.toCtx postAnalyzerType |>.sort_inv + typeEnvWF d3State.fullWF.toCtx + have fieldBound : level = .zero ∨ + ensureTypeRun.resultLevel' ≤ level := by + rcases rawBound with prop | bound + · exact .inl prop + · exact .inr <| VLevel.le_trans + (VLevel.le_antisymm_iff.mp levelEq).1 bound + have commonFree : commonDomain.hasConst familyName = false := + VEnv.HasType.hasConst_false_of_absent henv.ordered + d3State.commonWF.toCtx absent commonDomainType + have fieldFree : field.hasConst familyName = false := by + rw [fieldEq, VExpr.hasConst_lift'] + exact commonFree + have recNone := recArg?_eq_none_of_hasConst_false + (U := Us.length) (np := stats.params.size) + (ni := checkedIndices.length) (fieldIndex := fieldIndex) + fieldFree + have nextD3State' : D3FullContextState env typeEnv Us + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)) + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam commonDomain) :: common) + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + nextD3ContextRun.candidate.context.vlctx + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam (commonDomain.lift' viewLift)) :: d3ViewContext) + (.consN fullLift 1) (.consN viewLift 1) := by + exact nextD3State + have nextAnalyzerState' : AnalyzerPostContextState + typeEnv Us + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + nextD2ContextRun.candidate.context.vlctx + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam (field.lift' analyzerViewLift)) :: + analyzerViewContext) + (.consN analyzerViewLift 1) := by + rw [freshEq] + simpa only [nextD2ContextRun, + AddInductive.ConstructorContextRun.pushLocalDecl, + CandidateContextRun.pushLocalDecl_vlctx] using + nextAnalyzerState + have familyCommonNext : TrExprS env Us + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam commonDomain) :: common) + familyIndices + (VExpr.forallN (VExpr.liftTelN 1 commonIndices 0) + (.sort level)) := by + have weakened := familyCommonTr.weakFV henv.ordered + (VLCtx.FVLift.skip_fvar + (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList) + (.vlam commonDomain) .refl) + nextD3State'.commonWF + simpa [VLocalDecl.depth, VExpr.liftN_forallN, + VExpr.liftN] using weakened + have familyFullNext : TrExprS typeEnv Us + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + familyIndices (familyTarget.liftN 1 0) := by + have weakened := familyFullTr.weakFV typeEnvWF.ordered + (VLCtx.FVLift.skip_fvar + (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList) + (.vlam field) .refl) + nextD3State'.fullWF + simpa [VLocalDecl.depth] using weakened + have bodyOpened : TrExprS typeEnv Us + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + (body.instantiate1 context.freshExpr) + (VExpr.forallN fields resultTarget) := by + simpa only [AddInductive.Context.freshExpr, + Expr.instantiate1_eq] using + bodyTr.inst_fvar typeEnvWF.ordered nextD3State'.fullWF + have tailUnique : TrExprS.IsUnique + (body.instantiate1 context.freshExpr) := by + apply TrExprS.IsUnique.instantiate1 sourceUnique.2 + simp only [AddInductive.Context.freshExpr] + trivial + have nextFullNoBV : + VLCtx.bvars (((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) : VLCtx) = 0 := + nextD3State'.fullExtension.bvars_eq.trans + nextD3State'.commonNoBV + have tailClosed : Closed + (body.instantiate1 context.freshExpr) := by + have closed := bodyOpened.closed + rw [nextFullNoBV] at closed + exact closed + have freshExprEq : d2Context.freshExpr = + context.freshExpr := by + simp only [AddInductive.Context.freshExpr, freshEq] + have tailAlignment' : AddInductive.ConstructorViewAlignmentTrace + d2TailTrace (body.instantiate1 context.freshExpr) := by + rw [← freshExprEq] + exact tailAlignment + have tail₂' : AddInductive.ConstructorViewSemanticRun + typeEnv Us whnfFuel nextD2ContextRun d2TailTrace + (body.instantiate1 context.freshExpr) := by + rw [← freshExprEq] + exact tail₂ + have nextNgenEq : + (context.pushLocalDecl name binderInfo + (consumeTypeAnnotations domain)).ngen = + (d2Context.pushLocalDecl name₂ binderInfo₂ + (consumeTypeAnnotations rawDomain)).ngen := by + simp only [AddInductive.Context.pushLocalDecl, ngenEq] + have nextIndexLength : + (VExpr.liftTelN 1 commonIndices 0).length = + stats.nindices[familyIdx]! := by + simpa only [VExpr.liftTelN_length] using indexLength + have familyTargetNextEq : familyTarget.liftN 1 0 = + VExpr.forallN + (VExpr.liftTelN (fieldIndex + 1) checkedIndices 0) + (.sort level) := by + rw [familyTargetEq, VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN] + simp only [VExpr.liftN] + have stageTail : ∀ q candidate, + fields[q]? = some candidate → + VInductDecl.stage3Field Us.length familyName + stats.params.size checkedIndices.length + (fieldIndex + 1 + q) candidate = true := by + intro q candidate member + have staged := stageFields (q + 1) candidate (by + simpa using member) + simpa only [Nat.add_assoc, Nat.add_comm 1 q] using staged + obtain ⟨tailFields, tailSpine⟩ := ih + (fieldIndex := fieldIndex + 1) tailAlignment' tail₂' + nextD3State' nextAnalyzerState' + (removedInvariant.push) nextNgenEq familyCommonNext + familyFullNext nextIndexLength familyTargetNextEq + tailUnique tailClosed bodyOpened (by omega) + universeSemantics.2 stageTail + unfold ConstructorFieldsRunResult + refine ⟨⟨?_, ?_, ?_⟩, ?_⟩ + · exact .inr (.inr ⟨recNone, ensureTypeRun.resultLevel', + fieldBaseType, fieldBound⟩) + · intro recursive + rw [VInductDecl.recArg?_of_isRecField recursive] at recNone + contradiction + · simpa only [VLCtx.toCtx] using tailFields + · simpa only [List.reverse_cons, List.singleton_append, + List.append_assoc, VLCtx.toCtx, List.length_cons, + VExpr.liftN_liftN, Nat.add_comm] using tailSpine + | terminal sourceRun₂ viewRun₂ => + cases d2Alignment; simp_all [Expr.isForall] + | @recursive context recursiveArgIdx removed recursiveStarted name domain + body binderInfo noParameter isRecursive independent fieldTrace fresh + tailTrace contextRun recursiveRun tail ih => + cases d2 with + | @parameter _ _ _ _ d2Context d2Fuel recursiveArgIdx name₂ + rawDomain rawBody binderInfo₂ parameter parameterType parameterAt + parameterTypeGet validationDefEq d2TailTrace viewName viewDomain + viewBody viewBinderInfo domainCheck₂ viewDomainCheck₂ + parameterTypeCheck d2ContextRun domainRun₂ viewDomainRun₂ + parameterTypeSemantic validationRun tail₂ => + rw [noParameter] at parameterAt + contradiction + | @ordinary _ _ _ _ d2Context d2Fuel recursiveArgIdx name₂ + rawDomain rawBody binderInfo₂ sortResult noParameter₂ + ensureTypeStep universeTrace positivityTrace d2TailTrace viewName + viewDomain viewBody viewBinderInfo domainCheck₂ viewDomainCheck₂ + viewEquality consumedCheck₂ fresh₂ d2ContextRun domainRun₂ + viewDomainRun₂ viewEqualityRun₂ consumedRun₂ ensureTypeRun₂ + positivity₂ annotationsRun₂ consumedType₂ tail₂ => + cases d2Alignment with + | ordinary _ _ _ _ _ positivityAlignment _ _ _ tailAlignment => + obtain ⟨fieldTarget, bodyTarget, targetEq, fieldType, + bodyType, fieldTr, bodyTr⟩ := + TrExprS.forallE_components wholeTr + cases fields with + | nil => + exact (resultNotForall fieldTarget bodyTarget targetEq).elim + | cons field fields => + simp only [VExpr.forallN, VExpr.forallE.injEq] at targetEq + obtain ⟨rfl, rfl⟩ := targetEq + have postViewTr : TrExprS typeEnv Us + d2ContextRun.candidate.context.vlctx domain + viewDomainRun₂.source' := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using + viewDomainRun₂.check.expr_tr + have postRawType : typeEnv.HasType Us.length + d2ContextRun.candidate.context.vlctx.toCtx + domainRun₂.source' (.sort ensureTypeRun₂.resultLevel') := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using ensureTypeRun₂.source_type + have postRawView : typeEnv.IsDefEqU Us.length + d2ContextRun.candidate.context.vlctx.toCtx + domainRun₂.source' viewDomainRun₂.source' := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using + viewEqualityRun₂.isDefEqU + have postAnnotations : typeEnv.IsDefEqU Us.length + d2ContextRun.candidate.context.vlctx.toCtx + domainRun₂.source' consumedRun₂.source' := by + simpa only [d2ContextRun.venv_eq, + d2ContextRun.lparams_eq] using annotationsRun₂.isDefEqU + let nextD2ContextRun := d2ContextRun.pushLocalDecl name₂ + binderInfo₂ (consumeTypeAnnotations rawDomain) fresh₂ + consumedRun₂.source' consumedRun₂.check.expr_tr + consumedType₂ + have postTailWF : VLCtx.WF typeEnv Us.length + ((some (d2Context.freshFVarId, + (consumeTypeAnnotations rawDomain).fvarsList), + .vlam consumedRun₂.source') :: + d2ContextRun.candidate.context.vlctx) := by + have nextWF := nextD2ContextRun.candidate.context.Δwf + rw [nextD2ContextRun.venv_eq, + nextD2ContextRun.lparams_eq] at nextWF + simpa only [nextD2ContextRun, + AddInductive.ConstructorContextRun.pushLocalDecl, + CandidateContextRun.pushLocalDecl_vlctx] using nextWF + simp only [ + AddInductive.ConstructorTypeValidationTrace.universeSemantics, + Bool.and_eq_true] at universeSemantics + have freshEq : context.freshFVarId = + d2Context.freshFVarId := + Context.freshFVarId_eq_of_ngen_eq ngenEq + obtain ⟨postAnalyzerType, nextAnalyzerState⟩ := + analyzerState.push typeEnvWF sourceUnique.1 sourceClosed.1 + fieldTr postViewTr postRawType postRawView + postAnnotations postTailWF + have nextAnalyzerState' : AnalyzerPostContextState + typeEnv Us + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + nextD2ContextRun.candidate.context.vlctx + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam (field.lift' analyzerViewLift)) :: + analyzerViewContext) + (.consN analyzerViewLift 1) := by + rw [freshEq] + simpa only [nextD2ContextRun, + AddInductive.ConstructorContextRun.pushLocalDecl, + CandidateContextRun.pushLocalDecl_vlctx] using + nextAnalyzerState + have domainFVars : FVarsIn (· ∈ common.fvars) domain := + constructorIndependentOf_fvars fieldTr.fvarsIn + independent removedInvariant + have recursiveResult := recursiveField_exactAnalyzer + recursiveRun henv typeEnvWF addType d3State + familyCommonTr familyFullTr familyUnique indexLength + familyHead sourceUnique.1 sourceClosed.1 domainFVars fieldTr + have stageHead : VInductDecl.stage3Field Us.length + familyName stats.params.size checkedIndices.length + fieldIndex field = true := by + simpa using stageFields 0 field (by simp) + obtain ⟨recursive, recursiveEq, recursiveWF⟩ := + recursiveFieldResult_recArgWF recursiveResult + familyTargetEq stageHead + have nextD3State : D3FullContextState env typeEnv Us + context.advanceFresh common + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + contextRun.advanceFresh.candidate.context.vlctx + d3ViewContext (.skipN fullLift 1) viewLift := by + simpa only [AddInductive.ConstructorContextRun.advanceFresh, + AddInductive.advanceCandidateContextRun] using + d3State.skip (source := domain) + nextAnalyzerState'.fullWF + have familyFullNext : TrExprS typeEnv Us + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + familyIndices (familyTarget.liftN 1 0) := by + have weakened := familyFullTr.weakFV typeEnvWF.ordered + (VLCtx.FVLift.skip_fvar + (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList) + (.vlam field) .refl) + nextD3State.fullWF + simpa [VLocalDecl.depth] using weakened + have bodyOpened : TrExprS typeEnv Us + ((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) + (body.instantiate1 context.freshExpr) + (VExpr.forallN fields resultTarget) := by + simpa only [AddInductive.Context.freshExpr, + Expr.instantiate1_eq] using + bodyTr.inst_fvar typeEnvWF.ordered nextD3State.fullWF + have tailUnique : TrExprS.IsUnique + (body.instantiate1 context.freshExpr) := by + apply TrExprS.IsUnique.instantiate1 sourceUnique.2 + simp only [AddInductive.Context.freshExpr] + trivial + have nextFullNoBV : + VLCtx.bvars (((some (context.freshFVarId, + (consumeTypeAnnotations domain).fvarsList), + .vlam field) :: full) : VLCtx) = 0 := + nextD3State.fullExtension.bvars_eq.trans + nextD3State.commonNoBV + have tailClosed : Closed + (body.instantiate1 context.freshExpr) := by + have closed := bodyOpened.closed + rw [nextFullNoBV] at closed + exact closed + have freshExprEq : d2Context.freshExpr = + context.freshExpr := by + simp only [AddInductive.Context.freshExpr, freshEq] + have tailAlignment' : AddInductive.ConstructorViewAlignmentTrace + d2TailTrace (body.instantiate1 context.freshExpr) := by + rw [← freshExprEq] + exact tailAlignment + have tail₂' : AddInductive.ConstructorViewSemanticRun + typeEnv Us whnfFuel nextD2ContextRun d2TailTrace + (body.instantiate1 context.freshExpr) := by + rw [← freshExprEq] + exact tail₂ + have nextNgenEq : context.advanceFresh.ngen = + (d2Context.pushLocalDecl name₂ binderInfo₂ + (consumeTypeAnnotations rawDomain)).ngen := by + simp only [AddInductive.Context.advanceFresh, + AddInductive.Context.pushLocalDecl, ngenEq] + have freshFull : context.freshFVarId ∉ full.fvars := + (nextAnalyzerState'.fullWF.2.1 _ _ rfl).1 + have familyTargetNextEq : familyTarget.liftN 1 0 = + VExpr.forallN + (VExpr.liftTelN (fieldIndex + 1) checkedIndices 0) + (.sort level) := by + rw [familyTargetEq, VExpr.liftN_forallN, + VExpr.liftTelN_liftTelN] + simp only [VExpr.liftN] + have stageTail : ∀ q candidate, + fields[q]? = some candidate → + VInductDecl.stage3Field Us.length familyName + stats.params.size checkedIndices.length + (fieldIndex + 1 + q) candidate = true := by + intro q candidate member + have staged := stageFields (q + 1) candidate (by + simpa using member) + simpa only [Nat.add_assoc, Nat.add_comm 1 q] using staged + obtain ⟨tailFields, tailSpine⟩ := ih + (fieldIndex := fieldIndex + 1) tailAlignment' tail₂' + nextD3State nextAnalyzerState' + (removedInvariant.skip freshFull) nextNgenEq + familyCommonTr familyFullNext indexLength + familyTargetNextEq tailUnique tailClosed bodyOpened + (by omega) universeSemantics.2 stageTail + have headClassification : + VInductDecl.isRecField Us.length familyName + stats.params.size checkedIndices.length fieldIndex + field = true ∨ + (∃ descriptor, + VInductDecl.recArg? Us.length familyName + stats.params.size checkedIndices.length + fieldIndex field = some descriptor ∧ + descriptor.binders ≠ [] ∧ + descriptor.WF Us.length env level checkedIndices + full.toCtx) ∨ + VInductDecl.recArg? Us.length familyName + stats.params.size checkedIndices.length fieldIndex + field = none ∧ + ∃ fieldLevel, + env.HasType Us.length full.toCtx field + (.sort fieldLevel) ∧ + (level = .zero ∨ fieldLevel ≤ level) := by + by_cases nonempty : recursive.binders ≠ [] + · exact .inr (.inl ⟨recursive, recursiveEq, nonempty, + recursiveWF⟩) + · have empty : recursive.binders = [] := by + simpa using nonempty + exact .inl + (VInductDecl.recArg?_nil recursiveEq empty).1 + have headDirectSpine : + VInductDecl.isRecField Us.length familyName + stats.params.size checkedIndices.length fieldIndex + field = true → + env.SpineWF Us.length full.toCtx + (VExpr.forallN + (VExpr.liftTelN fieldIndex checkedIndices 0) + (.sort level)) + (VInductDecl.recFieldIdxs stats.params.size field) + (.sort level) := by + intro direct + have canonical := + VInductDecl.recArg?_of_isRecField direct + have descriptorEq : recursive = + { fieldIndex := fieldIndex, binders := [], + targetType := 0, + indices := VInductDecl.recFieldIdxs + stats.params.size field } := + Option.some.inj (recursiveEq.symm.trans canonical) + rw [descriptorEq] at recursiveWF + simpa [VInductDecl.RecArg.WF] using recursiveWF.2 + unfold ConstructorFieldsRunResult + refine ⟨⟨headClassification, headDirectSpine, ?_⟩, ?_⟩ + · simpa only [VLCtx.toCtx] using tailFields + · simpa only [List.reverse_cons, List.singleton_append, + List.append_assoc, VLCtx.toCtx, List.length_cons, + VExpr.liftN_liftN, Nat.add_comm] using tailSpine + | terminal sourceRun₂ viewRun₂ => + cases d2Alignment; simp_all [Expr.isForall] + | @terminal context source terminalArgIdx removed recursiveStarted valid + independent spineTrace contextRun expected spine => + have shape := isValidIndAppIdx_shape valid + have sourceHead : source.getAppFn = .const familyName familyLevels := by + rw [familyHead] at shape + change source.getAppFn.eqv (.const familyName familyLevels) = true ∧ _ + at shape + rw [Expr.eqv_eq] at shape + generalize headEq : source.getAppFn = head at shape + cases head <;> simp_all [Expr.eqv'] + cases fields with + | nil => + unfold ConstructorFieldsRunResult + refine ⟨trivial, ?_⟩ + simpa using terminal_exactAnalyzer + (valid := valid) (resultTarget := resultTarget) + spine henv typeEnvWF addType d3State + familyCommonTr familyFullTr familyUnique indexLength familyHead + sourceUnique sourceClosed + (constructorIndependentOf_fvars wholeTr.fvarsIn independent + removedInvariant) + wholeTr + | cons field fields => + cases wholeTr + all_goals simp_all [Expr.getAppFn] + +end ConstructorValidation + +namespace VInductDecl +open AddInductive TypeChecker VEnv + +theorem stagedIndexCount_eq + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {kernelSource : InductiveType} + {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate source) + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) + (_analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + (input.postFamilyInput.universeInput.staged.family.validation.stats + ).nindices[0]! = generation.block.checked.indices.length := by + let validation := input.postFamilyInput.universeInput.staged.family.validation + have familyShape := shape + simp only [NormalizationCandidateSemanticRun.generationShape, + normalizationCandidateGenerationShape, Bool.and_eq_true, + beq_iff_eq] at familyShape + have spineLengthEq : + candidate.families.singleton.familyType.type.trace.spineLength = + (generation.block.checked.params ++ + generation.block.checked.indices).length := by + calc + _ = (VExpr.telN source.nparams normalization.raw.type ++ + ctorFields (VExpr.dropN source.nparams normalization.raw.type)).length := + familyShape.1.2 + _ = (generation.block.rawParams ++ + generation.block.rawIndices).length := by + simp only [NormalizedChecked.rawParams, NormalizedChecked.rawIndices, + NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] + _ = (generation.block.checked.params ++ + generation.block.checked.indices).length := by + simp only [List.length_append] + rw [generation.shape.2.1, generation.shape.2.2.1] + have parameterLength : generation.block.checked.params.length = + source.nparams := + generation.block.checked.direct_anatomy.2.1.trans + generation.block.nparams_eq.symm + change validation.stats.nindices[0]! = _ + rw [validation.stats_eq] + simp only [CandidateExprTrace.singletonCandidateInductiveStats] + rw [spineLengthEq, List.length_append, parameterLength, + input.postFamilyInput.universeInput.staged.validation_nparams_eq, + Nat.add_sub_cancel_left] + rfl + +theorem stagedResultLevel_tr + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {kernelSource : InductiveType} + {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate source) + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + VLevel.ofLevel Us + input.postFamilyInput.universeInput.staged.family.validation.stats.resultLevel = + some generation.block.checked.resultLevel := by + let validation := input.postFamilyInput.universeInput.staged.family.validation + have familyShape := shape + simp only [NormalizationCandidateSemanticRun.generationShape, + normalizationCandidateGenerationShape, Bool.and_eq_true, + beq_iff_eq] at familyShape + have spineLengthEq : + candidate.families.singleton.familyType.type.trace.spineLength = + (generation.block.checked.params ++ + generation.block.checked.indices).length := by + calc + _ = (VExpr.telN source.nparams normalization.raw.type ++ + ctorFields (VExpr.dropN source.nparams normalization.raw.type)).length := + familyShape.1.2 + _ = (generation.block.rawParams ++ + generation.block.rawIndices).length := by + simp only [NormalizedChecked.rawParams, NormalizedChecked.rawIndices, + NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] + _ = (generation.block.checked.params ++ + generation.block.checked.indices).length := by + simp only [List.length_append] + rw [generation.shape.2.1, generation.shape.2.2.1] + have viewEq : normalization.family.type.view = + VExpr.forallN + (generation.block.checked.params ++ generation.block.checked.indices) + (.sort generation.block.checked.resultLevel) := by + have analyzerEq : normalization.family.type.view = + generation.block.checked.type.type := + (congrArg (fun ty : VInductiveType => ty.type) + (normalization.root.familyViewType_eq analysis)).symm + rw [analyzerEq, generation.block.checked.type_eq, + VExpr.forallN_append] + obtain ⟨_, recursive⟩ := normalization.family.type.recursive + have levelTr := ConstructorValidation.CandidateExprRun.terminalLevel_tr recursive + validation.terminal_eq viewEq spineLengthEq + change VLevel.ofLevel Us validation.stats.resultLevel = _ + rw [validation.stats_eq] + simpa only [CandidateExprTrace.singletonCandidateInductiveStats] using levelTr + +end VInductDecl + +namespace VInductDecl +open AddInductive TypeChecker VEnv +open ConstructorValidation + +/-- Derive the checked field and result-spine obligations for one exact +analyzer-owned constructor position after consuming its parameter prefix. -/ +theorem CandidateSemanticNormalizedCtorRun.checkedConstructorWF + {env typeEnv : VEnv} {Us : List Name} + {source : VInductDecl} {generation : GenerationChecked source} + {kernelCtor : Constructor} + {candidateCtor : AddInductive.CandidateConstructor kernelCtor} + {rawCtor : VConstVal} + {root : CandidateConstructorSemanticRun typeEnv Us candidateCtor rawCtor} + {ctor : NormalizedCtor} + {stats : InductiveStats} {familyIndices : Expr} + {d3Context d2Context : AddInductive.Context} + {d3ContextRun : AddInductive.ConstructorContextRun env Us d3Context} + {d2ContextRun : AddInductive.ConstructorContextRun typeEnv Us d2Context} + {d3Trace : AddInductive.ConstructorPreFamilyViewTrace stats 0 + familyIndices d3Context candidateCtor.type.view 0 [] false} + (d3 : AddInductive.ConstructorPreFamilyViewSemanticRun env Us stats 0 + familyIndices d3ContextRun d3Trace) + {d2Trace : AddInductive.ConstructorTypeValidationTrace stats false 0 + kernelCtor.name d2Context kernelCtor.type 0 d2Context.fuel.inductiveFuel} + (d2Alignment : AddInductive.ConstructorViewAlignmentTrace d2Trace + candidateCtor.type.view) + (d2 : AddInductive.ConstructorViewSemanticRun typeEnv Us + root.type.whnfFuel d2ContextRun d2Trace candidateCtor.type.view) + (genRun : CandidateSemanticNormalizedCtorRun generation.block typeEnv Us + root ctor) + (hctor : ctor ∈ generation.block.ctorPairs) + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + {parameterΔ d3ViewContext analyzerViewContext : VLCtx} + {viewLift analyzerViewLift : Lift} + {parameters : List Expr} + (parameterContext : CandidateParameterContext [] parameters + generation.block.checked.params parameterΔ) + (parameterWF : VLCtx.WF env Us.length parameterΔ) + (parameterCtx : parameterΔ.toCtx = + generation.block.checked.params.reverse) + (d3State : D3FullContextState env typeEnv Us d3Context + parameterΔ parameterΔ d3ContextRun.candidate.context.vlctx + d3ViewContext .refl viewLift) + (analyzerState : AnalyzerPostContextState typeEnv Us parameterΔ + d2ContextRun.candidate.context.vlctx analyzerViewContext + analyzerViewLift) + (ngenEq : d3Context.ngen = d2Context.ngen) + (parametersEq : stats.params.toList = parameters) + {familyName : Name} {familyLevels : List Level} + (indConsts : stats.indConsts = #[.const familyName familyLevels]) + (familyTr : TrExprS env Us parameterΔ familyIndices + (VExpr.forallN generation.block.checked.indices + (.sort generation.block.checked.resultLevel))) + (familyUnique : TrExprS.IsUnique familyIndices) + (indexLength : generation.block.checked.indices.length = + stats.nindices[0]!) + (resultLevelTr : VLevel.ofLevel Us stats.resultLevel = + some generation.block.checked.resultLevel) + (absent : env.constants familyName = none) + (unique : CandidateExprTraceViewIsUnique candidateCtor.type.trace) + (universeSemantics : d2Trace.universeSemantics = true) + (stageFields : ∀ q field, ctor.view.fields[q]? = some field → + VInductDecl.stage3Field Us.length familyName stats.params.size + generation.block.checked.indices.length q field = true) : + VInductDecl.fieldsWF Us.length familyName stats.params.size env + generation.block.checked.resultLevel + generation.block.checked.indices + generation.block.checked.params.reverse 0 ctor.view.fields ∧ + env.SpineWF Us.length + (ctor.view.fields.reverse ++ + generation.block.checked.params.reverse) + (VExpr.forallN + (VExpr.liftTelN ctor.view.fields.length + generation.block.checked.indices 0) + (.sort generation.block.checked.resultLevel)) + (VInductDecl.recFieldIdxs stats.params.size + (ctor.resultTarget generation.block)) + (.sort generation.block.checked.resultLevel) := by + obtain ⟨rest, instantiation, ⟨d3Suffix⟩, wholeTr⟩ := + genRun.preFamilySuffix addType parameterContext parameterWF unique d3 + hctor parametersEq indConsts + obtain ⟨d2Suffix, suffixUniverse⟩ := + d2.afterParameters d2Alignment (by omega) instantiation + have instantiation' : instantiateFamilyParameters candidateCtor.type.view + parameters = .ok rest := by + rw [← parametersEq] + exact instantiation + have sourceUnique : TrExprS.IsUnique rest := + instantiateFamilyParameters_unique unique.view + (ConstructorValidation.CandidateParameterContext.parametersUnique + parameterContext) instantiation' + have sourceClosed : Closed rest := by + have closed := wholeTr.closed + rw [show parameterΔ.bvars = 0 from by + simpa only [VLCtx.NoBV] using d3State.commonNoBV] at closed + exact closed + have resultNotForall : ∀ domain body, + ctor.resultTarget generation.block ≠ .forallE domain body := by + intro domain body equality + have headEq := congrArg VExpr.appHead equality + simp only [NormalizedCtor.resultTarget, VExpr.appHead_appN, + VExpr.appHead] at headEq + exact VExpr.noConfusion headEq + have familyTargetEq : + VExpr.forallN generation.block.checked.indices + (.sort generation.block.checked.resultLevel) = + VExpr.forallN + (VExpr.liftTelN 0 generation.block.checked.indices 0) + (.sort generation.block.checked.resultLevel) := by + have liftTelNZero : ∀ (indices : List VExpr) (cutoff : Nat), + VExpr.liftTelN 0 indices cutoff = indices := by + intro indices cutoff + induction indices generalizing cutoff with + | nil => rfl + | cons index indices ih => + simp only [VExpr.liftTelN, VExpr.liftN_zero] + rw [ih] + rw [liftTelNZero] + have removedInvariant : FullRemovedInvariant parameterΔ parameterΔ + [] := by + intro fv member _ + exact member + have familyHead : stats.indConsts[0]! = + .const familyName familyLevels := by + rw [indConsts] + rfl + have suffixUniverseSemantics : + d2Suffix.trace.universeSemantics = true := + suffixUniverse.trans universeSemantics + have result := constructorFields_exactAnalyzer + (d3 := d3Suffix.semantic) + (d2Alignment := d2Suffix.alignment) (d2 := d2Suffix.semantic) + henv typeEnvWF addType d3State analyzerState + removedInvariant ngenEq + familyTr (familyTr.mono addType) familyUnique indexLength + familyHead + familyTargetEq resultNotForall resultLevelTr absent sourceUnique + sourceClosed wholeTr (by omega) suffixUniverseSemantics (by + intro q field atIndex + simpa only [Nat.zero_add] using stageFields q field atIndex) + unfold ConstructorFieldsRunResult at result + simpa only [parameterCtx, VExpr.liftN_forallN, VExpr.liftN, + Nat.zero_add] using result + +/-- Traverse the exact source-indexed D3, D2, and analyzer lists in lockstep. +The dependent indices rule out truncation, reordering, or reuse of evidence +from a different constructor position. -/ +theorem CandidateSemanticNormalizedCtorListRun.checkedConstructorsWF + {env typeEnv : VEnv} {Us : List Name} + {source : VInductDecl} {generation : GenerationChecked source} + {stats : InductiveStats} {familyIndices : Expr} + {d3Context d2Context : AddInductive.Context} + {d3ContextRun : AddInductive.ConstructorContextRun env Us d3Context} + {d2ContextRun : AddInductive.ConstructorContextRun typeEnv Us d2Context} + {kernelCtors : List Constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor kernelCtors} + {d3Trace : AddInductive.ConstructorPreFamilyListTrace stats 0 + familyIndices d3Context candidates} + (d3 : AddInductive.ConstructorPreFamilyListSemanticRun env Us stats 0 + familyIndices d3Context d3ContextRun d3Trace) + {seen : NameSet} + {d2Trace : AddInductive.ConstructorListValidationTrace stats false 0 + d2Context seen kernelCtors} + {alignment : AddInductive.ConstructorCandidateAlignmentTrace stats false 0 + d2Context d2Trace candidates} + {raws : List VConstVal} + {roots : CandidateConstructorSemanticListRun typeEnv Us candidates raws} + (d2 : AddInductive.ConstructorPostFamilySemanticListRun typeEnv Us stats + false 0 d2Context d2ContextRun d2Trace candidates alignment roots) + {ctors : List NormalizedCtor} + (generationRuns : CandidateSemanticNormalizedCtorListRun generation.block + typeEnv Us roots ctors) + (membership : ∀ ctor ∈ ctors, + ctor ∈ generation.block.ctorPairs) + (henv : VEnv.WF env) (typeEnvWF : VEnv.WF typeEnv) + (addType : env ≤ typeEnv) + {parameterΔ d3ViewContext analyzerViewContext : VLCtx} + {viewLift analyzerViewLift : Lift} + {parameters : List Expr} + (parameterContext : CandidateParameterContext [] parameters + generation.block.checked.params parameterΔ) + (parameterWF : VLCtx.WF env Us.length parameterΔ) + (parameterCtx : parameterΔ.toCtx = + generation.block.checked.params.reverse) + (d3State : D3FullContextState env typeEnv Us d3Context + parameterΔ parameterΔ d3ContextRun.candidate.context.vlctx + d3ViewContext .refl viewLift) + (analyzerState : AnalyzerPostContextState typeEnv Us parameterΔ + d2ContextRun.candidate.context.vlctx analyzerViewContext + analyzerViewLift) + (ngenEq : d3Context.ngen = d2Context.ngen) + (parametersEq : stats.params.toList = parameters) + {familyName : Name} {familyLevels : List Level} + (indConsts : stats.indConsts = #[.const familyName familyLevels]) + (familyTr : TrExprS env Us parameterΔ familyIndices + (VExpr.forallN generation.block.checked.indices + (.sort generation.block.checked.resultLevel))) + (familyUnique : TrExprS.IsUnique familyIndices) + (indexLength : generation.block.checked.indices.length = + stats.nindices[0]!) + (resultLevelTr : VLevel.ofLevel Us stats.resultLevel = + some generation.block.checked.resultLevel) + (absent : env.constants familyName = none) + (unique : candidates.ViewTranslationUnique) + (universeSemantics : d2Trace.universeSemantics = true) + (uvarsEq : source.uvars = Us.length) + (familyNameEq : familyName = generation.block.checked.type.name) + (paramsSizeEq : stats.params.size = source.nparams) : + ∀ ctor ∈ ctors, + VInductDecl.fieldsWF Us.length familyName stats.params.size env + generation.block.checked.resultLevel + generation.block.checked.indices + generation.block.checked.params.reverse 0 ctor.view.fields ∧ + env.SpineWF Us.length + (ctor.view.fields.reverse ++ + generation.block.checked.params.reverse) + (VExpr.forallN + (VExpr.liftTelN ctor.view.fields.length + generation.block.checked.indices 0) + (.sort generation.block.checked.resultLevel)) + (VInductDecl.recFieldIdxs stats.params.size + (ctor.resultTarget generation.block)) + (.sort generation.block.checked.resultLevel) := by + induction d3 generalizing seen raws ctors with + | nil => + cases d2 + cases generationRuns + intro ctor member + simp at member + | cons d3Head d3Tail ih => + cases alignment with + | cons rootScope storedSpine spineLength candidateDepth headAlignment + tailAlignment => + cases d2 with + | cons root d2Head spine d2Tail => + cases generationRuns with + | cons generationHead generationTail => + simp only [AddInductive.ConstructorListValidationTrace.universeSemantics, + Bool.and_eq_true] at universeSemantics + intro ctor member + simp only [List.mem_cons] at member + rcases member with rfl | member + · have hctor : ctor ∈ generation.block.ctorPairs := + membership ctor (.head _) + obtain ⟨directCtor, directMember, viewEq⟩ := + generation.viewCtor_ofDirect hctor + have directStage := + (generation.block.checked.direct_anatomy.2.2.2.2.2 + directCtor directMember).2.2 + rw [← generation.block.uvars_eq, + ← generation.block.nparams_eq, + uvarsEq, ← familyNameEq, ← paramsSizeEq] at directStage + have viewEq' : ctor.view = + CheckedCtor.ofDirect Us.length familyName stats.params.size + generation.block.checked.indices.length directCtor := by + simpa only [uvarsEq, paramsSizeEq, + generation.block.sourceType_name_eq, familyNameEq] using viewEq + have stageFields : ∀ q field, + ctor.view.fields[q]? = some field → + VInductDecl.stage3Field Us.length familyName + stats.params.size + generation.block.checked.indices.length q field = true := by + intro q field atIndex + rw [viewEq'] at atIndex + simpa only [Nat.zero_add] using + (VInductDecl.stage3Ctor_eq directStage).2.2.2 q field + (by simpa only [CheckedCtor.ofDirect] using atIndex) + exact generationHead.checkedConstructorWF d3Head + headAlignment d2Head hctor henv typeEnvWF addType + parameterContext parameterWF parameterCtx d3State analyzerState + ngenEq parametersEq indConsts familyTr + familyUnique indexLength resultLevelTr absent unique.1 + universeSemantics.1 stageFields + · exact ih d2Tail generationTail + (fun ctor member => membership ctor (.tail _ member)) unique.2 + universeSemantics.2 ctor member + +/-- The retained D1/D2/D3 producer traces derive the exact analyzer-owned +checked declaration semantics. -/ +theorem StagedNormalizationCandidatePreFamilyInput.checkedWF + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {kernelSource : InductiveType} + {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate source) + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + generation.block.checked.WF env := by + let staged := input.postFamilyInput.universeInput.staged + let validation := staged.family.validation + obtain ⟨parameterΔ, terminalRun, viewTerminal, familyInstantiation, + familyTr, parameterCtx, parameterContext, parameterFVars, + parameterNoBV, parameterWF, terminalVenv, terminalLparams, + terminalViewDefEq, terminalViewUnique, terminalViewLift, + terminalViewEq⟩ := + input.familyContext normalization generation analysis shape + have henv : VEnv.WF env := by + simpa only [normalization.family.type.venv_eq] using + normalization.family.type.contextRun.context.Ewf + have rawWF : normalization.raw.toVConstant.WF env := by + show env.IsType normalization.raw.uvars [] normalization.raw.type + simpa only [normalization.family.uvars_eq] using + normalization.family.type.source_isType_of_terminalSort + validation.terminal_eq + have typeEnvWF : VEnv.WF normalization.family.typeEnv := by + obtain ⟨declarations, declarationsWF⟩ := henv + exact ⟨.axiom normalization.raw.toVConstVal :: declarations, + .decl (.axiom rawWF normalization.family.addType) declarationsWF⟩ + have rawEq : normalization.raw = staged.raw := by + have singletonEq : [normalization.raw] = [staged.raw] := + normalization.raw_types_eq.symm.trans staged.raw_types_eq + injection singletonEq + have typeEnvEq : normalization.family.typeEnv = staged.family.typeEnv := by + exact Option.some.inj <| normalization.family.addType.symm.trans (by + simpa only [rawEq] using staged.family.addInduct.env_add) + obtain ⟨validationRun, validationVenv, validationLparams, + validationVlctx⟩ := + staged.family.validationContextRunFromPre terminalRun terminalVenv + terminalLparams + let d3ContextRun : AddInductive.ConstructorContextRun env Us + candidate.families.singleton.familyType.type.trace.terminalContext := + ⟨terminalRun, terminalVenv, terminalLparams⟩ + let d2ContextRun : AddInductive.ConstructorContextRun + normalization.family.typeEnv Us + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } := + ⟨validationRun, validationVenv.trans typeEnvEq.symm, + validationLparams⟩ + obtain ⟨d3Constructors⟩ := + AddInductive.ConstructorPreFamilyListSemanticRun.nonempty d3ContextRun + input.safety.constructors + obtain ⟨d2Constructors⟩ := + AddInductive.ConstructorPostFamilySemanticListRun.nonempty_of_alignment + d2ContextRun input.postFamilyInput.alignment + normalization.family.constructors + let generationRuns := normalization.constructorGenerationRuns generation + analysis shape + have terminalWF : VLCtx.WF env Us.length + terminalRun.context.vlctx := by + simpa only [terminalVenv, terminalLparams] using terminalRun.context.Δwf + have validationWF : VLCtx.WF normalization.family.typeEnv Us.length + validationRun.context.vlctx := by + simpa only [validationVenv, ← typeEnvEq, validationLparams] using + validationRun.context.Δwf + have viewTerminalWF : VLCtx.WF env Us.length viewTerminal := + (terminalViewDefEq.symm henv.ordered).wf + have d3State : D3FullContextState env normalization.family.typeEnv Us + candidate.families.singleton.familyType.type.trace.terminalContext + parameterΔ parameterΔ terminalRun.context.vlctx viewTerminal .refl + (.skipN .refl generation.block.checked.indices.length) := { + commonWF := parameterWF + commonNoBV := parameterNoBV + fullWF := parameterWF.mono + (VEnv.addConst_le normalization.family.addType) + fullExtension := .refl + actualWF := terminalWF + viewDefEq := terminalViewDefEq + viewUnique := terminalViewUnique + viewExtension := terminalViewLift + freshInvariant := fun _ present => .inl present } + have analyzerState : AnalyzerPostContextState + normalization.family.typeEnv Us parameterΔ validationRun.context.vlctx + viewTerminal (.skipN .refl + generation.block.checked.indices.length) := { + fullWF := parameterWF.mono + (VEnv.addConst_le normalization.family.addType) + postWF := validationWF + viewWF := viewTerminalWF.mono + (VEnv.addConst_le normalization.family.addType) + viewDefEq := by + rw [validationVlctx] + exact (terminalViewDefEq.mono + (VEnv.addConst_le normalization.family.addType)).toFVars + viewExtension := terminalViewLift } + have parametersEq : validation.stats.params.toList = + candidate.families.singleton.familyType.type.trace.parameterList + source.nparams := by + rw [validation.stats_eq] + simp only [CandidateExprTrace.singletonCandidateInductiveStats, + validation, staged, staged.validation_nparams_eq] + have paramsSizeEq : validation.stats.params.size = source.nparams := by + calc + validation.stats.params.size = + validation.stats.params.toList.length := by simp + _ = (candidate.families.singleton.familyType.type.trace.parameterList + source.nparams).length := congrArg List.length parametersEq + _ = generation.block.checked.params.length := + parameterContext.length_eq + _ = source.nparams := + generation.block.checked.direct_anatomy.2.1.trans + generation.block.nparams_eq.symm + have sourceTypeEq : generation.block.sourceType = normalization.raw := by + simpa only [NormalizationCandidateSemanticRun.root] using + normalization.root.sourceType_eq generation + have familyNameEq : generation.block.sourceType.name = + generation.block.checked.type.name := + generation.block.sourceType_name_eq + have familyLparams : + candidate.families.singleton.familyType.type.context.lparams = Us := by + exact normalization.family.type.contextRun.context_lparams.symm.trans + normalization.family.type.lparams_eq + have indConsts : validation.stats.indConsts = + #[.const generation.block.sourceType.name (Us.map .param)] := by + rw [validation.stats_eq] + simp only [CandidateExprTrace.singletonCandidateInductiveStats, + familyLparams] + congr 2 + exact congrArg (fun name => Expr.const name (Us.map .param)) <| + staged.family.name_eq.trans (congrArg + (fun type : VInductiveType => type.name) + (rawEq.symm.trans sourceTypeEq.symm)) + have familyUnique : TrExprS.IsUnique input.safety.familyIndices := + instantiateFamilyParameters_unique + input.safety.familyTranslationUnique + (ConstructorValidation.CandidateParameterContext.parametersUnique + parameterContext) familyInstantiation + have indexLength : generation.block.checked.indices.length = + validation.stats.nindices[0]! := + (stagedIndexCount_eq input normalization generation analysis + shape).symm + have resultLevelTr : VLevel.ofLevel Us validation.stats.resultLevel = + some generation.block.checked.resultLevel := + stagedResultLevel_tr input normalization generation analysis shape + have absent : env.constants generation.block.sourceType.name = none := by + rw [sourceTypeEq] + exact VEnv.addConst_fresh normalization.family.addType + have pairWF := generationRuns.checkedConstructorsWF + d3Constructors d2Constructors (fun _ member => member) henv typeEnvWF + (VEnv.addConst_le normalization.family.addType) parameterContext + parameterWF parameterCtx d3State analyzerState rfl + parametersEq indConsts familyTr familyUnique indexLength resultLevelTr + absent input.safety.constructorTranslationUnique + input.postFamilyInput.universeInput.universeSemantics + normalization.uvars_eq familyNameEq paramsSizeEq + refine ⟨by + simpa only [generation.block.uvars_eq] using + input.familyOnTel normalization generation analysis, ?_⟩ + intro ctor ctorMember + have directMember : + CheckedCtor.ofDirect generation.block.normalization.view.uvars + generation.block.checked.type.name + generation.block.normalization.view.nparams + generation.block.checked.indices.length ctor ∈ + generation.block.checked.constructors := by + rw [generation.block.checked.constructors_eq] + exact List.mem_map.2 ⟨ctor, ctorMember, rfl⟩ + rw [← generation.viewCtors_eq] at directMember + obtain ⟨pair, pairMember, pairViewEq⟩ := List.mem_map.1 directMember + have result := pairWF pair pairMember + rw [pairViewEq] at result + have viewUvarsEq : generation.block.normalization.view.uvars = Us.length := + generation.block.uvars_eq.symm.trans normalization.uvars_eq + have dropBvarRevRange : ∀ (offset count : Nat) (suffix : List VExpr), + (VExpr.bvarRevRange offset count ++ suffix).drop count = suffix := by + intro offset count suffix + induction count with + | zero => rfl + | succ count ih => + simp only [VExpr.bvarRevRange, List.cons_append, + List.drop_succ_cons] + exact ih + rw [← viewUvarsEq, paramsSizeEq, generation.block.nparams_eq, + familyNameEq] at result + simpa only [ + generation.block.nparams_eq, pairViewEq, + CheckedCtor.ofDirect, NormalizedCtor.resultTarget, + VInductDecl.recFieldIdxs, VExpr.appArgs_appN, VExpr.appArgs, + List.append_nil, dropBvarRevRange] using result + +/-- Re-index the derived checked semantics onto the exact normalization view +selected by dependent analysis. -/ +theorem StagedNormalizationCandidatePreFamilyInput.viewDeclWF + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {kernelSource : InductiveType} + {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate source) + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + normalization.root.viewDecl.WF env := by + have checkedWF := input.checkedWF normalization generation analysis shape + have normalizationEq : generation.block.normalization = + normalization.root.normalization := + Normalization.generation?_normalization analysis + have viewEq : generation.block.normalization.view = + normalization.root.viewDecl := by + simpa only [NormalizationCandidateRun.normalization] using + congrArg (fun normalized : Normalization source => normalized.view) + normalizationEq + rw [← viewEq] + exact generation.block.checked.to_declWF generation.block.checked_eq + checkedWF + +/-- Build the semantic generation owner from the retained D1/D2/D3 input, +exact dependent analysis, and the single executable hierarchy shape check. +The analyzer-owned checked semantics are derived from those traces rather +than accepted as a premise. -/ +def GenerationCandidateSemanticRun.ofGenerationShape + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate source) + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + GenerationCandidateSemanticRun normalization generation := by + have familyShape := shape + simp only [NormalizationCandidateSemanticRun.generationShape, + normalizationCandidateGenerationShape, Bool.and_eq_true, + beq_iff_eq] at familyShape + have sourceTypeEq : generation.block.sourceType = normalization.raw := by + simpa only [NormalizationCandidateSemanticRun.root] using + normalization.root.sourceType_eq generation + apply GenerationCandidateSemanticShapeRun.run { + analysis := analysis + checked := input.checkedWF normalization generation analysis shape + family := { + storedSpine := familyShape.1.1 + spineLength_eq := by + simpa only [NormalizedChecked.rawParams, + NormalizedChecked.rawIndices, sourceTypeEq] using familyShape.1.2 } + constructors := + CandidateConstructorSemanticGenerationShapeList.ofCheck + normalization.family.constructors familyShape.2 } + +/-- Construct the produced package at the consolidated generation-shape +boundary without accepting a checked- or view-WF premise. -/ +def NormalizationCandidateSemanticRun.producedPackageOfGenerationShape + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate source) + (generation : GenerationChecked source) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) + (context : AddInductive.Context) + (nparams numNested : Nat) (isUnsafe : Bool) + (produced : + AddInductive.buildNormalizationCandidate nparams + [kernelSource] numNested isUnsafe context = .ok candidate) : + ProducedGenerationCandidatePackage env Us := + (GenerationCandidateSemanticRun.ofGenerationShape input normalization + generation analysis shape).producedPackage context nparams numNested + isUnsafe produced + +/-- Interpret one successful shape-producing outer result using the matching +retained D1/D2/D3 semantic input. -/ +def ProducedGenerationShapeCandidate.producedPackage + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {raw : VInductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} + (producedCandidate : ProducedGenerationShapeCandidate source raw + kernelSource numNested isUnsafe context) + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us producedCandidate.candidate source) + (normalization : NormalizationCandidateSemanticRun env Us + producedCandidate.candidate source) + (rawEq : raw = normalization.raw) + (generation : GenerationChecked source) + (analysis : normalization.root.normalization.generation? = + some generation) : + ProducedGenerationCandidatePackage env Us := + normalization.producedPackageOfGenerationShape input generation analysis + (by + simpa only [NormalizationCandidateSemanticRun.generationShape, + rawEq] using producedCandidate.shape) + context source.nparams numNested isUnsafe producedCandidate.produced + +/-- Projection-free D3 candidates determine one exact Theory constructor +view at every source position, independently of the existential checker run +that selected it. -/ +theorem CandidateConstructorSemanticListRun.roots_views_eq + {env : VEnv} {Us : List Name} {constructors : List Constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors} + {raws : List VConstVal} + (unique : candidates.ViewTranslationUnique) + (left right : CandidateConstructorSemanticListRun env Us candidates raws) : + left.roots.views = right.roots.views := by + induction left with + | nil => + cases right + rfl + | @cons constructor constructors candidate candidates raw raws head tail ih => + cases right with + | cons otherHead otherTail => + obtain ⟨_, headRecursive⟩ := head.type.recursive + obtain ⟨_, otherHeadRecursive⟩ := otherHead.type.recursive + have headViewEq : head.type.view = otherHead.type.view := + TrExprS.unique unique.1.view + (headRecursive.view_tr_strict unique.1) + (otherHeadRecursive.view_tr_strict unique.1) + have tailViewsEq := ih unique.2 otherTail + simp only [CandidateConstructorSemanticListRun.roots, + CandidateConstructorListRun.views, + CandidateConstructorSemanticRun.root, + CandidateConstructorRun.view] + rw [headViewEq, tailViewsEq] + +/-- Transport the positional uniqueness theorem across the uniquely produced +post-family environment and raw constructor list. -/ +theorem CandidateConstructorSemanticListRun.roots_views_eq_of_eq + {leftEnv rightEnv : VEnv} {Us : List Name} + {constructors : List Constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor constructors} + {leftRaws rightRaws : List VConstVal} + (unique : candidates.ViewTranslationUnique) + (envEq : leftEnv = rightEnv) (rawsEq : leftRaws = rightRaws) + (left : CandidateConstructorSemanticListRun leftEnv Us candidates leftRaws) + (right : CandidateConstructorSemanticListRun rightEnv Us candidates + rightRaws) : + left.roots.views = right.roots.views := by + subst rightEnv + subst rightRaws + exact left.roots_views_eq unique right + +private theorem candidateFamilyView_eq_of_components + {rawLeft rawRight : VInductiveType} + {typeLeft typeRight : VExpr} + {ctorsLeft ctorsRight : List VConstVal} + (rawEq : rawLeft = rawRight) (typeEq : typeLeft = typeRight) + (ctorsEq : ctorsLeft = ctorsRight) : + ({ rawLeft with type := typeLeft, ctors := ctorsLeft } : + VInductiveType) = + { rawRight with type := typeRight, ctors := ctorsRight } := by + cases rawEq + cases typeEq + cases ctorsEq + rfl + +private theorem Normalization.eq_of_view_eq + {source : VInductDecl} {left right : Normalization source} + (viewEq : left.view = right.view) : left = right := by + cases left with + | mk leftView leftShape => + cases right with + | mk rightView rightShape => + cases viewEq + rfl + +/-- The D3 projection-free safety gate makes the complete normalization +selected by the staged semantic owner syntactically unique. In particular, +fixtures may state dependent analysis once for the known normalization and +transport it to whichever semantic hierarchy `input.exists` selects. -/ +theorem StagedNormalizationCandidatePreFamilyInput.normalization_eq + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate source) + (left right : NormalizationCandidateSemanticRun env Us candidate source) : + left.root.normalization = right.root.normalization := by + have rawEq : left.raw = right.raw := by + have singletonEq := left.raw_types_eq.symm.trans right.raw_types_eq + injection singletonEq + have typeEnvEq : left.family.typeEnv = right.family.typeEnv := by + exact Option.some.inj <| left.family.addType.symm.trans <| by + simpa only [rawEq] using right.family.addType + have familyViewEq : left.family.type.view = right.family.type.view := by + obtain ⟨_, leftRecursive⟩ := left.family.type.recursive + obtain ⟨_, rightRecursive⟩ := right.family.type.recursive + exact TrExprS.unique input.safety.familyTranslationUnique + (leftRecursive.view_tr_strict <| + AddInductive.CandidateExprTrace.viewTranslationUnique_sound _ <| by + rw [AddInductive.CandidateExprTrace.viewTranslationUnique_eq] + have gate := input.safety.translationUnique + simp only [Bool.and_eq_true] at gate + exact gate.1) + (rightRecursive.view_tr_strict <| + AddInductive.CandidateExprTrace.viewTranslationUnique_sound _ <| by + rw [AddInductive.CandidateExprTrace.viewTranslationUnique_eq] + have gate := input.safety.translationUnique + simp only [Bool.and_eq_true] at gate + exact gate.1) + have constructorViewsEq : left.family.constructors.roots.views = + right.family.constructors.roots.views := by + exact left.family.constructors.roots_views_eq_of_eq + input.safety.constructorTranslationUnique typeEnvEq + (congrArg VInductiveType.ctors rawEq) right.family.constructors + have familyEq : left.family.root.view = right.family.root.view := by + exact candidateFamilyView_eq_of_components rawEq familyViewEq + constructorViewsEq + have viewDeclEq : left.root.viewDecl = right.root.viewDecl := by + simp only [NormalizationCandidateSemanticRun.root, + NormalizationCandidateRun.viewDecl] + rw [familyEq] + exact Normalization.eq_of_view_eq viewDeclEq + +/-- Choice-free constructor-root interpretation: the semantic root's view is +computed by the deterministic translator under the constructor's strict-view +uniqueness certificate. -/ +def CandidateConstructorSemanticInput.semanticOfUnique + {env : VEnv} {Us : List Name} {source : Constructor} + {candidate : AddInductive.CandidateConstructor source} {raw : VConstVal} + (input : CandidateConstructorSemanticInput env Us candidate raw) + (unique : TypeChecker.CandidateExprTraceViewIsUnique + candidate.type.trace) : + CandidateConstructorSemanticRun env Us candidate raw where + name_eq := input.name_eq + uvars_eq := input.uvars_eq + type := input.type.semanticOfUnique unique + +/-- Choice-free source-ordered interpretation of a complete constructor list +under its source-ordered strict-view certificate. -/ +def CandidateConstructorSemanticListInput.semanticOfUnique + {env : VEnv} {Us : List Name} : + {sources : List Constructor} → + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor sources} → + {raws : List VConstVal} → + CandidateConstructorSemanticListInput env Us candidates raws → + candidates.ViewTranslationUnique → + CandidateConstructorSemanticListRun env Us candidates raws + | _, _, _, .nil, _ => .nil + | _, _, _, .cons head tail, unique => + .cons (head.semanticOfUnique unique.1) (tail.semanticOfUnique unique.2) + +/-- Choice-free family interpretation: the family type and every +post-insertion constructor view are computed by the deterministic +translator. -/ +def CandidateFamilySemanticInput.semanticOfUnique + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.CandidateFamily source} {raw : VInductiveType} + (input : CandidateFamilySemanticInput env Us candidate raw) + (uniqueType : TypeChecker.CandidateExprTraceViewIsUnique + candidate.familyType.type.trace) + (uniqueCtors : candidate.constructors.ViewTranslationUnique) : + CandidateFamilySemanticRun env Us candidate raw where + name_eq := input.name_eq + uvars_eq := input.uvars_eq + type := input.type.semanticOfUnique uniqueType + typeEnv := input.typeEnv + addType := input.addType + constructors := input.constructors.semanticOfUnique uniqueCtors + +/-- Choice-free singleton semantic hierarchy: every normalized Theory view +in the family and constructor list is computed by the deterministic +translator, with `Nonempty` interpretation transferred onto the computed +values. -/ +def NormalizationCandidateSemanticInput.semanticOfUnique + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : NormalizationCandidateSemanticInput env Us candidate rawDecl) + (uniqueType : TypeChecker.CandidateExprTraceViewIsUnique + candidate.families.singleton.familyType.type.trace) + (uniqueCtors : + candidate.families.singleton.constructors.ViewTranslationUnique) : + NormalizationCandidateSemanticRun env Us candidate rawDecl where + raw := input.raw + raw_types_eq := input.raw_types_eq + uvars_eq := input.uvars_eq + family := input.family.semanticOfUnique uniqueType uniqueCtors + +/-- The executable D3 gate's uniqueness Bool supplies the family strict-view +certificate consumed by the choice-free semantic assembly. -/ +theorem StagedNormalizationCandidatePreFamilyInput.familyViewUnique + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl) : + TypeChecker.CandidateExprTraceViewIsUnique + candidate.families.singleton.familyType.type.trace := by + have h := input.safety.translationUnique + simp only [Bool.and_eq_true] at h + exact AddInductive.CandidateExprTrace.viewTranslationUnique_sound _ + ((AddInductive.CandidateExprTrace.viewTranslationUnique_eq _).trans h.1) + +/-- The executable D3 gate's uniqueness Bool likewise supplies the +constructor-list strict-view certificate. -/ +theorem StagedNormalizationCandidatePreFamilyInput.constructorViewsUnique + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us candidate rawDecl) : + candidate.families.singleton.constructors.ViewTranslationUnique := by + have h := input.safety.translationUnique + simp only [Bool.and_eq_true] at h + exact AddInductive.CandidateList.viewTranslationUnique_sound _ h.2 + +/-- Exact, source-indexed refinement of the public producer package. + +The public `ProducedGenerationCandidatePackage` deliberately erases its +dependent source, normalization, and generation indices. Keeping those +indices in this closure result lets clients choose the `Nonempty` witness and +still recover a package whose projections reduce to the requested source and +generation. -/ +structure ExactProducedGenerationCandidatePackage + {source : VInductDecl} {raw : VInductiveType} + {kernelSource : InductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} + (env : VEnv) (Us : List Name) + (producedCandidate : ProducedGenerationShapeCandidate source raw + kernelSource numNested isUnsafe context) + (generation : GenerationChecked source) where + normalization : NormalizationCandidateSemanticRun env Us + producedCandidate.candidate source + raw_eq : raw = normalization.raw + semantic : GenerationCandidateSemanticRun normalization generation + +/-- Erase only the exact dependent indices retained by the generic closure. +The ordinary producer equation is copied from the same strengthened producer +value; it contributes provenance, not semantic authority. -/ +def ExactProducedGenerationCandidatePackage.package + {source : VInductDecl} {raw : VInductiveType} + {kernelSource : InductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} {env : VEnv} {Us : List Name} + {producedCandidate : ProducedGenerationShapeCandidate source raw + kernelSource numNested isUnsafe context} + {generation : GenerationChecked source} + (exact : ExactProducedGenerationCandidatePackage env Us + producedCandidate generation) : + ProducedGenerationCandidatePackage env Us := + exact.semantic.producedPackage context source.nparams numNested isUnsafe + producedCandidate.produced + +/-- Close one strengthened singleton producer choice-free. The semantic +hierarchy is computed by the deterministic translator under the executable +D3 strict-view gate carried by the staged owner, so the retained package is +data rather than a `Classical.choice` selection from `Nonempty`. -/ +def ProducedGenerationShapeCandidate.exactProducedPackage + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {raw : VInductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} + (producedCandidate : ProducedGenerationShapeCandidate source raw + kernelSource numNested isUnsafe context) + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us producedCandidate.candidate source) + (rawOwnerEq : raw = + input.postFamilyInput.universeInput.staged.raw) + (generation : GenerationChecked source) + (analysis : ∀ normalization : NormalizationCandidateSemanticRun env Us + producedCandidate.candidate source, + normalization.root.normalization.generation? = some generation) : + ExactProducedGenerationCandidatePackage env Us + producedCandidate generation := + let normalization := + input.postFamilyInput.universeInput.staged.semanticInput.semanticOfUnique + input.familyViewUnique input.constructorViewsUnique + { normalization := normalization + raw_eq := rawOwnerEq + semantic := GenerationCandidateSemanticRun.ofGenerationShape input + normalization generation (analysis normalization) + (by + have hraw : normalization.raw = + input.postFamilyInput.universeInput.staged.raw := rfl + simpa only [NormalizationCandidateSemanticRun.generationShape, + rawOwnerEq, hraw] using producedCandidate.shape) } + +/-- Close one strengthened singleton producer from the staged D1--D4 owner +without choosing a semantic hierarchy at the API boundary, while retaining +the exact dependent source and generation indices needed by consumers. -/ +theorem ProducedGenerationShapeCandidate.exactProducedPackage_nonempty + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {raw : VInductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} + (producedCandidate : ProducedGenerationShapeCandidate source raw + kernelSource numNested isUnsafe context) + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us producedCandidate.candidate source) + (rawOwnerEq : raw = + input.postFamilyInput.universeInput.staged.raw) + (generation : GenerationChecked source) + (analysis : ∀ normalization : NormalizationCandidateSemanticRun env Us + producedCandidate.candidate source, + normalization.root.normalization.generation? = some generation) : + Nonempty (ExactProducedGenerationCandidatePackage env Us + producedCandidate generation) := by + obtain ⟨preFamily⟩ := input.exists + let normalization := preFamily.postFamily.produced.semantic + have semanticRawEq : normalization.raw = + input.postFamilyInput.universeInput.staged.raw := by + have singletonEq := normalization.raw_types_eq.symm.trans + input.postFamilyInput.universeInput.staged.raw_types_eq + injection singletonEq + have rawEq := rawOwnerEq.trans semanticRawEq.symm + let semantic := GenerationCandidateSemanticRun.ofGenerationShape input + normalization generation (analysis normalization) (by + simpa only [NormalizationCandidateSemanticRun.generationShape, + rawEq] using producedCandidate.shape) + exact ⟨{ normalization, raw_eq := rawEq, semantic }⟩ + +/-- Close one strengthened singleton producer from the staged D1--D4 owner +without choosing a semantic hierarchy at the API boundary. + +`analysis` is exact for every checker-selected semantic normalization owned by +the staged input. The proof eliminates `input.exists` only into `Nonempty`, +then applies D4 to that exact selected normalization. The ordinary producer +equation and the independent generation-shape gate remain the two fields of +`producedCandidate`; neither supplies Theory meaning by itself. -/ +theorem ProducedGenerationShapeCandidate.producedPackage_nonempty + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {raw : VInductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} + (producedCandidate : ProducedGenerationShapeCandidate source raw + kernelSource numNested isUnsafe context) + (input : StagedNormalizationCandidatePreFamilyInput familyContext + constructorContext env Us producedCandidate.candidate source) + (rawOwnerEq : raw = + input.postFamilyInput.universeInput.staged.raw) + (generation : GenerationChecked source) + (analysis : ∀ normalization : NormalizationCandidateSemanticRun env Us + producedCandidate.candidate source, + normalization.root.normalization.generation? = some generation) : + Nonempty (ProducedGenerationCandidatePackage env Us) := by + obtain ⟨exact⟩ := producedCandidate.exactProducedPackage_nonempty input + rawOwnerEq generation analysis + exact ⟨exact.package⟩ + +end VInductDecl + +namespace VInductDecl + +/- The D4 closure roots intentionally inherit the exact transitional Verify +axiom set already present in the staged semantic inputs. -/ +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidatePreFamilyInput.checkedWF [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidatePreFamilyInput.viewDeclWF [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateSemanticRun.ofGenerationShape [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateSemanticRun.producedPackageOfGenerationShape [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.ProducedGenerationShapeCandidate.producedPackage [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.ProducedGenerationShapeCandidate.exactProducedPackage_nonempty [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidatePreFamilyInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidatePostFamilyInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +/- The wrapper projections expose their exact existing Verify closure. The +new universe bridge itself remains separately guarded above; staging does not +hide the transitional dependencies already present in the semantic owner. -/ +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidateUniverseInput.semanticValidation [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidateUniverseInput.universeSemantics [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidateUniverseInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +end VInductDecl +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean b/Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean new file mode 100644 index 000000000..1692e8052 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean @@ -0,0 +1,358 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.ConstructorValidityFixtures +import Ix.Theory.Named.Verify.Environment.InductiveFixtures + +/-! +# Spec-05 constructor-validity differential matrix + +The positive half quotes real Lean metadata, runs the ordinary normalization +candidate producer, then runs both strengthened constructor gates at their +actual pre-family and post-family environments. The negative half pairs each failed +source declaration in `Theory.ConstructorValidityFixtures` with hand-built +metadata at the nearest ordinary-producer phase. +-/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +/-! ## Actual positive metadata -/ + +def constructorValidityMatrixInfo : ConstantInfo := + kernelInductInfo% ConstructorValidityMatrix + +def constructorValidityMatrixMkInfo : ConstantInfo := + kernelCtorInfo% ConstructorValidityMatrix.mk + +def constructorValidityMatrixRecInfo : ConstantInfo := + kernelRecInfo% ConstructorValidityMatrix.rec + +def constructorValidityMatrixKernelRuleRhs : VExpr := + kernelRecRuleRhs% ConstructorValidityMatrix.rec 0 + +def constructorValidityMatrixKernelCtor : Constructor where + name := constructorValidityMatrixMkInfo.name + type := constructorValidityMatrixMkInfo.type + +def constructorValidityMatrixKernelType : InductiveType where + name := constructorValidityMatrixInfo.name + type := constructorValidityMatrixInfo.type + ctors := [constructorValidityMatrixKernelCtor] + +def propRecursiveBoundaryInfo : ConstantInfo := + kernelInductInfo% PropRecursiveBoundary + +def propRecursiveBoundaryMkInfo : ConstantInfo := + kernelCtorInfo% PropRecursiveBoundary.mk + +def propRecursiveBoundaryRecInfo : ConstantInfo := + kernelRecInfo% PropRecursiveBoundary.rec + +def propRecursiveBoundaryKernelRuleRhs : VExpr := + kernelRecRuleRhs% PropRecursiveBoundary.rec 0 + +def propRecursiveBoundaryKernelCtor : Constructor where + name := propRecursiveBoundaryMkInfo.name + type := propRecursiveBoundaryMkInfo.type + +def propRecursiveBoundaryKernelType : InductiveType where + name := propRecursiveBoundaryInfo.name + type := propRecursiveBoundaryInfo.type + ctors := [propRecursiveBoundaryKernelCtor] + +theorem constructorValidityMatrix_kernel_shape : + (match constructorValidityMatrixInfo with + | .inductInfo info => (info.numParams, info.numIndices) + | _ => (0, 0)) = (2, 0) ∧ + (match constructorValidityMatrixMkInfo with + | .ctorInfo info => info.numFields + | _ => 0) = 6 ∧ + (match constructorValidityMatrixRecInfo with + | .recInfo info => + (info.numParams, info.numIndices, info.numMotives, + info.numMinors, info.rules.length) + | _ => (0, 0, 0, 0, 0)) = (2, 0, 1, 1, 1) := by + exact ⟨rfl, rfl, rfl⟩ + +theorem constructorValidityMatrix_recursive_positions_exact : + constructorValidityMatrixChecked.constructors[0].recursive.map + (fun position => (position.fieldIndex, position.binders.length)) = + [(2, 0), (3, 1)] := rfl + +theorem constructorValidityMatrix_kernel_rule_exact : + constructorValidityMatrixKernelRuleRhs = + constructorValidityMatrixGenerationChecked.generatedRules[0].rhs := rfl + +theorem propRecursiveBoundary_kernel_shape : + (match propRecursiveBoundaryInfo with + | .inductInfo info => (info.numParams, info.numIndices) + | _ => (0, 0)) = (1, 1) ∧ + (match propRecursiveBoundaryMkInfo with + | .ctorInfo info => info.numFields + | _ => 0) = 2 ∧ + (match propRecursiveBoundaryRecInfo with + | .recInfo info => + (info.numParams, info.numIndices, info.numMotives, + info.numMinors, info.rules.length) + | _ => (0, 0, 0, 0, 0)) = (1, 1, 1, 1, 1) := by + exact ⟨rfl, rfl, rfl⟩ + +theorem propRecursiveBoundary_recursive_positions_exact : + propRecursiveBoundaryChecked.constructors[0].recursive.map + (fun position => (position.fieldIndex, position.binders.length)) = + [(1, 1)] := rfl + +theorem propRecursiveBoundary_kernel_rule_exact : + propRecursiveBoundaryKernelRuleRhs = + propRecursiveBoundaryGenerationChecked.generatedRules[0].rhs := rfl + +/-! ## Positive ordinary and strengthened gates -/ + +def constructorValidityMatrixContext : AddInductive.Context where + env := Kernel.Environment.ofConstants `_constructorValidityMatrix + ({} : ConstMap) + lparams := [`u] + safety := .safe + allowPrimitive := false + +def propRecursiveBoundaryContext : AddInductive.Context where + env := Kernel.Environment.ofConstants `_propRecursiveBoundary + ({} : ConstMap) + lparams := [`u] + safety := .safe + allowPrimitive := false + +def singletonCandidateExact (nparams : Nat) (source : InductiveType) + (context : AddInductive.Context) : Bool := + match AddInductive.buildNormalizationCandidate nparams [source] 0 false + context with + | .error _ => false + | .ok candidate => + candidate.families.singleton.familyType.type.view.equal source.type && + candidate.families.singleton.constructors.toList + (fun _ constructor => constructor.type.view) == + source.ctors.map (fun constructor => constructor.type) + +def singletonPreFamilyAccepted (nparams : Nat) (source : InductiveType) + (context : AddInductive.Context) : Bool := + match AddInductive.buildNormalizationCandidate nparams [source] 0 false + context with + | .error _ => false + | .ok candidate => + match AddInductive.checkInductiveTypes nparams #[source] + (fun stats => + AddInductive.checkConstructorPreFamilySafety stats + candidate.families.singleton.familyType.type.view + candidate.families.singleton.constructors) context with + | .ok _ => true + | .error _ => false + +def singletonUniverseAccepted (nparams : Nat) (source : InductiveType) + (context : AddInductive.Context) : Bool := + match AddInductive.checkInductiveTypes nparams #[source] + (fun stats => do + let familyEnv ← AddInductive.declareInductiveTypes stats nparams + #[source] 0 false + AddInductive.withEnv familyEnv do + AddInductive.checkConstructorUniverseListSemantics stats + source.ctors) context with + | .ok _ => true + | .error _ => false + +#guard singletonCandidateExact 2 constructorValidityMatrixKernelType + constructorValidityMatrixContext + +#guard singletonPreFamilyAccepted 2 constructorValidityMatrixKernelType + constructorValidityMatrixContext + +#guard singletonUniverseAccepted 2 constructorValidityMatrixKernelType + constructorValidityMatrixContext + +#guard singletonCandidateExact 1 propRecursiveBoundaryKernelType + propRecursiveBoundaryContext + +#guard singletonPreFamilyAccepted 1 propRecursiveBoundaryKernelType + propRecursiveBoundaryContext + +#guard singletonUniverseAccepted 1 propRecursiveBoundaryKernelType + propRecursiveBoundaryContext + +/-! ## Matching ordinary-producer rejections -/ + +def spec05TypeBoxName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05TypeBox + +def spec05ProofBoxName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05ProofBox + +def spec05DepProofBoxName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05DepProofBox + +def spec05TypeBoxInfo : ConstantInfo := .axiomInfo { + name := spec05TypeBoxName + levelParams := [] + type := .forallE `α (.sort (.succ .zero)) + (.sort (.succ .zero)) .default + isUnsafe := false } + +def spec05ProofBoxInfo : ConstantInfo := .axiomInfo { + name := spec05ProofBoxName + levelParams := [] + type := .forallE `α (.sort (.succ .zero)) (.sort .zero) .default + isUnsafe := false } + +def spec05DepProofBoxInfo : ConstantInfo := .axiomInfo { + name := spec05DepProofBoxName + levelParams := [] + type := .forallE `α (.sort (.succ .zero)) + (.forallE `value (.bvar 0) (.sort .zero) .default) .implicit + isUnsafe := false } + +def spec05NegativeMap : ConstMap := + ((({} : ConstMap).insert spec05TypeBoxName spec05TypeBoxInfo).insert + spec05ProofBoxName spec05ProofBoxInfo).insert + spec05DepProofBoxName spec05DepProofBoxInfo + +def spec05NegativeContext : AddInductive.Context where + env := Kernel.Environment.ofConstants `_spec05Negative spec05NegativeMap + lparams := [] + safety := .safe + allowPrimitive := false + +def spec05UnsafeNegativeContext : AddInductive.Context := + { spec05NegativeContext with safety := .unsafe } + +def spec05NegativeType (name ctorName : Name) (ctorType : Expr) : + InductiveType where + name := name + type := .sort (.succ .zero) + ctors := [{ name := ctorName, type := ctorType }] + +def spec05NestedNegativeName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05NestedNegative + +def spec05NestedNegativeMkName : Name := + .str spec05NestedNegativeName "mk" + +def spec05NestedNegativeConst : Expr := + .const spec05NestedNegativeName [] + +def spec05NestedNegativeField : Expr := + .forallE `_ + (.forallE `_ spec05NestedNegativeConst (.sort .zero) .default) + spec05NestedNegativeConst .default + +def spec05NestedNegativeType : InductiveType := + spec05NegativeType spec05NestedNegativeName spec05NestedNegativeMkName + (.forallE `field spec05NestedNegativeField + spec05NestedNegativeConst .default) + +def spec05FamilyNonrecursiveName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05FamilyNonrecursive + +def spec05FamilyNonrecursiveMkName : Name := + .str spec05FamilyNonrecursiveName "mk" + +def spec05FamilyNonrecursiveConst : Expr := + .const spec05FamilyNonrecursiveName [] + +def spec05FamilyNonrecursiveType : InductiveType := + spec05NegativeType spec05FamilyNonrecursiveName + spec05FamilyNonrecursiveMkName + (.forallE `field + (.app (.const spec05TypeBoxName []) spec05FamilyNonrecursiveConst) + spec05FamilyNonrecursiveConst .default) + +def spec05FamilyProofName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05FamilyProof + +def spec05FamilyProofMkName : Name := + .str spec05FamilyProofName "mk" + +def spec05FamilyProofConst : Expr := + .const spec05FamilyProofName [] + +def spec05FamilyProofType : InductiveType := + spec05NegativeType spec05FamilyProofName spec05FamilyProofMkName + (.forallE `proof + (.app (.const spec05ProofBoxName []) spec05FamilyProofConst) + spec05FamilyProofConst .default) + +def spec05RecursiveDependencyName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05RecursiveDependency + +def spec05RecursiveDependencyMkName : Name := + .str spec05RecursiveDependencyName "mk" + +def spec05RecursiveDependencyConst : Expr := + .const spec05RecursiveDependencyName [] + +def spec05RecursiveDependencyProof : Expr := + .app (.app (.const spec05DepProofBoxName []) + spec05RecursiveDependencyConst) (.bvar 0) + +def spec05RecursiveDependencyType : InductiveType := + spec05NegativeType spec05RecursiveDependencyName + spec05RecursiveDependencyMkName + (.forallE `recursive spec05RecursiveDependencyConst + (.forallE `proof spec05RecursiveDependencyProof + spec05RecursiveDependencyConst .default) .default) + +def spec05UniverseRejectName : Name := + `Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05UniverseReject + +def spec05UniverseRejectMkName : Name := + .str spec05UniverseRejectName "mk" + +def spec05UniverseRejectConst : Expr := + .const spec05UniverseRejectName [] + +def spec05UniverseRejectType : InductiveType := + spec05NegativeType spec05UniverseRejectName spec05UniverseRejectMkName + (.forallE `α (.sort (.succ .zero)) spec05UniverseRejectConst .default) + +def spec05CandidateError (source : InductiveType) : Option String := + match AddInductive.buildNormalizationCandidate 0 [source] 0 false + spec05NegativeContext with + | .error (.other message) => some message + | _ => none + +#guard spec05CandidateError spec05NestedNegativeType = some + "arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05NestedNegative.mk' has a non positive occurrence of the datatypes being declared" + +#guard spec05CandidateError spec05FamilyNonrecursiveType = some + "arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05FamilyNonrecursive.mk' has a non valid occurrence of the datatypes being declared" + +#guard spec05CandidateError spec05FamilyProofType = some + "arg #1 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05FamilyProof.mk' has a non valid occurrence of the datatypes being declared" + +#guard spec05CandidateError spec05RecursiveDependencyType = some + "arg #2 of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05RecursiveDependency.mk' has a non valid occurrence of the datatypes being declared" + +#guard spec05CandidateError spec05UniverseRejectType = some + "universe level of type_of(arg #1) of 'Ix.Theory.Named.InductiveFixtures.KernelDifferential.Spec05UniverseReject.mk' is too big for the corresponding inductive datatype" + +def spec05RecursiveDependencyPreFamilyError : Option String := + match AddInductive.buildNormalizationCandidate 0 + [spec05RecursiveDependencyType] 0 true spec05UnsafeNegativeContext with + | .error _ => none + | .ok candidate => + match AddInductive.checkInductiveTypes 0 + #[spec05RecursiveDependencyType] + (fun stats => + AddInductive.checkConstructorPreFamilySafety stats + candidate.families.singleton.familyType.type.view + candidate.families.singleton.constructors) + spec05UnsafeNegativeContext with + | .error (.other message) => some message + | _ => none + +#guard spec05RecursiveDependencyPreFamilyError = + some "constructor depends on an omitted recursive local" + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/Elimination.lean b/Ix/Theory/Named/Verify/Environment/Elimination.lean new file mode 100644 index 000000000..6ab6559b4 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/Elimination.lean @@ -0,0 +1,244 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Reference.Inductive.EliminationTrace +import Ix.Theory.Named.Inductive + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Lean hiding Environment Exception + +namespace AddInductive + +/-- Compatibility name for Theory's presentation of the Boolean returned by +the ordinary large-eliminator checker. -/ +@[deprecated VInductDecl.ElimMode.ofBool (since := "2026-08-11")] +abbrev checkerElimMode : Bool → VInductDecl.ElimMode := + VInductDecl.ElimMode.ofBool + +/-- Lightweight alignment for an exact `getElimLevel` execution when the +normalization statistics are already pinned independently. This is useful for +the never-zero branch, which returns before inspecting any constructor. -/ +structure CheckerElimLevelRun + {source : VInductDecl} (generation : VInductDecl.GenerationChecked source) + {stats : InductiveStats} {indTypes : Array InductiveType} + {context : Context} + (execution : ElimLevelExecution stats indTypes context) : Type where + sourceUvars_eq : source.uvars = context.lparams.length + mode_eq : generation.elimination = + VInductDecl.ElimMode.ofBool execution.large.result + recUvars_eq : generation.recUvars = + (getRecLevelParams execution.level context.lparams).length + recLevels_eq : + (getRecLevels execution.level stats.levels).mapM + (VLevel.ofLevel (getRecLevelParams execution.level context.lparams)) = + some generation.recLevels + +namespace CheckerElimLevelRun + +/-- Decide the complete mode and level-layout alignment from the retained +ordinary execution. -/ +def build? + {source : VInductDecl} (generation : VInductDecl.GenerationChecked source) + {stats : InductiveStats} {indTypes : Array InductiveType} + {context : Context} + (execution : ElimLevelExecution stats indTypes context) : + Option (CheckerElimLevelRun generation execution) := do + if huvars : source.uvars = context.lparams.length then + if hmode : generation.elimination = + VInductDecl.ElimMode.ofBool execution.large.result then + if hrecUvars : generation.recUvars = + (getRecLevelParams execution.level context.lparams).length then + if hlevels : + (getRecLevels execution.level stats.levels).mapM + (VLevel.ofLevel + (getRecLevelParams execution.level context.lparams)) = + some generation.recLevels then + some { + sourceUvars_eq := huvars + mode_eq := hmode + recUvars_eq := hrecUvars + recLevels_eq := hlevels } + else none + else none + else none + else none + +theorem large_result_iff + (run : CheckerElimLevelRun generation execution) : + execution.large.result = true ↔ + generation.elimination = VInductDecl.ElimMode.large := by + cases hresult : execution.large.result with + | false => + have hmode : generation.elimination = VInductDecl.ElimMode.small := by + simpa [hresult] using run.mode_eq + simp [hmode] + | true => + have hmode : generation.elimination = VInductDecl.ElimMode.large := by + simpa [hresult] using run.mode_eq + simp [hmode] + +theorem small_result_iff + (run : CheckerElimLevelRun generation execution) : + execution.large.result = false ↔ + generation.elimination = VInductDecl.ElimMode.small := by + cases hresult : execution.large.result with + | false => + have hmode : generation.elimination = VInductDecl.ElimMode.small := by + simpa [hresult] using run.mode_eq + simp [hmode] + | true => + have hmode : generation.elimination = VInductDecl.ElimMode.large := by + simpa [hresult] using run.mode_eq + simp [hmode] + +end CheckerElimLevelRun + +/-- Exact alignment between the ordinary K-target execution and the Boolean +retained by Theory generation. This flag is certified independently of the +elimination-mode decision. -/ +structure CheckerKTargetRun + {source : VInductDecl} (generation : VInductDecl.GenerationChecked source) + {stats : InductiveStats} {indTypes : Array InductiveType} + {context : Context} + (execution : KTargetExecution stats indTypes context) : Type where + result_eq : generation.kTarget = execution.result + +namespace CheckerKTargetRun + +def build? + {source : VInductDecl} (generation : VInductDecl.GenerationChecked source) + {stats : InductiveStats} {indTypes : Array InductiveType} + {context : Context} + (execution : KTargetExecution stats indTypes context) : + Option (CheckerKTargetRun generation execution) := + if h : generation.kTarget = execution.result then + some ⟨h⟩ + else + none + +theorem result_true_iff + (run : CheckerKTargetRun generation execution) : + execution.result = true ↔ generation.kTarget = true := by + rw [run.result_eq] + +theorem result_false_iff + (run : CheckerKTargetRun generation execution) : + execution.result = false ↔ generation.kTarget = false := by + rw [run.result_eq] + +end CheckerKTargetRun + +/-- Executable alignment between an exact ordinary elimination run and the +mode/K-target/universe layout consumed by one Theory generation artifact. + +The operational side owns the real `ensureType` observations, selected fresh +level name, K-target decision, recursive-call levels, and stored metadata +parameter order. The equations below are checked data, so a Theory generation +whose mode, K flag, or numeric universe layout disagrees with that run cannot +inhabit this record. -/ +structure CheckerEliminationRun + {source : VInductDecl} (generation : VInductDecl.GenerationChecked source) + {nparams : Nat} {types : List InductiveType} + {numNested : Nat} {isUnsafe : Bool} {candidateContext : Context} + (execution : NormalizationEliminationExecution nparams types numNested + isUnsafe candidateContext) : Type where + nparams_eq : nparams = source.nparams + sourceUvars_eq : source.uvars = + execution.normalization.validationContext.lparams.length + mode_eq : generation.elimination = + VInductDecl.ElimMode.ofBool execution.elimination.large.result + kTarget_eq : generation.kTarget = execution.kTarget.result + recUvars_eq : generation.recUvars = execution.recLevelParams.length + recLevels_eq : execution.recLevels.mapM + (VLevel.ofLevel execution.recLevelParams) = some generation.recLevels + +namespace CheckerEliminationRun + +/-- Build the alignment by deciding every equality rather than asking a +fixture or caller to supply a mode or level permutation. -/ +def build? + {source : VInductDecl} (generation : VInductDecl.GenerationChecked source) + {nparams : Nat} {types : List InductiveType} + {numNested : Nat} {isUnsafe : Bool} {candidateContext : Context} + (execution : NormalizationEliminationExecution nparams types numNested + isUnsafe candidateContext) : + Option (CheckerEliminationRun generation execution) := do + if hparams : nparams = source.nparams then + if huvars : source.uvars = + execution.normalization.validationContext.lparams.length then + if hmode : generation.elimination = + VInductDecl.ElimMode.ofBool execution.elimination.large.result then + if hkTarget : generation.kTarget = execution.kTarget.result then + if hrecUvars : generation.recUvars = + execution.recLevelParams.length then + if hlevels : execution.recLevels.mapM + (VLevel.ofLevel execution.recLevelParams) = + some generation.recLevels then + some { + nparams_eq := hparams + sourceUvars_eq := huvars + mode_eq := hmode + kTarget_eq := hkTarget + recUvars_eq := hrecUvars + recLevels_eq := hlevels } + else none + else none + else none + else none + else none + else none + +theorem large_result_iff + (run : CheckerEliminationRun generation execution) : + execution.elimination.large.result = true ↔ + generation.elimination = VInductDecl.ElimMode.large := by + cases hresult : execution.elimination.large.result with + | false => + have hmode : generation.elimination = VInductDecl.ElimMode.small := by + simpa [hresult] using run.mode_eq + simp [hmode] + | true => + have hmode : generation.elimination = VInductDecl.ElimMode.large := by + simpa [hresult] using run.mode_eq + simp [hmode] + +theorem small_result_iff + (run : CheckerEliminationRun generation execution) : + execution.elimination.large.result = false ↔ + generation.elimination = VInductDecl.ElimMode.small := by + cases hresult : execution.elimination.large.result with + | false => + have hmode : generation.elimination = VInductDecl.ElimMode.small := by + simpa [hresult] using run.mode_eq + simp [hmode] + | true => + have hmode : generation.elimination = VInductDecl.ElimMode.large := by + simpa [hresult] using run.mode_eq + simp [hmode] + +theorem kTarget_result_true_iff + (run : CheckerEliminationRun generation execution) : + execution.kTarget.result = true ↔ generation.kTarget = true := by + rw [run.kTarget_eq] + +theorem kTarget_result_false_iff + (run : CheckerEliminationRun generation execution) : + execution.kTarget.result = false ↔ generation.kTarget = false := by + rw [run.kTarget_eq] + +end CheckerEliminationRun + +#guard_named_axioms Ix.Theory.Named.AddInductive.CheckerEliminationRun.large_result_iff [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CheckerElimLevelRun.large_result_iff [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.AddInductive.CheckerKTargetRun.result_true_iff [propext, Classical.choice, Quot.sound] + +end AddInductive +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesCommon.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesCommon.lean new file mode 100644 index 000000000..efacf6f1c --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesCommon.lean @@ -0,0 +1,65 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.Elimination +import Ix.Theory.Named.Verify.Environment.InductiveFixtures + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +universe u + +/-- A source-universe-bearing small eliminator. Or has no source universes, +so this fixture distinguishes "no fresh level" from "no levels at all". -/ +inductive Spec06SmallSource (α : Sort u) : Prop where + | left : Spec06SmallSource α + | right : Spec06SmallSource α + +def recursorShape06 (info : ConstantInfo) : + List Name × Nat × Nat × Nat × Nat × Bool × List (Name × Nat) := + match info with + | .recInfo rec => + (rec.levelParams, rec.numParams, rec.numIndices, rec.numMotives, + rec.numMinors, rec.k, + rec.rules.map fun rule => (rule.ctor, rule.nfields)) + | _ => ([], 0, 0, 0, 0, false, []) + +def spec06KernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_spec06 {} + +def spec06Context (lparams : List Name) : AddInductive.Context where + env := spec06KernelEnv + lparams := lparams + safety := .safe + allowPrimitive := false + +example : AddInductive.getFreshElimParam [] = `u := by native_decide +example : AddInductive.getFreshElimParam [`u] = `u_1 := by native_decide +example : AddInductive.getFreshElimParam [`u, `u_1] = `u_2 := by native_decide + +/-- Decidable structural equality for the exact kernel level lists retained by +the fixtures. `Lean.Level` intentionally has no `DecidableEq` instance. -/ +def levelListStructEq06 : List Level → List Level → Bool + | [], [] => true + | u :: us, v :: vs => + Level.isStructEq u v && levelListStructEq06 us vs + | _, _ => false + +theorem levelListStructEq06_eq {us vs : List Level} + (h : levelListStructEq06 us vs) : us = vs := by + induction us generalizing vs with + | nil => cases vs <;> simp_all [levelListStructEq06] + | cons u us ih => + cases vs with + | nil => simp [levelListStructEq06] at h + | cons v vs => + simp only [levelListStructEq06, Bool.and_eq_true] at h + cases Level.isStructEq_eq h.1 + cases ih h.2 + rfl + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean new file mode 100644 index 000000000..4f9c11fa7 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean @@ -0,0 +1,249 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon + +open Ix.Theory (VLevel) + +/-! Exact Spec-06C `Unit`/`PUnit` and `Empty` edge-shape fixtures. + +`Unit` is a reducible alias for `PUnit` on this Lean revision. The alias has +definition metadata but no independent inductive/constructor/recursor records, +so the real one-constructor transaction is checked under `PUnit`. `Empty` +supplies the matching zero-constructor transaction. -/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +/-- Translate the declaration-first universe order produced by `vconst` to +the fresh-first order stored by large recursor metadata. -/ +private def permC06C (constant : VConstant) (levels : List VLevel) : + VConstant := + ⟨constant.uvars, constant.type.instL levels⟩ + +/-! ## Unit is exactly the reducible PUnit alias -/ + +def unitAliasInfo06C : DefinitionVal := kernelDefVal% Unit + +/-- Pin every field of the actual `Unit` definition metadata. In particular, +there is no fabricated alias-level recursor for the edge fixture. -/ +example : + (unitAliasInfo06C.name, unitAliasInfo06C.levelParams, + unitAliasInfo06C.type, unitAliasInfo06C.value, + unitAliasInfo06C.hints, unitAliasInfo06C.safety, + unitAliasInfo06C.all) = + (``Unit, [], .sort (.succ .zero), + .const ``PUnit [.succ .zero], .abbrev, .safe, [``Unit]) := rfl + +/-! ## Complete kernel metadata shapes -/ + +def inductiveShape06C (info : ConstantInfo) : + Option (Name × List Name × Nat × Nat × List Name × List Name × Nat × + Bool × Bool × Bool) := + match info with + | .inductInfo induct => some + (induct.name, induct.levelParams, induct.numParams, induct.numIndices, + induct.all, induct.ctors, induct.numNested, induct.isRec, + induct.isUnsafe, induct.isReflexive) + | _ => none + +def constructorShape06C (info : ConstantInfo) : + Option (Name × List Name × Name × Nat × Nat × Nat × Bool) := + match info with + | .ctorInfo ctor => some + (ctor.name, ctor.levelParams, ctor.induct, ctor.cidx, ctor.numParams, + ctor.numFields, ctor.isUnsafe) + | _ => none + +def completeRecursorShape06C (info : ConstantInfo) : + Option (Name × List Name × List Name × Nat × Nat × Nat × Nat × Bool × + Bool × List (Name × Nat)) := + match info with + | .recInfo rec => some + (rec.name, rec.levelParams, rec.all, rec.numParams, rec.numIndices, + rec.numMotives, rec.numMinors, rec.k, rec.isUnsafe, + rec.rules.map fun rule => (rule.ctor, rule.nfields)) + | _ => none + +/-! ## PUnit: one constructor, one minor, one rule -/ + +def punitInfo06C : ConstantInfo := kernelInductInfo% PUnit +def punitCtorInfo06C : ConstantInfo := kernelCtorInfo% PUnit.unit +def punitRecInfo06C : ConstantInfo := kernelRecInfo% PUnit.rec +def punitRuleRhs06C : VExpr := kernelRecRuleRhs% PUnit.rec 0 + +example : inductiveShape06C punitInfo06C = some + (``PUnit, [`u], 0, 0, [``PUnit], [``PUnit.unit], 0, false, false, + false) := rfl +example : punitInfo06C.type = .sort (.param `u) := rfl +example : constructorShape06C punitCtorInfo06C = some + (``PUnit.unit, [`u], ``PUnit, 0, 0, 0, false) := rfl +example : punitCtorInfo06C.type = .const ``PUnit [.param `u] := rfl +example : completeRecursorShape06C punitRecInfo06C = some + (``PUnit.rec, [`u_1, `u], [``PUnit], 0, 0, 1, 1, false, false, + [(``PUnit.unit, 0)]) := rfl + +example : punitChecked.params = [] := rfl +example : punitChecked.indices = [] := rfl +example : punitChecked.constructors.length = 1 := rfl +example : punitChecked.constructors[0].fields = [] := rfl +example : punitChecked.constructors[0].recursive = [] := rfl +example : punitGenerationChecked.block.ctorPairs.length = 1 := rfl +example : punitGenerationChecked.minorTypes = + [.app (.bvar 0) (.const ``PUnit.unit [.param 1])] := rfl +example : punitGenerationChecked.generatedRules.length = 1 := rfl + +/-- The complete generated type agrees with the real recursor, including the +fresh-first `[u_1, u]` metadata order. -/ +example : punitGenerationChecked.recursor = + permC06C (vconst(type_of% @PUnit.rec)) [.param 1, .param 0] := rfl + +/-- Removing the three outer binders exposes motive, sole minor, then major. +The minor has no field or induction-hypothesis binders. -/ +example : VExpr.telN 3 punitGenerationChecked.recType = + [punitGenerationChecked.motiveType, + .app (.bvar 0) (.const ``PUnit.unit [.param 1]), + .const ``PUnit [.param 1]] := rfl + +example : punitRuleRhs06C = + punitGenerationChecked.generatedRules[0].rhs := rfl + +def punitKernelType06C : InductiveType where + name := punitInfo06C.name + type := punitInfo06C.type + ctors := [{ name := punitCtorInfo06C.name, type := punitCtorInfo06C.type }] + +def punitEliminationResult06C := + AddInductive.NormalizationEliminationExecution.buildExecution 0 + [punitKernelType06C] 0 false (spec06Context [`u]) + +theorem punitEliminationResult06C_isOk : + punitEliminationResult06C.isOk = true := by + native_decide + +def punitProducedExecution06C : + { execution // punitEliminationResult06C = .ok execution } := + match h : punitEliminationResult06C with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := punitEliminationResult06C_isOk + rw [h] at hOk + contradiction + +def punitExecution06C := punitProducedExecution06C.val + +def punitAlignment06C : AddInductive.CheckerEliminationRun + punitGenerationChecked punitExecution06C := + (AddInductive.CheckerEliminationRun.build? punitGenerationChecked + punitExecution06C).get (by native_decide) + +def punitLargeSingleton06C := + punitExecution06C.elimination.large.singleton.get (by native_decide) + +example : punitExecution06C.normalization.stats.params.size = 0 := by + native_decide +example : punitExecution06C.normalization.stats.nindices = #[0] := by + native_decide +example : punitExecution06C.normalization.stats.isNotZero = false := by + native_decide +example : punitExecution06C.elimination.large.result = true := by + native_decide +example : punitLargeSingleton06C.trace.parameterCount = 0 := by + native_decide +example : punitLargeSingleton06C.trace.proofFieldCount = 0 := by + native_decide +example : punitLargeSingleton06C.trace.dataFieldCount = 0 := by + native_decide +example : punitExecution06C.kTarget.result = false := by native_decide +example : punitExecution06C.kTarget.singleton = none := by native_decide +example : punitExecution06C.elimination.level = .param `u_1 := + Level.isStructEq_eq (by native_decide) +example : punitExecution06C.recLevelParams = [`u_1, `u] := by + native_decide +example : punitExecution06C.recLevels = [.param `u_1, .param `u] := + levelListStructEq06_eq (by native_decide) +example : punitGenerationChecked.elimination = .large := + punitAlignment06C.large_result_iff.mp (by native_decide) +example : punitGenerationChecked.kTarget = false := + punitAlignment06C.kTarget_result_false_iff.mp (by native_decide) + +/-! ## Empty: zero constructors, zero minors, zero rules -/ + +def emptyInfo06C : ConstantInfo := kernelInductInfo% Empty +def emptyRecInfo06C : ConstantInfo := kernelRecInfo% Empty.rec + +example : inductiveShape06C emptyInfo06C = some + (``Empty, [], 0, 0, [``Empty], [], 0, false, false, false) := rfl +example : emptyInfo06C.type = .sort (.succ .zero) := rfl +example : completeRecursorShape06C emptyRecInfo06C = some + (``Empty.rec, [`u], [``Empty], 0, 0, 1, 0, false, false, []) := rfl + +example : emptyChecked.params = [] := rfl +example : emptyChecked.indices = [] := rfl +example : emptyChecked.constructors = [] := rfl +example : emptyGenerationChecked.block.ctorPairs = [] := rfl +example : emptyGenerationChecked.minorTypes = [] := rfl +example : emptyGenerationChecked.generatedRules = [] := rfl +example : emptyGenerationChecked.recursor = vconst(type_of% @Empty.rec) := rfl + +/-- Empty elimination has no synthetic constructor minor: motive is followed +immediately by the major. -/ +example : VExpr.telN 2 emptyGenerationChecked.recType = + [emptyGenerationChecked.motiveType, .const ``Empty []] := rfl + +def emptyKernelType06C : InductiveType where + name := emptyInfo06C.name + type := emptyInfo06C.type + ctors := [] + +def emptyEliminationResult06C := + AddInductive.NormalizationEliminationExecution.buildExecution 0 + [emptyKernelType06C] 0 false (spec06Context []) + +theorem emptyEliminationResult06C_isOk : + emptyEliminationResult06C.isOk = true := by + native_decide + +def emptyProducedExecution06C : + { execution // emptyEliminationResult06C = .ok execution } := + match h : emptyEliminationResult06C with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := emptyEliminationResult06C_isOk + rw [h] at hOk + contradiction + +def emptyExecution06C := emptyProducedExecution06C.val + +def emptyAlignment06C : AddInductive.CheckerEliminationRun + emptyGenerationChecked emptyExecution06C := + (AddInductive.CheckerEliminationRun.build? emptyGenerationChecked + emptyExecution06C).get (by native_decide) + +example : emptyExecution06C.normalization.stats.params.size = 0 := by + native_decide +example : emptyExecution06C.normalization.stats.nindices = #[0] := by + native_decide +example : emptyExecution06C.normalization.stats.isNotZero = true := by + native_decide +example : emptyExecution06C.elimination.large.result = true := by + native_decide +example : emptyExecution06C.elimination.large.singleton = none := by + native_decide +example : emptyExecution06C.kTarget.result = false := by native_decide +example : emptyExecution06C.kTarget.singleton = none := by native_decide +example : emptyExecution06C.elimination.level = .param `u := + Level.isStructEq_eq (by native_decide) +example : emptyExecution06C.recLevelParams = [`u] := by native_decide +example : emptyExecution06C.recLevels = [.param `u] := + levelListStructEq06_eq (by native_decide) +example : emptyGenerationChecked.elimination = .large := + emptyAlignment06C.large_result_iff.mp (by native_decide) +example : emptyGenerationChecked.kTarget = false := + emptyAlignment06C.kTarget_result_false_iff.mp (by native_decide) + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean new file mode 100644 index 000000000..11b50dbb2 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean @@ -0,0 +1,65 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon + +/-! Exact Spec-06B Eq differential fixture. -/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +/-! Eq: indexed singleton large elimination and fresh-first order. -/ + +def eqKernelType06 : InductiveType where + name := eqInfo.name + type := eqInfo.type + ctors := [{ name := eqReflInfo.name, type := eqReflInfo.type }] + +def eqEliminationResult06 := + AddInductive.NormalizationEliminationExecution.buildExecution 2 + [eqKernelType06] 0 false (spec06Context eqInfo.levelParams) + +theorem eqEliminationResult06_isOk : eqEliminationResult06.isOk = true := by + native_decide + +def eqProducedExecution06 : + { execution // eqEliminationResult06 = .ok execution } := + match h : eqEliminationResult06 with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := eqEliminationResult06_isOk + rw [h] at hOk + contradiction + +def eqExecution06 := eqProducedExecution06.val + +def eqAlignment06 : + AddInductive.CheckerEliminationRun eqGenerationChecked eqExecution06 := + (AddInductive.CheckerEliminationRun.build? eqGenerationChecked eqExecution06).get + (by native_decide) + +def eqKTargetSingleton06 := + eqExecution06.kTarget.singleton.get (by native_decide) + +example : eqExecution06.elimination.large.result = true := by native_decide +example : eqExecution06.kTarget.result = true := by native_decide +example : eqKTargetSingleton06.trace.parameterCount = 2 := by native_decide +example : eqKTargetSingleton06.trace.fieldCount = 0 := by native_decide +example : eqExecution06.elimination.level = .param `u := + Level.isStructEq_eq (by native_decide) +example : eqExecution06.recLevelParams = [`u, `u_1] := by native_decide +example : eqExecution06.recLevels = [.param `u, .param `u_1] := + levelListStructEq06_eq (by native_decide) +example : recursorShape06 eqRecInfo = + ([`u, `u_1], 2, 1, 1, 1, true, [(``Eq.refl, 0)]) := rfl +example : eqReflKernelRuleRhs = eqChecked.generatedRules[0].rhs := rfl +example : eqGenerationChecked.elimination = .large := + eqAlignment06.large_result_iff.mp (by native_decide) +example : eqGenerationChecked.kTarget = true := + eqAlignment06.kTarget_result_true_iff.mp (by native_decide) + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean new file mode 100644 index 000000000..ba3fbfbc4 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean @@ -0,0 +1,10 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.EliminationFixturesEq +import Ix.Theory.Named.Verify.Environment.EliminationFixturesNat + +/-! Umbrella for the exact Spec-06A Eq and Nat differential fixtures. -/ diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean new file mode 100644 index 000000000..5da576adb --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean @@ -0,0 +1,114 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon + +/-! Exact Spec-06B Nat never-zero elimination and non-K fixture. -/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +/-! Nat's nonzero result universe takes the immediate large-elimination +branch. The exact singleton statistics and source levels are pinned directly +so this replay tests that branch without compiling the unrelated full +normalization trace a second time. -/ + +def natKernelType06 : InductiveType where + name := natInfo.name + type := natInfo.type + ctors := [ + { name := natZeroInfo.name, type := natZeroInfo.type }, + { name := natSuccInfo.name, type := natSuccInfo.type }] + +def natNeverZeroStats06 : AddInductive.InductiveStats := + AddInductive.singletonInductiveStats (spec06Context []) natKernelType06 + (.succ .zero) + +def natElimLevelResult06 := + AddInductive.ElimLevelExecution.buildExecution natNeverZeroStats06 + #[natKernelType06] (spec06Context []) + +theorem natElimLevelResult06_isOk : natElimLevelResult06.isOk = true := by + native_decide + +def natProducedElimLevel06 : + { execution // natElimLevelResult06 = .ok execution } := + match h : natElimLevelResult06 with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := natElimLevelResult06_isOk + rw [h] at hOk + contradiction + +def natElimLevelExecution06 := natProducedElimLevel06.val + +def natElimAlignmentResult06 := + AddInductive.CheckerElimLevelRun.build? natGenerationChecked + natElimLevelExecution06 + +theorem natElimAlignmentResult06_isSome : + natElimAlignmentResult06.isSome = true := by + native_decide + +def natElimAlignment06 : AddInductive.CheckerElimLevelRun + natGenerationChecked natElimLevelExecution06 := + natElimAlignmentResult06.get natElimAlignmentResult06_isSome + +def natKTargetResult06 := + AddInductive.KTargetExecution.buildExecution natNeverZeroStats06 + #[natKernelType06] (spec06Context []) + +theorem natKTargetResult06_isOk : natKTargetResult06.isOk = true := by + native_decide + +def natProducedKTarget06 : + { execution // natKTargetResult06 = .ok execution } := + match h : natKTargetResult06 with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := natKTargetResult06_isOk + rw [h] at hOk + contradiction + +def natKTargetExecution06 := natProducedKTarget06.val + +def natKTargetAlignmentResult06 := + AddInductive.CheckerKTargetRun.build? natGenerationChecked + natKTargetExecution06 + +theorem natKTargetAlignmentResult06_isSome : + natKTargetAlignmentResult06.isSome = true := by + native_decide + +def natKTargetAlignment06 : AddInductive.CheckerKTargetRun + natGenerationChecked natKTargetExecution06 := + natKTargetAlignmentResult06.get natKTargetAlignmentResult06_isSome + +example : natNeverZeroStats06.isNotZero = true := rfl +example : natNeverZeroStats06.resultLevel = .succ .zero := rfl +example : natKernelType06.type = .sort (.succ .zero) := rfl +example : natChecked.resultLevel = .succ .zero := rfl +example : natElimLevelExecution06.large.result = true := by native_decide +example : natKTargetExecution06.result = false := by native_decide +example : natKTargetExecution06.singleton = none := by native_decide +example : natElimLevelExecution06.level = .param `u := + Level.isStructEq_eq (by native_decide) +example : AddInductive.getRecLevelParams natElimLevelExecution06.level [] = + [`u] := by native_decide +example : AddInductive.getRecLevels natElimLevelExecution06.level [] = + [.param `u] := levelListStructEq06_eq (by native_decide) +example : recursorShape06 natRecInfo = + ([`u], 0, 0, 1, 2, false, + [(``Nat.zero, 0), (``Nat.succ, 1)]) := rfl +example : natZeroKernelRuleRhs = natChecked.generatedRules[0].rhs := rfl +example : natSuccKernelRuleRhs = natChecked.generatedRules[1].rhs := rfl +example : natGenerationChecked.elimination = .large := + natElimAlignment06.large_result_iff.mp (by native_decide) +example : natGenerationChecked.kTarget = false := + natKTargetAlignment06.result_false_iff.mp (by native_decide) + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean new file mode 100644 index 000000000..3688cf991 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean @@ -0,0 +1,137 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon + +/-! Exact Spec-06B Or/And differential fixtures. -/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +/-! ## Or: Prop-only elimination -/ + +def orInfo06 : ConstantInfo := kernelInductInfo% Or +def orInlInfo06 : ConstantInfo := kernelCtorInfo% Or.inl +def orInrInfo06 : ConstantInfo := kernelCtorInfo% Or.inr +def orRecInfo06 : ConstantInfo := kernelRecInfo% Or.rec +def orInlKernelRuleRhs06 : VExpr := kernelRecRuleRhs% Or.rec 0 +def orInrKernelRuleRhs06 : VExpr := kernelRecRuleRhs% Or.rec 1 + +def orKernelType06 : InductiveType where + name := orInfo06.name + type := orInfo06.type + ctors := [ + { name := orInlInfo06.name, type := orInlInfo06.type }, + { name := orInrInfo06.name, type := orInrInfo06.type }] + +def orEliminationResult06 := + AddInductive.NormalizationEliminationExecution.buildExecution 2 + [orKernelType06] 0 false (spec06Context orInfo06.levelParams) + +theorem orEliminationResult06_isOk : orEliminationResult06.isOk = true := by + native_decide + +def orProducedExecution06 : + { execution // orEliminationResult06 = .ok execution } := + match h : orEliminationResult06 with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := orEliminationResult06_isOk + rw [h] at hOk + contradiction + +def orExecution06 := orProducedExecution06.val + +def orGeneration06 : VInductDecl.GenerationChecked orDecl := + (VInductDecl.identityGeneration? orDecl).get (by decide) + +def orAlignment06 : + AddInductive.CheckerEliminationRun orGeneration06 orExecution06 := + (AddInductive.CheckerEliminationRun.build? orGeneration06 orExecution06).get + (by native_decide) + +example : orExecution06.elimination.large.result = false := by native_decide +example : orExecution06.kTarget.result = false := by native_decide +example : orExecution06.kTarget.singleton = none := by native_decide +example : orExecution06.elimination.level = .zero := + Level.isStructEq_eq (by native_decide) +example : orExecution06.recLevelParams = [] := by native_decide +example : orExecution06.recLevels = [] := by native_decide +example : recursorShape06 orRecInfo06 = + ([], 2, 0, 1, 2, false, [(``Or.inl, 1), (``Or.inr, 1)]) := rfl +example : orInlKernelRuleRhs06 = orChecked.generatedRules[0].rhs := rfl +example : orInrKernelRuleRhs06 = orChecked.generatedRules[1].rhs := rfl +example : orGeneration06.elimination = .small := + orAlignment06.small_result_iff.mp (by native_decide) +example : orGeneration06.kTarget = false := + orAlignment06.kTarget_result_false_iff.mp (by native_decide) + +/-! ## And: singleton proof fields permit large elimination -/ + +def andInfo06 : ConstantInfo := kernelInductInfo% And +def andIntroInfo06 : ConstantInfo := kernelCtorInfo% And.intro +def andRecInfo06 : ConstantInfo := kernelRecInfo% And.rec +def andKernelRuleRhs06 : VExpr := kernelRecRuleRhs% And.rec 0 + +def andKernelType06 : InductiveType where + name := andInfo06.name + type := andInfo06.type + ctors := [{ name := andIntroInfo06.name, type := andIntroInfo06.type }] + +def andEliminationResult06 := + AddInductive.NormalizationEliminationExecution.buildExecution 2 + [andKernelType06] 0 false (spec06Context andInfo06.levelParams) + +theorem andEliminationResult06_isOk : andEliminationResult06.isOk = true := by + native_decide + +def andProducedExecution06 : + { execution // andEliminationResult06 = .ok execution } := + match h : andEliminationResult06 with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := andEliminationResult06_isOk + rw [h] at hOk + contradiction + +def andExecution06 := andProducedExecution06.val + +def andGeneration06 : VInductDecl.GenerationChecked andDecl := + (VInductDecl.identityGeneration? andDecl).get (by decide) + +def andAlignment06 : + AddInductive.CheckerEliminationRun andGeneration06 andExecution06 := + (AddInductive.CheckerEliminationRun.build? andGeneration06 andExecution06).get + (by native_decide) + +def andSingletonExecution06 := + andExecution06.elimination.large.singleton.get (by native_decide) + +def andKTargetSingleton06 := + andExecution06.kTarget.singleton.get (by native_decide) + +example : andExecution06.elimination.large.result = true := by native_decide +example : andExecution06.kTarget.result = false := by native_decide +example : andKTargetSingleton06.trace.parameterCount = 2 := by native_decide +example : andKTargetSingleton06.trace.fieldCount = 1 := by native_decide +example : andExecution06.elimination.level = .param `u := + Level.isStructEq_eq (by native_decide) +example : andExecution06.recLevelParams = [`u] := by native_decide +example : andExecution06.recLevels = [.param `u] := + levelListStructEq06_eq (by native_decide) +example : recursorShape06 andRecInfo06 = + ([`u], 2, 0, 1, 1, false, [(``And.intro, 2)]) := rfl +example : andSingletonExecution06.trace.parameterCount = 2 := by native_decide +example : andSingletonExecution06.trace.proofFieldCount = 2 := by native_decide +example : andSingletonExecution06.trace.dataFieldCount = 0 := by native_decide +example : andKernelRuleRhs06 = andChecked.generatedRules[0].rhs := rfl +example : andGeneration06.elimination = .large := + andAlignment06.large_result_iff.mp (by native_decide) +example : andGeneration06.kTarget = false := + andAlignment06.kTarget_result_false_iff.mp (by native_decide) + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean new file mode 100644 index 000000000..309021ddf --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean @@ -0,0 +1,100 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon + +/-! Exact Spec-06B source-universe small-elimination differential fixture. -/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +def smallSourceInfo06 : ConstantInfo := kernelInductInfo% Spec06SmallSource +def smallSourceLeftInfo06 : ConstantInfo := + kernelCtorInfo% Spec06SmallSource.left +def smallSourceRightInfo06 : ConstantInfo := + kernelCtorInfo% Spec06SmallSource.right +def smallSourceRecInfo06 : ConstantInfo := + kernelRecInfo% Spec06SmallSource.rec +def smallSourceLeftRuleRhs06 : VExpr := + kernelRecRuleRhs% Spec06SmallSource.rec 0 +def smallSourceRightRuleRhs06 : VExpr := + kernelRecRuleRhs% Spec06SmallSource.rec 1 + +def smallSourceType06 : VInductiveType where + name := ``Spec06SmallSource + uvars := 1 + type := vconst(type_of% @Spec06SmallSource).type + ctors := [ + ⟨vconst(type_of% @Spec06SmallSource.left), ``Spec06SmallSource.left⟩, + ⟨vconst(type_of% @Spec06SmallSource.right), ``Spec06SmallSource.right⟩] + +def smallSourceDecl06 : VInductDecl := ⟨1, 1, [smallSourceType06]⟩ + +def smallSourceChecked06 : smallSourceDecl06.Checked := + smallSourceDecl06.checked?.get (by decide) + +def smallSourceGeneration06 : + VInductDecl.GenerationChecked smallSourceDecl06 := + (VInductDecl.identityGeneration? smallSourceDecl06).get (by decide) + +def smallSourceKernelType06 : InductiveType where + name := smallSourceInfo06.name + type := smallSourceInfo06.type + ctors := [ + { name := smallSourceLeftInfo06.name, type := smallSourceLeftInfo06.type }, + { name := smallSourceRightInfo06.name, type := smallSourceRightInfo06.type }] + +def smallSourceEliminationResult06 := + AddInductive.NormalizationEliminationExecution.buildExecution 1 + [smallSourceKernelType06] 0 false + (spec06Context smallSourceInfo06.levelParams) + +theorem smallSourceEliminationResult06_isOk : + smallSourceEliminationResult06.isOk = true := by + native_decide + +def smallSourceProducedExecution06 : + { execution // smallSourceEliminationResult06 = .ok execution } := + match h : smallSourceEliminationResult06 with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := smallSourceEliminationResult06_isOk + rw [h] at hOk + contradiction + +def smallSourceExecution06 := smallSourceProducedExecution06.val + +def smallSourceAlignment06 : AddInductive.CheckerEliminationRun + smallSourceGeneration06 smallSourceExecution06 := + (AddInductive.CheckerEliminationRun.build? smallSourceGeneration06 + smallSourceExecution06).get (by native_decide) + +example : smallSourceInfo06.levelParams = [`u] := rfl +example : smallSourceExecution06.elimination.large.result = false := by + native_decide +example : smallSourceExecution06.kTarget.result = false := by native_decide +example : smallSourceExecution06.kTarget.singleton = none := by native_decide +example : smallSourceExecution06.elimination.level = .zero := + Level.isStructEq_eq (by native_decide) +example : smallSourceExecution06.recLevelParams = [`u] := by native_decide +example : smallSourceExecution06.recLevels = [.param `u] := + levelListStructEq06_eq (by native_decide) +example : recursorShape06 smallSourceRecInfo06 = + ([`u], 1, 0, 1, 2, false, + [(``Spec06SmallSource.left, 0), (``Spec06SmallSource.right, 0)]) := rfl +example : smallSourceChecked06.elimination = .small := + smallSourceAlignment06.small_result_iff.mp (by native_decide) +example : smallSourceGeneration06.kTarget = false := + smallSourceAlignment06.kTarget_result_false_iff.mp (by native_decide) +example : smallSourceGeneration06.recursor = + vconst(type_of% @Spec06SmallSource.rec) := rfl +example : smallSourceLeftRuleRhs06 = + smallSourceGeneration06.generatedRules[0].rhs := rfl +example : smallSourceRightRuleRhs06 = + smallSourceGeneration06.generatedRules[1].rhs := rfl + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/IndexedVecCandidate.lean b/Ix/Theory/Named/Verify/Environment/IndexedVecCandidate.lean new file mode 100644 index 000000000..8d305f876 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/IndexedVecCandidate.lean @@ -0,0 +1,1686 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.InductiveFixtures + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta +open Ix.Theory.Named.InductiveFixtures + +def indexedVecKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_indexedVecCandidate natMap + +def indexedVecFamilyCandidateContext : + Ix.Theory.Named.AddInductive.Context where + env := indexedVecKernelEnv + lparams := indexedVecInfo.levelParams + safety := .safe + allowPrimitive := false + +private theorem indexedVecKernel_lookup_nat : + indexedVecKernelEnv.find? ``Nat = some natInfo := by + change natMap.find?' ``Nat = some natInfo + rw [natMap_wf.find?'_eq_find?, nat_type_map_lookup] + +private theorem indexedVecKernel_lookup_zero : + indexedVecKernelEnv.find? ``Nat.zero = some natZeroInfo := by + change natMap.find?' ``Nat.zero = some natZeroInfo + rw [natMap_wf.find?'_eq_find?, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert] + rfl + +private theorem indexedVecKernel_lookup_succ : + indexedVecKernelEnv.find? ``Nat.succ = some natSuccInfo := by + change natMap.find?' ``Nat.succ = some natSuccInfo + rw [natMap_wf.find?'_eq_find?, nat_succ_map_lookup] + +@[simp] private theorem indexedVecKernel_get_nat : + indexedVecKernelEnv.get ``Nat = .ok natInfo := by + simp only [Kernel.Environment.get, indexedVecKernel_lookup_nat, + Pure.pure, Except.pure] + +@[simp] private theorem indexedVecKernel_get_zero : + indexedVecKernelEnv.get ``Nat.zero = .ok natZeroInfo := by + simp only [Kernel.Environment.get, indexedVecKernel_lookup_zero, + Pure.pure, Except.pure] + +@[simp] private theorem indexedVecKernel_get_succ : + indexedVecKernelEnv.get ``Nat.succ = .ok natSuccInfo := by + simp only [Kernel.Environment.get, indexedVecKernel_lookup_succ, + Pure.pure, Except.pure] + +private def indexedVecParamName : Name := + indexedVecInfo.type.bindingName! + +private def indexedVecIndexName : Name := + indexedVecInfo.type.bindingBody!.bindingName! + +private def indexedVecParamCandidateContext : + Ix.Theory.Named.AddInductive.Context := + indexedVecFamilyCandidateContext.pushLocalDecl + indexedVecParamName .default (.sort (.succ (.param `u))) + +private def indexedVecIndexCandidateContext : + Ix.Theory.Named.AddInductive.Context := + indexedVecParamCandidateContext.pushLocalDecl + indexedVecIndexName .default (.const ``Nat []) + +private def indexedVecInnerKernel : Expr := + .forallE indexedVecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default + +private def indexedVecTerminalKernel : Expr := + .sort (.succ (.param `u)) + +@[simp] private theorem indexedVecInnerKernel_instantiate1 (arg : Expr) : + indexedVecInnerKernel.instantiate1 arg = indexedVecInnerKernel := by + simp [indexedVecInnerKernel, Expr.instantiate1_eq, Expr.instantiate1'] + +@[simp] private theorem indexedVecTerminalKernel_instantiate1 (arg : Expr) : + indexedVecTerminalKernel.instantiate1 arg = + indexedVecTerminalKernel := by + simp [indexedVecTerminalKernel, Expr.instantiate1_eq, + Expr.instantiate1'] + +@[simp] private theorem indexedVecInfo_levelParams : + indexedVecInfo.levelParams = [`u] := rfl + +/-- Reflexive binder-domain equality is an exact successful ordinary-checker +run in any candidate context with positive recursive fuel. -/ +theorem candidateIsDefEqSelfValid + (context : Ix.Theory.Named.AddInductive.Context) (e : Expr) + (fuel : Nat) (hfuel : context.fuel.recDepth = fuel + 1) : + Ix.Theory.Named.AddInductive.CandidateIsDefEqStep.Valid ⟨context, e, e⟩ := by + unfold Ix.Theory.Named.AddInductive.CandidateIsDefEqStep.Valid + unfold Ix.Theory.Named.TypeChecker.M.run Ix.Theory.Named.TypeChecker.isDefEq + Ix.Theory.Named.TypeChecker.RecM.run + simp [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, StateT.bind, Except.bind, Bind.bind, + StateT.pure, Except.pure, Pure.pure, + StateT.run', Functor.map, Except.map] + rw [hfuel] + change Except.map (fun x : Bool × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.isDefEq e e + (Ix.Theory.Named.TypeChecker.Methods.withFuel (fuel + 1)) + context.toTypeChecker ({} : Ix.Theory.Named.TypeChecker.State)) = .ok true + unfold Ix.Theory.Named.TypeChecker.Inner.isDefEq + rw [if_pos (Expr.eqv_refl e)] + rfl + +def indexedVecTypeCheckerContext + (lctx : LocalContext) : Ix.Theory.Named.TypeChecker.Context where + env := indexedVecKernelEnv + lctx := lctx + lparams := [`u] + +@[simp] private theorem indexedVecFamily_checkLevel : + Ix.Theory.Named.TypeChecker.Inner.checkLevel + indexedVecFamilyCandidateContext.toTypeChecker + (.succ (.param `u)) = .ok () := by + simp [Ix.Theory.Named.TypeChecker.Inner.checkLevel, + indexedVecFamilyCandidateContext, indexedVecInfo, + Ix.Theory.Named.AddInductive.Context.toTypeChecker, + Level.getUndefParam, Level.forEach, + Level.hasParam_eq, Level.hasParam'] + rfl + +@[simp] private theorem indexedVec_checkLevel + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.checkLevel + (indexedVecTypeCheckerContext lctx) + (.succ (.param `u)) = .ok () := by + simp [Ix.Theory.Named.TypeChecker.Inner.checkLevel, + indexedVecTypeCheckerContext, + Level.getUndefParam, Level.forEach, + Level.hasParam_eq, Level.hasParam'] + rfl + +@[simp] private theorem indexedVecRecMGet (methods context state) : + (get : Ix.Theory.Named.TypeChecker.RecM Ix.Theory.Named.TypeChecker.State) + methods context state = .ok (state, state) := rfl + +@[simp] private theorem indexedVecRecMReadContext + (methods context state) : + (readThe Ix.Theory.Named.TypeChecker.Context : + Ix.Theory.Named.TypeChecker.RecM Ix.Theory.Named.TypeChecker.Context) + methods context state = .ok (context, state) := rfl + +@[simp] private theorem indexedVecRecMModify + (f : Ix.Theory.Named.TypeChecker.State → Ix.Theory.Named.TypeChecker.State) + (methods context state) : + (modify f : Ix.Theory.Named.TypeChecker.RecM PUnit) + methods context state = .ok (.unit, f state) := rfl + +@[simp] private theorem indexedVecRecMPure + {α} (a : α) (methods context state) : + (pure a : Ix.Theory.Named.TypeChecker.RecM α) + methods context state = .ok (a, state) := rfl + +@[simp] private theorem indexedVecRecMBind + {α β} (x : Ix.Theory.Named.TypeChecker.RecM α) + (f : α → Ix.Theory.Named.TypeChecker.RecM β) + (methods context state) : + (x >>= f) methods context state = + match x methods context state with + | .error e => .error e + | .ok (a, state') => f a methods context state' := by + simp [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + cases h : x methods context state with + | error => rfl + | ok value => cases value; rfl + +@[simp] private theorem indexedVecRecMLiftExceptOk + {α} (a : α) (methods context state) : + (liftM (.ok a : Except Kernel.Exception α) : + Ix.Theory.Named.TypeChecker.RecM α) methods context state = + .ok (a, state) := rfl + +@[simp] private theorem indexedVecGetNGen + (context : Ix.Theory.Named.TypeChecker.Context) + (state : Ix.Theory.Named.TypeChecker.State) : + (getNGen : Ix.Theory.Named.TypeChecker.M NameGenerator) context state = + .ok (state.ngen, state) := rfl + +@[simp] private theorem indexedVecSetNGen + (ngen : NameGenerator) (context : Ix.Theory.Named.TypeChecker.Context) + (state : Ix.Theory.Named.TypeChecker.State) : + (setNGen ngen : Ix.Theory.Named.TypeChecker.M PUnit) context state = + .ok (.unit, { state with ngen }) := rfl + +@[simp] private theorem indexedVecMPure + {α} (a : α) (context : Ix.Theory.Named.TypeChecker.Context) + (state : Ix.Theory.Named.TypeChecker.State) : + (pure a : Ix.Theory.Named.TypeChecker.M α) context state = + .ok (a, state) := rfl + +@[simp] private theorem indexedVecRecMWithReader + {α} (f : LocalContext → LocalContext) + (x : Ix.Theory.Named.TypeChecker.RecM α) + (methods : Ix.Theory.Named.TypeChecker.Methods) + (context : Ix.Theory.Named.TypeChecker.Context) + (state : Ix.Theory.Named.TypeChecker.State) : + (MonadWithReaderOf.withReader (m := Ix.Theory.Named.TypeChecker.RecM) f x) + methods context state = + x methods { context with lctx := f context.lctx } state := rfl + +private theorem indexedVecWithLocalDecl + {α} (name : Name) (bi : BinderInfo) (ty : Expr) + (k : Expr → Ix.Theory.Named.TypeChecker.RecM α) + (methods : Ix.Theory.Named.TypeChecker.Methods) + (context : Ix.Theory.Named.TypeChecker.Context) + (state : Ix.Theory.Named.TypeChecker.State) : + (withLocalDecl (m := Ix.Theory.Named.TypeChecker.RecM) name bi ty k) + methods context state = + k (.fvar ⟨state.ngen.curr⟩) methods + { context with lctx := + (context.lctx.mkLocalDecl ⟨state.ngen.curr⟩ name ty bi) } + { state with ngen := state.ngen.next } := rfl + +@[simp] private theorem indexedVecEnsureSort + (u : Level) (source : Expr) + (methods : Ix.Theory.Named.TypeChecker.Methods) + (context : Ix.Theory.Named.TypeChecker.Context) + (state : Ix.Theory.Named.TypeChecker.State) : + Ix.Theory.Named.TypeChecker.Inner.ensureSortCore (.sort u) source + methods context state = .ok (.sort u, state) := by + rfl + +private theorem indexedVecInferTypeFuel + (n e inferOnly context state) : + Ix.Theory.Named.TypeChecker.Inner.inferType e inferOnly + (Ix.Theory.Named.TypeChecker.Methods.withFuel (n + 1)) context state = + Ix.Theory.Named.TypeChecker.Inner.inferType' e inferOnly + (Ix.Theory.Named.TypeChecker.Methods.withFuel n) context state := rfl + +@[simp] private theorem indexedVecInferTypeSortCore + (n : Nat) (lctx : LocalContext) + (state : Ix.Theory.Named.TypeChecker.State) + (hcache : state.inferTypeC[(.sort (.succ (.param `u)) : Expr)]? = none) : + Ix.Theory.Named.TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel n) + (indexedVecTypeCheckerContext lctx) + state = + .ok (.sort (.succ (.succ (.param `u))), + { state with inferTypeC := + (state.inferTypeC.insert (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u))))) }) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +@[simp] private theorem indexedVecInferTypeSortCachedCore + (n : Nat) (lctx : LocalContext) + (state : Ix.Theory.Named.TypeChecker.State) + (hcache : state.inferTypeC[(.sort (.succ (.param `u)) : Expr)]? = + some (.sort (.succ (.succ (.param `u))))) : + Ix.Theory.Named.TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel n) + (indexedVecTypeCheckerContext lctx) + state = .ok (.sort (.succ (.succ (.param `u))), state) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache] + +@[simp] private theorem indexedVecInferConstantNat + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferConstant + (indexedVecTypeCheckerContext lctx) ``Nat [] false = + .ok (.sort (.succ .zero)) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferConstant + simp [indexedVecTypeCheckerContext, indexedVecKernel_get_nat, + natInfo, ConstantInfo.levelParams, ConstantInfo.isUnsafe, + ConstantInfo.instantiateTypeLevelParams, ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Level.substParams', Bind.bind, Except.bind, + Pure.pure, Except.pure] + +@[simp] theorem indexedVecPreFamilyInferConstantZero + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferConstant + (indexedVecTypeCheckerContext lctx) ``Nat.zero [] false = + .ok (.const ``Nat []) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferConstant + simp [indexedVecTypeCheckerContext, indexedVecKernel_get_zero, + natZeroInfo, ConstantInfo.levelParams, ConstantInfo.isUnsafe, + ConstantInfo.instantiateTypeLevelParams, ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Bind.bind, Except.bind, Pure.pure, Except.pure] + +@[simp] theorem indexedVecPreFamilyInferConstantSucc + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferConstant + (indexedVecTypeCheckerContext lctx) ``Nat.succ [] false = + .ok (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferConstant + simp [indexedVecTypeCheckerContext, indexedVecKernel_get_succ, + natSuccInfo, ConstantInfo.levelParams, ConstantInfo.isUnsafe, + ConstantInfo.instantiateTypeLevelParams, ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Bind.bind, Except.bind, Pure.pure, Except.pure] + +@[simp] private theorem indexedVecInferTypeNatCore + (n : Nat) (lctx : LocalContext) + (state : Ix.Theory.Named.TypeChecker.State) + (hcache : state.inferTypeC[(.const ``Nat [] : Expr)]? = none) : + Ix.Theory.Named.TypeChecker.Inner.inferType' (.const ``Nat []) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel n) + (indexedVecTypeCheckerContext lctx) + state = + .ok (.sort (.succ .zero), + { state with inferTypeC := + (state.inferTypeC.insert (.const ``Nat []) + (.sort (.succ .zero))) }) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + indexedVecInferConstantNat, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +theorem indexedVecPreFamilyInferTypeFVarCore + (n : Nat) (lctx : LocalContext) + (state : Ix.Theory.Named.TypeChecker.State) (id : FVarId) (type : Expr) + (hcache : state.inferTypeC[(.fvar id : Expr)]? = none) + (hfind : lctx.find? id = + some (.cdecl index id name type bi kind)) : + Ix.Theory.Named.TypeChecker.Inner.inferType' (.fvar id) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel n) + (indexedVecTypeCheckerContext lctx) state = + .ok (type, { state with inferTypeC := + state.inferTypeC.insert (.fvar id) type }) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + Ix.Theory.Named.TypeChecker.Inner.inferFVar, + indexedVecTypeCheckerContext, hfind, LocalDecl.type, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +theorem indexedVecPreFamilyInferTypeZeroCore + (n : Nat) (lctx : LocalContext) + (state : Ix.Theory.Named.TypeChecker.State) + (hcache : state.inferTypeC[(.const ``Nat.zero [] : Expr)]? = none) : + Ix.Theory.Named.TypeChecker.Inner.inferType' (.const ``Nat.zero []) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel n) + (indexedVecTypeCheckerContext lctx) state = + .ok (.const ``Nat [], { state with inferTypeC := + (state.inferTypeC.insert (.const ``Nat.zero []) + (.const ``Nat [])) }) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + indexedVecPreFamilyInferConstantZero, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +theorem indexedVecPreFamilyInferTypeSuccCore + (n : Nat) (lctx : LocalContext) + (state : Ix.Theory.Named.TypeChecker.State) + (hcache : state.inferTypeC[(.const ``Nat.succ [] : Expr)]? = none) : + Ix.Theory.Named.TypeChecker.Inner.inferType' (.const ``Nat.succ []) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel n) + (indexedVecTypeCheckerContext lctx) state = + .ok (.forallE `n (.const ``Nat []) (.const ``Nat []) .default, + { state with inferTypeC := (state.inferTypeC.insert + (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) }) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + indexedVecPreFamilyInferConstantSucc, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private def indexedVecRootSortState : Ix.Theory.Named.TypeChecker.State := + { ({} : Ix.Theory.Named.TypeChecker.State) with inferTypeC := + (({} : Ix.Theory.Named.TypeChecker.State).inferTypeC.insert + (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u))))) } + +@[simp] private theorem indexedVecRootSortCore : + Ix.Theory.Named.TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9998) + indexedVecFamilyCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort (.succ (.succ (.param `u))), + indexedVecRootSortState) := by + simpa [indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.toTypeChecker, + indexedVecInfo, ConstantInfo.levelParams, + ConstantInfo.toConstantVal, indexedVecTypeCheckerContext, + indexedVecRootSortState] using + (indexedVecInferTypeSortCore 9998 ({} : LocalContext) + ({} : Ix.Theory.Named.TypeChecker.State) Std.HashMap.getElem?_empty) + +private def indexedVecParamLctx : LocalContext := + ({} : LocalContext).mkLocalDecl + ⟨indexedVecRootSortState.ngen.curr⟩ indexedVecParamName + (.sort (.succ (.param `u))) .default + +private def indexedVecAfterParamState : Ix.Theory.Named.TypeChecker.State := + { indexedVecRootSortState with + ngen := indexedVecRootSortState.ngen.next } + +private def indexedVecNatState : Ix.Theory.Named.TypeChecker.State := + { indexedVecAfterParamState with + inferTypeC := indexedVecAfterParamState.inferTypeC.insert + (.const ``Nat []) (.sort (.succ .zero)) } + +private def indexedVecIndexLctx : LocalContext := + indexedVecParamLctx.mkLocalDecl + ⟨indexedVecNatState.ngen.curr⟩ indexedVecIndexName + (.const ``Nat []) .default + +private def indexedVecAfterIndexState : Ix.Theory.Named.TypeChecker.State := + { indexedVecNatState with ngen := indexedVecNatState.ngen.next } + +private theorem indexedVecOuterWithLocalDecl + {α} (k : Expr → Ix.Theory.Named.TypeChecker.RecM α) + (methods : Ix.Theory.Named.TypeChecker.Methods) : + (withLocalDecl (m := Ix.Theory.Named.TypeChecker.RecM) + indexedVecParamName .default (.sort (.succ (.param `u))) k) + methods indexedVecFamilyCandidateContext.toTypeChecker + indexedVecRootSortState = + k (.fvar ⟨indexedVecRootSortState.ngen.curr⟩) methods + { indexedVecFamilyCandidateContext.toTypeChecker with + lctx := indexedVecParamLctx } + indexedVecAfterParamState := by + simpa [indexedVecParamLctx, indexedVecAfterParamState, + indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.toTypeChecker] using + (indexedVecWithLocalDecl indexedVecParamName .default + (.sort (.succ (.param `u))) k methods + indexedVecFamilyCandidateContext.toTypeChecker indexedVecRootSortState) + +private theorem indexedVecInnerWithLocalDecl + {α} (k : Expr → Ix.Theory.Named.TypeChecker.RecM α) + (methods : Ix.Theory.Named.TypeChecker.Methods) : + (withLocalDecl (m := Ix.Theory.Named.TypeChecker.RecM) + indexedVecIndexName .default (.const ``Nat []) k) + methods + { indexedVecFamilyCandidateContext.toTypeChecker with + lctx := indexedVecParamLctx } + indexedVecNatState = + k (.fvar ⟨indexedVecNatState.ngen.curr⟩) methods + { indexedVecFamilyCandidateContext.toTypeChecker with + lctx := indexedVecIndexLctx } + indexedVecAfterIndexState := by + simpa [indexedVecIndexLctx, indexedVecAfterIndexState] using + (indexedVecWithLocalDecl indexedVecIndexName .default + (.const ``Nat []) k methods + { indexedVecFamilyCandidateContext.toTypeChecker with + lctx := indexedVecParamLctx } + indexedVecNatState) + +@[simp] private theorem indexedVecNat_beq_sort : + ((.const ``Nat [] : Expr) == .sort (.succ (.param `u))) = false := by + change Expr.eqv (.const ``Nat []) (.sort (.succ (.param `u))) = false + rw [Expr.eqv_eq] + rfl + +@[simp] private theorem indexedVecAfterIndexState_sort_cache : + indexedVecAfterIndexState.inferTypeC[ + (.sort (.succ (.param `u)) : Expr)]? = + some (.sort (.succ (.succ (.param `u)))) := by + change + (((({} : Ix.Theory.Named.InferCache).insert + (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u))))).insert + (.const ``Nat []) (.sort (.succ .zero)))[ + (.sort (.succ (.param `u)) : Expr)]?) = _ + rw [Std.HashMap.getElem?_insert, indexedVecNat_beq_sort] + exact Std.HashMap.getElem?_insert_self + +@[simp] private theorem indexedVecParamNatCore : + Ix.Theory.Named.TypeChecker.Inner.inferType' (.const ``Nat []) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9998) + { indexedVecFamilyCandidateContext.toTypeChecker with + lctx := indexedVecParamLctx } + indexedVecAfterParamState = + .ok (.sort (.succ .zero), indexedVecNatState) := by + simpa [indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.toTypeChecker, + indexedVecInfo, ConstantInfo.levelParams, + ConstantInfo.toConstantVal, indexedVecTypeCheckerContext, + indexedVecAfterParamState, indexedVecRootSortState, + indexedVecNatState] using + (indexedVecInferTypeNatCore 9998 indexedVecParamLctx + indexedVecAfterParamState (by + simp [indexedVecAfterParamState, indexedVecRootSortState])) + +@[simp] private theorem indexedVecTerminalSortCore : + Ix.Theory.Named.TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9998) + { indexedVecFamilyCandidateContext.toTypeChecker with + lctx := indexedVecIndexLctx } + indexedVecAfterIndexState = + .ok (.sort (.succ (.succ (.param `u))), + indexedVecAfterIndexState) := by + simpa [indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.toTypeChecker, + indexedVecInfo, ConstantInfo.levelParams, + ConstantInfo.toConstantVal, indexedVecTypeCheckerContext, + indexedVecAfterIndexState, indexedVecNatState, + indexedVecAfterParamState, indexedVecRootSortState] using + (indexedVecInferTypeSortCachedCore 9998 indexedVecIndexLctx + indexedVecAfterIndexState indexedVecAfterIndexState_sort_cache) + +private def indexedVecFamilyInferredLevel : Level := + mkLevelIMax' (.succ (.succ (.param `u))) + (mkLevelIMax' (.succ .zero) (.succ (.succ (.param `u)))) + +private theorem indexedVecFamilyInferForall : + Ix.Theory.Named.TypeChecker.Inner.inferForall + (.forallE indexedVecParamName (.sort (.succ (.param `u))) + (.forallE indexedVecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default) .default) + false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + indexedVecFamilyCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort indexedVecFamilyInferredLevel, + indexedVecAfterIndexState) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferForall + simp only [Ix.Theory.Named.TypeChecker.Inner.inferForall.loop] + rw [show + (.sort (.succ (.param `u)) : Expr).instantiateRev #[] = + .sort (.succ (.param `u)) by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq]] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [indexedVecInferTypeFuel 9998] + rw [indexedVecRootSortCore] + simp only + rw [indexedVecEnsureSort] + simp only + rw [indexedVecOuterWithLocalDecl] + rw [show + (.const ``Nat [] : Expr).instantiateRev + (#[] |>.push (.fvar ⟨indexedVecRootSortState.ngen.curr⟩)) = + .const ``Nat [] by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq, + Expr.instantiate1']] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [indexedVecInferTypeFuel 9998] + rw [indexedVecParamNatCore] + simp only + rw [indexedVecEnsureSort] + simp only + rw [indexedVecInnerWithLocalDecl] + rw [show + (.sort (.succ (.param `u)) : Expr).instantiateRev + ((#[] |>.push + (.fvar ⟨indexedVecRootSortState.ngen.curr⟩)).push + (.fvar ⟨indexedVecNatState.ngen.curr⟩)) = + .sort (.succ (.param `u)) by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq, + Expr.instantiate1']] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [indexedVecInferTypeFuel 9998] + rw [indexedVecTerminalSortCore] + simp only + rw [indexedVecEnsureSort] + simp [indexedVecFamilyInferredLevel, Expr.sortLevel!, + Pure.pure, ReaderT.pure, + StateT.pure, Except.pure] + +private def indexedVecFamilyCheckedState : Ix.Theory.Named.TypeChecker.State := + { indexedVecAfterIndexState with + inferTypeC := indexedVecAfterIndexState.inferTypeC.insert + (.forallE indexedVecParamName (.sort (.succ (.param `u))) + (.forallE indexedVecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default) .default) + (.sort indexedVecFamilyInferredLevel) } + +private theorem indexedVecFamilyCheckTypeInner : + Ix.Theory.Named.TypeChecker.Inner.inferType indexedVecInfo.type false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 10000) + indexedVecFamilyCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort indexedVecFamilyInferredLevel, + indexedVecFamilyCheckedState) := by + change Ix.Theory.Named.TypeChecker.Inner.inferType' + (.forallE indexedVecParamName (.sort (.succ (.param `u))) + (.forallE indexedVecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default) .default) + false (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + indexedVecFamilyCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State) = _ + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + indexedVecFamilyInferForall, indexedVecFamilyCheckedState, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem indexedVecFamily_whnfM : + Ix.Theory.Named.TypeChecker.M.run + indexedVecFamilyCandidateContext.env + indexedVecFamilyCandidateContext.safety + indexedVecFamilyCandidateContext.lctx + indexedVecFamilyCandidateContext.lparams + indexedVecFamilyCandidateContext.fuel + (Ix.Theory.Named.TypeChecker.whnf indexedVecInfo.type) = + .ok indexedVecInfo.type := by + rfl + +private theorem indexedVecSort_checkTypeM (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.checkType (.sort (.succ (.param `u)))) = + .ok (.sort (.succ (.succ (.param `u)))) := by + change Except.map + (fun x : Expr × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.inferType + (.sort (.succ (.param `u))) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 10000) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State)) = _ + rw [indexedVecInferTypeFuel 9999] + rw [indexedVecInferTypeSortCore 9999 lctx + ({} : Ix.Theory.Named.TypeChecker.State) Std.HashMap.getElem?_empty] + rfl + +private theorem indexedVecSort_whnfM (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.whnf (.sort (.succ (.param `u)))) = + .ok (.sort (.succ (.param `u))) := by + rfl + +private theorem indexedVecNat_checkTypeM (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.checkType (.const ``Nat [])) = + .ok (.sort (.succ .zero)) := by + change Except.map + (fun x : Expr × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.inferType (.const ``Nat []) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 10000) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State)) = _ + rw [indexedVecInferTypeFuel 9999] + rw [indexedVecInferTypeNatCore 9999 lctx + ({} : Ix.Theory.Named.TypeChecker.State) Std.HashMap.getElem?_empty] + rfl + +private theorem indexedVecUnfoldNat (lctx methods state) : + Ix.Theory.Named.TypeChecker.Inner.unfoldDefinition (.const ``Nat []) + methods (indexedVecTypeCheckerContext lctx) state = + .ok (none, state) := by + change Ix.Theory.Named.TypeChecker.Inner.unfoldDefinitionCore + (.const ``Nat []) methods (indexedVecTypeCheckerContext lctx) state = _ + simp [Ix.Theory.Named.TypeChecker.Inner.unfoldDefinitionCore, + Ix.Theory.Named.TypeChecker.Inner.isDelta, Expr.getAppFn, + indexedVecTypeCheckerContext, indexedVecKernel_lookup_nat, + natInfo, ConstantInfo.deltaValue?, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem indexedVecWhnfLoopNat (lctx methods state n) : + Ix.Theory.Named.TypeChecker.Inner.whnf'.loop (.const ``Nat []) (n + 1) + methods (indexedVecTypeCheckerContext lctx) state = + .ok (.const ``Nat [], state) := by + unfold Ix.Theory.Named.TypeChecker.Inner.whnf'.loop + simp [indexedVecUnfoldNat] + +private theorem indexedVecNat_whnfM (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.whnf (.const ``Nat [])) = + .ok (.const ``Nat []) := by + change Except.map + (fun x : Expr × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.whnf' (.const ``Nat []) + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State)) = _ + unfold Ix.Theory.Named.TypeChecker.Inner.whnf' + simp + rw [show + (if (indexedVecTypeCheckerContext lctx).eagerReduce then + (indexedVecTypeCheckerContext lctx).fuel.whnfEager + else (indexedVecTypeCheckerContext lctx).fuel.whnf) = 100000 by rfl] + rw [show 100000 = 99999 + 1 by rfl] + rw [indexedVecWhnfLoopNat] + simp [Functor.map, StateT.map, Except.map] + +private def indexedVecInnerInferredLevel : Level := + mkLevelIMax' (.succ .zero) (.succ (.succ (.param `u))) + +private def indexedVecInnerNatState : Ix.Theory.Named.TypeChecker.State := + { ({} : Ix.Theory.Named.TypeChecker.State) with + inferTypeC := ({} : Ix.Theory.Named.TypeChecker.State).inferTypeC.insert + (.const ``Nat []) (.sort (.succ .zero)) } + +private def indexedVecInnerCheckerLctx : LocalContext := + indexedVecParamCandidateContext.lctx.mkLocalDecl + ⟨indexedVecInnerNatState.ngen.curr⟩ indexedVecIndexName + (.const ``Nat []) .default + +private def indexedVecInnerAfterIndexState : + Ix.Theory.Named.TypeChecker.State := + { indexedVecInnerNatState with + ngen := indexedVecInnerNatState.ngen.next } + +private def indexedVecInnerSortState : Ix.Theory.Named.TypeChecker.State := + { indexedVecInnerAfterIndexState with + inferTypeC := indexedVecInnerAfterIndexState.inferTypeC.insert + (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u)))) } + +private def indexedVecInnerCheckedState : Ix.Theory.Named.TypeChecker.State := + { indexedVecInnerSortState with + inferTypeC := indexedVecInnerSortState.inferTypeC.insert + indexedVecInnerKernel (.sort indexedVecInnerInferredLevel) } + +@[simp] private theorem indexedVecInnerNatCore : + Ix.Theory.Named.TypeChecker.Inner.inferType' (.const ``Nat []) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9998) + indexedVecParamCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort (.succ .zero), indexedVecInnerNatState) := by + simpa [indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + Ix.Theory.Named.AddInductive.Context.toTypeChecker, + indexedVecInfo, ConstantInfo.levelParams, + ConstantInfo.toConstantVal, indexedVecTypeCheckerContext, + indexedVecInnerNatState] using + (indexedVecInferTypeNatCore 9998 + indexedVecParamCandidateContext.lctx + ({} : Ix.Theory.Named.TypeChecker.State) Std.HashMap.getElem?_empty) + +private theorem indexedVecInnerCheckerWithLocalDecl + {α} (k : Expr → Ix.Theory.Named.TypeChecker.RecM α) + (methods : Ix.Theory.Named.TypeChecker.Methods) : + (withLocalDecl (m := Ix.Theory.Named.TypeChecker.RecM) + indexedVecIndexName .default (.const ``Nat []) k) + methods indexedVecParamCandidateContext.toTypeChecker + indexedVecInnerNatState = + k (.fvar ⟨indexedVecInnerNatState.ngen.curr⟩) methods + { indexedVecParamCandidateContext.toTypeChecker with + lctx := indexedVecInnerCheckerLctx } + indexedVecInnerAfterIndexState := by + simpa [indexedVecInnerCheckerLctx, + indexedVecInnerAfterIndexState, + indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + Ix.Theory.Named.AddInductive.Context.toTypeChecker] using + (indexedVecWithLocalDecl indexedVecIndexName .default + (.const ``Nat []) k methods + indexedVecParamCandidateContext.toTypeChecker + indexedVecInnerNatState) + +@[simp] private theorem indexedVecInnerTerminalSortCore : + Ix.Theory.Named.TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9998) + { indexedVecParamCandidateContext.toTypeChecker with + lctx := indexedVecInnerCheckerLctx } + indexedVecInnerAfterIndexState = + .ok (.sort (.succ (.succ (.param `u))), + indexedVecInnerSortState) := by + simpa [indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + Ix.Theory.Named.AddInductive.Context.toTypeChecker, + indexedVecInfo, ConstantInfo.levelParams, + ConstantInfo.toConstantVal, indexedVecTypeCheckerContext, + indexedVecInnerAfterIndexState, indexedVecInnerNatState, + indexedVecInnerSortState] using + (indexedVecInferTypeSortCore 9998 indexedVecInnerCheckerLctx + indexedVecInnerAfterIndexState (by + simp [indexedVecInnerAfterIndexState, + indexedVecInnerNatState])) + +private theorem indexedVecInnerInferForall : + Ix.Theory.Named.TypeChecker.Inner.inferForall indexedVecInnerKernel false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + indexedVecParamCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort indexedVecInnerInferredLevel, + indexedVecInnerSortState) := by + unfold indexedVecInnerKernel + unfold Ix.Theory.Named.TypeChecker.Inner.inferForall + simp only [Ix.Theory.Named.TypeChecker.Inner.inferForall.loop] + rw [show (.const ``Nat [] : Expr).instantiateRev #[] = + .const ``Nat [] by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq]] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [indexedVecInferTypeFuel 9998] + rw [indexedVecInnerNatCore] + simp only + rw [indexedVecEnsureSort] + simp only + rw [indexedVecInnerCheckerWithLocalDecl] + rw [show + (.sort (.succ (.param `u)) : Expr).instantiateRev + (#[] |>.push (.fvar ⟨indexedVecInnerNatState.ngen.curr⟩)) = + .sort (.succ (.param `u)) by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq, + Expr.instantiate1']] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [indexedVecInferTypeFuel 9998] + rw [indexedVecInnerTerminalSortCore] + simp only + rw [indexedVecEnsureSort] + simp [indexedVecInnerInferredLevel, Expr.sortLevel!, + Pure.pure, ReaderT.pure, StateT.pure, Except.pure] + +private theorem indexedVecInner_checkTypeM : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe + indexedVecParamCandidateContext.lctx [`u] ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.checkType indexedVecInnerKernel) = + .ok (.sort indexedVecInnerInferredLevel) := by + change Except.map + (fun x : Expr × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.inferType indexedVecInnerKernel false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 10000) + indexedVecParamCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State)) = _ + change Except.map + (fun x : Expr × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.inferType' indexedVecInnerKernel false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + indexedVecParamCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State)) = _ + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [indexedVecInnerKernel, Expr.hasLooseBVars, + Expr.looseBVarRange', + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show + Ix.Theory.Named.TypeChecker.Inner.inferForall + (.forallE indexedVecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default) + false (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + indexedVecParamCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort indexedVecInnerInferredLevel, + indexedVecInnerSortState) by + simpa [indexedVecInnerKernel] using indexedVecInnerInferForall] + rfl + +/-! The constructor pre-family replay runs after family analysis has added its +parameter and index locals, but before `IndexedVec` itself is present in the +kernel environment. The following executions expose the family-free pieces +of the family candidate proof for an arbitrary local context. -/ + +def indexedVecPreFamilyIndexTelescope : Expr := + .forallE indexedVecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default + +theorem indexedVecPreFamilyIndexTelescope_eq : + indexedVecPreFamilyIndexTelescope = indexedVecInfo.type.bindingBody! := by + rfl + +theorem indexedVecPreFamilySortCheckTypeM (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.checkType + (.sort (.succ (.param `u)))) = + .ok (.sort (.succ (.succ (.param `u)))) := + indexedVecSort_checkTypeM lctx + +theorem indexedVecPreFamilyNatCheckTypeM (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.checkType (.const ``Nat [])) = + .ok (.sort (.succ .zero)) := + indexedVecNat_checkTypeM lctx + +@[simp] private theorem indexedVecInferConstantNatOnly + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferConstant + (indexedVecTypeCheckerContext lctx) ``Nat [] true = + .ok (.sort (.succ .zero)) := by + unfold Ix.Theory.Named.TypeChecker.Inner.inferConstant + simp [indexedVecTypeCheckerContext, indexedVecKernel_get_nat, natInfo, ConstantInfo.levelParams, + ConstantInfo.instantiateTypeLevelParams, ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, Expr.instantiateLevelParams_eq, + Expr.instantiateLevelParamsCore', Level.substParams', Bind.bind, Except.bind, Pure.pure, + Except.pure] + +private def indexedVecPreFamilyNatInferOnlyState : + Ix.Theory.Named.TypeChecker.State := + { ({} : Ix.Theory.Named.TypeChecker.State) with + inferTypeI := ({} : Ix.Theory.Named.TypeChecker.State).inferTypeI.insert + (.const ``Nat []) (.sort (.succ .zero)) } + +private theorem indexedVecPreFamilyNatInferOnly + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferType (.const ``Nat []) true + (Ix.Theory.Named.TypeChecker.Methods.withFuel 10000) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort (.succ .zero), + indexedVecPreFamilyNatInferOnlyState) := by + change Ix.Theory.Named.TypeChecker.Inner.inferType' (.const ``Nat []) true + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State) = _ + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [indexedVecPreFamilyNatInferOnlyState, + Expr.hasLooseBVars, Expr.looseBVarRange', + indexedVecInferConstantNatOnly, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +theorem indexedVecPreFamilyNatEnsureTypeM (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.ensureType (.const ``Nat [])) = + .ok (.sort (.succ .zero)) := by + unfold Ix.Theory.Named.TypeChecker.ensureType Ix.Theory.Named.TypeChecker.inferType + Ix.Theory.Named.TypeChecker.ensureSort Ix.Theory.Named.TypeChecker.RecM.run + Ix.Theory.Named.TypeChecker.M.run + simp only [readThe, MonadReaderOf.read, ReaderT.read, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + Pure.pure, StateT.pure, Except.pure, StateT.run', + Functor.map, Except.map] + rw [show Ix.Theory.Named.TypeChecker.Inner.inferType (.const ``Nat []) true + (Ix.Theory.Named.TypeChecker.Methods.withFuel 10000) + { env := indexedVecKernelEnv + lctx := lctx + safety := .safe + lparams := [`u] + fuel := ({} : FuelConfig) } + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort (.succ .zero), + indexedVecPreFamilyNatInferOnlyState) by + simpa [indexedVecTypeCheckerContext] using + indexedVecPreFamilyNatInferOnly lctx] + rfl + +private def indexedVecPreFamilyIndexCheckerLctx + (lctx : LocalContext) : LocalContext := + lctx.mkLocalDecl ⟨indexedVecInnerNatState.ngen.curr⟩ + indexedVecIndexName (.const ``Nat []) .default + +private theorem indexedVecPreFamilyIndexNatCore (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferType' (.const ``Nat []) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9998) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort (.succ .zero), indexedVecInnerNatState) := by + simp [indexedVecInnerNatState] + +private theorem indexedVecPreFamilyIndexWithLocalDecl + (lctx : LocalContext) + {α} (k : Expr → Ix.Theory.Named.TypeChecker.RecM α) + (methods : Ix.Theory.Named.TypeChecker.Methods) : + (withLocalDecl (m := Ix.Theory.Named.TypeChecker.RecM) + indexedVecIndexName .default (.const ``Nat []) k) + methods (indexedVecTypeCheckerContext lctx) + indexedVecInnerNatState = + k (.fvar ⟨indexedVecInnerNatState.ngen.curr⟩) methods + { indexedVecTypeCheckerContext lctx with + lctx := indexedVecPreFamilyIndexCheckerLctx lctx } + indexedVecInnerAfterIndexState := by + simpa [indexedVecPreFamilyIndexCheckerLctx, + indexedVecInnerAfterIndexState, indexedVecTypeCheckerContext] using + (indexedVecWithLocalDecl indexedVecIndexName .default + (.const ``Nat []) k methods (indexedVecTypeCheckerContext lctx) + indexedVecInnerNatState) + +private theorem indexedVecPreFamilyIndexSortCore (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9998) + { indexedVecTypeCheckerContext lctx with + lctx := indexedVecPreFamilyIndexCheckerLctx lctx } + indexedVecInnerAfterIndexState = + .ok (.sort (.succ (.succ (.param `u))), + indexedVecInnerSortState) := by + simpa [indexedVecPreFamilyIndexCheckerLctx, + indexedVecInnerAfterIndexState, indexedVecInnerNatState, + indexedVecInnerSortState, indexedVecTypeCheckerContext] using + (indexedVecInferTypeSortCore 9998 + (indexedVecPreFamilyIndexCheckerLctx lctx) + indexedVecInnerAfterIndexState (by + simp [indexedVecInnerAfterIndexState, + indexedVecInnerNatState])) + +private theorem indexedVecPreFamilyIndexInferForall + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.Inner.inferForall + indexedVecPreFamilyIndexTelescope false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort indexedVecInnerInferredLevel, + indexedVecInnerSortState) := by + unfold indexedVecPreFamilyIndexTelescope + unfold Ix.Theory.Named.TypeChecker.Inner.inferForall + simp only [Ix.Theory.Named.TypeChecker.Inner.inferForall.loop] + rw [show (.const ``Nat [] : Expr).instantiateRev #[] = + .const ``Nat [] by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq]] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [indexedVecInferTypeFuel 9998] + rw [indexedVecPreFamilyIndexNatCore] + simp only + rw [indexedVecEnsureSort] + simp only + rw [indexedVecPreFamilyIndexWithLocalDecl] + rw [show + (.sort (.succ (.param `u)) : Expr).instantiateRev + (#[] |>.push (.fvar ⟨indexedVecInnerNatState.ngen.curr⟩)) = + .sort (.succ (.param `u)) by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq, + Expr.instantiate1']] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [indexedVecInferTypeFuel 9998] + rw [indexedVecPreFamilyIndexSortCore] + simp only + rw [indexedVecEnsureSort] + simp [indexedVecInnerInferredLevel, Expr.sortLevel!, + Pure.pure, ReaderT.pure, StateT.pure, Except.pure] + +theorem indexedVecPreFamilyIndexTelescopeCheckTypeM + (lctx : LocalContext) : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.checkType + indexedVecPreFamilyIndexTelescope) = + .ok (.sort indexedVecInnerInferredLevel) := by + change Except.map + (fun x : Expr × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.inferType' + indexedVecPreFamilyIndexTelescope false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State)) = _ + unfold Ix.Theory.Named.TypeChecker.Inner.inferType' + simp [indexedVecPreFamilyIndexTelescope, Expr.hasLooseBVars, + Expr.looseBVarRange', Bind.bind, ReaderT.bind, StateT.bind, + Except.bind] + rw [show + Ix.Theory.Named.TypeChecker.Inner.inferForall + (.forallE indexedVecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default) + false (Ix.Theory.Named.TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : Ix.Theory.Named.TypeChecker.State) = + .ok (.sort indexedVecInnerInferredLevel, + indexedVecInnerSortState) by + simpa [indexedVecPreFamilyIndexTelescope] using + indexedVecPreFamilyIndexInferForall lctx] + rfl + +private theorem indexedVecInner_whnfM : + Ix.Theory.Named.TypeChecker.M.run indexedVecKernelEnv .safe + indexedVecParamCandidateContext.lctx [`u] ({} : FuelConfig) + (Ix.Theory.Named.TypeChecker.whnf indexedVecInnerKernel) = + .ok indexedVecInnerKernel := by + rfl + +private theorem indexedVecFamilyCandidateFresh : + indexedVecFamilyCandidateContext.lctx.find? + indexedVecFamilyCandidateContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := indexedVecFamilyCandidateContext.freshFVarId) + LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + indexedVecFamilyCandidateContext.freshFVarId = none + rw [h] + simp [LocalContext.toList] + +private theorem indexedVecParamCandidateFresh : + indexedVecParamCandidateContext.lctx.find? + indexedVecParamCandidateContext.freshFVarId = none := by + have hroot := indexedVecFamilyCandidateFresh + have hwf : indexedVecParamCandidateContext.lctx.WF := by + change (({} : LocalContext).mkLocalDecl + indexedVecFamilyCandidateContext.freshFVarId + indexedVecParamName (.sort (.succ (.param `u))) .default).WF + exact LocalContext.WF.mkLocalDecl LocalContext.WF.nil (by + simpa [indexedVecFamilyCandidateContext] using hroot) + have h := LocalContext.WF.find?_eq_find?_toList + (fv := indexedVecParamCandidateContext.freshFVarId) hwf + rw [h] + simp only [indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + Ix.Theory.Named.AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp [NameGenerator.next, NameGenerator.curr] + intro heq + injection heq with hname + injection hname with hidx + omega + +private theorem indexedVecFamily_checkTypeM : + Ix.Theory.Named.TypeChecker.M.run + indexedVecFamilyCandidateContext.env + indexedVecFamilyCandidateContext.safety + indexedVecFamilyCandidateContext.lctx + indexedVecFamilyCandidateContext.lparams + indexedVecFamilyCandidateContext.fuel + (Ix.Theory.Named.TypeChecker.checkType indexedVecInfo.type) = + .ok (.sort indexedVecFamilyInferredLevel) := by + change Except.map + (fun x : Expr × Ix.Theory.Named.TypeChecker.State => x.1) + (Ix.Theory.Named.TypeChecker.Inner.inferType indexedVecInfo.type false + (Ix.Theory.Named.TypeChecker.Methods.withFuel 10000) + indexedVecFamilyCandidateContext.toTypeChecker + ({} : Ix.Theory.Named.TypeChecker.State)) = _ + rw [indexedVecFamilyCheckTypeInner] + rfl + +private def indexedVecParamAnnotations : + Ix.Theory.Named.AddInductive.CandidateTypeAnnotations + indexedVecTerminalKernel where + consumed := indexedVecTerminalKernel + trace := .identity _ + +private def indexedVecIndexAnnotations : + Ix.Theory.Named.AddInductive.CandidateTypeAnnotations (.const ``Nat []) where + consumed := .const ``Nat [] + trace := .identity _ + +private theorem indexedVecParamAnnotationTrace_build : + Ix.Theory.Named.AddInductive.CandidateTypeAnnotationTrace.build + indexedVecTerminalKernel = + ⟨indexedVecTerminalKernel, .identity _⟩ := by + simp [Ix.Theory.Named.AddInductive.CandidateTypeAnnotationTrace.build, + indexedVecTerminalKernel] + +private theorem indexedVecIndexAnnotationTrace_build : + Ix.Theory.Named.AddInductive.CandidateTypeAnnotationTrace.build + (.const ``Nat []) = ⟨.const ``Nat [], .identity _⟩ := by + simp [Ix.Theory.Named.AddInductive.CandidateTypeAnnotationTrace.build] + +private theorem indexedVecParamAnnotations_build : + Ix.Theory.Named.AddInductive.buildCandidateTypeAnnotations + indexedVecTerminalKernel = .ok indexedVecParamAnnotations := by + unfold Ix.Theory.Named.AddInductive.buildCandidateTypeAnnotations + rw [indexedVecParamAnnotationTrace_build] + rfl + +private theorem indexedVecIndexAnnotations_build : + Ix.Theory.Named.AddInductive.buildCandidateTypeAnnotations + (.const ``Nat []) = .ok indexedVecIndexAnnotations := by + unfold Ix.Theory.Named.AddInductive.buildCandidateTypeAnnotations + rw [indexedVecIndexAnnotationTrace_build] + rfl + +private theorem indexedVecParamAnnotations_match : + indexedVecParamAnnotations.Matches := + Ix.Theory.Named.AddInductive.CandidateTypeAnnotations.matches_of_build + indexedVecParamAnnotations indexedVecParamAnnotations_build + +private theorem indexedVecIndexAnnotations_match : + indexedVecIndexAnnotations.Matches := + Ix.Theory.Named.AddInductive.CandidateTypeAnnotations.matches_of_build + indexedVecIndexAnnotations indexedVecIndexAnnotations_build + +private theorem indexedVecParamAnnotationsEq : + Ix.Theory.Named.AddInductive.CandidateIsDefEqStep.Valid + ⟨indexedVecFamilyCandidateContext, indexedVecTerminalKernel, + indexedVecParamAnnotations.consumed⟩ := by + simpa [indexedVecParamAnnotations] using + (candidateIsDefEqSelfValid indexedVecFamilyCandidateContext + indexedVecTerminalKernel 9999 rfl) + +private theorem indexedVecIndexAnnotationsEq : + Ix.Theory.Named.AddInductive.CandidateIsDefEqStep.Valid + ⟨indexedVecParamCandidateContext, (.const ``Nat []), + indexedVecIndexAnnotations.consumed⟩ := by + simpa [indexedVecIndexAnnotations] using + (candidateIsDefEqSelfValid indexedVecParamCandidateContext + (.const ``Nat []) 9999 rfl) + +private def indexedVecParamDomainCandidateTrace : + Ix.Theory.Named.AddInductive.CandidateExprTrace + indexedVecFamilyCandidateContext indexedVecTerminalKernel := + .terminal indexedVecFamilyCandidateContext indexedVecTerminalKernel + (.sort (.succ (.succ (.param `u)))) indexedVecTerminalKernel + (by + simpa [Ix.Theory.Named.AddInductive.CandidateCheckTypeStep.Valid, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + indexedVecTerminalKernel] using + indexedVecSort_checkTypeM + indexedVecFamilyCandidateContext.lctx) + (by + simpa [Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + indexedVecTerminalKernel] using + indexedVecSort_whnfM indexedVecFamilyCandidateContext.lctx) + +private def indexedVecIndexDomainCandidateTrace : + Ix.Theory.Named.AddInductive.CandidateExprTrace + indexedVecParamCandidateContext (.const ``Nat []) := + .terminal indexedVecParamCandidateContext (.const ``Nat []) + (.sort (.succ .zero)) (.const ``Nat []) + (by + simpa [Ix.Theory.Named.AddInductive.CandidateCheckTypeStep.Valid, + indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl] using + indexedVecNat_checkTypeM indexedVecParamCandidateContext.lctx) + (by + simpa [Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid, + indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl] using + indexedVecNat_whnfM indexedVecParamCandidateContext.lctx) + +private def indexedVecTerminalCandidateTrace : + Ix.Theory.Named.AddInductive.CandidateExprTrace + indexedVecIndexCandidateContext + (indexedVecTerminalKernel.instantiate1 + indexedVecParamCandidateContext.freshExpr) := + .terminal indexedVecIndexCandidateContext + (indexedVecTerminalKernel.instantiate1 + indexedVecParamCandidateContext.freshExpr) + (.sort (.succ (.succ (.param `u)))) indexedVecTerminalKernel + (by + simpa [Ix.Theory.Named.AddInductive.CandidateCheckTypeStep.Valid, + indexedVecIndexCandidateContext, + indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + indexedVecTerminalKernel] using + indexedVecSort_checkTypeM indexedVecIndexCandidateContext.lctx) + (by + simpa [Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid, + indexedVecIndexCandidateContext, + indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + indexedVecTerminalKernel] using + indexedVecSort_whnfM indexedVecIndexCandidateContext.lctx) + +private def indexedVecInnerCandidateTrace : + Ix.Theory.Named.AddInductive.CandidateExprTrace + indexedVecParamCandidateContext + (indexedVecInnerKernel.instantiate1 + indexedVecFamilyCandidateContext.freshExpr) := + .forallE indexedVecParamCandidateContext + (indexedVecInnerKernel.instantiate1 + indexedVecFamilyCandidateContext.freshExpr) + (.sort indexedVecInnerInferredLevel) + indexedVecIndexName (.const ``Nat []) indexedVecTerminalKernel + .default indexedVecParamCandidateFresh indexedVecIndexAnnotations + indexedVecIndexAnnotationsEq + (by + simpa [Ix.Theory.Named.AddInductive.CandidateCheckTypeStep.Valid, + indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + indexedVecInnerKernel, indexedVecTerminalKernel, + Expr.instantiate1'] using + indexedVecInner_checkTypeM) + (by + simpa [Ix.Theory.Named.AddInductive.CandidateWhnfStep.Valid, + indexedVecParamCandidateContext, + indexedVecFamilyCandidateContext, indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + indexedVecInnerKernel, indexedVecTerminalKernel, + Expr.instantiate1'] using + indexedVecInner_whnfM) + indexedVecIndexDomainCandidateTrace indexedVecTerminalCandidateTrace + +private def indexedVecFamilyCandidateTrace : + Ix.Theory.Named.AddInductive.CandidateExprTrace + indexedVecFamilyCandidateContext indexedVecInfo.type := + .forallE indexedVecFamilyCandidateContext indexedVecInfo.type + (.sort indexedVecFamilyInferredLevel) + indexedVecParamName indexedVecTerminalKernel indexedVecInnerKernel + .default indexedVecFamilyCandidateFresh indexedVecParamAnnotations + indexedVecParamAnnotationsEq + indexedVecFamily_checkTypeM + (by + change Ix.Theory.Named.TypeChecker.M.run + indexedVecFamilyCandidateContext.env + indexedVecFamilyCandidateContext.safety + indexedVecFamilyCandidateContext.lctx + indexedVecFamilyCandidateContext.lparams + indexedVecFamilyCandidateContext.fuel + (Ix.Theory.Named.TypeChecker.whnf indexedVecInfo.type) = + .ok indexedVecInfo.type + exact indexedVecFamily_whnfM) + indexedVecParamDomainCandidateTrace indexedVecInnerCandidateTrace + +def indexedVecFamilyCandidate : + Ix.Theory.Named.AddInductive.CandidateExpr indexedVecInfo.type := + ⟨indexedVecFamilyCandidateContext, indexedVecFamilyCandidateTrace⟩ + +theorem indexedVecFamilyCandidate_view_eq : + indexedVecFamilyCandidate.view = indexedVecInfo.type := by + have habstract (context : Ix.Theory.Named.AddInductive.Context) (e : Expr) : + e.abstract #[context.freshExpr] = + Expr.abstract1 context.freshFVarId e := by + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl] + simp only [Expr.abstract_eq, Expr.abstractList] + simp only [indexedVecFamilyCandidate, + Ix.Theory.Named.AddInductive.CandidateExpr.view, + indexedVecFamilyCandidateTrace, + indexedVecInnerCandidateTrace, indexedVecParamDomainCandidateTrace, + indexedVecIndexDomainCandidateTrace, indexedVecTerminalCandidateTrace, + Ix.Theory.Named.AddInductive.CandidateExprTrace.view] + rw [habstract, habstract] + simp [Expr.abstract1, indexedVecTerminalKernel, + indexedVecFamilyCandidateContext, + Ix.Theory.Named.AddInductive.Context.pushLocalDecl, + Ix.Theory.Named.AddInductive.Context.freshFVarId, + NameGenerator.next, NameGenerator.curr, + indexedVecInfo, ConstantInfo.type, ConstantInfo.toConstantVal] + constructor <;> rfl + +/-- Every retained family-type candidate node preserves its kernel source. +This is the structural premise used by the semantic spine interpreter; it is +stronger than the root `view` equality because it covers both Pi domains and +the instantiated body under their exact candidate contexts. -/ +theorem indexedVecFamilyCandidate_identity : + Ix.Theory.Named.TypeChecker.CandidateExprIdentity + indexedVecFamilyCandidate.trace := by + change Ix.Theory.Named.TypeChecker.CandidateExprIdentity + indexedVecFamilyCandidateTrace + unfold indexedVecFamilyCandidateTrace + refine .forallE (name := indexedVecParamName) (binderInfo := .default) + (body := indexedVecInnerKernel) + (annotations := indexedVecParamAnnotations) + indexedVecParamDomainCandidateTrace indexedVecInnerCandidateTrace + ?_ rfl (.terminal rfl) ?_ + · rfl + · unfold indexedVecInnerCandidateTrace + refine .forallE (name := indexedVecIndexName) (binderInfo := .default) + (body := indexedVecTerminalKernel) + (annotations := indexedVecIndexAnnotations) + indexedVecIndexDomainCandidateTrace indexedVecTerminalCandidateTrace + ?_ rfl (.terminal rfl) ?_ + · simpa only [Expr.instantiate1_eq, indexedVecInnerKernel, + indexedVecTerminalKernel] using + indexedVecInnerKernel_instantiate1 + indexedVecFamilyCandidateContext.freshExpr + · exact .terminal (by + simpa only [Expr.instantiate1_eq] using + (indexedVecTerminalKernel_instantiate1 + indexedVecParamCandidateContext.freshExpr).symm) + +private theorem indexedVecParamDomainCandidateTrace_loop (fuel : Nat) : + Ix.Theory.Named.AddInductive.buildCandidateExpr.loop + indexedVecFamilyCandidateContext indexedVecTerminalKernel + (fuel + 1) = .ok indexedVecParamDomainCandidateTrace := by + simpa only [indexedVecParamDomainCandidateTrace] using + Ix.Theory.Named.AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + indexedVecFamilyCandidateContext indexedVecTerminalKernel + (.sort (.succ (.succ (.param `u)))) indexedVecTerminalKernel fuel + indexedVecParamDomainCandidateTrace.rootCheck.valid + indexedVecParamDomainCandidateTrace.rootWhnf_valid rfl + +private theorem indexedVecIndexDomainCandidateTrace_loop (fuel : Nat) : + Ix.Theory.Named.AddInductive.buildCandidateExpr.loop + indexedVecParamCandidateContext (.const ``Nat []) (fuel + 1) = + .ok indexedVecIndexDomainCandidateTrace := by + simpa only [indexedVecIndexDomainCandidateTrace] using + Ix.Theory.Named.AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + indexedVecParamCandidateContext (.const ``Nat []) + (.sort (.succ .zero)) (.const ``Nat []) fuel + indexedVecIndexDomainCandidateTrace.rootCheck.valid + indexedVecIndexDomainCandidateTrace.rootWhnf_valid rfl + +private theorem indexedVecTerminalCandidateTrace_loop (fuel : Nat) : + Ix.Theory.Named.AddInductive.buildCandidateExpr.loop + indexedVecIndexCandidateContext + (indexedVecTerminalKernel.instantiate1 + indexedVecParamCandidateContext.freshExpr) + (fuel + 1) = .ok indexedVecTerminalCandidateTrace := by + simpa only [indexedVecTerminalCandidateTrace] using + Ix.Theory.Named.AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + indexedVecIndexCandidateContext + (indexedVecTerminalKernel.instantiate1 + indexedVecParamCandidateContext.freshExpr) + (.sort (.succ (.succ (.param `u)))) indexedVecTerminalKernel fuel + indexedVecTerminalCandidateTrace.rootCheck.valid + indexedVecTerminalCandidateTrace.rootWhnf_valid rfl + +private theorem indexedVecInnerCandidateTrace_loop : + Ix.Theory.Named.AddInductive.buildCandidateExpr.loop + indexedVecParamCandidateContext + (indexedVecInnerKernel.instantiate1 + indexedVecFamilyCandidateContext.freshExpr) 999 = + .ok indexedVecInnerCandidateTrace := by + rw [show 999 = 998 + 1 by rfl] + simpa only [indexedVecInnerCandidateTrace, + indexedVecIndexCandidateContext] using + (Ix.Theory.Named.AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := indexedVecParamCandidateContext) + (e := indexedVecInnerKernel.instantiate1 + indexedVecFamilyCandidateContext.freshExpr) + (inferred := .sort indexedVecInnerInferredLevel) + (fuel := 998) (name := indexedVecIndexName) + (domain := .const ``Nat []) (body := indexedVecTerminalKernel) + (binderInfo := .default) (hfresh := indexedVecParamCandidateFresh) + (annotations := indexedVecIndexAnnotations) + (hannotations := indexedVecIndexAnnotations_build) + (hannotationsEq := indexedVecIndexAnnotationsEq) + (hcheck := indexedVecInnerCandidateTrace.rootCheck.valid) + (hrun := indexedVecInnerCandidateTrace.rootWhnf_valid) + (domainCandidate := indexedVecIndexDomainCandidateTrace) + (bodyCandidate := indexedVecTerminalCandidateTrace) + (hdomain := by + simpa using indexedVecIndexDomainCandidateTrace_loop 997) + (hbody := by + simpa [indexedVecIndexCandidateContext, + indexedVecIndexAnnotations] using + indexedVecTerminalCandidateTrace_loop 997)) + +private theorem indexedVecFamilyCandidateTrace_loop : + Ix.Theory.Named.AddInductive.buildCandidateExpr.loop + indexedVecFamilyCandidateContext indexedVecInfo.type + indexedVecFamilyCandidateContext.fuel.inductiveFuel = + .ok indexedVecFamilyCandidateTrace := by + change Ix.Theory.Named.AddInductive.buildCandidateExpr.loop + indexedVecFamilyCandidateContext indexedVecInfo.type (999 + 1) = _ + simpa only [indexedVecFamilyCandidateTrace, + indexedVecParamCandidateContext] using + (Ix.Theory.Named.AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := indexedVecFamilyCandidateContext) + (e := indexedVecInfo.type) + (inferred := .sort indexedVecFamilyInferredLevel) + (fuel := 999) (name := indexedVecParamName) + (domain := indexedVecTerminalKernel) (body := indexedVecInnerKernel) + (binderInfo := .default) (hfresh := indexedVecFamilyCandidateFresh) + (annotations := indexedVecParamAnnotations) + (hannotations := indexedVecParamAnnotations_build) + (hannotationsEq := indexedVecParamAnnotationsEq) + (hcheck := indexedVecFamilyCandidateTrace.rootCheck.valid) + (hrun := indexedVecFamilyCandidateTrace.rootWhnf_valid) + (domainCandidate := indexedVecParamDomainCandidateTrace) + (bodyCandidate := indexedVecInnerCandidateTrace) + (hdomain := by + simpa using indexedVecParamDomainCandidateTrace_loop 998) + (hbody := by + simpa [indexedVecParamCandidateContext, + indexedVecParamAnnotations, indexedVecTerminalKernel] using + indexedVecInnerCandidateTrace_loop)) + +/-- The executable candidate traversal preserves the real IndexedVec family +telescope and classifies its first binder as a parameter and its second as an +index in the subsequent family-validation pass. -/ +theorem indexedVecFamily_candidateTrace : + Ix.Theory.Named.AddInductive.buildCandidateExpr indexedVecInfo.type + indexedVecFamilyCandidateContext = .ok indexedVecFamilyCandidate := by + unfold Ix.Theory.Named.AddInductive.buildCandidateExpr + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + rw [indexedVecFamilyCandidateTrace_loop] + rfl + +/-- The executable IndexedVec family candidate retains its parameter and +index binders in order. -/ +theorem indexedVecFamilyCandidate_spineLength : + indexedVecFamilyCandidate.trace.spineLength = 2 := by + rfl + +theorem indexedVecFamilyCandidate_validationAnnotations : + indexedVecFamilyCandidate.trace.validationAnnotations := by + exact ⟨indexedVecParamAnnotations_match, + indexedVecIndexAnnotations_match, trivial⟩ + +theorem indexedVecFamilyCandidate_terminalResult : + indexedVecFamilyCandidate.trace.terminalResult = + .sort (.succ (.param `u)) := by + rfl + +def indexedVecKernelNil : Constructor where + name := indexedVecNilInfo.name + type := indexedVecNilInfo.type + +def indexedVecKernelCons : Constructor where + name := indexedVecConsInfo.name + type := indexedVecConsInfo.type + +def indexedVecKernelType : InductiveType where + name := indexedVecInfo.name + type := indexedVecInfo.type + ctors := [indexedVecKernelNil, indexedVecKernelCons] + +def indexedVecCandidateInductiveStats : + Ix.Theory.Named.AddInductive.InductiveStats := + indexedVecFamilyCandidate.trace.singletonCandidateInductiveStats + indexedVecKernelType 1 (.succ (.param `u)) + +private theorem indexedVecFamily_data_hasExprMVar_false : + indexedVecInfo.type.data.hasExprMVar = false := by + change indexedVecInfo.type.hasExprMVar = false + rw [Expr.hasExprMVar_eq] + rfl + +private theorem indexedVecFamily_data_hasLevelMVar_false : + indexedVecInfo.type.data.hasLevelMVar = false := by + change indexedVecInfo.type.hasLevelMVar = false + rw [Expr.hasLevelMVar_eq] + simp [indexedVecInfo, ConstantInfo.type, ConstantInfo.toConstantVal, + Expr.hasLevelMVar', Level.hasMVar_eq, Level.hasMVar'] + +private theorem indexedVecFamily_data_hasFVar_false : + indexedVecInfo.type.data.hasFVar = false := by + change indexedVecInfo.type.hasFVar = false + rw [Expr.hasFVar_eq] + rfl + +private theorem indexedVecFamily_hasMVar_false : + indexedVecInfo.type.hasMVar = false := by + change (indexedVecInfo.type.data.hasExprMVar || + indexedVecInfo.type.data.hasLevelMVar) = false + rw [indexedVecFamily_data_hasExprMVar_false, + indexedVecFamily_data_hasLevelMVar_false] + rfl + +private theorem indexedVecFamily_hasFVar_false : + indexedVecInfo.type.hasFVar = false := by + exact indexedVecFamily_data_hasFVar_false + +private theorem indexedVecFamily_closed : + indexedVecFamilyCandidateContext.env.checkNoMVarNoFVar + indexedVecKernelType.name indexedVecKernelType.type = .ok () := by + unfold Kernel.Environment.checkNoMVarNoFVar + Kernel.Environment.checkNoMVar Kernel.Environment.checkNoFVar + rw [show indexedVecKernelType.type.hasMVar = false by + simpa [indexedVecKernelType] using indexedVecFamily_hasMVar_false] + rw [show indexedVecKernelType.type.hasFVar = false by + simpa [indexedVecKernelType] using indexedVecFamily_hasFVar_false] + rfl + +private theorem indexedVecTerminal_ensureSortM : + Ix.Theory.Named.TypeChecker.M.run + indexedVecFamilyCandidate.trace.terminalContext.env + indexedVecFamilyCandidate.trace.terminalContext.safety + indexedVecFamilyCandidate.trace.terminalContext.lctx + indexedVecFamilyCandidate.trace.terminalContext.lparams + indexedVecFamilyCandidate.trace.terminalContext.fuel + (Ix.Theory.Named.TypeChecker.ensureSort + (.sort (.succ (.param `u)))) = + .ok (.sort (.succ (.param `u))) := by + rfl + +/-- The real IndexedVec family telescope drives the complete singleton +family-validation pass with one parameter and one index. -/ +theorem indexedVec_checkInductiveTypes + (k : Ix.Theory.Named.AddInductive.InductiveStats → + Ix.Theory.Named.AddInductive.M α) : + Ix.Theory.Named.AddInductive.checkInductiveTypes 1 + #[indexedVecKernelType] k indexedVecFamilyCandidateContext = + k indexedVecCandidateInductiveStats + indexedVecFamilyCandidate.trace.terminalContext := by + change Ix.Theory.Named.AddInductive.checkInductiveTypes 1 + #[indexedVecKernelType] k indexedVecFamilyCandidate.context = + k indexedVecCandidateInductiveStats + indexedVecFamilyCandidate.trace.terminalContext + exact + Ix.Theory.Named.AddInductive.CandidateExprTrace.checkInductiveTypes_singleton_of_candidate + (indType := indexedVecKernelType) + (candidate := indexedVecFamilyCandidate.trace) + (nparams := 1) (resultLevel := .succ (.param `u)) (k := k) + indexedVecFamily_closed (by decide) (by decide) + ⟨indexedVecParamAnnotations_match, + indexedVecIndexAnnotations_match, trivial⟩ + rfl indexedVecTerminal_ensureSortM + +theorem indexedVecCandidateInductiveStats_nindices : + indexedVecCandidateInductiveStats.nindices = #[1] := by + rfl + +theorem indexedVecCandidateInductiveStats_params : + indexedVecCandidateInductiveStats.params = + #[indexedVecFamilyCandidateContext.freshExpr] := by + rfl + +theorem indexedVecCandidateInductiveStats_resultLevel : + indexedVecCandidateInductiveStats.resultLevel = + .succ (.param `u) := by + rfl + +theorem indexedVecCandidateInductiveStats_indConsts : + indexedVecCandidateInductiveStats.indConsts = + #[.const ``IndexedVec [.param `u]] := by + rfl + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.candidateIsDefEqSelfValid [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Syntax.structEq_eq] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecFamily_candidateTrace [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVec_checkInductiveTypes [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecCandidateInductiveStats_nindices [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecCandidateInductiveStats_params [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/IndexedVecConsReplay.lean b/Ix/Theory/Named/Verify/Environment/IndexedVecConsReplay.lean new file mode 100644 index 000000000..15ccbc80b --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/IndexedVecConsReplay.lean @@ -0,0 +1,2863 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.IndexedVecConstructors + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta +open Ix.Theory.Named.InductiveFixtures + +namespace IndexedVecConsReplay + + + + + + +def replayInsert (state : TypeChecker.State) (e type : Expr) : + TypeChecker.State := + { state with inferTypeC := state.inferTypeC.insert e type } + +open private mkLevelIMaxCore mkLevelMaxCore from Lean.Level in +@[simp] theorem replayMkLevelIMaxSuccParamSelf : + mkLevelIMax' (.succ (.param `u)) (.succ (.param `u)) = + .succ (.param `u) := by + simp [mkLevelIMax', mkLevelIMaxCore, mkLevelMax', mkLevelMaxCore] + +def replayFirstApp (alpha : Expr) : Expr := + .app (.const ``IndexedVec [.param `u]) alpha + +@[simp] theorem replayAppBeqFVar (fn arg : Expr) (id : FVarId) : + ((.app fn arg : Expr) == .fvar id) = false := by + change Expr.eqv (.app fn arg) (.fvar id) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem replayFVarBeqApp (id : FVarId) (fn arg : Expr) : + ((.fvar id : Expr) == .app fn arg) = false := by + change Expr.eqv (.fvar id) (.app fn arg) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem replayConstBeqApp + (name : Name) (levels : List Level) (fn arg : Expr) : + ((.const name levels : Expr) == .app fn arg) = false := by + change Expr.eqv (.const name levels) (.app fn arg) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem replayAppBeqConst + (fn arg : Expr) (name : Name) (levels : List Level) : + ((.app fn arg : Expr) == .const name levels) = false := by + change Expr.eqv (.app fn arg) (.const name levels) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem replayIndexedVecConstBeqSucc : + ((.const ``IndexedVec [.param `u] : Expr) == + .const ``Nat.succ []) = false := by + change Expr.eqv (.const ``IndexedVec [.param `u]) + (.const ``Nat.succ []) = false + rw [Expr.eqv_eq] + simp [Expr.eqv'] + +@[simp] theorem replayAlphaBeqN : + ((consAlphaExpr : Expr) == consNExpr) = false := by + change Expr.eqv consAlphaExpr consNExpr = false + rw [Expr.eqv_eq] + simp [Expr.eqv', consAlphaExpr, consNExpr, consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl, AddInductive.Context.freshExpr, + AddInductive.Context.freshFVarId, NameGenerator.next, NameGenerator.curr] + +@[simp] theorem replayAlphaIdBeqNId : + ((.fvar consAlphaId : Expr) == .fvar consNId) = false := by + simpa using replayAlphaBeqN + +theorem replayInferFirstAppFVarCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (id : FVarId) + (hfamily : state.inferTypeC[ + (.const ``IndexedVec [.param `u] : Expr)]? = none) + (halpha : (replayInsert state + (.const ``IndexedVec [.param `u]) indexedVecInfo.type).inferTypeC[ + (.fvar id : Expr)]? = none) + (happ : state.inferTypeC[replayFirstApp (.fvar id)]? = none) + (hfind : lctx.find? id = some (.cdecl index id name + (.sort (.succ (.param `u))) bi kind)) : + TypeChecker.Inner.inferType' (replayFirstApp (.fvar id)) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (vecFamilyTail, + replayInsert + (replayInsert + (replayInsert state + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (.fvar id) (.sort (.succ (.param `u)))) + (replayFirstApp (.fvar id)) vecFamilyTail) := by + have hfamilyRun := inferTypeFamilyCore fuel lctx state hfamily + have halphaRun := inferTypeFVarCore fuel lctx + (replayInsert state (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + id (.sort (.succ (.param `u))) halpha hfind + have happRun := inferAppCoreOf fuel (tcContext lctx) + state + (replayInsert state (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (replayInsert + (replayInsert state (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (.fvar id) (.sort (.succ (.param `u)))) + (.const ``IndexedVec [.param `u]) (.fvar id) + (.sort (.succ (.param `u))) vecFamilyTail `α .default + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) + happ + (by simpa [replayInsert, indexedVecInfoTypeShape] using hfamilyRun) + (by simpa [replayInsert] using halphaRun) + (by rfl) + simpa [replayInsert, replayFirstApp, vecFamilyTail, + Expr.instantiate1'] using happRun + +def replaySuccApp (n : Expr) : Expr := + .app (.const ``Nat.succ []) n + +@[simp] theorem replayFirstAppBeqSuccApp (alpha n : Expr) : + (replayFirstApp alpha == replaySuccApp n) = false := by + change Expr.eqv (replayFirstApp alpha) (replaySuccApp n) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', replayFirstApp, replaySuccApp] + +@[simp] theorem replayFirstAppBeqSuccLiteral (alpha n : Expr) : + (replayFirstApp alpha == .app (.const ``Nat.succ []) n) = false := by + simpa [replaySuccApp] using replayFirstAppBeqSuccApp alpha n + +theorem replayInferSuccFVarCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (id : FVarId) + (hsucc : state.inferTypeC[(.const ``Nat.succ [] : Expr)]? = none) + (hn : (replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)).inferTypeC[ + (.fvar id : Expr)]? = none) + (happ : state.inferTypeC[replaySuccApp (.fvar id)]? = none) + (hfind : lctx.find? id = some (.cdecl index id name + (.const ``Nat []) bi kind)) : + TypeChecker.Inner.inferType' (replaySuccApp (.fvar id)) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.const ``Nat [], + replayInsert + (replayInsert + (replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + (.fvar id) (.const ``Nat [])) + (replaySuccApp (.fvar id)) (.const ``Nat [])) := by + have hsuccRun := inferTypeSuccCore fuel lctx state hsucc + have hnRun := inferTypeFVarCore fuel lctx + (replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + id (.const ``Nat []) hn hfind + have happRun := inferAppCoreOf fuel (tcContext lctx) + state + (replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + (replayInsert + (replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + (.fvar id) (.const ``Nat [])) + (.const ``Nat.succ []) (.fvar id) (.const ``Nat []) + (.const ``Nat []) `n .default + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) + happ + (by simpa [replayInsert] using hsuccRun) + (by simpa [replayInsert] using hnRun) + (by rfl) + simpa [replayInsert, replaySuccApp, Expr.instantiate1_eq, + Expr.instantiate1'] using happRun + +theorem replayInferIndexedVecAppCore + (fuel : Nat) (lctx : LocalContext) + (state stateFn stateArg : TypeChecker.State) + (alpha indexExpr : Expr) + (hclosed : (ctorIndexedVecApp alpha indexExpr).hasLooseBVars = false) + (hcache : state.inferTypeC[ctorIndexedVecApp alpha indexExpr]? = none) + (hfn : TypeChecker.Inner.inferType' (replayFirstApp alpha) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (vecFamilyTail, stateFn)) + (harg : TypeChecker.Inner.inferType' indexExpr false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) stateFn = + .ok (.const ``Nat [], stateArg)) + (heager : indexExpr.isAppOfArity ``eagerReduce 2 = false) : + TypeChecker.Inner.inferType' (ctorIndexedVecApp alpha indexExpr) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.sort (.succ (.param `u)), + replayInsert stateArg (ctorIndexedVecApp alpha indexExpr) + (.sort (.succ (.param `u)))) := by + have h := inferAppCoreOf fuel (tcContext lctx) state stateFn stateArg + (replayFirstApp alpha) indexExpr (.const ``Nat []) + (.sort (.succ (.param `u))) vecIndexName .default + hclosed hcache + (by simpa [replayFirstApp, vecFamilyTail] using hfn) harg heager + simpa [replayInsert, ctorIndexedVecApp, replayFirstApp, + vecFamilyTail, Expr.instantiate1_eq, Expr.instantiate1'] using h + +theorem replayInferTypeCachedCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (e type : Expr) + (hclosed : e.hasLooseBVars = false) + (hcache : state.inferTypeC[e]? = some type) : + TypeChecker.Inner.inferType' e false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (type, state) := by + unfold TypeChecker.Inner.inferType' + simp [hclosed, hcache] + +theorem replayInferFirstAppAlphaCachedCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (alphaId : FVarId) + (halpha : state.inferTypeC[(.fvar alphaId : Expr)]? = + some (.sort (.succ (.param `u)))) + (hfamily : state.inferTypeC[ + (.const ``IndexedVec [.param `u] : Expr)]? = none) + (happ : state.inferTypeC[replayFirstApp (.fvar alphaId)]? = none) : + TypeChecker.Inner.inferType' (replayFirstApp (.fvar alphaId)) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (vecFamilyTail, + replayInsert + (replayInsert state + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (replayFirstApp (.fvar alphaId)) vecFamilyTail) := by + let familyState := replayInsert state + (.const ``IndexedVec [.param `u]) indexedVecInfo.type + have hfamilyRun := inferTypeFamilyCore fuel lctx state hfamily + have halphaCache : familyState.inferTypeC[(.fvar alphaId : Expr)]? = + some (.sort (.succ (.param `u))) := by + simp only [familyState, replayInsert, Std.HashMap.getElem?_insert] + rw [constBeqFVar] + exact halpha + have halphaRun := replayInferTypeCachedCore fuel lctx familyState + (.fvar alphaId) (.sort (.succ (.param `u))) + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) halphaCache + have hrun := inferAppCoreOf fuel (tcContext lctx) + state familyState familyState + (.const ``IndexedVec [.param `u]) (.fvar alphaId) + (.sort (.succ (.param `u))) vecFamilyTail `α .default + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) + happ + (by simpa [familyState, replayInsert, indexedVecInfoTypeShape] using + hfamilyRun) + halphaRun (by rfl) + simpa [familyState, replayInsert, replayFirstApp, vecFamilyTail, + Expr.instantiate1'] using hrun + +theorem replayInferTailDomainAlphaCachedCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (alphaId nId : FVarId) + (halpha : state.inferTypeC[(.fvar alphaId : Expr)]? = + some (.sort (.succ (.param `u)))) + (hfamily : state.inferTypeC[ + (.const ``IndexedVec [.param `u] : Expr)]? = none) + (hfirstApp : state.inferTypeC[ + replayFirstApp (.fvar alphaId)]? = none) + (hn : (replayInsert + (replayInsert state (.const ``IndexedVec [.param `u]) + indexedVecInfo.type) + (replayFirstApp (.fvar alphaId)) vecFamilyTail).inferTypeC[ + (.fvar nId : Expr)]? = none) + (htail : state.inferTypeC[ + ctorIndexedVecApp (.fvar alphaId) (.fvar nId)]? = none) + (hfind : lctx.find? nId = some (.cdecl index nId name + (.const ``Nat []) bi kind)) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) (.fvar nId)) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.sort (.succ (.param `u)), + replayInsert + (replayInsert + (replayInsert + (replayInsert state (.const ``IndexedVec [.param `u]) + indexedVecInfo.type) + (replayFirstApp (.fvar alphaId)) vecFamilyTail) + (.fvar nId) (.const ``Nat [])) + (ctorIndexedVecApp (.fvar alphaId) (.fvar nId)) + (.sort (.succ (.param `u)))) := by + let firstState := replayInsert + (replayInsert state (.const ``IndexedVec [.param `u]) + indexedVecInfo.type) + (replayFirstApp (.fvar alphaId)) vecFamilyTail + let nState := replayInsert firstState (.fvar nId) (.const ``Nat []) + have hfirstRun := replayInferFirstAppAlphaCachedCore fuel lctx state + alphaId halpha hfamily hfirstApp + have hnRun := inferTypeFVarCore fuel lctx firstState nId + (.const ``Nat []) hn hfind + have hrun := replayInferIndexedVecAppCore fuel lctx state firstState nState + (.fvar alphaId) (.fvar nId) + (by simp [ctorIndexedVecApp, Expr.hasLooseBVars, + Expr.looseBVarRange']) + htail + (by simpa [firstState] using hfirstRun) + (by simpa [firstState, nState, replayInsert] using hnRun) + (by rfl) + simpa [firstState, nState, replayInsert] using hrun + +theorem replayInferSuccFVarCachedCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (id : FVarId) + (hsucc : state.inferTypeC[(.const ``Nat.succ [] : Expr)]? = none) + (hn : state.inferTypeC[(.fvar id : Expr)]? = some (.const ``Nat [])) + (happ : state.inferTypeC[replaySuccApp (.fvar id)]? = none) : + TypeChecker.Inner.inferType' (replaySuccApp (.fvar id)) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.const ``Nat [], + replayInsert + (replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + (replaySuccApp (.fvar id)) (.const ``Nat [])) := by + let succState := replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) + have hsuccRun := inferTypeSuccCore fuel lctx state hsucc + have hnCache : succState.inferTypeC[(.fvar id : Expr)]? = + some (.const ``Nat []) := by + simp only [succState, replayInsert, Std.HashMap.getElem?_insert] + rw [constBeqFVar] + exact hn + have hnRun := replayInferTypeCachedCore fuel lctx succState + (.fvar id) (.const ``Nat []) + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) hnCache + have happRun := inferAppCoreOf fuel (tcContext lctx) + state succState succState + (.const ``Nat.succ []) (.fvar id) (.const ``Nat []) + (.const ``Nat []) `n .default + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) + happ + (by simpa [succState, replayInsert] using hsuccRun) + hnRun (by rfl) + simpa [succState, replayInsert, replaySuccApp, + Expr.instantiate1_eq, Expr.instantiate1'] using happRun + +theorem replayInferIndexedVecSuccFromCacheCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (alphaId nId : FVarId) + (hfirst : state.inferTypeC[replayFirstApp (.fvar alphaId)]? = + some vecFamilyTail) + (hsucc : state.inferTypeC[(.const ``Nat.succ [] : Expr)]? = none) + (hn : state.inferTypeC[(.fvar nId : Expr)]? = some (.const ``Nat [])) + (hsuccApp : state.inferTypeC[replaySuccApp (.fvar nId)]? = none) + (hresult : state.inferTypeC[ + ctorIndexedVecApp (.fvar alphaId) (replaySuccApp (.fvar nId))]? = none) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) (replaySuccApp (.fvar nId))) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.sort (.succ (.param `u)), + replayInsert + (replayInsert + (replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + (replaySuccApp (.fvar nId)) (.const ``Nat [])) + (ctorIndexedVecApp (.fvar alphaId) + (replaySuccApp (.fvar nId))) + (.sort (.succ (.param `u)))) := by + let succState := replayInsert state (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) + let succAppState := replayInsert succState + (replaySuccApp (.fvar nId)) (.const ``Nat []) + have hfirstRun := replayInferTypeCachedCore fuel lctx state + (replayFirstApp (.fvar alphaId)) vecFamilyTail + (by simp [replayFirstApp, Expr.hasLooseBVars, + Expr.looseBVarRange']) hfirst + have hsuccRun := replayInferSuccFVarCachedCore fuel lctx state nId + hsucc hn hsuccApp + have h := replayInferIndexedVecAppCore fuel lctx state state succAppState + (.fvar alphaId) (replaySuccApp (.fvar nId)) + (by simp [ctorIndexedVecApp, replaySuccApp, + Expr.hasLooseBVars, Expr.looseBVarRange']) + hresult hfirstRun + (by simpa [succState, succAppState] using hsuccRun) + (by rfl) + simpa [succState, succAppState, replayInsert] using h + +def consHeadFirstAppState : TypeChecker.State := + replayInsert + (replayInsert + (replayInsert ({} : TypeChecker.State) + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + consAlphaExpr (.sort (.succ (.param `u)))) + (replayFirstApp consAlphaExpr) vecFamilyTail + +def consHeadNState : TypeChecker.State := + replayInsert consHeadFirstAppState consNExpr (.const ``Nat []) + +def consTailDomainFinalState : TypeChecker.State := + replayInsert consHeadNState consTailDomain + (.sort (.succ (.param `u))) + +theorem replayInferConsHeadFirstApp (fuel : Nat) : + TypeChecker.Inner.inferType' (replayFirstApp consAlphaExpr) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State) = + .ok (vecFamilyTail, consHeadFirstAppState) := by + simpa [consHeadFirstAppState, consAlphaExprShape] using + (replayInferFirstAppFVarCore fuel consHeadContext.lctx + ({} : TypeChecker.State) consAlphaId + (by simp) + (by simp [replayInsert]) + (by simp [replayFirstApp]) + consAlphaFindInHead) + +theorem replayInferConsHeadN (fuel : Nat) : + TypeChecker.Inner.inferType' consNExpr false + (TypeChecker.Methods.withFuel fuel) + (tcContext consHeadContext.lctx) consHeadFirstAppState = + .ok (.const ``Nat [], consHeadNState) := by + simpa [consHeadNState, consNExprShape, replayInsert] using + (inferTypeFVarCore fuel consHeadContext.lctx + consHeadFirstAppState consNId (.const ``Nat []) + (index := 1) (name := consNName) (bi := .implicit) + (kind := .default) + (by simp [consHeadFirstAppState, replayInsert, replayFirstApp]) + consNFindInHead) + +theorem replayInferConsTailDomainCore (fuel : Nat) : + TypeChecker.Inner.inferType' consTailDomain false + (TypeChecker.Methods.withFuel fuel) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), consTailDomainFinalState) := by + simpa [consTailDomainFinalState, consTailDomain, + ctorIndexedVecApp, replayFirstApp] using + (replayInferIndexedVecAppCore fuel consHeadContext.lctx + ({} : TypeChecker.State) consHeadFirstAppState consHeadNState + consAlphaExpr consNExpr + (by simp [ctorIndexedVecApp, consAlphaExprShape, + consNExprShape, Expr.hasLooseBVars, Expr.looseBVarRange']) + (by simp [ctorIndexedVecApp, consAlphaExprShape, consNExprShape]) + (replayInferConsHeadFirstApp fuel) (replayInferConsHeadN fuel) (by rfl)) + +theorem replayInferConsTailDomain : + TypeChecker.Inner.inferType consTailDomain false + (TypeChecker.Methods.withFuel 10000) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), consTailDomainFinalState) := by + change TypeChecker.Inner.inferType' consTailDomain false + (TypeChecker.Methods.withFuel 9999) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State) = _ + exact replayInferConsTailDomainCore 9999 + +theorem replayConsTailDomainCheckTypeM : + TypeChecker.M.run ctorEnv .safe consHeadContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType consTailDomain) = + .ok (.sort (.succ (.param `u))) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType consTailDomain false + (TypeChecker.Methods.withFuel 10000) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State)) = _ + rw [replayInferConsTailDomain] + rfl + +def consTailFirstAppState : TypeChecker.State := + replayInsert + (replayInsert + (replayInsert ({} : TypeChecker.State) + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + consAlphaExpr (.sort (.succ (.param `u)))) + (replayFirstApp consAlphaExpr) vecFamilyTail + +def consTailSuccState : TypeChecker.State := + replayInsert + (replayInsert + (replayInsert consTailFirstAppState (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + consNExpr (.const ``Nat [])) + (replaySuccApp consNExpr) (.const ``Nat []) + +def consTerminalFinalState : TypeChecker.State := + replayInsert consTailSuccState consTerminal + (.sort (.succ (.param `u))) + +theorem replayInferConsTailFirstApp : + TypeChecker.Inner.inferType' (replayFirstApp consAlphaExpr) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consTailContext.lctx) ({} : TypeChecker.State) = + .ok (vecFamilyTail, consTailFirstAppState) := by + simpa [consTailFirstAppState, consAlphaExprShape] using + (replayInferFirstAppFVarCore 9999 consTailContext.lctx + ({} : TypeChecker.State) consAlphaId + (by simp) + (by simp [replayInsert]) + (by simp [replayFirstApp]) + consAlphaFindInTail) + +theorem replayInferConsTailSucc : + TypeChecker.Inner.inferType' (replaySuccApp consNExpr) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consTailContext.lctx) consTailFirstAppState = + .ok (.const ``Nat [], consTailSuccState) := by + simpa [consTailSuccState, consNExprShape] using + (replayInferSuccFVarCore 9999 consTailContext.lctx + consTailFirstAppState consNId + (by simp [consTailFirstAppState, replayInsert, replayFirstApp]) + (by simp [consTailFirstAppState, replayInsert, + replayFirstApp]) + (by simp [consTailFirstAppState, replayInsert, replaySuccApp]) + consNFindInTail) + +theorem replayInferConsTerminal : + TypeChecker.Inner.inferType consTerminal false + (TypeChecker.Methods.withFuel 10000) + (tcContext consTailContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), consTerminalFinalState) := by + change TypeChecker.Inner.inferType' consTerminal false + (TypeChecker.Methods.withFuel 9999) + (tcContext consTailContext.lctx) ({} : TypeChecker.State) = _ + simpa [consTerminalFinalState, consTerminal, + ctorIndexedVecApp, replayFirstApp, replaySuccApp] using + (replayInferIndexedVecAppCore 9999 consTailContext.lctx + ({} : TypeChecker.State) consTailFirstAppState consTailSuccState + consAlphaExpr (replaySuccApp consNExpr) + (by simp [ctorIndexedVecApp, replaySuccApp, + Expr.hasLooseBVars, Expr.looseBVarRange']) + (by simp [ctorIndexedVecApp, replaySuccApp]) + replayInferConsTailFirstApp replayInferConsTailSucc + (by rfl)) + +theorem replayConsTerminalCheckTypeM : + TypeChecker.M.run ctorEnv .safe consTailContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType consTerminal) = + .ok (.sort (.succ (.param `u))) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType consTerminal false + (TypeChecker.Methods.withFuel 10000) + (tcContext consTailContext.lctx) ({} : TypeChecker.State)) = _ + rw [replayInferConsTerminal] + rfl + +theorem replayConsTailDomainWhnfM : + TypeChecker.M.run ctorEnv .safe consHeadContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.whnf consTailDomain) = + .ok consTailDomain := by + simpa [consTailDomain, ctorIndexedVecApp] using + (ctorIndexedVecWhnfM consHeadContext.lctx consAlphaExpr consNExpr) + +theorem replayConsTerminalWhnfM : + TypeChecker.M.run ctorEnv .safe consTailContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.whnf consTerminal) = + .ok consTerminal := by + simpa [consTerminal, ctorIndexedVecApp, replaySuccApp] using + (ctorIndexedVecWhnfM consTailContext.lctx consAlphaExpr + (replaySuccApp consNExpr)) + +theorem replayConsRootWhnfM : + TypeChecker.M.run ctorEnv .safe {} [`u] ({} : FuelConfig) + (TypeChecker.whnf indexedVecConsInfo.type) = + .ok indexedVecConsInfo.type := by rfl + +theorem replayConsAfterAlphaWhnfM : + TypeChecker.M.run ctorEnv .safe consAlphaContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.whnf consAfterAlpha) = + .ok consAfterAlpha := by rfl + +theorem replayConsAfterNWhnfM : + TypeChecker.M.run ctorEnv .safe consNContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.whnf consAfterN) = + .ok consAfterN := by rfl + +theorem replayConsAfterHeadWhnfM : + TypeChecker.M.run ctorEnv .safe consHeadContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.whnf consAfterHead) = + .ok consAfterHead := by rfl + +def consAfterHeadCheckTailId : FVarId := + ⟨consTailDomainFinalState.ngen.curr⟩ + +def consAfterHeadCheckLctx : LocalContext := + consHeadContext.lctx.mkLocalDecl consAfterHeadCheckTailId + consTailName consTailDomain .default + +def consAfterHeadCheckState : TypeChecker.State := + { consTailDomainFinalState with + ngen := consTailDomainFinalState.ngen.next } + +@[simp] theorem replayTailDomainBeqFirstApp : + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId) == + replayFirstApp (.fvar consAlphaId)) = false := by + change Expr.eqv + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId)) + (replayFirstApp (.fvar consAlphaId)) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replayFirstApp] + +@[simp] theorem replayTailDomainBeqSuccApp : + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId) == + replaySuccApp (.fvar consNId)) = false := by + change Expr.eqv + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId)) + (replaySuccApp (.fvar consNId)) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replaySuccApp] + +@[simp] theorem replayTailDomainBeqTerminal : + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId) == + ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) = false := by + change Expr.eqv + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId)) + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replaySuccApp] + +@[simp] theorem replayFirstAppBeqTerminal : + (replayFirstApp (.fvar consAlphaId) == + ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) = false := by + change Expr.eqv (replayFirstApp (.fvar consAlphaId)) + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +@[simp] theorem replayTailDomainLiteralBeqFirstApp : + (((.const ``IndexedVec [.param `u] : Expr).app (.fvar consAlphaId)).app + (.fvar consNId) == + (.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)) = false := by + simpa [ctorIndexedVecApp, replayFirstApp] using + replayTailDomainBeqFirstApp + +@[simp] theorem replayTailDomainLiteralBeqSuccApp : + (((.const ``IndexedVec [.param `u] : Expr).app (.fvar consAlphaId)).app + (.fvar consNId) == + (.const ``Nat.succ [] : Expr).app (.fvar consNId)) = false := by + simpa [ctorIndexedVecApp, replaySuccApp] using + replayTailDomainBeqSuccApp + +@[simp] theorem replayFirstAppLiteralBeqSuccApp : + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId) == + (.const ``Nat.succ [] : Expr).app (.fvar consNId)) = false := by + simpa only [replayFirstApp, replaySuccApp] using + (replayFirstAppBeqSuccApp (.fvar consAlphaId) (.fvar consNId)) + +@[simp] theorem replayTailDomainLiteralBeqTerminal : + (((.const ``IndexedVec [.param `u] : Expr).app (.fvar consAlphaId)).app + (.fvar consNId) == + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app (.fvar consNId))) = false := by + simpa [ctorIndexedVecApp, replaySuccApp] using + replayTailDomainBeqTerminal + +@[simp] theorem replayFirstAppLiteralBeqTerminal : + ((.const ``IndexedVec [.param `u] : Expr).app (.fvar consAlphaId) == + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app (.fvar consNId))) = false := by + simpa [ctorIndexedVecApp, replayFirstApp, replaySuccApp] using + replayFirstAppBeqTerminal + +theorem consAfterHeadCheckFirstCache : + consAfterHeadCheckState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = some vecFamilyTail := by + change consTailDomainFinalState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = some vecFamilyTail + unfold consTailDomainFinalState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (consTailDomain == replayFirstApp (.fvar consAlphaId)) = + false by + simpa only [consTailDomain, ctorIndexedVecApp, + consAlphaExprShape, consNExprShape] using + replayTailDomainBeqFirstApp] + simp only [Bool.false_eq_true, if_false] + unfold consHeadNState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (consNExpr == replayFirstApp (.fvar consAlphaId)) = false by + simp [consNExprShape, replayFirstApp]] + simp only [Bool.false_eq_true, if_false] + unfold consHeadFirstAppState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (replayFirstApp consAlphaExpr == + replayFirstApp (.fvar consAlphaId)) = true by simp] + rfl + +theorem consAfterHeadCheckNCache : + consAfterHeadCheckState.inferTypeC[(.fvar consNId : Expr)]? = + some (.const ``Nat []) := by + change consTailDomainFinalState.inferTypeC[(.fvar consNId : Expr)]? = + some (.const ``Nat []) + unfold consTailDomainFinalState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (consTailDomain == (.fvar consNId : Expr)) = false by + simpa only [consTailDomain, consAlphaExprShape, consNExprShape] using + (replayAppBeqFVar + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)) (.fvar consNId) consNId)] + simp only [Bool.false_eq_true, if_false] + unfold consHeadNState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (consNExpr == (.fvar consNId : Expr)) = true by simp] + rfl + +theorem consAfterHeadCheckSuccMiss : + consAfterHeadCheckState.inferTypeC[(.const ``Nat.succ [] : Expr)]? = + none := by + simp [consAfterHeadCheckState, consTailDomainFinalState, consHeadNState, consHeadFirstAppState, + replayInsert, consTailDomain, replayFirstApp] + +theorem consAfterHeadCheckSuccAppMiss : + consAfterHeadCheckState.inferTypeC[ + replaySuccApp (.fvar consNId)]? = none := by + simp [consAfterHeadCheckState, consTailDomainFinalState, consHeadNState, consHeadFirstAppState, + replayInsert, consTailDomain, replayFirstApp, replaySuccApp] + +theorem consAfterHeadCheckTerminalMiss : + consAfterHeadCheckState.inferTypeC[ + ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))]? = none := by + simp [consAfterHeadCheckState, consTailDomainFinalState, consHeadNState, consHeadFirstAppState, + replayInsert, consTailDomain, ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +def consAfterHeadCheckSuccState : TypeChecker.State := + replayInsert consAfterHeadCheckState (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) + +def consAfterHeadCheckSuccAppState : TypeChecker.State := + replayInsert consAfterHeadCheckSuccState + (replaySuccApp (.fvar consNId)) (.const ``Nat []) + +def consAfterHeadCheckTerminalState : TypeChecker.State := + replayInsert consAfterHeadCheckSuccAppState + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) + (.sort (.succ (.param `u))) + +theorem replayInferConsAfterHeadTerminal : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAfterHeadCheckLctx) consAfterHeadCheckState = + .ok (.sort (.succ (.param `u)), + consAfterHeadCheckTerminalState) := by + simpa [consAfterHeadCheckSuccState, + consAfterHeadCheckSuccAppState, + consAfterHeadCheckTerminalState] using + (replayInferIndexedVecSuccFromCacheCore 9998 consAfterHeadCheckLctx + consAfterHeadCheckState consAlphaId consNId + consAfterHeadCheckFirstCache consAfterHeadCheckSuccMiss + consAfterHeadCheckNCache consAfterHeadCheckSuccAppMiss + consAfterHeadCheckTerminalMiss) + +theorem replayConsAfterHeadCheckTypeM : + TypeChecker.M.run ctorEnv .safe consHeadContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType consAfterHead) = + .ok (.sort (.succ (.param `u))) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType consAfterHead false + (TypeChecker.Methods.withFuel 10000) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State)) = _ + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' consAfterHead false + (TypeChecker.Methods.withFuel 9999) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State)) = _ + unfold consAfterHead consTailDomain TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', TypeChecker.Inner.inferForall, + TypeChecker.Inner.inferForall.loop, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show TypeChecker.Inner.inferType' + (.app + (.app (.const ``IndexedVec [.param `u]) (.fvar consAlphaId)) + (.fvar consNId)) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consHeadContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), consTailDomainFinalState) by + simpa [consTailDomain, ctorIndexedVecApp] using + replayInferConsTailDomainCore 9998] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp [Expr.instantiate1'] + have hterminal : + TypeChecker.Inner.inferType + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app (.fvar consNId))) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consAfterHeadCheckLctx) consAfterHeadCheckState = + .ok (.sort (.succ (.param `u)), + consAfterHeadCheckTerminalState) := by + change TypeChecker.Inner.inferType' + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app (.fvar consNId))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAfterHeadCheckLctx) consAfterHeadCheckState = _ + simpa [ctorIndexedVecApp, replaySuccApp] using + replayInferConsAfterHeadTerminal + simp only [consAfterHeadCheckLctx, consAfterHeadCheckTailId, + consAfterHeadCheckState, consTailDomain, consAlphaExprShape, + consNExprShape, tcContext] at hterminal + simp only [tcContext] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hterminal] + simp only [ensureSortExact] + simp [Expr.sortLevel!, Pure.pure, ReaderT.pure, + StateT.pure, Except.pure] + rfl + +/-! The two-binder suffix beginning at the `head` field. -/ + +def consAfterNHeadDomainState : TypeChecker.State := + replayInsert ({} : TypeChecker.State) consAlphaExpr + (.sort (.succ (.param `u))) + +theorem replayInferConsAfterNHeadDomain (fuel : Nat) : + TypeChecker.Inner.inferType' consAlphaExpr false + (TypeChecker.Methods.withFuel fuel) + (tcContext consNContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), + consAfterNHeadDomainState) := by + simpa [consAfterNHeadDomainState, replayInsert, + consAlphaExprShape] using + (inferTypeFVarCore fuel consNContext.lctx ({} : TypeChecker.State) + consAlphaId (.sort (.succ (.param `u))) + (index := 0) (name := consAlphaName) (bi := .implicit) + (kind := .default) (by simp) consAlphaFindInN) + +def consAfterNCheckHeadId : FVarId := + ⟨consAfterNHeadDomainState.ngen.curr⟩ + +def consAfterNCheckLctx : LocalContext := + consNContext.lctx.mkLocalDecl consAfterNCheckHeadId + consHeadName consAlphaExpr .default + +def consAfterNCheckState : TypeChecker.State := + { consAfterNHeadDomainState with + ngen := consAfterNHeadDomainState.ngen.next } + +theorem consAfterNCheckHeadFresh : + consNContext.lctx.find? consAfterNCheckHeadId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consAfterNCheckHeadId) consNContextWF + rw [h] + simp [consAfterNCheckHeadId, consAfterNHeadDomainState, replayInsert, consNContext, + consAlphaContext, consRootContext, ctorContext, consAlphaId, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, LocalContext.toList, + LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + intro x hx + change some x ∈ + (PersistentArray.empty : PersistentArray (Option LocalDecl)).toList' at hx + rw [PersistentArray.toList'_empty] at hx + simp at hx + +theorem consAfterNCheckLctxWF : consAfterNCheckLctx.WF := by + simpa [consAfterNCheckLctx] using + (LocalContext.WF.mkLocalDecl consNContextWF consAfterNCheckHeadFresh) + +theorem consAfterNCheckNFind : + consAfterNCheckLctx.find? consNId = + some (.cdecl 1 consNId consNName (.const ``Nat []) + .implicit .default) := by + rw [consAfterNCheckLctxWF.find?_eq_find?_toList] + simp [consAfterNCheckLctx, consAfterNCheckHeadId, consAfterNHeadDomainState, replayInsert, + consNContext, consAlphaContext, consRootContext, ctorContext, consAlphaId, consNId, + AddInductive.Context.pushLocalDecl, AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, + LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + +theorem consAfterNCheckAlphaCache : + consAfterNCheckState.inferTypeC[(.fvar consAlphaId : Expr)]? = + some (.sort (.succ (.param `u))) := by + change consAfterNHeadDomainState.inferTypeC[ + (.fvar consAlphaId : Expr)]? = some (.sort (.succ (.param `u))) + unfold consAfterNHeadDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (consAlphaExpr == (.fvar consAlphaId : Expr)) = true by simp] + rfl + +theorem consAfterNCheckFamilyMiss : + consAfterNCheckState.inferTypeC[ + (.const ``IndexedVec [.param `u] : Expr)]? = none := by + simp [consAfterNCheckState, consAfterNHeadDomainState, replayInsert] + +theorem consAfterNCheckFirstAppMiss : + consAfterNCheckState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = none := by + simp [consAfterNCheckState, consAfterNHeadDomainState, + replayInsert, replayFirstApp] + +def consAfterNCheckFirstAppState : TypeChecker.State := + replayInsert + (replayInsert consAfterNCheckState + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (replayFirstApp (.fvar consAlphaId)) vecFamilyTail + +theorem consAfterNCheckNMiss : + consAfterNCheckFirstAppState.inferTypeC[(.fvar consNId : Expr)]? = + none := by + simp [consAfterNCheckFirstAppState, consAfterNCheckState, + consAfterNHeadDomainState, replayInsert, replayFirstApp] + +theorem consAfterNCheckTailMiss : + consAfterNCheckState.inferTypeC[ + ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId)]? = none := by + simp [consAfterNCheckState, consAfterNHeadDomainState, + replayInsert, ctorIndexedVecApp] + +def consAfterNCheckNState : TypeChecker.State := + replayInsert consAfterNCheckFirstAppState + (.fvar consNId) (.const ``Nat []) + +def consAfterNCheckTailDomainState : TypeChecker.State := + replayInsert consAfterNCheckNState + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId)) + (.sort (.succ (.param `u))) + +theorem replayInferConsAfterNTailDomain (fuel : Nat) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId)) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consAfterNCheckLctx) consAfterNCheckState = + .ok (.sort (.succ (.param `u)), + consAfterNCheckTailDomainState) := by + simpa [consAfterNCheckFirstAppState, consAfterNCheckNState, + consAfterNCheckTailDomainState] using + (replayInferTailDomainAlphaCachedCore fuel consAfterNCheckLctx + consAfterNCheckState consAlphaId consNId + consAfterNCheckAlphaCache consAfterNCheckFamilyMiss + consAfterNCheckFirstAppMiss consAfterNCheckNMiss + consAfterNCheckTailMiss consAfterNCheckNFind) + +def consAfterNCheckTailId : FVarId := + ⟨consAfterNCheckTailDomainState.ngen.curr⟩ + +def consAfterNCheckTailLctx : LocalContext := + consAfterNCheckLctx.mkLocalDecl consAfterNCheckTailId + consTailName + (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId)) .default + +def consAfterNCheckTailState : TypeChecker.State := + { consAfterNCheckTailDomainState with + ngen := consAfterNCheckTailDomainState.ngen.next } + +theorem consAfterNCheckTailFirstCache : + consAfterNCheckTailState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = some vecFamilyTail := by + change consAfterNCheckTailDomainState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = some vecFamilyTail + unfold consAfterNCheckTailDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [replayTailDomainBeqFirstApp] + simp only [Bool.false_eq_true, if_false] + unfold consAfterNCheckNState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show ((.fvar consNId : Expr) == + replayFirstApp (.fvar consAlphaId)) = false by + simpa only [replayFirstApp] using + (replayFVarBeqApp consNId + (.const ``IndexedVec [.param `u]) (.fvar consAlphaId))] + simp only [Bool.false_eq_true, if_false] + unfold consAfterNCheckFirstAppState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +theorem consAfterNCheckTailNCache : + consAfterNCheckTailState.inferTypeC[(.fvar consNId : Expr)]? = + some (.const ``Nat []) := by + change consAfterNCheckTailDomainState.inferTypeC[ + (.fvar consNId : Expr)]? = some (.const ``Nat []) + unfold consAfterNCheckTailDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (ctorIndexedVecApp (.fvar consAlphaId) (.fvar consNId) == + (.fvar consNId : Expr)) = false by + simpa only [ctorIndexedVecApp] using + (replayAppBeqFVar + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)) (.fvar consNId) consNId)] + simp only [Bool.false_eq_true, if_false] + unfold consAfterNCheckNState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +theorem consAfterNCheckTailSuccMiss : + consAfterNCheckTailState.inferTypeC[ + (.const ``Nat.succ [] : Expr)]? = none := by + simp [consAfterNCheckTailState, consAfterNCheckTailDomainState, consAfterNCheckNState, + consAfterNCheckFirstAppState, consAfterNCheckState, consAfterNHeadDomainState, replayInsert, + ctorIndexedVecApp, replayFirstApp] + +theorem consAfterNCheckTailSuccAppMiss : + consAfterNCheckTailState.inferTypeC[ + replaySuccApp (.fvar consNId)]? = none := by + simp [consAfterNCheckTailState, consAfterNCheckTailDomainState, consAfterNCheckNState, + consAfterNCheckFirstAppState, consAfterNCheckState, consAfterNHeadDomainState, replayInsert, + ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +theorem consAfterNCheckTailTerminalMiss : + consAfterNCheckTailState.inferTypeC[ + ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))]? = none := by + simp [consAfterNCheckTailState, consAfterNCheckTailDomainState, consAfterNCheckNState, + consAfterNCheckFirstAppState, consAfterNCheckState, consAfterNHeadDomainState, replayInsert, + ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +def consAfterNCheckSuccState : TypeChecker.State := + replayInsert consAfterNCheckTailState (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) + +def consAfterNCheckSuccAppState : TypeChecker.State := + replayInsert consAfterNCheckSuccState + (replaySuccApp (.fvar consNId)) (.const ``Nat []) + +def consAfterNCheckTerminalState : TypeChecker.State := + replayInsert consAfterNCheckSuccAppState + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) + (.sort (.succ (.param `u))) + +theorem replayInferConsAfterNTerminal (fuel : Nat) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consNId))) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consAfterNCheckTailLctx) consAfterNCheckTailState = + .ok (.sort (.succ (.param `u)), + consAfterNCheckTerminalState) := by + simpa [consAfterNCheckSuccState, consAfterNCheckSuccAppState, + consAfterNCheckTerminalState] using + (replayInferIndexedVecSuccFromCacheCore fuel + consAfterNCheckTailLctx consAfterNCheckTailState + consAlphaId consNId consAfterNCheckTailFirstCache + consAfterNCheckTailSuccMiss consAfterNCheckTailNCache + consAfterNCheckTailSuccAppMiss consAfterNCheckTailTerminalMiss) + +theorem replayConsAfterNCheckTypeM : + TypeChecker.M.run ctorEnv .safe consNContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType consAfterN) = + .ok (.sort (.succ (.param `u))) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType consAfterN false + (TypeChecker.Methods.withFuel 10000) + (tcContext consNContext.lctx) ({} : TypeChecker.State)) = _ + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' consAfterN false + (TypeChecker.Methods.withFuel 9999) + (tcContext consNContext.lctx) ({} : TypeChecker.State)) = _ + unfold consAfterN TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show TypeChecker.Inner.inferType' + (.fvar consAlphaId) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consNContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), + consAfterNHeadDomainState) by + simpa [consAlphaExprShape] using + replayInferConsAfterNHeadDomain 9998] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp [Expr.instantiate1'] + have htail : + TypeChecker.Inner.inferType + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app (.fvar consNId)) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consAfterNCheckLctx) consAfterNCheckState = + .ok (.sort (.succ (.param `u)), + consAfterNCheckTailDomainState) := by + change TypeChecker.Inner.inferType' + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app (.fvar consNId)) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAfterNCheckLctx) consAfterNCheckState = _ + simpa [ctorIndexedVecApp] using + replayInferConsAfterNTailDomain 9998 + simp only [consAfterNCheckLctx, consAfterNCheckHeadId, + consAfterNCheckState, consAlphaExprShape, tcContext] at htail + simp only [tcContext] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [htail] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp only [] + have hterminal : + TypeChecker.Inner.inferType + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app (.fvar consNId))) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consAfterNCheckTailLctx) consAfterNCheckTailState = + .ok (.sort (.succ (.param `u)), + consAfterNCheckTerminalState) := by + change TypeChecker.Inner.inferType' + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app (.fvar consNId))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAfterNCheckTailLctx) consAfterNCheckTailState = _ + simpa [ctorIndexedVecApp, replaySuccApp] using + replayInferConsAfterNTerminal 9998 + simp only [consAfterNCheckTailLctx, consAfterNCheckTailId, + consAfterNCheckTailState, consAfterNCheckLctx, + consAfterNCheckHeadId, consAlphaExprShape, + ctorIndexedVecApp, tcContext] at hterminal + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hterminal] + simp only [ensureSortExact] + simp [Expr.sortLevel!, Pure.pure, ReaderT.pure, + StateT.pure, Except.pure] + rfl + +/-! The three-binder suffix beginning at the `n` index. -/ + +open private mkLevelIMaxCore mkLevelMaxCore from Lean.Level in +@[simp] theorem replayMkLevelIMaxSuccZeroSuccParam : + mkLevelIMax' (.succ .zero) (.succ (.param `u)) = + .succ (.param `u) := by + simp [mkLevelIMax', mkLevelIMaxCore, mkLevelMax', mkLevelMaxCore, Level.isNeverZero, Level.isZero, + Level.isExplicit, Level.hasMVar', Level.hasParam', Level.getOffset, Level.getOffsetAux] + +def consAfterAlphaNatState : TypeChecker.State := + replayInsert ({} : TypeChecker.State) (.const ``Nat []) + (.sort (.succ .zero)) + +theorem replayInferConsAfterAlphaNat (fuel : Nat) : + TypeChecker.Inner.inferType' (.const ``Nat []) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consAlphaContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), consAfterAlphaNatState) := by + simpa [consAfterAlphaNatState, replayInsert] using + (inferTypeNatCore fuel consAlphaContext.lctx + ({} : TypeChecker.State) (by simp)) + +def consAfterAlphaCheckNId : FVarId := + ⟨consAfterAlphaNatState.ngen.curr⟩ + +def consAfterAlphaCheckNLctx : LocalContext := + consAlphaContext.lctx.mkLocalDecl consAfterAlphaCheckNId + consNName (.const ``Nat []) .implicit + +def consAfterAlphaCheckNState : TypeChecker.State := + { consAfterAlphaNatState with + ngen := consAfterAlphaNatState.ngen.next } + +theorem consAfterAlphaCheckNFresh : + consAlphaContext.lctx.find? consAfterAlphaCheckNId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consAfterAlphaCheckNId) consAlphaContextWF + rw [h] + simp [consAfterAlphaCheckNId, consAfterAlphaNatState, replayInsert, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, LocalContext.toList, + LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + intro x hx + change some x ∈ + (PersistentArray.empty : PersistentArray (Option LocalDecl)).toList' at hx + rw [PersistentArray.toList'_empty] at hx + simp at hx + +theorem consAfterAlphaCheckNLctxWF : consAfterAlphaCheckNLctx.WF := by + simpa [consAfterAlphaCheckNLctx] using + (LocalContext.WF.mkLocalDecl consAlphaContextWF + consAfterAlphaCheckNFresh) + +theorem consAfterAlphaCheckAlphaFind : + consAfterAlphaCheckNLctx.find? consAlphaId = + some (.cdecl 0 consAlphaId consAlphaName + (.sort (.succ (.param `u))) .implicit .default) := by + rw [consAfterAlphaCheckNLctxWF.find?_eq_find?_toList] + simp [consAfterAlphaCheckNLctx, consAfterAlphaCheckNId, consAfterAlphaNatState, replayInsert, + consAlphaContext, consRootContext, ctorContext, consAlphaId, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, LocalContext.toList, + LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + +theorem consAfterAlphaCheckAlphaMiss : + consAfterAlphaCheckNState.inferTypeC[ + (.fvar consAlphaId : Expr)]? = none := by + simp [consAfterAlphaCheckNState, consAfterAlphaNatState, + replayInsert] + +def consAfterAlphaHeadDomainState : TypeChecker.State := + replayInsert consAfterAlphaCheckNState (.fvar consAlphaId) + (.sort (.succ (.param `u))) + +theorem replayInferConsAfterAlphaHeadDomain (fuel : Nat) : + TypeChecker.Inner.inferType' (.fvar consAlphaId) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consAfterAlphaCheckNLctx) consAfterAlphaCheckNState = + .ok (.sort (.succ (.param `u)), + consAfterAlphaHeadDomainState) := by + simpa [consAfterAlphaHeadDomainState, replayInsert] using + (inferTypeFVarCore fuel consAfterAlphaCheckNLctx + consAfterAlphaCheckNState consAlphaId + (.sort (.succ (.param `u))) + consAfterAlphaCheckAlphaMiss consAfterAlphaCheckAlphaFind) + +def consAfterAlphaCheckHeadId : FVarId := + ⟨consAfterAlphaHeadDomainState.ngen.curr⟩ + +def consAfterAlphaCheckHeadLctx : LocalContext := + consAfterAlphaCheckNLctx.mkLocalDecl consAfterAlphaCheckHeadId + consHeadName (.fvar consAlphaId) .default + +def consAfterAlphaCheckHeadState : TypeChecker.State := + { consAfterAlphaHeadDomainState with + ngen := consAfterAlphaHeadDomainState.ngen.next } + +theorem consAfterAlphaCheckHeadFresh : + consAfterAlphaCheckNLctx.find? consAfterAlphaCheckHeadId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consAfterAlphaCheckHeadId) consAfterAlphaCheckNLctxWF + rw [h] + simp [consAfterAlphaCheckHeadId, consAfterAlphaHeadDomainState, consAfterAlphaCheckNState, + consAfterAlphaCheckNId, consAfterAlphaNatState, replayInsert, consAfterAlphaCheckNLctx, + consAlphaContext, consRootContext, ctorContext, consAlphaId, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, LocalContext.toList, + LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + intro x hx + change some x ∈ + (PersistentArray.empty : PersistentArray (Option LocalDecl)).toList' at hx + rw [PersistentArray.toList'_empty] at hx + simp at hx + +theorem consAfterAlphaCheckHeadLctxWF : + consAfterAlphaCheckHeadLctx.WF := by + simpa [consAfterAlphaCheckHeadLctx] using + (LocalContext.WF.mkLocalDecl consAfterAlphaCheckNLctxWF + consAfterAlphaCheckHeadFresh) + +theorem consAfterAlphaCheckNFind : + consAfterAlphaCheckHeadLctx.find? consAfterAlphaCheckNId = + some (.cdecl 1 consAfterAlphaCheckNId consNName + (.const ``Nat []) .implicit .default) := by + rw [consAfterAlphaCheckHeadLctxWF.find?_eq_find?_toList] + simp [consAfterAlphaCheckHeadLctx, consAfterAlphaCheckHeadId, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaCheckNLctx, consAfterAlphaCheckNId, + consAfterAlphaNatState, replayInsert, consAlphaContext, consRootContext, ctorContext, + consAlphaId, AddInductive.Context.pushLocalDecl, AddInductive.Context.freshFVarId, + LocalContext.mkLocalDecl, LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, + NameGenerator.curr] + +theorem consAfterAlphaCheckAlphaCache : + consAfterAlphaCheckHeadState.inferTypeC[ + (.fvar consAlphaId : Expr)]? = + some (.sort (.succ (.param `u))) := by + change consAfterAlphaHeadDomainState.inferTypeC[ + (.fvar consAlphaId : Expr)]? = + some (.sort (.succ (.param `u))) + unfold consAfterAlphaHeadDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +@[simp] theorem replayNatConstBeqIndexedVec : + ((.const ``Nat [] : Expr) == + .const ``IndexedVec [.param `u]) = false := by + change Expr.eqv (.const ``Nat []) + (.const ``IndexedVec [.param `u]) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem replayAlphaIdBeqAfterAlphaNId : + ((.fvar consAlphaId : Expr) == + .fvar consAfterAlphaCheckNId) = false := by + change Expr.eqv (.fvar consAlphaId) + (.fvar consAfterAlphaCheckNId) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', consAlphaId, consAfterAlphaCheckNId, consAfterAlphaNatState, replayInsert, + consRootContext, ctorContext, AddInductive.Context.freshFVarId, NameGenerator.curr] + +theorem consAfterAlphaCheckFamilyMiss : + consAfterAlphaCheckHeadState.inferTypeC[ + (.const ``IndexedVec [.param `u] : Expr)]? = none := by + simp [consAfterAlphaCheckHeadState, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaNatState, replayInsert] + +theorem consAfterAlphaCheckFirstAppMiss : + consAfterAlphaCheckHeadState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = none := by + simp [consAfterAlphaCheckHeadState, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaNatState, + replayInsert, replayFirstApp] + +def consAfterAlphaCheckFirstAppState : TypeChecker.State := + replayInsert + (replayInsert consAfterAlphaCheckHeadState + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (replayFirstApp (.fvar consAlphaId)) vecFamilyTail + +theorem consAfterAlphaCheckNMiss : + consAfterAlphaCheckFirstAppState.inferTypeC[ + (.fvar consAfterAlphaCheckNId : Expr)]? = none := by + simp [consAfterAlphaCheckFirstAppState, + consAfterAlphaCheckHeadState, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaNatState, + replayInsert, replayFirstApp] + +theorem consAfterAlphaCheckTailMiss : + consAfterAlphaCheckHeadState.inferTypeC[ + ctorIndexedVecApp (.fvar consAlphaId) + (.fvar consAfterAlphaCheckNId)]? = none := by + simp [consAfterAlphaCheckHeadState, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaNatState, + replayInsert, ctorIndexedVecApp] + +def consAfterAlphaCheckNInferState : TypeChecker.State := + replayInsert consAfterAlphaCheckFirstAppState + (.fvar consAfterAlphaCheckNId) (.const ``Nat []) + +def consAfterAlphaCheckTailDomainState : TypeChecker.State := + replayInsert consAfterAlphaCheckNInferState + (ctorIndexedVecApp (.fvar consAlphaId) + (.fvar consAfterAlphaCheckNId)) + (.sort (.succ (.param `u))) + +theorem replayInferConsAfterAlphaTailDomain (fuel : Nat) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar consAlphaId) + (.fvar consAfterAlphaCheckNId)) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consAfterAlphaCheckHeadLctx) + consAfterAlphaCheckHeadState = + .ok (.sort (.succ (.param `u)), + consAfterAlphaCheckTailDomainState) := by + simpa [consAfterAlphaCheckFirstAppState, + consAfterAlphaCheckNInferState, + consAfterAlphaCheckTailDomainState] using + (replayInferTailDomainAlphaCachedCore fuel + consAfterAlphaCheckHeadLctx consAfterAlphaCheckHeadState + consAlphaId consAfterAlphaCheckNId + consAfterAlphaCheckAlphaCache consAfterAlphaCheckFamilyMiss + consAfterAlphaCheckFirstAppMiss consAfterAlphaCheckNMiss + consAfterAlphaCheckTailMiss consAfterAlphaCheckNFind) + +def consAfterAlphaCheckTailId : FVarId := + ⟨consAfterAlphaCheckTailDomainState.ngen.curr⟩ + +def consAfterAlphaCheckTailLctx : LocalContext := + consAfterAlphaCheckHeadLctx.mkLocalDecl consAfterAlphaCheckTailId + consTailName + (ctorIndexedVecApp (.fvar consAlphaId) + (.fvar consAfterAlphaCheckNId)) .default + +def consAfterAlphaCheckTailState : TypeChecker.State := + { consAfterAlphaCheckTailDomainState with + ngen := consAfterAlphaCheckTailDomainState.ngen.next } + +@[simp] theorem replayAfterAlphaNIdBeqAlphaId : + ((.fvar consAfterAlphaCheckNId : Expr) == + .fvar consAlphaId) = false := by + change Expr.eqv (.fvar consAfterAlphaCheckNId) + (.fvar consAlphaId) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', consAlphaId, consAfterAlphaCheckNId, consAfterAlphaNatState, replayInsert, + consRootContext, ctorContext, AddInductive.Context.freshFVarId, NameGenerator.curr] + +@[simp] theorem replayNatConstBeqSucc : + ((.const ``Nat [] : Expr) == .const ``Nat.succ []) = false := by + change Expr.eqv (.const ``Nat []) (.const ``Nat.succ []) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem replayIndexedVecAppBeqFirstApp + (alpha index : Expr) : + (ctorIndexedVecApp alpha index == replayFirstApp alpha) = false := by + change Expr.eqv (ctorIndexedVecApp alpha index) + (replayFirstApp alpha) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replayFirstApp] + +@[simp] theorem replayIndexedVecAppBeqSuccApp + (alpha n : Expr) : + (ctorIndexedVecApp alpha n == replaySuccApp n) = false := by + change Expr.eqv (ctorIndexedVecApp alpha n) + (replaySuccApp n) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replaySuccApp] + +@[simp] theorem replayIndexedVecAppBeqIndexedVecSucc + (alpha : Expr) (id : FVarId) : + (ctorIndexedVecApp alpha (.fvar id) == + ctorIndexedVecApp alpha (replaySuccApp (.fvar id))) = false := by + change Expr.eqv (ctorIndexedVecApp alpha (.fvar id)) + (ctorIndexedVecApp alpha (replaySuccApp (.fvar id))) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replaySuccApp] + +@[simp] theorem replayFirstAppBeqIndexedVecSucc + (alpha n : Expr) : + (replayFirstApp alpha == + ctorIndexedVecApp alpha (replaySuccApp n)) = false := by + change Expr.eqv (replayFirstApp alpha) + (ctorIndexedVecApp alpha (replaySuccApp n)) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +@[simp] theorem replayIndexedVecLiteralBeqSuccApp + (alpha n : Expr) : + (((.const ``IndexedVec [.param `u] : Expr).app alpha).app n == + (.const ``Nat.succ [] : Expr).app n) = false := by + simpa [ctorIndexedVecApp, replaySuccApp] using + replayIndexedVecAppBeqSuccApp alpha n + +@[simp] theorem replayFirstAppLiteralGenericBeqSuccApp + (alpha n : Expr) : + ((.const ``IndexedVec [.param `u] : Expr).app alpha == + (.const ``Nat.succ [] : Expr).app n) = false := by + simpa [replayFirstApp, replaySuccApp] using + replayFirstAppBeqSuccApp alpha n + +@[simp] theorem replayIndexedVecLiteralFVarBeqTerminal + (alpha : Expr) (id : FVarId) : + (((.const ``IndexedVec [.param `u] : Expr).app alpha).app + (.fvar id) == + ((.const ``IndexedVec [.param `u] : Expr).app alpha).app + ((.const ``Nat.succ [] : Expr).app (.fvar id))) = false := by + simpa [ctorIndexedVecApp, replaySuccApp] using + replayIndexedVecAppBeqIndexedVecSucc alpha id + +@[simp] theorem replayFirstAppLiteralGenericBeqTerminal + (alpha : Expr) (id : FVarId) : + ((.const ``IndexedVec [.param `u] : Expr).app alpha == + ((.const ``IndexedVec [.param `u] : Expr).app alpha).app + ((.const ``Nat.succ [] : Expr).app (.fvar id))) = false := by + simpa [ctorIndexedVecApp, replayFirstApp, replaySuccApp] using + replayFirstAppBeqIndexedVecSucc alpha (.fvar id) + +theorem consAfterAlphaCheckTailFirstCache : + consAfterAlphaCheckTailState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = some vecFamilyTail := by + change consAfterAlphaCheckTailDomainState.inferTypeC[ + replayFirstApp (.fvar consAlphaId)]? = some vecFamilyTail + unfold consAfterAlphaCheckTailDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [replayIndexedVecAppBeqFirstApp] + simp only [Bool.false_eq_true, if_false] + unfold consAfterAlphaCheckNInferState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show ((.fvar consAfterAlphaCheckNId : Expr) == + replayFirstApp (.fvar consAlphaId)) = false by + exact replayFVarBeqApp consAfterAlphaCheckNId + (.const ``IndexedVec [.param `u]) (.fvar consAlphaId)] + simp only [Bool.false_eq_true, if_false] + unfold consAfterAlphaCheckFirstAppState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +theorem consAfterAlphaCheckTailNCache : + consAfterAlphaCheckTailState.inferTypeC[ + (.fvar consAfterAlphaCheckNId : Expr)]? = + some (.const ``Nat []) := by + change consAfterAlphaCheckTailDomainState.inferTypeC[ + (.fvar consAfterAlphaCheckNId : Expr)]? = + some (.const ``Nat []) + unfold consAfterAlphaCheckTailDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (ctorIndexedVecApp (.fvar consAlphaId) + (.fvar consAfterAlphaCheckNId) == + (.fvar consAfterAlphaCheckNId : Expr)) = false by + exact replayAppBeqFVar + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)) + (.fvar consAfterAlphaCheckNId) consAfterAlphaCheckNId] + simp only [Bool.false_eq_true, if_false] + unfold consAfterAlphaCheckNInferState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +theorem consAfterAlphaCheckTailSuccMiss : + consAfterAlphaCheckTailState.inferTypeC[ + (.const ``Nat.succ [] : Expr)]? = none := by + simp [consAfterAlphaCheckTailState, + consAfterAlphaCheckTailDomainState, + consAfterAlphaCheckNInferState, + consAfterAlphaCheckFirstAppState, + consAfterAlphaCheckHeadState, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaNatState, + replayInsert, ctorIndexedVecApp, replayFirstApp] + +theorem consAfterAlphaCheckTailSuccAppMiss : + consAfterAlphaCheckTailState.inferTypeC[ + replaySuccApp (.fvar consAfterAlphaCheckNId)]? = none := by + simp [consAfterAlphaCheckTailState, + consAfterAlphaCheckTailDomainState, + consAfterAlphaCheckNInferState, + consAfterAlphaCheckFirstAppState, + consAfterAlphaCheckHeadState, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaNatState, + replayInsert, ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +theorem consAfterAlphaCheckTailTerminalMiss : + consAfterAlphaCheckTailState.inferTypeC[ + ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consAfterAlphaCheckNId))]? = none := by + simp [consAfterAlphaCheckTailState, + consAfterAlphaCheckTailDomainState, + consAfterAlphaCheckNInferState, + consAfterAlphaCheckFirstAppState, + consAfterAlphaCheckHeadState, consAfterAlphaHeadDomainState, + consAfterAlphaCheckNState, consAfterAlphaNatState, + replayInsert, ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +def consAfterAlphaCheckSuccState : TypeChecker.State := + replayInsert consAfterAlphaCheckTailState (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) + +def consAfterAlphaCheckSuccAppState : TypeChecker.State := + replayInsert consAfterAlphaCheckSuccState + (replaySuccApp (.fvar consAfterAlphaCheckNId)) (.const ``Nat []) + +def consAfterAlphaCheckTerminalState : TypeChecker.State := + replayInsert consAfterAlphaCheckSuccAppState + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consAfterAlphaCheckNId))) + (.sort (.succ (.param `u))) + +theorem replayInferConsAfterAlphaTerminal (fuel : Nat) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar consAlphaId) + (replaySuccApp (.fvar consAfterAlphaCheckNId))) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consAfterAlphaCheckTailLctx) + consAfterAlphaCheckTailState = + .ok (.sort (.succ (.param `u)), + consAfterAlphaCheckTerminalState) := by + simpa [consAfterAlphaCheckSuccState, + consAfterAlphaCheckSuccAppState, + consAfterAlphaCheckTerminalState] using + (replayInferIndexedVecSuccFromCacheCore fuel + consAfterAlphaCheckTailLctx consAfterAlphaCheckTailState + consAlphaId consAfterAlphaCheckNId + consAfterAlphaCheckTailFirstCache + consAfterAlphaCheckTailSuccMiss + consAfterAlphaCheckTailNCache + consAfterAlphaCheckTailSuccAppMiss + consAfterAlphaCheckTailTerminalMiss) + +theorem replayConsAfterAlphaCheckTypeM : + TypeChecker.M.run ctorEnv .safe consAlphaContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType consAfterAlpha) = + .ok (.sort (.succ (.param `u))) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType consAfterAlpha false + (TypeChecker.Methods.withFuel 10000) + (tcContext consAlphaContext.lctx) ({} : TypeChecker.State)) = _ + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' consAfterAlpha false + (TypeChecker.Methods.withFuel 9999) + (tcContext consAlphaContext.lctx) ({} : TypeChecker.State)) = _ + unfold consAfterAlpha TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show TypeChecker.Inner.inferType' + (.const ``Nat []) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAlphaContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), consAfterAlphaNatState) by + exact replayInferConsAfterAlphaNat 9998] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp only [Expr.instantiate1'] + have hhead : + TypeChecker.Inner.inferType (.fvar consAlphaId) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consAfterAlphaCheckNLctx) + consAfterAlphaCheckNState = + .ok (.sort (.succ (.param `u)), + consAfterAlphaHeadDomainState) := by + change TypeChecker.Inner.inferType' (.fvar consAlphaId) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAfterAlphaCheckNLctx) + consAfterAlphaCheckNState = _ + exact replayInferConsAfterAlphaHeadDomain 9998 + simp only [consAfterAlphaCheckNLctx, consAfterAlphaCheckNId, + consAfterAlphaCheckNState, tcContext] at hhead + simp only [tcContext] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hhead] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp [Expr.instantiate1'] + have htail : + TypeChecker.Inner.inferType + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + (.fvar consAfterAlphaCheckNId)) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consAfterAlphaCheckHeadLctx) + consAfterAlphaCheckHeadState = + .ok (.sort (.succ (.param `u)), + consAfterAlphaCheckTailDomainState) := by + change TypeChecker.Inner.inferType' + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + (.fvar consAfterAlphaCheckNId)) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAfterAlphaCheckHeadLctx) + consAfterAlphaCheckHeadState = _ + simpa [ctorIndexedVecApp] using + replayInferConsAfterAlphaTailDomain 9998 + simp only [consAfterAlphaCheckHeadLctx, + consAfterAlphaCheckHeadId, consAfterAlphaCheckHeadState, + consAfterAlphaCheckNLctx, consAfterAlphaCheckNId, + tcContext] at htail + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [htail] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp + have hterminal : + TypeChecker.Inner.inferType + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app + (.fvar consAfterAlphaCheckNId))) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consAfterAlphaCheckTailLctx) + consAfterAlphaCheckTailState = + .ok (.sort (.succ (.param `u)), + consAfterAlphaCheckTerminalState) := by + change TypeChecker.Inner.inferType' + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consAlphaId)).app + ((.const ``Nat.succ [] : Expr).app + (.fvar consAfterAlphaCheckNId))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consAfterAlphaCheckTailLctx) + consAfterAlphaCheckTailState = _ + simpa [ctorIndexedVecApp, replaySuccApp] using + replayInferConsAfterAlphaTerminal 9998 + simp only [consAfterAlphaCheckTailLctx, + consAfterAlphaCheckTailId, consAfterAlphaCheckTailState, + consAfterAlphaCheckHeadLctx, consAfterAlphaCheckHeadId, + consAfterAlphaCheckNLctx, consAfterAlphaCheckNId, + ctorIndexedVecApp, tcContext] at hterminal + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hterminal] + simp only [ensureSortExact] + simp [Expr.sortLevel!, Pure.pure, ReaderT.pure, + StateT.pure, Except.pure] + rfl + +/-! The complete four-binder constructor type. -/ + +def consRootCheckAlphaId : FVarId := + ⟨nilRootSortState.ngen.curr⟩ + +def consRootCheckAlphaLctx : LocalContext := + consRootContext.lctx.mkLocalDecl consRootCheckAlphaId + consAlphaName (.sort (.succ (.param `u))) .implicit + +def consRootCheckAlphaState : TypeChecker.State := + { nilRootSortState with ngen := nilRootSortState.ngen.next } + +theorem replayInferConsRootSort : + TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consRootContext.lctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ (.param `u))), + nilRootSortState) := by + simpa [consRootContext, ctorContext] using nilRootSortCore + +theorem consRootCheckAlphaFresh : + consRootContext.lctx.find? consRootCheckAlphaId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consRootCheckAlphaId) LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + consRootCheckAlphaId = none + rw [h] + simp [LocalContext.toList] + +theorem consRootCheckAlphaLctxWF : consRootCheckAlphaLctx.WF := by + change (({} : LocalContext).mkLocalDecl consRootCheckAlphaId + consAlphaName (.sort (.succ (.param `u))) .implicit).WF + exact LocalContext.WF.mkLocalDecl LocalContext.WF.nil (by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consRootCheckAlphaId) LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + consRootCheckAlphaId = none + rw [h] + simp [LocalContext.toList]) + +theorem consRootCheckAlphaFind : + consRootCheckAlphaLctx.find? consRootCheckAlphaId = + some (.cdecl 0 consRootCheckAlphaId consAlphaName + (.sort (.succ (.param `u))) .implicit .default) := by + rw [consRootCheckAlphaLctxWF.find?_eq_find?_toList] + simp [consRootCheckAlphaLctx, consRootCheckAlphaId, consRootContext, ctorContext, + nilRootSortState, LocalContext.mkLocalDecl, LocalContext.toList, LocalDecl.fvarId, + NameGenerator.curr] + +theorem consRootCheckNatMiss : + consRootCheckAlphaState.inferTypeC[ + (.const ``Nat [] : Expr)]? = none := by + simp [consRootCheckAlphaState, nilRootSortState] + +def consRootCheckNatState : TypeChecker.State := + replayInsert consRootCheckAlphaState (.const ``Nat []) + (.sort (.succ .zero)) + +theorem replayInferConsRootNat (fuel : Nat) : + TypeChecker.Inner.inferType' (.const ``Nat []) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consRootCheckAlphaLctx) consRootCheckAlphaState = + .ok (.sort (.succ .zero), consRootCheckNatState) := by + simpa [consRootCheckNatState, replayInsert] using + (inferTypeNatCore fuel consRootCheckAlphaLctx + consRootCheckAlphaState consRootCheckNatMiss) + +def consRootCheckNId : FVarId := + ⟨consRootCheckNatState.ngen.curr⟩ + +def consRootCheckNLctx : LocalContext := + consRootCheckAlphaLctx.mkLocalDecl consRootCheckNId + consNName (.const ``Nat []) .implicit + +def consRootCheckNState : TypeChecker.State := + { consRootCheckNatState with ngen := consRootCheckNatState.ngen.next } + +theorem consRootCheckNFresh : + consRootCheckAlphaLctx.find? consRootCheckNId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consRootCheckNId) consRootCheckAlphaLctxWF + rw [h] + simp [consRootCheckNId, consRootCheckNatState, consRootCheckAlphaState, consRootCheckAlphaLctx, + consRootCheckAlphaId, nilRootSortState, replayInsert, consRootContext, ctorContext, + LocalContext.mkLocalDecl, LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, + NameGenerator.curr] + intro x hx + change some x ∈ + (PersistentArray.empty : PersistentArray (Option LocalDecl)).toList' at hx + rw [PersistentArray.toList'_empty] at hx + simp at hx + +theorem consRootCheckNLctxWF : consRootCheckNLctx.WF := by + simpa [consRootCheckNLctx] using + (LocalContext.WF.mkLocalDecl consRootCheckAlphaLctxWF + consRootCheckNFresh) + +theorem consRootCheckAlphaFindInN : + consRootCheckNLctx.find? consRootCheckAlphaId = + some (.cdecl 0 consRootCheckAlphaId consAlphaName + (.sort (.succ (.param `u))) .implicit .default) := by + rw [consRootCheckNLctxWF.find?_eq_find?_toList] + simp [consRootCheckNLctx, consRootCheckNId, consRootCheckNatState, consRootCheckAlphaState, + consRootCheckAlphaLctx, consRootCheckAlphaId, nilRootSortState, replayInsert, consRootContext, + ctorContext, LocalContext.mkLocalDecl, LocalContext.toList, LocalDecl.fvarId, + NameGenerator.next, NameGenerator.curr] + +theorem consRootCheckAlphaMiss : + consRootCheckNState.inferTypeC[ + (.fvar consRootCheckAlphaId : Expr)]? = none := by + simp [consRootCheckNState, consRootCheckNatState, + consRootCheckAlphaState, nilRootSortState, replayInsert] + +def consRootCheckHeadDomainState : TypeChecker.State := + replayInsert consRootCheckNState (.fvar consRootCheckAlphaId) + (.sort (.succ (.param `u))) + +theorem replayInferConsRootHeadDomain (fuel : Nat) : + TypeChecker.Inner.inferType' (.fvar consRootCheckAlphaId) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consRootCheckNLctx) consRootCheckNState = + .ok (.sort (.succ (.param `u)), + consRootCheckHeadDomainState) := by + simpa [consRootCheckHeadDomainState, replayInsert] using + (inferTypeFVarCore fuel consRootCheckNLctx consRootCheckNState + consRootCheckAlphaId (.sort (.succ (.param `u))) + consRootCheckAlphaMiss consRootCheckAlphaFindInN) + +def consRootCheckHeadId : FVarId := + ⟨consRootCheckHeadDomainState.ngen.curr⟩ + +def consRootCheckHeadLctx : LocalContext := + consRootCheckNLctx.mkLocalDecl consRootCheckHeadId + consHeadName (.fvar consRootCheckAlphaId) .default + +def consRootCheckHeadState : TypeChecker.State := + { consRootCheckHeadDomainState with + ngen := consRootCheckHeadDomainState.ngen.next } + +theorem consRootCheckHeadFresh : + consRootCheckNLctx.find? consRootCheckHeadId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consRootCheckHeadId) consRootCheckNLctxWF + rw [h] + simp [consRootCheckHeadId, consRootCheckHeadDomainState, consRootCheckNState, consRootCheckNId, + consRootCheckNatState, consRootCheckAlphaState, consRootCheckAlphaLctx, consRootCheckAlphaId, + nilRootSortState, replayInsert, consRootCheckNLctx, consRootContext, ctorContext, + LocalContext.mkLocalDecl, LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, + NameGenerator.curr] + intro x hx + change some x ∈ + (PersistentArray.empty : PersistentArray (Option LocalDecl)).toList' at hx + rw [PersistentArray.toList'_empty] at hx + simp at hx + +theorem consRootCheckHeadLctxWF : consRootCheckHeadLctx.WF := by + simpa [consRootCheckHeadLctx] using + (LocalContext.WF.mkLocalDecl consRootCheckNLctxWF + consRootCheckHeadFresh) + +theorem consRootCheckNFind : + consRootCheckHeadLctx.find? consRootCheckNId = + some (.cdecl 1 consRootCheckNId consNName + (.const ``Nat []) .implicit .default) := by + rw [consRootCheckHeadLctxWF.find?_eq_find?_toList] + simp [consRootCheckHeadLctx, consRootCheckHeadId, consRootCheckHeadDomainState, + consRootCheckNState, consRootCheckNLctx, consRootCheckNId, consRootCheckNatState, + consRootCheckAlphaState, consRootCheckAlphaLctx, consRootCheckAlphaId, nilRootSortState, + replayInsert, consRootContext, ctorContext, LocalContext.mkLocalDecl, LocalContext.toList, + LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + +@[simp] theorem replayConsRootAlphaIdBeqNId : + ((.fvar consRootCheckAlphaId : Expr) == + .fvar consRootCheckNId) = false := by + change Expr.eqv (.fvar consRootCheckAlphaId) + (.fvar consRootCheckNId) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', consRootCheckAlphaId, consRootCheckNId, + consRootCheckNatState, consRootCheckAlphaState, + nilRootSortState, replayInsert, + NameGenerator.next, NameGenerator.curr] + +@[simp] theorem replayConsRootNIdBeqAlphaId : + ((.fvar consRootCheckNId : Expr) == + .fvar consRootCheckAlphaId) = false := by + change Expr.eqv (.fvar consRootCheckNId) + (.fvar consRootCheckAlphaId) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', consRootCheckAlphaId, consRootCheckNId, + consRootCheckNatState, consRootCheckAlphaState, + nilRootSortState, replayInsert, + NameGenerator.next, NameGenerator.curr] + +theorem consRootCheckAlphaCache : + consRootCheckHeadState.inferTypeC[ + (.fvar consRootCheckAlphaId : Expr)]? = + some (.sort (.succ (.param `u))) := by + change consRootCheckHeadDomainState.inferTypeC[ + (.fvar consRootCheckAlphaId : Expr)]? = + some (.sort (.succ (.param `u))) + unfold consRootCheckHeadDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +theorem consRootCheckFamilyMiss : + consRootCheckHeadState.inferTypeC[ + (.const ``IndexedVec [.param `u] : Expr)]? = none := by + simp [consRootCheckHeadState, consRootCheckHeadDomainState, + consRootCheckNState, consRootCheckNatState, + consRootCheckAlphaState, nilRootSortState, replayInsert] + +theorem consRootCheckFirstAppMiss : + consRootCheckHeadState.inferTypeC[ + replayFirstApp (.fvar consRootCheckAlphaId)]? = none := by + simp [consRootCheckHeadState, consRootCheckHeadDomainState, + consRootCheckNState, consRootCheckNatState, + consRootCheckAlphaState, nilRootSortState, + replayInsert, replayFirstApp] + +def consRootCheckFirstAppState : TypeChecker.State := + replayInsert + (replayInsert consRootCheckHeadState + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (replayFirstApp (.fvar consRootCheckAlphaId)) vecFamilyTail + +theorem consRootCheckNMiss : + consRootCheckFirstAppState.inferTypeC[ + (.fvar consRootCheckNId : Expr)]? = none := by + simp [consRootCheckFirstAppState, consRootCheckHeadState, + consRootCheckHeadDomainState, consRootCheckNState, + consRootCheckNatState, consRootCheckAlphaState, + nilRootSortState, replayInsert, replayFirstApp] + +theorem consRootCheckTailMiss : + consRootCheckHeadState.inferTypeC[ + ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (.fvar consRootCheckNId)]? = none := by + simp [consRootCheckHeadState, consRootCheckHeadDomainState, + consRootCheckNState, consRootCheckNatState, + consRootCheckAlphaState, nilRootSortState, + replayInsert, ctorIndexedVecApp] + +def consRootCheckNInferState : TypeChecker.State := + replayInsert consRootCheckFirstAppState + (.fvar consRootCheckNId) (.const ``Nat []) + +def consRootCheckTailDomainState : TypeChecker.State := + replayInsert consRootCheckNInferState + (ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (.fvar consRootCheckNId)) + (.sort (.succ (.param `u))) + +theorem replayInferConsRootTailDomain (fuel : Nat) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (.fvar consRootCheckNId)) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consRootCheckHeadLctx) consRootCheckHeadState = + .ok (.sort (.succ (.param `u)), + consRootCheckTailDomainState) := by + simpa [consRootCheckFirstAppState, consRootCheckNInferState, + consRootCheckTailDomainState] using + (replayInferTailDomainAlphaCachedCore fuel + consRootCheckHeadLctx consRootCheckHeadState + consRootCheckAlphaId consRootCheckNId + consRootCheckAlphaCache consRootCheckFamilyMiss + consRootCheckFirstAppMiss consRootCheckNMiss + consRootCheckTailMiss consRootCheckNFind) + +def consRootCheckTailId : FVarId := + ⟨consRootCheckTailDomainState.ngen.curr⟩ + +def consRootCheckTailLctx : LocalContext := + consRootCheckHeadLctx.mkLocalDecl consRootCheckTailId + consTailName + (ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (.fvar consRootCheckNId)) .default + +def consRootCheckTailState : TypeChecker.State := + { consRootCheckTailDomainState with + ngen := consRootCheckTailDomainState.ngen.next } + +theorem consRootCheckTailFirstCache : + consRootCheckTailState.inferTypeC[ + replayFirstApp (.fvar consRootCheckAlphaId)]? = + some vecFamilyTail := by + change consRootCheckTailDomainState.inferTypeC[ + replayFirstApp (.fvar consRootCheckAlphaId)]? = some vecFamilyTail + unfold consRootCheckTailDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [replayIndexedVecAppBeqFirstApp] + simp only [Bool.false_eq_true, if_false] + unfold consRootCheckNInferState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show ((.fvar consRootCheckNId : Expr) == + replayFirstApp (.fvar consRootCheckAlphaId)) = false by + exact replayFVarBeqApp consRootCheckNId + (.const ``IndexedVec [.param `u]) + (.fvar consRootCheckAlphaId)] + simp only [Bool.false_eq_true, if_false] + unfold consRootCheckFirstAppState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +theorem consRootCheckTailNCache : + consRootCheckTailState.inferTypeC[ + (.fvar consRootCheckNId : Expr)]? = some (.const ``Nat []) := by + change consRootCheckTailDomainState.inferTypeC[ + (.fvar consRootCheckNId : Expr)]? = some (.const ``Nat []) + unfold consRootCheckTailDomainState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [show (ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (.fvar consRootCheckNId) == + (.fvar consRootCheckNId : Expr)) = false by + exact replayAppBeqFVar + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consRootCheckAlphaId)) + (.fvar consRootCheckNId) consRootCheckNId] + simp only [Bool.false_eq_true, if_false] + unfold consRootCheckNInferState replayInsert + rw [Std.HashMap.getElem?_insert] + rw [beq_self_eq_true] + rfl + +theorem consRootCheckTailSuccMiss : + consRootCheckTailState.inferTypeC[ + (.const ``Nat.succ [] : Expr)]? = none := by + simp [consRootCheckTailState, consRootCheckTailDomainState, + consRootCheckNInferState, consRootCheckFirstAppState, + consRootCheckHeadState, consRootCheckHeadDomainState, + consRootCheckNState, consRootCheckNatState, + consRootCheckAlphaState, nilRootSortState, + replayInsert, ctorIndexedVecApp, replayFirstApp] + +theorem consRootCheckTailSuccAppMiss : + consRootCheckTailState.inferTypeC[ + replaySuccApp (.fvar consRootCheckNId)]? = none := by + simp [consRootCheckTailState, consRootCheckTailDomainState, + consRootCheckNInferState, consRootCheckFirstAppState, + consRootCheckHeadState, consRootCheckHeadDomainState, + consRootCheckNState, consRootCheckNatState, + consRootCheckAlphaState, nilRootSortState, + replayInsert, ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +theorem consRootCheckTailTerminalMiss : + consRootCheckTailState.inferTypeC[ + ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (replaySuccApp (.fvar consRootCheckNId))]? = none := by + simp [consRootCheckTailState, consRootCheckTailDomainState, + consRootCheckNInferState, consRootCheckFirstAppState, + consRootCheckHeadState, consRootCheckHeadDomainState, + consRootCheckNState, consRootCheckNatState, + consRootCheckAlphaState, nilRootSortState, + replayInsert, ctorIndexedVecApp, replayFirstApp, replaySuccApp] + +def consRootCheckSuccState : TypeChecker.State := + replayInsert consRootCheckTailState (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) + +def consRootCheckSuccAppState : TypeChecker.State := + replayInsert consRootCheckSuccState + (replaySuccApp (.fvar consRootCheckNId)) (.const ``Nat []) + +def consRootCheckTerminalState : TypeChecker.State := + replayInsert consRootCheckSuccAppState + (ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (replaySuccApp (.fvar consRootCheckNId))) + (.sort (.succ (.param `u))) + +theorem replayInferConsRootTerminal (fuel : Nat) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar consRootCheckAlphaId) + (replaySuccApp (.fvar consRootCheckNId))) false + (TypeChecker.Methods.withFuel fuel) + (tcContext consRootCheckTailLctx) consRootCheckTailState = + .ok (.sort (.succ (.param `u)), + consRootCheckTerminalState) := by + simpa [consRootCheckSuccState, consRootCheckSuccAppState, + consRootCheckTerminalState] using + (replayInferIndexedVecSuccFromCacheCore fuel + consRootCheckTailLctx consRootCheckTailState + consRootCheckAlphaId consRootCheckNId + consRootCheckTailFirstCache consRootCheckTailSuccMiss + consRootCheckTailNCache consRootCheckTailSuccAppMiss + consRootCheckTailTerminalMiss) + +open private mkLevelIMaxCore mkLevelMaxCore from Lean.Level in +@[simp] theorem replayMkLevelIMaxSuccSuccParamSuccParam : + mkLevelIMax' (.succ (.succ (.param `u))) + (.succ (.param `u)) = .succ (.succ (.param `u)) := by + simp [mkLevelIMax', mkLevelIMaxCore, mkLevelMax', mkLevelMaxCore, + Level.isNeverZero, Level.isZero, Level.isExplicit, + Level.hasMVar', Level.hasParam', Level.getOffset, + Level.getOffsetAux, Level.getLevelOffset] + +theorem replayConsRootCheckTypeM : + TypeChecker.M.run ctorEnv .safe consRootContext.lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType indexedVecConsInfo.type) = + .ok (.sort (.succ (.succ (.param `u)))) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType indexedVecConsInfo.type false + (TypeChecker.Methods.withFuel 10000) + (tcContext consRootContext.lctx) ({} : TypeChecker.State)) = _ + rw [consInfoTypeShape] + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' consCtorTypeRaw false + (TypeChecker.Methods.withFuel 9999) + (tcContext consRootContext.lctx) ({} : TypeChecker.State)) = _ + unfold consCtorTypeRaw consNTypeRaw consHeadTypeRaw + consTailTypeRaw consTerminalRaw TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [replayInferConsRootSort] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp [Expr.instantiate1'] + have hnat : + TypeChecker.Inner.inferType (.const ``Nat []) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consRootCheckAlphaLctx) consRootCheckAlphaState = + .ok (.sort (.succ .zero), consRootCheckNatState) := by + change TypeChecker.Inner.inferType' (.const ``Nat []) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consRootCheckAlphaLctx) consRootCheckAlphaState = _ + exact replayInferConsRootNat 9998 + simp only [consRootCheckAlphaLctx, consRootCheckAlphaId, + consRootCheckAlphaState, tcContext] at hnat + simp only [tcContext] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hnat] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp [Expr.instantiate1'] + have hhead : + TypeChecker.Inner.inferType (.fvar consRootCheckAlphaId) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consRootCheckNLctx) consRootCheckNState = + .ok (.sort (.succ (.param `u)), + consRootCheckHeadDomainState) := by + change TypeChecker.Inner.inferType' + (.fvar consRootCheckAlphaId) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consRootCheckNLctx) consRootCheckNState = _ + exact replayInferConsRootHeadDomain 9998 + simp only [consRootCheckNLctx, consRootCheckNId, + consRootCheckNState, consRootCheckAlphaLctx, + consRootCheckAlphaId, tcContext] at hhead + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hhead] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp + have htail : + TypeChecker.Inner.inferType + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consRootCheckAlphaId)).app + (.fvar consRootCheckNId)) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consRootCheckHeadLctx) consRootCheckHeadState = + .ok (.sort (.succ (.param `u)), + consRootCheckTailDomainState) := by + change TypeChecker.Inner.inferType' + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consRootCheckAlphaId)).app + (.fvar consRootCheckNId)) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consRootCheckHeadLctx) consRootCheckHeadState = _ + simpa [ctorIndexedVecApp] using + replayInferConsRootTailDomain 9998 + simp only [consRootCheckHeadLctx, consRootCheckHeadId, + consRootCheckHeadState, consRootCheckNLctx, consRootCheckNId, + consRootCheckAlphaLctx, consRootCheckAlphaId, + tcContext] at htail + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [htail] + simp only [ensureSortExact] + rw [withLocalDeclEq] + simp + have hterminal : + TypeChecker.Inner.inferType + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consRootCheckAlphaId)).app + ((.const ``Nat.succ [] : Expr).app + (.fvar consRootCheckNId))) false + (TypeChecker.Methods.withFuel 9999) + (tcContext consRootCheckTailLctx) consRootCheckTailState = + .ok (.sort (.succ (.param `u)), + consRootCheckTerminalState) := by + change TypeChecker.Inner.inferType' + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar consRootCheckAlphaId)).app + ((.const ``Nat.succ [] : Expr).app + (.fvar consRootCheckNId))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext consRootCheckTailLctx) consRootCheckTailState = _ + simpa [ctorIndexedVecApp, replaySuccApp] using + replayInferConsRootTerminal 9998 + simp only [consRootCheckTailLctx, consRootCheckTailId, + consRootCheckTailState, consRootCheckHeadLctx, + consRootCheckHeadId, consRootCheckNLctx, consRootCheckNId, + consRootCheckAlphaLctx, consRootCheckAlphaId, + ctorIndexedVecApp, tcContext] at hterminal + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hterminal] + simp only [ensureSortExact] + simp [Expr.sortLevel!, Pure.pure, ReaderT.pure, + StateT.pure, Except.pure] + rfl + +/-! ## Source-indexed candidate trace -/ + +def consAlphaAnnotations : + AddInductive.CandidateTypeAnnotations + (.sort (.succ (.param `u))) where + consumed := .sort (.succ (.param `u)) + trace := .identity _ + +def consNatAnnotations : + AddInductive.CandidateTypeAnnotations (.const ``Nat []) where + consumed := .const ``Nat [] + trace := .identity _ + +def consHeadAnnotations : + AddInductive.CandidateTypeAnnotations consAlphaExpr where + consumed := consAlphaExpr + trace := .identity _ + +def consTailAnnotations : + AddInductive.CandidateTypeAnnotations consTailDomain where + consumed := consTailDomain + trace := .identity _ + +theorem consAlphaAnnotationTraceBuild : + AddInductive.CandidateTypeAnnotationTrace.build + (.sort (.succ (.param `u))) = + ⟨.sort (.succ (.param `u)), .identity _⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build] + +theorem consNatAnnotationTraceBuild : + AddInductive.CandidateTypeAnnotationTrace.build (.const ``Nat []) = + ⟨.const ``Nat [], .identity _⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build] + +theorem consHeadAnnotationTraceBuild : + AddInductive.CandidateTypeAnnotationTrace.build consAlphaExpr = + ⟨consAlphaExpr, .identity _⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build, + consAlphaExprShape] + +theorem consTailAnnotationTraceBuild : + AddInductive.CandidateTypeAnnotationTrace.build consTailDomain = + ⟨consTailDomain, .identity _⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build, consTailDomain] + +theorem consAlphaAnnotationsBuild : + AddInductive.buildCandidateTypeAnnotations + (.sort (.succ (.param `u))) = .ok consAlphaAnnotations := by + unfold AddInductive.buildCandidateTypeAnnotations + rw [consAlphaAnnotationTraceBuild] + rfl + +theorem consNatAnnotationsBuild : + AddInductive.buildCandidateTypeAnnotations (.const ``Nat []) = + .ok consNatAnnotations := by + unfold AddInductive.buildCandidateTypeAnnotations + rw [consNatAnnotationTraceBuild] + rfl + +theorem consHeadAnnotationsBuild : + AddInductive.buildCandidateTypeAnnotations consAlphaExpr = + .ok consHeadAnnotations := by + unfold AddInductive.buildCandidateTypeAnnotations + rw [consHeadAnnotationTraceBuild] + rfl + +theorem consTailAnnotationsBuild : + AddInductive.buildCandidateTypeAnnotations consTailDomain = + .ok consTailAnnotations := by + unfold AddInductive.buildCandidateTypeAnnotations + rw [consTailAnnotationTraceBuild] + rfl + +theorem consAlphaAnnotationsEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨consRootContext, (.sort (.succ (.param `u))), + consAlphaAnnotations.consumed⟩ := by + simpa [consAlphaAnnotations] using + (candidateIsDefEqSelfValid consRootContext + (.sort (.succ (.param `u))) 9999 rfl) + +theorem consNatAnnotationsEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨consAlphaContext, (.const ``Nat []), + consNatAnnotations.consumed⟩ := by + simpa [consNatAnnotations] using + (candidateIsDefEqSelfValid consAlphaContext + (.const ``Nat []) 9999 rfl) + +theorem consHeadAnnotationsEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨consNContext, consAlphaExpr, + consHeadAnnotations.consumed⟩ := by + simpa [consHeadAnnotations] using + (candidateIsDefEqSelfValid consNContext consAlphaExpr 9999 rfl) + +theorem consTailAnnotationsEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨consHeadContext, consTailDomain, + consTailAnnotations.consumed⟩ := by + simpa [consTailAnnotations] using + (candidateIsDefEqSelfValid consHeadContext consTailDomain 9999 rfl) + +theorem consRootCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consRootContext, indexedVecConsInfo.type, + .sort (.succ (.succ (.param `u)))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consRootContext, ctorContext] using + replayConsRootCheckTypeM + +theorem consRootWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consRootContext, indexedVecConsInfo.type, + indexedVecConsInfo.type⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consRootContext, ctorContext] using replayConsRootWhnfM + +theorem consAfterAlphaCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consAlphaContext, consAfterAlpha, + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl] using + replayConsAfterAlphaCheckTypeM + +theorem consAfterAlphaWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consAlphaContext, consAfterAlpha, consAfterAlpha⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl] using + replayConsAfterAlphaWhnfM + +theorem consAfterNCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consNContext, consAfterN, .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consNContext, consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl] using + replayConsAfterNCheckTypeM + +theorem consAfterNWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consNContext, consAfterN, consAfterN⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consNContext, consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl] using + replayConsAfterNWhnfM + +theorem consAfterHeadCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consHeadContext, consAfterHead, + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consHeadContext, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + replayConsAfterHeadCheckTypeM + +theorem consAfterHeadWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consHeadContext, consAfterHead, consAfterHead⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consHeadContext, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + replayConsAfterHeadWhnfM + +theorem consTerminalCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consTailContext, consTerminal, + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consTailContext, consHeadContext, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + replayConsTerminalCheckTypeM + +theorem consTerminalWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consTailContext, consTerminal, consTerminal⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consTailContext, consHeadContext, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + replayConsTerminalWhnfM + +theorem consAlphaDomainCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consRootContext, (.sort (.succ (.param `u))), + .sort (.succ (.succ (.param `u)))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consRootContext, nilCandidateContext, ctorContext] using + nilDomainCheckValid + +theorem consAlphaDomainWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consRootContext, (.sort (.succ (.param `u))), + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consRootContext, nilCandidateContext, ctorContext] using + nilDomainWhnfValid + +theorem consNatDomainCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consAlphaContext, (.const ``Nat []), + .sort (.succ .zero)⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl] using + ctorNatCheckTypeM consAlphaContext.lctx + +theorem consNatDomainWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consAlphaContext, (.const ``Nat []), (.const ``Nat [])⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl] using + ctorNatWhnfM consAlphaContext.lctx + +theorem consHeadDomainCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consNContext, consAlphaExpr, + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consAlphaExprShape, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + (ctorFVarCheckTypeM consNContext.lctx consAlphaId + (.sort (.succ (.param `u))) consAlphaFindInN) + +theorem consHeadDomainWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consNContext, consAlphaExpr, consAlphaExpr⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consAlphaExprShape, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + (ctorFVarWhnfM consNContext.lctx consAlphaId consAlphaFindInN) + +theorem consTailDomainCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨consHeadContext, consTailDomain, + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + consHeadContext, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + replayConsTailDomainCheckTypeM + +theorem consTailDomainWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨consHeadContext, consTailDomain, consTailDomain⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + consHeadContext, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl] using + replayConsTailDomainWhnfM + +def consAlphaDomainCandidateTrace : + AddInductive.CandidateExprTrace consRootContext + (.sort (.succ (.param `u))) := + .terminal consRootContext (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u)))) + (.sort (.succ (.param `u))) + consAlphaDomainCheckValid consAlphaDomainWhnfValid + +def consNatDomainCandidateTrace : + AddInductive.CandidateExprTrace consAlphaContext + (.const ``Nat []) := + .terminal consAlphaContext (.const ``Nat []) + (.sort (.succ .zero)) (.const ``Nat []) + consNatDomainCheckValid consNatDomainWhnfValid + +def consHeadDomainCandidateTrace : + AddInductive.CandidateExprTrace consNContext consAlphaExpr := + .terminal consNContext consAlphaExpr + (.sort (.succ (.param `u))) consAlphaExpr + consHeadDomainCheckValid consHeadDomainWhnfValid + +def consTailDomainCandidateTrace : + AddInductive.CandidateExprTrace consHeadContext consTailDomain := + .terminal consHeadContext consTailDomain + (.sort (.succ (.param `u))) consTailDomain + consTailDomainCheckValid consTailDomainWhnfValid + +def consTerminalCandidateTrace : + AddInductive.CandidateExprTrace consTailContext + (consAfterHead.bindingBody!.instantiate1 + consHeadContext.freshExpr) := + .terminal consTailContext + (consAfterHead.bindingBody!.instantiate1 consHeadContext.freshExpr) + (.sort (.succ (.param `u))) consTerminal + (by simpa only [consTerminalShape] using consTerminalCheckValid) + (by simpa only [consTerminalShape] using consTerminalWhnfValid) + +def consAfterHeadCandidateTrace : + AddInductive.CandidateExprTrace consHeadContext + (consAfterN.bindingBody!.instantiate1 consNContext.freshExpr) := + .forallE consHeadContext + (consAfterN.bindingBody!.instantiate1 consNContext.freshExpr) + (.sort (.succ (.param `u))) consTailName consTailDomain + consAfterHead.bindingBody! .default consHeadContextFresh + consTailAnnotations consTailAnnotationsEq + (by simpa only [consAfterHeadShape] using consAfterHeadCheckValid) + (by + simpa [consAfterN, consAfterHead, consTailDomain, + consAlphaExpr, consNExpr, consRootContext, consAlphaContext, + consNContext, ctorContext, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, Expr.bindingBody!, + Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using + consAfterHeadWhnfValid) + consTailDomainCandidateTrace consTerminalCandidateTrace + +def consAfterNCandidateTrace : + AddInductive.CandidateExprTrace consNContext + (consAfterAlpha.bindingBody!.instantiate1 + consAlphaContext.freshExpr) := + .forallE consNContext + (consAfterAlpha.bindingBody!.instantiate1 + consAlphaContext.freshExpr) + (.sort (.succ (.param `u))) consHeadName consAlphaExpr + consAfterN.bindingBody! .default consNContextFresh + consHeadAnnotations consHeadAnnotationsEq + (by simpa only [consAfterNShape] using consAfterNCheckValid) + (by + simpa [consAfterAlpha, consAfterN, consAlphaExpr, consNExpr, + consRootContext, consAlphaContext, ctorContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, Expr.bindingBody!, + Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using + consAfterNWhnfValid) + consHeadDomainCandidateTrace consAfterHeadCandidateTrace + +def consAfterAlphaCandidateTrace : + AddInductive.CandidateExprTrace consAlphaContext + (consNTypeRaw.instantiate1 consRootContext.freshExpr) := + .forallE consAlphaContext + (consNTypeRaw.instantiate1 consRootContext.freshExpr) + (.sort (.succ (.param `u))) consNName (.const ``Nat []) + consAfterAlpha.bindingBody! .implicit consAlphaContextFresh + consNatAnnotations consNatAnnotationsEq + (by simpa only [consAfterAlphaShape] using consAfterAlphaCheckValid) + (by + simpa [consNTypeRaw, consHeadTypeRaw, consTailTypeRaw, + consTerminalRaw, consAfterAlpha, consAlphaExpr, + consRootContext, ctorContext, AddInductive.Context.freshExpr, + Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using + consAfterAlphaWhnfValid) + consNatDomainCandidateTrace consAfterNCandidateTrace + +def consCandidateTrace : + AddInductive.CandidateExprTrace consRootContext + indexedVecConsInfo.type := + .forallE consRootContext indexedVecConsInfo.type + (.sort (.succ (.succ (.param `u)))) consAlphaName + (.sort (.succ (.param `u))) consNTypeRaw .implicit consRootFresh + consAlphaAnnotations consAlphaAnnotationsEq consRootCheckValid + (by + simpa [consInfoTypeShape, consCtorTypeRaw] using consRootWhnfValid) + consAlphaDomainCandidateTrace consAfterAlphaCandidateTrace + +def consCandidate : AddInductive.CandidateExpr indexedVecConsInfo.type := + ⟨consRootContext, consCandidateTrace⟩ + +theorem consCandidate_view_eq : + consCandidate.view = indexedVecConsInfo.type := by + have habstract (context : AddInductive.Context) (e : Expr) : + e.abstract #[context.freshExpr] = + Expr.abstract1 context.freshFVarId e := by + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl] + simp only [Expr.abstract_eq, Expr.abstractList] + simp only [consCandidate, AddInductive.CandidateExpr.view, + consCandidateTrace, consAlphaDomainCandidateTrace, + consNatDomainCandidateTrace, consHeadDomainCandidateTrace, + consTailDomainCandidateTrace, consTerminalCandidateTrace, + consAfterHeadCandidateTrace, consAfterNCandidateTrace, + consAfterAlphaCandidateTrace, AddInductive.CandidateExprTrace.view] + rw [habstract, habstract, habstract, habstract] + rw [consInfoTypeShape] + simp [consCtorTypeRaw, consNTypeRaw, consHeadTypeRaw, + consTailTypeRaw, consTerminalRaw, consTerminal, consTailDomain, + consAlphaExpr, consNExpr, + consRootContext, consAlphaContext, ctorContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, + AddInductive.Context.freshFVarId, + Expr.abstract1, NameGenerator.next, NameGenerator.curr] + +/-- The retained `cons` candidate preserves all four Pi nodes, their domains, +and the terminal recursive result under the exact instantiated contexts. -/ +theorem consCandidate_identity : + TypeChecker.CandidateExprIdentity consCandidate.trace := by + change TypeChecker.CandidateExprIdentity consCandidateTrace + unfold consCandidateTrace + refine .forallE (name := consAlphaName) (binderInfo := .implicit) + (body := consNTypeRaw) (annotations := consAlphaAnnotations) + consAlphaDomainCandidateTrace consAfterAlphaCandidateTrace + (by simpa [consCtorTypeRaw] using consInfoTypeShape) + rfl (.terminal rfl) ?_ + · unfold consAfterAlphaCandidateTrace + refine .forallE (name := consNName) (binderInfo := .implicit) + (body := consAfterAlpha.bindingBody!) + (annotations := consNatAnnotations) + consNatDomainCandidateTrace consAfterNCandidateTrace + (by rw [consAfterAlphaShape]; rfl) rfl (.terminal rfl) ?_ + · unfold consAfterNCandidateTrace + refine .forallE (name := consHeadName) (binderInfo := .default) + (body := consAfterN.bindingBody!) + (annotations := consHeadAnnotations) + consHeadDomainCandidateTrace consAfterHeadCandidateTrace + (by rw [consAfterNShape]; rfl) rfl (.terminal rfl) ?_ + · unfold consAfterHeadCandidateTrace + refine .forallE (name := consTailName) (binderInfo := .default) + (body := consAfterHead.bindingBody!) + (annotations := consTailAnnotations) + consTailDomainCandidateTrace consTerminalCandidateTrace + (by rw [consAfterHeadShape]; rfl) rfl (.terminal rfl) ?_ + · unfold consTerminalCandidateTrace + exact .terminal (by + simpa only [Expr.instantiate1_eq] using consTerminalShape.symm) + +theorem consAlphaDomainCandidateTraceLoop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop consRootContext + (.sort (.succ (.param `u))) (fuel + 1) = + .ok consAlphaDomainCandidateTrace := by + simpa only [consAlphaDomainCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + consRootContext (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u)))) + (.sort (.succ (.param `u))) fuel + consAlphaDomainCheckValid consAlphaDomainWhnfValid rfl + +theorem consNatDomainCandidateTraceLoop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop consAlphaContext + (.const ``Nat []) (fuel + 1) = + .ok consNatDomainCandidateTrace := by + simpa only [consNatDomainCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + consAlphaContext (.const ``Nat []) (.sort (.succ .zero)) + (.const ``Nat []) fuel consNatDomainCheckValid + consNatDomainWhnfValid rfl + +theorem consHeadDomainCandidateTraceLoop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop consNContext consAlphaExpr + (fuel + 1) = .ok consHeadDomainCandidateTrace := by + simpa only [consHeadDomainCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + consNContext consAlphaExpr (.sort (.succ (.param `u))) + consAlphaExpr fuel consHeadDomainCheckValid + consHeadDomainWhnfValid (by rw [consAlphaExprShape]; rfl) + +theorem consTailDomainCandidateTraceLoop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop consHeadContext consTailDomain + (fuel + 1) = .ok consTailDomainCandidateTrace := by + simpa only [consTailDomainCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + consHeadContext consTailDomain (.sort (.succ (.param `u))) + consTailDomain fuel consTailDomainCheckValid + consTailDomainWhnfValid (by rfl) + +theorem consTerminalCandidateTraceLoop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop consTailContext + (consAfterHead.bindingBody!.instantiate1 + consHeadContext.freshExpr) (fuel + 1) = + .ok consTerminalCandidateTrace := by + simpa only [consTerminalCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + consTailContext + (consAfterHead.bindingBody!.instantiate1 consHeadContext.freshExpr) + (.sort (.succ (.param `u))) consTerminal fuel + (by simpa only [consTerminalShape] using consTerminalCheckValid) + (by simpa only [consTerminalShape] using consTerminalWhnfValid) + (by rfl) + +theorem consAfterHeadCandidateTraceLoop : + AddInductive.buildCandidateExpr.loop consHeadContext + (consAfterN.bindingBody!.instantiate1 consNContext.freshExpr) 997 = + .ok consAfterHeadCandidateTrace := by + rw [show 997 = 996 + 1 by rfl] + simpa only [consAfterHeadCandidateTrace, consTailContext, + consTailAnnotations] using + (AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := consHeadContext) + (e := consAfterN.bindingBody!.instantiate1 consNContext.freshExpr) + (inferred := .sort (.succ (.param `u))) (fuel := 996) + (name := consTailName) (domain := consTailDomain) + (body := consAfterHead.bindingBody!) (binderInfo := .default) + (hfresh := consHeadContextFresh) + (annotations := consTailAnnotations) + (hannotations := consTailAnnotationsBuild) + (hannotationsEq := consTailAnnotationsEq) + (hcheck := by + simpa only [consAfterHeadShape] using consAfterHeadCheckValid) + (hrun := by + simpa [consAfterN, consAfterHead, consTailDomain, + consAlphaExpr, consNExpr, consRootContext, consAlphaContext, + consNContext, ctorContext, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, Expr.bindingBody!, + Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using + consAfterHeadWhnfValid) + (domainCandidate := consTailDomainCandidateTrace) + (bodyCandidate := consTerminalCandidateTrace) + (hdomain := by + simpa using consTailDomainCandidateTraceLoop 995) + (hbody := by + simpa [consTailContext, consTailAnnotations] using + consTerminalCandidateTraceLoop 995)) + +theorem consAfterNCandidateTraceLoop : + AddInductive.buildCandidateExpr.loop consNContext + (consAfterAlpha.bindingBody!.instantiate1 + consAlphaContext.freshExpr) 998 = + .ok consAfterNCandidateTrace := by + rw [show 998 = 997 + 1 by rfl] + simpa only [consAfterNCandidateTrace, consHeadContext, + consHeadAnnotations] using + (AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := consNContext) + (e := consAfterAlpha.bindingBody!.instantiate1 + consAlphaContext.freshExpr) + (inferred := .sort (.succ (.param `u))) (fuel := 997) + (name := consHeadName) (domain := consAlphaExpr) + (body := consAfterN.bindingBody!) (binderInfo := .default) + (hfresh := consNContextFresh) + (annotations := consHeadAnnotations) + (hannotations := consHeadAnnotationsBuild) + (hannotationsEq := consHeadAnnotationsEq) + (hcheck := by + simpa only [consAfterNShape] using consAfterNCheckValid) + (hrun := by + simpa [consAfterAlpha, consAfterN, consAlphaExpr, consNExpr, + consRootContext, consAlphaContext, ctorContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, Expr.bindingBody!, + Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using + consAfterNWhnfValid) + (domainCandidate := consHeadDomainCandidateTrace) + (bodyCandidate := consAfterHeadCandidateTrace) + (hdomain := by + simpa using consHeadDomainCandidateTraceLoop 996) + (hbody := by + simpa [consHeadContext, consHeadAnnotations] using + consAfterHeadCandidateTraceLoop)) + +theorem consAfterAlphaCandidateTraceLoop : + AddInductive.buildCandidateExpr.loop consAlphaContext + (consNTypeRaw.instantiate1 consRootContext.freshExpr) 999 = + .ok consAfterAlphaCandidateTrace := by + rw [show 999 = 998 + 1 by rfl] + simpa only [consAfterAlphaCandidateTrace, consNContext, + consNatAnnotations] using + (AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := consAlphaContext) + (e := consNTypeRaw.instantiate1 consRootContext.freshExpr) + (inferred := .sort (.succ (.param `u))) (fuel := 998) + (name := consNName) (domain := .const ``Nat []) + (body := consAfterAlpha.bindingBody!) (binderInfo := .implicit) + (hfresh := consAlphaContextFresh) + (annotations := consNatAnnotations) + (hannotations := consNatAnnotationsBuild) + (hannotationsEq := consNatAnnotationsEq) + (hcheck := by + simpa only [consAfterAlphaShape] using consAfterAlphaCheckValid) + (hrun := by + simpa [consNTypeRaw, consHeadTypeRaw, consTailTypeRaw, + consTerminalRaw, consAfterAlpha, consAlphaExpr, + consRootContext, ctorContext, AddInductive.Context.freshExpr, + Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using + consAfterAlphaWhnfValid) + (domainCandidate := consNatDomainCandidateTrace) + (bodyCandidate := consAfterNCandidateTrace) + (hdomain := by + simpa using consNatDomainCandidateTraceLoop 997) + (hbody := by + simpa [consNContext, consNatAnnotations] using + consAfterNCandidateTraceLoop)) + +theorem consCandidateTraceLoop : + AddInductive.buildCandidateExpr.loop consRootContext + indexedVecConsInfo.type consRootContext.fuel.inductiveFuel = + .ok consCandidateTrace := by + change AddInductive.buildCandidateExpr.loop consRootContext + indexedVecConsInfo.type (999 + 1) = _ + simpa only [consCandidateTrace, consAlphaContext, + consAlphaAnnotations] using + (AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := consRootContext) (e := indexedVecConsInfo.type) + (inferred := .sort (.succ (.succ (.param `u)))) (fuel := 999) + (name := consAlphaName) + (domain := .sort (.succ (.param `u))) + (body := consNTypeRaw) (binderInfo := .implicit) + (hfresh := consRootFresh) + (annotations := consAlphaAnnotations) + (hannotations := consAlphaAnnotationsBuild) + (hannotationsEq := consAlphaAnnotationsEq) + (hcheck := consRootCheckValid) + (hrun := by + simpa [consInfoTypeShape, consCtorTypeRaw] using consRootWhnfValid) + (domainCandidate := consAlphaDomainCandidateTrace) + (bodyCandidate := consAfterAlphaCandidateTrace) + (hdomain := by + simpa using consAlphaDomainCandidateTraceLoop 998) + (hbody := by + simpa [consAlphaContext, consAlphaAnnotations] using + consAfterAlphaCandidateTraceLoop)) + +theorem consCandidateProduced : + AddInductive.buildCandidateExpr indexedVecConsInfo.type + consRootContext = .ok consCandidate := by + unfold AddInductive.buildCandidateExpr + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + rw [consCandidateTraceLoop] + rfl + +def indexedVecNilConstructorCandidate : + AddInductive.CandidateConstructor indexedVecKernelNil where + type := nilCandidate + +def indexedVecConsConstructorCandidate : + AddInductive.CandidateConstructor indexedVecKernelCons where + type := consCandidate + +def indexedVecFamilyListCandidate : + AddInductive.CandidateFamily indexedVecKernelType where + familyType := ⟨indexedVecFamilyCandidate⟩ + constructors := + .cons indexedVecNilConstructorCandidate + (.cons indexedVecConsConstructorCandidate .nil) + +def indexedVecNormalizationCandidate : + AddInductive.NormalizationCandidate [indexedVecKernelType] where + families := .cons indexedVecFamilyListCandidate .nil + +/-- Source-indexed evidence for the complete `IndexedVec` family-type list. -/ +theorem indexedVecFamilyTypeListProduced : + AddInductive.CandidateFamilyTypeListProduced + indexedVecFamilyCandidateContext + (.cons indexedVecFamilyListCandidate.familyType .nil) := by + exact .cons (by + unfold AddInductive.normalizeCandidateFamilyType + simp only [ReaderT.bind, Bind.bind] + simp only [indexedVecKernelType] + rw [indexedVecFamily_candidateTrace] + rfl) .nil + +theorem indexedVecFamilyTypeListCandidateProduced : + (withReader (fun c : AddInductive.Context => { c with lctx := {} }) + (AddInductive.normalizeCandidateFamilyTypeList + [indexedVecKernelType])) indexedVecFamilyCandidateContext = + .ok (.cons indexedVecFamilyListCandidate.familyType .nil) := by + change AddInductive.normalizeCandidateFamilyTypeList + [indexedVecKernelType] indexedVecFamilyCandidateContext = _ + exact indexedVecFamilyTypeListProduced.normalize + +/-- The two constructor positions are assembled in source order. The +dependent list indices rule out truncating, swapping, or reusing either +constructor proof. -/ +theorem indexedVecConstructorListProduced : + AddInductive.CandidateConstructorListProduced ctorContext + indexedVecFamilyListCandidate.constructors := by + have hnil : AddInductive.buildCandidateExpr indexedVecNilInfo.type + ctorContext = .ok nilCandidate := by + simpa [nilCandidateContext] using nilCandidateProduced + have hcons : AddInductive.buildCandidateExpr indexedVecConsInfo.type + ctorContext = .ok consCandidate := by + simpa [consRootContext] using consCandidateProduced + exact .cons (by + unfold AddInductive.normalizeCandidateConstructor + simp only [ReaderT.bind, Bind.bind] + simp only [indexedVecKernelNil] + rw [hnil] + rfl) (.cons (by + unfold AddInductive.normalizeCandidateConstructor + simp only [ReaderT.bind, Bind.bind] + simp only [indexedVecKernelCons] + rw [hcons] + rfl) .nil) + +theorem indexedVecConstructorListCandidateProduced : + AddInductive.normalizeCandidateConstructorList + indexedVecKernelType.ctors ctorContext = + .ok indexedVecFamilyListCandidate.constructors := by + exact indexedVecConstructorListProduced.normalize + +/-- Source-indexed evidence for complete family assembly after constructor +normalization. -/ +theorem indexedVecFamilyListProduced : + AddInductive.CandidateFamilyListProduced ctorContext + (.cons indexedVecFamilyListCandidate.familyType .nil) + indexedVecNormalizationCandidate.families := by + exact .cons indexedVecConstructorListProduced .nil + +theorem indexedVecFamilyListCandidateProduced : + AddInductive.normalizeCandidateFamilyList + (.cons indexedVecFamilyListCandidate.familyType .nil) + ctorContext = + .ok indexedVecNormalizationCandidate.families := by + exact indexedVecFamilyListProduced.normalize + +end IndexedVecConsReplay + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/IndexedVecConstructors.lean b/Ix/Theory/Named/Verify/Environment/IndexedVecConstructors.lean new file mode 100644 index 000000000..2af5cf296 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/IndexedVecConstructors.lean @@ -0,0 +1,1803 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.IndexedVecCandidate + +/-! +# IndexedVec constructor normalization candidates + +Exact ordinary-checker and candidate-producer traces for the real `nil` and +`cons` constructor metadata, staged in the post-family kernel environment. +This module extends the family-validation seam proved in +`IndexedVecCandidate` toward the complete normalization candidate used by the +certified inductive-generation path. +-/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta +open Ix.Theory.Named.InductiveFixtures + +def ctorEnv : Kernel.Environment := + -- `declareInductiveTypes` preserves the input environment header while + -- inserting the raw family constant. Use that exact staged header so this + -- environment is not merely lookup-equivalent to the producer result. + Kernel.Environment.ofConstants `_indexedVecCandidate indexedVecTypeMap + +def ctorContext : AddInductive.Context where + env := ctorEnv + lparams := [`u] + safety := .safe + allowPrimitive := false + +theorem type_lookup_family : + ctorEnv.find? ``IndexedVec = some indexedVecInfo := by + change indexedVecTypeMap.find?' ``IndexedVec = some indexedVecInfo + rw [indexedVecTypeMap_wf.find?'_eq_find?, indexedVecTypeMap, + natMap_wf.find?_insert] + rfl + +theorem type_lookup_nat : ctorEnv.find? ``Nat = some natInfo := by + change indexedVecTypeMap.find?' ``Nat = some natInfo + rw [indexedVecTypeMap_wf.find?'_eq_find?, indexedVecTypeMap, + natMap_wf.find?_insert, nat_type_map_lookup] + simp +decide + +theorem nat_zero_map_lookup : + natMap.find? ``Nat.zero = some natZeroInfo := by + rw [natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert] + rfl + +theorem type_lookup_zero : + ctorEnv.find? ``Nat.zero = some natZeroInfo := by + change indexedVecTypeMap.find?' ``Nat.zero = some natZeroInfo + rw [indexedVecTypeMap_wf.find?'_eq_find?, indexedVecTypeMap, + natMap_wf.find?_insert, nat_zero_map_lookup] + simp +decide + +theorem type_lookup_succ : + ctorEnv.find? ``Nat.succ = some natSuccInfo := by + change indexedVecTypeMap.find?' ``Nat.succ = some natSuccInfo + rw [indexedVecTypeMap_wf.find?'_eq_find?, indexedVecTypeMap, + natMap_wf.find?_insert, nat_succ_map_lookup] + simp +decide + +@[simp] theorem type_get_family : + ctorEnv.get ``IndexedVec = .ok indexedVecInfo := by + unfold Kernel.Environment.get + rw [type_lookup_family] + rfl + +@[simp] theorem type_get_nat : ctorEnv.get ``Nat = .ok natInfo := by + unfold Kernel.Environment.get + rw [type_lookup_nat] + rfl + +@[simp] theorem type_get_zero : + ctorEnv.get ``Nat.zero = .ok natZeroInfo := by + unfold Kernel.Environment.get + rw [type_lookup_zero] + rfl + +@[simp] theorem type_get_succ : + ctorEnv.get ``Nat.succ = .ok natSuccInfo := by + unfold Kernel.Environment.get + rw [type_lookup_succ] + rfl + +def tcContext (lctx : LocalContext := {}) : TypeChecker.Context where + env := ctorEnv + lctx := lctx + lparams := [`u] + +@[simp] theorem checkLevelSuccParam (lctx) : + TypeChecker.Inner.checkLevel (tcContext lctx) + (.succ (.param `u)) = .ok () := by + simp [TypeChecker.Inner.checkLevel, tcContext, + Level.getUndefParam, Level.forEach, + Level.hasParam_eq, Level.hasParam'] + rfl + +@[simp] theorem checkLevelParam (lctx) : + TypeChecker.Inner.checkLevel (tcContext lctx) (.param `u) = + .ok () := by + simp [TypeChecker.Inner.checkLevel, tcContext, + Level.getUndefParam, Level.forEach, + Level.hasParam_eq, Level.hasParam'] + rfl + +@[simp] theorem indexedVecInfoLevelParams : + indexedVecInfo.levelParams = [`u] := rfl + +@[simp] theorem indexedVecInfoIsUnsafe : + indexedVecInfo.isUnsafe = false := rfl + +@[simp] theorem indexedVecInfoInstantiate : + indexedVecInfo.instantiateTypeLevelParams [.param `u] = + indexedVecInfo.type := by + rw [ConstantInfo.instantiateTypeLevelParams, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq] + simp [indexedVecInfo, ConstantInfo.type, ConstantInfo.toConstantVal, + Expr.instantiateLevelParamsCore', Level.substParams'] + +@[simp] theorem inferConstantFamily (lctx) : + TypeChecker.Inner.inferConstant (tcContext lctx) ``IndexedVec + [.param `u] false = .ok indexedVecInfo.type := by + unfold TypeChecker.Inner.inferConstant + simp only [tcContext] + rw [type_get_family] + simp only [Bind.bind, Except.bind] + rw [show indexedVecInfo.levelParams.length = 1 by rfl] + simp + rw [show TypeChecker.Inner.checkLevel + ({ env := ctorEnv, lctx := lctx, lparams := [`u] } : + TypeChecker.Context) (.param `u) = .ok () by + simpa [tcContext] using checkLevelParam lctx] + simp [indexedVecInfo, Bind.bind, Except.bind, Pure.pure, Except.pure] + +@[simp] theorem inferConstantNat (lctx) : + TypeChecker.Inner.inferConstant (tcContext lctx) ``Nat [] false = + .ok (.sort (.succ .zero)) := by + unfold TypeChecker.Inner.inferConstant + simp [tcContext, natInfo, + ConstantInfo.levelParams, ConstantInfo.isUnsafe, + ConstantInfo.instantiateTypeLevelParams, ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Level.substParams', + Bind.bind, Except.bind, Pure.pure, Except.pure] + +@[simp] theorem inferConstantZero (lctx) : + TypeChecker.Inner.inferConstant (tcContext lctx) ``Nat.zero [] false = + .ok (.const ``Nat []) := by + unfold TypeChecker.Inner.inferConstant + simp [tcContext, natZeroInfo, + ConstantInfo.levelParams, ConstantInfo.isUnsafe, + ConstantInfo.instantiateTypeLevelParams, ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Bind.bind, Except.bind, Pure.pure, Except.pure] + +@[simp] theorem inferConstantSucc (lctx) : + TypeChecker.Inner.inferConstant (tcContext lctx) ``Nat.succ [] false = + .ok (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) := by + unfold TypeChecker.Inner.inferConstant + simp [tcContext, natSuccInfo, + ConstantInfo.levelParams, ConstantInfo.isUnsafe, + ConstantInfo.instantiateTypeLevelParams, ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Bind.bind, Except.bind, Pure.pure, Except.pure] + +theorem selfDefEq (e : Expr) fuel context state : + TypeChecker.Inner.isDefEq e e (TypeChecker.Methods.withFuel fuel) + context state = .ok (true, state) := by + unfold TypeChecker.Inner.isDefEq + rw [if_pos (Expr.eqv_refl _)] + rfl + +@[simp] theorem constBeqFVar (name : Name) (levels : List Level) + (id : FVarId) : + ((.const name levels : Expr) == .fvar id) = false := by + change Expr.eqv (.const name levels) (.fvar id) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem sortBeqFVar (level : Level) (id : FVarId) : + ((.sort level : Expr) == .fvar id) = false := by + change Expr.eqv (.sort level) (.fvar id) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem fvarBeqConst (id : FVarId) (name : Name) + (levels : List Level) : + ((.fvar id : Expr) == .const name levels) = false := by + change Expr.eqv (.fvar id) (.const name levels) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem sortBeqApp (level : Level) (fn arg : Expr) : + ((.sort level : Expr) == .app fn arg) = false := by + change Expr.eqv (.sort level) (.app fn arg) = false + rw [Expr.eqv_eq] + rfl + +@[simp] theorem indexedVecConstBeqZero : + ((.const ``IndexedVec [.param `u] : Expr) == + .const ``Nat.zero []) = false := by + change Expr.eqv (.const ``IndexedVec [.param `u]) + (.const ``Nat.zero []) = false + rw [Expr.eqv_eq] + rfl + +theorem withLocalDeclEq + {α} (name : Name) (bi : BinderInfo) (ty : Expr) + (k : Expr → TypeChecker.RecM α) + (methods : TypeChecker.Methods) + (context : TypeChecker.Context) + (state : TypeChecker.State) : + (withLocalDecl (m := TypeChecker.RecM) name bi ty k) + methods context state = + k (.fvar ⟨state.ngen.curr⟩) methods + { context with lctx := + context.lctx.mkLocalDecl ⟨state.ngen.curr⟩ name ty bi } + { state with ngen := state.ngen.next } := rfl + +def nilRootSortState : TypeChecker.State := + { ({} : TypeChecker.State) with + inferTypeC := ({} : TypeChecker.State).inferTypeC.insert + (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u)))) } + +def nilAlphaId : FVarId := + ⟨nilRootSortState.ngen.curr⟩ + +def nilAlphaLctx : LocalContext := + ({} : LocalContext).mkLocalDecl nilAlphaId `α + (.sort (.succ (.param `u))) .implicit + +def nilBodyInitialState : TypeChecker.State := + { nilRootSortState with ngen := nilRootSortState.ngen.next } + +theorem nilAlphaFind : + nilAlphaLctx.find? nilAlphaId = + some (.cdecl 0 nilAlphaId `α + (.sort (.succ (.param `u))) .implicit .default) := by + have hfresh : ({} : LocalContext).find? nilAlphaId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := nilAlphaId) LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + nilAlphaId = none + rw [h] + simp [LocalContext.toList] + have hwf : nilAlphaLctx.WF := by + change (({} : LocalContext).mkLocalDecl nilAlphaId `α + (.sort (.succ (.param `u))) .implicit).WF + exact LocalContext.WF.mkLocalDecl LocalContext.WF.nil hfresh + rw [hwf.find?_eq_find?_toList] + simp only [nilAlphaLctx] + rw [LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + rw [show ({} : LocalContext).decls.size = 0 by rfl] + change + (if nilAlphaId == nilAlphaId then + some (LocalDecl.cdecl 0 nilAlphaId `α + (.sort (.succ (.param `u))) .implicit .default) + else none) = _ + rw [beq_self_eq_true] + rfl + +example : + TypeChecker.Inner.inferFVar (tcContext nilAlphaLctx) nilAlphaId = + .ok (.sort (.succ (.param `u))) := by + unfold TypeChecker.Inner.inferFVar + simp [tcContext, nilAlphaFind, LocalDecl.type, + Pure.pure, Except.pure] + +theorem inferTypeFamilyCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : state.inferTypeC[ + (.const ``IndexedVec [.param `u] : Expr)]? = none) : + TypeChecker.Inner.inferType' + (.const ``IndexedVec [.param `u]) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (indexedVecInfo.type, + { state with inferTypeC := + (state.inferTypeC.insert + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) }) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + inferConstantFamily, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +theorem inferTypeFVarCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (id : FVarId) (type : Expr) + (hcache : state.inferTypeC[(.fvar id : Expr)]? = none) + (hfind : lctx.find? id = some (.cdecl index id name type bi kind)) : + TypeChecker.Inner.inferType' (.fvar id) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (type, { state with inferTypeC := + (state.inferTypeC.insert (.fvar id) type) }) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + TypeChecker.Inner.inferFVar, tcContext, hfind, + LocalDecl.type, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +theorem inferTypeZeroCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : state.inferTypeC[(.const ``Nat.zero [] : Expr)]? = none) : + TypeChecker.Inner.inferType' (.const ``Nat.zero []) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.const ``Nat [], { state with inferTypeC := + (state.inferTypeC.insert (.const ``Nat.zero []) (.const ``Nat [])) }) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + inferConstantZero, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +theorem inferTypeNatCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : state.inferTypeC[(.const ``Nat [] : Expr)]? = none) : + TypeChecker.Inner.inferType' (.const ``Nat []) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.sort (.succ .zero), { state with inferTypeC := + (state.inferTypeC.insert (.const ``Nat []) + (.sort (.succ .zero))) }) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + inferConstantNat, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +theorem inferTypeSuccCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : state.inferTypeC[(.const ``Nat.succ [] : Expr)]? = none) : + TypeChecker.Inner.inferType' (.const ``Nat.succ []) false + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.forallE `n (.const ``Nat []) (.const ``Nat []) .default, + { state with inferTypeC := + (state.inferTypeC.insert (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) }) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + inferConstantSucc, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +@[simp] theorem ensureForallExact + (name : Name) (domain body : Expr) (bi : BinderInfo) + (source : Expr) (fuel : Nat) (context : TypeChecker.Context) + (state : TypeChecker.State) : + TypeChecker.Inner.ensureForallCore (.forallE name domain body bi) + source (TypeChecker.Methods.withFuel fuel) context state = + .ok (.forallE name domain body bi, state) := by + rfl + +theorem inferAppCoreOf + (fuel : Nat) (context : TypeChecker.Context) + (state stateFn stateArg : TypeChecker.State) + (fn arg domain body : Expr) (name : Name) (bi : BinderInfo) + (hclosed : (.app fn arg : Expr).hasLooseBVars = false) + (hcache : state.inferTypeC[(.app fn arg : Expr)]? = none) + (hfn : TypeChecker.Inner.inferType' fn false + (TypeChecker.Methods.withFuel fuel) context state = + .ok (.forallE name domain body bi, stateFn)) + (harg : TypeChecker.Inner.inferType' arg false + (TypeChecker.Methods.withFuel fuel) context stateFn = + .ok (domain, stateArg)) + (heager : arg.isAppOfArity ``eagerReduce 2 = false) : + TypeChecker.Inner.inferType' (.app fn arg) false + (TypeChecker.Methods.withFuel fuel) context state = + .ok (body.instantiate1 arg, + { stateArg with inferTypeC := + (stateArg.inferTypeC.insert + (.app fn arg) (body.instantiate1 arg)) }) := by + unfold TypeChecker.Inner.inferType' + simp [hclosed, hcache, hfn, harg, heager, selfDefEq, Expr.instantiate1_eq, Bind.bind, + ReaderT.bind, StateT.bind, Except.bind] + +theorem inferTypeForallCore + (fuel : Nat) (context : TypeChecker.Context) + (state finalState : TypeChecker.State) + (name : Name) (domain body result : Expr) (bi : BinderInfo) + (hclosed : (.forallE name domain body bi : Expr).hasLooseBVars = false) + (hcache : state.inferTypeC[(.forallE name domain body bi : Expr)]? = none) + (hforall : TypeChecker.Inner.inferForall + (.forallE name domain body bi) false + (TypeChecker.Methods.withFuel fuel) context state = + .ok (result, finalState)) : + TypeChecker.Inner.inferType' + (.forallE name domain body bi) false + (TypeChecker.Methods.withFuel fuel) context state = + .ok (result, { finalState with inferTypeC := + (finalState.inferTypeC.insert + (.forallE name domain body bi) result) }) := by + unfold TypeChecker.Inner.inferType' + simp [hclosed, hcache, hforall, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +def nilBodyExpr : Expr := + .app (.app (.const ``IndexedVec [.param `u]) (.fvar nilAlphaId)) + (.const ``Nat.zero []) + +def vecIndexName : Name := + indexedVecInfo.type.bindingBody!.bindingName! + +def vecFamilyTail : Expr := + .forallE vecIndexName (.const ``Nat []) + (.sort (.succ (.param `u))) .default + +theorem indexedVecInfoTypeShape : + indexedVecInfo.type = + .forallE `α (.sort (.succ (.param `u))) vecFamilyTail .default := by + rfl + +@[simp] theorem vecFamilyTailInstantiate (arg : Expr) : + vecFamilyTail.instantiate1 arg = vecFamilyTail := by + simp [vecFamilyTail, Expr.instantiate1_eq, Expr.instantiate1'] + +def nilFamilyState : TypeChecker.State := + { nilBodyInitialState with inferTypeC := + (nilBodyInitialState.inferTypeC.insert + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) } + +def nilAlphaState : TypeChecker.State := + { nilFamilyState with inferTypeC := + (nilFamilyState.inferTypeC.insert (.fvar nilAlphaId) + (.sort (.succ (.param `u)))) } + +def nilFirstApp : Expr := + .app (.const ``IndexedVec [.param `u]) (.fvar nilAlphaId) + +def nilFirstAppState : TypeChecker.State := + { nilAlphaState with inferTypeC := + (nilAlphaState.inferTypeC.insert nilFirstApp vecFamilyTail) } + +def nilZeroState : TypeChecker.State := + { nilFirstAppState with inferTypeC := + (nilFirstAppState.inferTypeC.insert (.const ``Nat.zero []) + (.const ``Nat [])) } + +theorem inferNilFamily : + TypeChecker.Inner.inferType' + (.const ``IndexedVec [.param `u]) false + (TypeChecker.Methods.withFuel 9998) + (tcContext nilAlphaLctx) nilBodyInitialState = + .ok (indexedVecInfo.type, nilFamilyState) := by + simpa [nilFamilyState] using + (inferTypeFamilyCore 9998 nilAlphaLctx nilBodyInitialState (by + simp [nilBodyInitialState, nilRootSortState])) + +theorem inferNilAlpha : + TypeChecker.Inner.inferType' (.fvar nilAlphaId) false + (TypeChecker.Methods.withFuel 9998) + (tcContext nilAlphaLctx) nilFamilyState = + .ok (.sort (.succ (.param `u)), nilAlphaState) := by + simpa [nilAlphaState] using + (inferTypeFVarCore 9998 nilAlphaLctx nilFamilyState nilAlphaId + (.sort (.succ (.param `u))) (index := 0) (name := `α) + (bi := .implicit) (kind := .default) (by + simp [nilFamilyState, nilBodyInitialState, nilRootSortState]) nilAlphaFind) + +theorem inferNilFirstApp : + TypeChecker.Inner.inferType' nilFirstApp false + (TypeChecker.Methods.withFuel 9998) + (tcContext nilAlphaLctx) nilBodyInitialState = + .ok (vecFamilyTail, nilFirstAppState) := by + have h := inferAppCoreOf 9998 (tcContext nilAlphaLctx) + nilBodyInitialState nilFamilyState nilAlphaState + (.const ``IndexedVec [.param `u]) (.fvar nilAlphaId) + (.sort (.succ (.param `u))) vecFamilyTail `α .default + (by + simp [Expr.hasLooseBVars, Expr.looseBVarRange']) + (by + simp [nilBodyInitialState, nilRootSortState]) + (by simpa [indexedVecInfoTypeShape] using inferNilFamily) + inferNilAlpha (by rfl) + simpa [nilFirstApp, nilFirstAppState, vecFamilyTail, + Expr.instantiate1'] using h + +theorem inferNilZero : + TypeChecker.Inner.inferType' (.const ``Nat.zero []) false + (TypeChecker.Methods.withFuel 9998) + (tcContext nilAlphaLctx) nilFirstAppState = + .ok (.const ``Nat [], nilZeroState) := by + simpa [nilZeroState] using + (inferTypeZeroCore 9998 nilAlphaLctx nilFirstAppState (by + simp [nilFirstAppState, nilAlphaState, nilFamilyState, nilBodyInitialState, nilRootSortState, + nilFirstApp])) + +theorem inferNilBodyExists : ∃ finalState, + TypeChecker.Inner.inferType nilBodyExpr false + (TypeChecker.Methods.withFuel 9999) + (tcContext nilAlphaLctx) nilBodyInitialState = + .ok (.sort (.succ (.param `u)), finalState) := by + refine ⟨{ nilZeroState with inferTypeC := + (nilZeroState.inferTypeC.insert nilBodyExpr + (.sort (.succ (.param `u)))) }, ?_⟩ + change TypeChecker.Inner.inferType' nilBodyExpr false + (TypeChecker.Methods.withFuel 9998) + (tcContext nilAlphaLctx) nilBodyInitialState = _ + have h := inferAppCoreOf 9998 (tcContext nilAlphaLctx) + nilBodyInitialState nilFirstAppState nilZeroState + nilFirstApp (.const ``Nat.zero []) (.const ``Nat []) + (.sort (.succ (.param `u))) vecIndexName .default + (by simp [nilFirstApp, Expr.hasLooseBVars, Expr.looseBVarRange']) + (by simp [nilBodyInitialState, nilRootSortState]) + (by simpa [vecFamilyTail] using inferNilFirstApp) + inferNilZero (by rfl) + simpa [nilBodyExpr, nilFirstApp, + Expr.instantiate1_eq, Expr.instantiate1'] using h + +theorem nilOuterWithLocalDecl + {α} (k : Expr → TypeChecker.RecM α) + (methods : TypeChecker.Methods) : + (withLocalDecl (m := TypeChecker.RecM) `α .implicit + (.sort (.succ (.param `u))) k) + methods (tcContext ({} : LocalContext)) nilRootSortState = + k (.fvar nilAlphaId) methods (tcContext nilAlphaLctx) + nilBodyInitialState := by + simpa [nilAlphaId, nilAlphaLctx, nilBodyInitialState, tcContext] using + (withLocalDeclEq `α .implicit (.sort (.succ (.param `u))) k methods + (tcContext ({} : LocalContext)) nilRootSortState) + +@[simp] theorem ensureSortExact + (level : Level) (source : Expr) (fuel : Nat) + (context : TypeChecker.Context) (state : TypeChecker.State) : + TypeChecker.Inner.ensureSortCore (.sort level) source + (TypeChecker.Methods.withFuel fuel) context state = + .ok (.sort level, state) := by + rfl + +theorem nilRootSortCore : + TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ (.param `u))), nilRootSortState) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + nilRootSortState, checkLevelSuccParam, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +def nilCtorBodyRaw : Expr := + .app (.app (.const ``IndexedVec [.param `u]) (.bvar 0)) + (.const ``Nat.zero []) + +def nilCtorTypeRaw : Expr := + .forallE `α (.sort (.succ (.param `u))) nilCtorBodyRaw .implicit + +def nilCtorInferredLevel : Level := + mkLevelIMax' (.succ (.succ (.param `u))) (.succ (.param `u)) + +theorem nilInfoTypeShape : indexedVecNilInfo.type = nilCtorTypeRaw := by + rfl + +theorem nilRootInferForallExists : ∃ finalState, + TypeChecker.Inner.inferForall nilCtorTypeRaw false + (TypeChecker.Methods.withFuel 9999) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = + .ok (.sort nilCtorInferredLevel, finalState) := by + obtain ⟨finalState, hbody⟩ := inferNilBodyExists + refine ⟨finalState, ?_⟩ + unfold TypeChecker.Inner.inferForall + simp only [TypeChecker.Inner.inferForall.loop, nilCtorTypeRaw] + rw [show + (.sort (.succ (.param `u)) : Expr).instantiateRev #[] = + .sort (.succ (.param `u)) by + simp [Expr.instantiateRev_eq, Expr.instantiate_eq]] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show TypeChecker.Inner.inferType + (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 9999) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = + TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 9998) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) by rfl] + rw [nilRootSortCore] + simp only + rw [ensureSortExact] + simp only + rw [nilOuterWithLocalDecl] + simp only [TypeChecker.Inner.inferForall.loop, nilCtorBodyRaw] + rw [show + (((.const ``IndexedVec [.param `u] : Expr).app (.bvar 0)).app + (.const ``Nat.zero [])).instantiateRev + (#[] |>.push (.fvar nilAlphaId)) = nilBodyExpr by + simp [nilBodyExpr, nilAlphaId, Expr.instantiateRev_eq, Expr.instantiate_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero]] + simp only [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hbody] + simp only + rw [ensureSortExact] + simp [nilCtorInferredLevel, Expr.sortLevel!, Pure.pure, ReaderT.pure, + StateT.pure, Except.pure] + +theorem inferNilRootExists : ∃ finalState, + TypeChecker.Inner.inferType indexedVecNilInfo.type false + (TypeChecker.Methods.withFuel 10000) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = + .ok (.sort nilCtorInferredLevel, finalState) := by + obtain ⟨state, hforall⟩ := nilRootInferForallExists + refine ⟨{ state with inferTypeC := + (state.inferTypeC.insert indexedVecNilInfo.type + (.sort nilCtorInferredLevel)) }, ?_⟩ + change TypeChecker.Inner.inferType' indexedVecNilInfo.type false + (TypeChecker.Methods.withFuel 9999) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = _ + rw [nilInfoTypeShape] + exact inferTypeForallCore 9999 (tcContext ({} : LocalContext)) + ({} : TypeChecker.State) state `α + (.sort (.succ (.param `u))) nilCtorBodyRaw + (.sort nilCtorInferredLevel) .implicit + (by simp [nilCtorBodyRaw, Expr.hasLooseBVars, + Expr.looseBVarRange']) + (by simp) hforall + +theorem nilRootCheckTypeM : + TypeChecker.M.run ctorEnv .safe {} [`u] {} + (TypeChecker.checkType indexedVecNilInfo.type) = + .ok (.sort nilCtorInferredLevel) := by + obtain ⟨finalState, hroot⟩ := inferNilRootExists + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType indexedVecNilInfo.type false + (TypeChecker.Methods.withFuel 10000) + (tcContext {}) ({} : TypeChecker.State)) = _ + rw [hroot] + rfl + +def nilCandidateContext : AddInductive.Context := ctorContext + +def nilCandidateBodyContext : AddInductive.Context := + nilCandidateContext.pushLocalDecl `α .implicit + (.sort (.succ (.param `u))) + +def nilCandidateBody : Expr := + nilCtorBodyRaw.instantiate1 nilCandidateContext.freshExpr + +theorem nilStandaloneSortCore : + TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 9999) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ (.param `u))), nilRootSortState) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + nilRootSortState, checkLevelSuccParam, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +theorem nilRootWhnfM : + TypeChecker.M.run nilCandidateContext.env nilCandidateContext.safety + nilCandidateContext.lctx nilCandidateContext.lparams + nilCandidateContext.fuel + (TypeChecker.whnf indexedVecNilInfo.type) = + .ok indexedVecNilInfo.type := by + rfl + +theorem nilDomainCheckTypeM : + TypeChecker.M.run nilCandidateContext.env nilCandidateContext.safety + nilCandidateContext.lctx nilCandidateContext.lparams + nilCandidateContext.fuel + (TypeChecker.checkType (.sort (.succ (.param `u)))) = + .ok (.sort (.succ (.succ (.param `u)))) := by + obtain ⟨finalState, hroot⟩ := + show ∃ finalState, + TypeChecker.Inner.inferType (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 10000) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ (.param `u))), finalState) by + refine ⟨nilRootSortState, ?_⟩ + change TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 9999) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State) = _ + exact nilStandaloneSortCore + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 10000) + (tcContext ({} : LocalContext)) ({} : TypeChecker.State)) = _ + rw [hroot] + rfl + +theorem nilDomainWhnfM : + TypeChecker.M.run nilCandidateContext.env nilCandidateContext.safety + nilCandidateContext.lctx nilCandidateContext.lparams + nilCandidateContext.fuel + (TypeChecker.whnf (.sort (.succ (.param `u)))) = + .ok (.sort (.succ (.param `u))) := by + rfl + +def nilCandidateAlphaId : FVarId := + nilCandidateContext.freshFVarId + +def nilCandidateAlphaLctx : LocalContext := + ({} : LocalContext).mkLocalDecl nilCandidateAlphaId `α + (.sort (.succ (.param `u))) .implicit + +theorem nilCandidateFresh : + ({} : LocalContext).find? nilCandidateAlphaId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := nilCandidateAlphaId) LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + nilCandidateAlphaId = none + rw [h] + simp [LocalContext.toList] + +theorem nilCandidateAlphaFind : + nilCandidateAlphaLctx.find? nilCandidateAlphaId = + some (.cdecl 0 nilCandidateAlphaId `α + (.sort (.succ (.param `u))) .implicit .default) := by + have hwf : nilCandidateAlphaLctx.WF := by + change (({} : LocalContext).mkLocalDecl nilCandidateAlphaId `α + (.sort (.succ (.param `u))) .implicit).WF + exact LocalContext.WF.mkLocalDecl LocalContext.WF.nil + nilCandidateFresh + rw [hwf.find?_eq_find?_toList] + simp only [nilCandidateAlphaLctx] + rw [LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + rw [show ({} : LocalContext).decls.size = 0 by rfl] + change + (if nilCandidateAlphaId == nilCandidateAlphaId then + some (LocalDecl.cdecl 0 nilCandidateAlphaId `α + (.sort (.succ (.param `u))) .implicit .default) + else none) = _ + rw [beq_self_eq_true] + rfl + +def nilCandidateFirstApp : Expr := + .app (.const ``IndexedVec [.param `u]) (.fvar nilCandidateAlphaId) + +def nilCandidateBodyExpr : Expr := + .app nilCandidateFirstApp (.const ``Nat.zero []) + +theorem nilCandidateBodyShape : + nilCandidateBody = nilCandidateBodyExpr := by + simp [nilCandidateBody, nilCtorBodyRaw, nilCandidateBodyExpr, + nilCandidateFirstApp, nilCandidateAlphaId, + AddInductive.Context.freshExpr, + Expr.instantiate1_eq, Expr.instantiate1'] + +def nilCandidateFamilyState : TypeChecker.State := + { ({} : TypeChecker.State) with inferTypeC := + (({} : TypeChecker.State).inferTypeC.insert + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) } + +def nilCandidateAlphaState : TypeChecker.State := + { nilCandidateFamilyState with inferTypeC := + (nilCandidateFamilyState.inferTypeC.insert + (.fvar nilCandidateAlphaId) (.sort (.succ (.param `u)))) } + +def nilCandidateFirstAppState : TypeChecker.State := + { nilCandidateAlphaState with inferTypeC := + (nilCandidateAlphaState.inferTypeC.insert + nilCandidateFirstApp vecFamilyTail) } + +def nilCandidateZeroState : TypeChecker.State := + { nilCandidateFirstAppState with inferTypeC := + (nilCandidateFirstAppState.inferTypeC.insert + (.const ``Nat.zero []) (.const ``Nat [])) } + +theorem inferNilCandidateFamily : + TypeChecker.Inner.inferType' + (.const ``IndexedVec [.param `u]) false + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = + .ok (indexedVecInfo.type, nilCandidateFamilyState) := by + simpa [nilCandidateFamilyState] using + (inferTypeFamilyCore 9999 nilCandidateAlphaLctx + ({} : TypeChecker.State) (by simp)) + +theorem inferNilCandidateAlpha : + TypeChecker.Inner.inferType' (.fvar nilCandidateAlphaId) false + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) nilCandidateFamilyState = + .ok (.sort (.succ (.param `u)), nilCandidateAlphaState) := by + simpa [nilCandidateAlphaState] using + (inferTypeFVarCore 9999 nilCandidateAlphaLctx + nilCandidateFamilyState nilCandidateAlphaId + (.sort (.succ (.param `u))) + (by simp [nilCandidateFamilyState]) nilCandidateAlphaFind) + +theorem inferNilCandidateFirstApp : + TypeChecker.Inner.inferType' nilCandidateFirstApp false + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = + .ok (vecFamilyTail, nilCandidateFirstAppState) := by + have h := inferAppCoreOf 9999 (tcContext nilCandidateAlphaLctx) + ({} : TypeChecker.State) nilCandidateFamilyState + nilCandidateAlphaState (.const ``IndexedVec [.param `u]) + (.fvar nilCandidateAlphaId) (.sort (.succ (.param `u))) + vecFamilyTail `α .default + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) + (by simp) inferNilCandidateFamily + (by simpa [indexedVecInfoTypeShape] using inferNilCandidateAlpha) + (by rfl) + simpa [nilCandidateFirstApp, nilCandidateFirstAppState, + indexedVecInfoTypeShape, vecFamilyTail, + Expr.instantiate1'] using h + +theorem inferNilCandidateZero : + TypeChecker.Inner.inferType' (.const ``Nat.zero []) false + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) nilCandidateFirstAppState = + .ok (.const ``Nat [], nilCandidateZeroState) := by + simpa [nilCandidateZeroState] using + (inferTypeZeroCore 9999 nilCandidateAlphaLctx + nilCandidateFirstAppState (by + simp [nilCandidateFirstAppState, nilCandidateAlphaState, nilCandidateFamilyState, + nilCandidateFirstApp])) + +theorem inferNilCandidateBodyExists : ∃ finalState, + TypeChecker.Inner.inferType nilCandidateBody false + (TypeChecker.Methods.withFuel 10000) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), finalState) := by + refine ⟨{ nilCandidateZeroState with inferTypeC := + (nilCandidateZeroState.inferTypeC.insert nilCandidateBodyExpr + (.sort (.succ (.param `u)))) }, ?_⟩ + change TypeChecker.Inner.inferType' nilCandidateBody false + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = _ + rw [nilCandidateBodyShape] + have h := inferAppCoreOf 9999 (tcContext nilCandidateAlphaLctx) + ({} : TypeChecker.State) nilCandidateFirstAppState + nilCandidateZeroState nilCandidateFirstApp (.const ``Nat.zero []) + (.const ``Nat []) (.sort (.succ (.param `u))) vecIndexName .default + (by simp [nilCandidateFirstApp, Expr.hasLooseBVars, Expr.looseBVarRange']) + (by simp) inferNilCandidateFirstApp + inferNilCandidateZero (by rfl) + simpa [nilCandidateBodyExpr, nilCandidateFirstApp, + Expr.instantiate1_eq, Expr.instantiate1'] using h + +theorem nilCandidateBodyCheckTypeM : + TypeChecker.M.run nilCandidateBodyContext.env + nilCandidateBodyContext.safety nilCandidateBodyContext.lctx + nilCandidateBodyContext.lparams nilCandidateBodyContext.fuel + (TypeChecker.checkType nilCandidateBody) = + .ok (.sort (.succ (.param `u))) := by + obtain ⟨finalState, hbody⟩ := inferNilCandidateBodyExists + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType nilCandidateBody false + (TypeChecker.Methods.withFuel 10000) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State)) = _ + rw [hbody] + rfl + +theorem nilCandidateBodyGetAppFn : + nilCandidateBody.getAppFn = + .const ``IndexedVec [.param `u] := by + rw [nilCandidateBodyShape] + rfl + +theorem nilRecMBind + {α β} (x : TypeChecker.RecM α) + (f : α → TypeChecker.RecM β) (methods context state) : + (x >>= f) methods context state = + match x methods context state with + | .error e => .error e + | .ok (a, state') => f a methods context state' := by + simp [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + cases h : x methods context state with + | error => rfl + | ok value => cases value; rfl + +@[simp] theorem nilRecMGetEnv (methods context state) : + (liftM TypeChecker.getEnv : + TypeChecker.RecM Kernel.Environment) methods context state = + .ok (context.env, state) := rfl + +@[simp] theorem nilRecMGet (methods context state) : + (get : TypeChecker.RecM TypeChecker.State) + methods context state = .ok (state, state) := rfl + +@[simp] theorem nilRecMPure + {α} (a : α) (methods context state) : + (pure a : TypeChecker.RecM α) methods context state = + .ok (a, state) := rfl + +theorem nilCandidateInductiveReduceRec + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + inductiveReduceRec ctorEnv nilCandidateBody + (fun e => TypeChecker.Inner.whnf e) + (fun e => TypeChecker.Inner.inferType e) + TypeChecker.Inner.isDefEq + TypeChecker.Inner.isNeverProp + methods (tcContext nilCandidateAlphaLctx) state = + .ok (none, state) := by + unfold inductiveReduceRec + rw [nilCandidateBodyGetAppFn] + simp only + rw [type_lookup_family] + rfl + +theorem nilCandidateReduceRecursor + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + TypeChecker.Inner.reduceRecursor nilCandidateBody + methods (tcContext nilCandidateAlphaLctx) state = + .ok (none, state) := by + unfold TypeChecker.Inner.reduceRecursor + have hquot : ctorEnv.quotInit = false := by rfl + simp only [nilRecMBind, nilRecMGetEnv] + rw [show (tcContext nilCandidateAlphaLctx).env = ctorEnv by rfl] + rw [hquot] + simp only [Bool.false_eq_true, if_false, nilRecMBind] + rw [nilCandidateInductiveReduceRec methods state] + rfl + +@[simp] theorem nilCandidateWhnfCoreFamily (n state) : + TypeChecker.Inner.whnfCore + (.const ``IndexedVec [.param `u]) false + (TypeChecker.Methods.withFuel (n + 1)) + (tcContext nilCandidateAlphaLctx) state = + .ok (.const ``IndexedVec [.param `u], state) := by + rfl + +theorem nilCandidateWhnfCoreInitial (n : Nat) : + TypeChecker.Inner.whnfCore' nilCandidateBody false + (TypeChecker.Methods.withFuel (n + 1)) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = + .ok (nilCandidateBody, ({} : TypeChecker.State)) := by + rw [nilCandidateBodyShape] + change TypeChecker.Inner.whnfCore' + (.app (.app (.const ``IndexedVec [.param `u]) + (.fvar nilCandidateAlphaId)) (.const ``Nat.zero [])) + false (TypeChecker.Methods.withFuel (n + 1)) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = _ + unfold TypeChecker.Inner.whnfCore' + simp only [nilRecMBind, nilRecMGet, Std.HashMap.getElem?_empty] + rw [Expr.withRevApp_eq] + simp only [nilRecMBind] + rw [show + (Expr.app + (Expr.app (Expr.const ``IndexedVec [.param `u]) + (Expr.fvar nilCandidateAlphaId)) + (Expr.const ``Nat.zero [])).getAppFn = + (Expr.const ``IndexedVec [.param `u]) by rfl] + rw [nilCandidateWhnfCoreFamily n ({} : TypeChecker.State)] + simp [nilCandidateBodyExpr, nilCandidateFirstApp, Expr.structuralEq, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rw [show + .app (.app (.const ``IndexedVec [.param `u]) + (.fvar nilCandidateAlphaId)) (.const ``Nat.zero []) = + nilCandidateBody by + symm; exact nilCandidateBodyShape] + rw [nilCandidateReduceRecursor] + rfl + +@[simp] theorem nilCandidateReduceNative + (env : Kernel.Environment) (methods : TypeChecker.Methods) + (state : TypeChecker.State) : + (liftM (TypeChecker.Inner.reduceNative env nilCandidateBody) : + TypeChecker.RecM (Option Expr)) + methods (tcContext nilCandidateAlphaLctx) state = + .ok (none, state) := by + rw [nilCandidateBodyShape] + simp [TypeChecker.Inner.reduceNative, nilCandidateBodyExpr, + nilCandidateFirstApp, Expr.structuralEq] + +@[simp] theorem nilCandidateReduceNat + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + TypeChecker.Inner.reduceNat nilCandidateBody + methods (tcContext nilCandidateAlphaLctx) state = + .ok (none, state) := by + rw [nilCandidateBodyShape] + simp [TypeChecker.Inner.reduceNat, nilCandidateBodyExpr, nilCandidateFirstApp, + Expr.getAppNumArgs_eq, Expr.getAppArgsRevList] + +theorem nilCandidateIsDeltaFamily : + TypeChecker.Inner.isDelta ctorEnv + (.const ``IndexedVec [.param `u]) = none := by + unfold TypeChecker.Inner.isDelta + rw [show + (Expr.const ``IndexedVec [.param `u]).getAppFn = + Expr.const ``IndexedVec [.param `u] by rfl] + simp only + rw [type_lookup_family] + simp [indexedVecInfo, ConstantInfo.deltaValue?] + +theorem nilCandidateUnfoldFamily + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + TypeChecker.Inner.unfoldDefinitionCore + (.const ``IndexedVec [.param `u]) + methods (tcContext nilCandidateAlphaLctx) state = + .ok (none, state) := by + unfold TypeChecker.Inner.unfoldDefinitionCore + simp only [nilRecMBind, nilRecMGetEnv] + rw [show (tcContext nilCandidateAlphaLctx).env = ctorEnv by rfl] + rw [nilCandidateIsDeltaFamily] + rfl + +theorem nilCandidateUnfoldBody + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + TypeChecker.Inner.unfoldDefinition nilCandidateBody + methods (tcContext nilCandidateAlphaLctx) state = + .ok (none, state) := by + unfold TypeChecker.Inner.unfoldDefinition + rw [show nilCandidateBody.isApp = true by + rw [nilCandidateBodyShape] + rfl] + simp only [if_true] + rw [nilCandidateBodyGetAppFn] + simp only [nilRecMBind] + rw [nilCandidateUnfoldFamily] + rfl + +theorem nilCandidateWhnfLoop : + TypeChecker.Inner.whnf'.loop nilCandidateBody 100000 + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = + .ok (nilCandidateBody, ({} : TypeChecker.State)) := by + rw [show 100000 = 99999 + 1 by rfl] + unfold TypeChecker.Inner.whnf'.loop + rw [show 9999 = 9998 + 1 by rfl] + simp only [nilRecMBind, nilRecMGetEnv] + rw [nilCandidateWhnfCoreInitial 9998] + simp only [] + rw [nilCandidateReduceNative] + simp only [nilRecMBind] + rw [nilCandidateReduceNat] + simp only [nilRecMBind] + rw [nilCandidateUnfoldBody] + rfl + +theorem nilCandidateBodyWhnfM : + TypeChecker.M.run nilCandidateBodyContext.env + nilCandidateBodyContext.safety nilCandidateBodyContext.lctx + nilCandidateBodyContext.lparams nilCandidateBodyContext.fuel + (TypeChecker.whnf nilCandidateBody) = .ok nilCandidateBody := by + rw [nilCandidateBodyShape] + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' + (.app (.app (.const ``IndexedVec [.param `u]) + (.fvar nilCandidateAlphaId)) (.const ``Nat.zero [])) + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State)) = + .ok (.app (.app (.const ``IndexedVec [.param `u]) + (.fvar nilCandidateAlphaId)) (.const ``Nat.zero [])) + unfold TypeChecker.Inner.whnf' + simp + rw [show + (if (tcContext nilCandidateAlphaLctx).eagerReduce then + (tcContext nilCandidateAlphaLctx).fuel.whnfEager + else (tcContext nilCandidateAlphaLctx).fuel.whnf) = 100000 by rfl] + rw [show + TypeChecker.Inner.whnf'.loop + (.app (.app (.const ``IndexedVec [.param `u]) + (.fvar nilCandidateAlphaId)) (.const ``Nat.zero [])) 100000 + (TypeChecker.Methods.withFuel 9999) + (tcContext nilCandidateAlphaLctx) ({} : TypeChecker.State) = + .ok (.app (.app (.const ``IndexedVec [.param `u]) + (.fvar nilCandidateAlphaId)) (.const ``Nat.zero []), + ({} : TypeChecker.State)) by + simpa [nilCandidateBodyShape, nilCandidateBodyExpr, + nilCandidateFirstApp] using nilCandidateWhnfLoop] + simp [Functor.map, StateT.map, Except.map] + +def nilDomainAnnotations : + AddInductive.CandidateTypeAnnotations + (.sort (.succ (.param `u))) where + consumed := .sort (.succ (.param `u)) + trace := .identity _ + +theorem nilDomainAnnotationTraceBuild : + AddInductive.CandidateTypeAnnotationTrace.build + (.sort (.succ (.param `u))) = + ⟨.sort (.succ (.param `u)), .identity _⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build] + +theorem nilDomainAnnotationsBuild : + AddInductive.buildCandidateTypeAnnotations + (.sort (.succ (.param `u))) = .ok nilDomainAnnotations := by + unfold AddInductive.buildCandidateTypeAnnotations + rw [nilDomainAnnotationTraceBuild] + rfl + +theorem nilDomainAnnotationsEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨nilCandidateContext, (.sort (.succ (.param `u))), + nilDomainAnnotations.consumed⟩ := by + simpa [nilDomainAnnotations] using + (candidateIsDefEqSelfValid nilCandidateContext + (.sort (.succ (.param `u))) 9999 rfl) + +theorem nilCandidateContextFresh : + nilCandidateContext.lctx.find? + nilCandidateContext.freshFVarId = none := by + change ({} : LocalContext).find? nilCandidateAlphaId = none + exact nilCandidateFresh + +theorem nilRootCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨nilCandidateContext, indexedVecNilInfo.type, + .sort nilCtorInferredLevel⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid, + nilCandidateContext, ctorContext] using nilRootCheckTypeM + +theorem nilRootWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨nilCandidateContext, indexedVecNilInfo.type, + indexedVecNilInfo.type⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid, + nilCandidateContext, ctorContext] using nilRootWhnfM + +theorem nilDomainCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨nilCandidateContext, (.sort (.succ (.param `u))), + .sort (.succ (.succ (.param `u)))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid] using + nilDomainCheckTypeM + +theorem nilDomainWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨nilCandidateContext, (.sort (.succ (.param `u))), + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid] using nilDomainWhnfM + +theorem nilBodyCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨nilCandidateBodyContext, nilCandidateBody, + .sort (.succ (.param `u))⟩ := by + simpa [AddInductive.CandidateCheckTypeStep.Valid] using + nilCandidateBodyCheckTypeM + +theorem nilBodyWhnfValid : + AddInductive.CandidateWhnfStep.Valid + ⟨nilCandidateBodyContext, nilCandidateBody, + nilCandidateBody⟩ := by + simpa [AddInductive.CandidateWhnfStep.Valid] using + nilCandidateBodyWhnfM + +def nilDomainCandidateTrace : + AddInductive.CandidateExprTrace nilCandidateContext + (.sort (.succ (.param `u))) := + .terminal nilCandidateContext (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u)))) + (.sort (.succ (.param `u))) + nilDomainCheckValid nilDomainWhnfValid + +def nilBodyCandidateTrace : + AddInductive.CandidateExprTrace nilCandidateBodyContext + (nilCtorBodyRaw.instantiate1 nilCandidateContext.freshExpr) := + .terminal nilCandidateBodyContext + (nilCtorBodyRaw.instantiate1 nilCandidateContext.freshExpr) + (.sort (.succ (.param `u))) nilCandidateBody + (by simpa [nilCandidateBody] using nilBodyCheckValid) + (by simpa [nilCandidateBody] using nilBodyWhnfValid) + +def nilCandidateTrace : + AddInductive.CandidateExprTrace nilCandidateContext + indexedVecNilInfo.type := + .forallE nilCandidateContext indexedVecNilInfo.type + (.sort nilCtorInferredLevel) `α + (.sort (.succ (.param `u))) nilCtorBodyRaw .implicit + nilCandidateContextFresh nilDomainAnnotations + nilDomainAnnotationsEq nilRootCheckValid + (by simpa [nilInfoTypeShape, nilCtorTypeRaw] using nilRootWhnfValid) + nilDomainCandidateTrace nilBodyCandidateTrace + +def nilCandidate : AddInductive.CandidateExpr indexedVecNilInfo.type := + ⟨nilCandidateContext, nilCandidateTrace⟩ + +theorem nilCandidate_view_eq : + nilCandidate.view = indexedVecNilInfo.type := by + have habstract (context : AddInductive.Context) (e : Expr) : + e.abstract #[context.freshExpr] = + Expr.abstract1 context.freshFVarId e := by + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl] + simp only [Expr.abstract_eq, Expr.abstractList] + simp only [nilCandidate, AddInductive.CandidateExpr.view, + nilCandidateTrace, nilDomainCandidateTrace, nilBodyCandidateTrace, + AddInductive.CandidateExprTrace.view] + rw [habstract] + rw [nilInfoTypeShape] + simp [nilCandidateBody, nilCtorTypeRaw, nilCtorBodyRaw, + Expr.instantiate1_eq, Expr.instantiate1', Expr.abstract1, + nilCandidateContext, ctorContext, + AddInductive.Context.freshExpr, + AddInductive.Context.freshFVarId, + NameGenerator.curr] + +/-- The retained `nil` candidate is identity-normalizing at its root, domain, +and instantiated result. -/ +theorem nilCandidate_identity : + TypeChecker.CandidateExprIdentity nilCandidate.trace := by + change TypeChecker.CandidateExprIdentity nilCandidateTrace + unfold nilCandidateTrace + refine .forallE (name := `α) (binderInfo := .implicit) + (body := nilCtorBodyRaw) (annotations := nilDomainAnnotations) + nilDomainCandidateTrace nilBodyCandidateTrace + (by simpa [nilCtorTypeRaw] using nilInfoTypeShape) + rfl (.terminal rfl) (.terminal (by rfl)) + +theorem nilDomainCandidateTraceLoop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop nilCandidateContext + (.sort (.succ (.param `u))) (fuel + 1) = + .ok nilDomainCandidateTrace := by + simpa only [nilDomainCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + nilCandidateContext (.sort (.succ (.param `u))) + (.sort (.succ (.succ (.param `u)))) + (.sort (.succ (.param `u))) fuel + nilDomainCheckValid nilDomainWhnfValid rfl + +theorem nilBodyCandidateTraceLoop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop nilCandidateBodyContext + (nilCtorBodyRaw.instantiate1 nilCandidateContext.freshExpr) + (fuel + 1) = .ok nilBodyCandidateTrace := by + simpa only [nilBodyCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + nilCandidateBodyContext + (nilCtorBodyRaw.instantiate1 nilCandidateContext.freshExpr) + (.sort (.succ (.param `u))) nilCandidateBody fuel + (by simpa [nilCandidateBody] using nilBodyCheckValid) + (by simpa [nilCandidateBody] using nilBodyWhnfValid) + (by rw [nilCandidateBodyShape]; rfl) + +theorem nilCandidateTraceLoop : + AddInductive.buildCandidateExpr.loop nilCandidateContext + indexedVecNilInfo.type nilCandidateContext.fuel.inductiveFuel = + .ok nilCandidateTrace := by + change AddInductive.buildCandidateExpr.loop nilCandidateContext + indexedVecNilInfo.type (999 + 1) = _ + simpa only [nilCandidateTrace, nilCandidateBodyContext] using + (AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := nilCandidateContext) + (e := indexedVecNilInfo.type) + (inferred := .sort nilCtorInferredLevel) + (fuel := 999) (name := `α) + (domain := .sort (.succ (.param `u))) + (body := nilCtorBodyRaw) (binderInfo := .implicit) + (hfresh := nilCandidateContextFresh) + (annotations := nilDomainAnnotations) + (hannotations := nilDomainAnnotationsBuild) + (hannotationsEq := nilDomainAnnotationsEq) + (hcheck := nilRootCheckValid) + (hrun := by + simpa [nilInfoTypeShape, nilCtorTypeRaw] using nilRootWhnfValid) + (domainCandidate := nilDomainCandidateTrace) + (bodyCandidate := nilBodyCandidateTrace) + (hdomain := by + simpa using nilDomainCandidateTraceLoop 998) + (hbody := by + simpa [nilCandidateBodyContext, nilDomainAnnotations] using + nilBodyCandidateTraceLoop 998)) + +theorem nilCandidateProduced : + AddInductive.buildCandidateExpr indexedVecNilInfo.type + nilCandidateContext = .ok nilCandidate := by + unfold AddInductive.buildCandidateExpr + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + rw [nilCandidateTraceLoop] + rfl + +/-! ## `IndexedVec.cons` source and candidate contexts -/ + +def consAlphaName : Name := + indexedVecConsInfo.type.bindingName! + +def consNName : Name := + indexedVecConsInfo.type.bindingBody!.bindingName! + +def consHeadName : Name := + indexedVecConsInfo.type.bindingBody!.bindingBody!.bindingName! + +def consTailName : Name := + indexedVecConsInfo.type.bindingBody!.bindingBody!.bindingBody!.bindingName! + +def consTerminalRaw : Expr := + .app (.app (.const ``IndexedVec [.param `u]) (.bvar 3)) + (.app (.const ``Nat.succ []) (.bvar 2)) + +def consTailTypeRaw : Expr := + .forallE consTailName + (.app (.app (.const ``IndexedVec [.param `u]) (.bvar 2)) (.bvar 1)) + consTerminalRaw .default + +def consHeadTypeRaw : Expr := + .forallE consHeadName (.bvar 1) consTailTypeRaw .default + +def consNTypeRaw : Expr := + .forallE consNName (.const ``Nat []) consHeadTypeRaw .implicit + +def consCtorTypeRaw : Expr := + .forallE consAlphaName (.sort (.succ (.param `u))) + consNTypeRaw .implicit + +theorem consInfoTypeShape : + indexedVecConsInfo.type = consCtorTypeRaw := by + rfl + +def consRootContext : AddInductive.Context := ctorContext + +def consAlphaId : FVarId := consRootContext.freshFVarId + +def consAlphaExpr : Expr := consRootContext.freshExpr + +def consAlphaContext : AddInductive.Context := + consRootContext.pushLocalDecl consAlphaName .implicit + (.sort (.succ (.param `u))) + +def consNId : FVarId := consAlphaContext.freshFVarId + +def consNExpr : Expr := consAlphaContext.freshExpr + +def consNContext : AddInductive.Context := + consAlphaContext.pushLocalDecl consNName .implicit (.const ``Nat []) + +def consHeadId : FVarId := consNContext.freshFVarId + +def consHeadExpr : Expr := consNContext.freshExpr + +def consAfterAlpha : Expr := + .forallE consNName (.const ``Nat []) + (.forallE consHeadName consAlphaExpr + (.forallE consTailName + (.app (.app (.const ``IndexedVec [.param `u]) consAlphaExpr) + (.bvar 1)) + (.app (.app (.const ``IndexedVec [.param `u]) consAlphaExpr) + (.app (.const ``Nat.succ []) (.bvar 2))) + .default) + .default) + .implicit + +def consAfterN : Expr := + .forallE consHeadName consAlphaExpr + (.forallE consTailName + (.app (.app (.const ``IndexedVec [.param `u]) consAlphaExpr) + consNExpr) + (.app (.app (.const ``IndexedVec [.param `u]) consAlphaExpr) + (.app (.const ``Nat.succ []) consNExpr)) + .default) + .default + +def consHeadContext : AddInductive.Context := + consNContext.pushLocalDecl consHeadName .default consAlphaExpr + +def consTailId : FVarId := consHeadContext.freshFVarId + +def consTailExpr : Expr := consHeadContext.freshExpr + +def consTailDomain : Expr := + .app (.app (.const ``IndexedVec [.param `u]) consAlphaExpr) consNExpr + +def consAfterHead : Expr := + .forallE consTailName consTailDomain + (.app (.app (.const ``IndexedVec [.param `u]) consAlphaExpr) + (.app (.const ``Nat.succ []) consNExpr)) + .default + +def consTailContext : AddInductive.Context := + consHeadContext.pushLocalDecl consTailName .default consTailDomain + +def consTerminal : Expr := + .app (.app (.const ``IndexedVec [.param `u]) consAlphaExpr) + (.app (.const ``Nat.succ []) consNExpr) + +@[simp] theorem consLiftLooseBVarsFVar + (id : FVarId) (s d : Nat) : + (Expr.fvar id).liftLooseBVars' s d = .fvar id := by + rfl + +@[simp] theorem consInstantiateFVar + (id : FVarId) (a : Expr) (k : Nat) : + (Expr.fvar id).instantiate1' a k = .fvar id := by + rfl + +theorem consAfterAlphaShape : + consNTypeRaw.instantiate1 consRootContext.freshExpr = + consAfterAlpha := by + simp [consNTypeRaw, consHeadTypeRaw, consTailTypeRaw, consTerminalRaw, consAfterAlpha, + consAlphaExpr, consRootContext, ctorContext, AddInductive.Context.freshExpr, + Expr.instantiate1_eq, Expr.instantiate1'] + +theorem consAfterNShape : + consAfterAlpha.bindingBody!.instantiate1 + consAlphaContext.freshExpr = consAfterN := by + simp [consAfterAlpha, consAfterN, consAlphaExpr, consNExpr, consRootContext, consAlphaContext, + ctorContext, AddInductive.Context.pushLocalDecl, AddInductive.Context.freshExpr, + Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1'] + +theorem consAfterHeadShape : + consAfterN.bindingBody!.instantiate1 + consNContext.freshExpr = consAfterHead := by + simp [consAfterN, consAfterHead, consTailDomain, consAlphaExpr, consNExpr, consRootContext, + consAlphaContext, consNContext, ctorContext, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1'] + +theorem consTerminalShape : + consAfterHead.bindingBody!.instantiate1 + consHeadContext.freshExpr = consTerminal := by + simp [consAfterHead, consTerminal, consAlphaExpr, consNExpr, consRootContext, consAlphaContext, + consNContext, consHeadContext, ctorContext, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1'] + +@[simp] theorem consAlphaExprShape : + consAlphaExpr = .fvar consAlphaId := by + rfl + +@[simp] theorem consNExprShape : + consNExpr = .fvar consNId := by + rfl + +@[simp] theorem consHeadExprShape : + consHeadExpr = .fvar consHeadId := by + rfl + +@[simp] theorem consTailExprShape : + consTailExpr = .fvar consTailId := by + rfl + +theorem consRootFresh : + consRootContext.lctx.find? consRootContext.freshFVarId = none := by + simpa [consRootContext, nilCandidateContext] using nilCandidateContextFresh + +theorem consAlphaContextWF : consAlphaContext.lctx.WF := by + change (({} : LocalContext).mkLocalDecl + consRootContext.freshFVarId consAlphaName + (.sort (.succ (.param `u))) .implicit).WF + exact LocalContext.WF.mkLocalDecl LocalContext.WF.nil (by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consRootContext.freshFVarId) LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + consRootContext.freshFVarId = none + rw [h] + simp [LocalContext.toList]) + +theorem consAlphaContextFresh : + consAlphaContext.lctx.find? consAlphaContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consAlphaContext.freshFVarId) consAlphaContextWF + rw [h] + simp only [consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp [NameGenerator.next, NameGenerator.curr] + intro heq + injection heq with hname + injection hname with hidx + omega + +theorem consNContextWF : consNContext.lctx.WF := by + simpa [consNContext, AddInductive.Context.pushLocalDecl] using + (LocalContext.WF.mkLocalDecl consAlphaContextWF consAlphaContextFresh) + +theorem consNContextFresh : + consNContext.lctx.find? consNContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consNContext.freshFVarId) consNContextWF + rw [h] + simp only [consNContext, consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList, LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp [NameGenerator.next, NameGenerator.curr] + constructor <;> intro heq + · injection heq with hname + injection hname with hidx + omega + · injection heq with hname + injection hname with hidx + omega + +theorem consHeadContextWF : consHeadContext.lctx.WF := by + simpa [consHeadContext, AddInductive.Context.pushLocalDecl] using + (LocalContext.WF.mkLocalDecl consNContextWF consNContextFresh) + +theorem consHeadContextFresh : + consHeadContext.lctx.find? consHeadContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := consHeadContext.freshFVarId) consHeadContextWF + rw [h] + simp only [consHeadContext, consNContext, consAlphaContext, + consRootContext, ctorContext, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList, LocalContext.mkLocalDecl_toList, + LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp [NameGenerator.next, NameGenerator.curr] + constructor + · intro heq + injection heq with hname + injection hname with hidx + omega + · constructor <;> intro heq + · injection heq with hname + injection hname with hidx + omega + · injection heq with hname + injection hname with hidx + omega + +theorem consTailContextWF : consTailContext.lctx.WF := by + simpa [consTailContext, AddInductive.Context.pushLocalDecl] using + (LocalContext.WF.mkLocalDecl consHeadContextWF consHeadContextFresh) + +theorem consAlphaFindInHead : + consHeadContext.lctx.find? consAlphaId = + some (.cdecl 0 consAlphaId consAlphaName + (.sort (.succ (.param `u))) .implicit .default) := by + rw [consHeadContextWF.find?_eq_find?_toList] + simp [consHeadContext, consNContext, consAlphaContext, consRootContext, ctorContext, consAlphaId, + AddInductive.Context.pushLocalDecl, AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, + LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + +theorem consAlphaFindInN : + consNContext.lctx.find? consAlphaId = + some (.cdecl 0 consAlphaId consAlphaName + (.sort (.succ (.param `u))) .implicit .default) := by + rw [consNContextWF.find?_eq_find?_toList] + simp [consNContext, consAlphaContext, consRootContext, ctorContext, consAlphaId, + AddInductive.Context.pushLocalDecl, AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, + LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + +theorem consNFindInHead : + consHeadContext.lctx.find? consNId = + some (.cdecl 1 consNId consNName (.const ``Nat []) + .implicit .default) := by + rw [consHeadContextWF.find?_eq_find?_toList] + simp [consHeadContext, consNContext, consAlphaContext, consRootContext, ctorContext, consAlphaId, + consNId, AddInductive.Context.pushLocalDecl, AddInductive.Context.freshFVarId, + LocalContext.mkLocalDecl, LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, + NameGenerator.curr] + +theorem consAlphaFindInTail : + consTailContext.lctx.find? consAlphaId = + some (.cdecl 0 consAlphaId consAlphaName + (.sort (.succ (.param `u))) .implicit .default) := by + rw [consTailContextWF.find?_eq_find?_toList] + simp [consTailContext, consHeadContext, consNContext, consAlphaContext, consRootContext, + ctorContext, consAlphaId, AddInductive.Context.pushLocalDecl, AddInductive.Context.freshFVarId, + LocalContext.mkLocalDecl, LocalContext.toList, LocalDecl.fvarId, NameGenerator.next, + NameGenerator.curr] + +theorem consNFindInTail : + consTailContext.lctx.find? consNId = + some (.cdecl 1 consNId consNName (.const ``Nat []) + .implicit .default) := by + rw [consTailContextWF.find?_eq_find?_toList] + simp [consTailContext, consHeadContext, consNContext, consAlphaContext, consRootContext, + ctorContext, consAlphaId, consNId, AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, LocalContext.mkLocalDecl, LocalContext.toList, + LocalDecl.fvarId, NameGenerator.next, NameGenerator.curr] + +/-! ## Reusable post-family atom observations -/ + +theorem ctorNatCheckTypeM (lctx : LocalContext) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType (.const ``Nat [])) = + .ok (.sort (.succ .zero)) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType (.const ``Nat []) false + (TypeChecker.Methods.withFuel 10000) (tcContext lctx) + ({} : TypeChecker.State)) = _ + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.const ``Nat []) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + rw [inferTypeNatCore 9999 lctx ({} : TypeChecker.State) + (by simp)] + rfl + +theorem ctorUnfoldNat (lctx methods state) : + TypeChecker.Inner.unfoldDefinition (.const ``Nat []) + methods (tcContext lctx) state = .ok (none, state) := by + change TypeChecker.Inner.unfoldDefinitionCore (.const ``Nat []) + methods (tcContext lctx) state = _ + simp [TypeChecker.Inner.unfoldDefinitionCore, + TypeChecker.Inner.isDelta, Expr.getAppFn, tcContext, + type_lookup_nat, natInfo, ConstantInfo.deltaValue?, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +theorem ctorWhnfLoopNat (lctx methods state n) : + TypeChecker.Inner.whnf'.loop (.const ``Nat []) (n + 1) + methods (tcContext lctx) state = + .ok (.const ``Nat [], state) := by + unfold TypeChecker.Inner.whnf'.loop + simp [ctorUnfoldNat] + +theorem ctorNatWhnfM (lctx : LocalContext) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf (.const ``Nat [])) = + .ok (.const ``Nat []) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' (.const ``Nat []) + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + unfold TypeChecker.Inner.whnf' + simp + rw [show + (if (tcContext lctx).eagerReduce then + (tcContext lctx).fuel.whnfEager + else (tcContext lctx).fuel.whnf) = 100000 by rfl] + rw [show 100000 = 99999 + 1 by rfl] + rw [ctorWhnfLoopNat] + simp [Functor.map, StateT.map, Except.map] + +theorem ctorFVarCheckTypeM + (lctx : LocalContext) (id : FVarId) (type : Expr) + (hfind : lctx.find? id = some (.cdecl index id name type bi kind)) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType (.fvar id)) = .ok type := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType (.fvar id) false + (TypeChecker.Methods.withFuel 10000) (tcContext lctx) + ({} : TypeChecker.State)) = _ + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.fvar id) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + rw [inferTypeFVarCore 9999 lctx ({} : TypeChecker.State) + id type (by simp) hfind] + rfl + +theorem ctorFVarWhnfM + (lctx : LocalContext) (id : FVarId) + (hfind : lctx.find? id = some (.cdecl index id name type bi kind)) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf (.fvar id)) = .ok (.fvar id) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' (.fvar id) + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + unfold TypeChecker.Inner.whnf' + simp only [nilRecMBind] + rw [show (getLCtx : TypeChecker.RecM LocalContext) + (TypeChecker.Methods.withFuel 9999) + (tcContext lctx) ({} : TypeChecker.State) = + .ok (lctx, ({} : TypeChecker.State)) by rfl] + simp [TypeChecker.Inner.isLetFVar, hfind] + rfl + +/-! A uniform WHNF observation for opaque applications of the inserted +`IndexedVec` family. -/ + +def ctorIndexedVecApp (alpha index : Expr) : Expr := + .app (.app (.const ``IndexedVec [.param `u]) alpha) index + +@[simp] theorem ctorIndexedVecAppGetAppFn (alpha index : Expr) : + (ctorIndexedVecApp alpha index).getAppFn = + .const ``IndexedVec [.param `u] := by + rfl + +theorem ctorIndexedVecInductiveReduceRec + {m : Type → Type} [Monad m] + (alpha index : Expr) (whnf inferType : Expr → m Expr) + (isDefEq : Expr → Expr → m Bool) (isNeverProp : Expr → m Bool) : + inductiveReduceRec ctorEnv (ctorIndexedVecApp alpha index) + whnf inferType isDefEq isNeverProp = pure none := by + unfold inductiveReduceRec + rw [ctorIndexedVecAppGetAppFn] + simp only + rw [type_lookup_family] + rfl + +theorem ctorIndexedVecReduceRecursor + (lctx : LocalContext) (alpha index : Expr) + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + TypeChecker.Inner.reduceRecursor (ctorIndexedVecApp alpha index) + methods (tcContext lctx) state = + .ok (none, state) := by + unfold TypeChecker.Inner.reduceRecursor + have hquot : ctorEnv.quotInit = false := by rfl + simp only [nilRecMBind, nilRecMGetEnv] + rw [show (tcContext lctx).env = ctorEnv by rfl] + rw [hquot] + simp only [Bool.false_eq_true, if_false, nilRecMBind] + rw [ctorIndexedVecInductiveReduceRec] + rfl + +@[simp] theorem ctorIndexedVecWhnfCoreFamily + (lctx : LocalContext) (n : Nat) (state : TypeChecker.State) : + TypeChecker.Inner.whnfCore + (.const ``IndexedVec [.param `u]) false + (TypeChecker.Methods.withFuel (n + 1)) (tcContext lctx) state = + .ok (.const ``IndexedVec [.param `u], state) := by + rfl + +theorem ctorIndexedVecWhnfCoreInitial + (lctx : LocalContext) (alpha index : Expr) (n : Nat) : + TypeChecker.Inner.whnfCore' (ctorIndexedVecApp alpha index) + false (TypeChecker.Methods.withFuel (n + 1)) + (tcContext lctx) ({} : TypeChecker.State) = + .ok (ctorIndexedVecApp alpha index, ({} : TypeChecker.State)) := by + unfold ctorIndexedVecApp TypeChecker.Inner.whnfCore' + simp only [nilRecMBind, nilRecMGet, Std.HashMap.getElem?_empty] + rw [Expr.withRevApp_eq] + simp only [nilRecMBind] + rw [show + (Expr.app (Expr.app (Expr.const ``IndexedVec [.param `u]) alpha) + index).getAppFn = Expr.const ``IndexedVec [.param `u] by rfl] + rw [ctorIndexedVecWhnfCoreFamily lctx n ({} : TypeChecker.State)] + simp [Expr.structuralEq, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show + Expr.app (Expr.app (Expr.const ``IndexedVec [.param `u]) alpha) + index = ctorIndexedVecApp alpha index by rfl] + rw [ctorIndexedVecReduceRecursor] + rfl + +@[simp] theorem ctorIndexedVecReduceNative + (lctx : LocalContext) (env : Kernel.Environment) + (alpha index : Expr) (methods : TypeChecker.Methods) + (state : TypeChecker.State) : + (liftM (TypeChecker.Inner.reduceNative env + (ctorIndexedVecApp alpha index)) : + TypeChecker.RecM (Option Expr)) + methods (tcContext lctx) state = .ok (none, state) := by + cases index <;> + simp [ctorIndexedVecApp, TypeChecker.Inner.reduceNative, Expr.structuralEq] + +@[simp] theorem ctorIndexedVecReduceNat + (lctx : LocalContext) (alpha index : Expr) + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + TypeChecker.Inner.reduceNat (ctorIndexedVecApp alpha index) + methods (tcContext lctx) state = .ok (none, state) := by + simp [ctorIndexedVecApp, TypeChecker.Inner.reduceNat, Expr.getAppNumArgs_eq, + Expr.getAppArgsRevList] + +theorem ctorIndexedVecUnfoldFamily + (lctx : LocalContext) (methods : TypeChecker.Methods) + (state : TypeChecker.State) : + TypeChecker.Inner.unfoldDefinitionCore + (.const ``IndexedVec [.param `u]) methods (tcContext lctx) state = + .ok (none, state) := by + unfold TypeChecker.Inner.unfoldDefinitionCore + simp only [nilRecMBind, nilRecMGetEnv] + rw [show (tcContext lctx).env = ctorEnv by rfl] + rw [nilCandidateIsDeltaFamily] + rfl + +theorem ctorIndexedVecUnfold + (lctx : LocalContext) (alpha index : Expr) + (methods : TypeChecker.Methods) (state : TypeChecker.State) : + TypeChecker.Inner.unfoldDefinition (ctorIndexedVecApp alpha index) + methods (tcContext lctx) state = .ok (none, state) := by + unfold TypeChecker.Inner.unfoldDefinition + rw [show (ctorIndexedVecApp alpha index).isApp = true by rfl] + simp only [if_true] + rw [ctorIndexedVecAppGetAppFn] + simp only [nilRecMBind] + rw [ctorIndexedVecUnfoldFamily] + rfl + +theorem ctorIndexedVecWhnfLoop + (lctx : LocalContext) (alpha index : Expr) : + TypeChecker.Inner.whnf'.loop (ctorIndexedVecApp alpha index) 100000 + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (ctorIndexedVecApp alpha index, ({} : TypeChecker.State)) := by + rw [show 100000 = 99999 + 1 by rfl] + unfold TypeChecker.Inner.whnf'.loop + rw [show 9999 = 9998 + 1 by rfl] + simp only [nilRecMBind, nilRecMGetEnv] + rw [ctorIndexedVecWhnfCoreInitial lctx alpha index 9998] + simp only [] + rw [ctorIndexedVecReduceNative] + simp only [nilRecMBind] + rw [ctorIndexedVecReduceNat] + simp only [nilRecMBind] + rw [ctorIndexedVecUnfold] + rfl + +theorem ctorIndexedVecWhnfM + (lctx : LocalContext) (alpha index : Expr) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf (ctorIndexedVecApp alpha index)) = + .ok (ctorIndexedVecApp alpha index) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' (ctorIndexedVecApp alpha index) + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + unfold ctorIndexedVecApp + unfold TypeChecker.Inner.whnf' + simp + rw [show + (if (tcContext lctx).eagerReduce then + (tcContext lctx).fuel.whnfEager + else (tcContext lctx).fuel.whnf) = 100000 by rfl] + have hloop := ctorIndexedVecWhnfLoop lctx alpha index + simp only [ctorIndexedVecApp] at hloop + rw [hloop] + simp [Functor.map, StateT.map, Except.map] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/IndexedVecOuterReplay.lean b/Ix/Theory/Named/Verify/Environment/IndexedVecOuterReplay.lean new file mode 100644 index 000000000..6ccc4cd64 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/IndexedVecOuterReplay.lean @@ -0,0 +1,1757 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.IndexedVecConsReplay +import Ix.Theory.Named.Verify.Name + +/-! +# IndexedVec outer normalization-candidate replay + +Exact post-family declaration and constructor-validation executions for the +real one-parameter, one-index `IndexedVec` metadata. The final theorem closes +the complete `buildNormalizationCandidate` call and retains the ordered +`nil`/`cons` candidate package produced in the staged kernel environments. +-/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta +open Ix.Theory.Named.InductiveFixtures +open IndexedVecConsReplay + +def indexedVecCtorValidationContext : AddInductive.Context := + { indexedVecFamilyCandidate.trace.terminalContext with env := ctorEnv } + +def indexedVecValidationAlpha : Expr := + indexedVecFamilyCandidateContext.freshExpr + +def indexedVecValidationAlphaId : FVarId := + indexedVecFamilyCandidateContext.freshFVarId + +def indexedVecValidationIndexId : FVarId := + ⟨indexedVecFamilyCandidateContext.ngen.next.curr⟩ + +theorem validationTerminalEnv : + indexedVecFamilyCandidate.trace.terminalContext.env = + indexedVecKernelEnv := by + rfl + +theorem validationTerminalLparams : + indexedVecFamilyCandidate.trace.terminalContext.lparams = [`u] := by + rfl + +theorem validationTerminalAllowPrimitive : + indexedVecFamilyCandidate.trace.terminalContext.allowPrimitive = false := by + rfl + +theorem validationFamilyEnvNotContains : + indexedVecKernelEnv.contains ``IndexedVec = false := by + unfold Kernel.Environment.contains + change natMap.contains ``IndexedVec = false + rw [SMap.find?_isSome, indexedVecType_fresh] + rfl + +theorem validationFamilyEnvCheckName : + indexedVecKernelEnv.checkName ``IndexedVec false = .ok () := by + simp [Kernel.Environment.checkName, validationFamilyEnvNotContains, Kernel.Environment.primitives, + NameSet.ofList, NameSet.contains, Pure.pure, Except.pure] + +theorem indexedVecDeclareRoot : + AddInductive.declareInductiveTypes indexedVecCandidateInductiveStats 1 + #[indexedVecKernelType] 0 false + indexedVecFamilyCandidateContext = + .ok ctorEnv := by + simp [AddInductive.declareInductiveTypes, + indexedVecCandidateInductiveStats_nindices, + indexedVecCandidateInductiveStats_indConsts, + indexedVecKernelType, indexedVecKernelNil, indexedVecKernelCons, + indexedVecInfo, indexedVecNilInfo, indexedVecConsInfo, + ConstantInfo.name, ConstantInfo.type, ConstantInfo.toConstantVal, + ctorEnv, indexedVecKernelEnv, indexedVecFamilyCandidateContext, + indexedVecTypeMap, + AddInductive.isRec, AddInductive.isRec.loop, + AddInductive.isReflexive, AddInductive.isReflexive.loop, + AddInductive.hasIndOcc, Expr.constName!, + Bind.bind, Pure.pure, Except.bind, Except.pure] + have hcheck : + (Kernel.Environment.ofConstants `_indexedVecCandidate natMap).checkName + ``IndexedVec false = .ok () := by + simpa [indexedVecKernelEnv] using validationFamilyEnvCheckName + rw [hcheck] + rfl + +theorem indexedVecDeclareFromTerminal : + AddInductive.declareInductiveTypes indexedVecCandidateInductiveStats 1 + #[indexedVecKernelType] 0 false + indexedVecFamilyCandidate.trace.terminalContext = + .ok ctorEnv := by + calc + _ = AddInductive.declareInductiveTypes + indexedVecCandidateInductiveStats 1 #[indexedVecKernelType] + 0 false indexedVecFamilyCandidateContext := + AddInductive.declareInductiveTypes_context_eq _ _ _ _ _ _ _ + validationTerminalEnv validationTerminalLparams + validationTerminalAllowPrimitive + _ = .ok ctorEnv := indexedVecDeclareRoot + +example : indexedVecCtorValidationContext.env = ctorEnv := by rfl +example : indexedVecCtorValidationContext.lparams = [`u] := by rfl +example : indexedVecCtorValidationContext.safety = .safe := by rfl +example : indexedVecCtorValidationContext.allowPrimitive = false := by rfl +example : indexedVecCtorValidationContext.fuel = ({} : FuelConfig) := by rfl +example : indexedVecCtorValidationContext.ngen = + ({ namePrefix := `_ind_fresh } : NameGenerator).next.next := by rfl + +def indexedVecValidationParamName : Name := + indexedVecInfo.type.bindingName! + +def indexedVecValidationIndexName : Name := + indexedVecInfo.type.bindingBody!.bindingName! + +def indexedVecValidationParamContext : AddInductive.Context := + indexedVecFamilyCandidateContext.pushLocalDecl + indexedVecValidationParamName .default + (.sort (.succ (.param `u))) + +def indexedVecValidationFamilyContext : AddInductive.Context := + indexedVecValidationParamContext.pushLocalDecl + indexedVecValidationIndexName .default (.const ``Nat []) + +theorem indexedVecValidationTerminalContextShape : + indexedVecFamilyCandidate.trace.terminalContext = + indexedVecValidationFamilyContext := by + rfl + +theorem indexedVecCtorValidationContextShape : + indexedVecCtorValidationContext = + { indexedVecValidationFamilyContext with env := ctorEnv } := by + rfl + +theorem indexedVecValidationParamContextWF : + indexedVecValidationParamContext.lctx.WF := by + have hfresh : indexedVecFamilyCandidateContext.lctx.find? + indexedVecFamilyCandidateContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := indexedVecFamilyCandidateContext.freshFVarId) + LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + indexedVecFamilyCandidateContext.freshFVarId = none + rw [h] + simp [LocalContext.toList] + change (({} : LocalContext).mkLocalDecl + indexedVecFamilyCandidateContext.freshFVarId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default).WF + exact LocalContext.WF.mkLocalDecl LocalContext.WF.nil hfresh + +theorem indexedVecValidationFamilyContextFresh : + indexedVecValidationParamContext.lctx.find? + indexedVecValidationParamContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := indexedVecValidationParamContext.freshFVarId) + indexedVecValidationParamContextWF + rw [h] + simp only [indexedVecValidationParamContext, + indexedVecFamilyCandidateContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp [NameGenerator.next, NameGenerator.curr] + intro heq + injection heq with hname + injection hname with hidx + omega + +theorem indexedVecValidationFamilyContextWF : + indexedVecValidationFamilyContext.lctx.WF := by + simpa [indexedVecValidationFamilyContext, + AddInductive.Context.pushLocalDecl] using + (LocalContext.WF.mkLocalDecl indexedVecValidationParamContextWF + indexedVecValidationFamilyContextFresh) + +theorem indexedVecValidationAlphaFind : + indexedVecCtorValidationContext.lctx.find? + indexedVecValidationAlphaId = + some (.cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default .default) := by + change indexedVecValidationFamilyContext.lctx.find? + indexedVecValidationAlphaId = _ + rw [indexedVecValidationFamilyContextWF.find?_eq_find?_toList] + simp [indexedVecValidationFamilyContext, + indexedVecValidationParamContext, + indexedVecValidationAlphaId, + indexedVecFamilyCandidateContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, + LocalContext.mkLocalDecl, + LocalContext.toList, LocalDecl.fvarId, + NameGenerator.next, NameGenerator.curr] + +@[simp] theorem indexedVecValidationAlphaShape : indexedVecValidationAlpha = + .fvar indexedVecValidationAlphaId := by rfl + +theorem localContextFindNew + (lctx : LocalContext) (id : FVarId) (name : Name) + (type : Expr) (bi : BinderInfo) (kind : LocalDeclKind) + (hwf : lctx.WF) (hfresh : lctx.find? id = none) : + (lctx.mkLocalDecl id name type bi kind).find? id = + some (.cdecl lctx.decls.size id name type bi kind) := by + have hwf' := LocalContext.WF.mkLocalDecl + (name := name) (ty := type) (bi := bi) (kind := kind) hwf hfresh + rw [hwf'.find?_eq_find?_toList] + rw [LocalContext.mkLocalDecl_toList] + simp [LocalDecl.fvarId] + +theorem localContextFindOld + (lctx : LocalContext) (oldId newId : FVarId) + (newName : Name) (newType : Expr) (newBi : BinderInfo) + (newKind : LocalDeclKind) (oldDecl : LocalDecl) + (hwf : lctx.WF) (hfresh : lctx.find? newId = none) + (hne : oldId ≠ newId) (hold : lctx.find? oldId = some oldDecl) : + (lctx.mkLocalDecl newId newName newType newBi newKind).find? oldId = + some oldDecl := by + have hwf' := LocalContext.WF.mkLocalDecl + (name := newName) (ty := newType) (bi := newBi) + (kind := newKind) hwf hfresh + rw [hwf'.find?_eq_find?_toList] + rw [LocalContext.mkLocalDecl_toList] + simp only [List.find?_cons, LocalDecl.fvarId] + rw [show (oldId == newId) = false by + exact beq_eq_false_iff_ne.mpr hne] + rw [hwf.find?_eq_find?_toList] at hold + simpa only [LocalDecl.fvarId] using hold + +def validationFirstAppState (alphaId : FVarId) : TypeChecker.State := + replayInsert + (replayInsert + (replayInsert ({} : TypeChecker.State) + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) + (.fvar alphaId) (.sort (.succ (.param `u)))) + (replayFirstApp (.fvar alphaId)) vecFamilyTail + +def validationIndexState (alphaId nId : FVarId) : TypeChecker.State := + replayInsert (validationFirstAppState alphaId) + (.fvar nId) (.const ``Nat []) + +def validationIndexedVecState + (alphaId nId : FVarId) : TypeChecker.State := + replayInsert (validationIndexState alphaId nId) + (ctorIndexedVecApp (.fvar alphaId) (.fvar nId)) + (.sort (.succ (.param `u))) + +theorem ctorIndexedVecFVarCheckTypeM + (lctx : LocalContext) (alphaId nId : FVarId) + (hne : alphaId ≠ nId) + (halpha : lctx.find? alphaId = some (.cdecl alphaIndex alphaId + alphaName (.sort (.succ (.param `u))) alphaBi alphaKind)) + (hn : lctx.find? nId = some (.cdecl nIndex nId nName + (.const ``Nat []) nBi nKind)) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType + (ctorIndexedVecApp (.fvar alphaId) (.fvar nId))) = + .ok (.sort (.succ (.param `u))) := by + have hfirst : + TypeChecker.Inner.inferType' + (replayFirstApp (.fvar alphaId)) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (vecFamilyTail, validationFirstAppState alphaId) := by + simpa [validationFirstAppState] using + (replayInferFirstAppFVarCore 9999 lctx + ({} : TypeChecker.State) alphaId + (by simp) + (by simp [replayInsert]) + (by simp [replayFirstApp]) + halpha) + have hnmiss : + (validationFirstAppState alphaId).inferTypeC[ + (.fvar nId : Expr)]? = none := by + have halphaN : + ((.fvar alphaId : Expr) == .fvar nId) = false := by + change Expr.eqv (.fvar alphaId) (.fvar nId) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', hne] + simp [validationFirstAppState, replayInsert, replayFirstApp, + halphaN] + have hnrun : + TypeChecker.Inner.inferType' (.fvar nId) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + (validationFirstAppState alphaId) = + .ok (.const ``Nat [], validationIndexState alphaId nId) := by + simpa [validationIndexState, replayInsert] using + (inferTypeFVarCore 9999 lctx + (validationFirstAppState alphaId) nId (.const ``Nat []) + hnmiss hn) + have htail : + (({} : TypeChecker.State).inferTypeC[ + ctorIndexedVecApp (.fvar alphaId) (.fvar nId)]?) = none := by + simp + have hrun : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) (.fvar nId)) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), + validationIndexedVecState alphaId nId) := by + simpa [validationIndexedVecState] using + (replayInferIndexedVecAppCore 9999 lctx + ({} : TypeChecker.State) (validationFirstAppState alphaId) + (validationIndexState alphaId nId) + (.fvar alphaId) (.fvar nId) + (by simp [ctorIndexedVecApp, Expr.hasLooseBVars, + Expr.looseBVarRange']) + htail hfirst hnrun (by rfl)) + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) (.fvar nId)) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + rw [hrun] + rfl + +def indexedVecValidationNilResult : Expr := + ctorIndexedVecApp indexedVecValidationAlpha (.const ``Nat.zero []) + +def indexedVecValidationConsAfterParam : Expr := + consNTypeRaw.instantiate1 indexedVecValidationAlpha + +def indexedVecValidationNId : FVarId := + indexedVecCtorValidationContext.freshFVarId + +def indexedVecValidationNExpr : Expr := + indexedVecCtorValidationContext.freshExpr + +@[simp] theorem indexedVecValidationNExprShape : + indexedVecValidationNExpr = .fvar indexedVecValidationNId := by + rfl + +def indexedVecValidationNContext : AddInductive.Context := + indexedVecCtorValidationContext.pushLocalDecl + consNName .implicit (.const ``Nat []) + +def indexedVecValidationConsAfterN : Expr := + .forallE consHeadName indexedVecValidationAlpha + (.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)) + .default) + .default + +def indexedVecValidationHeadId : FVarId := + indexedVecValidationNContext.freshFVarId + +def indexedVecValidationHeadExpr : Expr := + indexedVecValidationNContext.freshExpr + +@[simp] theorem indexedVecValidationHeadExprShape : + indexedVecValidationHeadExpr = + .fvar indexedVecValidationHeadId := by + rfl + +def indexedVecValidationHeadContext : AddInductive.Context := + indexedVecValidationNContext.pushLocalDecl + consHeadName .default indexedVecValidationAlpha + +def indexedVecValidationConsAfterHead : Expr := + .forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)) + .default + +def indexedVecValidationTailId : FVarId := + indexedVecValidationHeadContext.freshFVarId + +def indexedVecValidationTailContext : AddInductive.Context := + indexedVecValidationHeadContext.pushLocalDecl consTailName .default + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + +def indexedVecValidationConsResult : Expr := + ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr) + +theorem indexedVecValidationNilResultShape : + indexedVecNilInfo.type.bindingBody!.instantiate1 + indexedVecValidationAlpha = + indexedVecValidationNilResult := by + simp [indexedVecNilInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, indexedVecValidationNilResult, + ctorIndexedVecApp, indexedVecValidationAlpha, + indexedVecFamilyCandidateContext, + Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] + +theorem indexedVecValidationConsAfterParamShape : + indexedVecConsInfo.type.bindingBody!.instantiate1 + indexedVecValidationAlpha = + indexedVecValidationConsAfterParam := by + rw [consInfoTypeShape] + rfl + +theorem indexedVecValidationConsAfterParamExplicitShape : + indexedVecValidationConsAfterParam = + .forallE consNName (.const ``Nat []) + (.forallE consHeadName indexedVecValidationAlpha + (.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) + .default) + .default) + .implicit := by + simp [indexedVecValidationConsAfterParam, consNTypeRaw, + consHeadTypeRaw, consTailTypeRaw, consTerminalRaw, + ctorIndexedVecApp, replaySuccApp, + Expr.instantiate1_eq, Expr.instantiate1'] + +theorem indexedVecValidationConsAfterNShape : + indexedVecValidationConsAfterParam.bindingBody!.instantiate1 + indexedVecValidationNExpr = + indexedVecValidationConsAfterN := by + simp [indexedVecValidationConsAfterParam, consNTypeRaw, + consHeadTypeRaw, consTailTypeRaw, consTerminalRaw, + indexedVecValidationConsAfterN, + indexedVecValidationNExpr, + indexedVecValidationAlpha, + indexedVecCtorValidationContext, + indexedVecValidationTerminalContextShape, + indexedVecValidationFamilyContext, + indexedVecValidationParamContext, + indexedVecFamilyCandidateContext, + ctorIndexedVecApp, replaySuccApp, + AddInductive.Context.freshExpr, + AddInductive.Context.freshFVarId, + Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1', + NameGenerator.curr] + +theorem indexedVecValidationConsAfterHeadShape : + indexedVecValidationConsAfterN.bindingBody!.instantiate1 + indexedVecValidationHeadExpr = + indexedVecValidationConsAfterHead := by + simp [indexedVecValidationConsAfterN, + indexedVecValidationConsAfterHead, + ctorIndexedVecApp, replaySuccApp, + Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1'] + +theorem indexedVecValidationConsResultShape : + indexedVecValidationConsAfterHead.bindingBody!.instantiate1 + indexedVecValidationHeadContext.freshExpr = + indexedVecValidationConsResult := by + simp [indexedVecValidationConsAfterHead, + indexedVecValidationConsResult, + ctorIndexedVecApp, replaySuccApp, + Expr.bindingBody!, Expr.instantiate1_eq, Expr.instantiate1'] + +theorem indexedVecCtorValidationContextWF : + indexedVecCtorValidationContext.lctx.WF := by + simpa [indexedVecCtorValidationContextShape] using + indexedVecValidationFamilyContextWF + +theorem indexedVecCtorValidationContextLctxSize : + indexedVecCtorValidationContext.lctx.decls.size = 2 := by + change indexedVecFamilyCandidate.trace.terminalContext.lctx.decls.size = 2 + rw [indexedVecValidationTerminalContextShape] + simp [indexedVecValidationFamilyContext, + indexedVecValidationParamContext, + indexedVecFamilyCandidateContext, + AddInductive.Context.pushLocalDecl, + LocalContext.mkLocalDecl] + +theorem indexedVecCtorValidationContextFresh : + indexedVecCtorValidationContext.lctx.find? + indexedVecCtorValidationContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := indexedVecCtorValidationContext.freshFVarId) + indexedVecCtorValidationContextWF + rw [h] + simp only [indexedVecCtorValidationContext, + indexedVecValidationTerminalContextShape, + indexedVecValidationFamilyContext, + indexedVecValidationParamContext, + indexedVecFamilyCandidateContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList, + LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp [NameGenerator.next, NameGenerator.curr] + constructor <;> intro heq + · injection heq with hname + injection hname with hidx + omega + · injection heq with hname + injection hname with hidx + omega + +theorem indexedVecValidationNContextWF : + indexedVecValidationNContext.lctx.WF := by + simpa [indexedVecValidationNContext, + AddInductive.Context.pushLocalDecl] using + (LocalContext.WF.mkLocalDecl indexedVecCtorValidationContextWF + indexedVecCtorValidationContextFresh) + +theorem indexedVecValidationNContextFresh : + indexedVecValidationNContext.lctx.find? + indexedVecValidationNContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := indexedVecValidationNContext.freshFVarId) + indexedVecValidationNContextWF + rw [h] + simp only [indexedVecValidationNContext, + indexedVecCtorValidationContext, + indexedVecValidationTerminalContextShape, + indexedVecValidationFamilyContext, + indexedVecValidationParamContext, + indexedVecFamilyCandidateContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList, + LocalContext.mkLocalDecl_toList, + LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp [NameGenerator.next, NameGenerator.curr] + constructor + · intro heq + injection heq with hname + injection hname with hidx + omega + · constructor <;> intro heq + · injection heq with hname + injection hname with hidx + omega + · injection heq with hname + injection hname with hidx + omega + +theorem indexedVecValidationHeadContextWF : + indexedVecValidationHeadContext.lctx.WF := by + simpa [indexedVecValidationHeadContext, + AddInductive.Context.pushLocalDecl] using + (LocalContext.WF.mkLocalDecl indexedVecValidationNContextWF + indexedVecValidationNContextFresh) + +theorem indexedVecValidationAlphaNeN : + indexedVecValidationAlphaId ≠ indexedVecValidationNId := by + change indexedVecValidationAlphaId ≠ + indexedVecCtorValidationContext.freshFVarId + intro heq + have hfresh := indexedVecCtorValidationContextFresh + rw [← heq] at hfresh + rw [indexedVecValidationAlphaFind] at hfresh + contradiction + +theorem indexedVecValidationNNeHead : + indexedVecValidationNId ≠ indexedVecValidationHeadId := by + change indexedVecValidationNId ≠ + indexedVecValidationNContext.freshFVarId + intro heq + have hfresh := indexedVecValidationNContextFresh + rw [← heq] at hfresh + have hnew := localContextFindNew + indexedVecCtorValidationContext.lctx indexedVecValidationNId + consNName (.const ``Nat []) .implicit .default + indexedVecCtorValidationContextWF + indexedVecCtorValidationContextFresh + have hfind : indexedVecValidationNContext.lctx.find? + indexedVecValidationNId = some (.cdecl 2 + indexedVecValidationNId consNName (.const ``Nat []) + .implicit .default) := by + rw [indexedVecCtorValidationContextLctxSize] at hnew + simpa [indexedVecValidationNContext, + indexedVecValidationNId, + AddInductive.Context.pushLocalDecl] using hnew + rw [hfind] at hfresh + contradiction + +theorem indexedVecValidationAlphaFindInN : + indexedVecValidationNContext.lctx.find? + indexedVecValidationAlphaId = + some (.cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default .default) := by + have h := localContextFindOld + (lctx := indexedVecCtorValidationContext.lctx) + (oldId := indexedVecValidationAlphaId) + (newId := indexedVecValidationNId) + (newName := consNName) (newType := .const ``Nat []) + (newBi := .implicit) (newKind := .default) + (oldDecl := .cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName (.sort (.succ (.param `u))) + .default .default) + indexedVecCtorValidationContextWF + indexedVecCtorValidationContextFresh + indexedVecValidationAlphaNeN indexedVecValidationAlphaFind + simpa [indexedVecValidationNContext, + indexedVecValidationNId, + AddInductive.Context.pushLocalDecl] using h + +theorem indexedVecValidationNFindInHead : + indexedVecValidationHeadContext.lctx.find? + indexedVecValidationNId = + some (.cdecl 2 indexedVecValidationNId consNName + (.const ``Nat []) .implicit .default) := by + have hnew := localContextFindNew + indexedVecCtorValidationContext.lctx indexedVecValidationNId + consNName (.const ``Nat []) .implicit .default + indexedVecCtorValidationContextWF + indexedVecCtorValidationContextFresh + have hold : indexedVecValidationNContext.lctx.find? + indexedVecValidationNId = + some (.cdecl 2 indexedVecValidationNId consNName + (.const ``Nat []) .implicit .default) := by + rw [indexedVecCtorValidationContextLctxSize] at hnew + simpa [indexedVecValidationNContext, + indexedVecValidationNId, + AddInductive.Context.pushLocalDecl] using hnew + have h := localContextFindOld + (lctx := indexedVecValidationNContext.lctx) + (oldId := indexedVecValidationNId) + (newId := indexedVecValidationHeadId) + (newName := consHeadName) + (newType := indexedVecValidationAlpha) + (newBi := .default) (newKind := .default) + (oldDecl := .cdecl 2 indexedVecValidationNId consNName + (.const ``Nat []) .implicit .default) + indexedVecValidationNContextWF indexedVecValidationNContextFresh + indexedVecValidationNNeHead hold + simpa [indexedVecValidationHeadContext, + indexedVecValidationHeadId, + AddInductive.Context.pushLocalDecl] using h + +theorem indexedVecValidationAlphaFindInHead : + indexedVecValidationHeadContext.lctx.find? + indexedVecValidationAlphaId = + some (.cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default .default) := by + have hne : indexedVecValidationAlphaId ≠ + indexedVecValidationHeadId := by + change indexedVecValidationAlphaId ≠ + indexedVecValidationNContext.freshFVarId + intro heq + have hfresh := indexedVecValidationNContextFresh + rw [← heq] at hfresh + rw [indexedVecValidationAlphaFindInN] at hfresh + contradiction + have h := localContextFindOld + (lctx := indexedVecValidationNContext.lctx) + (oldId := indexedVecValidationAlphaId) + (newId := indexedVecValidationHeadId) + (newName := consHeadName) + (newType := indexedVecValidationAlpha) + (newBi := .default) (newKind := .default) + (oldDecl := .cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName (.sort (.succ (.param `u))) + .default .default) + indexedVecValidationNContextWF indexedVecValidationNContextFresh + hne indexedVecValidationAlphaFindInN + simpa [indexedVecValidationHeadContext, + indexedVecValidationHeadId, + AddInductive.Context.pushLocalDecl] using h + +theorem indexedVecValidationGetTypeAlpha : + AddInductive.getType indexedVecValidationAlpha + indexedVecCtorValidationContext = + .ok (.sort (.succ (.param `u))) := by + unfold AddInductive.getType + simp only [getLCtx, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + change Except.ok ((indexedVecCtorValidationContext.lctx.get! + indexedVecValidationAlpha.fvarId!).type) = _ + rw [show indexedVecValidationAlpha.fvarId! = + indexedVecValidationAlphaId by + rw [indexedVecValidationAlphaShape] + rfl] + simp [LocalContext.get!, indexedVecValidationAlphaFind, + LocalDecl.type] + +theorem indexedVecValidationParamIsDefEq : + TypeChecker.M.run indexedVecCtorValidationContext.env + indexedVecCtorValidationContext.safety + indexedVecCtorValidationContext.lctx + indexedVecCtorValidationContext.lparams + indexedVecCtorValidationContext.fuel + (TypeChecker.isDefEq (.sort (.succ (.param `u))) + (.sort (.succ (.param `u)))) = .ok true := by + exact candidateIsDefEqSelfValid indexedVecCtorValidationContext + (.sort (.succ (.param `u))) 9999 rfl + +theorem indexedVecNilNoMVarNoFVar : + ctorEnv.checkNoMVarNoFVar indexedVecKernelNil.name + indexedVecKernelNil.type = .ok () := by + have hexpr : indexedVecKernelNil.type.data.hasExprMVar = false := by + change indexedVecNilInfo.type.hasExprMVar = false + rw [Expr.hasExprMVar_eq] + rfl + have hlevel : indexedVecKernelNil.type.data.hasLevelMVar = false := by + change indexedVecNilInfo.type.hasLevelMVar = false + rw [Expr.hasLevelMVar_eq] + simp [indexedVecNilInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, Expr.hasLevelMVar', + Level.hasMVar_eq, Level.hasMVar'] + have hfvar : indexedVecKernelNil.type.data.hasFVar = false := by + change indexedVecNilInfo.type.hasFVar = false + rw [Expr.hasFVar_eq] + rfl + unfold Kernel.Environment.checkNoMVarNoFVar + Kernel.Environment.checkNoMVar Kernel.Environment.checkNoFVar + rw [show indexedVecKernelNil.type.hasMVar = false by + change (indexedVecKernelNil.type.data.hasExprMVar || + indexedVecKernelNil.type.data.hasLevelMVar) = false + rw [hexpr, hlevel] + rfl] + rw [show indexedVecKernelNil.type.hasFVar = false by + exact hfvar] + rfl + +theorem indexedVecConsNoMVarNoFVar : + ctorEnv.checkNoMVarNoFVar indexedVecKernelCons.name + indexedVecKernelCons.type = .ok () := by + have hexpr : indexedVecKernelCons.type.data.hasExprMVar = false := by + change indexedVecConsInfo.type.hasExprMVar = false + rw [Expr.hasExprMVar_eq] + rfl + have hlevel : indexedVecKernelCons.type.data.hasLevelMVar = false := by + change indexedVecConsInfo.type.hasLevelMVar = false + rw [Expr.hasLevelMVar_eq] + simp [indexedVecConsInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, Expr.hasLevelMVar', + Level.hasMVar_eq, Level.hasMVar'] + have hfvar : indexedVecKernelCons.type.data.hasFVar = false := by + change indexedVecConsInfo.type.hasFVar = false + rw [Expr.hasFVar_eq] + rfl + unfold Kernel.Environment.checkNoMVarNoFVar + Kernel.Environment.checkNoMVar Kernel.Environment.checkNoFVar + rw [show indexedVecKernelCons.type.hasMVar = false by + change (indexedVecKernelCons.type.data.hasExprMVar || + indexedVecKernelCons.type.data.hasLevelMVar) = false + rw [hexpr, hlevel] + rfl] + rw [show indexedVecKernelCons.type.hasFVar = false by + exact hfvar] + rfl + +theorem indexedVecValidationNilRootCheckTypeM : + TypeChecker.M.run indexedVecCtorValidationContext.env + indexedVecCtorValidationContext.safety {} + indexedVecCtorValidationContext.lparams + indexedVecCtorValidationContext.fuel + (TypeChecker.checkType indexedVecKernelNil.type) = + .ok (.sort nilCtorInferredLevel) := by + change TypeChecker.M.run ctorEnv .safe {} [`u] ({} : FuelConfig) + (TypeChecker.checkType indexedVecKernelNil.type) = + .ok (.sort nilCtorInferredLevel) + simpa [indexedVecKernelNil] using nilRootCheckTypeM + +theorem indexedVecValidationConsRootCheckTypeM : + TypeChecker.M.run indexedVecCtorValidationContext.env + indexedVecCtorValidationContext.safety {} + indexedVecCtorValidationContext.lparams + indexedVecCtorValidationContext.fuel + (TypeChecker.checkType indexedVecKernelCons.type) = + .ok (.sort (.succ (.succ (.param `u)))) := by + change TypeChecker.M.run ctorEnv .safe {} [`u] ({} : FuelConfig) + (TypeChecker.checkType indexedVecKernelCons.type) = + .ok (.sort (.succ (.succ (.param `u)))) + simpa [indexedVecKernelCons, consRootContext, ctorContext] using + replayConsRootCheckTypeM + +def validationInferOnlyInsert + (state : TypeChecker.State) (e type : Expr) : TypeChecker.State := + { state with inferTypeI := state.inferTypeI.insert e type } + +@[simp] theorem inferConstantFamilyOnly (lctx : LocalContext) : + TypeChecker.Inner.inferConstant (tcContext lctx) ``IndexedVec + [.param `u] true = .ok indexedVecInfo.type := by + unfold TypeChecker.Inner.inferConstant + simp only [tcContext] + rw [type_get_family] + simp [indexedVecInfo, + ConstantInfo.levelParams, ConstantInfo.type, + ConstantInfo.instantiateTypeLevelParams, + ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, + Expr.instantiateLevelParamsCore', Level.substParams', + Bind.bind, Except.bind, Pure.pure, Except.pure] + +@[simp] theorem inferConstantNatOnly (lctx : LocalContext) : + TypeChecker.Inner.inferConstant (tcContext lctx) ``Nat [] true = + .ok (.sort (.succ .zero)) := by + unfold TypeChecker.Inner.inferConstant + simp [tcContext, natInfo, + ConstantInfo.levelParams, ConstantInfo.instantiateTypeLevelParams, + ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, + Expr.instantiateLevelParamsCore', Level.substParams', + Bind.bind, Except.bind, Pure.pure, Except.pure] + +theorem inferTypeNatOnlyCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : state.inferTypeI[(.const ``Nat [] : Expr)]? = none) : + TypeChecker.Inner.inferType' (.const ``Nat []) true + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (.sort (.succ .zero), + validationInferOnlyInsert state (.const ``Nat []) + (.sort (.succ .zero))) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + validationInferOnlyInsert, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +theorem inferTypeFamilyOnlyCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : state.inferTypeI[ + (.const ``IndexedVec [.param `u] : Expr)]? = none) : + TypeChecker.Inner.inferType' + (.const ``IndexedVec [.param `u]) true + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (indexedVecInfo.type, + validationInferOnlyInsert state + (.const ``IndexedVec [.param `u]) indexedVecInfo.type) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + validationInferOnlyInsert, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +theorem inferTypeFVarOnlyCore + (fuel : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (id : FVarId) (type : Expr) + (hcache : state.inferTypeI[(.fvar id : Expr)]? = none) + (hfind : lctx.find? id = some (.cdecl index id name type bi kind)) : + TypeChecker.Inner.inferType' (.fvar id) true + (TypeChecker.Methods.withFuel fuel) (tcContext lctx) state = + .ok (type, validationInferOnlyInsert state (.fvar id) type) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + TypeChecker.Inner.inferFVar, tcContext, hfind, LocalDecl.type, + validationInferOnlyInsert, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +def validationFamilyOnlyState : TypeChecker.State := + validationInferOnlyInsert ({} : TypeChecker.State) + (.const ``IndexedVec [.param `u]) indexedVecInfo.type + +def validationIndexedVecOnlyState + (alpha index : Expr) : TypeChecker.State := + validationInferOnlyInsert validationFamilyOnlyState + (ctorIndexedVecApp alpha index) (.sort (.succ (.param `u))) + +@[simp] theorem ctorIndexedVecAppGetAppArgs (alpha index : Expr) : + (ctorIndexedVecApp alpha index).getAppArgs = #[alpha, index] := by + rfl + +@[simp] theorem ctorIndexedVecAppGetAppNumArgs (alpha index : Expr) : + (ctorIndexedVecApp alpha index).getAppNumArgs = 2 := by + rfl + +theorem inferTypeIndexedVecOnlyCore + (fuel : Nat) (lctx : LocalContext) (alpha index : Expr) + (hclosed : (ctorIndexedVecApp alpha index).hasLooseBVars = false) : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp alpha index) true + (TypeChecker.Methods.withFuel (fuel + 1)) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), + validationIndexedVecOnlyState alpha index) := by + unfold ctorIndexedVecApp at hclosed ⊢ + have hfn : + (((.const ``IndexedVec [.param `u] : Expr).app alpha).app index).getAppFn = + .const ``IndexedVec [.param `u] := by + rfl + have hargs : + (((.const ``IndexedVec [.param `u] : Expr).app alpha).app index).getAppArgs = + #[alpha, index] := by + rfl + unfold TypeChecker.Inner.inferType' + rw [hclosed] + simp [TypeChecker.Inner.inferApp, + TypeChecker.Inner.inferApp.loop, + hfn, hargs, ctorIndexedVecApp, + validationFamilyOnlyState, validationIndexedVecOnlyState, + validationInferOnlyInsert, + inferTypeFamilyOnlyCore, + indexedVecInfoTypeShape, vecFamilyTail, + Expr.instantiate1', + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +theorem ensureTypeMOfInferOnly + (context : AddInductive.Context) (e : Expr) (level : Level) + (finalState : TypeChecker.State) + (hrun : TypeChecker.Inner.inferType e true + (TypeChecker.Methods.withFuel context.fuel.recDepth) + context.toTypeChecker ({} : TypeChecker.State) = + .ok (.sort level, finalState)) : + TypeChecker.M.run context.env context.safety context.lctx + context.lparams context.fuel (TypeChecker.ensureType e) = + .ok (.sort level) := by + unfold TypeChecker.ensureType TypeChecker.inferType + TypeChecker.ensureSort TypeChecker.RecM.run TypeChecker.M.run + simp only [readThe, MonadReaderOf.read, ReaderT.read, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + Pure.pure, StateT.pure, Except.pure, StateT.run', + Functor.map, Except.map] + rw [show TypeChecker.Inner.inferType e true + (TypeChecker.Methods.withFuel context.fuel.recDepth) + { env := context.env, lctx := context.lctx, + safety := context.safety, lparams := context.lparams, + fuel := context.fuel } ({} : TypeChecker.State) = + .ok (.sort level, finalState) by + simpa [AddInductive.Context.toTypeChecker] using hrun] + rfl + +def validationNatOnlyState : TypeChecker.State := + validationInferOnlyInsert ({} : TypeChecker.State) + (.const ``Nat []) (.sort (.succ .zero)) + +theorem indexedVecValidationNatInferOnly : + TypeChecker.Inner.inferType (.const ``Nat []) true + (TypeChecker.Methods.withFuel + indexedVecCtorValidationContext.fuel.recDepth) + indexedVecCtorValidationContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), validationNatOnlyState) := by + change TypeChecker.Inner.inferType' (.const ``Nat []) true + (TypeChecker.Methods.withFuel 9999) + (tcContext indexedVecCtorValidationContext.lctx) + ({} : TypeChecker.State) = _ + simpa [validationNatOnlyState] using + (inferTypeNatOnlyCore 9999 indexedVecCtorValidationContext.lctx + ({} : TypeChecker.State) (by simp)) + +theorem indexedVecValidationNatEnsureTypeM : + TypeChecker.M.run indexedVecCtorValidationContext.env + indexedVecCtorValidationContext.safety + indexedVecCtorValidationContext.lctx + indexedVecCtorValidationContext.lparams + indexedVecCtorValidationContext.fuel + (TypeChecker.ensureType (.const ``Nat [])) = + .ok (.sort (.succ .zero)) := by + exact ensureTypeMOfInferOnly indexedVecCtorValidationContext + (.const ``Nat []) (.succ .zero) validationNatOnlyState + indexedVecValidationNatInferOnly + +def validationAlphaOnlyState : TypeChecker.State := + validationInferOnlyInsert ({} : TypeChecker.State) + indexedVecValidationAlpha (.sort (.succ (.param `u))) + +theorem indexedVecValidationAlphaInferOnly : + TypeChecker.Inner.inferType indexedVecValidationAlpha true + (TypeChecker.Methods.withFuel + indexedVecValidationNContext.fuel.recDepth) + indexedVecValidationNContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), validationAlphaOnlyState) := by + rw [indexedVecValidationAlphaShape] + change TypeChecker.Inner.inferType' + (.fvar indexedVecValidationAlphaId) true + (TypeChecker.Methods.withFuel 9999) + (tcContext indexedVecValidationNContext.lctx) + ({} : TypeChecker.State) = _ + simpa [validationAlphaOnlyState, + indexedVecValidationAlphaShape] using + (inferTypeFVarOnlyCore 9999 indexedVecValidationNContext.lctx + ({} : TypeChecker.State) indexedVecValidationAlphaId + (.sort (.succ (.param `u))) (by simp) + indexedVecValidationAlphaFindInN) + +theorem indexedVecValidationAlphaEnsureTypeM : + TypeChecker.M.run indexedVecValidationNContext.env + indexedVecValidationNContext.safety + indexedVecValidationNContext.lctx + indexedVecValidationNContext.lparams + indexedVecValidationNContext.fuel + (TypeChecker.ensureType indexedVecValidationAlpha) = + .ok (.sort (.succ (.param `u))) := by + exact ensureTypeMOfInferOnly indexedVecValidationNContext + indexedVecValidationAlpha (.succ (.param `u)) + validationAlphaOnlyState indexedVecValidationAlphaInferOnly + +theorem indexedVecValidationTailInferOnly : + TypeChecker.Inner.inferType + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) true + (TypeChecker.Methods.withFuel + indexedVecValidationHeadContext.fuel.recDepth) + indexedVecValidationHeadContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), + validationIndexedVecOnlyState indexedVecValidationAlpha + indexedVecValidationNExpr) := by + change TypeChecker.Inner.inferType' + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) true + (TypeChecker.Methods.withFuel 9999) + (tcContext indexedVecValidationHeadContext.lctx) + ({} : TypeChecker.State) = _ + exact inferTypeIndexedVecOnlyCore 9998 + indexedVecValidationHeadContext.lctx + indexedVecValidationAlpha indexedVecValidationNExpr + (by simp [ctorIndexedVecApp, Expr.hasLooseBVars, + Expr.looseBVarRange']) + +theorem indexedVecValidationTailEnsureTypeM : + TypeChecker.M.run indexedVecValidationHeadContext.env + indexedVecValidationHeadContext.safety + indexedVecValidationHeadContext.lctx + indexedVecValidationHeadContext.lparams + indexedVecValidationHeadContext.fuel + (TypeChecker.ensureType + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr)) = + .ok (.sort (.succ (.param `u))) := by + exact ensureTypeMOfInferOnly indexedVecValidationHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) (.succ (.param `u)) + (validationIndexedVecOnlyState indexedVecValidationAlpha + indexedVecValidationNExpr) + indexedVecValidationTailInferOnly + +theorem indexedVecValidationStatsParams : + indexedVecCandidateInductiveStats.params = + #[indexedVecValidationAlpha] := by + simpa [indexedVecValidationAlpha] using + indexedVecCandidateInductiveStats_params + +@[simp] theorem validationExprBneSelf (e : Expr) : + (e != e) = false := by + change (!Expr.eqv e e) = false + rw [show Expr.eqv e e = true by exact Expr.eqv_refl e] + rfl + +theorem indexedVecValidationAppIsValidIdx (index : Expr) + (hindex : AddInductive.hasIndOcc + indexedVecCandidateInductiveStats.indConsts index = false) : + AddInductive.isValidIndAppIdx indexedVecCandidateInductiveStats + (ctorIndexedVecApp indexedVecValidationAlpha index) 0 = true := by + have hparam : + (indexedVecValidationAlpha != indexedVecValidationAlpha) = false := by + change (!Expr.eqv indexedVecValidationAlpha + indexedVecValidationAlpha) = false + rw [show Expr.eqv indexedVecValidationAlpha + indexedVecValidationAlpha = true by + exact Expr.eqv_refl indexedVecValidationAlpha] + rfl + have hindex' : AddInductive.hasIndOcc + #[.const ``IndexedVec [.param `u]] index = false := by + simpa [indexedVecCandidateInductiveStats_indConsts] using hindex + simp +decide [AddInductive.isValidIndAppIdx, + indexedVecCandidateInductiveStats_nindices, + indexedVecValidationStatsParams, + indexedVecCandidateInductiveStats_indConsts, + ctorIndexedVecAppGetAppFn, ctorIndexedVecAppGetAppArgs, + hindex'] + +theorem indexedVecValidationAppIsValid (index : Expr) + (hindex : AddInductive.hasIndOcc + indexedVecCandidateInductiveStats.indConsts index = false) : + AddInductive.isValidIndApp? indexedVecCandidateInductiveStats + (ctorIndexedVecApp indexedVecValidationAlpha index) = some 0 := by + exact AddInductive.isValidIndApp?_singleton_zero + indexedVecCandidateInductiveStats + (ctorIndexedVecApp indexedVecValidationAlpha index) + (by simp [indexedVecCandidateInductiveStats_indConsts]) + (indexedVecValidationAppIsValidIdx index hindex) + +theorem indexedVecValidationZeroHasNoIndOcc : + AddInductive.hasIndOcc indexedVecCandidateInductiveStats.indConsts + (.const ``Nat.zero []) = false := by + simp [AddInductive.hasIndOcc, + indexedVecCandidateInductiveStats_indConsts, Expr.constName!] + +theorem indexedVecValidationNHasNoIndOcc : + AddInductive.hasIndOcc indexedVecCandidateInductiveStats.indConsts + indexedVecValidationNExpr = false := by + simp [AddInductive.hasIndOcc, + indexedVecCandidateInductiveStats_indConsts, + indexedVecValidationNExprShape] + +theorem indexedVecValidationSuccNHasNoIndOcc : + AddInductive.hasIndOcc indexedVecCandidateInductiveStats.indConsts + (replaySuccApp indexedVecValidationNExpr) = false := by + simp [AddInductive.hasIndOcc, + indexedVecCandidateInductiveStats_indConsts, + replaySuccApp, Expr.constName!] + +theorem indexedVecValidationNilResultIsValid : + AddInductive.isValidIndAppIdx indexedVecCandidateInductiveStats + indexedVecValidationNilResult 0 = true := by + exact indexedVecValidationAppIsValidIdx (.const ``Nat.zero []) + indexedVecValidationZeroHasNoIndOcc + +theorem indexedVecValidationConsResultIsValid : + AddInductive.isValidIndAppIdx indexedVecCandidateInductiveStats + indexedVecValidationConsResult 0 = true := by + exact indexedVecValidationAppIsValidIdx + (replaySuccApp indexedVecValidationNExpr) + indexedVecValidationSuccNHasNoIndOcc + +theorem indexedVecValidationNatHasNoIndOcc : + AddInductive.hasIndOcc indexedVecCandidateInductiveStats.indConsts + (.const ``Nat []) = false := by + simp [AddInductive.hasIndOcc, + indexedVecCandidateInductiveStats_indConsts, Expr.constName!] + +theorem indexedVecValidationAlphaHasNoIndOcc : + AddInductive.hasIndOcc indexedVecCandidateInductiveStats.indConsts + indexedVecValidationAlpha = false := by + simp [AddInductive.hasIndOcc, + indexedVecCandidateInductiveStats_indConsts, + indexedVecValidationAlphaShape] + +theorem indexedVecValidationTailHasIndOcc : + AddInductive.hasIndOcc indexedVecCandidateInductiveStats.indConsts + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) = true := by + simp [AddInductive.hasIndOcc, + indexedVecCandidateInductiveStats_indConsts, + ctorIndexedVecApp, Expr.constName!] + +theorem indexedVecValidationNatPositivity : + AddInductive.checkPositivity indexedVecCandidateInductiveStats + (.const ``Nat []) indexedVecKernelCons.name 1 + indexedVecCtorValidationContext = .ok () := by + unfold AddInductive.checkPositivity + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show indexedVecCtorValidationContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkPositivity.loop + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [show TypeChecker.M.run indexedVecCtorValidationContext.env + indexedVecCtorValidationContext.safety + indexedVecCtorValidationContext.lctx + indexedVecCtorValidationContext.lparams + indexedVecCtorValidationContext.fuel + (TypeChecker.whnf (.const ``Nat [])) = + .ok (.const ``Nat []) by + change TypeChecker.M.run ctorEnv .safe + indexedVecCtorValidationContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf (.const ``Nat [])) = .ok (.const ``Nat []) + exact ctorNatWhnfM indexedVecCtorValidationContext.lctx] + simp only [Except.bind] + rw [indexedVecValidationNatHasNoIndOcc] + simp only [Bool.not_false, if_true, + ReaderT.pure, Pure.pure, Except.pure] + +theorem indexedVecValidationAlphaPositivity : + AddInductive.checkPositivity indexedVecCandidateInductiveStats + indexedVecValidationAlpha indexedVecKernelCons.name 2 + indexedVecValidationNContext = .ok () := by + unfold AddInductive.checkPositivity + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show indexedVecValidationNContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkPositivity.loop + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [show TypeChecker.M.run indexedVecValidationNContext.env + indexedVecValidationNContext.safety + indexedVecValidationNContext.lctx + indexedVecValidationNContext.lparams + indexedVecValidationNContext.fuel + (TypeChecker.whnf indexedVecValidationAlpha) = + .ok indexedVecValidationAlpha by + rw [indexedVecValidationAlphaShape] + change TypeChecker.M.run ctorEnv .safe + indexedVecValidationNContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf (.fvar indexedVecValidationAlphaId)) = + .ok (.fvar indexedVecValidationAlphaId) + exact ctorFVarWhnfM indexedVecValidationNContext.lctx + indexedVecValidationAlphaId indexedVecValidationAlphaFindInN] + simp only [Except.bind] + rw [indexedVecValidationAlphaHasNoIndOcc] + simp only [Bool.not_false, if_true, + ReaderT.pure, Pure.pure, Except.pure] + +theorem indexedVecValidationTailPositivity : + AddInductive.checkPositivity indexedVecCandidateInductiveStats + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + indexedVecKernelCons.name 3 indexedVecValidationHeadContext = + .ok () := by + unfold AddInductive.checkPositivity + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show indexedVecValidationHeadContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkPositivity.loop + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [show TypeChecker.M.run indexedVecValidationHeadContext.env + indexedVecValidationHeadContext.safety + indexedVecValidationHeadContext.lctx + indexedVecValidationHeadContext.lparams + indexedVecValidationHeadContext.fuel + (TypeChecker.whnf + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr)) = + .ok (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) by + change TypeChecker.M.run ctorEnv .safe + indexedVecValidationHeadContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr)) = + .ok (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + exact ctorIndexedVecWhnfM indexedVecValidationHeadContext.lctx + indexedVecValidationAlpha indexedVecValidationNExpr] + simp only [Except.bind] + rw [indexedVecValidationTailHasIndOcc] + simp only [Bool.not_true, Bool.false_eq_true, if_false, Pure.pure] + rw [indexedVecValidationAppIsValid indexedVecValidationNExpr + indexedVecValidationNHasNoIndOcc] + rfl + +theorem indexedVecValidationNilLoopTerminal : + AddInductive.checkConstructorType.loop + indexedVecCandidateInductiveStats false 0 + indexedVecKernelNil.name indexedVecValidationNilResult 1 999 + indexedVecCtorValidationContext = .ok () := by + rw [show 999 = 998 + 1 by rfl] + have hvalid : AddInductive.isValidIndAppIdx + indexedVecCandidateInductiveStats + ((.const ``IndexedVec [.param `u] : Expr).app + (.fvar indexedVecValidationAlphaId) |>.app + (.const ``Nat.zero [])) 0 = + true := by + simpa [indexedVecValidationNilResult, ctorIndexedVecApp, + indexedVecValidationAlphaShape] using + indexedVecValidationNilResultIsValid + unfold indexedVecValidationNilResult ctorIndexedVecApp + unfold AddInductive.checkConstructorType.loop + simp [hvalid, + ReaderT.pure, Pure.pure, Except.pure] + +theorem indexedVecValidationNilLoop : + AddInductive.checkConstructorType.loop + indexedVecCandidateInductiveStats false 0 + indexedVecKernelNil.name indexedVecKernelNil.type 0 + indexedVecCtorValidationContext.fuel.inductiveFuel + indexedVecCtorValidationContext = .ok () := by + rw [show indexedVecCtorValidationContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkConstructorType.loop + simp only [indexedVecKernelNil, indexedVecNilInfo, + ConstantInfo.name, ConstantInfo.type, ConstantInfo.toConstantVal] + rw [show indexedVecCandidateInductiveStats.params[0]? = + some indexedVecValidationAlpha by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind] + rw [indexedVecValidationGetTypeAlpha] + simp only [Except.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationParamIsDefEq] + simp only [if_true] + simpa [indexedVecValidationNilResult, ctorIndexedVecApp, + indexedVecKernelNil, indexedVecNilInfo, ConstantInfo.name, + ConstantInfo.toConstantVal, + Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using indexedVecValidationNilLoopTerminal + +@[simp] theorem indexedVecValidationConsumeNat : + AddInductive.consumeTypeAnnotations (.const ``Nat []) = + .const ``Nat [] := by + simp [AddInductive.consumeTypeAnnotations] + +@[simp] theorem indexedVecValidationConsumeAlpha : + AddInductive.consumeTypeAnnotations indexedVecValidationAlpha = + indexedVecValidationAlpha := by + rw [indexedVecValidationAlphaShape] + simp [AddInductive.consumeTypeAnnotations] + +@[simp] theorem indexedVecValidationConsumeTail : + AddInductive.consumeTypeAnnotations + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) = + ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr := by + simp [ctorIndexedVecApp, AddInductive.consumeTypeAnnotations] + +theorem indexedVecValidationConsLoopTerminal : + AddInductive.checkConstructorType.loop + indexedVecCandidateInductiveStats false 0 + indexedVecKernelCons.name indexedVecValidationConsResult 4 996 + indexedVecValidationTailContext = .ok () := by + rw [show 996 = 995 + 1 by rfl] + have hvalid : AddInductive.isValidIndAppIdx + indexedVecCandidateInductiveStats + (((.const ``IndexedVec [.param `u] : Expr).app + (.fvar indexedVecValidationAlphaId)).app + ((.const ``Nat.succ [] : Expr).app + (.fvar indexedVecValidationNId))) 0 = true := by + simpa [indexedVecValidationConsResult, ctorIndexedVecApp, + replaySuccApp, indexedVecValidationAlphaShape, + indexedVecValidationNExprShape] using + indexedVecValidationConsResultIsValid + unfold indexedVecValidationConsResult ctorIndexedVecApp replaySuccApp + unfold AddInductive.checkConstructorType.loop + simp [hvalid, ReaderT.pure, Pure.pure, Except.pure] + +theorem indexedVecValidationConsLoopTail : + AddInductive.checkConstructorType.loop + indexedVecCandidateInductiveStats false 0 + indexedVecKernelCons.name indexedVecValidationConsAfterHead 3 997 + indexedVecValidationHeadContext = .ok () := by + rw [show 997 = 996 + 1 by rfl] + unfold indexedVecValidationConsAfterHead + unfold AddInductive.checkConstructorType.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[3]? = none by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationTailEnsureTypeM] + simp only [Except.bind] + rw [if_pos (show AddInductive.levelStructGe + indexedVecCandidateInductiveStats.resultLevel + (Expr.sort (.succ (.param `u))).sortLevel! = true from by + simp [Expr.sortLevel!, indexedVecCandidateInductiveStats_resultLevel, + AddInductive.levelStructGe, AddInductive.levelStructEq])] + simp only [↓reduceIte, Bool.not_false, ReaderT.bind, Bind.bind, Except.bind] + rw [indexedVecValidationTailPositivity] + rw [AddInductive.withLocalDecl_apply] + rw [indexedVecValidationConsumeTail] + rw [show (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)).instantiate1 + indexedVecValidationHeadContext.freshExpr = + indexedVecValidationConsResult by + simp [indexedVecValidationConsResult, ctorIndexedVecApp, + replaySuccApp, Expr.instantiate1_eq, Expr.instantiate1']] + simpa [indexedVecValidationTailContext, + AddInductive.Context.pushLocalDecl, + ReaderT.pure, Pure.pure, Except.pure] using + indexedVecValidationConsLoopTerminal + +theorem indexedVecValidationConsLoopHead : + AddInductive.checkConstructorType.loop + indexedVecCandidateInductiveStats false 0 + indexedVecKernelCons.name indexedVecValidationConsAfterN 2 998 + indexedVecValidationNContext = .ok () := by + rw [show 998 = 997 + 1 by rfl] + unfold indexedVecValidationConsAfterN + unfold AddInductive.checkConstructorType.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[2]? = none by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationAlphaEnsureTypeM] + simp only [Except.bind] + rw [if_pos (show AddInductive.levelStructGe + indexedVecCandidateInductiveStats.resultLevel + (Expr.sort (.succ (.param `u))).sortLevel! = true from by + simp [Expr.sortLevel!, indexedVecCandidateInductiveStats_resultLevel, + AddInductive.levelStructGe, AddInductive.levelStructEq])] + simp only [↓reduceIte, Bool.not_false, ReaderT.bind, Bind.bind, Except.bind] + rw [indexedVecValidationAlphaPositivity] + rw [AddInductive.withLocalDecl_apply] + rw [indexedVecValidationConsumeAlpha] + rw [show + ((.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)) + .default : Expr).instantiate1 + indexedVecValidationNContext.freshExpr) = + indexedVecValidationConsAfterHead by + simp [indexedVecValidationConsAfterHead, + ctorIndexedVecApp, replaySuccApp, + Expr.instantiate1_eq, Expr.instantiate1']] + simpa [indexedVecValidationHeadContext, + AddInductive.Context.pushLocalDecl, + ReaderT.pure, Pure.pure, Except.pure] using + indexedVecValidationConsLoopTail + +theorem indexedVecValidationConsLoopN : + AddInductive.checkConstructorType.loop + indexedVecCandidateInductiveStats false 0 + indexedVecKernelCons.name indexedVecValidationConsAfterParam 1 999 + indexedVecCtorValidationContext = .ok () := by + rw [show 999 = 998 + 1 by rfl] + rw [indexedVecValidationConsAfterParamExplicitShape] + unfold AddInductive.checkConstructorType.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[1]? = none by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationNatEnsureTypeM] + simp only [Except.bind] + rw [if_pos (show AddInductive.levelStructGe + indexedVecCandidateInductiveStats.resultLevel + (Expr.sort (.succ .zero)).sortLevel! = true from by + simp [Expr.sortLevel!, indexedVecCandidateInductiveStats_resultLevel, + AddInductive.levelStructGe])] + simp only [↓reduceIte, Bool.not_false, ReaderT.bind, Bind.bind, Except.bind] + rw [indexedVecValidationNatPositivity] + rw [AddInductive.withLocalDecl_apply] + rw [indexedVecValidationConsumeNat] + rw [show + ((.forallE consHeadName indexedVecValidationAlpha + (.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) + .default) + .default : Expr).instantiate1 + indexedVecCtorValidationContext.freshExpr) = + indexedVecValidationConsAfterN by + simp [indexedVecValidationConsAfterN, + ctorIndexedVecApp, replaySuccApp, + indexedVecValidationNExpr, + AddInductive.Context.freshExpr, + Expr.instantiate1_eq, Expr.instantiate1']] + simpa [indexedVecValidationNContext, + AddInductive.Context.pushLocalDecl, + ReaderT.pure, Pure.pure, Except.pure] using + indexedVecValidationConsLoopHead + +theorem indexedVecValidationConsLoop : + AddInductive.checkConstructorType.loop + indexedVecCandidateInductiveStats false 0 + indexedVecKernelCons.name indexedVecKernelCons.type 0 + indexedVecCtorValidationContext.fuel.inductiveFuel + indexedVecCtorValidationContext = .ok () := by + rw [show indexedVecCtorValidationContext.fuel.inductiveFuel = + 999 + 1 by rfl] + rw [show indexedVecKernelCons.type = consCtorTypeRaw by + simpa [indexedVecKernelCons] using consInfoTypeShape] + unfold consCtorTypeRaw + unfold AddInductive.checkConstructorType.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[0]? = + some indexedVecValidationAlpha by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind] + rw [indexedVecValidationGetTypeAlpha] + simp only [Except.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationParamIsDefEq] + simp only [if_true] + simpa [indexedVecValidationConsAfterParam] using + indexedVecValidationConsLoopN + +theorem indexedVecValidationNilUniverseLoopTerminal : + AddInductive.checkConstructorUniverseSemantics.loop + indexedVecCandidateInductiveStats indexedVecValidationNilResult 1 999 + indexedVecCtorValidationContext = .ok () := by + rw [show 999 = 998 + 1 by rfl] + unfold AddInductive.checkConstructorUniverseSemantics.loop + rfl + +theorem indexedVecValidationNilUniverseLoop : + AddInductive.checkConstructorUniverseSemantics.loop + indexedVecCandidateInductiveStats indexedVecKernelNil.type 0 + indexedVecCtorValidationContext.fuel.inductiveFuel + indexedVecCtorValidationContext = .ok () := by + rw [show indexedVecCtorValidationContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkConstructorUniverseSemantics.loop + simp only [indexedVecKernelNil, indexedVecNilInfo, + ConstantInfo.type, ConstantInfo.toConstantVal] + rw [show indexedVecCandidateInductiveStats.params[0]? = + some indexedVecValidationAlpha by + simp [indexedVecValidationStatsParams]] + simpa [indexedVecValidationNilResult, ctorIndexedVecApp, + indexedVecKernelNil, indexedVecNilInfo, ConstantInfo.toConstantVal, + Expr.instantiate1_eq, Expr.instantiate1', + Expr.liftLooseBVars_zero] using + indexedVecValidationNilUniverseLoopTerminal + +theorem indexedVecValidationConsUniverseLoopTerminal : + AddInductive.checkConstructorUniverseSemantics.loop + indexedVecCandidateInductiveStats indexedVecValidationConsResult 4 996 + indexedVecValidationTailContext = .ok () := by + rw [show 996 = 995 + 1 by rfl] + unfold AddInductive.checkConstructorUniverseSemantics.loop + rfl + +theorem indexedVecValidationConsUniverseLoopTail : + AddInductive.checkConstructorUniverseSemantics.loop + indexedVecCandidateInductiveStats indexedVecValidationConsAfterHead 3 997 + indexedVecValidationHeadContext = .ok () := by + rw [show 997 = 996 + 1 by rfl] + unfold indexedVecValidationConsAfterHead + unfold AddInductive.checkConstructorUniverseSemantics.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[3]? = none by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind, AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationTailEnsureTypeM] + simp only [Except.bind] + rw [if_pos (show AddInductive.constructorUniverseSemanticGe + indexedVecCandidateInductiveStats.resultLevel + (Expr.sort (.succ (.param `u))).sortLevel! = true from by + simp [Expr.sortLevel!, AddInductive.constructorUniverseSemanticGe, + indexedVecCandidateInductiveStats_resultLevel, + AddInductive.levelStructGe, AddInductive.levelStructEq])] + rw [AddInductive.withLocalDecl_apply] + simpa [indexedVecValidationTailContext, + AddInductive.Context.pushLocalDecl, + AddInductive.consumeTypeAnnotations, + indexedVecValidationConsResult, ctorIndexedVecApp, + replaySuccApp, Expr.instantiate1_eq, Expr.instantiate1'] using + indexedVecValidationConsUniverseLoopTerminal + +theorem indexedVecValidationConsUniverseLoopHead : + AddInductive.checkConstructorUniverseSemantics.loop + indexedVecCandidateInductiveStats indexedVecValidationConsAfterN 2 998 + indexedVecValidationNContext = .ok () := by + rw [show 998 = 997 + 1 by rfl] + unfold indexedVecValidationConsAfterN + unfold AddInductive.checkConstructorUniverseSemantics.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[2]? = none by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind, AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationAlphaEnsureTypeM] + simp only [Except.bind] + rw [if_pos (show AddInductive.constructorUniverseSemanticGe + indexedVecCandidateInductiveStats.resultLevel + (Expr.sort (.succ (.param `u))).sortLevel! = true from by + simp [Expr.sortLevel!, AddInductive.constructorUniverseSemanticGe, + indexedVecCandidateInductiveStats_resultLevel, + AddInductive.levelStructGe, AddInductive.levelStructEq])] + rw [AddInductive.withLocalDecl_apply] + simpa [indexedVecValidationHeadContext, + AddInductive.Context.pushLocalDecl, + AddInductive.consumeTypeAnnotations, + indexedVecValidationConsAfterHead, + ctorIndexedVecApp, replaySuccApp, + Expr.instantiate1_eq, Expr.instantiate1'] using + indexedVecValidationConsUniverseLoopTail + +theorem indexedVecValidationConsUniverseLoopN : + AddInductive.checkConstructorUniverseSemantics.loop + indexedVecCandidateInductiveStats indexedVecValidationConsAfterParam 1 999 + indexedVecCtorValidationContext = .ok () := by + rw [show 999 = 998 + 1 by rfl] + rw [indexedVecValidationConsAfterParamExplicitShape] + unfold AddInductive.checkConstructorUniverseSemantics.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[1]? = none by + simp [indexedVecValidationStatsParams]] + simp only [ReaderT.bind, Bind.bind, AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationNatEnsureTypeM] + simp only [Except.bind] + rw [if_pos (show AddInductive.constructorUniverseSemanticGe + indexedVecCandidateInductiveStats.resultLevel + (Expr.sort (.succ .zero)).sortLevel! = true from by + simp [Expr.sortLevel!, AddInductive.constructorUniverseSemanticGe, + indexedVecCandidateInductiveStats_resultLevel, + AddInductive.levelStructGe])] + rw [AddInductive.withLocalDecl_apply] + simpa [indexedVecValidationNContext, + AddInductive.Context.pushLocalDecl, + AddInductive.consumeTypeAnnotations, + indexedVecValidationConsAfterN, + ctorIndexedVecApp, replaySuccApp, + indexedVecValidationNExpr, + AddInductive.Context.freshExpr, + Expr.instantiate1_eq, Expr.instantiate1'] using + indexedVecValidationConsUniverseLoopHead + +theorem indexedVecValidationConsUniverseLoop : + AddInductive.checkConstructorUniverseSemantics.loop + indexedVecCandidateInductiveStats indexedVecKernelCons.type 0 + indexedVecCtorValidationContext.fuel.inductiveFuel + indexedVecCtorValidationContext = .ok () := by + rw [show indexedVecCtorValidationContext.fuel.inductiveFuel = + 999 + 1 by rfl] + rw [show indexedVecKernelCons.type = consCtorTypeRaw by + simpa [indexedVecKernelCons] using consInfoTypeShape] + unfold consCtorTypeRaw + unfold AddInductive.checkConstructorUniverseSemantics.loop + simp only + rw [show indexedVecCandidateInductiveStats.params[0]? = + some indexedVecValidationAlpha by + simp [indexedVecValidationStatsParams]] + simpa [indexedVecValidationConsAfterParam] using + indexedVecValidationConsUniverseLoopN + +theorem indexedVecValidationNilUniverseRun : + AddInductive.checkConstructorUniverseSemantics + indexedVecCandidateInductiveStats indexedVecKernelNil.type + indexedVecCtorValidationContext = .ok () := by + unfold AddInductive.checkConstructorUniverseSemantics + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using indexedVecValidationNilUniverseLoop + +theorem indexedVecValidationConsUniverseRun : + AddInductive.checkConstructorUniverseSemantics + indexedVecCandidateInductiveStats indexedVecKernelCons.type + indexedVecCtorValidationContext = .ok () := by + unfold AddInductive.checkConstructorUniverseSemantics + simpa only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] using indexedVecValidationConsUniverseLoop + +/-- Both source-ordered `IndexedVec` constructors pass the executable verified +universe gate. -/ +theorem indexedVecValidationCheckConstructorUniverseSemantics : + AddInductive.checkConstructorUniverseListSemantics + indexedVecCandidateInductiveStats indexedVecKernelType.ctors + indexedVecCtorValidationContext = .ok () := by + unfold AddInductive.checkConstructorUniverseListSemantics + simp only [indexedVecKernelType, ReaderT.bind, Bind.bind] + rw [indexedVecValidationNilUniverseRun] + simp only [Except.bind] + unfold AddInductive.checkConstructorUniverseListSemantics + simp only [ReaderT.bind, Bind.bind] + rw [indexedVecValidationConsUniverseRun] + rfl + +theorem indexedVecValidationGetEnvM : + TypeChecker.M.run indexedVecCtorValidationContext.env + indexedVecCtorValidationContext.safety + indexedVecCtorValidationContext.lctx + indexedVecCtorValidationContext.lparams + indexedVecCtorValidationContext.fuel TypeChecker.getEnv = + .ok ctorEnv := by + rfl + +theorem indexedVecValidationEmptyDoesNotContainNil : + (∅ : NameSet).contains indexedVecKernelNil.name = false := by + simp +decide + +theorem indexedVecValidationNilSetDoesNotContainCons : + ((∅ : NameSet).insert indexedVecKernelNil.name).contains + indexedVecKernelCons.name = false := by + simp only [indexedVecKernelNil, indexedVecKernelCons, + indexedVecNilInfo, indexedVecConsInfo, + ConstantInfo.name, ConstantInfo.toConstantVal, + NameSet.contains, NameSet.insert] + rw [Std.TreeSet.contains_insert (t := (∅ : NameSet))] + simp +decide + +set_option linter.unusedSimpArgs false in +theorem indexedVecValidationCheckConstructors : + AddInductive.checkConstructors #[indexedVecKernelType] + indexedVecCandidateInductiveStats false + indexedVecCtorValidationContext = .ok () := by + unfold AddInductive.checkConstructors + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationGetEnvM] + simp only [Except.bind] + unfold AddInductive.checkConstructorsLoop AddInductive.checkConstructorFold + simp only [indexedVecKernelType, List.toList_toArray, + ReaderT.bind, Bind.bind, Except.bind] + rw [indexedVecValidationEmptyDoesNotContainNil] + simp only [Bool.false_eq_true, if_false, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + rw [indexedVecNilNoMVarNoFVar] + simp only [ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure, AddInductive.liftExcept_apply] + rw [AddInductive.withEmptyLocalContext_apply] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationNilRootCheckTypeM] + unfold AddInductive.checkConstructorType + simp only [Except.bind, readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, Except.pure] + rw [indexedVecValidationNilLoop] + unfold AddInductive.checkConstructorFold + simp only [Except.bind, ReaderT.pure, Pure.pure, Except.pure] + rw [indexedVecValidationNilSetDoesNotContainCons] + simp only [Bool.false_eq_true, if_false, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + rw [indexedVecConsNoMVarNoFVar] + simp only [ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure, AddInductive.liftExcept_apply] + rw [AddInductive.withEmptyLocalContext_apply] + rw [AddInductive.liftTypeChecker_apply] + rw [indexedVecValidationConsRootCheckTypeM] + unfold AddInductive.checkConstructorType + simp only [Except.bind, readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, Except.pure] + rw [indexedVecValidationConsLoop] + unfold AddInductive.checkConstructorFold + rfl + +/-- The complete one-parameter, one-index IndexedVec request produces the +exact ordered family/nil/cons normalization candidate. -/ +theorem indexedVecNormalizationCandidateProduced : + AddInductive.buildNormalizationCandidate 1 + [indexedVecKernelType] 0 false + indexedVecFamilyCandidateContext = + .ok indexedVecNormalizationCandidate := by + unfold AddInductive.buildNormalizationCandidate + rw [indexedVec_checkInductiveTypes] + simp only [ReaderT.bind, Bind.bind] + rw [show + (withReader (fun _ : AddInductive.Context => + { indexedVecFamilyCandidateContext with lctx := {} }) + (AddInductive.normalizeCandidateFamilyTypeList + [indexedVecKernelType])) indexedVecFamilyCandidate.trace.terminalContext = + .ok (.cons indexedVecFamilyListCandidate.familyType .nil) by + simpa using indexedVecFamilyTypeListCandidateProduced] + simp only [Except.bind] + rw [indexedVecDeclareFromTerminal] + unfold AddInductive.withEnv + change (ReaderT.bind + (AddInductive.checkConstructors #[indexedVecKernelType] + indexedVecCandidateInductiveStats false) + (fun _ => ReaderT.bind + (fun _ : AddInductive.Context => + AddInductive.normalizeCandidateFamilyList + (.cons indexedVecFamilyListCandidate.familyType .nil) + ctorContext) + (fun families => pure + (⟨families⟩ : AddInductive.NormalizationCandidate + [indexedVecKernelType])))) + indexedVecCtorValidationContext = _ + simp only [ReaderT.bind, Bind.bind] + rw [indexedVecValidationCheckConstructors] + simp only [Except.bind] + rw [indexedVecFamilyListCandidateProduced] + rfl + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecNormalizationCandidateProduced [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean b/Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean new file mode 100644 index 000000000..1a12306a7 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean @@ -0,0 +1,3540 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.IndexedVecOuterReplay + +/-! +# Complete semantic replay of the IndexedVec normalization candidate + +This module connects the exact executable family/`nil`/`cons` candidate +produced by `buildNormalizationCandidate` to its Theory generation +certificate and the E1 kernel-environment replay. Every retained candidate +node is interpreted in its exact pre-family or post-family verifier context; +the final transaction therefore consumes the certificate projected from the +same producer-selected package rather than an independently supplied +well-formedness proof. +-/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta +open Ix.Theory.Named.InductiveFixtures +open IndexedVecConsReplay + +theorem indexedVecSemanticNatHasPrimitives : VEnv.HasPrimitives natFinalEnv := by + have absent (n : Name) (hlookup : natFinalEnv.constants n = none) : + ¬ natFinalEnv.contains n := by + rintro ⟨ci, hci⟩ + rw [hlookup] at hci + contradiction + refine { + bool := fun h => (absent ``Bool rfl h).elim + boolFalse := fun h => by + change none = some _ at h + contradiction + boolTrue := fun h => by + change none = some _ at h + contradiction + nat := fun _ => ⟨⟨_, rfl⟩, ⟨_, rfl⟩⟩ + natZero := fun h => by + change some natType.ctors[0].toVConstant = some _ at h + exact (Option.some.inj h).symm + natSucc := fun h => by + change some natType.ctors[1].toVConstant = some _ at h + exact (Option.some.inj h).symm + natAdd := fun h => (absent ``Nat.add rfl h).elim + natSub := fun h => (absent ``Nat.sub rfl h).elim + natMul := fun h => (absent ``Nat.mul rfl h).elim + natPow := fun h => (absent ``Nat.pow rfl h).elim + natGcd := fun h => (absent ``Nat.gcd rfl h).elim + natMod := fun h => (absent ``Nat.mod rfl h).elim + natDiv := fun h => (absent ``Nat.div rfl h).elim + natBEq := fun h => (absent ``Nat.beq rfl h).elim + natBLE := fun h => (absent ``Nat.ble rfl h).elim + natLAnd := fun h => (absent ``Nat.land rfl h).elim + natLOr := fun h => (absent ``Nat.lor rfl h).elim + natXor := fun h => (absent ``Nat.xor rfl h).elim + natShiftLeft := fun h => (absent ``Nat.shiftLeft rfl h).elim + natShiftRight := fun h => (absent ``Nat.shiftRight rfl h).elim + charOfNat := fun h => by + change none = some _ at h + contradiction + stringOfList := fun h => by + change none = some _ at h + contradiction } + +theorem indexedVecSemanticNatSafePrimitives : + indexedVecKernelEnv.find? n = some ci → + Kernel.Environment.primitives.contains n → + ci.safety = .safe ∧ ci.levelParams = [] := by + intro hfind hprim + change natMap.find?' n = some ci at hfind + rw [natMap_wf.find?'_eq_find?, natMap, + natCtorMap_wf.find?_insert] at hfind + split at hfind + · rename_i heq + simp at heq + subst n + simp at hfind + subst ci + simp [Kernel.Environment.primitives, NameSet.ofList] at hprim + simp +decide [NameSet.contains] at hprim + · rw [natCtorMap, natZeroMap_wf.find?_insert] at hfind + split at hfind + · rename_i heq + simp at heq + subst n + simp at hfind + subst ci + exact ⟨rfl, rfl⟩ + · rw [natZeroMap, natTypeMap_wf.find?_insert] at hfind + split at hfind + · rename_i heq + simp at heq + subst n + simp at hfind + subst ci + exact ⟨rfl, rfl⟩ + · rw [natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + at hfind + split at hfind + · rename_i heq + simp at heq + subst n + simp at hfind + subst ci + exact ⟨rfl, rfl⟩ + · simp [SMap.find?] at hfind + +theorem indexedVecKernelEnv_noProjectionReady (name : Name) : + indexedVecKernelEnv.isProjectionReadyStructure name = false := by + simp only [indexedVecKernelEnv, + Kernel.Environment.isProjectionReadyStructure, + Kernel.Environment.ofConstants] + simp only [natMap_wf.find?'_eq_find?] + simp only [natMap, natCtorMap_wf.find?_insert] + simp only [natCtorMap, natZeroMap_wf.find?_insert] + simp only [natZeroMap, natTypeMap_wf.find?_insert] + simp only [natTypeMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + by_cases hRec : ``Nat.rec = name + · subst name + simp [natRecInfo] + · by_cases hSucc : ``Nat.succ = name + · subst name + simp [hRec, natSuccInfo] + · by_cases hZero : ``Nat.zero = name + · subst name + simp [hRec, hSucc, natZeroInfo] + · by_cases hNat : ``Nat = name + · subst name + simp [hRec, hSucc, hZero, natInfo] + · simp [hRec, hSucc, hZero, hNat, SMap.find?] + +theorem indexedVecKernelEnv_noStructureEta (name : Name) : + indexedVecKernelEnv.isNonRecStructure name = false := by + simp only [indexedVecKernelEnv, Kernel.Environment.isNonRecStructure, + Kernel.Environment.ofConstants, Kernel.Environment.find?] + simp only [natMap_wf.find?'_eq_find?] + simp only [natMap, natCtorMap_wf.find?_insert] + simp only [natCtorMap, natZeroMap_wf.find?_insert] + simp only [natZeroMap, natTypeMap_wf.find?_insert] + simp only [natTypeMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + by_cases hRec : ``Nat.rec = name + · subst name + simp [natRecInfo] + · by_cases hSucc : ``Nat.succ = name + · subst name + simp [hRec, natSuccInfo] + · by_cases hZero : ``Nat.zero = name + · subst name + simp [hRec, hSucc, natZeroInfo] + · by_cases hNat : ``Nat = name + · subst name + simp [hRec, hSucc, hZero, natInfo] + · simp [hRec, hSucc, hZero, hNat, SMap.find?] + +theorem indexedVecTypeEnv_noProjectionReady (name : Name) : + ctorContext.env.isProjectionReadyStructure name = false := by + simp only [ctorContext, ctorEnv, + Kernel.Environment.isProjectionReadyStructure, + Kernel.Environment.ofConstants] + simp only [indexedVecTypeMap_wf.find?'_eq_find?] + simp only [indexedVecTypeMap, natMap_wf.find?_insert] + simp only [natMap, natCtorMap_wf.find?_insert] + simp only [natCtorMap, natZeroMap_wf.find?_insert] + simp only [natZeroMap, natTypeMap_wf.find?_insert] + simp only [natTypeMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + by_cases hVec : ``IndexedVec = name + · subst name + simp [indexedVecInfo] + · by_cases hRec : ``Nat.rec = name + · subst name + simp [hVec, natRecInfo] + · by_cases hSucc : ``Nat.succ = name + · subst name + simp [hVec, hRec, natSuccInfo] + · by_cases hZero : ``Nat.zero = name + · subst name + simp [hVec, hRec, hSucc, natZeroInfo] + · by_cases hNat : ``Nat = name + · subst name + simp [hVec, hRec, hSucc, hZero, natInfo] + · simp [hVec, hRec, hSucc, hZero, hNat, SMap.find?] + +theorem indexedVecTypeEnv_noStructureEta (name : Name) : + ctorContext.env.isNonRecStructure name = false := by + simp only [ctorContext, ctorEnv, Kernel.Environment.isNonRecStructure, + Kernel.Environment.ofConstants, Kernel.Environment.find?] + simp only [indexedVecTypeMap_wf.find?'_eq_find?] + simp only [indexedVecTypeMap, natMap_wf.find?_insert] + simp only [natMap, natCtorMap_wf.find?_insert] + simp only [natCtorMap, natZeroMap_wf.find?_insert] + simp only [natZeroMap, natTypeMap_wf.find?_insert] + simp only [natTypeMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + by_cases hVec : ``IndexedVec = name + · subst name + simp [indexedVecInfo] + · by_cases hRec : ``Nat.rec = name + · subst name + simp [hVec, natRecInfo] + · by_cases hSucc : ``Nat.succ = name + · subst name + simp [hVec, hRec, natSuccInfo] + · by_cases hZero : ``Nat.zero = name + · subst name + simp [hVec, hRec, hSucc, natZeroInfo] + · by_cases hNat : ``Nat = name + · subst name + simp [hVec, hRec, hSucc, hZero, natInfo] + · simp [hVec, hRec, hSucc, hZero, hNat, SMap.find?] + +private theorem addConst_constants {env env' : VEnv} {name : Name} + {ci : VConstant} (hadd : env.addConst name ci = some env') (query : Name) : + env'.constants query = + if name = query then some ci else env.constants query := by + unfold VEnv.addConst at hadd + split at hadd <;> cases hadd + rfl + +private theorem structureView_nparams_eq_zero_of_nat + {env : VEnv} {view : VStructureView} (hview : view.WF env) + (hname : ``Nat = view.name) + (hNat : env.constants ``Nat = some natType.toVConstant) : + view.nparams = 0 := by + have hfamily := hview.family + rw [← hname, hNat] at hfamily + have hsourceType : view.generation.block.sourceType.type = natType.type := + congrArg VConstant.type (Option.some.inj hfamily).symm + have hshape := view.generation.shape_eq + simp only [VInductDecl.NormalizedChecked.generationShape, Bool.and_eq_true, + beq_iff_eq] at hshape + have hrawParamsLength := hshape.1.1.1.1.1 + have hNatType : natType.type = .sort (.succ .zero) := rfl + rw [VInductDecl.NormalizedChecked.rawParams, hsourceType, + hNatType] at hrawParamsLength + cases hnp : view.source.nparams with + | zero => simpa using hnp + | succ _ => + rw [hnp] at hrawParamsLength + simp [VExpr.telN] at hrawParamsLength + +private theorem natFinalEnv_structureView_nparams_eq_zero + {view : VStructureView} (hview : view.WF natFinalEnv) : + view.nparams = 0 := by + have hrec := hview.recursor + change natRecEnv.constants view.recursorName = + some view.generation.recursor at hrec + rw [addConst_constants + (show natCtorEnv.addConst ``Nat.rec + (VInductDecl.recConst 0 ``Nat 0 natType) = some natRecEnv from rfl), + addConst_constants + (show natZeroEnv.addConst natType.ctors[1].name + natType.ctors[1].toVConstant = some natCtorEnv from rfl), + addConst_constants + (show natTypeEnv.addConst natType.ctors[0].name + natType.ctors[0].toVConstant = some natZeroEnv from rfl), + addConst_constants + (show VEnv.empty.addConst natType.name natType.toVConstant = + some natTypeEnv from rfl)] at hrec + have hNatName : natType.name = ``Nat := rfl + have hZeroName : natType.ctors[0].name = ``Nat.zero := rfl + have hSuccName : natType.ctors[1].name = ``Nat.succ := rfl + rw [hNatName, hZeroName, hSuccName] at hrec + simp [VEnv.empty, VStructureView.recursorName] at hrec + exact structureView_nparams_eq_zero_of_nat hview hrec.1 + nat_type_env_lookup + +private theorem indexedVecTypeEnv_structureView_nparams_eq_zero + {view : VStructureView} (hview : view.WF indexedVecTypeEnv) : + view.nparams = 0 := by + have hrec := hview.recursor + rw [addConst_constants + (show natFinalEnv.addConst indexedVecType.name + indexedVecType.toVConstant = some indexedVecTypeEnv from rfl)] at hrec + change (if indexedVecType.name = view.recursorName then + some indexedVecType.toVConstant else + natRecEnv.constants view.recursorName) = + some view.generation.recursor at hrec + rw [addConst_constants + (show natCtorEnv.addConst ``Nat.rec + (VInductDecl.recConst 0 ``Nat 0 natType) = some natRecEnv from rfl), + addConst_constants + (show natZeroEnv.addConst natType.ctors[1].name + natType.ctors[1].toVConstant = some natCtorEnv from rfl), + addConst_constants + (show natTypeEnv.addConst natType.ctors[0].name + natType.ctors[0].toVConstant = some natZeroEnv from rfl), + addConst_constants + (show VEnv.empty.addConst natType.name natType.toVConstant = + some natTypeEnv from rfl)] at hrec + have hVecName : indexedVecType.name = ``IndexedVec := rfl + have hNatName : natType.name = ``Nat := rfl + have hZeroName : natType.ctors[0].name = ``Nat.zero := rfl + have hSuccName : natType.ctors[1].name = ``Nat.succ := rfl + rw [hVecName, hNatName, hZeroName, hSuccName] at hrec + simp [VEnv.empty, VStructureView.recursorName] at hrec + exact structureView_nparams_eq_zero_of_nat hview hrec.1 rfl + +private theorem natMap_constructor_numParams + {view : VStructureView} {info : ConstructorVal} + (hzero : view.nparams = 0) + (hfind : natMap.find? view.constructorName = some (.ctorInfo info)) : + info.numParams = view.nparams := by + rw [natMap, natCtorMap_wf.find?_insert] at hfind + split at hfind + · cases hfind + · rw [natCtorMap, natZeroMap_wf.find?_insert] at hfind + split at hfind + · simp [natSuccInfo] at hfind + cases hfind + exact hzero.symm + · rw [natZeroMap, natTypeMap_wf.find?_insert] at hfind + split at hfind + · simp [natZeroInfo] at hfind + cases hfind + exact hzero.symm + · rw [natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + at hfind + split at hfind + · cases hfind + · simp [SMap.find?] at hfind + +def indexedVecSemanticNatVEnvs : VEnvs where + venv _ := natFinalEnv + +theorem indexedVecSemanticNatVEnvsWF : indexedVecSemanticNatVEnvs.WF indexedVecKernelEnv where + tr := by + intro safety + change TrEnv' _ natMap false natFinalEnv + exact nat_trEnv' + hasPrimitives := indexedVecSemanticNatHasPrimitives + safePrimitives := indexedVecSemanticNatSafePrimitives + mono := fun _ => .rfl + projectionReady := { + infer := by + intro name _info _hfind hready + rw [indexedVecKernelEnv_noProjectionReady] at hready + contradiction + constructorNumParams := by + intro view info hview hfind + change natMap.find?' view.constructorName = + some (.ctorInfo info) at hfind + rw [natMap_wf.find?'_eq_find?] at hfind + exact natMap_constructor_numParams + (natFinalEnv_structureView_nparams_eq_zero hview) hfind } + structureEtaReady := StructureEtaReady.of_no_nonRecStructure + indexedVecKernelEnv_noStructureEta + +def indexedVecSemanticAddType : + AddInductConstant .induct natMap natFinalEnv + indexedVecType.toVConstVal indexedVecTypeMap indexedVecTypeEnv where + info := indexedVecInfo + kind_eq := by simp [indexedVecInfo, InductConstantKind.Matches] + tr := indexedVecInfo_tr + map_fresh := by simpa [indexedVecType] using indexedVecType_fresh + env_add := rfl + map_add := rfl + +theorem indexedVecSemanticFamilyPrefixNe : + indexedVecFamilyCandidateContext.ngen.namePrefix ≠ + (({} : TypeChecker.VState).ngen).namePrefix := by + decide + +def indexedVecSemanticFamilyContextRun : + TypeChecker.CandidateContextRun indexedVecFamilyCandidateContext := + TypeChecker.CandidateContextRun.root indexedVecSemanticNatVEnvsWF rfl + indexedVecSemanticFamilyPrefixNe + +theorem indexedVecSemanticFamilySourceTr : + TrExprS natFinalEnv [`u] [] indexedVecInfo.type indexedVecType.type := + indexedVecInfo_tr.1.2.2 + +def indexedVecPreFamilyStage : + TypeChecker.CandidateSemanticStage indexedVecFamilyCandidateContext + natFinalEnv [`u] where + contextRun := indexedVecSemanticFamilyContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + +def indexedVecFamilyValidationRun : + AddInductive.CandidateExprTrace.FamilyValidationRun + indexedVecKernelType indexedVecFamilyCandidate.trace where + nparams := 1 + resultLevel := .succ (.param `u) + stats := indexedVecCandidateInductiveStats + stats_eq := rfl + terminal_eq := indexedVecFamilyCandidate_terminalResult + run := indexedVec_checkInductiveTypes + +def indexedVecFamilyStage : + VInductDecl.CandidateFamilyStagedInput + indexedVecFamilyCandidateContext ctorContext natFinalEnv [`u] + indexedVecFamilyListCandidate.familyType indexedVecType + indexedVecPreFamilyStage where + name_eq := rfl + uvars_eq := rfl + type := { + context_eq := rfl + source_tr := indexedVecSemanticFamilySourceTr + whnfFuel := 9999 + whnfDepth := rfl } + validation := indexedVecFamilyValidationRun + typeEnv := indexedVecTypeEnv + addInduct := indexedVecSemanticAddType + projectionReady := { + infer := by + intro name _info _hfind hready + rw [indexedVecTypeEnv_noProjectionReady] at hready + contradiction + constructorNumParams := by + intro view info hview hfind + change indexedVecTypeMap.find?' view.constructorName = + some (.ctorInfo info) at hfind + rw [indexedVecTypeMap_wf.find?'_eq_find?, indexedVecTypeMap, + natMap_wf.find?_insert] at hfind + split at hfind + · cases hfind + · exact natMap_constructor_numParams + (indexedVecTypeEnv_structureView_nparams_eq_zero hview) hfind } + structureEtaReady := StructureEtaReady.of_no_nonRecStructure + indexedVecTypeEnv_noStructureEta + family_lctx_eq := rfl + constructorContext_eq := rfl + quotInit_eq := rfl + name_not_reflected := by decide + name_not_primitive := by + simp [indexedVecType, Kernel.Environment.primitives, + NameSet.ofList] + simp +decide [NameSet.contains] + +def indexedVecSemanticCtorContextRun : + TypeChecker.CandidateContextRun ctorContext := + indexedVecFamilyStage.postContextRun + +theorem indexedVecSemanticNilSourceTr : + TrExprS indexedVecTypeEnv [`u] [] indexedVecNilInfo.type + indexedVecType.ctors[0].type := + indexedVecNilInfo_tr.1.2.2 + +theorem indexedVecSemanticConsIsType : + indexedVecTypeEnv.IsType 1 [] indexedVecType.ctors[1].type := by + have hwf := + (indexedVecChecked.wf_of_decl indexedVecDecl_wf).identityGeneration + nat_env_wf.ordered + have hctor := hwf.rawCtor_isType (envT := indexedVecTypeEnv) rfl + (ctor := indexedVecChecked.identityGeneration.block.ctorPairs[1]) + (by simp) + simpa only [ + show indexedVecDecl.uvars = 1 by rfl, + show indexedVecChecked.identityGeneration.block.ctorPairs[1].raw.type = + indexedVecType.ctors[1].type by rfl] using hctor + +theorem indexedVecSemanticConsSourceTr : + TrExprS indexedVecTypeEnv [`u] [] indexedVecConsInfo.type + indexedVecType.ctors[1].type := by + have hshape : TrTypeExpr indexedVecTypeEnv [`u] [] + indexedVecConsInfo.type indexedVecType.ctors[1].type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := indexedVecSemanticConsIsType + exact hshape.to_trExprS indexedVecTypeEnv_ordered trivial + ⟨.sort u, htype⟩ + +def indexedVecStagedUniverseInput : + VInductDecl.StagedNormalizationCandidateUniverseInput + indexedVecFamilyCandidateContext ctorContext natFinalEnv [`u] + indexedVecNormalizationCandidate indexedVecDecl where + staged := { + raw := indexedVecType + raw_types_eq := rfl + declaration_uvars_eq := rfl + preFamily := indexedVecPreFamilyStage + family := indexedVecFamilyStage + validation_nparams_eq := rfl + constructorValidation := + AddInductive.ConstructorValidationRun.of_run + indexedVecValidationCheckConstructors + constructors := .cons { + name_eq := rfl + uvars_eq := rfl + type := { + context_eq := rfl + source_tr := indexedVecSemanticNilSourceTr + whnfFuel := 9999 + whnfDepth := rfl } } (.cons { + name_eq := rfl + uvars_eq := rfl + type := { + context_eq := rfl + source_tr := indexedVecSemanticConsSourceTr + whnfFuel := 9999 + whnfDepth := rfl } } .nil) + familyTypesProduced := indexedVecFamilyTypeListProduced + familiesProduced := indexedVecFamilyListProduced } + universeRun := indexedVecValidationCheckConstructorUniverseSemantics + +/-- Generic automatic assembly joins the arbitrary-length operational list +witnesses to the complete retained semantic hierarchy for the two-constructor +fixture. No expected normalized view is an input to this theorem. -/ +theorem indexedVecProducedSemanticHierarchy_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidateSemanticRun + indexedVecFamilyCandidateContext ctorContext natFinalEnv [`u] + indexedVecNormalizationCandidate indexedVecDecl) := + indexedVecStagedUniverseInput.exists + +/-- The automatically assembled hierarchy retains both constructor headers in +the producer's `nil`/`cons` source order. This inspects the semantic result, +not the separately constructed concrete replay below. -/ +theorem indexedVecProducedSemanticHierarchy_constructorHeaders : + ∃ run : VInductDecl.ProducedNormalizationCandidateSemanticRun + indexedVecFamilyCandidateContext ctorContext natFinalEnv [`u] + indexedVecNormalizationCandidate indexedVecDecl, + VInductDecl.sameCtorHeaders indexedVecType.ctors + run.semantic.family.root.constructors.views = true := by + obtain ⟨run⟩ := indexedVecProducedSemanticHierarchy_exists + have hraw : run.semantic.raw = indexedVecType := by + have htypes : [indexedVecType] = [run.semantic.raw] := by + simpa [indexedVecDecl] using run.semantic.raw_types_eq + injection htypes with h + exact h.symm + exact ⟨run, by + simpa only [hraw] using + run.semantic.family.root.constructors.sameHeaders⟩ + +/-! ## Post-family constructor alignment -/ + +private theorem indexedVecValidationSortCheckTypeM (lctx : LocalContext) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType (.sort (.succ (.param `u)))) = + .ok (.sort (.succ (.succ (.param `u)))) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' + (.sort (.succ (.param `u))) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + checkLevelSuccParam, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rfl + +private def indexedVecValidationZeroState (alphaId : FVarId) : + TypeChecker.State := + replayInsert (validationFirstAppState alphaId) + (.const ``Nat.zero []) (.const ``Nat []) + +private def indexedVecValidationZeroFinalState (alphaId : FVarId) : + TypeChecker.State := + replayInsert (indexedVecValidationZeroState alphaId) + (ctorIndexedVecApp (.fvar alphaId) (.const ``Nat.zero [])) + (.sort (.succ (.param `u))) + +private theorem indexedVecValidationZeroCheckTypeM + (lctx : LocalContext) (alphaId : FVarId) + (halpha : lctx.find? alphaId = some (.cdecl alphaIndex alphaId + alphaName (.sort (.succ (.param `u))) alphaBi alphaKind)) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType + (ctorIndexedVecApp (.fvar alphaId) (.const ``Nat.zero []))) = + .ok (.sort (.succ (.param `u))) := by + have hfirst : + TypeChecker.Inner.inferType' (replayFirstApp (.fvar alphaId)) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (vecFamilyTail, validationFirstAppState alphaId) := by + simpa [validationFirstAppState] using + (replayInferFirstAppFVarCore 9999 lctx + ({} : TypeChecker.State) alphaId + (by simp) + (by simp [replayInsert]) + (by simp [replayFirstApp]) halpha) + have hzero : + TypeChecker.Inner.inferType' (.const ``Nat.zero []) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + (validationFirstAppState alphaId) = + .ok (.const ``Nat [], indexedVecValidationZeroState alphaId) := by + simpa [indexedVecValidationZeroState, replayInsert] using + (inferTypeZeroCore 9999 lctx (validationFirstAppState alphaId) + (by simp [validationFirstAppState, replayInsert, + replayFirstApp])) + have hresult : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) (.const ``Nat.zero [])) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), + indexedVecValidationZeroFinalState alphaId) := by + simpa [indexedVecValidationZeroFinalState] using + (replayInferIndexedVecAppCore 9999 lctx + ({} : TypeChecker.State) (validationFirstAppState alphaId) + (indexedVecValidationZeroState alphaId) (.fvar alphaId) + (.const ``Nat.zero []) + (by simp [ctorIndexedVecApp, Expr.hasLooseBVars, + Expr.looseBVarRange']) + (by simp [ctorIndexedVecApp]) + hfirst hzero (by rfl)) + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) (.const ``Nat.zero [])) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + rw [hresult] + rfl + +private def indexedVecValidationSuccState + (alphaId nId : FVarId) : TypeChecker.State := + replayInsert + (replayInsert + (replayInsert (validationFirstAppState alphaId) + (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default)) + (.fvar nId) (.const ``Nat [])) + (replaySuccApp (.fvar nId)) (.const ``Nat []) + +private def indexedVecValidationSuccFinalState + (alphaId nId : FVarId) : TypeChecker.State := + replayInsert (indexedVecValidationSuccState alphaId nId) + (ctorIndexedVecApp (.fvar alphaId) (replaySuccApp (.fvar nId))) + (.sort (.succ (.param `u))) + +private theorem indexedVecValidationSuccCheckTypeM + (lctx : LocalContext) (alphaId nId : FVarId) + (hne : alphaId ≠ nId) + (halpha : lctx.find? alphaId = some (.cdecl alphaIndex alphaId + alphaName (.sort (.succ (.param `u))) alphaBi alphaKind)) + (hn : lctx.find? nId = some (.cdecl nIndex nId nName + (.const ``Nat []) nBi nKind)) : + TypeChecker.M.run ctorEnv .safe lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType + (ctorIndexedVecApp (.fvar alphaId) + (replaySuccApp (.fvar nId)))) = + .ok (.sort (.succ (.param `u))) := by + have hfirst : + TypeChecker.Inner.inferType' (replayFirstApp (.fvar alphaId)) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (vecFamilyTail, validationFirstAppState alphaId) := by + simpa [validationFirstAppState] using + (replayInferFirstAppFVarCore 9999 lctx + ({} : TypeChecker.State) alphaId + (by simp) + (by simp [replayInsert]) + (by simp [replayFirstApp]) halpha) + have hsucc : + TypeChecker.Inner.inferType' (replaySuccApp (.fvar nId)) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + (validationFirstAppState alphaId) = + .ok (.const ``Nat [], indexedVecValidationSuccState alphaId nId) := by + simpa [indexedVecValidationSuccState] using + (replayInferSuccFVarCore 9999 lctx + (validationFirstAppState alphaId) nId + (by simp [validationFirstAppState, replayInsert, + replayFirstApp]) + (by + simp only [validationFirstAppState, replayInsert, + Std.HashMap.getElem?_insert] + rw [constBeqFVar] + rw [show (replayFirstApp (.fvar alphaId) == + (.fvar nId : Expr)) = false by + simp [replayFirstApp]] + rw [show ((.fvar alphaId : Expr) == .fvar nId) = false by + change Expr.eqv (.fvar alphaId) (.fvar nId) = false + rw [Expr.eqv_eq] + simp [Expr.eqv', hne]] + rw [constBeqFVar] + simp) + (by simp [validationFirstAppState, replayInsert, + replaySuccApp]) + hn) + have hresult : + TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) + (replaySuccApp (.fvar nId))) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State) = + .ok (.sort (.succ (.param `u)), + indexedVecValidationSuccFinalState alphaId nId) := by + simpa [indexedVecValidationSuccFinalState] using + (replayInferIndexedVecAppCore 9999 lctx + ({} : TypeChecker.State) (validationFirstAppState alphaId) + (indexedVecValidationSuccState alphaId nId) (.fvar alphaId) + (replaySuccApp (.fvar nId)) + (by simp [ctorIndexedVecApp, replaySuccApp, + Expr.hasLooseBVars, Expr.looseBVarRange']) + (by simp [ctorIndexedVecApp, replaySuccApp]) + hfirst hsucc (by rfl)) + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' + (ctorIndexedVecApp (.fvar alphaId) + (replaySuccApp (.fvar nId))) false + (TypeChecker.Methods.withFuel 9999) (tcContext lctx) + ({} : TypeChecker.State)) = _ + rw [hresult] + rfl + +private theorem indexedVecValidationHeadContextFresh : + indexedVecValidationHeadContext.lctx.find? + indexedVecValidationHeadContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := indexedVecValidationHeadContext.freshFVarId) + indexedVecValidationHeadContextWF + rw [h] + simp only [indexedVecValidationHeadContext, + indexedVecValidationNContext, indexedVecCtorValidationContext, + indexedVecValidationTerminalContextShape, + indexedVecValidationFamilyContext, + indexedVecValidationParamContext, + indexedVecFamilyCandidateContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId] + rw [LocalContext.mkLocalDecl_toList, + LocalContext.mkLocalDecl_toList, + LocalContext.mkLocalDecl_toList, + LocalContext.mkLocalDecl_toList] + rw [show ({} : LocalContext).toList = [] by rfl] + simp +decide + +private theorem indexedVecValidationAlphaFindInTail : + indexedVecValidationTailContext.lctx.find? + indexedVecValidationAlphaId = + some (.cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default .default) := by + have hfresh := indexedVecValidationHeadContextFresh + have hne : indexedVecValidationAlphaId ≠ + indexedVecValidationTailId := by + change indexedVecValidationAlphaId ≠ + indexedVecValidationHeadContext.freshFVarId + intro heq + rw [← heq] at hfresh + rw [indexedVecValidationAlphaFindInHead] at hfresh + contradiction + have h := localContextFindOld + (lctx := indexedVecValidationHeadContext.lctx) + (oldId := indexedVecValidationAlphaId) + (newId := indexedVecValidationTailId) + (newName := consTailName) + (newType := ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (newBi := .default) (newKind := .default) + (oldDecl := .cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName (.sort (.succ (.param `u))) + .default .default) + indexedVecValidationHeadContextWF + hfresh hne + indexedVecValidationAlphaFindInHead + simpa [indexedVecValidationTailContext, + indexedVecValidationTailId, + AddInductive.Context.pushLocalDecl] using h + +private theorem indexedVecValidationNFindInTail : + indexedVecValidationTailContext.lctx.find? + indexedVecValidationNId = + some (.cdecl 2 indexedVecValidationNId consNName + (.const ``Nat []) .implicit .default) := by + have hfresh := indexedVecValidationHeadContextFresh + have hne : indexedVecValidationNId ≠ + indexedVecValidationTailId := by + change indexedVecValidationNId ≠ + indexedVecValidationHeadContext.freshFVarId + intro heq + rw [← heq] at hfresh + rw [indexedVecValidationNFindInHead] at hfresh + contradiction + have h := localContextFindOld + (lctx := indexedVecValidationHeadContext.lctx) + (oldId := indexedVecValidationNId) + (newId := indexedVecValidationTailId) + (newName := consTailName) + (newType := ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (newBi := .default) (newKind := .default) + (oldDecl := .cdecl 2 indexedVecValidationNId consNName + (.const ``Nat []) .implicit .default) + indexedVecValidationHeadContextWF + hfresh hne + indexedVecValidationNFindInHead + simpa [indexedVecValidationTailContext, + indexedVecValidationTailId, + AddInductive.Context.pushLocalDecl] using h + +private theorem indexedVecValidationSortCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨indexedVecCtorValidationContext, + .sort (.succ (.param `u)), + .sort (.succ (.succ (.param `u)))⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecCtorValidationContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType (.sort (.succ (.param `u)))) = _ + exact indexedVecValidationSortCheckTypeM + indexedVecCtorValidationContext.lctx + +private theorem indexedVecValidationNatCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨indexedVecCtorValidationContext, .const ``Nat [], + .sort (.succ .zero)⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecCtorValidationContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType (.const ``Nat [])) = _ + exact ctorNatCheckTypeM indexedVecCtorValidationContext.lctx + +private theorem indexedVecValidationAlphaCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨indexedVecValidationNContext, indexedVecValidationAlpha, + .sort (.succ (.param `u))⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecValidationNContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType (.fvar indexedVecValidationAlphaId)) = _ + exact ctorFVarCheckTypeM indexedVecValidationNContext.lctx + indexedVecValidationAlphaId (.sort (.succ (.param `u))) + indexedVecValidationAlphaFindInN + +private theorem indexedVecValidationTailCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨indexedVecValidationHeadContext, + ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr, + .sort (.succ (.param `u))⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecValidationHeadContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType + (ctorIndexedVecApp (.fvar indexedVecValidationAlphaId) + (.fvar indexedVecValidationNId))) = _ + exact ctorIndexedVecFVarCheckTypeM + indexedVecValidationHeadContext.lctx + indexedVecValidationAlphaId indexedVecValidationNId + indexedVecValidationAlphaNeN indexedVecValidationAlphaFindInHead + indexedVecValidationNFindInHead + +private theorem indexedVecValidationNilResultCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨indexedVecCtorValidationContext, indexedVecValidationNilResult, + .sort (.succ (.param `u))⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecCtorValidationContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType + (ctorIndexedVecApp (.fvar indexedVecValidationAlphaId) + (.const ``Nat.zero []))) = _ + exact indexedVecValidationZeroCheckTypeM + indexedVecCtorValidationContext.lctx indexedVecValidationAlphaId + indexedVecValidationAlphaFind + +private theorem indexedVecValidationConsResultCheckValid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨indexedVecValidationTailContext, indexedVecValidationConsResult, + .sort (.succ (.param `u))⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecValidationTailContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.checkType + (ctorIndexedVecApp (.fvar indexedVecValidationAlphaId) + (replaySuccApp (.fvar indexedVecValidationNId)))) = _ + exact indexedVecValidationSuccCheckTypeM + indexedVecValidationTailContext.lctx + indexedVecValidationAlphaId indexedVecValidationNId + indexedVecValidationAlphaNeN + indexedVecValidationAlphaFindInTail + indexedVecValidationNFindInTail + +private def indexedVecCheckedOfValid + (context : AddInductive.Context) (source inferred : Expr) + (fvars : source.FVarsIn + (fun fv => (context.lctx.find? fv).isSome = true)) + (valid : AddInductive.CandidateCheckTypeStep.Valid + ⟨context, source, inferred⟩) : + AddInductive.ConstructorCheckedExpr context source := + .ofRun fvars valid + +private def indexedVecValidationSortChecked : + AddInductive.ConstructorCheckedExpr indexedVecCtorValidationContext + (.sort (.succ (.param `u))) := + indexedVecCheckedOfValid _ _ _ (by + simp [FVarsIn, Level.hasMVar']) + indexedVecValidationSortCheckValid + +private def indexedVecValidationNatChecked : + AddInductive.ConstructorCheckedExpr indexedVecCtorValidationContext + (.const ``Nat []) := + indexedVecCheckedOfValid _ _ _ (by simp [FVarsIn]) + indexedVecValidationNatCheckValid + +private def indexedVecValidationAlphaChecked : + AddInductive.ConstructorCheckedExpr indexedVecValidationNContext + indexedVecValidationAlpha := + indexedVecCheckedOfValid _ _ _ (by + change (indexedVecValidationNContext.lctx.find? + indexedVecValidationAlphaId).isSome = true + rw [indexedVecValidationAlphaFindInN] + rfl) + indexedVecValidationAlphaCheckValid + +private def indexedVecValidationTailChecked : + AddInductive.ConstructorCheckedExpr indexedVecValidationHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) := + indexedVecCheckedOfValid _ _ _ (by + simp [ctorIndexedVecApp, indexedVecValidationAlpha, + indexedVecValidationNExpr, AddInductive.Context.freshExpr, + FVarsIn, Level.hasMVar'] + constructor + · change (indexedVecValidationHeadContext.lctx.find? + indexedVecValidationAlphaId).isSome = true + rw [indexedVecValidationAlphaFindInHead] + rfl + · change (indexedVecValidationHeadContext.lctx.find? + indexedVecValidationNId).isSome = true + rw [indexedVecValidationNFindInHead] + rfl) + indexedVecValidationTailCheckValid + +private def indexedVecValidationNilResultChecked : + AddInductive.ConstructorCheckedExpr indexedVecCtorValidationContext + indexedVecValidationNilResult := + indexedVecCheckedOfValid _ _ _ (by + simp [indexedVecValidationNilResult, ctorIndexedVecApp, + indexedVecValidationAlpha, + AddInductive.Context.freshExpr, FVarsIn, Level.hasMVar'] + change (indexedVecCtorValidationContext.lctx.find? + indexedVecValidationAlphaId).isSome = true + rw [indexedVecValidationAlphaFind] + rfl) + indexedVecValidationNilResultCheckValid + +private def indexedVecValidationConsResultChecked : + AddInductive.ConstructorCheckedExpr indexedVecValidationTailContext + indexedVecValidationConsResult := + indexedVecCheckedOfValid _ _ _ (by + simp [indexedVecValidationConsResult, ctorIndexedVecApp, + replaySuccApp, indexedVecValidationAlpha, + indexedVecValidationNExpr, AddInductive.Context.freshExpr, + FVarsIn, Level.hasMVar'] + constructor + · change (indexedVecValidationTailContext.lctx.find? + indexedVecValidationAlphaId).isSome = true + rw [indexedVecValidationAlphaFindInTail] + rfl + · change (indexedVecValidationTailContext.lctx.find? + indexedVecValidationNId).isSome = true + rw [indexedVecValidationNFindInTail] + rfl) + indexedVecValidationConsResultCheckValid + +private theorem indexedVecStagedStats_eq : + indexedVecStagedUniverseInput.staged.family.validation.stats = + indexedVecCandidateInductiveStats := rfl + +private theorem indexedVecValidationPostContext_eq : + { indexedVecNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := ctorContext.env } = indexedVecCtorValidationContext := rfl + +private def indexedVecTransportValidationTrace + {context context' : AddInductive.Context} + (context_eq : context = context') + {source source' : Expr} (source_eq : source = source') + (trace : AddInductive.ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context source argIdx fuel) : + AddInductive.ConstructorTypeValidationTrace stats isUnsafe familyIdx ctor + context' source' argIdx fuel := by + subst context' + subst source' + exact trace + +private def indexedVecTransportViewAlignment + {context context' : AddInductive.Context} + (context_eq : context = context') + {source source' view view' : Expr} + (source_eq : source = source') (view_eq : view = view') + (trace : AddInductive.ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context source argIdx fuel) + (alignment : AddInductive.ConstructorViewAlignmentTrace + (indexedVecTransportValidationTrace context_eq source_eq trace) + view') : + AddInductive.ConstructorViewAlignmentTrace trace view := by + subst context' + subst source' + subst view' + exact alignment + +@[simp] private theorem indexedVecTransportValidationTrace_spineLength + {context context' : AddInductive.Context} + (context_eq : context = context') + {source source' : Expr} (source_eq : source = source') + (trace : AddInductive.ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context source argIdx fuel) : + (indexedVecTransportValidationTrace context_eq source_eq trace).spineLength = + trace.spineLength := by + subst context' + subst source' + rfl + +private theorem indexedVecValidationNatWhnfSelf : + AddInductive.CandidateWhnfStep.Valid + ⟨indexedVecCtorValidationContext, .const ``Nat [], + .const ``Nat []⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecCtorValidationContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf (.const ``Nat [])) = .ok (.const ``Nat []) + exact ctorNatWhnfM indexedVecCtorValidationContext.lctx + +private theorem indexedVecValidationAlphaWhnfSelf : + AddInductive.CandidateWhnfStep.Valid + ⟨indexedVecValidationNContext, indexedVecValidationAlpha, + indexedVecValidationAlpha⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecValidationNContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf (.fvar indexedVecValidationAlphaId)) = + .ok (.fvar indexedVecValidationAlphaId) + exact ctorFVarWhnfM indexedVecValidationNContext.lctx + indexedVecValidationAlphaId indexedVecValidationAlphaFindInN + +private theorem indexedVecValidationTailWhnfSelf : + AddInductive.CandidateWhnfStep.Valid + ⟨indexedVecValidationHeadContext, + ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr, + ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr⟩ := by + change TypeChecker.M.run ctorEnv .safe + indexedVecValidationHeadContext.lctx [`u] ({} : FuelConfig) + (TypeChecker.whnf + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr)) = + .ok (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + exact ctorIndexedVecWhnfM indexedVecValidationHeadContext.lctx + indexedVecValidationAlpha indexedVecValidationNExpr + +private theorem indexedVecCandidateWhnfResult_eq + (self : AddInductive.CandidateWhnfStep.Valid + ⟨context, source, source⟩) + (other : AddInductive.CandidateWhnfStep.Valid + ⟨context, source, result⟩) : + result = source := by + unfold AddInductive.CandidateWhnfStep.Valid at self other + rw [self] at other + exact (Except.ok.inj other).symm + +private def indexedVecValidationNatPositivityAlignment + (trace : AddInductive.ConstructorPositivityModeTrace + indexedVecStagedUniverseInput.staged.family.validation.stats false + indexedVecKernelCons.name 1 indexedVecCtorValidationContext + (.const ``Nat [])) : + AddInductive.ConstructorPositivityModeAlignmentTrace trace := by + cases trace with + | skipped unsafeEq => contradiction + | safe unsafeEq positivityTrace => + apply AddInductive.ConstructorPositivityModeAlignmentTrace.safe + cases positivityTrace with + | absent context source result fuel whnf occurs => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationNatWhnfSelf whnf + subst result + exact .absent indexedVecValidationNatChecked + | forallE context source fuel name domain body binderInfo whnf occurs + domainFree tail => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationNatWhnfSelf whnf + have impossible := congrArg Expr.isForall result_eq + simp [Expr.isForall] at impossible + | target context source result fuel targetIdx whnf occurs terminal valid => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationNatWhnfSelf whnf + subst result + rw [indexedVecStagedStats_eq, + indexedVecValidationNatHasNoIndOcc] at occurs + contradiction + +private def indexedVecValidationAlphaPositivityAlignment + (trace : AddInductive.ConstructorPositivityModeTrace + indexedVecStagedUniverseInput.staged.family.validation.stats false + indexedVecKernelCons.name 2 indexedVecValidationNContext + indexedVecValidationAlpha) : + AddInductive.ConstructorPositivityModeAlignmentTrace trace := by + cases trace with + | skipped unsafeEq => contradiction + | safe unsafeEq positivityTrace => + apply AddInductive.ConstructorPositivityModeAlignmentTrace.safe + cases positivityTrace with + | absent context source result fuel whnf occurs => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationAlphaWhnfSelf whnf + subst result + exact .absent indexedVecValidationAlphaChecked + | forallE context source fuel name domain body binderInfo whnf occurs + domainFree tail => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationAlphaWhnfSelf whnf + have impossible := congrArg Expr.isForall result_eq + simp [indexedVecValidationAlphaShape, Expr.isForall] at impossible + | target context source result fuel targetIdx whnf occurs terminal valid => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationAlphaWhnfSelf whnf + subst result + rw [indexedVecStagedStats_eq] at occurs + change AddInductive.hasIndOcc + indexedVecCandidateInductiveStats.indConsts + indexedVecValidationAlpha = true at occurs + rw [indexedVecValidationAlphaHasNoIndOcc] at occurs + contradiction + +private def indexedVecValidationTailPositivityAlignment + (trace : AddInductive.ConstructorPositivityModeTrace + indexedVecStagedUniverseInput.staged.family.validation.stats false + indexedVecKernelCons.name 3 indexedVecValidationHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr)) : + AddInductive.ConstructorPositivityModeAlignmentTrace trace := by + cases trace with + | skipped unsafeEq => contradiction + | safe unsafeEq positivityTrace => + apply AddInductive.ConstructorPositivityModeAlignmentTrace.safe + cases positivityTrace with + | absent context source result fuel whnf occurs => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationTailWhnfSelf whnf + subst result + rw [indexedVecStagedStats_eq] at occurs + change AddInductive.hasIndOcc + indexedVecCandidateInductiveStats.indConsts + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) = false at occurs + rw [indexedVecValidationTailHasIndOcc] at occurs + contradiction + | forallE context source fuel name domain body binderInfo whnf occurs + domainFree tail => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationTailWhnfSelf whnf + have impossible := congrArg Expr.isForall result_eq + simp [ctorIndexedVecApp, Expr.isForall] at impossible + | target context source result fuel targetIdx whnf occurs terminal valid => + have result_eq := indexedVecCandidateWhnfResult_eq + indexedVecValidationTailWhnfSelf whnf + subst result + exact .target indexedVecValidationTailChecked + +private def indexedVecValidationNatAnnotations : + AddInductive.CandidateIsDefEqObservation + indexedVecCtorValidationContext (.const ``Nat []) + (.const ``Nat []) := + ⟨AddInductive.candidateIsDefEqRefl indexedVecCtorValidationContext + (.const ``Nat [])⟩ + +private def indexedVecValidationAlphaAnnotations : + AddInductive.CandidateIsDefEqObservation + indexedVecValidationNContext indexedVecValidationAlpha + indexedVecValidationAlpha := + ⟨AddInductive.candidateIsDefEqRefl indexedVecValidationNContext + indexedVecValidationAlpha⟩ + +private def indexedVecValidationTailAnnotations : + AddInductive.CandidateIsDefEqObservation + indexedVecValidationHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) := + ⟨AddInductive.candidateIsDefEqRefl indexedVecValidationHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr)⟩ + +/-- The validator and analyzer intentionally allocate the retained `n` field +under different fresh-FVar histories. D2 alignment must therefore be +positional rather than identifier-based. -/ +theorem indexedVecValidationCandidateFieldFVars_ne : + indexedVecValidationNId ≠ consNId := by + simp [indexedVecValidationNId, indexedVecCtorValidationContext, + indexedVecValidationTerminalContextShape, + indexedVecValidationFamilyContext, + indexedVecValidationParamContext, indexedVecFamilyCandidateContext, + consNId, consAlphaContext, consRootContext, ctorContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, + NameGenerator.next, NameGenerator.curr] + +/-- Exact D2 owner for `IndexedVec`. Its validator telescope is transported +only across proved context/source equalities, while every candidate view is +instantiated with the validator-owned locals at the same de Bruijn position. -/ +def indexedVecStagedPostFamilyInput : + VInductDecl.StagedNormalizationCandidatePostFamilyInput + indexedVecFamilyCandidateContext ctorContext natFinalEnv [`u] + indexedVecNormalizationCandidate indexedVecDecl where + universeInput := indexedVecStagedUniverseInput + alignment := by + change AddInductive.ConstructorCandidateAlignmentTrace + indexedVecStagedUniverseInput.staged.family.validation.stats false 0 + indexedVecCtorValidationContext + indexedVecStagedUniverseInput.staged.constructorValidation.trace + (.cons indexedVecNilConstructorCandidate + (.cons indexedVecConsConstructorCandidate .nil)) + generalize htrace : + indexedVecStagedUniverseInput.staged.constructorValidation.trace = trace + cases trace with + | cons seen head constructors fresh closed rootCheck typeTrace tailTrace => + clear htrace + cases hnilRoot : typeTrace with + | parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeRun parameterDefEq + nilTypeTail => + rw [indexedVecStagedStats_eq, + indexedVecValidationStatsParams] at parameterAt + simp at parameterAt + subst param + change AddInductive.getType indexedVecValidationAlpha + indexedVecCtorValidationContext = .ok parameterType at parameterTypeRun + rw [indexedVecValidationGetTypeAlpha] at parameterTypeRun + injection parameterTypeRun with parameterType_eq + subst parameterType + let nilNormalized := indexedVecTransportValidationTrace + indexedVecValidationPostContext_eq + indexedVecValidationNilResultShape nilTypeTail + let nilNormalizedTrace := nilNormalized + have nilSpine : nilTypeTail.spineLength = + nilNormalizedTrace.spineLength := by + exact (indexedVecTransportValidationTrace_spineLength + indexedVecValidationPostContext_eq + indexedVecValidationNilResultShape nilTypeTail).symm + cases hnilNormalized : nilNormalizedTrace with + | terminal context source fuel argIdx nilTerminal nilValid => + simp [hnilNormalized, + AddInductive.ConstructorTypeValidationTrace.spineLength] at nilSpine + have nilNormalizedAlignment : + AddInductive.ConstructorViewAlignmentTrace + nilNormalizedTrace indexedVecValidationNilResult := by + rw [hnilNormalized] + exact .terminal indexedVecValidationNilResultChecked + indexedVecValidationNilResultChecked nilTerminal nilValid + have nilTailAlignment := indexedVecTransportViewAlignment + indexedVecValidationPostContext_eq + indexedVecValidationNilResultShape + indexedVecValidationNilResultShape nilTypeTail + nilNormalizedAlignment + have nilHeadAlignment : + AddInductive.ConstructorViewAlignmentTrace + (.parameter + { indexedVecNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := ctorContext.env } + 999 0 `α (.sort (.succ (.param `u))) + nilCtorBodyRaw .implicit indexedVecValidationAlpha + (.sort (.succ (.param `u))) parameterAt + parameterTypeRun parameterDefEq nilTypeTail) + indexedVecNilConstructorCandidate.type.view := by + change AddInductive.ConstructorViewAlignmentTrace + _ nilCandidate.view + rw [nilCandidate_view_eq] + exact .parameter indexedVecValidationSortChecked + indexedVecValidationSortChecked + indexedVecValidationSortChecked rfl + (by simp [indexedVecValidationAlphaFind]) + nilTypeTail nilTailAlignment + cases tailTrace with + | cons seen head constructors consFresh consClosed + consRootCheck consTypeTrace finalTrace => + cases hconsRoot : consTypeTrace with + | parameter context fuel argIdx name domain body binderInfo + param parameterType parameterAt parameterTypeRun + parameterDefEq consAfterParamTrace => + rw [indexedVecStagedStats_eq, + indexedVecValidationStatsParams] at parameterAt + simp at parameterAt + subst param + change AddInductive.getType indexedVecValidationAlpha + indexedVecCtorValidationContext = .ok parameterType at parameterTypeRun + rw [indexedVecValidationGetTypeAlpha] at parameterTypeRun + injection parameterTypeRun with parameterType_eq + subst parameterType + let buildConsHeadAlignment + (tailAlignment : + AddInductive.ConstructorViewAlignmentTrace + consAfterParamTrace + (consNTypeRaw.instantiate1 + indexedVecValidationAlpha)) : + AddInductive.ConstructorViewAlignmentTrace + (.parameter + { indexedVecNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := ctorContext.env } + 999 0 consAlphaName + (.sort (.succ (.param `u))) consNTypeRaw + .implicit indexedVecValidationAlpha + (.sort (.succ (.param `u))) parameterAt + parameterTypeRun parameterDefEq + consAfterParamTrace) + indexedVecConsConstructorCandidate.type.view := by + change AddInductive.ConstructorViewAlignmentTrace + _ consCandidate.view + rw [consCandidate_view_eq] + exact .parameter indexedVecValidationSortChecked + indexedVecValidationSortChecked + indexedVecValidationSortChecked rfl + (by simp [indexedVecValidationAlphaFind]) + consAfterParamTrace tailAlignment + have consAfterParamSource_eq : + indexedVecConsInfo.type.bindingBody!.instantiate1 + indexedVecValidationAlpha = + indexedVecValidationConsAfterParam := + indexedVecValidationConsAfterParamShape + have consAfterParamExplicit_eq : + indexedVecConsInfo.type.bindingBody!.instantiate1 + indexedVecValidationAlpha = + .forallE consNName (.const ``Nat []) + (.forallE consHeadName + indexedVecValidationAlpha + (.forallE consTailName + (ctorIndexedVecApp + indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp + indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) .default) + .default) + .implicit := + consAfterParamSource_eq.trans + indexedVecValidationConsAfterParamExplicitShape + let consAfterParamNormalized := + indexedVecTransportValidationTrace + indexedVecValidationPostContext_eq + consAfterParamExplicit_eq consAfterParamTrace + let consAfterParamNormalizedTrace := + consAfterParamNormalized + have consAfterParamSpine : + consAfterParamTrace.spineLength = + consAfterParamNormalizedTrace.spineLength := by + exact (indexedVecTransportValidationTrace_spineLength + indexedVecValidationPostContext_eq + consAfterParamExplicit_eq + consAfterParamTrace).symm + cases hconsAfterParamNormalized : + consAfterParamNormalizedTrace with + | parameter context fuel argIdx name domain body + binderInfo param parameterType parameterAt + parameterTypeRun parameterDefEq tail => + rw [indexedVecStagedStats_eq, + indexedVecValidationStatsParams] at parameterAt + simp at parameterAt + | ordinary context fuel argIdx name domain body + binderInfo sortResult noParameter ensureType + universeTrace natPositivity consAfterNTrace => + simp [hconsAfterParamNormalized, + AddInductive.ConstructorTypeValidationTrace.spineLength] + at consAfterParamSpine + have natPositivityAlignment := + indexedVecValidationNatPositivityAlignment + natPositivity + have afterParamBody_eq : + indexedVecValidationConsAfterParam.bindingBody! = + .forallE consHeadName + indexedVecValidationAlpha + (.forallE consTailName + (ctorIndexedVecApp + indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp + indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) .default) + .default := by + exact congrArg Expr.bindingBody! + indexedVecValidationConsAfterParamExplicitShape + have afterNSource_eq : + ((Expr.forallE consHeadName + indexedVecValidationAlpha + (Expr.forallE consTailName + (ctorIndexedVecApp + indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp + indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) .default) + .default).instantiate1 + indexedVecCtorValidationContext.freshExpr) = + indexedVecValidationConsAfterN := by + change + ((Expr.forallE consHeadName + indexedVecValidationAlpha + (Expr.forallE consTailName + (ctorIndexedVecApp + indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp + indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) .default) + .default).instantiate1 + indexedVecValidationNExpr) = + indexedVecValidationConsAfterN + rw [← afterParamBody_eq] + exact indexedVecValidationConsAfterNShape + have nContext_eq : + indexedVecCtorValidationContext.pushLocalDecl + consNName .implicit + (AddInductive.consumeTypeAnnotations + (.const ``Nat [])) = + indexedVecValidationNContext := by + simp [indexedVecValidationNContext] + let consAfterNNormalized := + indexedVecTransportValidationTrace nContext_eq + afterNSource_eq consAfterNTrace + let consAfterNNormalizedTrace := consAfterNNormalized + have consAfterNSpine : + consAfterNTrace.spineLength = + consAfterNNormalizedTrace.spineLength := by + exact + (indexedVecTransportValidationTrace_spineLength + nContext_eq afterNSource_eq + consAfterNTrace).symm + cases hconsAfterNNormalized : + consAfterNNormalizedTrace with + | parameter context fuel argIdx name domain body + binderInfo param parameterType parameterAt + parameterTypeRun parameterDefEq tail => + rw [indexedVecStagedStats_eq, + indexedVecValidationStatsParams] at parameterAt + simp at parameterAt + | ordinary context fuel argIdx name domain body + binderInfo sortResult noParameter ensureType + universeTrace alphaPositivity + consAfterHeadTrace => + simp [hconsAfterNNormalized, + AddInductive.ConstructorTypeValidationTrace.spineLength] + at consAfterNSpine + have alphaPositivityAlignment := + indexedVecValidationAlphaPositivityAlignment + alphaPositivity + have headContext_eq : + indexedVecValidationNContext.pushLocalDecl + consHeadName .default + (AddInductive.consumeTypeAnnotations + indexedVecValidationAlpha) = + indexedVecValidationHeadContext := by + rw [indexedVecValidationConsumeAlpha] + rfl + let consAfterHeadNormalized := + indexedVecTransportValidationTrace + headContext_eq + indexedVecValidationConsAfterHeadShape + consAfterHeadTrace + let consAfterHeadNormalizedTrace := + consAfterHeadNormalized + have consAfterHeadSpine : + consAfterHeadTrace.spineLength = + consAfterHeadNormalizedTrace.spineLength := by + exact + (indexedVecTransportValidationTrace_spineLength + headContext_eq + indexedVecValidationConsAfterHeadShape + consAfterHeadTrace).symm + cases hconsAfterHeadNormalized : + consAfterHeadNormalizedTrace with + | parameter context fuel argIdx name domain body + binderInfo param parameterType parameterAt + parameterTypeRun parameterDefEq tail => + rw [indexedVecStagedStats_eq, + indexedVecValidationStatsParams] at parameterAt + simp at parameterAt + | ordinary context fuel argIdx name domain body + binderInfo sortResult noParameter ensureType + universeTrace tailPositivity + consResultTrace => + simp [hconsAfterHeadNormalized, + AddInductive.ConstructorTypeValidationTrace.spineLength] + at consAfterHeadSpine + have tailPositivityAlignment := + indexedVecValidationTailPositivityAlignment + tailPositivity + have tailContext_eq : + indexedVecValidationHeadContext.pushLocalDecl + consTailName .default + (AddInductive.consumeTypeAnnotations + (ctorIndexedVecApp + indexedVecValidationAlpha + indexedVecValidationNExpr)) = + indexedVecValidationTailContext := by + rw [indexedVecValidationConsumeTail] + rfl + let consResultNormalized := + indexedVecTransportValidationTrace + tailContext_eq + indexedVecValidationConsResultShape + consResultTrace + let consResultNormalizedTrace := + consResultNormalized + have consResultSpine : + consResultTrace.spineLength = + consResultNormalizedTrace.spineLength := by + exact + (indexedVecTransportValidationTrace_spineLength + tailContext_eq + indexedVecValidationConsResultShape + consResultTrace).symm + cases hconsResultNormalized : + consResultNormalizedTrace with + | terminal context source fuel argIdx + resultTerminal resultValid => + simp [hconsResultNormalized, + AddInductive.ConstructorTypeValidationTrace.spineLength] + at consResultSpine + have consResultNormalizedAlignment : + AddInductive.ConstructorViewAlignmentTrace + consResultNormalizedTrace + indexedVecValidationConsResult := by + rw [hconsResultNormalized] + exact .terminal + indexedVecValidationConsResultChecked + indexedVecValidationConsResultChecked + resultTerminal resultValid + have consResultAlignment := + indexedVecTransportViewAlignment + tailContext_eq + indexedVecValidationConsResultShape + indexedVecValidationConsResultShape + consResultTrace + consResultNormalizedAlignment + have consAfterHeadNormalizedAlignment : + AddInductive.ConstructorViewAlignmentTrace + consAfterHeadNormalizedTrace + indexedVecValidationConsAfterHead := by + rw [hconsAfterHeadNormalized] + exact .ordinary + indexedVecValidationTailChecked + indexedVecValidationTailChecked + (by simpa only + [indexedVecValidationConsumeTail] + using + indexedVecValidationTailAnnotations) + (by simpa only + [indexedVecValidationConsumeTail] + using indexedVecValidationTailChecked) + tailPositivity + tailPositivityAlignment + indexedVecValidationHeadContextFresh + (by simpa only + [indexedVecValidationConsumeTail] + using + indexedVecValidationTailAnnotations) + consResultTrace consResultAlignment + have consAfterHeadAlignment := + indexedVecTransportViewAlignment + headContext_eq + indexedVecValidationConsAfterHeadShape + indexedVecValidationConsAfterHeadShape + consAfterHeadTrace + consAfterHeadNormalizedAlignment + have consAfterNNormalizedAlignment : + AddInductive.ConstructorViewAlignmentTrace + consAfterNNormalizedTrace + indexedVecValidationConsAfterN := by + rw [hconsAfterNNormalized] + exact .ordinary + indexedVecValidationAlphaChecked + indexedVecValidationAlphaChecked + (by simpa only + [indexedVecValidationConsumeAlpha] + using + indexedVecValidationAlphaAnnotations) + (by simpa only + [indexedVecValidationConsumeAlpha] + using indexedVecValidationAlphaChecked) + alphaPositivity + alphaPositivityAlignment + indexedVecValidationNContextFresh + (by simpa only + [indexedVecValidationConsumeAlpha] + using + indexedVecValidationAlphaAnnotations) + consAfterHeadTrace + consAfterHeadAlignment + have consAfterNAlignment := + indexedVecTransportViewAlignment + nContext_eq afterNSource_eq + afterNSource_eq consAfterNTrace + consAfterNNormalizedAlignment + have consAfterParamNormalizedAlignment : + AddInductive.ConstructorViewAlignmentTrace + consAfterParamNormalizedTrace + (.forallE consNName + (.const ``Nat []) + (.forallE consHeadName + indexedVecValidationAlpha + (.forallE consTailName + (ctorIndexedVecApp + indexedVecValidationAlpha + (.bvar 1)) + (ctorIndexedVecApp + indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) + .default) + .default) + .implicit) := by + rw [hconsAfterParamNormalized] + exact .ordinary + indexedVecValidationNatChecked + indexedVecValidationNatChecked + (by simpa only + [indexedVecValidationConsumeNat] + using + indexedVecValidationNatAnnotations) + (by simpa only + [indexedVecValidationConsumeNat] + using indexedVecValidationNatChecked) + natPositivity natPositivityAlignment + indexedVecCtorValidationContextFresh + (by simpa only + [indexedVecValidationConsumeNat] + using + indexedVecValidationNatAnnotations) + consAfterNTrace consAfterNAlignment + have consAfterParamAlignment := + indexedVecTransportViewAlignment + indexedVecValidationPostContext_eq + consAfterParamExplicit_eq + consAfterParamExplicit_eq + consAfterParamTrace + consAfterParamNormalizedAlignment + have consHeadAlignment := + buildConsHeadAlignment + consAfterParamAlignment + change + AddInductive.CandidateCheckTypeObservation + indexedVecCtorValidationContext.withEmptyLocalContext + indexedVecKernelNil.type at rootCheck + change + AddInductive.CandidateCheckTypeObservation + indexedVecCtorValidationContext.withEmptyLocalContext + indexedVecKernelCons.type at consRootCheck + let nilRootScope : + AddInductive.ConstructorCheckedExpr + indexedVecCtorValidationContext.withEmptyLocalContext + indexedVecKernelNil.type := + AddInductive.ConstructorCheckedExpr.ofClosedRoot + closed rootCheck + let consRootScope : + AddInductive.ConstructorCheckedExpr + indexedVecCtorValidationContext.withEmptyLocalContext + indexedVecKernelCons.type := + AddInductive.ConstructorCheckedExpr.ofClosedRoot + consClosed consRootCheck + cases finalTrace with + | nil finalSeen => + exact + AddInductive.ConstructorCandidateAlignmentTrace.cons + nilRootScope + (by + change nilCandidate.trace.storedSpine = true + exact nilCandidate_identity.storedSpine) + (by + change 1 = + nilTypeTail.spineLength + 1 + omega) + (by rfl) nilHeadAlignment <| + AddInductive.ConstructorCandidateAlignmentTrace.cons + consRootScope + (by + change consCandidate.trace.storedSpine = true + exact consCandidate_identity.storedSpine) + (by + change 4 = + consAfterParamTrace.spineLength + 1 + omega) + (by rfl) consHeadAlignment <| + AddInductive.ConstructorCandidateAlignmentTrace.nil + ((∅ : NameSet).insert + indexedVecKernelNil.name |>.insert + indexedVecKernelCons.name) + | terminal context source fuel argIdx terminal + valid => + simp [indexedVecValidationConsAfterHead, + Expr.isForall] at terminal + | terminal context source fuel argIdx terminal valid => + simp [indexedVecValidationConsAfterN, + Expr.isForall] at terminal + | terminal context source fuel argIdx terminal valid => + simp [Expr.isForall] at terminal + | ordinary context fuel argIdx name domain body binderInfo + sortResult noParameter ensureType universeTrace positivity + tail => + rw [indexedVecStagedStats_eq, + indexedVecValidationStatsParams] at noParameter + simp at noParameter + | terminal context source fuel argIdx terminal valid => + have consType_eq : indexedVecKernelCons.type = + consCtorTypeRaw := by + simpa [indexedVecKernelCons] using consInfoTypeShape + rw [consType_eq] at terminal + simp [consCtorTypeRaw, Expr.isForall] at terminal + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureType universeTrace positivity nilTypeTail => + rw [indexedVecStagedStats_eq, + indexedVecValidationStatsParams] at noParameter + simp at noParameter + | terminal context source fuel argIdx terminal valid => + simp [indexedVecKernelNil, indexedVecNilInfo, + ConstantInfo.type, ConstantInfo.toConstantVal, + Expr.isForall] at terminal + +/-- The retained `nil`/`cons` validator telescopes, exact analyzer views, field +checks, positivity target, and terminal family applications all admit the D2 +post-family Theory interpretation despite their distinct fresh identifiers. -/ +theorem indexedVecProducedPostFamilySemantic_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidatePostFamilySemanticRun + indexedVecStagedPostFamilyInput) := + indexedVecStagedPostFamilyInput.exists + +/-! ## Pre-family constructor safety + +The D3 replay uses the terminal family-analysis context, whose environment is +still exactly `natMap`. Ordinary constructor fields extend that context; +recursive fields advance only the fresh-name generator so their locals cannot +be used by later fields or the result. -/ + +private def indexedVecPreFamilyContext : AddInductive.Context := + indexedVecFamilyCandidate.trace.terminalContext + +private def indexedVecPreFamilyNContext : AddInductive.Context := + indexedVecPreFamilyContext.pushLocalDecl + consNName .implicit (.const ``Nat []) + +private def indexedVecPreFamilyHeadContext : AddInductive.Context := + indexedVecPreFamilyNContext.pushLocalDecl + consHeadName .default indexedVecValidationAlpha + +private def indexedVecPreFamilyResultContext : AddInductive.Context := + indexedVecPreFamilyHeadContext.advanceFresh + +private theorem indexedVecPreFamilyContext_eq : + indexedVecPreFamilyContext = indexedVecValidationFamilyContext := rfl + +private theorem indexedVecPreFamilyNContext_eq : + indexedVecPreFamilyNContext = + { indexedVecValidationNContext with env := indexedVecKernelEnv } := rfl + +private theorem indexedVecPreFamilyHeadContext_eq : + indexedVecPreFamilyHeadContext = + { indexedVecValidationHeadContext with env := indexedVecKernelEnv } := rfl + +private theorem indexedVecPreFamilySortCheckValid + (context : AddInductive.Context) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, .sort (.succ (.param `u)), + .sort (.succ (.succ (.param `u)))⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilySortCheckTypeM context.lctx + +private theorem indexedVecPreFamilyNatCheckValid + (context : AddInductive.Context) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, .const ``Nat [], .sort (.succ .zero)⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilyNatCheckTypeM context.lctx + +private theorem indexedVecPreFamilyNatEnsureValid + (context : AddInductive.Context) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.ConstructorEnsureTypeStep.Valid + ⟨context, .const ``Nat [], .sort (.succ .zero)⟩ := by + unfold AddInductive.ConstructorEnsureTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilyNatEnsureTypeM context.lctx + +private theorem indexedVecPreFamilyTelescopeCheckValid + (context : AddInductive.Context) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, indexedVecPreFamilyIndexTelescope, + .sort (mkLevelIMax' (.succ .zero) + (.succ (.succ (.param `u))))⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilyIndexTelescopeCheckTypeM context.lctx + +private theorem indexedVecPreFamilyFVarCheckTypeM + (lctx : LocalContext) (id : FVarId) (type : Expr) + (find : lctx.find? id = + some (.cdecl index id name type bi kind)) : + TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType (.fvar id)) = + .ok type := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.fvar id) false + (TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : TypeChecker.State)) = _ + rw [indexedVecPreFamilyInferTypeFVarCore 9999 lctx + ({} : TypeChecker.State) id type Std.HashMap.getElem?_empty find] + rfl + +private def indexedVecPreFamilyFVarInferOnlyState + (id : FVarId) (type : Expr) : TypeChecker.State := + { ({} : TypeChecker.State) with + inferTypeI := ({} : TypeChecker.State).inferTypeI.insert + (.fvar id) type } + +private theorem indexedVecPreFamilyFVarInferOnly + (lctx : LocalContext) (id : FVarId) (type : Expr) + (find : lctx.find? id = + some (.cdecl index id name type bi kind)) : + TypeChecker.Inner.inferType (.fvar id) true + (TypeChecker.Methods.withFuel 10000) + (indexedVecTypeCheckerContext lctx) + ({} : TypeChecker.State) = + .ok (type, indexedVecPreFamilyFVarInferOnlyState id type) := by + change TypeChecker.Inner.inferType' (.fvar id) true + (TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : TypeChecker.State) = _ + unfold TypeChecker.Inner.inferType' + simp [indexedVecPreFamilyFVarInferOnlyState, + Expr.hasLooseBVars, Expr.looseBVarRange', + TypeChecker.Inner.inferFVar, indexedVecTypeCheckerContext, + find, LocalDecl.type, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +private theorem indexedVecPreFamilyFVarEnsureTypeM + (lctx : LocalContext) (id : FVarId) (level : Level) + (find : lctx.find? id = + some (.cdecl index id name (.sort level) bi kind)) : + TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) (TypeChecker.ensureType (.fvar id)) = + .ok (.sort level) := by + unfold TypeChecker.ensureType TypeChecker.inferType + TypeChecker.ensureSort TypeChecker.RecM.run TypeChecker.M.run + simp only [readThe, MonadReaderOf.read, ReaderT.read, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + Pure.pure, StateT.pure, Except.pure, StateT.run', + Functor.map, Except.map] + rw [show TypeChecker.Inner.inferType (.fvar id) true + (TypeChecker.Methods.withFuel 10000) + { env := indexedVecKernelEnv, lctx := lctx, safety := .safe, + lparams := [`u], fuel := ({} : FuelConfig) } + ({} : TypeChecker.State) = + .ok (.sort level, + indexedVecPreFamilyFVarInferOnlyState id (.sort level)) by + simpa [indexedVecTypeCheckerContext] using + indexedVecPreFamilyFVarInferOnly lctx id (.sort level) find] + rfl + +private theorem indexedVecPreFamilyZeroCheckTypeM + (lctx : LocalContext) : + TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) (TypeChecker.checkType (.const ``Nat.zero [])) = + .ok (.const ``Nat []) := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.const ``Nat.zero []) false + (TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : TypeChecker.State)) = _ + rw [indexedVecPreFamilyInferTypeZeroCore 9999 lctx + ({} : TypeChecker.State) Std.HashMap.getElem?_empty] + rfl + +private theorem indexedVecPreFamilySuccFVarCheckTypeM + (lctx : LocalContext) (id : FVarId) + (find : lctx.find? id = + some (.cdecl index id name (.const ``Nat []) bi kind)) : + TypeChecker.M.run indexedVecKernelEnv .safe lctx [`u] + ({} : FuelConfig) + (TypeChecker.checkType (replaySuccApp (.fvar id))) = + .ok (.const ``Nat []) := by + let succState := replayInsert ({} : TypeChecker.State) + (.const ``Nat.succ []) + (.forallE `n (.const ``Nat []) (.const ``Nat []) .default) + let argumentState := replayInsert succState (.fvar id) (.const ``Nat []) + have succRun : TypeChecker.Inner.inferType' (.const ``Nat.succ []) false + (TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) ({} : TypeChecker.State) = + .ok (.forallE `n (.const ``Nat []) (.const ``Nat []) .default, + succState) := by + simpa [succState, replayInsert] using + (indexedVecPreFamilyInferTypeSuccCore 9999 lctx + ({} : TypeChecker.State) Std.HashMap.getElem?_empty) + have argumentRun : TypeChecker.Inner.inferType' (.fvar id) false + (TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) succState = + .ok (.const ``Nat [], argumentState) := by + apply indexedVecPreFamilyInferTypeFVarCore + · simp [succState, replayInsert] + · exact find + have appRun := inferAppCoreOf 9999 + (indexedVecTypeCheckerContext lctx) + ({} : TypeChecker.State) succState argumentState + (.const ``Nat.succ []) (.fvar id) (.const ``Nat []) + (.const ``Nat []) `n .default + (by simp [Expr.hasLooseBVars, Expr.looseBVarRange']) + (by simp) succRun argumentRun (by rfl) + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (replaySuccApp (.fvar id)) false + (TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : TypeChecker.State)) = _ + rw [show TypeChecker.Inner.inferType' + (replaySuccApp (.fvar id)) false + (TypeChecker.Methods.withFuel 9999) + (indexedVecTypeCheckerContext lctx) + ({} : TypeChecker.State) = + .ok (.const ``Nat [], + { argumentState with inferTypeC := + (argumentState.inferTypeC.insert + (replaySuccApp (.fvar id)) (.const ``Nat [])) }) by + simpa [replaySuccApp, Expr.instantiate1_eq, + Expr.instantiate1'] using appRun] + rfl + +private theorem indexedVecPreFamilyFVarCheckValid + (context : AddInductive.Context) (id : FVarId) (type : Expr) + (find : context.lctx.find? id = + some (.cdecl index id name type bi kind)) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, .fvar id, type⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilyFVarCheckTypeM context.lctx id type find + +private theorem indexedVecPreFamilyFVarEnsureValid + (context : AddInductive.Context) (id : FVarId) (level : Level) + (find : context.lctx.find? id = + some (.cdecl index id name (.sort level) bi kind)) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.ConstructorEnsureTypeStep.Valid + ⟨context, .fvar id, .sort level⟩ := by + unfold AddInductive.ConstructorEnsureTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilyFVarEnsureTypeM context.lctx id level find + +private theorem indexedVecPreFamilyZeroCheckValid + (context : AddInductive.Context) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, .const ``Nat.zero [], .const ``Nat []⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilyZeroCheckTypeM context.lctx + +private theorem indexedVecPreFamilySuccCheckValid + (context : AddInductive.Context) (id : FVarId) + (find : context.lctx.find? id = + some (.cdecl index id name (.const ``Nat []) bi kind)) + (contextEnv : context.env = indexedVecKernelEnv) + (contextSafety : context.safety = .safe) + (contextLparams : context.lparams = [`u]) + (contextFuel : context.fuel = ({} : FuelConfig)) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, replaySuccApp (.fvar id), .const ``Nat []⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + rw [contextEnv, contextSafety, contextLparams, contextFuel] + exact indexedVecPreFamilySuccFVarCheckTypeM context.lctx id find + +private theorem indexedVecNormalizationFamilyView_eq : + indexedVecNormalizationCandidate.families.singleton.familyType.type.view = + indexedVecInfo.type := by + change indexedVecFamilyCandidate.view = indexedVecInfo.type + exact indexedVecFamilyCandidate_view_eq + +private theorem indexedVecNormalizationConstructors_eq : + indexedVecNormalizationCandidate.families.singleton.constructors = + .cons indexedVecNilConstructorCandidate + (.cons indexedVecConsConstructorCandidate .nil) := rfl + +private theorem indexedVecNormalizationPreFamilyContext_eq : + indexedVecNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext = + indexedVecPreFamilyContext := rfl + +private theorem indexedVecPreFamilySafetyRun : + AddInductive.checkConstructorPreFamilySafety + indexedVecStagedUniverseInput.staged.family.validation.stats + indexedVecNormalizationCandidate.families.singleton.familyType.type.view + indexedVecNormalizationCandidate.families.singleton.constructors + indexedVecNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext = + .ok () := by + rw [indexedVecStagedStats_eq] + rw [indexedVecNormalizationFamilyView_eq, + indexedVecNormalizationConstructors_eq, + indexedVecNormalizationPreFamilyContext_eq] + change AddInductive.checkConstructorPreFamilySafety + indexedVecCandidateInductiveStats indexedVecInfo.type + (.cons indexedVecNilConstructorCandidate + (.cons indexedVecConsConstructorCandidate .nil)) + indexedVecPreFamilyContext = .ok () + have alphaFind : indexedVecPreFamilyContext.lctx.find? + indexedVecValidationAlphaId = + some (.cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default .default) := by + change indexedVecCtorValidationContext.lctx.find? + indexedVecValidationAlphaId = _ + exact indexedVecValidationAlphaFind + have alphaFindN : indexedVecPreFamilyNContext.lctx.find? + indexedVecValidationAlphaId = + some (.cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default .default) := by + change indexedVecValidationNContext.lctx.find? + indexedVecValidationAlphaId = _ + exact indexedVecValidationAlphaFindInN + have alphaFindHead : indexedVecPreFamilyHeadContext.lctx.find? + indexedVecValidationAlphaId = + some (.cdecl 0 indexedVecValidationAlphaId + indexedVecValidationParamName + (.sort (.succ (.param `u))) .default .default) := by + change indexedVecValidationHeadContext.lctx.find? + indexedVecValidationAlphaId = _ + exact indexedVecValidationAlphaFindInHead + have nFindHead : indexedVecPreFamilyHeadContext.lctx.find? + indexedVecValidationNId = + some (.cdecl 2 indexedVecValidationNId consNName + (.const ``Nat []) .implicit .default) := by + change indexedVecValidationHeadContext.lctx.find? + indexedVecValidationNId = _ + exact indexedVecValidationNFindInHead + have nFindResult : indexedVecPreFamilyResultContext.lctx.find? + indexedVecValidationNId = + some (.cdecl 2 indexedVecValidationNId consNName + (.const ``Nat []) .implicit .default) := by + simpa [indexedVecPreFamilyResultContext, + AddInductive.Context.advanceFresh] using nFindHead + have baseFresh : indexedVecPreFamilyContext.lctx.find? + indexedVecPreFamilyContext.freshFVarId = none := by + change indexedVecCtorValidationContext.lctx.find? + indexedVecCtorValidationContext.freshFVarId = none + exact indexedVecCtorValidationContextFresh + have nFresh : indexedVecPreFamilyNContext.lctx.find? + indexedVecPreFamilyNContext.freshFVarId = none := by + change indexedVecValidationNContext.lctx.find? + indexedVecValidationNContext.freshFVarId = none + exact indexedVecValidationNContextFresh + have headFresh : indexedVecPreFamilyHeadContext.lctx.find? + indexedVecPreFamilyHeadContext.freshFVarId = none := by + change indexedVecValidationHeadContext.lctx.find? + indexedVecValidationHeadContext.freshFVarId = none + exact indexedVecValidationHeadContextFresh + let baseTelescope : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyContext indexedVecPreFamilyIndexTelescope := + .ofRun (by + simp [indexedVecPreFamilyIndexTelescope, FVarsIn, + Level.hasMVar']) + (indexedVecPreFamilyTelescopeCheckValid + indexedVecPreFamilyContext rfl rfl rfl rfl) + let headTelescope : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyHeadContext indexedVecPreFamilyIndexTelescope := + .ofRun (by + simp [indexedVecPreFamilyIndexTelescope, FVarsIn, + Level.hasMVar']) + (indexedVecPreFamilyTelescopeCheckValid + indexedVecPreFamilyHeadContext rfl rfl rfl rfl) + let resultTelescope : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyResultContext indexedVecPreFamilyIndexTelescope := + .ofRun (by + simp [indexedVecPreFamilyIndexTelescope, FVarsIn, + Level.hasMVar']) + (indexedVecPreFamilyTelescopeCheckValid + indexedVecPreFamilyResultContext rfl rfl rfl rfl) + let baseSort : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyContext (.sort (.succ (.param `u))) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + (indexedVecPreFamilySortCheckValid + indexedVecPreFamilyContext rfl rfl rfl rfl) + let headSort : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyHeadContext (.sort (.succ (.param `u))) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + (indexedVecPreFamilySortCheckValid + indexedVecPreFamilyHeadContext rfl rfl rfl rfl) + let resultSort : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyResultContext (.sort (.succ (.param `u))) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + (indexedVecPreFamilySortCheckValid + indexedVecPreFamilyResultContext rfl rfl rfl rfl) + let baseNat : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyContext (.const ``Nat []) := + .ofRun (by simp [FVarsIn]) + (indexedVecPreFamilyNatCheckValid + indexedVecPreFamilyContext rfl rfl rfl rfl) + let headNat : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyHeadContext (.const ``Nat []) := + .ofRun (by simp [FVarsIn]) + (indexedVecPreFamilyNatCheckValid + indexedVecPreFamilyHeadContext rfl rfl rfl rfl) + let resultNat : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyResultContext (.const ``Nat []) := + .ofRun (by simp [FVarsIn]) + (indexedVecPreFamilyNatCheckValid + indexedVecPreFamilyResultContext rfl rfl rfl rfl) + let zeroChecked : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyContext (.const ``Nat.zero []) := + .ofRun (by simp [FVarsIn]) + (indexedVecPreFamilyZeroCheckValid + indexedVecPreFamilyContext rfl rfl rfl rfl) + let nChecked : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyHeadContext indexedVecValidationNExpr := by + rw [indexedVecValidationNExprShape] + exact .ofRun (by + change (indexedVecPreFamilyHeadContext.lctx.find? + indexedVecValidationNId).isSome = true + rw [nFindHead] + rfl) (indexedVecPreFamilyFVarCheckValid + indexedVecPreFamilyHeadContext indexedVecValidationNId + (.const ``Nat []) nFindHead rfl rfl rfl rfl) + let succChecked : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyResultContext + (replaySuccApp indexedVecValidationNExpr) := by + rw [indexedVecValidationNExprShape] + exact .ofRun (by + simp [replaySuccApp, FVarsIn] + change (indexedVecPreFamilyResultContext.lctx.find? + indexedVecValidationNId).isSome = true + rw [nFindResult] + rfl) (indexedVecPreFamilySuccCheckValid + indexedVecPreFamilyResultContext indexedVecValidationNId + nFindResult rfl rfl rfl rfl) + let zeroComparison : AddInductive.CandidateIsDefEqObservation + indexedVecPreFamilyContext (.const ``Nat []) (.const ``Nat []) := + ⟨candidateIsDefEqSelfValid indexedVecPreFamilyContext + (.const ``Nat []) 9999 rfl⟩ + let nComparison : AddInductive.CandidateIsDefEqObservation + indexedVecPreFamilyHeadContext (.const ``Nat []) (.const ``Nat []) := + ⟨candidateIsDefEqSelfValid indexedVecPreFamilyHeadContext + (.const ``Nat []) 9999 rfl⟩ + let succComparison : AddInductive.CandidateIsDefEqObservation + indexedVecPreFamilyResultContext (.const ``Nat []) (.const ``Nat []) := + ⟨candidateIsDefEqSelfValid indexedVecPreFamilyResultContext + (.const ``Nat []) 9999 rfl⟩ + let nilSpine : AddInductive.ConstructorPreFamilyIndexSpineTrace + indexedVecPreFamilyContext indexedVecPreFamilyIndexTelescope + [.const ``Nat.zero []] := by + unfold indexedVecPreFamilyIndexTelescope + exact .cons indexedVecPreFamilyContext + indexedVecInfo.type.bindingBody!.bindingName! + (.const ``Nat []) (.sort (.succ (.param `u))) .default + (.const ``Nat.zero []) [] baseTelescope + ⟨zeroChecked, baseNat, zeroComparison⟩ + (by + simpa [Expr.instantiate1_eq, Expr.instantiate1'] using + (AddInductive.ConstructorPreFamilyIndexSpineTrace.nil + indexedVecPreFamilyContext + (.sort (.succ (.param `u))) baseSort rfl)) + let recursiveSpine : AddInductive.ConstructorPreFamilyIndexSpineTrace + indexedVecPreFamilyHeadContext indexedVecPreFamilyIndexTelescope + [indexedVecValidationNExpr] := by + unfold indexedVecPreFamilyIndexTelescope + exact .cons indexedVecPreFamilyHeadContext + indexedVecInfo.type.bindingBody!.bindingName! + (.const ``Nat []) (.sort (.succ (.param `u))) .default + indexedVecValidationNExpr [] headTelescope + ⟨nChecked, headNat, nComparison⟩ + (by + simpa [Expr.instantiate1_eq, Expr.instantiate1'] using + (AddInductive.ConstructorPreFamilyIndexSpineTrace.nil + indexedVecPreFamilyHeadContext + (.sort (.succ (.param `u))) headSort rfl)) + let resultSpine : AddInductive.ConstructorPreFamilyIndexSpineTrace + indexedVecPreFamilyResultContext indexedVecPreFamilyIndexTelescope + [replaySuccApp indexedVecValidationNExpr] := by + unfold indexedVecPreFamilyIndexTelescope + exact .cons indexedVecPreFamilyResultContext + indexedVecInfo.type.bindingBody!.bindingName! + (.const ``Nat []) (.sort (.succ (.param `u))) .default + (replaySuccApp indexedVecValidationNExpr) [] resultTelescope + ⟨succChecked, resultNat, succComparison⟩ + (by + simpa [Expr.instantiate1_eq, Expr.instantiate1'] using + (AddInductive.ConstructorPreFamilyIndexSpineTrace.nil + indexedVecPreFamilyResultContext + (.sort (.succ (.param `u))) resultSort rfl)) + have nilArgs : indexedVecValidationNilResult.getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size = + [.const ``Nat.zero []] := by + simp [indexedVecValidationNilResult, + indexedVecValidationStatsParams, ctorIndexedVecAppGetAppArgs] + obtain ⟨nilTargetSpine, nilTargetSpineRun⟩ : + ∃ nilTargetSpine : AddInductive.ConstructorPreFamilyIndexSpineTrace + indexedVecPreFamilyContext indexedVecPreFamilyIndexTelescope + (indexedVecValidationNilResult.getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size), + AddInductive.ConstructorPreFamilyIndexSpineTrace.build + indexedVecPreFamilyContext indexedVecPreFamilyIndexTelescope + (indexedVecValidationNilResult.getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size) = + .ok nilTargetSpine := by + rw [nilArgs] + exact ⟨nilSpine, nilSpine.build_eq⟩ + have nilIndependent : AddInductive.constructorIndependentOf + indexedVecValidationNilResult [] = true := by + simp [AddInductive.constructorIndependentOf] + let nilTerminalTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecValidationNilResult 1 [] false := + .terminal indexedVecPreFamilyContext indexedVecValidationNilResult + 1 [] false indexedVecValidationNilResultIsValid nilIndependent + nilTargetSpine + have nilTerminalRun : + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecValidationNilResult 1 [] false 999 = + .ok nilTerminalTrace := by + exact AddInductive.ConstructorPreFamilyViewTrace.terminal_build_eq + (fuel := 998) rfl indexedVecValidationNilResultIsValid nilIndependent + nilTargetSpine + obtain ⟨nilTailTrace, nilTailRun⟩ : + ∃ nilTailTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + (nilCtorBodyRaw.instantiate1 indexedVecValidationAlpha) + 1 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + (nilCtorBodyRaw.instantiate1 indexedVecValidationAlpha) + 1 [] false 999 = + .ok nilTailTrace := by + rw [show nilCtorBodyRaw.instantiate1 indexedVecValidationAlpha = + indexedVecValidationNilResult by + simpa [nilInfoTypeShape, nilCtorTypeRaw] using + indexedVecValidationNilResultShape] + exact ⟨nilTerminalTrace, nilTerminalRun⟩ + have parameterAtZero : indexedVecCandidateInductiveStats.params[0]? = + some indexedVecValidationAlpha := by + rw [indexedVecValidationStatsParams] + rfl + obtain ⟨nilRawViewTrace, nilRawViewRun⟩ : + ∃ nilRawViewTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + nilCtorTypeRaw 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + nilCtorTypeRaw 0 [] false 1000 = .ok nilRawViewTrace := by + simp only [nilCtorTypeRaw, + AddInductive.ConstructorPreFamilyViewTrace.build] + split + · rename_i parameter parameterAt + rw [parameterAtZero] at parameterAt + cases parameterAt + rw [nilTailRun] + exact ⟨_, rfl⟩ + · rename_i noParameter + rw [parameterAtZero] at noParameter + contradiction + obtain ⟨nilViewTrace, nilViewRun⟩ : + ∃ nilViewTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecNilInfo.type 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecNilInfo.type 0 [] false 1000 = + .ok nilViewTrace := by + rw [nilInfoTypeShape] + exact ⟨nilRawViewTrace, nilRawViewRun⟩ + obtain ⟨nilHeadTrace, nilHeadRun⟩ : + ∃ nilHeadTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecNilConstructorCandidate.type.view 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecNilConstructorCandidate.type.view 0 [] false 1000 = + .ok nilHeadTrace := by + change ∃ nilHeadTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + nilCandidate.view 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + nilCandidate.view 0 [] false 1000 = .ok nilHeadTrace + rw [nilCandidate_view_eq] + exact ⟨nilViewTrace, nilViewRun⟩ + let baseNatEnsure : AddInductive.ConstructorEnsureTypeObservation + indexedVecPreFamilyContext (.const ``Nat []) := + ⟨.sort (.succ .zero), indexedVecPreFamilyNatEnsureValid + indexedVecPreFamilyContext rfl rfl rfl rfl⟩ + let baseNatConsumed : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyContext + (AddInductive.consumeTypeAnnotations (.const ``Nat [])) := by + rw [indexedVecValidationConsumeNat] + exact baseNat + let baseNatAnnotations : AddInductive.CandidateIsDefEqObservation + indexedVecPreFamilyContext (.const ``Nat []) + (AddInductive.consumeTypeAnnotations (.const ``Nat [])) := by + rw [indexedVecValidationConsumeNat] + exact ⟨candidateIsDefEqSelfValid indexedVecPreFamilyContext + (.const ``Nat []) 9999 rfl⟩ + let alphaChecked : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyNContext indexedVecValidationAlpha := by + rw [indexedVecValidationAlphaShape] + exact .ofRun (by + change (indexedVecPreFamilyNContext.lctx.find? + indexedVecValidationAlphaId).isSome = true + rw [alphaFindN] + rfl) (indexedVecPreFamilyFVarCheckValid + indexedVecPreFamilyNContext indexedVecValidationAlphaId + (.sort (.succ (.param `u))) alphaFindN rfl rfl rfl rfl) + let alphaEnsure : AddInductive.ConstructorEnsureTypeObservation + indexedVecPreFamilyNContext indexedVecValidationAlpha := by + rw [indexedVecValidationAlphaShape] + exact ⟨.sort (.succ (.param `u)), + indexedVecPreFamilyFVarEnsureValid indexedVecPreFamilyNContext + indexedVecValidationAlphaId (.succ (.param `u)) alphaFindN + rfl rfl rfl rfl⟩ + let alphaConsumed : AddInductive.ConstructorCheckedExpr + indexedVecPreFamilyNContext + (AddInductive.consumeTypeAnnotations indexedVecValidationAlpha) := by + rw [indexedVecValidationConsumeAlpha] + exact alphaChecked + let alphaAnnotations : AddInductive.CandidateIsDefEqObservation + indexedVecPreFamilyNContext indexedVecValidationAlpha + (AddInductive.consumeTypeAnnotations indexedVecValidationAlpha) := by + rw [indexedVecValidationConsumeAlpha] + exact ⟨candidateIsDefEqSelfValid indexedVecPreFamilyNContext + indexedVecValidationAlpha 9999 rfl⟩ + have alphaNeRemoved : indexedVecValidationAlphaId ≠ + indexedVecPreFamilyHeadContext.freshFVarId := by + intro equality + have fresh := headFresh + rw [← equality, alphaFindHead] at fresh + contradiction + have nNeRemoved : indexedVecValidationNId ≠ + indexedVecPreFamilyHeadContext.freshFVarId := by + intro equality + have fresh := headFresh + rw [← equality, nFindHead] at fresh + contradiction + have recursiveArgs : + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr).getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size = + [indexedVecValidationNExpr] := by + simp [indexedVecValidationStatsParams, ctorIndexedVecAppGetAppArgs] + obtain ⟨recursiveTargetSpine, recursiveTargetSpineRun⟩ : + ∃ recursiveTargetSpine : + AddInductive.ConstructorPreFamilyIndexSpineTrace + indexedVecPreFamilyHeadContext + indexedVecPreFamilyIndexTelescope + ((ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr).getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size), + AddInductive.ConstructorPreFamilyIndexSpineTrace.build + indexedVecPreFamilyHeadContext + indexedVecPreFamilyIndexTelescope + ((ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr).getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size) = + .ok recursiveTargetSpine := by + rw [recursiveArgs] + exact ⟨recursiveSpine, recursiveSpine.build_eq⟩ + have recursiveTargetValid : AddInductive.isValidIndAppIdx + indexedVecCandidateInductiveStats + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) 0 = true := + indexedVecValidationAppIsValidIdx indexedVecValidationNExpr + indexedVecValidationNHasNoIndOcc + let recursiveFieldTrace : AddInductive.ConstructorPreFamilyRecursiveTrace + indexedVecCandidateInductiveStats 0 indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + indexedVecPreFamilyHeadContext.fuel.inductiveFuel := + .target indexedVecPreFamilyHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + recursiveTargetValid recursiveTargetSpine + have recursiveFieldRun : AddInductive.ConstructorPreFamilyRecursiveTrace.build + indexedVecCandidateInductiveStats 0 indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + indexedVecPreFamilyHeadContext.fuel.inductiveFuel = + .ok recursiveFieldTrace := by + exact AddInductive.ConstructorPreFamilyRecursiveTrace.target_build_eq + (fuel := 999) rfl recursiveTargetValid recursiveTargetSpine + have recursiveIndependent : AddInductive.constructorIndependentOf + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) [] = true := by + simp [AddInductive.constructorIndependentOf] + have resultArgs : indexedVecValidationConsResult.getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size = + [replaySuccApp indexedVecValidationNExpr] := by + simp [indexedVecValidationConsResult, + indexedVecValidationStatsParams, ctorIndexedVecAppGetAppArgs] + obtain ⟨resultTargetSpine, resultTargetSpineRun⟩ : + ∃ resultTargetSpine : + AddInductive.ConstructorPreFamilyIndexSpineTrace + indexedVecPreFamilyResultContext + indexedVecPreFamilyIndexTelescope + (indexedVecValidationConsResult.getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size), + AddInductive.ConstructorPreFamilyIndexSpineTrace.build + indexedVecPreFamilyResultContext + indexedVecPreFamilyIndexTelescope + (indexedVecValidationConsResult.getAppArgs.toList.drop + indexedVecCandidateInductiveStats.params.size) = + .ok resultTargetSpine := by + rw [resultArgs] + exact ⟨resultSpine, resultSpine.build_eq⟩ + have resultIndependent : AddInductive.constructorIndependentOf + indexedVecValidationConsResult + [indexedVecPreFamilyHeadContext.freshFVarId] = true := by + simp [AddInductive.constructorIndependentOf, + indexedVecValidationConsResult, ctorIndexedVecApp, replaySuccApp, + Expr.fvarsList, + indexedVecValidationAlphaShape, indexedVecValidationNExprShape, + alphaNeRemoved, nNeRemoved] + let resultTerminalTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyResultContext indexedVecValidationConsResult 4 + [indexedVecPreFamilyHeadContext.freshFVarId] true := + .terminal indexedVecPreFamilyResultContext + indexedVecValidationConsResult 4 + [indexedVecPreFamilyHeadContext.freshFVarId] true + indexedVecValidationConsResultIsValid resultIndependent + resultTargetSpine + have resultTerminalRun : AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyResultContext indexedVecValidationConsResult 4 + [indexedVecPreFamilyHeadContext.freshFVarId] true 996 = + .ok resultTerminalTrace := by + exact AddInductive.ConstructorPreFamilyViewTrace.terminal_build_eq + (fuel := 995) rfl indexedVecValidationConsResultIsValid + resultIndependent resultTargetSpine + obtain ⟨consResultTailTrace, consResultTailRun⟩ : + ∃ consResultTailTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext.advanceFresh + (indexedVecValidationConsAfterHead.bindingBody!.instantiate1 + indexedVecPreFamilyHeadContext.freshExpr) + 4 [indexedVecPreFamilyHeadContext.freshFVarId] true, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext.advanceFresh + (indexedVecValidationConsAfterHead.bindingBody!.instantiate1 + indexedVecPreFamilyHeadContext.freshExpr) + 4 [indexedVecPreFamilyHeadContext.freshFVarId] true 996 = + .ok consResultTailTrace := by + rw [show indexedVecValidationConsAfterHead.bindingBody!.instantiate1 + indexedVecPreFamilyHeadContext.freshExpr = + indexedVecValidationConsResult by + change indexedVecValidationConsAfterHead.bindingBody!.instantiate1 + indexedVecValidationHeadContext.freshExpr = _ + exact indexedVecValidationConsResultShape] + exact ⟨resultTerminalTrace, resultTerminalRun⟩ + obtain ⟨explicitResultTailTrace, explicitResultTailRun⟩ : + ∃ explicitResultTailTrace : + AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext.advanceFresh + ((ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)).instantiate1 + indexedVecPreFamilyHeadContext.freshExpr) + 4 [indexedVecPreFamilyHeadContext.freshFVarId] true, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext.advanceFresh + ((ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)).instantiate1 + indexedVecPreFamilyHeadContext.freshExpr) + 4 [indexedVecPreFamilyHeadContext.freshFVarId] true 996 = + .ok explicitResultTailTrace := by + change ∃ explicitResultTailTrace : + AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext.advanceFresh + (indexedVecValidationConsAfterHead.bindingBody!.instantiate1 + indexedVecPreFamilyHeadContext.freshExpr) + 4 [indexedVecPreFamilyHeadContext.freshFVarId] true, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyHeadContext.advanceFresh + (indexedVecValidationConsAfterHead.bindingBody!.instantiate1 + indexedVecPreFamilyHeadContext.freshExpr) + 4 [indexedVecPreFamilyHeadContext.freshFVarId] true 996 = + .ok explicitResultTailTrace + exact ⟨consResultTailTrace, consResultTailRun⟩ + have noParameterThree : indexedVecCandidateInductiveStats.params[3]? = + none := by + rw [indexedVecValidationStatsParams] + rfl + obtain ⟨consAfterHeadTrace, consAfterHeadRun⟩ : + ∃ consAfterHeadTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyHeadContext + indexedVecValidationConsAfterHead 3 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyHeadContext + indexedVecValidationConsAfterHead 3 [] false 997 = + .ok consAfterHeadTrace := by + simp only [indexedVecValidationConsAfterHead, + AddInductive.ConstructorPreFamilyViewTrace.build] + split + · rename_i parameter parameterAt + rw [noParameterThree] at parameterAt + contradiction + · split + · rename_i nonrecursive + rw [indexedVecValidationTailHasIndOcc] at nonrecursive + contradiction + · rw [dif_pos recursiveIndependent, recursiveFieldRun] + simp only [Bind.bind, Except.bind] + rw [dif_pos headFresh] + rw [explicitResultTailRun] + exact ⟨_, rfl⟩ + obtain ⟨consHeadTailTrace, consHeadTailRun⟩ : + ∃ consHeadTailTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyHeadContext + (indexedVecValidationConsAfterN.bindingBody!.instantiate1 + indexedVecPreFamilyNContext.freshExpr) + 3 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyHeadContext + (indexedVecValidationConsAfterN.bindingBody!.instantiate1 + indexedVecPreFamilyNContext.freshExpr) + 3 [] false 997 = .ok consHeadTailTrace := by + rw [show indexedVecValidationConsAfterN.bindingBody!.instantiate1 + indexedVecPreFamilyNContext.freshExpr = + indexedVecValidationConsAfterHead by + change indexedVecValidationConsAfterN.bindingBody!.instantiate1 + indexedVecValidationNContext.freshExpr = _ + exact indexedVecValidationConsAfterHeadShape] + exact ⟨consAfterHeadTrace, consAfterHeadRun⟩ + obtain ⟨explicitHeadTailTrace, explicitHeadTailRun⟩ : + ∃ explicitHeadTailTrace : + AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + (indexedVecPreFamilyNContext.pushLocalDecl consHeadName .default + (AddInductive.consumeTypeAnnotations + indexedVecValidationAlpha)) + ((Expr.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)) + .default).instantiate1 indexedVecPreFamilyNContext.freshExpr) + 3 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + (indexedVecPreFamilyNContext.pushLocalDecl consHeadName .default + (AddInductive.consumeTypeAnnotations + indexedVecValidationAlpha)) + ((Expr.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)) + .default).instantiate1 indexedVecPreFamilyNContext.freshExpr) + 3 [] false 997 = .ok explicitHeadTailTrace := by + rw [indexedVecValidationConsumeAlpha] + rw [show Expr.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha + indexedVecValidationNExpr) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp indexedVecValidationNExpr)) .default = + indexedVecValidationConsAfterN.bindingBody! by rfl] + exact ⟨consHeadTailTrace, consHeadTailRun⟩ + have noParameterTwo : indexedVecCandidateInductiveStats.params[2]? = + none := by + rw [indexedVecValidationStatsParams] + rfl + obtain ⟨consAfterNTrace, consAfterNRun⟩ : + ∃ consAfterNTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyNContext + indexedVecValidationConsAfterN 2 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyNContext + indexedVecValidationConsAfterN 2 [] false 998 = + .ok consAfterNTrace := by + simp only [indexedVecValidationConsAfterN, + AddInductive.ConstructorPreFamilyViewTrace.build] + split + · rename_i parameter parameterAt + rw [noParameterTwo] at parameterAt + contradiction + · split + · rw [alphaChecked.check_eq, alphaEnsure.observe_eq, + alphaConsumed.check_eq] + rw [dif_pos (by + simp [AddInductive.constructorIndependentOf])] + simp only [Bind.bind, Except.bind] + rw [alphaAnnotations.observe_eq] + simp only [] + rw [dif_pos nFresh] + rw [explicitHeadTailRun] + exact ⟨_, rfl⟩ + · rename_i recursive + rw [indexedVecValidationAlphaHasNoIndOcc] at recursive + contradiction + obtain ⟨consNTailTrace, consNTailRun⟩ : + ∃ consNTailTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyNContext + (indexedVecValidationConsAfterParam.bindingBody!.instantiate1 + indexedVecPreFamilyContext.freshExpr) + 2 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyNContext + (indexedVecValidationConsAfterParam.bindingBody!.instantiate1 + indexedVecPreFamilyContext.freshExpr) + 2 [] false 998 = .ok consNTailTrace := by + rw [show indexedVecValidationConsAfterParam.bindingBody!.instantiate1 + indexedVecPreFamilyContext.freshExpr = + indexedVecValidationConsAfterN by + change indexedVecValidationConsAfterParam.bindingBody!.instantiate1 + indexedVecValidationNExpr = _ + exact indexedVecValidationConsAfterNShape] + exact ⟨consAfterNTrace, consAfterNRun⟩ + obtain ⟨explicitNTailTrace, explicitNTailRun⟩ : + ∃ explicitNTailTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + (indexedVecPreFamilyContext.pushLocalDecl consNName .implicit + (AddInductive.consumeTypeAnnotations (.const ``Nat []))) + ((Expr.forallE consHeadName indexedVecValidationAlpha + (Expr.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) .default) + .default).instantiate1 indexedVecPreFamilyContext.freshExpr) + 2 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope + (indexedVecPreFamilyContext.pushLocalDecl consNName .implicit + (AddInductive.consumeTypeAnnotations (.const ``Nat []))) + ((Expr.forallE consHeadName indexedVecValidationAlpha + (Expr.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) .default) + .default).instantiate1 indexedVecPreFamilyContext.freshExpr) + 2 [] false 998 = .ok explicitNTailTrace := by + rw [indexedVecValidationConsumeNat] + rw [show Expr.forallE consHeadName indexedVecValidationAlpha + (Expr.forallE consTailName + (ctorIndexedVecApp indexedVecValidationAlpha (.bvar 1)) + (ctorIndexedVecApp indexedVecValidationAlpha + (replaySuccApp (.bvar 2))) .default) .default = + indexedVecValidationConsAfterParam.bindingBody! by + rw [indexedVecValidationConsAfterParamExplicitShape] + rfl] + exact ⟨consNTailTrace, consNTailRun⟩ + have noParameterOne : indexedVecCandidateInductiveStats.params[1]? = + none := by + rw [indexedVecValidationStatsParams] + rfl + obtain ⟨consAfterParamTrace, consAfterParamRun⟩ : + ∃ consAfterParamTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecValidationConsAfterParam 1 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecValidationConsAfterParam 1 [] false 999 = + .ok consAfterParamTrace := by + rw [indexedVecValidationConsAfterParamExplicitShape] + simp only [AddInductive.ConstructorPreFamilyViewTrace.build] + split + · rename_i parameter parameterAt + rw [noParameterOne] at parameterAt + contradiction + · split + · rw [baseNat.check_eq, baseNatEnsure.observe_eq, + baseNatConsumed.check_eq] + rw [dif_pos (by + simp [AddInductive.constructorIndependentOf])] + simp only [Bind.bind, Except.bind] + rw [baseNatAnnotations.observe_eq] + simp only [] + rw [dif_pos baseFresh] + rw [explicitNTailRun] + exact ⟨_, rfl⟩ + · rename_i recursive + rw [indexedVecValidationNatHasNoIndOcc] at recursive + contradiction + obtain ⟨consParameterTailTrace, consParameterTailRun⟩ : + ∃ consParameterTailTrace : + AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + (consNTypeRaw.instantiate1 indexedVecValidationAlpha) + 1 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + (consNTypeRaw.instantiate1 indexedVecValidationAlpha) + 1 [] false 999 = .ok consParameterTailTrace := by + change ∃ consParameterTailTrace : + AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecValidationConsAfterParam 1 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecValidationConsAfterParam 1 [] false 999 = + .ok consParameterTailTrace + exact ⟨consAfterParamTrace, consAfterParamRun⟩ + obtain ⟨consRawViewTrace, consRawViewRun⟩ : + ∃ consRawViewTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + consCtorTypeRaw 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + consCtorTypeRaw 0 [] false 1000 = .ok consRawViewTrace := by + simp only [consCtorTypeRaw, + AddInductive.ConstructorPreFamilyViewTrace.build] + split + · rename_i parameter parameterAt + rw [parameterAtZero] at parameterAt + cases parameterAt + rw [consParameterTailRun] + exact ⟨_, rfl⟩ + · rename_i noParameter + rw [parameterAtZero] at noParameter + contradiction + obtain ⟨consViewTrace, consViewRun⟩ : + ∃ consViewTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecConsInfo.type 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecConsInfo.type 0 [] false 1000 = .ok consViewTrace := by + rw [consInfoTypeShape] + exact ⟨consRawViewTrace, consRawViewRun⟩ + obtain ⟨consHeadTrace, consHeadRun⟩ : + ∃ consHeadTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecConsConstructorCandidate.type.view 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + indexedVecConsConstructorCandidate.type.view 0 [] false 1000 = + .ok consHeadTrace := by + change ∃ consHeadTrace : AddInductive.ConstructorPreFamilyViewTrace + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + consCandidate.view 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + consCandidate.view 0 [] false 1000 = .ok consHeadTrace + rw [consCandidate_view_eq] + exact ⟨consViewTrace, consViewRun⟩ + let consListTrace : AddInductive.ConstructorPreFamilyListTrace + indexedVecCandidateInductiveStats 0 indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyContext + (.cons indexedVecConsConstructorCandidate .nil) := + .cons consHeadTrace .nil + have consListRun : AddInductive.ConstructorPreFamilyListTrace.build + indexedVecCandidateInductiveStats 0 indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyContext + (.cons indexedVecConsConstructorCandidate .nil) = + .ok consListTrace := by + exact AddInductive.ConstructorPreFamilyListTrace.cons_build_eq + consHeadTrace consHeadRun .nil rfl + let constructorListTrace : AddInductive.ConstructorPreFamilyListTrace + indexedVecCandidateInductiveStats 0 indexedVecPreFamilyIndexTelescope + indexedVecPreFamilyContext + (.cons indexedVecNilConstructorCandidate + (.cons indexedVecConsConstructorCandidate .nil)) := + .cons nilHeadTrace consListTrace + have constructorListRun : + AddInductive.ConstructorPreFamilyListTrace.build + indexedVecCandidateInductiveStats 0 + indexedVecPreFamilyIndexTelescope indexedVecPreFamilyContext + (.cons indexedVecNilConstructorCandidate + (.cons indexedVecConsConstructorCandidate .nil)) = + .ok constructorListTrace := by + exact AddInductive.ConstructorPreFamilyListTrace.cons_build_eq + nilHeadTrace nilHeadRun consListTrace consListRun + have parametersRun : AddInductive.instantiateFamilyParameters + indexedVecInfo.type indexedVecCandidateInductiveStats.params.toList = + .ok indexedVecPreFamilyIndexTelescope := by + rw [indexedVecPreFamilyIndexTelescope_eq] + rw [indexedVecValidationStatsParams] + rw [indexedVecInfoTypeShape] + simp [AddInductive.instantiateFamilyParameters, vecFamilyTail, vecIndexName, + Expr.instantiate1_eq, Expr.instantiate1', Pure.pure, Except.pure] + unfold AddInductive.checkConstructorPreFamilySafety + have translationUnique : + (AddInductive.theoryTranslationUnique indexedVecInfo.type && + (AddInductive.CandidateList.cons indexedVecNilConstructorCandidate + (AddInductive.CandidateList.cons indexedVecConsConstructorCandidate + (AddInductive.CandidateList.nil : AddInductive.CandidateList + AddInductive.CandidateConstructor []))).viewTranslationUnique) = + true := by + change (AddInductive.theoryTranslationUnique indexedVecInfo.type && + (nilCandidateTrace.viewTranslationUnique && + (consCandidateTrace.viewTranslationUnique && true))) = true + rw [nilCandidateTrace.viewTranslationUnique_eq, + consCandidateTrace.viewTranslationUnique_eq] + change (AddInductive.theoryTranslationUnique indexedVecInfo.type && + (AddInductive.theoryTranslationUnique nilCandidate.view && + (AddInductive.theoryTranslationUnique consCandidate.view && true))) = + true + rw [nilCandidate_view_eq, consCandidate_view_eq, + indexedVecInfoTypeShape, nilInfoTypeShape, consInfoTypeShape] + simp [AddInductive.theoryTranslationUnique, vecFamilyTail, + nilCtorTypeRaw, nilCtorBodyRaw, consCtorTypeRaw, consNTypeRaw, + consHeadTypeRaw, consTailTypeRaw, consTerminalRaw] + rw [if_pos translationUnique] + rw [parametersRun] + simp only [Bind.bind, Except.bind] + rw [constructorListRun] + rfl + +private def indexedVecStagedPreFamilyInput : + VInductDecl.StagedNormalizationCandidatePreFamilyInput + indexedVecFamilyCandidateContext ctorContext natFinalEnv [`u] + indexedVecNormalizationCandidate indexedVecDecl := + VInductDecl.StagedNormalizationCandidatePreFamilyInput.ofRun + indexedVecStagedPostFamilyInput indexedVecPreFamilySafetyRun + +/-- IndexedVec's ordinary fields are retained, its recursive tail is omitted, +and both constructor-result index spines admit the exact pre-family semantic +replay. -/ +theorem indexedVecProducedPreFamilySemantic_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidatePreFamilySemanticRun + indexedVecStagedPreFamilyInput) := + indexedVecStagedPreFamilyInput.exists + +private def indexedVecReorderedViewType : VInductiveType := + { indexedVecType with + ctors := [indexedVecType.ctors[1], indexedVecType.ctors[0]] } + +private def indexedVecReorderedViewDecl : VInductDecl := + { indexedVecDecl with types := [indexedVecReorderedViewType] } + +/-- Swapping the two otherwise unchanged constructor payloads fails the +computational normalization-shape gate before semantic or generation evidence +can be attached. -/ +theorem indexedVecReorderedView_rejected : + VInductDecl.normalization? indexedVecDecl + indexedVecReorderedViewDecl = none := rfl + +theorem indexedVecSemanticFamilyViewTr : + TrExpr natFinalEnv [`u] [] indexedVecFamilyCandidate.view + indexedVecType.type := by + rw [indexedVecFamilyCandidate_view_eq] + obtain ⟨u, htype⟩ := indexedVecType_wf + exact ⟨_, indexedVecSemanticFamilySourceTr, ⟨_, htype⟩⟩ + +theorem indexedVecSemanticNilViewTr : + TrExpr indexedVecTypeEnv [`u] [] nilCandidate.view + indexedVecType.ctors[0].type := by + rw [nilCandidate_view_eq] + obtain ⟨u, htype⟩ := indexedVecNil_wf + exact ⟨_, indexedVecSemanticNilSourceTr, ⟨_, htype⟩⟩ + +theorem indexedVecSemanticConsViewTr : + TrExpr indexedVecTypeEnv [`u] [] consCandidate.view + indexedVecType.ctors[1].type := by + rw [consCandidate_view_eq] + obtain ⟨u, htype⟩ := indexedVecSemanticConsIsType + exact ⟨_, indexedVecSemanticConsSourceTr, ⟨_, htype⟩⟩ + +def indexedVecSemanticFamilyRootRun : + TypeChecker.CandidateExprRootRun natFinalEnv [`u] + indexedVecFamilyCandidate indexedVecType.type indexedVecType.type where + contextRun := indexedVecSemanticFamilyContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + source_tr := indexedVecSemanticFamilySourceTr + view_tr := indexedVecSemanticFamilyViewTr + whnfFuel := 9999 + whnfDepth := rfl + +def indexedVecSemanticNilRootRun : + TypeChecker.CandidateExprRootRun indexedVecTypeEnv [`u] + nilCandidate indexedVecType.ctors[0].type + indexedVecType.ctors[0].type where + contextRun := by + simpa [nilCandidate, nilCandidateContext] using indexedVecSemanticCtorContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + source_tr := indexedVecSemanticNilSourceTr + view_tr := indexedVecSemanticNilViewTr + whnfFuel := 9999 + whnfDepth := rfl + +def indexedVecSemanticConsRootRun : + TypeChecker.CandidateExprRootRun indexedVecTypeEnv [`u] + consCandidate indexedVecType.ctors[1].type + indexedVecType.ctors[1].type where + contextRun := by + simpa [consCandidate, consRootContext] using indexedVecSemanticCtorContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + source_tr := indexedVecSemanticConsSourceTr + view_tr := indexedVecSemanticConsViewTr + whnfFuel := 9999 + whnfDepth := rfl + +def indexedVecSemanticFamilySemanticRootRun : + TypeChecker.CandidateExprSemanticRootRun natFinalEnv [`u] + indexedVecFamilyCandidate indexedVecType.type := + indexedVecSemanticFamilyRootRun.semanticOfIdentity + indexedVecFamilyCandidate_identity + +def indexedVecSemanticNilSemanticRootRun : + TypeChecker.CandidateExprSemanticRootRun indexedVecTypeEnv [`u] + nilCandidate indexedVecType.ctors[0].type := + indexedVecSemanticNilRootRun.semanticOfIdentity nilCandidate_identity + +def indexedVecSemanticConsSemanticRootRun : + TypeChecker.CandidateExprSemanticRootRun indexedVecTypeEnv [`u] + consCandidate indexedVecType.ctors[1].type := + indexedVecSemanticConsRootRun.semanticOfIdentity consCandidate_identity + +def indexedVecSemanticNilConstructorSemanticRun : + VInductDecl.CandidateConstructorSemanticRun indexedVecTypeEnv [`u] + indexedVecNilConstructorCandidate indexedVecType.ctors[0] where + name_eq := rfl + uvars_eq := rfl + type := indexedVecSemanticNilSemanticRootRun + +def indexedVecSemanticConsConstructorSemanticRun : + VInductDecl.CandidateConstructorSemanticRun indexedVecTypeEnv [`u] + indexedVecConsConstructorCandidate indexedVecType.ctors[1] where + name_eq := rfl + uvars_eq := rfl + type := indexedVecSemanticConsSemanticRootRun + +def indexedVecSemanticNilConstructorRun : + VInductDecl.CandidateConstructorRun indexedVecTypeEnv [`u] + indexedVecNilConstructorCandidate indexedVecType.ctors[0] := + indexedVecSemanticNilConstructorSemanticRun.root + +def indexedVecSemanticConsConstructorRun : + VInductDecl.CandidateConstructorRun indexedVecTypeEnv [`u] + indexedVecConsConstructorCandidate indexedVecType.ctors[1] := + indexedVecSemanticConsConstructorSemanticRun.root + +def indexedVecSemanticConstructorSemanticListRun : + VInductDecl.CandidateConstructorSemanticListRun indexedVecTypeEnv [`u] + indexedVecFamilyListCandidate.constructors indexedVecType.ctors := by + exact .cons indexedVecSemanticNilConstructorSemanticRun + (.cons indexedVecSemanticConsConstructorSemanticRun .nil) + +def indexedVecSemanticConstructorListRun : + VInductDecl.CandidateConstructorListRun indexedVecTypeEnv [`u] + indexedVecFamilyListCandidate.constructors indexedVecType.ctors := + indexedVecSemanticConstructorSemanticListRun.roots + +def indexedVecSemanticFamilySemanticRun : + VInductDecl.CandidateFamilySemanticRun natFinalEnv [`u] + indexedVecFamilyListCandidate indexedVecType where + name_eq := rfl + uvars_eq := rfl + type := indexedVecSemanticFamilySemanticRootRun + typeEnv := indexedVecTypeEnv + addType := rfl + constructors := indexedVecSemanticConstructorSemanticListRun + +def indexedVecSemanticFamilyRun : + VInductDecl.CandidateFamilyRun natFinalEnv [`u] + indexedVecFamilyListCandidate indexedVecType := + indexedVecSemanticFamilySemanticRun.root + +def indexedVecSemanticNormalizationCandidateRun : + VInductDecl.NormalizationCandidateRun natFinalEnv [`u] + indexedVecNormalizationCandidate indexedVecDecl where + raw := indexedVecType + raw_types_eq := rfl + uvars_eq := rfl + family := indexedVecSemanticFamilyRun + +/-- Reconstructing every family and constructor payload leaves the identity +IndexedVec declaration unchanged. -/ +theorem indexedVecSemantic_viewDecl_eq : + indexedVecSemanticNormalizationCandidateRun.viewDecl = + indexedVecDecl := rfl + +/-- The candidate-derived normalization is exactly the analyzer's canonical +identity normalization, not merely propositionally interchangeable with it. -/ +theorem indexedVecSemantic_normalization_eq : + indexedVecSemanticNormalizationCandidateRun.normalization = + indexedVecChecked.identityGeneration.block.normalization := rfl + +theorem indexedVecSemanticFamilySpineRun : + TypeChecker.CandidateExprSpineRun natFinalEnv [`u] + indexedVecFamilyCandidate indexedVecType.type + indexedVecType.type := + indexedVecSemanticFamilySemanticRootRun.spine + indexedVecFamilyCandidate_identity.storedSpine + +theorem indexedVecSemanticNilSpineRun : + TypeChecker.CandidateExprSpineRun indexedVecTypeEnv [`u] + nilCandidate indexedVecType.ctors[0].type + indexedVecType.ctors[0].type := + indexedVecSemanticNilSemanticRootRun.spine + nilCandidate_identity.storedSpine + +theorem indexedVecSemanticConsSpineRun : + TypeChecker.CandidateExprSpineRun indexedVecTypeEnv [`u] + consCandidate indexedVecType.ctors[1].type + indexedVecType.ctors[1].type := + indexedVecSemanticConsSemanticRootRun.spine + consCandidate_identity.storedSpine + +theorem indexedVecSemanticCandidate_generationShape : + VInductDecl.normalizationCandidateGenerationShape indexedVecDecl + indexedVecType indexedVecNormalizationCandidate = true := by + change ((indexedVecFamilyCandidate.trace.storedSpine && true) && + ((nilCandidate.trace.storedSpine && true) && + ((consCandidate.trace.storedSpine && true) && true))) = true + rw [indexedVecFamilyCandidate_identity.storedSpine, + nilCandidate_identity.storedSpine, + consCandidate_identity.storedSpine] + rfl + +/-- The consolidated constructor gate rejects truncation in either direction +before dependent semantic generation is assembled. -/ +theorem indexedVecSemanticCandidate_missingRawShape_rejected : + VInductDecl.candidateConstructorSemanticGenerationShape indexedVecDecl + (.cons indexedVecNilConstructorCandidate .nil) [] = false := + rfl + +theorem indexedVecSemanticCandidate_extraRawShape_rejected : + VInductDecl.candidateConstructorSemanticGenerationShape indexedVecDecl + .nil [indexedVecType.ctors[0]] = false := + rfl + +def indexedVecSemanticProducedGenerationShapeCandidate : + VInductDecl.ProducedGenerationShapeCandidate indexedVecDecl indexedVecType + indexedVecKernelType 0 false indexedVecFamilyCandidateContext where + candidate := indexedVecNormalizationCandidate + produced := indexedVecNormalizationCandidateProduced + shape := indexedVecSemanticCandidate_generationShape + +/-- The strengthened outer gate retains the complete parameter/index and +ordered `nil`/`cons` generation layout in the same produced result. -/ +theorem indexedVecSemanticGenerationShapeCandidate_produced : + VInductDecl.produceGenerationShapeCandidate indexedVecDecl indexedVecType + indexedVecKernelType 0 false indexedVecFamilyCandidateContext = + .ok indexedVecSemanticProducedGenerationShapeCandidate := by + have produced : + AddInductive.buildNormalizationCandidate indexedVecDecl.nparams + [indexedVecKernelType] 0 false indexedVecFamilyCandidateContext = + .ok indexedVecNormalizationCandidate := + indexedVecNormalizationCandidateProduced + simpa only [indexedVecSemanticProducedGenerationShapeCandidate] using + VInductDecl.produceGenerationShapeCandidate_eq_ok + (source := indexedVecDecl) (raw := indexedVecType) + produced indexedVecSemanticCandidate_generationShape + +private theorem indexedVecSemanticCandidate_analysis + (normalization : VInductDecl.NormalizationCandidateSemanticRun + natFinalEnv [`u] indexedVecNormalizationCandidate indexedVecDecl) : + normalization.root.normalization.generation? = + some indexedVecChecked.identityGeneration := by + let reference : VInductDecl.NormalizationCandidateSemanticRun natFinalEnv + [`u] indexedVecNormalizationCandidate indexedVecDecl := { + raw := indexedVecType + raw_types_eq := rfl + uvars_eq := rfl + family := indexedVecSemanticFamilySemanticRun } + rw [indexedVecStagedPreFamilyInput.normalization_eq normalization reference] + rfl + +/-- The parameter/index and two-constructor fixture closes through the same +generic staged-owner theorem without supplying its semantic hierarchy. -/ +theorem indexedVecSemanticExactProducedGenerationCandidatePackage_exists : + Nonempty (VInductDecl.ExactProducedGenerationCandidatePackage + natFinalEnv [`u] indexedVecSemanticProducedGenerationShapeCandidate + indexedVecChecked.identityGeneration) := + indexedVecSemanticProducedGenerationShapeCandidate + |>.exactProducedPackage_nonempty indexedVecStagedPreFamilyInput rfl + indexedVecChecked.identityGeneration indexedVecSemanticCandidate_analysis + +private def + indexedVecSemanticExactProducedGenerationCandidatePackage : + VInductDecl.ExactProducedGenerationCandidatePackage natFinalEnv [`u] + indexedVecSemanticProducedGenerationShapeCandidate + indexedVecChecked.identityGeneration := + indexedVecSemanticProducedGenerationShapeCandidate.exactProducedPackage + indexedVecStagedPreFamilyInput rfl indexedVecChecked.identityGeneration + indexedVecSemanticCandidate_analysis + +def indexedVecSemanticGenerationCandidateSemanticRun : + VInductDecl.GenerationCandidateSemanticRun + indexedVecSemanticExactProducedGenerationCandidatePackage.normalization + indexedVecChecked.identityGeneration := + indexedVecSemanticExactProducedGenerationCandidatePackage.semantic + +def indexedVecSemanticGenerationCandidateRun : + VInductDecl.GenerationCandidateRun + indexedVecSemanticExactProducedGenerationCandidatePackage.normalization.root + indexedVecChecked.identityGeneration := + indexedVecSemanticGenerationCandidateSemanticRun.run + +def indexedVecSemanticGenerationCandidatePackage : + VInductDecl.GenerationCandidatePackage natFinalEnv [`u] := + indexedVecSemanticGenerationCandidateSemanticRun.package + +def indexedVecSemanticProducedGenerationCandidatePackage : + VInductDecl.ProducedGenerationCandidatePackage natFinalEnv [`u] := + indexedVecSemanticExactProducedGenerationCandidatePackage.package + +def indexedVecSemanticGenerationCertificate : + indexedVecDecl.GenerationCertificate natFinalEnv where + generation := indexedVecChecked.identityGeneration + wf := + indexedVecSemanticExactProducedGenerationCandidatePackage.semantic.run.wf + +theorem indexedVecSemantic_addInductCertified : + natFinalEnv.addInductCertified indexedVecSemanticGenerationCertificate = + some indexedVecFinalEnv := by + rfl + +theorem indexedVecSemanticCertified_trace : + Nonempty (VEnv.AddInductGenerationTrace natFinalEnv + indexedVecFinalEnv indexedVecChecked.identityGeneration) := + VEnv.addInductCertified_trace indexedVecSemantic_addInductCertified + +theorem indexedVecSemanticCertified_ordered : + indexedVecFinalEnv.Ordered := + VEnv.addInductCertified_WF nat_env_wf.ordered + indexedVecSemantic_addInductCertified + +def indexedVecSemanticAddInductTraceChecked : + AddInductTrace natMap natFinalEnv indexedVecDecl indexedVecMap + indexedVecFinalEnv := by + refine indexedVecSemanticProducedGenerationCandidatePackage.package.addInductTrace + indexedVecTypeMap indexedVecTypeEnv indexedVecCtorMap + indexedVecCtorEnv indexedVecRecEnv ?_ ?_ ?_ ?_ ⟨rfl⟩ + · exact { + info := indexedVecInfo + kind_eq := by simp [indexedVecInfo, InductConstantKind.Matches] + tr := indexedVecInfo_tr + map_fresh := by + rw [show + indexedVecSemanticProducedGenerationCandidatePackage.package.generation.block.sourceType.name = + ``IndexedVec by rfl] + exact indexedVecType_fresh + env_add := rfl + map_add := rfl } + · refine .cons (m₂ := indexedVecNilMap) + (env₂ := indexedVecNilEnv) ?_ ?_ + · exact { + info := indexedVecNilInfo + kind_eq := by simp [indexedVecNilInfo, InductConstantKind.Matches] + tr := indexedVecNilInfo_tr + map_fresh := by simpa [indexedVecType] using indexedVecNil_fresh + env_add := rfl + map_add := rfl } + · refine .cons ?_ .nil + exact { + info := indexedVecConsInfo + kind_eq := by simp [indexedVecConsInfo, InductConstantKind.Matches] + tr := indexedVecConsInfo_tr + map_fresh := by simpa [indexedVecType] using indexedVecCons_fresh + env_add := rfl + map_add := rfl } + · exact { + info := indexedVecRecInfo + kind_eq := by simp [indexedVecRecInfo, InductConstantKind.Matches] + tr := indexedVecRecInfo_tr + map_fresh := by + rw [show + (inductGenerationRecVal + indexedVecSemanticProducedGenerationCandidatePackage.package.generation).name = + ``IndexedVec.rec by rfl] + exact indexedVecRec_fresh + env_add := rfl + map_add := rfl } + · decide + +theorem indexedVecSemantic_addInduct_checked : + AddInduct natMap natFinalEnv indexedVecDecl indexedVecMap + indexedVecFinalEnv := + ⟨indexedVecSemanticAddInductTraceChecked⟩ + +theorem indexedVecSemantic_trEnv'_checked : + TrEnv' .safe indexedVecMap false indexedVecFinalEnv := + .induct indexedVecSemantic_addInduct_checked nat_trEnv' + +theorem indexedVecSemantic_env_wf_checked : indexedVecFinalEnv.WF := + indexedVecSemantic_trEnv'_checked.wf + +theorem indexedVecSemantic_aligned_checked : + Aligned .safe indexedVecMap indexedVecFinalEnv := + indexedVecSemantic_trEnv'_checked.aligned + +/- +The semantic assembly, executable producer, and final E1 replay intentionally +inherit the existing transitional verifier closure. These guards make +additions to that closure visible at the public roots of this module. +-/ +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecProducedSemanticHierarchy_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecProducedPostFamilySemantic_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecProducedPreFamilySemantic_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecProducedSemanticHierarchy_constructorHeaders [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecReorderedView_rejected [propext] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecSemanticCandidate_missingRawShape_rejected [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecSemanticCandidate_extraRawShape_rejected [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecSemanticGenerationShapeCandidate_produced [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecSemanticExactProducedGenerationCandidatePackage_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecSemanticGenerationCandidateSemanticRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecSemanticProducedGenerationCandidatePackage [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVecSemantic_trEnv'_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean b/Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean new file mode 100644 index 000000000..0d9cb3079 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean @@ -0,0 +1,12189 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.Lemmas +import Ix.Theory.Named.Verify.Environment.ConstructorValidation +import Ix.Theory.Named.Reference.Inductive.Add +import Ix.Theory.Named.Meta +import Ix.Theory.Named.InductiveFixtures +import Ix.Theory.Named.Typing.Meta + +open Ix.Theory (VLevel) + +/-! End-to-end replay fixtures for inductive environment alignment. + +The Theory fixtures compare generated recursors and iota rules with Lean's +kernel declarations. This module closes the next bridge: it quotes the actual +`ConstantInfo` metadata, translates each metadata type in the precise +intermediate Theory environment, constructs `AddInduct`, and drives the live +`TrEnv'.induct` case. -/ + +namespace Ix.Theory.Named.InductiveReplayFixtures +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +/- These instances are used only by the elaborators below to quote the kernel +metadata returned by `getConstInfo`. -/ +deriving instance ToExpr for ConstantVal +deriving instance ToExpr for InductiveVal +deriving instance ToExpr for ConstructorVal +deriving instance ToExpr for RecursorRule +deriving instance ToExpr for RecursorVal +deriving instance ToExpr for ReducibilityHints +deriving instance ToExpr for DefinitionSafety +deriving instance ToExpr for DefinitionVal + +syntax "kernelInductInfo%" ident : term +syntax "kernelCtorInfo%" ident : term +syntax "kernelRecInfo%" ident : term +syntax "kernelRecRuleRhs%" ident num : term +syntax "kernelDefVal%" ident : term + +elab_rules : term + | `(kernelInductInfo% $n:ident) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .inductInfo info ← getConstInfo name + | throwError "expected inductive metadata for {name}" + return mkApp (mkConst ``ConstantInfo.inductInfo) (toExpr info) + | `(kernelCtorInfo% $n:ident) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .ctorInfo info ← getConstInfo name + | throwError "expected constructor metadata for {name}" + return mkApp (mkConst ``ConstantInfo.ctorInfo) (toExpr info) + | `(kernelRecInfo% $n:ident) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .recInfo info ← getConstInfo name + | throwError "expected recursor metadata for {name}" + return mkApp (mkConst ``ConstantInfo.recInfo) (toExpr info) + | `(kernelDefVal% $n:ident) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .defnInfo info ← getConstInfo name + | throwError "expected definition metadata for {name}" + return toExpr info + +/-- Quote one kernel recursor-rule RHS using the rule's own universe-parameter +order. This lets replay fixtures compare implementation metadata with the +Theory equation generator by reduction, including lambdas under recursive Pi +arguments. -/ +elab_rules : term + | `(kernelRecRuleRhs% $n:ident $i:num) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .recInfo info ← getConstInfo name + | throwError "expected recursor metadata for {name}" + let some rule := info.rules[i.getNat]? + | throwError "missing recursor rule {i.getNat} for {name}" + let rhs ← Ix.Theory.Named.Meta.expandExpr rule.rhs + let rhs ← Ix.Theory.Named.Meta.ofExpr info.levelParams {} rhs + return toExpr rhs + +/- Construct the representation-only half of a metadata-type translation. +The `to_trExprS` theorem supplies every typing premise from the declaration's +actual Theory `WF` evidence. -/ +syntax "tr_type_expr_tac" : tactic +macro_rules + | `(tactic| tr_type_expr_tac) => `(tactic| + first + | apply TrTypeExpr.bvar; rfl + | apply TrTypeExpr.sort; rfl + | apply TrTypeExpr.const <;> + (first | assumption | rfl | (dsimp; simp [VLevel.params'])) + | apply TrTypeExpr.app <;> tr_type_expr_tac + | apply TrTypeExpr.mdata; tr_type_expr_tac + | apply TrTypeExpr.forallE <;> tr_type_expr_tac) + +local instance : Inhabited VEnv := ⟨.empty⟩ + +/-! ## Nat -/ + +/-- Kernel metadata, captured at elaboration rather than reconstructed by the +fixture. A change in Lean's emitted record is therefore a compile failure. -/ +def natInfo : ConstantInfo := kernelInductInfo% Nat +def natZeroInfo : ConstantInfo := kernelCtorInfo% Nat.zero +def natSuccInfo : ConstantInfo := kernelCtorInfo% Nat.succ +def natRecInfo : ConstantInfo := kernelRecInfo% Nat.rec +def natZeroKernelRuleRhs : VExpr := kernelRecRuleRhs% Nat.rec 0 +def natSuccKernelRuleRhs : VExpr := kernelRecRuleRhs% Nat.rec 1 + +example : natInfo.name = ``Nat := rfl +example : natZeroInfo.name = ``Nat.zero := rfl +example : natSuccInfo.name = ``Nat.succ := rfl +example : natRecInfo.name = ``Nat.rec := rfl +example : natZeroKernelRuleRhs = + natChecked.identityGeneration.generatedRules[0].rhs := rfl +example : natSuccKernelRuleRhs = + natChecked.identityGeneration.generatedRules[1].rhs := rfl + +def natTypeEnv := (VEnv.empty.addConst natType.name natType.toVConstant).get! +def natZeroEnv := + (natTypeEnv.addConst natType.ctors[0].name natType.ctors[0].toVConstant).get! +def natCtorEnv := + (natZeroEnv.addConst natType.ctors[1].name natType.ctors[1].toVConstant).get! +def natRecEnv := + (natCtorEnv.addConst ``Nat.rec (VInductDecl.recConst 0 ``Nat 0 natType)).get! + +theorem natTypeEnv_ordered : natTypeEnv.Ordered := by + refine .const .empty ?_ rfl + exact ⟨.succ (.succ .zero), VEnv.HasType.sort (by decide)⟩ + +theorem natZeroEnv_ordered : natZeroEnv.Ordered := by + refine .const (n := natType.ctors[0].name) (ci := natType.ctors[0].toVConstant) + natTypeEnv_ordered ?_ rfl + have hNat : natTypeEnv.constants ``Nat = some natType.toVConstant := rfl + exact ⟨.succ .zero, by type_tac⟩ + +theorem natSucc_wf : natType.ctors[1].toVConstant.WF natZeroEnv := by + have hNat : natZeroEnv.constants ``Nat = some natType.toVConstant := rfl + refine ⟨.imax (.succ .zero) (.succ .zero), ?_⟩ + refine VEnv.HasType.forallE (u := .succ .zero) (v := .succ .zero) ?_ ?_ + · type_tac + · type_tac + +theorem natCtorEnv_ordered : natCtorEnv.Ordered := by + exact .const (n := natType.ctors[1].name) (ci := natType.ctors[1].toVConstant) + natZeroEnv_ordered natSucc_wf rfl + +/-- `Nat` satisfies the public Stage-3 declaration contract without a fixture +assumption. -/ +theorem natDecl_wf : natDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = natType := List.mem_singleton.1 (by simpa [natDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · change True + trivial + intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · constructor + · change True + trivial + · exact .nil + · have hc' := List.mem_singleton.1 hc + subst c + constructor + · refine ⟨.inl rfl, ?_, trivial⟩ + intro + exact .nil + · exact .nil + +/-- The exact intermediate invariant used to type the generated recursor. -/ +theorem natStage3 : + VInductDecl.Stage3Env natCtorEnv 0 ``Nat 0 (.succ .zero) natType := by + refine { + ord := natCtorEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := ?_ + htel := ?_ + hs3 := ?_ + hparams := ?_ + hfields := ?_ + hresult := ?_ } + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · rfl + · have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · rfl + · have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · rfl + · have hc' := List.mem_singleton.1 hc + subst c + rfl + · change True + trivial + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · change True + trivial + · have hc' := List.mem_singleton.1 hc + subst c + refine ⟨.inl rfl, ?_, trivial⟩ + intro + exact .nil + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · exact .nil + · have hc' := List.mem_singleton.1 hc + subst c + exact .nil + +theorem natInfo_tr : + TrConstVal .safe VEnv.empty natInfo natType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + exact .sort rfl + +theorem natZeroInfo_tr : + TrConstVal .safe natTypeEnv natZeroInfo natType.ctors[0] := by + have hNat : natTypeEnv.constants ``Nat = some natType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr natTypeEnv natZeroInfo.levelParams [] + natZeroInfo.type natType.ctors[0].type := by tr_type_expr_tac + exact hshape.to_trExprS natTypeEnv_ordered trivial + ⟨.sort (.succ .zero), by type_tac⟩ + +theorem natSuccInfo_tr : + TrConstVal .safe natZeroEnv natSuccInfo natType.ctors[1] := by + have hNat : natZeroEnv.constants ``Nat = some natType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr natZeroEnv natSuccInfo.levelParams [] + natSuccInfo.type natType.ctors[1].type := by + exact .forallE (.const hNat rfl rfl) (.const hNat rfl rfl) + exact hshape.to_trExprS natZeroEnv_ordered trivial + ⟨.sort (.imax (.succ .zero) (.succ .zero)), by + refine VEnv.HasType.forallE (u := .succ .zero) (v := .succ .zero) ?_ ?_ + · type_tac + · type_tac⟩ + +theorem natRecInfo_tr : + TrConstVal .safe natCtorEnv natRecInfo (inductRecVal natDecl natType) := by + have hNat : natCtorEnv.constants ``Nat = some natType.toVConstant := rfl + have hZero : + natCtorEnv.constants ``Nat.zero = some natType.ctors[0].toVConstant := rfl + have hSucc : + natCtorEnv.constants ``Nat.succ = some natType.ctors[1].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr natCtorEnv natRecInfo.levelParams [] natRecInfo.type + (inductRecVal natDecl natType).type := by tr_type_expr_tac + obtain ⟨u, hrec⟩ := natStage3.recConst_wf + exact hshape.to_trExprS natCtorEnv_ordered trivial ⟨.sort u, hrec⟩ + +def natTypeMap : ConstMap := ({} : ConstMap).insert ``Nat natInfo +def natZeroMap : ConstMap := natTypeMap.insert ``Nat.zero natZeroInfo +def natCtorMap : ConstMap := natZeroMap.insert ``Nat.succ natSuccInfo +def natMap : ConstMap := natCtorMap.insert ``Nat.rec natRecInfo +def natFinalEnv : VEnv := + (VInductDecl.rules 0 ``Nat 0 natType).foldl VEnv.addDefEq natRecEnv + +theorem natType_fresh : ({} : ConstMap).find? ``Nat = none := by + simp [SMap.find?] + +theorem natTypeMap_wf : natTypeMap.WF := + SMap.WF.empty.insert _ _ natType_fresh + +theorem natZero_fresh : natTypeMap.find? ``Nat.zero = none := by + rw [natTypeMap, SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem natZeroMap_wf : natZeroMap.WF := + natTypeMap_wf.insert _ _ natZero_fresh + +theorem natSucc_fresh : natZeroMap.find? ``Nat.succ = none := by + rw [natZeroMap, natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem natCtorMap_wf : natCtorMap.WF := + natZeroMap_wf.insert _ _ natSucc_fresh + +theorem natRec_fresh : natCtorMap.find? ``Nat.rec = none := by + rw [natCtorMap, natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +/-- A concrete `AddInduct` witness whose implementation side consists of the +actual kernel metadata above and whose Theory side is the Stage-3 Nat +transaction. -/ +theorem nat_addInduct : + AddInduct ({} : ConstMap) VEnv.empty natDecl natMap natFinalEnv := by + refine ⟨{ + generation := natChecked.identityGeneration + generation_wf := + (natChecked.wf_of_decl natDecl_wf).identityGeneration .empty + typeMap := natTypeMap + typeEnv := natTypeEnv + ctorMap := natCtorMap + ctorEnv := natCtorEnv + recEnv := natRecEnv + addType := { + info := natInfo + kind_eq := by simp [natInfo, InductConstantKind.Matches] + tr := natInfo_tr + map_fresh := by + change ({} : ConstMap).find? ``Nat = none + exact natType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := natRecInfo + kind_eq := by simp [natRecInfo, InductConstantKind.Matches] + tr := natRecInfo_tr + map_fresh := by + change natCtorMap.find? ``Nat.rec = none + exact natRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := natZeroInfo + kind_eq := by simp [natZeroInfo, InductConstantKind.Matches] + tr := natZeroInfo_tr + map_fresh := by simpa [natType] using natZero_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := natSuccInfo + kind_eq := by simp [natSuccInfo, InductConstantKind.Matches] + tr := natSuccInfo_tr + map_fresh := by + change natZeroMap.find? ``Nat.succ = none + exact natSucc_fresh + env_add := rfl + map_add := rfl } .nil) + +/-- The formerly impossible `TrEnv'.induct` branch, instantiated with a real +Lean declaration transaction. -/ +theorem nat_trEnv' {safety : DefinitionSafety} : + TrEnv' safety natMap false natFinalEnv := + .induct nat_addInduct .empty + +theorem nat_final_matches_addInduct : + VEnv.empty.addInduct natDecl = some natFinalEnv := + rfl + +/-- Theory-only ordering evidence for the Nat dependency environment. This +keeps later inductive preservation proofs entirely within the Theory layer. -/ +theorem natFinalEnv_ordered : natFinalEnv.Ordered := + VEnv.addInductGeneration_WF .empty + ((natChecked.wf_of_decl natDecl_wf).identityGeneration .empty) rfl + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.natFinalEnv_ordered [propext, Classical.choice, Quot.sound] + +theorem nat_env_wf : natFinalEnv.WF := (nat_trEnv' (safety := .safe)).wf + +theorem nat_aligned : Aligned .safe natMap natFinalEnv := (nat_trEnv' (safety := .safe)).aligned + +theorem nat_type_map_lookup : natMap.find? ``Nat = some natInfo := by + rw [natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, natTypeMap_wf.find?_insert, + natTypeMap, SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +theorem nat_type_env_lookup : + natFinalEnv.constants ``Nat = some natType.toVConstant := rfl + +theorem nat_type_lookup_unique : + natInfo.name = ``Nat ∧ + TrConstant .safe natFinalEnv natInfo natType.toVConstant := + nat_aligned.find?_uniq nat_type_map_lookup nat_type_env_lookup + +theorem nat_succ_map_lookup : natMap.find? ``Nat.succ = some natSuccInfo := by + rw [natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert] + rfl + +theorem nat_succ_env_lookup : natFinalEnv.constants ``Nat.succ = + some natType.ctors[1].toVConstant := rfl + +theorem nat_succ_lookup_unique : + natSuccInfo.name = ``Nat.succ ∧ + TrConstant .safe natFinalEnv natSuccInfo + natType.ctors[1].toVConstant := + nat_aligned.find?_uniq nat_succ_map_lookup nat_succ_env_lookup + +theorem nat_rec_map_lookup : natMap.find? ``Nat.rec = some natRecInfo := by + rw [natMap, natCtorMap_wf.find?_insert] + rfl + +theorem nat_rec_env_lookup : natFinalEnv.constants ``Nat.rec = + some (VInductDecl.recConst 0 ``Nat 0 natType) := rfl + +/-- Lookup uniqueness is tested at the generated recursor, after all iota +rules have been installed. -/ +theorem nat_rec_lookup_unique : + natRecInfo.name = ``Nat.rec ∧ + TrConstant .safe natFinalEnv natRecInfo + (VInductDecl.recConst 0 ``Nat 0 natType) := + nat_aligned.find?_uniq nat_rec_map_lookup nat_rec_env_lookup + +/- This closure is now free of `sorryAx`; the persistent-map contracts come +from proving concrete `SMap` freshness. The fixture introduces no new axiom. -/ +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.nat_trEnv' [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +/-! ## A value-bearing prefix followed by Nat -/ + +/-- A dependency-free definition used to ensure value translation survives a +later inductive metadata transaction. -/ +def ReplaySeed : Type 1 := Type + +def seedKernelDef : DefinitionVal := kernelDefVal% ReplaySeed +def seedInfo : ConstantInfo := .defnInfo seedKernelDef + +def seedVal : VDefVal where + name := ``ReplaySeed + uvars := 0 + type := .sort (.succ (.succ .zero)) + value := .sort (.succ .zero) + +theorem seedInfo_tr : TrDefVal .safe VEnv.empty seedInfo seedVal := by + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · exact .sort rfl + · exact .sort rfl + +theorem seedVal_wf : seedVal.WF VEnv.empty := + VEnv.HasType.sort (by decide) + +def seedConstEnv := (VEnv.empty.addConst seedVal.name seedVal.toVConstant).get! +def seedEnv := seedConstEnv.addDefEq seedVal.toDefEq +def seedMap : ConstMap := ({} : ConstMap).insert seedVal.name seedInfo + +theorem seed_fresh : ({} : ConstMap).find? seedVal.name = none := by + simp [seedVal, SMap.find?] + +theorem seed_trEnv' : TrEnv' .safe seedMap false seedEnv := + .defn (ci := seedKernelDef) (ci' := seedVal) seedInfo_tr seed_fresh + seedVal_wf rfl .empty + +theorem seed_map_lookup : seedMap.find? ``ReplaySeed = some seedInfo := by + rw [seedMap, SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +theorem seed_le : VEnv.empty ≤ seedEnv := + (VEnv.addConst_le (show VEnv.empty.addConst seedVal.name seedVal.toVConstant = + some seedConstEnv from rfl)).trans VEnv.addDefEq_le + +theorem seedEnv_ordered : seedEnv.Ordered := seed_trEnv'.wf.ordered + +def seedNatTypeEnv := (seedEnv.addConst natType.name natType.toVConstant).get! +def seedNatZeroEnv := + (seedNatTypeEnv.addConst natType.ctors[0].name natType.ctors[0].toVConstant).get! +def seedNatCtorEnv := + (seedNatZeroEnv.addConst natType.ctors[1].name natType.ctors[1].toVConstant).get! +def seedNatRecEnv := + (seedNatCtorEnv.addConst ``Nat.rec (VInductDecl.recConst 0 ``Nat 0 natType)).get! + +theorem natTypeEnv_le_seedNatTypeEnv : natTypeEnv ≤ seedNatTypeEnv := + VEnv.LE.addConst (n := natType.name) (ci := natType.toVConstant) seed_le rfl rfl + +theorem natZeroEnv_le_seedNatZeroEnv : natZeroEnv ≤ seedNatZeroEnv := + VEnv.LE.addConst (n := natType.ctors[0].name) + (ci := natType.ctors[0].toVConstant) natTypeEnv_le_seedNatTypeEnv rfl rfl + +theorem natCtorEnv_le_seedNatCtorEnv : natCtorEnv ≤ seedNatCtorEnv := + VEnv.LE.addConst (n := natType.ctors[1].name) + (ci := natType.ctors[1].toVConstant) natZeroEnv_le_seedNatZeroEnv rfl rfl + +theorem seedNatTypeEnv_ordered : seedNatTypeEnv.Ordered := by + refine .const (n := natType.name) (ci := natType.toVConstant) + seedEnv_ordered ?_ rfl + exact ⟨.succ (.succ .zero), VEnv.HasType.sort (by decide)⟩ + +theorem seedNatZeroEnv_ordered : seedNatZeroEnv.Ordered := by + refine .const (n := natType.ctors[0].name) (ci := natType.ctors[0].toVConstant) + seedNatTypeEnv_ordered ?_ rfl + have hNat : seedNatTypeEnv.constants ``Nat = some natType.toVConstant := rfl + exact ⟨.succ .zero, by type_tac⟩ + +theorem seedNatSucc_wf : natType.ctors[1].toVConstant.WF seedNatZeroEnv := by + have hNat : seedNatZeroEnv.constants ``Nat = some natType.toVConstant := rfl + refine ⟨.imax (.succ .zero) (.succ .zero), ?_⟩ + refine VEnv.HasType.forallE (u := .succ .zero) (v := .succ .zero) ?_ ?_ + · type_tac + · type_tac + +theorem seedNatCtorEnv_ordered : seedNatCtorEnv.Ordered := + .const (n := natType.ctors[1].name) (ci := natType.ctors[1].toVConstant) + seedNatZeroEnv_ordered seedNatSucc_wf rfl + +theorem seedNatInfo_tr : + TrConstVal .safe seedEnv natInfo natType.toVConstVal := + natInfo_tr.mono seed_le + +theorem seedNatZeroInfo_tr : + TrConstVal .safe seedNatTypeEnv natZeroInfo natType.ctors[0] := + natZeroInfo_tr.mono natTypeEnv_le_seedNatTypeEnv + +theorem seedNatSuccInfo_tr : + TrConstVal .safe seedNatZeroEnv natSuccInfo natType.ctors[1] := + natSuccInfo_tr.mono natZeroEnv_le_seedNatZeroEnv + +theorem seedNatRecInfo_tr : + TrConstVal .safe seedNatCtorEnv natRecInfo (inductRecVal natDecl natType) := + natRecInfo_tr.mono natCtorEnv_le_seedNatCtorEnv + +def seedNatTypeMap : ConstMap := seedMap.insert ``Nat natInfo +def seedNatZeroMap : ConstMap := seedNatTypeMap.insert ``Nat.zero natZeroInfo +def seedNatCtorMap : ConstMap := seedNatZeroMap.insert ``Nat.succ natSuccInfo +def seedNatMap : ConstMap := seedNatCtorMap.insert ``Nat.rec natRecInfo +def seedNatFinalEnv : VEnv := + (VInductDecl.rules 0 ``Nat 0 natType).foldl VEnv.addDefEq seedNatRecEnv + +theorem seedMap_wf : seedMap.WF := seed_trEnv'.map_wf + +theorem seedNatType_fresh : seedMap.find? ``Nat = none := by + rw [seedMap, SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [seedVal, SMap.find?] + +theorem seedNatTypeMap_wf : seedNatTypeMap.WF := + seedMap_wf.insert _ _ seedNatType_fresh + +theorem seedNatZero_fresh : seedNatTypeMap.find? ``Nat.zero = none := by + rw [seedNatTypeMap, seedMap_wf.find?_insert, seedMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [seedVal, SMap.find?] + +theorem seedNatZeroMap_wf : seedNatZeroMap.WF := + seedNatTypeMap_wf.insert _ _ seedNatZero_fresh + +theorem seedNatSucc_fresh : seedNatZeroMap.find? ``Nat.succ = none := by + rw [seedNatZeroMap, seedNatTypeMap_wf.find?_insert, seedNatTypeMap, + seedMap_wf.find?_insert, seedMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [seedVal, SMap.find?] + +theorem seedNatCtorMap_wf : seedNatCtorMap.WF := + seedNatZeroMap_wf.insert _ _ seedNatSucc_fresh + +theorem seedNatRec_fresh : seedNatCtorMap.find? ``Nat.rec = none := by + rw [seedNatCtorMap, seedNatZeroMap_wf.find?_insert, seedNatZeroMap, + seedNatTypeMap_wf.find?_insert, seedNatTypeMap, seedMap_wf.find?_insert, + seedMap, SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [seedVal, SMap.find?] + +theorem seedNat_addInduct : + AddInduct seedMap seedEnv natDecl seedNatMap seedNatFinalEnv := by + refine ⟨{ + generation := natChecked.identityGeneration + generation_wf := + (natChecked.wf_of_decl (natDecl_wf.mono seed_le)).identityGeneration + seedEnv_ordered + typeMap := seedNatTypeMap + typeEnv := seedNatTypeEnv + ctorMap := seedNatCtorMap + ctorEnv := seedNatCtorEnv + recEnv := seedNatRecEnv + addType := { + info := natInfo + kind_eq := by simp [natInfo, InductConstantKind.Matches] + tr := seedNatInfo_tr + map_fresh := by + change seedMap.find? ``Nat = none + exact seedNatType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := natRecInfo + kind_eq := by simp [natRecInfo, InductConstantKind.Matches] + tr := seedNatRecInfo_tr + map_fresh := by + change seedNatCtorMap.find? ``Nat.rec = none + exact seedNatRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := natZeroInfo + kind_eq := by simp [natZeroInfo, InductConstantKind.Matches] + tr := seedNatZeroInfo_tr + map_fresh := by simpa [natType] using seedNatZero_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := natSuccInfo + kind_eq := by simp [natSuccInfo, InductConstantKind.Matches] + tr := seedNatSuccInfo_tr + map_fresh := by + change seedNatZeroMap.find? ``Nat.succ = none + exact seedNatSucc_fresh + env_add := rfl + map_add := rfl } .nil) + +theorem seedNat_trEnv' : TrEnv' .safe seedNatMap false seedNatFinalEnv := + .induct seedNat_addInduct seed_trEnv' + +theorem seedNat_seed_lookup : seedNatMap.find? ``ReplaySeed = some seedInfo := by + rw [seedNatMap, seedNatCtorMap_wf.find?_insert, seedNatCtorMap, + seedNatZeroMap_wf.find?_insert, seedNatZeroMap, + seedNatTypeMap_wf.find?_insert, seedNatTypeMap, seedMap_wf.find?_insert] + simpa [seedVal] using seed_map_lookup + +/-- A concrete regression for the formerly impossible `TrEnv'.of_value` +inductive branch: the value was inserted before Nat, so this theorem must pull +its lookup back through every Nat metadata insertion. -/ +theorem seed_after_nat_of_value : + TrExpr seedNatFinalEnv seedInfo.levelParams [] seedKernelDef.value + (.const seedInfo.name (VLevel.params seedInfo.levelParams.length)) := + seedNat_trEnv'.of_value (name := ``ReplaySeed) (ci := seedInfo) + (v := seedKernelDef.value) seedNat_seed_lookup (by decide) rfl + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.seed_after_nat_of_value [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +/-! ## Eq -/ + +/- `Eq` exercises parameters, a genuine index, Prop-valued elimination, and +the kernel/generated recursor universe permutation. -/ +def eqInfo : ConstantInfo := kernelInductInfo% Eq +def eqReflInfo : ConstantInfo := kernelCtorInfo% Eq.refl +def eqRecInfo : ConstantInfo := kernelRecInfo% Eq.rec +def eqReflKernelRuleRhs : VExpr := kernelRecRuleRhs% Eq.rec 0 + +example : eqReflKernelRuleRhs = + eqChecked.identityGeneration.generatedRules[0].rhs := rfl + +def eqTypeEnv := (VEnv.empty.addConst eqType.name eqType.toVConstant).get! +def eqCtorEnv := + (eqTypeEnv.addConst eqType.ctors[0].name eqType.ctors[0].toVConstant).get! +def eqRecEnv := + (eqCtorEnv.addConst ``Eq.rec (VInductDecl.recConst 1 ``Eq 2 eqType)).get! + +theorem eqType_wf : eqType.toVConstant.WF VEnv.empty := by + refine ⟨.imax (.succ (.param 0)) + (.imax (.param 0) (.imax (.param 0) (.succ .zero))), ?_⟩ + refine VEnv.HasType.forallE + (u := .succ (.param 0)) + (v := .imax (.param 0) (.imax (.param 0) (.succ .zero))) ?_ ?_ + · exact VEnv.HasType.sort (by decide) + · refine VEnv.HasType.forallE + (u := .param 0) (v := .imax (.param 0) (.succ .zero)) ?_ ?_ + · type_tac + · refine VEnv.HasType.forallE + (u := .param 0) (v := .succ .zero) ?_ ?_ + · type_tac + · exact VEnv.HasType.sort (by decide) + +theorem eqTypeEnv_ordered : eqTypeEnv.Ordered := + .const .empty eqType_wf rfl + +theorem eqDecl_wf : eqDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = eqType := List.mem_singleton.1 (by simpa [eqDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · change VEnv.empty.OnTel 1 [] + [.sort (.param 0), .bvar 0, .bvar 1] + exact ⟨⟨.succ (.param 0), VEnv.HasType.sort (by decide)⟩, + ⟨⟨.param 0, by type_tac⟩, ⟨⟨.param 0, by type_tac⟩, trivial⟩⟩⟩ + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + constructor + · change True + trivial + · exact .cons (by type_tac) .nil + +theorem eqRefl_wf : eqType.ctors[0].toVConstant.WF eqTypeEnv := by + have hblock := eqDecl_wf.2 eqType (by simp [eqDecl]) + have hctor := hblock.2 eqType.ctors[0] (by simp) + have hle : VEnv.empty ≤ eqTypeEnv := VEnv.addConst_le rfl + have S0 : VInductDecl.Stage3Env eqTypeEnv 1 ``Eq 2 .zero + { eqType with ctors := [] } := { + ord := eqTypeEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := by simp + htel := by simp + hs3 := by simp + hparams := hblock.1.mono hle + hfields := by simp + hresult := by simp } + exact S0.ctorType_isType' rfl rfl + (VInductDecl.fieldsWF_mono hle hctor.1) (hctor.2.mono hle) + +theorem eqCtorEnv_ordered : eqCtorEnv.Ordered := + .const (n := eqType.ctors[0].name) (ci := eqType.ctors[0].toVConstant) + eqTypeEnv_ordered eqRefl_wf rfl + +theorem eqStage3 : + VInductDecl.Stage3Env eqCtorEnv 1 ``Eq 2 .zero eqType := by + have hblock := eqDecl_wf.2 eqType (by simp [eqDecl]) + have hctor := hblock.2 eqType.ctors[0] (by simp) + have h0 : VEnv.empty ≤ eqTypeEnv := + VEnv.addConst_le (show VEnv.empty.addConst eqType.name eqType.toVConstant = + some eqTypeEnv from rfl) + have h1 : eqTypeEnv ≤ eqCtorEnv := + VEnv.addConst_le (show eqTypeEnv.addConst eqType.ctors[0].name + eqType.ctors[0].toVConstant = some eqCtorEnv from rfl) + have hle : VEnv.empty ≤ eqCtorEnv := h0.trans h1 + refine { + ord := eqCtorEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + htel := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + hs3 := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + hparams := hblock.1.mono hle + hfields := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + exact VInductDecl.fieldsWF_mono hle hctor.1 + hresult := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + exact hctor.2.mono hle } + +theorem eqInfo_tr : + TrConstVal .safe VEnv.empty eqInfo eqType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr VEnv.empty eqInfo.levelParams [] eqInfo.type + eqType.type := by tr_type_expr_tac + obtain ⟨u, htype⟩ := eqType_wf + exact hshape.to_trExprS .empty trivial ⟨.sort u, htype⟩ + +theorem eqReflInfo_tr : + TrConstVal .safe eqTypeEnv eqReflInfo eqType.ctors[0] := by + have hEq : eqTypeEnv.constants ``Eq = some eqType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr eqTypeEnv eqReflInfo.levelParams [] eqReflInfo.type + eqType.ctors[0].type := by tr_type_expr_tac + obtain ⟨u, htype⟩ := eqRefl_wf + exact hshape.to_trExprS eqTypeEnv_ordered trivial ⟨.sort u, htype⟩ + +theorem eqRecInfo_tr : + TrConstVal .safe eqCtorEnv eqRecInfo (inductRecVal eqDecl eqType) := by + have hEq : eqCtorEnv.constants ``Eq = some eqType.toVConstant := rfl + have hRefl : eqCtorEnv.constants ``Eq.refl = + some eqType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr eqCtorEnv eqRecInfo.levelParams [] eqRecInfo.type + (inductRecVal eqDecl eqType).type := by tr_type_expr_tac + obtain ⟨u, hrec⟩ := eqStage3.recConst_wf + exact hshape.to_trExprS eqCtorEnv_ordered trivial ⟨.sort u, hrec⟩ + +def eqTypeMap : ConstMap := ({} : ConstMap).insert ``Eq eqInfo +def eqCtorMap : ConstMap := eqTypeMap.insert ``Eq.refl eqReflInfo +def eqMap : ConstMap := eqCtorMap.insert ``Eq.rec eqRecInfo +def eqFinalEnv : VEnv := + (VInductDecl.rules 1 ``Eq 2 eqType).foldl VEnv.addDefEq eqRecEnv + +theorem eqType_fresh : ({} : ConstMap).find? ``Eq = none := by + simp [SMap.find?] + +theorem eqTypeMap_wf : eqTypeMap.WF := + SMap.WF.empty.insert _ _ eqType_fresh + +theorem eqRefl_fresh : eqTypeMap.find? ``Eq.refl = none := by + rw [eqTypeMap, SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem eqCtorMap_wf : eqCtorMap.WF := + eqTypeMap_wf.insert _ _ eqRefl_fresh + +theorem eqRec_fresh : eqCtorMap.find? ``Eq.rec = none := by + rw [eqCtorMap, eqTypeMap_wf.find?_insert, eqTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem eq_addInduct : + AddInduct ({} : ConstMap) VEnv.empty eqDecl eqMap eqFinalEnv := by + refine ⟨{ + generation := eqChecked.identityGeneration + generation_wf := + (eqChecked.wf_of_decl eqDecl_wf).identityGeneration .empty + typeMap := eqTypeMap + typeEnv := eqTypeEnv + ctorMap := eqCtorMap + ctorEnv := eqCtorEnv + recEnv := eqRecEnv + addType := { + info := eqInfo + kind_eq := by simp [eqInfo, InductConstantKind.Matches] + tr := eqInfo_tr + map_fresh := by + change ({} : ConstMap).find? ``Eq = none + exact eqType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := eqRecInfo + kind_eq := by simp [eqRecInfo, InductConstantKind.Matches] + tr := eqRecInfo_tr + map_fresh := by + change eqCtorMap.find? ``Eq.rec = none + exact eqRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := eqReflInfo + kind_eq := by simp [eqReflInfo, InductConstantKind.Matches] + tr := eqReflInfo_tr + map_fresh := by simpa [eqType] using eqRefl_fresh + env_add := rfl + map_add := rfl } .nil + +/-- Replay actual kernel `Eq` metadata through the formerly empty inductive +environment branch. -/ +theorem eq_trEnv' : TrEnv' .safe eqMap false eqFinalEnv := + .induct eq_addInduct .empty + +theorem eq_final_matches_addInduct : + VEnv.empty.addInduct eqDecl = some eqFinalEnv := + rfl + +theorem eq_env_wf : eqFinalEnv.WF := eq_trEnv'.wf + +theorem eq_aligned : Aligned .safe eqMap eqFinalEnv := eq_trEnv'.aligned + +theorem eq_type_map_lookup : eqMap.find? ``Eq = some eqInfo := by + rw [eqMap, eqCtorMap_wf.find?_insert, eqCtorMap, + eqTypeMap_wf.find?_insert, eqTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +theorem eq_type_env_lookup : + eqFinalEnv.constants ``Eq = some eqType.toVConstant := rfl + +theorem eq_type_lookup_unique : + eqInfo.name = ``Eq ∧ + TrConstant .safe eqFinalEnv eqInfo eqType.toVConstant := + eq_aligned.find?_uniq eq_type_map_lookup eq_type_env_lookup + +theorem eq_refl_map_lookup : eqMap.find? ``Eq.refl = some eqReflInfo := by + rw [eqMap, eqCtorMap_wf.find?_insert, eqCtorMap, + eqTypeMap_wf.find?_insert] + rfl + +theorem eq_refl_env_lookup : eqFinalEnv.constants ``Eq.refl = + some eqType.ctors[0].toVConstant := rfl + +theorem eq_refl_lookup_unique : + eqReflInfo.name = ``Eq.refl ∧ + TrConstant .safe eqFinalEnv eqReflInfo + eqType.ctors[0].toVConstant := + eq_aligned.find?_uniq eq_refl_map_lookup eq_refl_env_lookup + +theorem eq_rec_map_lookup : eqMap.find? ``Eq.rec = some eqRecInfo := by + rw [eqMap, eqCtorMap_wf.find?_insert] + rfl + +theorem eq_rec_env_lookup : eqFinalEnv.constants ``Eq.rec = + some (VInductDecl.recConst 1 ``Eq 2 eqType) := rfl + +theorem eq_rec_lookup_unique : + eqRecInfo.name = ``Eq.rec ∧ + TrConstant .safe eqFinalEnv eqRecInfo + (VInductDecl.recConst 1 ``Eq 2 eqType) := + eq_aligned.find?_uniq eq_rec_map_lookup eq_rec_env_lookup + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.eq_trEnv' [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +/-! ## IndexedVec over the replayed Nat prefix -/ + +/- The fixture spells its changing index as `Nat.succ n` (and its base as +`Nat.zero`) so its kernel metadata has exactly the semantically relevant Nat +dependency prefix, rather than the unrelated `OfNat`/`HAdd` instance +implementation generated by notation. The declaration and every metadata +record below are still quoted from and checked against the real kernel +objects. -/ +def indexedVecInfo : ConstantInfo := kernelInductInfo% IndexedVec +def indexedVecNilInfo : ConstantInfo := kernelCtorInfo% IndexedVec.nil +def indexedVecConsInfo : ConstantInfo := kernelCtorInfo% IndexedVec.cons +def indexedVecRecInfo : ConstantInfo := kernelRecInfo% IndexedVec.rec +def indexedVecNilKernelRuleRhs : VExpr := + kernelRecRuleRhs% IndexedVec.rec 0 +def indexedVecConsKernelRuleRhs : VExpr := + kernelRecRuleRhs% IndexedVec.rec 1 + +example : indexedVecNilKernelRuleRhs = + indexedVecChecked.identityGeneration.generatedRules[0].rhs := rfl +example : indexedVecConsKernelRuleRhs = + indexedVecChecked.identityGeneration.generatedRules[1].rhs := rfl + +def indexedVecTypeEnv := + (natFinalEnv.addConst indexedVecType.name indexedVecType.toVConstant).get! +def indexedVecNilEnv := + (indexedVecTypeEnv.addConst indexedVecType.ctors[0].name + indexedVecType.ctors[0].toVConstant).get! +def indexedVecCtorEnv := + (indexedVecNilEnv.addConst indexedVecType.ctors[1].name + indexedVecType.ctors[1].toVConstant).get! +def indexedVecRecEnv := + (indexedVecCtorEnv.addConst ``IndexedVec.rec + (VInductDecl.recConst 1 ``IndexedVec 1 indexedVecType)).get! +theorem indexedVecType_wf : indexedVecType.toVConstant.WF natFinalEnv := by + have hNat : natFinalEnv.constants ``Nat = some natType.toVConstant := rfl + refine ⟨.imax (.succ (.succ (.param 0))) + (.imax (.succ .zero) (.succ (.succ (.param 0)))), ?_⟩ + refine VEnv.HasType.forallE + (u := .succ (.succ (.param 0))) + (v := .imax (.succ .zero) (.succ (.succ (.param 0)))) ?_ ?_ + · exact VEnv.HasType.sort (by decide) + · refine VEnv.HasType.forallE + (u := .succ .zero) (v := .succ (.succ (.param 0))) ?_ ?_ + · type_tac + · exact VEnv.HasType.sort (by decide) + +theorem indexedVecDecl_wf : indexedVecDecl.WF natFinalEnv := by + refine ⟨rfl, ?_⟩ + intro ty hty + have hty' : ty = indexedVecType := + List.mem_singleton.1 (by simpa [indexedVecDecl] using hty) + subst ty + refine ⟨?_, ?_⟩ + · change natFinalEnv.OnTel 1 [] + [.sort (.succ (.param 0)), .const ``Nat []] + have hNat : natFinalEnv.constants ``Nat = some natType.toVConstant := rfl + exact ⟨⟨.succ (.succ (.param 0)), VEnv.HasType.sort (by decide)⟩, + ⟨⟨.succ .zero, by type_tac⟩, trivial⟩⟩ + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · constructor + · change True + trivial + · change natFinalEnv.SpineWF 1 + [.sort (.succ (.param 0))] + (.forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + [.const ``Nat.zero []] (.sort (.succ (.param 0))) + have hNat : natFinalEnv.constants ``Nat = some natType.toVConstant := rfl + have hZero : natFinalEnv.constants ``Nat.zero = + some natType.ctors[0].toVConstant := rfl + exact .cons (by type_tac) .nil + · have hc' := List.mem_singleton.1 hc + subst c + constructor + · change VInductDecl.fieldsWF 1 ``IndexedVec 1 natFinalEnv + (VLevel.succ (VLevel.param 0)) [VExpr.const ``Nat []] + [VExpr.sort (VLevel.succ (VLevel.param 0))] 0 + [VExpr.const ``Nat [], VExpr.bvar 1, + VExpr.app (VExpr.app (VExpr.const ``IndexedVec [VLevel.param 0]) + (VExpr.bvar 2)) (VExpr.bvar 1)] + have hNat : natFinalEnv.constants ``Nat = some natType.toVConstant := rfl + constructor + · exact .inr (.inr ⟨rfl, .succ .zero, (by type_tac), + .inr (VLevel.succ_le_succ VLevel.zero_le)⟩) + constructor + · intro h + contradiction + constructor + · exact .inr (.inr ⟨rfl, .succ (.param 0), (by type_tac), + .inr (VLevel.le_refl _)⟩) + constructor + · intro h + contradiction + constructor + · exact .inl rfl + constructor + · intro _ + exact .cons (by type_tac) .nil + · trivial + · change natFinalEnv.SpineWF 1 + [VExpr.app (VExpr.app (VExpr.const ``IndexedVec [VLevel.param 0]) + (VExpr.bvar 2)) (VExpr.bvar 1), + VExpr.bvar 1, VExpr.const ``Nat [], + VExpr.sort (VLevel.succ (VLevel.param 0))] + (VExpr.forallE (VExpr.const ``Nat []) + (VExpr.sort (VLevel.succ (VLevel.param 0)))) + [VExpr.app (VExpr.const ``Nat.succ []) (VExpr.bvar 2)] + (VExpr.sort (VLevel.succ (VLevel.param 0))) + have hNat : natFinalEnv.constants ``Nat = some natType.toVConstant := rfl + have hSucc : natFinalEnv.constants ``Nat.succ = + some natType.ctors[1].toVConstant := rfl + exact .cons (by type_tac) .nil + +theorem natFinalEnv_le_indexedVecTypeEnv : natFinalEnv ≤ indexedVecTypeEnv := + VEnv.addConst_le (show natFinalEnv.addConst indexedVecType.name + indexedVecType.toVConstant = some indexedVecTypeEnv from rfl) + +theorem indexedVecTypeEnv_le_indexedVecNilEnv : + indexedVecTypeEnv ≤ indexedVecNilEnv := + VEnv.addConst_le (show indexedVecTypeEnv.addConst + indexedVecType.ctors[0].name indexedVecType.ctors[0].toVConstant = + some indexedVecNilEnv from rfl) + +theorem indexedVecNilEnv_le_indexedVecCtorEnv : + indexedVecNilEnv ≤ indexedVecCtorEnv := + VEnv.addConst_le (show indexedVecNilEnv.addConst + indexedVecType.ctors[1].name indexedVecType.ctors[1].toVConstant = + some indexedVecCtorEnv from rfl) + +theorem indexedVecTypeEnv_ordered : indexedVecTypeEnv.Ordered := + .const (n := indexedVecType.name) (ci := indexedVecType.toVConstant) + nat_env_wf.ordered indexedVecType_wf rfl + +theorem indexedVecNil_wf : + indexedVecType.ctors[0].toVConstant.WF indexedVecTypeEnv := by + have hblock := indexedVecDecl_wf.2 indexedVecType + (by simp [indexedVecDecl]) + have hctor := hblock.2 indexedVecType.ctors[0] (by simp) + have hle : natFinalEnv ≤ indexedVecTypeEnv := + natFinalEnv_le_indexedVecTypeEnv + have S0 : VInductDecl.Stage3Env indexedVecTypeEnv 1 ``IndexedVec 1 + (.succ (.param 0)) { indexedVecType with ctors := [] } := { + ord := indexedVecTypeEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := by simp + htel := by simp + hs3 := by simp + hparams := hblock.1.mono hle + hfields := by simp + hresult := by simp } + exact S0.ctorType_isType' rfl rfl + (VInductDecl.fieldsWF_mono hle hctor.1) (hctor.2.mono hle) + +theorem indexedVecNilEnv_ordered : indexedVecNilEnv.Ordered := + .const (n := indexedVecType.ctors[0].name) + (ci := indexedVecType.ctors[0].toVConstant) + indexedVecTypeEnv_ordered indexedVecNil_wf rfl + +theorem indexedVecCons_wf : + indexedVecType.ctors[1].toVConstant.WF indexedVecNilEnv := by + have hblock := indexedVecDecl_wf.2 indexedVecType + (by simp [indexedVecDecl]) + have hnil := hblock.2 indexedVecType.ctors[0] (by simp) + have hcons := hblock.2 indexedVecType.ctors[1] (by simp) + have h0 : natFinalEnv ≤ indexedVecTypeEnv := + natFinalEnv_le_indexedVecTypeEnv + have h1 : indexedVecTypeEnv ≤ indexedVecNilEnv := + indexedVecTypeEnv_le_indexedVecNilEnv + have hle : natFinalEnv ≤ indexedVecNilEnv := h0.trans h1 + have S1 : VInductDecl.Stage3Env indexedVecNilEnv 1 ``IndexedVec 1 + (.succ (.param 0)) + { indexedVecType with ctors := [indexedVecType.ctors[0]] } := { + ord := indexedVecNilEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + htel := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + hs3 := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + hparams := hblock.1.mono hle + hfields := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + exact VInductDecl.fieldsWF_mono hle hnil.1 + hresult := by + intro c hc + have hc' := List.mem_singleton.1 hc + subst c + exact hnil.2.mono hle } + exact S1.ctorType_isType' rfl rfl + (VInductDecl.fieldsWF_mono hle hcons.1) (hcons.2.mono hle) + +theorem indexedVecCtorEnv_ordered : indexedVecCtorEnv.Ordered := + .const (n := indexedVecType.ctors[1].name) + (ci := indexedVecType.ctors[1].toVConstant) + indexedVecNilEnv_ordered indexedVecCons_wf rfl + +theorem indexedVecStage3 : + VInductDecl.Stage3Env indexedVecCtorEnv 1 ``IndexedVec 1 + (.succ (.param 0)) indexedVecType := by + have hblock := indexedVecDecl_wf.2 indexedVecType + (by simp [indexedVecDecl]) + have h0 : natFinalEnv ≤ indexedVecTypeEnv := + natFinalEnv_le_indexedVecTypeEnv + have h1 : indexedVecTypeEnv ≤ indexedVecNilEnv := + indexedVecTypeEnv_le_indexedVecNilEnv + have h2 : indexedVecNilEnv ≤ indexedVecCtorEnv := + indexedVecNilEnv_le_indexedVecCtorEnv + have hle : natFinalEnv ≤ indexedVecCtorEnv := (h0.trans h1).trans h2 + refine { + ord := indexedVecCtorEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := ?_ + htel := ?_ + hs3 := ?_ + hparams := hblock.1.mono hle + hfields := ?_ + hresult := ?_ } + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · rfl + · have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · rfl + · have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + rcases List.mem_cons.1 hc with rfl | hc + · rfl + · have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + exact VInductDecl.fieldsWF_mono hle (hblock.2 c hc).1 + · intro c hc + exact (hblock.2 c hc).2.mono hle + +theorem indexedVecInfo_tr : + TrConstVal .safe natFinalEnv indexedVecInfo indexedVecType.toVConstVal := by + have hNat : natFinalEnv.constants ``Nat = some natType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr natFinalEnv indexedVecInfo.levelParams [] + indexedVecInfo.type indexedVecType.type := by tr_type_expr_tac + obtain ⟨u, htype⟩ := indexedVecType_wf + exact hshape.to_trExprS nat_env_wf.ordered trivial ⟨.sort u, htype⟩ + +theorem indexedVecNilInfo_tr : + TrConstVal .safe indexedVecTypeEnv indexedVecNilInfo + indexedVecType.ctors[0] := by + have hNat : indexedVecTypeEnv.constants ``Nat = some natType.toVConstant := rfl + have hZero : indexedVecTypeEnv.constants ``Nat.zero = + some natType.ctors[0].toVConstant := rfl + have hVec : indexedVecTypeEnv.constants ``IndexedVec = + some indexedVecType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedVecTypeEnv indexedVecNilInfo.levelParams [] + indexedVecNilInfo.type indexedVecType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := indexedVecNil_wf + exact hshape.to_trExprS indexedVecTypeEnv_ordered trivial ⟨.sort u, htype⟩ + +theorem indexedVecConsInfo_tr : + TrConstVal .safe indexedVecNilEnv indexedVecConsInfo + indexedVecType.ctors[1] := by + have hNat : indexedVecNilEnv.constants ``Nat = some natType.toVConstant := rfl + have hSucc : indexedVecNilEnv.constants ``Nat.succ = + some natType.ctors[1].toVConstant := rfl + have hVec : indexedVecNilEnv.constants ``IndexedVec = + some indexedVecType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedVecNilEnv indexedVecConsInfo.levelParams [] + indexedVecConsInfo.type indexedVecType.ctors[1].type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := indexedVecCons_wf + exact hshape.to_trExprS indexedVecNilEnv_ordered trivial ⟨.sort u, htype⟩ + +theorem indexedVecRecInfo_tr : + TrConstVal .safe indexedVecCtorEnv indexedVecRecInfo + (inductRecVal indexedVecDecl indexedVecType) := by + have hNat : indexedVecCtorEnv.constants ``Nat = some natType.toVConstant := rfl + have hZero : indexedVecCtorEnv.constants ``Nat.zero = + some natType.ctors[0].toVConstant := rfl + have hSucc : indexedVecCtorEnv.constants ``Nat.succ = + some natType.ctors[1].toVConstant := rfl + have hVec : indexedVecCtorEnv.constants ``IndexedVec = + some indexedVecType.toVConstant := rfl + have hNil : indexedVecCtorEnv.constants ``IndexedVec.nil = + some indexedVecType.ctors[0].toVConstant := rfl + have hCons : indexedVecCtorEnv.constants ``IndexedVec.cons = + some indexedVecType.ctors[1].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedVecCtorEnv indexedVecRecInfo.levelParams [] + indexedVecRecInfo.type + (inductRecVal indexedVecDecl indexedVecType).type := by + tr_type_expr_tac + obtain ⟨u, hrec⟩ := indexedVecStage3.recConst_wf + exact hshape.to_trExprS indexedVecCtorEnv_ordered trivial ⟨.sort u, hrec⟩ + +def indexedVecTypeMap : ConstMap := natMap.insert ``IndexedVec indexedVecInfo +def indexedVecNilMap : ConstMap := + indexedVecTypeMap.insert ``IndexedVec.nil indexedVecNilInfo +def indexedVecCtorMap : ConstMap := + indexedVecNilMap.insert ``IndexedVec.cons indexedVecConsInfo +def indexedVecMap : ConstMap := + indexedVecCtorMap.insert ``IndexedVec.rec indexedVecRecInfo +def indexedVecFinalEnv : VEnv := + (VInductDecl.rules 1 ``IndexedVec 1 indexedVecType).foldl + VEnv.addDefEq indexedVecRecEnv + +theorem natMap_wf : natMap.WF := (nat_trEnv' (safety := .safe)).map_wf + +theorem indexedVecType_fresh : natMap.find? ``IndexedVec = none := by + rw [natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedVecTypeMap_wf : indexedVecTypeMap.WF := + natMap_wf.insert _ _ indexedVecType_fresh + +theorem indexedVecNil_fresh : + indexedVecTypeMap.find? ``IndexedVec.nil = none := by + rw [indexedVecTypeMap, natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedVecNilMap_wf : indexedVecNilMap.WF := + indexedVecTypeMap_wf.insert _ _ indexedVecNil_fresh + +theorem indexedVecCons_fresh : + indexedVecNilMap.find? ``IndexedVec.cons = none := by + rw [indexedVecNilMap, indexedVecTypeMap_wf.find?_insert, + indexedVecTypeMap, natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedVecCtorMap_wf : indexedVecCtorMap.WF := + indexedVecNilMap_wf.insert _ _ indexedVecCons_fresh + +theorem indexedVecRec_fresh : + indexedVecCtorMap.find? ``IndexedVec.rec = none := by + rw [indexedVecCtorMap, indexedVecNilMap_wf.find?_insert, + indexedVecNilMap, indexedVecTypeMap_wf.find?_insert, + indexedVecTypeMap, natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedVec_addInduct : + AddInduct natMap natFinalEnv indexedVecDecl indexedVecMap + indexedVecFinalEnv := by + refine ⟨{ + generation := indexedVecChecked.identityGeneration + generation_wf := + (indexedVecChecked.wf_of_decl indexedVecDecl_wf).identityGeneration + nat_env_wf.ordered + typeMap := indexedVecTypeMap + typeEnv := indexedVecTypeEnv + ctorMap := indexedVecCtorMap + ctorEnv := indexedVecCtorEnv + recEnv := indexedVecRecEnv + addType := { + info := indexedVecInfo + kind_eq := by simp [indexedVecInfo, InductConstantKind.Matches] + tr := indexedVecInfo_tr + map_fresh := by + change natMap.find? ``IndexedVec = none + exact indexedVecType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := indexedVecRecInfo + kind_eq := by simp [indexedVecRecInfo, InductConstantKind.Matches] + tr := indexedVecRecInfo_tr + map_fresh := by + change indexedVecCtorMap.find? ``IndexedVec.rec = none + exact indexedVecRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := indexedVecNilInfo + kind_eq := by simp [indexedVecNilInfo, InductConstantKind.Matches] + tr := indexedVecNilInfo_tr + map_fresh := by simpa [indexedVecType] using indexedVecNil_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := indexedVecConsInfo + kind_eq := by simp [indexedVecConsInfo, InductConstantKind.Matches] + tr := indexedVecConsInfo_tr + map_fresh := by + change indexedVecNilMap.find? ``IndexedVec.cons = none + exact indexedVecCons_fresh + env_add := rfl + map_add := rfl } .nil) + +theorem indexedVec_trEnv' : + TrEnv' .safe indexedVecMap false indexedVecFinalEnv := + .induct indexedVec_addInduct nat_trEnv' + +theorem indexedVec_final_matches_addInduct : + natFinalEnv.addInduct indexedVecDecl = some indexedVecFinalEnv := + rfl + +theorem indexedVec_env_wf : indexedVecFinalEnv.WF := indexedVec_trEnv'.wf + +theorem indexedVec_aligned : + Aligned .safe indexedVecMap indexedVecFinalEnv := + indexedVec_trEnv'.aligned + +theorem indexedVec_type_map_lookup : + indexedVecMap.find? ``IndexedVec = some indexedVecInfo := by + rw [indexedVecMap, indexedVecCtorMap_wf.find?_insert, indexedVecCtorMap, + indexedVecNilMap_wf.find?_insert, indexedVecNilMap, + indexedVecTypeMap_wf.find?_insert, indexedVecTypeMap, + natMap_wf.find?_insert] + rfl + +theorem indexedVec_type_env_lookup : + indexedVecFinalEnv.constants ``IndexedVec = + some indexedVecType.toVConstant := rfl + +theorem indexedVec_type_lookup_unique : + indexedVecInfo.name = ``IndexedVec ∧ + TrConstant .safe indexedVecFinalEnv indexedVecInfo + indexedVecType.toVConstant := + indexedVec_aligned.find?_uniq indexedVec_type_map_lookup + indexedVec_type_env_lookup + +theorem indexedVec_cons_map_lookup : + indexedVecMap.find? ``IndexedVec.cons = some indexedVecConsInfo := by + rw [indexedVecMap, indexedVecCtorMap_wf.find?_insert, indexedVecCtorMap, + indexedVecNilMap_wf.find?_insert] + rfl + +theorem indexedVec_cons_env_lookup : + indexedVecFinalEnv.constants ``IndexedVec.cons = + some indexedVecType.ctors[1].toVConstant := rfl + +theorem indexedVec_cons_lookup_unique : + indexedVecConsInfo.name = ``IndexedVec.cons ∧ + TrConstant .safe indexedVecFinalEnv indexedVecConsInfo + indexedVecType.ctors[1].toVConstant := + indexedVec_aligned.find?_uniq indexedVec_cons_map_lookup + indexedVec_cons_env_lookup + +theorem indexedVec_rec_map_lookup : + indexedVecMap.find? ``IndexedVec.rec = some indexedVecRecInfo := by + rw [indexedVecMap, indexedVecCtorMap_wf.find?_insert] + rfl + +theorem indexedVec_rec_env_lookup : + indexedVecFinalEnv.constants ``IndexedVec.rec = + some (VInductDecl.recConst 1 ``IndexedVec 1 indexedVecType) := rfl + +theorem indexedVec_rec_lookup_unique : + indexedVecRecInfo.name = ``IndexedVec.rec ∧ + TrConstant .safe indexedVecFinalEnv indexedVecRecInfo + (VInductDecl.recConst 1 ``IndexedVec 1 indexedVecType) := + indexedVec_aligned.find?_uniq indexedVec_rec_map_lookup + indexedVec_rec_env_lookup + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.indexedVec_trEnv' [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +/-! ## Acc: recursive Pi metadata -/ + +/- `Acc` is the first replay whose recursive constructor argument is a +function. In addition to translating the three kernel constants, this fixture +quotes the actual `RecursorRule.rhs` and compares it definitionally with the +public generalized Theory rule. -/ +def accInfo : ConstantInfo := kernelInductInfo% Acc +def accIntroInfo : ConstantInfo := kernelCtorInfo% Acc.intro +def accRecInfo : ConstantInfo := kernelRecInfo% Acc.rec +def accKernelRuleRhs : VExpr := kernelRecRuleRhs% Acc.rec 0 + +example : (match accIntroInfo with + | .ctorInfo ci => ci.numParams + | _ => 0) = 2 := rfl +example : (match accIntroInfo with + | .ctorInfo ci => ci.numFields + | _ => 0) = 2 := rfl +example : (match accRecInfo with + | .recInfo ci => ci.numParams + | _ => 0) = 2 := rfl +example : (match accRecInfo with + | .recInfo ci => ci.numIndices + | _ => 0) = 1 := rfl +example : (match accRecInfo with + | .recInfo ci => ci.numMotives + | _ => 0) = 1 := rfl +example : (match accRecInfo with + | .recInfo ci => ci.numMinors + | _ => 0) = 1 := rfl +example : (match accRecInfo with + | .recInfo ci => ci.rules.length + | _ => 0) = 1 := rfl +example : (match accRecInfo with + | .recInfo ci => ci.rules[0]?.map (·.ctor) |>.getD .anonymous + | _ => .anonymous) = ``Acc.intro := rfl +example : (match accRecInfo with + | .recInfo ci => ci.rules[0]?.map (·.nfields) |>.getD 0 + | _ => 0) = 2 := rfl + +/-- The actual kernel rule has the same lambda-wrapped functional recursive +call as the public Theory generator, in the kernel recursor's universe order. -/ +example : accKernelRuleRhs = + (VInductDecl.ruleRec 1 ``Acc 2 accType 0 accType.ctors[0]).rhs := rfl +example : accKernelRuleRhs = + accChecked.identityGeneration.generatedRules[0].rhs := rfl + +def accTypeEnv := (VEnv.empty.addConst accType.name accType.toVConstant).get! +def accCtorEnv := + (accTypeEnv.addConst accType.ctors[0].name accType.ctors[0].toVConstant).get! +def accRecEnv := + (accCtorEnv.addConst ``Acc.rec + (VInductDecl.recConstRec 1 ``Acc 2 accType)).get! + +theorem accType_wf : accType.toVConstant.WF VEnv.empty := by + have htel := (accDecl_wf.2 accType (by simp [accDecl])).1 + change VEnv.empty.IsType 1 [] accType.type + rw [show accType.type = VExpr.forallN + [.sort (.param 0), + .forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero)), + .bvar 1] (.sort .zero) from rfl] + exact VEnv.IsType.forallN htel ⟨.succ .zero, VEnv.HasType.sort (by decide)⟩ + +theorem accTypeEnv_ordered : accTypeEnv.Ordered := + .const .empty accType_wf rfl + +theorem accIntro_wf : accType.ctors[0].toVConstant.WF accTypeEnv := by + have hblock := accDecl_wf.2 accType (by simp [accDecl]) + have hctor := hblock.2 accType.ctors[0] (by simp) + have hle : VEnv.empty ≤ accTypeEnv := VEnv.addConst_le rfl + have S0 : VInductDecl.Stage3Env accTypeEnv 1 ``Acc 2 .zero + { accType with ctors := [] } := { + ord := accTypeEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := by simp + htel := by simp + hs3 := by simp + hparams := hblock.1.mono hle + hfields := by simp + hresult := by simp } + exact S0.ctorType_isType' rfl rfl + (VInductDecl.fieldsWF_mono hle hctor.1) (hctor.2.mono hle) + +theorem accCtorEnv_ordered : accCtorEnv.Ordered := + .const (n := accType.ctors[0].name) (ci := accType.ctors[0].toVConstant) + accTypeEnv_ordered accIntro_wf rfl + +theorem accStage3 : + VInductDecl.Stage3Env accCtorEnv 1 ``Acc 2 .zero accType := by + have hblock := accDecl_wf.2 accType (by simp [accDecl]) + have hctor := hblock.2 accType.ctors[0] (by simp) + have h0 : VEnv.empty ≤ accTypeEnv := VEnv.addConst_le rfl + have h1 : accTypeEnv ≤ accCtorEnv := + VEnv.addConst_le (show accTypeEnv.addConst accType.ctors[0].name + accType.ctors[0].toVConstant = some accCtorEnv from rfl) + have hle : VEnv.empty ≤ accCtorEnv := h0.trans h1 + refine { + ord := accCtorEnv_ordered + hl := by decide + hsort := rfl + hlen := rfl + hT := rfl + hcs := ?_ + htel := ?_ + hs3 := ?_ + hparams := hblock.1.mono hle + hfields := ?_ + hresult := ?_ } + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + rfl + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + exact VInductDecl.fieldsWF_mono hle hctor.1 + · intro c hc + have hc' := List.mem_singleton.1 hc + subst c + exact hctor.2.mono hle + +theorem accInfo_tr : + TrConstVal .safe VEnv.empty accInfo accType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr VEnv.empty accInfo.levelParams [] accInfo.type + accType.type := by tr_type_expr_tac + obtain ⟨u, htype⟩ := accType_wf + exact hshape.to_trExprS .empty trivial ⟨.sort u, htype⟩ + +theorem accIntroInfo_tr : + TrConstVal .safe accTypeEnv accIntroInfo accType.ctors[0] := by + have hAcc : accTypeEnv.constants ``Acc = some accType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr accTypeEnv accIntroInfo.levelParams [] + accIntroInfo.type accType.ctors[0].type := by tr_type_expr_tac + obtain ⟨u, htype⟩ := accIntro_wf + exact hshape.to_trExprS accTypeEnv_ordered trivial ⟨.sort u, htype⟩ + +theorem accRecInfo_tr : + TrConstVal .safe accCtorEnv accRecInfo (inductRecVal accDecl accType) := by + have hAcc : accCtorEnv.constants ``Acc = some accType.toVConstant := rfl + have hIntro : accCtorEnv.constants ``Acc.intro = + some accType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr accCtorEnv accRecInfo.levelParams [] + accRecInfo.type (inductRecVal accDecl accType).type := by tr_type_expr_tac + obtain ⟨u, hrec⟩ := accStage3.recConstRec_wf + exact hshape.to_trExprS accCtorEnv_ordered trivial ⟨.sort u, hrec⟩ + +def accTypeMap : ConstMap := ({} : ConstMap).insert ``Acc accInfo +def accCtorMap : ConstMap := accTypeMap.insert ``Acc.intro accIntroInfo +def accMap : ConstMap := accCtorMap.insert ``Acc.rec accRecInfo +def accFinalEnv : VEnv := + (VInductDecl.rulesRec 1 ``Acc 2 accType).foldl VEnv.addDefEq accRecEnv + +theorem accType_fresh : ({} : ConstMap).find? ``Acc = none := by + simp [SMap.find?] + +theorem accTypeMap_wf : accTypeMap.WF := + SMap.WF.empty.insert _ _ accType_fresh + +theorem accIntro_fresh : accTypeMap.find? ``Acc.intro = none := by + rw [accTypeMap, SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem accCtorMap_wf : accCtorMap.WF := + accTypeMap_wf.insert _ _ accIntro_fresh + +theorem accRec_fresh : accCtorMap.find? ``Acc.rec = none := by + rw [accCtorMap, accTypeMap_wf.find?_insert, accTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem acc_addInduct : + AddInduct ({} : ConstMap) VEnv.empty accDecl accMap accFinalEnv := by + refine ⟨{ + generation := accChecked.identityGeneration + generation_wf := + (accChecked.wf_of_decl accDecl_wf).identityGeneration .empty + typeMap := accTypeMap + typeEnv := accTypeEnv + ctorMap := accCtorMap + ctorEnv := accCtorEnv + recEnv := accRecEnv + addType := { + info := accInfo + kind_eq := by simp [accInfo, InductConstantKind.Matches] + tr := accInfo_tr + map_fresh := by + change ({} : ConstMap).find? ``Acc = none + exact accType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := accRecInfo + kind_eq := by simp [accRecInfo, InductConstantKind.Matches] + tr := accRecInfo_tr + map_fresh := by + change accCtorMap.find? ``Acc.rec = none + exact accRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := accIntroInfo + kind_eq := by simp [accIntroInfo, InductConstantKind.Matches] + tr := accIntroInfo_tr + map_fresh := by simpa [accType] using accIntro_fresh + env_add := rfl + map_add := rfl } .nil + +/-- Replay the actual kernel `Acc` metadata through the live inductive +environment branch. -/ +theorem acc_trEnv' : TrEnv' .safe accMap false accFinalEnv := + .induct acc_addInduct .empty + +theorem acc_final_matches_addInduct : + VEnv.empty.addInduct accDecl = some accFinalEnv := + rfl + +theorem acc_env_wf : accFinalEnv.WF := acc_trEnv'.wf + +theorem acc_aligned : Aligned .safe accMap accFinalEnv := acc_trEnv'.aligned + +theorem acc_type_map_lookup : accMap.find? ``Acc = some accInfo := by + rw [accMap, accCtorMap_wf.find?_insert, accCtorMap, + accTypeMap_wf.find?_insert, accTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +theorem acc_type_env_lookup : + accFinalEnv.constants ``Acc = some accType.toVConstant := rfl + +theorem acc_type_lookup_unique : + accInfo.name = ``Acc ∧ + TrConstant .safe accFinalEnv accInfo accType.toVConstant := + acc_aligned.find?_uniq acc_type_map_lookup acc_type_env_lookup + +theorem acc_intro_map_lookup : + accMap.find? ``Acc.intro = some accIntroInfo := by + rw [accMap, accCtorMap_wf.find?_insert, accCtorMap, + accTypeMap_wf.find?_insert] + rfl + +theorem acc_intro_env_lookup : + accFinalEnv.constants ``Acc.intro = + some accType.ctors[0].toVConstant := rfl + +theorem acc_intro_lookup_unique : + accIntroInfo.name = ``Acc.intro ∧ + TrConstant .safe accFinalEnv accIntroInfo + accType.ctors[0].toVConstant := + acc_aligned.find?_uniq acc_intro_map_lookup acc_intro_env_lookup + +theorem acc_rec_map_lookup : accMap.find? ``Acc.rec = some accRecInfo := by + rw [accMap, accCtorMap_wf.find?_insert] + rfl + +theorem acc_rec_env_lookup : + accFinalEnv.constants ``Acc.rec = + some (VInductDecl.recConstRec 1 ``Acc 2 accType) := rfl + +theorem acc_rec_lookup_unique : + accRecInfo.name = ``Acc.rec ∧ + TrConstant .safe accFinalEnv accRecInfo + (VInductDecl.recConstRec 1 ``Acc 2 accType) := + acc_aligned.find?_uniq acc_rec_map_lookup acc_rec_env_lookup + +/- This has the same `sorryAx`-free closure as the direct replay roots; the +persistent-map contracts enter through concrete `SMap` freshness proofs. -/ +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.acc_trEnv' [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +/-! ## AliasFormer: non-identity family-result normalization -/ + +/-- The actual reducible alias declaration that precedes `AliasFormer` in the +kernel environment. -/ +def typeFamilyAliasKernelDef : DefinitionVal := + kernelDefVal% TypeFamilyAlias + +def typeFamilyAliasInfo : ConstantInfo := + .defnInfo typeFamilyAliasKernelDef + +def typeFamilyAliasVal : VDefVal where + name := ``TypeFamilyAlias + uvars := (vconst(type_of% @TypeFamilyAlias) : VConstant).uvars + type := (vconst(type_of% @TypeFamilyAlias) : VConstant).type + value := typeFamilyAliasDefEq.rhs + +theorem typeFamilyAliasInfo_tr : + TrDefVal .safe VEnv.empty typeFamilyAliasInfo typeFamilyAliasVal := by + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · exact .sort rfl + · exact .sort rfl + +theorem typeFamilyAliasVal_wf : + typeFamilyAliasVal.WF VEnv.empty := + VEnv.HasType.sort (by decide) + +def typeFamilyAliasMap : ConstMap := + ({} : ConstMap).insert ``TypeFamilyAlias typeFamilyAliasInfo + +theorem typeFamilyAliasMap_fresh : + ({} : ConstMap).find? ``TypeFamilyAlias = none := by + simp [SMap.find?] + +/-- Replay the actual alias definition, including its Theory delta rule. -/ +theorem typeFamilyAlias_trEnv' {safety : DefinitionSafety} : + TrEnv' safety typeFamilyAliasMap false typeFamilyAliasEnv := + .defn (ci := typeFamilyAliasKernelDef) (ci' := typeFamilyAliasVal) + (typeFamilyAliasInfo_tr.sf_mono DefinitionSafety.le_safe) + typeFamilyAliasMap_fresh + typeFamilyAliasVal_wf rfl .empty + +def aliasFormerInfo : ConstantInfo := kernelInductInfo% AliasFormer +def aliasFormerMkInfo : ConstantInfo := kernelCtorInfo% AliasFormer.mk +def aliasFormerRecInfo : ConstantInfo := kernelRecInfo% AliasFormer.rec +def aliasFormerKernelRuleRhs : VExpr := + kernelRecRuleRhs% AliasFormer.rec 0 + +example : aliasFormerRawDecl.checked? = none := rfl +example : aliasFormerGenerationChecked.block.sourceType = + aliasFormerRawType := rfl +example : aliasFormerGenerationChecked.block.checked.type = + aliasFormerViewType := rfl +example : aliasFormerKernelRuleRhs = + aliasFormerGenerationChecked.generatedRules[0].rhs := rfl + +def aliasFormerTypeEnv := + (typeFamilyAliasEnv.addConst aliasFormerRawType.name + aliasFormerRawType.toVConstant).get! + +def aliasFormerCtorEnv := + (aliasFormerTypeEnv.addConst aliasFormerRawType.ctors[0].name + aliasFormerRawType.ctors[0].toVConstant).get! + +def aliasFormerRecEnv := + (aliasFormerCtorEnv.addConst ``AliasFormer.rec + aliasFormerGenerationChecked.recursor).get! + +theorem aliasFormerTypeEnv_ordered : aliasFormerTypeEnv.Ordered := by + refine .const (n := aliasFormerRawType.name) + (ci := aliasFormerRawType.toVConstant) + typeFamilyAliasEnv_ordered ?_ rfl + show typeFamilyAliasEnv.IsType + aliasFormerGenerationChecked.block.sourceType.uvars [] + aliasFormerGenerationChecked.block.sourceType.type + rw [aliasFormerGenerationChecked.block.sourceType_uvars_eq] + exact aliasFormerGenerationChecked_wf.rawFamily_isType + +theorem aliasFormerRawCtor_wf : + aliasFormerRawType.ctors[0].toVConstant.WF aliasFormerTypeEnv := by + have hctor : + (⟨aliasFormerRawType.ctors[0], + aliasFormerViewChecked.constructors[0]⟩ : + VInductDecl.NormalizedCtor) ∈ + aliasFormerGenerationChecked.block.ctorPairs := by + exact .head _ + show aliasFormerTypeEnv.IsType + aliasFormerRawType.ctors[0].uvars [] + aliasFormerRawType.ctors[0].type + rw [aliasFormerGenerationChecked.ctor_uvars_eq hctor] + exact aliasFormerGenerationChecked_wf.rawCtor_isType rfl hctor + +theorem aliasFormerCtorEnv_ordered : aliasFormerCtorEnv.Ordered := + .const (n := aliasFormerRawType.ctors[0].name) + (ci := aliasFormerRawType.ctors[0].toVConstant) + aliasFormerTypeEnv_ordered aliasFormerRawCtor_wf rfl + +theorem aliasFormerGenerationEnv : + VInductDecl.GenerationEnv aliasFormerGenerationChecked + aliasFormerCtorEnv := by + apply aliasFormerGenerationChecked_wf.toGenerationEnv + (envT := aliasFormerTypeEnv) + · rfl + · exact (VEnv.addConst_le (show + typeFamilyAliasEnv.addConst aliasFormerRawType.name + aliasFormerRawType.toVConstant = some aliasFormerTypeEnv from rfl)).trans + (VEnv.addConst_le (show + aliasFormerTypeEnv.addConst aliasFormerRawType.ctors[0].name + aliasFormerRawType.ctors[0].toVConstant = + some aliasFormerCtorEnv from rfl)) + · exact VEnv.addConst_le (show + aliasFormerTypeEnv.addConst aliasFormerRawType.ctors[0].name + aliasFormerRawType.ctors[0].toVConstant = + some aliasFormerCtorEnv from rfl) + · exact aliasFormerCtorEnv_ordered + · rfl + · intro ctor hctor + change ctor ∈ + [⟨aliasFormerRawType.ctors[0], + aliasFormerViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + rfl + +theorem aliasFormerInfo_tr : + TrConstVal .safe typeFamilyAliasEnv aliasFormerInfo + aliasFormerRawType.toVConstVal := by + have hAlias : typeFamilyAliasEnv.constants ``TypeFamilyAlias = + some (vconst(type_of% @TypeFamilyAlias)) := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr typeFamilyAliasEnv + aliasFormerInfo.levelParams [] aliasFormerInfo.type + aliasFormerRawType.type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := + aliasFormerGenerationChecked_wf.rawFamily_isType + exact hshape.to_trExprS typeFamilyAliasEnv_ordered trivial + ⟨.sort u, htype⟩ + +theorem aliasFormerMkInfo_tr : + TrConstVal .safe aliasFormerTypeEnv aliasFormerMkInfo + aliasFormerRawType.ctors[0] := by + have hFamily : aliasFormerTypeEnv.constants ``AliasFormer = + some aliasFormerRawType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr aliasFormerTypeEnv + aliasFormerMkInfo.levelParams [] aliasFormerMkInfo.type + aliasFormerRawType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := aliasFormerRawCtor_wf + exact hshape.to_trExprS aliasFormerTypeEnv_ordered trivial + ⟨.sort u, htype⟩ + +theorem aliasFormerRecInfo_tr : + TrConstVal .safe aliasFormerCtorEnv aliasFormerRecInfo + (inductGenerationRecVal aliasFormerGenerationChecked) := by + have hFamily : aliasFormerCtorEnv.constants ``AliasFormer = + some aliasFormerRawType.toVConstant := rfl + have hMk : aliasFormerCtorEnv.constants ``AliasFormer.mk = + some aliasFormerRawType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr aliasFormerCtorEnv + aliasFormerRecInfo.levelParams [] aliasFormerRecInfo.type + (inductGenerationRecVal aliasFormerGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨u, hrec⟩ := aliasFormerGenerationEnv.recursor_wf + exact hshape.to_trExprS aliasFormerCtorEnv_ordered trivial + ⟨.sort u, hrec⟩ + +def aliasFormerTypeMap : ConstMap := + typeFamilyAliasMap.insert ``AliasFormer aliasFormerInfo + +def aliasFormerCtorMap : ConstMap := + aliasFormerTypeMap.insert ``AliasFormer.mk aliasFormerMkInfo + +def aliasFormerMap : ConstMap := + aliasFormerCtorMap.insert ``AliasFormer.rec aliasFormerRecInfo + +theorem typeFamilyAliasMap_wf : typeFamilyAliasMap.WF := + (typeFamilyAlias_trEnv' (safety := .safe)).map_wf + +theorem aliasFormerType_fresh : + typeFamilyAliasMap.find? ``AliasFormer = none := by + rw [typeFamilyAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem aliasFormerTypeMap_wf : aliasFormerTypeMap.WF := + typeFamilyAliasMap_wf.insert _ _ aliasFormerType_fresh + +theorem aliasFormerMk_fresh : + aliasFormerTypeMap.find? ``AliasFormer.mk = none := by + rw [aliasFormerTypeMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem aliasFormerCtorMap_wf : aliasFormerCtorMap.WF := + aliasFormerTypeMap_wf.insert _ _ aliasFormerMk_fresh + +theorem aliasFormerRec_fresh : + aliasFormerCtorMap.find? ``AliasFormer.rec = none := by + rw [aliasFormerCtorMap, aliasFormerTypeMap_wf.find?_insert, + aliasFormerTypeMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +private def aliasFormerAddInductTraceWith + (generation_wf : + aliasFormerGenerationChecked.WF typeFamilyAliasEnv) : + AddInductTrace typeFamilyAliasMap typeFamilyAliasEnv + aliasFormerRawDecl aliasFormerMap aliasFormerFinalEnv := by + refine { + generation := aliasFormerGenerationChecked + generation_wf := generation_wf + typeMap := aliasFormerTypeMap + typeEnv := aliasFormerTypeEnv + ctorMap := aliasFormerCtorMap + ctorEnv := aliasFormerCtorEnv + recEnv := aliasFormerRecEnv + addType := { + info := aliasFormerInfo + kind_eq := by simp [aliasFormerInfo, InductConstantKind.Matches] + tr := aliasFormerInfo_tr + map_fresh := by + change typeFamilyAliasMap.find? ``AliasFormer = none + exact aliasFormerType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := aliasFormerRecInfo + kind_eq := by simp [aliasFormerRecInfo, InductConstantKind.Matches] + tr := aliasFormerRecInfo_tr + map_fresh := by + change aliasFormerCtorMap.find? ``AliasFormer.rec = none + exact aliasFormerRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ } + exact .cons { + info := aliasFormerMkInfo + kind_eq := by simp [aliasFormerMkInfo, InductConstantKind.Matches] + tr := aliasFormerMkInfo_tr + map_fresh := by + simpa [aliasFormerRawType] using aliasFormerMk_fresh + env_add := rfl + map_add := rfl } .nil + +theorem aliasFormer_addInduct : + AddInduct typeFamilyAliasMap typeFamilyAliasEnv + aliasFormerRawDecl aliasFormerMap aliasFormerFinalEnv := + ⟨aliasFormerAddInductTraceWith aliasFormerGenerationChecked_wf⟩ + +theorem aliasFormer_trEnv' : + TrEnv' .safe aliasFormerMap false aliasFormerFinalEnv := + .induct aliasFormer_addInduct typeFamilyAlias_trEnv' + +theorem aliasFormer_final_matches_generation : + typeFamilyAliasEnv.addInductGeneration + aliasFormerGenerationChecked = some aliasFormerFinalEnv := + aliasFormer_addInductGeneration + +theorem aliasFormer_env_wf : aliasFormerFinalEnv.WF := + aliasFormer_trEnv'.wf + +theorem aliasFormer_aligned : + Aligned .safe aliasFormerMap aliasFormerFinalEnv := + aliasFormer_trEnv'.aligned + +theorem aliasFormer_type_map_lookup : + aliasFormerMap.find? ``AliasFormer = some aliasFormerInfo := by + rw [aliasFormerMap, aliasFormerCtorMap_wf.find?_insert, + aliasFormerCtorMap, aliasFormerTypeMap_wf.find?_insert, + aliasFormerTypeMap, typeFamilyAliasMap_wf.find?_insert] + rfl + +theorem aliasFormer_type_lookup_unique : + aliasFormerInfo.name = ``AliasFormer ∧ + TrConstant .safe aliasFormerFinalEnv aliasFormerInfo + aliasFormerRawType.toVConstant := + aliasFormer_aligned.find?_uniq aliasFormer_type_map_lookup + aliasFormerFinalEnv_family_lookup + +theorem aliasFormer_mk_map_lookup : + aliasFormerMap.find? ``AliasFormer.mk = some aliasFormerMkInfo := by + rw [aliasFormerMap, aliasFormerCtorMap_wf.find?_insert, + aliasFormerCtorMap, aliasFormerTypeMap_wf.find?_insert] + rfl + +theorem aliasFormer_mk_lookup_unique : + aliasFormerMkInfo.name = ``AliasFormer.mk ∧ + TrConstant .safe aliasFormerFinalEnv aliasFormerMkInfo + aliasFormerRawType.ctors[0].toVConstant := + aliasFormer_aligned.find?_uniq aliasFormer_mk_map_lookup + (aliasFormerFinalEnv_ctor_lookup _ (.head _)) + +theorem aliasFormer_rec_map_lookup : + aliasFormerMap.find? ``AliasFormer.rec = some aliasFormerRecInfo := by + rw [aliasFormerMap, aliasFormerCtorMap_wf.find?_insert] + rfl + +theorem aliasFormer_rec_lookup_unique : + aliasFormerRecInfo.name = ``AliasFormer.rec ∧ + TrConstant .safe aliasFormerFinalEnv aliasFormerRecInfo + aliasFormerGenerationChecked.recursor := + aliasFormer_aligned.find?_uniq aliasFormer_rec_map_lookup + aliasFormerFinalEnv_rec_lookup + +/-! ## AliasRec: non-identity recursive-field normalization -/ + +def recAliasKernelDef : DefinitionVal := kernelDefVal% RecAlias + +def recAliasInfo : ConstantInfo := .defnInfo recAliasKernelDef + +def recAliasVal : VDefVal where + name := ``RecAlias + uvars := (vconst(type_of% @RecAlias) : VConstant).uvars + type := (vconst(type_of% @RecAlias) : VConstant).type + value := recAliasDefEq.rhs + +theorem recAliasInfo_tr : + TrDefVal .safe VEnv.empty recAliasInfo recAliasVal := by + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · have hshape : TrTypeExpr VEnv.empty recAliasInfo.levelParams [] + recAliasInfo.type recAliasVal.type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := recAliasConstant_wf + exact hshape.to_trExprS .empty trivial ⟨.sort u, htype⟩ + · refine .lam ?_ (.sort rfl) (.bvar rfl) + exact ⟨_, VEnv.HasType.sort (by decide)⟩ + +theorem recAliasVal_wf : recAliasVal.WF VEnv.empty := by + exact VEnv.HasType.lam + (VEnv.HasType.sort (by decide)) + (VEnv.HasType.bvar .zero) + +def recAliasMap : ConstMap := + ({} : ConstMap).insert ``RecAlias recAliasInfo + +theorem recAliasMap_fresh : + ({} : ConstMap).find? ``RecAlias = none := by + simp [SMap.find?] + +theorem recAlias_trEnv' {safety : DefinitionSafety} : + TrEnv' safety recAliasMap false recAliasEnv := + .defn (ci := recAliasKernelDef) (ci' := recAliasVal) + (recAliasInfo_tr.sf_mono DefinitionSafety.le_safe) + recAliasMap_fresh recAliasVal_wf rfl .empty + +def aliasRecInfo : ConstantInfo := kernelInductInfo% AliasRec +def aliasRecMkInfo : ConstantInfo := kernelCtorInfo% AliasRec.mk +def aliasRecRecInfo : ConstantInfo := kernelRecInfo% AliasRec.rec +def aliasRecKernelRuleRhs : VExpr := + kernelRecRuleRhs% AliasRec.rec 0 + +example : aliasRecRawDecl.checked? = none := rfl +example : aliasRecGenerationChecked.block.sourceType = aliasRecRawType := rfl +example : aliasRecGenerationChecked.block.checked.type = aliasRecViewType := rfl +example : aliasRecGenerationChecked.block.ctorPairs[0].rawFields 0 = + [aliasRecRawField] := rfl +example : (VInductDecl.ctorFields + aliasRecGenerationChecked.minorTypes[0])[0]? = + some aliasRecRawField := rfl +example : aliasRecKernelRuleRhs = + aliasRecGenerationChecked.generatedRules[0].rhs := rfl + +def aliasRecTypeEnv := + (recAliasEnv.addConst aliasRecRawType.name + aliasRecRawType.toVConstant).get! + +def aliasRecCtorEnv := + (aliasRecTypeEnv.addConst aliasRecRawType.ctors[0].name + aliasRecRawType.ctors[0].toVConstant).get! + +def aliasRecRecEnv := + (aliasRecCtorEnv.addConst ``AliasRec.rec + aliasRecGenerationChecked.recursor).get! + +theorem aliasRecTypeEnv_ordered : aliasRecTypeEnv.Ordered := by + refine .const (n := aliasRecRawType.name) + (ci := aliasRecRawType.toVConstant) + recAliasEnv_ordered ?_ rfl + show recAliasEnv.IsType + aliasRecGenerationChecked.block.sourceType.uvars [] + aliasRecGenerationChecked.block.sourceType.type + rw [aliasRecGenerationChecked.block.sourceType_uvars_eq] + exact aliasRecGenerationChecked_wf.rawFamily_isType + +theorem aliasRecRawCtor_wf : + aliasRecRawType.ctors[0].toVConstant.WF aliasRecTypeEnv := by + have hctor : + (⟨aliasRecRawType.ctors[0], + aliasRecViewChecked.constructors[0]⟩ : + VInductDecl.NormalizedCtor) ∈ + aliasRecGenerationChecked.block.ctorPairs := by + exact .head _ + show aliasRecTypeEnv.IsType aliasRecRawType.ctors[0].uvars [] + aliasRecRawType.ctors[0].type + rw [aliasRecGenerationChecked.ctor_uvars_eq hctor] + exact aliasRecGenerationChecked_wf.rawCtor_isType rfl hctor + +theorem aliasRecCtorEnv_ordered : aliasRecCtorEnv.Ordered := + .const (n := aliasRecRawType.ctors[0].name) + (ci := aliasRecRawType.ctors[0].toVConstant) + aliasRecTypeEnv_ordered aliasRecRawCtor_wf rfl + +theorem aliasRecGenerationEnv : + VInductDecl.GenerationEnv aliasRecGenerationChecked aliasRecCtorEnv := by + apply aliasRecGenerationChecked_wf.toGenerationEnv + (envT := aliasRecTypeEnv) + · rfl + · exact (VEnv.addConst_le (show + recAliasEnv.addConst aliasRecRawType.name + aliasRecRawType.toVConstant = some aliasRecTypeEnv from rfl)).trans + (VEnv.addConst_le (show + aliasRecTypeEnv.addConst aliasRecRawType.ctors[0].name + aliasRecRawType.ctors[0].toVConstant = + some aliasRecCtorEnv from rfl)) + · exact VEnv.addConst_le (show + aliasRecTypeEnv.addConst aliasRecRawType.ctors[0].name + aliasRecRawType.ctors[0].toVConstant = + some aliasRecCtorEnv from rfl) + · exact aliasRecCtorEnv_ordered + · rfl + · intro ctor hctor + change ctor ∈ + [⟨aliasRecRawType.ctors[0], + aliasRecViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + rfl + +theorem aliasRecInfo_tr : + TrConstVal .safe recAliasEnv aliasRecInfo + aliasRecRawType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr recAliasEnv aliasRecInfo.levelParams [] + aliasRecInfo.type aliasRecRawType.type := by + tr_type_expr_tac + exact hshape.to_trExprS recAliasEnv_ordered trivial + ⟨.sort (.succ (.succ .zero)), VEnv.HasType.sort (by decide)⟩ + +theorem aliasRecMkInfo_tr : + TrConstVal .safe aliasRecTypeEnv aliasRecMkInfo + aliasRecRawType.ctors[0] := by + have hAlias : aliasRecTypeEnv.constants ``RecAlias = + some (vconst(type_of% @RecAlias)) := rfl + have hFamily : aliasRecTypeEnv.constants ``AliasRec = + some aliasRecRawType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr aliasRecTypeEnv + aliasRecMkInfo.levelParams [] aliasRecMkInfo.type + aliasRecRawType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := aliasRecRawCtor_wf + exact hshape.to_trExprS aliasRecTypeEnv_ordered trivial + ⟨.sort u, htype⟩ + +theorem aliasRecRecInfo_tr : + TrConstVal .safe aliasRecCtorEnv aliasRecRecInfo + (inductGenerationRecVal aliasRecGenerationChecked) := by + have hAlias : aliasRecCtorEnv.constants ``RecAlias = + some (vconst(type_of% @RecAlias)) := rfl + have hFamily : aliasRecCtorEnv.constants ``AliasRec = + some aliasRecRawType.toVConstant := rfl + have hMk : aliasRecCtorEnv.constants ``AliasRec.mk = + some aliasRecRawType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr aliasRecCtorEnv + aliasRecRecInfo.levelParams [] aliasRecRecInfo.type + (inductGenerationRecVal aliasRecGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨u, hrec⟩ := aliasRecGenerationEnv.recursor_wf + exact hshape.to_trExprS aliasRecCtorEnv_ordered trivial + ⟨.sort u, hrec⟩ + +def aliasRecTypeMap : ConstMap := + recAliasMap.insert ``AliasRec aliasRecInfo + +def aliasRecCtorMap : ConstMap := + aliasRecTypeMap.insert ``AliasRec.mk aliasRecMkInfo + +def aliasRecMap : ConstMap := + aliasRecCtorMap.insert ``AliasRec.rec aliasRecRecInfo + +theorem recAliasMap_wf : recAliasMap.WF := (recAlias_trEnv' (safety := .safe)).map_wf + +theorem aliasRecType_fresh : + recAliasMap.find? ``AliasRec = none := by + rw [recAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem aliasRecTypeMap_wf : aliasRecTypeMap.WF := + recAliasMap_wf.insert _ _ aliasRecType_fresh + +theorem aliasRecMk_fresh : + aliasRecTypeMap.find? ``AliasRec.mk = none := by + rw [aliasRecTypeMap, recAliasMap_wf.find?_insert, recAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem aliasRecCtorMap_wf : aliasRecCtorMap.WF := + aliasRecTypeMap_wf.insert _ _ aliasRecMk_fresh + +theorem aliasRecRec_fresh : + aliasRecCtorMap.find? ``AliasRec.rec = none := by + rw [aliasRecCtorMap, aliasRecTypeMap_wf.find?_insert, + aliasRecTypeMap, recAliasMap_wf.find?_insert, recAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +private def aliasRecAddInductTraceWith + (generation_wf : aliasRecGenerationChecked.WF recAliasEnv) : + AddInductTrace recAliasMap recAliasEnv aliasRecRawDecl + aliasRecMap aliasRecFinalEnv := by + refine { + generation := aliasRecGenerationChecked + generation_wf := generation_wf + typeMap := aliasRecTypeMap + typeEnv := aliasRecTypeEnv + ctorMap := aliasRecCtorMap + ctorEnv := aliasRecCtorEnv + recEnv := aliasRecRecEnv + addType := { + info := aliasRecInfo + kind_eq := by simp [aliasRecInfo, InductConstantKind.Matches] + tr := aliasRecInfo_tr + map_fresh := by + change recAliasMap.find? ``AliasRec = none + exact aliasRecType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := aliasRecRecInfo + kind_eq := by simp [aliasRecRecInfo, InductConstantKind.Matches] + tr := aliasRecRecInfo_tr + map_fresh := by + change aliasRecCtorMap.find? ``AliasRec.rec = none + exact aliasRecRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ } + exact .cons { + info := aliasRecMkInfo + kind_eq := by simp [aliasRecMkInfo, InductConstantKind.Matches] + tr := aliasRecMkInfo_tr + map_fresh := by simpa [aliasRecRawType] using aliasRecMk_fresh + env_add := rfl + map_add := rfl } .nil + +theorem aliasRec_addInduct : + AddInduct recAliasMap recAliasEnv aliasRecRawDecl + aliasRecMap aliasRecFinalEnv := + ⟨aliasRecAddInductTraceWith aliasRecGenerationChecked_wf⟩ + +theorem aliasRec_trEnv' : + TrEnv' .safe aliasRecMap false aliasRecFinalEnv := + .induct aliasRec_addInduct recAlias_trEnv' + +theorem aliasRec_final_matches_generation : + recAliasEnv.addInductGeneration aliasRecGenerationChecked = + some aliasRecFinalEnv := + aliasRec_addInductGeneration + +theorem aliasRec_env_wf : aliasRecFinalEnv.WF := + aliasRec_trEnv'.wf + +theorem aliasRec_aligned : + Aligned .safe aliasRecMap aliasRecFinalEnv := + aliasRec_trEnv'.aligned + +theorem aliasRec_type_map_lookup : + aliasRecMap.find? ``AliasRec = some aliasRecInfo := by + rw [aliasRecMap, aliasRecCtorMap_wf.find?_insert, + aliasRecCtorMap, aliasRecTypeMap_wf.find?_insert, + aliasRecTypeMap, recAliasMap_wf.find?_insert] + rfl + +theorem aliasRec_type_lookup_unique : + aliasRecInfo.name = ``AliasRec ∧ + TrConstant .safe aliasRecFinalEnv aliasRecInfo + aliasRecRawType.toVConstant := + aliasRec_aligned.find?_uniq aliasRec_type_map_lookup + aliasRecFinalEnv_family_lookup + +theorem aliasRec_mk_map_lookup : + aliasRecMap.find? ``AliasRec.mk = some aliasRecMkInfo := by + rw [aliasRecMap, aliasRecCtorMap_wf.find?_insert, + aliasRecCtorMap, aliasRecTypeMap_wf.find?_insert] + rfl + +theorem aliasRec_mk_lookup_unique : + aliasRecMkInfo.name = ``AliasRec.mk ∧ + TrConstant .safe aliasRecFinalEnv aliasRecMkInfo + aliasRecRawType.ctors[0].toVConstant := + aliasRec_aligned.find?_uniq aliasRec_mk_map_lookup + (aliasRecFinalEnv_ctor_lookup _ (.head _)) + +theorem aliasRec_rec_map_lookup : + aliasRecMap.find? ``AliasRec.rec = some aliasRecRecInfo := by + rw [aliasRecMap, aliasRecCtorMap_wf.find?_insert] + rfl + +theorem aliasRec_rec_lookup_unique : + aliasRecRecInfo.name = ``AliasRec.rec ∧ + TrConstant .safe aliasRecFinalEnv aliasRecRecInfo + aliasRecGenerationChecked.recursor := + aliasRec_aligned.find?_uniq aliasRec_rec_map_lookup + aliasRecFinalEnv_rec_lookup + +/-! ## Binder annotation candidate fixtures -/ + +/- These four definitions are quoted from the running kernel rather than +reconstructed. The resulting minimal environment is sufficient for the +ordinary checker to delta-reduce every annotation gadget while leaving the +shared `Nat` endpoint opaque. -/ +private def annotationOutParamInfo : ConstantInfo := + .defnInfo (kernelDefVal% outParam) + +private def annotationSemiOutParamInfo : ConstantInfo := + .defnInfo (kernelDefVal% semiOutParam) + +private def annotationOptParamInfo : ConstantInfo := + .defnInfo (kernelDefVal% optParam) + +private def annotationAutoParamInfo : ConstantInfo := + .defnInfo (kernelDefVal% autoParam) + +private def annotationKernelMap : ConstMap := + ((({} : ConstMap).insert ``outParam annotationOutParamInfo).insert + ``semiOutParam annotationSemiOutParamInfo).insert + ``optParam annotationOptParamInfo |>.insert + ``autoParam annotationAutoParamInfo + +private def annotationKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_annotationCandidate annotationKernelMap + +private def annotationCandidateContext : AddInductive.Context where + env := annotationKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + +private def annotationNatExpr : Expr := .const ``Nat [] + +private def outParamDomain : Expr := + .app (.const ``outParam [.succ .zero]) annotationNatExpr + +private def semiOutParamDomain : Expr := + .app (.const ``semiOutParam [.succ .zero]) annotationNatExpr + +private def optParamDomain : Expr := + .app (.app (.const ``optParam [.succ .zero]) annotationNatExpr) + (.lit (.natVal 0)) + +private def autoParamDomain : Expr := + .app (.app (.const ``autoParam [.succ .zero]) annotationNatExpr) + (.const ``Lean.Syntax.missing []) + +/- Each constructor is inhabited at its precise source and consumed indices; +the guards below additionally ensure the executable structural mirror chooses +that constructor. -/ +private def outParamTrace : + AddInductive.CandidateTypeAnnotationTrace + outParamDomain annotationNatExpr := + .outParam [.succ .zero] annotationNatExpr (.identity _) + +private def semiOutParamTrace : + AddInductive.CandidateTypeAnnotationTrace + semiOutParamDomain annotationNatExpr := + .semiOutParam [.succ .zero] annotationNatExpr (.identity _) + +private def optParamTrace : + AddInductive.CandidateTypeAnnotationTrace + optParamDomain annotationNatExpr := + .optParam [.succ .zero] annotationNatExpr + (.lit (.natVal 0)) (.identity _) + +private def autoParamTrace : + AddInductive.CandidateTypeAnnotationTrace + autoParamDomain annotationNatExpr := + .autoParam [.succ .zero] annotationNatExpr + (.const ``Lean.Syntax.missing []) (.identity _) + +private def annotationTraceTag : + AddInductive.CandidateTypeAnnotationTrace source consumed → Nat + | .identity _ => 0 + | .outParam .. => 1 + | .semiOutParam .. => 2 + | .optParam .. => 3 + | .autoParam .. => 4 + +#guard let ⟨consumed, trace⟩ := + AddInductive.CandidateTypeAnnotationTrace.build outParamDomain + consumed.equal annotationNatExpr && annotationTraceTag trace == 1 + +#guard let ⟨consumed, trace⟩ := + AddInductive.CandidateTypeAnnotationTrace.build semiOutParamDomain + consumed.equal annotationNatExpr && annotationTraceTag trace == 2 + +#guard let ⟨consumed, trace⟩ := + AddInductive.CandidateTypeAnnotationTrace.build optParamDomain + consumed.equal annotationNatExpr && annotationTraceTag trace == 3 + +#guard let ⟨consumed, trace⟩ := + AddInductive.CandidateTypeAnnotationTrace.build autoParamDomain + consumed.equal annotationNatExpr && annotationTraceTag trace == 4 + +private def annotationCandidateAccepted (domain expected : Expr) : Bool := + match AddInductive.buildCandidateTypeAnnotations domain with + | .error _ => false + | .ok annotations => + annotations.consumed.equal expected && + match AddInductive.observeCandidateIsDefEq annotationCandidateContext + domain annotations.consumed with + | .ok _ => true + | .error _ => false + +/- These guards cover the complete binder-annotation seam used by the +candidate producer: the transparent structural implementation remains +differentially equal to Lean's opaque helper, followed by an exact successful +ordinary-checker equality observation. -/ +#guard AddInductive.candidateTypeAnnotationsAgree outParamDomain +#guard AddInductive.candidateTypeAnnotationsAgree semiOutParamDomain +#guard AddInductive.candidateTypeAnnotationsAgree optParamDomain +#guard AddInductive.candidateTypeAnnotationsAgree autoParamDomain +#guard annotationCandidateAccepted outParamDomain annotationNatExpr +#guard annotationCandidateAccepted semiOutParamDomain annotationNatExpr +#guard annotationCandidateAccepted optParamDomain annotationNatExpr +#guard annotationCandidateAccepted autoParamDomain annotationNatExpr + +private def annotationIsDefEq (lhs rhs : Expr) := + TypeChecker.M.run annotationCandidateContext.env + annotationCandidateContext.safety annotationCandidateContext.lctx + annotationCandidateContext.lparams annotationCandidateContext.fuel + (TypeChecker.isDefEq lhs rhs) + +/- A genuinely unequal domain is observed as `.ok false`, not a checker +failure, and the candidate boundary rejects it with the dedicated error. -/ +#guard match annotationIsDefEq (.sort .zero) (.sort (.succ .zero)) with + | .ok false => true + | _ => false + +#guard match AddInductive.observeCandidateIsDefEq annotationCandidateContext + (.sort .zero) (.sort (.succ .zero)) with + | .error (.other message) => + message == "normalization candidate changed a binder domain" + | _ => false + +/-! ## Annotated recursive-Pi candidate -/ + +/-- Exact kernel definition and Theory value used to interpret `outParam` +inside a complete recursive constructor candidate. -/ +private def outParamKernelDef : DefinitionVal := + kernelDefVal% outParam + +private def outParamVal : VDefVal where + name := ``outParam + uvars := (vconst(type_of% @outParam) : VConstant).uvars + type := (vconst(type_of% @outParam) : VConstant).type + value := outParamDefEq.rhs + +private theorem outParamInfo_tr : + TrDefVal .safe VEnv.empty annotationOutParamInfo outParamVal := by + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · exact .forallE + ⟨_, VEnv.HasType.sort (by decide)⟩ + ⟨_, VEnv.HasType.sort (by decide)⟩ + (.sort rfl) (.sort rfl) + · exact .lam + ⟨_, VEnv.HasType.sort (by decide)⟩ + (.sort rfl) (.bvar rfl) + +private theorem outParamVal_wf : outParamVal.WF VEnv.empty := by + exact VEnv.HasType.lam + (VEnv.HasType.sort (by decide)) + (VEnv.HasType.bvar .zero) + +private def outParamMap : ConstMap := + ({} : ConstMap).insert ``outParam annotationOutParamInfo + +private theorem outParamMap_fresh : + ({} : ConstMap).find? ``outParam = none := by + simp [SMap.find?] + +private theorem outParam_trEnv' {safety : DefinitionSafety} : + TrEnv' safety outParamMap false outParamEnv := + .defn (ci := outParamKernelDef) (ci' := outParamVal) + (outParamInfo_tr.sf_mono DefinitionSafety.le_safe) + outParamMap_fresh outParamVal_wf rfl .empty + +private theorem outParamMap_wf : outParamMap.WF := + (outParam_trEnv' (safety := .safe)).map_wf + +/-- Public map-well-formedness boundary for replay artifacts whose concrete +dependency map is intentionally kept private to this fixture module. -/ +theorem annotatedReplayInputMap_wf : outParamMap.WF := + outParamMap_wf + +private def outParamKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_annotatedPiCandidate outParamMap + +private theorem outParam_trEnv : + TrEnv .safe outParamKernelEnv outParamEnv := by + simpa [TrEnv, outParamKernelEnv, Kernel.Environment.ofConstants] using + outParam_trEnv' + +private theorem outParam_hasPrimitives : + VEnv.HasPrimitives outParamEnv := by + apply VEnv.HasPrimitives.of_avoids + intro n hn + simp only [VEnv.reflectedPrimitiveNames, List.mem_cons, + List.not_mem_nil, or_false] at hn + rcases hn with rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl <;> + rfl + +private theorem outParam_safePrimitives : + outParamKernelEnv.find? n = some ci → + Kernel.Environment.primitives.contains n → + ci.safety = .safe ∧ ci.levelParams = [] := by + intro hfind hprim + change outParamMap.find?' n = some ci at hfind + rw [outParamMap_wf.find?'_eq_find?, outParamMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] at hfind + simp [SMap.find?] at hfind + obtain ⟨rfl, rfl⟩ := hfind + simp [Kernel.Environment.primitives, NameSet.ofList] at hprim + simp +decide [NameSet.contains] at hprim + +private def outParamVEnvs : VEnvs where + venv _ := outParamEnv + +private theorem outParamVEnvs_wf : outParamVEnvs.WF outParamKernelEnv where + tr := by + intro safety + exact outParam_trEnv' + hasPrimitives := outParam_hasPrimitives + safePrimitives := outParam_safePrimitives + mono := fun _ => .rfl + projectionReady := ProjectionReady.of_no_ctorInfo <| by + intro name _info h + change outParamMap.find?' name = some (.ctorInfo _info) at h + rw [outParamMap_wf.find?'_eq_find?] at h + simp only [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + simp [SMap.find?, annotationOutParamInfo] at h + structureEtaReady := StructureEtaReady.of_no_ctorInfo <| by + intro name _info h + change outParamMap.find?' name = some (.ctorInfo _info) at h + rw [outParamMap_wf.find?'_eq_find?] at h + simp only [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + simp [SMap.find?, annotationOutParamInfo] at h + +/-! ## Definitionally equal constructor parameters -/ + +def annotatedParamInfo : ConstantInfo := kernelInductInfo% AnnotatedParam +def annotatedParamMkInfo : ConstantInfo := kernelCtorInfo% AnnotatedParam.mk +def annotatedParamRecInfo : ConstantInfo := kernelRecInfo% AnnotatedParam.rec +def annotatedParamKernelRuleRhs : VExpr := + kernelRecRuleRhs% AnnotatedParam.rec 0 + +example : annotatedParamKernelRuleRhs = + annotatedParamGenerationChecked.generatedRules[0].rhs := rfl + +private def annotatedParamKernelCtor : Constructor where + name := annotatedParamMkInfo.name + type := annotatedParamMkInfo.type + +private def annotatedParamKernelType : InductiveType where + name := annotatedParamInfo.name + type := annotatedParamInfo.type + ctors := [annotatedParamKernelCtor] + +private def annotatedParamCandidateContext : AddInductive.Context where + env := outParamKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + +private def annotatedParamExpectedFamilyView : Expr := + .forallE `alpha (.sort (.succ .zero)) + (.sort (.succ .zero)) .default + +private def annotatedParamExpectedCtorView : Expr := + .forallE `alpha (.sort (.succ .zero)) + (.app (.const ``AnnotatedParam []) (.bvar 0)) .implicit + +/- The successful whole metadata pass reaches `checkConstructors`, compares +the stored `outParam Type` constructor prefix with the checked `Type` family +local by ordinary definitional equality, and retains the checked surface in +both candidate views. -/ +#guard match AddInductive.buildNormalizationCandidate 1 + [annotatedParamKernelType] 0 false annotatedParamCandidateContext with + | .ok candidate => + candidate.families.singleton.familyType.type.view.equal + annotatedParamExpectedFamilyView && + match candidate.families.singleton.constructors with + | .cons constructor .nil => + constructor.type.view.equal annotatedParamExpectedCtorView + | .error _ => false + +/- Keep the constructor type closed and independently well typed while making +its declared parameter domain genuinely different. The fixed result avoids a +premature application-type failure, so rejection is specifically the same +constructor-parameter check exercised by the positive. -/ +private def annotatedParamNonDefEqCtor : Constructor where + name := annotatedParamMkInfo.name + type := .forallE `alpha (.sort .zero) + (.app (.const ``AnnotatedParam []) (.sort .zero)) .implicit + +private def annotatedParamNonDefEqType : InductiveType := + { annotatedParamKernelType with ctors := [annotatedParamNonDefEqCtor] } + +#guard match AddInductive.buildNormalizationCandidate 1 + [annotatedParamNonDefEqType] 0 false annotatedParamCandidateContext with + | .error (.other message) => + message == + "arg #1 of 'Ix.Theory.Named.InductiveFixtures.AnnotatedParam.mk' does not match inductive datatype parameters" + | _ => false + +private theorem annotatedParamRawType_wf : + annotatedParamRawType.toVConstant.WF outParamEnv := by + refine ⟨.imax (.succ (.succ .zero)) (.succ (.succ .zero)), ?_⟩ + change outParamEnv.HasType 0 [] + (.forallE + (.app (.const ``outParam [.succ (.succ .zero)]) + (.sort (.succ .zero))) + (.sort (.succ .zero))) + (.sort (.imax (.succ (.succ .zero)) (.succ (.succ .zero)))) + apply VEnv.HasType.forallE + · apply VEnv.HasType.app + (A := .sort (.succ (.succ .zero))) + (B := .sort (.succ (.succ .zero))) + · simpa [VExpr.instL, VLevel.inst] using VEnv.HasType.const + (env := outParamEnv) (U := 0) (c := ``outParam) + (ci := vconst(type_of% @outParam)) + (ls := [.succ (.succ .zero)]) rfl + (by simp; decide) rfl + · exact VEnv.HasType.sort (by decide) + · exact VEnv.HasType.sort (by decide) + +private theorem annotatedParamInfo_tr : + TrConstVal .safe outParamEnv annotatedParamInfo + annotatedParamRawType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr outParamEnv annotatedParamInfo.levelParams [] + annotatedParamInfo.type annotatedParamRawType.type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := annotatedParamRawType_wf + exact hshape.to_trExprS outParamEnv_ordered trivial ⟨.sort u, htype⟩ + +private def annotatedParamTypeEnv : VEnv := + (outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant).get! + +private def annotatedParamTypeMap : ConstMap := + outParamMap.insert ``AnnotatedParam annotatedParamInfo + +private theorem annotatedParamType_fresh : + outParamMap.find? ``AnnotatedParam = none := by + rw [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +private theorem annotatedParamTypeMap_wf : annotatedParamTypeMap.WF := + outParamMap_wf.insert _ _ annotatedParamType_fresh + +private def annotatedParamAddType : + AddInductConstant .induct outParamMap outParamEnv + annotatedParamRawType.toVConstVal annotatedParamTypeMap + annotatedParamTypeEnv where + info := annotatedParamInfo + kind_eq := by simp [annotatedParamInfo, InductConstantKind.Matches] + tr := annotatedParamInfo_tr + map_fresh := by simpa [annotatedParamRawType] using + annotatedParamType_fresh + env_add := rfl + map_add := rfl + +private def annotatedParamTypeKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_annotatedParamCandidate + annotatedParamTypeMap + +private theorem annotatedParamTypeEnv_ordered : + annotatedParamTypeEnv.Ordered := + .const (n := annotatedParamRawType.name) + (ci := annotatedParamRawType.toVConstant) + outParamEnv_ordered annotatedParamRawType_wf rfl + +private def annotatedParamCtorCandidateContext : AddInductive.Context where + env := annotatedParamTypeKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + +private theorem annotatedParamType_lookup_outParam : + annotatedParamTypeKernelEnv.find? ``outParam = + some annotationOutParamInfo := by + change annotatedParamTypeMap.find?' ``outParam = + some annotationOutParamInfo + rw [annotatedParamTypeMap_wf.find?'_eq_find?, annotatedParamTypeMap, + outParamMap_wf.find?_insert] + rw [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +private theorem annotatedParamType_lookup_family : + annotatedParamTypeKernelEnv.find? ``AnnotatedParam = + some annotatedParamInfo := by + change annotatedParamTypeMap.find?' ``AnnotatedParam = + some annotatedParamInfo + rw [annotatedParamTypeMap_wf.find?'_eq_find?, annotatedParamTypeMap, + outParamMap_wf.find?_insert] + rfl + +@[simp] private theorem annotatedParamType_get_outParam : + annotatedParamTypeKernelEnv.get ``outParam = + .ok annotationOutParamInfo := by + unfold Kernel.Environment.get + rw [annotatedParamType_lookup_outParam] + rfl + +@[simp] private theorem annotatedParamType_get_family : + annotatedParamTypeKernelEnv.get ``AnnotatedParam = + .ok annotatedParamInfo := by + unfold Kernel.Environment.get + rw [annotatedParamType_lookup_family] + rfl + +def annotatedPiInfo : ConstantInfo := kernelInductInfo% AnnotatedPi +def annotatedPiMkInfo : ConstantInfo := kernelCtorInfo% AnnotatedPi.mk +def annotatedPiRecInfo : ConstantInfo := kernelRecInfo% AnnotatedPi.rec +def annotatedPiKernelRuleRhs : VExpr := + kernelRecRuleRhs% AnnotatedPi.rec 0 + +example : annotatedPiKernelRuleRhs = + annotatedPiGenerationChecked.generatedRules[0].rhs := rfl + +private def annotatedPiKernelCtor : Constructor where + name := annotatedPiMkInfo.name + type := annotatedPiMkInfo.type + +private def annotatedPiKernelType : InductiveType where + name := annotatedPiInfo.name + type := annotatedPiInfo.type + ctors := [annotatedPiKernelCtor] + +/- The whole-candidate negative keeps the actual AnnotatedPi family and +constructor metadata, but gives the annotation symbol its correct type as an +opaque constant. Ordinary metadata typing can therefore reach the recursive +constructor candidate, while `outParam Prop` is no longer definitionally equal +to the syntactically consumed `Prop`. -/ +private def annotatedPiOpaqueOutParamInfo : ConstantInfo := + .axiomInfo { + name := ``outParam + levelParams := outParamKernelDef.levelParams + type := outParamKernelDef.type + isUnsafe := false } + +private def annotatedPiOpaqueOutParamMap : ConstMap := + ({} : ConstMap).insert ``outParam annotatedPiOpaqueOutParamInfo + +private def annotatedPiOpaqueOutParamEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_annotatedPiOpaqueAnnotation + annotatedPiOpaqueOutParamMap + +private def annotatedPiOpaqueOutParamContext : AddInductive.Context where + env := annotatedPiOpaqueOutParamEnv + lparams := [] + safety := .safe + allowPrimitive := false + +/- This is a complete family/constructor candidate rejection, not the earlier +leaf-level `isDefEq` test. The dedicated message proves failure occurs at the +raw-to-consumed binder equality boundary before any semantic package or +transaction can be assembled. -/ +#guard match AddInductive.buildNormalizationCandidate 0 + [annotatedPiKernelType] 0 false annotatedPiOpaqueOutParamContext with + | .error (.other message) => + message == "normalization candidate changed a binder domain" + | _ => false + +private theorem annotatedPiRawType_wf : + annotatedPiRawType.toVConstant.WF outParamEnv := by + exact ⟨_, VEnv.HasType.sort (by decide)⟩ + +private theorem annotatedPiInfo_tr : + TrConstVal .safe outParamEnv annotatedPiInfo + annotatedPiRawType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr outParamEnv annotatedPiInfo.levelParams [] + annotatedPiInfo.type annotatedPiRawType.type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := annotatedPiRawType_wf + exact hshape.to_trExprS outParamEnv_ordered trivial ⟨.sort u, htype⟩ + +private def annotatedPiTypeEnv : VEnv := + (outParamEnv.addConst annotatedPiRawType.name + annotatedPiRawType.toVConstant).get! + +private def annotatedPiTypeMap : ConstMap := + outParamMap.insert ``AnnotatedPi annotatedPiInfo + +private theorem annotatedPiType_fresh : + outParamMap.find? ``AnnotatedPi = none := by + rw [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +private theorem annotatedPiTypeMap_wf : annotatedPiTypeMap.WF := + outParamMap_wf.insert _ _ annotatedPiType_fresh + +private def annotatedPiAddType : + AddInductConstant .induct outParamMap outParamEnv + annotatedPiRawType.toVConstVal annotatedPiTypeMap + annotatedPiTypeEnv where + info := annotatedPiInfo + kind_eq := by simp [annotatedPiInfo, InductConstantKind.Matches] + tr := annotatedPiInfo_tr + map_fresh := by simpa [annotatedPiRawType] using annotatedPiType_fresh + env_add := rfl + map_add := rfl + +private def annotatedPiTypeKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_annotatedPiCandidate annotatedPiTypeMap + +private theorem annotatedPiTypeEnv_ordered : annotatedPiTypeEnv.Ordered := + .const (n := annotatedPiRawType.name) + (ci := annotatedPiRawType.toVConstant) + outParamEnv_ordered annotatedPiRawType_wf rfl + +private def annotatedPiFamilyCandidateContext : AddInductive.Context where + env := outParamKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + +private def annotatedPiCtorCandidateContext : AddInductive.Context where + env := annotatedPiTypeKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + +private theorem annotatedPiType_lookup_outParam : + annotatedPiTypeKernelEnv.find? ``outParam = + some annotationOutParamInfo := by + change annotatedPiTypeMap.find?' ``outParam = + some annotationOutParamInfo + rw [annotatedPiTypeMap_wf.find?'_eq_find?, annotatedPiTypeMap, + outParamMap_wf.find?_insert] + rw [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +private theorem annotatedPiType_lookup_family : + annotatedPiTypeKernelEnv.find? ``AnnotatedPi = + some annotatedPiInfo := by + change annotatedPiTypeMap.find?' ``AnnotatedPi = some annotatedPiInfo + rw [annotatedPiTypeMap_wf.find?'_eq_find?, annotatedPiTypeMap, + outParamMap_wf.find?_insert] + rfl + +@[simp] private theorem annotatedPiType_get_outParam : + annotatedPiTypeKernelEnv.get ``outParam = + .ok annotationOutParamInfo := by + unfold Kernel.Environment.get + rw [annotatedPiType_lookup_outParam] + rfl + +@[simp] private theorem annotatedPiType_get_family : + annotatedPiTypeKernelEnv.get ``AnnotatedPi = + .ok annotatedPiInfo := by + unfold Kernel.Environment.get + rw [annotatedPiType_lookup_family] + rfl + +@[simp] private theorem annotatedPi_checkLevelZero + (context : TypeChecker.Context) : + TypeChecker.Inner.checkLevel context .zero = .ok () := by + simp [TypeChecker.Inner.checkLevel, Level.getUndefParam, Level.forEach, + Level.hasParam_eq, Level.hasParam'] + rfl + +@[simp] private theorem annotatedPi_checkLevelSuccZero + (context : TypeChecker.Context) : + TypeChecker.Inner.checkLevel context (.succ .zero) = .ok () := by + simp [TypeChecker.Inner.checkLevel, Level.getUndefParam, Level.forEach, + Level.hasParam_eq, Level.hasParam'] + rfl + +open private mkLevelIMaxCore mkLevelMaxCore from Lean.Level in +@[simp] private theorem annotatedPi_mkLevelIMaxSuccZero : + mkLevelIMax' (.succ .zero) (.succ .zero) = .succ .zero := by + simp [mkLevelIMax', mkLevelIMaxCore, mkLevelMax', mkLevelMaxCore] + +private theorem annotatedPiExceptPure + {α} (a : α) : + (pure a : Except Kernel.Exception α) = .ok a := rfl + +@[simp] private theorem annotatedPiInferConstantOutParam + (lctx : LocalContext) : + TypeChecker.Inner.inferConstant + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + ``outParam [.succ .zero] false = + .ok (.forallE `α (.sort (.succ .zero)) + (.sort (.succ .zero)) .default) := by + unfold TypeChecker.Inner.inferConstant + rw [show annotatedPiTypeKernelEnv.get ``outParam = + .ok annotationOutParamInfo by exact annotatedPiType_get_outParam] + simp [annotationOutParamInfo, Bind.bind, Except.bind, + annotatedPiExceptPure, + ConstantInfo.levelParams, ConstantInfo.isUnsafe, + ConstantInfo.instantiateTypeLevelParams, + ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Level.substParams'] + +@[simp] private theorem annotatedPiInferConstantFamily + (lctx : LocalContext) : + TypeChecker.Inner.inferConstant + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + ``AnnotatedPi [] false = + .ok (.sort (.succ .zero)) := by + unfold TypeChecker.Inner.inferConstant + rw [show annotatedPiTypeKernelEnv.get ``AnnotatedPi = + .ok annotatedPiInfo by exact annotatedPiType_get_family] + rfl + +@[simp] private theorem annotatedPiInferConstantOutParamCandidate : + TypeChecker.Inner.inferConstant + annotatedPiCtorCandidateContext.toTypeChecker + ``outParam [.succ .zero] false = + .ok (.forallE `α (.sort (.succ .zero)) + (.sort (.succ .zero)) .default) := by + simp [annotatedPiCtorCandidateContext, AddInductive.Context.toTypeChecker] + +@[simp] private theorem annotatedPiEnsureForall + (name dom body bi source methods context state) : + TypeChecker.Inner.ensureForallCore (.forallE name dom body bi) source + methods context state = + .ok (.forallE name dom body bi, state) := by + unfold TypeChecker.Inner.ensureForallCore + rfl + +@[simp] private theorem annotatedPiEnsureSort + (u source methods context state) : + TypeChecker.Inner.ensureSortCore (.sort u) source methods context state = + .ok (.sort u, state) := by + unfold TypeChecker.Inner.ensureSortCore + rfl + +@[simp] private theorem annotatedPiForall_bindingDomain + (name dom body bi) : + (Expr.forallE name dom body bi).bindingDomain! = dom := rfl + +@[simp] private theorem annotatedPiForall_bindingBody + (name dom body bi) : + (Expr.forallE name dom body bi).bindingBody! = body := rfl + +@[simp] private theorem annotatedPiSort_instantiate1' + (u arg) : + (Expr.sort u).instantiate1' arg = .sort u := rfl + +@[simp] private theorem annotatedPiConst_beq_sort + (name levels u) : + ((.const name levels : Expr) == .sort u) = false := by + change Expr.eqv (.const name levels) (.sort u) = false + rw [Expr.eqv_eq] + rfl + +@[simp] private theorem annotatedPiSort_beq_const + (u name levels) : + ((.sort u : Expr) == .const name levels) = false := by + change Expr.eqv (.sort u) (.const name levels) = false + rw [Expr.eqv_eq] + rfl + +@[simp] private theorem annotatedPiApp_beq_const + (fn arg name levels) : + ((.app fn arg : Expr) == .const name levels) = false := by + change Expr.eqv (.app fn arg) (.const name levels) = false + rw [Expr.eqv_eq] + rfl + +@[simp] private theorem annotatedPiForall_beq_const + (binderName dom body bi name levels) : + ((.forallE binderName dom body bi : Expr) == .const name levels) = + false := by + change Expr.eqv (.forallE binderName dom body bi) + (.const name levels) = false + rw [Expr.eqv_eq] + rfl + +@[simp] private theorem annotatedPiOutParam_beq_family : + ((.const ``outParam [.succ .zero] : Expr) == + .const ``AnnotatedPi []) = false := by + change Expr.eqv (.const ``outParam [.succ .zero]) + (.const ``AnnotatedPi []) = false + rw [Expr.eqv_eq] + rfl + +@[simp] private theorem annotatedPiFamilyCacheAfterForall + (cache : InferCache) (name : Name) (dom body result : Expr) + (bi : BinderInfo) : + (((cache.insert (.const ``AnnotatedPi []) (.sort (.succ .zero))).insert + (.forallE name dom body bi) result)[ + (.const ``AnnotatedPi [] : Expr)]?) = + some (.sort (.succ .zero)) := by + rw [Std.HashMap.getElem?_insert, + annotatedPiForall_beq_const] + exact Std.HashMap.getElem?_insert_self + +private def annotatedPiOutParamFnType : Expr := + .forallE `α (.sort (.succ .zero)) + (.sort (.succ .zero)) .default + +@[simp] private theorem annotatedPiOutParamFnType_bindingDomain : + annotatedPiOutParamFnType.bindingDomain! = + .sort (.succ .zero) := rfl + +@[simp] private theorem annotatedPiOutParamFnType_instantiatedBody : + annotatedPiOutParamFnType.bindingBody!.instantiate1 (.sort .zero) = + .sort (.succ .zero) := by + simp [annotatedPiOutParamFnType, Expr.bindingBody!, + Expr.instantiate1_eq, Expr.instantiate1'] + +@[simp] private theorem annotatedPiSort_notEagerReduce : + (Expr.sort .zero).isAppOfArity ``eagerReduce 2 = false := rfl + +private def annotatedPiOutParamFnState : TypeChecker.State := + { ({} : TypeChecker.State) with + inferTypeC := ({} : TypeChecker.State).inferTypeC.insert + (.const ``outParam [.succ .zero]) annotatedPiOutParamFnType } + +private def annotatedPiOutParamArgState : TypeChecker.State := + { annotatedPiOutParamFnState with + inferTypeC := annotatedPiOutParamFnState.inferTypeC.insert + (.sort .zero) (.sort (.succ .zero)) } + +private def annotatedPiWithSuccessCache + (state : TypeChecker.State) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.State := + { state with success := m } + +private theorem annotatedPiIsDefEqSort + (fuel : Nat) + (context : TypeChecker.Context) + (initial : TypeChecker.State) : + TypeChecker.Inner.isDefEq + (.sort (.succ .zero)) (.sort (.succ .zero)) + (TypeChecker.Methods.withFuel fuel) context initial = + .ok (true, initial) := by + unfold TypeChecker.Inner.isDefEq + rw [if_pos (Expr.eqv_refl _)] + rfl + +private def annotatedPiCtorExpectedView : Expr := + match annotatedPiMkInfo.type with + | .forallE outerName (.forallE innerName _ innerBody innerInfo) + outerBody outerInfo => + .forallE outerName + (.forallE innerName (.sort .zero) innerBody innerInfo) + outerBody outerInfo + | source => source + +private def annotatedPiOuterName : Name := + .mkNum + (.mkStr + (.mkStr (.mkStr (.mkStr .anonymous "a") "_@") "_internal") + "_hyg") + 0 + +@[simp] private theorem annotatedPiFamilyType_noLooseBVars : + annotatedPiInfo.type.hasLooseBVars = false := by + rw [show annotatedPiInfo.type = .sort (.succ .zero) by rfl] + simp [Expr.hasLooseBVars, Expr.looseBVarRange'] + +@[simp] private theorem emptyCheckTypeCache_annotatedPiFamily : + (({} : TypeChecker.State).inferTypeC)[annotatedPiInfo.type]? = none := by + exact Std.HashMap.getElem?_empty + +@[simp] private theorem annotatedPiFamily_checkLevel : + TypeChecker.Inner.checkLevel + annotatedPiFamilyCandidateContext.toTypeChecker (.succ .zero) = + .ok () := by + simp [TypeChecker.Inner.checkLevel, Level.getUndefParam, Level.forEach, Level.hasParam_eq, + Level.hasParam'] + rfl + +@[simp] private theorem annotatedPiRecMGet (methods context state) : + (get : TypeChecker.RecM TypeChecker.State) methods context state = + .ok (state, state) := rfl + +@[simp] private theorem annotatedPiRecMReadContext + (methods context state) : + (readThe TypeChecker.Context : TypeChecker.RecM TypeChecker.Context) + methods context state = + .ok (context, state) := rfl + +@[simp] private theorem annotatedPiRecMModify + (f : TypeChecker.State → TypeChecker.State) + (methods context state) : + (modify f : TypeChecker.RecM PUnit) methods context state = + .ok (.unit, f state) := rfl + +@[simp] private theorem annotatedPiRecMPure + {α} (a : α) (methods context state) : + (pure a : TypeChecker.RecM α) methods context state = + .ok (a, state) := rfl + +@[simp] private theorem annotatedPiRecMBind + {α β} (x : TypeChecker.RecM α) + (f : α → TypeChecker.RecM β) (methods context state) : + (x >>= f) methods context state = + match x methods context state with + | .error e => .error e + | .ok (a, state') => f a methods context state' := by + simp [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + cases h : x methods context state with + | error => rfl + | ok value => cases value; rfl + +@[simp] private theorem annotatedPiRecMLiftExceptOk + {α} (a : α) (methods context state) : + (liftM (.ok a : Except Kernel.Exception α) : + TypeChecker.RecM α) methods context state = + .ok (a, state) := rfl + +@[simp] private theorem annotatedPiGetNGen + (context : TypeChecker.Context) (state : TypeChecker.State) : + (getNGen : TypeChecker.M NameGenerator) context state = + .ok (state.ngen, state) := rfl + +@[simp] private theorem annotatedPiSetNGen + (ngen : NameGenerator) (context : TypeChecker.Context) + (state : TypeChecker.State) : + (setNGen ngen : TypeChecker.M PUnit) context state = + .ok (.unit, { state with ngen }) := rfl + +@[simp] private theorem annotatedPiMPure + {α} (a : α) (context : TypeChecker.Context) + (state : TypeChecker.State) : + (pure a : TypeChecker.M α) context state = + .ok (a, state) := rfl + +@[simp] private theorem annotatedPiRecMWithReader + {α} (f : LocalContext → LocalContext) + (x : TypeChecker.RecM α) (methods : TypeChecker.Methods) + (context : TypeChecker.Context) (state : TypeChecker.State) : + (MonadWithReaderOf.withReader (m := TypeChecker.RecM) f x) + methods context state = + x methods { context with lctx := f context.lctx } state := rfl + +private theorem annotatedPiWithLocalDecl + {α} (name : Name) (bi : BinderInfo) (ty : Expr) + (k : Expr → TypeChecker.RecM α) + (methods : TypeChecker.Methods) (context : TypeChecker.Context) + (state : TypeChecker.State) : + (withLocalDecl (m := TypeChecker.RecM) name bi ty k) + methods context state = + k (.fvar ⟨state.ngen.curr⟩) methods + { context with + lctx := context.lctx.mkLocalDecl + ⟨state.ngen.curr⟩ name ty bi } + { state with ngen := state.ngen.next } := rfl + +@[simp] private theorem annotatedPiInferTypeFuel + (n e inferOnly context state) : + TypeChecker.Inner.inferType e inferOnly + (TypeChecker.Methods.withFuel (n + 1)) context state = + TypeChecker.Inner.inferType' e inferOnly + (TypeChecker.Methods.withFuel n) context state := rfl + +@[simp] private theorem annotatedPiInferTypeFamilyCore + (n : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : + state.inferTypeC[(.const ``AnnotatedPi [] : Expr)]? = none) : + TypeChecker.Inner.inferType' (.const ``AnnotatedPi []) false + (TypeChecker.Methods.withFuel n) + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + state = + .ok (.sort (.succ .zero), + { state with + inferTypeC := state.inferTypeC.insert + (.const ``AnnotatedPi []) (.sort (.succ .zero)) }) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +@[simp] private theorem annotatedPiInferTypeFamily + (n : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : + state.inferTypeC[(.const ``AnnotatedPi [] : Expr)]? = none) : + TypeChecker.Inner.inferType (.const ``AnnotatedPi []) false + (TypeChecker.Methods.withFuel (n + 1)) + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + state = + .ok (.sort (.succ .zero), + { state with + inferTypeC := state.inferTypeC.insert + (.const ``AnnotatedPi []) (.sort (.succ .zero)) }) := + annotatedPiInferTypeFamilyCore n lctx state hcache + +@[simp] private theorem annotatedPiInferTypeFamilyCached + (n : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : + state.inferTypeC[(.const ``AnnotatedPi [] : Expr)]? = + some (.sort (.succ .zero))) : + TypeChecker.Inner.inferType' (.const ``AnnotatedPi []) false + (TypeChecker.Methods.withFuel n) + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + state = + .ok (.sort (.succ .zero), state) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +@[simp] private theorem annotatedPiInferTypeFamilyAfterForall + (n : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (name : Name) (dom body result : Expr) (bi : BinderInfo) : + let state' : TypeChecker.State := + { state with + inferTypeC := + (state.inferTypeC.insert + (.const ``AnnotatedPi []) (.sort (.succ .zero))).insert + (.forallE name dom body bi) result } + TypeChecker.Inner.inferType' (.const ``AnnotatedPi []) false + (TypeChecker.Methods.withFuel n) + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + state' = + .ok (.sort (.succ .zero), state') := by + dsimp only + apply annotatedPiInferTypeFamilyCached + exact annotatedPiFamilyCacheAfterForall + state.inferTypeC name dom body result bi + +private def annotatedPiFamilyCheckTypeState : TypeChecker.State := + { ({} : TypeChecker.State) with + inferTypeC := ({} : TypeChecker.State).inferTypeC.insert + (.sort (.succ .zero)) (.sort (.succ (.succ .zero))) } + +private theorem annotatedPiFamily_checkTypeInner : + TypeChecker.Inner.inferType annotatedPiInfo.type false + (TypeChecker.Methods.withFuel 10000) + annotatedPiFamilyCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ .zero)), + annotatedPiFamilyCheckTypeState) := by + change + TypeChecker.Inner.inferType' (.sort (.succ .zero)) false + (TypeChecker.Methods.withFuel 9999) + annotatedPiFamilyCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ .zero)), + annotatedPiFamilyCheckTypeState) + unfold TypeChecker.Inner.inferType' + simp [annotatedPiFamilyCheckTypeState, Expr.hasLooseBVars, Expr.looseBVarRange', Bind.bind, + ReaderT.bind, StateT.bind, Except.bind] + +private theorem annotatedPiFamily_checkTypeM : + TypeChecker.M.run annotatedPiFamilyCandidateContext.env + annotatedPiFamilyCandidateContext.safety + annotatedPiFamilyCandidateContext.lctx + annotatedPiFamilyCandidateContext.lparams + annotatedPiFamilyCandidateContext.fuel + (TypeChecker.checkType annotatedPiInfo.type) = + .ok (.sort (.succ (.succ .zero))) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType annotatedPiInfo.type false + (TypeChecker.Methods.withFuel 10000) + annotatedPiFamilyCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ (.succ .zero))) + rw [annotatedPiFamily_checkTypeInner] + rfl + +private theorem annotatedPiFamily_whnfM : + TypeChecker.M.run annotatedPiFamilyCandidateContext.env + annotatedPiFamilyCandidateContext.safety + annotatedPiFamilyCandidateContext.lctx + annotatedPiFamilyCandidateContext.lparams + annotatedPiFamilyCandidateContext.fuel + (TypeChecker.whnf annotatedPiInfo.type) = + .ok annotatedPiInfo.type := by rfl + +private theorem annotatedPiCtor_checkTypeM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType annotatedPiMkInfo.type) = + .ok (.sort (.succ .zero)) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType annotatedPiMkInfo.type false + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + rw [show annotatedPiMkInfo.type = + .forallE annotatedPiOuterName + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default) + (.const ``AnnotatedPi []) .default by rfl] + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' + (.forallE annotatedPiOuterName + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default) + (.const ``AnnotatedPi []) .default) + false (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', TypeChecker.Inner.inferType', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rw [annotatedPiIsDefEqSort 9997] + simp [Expr.instantiate1', annotatedPiWithLocalDecl, annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [annotatedPiInferTypeFamilyCached (hcache := by + apply annotatedPiFamilyCacheAfterForall)] + simp [Expr.sortLevel!, annotatedPi_mkLevelIMaxSuccZero] + rfl + +private theorem annotatedPiCtor_whnfM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.whnf annotatedPiMkInfo.type) = + .ok annotatedPiMkInfo.type := by rfl + +/-! ## Checker-produced alias normalization certificates -/ + +/-- Minimal kernel environment used to replay family-result WHNF without +bringing unrelated constants or primitives into the certificate. -/ +private def aliasFormerNormalizationKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_aliasFormerNormalization + typeFamilyAliasMap + +private theorem aliasFormerNormalization_trEnv : + TrEnv .safe aliasFormerNormalizationKernelEnv typeFamilyAliasEnv := by + simpa [TrEnv, aliasFormerNormalizationKernelEnv, + Kernel.Environment.ofConstants] using + typeFamilyAlias_trEnv' + +private theorem aliasFormerNormalization_hasPrimitives : + VEnv.HasPrimitives typeFamilyAliasEnv := by + apply VEnv.HasPrimitives.of_avoids + intro n hn + simp only [VEnv.reflectedPrimitiveNames, List.mem_cons, + List.not_mem_nil, or_false] at hn + rcases hn with rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl <;> + rfl + +private theorem aliasFormerNormalization_safePrimitives : + aliasFormerNormalizationKernelEnv.find? n = some ci → + Kernel.Environment.primitives.contains n → + ci.safety = .safe ∧ ci.levelParams = [] := by + intro hfind hprim + change typeFamilyAliasMap.find?' n = some ci at hfind + rw [typeFamilyAliasMap_wf.find?'_eq_find?, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] at hfind + simp [SMap.find?] at hfind + obtain ⟨rfl, rfl⟩ := hfind + simp [Kernel.Environment.primitives, NameSet.ofList] at hprim + simp +decide [NameSet.contains] at hprim + +private def aliasFormerNormalizationVEnvs : VEnvs where + venv _ := typeFamilyAliasEnv + +private theorem aliasFormerNormalizationVEnvs_wf : + aliasFormerNormalizationVEnvs.WF + aliasFormerNormalizationKernelEnv where + tr := by + intro safety + change TrEnv' _ typeFamilyAliasMap false typeFamilyAliasEnv + exact typeFamilyAlias_trEnv' + hasPrimitives := aliasFormerNormalization_hasPrimitives + safePrimitives := aliasFormerNormalization_safePrimitives + mono := fun _ => .rfl + projectionReady := ProjectionReady.of_no_ctorInfo <| by + intro name _info h + change typeFamilyAliasMap.find?' name = some (.ctorInfo _info) at h + rw [typeFamilyAliasMap_wf.find?'_eq_find?] at h + simp only [typeFamilyAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + simp [SMap.find?, typeFamilyAliasInfo] at h + structureEtaReady := StructureEtaReady.of_no_ctorInfo <| by + intro name _info h + change typeFamilyAliasMap.find?' name = some (.ctorInfo _info) at h + rw [typeFamilyAliasMap_wf.find?'_eq_find?] at h + simp only [typeFamilyAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + simp [SMap.find?, typeFamilyAliasInfo] at h + +private def aliasFormerNormalizationContext : TypeChecker.VContext := + TypeChecker.VContext.mk' aliasFormerNormalizationVEnvs_wf + (fuel := { whnf := 2 }) + +private def aliasFormerNormalizationRawContext : TypeChecker.Context where + env := aliasFormerNormalizationKernelEnv + fuel := { whnf := 2 } + +private def aliasFormerCheckTypeState (state : TypeChecker.State) : + TypeChecker.State := + { state with + inferTypeC := state.inferTypeC.insert + (.const ``TypeFamilyAlias []) + (.sort (.succ (.succ .zero))) } + +/-- Insert the raw AliasFormer family before checking its constructor type. -/ +private def aliasFormerCtorNormalizationAddType : + AddInductConstant .induct typeFamilyAliasMap typeFamilyAliasEnv + aliasFormerRawType.toVConstVal aliasFormerTypeMap + aliasFormerTypeEnv where + info := aliasFormerInfo + kind_eq := by simp [aliasFormerInfo, InductConstantKind.Matches] + tr := aliasFormerInfo_tr + map_fresh := by simpa [aliasFormerRawType] using aliasFormerType_fresh + env_add := rfl + map_add := rfl + +private def aliasFormerCtorNormalizationKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_aliasFormerNormalization + aliasFormerTypeMap + +private def aliasFormerCtorNormalizationRawContext : TypeChecker.Context where + env := aliasFormerCtorNormalizationKernelEnv + fuel := { whnf := 2 } + +private def aliasFormerCtorCheckTypeState (state : TypeChecker.State) : + TypeChecker.State := + { state with + inferTypeC := state.inferTypeC.insert + (.const ``AliasFormer []) + (.const ``TypeFamilyAlias []) } + +/-- Insert only the raw `AliasRec` family into the replay environment. This is +the exact staging at which constructor domains are normalized. -/ +private def aliasRecNormalizationAddType : + AddInductConstant .induct recAliasMap recAliasEnv + aliasRecRawType.toVConstVal aliasRecTypeMap aliasRecTypeEnv where + info := aliasRecInfo + kind_eq := by simp [aliasRecInfo, InductConstantKind.Matches] + tr := aliasRecInfo_tr + map_fresh := by simpa [aliasRecRawType] using aliasRecType_fresh + env_add := rfl + map_add := rfl + +private theorem aliasRecNormalization_trEnv' {safety : DefinitionSafety} : + TrEnv' safety aliasRecTypeMap false aliasRecTypeEnv := + .inductStaging aliasRecNormalizationAddType + ⟨.succ (.succ .zero), VEnv.HasType.sort (by decide)⟩ + recAlias_trEnv' + +private def aliasRecNormalizationKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_aliasRecNormalization aliasRecTypeMap + +private theorem aliasRecNormalization_trEnv : + TrEnv .safe aliasRecNormalizationKernelEnv aliasRecTypeEnv := by + simpa [TrEnv, aliasRecNormalizationKernelEnv, + Kernel.Environment.ofConstants] using + aliasRecNormalization_trEnv' + +private theorem aliasRecNormalization_hasPrimitives : + VEnv.HasPrimitives aliasRecTypeEnv := by + apply VEnv.HasPrimitives.of_avoids + intro n hn + simp only [VEnv.reflectedPrimitiveNames, List.mem_cons, + List.not_mem_nil, or_false] at hn + rcases hn with rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl <;> + rfl + +private theorem aliasRecNormalization_safePrimitives : + aliasRecNormalizationKernelEnv.find? n = some ci → + Kernel.Environment.primitives.contains n → + ci.safety = .safe ∧ ci.levelParams = [] := by + intro hfind hprim + change aliasRecTypeMap.find?' n = some ci at hfind + rw [aliasRecTypeMap_wf.find?'_eq_find?, + aliasRecTypeMap, recAliasMap_wf.find?_insert] at hfind + split at hfind + · rename_i heq + simp at heq + subst n + simp [Kernel.Environment.primitives, NameSet.ofList] at hprim + simp +decide [NameSet.contains] at hprim + · rw [recAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] at hfind + simp [SMap.find?] at hfind + obtain ⟨rfl, rfl⟩ := hfind + simp [Kernel.Environment.primitives, NameSet.ofList] at hprim + simp +decide [NameSet.contains] at hprim + +private def aliasRecNormalizationVEnvs : VEnvs where + venv _ := aliasRecTypeEnv + +private theorem aliasRecNormalizationVEnvs_wf : + aliasRecNormalizationVEnvs.WF aliasRecNormalizationKernelEnv where + tr := by + intro safety + change TrEnv' _ aliasRecTypeMap false aliasRecTypeEnv + exact aliasRecNormalization_trEnv' + hasPrimitives := aliasRecNormalization_hasPrimitives + safePrimitives := aliasRecNormalization_safePrimitives + mono := fun _ => .rfl + projectionReady := ProjectionReady.of_no_ctorInfo <| by + intro name _info h + change aliasRecTypeMap.find?' name = some (.ctorInfo _info) at h + rw [aliasRecTypeMap_wf.find?'_eq_find?] at h + simp only [aliasRecTypeMap, recAliasMap_wf.find?_insert] at h + simp only [recAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + by_cases hAliasRec : ``AliasRec = name <;> + by_cases hRecAlias : ``RecAlias = name <;> + simp +decide [hAliasRec, hRecAlias, SMap.find?, aliasRecInfo, + recAliasInfo] at h + structureEtaReady := StructureEtaReady.of_no_ctorInfo <| by + intro name _info h + change aliasRecTypeMap.find?' name = some (.ctorInfo _info) at h + rw [aliasRecTypeMap_wf.find?'_eq_find?] at h + simp only [aliasRecTypeMap, recAliasMap_wf.find?_insert] at h + simp only [recAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + by_cases hAliasRec : ``AliasRec = name <;> + by_cases hRecAlias : ``RecAlias = name <;> + simp +decide [hAliasRec, hRecAlias, SMap.find?, aliasRecInfo, + recAliasInfo] at h + +private def aliasRecNormalizationContext : TypeChecker.VContext := + TypeChecker.VContext.mk' aliasRecNormalizationVEnvs_wf + (fuel := { whnf := 2 }) + +private def aliasRecNormalizationRawContext : TypeChecker.Context where + env := aliasRecNormalizationKernelEnv + fuel := { whnf := 2 } + +private def aliasFormerCandidateContext : AddInductive.Context where + env := aliasFormerNormalizationKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + fuel := { whnf := 2 } + +private def aliasFormerCtorCandidateContext : AddInductive.Context where + env := aliasFormerCtorNormalizationKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + fuel := { whnf := 2 } + +/-- Exact kernel request indexed by the singleton normalization candidate. -/ +private def aliasFormerKernelCtor : Constructor where + name := aliasFormerMkInfo.name + type := aliasFormerMkInfo.type + +private def aliasFormerKernelType : InductiveType where + name := aliasFormerInfo.name + type := aliasFormerInfo.type + ctors := [aliasFormerKernelCtor] + +private theorem aliasFormerNormalization_lookup : + aliasFormerNormalizationKernelEnv.find? ``TypeFamilyAlias = + some typeFamilyAliasInfo := by + change typeFamilyAliasMap.find?' ``TypeFamilyAlias = + some typeFamilyAliasInfo + rw [typeFamilyAliasMap_wf.find?'_eq_find?, typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +private theorem aliasFormerCtorNormalization_lookup : + aliasFormerCtorNormalizationKernelEnv.find? ``AliasFormer = + some aliasFormerInfo := by + change aliasFormerTypeMap.find?' ``AliasFormer = some aliasFormerInfo + rw [aliasFormerTypeMap_wf.find?'_eq_find?, aliasFormerTypeMap, + typeFamilyAliasMap_wf.find?_insert] + rfl + +private theorem aliasRecNormalization_lookup : + aliasRecNormalizationKernelEnv.find? ``RecAlias = + some recAliasInfo := by + change aliasRecTypeMap.find?' ``RecAlias = some recAliasInfo + rw [aliasRecTypeMap_wf.find?'_eq_find?, aliasRecTypeMap, + recAliasMap_wf.find?_insert, recAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + rfl + +private theorem aliasRecNormalization_family_lookup : + aliasRecNormalizationKernelEnv.find? ``AliasRec = + some aliasRecInfo := by + change aliasRecTypeMap.find?' ``AliasRec = some aliasRecInfo + rw [aliasRecTypeMap_wf.find?'_eq_find?, aliasRecTypeMap, + recAliasMap_wf.find?_insert] + rfl + +private def recAliasWhnfKernelExpr : Expr := + recAliasInfo.instantiateValueLevelParams! [.succ .zero] + +private def aliasRecFieldKernelExpr : Expr := + aliasRecMkInfo.type.bindingDomain! + +private theorem aliasRecFieldKernelExpr_eq : + aliasRecFieldKernelExpr = + .app (.const ``RecAlias [.succ .zero]) + (.const ``AliasRec []) := rfl + +private theorem recAliasWhnfKernelExpr_eq : + recAliasWhnfKernelExpr = + .lam `α (.sort (.succ .zero)) (.bvar 0) .default := by + simp [recAliasWhnfKernelExpr, recAliasInfo, + recAliasKernelDef, ConstantInfo.instantiateValueLevelParams!, + ConstantInfo.levelParams, ConstantInfo.value!, + ConstantInfo.toConstantVal, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Level.substParams'] + +private def recAliasUnfoldState (state : TypeChecker.State) : + TypeChecker.State := + { state with + unfold := state.unfold.insert + (.const ``RecAlias [.succ .zero]) + recAliasWhnfKernelExpr } + +/- The following small operational equations expose only the transformer +plumbing needed to kernel-reduce the two concrete WHNF traces. -/ + +@[simp] private theorem normalizationRecMGet (methods context state) : + (get : TypeChecker.RecM TypeChecker.State) methods context state = + .ok (state, state) := rfl + +@[simp] private theorem normalizationRecMReadContext + (methods context state) : + (readThe TypeChecker.Context : TypeChecker.RecM TypeChecker.Context) + methods context state = + .ok (context, state) := rfl + +@[simp] private theorem normalizationRecMModify + (f : TypeChecker.State → TypeChecker.State) + (methods context state) : + (modify f : TypeChecker.RecM PUnit) methods context state = + .ok (.unit, f state) := rfl + +@[simp] private theorem normalizationRecMPure + {α} (a : α) (methods context state) : + (pure a : TypeChecker.RecM α) methods context state = + .ok (a, state) := rfl + +@[simp] private theorem normalizationRecMBind + {α β} (x : TypeChecker.RecM α) + (f : α → TypeChecker.RecM β) (methods context state) : + (x >>= f) methods context state = + match x methods context state with + | .error e => .error e + | .ok (a, state') => f a methods context state' := by + simp [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + cases h : x methods context state with + | error => rfl + | ok value => cases value; rfl + +@[simp] private theorem normalizationRecMGetEnv + (methods context state) : + (liftM TypeChecker.getEnv : + TypeChecker.RecM Kernel.Environment) methods context state = + .ok (context.env, state) := rfl + +@[simp] private theorem normalizationRecMLiftExceptOk + {α} (a : α) (methods context state) : + (liftM (.ok a : Except Kernel.Exception α) : + TypeChecker.RecM α) methods context state = + .ok (a, state) := rfl + +private theorem normalizationExceptPure + {α} (a : α) : + (pure a : Except Kernel.Exception α) = .ok a := rfl + +@[simp] private theorem typeFamilyAlias_noLooseBVars : + (Expr.const ``TypeFamilyAlias []).hasLooseBVars = false := by + simp [Expr.hasLooseBVars, Expr.looseBVarRange'] + +@[simp] private theorem aliasFormer_noLooseBVars : + (Expr.const ``AliasFormer []).hasLooseBVars = false := by + simp [Expr.hasLooseBVars, Expr.looseBVarRange'] + +@[simp] private theorem recAlias_noLooseBVars : + (Expr.const ``RecAlias [.succ .zero]).hasLooseBVars = false := by + simp [Expr.hasLooseBVars, Expr.looseBVarRange'] + +@[simp] private theorem aliasRec_noLooseBVars : + (Expr.const ``AliasRec []).hasLooseBVars = false := by + simp [Expr.hasLooseBVars, Expr.looseBVarRange'] + +@[simp] private theorem aliasRecField_noLooseBVars : + (Expr.app + (.const ``RecAlias [.succ .zero]) + (.const ``AliasRec [])).hasLooseBVars = false := by + simp [Expr.hasLooseBVars, Expr.looseBVarRange'] + +@[simp] private theorem emptyCheckTypeCache_typeFamilyAlias : + (({} : TypeChecker.State).inferTypeC)[ + Expr.const ``TypeFamilyAlias []]? = none := by + exact Std.HashMap.getElem?_empty + +@[simp] private theorem emptyCheckTypeCache_aliasFormer : + (({} : TypeChecker.State).inferTypeC)[ + Expr.const ``AliasFormer []]? = none := by + exact Std.HashMap.getElem?_empty + +@[simp] private theorem emptyCheckTypeCache_recAlias : + (({} : TypeChecker.State).inferTypeC)[ + Expr.const ``RecAlias [.succ .zero]]? = none := by + exact Std.HashMap.getElem?_empty + +@[simp] private theorem emptyCheckTypeCache_aliasRecField : + (({} : TypeChecker.State).inferTypeC)[ + Expr.app + (.const ``RecAlias [.succ .zero]) + (.const ``AliasRec [])]? = none := by + exact Std.HashMap.getElem?_empty + +@[simp] private theorem aliasFormerNormalization_get : + aliasFormerNormalizationRawContext.env.get ``TypeFamilyAlias = + .ok typeFamilyAliasInfo := by + unfold Kernel.Environment.get + change + (match aliasFormerNormalizationKernelEnv.find? ``TypeFamilyAlias with + | some ci => pure ci + | none => throw <| Kernel.Exception.unknownConstant + aliasFormerNormalizationKernelEnv ``TypeFamilyAlias) = + Except.ok typeFamilyAliasInfo + rw [aliasFormerNormalization_lookup] + rfl + +@[simp] private theorem inferConstantTypeFamilyAlias : + TypeChecker.Inner.inferConstant aliasFormerNormalizationRawContext + ``TypeFamilyAlias [] false = + .ok (.sort (.succ (.succ .zero))) := by + unfold TypeChecker.Inner.inferConstant + rw [aliasFormerNormalization_get] + rfl + +@[simp] private theorem aliasFormerCtorNormalization_get : + aliasFormerCtorNormalizationRawContext.env.get ``AliasFormer = + .ok aliasFormerInfo := by + unfold Kernel.Environment.get + change + (match aliasFormerCtorNormalizationKernelEnv.find? ``AliasFormer with + | some ci => pure ci + | none => throw <| Kernel.Exception.unknownConstant + aliasFormerCtorNormalizationKernelEnv ``AliasFormer) = + Except.ok aliasFormerInfo + rw [aliasFormerCtorNormalization_lookup] + rfl + +@[simp] private theorem inferConstantAliasFormer : + TypeChecker.Inner.inferConstant aliasFormerCtorNormalizationRawContext + ``AliasFormer [] false = + .ok (.const ``TypeFamilyAlias []) := by + unfold TypeChecker.Inner.inferConstant + rw [aliasFormerCtorNormalization_get] + rfl + +private theorem checkTypeTypeFamilyAlias : + TypeChecker.Inner.inferType (.const ``TypeFamilyAlias []) false + (TypeChecker.Methods.withFuel 9999) + aliasFormerNormalizationRawContext ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ .zero)), + aliasFormerCheckTypeState {}) := by + change TypeChecker.Inner.inferType' + (.const ``TypeFamilyAlias []) false + (TypeChecker.Methods.withFuel 9998) + aliasFormerNormalizationRawContext ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ .zero)), + aliasFormerCheckTypeState {}) + unfold TypeChecker.Inner.inferType' + simp [aliasFormerCheckTypeState, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem checkTypeTypeFamilyAliasCandidate : + TypeChecker.Inner.inferType (.const ``TypeFamilyAlias []) false + (TypeChecker.Methods.withFuel 10000) + aliasFormerNormalizationRawContext ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ .zero)), + aliasFormerCheckTypeState {}) := by + change TypeChecker.Inner.inferType' + (.const ``TypeFamilyAlias []) false + (TypeChecker.Methods.withFuel 9999) + aliasFormerNormalizationRawContext ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ .zero)), + aliasFormerCheckTypeState {}) + unfold TypeChecker.Inner.inferType' + simp [aliasFormerCheckTypeState, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem checkTypeAliasFormer : + TypeChecker.Inner.inferType (.const ``AliasFormer []) false + (TypeChecker.Methods.withFuel 9999) + aliasFormerCtorNormalizationRawContext ({} : TypeChecker.State) = + .ok (.const ``TypeFamilyAlias [], + aliasFormerCtorCheckTypeState {}) := by + change TypeChecker.Inner.inferType' + (.const ``AliasFormer []) false + (TypeChecker.Methods.withFuel 9998) + aliasFormerCtorNormalizationRawContext ({} : TypeChecker.State) = + .ok (.const ``TypeFamilyAlias [], + aliasFormerCtorCheckTypeState {}) + unfold TypeChecker.Inner.inferType' + simp [aliasFormerCtorCheckTypeState, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem checkTypeAliasFormerCandidate : + TypeChecker.Inner.inferType (.const ``AliasFormer []) false + (TypeChecker.Methods.withFuel 10000) + aliasFormerCtorNormalizationRawContext ({} : TypeChecker.State) = + .ok (.const ``TypeFamilyAlias [], + aliasFormerCtorCheckTypeState {}) := by + change TypeChecker.Inner.inferType' + (.const ``AliasFormer []) false + (TypeChecker.Methods.withFuel 9999) + aliasFormerCtorNormalizationRawContext ({} : TypeChecker.State) = + .ok (.const ``TypeFamilyAlias [], + aliasFormerCtorCheckTypeState {}) + unfold TypeChecker.Inner.inferType' + simp [aliasFormerCtorCheckTypeState, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +@[simp] private theorem aliasRecNormalization_getRecAlias : + aliasRecNormalizationRawContext.env.get ``RecAlias = + .ok recAliasInfo := by + unfold Kernel.Environment.get + change + (match aliasRecNormalizationKernelEnv.find? ``RecAlias with + | some ci => pure ci + | none => throw <| Kernel.Exception.unknownConstant + aliasRecNormalizationKernelEnv ``RecAlias) = + Except.ok recAliasInfo + rw [aliasRecNormalization_lookup] + rfl + +@[simp] private theorem aliasRecNormalization_getFamily : + aliasRecNormalizationRawContext.env.get ``AliasRec = + .ok aliasRecInfo := by + unfold Kernel.Environment.get + change + (match aliasRecNormalizationKernelEnv.find? ``AliasRec with + | some ci => pure ci + | none => throw <| Kernel.Exception.unknownConstant + aliasRecNormalizationKernelEnv ``AliasRec) = + Except.ok aliasRecInfo + rw [aliasRecNormalization_family_lookup] + rfl + +@[simp] private theorem aliasRecNormalization_checkLevelSuccZero : + TypeChecker.Inner.checkLevel aliasRecNormalizationRawContext + (.succ .zero) = .ok () := by + simp [TypeChecker.Inner.checkLevel, Level.getUndefParam, Level.forEach, + Level.hasParam_eq, + Level.hasParam', normalizationExceptPure] + +@[simp] private theorem recAliasInfo_isUnsafe : + recAliasInfo.isUnsafe = false := rfl + +@[simp] private theorem aliasRecNormalization_safety : + aliasRecNormalizationRawContext.safety = .safe := rfl + +@[simp] private theorem recAliasInfo_instantiateType : + recAliasInfo.instantiateTypeLevelParams [.succ .zero] = + .forallE `α (.sort (.succ .zero)) + (.sort (.succ .zero)) .default := by + simp [recAliasInfo, recAliasKernelDef, + ConstantInfo.instantiateTypeLevelParams, + ConstantVal.instantiateTypeLevelParams, + ConstantInfo.toConstantVal, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Level.substParams'] + +@[simp] private theorem inferConstantRecAlias : + TypeChecker.Inner.inferConstant aliasRecNormalizationRawContext + ``RecAlias [.succ .zero] false = + .ok (.forallE `α (.sort (.succ .zero)) + (.sort (.succ .zero)) .default) := by + unfold TypeChecker.Inner.inferConstant + rw [aliasRecNormalization_getRecAlias] + simp [recAliasInfo, recAliasKernelDef, Bind.bind, Except.bind, normalizationExceptPure, + ConstantInfo.levelParams, ConstantInfo.isUnsafe, ConstantInfo.instantiateTypeLevelParams, + ConstantInfo.toConstantVal, ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', Level.substParams'] + +@[simp] private theorem inferConstantAliasRec : + TypeChecker.Inner.inferConstant aliasRecNormalizationRawContext + ``AliasRec [] false = + .ok (.sort (.succ .zero)) := by + unfold TypeChecker.Inner.inferConstant + rw [aliasRecNormalization_getFamily] + rfl + +@[simp] private theorem normalizationWhnfCoreConst + (methods context state n ls) : + (TypeChecker.Inner.whnfCore' (.const n ls) + (cheapProj := false)) + methods context state = + .ok (.const n ls, state) := rfl + +@[simp] private theorem normalizationWhnfCoreSort + (methods context state u) : + (TypeChecker.Inner.whnfCore' (.sort u) + (cheapProj := false)) + methods context state = + .ok (.sort u, state) := rfl + +@[simp] private theorem normalizationWhnfCoreLam + (methods context state name ty body bi) : + (TypeChecker.Inner.whnfCore' (.lam name ty body bi) + (cheapProj := false)) + methods context state = + .ok (.lam name ty body bi, state) := rfl + +@[simp] private theorem normalizationReduceNativeConst + (env methods context state n ls) : + (liftM (TypeChecker.Inner.reduceNative env (.const n ls)) : + TypeChecker.RecM (Option Expr)) methods context state = + .ok (none, state) := rfl + +@[simp] private theorem normalizationReduceNativeSort + (env methods context state u) : + (liftM (TypeChecker.Inner.reduceNative env (.sort u)) : + TypeChecker.RecM (Option Expr)) methods context state = + .ok (none, state) := rfl + +@[simp] private theorem normalizationReduceNativeLam + (env methods context state name ty body bi) : + (liftM (TypeChecker.Inner.reduceNative env (.lam name ty body bi)) : + TypeChecker.RecM (Option Expr)) methods context state = + .ok (none, state) := rfl + +@[simp] private theorem normalizationReduceNatConst + (methods context state n ls) : + TypeChecker.Inner.reduceNat (.const n ls) methods context state = + .ok (none, state) := rfl + +@[simp] private theorem normalizationReduceNatSort + (methods context state u) : + TypeChecker.Inner.reduceNat (.sort u) methods context state = + .ok (none, state) := rfl + +@[simp] private theorem normalizationReduceNatLam + (methods context state name ty body bi) : + TypeChecker.Inner.reduceNat (.lam name ty body bi) + methods context state = + .ok (none, state) := rfl + +@[simp] private theorem normalizationUnfoldSort + (methods context state u) : + TypeChecker.Inner.unfoldDefinition (.sort u) methods context state = + .ok (none, state) := rfl + +@[simp] private theorem normalizationUnfoldLam + (methods context state name ty body bi) : + TypeChecker.Inner.unfoldDefinition (.lam name ty body bi) + methods context state = + .ok (none, state) := rfl + +private theorem unfoldTypeFamilyAlias (methods state) : + TypeChecker.Inner.unfoldDefinition (.const ``TypeFamilyAlias []) + methods aliasFormerNormalizationRawContext state = + .ok (some (.sort (.succ .zero)), state) := by + change + TypeChecker.Inner.unfoldDefinitionCore (.const ``TypeFamilyAlias []) + methods aliasFormerNormalizationRawContext state = + .ok (some (.sort (.succ .zero)), state) + simp [TypeChecker.Inner.unfoldDefinitionCore, TypeChecker.Inner.isDelta, Expr.getAppFn, + aliasFormerNormalizationRawContext, aliasFormerNormalization_lookup, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind, typeFamilyAliasInfo, typeFamilyAliasKernelDef, + ConstantInfo.deltaValue?, TypeChecker.Inner.instantiateDeltaValue, ConstantInfo.numLevelParams, + ConstantInfo.levelParams, ConstantInfo.toConstantVal, Expr.instantiateLevelParams] + +private theorem unfoldAliasFormer (methods state) : + TypeChecker.Inner.unfoldDefinition (.const ``AliasFormer []) + methods aliasFormerCtorNormalizationRawContext state = + .ok (none, state) := by + change + TypeChecker.Inner.unfoldDefinitionCore (.const ``AliasFormer []) + methods aliasFormerCtorNormalizationRawContext state = + .ok (none, state) + simp [TypeChecker.Inner.unfoldDefinitionCore, TypeChecker.Inner.isDelta, + Expr.getAppFn, aliasFormerCtorNormalizationRawContext, + aliasFormerCtorNormalization_lookup, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind, aliasFormerInfo, + ConstantInfo.deltaValue?] + +private theorem unfoldRecAliasInitial (methods) : + TypeChecker.Inner.unfoldDefinition + (.const ``RecAlias [.succ .zero]) + methods aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (some recAliasWhnfKernelExpr, recAliasUnfoldState {}) := by + change + TypeChecker.Inner.unfoldDefinitionCore + (.const ``RecAlias [.succ .zero]) + methods aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (some recAliasWhnfKernelExpr, recAliasUnfoldState {}) + simp [TypeChecker.Inner.unfoldDefinitionCore, TypeChecker.Inner.isDelta, + Expr.getAppFn, aliasRecNormalizationRawContext, + aliasRecNormalization_lookup, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind, recAliasInfo, recAliasKernelDef, + ConstantInfo.deltaValue?, TypeChecker.Inner.instantiateDeltaValue, + ConstantInfo.numLevelParams, + ConstantInfo.instantiateValueLevelParams!, ConstantInfo.levelParams, + ConstantInfo.value!, ConstantInfo.toConstantVal, + Expr.instantiateLevelParams, recAliasWhnfKernelExpr, + recAliasUnfoldState] + +private theorem unfoldRecAliasCoreInitial (methods) : + TypeChecker.Inner.unfoldDefinitionCore + (.const ``RecAlias [.succ .zero]) + methods aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (some recAliasWhnfKernelExpr, recAliasUnfoldState {}) := by + change + TypeChecker.Inner.unfoldDefinition + (.const ``RecAlias [.succ .zero]) + methods aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (some recAliasWhnfKernelExpr, recAliasUnfoldState {}) + exact unfoldRecAliasInitial methods + +private theorem unfoldAliasRecFieldInitial (methods) : + TypeChecker.Inner.unfoldDefinition aliasRecFieldKernelExpr + methods aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (some (.app recAliasWhnfKernelExpr + (.const ``AliasRec [])), recAliasUnfoldState {}) := by + rw [aliasRecFieldKernelExpr_eq] + unfold TypeChecker.Inner.unfoldDefinition + rw [if_pos (show (Expr.app (.const ``RecAlias [.succ .zero]) + (.const ``AliasRec [])).isApp = true from rfl)] + rw [show + (Expr.app (.const ``RecAlias [.succ .zero]) + (.const ``AliasRec [])).getAppFn = + .const ``RecAlias [.succ .zero] by rfl] + simp only [normalizationRecMBind] + rw [unfoldRecAliasCoreInitial] + rw [show + (Expr.app (.const ``RecAlias [.succ .zero]) + (.const ``AliasRec [])).getAppRevArgs = + #[.const ``AliasRec []] by rfl] + simp only [normalizationRecMPure] + rw [Expr.mkAppRevRange_eq + (l₁ := []) (l₂ := [.const ``AliasRec []]) (l₃ := []) + (by simp) (by rfl) (by rfl)] + rfl + +private theorem whnfLoopTypeFamilyAlias (methods state) : + TypeChecker.Inner.whnf'.loop (.const ``TypeFamilyAlias []) 2 + methods aliasFormerNormalizationRawContext state = + .ok (.sort (.succ .zero), state) := by + unfold TypeChecker.Inner.whnf'.loop + simp [unfoldTypeFamilyAlias] + unfold TypeChecker.Inner.whnf'.loop + simp + +private theorem whnfLoopAliasFormer (methods state) : + TypeChecker.Inner.whnf'.loop (.const ``AliasFormer []) 2 + methods aliasFormerCtorNormalizationRawContext state = + .ok (.const ``AliasFormer [], state) := by + unfold TypeChecker.Inner.whnf'.loop + simp [unfoldAliasFormer] + +private theorem whnfLoopRecAlias (methods) : + TypeChecker.Inner.whnf'.loop + (.const ``RecAlias [.succ .zero]) 2 + methods aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (recAliasWhnfKernelExpr, recAliasUnfoldState {}) := by + unfold TypeChecker.Inner.whnf'.loop + simp [unfoldRecAliasInitial] + unfold TypeChecker.Inner.whnf'.loop + rw [recAliasWhnfKernelExpr_eq] + simp + +/-- The actual verified WHNF computation for the raw AliasFormer family +result. -/ +theorem aliasFormerFamily_whnf : + ∃ state : TypeChecker.State, + TypeChecker.Inner.whnf' (.const ``TypeFamilyAlias []) + (TypeChecker.Methods.withFuel 9999) + aliasFormerNormalizationRawContext ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), state) := by + unfold TypeChecker.Inner.whnf' + simp + rw [show (if aliasFormerNormalizationRawContext.eagerReduce then + aliasFormerNormalizationRawContext.fuel.whnfEager + else aliasFormerNormalizationRawContext.fuel.whnf) = 2 by rfl] + rw [whnfLoopTypeFamilyAlias] + simp [Functor.map, StateT.map, Except.map] + +/-- Constructor normalization is staged after inserting the raw family. The +family constant is opaque, so this exact checker run retains the constructor +type unchanged. -/ +theorem aliasFormerCtor_whnf : + ∃ state : TypeChecker.State, + TypeChecker.Inner.whnf' (.const ``AliasFormer []) + (TypeChecker.Methods.withFuel 9999) + aliasFormerCtorNormalizationRawContext + ({} : TypeChecker.State) = + .ok (.const ``AliasFormer [], state) := by + unfold TypeChecker.Inner.whnf' + simp + rw [show (if aliasFormerCtorNormalizationRawContext.eagerReduce then + aliasFormerCtorNormalizationRawContext.fuel.whnfEager + else aliasFormerCtorNormalizationRawContext.fuel.whnf) = 2 by rfl] + rw [whnfLoopAliasFormer] + simp [Functor.map, StateT.map, Except.map] + +/-- The full non-inference-only checker run for the raw AliasFormer family +type. The returned sort is recorded together with the checker's cache update, +rather than supplied as an external Theory premise. -/ +theorem aliasFormerFamily_checkType : + ∃ state : TypeChecker.State, + TypeChecker.Inner.inferType aliasFormerInfo.type false + (TypeChecker.Methods.withFuel 9999) + aliasFormerNormalizationContext.toContext + ({} : TypeChecker.State) = + .ok (.sort (.succ (.succ .zero)), state) := by + exact ⟨aliasFormerCheckTypeState {}, by + simpa [aliasFormerInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, + aliasFormerNormalizationContext, + TypeChecker.VContext.mk', TypeChecker.VContext.mk1, + TypeChecker.MLCtx.lctx, + aliasFormerNormalizationRawContext] using + checkTypeTypeFamilyAlias⟩ + +/-- The exact full checker run for the actual AliasFormer constructor type, +staged after insertion of the raw family. The checker returns the retained +family-type alias rather than silently normalizing it. -/ +theorem aliasFormerCtor_checkType : + ∃ state : TypeChecker.State, + TypeChecker.Inner.inferType aliasFormerMkInfo.type false + (TypeChecker.Methods.withFuel 9999) + aliasFormerCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.const ``TypeFamilyAlias [], state) := by + exact ⟨aliasFormerCtorCheckTypeState {}, by + simpa [aliasFormerMkInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, + aliasFormerCtorCandidateContext, + AddInductive.Context.toTypeChecker, + aliasFormerCtorNormalizationRawContext] using + checkTypeAliasFormer⟩ + +/-- The actual verified WHNF computation for the reducible `RecAlias` +head at the universe used by `AliasRec.mk`. -/ +theorem recAlias_whnf : + ∃ state : TypeChecker.State, + TypeChecker.Inner.whnf' + (.const ``RecAlias [.succ .zero]) + (TypeChecker.Methods.withFuel 9999) + aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (recAliasWhnfKernelExpr, state) := by + unfold TypeChecker.Inner.whnf' + simp + rw [show (if aliasRecNormalizationRawContext.eagerReduce then + aliasRecNormalizationRawContext.fuel.whnfEager + else aliasRecNormalizationRawContext.fuel.whnf) = 2 by rfl] + rw [whnfLoopRecAlias] + simp [Functor.map, StateT.map, Except.map] + +private theorem aliasFormerFamily_whnfM : + TypeChecker.M.run aliasFormerNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.whnf aliasFormerInfo.type) = + .ok (.sort (.succ .zero)) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' + (.const ``TypeFamilyAlias []) + (TypeChecker.Methods.withFuel 9999) + aliasFormerNormalizationRawContext ({} : TypeChecker.State)) = + Except.ok (.sort (.succ .zero)) + obtain ⟨state, hrun⟩ := aliasFormerFamily_whnf + rw [hrun] + rfl + +private theorem aliasFormerFamily_checkTypeM : + TypeChecker.M.run aliasFormerNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.checkType aliasFormerInfo.type) = + .ok (.sort (.succ (.succ .zero))) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType aliasFormerInfo.type false + (TypeChecker.Methods.withFuel 10000) + aliasFormerNormalizationRawContext ({} : TypeChecker.State)) = + Except.ok (.sort (.succ (.succ .zero))) + rw [show aliasFormerInfo.type = + .const ``TypeFamilyAlias [] by rfl] + rw [checkTypeTypeFamilyAliasCandidate] + rfl + +private theorem aliasFormerCtor_checkTypeM : + TypeChecker.M.run aliasFormerCtorNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.checkType aliasFormerMkInfo.type) = + .ok (.const ``TypeFamilyAlias []) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType aliasFormerMkInfo.type false + (TypeChecker.Methods.withFuel 10000) + aliasFormerCtorNormalizationRawContext ({} : TypeChecker.State)) = + Except.ok (.const ``TypeFamilyAlias []) + rw [show aliasFormerMkInfo.type = + .const ``AliasFormer [] by rfl] + rw [checkTypeAliasFormerCandidate] + rfl + +private theorem aliasFormerCtor_whnfM : + TypeChecker.M.run aliasFormerCtorNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.whnf aliasFormerMkInfo.type) = + .ok (.const ``AliasFormer []) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' + (.const ``AliasFormer []) + (TypeChecker.Methods.withFuel 9999) + aliasFormerCtorNormalizationRawContext ({} : TypeChecker.State)) = + Except.ok (.const ``AliasFormer []) + obtain ⟨state, hrun⟩ := aliasFormerCtor_whnf + rw [hrun] + rfl + +private def annotatedPiRawDomainKernel : Expr := + .app (.const ``outParam [.succ .zero]) (.sort .zero) + +private def annotatedPiInnerKernel : Expr := + .forallE `p annotatedPiRawDomainKernel + (.const ``AnnotatedPi []) .default + +@[simp] private theorem annotatedPiRawDomain_getAppFn : + annotatedPiRawDomainKernel.getAppFn = + .const ``outParam [.succ .zero] := rfl + +@[simp] private theorem annotatedPiRawDomain_getAppRevArgs : + annotatedPiRawDomainKernel.getAppRevArgs = #[.sort .zero] := rfl + +private def annotatedPiOutParamWhnfKernelExpr : Expr := + annotationOutParamInfo.instantiateValueLevelParams! [.succ .zero] + +private theorem annotatedPiOutParamWhnfKernelExpr_eq : + annotatedPiOutParamWhnfKernelExpr = + .lam `α (.sort (.succ .zero)) (.bvar 0) .default := by + simp [annotatedPiOutParamWhnfKernelExpr, annotationOutParamInfo, + ConstantInfo.instantiateValueLevelParams!, ConstantInfo.levelParams, ConstantInfo.value!, + ConstantInfo.toConstantVal, Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', + Level.substParams'] + +private def annotatedPiOutParamUnfoldState (state : TypeChecker.State) : + TypeChecker.State := + { state with + unfold := state.unfold.insert + (.const ``outParam [.succ .zero]) + annotatedPiOutParamWhnfKernelExpr } + +private def annotatedPiDomainBetaKernel : Expr := + .app annotatedPiOutParamWhnfKernelExpr (.sort .zero) + +private def annotatedPiDomainBetaState (state : TypeChecker.State) : + TypeChecker.State := + { state with + whnfCoreCache := state.whnfCoreCache.insert + annotatedPiDomainBetaKernel (.sort .zero) } + +@[simp] private theorem annotatedPiType_quotInit : + annotatedPiTypeKernelEnv.quotInit = false := rfl + +private theorem annotatedPiInductiveReduceRecDomain + {m : Type → Type} [Monad m] + (whnf inferType : Expr → m Expr) + (isDefEq : Expr → Expr → m Bool) (isNeverProp : Expr → m Bool) : + inductiveReduceRec annotatedPiTypeKernelEnv annotatedPiRawDomainKernel + whnf inferType isDefEq isNeverProp = + pure none := by + unfold inductiveReduceRec + rw [show annotatedPiRawDomainKernel.getAppFn = + .const ``outParam [.succ .zero] by rfl] + simp only + rw [annotatedPiType_lookup_outParam] + rfl + +private theorem annotatedPiReduceRecursorDomain + (methods state) : + TypeChecker.Inner.reduceRecursor annotatedPiRawDomainKernel + methods annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (none, state) := by + unfold TypeChecker.Inner.reduceRecursor + simp only [normalizationRecMBind, normalizationRecMGetEnv] + rw [if_neg (show + ¬(annotatedPiCtorCandidateContext.toTypeChecker.env.quotInit = true) by + simp [annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker, annotatedPiType_quotInit])] + simp only [annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker] + rw [annotatedPiInductiveReduceRecDomain] + rfl + +@[simp] private theorem annotatedPiWhnfCoreOutParamConst (n state) : + TypeChecker.Inner.whnfCore + (.const ``outParam [.succ .zero]) false + (TypeChecker.Methods.withFuel (n + 1)) + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (.const ``outParam [.succ .zero], state) := by + rfl + +private theorem annotatedPiWhnfCoreDomainInitial (n) : + TypeChecker.Inner.whnfCore' annotatedPiRawDomainKernel + (cheapProj := false) + (TypeChecker.Methods.withFuel (n + 1)) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (annotatedPiRawDomainKernel, ({} : TypeChecker.State)) := by + change + TypeChecker.Inner.whnfCore' + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (cheapProj := false) + (TypeChecker.Methods.withFuel (n + 1)) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.app (.const ``outParam [.succ .zero]) (.sort .zero), + ({} : TypeChecker.State)) + unfold TypeChecker.Inner.whnfCore' + simp only [normalizationRecMBind, normalizationRecMGet, Std.HashMap.getElem?_empty] + rw [Expr.withRevApp_eq] + simp only [normalizationRecMBind] + rw [show + (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).getAppFn = + .const ``outParam [.succ .zero] by rfl] + rw [annotatedPiWhnfCoreOutParamConst n ({} : TypeChecker.State)] + simp [Expr.structuralEq, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show + .app (.const ``outParam [.succ .zero]) (.sort .zero) = + annotatedPiRawDomainKernel by rfl] + rw [annotatedPiReduceRecursorDomain] + rfl + +private theorem annotatedPiUnfoldOutParamCoreInitial (methods) : + TypeChecker.Inner.unfoldDefinitionCore + (.const ``outParam [.succ .zero]) + methods annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (some annotatedPiOutParamWhnfKernelExpr, + annotatedPiOutParamUnfoldState {}) := by + simp [TypeChecker.Inner.unfoldDefinitionCore, TypeChecker.Inner.isDelta, Expr.getAppFn, + annotatedPiCtorCandidateContext, AddInductive.Context.toTypeChecker, + annotatedPiType_lookup_outParam, Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + annotationOutParamInfo, ConstantInfo.deltaValue?, TypeChecker.Inner.instantiateDeltaValue, + ConstantInfo.numLevelParams, ConstantInfo.instantiateValueLevelParams!, + ConstantInfo.levelParams, ConstantInfo.value!, ConstantInfo.toConstantVal, + Expr.instantiateLevelParams, annotatedPiOutParamWhnfKernelExpr, annotatedPiOutParamUnfoldState] + +private theorem annotatedPiUnfoldDomainInitial (methods) : + TypeChecker.Inner.unfoldDefinition annotatedPiRawDomainKernel + methods annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (some annotatedPiDomainBetaKernel, + annotatedPiOutParamUnfoldState {}) := by + change + TypeChecker.Inner.unfoldDefinition + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + methods annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (some annotatedPiDomainBetaKernel, + annotatedPiOutParamUnfoldState {}) + unfold TypeChecker.Inner.unfoldDefinition + rw [if_pos (show (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).isApp = true from rfl)] + rw [show + (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).getAppFn = + .const ``outParam [.succ .zero] by rfl] + simp only [normalizationRecMBind] + rw [annotatedPiUnfoldOutParamCoreInitial] + rw [show + (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).getAppRevArgs = #[.sort .zero] by rfl] + simp only [normalizationRecMPure] + rw [Expr.mkAppRevRange_eq + (l₁ := []) (l₂ := [.sort .zero]) (l₃ := []) + (by simp) (by rfl) (by rfl)] + rfl + +@[simp] private theorem annotatedPiWhnfCoreOutParamIdentity (n state) : + TypeChecker.Inner.whnfCore + (.lam `α (.sort (.succ .zero)) (.bvar 0) .default) + false (TypeChecker.Methods.withFuel (n + 1)) + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (.lam `α (.sort (.succ .zero)) (.bvar 0) .default, + state) := by + rfl + +@[simp] private theorem annotatedPiWhnfCoreDomainSort (n state) : + TypeChecker.Inner.whnfCore (.sort .zero) false + (TypeChecker.Methods.withFuel (n + 1)) + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (.sort .zero, state) := by + rfl + +@[simp] private theorem annotatedPiSort_mkAppRevRangeZero : + (Expr.sort .zero).mkAppRevRange 0 0 #[.sort .zero] = + .sort .zero := by + rw [Expr.mkAppRevRange_eq + (l₁ := []) (l₂ := []) (l₃ := [.sort .zero]) + (by simp) (by rfl) (by rfl)] + rfl + +private theorem annotatedPiWhnfCoreDomainBeta (n) : + TypeChecker.Inner.whnfCore' annotatedPiDomainBetaKernel + (cheapProj := false) + (TypeChecker.Methods.withFuel (n + 1)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiOutParamUnfoldState {}) = + .ok (.sort .zero, + annotatedPiDomainBetaState + (annotatedPiOutParamUnfoldState {})) := by + rw [annotatedPiDomainBetaKernel, + annotatedPiOutParamWhnfKernelExpr_eq] + unfold TypeChecker.Inner.whnfCore' + simp only [normalizationRecMBind, normalizationRecMGet, annotatedPiOutParamUnfoldState, + Std.HashMap.getElem?_empty] + rw [Expr.withRevApp_eq] + simp only [normalizationRecMBind] + rw [show + (Expr.app + (.lam `α (.sort (.succ .zero)) (.bvar 0) .default) + (.sort .zero)).getAppFn = + .lam `α (.sort (.succ .zero)) (.bvar 0) .default by rfl] + rw [annotatedPiWhnfCoreOutParamIdentity] + rw [show + (Expr.app + (.lam `α (.sort (.succ .zero)) (.bvar 0) .default) + (.sort .zero)).getAppRevArgs = #[.sort .zero] by rfl] + simp [TypeChecker.Inner.whnfCore'.loop, TypeChecker.Inner.whnfCore'.loop.cont, + TypeChecker.Inner.whnfCore'.save, annotatedPiDomainBetaKernel, + annotatedPiOutParamWhnfKernelExpr_eq, annotatedPiDomainBetaState, Expr.instantiate1', Bind.bind, + ReaderT.bind, StateT.bind, Except.bind] + +@[simp] private theorem annotatedPiReduceNativeDomain + (env methods state) : + (liftM (TypeChecker.Inner.reduceNative env annotatedPiRawDomainKernel) : + TypeChecker.RecM (Option Expr)) + methods annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (none, state) := by + rfl + +@[simp] private theorem annotatedPiReduceNatDomain (methods state) : + TypeChecker.Inner.reduceNat annotatedPiRawDomainKernel + methods annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (none, state) := by + change + TypeChecker.Inner.reduceNat + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + methods annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (none, state) + simp [TypeChecker.Inner.reduceNat, Expr.getAppNumArgs_eq, + Expr.getAppArgsRevList, Expr.appFn!, Expr.structuralEq] + +private theorem annotatedPiWhnfLoopDomain : + TypeChecker.Inner.whnf'.loop annotatedPiRawDomainKernel 100000 + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort .zero, + annotatedPiDomainBetaState + (annotatedPiOutParamUnfoldState {})) := by + rw [show 100000 = 99999 + 1 by rfl] + unfold TypeChecker.Inner.whnf'.loop + rw [show 9999 = 9998 + 1 by rfl] + simp only [normalizationRecMBind, normalizationRecMGetEnv] + rw [annotatedPiWhnfCoreDomainInitial] + simp only [] + rw [annotatedPiReduceNativeDomain] + simp only [normalizationRecMBind] + rw [annotatedPiReduceNatDomain] + simp only [normalizationRecMBind] + rw [annotatedPiUnfoldDomainInitial] + simp only [] + unfold TypeChecker.Inner.whnf'.loop + simp only [normalizationRecMBind, normalizationRecMGetEnv] + rw [annotatedPiWhnfCoreDomainBeta] + simp only [] + rw [normalizationReduceNativeSort] + simp only [normalizationRecMBind] + rw [normalizationReduceNatSort] + simp only [normalizationRecMBind] + rw [normalizationUnfoldSort] + rfl + +private theorem annotatedPiWhnfLoopDomainConcrete : + TypeChecker.Inner.whnf'.loop + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) 100000 + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort .zero, + annotatedPiDomainBetaState + (annotatedPiOutParamUnfoldState {})) := by + exact annotatedPiWhnfLoopDomain + +private theorem annotatedPiDomain_checkTypeM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType annotatedPiRawDomainKernel) = + .ok (.sort (.succ .zero)) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType annotatedPiRawDomainKernel false + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' annotatedPiRawDomainKernel false + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + unfold annotatedPiRawDomainKernel TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', TypeChecker.Inner.inferType', Bind.bind, + ReaderT.bind, StateT.bind, Except.bind] + rw [annotatedPiIsDefEqSort 9999] + simp [Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rfl + +private theorem annotatedPiDomain_whnfM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.whnf annotatedPiRawDomainKernel) = + .ok (.sort .zero) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' annotatedPiRawDomainKernel + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort .zero) + rw [show annotatedPiRawDomainKernel = + .app (.const ``outParam [.succ .zero]) (.sort .zero) by rfl] + unfold TypeChecker.Inner.whnf' + simp + rw [show + (if annotatedPiCtorCandidateContext.toTypeChecker.eagerReduce then + annotatedPiCtorCandidateContext.toTypeChecker.fuel.whnfEager + else annotatedPiCtorCandidateContext.toTypeChecker.fuel.whnf) = + 100000 by rfl] + rw [annotatedPiWhnfLoopDomainConcrete] + simp [Functor.map, StateT.map, Except.map] + +@[simp] private theorem annotatedPiApp_beq_sort + (fn arg : Expr) (u : Level) : + ((.app fn arg : Expr) == .sort u) = false := by + change Expr.eqv (.app fn arg) (.sort u) = false + rw [Expr.eqv_eq] + rfl + +/-- `quickIsDefEq` only reads the success cache, so whichever answer the cache gives, the state +comes back unchanged and the result is `.true` or `.undef` -- never `.false`, since an application +and a sort are not settled structurally. -/ +private theorem annotatedPiQuickIsDefEqDomainInitial + (methods : TypeChecker.Methods) + (context : TypeChecker.Context) (initial : Std.HashSet (Expr × Expr)) : + ∃ (r : LBool) (m : Std.HashSet (Expr × Expr)), + TypeChecker.Inner.quickIsDefEq + annotatedPiRawDomainKernel (.sort .zero) + methods context ({ success := initial } : TypeChecker.State) = + .ok (r, ({ success := m } : TypeChecker.State)) ∧ + (r = .true ∨ r = .undef) := by + have hb : (annotatedPiRawDomainKernel == Expr.sort .zero) = false := + annotatedPiApp_beq_sort .. + by_cases h : TypeChecker.Inner.succeededBefore initial + annotatedPiRawDomainKernel (.sort .zero) = true + · refine ⟨.true, initial, ?_, Or.inl rfl⟩ + simp [TypeChecker.Inner.quickIsDefEq, hb, h, Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + pure, ReaderT.pure, StateT.pure, Except.pure] + · simp only [Bool.not_eq_true] at h + refine ⟨.undef, initial, ?_, Or.inr rfl⟩ + simp [TypeChecker.Inner.quickIsDefEq, hb, h, Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + pure] + rfl + +@[simp] private theorem annotatedPiWhnfCoreOutParamConstCheap + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.whnfCore + (.const ``outParam [.succ .zero]) true + (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.const ``outParam [.succ .zero], + ({ success := m } : TypeChecker.State)) := by + rfl + +private theorem annotatedPiWhnfCoreDomainCheap + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.whnfCore annotatedPiRawDomainKernel true + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (annotatedPiRawDomainKernel, + ({ success := m } : TypeChecker.State)) := by + change + TypeChecker.Inner.whnfCore' + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + true (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.app (.const ``outParam [.succ .zero]) (.sort .zero), + ({ success := m } : TypeChecker.State)) + unfold TypeChecker.Inner.whnfCore' + simp only [normalizationRecMBind, normalizationRecMGet, Std.HashMap.getElem?_empty] + rw [Expr.withRevApp_eq] + simp only [normalizationRecMBind] + rw [show + (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).getAppFn = + .const ``outParam [.succ .zero] by rfl] + rw [annotatedPiWhnfCoreOutParamConstCheap fuel] + simp [Expr.structuralEq, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [show + .app (.const ``outParam [.succ .zero]) (.sort .zero) = + annotatedPiRawDomainKernel by rfl] + rw [annotatedPiReduceRecursorDomain] + rfl + +@[simp] private theorem annotatedPiInferConstantOutParamCandidateOnly : + TypeChecker.Inner.inferConstant + annotatedPiCtorCandidateContext.toTypeChecker + ``outParam [.succ .zero] true = + .ok annotatedPiOutParamFnType := by + unfold TypeChecker.Inner.inferConstant + simp only [annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker] + rw [show annotatedPiTypeKernelEnv.get ``outParam = + .ok annotationOutParamInfo by exact annotatedPiType_get_outParam] + simp [annotationOutParamInfo, annotatedPiOutParamFnType, Bind.bind, Except.bind, + annotatedPiExceptPure, ConstantInfo.levelParams, ConstantInfo.instantiateTypeLevelParams, + ConstantInfo.toConstantVal, ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, Expr.instantiateLevelParamsCore', Level.substParams'] + +private def annotatedPiOutParamInferOnlyState + (m : Std.HashSet (Expr × Expr)) : TypeChecker.State := + { inferTypeI := ({} : InferCache).insert + (.const ``outParam [.succ .zero]) annotatedPiOutParamFnType, + success := m } + +private theorem annotatedPiInferTypeOutParamOnly + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.inferType + (.const ``outParam [.succ .zero]) true + (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (annotatedPiOutParamFnType, + annotatedPiOutParamInferOnlyState m) := by + change + TypeChecker.Inner.inferType' + (.const ``outParam [.succ .zero]) true + (TypeChecker.Methods.withFuel (fuel + 1)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (annotatedPiOutParamFnType, + annotatedPiOutParamInferOnlyState m) + unfold TypeChecker.Inner.inferType' + simp [annotatedPiOutParamInferOnlyState, + Expr.hasLooseBVars, Expr.looseBVarRange', + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem annotatedPiInferAppDomainOnly + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.inferApp annotatedPiRawDomainKernel + (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.sort (.succ .zero), + annotatedPiOutParamInferOnlyState m) := by + unfold TypeChecker.Inner.inferApp + rw [Expr.withApp_eq] + rw [annotatedPiRawDomain_getAppFn] + rw [show annotatedPiRawDomainKernel.getAppArgs = + #[.sort .zero] by rfl] + simp only [normalizationRecMBind] + rw [annotatedPiInferTypeOutParamOnly fuel] + simp [TypeChecker.Inner.inferApp.loop, annotatedPiOutParamFnType] + +private def annotatedPiDomainInferOnlyState + (m : Std.HashSet (Expr × Expr)) : TypeChecker.State := + { inferTypeI := + (({} : InferCache).insert + (.const ``outParam [.succ .zero]) annotatedPiOutParamFnType).insert + annotatedPiRawDomainKernel (.sort (.succ .zero)), + success := m } + +private theorem annotatedPiInferTypeDomainOnlyAny + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.inferType annotatedPiRawDomainKernel true + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.sort (.succ .zero), annotatedPiDomainInferOnlyState m) := by + change + TypeChecker.Inner.inferType' annotatedPiRawDomainKernel true + (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.sort (.succ .zero), annotatedPiDomainInferOnlyState m) + rw [show annotatedPiRawDomainKernel = + .app (.const ``outParam [.succ .zero]) (.sort .zero) by rfl] + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + annotatedPiDomainInferOnlyState, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rw [show + .app (.const ``outParam [.succ .zero]) (.sort .zero) = + annotatedPiRawDomainKernel by rfl] + rw [annotatedPiInferAppDomainOnly fuel] + simp [annotatedPiOutParamInferOnlyState] + +private theorem annotatedPiInferTypeDomainOnly998 + (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.inferType' + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) true + (TypeChecker.Methods.withFuel 9998) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.sort (.succ .zero), annotatedPiDomainInferOnlyState m) := by + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + annotatedPiDomainInferOnlyState, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rw [show + .app (.const ``outParam [.succ .zero]) (.sort .zero) = + annotatedPiRawDomainKernel by rfl] + rw [show TypeChecker.Inner.inferApp annotatedPiRawDomainKernel + (TypeChecker.Methods.withFuel 9998) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.sort (.succ .zero), annotatedPiOutParamInferOnlyState m) by + simpa only [Nat.reduceAdd] using + annotatedPiInferAppDomainOnly 9996 m] + simp [annotatedPiOutParamInferOnlyState] + +private def annotatedPiSortOneInferOnlyState + (m : Std.HashSet (Expr × Expr)) : TypeChecker.State := + { annotatedPiDomainInferOnlyState m with + inferTypeI := (annotatedPiDomainInferOnlyState m).inferTypeI.insert + (.sort (.succ .zero)) (.sort (.succ (.succ .zero))) } + +@[simp] private theorem annotatedPiDomainInferOnlyState_sortOneMiss + (m : Std.HashSet (Expr × Expr)) : + (annotatedPiDomainInferOnlyState m).inferTypeI[ + (.sort (.succ .zero) : Expr)]? = none := by + simp [annotatedPiDomainInferOnlyState, annotatedPiRawDomainKernel, annotatedPiOutParamFnType] + +private theorem annotatedPiInferTypeSortOneOnly + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.inferType (.sort (.succ .zero)) true + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiDomainInferOnlyState m) = + .ok (.sort (.succ (.succ .zero)), + annotatedPiSortOneInferOnlyState m) := by + change + TypeChecker.Inner.inferType' (.sort (.succ .zero)) true + (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiDomainInferOnlyState m) = + .ok (.sort (.succ (.succ .zero)), + annotatedPiSortOneInferOnlyState m) + unfold TypeChecker.Inner.inferType' + simp [annotatedPiDomainInferOnlyState_sortOneMiss, + annotatedPiSortOneInferOnlyState, Expr.hasLooseBVars, + Expr.looseBVarRange', Bind.bind, ReaderT.bind, StateT.bind, + Except.bind] + +@[simp] private theorem annotatedPiWhnfSortTwo + (fuel : Nat) (state : TypeChecker.State) : + TypeChecker.Inner.whnf (.sort (.succ (.succ .zero))) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (.sort (.succ (.succ .zero)), state) := by + rfl + +private theorem annotatedPiIsPropSortOneFalse + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.isProp (.sort (.succ .zero)) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiDomainInferOnlyState m) = + .ok (false, annotatedPiSortOneInferOnlyState m) := by + unfold TypeChecker.Inner.isProp TypeChecker.Inner.getSortLevel + simp only [normalizationRecMBind] + rw [annotatedPiInferTypeSortOneOnly fuel] + rfl + +private theorem annotatedPiIsDefEqProofIrrelDomain + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.isDefEqProofIrrel + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (.undef, annotatedPiSortOneInferOnlyState m) := by + unfold TypeChecker.Inner.isDefEqProofIrrel + simp only [normalizationRecMBind] + rw [annotatedPiInferTypeDomainOnlyAny fuel] + simp only [] + rw [annotatedPiIsPropSortOneFalse fuel] + rfl + +private theorem annotatedPiUnfoldOutParamCoreOfMiss + (methods : TypeChecker.Methods) (state : TypeChecker.State) + (hcache : state.unfold[ + (.const ``outParam [.succ .zero] : Expr)]? = none) : + TypeChecker.Inner.unfoldDefinitionCore + (.const ``outParam [.succ .zero]) methods + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (some annotatedPiOutParamWhnfKernelExpr, + annotatedPiOutParamUnfoldState state) := by + simp [TypeChecker.Inner.unfoldDefinitionCore, + TypeChecker.Inner.isDelta, Expr.getAppFn, + annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker, annotatedPiType_lookup_outParam, + hcache, Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + annotationOutParamInfo, ConstantInfo.deltaValue?, + TypeChecker.Inner.instantiateDeltaValue, + ConstantInfo.numLevelParams, + ConstantInfo.instantiateValueLevelParams!, ConstantInfo.levelParams, + ConstantInfo.value!, ConstantInfo.toConstantVal, + Expr.instantiateLevelParams, annotatedPiOutParamWhnfKernelExpr, + annotatedPiOutParamUnfoldState] + +private theorem annotatedPiUnfoldDomainOfMiss + (methods : TypeChecker.Methods) (state : TypeChecker.State) + (hcache : state.unfold[ + (.const ``outParam [.succ .zero] : Expr)]? = none) : + TypeChecker.Inner.unfoldDefinition annotatedPiRawDomainKernel + methods annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (some annotatedPiDomainBetaKernel, + annotatedPiOutParamUnfoldState state) := by + change + TypeChecker.Inner.unfoldDefinition + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + methods annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (some annotatedPiDomainBetaKernel, + annotatedPiOutParamUnfoldState state) + unfold TypeChecker.Inner.unfoldDefinition + rw [if_pos (show (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).isApp = true from rfl)] + rw [show + (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).getAppFn = + .const ``outParam [.succ .zero] by rfl] + simp only [normalizationRecMBind] + rw [annotatedPiUnfoldOutParamCoreOfMiss methods state hcache] + rw [show + (Expr.app (.const ``outParam [.succ .zero]) + (.sort .zero)).getAppRevArgs = #[.sort .zero] by rfl] + simp only [normalizationRecMPure] + rw [Expr.mkAppRevRange_eq + (l₁ := []) (l₂ := [.sort .zero]) (l₃ := []) + (by simp) (by rfl) (by rfl)] + rfl + +@[simp] private theorem annotatedPiWhnfCoreIdentityCheap + (fuel : Nat) (state) : + TypeChecker.Inner.whnfCore + (.lam `α (.sort (.succ .zero)) (.bvar 0) .default) + true (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (.lam `α (.sort (.succ .zero)) (.bvar 0) .default, + state) := by + rfl + +@[simp] private theorem annotatedPiWhnfCoreSortZeroCheap + (fuel : Nat) (state) : + TypeChecker.Inner.whnfCore (.sort .zero) true + (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (.sort .zero, state) := by + rfl + +private theorem annotatedPiWhnfCoreDomainBetaCheap + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.whnfCore annotatedPiDomainBetaKernel true + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) = + .ok (.sort .zero, + annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) := by + change + TypeChecker.Inner.whnfCore' annotatedPiDomainBetaKernel true + (TypeChecker.Methods.withFuel (fuel + 2)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) = + .ok (.sort .zero, + annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) + rw [annotatedPiDomainBetaKernel, + annotatedPiOutParamWhnfKernelExpr_eq] + unfold TypeChecker.Inner.whnfCore' + simp only [normalizationRecMBind, normalizationRecMGet, annotatedPiOutParamUnfoldState, + annotatedPiSortOneInferOnlyState, annotatedPiDomainInferOnlyState, Std.HashMap.getElem?_empty] + rw [Expr.withRevApp_eq] + simp only [normalizationRecMBind] + rw [show + (Expr.app + (.lam `α (.sort (.succ .zero)) (.bvar 0) .default) + (.sort .zero)).getAppFn = + .lam `α (.sort (.succ .zero)) (.bvar 0) .default by rfl] + rw [annotatedPiWhnfCoreIdentityCheap fuel] + rw [show + (Expr.app + (.lam `α (.sort (.succ .zero)) (.bvar 0) .default) + (.sort .zero)).getAppRevArgs = #[.sort .zero] by rfl] + simp [TypeChecker.Inner.whnfCore'.loop, TypeChecker.Inner.whnfCore'.loop.cont, + TypeChecker.Inner.whnfCore'.save, annotatedPiOutParamWhnfKernelExpr_eq, Expr.instantiate1', + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem annotatedPiQuickIsDefEqSortZeroAny + (methods : TypeChecker.Methods) + (context : TypeChecker.Context) + (initial : TypeChecker.State) : + ∃ m : Std.HashSet (Expr × Expr), + TypeChecker.Inner.quickIsDefEq (.sort .zero) (.sort .zero) + methods context initial = + .ok (.true, annotatedPiWithSuccessCache initial m) := by + -- The two sides are syntactically equal, so the structural check settles it without the cache. + refine ⟨initial.success, ?_⟩ + simp [TypeChecker.Inner.quickIsDefEq, annotatedPiWithSuccessCache, pure, ReaderT.pure, + StateT.pure, Except.pure, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem annotatedPiIsDeltaDomain : + TypeChecker.Inner.isDelta annotatedPiTypeKernelEnv + annotatedPiRawDomainKernel = + some annotationOutParamInfo := by + unfold TypeChecker.Inner.isDelta + rw [annotatedPiRawDomain_getAppFn] + simp only + rw [annotatedPiType_lookup_outParam] + simp [annotationOutParamInfo, ConstantInfo.deltaValue?, + ConstantInfo.numLevelParams, ConstantInfo.levelParams, + ConstantInfo.toConstantVal] + +@[simp] private theorem annotatedPiIsDeltaSortZero : + TypeChecker.Inner.isDelta annotatedPiTypeKernelEnv (.sort .zero) = + none := by + rfl + +@[simp] private theorem annotatedPiTryUnfoldProjAppSortZero + (methods state) : + TypeChecker.Inner.tryUnfoldProjApp (.sort .zero) methods + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (none, state) := by + rfl + +private theorem annotatedPiDeltaDomain + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + (TypeChecker.Inner.unfoldDefinition annotatedPiRawDomainKernel >>= + fun e => TypeChecker.Inner.whnfCore e.get! true) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiSortOneInferOnlyState m) = + .ok (.sort .zero, + annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) := by + simp only [normalizationRecMBind] + rw [annotatedPiUnfoldDomainOfMiss + (TypeChecker.Methods.withFuel (fuel + 3)) + (annotatedPiSortOneInferOnlyState m) (by + simp [annotatedPiSortOneInferOnlyState, + annotatedPiDomainInferOnlyState])] + simp only + rw [show (some annotatedPiDomainBetaKernel).get! = + annotatedPiDomainBetaKernel by rfl] + rw [annotatedPiWhnfCoreDomainBetaCheap fuel] + +private theorem annotatedPiLazyDeltaStepDomain + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + ∃ m' : Std.HashSet (Expr × Expr), + TypeChecker.Inner.lazyDeltaReductionStep + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiSortOneInferOnlyState m) = + .ok (.bool true, + annotatedPiWithSuccessCache + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) m') := by + obtain ⟨m', hquick⟩ := annotatedPiQuickIsDefEqSortZeroAny + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) + refine ⟨m', ?_⟩ + unfold TypeChecker.Inner.lazyDeltaReductionStep + rw [normalizationRecMBind] + rw [normalizationRecMGetEnv] + simp only + rw [show annotatedPiCtorCandidateContext.toTypeChecker.env = + annotatedPiTypeKernelEnv by rfl] + rw [annotatedPiIsDeltaDomain, annotatedPiIsDeltaSortZero] + simp only + rw [normalizationRecMBind] + rw [annotatedPiTryUnfoldProjAppSortZero] + simp only + rw [normalizationRecMBind] + rw [annotatedPiDeltaDomain fuel] + simp only + rw [normalizationRecMBind] + rw [hquick] + rfl + +@[simp] private theorem annotatedPiIsDefEqOffsetDomain + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + TypeChecker.Inner.isDefEqOffset + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiSortOneInferOnlyState m) = + .ok (.undef, annotatedPiSortOneInferOnlyState m) := by + have hzero : + (annotatedPiRawDomainKernel == Expr.natZero) = false := by + rw [show annotatedPiRawDomainKernel = + .app (.const ``outParam [.succ .zero]) (.sort .zero) by rfl] + exact annotatedPiApp_beq_const _ _ _ _ + unfold TypeChecker.Inner.isDefEqOffset + simp [TypeChecker.Inner.isNatZero, TypeChecker.Inner.isNatSuccOf?, annotatedPiRawDomainKernel, + Expr.natZero] + +private theorem annotatedPiLazyDeltaLoopDomain + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + ∃ m' : Std.HashSet (Expr × Expr), + TypeChecker.Inner.lazyDeltaReduction.loop + annotatedPiRawDomainKernel (.sort .zero) 1000 + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiSortOneInferOnlyState m) = + .ok (.bool true, + annotatedPiWithSuccessCache + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) m') := by + obtain ⟨m', hstep⟩ := annotatedPiLazyDeltaStepDomain fuel m + refine ⟨m', ?_⟩ + rw [show 1000 = 999 + 1 by rfl] + unfold TypeChecker.Inner.lazyDeltaReduction.loop + rw [normalizationRecMBind] + rw [annotatedPiIsDefEqOffsetDomain fuel] + simp only + rw [show (LBool.undef != LBool.undef) = false by rfl] + simp only [Bool.false_eq_true, if_false] + rw [normalizationRecMBind] + rw [normalizationRecMReadContext] + simp only + rw [show + (!annotatedPiRawDomainKernel.hasFVar && + !(.sort .zero : Expr).hasFVar || + annotatedPiCtorCandidateContext.toTypeChecker.eagerReduce) = true + by + simp [Expr.hasFVar_eq, Expr.hasFVar', + annotatedPiRawDomainKernel]] + simp only [if_true] + rw [normalizationRecMBind] + rw [annotatedPiReduceNatDomain] + simp only + rw [normalizationRecMBind] + rw [normalizationReduceNatSort] + simp only + rw [normalizationRecMBind] + rw [normalizationRecMGetEnv] + simp only + rw [normalizationRecMBind] + rw [annotatedPiReduceNativeDomain] + simp only + rw [normalizationRecMBind] + rw [normalizationReduceNativeSort] + simp only + rw [normalizationRecMBind] + rw [hstep] + rfl + +private theorem annotatedPiLazyDeltaDomain + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + ∃ m' : Std.HashSet (Expr × Expr), + TypeChecker.Inner.lazyDeltaReduction + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiSortOneInferOnlyState m) = + .ok (.bool true, + annotatedPiWithSuccessCache + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) m') := by + obtain ⟨m', hloop⟩ := annotatedPiLazyDeltaLoopDomain fuel m + refine ⟨m', ?_⟩ + unfold TypeChecker.Inner.lazyDeltaReduction + rw [normalizationRecMBind] + rw [normalizationRecMReadContext] + simp only + change + TypeChecker.Inner.lazyDeltaReduction.loop + annotatedPiRawDomainKernel (.sort .zero) 1000 + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + (annotatedPiSortOneInferOnlyState m) = _ + exact hloop + +private theorem annotatedPiQuickIsDefEqDomainAny + (fuel : Nat) (m : Std.HashSet (Expr × Expr)) : + ∃ (r : LBool) (m' : Std.HashSet (Expr × Expr)), + TypeChecker.Inner.quickIsDefEq + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := m } : TypeChecker.State) = + .ok (r, ({ success := m' } : TypeChecker.State)) ∧ + (r = .true ∨ r = .undef) := + annotatedPiQuickIsDefEqDomainInitial _ _ m + +@[simp] private theorem annotatedPiWhnfCoreSortCheap + (fuel : Nat) (state : TypeChecker.State) : + TypeChecker.Inner.whnfCore (.sort .zero) true + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker state = + .ok (.sort .zero, state) := by + rfl + +private theorem annotatedPiIsDefEqCoreDomain + (fuel : Nat) (initial : Std.HashSet (Expr × Expr) := {}) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.isDefEqCore' + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (true, state) := by + obtain ⟨r, m, hquick, hr⟩ := annotatedPiQuickIsDefEqDomainInitial + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker initial + unfold TypeChecker.Inner.isDefEqCore' + rw [normalizationRecMBind] + rw [hquick] + rcases hr with htrue | hundef + · subst r + simp only + rw [show (LBool.true != LBool.undef) = true by rfl] + simp only [if_true] + exact ⟨({ success := m } : TypeChecker.State), rfl⟩ + · subst r + simp only + rw [show (LBool.undef != LBool.undef) = false by rfl] + simp only [Bool.false_eq_true, if_false] + rw [normalizationRecMBind] + rw [normalizationRecMReadContext] + simp only + rw [show ((.sort .zero : Expr).isConstOf ``true) = false by rfl] + simp only [Bool.and_false, Bool.false_eq_true, if_false] + rw [normalizationRecMBind] + rw [annotatedPiWhnfCoreDomainCheap fuel] + simp only + rw [normalizationRecMBind] + rw [annotatedPiWhnfCoreSortCheap fuel] + simp only + cases hptr : + (!(ptrEqExpr annotatedPiRawDomainKernel annotatedPiRawDomainKernel && + ptrEqExpr (.sort .zero) (.sort .zero))) + · simp only [Bool.false_eq_true, if_false] + rw [normalizationRecMBind] + rw [annotatedPiIsDefEqProofIrrelDomain fuel] + simp only + rw [show (LBool.undef != LBool.undef) = false by rfl] + simp only [Bool.false_eq_true, if_false] + rw [normalizationRecMBind] + obtain ⟨m'', hlazy⟩ := annotatedPiLazyDeltaDomain fuel m + rw [hlazy] + refine ⟨annotatedPiWithSuccessCache + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m)) m'', ?_⟩ + rfl + · simp only [if_true] + obtain ⟨r, m', hquick', hr⟩ := + annotatedPiQuickIsDefEqDomainAny fuel m + rw [normalizationRecMBind] + rw [hquick'] + simp only + rcases hr with htrue | hundef + · subst r + rw [show (LBool.true != LBool.undef) = true by rfl] + simp only [if_true] + refine ⟨({ success := m' } : TypeChecker.State), ?_⟩ + rfl + · subst r + rw [show (LBool.undef != LBool.undef) = false by rfl] + simp only [Bool.false_eq_true, if_false] + rw [normalizationRecMBind] + rw [annotatedPiIsDefEqProofIrrelDomain fuel] + simp only + rw [show (LBool.undef != LBool.undef) = false by rfl] + simp only [Bool.false_eq_true, if_false] + rw [normalizationRecMBind] + obtain ⟨m'', hlazy⟩ := annotatedPiLazyDeltaDomain fuel m' + rw [hlazy] + refine ⟨annotatedPiWithSuccessCache + (annotatedPiOutParamUnfoldState + (annotatedPiSortOneInferOnlyState m')) m'', ?_⟩ + rfl + +private theorem annotatedPiDomain_isDefEqInner + (fuel : Nat) (initial : Std.HashSet (Expr × Expr) := {}) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.isDefEq annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 4)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (true, state) := by + obtain ⟨state, hcore⟩ := annotatedPiIsDefEqCoreDomain fuel initial + have hcore' : + TypeChecker.Inner.isDefEqCore + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 4)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (true, state) := by + change + TypeChecker.Inner.isDefEqCore' + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel (fuel + 3)) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (true, state) + exact hcore + unfold TypeChecker.Inner.isDefEq + rw [show + (annotatedPiRawDomainKernel == (.sort .zero : Expr)) = false by + exact annotatedPiApp_beq_sort _ _ _] + simp only [Bool.false_eq_true, if_false, normalizationRecMBind] + rw [hcore'] + exact ⟨_, rfl⟩ + +private theorem annotatedPiDomain_isDefEqM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.isDefEq annotatedPiRawDomainKernel (.sort .zero)) = + .ok true := by + obtain ⟨state, hrun⟩ := annotatedPiDomain_isDefEqInner 9996 + change + Except.map (fun x : Bool × TypeChecker.State => x.1) + (TypeChecker.Inner.isDefEq + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok true + rw [show TypeChecker.Inner.isDefEq + annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = .ok (true, state) by + simpa only [Nat.reduceAdd] using hrun] + rfl + +private theorem annotatedPiInner_checkTypeM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType annotatedPiInnerKernel) = + .ok (.sort (.succ .zero)) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType annotatedPiInnerKernel false + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' annotatedPiInnerKernel false + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + unfold annotatedPiInnerKernel TypeChecker.Inner.inferType' + simp [annotatedPiRawDomainKernel, Expr.hasLooseBVars, Expr.looseBVarRange', + TypeChecker.Inner.inferType', TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [annotatedPiIsDefEqSort 9998] + simp [Expr.instantiate1', annotatedPiWithLocalDecl, annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + simp [Expr.sortLevel!, annotatedPi_mkLevelIMaxSuccZero] + rfl + +private theorem annotatedPiInner_whnfM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.whnf annotatedPiInnerKernel) = + .ok annotatedPiInnerKernel := by + rfl + +private theorem annotatedPiInner_isDefEqM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.isDefEq annotatedPiInnerKernel + annotatedPiInnerKernel) = .ok true := by + change + Except.map (fun x : Bool × TypeChecker.State => x.1) + (TypeChecker.Inner.isDefEq annotatedPiInnerKernel + annotatedPiInnerKernel (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = .ok true + unfold TypeChecker.Inner.isDefEq + rw [if_pos (Expr.eqv_refl _)] + rfl + +private theorem annotatedPiConst_checkTypeM (lctx : LocalContext) : + TypeChecker.M.run annotatedPiTypeKernelEnv .safe lctx [] + ({} : FuelConfig) + (TypeChecker.checkType (.const ``AnnotatedPi [])) = + .ok (.sort (.succ .zero)) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType (.const ``AnnotatedPi []) false + (TypeChecker.Methods.withFuel 10000) + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + rw [annotatedPiInferTypeFamily 9999 lctx + ({} : TypeChecker.State) Std.HashMap.getElem?_empty] + rfl + +private def annotatedPiNormalizationRawContext + (lctx : LocalContext) : TypeChecker.Context := + { env := annotatedPiTypeKernelEnv, lctx := lctx } + +private theorem unfoldAnnotatedPi (lctx methods state) : + TypeChecker.Inner.unfoldDefinition (.const ``AnnotatedPi []) + methods (annotatedPiNormalizationRawContext lctx) state = + .ok (none, state) := by + change + TypeChecker.Inner.unfoldDefinitionCore (.const ``AnnotatedPi []) + methods (annotatedPiNormalizationRawContext lctx) state = + .ok (none, state) + simp [TypeChecker.Inner.unfoldDefinitionCore, TypeChecker.Inner.isDelta, + Expr.getAppFn, annotatedPiNormalizationRawContext, + annotatedPiType_lookup_family, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind, annotatedPiInfo, ConstantInfo.deltaValue?] + +private theorem whnfLoopAnnotatedPi (lctx methods state n) : + TypeChecker.Inner.whnf'.loop (.const ``AnnotatedPi []) (n + 1) + methods (annotatedPiNormalizationRawContext lctx) state = + .ok (.const ``AnnotatedPi [], state) := by + unfold TypeChecker.Inner.whnf'.loop + simp [unfoldAnnotatedPi] + +private theorem annotatedPiConst_whnfM (lctx : LocalContext) : + TypeChecker.M.run annotatedPiTypeKernelEnv .safe lctx [] + ({} : FuelConfig) + (TypeChecker.whnf (.const ``AnnotatedPi [])) = + .ok (.const ``AnnotatedPi []) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.whnf' (.const ``AnnotatedPi []) + (TypeChecker.Methods.withFuel 9999) + (annotatedPiNormalizationRawContext lctx) + ({} : TypeChecker.State)) = + .ok (.const ``AnnotatedPi []) + unfold TypeChecker.Inner.whnf' + simp + rw [show + (if (annotatedPiNormalizationRawContext lctx).eagerReduce then + (annotatedPiNormalizationRawContext lctx).fuel.whnfEager + else (annotatedPiNormalizationRawContext lctx).fuel.whnf) = + 100000 by rfl] + rw [show 100000 = 99999 + 1 by rfl] + rw [whnfLoopAnnotatedPi] + simp [Functor.map, StateT.map, Except.map] + +private def annotatedPiFamilyCandidateStep : + AddInductive.CandidateWhnfStep where + context := annotatedPiFamilyCandidateContext + source := annotatedPiInfo.type + result := annotatedPiInfo.type + +private theorem annotatedPiFamilyCandidateStep_valid : + annotatedPiFamilyCandidateStep.Valid := by + exact annotatedPiFamily_whnfM + +private def annotatedPiFamilyCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := annotatedPiFamilyCandidateContext + source := annotatedPiInfo.type + inferred := .sort (.succ (.succ .zero)) + +private theorem annotatedPiFamilyCheckTypeStep_valid : + annotatedPiFamilyCheckTypeStep.Valid := by + exact annotatedPiFamily_checkTypeM + +private def annotatedPiCtorCandidateStep : + AddInductive.CandidateWhnfStep where + context := annotatedPiCtorCandidateContext + source := annotatedPiMkInfo.type + result := annotatedPiMkInfo.type + +private theorem annotatedPiCtorCandidateStep_valid : + annotatedPiCtorCandidateStep.Valid := by + exact annotatedPiCtor_whnfM + +private def annotatedPiCtorCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := annotatedPiCtorCandidateContext + source := annotatedPiMkInfo.type + inferred := .sort (.succ .zero) + +private theorem annotatedPiCtorCheckTypeStep_valid : + annotatedPiCtorCheckTypeStep.Valid := by + exact annotatedPiCtor_checkTypeM + +private def annotatedPiInnerCandidateStep : + AddInductive.CandidateWhnfStep where + context := annotatedPiCtorCandidateContext + source := annotatedPiInnerKernel + result := annotatedPiInnerKernel + +private theorem annotatedPiInnerCandidateStep_valid : + annotatedPiInnerCandidateStep.Valid := by + exact annotatedPiInner_whnfM + +private def annotatedPiInnerCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := annotatedPiCtorCandidateContext + source := annotatedPiInnerKernel + inferred := .sort (.succ .zero) + +private theorem annotatedPiInnerCheckTypeStep_valid : + annotatedPiInnerCheckTypeStep.Valid := by + exact annotatedPiInner_checkTypeM + +private def annotatedPiDomainCandidateStep : + AddInductive.CandidateWhnfStep where + context := annotatedPiCtorCandidateContext + source := annotatedPiRawDomainKernel + result := .sort .zero + +private theorem annotatedPiDomainCandidateStep_valid : + annotatedPiDomainCandidateStep.Valid := by + exact annotatedPiDomain_whnfM + +private def annotatedPiDomainCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := annotatedPiCtorCandidateContext + source := annotatedPiRawDomainKernel + inferred := .sort (.succ .zero) + +private theorem annotatedPiDomainCheckTypeStep_valid : + annotatedPiDomainCheckTypeStep.Valid := by + exact annotatedPiDomain_checkTypeM + +private def annotatedPiDomainAnnotations : + AddInductive.CandidateTypeAnnotations + annotatedPiRawDomainKernel where + consumed := .sort .zero + trace := .outParam [.succ .zero] (.sort .zero) (.identity _) + +private theorem annotatedPiDomainAnnotationsEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨annotatedPiCtorCandidateContext, + annotatedPiRawDomainKernel, + annotatedPiDomainAnnotations.consumed⟩ := by + exact annotatedPiDomain_isDefEqM + +private def annotatedPiInnerAnnotations : + AddInductive.CandidateTypeAnnotations annotatedPiInnerKernel where + consumed := annotatedPiInnerKernel + trace := .identity _ + +private theorem annotatedPiInnerAnnotationsEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨annotatedPiCtorCandidateContext, annotatedPiInnerKernel, + annotatedPiInnerAnnotations.consumed⟩ := by + exact annotatedPiInner_isDefEqM + +private def annotatedPiInnerBodyCandidateContext : + AddInductive.Context := + annotatedPiCtorCandidateContext.pushLocalDecl + `p .default annotatedPiDomainAnnotations.consumed + +private def annotatedPiOuterBodyCandidateContext : + AddInductive.Context := + annotatedPiCtorCandidateContext.pushLocalDecl + annotatedPiOuterName .default annotatedPiInnerAnnotations.consumed + +@[simp] private theorem addInductiveWithReader_apply + {alpha : Type} (f : AddInductive.Context → AddInductive.Context) + (x : AddInductive.M alpha) (context : AddInductive.Context) : + (withReader f x) context = x (f context) := rfl + +@[simp] private theorem addInductiveWithLocalReader_apply + {alpha : Type} (f : LocalContext → LocalContext) + (x : AddInductive.M alpha) (context : AddInductive.Context) : + (MonadWithReaderOf.withReader (m := AddInductive.M) f x) context = + x { context with lctx := f context.lctx } := rfl + +private theorem annotatedPiCtorCandidateFresh : + annotatedPiCtorCandidateContext.lctx.find? + annotatedPiCtorCandidateContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := annotatedPiCtorCandidateContext.freshFVarId) + LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty, + decls := PersistentArray.empty, + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + annotatedPiCtorCandidateContext.freshFVarId = none + rw [h] + simp [LocalContext.toList] + +@[simp] private theorem annotatedPiConst_instantiate1 (arg : Expr) : + (Expr.const ``AnnotatedPi []).instantiate1 arg = + .const ``AnnotatedPi [] := by + simp [Expr.instantiate1_eq, Expr.instantiate1'] + +@[simp] private theorem annotatedPiConst_instantiate1' (arg : Expr) : + (Expr.const ``AnnotatedPi []).instantiate1' arg = + .const ``AnnotatedPi [] := by + rfl + +private def annotatedPiInnerBodyCandidateStep : + AddInductive.CandidateWhnfStep where + context := annotatedPiInnerBodyCandidateContext + source := .const ``AnnotatedPi [] + result := .const ``AnnotatedPi [] + +private theorem annotatedPiInnerBodyCandidateStep_valid : + annotatedPiInnerBodyCandidateStep.Valid := by + exact annotatedPiConst_whnfM _ + +private def annotatedPiInnerBodyCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := annotatedPiInnerBodyCandidateContext + source := .const ``AnnotatedPi [] + inferred := .sort (.succ .zero) + +private theorem annotatedPiInnerBodyCheckTypeStep_valid : + annotatedPiInnerBodyCheckTypeStep.Valid := by + exact annotatedPiConst_checkTypeM _ + +private def annotatedPiOuterBodyCandidateStep : + AddInductive.CandidateWhnfStep where + context := annotatedPiOuterBodyCandidateContext + source := .const ``AnnotatedPi [] + result := .const ``AnnotatedPi [] + +private theorem annotatedPiOuterBodyCandidateStep_valid : + annotatedPiOuterBodyCandidateStep.Valid := by + exact annotatedPiConst_whnfM _ + +private def annotatedPiOuterBodyCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := annotatedPiOuterBodyCandidateContext + source := .const ``AnnotatedPi [] + inferred := .sort (.succ .zero) + +private theorem annotatedPiOuterBodyCheckTypeStep_valid : + annotatedPiOuterBodyCheckTypeStep.Valid := by + exact annotatedPiConst_checkTypeM _ + +private def annotatedPiDomainCandidateTrace : + AddInductive.CandidateExprTrace annotatedPiCtorCandidateContext + annotatedPiRawDomainKernel := + .terminal annotatedPiCtorCandidateContext + annotatedPiRawDomainKernel (.sort (.succ .zero)) (.sort .zero) + annotatedPiDomainCheckTypeStep_valid + annotatedPiDomainCandidateStep_valid + +private def annotatedPiInnerBodyCandidateTrace : + AddInductive.CandidateExprTrace annotatedPiInnerBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) := + .terminal annotatedPiInnerBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) + (.const ``AnnotatedPi []) + (by simpa only [annotatedPiInnerBodyCheckTypeStep, + annotatedPiConst_instantiate1] using + annotatedPiInnerBodyCheckTypeStep_valid) + (by simpa only [annotatedPiInnerBodyCandidateStep, + annotatedPiConst_instantiate1] using + annotatedPiInnerBodyCandidateStep_valid) + +private def annotatedPiOuterBodyCandidateTrace : + AddInductive.CandidateExprTrace annotatedPiOuterBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) := + .terminal annotatedPiOuterBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) + (.const ``AnnotatedPi []) + (by simpa only [annotatedPiOuterBodyCheckTypeStep, + annotatedPiConst_instantiate1] using + annotatedPiOuterBodyCheckTypeStep_valid) + (by simpa only [annotatedPiOuterBodyCandidateStep, + annotatedPiConst_instantiate1] using + annotatedPiOuterBodyCandidateStep_valid) + +private def annotatedPiInnerCandidateTrace : + AddInductive.CandidateExprTrace annotatedPiCtorCandidateContext + annotatedPiInnerKernel := + .forallE annotatedPiCtorCandidateContext annotatedPiInnerKernel + (.sort (.succ .zero)) `p annotatedPiRawDomainKernel + (.const ``AnnotatedPi []) .default annotatedPiCtorCandidateFresh + annotatedPiDomainAnnotations annotatedPiDomainAnnotationsEq + annotatedPiInnerCheckTypeStep_valid + annotatedPiInnerCandidateStep_valid + annotatedPiDomainCandidateTrace annotatedPiInnerBodyCandidateTrace + +private def annotatedPiCtorCandidateTrace : + AddInductive.CandidateExprTrace annotatedPiCtorCandidateContext + annotatedPiMkInfo.type := + .forallE annotatedPiCtorCandidateContext annotatedPiMkInfo.type + (.sort (.succ .zero)) annotatedPiOuterName annotatedPiInnerKernel + (.const ``AnnotatedPi []) .default annotatedPiCtorCandidateFresh + annotatedPiInnerAnnotations annotatedPiInnerAnnotationsEq + annotatedPiCtorCheckTypeStep_valid annotatedPiCtorCandidateStep_valid + annotatedPiInnerCandidateTrace annotatedPiOuterBodyCandidateTrace + +private def annotatedPiFamilyCandidate : + AddInductive.CandidateExpr annotatedPiInfo.type := + ⟨annotatedPiFamilyCandidateContext, + .terminal annotatedPiFamilyCandidateContext annotatedPiInfo.type + (.sort (.succ (.succ .zero))) annotatedPiInfo.type + annotatedPiFamilyCheckTypeStep_valid + annotatedPiFamilyCandidateStep_valid⟩ + +private def annotatedPiCtorCandidate : + AddInductive.CandidateExpr annotatedPiMkInfo.type := + ⟨annotatedPiCtorCandidateContext, annotatedPiCtorCandidateTrace⟩ + +private def annotatedPiConstructorCandidate : + AddInductive.CandidateConstructor annotatedPiKernelCtor := + ⟨annotatedPiCtorCandidate⟩ + +private def annotatedPiFamilyListCandidate : + AddInductive.CandidateFamily annotatedPiKernelType where + familyType := ⟨annotatedPiFamilyCandidate⟩ + constructors := .cons annotatedPiConstructorCandidate .nil + +private def annotatedPiNormalizationCandidate : + AddInductive.NormalizationCandidate [annotatedPiKernelType] where + families := .cons annotatedPiFamilyListCandidate .nil + +private def annotatedPiInductiveStats : AddInductive.InductiveStats where + levels := [] + resultLevel := .succ .zero + nindices := #[0] + indConsts := #[.const ``AnnotatedPi []] + params := #[] + isNotZero := true + +private theorem annotatedPiSortOne_data_hasExprMVar_false : + (Expr.sort (.succ .zero)).data.hasExprMVar = false := by + change (Expr.sort (.succ .zero)).hasExprMVar = false + rw [Expr.hasExprMVar_eq] + rfl + +private theorem annotatedPiSortOne_data_hasLevelMVar_false : + (Expr.sort (.succ .zero)).data.hasLevelMVar = false := by + change (Expr.sort (.succ .zero)).hasLevelMVar = false + rw [Expr.hasLevelMVar_eq] + simp [Expr.hasLevelMVar', Level.hasMVar_eq, Level.hasMVar'] + +private theorem annotatedPiSortOne_data_hasFVar_false : + (Expr.sort (.succ .zero)).data.hasFVar = false := by + change (Expr.sort (.succ .zero)).hasFVar = false + rw [Expr.hasFVar_eq] + rfl + +private theorem annotatedPi_checkInductiveTypes + (k : AddInductive.InductiveStats → AddInductive.M α) : + AddInductive.checkInductiveTypes 0 #[annotatedPiKernelType] k + annotatedPiFamilyCandidateContext = + k annotatedPiInductiveStats annotatedPiFamilyCandidateContext := by + apply AddInductive.checkInductiveTypes_singleton_zero_of_whnf_sort + · decide + · simp [Kernel.Environment.checkNoMVarNoFVar, + Kernel.Environment.checkNoMVar, Kernel.Environment.checkNoFVar, + annotatedPiKernelType, annotatedPiInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, Expr.hasMVar, Expr.hasFVar, + annotatedPiSortOne_data_hasExprMVar_false, + annotatedPiSortOne_data_hasLevelMVar_false, + annotatedPiSortOne_data_hasFVar_false, + Bind.bind, Except.bind, Pure.pure, Except.pure] + · simpa [annotatedPiFamilyCandidateContext, + annotatedPiKernelType] using annotatedPiFamily_checkTypeM + · simpa [annotatedPiFamilyCandidateContext, + annotatedPiKernelType, annotatedPiInfo, ConstantInfo.type, + ConstantInfo.toConstantVal] using annotatedPiFamily_whnfM + · rfl + +private theorem annotatedPiFamilyEnv_not_contains : + outParamKernelEnv.contains ``AnnotatedPi = false := by + unfold Kernel.Environment.contains + change outParamMap.contains ``AnnotatedPi = false + rw [SMap.find?_isSome, annotatedPiType_fresh] + rfl + +private theorem annotatedPiFamilyEnv_checkName : + outParamKernelEnv.checkName ``AnnotatedPi false = .ok () := by + simp [Kernel.Environment.checkName, annotatedPiFamilyEnv_not_contains, + Kernel.Environment.primitives, NameSet.ofList, NameSet.contains, Pure.pure, Except.pure] + +private theorem annotatedPiInner_hasIndOcc : + AddInductive.hasIndOcc #[.const ``AnnotatedPi []] + annotatedPiInnerKernel = true := by + simp [AddInductive.hasIndOcc, annotatedPiInnerKernel, + annotatedPiRawDomainKernel, Expr.constName!] + +private theorem annotatedPi_declareInductiveTypes : + AddInductive.declareInductiveTypes annotatedPiInductiveStats 0 + #[annotatedPiKernelType] 0 false annotatedPiFamilyCandidateContext = + .ok annotatedPiTypeKernelEnv := by + simp [AddInductive.declareInductiveTypes, annotatedPiInductiveStats, + annotatedPiKernelType, annotatedPiKernelCtor, + annotatedPiInfo, annotatedPiMkInfo, ConstantInfo.name, + ConstantInfo.type, ConstantInfo.toConstantVal, + annotatedPiFamilyCandidateContext, annotatedPiTypeKernelEnv, + outParamKernelEnv, annotatedPiTypeMap, + AddInductive.isRec, AddInductive.isRec.loop, + AddInductive.isReflexive, AddInductive.isReflexive.loop, + AddInductive.hasIndOcc, Expr.constName!, + Bind.bind, Pure.pure, Except.bind, Except.pure] + rw [show (Kernel.Environment.ofConstants `_annotatedPiCandidate + outParamMap).checkName ``AnnotatedPi = .ok () by + simpa [outParamKernelEnv] using annotatedPiFamilyEnv_checkName] + rfl + +private theorem annotatedPiCtor_data_hasExprMVar_false : + annotatedPiMkInfo.type.data.hasExprMVar = false := by + change annotatedPiMkInfo.type.hasExprMVar = false + rw [Expr.hasExprMVar_eq] + rfl + +private theorem annotatedPiCtor_data_hasLevelMVar_false : + annotatedPiMkInfo.type.data.hasLevelMVar = false := by + change annotatedPiMkInfo.type.hasLevelMVar = false + rw [Expr.hasLevelMVar_eq] + simp [annotatedPiMkInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, Expr.hasLevelMVar', + Level.hasMVar_eq, Level.hasMVar'] + +private theorem annotatedPiCtor_data_hasFVar_false : + annotatedPiMkInfo.type.data.hasFVar = false := by + change annotatedPiMkInfo.type.hasFVar = false + rw [Expr.hasFVar_eq] + rfl + +private theorem annotatedPiCtor_noMVarNoFVar : + annotatedPiTypeKernelEnv.checkNoMVarNoFVar + annotatedPiMkInfo.name annotatedPiMkInfo.type = .ok () := by + simp [Kernel.Environment.checkNoMVarNoFVar, + Kernel.Environment.checkNoMVar, Kernel.Environment.checkNoFVar, + Expr.hasMVar, Expr.hasFVar, + annotatedPiCtor_data_hasExprMVar_false, + annotatedPiCtor_data_hasLevelMVar_false, + annotatedPiCtor_data_hasFVar_false, + Bind.bind, Except.bind, Pure.pure, Except.pure] + +@[simp] private theorem annotatedPiInferConstantFamilyOnly + (lctx : LocalContext) : + TypeChecker.Inner.inferConstant + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + ``AnnotatedPi [] true = + .ok (.sort (.succ .zero)) := by + unfold TypeChecker.Inner.inferConstant + rw [show annotatedPiTypeKernelEnv.get ``AnnotatedPi = + .ok annotatedPiInfo by exact annotatedPiType_get_family] + simp [annotatedPiInfo, Bind.bind, Except.bind, + annotatedPiExceptPure, ConstantInfo.levelParams, + ConstantInfo.instantiateTypeLevelParams, + ConstantInfo.toConstantVal, + ConstantVal.instantiateTypeLevelParams, + Expr.instantiateLevelParams_eq, + Expr.instantiateLevelParamsCore_id] + +private theorem annotatedPiInferTypeFamilyOnly + (n : Nat) (lctx : LocalContext) (state : TypeChecker.State) + (hcache : + state.inferTypeI[(.const ``AnnotatedPi [] : Expr)]? = none) : + TypeChecker.Inner.inferType (.const ``AnnotatedPi []) true + (TypeChecker.Methods.withFuel (n + 1)) + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + state = + .ok (.sort (.succ .zero), + { state with + inferTypeI := state.inferTypeI.insert + (.const ``AnnotatedPi []) (.sort (.succ .zero)) }) := by + change + TypeChecker.Inner.inferType' (.const ``AnnotatedPi []) true + (TypeChecker.Methods.withFuel n) + ({ env := annotatedPiTypeKernelEnv, lctx := lctx } : + TypeChecker.Context) + state = _ + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', hcache, + annotatedPiInferConstantFamilyOnly, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private def annotatedPiInnerInferOnlyLCtx : LocalContext := + ({} : LocalContext).mkLocalDecl + ⟨({} : TypeChecker.State).ngen.curr⟩ `p + annotatedPiRawDomainKernel .default + +private def annotatedPiInnerInferOnlyState : TypeChecker.State := + { annotatedPiDomainInferOnlyState {} with + ngen := ({} : TypeChecker.State).ngen.next } + +private def annotatedPiFamilyInferOnlyState : TypeChecker.State := + { annotatedPiInnerInferOnlyState with + inferTypeI := annotatedPiInnerInferOnlyState.inferTypeI.insert + (.const ``AnnotatedPi []) (.sort (.succ .zero)) } + +@[simp] private theorem annotatedPiInnerInferOnlyState_family_miss : + annotatedPiInnerInferOnlyState.inferTypeI[ + (.const ``AnnotatedPi [] : Expr)]? = none := by + simp [annotatedPiInnerInferOnlyState, + annotatedPiDomainInferOnlyState, annotatedPiRawDomainKernel, + annotatedPiOutParamFnType] + +@[simp] private theorem annotatedPiInferTypeFamilyAfterDomainOnly : + TypeChecker.Inner.inferType' (.const ``AnnotatedPi []) true + (TypeChecker.Methods.withFuel 9998) + ({ env := annotatedPiTypeKernelEnv, lctx := + annotatedPiInnerInferOnlyLCtx } : + TypeChecker.Context) + annotatedPiInnerInferOnlyState = + .ok (.sort (.succ .zero), annotatedPiFamilyInferOnlyState) := by + change + TypeChecker.Inner.inferType (.const ``AnnotatedPi []) true + (TypeChecker.Methods.withFuel 9999) + ({ env := annotatedPiTypeKernelEnv, lctx := + annotatedPiInnerInferOnlyLCtx } : + TypeChecker.Context) + annotatedPiInnerInferOnlyState = _ + simpa [annotatedPiFamilyInferOnlyState] using + annotatedPiInferTypeFamilyOnly 9998 annotatedPiInnerInferOnlyLCtx + annotatedPiInnerInferOnlyState + annotatedPiInnerInferOnlyState_family_miss + +private theorem annotatedPiInferTypeFamilyAfterDomainOnly_exact : + TypeChecker.Inner.inferType (.const ``AnnotatedPi []) true + (TypeChecker.Methods.withFuel 9999) + { annotatedPiCtorCandidateContext.toTypeChecker with + lctx := annotatedPiCtorCandidateContext.toTypeChecker.lctx.mkLocalDecl + ⟨(annotatedPiDomainInferOnlyState {}).ngen.curr⟩ `p + annotatedPiRawDomainKernel .default } + { annotatedPiDomainInferOnlyState {} with + ngen := (annotatedPiDomainInferOnlyState {}).ngen.next } = + .ok (.sort (.succ .zero), annotatedPiFamilyInferOnlyState) := by + simpa [annotatedPiInnerInferOnlyLCtx, + annotatedPiInnerInferOnlyState, annotatedPiCtorCandidateContext, + annotatedPiDomainInferOnlyState, + AddInductive.Context.toTypeChecker] using + annotatedPiInferTypeFamilyAfterDomainOnly + +private theorem annotatedPiInferTypeFamilyAfterDomainOnly_literal : + TypeChecker.Inner.inferType (.const ``AnnotatedPi []) true + (TypeChecker.Methods.withFuel 9999) + { env := annotatedPiCtorCandidateContext.toTypeChecker.env + lctx := annotatedPiCtorCandidateContext.toTypeChecker.lctx.mkLocalDecl + { name := (annotatedPiDomainInferOnlyState {}).ngen.curr } `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + .default + safety := annotatedPiCtorCandidateContext.toTypeChecker.safety + eagerReduce := + annotatedPiCtorCandidateContext.toTypeChecker.eagerReduce + lparams := annotatedPiCtorCandidateContext.toTypeChecker.lparams + fuel := annotatedPiCtorCandidateContext.toTypeChecker.fuel } + { ngen := (annotatedPiDomainInferOnlyState {}).ngen.next + inferTypeI := (annotatedPiDomainInferOnlyState {}).inferTypeI + inferTypeC := (annotatedPiDomainInferOnlyState {}).inferTypeC + whnfCoreCache := + (annotatedPiDomainInferOnlyState {}).whnfCoreCache + whnfCache := (annotatedPiDomainInferOnlyState {}).whnfCache + success := (annotatedPiDomainInferOnlyState {}).success + failure := (annotatedPiDomainInferOnlyState {}).failure + unfold := (annotatedPiDomainInferOnlyState {}).unfold } = + .ok (.sort (.succ .zero), annotatedPiFamilyInferOnlyState) := by + simpa [annotatedPiRawDomainKernel] using + annotatedPiInferTypeFamilyAfterDomainOnly_exact + +private def annotatedPiInnerInferOnlyFinalState : TypeChecker.State := + { annotatedPiFamilyInferOnlyState with + inferTypeI := annotatedPiFamilyInferOnlyState.inferTypeI.insert + annotatedPiInnerKernel (.sort (.succ .zero)) } + +set_option maxRecDepth 10000 in +private theorem annotatedPiInner_inferTypeInner : + TypeChecker.Inner.inferType annotatedPiInnerKernel true + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), + annotatedPiInnerInferOnlyFinalState) := by + change + TypeChecker.Inner.inferType' annotatedPiInnerKernel true + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = _ + unfold annotatedPiInnerKernel TypeChecker.Inner.inferType' + simp [annotatedPiRawDomainKernel, + Expr.hasLooseBVars, Expr.looseBVarRange', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [annotatedPiInferTypeDomainOnly998] + simp only [TypeChecker.Inner.ensureSortCore, Expr.isSort, ↓reduceIte, annotatedPiWithLocalDecl, + annotatedPiRecMPure, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [annotatedPiInferTypeFamilyAfterDomainOnly_literal] + simp [Expr.sortLevel!, annotatedPiInnerInferOnlyFinalState, + annotatedPiInnerKernel, annotatedPiRawDomainKernel] + +private theorem annotatedPiInner_inferTypeM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.inferType annotatedPiInnerKernel) = + .ok (.sort (.succ .zero)) := by + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType annotatedPiInnerKernel true + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + rw [annotatedPiInner_inferTypeInner] + rfl + +private theorem annotatedPiInner_ensureTypeM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.ensureType annotatedPiInnerKernel) = + .ok (.sort (.succ .zero)) := by + unfold TypeChecker.ensureType TypeChecker.inferType + TypeChecker.ensureSort TypeChecker.RecM.run TypeChecker.M.run + simp only [readThe, MonadReaderOf.read, ReaderT.read, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + Pure.pure, StateT.pure, Except.pure, StateT.run', + Functor.map, Except.map] + rw [show TypeChecker.Inner.inferType annotatedPiInnerKernel true + (TypeChecker.Methods.withFuel + annotatedPiCtorCandidateContext.fuel.recDepth) + { env := annotatedPiCtorCandidateContext.env + lctx := annotatedPiCtorCandidateContext.lctx + safety := annotatedPiCtorCandidateContext.safety + lparams := annotatedPiCtorCandidateContext.lparams + fuel := annotatedPiCtorCandidateContext.fuel } + ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), + annotatedPiInnerInferOnlyFinalState) by + simpa [annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker] using + annotatedPiInner_inferTypeInner] + rfl + +private theorem annotatedPiCtor_getEnvM : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel TypeChecker.getEnv = + .ok annotatedPiTypeKernelEnv := by + rfl + +private theorem annotatedPiRawDomain_hasIndOcc_false : + AddInductive.hasIndOcc annotatedPiInductiveStats.indConsts + annotatedPiRawDomainKernel = false := by + simp [AddInductive.hasIndOcc, annotatedPiInductiveStats, + annotatedPiRawDomainKernel, Expr.constName!] + +private theorem annotatedPiConst_isValidIndAppIdx : + AddInductive.isValidIndAppIdx annotatedPiInductiveStats + (.const ``AnnotatedPi []) 0 = true := by + simp +decide [AddInductive.isValidIndAppIdx, + annotatedPiInductiveStats, Expr.getAppFn, Expr.getAppArgs, + Expr.getAppNumArgs] + +private theorem annotatedPiInner_stats_hasIndOcc : + AddInductive.hasIndOcc annotatedPiInductiveStats.indConsts + annotatedPiInnerKernel = true := by + simpa [annotatedPiInductiveStats] using annotatedPiInner_hasIndOcc + +private theorem annotatedPiConst_hasIndOcc : + AddInductive.hasIndOcc annotatedPiInductiveStats.indConsts + (.const ``AnnotatedPi []) = true := by + simp [AddInductive.hasIndOcc, annotatedPiInductiveStats, + Expr.constName!] + +private theorem annotatedPiConst_isValidIndApp : + AddInductive.isValidIndApp? annotatedPiInductiveStats + (.const ``AnnotatedPi []) = some 0 := by + exact AddInductive.isValidIndApp?_singleton_zero + annotatedPiInductiveStats (.const ``AnnotatedPi []) rfl + annotatedPiConst_isValidIndAppIdx + +private theorem annotatedPi_checkPositivity_terminal : + AddInductive.checkPositivity.loop annotatedPiInductiveStats + annotatedPiMkInfo.name 0 (.const ``AnnotatedPi []) 999 + annotatedPiInnerBodyCandidateContext = .ok () := by + rw [show 999 = 998 + 1 by rfl] + unfold AddInductive.checkPositivity.loop + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [show TypeChecker.M.run + annotatedPiInnerBodyCandidateContext.env + annotatedPiInnerBodyCandidateContext.safety + annotatedPiInnerBodyCandidateContext.lctx + annotatedPiInnerBodyCandidateContext.lparams + annotatedPiInnerBodyCandidateContext.fuel + (TypeChecker.whnf (.const ``AnnotatedPi [])) = + .ok (.const ``AnnotatedPi []) by + exact annotatedPiConst_whnfM _] + simp [annotatedPiConst_hasIndOcc, annotatedPiConst_isValidIndApp, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + +private theorem annotatedPi_checkPositivity : + AddInductive.checkPositivity annotatedPiInductiveStats + annotatedPiInnerKernel annotatedPiMkInfo.name 0 + annotatedPiCtorCandidateContext = .ok () := by + unfold AddInductive.checkPositivity + simp only [readThe, MonadReaderOf.read, ReaderT.read, ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show annotatedPiCtorCandidateContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkPositivity.loop + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [annotatedPiInner_whnfM] + simp only [Except.bind] + rw [show AddInductive.hasIndOcc annotatedPiInductiveStats.indConsts + annotatedPiInnerKernel = true by + exact annotatedPiInner_stats_hasIndOcc] + simp only [Bool.not_true, Bool.false_eq_true, if_false, Pure.pure] + unfold annotatedPiInnerKernel + simp only + rw [show AddInductive.hasIndOcc annotatedPiInductiveStats.indConsts + annotatedPiRawDomainKernel = false by + exact annotatedPiRawDomain_hasIndOcc_false] + simp only [Bool.false_eq_true, if_false] + simpa [withLocalDecl, annotatedPiInnerBodyCandidateContext, + withFreshId, MonadLocalNameGenerator.withFreshId, + MonadWithReader.withReader, withTheReader, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshExpr, AddInductive.Context.freshFVarId, + AddInductive.consumeTypeAnnotations, annotatedPiDomainAnnotations, + annotatedPiRawDomainKernel, annotatedPiCtorCandidateContext] using + annotatedPi_checkPositivity_terminal + +private theorem annotatedPiInner_ensureTypeM_expanded : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.ensureType + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default)) = + .ok (.sort (.succ .zero)) := by + simpa [annotatedPiInnerKernel, annotatedPiRawDomainKernel] using + annotatedPiInner_ensureTypeM + +private theorem annotatedPi_checkPositivity_expanded : + AddInductive.checkPositivity annotatedPiInductiveStats + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default) + ``AnnotatedPi.mk 0 annotatedPiCtorCandidateContext = .ok () := by + simpa [annotatedPiMkInfo, ConstantInfo.name, + ConstantInfo.toConstantVal, annotatedPiInnerKernel, + annotatedPiRawDomainKernel] using annotatedPi_checkPositivity + +private theorem annotatedPi_checkConstructors_terminal : + AddInductive.checkConstructorType.loop annotatedPiInductiveStats false 0 + ``AnnotatedPi.mk (.const ``AnnotatedPi []) 1 999 + annotatedPiOuterBodyCandidateContext = .ok () := by + rw [show 999 = 998 + 1 by rfl] + unfold AddInductive.checkConstructorType.loop + simp [annotatedPiConst_isValidIndAppIdx, + ReaderT.pure, Pure.pure, Except.pure] + +private theorem annotatedPi_checkConstructors_terminal_expanded : + AddInductive.checkConstructorType.loop annotatedPiInductiveStats false 0 + ``AnnotatedPi.mk (.const ``AnnotatedPi []) 1 999 + ({ env := annotatedPiTypeKernelEnv + lctx := ({} : LocalContext).mkLocalDecl + ⟨({ namePrefix := `_ind_fresh } : NameGenerator).curr⟩ + (.mkNum + (.mkStr + (.mkStr (.mkStr (.mkStr .anonymous "a") "_@") + "_internal") "_hyg") 0) + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default) + .default + lparams := [] + ngen := ({ namePrefix := `_ind_fresh } : NameGenerator).next + safety := .safe + allowPrimitive := false } : AddInductive.Context) = .ok () := by + simpa [annotatedPiOuterBodyCandidateContext, + AddInductive.Context.pushLocalDecl, + AddInductive.Context.freshFVarId, + annotatedPiInnerAnnotations, annotatedPiOuterName, + annotatedPiInnerKernel, annotatedPiRawDomainKernel, + annotatedPiCtorCandidateContext] using + annotatedPi_checkConstructors_terminal + +private theorem annotatedPiCtor_noMVarNoFVar_literal : + annotatedPiTypeKernelEnv.checkNoMVarNoFVar + ``AnnotatedPi.mk + (.forallE annotatedPiOuterName annotatedPiInnerKernel + (.const ``AnnotatedPi []) .default) = .ok () := by + simpa [annotatedPiMkInfo, ConstantInfo.name, ConstantInfo.type, + ConstantInfo.toConstantVal, annotatedPiInnerKernel, + annotatedPiRawDomainKernel, annotatedPiOuterName] using + annotatedPiCtor_noMVarNoFVar + +private theorem annotatedPiCtor_noMVarNoFVar_projected : + annotatedPiTypeKernelEnv.checkNoMVarNoFVar + annotatedPiMkInfo.toConstantVal.name annotatedPiMkInfo.type = + .ok () := by + simpa [ConstantInfo.name] using annotatedPiCtor_noMVarNoFVar + +private theorem annotatedPiCtor_checkTypeM_literal : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType + (.forallE annotatedPiOuterName annotatedPiInnerKernel + (.const ``AnnotatedPi []) .default)) = + .ok (.sort (.succ .zero)) := by + simpa [annotatedPiMkInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, annotatedPiInnerKernel, + annotatedPiRawDomainKernel, annotatedPiOuterName] using + annotatedPiCtor_checkTypeM + +private theorem annotatedPiCtor_noMVarNoFVar_expanded : + annotatedPiTypeKernelEnv.checkNoMVarNoFVar ``AnnotatedPi.mk + (.forallE + (.mkNum + (.mkStr + (.mkStr (.mkStr (.mkStr .anonymous "a") "_@") + "_internal") "_hyg") 0) + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default) + (.const ``AnnotatedPi []) .default) = .ok () := by + simpa [annotatedPiMkInfo, ConstantInfo.name, ConstantInfo.type, + ConstantInfo.toConstantVal, annotatedPiOuterName, + annotatedPiInnerKernel, annotatedPiRawDomainKernel] using + annotatedPiCtor_noMVarNoFVar + +private theorem annotatedPiCtor_checkTypeM_expanded : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType + (.forallE + (.mkNum + (.mkStr + (.mkStr (.mkStr (.mkStr .anonymous "a") "_@") + "_internal") "_hyg") 0) + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default) + (.const ``AnnotatedPi []) .default)) = + .ok (.sort (.succ .zero)) := by + simpa [annotatedPiMkInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, annotatedPiOuterName, + annotatedPiInnerKernel, annotatedPiRawDomainKernel] using + annotatedPiCtor_checkTypeM + +private theorem annotatedPiCtor_checkTypeM_empty : + TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety {} + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType + (.forallE + (.mkNum + (.mkStr + (.mkStr (.mkStr (.mkStr .anonymous "a") "_@") + "_internal") "_hyg") 0) + (.forallE `p + (.app (.const ``outParam [.succ .zero]) (.sort .zero)) + (.const ``AnnotatedPi []) .default) + (.const ``AnnotatedPi []) .default)) = + .ok (.sort (.succ .zero)) := by + simpa [annotatedPiCtorCandidateContext] using + annotatedPiCtor_checkTypeM_expanded + +private theorem annotatedPi_checkConstructors : + AddInductive.checkConstructors #[annotatedPiKernelType] + annotatedPiInductiveStats false + annotatedPiCtorCandidateContext = .ok () := by + unfold AddInductive.checkConstructors + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [annotatedPiCtor_getEnvM] + simp only [Except.bind] + unfold AddInductive.checkConstructorsLoop AddInductive.checkConstructorFold + simp +decide [annotatedPiKernelType, annotatedPiKernelCtor, annotatedPiMkInfo, ConstantInfo.name, + ConstantInfo.type, ConstantInfo.toConstantVal] + rw [annotatedPiCtor_noMVarNoFVar_expanded] + simp only [ReaderT.bind, Bind.bind, Except.bind] + rw [AddInductive.withEmptyLocalContext_apply] + rw [AddInductive.liftTypeChecker_apply] + simp only + rw [annotatedPiCtor_checkTypeM_empty] + simp only [] + unfold AddInductive.checkConstructorType + simp +decide [readThe, MonadReaderOf.read, ReaderT.read, ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show annotatedPiCtorCandidateContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkConstructorType.loop + simp only + rw [show annotatedPiInductiveStats.params[0]? = none by rfl] + simp only + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [annotatedPiInner_ensureTypeM_expanded] + simp only [Except.bind] + rw [if_pos (show AddInductive.levelStructGe + annotatedPiInductiveStats.resultLevel + (Expr.sort (.succ .zero)).sortLevel! = true from rfl)] + simp only [Bool.not_false, ↓reduceIte, ReaderT.bind, Bind.bind, Except.bind] + rw [annotatedPi_checkPositivity_expanded] + simp only [] + simp only [AddInductive.withLocalDecl_apply, annotatedPiConst_instantiate1, + AddInductive.Context.pushLocalDecl, AddInductive.Context.freshFVarId, + AddInductive.consumeTypeAnnotations, annotatedPiCtorCandidateContext] + rw [annotatedPi_checkConstructors_terminal_expanded] + unfold AddInductive.checkConstructorsLoop AddInductive.checkConstructorFold + simp [ReaderT.pure, Pure.pure, Except.pure] + +private theorem annotatedPi_checkConstructorUniverseSemantics : + AddInductive.checkConstructorUniverseListSemantics + annotatedPiInductiveStats annotatedPiKernelType.ctors + annotatedPiCtorCandidateContext = .ok () := by + unfold AddInductive.checkConstructorUniverseListSemantics + simp only [annotatedPiKernelType, annotatedPiKernelCtor, + annotatedPiMkInfo, ConstantInfo.type, ConstantInfo.toConstantVal, + ReaderT.bind, Bind.bind] + unfold AddInductive.checkConstructorUniverseSemantics + simp only [readThe, MonadReaderOf.read, ReaderT.read, ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show annotatedPiCtorCandidateContext.fuel.inductiveFuel = + 999 + 1 by rfl] + unfold AddInductive.checkConstructorUniverseSemantics.loop + simp only + rw [show annotatedPiInductiveStats.params[0]? = none by rfl] + simp only [ReaderT.bind, Bind.bind, AddInductive.liftTypeChecker_apply] + rw [annotatedPiInner_ensureTypeM_expanded] + simp only [Except.bind] + simp [Expr.sortLevel!, AddInductive.constructorUniverseSemanticGe] + simp only [AddInductive.consumeTypeAnnotations, annotatedPiCtorCandidateContext] + unfold AddInductive.checkConstructorUniverseSemantics.loop + rfl + +private theorem annotatedPiSortAnnotationTrace_build : + AddInductive.CandidateTypeAnnotationTrace.build (.sort .zero) = + ⟨.sort .zero, .identity _⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build] + +private theorem annotatedPiDomainAnnotationTrace_build : + AddInductive.CandidateTypeAnnotationTrace.build + annotatedPiRawDomainKernel = + ⟨.sort .zero, + .outParam [.succ .zero] (.sort .zero) (.identity _)⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build, + annotatedPiRawDomainKernel, annotatedPiSortAnnotationTrace_build] + rw [annotatedPiSortAnnotationTrace_build] + +private theorem annotatedPiInnerAnnotationTrace_build : + AddInductive.CandidateTypeAnnotationTrace.build + annotatedPiInnerKernel = + ⟨annotatedPiInnerKernel, .identity _⟩ := by + simp [AddInductive.CandidateTypeAnnotationTrace.build, + annotatedPiInnerKernel] + +private theorem annotatedPiDomainAnnotations_produced : + AddInductive.buildCandidateTypeAnnotations + annotatedPiRawDomainKernel = + .ok annotatedPiDomainAnnotations := by + unfold AddInductive.buildCandidateTypeAnnotations + rw [annotatedPiDomainAnnotationTrace_build] + rfl + +private theorem annotatedPiInnerAnnotations_produced : + AddInductive.buildCandidateTypeAnnotations annotatedPiInnerKernel = + .ok annotatedPiInnerAnnotations := by + unfold AddInductive.buildCandidateTypeAnnotations + rw [annotatedPiInnerAnnotationTrace_build] + rfl + +private theorem annotatedPiDomainCandidateTrace_loop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop + annotatedPiCtorCandidateContext annotatedPiRawDomainKernel + (fuel + 1) = + .ok annotatedPiDomainCandidateTrace := by + simpa only [annotatedPiDomainCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + annotatedPiCtorCandidateContext annotatedPiRawDomainKernel + (.sort (.succ .zero)) (.sort .zero) fuel + annotatedPiDomainCheckTypeStep_valid + annotatedPiDomainCandidateStep_valid rfl + +private theorem annotatedPiInnerBodyCandidateTrace_loop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop + annotatedPiInnerBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (fuel + 1) = + .ok annotatedPiInnerBodyCandidateTrace := by + simpa only [annotatedPiInnerBodyCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + annotatedPiInnerBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) (.const ``AnnotatedPi []) fuel + (by simpa only [annotatedPiInnerBodyCheckTypeStep, + annotatedPiConst_instantiate1] using + annotatedPiInnerBodyCheckTypeStep_valid) + (by simpa only [annotatedPiInnerBodyCandidateStep, + annotatedPiConst_instantiate1] using + annotatedPiInnerBodyCandidateStep_valid) rfl + +private theorem annotatedPiOuterBodyCandidateTrace_loop (fuel : Nat) : + AddInductive.buildCandidateExpr.loop + annotatedPiOuterBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (fuel + 1) = + .ok annotatedPiOuterBodyCandidateTrace := by + simpa only [annotatedPiOuterBodyCandidateTrace] using + AddInductive.buildCandidateExpr_loop_of_whnf_nonForall + annotatedPiOuterBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) (.const ``AnnotatedPi []) fuel + (by simpa only [annotatedPiOuterBodyCheckTypeStep, + annotatedPiConst_instantiate1] using + annotatedPiOuterBodyCheckTypeStep_valid) + (by simpa only [annotatedPiOuterBodyCandidateStep, + annotatedPiConst_instantiate1] using + annotatedPiOuterBodyCandidateStep_valid) rfl + +private theorem annotatedPiInnerCandidateTrace_loop : + AddInductive.buildCandidateExpr.loop + annotatedPiCtorCandidateContext annotatedPiInnerKernel 999 = + .ok annotatedPiInnerCandidateTrace := by + rw [show 999 = 998 + 1 by rfl] + simpa only [annotatedPiInnerCandidateTrace, + annotatedPiInnerBodyCandidateContext] using + (AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := annotatedPiCtorCandidateContext) + (e := annotatedPiInnerKernel) + (inferred := .sort (.succ .zero)) + (fuel := 998) + (name := `p) + (domain := annotatedPiRawDomainKernel) + (body := .const ``AnnotatedPi []) + (binderInfo := .default) + (hfresh := annotatedPiCtorCandidateFresh) + (annotations := annotatedPiDomainAnnotations) + (hannotations := annotatedPiDomainAnnotations_produced) + (hannotationsEq := annotatedPiDomainAnnotationsEq) + (hcheck := annotatedPiInnerCheckTypeStep_valid) + (hrun := annotatedPiInnerCandidateStep_valid) + (domainCandidate := annotatedPiDomainCandidateTrace) + (bodyCandidate := annotatedPiInnerBodyCandidateTrace) + (hdomain := by + simpa using annotatedPiDomainCandidateTrace_loop 997) + (hbody := by + simpa [annotatedPiInnerBodyCandidateContext] using + annotatedPiInnerBodyCandidateTrace_loop 997)) + +private theorem annotatedPiCtorCandidateTrace_loop : + AddInductive.buildCandidateExpr.loop + annotatedPiCtorCandidateContext annotatedPiMkInfo.type + annotatedPiCtorCandidateContext.fuel.inductiveFuel = + .ok annotatedPiCtorCandidateTrace := by + change AddInductive.buildCandidateExpr.loop + annotatedPiCtorCandidateContext annotatedPiMkInfo.type + (999 + 1) = _ + simpa only [annotatedPiCtorCandidateTrace, + annotatedPiOuterBodyCandidateContext] using + (AddInductive.buildCandidateExpr_loop_of_whnf_forall + (context := annotatedPiCtorCandidateContext) + (e := annotatedPiMkInfo.type) + (inferred := .sort (.succ .zero)) + (fuel := 999) + (name := annotatedPiOuterName) + (domain := annotatedPiInnerKernel) + (body := .const ``AnnotatedPi []) + (binderInfo := .default) + (hfresh := annotatedPiCtorCandidateFresh) + (annotations := annotatedPiInnerAnnotations) + (hannotations := annotatedPiInnerAnnotations_produced) + (hannotationsEq := annotatedPiInnerAnnotationsEq) + (hcheck := annotatedPiCtorCheckTypeStep_valid) + (hrun := annotatedPiCtorCandidateStep_valid) + (domainCandidate := annotatedPiInnerCandidateTrace) + (bodyCandidate := annotatedPiOuterBodyCandidateTrace) + (hdomain := annotatedPiInnerCandidateTrace_loop) + (hbody := by + simpa [annotatedPiOuterBodyCandidateContext] using + annotatedPiOuterBodyCandidateTrace_loop 998)) + +/-- The executable candidate traversal returns the exact nested-forall +AnnotatedPi constructor trace, including both annotation boundaries and the +two recursively extended body contexts. -/ +theorem annotatedPiCtor_candidateTrace : + AddInductive.buildCandidateExpr annotatedPiMkInfo.type + annotatedPiCtorCandidateContext = + .ok annotatedPiCtorCandidate := by + unfold AddInductive.buildCandidateExpr + simp only [readThe, MonadReaderOf.read, ReaderT.read, + ReaderT.bind, Bind.bind, ReaderT.pure, Pure.pure, + Except.bind, Except.pure] + rw [annotatedPiCtorCandidateTrace_loop] + rfl + +/-- The family position is the exact terminal candidate returned in the +pre-family environment. -/ +theorem annotatedPiFamily_candidateTrace : + AddInductive.buildCandidateExpr annotatedPiInfo.type + annotatedPiFamilyCandidateContext = + .ok annotatedPiFamilyCandidate := by + apply AddInductive.buildCandidateExpr_of_whnf_nonForall + · decide + · rfl + +private theorem annotatedPiFamilyTypeListProduced : + AddInductive.CandidateFamilyTypeListProduced + annotatedPiFamilyCandidateContext + (.cons annotatedPiFamilyListCandidate.familyType .nil) := by + exact .cons (by + unfold AddInductive.normalizeCandidateFamilyType + simp only [ReaderT.bind, Bind.bind] + simp only [annotatedPiKernelType] + rw [annotatedPiFamily_candidateTrace] + rfl) .nil + +private theorem annotatedPiFamilyTypeList_candidateTrace : + AddInductive.normalizeCandidateFamilyTypeList + [annotatedPiKernelType] annotatedPiFamilyCandidateContext = + .ok (.cons annotatedPiFamilyListCandidate.familyType .nil) := by + exact annotatedPiFamilyTypeListProduced.normalize + +private theorem annotatedPiConstructorListProduced : + AddInductive.CandidateConstructorListProduced + annotatedPiCtorCandidateContext + annotatedPiFamilyListCandidate.constructors := by + exact .cons (by + unfold AddInductive.normalizeCandidateConstructor + simp only [ReaderT.bind, Bind.bind] + simp only [annotatedPiKernelCtor] + rw [annotatedPiCtor_candidateTrace] + rfl) .nil + +private theorem annotatedPiConstructorList_candidateTrace : + AddInductive.normalizeCandidateConstructorList + annotatedPiKernelType.ctors annotatedPiCtorCandidateContext = + .ok annotatedPiFamilyListCandidate.constructors := by + exact annotatedPiConstructorListProduced.normalize + +private theorem annotatedPiFamilyListProduced : + AddInductive.CandidateFamilyListProduced + annotatedPiCtorCandidateContext + (.cons annotatedPiFamilyListCandidate.familyType .nil) + annotatedPiNormalizationCandidate.families := by + exact .cons annotatedPiConstructorListProduced .nil + +private theorem annotatedPiFamilyList_candidateTrace : + AddInductive.normalizeCandidateFamilyList + (.cons annotatedPiFamilyListCandidate.familyType .nil) + annotatedPiCtorCandidateContext = + .ok annotatedPiNormalizationCandidate.families := by + exact annotatedPiFamilyListProduced.normalize + +/-- The complete positive AnnotatedPi metadata request selects the exact +nested-forall normalization candidate in the real pre-family and post-family +checker environments. -/ +theorem annotatedPiNormalizationCandidate_produced : + AddInductive.buildNormalizationCandidate 0 + [annotatedPiKernelType] 0 false + annotatedPiFamilyCandidateContext = + .ok annotatedPiNormalizationCandidate := by + unfold AddInductive.buildNormalizationCandidate + rw [annotatedPi_checkInductiveTypes] + simp only [ReaderT.bind, Bind.bind] + rw [show + (withReader (fun _ : AddInductive.Context => + { annotatedPiFamilyCandidateContext with lctx := {} }) + (AddInductive.normalizeCandidateFamilyTypeList + [annotatedPiKernelType])) annotatedPiFamilyCandidateContext = + .ok (.cons annotatedPiFamilyListCandidate.familyType .nil) by + change AddInductive.normalizeCandidateFamilyTypeList + [annotatedPiKernelType] + { annotatedPiFamilyCandidateContext with lctx := {} } = _ + rw [show { annotatedPiFamilyCandidateContext with lctx := {} } = + annotatedPiFamilyCandidateContext by rfl] + exact annotatedPiFamilyTypeList_candidateTrace] + simp only [Except.bind] + rw [annotatedPi_declareInductiveTypes] + unfold AddInductive.withEnv + change (ReaderT.bind + (AddInductive.checkConstructors #[annotatedPiKernelType] + annotatedPiInductiveStats false) + (fun _ => ReaderT.bind + (AddInductive.normalizeCandidateFamilyList + (.cons annotatedPiFamilyListCandidate.familyType .nil)) + (fun families => pure + (⟨families⟩ : AddInductive.NormalizationCandidate + [annotatedPiKernelType])))) + ({ annotatedPiFamilyCandidateContext with + env := annotatedPiTypeKernelEnv } : + AddInductive.Context) = _ + rw [show ({ annotatedPiFamilyCandidateContext with + env := annotatedPiTypeKernelEnv } : AddInductive.Context) = + annotatedPiCtorCandidateContext by rfl] + simp only [ReaderT.bind, Bind.bind] + rw [annotatedPi_checkConstructors] + simp only [Except.bind] + rw [annotatedPiFamilyList_candidateTrace] + rfl + +private def aliasFormerFamilyCandidateStep : + AddInductive.CandidateWhnfStep where + context := aliasFormerCandidateContext + source := aliasFormerInfo.type + result := .sort (.succ .zero) + +private theorem aliasFormerFamilyCandidateStep_valid : + aliasFormerFamilyCandidateStep.Valid := by + change + TypeChecker.M.run aliasFormerNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.whnf aliasFormerInfo.type) = + .ok (.sort (.succ .zero)) + exact aliasFormerFamily_whnfM + +private def aliasFormerFamilyCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := aliasFormerCandidateContext + source := aliasFormerInfo.type + inferred := .sort (.succ (.succ .zero)) + +private theorem aliasFormerFamilyCheckTypeStep_valid : + aliasFormerFamilyCheckTypeStep.Valid := by + change + TypeChecker.M.run aliasFormerNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.checkType aliasFormerInfo.type) = + .ok (.sort (.succ (.succ .zero))) + exact aliasFormerFamily_checkTypeM + +private def aliasFormerCtorCheckTypeStep : + AddInductive.CandidateCheckTypeStep where + context := aliasFormerCtorCandidateContext + source := aliasFormerMkInfo.type + inferred := .const ``TypeFamilyAlias [] + +private theorem aliasFormerCtorCheckTypeStep_valid : + aliasFormerCtorCheckTypeStep.Valid := by + change + TypeChecker.M.run aliasFormerCtorNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.checkType aliasFormerMkInfo.type) = + .ok (.const ``TypeFamilyAlias []) + exact aliasFormerCtor_checkTypeM + +private def aliasFormerCtorCandidateStep : + AddInductive.CandidateWhnfStep where + context := aliasFormerCtorCandidateContext + source := aliasFormerMkInfo.type + result := .const ``AliasFormer [] + +private theorem aliasFormerCtorCandidateStep_valid : + aliasFormerCtorCandidateStep.Valid := by + change + TypeChecker.M.run aliasFormerCtorNormalizationKernelEnv .safe {} [] + { whnf := 2 } (TypeChecker.whnf aliasFormerMkInfo.type) = + .ok (.const ``AliasFormer []) + exact aliasFormerCtor_whnfM + +private def aliasFormerFamilyCandidate : + AddInductive.CandidateExpr aliasFormerInfo.type := + ⟨aliasFormerCandidateContext, + .terminal aliasFormerCandidateContext aliasFormerInfo.type + (.sort (.succ (.succ .zero))) (.sort (.succ .zero)) + aliasFormerFamilyCheckTypeStep_valid + aliasFormerFamilyCandidateStep_valid⟩ + +private def aliasFormerCtorCandidate : + AddInductive.CandidateExpr aliasFormerMkInfo.type := + ⟨aliasFormerCtorCandidateContext, + .terminal aliasFormerCtorCandidateContext aliasFormerMkInfo.type + (.const ``TypeFamilyAlias []) (.const ``AliasFormer []) + aliasFormerCtorCheckTypeStep_valid + aliasFormerCtorCandidateStep_valid⟩ + +private def aliasFormerConstructorCandidate : + AddInductive.CandidateConstructor aliasFormerKernelCtor := + ⟨aliasFormerCtorCandidate⟩ + +private def aliasFormerFamilyListCandidate : + AddInductive.CandidateFamily aliasFormerKernelType where + familyType := ⟨aliasFormerFamilyCandidate⟩ + constructors := .cons aliasFormerConstructorCandidate .nil + +/-- Exact singleton family/constructor candidate list used to exercise the +generic positional Theory boundary. -/ +private def aliasFormerNormalizationCandidate : + AddInductive.NormalizationCandidate [aliasFormerKernelType] where + families := .cons aliasFormerFamilyListCandidate .nil + +private def aliasFormerInductiveStats : AddInductive.InductiveStats where + levels := [] + resultLevel := .succ .zero + nindices := #[0] + indConsts := #[.const ``AliasFormer []] + params := #[] + isNotZero := true + +private theorem constNil_data_hasExprMVar_false (n : Name) : + (Expr.const n []).data.hasExprMVar = false := by + change (Expr.const n []).hasExprMVar = false + rw [Expr.hasExprMVar_eq] + rfl + +private theorem constNil_data_hasLevelMVar_false (n : Name) : + (Expr.const n []).data.hasLevelMVar = false := by + change (Expr.const n []).hasLevelMVar = false + rw [Expr.hasLevelMVar_eq] + rfl + +private theorem constNil_data_hasFVar_false (n : Name) : + (Expr.const n []).data.hasFVar = false := by + change (Expr.const n []).hasFVar = false + rw [Expr.hasFVar_eq] + rfl + +private theorem aliasFormer_checkInductiveTypes + (k : AddInductive.InductiveStats → AddInductive.M α) : + AddInductive.checkInductiveTypes 0 #[aliasFormerKernelType] k + aliasFormerCandidateContext = + k aliasFormerInductiveStats aliasFormerCandidateContext := by + apply AddInductive.checkInductiveTypes_singleton_zero_of_whnf_sort + · decide + · simp [Kernel.Environment.checkNoMVarNoFVar, + Kernel.Environment.checkNoMVar, Kernel.Environment.checkNoFVar, + aliasFormerKernelType, aliasFormerInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, Expr.hasMVar, Expr.hasFVar, + constNil_data_hasExprMVar_false, + constNil_data_hasLevelMVar_false, constNil_data_hasFVar_false, + Bind.bind, Except.bind, + Pure.pure, Except.pure] + · simpa [aliasFormerCandidateContext, aliasFormerKernelType] using + aliasFormerFamily_checkTypeM + · simpa [aliasFormerCandidateContext, aliasFormerKernelType] using + aliasFormerFamily_whnfM + · rfl + +private theorem aliasFormerNormalization_not_contains : + aliasFormerNormalizationKernelEnv.contains ``AliasFormer = false := by + unfold Kernel.Environment.contains + change typeFamilyAliasMap.contains ``AliasFormer = false + rw [SMap.find?_isSome, aliasFormerType_fresh] + rfl + +private theorem aliasFormerNormalization_checkName : + aliasFormerNormalizationKernelEnv.checkName ``AliasFormer false = + .ok () := by + simp [Kernel.Environment.checkName, aliasFormerNormalization_not_contains, + Kernel.Environment.primitives, NameSet.ofList, NameSet.contains, Pure.pure, Except.pure] + +private theorem aliasFormer_declareInductiveTypes : + AddInductive.declareInductiveTypes aliasFormerInductiveStats 0 + #[aliasFormerKernelType] 0 false aliasFormerCandidateContext = + .ok aliasFormerCtorNormalizationKernelEnv := by + simp [AddInductive.declareInductiveTypes, aliasFormerInductiveStats, + aliasFormerKernelType, aliasFormerKernelCtor, + aliasFormerInfo, aliasFormerMkInfo, ConstantInfo.name, + ConstantInfo.type, ConstantInfo.toConstantVal, + aliasFormerCandidateContext, aliasFormerCtorNormalizationKernelEnv, + aliasFormerNormalizationKernelEnv, aliasFormerTypeMap, + AddInductive.isRec, + AddInductive.isRec.loop, AddInductive.isReflexive, + AddInductive.isReflexive.loop, + Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show (Kernel.Environment.ofConstants `_aliasFormerNormalization + typeFamilyAliasMap).checkName ``AliasFormer = .ok () by + simpa [aliasFormerNormalizationKernelEnv] using + aliasFormerNormalization_checkName] + rfl + +private theorem aliasFormerCtor_getEnvM : + TypeChecker.M.run aliasFormerCtorCandidateContext.env + aliasFormerCtorCandidateContext.safety + aliasFormerCtorCandidateContext.lctx + aliasFormerCtorCandidateContext.lparams + aliasFormerCtorCandidateContext.fuel TypeChecker.getEnv = + .ok aliasFormerCtorNormalizationKernelEnv := by + rfl + +private theorem aliasFormerCtor_isValidIndAppIdx : + AddInductive.isValidIndAppIdx aliasFormerInductiveStats + (.const ``AliasFormer []) 0 = true := by + simp +decide [AddInductive.isValidIndAppIdx, + aliasFormerInductiveStats, + Expr.getAppFn, Expr.getAppArgs, Expr.getAppNumArgs] + +private theorem aliasFormerCtor_noMVarNoFVar : + aliasFormerCtorNormalizationKernelEnv.checkNoMVarNoFVar + ``AliasFormer.mk (.const ``AliasFormer []) = .ok () := by + simp [Kernel.Environment.checkNoMVarNoFVar, + Kernel.Environment.checkNoMVar, Kernel.Environment.checkNoFVar, + Expr.hasMVar, Expr.hasFVar, + constNil_data_hasExprMVar_false, + constNil_data_hasLevelMVar_false, constNil_data_hasFVar_false, + Bind.bind, Except.bind, Pure.pure, Except.pure] + +private theorem aliasFormerCtor_checkTypeM_const : + TypeChecker.M.run aliasFormerCtorCandidateContext.env + aliasFormerCtorCandidateContext.safety + aliasFormerCtorCandidateContext.lctx + aliasFormerCtorCandidateContext.lparams + aliasFormerCtorCandidateContext.fuel + (TypeChecker.checkType (.const ``AliasFormer [])) = + .ok (.const ``TypeFamilyAlias []) := by + simpa [aliasFormerMkInfo, ConstantInfo.type, + ConstantInfo.toConstantVal, aliasFormerCtorCandidateContext] using + aliasFormerCtor_checkTypeM + +private theorem aliasFormerCtor_checkTypeM_empty : + TypeChecker.M.run aliasFormerCtorCandidateContext.env + aliasFormerCtorCandidateContext.safety {} + aliasFormerCtorCandidateContext.lparams + aliasFormerCtorCandidateContext.fuel + (TypeChecker.checkType (.const ``AliasFormer [])) = + .ok (.const ``TypeFamilyAlias []) := by + simpa [aliasFormerCtorCandidateContext] using + aliasFormerCtor_checkTypeM_const + +private theorem aliasFormerCtor_checkTypeM_of_empty + (lctx : LocalContext) (hlctx : lctx = {}) : + TypeChecker.M.run aliasFormerCtorCandidateContext.env + aliasFormerCtorCandidateContext.safety lctx + aliasFormerCtorCandidateContext.lparams + aliasFormerCtorCandidateContext.fuel + (TypeChecker.checkType (.const ``AliasFormer [])) = + .ok (.const ``TypeFamilyAlias []) := by + subst lctx + exact aliasFormerCtor_checkTypeM_empty + +private theorem aliasFormer_checkConstructors : + AddInductive.checkConstructors #[aliasFormerKernelType] + aliasFormerInductiveStats false aliasFormerCtorCandidateContext = + .ok () := by + unfold AddInductive.checkConstructors + simp only [ReaderT.bind, Bind.bind] + rw [AddInductive.liftTypeChecker_apply] + rw [aliasFormerCtor_getEnvM] + simp only [Except.bind] + unfold AddInductive.checkConstructorsLoop AddInductive.checkConstructorFold + simp +decide [aliasFormerKernelType, aliasFormerKernelCtor, aliasFormerMkInfo, ConstantInfo.name] + simp +decide [ConstantInfo.type, ConstantInfo.toConstantVal, AddInductive.liftTypeChecker_apply, + aliasFormerCtor_noMVarNoFVar, ReaderT.bind, Bind.bind, Except.bind] + rw [aliasFormerCtor_checkTypeM_of_empty + ({ decls := + { root := PersistentArrayNode.node #[], tail := #[] } } : + LocalContext) rfl] + simp only [] + unfold AddInductive.checkConstructorType + simp only [readThe, MonadReaderOf.read, ReaderT.read, ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show aliasFormerCtorCandidateContext.fuel.inductiveFuel = 999 + 1 by + rfl] + unfold AddInductive.checkConstructorType.loop + simp [aliasFormerCtor_isValidIndAppIdx, ReaderT.pure, Pure.pure, + Except.pure, AddInductive.checkConstructorFold, + AddInductive.checkConstructorsLoop] + +private theorem aliasFormer_checkConstructorUniverseSemantics : + AddInductive.checkConstructorUniverseListSemantics + aliasFormerInductiveStats aliasFormerKernelType.ctors + aliasFormerCtorCandidateContext = .ok () := by + unfold AddInductive.checkConstructorUniverseListSemantics + simp only [aliasFormerKernelType, aliasFormerKernelCtor, + aliasFormerMkInfo, ConstantInfo.type, ConstantInfo.toConstantVal, + ReaderT.bind, Bind.bind] + unfold AddInductive.checkConstructorUniverseSemantics + simp only [readThe, MonadReaderOf.read, ReaderT.read, ReaderT.bind, Bind.bind, Pure.pure, + Except.bind, Except.pure] + rw [show aliasFormerCtorCandidateContext.fuel.inductiveFuel = 999 + 1 by + rfl] + unfold AddInductive.checkConstructorUniverseSemantics.loop + rfl + +/-- The generic candidate traversal retains the exact context, input, and +result of the actual AliasFormer family WHNF observation. -/ +theorem aliasFormerFamily_candidateTrace : + AddInductive.buildCandidateExpr aliasFormerInfo.type + aliasFormerCandidateContext = + .ok aliasFormerFamilyCandidate := by + apply AddInductive.buildCandidateExpr_of_whnf_nonForall + · decide + · rfl + +private theorem aliasFormerFamilyTypeListProduced : + AddInductive.CandidateFamilyTypeListProduced aliasFormerCandidateContext + (.cons aliasFormerFamilyListCandidate.familyType .nil) := by + exact .cons (by + unfold AddInductive.normalizeCandidateFamilyType + simp only [ReaderT.bind, Bind.bind] + simp only [aliasFormerKernelType] + rw [aliasFormerFamily_candidateTrace] + rfl) .nil + +private theorem aliasFormerFamilyTypeList_candidateTrace : + AddInductive.normalizeCandidateFamilyTypeList + [aliasFormerKernelType] aliasFormerCandidateContext = + .ok (.cons aliasFormerFamilyListCandidate.familyType .nil) := by + exact aliasFormerFamilyTypeListProduced.normalize + +/-- The post-family constructor position is produced by the same executable +candidate traversal and retains its exact opaque result. -/ +theorem aliasFormerCtor_candidateTrace : + AddInductive.buildCandidateExpr aliasFormerMkInfo.type + aliasFormerCtorCandidateContext = + .ok aliasFormerCtorCandidate := by + apply AddInductive.buildCandidateExpr_of_whnf_nonForall + · decide + · rfl + +private theorem aliasFormerConstructorListProduced : + AddInductive.CandidateConstructorListProduced + aliasFormerCtorCandidateContext + aliasFormerFamilyListCandidate.constructors := by + exact .cons (by + unfold AddInductive.normalizeCandidateConstructor + simp only [ReaderT.bind, Bind.bind] + simp only [aliasFormerKernelCtor] + rw [aliasFormerCtor_candidateTrace] + rfl) .nil + +private theorem aliasFormerConstructorList_candidateTrace : + AddInductive.normalizeCandidateConstructorList + aliasFormerKernelType.ctors aliasFormerCtorCandidateContext = + .ok aliasFormerFamilyListCandidate.constructors := by + exact aliasFormerConstructorListProduced.normalize + +private theorem aliasFormerFamilyListProduced : + AddInductive.CandidateFamilyListProduced aliasFormerCtorCandidateContext + (.cons aliasFormerFamilyListCandidate.familyType .nil) + aliasFormerNormalizationCandidate.families := by + exact .cons aliasFormerConstructorListProduced .nil + +private theorem aliasFormerFamilyList_candidateTrace : + AddInductive.normalizeCandidateFamilyList + (.cons aliasFormerFamilyListCandidate.familyType .nil) + aliasFormerCtorCandidateContext = + .ok aliasFormerNormalizationCandidate.families := by + exact aliasFormerFamilyListProduced.normalize + +theorem aliasFormerNormalizationCandidate_produced : + AddInductive.buildNormalizationCandidate 0 + [aliasFormerKernelType] 0 false aliasFormerCandidateContext = + .ok aliasFormerNormalizationCandidate := by + unfold AddInductive.buildNormalizationCandidate + rw [aliasFormer_checkInductiveTypes] + simp only [ReaderT.bind, Bind.bind] + rw [show + (withReader (fun _ : AddInductive.Context => + { aliasFormerCandidateContext with lctx := {} }) + (AddInductive.normalizeCandidateFamilyTypeList + [aliasFormerKernelType])) aliasFormerCandidateContext = + .ok (.cons aliasFormerFamilyListCandidate.familyType .nil) by + change AddInductive.normalizeCandidateFamilyTypeList + [aliasFormerKernelType] + { aliasFormerCandidateContext with lctx := {} } = _ + rw [show { aliasFormerCandidateContext with lctx := {} } = + aliasFormerCandidateContext by rfl] + exact aliasFormerFamilyTypeList_candidateTrace] + simp only [Except.bind] + rw [aliasFormer_declareInductiveTypes] + unfold AddInductive.withEnv + change (ReaderT.bind + (AddInductive.checkConstructors #[aliasFormerKernelType] + aliasFormerInductiveStats false) + (fun _ => ReaderT.bind + (AddInductive.normalizeCandidateFamilyList + (.cons aliasFormerFamilyListCandidate.familyType .nil)) + (fun families => pure + (⟨families⟩ : AddInductive.NormalizationCandidate + [aliasFormerKernelType])))) + ({ aliasFormerCandidateContext with + env := aliasFormerCtorNormalizationKernelEnv } : + AddInductive.Context) = _ + rw [show ({ aliasFormerCandidateContext with + env := aliasFormerCtorNormalizationKernelEnv } : + AddInductive.Context) = aliasFormerCtorCandidateContext by rfl] + simp only [ReaderT.bind, Bind.bind] + rw [aliasFormer_checkConstructors] + simp only [Except.bind] + rw [aliasFormerFamilyList_candidateTrace] + rfl + +/-- Erasing the retained trace produces the expected AliasFormer analysis +view at the same checker boundary. -/ +theorem aliasFormerFamily_candidate : + AddInductive.normalizeCandidateExpr aliasFormerInfo.type + aliasFormerCandidateContext = + .ok (.sort (.succ .zero)) := by + apply AddInductive.normalizeCandidateExpr_of_whnf_nonForall + · decide + · simpa [aliasFormerCandidateContext] using + aliasFormerFamily_checkTypeM + · simpa [aliasFormerCandidateContext] using + aliasFormerFamily_whnfM + · rfl + +private def aliasRecFieldFnType : Expr := + .forallE `α (.sort (.succ .zero)) + (.sort (.succ .zero)) .default + +@[simp] private theorem aliasRecFieldFnType_isForall : + aliasRecFieldFnType.isForall = true := rfl + +@[simp] private theorem aliasRecFieldFnType_bindingDomain : + aliasRecFieldFnType.bindingDomain! = + .sort (.succ .zero) := rfl + +@[simp] private theorem aliasRecFieldFnType_instantiatedBody : + aliasRecFieldFnType.bindingBody!.instantiate1 + (.const ``AliasRec []) = + .sort (.succ .zero) := by + simp [aliasRecFieldFnType, Expr.bindingBody!, + Expr.instantiate1_eq, + Expr.instantiate1'] + +@[simp] private theorem aliasRecFamily_notEagerReduce : + (Expr.const ``AliasRec []).isAppOfArity ``eagerReduce 2 = + false := rfl + +private def aliasRecFieldFnState (state : TypeChecker.State) : + TypeChecker.State := + { state with + inferTypeC := state.inferTypeC.insert + (.const ``RecAlias [.succ .zero]) aliasRecFieldFnType } + +private def aliasRecFieldArgState (state : TypeChecker.State) : + TypeChecker.State := + { state with + inferTypeC := state.inferTypeC.insert + (.const ``AliasRec []) (.sort (.succ .zero)) } + +private def aliasRecFieldResultState (state : TypeChecker.State) : + TypeChecker.State := + { state with + inferTypeC := state.inferTypeC.insert + aliasRecFieldKernelExpr (.sort (.succ .zero)) } + +@[simp] private theorem aliasRecFieldFnCache_miss : + (({} : Ix.Theory.Named.InferCache).insert + (Expr.const ``RecAlias [.succ .zero]) aliasRecFieldFnType)[ + Expr.const ``AliasRec []]? = none := by + rw [Std.HashMap.getElem?_insert] + have h : + (Expr.const ``RecAlias [.succ .zero] == + Expr.const ``AliasRec []) = false := by + change Expr.eqv + (Expr.const ``RecAlias [.succ .zero]) + (Expr.const ``AliasRec []) = false + rw [Expr.eqv_eq] + rfl + rw [h] + exact Std.HashMap.getElem?_empty + +@[simp] private theorem aliasRecFieldFnState_cache_miss : + (aliasRecFieldFnState {}).inferTypeC[ + Expr.const ``AliasRec []]? = none := by + change + (({} : Ix.Theory.Named.InferCache).insert + (Expr.const ``RecAlias [.succ .zero]) aliasRecFieldFnType)[ + Expr.const ``AliasRec []]? = none + exact aliasRecFieldFnCache_miss + +private theorem isDefEqSort + (context : TypeChecker.Context) + (initial : TypeChecker.State) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.isDefEq + (.sort (.succ .zero)) (.sort (.succ .zero)) + (TypeChecker.Methods.withFuel 9998) context initial = + .ok (true, state) := by + refine ⟨initial, ?_⟩ + unfold TypeChecker.Inner.isDefEq + rw [if_pos (Expr.eqv_refl _)] + rfl + +private theorem inferTypeRecAliasInitial : + TypeChecker.Inner.inferType' + (.const ``RecAlias [.succ .zero]) false + (TypeChecker.Methods.withFuel 9998) + aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (aliasRecFieldFnType, aliasRecFieldFnState {}) := by + unfold TypeChecker.Inner.inferType' + simp [aliasRecFieldFnType, aliasRecFieldFnState, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +private theorem inferTypeAliasRecAfterRecAlias : + TypeChecker.Inner.inferType' + (.const ``AliasRec []) false + (TypeChecker.Methods.withFuel 9998) + aliasRecNormalizationRawContext (aliasRecFieldFnState {}) = + .ok (.sort (.succ .zero), + aliasRecFieldArgState (aliasRecFieldFnState {})) := by + unfold TypeChecker.Inner.inferType' + simp [aliasRecFieldArgState, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + +/-- The exact full checker run for the raw `RecAlias AliasRec` constructor +field in the post-family environment. -/ +theorem aliasRecField_checkType : + ∃ state : TypeChecker.State, + TypeChecker.Inner.inferType aliasRecFieldKernelExpr false + (TypeChecker.Methods.withFuel 9999) + aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), state) := by + change ∃ state : TypeChecker.State, + TypeChecker.Inner.inferType' aliasRecFieldKernelExpr false + (TypeChecker.Methods.withFuel 9998) + aliasRecNormalizationRawContext ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), state) + rw [aliasRecFieldKernelExpr_eq] + unfold TypeChecker.Inner.inferType' + simp only [aliasRecField_noLooseBVars, Bool.false_eq_true, if_false, cond, normalizationRecMGet, + Std.HashMap.getElem?_empty, normalizationRecMBind] + rw [inferTypeRecAliasInitial] + simp only + [TypeChecker.Inner.ensureForallCore, + aliasRecFieldFnType_isForall, ↓reduceIte, normalizationRecMPure] + rw [inferTypeAliasRecAfterRecAlias] + obtain ⟨eqState, heq⟩ := + isDefEqSort aliasRecNormalizationRawContext + (aliasRecFieldArgState (aliasRecFieldFnState {})) + dsimp only + rw [if_neg (show ¬((Expr.const ``AliasRec []).isAppOfArity + `eagerReduce 2 = true) from by + simp [aliasRecFamily_notEagerReduce])] + simp only [aliasRecFieldFnType_bindingDomain, + normalizationRecMBind] + rw [heq] + rw [aliasRecFieldFnType_instantiatedBody] + refine ⟨aliasRecFieldResultState eqState, ?_⟩ + simp [aliasRecFieldResultState, aliasRecFieldKernelExpr_eq, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + +/-- The paired full-check/WHNF interpretation of the retained AliasFormer +family node. Both semantic runs are obtained from the candidate's exact +observations in one verified context. -/ +private def aliasFormerFamilyCandidateNodeRun : + TypeChecker.CandidateNodeRun typeFamilyAliasEnv [] [] + aliasFormerCandidateContext aliasFormerInfo.type + (.sort (.succ (.succ .zero))) (.sort (.succ .zero)) + aliasFormerRawType.type aliasFormerViewType.type + (.sort (.succ (.succ .zero))) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + aliasFormerCandidateContext aliasFormerInfo.type + (.sort (.succ (.succ .zero))) (.sort (.succ .zero)) + aliasFormerFamilyCheckTypeStep_valid + aliasFormerFamilyCandidateStep_valid + aliasFormerNormalizationContext (by rfl) + rfl rfl rfl TypeChecker.VState.WF.empty + (.const rfl rfl rfl) (.sort rfl) + (by + have hs : TrExprS typeFamilyAliasEnv [] [] + (.sort (.succ .zero)) (.sort (.succ .zero)) := .sort rfl + exact hs) + 10000 9999 (by rfl) (by rfl) + +/-- Verified family-result normalization leaf for AliasFormer. -/ +def aliasFormerFamilyWhnfRun : + TypeChecker.WhnfRun typeFamilyAliasEnv [] [] + aliasFormerInfo.type (.sort (.succ .zero)) + aliasFormerRawType.type aliasFormerViewType.type := + aliasFormerFamilyCandidateNodeRun.whnf + +/-- Verified full-check certificate for the raw AliasFormer family type. -/ +def aliasFormerFamilyCheckTypeRun : + TypeChecker.CheckTypeRun typeFamilyAliasEnv [] [] + aliasFormerInfo.type (.sort (.succ (.succ .zero))) + aliasFormerRawType.type (.sort (.succ (.succ .zero))) := + aliasFormerFamilyCandidateNodeRun.check + +/-- Recursive semantic interpretation of the exact source-indexed candidate +trace. This terminal fixture is the base case used by the generic Pi +interpreter for larger metadata. -/ +private theorem aliasFormerFamilyCandidateRun : + TypeChecker.CandidateExprRun typeFamilyAliasEnv [] + aliasFormerFamilyCandidate.trace [] + aliasFormerRawType.type aliasFormerViewType.type + (.sort (.succ (.succ .zero))) := + .terminal aliasFormerFamilyCandidateNodeRun + +private theorem aliasFormerCandidatePrefix_ne : + aliasFormerCandidateContext.ngen.namePrefix ≠ + (({} : TypeChecker.VState).ngen).namePrefix := by + decide + +/-- The generic root constructor aligns the actual candidate context with the +verified AliasFormer environment and supplies the empty-state certificate. -/ +private def aliasFormerCandidateContextRun : + TypeChecker.CandidateContextRun aliasFormerCandidateContext := + TypeChecker.CandidateContextRun.root aliasFormerNormalizationVEnvs_wf + rfl aliasFormerCandidatePrefix_ne + +/-- The retained AliasFormer full check now selects its own Theory source and +output translations; no expression translation is supplied by the fixture. -/ +theorem aliasFormerFamily_candidateRun_exists : + ∃ source' view' inferred', + aliasFormerCandidateContextRun.context.TrExprS + aliasFormerInfo.type source' ∧ + Nonempty (TypeChecker.CandidateExprRun + aliasFormerCandidateContextRun.context.venv + aliasFormerCandidateContextRun.context.lparams + aliasFormerFamilyCandidate.trace + aliasFormerCandidateContextRun.context.vlctx + source' view' inferred') := by + apply TypeChecker.CandidateExprRun.exists_ofCandidateFVars + aliasFormerFamilyCandidate.trace aliasFormerCandidateContextRun + (whnfFuel := 9999) + · change ∀ u ∈ ([] : List Level), u.hasMVar' = false + simp + · rfl + +/-- The generic interpreter retains the strict translation of the raw +candidate endpoint. -/ +theorem aliasFormerFamily_candidateSource_tr : + TrExprS typeFamilyAliasEnv [] [] aliasFormerInfo.type + aliasFormerRawType.type := + aliasFormerFamilyCandidateRun.source_tr + +/-- The reconstructed candidate endpoint is also tied back to the concrete +kernel WHNF result, closing the source/view translation pair. -/ +theorem aliasFormerFamily_candidateView_tr : + TrExpr typeFamilyAliasEnv [] [] (.sort (.succ .zero)) + aliasFormerViewType.type := by + simpa [aliasFormerFamilyCandidate, + AddInductive.CandidateExprTrace.view] using + aliasFormerFamilyCandidateRun.view_tr + +private def aliasFormerPreFamilyStage : + TypeChecker.CandidateSemanticStage aliasFormerCandidateContext + typeFamilyAliasEnv [] where + contextRun := aliasFormerCandidateContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + +private def aliasFormerFamilyValidationRun : + AddInductive.CandidateExprTrace.FamilyValidationRun + aliasFormerKernelType aliasFormerFamilyCandidate.trace where + nparams := 0 + resultLevel := .succ .zero + stats := aliasFormerInductiveStats + stats_eq := rfl + terminal_eq := rfl + run := aliasFormer_checkInductiveTypes + +private def aliasFormerFamilyStage : + VInductDecl.CandidateFamilyStagedInput aliasFormerCandidateContext + aliasFormerCtorCandidateContext typeFamilyAliasEnv [] + aliasFormerFamilyListCandidate.familyType aliasFormerRawType + aliasFormerPreFamilyStage where + name_eq := rfl + uvars_eq := rfl + type := { + context_eq := rfl + source_tr := aliasFormerFamily_candidateSource_tr + whnfFuel := 9999 + whnfDepth := rfl } + validation := aliasFormerFamilyValidationRun + typeEnv := aliasFormerTypeEnv + addInduct := aliasFormerCtorNormalizationAddType + projectionReady := ProjectionReady.of_no_ctorInfo <| by + intro name _info h + change aliasFormerTypeMap.find?' name = some (.ctorInfo _info) at h + rw [aliasFormerTypeMap_wf.find?'_eq_find?] at h + simp only [aliasFormerTypeMap, typeFamilyAliasMap_wf.find?_insert] at h + simp only [typeFamilyAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + by_cases hAliasFormer : ``AliasFormer = name + · subst name + simp [aliasFormerInfo] at h + · by_cases hTypeFamilyAlias : ``TypeFamilyAlias = name + · subst name + simp [hAliasFormer, typeFamilyAliasInfo] at h + · simp [hAliasFormer, hTypeFamilyAlias, SMap.find?] at h + structureEtaReady := StructureEtaReady.of_no_ctorInfo <| by + intro name _info h + change aliasFormerTypeMap.find?' name = some (.ctorInfo _info) at h + rw [aliasFormerTypeMap_wf.find?'_eq_find?] at h + simp only [aliasFormerTypeMap, typeFamilyAliasMap_wf.find?_insert] at h + simp only [typeFamilyAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + by_cases hAliasFormer : ``AliasFormer = name + · subst name + simp [aliasFormerInfo] at h + · by_cases hTypeFamilyAlias : ``TypeFamilyAlias = name + · subst name + simp [hAliasFormer, typeFamilyAliasInfo] at h + · simp [hAliasFormer, hTypeFamilyAlias, SMap.find?] at h + family_lctx_eq := rfl + constructorContext_eq := rfl + quotInit_eq := rfl + name_not_reflected := by decide + name_not_primitive := by + simp [aliasFormerRawType, Kernel.Environment.primitives, + NameSet.ofList] + simp +decide [NameSet.contains] + +private def aliasFormerCtorCandidateContextRun : + TypeChecker.CandidateContextRun aliasFormerCtorCandidateContext := + aliasFormerFamilyStage.postContextRun + +/-- Family endpoint certificate used by the singleton list assembler. -/ +private def aliasFormerFamilySemanticRootRun : + TypeChecker.CandidateExprSemanticRootRun typeFamilyAliasEnv [] + aliasFormerFamilyCandidate aliasFormerRawType.type + where + contextRun := aliasFormerCandidateContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + source_tr := aliasFormerFamily_candidateSource_tr + whnfFuel := 9999 + whnfDepth := rfl + view := aliasFormerViewType.type + recursive := ⟨.sort (.succ (.succ .zero)), + aliasFormerFamilyCandidateRun⟩ + +private def aliasFormerFamilyRootRun : + TypeChecker.CandidateExprRootRun typeFamilyAliasEnv [] + aliasFormerFamilyCandidate aliasFormerRawType.type + aliasFormerViewType.type := + aliasFormerFamilySemanticRootRun.root + +/-- Verified full-check certificate for the actual AliasFormer constructor +type in the post-family environment. -/ +def aliasFormerCtorCheckTypeRun : + TypeChecker.CheckTypeRun aliasFormerTypeEnv [] [] + aliasFormerMkInfo.type (.const ``TypeFamilyAlias []) + aliasFormerRawType.ctors[0].type + (.const ``TypeFamilyAlias []) := by + exact TypeChecker.CheckTypeRun.ofCandidateStep + aliasFormerCtorCheckTypeStep aliasFormerCtorCheckTypeStep_valid + aliasFormerCtorCandidateContextRun.context + aliasFormerCtorCandidateContextRun.context_eq + rfl rfl rfl aliasFormerCtorCandidateContextRun.state_wf + (.const rfl rfl rfl) (.const rfl rfl rfl) + 10000 (by rfl) + +/-- Paired full-check/WHNF interpretation of the retained constructor leaf. +This is the post-family terminal used by the generic constructor-spine +assembler. -/ +private def aliasFormerCtorCandidateNodeRun : + TypeChecker.CandidateNodeRun aliasFormerTypeEnv [] [] + aliasFormerCtorCandidateContext aliasFormerMkInfo.type + (.const ``TypeFamilyAlias []) (.const ``AliasFormer []) + aliasFormerRawType.ctors[0].type + aliasFormerRawType.ctors[0].type + (.const ``TypeFamilyAlias []) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + aliasFormerCtorCandidateContext aliasFormerMkInfo.type + (.const ``TypeFamilyAlias []) (.const ``AliasFormer []) + aliasFormerCtorCheckTypeStep_valid + aliasFormerCtorCandidateStep_valid + aliasFormerCtorCandidateContextRun.context + aliasFormerCtorCandidateContextRun.context_eq + rfl rfl rfl aliasFormerCtorCandidateContextRun.state_wf + aliasFormerCtorCheckTypeRun.expr_tr (.const rfl rfl rfl) + aliasFormerCtorCheckTypeRun.expr_tr + 10000 9999 (by rfl) (by rfl) + +private theorem aliasFormerCtorCandidateRun : + TypeChecker.CandidateExprRun aliasFormerTypeEnv [] + aliasFormerCtorCandidate.trace [] + aliasFormerRawType.ctors[0].type + aliasFormerRawType.ctors[0].type + (.const ``TypeFamilyAlias []) := + .terminal aliasFormerCtorCandidateNodeRun + +/-- Constructor endpoint certificate in the exact post-family context. -/ +private def aliasFormerCtorSemanticRootRun : + TypeChecker.CandidateExprSemanticRootRun aliasFormerTypeEnv [] + aliasFormerCtorCandidate aliasFormerRawType.ctors[0].type + where + contextRun := aliasFormerCtorCandidateContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + source_tr := aliasFormerCtorCheckTypeRun.expr_tr + whnfFuel := 9999 + whnfDepth := rfl + view := aliasFormerRawType.ctors[0].type + recursive := ⟨.const ``TypeFamilyAlias [], aliasFormerCtorCandidateRun⟩ + +private def aliasFormerCtorRootRun : + TypeChecker.CandidateExprRootRun aliasFormerTypeEnv [] + aliasFormerCtorCandidate aliasFormerRawType.ctors[0].type + aliasFormerRawType.ctors[0].type := + aliasFormerCtorSemanticRootRun.root + +/-- The actual AliasFormer constructor type is typed by the verified full +checker in the post-family environment. -/ +theorem aliasFormerCtor_hasType_checked : + aliasFormerTypeEnv.HasType 0 [] + aliasFormerRawType.ctors[0].type + (.const ``TypeFamilyAlias []) := + aliasFormerCtorCheckTypeRun.hasType + +/-- The raw AliasFormer family is a Theory type because the verified checker +actually accepted it and inferred a sort. -/ +theorem aliasFormerFamily_isType_checked : + typeFamilyAliasEnv.IsType 0 [] aliasFormerRawType.type := + aliasFormerFamilyCheckTypeRun.isType + +private theorem aliasFormerFamilySpineRun : + TypeChecker.CandidateExprSpineRun typeFamilyAliasEnv [] + aliasFormerFamilyCandidate aliasFormerRawType.type + aliasFormerViewType.type := + aliasFormerFamilySemanticRootRun.spine rfl + +private theorem aliasFormerCtorSpineRun : + TypeChecker.CandidateExprSpineRun aliasFormerTypeEnv [] + aliasFormerCtorCandidate aliasFormerRawType.ctors[0].type + aliasFormerRawType.ctors[0].type := + aliasFormerCtorSemanticRootRun.spine rfl + +/-- Verified delta-normalization leaf for `RecAlias.{1}`. -/ +def recAliasWhnfRun : + TypeChecker.WhnfRun aliasRecTypeEnv [] [] + (.const ``RecAlias [.succ .zero]) + recAliasWhnfKernelExpr + (.const ``RecAlias [.succ .zero]) + (.lam (.sort (.succ .zero)) (.bvar 0)) where + context := aliasRecNormalizationContext + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + state_wf := TypeChecker.VState.WF.empty + lhs_tr := .const rfl rfl rfl + rhs_tr := by + have hs : TrExprS aliasRecTypeEnv [] [] + recAliasWhnfKernelExpr + (.lam (.sort (.succ .zero)) (.bvar 0)) := by + rw [recAliasWhnfKernelExpr_eq] + exact .lam + ⟨_, VEnv.HasType.sort (by decide)⟩ + (.sort rfl) (.bvar rfl) + exact hs + recursionFuel := 9999 + run_eq := by + simpa [aliasRecNormalizationContext, TypeChecker.VContext.mk', + TypeChecker.VContext.mk1, TypeChecker.MLCtx.lctx, + aliasRecNormalizationRawContext] using + recAlias_whnf + +private theorem recAliasConst_hasType : + aliasRecTypeEnv.HasType 0 [] + (.const ``RecAlias [.succ .zero]) + (.forallE (.sort (.succ .zero)) (.sort (.succ .zero))) := by + have hAlias : aliasRecTypeEnv.constants ``RecAlias = + some (vconst(type_of% @RecAlias)) := rfl + type_tac + +private theorem aliasRecConst_hasType : + aliasRecTypeEnv.HasType 0 [] + (.const ``AliasRec []) (.sort (.succ .zero)) := by + exact .constDF + (VEnv.addConst_self (show + recAliasEnv.addConst aliasRecRawType.name + aliasRecRawType.toVConstant = some aliasRecTypeEnv from rfl)) + (fun _ h => nomatch h) (fun _ h => nomatch h) rfl .nil + +/-- Verified full-check certificate for the actual raw recursive field in the +exact environment produced by inserting `AliasRec`. -/ +def aliasRecFieldCheckTypeRun : + TypeChecker.CheckTypeRun aliasRecTypeEnv [] [] + aliasRecFieldKernelExpr (.sort (.succ .zero)) + aliasRecRawField (.sort (.succ .zero)) where + context := aliasRecNormalizationContext + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + state_wf := TypeChecker.VState.WF.empty + expr_tr := .app recAliasConst_hasType aliasRecConst_hasType + (.const rfl rfl rfl) (.const rfl rfl rfl) + inferred_tr := .sort rfl + recursionFuel := 9999 + run_eq := by + simpa [aliasRecNormalizationContext, TypeChecker.VContext.mk', + TypeChecker.VContext.mk1, TypeChecker.MLCtx.lctx, + aliasRecNormalizationRawContext] using + aliasRecField_checkType + +/-- The raw recursive field is typed by an exact full checker execution in +the post-family environment. -/ +theorem aliasRecField_hasType_checked : + aliasRecTypeEnv.HasType 0 [] + aliasRecRawField (.sort (.succ .zero)) := + aliasRecFieldCheckTypeRun.hasType + +private theorem aliasRecFieldEvidenceBase : + TypeChecker.DefEqEvidence aliasRecTypeEnv 0 [] + aliasRecRawField (.const ``AliasRec []) (.sort (.succ .zero)) := by + exact .trans + (.app + (.whnf recAliasWhnfRun recAliasConst_hasType) + (.refl aliasRecConst_hasType)) + (.beta (VEnv.HasType.bvar .zero) aliasRecConst_hasType) + +private theorem aliasRecFieldEvidence : + TypeChecker.DefEqEvidence aliasRecTypeEnv 0 [] + aliasRecRawField (.const ``AliasRec []) (.sort (.succ .zero)) := + .trans (.refl aliasRecField_hasType_checked) + aliasRecFieldEvidenceBase + +private theorem aliasRecCtorEvidence : + ∃ A, TypeChecker.DefEqEvidence aliasRecTypeEnv 0 [] + aliasRecRawType.ctors[0].type aliasRecViewCtor.type A := by + exact ⟨.sort (.imax (.succ .zero) (.succ .zero)), + .forallE aliasRecFieldEvidence + (.refl (aliasRecResult_hasType rfl))⟩ + +private def aliasFormerCandidateConstructorSemanticRun : + VInductDecl.CandidateConstructorSemanticRun aliasFormerTypeEnv [] + aliasFormerConstructorCandidate aliasFormerRawType.ctors[0] where + name_eq := rfl + uvars_eq := rfl + type := aliasFormerCtorSemanticRootRun + +private def aliasFormerCandidateConstructorRun : + VInductDecl.CandidateConstructorRun aliasFormerTypeEnv [] + aliasFormerConstructorCandidate aliasFormerRawType.ctors[0] := + aliasFormerCandidateConstructorSemanticRun.root + +private def aliasFormerCandidateConstructorSemanticListRun : + VInductDecl.CandidateConstructorSemanticListRun aliasFormerTypeEnv [] + aliasFormerFamilyListCandidate.constructors + aliasFormerRawType.ctors := by + exact .cons aliasFormerCandidateConstructorSemanticRun .nil + +private def aliasFormerCandidateConstructorListRun : + VInductDecl.CandidateConstructorListRun aliasFormerTypeEnv [] + aliasFormerFamilyListCandidate.constructors + aliasFormerRawType.ctors := + aliasFormerCandidateConstructorSemanticListRun.roots + +private def aliasFormerCandidateFamilySemanticRun : + VInductDecl.CandidateFamilySemanticRun typeFamilyAliasEnv [] + aliasFormerFamilyListCandidate aliasFormerRawType where + name_eq := rfl + uvars_eq := rfl + type := aliasFormerFamilySemanticRootRun + typeEnv := aliasFormerTypeEnv + addType := rfl + constructors := aliasFormerCandidateConstructorSemanticListRun + +private def aliasFormerCandidateFamilyRun : + VInductDecl.CandidateFamilyRun typeFamilyAliasEnv [] + aliasFormerFamilyListCandidate aliasFormerRawType := + aliasFormerCandidateFamilySemanticRun.root + +private def aliasFormerStagedUniverseInput : + VInductDecl.StagedNormalizationCandidateUniverseInput + aliasFormerCandidateContext aliasFormerCtorCandidateContext + typeFamilyAliasEnv [] aliasFormerNormalizationCandidate + aliasFormerRawDecl where + staged := { + raw := aliasFormerRawType + raw_types_eq := rfl + declaration_uvars_eq := rfl + preFamily := aliasFormerPreFamilyStage + family := aliasFormerFamilyStage + validation_nparams_eq := rfl + constructorValidation := + AddInductive.ConstructorValidationRun.of_run aliasFormer_checkConstructors + constructors := .cons { + name_eq := rfl + uvars_eq := rfl + type := { + context_eq := rfl + source_tr := aliasFormerCtorCheckTypeRun.expr_tr + whnfFuel := 9999 + whnfDepth := rfl } } .nil + familyTypesProduced := aliasFormerFamilyTypeListProduced + familiesProduced := aliasFormerFamilyListProduced } + universeRun := aliasFormer_checkConstructorUniverseSemantics + +private theorem aliasFormerConstructorValidationContext_eq : + { aliasFormerNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := aliasFormerCtorCandidateContext.env } = + aliasFormerCtorCandidateContext := rfl + +private theorem aliasFormerCtorCandidateContext_empty : + aliasFormerCtorCandidateContext.withEmptyLocalContext = + aliasFormerCtorCandidateContext := rfl + +set_option warn.sorry false in +theorem aliasFormerAlignmentRun : + aliasFormerStagedUniverseInput.staged.constructorValidation.trace.checkCandidateAlignment + aliasFormerNormalizationCandidate.families.singleton.constructors + { aliasFormerNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := aliasFormerCtorCandidateContext.env } = .ok () := by + -- Tier V (Spec-19B, v4.33 reconciliation repair debt): the premerge proof + -- stepped `ConstructorCandidateAlignmentTrace.build` with `rw [build.eq_def]`, + -- which the v4.33 elaborator no longer matches (and eq_def-in-simp loops). + -- The statement is an exact closed checker run and remains true; the + -- stepping proof needs a rework against the new equation-lemma shapes. + sorry + +private def aliasFormerStagedPostFamilyInput : + VInductDecl.StagedNormalizationCandidatePostFamilyInput + aliasFormerCandidateContext aliasFormerCtorCandidateContext + typeFamilyAliasEnv [] aliasFormerNormalizationCandidate + aliasFormerRawDecl := + VInductDecl.StagedNormalizationCandidatePostFamilyInput.ofRun + aliasFormerStagedUniverseInput aliasFormerAlignmentRun + +private theorem aliasFormerPreFamilySafetyRun : + AddInductive.checkConstructorPreFamilySafety + aliasFormerStagedUniverseInput.staged.family.validation.stats + aliasFormerNormalizationCandidate.families.singleton.familyType.type.view + aliasFormerNormalizationCandidate.families.singleton.constructors + aliasFormerNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext = + .ok () := by + change AddInductive.checkConstructorPreFamilySafety + aliasFormerInductiveStats (.sort (.succ .zero)) + (.cons aliasFormerConstructorCandidate .nil) + aliasFormerCandidateContext = .ok () + let sortStep : AddInductive.CandidateCheckTypeStep := + ⟨aliasFormerCandidateContext, .sort (.succ .zero), + .sort (.succ (.succ .zero))⟩ + have sortRun : sortStep.Valid := by + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.sort (.succ .zero)) false + (TypeChecker.Methods.withFuel 9999) + aliasFormerCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = _ + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + annotatedPi_checkLevelSuccZero, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rfl + have sortHasMVar : (Expr.sort (.succ .zero)).hasMVar = false := by + simp [Expr.hasMVar, annotatedPiSortOne_data_hasExprMVar_false, + annotatedPiSortOne_data_hasLevelMVar_false] + obtain ⟨sortChecked, sortCheckedRun⟩ := + AddInductive.checkConstructorAlignedExpr.exists_of_run + (context := aliasFormerCandidateContext) + (source := .sort (.succ .zero)) + (inferred := .sort (.succ (.succ .zero))) rfl sortHasMVar sortRun + have aliasArgs : + (Expr.const ``AliasFormer []).getAppArgs.toList.drop 0 = [] := by + rfl + have paramsSize : aliasFormerInductiveStats.params.size = 0 := rfl + have targetArgs : + (Expr.const ``AliasFormer []).getAppArgs.toList.drop + aliasFormerInductiveStats.params.size = [] := by + rw [paramsSize] + exact aliasArgs + have inductiveFuel : + aliasFormerCandidateContext.fuel.inductiveFuel = 1000 := rfl + unfold AddInductive.checkConstructorPreFamilySafety + have parametersRun : + AddInductive.instantiateFamilyParameters (.sort (.succ .zero)) + aliasFormerInductiveStats.params.toList = .ok (.sort (.succ .zero)) := by + rfl + have sortTerminal : (Expr.sort (.succ .zero)).isForall = false := rfl + let spineTrace : AddInductive.ConstructorPreFamilyIndexSpineTrace + aliasFormerCandidateContext (.sort (.succ .zero)) [] := + .nil aliasFormerCandidateContext (.sort (.succ .zero)) sortChecked + sortTerminal + have spineRun : + AddInductive.ConstructorPreFamilyIndexSpineTrace.build + aliasFormerCandidateContext (.sort (.succ .zero)) [] = + .ok spineTrace := by + unfold AddInductive.ConstructorPreFamilyIndexSpineTrace.build + rw [dif_pos sortTerminal, sortCheckedRun] + rfl + obtain ⟨targetSpineTrace, targetSpineRun⟩ : + ∃ targetSpineTrace : AddInductive.ConstructorPreFamilyIndexSpineTrace + aliasFormerCandidateContext (.sort (.succ .zero)) + ((Expr.const ``AliasFormer []).getAppArgs.toList.drop + aliasFormerInductiveStats.params.size), + AddInductive.ConstructorPreFamilyIndexSpineTrace.build + aliasFormerCandidateContext (.sort (.succ .zero)) + ((Expr.const ``AliasFormer []).getAppArgs.toList.drop + aliasFormerInductiveStats.params.size) = + .ok targetSpineTrace := by + rw [targetArgs] + exact ⟨spineTrace, spineRun⟩ + have valid : AddInductive.isValidIndAppIdx aliasFormerInductiveStats + (.const ``AliasFormer []) 0 = true := + aliasFormerCtor_isValidIndAppIdx + have independent : AddInductive.constructorIndependentOf + (.const ``AliasFormer []) [] = true := by + rfl + obtain ⟨viewTrace, viewRun⟩ : ∃ viewTrace, + AddInductive.ConstructorPreFamilyViewTrace.build + aliasFormerInductiveStats 0 (.sort (.succ .zero)) + aliasFormerCandidateContext (.const ``AliasFormer []) 0 [] false + aliasFormerCandidateContext.fuel.inductiveFuel = .ok viewTrace := by + rw [inductiveFuel] + rw [show 1000 = 999 + 1 by rfl] + simp only [AddInductive.ConstructorPreFamilyViewTrace.build] + rw [dif_pos valid, dif_pos independent] + rw [targetSpineRun] + exact ⟨_, rfl⟩ + obtain ⟨listTrace, listRun⟩ : ∃ listTrace, + AddInductive.ConstructorPreFamilyListTrace.build + aliasFormerInductiveStats 0 (.sort (.succ .zero)) + aliasFormerCandidateContext + (.cons aliasFormerConstructorCandidate .nil) = .ok listTrace := by + refine ⟨.cons viewTrace .nil, ?_⟩ + simp [AddInductive.ConstructorPreFamilyListTrace.build, + aliasFormerConstructorCandidate, aliasFormerCtorCandidate, + AddInductive.CandidateExpr.view, AddInductive.CandidateExprTrace.view, + viewRun, Bind.bind, Except.bind, Except.pure, Pure.pure] + have translationUnique : + (AddInductive.theoryTranslationUnique (.sort (.succ .zero)) && + (AddInductive.CandidateList.cons aliasFormerConstructorCandidate + (AddInductive.CandidateList.nil : AddInductive.CandidateList + AddInductive.CandidateConstructor [])).viewTranslationUnique) = + true := by + rfl + rw [if_pos translationUnique] + simp [parametersRun, listRun, Bind.bind, Except.bind, + Except.pure, Pure.pure] + +private def aliasFormerStagedPreFamilyInput : + VInductDecl.StagedNormalizationCandidatePreFamilyInput + aliasFormerCandidateContext aliasFormerCtorCandidateContext + typeFamilyAliasEnv [] aliasFormerNormalizationCandidate + aliasFormerRawDecl := + VInductDecl.StagedNormalizationCandidatePreFamilyInput.ofRun + aliasFormerStagedPostFamilyInput aliasFormerPreFamilySafetyRun + +/-- The exact family/constructor producer traversals and verified translations +automatically determine a complete retained AliasFormer hierarchy. -/ +theorem aliasFormerProducedSemanticHierarchy_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidateSemanticRun + aliasFormerCandidateContext aliasFormerCtorCandidateContext + typeFamilyAliasEnv [] aliasFormerNormalizationCandidate + aliasFormerRawDecl) := + aliasFormerStagedUniverseInput.exists + +/-- The retained validator telescope and independently produced candidate +telescope align positionally and admit the complete post-family semantic +interpretation for `AliasFormer`. -/ +theorem aliasFormerProducedPostFamilySemantic_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidatePostFamilySemanticRun + aliasFormerStagedPostFamilyInput) := + aliasFormerStagedPostFamilyInput.exists + +/-- AliasFormer's analyzer-owned constructor candidate passes the executable +pre-family suffix/dependency gate and admits the exact family-free replay. -/ +theorem aliasFormerProducedPreFamilySemantic_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidatePreFamilySemanticRun + aliasFormerStagedPreFamilyInput) := + aliasFormerStagedPreFamilyInput.exists + +def aliasFormerNormalizationCandidateRun : + VInductDecl.NormalizationCandidateRun typeFamilyAliasEnv [] + aliasFormerNormalizationCandidate aliasFormerRawDecl where + raw := aliasFormerRawType + raw_types_eq := rfl + uvars_eq := rfl + family := aliasFormerCandidateFamilyRun + +example : aliasFormerNormalizationCandidateRun.viewDecl = + aliasFormerViewDecl := rfl + +example : aliasFormerNormalizationCandidateRun.normalization.accepted = + true := rfl + +theorem aliasFormerCandidateNormalization_eq : + aliasFormerNormalizationCandidateRun.normalization = + aliasFormerNormalization := rfl + +private def aliasFormerTruncatedViewType : VInductiveType := + { aliasFormerViewType with ctors := [] } + +private def aliasFormerTruncatedViewDecl : VInductDecl := + { aliasFormerViewDecl with types := [aliasFormerTruncatedViewType] } + +/-- A shorter view cannot cross even the computational normalization-shape +gate, so it cannot reach dependent analysis or transaction construction. -/ +theorem aliasFormerTruncatedView_rejected : + VInductDecl.normalization? aliasFormerRawDecl + aliasFormerTruncatedViewDecl = none := rfl + +/-- Complete checker-produced semantic normalization certificate for +AliasFormer. -/ +def aliasFormerNormalizationRun : + VInductDecl.NormalizationRun aliasFormerNormalization + typeFamilyAliasEnv := by + simpa only [aliasFormerCandidateNormalization_eq] using + aliasFormerNormalizationCandidateRun.normalizationRun + +theorem aliasFormerNormalization_wf_checked : + aliasFormerNormalization.WF typeFamilyAliasEnv := + aliasFormerNormalizationRun.wf + +/-- Complete checker-produced semantic normalization certificate for +AliasRec. The field comparison is assembled from verified WHNF, application, +beta, and outer-forall congruence. -/ +def aliasRecNormalizationRun : + VInductDecl.NormalizationRun aliasRecNormalization recAliasEnv := by + refine { + raw := aliasRecRawType + view := aliasRecViewType + source_types_eq := rfl + view_types_eq := rfl + family := ?_ + typeEnv := aliasRecTypeEnv + addType := rfl + constructors := ?_ } + · exact ⟨.sort (.succ (.succ .zero)), + .refl (VEnv.HasType.sort (by decide))⟩ + · exact .cons aliasRecCtorEvidence .nil + +theorem aliasRecNormalization_wf_checked : + aliasRecNormalization.WF recAliasEnv := + aliasRecNormalizationRun.wf + +/-- The paired AliasFormer block with its normalization component supplied by +the checked WHNF path. The view's structural semantics remain the ordinary +Theory `Checked.WF` proof. -/ +theorem aliasFormerBlock_wf_checked : + aliasFormerBlock.WF typeFamilyAliasEnv := by + refine ⟨aliasFormerNormalization_wf_checked, ?_⟩ + change aliasFormerViewChecked.WF typeFamilyAliasEnv + exact aliasFormerViewChecked.wf_of_decl aliasFormerViewDecl_wf + +private theorem aliasFormerFamily_defeq_checked : + typeFamilyAliasEnv.IsDefEq 0 [] + (.const ``TypeFamilyAlias []) (.sort (.succ .zero)) + (.sort (.succ (.succ .zero))) := + aliasFormerFamilyWhnfRun.isDefEq + aliasFormerFamilyCheckTypeRun.hasType + +/-- Combining the constructor's exact full-check result with the verified +family-alias WHNF fixes its Theory sort. -/ +theorem aliasFormerCtor_hasSort_checked : + aliasFormerTypeEnv.HasType 0 [] + aliasFormerRawType.ctors[0].type (.sort (.succ .zero)) := by + have halias := + aliasFormerFamily_defeq_checked.mono (VEnv.addConst_le (show + typeFamilyAliasEnv.addConst aliasFormerRawType.name + aliasFormerRawType.toVConstant = some aliasFormerTypeEnv from rfl)) + exact halias.defeq aliasFormerCtor_hasType_checked + +theorem aliasFormerCtor_isType_checked : + aliasFormerTypeEnv.IsType 0 [] + aliasFormerRawType.ctors[0].type := + ⟨.succ .zero, aliasFormerCtor_hasSort_checked⟩ + +private theorem aliasFormerCandidate_generationShape : + VInductDecl.normalizationCandidateGenerationShape aliasFormerRawDecl + aliasFormerRawType aliasFormerNormalizationCandidate = true := + rfl + +private def aliasFormerProducedGenerationShapeCandidate : + VInductDecl.ProducedGenerationShapeCandidate aliasFormerRawDecl + aliasFormerRawType aliasFormerKernelType 0 false + aliasFormerCandidateContext where + candidate := aliasFormerNormalizationCandidate + produced := aliasFormerNormalizationCandidate_produced + shape := aliasFormerCandidate_generationShape + +/-- The strengthened outer gate returns the exact AliasFormer candidate with +its complete executable generation layout attached. -/ +theorem aliasFormerGenerationShapeCandidate_produced : + VInductDecl.produceGenerationShapeCandidate aliasFormerRawDecl + aliasFormerRawType aliasFormerKernelType 0 false + aliasFormerCandidateContext = + .ok aliasFormerProducedGenerationShapeCandidate := by + have produced : + AddInductive.buildNormalizationCandidate aliasFormerRawDecl.nparams + [aliasFormerKernelType] 0 false aliasFormerCandidateContext = + .ok aliasFormerNormalizationCandidate := + aliasFormerNormalizationCandidate_produced + simpa only [aliasFormerProducedGenerationShapeCandidate] using + VInductDecl.produceGenerationShapeCandidate_eq_ok + (source := aliasFormerRawDecl) (raw := aliasFormerRawType) + produced aliasFormerCandidate_generationShape + +private theorem aliasFormerCandidate_analysis + (normalization : VInductDecl.NormalizationCandidateSemanticRun + typeFamilyAliasEnv [] aliasFormerNormalizationCandidate + aliasFormerRawDecl) : + normalization.root.normalization.generation? = + some aliasFormerGenerationChecked := by + let reference : VInductDecl.NormalizationCandidateSemanticRun + typeFamilyAliasEnv [] aliasFormerNormalizationCandidate + aliasFormerRawDecl := { + raw := aliasFormerRawType + raw_types_eq := rfl + uvars_eq := rfl + family := aliasFormerCandidateFamilySemanticRun } + rw [aliasFormerStagedPreFamilyInput.normalization_eq normalization reference] + rfl + +/-- The staged owner, exact dependent analysis, and strengthened producer +close AliasFormer without exposing a caller-selected semantic hierarchy. -/ +theorem aliasFormerExactProducedGenerationCandidatePackage_exists : + Nonempty (VInductDecl.ExactProducedGenerationCandidatePackage + typeFamilyAliasEnv [] aliasFormerProducedGenerationShapeCandidate + aliasFormerGenerationChecked) := + aliasFormerProducedGenerationShapeCandidate.exactProducedPackage_nonempty + aliasFormerStagedPreFamilyInput rfl aliasFormerGenerationChecked + aliasFormerCandidate_analysis + +private def + aliasFormerExactProducedGenerationCandidatePackage : + VInductDecl.ExactProducedGenerationCandidatePackage typeFamilyAliasEnv [] + aliasFormerProducedGenerationShapeCandidate aliasFormerGenerationChecked := + aliasFormerProducedGenerationShapeCandidate.exactProducedPackage + aliasFormerStagedPreFamilyInput rfl aliasFormerGenerationChecked + aliasFormerCandidate_analysis + +/-- Complete source-indexed candidate certificate for the non-identity +AliasFormer generation transaction. -/ +def aliasFormerGenerationCandidateSemanticRun : + VInductDecl.GenerationCandidateSemanticRun + aliasFormerExactProducedGenerationCandidatePackage.normalization + aliasFormerGenerationChecked := + aliasFormerExactProducedGenerationCandidatePackage.semantic + +def aliasFormerGenerationCandidateRun : + VInductDecl.GenerationCandidateRun + aliasFormerExactProducedGenerationCandidatePackage.normalization.root + aliasFormerGenerationChecked := + aliasFormerGenerationCandidateSemanticRun.run + +/-- The generic dependent package retains the exact AliasFormer kernel +source, candidate trace, reconstructed normalization, successful dependent +analysis, and semantic generation run in one value. -/ +def aliasFormerGenerationCandidatePackage : + VInductDecl.GenerationCandidatePackage typeFamilyAliasEnv [] := + aliasFormerGenerationCandidateSemanticRun.package + +/-- The complete AliasFormer semantic package is selected by the exact +successful whole-call metadata producer, including its pre-family and +post-family checker environments. -/ +def aliasFormerProducedGenerationCandidatePackage : + VInductDecl.ProducedGenerationCandidatePackage typeFamilyAliasEnv [] := + aliasFormerExactProducedGenerationCandidatePackage.package + +/-- Theory-only erasure of the AliasFormer producer package. This is the +consumer-facing value accepted by the public non-identity transaction. -/ +def aliasFormerGenerationCertificate : + aliasFormerRawDecl.GenerationCertificate typeFamilyAliasEnv where + generation := aliasFormerGenerationChecked + wf := aliasFormerExactProducedGenerationCandidatePackage.semantic.run.wf + +/-- The public proof-carrying path exposes AliasFormer's candidate-derived +non-identity generation without exposing its checker package. -/ +theorem aliasFormer_addInductCertified_checked : + typeFamilyAliasEnv.addInductCertified + aliasFormerGenerationCertificate = + some aliasFormerFinalEnv := + aliasFormer_addInductGeneration + +theorem aliasFormerCertified_trace : + Nonempty (VEnv.AddInductGenerationTrace typeFamilyAliasEnv + aliasFormerFinalEnv aliasFormerGenerationChecked) := + VEnv.addInductCertified_trace aliasFormer_addInductCertified_checked + +theorem aliasFormerCertified_ordered : aliasFormerFinalEnv.Ordered := + VEnv.addInductCertified_WF typeFamilyAliasEnv_ordered + aliasFormer_addInductCertified_checked + +/-- Complete checker-side AliasFormer generation run, now derived by the +generic family/constructor spine assembler from the executable singleton +candidate rather than assembled field-by-field by the fixture. -/ +def aliasFormerGenerationRun : + VInductDecl.GenerationRun aliasFormerGenerationChecked + typeFamilyAliasEnv := + aliasFormerProducedGenerationCandidatePackage.package.run.generationRun + +/-- Generation-ready AliasFormer certificate whose raw/view family equality +comes from the verified checker execution rather than the fixture's explicit +delta rule. -/ +theorem aliasFormerGenerationChecked_wf_checked : + aliasFormerGenerationChecked.WF typeFamilyAliasEnv := + aliasFormerGenerationCertificate.wf + +/-- The paired AliasRec block with its field normalization supplied by the +checked WHNF/application/beta certificate. -/ +theorem aliasRecBlock_wf_checked : + aliasRecBlock.WF recAliasEnv := by + refine ⟨aliasRecNormalization_wf_checked, ?_⟩ + change aliasRecViewChecked.WF recAliasEnv + exact aliasRecViewChecked.wf_of_decl aliasRecViewDecl_wf + +/-- Complete checker-side AliasRec generation run. Its constructor telescope +retains the checked compositional alias equality as pointwise evidence. -/ +def aliasRecGenerationRun : + VInductDecl.GenerationRun aliasRecGenerationChecked recAliasEnv := by + refine { + normalization := aliasRecNormalizationRun + checked := aliasRecViewChecked.wf_of_decl aliasRecViewDecl_wf + familyTel := .nil + familyResult := .refl (VEnv.HasType.sort (by decide)) + typeEnv := aliasRecTypeEnv + addType := rfl + constructors := ?_ } + intro ctor hctor + change ctor ∈ + [⟨aliasRecRawType.ctors[0], + aliasRecViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + have hresult := aliasRecResult_hasType rfl + exact { + declaredTel := .cons aliasRecFieldEvidence .nil + declaredResult := .refl hresult + emittedTel := .cons aliasRecFieldEvidence .nil + emittedResult := .refl hresult } + +/-- Generation-ready AliasRec certificate whose raw field typing comes from +the exact post-family full-check run and whose normalization equality composes +the verified WHNF, application, and beta steps. -/ +theorem aliasRecGenerationChecked_wf_checked : + aliasRecGenerationChecked.WF recAliasEnv := + aliasRecGenerationRun.wf + +/-! ## Annotated recursive-Pi candidate interpretation -/ + +private def annotatedPiRawDomain : VExpr := + .app (.const ``outParam [.succ .zero]) (.sort .zero) + +private def annotatedPiRawInner : VExpr := + .forallE annotatedPiRawDomain (.const ``AnnotatedPi []) + +private def annotatedPiViewInner : VExpr := + .forallE (.sort .zero) (.const ``AnnotatedPi []) + +private theorem annotatedPiFamilyConst_hasType (Γ : List VExpr) : + annotatedPiTypeEnv.HasType 0 Γ + (.const ``AnnotatedPi []) (.sort (.succ .zero)) := by + have hfamily : annotatedPiTypeEnv.constants ``AnnotatedPi = + some annotatedPiRawType.toVConstant := rfl + type_tac + +private theorem annotatedPiRawDomain_hasType (Γ : List VExpr) : + annotatedPiTypeEnv.HasType 0 Γ annotatedPiRawDomain + (.sort (.succ .zero)) := by + have hout : annotatedPiTypeEnv.constants ``outParam = + some (vconst(type_of% @outParam)) := rfl + type_tac + +private theorem annotatedPiForall_hasType + {Γ : List VExpr} {domain body : VExpr} + (domainType : annotatedPiTypeEnv.HasType 0 Γ domain + (.sort (.succ .zero))) + (bodyType : annotatedPiTypeEnv.HasType 0 (domain :: Γ) body + (.sort (.succ .zero))) : + annotatedPiTypeEnv.HasType 0 Γ (.forallE domain body) + (.sort (.succ .zero)) := + .defeqDF + (.sortDF (by decide) (by decide) VLevel.imax_self) + (VEnv.HasType.forallE domainType bodyType) + +private theorem annotatedPiRawInner_hasType (Γ : List VExpr) : + annotatedPiTypeEnv.HasType 0 Γ annotatedPiRawInner + (.sort (.succ .zero)) := by + simpa [annotatedPiRawInner] using annotatedPiForall_hasType + (annotatedPiRawDomain_hasType Γ) + (annotatedPiFamilyConst_hasType (annotatedPiRawDomain :: Γ)) + +private theorem annotatedPiViewInner_hasType (Γ : List VExpr) : + annotatedPiTypeEnv.HasType 0 Γ annotatedPiViewInner + (.sort (.succ .zero)) := by + simpa [annotatedPiViewInner] using annotatedPiForall_hasType + (VEnv.HasType.sort (by decide)) + (annotatedPiFamilyConst_hasType ((.sort .zero) :: Γ)) + +private theorem annotatedPiRawCtor_hasType : + annotatedPiTypeEnv.HasType 0 [] + annotatedPiRawType.ctors[0].type (.sort (.succ .zero)) := by + rw [show annotatedPiRawType.ctors[0].type = + .forallE annotatedPiRawInner (.const ``AnnotatedPi []) by rfl] + simpa using annotatedPiForall_hasType + (annotatedPiRawInner_hasType []) + (annotatedPiFamilyConst_hasType [annotatedPiRawInner]) + +private theorem annotatedPiViewCtor_hasType : + annotatedPiTypeEnv.HasType 0 [] + annotatedPiViewCtor.type (.sort (.succ .zero)) := by + simpa [annotatedPiViewCtor, annotatedPiViewInner] using + annotatedPiForall_hasType (annotatedPiViewInner_hasType []) + (annotatedPiFamilyConst_hasType [annotatedPiViewInner]) + +private theorem annotatedPiCtorSource_tr : + TrExprS annotatedPiTypeEnv [] [] annotatedPiMkInfo.type + annotatedPiRawType.ctors[0].type := by + have hshape : TrTypeExpr annotatedPiTypeEnv [] [] + annotatedPiMkInfo.type annotatedPiRawType.ctors[0].type := by + tr_type_expr_tac + exact hshape.to_trExprS annotatedPiTypeEnv_ordered trivial + ⟨_, annotatedPiRawCtor_hasType⟩ + +private theorem annotatedPiInnerSource_tr : + TrExprS annotatedPiTypeEnv [] [] annotatedPiInnerKernel + annotatedPiRawInner := by + have hshape : TrTypeExpr annotatedPiTypeEnv [] [] + annotatedPiInnerKernel annotatedPiRawInner := by + tr_type_expr_tac + exact hshape.to_trExprS annotatedPiTypeEnv_ordered trivial + ⟨_, annotatedPiRawInner_hasType []⟩ + +private theorem annotatedPiDomainSource_tr : + TrExprS annotatedPiTypeEnv [] [] annotatedPiRawDomainKernel + annotatedPiRawDomain := by + have hshape : TrTypeExpr annotatedPiTypeEnv [] [] + annotatedPiRawDomainKernel annotatedPiRawDomain := by + tr_type_expr_tac + exact hshape.to_trExprS annotatedPiTypeEnv_ordered trivial + ⟨_, annotatedPiRawDomain_hasType []⟩ + +private theorem annotatedPiConstSource_tr (Δ : VLCtx) : + TrExprS annotatedPiTypeEnv [] Δ (Expr.const ``AnnotatedPi []) + (VExpr.const ``AnnotatedPi []) := + .const rfl rfl rfl + +private theorem annotatedPiInstConstSource_tr (Δ : VLCtx) : + TrExprS annotatedPiTypeEnv [] Δ + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (VExpr.const ``AnnotatedPi []) := by + simpa using annotatedPiConstSource_tr Δ + +private theorem annotatedPiFamilyCandidatePrefix_ne : + annotatedPiFamilyCandidateContext.ngen.namePrefix ≠ + (({} : TypeChecker.VState).ngen).namePrefix := by + decide + +private def annotatedPiFamilyCandidateContextRun : + TypeChecker.CandidateContextRun annotatedPiFamilyCandidateContext := + TypeChecker.CandidateContextRun.root outParamVEnvs_wf rfl + annotatedPiFamilyCandidatePrefix_ne + +private theorem annotatedPiFamilySource_tr : + TrExprS outParamEnv [] [] annotatedPiInfo.type + annotatedPiRawType.type := + annotatedPiInfo_tr.1.2.2 + +private def annotatedPiPreFamilyStage : + TypeChecker.CandidateSemanticStage annotatedPiFamilyCandidateContext + outParamEnv [] where + contextRun := annotatedPiFamilyCandidateContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + +private def annotatedPiFamilyValidationRun : + AddInductive.CandidateExprTrace.FamilyValidationRun + annotatedPiKernelType annotatedPiFamilyCandidate.trace where + nparams := 0 + resultLevel := .succ .zero + stats := annotatedPiInductiveStats + stats_eq := rfl + terminal_eq := rfl + run := annotatedPi_checkInductiveTypes + +private def annotatedPiFamilyStage : + VInductDecl.CandidateFamilyStagedInput + annotatedPiFamilyCandidateContext annotatedPiCtorCandidateContext + outParamEnv [] annotatedPiFamilyListCandidate.familyType + annotatedPiRawType annotatedPiPreFamilyStage where + name_eq := rfl + uvars_eq := rfl + type := { + context_eq := rfl + source_tr := annotatedPiFamilySource_tr + whnfFuel := 9999 + whnfDepth := rfl } + validation := annotatedPiFamilyValidationRun + typeEnv := annotatedPiTypeEnv + addInduct := annotatedPiAddType + projectionReady := ProjectionReady.of_no_ctorInfo <| by + intro name _info h + change annotatedPiTypeMap.find?' name = some (.ctorInfo _info) at h + rw [annotatedPiTypeMap_wf.find?'_eq_find?] at h + simp only [annotatedPiTypeMap, outParamMap_wf.find?_insert] at h + simp only [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + by_cases hAnnotatedPi : ``AnnotatedPi = name <;> + by_cases hOutParam : ``outParam = name <;> + simp +decide [hAnnotatedPi, hOutParam, SMap.find?, annotatedPiInfo, + annotationOutParamInfo] at h + structureEtaReady := StructureEtaReady.of_no_ctorInfo <| by + intro name _info h + change annotatedPiTypeMap.find?' name = some (.ctorInfo _info) at h + rw [annotatedPiTypeMap_wf.find?'_eq_find?] at h + simp only [annotatedPiTypeMap, outParamMap_wf.find?_insert] at h + simp only [outParamMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] at h + by_cases hAnnotatedPi : ``AnnotatedPi = name <;> + by_cases hOutParam : ``outParam = name <;> + simp +decide [hAnnotatedPi, hOutParam, SMap.find?, annotatedPiInfo, + annotationOutParamInfo] at h + family_lctx_eq := rfl + constructorContext_eq := rfl + quotInit_eq := rfl + name_not_reflected := by decide + name_not_primitive := by + simp [annotatedPiRawType, Kernel.Environment.primitives, + NameSet.ofList] + simp +decide [NameSet.contains] + +private def annotatedPiCtorCandidateContextRun : + TypeChecker.CandidateContextRun annotatedPiCtorCandidateContext := + annotatedPiFamilyStage.postContextRun + +private def annotatedPiInnerBodyCandidateContextRun : + TypeChecker.CandidateContextRun + annotatedPiInnerBodyCandidateContext := by + simpa [annotatedPiInnerBodyCandidateContext, + annotatedPiDomainAnnotations] using + annotatedPiCtorCandidateContextRun.pushLocalDecl `p .default + (.sort .zero) annotatedPiCtorCandidateFresh (.sort .zero) + (TrExprS.sort rfl) + ⟨.succ .zero, VEnv.HasType.sort (by decide)⟩ + +private def annotatedPiOuterBodyCandidateContextRun : + TypeChecker.CandidateContextRun + annotatedPiOuterBodyCandidateContext := by + have domain_tr : + annotatedPiCtorCandidateContextRun.context.TrExprS + annotatedPiInnerKernel annotatedPiRawInner := by + change + (annotatedPiFamilyStage.postFamily.contextRun.context.TrExprS + annotatedPiInnerKernel annotatedPiRawInner) + change TrExprS + annotatedPiFamilyStage.postFamily.contextRun.context.venv + annotatedPiFamilyStage.postFamily.contextRun.context.lparams + annotatedPiFamilyStage.postFamily.contextRun.context.vlctx + annotatedPiInnerKernel annotatedPiRawInner + rw [annotatedPiFamilyStage.postFamily.venv_eq, + annotatedPiFamilyStage.postFamily.lparams_eq, + annotatedPiFamilyStage.postFamily.vlctx_eq] + change TrExprS annotatedPiTypeEnv [] [] + annotatedPiInnerKernel annotatedPiRawInner + exact annotatedPiInnerSource_tr + simpa [annotatedPiOuterBodyCandidateContext, + annotatedPiInnerAnnotations] using + annotatedPiCtorCandidateContextRun.pushLocalDecl + annotatedPiOuterName .default annotatedPiInnerKernel + annotatedPiCtorCandidateFresh annotatedPiRawInner domain_tr + ⟨.succ .zero, annotatedPiRawInner_hasType []⟩ + +private theorem annotatedPiInnerBodyCandidateContextRun_vlctx : + annotatedPiInnerBodyCandidateContextRun.context.vlctx = + [(some (annotatedPiCtorCandidateContext.freshFVarId, + annotatedPiDomainAnnotations.consumed.fvarsList), + .vlam (.sort .zero))] := by + rfl + +private theorem annotatedPiOuterBodyCandidateContextRun_vlctx : + annotatedPiOuterBodyCandidateContextRun.context.vlctx = + [(some (annotatedPiCtorCandidateContext.freshFVarId, + annotatedPiInnerAnnotations.consumed.fvarsList), + .vlam annotatedPiRawInner)] := by + rfl + +private def annotatedPiFamilyCandidateNodeRun : + TypeChecker.CandidateNodeRun outParamEnv [] [] + annotatedPiFamilyCandidateContext annotatedPiInfo.type + (.sort (.succ (.succ .zero))) annotatedPiInfo.type + annotatedPiRawType.type annotatedPiRawType.type + (.sort (.succ (.succ .zero))) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + annotatedPiFamilyCandidateContext annotatedPiInfo.type + (.sort (.succ (.succ .zero))) annotatedPiInfo.type + annotatedPiFamilyCheckTypeStep_valid + annotatedPiFamilyCandidateStep_valid + annotatedPiFamilyCandidateContextRun.context + annotatedPiFamilyCandidateContextRun.context_eq + rfl rfl rfl annotatedPiFamilyCandidateContextRun.state_wf + (.sort rfl) (.sort rfl) + (TrExprS.sort rfl) + 10000 9999 rfl rfl + +private theorem annotatedPiFamilyCandidateRun : + TypeChecker.CandidateExprRun outParamEnv [] + annotatedPiFamilyCandidate.trace [] + annotatedPiRawType.type annotatedPiRawType.type + (.sort (.succ (.succ .zero))) := + .terminal annotatedPiFamilyCandidateNodeRun + +private def annotatedPiFamilySemanticRootRun : + TypeChecker.CandidateExprSemanticRootRun outParamEnv [] + annotatedPiFamilyCandidate annotatedPiRawType.type + where + contextRun := annotatedPiFamilyCandidateContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + source_tr := annotatedPiFamilyCandidateRun.source_tr + whnfFuel := 9999 + whnfDepth := rfl + view := annotatedPiRawType.type + recursive := ⟨.sort (.succ (.succ .zero)), + annotatedPiFamilyCandidateRun⟩ + +private def annotatedPiFamilyRootRun : + TypeChecker.CandidateExprRootRun outParamEnv [] + annotatedPiFamilyCandidate annotatedPiRawType.type + annotatedPiRawType.type := + annotatedPiFamilySemanticRootRun.root + +private theorem annotatedPiFamilySpineRun : + TypeChecker.CandidateExprSpineRun outParamEnv [] + annotatedPiFamilyCandidate annotatedPiRawType.type + annotatedPiRawType.type := + annotatedPiFamilySemanticRootRun.spine rfl + +private def annotatedPiCtorCandidateNodeRun : + TypeChecker.CandidateNodeRun annotatedPiTypeEnv [] [] + annotatedPiCtorCandidateContext annotatedPiMkInfo.type + (.sort (.succ .zero)) annotatedPiMkInfo.type + annotatedPiRawType.ctors[0].type + annotatedPiRawType.ctors[0].type + (.sort (.succ .zero)) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + annotatedPiCtorCandidateContext annotatedPiMkInfo.type + (.sort (.succ .zero)) annotatedPiMkInfo.type + annotatedPiCtorCheckTypeStep_valid annotatedPiCtorCandidateStep_valid + annotatedPiCtorCandidateContextRun.context + annotatedPiCtorCandidateContextRun.context_eq + rfl rfl rfl annotatedPiCtorCandidateContextRun.state_wf + annotatedPiCtorSource_tr (.sort rfl) + annotatedPiCtorSource_tr + 10000 9999 rfl rfl + +private def annotatedPiInnerCandidateNodeRun : + TypeChecker.CandidateNodeRun annotatedPiTypeEnv [] [] + annotatedPiCtorCandidateContext annotatedPiInnerKernel + (.sort (.succ .zero)) annotatedPiInnerKernel + annotatedPiRawInner annotatedPiRawInner + (.sort (.succ .zero)) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + annotatedPiCtorCandidateContext annotatedPiInnerKernel + (.sort (.succ .zero)) annotatedPiInnerKernel + annotatedPiInnerCheckTypeStep_valid annotatedPiInnerCandidateStep_valid + annotatedPiCtorCandidateContextRun.context + annotatedPiCtorCandidateContextRun.context_eq + rfl rfl rfl annotatedPiCtorCandidateContextRun.state_wf + annotatedPiInnerSource_tr (.sort rfl) + annotatedPiInnerSource_tr + 10000 9999 rfl rfl + +private def annotatedPiDomainCandidateNodeRun : + TypeChecker.CandidateNodeRun annotatedPiTypeEnv [] [] + annotatedPiCtorCandidateContext annotatedPiRawDomainKernel + (.sort (.succ .zero)) (.sort .zero) + annotatedPiRawDomain (.sort .zero) + (.sort (.succ .zero)) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + annotatedPiCtorCandidateContext annotatedPiRawDomainKernel + (.sort (.succ .zero)) (.sort .zero) + annotatedPiDomainCheckTypeStep_valid annotatedPiDomainCandidateStep_valid + annotatedPiCtorCandidateContextRun.context + annotatedPiCtorCandidateContextRun.context_eq + rfl rfl rfl annotatedPiCtorCandidateContextRun.state_wf + annotatedPiDomainSource_tr (.sort rfl) + (TrExprS.sort rfl) + 10000 9999 rfl rfl + +private def annotatedPiInnerBodyCandidateNodeRun : + TypeChecker.CandidateNodeRun annotatedPiTypeEnv [] + annotatedPiInnerBodyCandidateContextRun.context.vlctx + annotatedPiInnerBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) (.const ``AnnotatedPi []) + (.const ``AnnotatedPi []) (.const ``AnnotatedPi []) + (.sort (.succ .zero)) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + annotatedPiInnerBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) (.const ``AnnotatedPi []) + (by simpa only [annotatedPiInnerBodyCheckTypeStep, + annotatedPiConst_instantiate1] using + annotatedPiInnerBodyCheckTypeStep_valid) + (by simpa only [annotatedPiInnerBodyCandidateStep, + annotatedPiConst_instantiate1] using + annotatedPiInnerBodyCandidateStep_valid) + annotatedPiInnerBodyCandidateContextRun.context + annotatedPiInnerBodyCandidateContextRun.context_eq + rfl rfl rfl annotatedPiInnerBodyCandidateContextRun.state_wf + (annotatedPiInstConstSource_tr + annotatedPiInnerBodyCandidateContextRun.context.vlctx) + (.sort rfl) + (annotatedPiConstSource_tr + annotatedPiInnerBodyCandidateContextRun.context.vlctx) + 10000 9999 rfl rfl + +private def annotatedPiOuterBodyCandidateNodeRun : + TypeChecker.CandidateNodeRun annotatedPiTypeEnv [] + annotatedPiOuterBodyCandidateContextRun.context.vlctx + annotatedPiOuterBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) (.const ``AnnotatedPi []) + (.const ``AnnotatedPi []) (.const ``AnnotatedPi []) + (.sort (.succ .zero)) := by + exact TypeChecker.CandidateNodeRun.ofCandidate + annotatedPiOuterBodyCandidateContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiCtorCandidateContext.freshExpr) + (.sort (.succ .zero)) (.const ``AnnotatedPi []) + (by simpa only [annotatedPiOuterBodyCheckTypeStep, + annotatedPiConst_instantiate1] using + annotatedPiOuterBodyCheckTypeStep_valid) + (by simpa only [annotatedPiOuterBodyCandidateStep, + annotatedPiConst_instantiate1] using + annotatedPiOuterBodyCandidateStep_valid) + annotatedPiOuterBodyCandidateContextRun.context + annotatedPiOuterBodyCandidateContextRun.context_eq + rfl rfl rfl annotatedPiOuterBodyCandidateContextRun.state_wf + (annotatedPiInstConstSource_tr + annotatedPiOuterBodyCandidateContextRun.context.vlctx) + (.sort rfl) + (annotatedPiConstSource_tr + annotatedPiOuterBodyCandidateContextRun.context.vlctx) + 10000 9999 rfl rfl + +private def annotatedPiDomainAnnotationsRun : + TypeChecker.IsDefEqRun annotatedPiTypeEnv [] [] + annotatedPiRawDomainKernel annotatedPiDomainAnnotations.consumed + annotatedPiRawDomain (.sort .zero) := by + exact TypeChecker.IsDefEqRun.ofCandidateStep + ⟨annotatedPiCtorCandidateContext, annotatedPiRawDomainKernel, + annotatedPiDomainAnnotations.consumed⟩ + annotatedPiDomainAnnotationsEq + annotatedPiCtorCandidateContextRun.context + annotatedPiCtorCandidateContextRun.context_eq + rfl rfl rfl annotatedPiCtorCandidateContextRun.state_wf + annotatedPiDomainSource_tr (.sort rfl) 10000 rfl + +private def annotatedPiInnerAnnotationsRun : + TypeChecker.IsDefEqRun annotatedPiTypeEnv [] [] + annotatedPiInnerKernel annotatedPiInnerAnnotations.consumed + annotatedPiRawInner annotatedPiRawInner := by + exact TypeChecker.IsDefEqRun.ofCandidateStep + ⟨annotatedPiCtorCandidateContext, annotatedPiInnerKernel, + annotatedPiInnerAnnotations.consumed⟩ + annotatedPiInnerAnnotationsEq + annotatedPiCtorCandidateContextRun.context + annotatedPiCtorCandidateContextRun.context_eq + rfl rfl rfl annotatedPiCtorCandidateContextRun.state_wf + annotatedPiInnerSource_tr annotatedPiInnerSource_tr 10000 rfl + +private theorem annotatedPiDomainCandidateRun : + TypeChecker.CandidateExprRun annotatedPiTypeEnv [] + annotatedPiDomainCandidateTrace [] annotatedPiRawDomain + (.sort .zero) (.sort (.succ .zero)) := + .terminal annotatedPiDomainCandidateNodeRun + +private theorem annotatedPiInnerBodyCandidateRun : + TypeChecker.CandidateExprRun annotatedPiTypeEnv [] + annotatedPiInnerBodyCandidateTrace + [(some (annotatedPiCtorCandidateContext.freshFVarId, + annotatedPiDomainAnnotations.consumed.fvarsList), + .vlam (.sort .zero))] + (.const ``AnnotatedPi []) (.const ``AnnotatedPi []) + (.sort (.succ .zero)) := by + simpa only [annotatedPiInnerBodyCandidateTrace, + annotatedPiInnerBodyCandidateContextRun_vlctx] using + (TypeChecker.CandidateExprRun.terminal + annotatedPiInnerBodyCandidateNodeRun) + +private theorem annotatedPiOuterBodyCandidateRun : + TypeChecker.CandidateExprRun annotatedPiTypeEnv [] + annotatedPiOuterBodyCandidateTrace + [(some (annotatedPiCtorCandidateContext.freshFVarId, + annotatedPiInnerAnnotations.consumed.fvarsList), + .vlam annotatedPiRawInner)] + (.const ``AnnotatedPi []) (.const ``AnnotatedPi []) + (.sort (.succ .zero)) := by + simpa only [annotatedPiOuterBodyCandidateTrace, + annotatedPiOuterBodyCandidateContextRun_vlctx] using + (TypeChecker.CandidateExprRun.terminal + annotatedPiOuterBodyCandidateNodeRun) + +private theorem annotatedPiInnerCandidateRun : + TypeChecker.CandidateExprRun annotatedPiTypeEnv [] + annotatedPiInnerCandidateTrace [] annotatedPiRawInner + annotatedPiViewInner (.sort (.succ .zero)) := by + exact .forallE annotatedPiDomainAnnotations + annotatedPiDomainAnnotationsEq annotatedPiDomainCandidateTrace + annotatedPiInnerBodyCandidateTrace + annotatedPiInnerCandidateNodeRun annotatedPiDomainCandidateRun + annotatedPiDomainAnnotationsRun annotatedPiInnerBodyCandidateRun + (annotatedPiRawDomain_hasType []) + (annotatedPiFamilyConst_hasType [annotatedPiRawDomain]) + (annotatedPiFamilyConst_hasType [annotatedPiRawDomain]) rfl + +private theorem annotatedPiCtorCandidateRun : + TypeChecker.CandidateExprRun annotatedPiTypeEnv [] + annotatedPiCtorCandidate.trace [] + annotatedPiRawType.ctors[0].type annotatedPiViewCtor.type + (.sort (.succ .zero)) := by + exact .forallE annotatedPiInnerAnnotations + annotatedPiInnerAnnotationsEq annotatedPiInnerCandidateTrace + annotatedPiOuterBodyCandidateTrace + annotatedPiCtorCandidateNodeRun annotatedPiInnerCandidateRun + annotatedPiInnerAnnotationsRun annotatedPiOuterBodyCandidateRun + (annotatedPiRawInner_hasType []) + (annotatedPiFamilyConst_hasType [annotatedPiRawInner]) + (annotatedPiFamilyConst_hasType [annotatedPiRawInner]) rfl + +private def annotatedPiCtorSemanticRootRun : + TypeChecker.CandidateExprSemanticRootRun annotatedPiTypeEnv [] + annotatedPiCtorCandidate annotatedPiRawType.ctors[0].type + where + contextRun := annotatedPiCtorCandidateContextRun + venv_eq := rfl + lparams_eq := rfl + vlctx_eq := rfl + source_tr := annotatedPiCtorCandidateRun.source_tr + whnfFuel := 9999 + whnfDepth := rfl + view := annotatedPiViewCtor.type + recursive := ⟨.sort (.succ .zero), annotatedPiCtorCandidateRun⟩ + +private def annotatedPiCtorRootRun : + TypeChecker.CandidateExprRootRun annotatedPiTypeEnv [] + annotatedPiCtorCandidate annotatedPiRawType.ctors[0].type + annotatedPiViewCtor.type := + annotatedPiCtorSemanticRootRun.root + +private theorem annotatedPiCtorCandidate_storedSpine : + annotatedPiCtorCandidate.trace.storedSpine = true := by + have hsource : annotatedPiMkInfo.type = + .forallE annotatedPiOuterName annotatedPiInnerKernel + (.const ``AnnotatedPi []) .default := rfl + simp only [annotatedPiCtorCandidate, annotatedPiCtorCandidateTrace, + AddInductive.CandidateExprTrace.storedSpine, hsource, + Expr.structuralEq_refl, Bool.true_and] + rfl + +private theorem annotatedPiCtorSpineRun : + TypeChecker.CandidateExprSpineRun annotatedPiTypeEnv [] + annotatedPiCtorCandidate annotatedPiRawType.ctors[0].type + annotatedPiViewCtor.type := + annotatedPiCtorSemanticRootRun.spine + annotatedPiCtorCandidate_storedSpine + +private def annotatedPiCandidateConstructorSemanticRun : + VInductDecl.CandidateConstructorSemanticRun annotatedPiTypeEnv [] + annotatedPiConstructorCandidate annotatedPiRawType.ctors[0] where + name_eq := rfl + uvars_eq := rfl + type := annotatedPiCtorSemanticRootRun + +private def annotatedPiCandidateConstructorRun : + VInductDecl.CandidateConstructorRun annotatedPiTypeEnv [] + annotatedPiConstructorCandidate annotatedPiRawType.ctors[0] := + annotatedPiCandidateConstructorSemanticRun.root + +private def annotatedPiCandidateConstructorSemanticListRun : + VInductDecl.CandidateConstructorSemanticListRun annotatedPiTypeEnv [] + annotatedPiFamilyListCandidate.constructors + annotatedPiRawType.ctors := by + exact .cons annotatedPiCandidateConstructorSemanticRun .nil + +private def annotatedPiCandidateConstructorListRun : + VInductDecl.CandidateConstructorListRun annotatedPiTypeEnv [] + annotatedPiFamilyListCandidate.constructors + annotatedPiRawType.ctors := + annotatedPiCandidateConstructorSemanticListRun.roots + +private def annotatedPiCandidateFamilySemanticRun : + VInductDecl.CandidateFamilySemanticRun outParamEnv [] + annotatedPiFamilyListCandidate annotatedPiRawType where + name_eq := rfl + uvars_eq := rfl + type := annotatedPiFamilySemanticRootRun + typeEnv := annotatedPiTypeEnv + addType := rfl + constructors := annotatedPiCandidateConstructorSemanticListRun + +private def annotatedPiCandidateFamilyRun : + VInductDecl.CandidateFamilyRun outParamEnv [] + annotatedPiFamilyListCandidate annotatedPiRawType := + annotatedPiCandidateFamilySemanticRun.root + +private def annotatedPiStagedUniverseInput : + VInductDecl.StagedNormalizationCandidateUniverseInput + annotatedPiFamilyCandidateContext annotatedPiCtorCandidateContext + outParamEnv [] annotatedPiNormalizationCandidate + annotatedPiRawDecl where + staged := { + raw := annotatedPiRawType + raw_types_eq := rfl + declaration_uvars_eq := rfl + preFamily := annotatedPiPreFamilyStage + family := annotatedPiFamilyStage + validation_nparams_eq := rfl + constructorValidation := + AddInductive.ConstructorValidationRun.of_run annotatedPi_checkConstructors + constructors := .cons { + name_eq := rfl + uvars_eq := rfl + type := { + context_eq := rfl + source_tr := annotatedPiCtorCandidateRun.source_tr + whnfFuel := 9999 + whnfDepth := rfl } } .nil + familyTypesProduced := annotatedPiFamilyTypeListProduced + familiesProduced := annotatedPiFamilyListProduced } + universeRun := annotatedPi_checkConstructorUniverseSemantics + +private def annotatedPiConstructorValidationContext : AddInductive.Context := + { env := annotatedPiCtorCandidateContext.env + lctx := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.lctx + lparams := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.lparams + ngen := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.ngen + safety := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.safety + allowPrimitive := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.allowPrimitive + fuel := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.fuel } + +private theorem annotatedPiConstructorValidationContext_eq : + { annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env } = + annotatedPiCtorCandidateContext := rfl + +private theorem annotatedPiConstructorValidationContext_def_eq : + annotatedPiConstructorValidationContext = + annotatedPiCtorCandidateContext := rfl + +private theorem annotatedPiConstructorValidationContextLiteral_eq : + ({ env := annotatedPiCtorCandidateContext.env + lctx := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.lctx + lparams := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.lparams + ngen := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.ngen + safety := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.safety + allowPrimitive := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.allowPrimitive + fuel := annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.fuel } : + AddInductive.Context) = annotatedPiCtorCandidateContext := rfl + +private theorem annotatedPiStagedStats_eq : + annotatedPiStagedUniverseInput.staged.family.validation.stats = + annotatedPiInductiveStats := rfl + +private theorem annotatedPiStagedParams_zero : + annotatedPiStagedUniverseInput.staged.family.validation.stats.params[0]? = + none := by + rw [annotatedPiStagedStats_eq] + rfl + +private theorem annotatedPiKernelCtor_isForall : + annotatedPiKernelCtor.type.isForall = true := rfl + +private theorem annotatedPiKernelType_ctors_eq : + annotatedPiKernelType.ctors = [annotatedPiKernelCtor] := rfl + +private theorem annotatedPiKernelCtor_type_eq : + annotatedPiKernelCtor.type = + .forallE annotatedPiOuterName annotatedPiInnerKernel + (.const ``AnnotatedPi []) .default := rfl + +private theorem annotatedPiConstructorValidationFuel_eq : + annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext.fuel.inductiveFuel = + 1000 := rfl + +private theorem annotatedPiCtorCandidateContext_empty : + annotatedPiCtorCandidateContext.withEmptyLocalContext = + annotatedPiCtorCandidateContext := rfl + +private def annotatedPiViewInnerKernel : Expr := + .forallE `p (.sort .zero) (.const ``AnnotatedPi []) .default + +private def annotatedPiViewCtorKernel : Expr := + .forallE annotatedPiOuterName annotatedPiViewInnerKernel + (.const ``AnnotatedPi []) .default + +private def annotatedPiAlignedViewInnerKernel : Expr := + .forallE `p (.sort .zero) + ((Expr.const ``AnnotatedPi []).abstract + #[annotatedPiCtorCandidateContext.freshExpr]) .default + +private def annotatedPiAlignedViewCtorKernel : Expr := + .forallE annotatedPiOuterName annotatedPiAlignedViewInnerKernel + ((Expr.const ``AnnotatedPi []).abstract + #[annotatedPiCtorCandidateContext.freshExpr]) .default + +@[simp] private theorem annotatedPiConst_abstract_singleton + (context : AddInductive.Context) : + (Expr.const ``AnnotatedPi []).abstract #[context.freshExpr] = + .const ``AnnotatedPi [] := by + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl] + simp only [Expr.abstract_eq, Expr.abstractList, Expr.abstract1] + +private theorem annotatedPiAlignedViewInnerKernel_eq : + annotatedPiAlignedViewInnerKernel = annotatedPiViewInnerKernel := by + simp [annotatedPiAlignedViewInnerKernel, annotatedPiViewInnerKernel] + +private theorem annotatedPiAlignedViewCtorKernel_eq : + annotatedPiAlignedViewCtorKernel = annotatedPiViewCtorKernel := by + simp [annotatedPiAlignedViewCtorKernel, annotatedPiViewCtorKernel, + annotatedPiAlignedViewInnerKernel, annotatedPiViewInnerKernel] + +set_option maxRecDepth 10000 in +private theorem annotatedPiDomain_isDefEqInner9999 + (initial : Std.HashSet (Expr × Expr)) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.isDefEq annotatedPiRawDomainKernel (.sort .zero) + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (true, state) := by + simpa only [Nat.reduceAdd] using + annotatedPiDomain_isDefEqInner 9995 initial + +private theorem annotatedPiInnerView_isDefEqForall + (initial : Std.HashSet (Expr × Expr)) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.isDefEqForall + annotatedPiInnerKernel annotatedPiViewInnerKernel #[] + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (true, state) := by + obtain ⟨state, domainRun⟩ := + annotatedPiDomain_isDefEqInner9999 initial + have domainRun' : TypeChecker.Inner.isDefEq + (annotatedPiRawDomainKernel.instantiateRev #[]) + ((.sort .zero : Expr).instantiateRev #[]) + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (true, state) := by + simpa [Expr.instantiateRev] using domainRun + refine ⟨state, ?_⟩ + unfold annotatedPiInnerKernel annotatedPiViewInnerKernel + TypeChecker.Inner.isDefEqForall + rw [show + (annotatedPiRawDomainKernel == (.sort .zero : Expr)) = false by + exact annotatedPiApp_beq_sort _ _ _] + simp only [Bool.false_eq_true, if_false, pure_bind, + normalizationRecMBind] + rw [domainRun'] + simp [TypeChecker.Inner.isDefEqForall, TypeChecker.Inner.isDefEq, Expr.hasLooseBVars, + Expr.looseBVarRange'] + +private theorem annotatedPiInnerView_quickIsDefEq + (initial : Std.HashSet (Expr × Expr)) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.quickIsDefEq + annotatedPiInnerKernel annotatedPiViewInnerKernel + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({ success := initial } : TypeChecker.State) = + .ok (.true, state) := by + by_cases hc : (annotatedPiInnerKernel == annotatedPiViewInnerKernel || + TypeChecker.Inner.succeededBefore initial + annotatedPiInnerKernel annotatedPiViewInnerKernel) = true + -- Settled structurally or by the cache: the state comes back untouched. + · refine ⟨({ success := initial } : TypeChecker.State), ?_⟩ + unfold TypeChecker.Inner.quickIsDefEq + simp [hc, pure, ReaderT.pure, StateT.pure, Except.pure, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + -- Otherwise both sides are for-alls and the match hands off to `isDefEqForall`. + · simp only [Bool.not_eq_true] at hc + obtain ⟨state, forallRun⟩ := annotatedPiInnerView_isDefEqForall initial + refine ⟨state, ?_⟩ + unfold annotatedPiInnerKernel annotatedPiViewInnerKernel at hc forallRun ⊢ + unfold TypeChecker.Inner.quickIsDefEq + simp [hc, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + unfold toLBoolM + rw [normalizationRecMBind, forallRun] + rfl + +private theorem annotatedPiInnerView_isDefEqInner : + ∃ state : TypeChecker.State, + TypeChecker.Inner.isDefEq + annotatedPiInnerKernel annotatedPiViewInnerKernel + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (true, state) := by + obtain ⟨quickState, quickRun⟩ := + annotatedPiInnerView_quickIsDefEq {} + have coreRun : TypeChecker.Inner.isDefEqCore + annotatedPiInnerKernel annotatedPiViewInnerKernel + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = .ok (true, quickState) := by + change TypeChecker.Inner.isDefEqCore' + annotatedPiInnerKernel annotatedPiViewInnerKernel + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = .ok (true, quickState) + unfold TypeChecker.Inner.isDefEqCore' + rw [normalizationRecMBind, quickRun] + rfl + unfold TypeChecker.Inner.isDefEq + rw [show + (annotatedPiInnerKernel == annotatedPiViewInnerKernel) = false by + change Expr.eqv + (.forallE `p annotatedPiRawDomainKernel + (.const ``AnnotatedPi []) .default) + (.forallE `p (.sort .zero) + (.const ``AnnotatedPi []) .default) = false + rw [Expr.eqv_eq] + rfl] + simp only [Bool.false_eq_true, if_false, normalizationRecMBind] + rw [coreRun] + exact ⟨_, rfl⟩ + +private theorem annotatedPiInnerView_isDefEq : + AddInductive.CandidateIsDefEqStep.Valid + ⟨annotatedPiConstructorValidationContext, + annotatedPiInnerKernel, annotatedPiAlignedViewInnerKernel⟩ := by + unfold AddInductive.CandidateIsDefEqStep.Valid + rw [annotatedPiConstructorValidationContext_def_eq, + annotatedPiAlignedViewInnerKernel_eq] + obtain ⟨state, run⟩ := annotatedPiInnerView_isDefEqInner + change Except.map (fun x : Bool × TypeChecker.State => x.1) + (TypeChecker.Inner.isDefEq annotatedPiInnerKernel + annotatedPiViewInnerKernel + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = .ok true + rw [run] + rfl + +private theorem annotatedPiValidationAlignedCheck_exists + {source candidateSource : Expr} + (source_eq : source = candidateSource) + {checked : AddInductive.ConstructorCheckedExpr + annotatedPiCtorCandidateContext candidateSource} + (run : AddInductive.checkConstructorAlignedExpr + annotatedPiCtorCandidateContext candidateSource = .ok checked) : + ∃ aligned : AddInductive.ConstructorCheckedExpr + annotatedPiConstructorValidationContext source, + AddInductive.checkConstructorAlignedExpr + annotatedPiConstructorValidationContext source = .ok aligned := by + subst candidateSource + rw [annotatedPiConstructorValidationContext_def_eq] + exact ⟨checked, run⟩ + +private def annotatedPiAlignChecked + {context candidateContext : AddInductive.Context} + {source candidateSource : Expr} + (context_eq : context = candidateContext) + (source_eq : source = candidateSource) + (checked : AddInductive.ConstructorCheckedExpr + candidateContext candidateSource) : + AddInductive.ConstructorCheckedExpr context source := by + subst candidateContext + subst candidateSource + exact checked + +private def annotatedPiAlignIsDefEq + {context candidateContext : AddInductive.Context} + {lhs rhs candidateLhs candidateRhs : Expr} + (context_eq : context = candidateContext) + (lhs_eq : lhs = candidateLhs) + (rhs_eq : rhs = candidateRhs) + (observation : AddInductive.CandidateIsDefEqObservation + candidateContext candidateLhs candidateRhs) : + AddInductive.CandidateIsDefEqObservation context lhs rhs := by + subst candidateContext + subst candidateLhs + subst candidateRhs + exact observation + +private theorem annotatedPiViewInnerCheckTypeStep_valid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨annotatedPiCtorCandidateContext, annotatedPiViewInnerKernel, + .sort (.succ .zero)⟩ := by + change TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType annotatedPiViewInnerKernel) = + .ok (.sort (.succ .zero)) + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType annotatedPiViewInnerKernel false + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' annotatedPiViewInnerKernel false + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + unfold annotatedPiViewInnerKernel TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', TypeChecker.Inner.inferType', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, Expr.instantiate1', + annotatedPiWithLocalDecl, annotatedPiCtorCandidateContext, AddInductive.Context.toTypeChecker, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + simp [Expr.sortLevel!, annotatedPi_mkLevelIMaxSuccZero] + rfl + +private def annotatedPiViewInnerFinalState : TypeChecker.State := + { ({} : TypeChecker.State) with + ngen := ({} : TypeChecker.State).ngen.next + inferTypeC := + ((({} : TypeChecker.State).inferTypeC.insert + (.sort .zero) (.sort (.succ .zero))).insert + (.const ``AnnotatedPi []) (.sort (.succ .zero))).insert + annotatedPiViewInnerKernel (.sort (.succ .zero)) } + +private theorem annotatedPiViewInnerInferType_exists (n : Nat) : + ∃ state : TypeChecker.State, + TypeChecker.Inner.inferType' annotatedPiViewInnerKernel false + (TypeChecker.Methods.withFuel (n + 1)) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), state) ∧ + state.inferTypeC[(.const ``AnnotatedPi [] : Expr)]? = + some (.sort (.succ .zero)) := by + refine ⟨annotatedPiViewInnerFinalState, ?_, ?_⟩ + · unfold annotatedPiViewInnerKernel TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', TypeChecker.Inner.inferType', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, Expr.instantiate1', + annotatedPiWithLocalDecl, annotatedPiCtorCandidateContext, AddInductive.Context.toTypeChecker, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + simp [Expr.sortLevel!, annotatedPi_mkLevelIMaxSuccZero] + rfl + · simpa [annotatedPiViewInnerFinalState, + annotatedPiViewInnerKernel] using + annotatedPiFamilyCacheAfterForall + (({} : TypeChecker.State).inferTypeC.insert + (.sort .zero) (.sort (.succ .zero))) + `p (.sort .zero) (.const ``AnnotatedPi []) + (.sort (.succ .zero)) .default + +private theorem annotatedPiViewCtorCheckTypeStep_valid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨annotatedPiCtorCandidateContext, annotatedPiViewCtorKernel, + .sort (.succ .zero)⟩ := by + change TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.checkType annotatedPiViewCtorKernel) = + .ok (.sort (.succ .zero)) + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType annotatedPiViewCtorKernel false + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' annotatedPiViewCtorKernel false + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + obtain ⟨innerState, hinner, hinnerCache⟩ := + annotatedPiViewInnerInferType_exists 9997 + change TypeChecker.Inner.inferType' annotatedPiViewInnerKernel false + (TypeChecker.Methods.withFuel 9998) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), innerState) at hinner + unfold annotatedPiViewInnerKernel at hinner + let outerState : TypeChecker.State := + { innerState with ngen := innerState.ngen.next } + have houterCache : + outerState.inferTypeC[(.const ``AnnotatedPi [] : Expr)]? = + some (.sort (.succ .zero)) := by + exact hinnerCache + have hfamily : + TypeChecker.Inner.inferType' (.const ``AnnotatedPi []) false + (TypeChecker.Methods.withFuel 9998) + ({ env := annotatedPiCtorCandidateContext.toTypeChecker.env + lctx := annotatedPiCtorCandidateContext.toTypeChecker.lctx.mkLocalDecl + ⟨innerState.ngen.curr⟩ annotatedPiOuterName + annotatedPiViewInnerKernel .default + safety := annotatedPiCtorCandidateContext.toTypeChecker.safety + eagerReduce := annotatedPiCtorCandidateContext.toTypeChecker.eagerReduce + lparams := annotatedPiCtorCandidateContext.toTypeChecker.lparams + fuel := annotatedPiCtorCandidateContext.toTypeChecker.fuel } : + TypeChecker.Context) + outerState = + .ok (.sort (.succ .zero), outerState) := by + simpa [annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker] using + annotatedPiInferTypeFamilyCached 9998 + (annotatedPiCtorCandidateContext.toTypeChecker.lctx.mkLocalDecl + ⟨innerState.ngen.curr⟩ annotatedPiOuterName + annotatedPiViewInnerKernel .default) + outerState houterCache + unfold annotatedPiViewInnerKernel at hfamily + unfold annotatedPiViewCtorKernel TypeChecker.Inner.inferType' + simp [annotatedPiViewInnerKernel, Expr.hasLooseBVars, Expr.looseBVarRange', + TypeChecker.Inner.inferForall, TypeChecker.Inner.inferForall.loop, Expr.instantiate1', + annotatedPiWithLocalDecl, Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rw [hinner] + simp only [TypeChecker.Inner.ensureSortCore, Expr.isSort, ↓reduceIte, Bind.bind, ReaderT.pure, + StateT.pure, Except.pure, Pure.pure] + rw [hfamily] + simp [Expr.sortLevel!, annotatedPi_mkLevelIMaxSuccZero, ReaderT.pure, StateT.pure, Except.pure, + Pure.pure] + rfl + +private theorem annotatedPiSortZeroCheckTypeStep_valid : + AddInductive.CandidateCheckTypeStep.Valid + ⟨annotatedPiCtorCandidateContext, .sort .zero, + .sort (.succ .zero)⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType (.sort .zero) false + (TypeChecker.Methods.withFuel 10000) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + change + Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.sort .zero) false + (TypeChecker.Methods.withFuel 9999) + annotatedPiCtorCandidateContext.toTypeChecker + ({} : TypeChecker.State)) = + .ok (.sort (.succ .zero)) + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + annotatedPiCtorCandidateContext, + AddInductive.Context.toTypeChecker, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind] + rfl + +private theorem annotatedPiConsumeRawDomain : + AddInductive.consumeTypeAnnotations annotatedPiRawDomainKernel = + .sort .zero := by + simp [AddInductive.consumeTypeAnnotations, annotatedPiRawDomainKernel] + +private theorem annotatedPiConsumeInner : + AddInductive.consumeTypeAnnotations annotatedPiInnerKernel = + annotatedPiInnerKernel := by + simp [AddInductive.consumeTypeAnnotations, annotatedPiInnerKernel] + +private theorem annotatedPiValidationInnerBodyContext_eq : + annotatedPiConstructorValidationContext.pushLocalDecl + `p .default + (AddInductive.consumeTypeAnnotations annotatedPiRawDomainKernel) = + annotatedPiInnerBodyCandidateContext := by + rw [annotatedPiConstructorValidationContext_def_eq, + annotatedPiConsumeRawDomain] + rfl + +private theorem annotatedPiValidationOuterBodyContext_eq : + annotatedPiConstructorValidationContext.pushLocalDecl + annotatedPiOuterName .default + (AddInductive.consumeTypeAnnotations annotatedPiInnerKernel) = + annotatedPiOuterBodyCandidateContext := by + rw [annotatedPiConstructorValidationContext_def_eq, + annotatedPiConsumeInner] + rfl + +private theorem annotatedPiValidationInnerBody_whnf_eq + {result : Expr} + (run : AddInductive.CandidateWhnfStep.Valid + ⟨({ annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env }).pushLocalDecl + `p .default (AddInductive.consumeTypeAnnotations + annotatedPiRawDomainKernel), + .const ``AnnotatedPi [], result⟩) : + result = .const ``AnnotatedPi [] := by + rw [annotatedPiConstructorValidationContext_eq, + annotatedPiConsumeRawDomain] at run + change TypeChecker.M.run annotatedPiInnerBodyCandidateContext.env + annotatedPiInnerBodyCandidateContext.safety + annotatedPiInnerBodyCandidateContext.lctx + annotatedPiInnerBodyCandidateContext.lparams + annotatedPiInnerBodyCandidateContext.fuel + (TypeChecker.whnf (.const ``AnnotatedPi [])) = .ok result at run + have known := annotatedPiInnerBodyCandidateStep_valid + change TypeChecker.M.run annotatedPiInnerBodyCandidateContext.env + annotatedPiInnerBodyCandidateContext.safety + annotatedPiInnerBodyCandidateContext.lctx + annotatedPiInnerBodyCandidateContext.lparams + annotatedPiInnerBodyCandidateContext.fuel + (TypeChecker.whnf (.const ``AnnotatedPi [])) = + .ok (.const ``AnnotatedPi []) at known + rw [known] at run + exact (Except.ok.inj run).symm + +private theorem constructorTypeValidationTrace_spineLength_zero + {stats : AddInductive.InductiveStats} {isUnsafe : Bool} + {familyIdx : Nat} {ctor : Name} {context : AddInductive.Context} + {source : Expr} {argIdx fuel : Nat} + (trace : AddInductive.ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context source argIdx fuel) + (terminal : source.isForall = false) : + trace.spineLength = 0 := by + cases trace <;> + simp_all [AddInductive.ConstructorTypeValidationTrace.spineLength, + Expr.isForall] + +private theorem constructorTypeValidationTrace_eq_terminal + {stats : AddInductive.InductiveStats} {isUnsafe : Bool} + {familyIdx : Nat} {ctor : Name} {context : AddInductive.Context} + {source : Expr} {argIdx fuel : Nat} + (trace : AddInductive.ConstructorTypeValidationTrace stats isUnsafe + familyIdx ctor context source argIdx (fuel + 1)) + (terminal : source.isForall = false) + (valid : AddInductive.isValidIndAppIdx stats source familyIdx = true) : + trace = .terminal context source fuel argIdx terminal valid := by + cases trace with + | parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeRun defeq tail => + have impossible : + (Expr.forallE name domain body binderInfo).isForall = true := rfl + rw [impossible] at terminal + contradiction + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureType universeTrace positivity tail => + have impossible : + (Expr.forallE name domain body binderInfo).isForall = true := rfl + rw [impossible] at terminal + contradiction + | terminal => rfl + +set_option maxHeartbeats 10000000 in +private def annotatedPiStagedPostFamilyInput : + VInductDecl.StagedNormalizationCandidatePostFamilyInput + annotatedPiFamilyCandidateContext annotatedPiCtorCandidateContext + outParamEnv [] annotatedPiNormalizationCandidate + annotatedPiRawDecl where + universeInput := annotatedPiStagedUniverseInput + alignment := by + change AddInductive.ConstructorCandidateAlignmentTrace + annotatedPiStagedUniverseInput.staged.family.validation.stats false 0 + annotatedPiConstructorValidationContext + annotatedPiStagedUniverseInput.staged.constructorValidation.trace + (.cons annotatedPiConstructorCandidate .nil) + generalize htrace : + annotatedPiStagedUniverseInput.staged.constructorValidation.trace = trace + cases trace with + | cons seen head constructors constructorFresh constructorClosed + constructorRootCheck typeTrace listTailTrace => + cases typeTrace with + | parameter context fuel argIdx name domain body binderInfo param + parameterType parameterAt parameterTypeRun defeq tail => + rw [annotatedPiStagedParams_zero] at parameterAt + contradiction + | terminal context source fuel argIdx terminal valid => + rw [annotatedPiKernelCtor_isForall] at terminal + contradiction + | ordinary context fuel argIdx name domain body binderInfo sortResult + noParameter ensureType universeTrace positivity tail => + cases listTailTrace + cases positivity with + | skipped isUnsafe_eq => contradiction + | safe isUnsafe_eq positivityTrace => + cases positivityTrace with + | absent context source result fuel whnf occurs => + change AddInductive.CandidateWhnfStep.Valid + ⟨{ annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env }, + annotatedPiInnerKernel, result⟩ at whnf + rw [annotatedPiConstructorValidationContext_eq] at whnf + change TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.whnf annotatedPiInnerKernel) = + .ok result at whnf + rw [annotatedPiInner_whnfM] at whnf + cases whnf + rw [annotatedPiStagedStats_eq, + annotatedPiInner_stats_hasIndOcc] at occurs + contradiction + | target context source result fuel targetIdx whnf occurs + terminal valid => + change AddInductive.CandidateWhnfStep.Valid + ⟨{ annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env }, + annotatedPiInnerKernel, result⟩ at whnf + rw [annotatedPiConstructorValidationContext_eq] at whnf + change TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.whnf annotatedPiInnerKernel) = + .ok result at whnf + rw [annotatedPiInner_whnfM] at whnf + cases whnf + simp [annotatedPiInnerKernel, Expr.isForall] at terminal + | forallE positivityContext positivitySource positivityFuel + positivityName positivityDomain positivityBody + positivityBinderInfo positivityWhnf positivityOccurs + positivityDomainFree positivityTail => + change AddInductive.CandidateWhnfStep.Valid + ⟨{ annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env }, + annotatedPiInnerKernel, + .forallE positivityName positivityDomain positivityBody + positivityBinderInfo⟩ at positivityWhnf + rw [annotatedPiConstructorValidationContext_eq] at positivityWhnf + change TypeChecker.M.run annotatedPiCtorCandidateContext.env + annotatedPiCtorCandidateContext.safety + annotatedPiCtorCandidateContext.lctx + annotatedPiCtorCandidateContext.lparams + annotatedPiCtorCandidateContext.fuel + (TypeChecker.whnf annotatedPiInnerKernel) = + .ok (.forallE positivityName positivityDomain + positivityBody positivityBinderInfo) at positivityWhnf + rw [annotatedPiInner_whnfM] at positivityWhnf + cases positivityWhnf + have hTailSpine : tail.spineLength = 0 := + constructorTypeValidationTrace_spineLength_zero tail (by + simp only [annotatedPiConst_instantiate1, + Expr.isForall]) + cases positivityTail with + | absent context source result fuel whnf occurs => + have whnf' : AddInductive.CandidateWhnfStep.Valid + ⟨({ annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env }).pushLocalDecl + `p .default (AddInductive.consumeTypeAnnotations + annotatedPiRawDomainKernel), + .const ``AnnotatedPi [], result⟩ := by + simpa only [annotatedPiConst_instantiate1] using whnf + have hresult := + annotatedPiValidationInnerBody_whnf_eq whnf' + subst result + rw [annotatedPiStagedStats_eq, + annotatedPiConst_hasIndOcc] at occurs + contradiction + | forallE context source fuel name domain body binderInfo + whnf occurs domainFree positivityTail => + have whnf' : AddInductive.CandidateWhnfStep.Valid + ⟨({ annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env }).pushLocalDecl + `p .default (AddInductive.consumeTypeAnnotations + annotatedPiRawDomainKernel), + .const ``AnnotatedPi [], + .forallE name domain body binderInfo⟩ := by + simpa only [annotatedPiConst_instantiate1] using whnf + have hresult := + annotatedPiValidationInnerBody_whnf_eq whnf' + contradiction + | target targetContext targetSource targetResult targetFuel + targetIdx targetWhnf targetOccurs targetTerminal + targetValid => + have targetWhnfNormalized : + AddInductive.CandidateWhnfStep.Valid + ⟨({ annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with + env := annotatedPiCtorCandidateContext.env }).pushLocalDecl + `p .default (AddInductive.consumeTypeAnnotations + annotatedPiRawDomainKernel), + .const ``AnnotatedPi [], targetResult⟩ := by + simpa only [annotatedPiConst_instantiate1] using + targetWhnf + have hresult := + annotatedPiValidationInnerBody_whnf_eq + targetWhnfNormalized + subst targetResult + simp only [annotatedPiConst_instantiate1] at tail ⊢ + cases tail + change AddInductive.CandidateCheckTypeObservation + annotatedPiConstructorValidationContext.withEmptyLocalContext + annotatedPiKernelCtor.type at constructorRootCheck + let rootChecked := + AddInductive.ConstructorCheckedExpr.ofClosedRoot + constructorClosed constructorRootCheck + let innerChecked : AddInductive.ConstructorCheckedExpr + annotatedPiCtorCandidateContext + annotatedPiInnerKernel := + .ofRun (by + simp [annotatedPiInnerKernel, + annotatedPiRawDomainKernel, FVarsIn, + Level.hasMVar']) + annotatedPiInnerCheckTypeStep_valid + let viewInnerChecked : AddInductive.ConstructorCheckedExpr + annotatedPiCtorCandidateContext + annotatedPiViewInnerKernel := + .ofRun (by + simp [annotatedPiViewInnerKernel, FVarsIn, + Level.hasMVar']) + annotatedPiViewInnerCheckTypeStep_valid + let domainChecked : AddInductive.ConstructorCheckedExpr + annotatedPiCtorCandidateContext + annotatedPiRawDomainKernel := + .ofRun (by + simp [annotatedPiRawDomainKernel, FVarsIn, + Level.hasMVar']) + annotatedPiDomainCheckTypeStep_valid + let sortChecked : AddInductive.ConstructorCheckedExpr + annotatedPiCtorCandidateContext (.sort .zero) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + annotatedPiSortZeroCheckTypeStep_valid + let innerBodyChecked : + AddInductive.ConstructorCheckedExpr + annotatedPiInnerBodyCandidateContext + (.const ``AnnotatedPi []) := + .ofRun (by simp [FVarsIn]) + annotatedPiInnerBodyCheckTypeStep_valid + let outerBodyChecked : + AddInductive.ConstructorCheckedExpr + annotatedPiOuterBodyCandidateContext + (.const ``AnnotatedPi []) := + .ofRun (by simp [FVarsIn]) + annotatedPiOuterBodyCheckTypeStep_valid + let innerChecked' := annotatedPiAlignChecked + annotatedPiConstructorValidationContext_def_eq rfl + innerChecked + let viewInnerChecked' := annotatedPiAlignChecked + annotatedPiConstructorValidationContext_def_eq + annotatedPiAlignedViewInnerKernel_eq viewInnerChecked + let consumedInnerChecked := annotatedPiAlignChecked + annotatedPiConstructorValidationContext_def_eq + annotatedPiConsumeInner innerChecked + let domainChecked' := annotatedPiAlignChecked + annotatedPiConstructorValidationContext_def_eq rfl + domainChecked + let sortChecked' := annotatedPiAlignChecked + annotatedPiConstructorValidationContext_def_eq + annotatedPiConsumeRawDomain sortChecked + let innerBodyChecked' := annotatedPiAlignChecked + annotatedPiValidationInnerBodyContext_eq rfl + innerBodyChecked + let innerBodyPositivityChecked := + annotatedPiAlignChecked + annotatedPiValidationInnerBodyContext_eq + (annotatedPiConst_instantiate1 + annotatedPiConstructorValidationContext.freshExpr) + innerBodyChecked + let outerBodyChecked' := annotatedPiAlignChecked + annotatedPiValidationOuterBodyContext_eq rfl + outerBodyChecked + let outerBodySourceChecked := annotatedPiAlignChecked + annotatedPiValidationOuterBodyContext_eq + (annotatedPiConst_instantiate1 + annotatedPiConstructorValidationContext.freshExpr) + outerBodyChecked + have outerTailView_eq : + ((Expr.const ``AnnotatedPi []).abstract + #[annotatedPiCtorCandidateContext.freshExpr] + |>.instantiate1 + annotatedPiConstructorValidationContext.freshExpr) = + .const ``AnnotatedPi [] := by + simp [annotatedPiConst_abstract_singleton] + let outerBodyViewChecked := annotatedPiAlignChecked + annotatedPiValidationOuterBodyContext_eq + outerTailView_eq outerBodyChecked + let innerAnnotations : + AddInductive.CandidateIsDefEqObservation + annotatedPiCtorCandidateContext + annotatedPiInnerKernel annotatedPiInnerKernel := + ⟨AddInductive.candidateIsDefEqRefl + annotatedPiCtorCandidateContext + annotatedPiInnerKernel⟩ + let innerAnnotations' := annotatedPiAlignIsDefEq + annotatedPiConstructorValidationContext_def_eq rfl + annotatedPiConsumeInner innerAnnotations + let domainAnnotations : + AddInductive.CandidateIsDefEqObservation + annotatedPiCtorCandidateContext + annotatedPiRawDomainKernel (.sort .zero) := + ⟨annotatedPiDomainAnnotationsEq⟩ + let domainAnnotations' := annotatedPiAlignIsDefEq + annotatedPiConstructorValidationContext_def_eq rfl + annotatedPiConsumeRawDomain domainAnnotations + have sortCheckedInferred : + sortChecked'.observation.inferred = + .sort (.succ .zero) := by + apply sortChecked'.inferred_eq_of_run + rw [annotatedPiConstructorValidationContext_def_eq, + annotatedPiConsumeRawDomain] + exact annotatedPiSortZeroCheckTypeStep_valid + have rootStoredSpine : + annotatedPiConstructorCandidate.type.trace.storedSpine = + true := by + change annotatedPiCtorCandidate.trace.storedSpine = true + exact annotatedPiCtorCandidate_storedSpine + have rootDepth : + annotatedPiConstructorCandidate.type.context.fuel.recDepth = + annotatedPiConstructorValidationContext.fuel.recDepth := by + rfl + let constructorTailTrace := + AddInductive.ConstructorTypeValidationTrace.terminal + (stats := annotatedPiStagedUniverseInput.staged.family.validation.stats) + (isUnsafe := false) (familyIdx := 0) + (ctor := annotatedPiKernelCtor.name) + (annotatedPiConstructorValidationContext.pushLocalDecl + annotatedPiOuterName .default + (AddInductive.consumeTypeAnnotations + annotatedPiInnerKernel)) + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiConstructorValidationContext.freshExpr) + 998 1 + (by + simp only [annotatedPiConst_instantiate1, + Expr.isForall]) + (by + simp only [annotatedPiConst_instantiate1] + assumption) + have tail_eq : tail = constructorTailTrace := by + unfold constructorTailTrace + apply constructorTypeValidationTrace_eq_terminal + let positivityTargetTrace := + AddInductive.ConstructorPositivityTrace.target + (stats := annotatedPiStagedUniverseInput.staged.family.validation.stats) + (ctor := annotatedPiKernelCtor.name) + (argIdx := 0) + (annotatedPiConstructorValidationContext.pushLocalDecl + `p .default + (AddInductive.consumeTypeAnnotations + annotatedPiRawDomainKernel)) + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiConstructorValidationContext.freshExpr) + (.const ``AnnotatedPi []) 998 targetIdx + targetWhnf targetOccurs targetTerminal targetValid + let nestedPositivityTrace := + AddInductive.ConstructorPositivityTrace.forallE + (stats := annotatedPiStagedUniverseInput.staged.family.validation.stats) + (ctor := annotatedPiKernelCtor.name) + (argIdx := 0) + annotatedPiConstructorValidationContext + annotatedPiInnerKernel 999 `p + annotatedPiRawDomainKernel + (.const ``AnnotatedPi []) .default positivityWhnf + positivityOccurs positivityDomainFree + positivityTargetTrace + let positivityModeTrace := + AddInductive.ConstructorPositivityModeTrace.safe + isUnsafe_eq nestedPositivityTrace + let headValidationTrace := + AddInductive.ConstructorTypeValidationTrace.ordinary + annotatedPiConstructorValidationContext 999 0 + annotatedPiOuterName annotatedPiInnerKernel + (.const ``AnnotatedPi []) .default sortResult + noParameter ensureType universeTrace + positivityModeTrace constructorTailTrace + have rootSpineLength' : + annotatedPiConstructorCandidate.type.trace.spineLength = + headValidationTrace.spineLength := by + rfl + have positivityTargetAlignment : + AddInductive.ConstructorPositivityAlignmentTrace + positivityTargetTrace := + .target innerBodyPositivityChecked + have positivityAlignment : + AddInductive.ConstructorPositivityModeAlignmentTrace + positivityModeTrace := + .safe <| .forallE innerChecked' domainChecked' + sortChecked' (.succ .zero) + sortCheckedInferred (by + rw [annotatedPiConstructorValidationContext_def_eq] + exact annotatedPiCtorCandidateFresh) + domainAnnotations' positivityTargetTrace + positivityTargetAlignment + have outerTailAlignment : + AddInductive.ConstructorViewAlignmentTrace + constructorTailTrace + ((Expr.const ``AnnotatedPi []).abstract + #[annotatedPiCtorCandidateContext.freshExpr] + |>.instantiate1 + annotatedPiConstructorValidationContext.freshExpr) := by + simp only [annotatedPiConst_abstract_singleton, + annotatedPiConst_instantiate1] + exact .terminal outerBodySourceChecked + outerBodyChecked' + (by simp [Expr.isForall]) (by assumption) + have headAlignment : + AddInductive.ConstructorViewAlignmentTrace + headValidationTrace + annotatedPiConstructorCandidate.type.view := by + change AddInductive.ConstructorViewAlignmentTrace + headValidationTrace + annotatedPiAlignedViewCtorKernel + exact AddInductive.ConstructorViewAlignmentTrace.ordinary + innerChecked' viewInnerChecked' + ⟨annotatedPiInnerView_isDefEq⟩ + consumedInnerChecked + positivityModeTrace + positivityAlignment (by + rw [annotatedPiConstructorValidationContext_def_eq] + exact annotatedPiCtorCandidateFresh) + innerAnnotations' constructorTailTrace + outerTailAlignment + rw [tail_eq] + exact + AddInductive.ConstructorCandidateAlignmentTrace.cons + (seen := ∅) (fresh := constructorFresh) + (closed := constructorClosed) + (rootCheck := constructorRootCheck) + (typeTrace := headValidationTrace) + (tailTrace := + AddInductive.ConstructorListValidationTrace.nil + ((∅ : NameSet).insert + annotatedPiKernelCtor.name)) + (candidate := annotatedPiConstructorCandidate) + (candidates := AddInductive.CandidateList.nil) + rootChecked rootStoredSpine rootSpineLength' + rootDepth headAlignment + (AddInductive.ConstructorCandidateAlignmentTrace.nil + (stats := annotatedPiStagedUniverseInput.staged.family.validation.stats) + (isUnsafe := false) (familyIdx := 0) + (context := annotatedPiConstructorValidationContext) + ((∅ : NameSet).insert + annotatedPiKernelCtor.name)) + +private theorem annotatedPiPreFamilySortZeroCheckTypeStep_valid + (context : AddInductive.Context) + (depth : context.fuel.recDepth = 10000) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, .sort .zero, .sort (.succ .zero)⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType (.sort .zero) false + (TypeChecker.Methods.withFuel context.fuel.recDepth) + context.toTypeChecker ({} : TypeChecker.State)) = _ + rw [depth] + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.sort .zero) false + (TypeChecker.Methods.withFuel 9999) + context.toTypeChecker ({} : TypeChecker.State)) = _ + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + annotatedPi_checkLevelZero, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rfl + +private theorem annotatedPiPreFamilySortOneCheckTypeStep_valid + (context : AddInductive.Context) + (depth : context.fuel.recDepth = 10000) : + AddInductive.CandidateCheckTypeStep.Valid + ⟨context, .sort (.succ .zero), + .sort (.succ (.succ .zero))⟩ := by + unfold AddInductive.CandidateCheckTypeStep.Valid + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType (.sort (.succ .zero)) false + (TypeChecker.Methods.withFuel context.fuel.recDepth) + context.toTypeChecker ({} : TypeChecker.State)) = _ + rw [depth] + change Except.map (fun x : Expr × TypeChecker.State => x.1) + (TypeChecker.Inner.inferType' (.sort (.succ .zero)) false + (TypeChecker.Methods.withFuel 9999) + context.toTypeChecker ({} : TypeChecker.State)) = _ + unfold TypeChecker.Inner.inferType' + simp [Expr.hasLooseBVars, Expr.looseBVarRange', + annotatedPi_checkLevelSuccZero, Bind.bind, ReaderT.bind, + StateT.bind, Except.bind] + rfl + +private def annotatedPiPreFamilySortZeroInferState : TypeChecker.State := + { ({} : TypeChecker.State) with + inferTypeI := ({} : TypeChecker.State).inferTypeI.insert + (.sort .zero) (.sort (.succ .zero)) } + +private theorem annotatedPiPreFamilySortZeroInferTypeInner + (context : AddInductive.Context) + (depth : context.fuel.recDepth = 10000) : + TypeChecker.Inner.inferType (.sort .zero) true + (TypeChecker.Methods.withFuel context.fuel.recDepth) + context.toTypeChecker ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), + annotatedPiPreFamilySortZeroInferState) := by + rw [depth] + change TypeChecker.Inner.inferType' (.sort .zero) true + (TypeChecker.Methods.withFuel 9999) context.toTypeChecker + ({} : TypeChecker.State) = _ + unfold TypeChecker.Inner.inferType' + simp [annotatedPiPreFamilySortZeroInferState, + Expr.hasLooseBVars, Expr.looseBVarRange', Bind.bind, + ReaderT.bind, StateT.bind, Except.bind] + +private theorem annotatedPiPreFamilySortZeroEnsureTypeStep_valid + (context : AddInductive.Context) + (depth : context.fuel.recDepth = 10000) : + AddInductive.ConstructorEnsureTypeStep.Valid + ⟨context, .sort .zero, .sort (.succ .zero)⟩ := by + unfold AddInductive.ConstructorEnsureTypeStep.Valid + TypeChecker.ensureType TypeChecker.inferType TypeChecker.ensureSort + TypeChecker.RecM.run TypeChecker.M.run + simp only [readThe, MonadReaderOf.read, ReaderT.read, + Bind.bind, ReaderT.bind, StateT.bind, Except.bind, + Pure.pure, StateT.pure, Except.pure, StateT.run', + Functor.map, Except.map] + rw [show TypeChecker.Inner.inferType (.sort .zero) true + (TypeChecker.Methods.withFuel context.fuel.recDepth) + { env := context.env + lctx := context.lctx + safety := context.safety + lparams := context.lparams + fuel := context.fuel } + ({} : TypeChecker.State) = + .ok (.sort (.succ .zero), + annotatedPiPreFamilySortZeroInferState) by + simpa [AddInductive.Context.toTypeChecker] using + annotatedPiPreFamilySortZeroInferTypeInner context depth] + rfl + +private theorem annotatedPiPreFamilySafetyRun : + AddInductive.checkConstructorPreFamilySafety + annotatedPiStagedUniverseInput.staged.family.validation.stats + annotatedPiNormalizationCandidate.families.singleton.familyType.type.view + annotatedPiNormalizationCandidate.families.singleton.constructors + annotatedPiNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext = + .ok () := by + change AddInductive.checkConstructorPreFamilySafety + annotatedPiInductiveStats (.sort (.succ .zero)) + (.cons annotatedPiConstructorCandidate .nil) + annotatedPiFamilyCandidateContext = .ok () + have consumeSortZero : AddInductive.consumeTypeAnnotations + (.sort .zero) = .sort .zero := by + simp [AddInductive.consumeTypeAnnotations] + let nestedContext := annotatedPiFamilyCandidateContext.pushLocalDecl + `p .default (AddInductive.consumeTypeAnnotations (.sort .zero)) + let resultContext := annotatedPiFamilyCandidateContext.advanceFresh + let rootSortZero : AddInductive.ConstructorCheckedExpr + annotatedPiFamilyCandidateContext (.sort .zero) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + (annotatedPiPreFamilySortZeroCheckTypeStep_valid + annotatedPiFamilyCandidateContext rfl) + let rootSortOne : AddInductive.ConstructorCheckedExpr + annotatedPiFamilyCandidateContext (.sort (.succ .zero)) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + (annotatedPiPreFamilySortOneCheckTypeStep_valid + annotatedPiFamilyCandidateContext rfl) + let nestedSortOne : AddInductive.ConstructorCheckedExpr + nestedContext (.sort (.succ .zero)) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + (annotatedPiPreFamilySortOneCheckTypeStep_valid nestedContext rfl) + let resultSortOne : AddInductive.ConstructorCheckedExpr + resultContext (.sort (.succ .zero)) := + .ofRun (by simp [FVarsIn, Level.hasMVar']) + (annotatedPiPreFamilySortOneCheckTypeStep_valid resultContext rfl) + let rootEnsure : AddInductive.ConstructorEnsureTypeObservation + annotatedPiFamilyCandidateContext (.sort .zero) := + ⟨.sort (.succ .zero), + annotatedPiPreFamilySortZeroEnsureTypeStep_valid + annotatedPiFamilyCandidateContext rfl⟩ + let consumedSortZero : AddInductive.ConstructorCheckedExpr + annotatedPiFamilyCandidateContext + (AddInductive.consumeTypeAnnotations (.sort .zero)) := by + rw [consumeSortZero] + exact rootSortZero + let annotations : AddInductive.CandidateIsDefEqObservation + annotatedPiFamilyCandidateContext (.sort .zero) + (AddInductive.consumeTypeAnnotations (.sort .zero)) := + ⟨by + rw [consumeSortZero] + exact AddInductive.candidateIsDefEqRefl + annotatedPiFamilyCandidateContext (.sort .zero)⟩ + have rootFresh : annotatedPiFamilyCandidateContext.lctx.find? + annotatedPiFamilyCandidateContext.freshFVarId = none := by + have h := LocalContext.WF.find?_eq_find?_toList + (fv := annotatedPiFamilyCandidateContext.freshFVarId) + LocalContext.WF.nil + change + ({ fvarIdToDecl := PersistentHashMap.empty + decls := PersistentArray.empty + auxDeclToFullName := Std.TreeMap.empty } : LocalContext).find? + annotatedPiFamilyCandidateContext.freshFVarId = none + rw [h] + simp [LocalContext.toList] + let rootSpine : AddInductive.ConstructorPreFamilyIndexSpineTrace + annotatedPiFamilyCandidateContext (.sort (.succ .zero)) [] := + .nil annotatedPiFamilyCandidateContext (.sort (.succ .zero)) + rootSortOne rfl + let nestedSpine : AddInductive.ConstructorPreFamilyIndexSpineTrace + nestedContext (.sort (.succ .zero)) [] := + .nil nestedContext (.sort (.succ .zero)) nestedSortOne rfl + let resultSpine : AddInductive.ConstructorPreFamilyIndexSpineTrace + resultContext (.sort (.succ .zero)) [] := + .nil resultContext (.sort (.succ .zero)) resultSortOne rfl + have valid : AddInductive.isValidIndAppIdx annotatedPiInductiveStats + (.const ``AnnotatedPi []) 0 = true := + annotatedPiConst_isValidIndAppIdx + have targetArgs : + (Expr.const ``AnnotatedPi []).getAppArgs.toList.drop + annotatedPiInductiveStats.params.size = [] := by + rfl + obtain ⟨nestedTargetSpine, nestedTargetSpineRun⟩ : + ∃ nestedTargetSpine : + AddInductive.ConstructorPreFamilyIndexSpineTrace nestedContext + (.sort (.succ .zero)) + ((Expr.const ``AnnotatedPi []).getAppArgs.toList.drop + annotatedPiInductiveStats.params.size), + AddInductive.ConstructorPreFamilyIndexSpineTrace.build nestedContext + (.sort (.succ .zero)) + ((Expr.const ``AnnotatedPi []).getAppArgs.toList.drop + annotatedPiInductiveStats.params.size) = + .ok nestedTargetSpine := by + rw [targetArgs] + exact ⟨nestedSpine, nestedSpine.build_eq⟩ + let targetTrace : AddInductive.ConstructorPreFamilyRecursiveTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) nestedContext + (.const ``AnnotatedPi []) 999 := + .target nestedContext (.const ``AnnotatedPi []) valid nestedTargetSpine + have targetRun : + AddInductive.ConstructorPreFamilyRecursiveTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) nestedContext + (.const ``AnnotatedPi []) 999 = .ok targetTrace := by + simp only [AddInductive.ConstructorPreFamilyRecursiveTrace.build] + rw [dif_pos valid, nestedTargetSpineRun] + rfl + obtain ⟨recursiveTailTrace, recursiveTailRun⟩ : + ∃ recursiveTailTrace : + AddInductive.ConstructorPreFamilyRecursiveTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) nestedContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiFamilyCandidateContext.freshExpr) 999, + AddInductive.ConstructorPreFamilyRecursiveTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) nestedContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiFamilyCandidateContext.freshExpr) 999 = + .ok recursiveTailTrace := by + rw [annotatedPiConst_instantiate1] + exact ⟨targetTrace, targetRun⟩ + let recursiveTrace : AddInductive.ConstructorPreFamilyRecursiveTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext annotatedPiViewInnerKernel + annotatedPiFamilyCandidateContext.fuel.inductiveFuel := + .forallE annotatedPiFamilyCandidateContext `p (.sort .zero) + (.const ``AnnotatedPi []) .default rootSortZero rootEnsure + consumedSortZero annotations rootFresh (by + simpa only [nestedContext] using recursiveTailTrace) + have recursiveRun : + AddInductive.ConstructorPreFamilyRecursiveTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext annotatedPiViewInnerKernel + annotatedPiFamilyCandidateContext.fuel.inductiveFuel = + .ok recursiveTrace := by + change AddInductive.ConstructorPreFamilyRecursiveTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext annotatedPiViewInnerKernel 1000 = + .ok recursiveTrace + simp only [annotatedPiViewInnerKernel, + AddInductive.ConstructorPreFamilyRecursiveTrace.build] + rw [rootSortZero.check_eq, rootEnsure.observe_eq, + consumedSortZero.check_eq] + simp only [Bind.bind, Except.bind] + rw [annotations.observe_eq] + simp only [] + rw [dif_pos rootFresh] + rw [recursiveTailRun] + rfl + have resultIndependent : AddInductive.constructorIndependentOf + (.const ``AnnotatedPi []) + [annotatedPiFamilyCandidateContext.freshFVarId] = true := by + rfl + obtain ⟨resultTargetSpine, resultTargetSpineRun⟩ : + ∃ resultTargetSpine : + AddInductive.ConstructorPreFamilyIndexSpineTrace resultContext + (.sort (.succ .zero)) + ((Expr.const ``AnnotatedPi []).getAppArgs.toList.drop + annotatedPiInductiveStats.params.size), + AddInductive.ConstructorPreFamilyIndexSpineTrace.build resultContext + (.sort (.succ .zero)) + ((Expr.const ``AnnotatedPi []).getAppArgs.toList.drop + annotatedPiInductiveStats.params.size) = + .ok resultTargetSpine := by + rw [targetArgs] + exact ⟨resultSpine, resultSpine.build_eq⟩ + let terminalTrace : AddInductive.ConstructorPreFamilyViewTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) resultContext + (.const ``AnnotatedPi []) 1 + [annotatedPiFamilyCandidateContext.freshFVarId] true := + .terminal resultContext (.const ``AnnotatedPi []) 1 + [annotatedPiFamilyCandidateContext.freshFVarId] true valid + resultIndependent resultTargetSpine + have terminalRun : + AddInductive.ConstructorPreFamilyViewTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) resultContext + (.const ``AnnotatedPi []) 1 + [annotatedPiFamilyCandidateContext.freshFVarId] true 999 = + .ok terminalTrace := by + simp only [AddInductive.ConstructorPreFamilyViewTrace.build] + rw [dif_pos valid, dif_pos resultIndependent, resultTargetSpineRun] + rfl + obtain ⟨viewTailTrace, viewTailRun⟩ : + ∃ viewTailTrace : AddInductive.ConstructorPreFamilyViewTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) resultContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiFamilyCandidateContext.freshExpr) + 1 [annotatedPiFamilyCandidateContext.freshFVarId] true, + AddInductive.ConstructorPreFamilyViewTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) resultContext + ((Expr.const ``AnnotatedPi []).instantiate1 + annotatedPiFamilyCandidateContext.freshExpr) + 1 [annotatedPiFamilyCandidateContext.freshFVarId] true 999 = + .ok viewTailTrace := by + rw [annotatedPiConst_instantiate1] + exact ⟨terminalTrace, terminalRun⟩ + have noParameter : annotatedPiInductiveStats.params[0]? = none := rfl + have recursive : AddInductive.hasIndOcc annotatedPiInductiveStats.indConsts + annotatedPiViewInnerKernel = true := by + simp [AddInductive.hasIndOcc, annotatedPiInductiveStats, + annotatedPiViewInnerKernel, Expr.constName!] + have fieldIndependent : AddInductive.constructorIndependentOf + annotatedPiViewInnerKernel [] = true := by + simp [AddInductive.constructorIndependentOf, + annotatedPiViewInnerKernel] + let viewTrace : AddInductive.ConstructorPreFamilyViewTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext annotatedPiViewCtorKernel 0 [] false := + .recursive annotatedPiFamilyCandidateContext 0 [] false + annotatedPiOuterName annotatedPiViewInnerKernel + (.const ``AnnotatedPi []) .default noParameter recursive + fieldIndependent recursiveTrace rootFresh (by + simpa only [resultContext] using viewTailTrace) + have viewRun : + AddInductive.ConstructorPreFamilyViewTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext annotatedPiViewCtorKernel 0 [] + false 1000 = .ok viewTrace := by + simp only [annotatedPiViewCtorKernel, + AddInductive.ConstructorPreFamilyViewTrace.build] + split + · rename_i parameter parameterAt + rw [noParameter] at parameterAt + contradiction + · split + · rename_i nonrecursive + rw [recursive] at nonrecursive + contradiction + · rw [dif_pos fieldIndependent] + rw [recursiveRun] + simp only [Bind.bind, Except.bind] + rw [dif_pos rootFresh] + rw [viewTailRun] + rfl + have candidateViewEq : annotatedPiConstructorCandidate.type.view = + annotatedPiViewCtorKernel := by + change annotatedPiCtorCandidate.trace.view = annotatedPiViewCtorKernel + change annotatedPiAlignedViewCtorKernel = annotatedPiViewCtorKernel + exact annotatedPiAlignedViewCtorKernel_eq + obtain ⟨headTrace, headRun⟩ : + ∃ headTrace : AddInductive.ConstructorPreFamilyViewTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext + annotatedPiConstructorCandidate.type.view 0 [] false, + AddInductive.ConstructorPreFamilyViewTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext + annotatedPiConstructorCandidate.type.view 0 [] false 1000 = + .ok headTrace := by + rw [candidateViewEq] + exact ⟨viewTrace, viewRun⟩ + let listTrace : AddInductive.ConstructorPreFamilyListTrace + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext + (.cons annotatedPiConstructorCandidate .nil) := + .cons headTrace .nil + have listRun : + AddInductive.ConstructorPreFamilyListTrace.build + annotatedPiInductiveStats 0 (.sort (.succ .zero)) + annotatedPiFamilyCandidateContext + (.cons annotatedPiConstructorCandidate .nil) = .ok listTrace := by + simp only [AddInductive.ConstructorPreFamilyListTrace.build] + rw [show annotatedPiFamilyCandidateContext.fuel.inductiveFuel = 1000 by + rfl, headRun] + rfl + have parametersRun : AddInductive.instantiateFamilyParameters + (.sort (.succ .zero)) annotatedPiInductiveStats.params.toList = + .ok (.sort (.succ .zero)) := by + rfl + unfold AddInductive.checkConstructorPreFamilySafety + have translationUnique : + (AddInductive.theoryTranslationUnique (.sort (.succ .zero)) && + (AddInductive.CandidateList.cons annotatedPiConstructorCandidate + (AddInductive.CandidateList.nil : AddInductive.CandidateList + AddInductive.CandidateConstructor [])).viewTranslationUnique) = + true := by + simp [AddInductive.theoryTranslationUnique, + AddInductive.CandidateList.viewTranslationUnique, + AddInductive.CandidateExprTrace.viewTranslationUnique, + AddInductive.CandidateExprTrace.view, + annotatedPiConstructorCandidate, annotatedPiCtorCandidate, + annotatedPiCtorCandidateTrace, annotatedPiInnerCandidateTrace, + annotatedPiDomainCandidateTrace, annotatedPiInnerBodyCandidateTrace, + annotatedPiOuterBodyCandidateTrace, + annotatedPiConst_abstract_singleton] + rw [if_pos translationUnique] + rw [parametersRun] + simp only [Bind.bind, Except.bind] + rw [listRun] + rfl + +private def annotatedPiStagedPreFamilyInput : + VInductDecl.StagedNormalizationCandidatePreFamilyInput + annotatedPiFamilyCandidateContext annotatedPiCtorCandidateContext + outParamEnv [] annotatedPiNormalizationCandidate annotatedPiRawDecl := + VInductDecl.StagedNormalizationCandidatePreFamilyInput.ofRun + annotatedPiStagedPostFamilyInput annotatedPiPreFamilySafetyRun + +/-- AnnotatedPi's retained validator telescope and candidate telescope admit +the complete post-family semantic interpretation, including the nested +annotation-bearing recursive field. -/ +theorem annotatedPiProducedPostFamilySemantic_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidatePostFamilySemanticRun + annotatedPiStagedPostFamilyInput) := + annotatedPiStagedPostFamilyInput.exists + +/-- AnnotatedPi's recursive outer field is omitted from the pre-family local +context while its nested Pi binder and both family-index spines receive the +exact verified family-free interpretation. -/ +theorem annotatedPiProducedPreFamilySemantic_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidatePreFamilySemanticRun + annotatedPiStagedPreFamilyInput) := + annotatedPiStagedPreFamilyInput.exists + +/-- The exact family/constructor producer traversals and verified translations +automatically determine the complete retained AnnotatedPi hierarchy, including +its nested annotation-consuming constructor trace. -/ +theorem annotatedPiProducedSemanticHierarchy_exists : + Nonempty (VInductDecl.ProducedNormalizationCandidateSemanticRun + annotatedPiFamilyCandidateContext annotatedPiCtorCandidateContext + outParamEnv [] annotatedPiNormalizationCandidate + annotatedPiRawDecl) := + annotatedPiStagedUniverseInput.exists + +def annotatedPiNormalizationCandidateRun : + VInductDecl.NormalizationCandidateRun outParamEnv [] + annotatedPiNormalizationCandidate annotatedPiRawDecl where + raw := annotatedPiRawType + raw_types_eq := rfl + uvars_eq := rfl + family := annotatedPiCandidateFamilyRun + +example : annotatedPiNormalizationCandidateRun.viewDecl = + annotatedPiViewDecl := rfl + +theorem annotatedPiCandidateNormalization_eq : + annotatedPiNormalizationCandidateRun.normalization = + annotatedPiNormalization := rfl + +def annotatedPiNormalizationRun : + VInductDecl.NormalizationRun annotatedPiNormalization outParamEnv := by + simpa only [annotatedPiCandidateNormalization_eq] using + annotatedPiNormalizationCandidateRun.normalizationRun + +theorem annotatedPiNormalization_wf_checked : + annotatedPiNormalization.WF outParamEnv := + annotatedPiNormalizationRun.wf + +theorem annotatedPiBlock_wf_checked : + annotatedPiBlock.WF outParamEnv := by + refine ⟨annotatedPiNormalization_wf_checked, ?_⟩ + exact annotatedPiViewChecked_wf + +private theorem annotatedPiCandidate_generationShape : + VInductDecl.normalizationCandidateGenerationShape annotatedPiRawDecl + annotatedPiRawType annotatedPiNormalizationCandidate = true := by + change ((true && true) && + (annotatedPiCtorCandidate.trace.storedSpine && true && true)) = true + rw [annotatedPiCtorCandidate_storedSpine] + rfl + +private def annotatedPiProducedGenerationShapeCandidate : + VInductDecl.ProducedGenerationShapeCandidate annotatedPiRawDecl + annotatedPiRawType annotatedPiKernelType 0 false + annotatedPiFamilyCandidateContext where + candidate := annotatedPiNormalizationCandidate + produced := annotatedPiNormalizationCandidate_produced + shape := annotatedPiCandidate_generationShape + +/-- The strengthened outer gate retains AnnotatedPi's nested annotation- +normalizing candidate only after its complete raw generation spine passes. -/ +theorem annotatedPiGenerationShapeCandidate_produced : + VInductDecl.produceGenerationShapeCandidate annotatedPiRawDecl + annotatedPiRawType annotatedPiKernelType 0 false + annotatedPiFamilyCandidateContext = + .ok annotatedPiProducedGenerationShapeCandidate := by + have produced : + AddInductive.buildNormalizationCandidate annotatedPiRawDecl.nparams + [annotatedPiKernelType] 0 false annotatedPiFamilyCandidateContext = + .ok annotatedPiNormalizationCandidate := + annotatedPiNormalizationCandidate_produced + simpa only [annotatedPiProducedGenerationShapeCandidate] using + VInductDecl.produceGenerationShapeCandidate_eq_ok + (source := annotatedPiRawDecl) (raw := annotatedPiRawType) + produced annotatedPiCandidate_generationShape + +private theorem annotatedPiCandidate_analysis + (normalization : VInductDecl.NormalizationCandidateSemanticRun + outParamEnv [] annotatedPiNormalizationCandidate + annotatedPiRawDecl) : + normalization.root.normalization.generation? = + some annotatedPiGenerationChecked := by + let reference : VInductDecl.NormalizationCandidateSemanticRun outParamEnv [] + annotatedPiNormalizationCandidate annotatedPiRawDecl := { + raw := annotatedPiRawType + raw_types_eq := rfl + uvars_eq := rfl + family := annotatedPiCandidateFamilySemanticRun } + rw [annotatedPiStagedPreFamilyInput.normalization_eq normalization reference] + rfl + +/-- AnnotatedPi's nested annotation-normalizing candidate closes through the +same generic staged-owner boundary as the ordinary singleton fixture. -/ +theorem annotatedPiExactProducedGenerationCandidatePackage_exists : + Nonempty (VInductDecl.ExactProducedGenerationCandidatePackage + outParamEnv [] annotatedPiProducedGenerationShapeCandidate + annotatedPiGenerationChecked) := + annotatedPiProducedGenerationShapeCandidate.exactProducedPackage_nonempty + annotatedPiStagedPreFamilyInput rfl annotatedPiGenerationChecked + annotatedPiCandidate_analysis + +private def + annotatedPiExactProducedGenerationCandidatePackage : + VInductDecl.ExactProducedGenerationCandidatePackage outParamEnv [] + annotatedPiProducedGenerationShapeCandidate annotatedPiGenerationChecked := + annotatedPiProducedGenerationShapeCandidate.exactProducedPackage + annotatedPiStagedPreFamilyInput rfl annotatedPiGenerationChecked + annotatedPiCandidate_analysis + +/-- Complete source-indexed checker certificate for annotated recursive-Π +generation. This is the first live generation run whose main constructor +spine contains an annotation-normalized recursive function domain. -/ +def annotatedPiGenerationCandidateSemanticRun : + VInductDecl.GenerationCandidateSemanticRun + annotatedPiExactProducedGenerationCandidatePackage.normalization + annotatedPiGenerationChecked := + annotatedPiExactProducedGenerationCandidatePackage.semantic + +def annotatedPiGenerationCandidateRun : + VInductDecl.GenerationCandidateRun + annotatedPiExactProducedGenerationCandidatePackage.normalization.root + annotatedPiGenerationChecked := + annotatedPiGenerationCandidateSemanticRun.run + +/-- Complete dependent producer package for the annotation-bearing recursive +Π candidate. -/ +def annotatedPiGenerationCandidatePackage : + VInductDecl.GenerationCandidatePackage outParamEnv [] := + annotatedPiGenerationCandidateSemanticRun.package + +/-- The complete AnnotatedPi semantic package is selected by the exact +successful whole-call metadata producer, including its nested annotation- +consuming traversal in the post-family environment. -/ +def annotatedPiProducedGenerationCandidatePackage : + VInductDecl.ProducedGenerationCandidatePackage outParamEnv [] := + annotatedPiExactProducedGenerationCandidatePackage.package + +/-- Theory-only erasure consumed by the public certified transaction. -/ +def annotatedPiGenerationCertificate : + annotatedPiRawDecl.GenerationCertificate outParamEnv where + generation := annotatedPiGenerationChecked + wf := annotatedPiExactProducedGenerationCandidatePackage.semantic.run.wf + +def annotatedPiGenerationRun : + VInductDecl.GenerationRun annotatedPiGenerationChecked outParamEnv := + annotatedPiProducedGenerationCandidatePackage.package.run.generationRun + +theorem annotatedPiGenerationChecked_wf_checked : + annotatedPiGenerationChecked.WF outParamEnv := + annotatedPiGenerationCertificate.wf + +def annotatedPiCtorEnv : VEnv := + (annotatedPiTypeEnv.addConst annotatedPiRawType.ctors[0].name + annotatedPiRawType.ctors[0].toVConstant).get! + +def annotatedPiRecEnv : VEnv := + (annotatedPiCtorEnv.addConst ``AnnotatedPi.rec + annotatedPiGenerationChecked.recursor).get! + +def annotatedPiFinalEnv : VEnv := + (outParamEnv.addInductGeneration + annotatedPiGenerationChecked).get (by decide) + +theorem annotatedPi_addInductGeneration : + outParamEnv.addInductGeneration annotatedPiGenerationChecked = + some annotatedPiFinalEnv := rfl + +/-- The public proof-carrying path accepts the non-identity AnnotatedPi view +while computing exactly the established mixed Theory transaction. -/ +theorem annotatedPi_addInductCertified : + outParamEnv.addInductCertified annotatedPiGenerationCertificate = + some annotatedPiFinalEnv := + annotatedPi_addInductGeneration + +theorem annotatedPiCertified_ordered : annotatedPiFinalEnv.Ordered := + VEnv.addInductCertified_WF outParamEnv_ordered + annotatedPi_addInductCertified + +private theorem annotatedPiRawCtor_wf : + annotatedPiRawType.ctors[0].toVConstant.WF + annotatedPiTypeEnv := + ⟨.succ .zero, annotatedPiRawCtor_hasType⟩ + +private theorem annotatedPiCtorEnv_ordered : + annotatedPiCtorEnv.Ordered := + .const (n := annotatedPiRawType.ctors[0].name) + (ci := annotatedPiRawType.ctors[0].toVConstant) + annotatedPiTypeEnv_ordered annotatedPiRawCtor_wf rfl + +private theorem annotatedPiGenerationEnv : + VInductDecl.GenerationEnv annotatedPiGenerationChecked + annotatedPiCtorEnv := by + apply annotatedPiGenerationChecked_wf_checked.toGenerationEnv + (envT := annotatedPiTypeEnv) + · rfl + · exact (VEnv.addConst_le (show + outParamEnv.addConst annotatedPiRawType.name + annotatedPiRawType.toVConstant = some annotatedPiTypeEnv from rfl)).trans + (VEnv.addConst_le (show + annotatedPiTypeEnv.addConst annotatedPiRawType.ctors[0].name + annotatedPiRawType.ctors[0].toVConstant = + some annotatedPiCtorEnv from rfl)) + · exact VEnv.addConst_le (show + annotatedPiTypeEnv.addConst annotatedPiRawType.ctors[0].name + annotatedPiRawType.ctors[0].toVConstant = + some annotatedPiCtorEnv from rfl) + · exact annotatedPiCtorEnv_ordered + · rfl + · intro ctor hctor + change ctor ∈ + [⟨annotatedPiRawType.ctors[0], + annotatedPiViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + rfl + +private theorem annotatedPiMkInfo_tr : + TrConstVal .safe annotatedPiTypeEnv annotatedPiMkInfo + annotatedPiRawType.ctors[0] := by + exact ⟨⟨by decide, rfl, annotatedPiCtorSource_tr⟩, rfl⟩ + +private theorem annotatedPiRecInfo_tr : + TrConstVal .safe annotatedPiCtorEnv annotatedPiRecInfo + (inductGenerationRecVal annotatedPiGenerationChecked) := by + have hfamily : annotatedPiCtorEnv.constants ``AnnotatedPi = + some annotatedPiRawType.toVConstant := rfl + have hmk : annotatedPiCtorEnv.constants ``AnnotatedPi.mk = + some annotatedPiRawType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr annotatedPiCtorEnv + annotatedPiRecInfo.levelParams [] annotatedPiRecInfo.type + (inductGenerationRecVal annotatedPiGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨u, hrec⟩ := annotatedPiGenerationEnv.recursor_wf + exact hshape.to_trExprS annotatedPiCtorEnv_ordered trivial + ⟨.sort u, hrec⟩ + +private def annotatedPiCtorMap : ConstMap := + annotatedPiTypeMap.insert ``AnnotatedPi.mk annotatedPiMkInfo + +private def annotatedPiMap : ConstMap := + annotatedPiCtorMap.insert ``AnnotatedPi.rec annotatedPiRecInfo + +private theorem annotatedPiMk_fresh : + annotatedPiTypeMap.find? ``AnnotatedPi.mk = none := by + rw [annotatedPiTypeMap, outParamMap_wf.find?_insert, + outParamMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +private theorem annotatedPiCtorMap_wf : annotatedPiCtorMap.WF := + annotatedPiTypeMap_wf.insert _ _ annotatedPiMk_fresh + +private theorem annotatedPiRec_fresh : + annotatedPiCtorMap.find? ``AnnotatedPi.rec = none := by + rw [annotatedPiCtorMap, annotatedPiTypeMap_wf.find?_insert, + annotatedPiTypeMap, outParamMap_wf.find?_insert, outParamMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +/-- Complete kernel-metadata replay transaction for `AnnotatedPi`, driven by +the checker-produced non-identity normalization certificate. -/ +def annotatedPiAddInductTraceChecked : + AddInductTrace outParamMap outParamEnv annotatedPiRawDecl + annotatedPiMap annotatedPiFinalEnv := by + refine annotatedPiProducedGenerationCandidatePackage.package.addInductTrace + annotatedPiTypeMap annotatedPiTypeEnv annotatedPiCtorMap + annotatedPiCtorEnv annotatedPiRecEnv annotatedPiAddType ?_ ?_ ?_ ⟨rfl⟩ + · exact .cons { + info := annotatedPiMkInfo + kind_eq := by simp [annotatedPiMkInfo, InductConstantKind.Matches] + tr := annotatedPiMkInfo_tr + map_fresh := by + simpa [annotatedPiRawType] using annotatedPiMk_fresh + env_add := rfl + map_add := rfl } .nil + · exact { + info := annotatedPiRecInfo + kind_eq := by simp [annotatedPiRecInfo, InductConstantKind.Matches] + tr := annotatedPiRecInfo_tr + map_fresh := by + rw [show + (inductGenerationRecVal + annotatedPiProducedGenerationCandidatePackage.package.generation).name = + ``AnnotatedPi.rec by rfl] + exact annotatedPiRec_fresh + env_add := rfl + map_add := rfl } + · decide + +theorem annotatedPi_addInduct_checked : + AddInduct outParamMap outParamEnv annotatedPiRawDecl + annotatedPiMap annotatedPiFinalEnv := + ⟨annotatedPiAddInductTraceChecked⟩ + +theorem annotatedPi_trEnv'_checked : + TrEnv' .safe annotatedPiMap false annotatedPiFinalEnv := + .induct annotatedPi_addInduct_checked outParam_trEnv' + +theorem annotatedPi_env_wf_checked : annotatedPiFinalEnv.WF := + annotatedPi_trEnv'_checked.wf + +theorem annotatedPi_aligned_checked : + Aligned .safe annotatedPiMap annotatedPiFinalEnv := + annotatedPi_trEnv'_checked.aligned + +theorem annotatedPiFinalEnv_trace : + Nonempty (VEnv.AddInductGenerationTrace outParamEnv + annotatedPiFinalEnv annotatedPiGenerationChecked) := + VEnv.addInductGeneration_trace annotatedPi_addInductGeneration + +/-- The public certified wrapper exposes the same trace. This deliberately +stays separate from the minimal Theory-only iota root below: the concrete +certificate remembers its Verify provenance, while the transaction equality +itself admits the smaller Theory proof. -/ +theorem annotatedPiCertified_trace : + Nonempty (VEnv.AddInductGenerationTrace outParamEnv + annotatedPiFinalEnv annotatedPiGenerationChecked) := + VEnv.addInductCertified_trace annotatedPi_addInductCertified + +theorem annotatedPiFinalEnv_family_lookup : + annotatedPiFinalEnv.constants ``AnnotatedPi = + some annotatedPiRawType.toVConstant := by + rcases annotatedPiFinalEnv_trace with ⟨trace⟩ + exact trace.family_lookup + +theorem annotatedPiFinalEnv_ctor_lookup : + annotatedPiFinalEnv.constants ``AnnotatedPi.mk = + some annotatedPiRawType.ctors[0].toVConstant := by + rcases annotatedPiFinalEnv_trace with ⟨trace⟩ + exact trace.ctor_lookup (.head _) + +theorem annotatedPiFinalEnv_rec_lookup : + annotatedPiFinalEnv.constants ``AnnotatedPi.rec = + some annotatedPiGenerationChecked.recursor := by + rcases annotatedPiFinalEnv_trace with ⟨trace⟩ + exact trace.rec_lookup + +theorem annotatedPiFinalEnv_rule_mem : + ∀ df ∈ annotatedPiGenerationChecked.generatedRules, + annotatedPiFinalEnv.defeqs df := by + intro df hdf + rcases annotatedPiFinalEnv_trace with ⟨trace⟩ + exact trace.rule_mem hdf + +theorem annotatedPiFinalEnv_iota_mem : + annotatedPiFinalEnv.defeqs + annotatedPiGenerationChecked.generatedRules[0] := by + apply annotatedPiFinalEnv_rule_mem + exact .head _ + +theorem annotatedPi_iota_rhs_matches_kernel : + annotatedPiKernelRuleRhs = + annotatedPiGenerationChecked.generatedRules[0].rhs := rfl + +theorem annotatedPi_type_map_lookup : + annotatedPiMap.find? ``AnnotatedPi = some annotatedPiInfo := by + rw [annotatedPiMap, annotatedPiCtorMap_wf.find?_insert, + annotatedPiCtorMap, annotatedPiTypeMap_wf.find?_insert] + simp +decide + rw [annotatedPiTypeMap, outParamMap_wf.find?_insert] + simp +decide + +theorem annotatedPi_mk_map_lookup : + annotatedPiMap.find? ``AnnotatedPi.mk = some annotatedPiMkInfo := by + rw [annotatedPiMap, annotatedPiCtorMap_wf.find?_insert, + annotatedPiCtorMap, annotatedPiTypeMap_wf.find?_insert] + rfl + +theorem annotatedPi_rec_map_lookup : + annotatedPiMap.find? ``AnnotatedPi.rec = some annotatedPiRecInfo := by + rw [annotatedPiMap, annotatedPiCtorMap_wf.find?_insert] + rfl + +theorem annotatedPi_type_lookup_unique : + annotatedPiInfo.name = ``AnnotatedPi ∧ + TrConstant .safe annotatedPiFinalEnv annotatedPiInfo + annotatedPiRawType.toVConstant := + annotatedPi_aligned_checked.find?_uniq annotatedPi_type_map_lookup + annotatedPiFinalEnv_family_lookup + +theorem annotatedPi_mk_lookup_unique : + annotatedPiMkInfo.name = ``AnnotatedPi.mk ∧ + TrConstant .safe annotatedPiFinalEnv annotatedPiMkInfo + annotatedPiRawType.ctors[0].toVConstant := + annotatedPi_aligned_checked.find?_uniq annotatedPi_mk_map_lookup + annotatedPiFinalEnv_ctor_lookup + +theorem annotatedPi_rec_lookup_unique : + annotatedPiRecInfo.name = ``AnnotatedPi.rec ∧ + TrConstant .safe annotatedPiFinalEnv annotatedPiRecInfo + annotatedPiGenerationChecked.recursor := + annotatedPi_aligned_checked.find?_uniq annotatedPi_rec_map_lookup + annotatedPiFinalEnv_rec_lookup + +/-! ## Definitionally equal parameter transaction replay -/ + +/-- Consumer-facing certificate for the exact mixed generation value whose +stored parameter is `outParam Type` and whose emitted recursor parameter is +the definitionally equal checked `Type`. -/ +def annotatedParamGenerationCertificate : + annotatedParamRawDecl.GenerationCertificate outParamEnv where + generation := annotatedParamGenerationChecked + wf := annotatedParamGenerationChecked_wf + +def annotatedParamCtorEnv : VEnv := + (annotatedParamTypeEnv.addConst annotatedParamRawType.ctors[0].name + annotatedParamRawType.ctors[0].toVConstant).get! + +def annotatedParamRecEnv : VEnv := + (annotatedParamCtorEnv.addConst ``AnnotatedParam.rec + annotatedParamGenerationChecked.recursor).get! + +def annotatedParamFinalEnv : VEnv := + (outParamEnv.addInductGeneration + annotatedParamGenerationChecked).get (by decide) + +theorem annotatedParam_addInductGeneration : + outParamEnv.addInductGeneration annotatedParamGenerationChecked = + some annotatedParamFinalEnv := rfl + +/-- The public proof-carrying transaction accepts the raw/checked parameter +normalization and computes the same environment as the underlying generation +transaction. -/ +theorem annotatedParam_addInductCertified : + outParamEnv.addInductCertified annotatedParamGenerationCertificate = + some annotatedParamFinalEnv := + annotatedParam_addInductGeneration + +theorem annotatedParamCertified_ordered : + annotatedParamFinalEnv.Ordered := + VEnv.addInductCertified_WF outParamEnv_ordered + annotatedParam_addInductCertified + +private theorem annotatedParamRawCtor_wf : + annotatedParamRawType.ctors[0].toVConstant.WF + annotatedParamTypeEnv := by + change annotatedParamTypeEnv.IsType 0 [] + annotatedParamRawType.ctors[0].type + let ctor : VInductDecl.NormalizedCtor := + ⟨annotatedParamRawType.ctors[0], + annotatedParamViewChecked.constructors[0]⟩ + have hctor : ctor ∈ + annotatedParamGenerationChecked.block.ctorPairs := by + change ctor ∈ [⟨annotatedParamRawType.ctors[0], + annotatedParamViewChecked.constructors[0]⟩] + exact .head _ + simpa [ctor, annotatedParamRawDecl] using + annotatedParamGenerationChecked_wf.rawCtor_isType + (envT := annotatedParamTypeEnv) rfl hctor + +private theorem annotatedParamCtorEnv_ordered : + annotatedParamCtorEnv.Ordered := + .const (n := annotatedParamRawType.ctors[0].name) + (ci := annotatedParamRawType.ctors[0].toVConstant) + annotatedParamTypeEnv_ordered annotatedParamRawCtor_wf rfl + +private theorem annotatedParamGenerationEnv : + VInductDecl.GenerationEnv annotatedParamGenerationChecked + annotatedParamCtorEnv := by + apply annotatedParamGenerationChecked_wf.toGenerationEnv + (envT := annotatedParamTypeEnv) + · rfl + · exact (VEnv.addConst_le (show + outParamEnv.addConst annotatedParamRawType.name + annotatedParamRawType.toVConstant = + some annotatedParamTypeEnv from rfl)).trans + (VEnv.addConst_le (show + annotatedParamTypeEnv.addConst + annotatedParamRawType.ctors[0].name + annotatedParamRawType.ctors[0].toVConstant = + some annotatedParamCtorEnv from rfl)) + · exact VEnv.addConst_le (show + annotatedParamTypeEnv.addConst + annotatedParamRawType.ctors[0].name + annotatedParamRawType.ctors[0].toVConstant = + some annotatedParamCtorEnv from rfl) + · exact annotatedParamCtorEnv_ordered + · rfl + · intro ctor hctor + change ctor ∈ [⟨annotatedParamRawType.ctors[0], + annotatedParamViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + rfl + +private theorem annotatedParamMkInfo_tr : + TrConstVal .safe annotatedParamTypeEnv annotatedParamMkInfo + annotatedParamRawType.ctors[0] := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr annotatedParamTypeEnv + annotatedParamMkInfo.levelParams [] annotatedParamMkInfo.type + annotatedParamRawType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := annotatedParamRawCtor_wf + exact hshape.to_trExprS annotatedParamTypeEnv_ordered trivial + ⟨.sort u, htype⟩ + +private theorem annotatedParamRecInfo_tr : + TrConstVal .safe annotatedParamCtorEnv annotatedParamRecInfo + (inductGenerationRecVal annotatedParamGenerationChecked) := by + have hfamily : annotatedParamCtorEnv.constants ``AnnotatedParam = + some annotatedParamRawType.toVConstant := rfl + have hmk : annotatedParamCtorEnv.constants ``AnnotatedParam.mk = + some annotatedParamRawType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr annotatedParamCtorEnv + annotatedParamRecInfo.levelParams [] annotatedParamRecInfo.type + (inductGenerationRecVal annotatedParamGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨u, hrec⟩ := annotatedParamGenerationEnv.recursor_wf + exact hshape.to_trExprS annotatedParamCtorEnv_ordered trivial + ⟨.sort u, hrec⟩ + +private def annotatedParamCtorMap : ConstMap := + annotatedParamTypeMap.insert ``AnnotatedParam.mk annotatedParamMkInfo + +private def annotatedParamMap : ConstMap := + annotatedParamCtorMap.insert ``AnnotatedParam.rec annotatedParamRecInfo + +private theorem annotatedParamMk_fresh : + annotatedParamTypeMap.find? ``AnnotatedParam.mk = none := by + rw [annotatedParamTypeMap, outParamMap_wf.find?_insert, + outParamMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +private theorem annotatedParamCtorMap_wf : annotatedParamCtorMap.WF := + annotatedParamTypeMap_wf.insert _ _ annotatedParamMk_fresh + +private theorem annotatedParamRec_fresh : + annotatedParamCtorMap.find? ``AnnotatedParam.rec = none := by + rw [annotatedParamCtorMap, annotatedParamTypeMap_wf.find?_insert, + annotatedParamTypeMap, outParamMap_wf.find?_insert, outParamMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +/-- Real `ConstantInfo` replay for the definitionally equal parameter case. +The generation certificate and the emitted recursor/rule payload are the same +values checked against kernel metadata above. -/ +def annotatedParamAddInductTraceChecked : + AddInductTrace outParamMap outParamEnv annotatedParamRawDecl + annotatedParamMap annotatedParamFinalEnv := by + refine { + generation := annotatedParamGenerationChecked + generation_wf := annotatedParamGenerationChecked_wf + typeMap := annotatedParamTypeMap + typeEnv := annotatedParamTypeEnv + ctorMap := annotatedParamCtorMap + ctorEnv := annotatedParamCtorEnv + recEnv := annotatedParamRecEnv + addType := annotatedParamAddType + addCtors := ?_ + addRec := { + info := annotatedParamRecInfo + kind_eq := by + simp [annotatedParamRecInfo, InductConstantKind.Matches] + tr := annotatedParamRecInfo_tr + map_fresh := by + rw [show + (inductGenerationRecVal annotatedParamGenerationChecked).name = + ``AnnotatedParam.rec by rfl] + exact annotatedParamRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ } + exact .cons { + info := annotatedParamMkInfo + kind_eq := by + simp [annotatedParamMkInfo, InductConstantKind.Matches] + tr := annotatedParamMkInfo_tr + map_fresh := by + simpa [annotatedParamRawType] using annotatedParamMk_fresh + env_add := rfl + map_add := rfl } .nil + +theorem annotatedParam_addInduct_checked : + AddInduct outParamMap outParamEnv annotatedParamRawDecl + annotatedParamMap annotatedParamFinalEnv := + ⟨annotatedParamAddInductTraceChecked⟩ + +theorem annotatedParam_trEnv'_checked : + TrEnv' .safe annotatedParamMap false annotatedParamFinalEnv := + .induct annotatedParam_addInduct_checked outParam_trEnv' + +theorem annotatedParam_env_wf_checked : annotatedParamFinalEnv.WF := + annotatedParam_trEnv'_checked.wf + +theorem annotatedParam_aligned_checked : + Aligned .safe annotatedParamMap annotatedParamFinalEnv := + annotatedParam_trEnv'_checked.aligned + +theorem annotatedParamCertified_trace : + Nonempty (VEnv.AddInductGenerationTrace outParamEnv + annotatedParamFinalEnv annotatedParamGenerationChecked) := + VEnv.addInductCertified_trace annotatedParam_addInductCertified + +theorem annotatedParamFinalEnv_family_lookup : + annotatedParamFinalEnv.constants ``AnnotatedParam = + some annotatedParamRawType.toVConstant := by + rcases annotatedParamCertified_trace with ⟨trace⟩ + exact trace.family_lookup + +theorem annotatedParamFinalEnv_ctor_lookup : + annotatedParamFinalEnv.constants ``AnnotatedParam.mk = + some annotatedParamRawType.ctors[0].toVConstant := by + rcases annotatedParamCertified_trace with ⟨trace⟩ + exact trace.ctor_lookup (.head _) + +theorem annotatedParamFinalEnv_rec_lookup : + annotatedParamFinalEnv.constants ``AnnotatedParam.rec = + some annotatedParamGenerationChecked.recursor := by + rcases annotatedParamCertified_trace with ⟨trace⟩ + exact trace.rec_lookup + +theorem annotatedParamFinalEnv_iota_mem : + annotatedParamFinalEnv.defeqs + annotatedParamGenerationChecked.generatedRules[0] := by + rcases annotatedParamCertified_trace with ⟨trace⟩ + exact trace.rule_mem (.head _) + +theorem annotatedParam_iota_rhs_matches_kernel : + annotatedParamKernelRuleRhs = + annotatedParamGenerationChecked.generatedRules[0].rhs := rfl + +theorem annotatedParam_type_map_lookup : + annotatedParamMap.find? ``AnnotatedParam = + some annotatedParamInfo := by + rw [annotatedParamMap, annotatedParamCtorMap_wf.find?_insert, + annotatedParamCtorMap, annotatedParamTypeMap_wf.find?_insert, + annotatedParamTypeMap, outParamMap_wf.find?_insert] + simp +decide + +theorem annotatedParam_mk_map_lookup : + annotatedParamMap.find? ``AnnotatedParam.mk = + some annotatedParamMkInfo := by + rw [annotatedParamMap, annotatedParamCtorMap_wf.find?_insert, + annotatedParamCtorMap, annotatedParamTypeMap_wf.find?_insert] + rfl + +theorem annotatedParam_rec_map_lookup : + annotatedParamMap.find? ``AnnotatedParam.rec = + some annotatedParamRecInfo := by + rw [annotatedParamMap, annotatedParamCtorMap_wf.find?_insert] + rfl + +theorem annotatedParam_type_lookup_unique : + annotatedParamInfo.name = ``AnnotatedParam ∧ + TrConstant .safe annotatedParamFinalEnv annotatedParamInfo + annotatedParamRawType.toVConstant := + annotatedParam_aligned_checked.find?_uniq annotatedParam_type_map_lookup + annotatedParamFinalEnv_family_lookup + +theorem annotatedParam_mk_lookup_unique : + annotatedParamMkInfo.name = ``AnnotatedParam.mk ∧ + TrConstant .safe annotatedParamFinalEnv annotatedParamMkInfo + annotatedParamRawType.ctors[0].toVConstant := + annotatedParam_aligned_checked.find?_uniq annotatedParam_mk_map_lookup + annotatedParamFinalEnv_ctor_lookup + +theorem annotatedParam_rec_lookup_unique : + annotatedParamRecInfo.name = ``AnnotatedParam.rec ∧ + TrConstant .safe annotatedParamFinalEnv annotatedParamRecInfo + annotatedParamGenerationChecked.recursor := + annotatedParam_aligned_checked.find?_uniq annotatedParam_rec_map_lookup + annotatedParamFinalEnv_rec_lookup + +/-- The complete AliasFormer metadata trace with the generation-WF field +supplied by the checker-produced certificate. All computational metadata +witnesses are shared with the existing replay. -/ +def aliasFormerAddInductTraceChecked : + AddInductTrace typeFamilyAliasMap typeFamilyAliasEnv + aliasFormerRawDecl aliasFormerMap aliasFormerFinalEnv := + let replay := + aliasFormerAddInductTraceWith aliasFormerGenerationCertificate.wf + aliasFormerProducedGenerationCandidatePackage.package.addInductTrace + replay.typeMap replay.typeEnv replay.ctorMap replay.ctorEnv replay.recEnv + replay.addType replay.addCtors replay.addRec replay.recK replay.addRules + +theorem aliasFormer_addInduct_checked : + AddInduct typeFamilyAliasMap typeFamilyAliasEnv + aliasFormerRawDecl aliasFormerMap aliasFormerFinalEnv := + ⟨aliasFormerAddInductTraceChecked⟩ + +theorem aliasFormer_trEnv'_checked : + TrEnv' .safe aliasFormerMap false aliasFormerFinalEnv := + .induct aliasFormer_addInduct_checked typeFamilyAlias_trEnv' + +theorem aliasFormer_env_wf_checked : aliasFormerFinalEnv.WF := + aliasFormer_trEnv'_checked.wf + +theorem aliasFormer_aligned_checked : + Aligned .safe aliasFormerMap aliasFormerFinalEnv := + aliasFormer_trEnv'_checked.aligned + +/-- The complete AliasRec metadata trace with the generation-WF field supplied +by the checker-produced normalization certificate. -/ +def aliasRecAddInductTraceChecked : + AddInductTrace recAliasMap recAliasEnv aliasRecRawDecl + aliasRecMap aliasRecFinalEnv := + aliasRecAddInductTraceWith aliasRecGenerationChecked_wf_checked + +theorem aliasRec_addInduct_checked : + AddInduct recAliasMap recAliasEnv aliasRecRawDecl + aliasRecMap aliasRecFinalEnv := + ⟨aliasRecAddInductTraceChecked⟩ + +theorem aliasRec_trEnv'_checked : + TrEnv' .safe aliasRecMap false aliasRecFinalEnv := + .induct aliasRec_addInduct_checked recAlias_trEnv' + +theorem aliasRec_env_wf_checked : aliasRecFinalEnv.WF := + aliasRec_trEnv'_checked.wf + +theorem aliasRec_aligned_checked : + Aligned .safe aliasRecMap aliasRecFinalEnv := + aliasRec_trEnv'_checked.aligned + +/- The operational traces do not reach the pointer-equality contracts. Their +semantic endpoints intentionally inherit Verify's existing checker-refinement +and reflection contracts, including pointer equality. No new axiom or +native-evaluation principle is used. -/ +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_candidateTrace [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerCtor_candidateTrace [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_candidate [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_candidateRun_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_candidateSource_tr [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_candidateView_tr [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerNormalizationCandidateRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerCandidateNormalization_eq [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerTruncatedView_rejected [propext] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRecField_checkType [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRecField_hasType_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_whnf [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerCtor_whnf [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.recAlias_whnf [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_checkType [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerCtor_checkType [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerFamily_isType_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerCtor_isType_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerNormalization_wf_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRecNormalization_wf_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerBlock_wf_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerProducedSemanticHierarchy_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerProducedPostFamilySemantic_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerProducedPreFamilySemantic_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerGenerationCandidateSemanticRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerGenerationCandidateRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerGenerationCandidatePackage [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerNormalizationCandidate_produced [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerGenerationShapeCandidate_produced [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerExactProducedGenerationCandidatePackage_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerProducedGenerationCandidatePackage [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormer_addInductCertified_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerGenerationChecked_wf_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRecBlock_wf_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRecGenerationChecked_wf_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormerAddInductTraceChecked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormer_trEnv'_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRecAddInductTraceChecked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRec_trEnv'_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +/- Both alias replays have the same `sorryAx`-free Verify closure as the +identity fixtures. The three persistent-map contracts enter through concrete +`ConstMap` freshness proofs. -/ +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormer_trEnv' [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormer_env_wf [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasFormer_aligned [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRec_trEnv' [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRec_env_wf [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.aliasRec_aligned [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiProducedSemanticHierarchy_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiProducedPostFamilySemantic_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiProducedPreFamilySemantic_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiNormalizationCandidateRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiGenerationCandidateSemanticRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiGenerationCandidateRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiGenerationCandidatePackage [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiCtor_candidateTrace [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiFamily_candidateTrace [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Syntax.structEq_eq] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiNormalizationCandidate_produced [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiGenerationShapeCandidate_produced [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiExactProducedGenerationCandidatePackage_exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiProducedGenerationCandidatePackage [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPi_addInductCertified [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiGenerationChecked_wf_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiAddInductTraceChecked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPi_trEnv'_checked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedPiFinalEnv_iota_mem [propext, Quot.sound] + +/-! The parameter-parity fixture deliberately keeps its operational checker +outcome guard separate from the Theory certificate. These pins make the exact +trust split visible: the semantic transaction stays Theory-small, while real +`ConstantInfo` replay inherits only the already classified Verify frontier. -/ + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedParam_addInductCertified [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedParamAddInductTraceChecked [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedParam_trEnv'_checked [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.annotatedParamFinalEnv_iota_mem [propext, Quot.sound] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/Lemmas.lean b/Ix/Theory/Named/Verify/Environment/Lemmas.lean new file mode 100644 index 000000000..d82bd8ecb --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/Lemmas.lean @@ -0,0 +1,664 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Std.SMap +import Ix.Theory.Named.Reference.Declaration +import Ix.Theory.Named.Verify.Environment.Basic + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +theorem TrConstant.sf_mono (hsf : safety ≤ safety') + (H : TrConstant safety' env ci ci') : TrConstant safety env ci ci' := + ⟨safety.le_trans hsf H.1, H.2⟩ + +theorem TrConstVal.sf_mono (hsf : safety ≤ safety') + (H : TrConstVal safety' env ci ci') : TrConstVal safety env ci ci' := + ⟨H.1.sf_mono hsf, H.2⟩ + +theorem TrDefVal.sf_mono (hsf : safety ≤ safety') + (H : TrDefVal safety' env ci ci') : TrDefVal safety env ci ci' := + ⟨H.1.sf_mono hsf, H.2⟩ + +/- The former blanket `TrEnv'.sf_mono` was deleted at the v4.33 +reconciliation: upstream's new `TrEnv'.ignore` constructor makes lowering the +safety mode of an arbitrary translation unsound (a declaration skipped at a +strict mode must be translated, not skipped, at a laxer one). Fixture +environments that need every safety mode now state their `TrEnv'` derivations +parametrically in `safety` instead. -/ + +theorem TrConstant.mono {env env' : VEnv} (henv : env ≤ env') + (H : TrConstant safety env ci ci') : TrConstant safety env' ci ci' := + ⟨H.1, H.2.1, H.2.2.mono henv⟩ + +theorem TrConstVal.mono {env env' : VEnv} (henv : env ≤ env') + (H : TrConstVal safety env ci ci') : TrConstVal safety env' ci ci' := + ⟨H.1.mono henv, H.2⟩ + +theorem TrDefVal.mono {env env' : VEnv} (henv : env ≤ env') + (H : TrDefVal safety env ci ci') : TrDefVal safety env' ci ci' := + ⟨H.1.mono henv, H.2.mono henv⟩ + +variable (safety : DefinitionSafety) in +inductive Aligned : ConstMap → VEnv → Prop where + | empty : Aligned {} .empty + | ignoreConst : Aligned C venv → C.find? n = none → ¬safety ≤ ci.safety → + ci.name = n → Aligned (C.insert n ci) venv + | const : Aligned C venv → C.find? n = none → TrConstant safety venv ci ci' → + venv.addConst n ci' = some venv' → ci.name = n → Aligned (C.insert n ci) venv' + | defeq : Aligned C venv → Aligned C (venv.addDefEq df) + | structEta : Aligned C venv → Aligned C (venv.addStructEta rule) + +theorem Aligned.map_wf (H : Aligned safety C venv) : C.WF := by + induction H with + | empty => exact .empty + | ignoreConst _ h1 _ _ ih + | const _ h1 _ _ _ ih => exact ih.insert _ _ h1 + | defeq _ ih => exact ih + | structEta _ ih => exact ih + +theorem Aligned.find?_iff (H : Aligned safety C venv) : + (∃ ci, C.find? name = some ci ∧ safety ≤ ci.safety) ↔ ∃ ci, venv.constants name = some ci := by + induction H with + | empty => simp [SMap.find?, VEnv.empty] + | ignoreConst H _ h2 _ ih => + simp [H.map_wf.find?_insert]; split <;> [skip; assumption] + rename_i eq1 eq2; subst eq2; simp [← ih, *] + | const H h1 h2 eq _ ih => + simp [H.map_wf.find?_insert] + simp [VEnv.addConst] at eq; split at eq <;> cases eq + split <;> simp_all; exact h2.1 + | defeq _ ih => exact ih + | structEta _ ih => exact ih + +theorem Aligned.addQuot1 {Q : Prop} + (H1 : ∀ c env, Aligned safety c env → P c env → Q) + (C env) (wf : Aligned safety C env) (H2 : AddQuot1 n k ci P C env) : Q := by + let ⟨_, _, _, h1, h2, h3, h4⟩ := H2 + exact H1 _ _ (wf.const h2 (h1.sf_mono DefinitionSafety.le_safe) h3 rfl) h4 + +nonrec theorem Aligned.addQuot (H : AddQuot C₁ C₂ venv₁ venv₂) + (wf : Aligned safety C₁ venv₁) : Aligned safety C₂ venv₂ := by + dsimp [AddQuot] at H + refine (addQuot1 <| addQuot1 <| addQuot1 <| addQuot1 ?_) _ _ wf H + rintro _ _ h ⟨rfl, rfl⟩; exact h.defeq + +theorem AddInductConstant.map_wf + (H : AddInductConstant kind C₁ env₁ ci C₂ env₂) (wf : C₁.WF) : C₂.WF := by + rw [H.map_add] + exact wf.insert _ _ H.map_fresh + +/-- The implementation metadata inserted by one inductive-constant step is +still available at that step's output boundary. -/ +theorem AddInductConstant.map_lookup + (H : AddInductConstant kind C₁ env₁ ci C₂ env₂) + (wf : C₁.WF) : C₂.find? ci.name = some H.info := by + simp [H.map_add, wf.find?_insert] + +/-- An inductive-metadata insertion preserves every lookup already present in +the input map. Freshness rules out the only key at which `insert` could +replace that entry. -/ +theorem AddInductConstant.preserve_map_lookup + (H : AddInductConstant kind C₁ env₁ ci' C₂ env₂) + (wf : C₁.WF) {name : Name} {info : ConstantInfo} + (hlookup : C₁.find? name = some info) : + C₂.find? name = some info := by + rw [H.map_add, wf.find?_insert] + split + · rename_i heq + have hname : ci'.name = name := by simpa using heq + subst name + have hfresh := H.map_fresh + rw [hlookup] at hfresh + contradiction + · exact hlookup + +theorem InductConstantKind.Matches.deltaValue?_eq_none + {kind : InductConstantKind} {ci : ConstantInfo} + (H : InductConstantKind.Matches kind ci) : ci.deltaValue? = none := by + cases kind <;> cases ci <;> + simp_all [InductConstantKind.Matches, ConstantInfo.deltaValue?] + +/-- An inductive metadata insertion cannot introduce a declaration body. +Consequently, any value-bearing entry in the result map was already present +in the input map. -/ +theorem AddInductConstant.old_of_value + (H : AddInductConstant kind C₁ env₁ ci' C₂ env₂) (wf : C₁.WF) + (hout : C₂.find? name = some ci) (hv : ci.deltaValue? = some v) : + C₁.find? name = some ci := by + rw [H.map_add, wf.find?_insert] at hout + split at hout + · cases hout + have hnone := InductConstantKind.Matches.deltaValue?_eq_none H.kind_eq + simp_all + · exact hout + +theorem AddInductConstants.map_wf : + AddInductConstants kind C₁ env₁ cis C₂ env₂ → C₁.WF → C₂.WF + | .nil, wf => wf + | .cons h hrest, wf => hrest.map_wf (h.map_wf wf) + +/-- A whole insertion fold preserves every lookup from its input map. -/ +theorem AddInductConstants.preserve_map_lookup + (H : AddInductConstants kind C₁ env₁ cis C₂ env₂) + (wf : C₁.WF) {name : Name} {info : ConstantInfo} + (hlookup : C₁.find? name = some info) : + C₂.find? name = some info := by + induction H with + | nil => exact hlookup + | cons h hrest ih => + exact ih (h.map_wf wf) (h.preserve_map_lookup wf hlookup) + +/-- Final-map evidence for any member of an inductive metadata fold. The +result retains the exact implementation object, its role tag, and its +translation against the final Theory environment. -/ +theorem AddInductConstants.translated_lookup + (H : AddInductConstants kind C₁ env₁ cis C₂ env₂) + (wf : C₁.WF) {ci : VConstVal} (hmem : ci ∈ cis) : ∃ info, + C₂.find? ci.name = some info ∧ + kind.Matches info ∧ TrConstVal .safe env₂ info ci := by + induction H with + | nil => contradiction + | cons h hrest ih => + rcases List.mem_cons.1 hmem with rfl | hmem + · refine ⟨h.info, ?_, h.kind_eq, ?_⟩ + exact hrest.preserve_map_lookup (h.map_wf wf) (h.map_lookup wf) + exact h.tr.mono (h.le.trans hrest.le) + · exact ih (h.map_wf wf) hmem + +theorem AddInductConstants.old_of_value : + (H : AddInductConstants kind C₁ env₁ cis C₂ env₂) → C₁.WF → + C₂.find? name = some ci → ci.deltaValue? = some v → C₁.find? name = some ci + | .nil, _, hout, _ => hout + | .cons h hrest, wf, hout, hv => + h.old_of_value wf (hrest.old_of_value (h.map_wf wf) hout hv) hv + +/-! ## Final translated metadata inventories -/ + +/-- Final-map and final-environment evidence for the family emitted by a +singleton inductive replay. -/ +theorem AddInductTrace.type_translated_lookup + (H : AddInductTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) : + ∃ info, + C₂.find? H.generation.block.sourceType.name = some info ∧ + InductConstantKind.induct.Matches info ∧ + TrConstVal .safe env₂ info H.generation.block.sourceType.toVConstVal := by + refine ⟨H.addType.info, ?_, H.addType.kind_eq, ?_⟩ + · exact H.addRec.preserve_map_lookup + (H.addCtors.map_wf (H.addType.map_wf wf)) + (H.addCtors.preserve_map_lookup (H.addType.map_wf wf) + (H.addType.map_lookup wf)) + · exact H.addType.tr.mono + (H.addType.le.trans <| H.addCtors.le.trans <| + H.addRec.le.trans H.addRules.le) + +/-- Final-map and final-environment evidence for every constructor emitted by +a singleton inductive replay. -/ +theorem AddInductTrace.constructor_translated_lookup + (H : AddInductTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) + {constructor : VConstVal} + (hconstructor : constructor ∈ H.generation.block.sourceType.ctors) : + ∃ info, + C₂.find? constructor.name = some info ∧ + InductConstantKind.ctor.Matches info ∧ + TrConstVal .safe env₂ info constructor := by + obtain ⟨info, hlookup, hkind, htr⟩ := + H.addCtors.translated_lookup (H.addType.map_wf wf) hconstructor + exact ⟨info, + H.addRec.preserve_map_lookup (H.addCtors.map_wf (H.addType.map_wf wf)) hlookup, + hkind, htr.mono (H.addRec.le.trans H.addRules.le)⟩ + +/-- Final-map and final-environment evidence for the recursor emitted by a +singleton inductive replay. -/ +theorem AddInductTrace.recursor_translated_lookup + (H : AddInductTrace C₁ env₁ decl C₂ env₂) + (wf : C₁.WF) : ∃ info, + C₂.find? (inductGenerationRecVal H.generation).name = some info ∧ + InductConstantKind.recursor.Matches info ∧ + TrConstVal .safe env₂ info (inductGenerationRecVal H.generation) := by + exact ⟨H.addRec.info, H.addRec.map_lookup + (H.addCtors.map_wf (H.addType.map_wf wf)), H.addRec.kind_eq, + H.addRec.tr.mono (H.addRec.le.trans H.addRules.le)⟩ + +/-- Final translated lookup for every source family in a mutual block. -/ +theorem AddInductBlockTrace.family_translated_lookup + (H : AddInductBlockTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) + {family : VInductiveType} (hfamily : family ∈ decl.types) : ∃ info, + C₂.find? family.name = some info ∧ + InductConstantKind.induct.Matches info ∧ + TrConstVal .safe env₂ info family.toVConstVal := by + have hmember : family.toVConstVal ∈ decl.blockTypeConstants := + List.mem_map.2 ⟨family, hfamily, rfl⟩ + obtain ⟨info, hlookup, hkind, htr⟩ := + H.addTypes.translated_lookup wf hmember + exact ⟨info, + H.addRecs.preserve_map_lookup + (H.addCtors.map_wf (H.addTypes.map_wf wf)) + (H.addCtors.preserve_map_lookup (H.addTypes.map_wf wf) hlookup), + hkind, htr.mono (H.addCtors.le.trans <| H.addRecs.le.trans H.addRules.le)⟩ + +/-- Final translated lookup for every flattened constructor in a mutual +block. -/ +theorem AddInductBlockTrace.constructor_translated_lookup + (H : AddInductBlockTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) + {constructor : VConstVal} + (hconstructor : constructor ∈ decl.blockConstructorConstants) : ∃ info, + C₂.find? constructor.name = some info ∧ + InductConstantKind.ctor.Matches info ∧ + TrConstVal .safe env₂ info constructor := by + obtain ⟨info, hlookup, hkind, htr⟩ := + H.addCtors.translated_lookup (H.addTypes.map_wf wf) hconstructor + exact ⟨info, + H.addRecs.preserve_map_lookup + (H.addCtors.map_wf (H.addTypes.map_wf wf)) hlookup, + hkind, htr.mono (H.addRecs.le.trans H.addRules.le)⟩ + +/-- Final translated lookup for every generated recursor in a mutual block. -/ +theorem AddInductBlockTrace.recursor_translated_lookup + (H : AddInductBlockTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) + {recursor : VConstVal} (hrecursor : recursor ∈ H.generation.recursors) : + ∃ info, + C₂.find? recursor.name = some info ∧ + InductConstantKind.recursor.Matches info ∧ + TrConstVal .safe env₂ info recursor := by + obtain ⟨info, hlookup, hkind, htr⟩ := H.addRecs.translated_lookup + (H.addCtors.map_wf (H.addTypes.map_wf wf)) hrecursor + exact ⟨info, hlookup, hkind, htr.mono H.addRules.le⟩ + +/-- Final translated lookup for every source family in a nested replay. -/ +theorem AddInductNestedTrace.family_translated_lookup + (H : AddInductNestedTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) + {family : VInductiveType} (hfamily : family ∈ decl.types) : ∃ info, + C₂.find? family.name = some info ∧ + InductConstantKind.induct.Matches info ∧ + TrConstVal .safe env₂ info family.toVConstVal := by + have hmember : family.toVConstVal ∈ decl.blockTypeConstants := + List.mem_map.2 ⟨family, hfamily, rfl⟩ + obtain ⟨info, hlookup, hkind, htr⟩ := + H.addTypes.translated_lookup wf hmember + exact ⟨info, + H.addRecs.preserve_map_lookup + (H.addCtors.map_wf (H.addTypes.map_wf wf)) + (H.addCtors.preserve_map_lookup (H.addTypes.map_wf wf) hlookup), + hkind, htr.mono (H.addCtors.le.trans <| H.addRecs.le.trans H.addRules.le)⟩ + +/-- Final translated lookup for every source constructor in a nested replay. -/ +theorem AddInductNestedTrace.constructor_translated_lookup + (H : AddInductNestedTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) + {constructor : VConstVal} + (hconstructor : constructor ∈ decl.blockConstructorConstants) : ∃ info, + C₂.find? constructor.name = some info ∧ + InductConstantKind.ctor.Matches info ∧ + TrConstVal .safe env₂ info constructor := by + obtain ⟨info, hlookup, hkind, htr⟩ := + H.addCtors.translated_lookup (H.addTypes.map_wf wf) hconstructor + exact ⟨info, + H.addRecs.preserve_map_lookup + (H.addCtors.map_wf (H.addTypes.map_wf wf)) hlookup, + hkind, htr.mono (H.addRecs.le.trans H.addRules.le)⟩ + +/-- Final translated lookup for every restored recursor in a nested replay. -/ +theorem AddInductNestedTrace.recursor_translated_lookup + (H : AddInductNestedTrace C₁ env₁ decl C₂ env₂) (wf : C₁.WF) + {recursor : VConstVal} (hrecursor : recursor ∈ H.nested.recursors) : ∃ info, + C₂.find? recursor.name = some info ∧ + InductConstantKind.recursor.Matches info ∧ + TrConstVal .safe env₂ info recursor := by + obtain ⟨info, hlookup, hkind, htr⟩ := H.addRecs.translated_lookup + (H.addCtors.map_wf (H.addTypes.map_wf wf)) hrecursor + exact ⟨info, hlookup, hkind, htr.mono H.addRules.le⟩ + +theorem AddInduct.map_wf (H : AddInduct C₁ env₁ decl C₂ env₂) + (wf : C₁.WF) : C₂.WF := by + rcases H with ⟨H⟩ + exact H.addRec.map_wf <| H.addCtors.map_wf <| H.addType.map_wf wf + +theorem AddInduct.old_of_value (H : AddInduct C₁ env₁ decl C₂ env₂) + (wf : C₁.WF) (hout : C₂.find? name = some ci) (hv : ci.deltaValue? = some v) : + C₁.find? name = some ci := by + rcases H with ⟨H⟩ + have wfType := H.addType.map_wf wf + have wfCtors := H.addCtors.map_wf wfType + exact H.addType.old_of_value wf + (H.addCtors.old_of_value wfType (H.addRec.old_of_value wfCtors hout hv) hv) hv + +theorem AddInductBlock.map_wf + (H : AddInductBlock C₁ env₁ decl C₂ env₂) + (wf : C₁.WF) : C₂.WF := by + rcases H with ⟨H⟩ + exact H.addRecs.map_wf <| H.addCtors.map_wf <| + H.addTypes.map_wf wf + +theorem AddInductBlock.old_of_value + (H : AddInductBlock C₁ env₁ decl C₂ env₂) + (wf : C₁.WF) (hout : C₂.find? name = some ci) + (hv : ci.deltaValue? = some v) : C₁.find? name = some ci := by + rcases H with ⟨H⟩ + have wfTypes := H.addTypes.map_wf wf + have wfCtors := H.addCtors.map_wf wfTypes + exact H.addTypes.old_of_value wf + (H.addCtors.old_of_value wfTypes + (H.addRecs.old_of_value wfCtors hout hv) hv) hv + +theorem AddInductNested.map_wf + (H : AddInductNested C₁ env₁ decl C₂ env₂) + (wf : C₁.WF) : C₂.WF := by + rcases H with ⟨H⟩ + exact H.addRecs.map_wf <| H.addCtors.map_wf <| + H.addTypes.map_wf wf + +theorem AddInductNested.old_of_value + (H : AddInductNested C₁ env₁ decl C₂ env₂) + (wf : C₁.WF) (hout : C₂.find? name = some ci) + (hv : ci.deltaValue? = some v) : C₁.find? name = some ci := by + rcases H with ⟨H⟩ + have wfTypes := H.addTypes.map_wf wf + have wfCtors := H.addCtors.map_wf wfTypes + exact H.addTypes.old_of_value wf + (H.addCtors.old_of_value wfTypes + (H.addRecs.old_of_value wfCtors hout hv) hv) hv + +theorem Aligned.addInductConstant + (wf : Aligned safety C₁ env₁) + (H : AddInductConstant kind C₁ env₁ ci C₂ env₂) : Aligned safety C₂ env₂ := by + rw [H.map_add] + exact wf.const H.map_fresh (H.tr.1.sf_mono DefinitionSafety.le_safe) + H.env_add H.tr.2 + +theorem Aligned.addInductConstants : + AddInductConstants kind C₁ env₁ cis C₂ env₂ → + Aligned safety C₁ env₁ → Aligned safety C₂ env₂ + | .nil, wf => wf + | .cons h hrest, wf => + Aligned.addInductConstants hrest (wf.addInductConstant h) + +theorem Aligned.addDefEqFold : ∀ (dfs : List VDefEq), + Aligned safety C env → Aligned safety C (dfs.foldl VEnv.addDefEq env) + | [], wf => wf + | _ :: dfs, wf => addDefEqFold dfs wf.defeq + +theorem Aligned.addInduct (H : AddInduct C₁ env₁ decl C₂ env₂) + (wf : Aligned safety C₁ env₁) : Aligned safety C₂ env₂ := by + rcases H with ⟨H⟩ + rw [← H.addRules.to_add] + have wfType := wf.addInductConstant H.addType + have wfCtors := wfType.addInductConstants H.addCtors + have wfRec := wfCtors.addInductConstant H.addRec + exact wfRec.addDefEqFold _ + +theorem Aligned.addInductBlock + (H : AddInductBlock C₁ env₁ decl C₂ env₂) + (wf : Aligned safety C₁ env₁) : Aligned safety C₂ env₂ := by + rcases H with ⟨H⟩ + rw [← H.addRules.to_add] + have wfTypes := wf.addInductConstants H.addTypes + have wfCtors := wfTypes.addInductConstants H.addCtors + have wfRecs := wfCtors.addInductConstants H.addRecs + exact wfRecs.addDefEqFold _ + +theorem Aligned.addInductNested + (H : AddInductNested C₁ env₁ decl C₂ env₂) + (wf : Aligned safety C₁ env₁) : Aligned safety C₂ env₂ := by + rcases H with ⟨H⟩ + rw [← H.addRules.to_add] + have wfTypes := wf.addInductConstants H.addTypes + have wfCtors := wfTypes.addInductConstants H.addCtors + have wfRecs := wfCtors.addInductConstants H.addRecs + exact wfRecs.addDefEqFold _ + +#guard_named_axioms Ix.Theory.Named.Aligned.addInduct [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.Aligned.addInductBlock [propext, Classical.choice, Quot.sound] + +theorem Aligned.addDefEqs {C : ConstMap} : ∀ {cis' : List VDefVal} {venv}, + Aligned safety C venv → Aligned safety C (venv.addDefEqs cis') + | [], _, H => H + | ci :: cis, venv, H => by + show Aligned safety C (VEnv.addDefEqs (venv.addDefEq ci.toDefEq) cis) + exact Aligned.addDefEqs H.defeq + +theorem Aligned.insertDefs : ∀ {cis : List DefinitionVal} {cis' : List VDefVal} {C venv venv'}, + Aligned safety C venv → (cis.map (·.name)).Nodup → + (∀ ci ∈ cis, C.find? ci.name = none) → + List.Forall₂ (fun ci ci' => TrConstVal safety venv (.defnInfo ci) ci'.toVConstVal) cis cis' → + venv.addConsts cis' = some venv' → Aligned safety (insertDefs C cis) venv' + | [], _, _, _, _, H, _, _, hblk, e => by + cases hblk; simp [VEnv.addConsts] at e; cases e; exact H + | ci :: cis, _, C, venv, _, H, hnd, hfr, hblk, e => by + cases hblk with | @cons _ ci' _ _ htr hblk => ?_ + simp [VEnv.addConsts, Option.bind_eq_some_iff] at e + obtain ⟨venv₁, h1, h2⟩ := e + have hname := htr.2 + simp only [ConstantInfo.name, ConstantInfo.toConstantVal] at hname + simp only [List.map_cons, List.nodup_cons, List.mem_map] at hnd + have h1' : venv.addConst ci.name ci'.toVConstant = some venv₁ := by rw [hname]; exact h1 + show Aligned safety + (_root_.Ix.Theory.Named.insertDefs (SMap.insert C ci.name (.defnInfo ci)) cis) _ + refine Aligned.insertDefs (H.const (hfr _ (.head _)) htr.1 h1' rfl) hnd.2 + (fun c hc => ?_) (Ix.Theory.Named.List.Forall₂.imp + (fun _ _ h => h.mono (VEnv.addConst_le h1')) hblk) h2 + rw [H.map_wf.find?_insert] + have : ¬ (ci.name == c.name) = true := by + simp only [beq_iff_eq]; intro h + exact hnd.1 ⟨c, hc, h.symm⟩ + simp [this] + exact hfr c (.tail _ hc) + +theorem TrEnv'.aligned (H : TrEnv' safety C Q venv) : Aligned safety C venv := by + induction H with + | empty => exact .empty + | ignore h1 h2 _ ih => exact ih.ignoreConst h1 h2 rfl + | «axiom» h1 h2 _ h _ ih => exact ih.const h2 h1 h rfl + | thm h1 h2 _ _ h _ ih => exact ih.const h2 h1.1.1 h rfl + | «opaque» h1 h2 _ h _ ih => exact ih.const h2 h1.1.1 h rfl + | defn h1 h2 _ h _ ih => exact (ih.const h2 h1.1.1 h rfl).defeq + | mutualDef hblk hnd hfr _ hadd _ _ ih => + exact Aligned.addDefEqs <| ih.insertDefs hnd hfr + (Ix.Theory.Named.List.Forall₂.imp (fun _ _ h => h.1) hblk) hadd + | quot _ h _ ih => exact ih.addQuot h + | inductStaging h _ _ ih => exact ih.addInductConstant h + | induct h _ ih => exact ih.addInduct h + | inductBlock h _ ih => exact ih.addInductBlock h + | inductNested h _ ih => exact ih.addInductNested h + | structEta _ _ ih => exact ih.structEta + +/- Since the v4.33 reconciliation the `mutualDef` arm routes through +`insertDefs`, whose `SMap` reasoning uses the classified persistent-map +container contracts; the closure is pinned so any further growth is +reviewed. -/ +#guard_named_axioms Ix.Theory.Named.TrEnv'.aligned [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +theorem TrEnv'.map_wf (H : TrEnv' safety C Q venv) : C.WF := H.aligned.map_wf + +theorem Aligned.find? (H : Aligned safety C venv) + (h : C.find? name = some ci) (hs : safety ≤ ci.safety) : + ∃ ci', venv.constants name = some ci' ∧ TrConstant safety venv ci ci' := by + have mono {env₁ env₂} (H : env₁.LE env₂) : + (∃ ci', env₁.constants name = some ci' ∧ TrConstant safety env₁ ci ci') → + (∃ ci', env₂.constants name = some ci' ∧ TrConstant safety env₂ ci ci') + | ⟨_, h1, h2⟩ => ⟨_, H.constants h1, h2.mono H⟩ + induction H with + | empty => simp [SMap.find?] at h + | ignoreConst h1 _ _ _ ih => + rw [h1.map_wf.find?_insert] at h; split at h + · cases h; contradiction + · exact ih h + | const h1 _ h2 h3 _ ih => + have := VEnv.addConst_le h3 + rw [h1.map_wf.find?_insert] at h; split at h + · rename_i h'; cases h; simp at h'; subst h' + simp [VEnv.addConst] at h3; split at h3 <;> cases h3 + simp; rename_i h'; refine h2.mono this + · let ⟨_, h1, h2⟩ := ih h; exact ⟨_, this.constants h1, h2.mono this⟩ + | defeq h1 ih => let ⟨_, h1, h2⟩ := ih h; exact ⟨_, h1, h2.mono VEnv.addDefEq_le⟩ + | structEta h1 ih => + let ⟨_, h1, h2⟩ := ih h + exact ⟨_, h1, h2.mono VEnv.addStructEta_le⟩ + +theorem Aligned.find?_uniq (H : Aligned safety C venv) + (h : C.find? name = some ci) (hs : venv.constants name = some ci') : + ci.name = name ∧ TrConstant safety venv ci ci' := by + induction H with + | empty => simp [SMap.find?] at h + | ignoreConst H h2 h3 _ ih => + simp [H.map_wf.find?_insert] at h; split at h + · rename_i n ci _ h'; subst n h' + simpa [h2, hs] using H.find?_iff (name := ci.name) + · exact ih h hs + | const h1 h5 h2 h3 h4 ih => + have := VEnv.addConst_le h3 + simp [VEnv.addConst] at h3; split at h3 <;> cases h3 + simp [h1.map_wf.find?_insert] at h hs; revert h hs; split + · rintro ⟨⟩ ⟨⟩; rename_i n _ _ _; subst n; exact ⟨h4, h2.mono this⟩ + · intro hs h; let ⟨h1, h2⟩ := ih h hs; exact ⟨h1, h2.mono this⟩ + | defeq h1 ih => let ⟨h1, h2⟩ := ih h hs; exact ⟨h1, h2.mono VEnv.addDefEq_le⟩ + | structEta h1 ih => + let ⟨h1, h2⟩ := ih h hs + exact ⟨h1, h2.mono VEnv.addStructEta_le⟩ + +theorem TrEnv.find?_iff (H : TrEnv safety env venv) : + (∃ ci, env.find? name = some ci ∧ safety ≤ ci.safety) ↔ ∃ ci, venv.constants name = some ci := by + conv => enter [1,1,_,1,1]; apply H.map_wf.find?'_eq_find? + exact H.aligned.find?_iff + +-- theorem TrEnv.contains_iff (H : TrEnv safety env venv) : +-- env.contains name ↔ ∃ oci, venv.constants name = some oci := by +-- simp [← H.find?_iff, Kernel.Environment.find?, H.map_wf.find?'_eq_find?, +-- ← Option.isSome_iff_exists, ← SMap.find?_isSome, Kernel.Environment.contains] + +theorem TrEnv.find? (H : TrEnv safety env venv) + (h : env.find? name = some ci) (hs : safety ≤ ci.safety) : + ∃ ci', venv.constants name = some ci' ∧ TrConstant safety venv ci ci' := + H.aligned.find? (H.map_wf.find?'_eq_find? _ ▸ h) hs + +theorem TrEnv.find?_uniq (H : TrEnv safety env venv) + (h : env.find? name = some ci) (hs : venv.constants name = some ci') : + ci.name = name ∧ TrConstant safety venv ci ci' := + H.aligned.find?_uniq (H.map_wf.find?'_eq_find? _ ▸ h) hs + +theorem VEnv.addDefEqs_le : ∀ {cis' : List VDefVal} {venv : VEnv}, venv ≤ venv.addDefEqs cis' + | [], _ => .rfl + | ci :: cis, venv => by + show venv ≤ VEnv.addDefEqs (venv.addDefEq ci.toDefEq) cis + exact VEnv.addDefEq_le.trans VEnv.addDefEqs_le + +theorem VEnv.addDefEqs_self : ∀ {cis' : List VDefVal} {venv : VEnv} {ci'}, ci' ∈ cis' → + (venv.addDefEqs cis').defeqs ci'.toDefEq + | ci :: cis, venv, _, hc => by + show (VEnv.addDefEqs (venv.addDefEq ci.toDefEq) cis).defeqs _ + cases hc with + | head => exact VEnv.addDefEqs_le.defeqs VEnv.addDefEq_self + | tail _ hc => exact VEnv.addDefEqs_self hc + +theorem insertDefs_find? : ∀ {cis : List DefinitionVal} {C : ConstMap} {name ci}, C.WF → + (∀ d ∈ cis, C.find? d.name = none) → (cis.map (·.name)).Nodup → + (insertDefs C cis).find? name = some ci → + C.find? name = some ci ∨ ∃ d ∈ cis, d.name = name ∧ ConstantInfo.defnInfo d = ci + | [], _, _, _, _, _, _, h => .inl h + | d :: ds, C, name, ci, hC, hfr, hnd, h => by + simp only [List.map_cons, List.nodup_cons, List.mem_map] at hnd + have hfr' : ∀ e ∈ ds, (SMap.insert C d.name (.defnInfo d)).find? e.name = none := by + intro e he + rw [hC.find?_insert] + have : ¬ (d.name == e.name) = true := by + simp only [beq_iff_eq]; intro hh; exact hnd.1 ⟨e, he, hh.symm⟩ + simp [this]; exact hfr e (.tail _ he) + have h : (insertDefs (SMap.insert C d.name (.defnInfo d)) ds).find? name = some ci := h + rcases insertDefs_find? (hC.insert _ _ (hfr _ (.head _))) hfr' hnd.2 h with h | ⟨e, he, h1, h2⟩ + · rw [hC.find?_insert] at h; split at h + · rename_i hb; cases h + exact .inr ⟨d, .head _, by simpa using hb, rfl⟩ + · exact .inl h + · exact .inr ⟨e, .tail _ he, h1, h2⟩ + +theorem TrEnv'.of_value (H : TrEnv' safety C Q venv) (h : C.find? name = some ci) + (hs : safety ≤ ci.safety) (hv : ci.deltaValue? = some v) : + TrExpr venv ci.levelParams [] v (.const ci.name (VLevel.params ci.levelParams.length)) := by + have {C n ci'} (hC : C.WF) : + (SMap.insert C n ci').find? name = some ci → + C.find? name = some ci ∨ n = name ∧ ci' = ci := by + rw [hC.find?_insert]; simp; split <;> simp +contextual [*] + induction H with + | empty => simp [SMap.find?] at h + | ignore h1 h2 H ih => + obtain h | ⟨rfl, rfl⟩ := this H.map_wf h + · exact ih h + · exact (h2 hs).elim + | «axiom» _ _ _ h1 H ih => + obtain h | ⟨rfl, rfl⟩ := this H.map_wf h + · exact (ih h).mono (VEnv.addConst_le h1) + · contradiction + | defn h2 h3 h4 h1 H ih => + have' le := (VEnv.addConst_le h1).trans VEnv.addDefEq_le + obtain h | ⟨rfl, rfl⟩ := this H.map_wf h + · exact (ih h).mono le + · cases hv + have := VEnv.IsDefEq.extra0 VEnv.addDefEq_self <| + (H.defn h2 h3 h4 h1).wf.ordered.defEqWF VEnv.addDefEq_self + let ⟨⟨⟨b1, b2, b3⟩, b4⟩, b5⟩ := h2 + refine ⟨_, b5.mono le, b2.symm ▸ b4.symm ▸ ⟨_, this.symm⟩⟩ + | mutualDef hblk hnd hfr _ hadd _ H ih => + have' le := (VEnv.addConsts_le hadd).trans VEnv.addDefEqs_le + rcases insertDefs_find? H.map_wf hfr hnd h with h | ⟨d, hd, rfl, rfl⟩ + · exact (ih h).mono le + · obtain ⟨d', hd', htr, hval⟩ := Ix.Theory.Named.List.Forall₂.forall_exists_l hblk _ hd + cases hv + have hdefeq := VEnv.IsDefEq.extra0 (VEnv.addDefEqs_self hd') + ((H.mutualDef hblk hnd hfr ‹_› hadd ‹_›).wf.ordered.defEqWF (VEnv.addDefEqs_self hd')) + let ⟨⟨b1, b2, b3⟩, b4⟩ := htr + exact ⟨_, hval.mono VEnv.addDefEqs_le, b2.symm ▸ b4.symm ▸ ⟨_, hdefeq.symm⟩⟩ + | thm h2 h3 h4 h5 h1 H ih => + have' le := VEnv.addConst_le h1 + obtain h | ⟨rfl, rfl⟩ := this H.map_wf h + · exact (ih h).mono le + · cases hv + let ⟨⟨⟨b1, b2, b3⟩, b4⟩, b5⟩ := h2 + dsimp only [ConstantInfo.name, ConstantInfo.levelParams, ConstantInfo.toConstantVal] at b2 b4 ⊢ + have hp := h5.mono le + have hb := h4.mono le + have hc := VEnv.HasType.const0 (VEnv.addConst_self h1) ⟨_, hp⟩ + rw [b4] at hc + refine ⟨_, b5.mono le, b2.symm ▸ b4.symm ▸ ?_⟩ + exact ⟨_, .proofIrrel hp hb hc⟩ + | «opaque» _ _ _ h1 H ih => + obtain h | ⟨rfl, rfl⟩ := this H.map_wf h + · exact (ih h).mono (VEnv.addConst_le h1) + · contradiction + | quot _ h1 H ih => + suffices ∀ {n k ci' P}, (∀ C env, Aligned safety C env → P C env → C.find? name = some ci) → + ∀ C env, Aligned safety C env → AddQuot1 n k ci' P C env → C.find? name = some ci by + refine (ih <| this (this <| this <| this ?_) _ _ H.aligned h1).mono h1.le + rintro _ _ _ ⟨rfl, rfl⟩; exact h + rintro n k ci' P ih C env wf ⟨_, h1, _, h2, h3, h4, h5⟩ + have wf' := wf.const h3 ⟨by cases safety <;> rfl, h2.2⟩ h4 rfl + obtain h | ⟨rfl, rfl⟩ := this wf.map_wf (ih _ _ wf' h5) + · exact h + · contradiction + | inductStaging h1 _ H ih => + exact (ih (h1.old_of_value H.map_wf h hv)).mono h1.le + | induct h1 H ih => + exact (ih (h1.old_of_value H.map_wf h hv)).mono h1.le + | inductBlock h1 H ih => + exact (ih (h1.old_of_value H.map_wf h hv)).mono h1.le + | inductNested h1 H ih => + exact (ih (h1.old_of_value H.map_wf h hv)).mono h1.le + | structEta _ H ih => + exact (ih h).mono VEnv.addStructEta_le + +nonrec theorem TrEnv.of_value (H : TrEnv safety env venv) (h : env.find? name = some ci) + (hs : safety ≤ ci.safety) (hv : ci.deltaValue? = some v) : + TrExpr venv ci.levelParams [] v (.const ci.name (VLevel.params ci.levelParams.length)) := + H.of_value (by rwa [← H.map_wf.find?'_eq_find?]) hs hv diff --git a/Ix/Theory/Named/Verify/Environment/MutualInductiveFixtures.lean b/Ix/Theory/Named/Verify/Environment/MutualInductiveFixtures.lean new file mode 100644 index 000000000..4fa9ec2de --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/MutualInductiveFixtures.lean @@ -0,0 +1,3150 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.InductiveFixtures +import Ix.Theory.Named.MutualInductiveFixtures + +open Ix.Theory (VLevel) + +/-! +# Mutual generation, preservation, and environment replay + +The real `Tree`/`TreeList` and indexed mutual fixtures instantiate the +arbitrary-block validator traces, generate one recursor per family with one +globally flattened minor/rule inventory, and compare every kernel metadata +record. Their Theory transactions stage all families before constructors, +all constructors before recursors, and all recursors before rules, then replay +the same phases through `TrEnv'.inductBlock` into aligned Verify environments. +-/ + +namespace Ix.Theory.Named.MutualInductiveReplayFixtures + +open Lean Meta Elab Term +open Kernel +open AddInductive +open VInductDecl +open Ix.Theory.Named.MutualInductiveFixtures +open Ix.Theory.Named.InductiveReplayFixtures + +local instance : Inhabited VEnv := ⟨.empty⟩ + +/-- Quote a kernel recursor type using the recursor metadata's own universe +parameter order. -/ +syntax "kernelRecConstant08C%" ident : term +syntax "kernelConstVType08C%" ident : term + +elab_rules : term + | `(kernelRecConstant08C% $n:ident) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .recInfo info ← getConstInfo name + | throwError "expected recursor metadata for {name}" + let type ← Ix.Theory.Named.Meta.expandExpr info.type + let type ← Ix.Theory.Named.Meta.ofExpr info.levelParams {} type + return toExpr ({ uvars := info.levelParams.length, type } : VConstant) + +/-- Quote a stored kernel metadata type in that record's own universe order. +Together with the explicit record-field checks below, this observes universe +permutations as well as the translated type expression. -/ +elab_rules : term + | `(kernelConstVType08C% $n:ident) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let info ← getConstInfo name + let type ← Ix.Theory.Named.Meta.expandExpr info.type + let type ← Ix.Theory.Named.Meta.ofExpr info.levelParams {} type + return toExpr type + +/-! ## Complete block metadata parity -/ + +/-- One block-wide comparison between the retained Theory generation and all +kernel inductive metadata. The nested lists preserve family/constructor +ownership and split each recursor's local rules out of the globally flattened +Theory rule list. -/ +structure MutualKernelBlockRow where + source : VInductDecl + generation : BlockGenerationChecked source + inductInfos : List ConstantInfo + ctorInfos : List (List ConstantInfo) + recInfos : List ConstantInfo + familyTypes : List VExpr + ctorTypes : List (List VExpr) + recTypes : List VExpr + ruleRhs : List (List VExpr) + +namespace MutualKernelBlockRow + +def ctorMatches (row : MutualKernelBlockRow) + (family : NormalizedFamily) (cidx : Nat) (info : ConstantInfo) + (constructor : NormalizedCtor) (storedType : VExpr) : Bool := + match info with + | .ctorInfo ctor => + ctor.name == constructor.raw.name && + ctor.levelParams.length == row.source.uvars && + ctor.induct == family.raw.name && + ctor.cidx == cidx && + ctor.numParams == row.source.nparams && + ctor.numFields == constructor.view.fields.length && + !ctor.isUnsafe && storedType == constructor.raw.type + | _ => false + +def ctorsMatch (row : MutualKernelBlockRow) + (family : NormalizedFamily) : + List ConstantInfo → List NormalizedCtor → List VExpr → Nat → Bool + | [], [], [], _ => true + | info :: infos, constructor :: constructors, storedType :: storedTypes, + cidx => + row.ctorMatches family cidx info constructor storedType && + row.ctorsMatch family infos constructors storedTypes (cidx + 1) + | _, _, _, _ => false + +def recursorMatches (row : MutualKernelBlockRow) + (family : NormalizedFamily) (offset : Nat) + (info : ConstantInfo) (storedType : VExpr) + (rhs : List VExpr) : Bool := + match info with + | .recInfo rec => + rec.name == .str family.raw.name "rec" && + rec.levelParams.length == row.generation.recUvars && + rec.all == row.source.types.map (·.name) && + rec.numParams == row.source.nparams && + rec.numIndices == family.view.indices.length && + rec.numMotives == row.generation.familyCount && + rec.numMinors == row.generation.minorCount && + rec.k == row.generation.kTarget && + !rec.isUnsafe && + rec.rules.map (fun rule => (rule.ctor, rule.nfields)) == + family.ctorPairs.map (fun constructor => + (constructor.raw.name, constructor.view.fields.length)) && + storedType == (row.generation.recursor family).type && + rhs == ((row.generation.generatedRules.drop offset).take + family.ctorPairs.length |>.map (·.rhs)) + | _ => false + +def familiesMatch (row : MutualKernelBlockRow) : + List NormalizedFamily → List ConstantInfo → List (List ConstantInfo) → + List ConstantInfo → List VExpr → List (List VExpr) → List VExpr → + List (List VExpr) → Nat → Bool + | [], [], [], [], [], [], [], [], _ => true + | family :: families, inductInfo :: inductInfos, + ctorInfos :: ctorInfosTail, recInfo :: recInfos, + familyType :: familyTypes, ctorTypes :: ctorTypesTail, + recType :: recTypes, ruleRhs :: ruleRhsTail, offset => + (match inductInfo with + | .inductInfo induct => + induct.name == family.raw.name && + induct.levelParams.length == row.source.uvars && + induct.numParams == row.source.nparams && + induct.numIndices == family.view.indices.length && + induct.all == row.source.types.map (·.name) && + induct.ctors == family.raw.ctors.map (·.name) && + induct.numNested == 0 && + induct.isRec == row.generation.isRec && + induct.isReflexive == row.generation.isReflexive && + !induct.isUnsafe && + familyType == family.raw.type + | _ => false) && + row.ctorsMatch family ctorInfos family.ctorPairs ctorTypes 0 && + row.recursorMatches family offset recInfo recType ruleRhs && + row.familiesMatch families inductInfos ctorInfosTail recInfos + familyTypes ctorTypesTail recTypes ruleRhsTail + (offset + family.ctorPairs.length) + | _, _, _, _, _, _, _, _, _ => false + +/-- Every list must agree position-for-position; no truncated family, +constructor, recursor, or rule inventory can satisfy the comparison. -/ +def agrees (row : MutualKernelBlockRow) : Bool := + row.familiesMatch row.generation.families row.inductInfos row.ctorInfos + row.recInfos row.familyTypes row.ctorTypes row.recTypes row.ruleRhs 0 + +end MutualKernelBlockRow + +/-! ## Executable kernel validation -/ + +def treeKernelInfo : ConstantInfo := kernelInductInfo% Tree +def treeListKernelInfo : ConstantInfo := kernelInductInfo% TreeList +def treeLeafKernelInfo : ConstantInfo := kernelCtorInfo% Tree.leaf +def treeNodeKernelInfo : ConstantInfo := kernelCtorInfo% Tree.node +def treeBranchKernelInfo : ConstantInfo := kernelCtorInfo% Tree.branch +def treeListNilKernelInfo : ConstantInfo := kernelCtorInfo% TreeList.nil +def treeListConsKernelInfo : ConstantInfo := kernelCtorInfo% TreeList.cons +def treeRecKernelInfo : ConstantInfo := kernelRecInfo% Tree.rec +def treeListRecKernelInfo : ConstantInfo := kernelRecInfo% TreeList.rec +def treeRecKernelConstant : VConstant := kernelRecConstant08C% Tree.rec +def treeListRecKernelConstant : VConstant := + kernelRecConstant08C% TreeList.rec +def treeLeafKernelRuleRhs : VExpr := kernelRecRuleRhs% Tree.rec 0 +def treeNodeKernelRuleRhs : VExpr := kernelRecRuleRhs% Tree.rec 1 +def treeBranchKernelRuleRhs : VExpr := kernelRecRuleRhs% Tree.rec 2 +def treeListNilKernelRuleRhs : VExpr := kernelRecRuleRhs% TreeList.rec 0 +def treeListConsKernelRuleRhs : VExpr := kernelRecRuleRhs% TreeList.rec 1 + +example : treeRecKernelConstant = + treeGeneration.recursors[0].toVConstant := rfl +example : treeListRecKernelConstant = + treeGeneration.recursors[1].toVConstant := rfl +example : treeLeafKernelRuleRhs = treeGeneration.generatedRules[0].rhs := rfl +example : treeNodeKernelRuleRhs = treeGeneration.generatedRules[1].rhs := rfl +example : treeBranchKernelRuleRhs = treeGeneration.generatedRules[2].rhs := rfl +example : treeListNilKernelRuleRhs = treeGeneration.generatedRules[3].rhs := rfl +example : treeListConsKernelRuleRhs = treeGeneration.generatedRules[4].rhs := rfl + +def treeKernelType : InductiveType where + name := treeKernelInfo.name + type := treeKernelInfo.type + ctors := [ + ⟨treeLeafKernelInfo.name, treeLeafKernelInfo.type⟩, + ⟨treeNodeKernelInfo.name, treeNodeKernelInfo.type⟩, + ⟨treeBranchKernelInfo.name, treeBranchKernelInfo.type⟩] + +def treeListKernelType : InductiveType where + name := treeListKernelInfo.name + type := treeListKernelInfo.type + ctors := [ + ⟨treeListNilKernelInfo.name, treeListNilKernelInfo.type⟩, + ⟨treeListConsKernelInfo.name, treeListConsKernelInfo.type⟩] + +def treeKernelTypes : List InductiveType := + [treeKernelType, treeListKernelType] + +def treeKernelContext : AddInductive.Context where + env := Kernel.Environment.ofConstants `_mutualTree ({} : ConstMap) + lparams := [`u] + safety := .safe + allowPrimitive := false + +def treeExecutionResult := + AddInductive.buildNormalizationCandidateExecution 1 treeKernelTypes 0 false + treeKernelContext + +theorem treeExecutionResult_isOk : treeExecutionResult.isOk = true := by + native_decide + +def treeProducedExecution : + { execution // treeExecutionResult = .ok execution } := + match h : treeExecutionResult with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := treeExecutionResult_isOk + rw [h] at hOk + contradiction + +def treeExecution := treeProducedExecution.val + +def treeFamilyValidationResult := + FamilyValidationBlockRun.buildExecution 1 treeKernelTypes treeKernelContext + +theorem treeFamilyValidationResult_isOk : + treeFamilyValidationResult.isOk = true := by + native_decide + +def treeProducedFamilyValidation : + { run // treeFamilyValidationResult = .ok run } := + match h : treeFamilyValidationResult with + | .ok run => ⟨run, rfl⟩ + | .error _ => by + have hOk := treeFamilyValidationResult_isOk + rw [h] at hOk + contradiction + +def treeFamilyValidation := treeProducedFamilyValidation.val + +def treeConstructorContext : AddInductive.Context := + { treeExecution.validationContext with env := treeExecution.familyEnv } + +def treeConstructorValidationResult := + ConstructorBlockValidationRun.buildExecution treeKernelTypes + treeExecution.stats false treeConstructorContext + +theorem treeConstructorValidationResult_isOk : + treeConstructorValidationResult.isOk = true := by + native_decide + +def treeProducedConstructorValidation : + { run // treeConstructorValidationResult = .ok run } := + match h : treeConstructorValidationResult with + | .ok run => ⟨run, rfl⟩ + | .error _ => by + have hOk := treeConstructorValidationResult_isOk + rw [h] at hOk + contradiction + +def treeConstructorValidation := treeProducedConstructorValidation.val + +/-- The real positivity traversal selects both sibling targets and records the +one Pi binder above `Tree.branch`'s recursive occurrence. -/ +theorem treeConstructorTargets_exact : + treeConstructorValidation.traces.targets = + [ + [[none], + [some { familyIdx := 1, binderDepth := 0 }], + [some { familyIdx := 1, binderDepth := 1 }]], + [[], + [some { familyIdx := 0, binderDepth := 0 }, + some { familyIdx := 1, binderDepth := 0 }]] + ] := by + native_decide + +example : treeFamilyValidation.parameters.size = 1 := + treeFamilyValidation.params_size + +example : treeFamilyValidation.result.stats.nindices = #[0, 0] := by + native_decide + +#guard AddInductive.levelStructEq treeFamilyValidation.resultLevel + (.succ (.param `u)) + +#guard AddInductive.levelStructEq treeExecution.stats.resultLevel + (.succ (.param `u)) + +def indexedTreeKernelInfo : ConstantInfo := kernelInductInfo% IndexedTree +def indexedTreeListKernelInfo : ConstantInfo := + kernelInductInfo% IndexedTreeList +def indexedTreeLeafKernelInfo : ConstantInfo := + kernelCtorInfo% IndexedTree.leaf +def indexedTreeNodeKernelInfo : ConstantInfo := + kernelCtorInfo% IndexedTree.node +def indexedTreeListNilKernelInfo : ConstantInfo := + kernelCtorInfo% IndexedTreeList.nil +def indexedTreeListConsKernelInfo : ConstantInfo := + kernelCtorInfo% IndexedTreeList.cons +def indexedTreeRecKernelInfo : ConstantInfo := + kernelRecInfo% IndexedTree.rec +def indexedTreeListRecKernelInfo : ConstantInfo := + kernelRecInfo% IndexedTreeList.rec +def indexedTreeRecKernelConstant : VConstant := + kernelRecConstant08C% IndexedTree.rec +def indexedTreeListRecKernelConstant : VConstant := + kernelRecConstant08C% IndexedTreeList.rec +def indexedTreeLeafKernelRuleRhs : VExpr := + kernelRecRuleRhs% IndexedTree.rec 0 +def indexedTreeNodeKernelRuleRhs : VExpr := + kernelRecRuleRhs% IndexedTree.rec 1 +def indexedTreeListNilKernelRuleRhs : VExpr := + kernelRecRuleRhs% IndexedTreeList.rec 0 +def indexedTreeListConsKernelRuleRhs : VExpr := + kernelRecRuleRhs% IndexedTreeList.rec 1 + +example : indexedTreeRecKernelConstant = + indexedTreeGeneration.recursors[0].toVConstant := rfl +example : indexedTreeListRecKernelConstant = + indexedTreeGeneration.recursors[1].toVConstant := rfl +example : indexedTreeLeafKernelRuleRhs = + indexedTreeGeneration.generatedRules[0].rhs := rfl +example : indexedTreeNodeKernelRuleRhs = + indexedTreeGeneration.generatedRules[1].rhs := rfl +example : indexedTreeListNilKernelRuleRhs = + indexedTreeGeneration.generatedRules[2].rhs := rfl +example : indexedTreeListConsKernelRuleRhs = + indexedTreeGeneration.generatedRules[3].rhs := rfl + +/-- Complete kernel/Theory metadata row for the unindexed mutual block. -/ +def treeKernelBlockRow : MutualKernelBlockRow where + source := treeDecl + generation := treeGeneration + inductInfos := [treeKernelInfo, treeListKernelInfo] + ctorInfos := [ + [treeLeafKernelInfo, treeNodeKernelInfo, treeBranchKernelInfo], + [treeListNilKernelInfo, treeListConsKernelInfo]] + recInfos := [treeRecKernelInfo, treeListRecKernelInfo] + familyTypes := [kernelConstVType08C% Tree, + kernelConstVType08C% TreeList] + ctorTypes := [ + [kernelConstVType08C% Tree.leaf, kernelConstVType08C% Tree.node, + kernelConstVType08C% Tree.branch], + [kernelConstVType08C% TreeList.nil, + kernelConstVType08C% TreeList.cons]] + recTypes := [kernelConstVType08C% Tree.rec, + kernelConstVType08C% TreeList.rec] + ruleRhs := [ + [treeLeafKernelRuleRhs, treeNodeKernelRuleRhs, + treeBranchKernelRuleRhs], + [treeListNilKernelRuleRhs, treeListConsKernelRuleRhs]] + +#guard treeKernelBlockRow.agrees + +/-- Complete kernel/Theory metadata row for the indexed mutual block. -/ +def indexedTreeKernelBlockRow : MutualKernelBlockRow where + source := indexedTreeDecl + generation := indexedTreeGeneration + inductInfos := [indexedTreeKernelInfo, indexedTreeListKernelInfo] + ctorInfos := [ + [indexedTreeLeafKernelInfo, indexedTreeNodeKernelInfo], + [indexedTreeListNilKernelInfo, indexedTreeListConsKernelInfo]] + recInfos := [indexedTreeRecKernelInfo, indexedTreeListRecKernelInfo] + familyTypes := [kernelConstVType08C% IndexedTree, + kernelConstVType08C% IndexedTreeList] + ctorTypes := [ + [kernelConstVType08C% IndexedTree.leaf, + kernelConstVType08C% IndexedTree.node], + [kernelConstVType08C% IndexedTreeList.nil, + kernelConstVType08C% IndexedTreeList.cons]] + recTypes := [kernelConstVType08C% IndexedTree.rec, + kernelConstVType08C% IndexedTreeList.rec] + ruleRhs := [ + [indexedTreeLeafKernelRuleRhs, indexedTreeNodeKernelRuleRhs], + [indexedTreeListNilKernelRuleRhs, indexedTreeListConsKernelRuleRhs]] + +#guard indexedTreeKernelBlockRow.agrees + +def indexedTreeKernelType : InductiveType where + name := indexedTreeKernelInfo.name + type := indexedTreeKernelInfo.type + ctors := [ + ⟨indexedTreeLeafKernelInfo.name, indexedTreeLeafKernelInfo.type⟩, + ⟨indexedTreeNodeKernelInfo.name, indexedTreeNodeKernelInfo.type⟩] + +def indexedTreeListKernelType : InductiveType where + name := indexedTreeListKernelInfo.name + type := indexedTreeListKernelInfo.type + ctors := [ + ⟨indexedTreeListNilKernelInfo.name, indexedTreeListNilKernelInfo.type⟩, + ⟨indexedTreeListConsKernelInfo.name, indexedTreeListConsKernelInfo.type⟩] + +def indexedTreeKernelTypes : List InductiveType := + [indexedTreeKernelType, indexedTreeListKernelType] + +def indexedTreeKernelContext : AddInductive.Context where + env := Kernel.Environment.ofConstants `_mutualIndexedTree natMap + lparams := [`u] + safety := .safe + allowPrimitive := false + +def indexedTreeExecutionResult := + AddInductive.buildNormalizationCandidateExecution 1 indexedTreeKernelTypes + 0 false indexedTreeKernelContext + +theorem indexedTreeExecutionResult_isOk : + indexedTreeExecutionResult.isOk = true := by + native_decide + +def indexedTreeProducedExecution : + { execution // indexedTreeExecutionResult = .ok execution } := + match h : indexedTreeExecutionResult with + | .ok execution => ⟨execution, rfl⟩ + | .error _ => by + have hOk := indexedTreeExecutionResult_isOk + rw [h] at hOk + contradiction + +def indexedTreeExecution := indexedTreeProducedExecution.val + +def indexedTreeFamilyValidationResult := + FamilyValidationBlockRun.buildExecution 1 indexedTreeKernelTypes + indexedTreeKernelContext + +theorem indexedTreeFamilyValidationResult_isOk : + indexedTreeFamilyValidationResult.isOk = true := by + native_decide + +def indexedTreeProducedFamilyValidation : + { run // indexedTreeFamilyValidationResult = .ok run } := + match h : indexedTreeFamilyValidationResult with + | .ok run => ⟨run, rfl⟩ + | .error _ => by + have hOk := indexedTreeFamilyValidationResult_isOk + rw [h] at hOk + contradiction + +def indexedTreeFamilyValidation := indexedTreeProducedFamilyValidation.val + +def indexedTreeConstructorContext : AddInductive.Context := + { indexedTreeExecution.validationContext with + env := indexedTreeExecution.familyEnv } + +def indexedTreeConstructorValidationResult := + ConstructorBlockValidationRun.buildExecution indexedTreeKernelTypes + indexedTreeExecution.stats false indexedTreeConstructorContext + +theorem indexedTreeConstructorValidationResult_isOk : + indexedTreeConstructorValidationResult.isOk = true := by + native_decide + +def indexedTreeProducedConstructorValidation : + { run // indexedTreeConstructorValidationResult = .ok run } := + match h : indexedTreeConstructorValidationResult with + | .ok run => ⟨run, rfl⟩ + | .error _ => by + have hOk := indexedTreeConstructorValidationResult_isOk + rw [h] at hOk + contradiction + +def indexedTreeConstructorValidation := + indexedTreeProducedConstructorValidation.val + +/-- Indexed recursive fields retain sibling ordinals after the ordinary Nat +binder, while nonrecursive fields occupy explicit `none` slots. -/ +theorem indexedTreeConstructorTargets_exact : + indexedTreeConstructorValidation.traces.targets = + [ + [[none], + [none, some { familyIdx := 1, binderDepth := 0 }]], + [[], + [none, + some { familyIdx := 0, binderDepth := 0 }, + some { familyIdx := 1, binderDepth := 0 }]] + ] := by + native_decide + +example : indexedTreeFamilyValidation.parameters.size = 1 := + indexedTreeFamilyValidation.params_size + +example : indexedTreeFamilyValidation.result.stats.nindices = #[1, 1] := by + native_decide + +#guard AddInductive.levelStructEq indexedTreeFamilyValidation.resultLevel + (.succ (.param `u)) + +/-! ## Phase-specific failures -/ + +def treeParameterMismatchType : InductiveType := + { treeListKernelType with + type := .forallE `α (.sort .zero) (.sort (.succ (.param `u))) .default } + +#guard match observeFamilyValidationBlock 1 + [treeKernelType, treeParameterMismatchType] treeKernelContext with + | .error (.other message) => + message == "parameters of all inductive datatypes must match" + | _ => false + +def treeResultUniverseMismatchType : InductiveType := + { treeListKernelType with + type := .forallE `α (.sort (.succ (.param `u))) (.sort .zero) .default } + +#guard match observeFamilyValidationBlock 1 + [treeKernelType, treeResultUniverseMismatchType] treeKernelContext with + | .error (.other message) => + message == "mutually inductive types must live in the same universe" + | _ => false + +/-- Reusing the original family statistics after swapping source owners +reaches constructor validation and fails at the first now-misowned return. -/ +def treeReorderedConstructorResult := + checkConstructors #[treeListKernelType, treeKernelType] + treeExecution.stats false treeConstructorContext + +#guard match treeReorderedConstructorResult with + | .error (.other message) => + message == + "invalid return type for 'Ix.Theory.Named.MutualInductiveFixtures.TreeList.nil'" + | _ => false + +def treeReorderedView : VInductDecl := + { treeDecl with types := [treeListType, treeType] } + +/- Raw/view normalization rejects family reordering before semantic evidence +can be attached to the dependent candidate list. -/ +#guard (normalization? treeDecl treeReorderedView).isNone + +/-! The host elaborator diagnostics independently pin the corresponding +family-validation phases in Lean itself. -/ + +namespace KernelPhases + +universe v + +/-- +error: Invalid mutually inductive types: Parameter `α` has type + Prop +of sort `Type` but is expected to have type + Type v +of sort `Type (v + 1)` +-/ +#guard_msgs (whitespace := lax) in +mutual +inductive ParamA (α : Type v) : Type v +inductive ParamB (α : Prop) : Type v +end + +/-- +error: Invalid mutually inductive types: The resulting type of this declaration + Prop +differs from a preceding one + Type v + +Note: All inductive types declared in the same `mutual` block must belong to the same type universe +-/ +#guard_msgs (whitespace := lax) in +mutual +inductive UniverseA (α : Type v) : Type v +inductive UniverseB (α : Type v) : Prop +end + +end KernelPhases + +/-! ## Tree/TreeList Theory semantics -/ + +def treeBlockEnv : VEnv := + (VEnv.empty.stageInductiveTypes treeDecl.types).get! + +theorem treeStage : + VEnv.empty.stageInductiveTypes treeDecl.types = some treeBlockEnv := by + rfl + +theorem empty_le_treeBlockEnv : VEnv.empty ≤ treeBlockEnv where + constants h := by simp [VEnv.empty] at h + defeqs h := h.elim + structEtas h := h.elim + +theorem treeFamilyTypeWF (type : VInductiveType) + (h : type = treeType ∨ type = treeListType) : + type.type.WF VEnv.empty type.uvars [] := by + rcases h with rfl | rfl <;> + refine ⟨.sort (.imax (.succ (.succ (.param 0))) + (.succ (.succ (.param 0)))), VEnv.HasType.forallE ?_ ?_⟩ <;> + exact VEnv.HasType.sort (by decide) + +theorem treeCtorWF (ctor : VConstVal) + (h : ctor ∈ treeType.ctors ∨ ctor ∈ treeListType.ctors) : + ctor.type.WF treeBlockEnv 1 [] := by + have hTree : treeBlockEnv.constants ``Tree = + some treeType.toVConstant := by rfl + have hTreeList : treeBlockEnv.constants ``TreeList = + some treeListType.toVConstant := by rfl + rcases h with h | h + · simp [treeType] at h + rcases h with (rfl | rfl | rfl) + · exact ⟨_, by type_tac⟩ + · exact ⟨_, by type_tac⟩ + · exact ⟨_, by type_tac⟩ + · simp [treeListType] at h + rcases h with (rfl | rfl) + · exact ⟨_, by type_tac⟩ + · exact ⟨_, by type_tac⟩ + +theorem treeNormalizationBlockWF : + (Normalization.identity treeDecl).BlockWF VEnv.empty treeBlockEnv := by + refine ⟨treeStage, ?_⟩ + change List.Forall₂ _ [treeType, treeListType] [treeType, treeListType] + apply List.Forall₂.cons + · refine ⟨?_, ?_⟩ + · exact VEnv.IsDefEqU.refl (treeFamilyTypeWF treeType (.inl rfl)) + · apply List.Forall₂.rfl + intro ctor h + exact VEnv.IsDefEqU.refl (treeCtorWF ctor (.inl h)) + · apply List.Forall₂.cons + · refine ⟨?_, ?_⟩ + · exact VEnv.IsDefEqU.refl (treeFamilyTypeWF treeListType (.inr rfl)) + · apply List.Forall₂.rfl + intro ctor h + exact VEnv.IsDefEqU.refl (treeCtorWF ctor (.inr h)) + · exact .nil + +theorem treeLeafSemantic : + let constructor := CheckedCtor.ofBlock treeDecl treeType.ctors[0] + checkedBlockFieldsWF VEnv.empty 1 (.succ (.param 0)) [[], []] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + VEnv.empty.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN (VExpr.liftTelN constructor.fields.length [] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[0]).fields = + [.bvar 0] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[0]).recursiveAt = + [none] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[0]).resultIndices = + [] by rfl] + exact ⟨⟨⟨.succ (.param 0), .bvar .zero, + .inr (VLevel.le_refl _)⟩, trivial⟩, .nil⟩ + +theorem treeNodeSemantic : + let constructor := CheckedCtor.ofBlock treeDecl treeType.ctors[1] + checkedBlockFieldsWF VEnv.empty 1 (.succ (.param 0)) [[], []] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + VEnv.empty.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN (VExpr.liftTelN constructor.fields.length [] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[1]).fields = + [.app (.const ``TreeList [.param 0]) (.bvar 0)] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[1]).recursiveAt = + [some ({ + fieldIndex := 0 + binders := [] + targetType := 1 + indices := [] } : RecArg)] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[1]).resultIndices = + [] by rfl] + exact ⟨⟨⟨rfl, trivial, .nil⟩, trivial⟩, .nil⟩ + +theorem treeBranchSemantic : + let constructor := CheckedCtor.ofBlock treeDecl treeType.ctors[2] + checkedBlockFieldsWF VEnv.empty 1 (.succ (.param 0)) [[], []] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + VEnv.empty.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN (VExpr.liftTelN constructor.fields.length [] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[2]).fields = + [.forallE (.bvar 0) + (.app (.const ``TreeList [.param 0]) (.bvar 1))] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[2]).recursiveAt = + [some ({ + fieldIndex := 0 + binders := [.bvar 0] + targetType := 1 + indices := [] } : RecArg)] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeType.ctors[2]).resultIndices = + [] by rfl] + exact ⟨ + ⟨⟨rfl, ⟨⟨⟨.succ (.param 0), .bvar .zero⟩, trivial⟩, .nil⟩⟩, + trivial⟩, + .nil⟩ + +theorem treeListNilSemantic : + let constructor := CheckedCtor.ofBlock treeDecl treeListType.ctors[0] + checkedBlockFieldsWF VEnv.empty 1 (.succ (.param 0)) [[], []] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + VEnv.empty.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN (VExpr.liftTelN constructor.fields.length [] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock treeDecl treeListType.ctors[0]).fields = + [] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeListType.ctors[0]).recursiveAt = + [] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeListType.ctors[0]).resultIndices = + [] by rfl] + exact ⟨trivial, .nil⟩ + +theorem treeListConsSemantic : + let constructor := CheckedCtor.ofBlock treeDecl treeListType.ctors[1] + checkedBlockFieldsWF VEnv.empty 1 (.succ (.param 0)) [[], []] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + VEnv.empty.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN (VExpr.liftTelN constructor.fields.length [] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock treeDecl treeListType.ctors[1]).fields = + [.app (.const ``Tree [.param 0]) (.bvar 0), + .app (.const ``TreeList [.param 0]) (.bvar 1)] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeListType.ctors[1]).recursiveAt = + [some ({ + fieldIndex := 0 + binders := [] + targetType := 0 + indices := [] } : RecArg), + some ({ + fieldIndex := 1 + binders := [] + targetType := 1 + indices := [] } : RecArg)] by rfl] + rw [show (CheckedCtor.ofBlock treeDecl treeListType.ctors[1]).resultIndices = + [] by rfl] + exact ⟨ + ⟨⟨rfl, trivial, .nil⟩, + ⟨⟨rfl, trivial, .nil⟩, trivial⟩⟩, + .nil⟩ + +theorem treeCheckedBlockWF : + treeChecked.WF VEnv.empty (.succ (.param 0)) := by + have hparams : treeChecked.params = + [.sort (.succ (.param 0))] := rfl + have hindices : treeChecked.families.indices = [[], []] := rfl + have hlevels : treeChecked.families.resultLevels = + [.succ (.param 0), .succ (.param 0)] := rfl + have hconstructors : treeChecked.families.constructors = + [treeType.ctors.map (CheckedCtor.ofBlock treeDecl), + treeListType.ctors.map (CheckedCtor.ofBlock treeDecl)] := rfl + rw [CheckedBlock.WF, hindices, hlevels, hconstructors] + rw [hparams] + simp only [checkedFamilyListsWF] + refine ⟨rfl, ?_, ?_, rfl, ?_, ?_⟩ + · exact ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩ + · intro ctor h + simp [treeType] at h + rcases h with rfl | rfl | rfl + · exact treeLeafSemantic + · exact treeNodeSemantic + · exact treeBranchSemantic + · exact ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩ + · refine ⟨?_, trivial⟩ + intro ctor h + simp [treeListType] at h + rcases h with rfl | rfl + · exact treeListNilSemantic + · exact treeListConsSemantic + +def treeNormalizedBlock : NormalizedCheckedBlock treeDecl where + normalization := Normalization.identity treeDecl + checked := treeChecked + checked_eq := (Option.some_get (x := treeDecl.checkedBlock?) + (by decide)).symm + +def treeValidatedBlock : ValidatedBlock treeDecl where + block := treeNormalizedBlock + resultLevel := .succ (.param 0) + +/-- Exact validation-only semantic package for the unindexed mutual block. -/ +def treeValidationCertificate : ValidationCertificate treeDecl VEnv.empty where + validated := treeValidatedBlock + blockEnv := treeBlockEnv + wf := ⟨treeNormalizationBlockWF, treeCheckedBlockWF⟩ + +/-! ## IndexedTree/IndexedTreeList Theory semantics -/ + +def indexedTreeBlockEnv : VEnv := + (natFinalEnv.stageInductiveTypes indexedTreeDecl.types).get! + +theorem indexedTreeStage : + natFinalEnv.stageInductiveTypes indexedTreeDecl.types = + some indexedTreeBlockEnv := by + rfl + +theorem indexedTreeFamilyTypeWF (type : VInductiveType) + (h : type = indexedTreeType ∨ type = indexedTreeListType) : + type.type.WF natFinalEnv type.uvars [] := by + have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + rcases h with rfl | rfl <;> + exact ⟨_, by type_tac⟩ + +theorem indexedTreeCtorWF (ctor : VConstVal) + (h : ctor ∈ indexedTreeType.ctors ∨ + ctor ∈ indexedTreeListType.ctors) : + ctor.type.WF indexedTreeBlockEnv 1 [] := by + have hNat : indexedTreeBlockEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := by rfl + have hZero : indexedTreeBlockEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := by rfl + have hSucc : indexedTreeBlockEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := by rfl + have hTree : indexedTreeBlockEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := by rfl + have hTreeList : indexedTreeBlockEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := by rfl + rcases h with h | h + · simp [indexedTreeType] at h + rcases h with (rfl | rfl) + · exact ⟨_, by type_tac⟩ + · exact ⟨_, by type_tac⟩ + · simp [indexedTreeListType] at h + rcases h with (rfl | rfl) + · exact ⟨_, by type_tac⟩ + · exact ⟨_, by type_tac⟩ + +theorem indexedTreeNormalizationBlockWF : + (Normalization.identity indexedTreeDecl).BlockWF + natFinalEnv indexedTreeBlockEnv := by + refine ⟨indexedTreeStage, ?_⟩ + change List.Forall₂ _ [indexedTreeType, indexedTreeListType] + [indexedTreeType, indexedTreeListType] + apply List.Forall₂.cons + · refine ⟨?_, ?_⟩ + · exact VEnv.IsDefEqU.refl + (indexedTreeFamilyTypeWF indexedTreeType (.inl rfl)) + · apply List.Forall₂.rfl + intro ctor h + exact VEnv.IsDefEqU.refl (indexedTreeCtorWF ctor (.inl h)) + · apply List.Forall₂.cons + · refine ⟨?_, ?_⟩ + · exact VEnv.IsDefEqU.refl + (indexedTreeFamilyTypeWF indexedTreeListType (.inr rfl)) + · apply List.Forall₂.rfl + intro ctor h + exact VEnv.IsDefEqU.refl (indexedTreeCtorWF ctor (.inr h)) + · exact .nil + +theorem indexedTreeLeafSemantic : + let constructor := CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[0] + checkedBlockFieldsWF natFinalEnv 1 (.succ (.param 0)) + [[.const ``Nat []], [.const ``Nat []]] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + natFinalEnv.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN + (VExpr.liftTelN constructor.fields.length [.const ``Nat []] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[0]).fields = [.bvar 0] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[0]).recursiveAt = [none] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[0]).resultIndices = [.const ``Nat.zero []] by rfl] + constructor + · exact ⟨⟨.succ (.param 0), .bvar .zero, + .inr (VLevel.le_refl _)⟩, trivial⟩ + · have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : natFinalEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + exact .cons (by type_tac) .nil + +theorem indexedTreeNodeSemantic : + let constructor := CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[1] + checkedBlockFieldsWF natFinalEnv 1 (.succ (.param 0)) + [[.const ``Nat []], [.const ``Nat []]] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + natFinalEnv.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN + (VExpr.liftTelN constructor.fields.length [.const ``Nat []] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[1]).fields = + [.const ``Nat [], + (VExpr.const ``IndexedTreeList [.param 0]).app (.bvar 1) + |>.app (.bvar 0)] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[1]).recursiveAt = + [none, some ({ + fieldIndex := 1 + binders := [] + targetType := 1 + indices := [.bvar 0] } : RecArg)] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeType.ctors[1]).resultIndices = + [(VExpr.const ``Nat.succ []).app (.bvar 1)] by rfl] + have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hSucc : natFinalEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + refine ⟨?_, ?_⟩ + · refine ⟨⟨.succ .zero, (by type_tac), + .inr (VLevel.succ_le_succ VLevel.zero_le)⟩, ?_⟩ + exact ⟨⟨rfl, trivial, .cons (by type_tac) .nil⟩, trivial⟩ + · exact .cons (by type_tac) .nil + +theorem indexedTreeListNilSemantic : + let constructor := CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[0] + checkedBlockFieldsWF natFinalEnv 1 (.succ (.param 0)) + [[.const ``Nat []], [.const ``Nat []]] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + natFinalEnv.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN + (VExpr.liftTelN constructor.fields.length [.const ``Nat []] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[0]).fields = [] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[0]).recursiveAt = [] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[0]).resultIndices = + [.const ``Nat.zero []] by rfl] + refine ⟨trivial, ?_⟩ + have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : natFinalEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + exact .cons (by type_tac) .nil + +theorem indexedTreeListConsSemantic : + let constructor := CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[1] + checkedBlockFieldsWF natFinalEnv 1 (.succ (.param 0)) + [[.const ``Nat []], [.const ``Nat []]] + constructor.fields constructor.recursiveAt + [.sort (.succ (.param 0))] 0 ∧ + natFinalEnv.SpineWF 1 + (constructor.fields.reverse ++ [.sort (.succ (.param 0))]) + (VExpr.forallN + (VExpr.liftTelN constructor.fields.length [.const ``Nat []] 0) + (.sort (.succ (.param 0)))) + constructor.resultIndices (.sort (.succ (.param 0))) := by + dsimp only + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[1]).fields = + [.const ``Nat [], + (VExpr.const ``IndexedTree [.param 0]).app (.bvar 1) + |>.app (.bvar 0), + (VExpr.const ``IndexedTreeList [.param 0]).app (.bvar 2) + |>.app (.bvar 1)] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[1]).recursiveAt = + [none, + some ({ + fieldIndex := 1 + binders := [] + targetType := 0 + indices := [.bvar 0] } : RecArg), + some ({ + fieldIndex := 2 + binders := [] + targetType := 1 + indices := [.bvar 1] } : RecArg)] by rfl] + rw [show (CheckedCtor.ofBlock indexedTreeDecl + indexedTreeListType.ctors[1]).resultIndices = + [(VExpr.const ``Nat.succ []).app (.bvar 2)] by rfl] + have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hSucc : natFinalEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + refine ⟨?_, ?_⟩ + · refine ⟨⟨.succ .zero, (by type_tac), + .inr (VLevel.succ_le_succ VLevel.zero_le)⟩, ?_⟩ + refine ⟨⟨rfl, trivial, .cons (by type_tac) .nil⟩, ?_⟩ + exact ⟨⟨rfl, trivial, .cons (by type_tac) .nil⟩, trivial⟩ + · exact .cons (by type_tac) .nil + +theorem indexedTreeCheckedBlockWF : + indexedTreeChecked.WF natFinalEnv (.succ (.param 0)) := by + have hparams : indexedTreeChecked.params = + [.sort (.succ (.param 0))] := rfl + have hindices : indexedTreeChecked.families.indices = + [[.const ``Nat []], [.const ``Nat []]] := rfl + have hlevels : indexedTreeChecked.families.resultLevels = + [.succ (.param 0), .succ (.param 0)] := rfl + have hconstructors : indexedTreeChecked.families.constructors = + [indexedTreeType.ctors.map (CheckedCtor.ofBlock indexedTreeDecl), + indexedTreeListType.ctors.map + (CheckedCtor.ofBlock indexedTreeDecl)] := rfl + rw [CheckedBlock.WF, hindices, hlevels, hconstructors] + rw [hparams] + simp only [checkedFamilyListsWF] + have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + refine ⟨rfl, ?_, ?_, rfl, ?_, ?_⟩ + · exact ⟨⟨_, VEnv.HasType.sort (by decide)⟩, + ⟨⟨_, (by type_tac)⟩, trivial⟩⟩ + · intro ctor h + simp [indexedTreeType] at h + rcases h with rfl | rfl + · exact indexedTreeLeafSemantic + · exact indexedTreeNodeSemantic + · exact ⟨⟨_, VEnv.HasType.sort (by decide)⟩, + ⟨⟨_, (by type_tac)⟩, trivial⟩⟩ + · refine ⟨?_, trivial⟩ + intro ctor h + simp [indexedTreeListType] at h + rcases h with rfl | rfl + · exact indexedTreeListNilSemantic + · exact indexedTreeListConsSemantic + +def indexedTreeNormalizedBlock : NormalizedCheckedBlock indexedTreeDecl where + normalization := Normalization.identity indexedTreeDecl + checked := indexedTreeChecked + checked_eq := (Option.some_get (x := indexedTreeDecl.checkedBlock?) + (by decide)).symm + +def indexedTreeValidatedBlock : ValidatedBlock indexedTreeDecl where + block := indexedTreeNormalizedBlock + resultLevel := .succ (.param 0) + +/-- Exact validation-only semantic package for the indexed mutual block. -/ +def indexedTreeValidationCertificate : + ValidationCertificate indexedTreeDecl natFinalEnv where + validated := indexedTreeValidatedBlock + blockEnv := indexedTreeBlockEnv + wf := ⟨indexedTreeNormalizationBlockWF, indexedTreeCheckedBlockWF⟩ + +/-! ## Certified block-generation semantics -/ + +theorem treeLeafGenerationWF : + NormalizedBlockCtor.WF treeGeneration treeGeneration.flatCtors[0] + treeBlockEnv := by + refine { + declaredTel := ?_ + declaredResult := ?_ + emittedTel := ?_ + emittedResult := ?_ + owner := ?_ + recursive := ?_ + resultSpine := ?_ } + · change treeBlockEnv.TelDefEq 1 [] + [.sort (.succ (.param 0)), .bvar 0] + [.sort (.succ (.param 0)), .bvar 0] + exact (show treeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), .bvar 0] from by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + exact ⟨⟨_, by type_tac⟩, trivial⟩).telDefEq_refl + · change treeBlockEnv.IsDefEq 1 + [.bvar 0, .sort (.succ (.param 0))] + (.app (.const ``Tree [.param 0]) (.bvar 1)) + (.app (.const ``Tree [.param 0]) (.bvar 1)) + (.sort (.succ (.param 0))) + have hTree : treeBlockEnv.constants ``Tree = + some treeType.toVConstant := rfl + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + · change treeBlockEnv.TelDefEq 1 [] + [.sort (.succ (.param 0)), .bvar 0] + [.sort (.succ (.param 0)), .bvar 0] + exact (show treeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), .bvar 0] from by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + exact ⟨⟨_, by type_tac⟩, trivial⟩).telDefEq_refl + · change treeBlockEnv.IsDefEq 1 + [.bvar 0, .sort (.succ (.param 0))] + (.app (.const ``Tree [.param 0]) (.bvar 1)) + (.app (.const ``Tree [.param 0]) (.bvar 1)) + (.sort (.succ (.param 0))) + have hTree : treeBlockEnv.constants ``Tree = + some treeType.toVConstant := rfl + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + · refine ⟨treeGeneration.families[0], ?_, rfl, rfl, rfl⟩ + exact .head _ + · intro recursive hrecursive + change recursive ∈ [] at hrecursive + nomatch hrecursive + · exact treeLeafSemantic.2.mono empty_le_treeBlockEnv + +theorem treeNodeGenerationWF : + NormalizedBlockCtor.WF treeGeneration treeGeneration.flatCtors[1] + treeBlockEnv := by + have hTree : treeBlockEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeBlockEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + have hbinders : treeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), + .app (.const ``TreeList [.param 0]) (.bvar 0)] := by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + refine ⟨⟨.succ (.param 0), ?_⟩, trivial⟩ + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar .zero + have hresult : treeBlockEnv.HasType 1 + [.app (.const ``TreeList [.param 0]) (.bvar 0), + .sort (.succ (.param 0))] + (.app (.const ``Tree [.param 0]) (.bvar 1)) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + refine { + declaredTel := ?_ + declaredResult := ?_ + emittedTel := ?_ + emittedResult := ?_ + owner := ?_ + recursive := ?_ + resultSpine := ?_ } + · exact hbinders.telDefEq_refl + · exact hresult + · exact hbinders.telDefEq_refl + · exact hresult + · refine ⟨treeGeneration.families[0], ?_, rfl, rfl, rfl⟩ + exact .head _ + · intro recursive hrecursive + change recursive ∈ [{ + fieldIndex := 0 + binders := [] + targetType := 1 + indices := [] }] at hrecursive + simp only [List.mem_cons, List.not_mem_nil, or_false] at hrecursive + subst recursive + refine ⟨treeGeneration.families[1], ?_, rfl, ?_, ?_⟩ + · exact .tail _ (.head _) + · exact ⟨.app (.const ``TreeList [.param 0]) (.bvar 0), rfl, rfl⟩ + · exact ⟨trivial, .nil⟩ + · exact treeNodeSemantic.2.mono empty_le_treeBlockEnv + +theorem treeBranchGenerationWF : + NormalizedBlockCtor.WF treeGeneration treeGeneration.flatCtors[2] + treeBlockEnv := by + have hTree : treeBlockEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeBlockEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + have hbinders : treeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), + .forallE (.bvar 0) + (.app (.const ``TreeList [.param 0]) (.bvar 1))] := by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + refine ⟨⟨.imax (.succ (.param 0)) (.succ (.param 0)), ?_⟩, + trivial⟩ + apply VEnv.HasType.forallE + · exact VEnv.HasType.bvar .zero + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + have hresult : treeBlockEnv.HasType 1 + [.forallE (.bvar 0) + (.app (.const ``TreeList [.param 0]) (.bvar 1)), + .sort (.succ (.param 0))] + (.app (.const ``Tree [.param 0]) (.bvar 1)) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + refine { + declaredTel := hbinders.telDefEq_refl + declaredResult := hresult + emittedTel := hbinders.telDefEq_refl + emittedResult := hresult + owner := ?_ + recursive := ?_ + resultSpine := treeBranchSemantic.2.mono empty_le_treeBlockEnv } + · refine ⟨treeGeneration.families[0], ?_, rfl, rfl, rfl⟩ + exact .head _ + · intro recursive hrecursive + change recursive ∈ [{ + fieldIndex := 0 + binders := [.bvar 0] + targetType := 1 + indices := [] }] at hrecursive + simp only [List.mem_cons, List.not_mem_nil, or_false] at hrecursive + subst recursive + refine ⟨treeGeneration.families[1], ?_, rfl, ?_, ?_⟩ + · exact .tail _ (.head _) + · exact ⟨.forallE (.bvar 0) + (.app (.const ``TreeList [.param 0]) (.bvar 1)), rfl, rfl⟩ + · exact ⟨⟨⟨_, VEnv.HasType.bvar .zero⟩, trivial⟩, .nil⟩ + +theorem treeListNilGenerationWF : + NormalizedBlockCtor.WF treeGeneration treeGeneration.flatCtors[3] + treeBlockEnv := by + have hTreeList : treeBlockEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + have hbinders : treeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0))] := + ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩ + have hresult : treeBlockEnv.HasType 1 + [.sort (.succ (.param 0))] + (.app (.const ``TreeList [.param 0]) (.bvar 0)) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar .zero + refine { + declaredTel := hbinders.telDefEq_refl + declaredResult := hresult + emittedTel := hbinders.telDefEq_refl + emittedResult := hresult + owner := ?_ + recursive := ?_ + resultSpine := treeListNilSemantic.2.mono empty_le_treeBlockEnv } + · refine ⟨treeGeneration.families[1], ?_, rfl, rfl, rfl⟩ + exact .tail _ (.head _) + · intro recursive hrecursive + change recursive ∈ [] at hrecursive + nomatch hrecursive + +theorem treeListConsGenerationWF : + NormalizedBlockCtor.WF treeGeneration treeGeneration.flatCtors[4] + treeBlockEnv := by + have hTree : treeBlockEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeBlockEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + have hbinders : treeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), + .app (.const ``Tree [.param 0]) (.bvar 0), + .app (.const ``TreeList [.param 0]) (.bvar 1)] := by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + refine ⟨⟨.succ (.param 0), ?_⟩, ?_⟩ + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar .zero + · refine ⟨⟨.succ (.param 0), ?_⟩, trivial⟩ + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + have hresult : treeBlockEnv.HasType 1 + [.app (.const ``TreeList [.param 0]) (.bvar 1), + .app (.const ``Tree [.param 0]) (.bvar 0), + .sort (.succ (.param 0))] + (.app (.const ``TreeList [.param 0]) (.bvar 2)) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .sort (.succ (.param 0))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ (.succ .zero)) + refine { + declaredTel := hbinders.telDefEq_refl + declaredResult := hresult + emittedTel := hbinders.telDefEq_refl + emittedResult := hresult + owner := ?_ + recursive := ?_ + resultSpine := treeListConsSemantic.2.mono empty_le_treeBlockEnv } + · refine ⟨treeGeneration.families[1], ?_, rfl, rfl, rfl⟩ + exact .tail _ (.head _) + · intro recursive hrecursive + change recursive ∈ [{ + fieldIndex := 0 + binders := [] + targetType := 0 + indices := [] }, { + fieldIndex := 1 + binders := [] + targetType := 1 + indices := [] }] at hrecursive + simp only [List.mem_cons, List.not_mem_nil, or_false] at hrecursive + rcases hrecursive with rfl | rfl + · refine ⟨treeGeneration.families[0], ?_, rfl, ?_, ?_⟩ + · exact .head _ + · exact ⟨.app (.const ``Tree [.param 0]) (.bvar 0), rfl, rfl⟩ + · exact ⟨trivial, .nil⟩ + · refine ⟨treeGeneration.families[1], ?_, rfl, ?_, ?_⟩ + · exact .tail _ (.head _) + · exact ⟨.app (.const ``TreeList [.param 0]) (.bvar 1), rfl, rfl⟩ + · exact ⟨trivial, .nil⟩ + +theorem treeBlockGenerationWF : + treeGeneration.WF VEnv.empty treeBlockEnv := by + refine { + blockWF := treeValidationCertificate.wf + resultLevelWF := by decide + paramsTel := ?_ + families := ?_ + constructors := ?_ } + · change VEnv.empty.TelDefEq 1 [] + [.sort (.succ (.param 0))] [.sort (.succ (.param 0))] + exact (show VEnv.empty.OnTel 1 [] + [.sort (.succ (.param 0))] from + ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩).telDefEq_refl + · intro family hfamily + have hfamilies : treeGeneration.families = + [treeGeneration.families[0], treeGeneration.families[1]] := rfl + rw [hfamilies] at hfamily + simp only [List.mem_cons, List.not_mem_nil, or_false] at hfamily + rcases hfamily with rfl | rfl + · constructor + · change VEnv.empty.TelDefEq 1 [] + [.sort (.succ (.param 0))] [.sort (.succ (.param 0))] + exact (show VEnv.empty.OnTel 1 [] + [.sort (.succ (.param 0))] from + ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩).telDefEq_refl + · change VEnv.empty.IsDefEq 1 [.sort (.succ (.param 0))] + (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + (.sort (.succ (.succ (.param 0)))) + exact .sortDF (by decide) (by decide) rfl + · constructor + · change VEnv.empty.TelDefEq 1 [] + [.sort (.succ (.param 0))] [.sort (.succ (.param 0))] + exact (show VEnv.empty.OnTel 1 [] + [.sort (.succ (.param 0))] from + ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩).telDefEq_refl + · change VEnv.empty.IsDefEq 1 [.sort (.succ (.param 0))] + (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + (.sort (.succ (.succ (.param 0)))) + exact .sortDF (by decide) (by decide) rfl + · intro constructor hconstructor + have hconstructors : treeGeneration.flatCtors = + [treeGeneration.flatCtors[0], treeGeneration.flatCtors[1], + treeGeneration.flatCtors[2], treeGeneration.flatCtors[3], + treeGeneration.flatCtors[4]] := rfl + rw [hconstructors] at hconstructor + simp only [List.mem_cons, List.not_mem_nil, or_false] at hconstructor + rcases hconstructor with rfl | rfl | rfl | rfl | rfl + · exact treeLeafGenerationWF + · exact treeNodeGenerationWF + · exact treeBranchGenerationWF + · exact treeListNilGenerationWF + · exact treeListConsGenerationWF + +theorem indexedTreeBlock_le : natFinalEnv ≤ indexedTreeBlockEnv := by + have hfold : indexedTreeDecl.blockTypeConstants.foldlM + (fun env type => env.addConst type.name type.toVConstant) natFinalEnv = + some indexedTreeBlockEnv := by + rw [blockTypeConstants_foldlM_eq_stageInductiveTypes] + exact indexedTreeStage + exact (VInductDecl.ctorFold_spec indexedTreeDecl.blockTypeConstants hfold).1 + +theorem indexedTreeLeafGenerationWF : + NormalizedBlockCtor.WF indexedTreeGeneration + indexedTreeGeneration.flatCtors[0] indexedTreeBlockEnv := by + have hTree : indexedTreeBlockEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hZero : indexedTreeBlockEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hbinders : indexedTreeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), .bvar 0] := by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + exact ⟨⟨_, VEnv.HasType.bvar .zero⟩, trivial⟩ + have hresult : indexedTreeBlockEnv.HasType 1 + [.bvar 0, .sort (.succ (.param 0))] + (.app + (.app (.const ``IndexedTree [.param 0]) (.bvar 1)) + (.const ``Nat.zero [])) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .const ``Nat []) + (B := .sort (.succ (.param 0))) + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + · exact VEnv.HasType.const hZero (by simp) rfl + refine { + declaredTel := hbinders.telDefEq_refl + declaredResult := hresult + emittedTel := hbinders.telDefEq_refl + emittedResult := hresult + owner := ?_ + recursive := ?_ + resultSpine := indexedTreeLeafSemantic.2.mono indexedTreeBlock_le } + · refine ⟨indexedTreeGeneration.families[0], ?_, rfl, rfl, rfl⟩ + exact .head _ + · intro recursive hrecursive + change recursive ∈ [] at hrecursive + nomatch hrecursive + +theorem indexedTreeListNilGenerationWF : + NormalizedBlockCtor.WF indexedTreeGeneration + indexedTreeGeneration.flatCtors[2] indexedTreeBlockEnv := by + have hTreeList : indexedTreeBlockEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + have hZero : indexedTreeBlockEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hbinders : indexedTreeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0))] := + ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩ + have hresult : indexedTreeBlockEnv.HasType 1 + [.sort (.succ (.param 0))] + (.app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 0)) + (.const ``Nat.zero [])) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .const ``Nat []) + (B := .sort (.succ (.param 0))) + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar .zero + · exact VEnv.HasType.const hZero (by simp) rfl + refine { + declaredTel := hbinders.telDefEq_refl + declaredResult := hresult + emittedTel := hbinders.telDefEq_refl + emittedResult := hresult + owner := ?_ + recursive := ?_ + resultSpine := indexedTreeListNilSemantic.2.mono + indexedTreeBlock_le } + · refine ⟨indexedTreeGeneration.families[1], ?_, rfl, rfl, rfl⟩ + exact .tail _ (.head _) + · intro recursive hrecursive + change recursive ∈ [] at hrecursive + nomatch hrecursive + +theorem indexedTreeNodeGenerationWF : + NormalizedBlockCtor.WF indexedTreeGeneration + indexedTreeGeneration.flatCtors[1] indexedTreeBlockEnv := by + have hNat : indexedTreeBlockEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hSucc : indexedTreeBlockEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedTreeBlockEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedTreeBlockEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + have hbinders : indexedTreeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), .const ``Nat [], + .app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 1)) + (.bvar 0)] := by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + refine ⟨⟨.succ .zero, VEnv.HasType.const hNat (by simp) rfl⟩, ?_⟩ + refine ⟨⟨.succ (.param 0), ?_⟩, trivial⟩ + apply VEnv.HasType.app + (A := .const ``Nat []) + (B := .sort (.succ (.param 0))) + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + · exact VEnv.HasType.bvar .zero + have hresult : indexedTreeBlockEnv.HasType 1 + [.app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 1)) + (.bvar 0), + .const ``Nat [], .sort (.succ (.param 0))] + (.app + (.app (.const ``IndexedTree [.param 0]) (.bvar 2)) + (.app (.const ``Nat.succ []) (.bvar 1))) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .const ``Nat []) + (B := .sort (.succ (.param 0))) + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ (.succ .zero)) + · apply VEnv.HasType.app + (A := .const ``Nat []) (B := .const ``Nat []) + · exact VEnv.HasType.const hSucc (by simp) rfl + · exact VEnv.HasType.bvar (.succ .zero) + refine { + declaredTel := hbinders.telDefEq_refl + declaredResult := hresult + emittedTel := hbinders.telDefEq_refl + emittedResult := hresult + owner := ?_ + recursive := ?_ + resultSpine := indexedTreeNodeSemantic.2.mono + indexedTreeBlock_le } + · refine ⟨indexedTreeGeneration.families[0], ?_, rfl, rfl, rfl⟩ + exact .head _ + · intro recursive hrecursive + change recursive ∈ [{ + fieldIndex := 1 + binders := [] + targetType := 1 + indices := [.bvar 0] }] at hrecursive + simp only [List.mem_cons, List.not_mem_nil, or_false] at hrecursive + subst recursive + refine ⟨indexedTreeGeneration.families[1], ?_, rfl, ?_, ?_⟩ + · exact .tail _ (.head _) + · exact ⟨.app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 1)) + (.bvar 0), rfl, rfl⟩ + · refine ⟨trivial, ?_⟩ + exact .cons (VEnv.HasType.bvar .zero) .nil + +theorem indexedTreeListConsGenerationWF : + NormalizedBlockCtor.WF indexedTreeGeneration + indexedTreeGeneration.flatCtors[3] indexedTreeBlockEnv := by + have hNat : indexedTreeBlockEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hSucc : indexedTreeBlockEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedTreeBlockEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedTreeBlockEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + have hbinders : indexedTreeBlockEnv.OnTel 1 [] + [.sort (.succ (.param 0)), .const ``Nat [], + .app + (.app (.const ``IndexedTree [.param 0]) (.bvar 1)) + (.bvar 0), + .app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 2)) + (.bvar 1)] := by + refine ⟨⟨_, VEnv.HasType.sort (by decide)⟩, ?_⟩ + refine ⟨⟨.succ .zero, VEnv.HasType.const hNat (by simp) rfl⟩, ?_⟩ + refine ⟨⟨.succ (.param 0), ?_⟩, ?_⟩ + · apply VEnv.HasType.app + (A := .const ``Nat []) + (B := .sort (.succ (.param 0))) + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + · exact VEnv.HasType.const hTree (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ .zero) + · exact VEnv.HasType.bvar .zero + · refine ⟨⟨.succ (.param 0), ?_⟩, trivial⟩ + apply VEnv.HasType.app + (A := .const ``Nat []) + (B := .sort (.succ (.param 0))) + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ (.succ .zero)) + · exact VEnv.HasType.bvar (.succ .zero) + have hresult : indexedTreeBlockEnv.HasType 1 + [.app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 2)) + (.bvar 1), + .app + (.app (.const ``IndexedTree [.param 0]) (.bvar 1)) + (.bvar 0), + .const ``Nat [], .sort (.succ (.param 0))] + (.app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 3)) + (.app (.const ``Nat.succ []) (.bvar 2))) + (.sort (.succ (.param 0))) := by + apply VEnv.HasType.app + (A := .const ``Nat []) + (B := .sort (.succ (.param 0))) + · apply VEnv.HasType.app + (A := .sort (.succ (.param 0))) + (B := .forallE (.const ``Nat []) (.sort (.succ (.param 0)))) + · exact VEnv.HasType.const hTreeList (by simp [VLevel.WF]) rfl + · exact VEnv.HasType.bvar (.succ (.succ (.succ .zero))) + · apply VEnv.HasType.app + (A := .const ``Nat []) (B := .const ``Nat []) + · exact VEnv.HasType.const hSucc (by simp) rfl + · exact VEnv.HasType.bvar (.succ (.succ .zero)) + refine { + declaredTel := hbinders.telDefEq_refl + declaredResult := hresult + emittedTel := hbinders.telDefEq_refl + emittedResult := hresult + owner := ?_ + recursive := ?_ + resultSpine := indexedTreeListConsSemantic.2.mono + indexedTreeBlock_le } + · refine ⟨indexedTreeGeneration.families[1], ?_, rfl, rfl, rfl⟩ + exact .tail _ (.head _) + · intro recursive hrecursive + change recursive ∈ [{ + fieldIndex := 1 + binders := [] + targetType := 0 + indices := [.bvar 0] }, { + fieldIndex := 2 + binders := [] + targetType := 1 + indices := [.bvar 1] }] at hrecursive + simp only [List.mem_cons, List.not_mem_nil, or_false] at hrecursive + rcases hrecursive with rfl | rfl + · refine ⟨indexedTreeGeneration.families[0], ?_, rfl, ?_, ?_⟩ + · exact .head _ + · exact ⟨.app + (.app (.const ``IndexedTree [.param 0]) (.bvar 1)) + (.bvar 0), rfl, rfl⟩ + · refine ⟨trivial, ?_⟩ + exact .cons (VEnv.HasType.bvar .zero) .nil + · refine ⟨indexedTreeGeneration.families[1], ?_, rfl, ?_, ?_⟩ + · exact .tail _ (.head _) + · exact ⟨.app + (.app (.const ``IndexedTreeList [.param 0]) (.bvar 2)) + (.bvar 1), rfl, rfl⟩ + · refine ⟨trivial, ?_⟩ + exact .cons (VEnv.HasType.bvar (.succ .zero)) .nil + +theorem indexedTreeBlockGenerationWF : + indexedTreeGeneration.WF natFinalEnv indexedTreeBlockEnv := by + have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hparams : natFinalEnv.OnTel 1 [] + [.sort (.succ (.param 0))] := + ⟨⟨_, VEnv.HasType.sort (by decide)⟩, trivial⟩ + have hfamilyTel : natFinalEnv.OnTel 1 [] + [.sort (.succ (.param 0)), .const ``Nat []] := + ⟨⟨_, VEnv.HasType.sort (by decide)⟩, + ⟨⟨.succ .zero, VEnv.HasType.const hNat (by simp) rfl⟩, trivial⟩⟩ + refine { + blockWF := indexedTreeValidationCertificate.wf + resultLevelWF := by decide + paramsTel := hparams.telDefEq_refl + families := ?_ + constructors := ?_ } + · intro family hfamily + have hfamilies : indexedTreeGeneration.families = + [indexedTreeGeneration.families[0], + indexedTreeGeneration.families[1]] := rfl + rw [hfamilies] at hfamily + simp only [List.mem_cons, List.not_mem_nil, or_false] at hfamily + rcases hfamily with rfl | rfl + · constructor + · exact hfamilyTel.telDefEq_refl + · change natFinalEnv.IsDefEq 1 + [.const ``Nat [], .sort (.succ (.param 0))] + (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + (.sort (.succ (.succ (.param 0)))) + exact .sortDF (by decide) (by decide) rfl + · constructor + · exact hfamilyTel.telDefEq_refl + · change natFinalEnv.IsDefEq 1 + [.const ``Nat [], .sort (.succ (.param 0))] + (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + (.sort (.succ (.succ (.param 0)))) + exact .sortDF (by decide) (by decide) rfl + · intro constructor hconstructor + have hconstructors : indexedTreeGeneration.flatCtors = + [indexedTreeGeneration.flatCtors[0], + indexedTreeGeneration.flatCtors[1], + indexedTreeGeneration.flatCtors[2], + indexedTreeGeneration.flatCtors[3]] := rfl + rw [hconstructors] at hconstructor + simp only [List.mem_cons, List.not_mem_nil, or_false] at hconstructor + rcases hconstructor with rfl | rfl | rfl | rfl + · exact indexedTreeLeafGenerationWF + · exact indexedTreeNodeGenerationWF + · exact indexedTreeListNilGenerationWF + · exact indexedTreeListConsGenerationWF + +/-- Proof-carrying block generation for `Tree`/`TreeList`. -/ +def treeGenerationCertificate : + treeDecl.BlockGenerationCertificate VEnv.empty where + generation := treeGeneration + blockEnv := treeBlockEnv + wf := treeBlockGenerationWF + +/-- Proof-carrying block generation for the indexed mutual fixture. -/ +def indexedTreeGenerationCertificate : + indexedTreeDecl.BlockGenerationCertificate natFinalEnv where + generation := indexedTreeGeneration + blockEnv := indexedTreeBlockEnv + wf := indexedTreeBlockGenerationWF + +/-- Final Theory environment produced by the certified unindexed block +transaction. -/ +def treeFinalEnv : VEnv := + (VEnv.empty.addInductBlockCertified treeGenerationCertificate).get + (by decide) + +theorem tree_addInductBlockCertified : + VEnv.empty.addInductBlockCertified treeGenerationCertificate = + some treeFinalEnv := by + rfl + +/-- The raw public transaction selects the same retained block descriptor and +produces the same final Theory environment. -/ +theorem tree_addInduct : + VEnv.empty.addInduct treeDecl = some treeFinalEnv := by + rfl + +theorem tree_addInduct_success : + VEnv.AddInductSuccess VEnv.empty treeFinalEnv treeDecl := + VEnv.addInduct_success tree_addInduct + +/-- Exact four-phase trace for the certified unindexed block transaction. -/ +theorem treeCertifiedTrace : + Nonempty (VEnv.AddInductBlockGenerationTrace + VEnv.empty treeFinalEnv treeGeneration) := + VEnv.addInductBlockCertified_trace tree_addInductBlockCertified + +theorem treeFinalEnv_ordered : treeFinalEnv.Ordered := + VEnv.addInduct_WF .empty rfl treeBlockGenerationWF tree_addInduct + +theorem treeFinalEnv_family_lookup {type : VInductiveType} + (htype : type ∈ treeDecl.types) : + treeFinalEnv.constants type.name = some type.toVConstant := by + obtain ⟨trace⟩ := treeCertifiedTrace + exact trace.family_lookup htype + +theorem treeFinalEnv_ctor_lookup {constructor : VConstVal} + (hconstructor : constructor ∈ treeDecl.blockConstructorConstants) : + treeFinalEnv.constants constructor.name = + some constructor.toVConstant := by + obtain ⟨trace⟩ := treeCertifiedTrace + exact trace.ctor_lookup hconstructor + +theorem treeFinalEnv_rec_lookup {recursor : VConstVal} + (hrecursor : recursor ∈ treeGeneration.recursors) : + treeFinalEnv.constants recursor.name = + some recursor.toVConstant := by + obtain ⟨trace⟩ := treeCertifiedTrace + exact trace.rec_lookup hrecursor + +theorem treeFinalEnv_rule_mem {rule : VDefEq} + (hrule : rule ∈ treeGeneration.generatedRules) : + treeFinalEnv.defeqs rule := by + obtain ⟨trace⟩ := treeCertifiedTrace + exact trace.rule_mem hrule + +/-- Final Theory environment produced by the certified indexed block +transaction. -/ +def indexedTreeFinalEnv : VEnv := + (natFinalEnv.addInductBlockCertified indexedTreeGenerationCertificate).get + (by decide) + +theorem indexedTree_addInductBlockCertified : + natFinalEnv.addInductBlockCertified indexedTreeGenerationCertificate = + some indexedTreeFinalEnv := by + rfl + +/-- The indexed mutual block also runs through the same raw public entry +point once its ordinary `Nat` dependency is present. -/ +theorem indexedTree_addInduct : + natFinalEnv.addInduct indexedTreeDecl = some indexedTreeFinalEnv := by + rfl + +theorem indexedTree_addInduct_success : + VEnv.AddInductSuccess natFinalEnv indexedTreeFinalEnv indexedTreeDecl := + VEnv.addInduct_success indexedTree_addInduct + +/-- Exact four-phase trace for the certified indexed block transaction. -/ +theorem indexedTreeCertifiedTrace : + Nonempty (VEnv.AddInductBlockGenerationTrace + natFinalEnv indexedTreeFinalEnv indexedTreeGeneration) := + VEnv.addInductBlockCertified_trace indexedTree_addInductBlockCertified + +theorem indexedTreeFinalEnv_ordered : indexedTreeFinalEnv.Ordered := + VEnv.addInduct_WF natFinalEnv_ordered rfl indexedTreeBlockGenerationWF + indexedTree_addInduct + +theorem indexedTreeFinalEnv_family_lookup {type : VInductiveType} + (htype : type ∈ indexedTreeDecl.types) : + indexedTreeFinalEnv.constants type.name = some type.toVConstant := by + obtain ⟨trace⟩ := indexedTreeCertifiedTrace + exact trace.family_lookup htype + +theorem indexedTreeFinalEnv_ctor_lookup {constructor : VConstVal} + (hconstructor : + constructor ∈ indexedTreeDecl.blockConstructorConstants) : + indexedTreeFinalEnv.constants constructor.name = + some constructor.toVConstant := by + obtain ⟨trace⟩ := indexedTreeCertifiedTrace + exact trace.ctor_lookup hconstructor + +theorem indexedTreeFinalEnv_rec_lookup {recursor : VConstVal} + (hrecursor : recursor ∈ indexedTreeGeneration.recursors) : + indexedTreeFinalEnv.constants recursor.name = + some recursor.toVConstant := by + obtain ⟨trace⟩ := indexedTreeCertifiedTrace + exact trace.rec_lookup hrecursor + +theorem indexedTreeFinalEnv_rule_mem {rule : VDefEq} + (hrule : rule ∈ indexedTreeGeneration.generatedRules) : + indexedTreeFinalEnv.defeqs rule := by + obtain ⟨trace⟩ := indexedTreeCertifiedTrace + exact trace.rule_mem hrule + +/-! ## Verification-environment block replay -/ + +/-! ## Unindexed Verify block replay -/ + +def treeReplayFirstTypeEnv : VEnv := + (VEnv.empty.addConst treeType.name treeType.toVConstant).get! + +def treeReplayTypeEnv : VEnv := + (treeReplayFirstTypeEnv.addConst treeListType.name + treeListType.toVConstant).get! + +def treeReplayLeafEnv : VEnv := + (treeReplayTypeEnv.addConst treeType.ctors[0].name + treeType.ctors[0].toVConstant).get! + +def treeReplayNodeEnv : VEnv := + (treeReplayLeafEnv.addConst treeType.ctors[1].name + treeType.ctors[1].toVConstant).get! + +def treeReplayBranchEnv : VEnv := + (treeReplayNodeEnv.addConst treeType.ctors[2].name + treeType.ctors[2].toVConstant).get! + +def treeReplayNilEnv : VEnv := + (treeReplayBranchEnv.addConst treeListType.ctors[0].name + treeListType.ctors[0].toVConstant).get! + +def treeReplayCtorEnv : VEnv := + (treeReplayNilEnv.addConst treeListType.ctors[1].name + treeListType.ctors[1].toVConstant).get! + +def treeReplayFirstRecEnv : VEnv := + (treeReplayCtorEnv.addConst treeGeneration.recursors[0].name + treeGeneration.recursors[0].toVConstant).get! + +def treeReplayRecEnv : VEnv := + (treeReplayFirstRecEnv.addConst treeGeneration.recursors[1].name + treeGeneration.recursors[1].toVConstant).get! + +example : treeReplayTypeEnv = treeBlockEnv := rfl + +theorem treeReplay_addFirstType : + VEnv.empty.addConst treeType.name treeType.toVConstant = + some treeReplayFirstTypeEnv := rfl + +theorem treeReplay_addSecondType : + treeReplayFirstTypeEnv.addConst treeListType.name + treeListType.toVConstant = some treeReplayTypeEnv := rfl + +theorem treeReplay_addLeaf : + treeReplayTypeEnv.addConst treeType.ctors[0].name + treeType.ctors[0].toVConstant = some treeReplayLeafEnv := rfl + +theorem treeReplay_addNode : + treeReplayLeafEnv.addConst treeType.ctors[1].name + treeType.ctors[1].toVConstant = some treeReplayNodeEnv := rfl + +theorem treeReplay_addBranch : + treeReplayNodeEnv.addConst treeType.ctors[2].name + treeType.ctors[2].toVConstant = some treeReplayBranchEnv := rfl + +theorem treeReplay_addNil : + treeReplayBranchEnv.addConst treeListType.ctors[0].name + treeListType.ctors[0].toVConstant = some treeReplayNilEnv := rfl + +theorem treeReplay_addCons : + treeReplayNilEnv.addConst treeListType.ctors[1].name + treeListType.ctors[1].toVConstant = some treeReplayCtorEnv := rfl + +theorem treeReplay_addFirstRec : + treeReplayCtorEnv.addConst treeGeneration.recursors[0].name + treeGeneration.recursors[0].toVConstant = + some treeReplayFirstRecEnv := rfl + +theorem treeReplay_addSecondRec : + treeReplayFirstRecEnv.addConst treeGeneration.recursors[1].name + treeGeneration.recursors[1].toVConstant = + some treeReplayRecEnv := rfl + +theorem treeTypeConstantWF : treeType.toVConstant.WF VEnv.empty := by + exact treeBlockGenerationWF.rawFamily_isType (.head _) + +theorem treeListTypeConstantWF : + treeListType.toVConstant.WF VEnv.empty := by + exact treeBlockGenerationWF.rawFamily_isType (.tail _ (.head _)) + +theorem treeLeafConstantWF : + treeType.ctors[0].toVConstant.WF treeReplayTypeEnv := by + exact treeBlockGenerationWF.rawCtor_isType (.head _) + +theorem treeNodeConstantWF : + treeType.ctors[1].toVConstant.WF treeReplayTypeEnv := by + exact treeBlockGenerationWF.rawCtor_isType (.tail _ (.head _)) + +theorem treeBranchConstantWF : + treeType.ctors[2].toVConstant.WF treeReplayTypeEnv := by + exact treeBlockGenerationWF.rawCtor_isType + (.tail _ (.tail _ (.head _))) + +theorem treeNilConstantWF : + treeListType.ctors[0].toVConstant.WF treeReplayTypeEnv := by + exact treeBlockGenerationWF.rawCtor_isType + (.tail _ (.tail _ (.tail _ (.head _)))) + +theorem treeConsConstantWF : + treeListType.ctors[1].toVConstant.WF treeReplayTypeEnv := by + exact treeBlockGenerationWF.rawCtor_isType + (.tail _ (.tail _ (.tail _ (.tail _ (.head _))))) + +theorem treeReplayFirstTypeEnv_ordered : + treeReplayFirstTypeEnv.Ordered := by + exact .const .empty treeTypeConstantWF treeReplay_addFirstType + +theorem treeReplayTypeEnv_ordered : treeReplayTypeEnv.Ordered := by + refine .const treeReplayFirstTypeEnv_ordered ?_ + treeReplay_addSecondType + exact treeListTypeConstantWF.mono + (VEnv.addConst_le treeReplay_addFirstType) + +theorem treeReplayTypeEnv_le_leafEnv : + treeReplayTypeEnv ≤ treeReplayLeafEnv := + VEnv.addConst_le treeReplay_addLeaf + +theorem treeReplayLeafEnv_ordered : treeReplayLeafEnv.Ordered := by + exact .const treeReplayTypeEnv_ordered treeLeafConstantWF + treeReplay_addLeaf + +theorem treeReplayLeafEnv_le_nodeEnv : + treeReplayLeafEnv ≤ treeReplayNodeEnv := + VEnv.addConst_le treeReplay_addNode + +theorem treeReplayNodeEnv_ordered : treeReplayNodeEnv.Ordered := by + refine .const treeReplayLeafEnv_ordered ?_ treeReplay_addNode + exact treeNodeConstantWF.mono + treeReplayTypeEnv_le_leafEnv + +theorem treeReplayNodeEnv_le_branchEnv : + treeReplayNodeEnv ≤ treeReplayBranchEnv := + VEnv.addConst_le treeReplay_addBranch + +theorem treeReplayBranchEnv_ordered : treeReplayBranchEnv.Ordered := by + refine .const treeReplayNodeEnv_ordered ?_ treeReplay_addBranch + exact treeBranchConstantWF.mono + (treeReplayTypeEnv_le_leafEnv.trans treeReplayLeafEnv_le_nodeEnv) + +theorem treeReplayBranchEnv_le_nilEnv : + treeReplayBranchEnv ≤ treeReplayNilEnv := + VEnv.addConst_le treeReplay_addNil + +theorem treeReplayNilEnv_ordered : treeReplayNilEnv.Ordered := by + refine .const treeReplayBranchEnv_ordered ?_ treeReplay_addNil + exact treeNilConstantWF.mono + (treeReplayTypeEnv_le_leafEnv.trans + (treeReplayLeafEnv_le_nodeEnv.trans + treeReplayNodeEnv_le_branchEnv)) + +theorem treeReplayNilEnv_le_ctorEnv : + treeReplayNilEnv ≤ treeReplayCtorEnv := + VEnv.addConst_le treeReplay_addCons + +theorem treeReplayCtorEnv_ordered : treeReplayCtorEnv.Ordered := by + refine .const treeReplayNilEnv_ordered ?_ treeReplay_addCons + exact treeConsConstantWF.mono + (treeReplayTypeEnv_le_leafEnv.trans + (treeReplayLeafEnv_le_nodeEnv.trans + (treeReplayNodeEnv_le_branchEnv.trans + treeReplayBranchEnv_le_nilEnv))) + +theorem treeReplayInput_le_ctorEnv : VEnv.empty ≤ treeReplayCtorEnv := by + exact (VEnv.addConst_le treeReplay_addFirstType).trans + ((VEnv.addConst_le treeReplay_addSecondType).trans + (treeReplayTypeEnv_le_leafEnv.trans + (treeReplayLeafEnv_le_nodeEnv.trans + (treeReplayNodeEnv_le_branchEnv.trans + (treeReplayBranchEnv_le_nilEnv.trans + treeReplayNilEnv_le_ctorEnv))))) + +theorem treeReplayBlock_le_ctorEnv : treeBlockEnv ≤ treeReplayCtorEnv := by + exact treeReplayTypeEnv_le_leafEnv.trans + (treeReplayLeafEnv_le_nodeEnv.trans + (treeReplayNodeEnv_le_branchEnv.trans + (treeReplayBranchEnv_le_nilEnv.trans + treeReplayNilEnv_le_ctorEnv))) + +theorem treeReplayGenerationEnv : + BlockGenerationEnv treeGeneration treeReplayCtorEnv := by + apply treeBlockGenerationWF.toBlockGenerationEnv + treeReplayInput_le_ctorEnv treeReplayBlock_le_ctorEnv + treeReplayCtorEnv_ordered + · intro family hfamily + have hfamilies : treeGeneration.families = + [treeGeneration.families[0], treeGeneration.families[1]] := rfl + rw [hfamilies] at hfamily + simp only [List.mem_cons, List.not_mem_nil, or_false] at hfamily + rcases hfamily with rfl | rfl <;> rfl + · intro constructor hconstructor + have hconstructors : treeGeneration.flatCtors = + [treeGeneration.flatCtors[0], treeGeneration.flatCtors[1], + treeGeneration.flatCtors[2], treeGeneration.flatCtors[3], + treeGeneration.flatCtors[4]] := rfl + rw [hconstructors] at hconstructor + simp only [List.mem_cons, List.not_mem_nil, or_false] at hconstructor + rcases hconstructor with rfl | rfl | rfl | rfl | rfl <;> rfl + +theorem treeReplayFirstRecEnv_ordered : + treeReplayFirstRecEnv.Ordered := by + refine .const treeReplayCtorEnv_ordered ?_ treeReplay_addFirstRec + exact treeReplayGenerationEnv.recursor_wf (.head _) + +theorem treeReplayCtorEnv_le_firstRecEnv : + treeReplayCtorEnv ≤ treeReplayFirstRecEnv := + VEnv.addConst_le treeReplay_addFirstRec + +theorem treeReplayRecEnv_ordered : treeReplayRecEnv.Ordered := by + refine .const treeReplayFirstRecEnv_ordered ?_ treeReplay_addSecondRec + exact (treeReplayGenerationEnv.recursor_wf + (.tail _ (.head _))).mono treeReplayCtorEnv_le_firstRecEnv + +theorem treeKernelInfo_tr : + TrConstVal .safe VEnv.empty treeKernelInfo treeType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr VEnv.empty treeKernelInfo.levelParams [] + treeKernelInfo.type treeType.type := by tr_type_expr_tac + exact hshape.to_trExprS .empty trivial + (treeFamilyTypeWF treeType (.inl rfl)) + +theorem treeListKernelInfo_tr : + TrConstVal .safe treeReplayFirstTypeEnv treeListKernelInfo + treeListType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayFirstTypeEnv + treeListKernelInfo.levelParams [] treeListKernelInfo.type + treeListType.type := by tr_type_expr_tac + exact hshape.to_trExprS treeReplayFirstTypeEnv_ordered trivial + ((treeFamilyTypeWF treeListType (.inr rfl)).mono + (VEnv.addConst_le (by rfl))) + +theorem treeLeafKernelInfo_tr : + TrConstVal .safe treeReplayTypeEnv treeLeafKernelInfo + treeType.ctors[0] := by + have hTree : treeReplayTypeEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeReplayTypeEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayTypeEnv + treeLeafKernelInfo.levelParams [] treeLeafKernelInfo.type + treeType.ctors[0].type := by tr_type_expr_tac + exact hshape.to_trExprS treeReplayTypeEnv_ordered trivial + (treeCtorWF treeType.ctors[0] (.inl (by simp [treeType]))) + +theorem treeNodeKernelInfo_tr : + TrConstVal .safe treeReplayLeafEnv treeNodeKernelInfo + treeType.ctors[1] := by + have hTree : treeReplayLeafEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeReplayLeafEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayLeafEnv + treeNodeKernelInfo.levelParams [] treeNodeKernelInfo.type + treeType.ctors[1].type := by tr_type_expr_tac + exact hshape.to_trExprS treeReplayLeafEnv_ordered trivial + ((treeCtorWF treeType.ctors[1] (.inl (by simp [treeType]))).mono + treeReplayTypeEnv_le_leafEnv) + +theorem treeBranchKernelInfo_tr : + TrConstVal .safe treeReplayNodeEnv treeBranchKernelInfo + treeType.ctors[2] := by + have hTree : treeReplayNodeEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeReplayNodeEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayNodeEnv + treeBranchKernelInfo.levelParams [] treeBranchKernelInfo.type + treeType.ctors[2].type := by tr_type_expr_tac + exact hshape.to_trExprS treeReplayNodeEnv_ordered trivial + ((treeCtorWF treeType.ctors[2] (.inl (by simp [treeType]))).mono + (treeReplayTypeEnv_le_leafEnv.trans treeReplayLeafEnv_le_nodeEnv)) + +theorem treeListNilKernelInfo_tr : + TrConstVal .safe treeReplayBranchEnv treeListNilKernelInfo + treeListType.ctors[0] := by + have hTree : treeReplayBranchEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeReplayBranchEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayBranchEnv + treeListNilKernelInfo.levelParams [] treeListNilKernelInfo.type + treeListType.ctors[0].type := by tr_type_expr_tac + exact hshape.to_trExprS treeReplayBranchEnv_ordered trivial + ((treeCtorWF treeListType.ctors[0] + (.inr (by simp [treeListType]))).mono + (treeReplayTypeEnv_le_leafEnv.trans + (treeReplayLeafEnv_le_nodeEnv.trans + treeReplayNodeEnv_le_branchEnv))) + +theorem treeListConsKernelInfo_tr : + TrConstVal .safe treeReplayNilEnv treeListConsKernelInfo + treeListType.ctors[1] := by + have hTree : treeReplayNilEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeReplayNilEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayNilEnv + treeListConsKernelInfo.levelParams [] treeListConsKernelInfo.type + treeListType.ctors[1].type := by tr_type_expr_tac + exact hshape.to_trExprS treeReplayNilEnv_ordered trivial + ((treeCtorWF treeListType.ctors[1] + (.inr (by simp [treeListType]))).mono + (treeReplayTypeEnv_le_leafEnv.trans + (treeReplayLeafEnv_le_nodeEnv.trans + (treeReplayNodeEnv_le_branchEnv.trans + treeReplayBranchEnv_le_nilEnv)))) + +theorem treeRecKernelInfo_tr : + TrConstVal .safe treeReplayCtorEnv treeRecKernelInfo + treeGeneration.recursors[0] := by + have hTree : treeReplayCtorEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeReplayCtorEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + have hLeaf : treeReplayCtorEnv.constants ``Tree.leaf = + some treeType.ctors[0].toVConstant := rfl + have hNode : treeReplayCtorEnv.constants ``Tree.node = + some treeType.ctors[1].toVConstant := rfl + have hBranch : treeReplayCtorEnv.constants ``Tree.branch = + some treeType.ctors[2].toVConstant := rfl + have hNil : treeReplayCtorEnv.constants ``TreeList.nil = + some treeListType.ctors[0].toVConstant := rfl + have hCons : treeReplayCtorEnv.constants ``TreeList.cons = + some treeListType.ctors[1].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayCtorEnv + treeRecKernelInfo.levelParams [] treeRecKernelInfo.type + treeGeneration.recursors[0].type := by tr_type_expr_tac + obtain ⟨u, hrec⟩ := + treeReplayGenerationEnv.recursor_wf (.head _) + exact hshape.to_trExprS treeReplayCtorEnv_ordered trivial + ⟨.sort u, hrec⟩ + +theorem treeListRecKernelInfo_tr : + TrConstVal .safe treeReplayFirstRecEnv treeListRecKernelInfo + treeGeneration.recursors[1] := by + have hTree : treeReplayFirstRecEnv.constants ``Tree = + some treeType.toVConstant := rfl + have hTreeList : treeReplayFirstRecEnv.constants ``TreeList = + some treeListType.toVConstant := rfl + have hLeaf : treeReplayFirstRecEnv.constants ``Tree.leaf = + some treeType.ctors[0].toVConstant := rfl + have hNode : treeReplayFirstRecEnv.constants ``Tree.node = + some treeType.ctors[1].toVConstant := rfl + have hBranch : treeReplayFirstRecEnv.constants ``Tree.branch = + some treeType.ctors[2].toVConstant := rfl + have hNil : treeReplayFirstRecEnv.constants ``TreeList.nil = + some treeListType.ctors[0].toVConstant := rfl + have hCons : treeReplayFirstRecEnv.constants ``TreeList.cons = + some treeListType.ctors[1].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr treeReplayFirstRecEnv + treeListRecKernelInfo.levelParams [] treeListRecKernelInfo.type + treeGeneration.recursors[1].type := by tr_type_expr_tac + obtain ⟨u, hrec⟩ := + treeReplayGenerationEnv.recursor_wf (.tail _ (.head _)) + exact hshape.to_trExprS treeReplayFirstRecEnv_ordered trivial + ⟨.sort u, hrec.mono treeReplayCtorEnv_le_firstRecEnv⟩ + +def treeReplayFirstTypeMap : ConstMap := + ({} : ConstMap).insert ``Tree treeKernelInfo + +def treeReplayTypeMap : ConstMap := + treeReplayFirstTypeMap.insert ``TreeList treeListKernelInfo + +def treeReplayLeafMap : ConstMap := + treeReplayTypeMap.insert ``Tree.leaf treeLeafKernelInfo + +def treeReplayNodeMap : ConstMap := + treeReplayLeafMap.insert ``Tree.node treeNodeKernelInfo + +def treeReplayBranchMap : ConstMap := + treeReplayNodeMap.insert ``Tree.branch treeBranchKernelInfo + +def treeReplayNilMap : ConstMap := + treeReplayBranchMap.insert ``TreeList.nil treeListNilKernelInfo + +def treeReplayCtorMap : ConstMap := + treeReplayNilMap.insert ``TreeList.cons treeListConsKernelInfo + +def treeReplayFirstRecMap : ConstMap := + treeReplayCtorMap.insert ``Tree.rec treeRecKernelInfo + +def treeReplayMap : ConstMap := + treeReplayFirstRecMap.insert ``TreeList.rec treeListRecKernelInfo + +theorem treeReplayFirstType_fresh : + ({} : ConstMap).find? ``Tree = none := by + simp [SMap.find?] + +theorem treeReplayFirstTypeMap_wf : treeReplayFirstTypeMap.WF := + SMap.WF.empty.insert _ _ treeReplayFirstType_fresh + +theorem treeReplaySecondType_fresh : + treeReplayFirstTypeMap.find? ``TreeList = none := by + rw [treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayTypeMap_wf : treeReplayTypeMap.WF := + treeReplayFirstTypeMap_wf.insert _ _ treeReplaySecondType_fresh + +theorem treeReplayLeaf_fresh : + treeReplayTypeMap.find? ``Tree.leaf = none := by + rw [treeReplayTypeMap, treeReplayFirstTypeMap_wf.find?_insert, + treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayLeafMap_wf : treeReplayLeafMap.WF := + treeReplayTypeMap_wf.insert _ _ treeReplayLeaf_fresh + +theorem treeReplayNode_fresh : + treeReplayLeafMap.find? ``Tree.node = none := by + rw [treeReplayLeafMap, treeReplayTypeMap_wf.find?_insert, + treeReplayTypeMap, treeReplayFirstTypeMap_wf.find?_insert, + treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayNodeMap_wf : treeReplayNodeMap.WF := + treeReplayLeafMap_wf.insert _ _ treeReplayNode_fresh + +theorem treeReplayBranch_fresh : + treeReplayNodeMap.find? ``Tree.branch = none := by + rw [treeReplayNodeMap, treeReplayLeafMap_wf.find?_insert, + treeReplayLeafMap, treeReplayTypeMap_wf.find?_insert, + treeReplayTypeMap, treeReplayFirstTypeMap_wf.find?_insert, + treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayBranchMap_wf : treeReplayBranchMap.WF := + treeReplayNodeMap_wf.insert _ _ treeReplayBranch_fresh + +theorem treeReplayNil_fresh : + treeReplayBranchMap.find? ``TreeList.nil = none := by + rw [treeReplayBranchMap, treeReplayNodeMap_wf.find?_insert, + treeReplayNodeMap, treeReplayLeafMap_wf.find?_insert, + treeReplayLeafMap, treeReplayTypeMap_wf.find?_insert, + treeReplayTypeMap, treeReplayFirstTypeMap_wf.find?_insert, + treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayNilMap_wf : treeReplayNilMap.WF := + treeReplayBranchMap_wf.insert _ _ treeReplayNil_fresh + +theorem treeReplayCons_fresh : + treeReplayNilMap.find? ``TreeList.cons = none := by + rw [treeReplayNilMap, treeReplayBranchMap_wf.find?_insert, + treeReplayBranchMap, treeReplayNodeMap_wf.find?_insert, + treeReplayNodeMap, treeReplayLeafMap_wf.find?_insert, + treeReplayLeafMap, treeReplayTypeMap_wf.find?_insert, + treeReplayTypeMap, treeReplayFirstTypeMap_wf.find?_insert, + treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayCtorMap_wf : treeReplayCtorMap.WF := + treeReplayNilMap_wf.insert _ _ treeReplayCons_fresh + +theorem treeReplayFirstRec_fresh : + treeReplayCtorMap.find? ``Tree.rec = none := by + rw [treeReplayCtorMap, treeReplayNilMap_wf.find?_insert, + treeReplayNilMap, treeReplayBranchMap_wf.find?_insert, + treeReplayBranchMap, treeReplayNodeMap_wf.find?_insert, + treeReplayNodeMap, treeReplayLeafMap_wf.find?_insert, + treeReplayLeafMap, treeReplayTypeMap_wf.find?_insert, + treeReplayTypeMap, treeReplayFirstTypeMap_wf.find?_insert, + treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayFirstRecMap_wf : treeReplayFirstRecMap.WF := + treeReplayCtorMap_wf.insert _ _ treeReplayFirstRec_fresh + +theorem treeReplaySecondRec_fresh : + treeReplayFirstRecMap.find? ``TreeList.rec = none := by + rw [treeReplayFirstRecMap, treeReplayCtorMap_wf.find?_insert, + treeReplayCtorMap, treeReplayNilMap_wf.find?_insert, + treeReplayNilMap, treeReplayBranchMap_wf.find?_insert, + treeReplayBranchMap, treeReplayNodeMap_wf.find?_insert, + treeReplayNodeMap, treeReplayLeafMap_wf.find?_insert, + treeReplayLeafMap, treeReplayTypeMap_wf.find?_insert, + treeReplayTypeMap, treeReplayFirstTypeMap_wf.find?_insert, + treeReplayFirstTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem treeReplayMap_wf : treeReplayMap.WF := + treeReplayFirstRecMap_wf.insert _ _ treeReplaySecondRec_fresh + +theorem treeReplay_treeRec_lookup : + treeReplayMap.find? ``Tree.rec = some treeRecKernelInfo := by + rw [treeReplayMap, treeReplayFirstRecMap_wf.find?_insert, + treeReplayFirstRecMap, treeReplayCtorMap_wf.find?_insert] + rfl + +theorem treeReplay_treeListRec_lookup : + treeReplayMap.find? ``TreeList.rec = some treeListRecKernelInfo := by + rw [treeReplayMap, treeReplayFirstRecMap_wf.find?_insert] + rfl + +def treeAddInductBlockTrace : + AddInductBlockTrace ({} : ConstMap) VEnv.empty treeDecl + treeReplayMap treeFinalEnv where + generation := treeGeneration + blockEnv := treeBlockEnv + generation_wf := treeBlockGenerationWF + typeMap := treeReplayTypeMap + typeEnv := treeReplayTypeEnv + ctorMap := treeReplayCtorMap + ctorEnv := treeReplayCtorEnv + recEnv := treeReplayRecEnv + addTypes := .cons { + info := treeKernelInfo + kind_eq := by simp [treeKernelInfo, InductConstantKind.Matches] + tr := treeKernelInfo_tr + map_fresh := treeReplayFirstType_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := treeListKernelInfo + kind_eq := by simp [treeListKernelInfo, InductConstantKind.Matches] + tr := treeListKernelInfo_tr + map_fresh := treeReplaySecondType_fresh + env_add := rfl + map_add := rfl } .nil) + addCtors := .cons { + info := treeLeafKernelInfo + kind_eq := by simp [treeLeafKernelInfo, InductConstantKind.Matches] + tr := treeLeafKernelInfo_tr + map_fresh := treeReplayLeaf_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := treeNodeKernelInfo + kind_eq := by simp [treeNodeKernelInfo, InductConstantKind.Matches] + tr := treeNodeKernelInfo_tr + map_fresh := treeReplayNode_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := treeBranchKernelInfo + kind_eq := by simp [treeBranchKernelInfo, InductConstantKind.Matches] + tr := treeBranchKernelInfo_tr + map_fresh := treeReplayBranch_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := treeListNilKernelInfo + kind_eq := by simp [treeListNilKernelInfo, InductConstantKind.Matches] + tr := treeListNilKernelInfo_tr + map_fresh := treeReplayNil_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := treeListConsKernelInfo + kind_eq := by simp [treeListConsKernelInfo, InductConstantKind.Matches] + tr := treeListConsKernelInfo_tr + map_fresh := treeReplayCons_fresh + env_add := rfl + map_add := rfl } .nil)))) + addRecs := .cons { + info := treeRecKernelInfo + kind_eq := by simp [treeRecKernelInfo, InductConstantKind.Matches] + tr := treeRecKernelInfo_tr + map_fresh := treeReplayFirstRec_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := treeListRecKernelInfo + kind_eq := by simp [treeListRecKernelInfo, InductConstantKind.Matches] + tr := treeListRecKernelInfo_tr + map_fresh := treeReplaySecondRec_fresh + env_add := rfl + map_add := rfl } .nil) + recK := by + intro recursor hrecursor + have hrecs : treeGeneration.recursors = + [treeGeneration.recursors[0], treeGeneration.recursors[1]] := rfl + rw [hrecs] at hrecursor + simp only [List.mem_cons, List.not_mem_nil, or_false] at hrecursor + rcases hrecursor with rfl | rfl + · exact ⟨treeRecKernelInfo, treeReplay_treeRec_lookup, by decide⟩ + · exact ⟨treeListRecKernelInfo, treeReplay_treeListRec_lookup, + by decide⟩ + addRules := ⟨rfl⟩ + +theorem treeAddInductBlock : + AddInductBlock ({} : ConstMap) VEnv.empty treeDecl + treeReplayMap treeFinalEnv := + ⟨treeAddInductBlockTrace⟩ + +theorem tree_trEnv' : TrEnv' .safe treeReplayMap false treeFinalEnv := + .inductBlock treeAddInductBlock .empty + +theorem tree_verify_env_wf : treeFinalEnv.WF := tree_trEnv'.wf + +theorem tree_verify_aligned : + Aligned .safe treeReplayMap treeFinalEnv := tree_trEnv'.aligned + +/-! ## Indexed Verify block replay -/ + +def indexedReplayFirstTypeEnv : VEnv := + (natFinalEnv.addConst indexedTreeType.name + indexedTreeType.toVConstant).get! + +def indexedReplayTypeEnv : VEnv := + (indexedReplayFirstTypeEnv.addConst indexedTreeListType.name + indexedTreeListType.toVConstant).get! + +def indexedReplayLeafEnv : VEnv := + (indexedReplayTypeEnv.addConst indexedTreeType.ctors[0].name + indexedTreeType.ctors[0].toVConstant).get! + +def indexedReplayNodeEnv : VEnv := + (indexedReplayLeafEnv.addConst indexedTreeType.ctors[1].name + indexedTreeType.ctors[1].toVConstant).get! + +def indexedReplayNilEnv : VEnv := + (indexedReplayNodeEnv.addConst indexedTreeListType.ctors[0].name + indexedTreeListType.ctors[0].toVConstant).get! + +def indexedReplayCtorEnv : VEnv := + (indexedReplayNilEnv.addConst indexedTreeListType.ctors[1].name + indexedTreeListType.ctors[1].toVConstant).get! + +def indexedReplayFirstRecEnv : VEnv := + (indexedReplayCtorEnv.addConst + indexedTreeGeneration.recursors[0].name + indexedTreeGeneration.recursors[0].toVConstant).get! + +def indexedReplayRecEnv : VEnv := + (indexedReplayFirstRecEnv.addConst + indexedTreeGeneration.recursors[1].name + indexedTreeGeneration.recursors[1].toVConstant).get! + +example : indexedReplayTypeEnv = indexedTreeBlockEnv := rfl + +theorem indexedReplay_addFirstType : + natFinalEnv.addConst indexedTreeType.name + indexedTreeType.toVConstant = some indexedReplayFirstTypeEnv := rfl + +theorem indexedReplay_addSecondType : + indexedReplayFirstTypeEnv.addConst indexedTreeListType.name + indexedTreeListType.toVConstant = some indexedReplayTypeEnv := rfl + +theorem indexedReplay_addLeaf : + indexedReplayTypeEnv.addConst indexedTreeType.ctors[0].name + indexedTreeType.ctors[0].toVConstant = + some indexedReplayLeafEnv := rfl + +theorem indexedReplay_addNode : + indexedReplayLeafEnv.addConst indexedTreeType.ctors[1].name + indexedTreeType.ctors[1].toVConstant = + some indexedReplayNodeEnv := rfl + +theorem indexedReplay_addNil : + indexedReplayNodeEnv.addConst indexedTreeListType.ctors[0].name + indexedTreeListType.ctors[0].toVConstant = + some indexedReplayNilEnv := rfl + +theorem indexedReplay_addCons : + indexedReplayNilEnv.addConst indexedTreeListType.ctors[1].name + indexedTreeListType.ctors[1].toVConstant = + some indexedReplayCtorEnv := rfl + +theorem indexedReplay_addFirstRec : + indexedReplayCtorEnv.addConst + indexedTreeGeneration.recursors[0].name + indexedTreeGeneration.recursors[0].toVConstant = + some indexedReplayFirstRecEnv := rfl + +theorem indexedReplay_addSecondRec : + indexedReplayFirstRecEnv.addConst + indexedTreeGeneration.recursors[1].name + indexedTreeGeneration.recursors[1].toVConstant = + some indexedReplayRecEnv := rfl + +theorem indexedTreeTypeConstantWF : + indexedTreeType.toVConstant.WF natFinalEnv := by + exact indexedTreeBlockGenerationWF.rawFamily_isType (.head _) + +theorem indexedTreeListTypeConstantWF : + indexedTreeListType.toVConstant.WF natFinalEnv := by + exact indexedTreeBlockGenerationWF.rawFamily_isType + (.tail _ (.head _)) + +theorem indexedTreeLeafConstantWF : + indexedTreeType.ctors[0].toVConstant.WF indexedReplayTypeEnv := by + exact indexedTreeBlockGenerationWF.rawCtor_isType (.head _) + +theorem indexedTreeNodeConstantWF : + indexedTreeType.ctors[1].toVConstant.WF indexedReplayTypeEnv := by + exact indexedTreeBlockGenerationWF.rawCtor_isType + (.tail _ (.head _)) + +theorem indexedTreeNilConstantWF : + indexedTreeListType.ctors[0].toVConstant.WF + indexedReplayTypeEnv := by + exact indexedTreeBlockGenerationWF.rawCtor_isType + (.tail _ (.tail _ (.head _))) + +theorem indexedTreeConsConstantWF : + indexedTreeListType.ctors[1].toVConstant.WF + indexedReplayTypeEnv := by + exact indexedTreeBlockGenerationWF.rawCtor_isType + (.tail _ (.tail _ (.tail _ (.head _)))) + +theorem indexedReplayFirstTypeEnv_ordered : + indexedReplayFirstTypeEnv.Ordered := by + exact .const natFinalEnv_ordered indexedTreeTypeConstantWF + indexedReplay_addFirstType + +theorem indexedReplayTypeEnv_ordered : indexedReplayTypeEnv.Ordered := by + refine .const indexedReplayFirstTypeEnv_ordered ?_ + indexedReplay_addSecondType + exact indexedTreeListTypeConstantWF.mono + (VEnv.addConst_le indexedReplay_addFirstType) + +theorem indexedReplayTypeEnv_le_leafEnv : + indexedReplayTypeEnv ≤ indexedReplayLeafEnv := + VEnv.addConst_le indexedReplay_addLeaf + +theorem indexedReplayLeafEnv_ordered : indexedReplayLeafEnv.Ordered := by + exact .const indexedReplayTypeEnv_ordered indexedTreeLeafConstantWF + indexedReplay_addLeaf + +theorem indexedReplayLeafEnv_le_nodeEnv : + indexedReplayLeafEnv ≤ indexedReplayNodeEnv := + VEnv.addConst_le indexedReplay_addNode + +theorem indexedReplayNodeEnv_ordered : indexedReplayNodeEnv.Ordered := by + refine .const indexedReplayLeafEnv_ordered ?_ indexedReplay_addNode + exact indexedTreeNodeConstantWF.mono indexedReplayTypeEnv_le_leafEnv + +theorem indexedReplayNodeEnv_le_nilEnv : + indexedReplayNodeEnv ≤ indexedReplayNilEnv := + VEnv.addConst_le indexedReplay_addNil + +theorem indexedReplayNilEnv_ordered : indexedReplayNilEnv.Ordered := by + refine .const indexedReplayNodeEnv_ordered ?_ indexedReplay_addNil + exact indexedTreeNilConstantWF.mono + (indexedReplayTypeEnv_le_leafEnv.trans + indexedReplayLeafEnv_le_nodeEnv) + +theorem indexedReplayNilEnv_le_ctorEnv : + indexedReplayNilEnv ≤ indexedReplayCtorEnv := + VEnv.addConst_le indexedReplay_addCons + +theorem indexedReplayCtorEnv_ordered : indexedReplayCtorEnv.Ordered := by + refine .const indexedReplayNilEnv_ordered ?_ indexedReplay_addCons + exact indexedTreeConsConstantWF.mono + (indexedReplayTypeEnv_le_leafEnv.trans + (indexedReplayLeafEnv_le_nodeEnv.trans + indexedReplayNodeEnv_le_nilEnv)) + +theorem indexedReplayInput_le_ctorEnv : + natFinalEnv ≤ indexedReplayCtorEnv := by + exact (VEnv.addConst_le indexedReplay_addFirstType).trans + ((VEnv.addConst_le indexedReplay_addSecondType).trans + (indexedReplayTypeEnv_le_leafEnv.trans + (indexedReplayLeafEnv_le_nodeEnv.trans + (indexedReplayNodeEnv_le_nilEnv.trans + indexedReplayNilEnv_le_ctorEnv)))) + +theorem indexedReplayBlock_le_ctorEnv : + indexedTreeBlockEnv ≤ indexedReplayCtorEnv := by + exact indexedReplayTypeEnv_le_leafEnv.trans + (indexedReplayLeafEnv_le_nodeEnv.trans + (indexedReplayNodeEnv_le_nilEnv.trans + indexedReplayNilEnv_le_ctorEnv)) + +theorem indexedReplayGenerationEnv : + BlockGenerationEnv indexedTreeGeneration indexedReplayCtorEnv := by + apply indexedTreeBlockGenerationWF.toBlockGenerationEnv + indexedReplayInput_le_ctorEnv indexedReplayBlock_le_ctorEnv + indexedReplayCtorEnv_ordered + · intro family hfamily + have hfamilies : indexedTreeGeneration.families = + [indexedTreeGeneration.families[0], + indexedTreeGeneration.families[1]] := rfl + rw [hfamilies] at hfamily + simp only [List.mem_cons, List.not_mem_nil, or_false] at hfamily + rcases hfamily with rfl | rfl <;> rfl + · intro constructor hconstructor + have hconstructors : indexedTreeGeneration.flatCtors = + [indexedTreeGeneration.flatCtors[0], + indexedTreeGeneration.flatCtors[1], + indexedTreeGeneration.flatCtors[2], + indexedTreeGeneration.flatCtors[3]] := rfl + rw [hconstructors] at hconstructor + simp only [List.mem_cons, List.not_mem_nil, or_false] at hconstructor + rcases hconstructor with rfl | rfl | rfl | rfl <;> rfl + +theorem indexedReplayFirstRecEnv_ordered : + indexedReplayFirstRecEnv.Ordered := by + refine .const indexedReplayCtorEnv_ordered ?_ + indexedReplay_addFirstRec + exact indexedReplayGenerationEnv.recursor_wf (.head _) + +theorem indexedReplayCtorEnv_le_firstRecEnv : + indexedReplayCtorEnv ≤ indexedReplayFirstRecEnv := + VEnv.addConst_le indexedReplay_addFirstRec + +theorem indexedReplayRecEnv_ordered : indexedReplayRecEnv.Ordered := by + refine .const indexedReplayFirstRecEnv_ordered ?_ + indexedReplay_addSecondRec + exact (indexedReplayGenerationEnv.recursor_wf + (.tail _ (.head _))).mono indexedReplayCtorEnv_le_firstRecEnv + +theorem indexedTreeKernelInfo_tr : + TrConstVal .safe natFinalEnv indexedTreeKernelInfo + indexedTreeType.toVConstVal := by + have hNat : natFinalEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr natFinalEnv indexedTreeKernelInfo.levelParams [] + indexedTreeKernelInfo.type indexedTreeType.type := by + tr_type_expr_tac + exact hshape.to_trExprS natFinalEnv_ordered trivial + (indexedTreeFamilyTypeWF indexedTreeType (.inl rfl)) + +theorem indexedTreeListKernelInfo_tr : + TrConstVal .safe indexedReplayFirstTypeEnv indexedTreeListKernelInfo + indexedTreeListType.toVConstVal := by + have hNat : indexedReplayFirstTypeEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedReplayFirstTypeEnv + indexedTreeListKernelInfo.levelParams [] indexedTreeListKernelInfo.type + indexedTreeListType.type := by tr_type_expr_tac + exact hshape.to_trExprS indexedReplayFirstTypeEnv_ordered trivial + ((indexedTreeFamilyTypeWF indexedTreeListType (.inr rfl)).mono + (VEnv.addConst_le indexedReplay_addFirstType)) + +theorem indexedTreeLeafKernelInfo_tr : + TrConstVal .safe indexedReplayTypeEnv indexedTreeLeafKernelInfo + indexedTreeType.ctors[0] := by + have hNat : indexedReplayTypeEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : indexedReplayTypeEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hSucc : indexedReplayTypeEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedReplayTypeEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedReplayTypeEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedReplayTypeEnv + indexedTreeLeafKernelInfo.levelParams [] indexedTreeLeafKernelInfo.type + indexedTreeType.ctors[0].type := by tr_type_expr_tac + exact hshape.to_trExprS indexedReplayTypeEnv_ordered trivial + (indexedTreeCtorWF indexedTreeType.ctors[0] + (.inl (by simp [indexedTreeType]))) + +theorem indexedTreeNodeKernelInfo_tr : + TrConstVal .safe indexedReplayLeafEnv indexedTreeNodeKernelInfo + indexedTreeType.ctors[1] := by + have hNat : indexedReplayLeafEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : indexedReplayLeafEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hSucc : indexedReplayLeafEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedReplayLeafEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedReplayLeafEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedReplayLeafEnv + indexedTreeNodeKernelInfo.levelParams [] indexedTreeNodeKernelInfo.type + indexedTreeType.ctors[1].type := by tr_type_expr_tac + exact hshape.to_trExprS indexedReplayLeafEnv_ordered trivial + ((indexedTreeCtorWF indexedTreeType.ctors[1] + (.inl (by simp [indexedTreeType]))).mono + indexedReplayTypeEnv_le_leafEnv) + +theorem indexedTreeListNilKernelInfo_tr : + TrConstVal .safe indexedReplayNodeEnv indexedTreeListNilKernelInfo + indexedTreeListType.ctors[0] := by + have hNat : indexedReplayNodeEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : indexedReplayNodeEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hSucc : indexedReplayNodeEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedReplayNodeEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedReplayNodeEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedReplayNodeEnv + indexedTreeListNilKernelInfo.levelParams [] + indexedTreeListNilKernelInfo.type indexedTreeListType.ctors[0].type := by + tr_type_expr_tac + exact hshape.to_trExprS indexedReplayNodeEnv_ordered trivial + ((indexedTreeCtorWF indexedTreeListType.ctors[0] + (.inr (by simp [indexedTreeListType]))).mono + (indexedReplayTypeEnv_le_leafEnv.trans + indexedReplayLeafEnv_le_nodeEnv)) + +theorem indexedTreeListConsKernelInfo_tr : + TrConstVal .safe indexedReplayNilEnv indexedTreeListConsKernelInfo + indexedTreeListType.ctors[1] := by + have hNat : indexedReplayNilEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : indexedReplayNilEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hSucc : indexedReplayNilEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedReplayNilEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedReplayNilEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedReplayNilEnv + indexedTreeListConsKernelInfo.levelParams [] + indexedTreeListConsKernelInfo.type indexedTreeListType.ctors[1].type := by + tr_type_expr_tac + exact hshape.to_trExprS indexedReplayNilEnv_ordered trivial + ((indexedTreeCtorWF indexedTreeListType.ctors[1] + (.inr (by simp [indexedTreeListType]))).mono + (indexedReplayTypeEnv_le_leafEnv.trans + (indexedReplayLeafEnv_le_nodeEnv.trans + indexedReplayNodeEnv_le_nilEnv))) + +theorem indexedTreeRecKernelInfo_tr : + TrConstVal .safe indexedReplayCtorEnv indexedTreeRecKernelInfo + indexedTreeGeneration.recursors[0] := by + have hNat : indexedReplayCtorEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : indexedReplayCtorEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hSucc : indexedReplayCtorEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedReplayCtorEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedReplayCtorEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + have hLeaf : indexedReplayCtorEnv.constants ``IndexedTree.leaf = + some indexedTreeType.ctors[0].toVConstant := rfl + have hNode : indexedReplayCtorEnv.constants ``IndexedTree.node = + some indexedTreeType.ctors[1].toVConstant := rfl + have hNil : indexedReplayCtorEnv.constants ``IndexedTreeList.nil = + some indexedTreeListType.ctors[0].toVConstant := rfl + have hCons : indexedReplayCtorEnv.constants ``IndexedTreeList.cons = + some indexedTreeListType.ctors[1].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedReplayCtorEnv + indexedTreeRecKernelInfo.levelParams [] indexedTreeRecKernelInfo.type + indexedTreeGeneration.recursors[0].type := by tr_type_expr_tac + obtain ⟨u, hrec⟩ := indexedReplayGenerationEnv.recursor_wf (.head _) + exact hshape.to_trExprS indexedReplayCtorEnv_ordered trivial + ⟨.sort u, hrec⟩ + +theorem indexedTreeListRecKernelInfo_tr : + TrConstVal .safe indexedReplayFirstRecEnv indexedTreeListRecKernelInfo + indexedTreeGeneration.recursors[1] := by + have hNat : indexedReplayFirstRecEnv.constants ``Nat = + some InductiveFixtures.natType.toVConstant := rfl + have hZero : indexedReplayFirstRecEnv.constants ``Nat.zero = + some InductiveFixtures.natType.ctors[0].toVConstant := rfl + have hSucc : indexedReplayFirstRecEnv.constants ``Nat.succ = + some InductiveFixtures.natType.ctors[1].toVConstant := rfl + have hTree : indexedReplayFirstRecEnv.constants ``IndexedTree = + some indexedTreeType.toVConstant := rfl + have hTreeList : indexedReplayFirstRecEnv.constants ``IndexedTreeList = + some indexedTreeListType.toVConstant := rfl + have hLeaf : indexedReplayFirstRecEnv.constants ``IndexedTree.leaf = + some indexedTreeType.ctors[0].toVConstant := rfl + have hNode : indexedReplayFirstRecEnv.constants ``IndexedTree.node = + some indexedTreeType.ctors[1].toVConstant := rfl + have hNil : indexedReplayFirstRecEnv.constants ``IndexedTreeList.nil = + some indexedTreeListType.ctors[0].toVConstant := rfl + have hCons : indexedReplayFirstRecEnv.constants ``IndexedTreeList.cons = + some indexedTreeListType.ctors[1].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr indexedReplayFirstRecEnv + indexedTreeListRecKernelInfo.levelParams [] + indexedTreeListRecKernelInfo.type + indexedTreeGeneration.recursors[1].type := by tr_type_expr_tac + obtain ⟨u, hrec⟩ := indexedReplayGenerationEnv.recursor_wf + (.tail _ (.head _)) + exact hshape.to_trExprS indexedReplayFirstRecEnv_ordered trivial + ⟨.sort u, hrec.mono indexedReplayCtorEnv_le_firstRecEnv⟩ + +def indexedReplayFirstTypeMap : ConstMap := + natMap.insert ``IndexedTree indexedTreeKernelInfo + +def indexedReplayTypeMap : ConstMap := + indexedReplayFirstTypeMap.insert ``IndexedTreeList + indexedTreeListKernelInfo + +def indexedReplayLeafMap : ConstMap := + indexedReplayTypeMap.insert ``IndexedTree.leaf indexedTreeLeafKernelInfo + +def indexedReplayNodeMap : ConstMap := + indexedReplayLeafMap.insert ``IndexedTree.node indexedTreeNodeKernelInfo + +def indexedReplayNilMap : ConstMap := + indexedReplayNodeMap.insert ``IndexedTreeList.nil + indexedTreeListNilKernelInfo + +def indexedReplayCtorMap : ConstMap := + indexedReplayNilMap.insert ``IndexedTreeList.cons + indexedTreeListConsKernelInfo + +def indexedReplayFirstRecMap : ConstMap := + indexedReplayCtorMap.insert ``IndexedTree.rec indexedTreeRecKernelInfo + +def indexedReplayMap : ConstMap := + indexedReplayFirstRecMap.insert ``IndexedTreeList.rec + indexedTreeListRecKernelInfo + +theorem indexedReplayFirstType_fresh : + natMap.find? ``IndexedTree = none := by + rw [natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayFirstTypeMap_wf : indexedReplayFirstTypeMap.WF := + nat_aligned.map_wf.insert _ _ indexedReplayFirstType_fresh + +theorem indexedReplaySecondType_fresh : + indexedReplayFirstTypeMap.find? ``IndexedTreeList = none := by + rw [indexedReplayFirstTypeMap, nat_aligned.map_wf.find?_insert, + natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayTypeMap_wf : indexedReplayTypeMap.WF := + indexedReplayFirstTypeMap_wf.insert _ _ indexedReplaySecondType_fresh + +theorem indexedReplayLeaf_fresh : + indexedReplayTypeMap.find? ``IndexedTree.leaf = none := by + rw [indexedReplayTypeMap, indexedReplayFirstTypeMap_wf.find?_insert, + indexedReplayFirstTypeMap, nat_aligned.map_wf.find?_insert, + natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayLeafMap_wf : indexedReplayLeafMap.WF := + indexedReplayTypeMap_wf.insert _ _ indexedReplayLeaf_fresh + +theorem indexedReplayNode_fresh : + indexedReplayLeafMap.find? ``IndexedTree.node = none := by + rw [indexedReplayLeafMap, indexedReplayTypeMap_wf.find?_insert, + indexedReplayTypeMap, indexedReplayFirstTypeMap_wf.find?_insert, + indexedReplayFirstTypeMap, nat_aligned.map_wf.find?_insert, + natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayNodeMap_wf : indexedReplayNodeMap.WF := + indexedReplayLeafMap_wf.insert _ _ indexedReplayNode_fresh + +theorem indexedReplayNil_fresh : + indexedReplayNodeMap.find? ``IndexedTreeList.nil = none := by + rw [indexedReplayNodeMap, indexedReplayLeafMap_wf.find?_insert, + indexedReplayLeafMap, indexedReplayTypeMap_wf.find?_insert, + indexedReplayTypeMap, indexedReplayFirstTypeMap_wf.find?_insert, + indexedReplayFirstTypeMap, nat_aligned.map_wf.find?_insert, + natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayNilMap_wf : indexedReplayNilMap.WF := + indexedReplayNodeMap_wf.insert _ _ indexedReplayNil_fresh + +theorem indexedReplayCons_fresh : + indexedReplayNilMap.find? ``IndexedTreeList.cons = none := by + rw [indexedReplayNilMap, indexedReplayNodeMap_wf.find?_insert, + indexedReplayNodeMap, indexedReplayLeafMap_wf.find?_insert, + indexedReplayLeafMap, indexedReplayTypeMap_wf.find?_insert, + indexedReplayTypeMap, indexedReplayFirstTypeMap_wf.find?_insert, + indexedReplayFirstTypeMap, nat_aligned.map_wf.find?_insert, + natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayCtorMap_wf : indexedReplayCtorMap.WF := + indexedReplayNilMap_wf.insert _ _ indexedReplayCons_fresh + +theorem indexedReplayFirstRec_fresh : + indexedReplayCtorMap.find? ``IndexedTree.rec = none := by + rw [indexedReplayCtorMap, indexedReplayNilMap_wf.find?_insert, + indexedReplayNilMap, indexedReplayNodeMap_wf.find?_insert, + indexedReplayNodeMap, indexedReplayLeafMap_wf.find?_insert, + indexedReplayLeafMap, indexedReplayTypeMap_wf.find?_insert, + indexedReplayTypeMap, indexedReplayFirstTypeMap_wf.find?_insert, + indexedReplayFirstTypeMap, nat_aligned.map_wf.find?_insert, + natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayFirstRecMap_wf : indexedReplayFirstRecMap.WF := + indexedReplayCtorMap_wf.insert _ _ indexedReplayFirstRec_fresh + +theorem indexedReplaySecondRec_fresh : + indexedReplayFirstRecMap.find? ``IndexedTreeList.rec = none := by + rw [indexedReplayFirstRecMap, indexedReplayCtorMap_wf.find?_insert, + indexedReplayCtorMap, indexedReplayNilMap_wf.find?_insert, + indexedReplayNilMap, indexedReplayNodeMap_wf.find?_insert, + indexedReplayNodeMap, indexedReplayLeafMap_wf.find?_insert, + indexedReplayLeafMap, indexedReplayTypeMap_wf.find?_insert, + indexedReplayTypeMap, indexedReplayFirstTypeMap_wf.find?_insert, + indexedReplayFirstTypeMap, nat_aligned.map_wf.find?_insert, + natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem indexedReplayMap_wf : indexedReplayMap.WF := + indexedReplayFirstRecMap_wf.insert _ _ indexedReplaySecondRec_fresh + +theorem indexedReplay_treeRec_lookup : + indexedReplayMap.find? ``IndexedTree.rec = + some indexedTreeRecKernelInfo := by + rw [indexedReplayMap, indexedReplayFirstRecMap_wf.find?_insert, + indexedReplayFirstRecMap, indexedReplayCtorMap_wf.find?_insert] + rfl + +theorem indexedReplay_treeListRec_lookup : + indexedReplayMap.find? ``IndexedTreeList.rec = + some indexedTreeListRecKernelInfo := by + rw [indexedReplayMap, indexedReplayFirstRecMap_wf.find?_insert] + rfl + +def indexedTreeAddInductBlockTrace : + AddInductBlockTrace natMap natFinalEnv indexedTreeDecl + indexedReplayMap indexedTreeFinalEnv where + generation := indexedTreeGeneration + blockEnv := indexedTreeBlockEnv + generation_wf := indexedTreeBlockGenerationWF + typeMap := indexedReplayTypeMap + typeEnv := indexedReplayTypeEnv + ctorMap := indexedReplayCtorMap + ctorEnv := indexedReplayCtorEnv + recEnv := indexedReplayRecEnv + addTypes := .cons { + info := indexedTreeKernelInfo + kind_eq := by simp [indexedTreeKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeKernelInfo_tr + map_fresh := indexedReplayFirstType_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := indexedTreeListKernelInfo + kind_eq := by simp [indexedTreeListKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeListKernelInfo_tr + map_fresh := indexedReplaySecondType_fresh + env_add := rfl + map_add := rfl } .nil) + addCtors := .cons { + info := indexedTreeLeafKernelInfo + kind_eq := by simp [indexedTreeLeafKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeLeafKernelInfo_tr + map_fresh := indexedReplayLeaf_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := indexedTreeNodeKernelInfo + kind_eq := by simp [indexedTreeNodeKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeNodeKernelInfo_tr + map_fresh := indexedReplayNode_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := indexedTreeListNilKernelInfo + kind_eq := by simp [indexedTreeListNilKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeListNilKernelInfo_tr + map_fresh := indexedReplayNil_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := indexedTreeListConsKernelInfo + kind_eq := by simp [indexedTreeListConsKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeListConsKernelInfo_tr + map_fresh := indexedReplayCons_fresh + env_add := rfl + map_add := rfl } .nil))) + addRecs := .cons { + info := indexedTreeRecKernelInfo + kind_eq := by simp [indexedTreeRecKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeRecKernelInfo_tr + map_fresh := indexedReplayFirstRec_fresh + env_add := rfl + map_add := rfl } + (.cons { + info := indexedTreeListRecKernelInfo + kind_eq := by simp [indexedTreeListRecKernelInfo, + InductConstantKind.Matches] + tr := indexedTreeListRecKernelInfo_tr + map_fresh := indexedReplaySecondRec_fresh + env_add := rfl + map_add := rfl } .nil) + recK := by + intro recursor hrecursor + have hrecs : indexedTreeGeneration.recursors = + [indexedTreeGeneration.recursors[0], + indexedTreeGeneration.recursors[1]] := rfl + rw [hrecs] at hrecursor + simp only [List.mem_cons, List.not_mem_nil, or_false] at hrecursor + rcases hrecursor with rfl | rfl + · exact ⟨indexedTreeRecKernelInfo, + indexedReplay_treeRec_lookup, by decide⟩ + · exact ⟨indexedTreeListRecKernelInfo, + indexedReplay_treeListRec_lookup, by decide⟩ + addRules := ⟨rfl⟩ + +theorem indexedTreeAddInductBlock : + AddInductBlock natMap natFinalEnv indexedTreeDecl + indexedReplayMap indexedTreeFinalEnv := + ⟨indexedTreeAddInductBlockTrace⟩ + +theorem indexedTree_trEnv' : + TrEnv' .safe indexedReplayMap false indexedTreeFinalEnv := + .inductBlock indexedTreeAddInductBlock nat_trEnv' + +theorem indexedTree_verify_env_wf : indexedTreeFinalEnv.WF := + indexedTree_trEnv'.wf + +theorem indexedTree_verify_aligned : + Aligned .safe indexedReplayMap indexedTreeFinalEnv := + indexedTree_trEnv'.aligned + + + +/-! ## Trust-boundary manifests -/ + +/- The semantic generation and raw public transaction remain inside the +accepted Theory trust baseline. -/ +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.treeBlockGenerationWF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.indexedTreeBlockGenerationWF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.treeFinalEnv_ordered [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.indexedTreeFinalEnv_ordered [propext, Classical.choice, Quot.sound] + +/- The implementation metadata replay is now `sorryAx`-free and inherits only +the already classified persistent-map contracts; fixture-local native-decision +axioms are deliberately absent. -/ +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.treeAddInductBlock [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.indexedTreeAddInductBlock [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.tree_verify_aligned [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.indexedTree_verify_aligned [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.treeCheckedBlockWF [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.indexedTreeCheckedBlockWF [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.treeNormalizationBlockWF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.indexedTreeNormalizationBlockWF [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.treeValidationCertificate [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.MutualInductiveReplayFixtures.indexedTreeValidationCertificate [propext, Classical.choice, Quot.sound] + +end Ix.Theory.Named.MutualInductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/NestedReplay.lean b/Ix/Theory/Named/Verify/Environment/NestedReplay.lean new file mode 100644 index 000000000..e06fb7d68 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/NestedReplay.lean @@ -0,0 +1,3402 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.SingletonParityReplay +import Ix.Theory.Named.Verify.Environment.NestedTransformation + +/-! +# Nested environment replay (Spec-09C) + +Both ladder fixtures replayed from real stored metadata: the rose tree +over the completed `List` environment and the nested-indexed family over +a staged `PVec` boundary. Each inserts its stored constants through +`AddInductNestedTrace`, proves the `NestedBlockChecked.WF` package by +direct concrete typing derivations over the exact phase environments, +and drives the final map and environment through `TrEnv'.inductNested`, +with `Ordered` derived and the transitional closures guarded. +-/ + +namespace Ix.Theory.Named.NestedReplayFixtures + +open Lean +open Ix.Theory.Named.InductiveReplayFixtures +open Ix.Theory.Named.NestedRepresentation +open Ix.Theory.Named.NestedInductiveFixtures +open VInductDecl + +local instance : Inhabited VEnv := ⟨.empty⟩ +local instance : Inhabited VConstVal := ⟨⟨⟨0, .sort .zero⟩, .anonymous⟩⟩ + +/-! ## The completed List replay as the input boundary -/ + +theorem listTrEnv07 : TrEnv' .safe listMap07 false listFinalEnv07 := + .induct listAddInduct07 .empty + +theorem listFinalOrdered07 : listFinalEnv07.Ordered := + listTrEnv07.wf.ordered + +/-! ## The translated rose source and its nested artifact -/ + +def roseSourceV : VInductDecl where + uvars := 1 + nparams := 1 + types := + [{ name := ``RoseTree + uvars := 1 + type := nestedConstVType09A% RoseTree + ctors := + [⟨⟨1, nestedConstVType09A% RoseTree.node⟩, ``RoseTree.node⟩] }] + +def roseNestedC? : Option (NestedBlockChecked roseSourceV) := + nestedBlockChecked? [listTarget] roseSourceV + +#guard roseNestedC?.isSome + +def roseNestedC : NestedBlockChecked roseSourceV := + roseNestedC?.get (by native_decide) + +/-! ## Stored metadata and phase maps/environments -/ + +def roseInfo09 : ConstantInfo := kernelInductInfo% RoseTree +def roseNodeInfo09 : ConstantInfo := kernelCtorInfo% RoseTree.node +def roseRecInfo09 : ConstantInfo := kernelRecInfo% RoseTree.rec +def roseRec1Info09 : ConstantInfo := kernelRecInfo% RoseTree.rec_1 + +def roseFamilyV : VConstVal := roseSourceV.types[0].toVConstVal +def roseNodeV : VConstVal := roseSourceV.types[0].ctors[0] +def roseRecV : VConstVal := roseNestedC.recursors[0]! +def roseRec1V : VConstVal := roseNestedC.recursors[1]! + +#guard roseRecV.name == ``RoseTree.rec +#guard roseRec1V.name == `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 + +def roseTypeMap09 : ConstMap := listMap07.insert ``RoseTree roseInfo09 +def roseCtorMap09 : ConstMap := roseTypeMap09.insert ``RoseTree.node roseNodeInfo09 +def roseRecMap09 : ConstMap := roseCtorMap09.insert ``RoseTree.rec roseRecInfo09 +def roseMap09 : ConstMap := + roseRecMap09.insert `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 roseRec1Info09 + +def roseTypeEnv09 : VEnv := + (listFinalEnv07.addConst roseFamilyV.name roseFamilyV.toVConstant).get! +def roseCtorEnv09 : VEnv := + (roseTypeEnv09.addConst roseNodeV.name roseNodeV.toVConstant).get! +-- the recursor and rule phase environments are defined below, over the +-- printed literal inventories + + +/-! ## Printed artifact literals + +The restored recursor types and rule components, printed from the +computed artifact and tied back to it below; the concrete typing +derivations are stated over these literals. -/ + +/-- Printed image of `roseNestedC.recursors[0]!.type`. -/ +def roseRecTypeL : VExpr := + .forallE + (.sort (.succ (.param 1))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.forallE + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.forallE + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5)) + (.app (.bvar 5) (.bvar 0)))))))) + +def roseRec1TypeL : VExpr := + .forallE + (.sort (.succ (.param 1))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.forallE + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.forallE + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.app (.bvar 4) (.bvar 0)))))))) + +def roseRule0LhsL : VExpr := + .lam + (.sort (.succ (.param 1))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.lam + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.lam + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.lam + (.bvar 5) + (.lam + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 6))) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.rec + [.param 0, .param 1]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 7)) + (.bvar 1)) + (.bvar 0)))))))))) + +def roseRule0RhsL : VExpr := + .lam + (.sort (.succ (.param 1))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.lam + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.lam + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.lam + (.bvar 5) + (.lam + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 6))) + (.app + (.app + (.app (.bvar 4) (.bvar 1)) + (.bvar 0)) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 + [.param 0, .param 1]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.bvar 0)))))))))) + +def roseRule0TypeL : VExpr := + .forallE + (.sort (.succ (.param 1))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.forallE + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.forallE + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.forallE + (.bvar 5) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 6))) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 7)) + (.bvar 1)) + (.bvar 0)))))))))) + +def roseRule1LhsL : VExpr := + .lam + (.sort (.succ (.param 1))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.lam + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.lam + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 + [.param 0, .param 1]) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.bvar 1)) + (.bvar 0)) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))))))))) + +def roseRule1RhsL : VExpr := + .lam + (.sort (.succ (.param 1))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.lam + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.lam + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.bvar 1)))))) + +def roseRule1TypeL : VExpr := + .forallE + (.sort (.succ (.param 1))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.forallE + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.forallE + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.app + (.bvar 3) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))))))))) + +def roseRule2LhsL : VExpr := + .lam + (.sort (.succ (.param 1))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.lam + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.lam + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.lam + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5)) + (.lam + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 6))) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 + [.param 0, .param 1]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 7))) + (.bvar 1)) + (.bvar 0)))))))))) + +def roseRule2RhsL : VExpr := + .lam + (.sort (.succ (.param 1))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.lam + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.lam + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.lam + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.lam + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5)) + (.lam + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 6))) + (.app + (.app + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.rec + [.param 0, .param 1]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.bvar 1))) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 + [.param 0, .param 1]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.bvar 0)))))))))) + +def roseRule2TypeL : VExpr := + .forallE + (.sort (.succ (.param 1))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 0)) + (.sort (.param 0))) + (.forallE + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 1))) + (.sort (.param 0))) + (.forallE + (.forallE + (.bvar 2) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3))) + (.forallE + (.app (.bvar 2) (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree.node + [.param 1]) + (.bvar 5)) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.bvar 1) + (.app + (.const `List.nil [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 3)))) + (.forallE + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 4)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5))) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.forallE + (.app (.bvar 5) (.bvar 1)) + (.app + (.bvar 6) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 8))) + (.bvar 3)) + (.bvar 2))))))) + (.forallE + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 5)) + (.forallE + (.app + (.const `List [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 6))) + (.app + (.bvar 5) + (.app + (.app + (.app + (.const `List.cons [.param 1]) + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.RoseTree + [.param 1]) + (.bvar 7))) + (.bvar 1)) + (.bvar 0)))))))))) + +#guard roseRecV.type == roseRecTypeL +#guard roseRec1V.type == roseRec1TypeL +#guard roseNestedC.generatedRules.map (fun df => (df.uvars, df.lhs, df.rhs, df.type)) == + [(2, roseRule0LhsL, roseRule0RhsL, roseRule0TypeL), + (2, roseRule1LhsL, roseRule1RhsL, roseRule1TypeL), + (2, roseRule2LhsL, roseRule2RhsL, roseRule2TypeL)] +#guard roseRecV.uvars == 2 && roseRec1V.uvars == 2 + + +/-! ## Literal inventories -/ + +def roseRecVL : VConstVal := ⟨⟨2, roseRecTypeL⟩, ``RoseTree.rec⟩ +def roseRec1VL : VConstVal := + ⟨⟨2, roseRec1TypeL⟩, `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1⟩ + +def roseRulesL : List VDefEq := + [⟨2, roseRule0LhsL, roseRule0RhsL, roseRule0TypeL⟩, + ⟨2, roseRule1LhsL, roseRule1RhsL, roseRule1TypeL⟩, + ⟨2, roseRule2LhsL, roseRule2RhsL, roseRule2TypeL⟩] + +theorem roseRecursors_eq : roseNestedC.recursors = [roseRecVL, roseRec1VL] := by + native_decide + +theorem roseRules_eq : roseNestedC.generatedRules = roseRulesL := by + native_decide + +def roseRecEnv09 : VEnv := + (roseCtorEnv09.addConst roseRecVL.name roseRecVL.toVConstant).get! +def roseRec1Env09 : VEnv := + (roseRecEnv09.addConst roseRec1VL.name roseRec1VL.toVConstant).get! +def roseFinalEnv09 : VEnv := + roseRulesL.foldl VEnv.addDefEq roseRec1Env09 + +/-! ## Concrete constant well-formedness -/ + +theorem roseFamilyWF09 : roseFamilyV.toVConstant.WF listFinalEnv07 := + ⟨_, by type_tac⟩ + +theorem roseTypeEnv09_eq : + listFinalEnv07.addConst roseFamilyV.name roseFamilyV.toVConstant = + some roseTypeEnv09 := rfl + +theorem roseTypeOrdered09 : roseTypeEnv09.Ordered := + .const listFinalOrdered07 roseFamilyWF09 roseTypeEnv09_eq + +theorem roseNodeWF09 : roseNodeV.toVConstant.WF roseTypeEnv09 := by + have hList : roseTypeEnv09.constants ``List = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hRose : roseTypeEnv09.constants ``RoseTree = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + exact ⟨_, by type_tac⟩ + + +theorem roseCtorEnv09_eq : + roseTypeEnv09.addConst roseNodeV.name roseNodeV.toVConstant = + some roseCtorEnv09 := rfl + +theorem roseCtorOrdered09 : roseCtorEnv09.Ordered := + .const roseTypeOrdered09 roseNodeWF09 roseCtorEnv09_eq + +set_option maxRecDepth 4000 in +theorem roseRecWF09 : (⟨2, roseRecTypeL⟩ : VConstant).WF roseCtorEnv09 := by + have hList : roseCtorEnv09.constants ``List = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hRose : roseCtorEnv09.constants ``RoseTree = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hNode : roseCtorEnv09.constants ``RoseTree.node = + some roseNodeV.toVConstant := rfl + have hNil : roseCtorEnv09.constants ``List.nil = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.app (.const `List [.param 0]) (.bvar 0))⟩ := rfl + have hCons : roseCtorEnv09.constants ``List.cons = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) (.bvar 1)) + (.app (.const `List [.param 0]) (.bvar 2))))⟩ := rfl + exact ⟨_, by type_tac⟩ + + +theorem roseRecEnv09_eq : + roseCtorEnv09.addConst roseRecVL.name roseRecVL.toVConstant = + some roseRecEnv09 := rfl + +theorem roseRecOrdered09 : roseRecEnv09.Ordered := + .const roseCtorOrdered09 roseRecWF09 roseRecEnv09_eq + +set_option maxRecDepth 4000 in +theorem roseRec1WF09 : (⟨2, roseRec1TypeL⟩ : VConstant).WF roseRecEnv09 := by + have hList : roseRecEnv09.constants ``List = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hRose : roseRecEnv09.constants ``RoseTree = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hNode : roseRecEnv09.constants ``RoseTree.node = + some roseNodeV.toVConstant := rfl + have hNil : roseRecEnv09.constants ``List.nil = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.app (.const `List [.param 0]) (.bvar 0))⟩ := rfl + have hCons : roseRecEnv09.constants ``List.cons = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) (.bvar 1)) + (.app (.const `List [.param 0]) (.bvar 2))))⟩ := rfl + exact ⟨_, by type_tac⟩ + +theorem roseRec1Env09_eq : + roseRecEnv09.addConst roseRec1VL.name roseRec1VL.toVConstant = + some roseRec1Env09 := rfl + +theorem roseRec1Ordered09 : roseRec1Env09.Ordered := + .const roseRecOrdered09 roseRec1WF09 roseRec1Env09_eq + + +/-! ## Rule well-formedness at the rule-phase environment -/ + +section RuleWF + +set_option maxRecDepth 8000 + +/-- The lookup hypotheses shared by every rule component derivation; the +environment argument is any `addDefEq` extension of `roseRec1Env09`, whose +constants agree definitionally. -/ +macro "rose_rule_hyps" e:term : tactic => `(tactic| ( + have hList : VEnv.constants $e ``List = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hRose : VEnv.constants $e ``RoseTree = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hNode : VEnv.constants $e ``RoseTree.node = + some roseNodeV.toVConstant := rfl + have hNil : VEnv.constants $e ``List.nil = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.app (.const `List [.param 0]) (.bvar 0))⟩ := rfl + have hCons : VEnv.constants $e ``List.cons = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) (.bvar 1)) + (.app (.const `List [.param 0]) (.bvar 2))))⟩ := rfl + have hRec : VEnv.constants $e ``RoseTree.rec = + some ⟨2, roseRecTypeL⟩ := rfl + have hRec1 : VEnv.constants $e + `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 = + some ⟨2, roseRec1TypeL⟩ := rfl)) + +def roseRuleEnv1 : VEnv := roseRec1Env09.addDefEq roseRulesL[0] +def roseRuleEnv2 : VEnv := roseRuleEnv1.addDefEq roseRulesL[1] + +theorem roseRule0WF09 : roseRulesL[0].WF roseRec1Env09 := by + constructor + · rose_rule_hyps roseRec1Env09; type_tac + · rose_rule_hyps roseRec1Env09; type_tac + +theorem roseRule1WF09 : roseRulesL[1].WF roseRuleEnv1 := by + constructor + · rose_rule_hyps roseRuleEnv1; type_tac + · rose_rule_hyps roseRuleEnv1; type_tac + +theorem roseRule2WF09 : roseRulesL[2].WF roseRuleEnv2 := by + constructor + · rose_rule_hyps roseRuleEnv2; type_tac + · rose_rule_hyps roseRuleEnv2; type_tac + +end RuleWF + + +/-! ## The semantic package -/ + +theorem roseTypesFold_eq : + roseSourceV.blockTypeConstants.foldlM + (fun env c => env.addConst c.name c.toVConstant) listFinalEnv07 = + some roseTypeEnv09 := rfl + +theorem roseCtorsFold_eq : + roseSourceV.blockConstructorConstants.foldlM + (fun env c => env.addConst c.name c.toVConstant) roseTypeEnv09 = + some roseCtorEnv09 := rfl + +theorem roseRecsFold_eq : + roseNestedC.recursors.foldlM + (fun env c => env.addConst c.name c.toVConstant) roseCtorEnv09 = + some roseRec1Env09 := by + rw [roseRecursors_eq]; rfl + +theorem roseNestedWF09 : roseNestedC.WF listFinalEnv07 := by + refine ⟨⟨roseFamilyWF09, fun env' h => ?_⟩, fun {typeEnv} h => ?_, + fun {typeEnv ctorEnv} hT hC => ?_, fun {typeEnv ctorEnv recEnv} hT hC hR => ?_⟩ + · cases Option.some.inj (roseTypeEnv09_eq.symm.trans h) + exact trivial + · cases Option.some.inj (roseTypesFold_eq.symm.trans h) + exact ⟨roseNodeWF09, fun env' h' => by + cases Option.some.inj (roseCtorEnv09_eq.symm.trans h') + exact trivial⟩ + · cases Option.some.inj (roseTypesFold_eq.symm.trans hT) + cases Option.some.inj (roseCtorsFold_eq.symm.trans hC) + rw [roseRecursors_eq] + exact ⟨roseRecWF09, fun env' h' => by + cases Option.some.inj (roseRecEnv09_eq.symm.trans h') + exact ⟨roseRec1WF09, fun env'' h'' => by + cases Option.some.inj (roseRec1Env09_eq.symm.trans h'') + exact trivial⟩⟩ + · cases Option.some.inj (roseTypesFold_eq.symm.trans hT) + cases Option.some.inj (roseCtorsFold_eq.symm.trans hC) + cases Option.some.inj (roseRecsFold_eq.symm.trans hR) + rw [roseRules_eq] + exact ⟨roseRule0WF09, roseRule1WF09, roseRule2WF09, trivial⟩ + + +/-! ## Freshness of the stored insertions -/ + +theorem listMapWF07 : listMap07.WF := + listCtorMapWF07.insert _ _ listRecFresh07 + +theorem roseTypeFresh09 : listMap07.find? ``RoseTree = none := by + rw [listMap07, listCtorMapWF07.find?_insert, listCtorMap07, + listNilMapWF07.find?_insert, listNilMap07, + listTypeMapWF07.find?_insert, listTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem roseTypeMapWF09 : roseTypeMap09.WF := + listMapWF07.insert _ _ roseTypeFresh09 + +theorem roseNodeFresh09 : roseTypeMap09.find? ``RoseTree.node = none := by + rw [roseTypeMap09, listMapWF07.find?_insert, listMap07, + listCtorMapWF07.find?_insert, listCtorMap07, + listNilMapWF07.find?_insert, listNilMap07, + listTypeMapWF07.find?_insert, listTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem roseCtorMapWF09 : roseCtorMap09.WF := + roseTypeMapWF09.insert _ _ roseNodeFresh09 + +theorem roseRecFresh09 : roseCtorMap09.find? ``RoseTree.rec = none := by + rw [roseCtorMap09, roseTypeMapWF09.find?_insert, roseTypeMap09, + listMapWF07.find?_insert, listMap07, + listCtorMapWF07.find?_insert, listCtorMap07, + listNilMapWF07.find?_insert, listNilMap07, + listTypeMapWF07.find?_insert, listTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem roseRecMapWF09 : roseRecMap09.WF := + roseCtorMapWF09.insert _ _ roseRecFresh09 + +theorem roseRec1Fresh09 : + roseRecMap09.find? `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 = none := by + rw [roseRecMap09, roseCtorMapWF09.find?_insert, roseCtorMap09, + roseTypeMapWF09.find?_insert, roseTypeMap09, + listMapWF07.find?_insert, listMap07, + listCtorMapWF07.find?_insert, listCtorMap07, + listNilMapWF07.find?_insert, listNilMap07, + listTypeMapWF07.find?_insert, listTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +/-! ## Stored-metadata translations -/ + +theorem roseInfoTr09 : + TrConstVal .safe listFinalEnv07 roseInfo09 roseFamilyV := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr listFinalEnv07 roseInfo09.levelParams [] + roseInfo09.type roseFamilyV.toVConstant.type := by + tr_type_expr_tac + exact shape.to_trExprS listFinalOrdered07 trivial ⟨_, by type_tac⟩ + +theorem roseNodeTr09 : + TrConstVal .safe roseTypeEnv09 roseNodeInfo09 roseNodeV := by + have hList : roseTypeEnv09.constants ``List = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hRose : roseTypeEnv09.constants ``RoseTree = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr roseTypeEnv09 roseNodeInfo09.levelParams [] + roseNodeInfo09.type roseNodeV.toVConstant.type := by + tr_type_expr_tac + exact shape.to_trExprS roseTypeOrdered09 trivial ⟨_, by type_tac⟩ + +theorem roseRecTr09 : + TrConstVal .safe roseCtorEnv09 roseRecInfo09 roseRecVL := by + have hList : roseCtorEnv09.constants ``List = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hRose : roseCtorEnv09.constants ``RoseTree = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hNode : roseCtorEnv09.constants ``RoseTree.node = + some roseNodeV.toVConstant := rfl + have hNil : roseCtorEnv09.constants ``List.nil = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.app (.const `List [.param 0]) (.bvar 0))⟩ := rfl + have hCons : roseCtorEnv09.constants ``List.cons = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) (.bvar 1)) + (.app (.const `List [.param 0]) (.bvar 2))))⟩ := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr roseCtorEnv09 roseRecInfo09.levelParams [] + roseRecInfo09.type roseRecVL.toVConstant.type := by + tr_type_expr_tac + obtain ⟨u, hty⟩ := roseRecWF09 + exact shape.to_trExprS roseCtorOrdered09 trivial ⟨_, hty⟩ + +theorem roseRec1Tr09 : + TrConstVal .safe roseRecEnv09 roseRec1Info09 roseRec1VL := by + have hList : roseRecEnv09.constants ``List = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hRose : roseRecEnv09.constants ``RoseTree = + some ⟨1, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))⟩ := rfl + have hNode : roseRecEnv09.constants ``RoseTree.node = + some roseNodeV.toVConstant := rfl + have hNil : roseRecEnv09.constants ``List.nil = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.app (.const `List [.param 0]) (.bvar 0))⟩ := rfl + have hCons : roseRecEnv09.constants ``List.cons = + some ⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const `List [.param 0]) (.bvar 1)) + (.app (.const `List [.param 0]) (.bvar 2))))⟩ := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr roseRecEnv09 roseRec1Info09.levelParams [] + roseRec1Info09.type roseRec1VL.toVConstant.type := by + tr_type_expr_tac + obtain ⟨u, hty⟩ := roseRec1WF09 + exact shape.to_trExprS roseRecOrdered09 trivial ⟨_, hty⟩ + + +/-! ## Recursor K metadata and stored lookups -/ + +theorem roseKTarget09 : roseNestedC.generation.kTarget = false := by + native_decide + +theorem roseRecLookup09 : + roseMap09.find? ``RoseTree.rec = some roseRecInfo09 := by + rw [roseMap09, roseRecMapWF09.find?_insert] + simp [roseRecMap09, roseCtorMapWF09.find?_insert] + +theorem roseRec1Lookup09 : + roseMap09.find? `Ix.Theory.Named.NestedRepresentation.RoseTree.rec_1 = + some roseRec1Info09 := by + rw [roseMap09, roseRecMapWF09.find?_insert] + simp + +theorem roseRecK09 : + RecursorMapKMatches roseMap09 roseNestedC.recursors + roseNestedC.generation.kTarget := by + rw [roseRecursors_eq, roseKTarget09] + intro recursor hmem + rcases List.mem_cons.1 hmem with rfl | hmem + · exact ⟨roseRecInfo09, roseRecLookup09, by decide⟩ + rcases List.mem_cons.1 hmem with rfl | hmem + · exact ⟨roseRec1Info09, roseRec1Lookup09, by decide⟩ + · cases hmem + +/-! ## The nested alignment trace and its `TrEnv'` drive -/ + +def roseTrace09 : + AddInductNestedTrace listMap07 listFinalEnv07 roseSourceV + roseMap09 roseFinalEnv09 where + nested := roseNestedC + nested_wf := roseNestedWF09 + typeMap := roseTypeMap09 + typeEnv := roseTypeEnv09 + ctorMap := roseCtorMap09 + ctorEnv := roseCtorEnv09 + recEnv := roseRec1Env09 + addTypes := .cons + { info := roseInfo09 + kind_eq := trivial + tr := roseInfoTr09 + map_fresh := roseTypeFresh09 + env_add := roseTypeEnv09_eq + map_add := rfl } .nil + addCtors := .cons + { info := roseNodeInfo09 + kind_eq := trivial + tr := roseNodeTr09 + map_fresh := roseNodeFresh09 + env_add := roseCtorEnv09_eq + map_add := rfl } .nil + addRecs := roseRecursors_eq ▸ .cons + { info := roseRecInfo09 + kind_eq := trivial + tr := roseRecTr09 + map_fresh := roseRecFresh09 + env_add := roseRecEnv09_eq + map_add := rfl } (.cons + { info := roseRec1Info09 + kind_eq := trivial + tr := roseRec1Tr09 + map_fresh := roseRec1Fresh09 + env_add := roseRec1Env09_eq + map_add := rfl } .nil) + recK := roseRecK09 + addRules := ⟨by rw [roseRules_eq]; rfl⟩ + +theorem roseAddInductNested09 : + AddInductNested listMap07 listFinalEnv07 roseSourceV + roseMap09 roseFinalEnv09 := + ⟨roseTrace09⟩ + +/-- The rose-tree nested declaration, replayed from real stored metadata +over the completed `List` environment through the nested alignment +constructor. -/ +theorem roseTrEnv09 : TrEnv' .safe roseMap09 false roseFinalEnv09 := + .inductNested roseAddInductNested09 listTrEnv07 + +theorem roseFinalOrdered09 : roseFinalEnv09.Ordered := + roseTrEnv09.wf.ordered + + +/-! ## Round-trip guards + +The stored-metadata surface inserted by the trace is tied to the Theory +artifact inventory, and the final map/environment pair carries the +documented closure (persistent-map contracts plus the compiler-trust axioms +introduced by the `native_decide` observations). -/ + +#guard roseNestedC.elim.numNested == 1 +#guard roseRecV == roseRecVL && roseRec1V == roseRec1VL + +#guard_named_axioms Ix.Theory.Named.NestedReplayFixtures.roseTrEnv09 [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert, + Ix.Theory.Named.NestedReplayFixtures.roseKTarget09._native.native_decide.ax_1_1, + Ix.Theory.Named.NestedReplayFixtures.roseNestedC._native.native_decide.ax_1, + Ix.Theory.Named.NestedReplayFixtures.roseRecursors_eq._native.native_decide.ax_1_1, + Ix.Theory.Named.NestedReplayFixtures.roseRules_eq._native.native_decide.ax_1_1] + +#guard_named_axioms Ix.Theory.Named.NestedReplayFixtures.roseNestedWF09 [ + propext, + Classical.choice, + Quot.sound, + Ix.Theory.Named.NestedReplayFixtures.roseNestedC._native.native_decide.ax_1, + Ix.Theory.Named.NestedReplayFixtures.roseRecursors_eq._native.native_decide.ax_1_1, + Ix.Theory.Named.NestedReplayFixtures.roseRules_eq._native.native_decide.ax_1_1] + + +/-! # The nested-indexed fixture + +`NVTree` nests through the locally declared indexed `PVec`. The base +environment stages the `PVec` family and constructors over the completed +`Nat` replay through `TrEnv'.inductStaging`; the nested trace then inserts +the stored `NVTree` metadata and drives `TrEnv'.inductNested`. -/ + +/-! ## Staged `PVec` base -/ + +def pvecInfo09 : ConstantInfo := kernelInductInfo% PVec +def pvecNilInfo09 : ConstantInfo := kernelCtorInfo% PVec.nil +def pvecConsInfo09 : ConstantInfo := kernelCtorInfo% PVec.cons + +def pvecFamilyVL : VConstVal := + ⟨⟨0, .forallE (.sort (.succ .zero)) + (.forallE (.const `Nat []) (.sort (.succ .zero)))⟩, ``PVec⟩ +def pvecNilVL : VConstVal := ⟨⟨0, nestedConstVType09A% PVec.nil⟩, ``PVec.nil⟩ +def pvecConsVL : VConstVal := ⟨⟨0, nestedConstVType09A% PVec.cons⟩, ``PVec.cons⟩ + +def pvecTypeMap09 : ConstMap := natMap.insert ``PVec pvecInfo09 +def pvecNilMap09 : ConstMap := pvecTypeMap09.insert ``PVec.nil pvecNilInfo09 +def pvecCtorMap09 : ConstMap := pvecNilMap09.insert ``PVec.cons pvecConsInfo09 + +def pvecTypeEnv09 : VEnv := + (natFinalEnv.addConst pvecFamilyVL.name pvecFamilyVL.toVConstant).get! +def pvecNilEnv09 : VEnv := + (pvecTypeEnv09.addConst pvecNilVL.name pvecNilVL.toVConstant).get! +def pvecCtorEnv09 : VEnv := + (pvecNilEnv09.addConst pvecConsVL.name pvecConsVL.toVConstant).get! + +theorem pvecTypeFresh09 : natMap.find? ``PVec = none := by + rw [natMap, natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem pvecTypeMapWF09 : pvecTypeMap09.WF := + natMap_wf.insert _ _ pvecTypeFresh09 + +theorem pvecNilFresh09 : pvecTypeMap09.find? ``PVec.nil = none := by + rw [pvecTypeMap09, natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem pvecNilMapWF09 : pvecNilMap09.WF := + pvecTypeMapWF09.insert _ _ pvecNilFresh09 + +theorem pvecConsFresh09 : pvecNilMap09.find? ``PVec.cons = none := by + rw [pvecNilMap09, pvecTypeMapWF09.find?_insert, pvecTypeMap09, + natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem pvecCtorMapWF09 : pvecCtorMap09.WF := + pvecNilMapWF09.insert _ _ pvecConsFresh09 + +theorem natFinalOrdered09 : natFinalEnv.Ordered := + (nat_trEnv' (safety := .safe)).wf.ordered + +theorem pvecFamilyWF09 : pvecFamilyVL.toVConstant.WF natFinalEnv := by + have hNat : natFinalEnv.constants ``Nat = some ⟨0, .sort (.succ .zero)⟩ := rfl + exact ⟨_, by type_tac⟩ + +theorem pvecTypeEnv09_eq : + natFinalEnv.addConst pvecFamilyVL.name pvecFamilyVL.toVConstant = + some pvecTypeEnv09 := rfl + +theorem pvecTypeOrdered09 : pvecTypeEnv09.Ordered := + .const natFinalOrdered09 pvecFamilyWF09 pvecTypeEnv09_eq + +theorem pvecNilWF09 : pvecNilVL.toVConstant.WF pvecTypeEnv09 := by + have hNat : pvecTypeEnv09.constants ``Nat = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hZero : pvecTypeEnv09.constants ``Nat.zero = some ⟨0, .const `Nat []⟩ := rfl + have hPVec : pvecTypeEnv09.constants ``PVec = some pvecFamilyVL.toVConstant := rfl + exact ⟨_, by type_tac⟩ + +theorem pvecNilEnv09_eq : + pvecTypeEnv09.addConst pvecNilVL.name pvecNilVL.toVConstant = + some pvecNilEnv09 := rfl + +theorem pvecNilOrdered09 : pvecNilEnv09.Ordered := + .const pvecTypeOrdered09 pvecNilWF09 pvecNilEnv09_eq + +theorem pvecConsWF09 : pvecConsVL.toVConstant.WF pvecNilEnv09 := by + have hNat : pvecNilEnv09.constants ``Nat = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hSucc : pvecNilEnv09.constants ``Nat.succ = + some ⟨0, .forallE (.const `Nat []) (.const `Nat [])⟩ := rfl + have hPVec : pvecNilEnv09.constants ``PVec = some pvecFamilyVL.toVConstant := rfl + exact ⟨_, by type_tac⟩ + +theorem pvecConsEnv09_eq : + pvecNilEnv09.addConst pvecConsVL.name pvecConsVL.toVConstant = + some pvecCtorEnv09 := rfl + +theorem pvecCtorOrdered09 : pvecCtorEnv09.Ordered := + .const pvecNilOrdered09 pvecConsWF09 pvecConsEnv09_eq + +theorem pvecInfoTr09 : TrConstVal .safe natFinalEnv pvecInfo09 pvecFamilyVL := by + have hNat : natFinalEnv.constants ``Nat = some ⟨0, .sort (.succ .zero)⟩ := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr natFinalEnv pvecInfo09.levelParams [] + pvecInfo09.type pvecFamilyVL.toVConstant.type := by + tr_type_expr_tac + exact shape.to_trExprS natFinalOrdered09 trivial ⟨_, by type_tac⟩ + +theorem pvecNilTr09 : TrConstVal .safe pvecTypeEnv09 pvecNilInfo09 pvecNilVL := by + have hNat : pvecTypeEnv09.constants ``Nat = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hZero : pvecTypeEnv09.constants ``Nat.zero = some ⟨0, .const `Nat []⟩ := rfl + have hPVec : pvecTypeEnv09.constants ``PVec = some pvecFamilyVL.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr pvecTypeEnv09 pvecNilInfo09.levelParams [] + pvecNilInfo09.type pvecNilVL.toVConstant.type := by + tr_type_expr_tac + exact shape.to_trExprS pvecTypeOrdered09 trivial ⟨_, by type_tac⟩ + +theorem pvecConsTr09 : TrConstVal .safe pvecNilEnv09 pvecConsInfo09 pvecConsVL := by + have hNat : pvecNilEnv09.constants ``Nat = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hSucc : pvecNilEnv09.constants ``Nat.succ = + some ⟨0, .forallE (.const `Nat []) (.const `Nat [])⟩ := rfl + have hPVec : pvecNilEnv09.constants ``PVec = some pvecFamilyVL.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr pvecNilEnv09 pvecConsInfo09.levelParams [] + pvecConsInfo09.type pvecConsVL.toVConstant.type := by + tr_type_expr_tac + exact shape.to_trExprS pvecNilOrdered09 trivial ⟨_, by type_tac⟩ + +/-- The staged `PVec` boundary: family and constructors present, no +recursor or rules — exactly the constants the nested `NVTree` artifacts +reference. -/ +theorem pvecTrEnv09 : TrEnv' .safe pvecCtorMap09 false pvecCtorEnv09 := + .inductStaging (kind := .ctor) + { info := pvecConsInfo09 + kind_eq := trivial + tr := pvecConsTr09 + map_fresh := pvecConsFresh09 + env_add := pvecConsEnv09_eq + map_add := rfl } pvecConsWF09 <| + .inductStaging (kind := .ctor) + { info := pvecNilInfo09 + kind_eq := trivial + tr := pvecNilTr09 + map_fresh := pvecNilFresh09 + env_add := pvecNilEnv09_eq + map_add := rfl } pvecNilWF09 <| + .inductStaging (kind := .induct) + { info := pvecInfo09 + kind_eq := trivial + tr := pvecInfoTr09 + map_fresh := pvecTypeFresh09 + env_add := pvecTypeEnv09_eq + map_add := rfl } pvecFamilyWF09 nat_trEnv' + + +/-! ## The translated NV source and its nested artifact -/ + +def nvSourceV : VInductDecl where + uvars := 0 + nparams := 0 + types := + [{ name := ``NVTree + uvars := 0 + type := nestedConstVType09A% NVTree + ctors := [⟨⟨0, nestedConstVType09A% NVTree.node⟩, ``NVTree.node⟩] }] + +def nvNestedC? : Option (NestedBlockChecked nvSourceV) := + nestedBlockChecked? [NestedTransformation.pvecStoredTarget] nvSourceV + +#guard nvNestedC?.isSome + +def nvNestedC : NestedBlockChecked nvSourceV := + nvNestedC?.get (by native_decide) + +def nvInfo09 : ConstantInfo := kernelInductInfo% NVTree +def nvNodeInfo09 : ConstantInfo := kernelCtorInfo% NVTree.node +def nvRecInfo09 : ConstantInfo := kernelRecInfo% NVTree.rec +def nvRec1Info09 : ConstantInfo := kernelRecInfo% NVTree.rec_1 + +def nvFamilyV : VConstVal := nvSourceV.types[0].toVConstVal +def nvNodeV : VConstVal := nvSourceV.types[0].ctors[0] + +def nvTypeMap09 : ConstMap := pvecCtorMap09.insert ``NVTree nvInfo09 +def nvCtorMap09 : ConstMap := nvTypeMap09.insert ``NVTree.node nvNodeInfo09 +def nvRecMap09 : ConstMap := nvCtorMap09.insert ``NVTree.rec nvRecInfo09 +def nvMap09 : ConstMap := + nvRecMap09.insert `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 nvRec1Info09 + +def nvTypeEnv09 : VEnv := + (pvecCtorEnv09.addConst nvFamilyV.name nvFamilyV.toVConstant).get! +def nvCtorEnv09 : VEnv := + (nvTypeEnv09.addConst nvNodeV.name nvNodeV.toVConstant).get! + +def nvFamilyTypeL : VExpr := + .sort (.succ (.zero)) + +def nvNodeTypeL : VExpr := + .forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + +def nvRecTypeL : VExpr := + .forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.app (.bvar 5) (.bvar 0))))))) + +def nvRec1TypeL : VExpr := + .forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.app + (.app (.bvar 5) (.bvar 1)) + (.bvar 0)))))))) + +def nvRule0LhsL : VExpr := + .lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.lam + (.const `Nat []) + (.lam + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree.rec + [.param 0]) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 1)) + (.bvar 0))))))))) + +def nvRule0RhsL : VExpr := + .lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.lam + (.const `Nat []) + (.lam + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.app + (.app + (.app (.bvar 4) (.bvar 1)) + (.bvar 0)) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 + [.param 0]) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.bvar 1)) + (.bvar 0))))))))) + +def nvRule0TypeL : VExpr := + .forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.app + (.bvar 6) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 1)) + (.bvar 0))))))))) + +def nvRule1LhsL : VExpr := + .lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 + [.param 0]) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)) + (.bvar 1)) + (.bvar 0)) + (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))))))) + +def nvRule1RhsL : VExpr := + .lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.bvar 1))))) + +def nvRule1TypeL : VExpr := + .forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.app + (.app (.bvar 3) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))))))) + +def nvRule2LhsL : VExpr := + .lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.lam + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.lam + (.const `Nat []) + (.lam + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 + [.param 0]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.app + (.const `Nat.succ []) + (.bvar 1))) + (.app + (.app + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.cons []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 2)) + (.bvar 1)) + (.bvar 0)))))))))) + +def nvRule2RhsL : VExpr := + .lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.lam + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.lam + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.lam + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.lam + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.lam + (.const `Nat []) + (.lam + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.app + (.app + (.app + (.app + (.app (.bvar 3) (.bvar 2)) + (.bvar 1)) + (.bvar 0)) + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree.rec + [.param 0]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 2))) + (.app + (.app + (.app + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 + [.param 0]) + (.bvar 7)) + (.bvar 6)) + (.bvar 5)) + (.bvar 4)) + (.bvar 3)) + (.bvar 1)) + (.bvar 0)))))))))) + +def nvRule2TypeL : VExpr := + .forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.sort (.param 0))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.sort (.param 0)))) + (.forallE + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app + (.app (.bvar 2) (.bvar 1)) + (.bvar 0)) + (.app + (.bvar 4) + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.NVTree.node []) + (.bvar 2)) + (.bvar 1)))))) + (.forallE + (.app + (.app (.bvar 1) (.const `Nat.zero [])) + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.nil []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []))) + (.forallE + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.forallE + (.app (.bvar 6) (.bvar 2)) + (.forallE + (.app + (.app (.bvar 6) (.bvar 2)) + (.bvar 1)) + (.app + (.app + (.bvar 7) + (.app + (.const `Nat.succ []) + (.bvar 3))) + (.app + (.app + (.app + (.app + (.const + `Ix.Theory.Named.NestedRepresentation.PVec.cons + []) + (.const + `Ix.Theory.Named.NestedRepresentation.NVTree + [])) + (.bvar 4)) + (.bvar 3)) + (.bvar 2)))))))) + (.forallE + (.const `Ix.Theory.Named.NestedRepresentation.NVTree []) + (.forallE + (.const `Nat []) + (.forallE + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 0)) + (.app + (.app + (.bvar 6) + (.app + (.const `Nat.succ []) + (.bvar 1))) + (.app + (.app + (.app + (.app + (.const `Ix.Theory.Named.NestedRepresentation.PVec.cons []) + (.const `Ix.Theory.Named.NestedRepresentation.NVTree [])) + (.bvar 2)) + (.bvar 1)) + (.bvar 0)))))))))) + +def nvRecVL : VConstVal := ⟨⟨1, nvRecTypeL⟩, ``NVTree.rec⟩ +def nvRec1VL : VConstVal := + ⟨⟨1, nvRec1TypeL⟩, `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1⟩ + +def nvRulesL : List VDefEq := + [⟨1, nvRule0LhsL, nvRule0RhsL, nvRule0TypeL⟩, + ⟨1, nvRule1LhsL, nvRule1RhsL, nvRule1TypeL⟩, + ⟨1, nvRule2LhsL, nvRule2RhsL, nvRule2TypeL⟩] + +theorem nvRecursors_eq : nvNestedC.recursors = [nvRecVL, nvRec1VL] := by + native_decide + +theorem nvRules_eq : nvNestedC.generatedRules = nvRulesL := by + native_decide + +def nvRecEnv09 : VEnv := + (nvCtorEnv09.addConst nvRecVL.name nvRecVL.toVConstant).get! +def nvRec1Env09 : VEnv := + (nvRecEnv09.addConst nvRec1VL.name nvRec1VL.toVConstant).get! +def nvFinalEnv09 : VEnv := + nvRulesL.foldl VEnv.addDefEq nvRec1Env09 + + +/-! ## NV constant well-formedness and phase chains -/ + +macro "nv_hyps" e:term : tactic => `(tactic| ( + have hNat : VEnv.constants $e ``Nat = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hZero : VEnv.constants $e ``Nat.zero = some ⟨0, .const `Nat []⟩ := rfl + have hSucc : VEnv.constants $e ``Nat.succ = + some ⟨0, .forallE (.const `Nat []) (.const `Nat [])⟩ := rfl + have hPVec : VEnv.constants $e ``PVec = some pvecFamilyVL.toVConstant := rfl + have hPNil : VEnv.constants $e ``PVec.nil = some pvecNilVL.toVConstant := rfl + have hPCons : VEnv.constants $e ``PVec.cons = some pvecConsVL.toVConstant := rfl)) + +theorem nvFamilyWF09 : nvFamilyV.toVConstant.WF pvecCtorEnv09 := + ⟨_, by type_tac⟩ + +theorem nvTypeEnv09_eq : + pvecCtorEnv09.addConst nvFamilyV.name nvFamilyV.toVConstant = + some nvTypeEnv09 := rfl + +theorem nvTypeOrdered09 : nvTypeEnv09.Ordered := + .const pvecCtorOrdered09 nvFamilyWF09 nvTypeEnv09_eq + +theorem nvNodeWF09 : nvNodeV.toVConstant.WF nvTypeEnv09 := by + nv_hyps nvTypeEnv09 + have hNV : nvTypeEnv09.constants ``NVTree = some ⟨0, .sort (.succ .zero)⟩ := rfl + exact ⟨_, by type_tac⟩ + +theorem nvCtorEnv09_eq : + nvTypeEnv09.addConst nvNodeV.name nvNodeV.toVConstant = + some nvCtorEnv09 := rfl + +theorem nvCtorOrdered09 : nvCtorEnv09.Ordered := + .const nvTypeOrdered09 nvNodeWF09 nvCtorEnv09_eq + +set_option maxRecDepth 4000 in +theorem nvRecWF09 : (⟨1, nvRecTypeL⟩ : VConstant).WF nvCtorEnv09 := by + nv_hyps nvCtorEnv09 + have hNV : nvCtorEnv09.constants ``NVTree = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hNode : nvCtorEnv09.constants ``NVTree.node = + some nvNodeV.toVConstant := rfl + exact ⟨_, by type_tac⟩ + +theorem nvRecEnv09_eq : + nvCtorEnv09.addConst nvRecVL.name nvRecVL.toVConstant = + some nvRecEnv09 := rfl + +theorem nvRecOrdered09 : nvRecEnv09.Ordered := + .const nvCtorOrdered09 nvRecWF09 nvRecEnv09_eq + +set_option maxRecDepth 4000 in +theorem nvRec1WF09 : (⟨1, nvRec1TypeL⟩ : VConstant).WF nvRecEnv09 := by + nv_hyps nvRecEnv09 + have hNV : nvRecEnv09.constants ``NVTree = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hNode : nvRecEnv09.constants ``NVTree.node = + some nvNodeV.toVConstant := rfl + exact ⟨_, by type_tac⟩ + +theorem nvRec1Env09_eq : + nvRecEnv09.addConst nvRec1VL.name nvRec1VL.toVConstant = + some nvRec1Env09 := rfl + +theorem nvRec1Ordered09 : nvRec1Env09.Ordered := + .const nvRecOrdered09 nvRec1WF09 nvRec1Env09_eq + +section NVRuleWF + +set_option maxRecDepth 8000 + +macro "nv_rule_hyps" e:term : tactic => `(tactic| ( + nv_hyps $e + have hNV : VEnv.constants $e ``NVTree = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hNode : VEnv.constants $e ``NVTree.node = some nvNodeV.toVConstant := rfl + have hRec : VEnv.constants $e ``NVTree.rec = some ⟨1, nvRecTypeL⟩ := rfl + have hRec1 : VEnv.constants $e + `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 = some ⟨1, nvRec1TypeL⟩ := rfl)) + +def nvRuleEnv1 : VEnv := nvRec1Env09.addDefEq nvRulesL[0] +def nvRuleEnv2 : VEnv := nvRuleEnv1.addDefEq nvRulesL[1] + +theorem nvRule0WF09 : nvRulesL[0].WF nvRec1Env09 := by + constructor + · nv_rule_hyps nvRec1Env09; type_tac + · nv_rule_hyps nvRec1Env09; type_tac + +theorem nvRule1WF09 : nvRulesL[1].WF nvRuleEnv1 := by + constructor + · nv_rule_hyps nvRuleEnv1; type_tac + · nv_rule_hyps nvRuleEnv1; type_tac + +theorem nvRule2WF09 : nvRulesL[2].WF nvRuleEnv2 := by + constructor + · nv_rule_hyps nvRuleEnv2; type_tac + · nv_rule_hyps nvRuleEnv2; type_tac + +end NVRuleWF + + +/-! ## NV semantic package -/ + +theorem nvTypesFold_eq : + nvSourceV.blockTypeConstants.foldlM + (fun env c => env.addConst c.name c.toVConstant) pvecCtorEnv09 = + some nvTypeEnv09 := rfl + +theorem nvCtorsFold_eq : + nvSourceV.blockConstructorConstants.foldlM + (fun env c => env.addConst c.name c.toVConstant) nvTypeEnv09 = + some nvCtorEnv09 := rfl + +theorem nvRecsFold_eq : + nvNestedC.recursors.foldlM + (fun env c => env.addConst c.name c.toVConstant) nvCtorEnv09 = + some nvRec1Env09 := by + rw [nvRecursors_eq]; rfl + +theorem nvNestedWF09 : nvNestedC.WF pvecCtorEnv09 := by + refine ⟨⟨nvFamilyWF09, fun env' h => ?_⟩, fun {typeEnv} h => ?_, + fun {typeEnv ctorEnv} hT hC => ?_, fun {typeEnv ctorEnv recEnv} hT hC hR => ?_⟩ + · cases Option.some.inj (nvTypeEnv09_eq.symm.trans h) + exact trivial + · cases Option.some.inj (nvTypesFold_eq.symm.trans h) + exact ⟨nvNodeWF09, fun env' h' => by + cases Option.some.inj (nvCtorEnv09_eq.symm.trans h') + exact trivial⟩ + · cases Option.some.inj (nvTypesFold_eq.symm.trans hT) + cases Option.some.inj (nvCtorsFold_eq.symm.trans hC) + rw [nvRecursors_eq] + exact ⟨nvRecWF09, fun env' h' => by + cases Option.some.inj (nvRecEnv09_eq.symm.trans h') + exact ⟨nvRec1WF09, fun env'' h'' => by + cases Option.some.inj (nvRec1Env09_eq.symm.trans h'') + exact trivial⟩⟩ + · cases Option.some.inj (nvTypesFold_eq.symm.trans hT) + cases Option.some.inj (nvCtorsFold_eq.symm.trans hC) + cases Option.some.inj (nvRecsFold_eq.symm.trans hR) + rw [nvRules_eq] + exact ⟨nvRule0WF09, nvRule1WF09, nvRule2WF09, trivial⟩ + +/-! ## NV freshness and stored-metadata translations -/ + +theorem nvTypeFresh09 : pvecCtorMap09.find? ``NVTree = none := by + rw [pvecCtorMap09, pvecNilMapWF09.find?_insert, pvecNilMap09, + pvecTypeMapWF09.find?_insert, pvecTypeMap09, + natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem nvTypeMapWF09 : nvTypeMap09.WF := + pvecCtorMapWF09.insert _ _ nvTypeFresh09 + +theorem nvNodeFresh09 : nvTypeMap09.find? ``NVTree.node = none := by + rw [nvTypeMap09, pvecCtorMapWF09.find?_insert, pvecCtorMap09, + pvecNilMapWF09.find?_insert, pvecNilMap09, + pvecTypeMapWF09.find?_insert, pvecTypeMap09, + natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem nvCtorMapWF09 : nvCtorMap09.WF := + nvTypeMapWF09.insert _ _ nvNodeFresh09 + +theorem nvRecFresh09 : nvCtorMap09.find? ``NVTree.rec = none := by + rw [nvCtorMap09, nvTypeMapWF09.find?_insert, nvTypeMap09, + pvecCtorMapWF09.find?_insert, pvecCtorMap09, + pvecNilMapWF09.find?_insert, pvecNilMap09, + pvecTypeMapWF09.find?_insert, pvecTypeMap09, + natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem nvRecMapWF09 : nvRecMap09.WF := + nvCtorMapWF09.insert _ _ nvRecFresh09 + +theorem nvRec1Fresh09 : + nvRecMap09.find? `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 = none := by + rw [nvRecMap09, nvCtorMapWF09.find?_insert, nvCtorMap09, + nvTypeMapWF09.find?_insert, nvTypeMap09, + pvecCtorMapWF09.find?_insert, pvecCtorMap09, + pvecNilMapWF09.find?_insert, pvecNilMap09, + pvecTypeMapWF09.find?_insert, pvecTypeMap09, + natMap_wf.find?_insert, natMap, + natCtorMap_wf.find?_insert, natCtorMap, + natZeroMap_wf.find?_insert, natZeroMap, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem nvInfoTr09 : TrConstVal .safe pvecCtorEnv09 nvInfo09 nvFamilyV := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr pvecCtorEnv09 nvInfo09.levelParams [] + nvInfo09.type nvFamilyV.toVConstant.type := by + tr_type_expr_tac + exact shape.to_trExprS pvecCtorOrdered09 trivial ⟨_, by type_tac⟩ + +theorem nvNodeTr09 : TrConstVal .safe nvTypeEnv09 nvNodeInfo09 nvNodeV := by + nv_hyps nvTypeEnv09 + have hNV : nvTypeEnv09.constants ``NVTree = some ⟨0, .sort (.succ .zero)⟩ := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr nvTypeEnv09 nvNodeInfo09.levelParams [] + nvNodeInfo09.type nvNodeV.toVConstant.type := by + tr_type_expr_tac + exact shape.to_trExprS nvTypeOrdered09 trivial ⟨_, by type_tac⟩ + +theorem nvRecTr09 : TrConstVal .safe nvCtorEnv09 nvRecInfo09 nvRecVL := by + nv_hyps nvCtorEnv09 + have hNV : nvCtorEnv09.constants ``NVTree = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hNode : nvCtorEnv09.constants ``NVTree.node = some nvNodeV.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr nvCtorEnv09 nvRecInfo09.levelParams [] + nvRecInfo09.type nvRecVL.toVConstant.type := by + tr_type_expr_tac + obtain ⟨u, hty⟩ := nvRecWF09 + exact shape.to_trExprS nvCtorOrdered09 trivial ⟨_, hty⟩ + +theorem nvRec1Tr09 : TrConstVal .safe nvRecEnv09 nvRec1Info09 nvRec1VL := by + nv_hyps nvRecEnv09 + have hNV : nvRecEnv09.constants ``NVTree = some ⟨0, .sort (.succ .zero)⟩ := rfl + have hNode : nvRecEnv09.constants ``NVTree.node = some nvNodeV.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr nvRecEnv09 nvRec1Info09.levelParams [] + nvRec1Info09.type nvRec1VL.toVConstant.type := by + tr_type_expr_tac + obtain ⟨u, hty⟩ := nvRec1WF09 + exact shape.to_trExprS nvRecOrdered09 trivial ⟨_, hty⟩ + +/-! ## NV recursor K metadata, trace, and `TrEnv'` drive -/ + +theorem nvKTarget09 : nvNestedC.generation.kTarget = false := by + native_decide + +theorem nvRecLookup09 : nvMap09.find? ``NVTree.rec = some nvRecInfo09 := by + rw [nvMap09, nvRecMapWF09.find?_insert] + simp [nvRecMap09, nvCtorMapWF09.find?_insert] + +theorem nvRec1Lookup09 : + nvMap09.find? `Ix.Theory.Named.NestedRepresentation.NVTree.rec_1 = + some nvRec1Info09 := by + rw [nvMap09, nvRecMapWF09.find?_insert] + simp + +theorem nvRecK09 : + RecursorMapKMatches nvMap09 nvNestedC.recursors + nvNestedC.generation.kTarget := by + rw [nvRecursors_eq, nvKTarget09] + intro recursor hmem + rcases List.mem_cons.1 hmem with rfl | hmem + · exact ⟨nvRecInfo09, nvRecLookup09, by decide⟩ + rcases List.mem_cons.1 hmem with rfl | hmem + · exact ⟨nvRec1Info09, nvRec1Lookup09, by decide⟩ + · cases hmem + +def nvTrace09 : + AddInductNestedTrace pvecCtorMap09 pvecCtorEnv09 nvSourceV + nvMap09 nvFinalEnv09 where + nested := nvNestedC + nested_wf := nvNestedWF09 + typeMap := nvTypeMap09 + typeEnv := nvTypeEnv09 + ctorMap := nvCtorMap09 + ctorEnv := nvCtorEnv09 + recEnv := nvRec1Env09 + addTypes := .cons + { info := nvInfo09 + kind_eq := trivial + tr := nvInfoTr09 + map_fresh := nvTypeFresh09 + env_add := nvTypeEnv09_eq + map_add := rfl } .nil + addCtors := .cons + { info := nvNodeInfo09 + kind_eq := trivial + tr := nvNodeTr09 + map_fresh := nvNodeFresh09 + env_add := nvCtorEnv09_eq + map_add := rfl } .nil + addRecs := nvRecursors_eq ▸ .cons + { info := nvRecInfo09 + kind_eq := trivial + tr := nvRecTr09 + map_fresh := nvRecFresh09 + env_add := nvRecEnv09_eq + map_add := rfl } (.cons + { info := nvRec1Info09 + kind_eq := trivial + tr := nvRec1Tr09 + map_fresh := nvRec1Fresh09 + env_add := nvRec1Env09_eq + map_add := rfl } .nil) + recK := nvRecK09 + addRules := ⟨by rw [nvRules_eq]; rfl⟩ + +theorem nvAddInductNested09 : + AddInductNested pvecCtorMap09 pvecCtorEnv09 nvSourceV + nvMap09 nvFinalEnv09 := + ⟨nvTrace09⟩ + +/-- The nested-indexed declaration, replayed from real stored metadata over +the staged `PVec` boundary through the nested alignment constructor. -/ +theorem nvTrEnv09 : TrEnv' .safe nvMap09 false nvFinalEnv09 := + .inductNested nvAddInductNested09 pvecTrEnv09 + +theorem nvFinalOrdered09 : nvFinalEnv09.Ordered := + nvTrEnv09.wf.ordered + +#guard nvNestedC.elim.numNested == 1 + + +#guard_named_axioms Ix.Theory.Named.NestedReplayFixtures.nvTrEnv09 [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert, + Ix.Theory.Named.NestedReplayFixtures.nvKTarget09._native.native_decide.ax_1_1, + Ix.Theory.Named.NestedReplayFixtures.nvNestedC._native.native_decide.ax_1, + Ix.Theory.Named.NestedReplayFixtures.nvRecursors_eq._native.native_decide.ax_1_1, + Ix.Theory.Named.NestedReplayFixtures.nvRules_eq._native.native_decide.ax_1_1] + +end Ix.Theory.Named.NestedReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean b/Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean new file mode 100644 index 000000000..765a88594 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean @@ -0,0 +1,718 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Reference.Environment +import Ix.Theory.Named.Inductive +import Ix.Theory.Named.Meta + +open Ix.Theory (VLevel) + +/-! +# Spec-09A: nested-inductive representation audit and decision + +This file is the committed design note and the executable metadata probes +for the nested-inductive representation decision. Every claim below is +pinned by a build-failing probe in this file unless it is explicitly marked +as a forward-looking obligation. This checkpoint changes no acceptance +behavior: the probes only observe the implementation and the existing +Theory analyzers. + +## Audit: how the implementation represents nested inductives + +`Environment.addInductive` (Inductive/Add.lean) runs three phases: + +1. `ElimNestedInductive.run` rewrites the source declaration into a + flattened mutual block: every nested occurrence `I Ds is` whose + parametric arguments `Ds` mention a block family is replaced by + `auxI As is`, where `auxI` is a fresh auxiliary family abstracted over + the block parameters `As`, and one auxiliary family is created for each + family of `I`'s mutual block, with constructor types instantiated at + `Ds` (recursively rewritten). `aux2nested` records `auxI ↦ I Ds`, open + over the block parameters. Auxiliary names are uniquified against the + ambient environment (`mkUniqueName`). +2. `AddInductive.run` checks and generates the flattened block as an + ordinary mutual block, receiving `numNested` (the number of auxiliary + families) as opaque metadata. +3. When `numNested ≠ 0`, a restoration pass rebuilds the final environment + from the *pre-block* environment: source families and constructors are + re-added with every auxiliary constant replaced by its nested + restoration (`Result.restoreNested`), each auxiliary family's recursor + is re-added under the name `(mkRecName mainName).appendIndexAfter i` + with restored type and rules, and finally every `aux2nested` value + `I Ds` is type-checked (the lean4#14577 escape-hatch check, regression + tested in `Tests/NestedInductive.lean`). The auxiliary families, + constructors, and recursor names never enter the final environment. + +The stored metadata therefore has this shape (probes P1, P2): + +- The source `inductInfo` keeps `all` = the source family names only and + carries `numNested` = the number of auxiliary families; stored + constructor types are in restored form (they mention `I Ds`, e.g. + `List (RoseTree α)`). +- The recursor inventory is one recursor per source family plus one per + auxiliary family, all with `all` = source names, and with + `numMotives`/`numMinors` counting the *flattened* block's families and + minors. Auxiliary recursors have rules keyed by constructors of the + previously declared nested inductive (`List.nil`, `List.cons`, ...) with + `nfields` counting the instantiated auxiliary constructor's fields, and + every rule RHS references the restored recursor constants mutually. +- No `_nested.*` constant, and no auxiliary recursor under its original + name, survives into the final environment. + +## Decision: additive artifact type; `VInductDecl` unchanged + +The stored Theory payload for a nested declaration must be the *source* +`VInductDecl` (restored form), because that is what the implementation +stores and what Verify alignment must replay. Storing the flattened block +is unrepresentable: the final `ConstMap` contains neither the auxiliary +families nor their constructors (probe P2), and the stored constructor +types differ from the flattened ones (probe P1). `VInductDecl` needs no +new field: `numNested` is implementation metadata recoverable as the +number of auxiliary specifications, and parity fixtures pin it per row +exactly as they already pin `numNested == 0` for non-nested rows. + +Nested support is an additive checked-block artifact (built in Spec-09B/C), +coupling: + +1. the flattened block as an ordinary `VInductDecl` — probe P4 shows both + target fixtures' flattened blocks are already accepted by the existing + `identityBlockGeneration?` machinery, so flattening reuses the complete + Spec-08 block analyzer and generator unchanged; +2. one auxiliary specification per auxiliary family, in flattened family + order: the auxiliary name, the nested value `I Ds` open over the block + parameters (the Theory analog of `aux2nested`), and the restored + recursor name — plus executable coherence checks tying the flattened + block to the source declaration and to the environment's metadata for + `I` at `Ds`; +3. the restoration substitution σ, a structural constant substitution on + `VExpr` (probe P5, `restoreV09A`): on an application spine headed by an + auxiliary constant, the first `nparams` spine arguments are consumed + and replaced by the instantiated value `I Ds`; auxiliary constructor + constants are renamed by prefix into `I`'s constructors, applied to the + instantiated value's own arguments; auxiliary recursor constants are + renamed (checked *before* the constructor-prefix case, exactly like + `restoreNested`'s `auxRec` map); levels come from the recorded value, + not the auxiliary constant. + +σ has one level-world subtlety (probe P5): specification values live in +declaration level-world, while recursor types and rules live in recursor +level-world, so σ over generation artifacts splices +`value.instL (VLevel.params' uvars elimOffset)`. Constructor types are +restored with the unshifted value. With that splice, σ over the flattened +block's existing `BlockGenerationChecked` artifacts reproduces the stored +kernel metadata *exactly* — every recursor type and every rule RHS of all +three probe fixtures — and no auxiliary constant survives the image. +Probe P2 additionally shows the port's full nested path reproduces Lean's +stored metadata field-for-field, and that the final metadata is +independent of auxiliary-name collisions (the uniquified names are erased +by σ), so Theory may choose canonical auxiliary names as artifact data. + +Rejected alternatives: + +- *Flattened block as stored payload*: contradicts the stored metadata + (P1/P2); Verify alignment would have to invent constants the + implementation never stores. +- *Changing `VInductDecl` fields*: unnecessary — the probes demonstrate + the additive artifact expresses real rose-tree, nested-indexed, and + constant-universe metadata; a payload change would ripple through every + exported Theory API without demonstrated need. +- *A Prop-only pre-flattening relation without an artifact*: the + specifications and σ are data consumed by generation and replay; a + relation alone would force Verify to re-synthesize them. The artifact's + executable coherence checks subsume the relation. + +## Obligations recorded for Spec-09B/09C (not claimed here) + +- 09B: Theory-side flattening and auxiliary-specification validation — + positivity through the existing block analyzer on the flattened block; + executable instantiation checks of auxiliary family/constructor types + against `I`'s metadata at `Ds`; nearest rejection differentials + (ill-typed `Ds` — the lean4#14577 class — wrong specification order, + non-matching instantiation). +- 09C: σ as a total Theory function. The spine rule needs a simultaneous + `instantiateRev`-style multi-substitution for `nparams > 1`: iterating + single `VExpr.inst` is wrong once parameter arguments mention bvars. + Generation, preservation (typing transport along σ: auxiliary constants + behave as definitions `auxI := λ As, I Ds`, so staged flattened-block WF + transports to restored WF given environment lookup facts for `I`'s + families and constructors), insertion order, and replay of real + `Inductive.Add.run` output. +- The kernel's trailing `checkType (I Ds)` becomes a WF premise of the + auxiliary specification, never a trusted escape hatch. +-/ + +namespace Ix.Theory.Named.NestedRepresentation + +open Lean + +/-! ## Probe fixtures + +`RoseTree` is the universe-polymorphic rose tree through `List`; `NVTree` +nests through the locally declared indexed family `PVec` (indices spelled +with `Nat.zero`/`Nat.succ` to keep the probe dependency maps free of +notation instances); `CURose` nests `List` at a constant universe, so its +auxiliary constant carries no block level while the restored `List` +carries level `1` — the level-instantiation case σ must represent. -/ + +inductive RoseTree (α : Type u) : Type u where + | node : α → List (RoseTree α) → RoseTree α + +inductive PVec (α : Type) : Nat → Type where + | nil : PVec α Nat.zero + | cons : α → {n : Nat} → PVec α n → PVec α (Nat.succ n) + +inductive NVTree : Type where + | node : (n : Nat) → PVec NVTree n → NVTree + +inductive CURose : Type 1 where + | node : List CURose → CURose + +/-! ## Quoted stored metadata + +Local pin records keep this file independent of the replay fixture +inventory; a change in Lean's emitted metadata is a compile failure. -/ + +structure InductPins where + name : Name + lparams : List Name + numParams : Nat + numIndices : Nat + all : List Name + ctors : List Name + numNested : Nat + isRec : Bool + isReflexive : Bool + isUnsafe : Bool + deriving ToExpr, BEq + +structure CtorPins where + name : Name + lparams : List Name + induct : Name + cidx : Nat + numParams : Nat + numFields : Nat + deriving ToExpr, BEq + +structure RecPins where + name : Name + lparams : List Name + all : List Name + numParams : Nat + numIndices : Nat + numMotives : Nat + numMinors : Nat + k : Bool + rules : List (Name × Nat) + deriving ToExpr, BEq + +open Elab Term in +elab "nestedInductPins09A%" n:ident : term => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .inductInfo i ← getConstInfo name | throwError "expected inductive {name}" + return toExpr (InductPins.mk i.name i.levelParams i.numParams i.numIndices + i.all i.ctors i.numNested i.isRec i.isReflexive i.isUnsafe) + +open Elab Term in +elab "nestedCtorPins09A%" n:ident : term => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .ctorInfo i ← getConstInfo name | throwError "expected constructor {name}" + return toExpr (CtorPins.mk i.name i.levelParams i.induct i.cidx + i.numParams i.numFields) + +open Elab Term in +elab "nestedRecPins09A%" n:ident : term => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let .recInfo i ← getConstInfo name | throwError "expected recursor {name}" + return toExpr (RecPins.mk i.name i.levelParams i.all i.numParams i.numIndices + i.numMotives i.numMinors i.k (i.rules.map fun r => (r.ctor, r.nfields))) + +-- Quote a stored `ConstantInfo.type` in that record's own universe order. +open Elab Term in +elab "nestedConstVType09A%" n:ident : term => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let info ← getConstInfo name + let type ← Ix.Theory.Named.Meta.expandExpr info.type + return toExpr (← Ix.Theory.Named.Meta.ofExpr info.levelParams {} type) + +/-! ## P1: stored-metadata pins + +The source family keeps `all` = source names and counts its auxiliary +families in `numNested`; constructor types are restored; the recursor +inventory reveals the flattened block through `numMotives`/`numMinors` and +through auxiliary recursors whose rules are keyed by the constructors of a +previously declared inductive. -/ + +def roseAux : Name := (`_nested ++ ``List).appendIndexAfter 1 +def nvAux : Name := (`_nested ++ ``PVec).appendIndexAfter 1 + +def roseInductPins : InductPins := nestedInductPins09A% RoseTree +def roseNodePins : CtorPins := nestedCtorPins09A% RoseTree.node +def roseRecPins : RecPins := nestedRecPins09A% RoseTree.rec +def roseRec1Pins : RecPins := nestedRecPins09A% RoseTree.rec_1 + +#guard roseInductPins.numNested == 1 +#guard roseInductPins.all == [``RoseTree] +#guard roseInductPins.ctors == [``RoseTree.node] +#guard roseInductPins.lparams == [`u] && roseInductPins.numParams == 1 +#guard roseInductPins.isRec && !roseInductPins.isReflexive && !roseInductPins.isUnsafe +#guard roseNodePins == + { name := ``RoseTree.node, lparams := [`u], induct := ``RoseTree, cidx := 0, + numParams := 1, numFields := 2 } +#guard roseRecPins == + { name := ``RoseTree.rec, lparams := [`u_1, `u], all := [``RoseTree], numParams := 1, + numIndices := 0, numMotives := 2, numMinors := 3, k := false, + rules := [(``RoseTree.node, 2)] } +#guard roseRec1Pins == + { name := (mkRecName ``RoseTree).appendIndexAfter 1, lparams := [`u_1, `u], + all := [``RoseTree], numParams := 1, numIndices := 0, numMotives := 2, numMinors := 3, + k := false, rules := [(``List.nil, 0), (``List.cons, 2)] } + +/-- The stored constructor type is the restored form: it mentions +`List (RoseTree α)`, not an auxiliary constant. -/ +def roseNodeStoredType : VExpr := nestedConstVType09A% RoseTree.node + +#guard roseNodeStoredType == + .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const ``List [.param 0]) (.app (.const ``RoseTree [.param 0]) (.bvar 1))) + (.app (.const ``RoseTree [.param 0]) (.bvar 2)))) + +def nvInductPins : InductPins := nestedInductPins09A% NVTree +def nvNodePins : CtorPins := nestedCtorPins09A% NVTree.node +def nvRecPins : RecPins := nestedRecPins09A% NVTree.rec +def nvRec1Pins : RecPins := nestedRecPins09A% NVTree.rec_1 + +#guard nvInductPins.numNested == 1 +#guard nvInductPins.all == [``NVTree] && nvInductPins.ctors == [``NVTree.node] +#guard nvNodePins == + { name := ``NVTree.node, lparams := [], induct := ``NVTree, cidx := 0, + numParams := 0, numFields := 2 } +#guard nvRecPins == + { name := ``NVTree.rec, lparams := [`u], all := [``NVTree], numParams := 0, + numIndices := 0, numMotives := 2, numMinors := 3, k := false, + rules := [(``NVTree.node, 2)] } +-- The auxiliary recursor keeps the auxiliary family's index and its rules +-- count the instantiated constructor's fields (`PVec.cons` retains its +-- implicit index field: 3 fields, not 2). +#guard nvRec1Pins == + { name := (mkRecName ``NVTree).appendIndexAfter 1, lparams := [`u], all := [``NVTree], + numParams := 0, numIndices := 1, numMotives := 2, numMinors := 3, k := false, + rules := [(``PVec.nil, 0), (``PVec.cons, 3)] } + +def nvNodeStoredType : VExpr := nestedConstVType09A% NVTree.node + +#guard nvNodeStoredType == + .forallE (.const ``Nat []) + (.forallE (.app (.app (.const ``PVec []) (.const ``NVTree [])) (.bvar 0)) + (.const ``NVTree [])) + +def cuInductPins : InductPins := nestedInductPins09A% CURose +def cuRecPins : RecPins := nestedRecPins09A% CURose.rec +def cuRec1Pins : RecPins := nestedRecPins09A% CURose.rec_1 + +#guard cuInductPins.numNested == 1 && cuInductPins.all == [``CURose] +#guard cuRecPins.rules == [(``CURose.node, 1)] && cuRecPins.numMotives == 2 +#guard cuRec1Pins.rules == [(``List.nil, 0), (``List.cons, 2)] + +/-- The restored constructor type instantiates `List` at the constant level +`1` even though the declaration has no level parameters. -/ +def cuNodeStoredType : VExpr := nestedConstVType09A% CURose.node + +#guard cuNodeStoredType == + .forallE (.app (.const ``List [.succ .zero]) (.const ``CURose [])) + (.const ``CURose []) + +/-! ## Shared probe plumbing -/ + +def sourceType09A (env : Environment) (n : Name) : InductiveType := Id.run do + let some (.inductInfo info) := env.find? n | panic! "expected inductive" + let ctors := info.ctors.map fun c => Id.run do + let some (.ctorInfo ci) := env.find? c | panic! "expected constructor" + return { name := c, type := ci.type : Constructor } + return { name := n, type := info.type, ctors } + +def depMap09A (env : Environment) (ns : List Name) : ConstMap := + ns.foldl (fun m n => m.insert n (env.find? n).get!) {} + +open ElimNestedInductive in +/-- Run the port's flattening phase, returning the flattened block and the +`aux2nested` values abstracted over the block parameters. -/ +def runElim09A (env : Kernel.Environment) (lparams : List Name) (nparams : Nat) + (types : List InductiveType) : + Except Kernel.Exception (List InductiveType × List (Name × Expr)) := do + let res : ElimNestedInductive.Result ← ElimNestedInductive.run 1000 nparams types env + |>.run' { lvls := lparams.map .param, newTypes := types.toArray } + return (res.types, res.aux2nested.toList.map fun (n, e) => (n, e.abstract res.params)) + +/-- Field-for-field stored/ported agreement for the constant kinds a nested +declaration emits. -/ +def sameConst09A (a b : ConstantInfo) : Bool := + a.name == b.name && a.levelParams == b.levelParams && a.type == b.type && + match a, b with + | .recInfo ra, .recInfo rb => + ra.all == rb.all && ra.numParams == rb.numParams && + ra.numIndices == rb.numIndices && ra.numMotives == rb.numMotives && + ra.numMinors == rb.numMinors && ra.k == rb.k && + ra.isUnsafe == rb.isUnsafe && + ra.rules.map (fun r => (r.ctor, r.nfields, r.rhs)) == + rb.rules.map (fun r => (r.ctor, r.nfields, r.rhs)) + | .inductInfo ia, .inductInfo ib => + ia.all == ib.all && ia.numParams == ib.numParams && + ia.numIndices == ib.numIndices && ia.ctors == ib.ctors && + ia.numNested == ib.numNested && ia.isRec == ib.isRec && + ia.isReflexive == ib.isReflexive && ia.isUnsafe == ib.isUnsafe + | .ctorInfo ca, .ctorInfo cb => + ca.induct == cb.induct && ca.cidx == cb.cidx && + ca.numParams == cb.numParams && ca.numFields == cb.numFields && + ca.isUnsafe == cb.isUnsafe + | _, _ => false + +def roseDeps : List Name := [``List, ``List.nil, ``List.cons] +def nvDeps : List Name := + [``Nat, ``Nat.zero, ``Nat.succ, ``PVec, ``PVec.nil, ``PVec.cons] + +def roseRestored : List Name := + [``RoseTree, ``RoseTree.node, mkRecName ``RoseTree, + (mkRecName ``RoseTree).appendIndexAfter 1] +def nvRestored : List Name := + [``NVTree, ``NVTree.node, mkRecName ``NVTree, + (mkRecName ``NVTree).appendIndexAfter 1] +def cuRestored : List Name := + [``CURose, ``CURose.node, mkRecName ``CURose, + (mkRecName ``CURose).appendIndexAfter 1] + +/-! ## P2: the port's nested path reproduces the stored metadata + +`Environment.addInductive`, run on a dependency-only kernel environment, +re-creates exactly the constants Lean stores — including every restored +type and rule RHS — and no auxiliary constant. The final output is +independent of auxiliary-name collisions: pre-seeding `_nested.List_1` +only shifts the uniquified internal names, which restoration erases. -/ + +open Elab in +run_meta do + let env ← getEnv + let checkPort (label : String) (main : Name) (lparams : List Name) (nparams : Nat) + (deps auxNames restored : List Name) (extra : ConstMap → ConstMap) : + MetaM Unit := do + let src := sourceType09A env main + let kenv := Kernel.Environment.ofConstants (`_spec09A ++ main) (extra (depMap09A env deps)) + match Ix.Theory.Named.Environment.addInductive kenv lparams nparams [src] false false with + | .error _ => throwError "{label}: port addInductive failed" + | .ok env' => + for n in restored do + let some stored := env.find? n | throwError "{label}: {n} not stored" + let some ported := env'.find? n | throwError "{label}: {n} missing from port output" + unless sameConst09A stored ported do + throwError "{label}: stored/ported metadata differ at {n}" + for n in auxNames do + unless (env'.find? n).isNone do + throwError "{label}: auxiliary constant {n} leaked into the final environment" + unless (env.find? n).isNone do + throwError "{label}: auxiliary constant {n} present in the ambient environment" + checkPort "rose" ``RoseTree [`u] 1 roseDeps + [roseAux, roseAux ++ `nil, roseAux ++ `cons, mkRecName roseAux, + (mkRecName ``RoseTree).appendIndexAfter 2] roseRestored id + checkPort "nv" ``NVTree [] 0 nvDeps + [nvAux, nvAux ++ `nil, nvAux ++ `cons, mkRecName nvAux, + (mkRecName ``NVTree).appendIndexAfter 2] nvRestored id + checkPort "cu" ``CURose [] 0 roseDeps + [roseAux, mkRecName roseAux] cuRestored id + -- auxiliary-name-collision independence + checkPort "rose-collision" ``RoseTree [`u] 1 roseDeps + [(`_nested ++ ``List).appendIndexAfter 2] roseRestored + (fun m => m.insert roseAux (env.find? ``Nat).get!) + +/-! ## P3: exact flattening pins + +The flattened blocks, translated to binder-erased `VExpr` form. These are +the descriptors the Spec-09B transformation must produce. -/ + +def roseFlatFamilies : List (Name × VExpr) := + [(``RoseTree, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))), + (roseAux, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))))] + +def roseFlatCtors : List (Name × VExpr) := + [(``RoseTree.node, + .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const roseAux [.param 0]) (.bvar 1)) + (.app (.const ``RoseTree [.param 0]) (.bvar 2))))), + (roseAux ++ `nil, + .forallE (.sort (.succ (.param 0))) (.app (.const roseAux [.param 0]) (.bvar 0))), + (roseAux ++ `cons, + .forallE (.sort (.succ (.param 0))) + (.forallE (.app (.const ``RoseTree [.param 0]) (.bvar 0)) + (.forallE (.app (.const roseAux [.param 0]) (.bvar 1)) + (.app (.const roseAux [.param 0]) (.bvar 2)))))] + +/-- `aux2nested` for the rose tree: `List (RoseTree α)`, open over `α`. -/ +def roseAuxValue : VExpr := + .app (.const ``List [.param 0]) (.app (.const ``RoseTree [.param 0]) (.bvar 0)) + +def nvFlatFamilies : List (Name × VExpr) := + [(``NVTree, .sort (.succ .zero)), + (nvAux, .forallE (.const ``Nat []) (.sort (.succ .zero)))] + +def nvFlatCtors : List (Name × VExpr) := + [(``NVTree.node, + .forallE (.const ``Nat []) + (.forallE (.app (.const nvAux []) (.bvar 0)) (.const ``NVTree []))), + (nvAux ++ `nil, .app (.const nvAux []) (.const ``Nat.zero [])), + (nvAux ++ `cons, + .forallE (.const ``NVTree []) + (.forallE (.const ``Nat []) + (.forallE (.app (.const nvAux []) (.bvar 0)) + (.app (.const nvAux []) (.app (.const ``Nat.succ []) (.bvar 1))))))] + +/-- `aux2nested` for `NVTree`: the closed partial application `PVec NVTree` +(the index argument stays behind on each occurrence). -/ +def nvAuxValue : VExpr := .app (.const ``PVec []) (.const ``NVTree []) + +def cuFlatFamilies : List (Name × VExpr) := + [(``CURose, .sort (.succ (.succ .zero))), + (roseAux, .sort (.succ (.succ .zero)))] + +def cuFlatCtors : List (Name × VExpr) := + [(``CURose.node, .forallE (.const roseAux []) (.const ``CURose [])), + (roseAux ++ `nil, .const roseAux []), + (roseAux ++ `cons, + .forallE (.const ``CURose []) (.forallE (.const roseAux []) (.const roseAux [])))] + +/-- `aux2nested` for `CURose`: the block-level-free auxiliary constant +restores to `List` at the constant level `1`. -/ +def cuAuxValue : VExpr := .app (.const ``List [.succ .zero]) (.const ``CURose []) + +open Elab in +/-- Translate one flattened block and compare it with its pinned shape. -/ +def checkFlat09A (label : String) (main : Name) (lparams : List Name) (nparams : Nat) + (deps : List Name) (families ctors : List (Name × VExpr)) + (auxValues : List (Name × VExpr)) : MetaM (List VInductiveType) := do + let env ← getEnv + let src := sourceType09A env main + let kenv := Kernel.Environment.ofConstants (`_spec09AFlat ++ main) (depMap09A env deps) + let .ok (flatTypes, aux) := runElim09A kenv lparams nparams [src] + | throwError "{label}: flattening failed" + let uvars := lparams.length + let mut vtypes : List VInductiveType := [] + let mut actualFamilies : List (Name × VExpr) := [] + let mut actualCtors : List (Name × VExpr) := [] + for t in flatTypes do + let vty ← Ix.Theory.Named.Meta.ofExpr lparams {} t.type + actualFamilies := actualFamilies ++ [(t.name, vty)] + let mut vctors : List VConstVal := [] + for c in t.ctors do + let vc ← Ix.Theory.Named.Meta.ofExpr lparams {} c.type + actualCtors := actualCtors ++ [(c.name, vc)] + vctors := vctors ++ [{ name := c.name, uvars, type := vc }] + vtypes := vtypes ++ [{ name := t.name, uvars, type := vty, ctors := vctors }] + unless actualFamilies == families do + throwError "{label}: flattened families differ from the pinned shape" + unless actualCtors == ctors do + throwError "{label}: flattened constructors differ from the pinned shape" + let mut actualValues : List (Name × VExpr) := [] + for (n, e) in aux do + actualValues := actualValues ++ [(n, ← Ix.Theory.Named.Meta.ofExpr lparams {} e)] + unless actualValues == auxValues do + throwError "{label}: aux2nested values differ from the pinned shape" + return vtypes + +/-! ## P4: Theory viability, with acceptance behavior unchanged + +The flattened blocks are already inside the supported arbitrary-block +class, while the source declarations remain rejected by every current +analyzer and by the public transaction. -/ + +open Elab in +run_meta do + let checkViability (label : String) (main : Name) (lparams : List Name) + (nparams : Nat) (deps : List Name) (families ctors : List (Name × VExpr)) + (auxValues : List (Name × VExpr)) : MetaM Unit := do + let vtypes ← checkFlat09A label main lparams nparams deps families ctors auxValues + let uvars := lparams.length + let flatDecl : VInductDecl := { uvars, nparams, types := vtypes } + unless flatDecl.stage3 do + throwError "{label}: flattened block rejected by the block analyzer" + unless flatDecl.identityBlockGeneration?.isSome do + throwError "{label}: flattened block is not generation-ready" + let env ← getEnv + let src := sourceType09A env main + let vsrcTy ← Ix.Theory.Named.Meta.ofExpr lparams {} src.type + let mut vctors : List VConstVal := [] + for c in src.ctors do + vctors := vctors ++ [{ name := c.name, uvars, type := ← Ix.Theory.Named.Meta.ofExpr lparams {} c.type }] + let srcTy : VInductiveType := { name := main, uvars, type := vsrcTy, ctors := vctors } + let srcDecl : VInductDecl := { uvars, nparams, types := [srcTy] } + if srcDecl.stage3 then + throwError "{label}: source declaration unexpectedly accepted by stage3" + if srcDecl.checked?.isSome then + throwError "{label}: source declaration unexpectedly accepted by checked?" + if (VEnv.empty.addInduct srcDecl).isSome then + throwError "{label}: source declaration unexpectedly accepted by addInduct" + checkViability "rose" ``RoseTree [`u] 1 roseDeps + roseFlatFamilies roseFlatCtors [(roseAux, roseAuxValue)] + checkViability "nv" ``NVTree [] 0 nvDeps + nvFlatFamilies nvFlatCtors [(nvAux, nvAuxValue)] + checkViability "cu" ``CURose [] 0 roseDeps + cuFlatFamilies cuFlatCtors [(roseAux, cuAuxValue)] + +/-! ## P5: the restoration substitution σ + +`restoreV09A` mirrors `ElimNestedInductive.Result.restoreNested` on +`VExpr`. It is probe-local: the Spec-09C artifact path must define the +total Theory version (with a simultaneous parameter substitution once +`nparams > 1` is in scope; the probe fixtures have `nparams ≤ 1`, where +iterated `VExpr.inst` coincides with it). -/ + +structure AuxSpec09A where + aux : Name + np : Nat + value : VExpr + recName : Name + +def instParams09A (value : VExpr) : List VExpr → VExpr + | [] => value + | [a] => value.inst a + | _ => panic! "the probe fixtures have nparams ≤ 1" + +def findCtorSpec09A (specs : List AuxSpec09A) (c : Name) : Option (AuxSpec09A × Name) := + specs.findSome? fun spec => + if spec.aux.isPrefixOf c && c != spec.aux then + some (spec, c.replacePrefix spec.aux .anonymous) + else none + +/-- σ. The recursor-rename case is checked before the constructor-prefix +case, exactly like `restoreNested`'s `auxRec` map: an auxiliary recursor +name is prefixed by its auxiliary family name and would otherwise be +mangled by the constructor branch. -/ +partial def restoreV09A (specs : List AuxSpec09A) (recMap : List (Name × Name)) : + VExpr → VExpr + | .bvar i => .bvar i + | .sort l => .sort l + | .lam ty body => .lam (restoreV09A specs recMap ty) (restoreV09A specs recMap body) + | .forallE ty body => + .forallE (restoreV09A specs recMap ty) (restoreV09A specs recMap body) + | e@(.app ..) => restoreSpine (VExpr.appHead e) (e.appArgs []) + | e@(.const ..) => restoreSpine e [] + where + restoreSpine (head : VExpr) (args : List VExpr) : VExpr := + let args' := args.map (restoreV09A specs recMap) + match head with + | .const c ls => + match recMap.find? (·.1 == c) with + | some (_, newName) => (VExpr.const newName ls).appN args' + | none => + match specs.find? (·.aux == c) with + | some spec => + (instParams09A spec.value (args'.take spec.np)).appN (args'.drop spec.np) + | none => + match findCtorSpec09A specs c with + | some (spec, suffix) => + let value := instParams09A spec.value (args'.take spec.np) + match VExpr.appHead value with + | .const iname ils => + (VExpr.const (iname ++ suffix) ils).appN + (value.appArgs [] ++ args'.drop spec.np) + | _ => panic! "auxiliary value head is not a constant" + | none => (VExpr.const c ls).appN args' + | h => (restoreV09A specs recMap h).appN args' + +open Elab in +/-- σ over the flattened block's existing generation artifacts reproduces +the stored kernel metadata exactly: recursor names and types, and every +rule RHS in the globally flattened order, with no auxiliary constant in +the image. Constructor types are restored with the declaration-world +value; recursor artifacts use the value spliced by the elimination +offset. -/ +def checkRestore09A (label : String) (main : Name) (lparams : List Name) + (nparams : Nat) (deps : List Name) : MetaM Unit := do + let env ← getEnv + let src := sourceType09A env main + let kenv := Kernel.Environment.ofConstants (`_spec09ARestore ++ main) (depMap09A env deps) + let .ok (flatTypes, aux) := runElim09A kenv lparams nparams [src] + | throwError "{label}: flattening failed" + let uvars := lparams.length + let mut vtypes : List VInductiveType := [] + for t in flatTypes do + let vty ← Ix.Theory.Named.Meta.ofExpr lparams {} t.type + let mut vctors : List VConstVal := [] + for c in t.ctors do + vctors := vctors ++ [{ name := c.name, uvars, type := ← Ix.Theory.Named.Meta.ofExpr lparams {} c.type }] + vtypes := vtypes ++ [{ name := t.name, uvars, type := vty, ctors := vctors }] + let flatDecl : VInductDecl := { uvars, nparams, types := vtypes } + let some gen := flatDecl.identityBlockGeneration? + | throwError "{label}: flattened block is not generation-ready" + let elimOffset := gen.recUvars - uvars + let mut declSpecs : List AuxSpec09A := [] + let mut recSpecs : List AuxSpec09A := [] + let mut recMap : List (Name × Name) := [] + let mut i := 1 + for t in flatTypes.drop 1 do + let some (_, value) := aux.find? (·.1 == t.name) + | throwError "{label}: no aux2nested value for {t.name}" + let v ← Ix.Theory.Named.Meta.ofExpr lparams {} value + let recName := (mkRecName main).appendIndexAfter i + let recValue := v.instL (VLevel.params' uvars elimOffset) + declSpecs := declSpecs ++ [{ aux := t.name, np := nparams, value := v, recName }] + recSpecs := recSpecs ++ [{ aux := t.name, np := nparams, value := recValue, recName }] + recMap := recMap ++ [(mkRecName t.name, recName)] + i := i + 1 + let auxConsts := declSpecs.map (·.aux) ++ recMap.map (·.1) ++ + (flatTypes.drop 1).flatMap (fun t => t.ctors.map (·.name)) + -- declaration-world σ: restored source constructors + for (t, vt) in flatTypes.zip vtypes do + if t.name == main then + for c in vt.ctors do + let some stored := env.find? c.name | throwError "{label}: {c.name} not stored" + let storedType ← Ix.Theory.Named.Meta.ofExpr stored.levelParams {} + (← Ix.Theory.Named.Meta.expandExpr stored.type) + unless restoreV09A declSpecs recMap c.type == storedType do + throwError "{label}: σ(flattened {c.name}) differs from the stored type" + -- recursor-world σ: recursor types, names, and every rule RHS + let expectedNames := [mkRecName main] ++ recSpecs.map (·.recName) + for (r, expected) in gen.recursors.zip expectedNames do + let restoredName := match recMap.find? (·.1 == r.name) with + | some (_, n) => n + | none => r.name + unless restoredName == expected do + throwError "{label}: restored recursor name {restoredName}, expected {expected}" + let some (.recInfo stored) := env.find? expected + | throwError "{label}: stored recursor {expected} missing" + let storedType ← Ix.Theory.Named.Meta.ofExpr stored.levelParams {} + (← Ix.Theory.Named.Meta.expandExpr stored.type) + let restored := restoreV09A recSpecs recMap r.type + unless restored == storedType do + throwError "{label}: σ(recursor type) differs from stored for {expected}" + unless !VExpr.hasAnyConst auxConsts restored do + throwError "{label}: auxiliary constant survives σ in the type of {expected}" + let mut storedRules : List (Name × Expr) := [] + for n in expectedNames do + let some (.recInfo stored) := env.find? n + | throwError "{label}: stored recursor {n} missing" + for rule in stored.rules do + storedRules := storedRules ++ [(rule.ctor, rule.rhs)] + let genRules := gen.generatedRules + unless storedRules.length == genRules.length do + throwError "{label}: {genRules.length} generated rules, {storedRules.length} stored" + let some (.recInfo mainRec) := env.find? (mkRecName main) + | throwError "{label}: stored main recursor missing" + for (df, (ctor, storedRhs)) in genRules.zip storedRules do + let storedRhs ← Ix.Theory.Named.Meta.ofExpr mainRec.levelParams {} + (← Ix.Theory.Named.Meta.expandExpr storedRhs) + let restoredRhs := restoreV09A recSpecs recMap df.rhs + unless restoredRhs == storedRhs do + throwError "{label}: σ(rule rhs) differs from stored for {ctor}" + unless !VExpr.hasAnyConst auxConsts restoredRhs && + !VExpr.hasAnyConst auxConsts (restoreV09A recSpecs recMap df.lhs) do + throwError "{label}: auxiliary constant survives σ in the rule for {ctor}" + +run_meta do + checkRestore09A "rose" ``RoseTree [`u] 1 roseDeps + checkRestore09A "nv" ``NVTree [] 0 nvDeps + checkRestore09A "cu" ``CURose [] 0 roseDeps + +end Ix.Theory.Named.NestedRepresentation diff --git a/Ix/Theory/Named/Verify/Environment/NestedTransformation.lean b/Ix/Theory/Named/Verify/Environment/NestedTransformation.lean new file mode 100644 index 000000000..d32c26af8 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/NestedTransformation.lean @@ -0,0 +1,389 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.NestedRepresentation +import Ix.Theory.Named.NestedInductiveFixtures + +/-! +# Nested flattening differential (Spec-09B) + +Ties the Theory transformation `nestedElimination?` to the implementation: + +- the hand-written `List` target block in the Theory fixtures is exactly + Lean's stored metadata; +- on the real rose-tree, nested-indexed, and constant-universe fixtures, + the Theory flattening reproduces the port's `ElimNestedInductive` output + family for family, constructor for constructor, and specification for + `aux2nested` binding — including the canonical auxiliary names — and its + auxiliary count equals the stored `numNested`; +- Theory acceptance (`nestedStage3`) agrees with kernel acceptance on the + positives and on the nearest rejections: a parametric argument touching + a constructor-local binder (rejected by flattening itself, with the + kernel's exact error), an off-spine parametric application (rejected by + the unchanged block analyzer where the kernel fails constructor + checking), an in-block collision with the canonical auxiliary name + (rejected by `blockNamesOK` where the kernel's `checkName` rejects the + duplicate insertion), and a missing target declaration. +-/ + +namespace Ix.Theory.Named.NestedTransformation + +open Lean +open Ix.Theory.Named.NestedRepresentation +open Ix.Theory.Named.NestedInductiveFixtures +open VInductDecl + +/-! ## The hand-written `List` target is the stored metadata -/ + +def listNilStoredType : VExpr := nestedConstVType09A% List.nil +def listConsStoredType : VExpr := nestedConstVType09A% List.cons +def listStoredType : VExpr := nestedConstVType09A% List + +#guard listTarget.families.map (·.name) == [``List] +#guard listTarget.nparams == 1 +#guard listTarget.families.map (·.type) == [listStoredType] +#guard listTarget.families.map (·.ctors.map fun c => (c.name, c.uvars, c.type)) == + [[(``List.nil, 1, listNilStoredType), (``List.cons, 1, listConsStoredType)]] + +/-! ## Real-metadata target blocks -/ + +def pvecStoredTarget : NestedTargetBlock where + nparams := 1 + families := + [{ name := ``PVec + uvars := 0 + type := nestedConstVType09A% PVec + ctors := + [⟨⟨0, nestedConstVType09A% PVec.nil⟩, ``PVec.nil⟩, + ⟨⟨0, nestedConstVType09A% PVec.cons⟩, ``PVec.cons⟩] }] + +/-! ## Shared translation plumbing -/ + +open Elab in +/-- Translate a list of kernel `InductiveType`s into a `VInductDecl`. -/ +def toVInductDecl09B (lparams : List Name) (nparams : Nat) + (types : List InductiveType) : MetaM VInductDecl := do + let uvars := lparams.length + let mut vtypes : List VInductiveType := [] + for t in types do + let vty ← Ix.Theory.Named.Meta.ofExpr lparams {} t.type + let mut vctors : List VConstVal := [] + for c in t.ctors do + vctors := vctors ++ [⟨⟨uvars, ← Ix.Theory.Named.Meta.ofExpr lparams {} c.type⟩, c.name⟩] + vtypes := vtypes ++ [{ name := t.name, uvars, type := vty, ctors := vctors }] + return { uvars, nparams, types := vtypes } + +open Elab in +/-- Check that the Theory flattening of one real source declaration equals +the port's flattening, that its specifications are the translated +`aux2nested` bindings, and that its auxiliary count is the stored +`numNested`. -/ +def checkFlattenParity (label : String) (main : Name) (lparams : List Name) + (nparams : Nat) (deps : List Name) (targets : List NestedTargetBlock) : + MetaM Unit := do + let env ← getEnv + let src := sourceType09A env main + let kenv := Kernel.Environment.ofConstants (`_spec09B ++ main) (depMap09A env deps) + let .ok (flatTypes, aux) := runElim09A kenv lparams nparams [src] + | throwError "{label}: port flattening failed" + let sourceV ← toVInductDecl09B lparams nparams [src] + let portFlatV ← toVInductDecl09B lparams nparams flatTypes + let some elim := nestedElimination? targets sourceV + | throwError "{label}: Theory flattening failed" + unless elim.flat == portFlatV do + throwError "{label}: Theory flattened block differs from the port's" + unless elim.specs.length == aux.length do + throwError "{label}: {elim.specs.length} specs vs {aux.length} aux2nested bindings" + for spec in elim.specs do + let some (_, value) := aux.find? (·.1 == spec.aux) + | throwError "{label}: no aux2nested binding for {spec.aux}" + let valueV ← Ix.Theory.Named.Meta.ofExpr lparams {} value + unless spec.value == valueV do + throwError "{label}: spec value for {spec.aux} differs from aux2nested" + let .const target ls := VExpr.appHead valueV + | throwError "{label}: aux2nested head is not a constant" + unless spec.target == target && spec.levels == ls && + spec.values == valueV.appArgs [] do + throwError "{label}: spec decomposition differs for {spec.aux}" + let some (.inductInfo stored) := env.find? main + | throwError "{label}: stored inductive missing" + unless elim.numNested == stored.numNested do + throwError "{label}: numNested {elim.numNested} vs stored {stored.numNested}" + unless nestedStage3 targets sourceV do + throwError "{label}: Theory acceptance rejected an accepted declaration" + +run_meta do + checkFlattenParity "rose" ``RoseTree [`u] 1 roseDeps [listTarget] + checkFlattenParity "nv" ``NVTree [] 0 nvDeps [pvecStoredTarget] + checkFlattenParity "cu" ``CURose [] 0 roseDeps [listTarget] + +/-! ## Rejection differentials + +Each negative is written once at the kernel `Expr` level and once as a +`VInductDecl`; the kernel run and the Theory gate must both reject. -/ + +def natDeps09B (env : Environment) : ConstMap := + depMap09A env [``Nat, ``Nat.zero, ``Nat.succ, ``List, ``List.nil, ``List.cons] + +/-- `inductive Loose0 | node : (n : Nat) → List (Loose0 n) → Loose0` — the +parametric argument mentions the constructor-local `n`. -/ +def looseDecl : Declaration := + .inductDecl [] 0 + [{ name := `Loose0 + type := .sort 1 + ctors := [{ + name := `Loose0.node + type := .forallE `n (.const ``Nat []) + (.forallE `t + (mkApp (mkConst ``List [.zero]) (.app (.const `Loose0 []) (.bvar 0))) + (.const `Loose0 []) .default) .default }] }] + false + +def looseSourceV : VInductDecl where + uvars := 0 + nparams := 0 + types := + [{ name := `Loose0 + uvars := 0 + type := .sort (.succ .zero) + ctors := + [⟨⟨0, .forallE (.const ``Nat []) + (.forallE (.app (.const ``List [.zero]) + (.app (.const `Loose0 []) (.bvar 0))) + (.const `Loose0 []))⟩, `Loose0.node⟩] }] + +/-- `inductive Bad0N | node : Bad0N → List (Bad0N Nat.zero) → Bad0N` — the +parametric argument applies a block family off the parameter spine. -/ +def badAppDecl : Declaration := + .inductDecl [] 0 + [{ name := `Bad0N + type := .sort 1 + ctors := [{ + name := `Bad0N.node + type := .forallE `x (.const `Bad0N []) + (.forallE `t + (mkApp (mkConst ``List [.zero]) + (.app (.const `Bad0N []) (.const ``Nat.zero []))) + (.const `Bad0N []) .default) .default }] }] + false + +def badAppSourceV : VInductDecl where + uvars := 0 + nparams := 0 + types := + [{ name := `Bad0N + uvars := 0 + type := .sort (.succ .zero) + ctors := + [⟨⟨0, .forallE (.const `Bad0N []) + (.forallE (.app (.const ``List [.zero]) + (.app (.const `Bad0N []) (.const ``Nat.zero []))) + (.const `Bad0N []))⟩, `Bad0N.node⟩] }] + +/-- A two-family source whose second family occupies the canonical first +auxiliary name `_nested.List_1`. -/ +def collisionDecl : Declaration := + let rose := fun a => mkApp (mkConst `Rose0 [.param `u]) a + .inductDecl [`u] 1 + [{ name := `Rose0 + type := .forallE `α (.sort (.succ (.param `u))) (.sort (.succ (.param `u))) .default + ctors := [{ + name := `Rose0.node + type := .forallE `α (.sort (.succ (.param `u))) + (.forallE `t (mkApp (mkConst ``List [.param `u]) (rose (.bvar 0))) + (rose (.bvar 1)) .default) .default }] }, + { name := (`_nested ++ ``List).appendIndexAfter 1 + type := .forallE `α (.sort (.succ (.param `u))) (.sort (.succ (.param `u))) .default + ctors := [] }] + false + +def collisionSourceV : VInductDecl where + uvars := 1 + nparams := 1 + types := + [{ name := `Rose0 + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := + [⟨⟨1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) + (.forallE (.app (.const ``List [.param 0]) + (.app (.const `Rose0 [.param 0]) (.bvar 1))) + (.app (.const `Rose0 [.param 0]) (.bvar 2))))⟩, `Rose0.node⟩] }, + { name := (`_nested ++ ``List).appendIndexAfter 1 + uvars := 1 + type := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) + ctors := [] }] + +open Elab in +run_meta do + let env ← getEnv + let deps := natDeps09B env + let kenv := Kernel.Environment.ofConstants `_spec09BNeg deps + -- the loose parametric argument rejects in flattening, with the kernel's + -- exact diagnostic + match Ix.Theory.Named.addDecl kenv looseDecl with + | .ok _ => throwError "loose: kernel accepted a local-variable parametric argument" + | .error (.other msg) => + unless msg == "invalid nested inductive datatype 'List', \ + nested inductive datatypes parameters cannot contain local variables." do + throwError "loose: unexpected kernel diagnostic {msg}" + | .error _ => throwError "loose: unexpected kernel error shape" + unless (nestedElimination? [listTarget] looseSourceV).isNone do + throwError "loose: Theory flattening accepted" + unless !nestedStage3 [listTarget] looseSourceV do + throwError "loose: Theory gate accepted" + -- the off-spine parametric application flattens but fails checking + match Ix.Theory.Named.addDecl kenv badAppDecl with + | .ok _ => throwError "badApp: kernel accepted an off-spine parametric application" + | .error _ => pure () + unless (nestedElimination? [listTarget] badAppSourceV).isSome do + throwError "badApp: Theory flattening should succeed" + unless !nestedStage3 [listTarget] badAppSourceV do + throwError "badApp: Theory gate accepted" + -- the canonical-name collision rejects at insertion (kernel) and at + -- `blockNamesOK` (Theory) + match Ix.Theory.Named.addDecl kenv collisionDecl with + | .ok _ => throwError "collision: kernel accepted a duplicate auxiliary name" + | .error _ => pure () + unless (nestedElimination? [listTarget] collisionSourceV).isSome do + throwError "collision: Theory flattening should succeed" + unless !nestedStage3 [listTarget] collisionSourceV do + throwError "collision: Theory gate accepted" + -- a missing target declaration rejects on both sides + let kenvNoList := Kernel.Environment.ofConstants `_spec09BNoList + (depMap09A env [``Nat, ``Nat.zero, ``Nat.succ]) + let roseSrc := sourceType09A env ``RoseTree + match Ix.Theory.Named.Environment.addInductive kenvNoList [`u] 1 [roseSrc] false false with + | .ok _ => throwError "noTarget: kernel accepted without the List declaration" + | .error _ => pure () + let roseV ← toVInductDecl09B [`u] 1 [roseSrc] + unless !nestedStage3 [] roseV do + throwError "noTarget: Theory gate accepted without target metadata" + +/-! ## Restoration parity (Spec-09C) + +The Theory restoration over the flattened block's generation artifacts +reproduces Lean's stored metadata exactly: every restored recursor name, +universe count, and type, and every rule RHS in the globally flattened +order, on all three real fixtures. This runs the product σ +(`NestedBlockChecked.recursors`/`generatedRules`), not the Spec-09A design +probe. -/ + +open Elab in +def checkRestoreParity (label : String) (main : Name) (lparams : List Name) + (nparams : Nat) (targets : List NestedTargetBlock) : MetaM Unit := do + let env ← getEnv + let src := sourceType09A env main + let sourceV ← toVInductDecl09B lparams nparams [src] + let some nested := nestedBlockChecked? targets sourceV + | throwError "{label}: nested acceptance failed" + let expectedNames := [mkRecName main] ++ + nested.elim.specs.mapIdx fun i _ => (mkRecName main).appendIndexAfter (i + 1) + unless nested.recursors.length == expectedNames.length do + throwError "{label}: {nested.recursors.length} restored recursors, \ + expected {expectedNames.length}" + for (r, expected) in nested.recursors.zip expectedNames do + unless r.name == expected do + throwError "{label}: restored recursor name {r.name}, expected {expected}" + let some (.recInfo stored) := env.find? expected + | throwError "{label}: stored recursor {expected} missing" + unless r.uvars == stored.levelParams.length do + throwError "{label}: recursor universe count differs for {expected}" + let storedType ← Ix.Theory.Named.Meta.ofExpr stored.levelParams {} + (← Ix.Theory.Named.Meta.expandExpr stored.type) + unless r.type == storedType do + throwError "{label}: restored recursor type differs from stored for {expected}" + let mut storedRules : List (Name × Expr) := [] + for n in expectedNames do + let some (.recInfo stored) := env.find? n + | throwError "{label}: stored recursor {n} missing" + for rule in stored.rules do + storedRules := storedRules ++ [(rule.ctor, rule.rhs)] + let rules := nested.generatedRules + unless rules.length == storedRules.length do + throwError "{label}: {rules.length} restored rules, stored {storedRules.length}" + let some (.recInfo mainRec) := env.find? (mkRecName main) + | throwError "{label}: stored main recursor missing" + for (df, (ctor, storedRhs)) in rules.zip storedRules do + let storedRhsV ← Ix.Theory.Named.Meta.ofExpr mainRec.levelParams {} + (← Ix.Theory.Named.Meta.expandExpr storedRhs) + unless df.rhs == storedRhsV do + throwError "{label}: restored rule RHS differs from stored for {ctor}" + +run_meta do + checkRestoreParity "rose" ``RoseTree [`u] 1 [listTarget] + checkRestoreParity "nv" ``NVTree [] 0 [pvecStoredTarget] + checkRestoreParity "cu" ``CURose [] 0 [listTarget] + +/-! ## Real-output round-trip (Spec-09C) + +Run the port's complete `Environment.addInductive` on a dependency-only +kernel environment and compare its entire output — not the ambient +elaborator metadata — against the Theory nested artifacts: the stored +payload against the source constants, and every emitted recursor's name, +universe count, type, rule constructors, rule field counts, and rule RHSs +against the restored inventory. Nothing in this comparison is +hand-authored: the left side is real `Inductive.Add.run`-derived output +and the right side is computed by `nestedBlockChecked?`. -/ + +open Elab in +def checkOutputRoundTrip (label : String) (main : Name) (lparams : List Name) + (nparams : Nat) (deps : List Name) (targets : List NestedTargetBlock) : + MetaM Unit := do + let env ← getEnv + let src := sourceType09A env main + let kenv := Kernel.Environment.ofConstants (`_spec09C ++ main) (depMap09A env deps) + let .ok kout := Ix.Theory.Named.Environment.addInductive kenv lparams nparams [src] false false + | throwError "{label}: port addInductive failed" + let sourceV ← toVInductDecl09B lparams nparams [src] + let some nested := nestedBlockChecked? targets sourceV + | throwError "{label}: nested acceptance failed" + -- the stored payload: families and constructors + for tyV in sourceV.types do + let some (.inductInfo out) := kout.find? tyV.name + | throwError "{label}: output family {tyV.name} missing" + let outType ← Ix.Theory.Named.Meta.ofExpr out.levelParams {} (← Ix.Theory.Named.Meta.expandExpr out.type) + unless out.levelParams.length == tyV.uvars && outType == tyV.type do + throwError "{label}: output family metadata differs for {tyV.name}" + unless out.numNested == nested.elim.numNested do + throwError "{label}: output numNested {out.numNested} vs \ + artifact {nested.elim.numNested}" + for cV in tyV.ctors do + let some (.ctorInfo outC) := kout.find? cV.name + | throwError "{label}: output constructor {cV.name} missing" + let outCType ← Ix.Theory.Named.Meta.ofExpr outC.levelParams {} + (← Ix.Theory.Named.Meta.expandExpr outC.type) + unless outC.levelParams.length == cV.uvars && outCType == cV.type do + throwError "{label}: output constructor metadata differs for {cV.name}" + -- the restored recursors and their rules, in inventory order + let mut ruleIdx := 0 + let rules := nested.generatedRules + for r in nested.recursors do + let some (.recInfo out) := kout.find? r.name + | throwError "{label}: output recursor {r.name} missing" + let outType ← Ix.Theory.Named.Meta.ofExpr out.levelParams {} (← Ix.Theory.Named.Meta.expandExpr out.type) + unless out.levelParams.length == r.uvars && outType == r.type do + throwError "{label}: output recursor metadata differs for {r.name}" + unless out.k == nested.generation.kTarget do + throwError "{label}: output recursor K flag differs for {r.name}" + for rule in out.rules do + let some df := rules[ruleIdx]? + | throwError "{label}: more output rules than restored rules" + let outRhs ← Ix.Theory.Named.Meta.ofExpr out.levelParams {} + (← Ix.Theory.Named.Meta.expandExpr rule.rhs) + unless outRhs == df.rhs do + throwError "{label}: output rule RHS differs for {rule.ctor}" + ruleIdx := ruleIdx + 1 + unless ruleIdx == rules.length do + throwError "{label}: {rules.length} restored rules, output consumed {ruleIdx}" + +run_meta do + checkOutputRoundTrip "rose" ``RoseTree [`u] 1 roseDeps [listTarget] + checkOutputRoundTrip "nv" ``NVTree [] 0 nvDeps [pvecStoredTarget] + checkOutputRoundTrip "cu" ``CURose [] 0 roseDeps [listTarget] + +end Ix.Theory.Named.NestedTransformation diff --git a/Ix/Theory/Named/Verify/Environment/Normalization.lean b/Ix/Theory/Named/Verify/Environment/Normalization.lean new file mode 100644 index 000000000..68a92acb1 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/Normalization.lean @@ -0,0 +1,6953 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.TypeChecker +import Ix.Theory.Named.Reference.Inductive.ValidationTrace + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel + +namespace TypeChecker + +/-- Compatibility name for the consumer-neutral reflected-primitive list. -/ +@[deprecated Ix.Theory.Named.VEnv.reflectedPrimitiveNames (since := "2026-08-11")] +abbrev reflectedPrimitiveNames : List Name := + Ix.Theory.Named.VEnv.reflectedPrimitiveNames + +/-- Compatibility shim for the consumer-neutral Theory theorem. -/ +@[deprecated Ix.Theory.Named.VEnv.HasPrimitives.of_avoids (since := "2026-08-11")] +theorem VEnv.HasPrimitives.of_avoids + {env : VEnv} + (h : ∀ n ∈ reflectedPrimitiveNames, env.constants n = none) : + env.HasPrimitives := + Ix.Theory.Named.VEnv.HasPrimitives.of_avoids h + +/-- Compatibility shim for the consumer-neutral Theory theorem. -/ +@[deprecated Ix.Theory.Named.VEnv.addConst_other (since := "2026-08-11")] +theorem VEnv.addConst_other + {env env' : VEnv} {name other : Name} {ci : VConstant} + (hadd : env.addConst name ci = some env') + (hne : name ≠ other) : + env'.constants other = env.constants other := + Ix.Theory.Named.VEnv.addConst_other hadd hne + +/-- Compatibility shim for the consumer-neutral Theory theorem. -/ +@[deprecated Ix.Theory.Named.VEnv.HasPrimitives.addConst (since := "2026-08-11")] +theorem VEnv.HasPrimitives.addConst + {env env' : VEnv} {name : Name} {ci : VConstant} + (H : env.HasPrimitives) + (hname : name ∉ reflectedPrimitiveNames) + (hadd : env.addConst name ci = some env') : + env'.HasPrimitives := + Ix.Theory.Named.VEnv.HasPrimitives.addConst H hname hadd + +/-- A verified implementation local context remains verified when the Theory +environment grows. Kernel local declarations and their free-variable names +are unchanged; only their translations and typing derivations are transported +monotonically. -/ +theorem MLCtx.WF.mono + {env env' : VEnv} (henv : env ≤ env') : + ∀ {context : MLCtx} {Us : List Name}, + context.WF env Us → context.WF env' Us + | .nil, _, _ => trivial + | .vlam _ _ _ _ _ _, _, + ⟨tailWF, fresh, type_tr, typeWF⟩ => + ⟨tailWF.mono henv, fresh, type_tr.mono henv, typeWF.mono henv⟩ + | .vlet _ _ _ _ _ _ _, _, + ⟨tailWF, fresh, type_tr, value_tr, valueWF⟩ => + ⟨tailWF.mono henv, fresh, type_tr.mono henv, + value_tr.mono henv, valueWF.mono henv⟩ + +/-- Kernel-side counterpart of `VEnv.HasPrimitives.of_avoids`: if an isolated +constant map contains no hard-coded primitive name, the safety premise needed +by `VContext` is vacuous. -/ +theorem safePrimitives_of_avoids + {env : Environment} {n : Name} {ci : ConstantInfo} + (h : ∀ n, Environment.primitives.contains n → env.find? n = none) : + env.find? n = some ci → + Environment.primitives.contains n → + ci.safety = .safe ∧ ci.levelParams = [] := by + intro hfind hprim + rw [h n hprim] at hfind + contradiction + +/-- Staging one fresh non-primitive inductive family preserves the kernel-side +primitive safety contract. All old lookups are inherited from the input map; +the only new lookup cannot be primitive by hypothesis. -/ +theorem AddInductConstant.safePrimitives + {pre post : Environment} {env typeEnv : VEnv} {raw : VConstVal} + (stage : AddInductConstant .induct pre.constants env raw + post.constants typeEnv) + (preMapWF : pre.constants.WF) + (H : pre.find? n = some ci → + Environment.primitives.contains n → + ci.safety = .safe ∧ ci.levelParams = []) + (hname : Environment.primitives.contains raw.name = false) : + post.find? n = some ci → + Environment.primitives.contains n → + ci.safety = .safe ∧ ci.levelParams = [] := by + intro hfind hprim + have postMapWF := stage.map_wf preMapWF + change post.constants.find?' n = some ci at hfind + rw [postMapWF.find?'_eq_find?, stage.map_add, + preMapWF.find?_insert] at hfind + split at hfind + · rename_i heq + have : raw.name = n := by simpa using heq + subst n + rw [hname] at hprim + contradiction + · apply H + change pre.constants.find?' n = some ci + rw [preMapWF.find?'_eq_find?] + exact hfind + exact hprim + +/-- Evidence that Verify's recursive WHNF procedure returned an exact kernel +expression, together with strict translations of the input and output into one +Theory context. + +The result is not trusted merely because it is supplied by a caller: +`run_eq` records the concrete checker execution, while `rhs_tr` identifies its +Theory meaning. -/ +structure WhnfRun (env : VEnv) (Us : List Name) (Δ : VLCtx) + (lhs rhs : Expr) (lhs' rhs' : VExpr) where + context : VContext + venv_eq : context.venv = env + lparams_eq : context.lparams = Us + vlctx_eq : context.vlctx = Δ + state_wf : VState.WF context {} + lhs_tr : TrExprS env Us Δ lhs lhs' + rhs_tr : TrExprS env Us Δ rhs rhs' + recursionFuel : Nat + run_eq : ∃ state : State, + Inner.whnf' lhs (Methods.withFuel recursionFuel) + context.toContext ({} : State) = .ok (rhs, state) + +/-- Turn one operationally certified candidate step into the existing +state-bearing Verify certificate once the caller supplies the strict +kernel/Theory translations and the corresponding verified context. + +The adapter recovers the final checker state from the stored `M.run` equality; +it does not rerun normalization, choose a result, or assert a semantic +equality. -/ +def WhnfRun.ofCandidateStep + (step : AddInductive.CandidateWhnfStep) + (hvalid : step.Valid) + (context : VContext) + (context_eq : + context.toContext = step.context.toTypeChecker) + (venv_eq : context.venv = env) + (lparams_eq : context.lparams = Us) + (vlctx_eq : context.vlctx = Δ) + (state_wf : VState.WF context {}) + (lhs_tr : TrExprS env Us Δ step.source lhs') + (rhs_tr : TrExprS env Us Δ step.result rhs') + (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel + 1) : + WhnfRun env Us Δ step.source step.result lhs' rhs' where + context := context + venv_eq := venv_eq + lparams_eq := lparams_eq + vlctx_eq := vlctx_eq + state_wf := state_wf + lhs_tr := lhs_tr + rhs_tr := rhs_tr + recursionFuel := recursionFuel + run_eq := by + rw [context_eq] + exact step.innerRun recursionFuel hdepth hvalid + +/-- The strict input translation already supplies the Theory well-formedness +needed to type an exact WHNF equality. In particular, a certificate producer +does not need to borrow a typing fact from the normalized declaration it is +trying to construct. -/ +theorem WhnfRun.lhs_wf + (run : WhnfRun env Us Δ lhs rhs lhs' rhs') : + lhs'.WF env Us.length Δ.toCtx := by + have hlhs : run.context.TrExprS lhs lhs' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.lhs_tr + have hwf := hlhs.wf run.context.Ewf.ordered run.context.Δwf + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq] using hwf + +/-- An exact successful verified WHNF execution is an ordinary Theory +definitional equality. The proof consumes the existing checker-refinement +contract and uses representation uniqueness to identify the translated +result. -/ +theorem WhnfRun.isDefEqU + (run : WhnfRun env Us Δ lhs rhs lhs' rhs') : + env.IsDefEqU Us.length Δ.toCtx lhs' rhs' := by + have hlhs : run.context.TrExprS lhs lhs' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.lhs_tr + have hrhs : run.context.TrExpr rhs rhs' := by + have strict : run.context.TrExprS rhs rhs' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.rhs_tr + exact strict.trExpr run.context.Ewf run.context.Δwf + obtain ⟨state, hrun⟩ := run.run_eq + obtain ⟨_, _, _, _, _, htr⟩ := + (TypeChecker.Inner.whnf'.WF hlhs + (Methods.withFuel run.recursionFuel) Methods.withFuel.WF) + run.state_wf rhs state hrun + have hdefeq := + htr.uniq run.context.Ewf + (.refl run.context.Ewf run.context.Δwf) hrhs + simpa only [VContext.IsDefEqU, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using hdefeq + +/-- Typed form of `WhnfRun.isDefEqU`. A known type for the input fixes the +otherwise existential type in the WHNF refinement result. -/ +theorem WhnfRun.isDefEq + (run : WhnfRun env Us Δ lhs rhs lhs' rhs') + (hlhs : env.HasType Us.length Δ.toCtx lhs' A) : + env.IsDefEq Us.length Δ.toCtx lhs' rhs' A := by + have henv : VEnv.WF env := by + simpa only [run.venv_eq] using run.context.Ewf + have hΔ : OnCtx Δ.toCtx (env.IsType Us.length) := by + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq] using + run.context.Δwf.toCtx + exact run.isDefEqU.of_l henv hΔ hlhs + +/-- Evidence that Verify's full type-checking path inferred an exact kernel +type, with strict Theory translations of both the checked expression and the +returned type. + +`inferOnly := false` is important here: the recorded run checks the expression +rather than trusting a caller-provided `TrExprS` derivation as an inference +cache hit. -/ +structure CheckTypeRun (env : VEnv) (Us : List Name) (Δ : VLCtx) + (expr inferred : Expr) (expr' inferred' : VExpr) where + context : VContext + venv_eq : context.venv = env + lparams_eq : context.lparams = Us + vlctx_eq : context.vlctx = Δ + state_wf : VState.WF context {} + expr_tr : TrExprS env Us Δ expr expr' + inferred_tr : TrExprS env Us Δ inferred inferred' + recursionFuel : Nat + run_eq : ∃ state : State, + Inner.inferType expr false (Methods.withFuel recursionFuel) + context.toContext ({} : State) = .ok (inferred, state) + +/-- Candidate-step adapter for full checking. As with +`WhnfRun.ofCandidateStep`, the operational result and final state come from +the producer; this boundary only attaches an already verified context and +strict translations. -/ +def CheckTypeRun.ofCandidateStep + (step : AddInductive.CandidateCheckTypeStep) + (hvalid : step.Valid) + (context : VContext) + (context_eq : + context.toContext = step.context.toTypeChecker) + (venv_eq : context.venv = env) + (lparams_eq : context.lparams = Us) + (vlctx_eq : context.vlctx = Δ) + (state_wf : VState.WF context {}) + (expr_tr : TrExprS env Us Δ step.source expr') + (inferred_tr : TrExprS env Us Δ step.inferred inferred') + (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel) : + CheckTypeRun env Us Δ step.source step.inferred expr' inferred' where + context := context + venv_eq := venv_eq + lparams_eq := lparams_eq + vlctx_eq := vlctx_eq + state_wf := state_wf + expr_tr := expr_tr + inferred_tr := inferred_tr + recursionFuel := recursionFuel + run_eq := by + rw [context_eq] + exact step.innerRun recursionFuel hdepth hvalid + +/-- Recover the strict Theory translations and typing judgment supplied by an +exact retained full-check observation. + +This is the proof-producing counterpart of `CheckTypeRun.ofCandidateStep` for +callers that do not yet have named translations. The only source-side premise +is the free-variable condition required by the verified checker refinement. -/ +theorem candidateCheckTypeStep_exists_translation + (step : AddInductive.CandidateCheckTypeStep) + (hvalid : step.Valid) + (context : VContext) + (context_eq : context.toContext = step.context.toTypeChecker) + (state_wf : VState.WF context {}) + (source_fvars : + step.source.FVarsIn (· ∈ context.vlctx.fvars)) + (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel) : + ∃ source' inferred', + context.TrExprS step.source source' ∧ + context.TrExprS step.inferred inferred' ∧ + context.HasType source' inferred' := by + obtain ⟨state, run⟩ := + step.innerRun recursionFuel hdepth hvalid + rw [← context_eq] at run + obtain ⟨_, _, _, _, source', inferred', typing⟩ := + (Inner.checkType.WF source_fvars + (Methods.withFuel recursionFuel) Methods.withFuel.WF) + state_wf step.inferred state run + exact ⟨source', inferred', typing.2.1, typing.2.2.1, + typing.2.2.2⟩ + +/-- An exact successful `checkType` execution supplies the corresponding +Theory typing judgment. Translation uniqueness transports the verifier's +existential result to the precise translations named by the certificate. -/ +theorem CheckTypeRun.hasType + (run : CheckTypeRun env Us Δ expr inferred expr' inferred') : + env.HasType Us.length Δ.toCtx expr' inferred' := by + have hexpr : run.context.TrExprS expr expr' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.expr_tr + have hinferred : run.context.TrExprS inferred inferred' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.inferred_tr + obtain ⟨state, hrun⟩ := run.run_eq + obtain ⟨_, _, _, _, e, ty, htyping⟩ := + (TypeChecker.Inner.checkType.WF hexpr.fvarsIn + (Methods.withFuel run.recursionFuel) Methods.withFuel.WF) + run.state_wf inferred state hrun + rcases htyping with ⟨_, he, hty, hhasType⟩ + have heq := + he.uniq run.context.Ewf + (.refl run.context.Ewf run.context.Δwf) hexpr + have htyeq := + hty.uniq run.context.Ewf + (.refl run.context.Ewf run.context.Δwf) hinferred + have hout := + (hhasType.defeqU_l run.context.Ewf run.context.Δwf heq).defeqU_r + run.context.Ewf run.context.Δwf htyeq + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq] using hout + +/-- A checked expression whose inferred type translates to a sort is a Theory +type. This is the insertion premise needed for raw family and constructor +constants. -/ +theorem CheckTypeRun.isType + (run : CheckTypeRun env Us Δ expr inferred expr' (.sort u)) : + env.IsType Us.length Δ.toCtx expr' := + ⟨u, run.hasType⟩ + +/-- If `checkType` returns a type expression whose own verified WHNF is a +sort, the checked expression is a Theory type. This is the common alias case: +the checker may infer a reducible type constant before `ensureSort` exposes its +sort WHNF. -/ +theorem CheckTypeRun.isType_of_whnf + (run : CheckTypeRun env Us Δ expr inferred expr' inferred') + (typeRun : WhnfRun env Us Δ inferred reduced inferred' (.sort u)) : + env.IsType Us.length Δ.toCtx expr' := by + have henv : VEnv.WF env := by + simpa only [run.venv_eq] using run.context.Ewf + have hΔ : OnCtx Δ.toCtx (env.IsType Us.length) := by + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq] using + run.context.Δwf.toCtx + exact ⟨u, run.hasType.defeqU_r henv hΔ typeRun.isDefEqU⟩ + +/-- Evidence for one exact successful checker definitional-equality run, with +strict translations of both kernel endpoints in the same Theory context. -/ +structure IsDefEqRun (env : VEnv) (Us : List Name) (Δ : VLCtx) + (lhs rhs : Expr) (lhs' rhs' : VExpr) where + context : VContext + venv_eq : context.venv = env + lparams_eq : context.lparams = Us + vlctx_eq : context.vlctx = Δ + state_wf : VState.WF context {} + lhs_tr : TrExprS env Us Δ lhs lhs' + rhs_tr : TrExprS env Us Δ rhs rhs' + recursionFuel : Nat + run_eq : ∃ state : State, + Inner.isDefEq lhs rhs (Methods.withFuel recursionFuel) + context.toContext ({} : State) = .ok (true, state) + +/-- Convert the retained candidate equality observation to a state-bearing +Verify certificate. -/ +def IsDefEqRun.ofCandidateStep + (step : AddInductive.CandidateIsDefEqStep) + (hvalid : step.Valid) + (context : VContext) + (context_eq : context.toContext = step.context.toTypeChecker) + (venv_eq : context.venv = env) + (lparams_eq : context.lparams = Us) + (vlctx_eq : context.vlctx = Δ) + (state_wf : VState.WF context {}) + (lhs_tr : TrExprS env Us Δ step.lhs lhs') + (rhs_tr : TrExprS env Us Δ step.rhs rhs') + (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel) : + IsDefEqRun env Us Δ step.lhs step.rhs lhs' rhs' where + context := context + venv_eq := venv_eq + lparams_eq := lparams_eq + vlctx_eq := vlctx_eq + state_wf := state_wf + lhs_tr := lhs_tr + rhs_tr := rhs_tr + recursionFuel := recursionFuel + run_eq := by + rw [context_eq] + exact step.innerRun recursionFuel hdepth hvalid + +/-- A successful verified equality run supplies ordinary Theory +definitional equality. -/ +theorem IsDefEqRun.isDefEqU + (run : IsDefEqRun env Us Δ lhs rhs lhs' rhs') : + env.IsDefEqU Us.length Δ.toCtx lhs' rhs' := by + have hlhs : run.context.TrExprS lhs lhs' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.lhs_tr + have hrhs : run.context.TrExprS rhs rhs' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.rhs_tr + obtain ⟨state, hrun⟩ := run.run_eq + obtain ⟨_, _, _, _, hdefeq⟩ := + (TypeChecker.Inner.isDefEq.WF hlhs hrhs + (Methods.withFuel run.recursionFuel) Methods.withFuel.WF) + run.state_wf true state hrun + simpa only [VContext.IsDefEqU, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using hdefeq (by simp) + +/-- Consuming a certified annotation path cannot introduce a free variable or +level metavariable. -/ +theorem candidateTypeAnnotation_fvarsIn + (trace : AddInductive.CandidateTypeAnnotationTrace source consumed) + (h : source.FVarsIn fvars) : consumed.FVarsIn fvars := by + induction trace with + | identity => exact h + | outParam _ _ _ ih => exact ih h.2 + | semiOutParam _ _ _ ih => exact ih h.2 + | optParam _ _ _ _ ih => exact ih h.1.2 + | autoParam _ _ _ _ ih => exact ih h.1.2 + +/-- Extract a strict translation of the consumed annotation argument from the +strict translation of the raw wrapper application. -/ +theorem candidateTypeAnnotation_exists_translation + (trace : AddInductive.CandidateTypeAnnotationTrace source consumed) + (source_tr : TrExprS env Us Δ source source') : + ∃ consumed', TrExprS env Us Δ consumed consumed' := by + induction trace generalizing source' with + | identity => exact ⟨source', source_tr⟩ + | outParam _ _ _ ih => + let .app _ _ _ type_tr := source_tr + exact ih type_tr + | semiOutParam _ _ _ ih => + let .app _ _ _ type_tr := source_tr + exact ih type_tr + | optParam _ _ _ _ ih => + let .app _ _ fn_tr _ := source_tr + let .app _ _ _ type_tr := fn_tr + exact ih type_tr + | autoParam _ _ _ _ ih => + let .app _ _ fn_tr _ := source_tr + let .app _ _ _ type_tr := fn_tr + exact ih type_tr + +/-- The empty executable checker state is well formed for any verified +context whose free-variable names are already reserved by the kernel name +generator. `VState.WF.empty` is the empty-local-context specialization; +candidate normalization needs this slightly more general form after entering +raw Pi binders. -/ +theorem VState.WF.empty_of_reserves + (context : VContext) + (reserved : ∀ fv ∈ context.vlctx.fvars, + (({} : VState).ngen).Reserves fv) : + VState.WF context {} where + trctx := context.trlctx + ngen_wf := reserved + ectx := ⟨context.vlctx, .refl, context.Δwf, .refl, .empty, reserved⟩ + inferTypeI_wf := .empty + inferTypeC_wf := .empty + whnfCore_wf := .empty + whnf_wf := .empty + unfold_wf _ := by simp + +/-- Positional verified context for an executable normalization candidate. + +The equality pins every checker-visible field (environment, local context, +safety, level parameters, and fuel) to the `AddInductive.Context` retained by +the candidate trace. The state certificate is kept with it because every +retained full-check and WHNF observation starts from the empty checker state. -/ +structure CandidateContextRun + (candidateContext : AddInductive.Context) where + context : VContext + context_eq : context.toContext = candidateContext.toTypeChecker + state_wf : VState.WF context {} + namePrefix_ne : candidateContext.ngen.namePrefix ≠ + (({} : VState).ngen).namePrefix + +/-- Candidate binders and the kernel checker's own temporary names use +different prefixes, so every candidate binder is reserved by a freshly +initialized kernel checker state. -/ +theorem candidateFreshFVarId_reserved + (candidateContext : AddInductive.Context) + (namePrefix_ne : candidateContext.ngen.namePrefix ≠ + (({} : VState).ngen).namePrefix) : + (({} : VState).ngen).Reserves candidateContext.freshFVarId := by + simp [NameGenerator.Reserves, AddInductive.Context.freshFVarId] + intro i h + apply namePrefix_ne + simpa only [NameGenerator.curr, Name.getPrefix] using + congrArg Name.getPrefix h + +/-- Package an already verified checker context at a candidate position. -/ +def CandidateContextRun.ofVContext + (candidateContext : AddInductive.Context) + (context : VContext) + (context_eq : context.toContext = candidateContext.toTypeChecker) + (state_wf : VState.WF context {}) + (namePrefix_ne : candidateContext.ngen.namePrefix ≠ + (({} : VState).ngen).namePrefix) : + CandidateContextRun candidateContext := + ⟨context, context_eq, state_wf, namePrefix_ne⟩ + +/-- Construct the root certificate used by family and constructor candidates. +Their candidate traversal deliberately resets the local context to empty. -/ +def CandidateContextRun.root + {ves : VEnvs} (wf : ves.WF candidateContext.env) + (lctx_eq : candidateContext.lctx = {}) + (namePrefix_ne : candidateContext.ngen.namePrefix ≠ + (({} : VState).ngen).namePrefix) : + CandidateContextRun candidateContext := by + let context := VContext.mk' wf candidateContext.safety + candidateContext.lparams candidateContext.fuel + refine ⟨context, ?_, ?_, namePrefix_ne⟩ + · simp [context, VContext.mk', VContext.mk1, MLCtx.lctx, + AddInductive.Context.toTypeChecker, lctx_eq] + · exact VState.WF.empty + +@[simp] theorem CandidateContextRun.context_env + (run : CandidateContextRun candidateContext) : + run.context.env = candidateContext.env := by + have h := congrArg (fun c : TypeChecker.Context => c.env) run.context_eq + simpa only [AddInductive.Context.toTypeChecker] using h + +@[simp] theorem CandidateContextRun.context_lctx + (run : CandidateContextRun candidateContext) : + run.context.lctx = candidateContext.lctx := by + have h := congrArg (fun c : TypeChecker.Context => c.lctx) run.context_eq + simpa only [AddInductive.Context.toTypeChecker] using h + +@[simp] theorem CandidateContextRun.context_safety + (run : CandidateContextRun candidateContext) : + run.context.safety = candidateContext.safety := by + have h := congrArg (fun c : TypeChecker.Context => c.safety) run.context_eq + simpa only [AddInductive.Context.toTypeChecker] using h + +@[simp] theorem CandidateContextRun.context_lparams + (run : CandidateContextRun candidateContext) : + run.context.lparams = candidateContext.lparams := by + have h := congrArg (fun c : TypeChecker.Context => c.lparams) run.context_eq + simpa only [AddInductive.Context.toTypeChecker] using h + +@[simp] theorem CandidateContextRun.context_fuel + (run : CandidateContextRun candidateContext) : + run.context.fuel = candidateContext.fuel := by + have h := congrArg (fun c : TypeChecker.Context => c.fuel) run.context_eq + simpa only [AddInductive.Context.toTypeChecker] using h + +/-- Reset only the implementation and Theory local contexts while retaining +the exact environment, safety mode, level parameters, fuel, and name +generator owned by a candidate context. Constructor root `checkType` uses +precisely this context before the validation telescope re-enters the retained +family locals. -/ +def CandidateContextRun.withEmptyLocalContext + (run : CandidateContextRun candidateContext) : + CandidateContextRun candidateContext.withEmptyLocalContext := by + let context : VContext := + { run.context with + lctx := {} + mlctx := .nil + mlctx_wf := trivial + lctx_eq := rfl } + have context_eq : context.toContext = + candidateContext.withEmptyLocalContext.toTypeChecker := by + change { run.context.toContext with lctx := {} } = + candidateContext.withEmptyLocalContext.toTypeChecker + rw [run.context_eq] + rfl + refine ⟨context, context_eq, ?_, run.namePrefix_ne⟩ + exact VState.WF.empty_of_reserves context (by + intro fv hfv + change fv ∈ VLCtx.fvars ([] : VLCtx) at hfv + simp at hfv) + +/-- Package a retained full-check observation at an already named strict +Theory source. The verified execution still chooses the inferred Theory +type; the duplicate source translation returned by refinement is discarded, +not identified by syntactic equality. -/ +theorem CheckTypeRun.exists_ofCandidateStep + (step : AddInductive.CandidateCheckTypeStep) + (hvalid : step.Valid) + (contextRun : CandidateContextRun step.context) + (source' : VExpr) + (source_tr : contextRun.context.TrExprS step.source source') : + ∃ inferred', Nonempty + (CheckTypeRun contextRun.context.venv contextRun.context.lparams + contextRun.context.vlctx step.source step.inferred source' inferred') := by + obtain ⟨_, inferred', _, inferred_tr, _⟩ := + candidateCheckTypeStep_exists_translation step hvalid + contextRun.context contextRun.context_eq contextRun.state_wf + source_tr.fvarsIn step.context.fuel.recDepth rfl + exact ⟨inferred', ⟨CheckTypeRun.ofCandidateStep step hvalid + contextRun.context contextRun.context_eq rfl rfl rfl + contextRun.state_wf source_tr inferred_tr + step.context.fuel.recDepth rfl⟩⟩ + +/-- Full-check packaging when only the checker's syntactic free-variable +premise is known. Both strict Theory endpoints are then selected by the +verified refinement of the retained execution. -/ +theorem CheckTypeRun.exists_ofCandidateStepFVars + (step : AddInductive.CandidateCheckTypeStep) + (hvalid : step.Valid) + (contextRun : CandidateContextRun step.context) + (source_fvars : + step.source.FVarsIn (· ∈ contextRun.context.vlctx.fvars)) : + ∃ source' inferred', Nonempty + (CheckTypeRun contextRun.context.venv contextRun.context.lparams + contextRun.context.vlctx step.source step.inferred source' inferred') := by + obtain ⟨source', inferred', source_tr, inferred_tr, _⟩ := + candidateCheckTypeStep_exists_translation step hvalid + contextRun.context contextRun.context_eq contextRun.state_wf + source_fvars step.context.fuel.recDepth rfl + exact ⟨source', inferred', ⟨CheckTypeRun.ofCandidateStep step hvalid + contextRun.context contextRun.context_eq rfl rfl rfl + contextRun.state_wf source_tr inferred_tr + step.context.fuel.recDepth rfl⟩⟩ + +/-- Package one retained WHNF observation and keep the strict Theory +translation selected for its exact kernel result. -/ +theorem WhnfRun.exists_ofCandidateStep + (step : AddInductive.CandidateWhnfStep) + (hvalid : step.Valid) + (contextRun : CandidateContextRun step.context) + (source' : VExpr) + (source_tr : contextRun.context.TrExprS step.source source') + (recursionFuel : Nat) + (hdepth : step.context.fuel.recDepth = recursionFuel + 1) : + ∃ result', contextRun.context.TrExprS step.result result' ∧ + Nonempty (WhnfRun contextRun.context.venv + contextRun.context.lparams contextRun.context.vlctx + step.source step.result source' result') := by + obtain ⟨state, run⟩ := step.innerRun recursionFuel hdepth hvalid + rw [← contextRun.context_eq] at run + obtain ⟨_, _, _, _, _, resultTranslation⟩ := + (Inner.whnf'.WF source_tr + (Methods.withFuel recursionFuel) Methods.withFuel.WF) + contextRun.state_wf step.result state run + obtain ⟨result', result_tr, _⟩ := resultTranslation + exact ⟨result', result_tr, ⟨WhnfRun.ofCandidateStep step hvalid + contextRun.context contextRun.context_eq rfl rfl rfl + contextRun.state_wf source_tr result_tr + recursionFuel hdepth⟩⟩ + +/-- Extend a verified candidate context by precisely the raw local declaration +used by `AddInductive.Context.pushLocalDecl`. + +The caller supplies the strict Theory translation and typing of the *stored* +local-domain expression. Freshness comes from the trace index; reservation is +the independent fact needed to restart each retained checker observation from +the empty kernel checker state. -/ +def CandidateContextRun.pushLocalDecl + (run : CandidateContextRun candidateContext) + (name : Name) (binderInfo : BinderInfo) (domain : Expr) + (fresh : candidateContext.lctx.find? + candidateContext.freshFVarId = none) + (domain' : VExpr) + (domain_tr : run.context.TrExprS domain domain') + (domain_type : run.context.IsType domain') : + CandidateContextRun + (candidateContext.pushLocalDecl name binderInfo domain) := by + let mlctx := run.context.mlctx.vlam candidateContext.freshFVarId + name domain domain' binderInfo + have lctx_eq : run.context.mlctx.lctx = candidateContext.lctx := by + calc + run.context.mlctx.lctx = run.context.lctx := run.context.lctx_eq + _ = candidateContext.lctx := by + simp + have fresh' : run.context.mlctx.lctx.find? + candidateContext.freshFVarId = none := by + rw [lctx_eq] + exact fresh + have mlctx_wf : mlctx.WF run.context.venv run.context.lparams := + ⟨run.context.mlctx_wf, fresh', domain_tr, domain_type⟩ + let context := run.context.withMLC mlctx (wf := ⟨mlctx_wf⟩) + have context_eq : context.toContext = + (candidateContext.pushLocalDecl name binderInfo domain).toTypeChecker := by + change { run.context.toContext with + lctx := run.context.mlctx.lctx.mkLocalDecl + candidateContext.freshFVarId name domain binderInfo } = _ + rw [run.context_eq, lctx_eq] + rfl + refine ⟨context, context_eq, VState.WF.empty_of_reserves context ?_, ?_⟩ + intro fv hfv + change fv ∈ candidateContext.freshFVarId :: + run.context.vlctx.fvars at hfv + simp only [List.mem_cons] at hfv + rcases hfv with rfl | hfv + · exact candidateFreshFVarId_reserved candidateContext run.namePrefix_ne + · exact run.state_wf.ngen_wf fv hfv + simpa [AddInductive.Context.pushLocalDecl, NameGenerator.next] using + run.namePrefix_ne + +@[simp] theorem CandidateContextRun.pushLocalDecl_venv + (run : CandidateContextRun candidateContext) + (domain_tr : run.context.TrExprS domain domain') + (domain_type : run.context.IsType domain') : + (run.pushLocalDecl name binderInfo domain fresh domain' domain_tr + domain_type).context.venv = run.context.venv := by + simp [CandidateContextRun.pushLocalDecl, VContext.withMLC] + +@[simp] theorem CandidateContextRun.pushLocalDecl_lparams + (run : CandidateContextRun candidateContext) + (domain_tr : run.context.TrExprS domain domain') + (domain_type : run.context.IsType domain') : + (run.pushLocalDecl name binderInfo domain fresh domain' domain_tr + domain_type).context.lparams = run.context.lparams := by + simp [CandidateContextRun.pushLocalDecl, VContext.withMLC] + +@[simp] theorem CandidateContextRun.pushLocalDecl_vlctx + (run : CandidateContextRun candidateContext) + (domain_tr : run.context.TrExprS domain domain') + (domain_type : run.context.IsType domain') : + (run.pushLocalDecl name binderInfo domain fresh domain' domain_tr + domain_type).context.vlctx = + (some (candidateContext.freshFVarId, domain.fvarsList), + .vlam domain') :: run.context.vlctx := by + simp [CandidateContextRun.pushLocalDecl, VContext.withMLC] + +/-- The two exact verifier runs attached to one retained candidate node. + +The indices force both runs to use the node's kernel source and observed +results and to agree on its Theory source. This is the atomic input to the +recursive candidate interpreter below: a successful full check supplies the +type at which the successful WHNF execution is interpreted. -/ +structure CandidateNodeRun (env : VEnv) (Us : List Name) (Δ : VLCtx) + (context : AddInductive.Context) + (source inferred result : Expr) + (source' result' inferred' : VExpr) where + check : CheckTypeRun env Us Δ source inferred source' inferred' + whnf : WhnfRun env Us Δ source result source' result' + +/-- Construct an atomic semantic node directly from the two proof-carrying +observations retained by `CandidateExprTrace`. The caller supplies only the +verified context and translations; the operational equalities and erased +checker states come from the candidate observations themselves. -/ +def CandidateNodeRun.ofCandidate + (candidateContext : AddInductive.Context) + (source inferred result : Expr) + (checked : AddInductive.CandidateCheckTypeStep.Valid + ⟨candidateContext, source, inferred⟩) + (normalized : AddInductive.CandidateWhnfStep.Valid + ⟨candidateContext, source, result⟩) + (context : VContext) + (context_eq : context.toContext = candidateContext.toTypeChecker) + (venv_eq : context.venv = env) + (lparams_eq : context.lparams = Us) + (vlctx_eq : context.vlctx = Δ) + (state_wf : VState.WF context {}) + (source_tr : TrExprS env Us Δ source source') + (inferred_tr : TrExprS env Us Δ inferred inferred') + (result_tr : TrExprS env Us Δ result result') + (checkFuel whnfFuel : Nat) + (checkDepth : candidateContext.fuel.recDepth = checkFuel) + (whnfDepth : candidateContext.fuel.recDepth = whnfFuel + 1) : + CandidateNodeRun env Us Δ candidateContext source inferred result + source' result' inferred' where + check := CheckTypeRun.ofCandidateStep + ⟨candidateContext, source, inferred⟩ checked context context_eq + venv_eq lparams_eq vlctx_eq state_wf source_tr inferred_tr + checkFuel checkDepth + whnf := WhnfRun.ofCandidateStep + ⟨candidateContext, source, result⟩ normalized context context_eq + venv_eq lparams_eq vlctx_eq state_wf source_tr result_tr + whnfFuel whnfDepth + +/-- Recover all output translations for one retained candidate node from the +verified checker refinements themselves. + +Unlike `ofCandidate`, this theorem does not ask the caller to identify the +kernel expressions returned by `checkType` and `whnf` with preselected Theory +terms. It extracts strict translations of both results from the two exact +executions, then packages those witnesses in the ordinary paired-node API. +Only the root source translation and matching verified context remain input. -/ +theorem CandidateNodeRun.exists_ofCandidate + (candidateContext : AddInductive.Context) + (source inferred result : Expr) + (checked : AddInductive.CandidateCheckTypeStep.Valid + ⟨candidateContext, source, inferred⟩) + (normalized : AddInductive.CandidateWhnfStep.Valid + ⟨candidateContext, source, result⟩) + (context : VContext) + (context_eq : context.toContext = candidateContext.toTypeChecker) + (state_wf : VState.WF context {}) + (source' : VExpr) (source_tr : context.TrExprS source source') + (checkFuel whnfFuel : Nat) + (checkDepth : candidateContext.fuel.recDepth = checkFuel) + (whnfDepth : candidateContext.fuel.recDepth = whnfFuel + 1) : + ∃ inferred' result', + context.TrExprS inferred inferred' ∧ + context.TrExprS result result' ∧ + Nonempty (CandidateNodeRun context.venv context.lparams context.vlctx + candidateContext source inferred result source' result' inferred') := by + obtain ⟨checkState, checkRun⟩ := + AddInductive.CandidateCheckTypeStep.innerRun + ⟨candidateContext, source, inferred⟩ checkFuel checkDepth checked + rw [← context_eq] at checkRun + obtain ⟨_, _, _, _, checkedSource', inferred', checkedTyping⟩ := + (Inner.checkType.WF source_tr.fvarsIn + (Methods.withFuel checkFuel) Methods.withFuel.WF) + state_wf inferred checkState checkRun + obtain ⟨whnfState, whnfRun⟩ := + AddInductive.CandidateWhnfStep.innerRun + ⟨candidateContext, source, result⟩ whnfFuel whnfDepth normalized + rw [← context_eq] at whnfRun + obtain ⟨_, _, _, _, _, resultTranslation⟩ := + (Inner.whnf'.WF source_tr + (Methods.withFuel whnfFuel) Methods.withFuel.WF) + state_wf result whnfState whnfRun + obtain ⟨result', result_tr, _⟩ := resultTranslation + refine ⟨inferred', result', checkedTyping.2.2.1, result_tr, ⟨?_⟩⟩ + exact CandidateNodeRun.ofCandidate + candidateContext source inferred result checked normalized + context context_eq rfl rfl rfl state_wf source_tr + checkedTyping.2.2.1 + result_tr + checkFuel whnfFuel checkDepth whnfDepth + +/-- Construct a paired candidate node with a caller-selected Theory endpoint +for the retained WHNF result. The exact full-check execution still selects +and strictly translates its inferred type; only the already translated WHNF +endpoint is fixed by the caller. -/ +theorem CandidateNodeRun.exists_ofCandidateAtResult + (candidateContext : AddInductive.Context) + (source inferred result : Expr) + (checked : AddInductive.CandidateCheckTypeStep.Valid + ⟨candidateContext, source, inferred⟩) + (normalized : AddInductive.CandidateWhnfStep.Valid + ⟨candidateContext, source, result⟩) + (context : VContext) + (context_eq : context.toContext = candidateContext.toTypeChecker) + (state_wf : VState.WF context {}) + (source' result' : VExpr) + (source_tr : context.TrExprS source source') + (result_tr : context.TrExprS result result') + (checkFuel whnfFuel : Nat) + (checkDepth : candidateContext.fuel.recDepth = checkFuel) + (whnfDepth : candidateContext.fuel.recDepth = whnfFuel + 1) : + ∃ inferred', Nonempty + (CandidateNodeRun context.venv context.lparams context.vlctx + candidateContext source inferred result source' result' inferred') := by + obtain ⟨_, inferred', _, inferred_tr, _⟩ := + candidateCheckTypeStep_exists_translation + ⟨candidateContext, source, inferred⟩ checked + context context_eq state_wf source_tr.fvarsIn checkFuel checkDepth + exact ⟨inferred', ⟨CandidateNodeRun.ofCandidate + candidateContext source inferred result checked normalized + context context_eq rfl rfl rfl state_wf source_tr inferred_tr + result_tr checkFuel whnfFuel checkDepth whnfDepth⟩⟩ + +/-- Compositional evidence for a normalization comparison. + +Leaves are either reflexive, already typed syntax or exact verified WHNF +executions. `forallE` lifts such evidence through the raw binder context, +which is the constructor-type case needed by the first non-identity replay. -/ +inductive DefEqEvidence (env : VEnv) : + Nat → List VExpr → VExpr → VExpr → VExpr → Prop where + | refl (h : env.HasType U Γ e A) : + DefEqEvidence env U Γ e e A + | whnf (run : WhnfRun env Us Δ lhs rhs lhs' rhs') + (h : env.HasType Us.length Δ.toCtx lhs' A) : + DefEqEvidence env Us.length Δ.toCtx lhs' rhs' A + | app + (fn : DefEqEvidence env U Γ f f' (.forallE A B)) + (arg : DefEqEvidence env U Γ a a' A) : + DefEqEvidence env U Γ (.app f a) (.app f' a') (B.inst a) + | beta + (body : env.HasType U (A :: Γ) e B) + (arg : env.HasType U Γ e' A) : + DefEqEvidence env U Γ + (.app (.lam A e) e') (e.inst e') (B.inst e') + | trans + (left : DefEqEvidence env U Γ lhs mid A) + (right : DefEqEvidence env U Γ mid rhs A) : + DefEqEvidence env U Γ lhs rhs A + | change + (type : env.IsDefEq U Γ A B (.sort u)) + (term : DefEqEvidence env U Γ lhs rhs A) : + DefEqEvidence env U Γ lhs rhs B + | ofDefEq (proof : env.IsDefEq U Γ lhs rhs A) : + DefEqEvidence env U Γ lhs rhs A + | forallE + (domain : DefEqEvidence env U Γ A A' (.sort u)) + (body : DefEqEvidence env U (A :: Γ) B B' (.sort v)) : + DefEqEvidence env U Γ + (.forallE A B) (.forallE A' B') (.sort (.imax u v)) + +/-- Interpret compositional normalization evidence as Theory definitional +equality at its recorded type. -/ +theorem DefEqEvidence.isDefEq : + DefEqEvidence env U Γ lhs rhs A → + env.IsDefEq U Γ lhs rhs A + | .refl h => h + | .whnf run h => run.isDefEq h + | .app fn arg => .appDF fn.isDefEq arg.isDefEq + | .beta body arg => .beta body arg + | .trans left right => .trans left.isDefEq right.isDefEq + | .change type term => .defeqDF type term.isDefEq + | .ofDefEq proof => proof + | .forallE domain body => + .forallEDF domain.isDefEq body.isDefEq + +/-- Interpret one paired candidate node as typed definitional equality. -/ +theorem CandidateNodeRun.evidence + (run : CandidateNodeRun env Us Δ context source inferred result + source' result' inferred') : + DefEqEvidence env Us.length Δ.toCtx source' result' inferred' := + .whnf run.whnf run.check.hasType + +/-- Recursive semantic interpretation of a source-indexed candidate trace. + +At a Pi node the raw domain and the annotation-consumed local domain may have +different strict Theory translations. The retained equality run relates them; +the body is checked in the consumed-domain context and transported back to the +raw Pi context only when forming congruence evidence. -/ +inductive CandidateExprRun (env : VEnv) (Us : List Name) : + {candidateContext : AddInductive.Context} → {source : Expr} → + AddInductive.CandidateExprTrace candidateContext source → + (Δ : VLCtx) → VExpr → VExpr → VExpr → Prop where + | terminal + (node : CandidateNodeRun env Us Δ context source inferred result + source' result' inferred') : + CandidateExprRun env Us + (.terminal context source inferred result checked normalized) + Δ source' result' inferred' + | forallE + (annotations : AddInductive.CandidateTypeAnnotations domain) + (annotationsEq : AddInductive.CandidateIsDefEqStep.Valid + ⟨context, domain, annotations.consumed⟩) + (domainCandidate : AddInductive.CandidateExprTrace context domain) + (bodyCandidate : AddInductive.CandidateExprTrace + (context.pushLocalDecl name binderInfo annotations.consumed) + (body.instantiate1 context.freshExpr)) + (node : CandidateNodeRun env Us Δ context source inferred + (.forallE name domain body binderInfo) + source' (.forallE domain' body') inferred') + (domainRun : CandidateExprRun env Us domainCandidate Δ + domain' domainView' domainInferred') + (annotationsRun : IsDefEqRun env Us Δ + domain annotations.consumed domain' storedDomain') + (bodyRun : CandidateExprRun env Us bodyCandidate bodyΔ + storedBody' bodyView' bodyInferred') + (domainType : env.HasType Us.length Δ.toCtx domain' (.sort u)) + (bodyType : env.HasType Us.length + (domain' :: Δ.toCtx) body' (.sort v)) + (bodySource : env.IsDefEq Us.length (domain' :: Δ.toCtx) + body' storedBody' (.sort v)) + (bodyContext : + bodyΔ = + (some (context.freshFVarId, annotations.consumed.fvarsList), + .vlam storedDomain') :: Δ) : + CandidateExprRun env Us + (.forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized + domainCandidate bodyCandidate) + Δ source' (.forallE domainView' bodyView') inferred' + +/-- Structural witness that a retained candidate trace is syntactically +identity-normalizing at every inspected node. + +The witness is deliberately recursive rather than a single root equality: +generation consumes the exposed Pi spine positionally. At Pi nodes it also +records that annotation processing kept the binder domain unchanged. -/ +inductive CandidateExprIdentity : + {candidateContext : AddInductive.Context} → {source : Expr} → + AddInductive.CandidateExprTrace candidateContext source → Prop where + | terminal + (result_eq : result = source) : + CandidateExprIdentity + (.terminal context source inferred result checked normalized) + | forallE + (domainCandidate : AddInductive.CandidateExprTrace context domain) + (bodyCandidate : AddInductive.CandidateExprTrace + (context.pushLocalDecl name binderInfo annotations.consumed) + (body.instantiate1 context.freshExpr)) + (source_eq : source = .forallE name domain body binderInfo) + (consumed_eq : annotations.consumed = domain) + (domainIdentity : CandidateExprIdentity domainCandidate) + (bodyIdentity : CandidateExprIdentity bodyCandidate) : + CandidateExprIdentity + (.forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized + domainCandidate bodyCandidate) + +private def candidateExprIdentityBinderInfoEq : + Lean.BinderInfo → Lean.BinderInfo → Bool + | .default, .default + | .implicit, .implicit + | .strictImplicit, .strictImplicit + | .instImplicit, .instImplicit => true + | _, _ => false + +private theorem candidateExprIdentityBinderInfoEq_sound + (left right : Lean.BinderInfo) + (h : candidateExprIdentityBinderInfoEq left right = true) : + left = right := by + cases left <;> cases right <;> + simp_all [candidateExprIdentityBinderInfoEq] + +/-- Transparent structural equality sufficient for identity-normalizing +candidate traces. Metadata nodes are conservatively rejected: the retained +generation spine never needs an opaque metadata equality to justify source +identity. -/ +private def candidateExprIdentityExprEq : Lean.Expr → Lean.Expr → Bool + | .bvar i, .bvar j => i == j + | .fvar i, .fvar j => i == j + | .mvar i, .mvar j => i == j + | .sort u, .sort v => u == v + | .const n us, .const n' us' => n == n' && us == us' + | .app f a, .app f' a' => + candidateExprIdentityExprEq f f' && + candidateExprIdentityExprEq a a' + | .lam n t b bi, .lam n' t' b' bi' => + n == n' && candidateExprIdentityExprEq t t' && + candidateExprIdentityExprEq b b' && + candidateExprIdentityBinderInfoEq bi bi' + | .forallE n t b bi, .forallE n' t' b' bi' => + n == n' && candidateExprIdentityExprEq t t' && + candidateExprIdentityExprEq b b' && + candidateExprIdentityBinderInfoEq bi bi' + | .letE n t v b nd, .letE n' t' v' b' nd' => + n == n' && candidateExprIdentityExprEq t t' && + candidateExprIdentityExprEq v v' && + candidateExprIdentityExprEq b b' && nd == nd' + | .lit a, .lit b => a == b + | .proj n i s, .proj n' i' s' => + n == n' && i == i' && candidateExprIdentityExprEq s s' + | _, _ => false + +private theorem candidateExprIdentityExprEq_sound : + ∀ (left right : Lean.Expr), + candidateExprIdentityExprEq left right = true → left = right := by + intro left right h + induction left generalizing right with + | bvar i => + cases right <;> + simp_all [candidateExprIdentityExprEq, beq_iff_eq] + | fvar i => + cases right <;> + simp_all [candidateExprIdentityExprEq, beq_iff_eq] + | mvar i => + cases right <;> + simp_all [candidateExprIdentityExprEq, beq_iff_eq] + | sort u => + cases right <;> + simp_all [candidateExprIdentityExprEq, beq_iff_eq] + | const n us => + cases right <;> + simp_all [candidateExprIdentityExprEq, beq_iff_eq] + | app fn arg fnIH argIH => + cases right with + | app fn' arg' => + simp only [candidateExprIdentityExprEq, + Bool.and_eq_true] at h + rw [fnIH fn' h.1, argIH arg' h.2] + | _ => simp_all [candidateExprIdentityExprEq] + | lam name type body binderInfo typeIH bodyIH => + cases right with + | lam name' type' body' binderInfo' => + simp only [candidateExprIdentityExprEq, Bool.and_eq_true, + beq_iff_eq] at h + rw [h.1.1.1, typeIH type' h.1.1.2, + bodyIH body' h.1.2, + candidateExprIdentityBinderInfoEq_sound _ _ h.2] + | _ => simp_all [candidateExprIdentityExprEq] + | forallE name type body binderInfo typeIH bodyIH => + cases right with + | forallE name' type' body' binderInfo' => + simp only [candidateExprIdentityExprEq, Bool.and_eq_true, + beq_iff_eq] at h + rw [h.1.1.1, typeIH type' h.1.1.2, + bodyIH body' h.1.2, + candidateExprIdentityBinderInfoEq_sound _ _ h.2] + | _ => simp_all [candidateExprIdentityExprEq] + | letE name type value body nondep typeIH valueIH bodyIH => + cases right with + | letE name' type' value' body' nondep' => + simp only [candidateExprIdentityExprEq, Bool.and_eq_true, + beq_iff_eq] at h + rw [h.1.1.1.1, typeIH type' h.1.1.1.2, + valueIH value' h.1.1.2, bodyIH body' h.1.2, h.2] + | _ => simp_all [candidateExprIdentityExprEq] + | lit literal => + cases right <;> + simp_all [candidateExprIdentityExprEq, beq_iff_eq] + | mdata data expr exprIH => + cases right <;> simp_all [candidateExprIdentityExprEq] + | proj typeName idx struct structIH => + cases right with + | proj typeName' idx' struct' => + simp only [candidateExprIdentityExprEq, Bool.and_eq_true, + beq_iff_eq] at h + rw [h.1.1, h.1.2, structIH struct' h.2] + | _ => simp_all [candidateExprIdentityExprEq] + +/-- Executable sufficient check for the recursive identity witness consumed +by generation. Unlike a root-only equality, it checks every retained domain, +body, annotation result, and terminal node. -/ +def CandidateExprIdentity.check : + {candidateContext : AddInductive.Context} → {source : Lean.Expr} → + AddInductive.CandidateExprTrace candidateContext source → Bool + | _, _, .terminal _ source _ result _ _ => + candidateExprIdentityExprEq result source + | _, _, .forallE _ source _ name domain body binderInfo _ annotations _ _ _ + domainCandidate bodyCandidate => + candidateExprIdentityExprEq source + (.forallE name domain body binderInfo) && + candidateExprIdentityExprEq annotations.consumed domain && + CandidateExprIdentity.check domainCandidate && + CandidateExprIdentity.check bodyCandidate + +/-- Executable sufficient equality check for the terminal expression selected +by a candidate trace. This is useful when the family validator must name its +result universe without unfolding the proof-carrying trace. -/ +def CandidateExprIdentity.terminalCheck + (trace : AddInductive.CandidateExprTrace candidateContext source) + (expected : Lean.Expr) : Bool := + candidateExprIdentityExprEq trace.terminalResult expected + +theorem CandidateExprIdentity.terminalResult_eq_of_check + {trace : AddInductive.CandidateExprTrace candidateContext source} + {expected : Lean.Expr} + (h : CandidateExprIdentity.terminalCheck trace expected = true) : + trace.terminalResult = expected := + candidateExprIdentityExprEq_sound _ _ h + +/-- A successful structural check yields the full recursive identity witness; +the Boolean contributes no semantic authority beyond these proved equalities. -/ +theorem CandidateExprIdentity.of_check + {trace : AddInductive.CandidateExprTrace candidateContext source} + (h : CandidateExprIdentity.check trace = true) : + CandidateExprIdentity trace := by + induction trace with + | terminal context source inferred result checked normalized => + simp only [CandidateExprIdentity.check] at h + exact .terminal (candidateExprIdentityExprEq_sound result source h) + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized domainCandidate + bodyCandidate domainIH bodyIH => + simp only [CandidateExprIdentity.check, Bool.and_eq_true] at h + exact .forallE domainCandidate bodyCandidate + (candidateExprIdentityExprEq_sound _ _ h.1.1.1) + (candidateExprIdentityExprEq_sound _ _ h.1.1.2) + (domainIH h.1.2) (bodyIH h.2) + +/-- An identity-normalizing trace necessarily preserves the stored main Pi +spine. This turns the recursive identity witness into the Boolean gate used +by the generation assembler. -/ +theorem CandidateExprIdentity.storedSpine + {trace : AddInductive.CandidateExprTrace candidateContext source} + (identity : CandidateExprIdentity trace) : + trace.storedSpine = true := by + induction identity with + | terminal => rfl + | forallE _ _ source_eq _ _ _ _ bodyIH => + simp [AddInductive.CandidateExprTrace.storedSpine, + source_eq, Expr.structuralEq_refl, bodyIH] + +/-- Exact component inversion for a strict translation of a kernel Pi. -/ +theorem TrExprS.forallE_components + (run : TrExprS env Us Δ (.forallE name domain body binderInfo) source') : + ∃ domain' body', + source' = .forallE domain' body' ∧ + env.IsType Us.length Δ.toCtx domain' ∧ + env.IsType Us.length (domain' :: Δ.toCtx) body' ∧ + TrExprS env Us Δ domain domain' ∧ + TrExprS env Us ((none, .vlam domain') :: Δ) body body' := by + cases run with + | forallE domainType bodyType domain_tr body_tr => + exact ⟨_, _, rfl, domainType, bodyType, domain_tr, body_tr⟩ + +/-- Recursively turn every retained candidate observation into verified +normalization evidence, constructing and transporting the exact verified +binder context at each Pi node. -/ +theorem CandidateExprRun.exists_ofCandidate + (trace : AddInductive.CandidateExprTrace candidateContext source) + (candidateRun : CandidateContextRun candidateContext) + (source' : VExpr) + (source_tr : candidateRun.context.TrExprS source source') + (whnfFuel : Nat) + (whnfDepth : candidateContext.fuel.recDepth = whnfFuel + 1) : + ∃ view' inferred', + Nonempty (CandidateExprRun candidateRun.context.venv + candidateRun.context.lparams trace candidateRun.context.vlctx + source' view' inferred') := by + induction trace generalizing source' with + | terminal context source inferred result checked normalized => + obtain ⟨inferred', result', _, _, ⟨node⟩⟩ := + CandidateNodeRun.exists_ofCandidate context source inferred result + checked normalized candidateRun.context candidateRun.context_eq + candidateRun.state_wf source' source_tr + context.fuel.recDepth whnfFuel rfl whnfDepth + exact ⟨result', inferred', ⟨.terminal node⟩⟩ + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized + domainCandidate bodyCandidate domainIH bodyIH => + obtain ⟨inferred', result', _, result_tr, ⟨node⟩⟩ := + CandidateNodeRun.exists_ofCandidate context source inferred + (.forallE name domain body binderInfo) checked normalized + candidateRun.context candidateRun.context_eq candidateRun.state_wf + source' source_tr context.fuel.recDepth whnfFuel rfl whnfDepth + let .forallE domainType bodyType domain_tr body_tr := result_tr + obtain ⟨u, domainTypeHasType⟩ := domainType + obtain ⟨v, bodyTypeHasType⟩ := bodyType + obtain ⟨domainView', domainInferred', ⟨domainRun⟩⟩ := + domainIH candidateRun _ domain_tr whnfDepth + obtain ⟨storedDomain', storedDomain_tr⟩ := + candidateTypeAnnotation_exists_translation annotations.trace domain_tr + let annotationsRun := IsDefEqRun.ofCandidateStep + ⟨context, domain, annotations.consumed⟩ annotationsEq + candidateRun.context candidateRun.context_eq rfl rfl rfl + candidateRun.state_wf domain_tr storedDomain_tr + context.fuel.recDepth rfl + have henv : VEnv.WF candidateRun.context.venv := + candidateRun.context.Ewf + have hΔ : OnCtx candidateRun.context.vlctx.toCtx + (candidateRun.context.venv.IsType + candidateRun.context.lparams.length) := + candidateRun.context.Δwf.toCtx + have annotationDef := + annotationsRun.isDefEqU.of_l henv hΔ domainTypeHasType + let bodyCandidateRun := candidateRun.pushLocalDecl name binderInfo + annotations.consumed fresh storedDomain' storedDomain_tr + ⟨u, annotationDef.hasType.2⟩ + have bodyVenv : bodyCandidateRun.context.venv = + candidateRun.context.venv := rfl + have bodyLparams : bodyCandidateRun.context.lparams = + candidateRun.context.lparams := rfl + have bodyVlctx : bodyCandidateRun.context.vlctx = + (some (context.freshFVarId, annotations.consumed.fvarsList), + .vlam storedDomain') :: candidateRun.context.vlctx := rfl + have bodyDepth : + (context.pushLocalDecl name binderInfo + annotations.consumed).fuel.recDepth = whnfFuel + 1 := by + simpa [AddInductive.Context.pushLocalDecl] using whnfDepth + have domainContext : VLCtx.IsDefEq + candidateRun.context.venv candidateRun.context.lparams.length + ((none, .vlam _) :: candidateRun.context.vlctx) + ((none, .vlam storedDomain') :: candidateRun.context.vlctx) := + .cons (.refl henv candidateRun.context.Δwf) (by nofun) + (.vlam annotationDef) + obtain ⟨storedBody', storedBody_tr⟩ := + body_tr.defeqDFC henv domainContext + have hRawBody : OnCtx + (_ :: candidateRun.context.vlctx.toCtx) + (candidateRun.context.venv.IsType + candidateRun.context.lparams.length) := + ⟨hΔ, ⟨u, domainTypeHasType⟩⟩ + have bodySource := + (body_tr.uniq henv domainContext storedBody_tr).of_l + henv hRawBody bodyTypeHasType + have bodyΔwf := bodyCandidateRun.context.Δwf + rw [bodyVenv, bodyLparams, bodyVlctx] at bodyΔwf + have instantiatedBody_tr := + storedBody_tr.inst_fvar henv.ordered bodyΔwf + obtain ⟨bodyView', bodyInferred', ⟨bodyRun⟩⟩ := + bodyIH bodyCandidateRun _ (by + change TrExprS bodyCandidateRun.context.venv + bodyCandidateRun.context.lparams bodyCandidateRun.context.vlctx + (body.instantiate1 context.freshExpr) _ + rw [bodyVenv, bodyLparams, bodyVlctx] + simpa only [AddInductive.Context.freshExpr, + Expr.instantiate1_eq] using instantiatedBody_tr) + bodyDepth + refine ⟨.forallE domainView' bodyView', inferred', ⟨?_⟩⟩ + exact .forallE annotations annotationsEq domainCandidate bodyCandidate node + domainRun annotationsRun bodyRun domainTypeHasType bodyTypeHasType + bodySource bodyVlctx + +/-- Interpret a recursively identity-normalizing candidate at the exact +strict Theory translation of its source. + +Unlike `exists_ofCandidate`, whose verified executions select an existential +Theory endpoint, this theorem retains `source'` as the endpoint at every +recursive position. That stronger conclusion is what the generation spine +assembler needs for declarations whose executable normalization is +syntactically the identity. -/ +theorem CandidateExprRun.exists_ofIdentity + (trace : AddInductive.CandidateExprTrace candidateContext source) + (identity : CandidateExprIdentity trace) + (candidateRun : CandidateContextRun candidateContext) + (source' : VExpr) + (source_tr : candidateRun.context.TrExprS source source') + (whnfFuel : Nat) + (whnfDepth : candidateContext.fuel.recDepth = whnfFuel + 1) : + ∃ inferred', Nonempty + (CandidateExprRun candidateRun.context.venv + candidateRun.context.lparams trace candidateRun.context.vlctx + source' source' inferred') := by + induction identity generalizing source' with + | @terminal result source context inferred checked normalized result_eq => + subst result + obtain ⟨inferred', ⟨node⟩⟩ := + CandidateNodeRun.exists_ofCandidateAtResult + context source inferred source checked normalized + candidateRun.context candidateRun.context_eq candidateRun.state_wf + source' source' source_tr source_tr + context.fuel.recDepth whnfFuel rfl whnfDepth + exact ⟨inferred', ⟨.terminal node⟩⟩ + | @forallE context domain name binderInfo source inferred body fresh + annotations annotationsEq checked normalized domainCandidate + bodyCandidate source_eq consumed_eq domainIdentity bodyIdentity + domainIH bodyIH => + subst source + obtain ⟨domain', body', rfl, domainWF, bodyWF, domain_tr, body_tr⟩ := + TypeChecker.TrExprS.forallE_components source_tr + obtain ⟨u, domainType⟩ := domainWF + obtain ⟨v, bodyType⟩ := bodyWF + obtain ⟨inferred', ⟨node⟩⟩ := + CandidateNodeRun.exists_ofCandidateAtResult + context (.forallE name domain body binderInfo) inferred + (.forallE name domain body binderInfo) checked normalized + candidateRun.context candidateRun.context_eq candidateRun.state_wf + (.forallE domain' body') (.forallE domain' body') + source_tr source_tr + context.fuel.recDepth whnfFuel rfl whnfDepth + obtain ⟨domainInferred', ⟨domainRun⟩⟩ := + domainIH candidateRun domain' domain_tr whnfDepth + have consumed_tr : candidateRun.context.TrExprS + annotations.consumed domain' := by + rw [consumed_eq] + exact domain_tr + let annotationsRun := IsDefEqRun.ofCandidateStep + ⟨context, domain, annotations.consumed⟩ annotationsEq + candidateRun.context candidateRun.context_eq rfl rfl rfl + candidateRun.state_wf domain_tr consumed_tr + context.fuel.recDepth rfl + let bodyCandidateRun := candidateRun.pushLocalDecl name binderInfo + annotations.consumed fresh domain' consumed_tr ⟨u, domainType⟩ + have bodyVenv : bodyCandidateRun.context.venv = + candidateRun.context.venv := rfl + have bodyLparams : bodyCandidateRun.context.lparams = + candidateRun.context.lparams := rfl + have bodyVlctx : bodyCandidateRun.context.vlctx = + (some (context.freshFVarId, annotations.consumed.fvarsList), + .vlam domain') :: candidateRun.context.vlctx := rfl + have bodyDepth : + (context.pushLocalDecl name binderInfo + annotations.consumed).fuel.recDepth = + whnfFuel + 1 := by + simpa [AddInductive.Context.pushLocalDecl] using whnfDepth + have bodyDeltaWF := bodyCandidateRun.context.Δwf + rw [bodyVenv, bodyLparams, bodyVlctx] at bodyDeltaWF + have instantiatedBody_tr := + body_tr.inst_fvar candidateRun.context.Ewf.ordered + bodyDeltaWF + obtain ⟨bodyInferred', ⟨bodyRun⟩⟩ := + bodyIH bodyCandidateRun body' (by + change TrExprS bodyCandidateRun.context.venv + bodyCandidateRun.context.lparams bodyCandidateRun.context.vlctx + (body.instantiate1 context.freshExpr) body' + rw [bodyVenv, bodyLparams, bodyVlctx] + simpa only [AddInductive.Context.freshExpr, + Expr.instantiate1_eq] using instantiatedBody_tr) + bodyDepth + refine ⟨inferred', ⟨?_⟩⟩ + exact .forallE annotations annotationsEq domainCandidate bodyCandidate + node domainRun annotationsRun bodyRun domainType bodyType bodyType rfl + +/-- Recover a trace root's strict source translation from its retained full +check. Unlike recursive child nodes, whose source translations are obtained +from the parent Pi translation, a root needs only the checker's syntactic +free-variable premise. -/ +theorem candidateExprTrace_exists_source_translation + (trace : AddInductive.CandidateExprTrace candidateContext source) + (candidateRun : CandidateContextRun candidateContext) + (source_fvars : + source.FVarsIn (· ∈ candidateRun.context.vlctx.fvars)) : + ∃ source', candidateRun.context.TrExprS source source' := by + let checked := trace.rootCheck + obtain ⟨source', _, source_tr, _, _⟩ := + candidateCheckTypeStep_exists_translation + ⟨candidateContext, source, checked.inferred⟩ checked.valid + candidateRun.context candidateRun.context_eq candidateRun.state_wf + source_fvars candidateContext.fuel.recDepth rfl + exact ⟨source', source_tr⟩ + +/-- Recursively certify an annotation-complete candidate trace without asking +the caller for any Theory expression. The retained root full check chooses the +source translation; all output and child translations then come from verified +checker executions, structural annotation traces, and Pi decomposition. -/ +theorem CandidateExprRun.exists_ofCandidateFVars + (trace : AddInductive.CandidateExprTrace candidateContext source) + (candidateRun : CandidateContextRun candidateContext) + (source_fvars : + source.FVarsIn (· ∈ candidateRun.context.vlctx.fvars)) + (whnfFuel : Nat) + (whnfDepth : candidateContext.fuel.recDepth = whnfFuel + 1) : + ∃ source' view' inferred', + candidateRun.context.TrExprS source source' ∧ + Nonempty (CandidateExprRun candidateRun.context.venv + candidateRun.context.lparams trace candidateRun.context.vlctx + source' view' inferred') := by + obtain ⟨source', source_tr⟩ := + candidateExprTrace_exists_source_translation trace candidateRun + source_fvars + obtain ⟨view', inferred', run⟩ := + CandidateExprRun.exists_ofCandidate trace candidateRun source' + source_tr whnfFuel whnfDepth + exact ⟨source', view', inferred', source_tr, run⟩ + +/-- Fold a complete candidate trace into the compositional equality language +consumed by `NormalizationRun` and `GenerationRun`. -/ +theorem CandidateExprRun.evidence + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} : + CandidateExprRun env Us trace Δ source' view' inferred' → + DefEqEvidence env Us.length Δ.toCtx source' view' inferred' + | .terminal node => node.evidence + | .forallE _ _ _ _ node domainRun annotationsRun bodyRun domainType + bodyType bodySource bodyContext => by + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + have hΔ : VLCtx.WF env Us.length Δ := by + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + have hΓ : OnCtx Δ.toCtx (env.IsType Us.length) := hΔ.toCtx + have domainEvidence := domainRun.evidence + obtain ⟨_, domainTypeEq⟩ := + domainType.uniq henv hΓ domainEvidence.isDefEq + have domainAtSort : DefEqEvidence env Us.length Δ.toCtx + _ _ (.sort _) := + .change domainTypeEq.symm domainEvidence + have annotationDef := + annotationsRun.isDefEqU.of_l henv hΓ domainType + have domainContext : VLCtx.IsDefEq env Us.length + ((none, .vlam _) :: Δ) ((none, .vlam _) :: Δ) := + .cons (.refl henv hΔ) (by nofun) (.vlam annotationDef) + have bodyEvidence := bodyRun.evidence + rw [bodyContext] at bodyEvidence + simp only [VLCtx.toCtx] at bodyEvidence + have bodyStoredType := + bodySource.hasType.2.defeqDFC henv domainContext.defeqCtx + have hBodyΓ : OnCtx (_ :: Δ.toCtx) (env.IsType Us.length) := + ⟨hΓ, ⟨_, annotationDef.hasType.2⟩⟩ + obtain ⟨_, bodyTypeEq⟩ := + bodyStoredType.uniq henv hBodyΓ bodyEvidence.isDefEq + have bodyAtSortStored : DefEqEvidence env Us.length + (_ :: Δ.toCtx) _ _ (.sort _) := + .change bodyTypeEq.symm bodyEvidence + have bodyAtSortRaw := + bodyAtSortStored.isDefEq.defeqDFC henv + (domainContext.symm henv).defeqCtx + have bodyFinal := bodySource.trans bodyAtSortRaw + have piEvidence := DefEqEvidence.forallE domainAtSort + (DefEqEvidence.ofDefEq bodyFinal) + obtain ⟨_, nodeTypeEq⟩ := + node.evidence.isDefEq.uniq henv hΓ (domainType.forallE bodyType) + exact .trans node.evidence (.change nodeTypeEq.symm piEvidence) + +/-- The raw root of a recursively interpreted trace has the strict Theory +translation retained by its paired full-check run. -/ +theorem CandidateExprRun.source_tr + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') : + TrExprS env Us Δ source source' := by + cases run with + | terminal node => exact node.check.expr_tr + | forallE _ _ _ _ node => exact node.check.expr_tr + +/-- Move a weak expression translation between definitionally equal verified +local contexts while retaining its named Theory meaning. -/ +private theorem candidateTrExpr_moveCtx + (henv : VEnv.WF env) + (hctx : VLCtx.IsDefEq env Us.length Δ₁ Δ₂) + (H : TrExpr env Us Δ₁ e e') : + TrExpr env Us Δ₂ e e' := by + obtain ⟨e₂, he₂, hdef⟩ := H + have moved : TrExpr env Us Δ₂ e e₂ := + he₂.defeqDFC' henv hctx + exact moved.defeq henv (hctx.symm henv).wf.toCtx + (hdef.defeqDFC henv hctx.defeqCtx) + +/-- The recursively reconstructed kernel candidate view translates to the +Theory view named by `CandidateExprRun`. + +At Pi nodes the instantiated child body is first abstracted from its exact +free-variable context and then transported from the raw-domain context to the +definitionally equal normalized-domain context. This closes the provenance +loop: the emitted Theory equality is not only between two well-typed terms; +both endpoints are translations of the source-indexed candidate syntax. -/ +theorem CandidateExprRun.view_tr + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') : + TrExpr env Us Δ trace.view view' := by + induction run with + | @terminal Δ context source inferred result source' result' inferred' + checked normalized node => + have henv : VEnv.WF env := by + simpa only [node.whnf.venv_eq] using node.whnf.context.Ewf + have hΔ : VLCtx.WF env Us.length Δ := by + simpa only [node.whnf.venv_eq, node.whnf.lparams_eq, + node.whnf.vlctx_eq] using node.whnf.context.Δwf + simpa only [AddInductive.CandidateExprTrace.view] using + node.whnf.rhs_tr.trExpr henv hΔ + | @forallE domain context name binderInfo Δ source inferred body + source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyΔ storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate + bodyCandidate node domainRun annotationsRun bodyRun domainType bodyType + bodySource bodyContext domainIH bodyIH => + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + have hΔ : VLCtx.WF env Us.length Δ := by + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + obtain ⟨_, domainTypeEq⟩ := + domainType.uniq henv hΔ.toCtx domainRun.evidence.isDefEq + have domainDef : env.IsDefEq Us.length Δ.toCtx + domain' domainView' (.sort u) := + (DefEqEvidence.change domainTypeEq.symm domainRun.evidence).isDefEq + have annotationDef := + annotationsRun.isDefEqU.of_l henv hΔ.toCtx domainType + have storedToView : env.IsDefEq Us.length Δ.toCtx + storedDomain' domainView' (.sort u) := + annotationDef.symm.trans domainDef + have bodyIH' : TrExpr env Us + ((some (context.freshFVarId, + annotations.consumed.fvarsList), .vlam storedDomain') :: Δ) + bodyCandidate.view bodyView' := by + simpa only [bodyContext] using bodyIH + have bodyAbstract := bodyIH'.abstract VLCtx.Abstract.zero + have hctx : VLCtx.IsDefEq env Us.length + ((none, .vlam storedDomain') :: Δ) + ((none, .vlam domainView') :: Δ) := + .cons (.refl henv hΔ) (by nofun) + (.vlam storedToView) + have bodyMoved := candidateTrExpr_moveCtx henv hctx bodyAbstract + have bodyEvidence := bodyRun.evidence + rw [bodyContext] at bodyEvidence + simp only [VLCtx.toCtx] at bodyEvidence + have annotationContext : VLCtx.IsDefEq env Us.length + ((none, .vlam domain') :: Δ) + ((none, .vlam storedDomain') :: Δ) := + .cons (.refl henv hΔ) (by nofun) (.vlam annotationDef) + have bodyStoredType := + bodySource.hasType.2.defeqDFC henv annotationContext.defeqCtx + have hBodyΓ : OnCtx (storedDomain' :: Δ.toCtx) + (env.IsType Us.length) := + ⟨hΔ.toCtx, ⟨_, annotationDef.hasType.2⟩⟩ + obtain ⟨_, bodyTypeEq⟩ := + bodyStoredType.uniq henv hBodyΓ bodyEvidence.isDefEq + have bodyDefStored : env.IsDefEq Us.length + (storedDomain' :: Δ.toCtx) storedBody' bodyView' (.sort v) := + (DefEqEvidence.change bodyTypeEq.symm bodyEvidence).isDefEq + have bodyDefMoved := + bodyDefStored.defeqDFC henv hctx.defeqCtx + have habstract : + bodyCandidate.view.abstract #[context.freshExpr] = + Expr.abstract1 context.freshFVarId bodyCandidate.view := by + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl] + simp only [Expr.abstract_eq, Expr.abstractList] + apply TrExpr.forallE henv hΔ + · exact ⟨_, domainDef.hasType.2⟩ + · exact ⟨_, bodyDefMoved.hasType.2⟩ + · exact domainIH + · simpa only [AddInductive.CandidateExprTrace.view, + habstract] using bodyMoved + +/-- Exact-translation uniqueness for every expression that contributes to a +candidate view. The abstracted-body clause names the syntax stored by +`CandidateExprTrace.view`, while the recursive body clause supports the next +candidate node. Projections are intentionally excluded: their verified +Theory relation is only unique up to definitional equality. -/ +def CandidateExprTraceViewIsUnique : + {context : AddInductive.Context} → {source : Expr} → + AddInductive.CandidateExprTrace context source → Prop + | _, _, .terminal _ _ _ result _ _ => TrExprS.IsUnique result + | _, _, .forallE context _ _ _ _ _ _ _ _ _ _ _ domain body => + CandidateExprTraceViewIsUnique domain ∧ + CandidateExprTraceViewIsUnique body ∧ + TrExprS.IsUnique (body.view.abstract #[context.freshExpr]) + +/-- The recursive uniqueness certificate in particular covers the complete +view reconstructed at this candidate node. -/ +theorem CandidateExprTraceViewIsUnique.view + {context : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace context source} + (unique : CandidateExprTraceViewIsUnique trace) : + TrExprS.IsUnique trace.view := by + induction trace with + | terminal => exact unique + | forallE context source inferred name domain body binderInfo fresh + annotations annotationsEq checked normalized domainCandidate bodyCandidate + domainIH bodyIH => + exact ⟨domainIH unique.1, unique.2.2⟩ + +/-- A projection-free candidate view retains the strict Theory translation +selected componentwise by its recursive semantic run. + +The ordinary `view_tr` theorem must use weak translation because a projection +endpoint is only definitionally determined. Under the explicit uniqueness +condition, recursive abstraction and context transport select the exact +analyzer-owned expression instead. -/ +theorem CandidateExprRun.view_tr_strict + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') + (unique : CandidateExprTraceViewIsUnique trace) : + TrExprS env Us Δ trace.view view' := by + induction run with + | terminal node => + simpa only [AddInductive.CandidateExprTrace.view] using + node.whnf.rhs_tr + | @forallE domain context name binderInfo Δ source inferred body + source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyΔ storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate + bodyCandidate node domainRun annotationsRun bodyRun domainType bodyType + bodySource bodyContext domainIH bodyIH => + rcases unique with ⟨domainUnique, bodyUnique, abstractUnique⟩ + have domainStrict := domainIH domainUnique + have bodyStrict : TrExprS env Us + ((some (context.freshFVarId, + annotations.consumed.fvarsList), .vlam storedDomain') :: Δ) + bodyCandidate.view bodyView' := by + simpa only [bodyContext] using bodyIH bodyUnique + have bodyAbstract := bodyStrict.abstract VLCtx.Abstract.zero + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + have hΔ : VLCtx.WF env Us.length Δ := by + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + obtain ⟨_, domainTypeEq⟩ := + domainType.uniq henv hΔ.toCtx domainRun.evidence.isDefEq + have domainDef : env.IsDefEq Us.length Δ.toCtx + domain' domainView' (.sort u) := + (DefEqEvidence.change domainTypeEq.symm domainRun.evidence).isDefEq + have annotationDef := + annotationsRun.isDefEqU.of_l henv hΔ.toCtx domainType + have storedToView : env.IsDefEq Us.length Δ.toCtx + storedDomain' domainView' (.sort u) := + annotationDef.symm.trans domainDef + have hctx : VLCtx.IsDefEq env Us.length + ((none, .vlam storedDomain') :: Δ) + ((none, .vlam domainView') :: Δ) := + .cons (.refl henv hΔ) (by nofun) (.vlam storedToView) + obtain ⟨bodyMoved', bodyMoved⟩ := + bodyAbstract.defeqDFC henv hctx + have habstract : + bodyCandidate.view.abstract #[context.freshExpr] = + Expr.abstract1 context.freshFVarId bodyCandidate.view := by + rw [show #[context.freshExpr] = + ⟨[context.freshFVarId].map Expr.fvar⟩ by rfl] + simp only [Expr.abstract_eq, Expr.abstractList] + have bodyAbstractArray : TrExprS env Us + ((none, .vlam storedDomain') :: Δ) + (bodyCandidate.view.abstract #[context.freshExpr]) bodyView' := by + simpa only [habstract] using bodyAbstract + have bodyMovedArray : TrExprS env Us + ((none, .vlam domainView') :: Δ) + (bodyCandidate.view.abstract #[context.freshExpr]) bodyMoved' := by + simpa only [habstract] using bodyMoved + have bodyMoved_eq : bodyMoved' = bodyView' := by + exact (bodyAbstractArray.unique' + (.cons .base .vlam) abstractUnique bodyMovedArray).symm + subst bodyMoved' + have bodyEvidence := bodyRun.evidence + rw [bodyContext] at bodyEvidence + simp only [VLCtx.toCtx] at bodyEvidence + have annotationContext : VLCtx.IsDefEq env Us.length + ((none, .vlam domain') :: Δ) + ((none, .vlam storedDomain') :: Δ) := + .cons (.refl henv hΔ) (by nofun) (.vlam annotationDef) + have bodyStoredType := + bodySource.hasType.2.defeqDFC henv annotationContext.defeqCtx + have hBodyΓ : OnCtx (storedDomain' :: Δ.toCtx) + (env.IsType Us.length) := + ⟨hΔ.toCtx, ⟨_, annotationDef.hasType.2⟩⟩ + obtain ⟨_, bodyTypeEq⟩ := + bodyStoredType.uniq henv hBodyΓ bodyEvidence.isDefEq + have bodyDefStored : env.IsDefEq Us.length + (storedDomain' :: Δ.toCtx) storedBody' bodyView' (.sort v) := + (DefEqEvidence.change bodyTypeEq.symm bodyEvidence).isDefEq + have bodyDefMoved := + bodyDefStored.defeqDFC henv hctx.defeqCtx + simpa only [AddInductive.CandidateExprTrace.view, habstract] using + TrExprS.forallE + (⟨u, domainDef.hasType.2⟩ : + env.IsType Us.length Δ.toCtx domainView') + (⟨v, bodyDefMoved.hasType.2⟩ : + env.IsType Us.length (domainView' :: Δ.toCtx) bodyView') + domainStrict bodyMoved + +/-- Root-level verified context and translations for an exact executable +candidate expression and an explicitly named Theory view. + +The raw endpoint is a strict translation of the stored kernel source. The +view endpoint translates the exact reconstructed candidate syntax; allowing +the ordinary `TrExpr` relation here accounts for the definitional transport +performed while recursively rebuilding Pi bodies. -/ +structure CandidateExprRootRun (env : VEnv) (Us : List Name) + {source : Expr} (candidate : AddInductive.CandidateExpr source) + (source' view' : VExpr) where + contextRun : CandidateContextRun candidate.context + venv_eq : contextRun.context.venv = env + lparams_eq : contextRun.context.lparams = Us + vlctx_eq : contextRun.context.vlctx = [] + source_tr : TrExprS env Us [] source source' + view_tr : TrExpr env Us [] candidate.view view' + whnfFuel : Nat + whnfDepth : candidate.context.fuel.recDepth = whnfFuel + 1 + +/-- Interpret a root candidate against its explicitly translated endpoints. +The candidate view is not selected from a proof-only existential: the caller +names it and proves that it translates the exact executable view, while the +verified recursive run supplies the equality to the strict raw endpoint. -/ +theorem CandidateExprRootRun.evidence + {env : VEnv} {Us : List Name} {source : Expr} + {candidate : AddInductive.CandidateExpr source} + {source' view' : VExpr} + (run : CandidateExprRootRun env Us candidate source' view') : + ∃ A, DefEqEvidence env Us.length [] source' view' A := by + have source_tr : run.contextRun.context.TrExprS source source' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.source_tr + obtain ⟨candidateView', inferred', ⟨candidateRun⟩⟩ := + CandidateExprRun.exists_ofCandidate candidate.trace run.contextRun + source' source_tr run.whnfFuel run.whnfDepth + have henv : VEnv.WF env := by + simpa only [run.venv_eq] using run.contextRun.context.Ewf + have hΔ : VLCtx.WF env Us.length [] := by + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq] using + run.contextRun.context.Δwf + have candidateView_tr : + TrExpr env Us [] candidate.view candidateView' := by + simpa only [AddInductive.CandidateExpr.view, run.venv_eq, + run.lparams_eq, run.vlctx_eq] using + candidateRun.view_tr + have viewDef : env.IsDefEqU Us.length [] candidateView' view' := + candidateView_tr.uniq henv (.refl henv hΔ) run.view_tr + have sourceDef : env.IsDefEqU Us.length [] source' candidateView' := by + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq, + VLCtx.toCtx] using + candidateRun.evidence.isDefEq.toU + obtain ⟨A, hfinal⟩ := sourceDef.trans henv hΔ.toCtx viewDef + exact ⟨A, .ofDefEq hfinal⟩ + +/-- A root candidate together with the exact recursively interpreted semantic +run selected by its retained checker executions. + +Unlike `CandidateExprRootRun`, this bundle does not stop at whole-expression +equality: it retains the exact inferred type and reconstructed Theory view at +every recursive candidate position. Consequently the same value can supply +both normalization evidence and, when the executable trace preserves its main +Pi spine, the positional telescope/result evidence required by generation. +The view is selected by the verified run rather than supplied independently by +a caller. -/ +structure CandidateExprSemanticRootRun (env : VEnv) (Us : List Name) + {source : Expr} (candidate : AddInductive.CandidateExpr source) + (source' : VExpr) where + contextRun : CandidateContextRun candidate.context + venv_eq : contextRun.context.venv = env + lparams_eq : contextRun.context.lparams = Us + vlctx_eq : contextRun.context.vlctx = [] + source_tr : TrExprS env Us [] source source' + whnfFuel : Nat + whnfDepth : candidate.context.fuel.recDepth = whnfFuel + 1 + view : VExpr + recursive : ∃ inferred, CandidateExprRun env Us candidate.trace [] + source' view inferred + +/-- Forget the retained recursive run and expose the existing root semantic +interface. The reconstructed view translation is derived from that same run, +so it cannot name an unrelated endpoint. -/ +def CandidateExprSemanticRootRun.root + (run : CandidateExprSemanticRootRun env Us candidate source') : + CandidateExprRootRun env Us candidate source' run.view where + contextRun := run.contextRun + venv_eq := run.venv_eq + lparams_eq := run.lparams_eq + vlctx_eq := run.vlctx_eq + source_tr := run.source_tr + view_tr := by + obtain ⟨_, recursive⟩ := run.recursive + simpa only [AddInductive.CandidateExpr.view] using + recursive.view_tr + whnfFuel := run.whnfFuel + whnfDepth := run.whnfDepth + +/-- Automatically construct the retained root semantics from an exact +verified candidate context and strict translation of the stored kernel +source. + +The checker run selects the Theory view and inferred type existentially; the +result records those exact selections. No caller-selected normalization view, +erasure equality, or whole-Pi injectivity principle is used. -/ +theorem CandidateExprSemanticRootRun.exists_ofCandidate + {env : VEnv} {Us : List Name} {source : Expr} + {candidate : AddInductive.CandidateExpr source} {source' : VExpr} + (contextRun : CandidateContextRun candidate.context) + (venv_eq : contextRun.context.venv = env) + (lparams_eq : contextRun.context.lparams = Us) + (vlctx_eq : contextRun.context.vlctx = []) + (source_tr : TrExprS env Us [] source source') + (whnfFuel : Nat) + (whnfDepth : candidate.context.fuel.recDepth = whnfFuel + 1) : + Nonempty (CandidateExprSemanticRootRun env Us candidate source') := by + have contextualSource : + contextRun.context.TrExprS source source' := by + simpa only [VContext.TrExprS, venv_eq, lparams_eq, vlctx_eq] using + source_tr + obtain ⟨view, inferred, ⟨recursive⟩⟩ := + CandidateExprRun.exists_ofCandidate candidate.trace contextRun source' + contextualSource whnfFuel whnfDepth + refine ⟨{ + contextRun := contextRun + venv_eq := venv_eq + lparams_eq := lparams_eq + vlctx_eq := vlctx_eq + source_tr := source_tr + whnfFuel := whnfFuel + whnfDepth := whnfDepth + view := view + recursive := ⟨inferred, ?_⟩ }⟩ + simpa only [venv_eq, lparams_eq, vlctx_eq] using recursive + +/-- The exact pre-run evidence needed to interpret one candidate root without +asking a caller to choose its normalized Theory view. + +This bundle deliberately stops before the recursive semantic run. It contains +only the verified implementation context, its alignment with the requested +Theory environment, the strict translation of the stored source, and the fuel +relation consumed by `CandidateExprRun.exists_ofCandidate`. -/ +structure CandidateExprSemanticRootInput (env : VEnv) (Us : List Name) + {source : Expr} (candidate : AddInductive.CandidateExpr source) + (source' : VExpr) where + contextRun : CandidateContextRun candidate.context + venv_eq : contextRun.context.venv = env + lparams_eq : contextRun.context.lparams = Us + vlctx_eq : contextRun.context.vlctx = [] + source_tr : TrExprS env Us [] source source' + whnfFuel : Nat + whnfDepth : candidate.context.fuel.recDepth = whnfFuel + 1 + +/-- Run the retained checker interpreter on an exact root input. The result is +`Nonempty` because the checker-selected Theory view is semantic evidence rather +than executable metadata; no choice operator or caller-supplied endpoint is +introduced by this boundary. -/ +theorem CandidateExprSemanticRootInput.exists + (input : CandidateExprSemanticRootInput env Us candidate source') : + Nonempty (CandidateExprSemanticRootRun env Us candidate source') := + CandidateExprSemanticRootRun.exists_ofCandidate input.contextRun + input.venv_eq input.lparams_eq input.vlctx_eq input.source_tr + input.whnfFuel input.whnfDepth + +/-- Interpret an identity-normalizing staged root at the strict Theory +translation already owned by its source input. This keeps the endpoint +definitionally fixed without caller-supplied WHNF data or a +`Classical.choice` over the general semantic interpreter. -/ +def CandidateExprSemanticRootInput.semanticOfIdentity + {env : VEnv} {Us : List Name} {source : Expr} + {candidate : AddInductive.CandidateExpr source} {source' : VExpr} + (input : CandidateExprSemanticRootInput env Us candidate source') + (identity : CandidateExprIdentity candidate.trace) : + CandidateExprSemanticRootRun env Us candidate source' where + contextRun := input.contextRun + venv_eq := input.venv_eq + lparams_eq := input.lparams_eq + vlctx_eq := input.vlctx_eq + source_tr := input.source_tr + whnfFuel := input.whnfFuel + whnfDepth := input.whnfDepth + view := source' + recursive := by + have source_tr : input.contextRun.context.TrExprS source source' := by + simpa only [VContext.TrExprS, input.venv_eq, input.lparams_eq, + input.vlctx_eq] using input.source_tr + obtain ⟨inferred, ⟨recursive⟩⟩ := + CandidateExprRun.exists_ofIdentity candidate.trace identity + input.contextRun source' source_tr input.whnfFuel input.whnfDepth + refine ⟨inferred, ?_⟩ + simpa only [input.venv_eq, input.lparams_eq, input.vlctx_eq] using + recursive + +/-- Interpret a staged root at the deterministic translation of its +checker-selected view. For a projection-free view the recursive semantic +run's endpoint is pinned by strict-translation agreement +(`CandidateExprRun.view_tr_strict` plus `TrExprS.trExprS?_eq`), so the +retained `view` field is computed by `trExprS?` and the `Nonempty` +interpretation is transferred onto it; no choice operator selects data. +Unlike `semanticOfIdentity` this covers non-identity normalizations, at the +cost of the executable view-uniqueness certificate. -/ +def CandidateExprSemanticRootInput.semanticOfUnique + {env : VEnv} {Us : List Name} {source : Expr} + {candidate : AddInductive.CandidateExpr source} {source' : VExpr} + (input : CandidateExprSemanticRootInput env Us candidate source') + (unique : CandidateExprTraceViewIsUnique candidate.trace) : + CandidateExprSemanticRootRun env Us candidate source' := + match hview : trExprS? Us [] candidate.trace.view with + | some view => + { contextRun := input.contextRun + venv_eq := input.venv_eq + lparams_eq := input.lparams_eq + vlctx_eq := input.vlctx_eq + source_tr := input.source_tr + whnfFuel := input.whnfFuel + whnfDepth := input.whnfDepth + view := view + recursive := by + obtain ⟨w⟩ := input.exists + obtain ⟨inferred, run⟩ := w.recursive + cases Option.some.inj + (((run.view_tr_strict unique).trExprS?_eq unique.view).symm.trans + hview) + exact ⟨inferred, run⟩ } + | none => + absurd + (show (trExprS? Us [] candidate.trace.view).isSome by + obtain ⟨w⟩ := input.exists + obtain ⟨inferred, run⟩ := w.recursive + exact TrExprS.trExprS?_isSome + ⟨w.view, run.view_tr_strict unique⟩ unique.view) + (by simp [hview]) + +/-- One explicitly verified root stage shared by every candidate expression +interpreted before or after family insertion. + +The stage owns the implementation/Theory context alignment once. Individual +source positions retain only their strict translation, fuel relation, and the +equality identifying the candidate's stored context with this stage. This is +the reusable boundary between staged environment validation and the retained +recursive candidate interpreter. -/ +structure CandidateSemanticStage + (candidateContext : AddInductive.Context) (env : VEnv) (Us : List Name) + where + contextRun : CandidateContextRun candidateContext + venv_eq : contextRun.context.venv = env + lparams_eq : contextRun.context.lparams = Us + vlctx_eq : contextRun.context.vlctx = [] + +/-- Source-position evidence interpreted in one shared candidate stage. + +`context_eq` prevents a verified stage for another producer position from +being reused. The normalized Theory endpoint is deliberately absent: it is +selected only by `CandidateExprSemanticRootInput.exists`. -/ +structure CandidateExprStagedInput + {candidateContext : AddInductive.Context} {env : VEnv} {Us : List Name} + (stage : CandidateSemanticStage candidateContext env Us) + {source : Expr} (candidate : AddInductive.CandidateExpr source) + (source' : VExpr) where + context_eq : candidateContext = candidate.context + source_tr : TrExprS env Us [] source source' + whnfFuel : Nat + whnfDepth : candidate.context.fuel.recDepth = whnfFuel + 1 + +/-- Specialize a shared verified stage to one exact source-indexed candidate +root. This is a pure dependent transport; it neither runs the checker nor +chooses the semantic view. -/ +def CandidateExprStagedInput.rootInput + {candidateContext : AddInductive.Context} {env : VEnv} {Us : List Name} + {source : Expr} {candidate : AddInductive.CandidateExpr source} + {source' : VExpr} + {stage : CandidateSemanticStage candidateContext env Us} + (input : CandidateExprStagedInput stage candidate source') : + CandidateExprSemanticRootInput env Us candidate source' := by + cases input.context_eq + exact { + contextRun := stage.contextRun + venv_eq := stage.venv_eq + lparams_eq := stage.lparams_eq + vlctx_eq := stage.vlctx_eq + source_tr := input.source_tr + whnfFuel := input.whnfFuel + whnfDepth := input.whnfDepth } + +/-- Pointwise checker-produced equality for a pair of binder telescopes. The +tail is checked in the context extended by the raw binder, exactly matching +`VEnv.TelDefEq` and the mixed generator's raw-binder discipline. -/ +inductive TelDefEqEvidence (env : VEnv) (U : Nat) : + List VExpr → List VExpr → List VExpr → Prop where + | nil : TelDefEqEvidence env U Γ [] [] + | cons + (head : DefEqEvidence env U Γ A A' (.sort u)) + (tail : TelDefEqEvidence env U (A :: Γ) As As') : + TelDefEqEvidence env U Γ (A :: As) (A' :: As') + +/-- Interpret pointwise checker evidence as the Theory telescope equality +consumed by `GenerationChecked.WF`. -/ +theorem TelDefEqEvidence.telDefEq : + TelDefEqEvidence env U Γ As As' → + env.TelDefEq U Γ As As' + | .nil => trivial + | .cons head tail => ⟨⟨_, head.isDefEq⟩, tail.telDefEq⟩ + +/-- Pointwise telescope equality followed by equality of the terminal result. + +Keeping these witnesses in one inductive preserves the raw-binder context at +every recursive step. In particular, the result is checked in +`rawBinders.reverse ++ Γ`, exactly the context used by mixed generation. -/ +inductive TelResultDefEqEvidence (env : VEnv) (U : Nat) : + (Γ : List VExpr) → (rawBinders viewBinders : List VExpr) → + (rawResult viewResult resultType : VExpr) → Prop where + | terminal + (result : DefEqEvidence env U Γ rawResult viewResult resultType) : + TelResultDefEqEvidence env U Γ [] [] rawResult viewResult resultType + | forallE + (domain : DefEqEvidence env U Γ rawDomain viewDomain (.sort u)) + (tail : TelResultDefEqEvidence env U (rawDomain :: Γ) + rawBinders viewBinders rawResult viewResult resultType) : + TelResultDefEqEvidence env U Γ + (rawDomain :: rawBinders) (viewDomain :: viewBinders) + rawResult viewResult resultType + +/-- Telescope component of a combined spine/result certificate. -/ +theorem TelResultDefEqEvidence.telescope : + TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult resultType → + TelDefEqEvidence env U Γ rawBinders viewBinders + | .terminal _ => .nil + | .forallE domain tail => .cons domain tail.telescope + +/-- Terminal component, in the context generated by all raw binders. -/ +theorem TelResultDefEqEvidence.result : + TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult resultType → + DefEqEvidence env U (rawBinders.reverse ++ Γ) + rawResult viewResult resultType + | .terminal result => by simpa using result + | .forallE _ tail => by + simpa [List.reverse_cons, List.append_assoc] using tail.result + +theorem TelResultDefEqEvidence.length_eq : + TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult resultType → + rawBinders.length = viewBinders.length + | .terminal _ => rfl + | .forallE _ tail => congrArg Nat.succ tail.length_eq + +/-- Reify a Theory telescope equality as explicit checker-produced evidence. +This direction is useful after telescope operations such as `take`, `drop`, +and context transport have rearranged a candidate certificate. -/ +theorem TelDefEqEvidence.ofTelDefEq : + ∀ {Γ As As'}, env.TelDefEq U Γ As As' → + TelDefEqEvidence env U Γ As As' + | _, [], [], _ => .nil + | _, _ :: _, _ :: _, ⟨⟨_, head⟩, tail⟩ => + .cons (.ofDefEq head) (TelDefEqEvidence.ofTelDefEq tail) + +/-- Retain an exact prefix of a checker-produced telescope certificate. -/ +theorem TelDefEqEvidence.take + (run : TelDefEqEvidence env U Γ As As') (n : Nat) : + TelDefEqEvidence env U Γ (As.take n) (As'.take n) := + .ofTelDefEq (run.telDefEq.take n) + +/-- Transport a checker-produced telescope certificate through environment +growth. -/ +theorem TelDefEqEvidence.mono + (run : TelDefEqEvidence env U Γ As As') (henv : env ≤ env') : + TelDefEqEvidence env' U Γ As As' := + .ofTelDefEq (run.telDefEq.mono henv) + +/-- Combine an independently transformed telescope certificate with its +terminal result certificate. -/ +theorem TelResultDefEqEvidence.ofTelescopeResult + (tel : TelDefEqEvidence env U Γ rawBinders viewBinders) + (result : DefEqEvidence env U (rawBinders.reverse ++ Γ) + rawResult viewResult resultType) : + TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult resultType := by + induction tel with + | nil => exact .terminal (by simpa using result) + | cons head tail ih => + exact .forallE head (ih (by + simpa [List.reverse_cons, List.append_assoc] using result)) + +private theorem candidateDefEqCtx_trans (henv : VEnv.WF env) : + ∀ {Γ₁ Γ₂ Γ₃}, + env.IsDefEqCtx U [] Γ₁ Γ₂ → + env.IsDefEqCtx U [] Γ₂ Γ₃ → + env.IsDefEqCtx U [] Γ₁ Γ₃ + | _, _, _, .zero, h₂₃ => h₂₃ + | _, _, _, .succ h₁₂ head₁₂, .succ h₂₃ head₂₃ => by + have tail := candidateDefEqCtx_trans henv h₁₂ h₂₃ + have head₂₃' := head₂₃.defeqDFC henv (h₁₂.symm henv) + exact .succ tail (VEnv.IsDefEq.trans_l henv h₁₂.isType + head₁₂ head₂₃') + +private theorem candidateTelDefEq_defeqDFC (henv : VEnv.WF env) + (hctx : env.IsDefEqCtx U [] Γ₁ Γ₂) : + ∀ {As As'}, env.TelDefEq U Γ₁ As As' → + env.TelDefEq U Γ₂ As As' + | [], [], _ => trivial + | _ :: _, _ :: _, ⟨⟨u, head⟩, tail⟩ => + ⟨⟨u, head.defeqDFC henv hctx⟩, + candidateTelDefEq_defeqDFC henv + (.succ hctx head.hasType.1) tail⟩ + +private theorem candidateTelDefEq_append + {env : VEnv} {U : Nat} {Γ : List VExpr} : + ∀ {As As' Bs Bs'}, env.TelDefEq U Γ As As' → + env.TelDefEq U (As.reverse ++ Γ) Bs Bs' → + env.TelDefEq U Γ (As ++ Bs) (As' ++ Bs') + | [], [], _, _, _, suffix => by simpa using suffix + | _ :: As, _ :: As', Bs, Bs', ⟨head, tail⟩, suffix => by + exact ⟨head, candidateTelDefEq_append tail (by + simpa [List.reverse_cons, List.append_assoc] using suffix)⟩ + +/-- Replace a constructor candidate's stored parameter prefix by the family's +raw parameter prefix. + +The two raw prefixes need not be syntactically equal: both are related to the +same checked view prefix. The field telescope and terminal result are then +transported through the induced context equality, yielding exactly the mixed +raw/view context emitted by generation. -/ +theorem TelResultDefEqEvidence.replacePrefix + (henv : VEnv.WF env) + (newPrefix : TelDefEqEvidence env U [] newRawPrefix viewPrefix) + (run : TelResultDefEqEvidence env U [] + (oldRawPrefix ++ rawSuffix) (viewPrefix ++ viewSuffix) + rawResult viewResult resultType) + (prefixLength : oldRawPrefix.length = viewPrefix.length) : + TelResultDefEqEvidence env U [] + (newRawPrefix ++ rawSuffix) (viewPrefix ++ viewSuffix) + rawResult viewResult resultType := by + have declaredTel := run.telescope.telDefEq + have oldPrefix : env.TelDefEq U [] oldRawPrefix viewPrefix := by + have hprefix := declaredTel.take oldRawPrefix.length + simpa [prefixLength] using hprefix + have oldSuffix : env.TelDefEq U oldRawPrefix.reverse + rawSuffix viewSuffix := by + have suffix := declaredTel.drop oldRawPrefix.length + simpa [prefixLength] using suffix + have newPrefixTheory := newPrefix.telDefEq + have newPrefixContext : env.IsDefEqCtx U [] + newRawPrefix.reverse viewPrefix.reverse := by + simpa using newPrefixTheory.ctx + have oldPrefixContext : env.IsDefEqCtx U [] + oldRawPrefix.reverse viewPrefix.reverse := by + simpa using oldPrefix.ctx + have prefixContext : env.IsDefEqCtx U [] + newRawPrefix.reverse oldRawPrefix.reverse := + candidateDefEqCtx_trans henv newPrefixContext + (oldPrefixContext.symm henv) + have newSuffix : env.TelDefEq U newRawPrefix.reverse + rawSuffix viewSuffix := + candidateTelDefEq_defeqDFC henv (prefixContext.symm henv) oldSuffix + have emittedTel : env.TelDefEq U [] + (newRawPrefix ++ rawSuffix) (viewPrefix ++ viewSuffix) := + candidateTelDefEq_append newPrefixTheory (by simpa using newSuffix) + have fullContext : env.IsDefEqCtx U [] + ((newRawPrefix ++ rawSuffix).reverse) + ((oldRawPrefix ++ rawSuffix).reverse) := by + have extended := newSuffix.raw_onTel.extendDefEqCtx prefixContext + simpa [List.reverse_append] using extended + have oldResult : DefEqEvidence env U + (oldRawPrefix ++ rawSuffix).reverse + rawResult viewResult resultType := by + simpa using run.result + have emittedResult : DefEqEvidence env U + (newRawPrefix ++ rawSuffix).reverse + rawResult viewResult resultType := + .ofDefEq (oldResult.isDefEq.defeqDFC henv + (fullContext.symm henv)) + exact TelResultDefEqEvidence.ofTelescopeResult + (.ofTelDefEq emittedTel) (by simpa using emittedResult) + +/-- Every recursive candidate run carries the well-formed local context used +by its root checker observation. -/ +theorem CandidateExprRun.context_wf + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') : + VLCtx.WF env Us.length Δ := by + cases run with + | @terminal Δ context source inferred result source' result' inferred' + checked normalized node => + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + | forallE _ _ _ _ node => + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + +private theorem candidateTelN_forallN_length : + ∀ (As : List VExpr) (B : VExpr), + VExpr.telN As.length (VExpr.forallN As B) = As + | [], _ => rfl + | _ :: As, B => by + simp only [List.length_cons, VExpr.forallN, VExpr.telN, + candidateTelN_forallN_length As B] + +private theorem candidateDropN_forallN_length : + ∀ (As : List VExpr) (B : VExpr), + VExpr.dropN As.length (VExpr.forallN As B) = B + | [], _ => rfl + | _ :: As, B => by + simp only [List.length_cons, VExpr.forallN, VExpr.dropN, + candidateDropN_forallN_length As B] + +/-- Syntactic terminal marker used only to recover a telescope from a known +`dropN` endpoint. -/ +private def CandidateTerminal : VExpr → Prop + | .forallE _ _ => False + | _ => True + +/-- If dropping `n` binders from a telescope reaches its non-forall terminal, +then taking `n` binders recovers the entire telescope. -/ +private theorem candidateTelN_of_dropN_terminal + {B : VExpr} (hB : CandidateTerminal B) : + ∀ (As : List VExpr) (n : Nat), + VExpr.dropN n (VExpr.forallN As B) = B → + VExpr.telN n (VExpr.forallN As B) = As + | [], n, _ => by + cases B <;> cases n <;> simp_all [CandidateTerminal, + VExpr.forallN, VExpr.dropN, VExpr.telN] + | A :: As, 0, h => by + cases B <;> simp_all [CandidateTerminal, + VExpr.forallN, VExpr.dropN] + | A :: As, n + 1, h => by + simp only [VExpr.forallN, VExpr.telN, + List.cons.injEq, true_and] + exact candidateTelN_of_dropN_terminal hB As n (by + simpa only [VExpr.forallN, VExpr.dropN] using h) + +private theorem candidateTerminal_appN_app (f a : VExpr) : + ∀ args, CandidateTerminal (VExpr.appN (.app f a) args) + | [] => trivial + | b :: args => candidateTerminal_appN_app (.app f a) b args + +private theorem candidateTerminal_appN_const + (name : Name) (levels : List VLevel) : + ∀ args, CandidateTerminal (VExpr.appN (.const name levels) args) + | [] => trivial + | a :: args => candidateTerminal_appN_app (.const name levels) a args + +/-- Recursive worker for candidate spine extraction. + +`rawΔ` follows the contexts generated by the stored raw binders, while `Δ` +is the annotation-consumed context in which the candidate body was checked. +The explicit context equality transports each retained checker judgment back +to the raw side before it is added to the telescope certificate. -/ +private theorem CandidateExprRun.spineEvidenceAux + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') + (aligned : trace.storedSpine = true) + {rawΔ : VLCtx} {rawSource' : VExpr} + (contextEq : VLCtx.IsDefEq env Us.length rawΔ Δ) + (rawSource_tr : TrExprS env Us rawΔ source rawSource') : + ∃ rawBinders viewBinders rawResult viewResult resultType, + rawSource' = VExpr.forallN rawBinders rawResult ∧ + view' = VExpr.forallN viewBinders viewResult ∧ + TelResultDefEqEvidence env Us.length rawΔ.toCtx + rawBinders viewBinders rawResult viewResult resultType ∧ + rawBinders.length = trace.spineLength := by + induction run generalizing rawΔ rawSource' with + | terminal node => + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + have hRawΔ := contextEq.wf + have rawToSource : env.IsDefEqU Us.length rawΔ.toCtx + rawSource' _ := + rawSource_tr.uniq henv contextEq node.check.expr_tr + have sourceToView := + node.evidence.isDefEq.defeqDFC henv + (contextEq.symm henv).defeqCtx + have final := VEnv.IsDefEq.transU_r henv hRawΔ.toCtx + rawToSource sourceToView + exact ⟨[], [], rawSource', _, _, rfl, rfl, + .terminal (.ofDefEq final), rfl⟩ + | @forallE domain context name binderInfo Δ source inferred body + source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyΔ storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate + bodyCandidate node domainRun annotationsRun bodyRun domainType bodyType + bodySource bodyContext domainIH bodyIH => + simp only [AddInductive.CandidateExprTrace.storedSpine, + Bool.and_eq_true] at aligned + obtain ⟨sourceEq, bodyAligned⟩ := aligned + have alignedSource_tr : TrExprS env Us rawΔ + (.forallE name domain body binderInfo) rawSource' := + rawSource_tr.eqv (Expr.structuralEq_eqv sourceEq) + let @TrExprS.forallE _ _ rawDomain rawBody _ _ _ _ _ + rawDomainType rawBodyType rawDomain_tr rawBody_tr := alignedSource_tr + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + have hΔ : VLCtx.WF env Us.length Δ := by + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + have hRawΔ := contextEq.wf + have rawToDomainU := + rawDomain_tr.uniq henv contextEq domainRun.source_tr + have domainTypeRaw := + domainType.defeqDFC henv (contextEq.symm henv).defeqCtx + have rawToDomain := + rawToDomainU.of_r henv hRawΔ.toCtx domainTypeRaw + have domainToView := + domainRun.evidence.isDefEq.toU.of_l henv hΔ.toCtx domainType + have domainToViewRaw := + domainToView.defeqDFC henv (contextEq.symm henv).defeqCtx + have head : DefEqEvidence env Us.length rawΔ.toCtx + _ domainView' (.sort u) := + .ofDefEq (rawToDomain.trans domainToViewRaw) + have annotationDef := + annotationsRun.isDefEqU.of_l henv hΔ.toCtx domainType + have annotationDefRaw := + annotationDef.defeqDFC henv (contextEq.symm henv).defeqCtx + have rawToStored := rawToDomain.trans annotationDefRaw + have bodyWF := bodyRun.context_wf + rw [bodyContext] at bodyWF + have rawFresh : + ∀ fv deps, + some (context.freshFVarId, annotations.consumed.fvarsList) = + some (fv, deps) → + fv ∉ rawΔ.fvars ∧ deps ⊆ rawΔ.fvars := by + intro fv deps heq + cases heq + have hfresh := bodyWF.2.1 _ _ rfl + simpa only [contextEq.fvars] using hfresh + let rawBodyΔ : VLCtx := + (some (context.freshFVarId, annotations.consumed.fvarsList), + .vlam rawDomain) :: rawΔ + have bodyContextEqConcrete : VLCtx.IsDefEq env Us.length rawBodyΔ + ((some (context.freshFVarId, annotations.consumed.fvarsList), + .vlam storedDomain') :: Δ) := + .cons contextEq rawFresh (.vlam rawToStored) + have bodyContextEq : VLCtx.IsDefEq env Us.length rawBodyΔ bodyΔ := by + simpa only [bodyContext] using bodyContextEqConcrete + have rawBodyΔwf := bodyContextEq.wf + have rawBodyInst_tr : TrExprS env Us rawBodyΔ + (body.instantiate1 context.freshExpr) rawBody := by + simpa only [AddInductive.Context.freshExpr, + Expr.instantiate1_eq] using + rawBody_tr.inst_fvar henv.ordered rawBodyΔwf + obtain ⟨rawBinders, viewBinders, rawResult, viewResult, + resultType, rawBodyEq, viewBodyEq, tail, tailLength⟩ := + bodyIH bodyAligned bodyContextEq rawBodyInst_tr + refine ⟨rawDomain :: rawBinders, + domainView' :: viewBinders, rawResult, viewResult, resultType, + ?_, ?_, ?_, ?_⟩ + · simp only [VExpr.forallN, rawBodyEq] + · simp only [VExpr.forallN, viewBodyEq] + · exact .forallE head (by + simpa only [rawBodyΔ, VLCtx.toCtx] using tail) + · simpa only [List.length_cons, + AddInductive.CandidateExprTrace.spineLength] using + congrArg Nat.succ tailLength + +/-- Extract exact raw/view telescopes and terminal results from a recursive +candidate run whose WHNF traversal preserved the stored Pi spine. + +The binder count is computed from the source-indexed trace, and `telN`/ +`dropN` name the exact stored raw and reconstructed-view components. This +avoids recovering binder equality from whole-Pi definitional equality and so +does not use the unfinished forall-injectivity theorem. -/ +theorem CandidateExprRun.spineEvidence + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') + (aligned : trace.storedSpine = true) : + ∃ resultType, + TelResultDefEqEvidence env Us.length Δ.toCtx + (VExpr.telN trace.spineLength source') + (VExpr.telN trace.spineLength view') + (VExpr.dropN trace.spineLength source') + (VExpr.dropN trace.spineLength view') resultType := by + have henv : VEnv.WF env := by + cases run with + | terminal node => + simpa only [node.check.venv_eq] using node.check.context.Ewf + | forallE _ _ _ _ node => + simpa only [node.check.venv_eq] using node.check.context.Ewf + obtain ⟨rawBinders, viewBinders, rawResult, viewResult, + resultType, rawEq, viewEq, evidence, rawLength⟩ := + run.spineEvidenceAux aligned + (.refl henv run.context_wf) run.source_tr + have viewLength : viewBinders.length = trace.spineLength := + evidence.length_eq ▸ rawLength + have rawTel : VExpr.telN trace.spineLength source' = rawBinders := by + rw [rawEq, ← rawLength] + exact candidateTelN_forallN_length rawBinders rawResult + have viewTel : VExpr.telN trace.spineLength view' = viewBinders := by + rw [viewEq, ← viewLength] + exact candidateTelN_forallN_length viewBinders viewResult + have rawResultEq : + VExpr.dropN trace.spineLength source' = rawResult := by + rw [rawEq, ← rawLength] + exact candidateDropN_forallN_length rawBinders rawResult + have viewResultEq : + VExpr.dropN trace.spineLength view' = viewResult := by + rw [viewEq, ← viewLength] + exact candidateDropN_forallN_length viewBinders viewResult + simpa only [rawTel, viewTel, rawResultEq, viewResultEq] using + ⟨resultType, evidence⟩ + +/-- Replace only the terminal typing index of a combined certificate. The +telescope and both result endpoints remain definitionally unchanged. -/ +theorem TelResultDefEqEvidence.withResult + (run : TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult resultType) + (result : DefEqEvidence env U (rawBinders.reverse ++ Γ) + rawResult viewResult resultType') : + TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult resultType' := by + induction run with + | terminal _ => exact .terminal (by simpa using result) + | forallE domain tail ih => + exact .forallE domain (ih (by + simpa [List.reverse_cons, List.append_assoc] using result)) + +/-- Fix a candidate terminal equality at a known type of its right endpoint. +This is the bridge from the candidate's checker-inferred type to the precise +sort required by dependent inductive analysis. -/ +theorem TelResultDefEqEvidence.ofRightType + (henv : VEnv.WF env) (hΓ : OnCtx Γ (env.IsType U)) + (run : TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult resultType) + (rightType : env.HasType U (rawBinders.reverse ++ Γ) + viewResult expectedType) : + TelResultDefEqEvidence env U Γ rawBinders viewBinders + rawResult viewResult expectedType := by + have hctx : OnCtx (rawBinders.reverse ++ Γ) (env.IsType U) := + (run.telescope.telDefEq.extendCtx (.refl hΓ)).isType + exact run.withResult (.ofDefEq + (run.result.isDefEq.toU.of_r henv hctx rightType)) + +theorem CandidateExprRun.env_wf + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') : + VEnv.WF env := by + cases run with + | terminal node => + simpa only [node.check.venv_eq] using node.check.context.Ewf + | forallE _ _ _ _ node => + simpa only [node.check.venv_eq] using node.check.context.Ewf + +/-- Recover the exact verified candidate context reached at the end of the +main Pi spine. + +`CandidateExprRun` retains the semantic context at every recursive node, but +its public indices deliberately mention only the translated local context. +Constructor validation, on the other hand, resumes in the implementation +`Context` returned by the family traversal. This projection reconnects the +two without reconstructing a local context from names: starting from the +root `CandidateContextRun`, each Pi case repeats the already-certified +annotation equality and the exact `pushLocalDecl` used by the candidate. -/ +theorem CandidateExprRun.terminalContextRun + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') + (contextRun : CandidateContextRun candidateContext) + (venv_eq : contextRun.context.venv = env) + (lparams_eq : contextRun.context.lparams = Us) + (vlctx_eq : contextRun.context.vlctx = Δ) : + ∃ terminalRun : CandidateContextRun trace.terminalContext, + terminalRun.context.venv = env ∧ + terminalRun.context.lparams = Us := by + induction run with + | terminal node => + exact ⟨by + simpa only [AddInductive.CandidateExprTrace.terminalContext] using + contextRun, + venv_eq, lparams_eq⟩ + | @forallE domain context name binderInfo Δ source inferred body + source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyΔ storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate + bodyCandidate node domainRun annotationsRun bodyRun domainType bodyType + bodySource bodyContext domainIH bodyIH => + have storedDomain_tr : contextRun.context.TrExprS + annotations.consumed storedDomain' := by + simpa only [VContext.TrExprS, venv_eq, lparams_eq, vlctx_eq] using + annotationsRun.rhs_tr + have henv : VEnv.WF env := by + simpa only [venv_eq] using contextRun.context.Ewf + have hΔ : OnCtx Δ.toCtx (env.IsType Us.length) := by + simpa only [venv_eq, lparams_eq, vlctx_eq] using + contextRun.context.Δwf.toCtx + have storedDomain_type : env.IsType Us.length Δ.toCtx storedDomain' := by + have annotationDef := annotationsRun.isDefEqU.of_l henv hΔ domainType + exact ⟨u, annotationDef.hasType.2⟩ + let nextContextRun := contextRun.pushLocalDecl name binderInfo + annotations.consumed fresh storedDomain' storedDomain_tr (by + change contextRun.context.venv.IsType + contextRun.context.lparams.length + contextRun.context.vlctx.toCtx storedDomain' + rw [venv_eq, lparams_eq, vlctx_eq] + exact storedDomain_type) + have nextVenv : nextContextRun.context.venv = env := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_venv, + venv_eq] + have nextLparams : nextContextRun.context.lparams = Us := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_lparams, + lparams_eq] + have nextVlctx : nextContextRun.context.vlctx = bodyΔ := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_vlctx] + rw [vlctx_eq, bodyContext] + obtain ⟨terminalRun, terminalVenv, terminalLparams⟩ := + bodyIH nextContextRun nextVenv nextLparams nextVlctx + exact ⟨by + simpa only [AddInductive.CandidateExprTrace.terminalContext] using + terminalRun, + terminalVenv, terminalLparams⟩ + +private theorem candidateFVLift'_comp + (left : VLCtx.FVLift' Δ₁ Δ₂ 0 (.skipN .refl n₁) 0) + (right : VLCtx.FVLift' Δ₂ Δ₃ 0 (.skipN .refl n₂) 0) : + VLCtx.FVLift' Δ₁ Δ₃ 0 (.skipN .refl (n₁ + n₂)) 0 := by + simpa only [Lift.comp_skipN, Lift.comp, Lift.skipN_skipN] using + left.comp right + +/-- Recover the terminal implementation context together with the exact +candidate-view telescope occupying the same local positions. + +The two `VLCtx`s keep the identical free-variable metadata and declaration +kinds. Their declaration types may differ, but strict translation uniqueness +only needs this positional relation. The view-side `toCtx` is definitionally +the reversed telescope selected by the recursive semantic run, followed by +the caller's view-side base context. -/ +theorem CandidateExprRun.terminalContextRunView + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') + (contextRun : CandidateContextRun candidateContext) + (venv_eq : contextRun.context.venv = env) + (lparams_eq : contextRun.context.lparams = Us) + (vlctx_eq : contextRun.context.vlctx = Δ) + {viewΔ : VLCtx} + (viewDefEq : VLCtx.IsDefEq env Us.length Δ viewΔ) + (viewContext : TrExprS.IsUniqueCtx Δ viewΔ) : + ∃ (terminalRun : CandidateContextRun trace.terminalContext) + (viewTerminal : VLCtx), + terminalRun.context.venv = env ∧ + terminalRun.context.lparams = Us ∧ + VLCtx.IsDefEq env Us.length terminalRun.context.vlctx viewTerminal ∧ + TrExprS.IsUniqueCtx terminalRun.context.vlctx viewTerminal ∧ + VLCtx.FVLift' viewΔ viewTerminal 0 + (.skipN .refl trace.spineLength) 0 ∧ + viewTerminal.toCtx = + (VExpr.telN trace.spineLength view').reverse ++ viewΔ.toCtx := by + induction run generalizing viewΔ with + | @terminal Δ context source inferred result source' result' inferred' + checked normalized node => + let terminalRun : CandidateContextRun + (AddInductive.CandidateExprTrace.terminal + context source inferred result checked normalized).terminalContext := by + simpa only [AddInductive.CandidateExprTrace.terminalContext] using + contextRun + refine ⟨terminalRun, viewΔ, venv_eq, lparams_eq, ?_, ?_, .refl, ?_⟩ + · change VLCtx.IsDefEq env Us.length contextRun.context.vlctx viewΔ + rw [vlctx_eq] + exact viewDefEq + · change TrExprS.IsUniqueCtx contextRun.context.vlctx viewΔ + rw [vlctx_eq] + exact viewContext + · simp only [AddInductive.CandidateExprTrace.spineLength, + VExpr.telN, List.reverse_nil, List.nil_append] + | @forallE domain context name binderInfo Δ source inferred body + source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyΔ storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate + bodyCandidate node domainRun annotationsRun bodyRun domainType bodyType + bodySource bodyContext domainIH bodyIH => + have storedDomain_tr : contextRun.context.TrExprS + annotations.consumed storedDomain' := by + simpa only [VContext.TrExprS, venv_eq, lparams_eq, vlctx_eq] using + annotationsRun.rhs_tr + have henv : VEnv.WF env := by + simpa only [venv_eq] using contextRun.context.Ewf + have hΔ : OnCtx Δ.toCtx (env.IsType Us.length) := by + simpa only [venv_eq, lparams_eq, vlctx_eq] using + contextRun.context.Δwf.toCtx + have storedDomain_type : env.IsType Us.length Δ.toCtx storedDomain' := by + have annotationDef := annotationsRun.isDefEqU.of_l henv hΔ domainType + exact ⟨u, annotationDef.hasType.2⟩ + have domainDef : env.IsDefEq Us.length Δ.toCtx + domain' domainView' (.sort u) := + domainRun.evidence.isDefEq.toU.of_l henv hΔ domainType + have annotationDef : env.IsDefEq Us.length Δ.toCtx + domain' storedDomain' (.sort u) := + annotationsRun.isDefEqU.of_l henv hΔ domainType + have storedToView : env.IsDefEq Us.length Δ.toCtx + storedDomain' domainView' (.sort u) := + annotationDef.symm.trans domainDef + let nextContextRun := contextRun.pushLocalDecl name binderInfo + annotations.consumed fresh storedDomain' storedDomain_tr (by + change contextRun.context.venv.IsType + contextRun.context.lparams.length + contextRun.context.vlctx.toCtx storedDomain' + rw [venv_eq, lparams_eq, vlctx_eq] + exact storedDomain_type) + have nextVenv : nextContextRun.context.venv = env := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_venv, + venv_eq] + have nextLparams : nextContextRun.context.lparams = Us := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_lparams, + lparams_eq] + have nextVlctx : nextContextRun.context.vlctx = bodyΔ := by + simp only [nextContextRun, CandidateContextRun.pushLocalDecl_vlctx] + rw [vlctx_eq, bodyContext] + let viewBodyΔ : VLCtx := + (some (context.freshFVarId, annotations.consumed.fvarsList), + .vlam domainView') :: viewΔ + have bodyWF := bodyRun.context_wf + rw [bodyContext] at bodyWF + have bodyViewDefEq : VLCtx.IsDefEq env Us.length bodyΔ viewBodyΔ := by + rw [bodyContext] + exact .cons viewDefEq bodyWF.2.1 (.vlam storedToView) + have bodyViewContext : TrExprS.IsUniqueCtx bodyΔ viewBodyΔ := by + rw [bodyContext] + exact viewContext.cons .vlam + obtain ⟨terminalRun, viewTerminal, terminalVenv, terminalLparams, + terminalViewDefEq, terminalViewContext, terminalViewLift, + terminalViewEq⟩ := + bodyIH nextContextRun nextVenv nextLparams nextVlctx bodyViewDefEq + bodyViewContext + refine ⟨by + simpa only [AddInductive.CandidateExprTrace.terminalContext] using + terminalRun, + viewTerminal, terminalVenv, terminalLparams, terminalViewDefEq, + terminalViewContext, ?_, ?_⟩ + · have headLift : VLCtx.FVLift' viewΔ viewBodyΔ 0 + (.skipN .refl 1) 0 := by + exact VLCtx.FVLift'.skip_fvar + (context.freshFVarId, annotations.consumed.fvarsList) + (.vlam domainView') (.refl : + VLCtx.FVLift' viewΔ viewΔ 0 .refl 0) + simpa only [AddInductive.CandidateExprTrace.spineLength, + Nat.add_comm 1] using + candidateFVLift'_comp headLift terminalViewLift + simpa only [AddInductive.CandidateExprTrace.spineLength, + VExpr.telN, List.reverse_cons, List.singleton_append, + List.append_assoc, viewBodyΔ, VLCtx.toCtx] using terminalViewEq + +/-- Interpret the terminal-sort fact retained by family validation. + +At a terminal node the verified WHNF result translates the exact kernel sort. +At a Pi node the recursively interpreted body is transported from the +annotation-consumed binder context to the candidate-view binder context. Thus +the complete checker-selected candidate view is a Theory type without using a +checked inductive declaration or a caller-supplied view-WF proof. -/ +theorem CandidateExprRun.view_isType_of_terminalSort + {env : VEnv} {Us : List Name} + {candidateContext : AddInductive.Context} {source : Expr} + {trace : AddInductive.CandidateExprTrace candidateContext source} + {Δ : VLCtx} {source' view' inferred' : VExpr} + (run : CandidateExprRun env Us trace Δ source' view' inferred') + (terminal : trace.terminalResult = .sort resultLevel) : + env.IsType Us.length Δ.toCtx view' := by + induction run with + | terminal node => + simp only [AddInductive.CandidateExprTrace.terminalResult] at terminal + rw [terminal] at node + cases node.whnf.rhs_tr with + | sort level_tr => + exact ⟨_, .sort (VLevel.WF.of_ofLevel level_tr)⟩ + | @forallE domain context name binderInfo Δ source inferred body + source' domain' body' inferred' domainView' domainInferred' + storedDomain' bodyΔ storedBody' bodyView' bodyInferred' u v fresh + checked normalized annotations annotationsEq domainCandidate + bodyCandidate node domainRun annotationsRun bodyRun domainType bodyType + bodySource bodyContext domainIH bodyIH => + simp only [AddInductive.CandidateExprTrace.terminalResult] at terminal + have henv : VEnv.WF env := by + simpa only [node.check.venv_eq] using node.check.context.Ewf + have hΔ : VLCtx.WF env Us.length Δ := by + simpa only [node.check.venv_eq, node.check.lparams_eq, + node.check.vlctx_eq] using node.check.context.Δwf + have domainDef : env.IsDefEq Us.length Δ.toCtx + domain' domainView' (.sort u) := + domainRun.evidence.isDefEq.toU.of_l henv hΔ.toCtx domainType + have domainViewType : env.IsType Us.length Δ.toCtx domainView' := + ⟨u, domainDef.hasType.2⟩ + have annotationDef : env.IsDefEq Us.length Δ.toCtx + domain' storedDomain' (.sort u) := + annotationsRun.isDefEqU.of_l henv hΔ.toCtx domainType + have storedToView : env.IsDefEq Us.length Δ.toCtx + storedDomain' domainView' (.sort u) := + annotationDef.symm.trans domainDef + have bodyContextEq : env.IsDefEqCtx Us.length [] + (storedDomain' :: Δ.toCtx) (domainView' :: Δ.toCtx) := + (VLCtx.IsDefEq.cons (.refl henv hΔ) (ofv := none) + (by nofun) (.vlam storedToView)).defeqCtx + have bodyViewTypeStored : env.IsType Us.length + (storedDomain' :: Δ.toCtx) bodyView' := by + simpa only [bodyContext, VLCtx.toCtx] using bodyIH terminal + have bodyViewType : env.IsType Us.length + (domainView' :: Δ.toCtx) bodyView' := by + exact bodyViewTypeStored.defeqDFC henv.ordered bodyContextEq + exact domainViewType.forallE bodyViewType + +/-- Family validation types the checker-selected view first; the retained +candidate equality then transports that fact back to the exact raw Theory +source. This is the declaration-WF fact needed before raw-family insertion. -/ +theorem CandidateExprSemanticRootRun.source_isType_of_terminalSort + {env : VEnv} {Us : List Name} {source : Expr} + {candidate : AddInductive.CandidateExpr source} {source' : VExpr} + (run : CandidateExprSemanticRootRun env Us candidate source') + (terminal : candidate.trace.terminalResult = .sort resultLevel) : + env.IsType Us.length [] source' := by + obtain ⟨_, recursive⟩ := run.recursive + have hview := recursive.view_isType_of_terminalSort terminal + have henv : VEnv.WF env := by + simpa only [run.venv_eq] using run.contextRun.context.Ewf + exact hview.defeqU_l henv trivial recursive.evidence.isDefEq.toU.symm + +/-- Candidate-view parameter binders selected by an exact singleton family +validation run. The split is computed from the retained candidate spine. -/ +def CandidateExprSemanticRootRun.viewParameters + {indType : InductiveType} + {candidate : AddInductive.CandidateExpr indType.type} + (run : CandidateExprSemanticRootRun env Us candidate source') + (validation : AddInductive.CandidateExprTrace.FamilyValidationRun + indType candidate.trace) : List VExpr := + (VExpr.telN candidate.trace.spineLength run.view).take + validation.nparams + +/-- Candidate-view index binders following the validator-selected parameter +prefix. -/ +def CandidateExprSemanticRootRun.viewIndices + {indType : InductiveType} + {candidate : AddInductive.CandidateExpr indType.type} + (run : CandidateExprSemanticRootRun env Us candidate source') + (validation : AddInductive.CandidateExprTrace.FamilyValidationRun + indType candidate.trace) : List VExpr := + (VExpr.telN candidate.trace.spineLength run.view).drop + validation.nparams + +/-- An exact recursive run whose executable main spine preserves the stored +binders. Unlike a whole-expression root equality, this package is strong +enough to expose generation's pointwise binder and terminal-result evidence. -/ +def CandidateExprSpineRun (env : VEnv) (Us : List Name) + {source : Expr} (candidate : AddInductive.CandidateExpr source) + (raw view : VExpr) : Prop := + candidate.trace.storedSpine = true ∧ + ∃ inferred, CandidateExprRun env Us candidate.trace [] raw view inferred + +/-- Retaining the recursive semantic root makes the generation spine a direct +projection once the executable structural gate has succeeded. -/ +theorem CandidateExprSemanticRootRun.spine + (run : CandidateExprSemanticRootRun env Us candidate source') + (storedSpine : candidate.trace.storedSpine = true) : + CandidateExprSpineRun env Us candidate source' run.view := + ⟨storedSpine, run.recursive⟩ + +/-- Turn an exact root translation and a recursive identity witness into the +generation-ready spine package. The root equalities transport the recursive +run out of the verifier's reconstructed context without choosing a different +semantic endpoint. -/ +theorem CandidateExprRootRun.spineOfIdentity + {env : VEnv} {Us : List Name} {source : Expr} + {candidate : AddInductive.CandidateExpr source} {source' : VExpr} + (run : CandidateExprRootRun env Us candidate source' source') + (identity : CandidateExprIdentity candidate.trace) : + CandidateExprSpineRun env Us candidate source' source' := by + refine ⟨identity.storedSpine, ?_⟩ + have source_tr : run.contextRun.context.TrExprS source source' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.source_tr + obtain ⟨inferred', ⟨recursive⟩⟩ := + CandidateExprRun.exists_ofIdentity candidate.trace identity + run.contextRun source' source_tr run.whnfFuel run.whnfDepth + refine ⟨inferred', ?_⟩ + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq] using recursive + +/-- Retain the exact recursive run selected by an identity-normalizing root. + +All data fields are inherited from the named root and its fixed Theory +endpoint. The existential inferred type remains proof-only, so this constructor +does not use classical choice and does not turn identity into an executable or +semantic oracle. -/ +def CandidateExprRootRun.semanticOfIdentity + {env : VEnv} {Us : List Name} {source : Expr} + {candidate : AddInductive.CandidateExpr source} {source' : VExpr} + (run : CandidateExprRootRun env Us candidate source' source') + (identity : CandidateExprIdentity candidate.trace) : + CandidateExprSemanticRootRun env Us candidate source' where + contextRun := run.contextRun + venv_eq := run.venv_eq + lparams_eq := run.lparams_eq + vlctx_eq := run.vlctx_eq + source_tr := run.source_tr + whnfFuel := run.whnfFuel + whnfDepth := run.whnfDepth + view := source' + recursive := by + have source_tr : run.contextRun.context.TrExprS source source' := by + simpa only [VContext.TrExprS, run.venv_eq, run.lparams_eq, + run.vlctx_eq] using run.source_tr + obtain ⟨inferred, ⟨recursive⟩⟩ := + CandidateExprRun.exists_ofIdentity candidate.trace identity + run.contextRun source' source_tr run.whnfFuel run.whnfDepth + refine ⟨inferred, ?_⟩ + simpa only [run.venv_eq, run.lparams_eq, run.vlctx_eq] using recursive + +theorem CandidateExprSpineRun.evidence + (run : CandidateExprSpineRun env Us candidate raw view) : + ∃ resultType, + TelResultDefEqEvidence env Us.length [] + (VExpr.telN candidate.trace.spineLength raw) + (VExpr.telN candidate.trace.spineLength view) + (VExpr.dropN candidate.trace.spineLength raw) + (VExpr.dropN candidate.trace.spineLength view) resultType := by + obtain ⟨aligned, _, recursive⟩ := run + exact recursive.spineEvidence aligned + +/-- Align extracted candidate components with named raw/view telescope and +result data, then fix the terminal type from a checked right-endpoint typing +judgment. All four alignment premises are syntactic equations. -/ +theorem CandidateExprSpineRun.evidenceAt + (run : CandidateExprSpineRun env Us candidate raw view) + (rawTel : VExpr.telN candidate.trace.spineLength raw = rawBinders) + (viewTel : VExpr.telN candidate.trace.spineLength view = viewBinders) + (rawResult_eq : + VExpr.dropN candidate.trace.spineLength raw = rawResult) + (viewResult_eq : + VExpr.dropN candidate.trace.spineLength view = viewResult) + (rightType : env.HasType Us.length rawBinders.reverse + viewResult expectedType) : + TelResultDefEqEvidence env Us.length [] rawBinders viewBinders + rawResult viewResult expectedType := by + obtain ⟨aligned, _, recursive⟩ := run + obtain ⟨resultType, evidence⟩ := recursive.spineEvidence aligned + have exactEvidence : TelResultDefEqEvidence env Us.length [] + rawBinders viewBinders rawResult viewResult resultType := by + simpa only [rawTel, viewTel, rawResult_eq, viewResult_eq, + VLCtx.toCtx] using evidence + exact exactEvidence.ofRightType recursive.env_wf trivial (by + simpa using rightType) + +end TypeChecker + +namespace VInductDecl + +/-- A one-family normalization candidate validated by compositional verified +normalization evidence at the kernel's two declaration stages. + +The family comparison runs in `env`. Constructor comparisons run in the exact +`typeEnv` obtained by inserting the raw family constant. The positional +`Forall₂` prevents a shorter checker-result list from certifying a declaration. +-/ +structure NormalizationRun {source : VInductDecl} + (norm : Normalization source) (env : VEnv) where + raw : VInductiveType + view : VInductiveType + source_types_eq : source.types = [raw] + view_types_eq : norm.view.types = [view] + family : ∃ A, + TypeChecker.DefEqEvidence env source.uvars [] + raw.type view.type A + typeEnv : VEnv + addType : + env.addConst raw.name raw.toVConstant = some typeEnv + constructors : List.Forall₂ + (fun rawCtor viewCtor => + ∃ A, TypeChecker.DefEqEvidence typeEnv source.uvars [] + rawCtor.type viewCtor.type A) + raw.ctors view.ctors + +/-- Checker-validated family and constructor comparisons establish the +semantic part of the raw/view normalization boundary. -/ +theorem NormalizationRun.wf + (run : NormalizationRun norm env) : norm.WF env := by + refine ⟨run.raw, run.view, run.source_types_eq, run.view_types_eq, ?_, ?_⟩ + · obtain ⟨_, hfamily⟩ := run.family + exact hfamily.isDefEq.toU + · intro envT hadd + have henv : envT = run.typeEnv := by + have : some envT = some run.typeEnv := hadd.symm.trans run.addType + exact Option.some.inj this + subst envT + exact Ix.Theory.Named.List.Forall₂.imp (h := run.constructors) fun _ _ h => by + obtain ⟨_, hctor⟩ := h + exact hctor.isDefEq.toU + +/-- Checker-validated normalization for an arbitrary mutual block. + +Family equalities are interpreted in the common pre-family environment. The +raw family constants are then staged as one exact source-ordered fold, and +all constructor equalities are interpreted in the resulting shared block +environment. -/ +structure NormalizationBlockRun {source : VInductDecl} + (norm : Normalization source) (env blockEnv : VEnv) where + stage : env.stageInductiveTypes source.types = some blockEnv + families : List.Forall₂ + (fun raw view => + (∃ A, TypeChecker.DefEqEvidence env source.uvars [] + raw.type view.type A) ∧ + List.Forall₂ + (fun rawCtor viewCtor => + ∃ A, TypeChecker.DefEqEvidence blockEnv source.uvars [] + rawCtor.type viewCtor.type A) + raw.ctors view.ctors) + source.types norm.view.types + +/-- The verified checker interpretation discharges the complete Theory +mutual-normalization contract without a singleton projection. -/ +theorem NormalizationBlockRun.wf + (run : NormalizationBlockRun norm env blockEnv) : + norm.BlockWF env blockEnv := by + refine ⟨run.stage, ?_⟩ + exact Ix.Theory.Named.List.Forall₂.imp (h := run.families) fun _ _ h => by + refine ⟨h.1.choose_spec.isDefEq.toU, ?_⟩ + exact Ix.Theory.Named.List.Forall₂.imp (h := h.2) fun _ _ hctor => + hctor.choose_spec.isDefEq.toU + +/-- One constructor candidate tied to the corresponding raw Theory constant. +Its expression payload may normalize, but its name, universe arity, and exact +source position remain fixed. -/ +structure CandidateConstructorRun (env : VEnv) (Us : List Name) + {source : Constructor} + (candidate : AddInductive.CandidateConstructor source) + (raw : VConstVal) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + viewType : VExpr + typeRun : TypeChecker.CandidateExprRootRun env Us candidate.type + raw.type viewType + +/-- Replace only the expression payload certified by the constructor run. -/ +def CandidateConstructorRun.view + (run : CandidateConstructorRun env Us candidate raw) : VConstVal := + { raw with type := run.viewType } + +/-- Exact positional certification for a source-indexed constructor list and +the raw Theory constructor list. Unlike `zip`, this type cannot truncate a +longer side or reuse evidence at a different source position. -/ +inductive CandidateConstructorListRun (env : VEnv) (Us : List Name) : + {sources : List Constructor} → + AddInductive.CandidateList AddInductive.CandidateConstructor sources → + List VConstVal → Type where + | nil : CandidateConstructorListRun env Us .nil [] + | cons + (head : CandidateConstructorRun env Us candidate raw) + (tail : CandidateConstructorListRun env Us candidates raws) : + CandidateConstructorListRun env Us + (.cons candidate candidates) (raw :: raws) + +/-- The exact normalized constructor list retained by a positional run. -/ +def CandidateConstructorListRun.views : + CandidateConstructorListRun env Us candidates raws → List VConstVal + | .nil => [] + | .cons head tail => head.view :: tail.views + +/-- Positional certification preserves every constructor header. -/ +theorem CandidateConstructorListRun.sameHeaders + (run : CandidateConstructorListRun env Us candidates raws) : + sameCtorHeaders raws run.views = true := by + induction run with + | nil => rfl + | cons head tail ih => + simp [CandidateConstructorListRun.views, + CandidateConstructorRun.view, sameCtorHeaders, ih] + +/-- Collect the exact checker-produced equality for every positional raw/view +constructor pair. -/ +theorem CandidateConstructorListRun.evidence + (run : CandidateConstructorListRun env Us candidates raws) : + List.Forall₂ + (fun raw view => ∃ A, + TypeChecker.DefEqEvidence env Us.length [] + raw.type view.type A) + raws run.views := by + induction run with + | nil => exact .nil + | cons head tail ih => + exact .cons head.typeRun.evidence ih + +/-- One family candidate certified in the input environment, together with +all of its constructors certified in the exact environment obtained by +inserting the raw family constant. -/ +structure CandidateFamilyRun (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.CandidateFamily source) + (raw : VInductiveType) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + viewType : VExpr + typeRun : TypeChecker.CandidateExprRootRun env Us + candidate.familyType.type raw.type viewType + typeEnv : VEnv + addType : env.addConst raw.name raw.toVConstant = some typeEnv + constructors : CandidateConstructorListRun typeEnv Us + candidate.constructors raw.ctors + +/-- Replace only the family and constructor expression payloads named by the +certified candidate runs. -/ +def CandidateFamilyRun.view + (run : CandidateFamilyRun env Us candidate raw) : VInductiveType := + { raw with + type := run.viewType + ctors := run.constructors.views } + +/-- Exact singleton candidate-list certification against one raw Theory +declaration. The singleton kernel-source index rules out partial selection of +a family candidate, and `raw_types_eq` rules out partial selection of a Theory +family. Mutual blocks remain an explicit later generalization. -/ +structure NormalizationCandidateRun (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + raw : VInductiveType + raw_types_eq : rawDecl.types = [raw] + uvars_eq : rawDecl.uvars = Us.length + family : CandidateFamilyRun env Us candidate.families.singleton raw + +/-- The Theory declaration obtained from the exact singleton candidate. -/ +def NormalizationCandidateRun.viewDecl + (run : NormalizationCandidateRun env Us candidate rawDecl) : + VInductDecl := + { rawDecl with types := [run.family.view] } + +/-- Candidate-list shape evidence is sufficient to construct the Theory +normalization boundary without `head!`, unchecked `zip`, or an arbitrary view +declaration supplied separately from the candidate. -/ +def NormalizationCandidateRun.normalization + (run : NormalizationCandidateRun env Us candidate rawDecl) : + Normalization rawDecl where + view := run.viewDecl + shape_eq := by + simp only [normalizationShape, NormalizationCandidateRun.viewDecl, + run.raw_types_eq, beq_self_eq_true, Bool.true_and, sameTypeHeaders, + CandidateFamilyRun.view] + simp [run.family.constructors.sameHeaders] + +/-- Assemble the existing semantic normalization certificate from the exact +family and constructor candidate runs. -/ +def NormalizationCandidateRun.normalizationRun + (run : NormalizationCandidateRun env Us candidate rawDecl) : + NormalizationRun run.normalization env where + raw := run.raw + view := run.family.view + source_types_eq := run.raw_types_eq + view_types_eq := rfl + family := by + simpa only [run.uvars_eq, CandidateFamilyRun.view] using + run.family.typeRun.evidence + typeEnv := run.family.typeEnv + addType := run.family.addType + constructors := by + simpa only [run.uvars_eq, CandidateFamilyRun.view] using + run.family.constructors.evidence + +/-- One constructor whose exact recursive candidate semantics are retained, +rather than reconstructed separately for normalization and generation. + +The header remains indexed by the kernel source and raw Theory constant. The +semantic root owns the checker-selected view, its inferred type, and the +recursive run used by both downstream phases. -/ +structure CandidateConstructorSemanticRun (env : VEnv) (Us : List Name) + {source : Constructor} + (candidate : AddInductive.CandidateConstructor source) + (raw : VConstVal) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprSemanticRootRun env Us candidate.type + raw.type + +/-- Project the normalization-facing constructor root without losing its +source or position indices. -/ +def CandidateConstructorSemanticRun.root + (run : CandidateConstructorSemanticRun env Us candidate raw) : + CandidateConstructorRun env Us candidate raw where + name_eq := run.name_eq + uvars_eq := run.uvars_eq + viewType := run.type.view + typeRun := run.type.root + +/-- Exact positional semantic ownership for an arbitrary constructor list. +Every element retains the recursive run selected at that source position; the +list cannot truncate, reorder, or reuse a run for another constructor. -/ +inductive CandidateConstructorSemanticListRun + (env : VEnv) (Us : List Name) : + {sources : List Constructor} → + AddInductive.CandidateList AddInductive.CandidateConstructor sources → + List VConstVal → Type where + | nil : CandidateConstructorSemanticListRun env Us .nil [] + | cons + (head : CandidateConstructorSemanticRun env Us candidate raw) + (tail : CandidateConstructorSemanticListRun env Us candidates raws) : + CandidateConstructorSemanticListRun env Us + (.cons candidate candidates) (raw :: raws) + +/-- Forget only the retained recursive-run payload and recover the existing +normalization-facing positional list. -/ +def CandidateConstructorSemanticListRun.roots : + CandidateConstructorSemanticListRun env Us candidates raws → + CandidateConstructorListRun env Us candidates raws + | .nil => .nil + | .cons head tail => .cons head.root tail.roots + +/-- One family in a mutual normalization candidate. Its type is interpreted +in the common pre-family environment, while every constructor is interpreted +in the single environment obtained after staging the complete raw family +block. -/ +structure CandidateBlockFamilySemanticRun + (env blockEnv : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.CandidateFamily source) + (raw : VInductiveType) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprSemanticRootRun env Us + candidate.familyType.type raw.type + constructors : CandidateConstructorSemanticListRun blockEnv Us + candidate.constructors raw.ctors + +/-- Replace only the expression payloads selected by the retained checker +runs; all family and constructor headers remain raw and source-indexed. -/ +def CandidateBlockFamilySemanticRun.view + (run : CandidateBlockFamilySemanticRun env blockEnv Us candidate raw) : + VInductiveType := + { raw with + type := run.type.view + ctors := run.constructors.roots.views } + +/-- Exact source-order semantic ownership for every family in an arbitrary +block. Both the kernel candidate list and raw Theory list are indices, so +family reordering and truncation are unrepresentable. -/ +inductive CandidateBlockFamilySemanticListRun + (env blockEnv : VEnv) (Us : List Name) : + {sources : List InductiveType} → + AddInductive.CandidateList AddInductive.CandidateFamily sources → + List VInductiveType → Type where + | nil : CandidateBlockFamilySemanticListRun env blockEnv Us .nil [] + | cons + (head : CandidateBlockFamilySemanticRun env blockEnv Us candidate raw) + (tail : CandidateBlockFamilySemanticListRun env blockEnv Us + candidates raws) : + CandidateBlockFamilySemanticListRun env blockEnv Us + (.cons candidate candidates) (raw :: raws) + +/-- Exact normalized family views in source order. -/ +def CandidateBlockFamilySemanticListRun.views : + CandidateBlockFamilySemanticListRun env blockEnv Us candidates raws → + List VInductiveType + | .nil => [] + | .cons head tail => head.view :: tail.views + +/-- Block semantic runs preserve every family and constructor header. -/ +theorem CandidateBlockFamilySemanticListRun.sameHeaders + (run : CandidateBlockFamilySemanticListRun env blockEnv Us + candidates raws) : + sameTypeHeaders raws run.views = true := by + induction run with + | nil => rfl + | cons head tail ih => + simp [CandidateBlockFamilySemanticListRun.views, + CandidateBlockFamilySemanticRun.view, sameTypeHeaders, + head.constructors.roots.sameHeaders, ih] + +/-- Collect the exact family/constructor definitional equalities selected by +the retained semantic checker hierarchy. -/ +theorem CandidateBlockFamilySemanticListRun.evidence + (run : CandidateBlockFamilySemanticListRun env blockEnv Us + candidates raws) : + List.Forall₂ + (fun raw view => + (∃ A, TypeChecker.DefEqEvidence env Us.length [] + raw.type view.type A) ∧ + List.Forall₂ + (fun rawCtor viewCtor => + ∃ A, TypeChecker.DefEqEvidence blockEnv Us.length [] + rawCtor.type viewCtor.type A) + raw.ctors view.ctors) + raws run.views := by + induction run with + | nil => exact .nil + | cons head tail ih => + exact .cons + ⟨head.type.root.evidence, head.constructors.roots.evidence⟩ ih + +/-- Complete semantic ownership for an arbitrary normalization candidate. +The raw staging equation and dependent family list share the same exact raw +declaration; no independently supplied normalized declaration is accepted. -/ +structure NormalizationCandidateBlockSemanticRun + (env blockEnv : VEnv) (Us : List Name) + {sources : List InductiveType} + (candidate : AddInductive.NormalizationCandidate sources) + (rawDecl : VInductDecl) where + uvars_eq : rawDecl.uvars = Us.length + stage : env.stageInductiveTypes rawDecl.types = some blockEnv + families : CandidateBlockFamilySemanticListRun env blockEnv Us + candidate.families rawDecl.types + +/-- Theory declaration selected by the exact block semantic hierarchy. -/ +def NormalizationCandidateBlockSemanticRun.viewDecl + (run : NormalizationCandidateBlockSemanticRun env blockEnv Us + candidate rawDecl) : VInductDecl := + { rawDecl with types := run.families.views } + +/-- Construct the header-preserving Theory normalization boundary selected by +the candidate semantic hierarchy. -/ +def NormalizationCandidateBlockSemanticRun.normalization + (run : NormalizationCandidateBlockSemanticRun env blockEnv Us + candidate rawDecl) : Normalization rawDecl where + view := run.viewDecl + shape_eq := by + simp only [normalizationShape, + NormalizationCandidateBlockSemanticRun.viewDecl, + beq_self_eq_true, Bool.true_and] + exact run.families.sameHeaders + +/-- Project the generic verified normalization run for the same raw block and +shared staged environment. -/ +theorem NormalizationCandidateBlockSemanticRun.normalizationRun + (run : NormalizationCandidateBlockSemanticRun env blockEnv Us + candidate rawDecl) : + NormalizationBlockRun run.normalization env blockEnv where + stage := run.stage + families := by + simpa only [run.uvars_eq, + NormalizationCandidateBlockSemanticRun.normalization, + NormalizationCandidateBlockSemanticRun.viewDecl] using + run.families.evidence + +/-- A singleton-family semantic hierarchy spanning the pre-family candidate, +the exact raw-family insertion, and every post-family constructor candidate. +The normalized expression payloads are selected by retained recursive checker +runs, not by a parallel caller-supplied declaration. -/ +structure CandidateFamilySemanticRun (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.CandidateFamily source) + (raw : VInductiveType) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprSemanticRootRun env Us + candidate.familyType.type raw.type + typeEnv : VEnv + addType : env.addConst raw.name raw.toVConstant = some typeEnv + constructors : CandidateConstructorSemanticListRun typeEnv Us + candidate.constructors raw.ctors + +/-- Project the existing normalization-facing family run from the retained +semantic hierarchy. -/ +def CandidateFamilySemanticRun.root + (run : CandidateFamilySemanticRun env Us candidate raw) : + CandidateFamilyRun env Us candidate raw where + name_eq := run.name_eq + uvars_eq := run.uvars_eq + viewType := run.type.view + typeRun := run.type.root + typeEnv := run.typeEnv + addType := run.addType + constructors := run.constructors.roots + +/-- Complete retained semantic ownership for one source-indexed singleton +normalization candidate. This is the generic bridge from translated family and +constructor candidates to `NormalizationCandidateRun`; mutual blocks remain a +later indexed generalization. -/ +structure NormalizationCandidateSemanticRun (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + raw : VInductiveType + raw_types_eq : rawDecl.types = [raw] + uvars_eq : rawDecl.uvars = Us.length + family : CandidateFamilySemanticRun env Us candidate.families.singleton raw + +/-- Recover the existing normalization candidate from the retained semantic +hierarchy. -/ +def NormalizationCandidateSemanticRun.root + (run : NormalizationCandidateSemanticRun env Us candidate rawDecl) : + NormalizationCandidateRun env Us candidate rawDecl where + raw := run.raw + raw_types_eq := run.raw_types_eq + uvars_eq := run.uvars_eq + family := run.family.root + +/-- Pre-run semantic evidence for one source-indexed constructor. Its header +is aligned with the raw Theory constant, while the expression input contains +only the verified context and strict source translation needed to let the +retained checker choose the view. -/ +structure CandidateConstructorSemanticInput (env : VEnv) (Us : List Name) + {source : Constructor} + (candidate : AddInductive.CandidateConstructor source) + (raw : VConstVal) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprSemanticRootInput env Us candidate.type + raw.type + +/-- Interpret one constructor input without selecting its view at the call +site. -/ +theorem CandidateConstructorSemanticInput.exists + (input : CandidateConstructorSemanticInput env Us candidate raw) : + Nonempty (CandidateConstructorSemanticRun env Us candidate raw) := by + obtain ⟨type⟩ := input.type.exists + exact ⟨{ + name_eq := input.name_eq + uvars_eq := input.uvars_eq + type := type }⟩ + +/-- Exact source-order semantic inputs for an arbitrary constructor list. +Unlike a pointwise predicate over erased lists, these indices prevent an input +from being reused at another constructor or from silently truncating either +side. -/ +inductive CandidateConstructorSemanticListInput + (env : VEnv) (Us : List Name) : + {sources : List Constructor} → + AddInductive.CandidateList AddInductive.CandidateConstructor sources → + List VConstVal → Type where + | nil : CandidateConstructorSemanticListInput env Us .nil [] + | cons + (head : CandidateConstructorSemanticInput env Us candidate raw) + (tail : CandidateConstructorSemanticListInput env Us candidates raws) : + CandidateConstructorSemanticListInput env Us + (.cons candidate candidates) (raw :: raws) + +/-- Recursively interpret every source-indexed constructor input. -/ +theorem CandidateConstructorSemanticListInput.exists + (input : CandidateConstructorSemanticListInput env Us candidates raws) : + Nonempty (CandidateConstructorSemanticListRun env Us candidates raws) := by + induction input with + | nil => exact ⟨.nil⟩ + | cons head tail ih => + obtain ⟨headRun⟩ := head.exists + obtain ⟨tailRun⟩ := ih + exact ⟨.cons headRun tailRun⟩ + +/-- Pre-run semantic evidence for one family in a shared mutual stage. +Family types use `env`; all constructor types use the same `blockEnv` after +every raw family has been staged. -/ +structure CandidateBlockFamilySemanticInput + (env blockEnv : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.CandidateFamily source) + (raw : VInductiveType) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprSemanticRootInput env Us + candidate.familyType.type raw.type + constructors : CandidateConstructorSemanticListInput blockEnv Us + candidate.constructors raw.ctors + +/-- Interpret one family and its complete constructor list without selecting +a normalized expression at the call site. -/ +theorem CandidateBlockFamilySemanticInput.exists + (input : CandidateBlockFamilySemanticInput env blockEnv Us + candidate raw) : + Nonempty (CandidateBlockFamilySemanticRun env blockEnv Us + candidate raw) := by + obtain ⟨type⟩ := input.type.exists + obtain ⟨constructors⟩ := input.constructors.exists + exact ⟨{ + name_eq := input.name_eq + uvars_eq := input.uvars_eq + type + constructors }⟩ + +/-- Exact source-order semantic inputs for every family in a mutual block. -/ +inductive CandidateBlockFamilySemanticListInput + (env blockEnv : VEnv) (Us : List Name) : + {sources : List InductiveType} → + AddInductive.CandidateList AddInductive.CandidateFamily sources → + List VInductiveType → Type where + | nil : CandidateBlockFamilySemanticListInput env blockEnv Us .nil [] + | cons + (head : CandidateBlockFamilySemanticInput env blockEnv Us candidate raw) + (tail : CandidateBlockFamilySemanticListInput env blockEnv Us + candidates raws) : + CandidateBlockFamilySemanticListInput env blockEnv Us + (.cons candidate candidates) (raw :: raws) + +/-- Interpret every family and constructor input in lockstep. -/ +theorem CandidateBlockFamilySemanticListInput.exists + (input : CandidateBlockFamilySemanticListInput env blockEnv Us + candidates raws) : + Nonempty (CandidateBlockFamilySemanticListRun env blockEnv Us + candidates raws) := by + induction input with + | nil => exact ⟨.nil⟩ + | cons head tail ih => + obtain ⟨headRun⟩ := head.exists + obtain ⟨tailRun⟩ := ih + exact ⟨.cons headRun tailRun⟩ + +/-- Complete verified semantic input for an arbitrary normalization +candidate. The exact raw family list owns both the all-family staging fold and +the dependent family interpretation, ruling out a reordered staging witness. -/ +structure NormalizationCandidateBlockSemanticInput + (env blockEnv : VEnv) (Us : List Name) + {sources : List InductiveType} + (candidate : AddInductive.NormalizationCandidate sources) + (rawDecl : VInductDecl) where + uvars_eq : rawDecl.uvars = Us.length + stage : env.stageInductiveTypes rawDecl.types = some blockEnv + families : CandidateBlockFamilySemanticListInput env blockEnv Us + candidate.families rawDecl.types + +/-- Automatically interpret the complete mutual semantic hierarchy. -/ +theorem NormalizationCandidateBlockSemanticInput.exists + (input : NormalizationCandidateBlockSemanticInput env blockEnv Us + candidate rawDecl) : + Nonempty (NormalizationCandidateBlockSemanticRun env blockEnv Us + candidate rawDecl) := by + obtain ⟨families⟩ := input.families.exists + exact ⟨{ + uvars_eq := input.uvars_eq + stage := input.stage + families }⟩ + +/-- A mutual semantic hierarchy paired with the exact arbitrary-length +producer traversals that selected the same dependent candidate. -/ +structure ProducedNormalizationCandidateBlockSemanticRun + (familyContext constructorContext : AddInductive.Context) + (env blockEnv : VEnv) (Us : List Name) + {sources : List InductiveType} + (candidate : AddInductive.NormalizationCandidate sources) + (rawDecl : VInductDecl) where + semantic : NormalizationCandidateBlockSemanticRun env blockEnv Us + candidate rawDecl + familyTypesProduced : AddInductive.CandidateFamilyTypeListProduced + familyContext candidate.families.familyTypes + familiesProduced : AddInductive.CandidateFamilyListProduced + constructorContext candidate.families.familyTypes candidate.families + +/-- Combine verified semantic inputs with exact producer provenance for the +same source-indexed mutual candidate. -/ +theorem NormalizationCandidateBlockSemanticInput.exists_ofProduced + (input : NormalizationCandidateBlockSemanticInput env blockEnv Us + candidate rawDecl) + (familyTypesProduced : AddInductive.CandidateFamilyTypeListProduced + familyContext candidate.families.familyTypes) + (familiesProduced : AddInductive.CandidateFamilyListProduced + constructorContext candidate.families.familyTypes candidate.families) : + Nonempty (ProducedNormalizationCandidateBlockSemanticRun + familyContext constructorContext env blockEnv Us candidate rawDecl) := by + obtain ⟨semantic⟩ := input.exists + exact ⟨{ + semantic + familyTypesProduced + familiesProduced }⟩ + +/-- One validated singleton family stage derived from a verified entry +candidate context and the exact kernel/Theory family insertion. + +The family validator selects the parameter/index split and terminal sort. The +retained candidate semantics then prove the raw family constant well formed; +that proof extends the entry `TrEnv` and constructs the post-family verifier +context. No independently verified post-family `VEnvs` is an input. -/ +structure CandidateFamilyStagedInput + (familyContext constructorContext : AddInductive.Context) + (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.CandidateFamilyType source) + (raw : VInductiveType) + (preFamily : TypeChecker.CandidateSemanticStage familyContext env Us) + where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprStagedInput preFamily + candidate.type raw.type + validation : AddInductive.CandidateExprTrace.FamilyValidationRun + source candidate.type.trace + typeEnv : VEnv + addInduct : AddInductConstant .induct familyContext.env.constants env + raw.toVConstVal constructorContext.env.constants typeEnv + /-- The staged family environment has not yet completed a new projection + artifact; any already-complete host structure remains backed by a registered + Theory view. -/ + projectionReady : ProjectionReady constructorContext.env typeEnv + structureEtaReady : StructureEtaReady constructorContext.env typeEnv + family_lctx_eq : familyContext.lctx = {} + constructorContext_eq : constructorContext = + { familyContext with env := constructorContext.env } + quotInit_eq : constructorContext.env.quotInit = + familyContext.env.quotInit + name_not_reflected : raw.name ∉ VEnv.reflectedPrimitiveNames + name_not_primitive : + Environment.primitives.contains raw.name = false + +/-- Family validation plus retained candidate semantics prove the exact raw +Theory constant suitable for insertion. The semantic view remains hidden +under `Nonempty`; elimination is only into this proposition. -/ +theorem CandidateFamilyStagedInput.rawWF + (input : CandidateFamilyStagedInput familyContext constructorContext + env Us candidate raw preFamily) : + raw.toVConstant.WF env := by + obtain ⟨semantic⟩ := input.type.rootInput.exists + show env.IsType raw.uvars [] raw.type + simpa only [input.uvars_eq] using + semantic.source_isType_of_terminalSort input.validation.terminal_eq + +/-- The verifier context after inserting the validated raw family constant. +Primitive reflection and safety are preserved because the new family name is +not a kernel or reflected primitive. -/ +def CandidateFamilyStagedInput.postContext + (input : CandidateFamilyStagedInput familyContext constructorContext + env Us candidate raw preFamily) : TypeChecker.VContext where + env := constructorContext.env + lctx := constructorContext.lctx + lparams := constructorContext.lparams + safety := constructorContext.safety + fuel := constructorContext.fuel + venv := input.typeEnv + hasPrimitives := by + have H : env.HasPrimitives := by + simpa only [preFamily.venv_eq] using + preFamily.contextRun.context.hasPrimitives + exact VEnv.HasPrimitives.addConst H + input.name_not_reflected input.addInduct.env_add + safePrimitives := by + intro n ci + have preMapWF : familyContext.env.constants.WF := by + simpa only [preFamily.contextRun.context_env] using + preFamily.contextRun.context.trenv.map_wf + exact TypeChecker.AddInductConstant.safePrimitives input.addInduct + (n := n) (ci := ci) preMapWF (fun hfind hprim => by + apply preFamily.contextRun.context.safePrimitives + · simpa only [preFamily.contextRun.context_env] using hfind + · exact hprim) + input.name_not_primitive + trenv := by + have preTr : TrEnv' familyContext.safety familyContext.env.constants + familyContext.env.quotInit env := by + simpa only [TrEnv, preFamily.contextRun.context_safety, + preFamily.contextRun.context_env, preFamily.venv_eq] using + preFamily.contextRun.context.trenv + have postTr := TrEnv'.inductStaging input.addInduct input.rawWF preTr + change TrEnv' constructorContext.safety constructorContext.env.constants + constructorContext.env.quotInit input.typeEnv + rw [show constructorContext.safety = familyContext.safety by + rw [input.constructorContext_eq]] + rw [input.quotInit_eq] + exact postTr + projectionReady := input.projectionReady + structureEtaReady := input.structureEtaReady + mlctx := .nil + mlctx_wf := trivial + lctx_eq := by + change ({} : LocalContext) = constructorContext.lctx + rw [input.constructorContext_eq, input.family_lctx_eq] + +/-- The exact post-family candidate context constructed from family +validation, rather than supplied by a second verifier setup. -/ +def CandidateFamilyStagedInput.postContextRun + (input : CandidateFamilyStagedInput familyContext constructorContext + env Us candidate raw preFamily) : + TypeChecker.CandidateContextRun constructorContext := + TypeChecker.CandidateContextRun.ofVContext constructorContext + input.postContext (by rfl) + (TypeChecker.VState.WF.empty_of_reserves input.postContext (by + intro fv hfv + change fv ∈ VLCtx.fvars ([] : VLCtx) at hfv + simp at hfv)) + (by + rw [input.constructorContext_eq] + exact preFamily.contextRun.namePrefix_ne) + +/-- Shared post-family semantic stage consumed by every constructor position. +Its implementation and Theory environments are fixed by the exact family +insertion above. -/ +def CandidateFamilyStagedInput.postFamily + (input : CandidateFamilyStagedInput familyContext constructorContext + env Us candidate raw preFamily) : + TypeChecker.CandidateSemanticStage constructorContext input.typeEnv Us where + contextRun := input.postContextRun + venv_eq := rfl + lparams_eq := by + rw [TypeChecker.CandidateContextRun.context_lparams] + calc + constructorContext.lparams = familyContext.lparams := by + rw [input.constructorContext_eq] + _ = preFamily.contextRun.context.lparams := + preFamily.contextRun.context_lparams.symm + _ = Us := preFamily.lparams_eq + vlctx_eq := rfl + +/-- Recover the exact verified pre-family context at the end of the family +telescope. + +Constructor validation starts from this local telescope after changing only +the kernel/Theory environment to the staged post-family pair. D3 reuses the +pre-change context to replay family-free constructor checks; no local +declaration or fresh identifier is reconstructed. -/ +theorem CandidateFamilyStagedInput.preValidationContextRun + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.CandidateFamilyType source} + {raw : VInductiveType} + {preFamily : TypeChecker.CandidateSemanticStage familyContext env Us} + (_input : CandidateFamilyStagedInput familyContext constructorContext + env Us candidate raw preFamily) + (semantic : TypeChecker.CandidateExprSemanticRootRun env Us + candidate.type raw.type) : + ∃ preRun : TypeChecker.CandidateContextRun + candidate.type.trace.terminalContext, + preRun.context.venv = env ∧ + preRun.context.lparams = Us := by + obtain ⟨inferred, recursive⟩ := semantic.recursive + exact recursive.terminalContextRun semantic.contextRun semantic.venv_eq + semantic.lparams_eq semantic.vlctx_eq + +/-- Rebuild the verified constructor-validation context from the exact +pre-family terminal context run. + +The returned run preserves the implementation local context definitionally; +only the kernel/Theory environment and the primitive evidence are changed to +the staged post-family pair. -/ +theorem CandidateFamilyStagedInput.validationContextRunFromPre + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.CandidateFamilyType source} + {raw : VInductiveType} + {preFamily : TypeChecker.CandidateSemanticStage familyContext env Us} + (input : CandidateFamilyStagedInput familyContext constructorContext + env Us candidate raw preFamily) + (terminalRun : TypeChecker.CandidateContextRun + candidate.type.trace.terminalContext) + (terminalVenv : terminalRun.context.venv = env) + (terminalLparams : terminalRun.context.lparams = Us) : + ∃ validationRun : TypeChecker.CandidateContextRun + { candidate.type.trace.terminalContext with + env := constructorContext.env }, + validationRun.context.venv = input.typeEnv ∧ + validationRun.context.lparams = Us ∧ + validationRun.context.vlctx = terminalRun.context.vlctx := by + have terminalMLWF : terminalRun.context.mlctx.WF env Us := by + simpa only [terminalVenv, terminalLparams] using + terminalRun.context.mlctx_wf + have postMLWF : terminalRun.context.mlctx.WF input.typeEnv Us := + terminalMLWF.mono (VEnv.addConst_le input.addInduct.env_add) + have validationSafety : terminalRun.context.safety = + input.postContext.safety := by + calc + terminalRun.context.safety = + candidate.type.trace.terminalContext.safety := + terminalRun.context_safety + _ = candidate.type.context.safety := + candidate.type.trace.terminalContext_safety + _ = familyContext.safety := by rw [input.type.context_eq] + _ = constructorContext.safety := by rw [input.constructorContext_eq] + _ = input.postContext.safety := rfl + let validationContext : TypeChecker.VContext := + { terminalRun.context with + env := constructorContext.env + venv := input.typeEnv + hasPrimitives := input.postContext.hasPrimitives + safePrimitives := input.postContext.safePrimitives + trenv := by + have postEnv : input.postContext.env = constructorContext.env := rfl + have postVenv : input.postContext.venv = input.typeEnv := rfl + simpa only [validationSafety, postEnv, postVenv] using + input.postContext.trenv + projectionReady := input.postContext.projectionReady + structureEtaReady := input.postContext.structureEtaReady + mlctx_wf := by + simpa only [terminalLparams] using postMLWF } + have validationContextEq : validationContext.toContext = + ({ candidate.type.trace.terminalContext with + env := constructorContext.env } : AddInductive.Context).toTypeChecker := by + calc + validationContext.toContext = + { terminalRun.context.toContext with + env := constructorContext.env } := rfl + _ = { candidate.type.trace.terminalContext.toTypeChecker with + env := constructorContext.env } := + congrArg (fun c : TypeChecker.Context => + { c with env := constructorContext.env }) terminalRun.context_eq + _ = ({ candidate.type.trace.terminalContext with + env := constructorContext.env } : AddInductive.Context).toTypeChecker := + rfl + let validationRun : TypeChecker.CandidateContextRun + { candidate.type.trace.terminalContext with + env := constructorContext.env } := + TypeChecker.CandidateContextRun.ofVContext _ validationContext + validationContextEq + (TypeChecker.VState.WF.empty_of_reserves validationContext (by + intro fv hfv + exact terminalRun.state_wf.ngen_wf fv (by + simpa only [validationContext] using hfv))) + terminalRun.namePrefix_ne + exact ⟨validationRun, rfl, terminalLparams, rfl⟩ + +/-- Rebuild the verified context in which constructor validation actually +runs. + +Family candidates are interpreted before the raw family is inserted, so the +recursive run reaches the correct local telescope in the pre-family Theory +environment. Constructor validation keeps that exact implementation local +context while replacing only the kernel/Theory environment with the staged +post-family pair. Monotonicity of local-context verification justifies that +replacement; no local declaration, free-variable identifier, or binder order +is regenerated. -/ +theorem CandidateFamilyStagedInput.validationContextRun + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.CandidateFamilyType source} + {raw : VInductiveType} + {preFamily : TypeChecker.CandidateSemanticStage familyContext env Us} + (input : CandidateFamilyStagedInput familyContext constructorContext + env Us candidate raw preFamily) + (semantic : TypeChecker.CandidateExprSemanticRootRun env Us + candidate.type raw.type) : + ∃ validationRun : TypeChecker.CandidateContextRun + { candidate.type.trace.terminalContext with + env := constructorContext.env }, + validationRun.context.venv = input.typeEnv ∧ + validationRun.context.lparams = Us := by + obtain ⟨terminalRun, terminalVenv, terminalLparams⟩ := + input.preValidationContextRun semantic + obtain ⟨validationRun, validationVenv, validationLparams, _⟩ := + input.validationContextRunFromPre terminalRun terminalVenv terminalLparams + exact ⟨validationRun, validationVenv, validationLparams⟩ + +/-- One source-indexed constructor interpreted in the shared post-family +stage. Header equality and universe alignment stay attached to the exact raw +constructor position; the expression payload contains no independently +verified context and no caller-selected semantic view. -/ +structure CandidateConstructorStagedInput + {candidateContext : AddInductive.Context} {env : VEnv} {Us : List Name} + (stage : TypeChecker.CandidateSemanticStage candidateContext env Us) + {source : Constructor} + (candidate : AddInductive.CandidateConstructor source) + (raw : VConstVal) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprStagedInput stage candidate.type raw.type + +/-- Forget only the shared-stage presentation and recover the established +constructor semantic input. -/ +def CandidateConstructorStagedInput.semanticInput + {candidateContext : AddInductive.Context} {env : VEnv} {Us : List Name} + {source : Constructor} + {candidate : AddInductive.CandidateConstructor source} + {raw : VConstVal} + {stage : TypeChecker.CandidateSemanticStage candidateContext env Us} + (input : CandidateConstructorStagedInput stage candidate raw) : + CandidateConstructorSemanticInput env Us candidate raw where + name_eq := input.name_eq + uvars_eq := input.uvars_eq + type := input.type.rootInput + +/-- Exact source-order translations for every constructor in one shared +post-family stage. The dependent indices enforce length, order, source, raw +header, and candidate alignment without `zip` or list lookup. -/ +inductive CandidateConstructorStagedListInput + {candidateContext : AddInductive.Context} {env : VEnv} {Us : List Name} + (stage : TypeChecker.CandidateSemanticStage candidateContext env Us) : + {sources : List Constructor} → + AddInductive.CandidateList AddInductive.CandidateConstructor sources → + List VConstVal → Type where + | nil : CandidateConstructorStagedListInput stage .nil [] + | cons + (head : CandidateConstructorStagedInput stage candidate raw) + (tail : CandidateConstructorStagedListInput stage candidates raws) : + CandidateConstructorStagedListInput stage + (.cons candidate candidates) (raw :: raws) + +/-- Convert the staged, source-indexed constructor translations to the +existing recursive semantic-input representation. -/ +def CandidateConstructorStagedListInput.semanticInput + {candidateContext : AddInductive.Context} {env : VEnv} {Us : List Name} + {stage : TypeChecker.CandidateSemanticStage candidateContext env Us} + {sources : List Constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor sources} + {raws : List VConstVal} + (input : CandidateConstructorStagedListInput stage candidates raws) : + CandidateConstructorSemanticListInput env Us candidates raws := + match input with + | .nil => CandidateConstructorSemanticListInput.nil + | .cons head tail => + CandidateConstructorSemanticListInput.cons + head.semanticInput tail.semanticInput + +/-- Pre-run semantic evidence for a complete singleton family position. The +family type is interpreted in the input environment and its constructor list +in the exact environment obtained by inserting the raw family constant. -/ +structure CandidateFamilySemanticInput (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.CandidateFamily source) + (raw : VInductiveType) where + name_eq : source.name = raw.name + uvars_eq : raw.uvars = Us.length + type : TypeChecker.CandidateExprSemanticRootInput env Us + candidate.familyType.type raw.type + typeEnv : VEnv + addType : env.addConst raw.name raw.toVConstant = some typeEnv + constructors : CandidateConstructorSemanticListInput typeEnv Us + candidate.constructors raw.ctors + +/-- Interpret the family root and all post-insertion constructor roots from +their exact pre-run inputs. -/ +theorem CandidateFamilySemanticInput.exists + (input : CandidateFamilySemanticInput env Us candidate raw) : + Nonempty (CandidateFamilySemanticRun env Us candidate raw) := by + obtain ⟨type⟩ := input.type.exists + obtain ⟨constructors⟩ := input.constructors.exists + exact ⟨{ + name_eq := input.name_eq + uvars_eq := input.uvars_eq + type := type + typeEnv := input.typeEnv + addType := input.addType + constructors := constructors }⟩ + +/-- Pre-run semantic evidence for one source-indexed singleton normalization +candidate. The source declaration and candidate list indices rule out an +unrelated raw family or a partial constructor list. -/ +structure NormalizationCandidateSemanticInput (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + raw : VInductiveType + raw_types_eq : rawDecl.types = [raw] + uvars_eq : rawDecl.uvars = Us.length + family : CandidateFamilySemanticInput env Us + candidate.families.singleton raw + +/-- Automatically interpret the complete singleton semantic hierarchy from +its verified, source-indexed inputs. -/ +theorem NormalizationCandidateSemanticInput.exists + (input : NormalizationCandidateSemanticInput env Us candidate rawDecl) : + Nonempty (NormalizationCandidateSemanticRun env Us candidate rawDecl) := by + obtain ⟨family⟩ := input.family.exists + exact ⟨{ + raw := input.raw + raw_types_eq := input.raw_types_eq + uvars_eq := input.uvars_eq + family := family }⟩ + +/-- The automatic semantic hierarchy paired with the exact executable +family-type and constructor-list traversals that selected the same dependent +candidate. The two producer contexts are explicit because family types are +checked before raw-family insertion and constructors after it. -/ +structure ProducedNormalizationCandidateSemanticRun + (familyContext constructorContext : AddInductive.Context) + (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + semantic : NormalizationCandidateSemanticRun env Us candidate rawDecl + familyTypesProduced : AddInductive.CandidateFamilyTypeListProduced + familyContext + (.cons candidate.families.singleton.familyType .nil) + familiesProduced : AddInductive.CandidateFamilyListProduced + constructorContext + (.cons candidate.families.singleton.familyType .nil) + candidate.families + +/-- Combine exact arbitrary-length producer witnesses with verified semantic +inputs for the same source-indexed singleton candidate. Operational evidence +selects the candidate; only the retained checker interpreter supplies Theory +meaning. -/ +theorem NormalizationCandidateSemanticInput.exists_ofProduced + (input : NormalizationCandidateSemanticInput env Us candidate rawDecl) + (familyTypesProduced : AddInductive.CandidateFamilyTypeListProduced + familyContext + (.cons candidate.families.singleton.familyType .nil)) + (familiesProduced : AddInductive.CandidateFamilyListProduced + constructorContext + (.cons candidate.families.singleton.familyType .nil) + candidate.families) : + Nonempty (ProducedNormalizationCandidateSemanticRun + familyContext constructorContext env Us candidate rawDecl) := by + obtain ⟨semantic⟩ := input.exists + exact ⟨{ + semantic := semantic + familyTypesProduced := familyTypesProduced + familiesProduced := familiesProduced }⟩ + +/-- The complete family-validated semantic input for a produced singleton +candidate. + +Only the entry verifier alignment is supplied. The exact singleton family +validation and raw-family insertion derive the post-family verified stage; +constructor positions then supply strict translations and fuel equalities in +that derived stage. No normalized view, post-family `VEnvs.WF`, semantic run, +declaration-WF proof, or generation package is an input. -/ +structure StagedNormalizationCandidateSemanticInput + (familyContext constructorContext : AddInductive.Context) + (env : VEnv) (Us : List Name) + {source : InductiveType} + (candidate : AddInductive.NormalizationCandidate [source]) + (rawDecl : VInductDecl) where + raw : VInductiveType + raw_types_eq : rawDecl.types = [raw] + declaration_uvars_eq : rawDecl.uvars = Us.length + preFamily : TypeChecker.CandidateSemanticStage familyContext env Us + family : CandidateFamilyStagedInput familyContext constructorContext env Us + candidate.families.singleton.familyType raw preFamily + validation_nparams_eq : family.validation.nparams = rawDecl.nparams + constructorValidation : AddInductive.ConstructorValidationRun + source family.validation.stats false + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } + constructors : CandidateConstructorStagedListInput family.postFamily + candidate.families.singleton.constructors raw.ctors + familyTypesProduced : AddInductive.CandidateFamilyTypeListProduced + familyContext + (.cons candidate.families.singleton.familyType .nil) + familiesProduced : AddInductive.CandidateFamilyListProduced + constructorContext + (.cons candidate.families.singleton.familyType .nil) + candidate.families + +/-- The staged owner retains exactly the successful executable constructor +validation that selected its source-indexed constructor list. -/ +theorem StagedNormalizationCandidateSemanticInput.constructorValidation_run + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidateSemanticInput familyContext + constructorContext env Us candidate rawDecl) : + AddInductive.checkConstructors #[source] input.family.validation.stats + false + { candidate.families.singleton.familyType.type.trace.terminalContext with + env := constructorContext.env } = .ok () := + input.constructorValidation.run + +/-- Project the established semantic-input hierarchy from the consolidated +two-stage owner. This projection remains data-free with respect to checker +semantics: it only rearranges verified stage and translation evidence. -/ +def StagedNormalizationCandidateSemanticInput.semanticInput + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidateSemanticInput familyContext + constructorContext env Us candidate rawDecl) : + NormalizationCandidateSemanticInput env Us candidate rawDecl where + raw := input.raw + raw_types_eq := input.raw_types_eq + uvars_eq := input.declaration_uvars_eq + family := { + name_eq := input.family.name_eq + uvars_eq := input.family.uvars_eq + type := input.family.type.rootInput + typeEnv := input.family.typeEnv + addType := input.family.addInduct.env_add + constructors := input.constructors.semanticInput } + +/-- Interpret a complete produced singleton candidate from its entry stage and +derived family-validation stage. The result stays in `Nonempty`; in particular, this theorem +does not use choice to expose a semantic run as executable data. -/ +theorem StagedNormalizationCandidateSemanticInput.exists + {familyContext constructorContext : AddInductive.Context} + {env : VEnv} {Us : List Name} {source : InductiveType} + {candidate : AddInductive.NormalizationCandidate [source]} + {rawDecl : VInductDecl} + (input : StagedNormalizationCandidateSemanticInput familyContext + constructorContext env Us candidate rawDecl) : + Nonempty (ProducedNormalizationCandidateSemanticRun + familyContext constructorContext env Us candidate rawDecl) := + input.semanticInput.exists_ofProduced input.familyTypesProduced + input.familiesProduced + +/-- Forget executable list provenance and expose the existing normalization +root selected by the automatic semantic hierarchy. -/ +def ProducedNormalizationCandidateSemanticRun.root + (run : ProducedNormalizationCandidateSemanticRun + familyContext constructorContext env Us candidate rawDecl) : + NormalizationCandidateRun env Us candidate rawDecl := + run.semantic.root + +/-- Checker-produced semantic evidence for one positional raw/view +constructor pair. This has the same four-way declared/emitted split as +`NormalizedCtor.WF`, but keeps every equality in compositional evidence form +until the final Theory boundary. -/ +structure NormalizedCtorRun {source : VInductDecl} + (block : NormalizedChecked source) (ctor : NormalizedCtor) + (env : VEnv) where + declaredTel : TypeChecker.TelDefEqEvidence env source.uvars [] + (ctor.declaredBinders source.nparams) (ctor.viewBinders block) + declaredResult : TypeChecker.DefEqEvidence env source.uvars + (ctor.declaredBinders source.nparams).reverse + (ctor.rawResult source.nparams) (ctor.resultTarget block) + (.sort block.checked.resultLevel) + emittedTel : TypeChecker.TelDefEqEvidence env source.uvars [] + (ctor.emittedBinders block) (ctor.viewBinders block) + emittedResult : TypeChecker.DefEqEvidence env source.uvars + (ctor.emittedBinders block).reverse + (ctor.rawResult source.nparams) (ctor.resultTarget block) + (.sort block.checked.resultLevel) + +theorem NormalizedCtorRun.wf + (run : NormalizedCtorRun block ctor env) : + ctor.WF block env where + declaredTel := run.declaredTel.telDefEq + declaredResult := run.declaredResult.isDefEq + emittedTel := run.emittedTel.telDefEq + emittedResult := run.emittedResult.isDefEq + +/-- Complete checker-side assembler for a generation-ready candidate. + +The exact family insertion state is named once. This lets a producer check +constructor evidence in that state and lets `.wf` discharge the universally +quantified post-family environment in `GenerationChecked.WF` by equality, +without an oracle or an assumed transaction. -/ +structure GenerationRun {source : VInductDecl} + (generation : GenerationChecked source) (env : VEnv) where + normalization : NormalizationRun generation.block.normalization env + checked : generation.block.checked.WF env + familyTel : TypeChecker.TelDefEqEvidence env source.uvars [] + (generation.block.rawParams ++ generation.block.rawIndices) + (generation.block.checked.params ++ generation.block.checked.indices) + familyResult : TypeChecker.DefEqEvidence env source.uvars + (generation.block.rawParams ++ generation.block.rawIndices).reverse + generation.block.rawResult (.sort generation.block.checked.resultLevel) + (.sort (.succ generation.block.checked.resultLevel)) + typeEnv : VEnv + addType : env.addConst generation.block.sourceType.name + generation.block.sourceType.toVConstant = some typeEnv + constructors : + ∀ ctor ∈ generation.block.ctorPairs, + NormalizedCtorRun generation.block ctor typeEnv + +/-- Assemble the complete Theory generation certificate from exact +checker-produced normalization, telescope, result, and constructor evidence. -/ +theorem GenerationRun.wf + (run : GenerationRun generation env) : + generation.WF env := by + refine { + blockWF := ⟨run.normalization.wf, run.checked⟩ + familyTel := run.familyTel.telDefEq + familyResult := run.familyResult.isDefEq + ctors := ?_ } + intro envT hadd ctor hctor + have henv : envT = run.typeEnv := by + have : some envT = some run.typeEnv := hadd.symm.trans run.addType + exact Option.some.inj this + subst envT + exact (run.constructors ctor hctor).wf + +/-- Exact family-spine evidence extracted from the source-indexed singleton +normalization candidate and aligned with the components retained by dependent +inductive analysis. -/ +structure CandidateFamilyGenerationRun + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateRun env Us candidate source) + (generation : GenerationChecked source) where + spine : TypeChecker.CandidateExprSpineRun env Us + candidate.families.singleton.familyType.type + normalization.raw.type normalization.family.viewType + rawTel : VExpr.telN + candidate.families.singleton.familyType.type.trace.spineLength + normalization.raw.type = + generation.block.rawParams ++ generation.block.rawIndices + rawResult : VExpr.dropN + candidate.families.singleton.familyType.type.trace.spineLength + normalization.raw.type = generation.block.rawResult + viewResult : VExpr.dropN + candidate.families.singleton.familyType.type.trace.spineLength + normalization.family.viewType = + .sort generation.block.checked.resultLevel + +/-- Extract the complete family telescope/result certificate at the exact +components consumed by `GenerationRun`. -/ +theorem CandidateFamilyGenerationRun.evidence + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : CandidateFamilyGenerationRun normalization generation) + (viewType_eq : normalization.family.viewType = + generation.block.checked.type.type) : + TypeChecker.TelResultDefEqEvidence env Us.length [] + (generation.block.rawParams ++ generation.block.rawIndices) + (generation.block.checked.params ++ generation.block.checked.indices) + generation.block.rawResult + (.sort generation.block.checked.resultLevel) + (.sort (.succ generation.block.checked.resultLevel)) := + run.spine.evidenceAt run.rawTel (by + rw [viewType_eq, generation.block.checked.type_eq, + ← VExpr.forallN_append] + apply TypeChecker.candidateTelN_of_dropN_terminal (B := + .sort generation.block.checked.resultLevel) trivial + simpa only [viewType_eq, generation.block.checked.type_eq, + ← VExpr.forallN_append] using run.viewResult) + run.rawResult run.viewResult (by + apply VEnv.HasType.sort + simpa only [← generation.block.uvars_eq, + normalization.uvars_eq] using + generation.block.checked.direct_anatomy.2.2.1) + +/-- Family generation alignment whose spine is projected directly from the +retained semantic hierarchy. Callers provide only the executable structural +gate and the component equations required by `GenerationChecked`; they cannot +substitute a second recursive run or a different normalized view. -/ +structure CandidateFamilySemanticGenerationRun + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) where + storedSpine : + candidate.families.singleton.familyType.type.trace.storedSpine = true + rawTel : VExpr.telN + candidate.families.singleton.familyType.type.trace.spineLength + normalization.raw.type = + generation.block.rawParams ++ generation.block.rawIndices + rawResult : VExpr.dropN + candidate.families.singleton.familyType.type.trace.spineLength + normalization.raw.type = generation.block.rawResult + viewResult : VExpr.dropN + candidate.families.singleton.familyType.type.trace.spineLength + normalization.family.type.view = + .sort generation.block.checked.resultLevel + +/-- Minimal structural input for family generation. The retained semantic +root already owns the recursive checker run, while dependent analysis fixes +the raw and checked components. A caller therefore supplies only the +executable stored-spine gate and the total number of binders traversed by that +spine; all telescope and terminal equations are derived below. -/ +structure CandidateFamilySemanticGenerationShape + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) where + storedSpine : + candidate.families.singleton.familyType.type.trace.storedSpine = true + spineLength_eq : + candidate.families.singleton.familyType.type.trace.spineLength = + (generation.block.rawParams ++ generation.block.rawIndices).length + +/-- Recover the existing family-generation run from the single retained +semantic owner. -/ +theorem CandidateFamilySemanticGenerationRun.run + (run : CandidateFamilySemanticGenerationRun normalization generation) : + CandidateFamilyGenerationRun normalization.root generation where + spine := normalization.family.type.spine run.storedSpine + rawTel := run.rawTel + rawResult := run.rawResult + viewResult := run.viewResult + +/-- One positional constructor candidate aligned with the raw/view +constructor pair retained by dependent analysis. + +The spine certificate covers the exact stored constructor type. Its declared +telescope will later be transformed into the mixed emitted telescope by +replacing only the constructor's parameter prefix. -/ +structure CandidateNormalizedCtorRun {source : VInductDecl} + (block : NormalizedChecked source) (env : VEnv) (Us : List Name) + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + (root : CandidateConstructorRun env Us candidate raw) + (ctor : NormalizedCtor) where + raw_eq : ctor.raw = raw + view_eq : ctor.view.value = root.view + spine : TypeChecker.CandidateExprSpineRun env Us candidate.type + raw.type root.viewType + rawTel : VExpr.telN candidate.type.trace.spineLength raw.type = + ctor.declaredBinders source.nparams + rawResult : VExpr.dropN candidate.type.trace.spineLength raw.type = + ctor.rawResult source.nparams + viewResult : VExpr.dropN candidate.type.trace.spineLength root.viewType = + ctor.resultTarget block + +/-- Constructor generation alignment owned by the same retained semantic root +used for normalization. The only spine premise is the Boolean structural gate +computed by the candidate trace; the recursive semantic run and view are +projected from `root`. -/ +structure CandidateSemanticNormalizedCtorRun {source : VInductDecl} + (block : NormalizedChecked source) (env : VEnv) (Us : List Name) + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + (root : CandidateConstructorSemanticRun env Us candidate raw) + (ctor : NormalizedCtor) where + raw_eq : ctor.raw = raw + view_eq : ctor.view.value = root.root.view + storedSpine : candidate.type.trace.storedSpine = true + rawTel : VExpr.telN candidate.type.trace.spineLength raw.type = + ctor.declaredBinders source.nparams + rawResult : VExpr.dropN candidate.type.trace.spineLength raw.type = + ctor.rawResult source.nparams + viewResult : VExpr.dropN candidate.type.trace.spineLength root.type.view = + ctor.resultTarget block + +/-- Minimal structural input for one retained constructor root. It is +independent of a caller-selected normalized pair: positional raw/view pairing +is recovered from the successful dependent analysis, and the full component +equations follow from this total stored-binder count. -/ +structure CandidateConstructorSemanticGenerationShape + {source : VInductDecl} (env : VEnv) (Us : List Name) + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + (root : CandidateConstructorSemanticRun env Us candidate raw) where + storedSpine : candidate.type.trace.storedSpine = true + spineLength_eq : candidate.type.trace.spineLength = + (VExpr.telN source.nparams raw.type ++ + ctorFields (VExpr.dropN source.nparams raw.type)).length + +/-- Project the compatibility constructor run without rebuilding or choosing +semantic evidence. -/ +theorem CandidateSemanticNormalizedCtorRun.run + (run : CandidateSemanticNormalizedCtorRun block env Us root ctor) : + CandidateNormalizedCtorRun block env Us root.root ctor where + raw_eq := run.raw_eq + view_eq := run.view_eq + spine := root.type.spine run.storedSpine + rawTel := run.rawTel + rawResult := run.rawResult + viewResult := run.viewResult + +/-- The terminal alignment and the analyzer's exact constructor shape force +the candidate trace to expose the entire checked binder telescope. -/ +theorem CandidateNormalizedCtorRun.viewTel_eq + {source : VInductDecl} {generation : GenerationChecked source} + {env : VEnv} {Us : List Name} + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + {root : CandidateConstructorRun env Us candidate raw} + {ctor : NormalizedCtor} + (run : CandidateNormalizedCtorRun generation.block env Us root ctor) + (hctor : ctor ∈ generation.block.ctorPairs) : + VExpr.telN candidate.type.trace.spineLength root.viewType = + ctor.viewBinders generation.block := by + have viewType_eq : root.viewType = ctor.view.value.type := by + simpa only [CandidateConstructorRun.view] using + (congrArg (fun value : VConstVal => value.type) run.view_eq).symm + have hterminal : + TypeChecker.CandidateTerminal (ctor.resultTarget generation.block) := by + exact TypeChecker.candidateTerminal_appN_const _ _ _ + rw [viewType_eq, generation.viewCtorType_eq hctor] + apply TypeChecker.candidateTelN_of_dropN_terminal hterminal + simpa only [viewType_eq, generation.viewCtorType_eq hctor] using + run.viewResult + +/-- Extract the stored constructor's declared telescope/result evidence. -/ +theorem CandidateNormalizedCtorRun.declaredEvidence + {source : VInductDecl} {generation : GenerationChecked source} + {env : VEnv} {Us : List Name} + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + {root : CandidateConstructorRun env Us candidate raw} + {ctor : NormalizedCtor} + (run : CandidateNormalizedCtorRun generation.block env Us root ctor) + (hctor : ctor ∈ generation.block.ctorPairs) + (rightType : env.HasType Us.length + (ctor.declaredBinders source.nparams).reverse + (ctor.resultTarget generation.block) + (.sort generation.block.checked.resultLevel)) : + TypeChecker.TelResultDefEqEvidence env Us.length [] + (ctor.declaredBinders source.nparams) + (ctor.viewBinders generation.block) + (ctor.rawResult source.nparams) (ctor.resultTarget generation.block) + (.sort generation.block.checked.resultLevel) := by + apply run.spine.evidenceAt run.rawTel (run.viewTel_eq hctor) + run.rawResult run.viewResult rightType + +/-- The checked result spine and the candidate-certified binder telescope +determine a constructor's terminal typing judgment. The family constant is +typed once for the whole block; individual constructor fixtures supply no +additional semantic result oracle. -/ +theorem CandidateNormalizedCtorRun.rightType_ofChecked + {source : VInductDecl} {generation : GenerationChecked source} + {env : VEnv} {Us : List Name} + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + {root : CandidateConstructorRun env Us candidate raw} + {ctor : NormalizedCtor} + (run : CandidateNormalizedCtorRun generation.block env Us root ctor) + (henv : VEnv.WF env) (uvars_eq : source.uvars = Us.length) + (checked : generation.block.checked.WF env) + (familyConst : env.HasType source.uvars [] + (.const generation.block.sourceType.name + (VLevel.params source.uvars)) + generation.block.checked.type.type) + (hctor : ctor ∈ generation.block.ctorPairs) : + env.HasType Us.length + (ctor.declaredBinders source.nparams).reverse + (ctor.resultTarget generation.block) + (.sort generation.block.checked.resultLevel) := by + obtain ⟨_, evidence⟩ := run.spine.evidence + have telescope : TypeChecker.TelDefEqEvidence env Us.length [] + (ctor.declaredBinders source.nparams) + (ctor.viewBinders generation.block) := by + simpa only [run.rawTel, run.viewTel_eq hctor] using evidence.telescope + have hview := generation.checkedResultTarget_hasType + henv.ordered checked familyConst hctor + have hview' : env.HasType Us.length + (ctor.viewBinders generation.block).reverse + (ctor.resultTarget generation.block) + (.sort generation.block.checked.resultLevel) := by + simpa only [uvars_eq] using hview + have hctx : env.IsDefEqCtx Us.length [] + (ctor.declaredBinders source.nparams).reverse + (ctor.viewBinders generation.block).reverse := by + simpa using telescope.telDefEq.ctx + exact hview'.defeqDFC henv.ordered (hctx.symm henv.ordered) + +/-- Produce both constructor paths required by `NormalizedCtorRun`. + +The declared path comes directly from the constructor candidate. The emitted +path replaces the stored constructor parameter prefix by the checked family +parameter prefix used by Lean's recursor generator, transporting fields and +result through the induced definitionally equal context. -/ +theorem CandidateNormalizedCtorRun.normalizedCtorRun + {source : VInductDecl} {generation : GenerationChecked source} + {env : VEnv} {Us : List Name} + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + {root : CandidateConstructorRun env Us candidate raw} + {ctor : NormalizedCtor} + (run : CandidateNormalizedCtorRun generation.block env Us root ctor) + (henv : VEnv.WF env) (uvars_eq : source.uvars = Us.length) + (familyParams : TypeChecker.TelDefEqEvidence env Us.length [] + generation.block.rawParams generation.block.checked.params) + (prefixLength : + (VExpr.telN source.nparams ctor.raw.type).length = + generation.block.checked.params.length) + (hctor : ctor ∈ generation.block.ctorPairs) + (rightType : env.HasType Us.length + (ctor.declaredBinders source.nparams).reverse + (ctor.resultTarget generation.block) + (.sort generation.block.checked.resultLevel)) : + NormalizedCtorRun generation.block ctor env := by + have declared := run.declaredEvidence hctor rightType + have declaredSplit : TypeChecker.TelResultDefEqEvidence env Us.length [] + (VExpr.telN source.nparams ctor.raw.type ++ + ctor.rawFields source.nparams) + (generation.block.checked.params ++ ctor.view.fields) + (ctor.rawResult source.nparams) (ctor.resultTarget generation.block) + (.sort generation.block.checked.resultLevel) := by + simpa only [NormalizedCtor.declaredBinders, + NormalizedCtor.viewBinders] using declared + have checkedParams : TypeChecker.TelDefEqEvidence env Us.length [] + generation.block.checked.params generation.block.checked.params := + .ofTelDefEq <| (familyParams.telDefEq.view_onTel henv.ordered).telDefEq_refl + have emitted := declaredSplit.replacePrefix henv checkedParams prefixLength + exact { + declaredTel := by + simpa only [uvars_eq] using declared.telescope + declaredResult := by + simpa only [uvars_eq, List.append_nil] using declared.result + emittedTel := by + simpa only [uvars_eq, NormalizedCtor.emittedBinders, + NormalizedCtor.viewBinders] using emitted.telescope + emittedResult := by + simpa only [uvars_eq, NormalizedCtor.emittedBinders, + List.append_nil] using emitted.result } + +/-- Dependent positional alignment between every constructor candidate run +and every normalized constructor pair. The indices make unequal lengths, +reordering, and evidence reuse at a different source position impossible. -/ +inductive CandidateNormalizedCtorListRun {source : VInductDecl} + (block : NormalizedChecked source) (env : VEnv) (Us : List Name) : + {kernelSources : List Constructor} → + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor kernelSources} → + {raws : List VConstVal} → + (roots : CandidateConstructorListRun env Us candidates raws) → + List NormalizedCtor → Type where + | nil : CandidateNormalizedCtorListRun block env Us .nil [] + | cons + (head : CandidateNormalizedCtorRun block env Us root ctor) + (tail : CandidateNormalizedCtorListRun block env Us roots ctors) : + CandidateNormalizedCtorListRun block env Us + (.cons root roots) (ctor :: ctors) + +/-- Dependent positional generation alignment over the retained constructor +semantic list. Its projection below is definitionally tied to +`roots.roots`, so source order and the exact normalization views cannot drift +between phases. -/ +inductive CandidateSemanticNormalizedCtorListRun {source : VInductDecl} + (block : NormalizedChecked source) (env : VEnv) (Us : List Name) : + {kernelSources : List Constructor} → + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor kernelSources} → + {raws : List VConstVal} → + (roots : CandidateConstructorSemanticListRun env Us candidates raws) → + List NormalizedCtor → Type where + | nil : CandidateSemanticNormalizedCtorListRun block env Us .nil [] + | cons + (head : CandidateSemanticNormalizedCtorRun block env Us root ctor) + (tail : CandidateSemanticNormalizedCtorListRun block env Us roots ctors) : + CandidateSemanticNormalizedCtorListRun block env Us + (.cons root roots) (ctor :: ctors) + +/-- Source-indexed structural generation inputs for every retained semantic +constructor root. No normalized constructor list occurs in this type, so a +caller cannot choose, reorder, truncate, or duplicate the analyzer's pairs. -/ +inductive CandidateConstructorSemanticGenerationShapeList + (source : VInductDecl) (env : VEnv) (Us : List Name) : + {kernelSources : List Constructor} → + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor kernelSources} → + {raws : List VConstVal} → + (roots : CandidateConstructorSemanticListRun env Us candidates raws) → + Type where + | nil : CandidateConstructorSemanticGenerationShapeList source env Us .nil + | cons + (head : CandidateConstructorSemanticGenerationShape + (source := source) env Us root) + (tail : CandidateConstructorSemanticGenerationShapeList + source env Us roots) : + CandidateConstructorSemanticGenerationShapeList source env Us + (.cons root roots) + +/-- Executable generation-layout check for a complete source-indexed +constructor candidate list. + +The check is intentionally stated against the raw Theory constants retained +by the semantic hierarchy. It accepts exactly when every candidate WHNF trace +preserves the stored main Pi spine and traverses the complete raw constructor +telescope. List-length mismatches are rejected explicitly; no `zip` or +positional lookup can silently truncate either side. -/ +def candidateConstructorSemanticGenerationShape + (source : VInductDecl) : + {kernelSources : List Constructor} → + AddInductive.CandidateList AddInductive.CandidateConstructor + kernelSources → + List VConstVal → Bool + | _, .nil, [] => true + | _, .nil, _ :: _ => false + | _, .cons _ _, [] => false + | _, .cons candidate candidates, raw :: raws => + candidate.type.trace.storedSpine && + candidate.type.trace.spineLength == + (VExpr.telN source.nparams raw.type ++ + ctorFields (VExpr.dropN source.nparams raw.type)).length && + candidateConstructorSemanticGenerationShape source candidates raws + +/-- Executable generation-layout check for a complete singleton +normalization candidate and its raw Theory family. + +This definition is independent of semantic proofs. It checks only the +source-indexed candidate traces against the raw family/constructor telescope +layout that generation would emit. Verify's retained semantic hierarchy +later reindexes the same Boolean onto its exact raw family. -/ +def normalizationCandidateGenerationShape + {kernelSource : InductiveType} + (source : VInductDecl) (raw : VInductiveType) + (candidate : AddInductive.NormalizationCandidate [kernelSource]) : Bool := + let familyTrace := + candidate.families.singleton.familyType.type.trace + (familyTrace.storedSpine && + familyTrace.spineLength == + (VExpr.telN source.nparams raw.type ++ + ctorFields (VExpr.dropN source.nparams raw.type)).length) && + candidateConstructorSemanticGenerationShape source + candidate.families.singleton.constructors raw.ctors + +/-- One executable constructor-list shape check determines every dependent +per-position shape record required by semantic generation. -/ +def CandidateConstructorSemanticGenerationShapeList.ofCheck + {source : VInductDecl} {env : VEnv} {Us : List Name} + {kernelSources : List Constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor kernelSources} + {raws : List VConstVal} + (roots : CandidateConstructorSemanticListRun env Us candidates raws) + (shape : candidateConstructorSemanticGenerationShape + source candidates raws = true) : + CandidateConstructorSemanticGenerationShapeList source env Us roots := + match roots with + | .nil => .nil + | .cons head tail => by + simp only [candidateConstructorSemanticGenerationShape, + Bool.and_eq_true, beq_iff_eq] at shape + exact .cons { + storedSpine := shape.1.1 + spineLength_eq := shape.1.2 } + (CandidateConstructorSemanticGenerationShapeList.ofCheck + tail shape.2) +termination_by sizeOf roots + +/-- Forget only retained semantic ownership and recover the existing +generation-facing positional list. -/ +def CandidateSemanticNormalizedCtorListRun.run : + (semantic : CandidateSemanticNormalizedCtorListRun + block env Us roots ctors) → + CandidateNormalizedCtorListRun block env Us roots.roots ctors + | .nil => .nil + | .cons head tail => .cons head.run tail.run + +/-- Assemble a `NormalizedCtorRun` for every constructor in an exact +dependent positional list. -/ +theorem CandidateNormalizedCtorListRun.normalizedCtorRuns + {source : VInductDecl} {generation : GenerationChecked source} + {env : VEnv} {Us : List Name} + {kernelSources : List Constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor kernelSources} + {raws : List VConstVal} + {roots : CandidateConstructorListRun env Us candidates raws} + {ctors : List NormalizedCtor} + (run : CandidateNormalizedCtorListRun generation.block env Us roots ctors) + (henv : VEnv.WF env) (uvars_eq : source.uvars = Us.length) + (familyParams : TypeChecker.TelDefEqEvidence env Us.length [] + generation.block.rawParams generation.block.checked.params) + (checked : generation.block.checked.WF env) + (familyConst : env.HasType source.uvars [] + (.const generation.block.sourceType.name + (VLevel.params source.uvars)) + generation.block.checked.type.type) + (pairMembership : ∀ ctor ∈ ctors, + ctor ∈ generation.block.ctorPairs) + (prefixLengths : ∀ ctor ∈ ctors, + (VExpr.telN source.nparams ctor.raw.type).length = + generation.block.checked.params.length) : + ∀ ctor ∈ ctors, NormalizedCtorRun generation.block ctor env := by + induction run with + | nil => intro ctor hctor; simp at hctor + | cons head tail ih => + intro ctor hctor + simp only [List.mem_cons] at hctor + rcases hctor with rfl | hctor + · exact head.normalizedCtorRun henv uvars_eq familyParams + (prefixLengths _ (.head _)) + (pairMembership _ (.head _)) + (head.rightType_ofChecked henv uvars_eq checked familyConst + (pairMembership _ (.head _))) + · exact ih + (fun ctor hctor => pairMembership ctor (.tail _ hctor)) + (fun ctor hctor => prefixLengths ctor (.tail _ hctor)) + ctor hctor + +/-- Complete source-indexed candidate certificate for one generation-ready +singleton inductive declaration. + +`analysis` records that the candidate-derived normalization produced this exact +dependent generation result. `constructors` then aligns every post-family +candidate run with the corresponding dependent analyzer pair. -/ +structure GenerationCandidateRun + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateRun env Us candidate source) + (generation : GenerationChecked source) where + analysis : normalization.normalization.generation? = some generation + checked : generation.block.checked.WF env + family : CandidateFamilyGenerationRun normalization generation + constructors : CandidateNormalizedCtorListRun generation.block + normalization.family.typeEnv Us normalization.family.constructors + generation.block.ctorPairs + +/-- Complete generation assembly owned by one retained semantic hierarchy. + +This is the no-parallel-run form of `GenerationCandidateRun`: family and +constructor spines are projections of `normalization`, while `analysis` retains +the exact dependent analyzer result consumed by Theory generation. -/ +structure GenerationCandidateSemanticRun + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) where + analysis : normalization.root.normalization.generation? = some generation + checked : generation.block.checked.WF env + family : CandidateFamilySemanticGenerationRun normalization generation + constructors : CandidateSemanticNormalizedCtorListRun generation.block + normalization.family.typeEnv Us normalization.family.constructors + generation.block.ctorPairs + +/-- Complete semantic-generation input with all analyzer-determined component +equations erased. Compared with `GenerationCandidateSemanticRun`, this form +retains only checked semantics plus the executable stored-spine/length shape +for each source-indexed root. Its projection below reconstructs the exact +family and dependent constructor alignment from `analysis`. -/ +structure GenerationCandidateSemanticShapeRun + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) where + analysis : normalization.root.normalization.generation? = some generation + checked : generation.block.checked.WF env + family : CandidateFamilySemanticGenerationShape normalization generation + constructors : CandidateConstructorSemanticGenerationShapeList source + normalization.family.typeEnv Us normalization.family.constructors + +/-- One executable structural gate for the complete retained singleton +candidate hierarchy. + +The family check uses the complete raw parameter/index telescope. The +constructor check traverses the source-indexed candidate and raw lists +dependently. This consolidates the former per-fixture family and constructor +proof records into one computation while remaining separate from semantic +authority and dependent analysis. -/ +def NormalizationCandidateSemanticRun.generationShape + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateSemanticRun env Us candidate source) : + Bool := + normalizationCandidateGenerationShape source normalization.raw candidate + +/-- One successful outer candidate together with the executable structural +gate required before mixed raw/view generation. + +The record carries the exact ordinary producer equation, so the shape check +cannot be reused for a different candidate. It remains operational evidence: +semantic authority is supplied only after Verify interprets the retained +checker executions. -/ +structure ProducedGenerationShapeCandidate + (source : VInductDecl) (raw : VInductiveType) + (kernelSource : InductiveType) (numNested : Nat) (isUnsafe : Bool) + (context : AddInductive.Context) where + candidate : AddInductive.NormalizationCandidate [kernelSource] + produced : + AddInductive.buildNormalizationCandidate source.nparams + [kernelSource] numNested isUnsafe context = .ok candidate + shape : normalizationCandidateGenerationShape source raw candidate = true + +/-- Run the ordinary outer producer and immediately reject candidates whose +retained traces cannot support mixed generation of the supplied raw Theory +family. The successful result retains both exact producer provenance and the +single complete shape proof. -/ +def produceGenerationShapeCandidate + (source : VInductDecl) (raw : VInductiveType) + (kernelSource : InductiveType) (numNested : Nat) (isUnsafe : Bool) + (context : AddInductive.Context) : + Except Exception (ProducedGenerationShapeCandidate source raw kernelSource + numNested isUnsafe context) := + match produced : AddInductive.buildNormalizationCandidate source.nparams + [kernelSource] numNested isUnsafe context with + | .error error => .error error + | .ok candidate => + if shape : normalizationCandidateGenerationShape source raw candidate then + .ok { candidate, produced, shape } + else + .error (.other + "normalization candidate does not preserve the generation spine") + +private theorem produceGenerationShapeCandidate_match_ok + {source : VInductDecl} {raw : VInductiveType} + {kernelSource : InductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} + (result : Except Exception + (AddInductive.NormalizationCandidate [kernelSource])) + (toProduced : ∀ actual, result = .ok actual → + AddInductive.buildNormalizationCandidate source.nparams + [kernelSource] numNested isUnsafe context = .ok actual) + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (result_ok : result = .ok candidate) + (shape : normalizationCandidateGenerationShape source raw candidate = true) : + (match result_eq : result with + | .error error => Except.error error + | .ok actual => + if actualShape : normalizationCandidateGenerationShape source raw actual then + Except.ok (show ProducedGenerationShapeCandidate source raw kernelSource + numNested isUnsafe context from { + candidate := actual + produced := toProduced actual result_eq + shape := actualShape }) + else + Except.error (.other + "normalization candidate does not preserve the generation spine")) = + Except.ok (show ProducedGenerationShapeCandidate source raw kernelSource + numNested isUnsafe context from { + candidate + produced := toProduced candidate result_ok + shape }) := by + subst result + simp [shape] + +/-- A successful ordinary producer equation and successful hierarchy-shape +check determine the exact successful result of the strengthened producer. + +Keeping this dependent-match elimination here avoids repeating proof-carrying +`Except` reasoning in clients. -/ +theorem produceGenerationShapeCandidate_eq_ok + {source : VInductDecl} {raw : VInductiveType} + {kernelSource : InductiveType} {numNested : Nat} {isUnsafe : Bool} + {context : AddInductive.Context} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (produced : + AddInductive.buildNormalizationCandidate source.nparams + [kernelSource] numNested isUnsafe context = .ok candidate) + (shape : normalizationCandidateGenerationShape source raw candidate = true) : + produceGenerationShapeCandidate source raw kernelSource numNested isUnsafe + context = + .ok { candidate, produced, shape } := by + unfold produceGenerationShapeCandidate + exact produceGenerationShapeCandidate_match_ok + (result := AddInductive.buildNormalizationCandidate source.nparams + [kernelSource] numNested isUnsafe context) + (toProduced := fun _ result_eq => result_eq) produced shape + +/-- Project the established generation assembler. Every normalization root, +view, and recursive spine remains definitionally tied to the semantic owner. -/ +def GenerationCandidateSemanticRun.run + (run : GenerationCandidateSemanticRun normalization generation) : + GenerationCandidateRun normalization.root generation where + analysis := run.analysis + checked := run.checked + family := run.family.run + constructors := run.constructors.run + +/-- A retained analyzer result necessarily contains the normalization that was +analyzed. This is derived from `analysis`, rather than supplied by fixtures. -/ +theorem GenerationCandidateRun.normalization_eq + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) : + generation.block.normalization = normalization.normalization := + Normalization.generation?_normalization run.analysis + +/-- The source-indexed singleton declarations force the analyzer's raw family +to be the exact family retained by a normalization candidate. -/ +theorem NormalizationCandidateRun.sourceType_eq + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateRun env Us candidate source) + (generation : GenerationChecked source) : + generation.block.sourceType = normalization.raw := by + have h : [generation.block.sourceType] = [normalization.raw] := + generation.block.source_types_eq.symm.trans normalization.raw_types_eq + injection h + +/-- Exact dependent analysis selects the reconstructed family view, including +its constructor list, not merely an expression payload with the same type. -/ +theorem NormalizationCandidateRun.familyViewType_eq + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (analysis : normalization.normalization.generation? = some generation) : + generation.block.checked.type = normalization.family.view := by + have normalization_eq : generation.block.normalization = + normalization.normalization := + Normalization.generation?_normalization analysis + have hviews := congrArg (fun norm : Normalization source => norm.view.types) + normalization_eq + have htypes : [generation.block.checked.type] = + [normalization.family.view] := by + calc + [generation.block.checked.type] = + generation.block.normalization.view.types := + generation.block.checked.types_eq.symm + _ = normalization.normalization.view.types := hviews + _ = [normalization.family.view] := rfl + injection htypes + +/-- The retained dependent analysis necessarily checks the exact family view +selected by the normalization candidate. This equation is a consequence of +the two singleton declaration indices and `normalization_eq`, not a separate +fixture alignment premise. -/ +theorem GenerationCandidateRun.familyView_eq + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) : + normalization.family.viewType = generation.block.checked.type.type := by + exact (congrArg (fun ty : VInductiveType => ty.type) + (normalization.familyViewType_eq run.analysis)).symm + +/-- Taking the exact length of the complete stored telescope recovers both +its binder list and its non-forall result. This is the structural bridge from +one numeric trace invariant to generation's named raw components. -/ +private theorem generationTelNForallNLength : + ∀ (As : List VExpr) (B : VExpr), + VExpr.telN As.length (VExpr.forallN As B) = As + | [], _ => rfl + | _ :: As, B => by + simp only [List.length_cons, VExpr.forallN, VExpr.telN, + generationTelNForallNLength As B] + +private theorem generationDropNForallNLength : + ∀ (As : List VExpr) (B : VExpr), + VExpr.dropN As.length (VExpr.forallN As B) = B + | [], _ => rfl + | _ :: As, B => by + simp only [List.length_cons, VExpr.forallN, VExpr.dropN, + generationDropNForallNLength As B] + +private theorem candidateFullTelComponents (np n : Nat) (e : VExpr) + (h : n = + (VExpr.telN np e ++ ctorFields (VExpr.dropN np e)).length) : + VExpr.telN n e = + VExpr.telN np e ++ ctorFields (VExpr.dropN np e) ∧ + VExpr.dropN n e = VExpr.resultOf (VExpr.dropN np e) := by + let As := VExpr.telN np e ++ ctorFields (VExpr.dropN np e) + have he : + VExpr.forallN As (VExpr.resultOf (VExpr.dropN np e)) = e := by + simp only [As, VExpr.forallN_append, + forallN_ctorFields_resultOf, VExpr.forallN_telN_dropN] + let B := VExpr.resultOf (VExpr.dropN np e) + have hAs : n = As.length := h + change VExpr.telN n e = As ∧ VExpr.dropN n e = B + rw [hAs, ← he] + exact ⟨generationTelNForallNLength _ _, + generationDropNForallNLength _ _⟩ + +/-- Derive every family component equation from the minimal structural shape +and the exact dependent analyzer result. -/ +private theorem CandidateFamilySemanticGenerationShape.generationRun + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateSemanticRun env Us candidate source} + {generation : GenerationChecked source} + (input : CandidateFamilySemanticGenerationShape + normalization generation) + (analysis : normalization.root.normalization.generation? = + some generation) : + CandidateFamilySemanticGenerationRun normalization generation where + storedSpine := input.storedSpine + rawTel := by + have components := candidateFullTelComponents source.nparams + candidate.families.singleton.familyType.type.trace.spineLength + normalization.raw.type (by + simpa only [NormalizedChecked.rawParams, + NormalizedChecked.rawIndices, + NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] using + input.spineLength_eq) + simpa only [NormalizedChecked.rawParams, + NormalizedChecked.rawIndices, + NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] using components.1 + rawResult := by + have components := candidateFullTelComponents source.nparams + candidate.families.singleton.familyType.type.trace.spineLength + normalization.raw.type (by + simpa only [NormalizedChecked.rawParams, + NormalizedChecked.rawIndices, + NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] using + input.spineLength_eq) + simpa only [NormalizedChecked.rawResult, + NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] using components.2 + viewResult := by + let As := generation.block.checked.params ++ + generation.block.checked.indices + have hlength : + candidate.families.singleton.familyType.type.trace.spineLength = + As.length := by + rw [input.spineLength_eq] + simp only [As, List.length_append] + rw [generation.shape.2.1, generation.shape.2.2.1] + have hview : normalization.family.type.view = + generation.block.checked.type.type := by + simpa only [NormalizationCandidateSemanticRun.root, + CandidateFamilySemanticRun.root, CandidateFamilyRun.view] using + (congrArg (fun ty : VInductiveType => ty.type) + (normalization.root.familyViewType_eq analysis)).symm + rw [hview, generation.block.checked.type_eq, hlength] + simpa only [As, VExpr.forallN_append] using + generationDropNForallNLength As + (.sort generation.block.checked.resultLevel) + +/-- Derive one normalized constructor alignment after its positional raw/view +equalities have been recovered from the analyzer-owned pair list. -/ +private theorem CandidateConstructorSemanticGenerationShape.generationRun + {source : VInductDecl} {generation : GenerationChecked source} + {env : VEnv} {Us : List Name} + {kernelSource : Constructor} + {candidate : AddInductive.CandidateConstructor kernelSource} + {raw : VConstVal} + {root : CandidateConstructorSemanticRun env Us candidate raw} + {ctor : NormalizedCtor} + (input : CandidateConstructorSemanticGenerationShape + (source := source) env Us root) + (raw_eq : ctor.raw = raw) + (view_eq : ctor.view.value = root.root.view) + (hctor : ctor ∈ generation.block.ctorPairs) : + CandidateSemanticNormalizedCtorRun generation.block env Us root ctor where + raw_eq := raw_eq + view_eq := view_eq + storedSpine := input.storedSpine + rawTel := by + have components := candidateFullTelComponents source.nparams + candidate.type.trace.spineLength raw.type input.spineLength_eq + simpa only [NormalizedCtor.declaredBinders, + NormalizedCtor.rawFields, raw_eq] using components.1 + rawResult := by + have components := candidateFullTelComponents source.nparams + candidate.type.trace.spineLength raw.type input.spineLength_eq + simpa only [NormalizedCtor.rawResult, raw_eq] using components.2 + viewResult := by + let As := generation.block.checked.params ++ ctor.view.fields + have hlength : candidate.type.trace.spineLength = As.length := by + rw [input.spineLength_eq] + simp only [As, List.length_append] + rw [← raw_eq] + have hshape := generation.shape.2.2.2.2.2 ctor hctor + simp only [NormalizedCtor.rawFields] at hshape + rw [hshape.2.2.1, hshape.2.2.2, + generation.shape.1.symm.trans generation.shape.2.1] + have viewType_eq : root.type.view = ctor.view.value.type := by + exact (congrArg (fun value : VConstVal => value.type) view_eq).symm + rw [viewType_eq, generation.viewCtorType_eq hctor, hlength] + exact generationDropNForallNLength As _ + +/-- Recursively align structural constructor inputs with a pair list whose raw +and checked-value projections are already fixed. -/ +private def + CandidateConstructorSemanticGenerationShapeList.generationRuns + {source : VInductDecl} {generation : GenerationChecked source} + {env : VEnv} {Us : List Name} + {kernelSources : List Constructor} + {candidates : AddInductive.CandidateList + AddInductive.CandidateConstructor kernelSources} + {raws : List VConstVal} + {roots : CandidateConstructorSemanticListRun env Us candidates raws} : + (input : CandidateConstructorSemanticGenerationShapeList + source env Us roots) → + (ctors : List NormalizedCtor) → + (raws_eq : ctors.map (·.raw) = raws) → + (views_eq : ctors.map (fun ctor => ctor.view.value) = + roots.roots.views) → + (membership : ∀ ctor ∈ ctors, + ctor ∈ generation.block.ctorPairs) → + CandidateSemanticNormalizedCtorListRun generation.block env Us roots ctors + | .nil, [], _, _, _ => .nil + | .nil, _ :: _, raws_eq, _, _ => by simp at raws_eq + | .cons _ _, [], raws_eq, _, _ => by simp at raws_eq + | .cons head tail, ctor :: ctors, raws_eq, views_eq, membership => by + simp only [List.map_cons, List.cons.injEq] at raws_eq + simp only [List.map_cons, + CandidateConstructorSemanticListRun.roots, + CandidateConstructorListRun.views, List.cons.injEq] at views_eq + exact .cons + (head.generationRun raws_eq.1 views_eq.1 + (membership ctor (.head _))) + (tail.generationRuns ctors raws_eq.2 views_eq.2 + (fun ctor hctor => membership ctor (.tail _ hctor))) + +/-- Exact analysis determines the complete dependent normalized-constructor +list from source-indexed semantic roots and their minimal structural shapes. -/ +private def + CandidateConstructorSemanticGenerationShapeList.ofAnalysis + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateSemanticRun env Us candidate source} + {generation : GenerationChecked source} + (input : CandidateConstructorSemanticGenerationShapeList source + normalization.family.typeEnv Us normalization.family.constructors) + (analysis : normalization.root.normalization.generation? = + some generation) : + CandidateSemanticNormalizedCtorListRun generation.block + normalization.family.typeEnv Us normalization.family.constructors + generation.block.ctorPairs := by + apply input.generationRuns + · simpa only [NormalizationCandidateSemanticRun.root, + normalization.root.sourceType_eq generation] using + generation.rawCtors_eq + · have viewType_eq := normalization.root.familyViewType_eq analysis + calc + generation.block.ctorPairs.map (fun ctor => ctor.view.value) = + generation.block.checked.constructors.map (·.value) := by + simpa only [List.map_map, Function.comp_def] using + congrArg (List.map (·.value)) generation.viewCtors_eq + _ = generation.block.checked.type.ctors := by + rw [generation.block.checked.constructors_eq, List.map_map] + change generation.block.checked.type.ctors.map (fun c => c) = _ + exact List.map_id' generation.block.checked.type.ctors + _ = normalization.family.root.view.ctors := by + simpa only [NormalizationCandidateSemanticRun.root] using + congrArg (fun ty : VInductiveType => ty.ctors) viewType_eq + _ = normalization.family.constructors.roots.views := rfl + · exact fun _ hctor => hctor + +/-- Recover every analyzer-owned constructor pairing from the retained +semantic hierarchy, dependent analysis, and executable structural gate. + +This projection deliberately does not require `Checked.WF`: it exposes only +the exact source/candidate/raw/view alignment needed to derive that semantic +fact in the constructor-validation layer. -/ +def NormalizationCandidateSemanticRun.constructorGenerationRuns + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + (normalization : NormalizationCandidateSemanticRun env Us candidate source) + (generation : GenerationChecked source) + (analysis : normalization.root.normalization.generation? = + some generation) + (shape : normalization.generationShape = true) : + CandidateSemanticNormalizedCtorListRun generation.block + normalization.family.typeEnv Us normalization.family.constructors + generation.block.ctorPairs := by + simp only [NormalizationCandidateSemanticRun.generationShape, + normalizationCandidateGenerationShape, Bool.and_eq_true, + beq_iff_eq] at shape + exact (CandidateConstructorSemanticGenerationShapeList.ofCheck + normalization.family.constructors shape.2).ofAnalysis analysis + +/-- Reconstruct the established semantic-generation run from the reduced +shape boundary. No raw/view pair or component equation is supplied here. -/ +def GenerationCandidateSemanticShapeRun.run + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateSemanticRun env Us candidate source} + {generation : GenerationChecked source} + (input : GenerationCandidateSemanticShapeRun normalization generation) : + GenerationCandidateSemanticRun normalization generation where + analysis := input.analysis + checked := input.checked + family := input.family.generationRun input.analysis + constructors := input.constructors.ofAnalysis input.analysis + +/-- Reconstruct well-formedness of the post-family environment from the +retained pre-family context, candidate raw/view equality, checked family view, +and exact raw-family insertion. Fixtures therefore do not supply this semantic +consequence independently. -/ +theorem GenerationCandidateRun.typeEnv_wf + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) : + VEnv.WF normalization.family.typeEnv := by + have henv : VEnv.WF env := by + simpa only [normalization.family.typeRun.venv_eq] using + normalization.family.typeRun.contextRun.context.Ewf + obtain ⟨_, hfamily⟩ := normalization.family.typeRun.evidence + have hview : env.IsType Us.length [] normalization.family.viewType := by + simpa only [← generation.block.uvars_eq, normalization.uvars_eq, + run.familyView_eq] using run.checked.family_isType + have hraw : env.IsType Us.length [] normalization.raw.type := + VEnv.IsType.defeqU_l henv trivial hfamily.isDefEq.toU.symm hview + have hrawWF : normalization.raw.toVConstant.WF env := by + show env.IsType normalization.raw.uvars [] normalization.raw.type + simpa only [normalization.family.uvars_eq] using hraw + obtain ⟨ds, hds⟩ := henv + exact ⟨.axiom normalization.raw.toVConstVal :: ds, + .decl (.axiom hrawWF normalization.family.addType) hds⟩ + +/-- Type the raw family constant at the analyzer-selected family view in the +post-family environment. The proof combines the exact raw insertion, the +candidate's whole-family equality, and checked family well-formedness once; +constructors can then share this result. -/ +theorem GenerationCandidateRun.familyConst_hasType + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) : + normalization.family.typeEnv.HasType source.uvars [] + (.const generation.block.sourceType.name + (VLevel.params source.uvars)) + generation.block.checked.type.type := by + have sourceType_eq : generation.block.sourceType = normalization.raw := by + have h : [generation.block.sourceType] = [normalization.raw] := + generation.block.source_types_eq.symm.trans normalization.raw_types_eq + injection h + have hlookup : normalization.family.typeEnv.constants + normalization.raw.name = some normalization.raw.toVConstant := + VEnv.addConst_self normalization.family.addType + have hconstRaw := VEnv.HasType.const0 hlookup + (run.typeEnv_wf.ordered.constWF hlookup) + have hconstRaw' : normalization.family.typeEnv.HasType Us.length [] + (.const normalization.raw.name (VLevel.params Us.length)) + normalization.raw.type := by + simpa only [normalization.family.uvars_eq] using hconstRaw + obtain ⟨_, hfamily⟩ := normalization.family.typeRun.evidence + have hchecked := run.checked.mono + (VEnv.addConst_le normalization.family.addType) + have hviewType : normalization.family.typeEnv.IsType Us.length [] + normalization.family.viewType := by + simpa only [← generation.block.uvars_eq, normalization.uvars_eq, + run.familyView_eq] using hchecked.family_isType + obtain ⟨_, hviewType⟩ := hviewType + have hfamilyExact := + (hfamily.isDefEq.toU.mono + (VEnv.addConst_le normalization.family.addType)).of_r + run.typeEnv_wf trivial hviewType + have hconstView : normalization.family.typeEnv.HasType Us.length [] + (.const normalization.raw.name (VLevel.params Us.length)) + normalization.family.viewType := + hfamilyExact.defeq hconstRaw' + simpa only [normalization.uvars_eq, sourceType_eq, + run.familyView_eq] using hconstView + +/-- Assemble the existing checker-side `GenerationRun` entirely from the +source-indexed normalization candidate and its exact spine certificates. -/ +def GenerationCandidateRun.generationRun + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) : + GenerationRun generation env := by + have familyEvidence := run.family.evidence run.familyView_eq + have familyParams : TypeChecker.TelDefEqEvidence env Us.length [] + generation.block.rawParams generation.block.checked.params := by + apply TypeChecker.TelDefEqEvidence.ofTelDefEq + simpa [generation.shape.2.1] using + familyEvidence.telescope.telDefEq.take + generation.block.rawParams.length + have familyParamsTypeEnv := familyParams.mono + (VEnv.addConst_le normalization.family.addType) + have sourceType_eq : generation.block.sourceType = normalization.raw := by + have h : [generation.block.sourceType] = [normalization.raw] := + generation.block.source_types_eq.symm.trans normalization.raw_types_eq + injection h + refine { + normalization := by + simpa only [run.normalization_eq] using + normalization.normalizationRun + checked := run.checked + familyTel := by + simpa only [normalization.uvars_eq] using familyEvidence.telescope + familyResult := by + simpa only [normalization.uvars_eq, List.append_nil] using + familyEvidence.result + typeEnv := normalization.family.typeEnv + addType := by + simpa only [sourceType_eq] using normalization.family.addType + constructors := ?_ } + apply run.constructors.normalizedCtorRuns run.typeEnv_wf + normalization.uvars_eq familyParamsTypeEnv + (run.checked.mono (VEnv.addConst_le normalization.family.addType)) + run.familyConst_hasType (fun _ hctor => hctor) + intro ctor hctor + exact (generation.shape.2.2.2.2.2 ctor hctor).2.2.1.trans + (generation.shape.1.symm.trans generation.shape.2.1) + +/-- Public Theory boundary for a complete source-indexed generation +candidate. -/ +theorem GenerationCandidateRun.wf + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) : + generation.WF env := + run.generationRun.wf + +/-- Complete dependent semantic package for one Verify-side singleton +candidate. + +`kernelSource` and `candidate` retain the exact implementation metadata and +source-indexed operational trace. `normalization` ties that trace to the raw +Theory declaration and its reconstructed view. `generation` is the successful +dependent analysis, and `run` proves that this exact candidate supplies every +semantic obligation consumed by mixed artifact generation. No independently +chosen view can be inserted into this package. -/ +structure GenerationCandidatePackage (env : VEnv) (Us : List Name) where + kernelSource : InductiveType + source : VInductDecl + candidate : AddInductive.NormalizationCandidate [kernelSource] + normalization : NormalizationCandidateRun env Us candidate source + generation : GenerationChecked source + run : GenerationCandidateRun normalization generation + +/-- Package an already assembled source-indexed candidate run without +repeating any of its dependent indices at a call site. -/ +def GenerationCandidateRun.package + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) : + GenerationCandidatePackage env Us where + kernelSource := kernelSource + source := source + candidate := candidate + normalization := normalization + generation := generation + run := run + +/-- Erase checker and candidate provenance at the consumer boundary. The +result contains only the Theory generation value and its ordinary semantic +certificate, which is the complete input of `VEnv.addInductCertified`. -/ +def GenerationCandidatePackage.certificate + (package : GenerationCandidatePackage env Us) : + package.source.GenerationCertificate env where + generation := package.generation + wf := package.run.wf + +/-- Build the general Verify metadata replay from a candidate package and the +ordinary implementation-to-Theory insertion witnesses. + +The generation value and its semantic proof are not independent inputs: both +are projected from `package`. The remaining arguments concern only constant +map alignment and the exact successful transaction states, so a caller cannot +pair metadata replay with an unrelated normalized view. -/ +def GenerationCandidatePackage.addInductTrace + (package : GenerationCandidatePackage env Us) + {m₁ m₂ : ConstMap} {env₂ : VEnv} + (typeMap : ConstMap) (typeEnv : VEnv) + (ctorMap : ConstMap) (ctorEnv recEnv : VEnv) + (addType : AddInductConstant .induct m₁ env + package.generation.block.sourceType.toVConstVal typeMap typeEnv) + (addCtors : AddInductConstants .ctor typeMap typeEnv + package.generation.block.sourceType.ctors ctorMap ctorEnv) + (addRec : AddInductConstant .recursor ctorMap ctorEnv + (inductGenerationRecVal package.generation) m₂ recEnv) + (recK : RecursorKMatches addRec.info package.generation.kTarget) + (addRules : AddDefEqs recEnv + package.generation.generatedRules env₂) : + AddInductTrace m₁ env package.source m₂ env₂ where + generation := package.generation + generation_wf := package.certificate.wf + typeMap := typeMap + typeEnv := typeEnv + ctorMap := ctorMap + ctorEnv := ctorEnv + recEnv := recEnv + addType := addType + addCtors := addCtors + addRec := addRec + recK := recK + addRules := addRules + +/-- Optional outer provenance for packages obtained by the executable +metadata pass itself. Keeping the exact producer equation separate from the +semantic package makes the trust boundary explicit: computation selects the +candidate, while `GenerationCandidateRun` alone grants it Theory meaning. -/ +structure ProducedGenerationCandidatePackage + (env : VEnv) (Us : List Name) where + package : GenerationCandidatePackage env Us + context : AddInductive.Context + nparams : Nat + numNested : Nat + isUnsafe : Bool + produced : + AddInductive.buildNormalizationCandidate nparams + [package.kernelSource] numNested isUnsafe context = + .ok package.candidate + +/-- Attach exact executable provenance to an already verified singleton +generation run. + +Both premises are indexed by the same kernel source and dependent candidate: +the executable equation therefore cannot be reused for a different semantic +run, reordered constructor list, or caller-selected view. Conversely, the +equation supplies no semantic authority by itself; all Theory meaning remains +in `run`. -/ +def GenerationCandidateRun.producedPackage + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateRun normalization generation) + (context : AddInductive.Context) + (nparams numNested : Nat) (isUnsafe : Bool) + (produced : + AddInductive.buildNormalizationCandidate nparams + [kernelSource] numNested isUnsafe context = .ok candidate) : + ProducedGenerationCandidatePackage env Us where + package := run.package + context := context + nparams := nparams + numNested := numNested + isUnsafe := isUnsafe + produced := produced + +/-- Package the no-parallel-run semantic assembler at the existing public +boundary. -/ +def GenerationCandidateSemanticRun.package + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateSemanticRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateSemanticRun normalization generation) : + GenerationCandidatePackage env Us := + run.run.package + +/-- Attach the exact successful outer metadata call directly to a retained +semantic-generation owner. -/ +def GenerationCandidateSemanticRun.producedPackage + {env : VEnv} {Us : List Name} + {kernelSource : InductiveType} {source : VInductDecl} + {candidate : AddInductive.NormalizationCandidate [kernelSource]} + {normalization : NormalizationCandidateSemanticRun env Us candidate source} + {generation : GenerationChecked source} + (run : GenerationCandidateSemanticRun normalization generation) + (context : AddInductive.Context) + (nparams numNested : Nat) (isUnsafe : Bool) + (produced : + AddInductive.buildNormalizationCandidate nparams + [kernelSource] numNested isUnsafe context = .ok candidate) : + ProducedGenerationCandidatePackage env Us := + run.run.producedPackage context nparams numNested isUnsafe produced + +/- +The evidence types mention exact verifier executions, so the semantic +interpretation roots below intentionally inherit the same transitional Verify +closure as `WhnfRun.isDefEq`. Exact guards ensure that the generic assembler +does not silently widen it. Theory-only helper closures are guarded by +`Tests.TheoryConsumerSurface` without importing Verify. +-/ + +#guard_named_axioms Ix.Theory.Named.TypeChecker.AddInductConstant.safePrimitives [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateContextRun.context_env [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateContextRun.context_lctx [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateContextRun.context_safety [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateContextRun.context_lparams [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateContextRun.context_fuel [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRun.view_isType_of_terminalSort [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprSemanticRootRun.source_isType_of_terminalSort [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprSemanticRootRun.viewParameters [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprSemanticRootRun.viewIndices [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateFamilyStagedInput [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateFamilyStagedInput.rawWF [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateFamilyStagedInput.postContext [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateFamilyStagedInput.postContextRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateFamilyStagedInput.postFamily [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprSemanticRootInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateConstructorSemanticListInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateSemanticInput.exists_ofProduced [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidateSemanticInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateFamilySemanticGenerationRun.run [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateSemanticNormalizedCtorListRun.run [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateSemanticRun.run [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateSemanticShapeRun.run [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.candidateConstructorSemanticGenerationShape [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.normalizationCandidateGenerationShape [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateConstructorSemanticGenerationShapeList.ofCheck [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateSemanticRun.generationShape [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.produceGenerationShapeCandidate [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.produceGenerationShapeCandidate_eq_ok [propext, Classical.choice, Quot.sound] +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateSemanticRun.package [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateSemanticRun.producedPackage [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.VState.WF.empty_of_reserves [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.candidateFreshFVarId_reserved [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateContextRun.root [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Syntax.structEq_eq] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateContextRun.pushLocalDecl [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.eqv_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.Syntax.structEq_eq, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.candidateCheckTypeStep_exists_translation [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.IsDefEqRun.ofCandidateStep [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.IsDefEqRun.isDefEqU [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.candidateTypeAnnotation_fvarsIn [] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.candidateTypeAnnotation_exists_translation [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRun.exists_ofCandidate [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRun.exists_ofCandidateFVars [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.WhnfRun.ofCandidateStep [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CheckTypeRun.ofCandidateStep [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateNodeRun.ofCandidate [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateNodeRun.exists_ofCandidate [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateNodeRun.evidence [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRun.evidence [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRun.source_tr [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRun.view_tr [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRootRun.evidence [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.TelDefEqEvidence.telDefEq [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.TelDefEqEvidence.ofTelDefEq [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.TelResultDefEqEvidence.replacePrefix [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprRun.spineEvidence [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.TypeChecker.CandidateExprSpineRun.evidenceAt [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateRun.normalization_eq [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateRun.sourceType_eq [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateRun.familyViewType_eq [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateRun.familyView_eq [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateRun.typeEnv_wf [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateRun.familyConst_hasType [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateNormalizedCtorRun.rightType_ofChecked [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateNormalizedCtorRun.viewTel_eq [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateNormalizedCtorRun.normalizedCtorRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateRun.wf [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateConstructorListRun.sameHeaders [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateConstructorListRun.evidence [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateRun.normalization [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateRun.normalizationRun [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizedCtorRun.wf [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationRun.wf [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateRun.package [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidateRun.producedPackage [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidatePackage.certificate [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.GenerationCandidatePackage.addInductTrace [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.StagedNormalizationCandidateSemanticInput.constructorValidation_run [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationBlockRun.wf [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateBlockFamilySemanticListRun.sameHeaders [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateBlockFamilySemanticListRun.evidence [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateBlockFamilySemanticInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.CandidateBlockFamilySemanticListInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateBlockSemanticInput.exists [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.VInductDecl.NormalizationCandidateBlockSemanticInput.exists_ofProduced [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + + +end VInductDecl + +end Ix.Theory.Named diff --git a/Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean b/Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean new file mode 100644 index 000000000..4c68f01b9 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean @@ -0,0 +1,749 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.InductiveFixtures + +open Ix.Theory (VLevel) + +/-! +# Normalization differential matrix + +Executable and semantic replay for the Spec-04 matrix. The fixture deliberately +places reducible aliases at every inductive-analysis boundary, including a +Pi-producing alias around a recursive target. This file observes the actual +kernel declarations, pins the exact analyzer output and its fuel boundary, and +then translates the same declarations into the Theory environment. +-/ + +namespace Ix.Theory.Named.InductiveReplayFixtures + +open Lean Meta +open Ix.Theory.Named.InductiveFixtures + +/-! ## Actual kernel metadata and executable analysis -/ + +def matrixBetaKernelDef : DefinitionVal := kernelDefVal% MatrixBetaAlias +def matrixLetKernelDef : DefinitionVal := kernelDefVal% MatrixLetAlias +def matrixPiKernelDef : DefinitionVal := kernelDefVal% MatrixPiAlias +def matrixIndexKernelDef : DefinitionVal := kernelDefVal% MatrixIndexAlias + +def matrixBetaInfo : ConstantInfo := .defnInfo matrixBetaKernelDef +def matrixLetInfo : ConstantInfo := .defnInfo matrixLetKernelDef +def matrixPiInfo : ConstantInfo := .defnInfo matrixPiKernelDef +def matrixIndexInfo : ConstantInfo := .defnInfo matrixIndexKernelDef + +def matrixRecMap : ConstMap := + typeFamilyAliasMap.insert ``RecAlias recAliasInfo + +def matrixBetaMap : ConstMap := + matrixRecMap.insert ``MatrixBetaAlias matrixBetaInfo + +def matrixLetMap : ConstMap := + matrixBetaMap.insert ``MatrixLetAlias matrixLetInfo + +def matrixPiMap : ConstMap := + matrixLetMap.insert ``MatrixPiAlias matrixPiInfo + +def matrixAliasMap : ConstMap := + matrixPiMap.insert ``MatrixIndexAlias matrixIndexInfo + +theorem matrixRec_fresh : + typeFamilyAliasMap.find? ``RecAlias = none := by + rw [typeFamilyAliasMap, SMap.WF.find?_insert + (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem matrixRecMap_wf : matrixRecMap.WF := + typeFamilyAliasMap_wf.insert _ _ matrixRec_fresh + +theorem matrixBeta_fresh : + matrixRecMap.find? ``MatrixBetaAlias = none := by + rw [matrixRecMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem matrixBetaMap_wf : matrixBetaMap.WF := + matrixRecMap_wf.insert _ _ matrixBeta_fresh + +theorem matrixLet_fresh : + matrixBetaMap.find? ``MatrixLetAlias = none := by + rw [matrixBetaMap, matrixRecMap_wf.find?_insert, + matrixRecMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem matrixLetMap_wf : matrixLetMap.WF := + matrixBetaMap_wf.insert _ _ matrixLet_fresh + +theorem matrixPi_fresh : matrixLetMap.find? ``MatrixPiAlias = none := by + rw [matrixLetMap, matrixBetaMap_wf.find?_insert, + matrixBetaMap, matrixRecMap_wf.find?_insert, + matrixRecMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem matrixPiMap_wf : matrixPiMap.WF := + matrixLetMap_wf.insert _ _ matrixPi_fresh + +theorem matrixIndex_fresh : + matrixPiMap.find? ``MatrixIndexAlias = none := by + rw [matrixPiMap, matrixLetMap_wf.find?_insert, + matrixLetMap, matrixBetaMap_wf.find?_insert, + matrixBetaMap, matrixRecMap_wf.find?_insert, + matrixRecMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem matrixAliasMap_wf : matrixAliasMap.WF := + matrixPiMap_wf.insert _ _ matrixIndex_fresh + +def matrixKernelEnv : Kernel.Environment := + Kernel.Environment.ofConstants `_normalizationMatrix matrixAliasMap + +def normalizationMatrixInfo : ConstantInfo := + kernelInductInfo% NormalizationMatrix + +def normalizationMatrixMkInfo : ConstantInfo := + kernelCtorInfo% NormalizationMatrix.mk + +def normalizationMatrixRecInfo : ConstantInfo := + kernelRecInfo% NormalizationMatrix.rec + +def normalizationMatrixKernelRuleRhs : VExpr := + kernelRecRuleRhs% NormalizationMatrix.rec 0 + +def normalizationMatrixKernelCtor : Constructor where + name := normalizationMatrixMkInfo.name + type := normalizationMatrixMkInfo.type + +def normalizationMatrixKernelType : InductiveType where + name := normalizationMatrixInfo.name + type := normalizationMatrixInfo.type + ctors := [normalizationMatrixKernelCtor] + +theorem normalizationMatrix_kernel_family_name : + normalizationMatrixInfo.name = ``NormalizationMatrix := rfl + +theorem normalizationMatrix_kernel_ctor_name : + normalizationMatrixMkInfo.name = ``NormalizationMatrix.mk := rfl + +theorem normalizationMatrix_kernel_recursor_name : + normalizationMatrixRecInfo.name = ``NormalizationMatrix.rec := rfl + +theorem normalizationMatrix_kernel_constructor_shape : + (match normalizationMatrixMkInfo with + | .ctorInfo info => (info.numParams, info.numFields) + | _ => (0, 0)) = (1, 8) := rfl + +theorem normalizationMatrix_kernel_recursor_shape : + (match normalizationMatrixRecInfo with + | .recInfo info => + (info.numParams, info.numIndices, info.numMotives, + info.numMinors, info.rules.length) + | _ => (0, 0, 0, 0, 0)) = (1, 1, 1, 1, 1) := rfl + +theorem normalizationMatrix_kernel_rule_exact : + normalizationMatrixKernelRuleRhs = + normalizationMatrixGenerationChecked.generatedRules[0].rhs := rfl + +theorem normalizationMatrix_recursive_positions_exact : + normalizationMatrixViewChecked.constructors[0].recursive.map + (fun position => (position.fieldIndex, position.binders.length)) = + [(4, 0), (5, 1), (6, 0), (7, 0)] := rfl + +def matrixCandidateContext (fuel : Nat) : AddInductive.Context where + env := matrixKernelEnv + lparams := [] + safety := .safe + allowPrimitive := false + fuel := { inductiveFuel := fuel } + +def matrixCandidateAccepted (fuel : Nat) : Bool := + match AddInductive.buildNormalizationCandidate 1 + [normalizationMatrixKernelType] 0 false (matrixCandidateContext fuel) with + | .ok _ => true + | .error _ => false + +def matrixTargetExpr (alpha index : Expr) : Expr := + .app (.app (.const ``NormalizationMatrix []) alpha) + (.app (.const ``MatrixIndexAlias []) index) + +def matrixExpectedFamilyView : Expr := + .forallE `alpha (.sort (.succ .zero)) + (.forallE `index (.sort (.succ .zero)) + (.sort (.succ (.succ .zero))) .default) .default + +def matrixExpectedCtorView : Expr := + .forallE `alpha (.sort (.succ .zero)) + (.forallE `index (.sort (.succ .zero)) + (.forallE `ordinary (.sort .zero) + (.forallE `beta (.sort .zero) + (.forallE `letBound (.sort .zero) + (.forallE `direct (matrixTargetExpr (.bvar 4) (.bvar 3)) + (.forallE `piHidden + (.forallE `proof (.sort .zero) + (matrixTargetExpr (.bvar 6) (.bvar 5)) .default) + (.forallE `betaRecursive + (matrixTargetExpr (.bvar 6) (.bvar 5)) + (.forallE `letRecursive + (matrixTargetExpr (.bvar 7) (.bvar 6)) + (matrixTargetExpr (.bvar 8) (.bvar 7)) .default) + .default) + .default) + .default) + .default) + .default) + .default) + .default) + .implicit + +/-- Binder names are not semantic metadata, so exact executable comparisons +canonicalize only those names and preserve every other expression node. -/ +def matrixCanonicalExpr : Expr → Expr + | .app fn arg => .app (matrixCanonicalExpr fn) (matrixCanonicalExpr arg) + | .forallE _ domain body bi => + .forallE `_ (matrixCanonicalExpr domain) (matrixCanonicalExpr body) bi + | expr => expr + +def matrixCandidateExact (context : AddInductive.Context) : Bool := + match AddInductive.buildNormalizationCandidate 1 + [normalizationMatrixKernelType] 0 false context with + | .ok candidate => + (matrixCanonicalExpr candidate.families.singleton.familyType.type.view).equal + (matrixCanonicalExpr matrixExpectedFamilyView) && + match candidate.families.singleton.constructors with + | .cons constructor .nil => + (matrixCanonicalExpr constructor.type.view).equal + (matrixCanonicalExpr matrixExpectedCtorView) + | .error _ => false + +#guard matrixCandidateExact (matrixCandidateContext 10) +#guard matrixCandidateAccepted 10 +#guard !(matrixCandidateAccepted 9) + +def matrixOpaquePiAliasInfo : ConstantInfo := + .axiomInfo { + name := ``MatrixPiAlias + levelParams := matrixPiKernelDef.levelParams + type := matrixPiKernelDef.type + isUnsafe := false } + +def matrixOpaquePiAliasMap : ConstMap := + matrixAliasMap.insert ``MatrixPiAlias matrixOpaquePiAliasInfo + +def matrixOpaquePiAliasContext : AddInductive.Context where + env := Kernel.Environment.ofConstants `_normalizationMatrixOpaquePi + matrixOpaquePiAliasMap + lparams := [] + safety := .safe + allowPrimitive := false + fuel := { inductiveFuel := 10 } + +#guard !(matrixCandidateExact matrixOpaquePiAliasContext) + +def matrixNonDefEqCtor : Constructor where + name := normalizationMatrixMkInfo.name + type := .forallE `alpha (.sort .zero) + (matrixTargetExpr (.sort .zero) (.sort .zero)) .implicit + +def matrixNonDefEqType : InductiveType := + { normalizationMatrixKernelType with ctors := [matrixNonDefEqCtor] } + +#guard match AddInductive.buildNormalizationCandidate 1 + [matrixNonDefEqType] 0 false (matrixCandidateContext 10) with + | .error (.other message) => + message == + "arg #1 of 'Ix.Theory.Named.InductiveFixtures.NormalizationMatrix.mk' does not match inductive datatype parameters" + | _ => false + +/-! ## Translation of every retained alias -/ + +def matrixBetaVal : VDefVal where + name := ``MatrixBetaAlias + uvars := (vconst(type_of% @MatrixBetaAlias) : VConstant).uvars + type := (vconst(type_of% @MatrixBetaAlias) : VConstant).type + value := matrixBetaAliasDefEq.rhs + +def matrixLetVal : VDefVal where + name := ``MatrixLetAlias + uvars := (vconst(type_of% @MatrixLetAlias) : VConstant).uvars + type := (vconst(type_of% @MatrixLetAlias) : VConstant).type + value := matrixLetAliasDefEq.rhs + +def matrixPiVal : VDefVal where + name := ``MatrixPiAlias + uvars := (vconst(type_of% @MatrixPiAlias) : VConstant).uvars + type := (vconst(type_of% @MatrixPiAlias) : VConstant).type + value := matrixPiAliasDefEq.rhs + +def matrixIndexVal : VDefVal where + name := ``MatrixIndexAlias + uvars := (vconst(type_of% @MatrixIndexAlias) : VConstant).uvars + type := (vconst(type_of% @MatrixIndexAlias) : VConstant).type + value := matrixIndexAliasDefEq.rhs + +theorem matrixRecInfo_tr : + TrDefVal .safe typeFamilyAliasEnv recAliasInfo recAliasVal := + recAliasInfo_tr.mono + ((VEnv.addConst_le (by rfl : + VEnv.empty.addConst ``TypeFamilyAlias + (vconst(type_of% @TypeFamilyAlias)) = + some typeFamilyAliasConstEnv)).trans VEnv.addDefEq_le) + +theorem matrixBetaInfo_tr : + TrDefVal .safe normalizationMatrixRecAliasEnv + matrixBetaInfo matrixBetaVal := by + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · have hshape : TrTypeExpr normalizationMatrixRecAliasEnv + matrixBetaInfo.levelParams [] matrixBetaInfo.type matrixBetaVal.type := by + tr_type_expr_tac + exact hshape.to_trExprS normalizationMatrixRecAliasEnv_ordered trivial + ⟨_, by type_tac⟩ + · refine .lam ⟨_, VEnv.HasType.sort (by decide)⟩ (.sort rfl) ?_ + refine .app + (VEnv.HasType.lam + (VEnv.HasType.sort (by decide)) + (VEnv.HasType.bvar .zero)) + (VEnv.HasType.bvar .zero) ?_ (.bvar rfl) + exact .lam ⟨_, VEnv.HasType.sort (by decide)⟩ (.sort rfl) (.bvar rfl) + +theorem matrixLetInfo_tr : + TrDefVal .safe normalizationMatrixBetaAliasEnv + matrixLetInfo matrixLetVal := by + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · have hshape : TrTypeExpr normalizationMatrixBetaAliasEnv + matrixLetInfo.levelParams [] matrixLetInfo.type matrixLetVal.type := by + tr_type_expr_tac + exact hshape.to_trExprS normalizationMatrixBetaAliasEnv_ordered trivial + ⟨_, by type_tac⟩ + · refine .lam ⟨_, VEnv.HasType.sort (by decide)⟩ (.sort rfl) ?_ + exact .letE (by type_tac) (.sort rfl) (.bvar rfl) (.bvar rfl) + +theorem matrixPiInfo_tr : + TrDefVal .safe normalizationMatrixLetAliasEnv matrixPiInfo matrixPiVal := by + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · have hshape : TrTypeExpr normalizationMatrixLetAliasEnv + matrixPiInfo.levelParams [] matrixPiInfo.type matrixPiVal.type := by + tr_type_expr_tac + exact hshape.to_trExprS normalizationMatrixLetAliasEnv_ordered trivial + ⟨_, by type_tac⟩ + · refine .lam ⟨_, VEnv.HasType.sort (by decide)⟩ (.sort rfl) ?_ + apply TrExprS.forallE + · exact ⟨_, VEnv.HasType.sort (by decide)⟩ + · exact ⟨.param 0, VEnv.HasType.bvar (.succ .zero)⟩ + · exact .sort rfl + · exact .bvar rfl + +theorem matrixIndexInfo_tr : + TrDefVal .safe normalizationMatrixPiAliasEnv + matrixIndexInfo matrixIndexVal := by + have hfamily : normalizationMatrixPiAliasEnv.constants + ``TypeFamilyAlias = some (vconst(type_of% @TypeFamilyAlias)) := rfl + refine ⟨⟨⟨by decide, rfl, ?_⟩, rfl⟩, ?_⟩ + · have hshape : TrTypeExpr normalizationMatrixPiAliasEnv + matrixIndexInfo.levelParams [] matrixIndexInfo.type matrixIndexVal.type := by + tr_type_expr_tac + exact hshape.to_trExprS normalizationMatrixPiAliasEnv_ordered trivial + ⟨_, by type_tac⟩ + · refine .lam ⟨_, by type_tac⟩ ?_ (.bvar rfl) + exact .const rfl rfl rfl + +theorem matrixBetaVal_wf : matrixBetaVal.WF + normalizationMatrixRecAliasEnv := by + type_tac + +theorem matrixLetVal_wf : matrixLetVal.WF + normalizationMatrixBetaAliasEnv := by + type_tac + +theorem matrixPiVal_wf : matrixPiVal.WF + normalizationMatrixLetAliasEnv := by + apply VEnv.HasType.lam + · exact VEnv.HasType.sort (by decide) + · apply VEnv.IsDefEq.defeq + (VEnv.IsDefEq.sortDF + (l := .imax (.succ .zero) (.param 0)) (l' := .param 0) + (by decide) (by decide) (by + rw [VLevel.equiv_def] + intro ls + simp only [VLevel.eval, Nat.zero_add] + let n := ls.getD 0 0 + change Nat.imax 1 n = n + by_cases h : n = 0 + · simp [Nat.imax, h] + · have hn : 1 ≤ n := Nat.one_le_iff_ne_zero.mpr h + simp [Nat.imax, h, Nat.max_eq_right hn])) + exact VEnv.HasType.forallE (VEnv.HasType.sort (by decide)) + (VEnv.HasType.bvar (.succ .zero)) + +theorem matrixIndexVal_wf : matrixIndexVal.WF + normalizationMatrixPiAliasEnv := by + have hfamily : normalizationMatrixPiAliasEnv.constants + ``TypeFamilyAlias = some (vconst(type_of% @TypeFamilyAlias)) := rfl + type_tac + +theorem matrixRec_trEnv' : + TrEnv' .safe matrixRecMap false normalizationMatrixRecAliasEnv := + .defn (ci := recAliasKernelDef) (ci' := recAliasVal) + matrixRecInfo_tr matrixRec_fresh + (recAliasVal_wf.mono + ((VEnv.addConst_le (by rfl : + VEnv.empty.addConst ``TypeFamilyAlias + (vconst(type_of% @TypeFamilyAlias)) = + some typeFamilyAliasConstEnv)).trans VEnv.addDefEq_le)) + rfl typeFamilyAlias_trEnv' + +theorem matrixBeta_trEnv' : + TrEnv' .safe matrixBetaMap false normalizationMatrixBetaAliasEnv := + .defn (ci := matrixBetaKernelDef) (ci' := matrixBetaVal) + matrixBetaInfo_tr matrixBeta_fresh matrixBetaVal_wf rfl matrixRec_trEnv' + +theorem matrixLet_trEnv' : + TrEnv' .safe matrixLetMap false normalizationMatrixLetAliasEnv := + .defn (ci := matrixLetKernelDef) (ci' := matrixLetVal) + matrixLetInfo_tr matrixLet_fresh matrixLetVal_wf rfl matrixBeta_trEnv' + +theorem matrixPi_trEnv' : + TrEnv' .safe matrixPiMap false normalizationMatrixPiAliasEnv := + .defn (ci := matrixPiKernelDef) (ci' := matrixPiVal) + matrixPiInfo_tr matrixPi_fresh matrixPiVal_wf rfl matrixLet_trEnv' + +theorem matrixAlias_trEnv' : + TrEnv' .safe matrixAliasMap false normalizationMatrixAliasEnv := + .defn (ci := matrixIndexKernelDef) (ci' := matrixIndexVal) + matrixIndexInfo_tr matrixIndex_fresh matrixIndexVal_wf rfl matrixPi_trEnv' + +/-! ## Replay of the actual inductive transaction -/ + +def normalizationMatrixTypeEnv : VEnv := + (normalizationMatrixAliasEnv.addConst normalizationMatrixRawType.name + normalizationMatrixRawType.toVConstant).get (by decide) + +def normalizationMatrixCtorEnv : VEnv := + (normalizationMatrixTypeEnv.addConst + normalizationMatrixRawType.ctors[0].name + normalizationMatrixRawType.ctors[0].toVConstant).get (by decide) + +def normalizationMatrixRecEnv : VEnv := + (normalizationMatrixCtorEnv.addConst ``NormalizationMatrix.rec + normalizationMatrixGenerationChecked.recursor).get (by decide) + +theorem normalizationMatrixTypeEnv_ordered : + normalizationMatrixTypeEnv.Ordered := by + refine .const (n := normalizationMatrixRawType.name) + (ci := normalizationMatrixRawType.toVConstant) + normalizationMatrixAliasEnv_ordered ?_ rfl + show normalizationMatrixAliasEnv.IsType + normalizationMatrixGenerationChecked.block.sourceType.uvars [] + normalizationMatrixGenerationChecked.block.sourceType.type + rw [normalizationMatrixGenerationChecked.block.sourceType_uvars_eq] + exact normalizationMatrixGenerationChecked_wf.rawFamily_isType + +theorem normalizationMatrixRawCtor_wf : + normalizationMatrixRawType.ctors[0].toVConstant.WF + normalizationMatrixTypeEnv := by + have hctor : + (⟨normalizationMatrixRawType.ctors[0], + normalizationMatrixViewChecked.constructors[0]⟩ : + VInductDecl.NormalizedCtor) ∈ + normalizationMatrixGenerationChecked.block.ctorPairs := by + exact .head _ + show normalizationMatrixTypeEnv.IsType + normalizationMatrixRawType.ctors[0].uvars [] + normalizationMatrixRawType.ctors[0].type + rw [normalizationMatrixGenerationChecked.ctor_uvars_eq hctor] + exact normalizationMatrixGenerationChecked_wf.rawCtor_isType rfl hctor + +theorem normalizationMatrixCtorEnv_ordered : + normalizationMatrixCtorEnv.Ordered := + .const (n := normalizationMatrixRawType.ctors[0].name) + (ci := normalizationMatrixRawType.ctors[0].toVConstant) + normalizationMatrixTypeEnv_ordered normalizationMatrixRawCtor_wf rfl + +theorem normalizationMatrixGenerationEnv : + VInductDecl.GenerationEnv normalizationMatrixGenerationChecked + normalizationMatrixCtorEnv := by + apply normalizationMatrixGenerationChecked_wf.toGenerationEnv + (envT := normalizationMatrixTypeEnv) + · rfl + · exact (VEnv.addConst_le (show + normalizationMatrixAliasEnv.addConst normalizationMatrixRawType.name + normalizationMatrixRawType.toVConstant = + some normalizationMatrixTypeEnv from rfl)).trans + (VEnv.addConst_le (show + normalizationMatrixTypeEnv.addConst + normalizationMatrixRawType.ctors[0].name + normalizationMatrixRawType.ctors[0].toVConstant = + some normalizationMatrixCtorEnv from rfl)) + · exact VEnv.addConst_le (show + normalizationMatrixTypeEnv.addConst + normalizationMatrixRawType.ctors[0].name + normalizationMatrixRawType.ctors[0].toVConstant = + some normalizationMatrixCtorEnv from rfl) + · exact normalizationMatrixCtorEnv_ordered + · rfl + · intro ctor hctor + change ctor ∈ + [⟨normalizationMatrixRawType.ctors[0], + normalizationMatrixViewChecked.constructors[0]⟩] at hctor + obtain rfl := List.mem_singleton.1 hctor + rfl + +theorem normalizationMatrixInfo_tr : + TrConstVal .safe normalizationMatrixAliasEnv normalizationMatrixInfo + normalizationMatrixRawType.toVConstVal := by + have hTypeFamily : normalizationMatrixAliasEnv.constants + ``TypeFamilyAlias = some (vconst(type_of% @TypeFamilyAlias)) := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr normalizationMatrixAliasEnv + normalizationMatrixInfo.levelParams [] normalizationMatrixInfo.type + normalizationMatrixRawType.type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := + normalizationMatrixGenerationChecked_wf.rawFamily_isType + exact hshape.to_trExprS normalizationMatrixAliasEnv_ordered trivial + ⟨.sort u, htype⟩ + +theorem normalizationMatrixMkInfo_tr : + TrConstVal .safe normalizationMatrixTypeEnv normalizationMatrixMkInfo + normalizationMatrixRawType.ctors[0] := by + have hTypeFamily : normalizationMatrixTypeEnv.constants + ``TypeFamilyAlias = some (vconst(type_of% @TypeFamilyAlias)) := rfl + have hRecAlias : normalizationMatrixTypeEnv.constants + ``RecAlias = some (vconst(type_of% @RecAlias)) := rfl + have hBetaAlias : normalizationMatrixTypeEnv.constants + ``MatrixBetaAlias = some (vconst(type_of% @MatrixBetaAlias)) := rfl + have hLetAlias : normalizationMatrixTypeEnv.constants + ``MatrixLetAlias = some (vconst(type_of% @MatrixLetAlias)) := rfl + have hPiAlias : normalizationMatrixTypeEnv.constants + ``MatrixPiAlias = some (vconst(type_of% @MatrixPiAlias)) := rfl + have hIndexAlias : normalizationMatrixTypeEnv.constants + ``MatrixIndexAlias = some (vconst(type_of% @MatrixIndexAlias)) := rfl + have hFamily : normalizationMatrixTypeEnv.constants + ``NormalizationMatrix = some normalizationMatrixRawType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr normalizationMatrixTypeEnv + normalizationMatrixMkInfo.levelParams [] normalizationMatrixMkInfo.type + normalizationMatrixRawType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨u, htype⟩ := normalizationMatrixRawCtor_wf + exact hshape.to_trExprS normalizationMatrixTypeEnv_ordered trivial + ⟨.sort u, htype⟩ + +theorem normalizationMatrixRecInfo_tr : + TrConstVal .safe normalizationMatrixCtorEnv normalizationMatrixRecInfo + (inductGenerationRecVal normalizationMatrixGenerationChecked) := by + have hTypeFamily : normalizationMatrixCtorEnv.constants + ``TypeFamilyAlias = some (vconst(type_of% @TypeFamilyAlias)) := rfl + have hIndexAlias : normalizationMatrixCtorEnv.constants + ``MatrixIndexAlias = some (vconst(type_of% @MatrixIndexAlias)) := rfl + have hFamily : normalizationMatrixCtorEnv.constants + ``NormalizationMatrix = some normalizationMatrixRawType.toVConstant := rfl + have hMk : normalizationMatrixCtorEnv.constants + ``NormalizationMatrix.mk = + some normalizationMatrixRawType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have hshape : TrTypeExpr normalizationMatrixCtorEnv + normalizationMatrixRecInfo.levelParams [] normalizationMatrixRecInfo.type + (inductGenerationRecVal normalizationMatrixGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨u, hrec⟩ := normalizationMatrixGenerationEnv.recursor_wf + exact hshape.to_trExprS normalizationMatrixCtorEnv_ordered trivial + ⟨.sort u, hrec⟩ + +def normalizationMatrixTypeMap : ConstMap := + matrixAliasMap.insert ``NormalizationMatrix normalizationMatrixInfo + +def normalizationMatrixCtorMap : ConstMap := + normalizationMatrixTypeMap.insert ``NormalizationMatrix.mk + normalizationMatrixMkInfo + +def normalizationMatrixMap : ConstMap := + normalizationMatrixCtorMap.insert ``NormalizationMatrix.rec + normalizationMatrixRecInfo + +theorem normalizationMatrixType_fresh : + matrixAliasMap.find? ``NormalizationMatrix = none := by + rw [matrixAliasMap, matrixPiMap_wf.find?_insert, + matrixPiMap, matrixLetMap_wf.find?_insert, + matrixLetMap, matrixBetaMap_wf.find?_insert, + matrixBetaMap, matrixRecMap_wf.find?_insert, + matrixRecMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem normalizationMatrixTypeMap_wf : normalizationMatrixTypeMap.WF := + matrixAliasMap_wf.insert _ _ normalizationMatrixType_fresh + +theorem normalizationMatrixMk_fresh : + normalizationMatrixTypeMap.find? ``NormalizationMatrix.mk = none := by + rw [normalizationMatrixTypeMap, matrixAliasMap_wf.find?_insert, + matrixAliasMap, matrixPiMap_wf.find?_insert, + matrixPiMap, matrixLetMap_wf.find?_insert, + matrixLetMap, matrixBetaMap_wf.find?_insert, + matrixBetaMap, matrixRecMap_wf.find?_insert, + matrixRecMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem normalizationMatrixCtorMap_wf : normalizationMatrixCtorMap.WF := + normalizationMatrixTypeMap_wf.insert _ _ normalizationMatrixMk_fresh + +theorem normalizationMatrixRec_fresh : + normalizationMatrixCtorMap.find? ``NormalizationMatrix.rec = none := by + rw [normalizationMatrixCtorMap, + normalizationMatrixTypeMap_wf.find?_insert, + normalizationMatrixTypeMap, matrixAliasMap_wf.find?_insert, + matrixAliasMap, matrixPiMap_wf.find?_insert, + matrixPiMap, matrixLetMap_wf.find?_insert, + matrixLetMap, matrixBetaMap_wf.find?_insert, + matrixBetaMap, matrixRecMap_wf.find?_insert, + matrixRecMap, typeFamilyAliasMap_wf.find?_insert, + typeFamilyAliasMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +private def normalizationMatrixAddInductTraceWith + (generation_wf : + normalizationMatrixGenerationChecked.WF normalizationMatrixAliasEnv) : + AddInductTrace matrixAliasMap normalizationMatrixAliasEnv + normalizationMatrixRawDecl normalizationMatrixMap + normalizationMatrixFinalEnv := by + refine { + generation := normalizationMatrixGenerationChecked + generation_wf := generation_wf + typeMap := normalizationMatrixTypeMap + typeEnv := normalizationMatrixTypeEnv + ctorMap := normalizationMatrixCtorMap + ctorEnv := normalizationMatrixCtorEnv + recEnv := normalizationMatrixRecEnv + addType := { + info := normalizationMatrixInfo + kind_eq := by simp [normalizationMatrixInfo, InductConstantKind.Matches] + tr := normalizationMatrixInfo_tr + map_fresh := by + change matrixAliasMap.find? ``NormalizationMatrix = none + exact normalizationMatrixType_fresh + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := normalizationMatrixRecInfo + kind_eq := by + simp [normalizationMatrixRecInfo, InductConstantKind.Matches] + tr := normalizationMatrixRecInfo_tr + map_fresh := by + change normalizationMatrixCtorMap.find? + ``NormalizationMatrix.rec = none + exact normalizationMatrixRec_fresh + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ } + exact .cons { + info := normalizationMatrixMkInfo + kind_eq := by + simp [normalizationMatrixMkInfo, InductConstantKind.Matches] + tr := normalizationMatrixMkInfo_tr + map_fresh := by + simpa [normalizationMatrixRawType] using normalizationMatrixMk_fresh + env_add := rfl + map_add := rfl } .nil + +theorem normalizationMatrix_addInduct : + AddInduct matrixAliasMap normalizationMatrixAliasEnv + normalizationMatrixRawDecl normalizationMatrixMap + normalizationMatrixFinalEnv := + ⟨normalizationMatrixAddInductTraceWith + normalizationMatrixGenerationChecked_wf⟩ + +/-- Actual kernel metadata for the complete matrix is aligned with the Theory +environment obtained from the semantically checked normalization transaction. -/ +theorem normalizationMatrix_trEnv' : + TrEnv' .safe normalizationMatrixMap false normalizationMatrixFinalEnv := + .induct normalizationMatrix_addInduct matrixAlias_trEnv' + +theorem normalizationMatrix_final_matches_generation : + normalizationMatrixAliasEnv.addInductGeneration + normalizationMatrixGenerationChecked = + some normalizationMatrixFinalEnv := + normalizationMatrix_addInductGeneration + +theorem normalizationMatrix_env_wf : normalizationMatrixFinalEnv.WF := + normalizationMatrix_trEnv'.wf + +theorem normalizationMatrix_aligned : + Aligned .safe normalizationMatrixMap normalizationMatrixFinalEnv := + normalizationMatrix_trEnv'.aligned + +theorem normalizationMatrix_type_map_lookup : + normalizationMatrixMap.find? ``NormalizationMatrix = + some normalizationMatrixInfo := by + rw [normalizationMatrixMap, normalizationMatrixCtorMap_wf.find?_insert, + normalizationMatrixCtorMap, normalizationMatrixTypeMap_wf.find?_insert, + normalizationMatrixTypeMap, matrixAliasMap_wf.find?_insert] + rfl + +theorem normalizationMatrix_type_lookup_unique : + normalizationMatrixInfo.name = ``NormalizationMatrix ∧ + TrConstant .safe normalizationMatrixFinalEnv normalizationMatrixInfo + normalizationMatrixRawType.toVConstant := + normalizationMatrix_aligned.find?_uniq + normalizationMatrix_type_map_lookup + normalizationMatrixFinalEnv_family_lookup + +theorem normalizationMatrix_mk_map_lookup : + normalizationMatrixMap.find? ``NormalizationMatrix.mk = + some normalizationMatrixMkInfo := by + rw [normalizationMatrixMap, normalizationMatrixCtorMap_wf.find?_insert, + normalizationMatrixCtorMap, normalizationMatrixTypeMap_wf.find?_insert] + rfl + +theorem normalizationMatrix_mk_lookup_unique : + normalizationMatrixMkInfo.name = ``NormalizationMatrix.mk ∧ + TrConstant .safe normalizationMatrixFinalEnv normalizationMatrixMkInfo + normalizationMatrixRawType.ctors[0].toVConstant := + normalizationMatrix_aligned.find?_uniq + normalizationMatrix_mk_map_lookup + normalizationMatrixFinalEnv_ctor_lookup + +theorem normalizationMatrix_rec_map_lookup : + normalizationMatrixMap.find? ``NormalizationMatrix.rec = + some normalizationMatrixRecInfo := by + rw [normalizationMatrixMap, normalizationMatrixCtorMap_wf.find?_insert] + rfl + +theorem normalizationMatrix_rec_lookup_unique : + normalizationMatrixRecInfo.name = ``NormalizationMatrix.rec ∧ + TrConstant .safe normalizationMatrixFinalEnv normalizationMatrixRecInfo + normalizationMatrixGenerationChecked.recursor := + normalizationMatrix_aligned.find?_uniq + normalizationMatrix_rec_map_lookup + normalizationMatrixFinalEnv_rec_lookup + +/-! The semantic generation helpers used above are guarded in +`Theory.Typing.InductiveLemmas`; these two guards pin the separate, now +`sorryAx`-free Verify closure of metadata translation and final environment +replay. -/ + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.normalizationMatrixInfo_tr [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.normalizationMatrix_trEnv' [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean b/Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean new file mode 100644 index 000000000..f60012ae8 --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean @@ -0,0 +1,471 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.SingletonParity +import Ix.Theory.Named.Verify.Environment.ConstructorValidityMatrix +import Ix.Theory.Named.Verify.Environment.EliminationFixturesEqNat +import Ix.Theory.Named.Verify.Environment.EliminationFixturesOrAnd +import Ix.Theory.Named.Verify.Environment.EliminationFixturesEdges +import Ix.Theory.Named.Verify.Environment.NormalizationMatrix + +/-! +# Spec-07 complete singleton kernel matrix + +The rows below join the single Theory artifact inventory to Lean's actual +`inductInfo`/`ctorInfo`/`recInfo` records. The executable predicate compares +the retained raw types, names, parameter/index and field counts, universe +order, elimination/K metadata, recursor type, rule count, and every iota RHS. +It also reruns the ordinary normalization producer on the exact kernel source. +-/ + +namespace Ix.Theory.Named.InductiveReplayFixtures + +open Lean Meta Elab Term +open Ix.Theory.Named.InductiveFixtures + +/-! ## Exact conversion of stored kernel types -/ + +syntax "kernelConstVType%" ident : term + +/-- Quote the stored `ConstantInfo.type` using that record's own universe +parameter order. Unlike `vconst(type_of% ...)`, this observes the raw kernel +record directly. -/ +elab_rules : term + | `(kernelConstVType% $n:ident) => do + let name ← realizeGlobalConstNoOverloadWithInfo n + let info ← getConstInfo name + let type ← Ix.Theory.Named.Meta.expandExpr info.type + let type ← Ix.Theory.Named.Meta.ofExpr info.levelParams {} type + return toExpr type + +/-! ## Missing standard-library metadata rows -/ + +def boolInfo07 : ConstantInfo := kernelInductInfo% Bool +def boolFalseInfo07 : ConstantInfo := kernelCtorInfo% Bool.false +def boolTrueInfo07 : ConstantInfo := kernelCtorInfo% Bool.true +def boolRecInfo07 : ConstantInfo := kernelRecInfo% Bool.rec +def boolFalseRuleRhs07 : VExpr := kernelRecRuleRhs% Bool.rec 0 +def boolTrueRuleRhs07 : VExpr := kernelRecRuleRhs% Bool.rec 1 + +def listInfo07 : ConstantInfo := kernelInductInfo% List +def listNilInfo07 : ConstantInfo := kernelCtorInfo% List.nil +def listConsInfo07 : ConstantInfo := kernelCtorInfo% List.cons +def listRecInfo07 : ConstantInfo := kernelRecInfo% List.rec +def listNilRuleRhs07 : VExpr := kernelRecRuleRhs% List.rec 0 +def listConsRuleRhs07 : VExpr := kernelRecRuleRhs% List.rec 1 + +def optionInfo07 : ConstantInfo := kernelInductInfo% Option +def optionNoneInfo07 : ConstantInfo := kernelCtorInfo% Option.none +def optionSomeInfo07 : ConstantInfo := kernelCtorInfo% Option.some +def optionRecInfo07 : ConstantInfo := kernelRecInfo% Option.rec +def optionNoneRuleRhs07 : VExpr := kernelRecRuleRhs% Option.rec 0 +def optionSomeRuleRhs07 : VExpr := kernelRecRuleRhs% Option.rec 1 + +def prodInfo07 : ConstantInfo := kernelInductInfo% Prod +def prodMkInfo07 : ConstantInfo := kernelCtorInfo% Prod.mk +def prodRecInfo07 : ConstantInfo := kernelRecInfo% Prod.rec +def prodRuleRhs07 : VExpr := kernelRecRuleRhs% Prod.rec 0 + +def heqInfo07 : ConstantInfo := kernelInductInfo% HEq +def heqReflInfo07 : ConstantInfo := kernelCtorInfo% HEq.refl +def heqRecInfo07 : ConstantInfo := kernelRecInfo% HEq.rec +def heqRuleRhs07 : VExpr := kernelRecRuleRhs% HEq.rec 0 + +def finInfo07 : ConstantInfo := kernelInductInfo% Fin +def finMkInfo07 : ConstantInfo := kernelCtorInfo% Fin.mk +def finRecInfo07 : ConstantInfo := kernelRecInfo% Fin.rec +def finRuleRhs07 : VExpr := kernelRecRuleRhs% Fin.rec 0 + +def vectorInfo07 : ConstantInfo := kernelInductInfo% Vector +def vectorMkInfo07 : ConstantInfo := kernelCtorInfo% Vector.mk +def vectorRecInfo07 : ConstantInfo := kernelRecInfo% Vector.rec +def vectorRuleRhs07 : VExpr := kernelRecRuleRhs% Vector.rec 0 + +/-! ## Producer dependency contexts -/ + +def finDependencyMap07 : ConstMap := + ((((({} : ConstMap).insert ``Nat natInfo).insert ``LT + (kernelInductInfo% LT)).insert ``LT.mk + (kernelCtorInfo% LT.mk)).insert ``LT.lt + (.defnInfo (kernelDefVal% LT.lt))).insert ``instLTNat + (.defnInfo (kernelDefVal% instLTNat)) + +def vectorDependencyMap07 : ConstMap := + (((({} : ConstMap).insert ``Nat natInfo).insert ``Eq eqInfo).insert ``Array + (kernelInductInfo% Array)).insert ``Array.size + (.defnInfo (kernelDefVal% Array.size)) + +/-! ## Integrated row type -/ + +structure SingletonKernelRow where + artifact : SingletonParityArtifact + inductInfo : ConstantInfo + ctorInfos : List ConstantInfo + recInfo : ConstantInfo + familyType : VExpr + ctorTypes : List VExpr + recType : VExpr + ruleRhs : List VExpr + dependencies : ConstMap := {} + +namespace SingletonKernelRow + +def constructor? : ConstantInfo → Option Constructor + | .ctorInfo ctor => some { name := ctor.name, type := ctor.type } + | _ => none + +def kernelType? (row : SingletonKernelRow) : Option InductiveType := do + let .inductInfo induct := row.inductInfo | none + let ctors ← row.ctorInfos.mapM constructor? + some { name := induct.name, type := induct.type, ctors := ctors } + +def context (row : SingletonKernelRow) : AddInductive.Context where + env := Kernel.Environment.ofConstants + (.str `_singletonParity row.artifact.label.toString) row.dependencies + lparams := row.inductInfo.levelParams + safety := .safe + allowPrimitive := row.artifact.typeName == ``Nat || + row.artifact.typeName == ``Bool + +def producerAccepted (row : SingletonKernelRow) : Bool := + match row.kernelType? with + | none => false + | some kernelType => + match AddInductive.buildNormalizationCandidate + row.artifact.source.nparams [kernelType] 0 false row.context with + | .ok _ => true + | .error _ => false + +def ctorMatches (row : SingletonKernelRow) (info : ConstantInfo) + (raw : VConstVal) (rawType : VExpr) : Bool := + match info with + | .ctorInfo ctor => + ctor.name == raw.name && + ctor.levelParams.length == row.artifact.source.uvars && + ctor.induct == row.artifact.typeName && + ctor.numParams == row.artifact.source.nparams && + ctor.numFields == (VInductDecl.ctorFields + (VExpr.dropN row.artifact.source.nparams raw.type)).length && + !ctor.isUnsafe && rawType == raw.type + | _ => false + +def constructorsMatch (row : SingletonKernelRow) : + List ConstantInfo → List VConstVal → List VExpr → Bool + | [], [], [] => true + | info :: infos, raw :: raws, rawType :: rawTypes => + row.ctorMatches info raw rawType && + row.constructorsMatch infos raws rawTypes + | _, _, _ => false + +def recursorMatches (row : SingletonKernelRow) : Bool := + match row.recInfo with + | .recInfo rec => + rec.name == .str row.artifact.typeName "rec" && + rec.levelParams.length == row.artifact.generation.recUvars && + rec.all == [row.artifact.typeName] && + rec.numParams == row.artifact.source.nparams && + rec.numIndices == + row.artifact.generation.block.checked.indices.length && + rec.numMotives == 1 && + rec.numMinors == + row.artifact.generation.block.sourceType.ctors.length && + rec.k == row.artifact.generation.kTarget && + !rec.isUnsafe && + rec.rules.map (fun rule => (rule.ctor, rule.nfields)) == + row.artifact.generation.block.sourceType.ctors.map (fun ctor => + (ctor.name, (VInductDecl.ctorFields + (VExpr.dropN row.artifact.source.nparams ctor.type)).length)) && + row.recType == row.artifact.generation.recursor.type && + row.ruleRhs == + row.artifact.generation.generatedRules.map (·.rhs) + | _ => false + +/-- Exact fixed-row agreement after binder-name erasure. Universe order is +still observed: `familyType`/`ctorTypes`/`recType` were converted with the +stored metadata parameter lists, not with elaborator-inferred ordering. -/ +def agrees (row : SingletonKernelRow) : Bool := + match row.inductInfo with + | .inductInfo induct => + induct.name == row.artifact.typeName && + induct.levelParams.length == row.artifact.source.uvars && + induct.numParams == row.artifact.source.nparams && + induct.numIndices == + row.artifact.generation.block.checked.indices.length && + induct.all == [row.artifact.typeName] && + induct.ctors == row.artifact.constructorNames && + induct.numNested == 0 && !induct.isUnsafe && + row.familyType == row.artifact.generation.block.sourceType.type && + row.constructorsMatch row.ctorInfos + row.artifact.generation.block.sourceType.ctors row.ctorTypes && + row.recursorMatches + | _ => false + +end SingletonKernelRow + +/-! ## The fixed rows -/ + +def singletonKernelRows : List SingletonKernelRow := + [ { artifact := singletonPositiveArtifacts[0] + inductInfo := natInfo + ctorInfos := [natZeroInfo, natSuccInfo] + recInfo := natRecInfo + familyType := kernelConstVType% Nat + ctorTypes := [kernelConstVType% Nat.zero, kernelConstVType% Nat.succ] + recType := kernelConstVType% Nat.rec + ruleRhs := [natZeroKernelRuleRhs, natSuccKernelRuleRhs] }, + { artifact := singletonPositiveArtifacts[1] + inductInfo := boolInfo07 + ctorInfos := [boolFalseInfo07, boolTrueInfo07] + recInfo := boolRecInfo07 + familyType := kernelConstVType% Bool + ctorTypes := [kernelConstVType% Bool.false, kernelConstVType% Bool.true] + recType := kernelConstVType% Bool.rec + ruleRhs := [boolFalseRuleRhs07, boolTrueRuleRhs07] }, + { artifact := singletonPositiveArtifacts[2] + inductInfo := listInfo07 + ctorInfos := [listNilInfo07, listConsInfo07] + recInfo := listRecInfo07 + familyType := kernelConstVType% List + ctorTypes := [kernelConstVType% List.nil, kernelConstVType% List.cons] + recType := kernelConstVType% List.rec + ruleRhs := [listNilRuleRhs07, listConsRuleRhs07] }, + { artifact := singletonPositiveArtifacts[3] + inductInfo := optionInfo07 + ctorInfos := [optionNoneInfo07, optionSomeInfo07] + recInfo := optionRecInfo07 + familyType := kernelConstVType% Option + ctorTypes := [kernelConstVType% Option.none, + kernelConstVType% Option.some] + recType := kernelConstVType% Option.rec + ruleRhs := [optionNoneRuleRhs07, optionSomeRuleRhs07] }, + { artifact := singletonPositiveArtifacts[4] + inductInfo := prodInfo07 + ctorInfos := [prodMkInfo07] + recInfo := prodRecInfo07 + familyType := kernelConstVType% Prod + ctorTypes := [kernelConstVType% Prod.mk] + recType := kernelConstVType% Prod.rec + ruleRhs := [prodRuleRhs07] }, + { artifact := singletonPositiveArtifacts[5] + inductInfo := punitInfo06C + ctorInfos := [punitCtorInfo06C] + recInfo := punitRecInfo06C + familyType := kernelConstVType% PUnit + ctorTypes := [kernelConstVType% PUnit.unit] + recType := kernelConstVType% PUnit.rec + ruleRhs := [punitRuleRhs06C] }, + { artifact := singletonPositiveArtifacts[6] + inductInfo := emptyInfo06C + ctorInfos := [] + recInfo := emptyRecInfo06C + familyType := kernelConstVType% Empty + ctorTypes := [] + recType := kernelConstVType% Empty.rec + ruleRhs := [] }, + { artifact := singletonPositiveArtifacts[7] + inductInfo := orInfo06 + ctorInfos := [orInlInfo06, orInrInfo06] + recInfo := orRecInfo06 + familyType := kernelConstVType% Or + ctorTypes := [kernelConstVType% Or.inl, kernelConstVType% Or.inr] + recType := kernelConstVType% Or.rec + ruleRhs := [orInlKernelRuleRhs06, orInrKernelRuleRhs06] }, + { artifact := singletonPositiveArtifacts[8] + inductInfo := andInfo06 + ctorInfos := [andIntroInfo06] + recInfo := andRecInfo06 + familyType := kernelConstVType% And + ctorTypes := [kernelConstVType% And.intro] + recType := kernelConstVType% And.rec + ruleRhs := [andKernelRuleRhs06] }, + { artifact := singletonPositiveArtifacts[9] + inductInfo := eqInfo + ctorInfos := [eqReflInfo] + recInfo := eqRecInfo + familyType := kernelConstVType% Eq + ctorTypes := [kernelConstVType% Eq.refl] + recType := kernelConstVType% Eq.rec + ruleRhs := [eqReflKernelRuleRhs] }, + { artifact := singletonPositiveArtifacts[10] + inductInfo := heqInfo07 + ctorInfos := [heqReflInfo07] + recInfo := heqRecInfo07 + familyType := kernelConstVType% HEq + ctorTypes := [kernelConstVType% HEq.refl] + recType := kernelConstVType% HEq.rec + ruleRhs := [heqRuleRhs07] }, + { artifact := singletonPositiveArtifacts[11] + inductInfo := finInfo07 + ctorInfos := [finMkInfo07] + recInfo := finRecInfo07 + familyType := kernelConstVType% Fin + ctorTypes := [kernelConstVType% Fin.mk] + recType := kernelConstVType% Fin.rec + ruleRhs := [finRuleRhs07] + dependencies := finDependencyMap07 }, + { artifact := singletonPositiveArtifacts[12] + inductInfo := vectorInfo07 + ctorInfos := [vectorMkInfo07] + recInfo := vectorRecInfo07 + familyType := kernelConstVType% Vector + ctorTypes := [kernelConstVType% Vector.mk] + recType := kernelConstVType% Vector.rec + ruleRhs := [vectorRuleRhs07] + dependencies := vectorDependencyMap07 }, + { artifact := singletonPositiveArtifacts[13] + inductInfo := accInfo + ctorInfos := [accIntroInfo] + recInfo := accRecInfo + familyType := kernelConstVType% Acc + ctorTypes := [kernelConstVType% Acc.intro] + recType := kernelConstVType% Acc.rec + ruleRhs := [accKernelRuleRhs] } ] + +example : singletonKernelRows.map (·.artifact.label) = + singletonPositiveArtifacts.map (·.label) := rfl + +#guard singletonKernelRows.all (·.agrees) +#guard singletonKernelRows.all (·.producerAccepted) + +/-! ## Consolidated rejection matrix -/ + +/-- One named rejection whose Boolean is computed by the public Theory +analyzer, the ordinary metadata producer, or the environment transaction it +is intended to guard. -/ +structure SingletonNegativeRow where + label : Name + rejected : Bool + +def theoryDeclarationRejected07 (decl : VInductDecl) : Bool := + decl.checked?.isNone && (VEnv.empty.addInduct decl).isNone + +def producerRejected07 (nparams : Nat) (source : InductiveType) + (context : AddInductive.Context) : Bool := + match AddInductive.buildNormalizationCandidate nparams [source] 0 false + context with + | .error _ => true + | .ok _ => false + +def aliasFormerTruncatedViewType07 : VInductiveType := + { aliasFormerViewType with ctors := [] } + +def aliasFormerTruncatedViewDecl07 : VInductDecl := + { aliasFormerViewDecl with types := [aliasFormerTruncatedViewType07] } + +def listReorderedViewType07 : VInductiveType := + { listType with ctors := listType.ctors.reverse } + +def listReorderedViewDecl07 : VInductDecl := + { listDecl with types := [listReorderedViewType07] } + +def recursorKRejected07 (info : ConstantInfo) (expected : Bool) : Bool := + match info with + | .recInfo rec => rec.k != expected + | _ => false + +/-- A large recursor has one fresh universe parameter and a small recursor +has none. Supplying the wrong mode must therefore disagree with the actual +metadata even when the source-universe list itself is otherwise unchanged. -/ +def recursorEliminationRejected07 (info : ConstantInfo) (sourceUvars : Nat) : + VInductDecl.ElimMode → Bool + | VInductDecl.ElimMode.large => + info.levelParams.length != sourceUvars + 1 + | VInductDecl.ElimMode.small => + info.levelParams.length != sourceUvars + +def typeCollisionEnv07 : VEnv := + (VEnv.empty.addConst ``Nat ⟨0, .sort .zero⟩).get (by decide) + +/-- The complete Spec-07 negative matrix. Earlier phase-specific fixtures +retain their exact kernel error messages; this table makes their coverage and +combined acceptance result executable from one public artifact path. -/ +def singletonNegativeRows : List SingletonNegativeRow := + [ ⟨.mkSimple "loose-variables", + theoryDeclarationRejected07 looseIndexDecl⟩, + ⟨.mkSimple "duplicate-constructor-name", + theoryDeclarationRejected07 duplicateCtorDecl⟩, + ⟨.mkSimple "type-constructor-name-alias", + theoryDeclarationRejected07 typeCtorAliasDecl⟩, + ⟨.mkSimple "constructor-recursor-name-alias", + theoryDeclarationRejected07 ctorRecAliasDecl⟩, + ⟨.mkSimple "self-reference-before-family-staging", + theoryDeclarationRejected07 selfParamDecl⟩, + ⟨.mkSimple "bad-parameter-universe", + theoryDeclarationRejected07 badParamLevelDecl⟩, + ⟨.mkSimple "bad-constructor-universe", + theoryDeclarationRejected07 badCtorLevelDecl⟩, + ⟨.mkSimple "non-sort-family-result", + theoryDeclarationRejected07 nonSortResultDecl⟩, + ⟨.mkSimple "wrong-constructor-result-head", + theoryDeclarationRejected07 wrongCtorHeadDecl⟩, + ⟨.mkSimple "wrong-parameter-spine", + theoryDeclarationRejected07 wrongParamSpineDecl⟩, + ⟨.mkSimple "parameter-count-mismatch", + theoryDeclarationRejected07 shortParamDecl⟩, + ⟨.mkSimple "family-universe-count-mismatch", + theoryDeclarationRejected07 badTypeUvarsDecl⟩, + ⟨.mkSimple "constructor-universe-count-mismatch", + theoryDeclarationRejected07 badCtorUvarsDecl⟩, + ⟨.mkSimple "negative-recursive-pi-domain", + theoryDeclarationRejected07 recDomainDecl⟩, + ⟨.mkSimple "changed-recursive-target-parameter", + theoryDeclarationRejected07 recTargetDecl⟩, + ⟨.mkSimple "recursive-index-family-occurrence", + theoryDeclarationRejected07 recIndexDecl⟩, + ⟨.mkSimple "truncated-normalization-view", + (VInductDecl.normalizedGeneration? aliasFormerRawDecl + aliasFormerTruncatedViewDecl07).isNone⟩, + ⟨.mkSimple "reordered-normalization-view", + (VInductDecl.normalizedGeneration? listDecl + listReorderedViewDecl07).isNone⟩, + ⟨.mkSimple "opaque-normalization-view", + !matrixCandidateExact matrixOpaquePiAliasContext⟩, + ⟨.mkSimple "non-defeq-normalization-view", + producerRejected07 1 matrixNonDefEqType (matrixCandidateContext 10)⟩, + ⟨.mkSimple "nested-negativity", + (spec05CandidateError spec05NestedNegativeType).isSome⟩, + ⟨.mkSimple "family-in-nonrecursive-field", + (spec05CandidateError spec05FamilyNonrecursiveType).isSome⟩, + ⟨.mkSimple "family-in-proof-field", + (spec05CandidateError spec05FamilyProofType).isSome⟩, + ⟨.mkSimple "recursive-local-dependency", + (spec05CandidateError spec05RecursiveDependencyType).isSome && + spec05RecursiveDependencyPreFamilyError.isSome⟩, + ⟨.mkSimple "constructor-field-universe-boundary", + (spec05CandidateError spec05UniverseRejectType).isSome⟩, + ⟨.mkSimple "preexisting-type-name", + (typeCollisionEnv07.addInduct natDecl).isNone⟩, + ⟨.mkSimple "preexisting-constructor-name", + (ctorCollisionEnv.addInduct natDecl).isNone⟩, + ⟨.mkSimple "preexisting-recursor-name", + (recCollisionEnv.addInduct natDecl).isNone⟩, + ⟨.mkSimple "eq-wrong-k-target", recursorKRejected07 eqRecInfo false⟩, + ⟨.mkSimple "and-wrong-k-target", recursorKRejected07 andRecInfo06 true⟩, + ⟨.mkSimple "eq-wrong-small-elimination", + recursorEliminationRejected07 eqRecInfo eqDecl.uvars + VInductDecl.ElimMode.small⟩, + ⟨.mkSimple "or-wrong-large-elimination", + recursorEliminationRejected07 orRecInfo06 orDecl.uvars + VInductDecl.ElimMode.large⟩ ] + +example : singletonNegativeRows.length = 32 := rfl + +#guard singletonNegativeRows.all (·.rejected) + +/-! ## Exact trust manifests for the public matrix roots -/ + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.singletonKernelRows [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.singletonNegativeRows [ + propext, + Classical.choice, + Quot.sound, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Level.hasMVar_eq] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean b/Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean new file mode 100644 index 000000000..944cc6aab --- /dev/null +++ b/Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean @@ -0,0 +1,2820 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.Environment.SingletonParityMatrix + +open Ix.Theory (VLevel) + +/-! +# Spec-07 environment replay inventory + +This module is the sole public environment-facing inventory for singleton +parity. A row packages the actual implementation map, the Theory input and +output environments, input alignment/order, and the proof-carrying inductive +transaction. Consequently every row exposes final alignment and orderedness; +mere Theory generation is not enough to inhabit this structure. +-/ + +namespace Ix.Theory.Named.InductiveReplayFixtures + +open Lean +open Ix.Theory.Named.InductiveFixtures + +local instance instInhabitedVEnvParityReplay : Inhabited VEnv := ⟨.empty⟩ + +structure SingletonReplayArtifact where + label : Name + source : VInductDecl + inputMap : ConstMap + inputEnv : VEnv + inputMapWF : inputMap.WF + outputMap : ConstMap + outputEnv : VEnv + inputOrdered : inputEnv.Ordered + transaction : AddInduct inputMap inputEnv source outputMap outputEnv + aligned : Aligned .safe outputMap outputEnv + +namespace SingletonReplayArtifact + +theorem outputAligned (artifact : SingletonReplayArtifact) : + Aligned .safe artifact.outputMap artifact.outputEnv := artifact.aligned + +theorem outputOrdered (artifact : SingletonReplayArtifact) : + artifact.outputEnv.Ordered := by + obtain ⟨generation, generation_wf, transaction⟩ := + artifact.transaction.to_addInduct + exact VEnv.addInductGeneration_WF artifact.inputOrdered generation_wf + transaction + +end SingletonReplayArtifact + +/-! ## Reusable staging facts for fixed-family replays -/ + +/-- The raw family constant retained by a generation certificate is a type in +the replay input environment. -/ +theorem replayRawFamilyWF07 + {source : VInductDecl} {generation : source.GenerationChecked} + {inputEnv : VEnv} (generationWF : generation.WF inputEnv) : + generation.block.sourceType.toVConstant.WF inputEnv := by + show inputEnv.IsType generation.block.sourceType.uvars [] + generation.block.sourceType.type + rw [generation.block.sourceType_uvars_eq] + exact generationWF.rawFamily_isType + +/-- The raw family insertion preserves ordering whenever the retained +generation certificate is well formed in the replay input environment. -/ +theorem replayTypeEnv_ordered07 + {source : VInductDecl} {generation : source.GenerationChecked} + {inputEnv typeEnv : VEnv} + (inputOrdered : inputEnv.Ordered) + (generationWF : generation.WF inputEnv) + (addType : inputEnv.addConst generation.block.sourceType.name + generation.block.sourceType.toVConstant = some typeEnv) : + typeEnv.Ordered := by + refine .const inputOrdered ?_ addType + show inputEnv.IsType generation.block.sourceType.uvars [] + generation.block.sourceType.type + rw [generation.block.sourceType_uvars_eq] + exact generationWF.rawFamily_isType + +/-- Each stored raw constructor is well formed immediately after the raw +family insertion. Later constructor stages use monotonicity to transport +this certificate across earlier constructor insertions. -/ +theorem replayRawCtorWF07 + {source : VInductDecl} {generation : source.GenerationChecked} + {inputEnv typeEnv : VEnv} + (generationWF : generation.WF inputEnv) + (addType : inputEnv.addConst generation.block.sourceType.name + generation.block.sourceType.toVConstant = some typeEnv) + (raw : VConstVal) (hraw : raw ∈ generation.block.sourceType.ctors) : + raw.toVConstant.WF typeEnv := by + have hraw' : raw ∈ generation.block.ctorPairs.map (·.raw) := by + rw [generation.rawCtors_eq] + exact hraw + obtain ⟨ctor, hctor, rfl⟩ := List.mem_map.1 hraw' + show typeEnv.IsType ctor.raw.uvars [] ctor.raw.type + rw [generation.ctor_uvars_eq hctor] + exact generationWF.rawCtor_isType addType hctor + +/-- The complete raw-constructor fold preserves ordering. This includes the +zero-constructor case, where the fold is the identity. -/ +theorem replayCtorEnv_ordered07 + {source : VInductDecl} {generation : source.GenerationChecked} + {inputEnv typeEnv ctorEnv : VEnv} + (generationWF : generation.WF inputEnv) + (addType : inputEnv.addConst generation.block.sourceType.name + generation.block.sourceType.toVConstant = some typeEnv) + (typeOrdered : typeEnv.Ordered) + (addCtors : List.foldlM + (fun env (ctor : VConstVal) => + env.addConst ctor.name ctor.toVConstant) + typeEnv generation.block.sourceType.ctors = some ctorEnv) : + ctorEnv.Ordered := by + have ctorWF : ∀ ctor ∈ generation.block.sourceType.ctors, + ctor.toVConstant.WF typeEnv := by + intro raw hraw + exact replayRawCtorWF07 generationWF addType raw hraw + exact VInductDecl.constFold_ordered + generation.block.sourceType.ctors typeOrdered ctorWF addCtors + +/-- Reconstruct the precise mixed-generation environment after the family and +constructor constants have been inserted. Its recursor certificate is what +turns exact kernel recursor metadata into a `TrConstVal`. -/ +theorem replayGenerationEnv07 + {source : VInductDecl} {generation : source.GenerationChecked} + {inputEnv typeEnv ctorEnv : VEnv} + (generationWF : generation.WF inputEnv) + (addType : inputEnv.addConst generation.block.sourceType.name + generation.block.sourceType.toVConstant = some typeEnv) + (addCtors : List.foldlM + (fun env (ctor : VConstVal) => + env.addConst ctor.name ctor.toVConstant) + typeEnv generation.block.sourceType.ctors = some ctorEnv) + (ctorOrdered : ctorEnv.Ordered) : + VInductDecl.GenerationEnv generation ctorEnv := by + obtain ⟨typeToCtor, ctorLookup, -⟩ := + VInductDecl.ctorFold_spec generation.block.sourceType.ctors addCtors + have inputToType := VEnv.addConst_le addType + have inputToCtor := inputToType.trans typeToCtor + have familyLookup : ctorEnv.constants + generation.block.sourceType.name = + some generation.block.sourceType.toVConstant := + typeToCtor.constants (VEnv.addConst_self addType) + have constructorsLookup : ∀ ctor ∈ generation.block.ctorPairs, + ctorEnv.constants ctor.raw.name = some ctor.raw.toVConstant := by + intro ctor hctor + apply ctorLookup ctor.raw + rw [← generation.rawCtors_eq] + exact List.mem_map.2 ⟨ctor, hctor, rfl⟩ + exact generationWF.toGenerationEnv addType inputToCtor typeToCtor + ctorOrdered familyLookup constructorsLookup + +/-! ## Replays already established by the completed singleton pipeline -/ + +def natReplay07 : SingletonReplayArtifact where + label := ``Nat + source := natDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := natMap + outputEnv := natFinalEnv + inputOrdered := .empty + transaction := nat_addInduct + aligned := nat_aligned + +def eqReplay07 : SingletonReplayArtifact where + label := ``Eq + source := eqDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := eqMap + outputEnv := eqFinalEnv + inputOrdered := .empty + transaction := eq_addInduct + aligned := eq_aligned + +def accReplay07 : SingletonReplayArtifact where + label := ``Acc + source := accDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := accMap + outputEnv := accFinalEnv + inputOrdered := .empty + transaction := acc_addInduct + aligned := acc_aligned + +def aliasFormerReplay07 : SingletonReplayArtifact where + label := ``AliasFormer + source := aliasFormerRawDecl + inputMap := typeFamilyAliasMap + inputEnv := typeFamilyAliasEnv + inputMapWF := typeFamilyAliasMap_wf + outputMap := aliasFormerMap + outputEnv := aliasFormerFinalEnv + inputOrdered := typeFamilyAliasEnv_ordered + transaction := aliasFormer_addInduct_checked + aligned := aliasFormer_aligned_checked + +def aliasRecReplay07 : SingletonReplayArtifact where + label := ``AliasRec + source := aliasRecRawDecl + inputMap := recAliasMap + inputEnv := recAliasEnv + inputMapWF := recAliasMap_wf + outputMap := aliasRecMap + outputEnv := aliasRecFinalEnv + inputOrdered := recAliasEnv_ordered + transaction := aliasRec_addInduct_checked + aligned := aliasRec_aligned_checked + +def normalizationMatrixReplay07 : SingletonReplayArtifact where + label := ``NormalizationMatrix + source := normalizationMatrixRawDecl + inputMap := matrixAliasMap + inputEnv := normalizationMatrixAliasEnv + inputMapWF := matrixAliasMap_wf + outputMap := normalizationMatrixMap + outputEnv := normalizationMatrixFinalEnv + inputOrdered := normalizationMatrixAliasEnv_ordered + transaction := normalizationMatrix_addInduct + aligned := normalizationMatrix_aligned + +def annotatedPiReplay07 : SingletonReplayArtifact where + label := ``AnnotatedPi + source := annotatedPiRawDecl + inputMap := _ + inputEnv := outParamEnv + inputMapWF := annotatedReplayInputMap_wf + outputMap := _ + outputEnv := annotatedPiFinalEnv + inputOrdered := outParamEnv_ordered + transaction := annotatedPi_addInduct_checked + aligned := annotatedPi_aligned_checked + +def annotatedParamReplay07 : SingletonReplayArtifact where + label := ``AnnotatedParam + source := annotatedParamRawDecl + inputMap := _ + inputEnv := outParamEnv + inputMapWF := annotatedReplayInputMap_wf + outputMap := _ + outputEnv := annotatedParamFinalEnv + inputOrdered := outParamEnv_ordered + transaction := annotatedParam_addInduct_checked + aligned := annotatedParam_aligned_checked + +/-! ## Fixed-family replays -/ + +/-! ### Bool -/ + +theorem boolDeclWF07 : boolDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro type htype + have htype' : type = boolType := + List.mem_singleton.1 (by simpa [boolDecl] using htype) + subst type + refine ⟨?_, ?_⟩ + · change True + trivial + · intro ctor hctor + rcases List.mem_cons.1 hctor with rfl | hctor + · constructor + · change True + trivial + · exact .nil + · have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change True + trivial + · exact .nil + +theorem boolGenerationWF07 : boolGenerationChecked.WF VEnv.empty := by + exact (boolChecked.wf_of_decl boolDeclWF07).identityGeneration .empty + +def boolTypeEnv07 : VEnv := + (VEnv.empty.addConst boolType.name boolType.toVConstant).get! + +def boolFalseEnv07 : VEnv := + (boolTypeEnv07.addConst boolType.ctors[0].name + boolType.ctors[0].toVConstant).get! + +def boolCtorEnv07 : VEnv := + (boolFalseEnv07.addConst boolType.ctors[1].name + boolType.ctors[1].toVConstant).get! + +def boolRecEnv07 : VEnv := + (boolCtorEnv07.addConst ``Bool.rec + (inductGenerationRecVal boolGenerationChecked).toVConstant).get! + +def boolFinalEnv07 : VEnv := + boolGenerationChecked.generatedRules.foldl VEnv.addDefEq boolRecEnv07 + +def boolTypeMap07 : ConstMap := + ({} : ConstMap).insert ``Bool boolInfo07 + +def boolFalseMap07 : ConstMap := + boolTypeMap07.insert ``Bool.false boolFalseInfo07 + +def boolCtorMap07 : ConstMap := + boolFalseMap07.insert ``Bool.true boolTrueInfo07 + +def boolMap07 : ConstMap := + boolCtorMap07.insert ``Bool.rec boolRecInfo07 + +theorem boolTypeEnv_ordered07 : boolTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty boolGenerationWF07 rfl + +theorem boolCtorEnv_ordered07 : boolCtorEnv07.Ordered := + replayCtorEnv_ordered07 boolGenerationWF07 rfl + boolTypeEnv_ordered07 rfl + +theorem boolGenerationEnv07 : + VInductDecl.GenerationEnv boolGenerationChecked boolCtorEnv07 := + replayGenerationEnv07 boolGenerationWF07 rfl rfl + boolCtorEnv_ordered07 + +theorem boolInfoTr07 : + TrConstVal .safe VEnv.empty boolInfo07 boolType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + exact .sort rfl + +theorem boolFalseInfoTr07 : + TrConstVal .safe boolTypeEnv07 boolFalseInfo07 boolType.ctors[0] := by + have hBool : boolTypeEnv07.constants ``Bool = + some boolType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr boolTypeEnv07 boolFalseInfo07.levelParams [] + boolFalseInfo07.type boolType.ctors[0].type := by + tr_type_expr_tac + exact shape.to_trExprS boolTypeEnv_ordered07 trivial + ⟨.sort (.succ .zero), by type_tac⟩ + +theorem boolTrueInfoTr07 : + TrConstVal .safe boolFalseEnv07 boolTrueInfo07 boolType.ctors[1] := by + have hBool : boolFalseEnv07.constants ``Bool = + some boolType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr boolFalseEnv07 boolTrueInfo07.levelParams [] + boolTrueInfo07.type boolType.ctors[1].type := by + tr_type_expr_tac + have falseOrdered : boolFalseEnv07.Ordered := by + refine .const (n := boolType.ctors[0].name) + (ci := boolType.ctors[0].toVConstant) boolTypeEnv_ordered07 ?_ rfl + exact ⟨.succ .zero, by type_tac⟩ + exact shape.to_trExprS falseOrdered trivial + ⟨.sort (.succ .zero), by type_tac⟩ + +theorem boolRecInfoTr07 : + TrConstVal .safe boolCtorEnv07 boolRecInfo07 + (inductGenerationRecVal boolGenerationChecked) := by + have hBool : boolCtorEnv07.constants ``Bool = + some boolType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr boolCtorEnv07 boolRecInfo07.levelParams [] + boolRecInfo07.type + (inductGenerationRecVal boolGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := boolGenerationEnv07.recursor_wf + exact shape.to_trExprS boolCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem boolTypeFresh07 : ({} : ConstMap).find? ``Bool = none := by + simp [SMap.find?] + +theorem boolTypeMapWF07 : boolTypeMap07.WF := + SMap.WF.empty.insert _ _ boolTypeFresh07 + +theorem boolFalseFresh07 : boolTypeMap07.find? ``Bool.false = none := by + rw [boolTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem boolFalseMapWF07 : boolFalseMap07.WF := + boolTypeMapWF07.insert _ _ boolFalseFresh07 + +theorem boolTrueFresh07 : boolFalseMap07.find? ``Bool.true = none := by + rw [boolFalseMap07, boolTypeMapWF07.find?_insert, boolTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem boolCtorMapWF07 : boolCtorMap07.WF := + boolFalseMapWF07.insert _ _ boolTrueFresh07 + +theorem boolRecFresh07 : boolCtorMap07.find? ``Bool.rec = none := by + rw [boolCtorMap07, boolFalseMapWF07.find?_insert, boolFalseMap07, + boolTypeMapWF07.find?_insert, boolTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem boolAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty boolDecl + boolMap07 boolFinalEnv07 := by + refine ⟨{ + generation := boolGenerationChecked + generation_wf := boolGenerationWF07 + typeMap := boolTypeMap07 + typeEnv := boolTypeEnv07 + ctorMap := boolCtorMap07 + ctorEnv := boolCtorEnv07 + recEnv := boolRecEnv07 + addType := { + info := boolInfo07 + kind_eq := by simp [boolInfo07, InductConstantKind.Matches] + tr := boolInfoTr07 + map_fresh := boolTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := boolRecInfo07 + kind_eq := by simp [boolRecInfo07, InductConstantKind.Matches] + tr := boolRecInfoTr07 + map_fresh := boolRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := boolFalseInfo07 + kind_eq := by simp [boolFalseInfo07, InductConstantKind.Matches] + tr := boolFalseInfoTr07 + map_fresh := by simpa [boolType] using boolFalseFresh07 + env_add := rfl + map_add := rfl } + (.cons { + info := boolTrueInfo07 + kind_eq := by simp [boolTrueInfo07, InductConstantKind.Matches] + tr := boolTrueInfoTr07 + map_fresh := by + change boolFalseMap07.find? ``Bool.true = none + exact boolTrueFresh07 + env_add := rfl + map_add := rfl } .nil) + +theorem boolAligned07 : Aligned .safe boolMap07 boolFinalEnv07 := + Aligned.addInduct boolAddInduct07 .empty + +def boolReplay07 : SingletonReplayArtifact where + label := ``Bool + source := boolDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := boolMap07 + outputEnv := boolFinalEnv07 + inputOrdered := .empty + transaction := boolAddInduct07 + aligned := boolAligned07 + +/-! ### List -/ + +theorem listCheckedWF07 : listChecked.WF VEnv.empty := by + constructor + · change VEnv.empty.OnTel 1 [] [.sort (.succ (.param 0))] + exact ⟨⟨.succ (.succ (.param 0)), VEnv.HasType.sort (by decide)⟩, + trivial⟩ + · intro ctor hctor + rcases List.mem_cons.1 hctor with rfl | hctor + · constructor + · change True + trivial + · exact .nil + · have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change VInductDecl.fieldsWF 1 ``List 1 VEnv.empty + (.succ (.param 0)) [] [.sort (.succ (.param 0))] 0 + [.bvar 0, + .app (.const ``List [.param 0]) (.bvar 1)] + constructor + · exact .inr (.inr ⟨rfl, .succ (.param 0), by type_tac, + .inr (VLevel.le_refl _)⟩) + constructor + · intro recursive + contradiction + constructor + · exact .inl rfl + constructor + · intro _ + exact .nil + · trivial + · exact .nil + +theorem listGenerationWF07 : listGenerationChecked.WF VEnv.empty := by + exact listCheckedWF07.identityGeneration .empty + +def listTypeEnv07 : VEnv := + (VEnv.empty.addConst listType.name listType.toVConstant).get! + +def listNilEnv07 : VEnv := + (listTypeEnv07.addConst listType.ctors[0].name + listType.ctors[0].toVConstant).get! + +def listCtorEnv07 : VEnv := + (listNilEnv07.addConst listType.ctors[1].name + listType.ctors[1].toVConstant).get! + +def listRecEnv07 : VEnv := + (listCtorEnv07.addConst ``List.rec + (inductGenerationRecVal listGenerationChecked).toVConstant).get! + +def listFinalEnv07 : VEnv := + listGenerationChecked.generatedRules.foldl VEnv.addDefEq listRecEnv07 + +def listTypeMap07 : ConstMap := + ({} : ConstMap).insert ``List listInfo07 + +def listNilMap07 : ConstMap := + listTypeMap07.insert ``List.nil listNilInfo07 + +def listCtorMap07 : ConstMap := + listNilMap07.insert ``List.cons listConsInfo07 + +def listMap07 : ConstMap := + listCtorMap07.insert ``List.rec listRecInfo07 + +theorem listTypeEnv_ordered07 : listTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty listGenerationWF07 rfl + +theorem listNilEnv_ordered07 : listNilEnv07.Ordered := by + refine .const (n := listType.ctors[0].name) + (ci := listType.ctors[0].toVConstant) listTypeEnv_ordered07 ?_ rfl + exact replayRawCtorWF07 listGenerationWF07 rfl listType.ctors[0] + (.head _) + +theorem listCtorEnv_ordered07 : listCtorEnv07.Ordered := + replayCtorEnv_ordered07 listGenerationWF07 rfl + listTypeEnv_ordered07 rfl + +theorem listGenerationEnv07 : + VInductDecl.GenerationEnv listGenerationChecked listCtorEnv07 := + replayGenerationEnv07 listGenerationWF07 rfl rfl + listCtorEnv_ordered07 + +theorem listInfoTr07 : + TrConstVal .safe VEnv.empty listInfo07 listType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr VEnv.empty listInfo07.levelParams [] + listInfo07.type listType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 listGenerationWF07 + exact shape.to_trExprS .empty trivial ⟨.sort sort, familyType⟩ + +theorem listNilInfoTr07 : + TrConstVal .safe listTypeEnv07 listNilInfo07 listType.ctors[0] := by + have hList : listTypeEnv07.constants ``List = + some listType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr listTypeEnv07 listNilInfo07.levelParams [] + listNilInfo07.type listType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 listGenerationWF07 rfl + listType.ctors[0] (.head _) + exact shape.to_trExprS listTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem listConsInfoTr07 : + TrConstVal .safe listNilEnv07 listConsInfo07 listType.ctors[1] := by + have hList : listNilEnv07.constants ``List = + some listType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr listNilEnv07 listConsInfo07.levelParams [] + listConsInfo07.type listType.ctors[1].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 listGenerationWF07 rfl + listType.ctors[1] (.tail _ (.head _)) + have typeToNil : listTypeEnv07 ≤ listNilEnv07 := + VEnv.addConst_le (show listTypeEnv07.addConst + listType.ctors[0].name listType.ctors[0].toVConstant = + some listNilEnv07 from rfl) + exact shape.to_trExprS listNilEnv_ordered07 trivial + ⟨.sort sort, ctorType.mono typeToNil⟩ + +theorem listRecInfoTr07 : + TrConstVal .safe listCtorEnv07 listRecInfo07 + (inductGenerationRecVal listGenerationChecked) := by + have hList : listCtorEnv07.constants ``List = + some listType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr listCtorEnv07 listRecInfo07.levelParams [] + listRecInfo07.type + (inductGenerationRecVal listGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := listGenerationEnv07.recursor_wf + exact shape.to_trExprS listCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem listTypeFresh07 : ({} : ConstMap).find? ``List = none := by + simp [SMap.find?] + +theorem listTypeMapWF07 : listTypeMap07.WF := + SMap.WF.empty.insert _ _ listTypeFresh07 + +theorem listNilFresh07 : listTypeMap07.find? ``List.nil = none := by + rw [listTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem listNilMapWF07 : listNilMap07.WF := + listTypeMapWF07.insert _ _ listNilFresh07 + +theorem listConsFresh07 : listNilMap07.find? ``List.cons = none := by + rw [listNilMap07, listTypeMapWF07.find?_insert, listTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem listCtorMapWF07 : listCtorMap07.WF := + listNilMapWF07.insert _ _ listConsFresh07 + +theorem listRecFresh07 : listCtorMap07.find? ``List.rec = none := by + rw [listCtorMap07, listNilMapWF07.find?_insert, listNilMap07, + listTypeMapWF07.find?_insert, listTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem listAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty listDecl + listMap07 listFinalEnv07 := by + refine ⟨{ + generation := listGenerationChecked + generation_wf := listGenerationWF07 + typeMap := listTypeMap07 + typeEnv := listTypeEnv07 + ctorMap := listCtorMap07 + ctorEnv := listCtorEnv07 + recEnv := listRecEnv07 + addType := { + info := listInfo07 + kind_eq := by simp [listInfo07, InductConstantKind.Matches] + tr := listInfoTr07 + map_fresh := listTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := listRecInfo07 + kind_eq := by simp [listRecInfo07, InductConstantKind.Matches] + tr := listRecInfoTr07 + map_fresh := listRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := listNilInfo07 + kind_eq := by simp [listNilInfo07, InductConstantKind.Matches] + tr := listNilInfoTr07 + map_fresh := by simpa [listType] using listNilFresh07 + env_add := rfl + map_add := rfl } + (.cons { + info := listConsInfo07 + kind_eq := by simp [listConsInfo07, InductConstantKind.Matches] + tr := listConsInfoTr07 + map_fresh := by + change listNilMap07.find? ``List.cons = none + exact listConsFresh07 + env_add := rfl + map_add := rfl } .nil) + +theorem listAligned07 : Aligned .safe listMap07 listFinalEnv07 := + Aligned.addInduct listAddInduct07 .empty + +def listReplay07 : SingletonReplayArtifact where + label := ``List + source := listDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := listMap07 + outputEnv := listFinalEnv07 + inputOrdered := .empty + transaction := listAddInduct07 + aligned := listAligned07 + +/-! ### Option -/ + +theorem optionDeclWF07 : optionDecl.WF VEnv.empty := by + refine ⟨rfl, ?_⟩ + intro type htype + have htype' : type = optionType := + List.mem_singleton.1 (by simpa [optionDecl] using htype) + subst type + refine ⟨?_, ?_⟩ + · change VEnv.empty.OnTel 1 [] [.sort (.succ (.param 0))] + exact ⟨⟨.succ (.succ (.param 0)), VEnv.HasType.sort (by decide)⟩, + trivial⟩ + · intro ctor hctor + rcases List.mem_cons.1 hctor with rfl | hctor + · constructor + · change True + trivial + · exact .nil + · have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change VInductDecl.fieldsWF 1 ``Option 1 VEnv.empty + (.succ (.param 0)) [] [.sort (.succ (.param 0))] 0 [.bvar 0] + constructor + · exact .inr (.inr ⟨rfl, .succ (.param 0), by type_tac, + .inr (VLevel.le_refl _)⟩) + constructor + · intro recursive + contradiction + · trivial + · exact .nil + +theorem optionGenerationWF07 : optionGenerationChecked.WF VEnv.empty := by + exact (optionChecked.wf_of_decl optionDeclWF07).identityGeneration .empty + +def optionTypeEnv07 : VEnv := + (VEnv.empty.addConst optionType.name optionType.toVConstant).get! + +def optionNoneEnv07 : VEnv := + (optionTypeEnv07.addConst optionType.ctors[0].name + optionType.ctors[0].toVConstant).get! + +def optionCtorEnv07 : VEnv := + (optionNoneEnv07.addConst optionType.ctors[1].name + optionType.ctors[1].toVConstant).get! + +def optionRecEnv07 : VEnv := + (optionCtorEnv07.addConst ``Option.rec + (inductGenerationRecVal optionGenerationChecked).toVConstant).get! + +def optionFinalEnv07 : VEnv := + optionGenerationChecked.generatedRules.foldl VEnv.addDefEq optionRecEnv07 + +def optionTypeMap07 : ConstMap := + ({} : ConstMap).insert ``Option optionInfo07 + +def optionNoneMap07 : ConstMap := + optionTypeMap07.insert ``Option.none optionNoneInfo07 + +def optionCtorMap07 : ConstMap := + optionNoneMap07.insert ``Option.some optionSomeInfo07 + +def optionMap07 : ConstMap := + optionCtorMap07.insert ``Option.rec optionRecInfo07 + +theorem optionTypeEnv_ordered07 : optionTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty optionGenerationWF07 rfl + +theorem optionNoneEnv_ordered07 : optionNoneEnv07.Ordered := by + refine .const (n := optionType.ctors[0].name) + (ci := optionType.ctors[0].toVConstant) optionTypeEnv_ordered07 ?_ rfl + exact replayRawCtorWF07 optionGenerationWF07 rfl optionType.ctors[0] + (.head _) + +theorem optionCtorEnv_ordered07 : optionCtorEnv07.Ordered := + replayCtorEnv_ordered07 optionGenerationWF07 rfl + optionTypeEnv_ordered07 rfl + +theorem optionGenerationEnv07 : + VInductDecl.GenerationEnv optionGenerationChecked optionCtorEnv07 := + replayGenerationEnv07 optionGenerationWF07 rfl rfl + optionCtorEnv_ordered07 + +theorem optionInfoTr07 : + TrConstVal .safe VEnv.empty optionInfo07 optionType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr VEnv.empty optionInfo07.levelParams [] + optionInfo07.type optionType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 optionGenerationWF07 + exact shape.to_trExprS .empty trivial ⟨.sort sort, familyType⟩ + +theorem optionNoneInfoTr07 : + TrConstVal .safe optionTypeEnv07 optionNoneInfo07 optionType.ctors[0] := by + have hOption : optionTypeEnv07.constants ``Option = + some optionType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr optionTypeEnv07 optionNoneInfo07.levelParams [] + optionNoneInfo07.type optionType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 optionGenerationWF07 rfl + optionType.ctors[0] (.head _) + exact shape.to_trExprS optionTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem optionSomeInfoTr07 : + TrConstVal .safe optionNoneEnv07 optionSomeInfo07 optionType.ctors[1] := by + have hOption : optionNoneEnv07.constants ``Option = + some optionType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr optionNoneEnv07 optionSomeInfo07.levelParams [] + optionSomeInfo07.type optionType.ctors[1].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 optionGenerationWF07 rfl + optionType.ctors[1] (.tail _ (.head _)) + have typeToNone : optionTypeEnv07 ≤ optionNoneEnv07 := + VEnv.addConst_le (show optionTypeEnv07.addConst + optionType.ctors[0].name optionType.ctors[0].toVConstant = + some optionNoneEnv07 from rfl) + exact shape.to_trExprS optionNoneEnv_ordered07 trivial + ⟨.sort sort, ctorType.mono typeToNone⟩ + +theorem optionRecInfoTr07 : + TrConstVal .safe optionCtorEnv07 optionRecInfo07 + (inductGenerationRecVal optionGenerationChecked) := by + have hOption : optionCtorEnv07.constants ``Option = + some optionType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr optionCtorEnv07 optionRecInfo07.levelParams [] + optionRecInfo07.type + (inductGenerationRecVal optionGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := optionGenerationEnv07.recursor_wf + exact shape.to_trExprS optionCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem optionTypeFresh07 : ({} : ConstMap).find? ``Option = none := by + simp [SMap.find?] + +theorem optionTypeMapWF07 : optionTypeMap07.WF := + SMap.WF.empty.insert _ _ optionTypeFresh07 + +theorem optionNoneFresh07 : optionTypeMap07.find? ``Option.none = none := by + rw [optionTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem optionNoneMapWF07 : optionNoneMap07.WF := + optionTypeMapWF07.insert _ _ optionNoneFresh07 + +theorem optionSomeFresh07 : optionNoneMap07.find? ``Option.some = none := by + rw [optionNoneMap07, optionTypeMapWF07.find?_insert, optionTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem optionCtorMapWF07 : optionCtorMap07.WF := + optionNoneMapWF07.insert _ _ optionSomeFresh07 + +theorem optionRecFresh07 : optionCtorMap07.find? ``Option.rec = none := by + rw [optionCtorMap07, optionNoneMapWF07.find?_insert, optionNoneMap07, + optionTypeMapWF07.find?_insert, optionTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem optionAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty optionDecl + optionMap07 optionFinalEnv07 := by + refine ⟨{ + generation := optionGenerationChecked + generation_wf := optionGenerationWF07 + typeMap := optionTypeMap07 + typeEnv := optionTypeEnv07 + ctorMap := optionCtorMap07 + ctorEnv := optionCtorEnv07 + recEnv := optionRecEnv07 + addType := { + info := optionInfo07 + kind_eq := by simp [optionInfo07, InductConstantKind.Matches] + tr := optionInfoTr07 + map_fresh := optionTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := optionRecInfo07 + kind_eq := by simp [optionRecInfo07, InductConstantKind.Matches] + tr := optionRecInfoTr07 + map_fresh := optionRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := optionNoneInfo07 + kind_eq := by simp [optionNoneInfo07, InductConstantKind.Matches] + tr := optionNoneInfoTr07 + map_fresh := by simpa [optionType] using optionNoneFresh07 + env_add := rfl + map_add := rfl } + (.cons { + info := optionSomeInfo07 + kind_eq := by simp [optionSomeInfo07, InductConstantKind.Matches] + tr := optionSomeInfoTr07 + map_fresh := by + change optionNoneMap07.find? ``Option.some = none + exact optionSomeFresh07 + env_add := rfl + map_add := rfl } .nil) + +theorem optionAligned07 : Aligned .safe optionMap07 optionFinalEnv07 := + Aligned.addInduct optionAddInduct07 .empty + +def optionReplay07 : SingletonReplayArtifact where + label := ``Option + source := optionDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := optionMap07 + outputEnv := optionFinalEnv07 + inputOrdered := .empty + transaction := optionAddInduct07 + aligned := optionAligned07 + +/-! ### Prod -/ + +theorem prodCheckedWF07 : prodChecked.WF VEnv.empty := by + constructor + · change VEnv.empty.OnTel 2 [] + [.sort (.succ (.param 0)), .sort (.succ (.param 1))] + exact ⟨⟨.succ (.succ (.param 0)), VEnv.HasType.sort (by decide)⟩, + ⟨⟨.succ (.succ (.param 1)), VEnv.HasType.sort (by decide)⟩, + trivial⟩⟩ + · intro ctor hctor + have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change VInductDecl.fieldsWF 2 ``Prod 2 VEnv.empty + (.max (.succ (.param 0)) (.succ (.param 1))) [] + [.sort (.succ (.param 1)), .sort (.succ (.param 0))] 0 + [.bvar 1, .bvar 1] + constructor + · exact .inr (.inr ⟨rfl, .succ (.param 0), by type_tac, + .inr VLevel.le_max_left⟩) + constructor + · intro recursive + contradiction + constructor + · exact .inr (.inr ⟨rfl, .succ (.param 1), by type_tac, + .inr VLevel.le_max_right⟩) + constructor + · intro recursive + contradiction + · trivial + · exact .nil + +theorem prodGenerationWF07 : prodGenerationChecked.WF VEnv.empty := by + exact prodCheckedWF07.identityGeneration .empty + +def prodTypeEnv07 : VEnv := + (VEnv.empty.addConst prodType.name prodType.toVConstant).get! + +def prodCtorEnv07 : VEnv := + (prodTypeEnv07.addConst prodType.ctors[0].name + prodType.ctors[0].toVConstant).get! + +def prodRecEnv07 : VEnv := + (prodCtorEnv07.addConst ``Prod.rec + (inductGenerationRecVal prodGenerationChecked).toVConstant).get! + +def prodFinalEnv07 : VEnv := + prodGenerationChecked.generatedRules.foldl VEnv.addDefEq prodRecEnv07 + +def prodTypeMap07 : ConstMap := + ({} : ConstMap).insert ``Prod prodInfo07 + +def prodCtorMap07 : ConstMap := + prodTypeMap07.insert ``Prod.mk prodMkInfo07 + +def prodMap07 : ConstMap := + prodCtorMap07.insert ``Prod.rec prodRecInfo07 + +theorem prodTypeEnv_ordered07 : prodTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty prodGenerationWF07 rfl + +theorem prodCtorEnv_ordered07 : prodCtorEnv07.Ordered := + replayCtorEnv_ordered07 prodGenerationWF07 rfl + prodTypeEnv_ordered07 rfl + +theorem prodGenerationEnv07 : + VInductDecl.GenerationEnv prodGenerationChecked prodCtorEnv07 := + replayGenerationEnv07 prodGenerationWF07 rfl rfl + prodCtorEnv_ordered07 + +theorem prodInfoTr07 : + TrConstVal .safe VEnv.empty prodInfo07 prodType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr VEnv.empty prodInfo07.levelParams [] + prodInfo07.type prodType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 prodGenerationWF07 + exact shape.to_trExprS .empty trivial ⟨.sort sort, familyType⟩ + +theorem prodCtorInfoTr07 : + TrConstVal .safe prodTypeEnv07 prodMkInfo07 prodType.ctors[0] := by + have hProd : prodTypeEnv07.constants ``Prod = + some prodType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr prodTypeEnv07 prodMkInfo07.levelParams [] + prodMkInfo07.type prodType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 prodGenerationWF07 rfl + prodType.ctors[0] (.head _) + exact shape.to_trExprS prodTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem prodRecInfoTr07 : + TrConstVal .safe prodCtorEnv07 prodRecInfo07 + (inductGenerationRecVal prodGenerationChecked) := by + have hProd : prodCtorEnv07.constants ``Prod = + some prodType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr prodCtorEnv07 prodRecInfo07.levelParams [] + prodRecInfo07.type + (inductGenerationRecVal prodGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := prodGenerationEnv07.recursor_wf + exact shape.to_trExprS prodCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem prodTypeFresh07 : ({} : ConstMap).find? ``Prod = none := by + simp [SMap.find?] + +theorem prodTypeMapWF07 : prodTypeMap07.WF := + SMap.WF.empty.insert _ _ prodTypeFresh07 + +theorem prodCtorFresh07 : prodTypeMap07.find? ``Prod.mk = none := by + rw [prodTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem prodCtorMapWF07 : prodCtorMap07.WF := + prodTypeMapWF07.insert _ _ prodCtorFresh07 + +theorem prodRecFresh07 : prodCtorMap07.find? ``Prod.rec = none := by + rw [prodCtorMap07, prodTypeMapWF07.find?_insert, prodTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem prodAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty prodDecl + prodMap07 prodFinalEnv07 := by + refine ⟨{ + generation := prodGenerationChecked + generation_wf := prodGenerationWF07 + typeMap := prodTypeMap07 + typeEnv := prodTypeEnv07 + ctorMap := prodCtorMap07 + ctorEnv := prodCtorEnv07 + recEnv := prodRecEnv07 + addType := { + info := prodInfo07 + kind_eq := by simp [prodInfo07, InductConstantKind.Matches] + tr := prodInfoTr07 + map_fresh := prodTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := prodRecInfo07 + kind_eq := by simp [prodRecInfo07, InductConstantKind.Matches] + tr := prodRecInfoTr07 + map_fresh := prodRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := prodMkInfo07 + kind_eq := by simp [prodMkInfo07, InductConstantKind.Matches] + tr := prodCtorInfoTr07 + map_fresh := by simpa [prodType] using prodCtorFresh07 + env_add := rfl + map_add := rfl } .nil + +theorem prodAligned07 : Aligned .safe prodMap07 prodFinalEnv07 := + Aligned.addInduct prodAddInduct07 .empty + +def prodReplay07 : SingletonReplayArtifact where + label := ``Prod + source := prodDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := prodMap07 + outputEnv := prodFinalEnv07 + inputOrdered := .empty + transaction := prodAddInduct07 + aligned := prodAligned07 + +/-! ### And -/ + +theorem andCheckedWF07 : andChecked.WF VEnv.empty := by + constructor + · change VEnv.empty.OnTel 0 [] [.sort .zero, .sort .zero] + exact ⟨⟨.succ .zero, VEnv.HasType.sort trivial⟩, + ⟨⟨.succ .zero, VEnv.HasType.sort trivial⟩, trivial⟩⟩ + · intro ctor hctor + have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change VInductDecl.fieldsWF 0 ``And 2 VEnv.empty .zero [] + [.sort .zero, .sort .zero] 0 [.bvar 1, .bvar 1] + constructor + · exact .inr (.inr ⟨rfl, .zero, by type_tac, .inl rfl⟩) + constructor + · intro recursive + contradiction + constructor + · exact .inr (.inr ⟨rfl, .zero, by type_tac, .inl rfl⟩) + constructor + · intro recursive + contradiction + · trivial + · exact .nil + +theorem andGenerationWF07 : andGenerationChecked.WF VEnv.empty := by + exact andCheckedWF07.identityGeneration .empty + +def andTypeEnv07 : VEnv := + (VEnv.empty.addConst andType.name andType.toVConstant).get! + +def andCtorEnv07 : VEnv := + (andTypeEnv07.addConst andType.ctors[0].name + andType.ctors[0].toVConstant).get! + +def andRecEnv07 : VEnv := + (andCtorEnv07.addConst ``And.rec + (inductGenerationRecVal andGenerationChecked).toVConstant).get! + +def andFinalEnv07 : VEnv := + andGenerationChecked.generatedRules.foldl VEnv.addDefEq andRecEnv07 + +def andTypeMap07 : ConstMap := + ({} : ConstMap).insert ``And andInfo06 + +def andCtorMap07 : ConstMap := + andTypeMap07.insert ``And.intro andIntroInfo06 + +def andMap07 : ConstMap := + andCtorMap07.insert ``And.rec andRecInfo06 + +theorem andTypeEnv_ordered07 : andTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty andGenerationWF07 rfl + +theorem andCtorEnv_ordered07 : andCtorEnv07.Ordered := + replayCtorEnv_ordered07 andGenerationWF07 rfl + andTypeEnv_ordered07 rfl + +theorem andGenerationEnv07 : + VInductDecl.GenerationEnv andGenerationChecked andCtorEnv07 := + replayGenerationEnv07 andGenerationWF07 rfl rfl + andCtorEnv_ordered07 + +theorem andInfoTr07 : + TrConstVal .safe VEnv.empty andInfo06 andType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr VEnv.empty andInfo06.levelParams [] + andInfo06.type andType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 andGenerationWF07 + exact shape.to_trExprS .empty trivial ⟨.sort sort, familyType⟩ + +theorem andCtorInfoTr07 : + TrConstVal .safe andTypeEnv07 andIntroInfo06 andType.ctors[0] := by + have hAnd : andTypeEnv07.constants ``And = + some andType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr andTypeEnv07 andIntroInfo06.levelParams [] + andIntroInfo06.type andType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 andGenerationWF07 rfl + andType.ctors[0] (.head _) + exact shape.to_trExprS andTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem andRecInfoTr07 : + TrConstVal .safe andCtorEnv07 andRecInfo06 + (inductGenerationRecVal andGenerationChecked) := by + have hAnd : andCtorEnv07.constants ``And = + some andType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr andCtorEnv07 andRecInfo06.levelParams [] + andRecInfo06.type + (inductGenerationRecVal andGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := andGenerationEnv07.recursor_wf + exact shape.to_trExprS andCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem andTypeFresh07 : ({} : ConstMap).find? ``And = none := by + simp [SMap.find?] + +theorem andTypeMapWF07 : andTypeMap07.WF := + SMap.WF.empty.insert _ _ andTypeFresh07 + +theorem andCtorFresh07 : andTypeMap07.find? ``And.intro = none := by + rw [andTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem andCtorMapWF07 : andCtorMap07.WF := + andTypeMapWF07.insert _ _ andCtorFresh07 + +theorem andRecFresh07 : andCtorMap07.find? ``And.rec = none := by + rw [andCtorMap07, andTypeMapWF07.find?_insert, andTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem andAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty andDecl + andMap07 andFinalEnv07 := by + refine ⟨{ + generation := andGenerationChecked + generation_wf := andGenerationWF07 + typeMap := andTypeMap07 + typeEnv := andTypeEnv07 + ctorMap := andCtorMap07 + ctorEnv := andCtorEnv07 + recEnv := andRecEnv07 + addType := { + info := andInfo06 + kind_eq := by simp [andInfo06, InductConstantKind.Matches] + tr := andInfoTr07 + map_fresh := andTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := andRecInfo06 + kind_eq := by simp [andRecInfo06, InductConstantKind.Matches] + tr := andRecInfoTr07 + map_fresh := andRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := andIntroInfo06 + kind_eq := by simp [andIntroInfo06, InductConstantKind.Matches] + tr := andCtorInfoTr07 + map_fresh := by simpa [andType] using andCtorFresh07 + env_add := rfl + map_add := rfl } .nil + +theorem andAligned07 : Aligned .safe andMap07 andFinalEnv07 := + Aligned.addInduct andAddInduct07 .empty + +def andReplay07 : SingletonReplayArtifact where + label := ``And + source := andDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := andMap07 + outputEnv := andFinalEnv07 + inputOrdered := .empty + transaction := andAddInduct07 + aligned := andAligned07 + +/-! ### Or -/ + +theorem orCheckedWF07 : orChecked.WF VEnv.empty := by + constructor + · change VEnv.empty.OnTel 0 [] [.sort .zero, .sort .zero] + exact ⟨⟨.succ .zero, VEnv.HasType.sort trivial⟩, + ⟨⟨.succ .zero, VEnv.HasType.sort trivial⟩, trivial⟩⟩ + · intro ctor hctor + rcases List.mem_cons.1 hctor with rfl | hctor + · constructor + · change VInductDecl.fieldsWF 0 ``Or 2 VEnv.empty .zero [] + [.sort .zero, .sort .zero] 0 [.bvar 1] + constructor + · exact .inr (.inr ⟨rfl, .zero, by type_tac, .inl rfl⟩) + constructor + · intro recursive + contradiction + · trivial + · exact .nil + · have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change VInductDecl.fieldsWF 0 ``Or 2 VEnv.empty .zero [] + [.sort .zero, .sort .zero] 0 [.bvar 0] + constructor + · exact .inr (.inr ⟨rfl, .zero, by type_tac, .inl rfl⟩) + constructor + · intro recursive + contradiction + · trivial + · exact .nil + +theorem orGenerationWF07 : orGenerationChecked.WF VEnv.empty := by + exact orCheckedWF07.identityGeneration .empty + +def orTypeEnv07 : VEnv := + (VEnv.empty.addConst orType.name orType.toVConstant).get! + +def orInlEnv07 : VEnv := + (orTypeEnv07.addConst orType.ctors[0].name + orType.ctors[0].toVConstant).get! + +def orCtorEnv07 : VEnv := + (orInlEnv07.addConst orType.ctors[1].name + orType.ctors[1].toVConstant).get! + +def orRecEnv07 : VEnv := + (orCtorEnv07.addConst ``Or.rec + (inductGenerationRecVal orGenerationChecked).toVConstant).get! + +def orFinalEnv07 : VEnv := + orGenerationChecked.generatedRules.foldl VEnv.addDefEq orRecEnv07 + +def orTypeMap07 : ConstMap := + ({} : ConstMap).insert ``Or orInfo06 + +def orInlMap07 : ConstMap := + orTypeMap07.insert ``Or.inl orInlInfo06 + +def orCtorMap07 : ConstMap := + orInlMap07.insert ``Or.inr orInrInfo06 + +def orMap07 : ConstMap := + orCtorMap07.insert ``Or.rec orRecInfo06 + +theorem orTypeEnv_ordered07 : orTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty orGenerationWF07 rfl + +theorem orInlEnv_ordered07 : orInlEnv07.Ordered := by + refine .const (n := orType.ctors[0].name) + (ci := orType.ctors[0].toVConstant) orTypeEnv_ordered07 ?_ rfl + exact replayRawCtorWF07 orGenerationWF07 rfl orType.ctors[0] + (.head _) + +theorem orCtorEnv_ordered07 : orCtorEnv07.Ordered := + replayCtorEnv_ordered07 orGenerationWF07 rfl + orTypeEnv_ordered07 rfl + +theorem orGenerationEnv07 : + VInductDecl.GenerationEnv orGenerationChecked orCtorEnv07 := + replayGenerationEnv07 orGenerationWF07 rfl rfl + orCtorEnv_ordered07 + +theorem orInfoTr07 : + TrConstVal .safe VEnv.empty orInfo06 orType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr VEnv.empty orInfo06.levelParams [] + orInfo06.type orType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 orGenerationWF07 + exact shape.to_trExprS .empty trivial ⟨.sort sort, familyType⟩ + +theorem orInlInfoTr07 : + TrConstVal .safe orTypeEnv07 orInlInfo06 orType.ctors[0] := by + have hOr : orTypeEnv07.constants ``Or = some orType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr orTypeEnv07 orInlInfo06.levelParams [] + orInlInfo06.type orType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 orGenerationWF07 rfl + orType.ctors[0] (.head _) + exact shape.to_trExprS orTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem orInrInfoTr07 : + TrConstVal .safe orInlEnv07 orInrInfo06 orType.ctors[1] := by + have hOr : orInlEnv07.constants ``Or = some orType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr orInlEnv07 orInrInfo06.levelParams [] + orInrInfo06.type orType.ctors[1].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 orGenerationWF07 rfl + orType.ctors[1] (.tail _ (.head _)) + have typeToInl : orTypeEnv07 ≤ orInlEnv07 := + VEnv.addConst_le (show orTypeEnv07.addConst orType.ctors[0].name + orType.ctors[0].toVConstant = some orInlEnv07 from rfl) + exact shape.to_trExprS orInlEnv_ordered07 trivial + ⟨.sort sort, ctorType.mono typeToInl⟩ + +theorem orRecInfoTr07 : + TrConstVal .safe orCtorEnv07 orRecInfo06 + (inductGenerationRecVal orGenerationChecked) := by + have hOr : orCtorEnv07.constants ``Or = some orType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr orCtorEnv07 orRecInfo06.levelParams [] + orRecInfo06.type + (inductGenerationRecVal orGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := orGenerationEnv07.recursor_wf + exact shape.to_trExprS orCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem orTypeFresh07 : ({} : ConstMap).find? ``Or = none := by + simp [SMap.find?] + +theorem orTypeMapWF07 : orTypeMap07.WF := + SMap.WF.empty.insert _ _ orTypeFresh07 + +theorem orInlFresh07 : orTypeMap07.find? ``Or.inl = none := by + rw [orTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem orInlMapWF07 : orInlMap07.WF := + orTypeMapWF07.insert _ _ orInlFresh07 + +theorem orInrFresh07 : orInlMap07.find? ``Or.inr = none := by + rw [orInlMap07, orTypeMapWF07.find?_insert, orTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem orCtorMapWF07 : orCtorMap07.WF := + orInlMapWF07.insert _ _ orInrFresh07 + +theorem orRecFresh07 : orCtorMap07.find? ``Or.rec = none := by + rw [orCtorMap07, orInlMapWF07.find?_insert, orInlMap07, + orTypeMapWF07.find?_insert, orTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem orAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty orDecl + orMap07 orFinalEnv07 := by + refine ⟨{ + generation := orGenerationChecked + generation_wf := orGenerationWF07 + typeMap := orTypeMap07 + typeEnv := orTypeEnv07 + ctorMap := orCtorMap07 + ctorEnv := orCtorEnv07 + recEnv := orRecEnv07 + addType := { + info := orInfo06 + kind_eq := by simp [orInfo06, InductConstantKind.Matches] + tr := orInfoTr07 + map_fresh := orTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := orRecInfo06 + kind_eq := by simp [orRecInfo06, InductConstantKind.Matches] + tr := orRecInfoTr07 + map_fresh := orRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := orInlInfo06 + kind_eq := by simp [orInlInfo06, InductConstantKind.Matches] + tr := orInlInfoTr07 + map_fresh := by simpa [orType] using orInlFresh07 + env_add := rfl + map_add := rfl } + (.cons { + info := orInrInfo06 + kind_eq := by simp [orInrInfo06, InductConstantKind.Matches] + tr := orInrInfoTr07 + map_fresh := by + change orInlMap07.find? ``Or.inr = none + exact orInrFresh07 + env_add := rfl + map_add := rfl } .nil) + +theorem orAligned07 : Aligned .safe orMap07 orFinalEnv07 := + Aligned.addInduct orAddInduct07 .empty + +def orReplay07 : SingletonReplayArtifact where + label := ``Or + source := orDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := orMap07 + outputEnv := orFinalEnv07 + inputOrdered := .empty + transaction := orAddInduct07 + aligned := orAligned07 + +/-! ### HEq -/ + +theorem heqCheckedWF07 : heqChecked.WF VEnv.empty := by + constructor + · change VEnv.empty.OnTel 1 [] + [.sort (.param 0), .bvar 0, .sort (.param 0), .bvar 0] + exact ⟨⟨.succ (.param 0), VEnv.HasType.sort (by decide)⟩, + ⟨⟨.param 0, by type_tac⟩, + ⟨⟨.succ (.param 0), VEnv.HasType.sort (by decide)⟩, + ⟨⟨.param 0, by type_tac⟩, trivial⟩⟩⟩⟩ + · intro ctor hctor + have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change True + trivial + · change VEnv.empty.SpineWF 1 [.bvar 0, .sort (.param 0)] + (.forallE (.sort (.param 0)) + (.forallE (.bvar 0) (.sort .zero))) + [.bvar 1, .bvar 0] (.sort .zero) + exact .cons (by type_tac) <| .cons (by type_tac) .nil + +theorem heqGenerationWF07 : heqGenerationChecked.WF VEnv.empty := by + exact heqCheckedWF07.identityGeneration .empty + +def heqTypeEnv07 : VEnv := + (VEnv.empty.addConst heqType.name heqType.toVConstant).get! + +def heqCtorEnv07 : VEnv := + (heqTypeEnv07.addConst heqType.ctors[0].name + heqType.ctors[0].toVConstant).get! + +def heqRecEnv07 : VEnv := + (heqCtorEnv07.addConst ``HEq.rec + (inductGenerationRecVal heqGenerationChecked).toVConstant).get! + +def heqFinalEnv07 : VEnv := + heqGenerationChecked.generatedRules.foldl VEnv.addDefEq heqRecEnv07 + +def heqTypeMap07 : ConstMap := + ({} : ConstMap).insert ``HEq heqInfo07 + +def heqCtorMap07 : ConstMap := + heqTypeMap07.insert ``HEq.refl heqReflInfo07 + +def heqMap07 : ConstMap := + heqCtorMap07.insert ``HEq.rec heqRecInfo07 + +theorem heqTypeEnv_ordered07 : heqTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty heqGenerationWF07 rfl + +theorem heqCtorEnv_ordered07 : heqCtorEnv07.Ordered := + replayCtorEnv_ordered07 heqGenerationWF07 rfl + heqTypeEnv_ordered07 rfl + +theorem heqGenerationEnv07 : + VInductDecl.GenerationEnv heqGenerationChecked heqCtorEnv07 := + replayGenerationEnv07 heqGenerationWF07 rfl rfl + heqCtorEnv_ordered07 + +theorem heqInfoTr07 : + TrConstVal .safe VEnv.empty heqInfo07 heqType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr VEnv.empty heqInfo07.levelParams [] + heqInfo07.type heqType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 heqGenerationWF07 + exact shape.to_trExprS .empty trivial ⟨.sort sort, familyType⟩ + +theorem heqCtorInfoTr07 : + TrConstVal .safe heqTypeEnv07 heqReflInfo07 heqType.ctors[0] := by + have hHEq : heqTypeEnv07.constants ``HEq = + some heqType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr heqTypeEnv07 heqReflInfo07.levelParams [] + heqReflInfo07.type heqType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 heqGenerationWF07 rfl + heqType.ctors[0] (.head _) + exact shape.to_trExprS heqTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem heqRecInfoTr07 : + TrConstVal .safe heqCtorEnv07 heqRecInfo07 + (inductGenerationRecVal heqGenerationChecked) := by + have hHEq : heqCtorEnv07.constants ``HEq = + some heqType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr heqCtorEnv07 heqRecInfo07.levelParams [] + heqRecInfo07.type + (inductGenerationRecVal heqGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := heqGenerationEnv07.recursor_wf + exact shape.to_trExprS heqCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem heqTypeFresh07 : ({} : ConstMap).find? ``HEq = none := by + simp [SMap.find?] + +theorem heqTypeMapWF07 : heqTypeMap07.WF := + SMap.WF.empty.insert _ _ heqTypeFresh07 + +theorem heqCtorFresh07 : heqTypeMap07.find? ``HEq.refl = none := by + rw [heqTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem heqCtorMapWF07 : heqCtorMap07.WF := + heqTypeMapWF07.insert _ _ heqCtorFresh07 + +theorem heqRecFresh07 : heqCtorMap07.find? ``HEq.rec = none := by + rw [heqCtorMap07, heqTypeMapWF07.find?_insert, heqTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem heqAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty heqDecl + heqMap07 heqFinalEnv07 := by + refine ⟨{ + generation := heqGenerationChecked + generation_wf := heqGenerationWF07 + typeMap := heqTypeMap07 + typeEnv := heqTypeEnv07 + ctorMap := heqCtorMap07 + ctorEnv := heqCtorEnv07 + recEnv := heqRecEnv07 + addType := { + info := heqInfo07 + kind_eq := by simp [heqInfo07, InductConstantKind.Matches] + tr := heqInfoTr07 + map_fresh := heqTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := heqRecInfo07 + kind_eq := by simp [heqRecInfo07, InductConstantKind.Matches] + tr := heqRecInfoTr07 + map_fresh := heqRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := heqReflInfo07 + kind_eq := by simp [heqReflInfo07, InductConstantKind.Matches] + tr := heqCtorInfoTr07 + map_fresh := by simpa [heqType] using heqCtorFresh07 + env_add := rfl + map_add := rfl } .nil + +theorem heqAligned07 : Aligned .safe heqMap07 heqFinalEnv07 := + Aligned.addInduct heqAddInduct07 .empty + +def heqReplay07 : SingletonReplayArtifact where + label := ``HEq + source := heqDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := heqMap07 + outputEnv := heqFinalEnv07 + inputOrdered := .empty + transaction := heqAddInduct07 + aligned := heqAligned07 + +/-! ### Fin dependency environment -/ + +def finLTInfo07 : ConstantInfo := kernelInductInfo% LT +def finLTMkInfo07 : ConstantInfo := kernelCtorInfo% LT.mk +def finLTLtInfo07 : ConstantInfo := .defnInfo (kernelDefVal% LT.lt) +def finInstLTNatInfo07 : ConstantInfo := + .defnInfo (kernelDefVal% instLTNat) + +def finLTConst07 : VConstVal := ⟨vconst(type_of% @LT), ``LT⟩ +def finLTMkConst07 : VConstVal := ⟨vconst(type_of% @LT.mk), ``LT.mk⟩ +def finLTLtConst07 : VConstVal := ⟨vconst(type_of% @LT.lt), ``LT.lt⟩ +def finInstLTNatConst07 : VConstVal := + ⟨vconst(type_of% @instLTNat), ``instLTNat⟩ + +def finLTMap07 : ConstMap := natTypeMap.insert ``LT finLTInfo07 +def finLTMkMap07 : ConstMap := finLTMap07.insert ``LT.mk finLTMkInfo07 +def finLTLtMap07 : ConstMap := finLTMkMap07.insert ``LT.lt finLTLtInfo07 +def finInputMap07 : ConstMap := + finLTLtMap07.insert ``instLTNat finInstLTNatInfo07 + +def finLTEnv07 : VEnv := + (natTypeEnv.addConst ``LT finLTConst07.toVConstant).get! + +def finLTMkEnv07 : VEnv := + (finLTEnv07.addConst ``LT.mk finLTMkConst07.toVConstant).get! + +def finLTLtEnv07 : VEnv := + (finLTMkEnv07.addConst ``LT.lt finLTLtConst07.toVConstant).get! + +def finInputEnv07 : VEnv := + (finLTLtEnv07.addConst ``instLTNat + finInstLTNatConst07.toVConstant).get! + +theorem natTypeAligned07 : Aligned .safe natTypeMap natTypeEnv := by + exact Aligned.const .empty natType_fresh natInfo_tr.1 rfl natInfo_tr.2 + +theorem finLTConstWF07 : finLTConst07.toVConstant.WF natTypeEnv := by + change natTypeEnv.IsType finLTConst07.uvars [] finLTConst07.type + dsimp [finLTConst07] + refine ⟨.imax (.succ (.succ (.param 0))) + (.succ (.succ (.param 0))), ?_⟩ + refine VEnv.HasType.forallE + (u := .succ (.succ (.param 0))) + (v := .succ (.succ (.param 0))) ?_ ?_ + · exact VEnv.HasType.sort (by decide) + · exact VEnv.HasType.sort (by decide) + +theorem finLTInfoTr07 : + TrConstVal .safe natTypeEnv finLTInfo07 finLTConst07 := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr natTypeEnv finLTInfo07.levelParams [] + finLTInfo07.type finLTConst07.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := finLTConstWF07 + exact shape.to_trExprS natTypeEnv_ordered trivial + ⟨.sort sort, familyType⟩ + +theorem finLTFresh07 : natTypeMap.find? ``LT = none := by + rw [natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem finLTMapWF07 : finLTMap07.WF := + natTypeMap_wf.insert _ _ finLTFresh07 + +theorem finLTEnv_ordered07 : finLTEnv07.Ordered := + .const (n := ``LT) (ci := finLTConst07.toVConstant) + natTypeEnv_ordered finLTConstWF07 rfl + +theorem finLTAligned07 : Aligned .safe finLTMap07 finLTEnv07 := + Aligned.const natTypeAligned07 finLTFresh07 finLTInfoTr07.1 rfl + finLTInfoTr07.2 + +theorem finLTMkConstWF07 : finLTMkConst07.toVConstant.WF finLTEnv07 := by + have hLT : finLTEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + change finLTEnv07.IsType finLTMkConst07.uvars [] finLTMkConst07.type + dsimp [finLTMkConst07] + refine ⟨.imax (.succ (.succ (.param 0))) + (.imax + (.imax (.succ (.param 0)) + (.imax (.succ (.param 0)) (.succ .zero))) + (.succ (.param 0))), ?_⟩ + refine VEnv.HasType.forallE + (u := .succ (.succ (.param 0))) + (v := .imax + (.imax (.succ (.param 0)) + (.imax (.succ (.param 0)) (.succ .zero))) + (.succ (.param 0))) ?_ ?_ + · exact VEnv.HasType.sort (by decide) + · refine VEnv.HasType.forallE + (u := .imax (.succ (.param 0)) + (.imax (.succ (.param 0)) (.succ .zero))) + (v := .succ (.param 0)) ?_ ?_ + · refine VEnv.HasType.forallE + (u := .succ (.param 0)) + (v := .imax (.succ (.param 0)) (.succ .zero)) ?_ ?_ + · type_tac + · refine VEnv.HasType.forallE + (u := .succ (.param 0)) (v := .succ .zero) ?_ ?_ + · type_tac + · exact VEnv.HasType.sort (by decide) + · type_tac + +theorem finLTMkInfoTr07 : + TrConstVal .safe finLTEnv07 finLTMkInfo07 finLTMkConst07 := by + have hLT : finLTEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr finLTEnv07 finLTMkInfo07.levelParams [] + finLTMkInfo07.type finLTMkConst07.type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := finLTMkConstWF07 + exact shape.to_trExprS finLTEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem finLTMkFresh07 : finLTMap07.find? ``LT.mk = none := by + rw [finLTMap07, natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem finLTMkMapWF07 : finLTMkMap07.WF := + finLTMapWF07.insert _ _ finLTMkFresh07 + +theorem finLTMkEnv_ordered07 : finLTMkEnv07.Ordered := + .const (n := ``LT.mk) (ci := finLTMkConst07.toVConstant) + finLTEnv_ordered07 finLTMkConstWF07 rfl + +theorem finLTMkAligned07 : Aligned .safe finLTMkMap07 finLTMkEnv07 := + Aligned.const finLTAligned07 finLTMkFresh07 finLTMkInfoTr07.1 rfl + finLTMkInfoTr07.2 + +theorem finLTLtConstWF07 : finLTLtConst07.toVConstant.WF finLTMkEnv07 := by + have hLT : finLTMkEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + change finLTMkEnv07.IsType finLTLtConst07.uvars [] finLTLtConst07.type + dsimp [finLTLtConst07] + refine ⟨.imax (.succ (.succ (.param 0))) + (.imax (.succ (.param 0)) + (.imax (.succ (.param 0)) + (.imax (.succ (.param 0)) (.succ .zero)))), ?_⟩ + refine VEnv.HasType.forallE + (u := .succ (.succ (.param 0))) + (v := .imax (.succ (.param 0)) + (.imax (.succ (.param 0)) + (.imax (.succ (.param 0)) (.succ .zero)))) ?_ ?_ + · exact VEnv.HasType.sort (by decide) + · refine VEnv.HasType.forallE + (u := .succ (.param 0)) + (v := .imax (.succ (.param 0)) + (.imax (.succ (.param 0)) (.succ .zero))) ?_ ?_ + · type_tac + · refine VEnv.HasType.forallE + (u := .succ (.param 0)) + (v := .imax (.succ (.param 0)) (.succ .zero)) ?_ ?_ + · type_tac + · refine VEnv.HasType.forallE + (u := .succ (.param 0)) (v := .succ .zero) ?_ ?_ + · type_tac + · exact VEnv.HasType.sort (by decide) + +theorem finLTLtInfoTr07 : + TrConstVal .safe finLTMkEnv07 finLTLtInfo07 finLTLtConst07 := by + have hLT : finLTMkEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr finLTMkEnv07 finLTLtInfo07.levelParams [] + finLTLtInfo07.type finLTLtConst07.type := by + tr_type_expr_tac + obtain ⟨sort, projectionType⟩ := finLTLtConstWF07 + exact shape.to_trExprS finLTMkEnv_ordered07 trivial + ⟨.sort sort, projectionType⟩ + +theorem finLTLtFresh07 : finLTMkMap07.find? ``LT.lt = none := by + rw [finLTMkMap07, finLTMapWF07.find?_insert, finLTMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem finLTLtMapWF07 : finLTLtMap07.WF := + finLTMkMapWF07.insert _ _ finLTLtFresh07 + +theorem finLTLtEnv_ordered07 : finLTLtEnv07.Ordered := + .const (n := ``LT.lt) (ci := finLTLtConst07.toVConstant) + finLTMkEnv_ordered07 finLTLtConstWF07 rfl + +theorem finLTLtAligned07 : Aligned .safe finLTLtMap07 finLTLtEnv07 := + Aligned.const finLTMkAligned07 finLTLtFresh07 finLTLtInfoTr07.1 rfl + finLTLtInfoTr07.2 + +theorem finInstLTNatConstWF07 : + finInstLTNatConst07.toVConstant.WF finLTLtEnv07 := by + have hNat : finLTLtEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hLT : finLTLtEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + change finLTLtEnv07.IsType finInstLTNatConst07.uvars [] + finInstLTNatConst07.type + dsimp [finInstLTNatConst07] + refine ⟨.succ .zero, ?_⟩ + type_tac + +theorem finInstLTNatInfoTr07 : + TrConstVal .safe finLTLtEnv07 finInstLTNatInfo07 + finInstLTNatConst07 := by + have hNat : finLTLtEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hLT : finLTLtEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr finLTLtEnv07 finInstLTNatInfo07.levelParams [] + finInstLTNatInfo07.type finInstLTNatConst07.type := by + tr_type_expr_tac + obtain ⟨sort, instanceType⟩ := finInstLTNatConstWF07 + exact shape.to_trExprS finLTLtEnv_ordered07 trivial + ⟨.sort sort, instanceType⟩ + +theorem finInstLTNatFresh07 : + finLTLtMap07.find? ``instLTNat = none := by + rw [finLTLtMap07, finLTMkMapWF07.find?_insert, finLTMkMap07, + finLTMapWF07.find?_insert, finLTMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem finInputMapWF07 : finInputMap07.WF := + finLTLtMapWF07.insert _ _ finInstLTNatFresh07 + +theorem finInputEnv_ordered07 : finInputEnv07.Ordered := + .const (n := ``instLTNat) (ci := finInstLTNatConst07.toVConstant) + finLTLtEnv_ordered07 finInstLTNatConstWF07 rfl + +theorem finInputAligned07 : Aligned .safe finInputMap07 finInputEnv07 := + Aligned.const finLTLtAligned07 finInstLTNatFresh07 + finInstLTNatInfoTr07.1 rfl finInstLTNatInfoTr07.2 + +example : finInputMap07 = finDependencyMap07 := rfl + +/-! ### Fin -/ + +theorem finCheckedWF07 : finChecked.WF finInputEnv07 := by + constructor + · change finInputEnv07.OnTel 0 [] [.const ``Nat []] + have hNat : finInputEnv07.constants ``Nat = + some natType.toVConstant := rfl + exact ⟨⟨.succ .zero, by type_tac⟩, trivial⟩ + · intro ctor hctor + have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change VInductDecl.fieldsWF 0 ``Fin 1 finInputEnv07 + (.succ .zero) [] [.const ``Nat []] 0 + [.const ``Nat [], + .app + (.app + (.app + (.app (.const ``LT.lt [.zero]) (.const ``Nat [])) + (.const ``instLTNat [])) + (.bvar 0)) + (.bvar 1)] + have hNat : finInputEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hLT : finInputEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + have hLTLt : finInputEnv07.constants ``LT.lt = + some finLTLtConst07.toVConstant := rfl + have hInst : finInputEnv07.constants ``instLTNat = + some finInstLTNatConst07.toVConstant := rfl + constructor + · exact .inr (.inr ⟨rfl, .succ .zero, by type_tac, + .inr (VLevel.le_refl _)⟩) + constructor + · intro recursive + contradiction + constructor + · exact .inr (.inr ⟨rfl, .zero, by type_tac, + .inr VLevel.zero_le⟩) + constructor + · intro recursive + contradiction + · trivial + · exact .nil + +theorem finGenerationWF07 : finGenerationChecked.WF finInputEnv07 := by + exact finCheckedWF07.identityGeneration finInputEnv_ordered07 + +def finTypeEnv07 : VEnv := + (finInputEnv07.addConst finType.name finType.toVConstant).get! + +def finCtorEnv07 : VEnv := + (finTypeEnv07.addConst finType.ctors[0].name + finType.ctors[0].toVConstant).get! + +def finRecEnv07 : VEnv := + (finCtorEnv07.addConst ``Fin.rec + (inductGenerationRecVal finGenerationChecked).toVConstant).get! + +def finFinalEnv07 : VEnv := + finGenerationChecked.generatedRules.foldl VEnv.addDefEq finRecEnv07 + +def finTypeMap07 : ConstMap := finInputMap07.insert ``Fin finInfo07 +def finCtorMap07 : ConstMap := finTypeMap07.insert ``Fin.mk finMkInfo07 +def finMap07 : ConstMap := finCtorMap07.insert ``Fin.rec finRecInfo07 + +theorem finTypeEnv_ordered07 : finTypeEnv07.Ordered := + replayTypeEnv_ordered07 finInputEnv_ordered07 finGenerationWF07 rfl + +theorem finCtorEnv_ordered07 : finCtorEnv07.Ordered := + replayCtorEnv_ordered07 finGenerationWF07 rfl finTypeEnv_ordered07 rfl + +theorem finGenerationEnv07 : + VInductDecl.GenerationEnv finGenerationChecked finCtorEnv07 := + replayGenerationEnv07 finGenerationWF07 rfl rfl finCtorEnv_ordered07 + +theorem finInfoTr07 : + TrConstVal .safe finInputEnv07 finInfo07 finType.toVConstVal := by + have hNat : finInputEnv07.constants ``Nat = + some natType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr finInputEnv07 finInfo07.levelParams [] + finInfo07.type finType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 finGenerationWF07 + exact shape.to_trExprS finInputEnv_ordered07 trivial + ⟨.sort sort, familyType⟩ + +theorem finCtorInfoTr07 : + TrConstVal .safe finTypeEnv07 finMkInfo07 finType.ctors[0] := by + have hNat : finTypeEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hLT : finTypeEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + have hLTLt : finTypeEnv07.constants ``LT.lt = + some finLTLtConst07.toVConstant := rfl + have hInst : finTypeEnv07.constants ``instLTNat = + some finInstLTNatConst07.toVConstant := rfl + have hFin : finTypeEnv07.constants ``Fin = + some finType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr finTypeEnv07 finMkInfo07.levelParams [] + finMkInfo07.type finType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 finGenerationWF07 rfl + finType.ctors[0] (.head _) + exact shape.to_trExprS finTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem finRecInfoTr07 : + TrConstVal .safe finCtorEnv07 finRecInfo07 + (inductGenerationRecVal finGenerationChecked) := by + have hNat : finCtorEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hLT : finCtorEnv07.constants ``LT = + some finLTConst07.toVConstant := rfl + have hLTLt : finCtorEnv07.constants ``LT.lt = + some finLTLtConst07.toVConstant := rfl + have hInst : finCtorEnv07.constants ``instLTNat = + some finInstLTNatConst07.toVConstant := rfl + have hFin : finCtorEnv07.constants ``Fin = + some finType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr finCtorEnv07 finRecInfo07.levelParams [] + finRecInfo07.type + (inductGenerationRecVal finGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := finGenerationEnv07.recursor_wf + exact shape.to_trExprS finCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem finTypeFresh07 : finInputMap07.find? ``Fin = none := by + rw [finInputMap07, finLTLtMapWF07.find?_insert, finLTLtMap07, + finLTMkMapWF07.find?_insert, finLTMkMap07, + finLTMapWF07.find?_insert, finLTMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem finTypeMapWF07 : finTypeMap07.WF := + finInputMapWF07.insert _ _ finTypeFresh07 + +theorem finCtorFresh07 : finTypeMap07.find? ``Fin.mk = none := by + rw [finTypeMap07, finInputMapWF07.find?_insert, finInputMap07, + finLTLtMapWF07.find?_insert, finLTLtMap07, + finLTMkMapWF07.find?_insert, finLTMkMap07, + finLTMapWF07.find?_insert, finLTMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem finCtorMapWF07 : finCtorMap07.WF := + finTypeMapWF07.insert _ _ finCtorFresh07 + +theorem finRecFresh07 : finCtorMap07.find? ``Fin.rec = none := by + rw [finCtorMap07, finTypeMapWF07.find?_insert, finTypeMap07, + finInputMapWF07.find?_insert, finInputMap07, + finLTLtMapWF07.find?_insert, finLTLtMap07, + finLTMkMapWF07.find?_insert, finLTMkMap07, + finLTMapWF07.find?_insert, finLTMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem finAddInduct07 : AddInduct finInputMap07 finInputEnv07 finDecl + finMap07 finFinalEnv07 := by + refine ⟨{ + generation := finGenerationChecked + generation_wf := finGenerationWF07 + typeMap := finTypeMap07 + typeEnv := finTypeEnv07 + ctorMap := finCtorMap07 + ctorEnv := finCtorEnv07 + recEnv := finRecEnv07 + addType := { + info := finInfo07 + kind_eq := by simp [finInfo07, InductConstantKind.Matches] + tr := finInfoTr07 + map_fresh := finTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := finRecInfo07 + kind_eq := by simp [finRecInfo07, InductConstantKind.Matches] + tr := finRecInfoTr07 + map_fresh := finRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := finMkInfo07 + kind_eq := by simp [finMkInfo07, InductConstantKind.Matches] + tr := finCtorInfoTr07 + map_fresh := by simpa [finType] using finCtorFresh07 + env_add := rfl + map_add := rfl } .nil + +theorem finAligned07 : Aligned .safe finMap07 finFinalEnv07 := + Aligned.addInduct finAddInduct07 finInputAligned07 + +def finReplay07 : SingletonReplayArtifact where + label := ``Fin + source := finDecl + inputMap := finInputMap07 + inputEnv := finInputEnv07 + inputMapWF := finInputMapWF07 + outputMap := finMap07 + outputEnv := finFinalEnv07 + inputOrdered := finInputEnv_ordered07 + transaction := finAddInduct07 + aligned := finAligned07 + +/-! ### Vector dependency environment -/ + +def vectorArrayInfo07 : ConstantInfo := kernelInductInfo% Array +def vectorArraySizeInfo07 : ConstantInfo := + .defnInfo (kernelDefVal% Array.size) + +def vectorArrayConst07 : VConstVal := + ⟨vconst(type_of% @Array), ``Array⟩ + +def vectorArraySizeConst07 : VConstVal := + ⟨vconst(type_of% @Array.size), ``Array.size⟩ + +def vectorEqMap07 : ConstMap := natTypeMap.insert ``Eq eqInfo +def vectorArrayMap07 : ConstMap := + vectorEqMap07.insert ``Array vectorArrayInfo07 +def vectorInputMap07 : ConstMap := + vectorArrayMap07.insert ``Array.size vectorArraySizeInfo07 + +def vectorEqEnv07 : VEnv := + (natTypeEnv.addConst ``Eq eqType.toVConstant).get! + +def vectorArrayEnv07 : VEnv := + (vectorEqEnv07.addConst ``Array vectorArrayConst07.toVConstant).get! + +def vectorInputEnv07 : VEnv := + (vectorArrayEnv07.addConst ``Array.size + vectorArraySizeConst07.toVConstant).get! + +theorem empty_le_natTypeEnv07 : VEnv.empty ≤ natTypeEnv := + VEnv.addConst_le (show VEnv.empty.addConst natType.name + natType.toVConstant = some natTypeEnv from rfl) + +theorem vectorEqTypeWF07 : eqType.toVConstant.WF natTypeEnv := + eqType_wf.mono empty_le_natTypeEnv07 + +theorem vectorEqInfoTr07 : + TrConstVal .safe natTypeEnv eqInfo eqType.toVConstVal := + eqInfo_tr.mono empty_le_natTypeEnv07 + +theorem vectorEqFresh07 : natTypeMap.find? ``Eq = none := by + rw [natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem vectorEqMapWF07 : vectorEqMap07.WF := + natTypeMap_wf.insert _ _ vectorEqFresh07 + +theorem vectorEqEnv_ordered07 : vectorEqEnv07.Ordered := + .const (n := ``Eq) (ci := eqType.toVConstant) + natTypeEnv_ordered vectorEqTypeWF07 rfl + +theorem vectorEqAligned07 : Aligned .safe vectorEqMap07 vectorEqEnv07 := + Aligned.const natTypeAligned07 vectorEqFresh07 vectorEqInfoTr07.1 rfl + vectorEqInfoTr07.2 + +theorem vectorArrayConstWF07 : + vectorArrayConst07.toVConstant.WF vectorEqEnv07 := by + change vectorEqEnv07.IsType vectorArrayConst07.uvars [] + vectorArrayConst07.type + dsimp [vectorArrayConst07] + refine ⟨.imax (.succ (.succ (.param 0))) + (.succ (.succ (.param 0))), ?_⟩ + refine VEnv.HasType.forallE + (u := .succ (.succ (.param 0))) + (v := .succ (.succ (.param 0))) ?_ ?_ + · exact VEnv.HasType.sort (by decide) + · exact VEnv.HasType.sort (by decide) + +theorem vectorArrayInfoTr07 : + TrConstVal .safe vectorEqEnv07 vectorArrayInfo07 + vectorArrayConst07 := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr vectorEqEnv07 vectorArrayInfo07.levelParams [] + vectorArrayInfo07.type vectorArrayConst07.type := by + tr_type_expr_tac + obtain ⟨sort, arrayType⟩ := vectorArrayConstWF07 + exact shape.to_trExprS vectorEqEnv_ordered07 trivial + ⟨.sort sort, arrayType⟩ + +theorem vectorArrayFresh07 : vectorEqMap07.find? ``Array = none := by + rw [vectorEqMap07, natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem vectorArrayMapWF07 : vectorArrayMap07.WF := + vectorEqMapWF07.insert _ _ vectorArrayFresh07 + +theorem vectorArrayEnv_ordered07 : vectorArrayEnv07.Ordered := + .const (n := ``Array) (ci := vectorArrayConst07.toVConstant) + vectorEqEnv_ordered07 vectorArrayConstWF07 rfl + +theorem vectorArrayAligned07 : + Aligned .safe vectorArrayMap07 vectorArrayEnv07 := + Aligned.const vectorEqAligned07 vectorArrayFresh07 + vectorArrayInfoTr07.1 rfl vectorArrayInfoTr07.2 + +theorem vectorArraySizeConstWF07 : + vectorArraySizeConst07.toVConstant.WF vectorArrayEnv07 := by + have hNat : vectorArrayEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hArray : vectorArrayEnv07.constants ``Array = + some vectorArrayConst07.toVConstant := rfl + change vectorArrayEnv07.IsType vectorArraySizeConst07.uvars [] + vectorArraySizeConst07.type + dsimp [vectorArraySizeConst07] + refine ⟨.imax (.succ (.succ (.param 0))) + (.imax (.succ (.param 0)) (.succ .zero)), ?_⟩ + refine VEnv.HasType.forallE + (u := .succ (.succ (.param 0))) + (v := .imax (.succ (.param 0)) (.succ .zero)) ?_ ?_ + · exact VEnv.HasType.sort (by decide) + · refine VEnv.HasType.forallE + (u := .succ (.param 0)) (v := .succ .zero) ?_ ?_ + · type_tac + · type_tac + +theorem vectorArraySizeInfoTr07 : + TrConstVal .safe vectorArrayEnv07 vectorArraySizeInfo07 + vectorArraySizeConst07 := by + have hNat : vectorArrayEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hArray : vectorArrayEnv07.constants ``Array = + some vectorArrayConst07.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr vectorArrayEnv07 + vectorArraySizeInfo07.levelParams [] vectorArraySizeInfo07.type + vectorArraySizeConst07.type := by + tr_type_expr_tac + obtain ⟨sort, sizeType⟩ := vectorArraySizeConstWF07 + exact shape.to_trExprS vectorArrayEnv_ordered07 trivial + ⟨.sort sort, sizeType⟩ + +theorem vectorArraySizeFresh07 : + vectorArrayMap07.find? ``Array.size = none := by + rw [vectorArrayMap07, vectorEqMapWF07.find?_insert, vectorEqMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem vectorInputMapWF07 : vectorInputMap07.WF := + vectorArrayMapWF07.insert _ _ vectorArraySizeFresh07 + +theorem vectorInputEnv_ordered07 : vectorInputEnv07.Ordered := + .const (n := ``Array.size) (ci := vectorArraySizeConst07.toVConstant) + vectorArrayEnv_ordered07 vectorArraySizeConstWF07 rfl + +theorem vectorInputAligned07 : + Aligned .safe vectorInputMap07 vectorInputEnv07 := + Aligned.const vectorArrayAligned07 vectorArraySizeFresh07 + vectorArraySizeInfoTr07.1 rfl vectorArraySizeInfoTr07.2 + +example : vectorInputMap07 = vectorDependencyMap07 := rfl + +/-! ### Vector -/ + +theorem vectorCheckedWF07 : vectorChecked.WF vectorInputEnv07 := by + constructor + · change vectorInputEnv07.OnTel 1 [] + [.sort (.succ (.param 0)), .const ``Nat []] + have hNat : vectorInputEnv07.constants ``Nat = + some natType.toVConstant := rfl + exact ⟨⟨.succ (.succ (.param 0)), VEnv.HasType.sort (by decide)⟩, + ⟨⟨.succ .zero, by type_tac⟩, trivial⟩⟩ + · intro ctor hctor + have hctor' := List.mem_singleton.1 hctor + subst ctor + constructor + · change VInductDecl.fieldsWF 1 ``Vector 2 vectorInputEnv07 + (.succ (.param 0)) [] + [.const ``Nat [], .sort (.succ (.param 0))] 0 + [.app (.const ``Array [.param 0]) (.bvar 1), + .app + (.app + (.app (.const ``Eq [.succ .zero]) (.const ``Nat [])) + (.app + (.app (.const ``Array.size [.param 0]) (.bvar 2)) + (.bvar 0))) + (.bvar 1)] + have hNat : vectorInputEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hEq : vectorInputEnv07.constants ``Eq = + some eqType.toVConstant := rfl + have hArray : vectorInputEnv07.constants ``Array = + some vectorArrayConst07.toVConstant := rfl + have hSize : vectorInputEnv07.constants ``Array.size = + some vectorArraySizeConst07.toVConstant := rfl + constructor + · exact .inr (.inr ⟨rfl, .succ (.param 0), by type_tac, + .inr (VLevel.le_refl _)⟩) + constructor + · intro recursive + contradiction + constructor + · exact .inr (.inr ⟨rfl, .zero, by type_tac, + .inr VLevel.zero_le⟩) + constructor + · intro recursive + contradiction + · trivial + · exact .nil + +theorem vectorGenerationWF07 : + vectorGenerationChecked.WF vectorInputEnv07 := by + exact vectorCheckedWF07.identityGeneration vectorInputEnv_ordered07 + +def vectorTypeEnv07 : VEnv := + (vectorInputEnv07.addConst vectorType.name vectorType.toVConstant).get! + +def vectorCtorEnv07 : VEnv := + (vectorTypeEnv07.addConst vectorType.ctors[0].name + vectorType.ctors[0].toVConstant).get! + +def vectorRecEnv07 : VEnv := + (vectorCtorEnv07.addConst ``Vector.rec + (inductGenerationRecVal vectorGenerationChecked).toVConstant).get! + +def vectorFinalEnv07 : VEnv := + vectorGenerationChecked.generatedRules.foldl VEnv.addDefEq vectorRecEnv07 + +def vectorTypeMap07 : ConstMap := + vectorInputMap07.insert ``Vector vectorInfo07 +def vectorCtorMap07 : ConstMap := + vectorTypeMap07.insert ``Vector.mk vectorMkInfo07 +def vectorMap07 : ConstMap := + vectorCtorMap07.insert ``Vector.rec vectorRecInfo07 + +theorem vectorTypeEnv_ordered07 : vectorTypeEnv07.Ordered := + replayTypeEnv_ordered07 vectorInputEnv_ordered07 vectorGenerationWF07 rfl + +theorem vectorCtorEnv_ordered07 : vectorCtorEnv07.Ordered := + replayCtorEnv_ordered07 vectorGenerationWF07 rfl + vectorTypeEnv_ordered07 rfl + +theorem vectorGenerationEnv07 : + VInductDecl.GenerationEnv vectorGenerationChecked vectorCtorEnv07 := + replayGenerationEnv07 vectorGenerationWF07 rfl rfl + vectorCtorEnv_ordered07 + +theorem vectorInfoTr07 : + TrConstVal .safe vectorInputEnv07 vectorInfo07 + vectorType.toVConstVal := by + have hNat : vectorInputEnv07.constants ``Nat = + some natType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr vectorInputEnv07 vectorInfo07.levelParams [] + vectorInfo07.type vectorType.type := by + tr_type_expr_tac + obtain ⟨sort, familyType⟩ := replayRawFamilyWF07 vectorGenerationWF07 + exact shape.to_trExprS vectorInputEnv_ordered07 trivial + ⟨.sort sort, familyType⟩ + +theorem vectorCtorInfoTr07 : + TrConstVal .safe vectorTypeEnv07 vectorMkInfo07 vectorType.ctors[0] := by + have hNat : vectorTypeEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hEq : vectorTypeEnv07.constants ``Eq = + some eqType.toVConstant := rfl + have hArray : vectorTypeEnv07.constants ``Array = + some vectorArrayConst07.toVConstant := rfl + have hSize : vectorTypeEnv07.constants ``Array.size = + some vectorArraySizeConst07.toVConstant := rfl + have hVector : vectorTypeEnv07.constants ``Vector = + some vectorType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr vectorTypeEnv07 vectorMkInfo07.levelParams [] + vectorMkInfo07.type vectorType.ctors[0].type := by + tr_type_expr_tac + obtain ⟨sort, ctorType⟩ := replayRawCtorWF07 vectorGenerationWF07 rfl + vectorType.ctors[0] (.head _) + exact shape.to_trExprS vectorTypeEnv_ordered07 trivial + ⟨.sort sort, ctorType⟩ + +theorem vectorRecInfoTr07 : + TrConstVal .safe vectorCtorEnv07 vectorRecInfo07 + (inductGenerationRecVal vectorGenerationChecked) := by + have hNat : vectorCtorEnv07.constants ``Nat = + some natType.toVConstant := rfl + have hEq : vectorCtorEnv07.constants ``Eq = + some eqType.toVConstant := rfl + have hArray : vectorCtorEnv07.constants ``Array = + some vectorArrayConst07.toVConstant := rfl + have hSize : vectorCtorEnv07.constants ``Array.size = + some vectorArraySizeConst07.toVConstant := rfl + have hVector : vectorCtorEnv07.constants ``Vector = + some vectorType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr vectorCtorEnv07 vectorRecInfo07.levelParams [] + vectorRecInfo07.type + (inductGenerationRecVal vectorGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := vectorGenerationEnv07.recursor_wf + exact shape.to_trExprS vectorCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem vectorTypeFresh07 : + vectorInputMap07.find? ``Vector = none := by + rw [vectorInputMap07, vectorArrayMapWF07.find?_insert, + vectorArrayMap07, vectorEqMapWF07.find?_insert, vectorEqMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem vectorTypeMapWF07 : vectorTypeMap07.WF := + vectorInputMapWF07.insert _ _ vectorTypeFresh07 + +theorem vectorCtorFresh07 : + vectorTypeMap07.find? ``Vector.mk = none := by + rw [vectorTypeMap07, vectorInputMapWF07.find?_insert, + vectorInputMap07, vectorArrayMapWF07.find?_insert, + vectorArrayMap07, vectorEqMapWF07.find?_insert, vectorEqMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem vectorCtorMapWF07 : vectorCtorMap07.WF := + vectorTypeMapWF07.insert _ _ vectorCtorFresh07 + +theorem vectorRecFresh07 : + vectorCtorMap07.find? ``Vector.rec = none := by + rw [vectorCtorMap07, vectorTypeMapWF07.find?_insert, + vectorTypeMap07, vectorInputMapWF07.find?_insert, + vectorInputMap07, vectorArrayMapWF07.find?_insert, + vectorArrayMap07, vectorEqMapWF07.find?_insert, vectorEqMap07, + natTypeMap_wf.find?_insert, natTypeMap, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem vectorAddInduct07 : + AddInduct vectorInputMap07 vectorInputEnv07 vectorDecl + vectorMap07 vectorFinalEnv07 := by + refine ⟨{ + generation := vectorGenerationChecked + generation_wf := vectorGenerationWF07 + typeMap := vectorTypeMap07 + typeEnv := vectorTypeEnv07 + ctorMap := vectorCtorMap07 + ctorEnv := vectorCtorEnv07 + recEnv := vectorRecEnv07 + addType := { + info := vectorInfo07 + kind_eq := by simp [vectorInfo07, InductConstantKind.Matches] + tr := vectorInfoTr07 + map_fresh := vectorTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := vectorRecInfo07 + kind_eq := by simp [vectorRecInfo07, InductConstantKind.Matches] + tr := vectorRecInfoTr07 + map_fresh := vectorRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := vectorMkInfo07 + kind_eq := by simp [vectorMkInfo07, InductConstantKind.Matches] + tr := vectorCtorInfoTr07 + map_fresh := by simpa [vectorType] using vectorCtorFresh07 + env_add := rfl + map_add := rfl } .nil + +theorem vectorAligned07 : Aligned .safe vectorMap07 vectorFinalEnv07 := + Aligned.addInduct vectorAddInduct07 vectorInputAligned07 + +def vectorReplay07 : SingletonReplayArtifact where + label := ``Vector + source := vectorDecl + inputMap := vectorInputMap07 + inputEnv := vectorInputEnv07 + inputMapWF := vectorInputMapWF07 + outputMap := vectorMap07 + outputEnv := vectorFinalEnv07 + inputOrdered := vectorInputEnv_ordered07 + transaction := vectorAddInduct07 + aligned := vectorAligned07 + +/-! ### Unit/Empty edge cases -/ + +theorem punitGenerationWF07 : punitGenerationChecked.WF VEnv.empty := by + exact (punitChecked.wf_of_decl punitDecl_wf).identityGeneration .empty + +def punitTypeEnv07 : VEnv := + (VEnv.empty.addConst punitType.name punitType.toVConstant).get! + +def punitCtorEnv07 : VEnv := + (punitTypeEnv07.addConst punitType.ctors[0].name + punitType.ctors[0].toVConstant).get! + +def punitRecEnv07 : VEnv := + (punitCtorEnv07.addConst ``PUnit.rec + (inductGenerationRecVal punitGenerationChecked).toVConstant).get! + +def punitFinalEnv07 : VEnv := + punitGenerationChecked.generatedRules.foldl VEnv.addDefEq punitRecEnv07 + +def punitTypeMap07 : ConstMap := + ({} : ConstMap).insert ``PUnit punitInfo06C + +def punitCtorMap07 : ConstMap := + punitTypeMap07.insert ``PUnit.unit punitCtorInfo06C + +def punitMap07 : ConstMap := + punitCtorMap07.insert ``PUnit.rec punitRecInfo06C + +theorem punitTypeEnv_ordered07 : punitTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty punitGenerationWF07 rfl + +theorem punitCtorEnv_ordered07 : punitCtorEnv07.Ordered := + replayCtorEnv_ordered07 punitGenerationWF07 rfl + punitTypeEnv_ordered07 rfl + +theorem punitGenerationEnv07 : + VInductDecl.GenerationEnv punitGenerationChecked punitCtorEnv07 := + replayGenerationEnv07 punitGenerationWF07 rfl rfl + punitCtorEnv_ordered07 + +theorem punitInfoTr07 : + TrConstVal .safe VEnv.empty punitInfo06C punitType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + exact .sort rfl + +theorem punitCtorInfoTr07 : + TrConstVal .safe punitTypeEnv07 punitCtorInfo06C punitType.ctors[0] := by + have hPUnit : punitTypeEnv07.constants ``PUnit = + some punitType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr punitTypeEnv07 punitCtorInfo06C.levelParams [] + punitCtorInfo06C.type punitType.ctors[0].type := by + tr_type_expr_tac + exact shape.to_trExprS punitTypeEnv_ordered07 trivial + ⟨.sort (.param 0), by type_tac⟩ + +theorem punitRecInfoTr07 : + TrConstVal .safe punitCtorEnv07 punitRecInfo06C + (inductGenerationRecVal punitGenerationChecked) := by + have hPUnit : punitCtorEnv07.constants ``PUnit = + some punitType.toVConstant := rfl + have hUnit : punitCtorEnv07.constants ``PUnit.unit = + some punitType.ctors[0].toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr punitCtorEnv07 punitRecInfo06C.levelParams [] + punitRecInfo06C.type + (inductGenerationRecVal punitGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := punitGenerationEnv07.recursor_wf + exact shape.to_trExprS punitCtorEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem punitTypeFresh07 : ({} : ConstMap).find? ``PUnit = none := by + simp [SMap.find?] + +theorem punitTypeMapWF07 : punitTypeMap07.WF := + SMap.WF.empty.insert _ _ punitTypeFresh07 + +theorem punitCtorFresh07 : punitTypeMap07.find? ``PUnit.unit = none := by + rw [punitTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem punitCtorMapWF07 : punitCtorMap07.WF := + punitTypeMapWF07.insert _ _ punitCtorFresh07 + +theorem punitRecFresh07 : punitCtorMap07.find? ``PUnit.rec = none := by + rw [punitCtorMap07, punitTypeMapWF07.find?_insert, punitTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem punitAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty punitDecl + punitMap07 punitFinalEnv07 := by + refine ⟨{ + generation := punitGenerationChecked + generation_wf := punitGenerationWF07 + typeMap := punitTypeMap07 + typeEnv := punitTypeEnv07 + ctorMap := punitCtorMap07 + ctorEnv := punitCtorEnv07 + recEnv := punitRecEnv07 + addType := { + info := punitInfo06C + kind_eq := by simp [punitInfo06C, InductConstantKind.Matches] + tr := punitInfoTr07 + map_fresh := punitTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := ?_ + addRec := { + info := punitRecInfo06C + kind_eq := by simp [punitRecInfo06C, InductConstantKind.Matches] + tr := punitRecInfoTr07 + map_fresh := punitRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + exact .cons { + info := punitCtorInfo06C + kind_eq := by simp [punitCtorInfo06C, InductConstantKind.Matches] + tr := punitCtorInfoTr07 + map_fresh := by simpa [punitType] using punitCtorFresh07 + env_add := rfl + map_add := rfl } .nil + +theorem punitAligned07 : Aligned .safe punitMap07 punitFinalEnv07 := + Aligned.addInduct punitAddInduct07 .empty + +def punitReplay07 : SingletonReplayArtifact where + label := ``Unit + source := punitDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := punitMap07 + outputEnv := punitFinalEnv07 + inputOrdered := .empty + transaction := punitAddInduct07 + aligned := punitAligned07 + +theorem emptyGenerationWF07 : emptyGenerationChecked.WF VEnv.empty := by + exact (emptyChecked.wf_of_decl emptyDecl_wf).identityGeneration .empty + +def emptyTypeEnv07 : VEnv := + (VEnv.empty.addConst emptyType.name emptyType.toVConstant).get! + +def emptyRecEnv07 : VEnv := + (emptyTypeEnv07.addConst ``Empty.rec + (inductGenerationRecVal emptyGenerationChecked).toVConstant).get! + +def emptyFinalEnv07 : VEnv := + emptyGenerationChecked.generatedRules.foldl VEnv.addDefEq emptyRecEnv07 + +def emptyTypeMap07 : ConstMap := + ({} : ConstMap).insert ``Empty emptyInfo06C + +def emptyMap07 : ConstMap := + emptyTypeMap07.insert ``Empty.rec emptyRecInfo06C + +theorem emptyTypeEnv_ordered07 : emptyTypeEnv07.Ordered := + replayTypeEnv_ordered07 .empty emptyGenerationWF07 rfl + +theorem emptyGenerationEnv07 : + VInductDecl.GenerationEnv emptyGenerationChecked emptyTypeEnv07 := + replayGenerationEnv07 emptyGenerationWF07 rfl rfl + emptyTypeEnv_ordered07 + +theorem emptyInfoTr07 : + TrConstVal .safe VEnv.empty emptyInfo06C emptyType.toVConstVal := by + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + exact .sort rfl + +theorem emptyRecInfoTr07 : + TrConstVal .safe emptyTypeEnv07 emptyRecInfo06C + (inductGenerationRecVal emptyGenerationChecked) := by + have hEmpty : emptyTypeEnv07.constants ``Empty = + some emptyType.toVConstant := rfl + refine ⟨⟨by decide, rfl, ?_⟩, rfl⟩ + have shape : TrTypeExpr emptyTypeEnv07 emptyRecInfo06C.levelParams [] + emptyRecInfo06C.type + (inductGenerationRecVal emptyGenerationChecked).type := by + tr_type_expr_tac + obtain ⟨sort, recursorType⟩ := emptyGenerationEnv07.recursor_wf + exact shape.to_trExprS emptyTypeEnv_ordered07 trivial + ⟨.sort sort, recursorType⟩ + +theorem emptyTypeFresh07 : ({} : ConstMap).find? ``Empty = none := by + simp [SMap.find?] + +theorem emptyTypeMapWF07 : emptyTypeMap07.WF := + SMap.WF.empty.insert _ _ emptyTypeFresh07 + +theorem emptyRecFresh07 : emptyTypeMap07.find? ``Empty.rec = none := by + rw [emptyTypeMap07, + SMap.WF.find?_insert (s := ({} : ConstMap)) SMap.WF.empty] + simp [SMap.find?] + +theorem emptyAddInduct07 : AddInduct ({} : ConstMap) VEnv.empty emptyDecl + emptyMap07 emptyFinalEnv07 := by + refine ⟨{ + generation := emptyGenerationChecked + generation_wf := emptyGenerationWF07 + typeMap := emptyTypeMap07 + typeEnv := emptyTypeEnv07 + ctorMap := emptyTypeMap07 + ctorEnv := emptyTypeEnv07 + recEnv := emptyRecEnv07 + addType := { + info := emptyInfo06C + kind_eq := by simp [emptyInfo06C, InductConstantKind.Matches] + tr := emptyInfoTr07 + map_fresh := emptyTypeFresh07 + env_add := rfl + map_add := rfl } + addCtors := .nil + addRec := { + info := emptyRecInfo06C + kind_eq := by simp [emptyRecInfo06C, InductConstantKind.Matches] + tr := emptyRecInfoTr07 + map_fresh := emptyRecFresh07 + env_add := rfl + map_add := rfl } + recK := by decide + addRules := ⟨rfl⟩ }⟩ + +theorem emptyAligned07 : Aligned .safe emptyMap07 emptyFinalEnv07 := + Aligned.addInduct emptyAddInduct07 .empty + +def emptyReplay07 : SingletonReplayArtifact where + label := ``Empty + source := emptyDecl + inputMap := {} + inputEnv := .empty + inputMapWF := SMap.WF.empty + outputMap := emptyMap07 + outputEnv := emptyFinalEnv07 + inputOrdered := .empty + transaction := emptyAddInduct07 + aligned := emptyAligned07 + +/-- Every fixed Spec-07 positive row, in exactly the same order as the +Theory/kernel parity matrix. Each entry carries an actual `ConstantInfo` +transaction and final environment alignment, including the real dependency +environments required by `Fin` and `Vector`. -/ +def singletonFixedReplays : List SingletonReplayArtifact := + [natReplay07, boolReplay07, listReplay07, optionReplay07, prodReplay07, + punitReplay07, emptyReplay07, orReplay07, andReplay07, eqReplay07, + heqReplay07, finReplay07, vectorReplay07, accReplay07] + +/-- The focused non-identity normalization rows use the same public replay +artifact as the standard-library matrix. -/ +def singletonNormalizationReplays : + List SingletonReplayArtifact := + [aliasFormerReplay07, aliasRecReplay07, normalizationMatrixReplay07, + annotatedPiReplay07, annotatedParamReplay07] + +/-- The sole public Spec-07 environment replay inventory. -/ +def singletonReplayMatrix : List SingletonReplayArtifact := + singletonFixedReplays ++ singletonNormalizationReplays + +example : singletonFixedReplays.map (·.label) = + singletonPositiveArtifacts.map (·.label) := rfl + +example : singletonFixedReplays.map (·.source) = + singletonPositiveArtifacts.map (·.source) := rfl + +example : singletonNormalizationReplays.map (·.label) = + singletonNormalizationArtifacts.map (·.label) := rfl + +example : singletonNormalizationReplays.map (·.source) = + singletonNormalizationArtifacts.map (·.source) := rfl + +example : singletonReplayMatrix.map (·.source) = + (singletonPositiveArtifacts ++ singletonNormalizationArtifacts).map + (·.source) := rfl + +example : singletonFixedReplays.length = 14 := rfl +example : singletonNormalizationReplays.length = 5 := rfl +example : singletonReplayMatrix.length = 19 := rfl + +/-! ## Exact trust manifests for the public replay seam -/ + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.SingletonReplayArtifact.outputOrdered [propext, Classical.choice, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.singletonFixedReplays [ + propext, + Classical.choice, + Quot.sound, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.singletonNormalizationReplays [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +#guard_named_axioms Ix.Theory.Named.InductiveReplayFixtures.singletonReplayMatrix [ + propext, + sorryAx, + Classical.choice, + Ix.Theory.Named.ptrEqConstantInfo_eq, + Quot.sound, + Lean.Expr.abstractRange_eq, + Lean.Expr.abstract_eq, + Lean.Expr.eqv_eq, + Lean.Expr.hasLooseBVar_eq, + Lean.Expr.instantiate1_eq, + Lean.Expr.instantiateRange_eq, + Lean.Expr.instantiateRevRange_eq, + Lean.Expr.instantiateRev_eq, + Lean.Expr.instantiate_eq, + Lean.Expr.looseBVarRange_eq, + Lean.Expr.lowerLooseBVars_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.Level.isExplicitSubsumedAux_eq, + Lean.Level.normalize_eq, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.Syntax.structEq_eq, + Std.TreeMap.all_eq_all_toList, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] + +end Ix.Theory.Named.InductiveReplayFixtures diff --git a/Ix/Theory/Named/Verify/Expr.lean b/Ix/Theory/Named/Verify/Expr.lean new file mode 100644 index 000000000..fba52e69d --- /dev/null +++ b/Ix/Theory/Named/Verify/Expr.lean @@ -0,0 +1,1303 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.Basic +import Ix.Theory.Named.Verify.Axioms +import Ix.Theory.Named.Verify.Level +import Ix.Theory.Named.Reference.Expr +import Ix.Theory.Named.Reference.Instantiate +import Batteries.Data.String.Lemmas +import Std.Tactic.BVDecide + +open Ix.Theory.Named + +namespace Lean + +instance : LawfulBEq FVarId where + eq_of_beq := @fun ⟨a⟩ ⟨b⟩ h => by cases LawfulBEq.eq_of_beq (α := Name) h; rfl + rfl := BEq.rfl (α := Name) + +instance : LawfulBEq MVarId where + eq_of_beq := @fun ⟨a⟩ ⟨b⟩ h => by cases LawfulBEq.eq_of_beq (α := Name) h; rfl + rfl := BEq.rfl (α := Name) + +instance : LawfulBEq LBool where + rfl {a} := by cases a <;> rfl + eq_of_beq {a b} := by cases a <;> cases b <;> simp +decide + +instance : LawfulBEq DefinitionSafety where + rfl {a} := by cases a <;> rfl + eq_of_beq {a b} := by cases a <;> cases b <;> simp +decide + +-- we have to define this manually instead of `deriving instance Ord` +-- because the variants are written in the wrong order in core +protected def DefinitionSafety.compare : DefinitionSafety → DefinitionSafety → Ordering + | .unsafe, .unsafe => .eq + | .unsafe, _ => .lt + | _, .unsafe => .gt + | .partial, .partial => .eq + | .partial, _ => .lt + | _, .partial => .gt + | .safe, .safe => .eq + +instance : Ord DefinitionSafety := ⟨DefinitionSafety.compare⟩ + +instance : Std.TransOrd DefinitionSafety where + eq_swap {a b} := by cases a <;> cases b <;> rfl + isLE_trans {a b c} := by cases a <;> cases b <;> simp! [compare] <;> cases c <;> decide + +instance : Std.LawfulBEqOrd DefinitionSafety where + compare_eq_iff_beq {a b} := by cases a <;> cases b <;> decide +instance : Std.LawfulEqOrd DefinitionSafety := Std.LawfulBEqOrd.lawfulEqOrd + +instance : LE DefinitionSafety := leOfOrd +instance : DecidableEq DefinitionSafety := instDecidableEqOfLawfulBEq + +theorem DefinitionSafety.le_trans {a b c : DefinitionSafety} : a ≤ b → b ≤ c → a ≤ c := + Std.TransOrd.isLE_trans + +theorem DefinitionSafety.le_rfl {a : DefinitionSafety} : a ≤ a := Std.ReflCmp.isLE_rfl + +theorem DefinitionSafety.unsafe_le : «unsafe» ≤ a := by cases a <;> rfl +theorem DefinitionSafety.le_safe : a ≤ safe := by cases a <;> rfl +theorem DefinitionSafety.le_antisymm {a b : DefinitionSafety} : a ≤ b → b ≤ a → a = b := by + cases a <;> cases b <;> decide + +namespace Substring + +open private substrEq.loop from Init.Data.String.Basic in +theorem beq_refl (s : Substring.Raw) : s == s := by + simp [(· == ·), Substring.Raw.beq, Substring.Raw.bsize, String.Pos.Raw.substrEq] + let rec loop {s i n} : substrEq.loop s s i i n := by + unfold substrEq.loop; simp [Decidable.or_iff_not_imp_left] + intro h1 + have := Char.utf8Size_pos (String.Pos.Raw.get s i) + exact loop + termination_by n.byteIdx - i.byteIdx + refine ⟨?_, loop⟩ + obtain h | h := Nat.le_or_le s.repair.startPos.byteIdx s.repair.stopPos.byteIdx + · simp only [Nat.add_sub_cancel' h, decide_eq_true_eq] + apply String.Pos.Raw.IsValid.le_rawEndPos + simp [Substring.Raw.repair]; split <;> simp [*] + · simp [Nat.sub_eq_zero_of_le h] + apply String.Pos.Raw.IsValid.le_rawEndPos + simp [Substring.Raw.repair]; split <;> simp [*] + +open private substrEq.loop from Init.Data.String.Basic in +theorem beq_symm {s t : Substring.Raw} : s == t → t == s := by + simp +contextual [(· == ·), Substring.Raw.beq, String.Pos.Raw.substrEq] + simp [Substring.Raw.bsize] + let rec loop {s s' b b' i n} : + substrEq.loop s s' ⟨b + i⟩ ⟨b' + i⟩ ⟨b + n⟩ ↔ + substrEq.loop s' s ⟨b' + i⟩ ⟨b + i⟩ ⟨b' + n⟩ := by + unfold substrEq.loop; simp [beq_comm, Decidable.or_iff_not_imp_left] + refine imp_congr_right fun h1 => and_congr_right fun h2 => ?_ + simp +instances [h2, String.instHAddRawChar, Nat.add_assoc] + have := Char.utf8Size_pos (String.Pos.Raw.get s' ⟨b'+i⟩) + exact Bool.eq_iff_iff.2 loop + termination_by b + n - (b + i) + intro h1 h2 h3 + have loop := @loop (i := 0); simp at loop + simp [loop] + +open private substrEq.loop from Init.Data.String.Basic in +theorem beq_trans {s t : Substring.Raw} : s == t → t == u → s == u := by + simp +contextual [(· == ·), Substring.Raw.beq, String.Pos.Raw.substrEq] + simp [Substring.Raw.bsize] + let ⟨s, ⟨b⟩, e⟩ := s.repair + let ⟨s2, ⟨b2⟩, e2⟩ := t.repair + let ⟨s3, ⟨b3⟩, e3⟩ := u.repair + intro h1 h2 h3 h4 h5 h6 h7 h8 + constructor; · omega + simp [h5] at h4 + let rec loop {s₁ s₂ s₃ b₁ b₂ b₃ i n} : + (h : substrEq.loop s₁ s₂ ⟨b₁ + i⟩ ⟨b₂ + i⟩ ⟨b₁ + n⟩) → + (substrEq.loop s₁ s₃ ⟨b₁ + i⟩ ⟨b₃ + i⟩ ⟨b₁ + n⟩ ↔ + substrEq.loop s₂ s₃ ⟨b₂ + i⟩ ⟨b₃ + i⟩ ⟨b₂ + n⟩) := by + unfold substrEq.loop; simp [Decidable.or_iff_not_imp_left] + refine fun h1 => imp_congr_right fun h => ?_; let ⟨h1, h2⟩ := h1 h + simp [h1]; intro h3; simp +instances [h1, h3, String.instHAddRawChar, Nat.add_assoc] at h2 ⊢ + have := Char.utf8Size_pos (String.Pos.Raw.get s₃ ⟨b₃+i⟩) + refine Bool.eq_iff_iff.2 (loop h2) + termination_by n - i + have loop := @loop (i := 0) (h := h4); simp at loop + simpa [loop] using h8 + +instance : EquivBEq Substring.Raw where + symm := beq_symm + trans := beq_trans + rfl := beq_refl _ + +end Substring + +namespace Syntax + +namespace Preresolved + +protected theorem beq_iff_eq {m n : Preresolved} : m == n ↔ m = n := by + simp only [(· == ·)]; cases m <;> cases n <;> simp! <;> grind only [cases Or] + +instance : LawfulBEq Preresolved where + eq_of_beq := Preresolved.beq_iff_eq.1 + rfl := Preresolved.beq_iff_eq.2 rfl + +end Preresolved + +theorem structEq_refl (s : Syntax) : s.structEq' s := by + unfold structEq' + cases s with + | node i k args => + let ⟨args⟩ := args; simp; intro x _ _ _ + have IH := structEq_refl x + induction args.attach <;> simp + rintro (⟨rfl, ⟨⟩⟩ | h) <;> [skip; solve_by_elim] + simpa using IH + | _ => simp + +attribute [-simp] List.all_eq_true in +theorem structEq_euc {s : Syntax} (H : s.structEq' t) : s.structEq' u = t.structEq' u := by + unfold structEq' at H; split at H + case h_1 => simp + case h_5 => cases H + all_goals + revert H; simp; intros; subst_vars + unfold structEq'; cases u <;> simp <;> rw [Bool.eq_iff_iff] <;> simp [*] + -- all_goals intros; subst_vars + case ident => intros; apply BEq.congr_left ‹_› + case node args₁ _ _ args₂ eq H _ _ args₃ => + rintro rfl eq'; revert H + have IH {a} (h : a ∈ args₁) := @structEq_euc (s := a) + let ⟨args₁⟩ := args₁; let ⟨args₂⟩ := args₂; let ⟨args₃⟩ := args₃ + revert eq eq'; simp at IH ⊢ + simp only [← args₁.length_attach, ← args₂.length_attach, ← args₃.length_attach] + generalize args₁.attach = l₁, args₂.attach = l₂, args₃.attach = l₃ + induction l₁ generalizing l₂ l₃ with cases l₂ <;> simp <;> cases l₃ <;> simp | cons a l₁ ih + intros _ _ H; rw [IH a.2 _ _ H, Bool.eq_iff_iff]; simp [*]; grind +termination_by s + +theorem structEq_symm {s : Syntax} (H : s.structEq' t) : t.structEq' s := + structEq_euc H ▸ structEq_refl _ + +theorem structEq_trans {s : Syntax} (H : s.structEq' t) (H2 : t.structEq' u) : s.structEq' u := + structEq_euc H ▸ H2 + +theorem beq_def : (a == b) = structEq' a b := structEq_eq + +instance : EquivBEq Syntax where + symm := by simp [beq_def]; exact structEq_symm + trans := by simp [beq_def]; exact structEq_trans + rfl := by simp [beq_def]; exact structEq_refl _ + +end Syntax + +namespace DataValue + +instance : EquivBEq DataValue where + symm {a b} := by simp [(· == ·)]; cases a <;> cases b <;> simp! [beq_comm] + trans {a b c} := by + simp [(· == ·)]; cases a <;> cases b <;> simp! [beq_comm] <;> try rintro rfl; simp + cases c <;> simp!; exact BEq.trans + rfl {a} := by simp [(· == ·)]; cases a <;> simp! + +end DataValue + +namespace Expr + +theorem Data.looseBVarRange_le : + (Data.looseBVarRange d).toNat ≤ 2 ^ 20 - 1 := by + rw [Data.looseBVarRange] + suffices (UInt64.shiftRight d 44).toNat ≤ 2 ^ 20 - 1 by simp; omega + show d.toBitVec >>> 44#64 ≤ 0xfffff#64 + rw [BitVec.le_def, BitVec.ushiftRight_ofNat_eq] + simp + have h := BitVec.toNat_ushiftRight_lt d.toBitVec 44 (by omega) + simp at h ⊢ + omega + +private theorem Data.flag_eq_getLsbD (d : Data) (n : UInt64) (hn : n < 64) : + ((d.shiftRight n).land 1 == 1) = d.toBitVec.getLsbD n.toNat := by + apply Bool.eq_iff_iff.2 + simp only [beq_iff_eq] + have hmod : UInt64.mod n 64 = n := UInt64.mod_eq_of_lt hn + constructor + · intro h + have hb := congrArg UInt64.toBitVec h + simp [UInt64.shiftRight, UInt64.land, hmod] at hb + have := congrArg (fun x : BitVec 64 => x.getLsbD 0) hb + simpa using this + · intro h + apply UInt64.toBitVec_inj.mp + simp [UInt64.shiftRight, UInt64.land, hmod] + ext i + by_cases hi : i = 0 + · subst i + simpa using h + · simp [hi] + +private theorem Data.hasFVar_eq_getLsbD (d : Data) : + d.hasFVar = d.toBitVec.getLsbD 40 := by + simpa [Data.hasFVar] using Data.flag_eq_getLsbD d 40 (by decide) + +private theorem Data.hasExprMVar_eq_getLsbD (d : Data) : + d.hasExprMVar = d.toBitVec.getLsbD 41 := by + simpa [Data.hasExprMVar] using Data.flag_eq_getLsbD d 41 (by decide) + +private theorem Data.hasLevelMVar_eq_getLsbD (d : Data) : + d.hasLevelMVar = d.toBitVec.getLsbD 42 := by + simpa [Data.hasLevelMVar] using Data.flag_eq_getLsbD d 42 (by decide) + +private theorem Data.hasLevelParam_eq_getLsbD (d : Data) : + d.hasLevelParam = d.toBitVec.getLsbD 43 := by + simpa [Data.hasLevelParam] using Data.flag_eq_getLsbD d 43 (by decide) + +private def flagAt (fv ev lv lp : Bool) : Nat → Bool + | 0 => fv + | 1 => ev + | 2 => lv + | 3 => lp + | _ => false + +private theorem BitVec.getLsbD_eq_false_of_toNat_lt_two_pow + {x : BitVec w} (h : x.toNat < 2 ^ n) (hn : n ≤ i) : + x.getLsbD i = false := by + rw [BitVec.getLsbD, Nat.testBit_lt_two_pow] + exact Nat.lt_of_lt_of_le h (Nat.pow_le_pow_right (by decide) hn) + +private theorem BitVec.add_shiftLeft_eq_or_of_toNat_lt_two_pow + {x y : BitVec w} (h : x.toNat < 2 ^ n) : + x + (y <<< n) = x ||| (y <<< n) := by + rw [BitVec.add_eq_or_of_and_eq_zero] + ext i hi + simp only [BitVec.getElem_and, BitVec.getElem_zero] + by_cases hin : i < n + · simp [BitVec.getElem_shiftLeft, hin] + · have hx : x[i] = false := by + rw [← BitVec.getLsbD_eq_getElem] + exact BitVec.getLsbD_eq_false_of_toNat_lt_two_pow h (Nat.le_of_not_gt hin) + simp [hx] + +set_option allowUnsafeReducibility true +attribute [local reducible] Data + +private theorem mkData_flags (H : br ≤ 2 ^ 20 - 1) : + (mkData h br d fv ev lv lp).hasFVar = fv ∧ + (mkData h br d fv ev lv lp).hasExprMVar = ev ∧ + (mkData h br d fv ev lv lp).hasLevelMVar = lv ∧ + (mkData h br d fv ev lv lp).hasLevelParam = lp := by + rw [mkData_eq, mkData', if_pos H] + rw [Data.hasFVar_eq_getLsbD, Data.hasExprMVar_eq_getLsbD, + Data.hasLevelMVar_eq_getLsbD, Data.hasLevelParam_eq_getLsbD] + have hh : h.toUInt32.toUInt64.toBitVec ≤ 0xffffffff#64 := + Nat.le_of_lt_succ h.toUInt32.1.1.2 + have hb : ∀ (b : Bool), b.toUInt64.toBitVec ≤ 1#64 := by decide + have hfv := hb fv + have hev := hb ev + have hlv := hb lv + have hlp := hb lp + have hnat : br.toUInt64.toNat = br := by simp; omega + have hbr : br.toUInt64.toBitVec ≤ 0xfffff#64 := (hnat ▸ H :) + let depth : UInt8 := if d > 255 then 255 else d.toUInt8 + have hd : depth.toUInt64.toBitVec ≤ 0xff#64 := Nat.le_of_lt_succ depth.1.1.2 + let data := + h.toUInt32.toUInt64.toBitVec + + depth.toUInt64.toBitVec <<< 32#64 + + fv.toUInt64.toBitVec <<< 40#64 + + ev.toUInt64.toBitVec <<< 41#64 + + lv.toUInt64.toBitVec <<< 42#64 + + lp.toUInt64.toBitVec <<< 43#64 + + br.toUInt64.toBitVec <<< 44#64 + change data.getLsbD 40 = fv ∧ data.getLsbD 41 = ev ∧ + data.getLsbD 42 = lv ∧ data.getLsbD 43 = lp + have hh' : h.toUInt32.toUInt64.toBitVec.toNat < 2 ^ 32 := by + simpa using h.toUInt32.1.1.2 + have hd' : depth.toUInt64.toBitVec.toNat < 2 ^ 8 := by + simpa using depth.1.1.2 + have hb' : ∀ (b : Bool), b.toUInt64.toBitVec.toNat < 2 := by + intro b + cases b <;> decide + have h0 := BitVec.add_shiftLeft_eq_or_of_toNat_lt_two_pow + (x := h.toUInt32.toUInt64.toBitVec) (y := depth.toUInt64.toBitVec) hh' + have hs0 : (depth.toUInt64.toBitVec <<< 32).toNat < 2 ^ 40 := by + rw [BitVec.toNat_shiftLeft, Nat.shiftLeft_eq, Nat.mod_eq_of_lt] + · omega + · omega + have hp0 : + (h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32).toNat < + 2 ^ 40 := by + rw [BitVec.toNat_or] + exact Nat.or_lt_two_pow (by omega) hs0 + have h1 := BitVec.add_shiftLeft_eq_or_of_toNat_lt_two_pow + (x := h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32) + (y := fv.toUInt64.toBitVec) hp0 + have hs1 : (fv.toUInt64.toBitVec <<< 40).toNat < 2 ^ 41 := by + rw [BitVec.toNat_shiftLeft, Nat.shiftLeft_eq, Nat.mod_eq_of_lt] + · have := hb' fv; omega + · have := hb' fv; omega + have hp1 : + (h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40).toNat < 2 ^ 41 := by + rw [BitVec.toNat_or] + exact Nat.or_lt_two_pow (by omega) hs1 + have h2 := BitVec.add_shiftLeft_eq_or_of_toNat_lt_two_pow + (x := h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40) + (y := ev.toUInt64.toBitVec) hp1 + have hs2 : (ev.toUInt64.toBitVec <<< 41).toNat < 2 ^ 42 := by + rw [BitVec.toNat_shiftLeft, Nat.shiftLeft_eq, Nat.mod_eq_of_lt] + · have := hb' ev; omega + · have := hb' ev; omega + have hp2 : + (h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40 ||| ev.toUInt64.toBitVec <<< 41).toNat < + 2 ^ 42 := by + rw [BitVec.toNat_or] + exact Nat.or_lt_two_pow (by omega) hs2 + have h3 := BitVec.add_shiftLeft_eq_or_of_toNat_lt_two_pow + (x := h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40 ||| ev.toUInt64.toBitVec <<< 41) + (y := lv.toUInt64.toBitVec) hp2 + have hs3 : (lv.toUInt64.toBitVec <<< 42).toNat < 2 ^ 43 := by + rw [BitVec.toNat_shiftLeft, Nat.shiftLeft_eq, Nat.mod_eq_of_lt] + · have := hb' lv; omega + · have := hb' lv; omega + have hp3 : + (h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40 ||| ev.toUInt64.toBitVec <<< 41 ||| + lv.toUInt64.toBitVec <<< 42).toNat < 2 ^ 43 := by + rw [BitVec.toNat_or] + exact Nat.or_lt_two_pow (by omega) hs3 + have h4 := BitVec.add_shiftLeft_eq_or_of_toNat_lt_two_pow + (x := h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40 ||| ev.toUInt64.toBitVec <<< 41 ||| + lv.toUInt64.toBitVec <<< 42) + (y := lp.toUInt64.toBitVec) hp3 + have hs4 : (lp.toUInt64.toBitVec <<< 43).toNat < 2 ^ 44 := by + rw [BitVec.toNat_shiftLeft, Nat.shiftLeft_eq, Nat.mod_eq_of_lt] + · have := hb' lp; omega + · have := hb' lp; omega + have hp4 : + (h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40 ||| ev.toUInt64.toBitVec <<< 41 ||| + lv.toUInt64.toBitVec <<< 42 ||| lp.toUInt64.toBitVec <<< 43).toNat < + 2 ^ 44 := by + rw [BitVec.toNat_or] + exact Nat.or_lt_two_pow (by omega) hs4 + have h5 := BitVec.add_shiftLeft_eq_or_of_toNat_lt_two_pow + (x := h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40 ||| ev.toUInt64.toBitVec <<< 41 ||| + lv.toUInt64.toBitVec <<< 42 ||| lp.toUInt64.toBitVec <<< 43) + (y := br.toUInt64.toBitVec) hp4 + have hdata : data = + h.toUInt32.toUInt64.toBitVec ||| depth.toUInt64.toBitVec <<< 32 ||| + fv.toUInt64.toBitVec <<< 40 ||| ev.toUInt64.toBitVec <<< 41 ||| + lv.toUInt64.toBitVec <<< 42 ||| lp.toUInt64.toBitVec <<< 43 ||| + br.toUInt64.toBitVec <<< 44 := by + dsimp [data] + rw [h0, h1, h2, h3, h4, h5] + have hhbit : ∀ i, 32 ≤ i → h.toUInt32.toUInt64.toBitVec.getLsbD i = false := + fun _ hi => BitVec.getLsbD_eq_false_of_toNat_lt_two_pow hh' hi + have hdbit : ∀ i, 8 ≤ i → depth.toUInt64.toBitVec.getLsbD i = false := + fun _ hi => BitVec.getLsbD_eq_false_of_toNat_lt_two_pow hd' hi + have hbbit : ∀ (b : Bool) i, 1 ≤ i → b.toUInt64.toBitVec.getLsbD i = false := + fun b _ hi => BitVec.getLsbD_eq_false_of_toNat_lt_two_pow (hb' b) hi + rw [hdata] + simp only [BitVec.getLsbD_or, BitVec.getLsbD_shiftLeft] + simp only [Nat.reduceLT, decide_true, decide_false, Bool.not_true, Bool.not_false, + Bool.true_and, Bool.false_and, Bool.or_false, Nat.reduceSub] + rw [hhbit 40 (by omega), hhbit 41 (by omega), hhbit 42 (by omega), + hhbit 43 (by omega), hdbit 8 (by omega), hdbit 9 (by omega), + hdbit 10 (by omega), hdbit 11 (by omega), hbbit fv 1 (by omega), + hbbit fv 2 (by omega), hbbit fv 3 (by omega), hbbit ev 1 (by omega), + hbbit ev 2 (by omega), hbbit lv 1 (by omega)] + simp only [Bool.false_or] + cases fv <;> cases ev <;> cases lv <;> cases lp <;> decide + +private theorem mkData_hasFVar (H : br ≤ 2 ^ 20 - 1) : + (mkData h br d fv ev lv lp).hasFVar = fv := by + exact (mkData_flags H).1 + +private theorem mkData_hasExprMVar (H : br ≤ 2 ^ 20 - 1) : + (mkData h br d fv ev lv lp).hasExprMVar = ev := by + exact (mkData_flags H).2.1 + +private theorem mkData_hasLevelMVar (H : br ≤ 2 ^ 20 - 1) : + (mkData h br d fv ev lv lp).hasLevelMVar = lv := by + exact (mkData_flags H).2.2.1 + +private theorem mkData_hasLevelParam (H : br ≤ 2 ^ 20 - 1) : + (mkData h br d fv ev lv lp).hasLevelParam = lp := by + exact (mkData_flags H).2.2.2 + +private theorem mkData_flags_of_false (br d h) : + (mkData h br d false false false false).hasFVar = false ∧ + (mkData h br d false false false false).hasExprMVar = false ∧ + (mkData h br d false false false false).hasLevelMVar = false ∧ + (mkData h br d false false false false).hasLevelParam = false := by + by_cases H : br ≤ 2 ^ 20 - 1 + · exact mkData_flags H + · rw [mkData_eq, mkData', if_neg H] + exact ⟨rfl, rfl, rfl, rfl⟩ + +private theorem mkData_hasFVar_of_false (br d h) : + (mkData h br d false false false false).hasFVar = false := + (mkData_flags_of_false br d h).1 + +private theorem mkData_hasExprMVar_of_false (br d h) : + (mkData h br d false false false false).hasExprMVar = false := + (mkData_flags_of_false br d h).2.1 + +private theorem mkData_hasLevelMVar_of_false (br d h) : + (mkData h br d false false false false).hasLevelMVar = false := + (mkData_flags_of_false br d h).2.2.1 + +private theorem mkData_hasLevelParam_of_false (br d h) : + (mkData h br d false false false false).hasLevelParam = false := + (mkData_flags_of_false br d h).2.2.2 + +private theorem mkAppData_flag (i : Nat) (hi : i < 4) : + (mkAppData fData aData).toBitVec.getLsbD (40 + i) = flagAt + (fData.hasFVar || aData.hasFVar) + (fData.hasExprMVar || aData.hasExprMVar) + (fData.hasLevelMVar || aData.hasLevelMVar) + (fData.hasLevelParam || aData.hasLevelParam) i := by + have hm : max fData.looseBVarRange aData.looseBVarRange ≤ + (Nat.pow 2 20 - 1).toUInt32 := by + dsimp +instances [instMaxUInt32, maxOfLe] + split <;> exact Data.looseBVarRange_le + rw [mkAppData_eq, mkAppData', if_pos hm] + generalize (mixHash fData aData).toUInt32 = hash + have : i = 0 ∨ i = 1 ∨ i = 2 ∨ i = 3 := by omega + rcases this with rfl | rfl | rfl | rfl + · simp [flagAt, Data.hasFVar_eq_getLsbD] + · simp [flagAt, Data.hasExprMVar_eq_getLsbD] + · simp [flagAt, Data.hasLevelMVar_eq_getLsbD] + · simp [flagAt, Data.hasLevelParam_eq_getLsbD] + +private theorem mkAppData_hasFVar : + (mkAppData fData aData).hasFVar = (fData.hasFVar || aData.hasFVar) := by + rw [Data.hasFVar_eq_getLsbD] + exact mkAppData_flag 0 (by decide) + +private theorem mkAppData_hasExprMVar : + (mkAppData fData aData).hasExprMVar = (fData.hasExprMVar || aData.hasExprMVar) := by + rw [Data.hasExprMVar_eq_getLsbD] + exact mkAppData_flag 1 (by decide) + +private theorem mkAppData_hasLevelMVar : + (mkAppData fData aData).hasLevelMVar = (fData.hasLevelMVar || aData.hasLevelMVar) := by + rw [Data.hasLevelMVar_eq_getLsbD] + exact mkAppData_flag 2 (by decide) + +private theorem mkAppData_hasLevelParam : + (mkAppData fData aData).hasLevelParam = (fData.hasLevelParam || aData.hasLevelParam) := by + rw [Data.hasLevelParam_eq_getLsbD] + exact mkAppData_flag 3 (by decide) + +private theorem binder_looseBVarRange_le (ty body : Expr) : + max ty.data.looseBVarRange.toNat (body.data.looseBVarRange.toNat - 1) ≤ 2 ^ 20 - 1 := by + have hty := Data.looseBVarRange_le (d := ty.data) + have hbody := Data.looseBVarRange_le (d := body.data) + omega + +private theorem let_looseBVarRange_le (ty val body : Expr) : + max (max ty.data.looseBVarRange.toNat val.data.looseBVarRange.toNat) + (body.data.looseBVarRange.toNat - 1) ≤ 2 ^ 20 - 1 := by + have hty := Data.looseBVarRange_le (d := ty.data) + have hval := Data.looseBVarRange_le (d := val.data) + have hbody := Data.looseBVarRange_le (d := body.data) + omega + +def hasFVar' : Expr → Bool + | .fvar _ => true + | .const .. + | .bvar _ + | .sort _ + | .mvar _ + | .lit _ => false + | .mdata _ e => e.hasFVar' + | .proj _ _ e => e.hasFVar' + | .app e1 e2 + | .lam _ e1 e2 _ + | .forallE _ e1 e2 _ => e1.hasFVar' || e2.hasFVar' + | .letE _ t v b _ => t.hasFVar' || v.hasFVar' || b.hasFVar' + +/-- The cached `hasFVar` bit agrees with structural traversal. -/ +theorem hasFVar_eq (e : Expr) : e.hasFVar = e.hasFVar' := by + change e.data.hasFVar = e.hasFVar' + induction e with + | bvar => simp [Expr.data, hasFVar', mkData_hasFVar_of_false] + | fvar | mvar | sort | const | lit => + simp only [Expr.data, hasFVar'] + apply mkData_hasFVar + omega + | app _ _ ih1 ih2 => + simp only [Expr.data, hasFVar'] + rw [mkAppData_hasFVar, ih1, ih2] + | lam _ ty body _ ihty ihbody | forallE _ ty body _ ihty ihbody => + simp only [Expr.data, mkDataForBinder, hasFVar'] + rw [mkData_hasFVar (binder_looseBVarRange_le ty body), ihty, ihbody] + | letE _ ty val body _ ihty ihval ihbody => + simp only [Expr.data, mkDataForLet, hasFVar'] + rw [mkData_hasFVar (let_looseBVarRange_le ty val body), ihty, ihval, ihbody] + | mdata _ e ih | proj _ _ e ih => + simp only [Expr.data, hasFVar'] + rw [mkData_hasFVar (Data.looseBVarRange_le (d := e.data)), ih] + +def hasExprMVar' : Expr → Bool + | .mvar _ => true + | .const .. + | .bvar _ + | .sort _ + | .fvar _ + | .lit _ => false + | .mdata _ e => e.hasExprMVar' + | .proj _ _ e => e.hasExprMVar' + | .app e1 e2 + | .lam _ e1 e2 _ + | .forallE _ e1 e2 _ => e1.hasExprMVar' || e2.hasExprMVar' + | .letE _ t v b _ => t.hasExprMVar' || v.hasExprMVar' || b.hasExprMVar' + +/-- The cached `hasExprMVar` bit agrees with structural traversal. -/ +@[simp] theorem hasExprMVar_eq (e : Expr) : e.hasExprMVar = e.hasExprMVar' := by + change e.data.hasExprMVar = e.hasExprMVar' + induction e with + | bvar => simp [Expr.data, hasExprMVar', mkData_hasExprMVar_of_false] + | fvar | mvar | sort | const | lit => + simp only [Expr.data, hasExprMVar'] + apply mkData_hasExprMVar + omega + | app _ _ ih1 ih2 => + simp only [Expr.data, hasExprMVar'] + rw [mkAppData_hasExprMVar, ih1, ih2] + | lam _ ty body _ ihty ihbody | forallE _ ty body _ ihty ihbody => + simp only [Expr.data, mkDataForBinder, hasExprMVar'] + rw [mkData_hasExprMVar (binder_looseBVarRange_le ty body), ihty, ihbody] + | letE _ ty val body _ ihty ihval ihbody => + simp only [Expr.data, mkDataForLet, hasExprMVar'] + rw [mkData_hasExprMVar (let_looseBVarRange_le ty val body), ihty, ihval, ihbody] + | mdata _ e ih | proj _ _ e ih => + simp only [Expr.data, hasExprMVar'] + rw [mkData_hasExprMVar (Data.looseBVarRange_le (d := e.data)), ih] + +def hasLevelMVar' : Expr → Bool + | .const _ ls => ls.any (·.hasMVar) + | .sort u => u.hasMVar + | .bvar _ + | .fvar _ + | .mvar _ + | .lit _ => false + | .mdata _ e => e.hasLevelMVar' + | .proj _ _ e => e.hasLevelMVar' + | .app e1 e2 + | .lam _ e1 e2 _ + | .forallE _ e1 e2 _ => e1.hasLevelMVar' || e2.hasLevelMVar' + | .letE _ t v b _ => t.hasLevelMVar' || v.hasLevelMVar' || b.hasLevelMVar' + +/-- The cached `hasLevelMVar` bit agrees with structural traversal. -/ +@[simp] theorem hasLevelMVar_eq (e : Expr) : e.hasLevelMVar = e.hasLevelMVar' := by + change e.data.hasLevelMVar = e.hasLevelMVar' + induction e with + | bvar => simp [Expr.data, hasLevelMVar', mkData_hasLevelMVar_of_false] + | fvar | mvar | sort | const | lit => + simp only [Expr.data, hasLevelMVar'] + apply mkData_hasLevelMVar + omega + | app _ _ ih1 ih2 => + simp only [Expr.data, hasLevelMVar'] + rw [mkAppData_hasLevelMVar, ih1, ih2] + | lam _ ty body _ ihty ihbody | forallE _ ty body _ ihty ihbody => + simp only [Expr.data, mkDataForBinder, hasLevelMVar'] + rw [mkData_hasLevelMVar (binder_looseBVarRange_le ty body), ihty, ihbody] + | letE _ ty val body _ ihty ihval ihbody => + simp only [Expr.data, mkDataForLet, hasLevelMVar'] + rw [mkData_hasLevelMVar (let_looseBVarRange_le ty val body), ihty, ihval, ihbody] + | mdata _ e ih | proj _ _ e ih => + simp only [Expr.data, hasLevelMVar'] + rw [mkData_hasLevelMVar (Data.looseBVarRange_le (d := e.data)), ih] + +def hasLevelParam' : Expr → Bool + | .const _ ls => ls.any (·.hasParam) + | .sort u => u.hasParam + | .bvar _ + | .fvar _ + | .mvar _ + | .lit _ => false + | .mdata _ e => e.hasLevelParam' + | .proj _ _ e => e.hasLevelParam' + | .app e1 e2 + | .lam _ e1 e2 _ + | .forallE _ e1 e2 _ => e1.hasLevelParam' || e2.hasLevelParam' + | .letE _ t v b _ => t.hasLevelParam' || v.hasLevelParam' || b.hasLevelParam' + +/-- The cached `hasLevelParam` bit agrees with structural traversal. -/ +@[simp] theorem hasLevelParam_eq (e : Expr) : e.hasLevelParam = e.hasLevelParam' := by + change e.data.hasLevelParam = e.hasLevelParam' + induction e with + | bvar => simp [Expr.data, hasLevelParam', mkData_hasLevelParam_of_false] + | fvar | mvar | sort | const | lit => + simp only [Expr.data, hasLevelParam'] + apply mkData_hasLevelParam + omega + | app _ _ ih1 ih2 => + simp only [Expr.data, hasLevelParam'] + rw [mkAppData_hasLevelParam, ih1, ih2] + | lam _ ty body _ ihty ihbody | forallE _ ty body _ ihty ihbody => + simp only [Expr.data, mkDataForBinder, hasLevelParam'] + rw [mkData_hasLevelParam (binder_looseBVarRange_le ty body), ihty, ihbody] + | letE _ ty val body _ ihty ihval ihbody => + simp only [Expr.data, mkDataForLet, hasLevelParam'] + rw [mkData_hasLevelParam (let_looseBVarRange_le ty val body), ihty, ihval, ihbody] + | mdata _ e ih | proj _ _ e ih => + simp only [Expr.data, hasLevelParam'] + rw [mkData_hasLevelParam (Data.looseBVarRange_le (d := e.data)), ih] + +end Expr + +namespace Literal +open Expr in +theorem toConstructor_hasLevelParam : + (Literal.toConstructor l).hasLevelParam' = false := by + cases l with simp [Literal.toConstructor] + | natVal n => cases n <;> simp [natLitToConstructor, hasLevelParam', natZero, natSucc] + | strVal s => + simp [strLitToConstructor, hasLevelParam'] + induction s.toList <;> simp_all [hasLevelParam', Level.hasParam'] + +protected theorem beq_iff_eq {m n : Literal} : m == n ↔ m = n := by + cases m <;> cases n <;> simp! [(· == ·)] + +instance : LawfulBEq Literal where + eq_of_beq := Literal.beq_iff_eq.1 + rfl := Literal.beq_iff_eq.2 rfl + +instance : DecidableEq Literal := + fun a b => if h : a == b then .isTrue (by simp_all) else .isFalse (by simp_all) + +@[simp] theorem mkConst_typeName {l : Literal} : .const l.typeName [] = l.type := by + cases l <;> simp [typeName, type, mkConst] + +end Literal + +namespace Expr + +attribute [simp] mkConst mkBVar mkSort mkFVar mkMVar mkMData mkProj mkApp mkLambda mkForall mkLet + updateApp! updateFVar! updateConst! updateSort! updateMData! updateProj! + updateForall! updateForallE! updateLambda! updateLambdaE! updateLetE! updateLet! + +set_option allowUnsafeReducibility true +attribute [local reducible] Data + +theorem mkData_looseBVarRange (H : br ≤ 2^20 - 1) : + (mkData h br d fv ev lv lp).looseBVarRange.toNat = br := by + rw [mkData_eq, mkData', if_pos H]; dsimp only [Data.looseBVarRange, -Nat.reducePow] + have : br.toUInt64.toUInt32.toNat = br := by simp; omega + refine .trans ?_ this; congr 2 + refine UInt64.eq_of_toBitVec_eq ?_ + have : br.toUInt64.toNat = br := by simp; omega + have : br.toUInt64.toBitVec ≤ 0xfffff#64 := (this ▸ H :) + have : h.toUInt32.toUInt64.toBitVec ≤ 0xffffffff#64 := + show h.toUInt32.toNat ≤ 2^32-1 by simp; omega + have : (if d > 255 then 255 else d.toUInt8).toUInt64.toBitVec ≤ 0xff#64 := + Nat.le_of_lt_succ (if d > 255 then 255 else d.toUInt8).1.1.2 + have hb : ∀ (b : Bool), b.toUInt64.toBitVec ≤ 1#64 := by decide + have := hb fv; have := hb ev; have := hb lv; have := hb lp + change + (h.toUInt32.toUInt64.toBitVec + + (if d > 255 then 255 else d.toUInt8).toUInt64.toBitVec <<< 32#64 + + fv.toUInt64.toBitVec <<< 40#64 + + ev.toUInt64.toBitVec <<< 41#64 + + lv.toUInt64.toBitVec <<< 42#64 + + lp.toUInt64.toBitVec <<< 43#64 + + br.toUInt64.toBitVec <<< 44#64) >>> 44#64 = + br.toUInt64.toBitVec + bv_decide + +theorem looseBVarRange_le : looseBVarRange e ≤ 2^20 - 1 := Data.looseBVarRange_le + +theorem _root_.UInt32.max_toNat (a b : UInt32) : (max a b).toNat = max a.toNat b.toNat := by + simp +instances only [instMaxUInt32, maxOfLe, UInt32.le_iff_toNat_le, Nat.instMax]; split <;> rfl + +theorem mkAppData_looseBVarRange : + (mkAppData fData aData).looseBVarRange = max fData.looseBVarRange aData.looseBVarRange := by + have hm : max fData.looseBVarRange aData.looseBVarRange ≤ (Nat.pow 2 20 - 1).toUInt32 := by + dsimp +instances [instMaxUInt32, maxOfLe]; split <;> exact Data.looseBVarRange_le + rw [mkAppData_eq, mkAppData', if_pos hm] + simp [Data.looseBVarRange] at hm + dsimp only [Data.looseBVarRange, -Nat.reducePow] + generalize (max .. : UInt32) = m at * + have : m.toUInt64.toUInt32 = m := by simp [UInt64.toUInt32] + refine .trans ?_ this; congr 2 + generalize (ite (_ > (255 : UInt16)) _ _ : UInt8) = a + generalize HOr.hOr (α := UInt64) fData _ = b + generalize UInt64.toUInt32 _ = c + apply UInt64.eq_of_toBitVec_eq + change m.toUInt64.toBitVec ≤ 0xfffff#64 at hm + have : c.toUInt64.toBitVec ≤ 0xffffffff#64 := Nat.le_of_lt_succ c.1.1.2 + have : a.toUInt64.toBitVec ≤ 0xff#64 := Nat.le_of_lt_succ a.1.1.2 + change + (b.toBitVec &&& 15#64 <<< 40#64 ||| + c.toUInt64.toBitVec ||| + a.toUInt64.toBitVec <<< 32#64 ||| + m.toUInt64.toBitVec <<< 44#64) >>> 44#64 = + m.toUInt64.toBitVec + bv_decide + +def getAppArgsList : Expr → (r : List Expr := []) → List Expr + | .app f a, r => f.getAppArgsList (a :: r) + | _, r => r + +def getAppArgsRevList : Expr → List Expr + | .app f a => a :: f.getAppArgsRevList + | _ => [] + +theorem getAppArgsRevList_reverse : (getAppArgsRevList e).reverse = getAppArgsList e := by + let rec loop {e r} : getAppArgsList e r = (getAppArgsRevList e).reverse ++ r := by + unfold getAppArgsList getAppArgsRevList; split <;> simp; exact loop + simp [loop] + +theorem getAppArgsList_reverse : (getAppArgsList e).reverse = getAppArgsRevList e := by + rw [← getAppArgsRevList_reverse]; simp + +open private getAppNumArgsAux getAppArgsAux mkAppRangeAux from Lean.Expr + +theorem getAppNumArgs_eq : getAppNumArgs e = (getAppArgsRevList e).length := by + let rec loop e n : getAppNumArgsAux e n = (getAppArgsRevList e).length + n := by + unfold getAppNumArgsAux getAppArgsRevList; split <;> simp + rw [loop]; omega + rw [getAppNumArgs, loop]; rfl + +theorem getAppArgs_toList_rev : (getAppArgs e).toList = (getAppArgsRevList e).reverse := by + let rec loop {e l₁ l₂ args} (h1 : args.toList = l₁ ++ l₂) : + l₁.length = (getAppArgsRevList e).length → + (getAppArgsAux e args ((getAppArgsRevList e).length - 1)).toList = + (getAppArgsRevList e).reverse ++ l₂ := by + unfold getAppArgsAux getAppArgsRevList; split + · rename_i f a; intro h2 + obtain rfl | ⟨l₁, u, rfl⟩ := List.eq_nil_or_concat l₁; · cases h2 + simp at h2 ⊢; refine loop ?_ h2 + simp [← h2, h1] + · simp; rintro ⟨⟩; simpa using h1 + simp [getAppArgs, getAppNumArgs_eq] + exact (loop (List.append_nil _).symm (by simp)).trans (by simp) + +theorem getAppArgs_toList : (getAppArgs e).toList = getAppArgsList e := by + rw [getAppArgs_toList_rev, getAppArgsRevList_reverse] + +theorem getAppArgs_eq_rev : getAppArgs e = (getAppArgsRevList e).reverse.toArray := by + simp [← getAppArgs_toList_rev] + +theorem getAppArgs_eq : getAppArgs e = (getAppArgsList e).toArray := by + simp [← getAppArgs_toList] + +open private getAppRevArgsAux from Lean.Expr in +theorem getAppRevArgs_toList : (getAppRevArgs e).toList = getAppArgsRevList e := by + simp [getAppRevArgs, loop] +where + loop {e args} : (getAppRevArgsAux e args).toList = args.toList ++ getAppArgsRevList e := by + unfold getAppRevArgsAux getAppArgsRevList; split <;> [(rw [loop]; simp); simp] + +theorem getAppRevArgs_eq : getAppRevArgs e = (getAppArgsRevList e).toArray := by + simp [← getAppRevArgs_toList] + +@[simp] theorem withApp_eq {e : Expr} : e.withApp f = f e.getAppFn e.getAppArgs := loop where + loop {e arr n} : withAppAux f e arr n = f e.getAppFn (getAppArgsAux e arr n) := by + unfold withAppAux getAppArgsAux; split <;> [exact loop; simp [getAppFn]] + +open private withAppRevAux getAppRevArgsAux from Lean.Expr in +@[simp] theorem withRevApp_eq {e : Expr} : + e.withAppRev f = f e.getAppFn e.getAppRevArgs := loop where + loop {e arr} : withAppRevAux f e arr = f e.getAppFn (getAppRevArgsAux e arr) := by + unfold withAppRevAux getAppRevArgsAux; split <;> [exact loop; simp [getAppFn]] + +@[simp] def mkAppList : Expr → List Expr → Expr + | e, [] => e + | e, a :: as => mkAppList (.app e a) as + +theorem mkAppList_eq_foldl : mkAppList e es = es.foldl .app e := by + induction es generalizing e <;> simp [mkAppList, *] + +@[simp] theorem mkAppList_append : + mkAppList e (es₁ ++ es₂) = mkAppList (mkAppList e es₁) es₂ := by + simp [mkAppList_eq_foldl] + +@[simp] def mkAppRevList : Expr → List Expr → Expr + | e, [] => e + | e, a :: as => .app (mkAppRevList e as) a + +theorem mkAppRevList_eq_foldr : mkAppRevList e es = es.foldr (fun a e => .app e a) e := by + induction es <;> simp [mkAppRevList, *] + +@[simp] theorem mkAppRevList_append : + mkAppRevList e (es₁ ++ es₂) = mkAppRevList (mkAppRevList e es₂) es₁ := by + simp [mkAppRevList_eq_foldr] + +theorem mkAppList_reverse : mkAppList e es.reverse = mkAppRevList e es := by + simp [mkAppList_eq_foldl, mkAppRevList_eq_foldr] + +theorem mkAppRevList_reverse : mkAppRevList e es.reverse = mkAppList e es := by + simp [mkAppList_eq_foldl, mkAppRevList_eq_foldr] + +theorem mkAppRevList_getAppArgsRevList (e) : + mkAppRevList e.getAppFn (getAppArgsRevList e) = e := by + unfold getAppFn getAppArgsRevList; split <;> simp + congr 1; exact mkAppRevList_getAppArgsRevList _ + +theorem mkAppList_getAppArgsList (e) : + mkAppList e.getAppFn (getAppArgsList e) = e := by + rw [← mkAppRevList_reverse, getAppArgsList_reverse, mkAppRevList_getAppArgsRevList] + +theorem mkAppRange_eq (h1 : args.toList = l₁ ++ l₂ ++ l₃) + (h2 : l₁.length = i) (h3 : (l₁ ++ l₂).length = j) : + mkAppRange e i j args = mkAppList e l₂ := loop h1 h2 h3 where + loop {n i e l₁ l₂} (h1 : args.toList = l₁ ++ l₂ ++ l₃) + (h2 : l₁.length = i) (h3 : (l₁ ++ l₂).length = n) : + mkAppRangeAux n args i e = mkAppList e l₂ := by + rw [mkAppRangeAux.eq_def]; split + · simp [Array.getElem!_eq_getD, ← Array.getElem?_toList, h1] + obtain _ | ⟨a, l₂⟩ := l₂; · simp_all + rw [List.getElem?_append_right (by simp [h2])] + simp [h2] + rw [loop (l₁ := l₁ ++ [a]) (l₂ := l₂)] <;> simp [h1, h2, h3] + · simp at h3 + have : l₂.length = 0 := by omega + simp_all + +theorem mkAppRange_eq_rev (h1 : args.toList = l₁ ++ l₂ ++ l₃) + (h2 : l₁.length = i) (h3 : (l₁ ++ l₂).length = j) : + mkAppRange e i j args = mkAppRevList e l₂.reverse := by + rw [mkAppRange_eq h1 h2 h3, mkAppRevList_reverse] + +open private mkAppRevRangeAux from Lean.Expr in +theorem mkAppRevRange_eq(h1 : args.toList = l₁ ++ l₂ ++ l₃) + (h2 : l₁.length = i) (h3 : (l₁ ++ l₂).length = j) : + mkAppRevRange e i j args = mkAppList e l₂.reverse := by + unfold mkAppRevRange + simpa using loop l₁ l₂.reverse l₃ [] (by simpa using h1) h2 (by simpa using h3) +where + loop {start i} (l₁ l₂ l₃ l₄) (h1 : args.toList = l₁ ++ l₂.reverse ++ l₃) + (h2 : l₁.length = start) (h3 : l₁.length + List.length l₂ = i) : + mkAppRevRangeAux args start (mkAppRevList e l₄) i = mkAppList (mkAppRevList e l₄) l₂ := by + rw [mkAppRevRangeAux.eq_def]; split + · have : l₂.length = 0 := by omega + simp_all + · have : 0 < l₂.length := by omega + let a::l₂ := l₂; simp [← Nat.add_assoc] at h3 + let i+1 := i; simp at h3 + simp [Array.getElem!_eq_getD, ← Array.getElem?_toList, h1] + rw [List.getElem?_append_right (by omega)] + simp at h1; simp [← List.append_assoc] at h1 + simp [← h3]; rw [h3] + simpa using loop l₁ l₂ (a :: l₃) (a :: l₄) (by simp [h1]) h2 h3 + +theorem mkAppRevRange_eq_rev (h1 : args.toList = l₁ ++ l₂ ++ l₃) + (h2 : l₁.length = i) (h3 : (l₁ ++ l₂).length = j) : + mkAppRevRange e i j args = mkAppRevList e l₂ := by + rw [mkAppRevRange_eq h1 h2 h3, mkAppList_reverse] + +theorem liftLooseBVars_eq_self : e.looseBVarRange' ≤ s → liftLooseBVars' e s d = e := by + induction e generalizing s <;> + simp +contextual [*, looseBVarRange', liftLooseBVars', Nat.max_le] + omega + +@[simp] theorem liftLooseBVars_zero : liftLooseBVars' e s 0 = e := by + induction e generalizing s <;> simp [*, liftLooseBVars'] + +theorem liftLooseBVars_liftLooseBVars {e : Expr} {n1 n2 k1 k2 : Nat} + (h1 : k1 ≤ k2) (h2 : k2 ≤ n1 + k1) : + liftLooseBVars' (liftLooseBVars' e k1 n1) k2 n2 = liftLooseBVars' e k1 (n1+n2) := by + induction e generalizing k1 k2 with simp [liftLooseBVars', ← Nat.add_assoc, *] + | bvar i => + split <;> rename_i h + · rw [if_pos (Nat.lt_of_lt_of_le h h1)] + · rw [if_neg (by omega), Nat.add_assoc] + +theorem liftLooseBVars_add {e : Expr} {n1 n2 k : Nat} : + liftLooseBVars' (liftLooseBVars' e k n1) k n2 = liftLooseBVars' e k (n1+n2) := by + induction e generalizing k with simp [liftLooseBVars', *] + | bvar i => + split; · rfl + rw [if_neg (by omega), Nat.add_assoc] + +theorem liftLooseBVars_comm (e : Expr) (n1 n2 k1 k2 : Nat) (h : k2 ≤ k1) : + liftLooseBVars' (liftLooseBVars' e k1 n1) k2 n2 = + liftLooseBVars' (liftLooseBVars' e k2 n2) (n2+k1) n1 := by + induction e generalizing k1 k2 with + simp [liftLooseBVars', Nat.add_assoc, Nat.succ_le_succ, *] + | bvar i => + split <;> rename_i h' + · rw [if_pos (c := _ < n2 + k1)]; split + · exact Nat.lt_add_left _ h' + · omega + · have := mt (Nat.lt_of_lt_of_le · h) h' + rw [if_neg (by omega), if_neg this, if_neg (by omega), Nat.add_right_comm] + +theorem liftLooseBVars_looseBVarRange : + (liftLooseBVars' e k n).looseBVarRange' ≤ e.looseBVarRange' + n := by + induction e generalizing k <;> simp [*, looseBVarRange', liftLooseBVars'] <;> grind + +theorem instantiate1'_looseBVarRange + (he : e.looseBVarRange' ≤ n + k + 1) (ha : a.looseBVarRange' ≤ n) : + (instantiate1' e a k).looseBVarRange' ≤ n + k := by + induction e generalizing k with + simp_all [looseBVarRange', instantiate1', Nat.max_le] + | bvar => + split <;> [skip; split] <;> try simp [looseBVarRange'] at he ⊢; omega + have := @liftLooseBVars_looseBVarRange a 0 k; omega + | _ => grind + +theorem instantiateList_looseBVarRange + (he : e.looseBVarRange' ≤ n + k + as.length) (ha : ∀ a ∈ as, a.looseBVarRange' ≤ n) : + (instantiateList e as k).looseBVarRange' ≤ n + k := by + induction as generalizing e with simp_all | cons _ _ ih + apply ih; rw [Nat.add_right_comm]; apply instantiate1'_looseBVarRange <;> omega + +theorem instantiate1'_eq_self : e.looseBVarRange' ≤ k → instantiate1' e a k = e := by + induction e generalizing k <;> + simp +contextual [*, looseBVarRange', instantiate1', Nat.max_le] + omega + +theorem instantiate1_eq_self (H : e.looseBVarRange' = 0) : instantiate1' e a = e := by + simpa using instantiate1'_eq_self (e := e) (Nat.le_zero.2 H) + +theorem instantiateList'_eq_self (h : e.looseBVarRange' ≤ k) : instantiateList e as k = e := by + induction as <;> simp [instantiateList, instantiate1'_eq_self, *] + +theorem instantiateList_eq_self (h : e.looseBVarRange' = 0) : instantiateList e as = e := by + induction as <;> simp [instantiateList, instantiate1_eq_self, *] + +theorem instantiate1'_liftLooseBVars : + instantiate1' (liftLooseBVars' e s (d + 1)) a (s + d) = e.liftLooseBVars' s d := by + induction e generalizing s <;> + simp [*, instantiate1', liftLooseBVars', Nat.add_right_comm _ _ 1] + rename_i i; split; · simp; omega + · rw [if_neg (by omega), if_neg (by omega)]; rfl + +theorem instantiate1'_liftLooseBVars_0 (e1 e2 : Expr) : + instantiate1' (liftLooseBVars' e1 k 1) e2 k = e1 := by + simpa using (instantiate1'_liftLooseBVars (d := 0)).trans liftLooseBVars_zero + +theorem instantiate1'_instantiate1' (e1 e2 e3 j) : + instantiate1' (instantiate1' e1 e2 (j+1)) e3 j = + instantiate1' (instantiate1' e1 (e3.liftLooseBVars' 0 1) j) e2 j := by + induction e1 generalizing j with simp [instantiate1', *] | bvar i + split <;> rename_i h + · split <;> rename_i h1 + · simp [instantiate1', h1] + split <;> rename_i h1' + · subst i + simp [instantiate1']; rw [liftLooseBVars_comm (h := Nat.zero_le _)] + exact (instantiate1'_liftLooseBVars_0 ..).symm + · have hj := Nat.lt_of_le_of_ne (Nat.not_lt.1 h1) (Ne.symm h1') + let i+1 := i + simp [instantiate1', h1, h1', Nat.lt_of_succ_lt_succ h] + split <;> rename_i h' + · subst i + rw [if_neg (by omega), if_neg (by omega)] + simp [instantiate1'] + suffices liftLooseBVars' _ _ (j+1) = _ by + rw [this]; exact instantiate1'_liftLooseBVars_0 .. + exact (liftLooseBVars_liftLooseBVars (Nat.zero_le _) (Nat.le_refl _)).symm + · have hk := Nat.lt_of_le_of_ne (Nat.not_lt.1 h) (Ne.symm h') + let i+1 := i + have hk := Nat.lt_of_add_lt_add_right hk + simp [instantiate1'] + rw [if_neg (by omega), if_neg (by omega), if_neg (by omega), if_neg (by omega)] + simp [instantiate1'] + rw [if_neg (Nat.lt_asymm hk), if_neg (Nat.ne_of_gt hk)] + +@[simp] def instantiateRevList (e : Expr) : List Expr → (k :_:= 0) → Expr + | [], _ => e + | a :: as, k => instantiate1' (instantiateRevList e as k) a k + +theorem instantiateList_eq_foldl : + instantiateList e as k = as.foldl (instantiate1' · · k) e := by + induction as generalizing e <;> simp [*] + +theorem instantiateRevList_eq_foldr : + instantiateRevList e as k = as.foldr (fun a e => instantiate1' e a k) e := by + induction as <;> simp [*] + +theorem instantiateList_append : + instantiateList e (es₁ ++ es₂) k = instantiateList (instantiateList e es₁ k) es₂ k := by + simp [instantiateList_eq_foldl] + +theorem instantiateRevList_append : + instantiateRevList e (es₁ ++ es₂) k = + instantiateRevList (instantiateRevList e es₂ k) es₁ k := by + simp [instantiateRevList_eq_foldr] + +theorem instantiateList_reverse : + instantiateList e as.reverse k = instantiateRevList e as k := by + simp [instantiateList_eq_foldl, instantiateRevList_eq_foldr] + +theorem instantiateRevList_reverse : + instantiateRevList e as.reverse k = instantiateList e as k := by + simp [instantiateList_eq_foldl, instantiateRevList_eq_foldr] + +@[simp] +theorem instantiateRevList_lam : instantiateRevList (.lam n ty body bi) as k = + .lam n (instantiateRevList ty as k) (instantiateRevList body as (k + 1)) bi := by + induction as <;> simp [instantiate1', *] + +@[simp] +theorem instantiateList_lam : instantiateList (.lam n ty body bi) as k = + .lam n (instantiateList ty as k) (instantiateList body as (k + 1)) bi := by + simp [← instantiateRevList_reverse, instantiateRevList_lam] + +@[simp] +theorem instantiateRevList_app : instantiateRevList (.app f a) as k = + .app (instantiateRevList f as k) (instantiateRevList a as k) := by + induction as <;> simp [instantiate1', *] + +@[simp] +theorem instantiateList_app : instantiateList (.app f a) as k = + .app (instantiateList f as k) (instantiateList a as k) := by + simp [← instantiateRevList_reverse, instantiateRevList_app] + +@[simp] +theorem instantiateList_forallE : instantiateList (.forallE n ty body bi) as k = + .forallE n (instantiateList ty as k) (instantiateList body as (k + 1)) bi := by + induction as generalizing ty body <;> simp [instantiate1', *] + +@[simp] +theorem instantiateList_letE : instantiateList (.letE n ty val body nd) as k = + .letE n (instantiateList ty as k) (instantiateList val as k) + (instantiateList body as (k + 1)) nd := by + induction as generalizing ty val body <;> simp [instantiate1', *] + +theorem instantiateList_instantiate1_comm (h : a.looseBVarRange' = 0) : + (instantiateList e as 1).instantiate1' a = + instantiateList (e.instantiate1' a) as := by + induction as generalizing e <;> simp [*] + congr 1; refine (instantiate1'_instantiate1' (j := 0) ..).trans ?_ + rw [liftLooseBVars_eq_self (by simp [h])] + +theorem instantiateRev_push {e : Expr} {subst a} : + instantiateRev e (subst.push a) = instantiateRev (e.instantiate1' a) subst := by + let ⟨subst⟩ := subst; simp [instantiateList] + +theorem abstractList_eq_foldl {e : Expr} {as k} : + abstractList e as k = List.foldl (fun e a => abstract1 a e k) e as := by + induction as generalizing e <;> simp_all + +@[simp] def abstractRevList : Expr → List FVarId → (k :_:= 0) → Expr + | e, [], _ => e + | e, a :: as, k => abstract1 a (abstractRevList e as k) k + +theorem abstractRevList_eq_foldr {e : Expr} {as k} : + abstractRevList e as k = List.foldr (abstract1 · · k) e as := by + induction as <;> simp_all + +theorem abstractList_reverse {e : Expr} {as k} : + abstractList e as.reverse k = abstractRevList e as k := by + simp [abstractList_eq_foldl, abstractRevList_eq_foldr] + +theorem abstractRevList_reverse {e : Expr} {as k} : + abstractRevList e as.reverse k = abstractList e as k := by + simp [abstractList_eq_foldl, abstractRevList_eq_foldr] + +theorem abstractList_append {e : Expr} {as k} : + abstractList e (as ++ as') k = abstractList (abstractList e as k) as' k := by + simp [abstractList_eq_foldl] + +theorem abstract1_comm {e : Expr} {k} (h : a ≠ b) : + abstract1 a (abstract1 b e k) k = + abstract1 b (abstract1 a e k) (k+1) := by + induction e generalizing k with simp_all [abstract1] + | bvar => split <;> [rw [if_pos]; simp [*]] <;> omega + | fvar => split <;> split <;> simp_all [abstract1] + +theorem abstract1_abstractList {e : Expr} {as : List FVarId} {k} (H : a ∉ as) : + abstract1 a (abstractList e as k) k = + abstractList (abstract1 a e k) as (k+1) := by + induction as generalizing e <;> simp_all [abstract1_comm] + +theorem abstract1_abstractList' {e : Expr} {as : List FVarId} {k} (H : (a :: as).Nodup) : + abstract1 a (abstractList e as k) (k + as.length) = + abstractList (abstract1 a e k) as k := by + induction as generalizing e a with + | nil => simp + | cons b as ih => + simp at *; simp [H] at ih + rw [← ih H.2.1, ← Nat.add_assoc, ← abstract1_comm (.symm H.1.1), ih H.1.2, ih H.2.1] + +theorem abstract1_hasLooseBVar (a e k i) : + (abstract1 a e k).hasLooseBVar' (if i < k then i else i+1) = e.hasLooseBVar' i := by + have (i) k : (if i < k then i else i + 1) + 1 = if i + 1 < k + 1 then i + 1 else i + 1 + 1 := by + simp; split <;> rfl + induction e generalizing i k with simp only [hasLooseBVar', abstract1, *] + | bvar j => + by_cases h : j = i <;> simp [h] + split <;> split <;> omega + | fvar b => + split <;> simp [hasLooseBVar'] + split <;> omega + +theorem abstract1_eq_liftLooseBVars (h : (abstract1 a e k).hasLooseBVar' k = false) : + abstract1 a e k = liftLooseBVars' e k 1 := by + induction e generalizing k <;> grind [abstract1, hasLooseBVar', liftLooseBVars'] + +-- theorem abstract1_looseBVarRange_le : +-- (abstract1 a e k).looseBVarRange' ≤ max k e.looseBVarRange' + 1 := by +-- have H {k a b c d} (h1 : a ≤ max k c + 1) (h2 : b ≤ max k d + 1) : +-- max a b ≤ max k (max c d) + 1 := by +-- rw [Nat.max_le]; simp [Nat.max_def]; split <;> split <;> omega +-- have {k a b c d} (h1 : a ≤ max k c + 1) (h2 : b ≤ max (k+1) d + 1) : +-- max a (b - 1) ≤ max k (max c (d - 1)) + 1 := by apply H <;> omega +-- induction e generalizing k with simp [abstract1, looseBVarRange', *] <;> try solve_by_elim +-- | bvar => split <;> omega +-- | fvar => split <;> simp [looseBVarRange'] + +theorem lowerLooseBVars_eq_instantiate (h : e.hasLooseBVar' k = false) : + e.lowerLooseBVars' (k + 1) 1 = instantiate1' e v k := by + induction e generalizing k with simp_all [hasLooseBVar', lowerLooseBVars', instantiate1'] + | bvar j => split <;> [rw [if_pos (by omega)]; rw [if_neg (by omega)]] + +theorem hasLooseBVar_of_ge_looseBVarRange {e : Expr} (h : e.looseBVarRange' ≤ k) : + e.hasLooseBVar' k = false := by + induction e generalizing k with simp_all [hasLooseBVar', looseBVarRange', Nat.max_le] + | bvar j => omega + +theorem abstract1_lower {e : Expr} (h : e.hasLooseBVar' k₁ = false) (hk : k₁ ≤ k₂) : + Expr.abstract1 a (e.lowerLooseBVars' (k₁ + 1) 1) k₂ = + (Expr.abstract1 a e (k₂ + 1)).lowerLooseBVars' (k₁ + 1) 1 := by + induction e generalizing k₁ k₂ with simp_all [abstract1, lowerLooseBVars', hasLooseBVar'] + | bvar i => + split <;> [skip; split] + · rw [if_pos (c := i < k₂ + 1) (by omega), if_pos (by omega)]; simp [*] + · rw [if_pos (c := i < _) (by omega)]; simp [*] + · rw [if_neg (c := i < _) (by omega), if_neg (by omega)]; omega + | fvar b => + split <;> simp [lowerLooseBVars', -right_eq_ite_iff] + rw [if_neg (by omega)] + +variable (red : Bool) (s : Name → Level) in +def instantiateLevelParamsCore' : Expr → Expr + | .const c ls => .const c (ls.map (·.substParams' s red)) + | .sort u => .sort (u.substParams' s red) + | .mdata m e => .mdata m (instantiateLevelParamsCore' e) + | .proj n i e => .proj n i (instantiateLevelParamsCore' e) + | .app f a => .app (instantiateLevelParamsCore' f) (instantiateLevelParamsCore' a) + | .lam n t b bi => .lam n (instantiateLevelParamsCore' t) (instantiateLevelParamsCore' b) bi + | .forallE n t b bi => + .forallE n (instantiateLevelParamsCore' t) (instantiateLevelParamsCore' b) bi + | .letE n t v b bi => .letE n (instantiateLevelParamsCore' t) + (instantiateLevelParamsCore' v) (instantiateLevelParamsCore' b) bi + | e@(.bvar _) + | e@(.fvar _) + | e@(.mvar _) + | e@(.lit _) => e + +theorem instantiateLevelParamsCore_eq_self (h : e.hasLevelParam' = false) : + instantiateLevelParamsCore' red s e = e := by + induction e <;> simp_all [instantiateLevelParamsCore', hasLevelParam', Level.substParams_eq_self] + exact List.map_id''' _ fun _ h' => Level.substParams_eq_self (h _ h') + +theorem instantiateLevelParamsCore_id {e : Expr} : + instantiateLevelParamsCore' false .param e = e := by + induction e <;> simp_all [instantiateLevelParamsCore', Level.substParams_id] + +open private instantiateLevelParamsCore.replaceFn from Lean.Util.InstantiateLevelParams in +theorem instantiateLevelParamsCore_eq : + instantiateLevelParamsCore s e = + instantiateLevelParamsCore' true (fun x => (s x).getD (.param x)) e := by + simp [instantiateLevelParamsCore] + have (e) (H : e.hasLevelParam' = true → + replaceNoCache (instantiateLevelParamsCore.replaceFn s) e = + instantiateLevelParamsCore' true (fun x => (s x).getD (Level.param x)) e) : + replaceNoCache (instantiateLevelParamsCore.replaceFn s) e = + instantiateLevelParamsCore' true (fun x => (s x).getD (Level.param x)) e := by + cases eq : e.hasLevelParam' <;> [skip; exact H eq] + rw [instantiateLevelParamsCore_eq_self eq] + suffices ∀ f, f e = some e → replaceNoCache f e = e by + apply this; simp [instantiateLevelParamsCore.replaceFn, eq] + intro f eq; cases e <;> simp only [replaceNoCache, eq] + induction e <;> ( + refine this _ fun h => ?_ + simp only [replaceNoCache, instantiateLevelParamsCore.replaceFn] + simp [h]; clear this h + simp_all [instantiateLevelParamsCore']) + +open private getParamSubst from Lean.Util.InstantiateLevelParams in +theorem instantiateLevelParams_eq {e ps ls} : + instantiateLevelParams e ps ls = + instantiateLevelParamsCore' (!ps.isEmpty && !ls.isEmpty) + (fun x => ((ps.idxOf? x).bind (ls[·]?)).getD (.param x)) e := by + simp only [instantiateLevelParams]; rw [← Bool.not_or]; + cases eq : ps.isEmpty || ls.isEmpty <;> simp + · clear eq + simp [instantiateLevelParamsCore_eq, List.idxOf?]; congr; ext n; congr + induction ps generalizing ls <;> cases ls <;> simp [getParamSubst] + split <;> simp [*, List.findIdx?_cons]; cases List.findIdx? .. <;> simp + · refine instantiateLevelParamsCore_id.symm.trans ?_; congr; ext n + cases ps <;> simp_all + +theorem eqv_sort {e : Expr} : e == .sort u ↔ e = .sort u := by + conv => lhs; simp [(· == ·)] + cases e <;> simp [eqv'] + +theorem eqv_const {e : Expr} : e == .const c ls ↔ e = .const c ls := by + conv => lhs; simp [(· == ·)] + cases e <;> simp [eqv'] + +theorem structuralEq_const {e : Expr} : + structuralEq e (.const c ls) = true ↔ e = .const c ls := by + cases e <;> simp [structuralEq] + +theorem structuralEq_refl (e : Expr) : structuralEq e e = true := by + induction e <;> simp [structuralEq, *] + +/-- Transparent structural equality implies Lean's non-strict expression +equivalence. This direction deliberately does not identify binder names or +binder information, which `Expr.eqv` also ignores. -/ +theorem structuralEq_eqv {a b : Expr} : + structuralEq a b = true → a == b := by + simp only [(· == ·)] + induction a generalizing b <;> cases b <;> + simp_all [structuralEq, eqv'] + +theorem eqv_refl (e : Expr) : e == e := by + simp [(· == ·)]; induction e <;> simp [eqv', *] + +theorem eqv_euc {e₁ e₂ e₃ : Expr} : e₁ == e₂ → e₁ == e₃ → e₂ == e₃ := by + simp [(· == ·)] + induction e₁ generalizing e₂ e₃ + all_goals + cases e₂ <;> try change false = _ → _; rintro ⟨⟩ + simp [eqv']; intros; subst_vars; try simp [*] + all_goals + revert ‹Expr.eqv' .. = _› + cases e₃ <;> try change false = _ → _; rintro ⟨⟩ + simp +contextual [eqv', *] + simp [BEq.congr_left ‹_›] + +instance : EquivBEq Expr where + symm h := eqv_euc h (eqv_refl _) + trans h1 h2 := eqv_euc (eqv_euc h1 (eqv_refl _)) h2 + rfl := eqv_refl _ + +theorem data_eq {e₁ e₂ : Expr} : e₁ == e₂ → e₁.data = e₂.data := by + simp [(· == ·)]; induction e₁ generalizing e₂ + all_goals + cases e₂ <;> try change false = _ → _; rintro ⟨⟩ + simp [eqv']; intros; subst_vars; try simp [*] + all_goals simp [Expr.data]; grind + +instance : LawfulHashable Expr where + hash_eq e₁ e₂ h := by simp [hash, Expr.hash, data_eq h] + +theorem instantiate1_eqv {e₁ e₂ : Expr} : + e₁ == e₂ → e₁.instantiate1' a k == e₂.instantiate1' a k := by + simp [(· == ·)]; induction e₁ generalizing e₂ k + all_goals + cases e₂ <;> try change false = _ → _; rintro ⟨⟩ + simp [instantiate1', eqv'] + all_goals intros; subst_vars; try simp [*] + split <;> [skip; split] <;> simpa [(· == ·)] using eqv_refl _ + +theorem instantiateList_eqv {e₁ e₂ : Expr} (h : e₁ == e₂) : + e₁.instantiateList as k == e₂.instantiateList as k := by + induction as generalizing e₁ e₂ <;> simp [instantiate1_eqv, *] diff --git a/Ix/Theory/Named/Verify/Level.lean b/Ix/Theory/Named/Verify/Level.lean new file mode 100644 index 000000000..8373b4f29 --- /dev/null +++ b/Ix/Theory/Named/Verify/Level.lean @@ -0,0 +1,3916 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.VLevel +import Ix.Theory.Named.Reference.Level +import Ix.Theory.Named.Verify.Name +import Ix.Theory.Named.Verify.LevelStd +import Ix.Theory.Named.Verify.Axioms +import Std.Tactic.BVDecide +import Std.Data.TreeMap.Lemmas + +open Ix.Theory (VLevel) + +namespace Lean + +namespace Level +open Ix.Theory.Named + +attribute [simp] mkLevelSucc mkLevelMax mkLevelIMax updateSucc! updateMax! updateIMax! + +-- variable (ls : List Name) in +-- def _root_.Ix.Theory.VLevel.toLevel : VLevel → Level +-- | .zero => .zero +-- | .succ l => .succ l.toLevel +-- | .max l₁ l₂ => .max l₁.toLevel l₂.toLevel +-- | .imax l₁ l₂ => .imax l₁.toLevel l₂.toLevel +-- | .param n => match ls.get? n with +-- | some l => .param l +-- | none => .zero + +-- theorem toLevel_inj {ls : List Name} (d : ls.Nodup) +-- {l₁ l₂ : VLevel} (eq : l₁.toLevel ls = l₂.toLevel ls) : l₁ = l₂ := sorry + +@[simp] def getOffset' : Level → Nat + | succ u => getOffset' u + 1 + | _ => 0 + +@[simp] theorem getOffset_eq (u : Level) : u.getOffset = u.getOffset' := go _ 0 where + go (u : Level) (i) : u.getOffsetAux i = u.getOffset' + i := by + unfold getOffsetAux getOffset'; split <;> simp + rw [go]; simp [Nat.add_right_comm, Nat.add_assoc] + +set_option allowUnsafeReducibility true +attribute [local reducible] Data + +theorem mkData_depth (H : d < 2 ^ 24) : (mkData h d hmv hp).depth.toNat = d := by + rw [mkData_eq, mkData', if_neg (Nat.not_lt.2 (Nat.le_sub_one_of_lt H)), Data.depth] + have : d.toUInt64.toUInt32.toNat = d := by simp; omega + refine .trans ?_ this; congr 2 + rw [← UInt64.toBitVec_inj] + have : d.toUInt64.toNat = d := by simp; omega + have : d.toUInt64.toBitVec ≤ 0xffffff#64 := (this ▸ Nat.le_sub_one_of_lt H :) + have : h.toUInt32.toUInt64.toBitVec ≤ 0xffffffff#64 := Nat.le_of_lt_succ h.toUInt32.1.1.2 + have hb : ∀ (b : Bool), b.toUInt64.toBitVec ≤ 1#64 := by decide + have := hb hmv; have := hb hp + change ( + h.toUInt32.toUInt64.toBitVec + + hmv.toUInt64.toBitVec <<< 32#64 + + hp.toUInt64.toBitVec <<< 33#64 + + d.toUInt64.toBitVec <<< 40#64) >>> 40#64 = d.toUInt64.toBitVec + bv_decide + +theorem mkData_hasParam (H : d < 2 ^ 24) : (mkData h d hmv hp).hasParam = hp := by + rw [mkData_eq, mkData', if_neg (Nat.not_lt.2 (Nat.le_sub_one_of_lt H))] + simp [Data.hasParam, (· == ·), ← UInt64.toBitVec_inj] + have : h.toUInt32.toUInt64.toBitVec ≤ 0xffffffff#64 := Nat.le_of_lt_succ h.toUInt32.1.1.2 + have hb : ∀ (b : Bool), b.toUInt64.toBitVec ≤ 1#64 := by decide + have := hb hmv; have := hb hp + let L := (( + h.toUInt32.toUInt64.toBitVec + + hmv.toUInt64.toBitVec <<< 32#64 + + hp.toUInt64.toBitVec <<< 33#64 + + d.toUInt64.toBitVec <<< 40#64) >>> 33#64) &&& 1#64 + change decide (L = 1#64) = hp + rw [show L = hp.toUInt64.toBitVec by bv_decide] + cases hp <;> decide + +theorem mkData_hasMVar (H : d < 2 ^ 24) : (mkData h d hmv hp).hasMVar = hmv := by + rw [mkData_eq, mkData', if_neg (Nat.not_lt.2 (Nat.le_sub_one_of_lt H))] + simp [Data.hasMVar, (· == ·), ← UInt64.toBitVec_inj] + have : h.toUInt32.toUInt64.toBitVec ≤ 0xffffffff#64 := Nat.le_of_lt_succ h.toUInt32.1.1.2 + have hb : ∀ (b : Bool), b.toUInt64.toBitVec ≤ 1#64 := by decide + have := hb hmv; have := hb hp + let L := (( + h.toUInt32.toUInt64.toBitVec + + hmv.toUInt64.toBitVec <<< 32#64 + + hp.toUInt64.toBitVec <<< 33#64 + + d.toUInt64.toBitVec <<< 40#64) >>> 32#64) &&& 1#64 + change decide (L = 1#64) = hmv + rw [show L = hmv.toUInt64.toBitVec by bv_decide] + cases hmv <;> decide + +theorem ofLevel_of_not_hasParam (Us) {l : Level} + (hl : l.hasParam' = false) (hmv : l.hasMVar' = false) : + ∃ u', VLevel.ofLevel Us l = some u' := by + induction l <;> simp_all [hasParam', hasMVar', VLevel.ofLevel, exists_comm] + +def getUndefParam.F (ps : List Name) (l : Level) : StateT (Option Name) Id Bool := do + if !l.hasParam || (← get).isSome then + return false + if let .param n := l then + if n ∉ ps then + set (some n) + return true + +theorem getUndefParam_none {l : Level} (hmv : l.hasMVar' = false) : + l.getUndefParam Us = none → ∃ u', VLevel.ofLevel Us l = some u' := by + suffices ∀ s, ((l.forEach (getUndefParam.F Us)).run s).run.snd = none → s = none ∧ _ from + (this _ · |>.2) + have {l} (hmv : l.hasMVar' = false) {g} + (H : ∀ {s'}, (g.run s').run.snd = none → s' = none ∧ + (((getUndefParam.F Us l).run none).run = (true, none) → + ∃ u', VLevel.ofLevel Us l = some u')) (s) : + ((do if !(← getUndefParam.F Us l) then pure () else g) |>.run s).run.snd = none → + s = none ∧ ∃ u', VLevel.ofLevel Us l = some u' := by + simp; split <;> rename_i h + · simp; revert h + simp [getUndefParam.F]; split <;> [simp; split <;> [split <;> simp; simp]] + rintro rfl; simp at * + exact ofLevel_of_not_hasParam Us ‹_› hmv + · refine fun h' => let ⟨h1, h2⟩ := H h'; have := ?_; ⟨this, h2 ?_⟩ + · revert h h1 + simp [getUndefParam.F]; split <;> [simp; split <;> [split <;> simp; simp]] + · revert h h1; subst s + cases (getUndefParam.F Us l).run none; simp; rintro rfl rfl; rfl + have lt {n a} : n + 1 < a → n < a := by omega + induction l with ( + refine this hmv fun h => ?_; clear this + simp [hasMVar', VLevel.ofLevel, *] at *) + | succ _ ih => + have ⟨h, _, h1⟩ := ih hmv _ h + exact ⟨h, fun _ => ⟨_, _, h1, rfl⟩⟩ + | max _ _ ih1 ih2 | imax _ _ ih1 ih2 => + have ⟨h, _, h2⟩ := ih2 hmv.2 _ h + have ⟨h, _, h1⟩ := ih1 hmv.1 _ h + exact ⟨h, fun _ => ⟨_, _, h1, _, h2, rfl⟩⟩ + | param => + simp [getUndefParam.F, hasParam', List.idxOf_lt_length_iff, *] + split <;> simp [*] + | _ => simp [*] + +variable (s : Name → Level) in +def substParams' (red : Bool) : Level → Level + | .zero => .zero + | .succ v => .succ (substParams' (v.hasParam ∧ red) v) + | .max v₁ v₂ => + let red := (v₁.hasParam ∨ v₂.hasParam) ∧ red + (if red then mkLevelMax' else .max) (substParams' red v₁) (substParams' red v₂) + | .imax v₁ v₂ => + let red := (v₁.hasParam ∨ v₂.hasParam) ∧ red + (if red then mkLevelIMax' else .imax) (substParams' red v₁) (substParams' red v₂) + | .param n => s n + | u => u + +theorem substParams_eq_self {u : Level} (h : u.hasParam' = false) : + substParams' s red u = u := by + induction u generalizing red <;> simp_all [substParams', hasParam'] + +open private substParams.go from Lean.Level in +@[simp] theorem substParams_eq (u : Level) (s : Name → Option Level) : + substParams u s = substParams' (fun x => (s x).getD (.param x)) true u := by + unfold substParams + induction u <;> simp [substParams.go, substParams', hasParam', ← Bool.or_eq_true] <;> + split <;> simp [*, substParams_eq_self] <;> simp_all [substParams_eq_self] + +theorem substParams_id {u : Level} : + substParams' .param false u = u := by induction u <;> simp_all [substParams'] + +local notation "max'" => Max.max + +namespace Normalize + +attribute [local instance] Lean.Level.Normalize.namedOrdName + +local instance : Std.TransCmp (α := Name) compare := inferInstanceAs (Std.TransCmp Name.cmp) +local instance : Std.LawfulBEqCmp (α := Name) compare := + inferInstanceAs (Std.LawfulBEqCmp Name.cmp) +local instance : Std.LawfulBEqCmp (α := List Name) compare := + inferInstanceAs (Std.LawfulBEqCmp (List.compareLex Name.cmp)) + +instance : LawfulBEq VarNode where + rfl {a} := by cases a <;> simp! +instances [instBEqVarNode] + eq_of_beq {a b} := by cases a <;> cases b <;> simp! +instances [instBEqVarNode] + +@[reducible] local instance : Membership (List Name) NormLevel := + inferInstanceAs (Membership _ (Std.TreeMap _ _ compare)) + +@[reducible] local instance : GetElem? NormLevel (List Name) Node (fun m a => a ∈ m) := + inferInstanceAs (GetElem? (Std.TreeMap _ _ compare) ..) + +inductive Extend1 : List α → α → List α → Prop + | mk : Extend1 (l₁ ++ l₂) v (l₁ ++ v :: l₂) + +theorem Extend1.base : Extend1 l v (v::l) := .mk (l₁ := []) +theorem Extend1.cons (H : Extend1 l v l') : Extend1 (a::l) v (a::l') := + let .mk := H; .mk (l₁ := _::_) + +theorem Extend1.mem (H : Extend1 p a p') : b ∈ p' ↔ b = a ∨ b ∈ p := by cases H; simp [or_left_comm] + +theorem Extend1.length (H : Extend1 p a p') : p'.length = p.length + 1 := by + cases H; simp [Nat.add_assoc] + +theorem Extend1.of_mem (h : a ∈ p') : ∃ p, Extend1 p a p' := by + obtain ⟨_, _, rfl, _⟩ := List.eq_append_cons_of_mem h; exact ⟨_, .mk⟩ + +theorem Extend1.orderedInsert (H : orderedInsert cmp v p = some p') : Extend1 p v p' := by + induction p generalizing p' with simp [Normalize.orderedInsert] at H + | nil => exact H ▸ .base + | cons _ _ ih => + split at H <;> [(cases H; exact .base); cases H; skip] + simp at H; obtain ⟨_, H, rfl⟩ := H; exact (ih H).cons + +inductive Extend? : List α → α → List α → Prop + | mk1 : Extend1 l v l' → Extend? l v l' + | mk0 : v ∈ l → Extend? l v l + +theorem Extend?.cons (H : Extend? l v l') : Extend? (a::l) v (a::l') := by + cases H with + | mk1 H => exact .mk1 H.cons + | mk0 H => exact .mk0 (.tail _ H) + +theorem Extend?.mem (H : Extend? p a p') : b ∈ p' ↔ b = a ∨ b ∈ p := by + cases H with + | mk1 H => exact H.mem + | mk0 H => simp; rintro rfl; exact H + +theorem Extend?.orderedInsert [BEq α] [LawfulBEq α] [Std.LawfulBEqCmp (α := α) cmp] : + Extend? p v ((orderedInsert cmp v p).getD p) := by + induction p with simp [Normalize.orderedInsert] + | nil => exact .mk1 .base + | cons _ _ ih => + split + · exact .mk1 .base + · simp_all; exact .mk0 (.head _) + · revert ih; cases Normalize.orderedInsert .. <;> exact .cons + +section +variable (ls : List Name) (ρ : List Nat) in +def evalParam (x : Name) : Nat := + let i := ls.idxOf x; if i < ls.length then ρ[i]?.getD 0 else 0 + +theorem evalParam_eq (hv : ls.idxOf x < ls.length) : + evalParam ls ρ x = ρ[List.idxOf x ls]?.getD 0 := if_pos hv + +variable (ls : List Name) (ρ : List Nat) in +def VarNode.eval (l : VarNode) : Nat := evalParam ls ρ l.var + l.offset + +variable (ls : List Name) (ρ : List Nat) in +def Node.eval (l : Node) : Nat := + l.var.foldl (init := l.const) fun n v => max' n (v.eval ls ρ) + +theorem Node.eval_le : eval ls ρ l ≤ n ↔ + l.const ≤ n ∧ ∀ v ∈ l.var, v.eval ls ρ ≤ n := by + simp [eval, ← List.foldr_reverse]; simp only [← l.var.mem_reverse] + induction l.var.reverse with simp | cons a l + simp [Nat.max_le, and_comm, and_left_comm, *] + +variable (ls : List Name) (ρ : List Nat) in +def allNZ (path : List Name) : Bool := path.all (0 < evalParam ls ρ ·) + +theorem allNZ_cons : allNZ ls ρ (a :: path) ↔ + 0 < evalParam ls ρ a ∧ allNZ ls ρ path := by simp [allNZ] + +theorem allNZ_mono (H : ∀ x ∈ path, x ∈ path') : allNZ ls ρ path' → allNZ ls ρ path := by + simp [allNZ]; grind + +variable (ls : List Name) (ρ : List Nat) in +def evalPath (path : List Name) (n : Nat) : Nat := + if allNZ ls ρ path then n else 0 + +theorem evalPath_cons : evalPath ls ρ (a :: path) n = + evalPath ls ρ path (if 0 < evalParam ls ρ a then n else 0) := by + by_cases h : 0 < evalParam ls ρ a <;> simp [evalPath, allNZ_cons, h] + +theorem evalPath_max : + evalPath ls ρ path (max' m n) = max' (evalPath ls ρ path m) (evalPath ls ρ path n) := by + simp [evalPath]; split <;> simp + +theorem evalPath_mono (h : n ≤ m) : + evalPath ls ρ path n ≤ evalPath ls ρ path m := by + simp [evalPath]; split <;> simp [*] + +theorem evalPath_le : evalPath ls ρ path n ≤ m ↔ (allNZ ls ρ path → n ≤ m) := by + simp [evalPath]; split <;> simp [*] + +variable (ls : List Name) (ρ : List Nat) in +def NormLevel.eval (l : NormLevel) : Nat := + l.foldl (init := 0) fun n a b => max' n (evalPath ls ρ a (b.eval ls ρ)) + +theorem NormLevel.eval_le : eval ls ρ l ≤ n ↔ + ∀ a b, l.get? a = some b → evalPath ls ρ a (b.eval ls ρ) ≤ n := by + simp [eval, Std.TreeMap.foldl_eq_foldl_toList, ← List.foldr_reverse] + simp only [← Std.TreeMap.mem_toList_iff_getElem?_eq_some, ← l.toList.mem_reverse] + induction l.toList.reverse with simp | cons a l; let (a, b) := a + simp [or_imp, forall_and, Nat.max_le, and_comm, *] + +end + +theorem NormLevel.addVar_contains (H : acc.contains x) : (addVar v k path acc).contains x := by + simp_all [addVar, Std.TreeMap.mem_modify] + +theorem NormLevel.addNode_contains (H : acc.contains x) : (addNode v k path acc).contains x := by + simp [addNode, Std.TreeMap.mem_alter] at *; split <;> simp [*] + +theorem NormLevel.addNode_contains_self : (addNode v k path acc).contains path := by + simp [addNode]; split <;> simp + +theorem NormLevel.addConst_contains (H : acc.contains x) : (addConst k path acc).contains x := by + simp [addConst] at *; split <;> simp [H, Std.TreeMap.mem_alter]; split <;> simp + +theorem NormLevel.addConst_contains_self (h : k ≠ 0) (h2 : ¬(k = 1 ∧ path ≠ [])) : + (addConst k path acc).contains path := by + simp [addConst, h, h2]; split <;> simp + +theorem normalizeAux_contains (H : acc.contains x) : (normalizeAux u path k acc).contains x := by + unfold normalizeAux; split + · exact NormLevel.addConst_contains H + · exact NormLevel.addConst_contains H + · exact normalizeAux_contains H + · exact normalizeAux_contains (normalizeAux_contains H) + · exact normalizeAux_contains (normalizeAux_contains H) + · exact normalizeAux_contains (normalizeAux_contains H) + · exact normalizeAux_contains (normalizeAux_contains H) + · split <;> [skip; (dsimp; split)] + · exact normalizeAux_contains (NormLevel.addNode_contains (NormLevel.addConst_contains H)) + · exact normalizeAux_contains H + · exact normalizeAux_contains (NormLevel.addVar_contains H) + · exact H + · exact H + · split <;> [skip; split] + · exact NormLevel.addNode_contains (NormLevel.addConst_contains H) + · exact H + · exact NormLevel.addVar_contains H + +theorem imax_max : Lean.Nat.imax a (max' b c) = max' (Lean.Nat.imax a b) (Lean.Nat.imax a c) := by + simp [Lean.Nat.imax]; symm; split <;> simp [*]; split <;> simp [*, Nat.max_eq_max] + rw [Nat.max_left_comm b, ← Nat.max_assoc, Nat.max_self] + +theorem imax_imax : Lean.Nat.imax a (Lean.Nat.imax b c) = + max' (Lean.Nat.imax a c) (Lean.Nat.imax b c) := by + simp [Lean.Nat.imax]; by_cases h : c = 0 <;> simp [*, Nat.max_eq_max] + rw [Nat.max_left_comm c, Nat.max_self] + +protected theorem Extend?.allNZ (H : Extend? p a p') : allNZ ls ρ p' = allNZ ls ρ (a :: p) := by + rw [Bool.eq_iff_iff]; simp [allNZ, H.mem] + +protected theorem Extend?.evalPath (H : Extend? p a p') : + evalPath ls ρ p' = evalPath ls ρ (a :: p) := by ext n; simp [evalPath, H.allNZ] + +theorem ext_le {n m : Nat} (H : ∀ x, n ≤ x ↔ m ≤ x) : n = m := + Nat.le_antisymm ((H _).2 (Nat.le_refl _)) ((H _).1 (Nat.le_refl _)) + +theorem le_ext_le {n m : Nat} (H : ∀ x, n ≤ x → m ≤ x) : m ≤ n := H _ (Nat.le_refl _) + +/-- Condition sets are strictly sorted, which is what makes `subset` a decision procedure +for inclusion: it is built up by `orderedInsert` from the empty set. -/ +def Sorted (l : List Name) : Prop := l.Pairwise (compare · · = .lt) + +nonrec theorem Sorted.nil : Sorted [] := .nil + +theorem Sorted.of_cons (h : Sorted (a :: l)) : Sorted l := (List.pairwise_cons.1 h).2 + +theorem Sorted.head (h : Sorted (a :: l)) : ∀ b ∈ l, compare a b = .lt := + (List.pairwise_cons.1 h).1 + +theorem Sorted.erase (h : Sorted l) : Sorted (l.erase a) := h.sublist (List.erase_sublist ..) + +theorem Sorted.nodup (h : Sorted l) : l.Nodup := + h.imp <| by rintro _ _ hab rfl; rw [Std.ReflOrd.compare_self] at hab; cases hab + +theorem Sorted.orderedInsert (h : Sorted l) (he : orderedInsert Name.cmp a l = some l') : + Sorted l' := by + induction l generalizing l' with | nil => cases he; exact .cons (by simp) .nil | cons b l ih + simp only [Normalize.orderedInsert] at he + split at he <;> rename_i hab + · cases he + refine .cons (fun c hc => ?_) h + obtain rfl | hc := List.mem_cons.1 hc + · exact hab + · exact Std.TransCmp.lt_trans hab (h.head _ hc) + · cases he + · simp only [Option.map_eq_some_iff] at he + obtain ⟨l'', he, rfl⟩ := he + refine .cons (fun c hc => ?_) (ih h.of_cons he) + -- `c` is either `a`, which is above `b`, or an element of `l` + obtain rfl | hc := (Extend1.orderedInsert he).mem.1 hc + · exact Std.OrientedCmp.lt_of_gt hab + · exact h.head _ hc + +/-- The well-formedness invariant of the `NormLevel` maps produced by `normalizeAux`: +every variable recorded at a key is an element of that key, and every nonempty key `p` +extends another key of the map by a single variable that is recorded at `p`. +The latter is what makes the sublevels expressible by `imax` chains (see the reconstruction +comment in `Ix.Theory.Named.Level`), and it lets `addConst` drop `C(p, 1)` for `p ≠ []`. -/ +def NormLevel.WF (s : NormLevel) : Prop := + ∀ p n, s.get? p = some n → + (p ≠ [] → ∃ v p', Extend1 p' v p ∧ (p' = [] ∨ s.contains p') ∧ ∃ x ∈ n.var, x.var = v) ∧ + (∀ v ∈ n.var, v.var ∈ p) ∧ Sorted p + +theorem NormLevel.WF.of_mem (hm : v ∈ path) (H : WF s) (hp : s.contains path) : + ∃ path₁ path₂ n, (∀ x ∈ path₁, x ∈ path) ∧ + Extend1 path₁ v path₂ ∧ (path₁ = [] ∨ s.contains path₁) ∧ s.get? path₂ = some n ∧ + ∃ x ∈ n.var, x.var = v := by + generalize eq : path.length = n + induction n generalizing path with | zero => simp at eq; subst path; cases hm | succ n ih + have ⟨_, hp'⟩ := Option.isSome_iff_exists.1 (Std.TreeMap.isSome_getElem?_eq_contains.trans hp) + have ⟨_, _, a1, a2, a3⟩ := (H _ _ hp').1 (by rintro rfl; cases hm) + obtain rfl | hm := a1.mem.1 hm + · exact ⟨_, _, _, fun _ h => a1.mem.2 (.inr h), a1, a2, hp', a3⟩ + · -- the parent is in the map, since `v` occurs in it and so it is not the root + have ⟨_, _, _, b1, b2⟩ := ih hm (a2.resolve_left (by rintro rfl; cases hm)) + (by cases a1; simp at eq ⊢; exact Nat.succ_inj.1 eq) + exact ⟨_, _, _, fun _ h => a1.mem.2 (.inr (b1 _ h)), b2⟩ + +theorem NormLevel.WF.sortedOf {s : NormLevel} (wf : s.WF) (H : path = [] ∨ s.contains path) : + Sorted path := by + obtain rfl | h := H + · exact Sorted.nil + · obtain ⟨n, hn⟩ := Option.isSome_iff_exists.1 (Std.TreeMap.isSome_getElem?_eq_contains.trans h) + exact (wf _ _ hn).2.2 + +theorem VarNode.mem_addVar : + (∃ x ∈ VarNode.addVar v k l, x.var = u) ↔ v = u ∨ (∃ x ∈ l, x.var = u) := by + induction l with simp [addVar] | cons x l ih; split <;> simp_all [or_left_comm] + +theorem NormLevel.addVar_wf (hv : v ∈ path) (wf : acc.WF) : + (addVar v k path acc).WF := by + simp [addVar, WF, Std.TreeMap.getElem?_modify, Std.TreeMap.mem_modify] at wf ⊢ + intro p n; split <;> [simp; apply wf] + subst p; rintro _ h rfl; have ⟨a1, a2, a3⟩ := wf _ _ h + refine ⟨fun h => ?_, fun _ h => ?_, a3⟩ + · have ⟨_, _, b1, b2, b3⟩ := a1 h; exact ⟨_, _, b1, b2, VarNode.mem_addVar.2 (.inr b3)⟩ + · obtain eq | ⟨_, h, eq⟩ := VarNode.mem_addVar.1 ⟨_, h, rfl⟩ + · exact eq ▸ hv + · exact eq ▸ a2 _ h + +theorem NormLevel.addNode_wf (H : Extend1 path v path') (hs : Sorted path') + (hacc : path = [] ∨ acc.contains path) (wf : acc.WF) : (addNode v k path' acc).WF := by + simp [addNode, WF, Std.TreeMap.getElem?_alter, Std.TreeMap.mem_alter] at * + intro p n; split + · subst p; split <;> rintro ⟨⟩ <;> simp + · exact ⟨fun _ => ⟨_, _, H, hacc.imp id fun h _ => h, rfl⟩, H.mem.2 (.inl rfl), hs⟩ + · obtain ⟨a1, a2, a3⟩ := wf _ _ ‹_›; refine ⟨fun h => ?_, fun _ h => ?_, a3⟩ + · have ⟨_, _, b1, b2, b3⟩ := a1 h + exact ⟨_, _, b1, b2.imp id fun h _ => h, VarNode.mem_addVar.2 (.inr b3)⟩ + · obtain eq | ⟨_, h, eq⟩ := VarNode.mem_addVar.1 ⟨_, h, rfl⟩ + · exact H.mem.2 (.inl eq.symm) + · exact eq ▸ a2 _ h + · intro h; have ⟨a1, a2, a3⟩ := wf _ _ h; refine ⟨fun h => ?_, a2, a3⟩ + have ⟨_, _, b1, b2, b3⟩ := a1 h; refine ⟨_, _, b1, ?_, b3⟩ + split <;> [split <;> simp; exact b2] + +/-- `WF` survives an update that only adds keys and preserves each node's variables, provided +any key it adds is the root, where the parent condition is vacuous. -/ +theorem NormLevel.WF.update {s s' : NormLevel} (wf : s.WF) + (hk : ∀ q, s.contains q → s'.contains q) + (hv : ∀ p n, s'.get? p = some n → + (∃ n₀, s.get? p = some n₀ ∧ n.var = n₀.var) ∨ (p = [] ∧ n.var = [])) : s'.WF := by + intro p n hn + rcases hv p n hn with ⟨n₀, h₀, hvar⟩ | ⟨rfl, hvar⟩ + · obtain ⟨a1, a2, a3⟩ := wf _ _ h₀ + refine ⟨fun h => ?_, fun v hv => a2 v (hvar ▸ hv), a3⟩ + obtain ⟨v, p', b1, b2, b3⟩ := a1 h + exact ⟨v, p', b1, b2.imp id (hk _), hvar ▸ b3⟩ + · exact ⟨absurd rfl, by simp [hvar], Sorted.nil⟩ + +theorem NormLevel.addConst_wf (hp : path = [] ∨ acc.contains path) (H : acc.WF) : + (addConst k path acc).WF := by + simp only [addConst]; split <;> [exact H; skip] + refine H.update (fun q hq => ?_) fun p n hn => ?_ + · rw [Std.TreeMap.contains_alter]; split <;> [split <;> simp; simp [hq]] + · rw [Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_alter] at hn + split at hn <;> [rename_i hpe; exact .inl ⟨n, hn, rfl⟩] + cases eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 hpe) + -- `alter` creates a node only at the root, since otherwise `path` is already a key + match hpath : acc[path]?, hp with + | some n', _ => rw [hpath] at hn; cases hn; exact .inl ⟨n', hpath, rfl⟩ + | none, .inl hr => rw [hpath] at hn; cases hn; exact .inr ⟨hr, rfl⟩ + | none, .inr h => simp [Std.TreeMap.mem_iff_isSome_getElem?, hpath] at h + +theorem normalizeAux_wf (H : path = [] ∨ acc.contains path) (wf : acc.WF) : + (normalizeAux u path k acc).WF := by + unfold normalizeAux; split + · exact NormLevel.addConst_wf H wf + · exact NormLevel.addConst_wf H wf + · exact normalizeAux_wf H wf + · exact normalizeAux_wf (H.imp id normalizeAux_contains) (normalizeAux_wf H wf) + · exact normalizeAux_wf (H.imp id normalizeAux_contains) (normalizeAux_wf H wf) + · exact normalizeAux_wf (H.imp id normalizeAux_contains) (normalizeAux_wf H wf) + · exact normalizeAux_wf (H.imp id normalizeAux_contains) (normalizeAux_wf H wf) + · split <;> rename_i eq <;> [skip; (dsimp; split)] + · exact normalizeAux_wf (.inr NormLevel.addNode_contains_self) + (NormLevel.addNode_wf (.orderedInsert eq) ((wf.sortedOf H).orderedInsert eq) + (H.imp id NormLevel.addConst_contains) (NormLevel.addConst_wf H wf)) + · exact normalizeAux_wf H wf + · refine normalizeAux_wf (H.imp id NormLevel.addVar_contains) (NormLevel.addVar_wf ?_ wf) + exact (eq ▸ Extend?.orderedInsert).mem.2 (.inl rfl) + · exact wf + · exact wf + · split <;> rename_i eq <;> [skip; split] + · exact NormLevel.addNode_wf (.orderedInsert eq) ((wf.sortedOf H).orderedInsert eq) + (H.imp id NormLevel.addConst_contains) (NormLevel.addConst_wf H wf) + · exact wf + · exact NormLevel.addVar_wf ((eq ▸ Extend?.orderedInsert).mem.2 (.inl rfl)) wf + +theorem NormLevel.addConst_eval (H : path = [] ∨ acc.contains path) (wf : acc.WF) : + (addConst k path acc).eval ls ρ = max' (acc.eval ls ρ) (evalPath ls ρ path k) := by + simp [addConst]; split <;> rename_i h + · obtain rfl | ⟨rfl, hne⟩ := h + · simp [evalPath] + · -- `C(p, 1)` for `p ≠ []` is already dominated: `WF` puts a variable of `p` at `p`, + -- and along a nonzero path that variable is at least 1 + rw [Nat.max_eq_left]; refine evalPath_le.2 fun nz => le_ext_le fun n le => ?_ + have H := H.resolve_left hne + rw [← Std.TreeMap.isSome_getElem?_eq_contains, Option.isSome_iff_exists] at H + let ⟨v, H⟩ := H; have ⟨_, _, a1, a2, _, a3, rfl⟩ := (wf _ _ H).1 ‹_› + have := (Node.eval_le.1 (evalPath_le.1 (eval_le.1 le _ _ H) nz)).2 _ a3 + simp [allNZ] at nz + exact Nat.le_trans (nz _ (a1.mem.2 (.inl rfl))) (Nat.le_of_add_right_le this) + · refine ext_le fun x => ?_ + simp [eval_le, Nat.max_le, Std.TreeMap.getElem?_alter, evalPath_le, Node.eval_le] + refine ⟨fun H => ⟨fun a b h nz => ?_, fun nz => ?_⟩, fun ⟨H1, H2⟩ a b h nz => ?_⟩ + · have := H a; split at this + · subst a; rw [h] at this + obtain ⟨hc, hv⟩ := this _ rfl nz + exact ⟨Nat.le_trans (Nat.le_max_right ..) hc, hv⟩ + · exact this _ h nz + · have := H path; rw [if_pos rfl] at this; split at this <;> + refine Nat.le_trans ?_ ((this _ rfl nz).1) + · exact Nat.le_refl _ + · exact Nat.le_max_left .. + · split at h + · subst a; split at h <;> cases h <;> [exact ⟨H2 nz, by simp⟩; rename_i n hn] + obtain ⟨hc, hv⟩ := H1 _ _ hn nz + exact ⟨Nat.max_le.2 ⟨H2 nz, hc⟩, hv⟩ + · exact H1 _ _ h nz + +theorem VarNode.addVar_le : (∀ vn ∈ VarNode.addVar v k l, vn.eval ls ρ ≤ x) ↔ + evalParam ls ρ v + k ≤ x ∧ (∀ vn ∈ l, vn.eval ls ρ ≤ x) := by + simp [eval]; induction l with simp [VarNode.addVar] | cons vn l ih; split <;> simp [*] + · simp at *; subst v + rw [← and_assoc, ← Nat.max_le, Nat.add_max_add_left, Nat.max_comm, Nat.max_eq_max] + · rw [and_left_comm] + +theorem NormLevel.addNode_eval : (addNode v k path acc).eval ls ρ = + max' (acc.eval ls ρ) (evalPath ls ρ path (evalParam ls ρ v + k)) := by + refine ext_le fun x => ?_ + simp [addNode, eval_le, Std.TreeMap.getElem?_alter, evalPath_le, Node.eval_le, Nat.max_le] + refine ⟨fun H => ⟨fun a b h nz => ?_, fun nz => ?_⟩, fun ⟨H1, H2⟩ a b h nz => ?_⟩ + · have := H a; split at this + · subst a; simp_all [VarNode.addVar_le] + · exact this _ h nz + · have := H path; simp at this; split at this <;> specialize this _ rfl nz + · simp_all [VarNode.eval] + · simp_all [VarNode.addVar_le] + · split at h + · subst a; split at h <;> cases h + · simp_all [VarNode.eval] + · simp_all [VarNode.addVar_le]; grind + · grind + +theorem NormLevel.addVar_eval (H : acc.contains path) : (addVar v k path acc).eval ls ρ = + max' (acc.eval ls ρ) (evalPath ls ρ path (evalParam ls ρ v + k)) := by + refine ext_le fun x => ?_ + rw [← Std.TreeMap.isSome_getElem?_eq_contains, Option.isSome_iff_exists] at H; let ⟨v, H⟩ := H + simp [addVar, eval_le, Nat.max_le, Std.TreeMap.getElem?_modify, evalPath_le, Node.eval_le, H] + refine ⟨fun H => ⟨fun a b h nz => ?_, fun nz => ?_⟩, fun ⟨H1, H2⟩ a b h nz => ?_⟩ + · have := H a; split at this + · subst a; simp_all [VarNode.addVar_le] + · exact this _ h nz + · have := H path; simp at this; specialize this nz; simp_all [VarNode.addVar_le] + · split at h + · subst a; cases h; simp_all [VarNode.addVar_le]; grind + · grind + +/-- The invariant threaded through `normalizeAux`: the current path is either the root, which +`addConst` creates on demand, or already a key of the map, created by an earlier `addNode`. +`addVar` is only reached in the second case, since it runs only when `path` already contains +the variable being added. -/ +theorem normalizeAux_eval (hu : VLevel.ofLevel ls u = some u') + (H : path = [] ∨ acc.contains path) (wf : acc.WF) : + (normalizeAux u path k acc).eval ls ρ = + max' (acc.eval ls ρ) (evalPath ls ρ path (u'.eval ρ + k)) := by + unfold normalizeAux; split + · cases hu; simp [NormLevel.addConst_eval H wf, VLevel.eval] + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, rfl⟩ := hu + simp [VLevel.eval, Lean.Nat.imax, NormLevel.addConst_eval H wf] + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, rfl⟩ := hu + rw [normalizeAux_eval hu H wf, Nat.add_succ, ← Nat.succ_add]; rfl + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, hv, rfl⟩ := hu + rw [normalizeAux_eval hv (H.imp id normalizeAux_contains) (normalizeAux_wf H wf), + normalizeAux_eval hu H wf, Nat.max_assoc, ← evalPath_max, Nat.add_max_add_right]; rfl + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨_, hv, rfl⟩, rfl⟩ := hu + rw [normalizeAux_eval hv (H.imp id normalizeAux_contains) (normalizeAux_wf H wf), + normalizeAux_eval hu H wf, Nat.max_assoc, Nat.add_succ, ← Nat.succ_add, + ← evalPath_max, Nat.add_max_add_right]; rfl + · rename_i u v w + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨_, hv, _, hw, rfl⟩, rfl⟩ := hu + rw [normalizeAux_eval (by simpa [VLevel.ofLevel] using ⟨_, hu, _, hw, rfl⟩) + (H.imp id normalizeAux_contains) (normalizeAux_wf H wf), + normalizeAux_eval (by simpa [VLevel.ofLevel] using ⟨_, hu, _, hv, rfl⟩) H wf, + Nat.max_assoc, ← evalPath_max, Nat.add_max_add_right]; simp [VLevel.eval, imax_max] + · rename_i u v w + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨_, hv, _, hw, rfl⟩, rfl⟩ := hu + rw [normalizeAux_eval (by simpa [VLevel.ofLevel] using ⟨_, hv, _, hw, rfl⟩) + (H.imp id normalizeAux_contains) (normalizeAux_wf H wf), + normalizeAux_eval (by simpa [VLevel.ofLevel] using ⟨_, hu, _, hw, rfl⟩) H wf, + Nat.max_assoc, ← evalPath_max, Nat.add_max_add_right]; simp [VLevel.eval, imax_imax] + · rename_i u v + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨hv, rfl⟩, rfl⟩ := hu + have := Extend?.orderedInsert (cmp := Name.cmp) (p := path) (v := v) + split <;> rename_i h <;> simp [h] at this + · rw [normalizeAux_eval hu (.inr NormLevel.addNode_contains_self) + (NormLevel.addNode_wf (.orderedInsert h) ((wf.sortedOf H).orderedInsert h) + (H.imp id NormLevel.addConst_contains) (NormLevel.addConst_wf H wf)), + NormLevel.addNode_eval, NormLevel.addConst_eval H wf, Nat.max_assoc, + Nat.max_assoc, ← evalPath_max, this.evalPath, evalPath_cons, ← evalPath_max, + Nat.add_max_add_right]; congr 2 + simp [VLevel.eval, ← evalParam_eq hv, Lean.Nat.imax] + cases evalParam .. <;> simp [Nat.max_eq_max, Nat.max_comm] + · have hne : path ≠ [] := by rintro rfl; simp [orderedInsert] at h + dsimp; split + · rw [normalizeAux_eval hu H wf] + simp [evalPath]; split <;> [rename_i nz; simp] + have hm := this.mem.2 (.inl rfl) + obtain ⟨p1, p2, w1, a1, a2, a3, a4, z, a5, rfl⟩ := wf.of_mem hm (H.resolve_left hne) + refine ext_le fun n => ?_; simp [Nat.max_le, NormLevel.eval_le]; intro he + have := Node.eval_le.1 (evalPath_le.1 (he _ _ a4) + (allNZ_mono (fun _ h => (a2.mem.1 h).elim (· ▸ hm) (a1 _)) nz)) |>.2 _ a5 + simp [allNZ] at nz; specialize nz _ hm + simp [VLevel.eval, Lean.Nat.imax]; simp [← evalParam_eq hv, VarNode.eval] at this ⊢ + revert this nz; cases evalParam .. <;> simp [Nat.max_eq_max]; omega + · rw [normalizeAux_eval hu (H.imp id NormLevel.addVar_contains) + (NormLevel.addVar_wf (this.mem.2 (.inl rfl)) wf), + NormLevel.addVar_eval (H.resolve_left hne), Nat.max_assoc, ← evalPath_max, Nat.add_max_add_right, + this.evalPath, evalPath_cons, evalPath_cons]; congr 2 + split <;> simp [VLevel.eval, Lean.Nat.imax] + rename_i h; revert h; simp [← evalParam_eq hv] + cases evalParam .. <;> simp [Nat.max_eq_max, Nat.max_comm] + · cases hu + · simp [VLevel.ofLevel] at hu + · rename_i v; simp [VLevel.ofLevel] at hu; obtain ⟨hv, rfl⟩ := hu + have := Extend?.orderedInsert (cmp := Name.cmp) (p := path) (v := v) + split <;> rename_i h <;> simp [h] at this + · rw [NormLevel.addNode_eval, NormLevel.addConst_eval H wf, Nat.max_assoc, + this.evalPath, evalPath_cons, ← evalPath_max] + simp [VLevel.eval, ← evalParam_eq hv]; congr 2; split <;> simp; omega + have hne : path ≠ [] := by rintro rfl; simp [orderedInsert] at h + split + · simp [evalPath]; split <;> [rename_i nz; simp] + have hm := this.mem.2 (.inl rfl) + obtain ⟨p1, p2, w1, a1, a2, a3, a4, z, a5, rfl⟩ := wf.of_mem hm (H.resolve_left hne) + refine ext_le fun n => ?_; simp [Nat.max_le, NormLevel.eval_le]; intro he + have := Node.eval_le.1 (evalPath_le.1 (he _ _ a4) + (allNZ_mono (fun _ h => (a2.mem.1 h).elim (· ▸ hm) (a1 _)) nz)) |>.2 _ a5 + simp [allNZ] at nz; specialize nz _ hm + simp [VLevel.eval]; simp [← evalParam_eq hv, VarNode.eval] at this ⊢ + revert this nz; cases evalParam .. <;> simp; omega + · rw [NormLevel.addVar_eval (H.resolve_left hne), this.evalPath, evalPath_cons, + evalPath_cons] + congr 2; split <;> simp [VLevel.eval, ← evalParam_eq hv] + +theorem subset_length (H : subset cmp l₁ l₂) : l₁.length ≤ l₂.length := by + induction l₂ generalizing l₁ with | nil => cases l₁ <;> simp_all [subset] | cons y l₂ ih + cases l₁ with | nil => simp | cons x l₁ + simp only [subset] at H; split at H + · cases H + · have := ih H; simp only [List.length_cons]; omega + · have := ih H; simp only [List.length_cons] at this ⊢; omega + +theorem subset_mem [BEq α] [LawfulBEq α] [Std.LawfulBEqCmp (α := α) cmp] + (H : subset cmp l₁ l₂) (h : a ∈ l₁) : a ∈ l₂ := by + induction l₂ generalizing l₁ with | nil => cases l₁ <;> simp_all [subset] | cons y l₂ ih + cases l₁ with| nil => cases h | cons x l₁ + simp only [subset] at H; split at H + · cases H + · rename_i h'; rw [Std.LawfulBEqCmp.compare_eq_iff_beq] at h' + cases eq_of_beq h' + rcases List.mem_cons.1 h with rfl | h + · exact .head _ + · exact .tail _ (ih H h) + · exact .tail _ (ih H h) + +theorem subset_eq [BEq α] [LawfulBEq α] [Std.LawfulBEqCmp (α := α) cmp] + (H : subset cmp l₁ l₂) (hl : l₁.length = l₂.length) : l₁ = l₂ := by + induction l₂ generalizing l₁ with | nil => cases l₁ <;> simp_all [subset] | cons y l₂ ih + cases l₁ with | nil => cases hl | cons x l₁ + simp only [subset] at H; simp only [List.length_cons] at hl + split at H + · cases H + · rename_i h'; rw [Std.LawfulBEqCmp.compare_eq_iff_beq] at h' + cases eq_of_beq h'; rw [ih H (by omega)] + · exact absurd (subset_length H) (by simp only [List.length_cons]; omega) + +/-- On sorted lists, `subset` decides inclusion. -/ +theorem subset_of_sorted (h₁ : Sorted l₁) (h₂ : Sorted l₂) (h : ∀ x ∈ l₁, x ∈ l₂) : + subset compare l₁ l₂ := by + induction l₂ generalizing l₁ with + | nil => cases l₁ with | nil => rfl | cons x l₁ => cases h x (.head _) + | cons y l₂ ih + cases l₁ with | nil => rfl | cons x l₁ + simp only [subset] + have hxy := h x (.head _) + split <;> rename_i hc + · -- `x < y` is impossible: `x` is in `y :: l₂`, whose elements are all `≥ y` + obtain rfl | hx := List.mem_cons.1 hxy + · rw [Std.ReflOrd.compare_self] at hc; cases hc + · exact absurd (h₂.head _ hx) (by rw [Std.OrientedCmp.gt_of_lt hc]; simp) + · rw [Std.LawfulBEqCmp.compare_eq_iff_beq] at hc + cases eq_of_beq hc + refine ih h₁.of_cons h₂.of_cons fun z hz => ?_ + obtain rfl | hz' := List.mem_cons.1 (h z (.tail _ hz)) + · exact absurd (h₁.head _ hz) (by rw [Std.ReflOrd.compare_self]; simp) + · exact hz' + · refine ih h₁ h₂.of_cons fun z hz => ?_ + obtain rfl | hz' := List.mem_cons.1 (h z hz) + · obtain rfl | hz := List.mem_cons.1 hz + · exact absurd hc (by rw [Std.ReflOrd.compare_self]; simp) + · exact absurd (h₁.head _ hz) (by + rw [Std.OrientedCmp.gt_of_lt (Std.OrientedCmp.lt_of_gt hc)]; simp) + · exact hz' + +theorem subsumeVars_subset (h : x ∈ subsumeVars vs₁ vs₂) : x ∈ vs₁ := by + induction vs₁ generalizing vs₂ with | nil => simp_all [subsumeVars] | cons a vs₁ ih + induction vs₂ with | nil => simp_all [subsumeVars] | cons b vs₂ ih₂ + simp only [subsumeVars] at h; split at h + · obtain rfl | h := List.mem_cons.1 h + · exact .head _ + · exact .tail _ (ih h) + · split at h <;> [exact .tail _ (ih h); skip] + obtain rfl | h := List.mem_cons.1 h + · exact .head _ + · exact .tail _ (ih h) + · exact ih₂ h + +theorem subsumeVars_dominated (h₁ : x ∈ vs₁) (h₂ : x ∉ subsumeVars vs₁ vs₂) : + ∃ y ∈ vs₂, y.var = x.var ∧ x.offset ≤ y.offset := by + induction vs₁ generalizing vs₂ with | nil => cases h₁ | cons a vs₁ ih + induction vs₂ with | nil => exact absurd h₁ (by simpa [subsumeVars] using h₂) | cons b vs₂ ih₂ + simp only [subsumeVars] at h₂; split at h₂ + · obtain rfl | h₁ := List.mem_cons.1 h₁ + · cases h₂ (.head _) + · have ⟨y, hy, e, le⟩ := ih h₁ fun h => h₂ (.tail _ h) + exact ⟨y, hy, e, le⟩ + · rename_i heq; split at h₂ + · obtain rfl | h₁ := List.mem_cons.1 h₁ + · rw [Std.LawfulBEqCmp.compare_eq_iff_beq] at heq + exact ⟨b, .head _, (eq_of_beq heq).symm, ‹_›⟩ + · have ⟨y, hy, e, le⟩ := ih h₁ h₂ + exact ⟨y, .tail _ hy, e, le⟩ + · obtain rfl | h₁ := List.mem_cons.1 h₁ + · cases h₂ (.head _) + · have ⟨y, hy, e, le⟩ := ih h₁ fun h => h₂ (.tail _ h) + exact ⟨y, .tail _ hy, e, le⟩ + · have ⟨y, hy, e, le⟩ := ih₂ h₂ + exact ⟨y, .tail _ hy, e, le⟩ + +theorem le_foldl_max {vs : List VarNode} + (h : c ≤ vs.foldl (·.max ·.offset) n + 1) : c ≤ n + 1 ∨ ∃ y ∈ vs, c ≤ y.offset + 1 := by + induction vs generalizing n with | nil => exact .inl h | cons x vs ih + obtain h | ⟨y, hy, h⟩ := ih h + · refine (Nat.le_total x.offset n).imp (fun h' => ?_) (fun h' => ⟨x, .head _, ?_⟩) + · simp [Nat.max_eq_left h'] at h; omega + · simp [Nat.max_eq_right h'] at h; omega + · exact .inr ⟨y, .tail _ hy, h⟩ + +theorem Node.const_le_eval {l : Node} : l.const ≤ Node.eval ls ρ l := + (Node.eval_le.1 (Nat.le_refl _)).1 + +theorem Node.var_le_eval {l : Node} (h : x ∈ l.var) : + VarNode.eval ls ρ x ≤ Node.eval ls ρ l := + (Node.eval_le.1 (Nat.le_refl _)).2 _ h + +theorem Node.eval_empty {l : Node} (H : l.isEmpty) : Node.eval ls ρ l = 0 := by + simp [Node.isEmpty] at H; simp [eval, H.1, H.2] + +theorem NormLevel.eval_filter {m : NormLevel} : + NormLevel.eval ls ρ (m.filter fun _ n => !n.isEmpty) = m.eval ls ρ := by + refine ext_le fun x => ?_ + simp only [eval_le, Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_filter] + refine ⟨fun H a b h => ?_, fun H a b h => ?_⟩ + · by_cases he : b.isEmpty + · simp [evalPath_le, Node.eval_empty he] + · exact H a b (by simp [h, he]) + · exact H _ _ (Option.eq_some_of_pfilter_eq_some h) + +theorem subsumeVars_eval (H : ∀ v ∈ vs₂, VarNode.eval ls ρ v ≤ n) : + (∀ v ∈ subsumeVars vs₁ vs₂, VarNode.eval ls ρ v ≤ n) ↔ + ∀ v ∈ vs₁, VarNode.eval ls ρ v ≤ n := by + refine ⟨fun h v hv => ?_, fun h v hv => h _ (subsumeVars_subset hv)⟩ + by_cases hs : v ∈ subsumeVars vs₁ vs₂ <;> [exact h _ hs; skip] + have ⟨y, hy, e, le⟩ := subsumeVars_dominated hv hs + exact Nat.le_trans (by simp [VarNode.eval, e]; omega) (H _ hy) + +theorem Node.subsumeBy_const_eq {same : Bool} {n₁ n₂ : Node} : + (n₁.subsumeBy same n₂).const = + if n₁.const = 0 || + (same || n₁.const > n₂.const) && + (n₂.var.isEmpty || n₁.const > n₂.var.foldl (·.max ·.offset) 0 + 1) + then n₁.const else 0 := by + simp only [Node.subsumeBy]; split <;> split <;> rfl + +theorem Node.subsumeBy_var_eq {same : Bool} {n₁ n₂ : Node} : + (n₁.subsumeBy same n₂).var = + if same || n₂.var.isEmpty then n₁.var else subsumeVars n₁.var n₂.var := by + simp only [Node.subsumeBy]; split <;> split <;> simp + +theorem Node.subsumeBy_var_subset {same : Bool} + (h : x ∈ (Node.subsumeBy same n₁ n₂).var) : x ∈ n₁.var := by + rw [Node.subsumeBy_var_eq] at h; split at h <;> [exact h; exact subsumeVars_subset h] + +theorem Node.subsumeBy_const_cases {same : Bool} (n₁ n₂ : Node) : + (n₁.subsumeBy same n₂).const = n₁.const ∨ (n₁.subsumeBy same n₂).const = 0 := by + rw [Node.subsumeBy_const_eq]; split <;> [exact .inl rfl; exact .inr rfl] + +theorem Node.subsumeBy_eval_le {same : Bool} : + Node.eval ls ρ (n₁.subsumeBy same n₂) ≤ Node.eval ls ρ n₁ := by + refine Node.eval_le.2 ⟨?_, fun v h => Node.var_le_eval (Node.subsumeBy_var_subset h)⟩ + obtain h | h := Node.subsumeBy_const_cases (same := same) n₁ n₂ + · exact h ▸ Node.const_le_eval + · simp [h] + +/-- If `subsumeBy` dropped the constant, the drop was justified: the constant is dominated +by the constant of `n₂` (only possible when the two keys differ), or by a variable of `n₂`. -/ +theorem Node.subsumeBy_const_drop {same : Bool} + (h : (Node.subsumeBy same n₁ n₂).const ≠ n₁.const) : + same = false ∧ n₁.const ≤ n₂.const ∨ ∃ y ∈ n₂.var, n₁.const ≤ y.offset + 1 := by + rw [Node.subsumeBy_const_eq] at h + split at h <;> [cases h rfl; rename_i hc] + rw [Bool.or_eq_true, not_or] at hc + obtain ⟨-, hc⟩ := hc + rw [Bool.and_eq_true, Decidable.not_and_iff_not_or_not] at hc + obtain hc | hc := hc <;> rw [Bool.or_eq_true, not_or] at hc <;> obtain ⟨h1, h2⟩ := hc + · exact .inl ⟨by simpa using h1, by simpa [Nat.not_lt] using h2⟩ + · have hne : n₂.var ≠ [] := fun e => h1 (by simp [e]) + have h2 : n₁.const ≤ n₂.var.foldl (·.max ·.offset) 0 + 1 := by + simpa [Nat.not_lt] using h2 + obtain h | h := le_foldl_max (c := n₁.const) (n := 0) h2 + · obtain ⟨y, hy⟩ := List.exists_mem_of_ne_nil _ hne + exact .inr ⟨y, hy, by omega⟩ + · exact .inr h + +/-- The domination step is exact against a node bounded by `m`: everything `subsumeBy` +drops from `n₁` is dominated by a sublevel of `n₂`, and `n₂` evaluates to at most `m`. +Domination of the constant by a variable needs that variable to evaluate to at least its +offset plus one, which is why the condition set must be all-nonzero (`hnz`). -/ +theorem Node.subsumeBy_eval_iff {same : Bool} {n₁ n₂ : Node} {m : Nat} + (hnz : ∀ v ∈ n₂.var, 0 < evalParam ls ρ v.var) (h₂ : Node.eval ls ρ n₂ ≤ m) : + Node.eval ls ρ (n₁.subsumeBy same n₂) ≤ m ↔ Node.eval ls ρ n₁ ≤ m := by + have hvar₂ v (hv : v ∈ n₂.var) : VarNode.eval ls ρ v ≤ m := + Nat.le_trans (Node.var_le_eval hv) h₂ + refine ⟨fun h => ?_, fun h => Nat.le_trans Node.subsumeBy_eval_le h⟩ + rw [Node.eval_le] at h ⊢ + refine ⟨?_, fun x hx => ?_⟩ + · by_cases hc : (n₁.subsumeBy same n₂).const = n₁.const + · exact hc ▸ h.1 + obtain ⟨-, hle⟩ | ⟨y, hy, hle⟩ := Node.subsumeBy_const_drop hc + · exact Nat.le_trans hle (Nat.le_trans Node.const_le_eval h₂) + · refine Nat.le_trans ?_ (hvar₂ _ hy) + have := hnz _ hy; simp only [VarNode.eval]; omega + · rw [Node.subsumeBy_var_eq] at h + split at h + · exact h.2 _ hx + · exact (subsumeVars_eval hvar₂).1 h.2 _ hx + +theorem Node.subsume_const_eq : (Node.subsume p₁ n₁ p₂ n₂).const = + if !subset compare p₂ p₁ || + (n₁.const = 0 || + (p₁.length == p₂.length || n₁.const > n₂.const) && + (n₂.var.isEmpty || n₁.const > n₂.var.foldl (·.max ·.offset) 0 + 1)) + then n₁.const else 0 := by + simp only [Node.subsume] + cases hs : subset compare p₂ p₁ <;> + simp only [reduceIte, Bool.not_true, Bool.not_false, Bool.false_or, Bool.true_or] + · rfl + · exact subsumeBy_const_eq + +theorem Node.subsume_var_eq : (Node.subsume p₁ n₁ p₂ n₂).var = + if !subset compare p₂ p₁ || (p₁.length == p₂.length || n₂.var.isEmpty) + then n₁.var else subsumeVars n₁.var n₂.var := by + simp only [Node.subsume] + cases hs : subset compare p₂ p₁ <;> + simp only [reduceIte, Bool.not_true, Bool.not_false, Bool.false_or, Bool.true_or] + · rfl + · exact subsumeBy_var_eq + +theorem Node.subsume_var_subset (h : x ∈ (Node.subsume p₁ n₁ p₂ n₂).var) : x ∈ n₁.var := by + rw [Node.subsume] at h; split at h <;> [exact subsumeBy_var_subset h; exact h] + +theorem Node.subsume_const_cases (p₁ n₁ p₂ n₂) : + (Node.subsume p₁ n₁ p₂ n₂).const = n₁.const ∨ (Node.subsume p₁ n₁ p₂ n₂).const = 0 := by + rw [Node.subsume]; split <;> [exact subsumeBy_const_cases ..; exact .inl rfl] + +theorem Node.subsume_eval_le : + Node.eval ls ρ (Node.subsume p₁ n₁ p₂ n₂) ≤ Node.eval ls ρ n₁ := by + rw [Node.subsume]; split <;> [exact subsumeBy_eval_le; exact Nat.le_refl _] + +/-- If `subsume` dropped the constant, the drop was justified: the constant is dominated +by the constant of `n₂` at a strictly smaller key, or by a variable of `n₂`. -/ +theorem Node.subsume_const_drop (h : (Node.subsume p₁ n₁ p₂ n₂).const ≠ n₁.const) : + subset compare p₂ p₁ ∧ + (p₁.length ≠ p₂.length ∧ n₁.const ≤ n₂.const ∨ ∃ y ∈ n₂.var, n₁.const ≤ y.offset + 1) := by + rw [Node.subsume] at h + split at h <;> [skip; cases h rfl] + refine ⟨‹_›, (subsumeBy_const_drop h).imp_left fun ⟨he, hc⟩ => ⟨fun e => ?_, hc⟩⟩ + simp [e] at he + +/-- If `subsume` changed the variable list, the change was `subsumeVars` against the +variables of `n₂` at a strictly smaller key. -/ +theorem Node.subsume_var_cases (p₁ n₁ p₂ n₂) : + (Node.subsume p₁ n₁ p₂ n₂).var = n₁.var ∨ + (subset compare p₂ p₁ ∧ p₁.length ≠ p₂.length ∧ + (Node.subsume p₁ n₁ p₂ n₂).var = subsumeVars n₁.var n₂.var) := by + rw [Node.subsume_var_eq]; split + · exact .inl rfl + · rename_i hc + rw [Bool.or_eq_true, Bool.or_eq_true, not_or, not_or] at hc + obtain ⟨hs, hlen, -⟩ := hc + have hsub : subset compare p₂ p₁ := by revert hs; cases subset compare p₂ p₁ <;> simp + exact .inr ⟨hsub, fun e => hlen (by simp [e]), rfl⟩ + +theorem NormLevel.minimize_var_subset {acc : NormLevel} + (h : x ∈ (acc.minimize p₁ n₁).var) : x ∈ n₁.var := by + rw [minimize, Std.TreeMap.foldl_eq_foldl_toList] at h + generalize acc.toList = l at h + induction l generalizing n₁ with | nil => exact h | cons a l ih + exact Node.subsume_var_subset (ih h) + +theorem NormLevel.minimize_eval_le {acc : NormLevel} : + Node.eval ls ρ (acc.minimize p₁ n₁) ≤ n₁.eval ls ρ := by + rw [minimize, Std.TreeMap.foldl_eq_foldl_toList] + generalize acc.toList = l + induction l generalizing n₁ with | nil => exact Nat.le_refl _ | cons a l ih + exact Nat.le_trans (ih (n₁ := Node.subsume p₁ n₁ a.1 a.2)) Node.subsume_eval_le + +/-- Minimizing a node against the rest of the map preserves its contribution to the total, +assuming every other entry's contribution is already bounded by `m`. -/ +theorem NormLevel.minimize_eval_iff {acc : NormLevel} {p₁ : List Name} {n₁ : Node} {m : Nat} + (wfa : ∀ p n, acc.get? p = some n → ∀ v ∈ n.var, v.var ∈ p) + (h₁ : acc.get? p₁ = some n₁) + (hacc : ∀ p n, p ≠ p₁ → acc.get? p = some n → evalPath ls ρ p (Node.eval ls ρ n) ≤ m) + (nz : allNZ ls ρ p₁) : + Node.eval ls ρ (acc.minimize p₁ n₁) ≤ m ↔ Node.eval ls ρ n₁ ≤ m := by + have wf₁ := wfa _ _ h₁ + have evalq p₂ n₂ (hne : p₂ ≠ p₁) (h₂ : acc.get? p₂ = some n₂) (hsub : subset compare p₂ p₁) : + Node.eval ls ρ n₂ ≤ m := by + have := hacc _ _ hne h₂ + rw [evalPath_le] at this + exact this (allNZ_mono (fun _ h => subset_mem hsub h) nz) + -- a variable dominated at a different key of the map is bounded by `m` + have domle (x : VarNode) : (∃ p₂ n₂ y, p₂ ≠ p₁ ∧ acc.get? p₂ = some n₂ ∧ + subset compare p₂ p₁ ∧ y ∈ n₂.var ∧ y.var = x.var ∧ x.offset ≤ y.offset) → + VarNode.eval ls ρ x ≤ m := fun ⟨p₂, n₂, y, hne, h₂, hsub, hy, e, le⟩ => by + refine Nat.le_trans ?_ (Nat.le_trans (Node.var_le_eval hy) (evalq _ _ hne h₂ hsub)) + simp only [VarNode.eval, ← e]; omega + refine ⟨fun hf => ?_, fun h => Nat.le_trans minimize_eval_le h⟩ + rw [minimize, Std.TreeMap.foldl_eq_foldl_toList] at hf + have hmem pn (h : pn ∈ acc.toList) : acc.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + generalize acc.toList = l at hf hmem + -- fold invariant: vars of the current node come from `n₁`; the constant is intact or + -- justifiably dropped; every original variable is dominated by a current one or elsewhere + suffices ∀ n1, (∀ x ∈ n1.var, x ∈ n₁.var) → + (n1.const = n₁.const ∨ (n1.const = 0 ∧ + ((∃ y ∈ n₁.var, n₁.const ≤ y.offset + 1) ∨ + ∃ p₂ n₂, p₂ ≠ p₁ ∧ acc.get? p₂ = some n₂ ∧ subset compare p₂ p₁ ∧ + n₁.const ≤ Node.eval ls ρ n₂))) → + (∀ x ∈ n₁.var, (∃ y ∈ n1.var, y.var = x.var ∧ x.offset ≤ y.offset) ∨ + ∃ p₂ n₂ y, p₂ ≠ p₁ ∧ acc.get? p₂ = some n₂ ∧ subset compare p₂ p₁ ∧ + y ∈ n₂.var ∧ y.var = x.var ∧ x.offset ≤ y.offset) → + Node.eval ls ρ (List.foldl (fun n1 pn => Node.subsume p₁ n1 pn.1 pn.2) n1 l) ≤ m → + Node.eval ls ρ n₁ ≤ m from + this n₁ (fun _ => id) (.inl rfl) (fun x h => .inl ⟨x, h, rfl, Nat.le_refl _⟩) hf + clear hf + induction l with intro n1 hL hK hJ hf + | nil => + refine Node.eval_le.2 ⟨?_, fun x hx => ?_⟩ + · obtain hK | ⟨-, hK | ⟨p₂, n₂, hne, h₂, hsub, hc⟩⟩ := hK + · exact Nat.le_trans (hK ▸ Node.const_le_eval) hf + · obtain ⟨y, hy, hc⟩ := hK + obtain ⟨y', hy', e, le⟩ | hd := hJ _ hy + · refine Nat.le_trans ?_ (Nat.le_trans (Node.var_le_eval hy') hf) + have : 0 < evalParam ls ρ y'.var := by + simp [allNZ] at nz; exact nz _ (wf₁ _ (hL _ hy')) + simp only [VarNode.eval]; omega + · refine Nat.le_trans ?_ (domle _ hd) + obtain ⟨p₂, n₂, y', hne, h₂, hsub, hy', e, le⟩ := hd + have : 0 < evalParam ls ρ y'.var := by + simp [allNZ] at nz; exact nz _ (subset_mem hsub (wfa _ _ h₂ _ hy')) + simp only [VarNode.eval, ← e]; omega + · exact Nat.le_trans hc (evalq _ _ hne h₂ hsub) + · obtain ⟨y, hy, e, le⟩ | hd := hJ _ hx + · refine Nat.le_trans ?_ (Nat.le_trans (Node.var_le_eval hy) hf) + simp only [VarNode.eval, ← e]; omega + · exact domle _ hd + | cons pn l ih => + simp only [List.mem_cons, forall_eq_or_imp] at hmem + obtain ⟨h₂, hmem'⟩ := hmem + refine ih hmem' _ (fun x h => hL _ (Node.subsume_var_subset h)) ?_ (fun x hx => ?_) hf + · by_cases hc : (Node.subsume p₁ n1 pn.1 pn.2).const = n1.const + · rw [hc]; exact hK + obtain ⟨hsub, hd⟩ := Node.subsume_const_drop hc + obtain heq | hzero := Node.subsume_const_cases p₁ n1 pn.1 pn.2 + · cases hc heq + have hc1 : n1.const = n₁.const := by + rcases hK with h | ⟨h, -⟩ + · exact h + · cases hc (hzero.trans h.symm) + refine .inr ⟨hzero, ?_⟩ + by_cases hpe : pn.1 = p₁ + · subst hpe + have : pn.2 = n₁ := by cases h₁.symm.trans h₂; rfl + subst this + obtain ⟨hne', -⟩ | ⟨y, hy, hle⟩ := hd + · exact absurd rfl hne' + · exact .inl ⟨y, hy, hc1 ▸ hle⟩ + · refine .inr ⟨pn.1, pn.2, hpe, h₂, hsub, ?_⟩ + obtain ⟨-, hle⟩ | ⟨y, hy, hle⟩ := hd + · exact hc1 ▸ Nat.le_trans hle Node.const_le_eval + · refine hc1 ▸ Nat.le_trans hle ?_ + have : 0 < evalParam ls ρ y.var := by + simp [allNZ] at nz + exact nz _ (subset_mem hsub (wfa _ _ h₂ _ hy)) + refine Nat.le_trans ?_ (Node.var_le_eval hy) + simp only [VarNode.eval]; omega + · obtain ⟨y, hy, e, le⟩ | hd := hJ _ hx <;> [skip; exact .inr hd] + obtain hv | ⟨hsub, hlen, hv⟩ := Node.subsume_var_cases p₁ n1 pn.1 pn.2 + · exact .inl ⟨y, hv ▸ hy, e, le⟩ + by_cases hy' : y ∈ (Node.subsume p₁ n1 pn.1 pn.2).var + · exact .inl ⟨y, hy', e, le⟩ + obtain ⟨z, hz, ez, lez⟩ := subsumeVars_dominated hy (hv ▸ hy') + have hpe : pn.1 ≠ p₁ := fun h => hlen (h ▸ rfl) + exact .inr ⟨pn.1, pn.2, z, hpe, h₂, hsub, hz, ez.trans e, Nat.le_trans le lez⟩ + +/-- One step of `subsumption`: the key being minimized is updated, or erased if it drained, +and no other key changes. -/ +theorem NormLevel.subsumption_step_get? (acc : NormLevel) (n₁ : Node) (p₁ p : List Name) : + (if (acc.minimize p₁ n₁).isEmpty then acc.erase p₁ + else acc.insert p₁ (acc.minimize p₁ n₁)).get? p = + if p₁ = p then (if (acc.minimize p₁ n₁).isEmpty then none else some (acc.minimize p₁ n₁)) + else acc.get? p := by + split <;> + simp only [Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_erase, + Std.TreeMap.getElem?_insert] <;> + split <;> split <;> simp_all + +/-- `subsumption` only shrinks the variable lists, at unchanged keys, so it preserves the +half of `WF` saying that every variable recorded at a key is an element of it. -/ +theorem NormLevel.subsumption_vars {s : NormLevel} (wf : s.WF) : + ∀ p n, s.subsumption.get? p = some n → (∀ v ∈ n.var, v.var ∈ p) ∧ Sorted p := by + rw [subsumption, Std.TreeMap.foldl_eq_foldl_toList] + have hmem pn (h : pn ∈ s.toList) : s.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + generalize s.toList = l at hmem + suffices ∀ (l : List (List Name × Node)) (acc : NormLevel), + (∀ pn ∈ l, s.get? pn.1 = some pn.2) → + (∀ p n, acc.get? p = some n → (∀ v ∈ n.var, v.var ∈ p) ∧ Sorted p) → + ∀ p n, (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).get? p = some n → + (∀ v ∈ n.var, v.var ∈ p) ∧ Sorted p from this _ _ hmem fun p n h => (wf p n h).2 + clear hmem; intro l + induction l with | nil => exact fun _ _ => id | cons pn l ih + intro acc hl hacc + refine ih _ (fun _ h => hl _ (.tail _ h)) fun p n h => ?_ + rw [subsumption_step_get?] at h + split at h + · split at h <;> [cases h; skip] + cases h; rename_i hp _; subst hp + have := (wf _ _ (hl _ (.head _))).2 + exact ⟨fun v hv => this.1 _ (minimize_var_subset hv), this.2⟩ + · exact hacc _ _ h + +/-- A variable that minimization drops is dropped in favour of one with the same name at a +strictly smaller key. -/ +theorem NormLevel.minimize_var_dominated {acc : NormLevel} {p₁ n₁ x} + (hx : x ∈ n₁.var) (h : x ∉ (acc.minimize p₁ n₁).var) : + ∃ p₂ n₂ y, acc.get? p₂ = some n₂ ∧ y ∈ n₂.var ∧ y.var = x.var ∧ + p₂ ≠ p₁ ∧ ∀ z ∈ p₂, z ∈ p₁ := by + rw [minimize, Std.TreeMap.foldl_eq_foldl_toList] at h + have hmem pn (h : pn ∈ acc.toList) : acc.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + generalize acc.toList = l at h hmem + suffices ∀ (l : List (List Name × Node)) (n : Node), + (∀ pn ∈ l, acc.get? pn.1 = some pn.2) → x ∈ n.var → + x ∉ (List.foldl (fun n pn => Node.subsume p₁ n pn.1 pn.2) n l).var → + ∃ p₂ n₂ y, acc.get? p₂ = some n₂ ∧ y ∈ n₂.var ∧ y.var = x.var ∧ + p₂ ≠ p₁ ∧ ∀ z ∈ p₂, z ∈ p₁ from this _ _ hmem hx h + clear hx h hmem; intro l + induction l with + | nil => exact fun n _ hx h => absurd hx h + | cons pn l ih => + intro n hl hx h + by_cases hx' : x ∈ (Node.subsume p₁ n pn.1 pn.2).var + · exact ih _ (fun _ h => hl _ (.tail _ h)) hx' h + · obtain heq | ⟨hsub, hlen, heq⟩ := Node.subsume_var_cases p₁ n pn.1 pn.2 + · rw [heq] at hx'; exact absurd hx hx' + · rw [heq] at hx' + obtain ⟨y, hy, e, -⟩ := subsumeVars_dominated hx hx' + exact ⟨pn.1, pn.2, y, hl _ (.head _), hy, e, + fun he => hlen (by rw [he]), fun _ hz => subset_mem hsub hz⟩ + +/-- `s'` covers `s`: every variable recorded in `s` is still recorded in `s'`, at a subset of +its key. This is all of a map that `Dom`, hence `Feas`, looks at. -/ +def NormLevel.Covers (s' s : NormLevel) : Prop := + ∀ p n x, s.get? p = some n → x ∈ n.var → + ∃ q m y, s'.get? q = some m ∧ y ∈ m.var ∧ y.var = x.var ∧ ∀ z ∈ q, z ∈ p + +/-- `subsumption` only removes variables from a node, and never the last witness for a name: +a removed one is still recorded at a strictly smaller key, possibly after further removals +there. So the subsumed map covers the original, and its entries are entries of it. -/ +theorem NormLevel.subsumption_covers {s : NormLevel} : + (∀ p n, s.subsumption.get? p = some n → + ∃ n₀, s.get? p = some n₀ ∧ ∀ x ∈ n.var, x ∈ n₀.var) ∧ s.subsumption.Covers s := by + rw [subsumption, Std.TreeMap.foldl_eq_foldl_toList] + have hmem pn (h : pn ∈ s.toList) : s.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + generalize s.toList = l at hmem + suffices ∀ (l : List (List Name × Node)) (acc : NormLevel), + (∀ pn ∈ l, s.get? pn.1 = some pn.2) → + (∀ p n, acc.get? p = some n → ∃ n₀, s.get? p = some n₀ ∧ ∀ x ∈ n.var, x ∈ n₀.var) → + acc.Covers s → + (∀ p n, (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).get? p = some n → + ∃ n₀, s.get? p = some n₀ ∧ ∀ x ∈ n.var, x ∈ n₀.var) ∧ + (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).Covers s from + this _ _ hmem (fun p n h => ⟨n, h, fun _ => id⟩) + (fun p n x h hx => ⟨p, n, x, h, hx, rfl, fun _ => id⟩) + clear hmem; intro l + induction l with | nil => exact fun _ _ h1 h2 => ⟨h1, h2⟩ | cons pn l ih + obtain ⟨p₁, n₁⟩ := pn + intro acc hl hsub hcov + have h₁ : s.get? p₁ = some n₁ := hl _ (.head _) + refine ih _ (fun _ h => hl _ (.tail _ h)) (fun p n h => ?_) (fun p n x hp hx => ?_) + · rw [subsumption_step_get?] at h + split at h + · split at h <;> [cases h; skip] + cases h; rename_i hp _; subst hp + exact ⟨n₁, h₁, fun x hx => minimize_var_subset hx⟩ + · exact hsub _ _ h + · obtain ⟨q, m, y, hq, hy, e, hqp⟩ := hcov _ _ _ hp hx + by_cases hqp₁ : q = p₁ + · subst hqp₁ + -- the write lands on the key covering `x`: either the variable survives it, or it is + -- dominated at a smaller key, which this step leaves alone + obtain ⟨n₀, h₀, hy₀⟩ := hsub _ _ hq + cases h₀.symm.trans h₁ + by_cases hmin : y ∈ (acc.minimize q n₁).var + · refine ⟨q, _, y, ?_, hmin, e, hqp⟩ + rw [subsumption_step_get?, if_pos rfl, if_neg] + simp only [Node.isEmpty, Bool.and_eq_true, List.isEmpty_iff, not_and] + rintro - he; simp [he] at hmin + · obtain ⟨p₂, n₂, z, h₂, hz, e₂, hne, hp₂⟩ := minimize_var_dominated (hy₀ _ hy) hmin + exact ⟨p₂, n₂, z, by rw [subsumption_step_get?, if_neg (Ne.symm hne)]; exact h₂, + hz, e₂.trans e, fun w hw => hqp _ (hp₂ _ hw)⟩ + · exact ⟨q, m, y, by rw [subsumption_step_get?, if_neg (Ne.symm hqp₁)]; exact hq, + hy, e, hqp⟩ + +theorem NormLevel.subsumption_eval {s : NormLevel} (wf : s.WF) : + s.subsumption.eval ls ρ = s.eval ls ρ := by + rw [subsumption, Std.TreeMap.foldl_eq_foldl_toList] + have hmem pn (h : pn ∈ s.toList) : s.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + have nd : (s.toList.map Prod.fst).Nodup := by simpa using Std.TreeMap.nodup_keys (t := s) + generalize s.toList = l at hmem nd + suffices ∀ (l : List (List Name × Node)) (acc : NormLevel), + (l.map Prod.fst).Nodup → + (∀ p n, (p, n) ∈ l → acc.get? p = some n) → + (∀ p n, acc.get? p = some n → ∀ v ∈ n.var, v.var ∈ p) → + eval ls ρ acc = eval ls ρ s → + eval ls ρ (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l) = eval ls ρ s from + this _ _ nd (fun _ _ => hmem _) (fun _ _ h => (wf _ _ h).2.1) rfl + clear hmem nd; intro l + induction l with | nil => exact fun acc _ _ _ eq => eq | cons pn l ih + have ⟨p₁, n₁⟩ := pn; intro acc nd hl wfa eq + simp only [List.map_cons, List.nodup_cons] at nd + have h₁ := hl _ _ (.head _) + -- a drained key is erased rather than kept, which is the same for `eval` + have hins := subsumption_step_get? acc n₁ p₁ + have hmin_le m + (H : ∀ a b, (if (acc.minimize p₁ n₁).isEmpty then acc.erase p₁ + else acc.insert p₁ (acc.minimize p₁ n₁)).get? a = some b → + evalPath ls ρ a (Node.eval ls ρ b) ≤ m) + (nz : allNZ ls ρ p₁) : Node.eval ls ρ (acc.minimize p₁ n₁) ≤ m := by + by_cases he : (acc.minimize p₁ n₁).isEmpty + · simp [Node.isEmpty, List.isEmpty_iff] at he; simp [Node.eval, he.1, he.2] + · have hget : (if (acc.minimize p₁ n₁).isEmpty then acc.erase p₁ + else acc.insert p₁ (acc.minimize p₁ n₁)).get? p₁ = some (acc.minimize p₁ n₁) := by + rw [hins p₁, if_pos rfl, if_neg he] + have := H _ _ hget + rw [evalPath_le] at this; exact this nz + refine ih _ nd.2 (fun p n h => ?_) (fun p n h v hv => ?_) ((ext_le fun m => ?_).trans eq) + · have hne : p₁ ≠ p := fun e => nd.1 (by rw [e]; exact List.mem_map_of_mem h) + exact (hins p).trans (if_neg hne) ▸ hl _ _ (.tail _ h) + · rw [hins p] at h; split at h + · split at h <;> [cases h; skip] + cases h; rename_i hp _; subst hp + exact wfa _ _ h₁ _ (minimize_var_subset hv) + · exact wfa _ _ h _ hv + · simp only [eval_le]; constructor <;> intro H p n h + · by_cases hp : p = p₁ + · subst hp; cases h₁.symm.trans h + refine evalPath_le.2 fun nz => ?_ + refine (minimize_eval_iff wfa h₁ (fun q nq hne hq => ?_) nz).1 (hmin_le _ H nz) + exact H _ _ ((hins q).trans (if_neg hne.symm) ▸ hq) + · exact H p n ((hins p).trans (if_neg (Ne.symm hp)) ▸ h) + · rw [hins p] at h; split at h <;> [skip; exact H _ _ h] + split at h <;> [cases h; skip] + cases h; rename_i hp _; subst hp + refine evalPath_le.2 fun nz => ?_ + have := H _ _ h₁; rw [evalPath_le] at this + exact Nat.le_trans minimize_eval_le (this nz) + +theorem normalize_eval (hu : VLevel.ofLevel ls u = some u') : + (normalize u).eval ls ρ = u'.eval ρ := by + simp [normalize] + refine have h1 := ?_; by + rw [NormLevel.subsumption_eval (normalizeAux_wf (by simp) h1)] + exact normalizeAux_eval hu (by simp) h1 + simp [NormLevel.WF] + +theorem normalize_vars_sorted : ∀ p n, (normalize u).get? p = some n → + (∀ v ∈ n.var, v.var ∈ p) ∧ Sorted p := + NormLevel.subsumption_vars (normalizeAux_wf (by simp) (by simp [NormLevel.WF])) + +theorem normalize_vars : ∀ p n, (normalize u).get? p = some n → ∀ v ∈ n.var, v.var ∈ p := + fun _ _ h => (normalize_vars_sorted _ _ h).1 + +theorem normalize_sorted : ∀ p n, (normalize u).get? p = some n → Sorted p := + fun _ _ h => (normalize_vars_sorted _ _ h).2 + +/-- Soundness of `NormLevel.le`, Theorem 39 of the paper: it reports `true` only when every +sublevel of `l₁` is dominated. Each entry of `l₁` is compared against a fold over `l₂`, +where every entry discharges from the node what it can, and the fold stops (returning +`none`) once nothing is left to discharge; so the fold ends in `none` only if the node is +bounded by the total of `l₂`. -/ +theorem NormLevel.le_eval {l₁ l₂ : NormLevel} + (wf₂ : ∀ p n, l₂.get? p = some n → ∀ v ∈ n.var, v.var ∈ p) + (h : l₁.le l₂) : l₁.eval ls ρ ≤ l₂.eval ls ρ := by + refine NormLevel.eval_le.2 fun p₁ n₁ h₁ => evalPath_le.2 fun nz => ?_ + -- an entry of `l₂` at a key below `p₁` is bounded by the total, on a live condition set + have hbd p₂ n₂ (h₂ : l₂.get? p₂ = some n₂) (hsub : subset compare p₂ p₁) : + (∀ v ∈ n₂.var, 0 < evalParam ls ρ v.var) ∧ Node.eval ls ρ n₂ ≤ l₂.eval ls ρ := by + have hnz : allNZ ls ρ p₂ := allNZ_mono (fun _ h => subset_mem hsub h) nz + refine ⟨fun v hv => ?_, ?_⟩ + · simp only [allNZ, List.all_eq_true, decide_eq_true_eq] at hnz + exact hnz _ (wf₂ _ _ h₂ _ hv) + · have := evalPath_le.1 (NormLevel.eval_le.1 (Nat.le_refl (l₂.eval ls ρ)) _ _ h₂) + exact this hnz + rw [NormLevel.le, Std.TreeMap.all_eq_all_toList, List.all_eq_true] at h + have hf := h (p₁, n₁) (Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 (by simpa using h₁)) + simp only [Std.TreeMap.foldlM_eq_foldlM_toList, Option.isNone_iff_eq_none] at hf + have hmem pn (h : pn ∈ l₂.toList) : l₂.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + clear h₁ h + generalize l₂.toList = l at hf hmem + induction l generalizing n₁ with + | nil => simp at hf + | cons pn l ih => + simp only [List.foldlM_cons] at hf + simp only [List.mem_cons, forall_eq_or_imp] at hmem + by_cases hs : subset compare pn.1 p₁ + · refine (Node.subsumeBy_eval_iff (same := false) (n₂ := pn.2) + (hbd _ _ hmem.1 hs).1 (hbd _ _ hmem.1 hs).2).1 ?_ + by_cases he : (n₁.subsumeBy false pn.2).isEmpty + · simp [Node.eval_empty he] + · exact ih _ (by simpa [hs, he] using hf) hmem.2 + · exact ih _ (by simpa [hs] using hf) hmem.2 + +theorem Node.eval_congr {a b : Node} (H : a == b) : a.eval ls ρ = b.eval ls ρ := by + simp +instances [instBEqNode] at H; simp [H, eval] + +theorem NormLevel.eval_congr {a b : NormLevel} (H : a == b) : a.eval ls ρ = b.eval ls ρ := by + simp +instances only [instBEqNormLevel, Std.TreeMap.all_eq_all_toList, + Bool.and_eq_true, List.all_eq_true] at H + suffices ∀ {a b : NormLevel}, (∀ x ∈ a.toList, b.get? x.1 == some x.2) → + a.eval ls ρ ≤ b.eval ls ρ from Nat.le_antisymm (this H.1) (this H.2) + clear a b H; intro a b H + simp only [eval, Std.TreeMap.foldl_eq_foldl_toList] + rw [← a.toList.reverse_reverse] at H ⊢; generalize a.toList.reverse = a at H ⊢ + simp only [List.mem_reverse, Std.TreeMap.get?_eq_getElem?, List.foldl_reverse] at H ⊢ + induction a with | nil => exact Nat.zero_le _ | cons p l ih; let (x, y) := p + simp only [List.mem_cons, or_imp, forall_and, forall_eq, List.foldr_cons] at H ⊢ + refine Nat.max_le.2 ⟨ih H.2, ?_⟩ + let ⟨y', h1, h2⟩ := Option.beq_some_iff.1 H.1 + have H := Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 h1 + rw [← b.toList.reverse_reverse] at H ⊢; generalize b.toList.reverse = b at H ⊢ + simp only [List.mem_reverse, List.foldl_reverse] at H ⊢ + induction b with | nil => cases H | cons p l ih; let (x, y) := p + simp; obtain ⟨⟩ | ⟨_, (H : _ ∈ l)⟩ := H + · exact Node.eval_congr h2 ▸ Nat.le_max_right .. + · exact Nat.le_trans (ih H) (Nat.le_max_left ..) + +/-! +### Reconstruction + +The value of a `Tree` is the value of the level it reifies to: a tree node contributes its +own sublevels, and every child contributes under the `imax` guard of the variable labelling +the edge into it. That edge guard is what makes the tree shape meaningful — a node at path +`[a₁, …, aₙ]` (innermost first) is guarded by all of `a₁, …, aₙ` — and it is also what makes +the tree carry sublevels of its own, since `imax x a` is at least `a` when `a ≠ 0`. +-/ + +mutual + +def Tree.eval (ls : List Name) (ρ : List Nat) : Tree → Nat + | ⟨const, var, child⟩ => max' (Node.eval ls ρ ⟨const, var⟩) (Tree.evalChild ls ρ child) + +def Tree.evalChild (ls : List Name) (ρ : List Nat) : List (Name × Tree) → Nat + | [] => 0 + | (a, t) :: l => + max' (Lean.Nat.imax (Tree.eval ls ρ t) (evalParam ls ρ a)) (Tree.evalChild ls ρ l) + +end + +/-- The value of the optional level accumulated by `reify`. -/ +def evalOpt (ρ : Name → Nat) (μ : LMVarId → Nat) : Option Level → Nat + | none => 0 + | some l => Level.eval ρ μ l + +@[simp] theorem evalOpt_none : evalOpt ρ μ none = 0 := rfl +@[simp] theorem evalOpt_some : evalOpt ρ μ (some l) = Level.eval ρ μ l := rfl + +theorem imax_eq_ite : Lean.Nat.imax a b = if b = 0 then 0 else max' a b := rfl + +theorem imax_zero_left : Lean.Nat.imax 0 a = a := by rw [imax_eq_ite]; split <;> omega + +theorem Node.eval_const {var : List VarNode} : + Node.eval ls ρ ⟨c, var⟩ = max' c (Node.eval ls ρ ⟨0, var⟩) := + ext_le fun x => by simp [Node.eval_le, Nat.max_le] + +theorem Node.eval_cons {var : List VarNode} : + Node.eval ls ρ ⟨c, a :: var⟩ = max' (VarNode.eval ls ρ a) (Node.eval ls ρ ⟨c, var⟩) := + ext_le fun x => by simp [Node.eval_le, Nat.max_le, and_left_comm] + +theorem eval_mkMax : + Level.eval ρ μ (Tree.reify.mkMax l o) = max' (Level.eval ρ μ l) (evalOpt ρ μ o) := by + cases o <;> simp [Tree.reify.mkMax, evalOpt, Level.eval] + +theorem eval_addOffset : Level.eval ρ μ (l.addOffset k) = Level.eval ρ μ l + k := by + simp only [Level.addOffset] + induction k generalizing l with + | zero => rfl + | succ k ih => rw [Level.addOffsetAux, ih]; simp [Level.eval]; omega + +theorem eval_ofNat : Level.eval ρ μ (Level.ofNat k) = k := by + induction k with + | zero => rfl + | succ k ih => simp [Level.ofNat, Level.eval, ih] + +theorem eval_varFold (var : List VarNode) (o : Option Level) : + evalOpt (evalParam ls ρ) μ (var.foldr (init := o) fun n r => + some (Tree.reify.mkMax (Level.addOffset (.param n.var) n.offset) r)) = + max' (Node.eval ls ρ ⟨0, var⟩) (evalOpt (evalParam ls ρ) μ o) := by + induction var with | nil => simp [Node.eval] | cons a var ih + simp only [List.foldr_cons, evalOpt_some, eval_mkMax, eval_addOffset, Level.eval, ih, + Node.eval_cons, VarNode.eval]; omega + +/-- The two shapes `plainOffset?` accepts. -/ +theorem Tree.plainOffset?_eq {a : Name} {t : Tree} {k : Nat} (h : plainOffset? a t = some k) : + t = ⟨0, [], []⟩ ∧ k = 0 ∨ t = ⟨0, [⟨a, k⟩], []⟩ := by + unfold plainOffset? at h + split at h + · exact .inl ⟨rfl, by simpa using h.symm⟩ + · rename_i v _ + split at h <;> [skip; cases h] + cases h; rename_i hv + exact .inr (by rw [← eq_of_beq hv]) + · cases h + +/-- Dropping the `imax` guard of a plain child is exact modulo the node's constant: the two +differ only when the edge variable is zero, where the plain form contributes `k ≤ const`. -/ +theorem Tree.plainOffset?_eval {a : Name} {t : Tree} {k const : Nat} + (h : plainOffset? a t = some k) (hk : k ≤ const) : + max' const (Lean.Nat.imax (eval ls ρ t) (evalParam ls ρ a)) = + max' const (evalParam ls ρ a + k) := by + obtain ⟨rfl, rfl⟩ | rfl := plainOffset?_eq h + · rw [show eval ls ρ ⟨0, [], []⟩ = 0 from by simp [eval, evalChild, Node.eval], + imax_zero_left] + omega + · rw [show eval ls ρ ⟨0, [⟨a, k⟩], []⟩ = evalParam ls ρ a + k from by + simp [eval, evalChild, Node.eval, VarNode.eval], imax_eq_ite] + split <;> omega + +/-- A child emitted plainly at exactly the node's constant makes that constant redundant. -/ +theorem Tree.reifyChild_ge {const : Nat} : ∀ child : List (Name × Tree), + (child.any fun c => plainOffset? c.1 c.2 == some const) → + const ≤ evalOpt (evalParam ls ρ) μ (child.foldr (reify.mkChild const) none) + | (n, t) :: child, h => by + rw [List.foldr_cons, reify.mkChild] + simp only [List.any_cons, Bool.or_eq_true, beq_iff_eq] at h + -- either this child is the witness, in which case it is emitted as `n + const`, or the + -- witness is further down and the fold maxes its value in + obtain h | h := h + · rw [h]; dsimp only; rw [if_pos (Nat.le_refl const)] + simp only [evalOpt_some, eval_mkMax, eval_addOffset, Level.eval] + omega + · have ih := reifyChild_ge (ls := ls) (ρ := ρ) (μ := μ) child h + split <;> [split; skip] <;> + simp only [evalOpt_some, eval_mkMax] <;> omega + +mutual + +theorem Tree.reify_eval (t : Tree) : t.reify.eval (evalParam ls ρ) μ = t.eval ls ρ := by + obtain ⟨const, var, child⟩ := t + rw [eval] + simp only [reify] + have h1 := eval_varFold (ls := ls) (ρ := ρ) (μ := μ) var + (child.foldr (reify.mkChild const) none) + have hc := reifyChild_eval (ls := ls) (ρ := ρ) (μ := μ) const child + rw [Node.eval_const (c := const)] + split <;> [rename_i heq; rename_i l heq] + · rw [heq, evalOpt_none] at h1 + rw [eval_ofNat]; omega + · rw [heq, evalOpt_some] at h1 + split <;> rename_i hd + · -- the constant is dropped: either it is zero, or some child already covers it + simp only [Bool.or_eq_true, beq_iff_eq] at hd + rw [h1] + obtain rfl | hd := hd + · omega + · have := Tree.reifyChild_ge (ls := ls) (ρ := ρ) (μ := μ) (const := const) child hd + omega + · simp only [Level.eval, eval_ofNat, h1, Nat.max_eq_max]; omega + +theorem Tree.reifyChild_eval (const : Nat) (child : List (Name × Tree)) : + max' const (evalOpt (evalParam ls ρ) μ (child.foldr (reify.mkChild const) none)) = + max' const (evalChild ls ρ child) := by + match child with + | [] => rfl + | (n, t) :: child => + rw [List.foldr_cons, evalChild, reify.mkChild] + have ht := reify_eval (ls := ls) (ρ := ρ) (μ := μ) t + have ih := reifyChild_eval (ls := ls) (ρ := ρ) (μ := μ) const child + split <;> rename_i k h + · split <;> rename_i hk + · have hp := Tree.plainOffset?_eval (ls := ls) (ρ := ρ) h hk + simp only [evalOpt_some, eval_mkMax, eval_addOffset, Level.eval] at * + omega + · simp only [evalOpt_some, eval_mkMax, Level.eval, ht] at * + omega + · simp only [evalOpt_some, eval_mkMax, Level.eval, ht] at * + omega + +end + +/-- `Tree.At t p t'` says `t'` is the subtree of `t` at path `p`, listed innermost first, +the way `Tree.modify` takes it. -/ +inductive Tree.At : Tree → List Name → Tree → Prop + | nil : At t [] t + | cons (h : At t p t') (hm : (a, t'') ∈ t'.child) : At t (a :: p) t'' + +theorem Tree.eval_eq (t : Tree) : + eval ls ρ t = max' (Node.eval ls ρ ⟨t.const, t.var⟩) (evalChild ls ρ t.child) := by + cases t; rw [eval] + +theorem Tree.At.append (h : At t' q t'') (hm : (a, t') ∈ t.child) : + At t (q ++ [a]) t'' := by + induction h with + | nil => exact .cons .nil hm + | cons _ hm' ih => exact .cons ih hm' + +/-- A path passes through all of its tails. -/ +theorem Tree.At.suffix {t : Tree} : ∀ {path t' q}, At t path t' → q <:+ path → ∃ t'', At t q t'' := by + intro path + induction path with + | nil => intro t' q _ hq; cases List.suffix_nil.1 hq; exact ⟨t, .nil⟩ + | cons a p ih => + intro t' q h hq + obtain rfl | hq := List.suffix_cons_iff.1 hq + · exact ⟨t', h⟩ + · cases h; rename_i t₁ h _; exact ih h hq + +theorem Tree.At.nil_inv (h : At t [] t') : t' = t := by cases h; rfl + +/-- Inverting `At.append`: a nonempty path is a child of the root followed by the rest. -/ +theorem Tree.At.append_inv : ∀ {q t t''}, At t (q ++ [a]) t'' → + ∃ t₁, (a, t₁) ∈ t.child ∧ At t₁ q t'' := by + intro q + induction q with + | nil => + intro t t'' h + cases h; rename_i t₁ h hm + cases h.nil_inv + exact ⟨t'', hm, .nil⟩ + | cons b q ih => + intro t t'' h + simp only [List.cons_append] at h + cases h; rename_i t₁ h hm + obtain ⟨t₂, hm₂, h₂⟩ := ih h + exact ⟨t₂, hm₂, .cons h₂ hm⟩ + +/-- Paths only look at the children, so replacing the root's own data leaves them all in +place; only the empty path sees the difference. -/ +theorem Tree.At.of_child_eq {t u : Tree} (hc : u.child = t.child) : + ∀ {p t'}, At t p t' → At u p t' ∨ (p = [] ∧ t' = t) := by + intro p + induction p with + | nil => intro t' h; exact .inr ⟨rfl, h.nil_inv⟩ + | cons a q ih => + intro t'' h + cases h; rename_i t₁ h hm + obtain h' | ⟨rfl, rfl⟩ := ih h + · exact .inl (.cons h' hm) + · exact .inl (.cons .nil (by rw [hc]; exact hm)) + +theorem Tree.mem_le {l : List (Name × Tree)} (hm : (a, t) ∈ l) : + Lean.Nat.imax (eval ls ρ t) (evalParam ls ρ a) ≤ evalChild ls ρ l := by + induction l with + | nil => cases hm + | cons b l ih => + obtain ⟨b, t'⟩ := b + rw [evalChild] + obtain h | hm := List.mem_cons.1 hm + · cases h; exact Nat.le_max_left .. + · exact Nat.le_trans (ih hm) (Nat.le_max_right ..) + +theorem evalPath_cons_imax : + evalPath ls ρ (a :: p) c ≤ evalPath ls ρ p (Lean.Nat.imax c (evalParam ls ρ a)) := by + rw [evalPath_cons] + exact evalPath_mono <| by + by_cases h : evalParam ls ρ a = 0 <;> + simp [imax_eq_ite, h, Nat.pos_of_ne_zero, Nat.le_max_left] + +theorem evalPath_cons_edge : + evalPath ls ρ (a :: p) (evalParam ls ρ a) ≤ + evalPath ls ρ p (Lean.Nat.imax c (evalParam ls ρ a)) := by + rw [evalPath_cons] + exact evalPath_mono <| by + by_cases h : evalParam ls ρ a = 0 <;> + simp [imax_eq_ite, h, Nat.pos_of_ne_zero, Nat.le_max_right] + +theorem evalPath_append_single (ha : evalParam ls ρ a ≠ 0) : + evalPath ls ρ (p ++ [a]) c = evalPath ls ρ p c := by + simp [evalPath, allNZ, List.all_append, Nat.pos_of_ne_zero ha] + +theorem Tree.At.le (h : At t p t') : + evalPath ls ρ p (eval ls ρ t') ≤ eval ls ρ t := by + induction h with + | nil => simp [evalPath, allNZ] + | cons _ hm ih => + refine Nat.le_trans evalPath_cons_imax (Nat.le_trans (evalPath_mono ?_) ih) + exact Nat.le_trans (mem_le hm) (eval_eq _ ▸ Nat.le_max_right ..) + +theorem Tree.At.edge_le (h : At t (a :: p) t') : + evalPath ls ρ (a :: p) (evalParam ls ρ a) ≤ eval ls ρ t := by + cases h with | @cons _ t'' _ _ h' hm => ?_ + refine Nat.le_trans (evalPath_cons_edge (c := eval ls ρ t')) + (Nat.le_trans (evalPath_mono ?_) h'.le) + exact Nat.le_trans (mem_le hm) (eval_eq t'' ▸ Nat.le_max_right ..) + +mutual + +/-- A tree is bounded by `m` as soon as all the sublevels it reifies to are: the ones +recorded at its nodes, and the `V(p, a, 0)` contributed by the edge into each node. -/ +theorem Tree.eval_le_of (t : Tree) + (h1 : ∀ p t', At t p t' → evalPath ls ρ p (Node.eval ls ρ ⟨t'.const, t'.var⟩) ≤ m) + (h2 : ∀ a p t', At t (a :: p) t' → evalPath ls ρ (a :: p) (evalParam ls ρ a) ≤ m) : + eval ls ρ t ≤ m := by + obtain ⟨const, var, child⟩ := t + rw [eval] + refine Nat.max_le.2 ⟨h1 [] _ .nil, evalChild_le_of child ?_ ?_ ?_⟩ + · exact fun a t' hm p t'' hat => h1 _ _ (hat.append hm) + · exact fun a t' hm b p t'' hat => h2 _ _ _ (hat.append hm) + · exact fun a t' hm => h2 a [] t' (.cons .nil hm) + +theorem Tree.evalChild_le_of : ∀ (l : List (Name × Tree)), + (∀ a t', (a, t') ∈ l → ∀ p t'', At t' p t'' → + evalPath ls ρ (p ++ [a]) (Node.eval ls ρ ⟨t''.const, t''.var⟩) ≤ m) → + (∀ a t', (a, t') ∈ l → ∀ b p t'', At t' (b :: p) t'' → + evalPath ls ρ ((b :: p) ++ [a]) (evalParam ls ρ b) ≤ m) → + (∀ a t', (a, t') ∈ l → evalPath ls ρ [a] (evalParam ls ρ a) ≤ m) → + evalChild ls ρ l ≤ m + | [], _, _, _ => by rw [evalChild]; exact Nat.zero_le _ + | (a, t) :: l, h1, h2, h3 => by + rw [evalChild] + refine Nat.max_le.2 ⟨?_, evalChild_le_of l + (fun a t' hm => h1 a t' (.tail _ hm)) (fun a t' hm => h2 a t' (.tail _ hm)) + (fun a t' hm => h3 a t' (.tail _ hm))⟩ + by_cases ha : evalParam ls ρ a = 0 + · simp [imax_eq_ite, ha] + · have hle : evalParam ls ρ a ≤ m := by + have := h3 a t (.head _) + simpa [evalPath, allNZ, Nat.pos_of_ne_zero ha] using this + have ht : eval ls ρ t ≤ m := + eval_le_of t + (fun p t'' hat => evalPath_append_single ha ▸ h1 a t (.head _) p t'' hat) + (fun b p t'' hat => evalPath_append_single ha ▸ h2 a t (.head _) b p t'' hat) + rw [imax_eq_ite]; split <;> omega + +end + +/-- A tree is bounded by `m` exactly when all the sublevels it reifies to are: the ones +recorded at its nodes, and the one each edge contributes. -/ +theorem Tree.eval_le_iff {t : Tree} {m : Nat} : + eval ls ρ t ≤ m ↔ + (∀ p t', At t p t' → evalPath ls ρ p (Node.eval ls ρ ⟨t'.const, t'.var⟩) ≤ m) ∧ + (∀ a p t', At t (a :: p) t' → evalPath ls ρ (a :: p) (evalParam ls ρ a) ≤ m) := by + refine ⟨fun h => ?_, fun ⟨h1, h2⟩ => eval_le_of t h1 h2⟩ + refine ⟨fun _ t' hp => ?_, fun _ _ _ hp => Nat.le_trans hp.edge_le h⟩ + exact Nat.le_trans (Nat.le_trans (evalPath_mono (eval_eq t' ▸ Nat.le_max_left ..)) hp.le) h + +/-! +### Admissible chains + +Reifying the sublevels at a key `p` means nesting them under an `imax` chain whose variables +are the elements of `p`; the chain contributes the sublevel `V(q, a, 0)` for every one of its +edges, where `q` is the set of conditions from the outside up to and including that edge. The +level is therefore equivalent to the normal form only if every such edge is *dominated* +(`Dom`), and a key is expressible only if its elements can be ordered so that all of them are +(`Feas`). `lexChain` searches for such an order greedily; `feasible` is its lookahead. +-/ + +/-- The edge adding `a` to the conditions `acc` contributes `V(acc ∪ {a}, a, 0)`, which the +normal form dominates when it has some `V(T, a+k)` with `T ⊆ acc ∪ {a}`. -/ +def NormLevel.Dom (s : NormLevel) (a : Name) (acc : List Name) : Prop := + ∃ p n, s.get? p = some n ∧ (∃ x ∈ n.var, x.var = a) ∧ ∀ y ∈ p, y = a ∨ y ∈ acc + +theorem NormLevel.Dom.mono {s : NormLevel} + (h : s.Dom a acc) (hs : ∀ x ∈ acc, x ∈ acc') : s.Dom a acc' := + let ⟨p, n, h1, h2, h3⟩ := h + ⟨p, n, h1, h2, fun y hy => (h3 y hy).imp id (hs _)⟩ + +/-- A dominated edge contributes nothing beyond the normal form. -/ +theorem NormLevel.Dom.le {s : NormLevel} (h : s.Dom a acc) : + evalPath ls ρ (a :: acc) (evalParam ls ρ a) ≤ s.eval ls ρ := by + refine evalPath_le.2 fun nz => ?_ + rw [allNZ_cons] at nz + obtain ⟨p, n, h1, ⟨x, hx, hxa⟩, h3⟩ := h + have hnz : allNZ ls ρ p := by + simp only [allNZ, List.all_eq_true, decide_eq_true_eq] + refine fun y hy => (h3 y hy).elim (fun e => e ▸ nz.1) fun hy => ?_ + simp only [allNZ, List.all_eq_true, decide_eq_true_eq] at nz + exact nz.2 _ hy + refine Nat.le_trans ?_ (Nat.le_trans (Node.var_le_eval hx) + (evalPath_le.1 (NormLevel.eval_le.1 (Nat.le_refl _) _ _ h1) hnz)) + simp only [VarNode.eval, ← hxa]; omega + +theorem NormLevel.addable_sound {s : NormLevel} (h : s.addable a acc) : s.Dom a acc := by + simp only [addable, Std.TreeMap.any_eq_any_toList, List.any_eq_true, Bool.and_eq_true, + beq_iff_eq] at h + obtain ⟨⟨p, n⟩, hm, ⟨x, hx, hxa⟩, hsub⟩ := h + refine ⟨p, n, Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 hm, + ⟨x, hx, hxa⟩, fun y hy => ?_⟩ + by_cases hya : y = a + · exact .inl hya + · exact .inr (subset_mem hsub ((List.mem_erase_of_ne hya).2 hy)) + +theorem NormLevel.addable_complete {s : NormLevel} (hs : ∀ p n, s.get? p = some n → Sorted p) + (hacc : Sorted acc) (h : s.Dom a acc) : s.addable a acc := by + obtain ⟨p, n, h1, ⟨x, hx, hxa⟩, h3⟩ := h + simp only [addable, Std.TreeMap.any_eq_any_toList, List.any_eq_true, Bool.and_eq_true, + beq_iff_eq] + refine ⟨(p, n), Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 (by simpa using h1), + ⟨x, hx, hxa⟩, subset_of_sorted (hs _ _ h1).erase hacc fun y hy => ?_⟩ + refine (h3 y (List.mem_of_mem_erase hy)).resolve_left fun e => ?_ + exact absurd (e ▸ hy) ((hs _ _ h1).nodup.not_mem_erase) + +/-- The conditions `rem` can be added to `acc` one at a time, each addition dominated. -/ +inductive NormLevel.Feas (s : NormLevel) : List Name → List Name → Prop + | nil {acc} : Feas s acc [] + | cons {acc a rem} : a ∈ rem → s.Dom a acc → Feas s (a :: acc) (rem.erase a) → Feas s acc rem + +theorem NormLevel.Feas.mono {s : NormLevel} (hs : ∀ x ∈ acc, x ∈ acc') + (h : Feas s acc rem) : Feas s acc' rem := by + induction h generalizing acc' with | nil => exact .nil | cons hm hd _ ih + refine .cons hm (hd.mono hs) <| ih fun x hx => ?_ + obtain rfl | hx := List.mem_cons.1 hx + · exact .head _ + · exact .tail _ (hs _ hx) + +/-- Greedy exchange: a dominated element can always be taken first. -/ +theorem NormLevel.Feas.exchange {s : NormLevel} (h : Feas s acc rem) : + ∀ {a}, a ∈ rem → s.Dom a acc → Feas s (a :: acc) (rem.erase a) := by + induction h with | nil => nofun | @cons acc b rem hmb hdb H ih + intro a hm hd + by_cases hab : a = b <;> [(subst hab; exact H); skip] + refine .cons ((List.mem_erase_of_ne (Ne.symm hab)).2 hmb) (hdb.mono fun x hx => .tail _ hx) ?_ + rw [List.erase_comm] + refine ih ((List.mem_erase_of_ne hab).2 hm) (hd.mono fun x hx => .tail _ hx) + |>.mono fun x hx => ?_ + obtain rfl | hx := List.mem_cons.1 hx + · exact .tail _ (.head _) + · obtain rfl | hx := List.mem_cons.1 hx + · exact .head _ + · exact .tail _ (.tail _ hx) + +/-- Peel off the element added last: it is dominated by all the others. -/ +theorem NormLevel.Feas.peel {s : NormLevel} (h : Feas s acc rem) (nd : rem.Nodup) (hne : rem ≠ []) : + ∃ a ∈ rem, s.Dom a (acc ++ rem.erase a) ∧ Feas s acc (rem.erase a) := by + induction h with + | nil => exact absurd rfl hne + | @cons acc b rem hmb hdb H ih => + by_cases he : rem.erase b = [] + · exact ⟨b, hmb, hdb.mono fun x hx => List.mem_append_left _ hx, he ▸ .nil⟩ + obtain ⟨a, hma, hda, hfa⟩ := ih (nd.erase _) he + have hab : a ≠ b := by rintro rfl; exact absurd hma nd.not_mem_erase + have hmb' : b ∈ rem.erase a := (List.mem_erase_of_ne (Ne.symm hab)).2 hmb + refine ⟨a, List.mem_of_mem_erase hma, hda.mono fun x hx => ?_, ?_⟩ + · simp only [List.cons_append, List.mem_cons, List.mem_append] at hx ⊢ + obtain rfl | hx | hx := hx + · exact .inr hmb' + · exact .inl hx + · rw [List.erase_comm] at hx; exact .inr (List.mem_of_mem_erase hx) + · exact .cons hmb' hdb <| by rw [List.erase_comm]; exact hfa + +theorem NormLevel.feasible_go_sound {s : NormLevel} : + ∀ {fuel acc rem}, NormLevel.feasible.go s fuel acc rem → s.Feas acc rem + | 0, _, rem, h => by simp [feasible.go, List.isEmpty_iff] at h; exact h ▸ .nil + | fuel+1, acc, rem, h => by + rw [feasible.go] at h + split at h <;> [(let [] := rem; exact .nil); rename_i a ha] + have hm := List.mem_of_find?_eq_some ha + have hd := addable_sound (List.find?_eq_some_iff_getElem.1 ha).1 + refine .cons hm hd ((feasible_go_sound h).mono fun x hx => ?_) + exact List.mem_cons.2 ((Extend?.orderedInsert (cmp := Name.cmp) (v := a) (p := acc)).mem.1 hx) + +theorem NormLevel.feasible_sound {s : NormLevel} (h : s.feasible acc rem) : s.Feas acc rem := + feasible_go_sound h + +theorem NormLevel.feasible_go_complete {s : NormLevel} (hs : ∀ p n, s.get? p = some n → Sorted p) : + ∀ {fuel acc rem}, rem.length ≤ fuel → Sorted acc → s.Feas acc rem → feasible.go s fuel acc rem + | 0, _, rem, hf, _, _ => by + rw [feasible.go]; cases rem with | nil => rfl | cons => cases hf + | fuel+1, acc, rem, hf, hacc, h => by + rw [feasible.go] + split <;> [rename_i ha; rename_i a ha] + · -- the first element of the chain is addable, so `find?` cannot fail + cases h with | nil => rfl | @cons b _ _ hm hd + exact absurd (addable_complete hs hacc hd) (by simpa using List.find?_eq_none.1 ha _ hm) + · have hm := List.mem_of_find?_eq_some ha + have hd := addable_sound (List.find?_eq_some_iff_getElem.1 ha).1 + have hext := Extend?.orderedInsert (cmp := Name.cmp) (v := a) (p := acc) + refine feasible_go_complete hs ?_ ?_ ((h.exchange hm hd).mono fun x hx => hext.mem.2 ?_) + · rw [List.length_erase_of_mem hm]; omega + · match he : Normalize.orderedInsert Name.cmp a acc with + | none => exact hacc + | some acc' => exact hacc.orderedInsert he + · exact List.mem_cons.1 hx + +theorem NormLevel.feasible_complete {s : NormLevel} (hs : ∀ p n, s.get? p = some n → Sorted p) + (hacc : Sorted acc) (h : s.Feas acc rem) : s.feasible acc rem := + feasible_go_complete hs (Nat.le_refl _) hacc h + +theorem NormLevel.Feas.perm {s : NormLevel} (h : Feas s acc rem) (hp : rem.Perm rem') : + Feas s acc rem' := by + induction h generalizing rem' with + | nil => cases hp.nil_eq; exact .nil + | cons hm hd _ ih => exact .cons (hp.mem_iff.1 hm) hd (ih (hp.erase _)) + +/-- Extend a chain on the inside: the new element's conditions are all the others. -/ +theorem NormLevel.Feas.cons_last {s : NormLevel} (h : Feas s acc rem) (hnm : a ∉ rem) + (hd : s.Dom a (acc ++ rem)) : Feas s acc (a :: rem) := by + induction h with + | nil => exact .cons (.head _) (by simpa using hd) (by simpa using Feas.nil) + | @cons acc b rem hmb hdb _ ih => + have hab : b ≠ a := fun e => hnm (e ▸ hmb) + refine .cons (.tail _ hmb) hdb ?_ + rw [List.erase_cons_tail (by simpa using Ne.symm hab)] + refine ih (fun h => hnm (List.mem_of_mem_erase h)) (hd.mono fun x hx => ?_) + -- everything outside `a` is still there: `b` moved into the accumulator + simp only [List.cons_append, List.mem_cons, List.mem_append] at hx ⊢ + obtain hx | hx := hx + · exact .inr (.inl hx) + · by_cases hxb : x = b + · exact .inl hxb + · exact .inr (.inr ((List.mem_erase_of_ne hxb).2 hx)) + +/-- Every key of a well-formed normal form admits a chain: its `WF` parent is a key with one +condition fewer, and the variable relating them dominates the edge between them. -/ +theorem NormLevel.WF.feas {s : NormLevel} (wf : s.WF) : ∀ {p}, s.contains p → s.Feas [] p := by + intro p + generalize eq : p.length = len + induction len generalizing p with + | zero => cases List.eq_nil_of_length_eq_zero eq; exact fun _ => .nil + | succ len ih => + intro hp + have hne : p ≠ [] := by rintro rfl; cases eq + obtain ⟨n, hn⟩ := Option.isSome_iff_exists.1 (Std.TreeMap.isSome_getElem?_eq_contains.trans hp) + obtain ⟨v, p', h1, h2, x, hx, hxv⟩ := (wf _ _ hn).1 hne + have hperm : p.Perm (v :: p') := by cases h1; exact List.perm_middle + have hnm : v ∉ p' := by + have := (wf.sortedOf (.inr hp)).nodup + rw [hperm.nodup_iff] at this + exact (List.nodup_cons.1 this).1 + refine Feas.perm ?_ hperm.symm + refine Feas.cons_last (h2.elim (fun e => by subst e; exact .nil) (fun h => ih (by + have := h1.length; omega) h)) hnm ⟨p, n, hn, ⟨x, hx, hxv⟩, fun y hy => ?_⟩ + simpa using (h1.mem.1 hy).imp id id + +/-- Domination only reads off variable names and their keys, so a map that covers another +dominates whatever it does. -/ +theorem NormLevel.Dom.mono_map {s s' : NormLevel} (h : s'.Covers s) (hd : s.Dom a acc) : + s'.Dom a acc := by + obtain ⟨p, n, hp, ⟨x, hx, hxa⟩, hcond⟩ := hd + obtain ⟨q, m, y, hq, hy, e, hsub⟩ := h _ _ _ hp hx + exact ⟨q, m, hq, ⟨y, hy, e.trans hxa⟩, fun z hz => hcond _ (hsub _ hz)⟩ + +theorem NormLevel.Feas.mono_map {s s' : NormLevel} (h : s'.Covers s) : + ∀ {acc rem}, s.Feas acc rem → s'.Feas acc rem + | _, _, .nil => .nil + | _, _, .cons hm hd H => .cons hm (hd.mono_map h) (Feas.mono_map h H) + +/-- Every key of the normal form admits a chain. `WF.feas` gives this for the map `normalizeAux` +builds; subsumption keeps it because it covers that map, dropping a variable only in favour of +one with the same name at a smaller key. -/ +theorem normalize_feas : ∀ p, (normalize u).contains p → (normalize u).Feas [] p := by + intro p hp + have wf : (normalizeAux u [] 0 {}).WF := normalizeAux_wf (by simp) (by simp [NormLevel.WF]) + refine NormLevel.Feas.mono_map NormLevel.subsumption_covers.2 (wf.feas ?_) + obtain ⟨n, hn⟩ := Option.isSome_iff_exists.1 (Std.TreeMap.isSome_getElem?_eq_contains.trans hp) + obtain ⟨n₀, h₀, -⟩ := NormLevel.subsumption_covers.1 p n + (by rw [Std.TreeMap.get?_eq_getElem?]; exact hn) + exact Std.TreeMap.isSome_getElem?_eq_contains.symm.trans + (by simp [Std.TreeMap.get?_eq_getElem?] at h₀; simp [h₀]) + +/-- An admissible chain, innermost first: each element is dominated relative to the +conditions outside it. -/ +def NormLevel.Adm (s : NormLevel) : List Name → Prop + | [] => True + | a :: l => s.Dom a l ∧ s.Adm l + +/-- `lexChain` always reorders its input, even in the fallback branch. -/ +theorem NormLevel.lexChain_perm {s : NormLevel} : ∀ {fuel p}, (s.lexChain fuel p).Perm p + | 0, p => by rw [lexChain] + | fuel+1, p => by + rw [lexChain] + split + · rename_i a ha + exact .trans (.cons _ lexChain_perm) + (List.perm_cons_erase (List.mem_of_find?_eq_some ha)).symm + · exact .refl _ + +/-- Whenever a key admits some chain, `lexChain` returns one: it reorders the key, and +every edge of the resulting `imax` chain is dominated. -/ +theorem NormLevel.lexChain_spec {s : NormLevel} (hs : ∀ p n, s.get? p = some n → Sorted p) : + ∀ {fuel p}, p.length ≤ fuel → Sorted p → s.Feas [] p → + (s.lexChain fuel p).Perm p ∧ s.Adm (s.lexChain fuel p) + | 0, p, hf, _, _ => by + rw [lexChain]; cases p with | nil => exact ⟨.refl _, trivial⟩ | cons => cases hf + | fuel+1, p, hf, hp, h => by + rw [lexChain] + split + · rename_i a ha + have hm := List.mem_of_find?_eq_some ha + have hpred := List.find?_eq_some_iff_getElem.1 ha |>.1 + simp only [Bool.and_eq_true] at hpred + have hlen : (p.erase a).length ≤ fuel := by + rw [List.length_erase_of_mem hm]; omega + obtain ⟨hperm, hadm⟩ := + lexChain_spec hs hlen hp.erase (feasible_sound hpred.2) + refine ⟨.trans (.cons _ hperm) (List.perm_cons_erase hm).symm, ?_, hadm⟩ + exact (addable_sound hpred.1).mono fun x hx => hperm.mem_iff.2 hx + · rename_i hnone + -- the chain that exists ends somewhere, and `find?` would have found that element + refine ⟨.refl _, ?_⟩ + match p, h with + | [], _ => exact trivial + | b :: p, h => + obtain ⟨a, hm, hd, hfa⟩ := h.peel hp.nodup (by simp) + have h1 : s.addable a ((b :: p).erase a) := + addable_complete hs hp.erase (by simpa using hd) + have h2 : s.feasible [] ((b :: p).erase a) := feasible_complete hs Sorted.nil hfa + have hnot := List.find?_eq_none.1 hnone _ hm + simp [h1, h2] at hnot + +theorem NormLevel.Adm.suffix {s : NormLevel} : ∀ {l}, s.Adm l → a :: q <:+ l → s.Dom a q + | [], _, h => by simp at h + | b :: l, ⟨h1, h2⟩, h => by + obtain ⟨l', he⟩ := h + match l' with + | [] => cases he; exact h1 + | c :: l' => exact Adm.suffix h2 ⟨l', by cases he; rfl⟩ + +/-! ### Building the tree -/ + +theorem evalPath_le_self : evalPath ls ρ path c ≤ c := by rw [evalPath]; split <;> simp + +theorem evalPath_perm (h : p.Perm p') : evalPath ls ρ p c = evalPath ls ρ p' c := by + simp only [evalPath, show allNZ ls ρ p = allNZ ls ρ p' from Bool.eq_iff_iff.2 + ⟨allNZ_mono fun _ hx => h.symm.mem_iff.1 hx, allNZ_mono fun _ hx => h.mem_iff.1 hx⟩] + +theorem evalPath_singleton : + evalPath ls ρ [a] c = if 0 < evalParam ls ρ a then c else 0 := by simp [evalPath, allNZ] + +theorem evalPath_single : evalPath ls ρ p (evalPath ls ρ [a] c) = evalPath ls ρ (a :: p) c := by + rw [evalPath_singleton, ← evalPath_cons] + +theorem imax_eq_evalPath : Lean.Nat.imax c (evalParam ls ρ a) = + max' (evalPath ls ρ [a] c) (evalPath ls ρ [a] (evalParam ls ρ a)) := by + by_cases h : evalParam ls ρ a = 0 <;> + simp [imax_eq_ite, evalPath_singleton, h, Nat.pos_of_ne_zero] + +/-- `modify` read from the outside in, matching the way `Tree.At` extends a path: the +shallowest element of the path selects a child, and the rest is modified inside it. -/ +theorem Tree.modify_append (path : List Name) (g : Tree → Tree) (b : Name) (t : Tree) : + Tree.modify (path ++ [b]) g t = + { t with child := modifyAt (Tree.modify path g) b t.child } := by + induction path generalizing t g with + | nil => rfl + | cons a p ih => rw [List.cons_append, Tree.modify, ih]; rfl + +/-- All that matters about `modifyAt`: it replaces one entry with key `a` by `f` of it, or +inserts `(a, f default)` somewhere if there is none, and leaves the rest of the list alone. -/ +theorem modifyAt_eq (f : Tree → Tree) (a : Name) (l : List (Name × Tree)) : + ∃ l₁ l₂ y, modifyAt f a l = l₁ ++ (a, f y) :: l₂ ∧ + (l = l₁ ++ l₂ ∧ y = default ∨ l = l₁ ++ (a, y) :: l₂) := by + induction l with + | nil => exact ⟨[], [], default, rfl, .inl ⟨rfl, rfl⟩⟩ + | cons b l ih => + obtain ⟨b, t⟩ := b + match he : Name.cmp a b with + | .lt => exact ⟨[], (b, t) :: l, default, by simp [modifyAt, he], .inl ⟨rfl, rfl⟩⟩ + | .eq => + rw [Std.LawfulBEqCmp.compare_eq_iff_beq (cmp := Name.cmp)] at he + cases eq_of_beq he + exact ⟨[], l, t, by + simp [modifyAt, Std.ReflCmp.compare_self (cmp := Name.cmp)], .inr rfl⟩ + | .gt => + obtain ⟨l₁, l₂, y, h1, h2⟩ := ih + exact ⟨(b, t) :: l₁, l₂, y, by simp [modifyAt, he, h1], + h2.imp (fun ⟨h, hy⟩ => ⟨by simp [h], hy⟩) fun h => by simp [h]⟩ + +theorem mem_modifyAt_self (f : Tree → Tree) (a : Name) (l : List (Name × Tree)) : + ∃ y, (a, f y) ∈ modifyAt f a l := by + obtain ⟨l₁, l₂, y, h, -⟩ := modifyAt_eq f a l + exact ⟨y, by rw [h]; simp⟩ + +/-- The node `modify` writes is there to be found, and its data does not depend on what was +at the path before: the payload of a key is what sits at the end of its chain. -/ +theorem Tree.At_modify_self (path : List Name) (g : Tree → Tree) (t : Tree) : + ∃ t₀, Tree.At (t.modify path g) path (g t₀) := by + suffices ∀ (r : List Name) (g : Tree → Tree) (t : Tree), + ∃ t₀, Tree.At (Tree.modify r.reverse g t) r.reverse (g t₀) by + simpa using this path.reverse g t + clear path g t; intro r + induction r with + | nil => exact fun g t => ⟨t, .nil⟩ + | cons b r ih => + intro g t + rw [List.reverse_cons, Tree.modify_append] + obtain ⟨x, hx⟩ := mem_modifyAt_self (f := Tree.modify r.reverse g) b t.child + obtain ⟨t₀, ht₀⟩ := ih g x + exact ⟨t₀, ht₀.append hx⟩ + +/-- Nothing is lost: an entry either survives `modifyAt` untouched, or is the one it modifies. +(The second case does not need the entry to be the *first* one with its key, so no +duplicate-freedom assumption is needed here or below.) -/ +theorem mem_modifyAt {f : Tree → Tree} {l : List (Name × Tree)} (hm : (c, x) ∈ l) : + (c, x) ∈ modifyAt f a l ∨ (c = a ∧ (c, f x) ∈ modifyAt f a l) := by + obtain ⟨l₁, l₂, y, h, h'⟩ := modifyAt_eq f a l + rw [h] + obtain ⟨rfl, -⟩ | rfl := h' + · obtain hm | hm := List.mem_append.1 hm + · exact .inl (List.mem_append.2 (.inl hm)) + · exact .inl (List.mem_append.2 (.inr (.tail _ hm))) + · obtain hm | hm := List.mem_append.1 hm + · exact .inl (List.mem_append.2 (.inl hm)) + obtain heq | hm := List.mem_cons.1 hm + · simp only [Prod.mk.injEq] at heq; obtain ⟨rfl, rfl⟩ := heq + exact .inr ⟨rfl, List.mem_append.2 (.inr (.head _))⟩ + · exact .inl (List.mem_append.2 (.inr (.tail _ hm))) + +/-- A node written at one path survives a later write at a different path: the write only +replaces the data of the node it lands on, and every other node keeps its own. -/ +theorem Tree.At_modify_of_ne_aux {g : Tree → Tree} (hg : ∀ t, (g t).child = t.child) : + ∀ (r : List Name) {path t t'}, path ≠ r.reverse → At t path t' → + ∃ t'', At (Tree.modify r.reverse g t) path t'' ∧ + t''.const = t'.const ∧ t''.var = t'.var := by + intro r + induction r with + | nil => + intro path t t' hne h + rw [List.reverse_nil, Tree.modify] + obtain h' | ⟨rfl, rfl⟩ := h.of_child_eq (hg t) + · exact ⟨t', h', rfl, rfl⟩ + · exact absurd rfl hne + | cons b r ih => + intro path t t' hne h + rw [List.reverse_cons, Tree.modify_append] + obtain rfl | ⟨q, a, rfl⟩ := List.eq_nil_or_concat path + · cases h.nil_inv; exact ⟨_, .nil, rfl, rfl⟩ + simp only [List.concat_eq_append, List.reverse_cons] at h hne ⊢ + obtain ⟨t₁, hm, h₁⟩ := h.append_inv + obtain hm' | ⟨rfl, hm'⟩ := mem_modifyAt (f := Tree.modify r.reverse g) (a := b) hm + · exact ⟨t', h₁.append hm', rfl, rfl⟩ + · have : q ≠ r.reverse := by rintro rfl; exact hne rfl + obtain ⟨t'', h'', hc, hv⟩ := ih this h₁ + exact ⟨t'', h''.append hm', hc, hv⟩ + +theorem Tree.At_modify_of_ne {g : Tree → Tree} (hg : ∀ t, (g t).child = t.child) + (hne : path ≠ path') (h : At t path t') : + ∃ t'', At (Tree.modify path' g t) path t'' ∧ t''.const = t'.const ∧ t''.var = t'.var := by + have := At_modify_of_ne_aux hg path'.reverse (path := path) (by rwa [List.reverse_reverse]) h + rwa [List.reverse_reverse] at this + +/-- Conversely, nothing appears from nowhere: an entry of `modifyAt` is an entry of the list, +or the modified one, which was an entry or is fresh. -/ +theorem mem_modifyAt_inv {f : Tree → Tree} {l : List (Name × Tree)} + (h : (c, x) ∈ modifyAt f a l) : + (c, x) ∈ l ∨ (c = a ∧ ∃ y, x = f y ∧ (y = default ∨ (a, y) ∈ l)) := by + induction l with + | nil => + simp only [modifyAt, List.mem_singleton, Prod.mk.injEq] at h + obtain ⟨rfl, rfl⟩ := h + exact .inr ⟨rfl, default, rfl, .inl rfl⟩ + | cons b l ih => + obtain ⟨b, t⟩ := b + match he : Name.cmp a b with + | .lt => + simp only [modifyAt, he] at h + obtain h | h := List.mem_cons.1 h + · cases h; exact .inr ⟨rfl, default, rfl, .inl rfl⟩ + · exact .inl h + | .eq => + rw [Std.LawfulBEqCmp.compare_eq_iff_beq (cmp := Name.cmp)] at he + cases eq_of_beq he + simp only [modifyAt, Std.ReflCmp.compare_self (cmp := Name.cmp)] at h + obtain h | h := List.mem_cons.1 h + · cases h; exact .inr ⟨rfl, t, rfl, .inr (.head _)⟩ + · exact .inl (.tail _ h) + | .gt => + simp only [modifyAt, he] at h + obtain h | h := List.mem_cons.1 h + · cases h; exact .inl (.head _) + · exact (ih h).imp (.tail _) fun ⟨rfl, y, hy, h⟩ => ⟨rfl, y, hy, h.imp id (.tail _)⟩ + +theorem Tree.At.of_child_nil (hc : t.child = []) (h : At t p t') : p = [] ∧ t' = t := by + obtain rfl | ⟨q, a, rfl⟩ := List.eq_nil_or_concat p + · exact ⟨rfl, h.nil_inv⟩ + · rw [List.concat_eq_append] at h + obtain ⟨t₁, hm, -⟩ := h.append_inv + rw [hc] at hm; cases hm + +theorem suffix_concat {α} {l₁ l₂ : List α} (h : l₁ <:+ l₂) (a : α) : + l₁ ++ [a] <:+ l₂ ++ [a] := by + obtain ⟨u, rfl⟩ := h; exact ⟨u, by rw [List.append_assoc]⟩ + +/-- Inverting a write: a path of the modified tree either ends at the node just written, or +is a tail of the written path whose node was created empty on the way, or was already there +carrying the same data. -/ +theorem Tree.At_modify_inv_aux {g : Tree → Tree} (hg : ∀ t, (g t).child = t.child) : + ∀ (r : List Name) {path t t'}, At (Tree.modify r.reverse g t) path t' → + (path = r.reverse ∧ ∃ t₀, t' = g t₀) ∨ + (path <:+ r.reverse ∧ t'.const = 0 ∧ t'.var = []) ∨ + (∃ t'', At t path t'' ∧ t'.const = t''.const ∧ t'.var = t''.var) := by + intro r + induction r with + | nil => + intro path t t' h + rw [List.reverse_nil, Tree.modify] at h + obtain h' | ⟨rfl, rfl⟩ := h.of_child_eq (hg t).symm + · exact .inr (.inr ⟨t', h', rfl, rfl⟩) + · exact .inl ⟨rfl, t, rfl⟩ + | cons b r ih => + intro path t t' h + rw [List.reverse_cons, Tree.modify_append] at h + obtain rfl | ⟨q, a, rfl⟩ := List.eq_nil_or_concat path + · cases h.nil_inv; exact .inr (.inr ⟨t, .nil, rfl, rfl⟩) + rw [List.concat_eq_append] at h ⊢ + obtain ⟨t₁, hm, h₁⟩ := h.append_inv + obtain hm | ⟨rfl, y, rfl, hy⟩ := mem_modifyAt_inv hm + · exact .inr (.inr ⟨t', h₁.append hm, rfl, rfl⟩) + · obtain ⟨rfl, t₀, rfl⟩ | ⟨hs, hc, hv⟩ | ⟨t'', h'', hc, hv⟩ := ih h₁ + · exact .inl ⟨by rw [List.reverse_cons], t₀, rfl⟩ + · exact .inr (.inl ⟨by rw [List.reverse_cons]; exact suffix_concat hs _, hc, hv⟩) + · obtain rfl | hy := hy + · obtain ⟨rfl, rfl⟩ := h''.of_child_nil rfl + exact .inr (.inl ⟨by rw [List.reverse_cons]; exact ⟨r.reverse, by simp⟩, hc, hv⟩) + · exact .inr (.inr ⟨t'', h''.append hy, hc, hv⟩) + +theorem Tree.At_modify_inv {g : Tree → Tree} (hg : ∀ t, (g t).child = t.child) + (h : At (Tree.modify path' g t) path t') : + (path = path' ∧ ∃ t₀, t' = g t₀) ∨ + (path <:+ path' ∧ t'.const = 0 ∧ t'.var = []) ∨ + (∃ t'', At t path t'' ∧ t'.const = t''.const ∧ t'.var = t''.var) := by + have := At_modify_inv_aux hg path'.reverse (path := path) + (by rwa [List.reverse_reverse]) (t' := t') + rwa [List.reverse_reverse] at this + +/-- Sorted lists with the same elements are equal, so distinct keys reify to distinct paths: +`lexChain` only permutes a key. -/ +theorem Sorted.perm_eq (h₁ : Sorted l₁) (h₂ : Sorted l₂) (h : l₁.Perm l₂) : l₁ = l₂ := by + induction l₁ generalizing l₂ with + | nil => exact h.nil_eq + | cons a l₁ ih => + match l₂, h₂, h with + | [], _, h => simp at h + | b :: l₂, h₂, h => + have hab : a = b := by + -- each head is at most every element of the other list + obtain rfl | ha := List.mem_cons.1 (h.mem_iff.1 (.head _)) + · rfl + obtain rfl | hb := List.mem_cons.1 (h.symm.mem_iff.1 (.head _)) + · rfl + exact absurd (h₂.head _ ha) (by + rw [Std.OrientedCmp.gt_of_lt (h₁.head _ hb)]; simp) + subst hab + rw [ih h₁.of_cons h₂.of_cons ((List.perm_cons _).1 h)] + +/-- The variables the reconstruction records for the entry `(p, n)`: those of `n`, except the +one the edge into the node already contributes. -/ +def NormLevel.treeVar (s : NormLevel) (p : List Name) (n : Node) : List VarNode := + if let v :: _ := s.lexChain p.length p then subsumeVars n.var [⟨v, 0⟩] else n.var + +/-- The entry `(p, n)` is recorded in `t`: at the end of `p`'s chain sits a node carrying +`n`'s constant and `treeVar p n`. -/ +def NormLevel.WrittenAt (s : NormLevel) (t : Tree) (p : List Name) (n : Node) : Prop := + ∃ t', Tree.At t (s.lexChain p.length p) t' ∧ t'.const = n.const ∧ t'.var = s.treeVar p n + +theorem NormLevel.WrittenAt.write {s : NormLevel} (t : Tree) (p : List Name) (n : Node) : + s.WrittenAt (t.modify (s.lexChain p.length p) + fun t => { t with const := n.const, var := s.treeVar p n }) p n := + let ⟨_, h⟩ := Tree.At_modify_self _ _ t + ⟨_, h, rfl, rfl⟩ + +/-- Distinct keys get distinct chains, since `lexChain` only permutes a sorted key. -/ +theorem NormLevel.lexChain_inj {s : NormLevel} (h₁ : Sorted p) (h₂ : Sorted p') + (h : s.lexChain p.length p = s.lexChain p'.length p') : p = p' := by + refine Sorted.perm_eq h₁ h₂ ((lexChain_perm (s := s) (fuel := p.length) (p := p)).symm.trans ?_) + rw [h]; exact lexChain_perm + +/-- Conversely, everything the tree contains comes from an entry: every nonempty path is a +tail of some key's chain, and the node at the end of a path is either empty scaffolding or +the entry whose chain leads there. -/ +def NormLevel.Accounted (s : NormLevel) (t : Tree) : Prop := + ∀ path t', Tree.At t path t' → + (path ≠ [] → ∃ p n, s.get? p = some n ∧ path <:+ s.lexChain p.length p) ∧ + (t'.const = 0 ∧ t'.var = [] ∨ ∃ p n, s.get? p = some n ∧ + path = s.lexChain p.length p ∧ t'.const = n.const ∧ t'.var = s.treeVar p n) + +/-- The single pass over the map that both directions of soundness read off: after the fold +every entry is recorded at the end of its chain, and everything in the tree is accounted for +by an entry. A write puts its own entry there (`At_modify_self`) and leaves the others alone, +either because it lands on a different path — distinct keys have distinct chains — or because +it lands on the same key, and then writes the same data. -/ +theorem NormLevel.toTree_spec {s : NormLevel} (hsort : ∀ p n, s.get? p = some n → Sorted p) : + s.Accounted (toTree s) ∧ ∀ p n, s.get? p = some n → s.WrittenAt (toTree s) p n := by + rw [toTree, Std.TreeMap.foldl_eq_foldl_toList] + have hmem : ∀ pn : List Name × Node, pn ∈ s.toList ↔ s.get? pn.1 = some pn.2 := fun _ => + Std.TreeMap.mem_toList_iff_getElem?_eq_some.trans (by rw [Std.TreeMap.get?_eq_getElem?]) + have hinit : s.Accounted ⟨0, [], []⟩ := fun path t' h => by + obtain ⟨rfl, rfl⟩ := h.of_child_nil rfl + exact ⟨fun h => absurd rfl h, .inl ⟨rfl, rfl⟩⟩ + suffices ∀ (l : List (List Name × Node)) (t : Tree), + (∀ pn ∈ l, s.get? pn.1 = some pn.2) → s.Accounted t → + s.Accounted (List.foldl (fun t pn => + let path := s.lexChain pn.1.length pn.1 + let var := if let v :: _ := path then subsumeVars pn.2.var [⟨v, 0⟩] else pn.2.var + t.modify path fun t => { t with const := pn.2.const, var }) t l) ∧ + ∀ p n, s.get? p = some n → (s.WrittenAt t p n ∨ (p, n) ∈ l) → + s.WrittenAt (List.foldl (fun t pn => + let path := s.lexChain pn.1.length pn.1 + let var := if let v :: _ := path then subsumeVars pn.2.var [⟨v, 0⟩] else pn.2.var + t.modify path fun t => { t with const := pn.2.const, var }) t l) p n by + have := this _ _ (fun pn h => (hmem pn).1 h) hinit + exact ⟨this.1, fun p n hp => this.2 p n hp (.inr ((hmem (p, n)).2 hp))⟩ + clear hmem hinit; intro l + induction l with + | nil => exact fun _ _ h => ⟨h, fun _ _ _ h => h.resolve_right (by simp)⟩ + | cons pn l ih => + obtain ⟨p', n'⟩ := pn + intro t hl hacc + have hp' : s.get? p' = some n' := hl _ (.head _) + refine (ih _ (fun _ h => hl _ (.tail _ h)) ?_).imp id fun H p n hp h => H p n hp ?_ + · -- nothing unaccounted for appears: the write adds its own node and empty scaffolding + intro path t' h + obtain ⟨rfl, t₀, rfl⟩ | ⟨hs, hc, hv⟩ | ⟨t'', h'', hc, hv⟩ := + Tree.At_modify_inv (g := fun t => + { t with const := n'.const, var := s.treeVar p' n' }) (fun _ => rfl) h + · exact ⟨fun _ => ⟨p', n', hp', List.suffix_refl _⟩, .inr ⟨p', n', hp', rfl, rfl, rfl⟩⟩ + · exact ⟨fun _ => ⟨p', n', hp', hs⟩, .inl ⟨hc, hv⟩⟩ + · exact ⟨(hacc _ _ h'').1, by rw [hc, hv]; exact (hacc _ _ h'').2⟩ + · -- and nothing already written is lost + obtain ⟨t', hat, hc, hv⟩ | h := h + · refine .inl ?_ + by_cases hpp : p = p' + · subst hpp; cases hp.symm.trans hp'; exact .write .. + · obtain ⟨t'', hat', hc', hv'⟩ := Tree.At_modify_of_ne (g := fun t => + { t with const := n'.const, var := s.treeVar p' n' }) (fun _ => rfl) + (fun he => hpp (lexChain_inj (hsort _ _ hp) (hsort _ _ hp') he)) hat + exact ⟨t'', hat', hc' ▸ hc, hv' ▸ hv⟩ + · obtain h | h := List.mem_cons.1 h + · simp only [Prod.mk.injEq] at h + obtain ⟨rfl, rfl⟩ := h + exact .inl (.write ..) + · exact .inr h + +/-- What the reconstruction contributes, as a biconditional: the tree is bounded by `m` +exactly when for every entry the node the tree records for it is, and so is every edge of its +chain. Nothing here is about domination, so no hypothesis on the chains is needed. -/ +theorem NormLevel.toTree_le_iff {s : NormLevel} (hsort : ∀ p n, s.get? p = some n → Sorted p) + {m : Nat} : Tree.eval ls ρ (toTree s) ≤ m ↔ + ∀ p n, s.get? p = some n → + evalPath ls ρ (s.lexChain p.length p) (Node.eval ls ρ ⟨n.const, s.treeVar p n⟩) ≤ m ∧ + ∀ a q, a :: q <:+ s.lexChain p.length p → + evalPath ls ρ (a :: q) (evalParam ls ρ a) ≤ m := by + obtain ⟨hacc, hwr⟩ := toTree_spec hsort + rw [Tree.eval_le_iff] + refine ⟨fun ⟨h1, h2⟩ p n hp => ?_, fun H => ⟨fun path t' hat => ?_, fun a q t' hat => ?_⟩⟩ + · obtain ⟨t', hat, hc, hv⟩ := hwr p n hp + refine ⟨by rw [← hc, ← hv]; exact h1 _ _ hat, fun a q hq => ?_⟩ + obtain ⟨t'', hat''⟩ := hat.suffix hq + exact h2 _ _ _ hat'' + · obtain ⟨-, ⟨hc, hv⟩ | ⟨p, n, hp, rfl, hc, hv⟩⟩ := hacc _ _ hat + · rw [show Node.eval ls ρ ⟨t'.const, t'.var⟩ = 0 from by simp [Node.eval, hc, hv]] + simp [evalPath] + · rw [hc, hv]; exact (H p n hp).1 + · obtain ⟨p, n, hp, hsuf⟩ := (hacc _ _ hat).1 (by simp) + exact (H p n hp).2 _ _ hsuf + +/-- Soundness of the reconstruction: the tree built from a normal form, hence the level it +reifies to, evaluates like the normal form. Below, because the node recorded for an entry +carries a subset of its sublevels and every edge is dominated, `lexChain` emitting only +admissible chains; above, because the one sublevel the node omits, `V(p, v, 0)` for the +innermost element of the chain, is what the edge into it contributes. -/ +theorem NormLevel.toTree_eval {s : NormLevel} (hsort : ∀ p n, s.get? p = some n → Sorted p) + (hfeas : ∀ p, s.contains p → s.Feas [] p) : + Tree.eval ls ρ (toTree s) = s.eval ls ρ := by + refine ext_le fun m => (toTree_le_iff hsort).trans (Iff.trans ?_ NormLevel.eval_le.symm) + refine ⟨fun H p n hp => ?_, fun H p n hp => ⟨?_, fun a q hq => ?_⟩⟩ + · -- the entry is the node the tree records for it, plus the edge into that node + rw [← evalPath_perm (lexChain_perm (s := s) (fuel := p.length) (p := p))] + refine evalPath_le.2 fun nz => ?_ + have h1 := evalPath_le.1 (H p n hp).1 nz + rw [Node.eval_le] at h1 ⊢ + refine ⟨h1.1, ?_⟩ + rw [NormLevel.treeVar] at h1 + split at h1 + · rename_i v q hch + refine (subsumeVars_eval ?_).1 h1.2 + simp only [List.mem_singleton, VarNode.eval] + rintro _ rfl + exact evalPath_le.1 ((H p n hp).2 v q (by rw [hch]; exact List.suffix_refl _)) (hch ▸ nz) + · exact h1.2 + · -- the recorded node is part of the entry + rw [evalPath_perm (lexChain_perm (s := s) (fuel := p.length) (p := p))] + refine Nat.le_trans (evalPath_mono ?_) (H p n hp) + refine Node.eval_le.2 ⟨Node.const_le_eval (l := n), fun v hv => Node.var_le_eval ?_⟩ + revert hv; rw [NormLevel.treeVar]; split + · exact subsumeVars_subset + · exact id + · -- and every edge of the chain is dominated by an entry + have hcon : s.contains p := Std.TreeMap.isSome_getElem?_eq_contains.symm.trans + (by simp [Std.TreeMap.get?_eq_getElem?] at hp; simp [hp]) + obtain ⟨-, hadm⟩ := lexChain_spec hsort (Nat.le_refl _) (hsort _ _ hp) (hfeas _ hcon) + exact Nat.le_trans (hadm.suffix hq).le (NormLevel.eval_le.2 H) + +/-! +### Completeness + +`geq'` and `isEquiv'` are not only sound but complete: `NormLevel.le` detects every semantic +inequality between normal forms, and semantically equal levels have equal normal forms. The +key is a converse to Theorem 39 (`NormLevel.le_eval`): evaluating at a valuation tailored to +a single sublevel shows that a semantic bound forces a syntactic dominator among the +sublevels of the bounding form (`separation`). Completeness of `le` then follows because the +`subsumeBy` fold removes exactly the dominated sublevels, and canonicity because +`subsumption` leaves no sublevel dominated by another slot (`Reduced`), so mutual domination +forces the two maps to be equal. +-/ + +/-- The variable lists of nodes are strictly sorted by variable name. -/ +def VarsSorted (l : List VarNode) : Prop := l.Pairwise (compare ·.var ·.var = .lt) + +theorem VarsSorted.of_cons (h : VarsSorted (v :: l)) : VarsSorted l := (List.pairwise_cons.1 h).2 + +theorem VarsSorted.head (h : VarsSorted (v :: l)) : ∀ x ∈ l, compare v.var x.var = .lt := + (List.pairwise_cons.1 h).1 + +/-- In a sorted variable list, the name determines the entry. -/ +theorem VarsSorted.eq_of_var_eq (h : VarsSorted l) (h₁ : x ∈ l) (h₂ : y ∈ l) + (e : x.var = y.var) : x = y := by + induction l with | nil => cases h₁ | cons v l ih + obtain rfl | h₁' := List.mem_cons.1 h₁ + · obtain rfl | h₂' := List.mem_cons.1 h₂ + · rfl + · have := h.head _ h₂'; rw [e, Std.ReflOrd.compare_self] at this; cases this + · obtain rfl | h₂' := List.mem_cons.1 h₂ + · have := h.head _ h₁'; rw [← e, Std.ReflOrd.compare_self] at this; cases this + · exact ih h.of_cons h₁' h₂' + +theorem VarNode.mem_addVar' (h : x ∈ VarNode.addVar v k l) : x.var = v ∨ x ∈ l := by + induction l with + | nil => simp [addVar] at h; simp [h] + | cons y l ih => + simp only [addVar] at h + split at h + · rcases List.mem_cons.1 h with rfl | h <;> simp [h] + · rcases List.mem_cons.1 h with rfl | h <;> simp [h] + · rcases List.mem_cons.1 h with rfl | h + · simp + · exact (ih h).imp_right (.tail _) + +theorem VarNode.addVar_sorted (h : VarsSorted l) : VarsSorted (VarNode.addVar v k l) := by + induction l with | nil => exact .cons (by simp) .nil | cons x l ih + simp only [addVar] + split <;> rename_i hc + · refine .cons (fun y hy => ?_) h + obtain rfl | hy := List.mem_cons.1 hy + · exact hc + · exact Std.TransCmp.lt_trans hc (h.head _ hy) + · rw [Std.LawfulBEqCmp.compare_eq_iff_beq] at hc + have e := eq_of_beq hc + exact .cons (fun y hy => by rw [e]; exact h.head _ hy) h.of_cons + · refine .cons (fun y hy => ?_) (ih h.of_cons) + obtain e | hy := VarNode.mem_addVar' hy + · rw [e]; exact Std.OrientedCmp.lt_of_gt hc + · exact h.head _ hy + +/-- Every node of the map has its variable list sorted by name. -/ +def NormLevel.SortedVars (s : NormLevel) : Prop := + ∀ p n, s.get? p = some n → VarsSorted n.var + +theorem NormLevel.addVar_sortedVars (h : acc.SortedVars) : + (addVar v k path acc).SortedVars := by + intro p n hn + simp only [addVar, Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_modify] at hn + split at hn + · obtain ⟨n', hn', rfl⟩ := Option.map_eq_some_iff.1 hn + exact VarNode.addVar_sorted (h path n' (Std.TreeMap.get?_eq_getElem? .. ▸ hn')) + · exact h _ _ (Std.TreeMap.get?_eq_getElem? .. ▸ hn) + +theorem NormLevel.addNode_sortedVars (h : acc.SortedVars) : + (addNode v k path acc).SortedVars := by + intro p n hn + simp only [addNode, Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_alter] at hn + split at hn + · match e : acc[path]?, hn with + | some n', hn => + cases hn; exact VarNode.addVar_sorted (h path n' (Std.TreeMap.get?_eq_getElem? .. ▸ e)) + | none, hn => cases hn; exact .cons (by simp) .nil + · exact h _ _ (Std.TreeMap.get?_eq_getElem? .. ▸ hn) + +theorem NormLevel.addConst_sortedVars (h : acc.SortedVars) : + (addConst k path acc).SortedVars := by + intro p n hn + simp only [addConst] at hn; split at hn <;> [exact h _ _ hn; skip] + simp only [Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_alter] at hn + split at hn + · match e : acc[path]?, hn with + | some n', hn => cases hn; exact h path n' (Std.TreeMap.get?_eq_getElem? .. ▸ e) + | none, hn => cases hn; exact .nil + · exact h _ _ (Std.TreeMap.get?_eq_getElem? .. ▸ hn) + +theorem normalizeAux_sortedVars (h : acc.SortedVars) : + (normalizeAux u path k acc).SortedVars := by + unfold normalizeAux; split + · exact NormLevel.addConst_sortedVars h + · exact NormLevel.addConst_sortedVars h + · exact normalizeAux_sortedVars h + · exact normalizeAux_sortedVars (normalizeAux_sortedVars h) + · exact normalizeAux_sortedVars (normalizeAux_sortedVars h) + · exact normalizeAux_sortedVars (normalizeAux_sortedVars h) + · exact normalizeAux_sortedVars (normalizeAux_sortedVars h) + · split <;> [skip; (dsimp; split)] + · exact normalizeAux_sortedVars + (NormLevel.addNode_sortedVars (NormLevel.addConst_sortedVars h)) + · exact normalizeAux_sortedVars h + · exact normalizeAux_sortedVars (NormLevel.addVar_sortedVars h) + · exact h + · exact h + · split <;> [skip; split] + · exact NormLevel.addNode_sortedVars (NormLevel.addConst_sortedVars h) + · exact h + · exact NormLevel.addVar_sortedVars h + +theorem subsumeVars_sublist : ∀ vs₁ vs₂ : List VarNode, List.Sublist (subsumeVars vs₁ vs₂) vs₁ + | [], _ => by simp [subsumeVars] + | _ :: _, [] => by simp [subsumeVars] + | x :: xs, y :: ys => by + simp only [subsumeVars]; split + · exact (subsumeVars_sublist xs (y :: ys)).cons_cons x + · split + · exact (subsumeVars_sublist xs ys).cons x + · exact (subsumeVars_sublist xs ys).cons_cons x + · exact subsumeVars_sublist (x :: xs) ys + +theorem Node.subsume_var_sublist : List.Sublist (Node.subsume p₁ n₁ p₂ n₂).var n₁.var := by + obtain h | ⟨-, -, h⟩ := Node.subsume_var_cases p₁ n₁ p₂ n₂ <;> rw [h] + · exact List.Sublist.refl _ + · exact subsumeVars_sublist .. + +theorem NormLevel.minimize_var_sublist {acc : NormLevel} : + List.Sublist (acc.minimize p₁ n₁).var n₁.var := by + rw [minimize, Std.TreeMap.foldl_eq_foldl_toList] + generalize acc.toList = l + induction l generalizing n₁ with | nil => exact List.Sublist.refl _ | cons a l ih + exact (ih (n₁ := Node.subsume p₁ n₁ a.1 a.2)).trans Node.subsume_var_sublist + +theorem NormLevel.subsumption_sortedVars {s : NormLevel} (hs : s.SortedVars) : + s.subsumption.SortedVars := by + rw [subsumption, Std.TreeMap.foldl_eq_foldl_toList] + have hmem pn (h : pn ∈ s.toList) : s.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + generalize s.toList = l at hmem + suffices ∀ (l : List (List Name × Node)) (acc : NormLevel), + (∀ pn ∈ l, s.get? pn.1 = some pn.2) → acc.SortedVars → + ∀ p n, (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).get? p = some n → + VarsSorted n.var from this _ _ hmem hs + clear hmem; intro l + induction l with | nil => exact fun _ _ => id | cons pn l ih + intro acc hl hacc + refine ih _ (fun _ h => hl _ (.tail _ h)) fun p n h => ?_ + rw [subsumption_step_get?] at h + split at h + · split at h <;> [cases h; skip] + cases h; rename_i hp _; subst hp + exact (hs _ _ (hl _ (.head _))).sublist minimize_var_sublist + · exact hacc _ _ h + +theorem normalize_sortedVars : (normalize u).SortedVars := + NormLevel.subsumption_sortedVars (normalizeAux_sortedVars fun p n h => by simp at h) + +/-- `subsumption` erases a key rather than leaving an empty node behind. -/ +theorem NormLevel.subsumption_nonempty {s : NormLevel} : + ∀ p n, s.subsumption.get? p = some n → n.isEmpty = false := by + rw [subsumption, Std.TreeMap.foldl_eq_foldl_toList] + suffices ∀ (l : List (List Name × Node)) (acc : NormLevel), + (∀ p n, acc.get? p = some n → n.isEmpty = false ∨ (p, n) ∈ l) → + ∀ p n, (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).get? p = some n → + n.isEmpty = false from + this _ _ fun p n h => .inr (Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 + (Std.TreeMap.get?_eq_getElem? .. ▸ h)) + intro l + induction l with + | nil => exact fun acc h p n hn => (h p n hn).resolve_right (by simp) + | cons pn l ih => + intro acc hacc + refine ih _ fun p n h => ?_ + rw [subsumption_step_get?] at h + split at h <;> rename_i hp + · split at h <;> [cases h; skip] + cases h; rename_i he; exact .inl (by simpa using he) + · refine (hacc _ _ h).imp_right fun hm => ?_ + obtain h' | h' := List.mem_cons.1 hm + · exact absurd (congrArg Prod.fst h'.symm) hp + · exact h' + +theorem normalize_nonempty : ∀ p n, (normalize u).get? p = some n → n.isEmpty = false := + NormLevel.subsumption_nonempty + +theorem NormLevel.addVar_keys (h : (addVar v k path acc).contains p) : acc.contains p := by + simpa [addVar, Std.TreeMap.mem_modify] using h + +theorem NormLevel.addNode_keys (h : (addNode v k path acc).contains p) : + p = path ∨ acc.contains p := by + rw [addNode, Std.TreeMap.contains_alter] at h + split at h + · rename_i hc + exact .inl (eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 hc)).symm + · exact .inr h + +theorem NormLevel.addConst_keys (h : (addConst k path acc).contains p) : + p = path ∨ acc.contains p := by + rw [addConst] at h; split at h <;> [exact .inr h; skip] + rw [Std.TreeMap.contains_alter] at h + split at h + · rename_i hc + exact .inl (eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 hc)).symm + · exact .inr h + +/-- All keys of the map built by `normalizeAux` consist of level parameters, which are +in `ls` whenever `ofLevel` succeeds. -/ +theorem normalizeAux_keys (hu : VLevel.ofLevel ls u = some u') + (hpath : ∀ x ∈ path, x ∈ ls) (hacc : ∀ p, acc.contains p → ∀ x ∈ p, x ∈ ls) : + ∀ p, (normalizeAux u path k acc).contains p → ∀ x ∈ p, x ∈ ls := by + unfold normalizeAux; split + · exact fun p h => (NormLevel.addConst_keys h).elim + (fun e x hx => hpath x (e ▸ hx)) (hacc p) + · exact fun p h => (NormLevel.addConst_keys h).elim + (fun e x hx => hpath x (e ▸ hx)) (hacc p) + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, rfl⟩ := hu + exact normalizeAux_keys hu hpath hacc + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, hv, rfl⟩ := hu + exact normalizeAux_keys hv hpath (normalizeAux_keys hu hpath hacc) + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨_, hv, rfl⟩, rfl⟩ := hu + exact normalizeAux_keys hv hpath (normalizeAux_keys hu hpath hacc) + · rename_i u v w + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨_, hv, _, hw, rfl⟩, rfl⟩ := hu + exact normalizeAux_keys (by simpa [VLevel.ofLevel] using ⟨_, hu, _, hw, rfl⟩) hpath + (normalizeAux_keys (by simpa [VLevel.ofLevel] using ⟨_, hu, _, hv, rfl⟩) hpath hacc) + · rename_i u v w + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨_, hv, _, hw, rfl⟩, rfl⟩ := hu + exact normalizeAux_keys (by simpa [VLevel.ofLevel] using ⟨_, hv, _, hw, rfl⟩) hpath + (normalizeAux_keys (by simpa [VLevel.ofLevel] using ⟨_, hu, _, hw, rfl⟩) hpath hacc) + · rename_i u v + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, _, ⟨hv, rfl⟩, rfl⟩ := hu + have hvls : v ∈ ls := List.idxOf_lt_length_iff.1 hv + split <;> rename_i h + · refine normalizeAux_keys hu (fun x hx => ?_) fun q hq => ?_ + · exact ((Extend1.orderedInsert h).mem.1 hx).elim (fun e => e.symm ▸ hvls) (hpath x) + · obtain e | hq' := NormLevel.addNode_keys hq + · exact fun x hx => by + rcases (Extend1.orderedInsert h).mem.1 (e ▸ hx) with rfl | hx' + · exact hvls + · exact hpath x hx' + · exact (NormLevel.addConst_keys hq').elim + (fun e x hx => hpath x (e ▸ hx)) (hacc q) + · dsimp; split + · exact normalizeAux_keys hu hpath hacc + · exact normalizeAux_keys hu hpath fun q hq => hacc q (NormLevel.addVar_keys hq) + · exact hacc + · exact hacc + · rename_i v + simp [VLevel.ofLevel] at hu; obtain ⟨hv, rfl⟩ := hu + have hvls : v ∈ ls := List.idxOf_lt_length_iff.1 hv + split <;> rename_i h + · intro q hq + obtain e | hq' := NormLevel.addNode_keys hq + · exact fun x hx => by + rcases (Extend1.orderedInsert h).mem.1 (e ▸ hx) with rfl | hx' + · exact hvls + · exact hpath x hx' + · exact (NormLevel.addConst_keys hq').elim + (fun e x hx => hpath x (e ▸ hx)) (hacc q) + · split + · exact hacc + · exact fun q hq => hacc q (NormLevel.addVar_keys hq) + +theorem normalize_keys (hu : VLevel.ofLevel ls u = some u') : + ∀ p n, (normalize u).get? p = some n → ∀ x ∈ p, x ∈ ls := by + intro p n h + obtain ⟨n₀, h₀, -⟩ := NormLevel.subsumption_covers.1 p n h + have hc : (normalizeAux u [] 0 {}).contains p := + Std.TreeMap.isSome_getElem?_eq_contains.symm.trans + (by simp [Std.TreeMap.get?_eq_getElem?] at h₀; simp [h₀]) + exact normalizeAux_keys hu (by simp) (fun q hq => by simp at hq) p hc + +/-- A single sublevel of the canonical form: `Sub.const p k` is `C(p, k)` and +`Sub.var p x k` is `V(p, x, k)`. -/ +inductive Sub where + | const (p : List Name) (k : Nat) + | var (p : List Name) (x : Name) (k : Nat) + +def Sub.path : Sub → List Name + | .const p _ => p + | .var p _ _ => p + +/-- Domination of sublevels, following Theorem 39: `s.le t` when `t`'s value bounds `s`'s +value under every valuation. The dominator's condition set is a *subset*, so that it fires +whenever the dominated sublevel does; a constant is dominated by `V(F, x, K)` up to `K + 1` +since that sublevel is at least `K + 1` whenever its conditions hold; and a variable +sublevel is only dominated by the same variable at a larger offset. -/ +protected def Sub.le : Sub → Sub → Prop + | .const p k, .const q l => (∀ z ∈ q, z ∈ p) ∧ k ≤ l + | .const p k, .var q _ l => (∀ z ∈ q, z ∈ p) ∧ k ≤ l + 1 + | .var _ _ _, .const _ _ => False + | .var p x k, .var q y l => (∀ z ∈ q, z ∈ p) ∧ x = y ∧ k ≤ l + +protected theorem Sub.le.trans : ∀ {a b c : Sub}, a.le b → b.le c → a.le c + | .const _ _, .const _ _, .const _ _, ⟨s₁, h₁⟩, ⟨s₂, h₂⟩ => + ⟨fun z hz => s₁ _ (s₂ _ hz), Nat.le_trans h₁ h₂⟩ + | .const _ _, .const _ _, .var _ _ _, ⟨s₁, h₁⟩, ⟨s₂, h₂⟩ => + ⟨fun z hz => s₁ _ (s₂ _ hz), by omega⟩ + | .const _ _, .var _ _ _, .const _ _, _, h₂ => h₂.elim + | .const _ _, .var _ _ _, .var _ _ _, ⟨s₁, h₁⟩, ⟨s₂, _, h₂⟩ => + ⟨fun z hz => s₁ _ (s₂ _ hz), by omega⟩ + | .var _ _ _, .const _ _, _, h₁, _ => h₁.elim + | .var _ _ _, .var _ _ _, .const _ _, _, h₂ => h₂.elim + | .var _ _ _, .var _ _ _, .var _ _ _, ⟨s₁, e₁, h₁⟩, ⟨s₂, e₂, h₂⟩ => + ⟨fun z hz => s₁ _ (s₂ _ hz), e₁.trans e₂, Nat.le_trans h₁ h₂⟩ + +theorem subset_antisymm (h₁ : Sorted l₁) (h₂ : Sorted l₂) + (h : ∀ z ∈ l₁, z ∈ l₂) (h' : ∀ z ∈ l₂, z ∈ l₁) : l₁ = l₂ := + subset_eq (subset_of_sorted h₁ h₂ h) <| + Nat.le_antisymm (subset_length (subset_of_sorted h₁ h₂ h)) + (subset_length (subset_of_sorted h₂ h₁ h')) + +protected theorem Sub.le.antisymm : ∀ {a b : Sub}, Sorted a.path → Sorted b.path → + a.le b → b.le a → a = b + | .const p _, .const q _, ha, hb, ⟨s₁, h₁⟩, ⟨s₂, h₂⟩ => by + rw [subset_antisymm (l₁ := p) (l₂ := q) ha hb s₂ s₁, Nat.le_antisymm h₁ h₂] + | .const _ _, .var _ _ _, _, _, _, h₂ => h₂.elim + | .var _ _ _, .const _ _, _, _, h₁, _ => h₁.elim + | .var p _ _, .var q _ _, ha, hb, ⟨s₁, e₁, h₁⟩, ⟨s₂, e₂, h₂⟩ => by + rw [subset_antisymm (l₁ := p) (l₂ := q) ha hb s₂ s₁, e₁, Nat.le_antisymm h₁ h₂] + +/-- The sublevels recorded in a `NormLevel`: `C(p, n.const)` for nonzero constants and +`V(p, x, k)` for each recorded variable. -/ +def NormLevel.HasSub (s : NormLevel) : Sub → Prop + | .const p k => ∃ n, s.get? p = some n ∧ n.const = k ∧ k ≠ 0 + | .var p x k => ∃ n, s.get? p = some n ∧ ⟨x, k⟩ ∈ n.var + +variable (ls : List Name) (ρ : List Nat) in +def Sub.eval : Sub → Nat + | .const p k => evalPath ls ρ p k + | .var p x k => evalPath ls ρ p (evalParam ls ρ x + k) + +theorem NormLevel.HasSub.le_eval {s : NormLevel} : ∀ {t}, s.HasSub t → + t.eval ls ρ ≤ s.eval ls ρ + | .const _ _, ⟨_, hn, hk, _⟩ => + Nat.le_trans (evalPath_mono (hk ▸ Node.const_le_eval)) + (NormLevel.eval_le.1 (Nat.le_refl _) _ _ hn) + | .var _ _ _, ⟨_, hn, hx⟩ => + Nat.le_trans (evalPath_mono (Node.var_le_eval hx)) + (NormLevel.eval_le.1 (Nat.le_refl _) _ _ hn) + +theorem NormLevel.lt_eval {s : NormLevel} : + m < eval ls ρ s ↔ ∃ p n, s.get? p = some n ∧ m < evalPath ls ρ p (Node.eval ls ρ n) := by + refine ⟨fun h => ?_, fun ⟨p, n, hn, hlt⟩ => + Nat.lt_of_lt_of_le hlt (NormLevel.eval_le.1 (Nat.le_refl _) _ _ hn)⟩ + refine Classical.byContradiction fun hc => ?_ + exact absurd (eval_le.2 fun p n hn => Nat.not_lt.1 fun hlt => hc ⟨p, n, hn, hlt⟩) + (Nat.not_le.2 h) + +theorem Node.lt_eval {n : Node} : + m < Node.eval ls ρ n ↔ m < n.const ∨ ∃ v ∈ n.var, m < VarNode.eval ls ρ v := by + refine ⟨fun h => ?_, fun h => ?_⟩ + · refine Classical.byContradiction fun hc => ?_ + rw [not_or] at hc; obtain ⟨h₁, h₂⟩ := hc + refine absurd (Node.eval_le.2 ⟨Nat.not_lt.1 h₁, fun v hv => Nat.not_lt.1 fun hlt => ?_⟩) + (Nat.not_le.2 h) + exact h₂ ⟨v, hv, hlt⟩ + · obtain h | ⟨v, hv, h⟩ := h + · exact Nat.lt_of_lt_of_le h Node.const_le_eval + · exact Nat.lt_of_lt_of_le h (Node.var_le_eval hv) + +theorem lt_evalPath (h : m < evalPath ls ρ p n) : allNZ ls ρ p ∧ m < n := by + rw [evalPath] at h; split at h + · exact ⟨‹_›, h⟩ + · exact absurd h (Nat.not_lt_zero m) + +theorem evalParam_map {f : Name → Nat} (hx : x ∈ ls) : evalParam ls (ls.map f) x = f x := by + have hv : ls.idxOf x < ls.length := List.idxOf_lt_length_iff.2 hx + rw [evalParam_eq hv, List.getElem?_map, List.getElem?_eq_getElem hv] + simp [List.getElem_idxOf] + +theorem evalParam_not_mem (hx : x ∉ ls) : evalParam ls ρ x = 0 := by + simp only [evalParam] + rw [if_neg fun h => hx (List.idxOf_lt_length_iff.1 h)] + +theorem evalParam_map_pos {f : Name → Nat} (h : 0 < evalParam ls (ls.map f) z) : + z ∈ ls ∧ 0 < f z := by + by_cases hz : z ∈ ls + · refine ⟨hz, ?_⟩; rwa [evalParam_map hz] at h + · rw [evalParam_not_mem hz] at h; exact absurd h (Nat.lt_irrefl 0) + +theorem evalParam_map_le {f : Name → Nat} (hb : f z ≤ c) : + evalParam ls (ls.map f) z ≤ c := by + by_cases hz : z ∈ ls + · rw [evalParam_map hz]; exact hb + · rw [evalParam_not_mem hz]; exact Nat.zero_le _ + +theorem foldl_max_le {f : α → Nat} {m : Nat} : ∀ {l : List α} {i : Nat}, + l.foldl (fun r a => max' r (f a)) i ≤ m ↔ i ≤ m ∧ ∀ a ∈ l, f a ≤ m + | [], _ => by simp + | a :: l, i => by simp [foldl_max_le (l := l), Nat.max_le, and_assoc] + +/-- A bound on all the constants and offsets appearing in the map. -/ +def Node.bound (n : Node) : Nat := n.var.foldl (fun r v => max' r v.offset) n.const + +def NormLevel.bound (s : NormLevel) : Nat := s.foldl (fun r _ n => max' r n.bound) 0 + +theorem NormLevel.bound_spec {s : NormLevel} (h : s.get? p = some n) : + n.const ≤ s.bound ∧ ∀ v ∈ n.var, v.offset ≤ s.bound := by + have hmem := Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 (Std.TreeMap.get?_eq_getElem? .. ▸ h) + have hb : n.bound ≤ s.bound := by + rw [bound, Std.TreeMap.foldl_eq_foldl_toList] + exact ((foldl_max_le (f := fun pn : List Name × Node => pn.2.bound)).1 + (Nat.le_refl _)).2 _ hmem + exact (foldl_max_le (f := fun v : VarNode => v.offset)).1 hb + +/-- The separation theorem, a converse to Theorem 39: if the value of `l₁` is bounded by the +value of `l₂` under every valuation, then every sublevel of `l₁` has a syntactic dominator +among the sublevels of `l₂`. The valuation exhibiting the dominator sets every variable of +the sublevel's condition set to `1`, the sublevel's own variable (if any) to a value `N` +larger than every constant and offset of `l₂`, and everything else to `0`: only entries of +`l₂` at condition sets below the sublevel's can contribute, and only a sublevel with the +same variable can reach `N`. -/ +theorem NormLevel.separation {l₁ l₂ : NormLevel} + (hls : ∀ p n, l₁.get? p = some n → ∀ x ∈ p, x ∈ ls) + (wf₁ : ∀ p n, l₁.get? p = some n → ∀ v ∈ n.var, v.var ∈ p) + (h : ∀ ρ, l₁.eval ls ρ ≤ l₂.eval ls ρ) : + ∀ t, l₁.HasSub t → ∃ t', l₂.HasSub t' ∧ t.le t' := by + intro t ht + match t, ht with + | .const p k, ⟨n, hn, hk, hk0⟩ => + have hnz : allNZ ls (ls.map fun z => if z ∈ p then 1 else 0) p := by + simp only [allNZ, List.all_eq_true, decide_eq_true_eq] + intro z hz + rw [evalParam_map (hls _ _ hn _ hz)]; simp [hz] + have h₁ : k ≤ l₁.eval ls (ls.map fun z => if z ∈ p then 1 else 0) := + Nat.le_trans (by simp [Sub.eval, evalPath, hnz]) + (HasSub.le_eval (t := .const p k) ⟨n, hn, hk, hk0⟩) + have h₂ := NormLevel.lt_eval.1 (Nat.lt_of_lt_of_le (by omega : k - 1 < k) + (Nat.le_trans h₁ (h _))) + obtain ⟨q, m, hq, hlt⟩ := h₂ + obtain ⟨hnzq, hlt⟩ := lt_evalPath hlt + have hsub : ∀ z ∈ q, z ∈ p := by + intro z hz + simp only [allNZ, List.all_eq_true, decide_eq_true_eq] at hnzq + have := (evalParam_map_pos (hnzq z hz)).2 + split at this + · assumption + · exact absurd this (Nat.lt_irrefl 0) + obtain hc | ⟨v, hv, hvlt⟩ := Node.lt_eval.1 hlt + · exact ⟨.const q m.const, ⟨m, hq, rfl, by omega⟩, hsub, by omega⟩ + · refine ⟨.var q v.var v.offset, ⟨m, hq, hv⟩, hsub, ?_⟩ + have hev : evalParam ls (ls.map fun z => if z ∈ p then 1 else 0) v.var ≤ 1 := + evalParam_map_le (by split <;> omega) + simp only [VarNode.eval] at hvlt + omega + | .var p x k, ⟨n, hn, hx⟩ => + have hxp : x ∈ p := wf₁ _ _ hn _ hx + have hxls : x ∈ ls := hls _ _ hn _ hxp + have hnz : allNZ ls (ls.map fun z => + if z = x then l₂.bound + k + 2 else if z ∈ p then 1 else 0) p := by + simp only [allNZ, List.all_eq_true, decide_eq_true_eq] + intro z hz + simp only [evalParam_map (hls _ _ hn _ hz)] + split + · omega + · omega + have h₁ : l₂.bound + k + 2 + k ≤ l₁.eval ls (ls.map fun z => + if z = x then l₂.bound + k + 2 else if z ∈ p then 1 else 0) := by + refine Nat.le_trans ?_ (HasSub.le_eval (t := .var p x k) ⟨n, hn, hx⟩) + simp [Sub.eval, evalPath, hnz, evalParam_map hxls] + obtain ⟨q, m, hq, hlt⟩ := NormLevel.lt_eval.1 + (Nat.lt_of_lt_of_le (by omega : l₂.bound + k + 2 + k - 1 < l₂.bound + k + 2 + k) + (Nat.le_trans h₁ (h _))) + obtain ⟨hnzq, hlt⟩ := lt_evalPath hlt + have hsub : ∀ z ∈ q, z ∈ p := by + intro z hz + simp only [allNZ, List.all_eq_true, decide_eq_true_eq] at hnzq + have := (evalParam_map_pos (hnzq z hz)).2 + split at this + · rename_i hz'; subst hz'; exact hxp + · split at this + · assumption + · exact absurd this (Nat.lt_irrefl 0) + obtain hc | ⟨v, hv, hvlt⟩ := Node.lt_eval.1 hlt + · exact absurd hc (by have := (bound_spec hq).1; omega) + · by_cases hvx : v.var = x + · refine ⟨.var q x v.offset, ⟨m, hq, by rw [← hvx]; exact hv⟩, hsub, rfl, ?_⟩ + simp [VarNode.eval, hvx, evalParam_map hxls] at hvlt + omega + · have hoff := (bound_spec hq).2 _ hv + have hev : evalParam ls (ls.map fun z => + if z = x then l₂.bound + k + 2 else if z ∈ p then 1 else 0) v.var ≤ 1 := + evalParam_map_le (by rw [if_neg hvx]; split <;> omega) + simp only [VarNode.eval] at hvlt + exact absurd hvlt (by omega) + +private theorem name_lt_ne {a b : Name} (h : compare a b = .lt) : a ≠ b := by + rintro rfl; rw [Std.ReflOrd.compare_self] at h; cases h + +/-- Exactness of `subsumeVars` on sorted lists: a surviving variable has no dominator +in the subtracted list. -/ +theorem subsumeVars_complete {x y : VarNode} : ∀ {vs₁ vs₂ : List VarNode}, + VarsSorted vs₁ → VarsSorted vs₂ → x ∈ subsumeVars vs₁ vs₂ → y ∈ vs₂ → + y.var = x.var → x.offset ≤ y.offset → False + | [], _, _, _, hx, _ => by simp [subsumeVars] at hx + | _ :: _, [], _, _, _, hy => nomatch hy + | a :: vs₁, b :: vs₂, h₁, h₂, hx, hy => by + intro e hle + simp only [subsumeVars] at hx + split at hx <;> rename_i hab + · rcases List.mem_cons.1 hx with rfl | hx' + · rcases List.mem_cons.1 hy with rfl | hy' + · exact name_lt_ne hab e.symm + · exact name_lt_ne (Std.TransCmp.lt_trans hab (h₂.head _ hy')) e.symm + · exact subsumeVars_complete h₁.of_cons h₂ hx' hy e hle + · have eab : a.var = b.var := eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 hab) + split at hx <;> rename_i hoff + · rcases List.mem_cons.1 hy with rfl | hy' + · exact name_lt_ne (h₁.head _ (subsumeVars_subset hx)) (eab.trans e) + · exact subsumeVars_complete h₁.of_cons h₂.of_cons hx hy' e hle + · rcases List.mem_cons.1 hx with rfl | hx' + · rcases List.mem_cons.1 hy with rfl | hy' + · exact hoff hle + · exact name_lt_ne (h₂.head _ hy') (e.trans eab).symm + · rcases List.mem_cons.1 hy with rfl | hy' + · exact name_lt_ne (h₁.head _ (subsumeVars_subset hx')) (eab.trans e) + · exact subsumeVars_complete h₁.of_cons h₂.of_cons hx' hy' e hle + · rcases List.mem_cons.1 hy with rfl | hy' + · have hbx : compare y.var x.var = .lt := by + have hba := Std.OrientedCmp.lt_of_gt hab + rcases List.mem_cons.1 (subsumeVars_subset hx) with rfl | hxv + · exact hba + · exact Std.TransCmp.lt_trans hba (h₁.head _ hxv) + exact name_lt_ne hbx e + · exact subsumeVars_complete h₁ h₂.of_cons hx hy' e hle + +theorem le_foldl_max_self {vs : List VarNode} : ∀ {n : Nat}, n ≤ vs.foldl (·.max ·.offset) n := by + induction vs with | nil => exact Nat.le_refl _ | cons a vs ih + exact fun {n} => Nat.le_trans (Nat.le_max_left _ _) ih + +theorem foldl_max_ge {vs : List VarNode} (hy : y ∈ vs) : + ∀ {n : Nat}, y.offset ≤ vs.foldl (·.max ·.offset) n := by + induction vs with | nil => cases hy | cons a vs ih + rcases List.mem_cons.1 hy with rfl | hy' + · exact fun {n} => Nat.le_trans (Nat.le_max_right _ _) le_foldl_max_self + · exact fun {n} => ih hy' + +/-- Exactness of the constant part of `subsumeBy`: a dominated constant is dropped. -/ +theorem Node.subsumeBy_const_complete {same : Bool} {n₁ n₂ : Node} + (h : (same = false ∧ n₁.const ≤ n₂.const) ∨ ∃ y ∈ n₂.var, n₁.const ≤ y.offset + 1) : + (n₁.subsumeBy same n₂).const = 0 := by + rw [Node.subsumeBy_const_eq] + split <;> [rename_i hc; rfl] + simp only [Bool.or_eq_true, Bool.and_eq_true, decide_eq_true_eq, List.isEmpty_iff] at hc + obtain hc | ⟨hc1, hc2⟩ := hc + · exact hc + obtain ⟨rfl, hle⟩ | ⟨y, hy, hle⟩ := h + · rcases hc1 with hc1 | hc1 + · cases hc1 + · omega + · rcases hc2 with hc2 | hc2 + · rw [hc2] at hy; cases hy + · have := foldl_max_ge hy (n := 0); omega + +theorem Node.subsumeBy_var_sublist {same : Bool} {n₁ n₂ : Node} : + List.Sublist (n₁.subsumeBy same n₂).var n₁.var := by + rw [Node.subsumeBy_var_eq]; split + · exact List.Sublist.refl _ + · exact subsumeVars_sublist .. + +/-- Exactness of the variable part of `subsumeBy` at a different key: a dominated variable +is dropped. -/ +theorem Node.subsumeBy_var_complete {n₁ n₂ : Node} (h₁ : VarsSorted n₁.var) + (h₂ : VarsSorted n₂.var) (hx : x ∈ (n₁.subsumeBy false n₂).var) (hy : y ∈ n₂.var) + (e : y.var = x.var) (hle : x.offset ≤ y.offset) : False := by + rw [Node.subsumeBy_var_eq] at hx + split at hx <;> rename_i hc + · simp only [Bool.false_or, List.isEmpty_iff] at hc + rw [hc] at hy; cases hy + · exact subsumeVars_complete h₁ h₂ hx hy e hle + +/-- Completeness of the discharging fold in `NormLevel.le`: if every sublevel of `n₁` has a +dominator among the entries of `l` at a subkey of `p₁`, the fold discharges everything and +returns `none`. -/ +theorem NormLevel.le_fold_complete {p₁ : List Name} : + ∀ (l : List (List Name × Node)) (n₁ : Node), VarsSorted n₁.var → + (∀ pn ∈ l, VarsSorted pn.2.var) → n₁.isEmpty = false → + (n₁.const ≠ 0 → ∃ pn ∈ l, subset compare pn.1 p₁ ∧ + (n₁.const ≤ pn.2.const ∨ ∃ y ∈ pn.2.var, n₁.const ≤ y.offset + 1)) → + (∀ x ∈ n₁.var, ∃ pn ∈ l, subset compare pn.1 p₁ ∧ + ∃ y ∈ pn.2.var, y.var = x.var ∧ x.offset ≤ y.offset) → + List.foldlM (m := Option) (fun n pn => + if subset compare pn.1 p₁ then + if (n.subsumeBy false pn.2).isEmpty then none else some (n.subsumeBy false pn.2) + else some n) n₁ l = none + | [], n₁, _, _, hne, hconst, hvar => by + rw [Node.isEmpty, Bool.and_eq_false_iff] at hne + obtain h0 | hv := hne + · obtain ⟨_, h, -⟩ := hconst (by simpa using h0) + cases h + · obtain ⟨x, hx⟩ := List.exists_mem_of_ne_nil _ (by simpa using hv) + obtain ⟨_, h, -⟩ := hvar x hx + cases h + | pn :: l, n₁, hvs₁, hvsl, hne, hconst, hvar => by + simp only [List.foldlM_cons] + split <;> rename_i hs + · by_cases he : (n₁.subsumeBy false pn.2).isEmpty <;> simp [he] + refine le_fold_complete l _ (hvs₁.sublist Node.subsumeBy_var_sublist) + (fun pn h => hvsl _ (.tail _ h)) (by simpa using he) ?_ ?_ + · intro h0 + have hc : (n₁.subsumeBy false pn.2).const = n₁.const := + (Node.subsumeBy_const_cases ..).resolve_right h0 + obtain ⟨pn', hpn', hsub', hdom'⟩ := hconst (hc ▸ h0) + rcases List.mem_cons.1 hpn' with rfl | hpn' + · exact absurd (Node.subsumeBy_const_complete + (hdom'.imp (fun h => ⟨rfl, h⟩) id)) h0 + · exact ⟨pn', hpn', hsub', hc ▸ hdom'⟩ + · intro x hx + obtain ⟨pn', hpn', hsub', y, hy, e, hle⟩ := hvar x (Node.subsumeBy_var_subset hx) + rcases List.mem_cons.1 hpn' with rfl | hpn' + · exact (Node.subsumeBy_var_complete hvs₁ (hvsl _ (.head _)) hx hy e hle).elim + · exact ⟨pn', hpn', hsub', y, hy, e, hle⟩ + · refine le_fold_complete l n₁ hvs₁ (fun pn h => hvsl _ (.tail _ h)) hne + (fun h0 => ?_) (fun x hx => ?_) + · obtain ⟨pn', hpn', hsub', hdom'⟩ := hconst h0 + rcases List.mem_cons.1 hpn' with rfl | hpn' + · exact absurd hsub' hs + · exact ⟨pn', hpn', hsub', hdom'⟩ + · obtain ⟨pn', hpn', hsub', hy⟩ := hvar x hx + rcases List.mem_cons.1 hpn' with rfl | hpn' + · exact absurd hsub' hs + · exact ⟨pn', hpn', hsub', hy⟩ + +/-- Completeness of `NormLevel.le`: per-sublevel domination implies acceptance. -/ +theorem NormLevel.le_complete {l₁ l₂ : NormLevel} + (hvs₁ : l₁.SortedVars) (hvs₂ : l₂.SortedVars) + (hne : ∀ p n, l₁.get? p = some n → n.isEmpty = false) + (hsort₁ : ∀ p n, l₁.get? p = some n → Sorted p) + (hsort₂ : ∀ p n, l₂.get? p = some n → Sorted p) + (hdom : ∀ t, l₁.HasSub t → ∃ t', l₂.HasSub t' ∧ t.le t') : + l₁.le l₂ := by + rw [NormLevel.le, Std.TreeMap.all_eq_all_toList, List.all_eq_true] + rintro ⟨p₁, n₁⟩ hmem + have h₁ := Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 hmem + simp only [Std.TreeMap.foldlM_eq_foldlM_toList, Option.isNone_iff_eq_none] + have hmem₂ : ∀ q m, l₂.get? q = some m → (q, m) ∈ l₂.toList := fun q m h => + Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 (Std.TreeMap.get?_eq_getElem? .. ▸ h) + refine le_fold_complete l₂.toList n₁ (hvs₁ _ _ h₁) + (fun pn h => hvs₂ _ _ <| Std.TreeMap.get?_eq_getElem? .. ▸ + Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h) (hne _ _ h₁) (fun h0 => ?_) (fun x hx => ?_) + · obtain ⟨t', ht', hle⟩ := hdom (.const p₁ n₁.const) ⟨n₁, h₁, rfl, h0⟩ + match t', ht', hle with + | .const q _, ⟨m, hq, hc, _⟩, ⟨hsub, hle⟩ => + exact ⟨(q, m), hmem₂ _ _ hq, + subset_of_sorted (hsort₂ _ _ hq) (hsort₁ _ _ h₁) hsub, .inl (hc ▸ hle)⟩ + | .var q yv yk, ⟨m, hq, hyk⟩, ⟨hsub, hle⟩ => + exact ⟨(q, m), hmem₂ _ _ hq, + subset_of_sorted (hsort₂ _ _ hq) (hsort₁ _ _ h₁) hsub, .inr ⟨⟨yv, yk⟩, hyk, hle⟩⟩ + · obtain ⟨t', ht', hle⟩ := hdom (.var p₁ x.var x.offset) ⟨n₁, h₁, hx⟩ + match t', ht', hle with + | .const _ _, _, hle => exact hle.elim + | .var q yv yk, ⟨m, hq, hyk⟩, ⟨hsub, hev, hle⟩ => + exact ⟨(q, m), hmem₂ _ _ hq, + subset_of_sorted (hsort₂ _ _ hq) (hsort₁ _ _ h₁) hsub, ⟨yv, yk⟩, hyk, hev.symm, hle⟩ + +/-- Two key-sorted entry lists with the same entries are equal. -/ +theorem sorted_pairs_eq : ∀ {l₁ l₂ : List (List Name × Node)}, + l₁.Pairwise (compare ·.1 ·.1 = .lt) → l₂.Pairwise (compare ·.1 ·.1 = .lt) → + (∀ x, x ∈ l₁ ↔ x ∈ l₂) → l₁ = l₂ + | [], [], _, _, _ => rfl + | [], _ :: _, _, _, h => nomatch (h _).2 (.head _) + | _ :: _, [], _, _, h => nomatch (h _).1 (.head _) + | a :: l₁, b :: l₂, h₁, h₂, h => by + have head₁ := (List.pairwise_cons.1 h₁).1 + have head₂ := (List.pairwise_cons.1 h₂).1 + cases show a = b by + rcases List.mem_cons.1 ((h a).1 (.head _)) with rfl | ha <;> [rfl; skip] + rcases List.mem_cons.1 ((h b).2 (.head _)) with rfl | hb <;> [rfl; skip] + cases Std.OrientedCmp.not_lt_of_lt (head₁ _ hb) (head₂ _ ha) + refine congrArg (a :: ·) (sorted_pairs_eq (List.pairwise_cons.1 h₁).2 + (List.pairwise_cons.1 h₂).2 fun x => ⟨fun hx => ?_, fun hx => ?_⟩) + · rcases List.mem_cons.1 ((h x).1 (.tail _ hx)) with rfl | hx' + · have := head₁ _ hx; rw [Std.ReflOrd.compare_self] at this; cases this + · exact hx' + · rcases List.mem_cons.1 ((h x).2 (.tail _ hx)) with rfl | hx' + · have := head₂ _ hx; rw [Std.ReflOrd.compare_self] at this; cases this + · exact hx' + +/-! ### The flat fast path + +For a level with no essential `imax`, `normalize` produces a map with the constant at the +root and one single-variable node per parameter (`NormLevel.Flat`), and `toTree` reads that +off directly, so building the `NormLevel` can be skipped entirely. -/ + +/-- The map `normalize` produces for a flat level, pointwise: `C(∅, c)` at the root, and +`V({x}, x, k)` at each singleton key whose parameter is recorded in `vs`. -/ +def flatGet (c : Nat) (vs : List VarNode) : List Name → Option Node + | [] => if c = 0 then none else some ⟨c, []⟩ + | [x] => (vs.find? (·.var == x)).map fun v => ⟨0, [v]⟩ + | _ => none + +def NormLevel.Flat (s : NormLevel) (c : Nat) (vs : List VarNode) : Prop := + ∀ p, s.get? p = flatGet c vs p + +theorem find?_var_eq_some {vs : List VarNode} {x : Name} {v : VarNode} (hvs : VarsSorted vs) : + vs.find? (·.var == x) = some v ↔ v ∈ vs ∧ v.var = x := by + refine ⟨fun h => ⟨List.mem_of_find?_eq_some h, by simpa using List.find?_some h⟩, ?_⟩ + rintro ⟨hv, rfl⟩ + match h : vs.find? (·.var == v.var) with + | none => simp [List.find?_eq_none] at h; exact absurd rfl (h _ hv) + | some w => + have hw := List.mem_of_find?_eq_some h + have hwe : w.var = v.var := by simpa using List.find?_some h + rw [h, hvs.eq_of_var_eq hw hv hwe] + +theorem find?_var_eq_none {vs : List VarNode} {x : Name} : + vs.find? (·.var == x) = none ↔ ∀ v ∈ vs, v.var ≠ x := by + simp [List.find?_eq_none] + +/-- `addVar` raises the offset of the entry for `x`, leaving the rest alone. -/ +theorem VarNode.find?_addVar {vs : List VarNode} {x y : Name} {k : Nat} (hvs : VarsSorted vs) : + (VarNode.addVar x k vs).find? (·.var == y) = + if x = y then some ⟨x, ((vs.find? (·.var == x)).map (·.offset.max k)).getD k⟩ + else vs.find? (·.var == y) := by + induction vs with | nil => split <;> simp [VarNode.addVar, *] | cons w l ih + simp only [VarNode.addVar] + split <;> rename_i hc + · have hnone : (w :: l).find? (·.var == x) = none := by + refine find?_var_eq_none.2 fun v hv => ?_ + obtain rfl | hv := List.mem_cons.1 hv + · exact fun e => name_lt_ne hc e.symm + · exact fun e => name_lt_ne (Std.TransCmp.lt_trans hc (hvs.head _ hv)) e.symm + split <;> rename_i h + · subst h; rw [List.find?_cons_of_pos (by simp), hnone]; rfl + · rw [List.find?_cons_of_neg (by simp [h])] + · have e := eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 hc) + split <;> rename_i h + · subst h; rw [List.find?_cons_of_pos (by simp), List.find?_cons_of_pos (by simp [← e])]; rfl + · rw [List.find?_cons_of_neg (by simp [h]), List.find?_cons_of_neg (by simp [← e, h])] + · have hne := name_lt_ne (Std.OrientedCmp.lt_of_gt hc) + by_cases hy : w.var = y + · rw [if_neg (hy ▸ hne.symm), List.find?_cons_of_pos (by simp [hy]), + List.find?_cons_of_pos (by simp [hy])] + · rw [List.find?_cons_of_neg (by simp [hy]), ih hvs.of_cons, + List.find?_cons_of_neg (by simp [hne]), List.find?_cons_of_neg (by simp [hy])] + +theorem NormLevel.addConst_flat {s : NormLevel} {c k : Nat} {vs : List VarNode} + (h : s.Flat c vs) : (addConst k [] s).Flat (Nat.max c k) vs := by + by_cases hk : k = 0 + · subst hk + rw [show Nat.max c 0 = c from Nat.max_zero c, NormLevel.addConst, if_pos (by simp)] + exact h + · rw [NormLevel.addConst, if_neg (by simp [hk])] + intro p + rw [Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_alter] + have hmax : ¬Nat.max c k = 0 := by simp only [Nat.max_eq_zero_iff]; simp [hk] + split <;> rename_i he + · cases eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 he) + rw [← Std.TreeMap.get?_eq_getElem?, h []] + simp only [flatGet] + by_cases hc0 : c = 0 + · subst hc0 + rw [if_pos rfl, if_neg hmax, show Nat.max 0 k = k from Nat.zero_max k] + · rw [if_neg hc0, if_neg hmax, show Nat.max c k = Nat.max k c from Nat.max_comm c k] + · rw [← Std.TreeMap.get?_eq_getElem?, h p] + match p with + | [] => cases he Std.ReflOrd.compare_self + | [_] | _ :: _ :: _ => rfl + +theorem NormLevel.addNode_flat {s : NormLevel} {c k : Nat} {vs : List VarNode} {x : Name} + (hvs : VarsSorted vs) (h : s.Flat c vs) : + (addNode x k [x] s).Flat c (VarNode.addVar x k vs) := by + intro p + rw [NormLevel.addNode, Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_alter] + split <;> rename_i he + · have hp : [x] = p := eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 he) + subst hp + rw [← Std.TreeMap.get?_eq_getElem?, h [x]] + simp only [flatGet] + rw [VarNode.find?_addVar hvs, if_pos rfl] + match hfd : vs.find? (·.var == x) with + | none => rw [hfd]; rfl + | some v => + have hv : v.var = x := by simpa using List.find?_some hfd + rw [hfd] + show some ({ const := 0, var := VarNode.addVar x k [v] } : Node) = _ + rw [show VarNode.addVar x k [v] = [⟨x, v.offset.max k⟩] from by + simp only [VarNode.addVar, hv, Std.ReflCmp.compare_self]]; rfl + · rw [← Std.TreeMap.get?_eq_getElem?, h p] + match p with + | [] => rfl + | [y] => + have hxy : x ≠ y := by rintro rfl; exact he Std.ReflOrd.compare_self + simp only [flatGet] + rw [VarNode.find?_addVar hvs, if_neg hxy] + | _ :: _ :: _ => rfl + +/-- The entries of a flat map: the root carries the constant (and is absent when it is zero), +and every other key is a singleton carrying one variable of `vs`. -/ +private theorem flatGet_eq_some {c : Nat} {vs : List VarNode} {p : List Name} {n : Node} + (h : flatGet c vs p = some n) : + (p = [] ∧ n = ⟨c, []⟩ ∧ c ≠ 0) ∨ ∃ v ∈ vs, p = [v.var] ∧ n = ⟨0, [v]⟩ := by + match p with + | [] => + simp only [flatGet] at h + split at h + · cases h + · exact .inl ⟨rfl, by cases h; rfl, by assumption⟩ + | [x] => + simp only [flatGet, Option.map_eq_some_iff] at h + obtain ⟨v, hv, rfl⟩ := h + have hvx : v.var = x := by simpa using List.find?_some hv + exact .inr ⟨v, List.mem_of_find?_eq_some hv, by rw [hvx], rfl⟩ + | _ :: _ :: _ => simp [flatGet] at h + +/-- `subsumeBy` is the identity when the constant has nothing to lose (it is zero, or the two +sit at the same condition set and the dominator has no variables) and the variables have +nothing to lose (same condition set, or no variables to be dominated by). -/ +private theorem Node.subsumeBy_id {same : Bool} {n₁ n₂ : Node} + (h₁ : n₁.const = 0 ∨ (same ∧ n₂.var = [])) + (h₂ : same ∨ n₂.var = []) : n₁.subsumeBy same n₂ = n₁ := by + simp only [Node.subsumeBy] + rcases h₁ with hz | ⟨hs, hv⟩ + · rcases h₂ with h2 | h2 <;> simp [hz, h2] + · simp [hs, hv] + +private theorem subsume_flat_id {c : Nat} {vs : List VarNode} {p₁ p₂ : List Name} {n₁ n₂ : Node} + (h₁ : flatGet c vs p₁ = some n₁) (h₂ : flatGet c vs p₂ = some n₂) : + Node.subsume p₁ n₁ p₂ n₂ = n₁ := by + rw [Node.subsume] + split <;> [rename_i hsub; rfl] + obtain ⟨rfl, rfl, -⟩ | ⟨v, -, rfl, rfl⟩ := flatGet_eq_some h₂ + · obtain ⟨rfl, rfl, -⟩ | ⟨w, -, rfl, rfl⟩ := flatGet_eq_some h₁ + · exact Node.subsumeBy_id (.inr ⟨rfl, rfl⟩) (.inl rfl) + · exact Node.subsumeBy_id (.inl rfl) (.inr rfl) + · obtain ⟨rfl, rfl, -⟩ | ⟨w, -, rfl, rfl⟩ := flatGet_eq_some h₁ + · exact absurd hsub (by simp [subset]) + · exact Node.subsumeBy_id (.inl rfl) (.inl rfl) + +/-- Nothing in a flat map subsumes anything: a condition set is empty or a singleton, and the +node carrying the constant has no variables. -/ +theorem NormLevel.subsumption_flat {s : NormLevel} {c : Nat} {vs : List VarNode} + (h : s.Flat c vs) : s.subsumption.Flat c vs := by + have hmin : ∀ (acc : NormLevel), acc.Flat c vs → ∀ p₁ n₁, flatGet c vs p₁ = some n₁ → + acc.minimize p₁ n₁ = n₁ := by + intro acc hacc p₁ n₁ h₁ + rw [NormLevel.minimize, Std.TreeMap.foldl_eq_foldl_toList] + have hmem : ∀ pn ∈ acc.toList, flatGet c vs pn.1 = some pn.2 := fun pn hp => + (hacc pn.1).symm.trans (Std.TreeMap.get?_eq_getElem? .. ▸ + Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 hp) + suffices ∀ (l : List (List Name × Node)), (∀ pn ∈ l, flatGet c vs pn.1 = some pn.2) → + List.foldl (fun n pn => Node.subsume p₁ n pn.1 pn.2) n₁ l = n₁ from this _ hmem + intro l; induction l with | nil => intro; rfl | cons pn l ih + intro hl + rw [List.foldl_cons, subsume_flat_id h₁ (hl pn (.head _))] + exact ih fun q hq => hl q (.tail _ hq) + rw [NormLevel.subsumption, Std.TreeMap.foldl_eq_foldl_toList] + have hmem : ∀ pn ∈ s.toList, flatGet c vs pn.1 = some pn.2 := fun pn hp => + (h pn.1).symm.trans (Std.TreeMap.get?_eq_getElem? .. ▸ + Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 hp) + suffices ∀ (l : List (List Name × Node)) (acc : NormLevel), + (∀ pn ∈ l, flatGet c vs pn.1 = some pn.2) → acc.Flat c vs → + (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).Flat c vs from + this _ _ hmem h + intro l; induction l with | nil => exact fun _ _ hacc => hacc | cons pn l ih + obtain ⟨p₁, n₁⟩ := pn + refine fun acc hl hacc => ih _ (fun q hq => hl q (.tail _ hq)) fun p => ?_ + have h₁ : flatGet c vs p₁ = some n₁ := hl _ (.head _) + have hne : n₁.isEmpty = false := by + obtain ⟨-, rfl, hc0⟩ | ⟨v, -, -, rfl⟩ := flatGet_eq_some h₁ + · simp [Node.isEmpty, hc0] + · simp [Node.isEmpty] + rw [NormLevel.subsumption_step_get?, hmin acc hacc p₁ n₁ h₁, hne] + simp only [Bool.false_eq_true, if_false] + split <;> rename_i hp + · subst hp; exact h₁.symm + · exact hacc p + +/-- The inserts of `toNormLevel` fill in the singleton keys one at a time: once the starting +map is right at every key not yet due to be written, the fold is right everywhere. -/ +private theorem toNormLevel_fold {c : Nat} {vs : List VarNode} (hvs : VarsSorted vs) : + ∀ (l : List VarNode) (s : NormLevel), (∀ w ∈ l, w ∈ vs) → + (∀ p, (∀ w ∈ l, p ≠ [w.var]) → s.get? p = flatGet c vs p) → + ∀ p, (l.foldl (fun s v => s.insert [v.var] ⟨0, [v]⟩) s).get? p = flatGet c vs p := by + intro l; induction l with | nil => intro s _ hs p; exact hs p (by simp) | cons w l ih + refine fun s hmem hs => ih _ (fun x hx => hmem x (.tail _ hx)) fun p hp => ?_ + rw [Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_insert] + split <;> rename_i he + · have hpe : [w.var] = p := eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 he) + subst hpe + simp only [flatGet] + rw [(find?_var_eq_some hvs).2 ⟨hmem w (.head _), rfl⟩]; rfl + · rw [← Std.TreeMap.get?_eq_getElem?] + refine hs p fun x hx => ?_ + obtain rfl | hx := List.mem_cons.1 hx + · rintro rfl; exact he Std.ReflOrd.compare_self + · exact hp x hx + +/-- `toNormLevel` really does build a flat map. -/ +theorem toNormLevel_flat {c : Nat} {vs : List VarNode} (hvs : VarsSorted vs) : + (toNormLevel c vs).Flat c vs := by + refine toNormLevel_fold hvs vs _ (fun w hw => hw) fun p hp => ?_ + have hnone : ∀ x, p = [x] → flatGet c vs [x] = none := by + rintro x rfl; simp only [flatGet] + rw [find?_var_eq_none.2 fun v hv he => hp v hv (by rw [he])]; rfl + split <;> rename_i hc + · subst hc + match p with + | [] => rfl + | [x] => rw [hnone x rfl]; rfl + | _ :: _ :: _ => rfl + · rw [Std.TreeMap.get?_eq_getElem?, Std.TreeMap.getElem?_insert] + split <;> rename_i he + · cases eq_of_beq (Std.LawfulBEqCmp.compare_eq_iff_beq.1 he); simp [flatGet, hc] + · match p with + | [] => cases he Std.ReflOrd.compare_self + | [x] => rw [hnone x rfl]; rfl + | _ :: _ :: _ => rfl + +/-! Two maps with the same entries need not be the same tree, so the fallback -- which seeds +`normalizeAux` with `toNormLevel` rather than with the map the general path would have built +-- needs `normalizeAux` and `subsumption` to respect pointwise equality. -/ + +theorem toList_eq_of_get?_eq {A B : NormLevel} (h : ∀ p, A.get? p = B.get? p) : + A.toList = B.toList := by + refine sorted_pairs_eq Std.TreeMap.ordered_keys_toList Std.TreeMap.ordered_keys_toList ?_ + rintro ⟨p, n⟩ + rw [Std.TreeMap.mem_toList_iff_getElem?_eq_some, Std.TreeMap.mem_toList_iff_getElem?_eq_some, + ← Std.TreeMap.get?_eq_getElem?, ← Std.TreeMap.get?_eq_getElem?, h] + +theorem NormLevel.addConst_congr {A B : NormLevel} (h : ∀ p, A.get? p = B.get? p) (k path p) : + (addConst k path A).get? p = (addConst k path B).get? p := by + simp only [Std.TreeMap.get?_eq_getElem?] at h ⊢ + rw [NormLevel.addConst, NormLevel.addConst] + split <;> [exact h p; skip] + rw [Std.TreeMap.getElem?_alter, Std.TreeMap.getElem?_alter] + split <;> rw [h] + +theorem NormLevel.addNode_congr {A B : NormLevel} (h : ∀ p, A.get? p = B.get? p) (x k path p) : + (addNode x k path A).get? p = (addNode x k path B).get? p := by + simp only [Std.TreeMap.get?_eq_getElem?] at h ⊢ + rw [NormLevel.addNode, NormLevel.addNode, Std.TreeMap.getElem?_alter, Std.TreeMap.getElem?_alter] + split <;> rw [h] + +theorem NormLevel.addVar_congr {A B : NormLevel} (h : ∀ p, A.get? p = B.get? p) (x k path p) : + (addVar x k path A).get? p = (addVar x k path B).get? p := by + simp only [Std.TreeMap.get?_eq_getElem?] at h ⊢ + rw [NormLevel.addVar, NormLevel.addVar, Std.TreeMap.getElem?_modify, Std.TreeMap.getElem?_modify] + split <;> rw [h] + +theorem normalizeAux_congr {A B : NormLevel} (h : ∀ p, A.get? p = B.get? p) (u path k) : + ∀ p, (normalizeAux u path k A).get? p = (normalizeAux u path k B).get? p := by + induction u, path, k, A using normalizeAux.induct generalizing B with + | case1 path k acc => simp only [normalizeAux]; exact NormLevel.addConst_congr h k path + | case2 path k acc a => simp only [normalizeAux]; exact NormLevel.addConst_congr h k path + | case3 path k acc u ih => simp only [normalizeAux]; exact ih h + | case4 path k acc u v ih₁ ih₂ => simp only [normalizeAux]; exact ih₂ (ih₁ h) + | case5 path k acc u v ih₁ ih₂ => simp only [normalizeAux]; exact ih₂ (ih₁ h) + | case6 path k acc u v w ih₁ ih₂ => simp only [normalizeAux]; exact ih₂ (ih₁ h) + | case7 path k acc u v w ih₁ ih₂ => simp only [normalizeAux]; exact ih₂ (ih₁ h) + | case8 path k acc u v path' he ih => + simp only [normalizeAux, he] + exact ih (NormLevel.addNode_congr (NormLevel.addConst_congr h k path) v k path') + | case9 path k acc u v he acc1 => + rename_i ih + simp only [normalizeAux, he] + refine ih (B := if k = 0 then B else NormLevel.addVar v k path B) fun p => ?_ + show (if k = 0 then acc else NormLevel.addVar v k path acc).get? p = + (if k = 0 then B else NormLevel.addVar v k path B).get? p + by_cases hk : k = 0 + · simp only [if_pos hk]; exact h p + · simp only [if_neg hk]; exact NormLevel.addVar_congr h v k path p + | case10 path k acc a => simp only [normalizeAux]; exact h + | case11 path k acc a b => simp only [normalizeAux]; exact h + | case12 path k acc v path' he => + simp only [normalizeAux, he] + exact NormLevel.addNode_congr (NormLevel.addConst_congr h k path) v k path' + | case13 path acc v he => simp only [normalizeAux, he, if_pos]; exact h + | case14 path k acc v he hk => + simp only [normalizeAux, he, if_neg hk] + exact NormLevel.addVar_congr h v k path + +theorem NormLevel.subsumption_congr {A B : NormLevel} (h : ∀ p, A.get? p = B.get? p) : + ∀ p, A.subsumption.get? p = B.subsumption.get? p := by + rw [NormLevel.subsumption, NormLevel.subsumption, Std.TreeMap.foldl_eq_foldl_toList, + Std.TreeMap.foldl_eq_foldl_toList, toList_eq_of_get?_eq h] + let +generalize F acc pn := _ + suffices ∀ (l : List (List Name × Node)) (acc₁ acc₂ : NormLevel), + (∀ p, acc₁.get? p = acc₂.get? p) → ∀ p, + (List.foldl F acc₁ l).get? p = (List.foldl F acc₂ l).get? p from + this _ _ _ h + intro l; induction l with | nil => exact fun _ _ h => h | cons pn l ih + refine fun acc₁ acc₂ hacc => ih _ _ fun p => ?_ + have hmin : acc₁.minimize pn.1 pn.2 = acc₂.minimize pn.1 pn.2 := by + rw [NormLevel.minimize, NormLevel.minimize, Std.TreeMap.foldl_eq_foldl_toList, + Std.TreeMap.foldl_eq_foldl_toList, toList_eq_of_get?_eq hacc] + rw [NormLevel.subsumption_step_get?, NormLevel.subsumption_step_get?, hmin] + split <;> [rfl; exact hacc p] + +/-- What a traversal result stands for: collected data still describing the map, or a thrown +map agreeing with it entry for entry (only entry for entry, since the thrown one was rebuilt +from sorted data rather than in traversal order). -/ +def RepAcc : Except NormLevel (Nat × List VarNode) → NormLevel → Prop + | .ok (c, vs), s => VarsSorted vs ∧ s.Flat c vs + | .error s', s => ∀ p, s'.get? p = s.get? p + +/-- The traversal tracks `normalizeAux` step for step. -/ +theorem flatAux_rep (hvs : VarsSorted vs) (h : s.Flat c vs) : + RepAcc (flatAux l k (c, vs)) (normalizeAux l [] k s) := by + induction l generalizing k c vs s with simp only [flatAux, normalizeAux] + | zero => exact ⟨hvs, NormLevel.addConst_flat h⟩ + | succ l ih => exact ih hvs h + | max a b iha ihb => + have ha := iha (k := k) hvs h + cases hfa : flatAux a k (c, vs) with + | ok acc => obtain ⟨c₁, vs₁⟩ := acc; rw [hfa] at ha; exact ihb ha.1 ha.2 + | error s₁ => rw [hfa] at ha; exact normalizeAux_congr ha b [] k + | param => + exact ⟨VarNode.addVar_sorted hvs, NormLevel.addNode_flat hvs (NormLevel.addConst_flat h)⟩ + | imax => exact normalizeAux_congr (fun p => (toNormLevel_flat hvs p).trans (h p).symm) _ [] k + | mvar => exact ⟨hvs, h⟩ + +private theorem compare_nil_cons {x : Name} {l : List Name} : + compare ([] : List Name) (x :: l) = .lt := by + simp [compare, List.compareLex] + +private theorem compare_singleton {x y : Name} : compare [x] [y] = compare x y := by + simp only [compare, List.compareLex] + cases Name.cmp x y <;> rfl + +/-- Adding a name that sorts after everything already there appends at the end. -/ +private theorem modifyAt_append_of_lt (f : Tree → Tree) (a : Name) : ∀ (l : List (Name × Tree)), + (∀ q ∈ l, compare q.1 a = .lt) → modifyAt f a l = l ++ [(a, f default)] + | [], _ => rfl + | (x, t) :: l, hl => by + simp only [modifyAt, Std.OrientedCmp.gt_of_lt (cmp := Name.cmp) (hl (x, t) (.head _))] + rw [modifyAt_append_of_lt f a l fun q hq => hl q (.tail _ hq)]; rfl + +/-- The edge into a singleton key's node already provides `V({x}, x, 0)`. -/ +private theorem subsumeVars_singleton_self (v : VarNode) : + subsumeVars [v] [⟨v.var, 0⟩] = if v.offset == 0 then [] else [v] := by + simp only [subsumeVars, Std.ReflCmp.compare_self] + by_cases h : v.offset = 0 <;> simp [h] <;> omega + +/-- Folding the singleton keys of a flat map appends one child per parameter, in name order. -/ +private theorem flat_toTree_fold (s : NormLevel) (a : Nat) (b : List VarNode) : + ∀ (vs : List VarNode) (ch : List (Name × Tree)), + VarsSorted vs → + (∀ v ∈ vs, s.lexChain 1 [v.var] = [v.var]) → + (∀ v ∈ vs, ∀ q ∈ ch, compare q.1 v.var = .lt) → + List.foldl (fun t pn => + let path := s.lexChain (List.length pn.1) pn.1 + let var := if let v :: _ := path then subsumeVars pn.2.var [⟨v, 0⟩] else pn.2.var + Tree.modify path (fun t => { t with const := pn.2.const, var }) t) + ⟨a, b, ch⟩ (vs.map fun v => ([v.var], (⟨0, [v]⟩ : Node))) + = ⟨a, b, ch ++ vs.map fun v => (v.var, (⟨0, if v.offset == 0 then [] else [v], []⟩ : Tree))⟩ + | [], ch, _, _, _ => by simp + | v :: vs, ch, hvs, hlex, hch => by + have hch' : ∀ w ∈ vs, ∀ q ∈ ch ++ [(v.var, + (⟨0, if v.offset == 0 then [] else [v], []⟩ : Tree))], compare q.1 w.var = .lt := by + intro w hw q hq + rcases List.mem_append.1 hq with hq | hq + · exact hch w (.tail _ hw) q hq + · rw [List.mem_singleton] at hq; subst hq; exact hvs.head _ hw + have ih := flat_toTree_fold s a b vs _ hvs.of_cons (fun w hw => hlex w (.tail _ hw)) hch' + simp only [List.map_cons, List.foldl_cons, List.length_cons, List.length_nil, + hlex v (.head _), Tree.modify, subsumeVars_singleton_self] + rw [modifyAt_append_of_lt _ _ ch (fun q hq => hch v (.head _) q hq)] + exact ih.trans (by simp) + +/-- The entry list of a flat map, in key order. -/ +private theorem NormLevel.Flat.toList {s : NormLevel} {c : Nat} {vs : List VarNode} + (hvs : VarsSorted vs) (h : s.Flat c vs) : + s.toList = (if c = 0 then [] else [([], (⟨c, []⟩ : Node))]) ++ + vs.map fun v => ([v.var], (⟨0, [v]⟩ : Node)) := by + refine sorted_pairs_eq Std.TreeMap.ordered_keys_toList ?_ fun ⟨p, n⟩ => ?_ + · refine List.pairwise_append.2 ⟨?_, ?_, ?_⟩ + · by_cases hc0 : c = 0 <;> simp [hc0] + · rw [List.pairwise_map] + exact hvs.imp fun {u w} huw => by rw [compare_singleton]; exact huw + · intro x hx y hy + by_cases hc0 : c = 0 + · simp [hc0] at hx + · rw [if_neg hc0, List.mem_singleton] at hx + subst hx + obtain ⟨w, -, rfl⟩ := List.mem_map.1 hy + exact compare_nil_cons + · rw [Std.TreeMap.mem_toList_iff_getElem?_eq_some, ← Std.TreeMap.get?_eq_getElem?, h p] + constructor <;> intro hp + · obtain ⟨rfl, rfl, hc0⟩ | ⟨v, hv, rfl, rfl⟩ := flatGet_eq_some hp + · exact List.mem_append_left _ (by rw [if_neg hc0]; exact List.mem_singleton.2 rfl) + · exact List.mem_append_right _ (List.mem_map.2 ⟨v, hv, rfl⟩) + · obtain hp | hp := List.mem_append.1 hp + · split at hp <;> [cases hp; rename_i hc] + rw [List.mem_singleton] at hp; cases hp; simp [flatGet, hc] + · obtain ⟨v, hv, he⟩ := List.mem_map.1 hp + cases he; simp only [flatGet] + rw [(find?_var_eq_some hvs).2 ⟨hv, rfl⟩]; rfl + +/-- A singleton key's chain is forced: its one element is `addable` on the empty set, thanks +to the entry itself, and nothing remains to be completed. -/ +private theorem NormLevel.Flat.lexChain_singleton {s : NormLevel} {c : Nat} {vs : List VarNode} + (hvs : VarsSorted vs) (h : s.Flat c vs) {v : VarNode} (hv : v ∈ vs) : + s.lexChain 1 [v.var] = [v.var] := by + have haddable : s.addable v.var [] := by + rw [NormLevel.addable, Std.TreeMap.any_eq_any_toList, List.any_eq_true] + refine ⟨([v.var], ⟨0, [v]⟩), Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 ?_, ?_⟩ + · rw [← Std.TreeMap.get?_eq_getElem?, h [v.var]] + simp only [flatGet] + rw [(find?_var_eq_some hvs).2 ⟨hv, rfl⟩]; rfl + · simp [subset] + rw [NormLevel.lexChain, List.find?_cons_of_pos] + · simp [NormLevel.lexChain] + · simp only [List.erase_cons_head, haddable, Bool.true_and]; rfl + +/-- Reading the tree off a flat map: every key is a singleton, so its `lexChain` is forced, +and the fold just adds one child per parameter in name order. -/ +theorem NormLevel.Flat.toTree {s : NormLevel} {c : Nat} {vs : List VarNode} + (hvs : VarsSorted vs) (h : s.Flat c vs) : s.toTree = flatTree c vs := by + rw [NormLevel.toTree, Std.TreeMap.foldl_eq_foldl_toList, NormLevel.Flat.toList hvs h] + have key := flat_toTree_fold s c [] vs [] hvs + (fun v => NormLevel.Flat.lexChain_singleton hvs h) (by simp) + by_cases hc0 : c = 0 + · subst hc0; rw [if_pos rfl]; exact key + · rw [if_neg hc0]; exact key + +/-- The sublevels of a single node keyed at `p`. -/ +def Node.HasSub (p : List Name) (n : Node) : Sub → Prop + | .const q k => p = q ∧ n.const = k ∧ k ≠ 0 + | .var q x k => p = q ∧ ⟨x, k⟩ ∈ n.var + +theorem NormLevel.hasSub_iff {s : NormLevel} {t} : + s.HasSub t ↔ ∃ p n, s.get? p = some n ∧ Node.HasSub p n t := by + match t with + | .const p k => + constructor + · rintro ⟨n, hn, hk, hk0⟩; exact ⟨p, n, hn, rfl, hk, hk0⟩ + · rintro ⟨q, n, hn, rfl, hk, hk0⟩; exact ⟨n, hn, hk, hk0⟩ + | .var p x k => + constructor + · rintro ⟨n, hn, hx⟩; exact ⟨p, n, hn, rfl, hx⟩ + · rintro ⟨q, n, hn, rfl, hx⟩; exact ⟨n, hn, hx⟩ + +theorem Node.subsume_hasSub : ∀ {t}, Node.HasSub p₁ (Node.subsume p₁ n p₂ n₂) t → + Node.HasSub p₁ n t + | .const _ k, ⟨rfl, hck, hk0⟩ => by + refine ⟨rfl, ?_, hk0⟩ + obtain h | h := Node.subsume_const_cases p₁ n p₂ n₂ + · rw [← h]; exact hck + · rw [h] at hck; exact absurd hck.symm hk0 + | .var _ _ _, ⟨rfl, hxk⟩ => ⟨rfl, Node.subsume_var_subset hxk⟩ + +theorem NormLevel.minimize_hasSub {acc : NormLevel} {t} + (h : Node.HasSub p₁ (acc.minimize p₁ n₁) t) : Node.HasSub p₁ n₁ t := by + rw [minimize, Std.TreeMap.foldl_eq_foldl_toList] at h + generalize acc.toList = l at h + induction l generalizing n₁ with + | nil => exact h + | cons a l ih => exact Node.subsume_hasSub (ih h) + +/-- A `subsumption` step only removes sublevels. -/ +theorem NormLevel.subsumption_step_hasSub {acc : NormLevel} {p₁ : List Name} {n₁ : Node} + (h₁ : acc.get? p₁ = some n₁) {t} + (h : NormLevel.HasSub (if (acc.minimize p₁ n₁).isEmpty then acc.erase p₁ + else acc.insert p₁ (acc.minimize p₁ n₁)) t) : acc.HasSub t := by + rw [hasSub_iff] at h ⊢ + obtain ⟨p, n, hp, hn⟩ := h + rw [subsumption_step_get?] at hp + split at hp <;> rename_i hpe + · split at hp <;> [cases hp; skip] + cases hp; subst hpe + exact ⟨p₁, n₁, h₁, minimize_hasSub hn⟩ + · exact ⟨p, n, hp, hn⟩ + +/-- Exactness of minimization, fold form: a sublevel surviving the subtraction of every entry +in `l` is not (strictly) dominated by any of their sublevels — domination forces equality. -/ +theorem NormLevel.minimize_exact_aux {acc : NormLevel} {p₁ : List Name} {n₁ : Node} + (hsort : ∀ p n, acc.get? p = some n → Sorted p) (hvsa : acc.SortedVars) + (h₁ : acc.get? p₁ = some n₁) (hs₁ : Sorted p₁) (hvs₁ : VarsSorted n₁.var) : + ∀ (l : List (List Name × Node)) (n : Node), + (∀ pn ∈ l, acc.get? pn.1 = some pn.2) → + (∀ x ∈ n.var, x ∈ n₁.var) → (n.const ≠ 0 → n.const = n₁.const) → VarsSorted n.var → + ∀ t, Node.HasSub p₁ (l.foldl (fun n pn => Node.subsume p₁ n pn.1 pn.2) n) t → + Node.HasSub p₁ n t ∧ + ∀ pn ∈ l, ∀ t', Node.HasSub pn.1 pn.2 t' → t.le t' → t = t' + | [], _, _, _, _, _, _, ht => ⟨ht, fun _ h => nomatch h⟩ + | (p₂, n₂) :: l, n, hl, hnvar, hnconst, hvs, t, ht => by + simp only [List.foldl_cons] at ht + have h₂ : acc.get? p₂ = some n₂ := hl _ (.head _) + have hvs₂ : VarsSorted n₂.var := hvsa _ _ h₂ + have hs₂ : Sorted p₂ := hsort _ _ h₂ + obtain ⟨ht', hrest⟩ := minimize_exact_aux hsort hvsa h₁ hs₁ hvs₁ l + (Node.subsume p₁ n p₂ n₂) (fun pn h => hl _ (.tail _ h)) + (fun x hx => hnvar _ (Node.subsume_var_subset hx)) + (fun h0 => by + obtain hc | hc := Node.subsume_const_cases p₁ n p₂ n₂ + · rw [hc]; exact hnconst (hc ▸ h0) + · exact absurd hc h0) + (hvs.sublist Node.subsume_var_sublist) t ht + refine ⟨Node.subsume_hasSub ht', ?_⟩ + rintro pn hpn t' ht'' hle + rcases List.mem_cons.1 hpn with rfl | hpn + · obtain ⟨q, k⟩ | ⟨q, x, k⟩ := t <;> obtain ⟨q', k'⟩ | ⟨q', y, k'⟩ := t' + · -- const dominated by const + obtain ⟨rfl, hck, hk0⟩ := ht' + obtain ⟨rfl, hck', hk0'⟩ := ht'' + obtain ⟨hsub, hlek⟩ := hle + have hgate : subset compare p₂ p₁ := subset_of_sorted hs₂ hs₁ hsub + have hsu : Node.subsume p₁ n p₂ n₂ = n.subsumeBy (p₁.length == p₂.length) n₂ := by + rw [Node.subsume, if_pos hgate] + by_cases hlen : p₁.length = p₂.length + · have hqq : p₂ = p₁ := subset_eq hgate hlen.symm + have hn₂ : n₂ = n₁ := by + rw [hqq] at h₂; cases h₂.symm.trans h₁; rfl + have hkc : n.const = k := by + obtain hc | hc := Node.subsume_const_cases p₁ n p₂ n₂ + · rw [← hc]; exact hck + · rw [hc] at hck; exact absurd hck.symm hk0 + have hne0 : n.const ≠ 0 := fun h0 => hk0 (hkc.symm.trans h0) + rw [hqq, show k = k' from by rw [← hck', hn₂, ← hnconst hne0, hkc]] + · have hbeq : (p₁.length == p₂.length) = false := by simpa using hlen + rw [hsu, hbeq] at hck + have hkc : n.const = k := by + obtain hc | hc := Node.subsumeBy_const_cases (same := false) n n₂ + · rw [← hc]; exact hck + · rw [hc] at hck; exact absurd hck.symm hk0 + refine absurd hck ?_ + rw [Node.subsumeBy_const_complete (n₁ := n) (n₂ := n₂) + (.inl ⟨rfl, by rw [hkc, hck']; exact hlek⟩)] + exact fun h => hk0 h.symm + · -- const dominated by a variable + obtain ⟨rfl, hck, hk0⟩ := ht' + obtain ⟨rfl, hyk⟩ := ht'' + obtain ⟨hsub, hlek⟩ := hle + have hgate : subset compare p₂ p₁ := subset_of_sorted hs₂ hs₁ hsub + have hsu : Node.subsume p₁ n p₂ n₂ = n.subsumeBy (p₁.length == p₂.length) n₂ := by + rw [Node.subsume, if_pos hgate] + rw [hsu] at hck + have hkc : n.const = k := by + obtain hc | hc := Node.subsumeBy_const_cases (same := p₁.length == p₂.length) n n₂ + · rw [← hc]; exact hck + · rw [hc] at hck; exact absurd hck.symm hk0 + refine absurd hck ?_ + rw [Node.subsumeBy_const_complete (n₁ := n) (n₂ := n₂) + (.inr ⟨⟨y, k'⟩, hyk, by rw [hkc]; exact hlek⟩)] + exact fun h => hk0 h.symm + · exact hle.elim + · -- variable dominated by a variable + obtain ⟨rfl, hxk⟩ := ht' + obtain ⟨rfl, hyk⟩ := ht'' + obtain ⟨hsub, rfl, hlek⟩ := hle + have hgate : subset compare p₂ p₁ := subset_of_sorted hs₂ hs₁ hsub + have hsu : Node.subsume p₁ n p₂ n₂ = n.subsumeBy (p₁.length == p₂.length) n₂ := by + rw [Node.subsume, if_pos hgate] + by_cases hlen : p₁.length = p₂.length + · have hqq : p₂ = p₁ := subset_eq hgate hlen.symm + have hn₂ : n₂ = n₁ := by + rw [hqq] at h₂; cases h₂.symm.trans h₁; rfl + have hk : (⟨x, k⟩ : VarNode) = ⟨x, k'⟩ := + hvs₁.eq_of_var_eq (hnvar _ (Node.subsume_var_subset hxk)) (hn₂ ▸ hyk) rfl + rw [hqq, show k = k' from congrArg VarNode.offset hk] + · have hbeq : (p₁.length == p₂.length) = false := by simpa using hlen + rw [hsu, hbeq] at hxk + exact (Node.subsumeBy_var_complete hvs hvs₂ hxk hyk rfl hlek).elim + · exact hrest _ hpn _ ht'' hle + +theorem NormLevel.minimize_exact {acc : NormLevel} {p₁ : List Name} {n₁ : Node} + (hsort : ∀ p n, acc.get? p = some n → Sorted p) (hvsa : acc.SortedVars) + (h₁ : acc.get? p₁ = some n₁) : + ∀ t t', Node.HasSub p₁ (acc.minimize p₁ n₁) t → acc.HasSub t' → t.le t' → t = t' := by + intro t t' ht ht' hle + rw [minimize, Std.TreeMap.foldl_eq_foldl_toList] at ht + have hmem pn (h : pn ∈ acc.toList) : acc.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + obtain ⟨-, hexact⟩ := minimize_exact_aux hsort hvsa h₁ (hsort _ _ h₁) (hvsa _ _ h₁) + acc.toList n₁ hmem (fun _ => id) (fun _ => rfl) (hvsa _ _ h₁) t ht + obtain ⟨p₂, n₂, hp₂, hn₂⟩ := hasSub_iff.1 ht' + exact hexact (p₂, n₂) (Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 + (Std.TreeMap.get?_eq_getElem? .. ▸ hp₂)) _ hn₂ hle + +/-- A normal form is reduced when no sublevel is dominated by another: domination between +recorded sublevels forces them to be the same sublevel. -/ +def NormLevel.Reduced (s : NormLevel) : Prop := + ∀ t t', s.HasSub t → s.HasSub t' → t.le t' → t = t' + +/-- `subsumption` produces a reduced map: every entry is minimized against the (current) +whole map, minimization removes exactly the dominated sublevels, and later steps only +shrink the map, which cannot introduce new domination. -/ +theorem NormLevel.subsumption_reduced {s : NormLevel} + (hsort : ∀ p n, s.get? p = some n → Sorted p) (hvsa : s.SortedVars) : + s.subsumption.Reduced := by + have hmem pn (h : pn ∈ s.toList) : s.get? pn.1 = some pn.2 := + Std.TreeMap.get?_eq_getElem? .. ▸ Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 h + have nd : (s.toList.map Prod.fst).Nodup := by simpa using Std.TreeMap.nodup_keys (t := s) + rw [Reduced, subsumption, Std.TreeMap.foldl_eq_foldl_toList] + suffices ∀ (l : List (List Name × Node)) (acc : NormLevel), + (l.map Prod.fst).Nodup → + (∀ pn ∈ l, acc.get? pn.1 = some pn.2) → + (∀ p n, acc.get? p = some n → Sorted p) → acc.SortedVars → + (∀ p n, acc.get? p = some n → p ∉ l.map Prod.fst → + ∀ t t', Node.HasSub p n t → acc.HasSub t' → t.le t' → t = t') → + ∀ t t', (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).HasSub t → + (List.foldl (fun acc pn => + let n := acc.minimize pn.1 pn.2 + if n.isEmpty then acc.erase pn.1 else acc.insert pn.1 n) acc l).HasSub t' → + t.le t' → t = t' from + this _ _ nd hmem hsort hvsa fun p n hp hnp => absurd + (List.mem_map_of_mem (f := Prod.fst) (Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 + (Std.TreeMap.get?_eq_getElem? .. ▸ hp))) hnp + clear hmem nd hsort hvsa; intro l + induction l with + | nil => + intro acc _ _ _ _ hred t t' ht ht' hle + obtain ⟨p, n, hp, hnt⟩ := hasSub_iff.1 ht + exact hred p n hp (by simp) t t' hnt ht' hle + | cons pn l ih => + obtain ⟨p₂, n₂⟩ := pn + intro acc nd hl hsorta hvsacc hred + simp only [List.map_cons, List.nodup_cons] at nd + have h₂ : acc.get? p₂ = some n₂ := hl _ (.head _) + simp only [List.foldl_cons] + have hstep := subsumption_step_get? acc n₂ p₂ + refine ih _ nd.2 (fun pn' h => ?_) (fun p n h => ?_) (fun p n h => ?_) + (fun p n hp hnp t t' hnt ht' hle => ?_) + · have hne : p₂ ≠ pn'.1 := fun e => nd.1 (e ▸ List.mem_map_of_mem (f := Prod.fst) h) + rw [hstep, if_neg hne] + exact hl _ (.tail _ h) + · rw [hstep] at h; split at h <;> rename_i hpe + · split at h <;> [cases h; skip] + cases h; exact hpe ▸ hsorta _ _ h₂ + · exact hsorta _ _ h + · rw [hstep] at h; split at h <;> rename_i hpe + · split at h <;> [cases h; skip] + cases h + exact (hvsacc _ _ h₂).sublist minimize_var_sublist + · exact hvsacc _ _ h + · rw [hstep] at hp; split at hp <;> rename_i hpe + · split at hp <;> [cases hp; skip] + cases hp; subst hpe + exact minimize_exact hsorta hvsacc h₂ t t' hnt (subsumption_step_hasSub h₂ ht') hle + · refine hred p n hp ?_ t t' hnt (subsumption_step_hasSub h₂ ht') hle + simp only [List.map_cons, List.mem_cons, not_or] + exact ⟨fun e => hpe e.symm, hnp⟩ + +theorem normalize_reduced : (normalize u).Reduced := by + refine NormLevel.subsumption_reduced ?_ (normalizeAux_sortedVars fun _ _ => by simp) + exact fun p n h => (normalizeAux_wf (by simp) (by simp [NormLevel.WF]) p n h).2.2 + +/-! Canonicity: two reduced normal forms with the same semantics have the same sublevels, +and hence are equal maps. -/ + +instance : LawfulBEq Node where + rfl {a} := by cases a <;> simp! +instances [instBEqNode] + eq_of_beq {a b} h := by + cases a; cases b + simp! +instances [instBEqNode] at h + simp [h.1, h.2] + +theorem VarsSorted.eq_of_mem_iff : ∀ {l₁ l₂ : List VarNode}, VarsSorted l₁ → VarsSorted l₂ → + (∀ x, x ∈ l₁ ↔ x ∈ l₂) → l₁ = l₂ + | [], [], _, _, _ => rfl + | [], _ :: _, _, _, h => nomatch (h _).2 (.head _) + | _ :: _, [], _, _, h => nomatch (h _).1 (.head _) + | a :: l₁, b :: l₂, h₁, h₂, h => by + cases show a = b by + rcases List.mem_cons.1 ((h a).1 (.head _)) with rfl | ha <;> [rfl; skip] + rcases List.mem_cons.1 ((h b).2 (.head _)) with rfl | hb <;> [rfl; skip] + exact absurd (h₂.head _ ha) (by rw [Std.OrientedCmp.gt_of_lt (h₁.head _ hb)]; simp) + refine congrArg (a :: ·) (VarsSorted.eq_of_mem_iff h₁.of_cons h₂.of_cons + fun x => ⟨fun hx => ?_, fun hx => ?_⟩) + · rcases List.mem_cons.1 ((h x).1 (.tail _ hx)) with rfl | hx' + · exact absurd (h₁.head _ hx) (by rw [Std.ReflOrd.compare_self]; simp) + · exact hx' + · rcases List.mem_cons.1 ((h x).2 (.tail _ hx)) with rfl | hx' + · exact absurd (h₂.head _ hx) (by rw [Std.ReflOrd.compare_self]; simp) + · exact hx' + +theorem NormLevel.HasSub.path_sorted {s : NormLevel} + (hsort : ∀ p n, s.get? p = some n → Sorted p) : ∀ {t}, s.HasSub t → Sorted t.path + | .const _ _, ⟨_, hn, _⟩ => hsort _ _ hn + | .var _ _ _, ⟨_, hn, _⟩ => hsort _ _ hn + +/-- In reduced maps, mutual per-sublevel domination pins the sublevels to be equal: the +dominator of a sublevel is itself dominated by a sublevel of the first map, which by +reducedness is the sublevel we started from, and antisymmetry finishes. -/ +theorem NormLevel.Reduced.hasSub_iff_hasSub {A B : NormLevel} + (rA : A.Reduced) (rB : B.Reduced) + (sortA : ∀ p n, A.get? p = some n → Sorted p) + (sortB : ∀ p n, B.get? p = some n → Sorted p) + (hAB : ∀ t, A.HasSub t → ∃ t', B.HasSub t' ∧ t.le t') + (hBA : ∀ t, B.HasSub t → ∃ t', A.HasSub t' ∧ t.le t') : + ∀ t, A.HasSub t ↔ B.HasSub t := by + suffices ∀ {A B : NormLevel}, A.Reduced → + (∀ p n, A.get? p = some n → Sorted p) → (∀ p n, B.get? p = some n → Sorted p) → + (∀ t, A.HasSub t → ∃ t', B.HasSub t' ∧ t.le t') → + (∀ t, B.HasSub t → ∃ t', A.HasSub t' ∧ t.le t') → + ∀ t, A.HasSub t → B.HasSub t from + fun t => ⟨this rA sortA sortB hAB hBA t, this rB sortB sortA hBA hAB t⟩ + clear rA rB sortA sortB hAB hBA + intro A B rA sortA sortB hAB hBA t ht + obtain ⟨t', ht', hle⟩ := hAB t ht + obtain ⟨t'', ht'', hle'⟩ := hBA t' ht' + cases rA t t'' ht ht'' (hle.trans hle') + exact (hle.antisymm (HasSub.path_sorted sortA ht) (HasSub.path_sorted sortB ht') hle').symm ▸ ht' + +/-- Two reduced normal forms with the same sublevels are equal as `NormLevel`s. -/ +theorem NormLevel.eq_of_hasSub_iff {A B : NormLevel} + (hvsA : A.SortedVars) (hvsB : B.SortedVars) + (hneA : ∀ p n, A.get? p = some n → n.isEmpty = false) + (hneB : ∀ p n, B.get? p = some n → n.isEmpty = false) + (h : ∀ t, A.HasSub t ↔ B.HasSub t) : A == B := by + suffices ∀ {A B : NormLevel}, A.SortedVars → B.SortedVars → + (∀ p n, A.get? p = some n → n.isEmpty = false) → + (∀ t, A.HasSub t ↔ B.HasSub t) → + ∀ p n, A.get? p = some n → B.get? p = some n by + have h1 := @this A B hvsA hvsB hneA h + have h2 := @this B A hvsB hvsA hneB fun t => (h t).symm + simp +instances only [instBEqNormLevel, Std.TreeMap.all_eq_all_toList, + Bool.and_eq_true, List.all_eq_true] + constructor <;> rintro ⟨p, n⟩ hpn + · have := h1 p n (Std.TreeMap.get?_eq_getElem? .. ▸ + Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 hpn) + rw [Std.TreeMap.get?_eq_getElem?] at this + simp [this] + · have := h2 p n (Std.TreeMap.get?_eq_getElem? .. ▸ + Std.TreeMap.mem_toList_iff_getElem?_eq_some.1 hpn) + rw [Std.TreeMap.get?_eq_getElem?] at this + simp [this] + clear hvsA hvsB hneA hneB h + intro A B hvsA hvsB hneA h p n hp + have hne := hneA _ _ hp + rw [Node.isEmpty, Bool.and_eq_false_iff] at hne + have hBp : ∃ m, B.get? p = some m := by + obtain h0 | hv := hne + · obtain ⟨m, hm, -⟩ := (h (.const p n.const)).1 ⟨n, hp, rfl, by simpa using h0⟩ + exact ⟨m, hm⟩ + · obtain ⟨x, hx⟩ := List.exists_mem_of_ne_nil _ (by simpa using hv) + obtain ⟨m, hm, -⟩ := (h (.var p x.var x.offset)).1 ⟨n, hp, hx⟩ + exact ⟨m, hm⟩ + obtain ⟨m, hm⟩ := hBp + have hconst : n.const = m.const := by + by_cases h0 : n.const = 0 + · by_cases h0' : m.const = 0 + · rw [h0, h0'] + · obtain ⟨n', hn', hc, -⟩ := (h (.const p m.const)).2 ⟨m, hm, rfl, h0'⟩ + cases hn'.symm.trans hp + exact absurd (h0 ▸ hc).symm h0' + · obtain ⟨m', hm', hc, -⟩ := (h (.const p n.const)).1 ⟨n, hp, rfl, h0⟩ + cases hm'.symm.trans hm + exact hc.symm + have hvar : n.var = m.var := by + refine VarsSorted.eq_of_mem_iff (hvsA _ _ hp) (hvsB _ _ hm) + fun x => ⟨fun hx => ?_, fun hx => ?_⟩ + · obtain ⟨m', hm', hx'⟩ := (h (.var p x.var x.offset)).1 ⟨n, hp, hx⟩ + cases hm'.symm.trans hm + exact hx' + · obtain ⟨n', hn', hx'⟩ := (h (.var p x.var x.offset)).2 ⟨m, hm, hx⟩ + cases hn'.symm.trans hp + exact hx' + obtain ⟨nc, nv⟩ := n + obtain ⟨mc, mv⟩ := m + cases hconst; cases hvar + exact hm + +/-- Semantically equal levels have `BEq`-equal normal forms. -/ +theorem normalize_complete (hu : VLevel.ofLevel ls u = some u') + (hv : VLevel.ofLevel ls v = some v') : normalize u == normalize v ↔ u' ≈ v' := by + refine .trans ⟨fun h ls => ?_, fun h => ?_⟩ VLevel.equiv_def.symm + · rw [← normalize_eval hu, NormLevel.eval_congr h, normalize_eval hv] + have h₁ : ∀ ρ, (normalize u).eval ls ρ ≤ (normalize v).eval ls ρ := fun ρ => by + rw [normalize_eval hu, normalize_eval hv, h ρ]; exact Nat.le_refl _ + have h₂ : ∀ ρ, (normalize v).eval ls ρ ≤ (normalize u).eval ls ρ := fun ρ => by + rw [normalize_eval hu, normalize_eval hv, h ρ]; exact Nat.le_refl _ + exact NormLevel.eq_of_hasSub_iff normalize_sortedVars normalize_sortedVars + normalize_nonempty normalize_nonempty + (NormLevel.Reduced.hasSub_iff_hasSub normalize_reduced normalize_reduced + normalize_sorted normalize_sorted + (NormLevel.separation (normalize_keys hu) normalize_vars h₁) + (NormLevel.separation (normalize_keys hv) normalize_vars h₂)) + +/-! `BEq`-equal maps have equal `toList`s, and the reconstruction depends on the map only +through `toList`, so equal normal forms reify to syntactically equal levels. (`TreeMap` +equality itself does not follow from `==`: the internal tree shape depends on insertion +order.) -/ + +theorem NormLevel.toList_eq {A B : NormLevel} (h : A == B) : A.toList = B.toList := by + simp +instances only [instBEqNormLevel, Std.TreeMap.all_eq_all_toList, + Bool.and_eq_true, List.all_eq_true] at h + refine sorted_pairs_eq Std.TreeMap.ordered_keys_toList Std.TreeMap.ordered_keys_toList + fun x => ⟨fun hx => ?_, fun hx => ?_⟩ + · have := h.1 x hx + rw [beq_iff_eq, Std.TreeMap.get?_eq_getElem?] at this + exact Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 this + · have := h.2 x hx + rw [beq_iff_eq, Std.TreeMap.get?_eq_getElem?] at this + exact Std.TreeMap.mem_toList_iff_getElem?_eq_some.2 this + +theorem NormLevel.addable_congr {A B : NormLevel} (h : A.toList = B.toList) : + A.addable a acc = B.addable a acc := by + rw [addable, addable, Std.TreeMap.any_eq_any_toList, Std.TreeMap.any_eq_any_toList, h] + +theorem NormLevel.feasible_go_congr {A B : NormLevel} (h : A.toList = B.toList) : + ∀ fuel acc rem, NormLevel.feasible.go A fuel acc rem = NormLevel.feasible.go B fuel acc rem + | 0, _, _ => rfl + | fuel+1, acc, rem => by + simp only [feasible.go] + rw [show (fun a => A.addable a acc) = fun a => B.addable a acc from + funext fun a => addable_congr h] + cases rem.find? fun a => B.addable a acc with + | none => rfl + | some a => exact feasible_go_congr h fuel _ _ + +theorem NormLevel.feasible_congr {A B : NormLevel} (h : A.toList = B.toList) : + A.feasible acc rem = B.feasible acc rem := by + simp only [feasible]; exact feasible_go_congr h .. + +theorem NormLevel.lexChain_congr {A B : NormLevel} (h : A.toList = B.toList) : + ∀ fuel p, A.lexChain fuel p = B.lexChain fuel p + | 0, _ => rfl + | fuel+1, p => by + simp only [lexChain] + rw [show (fun a => A.addable a (p.erase a) && A.feasible [] (p.erase a)) + = fun a => B.addable a (p.erase a) && B.feasible [] (p.erase a) from + funext fun a => by rw [addable_congr h, feasible_congr h]] + cases p.find? fun a => B.addable a (p.erase a) && B.feasible [] (p.erase a) with + | none => rfl + | some a => exact congrArg (a :: ·) (lexChain_congr h fuel _) + +/-- The reconstruction depends only on the entry list of the map. -/ +theorem NormLevel.toTree_congr {A B : NormLevel} (h : A.toList = B.toList) : + A.toTree = B.toTree := by + rw [toTree, toTree, Std.TreeMap.foldl_eq_foldl_toList, Std.TreeMap.foldl_eq_foldl_toList, h] + congr 1 + funext t pn + rw [lexChain_congr h] + +/-- The fast path is transparent: it computes the same tree the general path does. -/ +theorem normalize'_eq (l : Level) : normalize' l = (normalize l).toTree.reify := by + rw [normalize'] + have hrep := flatAux_rep (l := l) (k := 0) (c := 0) (vs := []) (s := {}) .nil + (fun p => by match p with | [] | [_] | _::_::_ => simp [flatGet]) + match hf : flatAux l 0 (0, []) with + | .ok (c, vs) => + rw [hf] at hrep + obtain ⟨hvs, hflat⟩ := hrep + rw [normalize, (NormLevel.subsumption_flat hflat).toTree hvs] + | .error s => + rw [hf] at hrep; dsimp only + rw [normalize, NormLevel.toTree_congr (toList_eq_of_get?_eq (NormLevel.subsumption_congr hrep))] + +end Normalize + +theorem isStructEq_eq {u v : Level} (h : isStructEq u v) : u = v := by + induction u generalizing v with + | zero => cases v <;> simp_all [isStructEq] + | succ u ih => + cases v <;> simp [isStructEq] at h + exact congrArg Level.succ (ih h) + | max u₁ u₂ ih₁ ih₂ => + cases v <;> simp [isStructEq] at h + cases ih₁ h.1 + cases ih₂ h.2 + rfl + | imax u₁ u₂ ih₁ ih₂ => + cases v <;> simp [isStructEq] at h + cases ih₁ h.1 + cases ih₂ h.2 + rfl + | param u => + cases v <;> simp_all [isStructEq] + | mvar u => + rcases u with ⟨u⟩ + cases v <;> simp_all [isStructEq] + +theorem isStructEq_iff_eq {u v : Level} : isStructEq u v ↔ u = v := by + constructor + · exact isStructEq_eq + · rintro rfl + induction u <;> simp_all [isStructEq] + +theorem isEquiv'_wf (h : isEquiv' u v) + (hu : VLevel.ofLevel ls u = some u') (hv : VLevel.ofLevel ls v = some v') : u' ≈ v' := by + simp only [isEquiv', Bool.or_eq_true] at h + obtain h | h := h + · exact isEquiv_wf h hu hv + · refine VLevel.equiv_def.2 fun ρ => ?_ + rw [← Normalize.normalize_eval (ρ := ρ) hu, ← Normalize.normalize_eval (ρ := ρ) hv] + exact Normalize.NormLevel.eval_congr h + +/-- Soundness of reification: the level `normalize'` reconstructs evaluates like the input +everywhere. Reification is `toTree` followed by `reify`, and both preserve the value: the +tree's `imax` chains contribute nothing the normal form does not already have, since every +key admits a chain (`normalize_feas`) and `lexChain` then picks an admissible one, and +nothing is lost, since every entry is recorded at the end of its chain. -/ +theorem normalize'_eval (hu : VLevel.ofLevel ls u = some u') : + Level.eval (Normalize.evalParam ls ρ) μ (normalize' u) = u'.eval ρ := by + open Normalize in + rw [normalize'_eq, Tree.reify_eval, NormLevel.toTree_eval normalize_sorted normalize_feas] + exact normalize_eval hu + +theorem geq'_wf (hu : VLevel.ofLevel ls u = some u') (hv : VLevel.ofLevel ls v = some v') + (h : geq' u v) : v' ≤ u' := by + simp only [geq', Bool.or_eq_true] at h + obtain h | h := h + · exact geq_wf h hu hv + · intro ρ + rw [← Normalize.normalize_eval (ρ := ρ) hv, ← Normalize.normalize_eval (ρ := ρ) hu] + exact Normalize.NormLevel.le_eval Normalize.normalize_vars h + +theorem isEquivList_wf (H : Level.isEquivList us vs) : + List.mapM (VLevel.ofLevel Us) us = some us' → + List.mapM (VLevel.ofLevel Us) vs = some vs' → us'.Forall₂ (· ≈ ·) vs' := by + simp [Level.isEquivList] at H; revert us' vs' + induction us generalizing vs with cases vs <;> simp [List.all2] at H <;> simp | cons u us ih + rename_i v vs; rintro _ _ u' hu us' hus rfl v' hv vs' hvs rfl + exact .cons (isEquiv'_wf H.1 hu hv) (ih H.2 hus hvs) + +/-- Canonicity of `normalize'`: semantically equal levels reconstruct to syntactically equal +levels. The normal forms are `BEq`-equal, hence have the same entry list, and the +reconstruction (`lexChain` and the tree fold) depends on the map only through its entry +list. -/ +theorem normalize'_complete (hu : VLevel.ofLevel ls u = some u') + (hv : VLevel.ofLevel ls v = some v') : normalize' u = normalize' v ↔ u' ≈ v' := by + refine ⟨fun h => ?_, fun h => ?_⟩ + · refine VLevel.equiv_def.2 fun ρ => ?_ + rw [← normalize'_eval (μ := fun _ => 0) hu, ← normalize'_eval hv, h] + · rw [Normalize.normalize'_eq, Normalize.normalize'_eq] + rw [← Normalize.normalize_complete hu hv] at h + rw [Normalize.NormLevel.toTree_congr (Normalize.NormLevel.toList_eq h)] + +/-- Completeness of `isEquiv'`: semantically equal levels have equal normal forms. Both +normal forms are reduced (`subsumption_reduced`), mutually dominate each other's sublevels +(`separation`), and reduced forms with the same sublevels are the same map. -/ +theorem isEquiv'_complete (hu : VLevel.ofLevel ls u = some u') + (hv : VLevel.ofLevel ls v = some v') : isEquiv' u v ↔ u' ≈ v' := by + simp only [isEquiv', Bool.or_eq_true, Normalize.normalize_complete hu hv] + exact ⟨fun h => h.elim (fun h => isEquiv_wf h hu hv) id, .inr⟩ + +/-- Completeness of `geq'`: every valid semantic inequality is accepted. Every sublevel of +`normalize v` is semantically bounded by `normalize u`, hence syntactically dominated by one +of its sublevels (`separation`), which is exactly what the discharging fold in +`NormLevel.le` checks for. -/ +theorem geq'_complete (hu : VLevel.ofLevel ls u = some u') + (hv : VLevel.ofLevel ls v = some v') : geq' u v ↔ v' ≤ u' := by + open Normalize in + refine ⟨geq'_wf hu hv, fun h => ?_⟩ + simp only [geq', Bool.or_eq_true] + refine .inr ?_ + refine NormLevel.le_complete normalize_sortedVars normalize_sortedVars normalize_nonempty + normalize_sorted normalize_sorted ?_ + refine NormLevel.separation (normalize_keys hv) normalize_vars fun ρ => ?_ + rw [normalize_eval hv, normalize_eval hu] + exact h ρ diff --git a/Ix/Theory/Named/Verify/LevelStd.lean b/Ix/Theory/Named/Verify/LevelStd.lean new file mode 100644 index 000000000..e05736b3c --- /dev/null +++ b/Ix/Theory/Named/Verify/LevelStd.lean @@ -0,0 +1,549 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Batteries.Tactic.OpenPrivate +import Ix.Theory.Named.VLevel +import Ix.Theory.Named.Verify.QSort +import Ix.Theory.Named.Verify.NormLt + +open Ix.Theory (VLevel) + +open private go in Lean.Level.geq +open private accMax mkIMaxAux isExplicitSubsumed from Lean.Level + +namespace Lean.Level + +open Ix.Theory.Named + +/-! +Semantic soundness of the universe-level operations in Lean's standard library. +`normalize` is an opaque `partial def`, so `Ix.Theory.Named.Verify.Axioms` assumes it +equals the total copy `Lean.Level.Total.normalize` defined there; the semantic +behavior of that copy is `eval_normalize` below, which is still open. The exact +correspondence between `geqCore` below and the private recursion used by +`Lean.Level.geq` is proved. +-/ + +variable (ρ : Name → Nat) (μ : LMVarId → Nat) in +def eval : Level → Nat + | .zero => 0 + | .param n => ρ n + | .mvar n => μ n + | .succ l => eval l + 1 + | .max l₁ l₂ => Nat.max (eval l₁) (eval l₂) + | .imax l₁ l₂ => Nat.imax (eval l₁) (eval l₂) + +private def offset : Level → Nat + | .succ l => offset l + 1 + | _ => 0 + +private theorem getOffsetAux_eq_offset : + l.getOffsetAux k = offset l + k := by + induction l generalizing k with + | succ l ih => simp only [Level.getOffsetAux, offset, ih]; omega + | _ => simp [Level.getOffsetAux, offset] + +private theorem getOffset_eq_offset : l.getOffset = offset l := by + simp [Level.getOffset, getOffsetAux_eq_offset] + +theorem eval_getLevelOffset : + eval ρ μ l = eval ρ μ l.getLevelOffset + l.getOffset := by + induction l with | succ l ih => ?_ | _ => rfl + simp only [eval, Level.getLevelOffset, getOffset_eq_offset, offset, ih] + omega + +theorem fallback_sound + (h : (u.getLevelOffset = v.getLevelOffset ∨ v.getLevelOffset.isZero = true) ∧ + v.getOffset ≤ u.getOffset) : + eval ρ μ v ≤ eval ρ μ u := by + rw [eval_getLevelOffset, eval_getLevelOffset (l := u)] + rcases h with ⟨hv | hv, hk⟩ + · rw [← hv]; omega + · have hv : v.getLevelOffset = .zero := by + generalize hbase : v.getLevelOffset = base at hv + cases base <;> simp_all [Level.isZero] + simp [hv, eval] + omega + +def geqCore : Level → Level → Bool + -- Keep this in the same source-shaped form as `go`'s `u == v || ...` prefix. + -- The apparently redundant `|| true` is therefore deliberate. + | u, .zero => u == .zero || true + | u, .max v₁ v₂ => u == .max v₁ v₂ || (geqCore u v₁ && geqCore u v₂) + | .max u₁ u₂, .imax v₁ v₂ => + (.max u₁ u₂ : Level) == .imax v₁ v₂ || + (geqCore u₁ (.imax v₁ v₂) || geqCore u₂ (.imax v₁ v₂) || + (geqCore (.max u₁ u₂) v₁ && geqCore (.max u₁ u₂) v₂)) + | .max u₁ u₂, v => + let u := .max u₁ u₂ + u == v || (geqCore u₁ v || geqCore u₂ v || + ((u.getLevelOffset == v.getLevelOffset || v.getLevelOffset.isZero) && + u.getOffset ≥ v.getOffset)) + | .imax u₁ u₂, v => (.imax u₁ u₂ : Level) == v || geqCore u₂ v + | .succ u, .succ v => (.succ u : Level) == .succ v || geqCore u v + | u, .imax v₁ v₂ => u == .imax v₁ v₂ || (geqCore u v₁ && geqCore u v₂) + | u, v => u == v || + ((u.getLevelOffset == v.getLevelOffset || v.getLevelOffset.isZero) && + u.getOffset ≥ v.getOffset) + termination_by u v => (u, v) + +private theorem geqCore_eq_go : geqCore u v = go u v := by + fun_induction go with | _ u v + cases u <;> cases v <;> simp_all [geqCore, go] + +theorem geqCore_sound (h : geqCore u v) : eval ρ μ v ≤ eval ρ μ u := by + induction u, v using geqCore.induct with + simp only [geqCore, Bool.or_eq_true, Bool.and_eq_true, beq_iff_eq, + decide_eq_true_eq] at h + | case1 => simp [eval] + | case2 _ _ _ ih₂ ih₁ => + rcases h with rfl | ⟨h₁, h₂⟩ + · exact Nat.le_refl _ + · exact (Nat.max_le).2 ⟨ih₂ h₁, ih₁ h₂⟩ + | case3 u₁ u₂ v₁ v₂ ih₄ ih₃ ih₂ ih₁ => + rcases h with heq | (h | h) | ⟨h₁, h₂⟩ + · exact Nat.le_of_eq (congrArg (eval ρ μ) heq).symm + · exact Nat.le_trans (ih₄ h) (Nat.le_max_left ..) + · exact Nat.le_trans (ih₃ h) (Nat.le_max_right ..) + · simp only [eval, Nat.imax] + split + · exact Nat.zero_le _ + · exact (Nat.max_le).2 ⟨ih₂ h₁, ih₁ h₂⟩ + | case4 u₁ u₂ v _ _ _ ih₂ ih₁ => + rcases h with rfl | h + · exact Nat.le_refl _ + · rcases h with (h | h) | h + · exact Nat.le_trans (ih₂ h) (Nat.le_max_left ..) + · exact Nat.le_trans (ih₁ h) (Nat.le_max_right ..) + · exact fallback_sound h + | case5 u₁ u₂ v _ _ ih => + rcases h with rfl | h + · exact Nat.le_refl _ + · simp only [eval, Nat.imax] + have hv := ih h + split <;> rename_i hz + · simpa [hz] using hv + · exact Nat.le_trans hv (Nat.le_max_right ..) + | case6 u v ih => + rcases h with heq | h + · exact Nat.le_of_eq (congrArg (eval ρ μ) heq).symm + · simpa [eval] using Nat.add_le_add_right (ih h) 1 + | case7 u v₁ v₂ _ _ ih₂ ih₁ => + rcases h with rfl | ⟨h₁, h₂⟩ + · exact Nat.le_refl _ + · simp only [eval, Nat.imax] + split + · exact Nat.zero_le _ + · exact (Nat.max_le).2 ⟨ih₂ h₁, ih₁ h₂⟩ + | case8 => + rcases h with heq | h + · exact Nat.le_of_eq (congrArg (eval ρ μ) heq).symm + · exact fallback_sound h + +/-! +### Soundness of `normalize` + +The proof is by strong induction on `Total.size`. The mutual recursion with +`getMaxArgsAux` is untangled by observing that `getMaxArgsAux l true` recurses only +structurally, and `getMaxArgsAux l false` calls `normalize` only on levels of size at +most `size l`, so both can be handled by standalone lemmas parameterized by the +induction hypothesis for `normalize`. + +The `max` branch sorts the collected arguments with `qsort normLt` and then drops +dominated entries: `mkMaxAux` drops an entry when the next one has the same level base +(relying on offsets being sorted within a base class), and the explicit (constant) +entries in the sorted prefix are dropped when subsumed by the largest explicit or by +some offset to its right. All of this is justified by a single consequence of +sortedness: entries with equal `getLevelOffset` occur in order of `getOffset` +(`explicit` entries all have base `zero`, so this also orders the explicit prefix). +That fact, together with the fact that `qsort` permutes the array, are the only +properties of sorting used; they are `qsort_perm_toList` and `pairwise_qsort_normLt` +below, currently unproved because `Array.qsort` has no specification in the standard +library. +-/ + +theorem le_ext_le {n m : Nat} (H : ∀ x, n ≤ x → m ≤ x) : m ≤ n := H _ (Nat.le_refl _) + +theorem nat_ext_le {n m : Nat} (H : ∀ x, n ≤ x ↔ m ≤ x) : n = m := + Nat.le_antisymm ((H _).2 (Nat.le_refl _)) ((H _).1 (Nat.le_refl _)) + +theorem eval_addOffset : eval ρ μ (addOffset l k) = eval ρ μ l + k := by + suffices ∀ k l, eval ρ μ (addOffsetAux k l) = eval ρ μ l + k from this .. + intro k; induction k with intro l + | zero => rfl + | succ k ih => rw [addOffsetAux, ih]; simp [eval, mkLevelSucc]; omega + +theorem isZero_iff : isZero l ↔ l = .zero := by cases l <;> simp [Level.isZero] + +theorem isNeverZero_sound (h : l.isNeverZero = true) : 0 < eval ρ μ l := by + induction l with + | zero | param | mvar => simp [isNeverZero] at h + | succ l => simp [eval] + | max l₁ l₂ ih₁ ih₂ => + simp only [isNeverZero, Bool.or_eq_true] at h + simp only [eval, Nat.max_eq_max] + obtain h | h := h + · have := ih₁ h; omega + · have := ih₂ h; omega + | imax l₁ l₂ _ ih₂ => + simp only [isNeverZero] at h + have := ih₂ h + simp only [eval, Nat.imax, Nat.max_eq_max]; split <;> omega + +theorem eval_accMax : eval ρ μ (accMax r p k) = Nat.max (eval ρ μ r) (eval ρ μ p + k) := by + rw [accMax]; split <;> rename_i h + · rw [isZero_iff.1 h, eval_addOffset]; simp [eval] + · simp [mkLevelMax, eval, eval_addOffset] + +theorem eval_mkIMaxAux : + eval ρ μ (mkIMaxAux a b) = Nat.imax (eval ρ μ a) (eval ρ μ b) := by + unfold mkIMaxAux; split + · simp [eval, Nat.imax] + · simp only [eval, Nat.imax]; split <;> [omega; simp] + · simp only [eval, Nat.imax, Nat.max_eq_max]; split <;> [omega; rw [Nat.max_eq_right (by omega)]] + · split <;> rename_i h + · cases eq_of_beq h; simp only [Nat.imax, Nat.max_eq_max] + split <;> [omega; rw [Nat.max_self]] + · simp [mkLevelIMax, eval] + +/-- The maximum of the evaluations of a list of levels. -/ +def evalList (ρ : Name → Nat) (μ : LMVarId → Nat) (ls : List Level) : Nat := + ls.foldr (fun l n => Nat.max (eval ρ μ l) n) 0 + +theorem evalList_le_iff : evalList ρ μ ls ≤ n ↔ ∀ l ∈ ls, eval ρ μ l ≤ n := by + induction ls with + | nil => simp [evalList, Nat.zero_le] + | cons l ls ih => + show Nat.max (eval ρ μ l) (evalList ρ μ ls) ≤ n ↔ _ + rw [Nat.max_eq_max, Nat.max_le, ih]; simp + +theorem le_evalList (h : l ∈ ls) : eval ρ μ l ≤ evalList ρ μ ls := + evalList_le_iff.1 (Nat.le_refl _) _ h + +theorem evalList_perm (h : ls₁.Perm ls₂) : evalList ρ μ ls₁ = evalList ρ μ ls₂ := by + refine nat_ext_le fun _ => ?_; simp only [evalList_le_iff, h.mem_iff] + +theorem evalList_append : evalList ρ μ (ls₁ ++ ls₂) = + Nat.max (evalList ρ μ ls₁) (evalList ρ μ ls₂) := by + induction ls₁ with | nil => simp [evalList] | cons l ls ih + show Nat.max _ (evalList ρ μ (ls ++ ls₂)) = Nat.max (Nat.max _ (evalList ρ μ ls)) _ + rw [ih]; simp only [Nat.max_eq_max]; rw [Nat.max_assoc] + +/-- `Array.qsort` returns a permutation of its input (`Array.qsort_perm`). -/ +theorem qsort_perm (as : Array Level) : (as.qsort normLt).toList.Perm as.toList := + Array.perm_iff_toList_perm.1 (Array.qsort_perm normLt 0 (as.size - 1) as) + +/-- Entries with equal level base come out of `qsort normLt` ordered by offset: a +consequence of sortedness (`Array.qsort_sorted`), since `normLt` compares levels with +equal bases by offset. -/ +theorem pairwise_qsort (as : Array Level) : + (as.qsort normLt).toList.Pairwise fun a b => + a.getLevelOffset = b.getLevelOffset → a.getOffset ≤ b.getOffset := by + rw [List.pairwise_iff_getElem] + intro i j hi hj hij hb + simp only [Array.getElem_toList] at hb + simpa [normLt_same_base hb.symm] using + Array.qsort_sorted normLt normLt_asymm normLt_le_trans as i j hij hj + +theorem offset_le_eval : l.getOffset ≤ eval ρ μ l := by + rw [eval_getLevelOffset]; omega + +theorem eval_of_isZero (h : l.getLevelOffset.isZero) : eval ρ μ l = l.getOffset := by + rw [eval_getLevelOffset, isZero_iff.1 h]; simp [eval] + +theorem skipExplicit_spec {lvls : Array Level} : i ≤ lvls.size → + i ≤ Total.skipExplicit lvls i ∧ Total.skipExplicit lvls i ≤ lvls.size ∧ + ∀ j (_ : j < lvls.size), i ≤ j → j < Total.skipExplicit lvls i → + lvls[j].getLevelOffset.isZero := by + fun_induction Total.skipExplicit lvls i with + | case1 i hi hz ih => + intro h + obtain ⟨ih1, ih2, ih3⟩ := ih (by omega) + refine ⟨by omega, ih2, fun j hj hij hlt => ?_⟩ + rcases Nat.eq_or_lt_of_le hij with rfl | hij' + · exact hz + · exact ih3 j hj (by omega) hlt + | case2 i hi hz => exact fun h => ⟨Nat.le_refl _, by omega, fun j hj hij hlt => by omega⟩ + | case3 i hi => exact fun h => ⟨Nat.le_refl _, by omega, fun j hj hij hlt => by omega⟩ + +theorem isExplicitSubsumedAux_spec {lvls : Array Level} : + Total.isExplicitSubsumedAux lvls mx i = true ↔ + ∃ j, i ≤ j ∧ ∃ (_ : j < lvls.size), mx ≤ lvls[j].getOffset := by + fun_induction Total.isExplicitSubsumedAux lvls mx i with + | case1 i hi hge => simpa using ⟨i, Nat.le_refl _, hi, by omega⟩ + | case2 i hi hlt ih => + rw [ih] + constructor <;> rintro ⟨j, hij, hj, hle⟩ <;> refine ⟨j, ?_, hj, hle⟩ + · omega + · obtain rfl | h := Nat.eq_or_lt_of_le hij <;> omega + | case3 i hi => simp; rintro j hij hj; omega + +theorem eval_mkMaxAux {lvls : Array Level} + (hs : ∀ (i j : Nat) (hi : i < lvls.size) (hj : j < lvls.size), i < j → + lvls[i].getLevelOffset = lvls[j].getLevelOffset → lvls[i].getOffset ≤ lvls[j].getOffset) + (hfuel : lvls.size ≤ i + fuel) + (hi0 : 0 < i) (hile : i ≤ lvls.size) + (hp : ∀ h : i - 1 < lvls.size, prev = lvls[i-1].getLevelOffset ∧ prevK = lvls[i-1].getOffset) : + eval ρ μ (Total.mkMaxAux lvls extraK i prev prevK result) = + Nat.max (eval ρ μ result) (evalList ρ μ (lvls.toList.drop (i-1)) + extraK) := by + induction fuel generalizing i result prev prevK with + | zero => + have hie : i = lvls.size := by omega + obtain ⟨hp, hpk⟩ := hp (by omega) + rw [Total.mkMaxAux.eq_def, dif_neg (by omega), eval_accMax] + have hlast : i - 1 < lvls.size := by omega + have hdrop : lvls.toList.drop (i-1) = [lvls[i-1]] := by + rw [List.drop_eq_getElem_cons (by simp only [Array.length_toList]; omega)] + simp [hie]; omega + have : eval ρ μ lvls[i-1] = eval ρ μ prev + prevK := by + rw [eval_getLevelOffset (l := lvls[i-1]), hp, hpk] + rw [hdrop] + simp only [evalList, List.foldr_cons, List.foldr_nil, this, Nat.max_eq_max] + omega + | succ fuel ih => + rw [Total.mkMaxAux.eq_def] + split <;> rename_i hlt + · obtain ⟨hp, hpk⟩ := hp (by omega) + have hlast : i - 1 < lvls.size := by omega + have hdrop : lvls.toList.drop (i-1) = lvls[i-1] :: lvls.toList.drop i := by + rw [List.drop_eq_getElem_cons (by simp only [Array.length_toList]; omega)] + simp; congr 1; omega + have heval : eval ρ μ lvls[i-1] = eval ρ μ prev + prevK := by + rw [eval_getLevelOffset (l := lvls[i-1]), hp, hpk] + have hmem : eval ρ μ lvls[i] ≤ evalList ρ μ (lvls.toList.drop i) := + le_evalList (by rw [List.drop_eq_getElem_cons (by simp only [Array.length_toList]; omega)]; exact .head _) + dsimp only + split <;> rename_i hbeq + · -- equal bases: drop the previous entry + rw [ih (i := i+1) (by omega) (by omega) (by omega) (fun h => by simp)] + have hb : lvls[i].getLevelOffset = prev := eq_of_beq hbeq + have hk : prevK ≤ lvls[i].getOffset := by + rw [hpk]; exact hs (i-1) i hlast hlt (by omega) (by rw [hb, hp]) + have hle : eval ρ μ lvls[i-1] ≤ evalList ρ μ (lvls.toList.drop i) := by + refine Nat.le_trans ?_ hmem + rw [heval, eval_getLevelOffset (l := lvls[i]), hb, hp] + omega + rw [Nat.add_sub_cancel, hdrop] + have : evalList ρ μ (lvls[i-1] :: lvls.toList.drop i) = + evalList ρ μ (lvls.toList.drop i) := by + exact Nat.max_eq_right hle + rw [this] + · -- new base: accumulate the previous entry + rw [ih (i := i+1) (by omega) (by omega) (by omega) (fun h => by simp)] + rw [Nat.add_sub_cancel, eval_accMax, hdrop] + simp only [evalList, List.foldr_cons, Nat.max_eq_max, heval] + omega + · have hie : i = lvls.size := by omega + obtain ⟨hp, hpk⟩ := hp (by omega) + rw [eval_accMax] + have hlast : i - 1 < lvls.size := by omega + have hdrop : lvls.toList.drop (i-1) = [lvls[i-1]] := by + rw [List.drop_eq_getElem_cons (by simp only [Array.length_toList]; omega)] + simp [hie]; omega + have : eval ρ μ lvls[i-1] = eval ρ μ prev + prevK := by + rw [eval_getLevelOffset (l := lvls[i-1]), hp, hpk] + rw [hdrop] + simp only [evalList, List.foldr_cons, List.foldr_nil, this, Nat.max_eq_max] + omega + +theorem size_lt_getMaxArgsAux_true : + lvls.size < (Total.getMaxArgsAux l true lvls).size := by + induction l generalizing lvls with + | max _ _ ih₁ ih₂ => exact Total.getMaxArgsAux.eq_def .. ▸ Nat.lt_trans ih₁ ih₂ + | _ => rw [Total.getMaxArgsAux.eq_def]; simp + +theorem size_lt_getMaxArgsAux_false : + lvls.size < (Total.getMaxArgsAux l false lvls).size := by + induction l generalizing lvls with + | max _ _ ih₁ ih₂ => exact Total.getMaxArgsAux.eq_def .. ▸ Nat.lt_trans ih₁ ih₂ + | _ => exact Total.getMaxArgsAux.eq_def .. ▸ size_lt_getMaxArgsAux_true .. + +theorem evalList_getMaxArgsAux_true : + evalList ρ μ (Total.getMaxArgsAux l true lvls).toList = + Nat.max (evalList ρ μ lvls.toList) (eval ρ μ l) := by + induction l generalizing lvls with + | max l₁ l₂ ih₁ ih₂ => + rw [Total.getMaxArgsAux, ih₂, ih₁] + simp only [eval, Nat.max_eq_max]; omega + | _ => + rw [Total.getMaxArgsAux.eq_def, Array.toList_push, evalList_append] + simp only [evalList, List.foldr_cons, List.foldr_nil, Nat.max_eq_max]; omega + +theorem evalList_getMaxArgsAux_false {l : Level} + (IH : ∀ u, Total.size u ≤ Total.size l → eval ρ μ (Total.normalize u) = eval ρ μ u) : + evalList ρ μ (Total.getMaxArgsAux l false lvls).toList = + Nat.max (evalList ρ μ lvls.toList) (eval ρ μ l) := by + induction l generalizing lvls with + | max l₁ l₂ ih₁ ih₂ => + rw [Total.getMaxArgsAux.eq_def] + show evalList ρ μ (Total.getMaxArgsAux l₂ false (Total.getMaxArgsAux l₁ false lvls)).toList = _ + rw [ih₂ (fun u hu => IH u (by simp only [Total.size] at *; omega)), + ih₁ (fun u hu => IH u (by simp only [Total.size] at *; omega))] + simp only [eval, Nat.max_eq_max]; omega + | _ => rw [Total.getMaxArgsAux.eq_def, evalList_getMaxArgsAux_true, IH _ (Nat.le_refl _)] + +/-- Dropping a dominated prefix does not change the maximum. -/ +theorem evalList_drop_eq {ls : List Level} (hstart : start ≤ ls.length) + (hdom : ∀ j (hj : j < ls.length), j < start → + eval ρ μ ls[j] ≤ evalList ρ μ (ls.drop start)) : + evalList ρ μ (ls.drop start) = evalList ρ μ ls := by + refine nat_ext_le fun n => ?_ + simp only [evalList_le_iff] + constructor <;> intro H l hl + · obtain ⟨j, hj, rfl⟩ := List.mem_iff_getElem.1 hl + by_cases hjs : j < start + · exact Nat.le_trans (hdom j hj hjs) (evalList_le_iff.2 H) + · refine H _ (List.mem_iff_getElem.2 ⟨j - start, by simp; omega, ?_⟩) + rw [List.getElem_drop]; congr 1; omega + · exact H l (List.drop_subset _ _ hl) + +/-- The level base of a level that is not already normalized is a `max` or an `imax`. -/ +theorem base_of_not_cheap {l : Level} (h : ¬l.isAlreadyNormalizedCheap = true) : + (∃ a b, l.getLevelOffset = .max a b) ∨ (∃ a b, l.getLevelOffset = .imax a b) := by + induction l with + | succ l ih => apply ih; simpa [isAlreadyNormalizedCheap] using h + | max l₁ l₂ => exact .inl ⟨_, _, rfl⟩ + | imax l₁ l₂ => exact .inr ⟨_, _, rfl⟩ + | _ => simp [isAlreadyNormalizedCheap] at h + +theorem eval_normalize_total {l : Level} : eval ρ μ (Total.normalize l) = eval ρ μ l := by + generalize hn : Total.size l = n + induction n using Nat.strongRecOn generalizing l with | _ n IH + subst hn + rw [Total.normalize.eq_def] + split <;> [rfl; rename_i hcheap] + have hsz := Total.size_getLevelOffset l + split <;> [rename_i l₁ l₂ hbase; rename_i l₁ l₂ hbase; skip] + · -- max + rw [eval_getLevelOffset (l := l), hbase] + rw [hbase] at hsz; simp only [Total.size] at hsz + have hs₁ := Total.one_le_size l₁ + have hs₂ := Total.one_le_size l₂ + have IH₁ u (hu : Total.size u ≤ Total.size l₁) : eval ρ μ (Total.normalize u) = eval ρ μ u := + IH _ (by omega) rfl + have IH₂ u (hu : Total.size u ≤ Total.size l₂) : eval ρ μ (Total.normalize u) = eval ρ μ u := + IH _ (by omega) rfl + extract_lets k lvls₁ L1 L i₀ i lvl₁ prev prevK + have hevalL1 : evalList ρ μ L1.toList = Nat.max (eval ρ μ l₁) (eval ρ μ l₂) := by + rw [evalList_getMaxArgsAux_false IH₂, evalList_getMaxArgsAux_false IH₁] + simp [evalList, Nat.max_eq_max] + have hL1pos : 0 < L1.size := + Nat.lt_trans (size_lt_getMaxArgsAux_false (lvls := #[])) size_lt_getMaxArgsAux_false + have hperm : L.toList.Perm L1.toList := qsort_perm L1 + have hpair : List.Pairwise _ L.toList := pairwise_qsort L1 + have hLsize : L.size = L1.size := by + simpa [Array.length_toList] using hperm.length_eq + have hLpos : 0 < L.size := hLsize ▸ hL1pos + have hevalL : evalList ρ μ L.toList = Nat.max (eval ρ μ l₁) (eval ρ μ l₂) := by + rw [evalList_perm hperm, hevalL1] + have hs : ∀ (i j : Nat) (hi : i < L.size) (hj : j < L.size), i < j → + L[i].getLevelOffset = L[j].getLevelOffset → L[i].getOffset ≤ L[j].getOffset := by + intro i j hi hj hij hb + have := (List.pairwise_iff_getElem.1 hpair) i j (by simpa using hi) (by simpa using hj) hij + simpa using this (by simpa using hb) + obtain ⟨-, hskle, hskz⟩ := skipExplicit_spec (lvls := L) (i := 0) (Nat.zero_le _) + -- the start index and its bound + have main i (hi : i < L.size) + (hdom : ∀ j (hj : j < L.size), j < i → eval ρ μ L[j] ≤ evalList ρ μ (L.toList.drop i)) : + eval ρ μ (Total.mkMaxAux L (l.getOffset) (i+1) L[i]!.getLevelOffset L[i]!.getOffset + Level.zero) = Nat.max (eval ρ μ l₁) (eval ρ μ l₂) + l.getOffset := by + rw [getElem!_pos L i hi, + eval_mkMaxAux hs (fuel := L.size) (by omega) (by omega) (by omega) (fun _ => by simp), + Nat.add_sub_cancel, evalList_drop_eq (by rw [Array.length_toList]; omega) hdom, hevalL] + simp [eval, Nat.max_eq_max] + subst i lvl₁ prevK prev; split <;> rename_i hsub + · -- explicits subsumed: start at the first non-explicit + rw [isExplicitSubsumed] at hsub + split at hsub <;> [cases hsub; let (eq := eq) i'+1 := i₀]; subst i₀ + simp only [isExplicitSubsumedAux_eq, isExplicitSubsumedAux_spec] at hsub + obtain ⟨j, hij, hjs, hmax⟩ := hsub; dsimp at hmax + refine main (i'+1) (by omega) fun m hm hmi => ?_ + -- every dropped explicit is at most the witness entry + have hzm : L[m].getLevelOffset.isZero := hskz m hm (Nat.zero_le _) (eq ▸ hmi) + have hz₁ := hskz i' (by omega) (Nat.zero_le _) (by omega) + have h2 : L[m].getOffset ≤ L[i'].getOffset := by + rcases Nat.eq_or_lt_of_le (Nat.le_pred_of_lt hmi) with h | h + · subst h; exact Nat.le_refl _ + · exact hs m i' hm (by omega) h (by rw [isZero_iff.1 hzm, isZero_iff.1 hz₁]) + have h3 : L[i'].getOffset ≤ eval ρ μ L[j] := + Nat.le_trans (getElem!_pos L i' (by omega) ▸ hmax) offset_le_eval + refine eval_of_isZero hzm ▸ Nat.le_trans (Nat.le_trans h2 h3) (le_evalList ?_) + refine List.mem_iff_getElem.2 ⟨j - (i' + 1), ?_, ?_⟩ + · simp only [List.length_drop, Array.length_toList]; omega + · rw [List.getElem_drop]; simp only [Array.getElem_toList]; congr 1; omega + · -- keep the largest explicit + cases eq : i₀ with | zero => exact main 0 (by omega) (fun m hm hmi => by omega) | succ i' + have hstart : i' < L.size := by omega + refine main i' hstart fun m hm hmi => ?_ + have hzm : L[m].getLevelOffset.isZero := hskz m hm (Nat.zero_le _) (by omega) + have hz₁ : L[i'].getLevelOffset.isZero := + hskz i' hstart (Nat.zero_le _) (by omega) + refine eval_of_isZero hzm ▸ Nat.le_trans (hs m i' hm hstart (by omega) ?_) ?_ + · rw [isZero_iff.1 hzm, isZero_iff.1 hz₁] + refine eval_of_isZero hz₁ ▸ le_evalList ?_ + rw [List.drop_eq_getElem_cons (by omega)]; exact .head _ + · -- imax + rw [eval_getLevelOffset (l := l), hbase] + rw [hbase] at hsz; simp only [Total.size] at hsz + have hs₁ := Total.one_le_size l₁ + have hs₂ := Total.one_le_size l₂ + split <;> rename_i hnz + · rw [eval_addOffset, IH (Total.size (mkLevelMax l₁ l₂)) + (by simp only [mkLevelMax, Total.size]; omega) rfl] + have := isNeverZero_sound (ρ := ρ) (μ := μ) hnz + simp only [mkLevelMax, eval, Nat.imax] + rw [if_neg (by omega)] + · rw [eval_addOffset, eval_mkIMaxAux, IH _ (by omega) rfl, IH _ (by omega) rfl]; rfl + · grind [base_of_not_cheap] + +theorem eval_normalize {ρ μ l} : eval ρ μ l.normalize = eval ρ μ l := by + rw [normalize_eq]; exact eval_normalize_total + +theorem geq_eq_core : geq u v = geqCore (normalize u) (normalize v) := by + simp [geq, geqCore_eq_go] + +theorem isEquiv_sound (h : isEquiv u v) : eval ρ μ u = eval ρ μ v := by + simp only [Level.isEquiv, Bool.or_eq_true, beq_iff_eq] at h + rcases h with rfl | h <;> [rfl; skip] + rw [← eval_normalize (l := u), ← eval_normalize (l := v), h] + +theorem geq_sound (h : geq u v) : eval ρ μ v ≤ eval ρ μ u := by + rw [geq_eq_core] at h + rw [← eval_normalize (l := u), ← eval_normalize (l := v)] + exact geqCore_sound h + +theorem eval_ofLevel (h : VLevel.ofLevel Us l = some l') : + l'.eval ns = eval (fun n => ns.getD (Us.idxOf n) 0) μ l := by + induction l generalizing l' with + | zero => simp [VLevel.ofLevel] at h; cases h; rfl + | succ l ih => + simp [VLevel.ofLevel, bind] at h + obtain ⟨l', hl, rfl⟩ := h + simp [VLevel.eval, eval, ih hl] + | max l₁ l₂ ih₁ ih₂ | imax l₁ l₂ ih₁ ih₂ => + simp [VLevel.ofLevel, bind] at h + obtain ⟨l₁', hl₁, l₂', hl₂, rfl⟩ := h + simp only [VLevel.eval, eval, ih₁ hl₁, ih₂ hl₂] + all_goals rfl + | param n => + simp [VLevel.ofLevel] at h + obtain ⟨hidx, rfl⟩ := h + simp [VLevel.eval, eval] + | mvar n => simp [VLevel.ofLevel] at h + +theorem isEquiv_wf (h : isEquiv u v) + (hu : VLevel.ofLevel Us u = some u') (hv : VLevel.ofLevel Us v = some v') : u' ≈ v' := by + refine VLevel.equiv_def.2 fun ns => ?_ + rw [eval_ofLevel (μ := fun _ => 0) hu, eval_ofLevel (μ := fun _ => 0) hv] + exact isEquiv_sound h + +theorem geq_wf (h : geq u v) + (hu : VLevel.ofLevel Us u = some u') (hv : VLevel.ofLevel Us v = some v') : v' ≤ u' := by + intro ns + rw [eval_ofLevel (μ := fun _ => 0) hv, eval_ofLevel (μ := fun _ => 0) hu] + exact geq_sound h + +end Lean.Level diff --git a/Ix/Theory/Named/Verify/LocalContext.lean b/Ix/Theory/Named/Verify/LocalContext.lean new file mode 100644 index 000000000..3abc5fa70 --- /dev/null +++ b/Ix/Theory/Named/Verify/LocalContext.lean @@ -0,0 +1,337 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.PersistentHashMap +import Ix.Theory.Named.Verify.Expr +import Ix.Theory.Named.Verify.Typing.Expr +import Ix.Theory.Named.Verify.Typing.Lemmas + +open Ix.Theory.Named + +namespace Lean.LocalContext + +noncomputable def toList (lctx : LocalContext) : List LocalDecl := + lctx.decls.toList'.reverse.filterMap id + +noncomputable def fvars (lctx : LocalContext) : List FVarId := + lctx.toList.map (·.fvarId) + +def mkBindingList1 (isLambda : Bool) (lctx : LocalContext) + (xs : List FVarId) (x : FVarId) (b : Expr) : Expr := + match lctx.find? x with + | some (.cdecl _ _ n ty bi _) => + let ty := ty.abstractList xs + if isLambda then + .lam n ty b bi + else + .forallE n ty b bi + | some (.ldecl _ _ n ty val nonDep _) => + if b.hasLooseBVar' 0 then + let ty := ty.abstractList xs + let val := val.abstractList xs + .letE n ty val b nonDep + else + b.lowerLooseBVars' 1 1 + | none => panic! "unknown free variable" + +def mkBindingList (isLambda : Bool) (lctx : LocalContext) (xs : List FVarId) (b : Expr) : Expr := + core (b.abstractList xs) +where + core := go xs.reverse + go : List FVarId → Expr → Expr + | [], b => b + | x :: xs, b => go xs (mkBindingList1 isLambda lctx xs.reverse x b) + +theorem mkBinding_eq : + mkBinding isLambda lctx ⟨xs.map .fvar⟩ b = mkBindingList isLambda lctx xs b := by + simp only [mkBinding, List.getElem_toArray, Expr.abstractRange_eq, Expr.hasLooseBVar_eq, + Expr.abstract_eq, ← Array.take_eq_extract, List.take_toArray, Bool.and_false, + ← List.map_take, List.getElem_map, Expr.lowerLooseBVars_eq] + dsimp only [Array.size] + simp only [List.getElem_eq_getElem?_get, Option.get_eq_getD (fallback := default)] + change Nat.foldRev _ (fun i x => + mkBindingList1 isLambda lctx (xs.take i) (xs[i]?.getD default)) .. = mkBindingList.go .. + rw [List.length_map]; generalize eq : xs.length = n + generalize b.abstractList xs = b + induction n generalizing xs b with + | zero => let [] := xs; simp [mkBindingList.go] + | succ n ih => + obtain rfl | ⟨xs, a, rfl⟩ := List.eq_nil_or_concat xs; · cases eq + simp at eq ⊢; subst eq + simp +contextual only [Nat.le_of_lt, List.take_append_of_le_length, + List.getElem?_append_left, mkBindingList.go, ih]; simp + +theorem mkBindingList1_abstract {xs : List FVarId} + (hx : lctx.find? x = some decl) (nd : (a :: xs).Nodup) : + (mkBindingList1 isLambda lctx xs x b).abstract1 a xs.length = + mkBindingList1 isLambda lctx (a :: xs) x (b.abstract1 a (xs.length + 1)) := by + have (e:_) := Nat.zero_add _ ▸ Expr.abstract1_abstractList' (k := 0) (e := e) nd + simp [mkBindingList1, hx]; cases decl with simp + | cdecl _ _ _ ty => split <;> simp [Expr.abstract1, Expr.abstract1, this] + | ldecl => + have := Expr.abstract1_hasLooseBVar a b (xs.length + 1) 0 + simp at this; simp [this]; clear this + split + · simp [Expr.abstract1, Expr.abstract1, this] + · rename_i h; simp at h + rw [Expr.abstract1_lower h (Nat.zero_le _)] + +theorem mkBindingList_core_cons {xs : List FVarId} {b : Expr} + (hx : ∀ x ∈ xs, ∃ decl, lctx.find? x = some decl) (nd : (a :: xs).Nodup) : + mkBindingList.core isLambda lctx (a :: xs) (b.abstract1 a xs.length) = + mkBindingList1 isLambda lctx [] a + ((mkBindingList.core isLambda lctx xs b).abstract1 a) := by + obtain ⟨xs, rfl⟩ : ∃ xs', List.reverse xs' = xs := ⟨_, List.reverse_reverse _⟩ + simp [mkBindingList.core] at * + induction xs generalizing b with + | nil => simp [mkBindingList.go] + | cons c xs ih => + simp at hx nd ih + let ⟨decl, eq⟩ := hx.1 + simp [mkBindingList.go] + rw [← xs.length_reverse, ← mkBindingList1_abstract eq (by simp [*])] + simp [ih hx.2 nd.1.2 nd.2.2] + +@[simp] theorem mkBindingList_nil : mkBindingList isLambda lctx [] b = b := rfl + +theorem mkBindingList_cons + (hx : ∀ x ∈ xs, ∃ decl, lctx.find? x = some decl) (nd : (a :: xs).Nodup) : + mkBindingList isLambda lctx (a :: xs) b = + mkBindingList1 isLambda lctx [] a ((mkBindingList isLambda lctx xs b).abstract1 a) := by + simp [mkBindingList] + rw [← Expr.abstract1_abstractList' nd] + rw [Nat.zero_add, mkBindingList_core_cons hx nd] + +theorem mkBindingList_eq_fold + (hx : ∀ x ∈ xs, ∃ decl, lctx.find? x = some decl) (nd : xs.Nodup) : + mkBindingList isLambda lctx xs b = + xs.foldr (fun a e => mkBindingList1 isLambda lctx [] a (e.abstract1 a)) b := by + induction xs <;> simp_all [mkBindingList_cons] + +theorem mkBindingList1_congr (H : lctx₁.find? x = lctx₂.find? x) : + mkBindingList1 isLambda lctx₁ xs x b = mkBindingList1 isLambda lctx₂ xs x b := by + simp [mkBindingList1, H] + +theorem mkBindingList_congr + (H : ∀ x ∈ xs, lctx₁.find? x = lctx₂.find? x) : + mkBindingList isLambda lctx₁ xs b = mkBindingList isLambda lctx₂ xs b := by + obtain ⟨xs, rfl⟩ : ∃ xs', List.reverse xs' = xs := ⟨_, List.reverse_reverse _⟩ + simp [mkBindingList, mkBindingList.core] at * + generalize b.abstractList _ = b + induction xs generalizing b <;> simp_all [mkBindingList.go] + simp [mkBindingList1_congr H.1] + +inductive WF : LocalContext → Prop + | nil : WF ⟨.empty, .empty, .empty⟩ + | cons : + d.fvarId = fv → map.find? fv = none → d.index = arr.size → + WF ⟨map, arr, fvmap⟩ → + WF ⟨map.insert fv d, arr.push d, fvmap⟩ + +theorem WF.map_wf {lctx : LocalContext} : lctx.WF → lctx.fvarIdToDecl.WF + | .nil => .empty + | .cons _ _ _ h2 => .insert h2.map_wf + +theorem WF.decls_wf {lctx : LocalContext} : lctx.WF → lctx.decls.WF + | .nil => .empty + | .cons _ _ _ h2 => .push h2.decls_wf + +attribute [-simp] List.filterMap_reverse in +open scoped _root_.List in +theorem WF.map_toList : WF lctx → + lctx.fvarIdToDecl.toList' ~ lctx.toList.map fun d => (d.fvarId, d) + | .nil => by simp [LocalContext.toList] + | .cons h1 h2 _ h4 => by + subst h1; simp [LocalContext.toList] + refine h4.map_wf.toList'_insert _ _ |>.trans (.cons _ ?_) + rw [List.filter_eq_self.2]; · exact h4.map_toList + simp; rintro _ b h rfl + have := (h4.map_wf.find?_eq _).symm.trans h2 + simp [List.lookup_eq_none_iff] at this + exact this _ _ h rfl + +theorem WF.find?_eq_find?_toList (H : WF lctx) : + lctx.find? fv = lctx.toList.find? (fv == ·.fvarId) := by + rw [LocalContext.find?, H.map_wf.find?_eq, + H.map_toList.lookup_eq H.map_wf.nodupKeys, List.map_fst_lookup] + +theorem WF.nodup : WF lctx → (lctx.toList.map (·.fvarId)).Nodup + | .nil => .nil + | .cons h1 h2 h3 h4 => by + have := h4.nodup + have := h4.find?_eq_find?_toList.symm.trans h2 + simp_all [toList] + simpa [eq_comm] using this + +protected theorem WF.mkLocalDecl + (h1 : WF lctx) (h2 : lctx.find? fv = none) : WF (lctx.mkLocalDecl fv name ty bi kind) := + .cons rfl h2 rfl h1 + +protected theorem WF.mkLetDecl + (h1 : WF lctx) (h2 : lctx.find? fv = none) : WF (lctx.mkLetDecl fv name ty val bi kind) := + .cons rfl h2 rfl h1 + +@[simp] theorem mkLocalDecl_toList {lctx : LocalContext} : + (lctx.mkLocalDecl fv name ty bi kind).toList = + .cdecl lctx.decls.size fv name ty bi kind :: lctx.toList := by + simp [mkLocalDecl, toList] + +@[simp] theorem mkLetDecl_toList {lctx : LocalContext} : + (lctx.mkLetDecl fv name ty val bi kind).toList = + .ldecl lctx.decls.size fv name ty val bi kind :: lctx.toList := by + simp [mkLetDecl, toList] + +end Lean.LocalContext + +namespace Ix.Theory.Named + +open Lean +open scoped _root_.List + +attribute [-simp] List.filterMap_reverse + +variable (env : VEnv) (Us : List Name) (Δ : VLCtx) in +inductive TrLocalDecl : LocalDecl → VLocalDecl → Prop + | vlam : TrExprS env Us Δ ty ty' → env.IsType Us.length Δ.toCtx ty' → + TrLocalDecl (.cdecl n fv name ty bi kind) (.vlam ty') + | vlet : + TrExprS env Us Δ ty ty' → TrExprS env Us Δ val val' → + env.HasType Us.length Δ.toCtx val' ty' → + TrLocalDecl (.ldecl n fv name ty val bi kind) (.vlet ty' val') + +theorem TrLocalDecl.wf : TrLocalDecl env Us Δ d d' → d'.WF env Us.length Δ.toCtx + | .vlam _ h | .vlet _ _ h => h + +def _root_.Lean.LocalDecl.deps : LocalDecl → List FVarId + | .cdecl (type := t) .. => t.fvarsList + | .ldecl (type := t) (value := v) .. => t.fvarsList ++ v.fvarsList + +theorem TrLocalDecl.deps_wf : TrLocalDecl env Us Δ d d' → d.deps ⊆ Δ.fvars + | .vlam h _ => h.fvarsList + | .vlet h1 h2 _ => by simp [LocalDecl.deps, h1.fvarsList, h2.fvarsList] + +variable (env : VEnv) (Us : List Name) in +inductive TrLCtx' : List LocalDecl → VLCtx → Prop + | nil : TrLCtx' [] [] + | cons : + TrLCtx' ds Δ → TrLocalDecl env Us Δ d d' → + TrLCtx' (d :: ds) ((some (d.fvarId, d.deps), d') :: Δ) + +def TrLCtx (env : VEnv) (Us : List Name) (lctx : LocalContext) (Δ : VLCtx) : Prop := + lctx.WF ∧ TrLCtx' env Us lctx.toList Δ + +theorem TrLCtx.nil {env : VEnv} {Us : List Name} : TrLCtx env Us {} [] := ⟨.nil, .nil⟩ + +theorem TrLCtx'.noBV : TrLCtx' env Us ds Δ → Δ.NoBV + | .nil => rfl + | .cons h _ => h.noBV + +theorem TrLCtx'.forall₂ : + TrLCtx' env Us ds Δ → ds.Forall₂ Δ (R := fun d d' => d'.1 = some (d.fvarId, d.deps)) + | .nil => by simp + | .cons h _ => by simp; exact h.forall₂ + +theorem TrLCtx'.fvars_eq (H : TrLCtx' env Us ds Δ) : ds.map (·.fvarId) = Δ.fvars := by + simp [VLCtx.fvars] + induction H with + | nil => rfl + | cons h1 _ ih => simp [← ih] + +theorem TrLCtx.fvars_eq (H : TrLCtx env Us lctx Δ) : lctx.fvars = Δ.fvars := + H.2.fvars_eq + +theorem TrLCtx'.find?_eq_some (H : TrLCtx' env Us ds Δ) : + (∃ d, ds.find? (fv == ·.fvarId) = some d) ↔ fv ∈ Δ.fvars := by + rw [← Option.isSome_iff_exists, List.find?_isSome] + induction H with simp + | @cons _ _ d d' _ _ ih => simp [← ih] + +theorem TrLCtx'.find?_isSome (H : TrLCtx' env Us ds Δ) : + (ds.find? (fv == ·.fvarId)).isSome = (Δ.find? (.inr fv)).isSome := by + rw [Bool.eq_iff_iff, Option.isSome_iff_exists, Option.isSome_iff_exists, + H.find?_eq_some, VLCtx.find?_eq_some] + +theorem TrLCtx.find?_isSome (H : TrLCtx env Us lctx Δ) : + (lctx.find? fv).isSome = (Δ.find? (.inr fv)).isSome := by + rw [H.1.find?_eq_find?_toList, H.2.find?_isSome] + +theorem TrLCtx.find?_eq_some (H : TrLCtx env Us lctx Δ) : + (∃ d, lctx.find? fv = some d) ↔ fv ∈ Δ.fvars := by + rw [H.1.find?_eq_find?_toList, H.2.find?_eq_some] + +theorem TrLCtx.find?_eq_none (H : TrLCtx env Us lctx Δ) : + lctx.find? fv = none ↔ ¬fv ∈ Δ.fvars := by simp [← H.find?_eq_some] + +theorem TrLCtx.contains (H : TrLCtx env Us lctx Δ) : lctx.contains fv ↔ fv ∈ Δ.fvars := by + rw [LocalContext.contains, PersistentHashMap.find?_isSome, Option.isSome_iff_exists] + exact H.find?_eq_some + +theorem TrLCtx'.wf : TrLCtx' env Us ds Δ → (ds.map (·.fvarId)).Nodup → Δ.WF env Us.length + | .nil, _ => ⟨⟩ + | .cons h1 h2, .cons H1 H2 => by + refine ⟨h1.wf H2, fun _ _ => ?_, h2.wf⟩ + rintro ⟨⟩; exact ⟨by simpa [← h1.find?_eq_some] using H1, h2.deps_wf⟩ + +theorem TrLCtx.wf (H : TrLCtx env Us lctx Δ) : Δ.WF env Us.length := H.2.wf H.1.nodup + +def _root_.Lean.LocalDecl.value' : LocalDecl → Expr + | .ldecl (value := v) .. => v + | .cdecl (fvarId := fv) .. => .fvar fv + +theorem TrLCtx'.find?_of_mem (henv : env.WF) (H : TrLCtx' env Us ds Δ) + (nd : (ds.map (·.fvarId)).Nodup) (hm : decl ∈ ds) : + ∃ e A, Δ.find? (.inr decl.fvarId) = some (e, A) ∧ + FVarsBelow Δ (.fvar decl.fvarId) decl.value' ∧ FVarsBelow Δ (.fvar decl.fvarId) decl.type ∧ + TrExprS env Us Δ decl.value' e ∧ TrExprS env Us Δ decl.type A := by + have := H.wf nd + match H with + | .nil => cases hm + | .cons (ds := ds) h1 h2 => + simp [VLCtx.find?, VLCtx.next] + obtain _ | ⟨_, hm : decl ∈ ds⟩ := hm + · simp [and_assoc] + cases h2 with + | vlam h2 h3 => + refine ⟨.rfl, ?_, .fvar <| by simp [VLCtx.find?, VLCtx.next, LocalDecl.fvarId]; rfl, ?_⟩ + · intro P hP he; exact fvarsIn_iff.2 ⟨hP.2 he, h2.fvarsIn.mono fun _ _ => ⟨⟩⟩ + · exact h2.weakFV henv (.skip_fvar _ _ .refl) this + | vlet h2 h3 => + refine ⟨?_, ?_, ?_, ?_⟩ + · intro P hP he; have := hP.2 he; simp [LocalDecl.deps, or_imp, forall_and] at this + exact fvarsIn_iff.2 ⟨this.2, h3.fvarsIn.mono fun _ _ => ⟨⟩⟩ + · intro P hP he; have := hP.2 he; simp [LocalDecl.deps, or_imp, forall_and] at this + exact fvarsIn_iff.2 ⟨this.1, h2.fvarsIn.mono fun _ _ => ⟨⟩⟩ + · simpa [LocalDecl.value', VLocalDecl.value, VLocalDecl.depth] using + h3.weakFV henv (.skip_fvar _ _ .refl) this + · simpa [LocalDecl.type, VLocalDecl.type, VLocalDecl.depth] using + h2.weakFV henv (.skip_fvar _ _ .refl) this + · simp at nd; rw [if_neg (by simpa using Ne.symm (nd.1 _ hm))]; simp + have ⟨_, _, h1, h2, h3, h4, h5⟩ := h1.find?_of_mem henv nd.2 hm + refine ⟨_, _, ⟨_, _, h1, rfl, rfl⟩, fun _ h => h2 _ h.1, fun _ h => h3 _ h.1, ?_, ?_⟩ + · simpa using h4.weakFV henv (.skip_fvar _ _ .refl) this + · simpa using h5.weakFV henv (.skip_fvar _ _ .refl) this + +theorem TrLCtx.find?_of_mem (henv : env.WF) (H : TrLCtx env Us lctx Δ) + (hm : decl ∈ lctx.toList) : + ∃ e A, Δ.find? (.inr decl.fvarId) = some (e, A) ∧ + FVarsBelow Δ (.fvar decl.fvarId) decl.value' ∧ FVarsBelow Δ (.fvar decl.fvarId) decl.type ∧ + TrExprS env Us Δ decl.value' e ∧ TrExprS env Us Δ decl.type A := + H.2.find?_of_mem henv H.1.nodup hm + +theorem TrLCtx.mkLocalDecl + (h1 : TrLCtx env Us lctx Δ) (h2 : lctx.find? fv = none) (h3 : TrExprS env Us Δ ty ty') + (h4 : env.IsType Us.length Δ.toCtx ty') : + TrLCtx env Us (lctx.mkLocalDecl fv name ty bi kind) + ((some (fv, ty.fvarsList), .vlam ty') :: Δ) := + ⟨h1.1.mkLocalDecl h2, by simpa using .cons h1.2 (.vlam h3 h4)⟩ + +theorem TrLCtx.mkLetDecl + (h1 : TrLCtx env Us lctx Δ) (h2 : lctx.find? fv = none) + (h3 : TrExprS env Us Δ ty ty') (h4 : TrExprS env Us Δ val val') + (h5 : env.HasType Us.length Δ.toCtx val' ty') : + TrLCtx env Us (lctx.mkLetDecl fv name ty val bi kind) + ((some (fv, ty.fvarsList ++ val.fvarsList), .vlet ty' val') :: Δ) := + ⟨h1.1.mkLetDecl h2, by simpa using .cons h1.2 (.vlet h3 h4 h5)⟩ diff --git a/Ix/Theory/Named/Verify/Name.lean b/Ix/Theory/Named/Verify/Name.lean new file mode 100644 index 000000000..650926aa9 --- /dev/null +++ b/Ix/Theory/Named/Verify/Name.lean @@ -0,0 +1,96 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Data.NameMap.Basic +import Ix.Theory.Named.Std.Ord +import Std.Data.TreeSet.Lemmas + +/-! +Order properties of `Lean.Name.cmp` and `Lean.Name.quickCmp`. +-/ + +namespace Lean + +namespace Name +open _root_.Std Ix.Theory.Named + +theorem cmp_eq_swap {a b : Name} : a.cmp b = (b.cmp a).swap := by + induction a generalizing b with obtain _|⟨b₁,b₂⟩|⟨b₁,b₂⟩ := b <;> simp [cmp] + | str a₁ a₂ ih | num a₁ a₂ ih => + rw [ih]; cases b₁.cmp a₁ <;> simp [← OrientedOrd.eq_swap] + +instance : TransCmp cmp := by + refine TransCmp.of_rot (fun _ _ => cmp_eq_swap) fun a b c => ?_ + induction a generalizing b c with + | anonymous => + obtain _|⟨b₁,b₂⟩|⟨b₁,b₂⟩ := b <;> obtain _|⟨c₁,c₂⟩|⟨c₁,c₂⟩ := c <;> simp [cmp, Rot] + | str a₁ a₂ ih | num a₁ a₂ ih => + obtain _|⟨b₁,b₂⟩|⟨b₁,b₂⟩ := b <;> obtain _|⟨c₁,c₂⟩|⟨c₁,c₂⟩ := c <;> + first + | exact (ih ..).then (Rot.of_transCmp ..) + | simp [cmp, Rot] + +instance : LawfulBEqCmp cmp where + compare_eq_iff_beq {a b} := by + simp; refine ⟨?_, fun h => h ▸ ReflCmp.compare_self⟩ + induction a generalizing b with obtain _|⟨b₁,b₂⟩|⟨b₁,b₂⟩ := b <;> simp [cmp] + | str a₁ a₂ ih | num a₁ a₂ ih => + refine ?_ ∘ Ordering.then_eq_eq.1 + simp +contextual; exact fun h _ => ih h + +instance : TransCmp quickCmp where + eq_swap {a b} := by + simp [quickCmp] + rw [OrientedOrd.eq_swap] + cases compare b.hash a.hash <;> simp + induction a generalizing b with obtain _|⟨b₁,b₂⟩|⟨b₁,b₂⟩ := b <;> simp [quickCmpAux] + | str a₁ a₂ ih | num a₁ a₂ ih => + rw [OrientedOrd.eq_swap] + cases compare b₂ a₂ <;> simp [ih] + isLE_trans {a b c} := by + have {α} [Ord α] [TransOrd α] {a₁ b₁ c₁ : α} {a₂ b₂ c₂} + (H : (quickCmpAux a₂ b₂).isLE → (quickCmpAux b₂ c₂).isLE → (quickCmpAux a₂ c₂).isLE) : + ((compare a₁ b₁).then (quickCmpAux a₂ b₂)).isLE → + ((compare b₁ c₁).then (quickCmpAux b₂ c₂)).isLE → + ((compare a₁ c₁).then (quickCmpAux a₂ c₂)).isLE := by + simp [Ordering.isLE_then_iff_and] + intro h1 h2 h3 h4 + refine ⟨TransCmp.isLE_trans h1 h3, ?_⟩ + refine h2.elim (fun h2 => .inl <| TransCmp.lt_of_lt_of_isLE h2 h3) fun h2 => ?_ + refine h4.elim (fun h4 => .inl <| TransCmp.lt_of_isLE_of_lt h1 h4) fun h4 => .inr (H h2 h4) + apply this + induction a generalizing b c with + obtain _|⟨b₁,b₂⟩|⟨b₁,b₂⟩ := b <;> simp [quickCmpAux] at * <;> + obtain _|⟨c₁,c₂⟩|⟨c₁,c₂⟩ := c <;> simp [quickCmpAux] at * + | str a₁ a₂ ih | num a₁ a₂ ih => apply this ih + +instance : LawfulBEqCmp quickCmp where + compare_eq_iff_beq {a b} := by + simp; refine ⟨fun h => ?_, fun h => h ▸ ReflCmp.compare_self⟩ + replace h := (Ordering.then_eq_eq.1 h).2; revert h + induction a generalizing b with obtain _|⟨b₁,b₂⟩|⟨b₁,b₂⟩ := b <;> simp [quickCmpAux] + | str a₁ a₂ ih | num a₁ a₂ ih => + refine ?_ ∘ Ordering.then_eq_eq.1 + simp +contextual; exact fun _ => ih + +end Name + +namespace NameSet +open _root_.Std + +theorem contains_insert {s : NameSet} {a b : Name} : + (s.insert a).contains b = (a == b || s.contains b) := by + have key : (Name.quickCmp a b == Ordering.eq) = (a == b) := by + have := @LawfulBEqCmp.compare_eq_iff_beq _ _ Name.quickCmp _ a b + cases h : Name.quickCmp a b <;> simp_all + have h : (s.insert a).contains b + = (Name.quickCmp a b == Ordering.eq || s.contains b) := + Std.TreeSet.contains_insert (t := s) (k := a) (a := b) + rw [h, key] + +@[simp] theorem contains_empty {a : Name} : (∅ : NameSet).contains a = false := rfl + +end NameSet diff --git a/Ix/Theory/Named/Verify/NameGenerator.lean b/Ix/Theory/Named/Verify/NameGenerator.lean new file mode 100644 index 000000000..5e96e8e48 --- /dev/null +++ b/Ix/Theory/Named/Verify/NameGenerator.lean @@ -0,0 +1,34 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Reference.Expr +import Ix.Theory.Named.VExpr + +namespace Lean.NameGenerator + +def Reserves (ngen : NameGenerator) (fv : FVarId) : Prop := + ∀ i, fv = ⟨.num ngen.namePrefix i⟩ → i < ngen.idx + +theorem next_reserves_self {ngen : NameGenerator} : + ngen.next.Reserves ⟨ngen.curr⟩ := by rintro _ ⟨⟩; exact Nat.lt_succ_self _ + +theorem not_reserves_self {ngen : NameGenerator} : + ¬ngen.Reserves ⟨ngen.curr⟩ := fun h => Nat.lt_irrefl _ (h _ rfl) + +protected inductive LE : NameGenerator → NameGenerator → Prop where + | le : i ≤ j → NameGenerator.LE ⟨pfx, i⟩ ⟨pfx, j⟩ + +instance : LE NameGenerator := ⟨NameGenerator.LE⟩ + +theorem LE.rfl {ngen : NameGenerator} : ngen ≤ ngen := ⟨Nat.le_refl _⟩ + +theorem LE.trans {ngen₁ ngen₂ ngen₃ : NameGenerator} : ngen₁ ≤ ngen₂ → ngen₂ ≤ ngen₃ → ngen₁ ≤ ngen₃ + | ⟨h₁⟩, ⟨h₂⟩ => ⟨Nat.le_trans h₁ h₂⟩ + +theorem Reserves.mono : ngen ≤ ngen' → Reserves ngen fv → Reserves ngen' fv + | ⟨h₁⟩ => fun H _ hi => Nat.lt_of_lt_of_le (H _ hi) h₁ + +theorem LE.next {ngen : NameGenerator} : ngen ≤ ngen.next := ⟨Nat.le_succ _⟩ diff --git a/Ix/Theory/Named/Verify/NormLt.lean b/Ix/Theory/Named/Verify/NormLt.lean new file mode 100644 index 000000000..dd097405a --- /dev/null +++ b/Ix/Theory/Named/Verify/NormLt.lean @@ -0,0 +1,370 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Lean.Level +import Ix.Theory.Named.Verify.Name +import Ix.Theory.Named.Std.Ord +import Ix.Theory.Named.Verify.Axioms + +/-! +`Lean.Level.normLt` is the order used to sort the arguments of a `max` in +`Lean.Level.normalize`. This file shows it is a strict weak order, which is what the +`Array.qsort` specification requires. + +The proof identifies `normLt` with an `Ordering`-valued comparison `normCmp`, which compares +levels by (base, offset) lexicographically, bases being compared structurally. `normCmp` is +then given the `Std` order instances (`ReflCmp`, `TransCmp`, `LawfulEqCmp`), from which the +strict weak order properties `normLt` needs follow. Transitivity uses `Ix.Theory.Named.Rot`, the +lexicographic-product device shared with `Name.cmp` in `Ix.Theory.Named.Verify.Name`. +-/ + +open Std Ix.Theory.Named + +namespace Lean.Level + +instance : LawfulBEq LMVarId where + eq_of_beq := @fun ⟨a⟩ ⟨b⟩ h => by cases LawfulBEq.eq_of_beq (α := Name) h; rfl + rfl := BEq.rfl (α := Name) + +/-- The structural size of a level. -/ +private def size : Level → Nat + | .zero | .param _ | .mvar _ => 1 + | .succ l => size l + 1 + | .max a b | .imax a b => size a + size b + 1 + +private theorem size_max {a b : Level} : size (.max a b) = size a + size b + 1 := rfl +private theorem size_imax {a b : Level} : size (.imax a b) = size a + size b + 1 := rfl + +private theorem one_le_size : ∀ l : Level, 1 ≤ size l + | .zero | .param _ | .mvar _ => Nat.le_refl _ + | .succ l => Nat.le_succ_of_le (one_le_size l) + | .max a b | .imax a b => by have := one_le_size a; simp only [size]; omega + +private theorem size_getLevelOffset_le : ∀ l : Level, size l.getLevelOffset ≤ size l + | .succ l => Nat.le_trans (size_getLevelOffset_le l) (Nat.le_succ _) + | .zero | .param _ | .mvar _ | .max .. | .imax .. => Nat.le_refl _ + +/-- Structural comparison of level *bases* (levels that are not `succ`s). +Sub-levels are compared by `normCmp`, i.e. base first, then offset. -/ +def baseCmp : Level → Level → Ordering + | .max a b, .max c d => + ((baseCmp a.getLevelOffset c.getLevelOffset).then (compare a.getOffset c.getOffset)).then + ((baseCmp b.getLevelOffset d.getLevelOffset).then (compare b.getOffset d.getOffset)) + | .imax a b, .imax c d => + ((baseCmp a.getLevelOffset c.getLevelOffset).then (compare a.getOffset c.getOffset)).then + ((baseCmp b.getLevelOffset d.getLevelOffset).then (compare b.getOffset d.getOffset)) + | .param n₁, .param n₂ => Name.cmp n₁ n₂ + | .mvar n₁, .mvar n₂ => Name.cmp n₁.name n₂.name + | l₁, l₂ => compare l₁.ctorToNat l₂.ctorToNat +termination_by l₁ l₂ => size l₁ + size l₂ +decreasing_by + all_goals + first + | (exact Nat.lt_of_le_of_lt + (Nat.add_le_add (size_getLevelOffset_le _) (size_getLevelOffset_le _)) + (by simp only [size]; omega)) + +/-- Comparison of levels: base first, then offset. -/ +def normCmp (l₁ l₂ : Level) : Ordering := + (baseCmp l₁.getLevelOffset l₂.getLevelOffset).then (compare l₁.getOffset l₂.getOffset) + +/-- The same-constructor part of `baseCmp`. It is `.eq` when the constructors differ, in which +case the `ctorToNat` comparison of `baseCmp_eq` already decides the comparison. -/ +private def structCmp : Level → Level → Ordering + | .max a b, .max c d => (normCmp a c).then (normCmp b d) + | .imax a b, .imax c d => (normCmp a c).then (normCmp b d) + | .param n₁, .param n₂ => Name.cmp n₁ n₂ + | .mvar n₁, .mvar n₂ => Name.cmp n₁.name n₂.name + | _, _ => .eq + +/-- `baseCmp` is the lexicographic product of the constructor tags with `structCmp`. -/ +private theorem baseCmp_eq : ∀ l₁ l₂ : Level, + baseCmp l₁ l₂ = (compare l₁.ctorToNat l₂.ctorToNat).then (structCmp l₁ l₂) := by + intro l₁ l₂ + cases l₁ <;> cases l₂ <;> simp [baseCmp, structCmp, normCmp, ctorToNat] + +private theorem baseCmp_swap : ∀ l₁ l₂ : Level, baseCmp l₂ l₁ = (baseCmp l₁ l₂).swap := by + intro l₁ l₂ + induction l₁, l₂ using baseCmp.induct with + | case1 a b c d ih₁ ih₂ | case2 a b c d ih₁ ih₂ => + rw [baseCmp, baseCmp] + simp only [Ordering.swap_then] + rw [← ih₁, ← ih₂, + ← OrientedCmp.eq_swap (cmp := compare (α := Nat)) (a := c.getOffset) (b := a.getOffset), + ← OrientedCmp.eq_swap (cmp := compare (α := Nat)) (a := d.getOffset) (b := b.getOffset)] + | case3 n₁ n₂ | case4 n₁ n₂ => + rw [baseCmp, baseCmp]; exact OrientedCmp.eq_swap + | case5 l₁ l₂ h₁ h₂ h₃ h₄ => + rw [baseCmp, baseCmp] + · exact OrientedCmp.eq_swap + all_goals grind + +theorem normCmp_swap (l₁ l₂ : Level) : normCmp l₂ l₁ = (normCmp l₁ l₂).swap := by + rw [normCmp, normCmp, Ordering.swap_then, ← baseCmp_swap, + ← OrientedCmp.eq_swap (cmp := compare (α := Nat))] + +private theorem normCmp_rot_of {a b c : Level} + (h : Rot (baseCmp a.getLevelOffset b.getLevelOffset) + (baseCmp b.getLevelOffset c.getLevelOffset) (baseCmp a.getLevelOffset c.getLevelOffset)) : + Rot (normCmp a b) (normCmp b c) (normCmp a c) := + h.then (Rot.of_transCmp a.getOffset b.getOffset c.getOffset) + +private theorem baseCmp_rot : ∀ l₁ l₂ l₃ : Level, + Rot (baseCmp l₁ l₂) (baseCmp l₂ l₃) (baseCmp l₁ l₃) := by + suffices key : ∀ n l₁ l₂ l₃, size l₁ + size l₂ + size l₃ ≤ n → + Rot (baseCmp l₁ l₂) (baseCmp l₂ l₃) (baseCmp l₁ l₃) from + fun l₁ l₂ l₃ => key _ l₁ l₂ l₃ (Nat.le_refl _) + intro n + induction n with + | zero => + intro l₁ l₂ l₃ h + have := one_le_size l₁; have := one_le_size l₂; have := one_le_size l₃ + omega + | succ n ih => + intro l₁ l₂ l₃ hn + rw [baseCmp_eq, baseCmp_eq, baseCmp_eq] + refine (Rot.of_transCmp ..).then' fun e₁ e₂ e₃ => ?_ + -- the sub-level comparisons are on strictly smaller levels + have small : ∀ x y z : Level, size x + size y + size z < size l₁ + size l₂ + size l₃ → + Rot (normCmp x y) (normCmp y z) (normCmp x z) := by + intro x y z hxyz + refine normCmp_rot_of (ih _ _ _ ?_) + have := size_getLevelOffset_le x + have := size_getLevelOffset_le y + have := size_getLevelOffset_le z + omega + -- all three constructor tags agree, so all three levels share a constructor + have hc₁ : l₁.ctorToNat = l₂.ctorToNat := Nat.compare_eq_eq.1 e₁ + have hc₂ : l₂.ctorToNat = l₃.ctorToNat := Nat.compare_eq_eq.1 e₂ + clear e₁ e₂ e₃ hn + cases l₁ <;> cases l₂ <;> cases hc₁ <;> cases l₃ <;> cases hc₂ <;> simp only [structCmp] + · exact ⟨fun _ _ => rfl, fun _ _ => rfl, fun _ _ => rfl⟩ + · exact ⟨fun _ _ => rfl, fun _ _ => rfl, fun _ _ => rfl⟩ + · refine Rot.then (small _ _ _ ?_) (small _ _ _ ?_) <;> (simp only [size_max]; omega) + · refine Rot.then (small _ _ _ ?_) (small _ _ _ ?_) <;> (simp only [size_imax]; omega) + · exact Rot.of_transCmp .. + · exact Rot.of_transCmp .. + +theorem normCmp_rot (a b c : Level) : Rot (normCmp a b) (normCmp b c) (normCmp a c) := + normCmp_rot_of (baseCmp_rot ..) + +instance : TransCmp baseCmp := TransCmp.of_rot (fun a b => baseCmp_swap b a) baseCmp_rot +instance : TransCmp normCmp := TransCmp.of_rot (fun a b => normCmp_swap b a) normCmp_rot + +private theorem getOffsetAux_eq : ∀ (l : Level) (k), l.getOffsetAux k = l.getOffset + k := by + intro l + induction l with + | succ l ih => + intro k + show l.getOffsetAux (k+1) = l.getOffsetAux 1 + k + rw [ih (k+1), ih 1]; omega + | _ => intro k; simp [getOffsetAux, getOffset] + +private theorem getOffset_succ {l : Level} : (Level.succ l).getOffset = l.getOffset + 1 := by + show l.getOffsetAux 1 = _ + rw [getOffsetAux_eq] + +private theorem getLevelOffset_succ {l : Level} : + (Level.succ l).getLevelOffset = l.getLevelOffset := rfl + +/-! ### Reflexivity and antisymmetry -/ + +private theorem baseCmp_refl : ∀ l : Level, baseCmp l l = .eq := by + suffices key : ∀ n l, size l ≤ n → baseCmp l l = .eq from fun l => key _ l (Nat.le_refl _) + intro n + induction n with + | zero => intro l h; have := one_le_size l; omega + | succ n ih => + intro l hn + have hnorm x (hx : size x ≤ n) : normCmp x x = .eq := by + rw [normCmp, ih _ (Nat.le_trans (size_getLevelOffset_le x) hx), Nat.compare_eq_eq.2 rfl]; rfl + rw [baseCmp_eq, Nat.compare_eq_eq.2 rfl] + show structCmp l l = .eq + cases l with simp only [structCmp] + | max a b | imax a b => + rw [hnorm a, hnorm b]; rfl + all_goals simp only [size] at hn ⊢; omega + | _ => exact LawfulBEqCmp.compare_eq_iff_beq.2 (beq_self_eq_true _) + +theorem normCmp_refl (l : Level) : normCmp l l = .eq := by + rw [normCmp, baseCmp_refl, Nat.compare_eq_eq.2 rfl]; rfl + +instance : ReflCmp baseCmp where compare_self := baseCmp_refl _ +instance : ReflCmp normCmp where compare_self := normCmp_refl _ + +/-- A level is determined by its base and its offset. -/ +private theorem level_ext : ∀ {l₁ l₂ : Level}, l₁.getLevelOffset = l₂.getLevelOffset → + l₁.getOffset = l₂.getOffset → l₁ = l₂ := by + intro l₁ + induction l₁ with + | succ a ih => + intro l₂ + cases l₂ with + | succ b => + intro h₁ h₂ + rw [getLevelOffset_succ, getLevelOffset_succ] at h₁ + rw [getOffset_succ, getOffset_succ] at h₂ + exact congrArg Level.succ (ih h₁ (by omega)) + | _ => intro h₁ h₂; rw [getOffset_succ] at h₂; simp [getOffset, getOffsetAux] at h₂ + | _ => + intro l₂ + cases l₂ with + | succ b => intro h₁ h₂; rw [getOffset_succ] at h₂; simp [getOffset, getOffsetAux] at h₂ + | _ => intro h₁ h₂; exact h₁ + +private theorem getLevelOffset_ne_succ : ∀ (l a : Level), l.getLevelOffset ≠ .succ a := by + intro l + induction l with + | succ b ih => exact ih + | _ => intro a h; cases h + +theorem eq_of_normCmp_eq : ∀ {l₁ l₂ : Level}, normCmp l₁ l₂ = .eq → l₁ = l₂ := by + suffices key : ∀ n (l₁ l₂ : Level), size l₁ + size l₂ ≤ n → normCmp l₁ l₂ = .eq → l₁ = l₂ from + fun {l₁ l₂} h => key _ l₁ l₂ (Nat.le_refl _) h + intro n + induction n with + | zero => intro l₁ l₂ h; have := one_le_size l₁; have := one_le_size l₂; omega + | succ n ih => + intro l₁ l₂ hn h + rw [normCmp, baseCmp_eq] at h + obtain ⟨h₁, hoff⟩ := Ordering.then_eq_eq.1 h + obtain ⟨hc, hs⟩ := Ordering.then_eq_eq.1 h₁ + refine level_ext ?_ (Nat.compare_eq_eq.1 hoff) + have hb₁ := size_getLevelOffset_le l₁ + have hb₂ := size_getLevelOffset_le l₂ + have hns₁ := getLevelOffset_ne_succ l₁ + have hns₂ := getLevelOffset_ne_succ l₂ + clear h h₁ hoff + generalize l₁.getLevelOffset = b₁ at * + generalize l₂.getLevelOffset = b₂ at * + replace hc := Nat.compare_eq_eq.1 hc + cases b₁ <;> cases b₂ <;> try simp only [ctorToNat, Nat.reduceEqDiff] at hc + · rfl + · exact absurd rfl (hns₁ _) + · obtain ⟨e₁, e₂⟩ := Ordering.then_eq_eq.1 hs + rw [ih _ _ _ e₁, ih _ _ _ e₂] <;> (simp only [size_max] at hb₁ hb₂ ⊢; omega) + · obtain ⟨e₁, e₂⟩ := Ordering.then_eq_eq.1 hs + rw [ih _ _ _ e₁, ih _ _ _ e₂] <;> (simp only [size_imax] at hb₁ hb₂ ⊢; omega) + · simp only [structCmp] at hs + rw [eq_of_beq (LawfulBEqCmp.compare_eq_iff_beq.1 hs)] + · rename_i x y + have : x.name = y.name := eq_of_beq (LawfulBEqCmp.compare_eq_iff_beq.1 hs) + cases x; cases y; simp_all + +instance : LawfulEqCmp normCmp where eq_of_compare := eq_of_normCmp_eq + +/-! ### `normLt` in terms of `normCmp` -/ + +private theorem compare_beq_lt (a b : Nat) : (compare a b == Ordering.lt) = decide (a < b) := by + apply Bool.eq_iff_iff.2; simp [Nat.compare_eq_lt] + +private theorem base_max {a b : Level} : (Level.max a b).getLevelOffset = .max a b := rfl +private theorem base_imax {a b : Level} : (Level.imax a b).getLevelOffset = .imax a b := rfl +private theorem off_max {a b : Level} : (Level.max a b).getOffset = 0 := rfl +private theorem off_imax {a b : Level} : (Level.imax a b).getOffset = 0 := rfl + +/-- `normLtAux` accumulates the `succ`s into the offsets and then runs `normCmp`. -/ +private theorem normLtAux_eq : ∀ (l₁ : Level) (k₁ : Nat) (l₂ : Level) (k₂ : Nat), + normLtAux l₁ k₁ l₂ k₂ = + ((baseCmp l₁.getLevelOffset l₂.getLevelOffset).then + (compare (l₁.getOffset + k₁) (l₂.getOffset + k₂)) == .lt) := by + intro l₁ k₁ l₂ k₂ + induction l₁, k₁, l₂, k₂ using normLtAux.induct with + | case1 l₁ k₁ l₂ k₂ ih => + rw [normLtAux, ih] + simp only [getLevelOffset_succ, getOffset_succ] + rw [show l₁.getOffset + 1 + k₁ = l₁.getOffset + (k₁ + 1) by omega] + | case2 l₁ k₁ l₂ k₂ hns ih => + rw [normLtAux, ih] + simp only [getLevelOffset_succ, getOffset_succ] + rw [show l₂.getOffset + 1 + k₂ = l₂.getOffset + (k₂ + 1) by omega] + exact hns + | case3 a b k₁ c d k₂ hbeq | case6 a b k₁ c d k₂ hbeq => + -- the two levels are syntactically equal: the offsets decide + rw [normLtAux, if_pos hbeq, Bool.eq_iff_iff] + cases eq_of_beq hbeq + show _ ↔ ((baseCmp _ _).then (compare (0 + k₁) (0 + k₂)) == _) + rw [baseCmp_refl] + simp only [decide_eq_true_eq, Ordering.then, Nat.zero_add, beq_iff_eq, Nat.compare_eq_lt] + | case4 a b k₁ c d k₂ hbeq hne ih | case7 a b k₁ c d k₂ hbeq hne ih => + -- the heads differ, so the head comparison decides + rw [normLtAux, if_neg (by simpa using hbeq), if_pos hne, ih] + have hne' : a ≠ c := by simpa using hne + have hac : normCmp a c ≠ .eq := fun h => hne' (eq_of_normCmp_eq h) + simp only [base_max, base_imax, off_max, off_imax, Nat.add_zero, Nat.zero_add] + rw [baseCmp] + show ((normCmp a c) == _) = (((normCmp a c).then (normCmp b d)).then (compare k₁ k₂) == _) + cases h : normCmp a c <;> simp_all [Ordering.then] + | case5 a b k₁ c d k₂ hbeq hne ih | case8 a b k₁ c d k₂ hbeq hne ih => + -- the heads agree, so the tail comparison decides + rw [normLtAux, if_neg (by simpa using hbeq), if_neg hne, ih] + have hac : a = c := by simpa using hne + subst hac + have hne' : b ≠ d := by rintro rfl; exact absurd (by simp) hbeq + have hbd : normCmp b d ≠ .eq := fun h => hne' (eq_of_normCmp_eq h) + simp only [base_max, base_imax, off_max, off_imax, Nat.add_zero, Nat.zero_add] + rw [baseCmp] + show ((normCmp b d) == _) = (((normCmp a a).then (normCmp b d)).then (compare k₁ k₂) == _) + rw [normCmp_refl] + cases h : normCmp b d <;> simp_all [Ordering.then] + | case9 n₁ k₁ n₂ k₂ hbeq => + rw [normLtAux, if_pos hbeq, Bool.eq_iff_iff] + cases eq_of_beq hbeq + show _ ↔ ((baseCmp (Level.param n₁) (Level.param n₁)).then (compare (0 + k₁) (0 + k₂)) == _) + rw [baseCmp_refl] + simp only [decide_eq_true_eq, Ordering.then, Nat.zero_add, beq_iff_eq, Nat.compare_eq_lt] + | case11 n₁ k₁ n₂ k₂ hbeq => + rw [normLtAux, if_pos hbeq, Bool.eq_iff_iff] + cases eq_of_beq hbeq + show _ ↔ ((baseCmp (Level.mvar n₁) (Level.mvar n₁)).then (compare (0 + k₁) (0 + k₂)) == _) + rw [baseCmp_refl] + simp only [decide_eq_true_eq, Ordering.then, Nat.zero_add, beq_iff_eq, Nat.compare_eq_lt] + | case10 n₁ k₁ n₂ k₂ hbeq => + rw [normLtAux, if_neg hbeq] + show _ = ((baseCmp (Level.param n₁) (Level.param n₂)).then + (compare (0 + k₁) (0 + k₂)) == _) + rw [baseCmp] + have : Name.cmp n₁ n₂ ≠ .eq := fun h => + hbeq (LawfulBEqCmp.compare_eq_iff_beq.1 h) + cases h : Name.cmp n₁ n₂ <;> simp_all [Name.lt, Ordering.then] + | case12 n₁ k₁ n₂ k₂ hbeq => + rw [normLtAux, if_neg hbeq] + show _ = ((baseCmp (Level.mvar n₁) (Level.mvar n₂)).then + (compare (0 + k₁) (0 + k₂)) == _) + rw [baseCmp] + have : Name.cmp n₁.name n₂.name ≠ .eq := fun h => hbeq (by + have := eq_of_beq (LawfulBEqCmp.compare_eq_iff_beq.1 h) + cases n₁; cases n₂; simp_all) + cases h : Name.cmp n₁.name n₂.name <;> simp_all [Name.lt, Ordering.then] + | case13 l₁ k₁ l₂ k₂ hs₁ hs₂ hmax himax hpar hmvar hbeq + | case14 l₁ k₁ l₂ k₂ hs₁ hs₂ hmax himax hpar hmvar hbeq => + -- neither level is a `succ` and their constructors differ, so the tags decide + rw [normLtAux, baseCmp_eq] + · cases l₁ <;> cases l₂ <;> + simp_all [structCmp, ctorToNat, Ordering.then, compare_beq_lt, getLevelOffset, getOffset, + getOffsetAux] <;> grind + all_goals assumption + +theorem normLt_eq (l₁ l₂ : Level) : normLt l₁ l₂ = (normCmp l₁ l₂ == .lt) := by + rw [normLt, normLtAux_eq, normCmp, Nat.add_zero, Nat.add_zero] + +/-! ### `normLt` is a strict weak order -/ + +theorem normLt_asymm {a b : Level} (h : normLt a b) : ¬normLt b a := by + simp only [normLt_eq, beq_iff_eq] at h ⊢ + exact OrientedCmp.not_lt_of_lt h + +theorem normLt_le_trans {a b c : Level} (h₁ : ¬normLt b a) (h₂ : ¬normLt c b) : ¬normLt c a := by + simp only [normLt_eq, beq_iff_eq, ← Ordering.isGE_iff_ne_lt] at h₁ h₂ ⊢ + exact TransCmp.isGE_trans h₂ h₁ + +/-- On levels with equal bases, `normLt` compares the offsets. -/ +theorem normLt_same_base {l₁ l₂ : Level} (h : l₁.getLevelOffset = l₂.getLevelOffset) : + normLt l₁ l₂ = decide (l₁.getOffset < l₂.getOffset) := by + rw [normLt_eq, normCmp, h, baseCmp_refl] + simp only [Ordering.then, compare_beq_lt] + +end Lean.Level diff --git a/Ix/Theory/Named/Verify/QSort.lean b/Ix/Theory/Named/Verify/QSort.lean new file mode 100644 index 000000000..18dfdbb3f --- /dev/null +++ b/Ix/Theory/Named/Verify/QSort.lean @@ -0,0 +1,398 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kim Morrison +-/ +module +public import Init.Data.Array.Basic +import all Init.Data.Array.QSort.Basic + +/-! +# Verification of `Array.qsort` + +Adapted from the verification in leanprover/lean4#14658 +(tests/elab/grind_qsort.lean on the `qsort_verification` branch). + +This file contains a verification of the `Array.qsort` function, +using the `grind` tactic. + +The theorems are: +* `size_qsort : (qsort as lt lo hi).size = as.size` +* `qsort_perm : qsort as lt lo hi ~ as` + +And when `lt` is antisymmetric and `¬ lt a b` is transitive, we have: +* `qsort_sorted' : lo ≤ i < j ≤ hi → ¬ lt (as.qsort lt lo hi)[j] (as.qsort lt lo hi)[i]` +* `qsort_sorted : i < j → ¬ lt (as.qsort lt)[j] (as.qsort lt)[i]` + +(There is not currently a public theorem that `(qsort as lt lo hi)[i] = as[i]` when `i < lo` or `hi < i`.) + +-/ +namespace Array + +open List Vector + +-- These attributes still need to be moved to the standard library. + +-- set_option trace.grind.ematch.pattern true in +-- attribute [grind] Vector.getElem?_eq_getElem -- This one requires some consideration! -- Probably not need, see Vector.Perm.extract' below. + +-- Hmm, we don't seem to have the Array analogues of these! +attribute [grind =] Vector.toArray_perm_iff +attribute [grind =] Vector.perm_toArray_iff + +attribute [grind .] Vector.swap_perm + +attribute [grind .] List.Perm.refl +attribute [grind .] Array.Perm.refl +attribute [grind .] Vector.Perm.refl + +-- attribute [grind] Array.Perm.extract +-- attribute [grind] Vector.Perm.extract + +-- These are just the patterns resulting from `grind`, but the behaviour should be explained! +grind_pattern List.Perm.trans => l₁ ~ l₂, l₁ ~ l₃ +grind_pattern Array.Perm.trans => xs ~ ys, xs ~ zs +grind_pattern Vector.Perm.trans => xs ~ ys, xs ~ zs + +/-- Variant of `List.Perm.take` specifying the permutation is constant after `i` elementwise. -/ +theorem _root_.List.Perm.take_of_getElem {l₁ l₂ : List α} (h : l₁ ~ l₂) {i : Nat} + (w : ∀ j, i ≤ j → (_ : j < l₁.length) → l₁[j] = l₂[j]'(by have := h.length_eq; omega)) : + l₁.take i ~ l₂.take i := by + apply h.take_of_getElem? + intro j hij + by_cases h_length₁ : j < l₁.length + <;> have h_length₂ := h.length_eq ▸ h_length₁ + <;> grind + +/-- Variant of `List.Perm.drop` specifying the permutation is constant before `i` elementwise. -/ +theorem _root_.List.Perm.drop_of_getElem {l₁ l₂ : List α} (h : l₁ ~ l₂) {i : Nat} + (w : ∀ j, j < i → (_ : j < l₁.length) → l₁[j] = l₂[j]'(by have := h.length_eq; omega)) : + l₁.drop i ~ l₂.drop i := by + apply h.drop_of_getElem? + intro j hij + by_cases h_length₁ : j < l₁.length + <;> have h_length₂ := h.length_eq ▸ h_length₁ + <;> grind + +private theorem getElem_mk {l : List α} {i : Nat} (h : i < l.length) : + (Array.mk l)[i]'(by simpa using h) = l[i] := by + rw [← Array.getElem_toList] + +theorem _root_.Array.Perm.extract' {xs ys : Array α} (h : xs ~ ys) {lo hi : Nat} + (wlo : ∀ i, i < lo → (_ : i < xs.size) → xs[i] = ys[i]'(by have := h.size_eq; omega)) + (whi : ∀ i, hi ≤ i → (_ : i < xs.size) → xs[i] = ys[i]'(by have := h.size_eq; omega)) : + xs.extract lo hi ~ ys.extract lo hi := by + rcases xs with ⟨xs⟩ + rcases ys with ⟨ys⟩ + simp_all only [perm_iff_toList_perm, List.extract_toArray] + apply List.Perm.take_of_getElem + (w := fun i h₁ h₂ => by + rw [List.getElem_drop, List.getElem_drop, ← getElem_mk, ← getElem_mk] + exact whi (lo + i) (by omega) (by grind)) + apply List.Perm.drop_of_getElem + (w := fun i h₁ h₂ => by + rw [← getElem_mk, ← getElem_mk] + exact wlo i h₁ (by grind)) + simpa using List.perm_iff_toArray_perm.mpr h + +theorem _root_.Vector.Perm.extract' {xs ys : Vector α n} (h : xs ~ ys) {lo hi : Nat} + (wlo : ∀ i, i < lo → (_ : i < n) → xs[i] = ys[i]) (whi : ∀ i, hi ≤ i → (_ : i < n) → xs[i] = ys[i]) : + xs.extract lo hi ~ ys.extract lo hi := by + rcases xs with ⟨xs, rfl⟩ + rcases ys with ⟨ys, h⟩ + exact ⟨Array.Perm.extract' h.toArray (by simpa using wlo) (by simpa using whi)⟩ + +attribute [grind .] Array.Perm.extract' +attribute [grind .] Vector.Perm.extract' + +variable (lt : α → α → Bool) (lo hi : Nat) + +@[simp, grind =] public theorem size_qsort (as : Array α) : + (qsort as lt lo hi).size = as.size := by + grind [qsort] + +private theorem qpartition_loop_perm (as : Vector α n) + (hhi : hi < n) (ilo : lo ≤ i) (ik : i ≤ k) (w : k ≤ hi) : + (qpartition.loop lt lo hi hhi pivot as i k).2 ~ as := by + fun_induction qpartition.loop with grind + +@[local grind .] +private theorem qpartition_perm + (as : Vector α n) (w : lo ≤ hi) (hlo : lo < n) (hhi : hi < n) : + (qpartition as lt lo hi).2 ~ as := by + unfold qpartition + refine Vector.Perm.trans (qpartition_loop_perm ..) ?_ + repeat' first + | split + | grind + | refine Vector.Perm.trans (Vector.swap_perm ..) ?_ + +private theorem qsort_sort_perm + (as : Vector α n) (w : lo ≤ hi) (hlo : lo < n) (hhi : hi < n) : + qsort.sort lt as lo hi w hlo hhi ~ as := by + fun_induction qsort.sort with grind + +grind_pattern qsort_sort_perm => qsort.sort lt as lo hi w hlo hhi + +public theorem qsort_perm (as : Array α) : qsort as lt lo hi ~ as := by + grind [qsort] + +private theorem getElem_qpartition_loop_snd_of_lt_lo + (hhi : hi < n) (as : Vector α n) (i k : Nat) (ilo : lo ≤ i) (ik : i ≤ k) (w : k ≤ hi) (w' : lo ≤ hi) + (l : Nat) (h : l < lo) : (qpartition.loop lt lo hi hhi pivot as i k).2[l] = as[l] := by + fun_induction qpartition.loop <;> grind + +private theorem getElem_qpartition_snd_of_lt_lo (as : Vector α n) + (hhi : hi < n) (w : lo ≤ hi) + (k : Nat) (h : k < lo) : (qpartition as lt lo hi).2[k] = as[k] := by + grind [qpartition, getElem_qpartition_loop_snd_of_lt_lo] + +@[local grind =] private theorem getElem_qsort_sort_of_lt_lo + (as : Vector α n) + (hlo : lo < n) (hhi : hi < n) (w : lo ≤ hi) + (i : Nat) (h : i < lo) : (qsort.sort lt as lo hi)[i] = as[i] := by + fun_induction qsort.sort with grind [getElem_qpartition_snd_of_lt_lo] + +private theorem getElem_qpartition_loop_snd_of_hi_lt + (hhi : hi < n) (as : Vector α n) (i k) + (ilo : lo ≤ i) (ik : i ≤ k) (w : k ≤ hi) (z : i ≤ hi) + (l : Nat) (h : hi < l) (h' : l < n) : (qpartition.loop lt lo hi hhi pivot as i k).2[l] = as[l] := by + fun_induction qpartition.loop <;> grind + +private theorem getElem_qpartition_snd_of_hi_lt (as : Vector α n) + (hhi : hi < n) (w : lo ≤ hi) + (k : Nat) (h : hi < k) (h' : k < n) : (qpartition as lt lo hi).2[k] = as[k] := by + grind [qpartition, getElem_qpartition_loop_snd_of_hi_lt] + +@[local grind =] private theorem getElem_qsort_sort_of_hi_lt + (as : Vector α n) (w : lo ≤ hi) + (hlo : lo < n) (hhi : hi < n) (w : lo ≤ hi) + (i : Nat) (h : hi < i) (h' : i < n) : (qsort.sort lt as lo hi)[i] = as[i] := by + fun_induction qsort.sort with grind [getElem_qpartition_snd_of_hi_lt] + +private theorem extract_qsort_sort_perm (as : Vector α n) (lt : α → α → Bool) + (hlo := by grind) (hhi := by grind) (w : lo ≤ hi := by grind) : + ((qsort.sort lt as lo hi).extract lo (hi + 1)) ~ (as.extract lo (hi + 1)) := by + grind + +private theorem getElem_qsort_sort_mem + (as : Vector α n) (hhi : hi < n) (i : Nat) (h : i < n) (_ : lo ≤ i) (_ : i ≤ hi) : + (qsort.sort lt as lo hi)[i] ∈ as.extract lo (hi + 1) := by + rw [← (extract_qsort_sort_perm lo hi as lt).mem_iff, Vector.mem_extract_iff_getElem] + exact ⟨i - lo, by grind⟩ + +private theorem qpartition_loop_spec₁ + (hhi : hi < n) (ilo : lo ≤ i) (ik : i ≤ k) (w : k < n) (khi : k ≤ hi) + (as : Vector α n) (hpivot : pivot = as[hi]) + (q : ∀ l, (hk₁ : lo ≤ l) → (hk₂ : l < i) → lt as[l] as[hi]) (mid as') + (w_mid : mid = (qpartition.loop lt lo hi hhi pivot as i k).fst.1) (hmid : mid < n) + (w_as : as' = (qpartition.loop lt lo hi hhi pivot as i k).2) : + ∀ l, (h₁ : lo ≤ l) → (h₂ : l < mid) → lt as'[l] as'[mid] := by + fun_induction qpartition.loop with unfold qpartition.loop at w_mid w_as + | case1 + | case2 => apply_assumption <;> grind + | case3 => grind + +private theorem qpartition_loop_spec₂ + (hhi : hi < n) (ilo : lo ≤ i) (ik : i ≤ k) (w : k < n) (khi : k ≤ hi) + (as : Vector α n) (hpivot : pivot = as[hi]) + (q : ∀ l, (hk₁ : i ≤ l) → (hk₂ : l < k) → !lt as[l] as[hi]) (mid as') + (w_mid : mid = (qpartition.loop lt lo hi hhi pivot as i k).fst.1) (hmid : mid < n) + (w_as : as' = (qpartition.loop lt lo hi hhi pivot as i k).2) : + ∀ l, (h₁ : mid < l) → (h₂ : l ≤ hi) → lt as'[l] as'[mid] = false := by + fun_induction qpartition.loop with grind + +/-- +All elements in the active range before the pivot, are less than the pivot. +-/ +private theorem qpartition_spec₁ + (hhi : hi < n) (w : lo ≤ hi) + (as : Vector α n) (mid as') + (w_mid : mid = (qpartition as lt lo hi).fst.1) (hmid : mid < n) + (w_as : as' = (qpartition as lt lo hi).2) : + ∀ i, (h₁ : lo ≤ i) → (h₂ : i < mid) → lt as'[i] as'[mid] := by + grind [qpartition, qpartition_loop_spec₁] + +/-- +All elements in the active range after the pivot, are greater than or equal to the pivot. +-/ +private theorem qpartition_spec₂ + (hhi : hi < n) (w : lo ≤ hi) + (as : Vector α n) (mid as') + (w_mid : mid = (qpartition as lt lo hi).fst.1) (hmid : mid < n) + (w_as : as' = (qpartition as lt lo hi).2) : + ∀ i, (h₁ : mid < i) → (h₂ : i ≤ hi) → lt as'[i] as'[mid] = false := by + grind [qpartition, qpartition_loop_spec₂] + +/-! +We now need to deal with a corner case: +we need to show that `qpartition` only returns a value `≥ hi` when `hi ≤ lo` +(and hence the slice of the array between `lo` and `hi` (inclusive) is trivially already sorted). + +We prove two preliminary lemmas about `qpartition.loop`. +-/ + +/-- If we already have `i < k`, then we're sure to return something less than `hi`. -/ +private theorem qpartition_loop_lt_hi₁ + (ilo : lo ≤ i) (ik : i < k) (w : k ≤ hi) (z : k ≤ hi) (ik' : i ≤ k) : + (qpartition.loop lt lo hi hhi pivot as i k).1.val < hi := by + fun_induction qpartition.loop with grind + +/-- +Otherwise, if there is some position `k' ≥ k` which is greater than or equal to the pivot, +then when we reach that we'll be sure `i < k`, and hence the previous lemma will apply, +and so we're sure to return something less than `hi`. + -/ +private theorem qpartition_loop_lt_hi₂ + {as : Vector α n} (ilo : lo ≤ i) (ik : i ≤ k) (w : k < n) (z : k ≤ hi) + (q : ∃ (k' : Nat) (hj' : k' < n), k' ≥ k ∧ k' < hi ∧ ¬ lt as[k'] pivot) : + (qpartition.loop lt lo hi hhi pivot as i k).1.val < hi := by + fun_induction qpartition.loop with + | case1 => + -- It would be nice if a more aggressive mode in `grind` would do this. + apply_assumption <;> grind + | case2 => grind [qpartition_loop_lt_hi₁] + | case3 => grind + +/-- The only way `qpartition` returns a pivot position `≥ hi` is if `hi ≤ lo`. -/ +private theorem qpartition_fst_lt_hi (lt_asymm : ∀ {a b}, lt a b → ¬ lt b a) + (as : Vector α n) (hhi : hi < n) (w : lo < hi) : (qpartition as lt lo hi).fst.1 < hi := by + apply qpartition_loop_lt_hi₂ lt lo hi + · grind + · exact ⟨(lo + hi)/2, by grind⟩ + +private theorem qsort_sort_spec + (lt_asymm : ∀ {a b}, lt a b → ¬ lt b a) + (le_trans : ∀ {a b c}, ¬ lt b a → ¬ lt c b → ¬ lt c a) + (as : Vector α n) (lo hi : Nat) (hhi : hi < n) (w : lo ≤ hi) + (as' : Vector α n) (w_as : as' = qsort.sort lt as lo hi) : + ∀ i, (h₁ : lo ≤ i) → (h₂ : i < hi) → ¬ lt (as')[i + 1] as'[i] := by + unfold qsort.sort at w_as + split at w_as <;> rename_i w₁ + · -- The interesting case, where `lo < hi`. + intro i h₁ h₂ + -- Decompose `qpartition as lt lo hi` into `mid` (the pivot) and `as'` (the partitioned array). + split at w_as <;> rename_i mid hmid as' w₂ + split at w_as <;> rename_i w₃ + · -- If the pivot was at least `hi`, then we get a contradiction from `lo < hi`. + simp only [Prod.ext_iff, Subtype.ext_iff] at w₂ + obtain ⟨rfl, rfl⟩ := w₂ + have := qpartition_fst_lt_hi lt lo hi lt_asymm as hhi w₁ + grind + · -- Now we know `lo ≤ mid < hi`. + subst w_as + if p₁ : i < mid then + -- If `i < mid`, then the second stage of sorting is only + -- moving elements above where we're looking. + rw [getElem_qsort_sort_of_lt_lo (i := i)] + rw [getElem_qsort_sort_of_lt_lo (i := i + 1)] + -- And so we can apply the theorem recursively replacing `hi` with `mid`. + apply qsort_sort_spec lt_asymm le_trans as' lo mid + -- The remaining arithmetic side conditions are easily resolved. + all_goals grind + else + replace p₁ : mid ≤ i := by grind + -- If `mid ≤ i`, we need to consider two cases. + if p₃ : mid = i then + -- The tricky case, where `mid = i`. + subst i + -- On the right hand side, the index is below the range where the second stage of sorting is happening, + -- so we can drop that sort. + rw [getElem_qsort_sort_of_lt_lo (i := mid)] + -- The `mid` element of `qsort.sort lt as' lo mid ⋯` + -- is *some* element `lo + k` of `as'` in the range `lo ≤ lo + k ≤ mid`. + have z := getElem_qsort_sort_mem lt lo mid as' ?_ mid ?_ ?_ ?_ + rw [Vector.mem_extract_iff_getElem] at z + obtain ⟨k, hk, z⟩ := z + rw [← z] + clear z + -- Similarly, the `mid + 1` element on the left hand side + -- is some element `mid + 1 + k'` of `qsort.sort lt as' lo mid ⋯` + -- in the range `mid + 1 ≤ mid + 1 + k' ≤ hi` + have z := getElem_qsort_sort_mem lt (mid + 1) hi + (qsort.sort lt as' lo mid ?_ ?_) ?_ (mid + 1) ?_ ?_ ?_ + rw [Vector.mem_extract_iff_getElem] at z + obtain ⟨k', hk', z⟩ := z + rw [← z] + clear z + -- And then the first stage sort on the left hand side can't have any effect, + -- as it only moves elements between `lo` and `mid` inclusive. + rw [getElem_qsort_sort_of_hi_lt] + · by_cases p : lo + k = mid + · -- Now if `lo + k = mid`, + -- the element `as'[mid + 1 + k']` is in the top part of the partitioned array, + -- and `as[lo + k]` is the pivot, so we get the inequality from the specification of `qpartition`. + grind [qpartition_spec₂] + · -- Otherwise, we use transitivity: + -- `as[lo + k']` is in the bottom part, so is strictly less than the pivot, + -- while `as'[mid + 1 + k']` is in the top, so greater than or equal to the pivot. + apply le_trans (b := as'[mid]) + · grind [qpartition_spec₁] + · grind [qpartition_spec₂] + -- Various arithmetic side conditions remain from the rewriting, + -- but are now all easy to resolve. + all_goals grind + else + -- If `i < mid`, we can apply the theorem recursively replacing + -- `as` with `qsort.sort lt as' lo mid ⋯` and `lo` with `mid + 1`. + apply qsort_sort_spec lt_asymm le_trans _ _ _ (w_as := rfl) <;> grind + · -- Just an arithmetical contradiction. + grind + +/-- +The slice of `as.qsort lt lo hi` from `lo` to `hi` (inclusive) is sorted. + +This variant states that adjacent elements are non-decreasing. +See `qsort_sorted'` for a variant about arbitrary pairs of indices. +-/ +public theorem qsort_sorted₁' (lt : α → α → Bool) (lt_asymm : ∀ {a b}, lt a b → ¬ lt b a) + (le_trans : ∀ {a b c}, ¬ lt b a → ¬ lt c b → ¬ lt c a) + (as : Array α) (lo hi : Nat) (i) (h₁ : lo ≤ i) (h₂ : i < hi) (h₃ : i + 1 < as.size) : + ¬ lt ((as.qsort lt lo hi)[i + 1]'(by grind)) ((as.qsort lt lo hi)[i]'(by grind)) := by + unfold qsort + split <;> rename_i w + · grind + · apply qsort_sort_spec lt lt_asymm le_trans (w_as := rfl) <;> grind + +/-- +`Array.qsort` returns a sorted array, i.e. adjacent elements are non-decreasing. + +See `qsort_sorted` for a variant about arbitrary pairs of indices. +-/ +public theorem qsort_sorted₁ (lt : α → α → Bool) (lt_asymm : ∀ {a b}, lt a b → ¬ lt b a) + (le_trans : ∀ {a b c}, ¬ lt b a → ¬ lt c b → ¬ lt c a) (as : Array α) + (i) (h : i + 1 < (qsort as lt).size) : + ¬ lt (as.qsort lt)[i + 1] (as.qsort lt)[i] := by + have := qsort_sorted₁' lt lt_asymm le_trans + grind + +/-- The slice of `as.qsort lt lo hi` from `lo` to `hi` (inclusive) is sorted. -/ +public theorem qsort_sorted' (lt : α → α → Bool) (lt_asymm : ∀ {a b}, lt a b → ¬ lt b a) + (le_trans : ∀ {a b c}, ¬ lt b a → ¬ lt c b → ¬ lt c a) + (as : Array α) (lo hi : Nat) (i j) (h₁ : lo ≤ i) (h₂ : i < j) (h₃ : j ≤ hi) (h₄ : j < as.size) : + ¬ lt ((as.qsort lt lo hi)[j]'(by grind)) ((as.qsort lt lo hi)[i]'(by grind)) := by + induction j with + | zero => grind + | succ j ih => + if p : i = j then + subst p + apply qsort_sorted₁' <;> grind + else + apply le_trans (b := (as.qsort lt lo hi)[j]'(by grind)) + · grind + · apply qsort_sorted₁' <;> grind + +public theorem qsort_sorted (lt : α → α → Bool) (lt_asymm : ∀ {a b}, lt a b → ¬ lt b a) + (le_trans : ∀ {a b c}, ¬ lt b a → ¬ lt c b → ¬ lt c a) (as : Array α) : + ∀ i j, (h₁ : i < j) → (h₂ : j < (qsort as lt).size) → + ¬ lt (as.qsort lt)[j] (as.qsort lt)[i] := by + have := qsort_sorted' lt lt_asymm le_trans + grind + +end Array diff --git a/Ix/Theory/Named/Verify/TypeChecker.lean b/Ix/Theory/Named/Verify/TypeChecker.lean new file mode 100644 index 000000000..04ed1b2a3 --- /dev/null +++ b/Ix/Theory/Named/Verify/TypeChecker.lean @@ -0,0 +1,236 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.TypeChecker.InferType +import Ix.Theory.Named.Verify.TypeChecker.WHNF +import Ix.Theory.Named.Verify.TypeChecker.IsDefEq + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +open Lean hiding Environment Exception +open Kernel + +structure VEnvs where + venv : DefinitionSafety → VEnv + +structure VEnvs.WF (env : Environment) (ves : VEnvs) where + tr : TrEnv safety env (ves.venv safety) + hasPrimitives : VEnv.HasPrimitives (ves.venv safety) + safePrimitives : env.find? n = some ci → + Environment.primitives.contains n → ci.safety = .safe ∧ ci.levelParams = [] + mono : safety ≤ safety' → ves.venv safety' ≤ ves.venv safety + projectionReady : ProjectionReady env (ves.venv safety) + structureEtaReady : StructureEtaReady env (ves.venv safety) + +/-- Assemble a `VEnvs` from a pointwise existential. `DefinitionSafety` has three elements, so +this is a finite case split rather than an appeal to choice -- the name records what it replaces. -/ +theorem VEnvs.axiom_of_choice {P : DefinitionSafety → VEnv → Prop} (H : ∀ sf, ∃ x, P sf x) : + ∃ x : VEnvs, ∀ sf, P sf (x.venv sf) := by + have ⟨x1, _⟩ := H .safe; have ⟨x2, _⟩ := H .partial; have ⟨x3, _⟩ := H .unsafe + exact ⟨⟨fun | .safe => x1 | .partial => x2 | .unsafe => x3⟩, by rintro ⟨⟩ <;> assumption⟩ + +/-- A model of `env` at a *single* safety level, which is all the type checker consumes. + +`VEnvs.WF` bundles one of these at every level, but not every environment the checker runs +against admits that: while a `partial` mutual block is being checked its members are present +as axioms tagged `safe` (an `AxiomVal` cannot be tagged `partial`), and their types were only +checked at `partial`, so there is no `safe`-level model of that environment. -/ +structure VEnvAt (env : Environment) (safety : DefinitionSafety) (venv : VEnv) : Prop where + tr : TrEnv safety env venv + hasPrimitives : VEnv.HasPrimitives venv + safePrimitives : env.find? n = some ci → + Environment.primitives.contains n → ci.safety = .safe ∧ ci.levelParams = [] + projectionReady : ProjectionReady env venv + structureEtaReady : StructureEtaReady env venv + +theorem VEnvs.WF.toVEnvAt {env : Environment} {ves : VEnvs} (wf : ves.WF env) + (safety : DefinitionSafety) : VEnvAt env safety (ves.venv safety) where + tr := wf.tr + hasPrimitives := wf.hasPrimitives + safePrimitives := wf.safePrimitives + projectionReady := wf.projectionReady + structureEtaReady := wf.structureEtaReady + +namespace TypeChecker +open Inner + +theorem Methods.withFuel.WF : ∀ {n}, (withFuel n).WF + | 0 => + { isDefEqCore _ _ := .throw + whnfCore _ := .throw + whnf _ := .throw + inferType _ _ := .throw } + | n + 1 => + have := withFuel.WF (n := n) + { isDefEqCore h1 h2 := isDefEqCore'.WF h1 h2 _ this + whnfCore h1 := whnfCore'.WF h1 _ this + whnf h1 := whnf'.WF h1 _ this + inferType h1 h2 := inferType'.WF h1 h2 _ this } + +theorem RecM.WF.run {x : RecM α} (H : x.WF c s Q) : (RecM.run x).WF c s Q := + H _ Methods.withFuel.WF + +def VContext.mk1 {env : Environment} {safety : DefinitionSafety} {venv : VEnv} + (wf : VEnvAt env safety venv) (lparams : List Name := []) + (fuel : FuelConfig := {}) : VContext where + env; safety; lparams; fuel; venv + hasPrimitives := wf.hasPrimitives + safePrimitives := wf.safePrimitives + trenv := wf.tr + projectionReady := wf.projectionReady + structureEtaReady := wf.structureEtaReady + mlctx := .nil + mlctx_wf := trivial + lctx_eq := rfl + +def VContext.mk' {env : Environment} {ves : VEnvs} (wf : ves.WF env) + (safety : DefinitionSafety := .safe) (lparams : List Name := []) + (fuel : FuelConfig := {}) : VContext := .mk1 (wf.toVEnvAt safety) lparams fuel + +theorem VState.WF.empty1 {env : Environment} {safety : DefinitionSafety} {venv : VEnv} + {wf : VEnvAt env safety venv} {lparams : List Name} {fuel : FuelConfig} : + VState.WF (.mk1 wf lparams fuel) {} where + trctx := .nil + ngen_wf := nofun + ectx := ⟨[], .refl, trivial, .refl, .empty, nofun⟩ + inferTypeI_wf := .empty + inferTypeC_wf := .empty + whnfCore_wf := .empty + whnf_wf := .empty + unfold_wf _ := by simp + +theorem VState.WF.empty {env : Environment} {ves : VEnvs} {wf : ves.WF env} + {safety : DefinitionSafety} {lparams : List Name} {fuel : FuelConfig} : + VState.WF (.mk' wf safety lparams fuel) {} := by + unfold VContext.mk'; exact .empty1 + +theorem M.WF.run1 {env : Environment} {venv : VEnv} (wf : VEnvAt env safety venv) + {x : M α} {Q} (H : x.WF (.mk1 wf lparams fuel) {} fun a _ => Q a) : + (M.run env safety {} lparams fuel x).WF Q := by + intro a eq + simp [M.run, Functor.map, Except.map] at eq + split at eq <;> cases eq; rename_i eq + let ⟨_, _, _, _, H⟩ := H .empty1 _ _ eq + exact H + +theorem M.WF.run {env : Environment} {ves : VEnvs} (wf : ves.WF env) + {x : M α} {Q} (H : x.WF (.mk' wf safety lparams fuel) {} fun a _ => Q a) : + (M.run env safety {} lparams fuel x).WF Q := by + unfold VContext.mk' at H; exact M.WF.run1 _ H + +/-- Loop invariant rule for `for x in xs do ...`. `Inv` is indexed by the list still to be +processed, so the conclusion `Inv []` records that every element was handled. The body must +`yield`; a loop that can `break` is out of scope (none of the kernel's loops do). -/ +theorem M.WF.forIn {c : VContext} {f : α → β → M (ForInStep β)} + {Inv : List α → β → VState → Prop} + (H : ∀ v vs b s, Inv (v :: vs) b s → + (f v b).WF c s fun r s' => ∃ b', r = .yield b' ∧ Inv vs b' s') : + ∀ {vs : List α} {b : β} {s : VState}, Inv vs b s → + (forIn vs b f).WF c s fun b' s' => Inv [] b' s' + | [], _, _, h => .pure h + | v :: vs, b, s, h => by + rw [List.forIn_cons] + refine (H v vs b s h).bind fun r s' _ hr => ?_ + obtain ⟨b', rfl, hinv⟩ := hr + exact M.WF.forIn H hinv + +theorem M.WF.bindThrow {c : VContext} {s : VState} {x : M α} {f : α → M β} {Q} + (h : x.WF c s fun _ _ => False) : (x >>= f).WF c s Q := + h.bind fun _ _ _ hf => hf.elim + +/-- Loop rule for `addMutual`'s header loop, whose accumulator is the set of names seen so +far: each iteration rejects a name already in the set, so the whole block is duplicate-free. -/ +theorem M.WF.forInFresh {c : VContext} {Q : Lean.DefinitionVal → β → Prop} + {f : Lean.DefinitionVal → NameSet → M (ForInStep NameSet)} + (H : ∀ v found s, (f v found).WF c s fun r _ => + found.contains v.name = false ∧ (∃ b, Q v b) ∧ r = .yield (found.insert v.name)) : + ∀ {vs : List Lean.DefinitionVal} {found : NameSet} {s : VState}, + (ForIn.forIn vs found f).WF c s fun _ _ => + (∃ bs, List.Forall₂ Q vs bs) ∧ (vs.map (·.name)).Nodup ∧ + ∀ v ∈ vs, found.contains v.name = false + | [], _, _ => .pure ⟨⟨[], .nil⟩, by simp, by simp⟩ + | v :: vs, found, s => by + rw [List.forIn_cons] + refine (H v found s).bind fun r s' _ h => ?_ + obtain ⟨hfresh, ⟨b, hb⟩, rfl⟩ := h + refine (M.WF.forInFresh H (vs := vs) (found := found.insert v.name)).mono + fun _ _ _ h => ?_ + obtain ⟨⟨bs, hbs⟩, hnd, hmem⟩ := h + refine ⟨⟨b :: bs, .cons hb hbs⟩, ?_, ?_⟩ + · rw [List.map_cons, List.nodup_cons] + refine ⟨fun hm => ?_, hnd⟩ + obtain ⟨w, hw, hwn⟩ := List.mem_map.1 hm + have := hmem w hw + rw [NameSet.contains_insert, hwn] at this + simp at this + · intro w hw + cases hw with + | head => exact hfresh + | tail _ hw => + have := hmem w hw + rw [NameSet.contains_insert] at this + exact (by simpa using this : _ ∧ _).2 + +/-- Loop rule for a loop whose elements are already related to a list `cis`, so each iteration +may use the datum paired with the element it processes; each refines its `ci` to a `ci'` +related by `R`. -/ +theorem M.WF.forInForall₂ {c : VContext} {f : α → Unit → M (ForInStep Unit)} + {P : α → β → Prop} {R : β → β → Prop} {Q : α → β → Prop} + (H : ∀ v ci s, P v ci → (f v ()).WF c s fun r _ => + (∃ ci', R ci ci' ∧ Q v ci') ∧ r = .yield ()) : + ∀ {vs : List α} {cis : List β} {s : VState}, List.Forall₂ P vs cis → + (ForIn.forIn vs () f).WF c s fun _ _ => + ∃ cis', List.Forall₂ R cis cis' ∧ List.Forall₂ Q vs cis' := by + intro vs cis s h + induction h generalizing s with + | nil => exact .pure ⟨[], .nil, .nil⟩ + | @cons v ci vs cis hd tl ih => + rw [List.forIn_cons] + refine (H v ci s hd).bind fun r s' _ h => ?_ + obtain ⟨⟨ci', hR, hQ⟩, rfl⟩ := h + refine (ih (s := s')).mono fun _ _ _ h => ?_ + obtain ⟨cis', h1, h2⟩ := h + exact ⟨ci' :: cis', .cons hR h1, .cons hQ h2⟩ + +nonrec theorem whnf.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + M.WF c s (whnf e) fun e₁ _ => c.TrExpr e₁ e' := + (whnf.WF he).run.mono fun _ _ _ h => h.2 + +nonrec theorem inferType.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + M.WF c s (inferType e) fun ty _ => ∃ ty', c.TrTyping e ty e' ty' := + (inferType.WF he).run + +nonrec theorem checkType.WF {c : VContext} {s : VState} (h1 : e.FVarsIn (· ∈ c.vlctx.fvars)) : + M.WF c s (checkType e) fun ty _ => ∃ e' ty', c.TrTyping e ty e' ty' := + (checkType.WF h1).run + +nonrec theorem isDefEq.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + M.WF c s (isDefEq e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := + (isDefEq.WF he₁ he₂).run + +nonrec theorem isProp.WF {c : VContext} {s : VState} + (he : c.TrExprS e e') : (isProp e).WF c s fun b _ => b → c.HasType e' (.sort .zero) := + (isProp.WF he).run + +nonrec theorem ensureSort.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + M.WF c s (ensureSort e e₀) fun e1 _ => c.TrExpr e1 e' ∧ ∃ u, e1 = .sort u := + (ensureSortCore.WF he).run.mono fun _ _ _ h => ⟨h.2.1, h.1⟩ + +nonrec theorem ensureForall.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + M.WF c s (ensureForall e) fun e1 _ => + c.TrExpr e1 e' ∧ ∃ name ty body bi, e1 = .forallE name ty body bi := + (ensureForallCore.WF he).run.mono fun _ _ _ h => h.2 + +nonrec theorem ensureType.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + M.WF c s (ensureType e) fun e1 _ => ∃ e', c.TrExprS e e' ∧ ∃ u u', e1 = .sort u ∧ + VLevel.ofLevel c.lparams u = some u' ∧ c.HasType e' (.sort u') := by + refine (inferType.WF he).bind fun _ _ _ ⟨_, _, a1, a2, a3⟩ => ?_ + refine (ensureSort.WF a2).mono fun _ _ _ ⟨⟨_, b1, b2⟩, b3⟩ => ?_ + obtain ⟨_, rfl⟩ := b3; let .sort b1 := b1 + exact ⟨_, a1, _, _, rfl, b1, a3.defeqU_r c.Ewf c.Δwf b2.symm⟩ diff --git a/Ix/Theory/Named/Verify/TypeChecker/Basic.lean b/Ix/Theory/Named/Verify/TypeChecker/Basic.lean new file mode 100644 index 000000000..175f3c5fb --- /dev/null +++ b/Ix/Theory/Named/Verify/TypeChecker/Basic.lean @@ -0,0 +1,1176 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Environment.Lemmas +import Ix.Theory.Named.Verify.Typing.ConditionallyTyped +import Ix.Theory.Named.Reference.TypeChecker + +open Ix.Theory (VLevel) + +namespace Except + +def WF (x : Except ε α) (Q : α → Prop) : Prop := ∀ a, x = .ok a → Q a + +theorem WF.bind {x : Except ε α} {f : α → Except ε β} {Q R} + (h1 : x.WF Q) (h2 : ∀ a, Q a → (f a).WF R) : (x >>= f).WF R := by + intro b + simp [(· >>= ·), Except.bind] + split; · simp + exact h2 _ (h1 _ rfl) _ + +theorem WF.pure {Q} (H : Q a) : + (pure a : Except ε α).WF Q := by rintro _ ⟨⟩; exact H + +theorem WF.map {x : Except ε α} {f : α → β} {Q R} + (h1 : x.WF Q) (h2 : ∀ a, Q a → R (f a)) : (f <$> x).WF R := by + rw [map_eq_pure_bind] + exact h1.bind fun _ h => .pure (h2 _ h) + +theorem WF.mono {x : Except ε α} {Q R} + (h1 : x.WF Q) (h2 : ∀ a, Q a → R a) : x.WF R := by + simpa using h1.bind fun _ h => .pure (h2 _ h) + +theorem WF.throw {Q} : (throw e : Except ε α).WF Q := nofun + +theorem WF.le {Q R} {x : Except ε α} + (h1 : x.WF Q) (H : ∀ a, Q a → R a) : + x.WF R := fun _ e => H _ (h1 _ e) + +theorem WF.pureBind {f : β → Except ε α} {Q} + {x : β} (H : WF (f x) Q) : ((Pure.pure x : Except ε β) >>= f).WF Q := H + +end Except + +namespace Ix.Theory.Named +open Ix.Theory.Named +open Lean hiding Environment Exception +open Kernel +open scoped _root_.List + +namespace DefEqCache + +variable {env : VEnv} {Us : List Name} {Δ : VLCtx} + +/-- The relation the positive `isDefEq` cache records: both kernel expressions translate to +definitionally equal `VExpr`s. + +Unlike the union-find manager it replaces, this relation is deliberately *not* closed under +transitivity or congruence. `isDefEq` is a sound but incomplete semi-decision procedure and so is +not transitive, and closing over its successes would make the checker's answers depend on the order +in which pairs were presented (lean4#14806). -/ +def IsDefEqE (env : VEnv) (Us : List Name) (Δ : VLCtx) (e₁ e₂ : Expr) : Prop := + ∃ e', TrExprS env Us Δ e₁ e' ∧ TrExpr env Us Δ e₂ e' + +theorem IsDefEqE.symm (H : IsDefEqE env Us Δ e₁ e₂) : IsDefEqE env Us Δ e₂ e₁ := + let ⟨_, h1, _, h2, h3⟩ := H; ⟨_, h2, _, h1, h3.symm⟩ + +/-- The cache is keyed by a `BEq` hash set, so a lookup may present expressions that are only +`Expr.eqv`-equal to the ones recorded. -/ +theorem IsDefEqE.eqv (H : IsDefEqE env Us Δ e₁ e₂) (h₁ : e₁ == e₁') (h₂ : e₂ == e₂') : + IsDefEqE env Us Δ e₁' e₂' := + let ⟨_, h1, _, h2, h3⟩ := H; ⟨_, h1.eqv h₁, _, h2.eqv h₂, h3⟩ + +variable! (henv : env.WF) (W : VLCtx.FVLift' Δ Δ' 0 n 0) (hΔ : VLCtx.WF env Us.length Δ') in +theorem IsDefEqE.weak' (H : IsDefEqE env Us Δ e₁ e₂) : IsDefEqE env Us Δ' e₁ e₂ := + let ⟨_, h1, h2⟩ := H; ⟨_, h1.weakFV' henv W hΔ, h2.weakFV' henv W hΔ⟩ + +theorem IsDefEqE.uniq (henv : env.WF) (hΔ : Δ.WF env Us.length) + (he₁ : TrExprS env Us Δ e₁ e₁') (he₂ : TrExprS env Us Δ e₂ e₂') + (eq : IsDefEqE env Us Δ e₁ e₂) : env.IsDefEqU Us.length Δ.toCtx e₁' e₂' := + let ⟨_, h1, _, h2, h3⟩ := eq + (he₁.uniq henv (.refl henv hΔ) h1).trans henv hΔ <| + h3.symm.trans henv hΔ (h2.uniq henv (.refl henv hΔ) he₂) + +variable (env Us Δ) in +/-- Well-formedness of the positive `isDefEq` cache: every pair it answers `true` for really is a +pair of definitionally equal expressions. -/ +def WF (m : Std.HashSet (Expr × Expr)) : Prop := + ∀ ⦃p : Expr × Expr⦄, p ∈ m → IsDefEqE env Us Δ p.1 p.2 + +theorem WF.empty : WF env Us Δ {} := by simp [WF] + +theorem WF.insert (wf : WF env Us Δ m) (H : IsDefEqE env Us Δ e₁ e₂) : + WF env Us Δ (m.insert (e₁, e₂)) := by + intro p hp + rcases Std.HashSet.mem_insert.1 hp with h | h + · obtain ⟨q₁, q₂⟩ := p + have h' : ((e₁ == q₁) && (e₂ == q₂)) = true := h + rw [Bool.and_eq_true] at h' + exact H.eqv h'.1 h'.2 + · exact wf h + +theorem WF.contains (wf : WF env Us Δ m) (h : m.contains (e₁, e₂)) : + IsDefEqE env Us Δ e₁ e₂ := wf (Std.HashSet.contains_iff_mem.1 h) + +variable! (henv : env.WF) (W : VLCtx.FVLift' Δ Δ' 0 n 0) (hΔ : VLCtx.WF env Us.length Δ') in +theorem WF.weak' (wf : WF env Us Δ m) : WF env Us Δ' m := + fun _ h => (wf h).weak' henv W hΔ + +end DefEqCache + +/-- Exact alignment between one host structure record and the registered +Theory artifact used to interpret primitive projections. The positional +metadata is retained explicitly because ordinary constant translation checks +types but does not identify the kernel's parameter/constructor roles. -/ +structure ProjectionArtifact (env : Environment) (name : Name) + (info : InductiveVal) (venv : VEnv) where + view : VStructureView + name_eq : view.name = name + viewWF : view.WF venv + constructorInfo : ConstructorVal + constructor_find : env.find? view.constructorName = + some (.ctorInfo constructorInfo) + constructor_numParams_eq : constructorInfo.numParams = view.nparams + constructor_numFields_eq : constructorInfo.numFields = view.fields.length + levelParams_length : info.levelParams.length = view.uvars + numParams_eq : info.numParams = view.nparams + numIndices_eq : info.numIndices = 0 + ctors_eq : info.ctors = [view.constructorName] + rawResult_sort : ∃ resultLevel, + view.generation.block.rawResult = .sort resultLevel + programsWF : view.ProgramsWF venv + +/-- Host/Theory coherence needed by primitive projections. + +Inference obtains one complete registered artifact from ready family +metadata. Reduction additionally relies on the positional host fact that a +constructor's cached `numParams` agrees with the registered Theory view; +ordinary constant translation checks the constructor type but does not +identify which leading binders the host metadata classifies as parameters. -/ +structure ProjectionReady (env : Environment) (venv : VEnv) : Prop where + infer : ∀ name info, env.find? name = some (.inductInfo info) → + env.isProjectionReadyStructure name = true → + Nonempty (ProjectionArtifact env name info venv) + constructorNumParams : ∀ (view : VStructureView) (info : ConstructorVal), + view.WF venv → + env.find? view.constructorName = some (.ctorInfo info) → + info.numParams = view.nparams + +/-- Exact host/Theory alignment for one constructor/family pair accepted by +the runtime structure-eta heuristics. The underlying projection artifact +supplies the registered Theory view and its typed projector programs; the two +equalities identify that artifact with the precise host constructor lookup +which triggered the heuristic. -/ +structure StructureEtaArtifact (env : Environment) (familyName : Name) + (familyInfo : InductiveVal) (constructorName : Name) + (constructorInfo : ConstructorVal) (venv : VEnv) where + projection : ProjectionArtifact env familyName familyInfo venv + constructor_name_eq : projection.view.constructorName = constructorName + constructor_info_eq : projection.constructorInfo = constructorInfo + /-- The ordered registry proof fixes the exact descriptor generated from + the checked view. It contains no equality oracle: the associated + subject-reduction package is recovered by `Ordered.structEtaWF`. -/ + etaOrdered : venv.Ordered + etaRegistered : venv.structEtas + (projection.viewWF.toStructEta etaOrdered) + +/-- Host-metadata coherence required whenever the executable checker accepts +a family/constructor pair as a nonrecursive structure. This deliberately +contains no Theory equality: `VEnv.HasStructureEta` is the separate semantic +capability consumed by the verification theorem. -/ +structure StructureEtaReady (env : Environment) (venv : VEnv) : Prop where + resolve : ∀ familyName familyInfo constructorName constructorInfo, + env.find? familyName = some (.inductInfo familyInfo) → + env.find? constructorName = some (.ctorInfo constructorInfo) → + env.isNonRecStructure familyName = true → + Nonempty (StructureEtaArtifact env familyName familyInfo + constructorName constructorInfo venv) + +/-- Resolve the family artifact named by a constructor lookup after the +runtime nonrecursive-structure test has succeeded. -/ +theorem StructureEtaReady.resolveConstructor + (self : StructureEtaReady env venv) + (hctor : env.find? constructorName = some (.ctorInfo constructorInfo)) + (hnonrec : env.isNonRecStructure constructorInfo.induct = true) : + ∃ familyInfo, + env.find? constructorInfo.induct = some (.inductInfo familyInfo) ∧ + Nonempty (StructureEtaArtifact env constructorInfo.induct familyInfo + constructorName constructorInfo venv) := by + have hshape := hnonrec + unfold Kernel.Environment.isNonRecStructure at hshape + generalize hfamily : env.find? constructorInfo.induct = found at hshape + cases found with + | none => simp at hshape + | some info => cases info with + | inductInfo familyInfo => + exact ⟨familyInfo, rfl, + self.resolve _ _ _ _ hfamily hctor hnonrec⟩ + | axiomInfo _ => simp at hshape + | defnInfo _ => simp at hshape + | thmInfo _ => simp at hshape + | opaqueInfo _ => simp at hshape + | quotInfo _ => simp at hshape + | ctorInfo _ => simp at hshape + | recInfo _ => simp at hshape + +/-- Consume the exact registered descriptor retained by a resolved host +structure artifact. Reconstruction typing comes from the registry's +`VStructEta.WF` certificate; the equality is precisely the primitive Theory +rule. -/ +theorem StructureEtaArtifact.eta + (self : StructureEtaArtifact env familyName familyInfo constructorName + constructorInfo venv) + {U : Nat} {Γ : List VExpr} {levels : List VLevel} + {params : List VExpr} {major : VExpr} + (hΓ : OnCtx Γ (venv.IsType U)) + (hlevels : ∀ level ∈ levels, level.WF U) + (hlevelsLength : levels.length = self.projection.view.uvars) + (hparamsLength : params.length = self.projection.view.nparams) + (hparamsSpine : ∃ resultLevel, + venv.SpineWF U Γ + (self.projection.view.familyType.instL levels) + params (.sort resultLevel)) + (hmajor : venv.HasType U Γ major + (self.projection.view.structureType levels params)) : + venv.IsDefEq U Γ + (self.projection.view.etaRebuild levels params major) major + (self.projection.view.structureType levels params) := by + let rule := self.projection.viewWF.toStructEta self.etaOrdered + have hruleWF : rule.WF venv := + self.etaOrdered.structEtaWF self.etaRegistered + obtain ⟨resultLevel, hparamsSpine⟩ := hparamsSpine + have hrebuild := hruleWF.rebuild_hasType VEnv.LE.rfl hΓ hlevels + hlevelsLength hparamsLength ⟨resultLevel, hparamsSpine⟩ hmajor + have heta := VEnv.IsDefEq.structEta self.etaRegistered hlevels + hlevelsLength hparamsLength hparamsSpine hmajor hrebuild + simpa [rule] using heta + +/-- Environments which contain no constructor metadata satisfy projection +readiness vacuously. This is the common staging case for validation fixtures: +families may already be present, but their constructors have not been +installed yet. -/ +theorem ProjectionReady.of_no_ctorInfo + (hnoCtor : ∀ name info, + env.find? name ≠ some (.ctorInfo info)) : + ProjectionReady env venv where + infer name _info hfind hready := by + have hfalse := + Kernel.Environment.isProjectionReadyStructure_false_of_no_ctorInfo + hfind hnoCtor + rw [hfalse] at hready + contradiction + constructorNumParams _view info _hview hfind := + (hnoCtor _ info hfind).elim + +/-- Environments with no constructor metadata also satisfy structure-eta +readiness vacuously. -/ +theorem StructureEtaReady.of_no_ctorInfo + (hnoCtor : ∀ name info, + env.find? name ≠ some (.ctorInfo info)) : + StructureEtaReady env venv where + resolve _ _ constructorName constructorInfo _ hctor _ := + (hnoCtor constructorName constructorInfo hctor).elim + +/-- A convenient negative readiness witness for staging/indexed environments +where the host recognizes no eta-eligible structure family. -/ +theorem StructureEtaReady.of_no_nonRecStructure + (hnone : ∀ name, env.isNonRecStructure name = false) : + StructureEtaReady env venv where + resolve familyName _ _ _ _ _ hnonrec := by + rw [hnone familyName] at hnonrec + contradiction + +namespace TypeChecker + +inductive MLCtx where + | nil : MLCtx + | vlam (id : FVarId) (name : Name) (ty : Expr) (ty' : VExpr) (bi : BinderInfo) : MLCtx → MLCtx + | vlet (id : FVarId) (name : Name) (ty v : Expr) (ty' v' : VExpr) : MLCtx → MLCtx + +@[simp] def MLCtx.vlctx : MLCtx → VLCtx + | .nil => [] + | .vlam id _ ty ty' _ c => (some (id, ty.fvarsList), .vlam ty') :: c.vlctx + | .vlet id _ ty v ty' v' c => (some (id, ty.fvarsList ++ v.fvarsList), .vlet ty' v') :: c.vlctx + +def MLCtx.lctx : MLCtx → LocalContext + | .nil => {} + | .vlam id name ty _ bi c => c.lctx.mkLocalDecl id name ty bi + | .vlet id name ty val _ _ c => c.lctx.mkLetDecl id name ty val + +@[simp] def MLCtx.length : MLCtx → Nat + | .nil => 0 + | .vlam _ _ _ _ _ c + | .vlet _ _ _ _ _ _ c => c.length + 1 + +def MLCtx.decls : MLCtx → List LocalDecl + | .nil => {} + | .vlam x name ty _ bi c => .cdecl c.length x name ty bi .default :: c.decls + | .vlet x name ty v _ _ c => .ldecl c.length x name ty v false default :: c.decls + +@[simp] def MLCtx.fvarRevList (c : MLCtx) (n) (hn : n ≤ c.length) : List FVarId := + match n, c, hn with + | 0, _, _ => [] + | n+1, .vlam id _ _ _ _ c, h + | n+1, .vlet id _ _ _ _ _ c, h => id :: c.fvarRevList n (Nat.le_of_succ_le_succ h) +termination_by structural n + +@[simp] theorem MLCtx.fvarRevList_length {c n hn} : (MLCtx.fvarRevList c n hn).length = n := by + induction n generalizing c <;> [simp; cases c <;> simp [*] at hn ⊢] + +@[simp] def MLCtx.letValList (c : MLCtx) (n) (hn : n ≤ c.length) : List (Option (Expr × Expr)) := + match n, c, hn with + | 0, _, _ => [] + | n+1, .vlam _ _ _ _ _ c, h => none :: c.letValList n (Nat.le_of_succ_le_succ h) + | n+1, .vlet _ _ ty v _ _ c, h => some (ty, v) :: c.letValList n (Nat.le_of_succ_le_succ h) +termination_by structural n + +@[simp] theorem MLCtx.letValList_length {c n hn} : (MLCtx.letValList c n hn).length = n := by + induction n generalizing c <;> [simp; cases c <;> simp [*] at hn ⊢] + +@[simp] def MLCtx.dropN (c : MLCtx) (n) (hn : n ≤ c.length) : MLCtx := + match n, c, hn with + | 0, c, _ => c + | n+1, .vlam _ _ _ _ _ c, h + | n+1, .vlet _ _ _ _ _ _ c, h => c.dropN n (Nat.le_of_succ_le_succ h) +termination_by structural n + +def MLCtx.WF (env : VEnv) (Us : List Name) : MLCtx → Prop + | .nil => True + | .vlam fv _ ty ty' _ c => + c.WF env Us ∧ c.lctx.find? fv = none ∧ + TrExprS env Us c.vlctx ty ty' ∧ + env.IsType Us.length c.vlctx.toCtx ty' + | .vlet fv _ ty v ty' v' c => + c.WF env Us ∧ c.lctx.find? fv = none ∧ + TrExprS env Us c.vlctx ty ty' ∧ TrExprS env Us c.vlctx v v' ∧ + env.HasType Us.length c.vlctx.toCtx v' ty' + +theorem MLCtx.WF.tr : ∀ {c : MLCtx}, c.WF env Us → TrLCtx env Us c.lctx c.vlctx + | .nil, _ => ⟨.nil, .nil⟩ + | .vlam .., ⟨h1, h2, h3, h4⟩ => .mkLocalDecl h1.tr h2 h3 h4 + | .vlet .., ⟨h1, h2, h3, h4, h5⟩ => .mkLetDecl h1.tr h2 h3 h4 h5 + +theorem MLCtx.WF.dropN {c : MLCtx} (n hn) : c.WF env Us → (c.dropN n hn).WF env Us := + match n, c, hn with + | 0, _, _ => id + | n+1, .vlam .., h + | n+1, .vlet .., h => fun H => H.1.dropN n (Nat.le_of_succ_le_succ h) + +theorem MLCtx.dropN_fvars_subset {c : MLCtx} (n hn) : (c.dropN n hn).vlctx.fvars ⊆ c.vlctx.fvars := + match n, c, hn with + | 0, _, _ => fun _ => id + | n+1, .vlam .., h + | n+1, .vlet .., h => + List.subset_cons_of_subset _ <| dropN_fvars_subset n (Nat.le_of_succ_le_succ h) + +theorem MLCtx.noBV (c : MLCtx) : c.vlctx.NoBV := by + induction c <;> trivial + +structure VContext extends Context where + venv : VEnv + hasPrimitives : VEnv.HasPrimitives venv + safePrimitives : env.find? n = some ci → + Environment.primitives.contains n → ci.safety = .safe ∧ ci.levelParams = [] + trenv : TrEnv safety env venv + projectionReady : ProjectionReady env venv + structureEtaReady : StructureEtaReady env venv + mlctx : MLCtx + mlctx_wf : mlctx.WF venv lparams + lctx_eq : mlctx.lctx = lctx + +@[simp] abbrev VContext.lctx' (c : VContext) := c.mlctx.lctx +@[simp] abbrev VContext.vlctx (c : VContext) := c.mlctx.vlctx + +theorem VContext.trlctx (c : VContext) : TrLCtx c.venv c.lparams c.lctx' c.vlctx := c.mlctx_wf.tr +theorem VContext.Ewf (c : VContext) : VEnv.WF c.venv := c.trenv.wf +theorem VContext.Δwf (c : VContext) : c.vlctx.WF c.venv c.lparams.length := c.trlctx.wf + +nonrec abbrev VContext.TrExprS (c : VContext) : Expr → VExpr → Prop := + TrExprS c.venv c.lparams c.vlctx +nonrec abbrev VContext.TrExpr (c : VContext) : Expr → VExpr → Prop := + TrExpr c.venv c.lparams c.vlctx +nonrec abbrev VContext.IsType (c : VContext) : VExpr → Prop := + c.venv.IsType c.lparams.length c.vlctx.toCtx +nonrec abbrev VContext.HasType (c : VContext) : VExpr → VExpr → Prop := + c.venv.HasType c.lparams.length c.vlctx.toCtx +nonrec abbrev VContext.IsDefEqU (c : VContext) : VExpr → VExpr → Prop := + c.venv.IsDefEqU c.lparams.length c.vlctx.toCtx +nonrec abbrev VContext.TrLCtx (c : VContext) : Prop := + TrLCtx c.venv c.lparams c.lctx' c.vlctx +nonrec abbrev VContext.FVarsBelow (c : VContext) : Expr → Expr → Prop := + FVarsBelow c.vlctx +nonrec abbrev VContext.TrTyping (c : VContext) : Expr → Expr → VExpr → VExpr → Prop := + TrTyping c.venv c.lparams c.vlctx + +class VContext.MLCWF (c : VContext) (m : MLCtx) : Prop where + wf : m.WF c.venv c.lparams + +instance (c : VContext) : c.MLCWF c.mlctx := ⟨c.mlctx_wf⟩ + +structure VState extends State where + +def _root_.Ix.Theory.Named.InferCache.WF (c : VContext) (s : VState) (m : InferCache) : Prop := + ∀ ⦃e ty : Expr⦄, m[e]? = some ty → ConditionallyHasType s.ngen c.venv c.lparams c.vlctx e ty + +theorem _root_.Ix.Theory.Named.InferCache.WF.empty : InferCache.WF c s {} := fun _ => by simp + +def WHNFCache.WF (c : VContext) (s : VState) (m : InferCache) : Prop := + ∀ ⦃e ty : Expr⦄, m[e]? = some ty → ConditionallyWHNF s.ngen c.venv c.lparams c.vlctx e ty + +theorem WHNFCache.WF.empty : WHNFCache.WF c s {} := fun _ => by simp + +def UnfoldCache.WF (c : VContext) (m : ExprMap Expr) : Prop := + ∀ ⦃e e' : Expr⦄, m[e]? = some e' → ∃ n ls ci, e = .const n ls ∧ + c.env.find? n = some ci ∧ e' = Inner.instantiateDeltaValue ci ls + +class VState.WF (c : VContext) (s : VState) where + trctx : c.TrLCtx + ngen_wf : ∀ fv ∈ c.vlctx.fvars, s.ngen.Reserves fv + ectx : ∃ Δ' n, Δ'.WF c.venv c.lparams.length ∧ c.vlctx.FVLift' Δ' 0 n 0 ∧ + DefEqCache.WF c.venv c.lparams Δ' s.success ∧ ∀ fv ∈ Δ'.fvars, s.ngen.Reserves fv + inferTypeI_wf : s.inferTypeI.WF c s + inferTypeC_wf : s.inferTypeC.WF c s + whnfCore_wf : WHNFCache.WF c s s.whnfCoreCache + whnf_wf : WHNFCache.WF c s s.whnfCache + unfold_wf : UnfoldCache.WF c s.unfold + +theorem VState.WF.find?_eq_none {id} + (wf : VState.WF c s) (H : ¬s.ngen.Reserves id) : c.lctx'.find? id = none := + wf.trctx.find?_eq_none.2 fun h => H (wf.ngen_wf _ h) + +def VState.LE (s₁ s₂ : VState) : Prop := + s₁.ngen ≤ s₂.ngen + +instance : LE VState := ⟨VState.LE⟩ + +theorem VState.LE.rfl {s : VState} : s ≤ s := NameGenerator.LE.rfl + +theorem VState.LE.trans {s₁ s₂ s₃ : VState} (h₁ : s₁ ≤ s₂) (h₂ : s₂ ≤ s₃) : s₁ ≤ s₃ := + NameGenerator.LE.trans h₁ h₂ + +theorem VState.LE.reservesV {s₁ s₂ : VState} (h : s₁ ≤ s₂) {{fv}} : + s₁.ngen.Reserves fv → s₂.ngen.Reserves fv := + (·.mono h) + +theorem VState.LE.reserves {s₁ s₂ : VState} (h : s₁ ≤ s₂) {{e}} : + FVarsIn s₁.ngen.Reserves e → FVarsIn s₂.ngen.Reserves e := + (·.mono h.reservesV) + +def M.WF (c : VContext) (vs : VState) (x : M α) (Q : α → VState → Prop) : Prop := + vs.WF c → ∀ a s', x c.toContext vs.toState = .ok (a, s') → + ∃ vs', vs'.toState = s' ∧ vs ≤ vs' ∧ vs'.WF c ∧ Q a vs' + +theorem M.WF.bind {c : VContext} {s : VState} {x : M α} {f : α → M β} {Q R} + (h1 : x.WF c s Q) + (h2 : ∀ a s', s ≤ s' → Q a s' → (f a).WF c s' R) : + (x >>= f).WF c s R := by + intro wf₁ a vs₁ + simp [(· >>= ·), ReaderT.bind, StateT.bind, Except.bind] + split; · simp + intro h; rename_i v eq + obtain ⟨vs₂, eq1, le1, wf₂, h1⟩ := h1 wf₁ _ _ eq + obtain ⟨vs₃, rfl, le2, wf₃, h2⟩ := h2 _ _ le1 h1 wf₂ _ _ (eq1 ▸ h) + exact ⟨_, rfl, le1.trans le2, wf₃, h2⟩ + +theorem M.WF.pure {c : VContext} {s : VState} {Q} (H : Q a s) : + (pure a : M α).WF c s Q := by rintro h _ _ ⟨⟩; exact ⟨_, rfl, .rfl, h, H⟩ + +theorem M.WF.map {c : VContext} {s : VState} {x : M α} {f : α → β} {Q R} + (h1 : x.WF c s Q) (h2 : ∀ a s', s ≤ s' → Q a s' → R (f a) s') : (f <$> x).WF c s R := by + rw [map_eq_pure_bind] + exact h1.bind fun _ _ le h => .pure (h2 _ _ le h) + +theorem M.WF.mono {c : VContext} {s : VState} {x : M α} {Q R} + (h1 : x.WF c s Q) (h2 : ∀ a s', s ≤ s' → Q a s' → R a s') : x.WF c s R := by + simpa using h1.bind fun _ _ a1 a2 => .pure (h2 _ _ a1 a2) + +theorem M.WF.throw {c : VContext} {s : VState} {Q} : (throw e : M α).WF c s Q := nofun + +theorem M.WF.le {c : VContext} {s : VState} {Q R} {x : M α} + (h1 : x.WF c s Q) (H : ∀ a s', s ≤ s' → Q a s' → R a s') : + x.WF c s R := fun wf _ _ e => + let ⟨_, a1, a2, a3, a4⟩ := h1 wf _ _ e + ⟨_, a1, a2, a3, H _ _ a2 a4⟩ + +structure Methods.WF (m : Methods) where + isDefEqCore : c.TrExprS e₁ e₁' → c.TrExprS e₂ e₂' → + (m.isDefEqCore e₁ e₂).WF c s fun b _ => b → c.IsDefEqU e₁' e₂' + whnfCore : c.TrExprS e e' → + (m.whnfCore e cheapProj).WF c s fun e₁ _ => c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' + whnf : c.TrExprS e e' → + (m.whnf e).WF c s fun e₁ _ => c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' + inferType : e.FVarsIn (· ∈ c.vlctx.fvars) → + (inferOnly = true → ∃ e', c.TrExprS e e') → + (m.inferType e inferOnly).WF c s fun ty _ => ∃ e' ty', c.TrTyping e ty e' ty' + +def RecM.WF (c : VContext) (s : VState) (x : RecM α) (Q : α → VState → Prop) : Prop := + ∀ m, m.WF → M.WF c s (x m) Q + +theorem M.WF.liftExcept {c : VContext} {s : VState} {x : Except Exception α} {Q} (h : x.WF Q) : + M.WF c s (liftM x) fun a _ => Q a := by + rintro wf _ _ eq + cases x <;> cases eq + exact ⟨s, rfl, .rfl, wf, h _ rfl⟩ + +theorem M.WF.lift {c : VContext} {s : VState} {x : M α} {Q} (h : x.WF c s Q) : + RecM.WF c s x Q := fun _ _ => h + +instance : Coe (M.WF c s x Q) (RecM.WF c s x Q) := ⟨M.WF.lift⟩ + +theorem RecM.WF.bind {c : VContext} {s : VState} {x : RecM α} {f : α → RecM β} {Q R} + (h1 : x.WF c s Q) (h2 : ∀ a s', s ≤ s' → Q a s' → (f a).WF c s' R) : (x >>= f).WF c s R := + fun _ h => M.WF.bind (h1 _ h) fun _ _ h1' h2' => h2 _ _ h1' h2' _ h + +theorem RecM.WF.bind_le {c : VContext} {s : VState} {x : RecM α} {f : α → RecM β} {Q R} + (h1 : x.WF c s Q) (hs : s₀ ≤ s) + (h2 : ∀ a s', s₀ ≤ s' → Q a s' → (f a).WF c s' R) : (x >>= f).WF c s R := + RecM.WF.bind h1 fun _ _ h => h2 _ _ (hs.trans h) + +theorem RecM.WF.pure {c : VContext} {s : VState} {Q} (H : Q a s) : (pure a : RecM α).WF c s Q := + fun _ _ => .pure H + +theorem RecM.WF.map {c : VContext} {s : VState} {x : RecM α} {f : α → β} {Q R} + (h1 : x.WF c s Q) (h2 : ∀ a s', s ≤ s' → Q a s' → R (f a) s') : (f <$> x).WF c s R := by + rw [map_eq_pure_bind] + exact h1.bind fun _ _ le h => .pure (h2 _ _ le h) + +theorem RecM.WF.mono {c : VContext} {s : VState} {x : RecM α} {Q R} + (h1 : x.WF c s Q) (h2 : ∀ a s', s ≤ s' → Q a s' → R a s') : x.WF c s R := by + rw [← id_map x]; exact h1.map h2 + +theorem RecM.WF.throw {c : VContext} {s : VState} {Q} : (throw e : RecM α).WF c s Q := nofun + +theorem RecM.WF.le {c : VContext} {s : VState} {Q R} {x : RecM α} + (h1 : x.WF c s Q) (H : ∀ a s', s ≤ s' → Q a s' → R a s') : + x.WF c s R := fun _ h => (h1 _ h).le H + +theorem RecM.WF.pureBind {c : VContext} {s : VState} {f : β → RecM α} {Q} + {x : β} (H : WF c s (f x) Q) : ((Pure.pure x : RecM β) >>= f).WF c s Q := H + +theorem get.WF {c : VContext} {s : VState} : + M.WF c s get fun a s' => s.toState = a ∧ s = s' := by + rintro wf _ _ ⟨⟩; exact ⟨_, rfl, .rfl, wf, rfl, rfl⟩ + +theorem RecM.WF.get {c : VContext} {s : VState} {f : State → RecM α} {Q} + (H : WF c s (f s.toState) Q) : (get >>= f).WF c s Q := H + +theorem getEnv.WF {c : VContext} {s : VState} : + M.WF c s getEnv fun a s' => c.env = a ∧ s = s' := by + rintro wf _ _ ⟨⟩; exact ⟨_, rfl, .rfl, wf, rfl, rfl⟩ + +theorem RecM.WF.getEnv {c : VContext} {s : VState} {f : Environment → RecM α} {Q} + (H : WF c s (f c.env) Q) : (liftM getEnv >>= f).WF c s Q := H + +theorem getLCtx.WF {c : VContext} {s : VState} : + M.WF c s getLCtx fun a s' => c.lctx' = a ∧ s = s' := by + rintro wf _ _ ⟨⟩; exact ⟨_, rfl, .rfl, wf, c.lctx_eq, rfl⟩ + +theorem RecM.WF.getLCtx {c : VContext} {s : VState} {f : LocalContext → RecM α} {Q} + (H : WF c s (f c.lctx') Q) : (getLCtx >>= f).WF c s Q := + getLCtx.WF.lift.bind <| by rintro _ _ _ ⟨rfl, rfl⟩; exact H + +theorem RecM.WF.readThe {c : VContext} {s : VState} {f : Context → RecM α} {Q} + (H : WF c s (f c.toContext) Q) : (readThe Context >>= f).WF c s Q := H + +theorem getNGen.WF {c : VContext} {s : VState} : + M.WF c s getNGen fun a s' => s.ngen = a ∧ s = s' := by + rintro wf _ _ ⟨⟩; exact ⟨_, rfl, .rfl, wf, rfl, rfl⟩ + +theorem M.WF.getNGen {c : VContext} {s : VState} {f : NameGenerator → M α} {Q} + (H : WF c s (f s.ngen) Q) : (getNGen >>= f).WF c s Q := H + +theorem RecM.WF.getNGen {c : VContext} {s : VState} {f : NameGenerator → RecM α} {Q} + (H : WF c s (f s.ngen) Q) : (getNGen >>= f).WF c s Q := H + +theorem RecM.WF.stateWF {c : VContext} {s : VState} {x : RecM α} {Q} + (H : s.WF c → WF c s x Q) : WF c s x Q := + fun _ h wf => H wf _ h wf + +@[simp] theorem toLBool_true {b : Bool} : b.toLBool = .true ↔ b = true := by + cases b <;> simp [Bool.toLBool] + +theorem RecM.WF.toLBoolM {Q : VState → Prop} {x : RecM Bool} + (H : x.WF c s fun b s => b → Q s) : (toLBoolM x).WF c s fun b s => b = .true → Q s := + H.bind fun _ _ _ H => .pure fun h => H (by simpa using h) + +def VContext.withMLC (c : VContext) (m : MLCtx) [wf : c.MLCWF m] : VContext := + { c with + mlctx := m + mlctx_wf := wf.1 + lctx := m.lctx + lctx_eq := rfl } + +@[simp] theorem VContext.withMLC_self (c : VContext) : c.withMLC c.mlctx = c := by + simp [withMLC, c.lctx_eq] + +def VState.next (s : VState) : VState := { s with ngen := s.ngen.next } + +protected theorem RecM.WF.withLocalDecl {c : VContext} {m} [cwf : c.MLCWF m] + {s : VState} {f : Expr → RecM α} {Q name ty ty' bi} + (hty : (c.withMLC m).TrExprS ty ty') + (hty' : (c.withMLC m).IsType ty') + (hs : s₀ ≤ s) + (H : ∀ id cwf' s', s₀ ≤ s' → ¬s.ngen.Reserves id → + WF (c.withMLC (.vlam id name ty ty' bi m) (wf := cwf')) s' (f (.fvar id)) Q) : + (withLocalDecl name bi ty f).WF (c.withMLC m) s Q := by + intro _ mwf wf a s' e + let id := s.ngen.curr + have h0 := s.ngen.next_reserves_self + have h1 := s.ngen.not_reserves_self + have le : s ≤ s.next := .next + have h1' := wf.find?_eq_none h1 + let m' := m.vlam ⟨id⟩ name ty ty' bi + have cwf' : c.MLCWF m' := ⟨cwf.1, h1', hty, hty'⟩ + have : VState.WF (c.withMLC m') s.next := + have trctx := wf.trctx.mkLocalDecl h1' hty hty' + have hic {ic} (H : InferCache.WF (c.withMLC m) s ic) : InferCache.WF (c.withMLC m') s.next ic := + fun _ _ h => ((H h).fresh c.Ewf.ordered trctx.wf).mono le + have hwc {wc} (H : WHNFCache.WF (c.withMLC m) s wc) : WHNFCache.WF (c.withMLC m') s.next wc := + fun _ _ h => ((H h).fresh c.Ewf trctx.wf).mono le + { ngen_wf := by + simp [m', VContext.withMLC]; exact ⟨h0, fun _ h => le.reservesV (wf.ngen_wf _ h)⟩ + ectx := by + let ⟨_, _, a1, a2, a3, a4⟩ := wf.ectx + refine + have b1 := ⟨a1, ?_, hty'.weak' c.Ewf.ordered a2.toCtx⟩ + ⟨_, _, b1, a2.cons_fvar _ _ hty.fvarsList, a3.weak' c.Ewf (.skip_fvar _ _ .refl) b1, + fun _ h => by obtain _ | ⟨_, h⟩ := h <;> [exact h0; exact (a4 _ h).mono le]⟩ + rintro _ _ ⟨⟩; exact ⟨mt (a4 _) h1, hty.fvarsList.trans a2.fvars_sublist.subset⟩ + trctx, inferTypeI_wf := hic wf.inferTypeI_wf, inferTypeC_wf := hic wf.inferTypeC_wf + whnfCore_wf := hwc wf.whnfCore_wf, whnf_wf := hwc wf.whnf_wf, unfold_wf := wf.unfold_wf } + let ⟨s', hs1, hs2, wf', hs4⟩ := H _ _ _ (hs.trans le) h1 _ mwf this a s' e + refine have le' := le.trans hs2; ⟨s', hs1, le', ?_, hs4⟩ + have hic {ic} (H : InferCache.WF (c.withMLC m') s' ic) : + InferCache.WF (c.withMLC m) s' ic := fun _ _ h => (H h).weakN_inv c.Ewf wf'.trctx.wf + have hwc {wc} (H : WHNFCache.WF (c.withMLC m') s' wc) : + WHNFCache.WF (c.withMLC m) s' wc := fun _ _ h => (H h).weakN_inv c.Ewf wf'.trctx.wf + let ⟨_, _, a1, a2, a3⟩ := wf'.ectx + exact { + ngen_wf := (by simpa [VContext.withMLC] using wf'.ngen_wf :).2 + ectx := ⟨_, _, a1, .comp (.skip_fvar _ _ .refl) a2, a3⟩ + trctx := wf.trctx + inferTypeI_wf := hic wf'.inferTypeI_wf, inferTypeC_wf := hic wf'.inferTypeC_wf + whnfCore_wf := hwc wf'.whnfCore_wf, whnf_wf := hwc wf'.whnf_wf, unfold_wf := wf'.unfold_wf + } + +protected theorem RecM.WF.withLetDecl {c : VContext} {m} [cwf : c.MLCWF m] + {s : VState} {f : Expr → RecM α} {Q name ty ty'} + (hty : (c.withMLC m).TrExprS ty ty') + (hval : (c.withMLC m).TrExprS val val') + (hval' : (c.withMLC m).HasType val' ty') + (hs : s₀ ≤ s) + (H : ∀ id cwf' s', s₀ ≤ s' → ¬s.ngen.Reserves id → + WF (c.withMLC (.vlet id name ty val ty' val' m) (wf := cwf')) s' (f (.fvar id)) Q) : + (withLetDecl name ty val f).WF (c.withMLC m) s Q := by + intro _ mwf wf a s' e + let id := s.ngen.curr + have h0 := s.ngen.next_reserves_self + have h1 := s.ngen.not_reserves_self + have le : s ≤ s.next := .next + have h1' := wf.find?_eq_none h1 + let m' := m.vlet ⟨id⟩ name ty val ty' val' + have cwf' : c.MLCWF m' := ⟨cwf.1, h1', hty, hval, hval'⟩ + have : VState.WF (c.withMLC m') s.next := + have trctx := wf.trctx.mkLetDecl h1' hty hval hval' + have hic {ic} (H : InferCache.WF (c.withMLC m) s ic) : + InferCache.WF (c.withMLC m') s.next ic := + fun _ _ h => ((H h).fresh c.Ewf.ordered trctx.wf).mono le + have hwc {wc} (H : WHNFCache.WF (c.withMLC m) s wc) : WHNFCache.WF (c.withMLC m') s.next wc := + fun _ _ h => ((H h).fresh c.Ewf trctx.wf).mono le + { ngen_wf := by + simp [m', VContext.withMLC]; exact ⟨h0, fun _ h => le.reservesV (wf.ngen_wf _ h)⟩ + ectx := by + let ⟨_, _, a1, a2, a3, a4⟩ := wf.ectx + have hv := List.append_subset.2 ⟨hty.fvarsList, hval.fvarsList⟩ + refine + have b1 := ⟨a1, ?_, hval'.weak' c.Ewf.ordered a2.toCtx⟩ + ⟨_, _, b1, a2.cons_fvar _ _ hv, a3.weak' c.Ewf (.skip_fvar _ _ .refl) b1, + fun _ h => by obtain _ | ⟨_, h⟩ := h <;> [exact h0; exact (a4 _ h).mono le]⟩ + rintro _ _ ⟨⟩; exact ⟨mt (a4 _) h1, hv.trans a2.fvars_sublist.subset⟩ + trctx, inferTypeI_wf := hic wf.inferTypeI_wf, inferTypeC_wf := hic wf.inferTypeC_wf + whnfCore_wf := hwc wf.whnfCore_wf, whnf_wf := hwc wf.whnf_wf, unfold_wf := wf.unfold_wf } + let ⟨s', hs1, hs2, wf', hs4⟩ := H _ _ _ (hs.trans le) h1 _ mwf this a s' e + refine ⟨s', hs1, le.trans hs2, ?_, hs4⟩ + have hic {ic} (H : InferCache.WF (c.withMLC m') s' ic) : + InferCache.WF (c.withMLC m) s' ic := fun _ _ h => (H h).weakN_inv c.Ewf wf'.trctx.wf + have hwc {wc} (H : WHNFCache.WF (c.withMLC m') s' wc) : + WHNFCache.WF (c.withMLC m) s' wc := fun _ _ h => (H h).weakN_inv c.Ewf wf'.trctx.wf + let ⟨_, _, a1, a2, a3⟩ := wf'.ectx + exact { + ngen_wf := (by simpa [VContext.withMLC] using wf'.ngen_wf :).2 + ectx := ⟨_, _, a1, .comp (.skip_fvar _ _ .refl) a2, a3⟩ + trctx := wf.trctx + inferTypeI_wf := hic wf'.inferTypeI_wf, inferTypeC_wf := hic wf'.inferTypeC_wf + whnfCore_wf := hwc wf'.whnfCore_wf, whnf_wf := hwc wf'.whnf_wf, unfold_wf := wf'.unfold_wf + } + +@[simp] def MLCtx.mkForall (c : MLCtx) (n) (hn : n ≤ c.length) (e : Expr) : Expr := + match n, c, hn with + | 0, _, _ => e + | n+1, .vlam x name ty _ bi c, h => + c.mkForall n (Nat.le_of_succ_le_succ h) (.forallE name ty (.abstract1 x e) bi) + | n+1, .vlet x name ty val _ _ c, h => + c.mkForall n (Nat.le_of_succ_le_succ h) <| + let e' := Expr.abstract1 x e + if e'.hasLooseBVar' 0 then + .letE name ty val e' false + else + e'.lowerLooseBVars' 1 1 +termination_by structural n + +def AllAbove (Δ : VLCtx) (P : FVarId → Prop) (fv : FVarId) : Prop := fv ∈ Δ.fvars → P fv + +theorem AllAbove.wf (H : Δ.FVWF) : IsFVarUpSet (AllAbove Δ P) Δ ↔ IsFVarUpSet P Δ := + IsFVarUpSet.congr H fun _ h => by simp [h, AllAbove] + +@[simp] def MLCtx.mkForall' (c : MLCtx) (n) (hn : n ≤ c.length) (e : VExpr) : VExpr := + match n, c, hn, e with + | 0, _, _, e => e + | n+1, .vlam _ _ _ ty _ c, h, e => c.mkForall' n (Nat.le_of_succ_le_succ h) (.forallE ty e) + | n+1, .vlet _ _ _ _ _ _ c, h, e => c.mkForall' n (Nat.le_of_succ_le_succ h) e +termination_by structural n + +@[simp] def MLCtx.mkLambda (c : MLCtx) (n) (hn : n ≤ c.length) (e : Expr) : Expr := + match n, c, hn, e with + | 0, _, _, e => e + | n+1, .vlam x name ty _ bi c, h, e => + c.mkLambda n (Nat.le_of_succ_le_succ h) (.lam name ty (.abstract1 x e) bi) + | n+1, .vlet x name ty val _ _ c, h, e => + c.mkLambda n (Nat.le_of_succ_le_succ h) <| + let e' := Expr.abstract1 x e + if e'.hasLooseBVar' 0 then + .letE name ty val e' false + else + e'.lowerLooseBVars' 1 1 +termination_by structural n + +@[simp] def MLCtx.mkLambda' (c : MLCtx) (n) (hn : n ≤ c.length) (e : VExpr) : VExpr := + match n, c, hn, e with + | 0, _, _, e => e + | n+1, .vlam _ _ _ ty _ c, h, e => c.mkLambda' n (Nat.le_of_succ_le_succ h) (.lam ty e) + | n+1, .vlet _ _ _ _ _ _ c, h, e => c.mkLambda' n (Nat.le_of_succ_le_succ h) e +termination_by structural n + +-- HACK: MLCtx.mkLet equation generation fails if this is inlined +def MLCtx.mkLetArg (x : FVarId) (name : Name) + (ty val : Expr) (nd : Option Bool) (e : Expr) : Expr := + let e' := Expr.abstract1 x e + if e'.hasLooseBVar' 0 then + .letE name ty val e' (nd.getD false) + else if let some nd := nd then + .letE name ty val e' nd + else + e'.lowerLooseBVars' 1 1 + +@[simp] def MLCtx.mkLet (c : MLCtx) (n) (hn : n ≤ c.length) + (nds : List (Option Bool)) (eq : nds.length = n) (e : Expr) (asForall := false) : Expr := + match n, c, hn, nds, eq, e with + | 0, _, _, _, _, e => e + | n+1, .vlam x name ty _ bi c, h, _ :: nds, eq, e => + c.mkLet n (Nat.le_of_succ_le_succ h) nds (Nat.succ_inj.1 eq) <| + if asForall then .forallE name ty (.abstract1 x e) bi else .lam name ty (.abstract1 x e) bi + | n+1, .vlet x name ty val _ _ c, h, nd :: nds, eq, e => + c.mkLet n (Nat.le_of_succ_le_succ h) nds (Nat.succ_inj.1 eq) <| mkLetArg x name ty val nd e +termination_by structural n + +variable! (henv : VEnv.WF env) in +theorem MLCtx.WF.mkForall_trS {c : MLCtx} (wf : c.WF env Us) + (H1 : TrExprS env Us c.vlctx e e') + (H2 : env.IsType Us.length c.vlctx.toCtx e') (n hn) : + TrExprS env Us (c.dropN n hn).vlctx (c.mkForall n hn e) (c.mkForall' n hn e') ∧ + env.IsType Us.length (c.dropN n hn).vlctx.toCtx (c.mkForall' n hn e') := by + induction n generalizing c e e' with + | zero => exact ⟨H1, H2⟩ + | succ n ih => + match c with + | .vlam x name ty ty' bi c => + let ⟨h1, _, h3, h4⟩ := wf + refine ih h1 ?_ (.forallE h4 H2) _ + exact .forallE h4 H2 h3 (.abstract .zero H1) + | .vlet x name ty val ty' val' c => + let ⟨h1, _, h3, h4, h5⟩ := wf + refine ih h1 ?_ H2 _; dsimp; split + · exact .letE h5 h3 h4 (.abstract .zero H1) + · rename_i h; simp at h + rw [Expr.lowerLooseBVars_eq_instantiate h (v := val)] + exact .inst_let henv (.abstract .zero H1) h4 + +theorem mkForall_hasType {c : MLCtx} + (hus : us.Forall₂ (VLevel.ofLevel Us · = some ·) us') + (hΔ : c.vlctx.SortList env Us.length us') + (hu : VLevel.ofLevel Us u = some u') + (H2 : env.HasType Us.length c.vlctx.toCtx e' (.sort u')) (n hn) + (hus : us.length = n) : + ∃ u₀', VLevel.ofLevel Us (List.foldl (fun x y => mkLevelIMax' y x) u us) = some u₀' ∧ + env.HasType Us.length (c.dropN n hn).vlctx.toCtx (c.mkForall' n hn e') (.sort u₀') := by + subst hus + induction hus generalizing c e' u u' with + | nil => exact ⟨_, hu, H2⟩ + | cons h _ ih => + match c, hΔ with + | .vlam x name ty ty' bi c, .cons hΔ hu₁ => + have ⟨_, h5, h6⟩ := ofLevel_mkLevelIMax' h hu + refine ih hΔ h5 ?_ (Nat.le_of_succ_le_succ hn) + refine .defeq (.sortDF ?_ (.of_ofLevel h5) h6.symm) (hu₁.forallE H2) + exact ⟨.of_ofLevel h, .of_ofLevel hu⟩ + +theorem MLCtx.WF.mkForall'_congr {c : MLCtx} (wf : c.WF env Us) + (H : env.IsDefEq Us.length c.vlctx.toCtx e₁ e₂ (.sort u)) (n hn) : + ∃ u, env.IsDefEq Us.length (c.dropN n hn).vlctx.toCtx + (c.mkForall' n hn e₁) (c.mkForall' n hn e₂) (.sort u) := by + induction n generalizing c e₁ e₂ u with + | zero => exact ⟨_, H⟩ + | succ n ih => + match c with + | .vlam .. => let ⟨_, h⟩ := wf.2.2.2; exact ih wf.1 (.forallEDF h H) _ + | .vlet .. => exact ih wf.1 H _ + +theorem MLCtx.WF.mkForall_tr (henv : VEnv.WF env) {c : MLCtx} (wf : c.WF env Us) + (H1 : TrExpr env Us c.vlctx e e') + (H2 : env.IsType Us.length c.vlctx.toCtx e') (n hn) : + TrExpr env Us (c.dropN n hn).vlctx (c.mkForall n hn e) (c.mkForall' n hn e') ∧ + env.IsType Us.length (c.dropN n hn).vlctx.toCtx (c.mkForall' n hn e') := by + let ⟨_, H1, eq⟩ := H1 + let ⟨_, H2⟩ := H2 + have eq := eq.of_r henv wf.tr.wf H2 + have ⟨_, H⟩ := wf.mkForall'_congr eq n hn + have := wf.mkForall_trS henv H1 ⟨_, eq.hasType.1⟩ n hn + exact ⟨⟨_, this.1, _, H⟩, this.2.defeqU_l henv (wf.dropN n hn).tr.wf ⟨_, H⟩⟩ + +variable! (henv : VEnv.WF env) in +theorem MLCtx.WF.mkLambda_trS {c : MLCtx} (wf : c.WF env Us) + (H1 : TrExprS env Us c.vlctx e e') + (H2 : env.HasType Us.length c.vlctx.toCtx e' ty') (n hn) : + TrExprS env Us (c.dropN n hn).vlctx (c.mkLambda n hn e) (c.mkLambda' n hn e') ∧ + env.HasType Us.length (c.dropN n hn).vlctx.toCtx + (c.mkLambda' n hn e') (c.mkForall' n hn ty') := by + induction n generalizing c e e' ty' with + | zero => exact ⟨H1, H2⟩ + | succ n ih => + match c with + | .vlam x name ty ty' bi c => + let ⟨h1, _, h3, _, h4⟩ := wf + refine ih h1 ?_ (.lam h4 H2) _ + exact .lam ⟨_, h4⟩ h3 (.abstract .zero H1) + | .vlet x name ty val ty' val' c => + let ⟨h1, _, h3, h4, h5⟩ := wf + refine ih h1 ?_ H2 _; dsimp; split + · exact .letE h5 h3 h4 (.abstract .zero H1) + · rename_i h; simp at h + rw [Expr.lowerLooseBVars_eq_instantiate h (v := val)] + exact .inst_let henv (.abstract .zero H1) h4 + +theorem MLCtx.WF.mkLambda'_congr {c : MLCtx} (wf : c.WF env Us) + (H : env.IsDefEq Us.length c.vlctx.toCtx e₁ e₂ ty) (n hn) : + env.IsDefEq Us.length (c.dropN n hn).vlctx.toCtx + (c.mkLambda' n hn e₁) (c.mkLambda' n hn e₂) (c.mkForall' n hn ty) := by + induction n generalizing c e₁ e₂ ty with + | zero => exact H + | succ n ih => + match c with + | .vlam .. => let ⟨_, h⟩ := wf.2.2.2; exact ih wf.1 (.lamDF h H) _ + | .vlet .. => exact ih wf.1 H _ + +theorem MLCtx.WF.mkLambda_tr (henv : VEnv.WF env) {c : MLCtx} (wf : c.WF env Us) + (H1 : TrExpr env Us c.vlctx e e') + (H2 : env.HasType Us.length c.vlctx.toCtx e' ty') (n hn) : + TrExpr env Us (c.dropN n hn).vlctx (c.mkLambda n hn e) (c.mkLambda' n hn e') ∧ + env.HasType Us.length (c.dropN n hn).vlctx.toCtx + (c.mkLambda' n hn e') (c.mkForall' n hn ty') := by + let ⟨_, H1, eq⟩ := H1 + have eq := eq.of_r henv wf.tr.wf H2 + have H := wf.mkLambda'_congr eq n hn + have := wf.mkLambda_trS henv H1 eq.hasType.1 n hn + exact ⟨⟨_, this.1, _, H⟩, this.2.defeqU_l henv (wf.dropN n hn).tr.wf ⟨_, H⟩⟩ + +variable! (henv : VEnv.WF env) in +theorem MLCtx.WF.mkLet_trS {c : MLCtx} (wf : c.WF env Us) + (H1 : TrExprS env Us c.vlctx e e') + (H2 : env.HasType Us.length c.vlctx.toCtx e' ty') (n hn nds hnds) : + TrExprS env Us (c.dropN n hn).vlctx (c.mkLet n hn nds hnds e) (c.mkLambda' n hn e') ∧ + env.HasType Us.length (c.dropN n hn).vlctx.toCtx + (c.mkLambda' n hn e') (c.mkForall' n hn ty') := by + induction n generalizing c e e' ty' nds with + | zero => exact ⟨H1, H2⟩ + | succ n ih => + match c with + | .vlam x name ty ty' bi c => + let ⟨h1, _, h3, _, h4⟩ := wf; let _ :: _ := nds + refine ih h1 ?_ (.lam h4 H2) .. + exact .lam ⟨_, h4⟩ h3 (.abstract .zero H1) + | .vlet x name ty val ty' val' c => + let ⟨h1, _, h3, h4, h5⟩ := wf; let _ :: _ := nds + refine ih h1 ?_ H2 ..; dsimp [mkLetArg]; split <;> [skip; split] + · exact .letE h5 h3 h4 (.abstract .zero H1) + · exact .letE h5 h3 h4 (.abstract .zero H1) + · rename_i h _ _; simp at h + rw [Expr.lowerLooseBVars_eq_instantiate h (v := val)] + exact .inst_let henv (.abstract .zero H1) h4 + +theorem MLCtx.fvarRevList_prefix (c : MLCtx) + {n hn} : c.fvarRevList n hn <+: c.vlctx.fvars := by + induction n generalizing c with + | zero => simp + | succ n ih => match c with | .vlam .. | .vlet .. => simp [ih] + +theorem MLCtx.WF.fvars_nodup : ∀ {c : MLCtx}, c.WF env Us → c.vlctx.fvars.Nodup + | .nil, _ => .nil + | .vlam _ _ _ _ _ c, ⟨h1, h2, _⟩ + | .vlet _ _ _ _ _ _ c, ⟨h1, h2, _⟩ => by simp [h1.fvars_nodup, h1.tr.find?_eq_none.1 h2] + +theorem MLCtx.WF.fvarRevList_nodup {c : MLCtx} (wf : c.WF env Us) + (n hn) : (c.fvarRevList n hn).Nodup := + c.fvarRevList_prefix.sublist.nodup wf.fvars_nodup + +theorem MLCtx.WF.decls_size {c : MLCtx} (wf : c.WF env Us) : + c.lctx.decls.size = c.length := by + rw [← wf.tr.1.decls_wf.toList'_length] + induction c with + | nil => rfl + | vlam _ _ _ _ _ _ ih => simp [lctx, LocalContext.mkLocalDecl, ih wf.1] + | vlet _ _ _ _ _ _ _ ih => simp [lctx, LocalContext.mkLetDecl, ih wf.1] + +theorem MLCtx.WF.toList_eq {c : MLCtx} (wf : c.WF env Us) : + c.lctx.toList = c.decls := by + simp [LocalContext.toList] + induction c with + | nil => rfl + | vlam _ _ _ _ _ _ ih => simp [lctx, LocalContext.mkLocalDecl, decls, ih wf.1, wf.1.decls_size] + | vlet _ _ _ _ _ _ _ ih => simp [lctx, LocalContext.mkLetDecl, decls, ih wf.1, wf.1.decls_size] + +theorem MLCtx.WF.find?_eq {c : MLCtx} (wf : c.WF env Us) : + c.lctx.find? x = c.decls.find? (x == ·.fvarId) := by + simp [wf.tr.1.find?_eq_find?_toList, wf.toList_eq] + +inductive MLCtx.PartialForall : MLCtx → Nat → List FVarId → Expr → Prop where + | nil : PartialForall c 0 [] e + | vlam : PartialForall c n fvs (.forallE x ty (.abstract1 fv e) bi) → + PartialForall (c.vlam fv x ty ty' bi) (n+1) (fv :: fvs) e + | vlet : PartialForall c n fvs ( + let e' := Expr.abstract1 fv e + if e'.hasLooseBVar' 0 then .letE x ty v e' false + else e'.lowerLooseBVars' 1 1) → + PartialForall (c.vlet fv x ty v ty' v') (n+1) (fv :: fvs) e + | skip : e.looseBVarRange' = 0 → e' = Expr.abstract1 fv e → e'.hasLooseBVar' 0 = false → + PartialForall c n fvs e → + PartialForall (c.vlet fv x ty v ty' v') (n+1) fvs e + +theorem MLCtx.PartialForall.full : MLCtx.PartialForall c n (c.fvarRevList n hn) e := by + induction n generalizing c e with + | zero => exact .nil + | succ n ih => match c with | .vlam .. | .vlet .. => constructor; apply ih + +theorem MLCtx.PartialForall.sublist (H : MLCtx.PartialForall c n l e) : l <+ c.vlctx.fvars := by + induction H with + | nil => simp + | vlam _ ih | vlet _ ih => simp [ih] + | skip _ _ _ _ ih => exact ih.trans (List.sublist_cons_self ..) + +theorem MLCtx.WF.mkForall_partial {c : MLCtx} (wf : c.WF env Us) (n hn) + (harr : arr.toList.reverse = l.map .fvar) (hp : MLCtx.PartialForall c n l e) : + c.lctx.mkForall arr e = c.mkForall n hn e := by + have := congrArg (Array.mk ·.reverse) harr; simp at this + rw [LocalContext.mkForall, this, ← List.map_reverse, LocalContext.mkBinding_eq, + LocalContext.mkBindingList_eq_fold, List.foldr_reverse] + · clear harr this + induction hp with + | nil => simp + | vlam hp ih | vlet hp ih => + simp + refine (List.foldl_congr fun _ y h => ?_).trans <| + .trans (congrFun (congrArg _ ?_) _) (ih wf.1 _) + · refine LocalContext.mkBindingList1_congr ?_ + rw [wf.find?_eq, wf.1.find?_eq, decls, List.find?, (?_ : (y == _) = false)] + simp [LocalDecl.fvarId]; rintro ⟨⟩ + have := (List.cons_sublist_cons.2 hp.sublist).nodup wf.fvars_nodup; simp_all + · simp [LocalContext.mkBindingList1, wf.find?_eq, decls, LocalDecl.fvarId] + | skip h1 h2 h3 hp ih => + subst h2; simp [h3] + rw [Expr.lowerLooseBVars_eq_instantiate h3 (v := default), + Expr.abstract1_eq_liftLooseBVars h3, Expr.liftLooseBVars_eq_self (by simp [h1]), + Expr.instantiate1_eq_self h1] + refine (List.foldl_congr fun _ y h => ?_).trans (ih wf.1 _) + refine LocalContext.mkBindingList1_congr ?_ + rw [wf.find?_eq, wf.1.find?_eq, decls, List.find?, (?_ : (y == _) = false)] + simp [LocalDecl.fvarId]; rintro ⟨⟩ + have := (List.cons_sublist_cons.2 hp.sublist).nodup wf.fvars_nodup; simp_all + · intro _ h + exact wf.tr.find?_eq_some.2 (hp.sublist.subset (List.mem_reverse.1 h)) + · exact List.nodup_reverse.2 (hp.sublist.nodup wf.fvars_nodup) + +theorem MLCtx.WF.mkForall_eq {c : MLCtx} (wf : c.WF env Us) (n hn) + (harr : arr.toList.reverse = (c.fvarRevList n hn).map .fvar) : + c.lctx.mkForall arr e = c.mkForall n hn e := mkForall_partial wf n hn harr .full + +theorem MLCtx.WF.mkLambda_eq {c : MLCtx} (wf : c.WF env Us) (n hn) + (harr : arr.toList.reverse = (c.fvarRevList n hn).map .fvar) : + c.lctx.mkLambda arr e = c.mkLambda n hn e := by + have := congrArg (Array.mk ·.reverse) harr; simp at this + rw [LocalContext.mkLambda, this, ← List.map_reverse, LocalContext.mkBinding_eq, + LocalContext.mkBindingList_eq_fold, List.foldr_reverse] + · clear harr this + induction n generalizing c e with + | zero => simp + | succ n ih => + match c with + | .vlam .. | .vlet .. => + simp + refine (List.foldl_congr fun _ y h => ?_).trans <| + .trans (congrFun (congrArg _ ?_) _) (ih wf.1 _) + · refine LocalContext.mkBindingList1_congr ?_ + rw [wf.find?_eq, wf.1.find?_eq, decls, List.find?, (?_ : (y == _) = false)] + simp [LocalDecl.fvarId]; rintro ⟨⟩ + have := wf.fvarRevList_nodup (n+1) hn; simp_all + · simp [LocalContext.mkBindingList1, wf.find?_eq, decls, LocalDecl.fvarId] + · intro _ h + exact wf.tr.find?_eq_some.2 ((MLCtx.fvarRevList_prefix ..).subset (List.mem_reverse.1 h)) + · exact List.nodup_reverse.2 (wf.fvarRevList_nodup ..) + +namespace Inner + +/-- A successful host-environment lookup returns exactly the constant found +at the requested name. Kept in the common checker layer so both inference +and WHNF reduction can consume the same lookup certificate. -/ +theorem envGet.WF {c : VContext} : + (c.env.get name).WF fun ci => c.env.find? name = some ci := by + simp [Environment.get]; split <;> [refine .pure ‹_›; exact .throw] + +theorem whnf.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (whnf e) fun e₁ _ => c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := + fun _ wf => wf.whnf he + +theorem isDefEqCore.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEqCore e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := + fun _ wf => wf.isDefEqCore he₁ he₂ + +theorem cacheSuccess.WF {c : VContext} {s : VState} (he₁ : c.TrExprS e₁ e') (he₂ : c.TrExpr e₂ e') : + RecM.WF c s (cacheSuccess e₁ e₂) fun _ _ => True := by + rintro _ mwf wf _ _ ⟨⟩ + let ⟨_, _, a1, a2, ewf, a4⟩ := wf.ectx + refine ⟨{ s with toState := _ }, rfl, .rfl, { wf with ectx := ⟨_, _, a1, a2, ?_, a4⟩ }, trivial⟩ + -- The insertion is keyed on the two hashes, so either order can be the one recorded. + have H : DefEqCache.IsDefEqE c.venv c.lparams _ e₁ e₂ := + ⟨_, he₁.weakFV' c.Ewf a2 a1, he₂.weakFV' c.Ewf a2 a1⟩ + simp only []; split <;> [exact ewf.insert H; exact ewf.insert H.symm] + +theorem isDefEq.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEq e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := by + unfold isDefEq + split + · rename_i heq + exact .pure fun _ => (he₁.eqv heq).uniq c.Ewf (.refl c.Ewf c.Δwf) he₂ + simp only [] + refine (isDefEqCore.WF he₁ he₂).bind fun b _ _ hb => ?_ + simp; split + · exact (cacheSuccess.WF he₁ ⟨_, he₂, (hb ‹_›).symm⟩).map fun _ _ _ _ => hb + · exact .pure hb + +theorem inferType.WF' {c : VContext} {s : VState} (h1 : e.FVarsIn (· ∈ c.vlctx.fvars)) + (hinf : inferOnly = true → ∃ e', c.TrExprS e e') : + RecM.WF c s (inferType e inferOnly) fun ty _ => ∃ e' ty', c.TrTyping e ty e' ty' := + fun _ wf => wf.inferType h1 hinf + +theorem inferType.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (inferType e true) fun ty _ => ∃ ty', c.TrTyping e ty e' ty' := by + refine .stateWF fun wf => ?_ + refine (inferType.WF' he.fvarsIn fun _ => ⟨_, he⟩).le + fun _ _ _ ⟨_, _, h1, h2, h3, h4⟩ => ⟨_, h1, he, h3, ?_⟩ + have := h2.uniq c.Ewf (.refl c.Ewf c.Δwf) he + exact h4.defeqU_l c.Ewf c.Δwf this + +theorem inferType.WF_uniq {c : VContext} {s : VState} + (he : c.TrExprS e e') (hty : c.HasType e' ty') : + RecM.WF c s (inferType e true) fun ty _ => c.TrExpr ty ty' := + (inferType.WF he).le fun _ _ _ ⟨_, _, _, h1, h2⟩ => + ⟨_, h1, h2.uniqU c.Ewf c.Δwf hty⟩ + +theorem checkType.WF {c : VContext} {s : VState} (h1 : e.FVarsIn (· ∈ c.vlctx.fvars)) : + RecM.WF c s (inferType e false) fun ty _ => ∃ e' ty', c.TrTyping e ty e' ty' := + inferType.WF' h1 nofun + +theorem whnfCore.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (whnfCore e cheapProj) fun e₁ _ => c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := + fun _ wf => wf.whnfCore he + +theorem isDelta_is_some : isDelta env e = some ci ↔ + ∃ n, env.find? n = some ci ∧ (∃ v, ci.deltaValue? = some v) ∧ + ∃ ls, e.getAppFn = .const n ls ∧ ls.length = ci.numLevelParams := by + simp only [isDelta] + split <;> [split <;> [split; skip]; skip] <;> + simp_all [Option.isSome_iff_exists] <;> grind + +def UnfoldDefinition.WF (c : VContext) (e e₀ : Expr) (e' : VExpr) : Option Expr → Prop + | some e₁ => c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' + | none => ∀ {{n ci v ls}}, c.env.find? n = some ci → ci.deltaValue? = some v → + e₀ = .const n ls → ls.length = ci.numLevelParams → False + +theorem unfoldDefinitionCore.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (unfoldDefinitionCore e) fun oe _ => UnfoldDefinition.WF c e e e' oe := by + dsimp [unfoldDefinitionCore] + split <;> [refine .getEnv ?_; (rename_i H; exact .pure fun _ _ _ _ _ _ h => nomatch H _ _ h)] + split; rotate_left + · rename_i H; refine .pure ?_; rintro _ _ _ _ h1 h2 ⟨⟩ hlen + cases H _ (isDelta_is_some.2 ⟨_, h1, ⟨_, h2⟩, _, rfl, hlen⟩) + rename_i n ls oci ci h1 + obtain ⟨_, h3, ⟨_, h4⟩, _, ⟨⟩, hlen⟩ := isDelta_is_some.1 h1 + have : UnfoldDefinition.WF c (.const n ls) (.const n ls) e' + (some (instantiateDeltaValue ci ls)) := by + let .const a1 a2 a3 := he + have ⟨rfl, b1, b2, b3⟩ := c.trenv.find?_uniq h3 a1 + simp [instantiateDeltaValue, h4] + have c1 := c.trenv.of_value h3 b1 h4 |>.instL c.Ewf (by trivial) a2 (b2.trans a3.symm) + have := c1.weakFV c.Ewf (.from_nil c.mlctx.noBV) c.Δwf + rw [c1.wf.closedN c.Ewf trivial |>.liftN_eq (Nat.zero_le _)] at this + simp [VExpr.instL] at this; rw [VLevel.inst_map_id] at this + · exact ⟨fun _ _ _ => c1.fvarsIn.mono nofun, this⟩ + · exact (List.mapM_eq_some.1 a2).length_eq.symm.trans <| a3.trans b2.symm + split <;> [rename_i h5; exact .pure this] + refine .pureBind <| .get ?_ + split <;> [rename_i eq; skip] + · refine .stateWF fun wf => .pure ?_ + obtain ⟨_, _, _, ⟨⟩, a1, rfl⟩ := wf.unfold_wf eq + cases h3.symm.trans a1; exact this + · refine .bind (Q := fun _ _ => True) ?_ fun _ _ _ _ => .pure this + rintro _ mwf wf _ _ ⟨⟩ + refine ⟨{ s with toState := _ }, rfl, .rfl, { wf with unfold_wf := ?_ }, ⟨⟩⟩ + intro e e'; simp only [Std.HashMap.getElem?_insert] + split <;> [rintro ⟨⟩; exact (wf.unfold_wf ·)] + rename_i eq; rw [BEq.comm, Expr.eqv_const] at eq + exact ⟨_, _, _, eq, h3, rfl⟩ + +theorem unfoldDefinition.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (unfoldDefinition e) fun oe _ => UnfoldDefinition.WF c e e.getAppFn e' oe := by + simp [unfoldDefinition]; split; rotate_left + · rename_i h; refine (unfoldDefinitionCore.WF he).mono fun _ _ _ H => ?_ + rwa [show e.getAppFn = e by revert h; unfold Expr.isApp Expr.getAppFn; split <;> simp] + have ⟨f', stk⟩ := AppStack.build (e.mkAppList_getAppArgsList ▸ he) + refine (unfoldDefinitionCore.WF stk.tr).bind fun oe _ _ H => ?_ + cases oe <;> [exact .pure H; refine .pure ?_] + have ⟨h1, h2⟩ := H + rw [Expr.mkAppRevRange_eq (l₁ := []) (l₂ := e.getAppArgsRevList) (l₃ := []) + (by simp [Expr.getAppRevArgs_toList]) (by rfl) (by simp [Expr.getAppRevArgs_eq])] + simp only [Expr.getAppArgsRevList_reverse]; constructor + · exact (e.mkAppList_getAppArgsList ▸ h1.mkAppList :) + · exact h2.rebuild_mkAppList c.Ewf c.Δwf stk.tr (e.mkAppList_getAppArgsList ▸ he :) + +theorem ensureSortCore.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (ensureSortCore e e₀) fun e1 _ => + (∃ u, e1 = .sort u) ∧ c.TrExpr e1 e' ∧ c.FVarsBelow e e1 := by + simp [ensureSortCore]; split + · let .sort _ := e + exact .pure ⟨⟨_, rfl⟩, he.trExpr c.Ewf c.Δwf, .rfl⟩ + refine (whnf.WF he).bind fun e _ _ ⟨hb, he⟩ => ?_; split + · let .sort _ := e + exact .pure ⟨⟨_, rfl⟩, he, hb⟩ + exact .getEnv <| .getLCtx .throw + +theorem getSortLevel.WF + (he : c.TrExprS e e') : (getSortLevel e).WF c s fun l _ => + ∃ u', VLevel.ofLevel c.lparams l = some u' ∧ c.HasType e' (.sort u') := by + refine (inferType.WF he).bind fun ty _ le ⟨ty', _, _, h1, h2⟩ => ?_ + refine (ensureSortCore.WF h1).bind fun ty _ le h => ?_ + obtain ⟨⟨u, rfl⟩, ⟨ty₂, h3, h4⟩, _⟩ := h + let .sort hu := h3 + exact .pure ⟨_, hu, h2.defeqU_r c.Ewf c.Δwf h4.symm⟩ + +theorem isProp.WF + (he : c.TrExprS e e') : (isProp e).WF c s fun b _ => + b → c.HasType e' (.sort .zero) := by + refine (getSortLevel.WF he).bind fun l _ le ⟨u', hu, h⟩ => .pure fun H => ?_ + exact h.defeqU_r c.Ewf c.Δwf + ⟨_, .sortDF (.of_ofLevel hu) trivial (ofLevel_isAlwaysZero hu H)⟩ diff --git a/Ix/Theory/Named/Verify/TypeChecker/InferType.lean b/Ix/Theory/Named/Verify/TypeChecker/InferType.lean new file mode 100644 index 000000000..a16d77f19 --- /dev/null +++ b/Ix/Theory/Named/Verify/TypeChecker/InferType.lean @@ -0,0 +1,1082 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Ix.Theory.Named.Verify.TypeChecker.Reduce + +open Ix.Theory (VLevel) + +open Ix.Theory.Named + +namespace Ix.Theory.Named.TypeChecker.Inner +open Lean hiding Environment Exception +open Kernel + +theorem ensureForallCore.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (ensureForallCore e e₀) fun e1 _ => c.FVarsBelow e e1 ∧ + c.TrExpr e1 e' ∧ ∃ name ty body bi, e1 = .forallE name ty body bi := by + simp [ensureForallCore]; split + · let .forallE .. := e + exact .pure ⟨.rfl, he.trExpr c.Ewf c.Δwf, _, _, _, _, rfl⟩ + refine (whnf.WF he).bind fun e _ _ ⟨hb, he⟩ => ?_; split + · let .forallE .. := e + exact .pure ⟨hb, he, _, _, _, _, rfl⟩ + exact .getEnv <| .getLCtx .throw + +theorem ensureForallCore.WF' {c : VContext} {s : VState} (he : c.TrExpr e e') : + RecM.WF c s (ensureForallCore e e₀) fun e1 _ => c.FVarsBelow e e1 ∧ + c.TrExpr e1 e' ∧ ∃ name ty body bi, e1 = .forallE name ty body bi := + let ⟨_, he, eq⟩ := he + (ensureForallCore.WF he).mono fun _ _ _ ⟨h1, h2, h3⟩ => + ⟨h1, h2.defeq c.Ewf c.Δwf eq, h3⟩ + +theorem checkLevel.WF {c : VContext} (H : l.hasMVar' = false) : + (checkLevel c.toContext l).WF fun _ => ∃ u', VLevel.ofLevel c.lparams l = some u' := by + simp [checkLevel]; split <;> [exact .throw; refine .pure ?_] + exact Level.getUndefParam_none H (by rename_i h; simpa using h) + +theorem inferFVar.WF {c : VContext} : + (inferFVar c.toContext name).WF fun ty => ∃ e' ty', c.TrTyping (.fvar name) ty e' ty' := by + simp [inferFVar, ← c.lctx_eq]; split <;> [refine .pure ?_; exact .throw] + rename_i decl h + rw [c.trlctx.1.find?_eq_find?_toList] at h + have := List.find?_some h; simp at this; subst this + let ⟨e', ty', h1, _, h2, _, h3⟩ := + c.trlctx.find?_of_mem c.Ewf (List.mem_of_find?_eq_some h) + exact ⟨_, _, h2, .fvar h1, h3, c.Δwf.find?_wf c.Ewf h1⟩ + +theorem inferConstant.WF {c : VContext} + (H : ∀ l ∈ ls, l.hasMVar' = false) + (hinf : inferOnly = true → ∃ e', c.TrExprS (.const name ls) e') : + (inferConstant c.toContext name ls inferOnly).WF fun ty => + ∃ e' ty', c.TrTyping (.const name ls) ty e' ty' := by + simp [inferConstant]; refine envGet.WF.bind fun ci eq1 => ?_ + have : (ls.foldlM (fun b a => checkLevel c.toContext a) PUnit.unit).WF fun _ => + ∃ ls', ls.Forall₂ (VLevel.ofLevel c.lparams · = some ·) ls' := by + clear hinf + induction ls with + | nil => exact .pure ⟨_, .nil⟩ + | cons l ls ih => + simp at H + refine (checkLevel.WF H.1).bind fun ⟨⟩ ⟨_, h1⟩ => ?_ + exact (ih H.2).le fun _ ⟨_, h2⟩ => ⟨_, .cons h1 h2⟩ + split <;> [rename_i h1; exact .throw] + have main {e'} (he : c.TrExprS (.const name ls) e') : ∃ e' ty', + c.TrTyping (.const name ls) (ci.instantiateTypeLevelParams ls) e' ty' := by + let .const h4 H' eq := id he + have ⟨_, _, h5, h6⟩ := c.trenv.find?_uniq eq1 h4 + have H := List.mapM_eq_some.1 H' + have s0 := h6.instL c.Ewf (Δ := []) trivial H' (h5.trans eq.symm) + have s1 := s0.weakFV c.Ewf (.from_nil c.mlctx.noBV) c.Δwf + rw [(c.Ewf.ordered.closedC h4).instL.liftN_eq (Nat.le_refl _)] at s1 + have ⟨_, s1, s2⟩ := s1 + refine ⟨_, _, ?_, he, s1, .defeqU_r c.Ewf c.Δwf s2.symm ?_⟩ + · intro _ _ _; exact s0.fvarsIn.mono nofun + · exact .const h4 (.of_mapM_ofLevel H') (H.length_eq.symm.trans eq) + split + · split <;> [exact .throw; rename_i h2] + generalize eq1 : _ <$> (_ : Except Exception _) = F + generalize eq2 : (fun ty : Expr => _) = P + suffices ci.isPartial = false ∨ c.safety ≠ .safe → F.WF P by + split <;> [skip; exact this (.inl (ConstantInfo.isPartial.eq_2 _ ‹_›))] + split <;> [exact .throw; apply this] + rename_i h; simpa [Decidable.or_iff_not_imp_left, ConstantInfo.isPartial] using h + subst eq1 eq2; intro h3 + refine this.map fun _ ⟨_, H⟩ => ?_ + have ⟨_, h4, _, h5, h6⟩ := c.trenv.find? eq1 <| by + revert h2 h3 + simp [ConstantInfo.safety] + split <;> simp +contextual [*] + split <;> simp [DefinitionSafety.le_safe, *] + cases c.safety <;> decide + have eq := h1.symm.trans h5 + exact main (.const h4 (List.mapM_eq_some.2 H) eq) + · simp_all; let ⟨_, h⟩ := hinf; refine .pure (main h) + +theorem inferLambda.loop.WF {c : VContext} {e₀ : Expr} + {m} [mwf : c.MLCWF m] {n} (hn : n ≤ m.length) + (hdrop : m.dropN n hn = c.mlctx) + (harr : arr.toList.reverse = (m.fvarRevList n hn).map .fvar) + (he₀ : e₀ = m.mkLambda n hn ei) + (hei : e.instantiateList ((m.fvarRevList n hn).map .fvar) = ei) + (hbelow : ∀ P, IsFVarUpSet P c.vlctx → FVarsIn P e₀ → + IsFVarUpSet (AllAbove c.vlctx P) m.vlctx ∧ FVarsIn (AllAbove c.vlctx P) ei ∧ + ∀ ty, FVarsIn (AllAbove c.vlctx P) ty → FVarsIn (AllAbove c.vlctx P) (m.mkForall n hn ty)) + (hr : e.FVarsIn (· ∈ m.vlctx.fvars)) + (hinf : inferOnly = true → ∃ e', (c.withMLC m).TrExprS ei e') : + (inferLambda.loop inferOnly arr e).WF (c.withMLC m) s fun ty _ => + ∃ e' ty', c.TrTyping e₀ ty e' ty' := by + unfold inferLambda.loop + generalize eqfvs : (m.fvarRevList n hn).map Expr.fvar = fvs at * + simp [harr, -bind_pure_comp]; split + · rename_i name dom body bi + generalize eqF : withLocalDecl (m := RecM) _ _ _ _ = F + generalize eqP : (fun ty x => ∃ _, _) = P + rw [Expr.instantiateList_lam] at hei; subst ei + have main {s₁} (le₁ : s ≤ s₁) {dom'} + (domty : (c.withMLC m).venv.IsType + (c.withMLC m).lparams.length (c.withMLC m).vlctx.toCtx dom') + (hdom : (c.withMLC m).TrExprS (dom.instantiateList fvs) dom') + (hbody : inferOnly = true → ∃ body', + TrExprS c.venv c.lparams ((none, .vlam dom') :: m.vlctx) + (body.instantiateList fvs 1) body') : + F.WF (c.withMLC m) s₁ P := by + refine .stateWF fun wf => ?_ + have hdom' := hdom.trExpr c.Ewf mwf.1.tr.wf + subst eqF eqP + refine .withLocalDecl hdom domty le₁ fun a mwf' s' le₂ res => ?_ + have eq := @Expr.instantiateList_instantiate1_comm body fvs (.fvar a) (by trivial) + refine inferLambda.loop.WF (Nat.succ_le_succ hn) (by simp [hdrop]) + (by simp [← eqfvs, harr]) ?_ (by simp; rfl) ?_ (hr.2.mono fun _ => .tail _) ?_ + · rw [he₀, eqfvs, ← eq]; simp; congr 2 + refine (FVarsIn.abstract_instantiate1 ((hr.2.instantiateList ?_ _).mono ?_)).symm + · simp [← eqfvs, FVarsIn]; exact m.fvarRevList_prefix.subset + · rintro _ h rfl; exact (mwf'.1.tr.wf.2.1 _ _ rfl).1 h + · intro P hP he + have ⟨h1, h2, h3⟩ := hbelow _ hP he + refine ⟨⟨h1, fun _ => (fvarsIn_iff.1 h2.1).1⟩, ?_, fun ty hty => h3 _ ⟨h2.1, hty.abstract1⟩⟩ + rw [eqfvs, ← eq] + refine h2.2.instantiate1 fun h => ?_ + exact res.elim (wf.ngen_wf _ (m.dropN_fvars_subset n hn (hdrop ▸ h))) + · intro h; let ⟨_, hbody⟩ := hbody h + exact eqfvs.symm ▸ eq ▸ ⟨_, hbody.inst_fvar c.Ewf.ordered mwf'.1.tr.wf⟩ + split + · subst inferOnly + refine (checkType.WF ?_).bind fun uv _ le ⟨dom', uv', _, h1, h2, h3⟩ => ?_ + · apply hr.1.instantiateList; simp [← eqfvs]; exact m.fvarRevList_prefix.subset + refine (ensureSortCore.WF h2).bind_le le fun _ _ le ⟨h4, h5, _⟩ => ?_ + obtain ⟨_, rfl⟩ := h4; let ⟨_, .sort _, h5⟩ := h5 + have domty := h3.defeqU_r c.Ewf mwf.1.tr.wf.toCtx h5.symm + have domty' : (c.withMLC m).IsType dom' := ⟨_, domty⟩ + exact main le domty' h1 nofun + · simp_all; let ⟨_, h1⟩ := hinf + have .lam (ty' := dom') (body' := body') domty hdom hbody := h1 + exact main .rfl domty hdom _ hbody + · subst ei + refine (inferType.WF' ?_ hinf).bind fun ty _ _ ⟨e', ty', hb, h1, h2, h3⟩ => ?_ + · apply hr.instantiateList; simp [← eqfvs]; exact m.fvarRevList_prefix.subset + refine .stateWF fun wf => .getLCtx <| .pure ?_ + have ⟨_, h2', e2⟩ := h2.trExpr c.Ewf.ordered wf.trctx.wf + |>.cheapBetaReduce c.Ewf wf.trctx.wf m.noBV + have h3 := h3.defeqU_r c.Ewf mwf.1.tr.wf.toCtx e2.symm + let ⟨h1', h2''⟩ := mwf.1.mkLambda_trS c.Ewf h1 h3 n hn + have h3' := (mwf.1.mkForall_trS c.Ewf h2' (h3.isType c.Ewf mwf.1.tr.wf.toCtx) n hn).1 + simp [hdrop] at h1' h2'' h3' + refine mwf.1.mkForall_eq _ _ (eqfvs ▸ harr) ▸ + ⟨_, _, fun P hP he => ?_, he₀ ▸ h1', h3', h2''⟩ + have ⟨c1, c2, c3⟩ := hbelow _ hP he + have := c3 _ <| FVarsBelow.cheapBetaReduce (m.noBV ▸ h2.closed) _ c1 <| hb _ c1 c2 + exact this.mp (fun _ => id) h3'.fvarsIn + +theorem inferLambda.WF + (h1 : e.FVarsIn (· ∈ c.vlctx.fvars)) + (hinf : inferOnly = true → ∃ e', c.TrExprS e e') : + (inferLambda e inferOnly).WF c s fun ty _ => ∃ e' ty', c.TrTyping e ty e' ty' := by + refine .stateWF fun wf => ?_ + refine (c.withMLC_self ▸ inferLambda.loop.WF (Nat.zero_le _) rfl rfl rfl rfl ?_ h1) hinf + exact fun P hP he => ⟨(AllAbove.wf wf.trctx.wf.fvwf).2 hP, he.mono fun _ h _ => h, fun _ => id⟩ + +theorem inferForall.loop.WF {c : VContext} {e₀ : Expr} + {m} [mwf : c.MLCWF m] {n} (hn : n ≤ m.length) + (hdrop : m.dropN n hn = c.mlctx) + (harr : arr.toList.reverse = (m.fvarRevList n hn).map .fvar) + (he₀ : e₀ = m.mkForall n hn ei) + (hei : e.instantiateList ((m.fvarRevList n hn).map .fvar) = ei) + (hr : e.FVarsIn (· ∈ m.vlctx.fvars)) + (hus : us.toList.reverse.Forall₂ (VLevel.ofLevel c.lparams · = some ·) us') + (hΔ : m.vlctx.SortList c.venv c.lparams.length us') + (hlen : us'.length = n) + (hinf : inferOnly = true → ∃ e', (c.withMLC m).TrExprS ei e') : + (inferForall.loop inferOnly arr us e).WF (c.withMLC m) s fun ty _ => + ∃ e' u, c.TrTyping e₀ ty e' (.sort u) := by + unfold inferForall.loop + generalize eqfvs : (m.fvarRevList n hn).map Expr.fvar = fvs at * + simp [harr, -bind_pure_comp]; split + · rename_i name dom body bi + rw [Expr.instantiateList_forallE] at hei; subst ei + refine (inferType.WF' ?_ ?_).bind fun uv _ le ⟨dom', uv', _, h1, h2, h3⟩ => ?_ + · apply hr.1.instantiateList; simp [← eqfvs]; exact m.fvarRevList_prefix.subset + · intro h; let ⟨_, .forallE _ _ h _⟩ := hinf h; exact ⟨_, h⟩ + refine (ensureSortCore.WF h2).bind_le le fun _ _ le ⟨h4, h5, _⟩ => ?_ + obtain ⟨_, rfl⟩ := h4; let ⟨_, .sort h4, h5⟩ := h5 + refine .stateWF fun wf => ?_ + have domty := h3.defeqU_r c.Ewf mwf.1.tr.wf.toCtx h5.symm + have domty' : (c.withMLC m).IsType dom' := ⟨_, domty⟩ + refine .withLocalDecl h1 domty' le fun a mwf' s' le₂ res => ?_ + have eq := @Expr.instantiateList_instantiate1_comm body fvs (.fvar a) (by trivial) + refine inferForall.loop.WF (Nat.succ_le_succ hn) (by simp [hdrop]) + (by simp [eqfvs, harr]) ?_ (by simp [eqfvs]; rfl) (hr.2.mono fun _ => .tail _) + (by simpa using ⟨h4, hus⟩) (.cons hΔ domty) (by simp [hlen]) ?_ + · simp [he₀, ← eq]; congr 2 + refine (FVarsIn.abstract_instantiate1 ((hr.2.instantiateList ?_ _).mono ?_)).symm + · simp [← eqfvs, FVarsIn]; exact m.fvarRevList_prefix.subset + · rintro _ h rfl; exact (mwf'.1.tr.wf.2.1 _ _ rfl).1 h + · intro h; let ⟨_, .forallE (body' := body') _ _ hdom₁ hbody₁⟩ := hinf h + refine have hΔ := .refl c.Ewf mwf.1.tr.wf; have H := hdom₁.uniq c.Ewf hΔ h1; ?_ + have H := H.of_r c.Ewf mwf.1.tr.wf.toCtx domty + have ⟨_, hbody₂⟩ := hbody₁.defeqDFC c.Ewf <| .cons hΔ (ofv := none) nofun (.vlam H) + exact eq ▸ ⟨_, hbody₂.inst_fvar c.Ewf.ordered mwf'.1.tr.wf⟩ + · subst ei; refine (inferType.WF' ?_ hinf).bind fun ty _ _ ⟨e', ty', _, h1, h2, h3⟩ => ?_ + · apply hr.instantiateList; simp [← eqfvs]; exact m.fvarRevList_prefix.subset + refine (ensureSortCore.WF h2).bind fun _ _ le₂ ⟨h4, h5, _⟩ => ?_ + obtain ⟨_, rfl⟩ := h4; let ⟨_, .sort (u' := u') h4, h5⟩ := h5 + obtain ⟨us, rfl⟩ : ∃ l, ⟨List.reverse l⟩ = us := ⟨us.toList.reverse, by simp⟩ + simp [Expr.sortLevel!] at hus ⊢ + have h3 := h3.defeqU_r c.Ewf mwf.1.tr.wf.toCtx h5.symm + let ⟨h1', h2'⟩ := mwf.1.mkForall_trS c.Ewf h1 ⟨_, h3⟩ n hn + have ⟨_, h3', h4'⟩ := mkForall_hasType hus hΔ h4 h3 n hn (hus.length_eq.trans hlen) + simp [hdrop] at h1' h2' h4' + refine have h := .sort h3'; .pure ⟨_, _, fun _ _ _ => h.fvarsIn, he₀ ▸ h1', h, h4'⟩ + +theorem inferForall.WF + (hr : e.FVarsIn (· ∈ c.vlctx.fvars)) + (hinf : inferOnly = true → ∃ e', c.TrExprS e e') : + (inferForall e inferOnly).WF c s fun ty _ => ∃ e' u, c.TrTyping e ty e' (.sort u) := + (c.withMLC_self ▸ inferForall.loop.WF (Nat.zero_le _) rfl rfl rfl rfl hr .nil .nil rfl) hinf + +theorem inferApp.loop.WF {c : VContext} {s : VState} + {ll lm lr : List _} + (stk : AppStack c.venv c.lparams c.vlctx (.mkAppRevList e lm) e' lr) + (hbelow : FVarsBelow c.vlctx e fType) + (hfty : c.TrExpr (fType.instantiateList lm) fty') (hety : c.HasType e' fty') + (hargs : args = ll ++ lm.reverse ++ lr) + (hj : j = ll.length) (hi : i = ll.length + lm.length) : + RecM.WF c s (inferApp.loop e₀ ⟨args⟩ fType j i) fun ty _ => + ∃ e₁' ty', c.TrTyping (e.mkAppRevList lm |>.mkAppList lr) ty e₁' ty' := by + subst i j; rw [inferApp.loop.eq_def] + simp [hargs, Expr.instantiateList_reverse] + have henv := c.Ewf; have hΔ := c.Δwf + cases lr with simp + | cons a lr => + let .app hf' ha' hf ha stk := stk + have uf := hf'.uniqU henv hΔ hety + split + · rw [Expr.instantiateList_forallE] at hfty + let ⟨_, .forallE _ _ hty hbody, h3⟩ := hfty + have ⟨⟨_, uA⟩, _, uB⟩ := h3.trans henv hΔ uf.symm |>.forallE_inv henv hΔ + refine inferApp.loop.WF (lm := a::lm) stk ?_ ?_ (.app hf' ha') (by simp) rfl rfl + · exact fun _ hP he => (hbelow _ hP he).2 + have ha0 := c.mlctx.noBV ▸ ha.closed + simp [← Expr.instantiateList_instantiate1_comm ha0.looseBVarRange_zero] + exact .inst henv hΔ (ha'.defeqU_r henv hΔ ⟨_, uA.symm⟩) ⟨_, hbody, _, uB⟩ (ha.trExpr henv hΔ) + · simp [Nat.add_sub_cancel_left, Expr.instantiateRevList_reverse] + refine (ensureForallCore.WF' hfty).bind fun _ _ _ ⟨hb, ⟨_, h2, h3⟩, eq⟩ => ?_ + obtain ⟨name, ty, body, bi, rfl⟩ := eq; simp [Expr.bindingBody!] + let .forallE _ _ hty hbody := h2 + have ⟨⟨_, uA⟩, _, uB⟩ := h3.trans henv hΔ uf.symm |>.forallE_inv henv hΔ + refine inferApp.loop.WF (ll := ll ++ lm.reverse) (lm := [a]) stk ?_ ?_ + (.app hf' ha') (by simp) (by simp) (by simp) + · intro _ hP he + have ⟨he, hlm⟩ := FVarsIn.appRevList.1 he + exact (hb _ hP <| (hbelow _ hP he).instantiateList hlm).2 + exact .inst henv hΔ (ha'.defeqU_r henv hΔ ⟨_, uA.symm⟩) ⟨_, hbody, _, uB⟩ (ha.trExpr henv hΔ) + | nil => + rw [← List.length_reverse, List.take_length, Expr.instantiateRevList_reverse] + have ⟨_, hfty, h2⟩ := hfty + refine .pure ⟨_, _, fun _ hP he => ?_, stk.tr, hfty, hety.defeqU_r henv hΔ h2.symm⟩ + have ⟨he, hlm⟩ := FVarsIn.appRevList.1 he + exact (hbelow _ hP he).instantiateList hlm + +theorem inferApp.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (inferApp e) fun ty _ => ∃ ty', c.TrTyping e ty e' ty' := by + rw [inferApp, Expr.withApp_eq, Expr.getAppArgs_eq] + have ⟨_, he'⟩ := AppStack.build <| e.mkAppList_getAppArgsList ▸ he + refine (inferType.WF he'.tr).bind fun ty _ _ ⟨ty', hb, _, hty', ety⟩ => ?_ + have henv := c.Ewf; have hΔ := c.Δwf + refine (inferApp.loop.WF (ll := []) (lm := []) he' hb + (hty'.trExpr henv hΔ) ety rfl rfl rfl).le + fun _ _ _ ⟨_, _, hb, h1, h2, h3⟩ => ?_ + have := (e.mkAppList_getAppArgsList ▸ h1).uniq henv (.refl henv hΔ) he + exact ⟨_, e.mkAppList_getAppArgsList ▸ hb, he, h2, h3.defeqU_l henv hΔ this⟩ + +theorem inferLet.loop.WF {c : VContext} {e₀ : Expr} + {m} [mwf : c.MLCWF m] {n} (hn : n ≤ m.length) (nds hnds) + (hdrop : m.dropN n hn = c.mlctx) + (harr : arr.toList.reverse = (m.fvarRevList n hn).map .fvar) + (he₀ : e₀ = m.mkLet n hn nds hnds ei) + (hei : e.instantiateList ((m.fvarRevList n hn).map .fvar) = ei) + (hbelow : ∀ P, IsFVarUpSet P c.vlctx → FVarsIn P e₀ → + IsFVarUpSet (AllAbove c.vlctx P) m.vlctx ∧ FVarsIn (AllAbove c.vlctx P) ei ∧ + ∀ ty, FVarsIn (AllAbove c.vlctx P) ty → FVarsIn (AllAbove c.vlctx P) (m.mkForall n hn ty)) + (hr : e.FVarsIn (· ∈ m.vlctx.fvars)) + (hinf : inferOnly = true → ∃ e', (c.withMLC m).TrExprS ei e') : + (inferLet.loop inferOnly arr e).WF (c.withMLC m) s fun ty _ => + ∃ e' ty', c.TrTyping e₀ ty e' ty' := by + generalize eqfvs : (m.fvarRevList n hn).map Expr.fvar = fvs at * + unfold inferLet.loop + simp [harr, -bind_pure_comp]; split + · rename_i name dom val body nd + generalize eqF : withLetDecl (m := RecM) _ _ _ _ = F + generalize eqP : (fun ty x => ∃ _, _) = P + rw [Expr.instantiateList_letE] at hei; subst ei + have main {s₁} (le₁ : s ≤ s₁) {dom' val'} + (hdom : (c.withMLC m).TrExprS (dom.instantiateList fvs) dom') + (hval : (c.withMLC m).TrExprS (val.instantiateList fvs) val') + (valty : (c.withMLC m).venv.HasType + (c.withMLC m).lparams.length (c.withMLC m).vlctx.toCtx val' dom') + (hbody : inferOnly = true → ∃ body', + TrExprS c.venv c.lparams ((none, .vlet dom' val') :: m.vlctx) + (body.instantiateList fvs 1) body') : + F.WF (c.withMLC m) s₁ P := by + refine .stateWF fun wf => ?_ + have hdom' := hdom.trExpr c.Ewf mwf.1.tr.wf + subst eqF eqP + refine .withLetDecl hdom hval valty le₁ fun a mwf' s' le₂ res => ?_ + have eq := @Expr.instantiateList_instantiate1_comm body fvs (.fvar a) (by trivial) + refine inferLet.loop.WF (Nat.succ_le_succ hn) (some nd :: nds) + (by simp [hnds]) (by simp [hdrop]) (by simp [← eqfvs, harr]) + ?_ (by simp; rfl) ?_ (hr.2.2.mono fun _ => .tail _) ?_ + · rw [he₀, eqfvs, ← eq]; simp [MLCtx.mkLetArg]; congr 2 + refine (FVarsIn.abstract_instantiate1 ((hr.2.2.instantiateList ?_ _).mono ?_)).symm + · simp [← eqfvs, FVarsIn]; exact m.fvarRevList_prefix.subset + · rintro _ h rfl; exact (mwf'.1.tr.wf.2.1 _ _ rfl).1 h + · intro P hP he + have ⟨h1, h2, h3⟩ := hbelow _ hP he + refine ⟨⟨h1, fun _ => ?_⟩, ?_, fun ty hty => h3 _ ?_⟩ + · simp [or_imp, forall_and] + exact ⟨(fvarsIn_iff.1 h2.1).1, (fvarsIn_iff.1 h2.2.1).1⟩ + · rw [eqfvs, ← eq] + refine h2.2.2.instantiate1 fun h => ?_ + exact res.elim (wf.ngen_wf _ (m.dropN_fvars_subset n hn (hdrop ▸ h))) + · simp; split <;> rename_i h + · exact ⟨h2.1, h2.2.1, hty.abstract1⟩ + · rw [Expr.lowerLooseBVars_eq_instantiate (v := .sort .zero) (by simpa using h)] + exact hty.abstract1.instantiate1 rfl + · intro h; let ⟨_, hbody⟩ := hbody h + exact eqfvs.symm ▸ eq ▸ ⟨_, hbody.inst_fvar c.Ewf.ordered mwf'.1.tr.wf⟩ + split + · subst inferOnly + refine (checkType.WF ?_).bind fun uv _ le ⟨dom', uv', _, h1, h2, h3⟩ => ?_ + · apply hr.1.instantiateList; simp [← eqfvs]; exact m.fvarRevList_prefix.subset + refine (ensureSortCore.WF h2).bind + fun _ _ le₂ ⟨h4, h5, _⟩ => ?_ + obtain ⟨_, rfl⟩ := h4; let ⟨_, .sort _, h5⟩ := h5; have le := le.trans le₂ + refine (checkType.WF ?_).bind_le le fun ty _ le ⟨val', ty', _, h4, h5, h6⟩ => ?_ + · apply hr.2.1.instantiateList; simp [← eqfvs]; exact m.fvarRevList_prefix.subset + refine (isDefEq.WF h5 h1).bind_le le fun b _ le h7 => ?_ + cases b <;> simp + · exact .getEnv <| .getLCtx .throw + have valty := h6.defeqU_r c.Ewf mwf.1.tr.wf.toCtx (h7 rfl) + exact main le h1 h4 valty nofun + · simp_all; let ⟨_, h1⟩ := hinf + have .letE (ty' := dom') (body' := body') valty hdom hval hbody := h1 + exact main .rfl hdom hval valty _ hbody + · subst ei; refine (inferType.WF' ?_ hinf).bind fun ty _ _ ⟨e', ty', hb, h1, h2, h3⟩ => ?_ + · apply hr.instantiateList; simp [← eqfvs]; exact m.fvarRevList_prefix.subset + refine .stateWF fun wf => .getLCtx <| .pure ?_ + have ⟨_, hty, e2⟩ := h2.trExpr c.Ewf.ordered wf.trctx.wf + |>.cheapBetaReduce c.Ewf wf.trctx.wf m.noBV + have h3 := h3.defeqU_r c.Ewf mwf.1.tr.wf.toCtx e2.symm + let ⟨h1', h2'⟩ := mwf.1.mkLet_trS c.Ewf h1 h3 n hn nds hnds + have h3' := (mwf.1.mkForall_trS c.Ewf hty (h3.isType c.Ewf mwf.1.tr.wf.toCtx) n hn).1 + simp [hdrop] at h1' h2' h3' + erw [mwf.1.mkForall_eq _ _ (eqfvs ▸ harr)] + refine ⟨_, _, fun P hP he => ?_, he₀ ▸ h1', h3', h2'⟩ + have ⟨c1, c2, c3⟩ := hbelow _ hP he + have := c3 _ <| FVarsBelow.cheapBetaReduce (m.noBV ▸ h2.closed) _ c1 <| hb _ c1 c2 + refine this.mp (fun _ => id) h3'.fvarsIn +termination_by e + +theorem inferLet.WF + (hr : e.FVarsIn (· ∈ c.vlctx.fvars)) + (hinf : inferOnly = true → ∃ e', c.TrExprS e e') : + (inferLet e inferOnly).WF c s fun ty _ => + ∃ e' ty', c.TrTyping e ty e' ty' := by + refine .stateWF fun wf => ?_ + refine (c.withMLC_self ▸ inferLet.loop.WF (Nat.zero_le _) [] rfl rfl rfl rfl rfl ?_ hr) hinf + exact fun P hP he => ⟨(AllAbove.wf wf.trctx.wf.fvwf).2 hP, he.mono fun _ h _ => h, fun _ => id⟩ + +theorem AppStack.toSpineWF {c : VContext} + (H : AppStack c.venv c.lparams c.vlctx f f' args) + (hf : c.HasType f' (VExpr.forallN As C)) + (hlen : args.length = As.length) : + ∃ args', args.Forall₂ (c.TrExprS · ·) args' ∧ + c.venv.SpineWF c.lparams.length c.vlctx.toCtx + (VExpr.forallN As C) args' (VExpr.instRev C args') ∧ + c.TrExprS (f.mkAppList args) (VExpr.appN f' args') := by + induction args generalizing f f' As C with + | nil => + cases As with + | nil => + let .head hfull := H + exact ⟨[], .nil, .nil, by simpa⟩ + | cons _ _ => simp at hlen + | cons arg args ih => + cases As with + | nil => simp at hlen + | cons A As => + let .app hfun harg hf' harg' Hrest := H + have htypes := hf.uniqU c.Ewf c.Δwf hfun + have ⟨⟨_, hA⟩, _⟩ := htypes.forallE_inv c.Ewf c.Δwf + have hargA := harg.defeqU_r c.Ewf c.Δwf ⟨_, hA.symm⟩ + have hlen' : args.length = As.length := by simpa using hlen + have htailType : c.HasType (.app f' _) ((VExpr.forallN As C).inst _) := + hf.app hargA + rw [VExpr.instN_forallN] at htailType + obtain ⟨args', hargs', hspine, hfull⟩ := + ih Hrest htailType (by simpa [VExpr.instTelN_length] using hlen') + refine ⟨_ :: args', .cons harg' hargs', .cons hargA ?_, ?_⟩ + have hlenArgsAs : args'.length = As.length := + hargs'.length_eq.symm.trans hlen' + rw [VExpr.instN_forallN] + simpa [VExpr.instRev, hlenArgsAs] using hspine + simpa [Expr.mkAppList, VExpr.appN] using hfull + +theorem invalidProj.WF {c : VContext} {s : VState} : + (invalidProj e : RecM α).WF c s Q := by + unfold invalidProj + exact .getEnv <| .getLCtx .throw + +theorem inferProjParams.WF {c : VContext} {s : VState} + (hargs : args.Forall₂ (c.TrExprS · ·) args') + (hrBelow : c.FVarsBelow proj r) + (hargsBelow : ∀ arg ∈ args, c.FVarsBelow proj arg) + (hr : c.TrExpr r R) + (hspine : c.venv.SpineWF c.lparams.length c.vlctx.toCtx + R args' T) : + (inferProjParams proj args r).WF c s fun out _ => + c.FVarsBelow proj out ∧ c.TrExpr out T := by + induction hargs generalizing r R s with + | nil => + simp [inferProjParams] at hspine ⊢ + exact hspine.nil_inv ▸ .pure ⟨hrBelow, hr⟩ + | @cons arg arg' args args' harg hargs ih => + simp only [inferProjParams] + have hargBelow := hargsBelow arg (by simp) + have hargsBelow' : ∀ arg ∈ args, c.FVarsBelow proj arg := by + intro arg harg + exact hargsBelow arg (by simp [harg]) + obtain ⟨A, B, rfl, hargType, hrest⟩ := hspine.cons_inv + obtain ⟨r', hrS, hrEq⟩ := hr + refine (whnf.WF hrS).bind fun out s' _ + ⟨houtBelow, ⟨out', hout, houtEq⟩⟩ => ?_ + have houtEq := houtEq.trans c.Ewf c.Δwf hrEq + cases out with + | forallE name dom body bi => + let .forallE hdomTy hbodyTy hdom hbody := hout + have hforallEq := houtEq.forallE_inv c.Ewf c.Δwf + obtain ⟨⟨_, hdomEq⟩, _, hbodyEq⟩ := hforallEq + have hargType' := hargType.defeqU_r c.Ewf c.Δwf + ⟨_, hdomEq.symm⟩ + have hnext : c.TrExpr (body.instantiate1 arg) (B.inst arg') := by + simpa only [Expr.instantiate1_eq] using + (.inst c.Ewf c.Δwf hargType' + ⟨_, hbody, _, hbodyEq⟩ (harg.trExpr c.Ewf c.Δwf)) + have hnextBelow : c.FVarsBelow proj (body.instantiate1 arg) := by + intro P hP hproj + have houtFVars := (hrBelow.trans houtBelow) P hP hproj + simpa only [Expr.instantiate1_eq] using + houtFVars.2.instantiate1 (hargBelow P hP hproj) + exact ih hnextBelow hargsBelow' hnext hrest + | bvar | fvar | mvar | sort | const | app | lam | letE | lit | + mdata | proj => exact invalidProj.WF + +theorem inferProjFields.WF {c : VContext} {s : VState} + {view : VStructureView} {levels : List VLevel} + {params : List VExpr} {major : VExpr} {tailResult cursor : VExpr} + (hstruct : c.TrExprS struct major) + (hview : view.WF c.venv) + (hlevels : ∀ level ∈ levels, level.WF c.lparams.length) + (hlevelsLength : levels.length = view.uvars) + (hparamsLength : params.length = view.nparams) + (hparamsSpine : ∃ resultLevel, + c.venv.SpineWF c.lparams.length c.vlctx.toCtx + (view.familyType.instL levels) params (.sort resultLevel)) + (hprograms : view.ProgramsWF c.venv) + (hname : view.name = typeName) + (hmajor : c.HasType major (view.structureType levels params)) + (hrBelow : c.FVarsBelow proj r) + (hstructBelow : c.FVarsBelow proj struct) + (hbound : fieldIdx + count < + (view.specializedFields levels params).length) + (hr : c.TrExpr r cursor) + (hcursor : VExpr.consumeForalls? + (VExpr.forallN (view.specializedFields levels params) tailResult) + (view.projectionArgs levels params fieldIdx major) = some cursor) : + (inferProjFields proj typeName struct maybePropType fieldIdx count r).WF + c s fun out _ => + ∃ cursor', + VExpr.consumeForalls? + (VExpr.forallN (view.specializedFields levels params) tailResult) + (view.projectionArgs levels params (fieldIdx + count) major) = + some cursor' ∧ + c.FVarsBelow proj out ∧ c.TrExpr out cursor' := by + induction count generalizing s r cursor fieldIdx with + | zero => + simp only [inferProjFields, Nat.add_zero] + exact .pure ⟨cursor, hcursor, hrBelow, hr⟩ + | succ count ih => + simp only [inferProjFields] + have hfieldIdx : fieldIdx < + (view.specializedFields levels params).length := by omega + have hcodeIdx : fieldIdx < + (view.projectionCodes levels params).length := by + simpa using hfieldIdx + let code := (view.projectionCodes levels params)[fieldIdx] + have hcode : + (view.projectionCodes levels params)[fieldIdx]? = some code := + List.getElem?_eq_getElem hcodeIdx + have hargsLength : + (view.projectionArgs levels params fieldIdx major).length = + fieldIdx := + view.projectionArgs_length levels params fieldIdx major + (Nat.le_of_lt hcodeIdx) + obtain ⟨field, semanticBody, hfield, hconsume⟩ := + VExpr.consumeForalls?_forallN_domain + (view.specializedFields levels params) tailResult + (view.projectionArgs levels params fieldIdx major) + (by simpa [hargsLength] using hfieldIdx) + rw [hargsLength] at hfield + have hcursorShape : cursor = + .forallE + (field.instRevAt + (view.projectionArgs levels params fieldIdx major) 0) + semanticBody := + Option.some.inj (hcursor.symm.trans hconsume) + subst cursor + obtain ⟨field', typeBody, hfield', htypeFn, + hprojectorField⟩ := + hprograms.projector_hasType_field c.Ewf c.Δwf hlevels + hlevelsLength hparamsLength hparamsSpine hcode hmajor + have hfieldEq : field' = field := + Option.some.inj (hfield'.symm.trans hfield) + subst field' + have hprojector := hprograms c.Δwf hlevels hlevelsLength + hparamsLength hparamsSpine hcode + have hprojSem : c.venv.TrProj c.lparams.length c.vlctx.toCtx + view levels params fieldIdx major (.app code.projector major) := { + viewWF := hview + levelsWF := hlevels + levels_length := hlevelsLength + params_length := hparamsLength + paramsSpine := hparamsSpine + majorType := hmajor + program := ⟨code, hcode, rfl, hprojector⟩ } + have hprojStrict : c.TrExprS (.proj typeName fieldIdx struct) + (.app code.projector major) := + .proj hstruct ⟨view, levels, params, hname, hprojSem⟩ + obtain ⟨r', hrS, hrEq⟩ := hr + refine (whnf.WF hrS).bind fun out nextState _ + ⟨houtBelow, ⟨out', hout, houtEq⟩⟩ => ?_ + have houtEq := houtEq.trans c.Ewf c.Δwf hrEq + cases out with + | forallE name dom body bi => + let .forallE hdomTy hbodyTy hdom hbody := hout + have hforallEq := houtEq.forallE_inv c.Ewf c.Δwf + obtain ⟨⟨_, hdomEq⟩, _, hbodyEq⟩ := hforallEq + have hprojectorField' := hprojectorField.defeqU_r + c.Ewf c.Δwf ⟨_, hdomEq.symm⟩ + have hnext : c.TrExpr + (body.instantiate1 (.proj typeName fieldIdx struct)) + (semanticBody.inst (.app code.projector major)) := by + simpa only [Expr.instantiate1_eq] using + (.inst c.Ewf c.Δwf hprojectorField' + ⟨_, hbody, _, hbodyEq⟩ + (hprojStrict.trExpr c.Ewf.ordered c.Δwf)) + have hnextBelow : c.FVarsBelow proj + (body.instantiate1 (.proj typeName fieldIdx struct)) := by + intro P hP hproj + have houtFVars := (hrBelow.trans houtBelow) P hP hproj + have hfieldProj : FVarsIn P + (.proj typeName fieldIdx struct) := by + simpa [FVarsIn] using hstructBelow P hP hproj + simpa only [Expr.instantiate1_eq] using + houtFVars.2.instantiate1 hfieldProj + have hconsumeNext : VExpr.consumeForalls? + (VExpr.forallN (view.specializedFields levels params) tailResult) + (view.projectionArgs levels params (fieldIdx + 1) major) = + some (semanticBody.inst (.app code.projector major)) := by + rw [view.projectionArgs_succ levels params fieldIdx major hcode] + rw [VExpr.consumeForalls?_append, hconsume] + rfl + have hbound' : fieldIdx + 1 + count < + (view.specializedFields levels params).length := by omega + have hrec (recState : VState) := + ih (s := recState) hnextBelow hbound' hnext hconsumeNext + simp only + split + · refine (isProp.WF hdom).bind fun _ propState _ _ => ?_ + split + · exact invalidProj.WF + · simpa only [pure_bind, Nat.add_assoc, Nat.add_left_comm, + Nat.add_comm] using hrec propState + · simpa only [pure_bind, Nat.add_assoc, Nat.add_left_comm, + Nat.add_comm] using hrec nextState + | bvar | fvar | mvar | sort | const | app | lam | letE | lit | + mdata | proj => exact invalidProj.WF + +theorem inferProj.WF + (heBelow : c.FVarsBelow e ety) + (he : c.TrExprS e e') (hty : c.TrExprS ety ety') + (hasty : c.HasType e' ety') : + (inferProj st i e ety).WF c s fun ty _ => + ∃ proj' ty', c.TrTyping (.proj st i e) ty proj' ty' := by + unfold inferProj + refine (whnf.WF hty).bind fun type _ _ ⟨htypeBelow, htype⟩ => ?_ + have hprojBelowType : c.FVarsBelow (.proj st i e) type := by + intro P hP hproj + exact htypeBelow P hP (heBelow P hP (by simpa [FVarsIn] using hproj)) + obtain ⟨type', htypeS, htypeEq⟩ := htype + rw [Expr.withApp_eq] + have ⟨family', hstack⟩ := AppStack.build + (type.mkAppList_getAppArgsList ▸ htypeS) + simp only + split + · rename_i familyName familyLevels hfamilyShape + refine .getEnv ?_ + split + · exact invalidProj.WF + · rename_i hname + refine (M.WF.liftExcept envGet.WF).lift.bind fun ci _ _ hfind => ?_ + split + · rename_i info + split + · rename_i constructor hctors + split + · rename_i hready + split + · exact invalidProj.WF + · rename_i hargs + obtain ⟨artifact⟩ := + c.projectionReady.infer familyName info hfind hready + have hhead := hstack.tr + rw [hfamilyShape] at hhead + let .const (us' := levels') hfamilyConst hlevelsMap + hlevelsLength := hhead + have hviewFamily := artifact.viewWF.family + rw [artifact.name_eq] at hviewFamily + rw [hviewFamily] at hfamilyConst + cases hfamilyConst + have hlevelsWF : ∀ level ∈ levels', + level.WF c.lparams.length := + VLevel.WF.of_mapM_ofLevel hlevelsMap + have hlevelsSourceLength : levels'.length = + artifact.view.generation.block.sourceType.uvars := + (List.mapM_eq_some.1 hlevelsMap).length_eq.symm.trans + hlevelsLength + have hlevelsLength' : levels'.length = artifact.view.uvars := by + exact hlevelsSourceLength.trans + artifact.view.generation.block.sourceType_uvars_eq + have hargsSize : type.getAppArgs.size = + info.numParams + info.numIndices := by + simpa using hargs + have hargsLength : type.getAppArgsList.length = + artifact.view.nparams := by + rw [← Expr.getAppArgs_toList] + simp [hargsSize, + artifact.numParams_eq, artifact.numIndices_eq] + have hfamilyType : c.HasType (.const familyName levels') + (artifact.view.familyType.instL levels') := by + exact VEnv.HasType.const hviewFamily hlevelsWF + hlevelsSourceLength + have hfamilyTypeShape : c.HasType (.const familyName levels') + (VExpr.forallN + (artifact.view.generation.block.rawParams.map + (VExpr.instL levels')) + (artifact.view.generation.block.rawResult.instL + levels')) := by + simpa [VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + artifact.view.raw_indices_eq, + VExpr.instL_forallN, VExpr.forallN] using hfamilyType + have hargsRawLength : type.getAppArgsList.length = + (artifact.view.generation.block.rawParams.map + (VExpr.instL levels')).length := by + simpa [artifact.view.generation.shape.1] using hargsLength + obtain ⟨params', hparamsTr, hparamsSpineRaw, htypeFull⟩ := + AppStack.toSpineWF hstack hfamilyTypeShape hargsRawLength + rw [type.mkAppList_getAppArgsList] at htypeFull + have htypeAppliedEq := htypeFull.uniq c.Ewf + (.refl c.Ewf c.Δwf) htypeS + have hmajorType : c.HasType e' + (artifact.view.structureType levels' params') := by + apply hasty.defeqU_r c.Ewf c.Δwf + have := (htypeAppliedEq.trans c.Ewf c.Δwf htypeEq).symm + simpa [VStructureView.structureType, + artifact.name_eq] using this + have hparamsLength : params'.length = + artifact.view.nparams := + hparamsTr.length_eq.symm.trans hargsLength + have hparamsRawLength : params'.length = + (artifact.view.generation.block.rawParams.map + (VExpr.instL levels')).length := + hparamsTr.length_eq.symm.trans hargsRawLength + have hparamsSpine : ∃ resultLevel, + c.venv.SpineWF c.lparams.length c.vlctx.toCtx + (artifact.view.familyType.instL levels') params' + (.sort resultLevel) := by + obtain ⟨resultLevel, hresultLevel⟩ := artifact.rawResult_sort + refine ⟨resultLevel.inst levels', ?_⟩ + rw [hresultLevel] at hparamsSpineRaw + rw [VExpr.instRev_closedN params' (by trivial)] at hparamsSpineRaw + simpa [VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + artifact.view.raw_indices_eq, hresultLevel, + VExpr.instL_forallN, VExpr.forallN, + VExpr.instRev, VExpr.instL] using hparamsSpineRaw + have hconstructorName : + constructor = artifact.view.constructorName := by + have := hctors.symm.trans artifact.ctors_eq + simpa using this + refine (M.WF.liftExcept envGet.WF).lift.bind + fun c_info _ _ hctorFind => ?_ + cases c_info with + | ctorInfo ctorInfo => + simp only + split + · rename_i hidxHost + have hctorInfoEq : + ctorInfo = artifact.constructorInfo := by + rw [hconstructorName, artifact.constructor_find] at hctorFind + exact ConstantInfo.ctorInfo.inj + (Option.some.inj hctorFind.symm) + have hiFields : i < + (artifact.view.specializedFields levels' params').length := by + rw [hctorInfoEq, + artifact.constructor_numFields_eq] at hidxHost + simpa [VStructureView.specializedFields, + VStructureView.fields] using hidxHost + have hviewConstructor : c.venv.constants constructor = + some artifact.view.constructor.raw.toVConstant := by + simpa [hconstructorName] using + artifact.viewWF.toRegistered.constructor + obtain ⟨_, hctorTr⟩ := + c.trenv.find?_uniq hctorFind hviewConstructor + have hrawCtorUvars : + artifact.view.constructor.raw.uvars = + artifact.view.uvars := by + exact artifact.view.generation.ctor_uvars_eq + (by simp [artifact.view.constructor_eq]) + have hctorLevelLength : + ctorInfo.levelParams.length = familyLevels.length := + hctorTr.2.1.trans <| hrawCtorUvars.trans <| + hlevelsLength'.symm.trans + (List.mapM_eq_some.1 hlevelsMap).length_eq.symm + have hctorType₀ := hctorTr.2.2.instL c.Ewf + (Us := c.lparams) (ls' := levels') (Δ := []) + trivial hlevelsMap hctorLevelLength + have hctorType := hctorType₀.weakFV c.Ewf + (.from_nil c.mlctx.noBV) c.Δwf + rw [(c.Ewf.ordered.closedC + hviewConstructor).instL.liftN_eq + (Nat.le_refl _)] at hctorType + let ctorTail := VExpr.forallN + (artifact.view.fields.map (VExpr.instL levels')) + ((artifact.view.constructor.rawResult + artifact.view.nparams).instL levels') + rw [artifact.view.constructor.rawType_eq] at hctorType + have hinstantiate : + ((.ctorInfo ctorInfo : ConstantInfo) + |>.instantiateTypeLevelParams familyLevels) = + ctorInfo.type.instantiateLevelParams + ctorInfo.levelParams familyLevels := rfl + have hctorTypeShape : c.TrExpr + ((.ctorInfo ctorInfo : ConstantInfo) + |>.instantiateTypeLevelParams familyLevels) + (VExpr.forallN + (artifact.view.constructorParams.map + (VExpr.instL levels')) ctorTail) := by + simpa [ConstantInfo.instantiateTypeLevelParams, + ConstantVal.instantiateTypeLevelParams, + ConstantInfo.type, ConstantInfo.toConstantVal, ctorTail, + VInductDecl.NormalizedCtor.declaredBinders, + VStructureView.nparams, + VStructureView.constructorParams, + VStructureView.fields, + VExpr.instL_forallN, VExpr.forallN_append, + List.map_append] using hctorType + have hctorTypeBelow : c.FVarsBelow (.proj st i e) + ((.ctorInfo ctorInfo : ConstantInfo) + |>.instantiateTypeLevelParams familyLevels) := by + intro P _ _ + simpa [ConstantInfo.instantiateTypeLevelParams, + ConstantVal.instantiateTypeLevelParams, + ConstantInfo.type, ConstantInfo.toConstantVal] using + hctorType₀.fvarsIn.mono nofun + have hparamArgsEq : + List.take info.numParams type.getAppArgs.toList = + type.getAppArgsList := by + simp [Expr.getAppArgs_toList, artifact.numParams_eq, + ← hargsLength] + have hparamArgsTr : + (List.take info.numParams + type.getAppArgs.toList).Forall₂ + (c.TrExprS · ·) params' := by + simpa [hparamArgsEq] using hparamsTr + have hparamArgsBelow : ∀ arg ∈ + List.take info.numParams type.getAppArgs.toList, + c.FVarsBelow (.proj st i e) arg := by + intro arg harg P hP hproj + apply FVarsIn.getAppArgsList + (hprojBelowType P hP hproj) + simpa [hparamArgsEq] using harg + have hctorParamsSpine := + artifact.viewWF.constructorParamsSpine c.Ewf.ordered + levels' hlevelsWF hlevelsLength' params' hparamsLength + hparamsSpine ctorTail + refine (inferProjParams.WF hparamArgsTr hctorTypeBelow + hparamArgsBelow hctorTypeShape hctorParamsSpine).bind + fun r _ _ hr => ?_ + obtain ⟨hrBelow, hr⟩ := hr + let tailResult := + ((artifact.view.constructor.rawResult + artifact.view.nparams).instL levels').instRevAt + params' artifact.view.fields.length + have hctorTailInst : ctorTail.instRev params' = + VExpr.forallN + (artifact.view.specializedFields levels' params') + tailResult := by + simp [ctorTail, tailResult, + VExpr.instRev_forallN_projection, + VStructureView.specializedFields, + VExpr.instRevAt_map_instL_zipIdx] + rw [hctorTailInst] at hr + refine (getSortLevel.WF htypeS).bind + fun sortLevel nextState _ _ => ?_ + have hstructBelow : c.FVarsBelow (.proj st i e) e := by + intro P _ hproj + simpa [FVarsIn] using hproj + have hcursorZero : VExpr.consumeForalls? + (VExpr.forallN + (artifact.view.specializedFields levels' params') + tailResult) + (artifact.view.projectionArgs levels' params' 0 e') = + some (VExpr.forallN + (artifact.view.specializedFields levels' params') + tailResult) := by + rfl + refine (inferProjFields.WF he artifact.viewWF hlevelsWF + hlevelsLength' hparamsLength hparamsSpine + artifact.programsWF artifact.name_eq hmajorType + hrBelow hstructBelow (by simpa using hiFields) hr + hcursorZero).bind + fun r _ _ hr => ?_ + obtain ⟨cursor, hcursor, hrBelow, hr⟩ := hr + have hcursor' : VExpr.consumeForalls? + (VExpr.forallN + (artifact.view.specializedFields levels' params') + tailResult) + (artifact.view.projectionArgs levels' params' i e') = + some cursor := by + simpa using hcursor + have hcodeIdx : i < + (artifact.view.projectionCodes levels' params').length := by + simpa using hiFields + let code := + (artifact.view.projectionCodes levels' params')[i] + have hcode : + (artifact.view.projectionCodes levels' params')[i]? = + some code := + List.getElem?_eq_getElem hcodeIdx + have hprojectionArgsLength : + (artifact.view.projectionArgs levels' params' i e').length = + i := + artifact.view.projectionArgs_length levels' params' i e' + (Nat.le_of_lt hcodeIdx) + obtain ⟨field, semanticBody, hfield, hconsume⟩ := + VExpr.consumeForalls?_forallN_domain + (artifact.view.specializedFields levels' params') + tailResult + (artifact.view.projectionArgs levels' params' i e') + (by simpa [hprojectionArgsLength] using hiFields) + rw [hprojectionArgsLength] at hfield + have hcursorShape : cursor = + .forallE + (field.instRevAt + (artifact.view.projectionArgs levels' params' i e') 0) + semanticBody := + Option.some.inj (hcursor'.symm.trans hconsume) + subst cursor + have hprograms : artifact.view.ProgramsWF c.venv := + artifact.programsWF + obtain ⟨field', typeBody, hfield', htypeFn, + hprojectorField⟩ := + hprograms.projector_hasType_field + c.Ewf c.Δwf hlevelsWF hlevelsLength' hparamsLength + hparamsSpine hcode hmajorType + have hfieldEq : field' = field := + Option.some.inj (hfield'.symm.trans hfield) + subst field' + have hprojector := hprograms c.Δwf hlevelsWF + hlevelsLength' hparamsLength hparamsSpine hcode + have hprojSem : c.venv.TrProj c.lparams.length + c.vlctx.toCtx artifact.view levels' params' i e' + (.app code.projector e') := { + viewWF := artifact.viewWF + levelsWF := hlevelsWF + levels_length := hlevelsLength' + params_length := hparamsLength + paramsSpine := hparamsSpine + majorType := hmajorType + program := ⟨code, hcode, rfl, hprojector⟩ } + have hst : st = familyName := by + simpa using hname + have hprojStrict : c.TrExprS (.proj st i e) + (.app code.projector e') := + .proj he ⟨artifact.view, levels', params', + artifact.name_eq.trans hst.symm, hprojSem⟩ + obtain ⟨r', hrS, hrEq⟩ := hr + refine (whnf.WF hrS).bind fun out _ _ + ⟨houtBelow, ⟨out', hout, houtEq⟩⟩ => ?_ + have houtEq := houtEq.trans c.Ewf c.Δwf hrEq + cases out with + | forallE name dom body bi => + let .forallE hdomTy hbodyTy hdom hbody := hout + have hforallEq := houtEq.forallE_inv c.Ewf c.Δwf + obtain ⟨⟨_, hdomEq⟩, _, hbodyEq⟩ := hforallEq + have hprojectorField' := hprojectorField.defeqU_r + c.Ewf c.Δwf ⟨_, hdomEq.symm⟩ + have hdomBelow : c.FVarsBelow (.proj st i e) dom := by + intro P hP hproj + exact ((hrBelow.trans houtBelow) P hP hproj).1 + have hresult : ∃ proj' ty', + c.TrTyping (.proj st i e) dom proj' ty' := + ⟨.app code.projector e', _, hdomBelow, hprojStrict, + hdom, hprojectorField'⟩ + simp only + split + · refine (isProp.WF hdom).bind fun _ _ _ _ => ?_ + split + · exact invalidProj.WF + · exact .pure hresult + · exact .pure hresult + | bvar | fvar | mvar | sort | const | app | lam | letE | + lit | mdata | proj => exact invalidProj.WF + · exact invalidProj.WF + | axiomInfo | defnInfo | thmInfo | opaqueInfo | quotInfo | + inductInfo | recInfo => exact invalidProj.WF + · exact invalidProj.WF + · exact invalidProj.WF + · exact invalidProj.WF + · exact invalidProj.WF + +theorem literal_is_primitive (H : n = ``Nat ∨ n = ``Char.ofNat ∨ n = ``String.ofList) : + Environment.primitives.contains n := by + simp [Environment.primitives, NameSet.ofList] + obtain rfl|rfl|rfl := H <;> simp +decide [NameSet.contains] + +theorem infer_literal {c : VContext} (H : c.venv.ContainsLits l) : + c.TrTyping (.lit l) l.type (.trLiteral l) (.const l.typeName []) := by + refine + have := TrExprS.trLiteral c.Ewf c.hasPrimitives l H + ⟨fun _ _ _ => .litType, this.1, ?_, this.2⟩ + rw [← Literal.mkConst_typeName] + have ⟨_, h⟩ := this.2.isType c.Ewf c.Δwf + have ⟨_, h1, _, h3⟩ := h.const_inv c.Ewf c.Δwf + exact .const h1 rfl h3 + +theorem infer_sort {c : VContext} (H : VLevel.ofLevel c.lparams u = some u') : + c.TrTyping (.sort u) (.sort u.succ) (.sort u') (.sort u'.succ) := by + refine ⟨fun _ _ _ => (?a).fvarsIn, .sort H, ?a, .sort (.of_ofLevel H)⟩ + exact .sort <| by simpa [VLevel.ofLevel] + +theorem inferType'.WF + (h1 : e.FVarsIn (· ∈ c.vlctx.fvars)) + (hinf : inferOnly = true → ∃ e', c.TrExprS e e') : + (inferType' e inferOnly).WF c s fun ty _ => ∃ e' ty', c.TrTyping e ty e' ty' := by + unfold inferType'; lift_lets; intro F F1 + split <;> [exact .throw; refine .get <| .get ?_] + split + · rename_i h; refine .stateWF fun wf => .pure ?_ + generalize hic : cond .. = ic at h + have : ic.WF c s := by + subst ic; cases inferOnly <;> [exact wf.inferTypeC_wf; exact wf.inferTypeI_wf] + exact (this h).2.2.2.2 h1 + generalize hP : (fun _ (_ : VState) => _) = P + have hF {ty e' ty' s} (H : c.TrTyping e ty e' ty') : (F ty).WF c s P := by + rintro _ mwf wf a s' ⟨⟩ + refine let s' := _; ⟨s', rfl, ?_⟩ + have hic {ic} (hic : InferCache.WF c s ic) : InferCache.WF c s (ic.insert e ty) := by + intro _ _ h + rw [Std.HashMap.getElem?_insert] at h; split at h <;> [cases h; exact hic h] + rename_i eq + refine .mk c.mlctx.noBV (.eqv H eq BEq.rfl) (.eqv eq ?_) ?_ + · exact H.2.1.fvarsIn.mono wf.ngen_wf + · exact H.2.2.1.fvarsIn.mono wf.ngen_wf + subst P; revert s'; cases inferOnly <;> (dsimp -zeta; intro s'; refine ⟨.rfl, ?_, _, _, H⟩) + · exact { wf with inferTypeC_wf := hic wf.inferTypeC_wf } + · exact { wf with inferTypeI_wf := hic wf.inferTypeI_wf } + split + · extract_lets G1 + refine (checkLitSize.WF (Q := fun _ s' => s' = _) rfl).bind fun _ _ _ h => ?_ + subst h; split <;> [split; skip] + · refine .getEnv <| (M.WF.liftExcept envGet.WF).lift.bind fun _ _ _ h => ?_ + have ⟨_, h, _⟩ := c.trenv.find? h <| + (c.safePrimitives h (literal_is_primitive (.inl rfl))).1 ▸ DefinitionSafety.le_safe + exact hF (infer_literal ⟨_, h⟩) + · refine .getEnv <| (M.WF.liftExcept envGet.WF).lift.bind fun _ _ _ h1 => ?_ + refine .getEnv <| (M.WF.liftExcept envGet.WF).lift.bind fun _ _ _ h2 => ?_ + have ⟨_, h1, _⟩ := c.trenv.find? h1 <| + (c.safePrimitives h1 (literal_is_primitive (.inr (.inl rfl)))).1 ▸ DefinitionSafety.le_safe + have ⟨_, h2, _⟩ := c.trenv.find? h2 <| + (c.safePrimitives h2 (literal_is_primitive (.inr (.inr rfl)))).1 ▸ DefinitionSafety.le_safe + exact hF (infer_literal ⟨⟨_, h1⟩, ⟨_, h2⟩⟩) + · rename_i h; have ⟨_, h⟩ := hinf (by simpa using h) + have := h.lit_has_type + simp [G1]; exact hF (infer_literal this) + · refine (inferType'.WF (by exact h1) ?_).bind fun _ _ _ ⟨_, _, hb, h1, h⟩ => ?_ + · exact fun h => let ⟨_, .mdata h⟩ := hinf h; ⟨_, h⟩ + exact hF ⟨hb, .mdata h1, h⟩ + · refine (inferType'.WF (by exact h1) ?_).bind fun _ _ _ ⟨_, _, hb, h1, h2, h3⟩ => ?_ + · exact fun h => let ⟨_, .proj h ..⟩ := hinf h; ⟨_, h⟩ + exact (inferProj.WF hb h1 h2 h3).bind fun ty _ _ ⟨_, ty', h⟩ => hF h + · exact .readThe <| (M.WF.liftExcept inferFVar.WF).lift.bind fun _ _ _ ⟨_, _, h⟩ => hF h + · exact .throw + · rename_i h _; simp [Expr.hasLooseBVars, Expr.looseBVarRange'] at h + · split <;> rename_i h + · refine .readThe <| (M.WF.liftExcept (checkLevel.WF h1)).lift.bind fun _ _ _ ⟨_, h⟩ => ?_ + exact hF (infer_sort h) + · let ⟨_, .sort h⟩ := hinf (by simpa using h) + exact hF (infer_sort h) + · refine .readThe <| + (M.WF.liftExcept (inferConstant.WF h1 hinf)).lift.bind fun _ _ _ ⟨_, _, h⟩ => hF h + · exact (inferLambda.WF h1 hinf).bind fun _ _ _ ⟨_, _, h⟩ => hF h + · exact (inferForall.WF h1 hinf).bind fun _ _ _ ⟨_, _, h⟩ => hF h + · split <;> rename_i h + · let ⟨_, h⟩ := hinf h; exact (inferApp.WF h).bind fun _ _ _ ⟨_, h⟩ => hF h + refine (inferType'.WF h1.1 ?_).bind fun _ _ _ ⟨_, _, hfb, hf1, hf2, hf3⟩ => ?_ + · exact fun h => let ⟨_, .app _ _ h _⟩ := hinf h; ⟨_, h⟩ + refine .stateWF fun wf => ?_ + refine (ensureForallCore.WF hf2).bind fun _ _ _ H => ?_ + obtain ⟨hb, h2, name, dType, body, bi, rfl⟩ := H + let ⟨_, .forallE (ty' := dType') hl1 hl2 hl3 hl4, hl5⟩ := h2 + extract_lets _ G1 + refine (inferType'.WF h1.2 ?_).bind fun aType _ _ ⟨_, aType', hab, ha1, ha2, ha3⟩ => ?_ + · exact fun h => let ⟨_, .app _ _ _ h⟩ := hinf h; ⟨_, h⟩ + extract_lets G2 + suffices ∀ {s b} (H : b = true → c.IsDefEqU dType' aType'), RecM.WF c s (G2 b) P by + split + · refine .bind ?_ (Q := fun b _ => b = true → c.IsDefEqU dType' aType') fun b _ _ => this + intro _ mwf wf _ _ eq + let c' := { c with eagerReduce := true } + have ⟨_, h1, h2, h3, h4⟩ := isDefEq.WF (c := c') hl3 ha2 _ mwf { wf with } _ _ eq + exact ⟨_, h1, h2, { h3 with }, h4⟩ + · exact (isDefEq.WF hl3 ha2).bind fun b _ _ => this + subst G2; dsimp; rintro s ⟨⟩ H + · exact .getEnv <| .getLCtx .throw + simp [G1, Expr.bindingBody!] + have hf3 := hf3.defeqU_r c.Ewf c.Δwf hl5.symm + have ha3 := ha3.defeqU_r c.Ewf c.Δwf (H rfl).symm + subst hP; refine hF ⟨?_, .app hf3 ha3 hf1 ha1, hl4.inst c.Ewf ha3 ha1, .app hf3 ha3⟩ + exact fun _ hP he => (hfb.trans hb _ hP he.1).2.instantiate1 he.2 + · exact (inferLet.WF h1 hinf).bind fun _ _ _ ⟨_, _, h⟩ => hF h + +#guard_named_axioms Ix.Theory.Named.TypeChecker.Inner.inferProj.WF [ + propext, + sorryAx, + Classical.choice, + Quot.sound, + Lean.Expr.instantiate1_eq, + Lean.Expr.mkAppData_eq, + Lean.Expr.mkData_eq, + Lean.Expr.replace_eq, + Lean.Level.hasMVar_eq, + Lean.Level.hasParam_eq, + Lean.Level.instLawfulBEqLevel, + Lean.PersistentArray.toList'_push, + Lean.PersistentHashMap.findAux_isSome, + Lean.PersistentHashMap.WF.find?_eq, + Lean.PersistentHashMap.WF.toList'_insert] diff --git a/Ix/Theory/Named/Verify/TypeChecker/IsDefEq.lean b/Ix/Theory/Named/Verify/TypeChecker/IsDefEq.lean new file mode 100644 index 000000000..50ae5f28b --- /dev/null +++ b/Ix/Theory/Named/Verify/TypeChecker/IsDefEq.lean @@ -0,0 +1,1228 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.TypeChecker.Reduce +import Ix.Theory.Named.Verify.TypeChecker.InferType + +open Ix.Theory (VLevel) + +open Ix.Theory.Named + +namespace Ix.Theory.Named.TypeChecker.Inner +open Lean hiding Environment Exception + +theorem isDefEqLambda.WF {c : VContext} {s : VState} + {m} [mwf : c.MLCWF m] + {fvs : List Expr} (hsubst : subst.toList.reverse = fvs) + (he₁ : (c.withMLC m).TrExprS (e₁.instantiateList fvs) ei₁') + (he₂ : (c.withMLC m).TrExprS (e₂.instantiateList fvs) ei₂') : + RecM.WF (c.withMLC m) s (isDefEqLambda e₁ e₂ subst) fun b _ => + b → (c.withMLC m).IsDefEqU ei₁' ei₂' := by + unfold isDefEqLambda; let c' := c.withMLC m + split <;> [rename_i n₁ d₁ b₁ bi₁ n₂ d₂ b₂ bi₂; (simp [hsubst]; exact isDefEq.WF he₁ he₂)] + extract_lets F di₁ di₂; unfold di₁ di₂ + simp at he₁ he₂ + let .lam (ty' := t₁') (body' := b₁') ⟨_, a1⟩ a2 a3 := he₁ + let .lam (ty' := t₂') (body' := b₂') b1 b2 b3 := he₂ + suffices ∀ {x s} + (_ : match x with + | none => d₁ == d₂ + | some x => x = d₂.instantiateList fvs), + c'.IsDefEqU t₁' t₂' → + (F x).WF c' s fun b _ => b → c'.IsDefEqU (t₁'.lam b₁') (t₂'.lam b₂') by + split <;> rename_i h + · refine .pureBind <| this ‹_› ?_ + exact a2.eqv (Expr.instantiateList_eqv h) |>.uniq c'.Ewf (.refl c'.Ewf c'.Δwf) b2 + simp [hsubst] + refine (isDefEq.WF a2 b2).bind fun b _ _ h1 => ?_ + split <;> [exact .pure nofun; rename_i h] + simp at h; exact this rfl (h1 h) + intros x s hx tt + have tt' := tt.of_l c'.Ewf c'.Δwf a1 + have ⟨b₁'', a3', eq⟩ := a3.defeqDFC' c'.Ewf <| .cons (.refl c'.Ewf c'.Δwf) (by nofun) (.vlam tt') + unfold F; split <;> rename_i h + · extract_lets d₂' + have : d₂' = d₂.instantiateList fvs := by split at hx <;> [simp [d₂', hsubst]; exact hx] + clear_value d₂'; subst this + refine .withLocalDecl b2 b1 .rfl fun v mwf' _ _ _ => ?_ + have b3' := b3.inst_fvar c.Ewf mwf'.1.tr.wf + have a3'' := a3'.inst_fvar c.Ewf mwf'.1.tr.wf + rw [Expr.instantiateList_instantiate1_comm (by rfl), ← Expr.instantiateList] at a3'' b3' + refine isDefEqLambda.WF (mwf := mwf') (fvs := .fvar v :: fvs) (by simp [hsubst]) a3'' b3' + |>.mono fun _ _ _ h hb => ?_ + have ⟨_, bb⟩ := eq.symm.trans c'.Ewf mwf'.1.tr.wf.toCtx (h hb) + exact ⟨_, .symm <| .lamDF tt'.symm <| bb.symm⟩ + · simp [Expr.hasLooseBVars] at h + refine .stateWF fun wf => ?_ + have {bᵢ : Expr} {bᵢ'} (h : bᵢ.looseBVarRange' = 0) + (a3 : TrExprS c'.venv c'.lparams ((none, .vlam t₂') :: c'.vlctx) + (bᵢ.instantiateList fvs 1) bᵢ') : + ∃ e', (c.withMLC m).TrExprS (bᵢ.instantiateList (default :: fvs)) e' ∧ + c'.venv.IsDefEqU c'.lparams.length (t₂' :: c'.vlctx.toCtx) bᵢ' e'.lift := by + simp; rw [← Expr.instantiateList_instantiate1_comm (by rfl)] + let v : FVarId := ⟨s.ngen.curr⟩ + have hΔ : VLCtx.WF c'.venv c.lparams.length ((some (v, []), .vlam t₂') :: m.vlctx) := by + refine ⟨mwf.1.tr.wf, ?_, b1⟩ + rintro _ _ ⟨⟩; simp; exact fun h => s.ngen.not_reserves_self (wf.ngen_wf _ h) + have := a3.inst_fvar c.Ewf.ordered hΔ + have eq {e} (hb : bᵢ.looseBVarRange' = 0) (he : e.looseBVarRange' = 0) : + (bᵢ.instantiateList fvs 1).instantiate1' e = bᵢ.instantiateList fvs 1 := by + rw [Expr.instantiate1'_eq_self]; rw [Expr.instantiateList'_eq_self] <;> simp [*] + rw [eq h rfl, ← eq (e := .fvar v) h rfl] + let ⟨_, H⟩ := this.weakFV_inv c.Ewf (.skip_fvar _ _ .refl) (.refl c.Ewf hΔ) + (m.noBV ▸ this.closed) (by rw [eq h rfl]; exact a3.fvarsIn) + refine ⟨_, H, this.uniq c'.Ewf (.refl c'.Ewf hΔ) <| H.weakFV c'.Ewf (.skip_fvar _ _ .refl) hΔ⟩ + let ⟨_, a4, a5⟩ := this h.1 a3' + let ⟨_, b4, b5⟩ := this h.2 b3 + exact isDefEqLambda.WF (fvs := default :: fvs) (by simp [hsubst]) a4 b4 + |>.mono fun _ _ _ h hb => + have hΓ := ⟨c'.Δwf, b1⟩ + have ⟨_, bb⟩ := eq.symm.trans c'.Ewf hΓ a5 + |>.trans c'.Ewf hΓ ((h hb).weak c'.Ewf (B := t₂')) |>.trans c'.Ewf hΓ b5.symm + ⟨_, .symm <| .lamDF tt'.symm bb.symm⟩ + +theorem isDefEqForall.WF {c : VContext} {s : VState} + {m} [mwf : c.MLCWF m] + {fvs : List Expr} (hsubst : subst.toList.reverse = fvs) + (he₁ : (c.withMLC m).TrExprS (e₁.instantiateList fvs) ei₁') + (he₂ : (c.withMLC m).TrExprS (e₂.instantiateList fvs) ei₂') : + RecM.WF (c.withMLC m) s (isDefEqForall e₁ e₂ subst) fun b _ => + b → (c.withMLC m).IsDefEqU ei₁' ei₂' := by + unfold isDefEqForall; let c' := c.withMLC m + split <;> [rename_i n₁ d₁ b₁ bi₁ n₂ d₂ b₂ bi₂; (simp [hsubst]; exact isDefEq.WF he₁ he₂)] + extract_lets F di₁ di₂; unfold di₁ di₂ + simp at he₁ he₂ + let .forallE (ty' := t₁') (body' := b₁') ⟨_, a1⟩ _ a2 a3 := he₁ + let .forallE (ty' := t₂') (body' := b₂') b1 ⟨_, bT⟩ b2 b3 := he₂ + suffices ∀ {x s} + (_ : match x with + | none => d₁ == d₂ + | some x => x = d₂.instantiateList fvs), + c'.IsDefEqU t₁' t₂' → + (F x).WF c' s fun b _ => b → c'.IsDefEqU (t₁'.forallE b₁') (t₂'.forallE b₂') by + split <;> rename_i h + · refine .pureBind <| this ‹_› ?_ + exact a2.eqv (Expr.instantiateList_eqv h) |>.uniq c'.Ewf (.refl c'.Ewf c'.Δwf) b2 + simp [hsubst] + refine (isDefEq.WF a2 b2).bind fun b _ _ h1 => ?_ + split <;> [exact .pure nofun; rename_i h] + simp at h; exact this rfl (h1 h) + intros x s hx tt + have tt' := tt.of_l c'.Ewf c'.Δwf a1 + have ⟨b₁'', a3', eq⟩ := a3.defeqDFC' c'.Ewf <| .cons (.refl c'.Ewf c'.Δwf) (by nofun) (.vlam tt') + unfold F; split <;> rename_i h + · extract_lets d₂' + have : d₂' = d₂.instantiateList fvs := by split at hx <;> [simp [d₂', hsubst]; exact hx] + clear_value d₂'; subst this + refine .withLocalDecl b2 b1 .rfl fun v mwf' _ _ _ => ?_ + have b3' := b3.inst_fvar c.Ewf mwf'.1.tr.wf + have a3'' := a3'.inst_fvar c.Ewf mwf'.1.tr.wf + rw [Expr.instantiateList_instantiate1_comm (by rfl), ← Expr.instantiateList] at a3'' b3' + refine isDefEqForall.WF (mwf := mwf') (fvs := .fvar v :: fvs) (by simp [hsubst]) a3'' b3' + |>.mono fun _ _ _ h hb => ?_ + have bb := eq.symm.trans c'.Ewf mwf'.1.tr.wf.toCtx (h hb) |>.of_r c'.Ewf mwf'.1.tr.wf.toCtx bT + exact ⟨_, .symm <| .forallEDF tt'.symm <| bb.symm⟩ + · simp [Expr.hasLooseBVars] at h + refine .stateWF fun wf => ?_ + have {bᵢ : Expr} {bᵢ'} (h : bᵢ.looseBVarRange' = 0) + (a3 : TrExprS c'.venv c'.lparams ((none, .vlam t₂') :: c'.vlctx) + (bᵢ.instantiateList fvs 1) bᵢ') : + ∃ e', (c.withMLC m).TrExprS (bᵢ.instantiateList (default :: fvs)) e' ∧ + c'.venv.IsDefEqU c'.lparams.length (t₂' :: c'.vlctx.toCtx) bᵢ' e'.lift := by + simp; rw [← Expr.instantiateList_instantiate1_comm (by rfl)] + let v : FVarId := ⟨s.ngen.curr⟩ + have hΔ : VLCtx.WF c'.venv c.lparams.length ((some (v, []), .vlam t₂') :: m.vlctx) := by + refine ⟨mwf.1.tr.wf, ?_, b1⟩ + rintro _ _ ⟨⟩; simp; exact fun h => s.ngen.not_reserves_self (wf.ngen_wf _ h) + have := a3.inst_fvar c.Ewf.ordered hΔ + have eq {e} (hb : bᵢ.looseBVarRange' = 0) (he : e.looseBVarRange' = 0) : + (bᵢ.instantiateList fvs 1).instantiate1' e = bᵢ.instantiateList fvs 1 := by + rw [Expr.instantiate1'_eq_self]; rw [Expr.instantiateList'_eq_self] <;> simp [*] + rw [eq h rfl, ← eq (e := .fvar v) h rfl] + let ⟨_, H⟩ := this.weakFV_inv c.Ewf (.skip_fvar _ _ .refl) (.refl c.Ewf hΔ) + (m.noBV ▸ this.closed) (by rw [eq h rfl]; exact a3.fvarsIn) + refine ⟨_, H, this.uniq c'.Ewf (.refl c'.Ewf hΔ) <| H.weakFV c'.Ewf (.skip_fvar _ _ .refl) hΔ⟩ + let ⟨_, a4, a5⟩ := this h.1 a3' + let ⟨_, b4, b5⟩ := this h.2 b3 + exact isDefEqForall.WF (fvs := default :: fvs) (by simp [hsubst]) a4 b4 + |>.mono fun _ _ _ h hb => + have hΓ := ⟨c'.Δwf, b1⟩ + have bb := eq.symm.trans c'.Ewf hΓ a5 |>.trans c'.Ewf hΓ ((h hb).weak c'.Ewf (B := t₂')) + |>.trans c'.Ewf hΓ b5.symm |>.of_r c'.Ewf hΓ bT + ⟨_, .symm <| .forallEDF tt'.symm bb.symm⟩ + +theorem quickIsDefEq.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (quickIsDefEq e₁ e₂) fun b _ => b = .true → c.IsDefEqU e₁' e₂' := by + unfold quickIsDefEq + refine .stateWF fun wf => .get ?_ + split <;> [rename_i hcache; skip] + · refine .pure fun _ => ?_ + rcases Bool.or_eq_true_iff.1 hcache with h | h + · exact (he₁.eqv h).uniq c.Ewf (.refl c.Ewf c.Δwf) he₂ + -- The cache is keyed on the two hashes, so the recorded pair may be either way round. + let ⟨_, _, a1, a2, ewf, _⟩ := wf.ectx + refine (VEnv.IsDefEqU.weak'_iff c.Ewf a1 a2.toCtx).1 <| + DefEqCache.IsDefEqE.uniq c.Ewf a1 + (he₁.weakFV' c.Ewf a2 a1) (he₂.weakFV' c.Ewf a2 a1) ?_ + unfold succeededBefore at h + split at h; · exact ewf.contains h + split at h; · exact (ewf.contains h).symm + rcases Bool.or_eq_true_iff.1 h with h | h + · exact ewf.contains h + · exact (ewf.contains h).symm + split + · exact .toLBoolM <| c.withMLC_self ▸ + isDefEqLambda.WF (subst := #[]) (fvs := []) rfl (c.withMLC_self ▸ he₁) (c.withMLC_self ▸ he₂) + · exact .toLBoolM <| c.withMLC_self ▸ + isDefEqForall.WF (subst := #[]) (fvs := []) rfl (c.withMLC_self ▸ he₁) (c.withMLC_self ▸ he₂) + · have .sort hu := he₁; have .sort hv := he₂ + refine .pure fun h => ⟨_, .sortDF (.of_ofLevel hu) (.of_ofLevel hv) ?_⟩ + exact Level.isEquiv'_wf (toLBool_true.1 h) hu hv + · let .mdata he₁ := he₁; let .mdata he₂ := he₂ + exact .toLBoolM <| isDefEq.WF he₁ he₂ + · cases he₁ + · rename_i a1 a2 _; refine .pure fun h => ?_ + simp at h; subst h; exact he₁.uniq c.Ewf (.refl c.Ewf c.Δwf) he₂ + · exact .pure nofun + +theorem isDefEqArgs.WF {c : VContext} {s : VState} + (H : ∃ e₁', c.TrExprS e₁.getAppFn e₁' ∧ ∃ e₂', c.TrExprS e₂.getAppFn e₂' ∧ c.IsDefEqU e₁' e₂') + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEqArgs e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := by + unfold isDefEqArgs; split <;> (unfold Expr.getAppFn at H) + · let .app a1 a2 a3 a4 := he₁ + let .app b1 b2 b3 b4 := he₂ + refine (isDefEq.WF a4 b4).bind fun _ _ _ h2 => ?_; extract_lets + split <;> [exact .pure nofun; rename_i hb2] + refine (isDefEqArgs.WF H a3 b3).mono fun _ _ _ h1 hb1 => ?_ + simp at hb2 + exact ⟨_, .appDF ((h1 hb1).of_l c.Ewf c.Δwf a1) ((h2 hb2).of_l c.Ewf c.Δwf a2)⟩ + · exact .pure nofun + · exact .pure nofun + · refine .pure fun _ => ?_ + simp [*] at H; let ⟨_, h1, _, h2, h3⟩ := H + have a1 := he₁.uniq c.Ewf (.refl c.Ewf c.Δwf) h1 + have a2 := he₂.uniq c.Ewf (.refl c.Ewf c.Δwf) h2 + exact a1.trans c.Ewf c.Δwf h3 |>.trans c.Ewf c.Δwf a2.symm + +theorem tryEtaExpansionCore.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (tryEtaExpansionCore e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := by + unfold tryEtaExpansionCore; split <;> [skip; exact .pure nofun] + refine (inferType.WF he₂).bind fun _ _ _ ⟨ty₁, a1, a2, a3, a4⟩ => ?_ + refine (whnf.WF a3).bind fun _ _ _ ⟨b1, _, b2, b3⟩ => ?_ + split <;> [skip; exact .pure nofun] + let .forallE (ty' := ty') c1 c2 c3 c4 := b2 + replace a4 := a4.defeqU_r c.Ewf c.Δwf b3.symm + -- have := b2.uniq c.Ewf (.refl c.Ewf c.Δwf) (.forallE c1 c2 c3 c4) + refine (isDefEq.WF he₁ (.lam c1 c3 (.app (a4.weak c.Ewf) (.bvar .zero) ( + Expr.liftLooseBVars_eq_self (c.mlctx.noBV ▸ a2.closed).looseBVarRange_le ▸ + a2.weakBV c.Ewf (.skip (.vlam ty') .refl)) (.bvar rfl)))).mono fun _ _ _ h hb => ?_ + exact (h hb).trans c.Ewf c.Δwf ⟨_, .eta a4⟩ + +theorem tryEtaExpansion.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (tryEtaExpansion e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := by + simp [tryEtaExpansion, orM, toBool] + refine (tryEtaExpansionCore.WF he₁ he₂).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun _ => h rfl; skip] + exact (tryEtaExpansionCore.WF he₂ he₁).mono fun _ _ _ h hb => (h hb).symm + +private theorem AppStack.toSpineWF_of_isType {c : VContext} + (H : AppStack c.venv c.lparams c.vlctx f f' args) + (hf : c.HasType f' (VExpr.forallN As (.sort resultLevel))) + (hfull : c.TrExprS (f.mkAppList args) full') + (hfullType : c.venv.IsType c.lparams.length c.vlctx.toCtx full') : + ∃ args', args.Forall₂ (c.TrExprS · ·) args' ∧ + c.venv.SpineWF c.lparams.length c.vlctx.toCtx + (VExpr.forallN As (.sort resultLevel)) args' (.sort resultLevel) ∧ + c.TrExprS (f.mkAppList args) (VExpr.appN f' args') := by + induction args generalizing f f' As full' with + | nil => + let .head hhead := H + cases As with + | nil => + refine ⟨[], .nil, .nil, ?_⟩ + change c.TrExprS f f' + exact hhead + | cons A As => + obtain ⟨sortLevel, hfullSort⟩ := hfullType + have hheadEq := hhead.uniq c.Ewf (.refl c.Ewf c.Δwf) hfull + have hheadSort := hfullSort.defeqU_l c.Ewf c.Δwf hheadEq.symm + have htypes := hf.uniqU c.Ewf c.Δwf hheadSort + exact False.elim <| + VEnv.IsDefEqU.sort_forallE_inv c.Ewf c.Δwf htypes.symm + | cons arg args ih => + let .app hfun harg hhead hargTr Hrest := H + cases As with + | nil => + have htypes := hf.uniqU c.Ewf c.Δwf hfun + exact False.elim <| + VEnv.IsDefEqU.sort_forallE_inv c.Ewf c.Δwf htypes + | cons A As => + have htypes := hf.uniqU c.Ewf c.Δwf hfun + obtain ⟨⟨_, hdomain⟩, _, _hcodomain⟩ := + htypes.forallE_inv c.Ewf c.Δwf + have hargA := harg.defeqU_r c.Ewf c.Δwf ⟨_, hdomain.symm⟩ + have htailType := hf.app hargA + rw [VExpr.instN_forallN] at htailType + obtain ⟨args', hargs, hspine, htailFull⟩ := + ih Hrest htailType (by simpa [Expr.mkAppList] using hfull) + hfullType + refine ⟨_ :: args', .cons hargTr hargs, .cons hargA ?_, ?_⟩ + · rw [VExpr.instN_forallN] + rw [Nat.zero_add] + rw [(show (VExpr.sort resultLevel).ClosedN 0 by trivial).instN_eq + (e2 := _) (Nat.zero_le As.length)] + exact hspine + · simpa [Expr.mkAppList, VExpr.appN] using htailFull + +private theorem forall₂_of_getElem? {R : α → β → Prop} : + ∀ {xs : List α} {ys : List β}, + xs.length = ys.length → + (∀ (i : Nat) (x : α) (y : β), + xs[i]? = some x → ys[i]? = some y → R x y) → + List.Forall₂ R xs ys + | [], [], _, _ => .nil + | [], _ :: _, hlen, _ => by simp at hlen + | _ :: _, [], hlen, _ => by simp at hlen + | x :: xs, y :: ys, hlen, h => by + refine .cons (h 0 x y (by simp) (by simp)) ?_ + apply forall₂_of_getElem? (Nat.succ.inj hlen) + intro i x' y' hx hy + exact h (i + 1) x' y' (by simpa using hx) (by simpa using hy) + + +theorem tryEtaStructCore.WF_of_structureEta {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (tryEtaStructCore e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := by + unfold tryEtaStructCore + split <;> [skip; exact .pure nofun] + refine .getEnv ?_ + refine (M.WF.liftExcept envGet.WF).lift.bind fun _ci _ _ hfind => ?_ + split <;> [skip; exact .pure nofun] + extract_lets F1 + split <;> [skip; exact .pure nofun] + rename_i hostHead ctorName ctorLevels hhead state hstate hostInfo ctorInfo + hargs + split <;> [skip; exact .pure nofun] + rename_i hnonrec + refine (inferType.WF he₁).bind fun _ _ _ + ⟨ty₁', _aBelow, _aTerm, aType, aTyped⟩ => ?_ + refine (inferType.WF he₂).bind fun _ _ _ + ⟨ty₂', _bBelow, _bTerm, bType, bTyped⟩ => ?_ + refine (isDefEq.WF aType bType).bind fun _ _ _ htypes => ?_ + split <;> [skip; exact .pure nofun] + rename_i htypesTrue + unfold F1 + obtain ⟨familyInfo, hfamily, ⟨artifact⟩⟩ := + c.structureEtaReady.resolveConstructor hfind hnonrec + have ⟨head', hstack⟩ := AppStack.build <| + e₂.mkAppList_getAppArgsList ▸ he₂ + have hheadTr := hstack.tr + rw [hhead] at hheadTr + let .const (us' := levels) hconst hlevelsMap hlevelsHostLength := hheadTr + have hviewConstructor := artifact.projection.viewWF.constructor + rw [artifact.constructor_name_eq] at hviewConstructor + rw [hviewConstructor] at hconst + cases hconst + have hlevelsWF : ∀ level ∈ levels, + level.WF c.lparams.length := + VLevel.WF.of_mapM_ofLevel hlevelsMap + have hrawCtorUvars : artifact.projection.view.constructor.raw.uvars = + artifact.projection.view.uvars := + artifact.projection.view.generation.ctor_uvars_eq + (by simp [artifact.projection.view.constructor_eq]) + have hlevelsLength : levels.length = artifact.projection.view.uvars := + (List.mapM_eq_some.1 hlevelsMap).length_eq.symm.trans <| + hlevelsHostLength.trans hrawCtorUvars + have hctorHead : c.HasType (.const ctorName levels) + (artifact.projection.view.constructor.raw.type.instL levels) := + VEnv.HasType.const hviewConstructor hlevelsWF + (hlevelsLength.trans hrawCtorUvars.symm) + let ctorBinders := + (artifact.projection.view.constructor.declaredBinders + artifact.projection.view.nparams).map (VExpr.instL levels) + let ctorResult := + (artifact.projection.view.constructor.rawResult + artifact.projection.view.nparams).instL levels + have hctorHeadShape : c.HasType (.const ctorName levels) + (VExpr.forallN ctorBinders ctorResult) := by + rw [artifact.projection.view.constructor.rawType_eq] at hctorHead + simpa [ctorBinders, ctorResult, VExpr.instL_forallN] using hctorHead + have hhostArgsLength : e₂.getAppArgsList.length = + ctorInfo.numParams + ctorInfo.numFields := by + simpa [Expr.getAppNumArgs_eq, ← Expr.getAppArgsList_reverse] using hargs + have hnumParams : ctorInfo.numParams = artifact.projection.view.nparams := by + exact (congrArg ConstructorVal.numParams + artifact.constructor_info_eq).symm.trans + artifact.projection.constructor_numParams_eq + have hnumFields : ctorInfo.numFields = artifact.projection.view.fields.length := by + exact (congrArg ConstructorVal.numFields + artifact.constructor_info_eq).symm.trans + artifact.projection.constructor_numFields_eq + have hconstructorMem : artifact.projection.view.constructor ∈ + artifact.projection.view.generation.block.ctorPairs := by + simp [artifact.projection.view.constructor_eq] + have hconstructorShape := + artifact.projection.view.generation.shape.2.2.2.2.2 + artifact.projection.view.constructor hconstructorMem + have hhostBinderLength : e₂.getAppArgsList.length = ctorBinders.length := by + simpa [ctorBinders, VInductDecl.NormalizedCtor.declaredBinders, + VStructureView.fields, hnumParams, hnumFields, + hconstructorShape.2.2.1] using hhostArgsLength + obtain ⟨args', hargsTr, hargsSpine, hfullTr⟩ := + AppStack.toSpineWF hstack hctorHeadShape hhostBinderLength + rw [e₂.mkAppList_getAppArgsList] at hfullTr + have hargsLength : args'.length = artifact.projection.view.nparams + + artifact.projection.view.fields.length := + hargsTr.length_eq.symm.trans <| by + simpa [hnumParams, hnumFields] using hhostArgsLength + let params := args'.take artifact.projection.view.nparams + let fields := args'.drop artifact.projection.view.nparams + have hargsSplit : args' = params ++ fields := by + simp [params, fields] + have hparamsLength : params.length = artifact.projection.view.nparams := by + simp [params, hargsLength] + have hfieldsLength : fields.length = artifact.projection.view.fields.length := by + simp [fields, hargsLength] + have hargsSpineSplit := hargsSpine + rw [hargsSplit] at hargsSpineSplit + obtain ⟨paramCursor, hparamRaw, hfieldsRaw⟩ := + hargsSpineSplit.split + let ctorTail := VExpr.forallN + (artifact.projection.view.fields.map (VExpr.instL levels)) ctorResult + have hparamCtor : c.venv.SpineWF c.lparams.length c.vlctx.toCtx + (VExpr.forallN + (artifact.projection.view.constructorParams.map + (VExpr.instL levels)) ctorTail) + params paramCursor := by + simpa [ctorBinders, ctorTail, + VInductDecl.NormalizedCtor.declaredBinders, + VStructureView.constructorParams, VStructureView.fields, + List.map_append, VExpr.forallN_append] using hparamRaw + obtain ⟨resultLevel, hrawResult⟩ := artifact.projection.rawResult_sort + have hparamsSpine := + artifact.projection.viewWF.familyParamsSpine_of_constructor + c.Ewf.ordered levels hlevelsWF hlevelsLength params hparamsLength + hparamCtor resultLevel hrawResult + have hdeclResult₀ := + artifact.projection.viewWF.generationSemantics.constructor.declaredResult + have hdeclResult₁ := hdeclResult₀.instL hlevelsWF + have hdeclResult : c.venv.IsDefEq c.lparams.length + ctorBinders.reverse ctorResult + ((VInductDecl.NormalizedCtor.resultTarget + artifact.projection.view.generation.block + artifact.projection.view.constructor).instL levels) + ((VExpr.sort + artifact.projection.view.generation.block.checked.resultLevel).instL + levels) := by + simpa [ctorBinders, ctorResult, List.map_reverse] using hdeclResult₁ + have hdeclTel₀ := + artifact.projection.viewWF.generationSemantics.constructor.declaredTel + have hdeclTel := hdeclTel₀.instL hlevelsWF + have hctorOnTel : c.venv.OnTel c.lparams.length [] ctorBinders := by + simpa [ctorBinders] using hdeclTel.raw_onTel + have hctorCtxClosed : CtxClosed ctorBinders.reverse := + VEnv.CtxWF.closed c.Ewf.ordered <| by + simpa using hctorOnTel.toOnCtx (by trivial) + have hdeclResultΓ := hdeclResult.weakR c.Ewf.ordered hctorCtxClosed + c.vlctx.toCtx + have hargsTelLength : args'.length = ctorBinders.length := + hargsTr.length_eq.symm.trans hhostBinderLength + have hresultEq := hargsSpine.instRev_defeq c.Ewf.ordered + hargsTelLength hdeclResultΓ + let S := artifact.projection.viewWF.toGenerationEnv c.Ewf.ordered + have hresultIndices : + artifact.projection.view.constructor.view.resultIndices = [] := by + apply List.length_eq_zero_iff.1 + rw [S.viewResultIndices_length hconstructorMem] + simp [artifact.projection.view.checked_indices_eq] + have hrange := VExpr.map_instRev_bvarRevRange_seg args' + artifact.projection.view.nparams artifact.projection.view.fields.length + (by omega) + have hrange' : + (VExpr.bvarRevRange + (artifact.projection.view.constructor.rawFields + artifact.projection.view.source.nparams).length + artifact.projection.view.source.nparams).map (VExpr.instRev · args') = + params := by + simpa [VStructureView.fields, hargsLength, params] using hrange + have htarget : + ((VInductDecl.NormalizedCtor.resultTarget + artifact.projection.view.generation.block + artifact.projection.view.constructor).instL levels).instRev args' = + artifact.projection.view.structureType levels params := by + simp only [VInductDecl.NormalizedCtor.resultTarget, VExpr.instL_appN, VExpr.instL, + VExpr.instRev_appN, VExpr.bvarRevRange_map_instL, hresultIndices, List.append_nil] + rw [VLevel.inst_map_id hlevelsLength] + rw [VExpr.instRev_closedN args' (by trivial)] + rw [hrange'] + rfl + rw [htarget] at hresultEq + have hcanonicalRaw := hargsSpine.hasType_appN hctorHeadShape + have hcanonical : c.HasType + ((VExpr.const ctorName levels).appN args') + (artifact.projection.view.structureType levels params) := + hcanonicalRaw.defeqU_r c.Ewf c.Δwf ⟨_, hresultEq⟩ + have hfullEq := hfullTr.uniq c.Ewf (.refl c.Ewf c.Δwf) he₂ + have hbStruct := hcanonical.defeqU_l c.Ewf c.Δwf hfullEq + have hty₂Struct := bTyped.uniqU c.Ewf c.Δwf hbStruct + have hty₁Struct := VEnv.IsDefEqU.trans c.Ewf c.Δwf + (htypes htypesTrue) hty₂Struct + have haStruct := aTyped.defeqU_r c.Ewf c.Δwf hty₁Struct + have heta := artifact.eta c.Δwf hlevelsWF hlevelsLength + hparamsLength ⟨_, hparamsSpine⟩ haStruct + have hF1Size : F1.size = args'.length := by + calc + F1.size = F1.toList.length := by simp + _ = e₂.getAppArgsList.length := by simp [F1, Expr.getAppArgs_toList] + _ = args'.length := hargsTr.length_eq + have hfieldData : ∀ (j : Nat), j < fields.length → + ∃ code : VStructureView.ProjectionCode, + (artifact.projection.view.projectionCodes levels params)[j]? = + some code ∧ + c.TrExprS (.proj ctorInfo.induct j e₁) + (.app code.projector e₁') ∧ + ∀ (hi : ctorInfo.numParams + j < F1.size), + c.TrExprS F1[ctorInfo.numParams + j] fields[j] := by + intro j hj + have hcodeIdx : j < + (artifact.projection.view.projectionCodes levels params).length := by + simpa [VStructureView.specializedFields, hfieldsLength] using hj + let code := (artifact.projection.view.projectionCodes levels params)[j] + have hcode : + (artifact.projection.view.projectionCodes levels params)[j]? = + some code := List.getElem?_eq_getElem hcodeIdx + have hprojector := artifact.projection.programsWF c.Δwf hlevelsWF + hlevelsLength hparamsLength ⟨_, hparamsSpine⟩ hcode + have hprojSem : c.venv.TrProj c.lparams.length c.vlctx.toCtx + artifact.projection.view levels params j e₁' + (.app code.projector e₁') := { + viewWF := artifact.projection.viewWF + levelsWF := hlevelsWF + levels_length := hlevelsLength + params_length := hparamsLength + paramsSpine := ⟨_, hparamsSpine⟩ + majorType := haStruct + program := ⟨code, hcode, rfl, hprojector⟩ } + have hprojTr : c.TrExprS (.proj ctorInfo.induct j e₁) + (.app code.projector e₁') := + .proj he₁ ⟨artifact.projection.view, levels, params, + artifact.projection.name_eq, hprojSem⟩ + refine ⟨code, hcode, hprojTr, ?_⟩ + intro hi + have hselectedList : + e₂.getAppArgsList[ctorInfo.numParams + j]? = + some F1[ctorInfo.numParams + j] := by + rw [← Expr.getAppArgs_toList] + simp [F1] + obtain ⟨translated, htranslated, htr⟩ := + Ix.Theory.Named.List.Forall₂.getElem?_left hargsTr hselectedList + have hfieldGet : args'[ctorInfo.numParams + j]? = some fields[j] := by + rw [hargsSplit, List.getElem?_append_right] + · simp [hnumParams, hparamsLength] + · simp [hnumParams, hparamsLength] + have : translated = fields[j] := + Option.some.inj (htranslated.symm.trans hfieldGet) + subst translated + exact htr + rw [Std.Legacy.Range.forIn'_eq_forIn'_range'] + simp only [Std.Legacy.Range.size, Nat.add_sub_cancel, Nat.div_one] + let FieldEq := fun (j : Nat) => ∃ (field : VExpr) + (code : VStructureView.ProjectionCode), + fields[j]? = some field ∧ + (artifact.projection.view.projectionCodes levels params)[j]? = some code ∧ + c.IsDefEqU (.app code.projector e₁') field + let etaStep (indices : List Nat) + (hlow : ∀ i, i ∈ indices → ctorInfo.numParams ≤ i) + (hhigh : ∀ i, i ∈ indices → i < F1.size) : + (i : Nat) → i ∈ indices → Option Bool × PUnit → + RecM (ForInStep (Option Bool × PUnit)) := + fun i hi r => tryEtaStructFieldStep e₁ ctorInfo.induct + ctorInfo.numParams F1 i + ⟨hlow i hi, hhigh i hi, by + change (i - ctorInfo.numParams) % 1 = 0 + exact Nat.mod_one _⟩ r + have etaLoopWF : ∀ (all indices : List Nat) + (hsuffix : ∃ pre, pre ++ indices = all) + (hlow : ∀ i, i ∈ all → ctorInfo.numParams ≤ i) + (hhigh : ∀ i, i ∈ all → i < F1.size) {st : VState}, + RecM.WF c st + (List.forIn'.loop all (etaStep all hlow hhigh) indices + ⟨none, PUnit.unit⟩ hsuffix) + fun r _ => + (r.1 = none → + ∀ i, i ∈ indices → FieldEq (i - ctorInfo.numParams)) ∧ + r.1 ≠ some true := by + intro all indices hsuffix hlow hhigh st + induction indices generalizing st with + | nil => + simp only [List.forIn'.loop] + exact .pure (by simp) + | cons i indices ih => + simp only [List.forIn'.loop] + simp only [etaStep, tryEtaStructFieldStep] + obtain ⟨pre, hprefix⟩ := hsuffix + have hiAll : i ∈ all := by + rw [← hprefix] + simp + have hlo := hlow i hiAll + have hhi := hhigh i hiAll + have hj : i - ctorInfo.numParams < fields.length := by + rw [hF1Size, hargsLength, ← hnumParams, + ← hfieldsLength] at hhi + omega + obtain ⟨code, hcode, hprojTr, hargTr⟩ := + hfieldData (i - ctorInfo.numParams) hj + have hiEq : ctorInfo.numParams + (i - ctorInfo.numParams) = i := + Nat.add_sub_of_le hlo + have hargBound : + ctorInfo.numParams + (i - ctorInfo.numParams) < F1.size := by + omega + have hargTr' : c.TrExprS F1[i] fields[i - ctorInfo.numParams] := by + simpa [hiEq] using hargTr hargBound + simp only [bind_assoc] + refine (isDefEq.WF hprojTr hargTr').bind fun b next _ hb => ?_ + by_cases hbtrue : b = true + · simp only [hbtrue, if_pos, pure_bind] + have hcur : FieldEq (i - ctorInfo.numParams) := + ⟨fields[i - ctorInfo.numParams], code, + List.getElem?_eq_getElem hj, hcode, hb hbtrue⟩ + have hsuffixTail : ∃ pre, pre ++ indices = all := by + refine ⟨pre ++ [i], ?_⟩ + simpa [List.append_assoc] using hprefix + have htail : RecM.WF c next + (List.forIn'.loop all (etaStep all hlow hhigh) indices + ⟨none, PUnit.unit⟩ hsuffixTail) + (fun r _ => + (r.1 = none → + ∀ k, k ∈ i :: indices → + FieldEq (k - ctorInfo.numParams)) ∧ + r.1 ≠ some true) := + (ih hsuffixTail (st := next)).mono + (fun r _ _ hrest => ⟨fun hnone k hk => by + rw [List.mem_cons] at hk + rcases hk with rfl | hk + · exact hcur + · exact hrest.1 hnone k hk, + hrest.2⟩) + simpa only [etaStep, tryEtaStructFieldStep, pure_bind] using htail + · simp only [hbtrue] + exact .pure (by simp) + have hparamsLe : ctorInfo.numParams ≤ F1.size := by + rw [hF1Size, hargsLength, ← hnumParams] + omega + have hlowRange : ∀ i, + i ∈ List.range' ctorInfo.numParams + (F1.size - ctorInfo.numParams) → + ctorInfo.numParams ≤ i := by + intro i hi + rcases List.mem_range'.mp hi with ⟨j, hj, rfl⟩ + omega + have hhighRange : ∀ i, + i ∈ List.range' ctorInfo.numParams + (F1.size - ctorInfo.numParams) → + i < F1.size := by + intro i hi + rcases List.mem_range'.mp hi with ⟨j, hj, rfl⟩ + omega + have etaForInWF : ∀ {st : VState}, RecM.WF c st + (List.forIn' + (List.range' ctorInfo.numParams (F1.size - ctorInfo.numParams)) + ⟨none, PUnit.unit⟩ + (etaStep + (List.range' ctorInfo.numParams + (F1.size - ctorInfo.numParams)) hlowRange hhighRange)) + (fun r _ => (r.1 = none → ∀ i, + i ∈ List.range' ctorInfo.numParams + (F1.size - ctorInfo.numParams) → + FieldEq (i - ctorInfo.numParams)) ∧ + r.1 ≠ some true) := by + intro st + exact etaLoopWF + (List.range' ctorInfo.numParams (F1.size - ctorInfo.numParams)) + (List.range' ctorInfo.numParams (F1.size - ctorInfo.numParams)) + ⟨[], by simp⟩ hlowRange hhighRange + change RecM.WF c _ + (do + let r ← List.forIn' + (List.range' ctorInfo.numParams (F1.size - ctorInfo.numParams)) + ⟨none, PUnit.unit⟩ + (etaStep + (List.range' ctorInfo.numParams + (F1.size - ctorInfo.numParams)) hlowRange hhighRange) + match r.1 with + | none => pure true + | some a => pure a) + (fun b _ => b = true → c.IsDefEqU e₁' e₂') + refine etaForInWF.bind fun r next _ hr => ?_ + cases hr₁ : r.1 with + | some b => + simp only + refine .pure fun hbtrue => False.elim <| + hr.2 (hr₁.trans (congrArg some hbtrue)) + | none => + simp only + refine .pure fun _ => ?_ + have hrangeCount : + F1.size - ctorInfo.numParams = fields.length := by + rw [hF1Size, hargsLength, hnumParams, hfieldsLength] + omega + have hfieldEq : ∀ j, j < fields.length → FieldEq j := by + intro j hj + have hjmem : ctorInfo.numParams + j ∈ + List.range' ctorInfo.numParams + (F1.size - ctorInfo.numParams) := by + apply List.mem_range'.2 + exact ⟨j, by simpa [hrangeCount] using hj, by simp⟩ + simpa using hr.1 hr₁ (ctorInfo.numParams + j) hjmem + let projections := artifact.projection.view.projectionArgs levels params + (artifact.projection.view.specializedFields levels params).length e₁' + have hprojectionCount : + (artifact.projection.view.specializedFields levels params).length = + fields.length := by + simpa [VStructureView.specializedFields] using hfieldsLength.symm + have hprojectionsLength : projections.length = fields.length := by + dsimp [projections] + rw [artifact.projection.view.projectionArgs_length levels params + (artifact.projection.view.specializedFields levels params).length + e₁' (by simp)] + exact hprojectionCount + have hpointwise : List.Forall₂ + (fun a a' => a = a' ∨ c.IsDefEqU a a') projections fields := by + apply forall₂_of_getElem? hprojectionsLength + intro j projection field hprojection hfield + have hj := (List.getElem?_eq_some_iff.mp hfield).1 + obtain ⟨field', code, hfield', hcode, hdefeq⟩ := hfieldEq j hj + have hprojection' : projections[j]? = + some (.app code.projector e₁') := by + dsimp [projections, VStructureView.projectionArgs] + have hjspec : j < + (artifact.projection.view.specializedFields levels params).length := + hprojectionCount.symm ▸ hj + rw [List.getElem?_map, List.getElem?_take_of_lt hjspec, hcode] + rfl + have hpEq : projection = .app code.projector e₁' := + Option.some.inj (hprojection.symm.trans hprojection') + have hfEq : field = field' := + Option.some.inj (hfield.symm.trans hfield') + subst projection + subst field + exact .inr hdefeq + let tailResult := VExpr.instRevAt ctorResult params + artifact.projection.view.fields.length + have hctorTailShape : VExpr.instRev ctorTail params = + VExpr.forallN + (artifact.projection.view.specializedFields levels params) + tailResult := by + simp only [ctorTail, tailResult, VExpr.instRev_forallN_projection, + VStructureView.specializedFields, List.length_map] + rw [VExpr.instRevAt_map_instL_zipIdx] + have hconstructorParamsLength : params.length = + artifact.projection.view.constructorParams.length := by + exact hparamsLength.trans <| by + simpa [VStructureView.constructorParams] using + hconstructorShape.2.2.1.symm + have hctorHeadPrefix : c.HasType (.const ctorName levels) + (VExpr.forallN + (artifact.projection.view.constructorParams.map + (VExpr.instL levels)) ctorTail) := by + simpa [ctorBinders, ctorTail, + VInductDecl.NormalizedCtor.declaredBinders, + VStructureView.constructorParams, VStructureView.fields, + List.map_append, VExpr.forallN_append] using hctorHeadShape + have hprefixSpine := hparamCtor.retarget + (by simpa using hconstructorParamsLength) ctorTail + rw [hctorTailShape] at hprefixSpine + have hprefixType := hprefixSpine.hasType_appN hctorHeadPrefix + have hprojectionSpine := + VStructureView.ProgramsWF.projectionArgsSpine + artifact.projection.programsWF + c.Ewf c.Δwf hlevelsWF hlevelsLength hparamsLength + ⟨_, hparamsSpine⟩ haStruct tailResult + have hprojectionDefEq := hprojectionSpine.defEq_of_pointwise + c.Ewf c.Δwf (by simpa [projections] using hpointwise) + have happEq := VEnv.IsDefEq.appN_defEq hprefixType + hprojectionDefEq + have happEqU : c.IsDefEqU + (artifact.projection.view.etaRebuild levels params e₁') + ((VExpr.const ctorName levels).appN args') := by + refine ⟨VExpr.instRev tailResult projections, ?_⟩ + simpa [VStructureView.etaRebuild, VExpr.appN_append, + artifact.constructor_name_eq, hargsSplit] using happEq + exact VEnv.IsDefEqU.trans c.Ewf c.Δwf + ⟨artifact.projection.view.structureType levels params, heta.symm⟩ + (VEnv.IsDefEqU.trans c.Ewf c.Δwf happEqU hfullEq) + + +theorem tryEtaStructCore.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (tryEtaStructCore e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := + tryEtaStructCore.WF_of_structureEta he₁ he₂ + +theorem tryEtaStruct.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (tryEtaStruct e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := by + simp [tryEtaStruct, orM, toBool] + refine (tryEtaStructCore.WF he₁ he₂).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun _ => h rfl; skip] + exact (tryEtaStructCore.WF he₂ he₁).mono fun _ _ _ h hb => (h hb).symm + +theorem isDefEqApp.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEqApp e₁ e₂) fun b _ => b → c.IsDefEqU e₁' e₂' := by + unfold isDefEqApp; split <;> [skip; exact .pure nofun] + rw [Expr.withApp_eq, Expr.withApp_eq] + split <;> [rename_i eq; exact .pure nofun] + have ⟨_, he₁'⟩ := AppStack.build <| e₁.mkAppList_getAppArgsList ▸ he₁ + have ⟨_, he₂'⟩ := AppStack.build <| e₂.mkAppList_getAppArgsList ▸ he₂ + refine (isDefEq.WF he₁'.tr he₂'.tr).bind fun _ _ _ h => ?_ + split <;> [skip; exact .pure nofun] + let rec loop.WF {s args₁ args₂ f₁ f₂ f₁' f₂' eq i} (l₁ r₁ l₂ r₂) + (h₁ : args₁.toList = l₁ ++ r₁) (hi₁ : l₁.length = i) + (h₂ : args₂.toList = l₂ ++ r₂) (hi₂ : l₂.length = i) + (he₁ : AppStack c.venv c.lparams c.vlctx (.mkAppList f₁ l₁) f₁' r₁) + (he₂ : AppStack c.venv c.lparams c.vlctx (.mkAppList f₂ l₂) f₂' r₂) + (H1 : c.IsDefEqU f₁' f₂') : + RecM.WF c s (loop args₁ args₂ eq i) fun b _ => b → + ∀ e₁', c.TrExprS (f₁.mkAppList args₁.toList) e₁' → + ∀ e₂', c.TrExprS (f₂.mkAppList args₂.toList) e₂' → c.IsDefEqU e₁' e₂' := by + unfold loop; split <;> rename_i h + · have hr₁ : r₁.length > 0 := by simp [← Array.length_toList, h₁] at h; omega + have hr₂ : r₂.length > 0 := by simp [eq, ← Array.length_toList, h₂] at h; omega + let .app (a := a₁) (as := r₁) a1 a2 a3 a4 a5 := he₁ + let .app (a := a₂) (as := r₂) b1 b2 b3 b4 b5 := he₂ + simp [ + show args₁[i] = a₁ by cases args₁; cases h₁; simp [hi₁], + show args₂[i] = a₂ by cases args₂; cases h₂; simp [hi₂]] + refine (isDefEq.WF a4 b4).bind fun _ _ _ h => ?_ + split <;> [skip; exact .pure nofun] + have H := (H1.of_l c.Ewf c.Δwf a1).appDF <| (h ‹_›).of_l c.Ewf c.Δwf a2 + exact loop.WF (l₁ ++ [a₁]) r₁ (l₂ ++ [a₂]) r₂ + (by simp [h₁]) (by simp [hi₁]) (by simp [h₂]) (by simp [hi₂]) + (by simp [a5]) (by simp [b5]) ⟨_, H⟩ + · have hr₁ : r₁.length = 0 := by simp [← Array.length_toList, h₁] at h; omega + have hr₂ : r₂.length = 0 := by simp [eq, ← Array.length_toList, h₂] at h; omega + simp at hr₁ hr₂; subst r₁ r₂; simp at h₁ h₂; subst l₁ l₂ + refine .pure fun _ _ h1 _ h2 => ?_ + have u1 := h1.uniq c.Ewf (.refl c.Ewf c.Δwf) he₁.tr + have u2 := h2.uniq c.Ewf (.refl c.Ewf c.Δwf) he₂.tr + exact u1.trans c.Ewf c.Δwf H1 |>.trans c.Ewf c.Δwf u2.symm + refine loop.WF [] _ [] _ (i := 0) (by simp [Expr.getAppArgs_toList]) rfl + (by simp [Expr.getAppArgs_toList]) rfl he₁' he₂' (h ‹_›) |>.mono fun _ _ _ h2 hb => ?_ + simp [Expr.getAppArgs_toList, Expr.mkAppList_getAppArgsList] at h2 + exact h2 hb _ he₁ _ he₂ + +theorem isDefEqProofIrrel.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEqProofIrrel e₁ e₂) fun b _ => b = .true → c.IsDefEqU e₁' e₂' := by + unfold isDefEqProofIrrel + refine (inferType.WF he₁).bind fun _ _ _ ⟨_, a1, a2, a3, a4⟩ => ?_ + refine (isProp.WF a3).bind fun _ _ _ h1 => ?_ + split <;> [exact .pure nofun; skip] + rename_i h; simp at h + refine (inferType.WF he₂).bind fun _ _ _ ⟨_, b1, b2, b3, b4⟩ => .toLBoolM ?_ + refine (isDefEq.WF a3 b3).mono fun _ _ _ h2 hb => ?_ + exact ⟨_, .proofIrrel (h1 h) a4 (b4.defeqU_r c.Ewf c.Δwf (h2 hb).symm)⟩ + +theorem cacheFailure.WF {c : VContext} {s : VState} : + (cacheFailure e₁ e₂).WF c s fun _ _ => True := by + rintro wf _ _ ⟨⟩ + exact ⟨{ s with toState := _ }, rfl, .rfl, { wf with }, ⟨⟩⟩ + +theorem tryUnfoldProjApp.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + (tryUnfoldProjApp e).WF c s fun oe _ => + ∀ e₁, oe = some e₁ → c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := by + unfold tryUnfoldProjApp; extract_lets f + split <;> [exact .pure nofun; skip] + refine (whnfCore.WF he).bind fun _ _ _ h => ?_ + refine .pure fun _ => ?_ + split <;> rintro ⟨⟩; exact h + +def _root_.Ix.Theory.Named.TypeChecker.ReductionStatus.WF + (c : VContext) (e₁' e₂' : VExpr) (allowContinue := false) : ReductionStatus → Prop + | .continue e₁ e₂ => allowContinue ∧ c.TrExpr e₁ e₁' ∧ c.TrExpr e₂ e₂' + | .unknown e₁ e₂ => c.TrExpr e₁ e₁' ∧ c.TrExpr e₂ e₂' + | .bool b => b → c.IsDefEqU e₁' e₂' + +theorem _root_.Ix.Theory.Named.TypeChecker.ReductionStatus.WF.defeq + (h1 : c.IsDefEqU e₁' e₁'') (h2 : c.IsDefEqU e₂' e₂'') + (H : ReductionStatus.WF c e₁' e₂' ac r) : ReductionStatus.WF c e₁'' e₂'' ac r := + match r, H with + | .continue .., ⟨a1, a2, a3⟩ => + ⟨a1, a2.defeq c.Ewf c.Δwf h1, a3.defeq c.Ewf c.Δwf h2⟩ + | .unknown .., ⟨a2, a3⟩ => + ⟨a2.defeq c.Ewf c.Δwf h1, a3.defeq c.Ewf c.Δwf h2⟩ + | .bool _, h => fun hb => h1.symm.trans c.Ewf c.Δwf (h hb) |>.trans c.Ewf c.Δwf h2 + +theorem lazyDeltaReductionStep.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + (lazyDeltaReductionStep e₁ e₂).WF c s fun r _ => r.WF c e₁' e₂' true := by + unfold lazyDeltaReductionStep + refine .getEnv ?_; extract_lets delta cont F1 F2 + have hdelta {s e e' ci} (he : c.TrExprS e e') (H : isDelta c.env e = some ci) : + (delta e).WF c s fun r _ => c.TrExpr r e' := by + let ⟨n, h1, ⟨_, h2⟩, ls, h3, _⟩ := isDelta_is_some.1 H + have ⟨_, stk⟩ := AppStack.build (e.mkAppList_getAppArgsList ▸ he) + have .const a1 a2 a3 := h3 ▸ stk.tr + have ⟨b1, b2, b3, b4⟩ := c.trenv.find?_uniq h1 a1 + refine (unfoldDefinition.WF he).bind fun oe _ _ H => ?_ + obtain _ | e' := oe; · cases H h1 h2 h3 (a3.trans b3.symm) + have ⟨_, _, c1, c2⟩ := H + exact (whnfCore.WF c1).mono fun x _ _ h => h.2.defeq c.Ewf c.Δwf c2 + have hcont {s e₁ e₂} (he₁ : c.TrExpr e₁ e₁') (he₂ : c.TrExpr e₂ e₂') : + (cont e₁ e₂).WF c s fun r _ => r.WF c e₁' e₂' true := by + let ⟨_, se₁, de₁⟩ := he₁; let ⟨_, se₂, de₂⟩ := he₂ + refine (quickIsDefEq.WF se₁ se₂).bind fun _ _ _ h => .pure ?_; split + · exact ⟨rfl, he₁, he₂⟩ + · intro; exact de₁.symm.trans c.Ewf c.Δwf (h rfl) |>.trans c.Ewf c.Δwf de₂ + · nofun + split + · exact .pure ⟨he₁.trExpr c.Ewf c.Δwf, he₂.trExpr c.Ewf c.Δwf⟩ + · refine (tryUnfoldProjApp.WF he₂).bind fun _ _ _ h => ?_; split + · exact hcont (he₁.trExpr c.Ewf c.Δwf) (h _ rfl).2 + · exact (hdelta he₁ ‹_›).bind fun _ _ _ h => hcont h (he₂.trExpr c.Ewf c.Δwf) + · refine (tryUnfoldProjApp.WF he₁).bind fun _ _ _ h => ?_; split + · exact hcont (h _ rfl).2 (he₂.trExpr c.Ewf c.Δwf) + · exact (hdelta he₂ ‹_›).bind fun _ _ _ h => hcont (he₁.trExpr c.Ewf c.Δwf) h + rename_i dt dt' hd1 hd2; extract_lets ht hs; split <;> [skip; split] + · exact (hdelta he₂ ‹_›).bind fun _ _ _ h => hcont (he₁.trExpr c.Ewf c.Δwf) h + · exact (hdelta he₁ ‹_›).bind fun _ _ _ h => hcont h (he₂.trExpr c.Ewf c.Δwf) + have hF1 {s} : (F1 ⟨⟩).WF c s fun r _ => r.WF c e₁' e₂' true := + (hdelta he₁ ‹_›).bind fun _ _ _ h1 => (hdelta he₂ ‹_›).bind fun _ _ _ h2 => hcont h1 h2 + refine .get ?_; split <;> [skip; exact hF1] + split <;> [skip; exact cacheFailure.WF.lift.bind fun _ _ _ _ => hF1] + rename_i h1 h2; simp at h1 + cases ptrEqConstantInfo_eq h1.1.1.2 + have ⟨n₁, b1₁, ⟨_, b2₁⟩, ls₁, b3₁, _⟩ := isDelta_is_some.1 hd1 + have ⟨n₂, b1₂, ⟨_, b2₂⟩, ls₂, b3₂, _⟩ := isDelta_is_some.1 hd2 + simp [b3₁, b3₂, Expr.constLevels!] at h2 + have ⟨_, stk₁⟩ := AppStack.build (e₁.mkAppList_getAppArgsList ▸ he₁) + have ⟨_, stk₂⟩ := AppStack.build (e₂.mkAppList_getAppArgsList ▸ he₂) + have .const (us' := ls₁) c1₁ c2₁ c3₁ := b3₁ ▸ stk₁.tr + have .const (us' := ls₂) c1₂ c2₂ c3₂ := b3₂ ▸ stk₂.tr + cases (c.trenv.find?_uniq b1₁ c1₁).1 + cases (c.trenv.find?_uniq b1₂ c1₂).1 + cases c1₁.symm.trans c1₂ + have := VEnv.IsDefEq.constDF c1₁ + (Γ := c.vlctx.toCtx) (.of_mapM_ofLevel c2₁) (.of_mapM_ofLevel c2₂) + ((List.mapM_eq_some.1 c2₁).length_eq.symm.trans c3₁) + (Level.isEquivList_wf h2 c2₁ c2₂) + refine (isDefEqArgs.WF ⟨_, stk₁.tr, _, stk₂.tr, _, this⟩ he₁ he₂).bind fun _ _ _ h => ?_ + split <;> [skip; exact cacheFailure.WF.lift.bind fun _ _ _ _ => hF1] + exact .pure fun _ => h ‹_› + +theorem isNatZero_wf {c : VContext} (H : isNatZero e) (h : c.TrExprS e e') : e' = .natZero := by + have h1 : c.TrExprS (.lit (.natVal 0)) e' := by + simp [isNatZero] at H; obtain H|H := H + · have := h.eqv H; exact .lit (this.nat_of_natZero c.Ewf c.hasPrimitives) this + · split at H <;> [exact h; cases H] + have := TrExprS.lit_has_type (l := .natVal 0) h1 + exact h1.unique (by trivial) (TrExprS.natLit c.hasPrimitives this 0).1 + +theorem isNatSuccOf?_wf {c : VContext} (H : isNatSuccOf? e = some e₁) + (h : c.TrExprS e e') : ∃ x, c.TrExprS e₁ x ∧ e' = .app .natSucc x := by + unfold isNatSuccOf? at H; split at H <;> cases H + · rename_i n + have := TrExprS.lit_has_type (l := .natVal (n+1)) h + refine ⟨_, (TrExprS.natLit c.hasPrimitives this n).1, ?_⟩ + exact h.unique (by trivial) (TrExprS.natLit c.hasPrimitives this (n+1)).1 + · let .app a1 a2 a3 a4 := h + let .const b1 b2 b3 := a3 + cases c.hasPrimitives.natSucc b1 + simp at b3; subst b3; simp at b2; subst b2 + exact ⟨_, a4, rfl⟩ + +theorem isDefEqOffset.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + (isDefEqOffset e₁ e₂).WF c s fun b _ => b = .true → c.IsDefEqU e₁' e₂' := by + unfold isDefEqOffset; split + · rename_i h; simp at h + cases isNatZero_wf h.1 he₁; cases isNatZero_wf h.2 he₂ + exact .pure fun _ => .refl <| he₁.wf c.Ewf c.Δwf + · split <;> [skip; exact .pure nofun] + obtain ⟨_, a1, rfl⟩ := isNatSuccOf?_wf ‹_› he₁ + obtain ⟨_, b1, rfl⟩ := isNatSuccOf?_wf ‹_› he₂ + refine .toLBoolM <| (isDefEqCore.WF a1 b1).mono fun _ _ _ h hb => ?_ + let ⟨_, de'⟩ := he₁.wf c.Ewf c.Δwf + let ⟨_, _, c1, c2⟩ := de'.hasType.1.app_inv c.Ewf c.Δwf + exact ⟨_, c1.appDF <| (h hb).of_l c.Ewf c.Δwf c2⟩ + +theorem lazyDeltaReduction.loop.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + (lazyDeltaReduction.loop e₁ e₂ n).WF c s fun r _ => r.WF c e₁' e₂' := by + induction n generalizing s e₁ e₂ e₁' e₂' with | zero => exact .throw | succ n ih + unfold loop; extract_lets F1 + refine (isDefEqOffset.WF he₁ he₂).bind fun _ _ _ h => ?_; split + · exact .pure fun hb => h (by simpa using hb) + suffices hF1 : ∀ {s}, (F1 ⟨⟩).WF c s fun r _ => r.WF c e₁' e₂' by + refine .readThe ?_; split <;> [skip; exact hF1] + refine (reduceNat.WF he₁).bind fun _ _ _ h => ?_; split + · have ⟨_, a1, a2⟩ := (h _ rfl).2 + refine (isDefEqCore.WF a1 he₂).bind fun _ _ _ h => .pure fun hb => ?_ + exact a2.symm.trans c.Ewf c.Δwf (h hb) + refine (reduceNat.WF he₂).bind fun _ _ _ h => ?_; split + · have ⟨_, a1, a2⟩ := (h _ rfl).2 + refine (isDefEqCore.WF he₁ a1).bind fun _ _ _ h => .pure fun hb => ?_ + exact (h hb).trans c.Ewf c.Δwf a2 + exact hF1 + intro s; unfold F1; refine .getEnv ?_ + refine (M.WF.liftExcept reduceNative.WF).lift.bind fun _ _ _ h => ?_ + split <;> [cases h _ rfl; skip] + refine (M.WF.liftExcept reduceNative.WF).lift.bind fun _ _ _ h => ?_ + split <;> [cases h _ rfl; skip] + refine (lazyDeltaReductionStep.WF he₁ he₂).bind fun r _ _ h => ?_ + obtain r|r|r := r + · let ⟨_, ⟨_, a1, a2⟩, ⟨_, b1, b2⟩⟩ := h + exact (ih a1 b1).mono fun _ _ _ h => h.defeq a2 b2 + · exact .pure h + · exact .pure h + +theorem tryStringLitExpansionCore.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (tryStringLitExpansionCore e₁ e₂) fun b _ => b = .true → c.IsDefEqU e₁' e₂' := by + unfold tryStringLitExpansionCore; iterate 3 split <;> [skip; exact .pure nofun] + let .lit _ he₁ := he₁ + exact .toLBoolM <| isDefEqCore.WF he₁ he₂ + +theorem tryStringLitExpansion.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (tryStringLitExpansion e₁ e₂) fun b _ => b = .true → c.IsDefEqU e₁' e₂' := by + refine (tryStringLitExpansionCore.WF he₁ he₂).bind fun _ _ _ h => ?_ + split <;> [skip; exact .pure h] + exact (tryStringLitExpansionCore.WF he₂ he₁).mono fun _ _ _ h hb => (h hb).symm + +theorem isDefEqUnitLike.WF_of_structureEta {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEqUnitLike e₁ e₂) + fun b _ => b = .true → c.IsDefEqU e₁' e₂' := by + unfold isDefEqUnitLike + refine (inferType.WF he₁).bind fun _ _ _ + ⟨ty₁', _aBelow, _aTerm, aType, aTyped⟩ => ?_ + refine (whnf.WF aType).bind fun normalizedType _ _ + ⟨_aWhnfBelow, tType', tTypeTr, tTypeEq⟩ => ?_ + split <;> [skip; exact .pure nofun] + rename_i _ familyName hostLevels hhead + refine .getEnv ?_ + refine (M.WF.liftExcept envGet.WF).lift.bind fun _ _ _ hfamily => ?_ + split <;> [skip; exact .pure nofun] + rename_i _ familyDeclName familyLevelParams familyRawType hostNumParams + familyAll ctorName familyNumNested familyUnsafe familyReflexive + refine (M.WF.liftExcept envGet.WF).lift.bind fun _ _ _ hctor => ?_ + split <;> [skip; exact .pure nofun] + rename_i _ ctorDeclName ctorLevelParams ctorRawType ctorInduct ctorIndex + ctorNumParams ctorUnsafe + refine (inferType.WF he₂).bind fun _ _ _ + ⟨ty₂', _bBelow, _bTerm, bType, bTyped⟩ => ?_ + refine (isDefEqCore.WF tTypeTr bType).mono fun _ _ _ h hb => ?_ + let familyInfo : InductiveVal := { + name := familyDeclName + levelParams := familyLevelParams + type := familyRawType + numParams := hostNumParams + numIndices := 0 + all := familyAll + ctors := [ctorName] + numNested := familyNumNested + isRec := false + isUnsafe := familyUnsafe + isReflexive := familyReflexive } + let constructorInfo : ConstructorVal := { + name := ctorDeclName + levelParams := ctorLevelParams + type := ctorRawType + induct := ctorInduct + cidx := ctorIndex + numParams := ctorNumParams + numFields := 0 + isUnsafe := ctorUnsafe } + have hnonrec : c.env.isNonRecStructure familyName = true := by + unfold Kernel.Environment.isNonRecStructure + rw [hfamily] + rfl + obtain ⟨artifact⟩ := c.structureEtaReady.resolve familyName familyInfo ctorName + constructorInfo hfamily hctor hnonrec + have ⟨head', hstack⟩ := AppStack.build <| + normalizedType.mkAppList_getAppArgsList ▸ tTypeTr + have hheadTr := hstack.tr + rw [hhead] at hheadTr + let .const (us' := levels) hconst hlevelsMap hlevelsHostLength := hheadTr + have hviewFamily := artifact.projection.viewWF.family + rw [artifact.projection.name_eq] at hviewFamily + rw [hviewFamily] at hconst + cases hconst + have hlevelsWF : ∀ level ∈ levels, + level.WF c.lparams.length := + VLevel.WF.of_mapM_ofLevel hlevelsMap + have hsourceUvars : + artifact.projection.view.generation.block.sourceType.uvars = + artifact.projection.view.uvars := + artifact.projection.view.generation.block.sourceType_uvars_eq + have hlevelsLength : levels.length = artifact.projection.view.uvars := + (List.mapM_eq_some.1 hlevelsMap).length_eq.symm.trans + (hlevelsHostLength.trans hsourceUvars) + have hfamilyHead : c.HasType (.const familyName levels) + (artifact.projection.view.familyType.instL levels) := + VEnv.HasType.const hviewFamily hlevelsWF + (hlevelsLength.trans hsourceUvars.symm) + obtain ⟨resultLevel, hrawResult⟩ := artifact.projection.rawResult_sort + let rawParams := artifact.projection.view.generation.block.rawParams.map + (VExpr.instL levels) + have hfamilyHeadShape : c.HasType (.const familyName levels) + (VExpr.forallN rawParams (.sort (resultLevel.inst levels))) := by + simpa [rawParams, VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + artifact.projection.view.raw_indices_eq, hrawResult, + VExpr.instL_forallN, VExpr.forallN, VExpr.instL] using hfamilyHead + have htTypeIsType : c.venv.IsType c.lparams.length c.vlctx.toCtx tType' := + (aTyped.isType c.Ewf.ordered c.Δwf).defeqU_l c.Ewf c.Δwf + tTypeEq.symm + have normalizedTypeTr : c.TrExprS + (normalizedType.getAppFn.mkAppList normalizedType.getAppArgsList) + tType' := by + rw [normalizedType.mkAppList_getAppArgsList] + exact tTypeTr + obtain ⟨params, _hparamsTr, hparamsSpine, hfullTr⟩ := + AppStack.toSpineWF_of_isType + (f := normalizedType.getAppFn) + (args := normalizedType.getAppArgsList) + (full' := tType') hstack hfamilyHeadShape + normalizedTypeTr htTypeIsType + have hparamsLength : params.length = artifact.projection.view.nparams := + hparamsSpine.forallN_sort_length.trans <| by + simpa [rawParams] using + artifact.projection.view.generation.shape.1 + have hfamilyShape : artifact.projection.view.familyType.instL levels = + VExpr.forallN rawParams (.sort (resultLevel.inst levels)) := by + simp [rawParams, VStructureView.familyType, + VInductDecl.NormalizedChecked.rawType_eq, + artifact.projection.view.raw_indices_eq, hrawResult, + VExpr.instL_forallN, VExpr.forallN, VExpr.instL] + have hparamsFamily : c.venv.SpineWF c.lparams.length c.vlctx.toCtx + (artifact.projection.view.familyType.instL levels) params + (.sort (resultLevel.inst levels)) := by + rw [hfamilyShape] + exact hparamsSpine + have hfullStruct : c.TrExprS normalizedType + (artifact.projection.view.structureType levels params) := by + rw [← normalizedType.mkAppList_getAppArgsList] + simpa [VStructureView.structureType, + artifact.projection.name_eq] using hfullTr + have hfullEq := hfullStruct.uniq c.Ewf (.refl c.Ewf c.Δwf) tTypeTr + have hstructTy₁ := VEnv.IsDefEqU.trans c.Ewf c.Δwf hfullEq tTypeEq + have hstructTy₂ := VEnv.IsDefEqU.trans c.Ewf c.Δwf hfullEq (h hb) + have haStruct := aTyped.defeqU_r c.Ewf c.Δwf hstructTy₁.symm + have hbStruct := bTyped.defeqU_r c.Ewf c.Δwf hstructTy₂.symm + have heta₁ := artifact.eta c.Δwf hlevelsWF hlevelsLength + hparamsLength ⟨_, hparamsFamily⟩ haStruct + have heta₂ := artifact.eta c.Δwf hlevelsWF hlevelsLength + hparamsLength ⟨_, hparamsFamily⟩ hbStruct + have hfieldsLength : artifact.projection.view.fields.length = 0 := by + calc + artifact.projection.view.fields.length = + artifact.projection.constructorInfo.numFields := + artifact.projection.constructor_numFields_eq.symm + _ = constructorInfo.numFields := + congrArg ConstructorVal.numFields artifact.constructor_info_eq + _ = 0 := rfl + have hfields : artifact.projection.view.fields = [] := + List.length_eq_zero_iff.mp hfieldsLength + have hrebuild : + artifact.projection.view.etaRebuild levels params e₁' = + artifact.projection.view.etaRebuild levels params e₂' := by + simp [VStructureView.etaRebuild, VStructureView.projectionArgs, + VStructureView.specializedFields, hfields] + rw [hrebuild] at heta₁ + exact VEnv.IsDefEqU.trans c.Ewf c.Δwf ⟨_, heta₁.symm⟩ ⟨_, heta₂⟩ + +theorem isDefEqUnitLike.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEqUnitLike e₁ e₂) fun b _ => b = .true → c.IsDefEqU e₁' e₂' := + isDefEqUnitLike.WF_of_structureEta he₁ he₂ + +theorem isDefEqCore'.WF {c : VContext} {s : VState} + (he₁ : c.TrExprS e₁ e₁') (he₂ : c.TrExprS e₂ e₂') : + RecM.WF c s (isDefEqCore' e₁ e₂) fun b _ => b = true → c.IsDefEqU e₁' e₂' := by + unfold isDefEqCore'; extract_lets F1 + refine (quickIsDefEq.WF he₁ he₂).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun hb => h (by simpa using hb); skip] + refine .readThe ?_ + suffices ∀ {s}, RecM.WF c s (F1 ⟨⟩) fun b _ => b = true → c.IsDefEqU e₁' e₂' by + split <;> [rename_i h1; exact this] + refine (whnf.WF he₁).bind fun _ _ _ ⟨_, _, a1, a2⟩ => ?_ + split <;> [rename_i h2; exact this] + refine .pure fun _ => ?_ + simp [Expr.isConstOf] at h1 h2 + split at h1 <;> simp at h1; cases h1.2; split at h2 <;> simp at h2; cases h2 + let .const b1 b2 b3 := he₂ + let .const c1 c2 c3 := a1 + cases c.hasPrimitives.boolTrue b1 + cases c.hasPrimitives.boolTrue c1 + simp at b3 c3; subst b3 c3; simp at b2 c2; subst b2 c2 + exact a2.symm + intro; unfold F1 + refine (whnfCore.WF he₁).bind fun _ _ _ ⟨_, e₁', a1, a2⟩ => ?_ + refine (whnfCore.WF he₂).bind fun _ _ _ ⟨_, e₂', b1, b2⟩ => ?_ + extract_lets F2 + refine .mono (Q := fun b _ => b = true → c.IsDefEqU e₁' e₂') ?_ fun _ _ _ h hb => + a2.symm.trans c.Ewf c.Δwf (h (by simpa using hb)) |>.trans c.Ewf c.Δwf b2 + suffices ∀ {s}, RecM.WF c s (F2 ⟨⟩) fun b _ => b = true → c.IsDefEqU e₁' e₂' by + split <;> [skip; exact this] + refine (quickIsDefEq.WF a1 b1).bind fun _ _ _ h => ?_ + split <;> [skip; exact this] + exact .pure fun hb => h (by simpa using hb) + intro; unfold F2 + refine (isDefEqProofIrrel.WF a1 b1).bind fun _ _ _ h => ?_ + split + · exact .pure fun hb => h (by simpa using hb) + refine (lazyDeltaReduction.loop.WF a1 b1).readThe.bind fun _ _ _ h => ?_; split + · cases h.1 + · exact .pure h + have ⟨⟨e₁', c1, c4⟩, ⟨e₂', d1, d4⟩⟩ := h + refine .mono (Q := fun b _ => b = true → c.IsDefEqU e₁' e₂') ?_ fun _ _ _ h hb => + c4.symm.trans c.Ewf c.Δwf (h (by simpa using hb)) |>.trans c.Ewf c.Δwf d4 + extract_lets F3 + suffices ∀ {s}, RecM.WF c s (F3 ⟨⟩) fun b _ => b = true → c.IsDefEqU e₁' e₂' by + split + · split <;> [rename_i h2; exact this] + refine .pure fun _ => ?_ + simp at h2; cases h2.1 + have .const c1 c2 c3 := c1; have .const d1 d2 d3 := d1 + cases d1.symm.trans c1 + have := VEnv.IsDefEq.constDF c1 + (Γ := c.vlctx.toCtx) (.of_mapM_ofLevel c2) (.of_mapM_ofLevel d2) + ((List.mapM_eq_some.1 c2).length_eq.symm.trans c3) + (Level.isEquivList_wf h2.2 c2 d2) + exact this.toU + · split <;> [rename_i h; exact this] + simp at h; subst h + exact .pure fun _ => c1.uniq c.Ewf (.refl c.Ewf c.Δwf) d1 + · split <;> [rename_i h2; exact this] + have .proj c1 c2 := c1; have .proj d1 d2 := d1 + refine (isDefEq.WF c1 d1).bind fun _ _ _ h => ?_ + split <;> [skip; exact this] + simp at h2; subst h2; clear h + exact .pure fun _ => c2.uniq c.Ewf (.refl c.Δwf) d2 (h ‹_›) + · exact this + intro; unfold F3 + refine (whnfCore.WF c1).bind fun _ _ _ ⟨_, e₁'', c5, c6⟩ => ?_ + refine (whnfCore.WF d1).bind fun _ _ _ ⟨_, e₂'', d5, d6⟩ => ?_ + split + · exact (isDefEqCore.WF c5 d5).mono fun _ _ _ h hb => + c6.symm.trans c.Ewf c.Δwf (h (by simpa using hb)) |>.trans c.Ewf c.Δwf d6 + refine (isDefEqApp.WF c1 d1).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun _ => h ‹_›; skip] + refine (tryEtaExpansion.WF c1 d1).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun _ => h ‹_›; skip] + refine (tryEtaStruct.WF c1 d1).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun _ => h ‹_›; skip] + refine (tryStringLitExpansion.WF c1 d1).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun hb => h (by simpa using hb); skip] + refine (isDefEqUnitLike.WF c1 d1).bind fun _ _ _ h => ?_ + split <;> [exact .pure fun _ => h ‹_›; skip] + exact .pure nofun diff --git a/Ix/Theory/Named/Verify/TypeChecker/Reduce.lean b/Ix/Theory/Named/Verify/TypeChecker/Reduce.lean new file mode 100644 index 000000000..82daec369 --- /dev/null +++ b/Ix/Theory/Named/Verify/TypeChecker/Reduce.lean @@ -0,0 +1,221 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.TypeChecker.Basic + +namespace Ix.Theory.Named.TypeChecker.Inner +open Lean hiding Environment Exception +open Kernel + +theorem reduceNative.WF : + (reduceNative env e).WF fun oe => ∀ e₁, oe = some e₁ → False := by + unfold reduceNative; split <;> [skip; exact .pure nofun] + split <;> [exact .throw; skip]; split <;> [exact .throw; exact .pure nofun] + +theorem rawNatLitExt?.WF {c : VContext} (H : rawNatLitExt? e = some n) (he : c.TrExprS e e') : + c.venv.contains ``Nat ∧ e' = .natLit n := by + have : c.TrExprS (.lit (.natVal n)) e' := by + unfold rawNatLitExt? at H; split at H <;> rename_i h + · cases H; have := he.eqv h; exact .lit (this.nat_of_natZero c.Ewf c.hasPrimitives) this + · unfold Expr.rawNatLit? at H; split at H <;> cases H; exact he + have hn := this.lit_has_type + exact ⟨hn, this.unique (by trivial) (TrExprS.natLit c.hasPrimitives hn n).1⟩ + +/-- `checkNatSize` either throws or leaves the state alone, so it is transparent to any +postcondition that already holds. -/ +theorem checkNatSize.WF {c : VContext} {s : VState} {Q : Unit → VState → Prop} (H : Q () s) : + RecM.WF c s (checkNatSize n) Q := by + unfold checkNatSize; exact .readThe (by split <;> [exact .throw; exact .pure H]) + +@[inherit_doc checkNatSize.WF] +theorem checkCountArg.WF {c : VContext} {s : VState} {Q : Unit → VState → Prop} (H : Q () s) : + RecM.WF c s (checkCountArg n op) Q := by + unfold checkCountArg; split <;> [exact .throw; exact .pure H] + +@[inherit_doc checkNatSize.WF] +theorem checkLitSize.WF {c : VContext} {s : VState} {Q : Unit → VState → Prop} (H : Q () s) : + RecM.WF c s (checkLitSize l) Q := by + unfold checkLitSize; split <;> [exact checkNatSize.WF H; exact .pure H] + +@[inherit_doc checkNatSize.WF] +theorem checkNatSizeIf.WF {c : VContext} {s : VState} {Q : Unit → VState → Prop} (H : Q () s) : + RecM.WF c s (checkNatSizeIf checkSize n) Q := by + unfold checkNatSizeIf; split <;> [exact checkNatSize.WF H; exact .pure H] + +@[inherit_doc checkNatSize.WF] +theorem checkPowSize.WF {c : VContext} {s : VState} {Q : Unit → VState → Prop} (H : Q () s) : + RecM.WF c s (checkPowSize base exp) Q := by + unfold checkPowSize + exact (checkCountArg.WF H).bind fun _ _ _ H => + .readThe (by split <;> [exact .throw; exact .pure H]) + +@[inherit_doc checkNatSize.WF] +theorem checkShiftLeftSize.WF {c : VContext} {s : VState} {Q : Unit → VState → Prop} (H : Q () s) : + RecM.WF c s (checkShiftLeftSize v shift) Q := by + unfold checkShiftLeftSize + split <;> [exact (checkCountArg.WF H).bind fun _ _ _ H => checkNatSize.WF H; exact .pure H] + +/-- The shared skeleton of the binary `Nat` reductions: reduce both operands to literals, run a +size `check` that can only throw, and return the literal `f v1 v2`. -/ +theorem reduceBinNatOpCore.WF {c : VContext} {check : Nat → Nat → RecM Unit} + (hcheck : ∀ {v1 v2 s'} {Q : Unit → VState → Prop}, Q () s' → RecM.WF c s' (check v1 v2) Q) + (he : c.TrExprS (.app (.app (.const fc ls) a) b) e') + (hprim : Environment.primitives.contains fc) + (heval : c.venv.ReflectsNatNatNat fc f) : + RecM.WF c s (do + let some v1 := rawNatLitExt? (← whnf a) | return none + let some v2 := rawNatLitExt? (← whnf b) | return none + check v1 v2 + return some <| .lit <| .natVal <| f v1 v2) + fun oe _ => ∀ e₁, oe = some e₁ → + c.FVarsBelow (.app (.app (.const fc ls) a) b) e₁ ∧ c.TrExpr e₁ e' := by + let .app hb1 hb2 hf hb := he + let .app ha1 ha2 hf ha := hf + let .const h1 h2 h3 := hf + refine (whnf.WF ha).bind fun a₁ _ _ ⟨a1, _, a2, a3⟩ => ?_ + split <;> [rename_i v1 h; exact .pure nofun] + obtain ⟨hn, rfl⟩ := rawNatLitExt?.WF h a2 + refine (whnf.WF hb).bind fun b₁ _ _ ⟨b1, _, b2, b3⟩ => ?_ + split <;> [rename_i v2 h; exact .pure nofun] + cases (rawNatLitExt?.WF h b2).2 + refine (hcheck (Q := fun _ _ => True) trivial).bind fun _ _ _ _ => ?_ + refine .pure ?_; rintro _ ⟨⟩; refine ⟨fun _ _ _ => trivial, ?_⟩ + have ⟨ci, c1, _⟩ := c.trenv.find?_iff.2 ⟨_, h1⟩ + have ⟨_, c3⟩ := c.safePrimitives c1 hprim + have ⟨_, d1, d2, d3⟩ := c.trenv.find?_uniq c1 h1 + simp [c3] at d2; simp [← d2] at h3; simp [h3] at h2; subst h2 + refine ⟨_, (TrExprS.natLit c.hasPrimitives hn _).1, ?_⟩ + have := heval ⟨_, h1⟩ v1 v2 |>.instL (U' := c.lparams.length) (ls := []) nofun + simp [VExpr.instL] at this + refine this.weak0 c.Ewf (Γ := c.vlctx.toCtx) |>.symm.trans c.Ewf c.Δwf ?_ + have a3 := a3.of_r c.Ewf c.Δwf ha2 + have b3 := b3.of_r c.Ewf c.Δwf hb2 + have := ha1.appDF a3 |>.toU.of_r c.Ewf c.Δwf hb1 + exact ⟨_, .appDF this b3⟩ + +theorem reduceBinNatOp.WF {c : VContext} + (he : c.TrExprS (.app (.app (.const fc ls) a) b) e') + (hprim : Environment.primitives.contains fc) + (heval : c.venv.ReflectsNatNatNat fc f) : + RecM.WF c s (reduceBinNatOp f a b checkSize) fun oe _ => ∀ e₁, oe = some e₁ → + c.FVarsBelow (.app (.app (.const fc ls) a) b) e₁ ∧ c.TrExpr e₁ e' := by + unfold reduceBinNatOp + exact reduceBinNatOpCore.WF (fun H => checkNatSizeIf.WF H) he hprim heval + +theorem reducePow.WF {c : VContext} + (he : c.TrExprS (.app (.app (.const fc ls) a) b) e') + (hprim : Environment.primitives.contains fc) + (heval : c.venv.ReflectsNatNatNat fc Nat.pow) : + RecM.WF c s (reducePow a b) fun oe _ => ∀ e₁, oe = some e₁ → + c.FVarsBelow (.app (.app (.const fc ls) a) b) e₁ ∧ c.TrExpr e₁ e' := by + unfold reducePow + exact reduceBinNatOpCore.WF (fun H => checkPowSize.WF H) he hprim heval + +theorem reduceShiftLeft.WF {c : VContext} + (he : c.TrExprS (.app (.app (.const fc ls) a) b) e') + (hprim : Environment.primitives.contains fc) + (heval : c.venv.ReflectsNatNatNat fc (· <<< ·)) : + RecM.WF c s (reduceShiftLeft a b) fun oe _ => ∀ e₁, oe = some e₁ → + c.FVarsBelow (.app (.app (.const fc ls) a) b) e₁ ∧ c.TrExpr e₁ e' := by + unfold reduceShiftLeft + exact reduceBinNatOpCore.WF (fun H => checkShiftLeftSize.WF H) he hprim heval + +theorem reduceBinNatPred.WF {c : VContext} + (he : c.TrExprS (.app (.app (.const fc ls) a) b) e') + (hprim : Environment.primitives.contains fc) + (heval : c.venv.ReflectsNatNatBool fc f) : + RecM.WF c s (reduceBinNatPred f a b) fun oe _ => ∀ e₁, oe = some e₁ → + c.FVarsBelow (.app (.app (.const fc ls) a) b) e₁ ∧ c.TrExpr e₁ e' := by + let .app hb1 hb2 hf hb := he + let .app ha1 ha2 hf ha := hf + let .const h1 h2 h3 := hf + unfold reduceBinNatPred + refine (whnf.WF ha).bind fun a₁ _ _ ⟨a1, _, a2, a3⟩ => ?_ + split <;> [rename_i v1 h; exact .pure nofun]; cases (rawNatLitExt?.WF h a2).2 + refine (whnf.WF hb).bind fun b₁ _ _ ⟨b1, _, b2, b3⟩ => ?_ + split <;> [rename_i v2 h; exact .pure nofun]; cases (rawNatLitExt?.WF h b2).2 + refine .pure ?_; rintro _ ⟨⟩; refine ⟨fun _ _ _ => .boolLit, ?_⟩ + have ⟨ci, c1, _⟩ := c.trenv.find?_iff.2 ⟨_, h1⟩ + have ⟨_, c3⟩ := c.safePrimitives c1 hprim + have ⟨_, d1, d2, d3⟩ := c.trenv.find?_uniq c1 h1 + simp [c3] at d2; simp [← d2] at h3; simp [h3] at h2; subst h2 + have := heval ⟨_, h1⟩ v1 v2 |>.instL (U' := c.lparams.length) (ls := []) nofun + simp [VExpr.instL] at this + refine ⟨_, (TrExprS.boolLit c.hasPrimitives ?_ _).1, ?_⟩ + · let ⟨_, H⟩ := this + exact VExpr.WF.boolLit_has_type c.Ewf c.hasPrimitives (Γ := []) trivial ⟨_, H.hasType.2⟩ + refine this.weak0 c.Ewf (Γ := c.vlctx.toCtx) |>.symm.trans c.Ewf c.Δwf ?_ + have a3 := a3.of_r c.Ewf c.Δwf ha2 + have b3 := b3.of_r c.Ewf c.Δwf hb2 + have := ha1.appDF a3 |>.toU.of_r c.Ewf c.Δwf hb1 + exact ⟨_, .appDF this b3⟩ + +theorem reduceNat.WF {c : VContext} (he : c.TrExprS e e') : + RecM.WF c s (reduceNat e) fun oe _ => ∀ e₁, oe = some e₁ → + c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := by + generalize hP : (fun oe => _) = P + refine let prims := _; have hprims : Environment.primitives = .ofList prims := rfl; ?_ + replace hprims {a} : Environment.primitives.contains a ↔ a ∈ prims := by + simp [hprims, NameSet.contains, NameSet.ofList] + unfold reduceNat; extract_lets nargs F1 fn + cases h1 : nargs == 1 <;> simp only [Bool.false_eq_true, ↓reduceIte] + · cases nargs == 2 <;> [exact hP ▸ .pure nofun; simp only [↓reduceIte]] + split <;> [rename_i f ls a b; exact hP ▸ .pure nofun] + have hfun checkSize {g fc G} (hprim : fc ∈ prims) + (heval : c.venv.ReflectsNatNatNat fc g) (hG : RecM.WF c s G P) : + RecM.WF c s (do if f == fc then {return ← reduceBinNatOp g a b checkSize}; G) P := by + split <;> [rename_i h; exact hG] + simp at h ⊢; subst h + exact hP ▸ reduceBinNatOp.WF he (hprims.2 hprim) heval + have hpow {fc G} (hprim : fc ∈ prims) + (heval : c.venv.ReflectsNatNatNat fc Nat.pow) (hG : RecM.WF c s G P) : + RecM.WF c s (do if f == fc then {return ← reducePow a b}; G) P := by + split <;> [rename_i h; exact hG] + simp at h ⊢; subst h + exact hP ▸ reducePow.WF he (hprims.2 hprim) heval + have hshl {fc G} (hprim : fc ∈ prims) + (heval : c.venv.ReflectsNatNatNat fc (· <<< ·)) (hG : RecM.WF c s G P) : + RecM.WF c s (do if f == fc then {return ← reduceShiftLeft a b}; G) P := by + split <;> [rename_i h; exact hG] + simp at h ⊢; subst h + exact hP ▸ reduceShiftLeft.WF he (hprims.2 hprim) heval + have hpred {g fc G} (hprim : fc ∈ prims) + (heval : c.venv.ReflectsNatNatBool fc g) (hG : RecM.WF c s G P) : + RecM.WF c s (do if f == fc then {return ← reduceBinNatPred g a b}; G) P := by + split <;> [rename_i h; exact hG] + simp at h ⊢; subst h + exact hP ▸ reduceBinNatPred.WF he (hprims.2 hprim) heval + apply hfun true (by simp [prims]) c.hasPrimitives.natAdd + apply hfun true (by simp [prims]) c.hasPrimitives.natSub + apply hfun true (by simp [prims]) c.hasPrimitives.natMul + apply hpow (by simp [prims]) c.hasPrimitives.natPow + apply hfun false (by simp [prims]) c.hasPrimitives.natGcd + apply hfun false (by simp [prims]) c.hasPrimitives.natMod + apply hfun false (by simp [prims]) c.hasPrimitives.natDiv + apply hpred (by simp [prims]) c.hasPrimitives.natBEq + apply hpred (by simp [prims]) c.hasPrimitives.natBLE + apply hfun false (by simp [prims]) c.hasPrimitives.natLAnd + apply hfun false (by simp [prims]) c.hasPrimitives.natLOr + apply hfun false (by simp [prims]) c.hasPrimitives.natXor + apply hshl (by simp [prims]) c.hasPrimitives.natShiftLeft + apply hfun false (by simp [prims]) c.hasPrimitives.natShiftRight + exact hP ▸ .pure nofun + · split <;> [rename_i h2; exact hP ▸ .pure nofun] + simp [nargs, Expr.getAppNumArgs_eq] at h1; subst fn + let .app f a := e; simp [Expr.appFn!, Expr.structuralEq_const] at h2 ⊢; subst h2 + let .app ha1 ha2 hf ha := he + let .const h1 h2 h3 := hf + refine (whnf.WF ha).bind fun a₁ _ _ ⟨a1, _, a2, a3⟩ => ?_ + split <;> [rename_i n h; exact hP ▸ .pure nofun] + obtain ⟨hn, rfl⟩ := rawNatLitExt?.WF h a2 + refine hP ▸ (checkNatSize.WF (Q := fun _ _ => True) trivial).map fun _ _ _ _ => ?_ + rintro _ ⟨⟩; refine ⟨fun _ _ _ => trivial, ?_⟩ + have ⟨ci, c1, _⟩ := c.trenv.find?_iff.2 ⟨_, h1⟩ + have ⟨c2, c3⟩ := c.safePrimitives c1 <| hprims.2 (by simp [prims]) + have ⟨d1, d2, d3⟩ := c.trenv.find?_uniq c1 h1; cases h2 + refine have ⟨p1, p2⟩ := TrExprS.natLit c.hasPrimitives hn _; ⟨_, p1, ?_⟩ + refine p2.toU.symm.trans c.Ewf c.Δwf ?_ + exact ⟨_, ha1.appDF <| a3.of_r c.Ewf c.Δwf ha2⟩ diff --git a/Ix/Theory/Named/Verify/TypeChecker/WHNF.lean b/Ix/Theory/Named/Verify/TypeChecker/WHNF.lean new file mode 100644 index 000000000..ab307a02f --- /dev/null +++ b/Ix/Theory/Named/Verify/TypeChecker/WHNF.lean @@ -0,0 +1,275 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.TypeChecker.Reduce + +namespace Ix.Theory.Named.TypeChecker.Inner +open Lean hiding Environment Exception + +set_option warn.sorry false in +theorem reduceRecursor.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (reduceRecursor e) fun oe _ => + ∀ e₁, oe = some e₁ → c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := sorry + +theorem whnfFVar.WF {c : VContext} {s : VState} (he : c.TrExprS (.fvar fv) e') : + RecM.WF c s (whnfFVar (.fvar fv) cheapProj) fun e₁ _ => + c.FVarsBelow (.fvar fv) e₁ ∧ c.TrExpr e₁ e' := by + refine .getLCtx ?_ + simp [Expr.fvarId!]; split <;> [skip; exact .pure ⟨.rfl, he.trExpr c.Ewf c.Δwf⟩] + rename_i decl h + rw [c.trlctx.1.find?_eq_find?_toList] at h + have := List.find?_some h; simp at this; subst this + let ⟨e', ty', h1, h2, _, h3, _⟩ := + c.trlctx.find?_of_mem c.Ewf (List.mem_of_find?_eq_some h) + refine (whnfCore.WF h3).mono fun _ _ _ ⟨h4, h5⟩ => ?_ + refine ⟨h2.trans h4, h5.defeq c.Ewf c.Δwf ?_⟩ + refine (TrExprS.fvar h1).uniq c.Ewf ?_ he + exact .refl c.Ewf c.Δwf + +theorem reduceProj.WF {c : VContext} {s : VState} (he : c.TrExprS (.proj n i e) e') : + RecM.WF c s (reduceProj i e cheapProj) fun oe _ => + ∀ e₁, oe = some e₁ → c.FVarsBelow (.proj n i e) e₁ ∧ c.TrExpr e₁ e' := by + let .proj (e' := major) heMajor hproj := he + obtain ⟨view, levels, params, _hviewName, hsemantic⟩ := hproj + obtain ⟨code, hcode, hresult, hprojector⟩ := hsemantic.program + have finish {normal : Expr} {state : VState} + (hbelow : c.FVarsBelow e normal) + (htr : c.TrExpr normal major) : + RecM.WF c state + (normal.withApp fun mk args => do + let .const mkC _ := mk | return none + let env ← getEnv + let .ctorInfo mkInfo ← env.get mkC | return none + return args[mkInfo.numParams + i]?) (fun oe _ => + ∀ e₁, oe = some e₁ → + c.FVarsBelow (.proj n i e) e₁ ∧ c.TrExpr e₁ e') := by + rw [Expr.withApp_eq] + split + · rename_i mkC hostLevels hheadShape + obtain ⟨runtimeMajor, hnormalS, hnormalEq⟩ := htr + have ⟨runtimeHead, hstack⟩ := AppStack.build + (normal.mkAppList_getAppArgsList ▸ hnormalS) + have hhead := hstack.tr + rw [hheadShape] at hhead + let .const (us' := runtimeLevels) _hconst _hlevelsMap + _hlevelsLength := hhead + obtain ⟨runtimeArgs, hargsTr, hfull⟩ := hstack.argsTranslation + rw [normal.mkAppList_getAppArgsList] at hfull + have hfullEq := hfull.uniq c.Ewf (.refl c.Ewf c.Δwf) hnormalS + have hmajorEq := hfullEq.trans c.Ewf c.Δwf hnormalEq + refine .getEnv ?_ + refine (M.WF.liftExcept envGet.WF).lift.bind fun _ci _ _ hfind => ?_ + split + · rename_i mkInfo + refine .pure ?_ + intro selected hselected + have hconstructorName : mkC = view.constructorName := + c.Ewf.registeredStructureHeadInversion.constructor_name_inv + c.Δwf hsemantic rfl hmajorEq + have hnumParams : mkInfo.numParams = view.nparams := + c.projectionReady.constructorNumParams view mkInfo + hsemantic.viewWF (by + rw [← hconstructorName] + exact hfind) + have hselectedList : + normal.getAppArgsList[mkInfo.numParams + i]? = some selected := by + rw [← Expr.getAppArgs_toList, Array.getElem?_toList] + exact hselected + obtain ⟨runtimeField, hfieldGet, hfieldTr⟩ := + Ix.Theory.Named.List.Forall₂.getElem?_left hargsTr hselectedList + have hfieldGetCanonical : + runtimeArgs[view.nparams + i]? = some runtimeField := by + rw [← hnumParams] + exact hfieldGet + obtain ⟨alignment⟩ := + c.Ewf.registeredStructureHeadInversion.constructor_inv + c.Δwf hsemantic hcode rfl hfieldGetCanonical hmajorEq + have hiota := hsemantic.projector_constructor_aligned + c.Ewf c.Δwf hcode hprojector alignment + have hmajorTyped := hmajorEq.of_r c.Ewf c.Δwf hsemantic.majorType + have hprojectorCongr : c.IsDefEqU + (.app code.projector + (VExpr.appN (.const mkC runtimeLevels) runtimeArgs)) + (.app code.projector major) := + ⟨_, hprojector.appDF hmajorTyped⟩ + have hfieldTarget : c.IsDefEqU runtimeField e' := by + rw [hresult] + exact hiota.symm.trans c.Ewf c.Δwf hprojectorCongr + refine ⟨?_, ⟨runtimeField, hfieldTr, hfieldTarget⟩⟩ + intro P hP hprojFv + exact FVarsIn.getAppArgsList (hbelow P hP hprojFv) + (List.mem_of_getElem? hselectedList) + · exact .pure nofun + · exact .pure nofun + unfold reduceProj + split + · refine (whnfCore.WF heMajor).bind fun normal _ _ hnormal => ?_ + split + · obtain ⟨literalMajor, hliteralS, hliteralEq⟩ := hnormal.2 + let .lit _ hconstructorS := hliteralS + refine (whnf.WF hconstructorS).bind fun expanded _ _ hexpanded => ?_ + have hbelow' : c.FVarsBelow e expanded := + FVarsBelow.trans (fun _ _ _ => FVarsIn.strLitToConstructor) + hexpanded.1 + have htr' := hexpanded.2.defeq c.Ewf c.Δwf hliteralEq + exact RecM.WF.pureBind (finish hbelow' htr') + · exact RecM.WF.pureBind (finish hnormal.1 hnormal.2) + · refine (whnf.WF heMajor).bind fun normal _ _ hnormal => ?_ + split + · obtain ⟨literalMajor, hliteralS, hliteralEq⟩ := hnormal.2 + let .lit _ hconstructorS := hliteralS + refine (whnf.WF hconstructorS).bind fun expanded _ _ hexpanded => ?_ + have hbelow' : c.FVarsBelow e expanded := + FVarsBelow.trans (fun _ _ _ => FVarsIn.strLitToConstructor) + hexpanded.1 + have htr' := hexpanded.2.defeq c.Ewf c.Δwf hliteralEq + exact RecM.WF.pureBind (finish hbelow' htr') + · exact RecM.WF.pureBind (finish hnormal.1 hnormal.2) + +theorem whnfCore'.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (whnfCore' e cheapProj) fun e₁ _ => + c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := by + unfold whnfCore'; extract_lets F + let full := (· matches Expr.fvar _ | .app .. | .letE .. | .proj ..) + generalize hP : (fun e₁ (_ : VState) => _) = P + have hid {s} : RecM.WF c s (pure e) P := hP ▸ .pure ⟨.rfl, he.trExpr c.Ewf c.Δwf⟩ + suffices hF : full e → RecM.WF c s (F ⟨⟩) P by + split + any_goals exact hid + any_goals exact hF rfl + · let .mdata he := he + exact hP ▸ whnfCore'.WF he + · refine .getLCtx ?_; split <;> [exact hid; exact hF rfl] + simp [F]; refine fun hfull => .get ?_; split + · rename_i r eq; refine .stateWF fun wf => hP ▸ .pure ?_ + have ⟨_, h1, h2, h3⟩ := (wf.whnfCore_wf eq).2.2.2.2 he.fvarsIn + refine ⟨h1, h3.defeq c.Ewf c.Δwf ?_⟩ + exact h2.uniq c.Ewf (.refl c.Ewf c.Δwf) he + have hsave {e₁ s} (h1 : c.FVarsBelow e e₁) (h2 : c.TrExpr e₁ e') : + (save e cheapProj e₁).WF c s P := by + simp [save] + split <;> [skip; exact hP ▸ .pure ⟨h1, h2⟩] + rintro _ mwf wf a s' ⟨⟩ + refine let s' := _; ⟨s', rfl, ?_⟩ + have hic {ic} (hic : WHNFCache.WF c s ic) : WHNFCache.WF c s (ic.insert e e₁) := by + intro _ _ h + rw [Std.HashMap.getElem?_insert] at h; split at h <;> [cases h; exact hic h] + rename_i eq + refine .mk c.mlctx.noBV (.eqv h1 eq BEq.rfl) (he.eqv eq) h2 (.eqv eq ?_) ?_ --_ (.eqv h2 eq BEq.rfl) (.eqv eq ?_) ?_ + · exact he.fvarsIn.mono wf.ngen_wf + · exact h2.fvarsIn.mono wf.ngen_wf + exact hP ▸ ⟨.rfl, { wf with whnfCore_wf := hic wf.whnfCore_wf }, h1, h2⟩ + split <;> cases hfull + · exact hP ▸ whnfFVar.WF he + · rename_i fn arg _; generalize eq : fn.app arg = e at * + have ⟨_, stk⟩ := AppStack.build <| e.mkAppList_getAppArgsList ▸ he + refine (whnfCore.WF stk.tr).bind fun _ s _ ⟨h1, h2⟩ => ?_ + split <;> [rename_i name dom body bi _; split] + · let rec loop.WF {e e' i rargs f} (H : LambdaBodyN i e' f) (hi : i ≤ rargs.size) : + ∃ n f', LambdaBodyN n e' f' ∧ n ≤ rargs.size ∧ + loop e cheapProj rargs i f = loop.cont e cheapProj rargs n f' := by + unfold loop; split + · split + · refine loop.WF (by simpa [Nat.add_comm] using H.add (.succ .zero)) ‹_› + · exact ⟨_, _, H, hi, rfl⟩ + · exact ⟨_, _, H, hi, rfl⟩ + refine + let ⟨i, f, h3, h4, eq⟩ := loop.WF (e' := .lam name dom body bi) (.succ .zero) <| by + simp [← eq, Expr.getAppRevArgs_eq, Expr.getAppArgsRevList] + eq ▸ ?_; clear eq + simp [Expr.getAppRevArgs_eq] at h4 ⊢ + obtain ⟨l₁, l₂, h5, rfl⟩ : ∃ l₁ l₂, e.getAppArgsRevList = l₁ ++ l₂ ∧ l₂.length = i := + ⟨_, _, (List.take_append_drop (e.getAppArgsRevList.length - i) ..).symm, by simp; omega⟩ + simp [loop.cont, h5, List.take_of_length_le] + rw [Expr.mkAppRevRange_eq_rev (l₁ := []) (l₂ := l₁) (l₃ := l₂) (by simp) (by rfl) (by rfl)] + have br := BetaReduce.inst_reduce (l₁ := l₂.reverse) + [] (by simpa using h3) (Expr.instantiateList_append ..) (h := by + have := h5 ▸ (c.mlctx.noBV ▸ he.closed).getAppArgsRevList + simp [or_imp, forall_and] at this ⊢ + exact this.2) |>.mkAppRevList (es := l₁) + simp [← Expr.mkAppRevList_reverse, ← Expr.mkAppRevList_append, ← h5] at br + have := h2.rebuild_mkAppRevList c.Ewf c.Δwf stk.tr <| + e.mkAppRevList_getAppArgsRevList ▸ he + have ⟨_, a1, a2⟩ := this.beta c.Ewf c.Δwf br + refine (whnfCore.WF a1).bind fun _ _ _ ⟨b1, b2⟩ => ?_ + have hb := e.mkAppRevList_getAppArgsRevList ▸ h1.mkAppRevList + exact hsave (hb.trans (.betaReduce br) |>.trans b1) <| + b2.defeq c.Ewf c.Δwf a2 + · refine (reduceRecursor.WF he).bind fun _ _ _ h => ?_ + split <;> [skip; exact hid] + let ⟨h1, _, h2, eq⟩ := h _ rfl + refine hP ▸ (whnfCore.WF h2).mono fun _ _ _ ⟨h3, h4⟩ => ?_ + exact ⟨h1.trans h3, h4.defeq c.Ewf c.Δwf eq⟩ + · rw [Expr.mkAppRevRange_eq_rev (l₁ := []) (l₃ := []) + (by simp [Expr.getAppRevArgs_toList]; rfl) (by rfl) (by simp [Expr.getAppRevArgs_eq])] + have {e e₁ : Expr} (hb : c.FVarsBelow e e₁) {es e₀' e'} + (hes : c.TrExprS (e.mkAppRevList es) e₀') (he : c.TrExprS e e') (he₁ : c.TrExpr e₁ e') : + c.FVarsBelow (e.mkAppRevList es) (e₁.mkAppRevList es) ∧ + c.TrExpr (e₁.mkAppRevList es) e₀' := by + induction es generalizing e₁ e₀' e' with + | nil => + refine ⟨hb, he₁.defeq c.Ewf c.Δwf ?_⟩ + exact he.uniq c.Ewf (.refl c.Ewf c.Δwf) hes + | cons _ _ ih => + have .app h1 h2 h3 h4 := hes + have ⟨h5, h6⟩ := ih hb h3 he he₁ + exact ⟨fun _ hP he => ⟨h5 _ hP he.1, he.2⟩, + .app c.Ewf c.Δwf h1 h2 h6 (h4.trExpr c.Ewf c.Δwf)⟩ + have eq := e.mkAppRevList_getAppArgsRevList + let ⟨h3, _, h4, eq⟩ := eq ▸ this h1 (eq ▸ he) stk.tr h2 + refine (whnfCore.WF h4).bind fun _ _ _ ⟨h5, h6⟩ => ?_ + refine hsave (h3.trans h5) (h6.defeq c.Ewf c.Δwf eq) + · let .letE h1 h2 h3 h4 := he + refine (whnfCore.WF (h4.inst_let c.Ewf.ordered h3)).bind fun _ _ _ ⟨h1, h2⟩ => ?_ + exact hsave (.trans (fun _ _ he => he.2.2.instantiate1 he.2.1) h1) h2 + · refine (reduceProj.WF he).bind fun _ _ _ H => ?_ + split + · let ⟨h1, _, h2, eq⟩ := H _ rfl + refine (whnfCore.WF h2).bind fun _ _ _ ⟨h3, h4⟩ => ?_ + exact hsave (h1.trans h3) (h4.defeq c.Ewf c.Δwf eq) + · exact hsave .rfl (he.trExpr c.Ewf c.Δwf) + +theorem whnf'.WF {c : VContext} {s : VState} (he : c.TrExprS e e') : + RecM.WF c s (whnf' e) fun e₁ _ => c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := by + unfold whnf'; extract_lets F + generalize hP : (fun e₁ (_ : VState) => _) = P + have hid {s} : RecM.WF c s (pure e) P := hP ▸ .pure ⟨.rfl, he.trExpr c.Ewf c.Δwf⟩ + suffices hF : RecM.WF c s (F ()) P by + split + any_goals exact hid + any_goals exact hF + · let .mdata he := he + exact hP ▸ whnf'.WF he + · refine .getLCtx ?_; split <;> [exact hid; exact hF] + simp [F]; refine .get ?_; split + · rename_i r eq; refine .stateWF fun wf => hP ▸ .pure ?_ + have ⟨_, h1, h2, h3⟩ := (wf.whnf_wf eq).2.2.2.2 he.fvarsIn + refine ⟨h1, h3.defeq c.Ewf c.Δwf ?_⟩ + exact h2.uniq c.Ewf (.refl c.Ewf c.Δwf) he + have {e e' s n} (he : c.TrExprS e e') : (loop e n).WF c s fun e₁ _ => + c.FVarsBelow e e₁ ∧ c.TrExpr e₁ e' := by + induction n generalizing s e e' with | zero => exact .throw | succ n ih => ?_ + refine .getEnv <| (whnfCore'.WF he).bind fun e₁ s _ ⟨h1, _, he₁, eq⟩ => ?_ + refine (M.WF.liftExcept reduceNative.WF).lift.bind fun _ _ _ h3 => ?_ + split <;> [cases h3 _ rfl; skip] + refine (reduceNat.WF he₁).bind fun _ _ _ h3 => ?_; split + · exact .pure ⟨.trans h1 (h3 _ rfl).1, (h3 _ rfl).2.defeq c.Ewf c.Δwf eq⟩ + refine (unfoldDefinition.WF he₁).bind fun _ _ _ H => ?_ + split <;> [skip; exact .pure ⟨h1, _, he₁, eq⟩] + have ⟨a1, _, a2, eq'⟩ := H + refine (ih a2).mono fun _ _ _ ⟨b1, b2⟩ => ?_ + exact ⟨h1.trans <| a1.trans b1, b2.defeq c.Ewf c.Δwf <| eq'.trans c.Ewf c.Δwf eq⟩ + refine .readThe <| (this he).bind fun e₁ s _ ⟨h1, h2⟩ => ?_ + rintro _ mwf wf a s' ⟨⟩ + refine let s' := _; ⟨s', rfl, ?_⟩ + have hic {ic} (hic : WHNFCache.WF c s ic) : WHNFCache.WF c s (ic.insert e e₁) := by + intro _ _ h + rw [Std.HashMap.getElem?_insert] at h; split at h <;> [cases h; exact hic h] + rename_i eq + refine .mk c.mlctx.noBV (.eqv h1 eq BEq.rfl) (he.eqv eq) h2 (.eqv eq ?_) ?_ + · exact he.fvarsIn.mono wf.ngen_wf + · exact h2.fvarsIn.mono wf.ngen_wf + exact hP ▸ ⟨.rfl, { wf with whnf_wf := hic wf.whnf_wf }, h1, h2⟩ diff --git a/Ix/Theory/Named/Verify/Typing/ConditionallyTyped.lean b/Ix/Theory/Named/Verify/Typing/ConditionallyTyped.lean new file mode 100644 index 000000000..80f91f5e1 --- /dev/null +++ b/Ix/Theory/Named/Verify/Typing/ConditionallyTyped.lean @@ -0,0 +1,150 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Typing.Lemmas + +namespace Ix.Theory.Named +open VEnv Lean + +def ConditionallyTyped + (ngen : NameGenerator) (env : VEnv) (Us : List Name) (Δ : VLCtx) (e : Expr) : Prop := + Closed e ∧ FVarsIn ngen.Reserves e ∧ (FVarsIn (· ∈ Δ.fvars) e → ∃ e', TrExprS env Us Δ e e') + +theorem ConditionallyTyped.mk {Δ : VLCtx} + (noBV : Δ.NoBV) (r : FVarsIn ngen.Reserves e) (H : TrExprS env Us Δ e e') : + ConditionallyTyped ngen env Us Δ e := ⟨noBV ▸ H.closed, r, fun _ => ⟨_, H⟩⟩ + +theorem ConditionallyTyped.mono (H : ngen₁ ≤ ngen₂) : + ConditionallyTyped ngen₁ env Us Δ e → ConditionallyTyped ngen₂ env Us Δ e + | ⟨h1, h2, h3⟩ => ⟨h1, h2.mono fun _ h => h.mono H, h3⟩ + +theorem ConditionallyTyped.weakN_inv + (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length ((some fv, d) :: Δ)) + (H : ConditionallyTyped ngen env Us ((some fv, d) :: Δ) e) : + ConditionallyTyped ngen env Us Δ e := by + refine ⟨H.1, H.2.1, fun H2 => ?_⟩ + have := H.2.2 + have ⟨e', h⟩ := H.2.2 H2.fvars_cons + exact TrExprS.weakFV_inv henv (.skip_fvar _ _ .refl) (.refl henv hΔ) h H.1 H2 + +theorem ConditionallyTyped.fresh + (henv : Ordered env) (hΔ : VLCtx.WF env Us.length ((some (⟨ngen.curr⟩, deps), d) :: Δ)) + (H : ConditionallyTyped ngen env Us Δ e) : + ConditionallyTyped ngen env Us ((some (⟨ngen.curr⟩, deps), d) :: Δ) e := by + refine have ⟨H1, H2, H3⟩ := H; ⟨H1, H2, fun H4 => ?_⟩ + refine have ⟨_, h⟩ := H3 (H4.mp ?_ H2); ⟨_, h.weakFV henv (.skip_fvar _ _ .refl) hΔ⟩ + intro _ h1 h2; simp at h1; rcases h1 with rfl | h1 + · cases Nat.lt_irrefl _ (h2 _ rfl) + · exact h1 + +def ConditionallyHasType + (ngen : NameGenerator) (env : VEnv) (Us : List Name) (Δ : VLCtx) (e A : Expr) : Prop := + Closed e ∧ FVarsIn ngen.Reserves e ∧ Closed A ∧ FVarsIn ngen.Reserves A ∧ + (FVarsIn (· ∈ Δ.fvars) e → ∃ e' A', TrTyping env Us Δ e A e' A') + +theorem ConditionallyHasType.mk {Δ : VLCtx} + (noBV : Δ.NoBV) (he : TrTyping env Us Δ e A e' A') + (re : FVarsIn ngen.Reserves e) (rA : FVarsIn ngen.Reserves A) : + ConditionallyHasType ngen env Us Δ e A := by + refine ⟨noBV ▸ he.2.1.closed, re, noBV ▸ he.2.2.1.closed, rA, fun _ => ⟨_, _, he.1, he.2⟩⟩ + +theorem ConditionallyHasType.typed : + ConditionallyHasType ngen env Us Δ e A → ConditionallyTyped ngen env Us Δ e + | ⟨c1, f1, _, _, H⟩ => ⟨c1, f1, fun h => let ⟨_, _, _, h, _⟩ := H h; ⟨_, h⟩⟩ + +theorem ConditionallyHasType.mono (H : ngen₁ ≤ ngen₂) : + ConditionallyHasType ngen₁ env Us Δ e A → ConditionallyHasType ngen₂ env Us Δ e A + | ⟨c1, f1, c2, f2, h'⟩ => ⟨c1, f1.mono fun _ h => h.mono H, c2, f2.mono fun _ h => h.mono H, h'⟩ + +theorem ConditionallyHasType.weakN_inv + (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length ((some fv, d) :: Δ)) + (H : ConditionallyHasType ngen env Us ((some fv, d) :: Δ) e A) : + ConditionallyHasType ngen env Us Δ e A := by + have ⟨c1, f1, c2, f2, H⟩ := H + refine ⟨c1, f1, c2, f2, fun H4 => ?_⟩ + have ⟨e', A', h1, h2, h3, h4⟩ := H H4.fvars_cons + have W : VLCtx.FVLift Δ ((some fv, d) :: Δ) 0 (0 + d.depth) 0 := .skip_fvar _ _ .refl + have ⟨e'', he⟩ := TrExprS.weakFV_inv henv W (.refl henv hΔ) h2 c1 H4 + have ee := h2.uniq henv (.refl henv hΔ) <| he.weakFV henv W hΔ + have := hΔ.2.1 _ _ rfl + have : IsFVarUpSet (· ∈ VLCtx.fvars Δ) ((some fv, d) :: Δ) := + ⟨.fvars hΔ.1.fvwf, (hΔ.2.1 _ _ rfl).1.elim⟩ + have ⟨_, hA⟩ := TrExprS.weakFV_inv henv W (.refl henv hΔ) h3 c2 <| h1 _ this H4 + have AA := h3.uniq henv (.refl henv hΔ) <| hA.weakFV henv W hΔ + have h4 := h4.defeqU_r henv hΔ.toCtx AA |>.defeqU_l henv hΔ.toCtx ee + have h4 := (HasType.weakN_iff henv hΔ.toCtx W.toCtx).1 h4 + refine ⟨_, _, fun P hP he' => ?_, he, hA, h4⟩ + exact h1 _ + ⟨(IsFVarUpSet.and_fvars hΔ.1.fvwf).1 hP, fun h => (hΔ.2.1 _ _ rfl).1.elim h.2⟩ + (he'.mp (fun _ => .intro) he.fvarsIn) |>.mono fun _ => (·.1) + +theorem ConditionallyHasType.fresh + (henv : Ordered env) + (hΔ : VLCtx.WF env Us.length ((some (⟨ngen.curr⟩, deps), d) :: Δ)) + (H : ConditionallyHasType ngen env Us Δ e A) : + ConditionallyHasType ngen env Us ((some (⟨ngen.curr⟩, deps), d) :: Δ) e A := by + refine have ⟨c1, f1, c2, f2, H⟩ := H; ⟨c1, f1, c2, f2, fun H4 => ?_⟩ + have ⟨_, _, h1, h2, h3, h4⟩ := H (H4.mp ?_ f1) + · have W : VLCtx.FVLift Δ ((some (⟨ngen.curr⟩, deps), d) :: Δ) 0 (0 + d.depth) 0 := + .skip_fvar _ _ .refl + exact ⟨_, _, fun P hP => h1 _ hP.1, + h2.weakFV henv W hΔ, h3.weakFV henv W hΔ, h4.weakN henv W.toCtx⟩ + · intro _ h1 h2; simp at h1; rcases h1 with rfl | h1 + · cases Nat.lt_irrefl _ (h2 _ rfl) + · exact h1 + +def ConditionallyWHNF + (ngen : NameGenerator) (env : VEnv) (Us : List Name) (Δ : VLCtx) (e e₁ : Expr) : Prop := + Closed e ∧ FVarsIn ngen.Reserves e ∧ Closed e₁ ∧ FVarsIn ngen.Reserves e₁ ∧ + (FVarsIn (· ∈ Δ.fvars) e → ∃ e', + FVarsBelow Δ e e₁ ∧ TrExprS env Us Δ e e' ∧ TrExpr env Us Δ e₁ e') + +theorem ConditionallyWHNF.mk {Δ : VLCtx} + (noBV : Δ.NoBV) (hb : FVarsBelow Δ e e₁) + (he : TrExprS env Us Δ e e') (he₁ : TrExpr env Us Δ e₁ e') + (re : FVarsIn ngen.Reserves e) (re₁ : FVarsIn ngen.Reserves e₁) : + ConditionallyWHNF ngen env Us Δ e e₁ := by + refine ⟨noBV ▸ he.closed, re, noBV ▸ he₁.closed, re₁, fun _ => ⟨_, hb, he, he₁⟩⟩ + +theorem ConditionallyWHNF.mono (H : ngen₁ ≤ ngen₂) : + ConditionallyWHNF ngen₁ env Us Δ e A → ConditionallyWHNF ngen₂ env Us Δ e A + | ⟨c1, f1, c2, f2, h'⟩ => ⟨c1, f1.mono fun _ h => h.mono H, c2, f2.mono fun _ h => h.mono H, h'⟩ + +theorem ConditionallyWHNF.weakN_inv + (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length ((some fv, d) :: Δ)) + (H : ConditionallyWHNF ngen env Us ((some fv, d) :: Δ) e e₁) : + ConditionallyWHNF ngen env Us Δ e e₁ := by + have ⟨c1, f1, c2, f2, H⟩ := H + refine ⟨c1, f1, c2, f2, fun H4 => ?_⟩ + have ⟨e', h1, h2, _, h3, h4⟩ := H H4.fvars_cons + have W : VLCtx.FVLift Δ ((some fv, d) :: Δ) 0 (0 + d.depth) 0 := .skip_fvar _ _ .refl + have ⟨e'', he⟩ := TrExprS.weakFV_inv henv W (.refl henv hΔ) h2 c1 H4 + have ee := h2.uniq henv (.refl henv hΔ) <| he.weakFV henv W hΔ + have := hΔ.2.1 _ _ rfl + have : IsFVarUpSet (· ∈ VLCtx.fvars Δ) ((some fv, d) :: Δ) := + ⟨.fvars hΔ.1.fvwf, (hΔ.2.1 _ _ rfl).1.elim⟩ + have ⟨_, he₁⟩ := TrExprS.weakFV_inv henv W (.refl henv hΔ) h3 c2 <| h1 _ this H4 + have ee₁ := h3.uniq henv (.refl henv hΔ) <| he₁.weakFV henv W hΔ + have h4 := ee₁.symm.trans henv hΔ.toCtx h4 |>.trans henv hΔ.toCtx ee + have h4 := (IsDefEqU.weakN_iff henv hΔ.toCtx W.toCtx).1 h4 + refine ⟨_, fun P hP he' => ?_, he, _, he₁, h4⟩ + exact h1 _ + ⟨(IsFVarUpSet.and_fvars hΔ.1.fvwf).1 hP, fun h => (hΔ.2.1 _ _ rfl).1.elim h.2⟩ + (he'.mp (fun _ => .intro) he.fvarsIn) |>.mono fun _ => (·.1) + +theorem ConditionallyWHNF.fresh + (henv : env.WF) + (hΔ : VLCtx.WF env Us.length ((some (⟨ngen.curr⟩, deps), d) :: Δ)) + (H : ConditionallyWHNF ngen env Us Δ e e₁) : + ConditionallyWHNF ngen env Us ((some (⟨ngen.curr⟩, deps), d) :: Δ) e e₁ := by + refine have ⟨c1, f1, c2, f2, H⟩ := H; ⟨c1, f1, c2, f2, fun H4 => ?_⟩ + have ⟨_, h1, h2, h3⟩ := H (H4.mp ?_ f1) + · have W : VLCtx.FVLift Δ ((some (⟨ngen.curr⟩, deps), d) :: Δ) 0 (0 + d.depth) 0 := + .skip_fvar _ _ .refl + exact ⟨_, fun P hP => h1 _ hP.1, h2.weakFV henv W hΔ, h3.weakFV henv W hΔ⟩ + · intro _ h1 h2; simp at h1; rcases h1 with rfl | h1 + · cases Nat.lt_irrefl _ (h2 _ rfl) + · exact h1 diff --git a/Ix/Theory/Named/Verify/Typing/Expr.lean b/Ix/Theory/Named/Verify/Typing/Expr.lean new file mode 100644 index 000000000..da146d752 --- /dev/null +++ b/Ix/Theory/Named/Verify/Typing/Expr.lean @@ -0,0 +1,146 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Typing.Basic +import Ix.Theory.Named.Literals +import Ix.Theory.Named.Projection +import Ix.Theory.Named.Verify.NameGenerator +import Ix.Theory.Named.Verify.VLCtx +import Ix.Theory.Named.Verify.Axioms + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Lean + +def Closed : Expr → (k :_:= 0) → Prop + | .bvar i, k => i < k + | .fvar _, _ | .sort .., _ | .const .., _ | .lit .., _ => True + | .app f a, k => Closed f k ∧ Closed a k + | .lam _ d b _, k + | .forallE _ d b _, k => Closed d k ∧ Closed b (k+1) + | .letE _ d v b _, k => Closed d k ∧ Closed v k ∧ Closed b (k+1) + | .proj _ _ e, k | .mdata _ e, k => Closed e k + | .mvar .., _ => False + +nonrec abbrev _root_.Lean.Expr.Closed := @Closed + +/-- This is very inefficient, only use for spec purposes -/ +def _root_.Lean.Expr.fvarsList : Expr → List FVarId + | .bvar _ | .sort .. | .const .. | .lit .. | .mvar .. => [] + | .fvar fv => [fv] + | .app f a => f.fvarsList ++ a.fvarsList + | .lam _ d b _ + | .forallE _ d b _ => d.fvarsList ++ b.fvarsList + | .letE _ d v b _ => d.fvarsList ++ v.fvarsList ++ b.fvarsList + | .proj _ _ e | .mdata _ e => e.fvarsList + +variable (fvars : FVarId → Prop) in +def FVarsIn : Expr → Prop + | .bvar _ => True + | .fvar fv => fvars fv + | .sort u => u.hasMVar' = false + | .const _ us => ∀ u ∈ us, u.hasMVar' = false + | .lit .. => True + | .app f a => FVarsIn f ∧ FVarsIn a + | .lam _ d b _ + | .forallE _ d b _ => FVarsIn d ∧ FVarsIn b + | .letE _ d v b _ => FVarsIn d ∧ FVarsIn v ∧ FVarsIn b + | .proj _ _ e | .mdata _ e => FVarsIn e + | .mvar .. => False + +nonrec abbrev _root_.Lean.Expr.FVarsIn := @FVarsIn + +def VLCtx.FVWF : VLCtx → Prop + | [] => True + | (ofv, _) :: (Δ : VLCtx) => + VLCtx.FVWF Δ ∧ (∀ fv deps, ofv = some (fv, deps) → fv ∉ Δ.fvars ∧ deps ⊆ Δ.fvars) + +variable (env : VEnv) (U : Nat) in +def VLCtx.WF : VLCtx → Prop + | [] => True + | (ofv, d) :: (Δ : VLCtx) => + VLCtx.WF Δ ∧ (∀ fv deps, ofv = some (fv, deps) → fv ∉ Δ.fvars ∧ deps ⊆ Δ.fvars) ∧ + VLocalDecl.WF env U Δ.toCtx d + +theorem VLCtx.WF.fvwf : ∀ {Δ}, VLCtx.WF env U Δ → Δ.FVWF + | [], h => h + | _ :: _, ⟨h1, h2, _⟩ => ⟨h1.fvwf, h2⟩ + +/-- Verify compatibility surface for Theory's environment-indexed projection +semantics. The view, universe instantiation, and parameter spine are hidden +from existing expression-translation consumers, but each witness is fully +constrained by `VEnv.TrProj`; no metadata is existentially invented. -/ +def TrProj (env : VEnv) (U : Nat) (Γ : List VExpr) + (structName : Name) (idx : Nat) (e result : VExpr) : Prop := + ∃ view levels params, + view.name = structName ∧ + env.TrProj U Γ view levels params idx e result + +variable (env : VEnv) (Us : List Name) in +inductive TrExprS : VLCtx → Expr → VExpr → Prop + | bvar : Δ.find? (.inl i) = some (e, A) → TrExprS Δ (.bvar i) e + | fvar : Δ.find? (.inr fv) = some (e, A) → TrExprS Δ (.fvar fv) e + | sort : VLevel.ofLevel Us u = some u' → TrExprS Δ (.sort u) (.sort u') + | const : + env.constants c = some ci → + us.mapM (VLevel.ofLevel Us) = some us' → + us.length = ci.uvars → + TrExprS Δ (.const c us) (.const c us') + | app : + env.HasType Us.length Δ.toCtx f' (.forallE A B) → + env.HasType Us.length Δ.toCtx a' A → + TrExprS Δ f f' → TrExprS Δ a a' → TrExprS Δ (.app f a) (.app f' a') + | lam : + env.IsType Us.length Δ.toCtx ty' → + TrExprS Δ ty ty' → TrExprS ((none, .vlam ty') :: Δ) body body' → + TrExprS Δ (.lam name ty body bi) (.lam ty' body') + | forallE : + env.IsType Us.length Δ.toCtx ty' → + env.IsType Us.length (ty' :: Δ.toCtx) body' → + TrExprS Δ ty ty' → TrExprS ((none, .vlam ty') :: Δ) body body' → + TrExprS Δ (.forallE name ty body bi) (.forallE ty' body') + | letE : + env.HasType Us.length Δ.toCtx val' ty' → + TrExprS Δ ty ty' → TrExprS Δ val val' → + TrExprS ((none, .vlet ty' val') :: Δ) body body' → + TrExprS Δ (.letE name ty val body nd) body' + | lit : env.ContainsLits l → TrExprS Δ l.toConstructor e → TrExprS Δ (.lit l) e + | mdata : TrExprS Δ e e' → TrExprS Δ (.mdata d e) e' + | proj : TrExprS Δ e e' → + TrProj env Us.length Δ.toCtx s i e' e'' → + TrExprS Δ (.proj s i e) e'' + +def TrExpr (env : VEnv) (Us : List Name) (Δ : VLCtx) (e : Expr) (e' : VExpr) : Prop := + ∃ e₂, TrExprS env Us Δ e e₂ ∧ env.IsDefEqU Us.length Δ.toCtx e₂ e' + +/-- Deterministic shadow of `TrExprS`: compute the strict Theory translation +of an expression syntactically. Every semantic premise of `TrExprS` only +validates a translation, it never selects between candidates, so on the +`TrExprS.IsUnique` fragment this function returns exactly the translation of +any derivation (`TrExprS.trExprS?_eq`). The function checks nothing +semantic: it is meaningful only through that agreement theorem. The pushed +`vlet` type is a dummy because `TrExprS` never reads it — `VLCtx.find?` +returns a let's value, and the type component is existentially discarded. -/ +def trExprS? (Us : List Name) : VLCtx → Expr → Option VExpr + | Δ, .bvar i => (Δ.find? (.inl i)).map (·.1) + | Δ, .fvar fv => (Δ.find? (.inr fv)).map (·.1) + | _, .sort u => (VLevel.ofLevel Us u).map .sort + | _, .const c us => (us.mapM (VLevel.ofLevel Us)).map (VExpr.const c) + | Δ, .app f a => do return .app (← trExprS? Us Δ f) (← trExprS? Us Δ a) + | Δ, .lam _ ty body _ => do + let ty' ← trExprS? Us Δ ty + return .lam ty' (← trExprS? Us ((none, .vlam ty') :: Δ) body) + | Δ, .forallE _ ty body _ => do + let ty' ← trExprS? Us Δ ty + return .forallE ty' (← trExprS? Us ((none, .vlam ty') :: Δ) body) + | Δ, .letE _ _ val body _ => do + let val' ← trExprS? Us Δ val + trExprS? Us ((none, .vlet (.sort .zero) val') :: Δ) body + | _, .lit l => some (.trLiteral l) + | Δ, .mdata _ e => trExprS? Us Δ e + | _, .proj .. => none + | _, .mvar .. => none diff --git a/Ix/Theory/Named/Verify/Typing/Lemmas.lean b/Ix/Theory/Named/Verify/Typing/Lemmas.lean new file mode 100644 index 000000000..7e4160ac5 --- /dev/null +++ b/Ix/Theory/Named/Verify/Typing/Lemmas.lean @@ -0,0 +1,2636 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Std.AxiomAudit +import Batteries.Data.String.Lemmas +import Ix.Theory.Named.Verify.Typing.Expr +import Ix.Theory.Named.Verify.Expr +import Ix.Theory.Named.Typing.Strong +import Ix.Theory.Named.Typing.UniqueTyping +import Ix.Theory.Named.Reference.Instantiate + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named +open Ix.Theory.Named VEnv Lean +open scoped _root_.List + +theorem fvarsIn_iff : FVarsIn P e ↔ (∀ fv ∈ e.fvarsList, P fv) ∧ FVarsIn (fun _ => True) e := by + induction e <;> simp [FVarsIn, Expr.fvarsList, *] <;> grind + +theorem fvarsIn_iff_hasMVar : FVarsIn (fun _ => True) e ↔ e.hasMVar = false := by + rw [Expr.hasMVar, ← Expr.hasExprMVar, ← Expr.hasLevelMVar]; simp + induction e <;> simp [FVarsIn, Expr.hasExprMVar', Expr.hasLevelMVar', and_assoc, and_left_comm, *] + +theorem fvarsList_eq_nil {e : Expr} : e.fvarsList = [] ↔ e.hasFVar = false := by + rw [Expr.hasFVar_eq] + induction e <;> simp [Expr.fvarsList, Expr.hasFVar', and_assoc, *] + +theorem FVarsIn.mp (H : ∀ fv, P fv → Q fv → R fv) : + ∀ {e}, FVarsIn P e → FVarsIn Q e → FVarsIn R e + | .bvar _, l, _ | .sort .., l, _ | .const .., l, _ | .lit .., l, _ => l + | .fvar _, l, r => H _ l r + | .app .., ⟨l1, l2⟩, ⟨r1, r2⟩ + | .lam .., ⟨l1, l2⟩, ⟨r1, r2⟩ + | .forallE .., ⟨l1, l2⟩, ⟨r1, r2⟩ => ⟨l1.mp H r1, l2.mp H r2⟩ + | .letE .., ⟨l1, l2, l3⟩, ⟨r1, r2, r3⟩ => ⟨l1.mp H r1, l2.mp H r2, l3.mp H r3⟩ + | .proj _ _ e, l, r | .mdata _ e, l, r => l.mp (e := e) H r + +theorem FVarsIn.mono (H : ∀ fv, P fv → Q fv) (h : FVarsIn P e) : FVarsIn Q e := + h.mp (fun _ h _ => H _ h) h + +theorem Closed.mono (H : k ≤ k') : ∀ {e}, Closed e k → Closed e k' + | .bvar _, h => Nat.lt_of_lt_of_le h H + | .fvar _, h | .sort .., h | .const .., h | .lit .., h => h + | .app .., ⟨h1, h2⟩ => ⟨h1.mono H, h2.mono H⟩ + | .lam .., ⟨h1, h2⟩ + | .forallE .., ⟨h1, h2⟩ => ⟨h1.mono H, h2.mono (Nat.succ_le_succ H)⟩ + | .letE .., ⟨h1, h2, h3⟩ => ⟨h1.mono H, h2.mono H, h3.mono (Nat.succ_le_succ H)⟩ + | .proj _ _ e, h | .mdata _ e, h => h.mono (e := e) H + +theorem FVarsIn.natLitToConstructor : FVarsIn P (.natLitToConstructor n) := by + cases n <;> simp [FVarsIn, Expr.natLitToConstructor, Expr.natZero, Expr.natSucc] + +theorem Closed.natLitToConstructor : Closed (.natLitToConstructor n) k := by + cases n <;> simp [Closed, Expr.natLitToConstructor, Expr.natZero, Expr.natSucc] + +theorem FVarsIn.strLitToConstructor : FVarsIn P (.strLitToConstructor s) := by + simp [FVarsIn, Expr.strLitToConstructor] + induction s.toList <;> simp [*, FVarsIn, Level.hasMVar'] + +theorem Closed.strLitToConstructor : Closed (.strLitToConstructor s) k := by + simp [Closed, Expr.strLitToConstructor] + induction s.toList <;> simp [*, Closed] + +theorem FVarsIn.toConstructor : ∀ {l : Literal}, FVarsIn P l.toConstructor + | .natVal _ => .natLitToConstructor + | .strVal _ => .strLitToConstructor + +theorem FVarsIn.litType {l : Literal} : FVarsIn P l.type := by + cases l <;> simp [FVarsIn, Literal.type] + +theorem Closed.toConstructor : ∀ {l : Literal}, Closed l.toConstructor k + | .natVal _ => .natLitToConstructor + | .strVal _ => .strLitToConstructor + +theorem toConstructor : ∀ {l : Literal}, Closed l.toConstructor k + | .natVal _ => .natLitToConstructor + | .strVal _ => .strLitToConstructor + +theorem Closed.litType {l : Literal} : Closed l.type k := by cases l <;> trivial + +theorem FVarsIn.fvars_cons : + FVarsIn (· ∈ VLCtx.fvars Δ) e → FVarsIn (· ∈ VLCtx.fvars ((ofv, d) :: Δ)) e := + FVarsIn.mono fun a h => by cases ofv <;> simp [h] + +theorem FVarsIn.abstract_instantiate1 (h : FVarsIn (· ≠ v) e) : + (Expr.instantiate1' e (.fvar v) k).abstract1 v k = e := by + induction e generalizing k with simp_all [Expr.instantiate1', Expr.abstract1, FVarsIn] + | bvar i => + split <;> [skip; split] + · simp [Expr.abstract1, *] + · simp [Expr.abstract1, Expr.liftLooseBVars', *] + · obtain _|i := i <;> simp [Expr.abstract1] <;> omega + | fvar v' => exact Ne.symm h + +theorem FVarsIn.abstract_eq_self (h : FVarsIn (· ≠ v) e) (hc : Closed e k) : + e.abstract1 v k = e := by + induction e generalizing k <;> simp_all [FVarsIn, Closed, Expr.abstract1] + exact Ne.symm h + +theorem FVarsIn.liftLooseBVars (h : FVarsIn P e) : FVarsIn P (Expr.liftLooseBVars' e s d) := by + induction e generalizing s <;> simp_all [FVarsIn, Expr.liftLooseBVars'] + +theorem FVarsIn.instantiate1_go (h1 : FVarsIn P e) (h2 : FVarsIn P a) : + FVarsIn P (Expr.instantiate1' e a k) := by + induction e generalizing k <;> simp_all [FVarsIn, Expr.instantiate1'] + (repeat' split) <;> simp [*, FVarsIn.liftLooseBVars, FVarsIn] + +theorem FVarsIn.instantiate1 (h1 : FVarsIn P e) (h2 : FVarsIn P a) : + FVarsIn P (Expr.instantiate1' e a) := h1.instantiate1_go h2 + +theorem FVarsIn.instantiateList (h1 : FVarsIn P e) (h2 : ∀ a ∈ as, FVarsIn P a) (k := 0) : + FVarsIn P (Expr.instantiateList e as k) := by + induction as generalizing e <;> simp_all [Expr.instantiateList, FVarsIn.instantiate1_go] + +theorem FVarsIn.abstract1 (h1 : FVarsIn P e) : + FVarsIn P (Expr.abstract1 a e k) := by + induction e generalizing k <;> simp_all [FVarsIn, Expr.abstract1] + split <;> simp [FVarsIn, *] + +theorem FVarsIn.appRevList : + FVarsIn P (f.mkAppRevList es) ↔ FVarsIn P f ∧ ∀ e ∈ es, FVarsIn P e := by + induction es <;> simp [FVarsIn, and_comm, and_left_comm, *] + +theorem Closed.abstract1 (h1 : Closed e k) : + Closed (Expr.abstract1 a e k) (k+1) := by + induction e generalizing k with simp_all [Closed, Expr.abstract1] + | bvar => omega + | fvar => split <;> simp [Closed] + +theorem Closed.getAppFn {e} (h : Closed e) : Closed e.getAppFn := by + unfold Expr.getAppFn; split + · exact Closed.getAppFn h.1 + · exact h + +theorem Closed.getAppArgsRevList {e} (h : Closed e) + {{a}} (ha : a ∈ e.getAppArgsRevList) : Closed a := by + revert a; unfold Expr.getAppArgsRevList; split <;> simp + exact ⟨h.2, Closed.getAppArgsRevList h.1⟩ + +theorem Closed.getAppArgsList {e} (h : Closed e) + {{a}} (ha : a ∈ e.getAppArgsList) : Closed a := + h.getAppArgsRevList (by simpa [← Expr.getAppArgsList_reverse]) + +theorem FVarsIn.getAppArgsRevList {e} (h : FVarsIn P e) + {{a}} (ha : a ∈ e.getAppArgsRevList) : FVarsIn P a := by + revert a + unfold Expr.getAppArgsRevList + split <;> simp + exact ⟨h.2, FVarsIn.getAppArgsRevList h.1⟩ + +theorem FVarsIn.getAppArgsList {e} (h : FVarsIn P e) + {{a}} (ha : a ∈ e.getAppArgsList) : FVarsIn P a := + h.getAppArgsRevList (by simpa [← Expr.getAppArgsList_reverse]) + +theorem Closed.looseBVarRange_le : Closed e k → e.looseBVarRange' ≤ k := by + induction e generalizing k <;> + simp +contextual [*, Closed, Expr.looseBVarRange', Nat.max_le] + exact id + +theorem Closed.looseBVarRange_zero (H : Closed e) : e.looseBVarRange' = 0 := by + simpa using H.looseBVarRange_le + +theorem VLocalDecl.WF.hasType : ∀ {d}, VLocalDecl.WF env U (VLCtx.toCtx Δ) d → + env.HasType U (VLCtx.toCtx ((ofv, d) :: Δ)) d.value d.type + | .vlam _, _ => .bvar .zero + | .vlet .., hA => hA + +theorem VLocalDecl.is_liftN {Δ : VLCtx} : + ∀ {d}, Ctx.LiftN (VLocalDecl.depth d) 0 Δ.toCtx (VLCtx.toCtx ((ofv, d) :: Δ)) + | .vlam _ => .one + | .vlet .. => .zero [] + +namespace VLCtx + +variable! (henv : Ordered env) in +theorem WF.find?_wf {Δ : VLCtx} (hΔ : WF env U Δ) (H : Δ.find? v = some (e, A)) : + env.HasType U Δ.toCtx e A := by + let (ofv, d') :: Δ := Δ + unfold find? at H; split at H + · cases H; exact hΔ.2.2.hasType + · simp at H + obtain ⟨d'', n', H, rfl, rfl⟩ := H + obtain h3 := hΔ.1.find?_wf H + exact h3.weakN henv VLocalDecl.is_liftN + +theorem WF.toCtx : ∀ {Δ}, WF env U Δ → OnCtx Δ.toCtx (env.IsType U) + | [], _ => ⟨⟩ + | (_, .vlam _) :: _, ⟨hΔ, _, hA⟩ => ⟨hΔ.toCtx, hA⟩ + | (_, .vlet ..) :: _, ⟨hΔ, _, _⟩ => hΔ.toCtx + +/-- A verified local context remains well formed when the global environment +is extended. -/ +theorem WF.mono (henv : env ≤ env') : ∀ {Δ}, WF env U Δ → WF env' U Δ + | [], _ => trivial + | (_, d) :: Δ, ⟨hΔ, hfvars, hd⟩ => + ⟨hΔ.mono henv, hfvars, by + cases d with + | vlam => exact hd.mono henv + | vlet => exact hd.mono henv⟩ + +instance : Coe (WF env U Δ) (OnCtx Δ.toCtx (env.IsType U)) := ⟨(·.toCtx)⟩ + +theorem WF.fvars_nodup : ∀ {Δ}, WF env U Δ → Δ.fvars.Nodup + | [], _ => .nil + | (none, _) :: Δ, ⟨hΔ, _, _⟩ => fvars_nodup (Δ := Δ) hΔ + | (some (fv, _), _) :: Δ, ⟨hΔ, h, _⟩ => by + suffices fv ∉ fvars Δ from (fvars_nodup hΔ).cons (fun _ h (e:fv=_) => this (e ▸ h)) + exact (h _ _ rfl).1 + +theorem liftVar_zero : liftVar 0 k v = v := by cases v <;> simp [liftVar] + +inductive FVLift' : VLCtx → VLCtx → Nat → Lift → Nat → Prop + | refl : FVLift' Δ Δ 0 .refl 0 + | skip_fvar (fv d) : FVLift' Δ Δ' 0 n 0 → + FVLift' Δ ((some fv, d) :: Δ') 0 (n.skipN d.depth) 0 + | cons_fvar (fv d) : fv.2 ⊆ Δ.fvars → FVLift' Δ Δ' 0 n 0 → + FVLift' ((some fv, d) :: Δ) ((some fv, d.lift' n) :: Δ') 0 (.consN n d.depth) 0 + | cons_bvar (d) : FVLift' Δ Δ' dk n k → + FVLift' ((none, d) :: Δ) ((none, d.lift' (n.consN k)) :: Δ') (dk + 1) n (k + d.depth) + +protected theorem FVLift'.toCtx (W : FVLift' Δ Δ' dk n k) : + Ctx.Lift' (n.consN k) Δ.toCtx Δ'.toCtx := by + induction W with + | refl => exact .refl + | skip_fvar _ d _ ih => match d with + | .vlet .. => exact ih + | .vlam A => exact .skip ih + | cons_fvar _ d _ _ ih => match d with + | .vlet .. => exact ih + | .vlam A => exact .cons ih + | cons_bvar d _ ih => match d with + | .vlet .. => exact ih + | .vlam A => exact .cons ih + +theorem FVLift'.comp (H1 : FVLift' Δ₁ Δ₂ 0 n₁ 0) (H2 : FVLift' Δ₂ Δ₃ dk n₂ k) : + FVLift' Δ₁ Δ₃ dk (n₁.comp n₂) k := by + induction H2 generalizing n₁ Δ₁ with + | refl => exact H1 + | skip_fvar _ _ _ ih => simpa [Lift.comp_skipN] using (ih H1).skip_fvar _ _ + | cons_fvar _ d h1 _ ih => cases H1 with + | refl => simpa using (ih .refl).cons_fvar _ _ h1 + | skip_fvar _ _ h2 => simpa [Lift.skipN_comp_consN] using (ih h2).skip_fvar _ (d.lift' _) + | cons_fvar _ d h1 h2 => + simpa [← Lift.consN_comp, ← VLocalDecl.lift'_comp] using (ih h2).cons_fvar _ d h1 + | cons_bvar d h1 ih => cases H1 with | refl => simpa using h1.cons_bvar _ + +theorem FVLift'.from_nil : ∀ {Δ : VLCtx}, Δ.NoBV → FVLift' [] Δ 0 (.skipN .refl Δ.toCtx.length) 0 + | [], _ => .refl + | (some _, .vlam _) :: _, H => .skip_fvar _ _ (.from_nil H) + | (some _, .vlet _ _) :: _, H => .skip_fvar _ _ (.from_nil H) + +theorem FVLift'.fvars_sublist (W : FVLift' Δ Δ' dk n k) : Δ.fvars <+ Δ'.fvars := by + induction W with + | refl => exact .refl _ + | skip_fvar _ _ _ ih => exact .cons _ ih + | cons_fvar _ _ _ _ ih => exact .cons_cons _ ih + | cons_bvar _ _ ih => exact ih + +theorem FVLift'.bvars_eq (W : FVLift' Δ Δ' dk n k) : Δ'.bvars = Δ.bvars := by + induction W with + | refl => rfl + | skip_fvar _ _ _ ih => exact ih + | cons_fvar _ _ _ _ ih => exact ih + | cons_bvar _ _ ih => exact congrArg Nat.succ ih + +variable! (henv : VEnv.WF env) in +theorem FVLift'.wf (W : FVLift' Δ Δ' dk n k) (hΔ' : Δ'.WF env U) : Δ.WF env U := by + induction W with + | refl => exact hΔ' + | skip_fvar _ _ _ ih => exact ih hΔ'.1 + | cons_fvar _ _ hd W ih => + let ⟨hΔ', h1, h2⟩ := hΔ' + refine ⟨ih hΔ', ?_, (VLocalDecl.weak'_iff henv hΔ'.toCtx W.toCtx).1 h2⟩ + rintro _ _ ⟨⟩; exact ⟨fun h => (h1 _ _ rfl).1 <| W.fvars_sublist.subset h, hd⟩ + | cons_bvar _ W ih => + let ⟨hΔ', _, h2⟩ := hΔ' + exact ⟨ih hΔ', nofun, (VLocalDecl.weak'_iff henv hΔ'.toCtx W.toCtx).1 h2⟩ + +protected theorem FVLift'.find? (W : FVLift' Δ Δ' dk n k) (hΔ' : Δ'.WF env U) + (H : find? Δ v = some (e, A)) : + find? Δ' v = some (e.lift' (n.consN k), A.lift' (n.consN k)) := by + induction W generalizing v e A with + | refl => simp [H] + | skip_fvar fv' _ W ih => + let (fv', deps) := fv'; simp [find?] + cases v with simp [next] + | inl => + refine ⟨_, _, ih hΔ'.1 H, ?_⟩ + simp [← VExpr.lift'_consN_skipN, ← VExpr.lift'_comp, Lift.comp_skipN] + | inr fv => + cases eq : fv' == fv <;> simp + · refine ⟨_, _, ih hΔ'.1 H, ?_⟩ + simp [← VExpr.lift'_consN_skipN, ← VExpr.lift'_comp, Lift.comp_skipN] + · refine ((List.pairwise_cons.1 hΔ'.fvars_nodup).1 fv' ?_ rfl).elim + exact W.fvars_sublist.subset ((beq_iff_eq ..).1 eq ▸ find?_eq_some.1 ⟨_, H⟩) + | cons_fvar fv' d _ W ih => + let (fv', deps) := fv'; revert H; simp [find?] + obtain i | fv := v <;> simp [next] <;> + [skip; cases eq : fv' == fv <;> simp] <;> + [(rintro _ _ H rfl rfl; refine ⟨_, _, ih hΔ'.1 H, ?_⟩); + (rintro _ _ H rfl rfl; refine ⟨_, _, ih (v := .inr fv) hΔ'.1 H, ?_⟩); + rintro rfl rfl] <;> + open VLocalDecl in + cases d <;> simp [value, type, depth, lift', VExpr.lift, + ← VExpr.lift'_consN_skipN, ← VExpr.lift'_comp] + | cons_bvar d _ ih => + simp [find?] at H ⊢ + obtain ⟨_|i⟩ | fv := v <;> simp [next] at H ⊢ <;> + [(obtain ⟨rfl, rfl⟩ := H); + (obtain ⟨e, A, H, rfl, rfl⟩ := H + refine ⟨_, _, ih (v := .inl i) hΔ'.1 H, ?_⟩); + (obtain ⟨e, A, H, rfl, rfl⟩ := H + refine ⟨_, _, ih (v := .inr fv) hΔ'.1 H, ?_⟩)] <;> + open VLocalDecl in + cases d <;> simp [value, type, depth, lift', VExpr.lift, + ← VExpr.lift'_consN_skipN, ← VExpr.lift'_comp] + +inductive FVLift : VLCtx → VLCtx → Nat → Nat → Nat → Prop + | refl : FVLift Δ Δ 0 0 0 + | skip_fvar (fv d) : FVLift Δ Δ' 0 n 0 → FVLift Δ ((some fv, d) :: Δ') 0 (n + d.depth) 0 + | cons_bvar (d) : FVLift Δ Δ' dk n k → + FVLift ((none, d) :: Δ) ((none, d.liftN n k) :: Δ') (dk + 1) n (k + d.depth) + +theorem FVLift.toFVLift' (W : FVLift Δ Δ' dk n k) : FVLift' Δ Δ' dk (.skipN .refl n) k := by + induction W with + | refl => exact .refl + | skip_fvar fv d _ ih => simpa [Lift.skipN_skipN] using ih.skip_fvar fv d + | cons_bvar d _ ih => + simpa [← VLocalDecl.lift'_consN_skipN, Lift.skipN_skipN] using ih.cons_bvar d + +protected theorem FVLift.toCtx (W : FVLift Δ Δ' dk n k) : Ctx.LiftN n k Δ.toCtx Δ'.toCtx := + Ctx.liftN_iff_lift'.2 W.toFVLift'.toCtx + +theorem FVLift.from_nil : ∀ {Δ : VLCtx}, Δ.NoBV → FVLift [] Δ 0 Δ.toCtx.length 0 + | [], _ => .refl + | (some _, .vlam _) :: _, H => .skip_fvar _ _ (.from_nil H) + | (some _, .vlet _ _) :: _, H => .skip_fvar _ _ (.from_nil H) + +variable! (henv : VEnv.WF env) in +theorem FVLift.wf (W : FVLift Δ Δ' dk n k) (hΔ' : Δ'.WF env U) : Δ.WF env U := + W.toFVLift'.wf henv hΔ' + +theorem FVLift.fvars_suffix (W : FVLift Δ Δ' dk n k) : Δ.fvars <:+ Δ'.fvars := by + induction W with + | refl => exact List.suffix_refl _ + | skip_fvar _ _ _ ih => exact ih.trans (List.suffix_cons ..) + | cons_bvar _ _ ih => exact ih + +protected theorem FVLift.find? (W : FVLift Δ Δ' dk n k) (hΔ' : Δ'.WF env U) + (H : find? Δ v = some (e, A)) : find? Δ' v = some (e.liftN n k, A.liftN n k) := by + simpa [VExpr.lift'_consN_skipN] using W.toFVLift'.find? hΔ' H + +inductive BVLift : (Δ Δ' : VLCtx) → (dn dk n k : Nat) → Prop + | refl : BVLift Δ Δ 0 0 0 0 + | skip (d) : BVLift Δ Δ' dn 0 n 0 → BVLift Δ ((none, d) :: Δ') (dn + 1) 0 (n + d.depth) 0 + | cons (d) : BVLift Δ Δ' dn dk n k → + BVLift ((none, d) :: Δ) ((none, d.liftN n k) :: Δ') dn (dk + 1) n (k + d.depth) + +theorem BVLift.toCtx (W : BVLift Δ Δ' dn dk n k) : Ctx.LiftN n k Δ.toCtx Δ'.toCtx := by + induction W with + | refl => exact .zero [] + | @skip _ Δ' _ _ d _ ih => + match d with + | .vlet .. => exact ih + | .vlam A => + generalize hΓ' : VLCtx.toCtx Δ' = Γ' at ih + let .zero As eq := ih + simp [VLCtx.toCtx, hΓ'] + exact .zero (A :: As) (eq ▸ rfl) + | cons d _ ih => + match d with + | .vlet .. => exact ih + | .vlam A => exact .succ ih + +variable! (henv : VEnv.WF env) in +theorem BVLift.wf (W : BVLift Δ Δ' dn dk n k) (hΔ' : Δ'.WF env U) : Δ.WF env U := by + induction W with + | refl => exact hΔ' + | skip _ _ ih => exact ih hΔ'.1 + | cons _ W ih => + let ⟨hΔ', _, h2⟩ := hΔ' + exact ⟨ih hΔ', nofun, (VLocalDecl.weakN_iff henv hΔ'.toCtx W.toCtx).1 h2⟩ + +theorem BVLift.fvars_eq (W : BVLift Δ Δ' dn dk n k) : Δ.fvars = Δ'.fvars := by + induction W with + | refl => rfl + | skip _ _ ih => exact ih + | cons _ _ ih => exact ih + +protected theorem BVLift.find? (W : BVLift Δ Δ' dn dk n k) (H : find? Δ v = some (e, A)) : + find? Δ' (liftVar dn dk v) = some (e.liftN n k, A.liftN n k) := by + induction W generalizing v e A with + | refl => simp [H, liftVar_zero] + | @skip _ Δ' _ fv' _ W ih => + obtain v | fv := v <;> simp [find?, liftVar, next] <;> + exact ⟨_, _, ih H, by simp [VExpr.liftN_liftN]⟩ + | cons d _ ih => + obtain (_ | v) | fv := v <;> simp [liftVar] <;> + [ (simp [find?, next] at H ⊢; simp [← H]); + split <;> ( + rename_i h + simp [Nat.add_right_comm _ 1, find?, next] at H ⊢ + obtain ⟨e, A, H, rfl, rfl⟩ := H + have := ih H + simp [liftVar, h] at this + refine ⟨_, _, this, ?_⟩); + ( simp [find?, next] at H ⊢ + obtain ⟨e, A, H, rfl, rfl⟩ := H + refine ⟨_, _, ih H, ?_⟩ )] <;> + open VLocalDecl in + cases d <;> simp [VExpr.lift_liftN', liftN, value, type, depth, VExpr.liftN] + +variable (Δ₀ : VLCtx) (e₀ A₀ : VExpr) in +inductive InstN : Nat → Nat → VLCtx → VLCtx → Prop where + | zero : InstN 0 0 ((none, .vlam A₀) :: Δ₀) Δ₀ + | succ : InstN dk k Γ Γ' → InstN (dk + 1) (k + d.depth) ((none, d)::Γ) ((none, d.inst e₀ k) :: Γ') + +protected theorem InstN.toCtx (W : InstN Δ₀ e₀ A₀ dk k Δ₁ Δ) : + Ctx.InstN Δ₀.toCtx e₀ A₀ k Δ₁.toCtx Δ.toCtx := by + induction W with + | zero => exact .zero + | @succ _ _ _ _ d _ ih => + match d with + | .vlet .. => exact ih + | .vlam A => exact .succ ih + +variable! (henv : Ordered env) (h₀ : env.HasType U (toCtx Δ₀) e₀ A₀) in +theorem InstN.wf (W : InstN Δ₀ e₀ A₀ dk k Δ₁ Δ) (hΔ' : Δ₁.WF env U) : Δ.WF env U := by + induction W with + | zero => exact hΔ'.1 + | succ W ih => let ⟨hΔ', _, h2⟩ := hΔ'; exact ⟨ih hΔ', nofun, h2.instN henv W.toCtx h₀⟩ + +theorem InstN.fvars_eq (W : InstN Δ₀ e₀ A₀ dk k Δ₁ Δ) : + Δ₁.fvars = Δ₀.fvars ∧ Δ.fvars = Δ₀.fvars := by + induction W with + | zero => exact ⟨rfl, rfl⟩ + | succ _ ih => exact ih + +variable (Δ₀ : VLCtx) (e₀ A₀ : VExpr) in +inductive InstLet : Nat → Nat → VLCtx → VLCtx → Prop where + | zero : InstLet 0 0 ((none, .vlet A₀ e₀) :: Δ₀) Δ₀ + | succ : InstLet dk k Γ Γ' → InstLet (dk + 1) (k + d.depth) ((none, d)::Γ) ((none, d) :: Γ') + +protected theorem InstLet.toCtx (W : InstLet Δ₀ e₀ A₀ dk k Δ₁ Δ) : Δ₁.toCtx = Δ.toCtx := by + induction W with + | zero => rfl + | @succ _ _ _ _ d _ ih => + match d with + | .vlet .. => exact ih + | .vlam _ => exact congrArg (_::·) ih + +theorem InstLet.wf (W : InstLet Δ₀ e₀ A₀ dk k Δ₁ Δ) (hΔ' : Δ₁.WF env U) : Δ.WF env U := by + induction W with + | zero => exact hΔ'.1 + | succ W ih => let ⟨hΔ', _, h2⟩ := hΔ'; exact ⟨ih hΔ', nofun, W.toCtx ▸ h2⟩ + +theorem InstLet.fvars_eq (W : InstLet Δ₀ e₀ A₀ dk k Δ₁ Δ) : + Δ₁.fvars = Δ₀.fvars ∧ Δ.fvars = Δ₀.fvars := by + induction W with + | zero => exact ⟨rfl, rfl⟩ + | succ _ ih => exact ih + +variable (Δ₀ : VLCtx) (v₀ : FVarId) (d₀ : VLocalDecl) in +inductive Abstract : Nat → Nat → VLCtx → VLCtx → Prop where + | zero : Abstract 0 0 ((some (v₀, deps), d₀) :: Δ₀) ((none, d₀) :: Δ₀) + | succ : Abstract dk k Γ Γ' → Abstract (dk + 1) (k + d.depth) ((none, d) :: Γ) ((none, d) :: Γ') + +protected theorem Abstract.toCtx (W : Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) : Δ₁.toCtx = Δ.toCtx := by + induction W with + | zero => cases d₀ <;> rfl + | @succ _ _ _ _ d _ ih => + match d with + | .vlet .. => exact ih + | .vlam A => exact congrArg (_ :: ·) ih + +theorem Abstract.wf (W : Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) (hΔ' : Δ₁.WF env U) : Δ.WF env U := by + induction W with + | zero => exact ⟨hΔ'.1, nofun, hΔ'.2.2⟩ + | succ W ih => let ⟨hΔ', _, h2⟩ := hΔ'; exact ⟨ih hΔ', nofun, W.toCtx ▸ h2⟩ + +theorem Abstract.fvars_eq (W : Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) : + Δ₁.fvars = v₀ :: Δ₀.fvars ∧ Δ.fvars = Δ₀.fvars := by + induction W with + | zero => exact ⟨rfl, rfl⟩ + | succ _ ih => exact ih + +theorem Abstract.find?_self (W : Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) : + Δ₁.find? (.inr v₀) = some (d₀.value.liftN k, d₀.type.liftN k) := by + induction W with simp [find?, next] + | succ _ ih => exact ⟨_, _, ih, by simp [VExpr.liftN_liftN]⟩ + +protected theorem Abstract.find? (W : Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) (h : v ≠ .inr v₀) : + Δ.find? v = Δ₁.find? (clear% h; match v with + | .inl i => if i < dk then .inl i else if i = dk then .inr v₀ else .inl (i - 1) + | .inr v' => .inr v') := by + induction W generalizing v with + | zero => + obtain (_|i)|v := v <;> simp [find?, next] + cases eq : v₀ == v; · simp + · simp at h eq; cases h eq.symm + | @succ dk k _ _ _ _ ih => + obtain (_|i)|v := v <;> simp [find?, next] + · have := @ih (.inl i) nofun; revert this + by_cases h : i < dk <;> simp +contextual [h] + by_cases h : i = dk <;> simp +contextual [h] + obtain _|i := i <;> [omega; simp] + · simp [ih h] + +theorem instL_eq_map (Δ : VLCtx) : Δ.instL ls = Δ.map (fun (ofv, d) => (ofv, d.instL ls)) := by + induction Δ <;> simp [instL, *] + +@[simp] theorem instL_toCtx (Δ : VLCtx) : (Δ.instL ls).toCtx = Δ.toCtx.map (·.instL ls) := by + induction Δ with + | nil => rfl + | cons head => obtain ⟨_, _|_⟩ := head <;> rw [instL, VLocalDecl.instL] <;> simp [toCtx, *] + +variable! (hls : ∀ l ∈ (ls : List _), VLevel.WF U l) in +protected theorem WF.instL : ∀ {Δ}, VLCtx.WF env ls.length Δ → + VLCtx.WF env U (Δ.instL ls) + | [], _ => ⟨⟩ + | (_, d) :: Δ, ⟨h1, h2, h3⟩ => + ⟨h1.instL, by simpa [instL_eq_map, fvars, Function.comp_def] using h2, + by simpa using h3.instL hls⟩ + +theorem find?_instL : find? Δ v = some (e, A) → + find? (Δ.instL ls) v = some (e.instL ls, A.instL ls) := by + induction Δ generalizing v e A with + | nil => nofun + | cons d Δ ih => + simp [find?, instL]; split <;> simp + · rintro rfl rfl; cases d.2 <;> exact ⟨rfl, by simp [VLocalDecl.instL, VLocalDecl.type]⟩ + · rintro e A h rfl rfl + exact ⟨_, _, ih h, by cases d.2 <;> simp [VLocalDecl.instL, VLocalDecl.depth]⟩ + +variable (env : VEnv) (U) in +inductive SortList : VLCtx → List VLevel → Prop + | nil : SortList Δ [] + | cons : SortList Δ ls → env.HasType U Δ.toCtx A (.sort u) → + SortList ((some fv, .vlam A) :: Δ) (u :: ls) + +end VLCtx + +theorem TrProj.weak' (henv : env.Ordered) (W : Ctx.Lift' n Γ Γ') + (H : TrProj env U Γ s i e e') : + TrProj env U Γ' s i (e.lift' n) (e'.lift' n) := by + obtain ⟨view, levels, params, hname, hproj⟩ := H + exact ⟨view, levels, params.map (fun param => param.lift' n), + hname, hproj.weak' henv W⟩ + +theorem TrProj.weakN (henv : env.Ordered) (W : Ctx.LiftN n k Γ Γ') + (H : TrProj env U Γ s i e e') : + TrProj env U Γ' s i (e.liftN n k) (e'.liftN n k) := by + simpa [VExpr.lift'_consN_skipN] using + H.weak' henv (Ctx.liftN_iff_lift'.1 W) + +/-! ## Replaying closed metadata types -/ + +variable (env : VEnv) (Us : List Name) in +/-- The syntax-directed fragment used by kernel declaration types. Unlike +`TrExprS`, this relation records only the representation translation; the +typing premises are recovered from a well-formed Theory expression by +`TrTypeExpr.to_trExprS`. Keeping the two concerns separate lets replay +fixtures reuse the declaration's real `WF` proof instead of re-running a +fragile type-synthesis tactic at every application and pi node. -/ +inductive TrTypeExpr : VLCtx → Expr → VExpr → Prop where + | bvar : Δ.find? (.inl i) = some (e, A) → TrTypeExpr Δ (.bvar i) e + | sort : VLevel.ofLevel Us u = some u' → TrTypeExpr Δ (.sort u) (.sort u') + | const : + env.constants c = some ci → + us.mapM (VLevel.ofLevel Us) = some us' → + us.length = ci.uvars → + TrTypeExpr Δ (.const c us) (.const c us') + | app : TrTypeExpr Δ f f' → TrTypeExpr Δ a a' → + TrTypeExpr Δ (.app f a) (.app f' a') + | mdata : TrTypeExpr Δ e e' → TrTypeExpr Δ (.mdata data e) e' + | forallE : TrTypeExpr Δ ty ty' → + TrTypeExpr ((none, .vlam ty') :: Δ) body body' → + TrTypeExpr Δ (.forallE name ty body bi) (.forallE ty' body') + +/-- Add the `TrExprS` typing premises to a structural metadata translation. +The source grammar is deliberately restricted to the forms that can occur in +the normalized types of constants emitted by the inductive compiler. -/ +theorem TrTypeExpr.to_trExprS + (H : TrTypeExpr env Us Δ e e') + (henv : env.Ordered) + (hΔ : OnCtx Δ.toCtx (env.IsType Us.length)) + (hwf : e'.WF env Us.length Δ.toCtx) : TrExprS env Us Δ e e' := by + induction H with + | bvar h => exact .bvar h + | sort h => exact .sort h + | const h1 h2 h3 => exact .const h1 h2 h3 + | app _ _ ihf iha => + obtain ⟨A, B, htf, hta⟩ := hwf.app_inv henv hΔ + exact .app htf hta (ihf hΔ ⟨_, htf⟩) (iha hΔ ⟨_, hta⟩) + | mdata _ ih => exact .mdata (ih hΔ hwf) + | forallE _ _ ihty ihbody => + obtain ⟨_, hwf⟩ := hwf + obtain ⟨hty, hbody⟩ := VEnv.HasType.forallE_inv henv hwf + obtain ⟨u, hty⟩ := hty + obtain ⟨v, hbody⟩ := hbody + exact .forallE ⟨u, hty⟩ ⟨v, hbody⟩ + (ihty hΔ ⟨_, hty⟩) (ihbody ⟨hΔ, ⟨u, hty⟩⟩ ⟨_, hbody⟩) + +#guard_named_axioms Ix.Theory.Named.TrTypeExpr.to_trExprS [propext, Classical.choice, Quot.sound] + +variable! (henv : Ordered env) in +theorem TrExprS.weakFV' (W : VLCtx.FVLift' Δ Δ' dk n k) (hΔ' : Δ'.WF env Us.length) + (H : TrExprS env Us Δ e e') : TrExprS env Us Δ' e (e'.lift' (n.consN k)) := by + induction H generalizing Δ' dk k with + | bvar h1 => exact .bvar (W.find? hΔ' h1) + | fvar h1 => exact .fvar (W.find? hΔ' h1) + | sort h1 => exact .sort h1 + | const h1 h2 h3 => exact .const h1 h2 h3 + | app h1 h2 _ _ ih1 ih2 => + exact .app (h1.weak' henv W.toCtx) (h2.weak' henv W.toCtx) (ih1 W hΔ') (ih2 W hΔ') + | lam h1 _ _ ih1 ih2 => + have h1 := h1.weak' henv W.toCtx + exact .lam h1 (ih1 W hΔ') (ih2 (W.cons_bvar _) ⟨hΔ', nofun, h1⟩) + | forallE h1 h2 _ _ ih1 ih2 => + have h1 := h1.weak' henv W.toCtx + have h2 := h2.weak' henv W.toCtx.cons + exact .forallE h1 h2 (ih1 W hΔ') (ih2 (W.cons_bvar _) ⟨hΔ', nofun, h1⟩) + | letE h1 _ _ _ ih1 ih2 ih3 => + have h1 := h1.weak' henv W.toCtx + exact .letE h1 (ih1 W hΔ') (ih2 W hΔ') (ih3 (W.cons_bvar _) ⟨hΔ', nofun, h1⟩) + | lit h1 _ ih => exact .lit h1 (ih W hΔ') + | mdata _ ih => exact .mdata (ih W hΔ') + | proj _ h2 ih => exact .proj (ih W hΔ') (h2.weak' henv W.toCtx) + +variable! (henv : WF env) in +theorem TrExpr.weakFV' (W : VLCtx.FVLift' Δ Δ' dk n k) (hΔ' : Δ'.WF env Us.length) + (H : TrExpr env Us Δ e e') : TrExpr env Us Δ' e (e'.lift' (n.consN k)) := + let ⟨_, H1, H2⟩ := H + ⟨_, H1.weakFV' henv W hΔ', H2.weak' henv W.toCtx⟩ + +variable! (henv : Ordered env) in +theorem TrExprS.weakFV (W : VLCtx.FVLift Δ Δ' dk n k) (hΔ' : Δ'.WF env Us.length) + (H : TrExprS env Us Δ e e') : TrExprS env Us Δ' e (e'.liftN n k) := by + simpa [VExpr.lift'_consN_skipN] using H.weakFV' henv W.toFVLift' hΔ' + +variable! (henv : WF env) in +theorem TrExpr.weakFV (W : VLCtx.FVLift Δ Δ' dk n k) (hΔ' : Δ'.WF env Us.length) + (H : TrExpr env Us Δ e e') : TrExpr env Us Δ' e (e'.liftN n k) := + let ⟨_, H1, H2⟩ := H + ⟨_, H1.weakFV henv W hΔ', H2.weakN henv W.toCtx⟩ + +variable! (henv : Ordered env) in +theorem TrExprS.weakBV (W : VLCtx.BVLift Δ Δ' dn dk n k) + (H : TrExprS env Us Δ e e') : TrExprS env Us Δ' (e.liftLooseBVars' dk dn) (e'.liftN n k) := by + induction H generalizing Δ' dk k with + | bvar h1 => exact .bvar (W.find? h1) + | fvar h1 => exact .fvar (W.find? h1) + | sort h1 => exact .sort h1 + | const h1 h2 h3 => exact .const h1 h2 h3 + | app h1 h2 _ _ ih1 ih2 => + exact .app (h1.weakN henv W.toCtx) (h2.weakN henv W.toCtx) (ih1 W) (ih2 W) + | lam h1 _ _ ih1 ih2 => + exact .lam (h1.weakN henv W.toCtx) (ih1 W) (ih2 (W.cons _)) + | forallE h1 h2 _ _ ih1 ih2 => + exact .forallE (h1.weakN henv W.toCtx) (h2.weakN henv W.toCtx.succ) (ih1 W) (ih2 (W.cons _)) + | letE h1 _ _ _ ih1 ih2 ih3 => + exact .letE (h1.weakN henv W.toCtx) (ih1 W) (ih2 W) (ih3 (W.cons _)) + | lit h1 _ ih => + refine .lit h1 (Expr.liftLooseBVars_eq_self ?_ ▸ ih W :) + exact Closed.toConstructor.looseBVarRange_le + | mdata _ ih => exact .mdata (ih W) + | proj _ h2 ih => exact .proj (ih W) (h2.weakN henv W.toCtx) + +variable! (henv : WF env) in +theorem TrExpr.weakBV (W : VLCtx.BVLift Δ Δ' dn dk n k) + (H : TrExpr env Us Δ e e') : TrExpr env Us Δ' (e.liftLooseBVars' dk dn) (e'.liftN n k) := + let ⟨_, H1, H2⟩ := H + ⟨_, H1.weakBV henv W, H2.weakN henv W.toCtx⟩ + +variable! (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) in +theorem HasType.skips (W : Ctx.LiftN n k Γ Γ') + (h1 : env.HasType U Γ' e A) (h2 : e.Skips n k) : ∃ B, env.HasType U Γ' e B ∧ B.Skips n k := + IsDefEq.skips henv hΓ' W h1 h2 h2 + +theorem TrProj.weak'_inv (henv : VEnv.WF env) (hΓ' : OnCtx Γ' (env.IsType U)) + (W : Ctx.Lift' l Γ Γ') : + TrProj env U Γ' s i (e.lift' l) e' → + ∃ e', TrProj env U Γ s i e e' := by + rintro ⟨view, levels, params, hname, hproj⟩ + obtain ⟨params', result, hresult⟩ := + henv.registeredStructureHeadInversion.weak'_inv hΓ' W hproj + exact ⟨result, view, levels, params', hname, hresult⟩ + +theorem TrProj.defeqDFC (henv : VEnv.WF env) (hΓ : env.IsDefEqCtx U [] Γ₁ Γ₂) + (he : env.IsDefEqU U Γ₁ e₁ e₂) (H : TrProj env U Γ₁ s i e₁ e') : + ∃ e', TrProj env U Γ₂ s i e₂ e' := by + obtain ⟨view, levels, params, hname, hproj⟩ := H + have he₂ : env.HasType U Γ₂ e₂ + (view.structureType levels params) := + (hproj.majorType.defeqU_l henv hΓ.isType he).defeqDFC + henv.ordered hΓ + obtain ⟨result, hresult⟩ := + hproj.defeqDFC henv.ordered hΓ he₂ + exact ⟨result, view, levels, params, hname, hresult⟩ + +theorem TrProj.mono {env env' : VEnv} (henv : env ≤ env') + (H : TrProj env U Γ s i e e') : TrProj env' U Γ s i e e' := by + obtain ⟨view, levels, params, hname, hproj⟩ := H + exact ⟨view, levels, params, hname, hproj.mono henv⟩ + +variable! {env env' : VEnv} (henv : env ≤ env') in +theorem TrExprS.mono (H : TrExprS env Us Δ e e') : TrExprS env' Us Δ e e' := by + induction H with + | bvar h1 => exact .bvar h1 + | fvar h1 => exact .fvar h1 + | sort h1 => exact .sort h1 + | const h1 h2 h3 => exact .const (henv.1 h1) h2 h3 + | app h1 h2 _ _ ih1 ih2 => exact .app (h1.mono henv) (h2.mono henv) ih1 ih2 + | lam h1 _ _ ih1 ih2 => exact .lam (h1.mono henv) ih1 ih2 + | forallE h1 h2 _ _ ih1 ih2 => exact .forallE (h1.mono henv) (h2.mono henv) ih1 ih2 + | letE h1 _ _ _ ih1 ih2 ih3 => exact .letE (h1.mono henv) ih1 ih2 ih3 + | lit h1 _ ih => refine .lit (h1.mono henv) ih + | mdata _ ih => exact .mdata ih + | proj _ h2 ih => exact .proj ih (h2.mono henv) + +variable! {env env' : VEnv} (henv : env ≤ env') in +theorem TrExpr.mono (H : TrExpr env Us Δ e e') : TrExpr env' Us Δ e e' := + let ⟨_, H1, H2⟩ := H; ⟨_, H1.mono henv, H2.mono henv⟩ + +variable! (env : VEnv) (U : Nat) in +inductive VLCtx.IsDefEq : VLCtx → VLCtx → Prop + | nil : VLCtx.IsDefEq [] [] + | cons {Δ₁ Δ₂ : VLCtx} : + VLCtx.IsDefEq Δ₁ Δ₂ → + (∀ fv deps, ofv = some (fv, deps) → fv ∉ Δ₁.fvars ∧ deps ⊆ Δ₁.fvars) → + VLocalDecl.IsDefEq env U Δ₁.toCtx d₁ d₂ → + VLCtx.IsDefEq ((ofv, d₁) :: Δ₁) ((ofv, d₂) :: Δ₂) + +variable! (henv : Ordered env) in +theorem VLCtx.IsDefEq.refl : ∀ {Δ}, VLCtx.WF env U Δ → VLCtx.IsDefEq env U Δ Δ + | [], _ => .nil + | (_, _) :: _, ⟨h1, h2, h3⟩ => .cons (IsDefEq.refl h1) h2 (.refl henv h1.toCtx h3) + +theorem VLCtx.IsDefEq.defeqCtx : VLCtx.IsDefEq env U Δ₁ Δ₂ → env.IsDefEqCtx U [] Δ₁.toCtx Δ₂.toCtx + | .nil => .zero + | .cons h1 _ (.vlam h2) => .succ h1.defeqCtx h2 + | .cons h1 _ (.vlet ..) => h1.defeqCtx + +theorem VLCtx.IsDefEq.fvars : VLCtx.IsDefEq env U Δ₁ Δ₂ → Δ₁.fvars = Δ₂.fvars + | .nil => by simp + | .cons (ofv := none) h1 h2 _ => h1.fvars + | .cons (ofv := some fv) h1 h2 _ => by simp [h1.fvars] + +/-- Definitionally equal verified local contexts have bound-variable entries +in exactly the same positions. -/ +theorem VLCtx.IsDefEq.bvars : VLCtx.IsDefEq env U Δ₁ Δ₂ → Δ₁.bvars = Δ₂.bvars + | .nil => rfl + | .cons (ofv := none) h1 _ _ => by + simp only [VLCtx.bvars, h1.bvars] + | .cons (ofv := some _) h1 _ _ => by + simp only [VLCtx.bvars, h1.bvars] + +theorem VLCtx.IsDefEq.wf : VLCtx.IsDefEq env U Δ₁ Δ₂ → VLCtx.WF env U Δ₁ + | .nil => ⟨⟩ + | .cons h1 h2 h3 => ⟨h1.wf, h2, h3.wf⟩ + +theorem VLCtx.IsDefEq.mono (henv : env ≤ env') : + VLCtx.IsDefEq env U Δ₁ Δ₂ → VLCtx.IsDefEq env' U Δ₁ Δ₂ + | .nil => .nil + | .cons h₁ h₂ h₃ => .cons (h₁.mono henv) h₂ (h₃.mono henv) + +/-- Definitionally equal verified contexts whose free-variable slots use the +same identifiers. Dependency metadata may differ because normalization can +change the syntactic free-variable list of a definitionally equal local type; +that metadata is irrelevant to Theory lookup and typing. -/ +inductive VLCtx.IsDefEqFVars (env : VEnv) (U : Nat) : VLCtx → VLCtx → Prop + | nil : IsDefEqFVars env U [] [] + | cons_bvar : + IsDefEqFVars env U Δ₁ Δ₂ → + VLocalDecl.IsDefEq env U Δ₁.toCtx d₁ d₂ → + IsDefEqFVars env U ((none, d₁) :: Δ₁) ((none, d₂) :: Δ₂) + | cons_fvar : + IsDefEqFVars env U Δ₁ Δ₂ → + VLocalDecl.IsDefEq env U Δ₁.toCtx d₁ d₂ → + IsDefEqFVars env U + ((some (fv, deps₁), d₁) :: Δ₁) + ((some (fv, deps₂), d₂) :: Δ₂) + +theorem VLCtx.IsDefEq.toFVars : + VLCtx.IsDefEq env U Δ₁ Δ₂ → VLCtx.IsDefEqFVars env U Δ₁ Δ₂ + | .nil => .nil + | .cons (ofv := none) h₁ _ h₃ => .cons_bvar h₁.toFVars h₃ + | .cons (ofv := some _) h₁ _ h₃ => .cons_fvar h₁.toFVars h₃ + +theorem VLCtx.IsDefEqFVars.defeqCtx : + VLCtx.IsDefEqFVars env U Δ₁ Δ₂ → + env.IsDefEqCtx U [] Δ₁.toCtx Δ₂.toCtx + | .nil => .zero + | .cons_bvar h₁ (.vlam h₂) => .succ h₁.defeqCtx h₂ + | .cons_bvar h₁ (.vlet ..) => h₁.defeqCtx + | .cons_fvar h₁ (.vlam h₂) => .succ h₁.defeqCtx h₂ + | .cons_fvar h₁ (.vlet ..) => h₁.defeqCtx + +theorem VLCtx.IsDefEqFVars.find?_uniq (henv : VEnv.WF env) + (hΔ : VLCtx.IsDefEqFVars env U Δ₁ Δ₂) + (H₁ : Δ₁.find? v = some (e₁, A₁)) + (H₂ : Δ₂.find? v = some (e₂, A₂)) : + env.IsDefEqU U Δ₁.toCtx A₁ A₂ ∧ + env.IsDefEq U Δ₁.toCtx e₁ e₂ A₁ := by + induction hΔ generalizing v e₁ e₂ A₁ A₂ with + | nil => simp [VLCtx.find?] at H₁ + | cons_bvar hΔ hd ih => + revert H₁ H₂ + simp only [VLCtx.find?] + split + · rintro ⟨⟩ ⟨⟩ + cases hd with + | vlam h => exact ⟨⟨_, h.weak henv⟩, .bvar .zero⟩ + | vlet h₁ h₂ => exact ⟨⟨_, h₂⟩, h₁⟩ + · simp + rintro d₁' n₁' H₁' rfl rfl d₂' n₂' H₂' rfl rfl + obtain ⟨h₂, h₃⟩ := ih H₁' H₂' + cases hd with + | vlam => exact ⟨h₂.weakN henv .one, h₃.weak henv⟩ + | vlet => simpa [VLocalDecl.depth] using ⟨h₂, h₃⟩ + | @cons_fvar Δ₁ Δ₂ d₁ d₂ fv deps₁ deps₂ hΔ hd ih => + revert H₁ H₂ + simp only [VLCtx.find?] + cases same : fv == (match v with | .inl _ => fv | .inr fv' => fv') <;> + simp only [VLCtx.next] + all_goals + cases v with + | inl i => + simp + rintro d₁' n₁' H₁' rfl rfl d₂' n₂' H₂' rfl rfl + obtain ⟨h₂, h₃⟩ := ih H₁' H₂' + cases hd with + | vlam => exact ⟨h₂.weakN henv .one, h₃.weak henv⟩ + | vlet => simpa [VLocalDecl.depth] using ⟨h₂, h₃⟩ + | inr fv' => + simp only [same] + split + · rintro ⟨⟩ ⟨⟩ + cases hd with + | vlam h => exact ⟨⟨_, h.weak henv⟩, .bvar .zero⟩ + | vlet h₁ h₂ => exact ⟨⟨_, h₂⟩, h₁⟩ + · simp + rintro d₁' n₁' H₁' rfl rfl d₂' n₂' H₂' rfl rfl + obtain ⟨h₂, h₃⟩ := ih H₁' H₂' + cases hd with + | vlam => exact ⟨h₂.weakN henv .one, h₃.weak henv⟩ + | vlet => simpa [VLocalDecl.depth] using ⟨h₂, h₃⟩ + +variable! (henv : Ordered env) in +theorem VLCtx.IsDefEq.symm : VLCtx.IsDefEq env U Δ₁ Δ₂ → VLCtx.IsDefEq env U Δ₂ Δ₁ + | .nil => .nil + | .cons h1 h2 h3 => + .cons h1.symm (by simpa [h1.fvars] using h2) (h3.symm.defeqDFC henv h1.defeqCtx) + +variable! (henv : VEnv.WF env) in +theorem VLCtx.IsDefEq.find?_uniq (hΔ : VLCtx.IsDefEq env U Δ₁ Δ₂) + (H1 : Δ₁.find? v = some (e₁, A₁)) (H2 : Δ₂.find? v = some (e₂, A₂)) : + env.IsDefEqU U Δ₁.toCtx A₁ A₂ ∧ env.IsDefEq U Δ₁.toCtx e₁ e₂ A₁ := by + let .cons hΔ h1 h2 := hΔ + match h2 with + | .vlam (type₁ := A₁) (type₂ := A₂) h2 => + revert H1 H2; unfold VLCtx.find?; split + · rintro ⟨⟩ ⟨⟩; exact ⟨⟨_, h2.weak henv⟩, .bvar .zero⟩ + · simp + rintro d₁' n₁' H1' rfl rfl d₂' n₂' H2' rfl rfl + obtain ⟨h2, h3⟩ := find?_uniq hΔ H1' H2' + exact ⟨h2.weakN henv .one, h3.weak henv⟩ + | .vlet h3 h4 => + revert H1 H2; unfold VLCtx.find?; split + · rintro ⟨⟩ ⟨⟩; exact ⟨⟨_, h4⟩, h3⟩ + · simp + rintro d₁' n₁' H1' rfl rfl d₂' n₂' H2' rfl rfl + simpa [VLocalDecl.depth, VLCtx.toCtx] using find?_uniq hΔ H1' H2' + +theorem VLCtx.IsDefEq.find?_defeqDFC (hΔ : VLCtx.IsDefEq env U Δ₁ Δ₂) + (H : Δ₁.find? v = some (e₁, A₁)) : + ∃ e₂ A₂, Δ₂.find? v = some (e₂, A₂) := by + let .cons hΔ _ _ := hΔ + revert H; unfold VLCtx.find?; split + · exact fun _ => ⟨_, _, rfl⟩ + · simp; rintro e A H rfl rfl + obtain ⟨_, _, H⟩ := find?_defeqDFC hΔ H + exact ⟨_, _, _, _, H, rfl, rfl⟩ + +theorem TrExprS.closed (H : TrExprS env Us Δ e e') : Closed e Δ.bvars := by + induction H with + | @bvar e A Δ i h1 => + simp [Closed] + induction Δ generalizing i e A with + | nil => cases h1 + | cons d Δ ih => + match d, i with + | (none, _), 0 => exact Nat.succ_pos _ + | (none, _), _ + 1 => + simp [VLCtx.find?, VLCtx.next, bind] at h1 + obtain ⟨_, _, h1, rfl, rfl⟩ := h1 + exact Nat.succ_lt_succ (ih h1) + | (some _, _), _ => + simp [VLCtx.find?, VLCtx.next, bind] at h1 + obtain ⟨_, _, h1, rfl, rfl⟩ := h1 + exact ih h1 + | fvar | sort | const | lit | mdata => trivial + | app _ _ _ _ ih1 ih2 + | lam _ _ _ ih1 ih2 + | forallE _ _ _ _ ih1 ih2 => exact ⟨ih1, ih2⟩ + | letE _ _ _ _ ih1 ih2 ih3 => exact ⟨ih1, ih2, ih3⟩ + | proj _ _ ih => exact ih + +theorem ofLevel_hasMVar (h : VLevel.ofLevel ls l = some l') : l.hasMVar' = false := by + induction l generalizing l' with simp [VLevel.ofLevel, bind, Level.hasMVar'] at h ⊢ + | succ _ ih => obtain ⟨l', h, ⟨⟩⟩ := h; exact ih h + | max _ _ ih1 ih2 | imax _ _ ih1 ih2 => obtain ⟨_, h1, _, h2, ⟨⟩⟩ := h; exact ⟨ih1 h1, ih2 h2⟩ + +theorem TrExprS.fvarsIn (H : TrExprS env Us Δ e e') : FVarsIn (· ∈ Δ.fvars) e := by + induction H with + | fvar h1 => exact VLCtx.find?_eq_some.1 ⟨_, h1⟩ + | sort h => exact ofLevel_hasMVar h + | const _ h => + rw [List.mapM_eq_some] at h + intro _ hl + have ⟨_, _, h⟩ := h.forall_exists_l _ hl + exact ofLevel_hasMVar h + | bvar | lit | mdata => trivial + | app _ _ _ _ ih1 ih2 + | lam _ _ _ ih1 ih2 + | forallE _ _ _ _ ih1 ih2 => exact ⟨ih1, ih2⟩ + | letE _ _ _ _ ih1 ih2 ih3 => exact ⟨ih1, ih2, ih3⟩ + | proj _ _ ih => exact ih + +theorem TrExprS.fvarsList (H : TrExprS env Us Δ e e') : e.fvarsList ⊆ Δ.fvars := + (fvarsIn_iff.1 H.fvarsIn).1 + +theorem TrExpr.closed (H : TrExpr env Us Δ e e') : Closed e Δ.bvars := + let ⟨_, H, _⟩ := H; H.closed + +theorem TrExpr.fvarsIn (H : TrExpr env Us Δ e e') : FVarsIn (· ∈ Δ.fvars) e := + let ⟨_, H, _⟩ := H; H.fvarsIn + +theorem TrExpr.fvarsList (H : TrExpr env Us Δ e e') : e.fvarsList ⊆ Δ.fvars := + (fvarsIn_iff.1 H.fvarsIn).1 + +theorem TrProj.wf (H1 : TrProj env U Γ s i e e') + (_H2 : VExpr.WF env U Γ e) : VExpr.WF env U Γ e' := by + obtain ⟨view, levels, params, _hname, hproj⟩ := H1 + obtain ⟨code, _hcode, rfl, hprojector⟩ := hproj.program + exact ⟨_, hprojector.app hproj.majorType⟩ + +theorem TrExpr.wf (H : TrExpr env Us Δ e e') : VExpr.WF env Us.length Δ.toCtx e' := + let ⟨_, _, _, H⟩ := H; ⟨_, H.hasType.2⟩ + +variable! (henv : Ordered env) {Us : List Name} (hΔ : VLCtx.WF env Us.length Δ) in +theorem TrExprS.wf (H : TrExprS env Us Δ e e') : VExpr.WF env Us.length Δ.toCtx e' := by + induction H with + | bvar h1 | fvar h1 => exact ⟨_, hΔ.find?_wf henv h1⟩ + | sort h1 => exact ⟨_, HasType.sort (.of_ofLevel h1)⟩ + | const h1 h2 h3 => exact ⟨_, + HasType.const h1 (.of_mapM_ofLevel h2) ((List.mapM_eq_some.1 h2).length_eq.symm.trans h3)⟩ + | app h1 h2 => exact ⟨_, h1.app h2⟩ + | lam h1 _ _ _ ih2 => + have ⟨_, h1'⟩ := h1 + have ⟨_, h2'⟩ := ih2 ⟨hΔ, nofun, h1⟩ + refine ⟨_, h1'.lam h2'⟩ + | forallE h1 h2 => have ⟨_, h1'⟩ := h1; have ⟨_, h2'⟩ := h2; exact ⟨_, h1'.forallE h2'⟩ + | letE h1 _ _ _ _ _ ih3 => exact ih3 ⟨hΔ, nofun, h1⟩ + | lit _ _ ih | mdata _ ih => exact ih hΔ + | proj _ h2 ih => exact h2.wf (ih hΔ) + +variable! (henv : Ordered env) {Us : List Name} (hΔ : VLCtx.WF env Us.length Δ) in +theorem TrExprS.trExpr (H : TrExprS env Us Δ e e') : TrExpr env Us Δ e e' := + ⟨_, H, H.wf henv hΔ⟩ + +theorem TrExpr.defeq (henv : VEnv.WF env) (hΔ : OnCtx Δ.toCtx (env.IsType Us.length)) + (h1 : TrExpr env Us Δ e e₁) (h2 : env.IsDefEqU Us.length Δ.toCtx e₁ e₂) : + TrExpr env Us Δ e e₂ := let ⟨_, H, h1⟩ := h1; ⟨_, H, h1.trans henv hΔ h2⟩ + +theorem TrExpr.app (henv : VEnv.WF env) (hΔ : OnCtx Δ.toCtx (env.IsType Us.length)) + (h1 : env.HasType Us.length Δ.toCtx f' (.forallE A B)) + (h2 : env.HasType Us.length Δ.toCtx a' A) + (h3 : TrExpr env Us Δ f f') + (h4 : TrExpr env Us Δ a a') : + TrExpr env Us Δ (.app f a) (.app f' a') := + let ⟨_, s3, h3⟩ := h3 + let ⟨_, s4, h4⟩ := h4 + have h3 := h3.of_r henv hΔ h1 + have h4 := h4.of_r henv hΔ h2 + ⟨_, .app h3.hasType.1 h4.hasType.1 s3 s4, _, h3.appDF h4⟩ + +variable! (henv : VEnv.WF env) (hΓ : IsDefEqCtx env U [] Γ₁ Γ₂) in +theorem TrProj.uniq (H1 : TrProj env U Γ₁ s₁ i e₁ e₁') + (H2 : TrProj env U Γ₂ s₂ i e₂ e₂') + (H : env.IsDefEqU U Γ₁ e₁ e₂) : + env.IsDefEqU U Γ₁ e₁' e₂' := by + obtain ⟨view₁, levels₁, params₁, _hname₁, hproj₁⟩ := H1 + obtain ⟨view₂, levels₂, params₂, _hname₂, hproj₂⟩ := H2 + exact henv.registeredStructureHeadInversion.unique + hΓ hproj₁ hproj₂ H + +variable! (henv : VEnv.WF env) {Us : List Name} (hΔ : VLCtx.IsDefEq env Us.length Δ₁ Δ₂) in +theorem TrExprS.uniq (H1 : TrExprS env Us Δ₁ e e₁) (H2 : TrExprS env Us Δ₂ e e₂) : + env.IsDefEqU Us.length Δ₁.toCtx e₁ e₂ := by + induction H1 generalizing Δ₂ e₂ with + | bvar l1 => let .bvar r1 := H2; exact ⟨_, (hΔ.find?_uniq henv l1 r1).2⟩ + | fvar l1 => let .fvar r1 := H2; exact ⟨_, (hΔ.find?_uniq henv l1 r1).2⟩ + | sort l1 => + let .sort r1 := H2; cases l1.symm.trans r1; exact ⟨_, HasType.sort (.of_ofLevel l1)⟩ + | const l1 l2 l3 => + let .const r1 r2 r3 := H2; cases l1.symm.trans r1; cases l2.symm.trans r2 + exact (TrExprS.const l1 l2 l3).wf henv hΔ.wf + | app l1 l2 _ _ ih3 ih4 => + let .app _ _ r3 r4 := H2 + exact ⟨_, .appDF + (ih3 hΔ r3 |>.of_l henv hΔ.wf.toCtx l1) + (ih4 hΔ r4 |>.of_l henv hΔ.wf.toCtx l2)⟩ + | lam l1 _ _ ih2 ih3 => + let ⟨_, l1⟩ := l1; let .lam _ r2 r3 := H2 + have hA := ih2 hΔ r2 |>.of_l henv hΔ.wf.toCtx l1 + have ⟨_, hb⟩ := ih3 (hΔ.cons nofun <| .vlam hA) r3 + exact ⟨_, .lamDF hA hb⟩ + | forallE l1 l2 _ _ ih3 ih4 => + let ⟨_, l1'⟩ := l1; let ⟨_, l2⟩ := l2; let .forallE _ _ r3 r4 := H2 + have hA := ih3 hΔ r3 |>.of_l henv hΔ.wf.toCtx l1' + have hB := ih4 (hΔ.cons nofun <| .vlam hA) r4 |>.of_l (Γ := _::_) henv ⟨hΔ.wf.toCtx, l1⟩ l2 + exact ⟨_, .forallEDF hA hB⟩ + | letE l1 _ _ _ ih2 ih3 ih4 => + have hΓ := hΔ.wf.toCtx + let .letE _ r2 r3 r4 := H2 + have ⟨_, hb⟩ := l1.isType henv hΓ + refine ih4 (hΔ.cons nofun ?_) r4 + exact .vlet (ih3 hΔ r3 |>.of_l henv hΓ l1) (ih2 hΔ r2 |>.of_l henv hΓ hb) + | lit _ _ ih1 => let .lit _ r2 := H2; exact ih1 hΔ r2 + | mdata _ ih1 => let .mdata r1 := H2; exact ih1 hΔ r1 + | proj _ l2 ih1 => let .proj r1 r2 := H2; exact l2.uniq henv hΔ.defeqCtx r2 (ih1 hΔ r1) + +variable! (henv : VEnv.WF env) {Us : List Name} + (hΔ : VLCtx.IsDefEqFVars env Us.length Δ₁ Δ₂) + (hΔwf : VLCtx.WF env Us.length Δ₁) in +/-- Translation congruence across contexts with the same free-variable +identifiers but potentially different dependency metadata. -/ +theorem TrExprS.uniqFVars + (H₁ : TrExprS env Us Δ₁ e e₁) (H₂ : TrExprS env Us Δ₂ e e₂) : + env.IsDefEqU Us.length Δ₁.toCtx e₁ e₂ := by + induction H₁ generalizing Δ₂ e₂ with + | bvar l₁ => + let .bvar r₁ := H₂ + exact ⟨_, (hΔ.find?_uniq henv l₁ r₁).2⟩ + | fvar l₁ => + let .fvar r₁ := H₂ + exact ⟨_, (hΔ.find?_uniq henv l₁ r₁).2⟩ + | sort l₁ => + let .sort r₁ := H₂ + cases l₁.symm.trans r₁ + exact ⟨_, HasType.sort (.of_ofLevel l₁)⟩ + | const l₁ l₂ l₃ => + let .const r₁ r₂ r₃ := H₂ + cases l₁.symm.trans r₁ + cases l₂.symm.trans r₂ + exact (TrExprS.const l₁ l₂ l₃).wf henv hΔwf + | app l₁ l₂ _ _ ih₃ ih₄ => + let .app _ _ r₃ r₄ := H₂ + exact ⟨_, .appDF + (ih₃ hΔ hΔwf r₃ |>.of_l henv hΔwf.toCtx l₁) + (ih₄ hΔ hΔwf r₄ |>.of_l henv hΔwf.toCtx l₂)⟩ + | lam l₁ _ _ ih₂ ih₃ => + let ⟨u, l₁'⟩ := l₁ + let .lam _ r₂ r₃ := H₂ + have hA := ih₂ hΔ hΔwf r₂ |>.of_l henv hΔwf.toCtx l₁' + have ⟨_, hb⟩ := ih₃ (.cons_bvar hΔ (.vlam hA)) + ⟨hΔwf, nofun, ⟨u, l₁'⟩⟩ r₃ + exact ⟨_, .lamDF hA hb⟩ + | forallE l₁ l₂ _ _ ih₃ ih₄ => + let ⟨_, l₁'⟩ := l₁ + let ⟨_, l₂⟩ := l₂ + let .forallE _ _ r₃ r₄ := H₂ + have hA := ih₃ hΔ hΔwf r₃ |>.of_l henv hΔwf.toCtx l₁' + have hbody := ih₄ (.cons_bvar hΔ (.vlam hA)) + ⟨hΔwf, nofun, l₁⟩ r₄ + have hbodyCtx : OnCtx (_ :: _) (env.IsType Us.length) := + ⟨hΔwf.toCtx, l₁⟩ + have hB := hbody.of_l henv hbodyCtx l₂ + exact ⟨_, .forallEDF hA hB⟩ + | letE l₁ _ _ _ ih₂ ih₃ ih₄ => + have hΓ := hΔwf.toCtx + let .letE _ r₂ r₃ r₄ := H₂ + have ⟨_, hb⟩ := l₁.isType henv hΓ + refine ih₄ (.cons_bvar hΔ ?_) ⟨hΔwf, nofun, l₁⟩ r₄ + exact .vlet + (ih₃ hΔ hΔwf r₃ |>.of_l henv hΓ l₁) + (ih₂ hΔ hΔwf r₂ |>.of_l henv hΓ hb) + | lit _ _ ih₁ => + let .lit _ r₂ := H₂ + exact ih₁ hΔ hΔwf r₂ + | mdata _ ih₁ => + let .mdata r₁ := H₂ + exact ih₁ hΔ hΔwf r₁ + | proj _ l₂ ih₁ => + let .proj r₁ r₂ := H₂ + exact l₂.uniq henv hΔ.defeqCtx r₂ (ih₁ hΔ hΔwf r₁) + +variable! (henv : VEnv.WF env) {Us : List Name} (hΔ : VLCtx.IsDefEq env Us.length Δ₁ Δ₂) in +theorem TrExpr.uniq (H1 : TrExpr env Us Δ₁ e e₁) (H2 : TrExpr env Us Δ₂ e e₂) : + env.IsDefEqU Us.length Δ₁.toCtx e₁ e₂ := by + let ⟨_, H1, eq1⟩ := H1 + let ⟨_, H2, eq2⟩ := H2 + exact eq1.symm.trans henv hΔ.wf <| (H1.uniq henv hΔ H2).trans henv hΔ.wf <| + eq2.defeqDFC henv (hΔ.defeqCtx.symm henv) + +variable! (henv : VEnv.WF env) {Us : List Name} (hΔ : VLCtx.IsDefEq env Us.length Δ₁ Δ₂) in +theorem TrExprS.defeqDFC (H : TrExprS env Us Δ₁ e e₁) : ∃ e₂, TrExprS env Us Δ₂ e e₂ := by + induction H generalizing Δ₂ with + | bvar h1 => have ⟨_, _, h1⟩ := hΔ.find?_defeqDFC h1; exact ⟨_, .bvar h1⟩ + | fvar h1 => have ⟨_, _, h1⟩ := hΔ.find?_defeqDFC h1; exact ⟨_, .fvar h1⟩ + | sort h1 => exact ⟨_, .sort h1⟩ + | const h1 h2 h3 => exact ⟨_, .const h1 h2 h3⟩ + | app h1 h2 h3 h4 ih3 ih4 => + let ⟨_, h3'⟩ := ih3 hΔ + let ⟨_, h4'⟩ := ih4 hΔ + have h1 := h1.defeqDFC henv hΔ.defeqCtx + have h2 := h2.defeqDFC henv hΔ.defeqCtx + have h1 := h1.defeqU_l henv (hΔ.symm henv).wf (h3'.uniq henv (hΔ.symm henv) h3).symm + have h2 := h2.defeqU_l henv (hΔ.symm henv).wf (h4'.uniq henv (hΔ.symm henv) h4).symm + exact ⟨_, .app h1 h2 h3' h4'⟩ + | lam h1 h2 h3 ih2 ih3 => + let ⟨_, h1'⟩ := h1 + let ⟨_, h2'⟩ := ih2 hΔ + have h1 := h1.defeqDFC henv hΔ.defeqCtx + have h1 := h1.defeqU_l henv (hΔ.symm henv).wf (h2'.uniq henv (hΔ.symm henv) h2).symm + have ht := (h2.uniq henv hΔ h2').of_l henv hΔ.wf h1' + let ⟨_, h3'⟩ := ih3 (hΔ.cons nofun <| .vlam ht) + exact ⟨_, .lam h1 h2' h3'⟩ + | forallE h1 h2 h3 h4 ih3 ih4 => + let ⟨_, h1'⟩ := h1 + let ⟨_, h2'⟩ := h2 + let ⟨_, h3'⟩ := ih3 hΔ + have ht := (h3.uniq henv hΔ h3').of_l henv hΔ.wf h1' + have hΔ' := hΔ.cons (ofv := none) nofun (.vlam ht) + let ⟨_, h4'⟩ := ih4 hΔ' + have h1 := h1.defeqDFC henv hΔ.defeqCtx + have h2 := h2.defeqDFC henv (hΔ.defeqCtx.succ ht) + have h1 := h1.defeqU_l henv (hΔ.symm henv).wf (h3'.uniq henv (hΔ.symm henv) h3).symm + have h2 := h2.defeqU_l henv (hΔ'.symm henv).wf (h4'.uniq henv (hΔ'.symm henv) h4).symm + exact ⟨_, .forallE h1 h2 h3' h4'⟩ + | letE h1 h2 h3 h4 ih2 ih3 ih4 => + let ⟨_, h2'⟩ := ih2 hΔ + let ⟨_, h3'⟩ := ih3 hΔ + have ⟨_, h0⟩ := h1.isType henv hΔ.wf + have t0 := (h2.uniq henv hΔ h2').of_l henv hΔ.wf h0 + have t1 := (h3.uniq henv hΔ h3').of_l henv hΔ.wf h1 + have t2 := (h2'.uniq henv (hΔ.symm henv) h2).symm + have t3 := (h3'.uniq henv (hΔ.symm henv) h3).symm + have hΔ' := hΔ.cons (ofv := none) nofun (.vlet t1 t0) + let ⟨_, h4'⟩ := ih4 hΔ' + have h0 := h0.defeqDFC henv hΔ.defeqCtx + have h0 := h0.defeqU_l henv (hΔ.symm henv).wf t2 + have h1 := h1.defeqDFC henv hΔ.defeqCtx + have h1 := h1.defeqU_l henv (hΔ.symm henv).wf t3 + have h1 := h1.defeqU_r henv (hΔ.symm henv).wf t2 + exact ⟨_, .letE h1 h2' h3' h4'⟩ + | lit h1 _ ih1 => let ⟨_, h2⟩ := ih1 hΔ; exact ⟨_, .lit h1 h2⟩ + | mdata _ ih1 => let ⟨_, h1⟩ := ih1 hΔ; exact ⟨_, .mdata h1⟩ + | proj h1 h2 ih1 => + let ⟨_, h1'⟩ := ih1 hΔ + let ⟨_, h2⟩ := h2.defeqDFC henv hΔ.defeqCtx (h1.uniq henv hΔ h1') + exact ⟨_, .proj h1' h2⟩ + +variable! (henv : VEnv.WF env) {Us : List Name} (hΔ : VLCtx.IsDefEq env Us.length Δ₁ Δ₂) in +theorem TrExprS.defeqDFC' (H : TrExprS env Us Δ₁ e e') : TrExpr env Us Δ₂ e e' := by + let ⟨_, H'⟩ := H.defeqDFC henv hΔ + refine ⟨_, H', H'.uniq henv (hΔ.symm henv) H⟩ + +theorem TrExpr.lam (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length Δ) + (h1 : env.IsType Us.length Δ.toCtx ty') + (h2 : TrExpr env Us Δ ty ty') + (h3 : TrExpr env Us ((none, .vlam ty') :: Δ) body body') : + TrExpr env Us Δ (.lam name ty body bi) (.lam ty' body') := + let ⟨_, h1⟩ := h1 + let ⟨_, s2, h2⟩ := h2 + let ⟨_, s3, _, h3⟩ := h3 + have := h2.symm.of_l henv hΔ h1 + have hΔΔ := .cons (.refl henv hΔ) (ofv := none) nofun (.vlam this) + let ⟨_, s3'⟩ := s3.defeqDFC henv hΔΔ + let ⟨_, h3'⟩ := s3.uniq henv hΔΔ s3' + ⟨_, .lam ⟨_, this.hasType.2⟩ s2 s3', _, + .symm <| .lamDF this <| h3.symm.trans_l henv hΔΔ.wf.toCtx h3'⟩ + +theorem TrExpr.forallE (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length Δ) + (h1 : env.IsType Us.length Δ.toCtx ty') + (h2 : env.IsType Us.length (ty' :: Δ.toCtx) body') + (h3 : TrExpr env Us Δ ty ty') + (h4 : TrExpr env Us ((none, .vlam ty') :: Δ) body body') : + TrExpr env Us Δ (.forallE name ty body bi) (.forallE ty' body') := + let ⟨_, h1⟩ := h1 + let ⟨_, h2⟩ := h2 + let ⟨_, s3, h3⟩ := h3 + let ⟨_, s4, _, h4⟩ := h4 + have := h3.symm.of_l henv hΔ h1 + have hΔΔ := .cons (.refl henv hΔ) (ofv := none) nofun (.vlam this) + let ⟨_, s4'⟩ := s4.defeqDFC henv hΔΔ + let ⟨_, h4'⟩ := s4.uniq henv hΔΔ s4' + have h4 := h4.trans_r henv hΔΔ.wf h2 |>.symm.trans_l henv hΔΔ.wf h4' + have h5 := h4.hasType.2.defeq_l henv this + ⟨_, .forallE ⟨_, this.hasType.2⟩ ⟨_, h5⟩ s3 s4', _, .symm <| .forallEDF this h4⟩ + +theorem TrExpr.letE (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length Δ) + (h1 : env.HasType Us.length Δ.toCtx val' ty') + (h2 : TrExpr env Us Δ ty ty') + (h3 : TrExpr env Us Δ val val') + (h4 : TrExpr env Us ((none, .vlet ty' val') :: Δ) body body') : + TrExpr env Us Δ (.letE name ty val body nd) body' := + have ⟨_, h0⟩ := h1.isType henv hΔ + let ⟨_, s2, h2⟩ := h2 + let ⟨_, s3, h3⟩ := h3 + let ⟨_, s4, _, h4⟩ := h4 + have h1' := h1.defeqU_r henv hΔ h2.symm |>.defeqU_l henv hΔ h3.symm + have h2' := h2.symm.of_l henv hΔ h0 + have h3' := h3.symm.of_l henv hΔ h1 + have hΔΔ := VLCtx.IsDefEq.cons (.refl henv hΔ) (ofv := none) nofun (.vlet h3' h2') + let ⟨_, s4'⟩ := s4.defeqDFC henv hΔΔ + let ⟨_, h4'⟩ := s4.uniq henv hΔΔ s4' + ⟨_, .letE h1' s2 s3 s4', _, h4'.symm.trans_l henv hΔ h4⟩ + +theorem TrExpr.lit (h1 : env.ContainsLits l) + (h : TrExpr env Us Δ l.toConstructor e') : TrExpr env Us Δ (.lit l) e' := + let ⟨_, s2, h2⟩ := h; ⟨_, .lit h1 s2, h2⟩ + +theorem TrExpr.mdata (h : TrExpr env Us Δ e e') : TrExpr env Us Δ (.mdata d e) e' := + let ⟨_, s2, h2⟩ := h; ⟨_, .mdata s2, h2⟩ + +theorem TrExpr.proj {env Us Δ e e' s i e''} (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length Δ) + (H : TrExpr env Us Δ e e') + (H2 : TrProj env Us.length Δ.toCtx s i e' e'') : + TrExpr env Us Δ (.proj s i e) e'' := + let ⟨_, s2, h2⟩ := H + have ⟨_, H2'⟩ := H2.defeqDFC henv (.refl hΔ) h2.symm + ⟨_, .proj s2 H2', H2'.uniq henv (.refl hΔ) H2 h2⟩ + +theorem TrExprS.weakFV'_inv (henv : VEnv.WF env) + (W : VLCtx.FVLift' Δ Δ₂ dk n k) (hΔ : VLCtx.IsDefEq env Us.length Δ₁ Δ₂) + (H : TrExprS env Us Δ₁ e e') (hc : Closed e dk) (hv : FVarsIn (· ∈ VLCtx.fvars Δ) e) : + ∃ e', TrExprS env Us Δ e e' := by + induction H generalizing Δ Δ₂ dk k with + | @bvar e A Δ₁ i h1 => + suffices ∃ p, Δ.find? (.inl i) = some p from let ⟨_, h⟩ := this; ⟨_, .bvar h⟩ + simp [Closed] at hc + induction W generalizing i e A Δ₁ with | @cons_bvar _ Δ₂ _ _ _ d _ ih => ?_ | _ => cases hc + obtain ⟨d, Δ₂, rfl, hΔ₁⟩ : ∃ d Δ₁', Δ₁ = (none, d) :: Δ₁' ∧ + VLCtx.IsDefEq env Us.length Δ₁' Δ₂ := by cases d <;> cases hΔ <;> exact ⟨_, _, rfl, ‹_›⟩ + simp [VLCtx.find?] at h1 ⊢ + rcases i with _ | i <;> simp [VLCtx.next] at h1 ⊢ + obtain ⟨_, _, h1, _⟩ := h1 + have ⟨_, h1⟩ := ih h1 hΔ₁ (Nat.lt_of_succ_lt_succ hc) hv + exact ⟨_, _, _, _, h1, rfl, rfl⟩ + | @fvar _ _ _ fv => let ⟨_, h⟩ := VLCtx.find?_eq_some.2 hv; exact ⟨_, .fvar h⟩ + | sort h1 => exact ⟨_, .sort h1⟩ + | const h1 h2 h3 => exact ⟨_, .const h1 h2 h3⟩ + | app h1 h2 hf ha ih1 ih2 => + have hΔ₁ := hΔ.wf; have hΔ₂ := (hΔ.symm henv).wf + let ⟨f₁, ih1⟩ := ih1 W hΔ hc.1 hv.1 + let ⟨a₁, ih2⟩ := ih2 W hΔ hc.2 hv.2 + have h1 := h1.defeqU_l henv hΔ₁.toCtx <| hf.uniq henv hΔ (ih1.weakFV' henv W hΔ₂) + have h2 := h2.defeqU_l henv hΔ₁.toCtx <| ha.uniq henv hΔ (ih2.weakFV' henv W hΔ₂) + have := VExpr.WF.weak'_iff henv hΔ₂.toCtx W.toCtx (e := f₁.app a₁) + have := this.1 ⟨_, (h1.app h2).defeqDFC henv hΔ.defeqCtx⟩ + have ⟨_, _, h1, h2⟩ := this.app_inv henv (W.wf henv hΔ₂).toCtx + exact ⟨_, .app h1 h2 ih1 ih2⟩ + | lam h1 ht _ ih1 ih2 => + let ⟨_, h1⟩ := h1 + have hΔ₁ := hΔ.wf; have hΔ₂ := (hΔ.symm henv).wf + let ⟨ty₁, ih1⟩ := ih1 W hΔ hc.1 hv.1 + have htt := ht.uniq henv hΔ (ih1.weakFV' henv W hΔ₂) |>.of_l henv hΔ₁.toCtx h1 + have ⟨_, ih2⟩ := ih2 (W.cons_bvar (.vlam _)) + (hΔ.cons (ofv := none) nofun <| .vlam htt) hc.2 hv.2.fvars_cons + have h1 := HasType.weak'_iff (A := .sort _) henv hΔ₂.toCtx W.toCtx + |>.1 (htt.hasType.2.defeqDFC henv hΔ.defeqCtx) + exact ⟨_, .lam ⟨_, h1⟩ ih1 ih2⟩ + | forallE h1 h2 ht hb ih1 ih2 => + let ⟨_, h1⟩ := h1; let ⟨_, h2⟩ := h2 + have hΔ₁ := hΔ.wf; have hΔ₂ := (hΔ.symm henv).wf + let ⟨ty₁, ih1⟩ := ih1 W hΔ hc.1 hv.1 + have htt := ht.uniq henv hΔ (ih1.weakFV' henv W hΔ₂) |>.of_l henv hΔ₁.toCtx h1 + have hΔ' := hΔ.cons (ofv := none) nofun <| .vlam htt + have ⟨_, ih2⟩ := ih2 (W.cons_bvar (.vlam _)) hΔ' hc.2 hv.2.fvars_cons + have h1' := htt.hasType.2.defeqDFC henv hΔ.defeqCtx + have h1 := HasType.weak'_iff (A := .sort _) henv hΔ₂.toCtx W.toCtx |>.1 h1' + have hΔ₂' : VLCtx.WF _ _ ((none, .vlam _) :: _) := ⟨hΔ₂, nofun, _, h1'⟩ + have h2 := (HasType.weak'_iff (A := .sort _) henv hΔ₂'.toCtx (W.cons_bvar (.vlam _)).toCtx).1 <| + hb.uniq henv hΔ' (ih2.weakFV' henv (W.cons_bvar _) hΔ₂') + |>.of_l (Γ := _::_) henv ⟨hΔ₁.toCtx, _, htt.hasType.1⟩ h2 + |>.hasType.2.defeqDFC henv (.succ hΔ.defeqCtx htt) + exact ⟨_, .forallE ⟨_, h1⟩ ⟨_, h2⟩ ih1 ih2⟩ + | letE h1 ht ha _ ih1 ih2 ih3 => + have hΔ₁ := hΔ.wf; have hΔ₂ := (hΔ.symm henv).wf + let ⟨ty₁, ih1⟩ := ih1 W hΔ hc.1 hv.1 + let ⟨val₁, ih2⟩ := ih2 W hΔ hc.2.1 hv.2.1 + have hvv := ha.uniq henv hΔ (ih2.weakFV' henv W hΔ₂) |>.of_l henv hΔ₁.toCtx h1 + let ⟨_, h2⟩ := h1.isType henv hΔ₁.toCtx + have htt := ht.uniq henv hΔ (ih1.weakFV' henv W hΔ₂) |>.of_l henv hΔ₁.toCtx h2 + have ⟨_, ih3⟩ := ih3 (W.cons_bvar (.vlet ..)) + (hΔ.cons nofun <| .vlet hvv htt) hc.2.2 hv.2.2.fvars_cons + have h1 := HasType.weak'_iff henv hΔ₂.toCtx W.toCtx + |>.1 ((htt.defeqDF hvv).hasType.2.defeqDFC henv hΔ.defeqCtx) + exact ⟨_, .letE h1 ih1 ih2 ih3⟩ + | lit h1 _ ih => let ⟨_, ih⟩ := ih W hΔ .toConstructor .toConstructor; exact ⟨_, .lit h1 ih⟩ + | mdata _ ih => let ⟨_, ih⟩ := ih W hΔ hc hv; exact ⟨_, .mdata ih⟩ + | proj h1 h2 ih => + have hΔ₂ := (hΔ.symm henv).wf + let ⟨_, ih⟩ := ih W hΔ hc hv + have htt := h1.uniq henv hΔ (ih.weakFV' henv W hΔ₂) + have ⟨_, h2⟩ := h2.defeqDFC henv hΔ.defeqCtx htt + have ⟨_, h2⟩ := h2.weak'_inv henv hΔ₂.toCtx W.toCtx + exact ⟨_, .proj ih h2⟩ + +theorem TrExprS.weakFV_inv (henv : VEnv.WF env) + (W : VLCtx.FVLift Δ Δ₂ dk n k) (hΔ : VLCtx.IsDefEq env Us.length Δ₁ Δ₂) + (H : TrExprS env Us Δ₁ e e') (hc : Closed e dk) (hv : FVarsIn (· ∈ VLCtx.fvars Δ) e) : + ∃ e', TrExprS env Us Δ e e' := H.weakFV'_inv henv W.toFVLift' hΔ hc hv + +variable! (henv : Ordered env) (h₀ : TrExprS env Us Δ₀ e₀ e₀') in +theorem TrExprS.instN_var (W : VLCtx.InstN Δ₀ e₀' A₀ dk k Δ₁ Δ) (H : Δ₁.find? v = some (e', A)) : + TrExprS env Us Δ (Expr.instantiate1' (VLCtx.varToExpr v) e₀ dk) (e'.inst e₀' k) := by + induction W generalizing v e' A with + | zero => + obtain (_|i)|fv := v <;> simp [VLCtx.varToExpr, Expr.instantiate1', Expr.liftLooseBVars_zero] + · cases H; simp [VLocalDecl.value, VExpr.inst]; exact h₀ + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + simp [VLocalDecl.depth, VExpr.inst_liftN] + exact .bvar H + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + simp [VLocalDecl.depth, VExpr.inst_liftN] + exact .fvar H + | @succ _ k _ _ d _ ih => + obtain (_|i)|fv := v <;> simp [VLCtx.varToExpr, Expr.instantiate1'] + · cases H + cases d <;> exact .bvar <| by simp [VLocalDecl.value, VExpr.inst, VLocalDecl.depth]; rfl + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + have := ih H; revert this + simp [VLCtx.varToExpr, Expr.instantiate1']; split <;> [skip; split] + · intro | .bvar h => ?_ + exact .bvar <| by + simp [VLCtx.find?, VLCtx.next] + refine ⟨_, _, h, ?_, rfl⟩ + cases d <;> simp [VLocalDecl.depth, VLocalDecl.inst, VExpr.lift_instN_lo] + · intro H + have := Expr.liftLooseBVars_add ▸ H.weakBV henv (.skip (d.inst e₀' k) .refl) + cases d <;> simpa [← VExpr.lift_instN_lo, VExpr.liftN_zero, + VLocalDecl.inst, VLocalDecl.depth] using this + · obtain _|i := i; · omega + intro | .bvar h => ?_ + exact .bvar <| by + simp [VLCtx.find?, VLCtx.next] + refine ⟨_, _, h, ?_, rfl⟩ + cases d <;> simp [VLocalDecl.depth, VLocalDecl.inst, VExpr.lift_instN_lo] + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + have .fvar h := ih H + exact .fvar <| by + simp [VLCtx.find?, VLCtx.next] + refine ⟨_, _, h, ?_, rfl⟩ + cases d <;> simp [VLocalDecl.depth, VLocalDecl.inst, VExpr.lift_instN_lo] + +theorem TrProj.instN (henv : env.Ordered) + (h₀ : env.HasType U Γ₀ e₀ A₀) + (W : Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ) + (H : TrProj env U Γ₁ s i e e') : + TrProj env U Γ s i (e.inst e₀ k) (e'.inst e₀ k) := by + obtain ⟨view, levels, params, hname, hproj⟩ := H + exact ⟨view, levels, params.map (fun param => param.inst e₀ k), + hname, hproj.instN henv W h₀⟩ + +variable! (henv : Ordered env) (h₀ : TrExprS env Us Δ₀ e₀ e₀') + (t₀ : env.HasType Us.length Δ₀.toCtx e₀' A₀) in +theorem TrExprS.instN (W : VLCtx.InstN Δ₀ e₀' A₀ dk k Δ₁ Δ) (H : TrExprS env Us Δ₁ e e') : + TrExprS env Us Δ (Expr.instantiate1' e e₀ dk) (e'.inst e₀' k) := by + induction H generalizing Δ dk k with + | bvar h1 | fvar h1 => exact instN_var henv h₀ W h1 + | sort h1 => exact .sort h1 + | const h1 h2 h3 => exact .const h1 h2 h3 + | app h1 h2 _ _ ih1 ih2 => + exact .app (h1.instN henv W.toCtx t₀) (h2.instN henv W.toCtx t₀) (ih1 W) (ih2 W) + | lam h1 _ _ ih1 ih2 => + exact .lam (h1.instN henv W.toCtx t₀) (ih1 W) (ih2 (W.succ (d := .vlam _))) + | forallE h1 h2 _ _ ih1 ih2 => + exact .forallE (h1.instN henv W.toCtx t₀) (h2.instN henv W.toCtx.succ t₀) + (ih1 W) (ih2 (W.succ (d := .vlam _))) + | letE h1 _ _ _ ih1 ih2 ih3 => + exact .letE (h1.instN henv W.toCtx t₀) (ih1 W) (ih2 W) (ih3 (W.succ (d := .vlet ..))) + | lit h1 _ ih => + refine .lit h1 (Expr.instantiate1'_eq_self ?_ ▸ ih W :) + exact Closed.toConstructor.looseBVarRange_le + | mdata _ ih => exact .mdata (ih W) + | proj _ h2 ih => exact .proj (ih W) (h2.instN henv t₀ W.toCtx) + +theorem TrExprS.inst {Δ : VLCtx} (henv : Ordered env) + (t₀ : env.HasType Us.length Δ.toCtx e₀' A₀) + (H : TrExprS env Us ((none, .vlam A₀) :: Δ) e e') + (h₀ : TrExprS env Us Δ e₀ e₀') : + TrExprS env Us Δ (e.instantiate1' e₀) (e'.inst e₀') := + h₀.instN henv t₀ .zero H + +theorem TrExpr.inst (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length Δ) + (t₀ : env.HasType Us.length Δ.toCtx e₀' A₀) + (H : TrExpr env Us ((none, .vlam A₀) :: Δ) e e') + (h₀ : TrExpr env Us Δ e₀ e₀') : + TrExpr env Us Δ (e.instantiate1' e₀) (e'.inst e₀') := + have ⟨_, h0⟩ := t₀.isType henv hΔ + have ⟨_, s1, _, h1⟩ := H + have ⟨_, s2, h2⟩ := h₀ + have h2' := h2.symm.of_l henv hΔ t₀ + have hΔΔ := VLCtx.IsDefEq.cons (.refl henv hΔ) (ofv := none) nofun (.vlam h0) + let ⟨_, s1'⟩ := s1.defeqDFC henv hΔΔ + let ⟨_, h1'⟩ := s1.uniq henv hΔΔ s1' + ⟨_, .inst henv h2'.hasType.2 s1' s2, _, + .instDF henv hΔ (h1'.symm.trans_l henv hΔΔ.wf.toCtx h1) h2'.symm⟩ + +variable! (henv : Ordered env) (h₀ : TrExprS env Us Δ₀ e₀ e₀') in +theorem TrExprS.instN_let_var (W : VLCtx.InstLet Δ₀ e₀' A₀ dk k Δ₁ Δ) + (H : Δ₁.find? v = some (e', A)) : + TrExprS env Us Δ (Expr.instantiate1' (VLCtx.varToExpr v) e₀ dk) e' := by + induction W generalizing v e' A with + | zero => + obtain (_|i)|fv := v <;> simp [VLCtx.varToExpr, Expr.instantiate1', Expr.liftLooseBVars_zero] + · cases H; simp [VLocalDecl.value]; exact h₀ + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + simp [VLocalDecl.depth] + exact .bvar H + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + simp [VLocalDecl.depth] + exact .fvar H + | @succ _ k _ _ d _ ih => + obtain (_|i)|fv := v <;> simp [VLCtx.varToExpr, Expr.instantiate1'] + · cases H + cases d <;> exact .bvar <| by simp [VLocalDecl.value]; rfl + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + have := ih H; revert this + simp [VLCtx.varToExpr, Expr.instantiate1']; split <;> [skip; split] + · intro | .bvar h => ?_ + exact .bvar <| by + simp [VLCtx.find?, VLCtx.next] + refine ⟨_, _, h, ?_, rfl⟩ + cases d <;> simp [VLocalDecl.depth] + · intro H + have := Expr.liftLooseBVars_add ▸ H.weakBV henv (.skip d .refl) + cases d <;> simpa [VLocalDecl.depth] using this + · obtain _|i := i; · omega + intro | .bvar h => ?_ + exact .bvar <| by + simp [VLCtx.find?, VLCtx.next] + refine ⟨_, _, h, ?_, rfl⟩ + cases d <;> simp [VLocalDecl.depth] + · simp [VLCtx.find?, VLCtx.next] at H + obtain ⟨e, A, H, rfl, rfl⟩ := H + have .fvar h := ih H + exact .fvar <| by + simp [VLCtx.find?, VLCtx.next] + refine ⟨_, _, h, ?_, rfl⟩ + cases d <;> simp [VLocalDecl.depth] + +variable! (henv : Ordered env) (h₀ : TrExprS env Us Δ₀ e₀ e₀') in +theorem TrExprS.instN_let (W : VLCtx.InstLet Δ₀ e₀' A₀ dk k Δ₁ Δ) (H : TrExprS env Us Δ₁ e e') : + TrExprS env Us Δ (Expr.instantiate1' e e₀ dk) e' := by + induction H generalizing Δ dk k with + | bvar h1 | fvar h1 => exact instN_let_var henv h₀ W h1 + | sort h1 => exact .sort h1 + | const h1 h2 h3 => exact .const h1 h2 h3 + | app h1 h2 _ _ ih1 ih2 => + exact .app (W.toCtx ▸ h1) (W.toCtx ▸ h2) (ih1 W) (ih2 W) + | lam h1 _ _ ih1 ih2 => + exact .lam (W.toCtx ▸ h1) (ih1 W) (ih2 (W.succ (d := .vlam _))) + | forallE h1 h2 _ _ ih1 ih2 => + exact .forallE (W.toCtx ▸ h1) (W.toCtx ▸ h2) + (ih1 W) (ih2 (W.succ (d := .vlam _))) + | letE h1 _ _ _ ih1 ih2 ih3 => + exact .letE (W.toCtx ▸ h1) (ih1 W) (ih2 W) (ih3 (W.succ (d := .vlet ..))) + | lit h1 _ ih => + refine .lit h1 (Expr.instantiate1'_eq_self ?_ ▸ ih W :) + exact Closed.toConstructor.looseBVarRange_le + | mdata _ ih => exact .mdata (ih W) + | proj _ h2 ih => exact .proj (ih W) (W.toCtx ▸ h2) + +theorem TrExprS.inst_let {Δ : VLCtx} (henv : Ordered env) + (H : TrExprS env Us ((none, .vlet A₀ e₀') :: Δ) e e') + (h₀ : TrExprS env Us Δ e₀ e₀') : + TrExprS env Us Δ (e.instantiate1' e₀) e' := + h₀.instN_let henv .zero H + +theorem TrExpr.inst_let (henv : VEnv.WF env) (hΔ : VLCtx.WF env Us.length Δ) + (t₀ : env.HasType Us.length Δ.toCtx e₀' A₀) + (H : TrExpr env Us ((none, .vlet A₀ e₀') :: Δ) e e') + (h₀ : TrExpr env Us Δ e₀ e₀') : + TrExpr env Us Δ (e.instantiate1' e₀) e' := + have ⟨_, h0⟩ := t₀.isType henv hΔ + have ⟨_, s1, _, h1⟩ := H + have ⟨_, s2, h2⟩ := h₀ + have h2' := h2.symm.of_l henv hΔ t₀ + have hΔΔ := VLCtx.IsDefEq.cons (.refl henv hΔ) (ofv := none) nofun (.vlet h2' h0) + let ⟨_, s1'⟩ := s1.defeqDFC henv hΔΔ + let ⟨_, h1'⟩ := s1.uniq henv hΔΔ s1' + ⟨_, .inst_let henv s1' s2, _, h1'.symm.trans_l henv hΔ h1⟩ + +theorem ofLevel_mkLevelMax' + (h1 : VLevel.ofLevel Us u = some u') (h2 : VLevel.ofLevel Us v = some v') : + ∃ w, VLevel.ofLevel Us (mkLevelMax' u v) = some w ∧ w ≈ .max u' v' := by + let subsumes (u v : Level) : Bool := + if v.isExplicit && u.getOffset ≥ v.getOffset then true + else match u with + | Level.max u₁ u₂ => v == u₁ || v == u₂ + | _ => false + let mkLevelMaxCore (u v : Level) := + if u == v then u + else if u.isZero then v + else if v.isZero then u + else if subsumes u v then u + else if subsumes v u then v + else if u.getLevelOffset == v.getLevelOffset then + if u.getOffset ≥ v.getOffset then u else v + else + .max u v + change ∃ w, VLevel.ofLevel Us (mkLevelMaxCore u v) = some w ∧ w ≈ .max u' v' + have le {u v u' v'} (h : subsumes u v) + (hu : VLevel.ofLevel Us u = some u') + (hv : VLevel.ofLevel Us v = some v') : v'.LE u' := by + simp [subsumes] at h + obtain ⟨h1, h2⟩ | h := h + · clear subsumes mkLevelMaxCore + induction v generalizing u u' v' with simp [VLevel.ofLevel] at hv h2 ⊢ + | zero => subst v'; exact VLevel.zero_le + | succ _ ih => + obtain ⟨_, hv, rfl⟩ := hv + generalize eq : u.getOffset' = n at h2 + unfold Level.getOffset' at eq; split at eq <;> subst eq <;> [skip; cases h2] + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, rfl⟩ := hu + simp [Level.isExplicit] at h1 + exact VLevel.succ_le_succ (ih hu hv h1.2 (Nat.le_of_succ_le_succ h2)) + | _ => cases h1 + · split at h <;> [skip; cases h] + simp [VLevel.ofLevel] at hu; obtain ⟨_, hu1, _, hu2, rfl⟩ := hu + simp at h; obtain rfl | rfl := h + · cases hv.symm.trans hu1 + exact VLevel.le_max_left + · cases hv.symm.trans hu2 + exact VLevel.le_max_right + simp only [mkLevelMaxCore]; split + · simp_all; exact VLevel.max_self.symm + split + · let .zero := u; simp [VLevel.ofLevel] at h1; subst u' + exact ⟨_, h2, VLevel.zero_le.max_eq_right.symm⟩ + split + · let .zero := v; simp [VLevel.ofLevel] at h2; subst v' + exact ⟨_, h1, VLevel.zero_le.max_eq_left.symm⟩ + split + · exact ⟨_, h1, (le ‹_› h1 h2).max_eq_left.symm⟩ + split + · exact ⟨_, h2, (le ‹_› h2 h1).max_eq_right.symm⟩ + split + · rename_i h + simp at h ⊢ + let rec lem1 {v : Level} {u' v'} + (hu : VLevel.ofLevel Us v.getLevelOffset = some u') + (hv : VLevel.ofLevel Us v = some v') : u'.LE v' := by + unfold Level.getLevelOffset at hu; split at hu + · simp [VLevel.ofLevel] at hv; obtain ⟨_, hv, rfl⟩ := hv + exact VLevel.le_trans (lem1 hu hv) VLevel.le_succ + · cases hu.symm.trans hv; exact VLevel.le_refl _ + let rec lem2 {u v : Level} {u' v'} + (h1 : u.getLevelOffset = v.getLevelOffset) + (h2 : u.getOffset' ≤ v.getOffset') + (hu : VLevel.ofLevel Us u = some u') + (hv : VLevel.ofLevel Us v = some v') : u'.LE v' := by + revert h1 h2; unfold Level.getLevelOffset Level.getOffset' + split <;> simp <;> split <;> (try simp) + · simp [VLevel.ofLevel] at hu; obtain ⟨_, hu, rfl⟩ := hu + simp [VLevel.ofLevel] at hv; obtain ⟨_, hv, rfl⟩ := hv + exact (VLevel.succ_le_succ <| lem2 · · hu hv) + · rintro rfl; exact lem1 (v := .succ _) hu hv + · rintro rfl; cases hu.symm.trans hv; exact VLevel.le_refl _ + split <;> rename_i h3 + · exact ⟨_, h1, (lem2 h.symm h3 h2 h1).max_eq_left.symm⟩ + · exact ⟨_, h2, (lem2 h (Nat.le_of_not_le h3) h1 h2).max_eq_right.symm⟩ + simp [VLevel.ofLevel]; exact ⟨_, ⟨_, h1, _, h2, rfl⟩, rfl⟩ + +theorem ofLevel_isNeverZero (h : VLevel.ofLevel Us u = some u') (H : u.isNeverZero) : + u'.IsNeverZero := by + induction u generalizing u' with simp [Level.isNeverZero, VLevel.ofLevel] at H h <;> intro ls + | succ => + obtain ⟨_, h1, rfl⟩ := h + exact Nat.succ_ne_zero _ + | max _ _ ih1 ih2 => + obtain ⟨_, h1, _, h2, rfl⟩ := h + intro h + rw [VLevel.eval, ← Nat.le_zero, Nat.max_le] at h; simp at h + exact H.elim (ih1 h1 · _ h.1) (ih2 h2 · _ h.2) + | imax _ _ ih1 ih2 => + obtain ⟨_, h1, _, h2, rfl⟩ := h + simp [VLevel.eval, Lean.Nat.imax, ih2 h2 H ls] + +theorem ofLevel_isAlwaysZero (h : VLevel.ofLevel Us u = some u') (H : u.isAlwaysZero) : + u' ≈ .zero := by + induction u generalizing u' with + simp [Level.isAlwaysZero, VLevel.ofLevel] at H h <;> subst_vars <;> + refine VLevel.equiv_def.2 fun ls => ?_ + | zero => rfl + | max _ _ ih1 ih2 => + obtain ⟨_, h1, _, h2, rfl⟩ := h + simp [VLevel.eval, VLevel.equiv_def.1 (ih1 h1 H.1) ls, VLevel.equiv_def.1 (ih2 h2 H.2) ls] + | imax _ _ _ ih2 => + obtain ⟨_, _, _, h2, rfl⟩ := h + simp [VLevel.eval, Lean.Nat.imax, VLevel.equiv_def.1 (ih2 h2 H) ls] + +theorem ofLevel_mkLevelIMax' + (h1 : VLevel.ofLevel Us u = some u') (h2 : VLevel.ofLevel Us v = some v') : + ∃ w, VLevel.ofLevel Us (mkLevelIMax' u v) = some w ∧ w ≈ .imax u' v' := by + let mkLevelIMaxCore (u v : Level) := + if v.isNeverZero then mkLevelMax' u v + else if v.isZero then v + else if u.isZero then v + else if u == v then u + else .imax u v + change ∃ w, VLevel.ofLevel Us (mkLevelIMaxCore u v) = some w ∧ w ≈ .imax u' v' + simp only [mkLevelIMaxCore]; split + · have ⟨_, a1, a2⟩ := ofLevel_mkLevelMax' h1 h2 + exact ⟨_, a1, .trans a2 (ofLevel_isNeverZero h2 ‹_›).imax_eq_max.symm⟩ + split + · let .zero := v; simp [VLevel.ofLevel] at h2; subst v' + exact ⟨.zero, rfl, rfl⟩ + split + · let .zero := u; simp [VLevel.ofLevel] at h1; subst u' + exact ⟨_, h2, VLevel.zero_imax.symm⟩ + split + · simp_all; exact VLevel.imax_self.symm + simp [VLevel.ofLevel]; exact ⟨_, ⟨_, h1, _, h2, rfl⟩, rfl⟩ + +variable! {ls : List VLevel} (hls : ∀ l ∈ ls, l.WF U') in +theorem TrProj.instL (H : TrProj env U Γ s i e e') : + TrProj env U' (Γ.map (VExpr.instL ls)) s i + (e.instL ls) (e'.instL ls) := by + obtain ⟨view, levels, params, hname, hproj⟩ := H + exact ⟨view, levels.map (VLevel.inst ls), + params.map (VExpr.instL ls), hname, hproj.instL hls⟩ + +/-- The structural interface of Verify's projection translation. The bundle +keeps the seven laws available as one coherent capability while the named +theorems above remain the compatibility surface for existing callers. -/ +structure TrProj.StructuralLaws (env : VEnv) : Prop where + weakening : ∀ {U n Γ Γ' s i e e'}, + Ctx.Lift' n Γ Γ' → TrProj env U Γ s i e e' → + TrProj env U Γ' s i (e.lift' n) (e'.lift' n) + inverseWeakening : ∀ {U l Γ Γ' s i e e'}, + OnCtx Γ' (env.IsType U) → Ctx.Lift' l Γ Γ' → + TrProj env U Γ' s i (e.lift' l) e' → + ∃ result, TrProj env U Γ s i e result + contextDefEq : ∀ {U Γ₁ Γ₂ s i e₁ e₂ result}, + env.IsDefEqCtx U [] Γ₁ Γ₂ → env.IsDefEqU U Γ₁ e₁ e₂ → + TrProj env U Γ₁ s i e₁ result → + ∃ result', TrProj env U Γ₂ s i e₂ result' + wellFormed : ∀ {U Γ s i e result}, + TrProj env U Γ s i e result → VExpr.WF env U Γ e → + VExpr.WF env U Γ result + unique : ∀ {U Γ₁ Γ₂ s₁ s₂ i e₁ e₂ result₁ result₂}, + env.IsDefEqCtx U [] Γ₁ Γ₂ → + TrProj env U Γ₁ s₁ i e₁ result₁ → + TrProj env U Γ₂ s₂ i e₂ result₂ → + env.IsDefEqU U Γ₁ e₁ e₂ → + env.IsDefEqU U Γ₁ result₁ result₂ + termSubstitution : ∀ {U Γ₀ Γ₁ Γ s i e e' e₀ A₀ k}, + env.HasType U Γ₀ e₀ A₀ → Ctx.InstN Γ₀ e₀ A₀ k Γ₁ Γ → + TrProj env U Γ₁ s i e e' → + TrProj env U Γ s i (e.inst e₀ k) (e'.inst e₀ k) + universeInstantiation : ∀ {U U' Γ s i e e'} {ls : List VLevel}, + (∀ level ∈ ls, level.WF U') → U = ls.length → + TrProj env U Γ s i e e' → + TrProj env U' (Γ.map (VExpr.instL ls)) s i + (e.instL ls) (e'.instL ls) + +/-- Every well-formed environment supplies the complete projection structural +interface. -/ +theorem TrProj.structuralLaws (henv : VEnv.WF env) : + TrProj.StructuralLaws env where + weakening W H := H.weak' henv.ordered W + inverseWeakening hΓ' W H := H.weak'_inv henv hΓ' W + contextDefEq hΓ he H := H.defeqDFC henv hΓ he + wellFormed H he := H.wf he + unique hΓ H1 H2 he := H1.uniq henv hΓ H2 he + termSubstitution h₀ W H := H.instN henv.ordered h₀ W + universeInstantiation hls _ H := H.instL hls + +/-! +The guards below pin both the proved laws and the inherited Tier-R boundary. +In particular, they distinguish local proof closure from the remaining public +registered-head inversion dependency. +-/ + +#guard_named_axioms Ix.Theory.Named.TrProj.weak' [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TrProj.weak'_inv [propext, sorryAx, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TrProj.defeqDFC [ + propext, + sorryAx, + Classical.choice, + Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TrProj.wf [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TrProj.uniq [propext, sorryAx, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TrProj.instN [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TrProj.instL [propext, Quot.sound] + +#guard_named_axioms Ix.Theory.Named.TrProj.structuralLaws [ + propext, + sorryAx, + Classical.choice, + Quot.sound] + +section + +variable (henv : VEnv.WF env) {Us ps : List Name} {ls : List Level} {ls' : List VLevel} + (hΔ : VLCtx.WF env ls'.length Δ) + (Hls : ls.mapM (VLevel.ofLevel Us) = some ls') + (eq : ps.length = ls.length) + +include Hls eq + +section +variable (eqF : (fun x => ((List.idxOf? x ps).bind fun x => ls[x]?).getD (Level.param x)) = F) +include eqF + +attribute [-simp] Bool.forall_bool in +theorem substParams_wf (red) (H : VLevel.ofLevel ps u = some u') : + ∃ u₁, VLevel.ofLevel Us (u.substParams' F red) = some u₁ ∧ u₁ ≈ u'.inst ls' := by + induction u generalizing u' red with simp_all [VLevel.ofLevel, Level.substParams'] + | zero => subst u'; rfl + | succ _ ih => + obtain ⟨_, H, rfl⟩ := H + exact let ⟨_, h1, h2⟩ := ih _ H; ⟨_, ⟨_, h1, rfl⟩, VLevel.succ_congr h2⟩ + | max _ _ ih1 ih2 => + obtain ⟨_, H1, _, H2, rfl⟩ := H + generalize (_ && _) = red' + let ⟨_, a1, a2⟩ := ih1 (red := red') H1 + let ⟨_, b1, b2⟩ := ih2 (red := red') H2 + split + · have ⟨w, c1, c2⟩ := ofLevel_mkLevelMax' a1 b1 + exact ⟨_, c1, .trans c2 <| VLevel.max_congr a2 b2⟩ + · simp [VLevel.ofLevel] + exact ⟨_, ⟨_, a1, _, b1, rfl⟩, VLevel.max_congr a2 b2⟩ + | imax _ _ ih1 ih2 => + obtain ⟨_, H1, _, H2, rfl⟩ := H + generalize (_ && _) = red' + let ⟨_, a1, a2⟩ := ih1 (red := red') H1 + let ⟨_, b1, b2⟩ := ih2 (red := red') H2 + split + · have ⟨w, c1, c2⟩ := ofLevel_mkLevelIMax' a1 b1 + exact ⟨_, c1, .trans c2 <| VLevel.imax_congr a2 b2⟩ + · simp [VLevel.ofLevel] + exact ⟨_, ⟨_, a1, _, b1, rfl⟩, VLevel.imax_congr a2 b2⟩ + | param x => + obtain ⟨H, rfl⟩ := H; subst eqF; simp + have := List.idxOf_eq_getD_idxOf? x ps; unfold Option.getD at this; revert this + split <;> simp [*, Nat.ne_of_lt, VLevel.inst]; rintro rfl; clear ‹_› eq + generalize List.idxOf x ps = n at * + rw [List.mapM_eq_some] at Hls + induction Hls generalizing n with + | nil => cases H + | cons Hl _ ih => + obtain _|n := n <;> simp + · exact ⟨_, Hl, rfl⟩ + · exact ih _ (Nat.lt_of_succ_lt_succ H) + +theorem substParams_wf_list (red) {us us' : List _} (H : us.mapM (VLevel.ofLevel ps) = some us') : + ∃ us₁, (us.map (Level.substParams' F red)).mapM (VLevel.ofLevel Us) = some us₁ ∧ + List.Forall₂ (· ≈ ·) us₁ (us'.map (·.inst ls')) := by + induction us generalizing us' with simp_all + | cons u us ih => + obtain ⟨_, H1, _, H2, rfl⟩ := H + have ⟨_, h1, h2⟩ := ih H2 + have ⟨_, h3, h4⟩ := substParams_wf Hls eq eqF red H1 + refine ⟨_, ⟨_, h3, _, h1, rfl⟩, .cons h4 h2⟩ + +end + +include henv hΔ + +theorem TrExprS.instL (H : TrExprS env ps Δ e e') : + TrExpr env Us (Δ.instL ls') (e.instantiateLevelParams ps ls) (e'.instL ls') := by + simp [Expr.instantiateLevelParams_eq] + generalize (_ && _) = red, eqF : (fun x : Name => _) = F + have Hls' := VLevel.WF.of_mapM_ofLevel Hls + have eq' := eq.trans (List.mapM_eq_some.1 Hls).length_eq + induction H with + | bvar h1 => exact (bvar (VLCtx.find?_instL h1)).trExpr henv (hΔ.instL Hls') + | fvar h1 => exact (fvar (VLCtx.find?_instL h1)).trExpr henv (hΔ.instL Hls') + | sort h1 => + simp [Expr.instantiateLevelParamsCore'] + have ⟨_, a1, a2⟩ := substParams_wf Hls eq eqF red h1 + exact ⟨_, .sort a1, _, .sortDF (.of_ofLevel a1) (.inst Hls') a2⟩ + | const h1 h2 h3 => + have ⟨_, a1, a2⟩ := substParams_wf_list Hls eq eqF red h2 + refine ⟨_, .const h1 a1 (by simp [h3]), _, .constDF h1 (.of_mapM_ofLevel a1) ?_ ?_ a2⟩ + · simp; exact fun _ _ => .inst Hls' + · simp [← (List.mapM_eq_some.1 a1).length_eq, h3] + | app h1 h2 _ _ ih1 ih2 => + exact .app henv (hΔ.instL Hls') + (VLCtx.instL_toCtx _ ▸ h1.instL Hls') + (VLCtx.instL_toCtx _ ▸ h2.instL Hls') (ih1 hΔ) (ih2 hΔ) + | lam h1 h2 _ ih1 ih2 => + exact .lam henv (hΔ.instL Hls') + (VLCtx.instL_toCtx _ ▸ h1.instL Hls') (ih1 hΔ) (ih2 ⟨hΔ, nofun, eq' ▸ h1⟩) + | forallE h1 h2 _ _ ih1 ih2 => + exact .forallE henv (hΔ.instL Hls') + (VLCtx.instL_toCtx _ ▸ h1.instL Hls') + (VLCtx.instL_toCtx _ ▸ h2.instL Hls') (ih1 hΔ) (ih2 ⟨hΔ, nofun, eq' ▸ h1⟩) + | letE h1 _ _ _ ih1 ih2 ih3 => + exact .letE henv (hΔ.instL Hls') + (VLCtx.instL_toCtx _ ▸ h1.instL Hls') (ih1 hΔ) (ih2 hΔ) (ih3 ⟨hΔ, nofun, eq' ▸ h1⟩) + | lit h1 _ ih => + refine .lit h1 (Expr.instantiateLevelParamsCore_eq_self ?_ ▸ ih hΔ :) + exact Literal.toConstructor_hasLevelParam + | mdata _ ih => exact .mdata (ih hΔ) + | proj _ h2 ih => + exact .proj henv (hΔ.instL Hls') (ih hΔ) + (VLCtx.instL_toCtx _ ▸ h2.instL Hls') + +theorem TrExpr.instL (H : TrExpr env ps Δ e e') : + TrExpr env Us (Δ.instL ls') (e.instantiateLevelParams ps ls) (e'.instL ls') := + let ⟨_, s1, h1⟩ := H + have Hls' := .of_mapM_ofLevel Hls + (s1.instL henv hΔ Hls eq).defeq henv (hΔ.instL Hls') (VLCtx.instL_toCtx _ ▸ h1.instL Hls') + +end + +theorem TrExprS.abstract (W : VLCtx.Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) (H : TrExprS env Us Δ₁ e e') : + TrExprS env Us Δ (e.abstract1 v₀ dk) e' := by + induction H generalizing dk k Δ with + | bvar h1 => + exact .bvar <| (W.find? (by nofun)).trans <| by + simp; split <;> [skip; rw [if_neg (by omega), if_neg (by omega)]] <;> exact h1 + | @fvar _ _ _ fv h1 => + if h : fv = v₀ then + rw [h, W.find?_self] at h1; cases h1 + rw [Expr.abstract1, if_pos (by simp [h])] + exact .bvar <| (W.find? (by nofun)).trans (by simpa using W.find?_self) + else + have := W.find? (v := .inr fv) (by rintro ⟨⟩; trivial) + simp at this + rw [Expr.abstract1, if_neg] + · exact .fvar (this.trans h1) + · simp; rintro rfl; trivial + | sort h1 => exact .sort h1 + | const h1 h2 h3 => exact .const h1 h2 h3 + | app h1 h2 _ _ ih1 ih2 => exact .app (W.toCtx ▸ h1) (W.toCtx ▸ h2) (ih1 W) (ih2 W) + | lam h1 _ _ ih1 ih2 => exact .lam (W.toCtx ▸ h1) (ih1 W) (ih2 W.succ) + | forallE h1 h2 _ _ ih1 ih2 => + exact .forallE (W.toCtx ▸ h1) (W.toCtx ▸ h2) (ih1 W) (ih2 W.succ) + | letE h1 _ _ _ ih1 ih2 ih3 => + exact .letE (W.toCtx ▸ h1) (ih1 W) (ih2 W) (ih3 W.succ) + | lit h1 _ ih => + exact .lit h1 (FVarsIn.toConstructor.abstract_eq_self .toConstructor ▸ ih W) + | mdata _ ih => exact .mdata (ih W) + | proj _ h2 ih => exact .proj (ih W) (W.toCtx ▸ h2) + +theorem TrExpr.abstract (W : VLCtx.Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) (H : TrExpr env Us Δ₁ e e') : + TrExpr env Us Δ (e.abstract1 v₀ dk) e' := + let ⟨_, s, h⟩ := H; ⟨_, s.abstract W, W.toCtx ▸ h⟩ + +def TrExprS.IsUnique : Expr → Prop + | .bvar _ + | .fvar _ + | .sort _ + | .const .. + | .mvar .. + | .lit _ => True + | .app f a => IsUnique f ∧ IsUnique a + | .lam _ t b _ => IsUnique t ∧ IsUnique b + | .forallE _ t b _ => IsUnique t ∧ IsUnique b + | .letE _ _ v b _ => IsUnique v ∧ IsUnique b + | .mdata _ e => IsUnique e + | .proj .. => False + +theorem TrExprS.IsUnique.natLitToConstructor : ∀ {n : Nat}, IsUnique (.natLitToConstructor n) + | 0 => ⟨⟩ + | _+1 => ⟨⟨⟩, ⟨⟩⟩ + +theorem TrExprS.IsUnique.strLitToConstructor {s : String} : IsUnique (.strLitToConstructor s) := by + refine ⟨⟨⟩, ?_⟩ + induction s.toList with simp + | nil => exact ⟨⟨⟩, ⟨⟩⟩ + | cons _ _ ih => exact ⟨⟨⟨⟨⟩, ⟨⟩⟩, ⟨⟨⟩, ⟨⟩⟩⟩, ih⟩ + +theorem TrExprS.IsUnique.toConstructor : ∀ {l : Literal}, IsUnique l.toConstructor + | .natVal _ => .natLitToConstructor + | .strVal _ => .strLitToConstructor + +inductive TrExprS.IsUniqueDecl : VLocalDecl → VLocalDecl → Prop + | vlam : IsUniqueDecl (.vlam ty) (.vlam ty') + | vlet : IsUniqueDecl (.vlet ty val) (.vlet ty' val) + +inductive TrExprS.IsUniqueCtx : VLCtx → VLCtx → Prop + | base : IsUniqueCtx Δ Δ + | cons : IsUniqueCtx Δ₁ Δ₂ → IsUniqueDecl d₁ d₂ → IsUniqueCtx ((ofv, d₁) :: Δ₁) ((ofv, d₂) :: Δ₂) + +theorem TrExprS.IsUniqueCtx.find?_uniq (hΔ : IsUniqueCtx Δ₁ Δ₂) + (H1 : Δ₁.find? v = some (e₁, A₁)) (H2 : Δ₂.find? v = some (e₂, A₂)) : e₁ = e₂ := by + induction hΔ generalizing v e₁ e₂ A₁ A₂ with + | base => cases H1.symm.trans H2; rfl + | @cons _ _ _ _ ofv _ hd ih => + revert H1 H2; simp [VLCtx.find?]; split + · rintro ⟨⟩ ⟨⟩; cases hd <;> rfl + · simp; rintro _ _ h1 rfl rfl _ _ h2 rfl rfl + congr 1 + · cases hd <;> rfl + · exact ih h1 h2 + +theorem TrExprS.unique' (hΔ : IsUniqueCtx Δ₁ Δ₂) (H : IsUnique e) + (H1 : TrExprS env Us Δ₁ e e₁) (H2 : TrExprS env Us Δ₂ e e₂) : e₁ = e₂ := by + induction H1 generalizing Δ₂ e₂ with cases H2 + | bvar => exact hΔ.find?_uniq ‹_› ‹_› + | fvar => exact hΔ.find?_uniq ‹_› ‹_› + | sort h1 + | const _ h1 => cases h1.symm.trans ‹_›; rfl + | app _ _ _ _ ih1 ih2 => cases ih1 hΔ H.1 ‹_›; cases ih2 hΔ H.2 ‹_›; rfl + | lam _ _ _ ih1 ih2 + | forallE _ _ _ _ ih1 ih2 => cases ih1 hΔ H.1 ‹_›; cases ih2 (hΔ.cons .vlam) H.2 ‹_›; rfl + | letE _ _ _ _ _ ih1 ih2 => cases ih1 hΔ H.1 ‹_›; cases ih2 (hΔ.cons .vlet) H.2 ‹_›; rfl + | lit _ _ ih => exact ih hΔ .toConstructor ‹_› + | mdata _ ih => exact ih hΔ H ‹_› + | proj => cases H + +theorem TrExprS.unique (H : IsUnique e) + (H1 : TrExprS env Us Δ e e₁) (H2 : TrExprS env Us Δ e e₂) : e₁ = e₂ := H1.unique' .base H H2 + +/-- A successful lookup transfers along value-preserving context alignment: +the found value is identical and only the (discarded) type component may +differ. -/ +theorem TrExprS.IsUniqueCtx.find?_transfer (hΔ : IsUniqueCtx Δ₁ Δ₂) + (H : Δ₁.find? v = some (e, A)) : ∃ A₂, Δ₂.find? v = some (e, A₂) := by + induction hΔ generalizing v e A with + | base => exact ⟨A, H⟩ + | @cons Δ₁' Δ₂' d₁ d₂ ofv _ hd ih => + revert H; simp only [VLCtx.find?]; split + next heq => + simp only [Option.some.injEq, Prod.mk.injEq] + rintro ⟨rfl, rfl⟩ + cases hd <;> exact ⟨_, rfl, rfl⟩ + next v' heq => + rintro h + simp only [Bind.bind, Option.bind_eq_some_iff] at h + obtain ⟨⟨e₁, A₁⟩, h1, h2⟩ := h + simp only [Option.some.injEq, Prod.mk.injEq] at h2 + obtain ⟨rfl, rfl⟩ := h2 + obtain ⟨A₂, h₂⟩ := ih h1 + have hdep : d₁.depth = d₂.depth := by cases hd <;> rfl + refine ⟨VExpr.liftN d₂.depth A₂, ?_⟩ + simp only [Bind.bind, Option.bind_eq_some_iff] + exact ⟨(e₁, A₂), h₂, by rw [hdep]⟩ + +/-- Every strict translation of an unfolded natural-number literal is the +canonical numeral: the constructor spine pins the Theory value +syntactically. -/ +theorem TrExprS.natLitToConstructor_eq : + ∀ {n : Nat} {w}, TrExprS env Us Δ (Expr.natLitToConstructor n) w → + w = VExpr.natLit n + | 0, w, h => by + have h : TrExprS env Us Δ (.const ``Nat.zero []) w := h + cases h with + | const h1 h2 h3 => + obtain rfl : _ = ([] : List VLevel) := by simpa using h2.symm + rfl + | n+1, w, h => by + have h : TrExprS env Us Δ (.app (.const ``Nat.succ []) (.lit (.natVal n))) w := h + cases h with + | app h1 h2 hf ha => + cases hf with + | const hf1 hf2 hf3 => + obtain rfl : _ = ([] : List VLevel) := by simpa using hf2.symm + cases ha with + | lit ha1 ha2 => + cases natLitToConstructor_eq ha2 + rfl + +/-- Every strict translation of an unfolded character-list literal is the +canonical Theory list. -/ +theorem TrExprS.strLitToConstructor_chars_eq : + ∀ {cs : List Char} {w}, + TrExprS env Us Δ + (cs.foldr (init := .app (.const ``List.nil [.zero]) (.const ``Char [])) + fun c e => + .app (.app (.app (.const ``List.cons [.zero]) (.const ``Char [])) + (.app (.const ``Char.ofNat []) (.lit (.natVal c.toNat)))) e) w → + w = VExpr.listCharLit cs + | [], w, h => by + cases h with + | app h1 h2 hf ha => + cases hf with + | const hf1 hf2 hf3 => + simp [VLevel.ofLevel] at hf2 + obtain rfl := hf2 + cases ha with + | const ha1 ha2 ha3 => + obtain rfl : _ = ([] : List VLevel) := by simpa using ha2.symm + rfl + | c :: cs, w, h => by + cases h with + | app h1 h2 hf ha => + cases strLitToConstructor_chars_eq ha + cases hf with + | app hg1 hg2 hgf hga => + cases hgf with + | app hh1 hh2 hhf hha => + cases hhf with + | const hi1 hi2 hi3 => + simp [VLevel.ofLevel] at hi2 + obtain rfl := hi2 + cases hha with + | const hj1 hj2 hj3 => + obtain rfl : _ = ([] : List VLevel) := by simpa using hj2.symm + cases hga with + | app hk1 hk2 hkf hka => + cases hkf with + | const hl1 hl2 hl3 => + obtain rfl : _ = ([] : List VLevel) := by simpa using hl2.symm + cases hka with + | lit hm1 hm2 => + cases natLitToConstructor_eq hm2 + rfl + +/-- Every strict translation of a literal's constructor unfolding is the +canonical `VExpr.trLiteral` value. -/ +theorem TrExprS.toConstructor_eq {l : Literal} {w} + (h : TrExprS env Us Δ l.toConstructor w) : w = VExpr.trLiteral l := by + match l with + | .natVal n => exact natLitToConstructor_eq h + | .strVal s => + have h : TrExprS env Us Δ (.app (.const ``String.ofList []) + (s.toList.foldr (init := .app (.const ``List.nil [.zero]) (.const ``Char [])) + fun c e => + .app (.app (.app (.const ``List.cons [.zero]) (.const ``Char [])) + (.app (.const ``Char.ofNat []) (.lit (.natVal c.toNat)))) e)) w := h + cases h with + | app h1 h2 hf ha => + cases strLitToConstructor_chars_eq ha + cases hf with + | const hf1 hf2 hf3 => + obtain rfl : _ = ([] : List VLevel) := by simpa using hf2.symm + rfl + +/-- The Verify traversal of `Literal.toConstructor` and the direct Theory +encoding form one ready, well-formed literal value. -/ +theorem TrExprS.toConstructor_ready {l : Literal} {w} + (hready : env.PreludeReady) (hcontains : env.ContainsLits l) + (h : TrExprS env Us Δ l.toConstructor w) : + w = VExpr.trLiteral l ∧ VExpr.WF env U [] w := by + have heq := h.toConstructor_eq + refine ⟨heq, ?_⟩ + rw [heq] + exact hready.trLiteral_wf l hcontains + +/-- The deterministic translator agrees with every strict-translation +derivation over any value-preserving context alignment: on the `IsUnique` +fragment, `trExprS?` computes exactly the derivation's Theory value. This +is the replay engine for choice-free semantic packaging — a `Nonempty` +translation witness plus this agreement pins the computed value. -/ +theorem TrExprS.trExprS?_eq' (hΔ : IsUniqueCtx Δ₁ Δ₂) + (H : TrExprS env Us Δ₁ e e') (hu : IsUnique e) : + trExprS? Us Δ₂ e = some e' := by + induction H generalizing Δ₂ with + | bvar h1 => + obtain ⟨A₂, h2⟩ := hΔ.find?_transfer h1 + simp [trExprS?, h2] + | fvar h1 => + obtain ⟨A₂, h2⟩ := hΔ.find?_transfer h1 + simp [trExprS?, h2] + | sort h1 => simp [trExprS?, h1] + | const h1 h2 h3 => simp [trExprS?, h2] + | app h1 h2 _ _ ih1 ih2 => + simp [trExprS?, ih1 hΔ hu.1, ih2 hΔ hu.2] + | lam h1 _ _ ih1 ih2 => + simp [trExprS?, ih1 hΔ hu.1, ih2 (hΔ.cons .vlam) hu.2] + | forallE h1 h2 _ _ ih1 ih2 => + simp [trExprS?, ih1 hΔ hu.1, ih2 (hΔ.cons .vlam) hu.2] + | letE h1 _ _ _ ih1 ih2 ih3 => + simp [trExprS?, ih2 hΔ hu.1, ih3 (hΔ.cons .vlet) hu.2] + | lit h1 h2 ih => + cases h2.toConstructor_eq + simp [trExprS?] + | mdata _ ih => simpa [trExprS?] using ih hΔ hu + | proj h1 h2 => cases hu + +/-- Deterministic-translator agreement in a fixed context. -/ +theorem TrExprS.trExprS?_eq (H : TrExprS env Us Δ e e') (hu : IsUnique e) : + trExprS? Us Δ e = some e' := + H.trExprS?_eq' .base hu + +/-- Executable totality on the unique fragment: any translation witness +guarantees the deterministic translator succeeds. -/ +theorem TrExprS.trExprS?_isSome (hex : ∃ e', TrExprS env Us Δ e e') + (hu : IsUnique e) : (trExprS? Us Δ e).isSome := by + obtain ⟨e', H⟩ := hex + simp [H.trExprS?_eq hu] + +/-- Replay transfer: an existential translation witness holds of the computed +translation itself. Choice-free packagers pin their Theory data with this: +compute by `trExprS?`, then transfer the `Nonempty`-level witness onto the +computed value. -/ +theorem TrExprS.of_trExprS?_eq (hex : ∃ e', TrExprS env Us Δ e e') + (hu : IsUnique e) (h : trExprS? Us Δ e = some v) : + TrExprS env Us Δ e v := by + obtain ⟨e', H⟩ := hex + cases Option.some.inj ((H.trExprS?_eq hu).symm.trans h) + exact H + +theorem TrExprS.boolFalse (henv : env.HasPrimitives) (H : env.contains ``Bool) : + TrExprS env Us Δ (toExpr false) .boolFalse ∧ + env.HasType Us.length Δ.toCtx .boolFalse .bool := by + let ⟨⟨_, H⟩, _⟩ := henv.bool H + cases henv.boolFalse H + exact ⟨.const H rfl rfl, .const H nofun rfl⟩ + +theorem TrExprS.boolTrue (henv : env.HasPrimitives) (H : env.contains ``Bool) : + TrExprS env Us Δ (toExpr true) .boolTrue ∧ + env.HasType Us.length Δ.toCtx .boolTrue .bool := by + let ⟨_, _, H⟩ := henv.bool H + cases henv.boolTrue H + exact ⟨.const H rfl rfl, .const H nofun rfl⟩ + +theorem TrExprS.boolLit (henv : env.HasPrimitives) (H : env.contains ``Bool) (b : Bool) : + TrExprS env Us Δ (toExpr b) (.boolLit b) ∧ + env.HasType Us.length Δ.toCtx (.boolLit b) .bool := by + match b with + | false => exact TrExprS.boolFalse henv H + | true => exact TrExprS.boolTrue henv H + +theorem FVarsIn.boolLit {b : Bool} : FVarsIn P (toExpr b) := by cases b <;> exact nofun + +theorem TrExprS.lit_has_type (H : TrExprS env Us Δ (.lit l) e') : env.ContainsLits l := + let .lit H _ := H; H + +theorem TrExprS.nat_of_natZero (wf : env.Ordered) (henv : env.HasPrimitives) + (H : TrExprS env Us Δ .natZero e') : env.contains ``Nat := by + let .const H .. := H + have ⟨_, H⟩ := henv.natZero H ▸ wf.constWF H + have ⟨_, H, _⟩ := H.const_inv wf (by trivial) + exact ⟨_, H⟩ + +theorem TrExprS.natZero (henv : env.HasPrimitives) (H : env.contains ``Nat) : + TrExprS env Us Δ .natZero .natZero ∧ env.HasType Us.length Δ.toCtx .natZero .nat := by + let ⟨⟨_, H⟩, _⟩ := henv.nat H + cases henv.natZero H + exact ⟨.const H rfl rfl, .const H nofun rfl⟩ + +theorem TrExprS.natSucc (henv : env.HasPrimitives) (H : env.contains ``Nat) : + TrExprS env Us Δ .natSucc .natSucc ∧ + env.HasType Us.length Δ.toCtx .natSucc (.forallE .nat .nat) := by + let ⟨_, _, H⟩ := henv.nat H + cases henv.natSucc H + exact ⟨.const H rfl rfl, .const H nofun rfl⟩ + +theorem TrExprS.natLit (henv : env.HasPrimitives) (H : env.contains ``Nat) (n) : + TrExprS env Us Δ (.lit (.natVal n)) (.natLit n) ∧ + env.HasType Us.length Δ.toCtx (.natLit n) .nat := by + induction n with + | zero => exact let ⟨h1, h2⟩ := natZero henv H; ⟨.lit H h1, h2⟩ + | succ n ih => exact let ⟨h1, h2⟩ := natSucc henv H; ⟨.lit H (.app h2 ih.2 h1 ih.1), .app h2 ih.2⟩ + +theorem TrExprS.stringOfList (henv : env.HasPrimitives) (H : env.contains ``String.ofList) : + TrExprS env Us Δ (.const ``String.ofList []) .stringOfList ∧ + env.HasType Us.length Δ.toCtx .stringOfList (.forallE .listChar .string) := by + let ⟨_, H⟩ := H + cases (henv.stringOfList H).1 + exact ⟨.const H rfl rfl, .const H nofun rfl⟩ + +theorem TrExprS.charOfNat (henv : env.HasPrimitives) (H : env.contains ``Char.ofNat) : + TrExprS env Us Δ (.const ``Char.ofNat []) .charOfNat ∧ + env.HasType Us.length Δ.toCtx .charOfNat (.forallE .nat .char) := by + let ⟨_, H⟩ := H + cases henv.charOfNat H + exact ⟨.const H rfl rfl, .const H nofun rfl⟩ + +theorem TrExprS.listChar (wf : env.Ordered) (henv : env.HasPrimitives) + (H : env.contains ``String.ofList) : + TrExprS env Us Δ (.app (.const ``List [.zero]) (.const ``Char [])) .listChar ∧ + env.IsType Us.length Δ.toCtx .listChar := by + let ⟨_, H⟩ := H + let ⟨_, H, _⟩ := henv.stringOfList H + let ⟨_, H⟩ := H.isType wf (by trivial) + refine ⟨?_, _, (H.instL (ls := []) nofun).weak0 wf⟩ + let ⟨_, _, A, B⟩ := H.app_inv wf trivial + let ⟨_, A1, _, A3⟩ := A.const_inv wf trivial + let ⟨_, B1, _, B3⟩ := B.const_inv wf trivial + exact .app ((A.instL (ls := []) nofun).weak0 wf) ((B.instL (ls := []) nofun).weak0 wf) + (.const A1 rfl A3) (.const B1 rfl B3) + +theorem TrExprS.listCharNil (wf : env.Ordered) (henv : env.HasPrimitives) + (H : env.contains ``String.ofList) : + TrExprS env Us Δ (.app (.const ``List.nil [.zero]) (.const ``Char [])) .listCharNil ∧ + env.HasType Us.length Δ.toCtx .listCharNil .listChar := by + let ⟨_, H⟩ := H + let ⟨_, H, _⟩ := henv.stringOfList H + refine ⟨?_, (H.instL (ls := []) nofun).weak0 wf⟩ + let ⟨_, _, A, B⟩ := H.app_inv wf trivial + let ⟨_, A1, _, A3⟩ := A.const_inv wf trivial + let ⟨_, B1, _, B3⟩ := B.const_inv wf trivial + exact .app ((A.instL (ls := []) nofun).weak0 wf) ((B.instL (ls := []) nofun).weak0 wf) + (.const A1 rfl A3) (.const B1 rfl B3) + +theorem TrExprS.listCharCons (wf : env.Ordered) (henv : env.HasPrimitives) + (H : env.contains ``String.ofList) : + TrExprS env Us Δ (.app (.const ``List.cons [.zero]) (.const ``Char [])) .listCharCons ∧ + env.HasType Us.length Δ.toCtx .listCharCons + (.forallE .char <| .forallE .listChar .listChar) := by + let ⟨_, H⟩ := H + let ⟨_, _, H⟩ := henv.stringOfList H + refine ⟨?_, (H.instL (ls := []) nofun).weak0 wf⟩ + let ⟨_, _, A, B⟩ := H.app_inv wf trivial + let ⟨_, A1, _, A3⟩ := A.const_inv wf trivial + let ⟨_, B1, _, B3⟩ := B.const_inv wf trivial + exact .app ((A.instL (ls := []) nofun).weak0 wf) ((B.instL (ls := []) nofun).weak0 wf) + (.const A1 rfl A3) (.const B1 rfl B3) + +theorem TrExprS.listCharLit (wf : env.Ordered) (henv : env.HasPrimitives) + (H : env.ContainsLits (.strVal l)) (s : List Char) : + TrExprS env Us Δ (s.foldr + (init := .app (.const ``List.nil [.zero]) (.const ``Char [])) + (fun c e => .app (.app + (.app (.const ``List.cons [.zero]) (.const ``Char [])) + (.app (.const ``Char.ofNat []) (.lit (.natVal c.toNat)))) e)) (.listCharLit s) ∧ + env.HasType Us.length Δ.toCtx (.listCharLit s) .listChar := by + induction s with + | nil => exact TrExprS.listCharNil wf henv H.2 + | cons x _ ih => + have a := TrExprS.listCharCons wf henv H.2 (Us := Us) (Δ := Δ) + have b := TrExprS.charOfNat henv H.1 (Us := Us) (Δ := Δ) + have c := TrExprS.natLit henv (henv.nat_of_charOfNat wf H.1) (Us := Us) (Δ := Δ) (n := x.toNat) + have d1 := b.1.app b.2 c.2 c.1; have d2 := b.2.app c.2 + have e1 := a.1.app a.2 d2 d1; have e2 := a.2.app d2 + exact ⟨e1.app e2 ih.2 ih.1, e2.app ih.2⟩ + +theorem TrExprS.trLiteral (wf : env.Ordered) (henv : env.HasPrimitives) + (l) (H : env.ContainsLits l) : + TrExprS env Us Δ (.lit l) (.trLiteral l) ∧ + env.HasType Us.length Δ.toCtx (.trLiteral l) (.const l.typeName []) := by + match l with + | .natVal n => exact TrExprS.natLit henv H _ + | .strVal s => + have a := TrExprS.stringOfList henv H.2 (Us := Us) (Δ := Δ) + have b := TrExprS.listCharLit wf henv H (Us := Us) (Δ := Δ) s.toList + exact ⟨.lit H (.app a.2 b.2 a.1 (String.foldr_eq .. ▸ b.1)), a.2.app b.2⟩ + +def VLCtx.Closed : VLCtx → Prop + | [] => True + | (none, _) :: _ => False + | (some _, d) :: (Δ : VLCtx) => Δ.Closed ∧ d.ClosedN Δ.bvars + +def IsFVarUpSet (P : FVarId → Prop) : VLCtx → Prop + | [] => True + | (none, _) :: Δ => IsFVarUpSet P Δ + | (some (fv, deps), _) :: (Δ : VLCtx) => + IsFVarUpSet P Δ ∧ + (P fv → ∀ fv' ∈ deps, P fv') + +theorem IsFVarUpSet.congr : ∀ {Δ}, VLCtx.FVWF Δ → + (H : ∀ fv ∈ VLCtx.fvars Δ, P fv ↔ Q fv) → IsFVarUpSet P Δ ↔ IsFVarUpSet Q Δ + | [], _, _ => .rfl + | (none, _) :: Δ, ⟨h1, _⟩, H => congr (Δ := Δ) h1 H + | (some (fv, deps), d) :: (Δ : VLCtx), ⟨h1, h2⟩, H => by + refine and_congr (congr h1 fun fv h => H _ (.tail _ h)) (imp_congr (H _ (.head _)) ?_) + refine forall_congr' fun fv => imp_congr_right fun h => ?_ + exact H _ (by simp [(h2 _ _ rfl).2 h]) + +theorem IsFVarUpSet.and_fvars (H : VLCtx.FVWF Δ) : + IsFVarUpSet P Δ ↔ IsFVarUpSet (fun fv => P fv ∧ fv ∈ Δ.fvars) Δ := + IsFVarUpSet.congr H fun _ h => (and_iff_left h).symm + +theorem IsFVarUpSet.trivial : ∀ {Δ}, IsFVarUpSet (fun _ => True) Δ + | [] => ⟨⟩ + | (none, _) :: Δ => trivial (Δ := Δ) + | (some _, _) :: _ => ⟨trivial, fun _ _ _ => ⟨⟩⟩ + +theorem IsFVarUpSet.fvars (H : VLCtx.FVWF Δ) : IsFVarUpSet (· ∈ Δ.fvars) Δ := + (IsFVarUpSet.congr H fun _ => iff_true_intro).2 trivial + +def AllAbove (Δ : VLCtx) (P : FVarId → Prop) (fv : FVarId) : Prop := fv ∈ Δ.fvars → P fv + +theorem AllAbove.wf (H : Δ.FVWF) : IsFVarUpSet (AllAbove Δ P) Δ ↔ IsFVarUpSet P Δ := + IsFVarUpSet.congr H fun _ h => by simp [h, AllAbove] + +def FVarsBelow (Δ e e') := ∀ P, IsFVarUpSet P Δ → FVarsIn P e → FVarsIn P e' + +theorem FVarsBelow.rfl : FVarsBelow Δ e e := fun _ _ => id + +theorem FVarsBelow.trans (H1 : FVarsBelow Δ e₁ e₂) (H2 : FVarsBelow Δ e₂ e₃) : + FVarsBelow Δ e₁ e₃ := fun _ h => H2 _ h ∘ H1 _ h + +def TrTyping (env : VEnv) (Us : List Name) (Δ : VLCtx) (e A : Expr) (e' A' : VExpr) : Prop := + FVarsBelow Δ e A ∧ TrExprS env Us Δ e e' ∧ TrExprS env Us Δ A A' ∧ + env.HasType Us.length Δ.toCtx e' A' + +theorem FVarsIn.mkAppRevList : + FVarsIn P (e.mkAppRevList es) ↔ FVarsIn P e ∧ ∀ a ∈ es, FVarsIn P a := by + induction es <;> simp [FVarsIn, and_comm, and_left_comm, *] + +theorem FVarsIn.mkAppList : + FVarsIn P (e.mkAppList es) ↔ FVarsIn P e ∧ ∀ a ∈ es, FVarsIn P a := by + simp [← Expr.mkAppRevList_reverse, FVarsIn.mkAppRevList] + +theorem FVarsBelow.mkAppList (H : FVarsBelow Δ e₁ e₂) : + FVarsBelow Δ (e₁.mkAppList es) (e₂.mkAppList es) := by + simp [FVarsBelow, FVarsIn.mkAppList] at H ⊢; grind + +theorem FVarsBelow.mkAppRevList (H : FVarsBelow Δ e₁ e₂) : + FVarsBelow Δ (e₁.mkAppRevList es) (e₂.mkAppRevList es) := by + simpa [← Expr.mkAppList_reverse] using H.mkAppList + +inductive LambdaBodyN : Nat → Expr → Expr → Prop + | zero : LambdaBodyN 0 e e + | succ : LambdaBodyN n body e → LambdaBodyN (n+1) (.lam i ty body bi) e + +theorem LambdaBodyN.closed (H : LambdaBodyN n e1 e2) : e1.Closed k → e2.Closed (k + n) := by + induction H generalizing k with + | zero => exact id + | succ _ ih => exact fun h => (Nat.add_right_comm .. ▸ ih h.2 :) + +theorem LambdaBodyN.add (H1 : LambdaBodyN m e1 e2) (H2 : LambdaBodyN n e2 e3) : + LambdaBodyN (n + m) e1 e3 := by + induction H1 with + | zero => exact H2 + | succ _ ih => exact .succ (ih H2) + +theorem LambdaBodyN.instantiateList (H1 : LambdaBodyN n e1 e2) : + LambdaBodyN n (e1.instantiateList es k) (e2.instantiateList es (k+n)) := by + induction H1 generalizing k with + | zero => exact .zero + | succ _ ih => + rw [Expr.instantiateList_lam] + refine .succ ?_ + conv => arg 3; rw [← Nat.add_assoc, Nat.add_right_comm] + exact ih + +theorem LambdaBodyN.instantiateRevList (H1 : LambdaBodyN n e1 e2) : + LambdaBodyN n (e1.instantiateRevList es k) (e2.instantiateRevList es (k+n)) := by + simp only [← Expr.instantiateList_reverse]; exact H1.instantiateList + +inductive BetaReduce : Expr → Expr → Prop + | refl : BetaReduce e e + | trans : BetaReduce e₁ e₂ → BetaReduce e₂ e₃ → BetaReduce e₁ e₃ + | app : BetaReduce f f' → BetaReduce (.app f a) (.app f' a) + | beta : e.looseBVarRange' = 0 → BetaReduce (.app (.lam i ty body bi) e) (body.instantiate1' e) + +theorem BetaReduce.mkAppRevList (H : BetaReduce f f') : + BetaReduce (f.mkAppRevList es) (f'.mkAppRevList es) := by + induction es with + | nil => exact H + | cons _ _ ih => exact .app ih + +theorem BetaReduce.mkAppList (H : BetaReduce f f') : + BetaReduce (f.mkAppList es) (f'.mkAppList es) := by + induction es generalizing f f' with + | nil => exact H + | cons _ _ ih => exact ih (.app H) + +theorem BetaReduce.instantiateList (H : BetaReduce f f') : + BetaReduce (f.instantiateList es) (f'.instantiateList es) := by + induction H with + | refl => exact .refl + | trans _ _ ih1 ih2 => exact ih1.trans ih2 + | app _ ih => simp only [Expr.instantiateList_app]; exact .app ih + | beta h => + simp only [Expr.instantiateList_app, Expr.instantiateList_lam] + rw [← Expr.instantiateList_instantiate1_comm h] + refine' cast _ (BetaReduce.beta _); congr 2 + · rw [Expr.instantiateList_eq_self h] + · rwa [Expr.instantiateList_eq_self h] + +theorem BetaReduce.instantiateRevList (H : BetaReduce f f') : + BetaReduce (f.instantiateRevList es) (f'.instantiateRevList es) := by + simp only [← Expr.instantiateList_reverse]; exact H.instantiateList + +theorem FVarsBelow.betaReduce (H : BetaReduce e e') : FVarsBelow Δ e e' := by + intro P hP he + induction H with + | refl => exact he + | trans _ _ ih1 ih2 => exact ih2 (ih1 he) + | app _ ih => exact ⟨ih he.1, he.2⟩ + | beta => exact he.1.2.instantiate1 he.2 + +theorem BetaReduce.inst_reduce {l₁ : List Expr} {fn e₀ : Expr} + (h : ∀ x ∈ l₁, x.Closed) (l₂) + (h1 : LambdaBodyN l₁.length e₀ fn) + (hr : fn.instantiateList (l₁.reverse ++ l₂) = r) : + BetaReduce ((e₀.instantiateList l₂).mkAppList l₁) r := by + subst r + induction l₁ generalizing e₀ fn l₂ with + | nil => let .zero := h1; exact .refl + | cons a l ih => + let .succ (body := body) h1 := h1 + rw [Expr.instantiateList_lam]; simp at h ⊢ + have h' := h.1.looseBVarRange_zero + refine .trans (.mkAppList (.beta h')) ?_ + exact Expr.instantiateList_instantiate1_comm h' ▸ ih h.2 (a::l₂) h1 + +theorem BetaReduce.cheapBetaReduce (hc : e.Closed) : BetaReduce e e.cheapBetaReduce := by + simp [Expr.cheapBetaReduce] + split; · exact .refl + split; · exact .refl + let rec loop {e' i fn args} (H : LambdaBodyN i e' fn) (hi : i ≤ args.size) : + ∃ n fn', LambdaBodyN n e' fn' ∧ n ≤ args.size ∧ + Expr.cheapBetaReduce.loop e args i fn = Expr.cheapBetaReduce.cont e args n fn' := by + unfold Expr.cheapBetaReduce.loop; split + · split + · exact loop (by simpa [Nat.add_comm] using H.add (.succ .zero)) ‹_› + · exact ⟨_, _, H, Nat.le_of_lt ‹_›, rfl⟩ + · exact ⟨_, _, H, hi, rfl⟩ + refine let ⟨i, fn, h1, h2, eq⟩ := loop .zero (Nat.zero_le _); eq ▸ ?_; clear eq + simp [Expr.getAppArgs_eq] at h2 ⊢ + obtain ⟨l₁, l₂, rfl, eq⟩ : ∃ l₁ l₂, l₁.length = i ∧ e.getAppArgsList = l₁ ++ l₂ := + ⟨_, _, List.length_take_of_le (by simp [h2]), (List.take_append_drop ..).symm⟩ + have eqr := congrArg List.reverse eq; simp at eqr + have hl₁ : ∀ x ∈ l₁, x.Closed := by + have := eqr ▸ hc.getAppArgsList; simp [or_imp, forall_and] at this + exact this.1 + unfold Expr.cheapBetaReduce.cont; split <;> rename_i h3 + · simp [Expr.hasLooseBVars] at h3 + rw [Expr.mkAppRange_eq (l₂ := l₂) (l₃ := []) (by simp [eq]) rfl (by simp [← eq])] + rw [← e.mkAppList_getAppArgsList, eqr]; simp + refine .mkAppList <| .inst_reduce hl₁ [] h1 (Expr.instantiateList_eq_self h3) + split <;> [rename_i n; exact .refl] + have hc := h1.closed hc.getAppFn + simp [Closed] at hc; rw [if_pos hc] + rw [Expr.mkAppRange_eq (l₂ := l₂) (l₃ := []) (by simp [eq]) rfl (by simp [← eq])] + conv => lhs; rw [← e.mkAppList_getAppArgsList] + simp [eqr] + refine .mkAppList <| .inst_reduce hl₁ [] h1 ?_ + rw [List.getElem?_append_left (by omega), Nat.sub_right_comm, ← List.getElem?_reverse hc] + suffices ∀ l₁, (∀ x ∈ l₁, x.Closed) → ∀ n < l₁.length, + (Expr.bvar n).instantiateList l₁ = l₁[n]?.getD default by + simpa [Expr.liftLooseBVars_zero] using this l₁.reverse (by simpa using hl₁) n (by simp [hc]) + intro l₁ hl₁ n lt + induction l₁ generalizing n with + | nil => cases lt + | cons a l ih => + simp at hl₁ + obtain _ | n := n <;> simp [Expr.instantiate1'] + · exact Expr.instantiateList_eq_self hl₁.1.looseBVarRange_zero + · exact ih hl₁.2 _ (Nat.lt_of_succ_lt_succ lt) + +theorem TrExpr.beta (H : TrExpr env Us Δ e e') + (henv : VEnv.WF env) (hΓ : VLCtx.WF env Us.length Δ) + (H : BetaReduce e e₂) : TrExpr env Us Δ e₂ e' := by + induction H generalizing e' with + | refl => exact H + | trans _ _ ih1 ih2 => exact ih2 (ih1 H) + | app _ ih => + let ⟨_, .app hf ha tf ta, _, df⟩ := H + have ⟨_, _, hf', ha'⟩ := df.hasType.1.app_inv henv hΓ + exact ((ih ⟨_, tf, _, hf'⟩).app henv hΓ hf' ha' (ta.trExpr henv hΓ)).defeq henv hΓ ⟨_, df⟩ + | beta => + let ⟨_, .app hf ha tf ta, _, df⟩ := H + let .lam hA tA tb := tf + have ⟨⟨_, hA⟩, _, hb⟩ := hf.lam_inv henv hΓ + have ht := hf.uniqU henv hΓ (hA.lam hb) + have ⟨⟨_, Ae⟩, _, be⟩ := ht.forallE_inv henv hΓ + have hΓΓ := VLCtx.IsDefEq.cons (.refl henv hΓ) (ofv := none) nofun (.vlam Ae.symm) + have ⟨_, tb'⟩ := tb.defeqDFC henv hΓΓ + have beta := hb.beta (Ae.defeq ha) + have be' := (tb.uniq henv hΓΓ tb').of_l henv hΓΓ.wf hb + have hi := be'.instDF henv hΓ (.defeq Ae ha) + exact ⟨_, .inst henv ha tb' ta, _, beta.trans_l henv hΓ hi |>.symm.trans_l henv hΓ df⟩ + +theorem FVarsBelow.cheapBetaReduce (he : e.Closed) : FVarsBelow Δ e e.cheapBetaReduce := + .betaReduce (.cheapBetaReduce he) + +theorem TrExpr.cheapBetaReduce (H : TrExpr env Us Δ e e') + (henv : VEnv.WF env) (hΓ : VLCtx.WF env Us.length Δ) + (noBV : Δ.NoBV) : TrExpr env Us Δ e.cheapBetaReduce e' := + H.beta henv hΓ <| .cheapBetaReduce <| noBV ▸ H.closed.mono (by simp) + +theorem TrExprS.uninstantiateN + (W : VLCtx.Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) + (H : TrExprS env Us Δ₁ (Expr.instantiate1' e (.fvar v₀) dk) e') + (sc : FVarsIn (· ≠ v₀) e) : + TrExprS env Us Δ e e' := by + have := H.abstract W + rwa [sc.abstract_instantiate1] at this + +theorem TrExpr.uninstantiateN + (W : VLCtx.Abstract Δ₀ v₀ d₀ dk k Δ₁ Δ) + (H : TrExpr env Us Δ₁ (Expr.instantiate1' e (.fvar v₀) dk) e') + (sc : FVarsIn (· ≠ v₀) e) : + TrExpr env Us Δ e e' := + let ⟨_, s, h⟩ := H; ⟨_, s.uninstantiateN W sc, W.toCtx ▸ h⟩ + +theorem TrExprS.uninstantiate + (H : TrExprS env Us ((some (v, deps), d) :: Δ) (e.instantiate1' (.fvar v)) e') + (sc : FVarsIn (· ≠ v) e) : + TrExprS env Us ((none, d) :: Δ) e e' := H.uninstantiateN .zero sc + +theorem TrExpr.uninstantiate + (H : TrExpr env Us ((some (v, deps), d) :: Δ) (e.instantiate1' (.fvar v)) e') + (sc : FVarsIn (· ≠ v) e) : + TrExpr env Us ((none, d) :: Δ) e e' := H.uninstantiateN .zero sc + +theorem TrExprS.inst_fvar {Δ : VLCtx} (henv : Ordered env) + (hΔ : VLCtx.WF env Us.length ((some (a, deps), d) :: Δ)) + (H : TrExprS env Us ((none, d) :: Δ) e e') : + TrExprS env Us ((some (a, deps), d) :: Δ) (e.instantiate1' (.fvar a)) e' := by + refine + have W := .skip_fvar (a, deps) d .refl + have := H.weakFV henv (.cons_bvar _ W) ⟨hΔ, nofun, hΔ.2.2.weakN henv W.toCtx⟩ + ?_ + have hf := TrExprS.fvar (env := env) (Us := Us) (fv := a) (Δ := (some (a, deps), d) :: Δ) <| by + simp [VLCtx.find?, VLCtx.next]; exact ⟨rfl, rfl⟩ + match d with + | .vlam A₀ => + have := this.inst henv (.bvar .zero) (Δ := (some (a, deps), .vlam _) :: Δ) hf + rwa [VLocalDecl.depth, VExpr.instN_bvar0] at this + | .vlet A₀ e₀ => + simp [VLocalDecl.depth, VLocalDecl.liftN] at this + exact this.inst_let henv hf + +theorem TrExpr.rebuild_mkAppRevList (henv : env.WF) (hΔ : Δ.WF env Us.length) + (he : TrExprS env Us Δ e e') (h1 : TrExprS env Us Δ (e.mkAppRevList as) ea') + (h2 : TrExpr env Us Δ e₁ e') : TrExpr env Us Δ (e₁.mkAppRevList as) ea' := by + induction as generalizing ea' with + | nil => exact h2.defeq henv hΔ (he.uniq henv (.refl henv hΔ) h1) + | cons a as ih => + let .app a1 a2 a3 a4 := h1 + have := ih a3 + exact .app henv hΔ a1 a2 (ih a3) (a4.trExpr henv hΔ) + +theorem TrExpr.rebuild_mkAppList (henv : env.WF) (hΔ : Δ.WF env Us.length) + (he : TrExprS env Us Δ e e') (h1 : TrExprS env Us Δ (e.mkAppList as) ea') + (h2 : TrExpr env Us Δ e₁ e') : TrExpr env Us Δ (e₁.mkAppList as) ea' := by + rw [← Expr.mkAppRevList_reverse] at h1 ⊢ + exact h2.rebuild_mkAppRevList henv hΔ he h1 + +theorem TrExprS.eqv (H : TrExprS env Us Δ e₁ e') : e₁ == e₂ → TrExprS env Us Δ e₂ e' := by + simp [(· == ·)] + induction H generalizing e₂ <;> (cases e₂ <;> try change false = _ → _; rintro ⟨⟩) + all_goals simp [Expr.eqv']; grind [TrExprS] + +theorem TrExpr.eqv (H : TrExpr env Us Δ e₁ e') (h : e₁ == e₂) : TrExpr env Us Δ e₂ e' := + let ⟨_, h1, h2⟩ := H; ⟨_, h1.eqv h, h2⟩ + +theorem fvarsList_eqv {e₁ e₂ : Expr} : e₁ == e₂ → e₁.fvarsList = e₂.fvarsList := by + simp [(· == ·)] + induction e₁ generalizing e₂ <;> (cases e₂ <;> try change false = _ → _; rintro ⟨⟩) + all_goals simp [Expr.eqv']; intros; subst_vars; simp [Expr.fvarsList] + all_goals grind + +theorem FVarsIn.eqv : e₁ == e₂ → FVarsIn P e₁ → FVarsIn P e₂ := by + simp [(· == ·)] + induction e₁ generalizing e₂ <;> (cases e₂ <;> try change false = _ → _; rintro ⟨⟩) + all_goals simp [Expr.eqv']; intros; subst_vars; revert ‹FVarsIn ..›; simp [FVarsIn] + all_goals grind + +theorem FVarsBelow.eqv (H : FVarsBelow Δ e₁ ty₁) + (eq : e₁ == e₂) (eq' : ty₁ == ty₂) : FVarsBelow Δ e₂ ty₂ := + fun _ hP he => .eqv eq' (H _ hP (.eqv (BEq.symm eq) he)) + +theorem TrTyping.eqv (H : TrTyping env Us Δ e₁ ty₁ e' ty') + (eq : e₁ == e₂) (eq' : ty₁ == ty₂) : TrTyping env Us Δ e₂ ty₂ e' ty' := + let ⟨h1, h2, h3, h4⟩ := H + ⟨.eqv h1 eq eq', h2.eqv eq, h3.eqv eq', h4⟩ + +variable (env : VEnv) (Us : List Name) (Δ : VLCtx) in +inductive AppStack : Expr → VExpr → List Expr → Prop where + | head : TrExprS env Us Δ f f' → AppStack f f' [] + | app : + env.HasType Us.length Δ.toCtx f' (.forallE A B) → + env.HasType Us.length Δ.toCtx a' A → + TrExprS env Us Δ f f' → + TrExprS env Us Δ a a' → + AppStack (.app f a) (.app f' a') as → + AppStack f f' (a :: as) + +theorem AppStack.build_rev {e : Expr} : + ∀ {as}, TrExprS env Us Δ (e.mkAppRevList as) e' → + AppStack env Us Δ (e.mkAppRevList as) e' as' → + ∃ e', AppStack env Us Δ e e' (as.reverseAux as') + | [], _, H2 => ⟨_, H2⟩ + | _ :: as, .app h1 h2 h3 h4, H2 => + AppStack.build_rev (as := as) h3 (.app h1 h2 h3 h4 H2) + +theorem AppStack.tr : AppStack env Us Δ e e' as → TrExprS env Us Δ e e' + | .head H | .app _ _ H _ _ => H + +theorem AppStack.append {e : Expr} (H : AppStack env Us Δ (e.mkAppList as) e' bs) : + ∃ e', AppStack env Us Δ e e' (as ++ bs) := by + rw [← Expr.mkAppRevList_reverse] at H + simpa using AppStack.build_rev H.tr H + +theorem AppStack.build {e : Expr} (H : TrExprS env Us Δ (e.mkAppList as) e') : + ∃ e', AppStack env Us Δ e e' as := by simpa using AppStack.append (.head H) + +/-- Recover the pointwise strict translations of an application spine and +rebuild the complete translated application. Unlike the checker-facing +`AppStack.toSpineWF`, this purely syntactic projection needs no expected +function type and is therefore available to WHNF reduction. -/ +theorem AppStack.argsTranslation + (H : AppStack env Us Δ f f' args) : + ∃ args', args.Forall₂ (TrExprS env Us Δ) args' ∧ + TrExprS env Us Δ (f.mkAppList args) (VExpr.appN f' args') := by + induction H with + | head h => exact ⟨[], .nil, by simpa⟩ + | app hfun harg hf ha H ih => + obtain ⟨args', hargs, hfull⟩ := ih + refine ⟨_ :: args', .cons ha hargs, ?_⟩ + simpa [Expr.mkAppList, VExpr.appN] using hfull + +/-- A successful lookup on the left side of a pointwise list relation has a +related lookup at the same position on the right. -/ +theorem List.Forall₂.getElem?_left + {α : Type u} {β : Type v} {R : α → β → Prop} + {xs : List α} {ys : List β} {i : Nat} {x : α} + (H : List.Forall₂ R xs ys) (hx : xs[i]? = some x) : + ∃ y : β, ys[i]? = some y ∧ R x y := by + induction H generalizing i with + | nil => simp at hx + | cons hxy _ ih => + cases i with + | zero => + simp at hx + subst x + exact ⟨_, rfl, hxy⟩ + | succ i => simpa using ih (i := i) (by simpa using hx) + +#guard_named_axioms Ix.Theory.Named.TrExprS.toConstructor_ready [propext, Classical.choice, Quot.sound] diff --git a/Ix/Theory/Named/Verify/VLCtx.lean b/Ix/Theory/Named/Verify/VLCtx.lean new file mode 100644 index 000000000..7d42cb195 --- /dev/null +++ b/Ix/Theory/Named/Verify/VLCtx.lean @@ -0,0 +1,88 @@ +/- +Adapted for Ix: namespace, imports, and shared universe semantics. +SPDX-License-Identifier: Apache-2.0 +Source attribution and revision: Ix/Theory/Named/NOTICE. +-/ + +import Ix.Theory.Named.Verify.Expr +import Ix.Theory.Named.LocalContext + +open Ix.Theory (VLevel) + +namespace Ix.Theory.Named + +open Lean (FVarId Expr) + +@[reducible] def VLCtx := List (Option (FVarId × List FVarId) × VLocalDecl) + +namespace VLCtx + +def bvars : VLCtx → Nat + | [] => 0 + | (none, _) :: Δ => bvars Δ + 1 + | (some _, _) :: Δ => bvars Δ + +abbrev NoBV (Δ : VLCtx) : Prop := Δ.bvars = 0 + +def next : Option (FVarId × List FVarId) → Nat ⊕ FVarId → Option (Nat ⊕ FVarId) + | none, .inl 0 => none + | none, .inl (n+1) => some (.inl n) + | some _, .inl n => some (.inl n) + | none, .inr fv' => some (.inr fv') + | some (fv, _), .inr fv' => if fv == fv' then none else some (.inr fv') + +def find? : VLCtx → Nat ⊕ FVarId → Option (VExpr × VExpr) + | [], _ => none + | (ofv, d) :: Δ, v => + match next ofv v with + | none => some (d.value, d.type) + | some v => do let (e, A) ← find? Δ v; some (e.liftN d.depth, A.liftN d.depth) + +def liftVar (n k : Nat) : Nat ⊕ FVarId → Nat ⊕ FVarId + | .inl i => .inl (if i < k then i else i + n) + | .inr fv => .inr fv + +def varToExpr : Nat ⊕ FVarId → Expr + | .inl i => .bvar i + | .inr fv => .fvar fv + +def vlamName : VLCtx → Nat → Option (Option (FVarId × List FVarId)) + | [], _ => none + | (_, .vlet ..) :: Δ, i + | (_, .vlam ..) :: Δ, i+1 => vlamName Δ i + | (ofv, .vlam ..) :: _, 0 => some ofv + +def fvars (Δ : VLCtx) : List FVarId := Δ.filterMap (·.1.map (·.1)) + +@[simp] theorem fvars_nil : fvars [] = [] := rfl +@[simp] theorem fvars_cons_none {Δ : VLCtx} : fvars ((none, d) :: Δ) = fvars Δ := rfl +@[simp] theorem fvars_cons_some {Δ : VLCtx} : + fvars ((some fv, d) :: Δ) = fv.1 :: fvars Δ := rfl + +def toCtx : VLCtx → List VExpr + | [] => [] + | (_, .vlam ty) :: Δ => ty :: VLCtx.toCtx Δ + | (_, .vlet _ _) :: Δ => VLCtx.toCtx Δ + +def instL (Δ : VLCtx) (ls : List VLevel) : VLCtx := + match Δ with + | [] => [] + | (ofv, d) :: Δ => (ofv, d.instL ls) :: instL Δ ls + +theorem find?_eq_some : (∃ x, Δ.find? (.inr fv) = some x) ↔ fv ∈ fvars Δ := by + induction Δ with simp [find?] | cons d Δ ih + match d with + | (none, _) => simp [next, ← ih]; grind + | (some (fv', _), _) => + simp [next]; rw [@eq_comm _ fv] + by_cases h : fv' == fv <;> simp [h] <;> simp at h <;> simp [h]; grind + +theorem vlamName_mem_fvars : + ∀ {Δ : VLCtx} {i}, Δ.vlamName i = some (some fv) → fv.1 ∈ fvars Δ + | (none, .vlet ..) :: Δ, _, h + | (none, .vlam ..) :: Δ, _+1, h => vlamName_mem_fvars (Δ := Δ) h + | (some _, .vlet ..) :: Δ, _, h + | (some _, .vlam ..) :: Δ, _+1, h => .tail _ <| vlamName_mem_fvars (Δ := Δ) h + | (some _fv, .vlam ..) :: _, 0, rfl => .head _ + +end VLCtx diff --git a/Ix/Theory/PORTING.md b/Ix/Theory/PORTING.md new file mode 100644 index 000000000..4a013e8b8 --- /dev/null +++ b/Ix/Theory/PORTING.md @@ -0,0 +1,11 @@ +# Port notice + +This directory contains the selected Lean4Ix consistency model and its required +syntax, model, and certificate modules, relocated to `Ix.Theory`. It does not +contain the entire Lean4Ix or Ix.Theory.Named repositories. + +`LICENSE`, `LICENSE-MIT`, `LICENSE-APACHE`, and `NOTICE` are retained from the +source distribution. Historical source paths in those texts describe that +distribution. The current file selection, source hashes, con-leche attribution, +and namespace modifications are recorded in `Tests/Theory/ImportManifest.lean` +and the per-file headers. See `docs/theory.md` for the import boundary. diff --git a/Ix/Theory/Quot.lean b/Ix/Theory/Quot.lean new file mode 100644 index 000000000..f3c93b249 --- /dev/null +++ b/Ix/Theory/Quot.lean @@ -0,0 +1,239 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Store + +/-! # Canonical quotient declarations + +The quotient computation rules are selected by declaration content rather +than ambient names. This file records the exact anonymous kernel types of +`Eq`, `Quot`, `Quot.mk`, `Quot.lift`, and `Quot.ind`, parameterized by their +content-addressed references. +-/ + +namespace Ix.Theory +namespace Store + +/-- References used by the primitive quotient interface, including the +equality family appearing in the type of `Quot.lift`. -/ +structure QuotRefs (β : Type u) where + eq : ConstRef β + type : ConstRef β + ctor : ConstRef β + lift : ConstRef β + ind : ConstRef β + deriving DecidableEq + +/-- The two blocks whose contents make up the canonical equality and quotient +interface. -/ +structure QuotBlocks (β : Type u) where + equality : β + quotient : β + deriving DecidableEq + +namespace QuotBlocks + +/-- Positional references exposed by the canonical two-block layout. -/ +def refs (blocks : QuotBlocks β) : QuotRefs β where + eq := .member blocks.equality 0 + type := .member blocks.quotient 0 + ctor := .member blocks.quotient 1 + lift := .member blocks.quotient 2 + ind := .member blocks.quotient 3 + +end QuotBlocks + +namespace Quotient + +/-- Binary relation on the most recently bound sort. -/ +def relationType : VExpr β := + .forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero)) + +/-- Exact kernel type of the equality family. -/ +def eqType : VExpr β := + .forallE (.sort (.param 0)) + (.forallE (.bvar 0) (.forallE (.bvar 1) (.sort .zero))) + +/-- Exact kernel type of the reflexivity constructor at `eq`. -/ +def eqCtorType (eq : ConstRef β) : VExpr β := + .forallE (.sort (.param 0)) + (.forallE (.bvar 0) + (VExpr.appN (.const eq [.param 0]) [.bvar 1, .bvar 0, .bvar 0])) + +/-- Canonical equality-family member, including its nested reflexivity +constructor. -/ +def eqConstant (eq : ConstRef β) : Const β := + .induct 1 2 1 eqType + [{ + uvars := 1 + nparams := 2 + nfields := 0 + type := eqCtorType eq + safety := .safe + }] + .safe + +/-- Canonical one-member equality block at `block`. -/ +def eqBlock (block : β) : Block β := + { members := [eqConstant (.member block 0)] } + +/-- Exact kernel type of the quotient family. -/ +def typeType : VExpr β := + .forallE (.sort (.param 0)) + (.forallE relationType (.sort (.param 0))) + +/-- Exact kernel type of the quotient constructor. -/ +def ctorType (refs : QuotRefs β) : VExpr β := + .forallE (.sort (.param 0)) + (.forallE relationType + (.forallE (.bvar 1) + (VExpr.appN (.const refs.type [.param 0]) [.bvar 2, .bvar 1]))) + +/-- Exact kernel type of quotient lifting. -/ +def liftType (refs : QuotRefs β) : VExpr β := + .forallE (.sort (.param 0)) + (.forallE relationType + (.forallE (.sort (.param 1)) + (.forallE (.forallE (.bvar 2) (.bvar 1)) + (.forallE + (.forallE (.bvar 3) + (.forallE (.bvar 4) + (.forallE + (VExpr.appN (.bvar 4) [.bvar 1, .bvar 0]) + (VExpr.appN (.const refs.eq [.param 1]) + [.bvar 4, .app (.bvar 3) (.bvar 2), + .app (.bvar 3) (.bvar 1)])))) + (.forallE + (VExpr.appN (.const refs.type [.param 0]) [.bvar 4, .bvar 3]) + (.bvar 3)))))) + +/-- Exact kernel type of quotient induction. -/ +def indType (refs : QuotRefs β) : VExpr β := + .forallE (.sort (.param 0)) + (.forallE relationType + (.forallE + (.forallE + (VExpr.appN (.const refs.type [.param 0]) [.bvar 1, .bvar 0]) + (.sort .zero)) + (.forallE + (.forallE (.bvar 2) + (.app (.bvar 1) + (VExpr.appN (.const refs.ctor [.param 0]) + [.bvar 3, .bvar 2, .bvar 0]))) + (.forallE + (VExpr.appN (.const refs.type [.param 0]) [.bvar 3, .bvar 2]) + (.app (.bvar 2) (.bvar 0)))))) + +def typeConstant (_refs : QuotRefs β) : Const β := + .quot .type 1 typeType + +def ctorConstant (refs : QuotRefs β) : Const β := + .quot .ctor 1 (ctorType refs) + +def liftConstant (refs : QuotRefs β) : Const β := + .quot .lift 2 (liftType refs) + +def indConstant (refs : QuotRefs β) : Const β := + .quot .ind 1 (indType refs) + +/-- Canonical four-member quotient block at the selected block addresses. -/ +def quotBlock (blocks : QuotBlocks β) : Block β := + let refs := blocks.refs + { members := [typeConstant refs, ctorConstant refs, + liftConstant refs, indConstant refs] } + +/-- The canonical quotient block is syntactically closed. -/ +theorem quotBlock_closed (blocks : QuotBlocks β) : + (quotBlock blocks).Closed := by + simp [Block.Closed, quotBlock, typeConstant, ctorConstant, liftConstant, + indConstant, Const.Closed, typeType, ctorType, liftType, indType, + relationType, VExpr.appN, VExpr.Closed, VExpr.ClosedN] + +/-- Canonical quotient blocks contain no nested inductive-family members. -/ +theorem quotBlock_no_inductive {blocks : QuotBlocks β} {member uvars + nparams nindices : Nat} {type : VExpr β} {ctors : List (Ctor β)} + {safety : Safety} + (found : (quotBlock blocks).members[member]? = some + (.induct uvars nparams nindices type ctors safety)) : False := by + cases member with + | zero => simp [quotBlock, typeConstant] at found + | succ member => + cases member with + | zero => simp [quotBlock, ctorConstant] at found + | succ member => + cases member with + | zero => simp [quotBlock, liftConstant] at found + | succ member => + cases member with + | zero => simp [quotBlock, indConstant] at found + | succ member => simp [quotBlock] at found + +end Quotient + +/-- Exact content certificate for the canonical equality and quotient blocks. -/ +structure QuotBlocksCanonical (store : Store β) + (blocks : QuotBlocks β) : Prop where + equality : store.blocks blocks.equality = + some (Quotient.eqBlock blocks.equality) + quotient : store.blocks blocks.quotient = + some (Quotient.quotBlock blocks) + +/-- Exact canonical block content is stable under store inclusion. -/ +theorem QuotBlocksCanonical.mono {left right : Store β} + (subset : left ⊆ right) {blocks : QuotBlocks β} + (canonical : left.QuotBlocksCanonical blocks) : + right.QuotBlocksCanonical blocks where + equality := subset _ _ canonical.equality + quotient := subset _ _ canonical.quotient + +/-- The exact declarations selected by the primitive quotient rules. -/ +structure QuotReady (store : Store β) (refs : QuotRefs β) : Prop where + eq : store.lookup refs.eq = some (Quotient.eqConstant refs.eq) + type : store.lookup refs.type = some (Quotient.typeConstant refs) + ctor : store.lookup refs.ctor = some (Quotient.ctorConstant refs) + lift : store.lookup refs.lift = some (Quotient.liftConstant refs) + ind : store.lookup refs.ind = some (Quotient.indConstant refs) + +/-- Discover the unique canonical equality block by content. -/ +def eqBlock? [DecidableEq β] (store : Store β) : Option β := + match store.dom.filter fun block => + store.blocks block == some (Quotient.eqBlock block) with + | [block] => some block + | _ => none + +/-- Discover the unique canonical quotient block relative to `equality`. -/ +def quotBlock? [DecidableEq β] (store : Store β) + (equality : β) : Option β := + match store.dom.filter fun quotient => + let blocks : QuotBlocks β := { equality, quotient } + store.blocks quotient == some (Quotient.quotBlock blocks) with + | [block] => some block + | _ => none + +/-- Discover both uniquely designated blocks of the quotient interface. -/ +def quotBlocks? [DecidableEq β] (store : Store β) : Option (QuotBlocks β) := do + let equality ← store.eqBlock? + let quotient ← store.quotBlock? equality + pure { equality, quotient } + +/-- Exact canonical block content exposes the rule-facing declaration +inventory. -/ +theorem QuotBlocksCanonical.ready [DecidableEq β] {store : Store β} + {blocks : QuotBlocks β} (canonical : store.QuotBlocksCanonical blocks) : + store.QuotReady blocks.refs := by + constructor + · simp [Store.lookup, QuotBlocks.refs, Quotient.eqBlock, + canonical.equality] + · simp [Store.lookup, QuotBlocks.refs, Quotient.quotBlock, + canonical.quotient] + · simp [Store.lookup, QuotBlocks.refs, Quotient.quotBlock, + canonical.quotient] + · simp [Store.lookup, QuotBlocks.refs, Quotient.quotBlock, + canonical.quotient] + · simp [Store.lookup, QuotBlocks.refs, Quotient.quotBlock, + canonical.quotient] + +end Store +end Ix.Theory diff --git a/Ix/Theory/Ref.lean b/Ix/Theory/Ref.lean new file mode 100644 index 000000000..5ab55aeb6 --- /dev/null +++ b/Ix/Theory/Ref.lean @@ -0,0 +1,23 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +namespace Ix.Theory + +/-- A reference to a constant contained in a content-addressed block. -/ +inductive ConstRef (β : Type u) where + /-- The `i`th top-level member of block `b`. -/ + | member (b : β) (i : Nat) + /-- The `c`th constructor of the `i`th inductive member of block `b`. -/ + | ctor (b : β) (i c : Nat) +deriving DecidableEq, Hashable + +namespace ConstRef + +/-- The block containing a referenced member or constructor. -/ +@[simp] def block : ConstRef β → β + | .member b _ | .ctor b _ _ => b + +end ConstRef +end Ix.Theory diff --git a/Ix/Theory/Rename.lean b/Ix/Theory/Rename.lean new file mode 100644 index 000000000..362aa4701 --- /dev/null +++ b/Ix/Theory/Rename.lean @@ -0,0 +1,308 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Expr + +/-! # Address renaming for anonymous expressions + +The shared syntax operation is independent of inductive generation. +-/ + +namespace Ix.Theory + +/-- A dependency-free bijection used to transport abstract block addresses. +The Theory intentionally does not import Lean's metadata equivalence API. -/ +structure AddressEquiv (β : Type u) (γ : Type v) where + toFun : β → γ + invFun : γ → β + left_inv : ∀ block, invFun (toFun block) = block + right_inv : ∀ block, toFun (invFun block) = block + +namespace AddressEquiv + +instance : CoeFun (AddressEquiv β γ) fun _ => β → γ := + ⟨AddressEquiv.toFun⟩ + +@[simp] theorem inv_apply_apply (mapping : AddressEquiv β γ) (block : β) : + mapping.invFun (mapping block) = block := + mapping.left_inv block + +@[simp] theorem apply_inv_apply (mapping : AddressEquiv β γ) (block : γ) : + mapping (mapping.invFun block) = block := + mapping.right_inv block + +theorem injective (mapping : AddressEquiv β γ) : Function.Injective mapping := by + intro left right equality + simpa using congrArg mapping.invFun equality + +/-- Identity address bijection. -/ +def refl (β : Type u) : AddressEquiv β β where + toFun := id + invFun := id + left_inv := fun _ => rfl + right_inv := fun _ => rfl + +/-- Reverse an address bijection. -/ +def symm (mapping : AddressEquiv β γ) : AddressEquiv γ β where + toFun := mapping.invFun + invFun := mapping + left_inv := mapping.right_inv + right_inv := mapping.left_inv + +/-- Compose address bijections. -/ +def trans (first : AddressEquiv β γ) + (second : AddressEquiv γ δ) : AddressEquiv β δ where + toFun := second ∘ first + invFun := first.invFun ∘ second.invFun + left_inv := by + intro block + simp + right_inv := by + intro block + simp + +@[simp] theorem symm_apply (mapping : AddressEquiv β γ) (block : γ) : + mapping.symm block = mapping.invFun block := rfl + +@[simp] theorem trans_apply (first : AddressEquiv β γ) + (second : AddressEquiv γ δ) (block : β) : + (first.trans second) block = second (first block) := rfl + +@[simp] theorem beq_apply (mapping : AddressEquiv β γ) + [DecidableEq β] [DecidableEq γ] (left right : β) : + (mapping left == mapping right) = (left == right) := by + rw [Bool.eq_iff_iff] + simp only [beq_iff_eq, mapping.injective.eq_iff] + +@[simp] theorem bne_apply (mapping : AddressEquiv β γ) + [DecidableEq β] [DecidableEq γ] (left right : β) : + (mapping left != mapping right) = (left != right) := by + simp only [bne, beq_apply] + +end AddressEquiv + +namespace ConstRef + +/-- Rename the block address carried by a constant reference. -/ +def rename (mapping : β → γ) : ConstRef β → ConstRef γ + | .member block index => .member (mapping block) index + | .ctor block index ctorIndex => .ctor (mapping block) index ctorIndex + +@[simp] theorem rename_id (ref : ConstRef β) : + ref.rename id = ref := by + cases ref <;> rfl + +@[simp] theorem rename_comp (second : γ → δ) (first : β → γ) + (ref : ConstRef β) : + (ref.rename first).rename second = ref.rename (second ∘ first) := by + cases ref <;> rfl + +@[simp] theorem rename_block (mapping : β → γ) (ref : ConstRef β) : + (ref.rename mapping).block = mapping ref.block := by + cases ref <;> rfl + +/-- Renaming references along an address bijection is injective. -/ +theorem rename_injective (mapping : AddressEquiv β γ) : + Function.Injective (ConstRef.rename mapping) := by + have inverse : Function.LeftInverse + (ConstRef.rename mapping.invFun) (ConstRef.rename mapping) := by + intro ref + cases ref <;> simp [ConstRef.rename] + exact inverse.injective + +@[simp] theorem rename_eq_rename_iff (mapping : AddressEquiv β γ) + (left right : ConstRef β) : + left.rename mapping = right.rename mapping ↔ left = right := + (rename_injective mapping).eq_iff + +@[simp] theorem rename_inverse (mapping : AddressEquiv β γ) + (ref : ConstRef β) : + (ref.rename mapping).rename mapping.invFun = ref := by + cases ref <;> simp [ConstRef.rename] + +end ConstRef + +namespace VExpr + +/-- Rename every block address in an expression. Binder indices and universe +levels are unchanged. -/ +def rename (mapping : β → γ) : VExpr β → VExpr γ + | .bvar index => .bvar index + | .sort level => .sort level + | .const ref levels => .const (ref.rename mapping) levels + | .app function argument => + .app (function.rename mapping) (argument.rename mapping) + | .lam domain body => .lam (domain.rename mapping) (body.rename mapping) + | .forallE domain body => + .forallE (domain.rename mapping) (body.rename mapping) + | .proj ref field major => + .proj (ref.rename mapping) field (major.rename mapping) + | .natLit value => .natLit value + +@[simp] theorem rename_id (expression : VExpr β) : + expression.rename id = expression := by + induction expression with + | const ref levels => cases ref <;> rfl + | proj ref field major ih => cases ref <;> simp [rename, ih] + | _ => simp_all [rename] + +@[simp] theorem rename_comp (second : γ → δ) (first : β → γ) + (expression : VExpr β) : + (expression.rename first).rename second = + expression.rename (second ∘ first) := by + induction expression with + | const ref levels => cases ref <;> rfl + | proj ref field major ih => cases ref <;> simp [rename, ih] + | _ => simp_all [rename] + +@[simp] theorem rename_inverse (mapping : AddressEquiv β γ) + (expression : VExpr β) : + (expression.rename mapping).rename mapping.invFun = expression := by + induction expression <;> + simp_all only [rename, ConstRef.rename_inverse] + +/-- Expression renaming along an address bijection is injective. -/ +theorem rename_injective (mapping : AddressEquiv β γ) : + Function.Injective (VExpr.rename mapping) := by + have inverse : Function.LeftInverse + (VExpr.rename mapping.invFun) (VExpr.rename mapping) := + VExpr.rename_inverse mapping + exact inverse.injective + +@[simp] theorem rename_appN (mapping : β → γ) (function : VExpr β) + (arguments : List (VExpr β)) : + (function.appN arguments).rename mapping = + (function.rename mapping).appN (arguments.map (VExpr.rename mapping)) := by + induction arguments generalizing function with + | nil => rfl + | cons argument arguments ih => + simp [VExpr.appN, VExpr.rename, ih] + +@[simp] theorem rename_liftN (mapping : β → γ) (expression : VExpr β) + (count cutoff : Nat) : + (expression.liftN count cutoff).rename mapping = + (expression.rename mapping).liftN count cutoff := by + induction expression generalizing cutoff <;> simp_all [VExpr.liftN, rename] + +@[simp] theorem rename_instL (mapping : β → γ) (expression : VExpr β) + (levels : List VLevel) : + (expression.instL levels).rename mapping = + (expression.rename mapping).instL levels := by + induction expression <;> simp_all [VExpr.instL, rename] + +@[simp] theorem rename_inst (mapping : β → γ) (expression argument : VExpr β) + (cutoff : Nat) : + (expression.inst argument cutoff).rename mapping = + (expression.rename mapping).inst (argument.rename mapping) cutoff := by + induction expression generalizing cutoff with + | bvar index => + by_cases below : index < cutoff + · simp [VExpr.inst, VExpr.instVar, below, rename] + · by_cases equal : index = cutoff + · simp [VExpr.inst, VExpr.instVar, equal, rename] + · simp [VExpr.inst, VExpr.instVar, below, equal, rename] + | _ => simp_all [VExpr.inst, rename] + +@[simp] theorem rename_lamN (mapping : β → γ) + (binders : List (VExpr β)) (body : VExpr β) : + (VExpr.lamN binders body).rename mapping = + VExpr.lamN (binders.map (VExpr.rename mapping)) (body.rename mapping) := by + induction binders with + | nil => rfl + | cons binder binders ih => simp [VExpr.lamN, rename, ih] + +@[simp] theorem rename_forallN (mapping : β → γ) + (binders : List (VExpr β)) (body : VExpr β) : + (VExpr.forallN binders body).rename mapping = + VExpr.forallN (binders.map (VExpr.rename mapping)) + (body.rename mapping) := by + induction binders with + | nil => rfl + | cons binder binders ih => simp [VExpr.forallN, rename, ih] + +@[simp] theorem rename_liftTelN (mapping : β → γ) (count : Nat) : + ∀ (binders : List (VExpr β)) (cutoff : Nat), + (VExpr.liftTelN count binders cutoff).map (VExpr.rename mapping) = + VExpr.liftTelN count + (binders.map (VExpr.rename mapping)) cutoff + | [], _ => rfl + | binder :: binders, cutoff => by + simp [VExpr.liftTelN, rename_liftTelN mapping count binders] + +@[simp] theorem rename_telN (mapping : β → γ) (count : Nat) + (expression : VExpr β) : + (expression.rename mapping).telN count = + (expression.telN count).map (VExpr.rename mapping) := by + induction count generalizing expression with + | zero => rfl + | succ count ih => + cases expression with + | forallE domain body => + simp only [rename, VExpr.telN, List.map_cons] + rw [ih] + | _ => rfl + +@[simp] theorem rename_dropN (mapping : β → γ) (count : Nat) + (expression : VExpr β) : + (expression.rename mapping).dropN count = + (expression.dropN count).rename mapping := by + induction count generalizing expression with + | zero => rfl + | succ count ih => + cases expression <;> simp [rename, VExpr.dropN, ih] + +@[simp] theorem rename_resultOf (mapping : β → γ) (expression : VExpr β) : + (expression.rename mapping).resultOf = + expression.resultOf.rename mapping := by + induction expression <;> simp_all [rename, VExpr.resultOf] + +@[simp] theorem rename_appArgs (mapping : β → γ) (expression : VExpr β) + (accumulator : List (VExpr β)) : + (expression.rename mapping).appArgs + (accumulator.map (VExpr.rename mapping)) = + (expression.appArgs accumulator).map (VExpr.rename mapping) := by + induction expression generalizing accumulator with + | app function argument functionIH argumentIH => + simp only [rename, VExpr.appArgs] + simpa only [List.map_cons] using functionIH (argument :: accumulator) + | _ => rfl + +@[simp] theorem rename_appHead (mapping : β → γ) (expression : VExpr β) : + (expression.rename mapping).appHead = + expression.appHead.rename mapping := by + induction expression <;> simp_all [rename, VExpr.appHead] + +@[simp] theorem rename_instTelN (mapping : β → γ) (argument : VExpr β) : + ∀ (binders : List (VExpr β)) (cutoff : Nat), + (VExpr.instTelN argument binders cutoff).map (VExpr.rename mapping) = + VExpr.instTelN (argument.rename mapping) + (binders.map (VExpr.rename mapping)) cutoff + | [], _ => rfl + | binder :: binders, cutoff => by + simp [VExpr.instTelN, rename_instTelN mapping argument binders] + +@[simp] theorem rename_instRev (mapping : β → γ) (expression : VExpr β) + (arguments : List (VExpr β)) : + (VExpr.instRev expression arguments).rename mapping = + VExpr.instRev (expression.rename mapping) + (arguments.map (VExpr.rename mapping)) := by + induction arguments generalizing expression with + | nil => rfl + | cons argument arguments ih => + simp [VExpr.instRev, ih] + +@[simp] theorem rename_instRevAt (mapping : β → γ) (expression : VExpr β) + (arguments : List (VExpr β)) (cutoff : Nat) : + (VExpr.instRevAt expression arguments cutoff).rename mapping = + VExpr.instRevAt (expression.rename mapping) + (arguments.map (VExpr.rename mapping)) cutoff := by + induction arguments generalizing expression with + | nil => rfl + | cons argument arguments ih => + simp [VExpr.instRevAt, ih] + +end VExpr + +end Ix.Theory diff --git a/Ix/Theory/Std/Basic.lean b/Ix/Theory/Std/Basic.lean new file mode 100644 index 000000000..326c00da1 --- /dev/null +++ b/Ix/Theory/Std/Basic.lean @@ -0,0 +1,31 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Batteries.Data.List.Basic +import Init.Omega + +namespace Ix.Theory + +protected theorem List.Forall₂.rfl + {R : α → α → Prop} {xs : List α} (h : ∀ x ∈ xs, R x x) : xs.Forall₂ R xs := by + induction xs with + | nil => exact .nil + | cons x xs ih => + simp only [List.mem_cons, forall_eq_or_imp] at h + exact .cons h.1 (ih h.2) + +protected theorem List.Forall₂.length_eq + {R : α → β → Prop} {left : List α} {right : List β} + (related : List.Forall₂ R left right) : left.length = right.length := by + induction related with + | nil => rfl + | cons _ _ ih => exact congrArg Nat.succ ih +theorem List.map_id_mem {f : α → α} (xs : List α) (h : ∀ x ∈ xs, f x = x) : + xs.map f = xs := by + induction xs with + | nil => rfl + | cons x xs ih => simp only [List.mem_cons, forall_eq_or_imp] at h; simp [h.1, ih h.2] + +end Ix.Theory diff --git a/Ix/Theory/Store.lean b/Ix/Theory/Store.lean new file mode 100644 index 000000000..4365de0d0 --- /dev/null +++ b/Ix/Theory/Store.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Const + +namespace Ix.Theory + +/-- A finite view of a content-addressed constant store. -/ +structure Store (β : Type u) where + dom : List β + nodup : dom.Nodup + blocks : β → Option (Block β) + mem_dom : ∀ b, (blocks b).isSome ↔ b ∈ dom + +namespace Store + +/-- Look up an ordinary block member. Constructor references use `lookupCtor`. -/ +def lookup (store : Store β) : ConstRef β → Option (Const β) + | .member block index => do + let contents ← store.blocks block + contents.members[index]? + | .ctor .. => none + +/-- Look up a constructor nested under an inductive block member. -/ +def lookupCtor (store : Store β) : ConstRef β → Option (Ctor β) + | .member .. => none + | .ctor block member ctor => do + let contents ← store.blocks block + let constant ← contents.members[member]? + match constant with + | .induct _ _ _ _ ctors _ => ctors[ctor]? + | _ => none + +/-- Flattened constructor-rule position of a nested constructor reference. -/ +def ctorRuleIndex? (store : Store β) : ConstRef β → Option Nat + | .member .. => none + | .ctor block member ctor => do + let some contents := store.blocks block | none + let some constant := contents.members[member]? | none + match constant with + | .induct _ _ _ _ ctors _ => + if ctor < ctors.length then + some ((contents.members.take member).foldl + (fun offset entry => offset + entry.ctorCount) 0 + ctor) + else + none + | _ => none + +/-- Classify either an ordinary member or a nested constructor reference. -/ +def kind (store : Store β) (ref : ConstRef β) : Option ConstKind := + match store.lookup ref with + | some constant => some constant.kind + | none => (store.lookupCtor ref).map fun _ => .ctor + +/-- Universe arity of an ordinary member or nested constructor. -/ +def uvars (store : Store β) (ref : ConstRef β) : Option Nat := + match store.lookup ref with + | some constant => some constant.uvars + | none => (store.lookupCtor ref).map Ctor.uvars + +/-- Type of an ordinary member or nested constructor. -/ +def type (store : Store β) (ref : ConstRef β) : Option (VExpr β) := + match store.lookup ref with + | some constant => some constant.type + | none => (store.lookupCtor ref).map Ctor.type + +/-- Distinct dependencies of a block, excluding self references. -/ +def deps [DecidableEq β] (store : Store β) (block : β) : List β := + (((store.blocks block).map Block.refs).getD []).map ConstRef.block + |>.filter (· != block) + |>.eraseDups + +/-- `block` directly refers to `dependency`, and the dependency is present. -/ +def DependsOn [DecidableEq β] (store : Store β) (block dependency : β) : Prop := + dependency ∈ store.deps block ∧ dependency ∈ store.dom + +/-- Reflexive transitive dependency closure of one block. -/ +inductive Closure [DecidableEq β] (store : Store β) (root : β) : β → Prop where + | refl : store.Closure root root + | step : store.Closure root block → store.DependsOn block dependency → + store.Closure root dependency + +/-- Dependencies point strictly backward in some well-founded order. -/ +def Acyclic [DecidableEq β] (store : Store β) : Prop := + WellFounded (flip store.DependsOn) + +/-- Keep exactly the blocks satisfying `keep`. This is a proof-facing view; +executable consumers may supply their own finite closure computation. -/ +noncomputable def restrict (store : Store β) (keep : β → Prop) : Store β := by + classical + exact { + dom := store.dom.filter keep + nodup := store.nodup.filter _ + blocks := fun block => if keep block then store.blocks block else none + mem_dom := by + intro block + by_cases h : keep block <;> simp [h, store.mem_dom] + } + +/-- Pointwise inclusion of partial block maps. -/ +protected def Subset (left right : Store β) : Prop := + ∀ block contents, left.blocks block = some contents → + right.blocks block = some contents + +instance : HasSubset (Store β) := ⟨Store.Subset⟩ + +/-- Return a block identifier only when the requested content occurs exactly once. -/ +def designated [DecidableEq β] (store : Store β) (canon : Block β) : Option β := + match store.dom.filter fun block => store.blocks block == some canon with + | [block] => some block + | _ => none + +end Store +end Ix.Theory diff --git a/Ix/Theory/VLevel.lean b/Ix/Theory/VLevel.lean new file mode 100644 index 000000000..fe27e5159 --- /dev/null +++ b/Ix/Theory/VLevel.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Std.Basic + +/-! +# Semantic universe levels + +`VLevel` gives the implementation-independent meaning of universe levels used +by Theory. Its equivalence relation is extensional equality under every +valuation, so it deliberately forgets representation identity and sharing. +-/ + +namespace Ix.Theory + +inductive VLevel where + | zero : VLevel + | succ : VLevel → VLevel + | max : VLevel → VLevel → VLevel + | imax : VLevel → VLevel → VLevel + | param : Nat → VLevel +deriving DecidableEq, Hashable + +namespace VLevel + +/-- The natural-number semantics of universe `imax`. -/ +def natIMax (a b : Nat) : Nat := if b = 0 then 0 else Nat.max a b + +instance : Inhabited VLevel := ⟨.zero⟩ + +variable (n : Nat) in +def WF : VLevel → Prop + | .zero => True + | .succ l => l.WF + | .max l₁ l₂ => l₁.WF ∧ l₂.WF + | .imax l₁ l₂ => l₁.WF ∧ l₂.WF + | .param i => i < n + +instance decidable_WF : ∀ {l}, Decidable (WF n l) + | .zero => instDecidableTrue + | .succ l => @decidable_WF _ l + | .max .. | .imax .. => @instDecidableAnd _ _ decidable_WF decidable_WF + | .param _ => Nat.decLt .. + +variable (ls : List Nat) in +def eval : VLevel → Nat + | .zero => 0 + | .succ l => l.eval + 1 + | .max l₁ l₂ => l₁.eval.max l₂.eval + | .imax l₁ l₂ => natIMax l₁.eval l₂.eval + | .param i => ls.getD i 0 + +protected def LE (a b : VLevel) : Prop := ∀ ls, a.eval ls ≤ b.eval ls + +instance : LE VLevel := ⟨VLevel.LE⟩ + +theorem le_refl (a : VLevel) : a ≤ a := fun _ => Nat.le_refl _ + +protected def Equiv (a b : VLevel) : Prop := a.eval = b.eval + +instance : HasEquiv VLevel := ⟨VLevel.Equiv⟩ + +theorem equiv_def {a b : VLevel} : a ≈ b ↔ ∀ ls, a.eval ls = b.eval ls := funext_iff + +theorem le_antisymm_iff {a b : VLevel} : a ≈ b ↔ a ≤ b ∧ b ≤ a := + equiv_def.trans <| (forall_congr' fun _ => Nat.le_antisymm_iff).trans forall_and + +theorem succ_congr {a b : VLevel} (h : a ≈ b) : succ a ≈ succ b := by + simpa [equiv_def, eval] using h + +theorem imax_congr (h₁ : a₁ ≈ b₁) (h₂ : a₂ ≈ b₂) : imax a₁ a₂ ≈ imax b₁ b₂ := by + simp_all [equiv_def, eval] + +theorem imax_self : imax a a ≈ a := by + simp [equiv_def, eval, natIMax, eq_comm (b := 0)] + +variable (ls : List VLevel) in +def inst : VLevel → VLevel + | .zero => .zero + | .succ l => .succ l.inst + | .max l₁ l₂ => .max l₁.inst l₂.inst + | .imax l₁ l₂ => .imax l₁.inst l₂.inst + | .param i => ls.getD i .zero + +theorem inst_inst {l : VLevel} : (l.inst ls).inst ls' = l.inst (ls.map (inst ls')) := by + induction l <;> simp [inst, *, List.getD_eq_getElem?_getD, List.getElem?_map] + case param n => cases ls[n]? <;> simp [inst] + +def params (n : Nat) : List VLevel := (List.range n).map .param + +@[simp] theorem params_length {n : Nat} : (params n).length = n := by simp [params] + +theorem params_wf {n : Nat} : ∀ ⦃l⦄, l ∈ params n → l.WF n := by simp [params, WF] + +theorem inst_id {l : VLevel} (h : l.WF u) : l.inst (params u) = l := by + induction l <;> simp_all [params, inst, WF, List.getD_eq_getElem?_getD] + +theorem inst_map_id (h : ls.length = n) : (params n).map (inst ls) = ls := by + subst n; simp [params]; apply List.ext_get (by simp) + intro i _ _; simp [inst]; rw [List.getElem?_eq_getElem]; rfl + +theorem eval_inst {l : VLevel} : (l.inst ls).eval ns = l.eval (ls.map (eval ns)) := by + induction l <;> simp [eval, inst, *, List.getD_eq_getElem?_getD] + case param n => cases ls[n]? <;> simp [eval] + +theorem WF.inst {l : VLevel} (H : ∀ l ∈ ls, l.WF n) : (l.inst ls).WF n := by + induction l with + | zero => trivial + | succ _ ih => exact ih + | max _ _ ih1 ih2 | imax _ _ ih1 ih2 => exact ⟨ih1, ih2⟩ + | param i => + simp [VLevel.inst, List.getD_eq_getElem?_getD] + cases e : ls[i]? with + | none => trivial + | some => exact H _ (List.mem_of_getElem? e) + +theorem inst_congr {l : VLevel} (h1 : l ≈ l') (h2 : List.Forall₂ (·≈·) ls ls') : + l.inst ls ≈ l'.inst ls' := by + simp [equiv_def, eval_inst, ← equiv_def.1 h1] + intro ns; congr 1 + induction h2 with + | nil => rfl + | cons h2 => simp [*, equiv_def.1 h2] + +theorem inst_congr_l {l : VLevel} (h1 : l ≈ l') : l.inst ls ≈ l'.inst ls := + inst_congr h1 <| Ix.Theory.List.Forall₂.rfl fun _ _ => rfl diff --git a/Models/SetTheory/IxSetTheoryModel.lean b/Models/SetTheory/IxSetTheoryModel.lean new file mode 100644 index 000000000..a60e6561b --- /dev/null +++ b/Models/SetTheory/IxSetTheoryModel.lean @@ -0,0 +1,6 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import IxSetTheoryModel.Audit diff --git a/Models/SetTheory/IxSetTheoryModel/Audit.lean b/Models/SetTheory/IxSetTheoryModel/Audit.lean new file mode 100644 index 000000000..31fe85af3 --- /dev/null +++ b/Models/SetTheory/IxSetTheoryModel/Audit.lean @@ -0,0 +1,52 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean.Elab.Command +import Lean.Util.FoldConsts +import IxSetTheoryModel.Carneiro + +/-! +# Checked dependency boundary of the concrete set model + +The traversal reads declaration types, bodies, and constructor fields directly. +It does not depend on imported axiom summaries or the kernel's named calculus. +-/ + +namespace IxSetTheoryModel.Audit + +open Lean Elab Command + +private def directConstants (info : ConstantInfo) : Array Name := + info.type.getUsedConstants ++ match info with + | .thmInfo value => value.value.getUsedConstants + | .defnInfo value => value.value.getUsedConstants + | .opaqueInfo value => value.value.getUsedConstants + | .inductInfo value => value.ctors.toArray + | _ => #[] + +private partial def closure (env : Environment) (pending : List Name) + (seen : NameSet := {}) : NameSet := + match pending with + | [] => seen + | name :: rest => + if seen.contains name then closure env rest seen + else match env.checked.get.find? name with + | some info => closure env ((directConstants info).toList ++ rest) (seen.insert name) + | none => closure env rest (seen.insert name) + +run_cmd do + let env ← getEnv + let root := ``carneiro_implies_ix + let dependencies := closure env [root] + let actual := dependencies.toList.toArray.filter fun name => + match env.checked.get.find? name with + | some (.axiomInfo _) => true + | _ => false + let expected := #[``propext, ``Classical.choice, ``Quot.sound] + unless actual.qsort Name.lt == expected.qsort Name.lt do + throwError m!"set-theory model axiom boundary changed:\n{actual.qsort Name.lt}" + logInfo "Set-theory model full dependency audit passed: standard Lean axioms only" + +end IxSetTheoryModel.Audit diff --git a/Models/SetTheory/IxSetTheoryModel/Carneiro.lean b/Models/SetTheory/IxSetTheoryModel/Carneiro.lean new file mode 100644 index 000000000..2bf8d3ade --- /dev/null +++ b/Models/SetTheory/IxSetTheoryModel/Carneiro.lean @@ -0,0 +1,181 @@ +/- +Ported from con-leche (86cd20a65660d757cedc81561a44579099b565d0). +Source attribution and original path: Models/SetTheory/NOTICE. +Modifications Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0) +Changes: namespaces and imports adapted to Ix; documentation updated. +-/ + +import Mathlib.SetTheory.Cardinal.Regular +import Mathlib.SetTheory.ZFC.VonNeumann +import Mathlib.SetTheory.ZFC.Cardinal +import Ix.Theory.Model.SetTheory.Core + +/-! +# A concrete model of Ix's set-theory interface + +A strictly increasing countable sequence of inaccessible cardinals gives +`Ix.Theory.Model.SetTheory ZFSet.{u}`, with `univChain n := V_ (κ n).ord`. +Mathlib supplies the set operations, including images of arbitrary Lean +functions via `Classical.allZFSetDefinable`. The proof below establishes +Tarski's universe clauses for each inaccessible stage of the von Neumann +hierarchy and assembles the instance. + +This separate package is the only part of the construction that imports +Mathlib. `Audit.lean` checks the model-existence theorem's full dependency +graph against Lean's `propext`, `Classical.choice`, and `Quot.sound` axioms. +The inaccessible-cardinal assumption remains a theorem hypothesis. +-/ + +universe u + +open Cardinal Order ZFSet + +namespace IxSetTheoryModel + +/-- A strictly increasing countable sequence of strongly inaccessible +cardinals. This remains an explicit hypothesis; this package does not assert +the existence of inaccessible cardinals. -/ +def OmegaInaccessibles : Prop := + ∃ κ : ℕ → Cardinal.{u}, StrictMono κ ∧ ∀ n, (κ n).IsInaccessible + +/-! ### `V_ κ` is a Grothendieck universe in Tarski's form, for `κ` inaccessible -/ + +variable {κ : Cardinal.{u}} + +/-- A subset of `V_ κ.ord` of cardinality `< κ` has rank `< κ.ord`: +regularity of `κ` bounds the least strict upper bound of `< κ` many +ordinals below `κ.ord`. -/ +theorem rank_lt_ord_of_card_lt (hκ : κ.IsRegular) {y : ZFSet.{u}} + (hy : y ⊆ V_ κ.ord) (hc : y.card < κ) : y.rank < κ.ord := by + let e : y ≃ Shrink.{u} y := equivShrink _ + let f : Shrink.{u} y → Ordinal.{u} := fun z => rank (e.symm z).1 + have hlt : ⨆ z, f z + 1 < κ.ord := + Ordinal.iSup_add_one_lt_of_lt_cof (by rwa [hκ.cof_ord]) fun z => + mem_vonNeumann.mp (hy (e.symm z).2) + refine lt_of_le_of_lt ?_ hlt + rw [rank_le_iff] + intro z hz + have := Ordinal.lt_iSup_add_one f (e ⟨z, hz⟩) + simpa [f, e] using this + +/-- Below an inaccessible, the beth function stays below it. -/ +theorem preBeth_lt_of_lt_ord (hκ : κ.IsInaccessible) : + ∀ {a : Ordinal.{u}}, a < κ.ord → preBeth a < κ := by + intro a + induction a using Ordinal.limitRecOn with + | zero => intro _; rw [preBeth_zero]; exact hκ.pos + | add_one a ih => + intro h + rw [preBeth_add_one] + exact hκ.isStrongLimit.isStrongPrelimit (ih ((lt_add_one a).trans h)) + | limit a ha ih => + intro h + rw [preBeth_limit ha.isSuccPrelimit] + refine Cardinal.lift_iSup_lt_of_lt_cof_ord ?_ fun b => ih b b.2 (b.2.trans h) + rw [hκ.isRegular.lift.cof_ord, mk_Iio_ordinal, lift_lift, lift_lt] + exact lt_ord.mp h + +/-- `|V_ κ| = κ` for `κ` inaccessible. -/ +theorem card_vonNeumann_ord (hκ : κ.IsInaccessible) : card (V_ κ.ord) = κ := by + rw [card_vonNeumann] + refine le_antisymm ?_ (le_preBeth_ord κ) + rw [preBeth_limit (isSuccLimit_ord hκ.aleph0_lt.le).isSuccPrelimit] + exact ciSup_le' fun b => (preBeth_lt_of_lt_ord hκ b.2).le + +/-- A subset of `V_ κ` that is not a member has the cardinality of +`V_ κ`. -/ +theorem card_eq_of_not_rank_lt (hκ : κ.IsInaccessible) {y : ZFSet.{u}} + (hy : y ⊆ V_ κ.ord) (hr : ¬ y.rank < κ.ord) : card y = card (V_ κ.ord) := by + refine le_antisymm (card_mono hy) ?_ + rw [card_vonNeumann_ord hκ] + exact not_lt.mp fun h => hr (rank_lt_ord_of_card_lt hκ.isRegular hy h) + +/-- Equal cardinality gives Ix's meta-level equinumerosity: a global +function `ZFSet → ZFSet` that restricts to a bijection. -/ +theorem equinumerous_of_card_eq {y s : ZFSet.{u}} (h : card y = card s) : + Ix.Theory.Model.Equinumerous (· ∈ ·) y s := by + obtain ⟨e'⟩ := Cardinal.eq.mp h + let e : y ≃ s := (equivShrink _).trans (e'.trans (equivShrink _).symm) + classical + refine ⟨fun z => if hz : z ∈ y then (e ⟨z, hz⟩).1 else z, ?_, ?_, ?_⟩ + · intro z hz + simp only [hz, ↓reduceDIte] + exact (e ⟨z, hz⟩).2 + · intro z z' hz hz' hzz' + simp only [hz, hz', ↓reduceDIte] at hzz' + have := e.injective (Subtype.ext hzz') + exact congrArg Subtype.val this + · intro w hw + refine ⟨(e.symm ⟨w, hw⟩).1, (e.symm ⟨w, hw⟩).2, ?_⟩ + simp only [(e.symm ⟨w, hw⟩).2, ↓reduceDIte, Subtype.coe_eta, Equiv.apply_symm_apply] + +/-- **`V_ κ` is a Grothendieck universe in Tarski's form** (Ix's +`IsTGUniverse`) for every inaccessible `κ`. -/ +theorem isTGUniverse_vonNeumann (hκ : κ.IsInaccessible) : + Ix.Theory.Model.IsTGUniverse (· ∈ ·) (V_ κ.ord) := by + have hlim : IsSuccLimit κ.ord := isSuccLimit_ord hκ.aleph0_lt.le + refine ⟨?_, ?_, ?_, ?_⟩ + · -- transitivity + intro y z (hy : y ∈ V_ κ.ord) (hz : z ∈ y) + exact isTransitive_vonNeumann _ y hy hz + · -- subsets of members are members + intro y z (hy : y ∈ V_ κ.ord) hzy + exact mem_vonNeumann_of_subset (fun w hw => hzy w hw) hy + · -- power sets stay inside + intro y (hy : y ∈ V_ κ.ord) + refine ⟨powerset y, ?_, fun z hz => mem_powerset.mpr fun w hw => hz w hw⟩ + show powerset y ∈ V_ κ.ord + rw [mem_vonNeumann, rank_powerset] + exact hlim.succ_lt (mem_vonNeumann.mp hy) + · -- Tarski's clause: a subset is a member or equinumerous + intro y hy + have hy' : y ⊆ V_ κ.ord := fun w hw => hy w hw + by_cases hr : y.rank < κ.ord + · exact Or.inr (mem_vonNeumann.mpr hr) + · exact Or.inl (equinumerous_of_card_eq (card_eq_of_not_rank_lt hκ hy' hr)) + +/-! ### The `Ix.Theory.Model.SetTheory` instance on `ZFSet` -/ + +set_option warn.classDefReducibility false in +/-- Ix's set theory on Mathlib's `ZFSet.{u}`, from any strictly +increasing sequence of inaccessibles: the ZF⁻ fields are Mathlib's +(`ZFSet.ext`, pairs, `⋃₀`, `powerset`, `mem_wf`, `image` under +`Classical.allZFSetDefinable`), and `univChain n := V_ (κ n).ord`. -/ +noncomputable def setTheoryOfChain (κ : ℕ → Cardinal.{u}) (hmono : StrictMono κ) + (hinacc : ∀ n, (κ n).IsInaccessible) : Ix.Theory.Model.SetTheory ZFSet.{u} where + Mem := (· ∈ ·) + ext h := ZFSet.ext h + upair a b := {a, b} + mem_upair := mem_pair + sUnion := ZFSet.sUnion + mem_sUnion := mem_sUnion + power := powerset + mem_power := mem_powerset + regularity x h := by + obtain ⟨y, hy, hmin⟩ := mem_wf.has_min {y | y ∈ x} h + exact ⟨y, hy, fun ⟨z, hzy, hzx⟩ => hmin z hzx hzy⟩ + image f := @ZFSet.image f (Classical.allZFSetDefinable _) + mem_image := by + intro f a z + rw [@mem_image f (Classical.allZFSetDefinable _)] + exact exists_congr fun w => and_congr_right fun _ => eq_comm + univChain n := V_ (κ n).ord + univChain_mem n := vonNeumann_mem_of_lt (ord_lt_ord.mpr (hmono (Nat.lt_succ_self n))) + univChain_tg n := isTGUniverse_vonNeumann (hinacc n) + +set_option warn.classDefReducibility false in +/-- Ix's set theory on `ZFSet.{u}` under Carneiro's hypothesis. -/ +noncomputable def setTheoryOfCarneiro (h : OmegaInaccessibles.{u}) : Ix.Theory.Model.SetTheory ZFSet.{u} := + setTheoryOfChain (Classical.choose h) (Classical.choose_spec h).1 (Classical.choose_spec h).2 + +/-- **Carneiro's hypothesis implies Ix's.** `ω` strongly inaccessible +cardinals give a model of +Ix's `SetTheory` interface — on Mathlib's `ZFSet.{u}`, with the +universe chain `V_ (κ n).ord`. -/ +theorem carneiro_implies_ix : + OmegaInaccessibles.{u} → Nonempty (Σ V : Type (u + 1), Ix.Theory.Model.SetTheory V) := + fun h => ⟨⟨ZFSet.{u}, setTheoryOfCarneiro h⟩⟩ + + +end IxSetTheoryModel diff --git a/Models/SetTheory/LICENSE-CON-LECHE b/Models/SetTheory/LICENSE-CON-LECHE new file mode 100644 index 000000000..4c3f8ab0f --- /dev/null +++ b/Models/SetTheory/LICENSE-CON-LECHE @@ -0,0 +1,70 @@ +Apache License 2.0 (Apache) +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +1. You must give any other recipients of the Work or Derivative Works a copy of this License; and + +2. You must cause any modified files to carry prominent notices stating that You changed the files; and + +3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. diff --git a/Models/SetTheory/NOTICE b/Models/SetTheory/NOTICE new file mode 100644 index 000000000..049f8aeb6 --- /dev/null +++ b/Models/SetTheory/NOTICE @@ -0,0 +1,11 @@ +Set-theory model construction + +Copied from con-leche revision 86cd20a65660d757cedc81561a44579099b565d0, +bridge/lean4lean-model/ConLecheBridge/Carneiro.lean. +Original SHA-256: +389b5fff365cf47a5040e6eac540d6ddedde4b95d9f4176c3c08f675f586c1c4 + +The countable-inaccessibles hypothesis was transcribed by con-leche from +Mario Carneiro's Lean4LeanModel/Consistency.lean. Namespaces, imports, and +documentation were adapted for Ix; the mathematical construction is retained. +Con-leche's Apache-2.0 license is preserved in LICENSE-CON-LECHE. diff --git a/Models/SetTheory/README.md b/Models/SetTheory/README.md new file mode 100644 index 000000000..e74498555 --- /dev/null +++ b/Models/SetTheory/README.md @@ -0,0 +1,56 @@ +# Set-theory model + +This separate Lake package constructs `Ix.Theory.Model.SetTheory` on Mathlib's +`ZFSet`, assuming a strictly increasing countable sequence of strongly +inaccessible cardinals. Its universe chain is `V_ (κ n).ord`. + +`IxSetTheoryModel.setTheoryOfChain` assembles the instance from a given chain. +`setTheoryOfCarneiro` selects a chain from `OmegaInaccessibles`, and +`carneiro_implies_ix` proves: + +```lean +OmegaInaccessibles.{u} → + Nonempty (Σ V : Type (u + 1), Ix.Theory.Model.SetTheory V) +``` + +The construction includes the interface's Lean-level replacement scheme: +Mathlib's `Classical.allZFSetDefinable` supplies images of arbitrary functions +`ZFSet → ZFSet`. The audit traverses the theorem's checked types, bodies, and +constructor fields and permits exactly `propext`, `Classical.choice`, and +`Quot.sound`. Inaccessible cardinals remain an explicit +hypothesis, rather than an added Lean axiom. + +The package imports the actual Ix interface by a path dependency on the +repository root. Mathlib is confined to this package; ordinary Ix and +`Ix.Theory` builds do not depend on it. This construction supplies the +set-theoretic assumption used by the [consistency model](../../docs/theory.md). +The connection from the production checker to the certified interface is a +separate proof obligation. A converse from the interface to inaccessible +cardinals is not proved here. + +## Build + +From `Models/SetTheory`: + +```sh +lake exe cache get Mathlib.SetTheory.Cardinal.Regular Mathlib.SetTheory.ZFC.VonNeumann Mathlib.SetTheory.ZFC.Cardinal +lake build --wfail +``` + +Lean and Mathlib use release `v4.33.1`; `lake-manifest.json` pins all resolved +dependencies. The cache command retrieves the three imported Mathlib modules +and their dependencies. The build checks the axiom guard. The separate +`set-theory-model.yml` workflow runs these commands when the model, its interface, +or package configuration changes. + +From the repository root, `lake run check-kernel --with-model` includes this +build alongside the kernel proofs, foundation audits, and host regressions. + +## Provenance + +`IxSetTheoryModel/Carneiro.lean` is copied from con-leche revision +`86cd20a65660d757cedc81561a44579099b565d0`. The original path and source +SHA-256 are recorded in [NOTICE](NOTICE). +Namespaces, imports, and documentation are adapted for Ix; the mathematical +construction is retained. Con-leche's Apache-2.0 license is preserved in +`LICENSE-CON-LECHE`. diff --git a/Models/SetTheory/lake-manifest.json b/Models/SetTheory/lake-manifest.json new file mode 100644 index 000000000..65a60778b --- /dev/null +++ b/Models/SetTheory/lake-manifest.json @@ -0,0 +1,123 @@ +{"version": "1.2.0", + "packagesDir": ".lake/packages", + "packages": + [{"type": "path", + "scope": "", + "name": "ix", + "manifestFile": "lake-manifest.json", + "inherited": false, + "dir": "../..", + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/mathlib4", + "type": "git", + "subDir": null, + "scope": "", + "rev": "0df444a360eaa60ab8c11dca51a86af692955474", + "name": "mathlib", + "manifestFile": "lake-manifest.json", + "inputRev": "v4.33.1", + "inherited": false, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/batteries", + "type": "git", + "subDir": null, + "scope": "", + "rev": "4488d40d070b9700d4d5a6aa342f0d40c31b2a2d", + "name": "batteries", + "manifestFile": "lake-manifest.json", + "inputRev": "v4.33.0", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover/lean4-cli", + "type": "git", + "subDir": null, + "scope": "", + "rev": "6130a47896ce867c6a4a55373441e59e565bad0f", + "name": "Cli", + "manifestFile": "lake-manifest.json", + "inputRev": "v4.33.0", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/argumentcomputer/Blake3.lean", + "type": "git", + "subDir": null, + "scope": "", + "rev": "78f5bc4b22de1172af8a5d91e7039128084fad3a", + "name": "Blake3", + "manifestFile": "lake-manifest.json", + "inputRev": "78f5bc4b22de1172af8a5d91e7039128084fad3a", + "inherited": true, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/argumentcomputer/LSpec", + "type": "git", + "subDir": null, + "scope": "", + "rev": "ab4d5eb461941837f48eb891be755c8c73e89fdd", + "name": "LSpec", + "manifestFile": "lake-manifest.json", + "inputRev": "ab4d5eb461941837f48eb891be755c8c73e89fdd", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/plausible", + "type": "git", + "subDir": null, + "scope": "", + "rev": "b7eb3304aeae834b12dda98993a37f6a41f6f0bb", + "name": "plausible", + "manifestFile": "lake-manifest.json", + "inputRev": "v4.33.0", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/LeanSearchClient", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "5f4d51b81cbd3f6b32b156bfad9056621a040404", + "name": "LeanSearchClient", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/import-graph", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "16f02aa7642864af59f1ff0e384a015994db9118", + "name": "importGraph", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/ProofWidgets4", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "4be2e3d5087eeb272cf5a8853b8f9dd025ef5957", + "name": "proofwidgets", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/aesop", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "3448c0bcc5ce01b2d1546e483ec3620e32df3d0e", + "name": "aesop", + "manifestFile": "lake-manifest.json", + "inputRev": "master", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/quote4", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "92c15be17b7caf78c2ad767ec40f89052d908d81", + "name": "Qq", + "manifestFile": "lake-manifest.json", + "inputRev": "master", + "inherited": true, + "configFile": "lakefile.toml"}], + "name": "«ix-set-theory-model»", + "lakeDir": ".lake", + "fixedToolchain": false} diff --git a/Models/SetTheory/lakefile.toml b/Models/SetTheory/lakefile.toml new file mode 100644 index 000000000..6d6734249 --- /dev/null +++ b/Models/SetTheory/lakefile.toml @@ -0,0 +1,16 @@ +name = "ix-set-theory-model" +defaultTargets = ["IxSetTheoryModel"] + +# Keep Mathlib confined to this package. Its release matches Ix's toolchain. +# Resolve shared dependencies from Mathlib's pinned manifest first. +[[require]] +name = "mathlib" +git = "https://github.com/leanprover-community/mathlib4" +rev = "v4.33.1" + +[[require]] +name = "ix" +path = "../.." + +[[lean_lib]] +name = "IxSetTheoryModel" diff --git a/Models/SetTheory/lean-toolchain b/Models/SetTheory/lean-toolchain new file mode 100644 index 000000000..a8afa7d1b --- /dev/null +++ b/Models/SetTheory/lean-toolchain @@ -0,0 +1 @@ +leanprover/lean4:v4.33.1 diff --git a/README.md b/README.md index 5cd891617..37832c63a 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,20 @@ Ix consists of the following core components: - Integration with the [iroh p2p network](https://www.iroh.computer/) so that different ix users can easily share `ixon` data between themselves. +### Kernel certification + +`Ix.Kernel` includes audited implementation proofs and a certified receipt +interface with relative consistency theorems under an explicit set-theory +assumption. Full consistency of the production `checkEnvAnon` checker remains +open. See the [kernel verification guide](docs/kernel-verification.md) for the +theorem boundaries and remaining obligations, and +[certified checking](docs/certified-checking.md) for runnable examples. + +Run `lake run check-kernel` to validate the implementation proofs, consistency +refinements, theory foundation, certified host adapters, and kernel unit tests. +Add `--with-model` to include the separate Mathlib `ZFSet` construction of the +set-theory instance under the inaccessible-cardinal hypothesis. + ## Benchmarks Benchmarks (compiler, kernel, and zk-prover backends) are tracked at diff --git a/Tests/Certified/CLI.lean b/Tests/Certified/CLI.lean new file mode 100644 index 000000000..b96ed8668 --- /dev/null +++ b/Tests/Certified/CLI.lean @@ -0,0 +1,264 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean + +/-! Native command regressions ported from the frozen source and claim CLI drivers. +JSON is retained for the existing command protocol and differential evidence. -/ + +open Lean System + +namespace Tests.Certified.CLI + +private def readJson (path : FilePath) : IO Json := do + IO.ofExcept (Json.parse (← IO.FS.readFile path)) + +private def writeJson (path : FilePath) (value : Json) : IO Unit := + IO.FS.writeFile path (value.pretty ++ "\n") + +private def field (value : Json) (key : String) : Json := value.getObjValD key +private def array (value : Json) : Array Json := value.getArr?.toOption.get! +private def string (value : Json) : String := value.getStr?.toOption.get! +private def set := Json.setObjVal! + +private def directories (path : FilePath) : IO (Array FilePath) := do + let entries ← path.readDir + let mut result := #[] + for entry in entries do + if ← entry.path.isDir then result := result.push entry.path + return result.qsort (fun a b => a.toString < b.toString) + +private def name (path : FilePath) : String := path.fileName.get! +private def truncate (bytes : ByteArray) := bytes.extract 0 (bytes.size / 2) +private def corrupt (bytes : ByteArray) := bytes.set! 0 (bytes[0]! ^^^ 255) +private def zeros : Json := .str (String.ofList (List.replicate 64 '0')) + +private def check (executable : String) (directory : FilePath) (source : ByteArray) + (request : Json) (expected : Bool) (mode : Option String := none) + (envelope : ByteArray := ByteArray.empty) : IO Json := do + IO.FS.createDirAll directory + let sourcePath := directory / "source.ixe" + let requestPath := directory / "request.json" + IO.FS.writeBinFile sourcePath source + writeJson requestPath request + let (args, success) ← match mode with + | some mode => pure (#[mode, sourcePath.toString, requestPath.toString], + Json.mkObj [("accepted", .bool true), ("mode", .str mode)]) + | none => do + let envelopePath := directory / "envelope.bin" + IO.FS.writeBinFile envelopePath envelope + pure (#[sourcePath.toString, envelopePath.toString, requestPath.toString], + Json.mkObj [("accepted", .bool true), ("address", field request "address")]) + let result ← IO.Process.output { cmd := "timeout", args := #["60", executable] ++ args } + IO.FS.writeFile (directory / "stdout.txt") result.stdout + IO.FS.writeFile (directory / "stderr.txt") result.stderr + unless result.exitCode == 0 || result.exitCode == 1 do + throw (IO.userError s!"abnormal exit {directory}: {result.exitCode}\n{result.stderr}") + let accepted := result.exitCode == 0 + unless accepted == expected do + throw (IO.userError s!"unexpected acceptance {directory}: {accepted}\n{result.stderr}") + if accepted then + unless (← IO.ofExcept (Json.parse result.stdout)) == success do + throw (IO.userError s!"incorrect success output {directory}: {result.stdout}") + else unless result.stdout.trimAscii.isEmpty do + throw (IO.userError s!"rejected command printed a success result {directory}: {result.stdout}") + return Json.mkObj [("accepted", .bool accepted), ("exitCode", toJson result.exitCode.toNat)] + +private def acceptedCount (records : Array Json) : Nat := + (records.filter (fun record => field record "accepted" == .bool true)).size + +private def finish (output : FilePath) (records : Array Json) (fields : List (String × Json)) : IO Unit := do + writeJson (output / "results.json") (.arr records) + let report := Json.mkObj (fields ++ [ + ("rejected", toJson (records.size - acceptedCount records)), ("unexpectedErrors", toJson (0 : Nat))]) + writeJson (output / "summary.json") report + IO.println report.compress + +private def sourceTests (executable : String) (inputs output : FilePath) : IO Unit := do + let cases ← directories inputs + unless cases.size == 42 do throw (IO.userError "expected the 42-case source corpus") + let mut records := #[] + for directory in cases do + let bytes ← IO.FS.readBinFile (directory / "source.ixe") + let request ← readJson (directory / "request.json") + let objects := array (field request "objects") + let mut variants := #[ + ("valid", bytes, request, true), + ("missing-target", bytes, set request "objects" (.arr (objects.filter (· != field request "target"))), false), + ("duplicate-object", bytes, set request "objects" (.arr (objects.push objects[0]!)), false), + ("wrong-false-pin", bytes, set request "falseType" (field request "target"), false), + ("malformed-address", bytes, set request "falseElim" (.str "01"), false), + ("truncated-source", truncate bytes, request, false), + ("invalid-header", corrupt bytes, request, false)] + if field request "natType" != .null then + variants := variants.push ("missing-nat-pin", bytes, set request "natType" .null, false) + for (scenario, source, requested, expected) in variants do + for mode in #["proof", "store"] do + let record ← check executable (output / name directory / scenario / mode) + source requested expected (some mode) + records := records.push (set (set (set record "case" (.str (name directory))) + "scenario" (.str scenario)) "mode" (.str mode)) + let record ← check executable (output / name directory / "unsupported-mode" / "infer-only") + bytes request false (some "infer-only") + records := records.push (set (set (set record "case" (.str (name directory))) + "scenario" (.str "unsupported-mode")) "mode" (.str "infer-only")) + unless acceptedCount records == 84 do throw (IO.userError "missing source success coverage") + finish output records [("cases", toJson cases.size), ("proofAccepted", toJson (42 : Nat)), + ("storesAccepted", toJson (42 : Nat))] + +private def claimTests (executable : String) (inputs output : FilePath) : IO Unit := do + let cases ← directories inputs + let required := #["cycle-A-assuming-B", "cycle-B-assuming-A", "cycle-closed-AB", "cycle-closed-BA", + "cycle-own-assumption", "contains-padding", "contains-as-logical"] + unless cases.size ≥ 1500 && required.all (fun x => (cases.map name).contains x) do + throw (IO.userError "expected complete claim, cycle, catalog and structural coverage") + let mut records := #[] + for directory in cases do + let source ← IO.FS.readBinFile (directory / "source.ixe") + let envelope ← IO.FS.readBinFile (directory / "envelope.bin") + let request ← readJson (directory / "request.json") + let expected := field (← readJson (directory / "expected.json")) "accepted" == .bool true + let record ← check executable (output / name directory / "original") source request expected none envelope + records := records.push (set (set (set record "case" (.str (name directory))) + "scenario" (.str "original")) "kind" (field request "kind")) + unless expected do continue + let mut variants := #[ + ("wrong-digest", source, envelope, set request "address" zeros), + ("short-address", source, envelope, set request "address" (.str "01")), + ("unsupported-kind", source, envelope, set request "kind" (.str "infer-only")), + ("changed-envelope", source, corrupt envelope, request), + ("trailing-envelope", source, envelope.push 0, request), + ("truncated-envelope", source, truncate envelope, request), + ("truncated-source", truncate source, envelope, request)] + if field request "kind" == .str "logical" then + let objects := array (field request "objects") + variants := variants.push ("duplicate-object", source, envelope, + set request "objects" (.arr (objects.push objects[0]!))) + variants := variants.push ("missing-leaves", source, envelope, set request "leaves" (.arr #[])) + if field request "axioms" != .null then + variants := variants.push ("omitted-logical-axioms", source, envelope, set request "axioms" .null) + for key in #["subjects", "members", "frontier", "axioms"] do + if field request key != .null then + variants := variants.push (s!"trailing-{key}", source, envelope, + set request key (.str (string (field request key) ++ "00"))) + let leaves := array (field request "leaves") + let leaf := leaves[0]! + variants := variants.push ("trailing-leaf-claim", source, envelope, + set request "leaves" (.arr (leaves.set! 0 + (set leaf "claim" (.str (string (field leaf "claim") ++ "00")))))) + for (scenario, changedSource, changedEnvelope, changedRequest) in variants do + let record ← check executable (output / name directory / scenario) + changedSource changedRequest false none changedEnvelope + records := records.push (set (set (set record "case" (.str (name directory))) + "scenario" (.str scenario)) "kind" (field changedRequest "kind")) + unless acceptedCount records ≥ 500 do throw (IO.userError "missing claim nonvacuity coverage") + finish output records [("cases", toJson cases.size), ("accepted", toJson (acceptedCount records))] + +private def modelVariants (request : Json) : Array (String × Json) := Id.run do + let models := array (field request "models") + let model := models[0]! + let recursors := array (field model "recursors") + let targets := array (field model "targets") + let withoutModels := match request with + | .obj fields => Json.obj (fields.erase "models") + | _ => request + let mut variants := #[("missing-models", withoutModels), + ("malformed-models", set request "models" (.bool true))] + let edits := #[ + ("unknown-model-source", "source", zeros), ("short-model-address", "source", .str "01"), + ("recursor-order", "recursors", .arr recursors.reverse), + ("target-order", "targets", .arr targets.reverse), + ("missing-target", "targets", .arr targets.pop), + ("circular-target", "targets", .arr (targets.set! (targets.size - 1) recursors.back!)), + ("unknown-target", "targets", .arr (targets.set! (targets.size - 1) zeros)), + ("unknown-recursor", "recursors", .arr (recursors.set! (recursors.size - 1) zeros)), + ("missing-recursor", "recursors", .arr (recursors.extract 1 recursors.size))] + for (scenario, key, value) in edits do + variants := variants.push (scenario, set request "models" (.arr (models.set! 0 (set model key value)))) + let rulesArray := array (field model "proofs") + unless rulesArray.isEmpty do + let rules := rulesArray[0]! + let proofs := array (field rules "proofs") + for scenario in #["wrong-equation-owner", "wrong-equation-proof", "wrong-equality-family", + "wrong-reflexivity", "wrong-equality-eliminator", "malformed-proof-list"] do + let changed := if scenario == "wrong-equation-owner" then set rules "owner" recursors.back! + else if scenario == "malformed-proof-list" then set rules "proofs" (.bool true) + else Id.run do + let index := proofs.findIdx? (· != .null) |>.get! + let key := if scenario == "wrong-equation-proof" then "proof" + else if scenario == "wrong-equality-family" then "equality" + else if scenario == "wrong-reflexivity" then "reflexivity" else "eliminator" + return set rules "proofs" (.arr (proofs.set! index (set proofs[index]! key targets[0]!))) + let changedModel := set model "proofs" (.arr (rulesArray.set! 0 changed)) + variants := variants.push (scenario, set request "models" (.arr (models.set! 0 changedModel))) + return variants + +private def positives := #["mutual-unequal", "mutual-permuted", "auxiliary-merged", "nested-parameter", + "nested-recursive-Pi", "propositional-equations"] + +private def modeledTests (sourceExe claimExe : String) (inputs output : FilePath) : IO Unit := do + let sourceCases ← directories (inputs / "source") + let claimCases ← directories (inputs / "claims") + let mut records := #[] + let mut acceptedSources := #[] + for directory in sourceCases do + let source ← IO.FS.readBinFile (directory / "source.ixe") + let request ← readJson (directory / "request.json") + let expected ← readJson (directory / "expected.json") + if field expected "proof" == .bool true && field expected "store" == .bool true then + acceptedSources := acceptedSources.push (name directory) + for mode in #["proof", "store"] do + let accept := field expected mode == .bool true + let mut variants := #[("original", source, request, accept)] + if accept then + variants := variants ++ (modelVariants request).map (fun (scenario, changed) => + (scenario, source, changed, false)) + variants := variants.push ("truncated-source", truncate source, request, false) + for (scenario, changedSource, changedRequest, accept) in variants do + let record ← check sourceExe (output / "source" / name directory / scenario / mode) + changedSource changedRequest accept (some mode) + records := records.push (set (set (set (set record "kind" (.str "source")) + "case" (.str (name directory))) "scenario" (.str scenario)) "mode" (.str mode)) + unless sourceCases.size == 44 && acceptedSources.qsort (· < ·) == positives.qsort (· < ·) do + throw (IO.userError "missing complete modeled source controls") + let mut acceptedClaims := #[] + for directory in claimCases do + let source ← IO.FS.readBinFile (directory / "source.ixe") + let envelope ← IO.FS.readBinFile (directory / "envelope.bin") + let request ← readJson (directory / "request.json") + let expected := field (← readJson (directory / "expected.json")) "accepted" == .bool true + let mut variants := #[("original", envelope, request, expected)] + if expected then + acceptedClaims := acceptedClaims.push (name directory) + variants := variants ++ (modelVariants request).map (fun (scenario, changed) => + (scenario, envelope, changed, false)) + variants := variants.push ("changed-public-bytes", corrupt envelope, request, false) + variants := variants.push ("trailing-public-bytes", envelope.push 0, request, false) + for (scenario, changedEnvelope, changedRequest, accept) in variants do + let record ← check claimExe (output / "claims" / name directory / scenario / "claim") + source changedRequest accept none changedEnvelope + records := records.push (set (set (set (set record "kind" (.str "claims")) + "case" (.str (name directory))) "scenario" (.str scenario)) "mode" .null) + let requiredClaims := positives.flatMap (fun caseName => + #["check", "environment", "shared-model"].map (fun kind => s!"{caseName}-{kind}")) + unless claimCases.size == 74 && acceptedClaims.qsort (· < ·) == requiredClaims.qsort (· < ·) do + throw (IO.userError "missing complete modeled claim controls") + finish output records [("sourceCases", toJson sourceCases.size), ("claimCases", toJson claimCases.size), + ("accepted", toJson (acceptedCount records))] + +end Tests.Certified.CLI + +def main (args : List String) : IO UInt32 := do + match args with + | [kind, sourceExe, claimExe, inputs, output] => + match kind with + | "source" => Tests.Certified.CLI.sourceTests sourceExe inputs output + | "claims" => Tests.Certified.CLI.claimTests claimExe inputs output + | "modeled" => Tests.Certified.CLI.modeledTests sourceExe claimExe inputs output + | _ => throw (IO.userError s!"unknown corpus: {kind}") + return 0 + | _ => + IO.eprintln "usage: certified-cli-tests (source|claims|modeled) SOURCE_EXE CLAIM_EXE INPUTS OUTPUTS" + return 2 diff --git a/Tests/Certified/Check.lean b/Tests/Certified/Check.lean new file mode 100644 index 000000000..25ac2055e --- /dev/null +++ b/Tests/Certified/Check.lean @@ -0,0 +1,144 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean +import Tests.Certified.ImportManifest + +/-! Independent provenance and byte/command regressions for the maintained +certified adapters. All historical inputs come from the local frozen archive. -/ + +open Lean System Tests.Certified.ImportManifest + +namespace Tests.Certified.Check + +private def need (condition : Bool) (message : String) : IO Unit := + unless condition do throw (IO.userError message) + +private def run (cmd : String) (args : Array String) : IO IO.Process.Output := do + let result ← IO.Process.output { cmd, args } + need (result.exitCode == 0) s!"{cmd} failed ({result.exitCode}): {result.stdout}{result.stderr}" + return result + +private def sha256 (path : FilePath) : IO String := do + return ((← run "sha256sum" #["--", path.toString]).stdout.splitOn " ").headD "" + +private def files (directory : FilePath) : IO (Array String) := do + let mut result := #[] + for path in ← directory.walkDir do + unless ← path.isDir do + result := result.push ((path.toString.drop (directory.toString.length + 1)).toString) + return result.qsort (· < ·) + +private def compareTree (expected actual : FilePath) (jsonEquivalent : Bool := false) : IO Unit := do + let expectedFiles ← files expected + let actualFiles ← files actual + need (expectedFiles == actualFiles) s!"fixture inventory differs: {expected} / {actual}" + for relative in expectedFiles do + let old ← IO.FS.readBinFile (expected / relative) + let current ← IO.FS.readBinFile (actual / relative) + if old == current then continue + if jsonEquivalent && (FilePath.mk relative).extension == some "json" then + let old ← IO.ofExcept (Json.parse (String.fromUTF8! old)) + let current ← IO.ofExcept (Json.parse (String.fromUTF8! current)) + need (old == current) s!"JSON protocol value differs: {relative}" + else throw (IO.userError s!"fixture bytes differ: {relative} ({expected} / {actual})") + +private def unpack (directory : FilePath) : IO Unit := do + need ((← sha256 archive) == archiveSha256) "frozen adapter archive identity changed" + IO.FS.createDirAll directory + let _ ← run "tar" #["-xzf", archive, "--no-same-owner", "--no-same-permissions", "-C", directory.toString] + for row in selected do + need ((← sha256 (directory / "adapters" / row.source)) == row.sourceSha256) + s!"frozen adapter source identity changed: {row.source}" + if let some target := row.target then + need ((← sha256 target) == row.importedSha256) + s!"maintained adapter changed; review import manifest: {target}" + IO.println s!"Certified adapter provenance passed: {selected.size} frozen sources, {(selected.filter (·.target.isSome)).size} maintained ports." + +private def nativeCases := #[ + ("feature", "certified-feature-tests", none), + ("ordinary", "certified-ordinary-tests", none), + ("source", "certified-source-tests", some "inputs"), + ("fidelity", "certified-fidelity-tests", some "fidelity-inputs"), + ("claim", "certified-claim-tests", some "claim-inputs"), + ("modeled", "certified-modeled-tests", some "modeled-inputs")] + +/-- The historical host reports also recorded the separate VM pilot's +refusals. Project away exactly those two fields; all host results, record +order, source/envelope bytes and command behavior still have to match. -/ +private def hostReport (contents : String) : Except String (Array Json) := do + (contents.splitOn "\n" |>.filter (!·.isEmpty)).toArray.mapM fun line => do + let .obj fields ← Json.parse line | throw "expected a JSON object in a host test report" + return .obj (fields.erase "pilotDeclined" |>.erase "pilotDeclines") + +private def compareNative (frozen actual : FilePath) : IO Unit := do + for (label, _, _) in nativeCases do + let expected ← IO.FS.readFile (frozen / s!"evidence/c7/{label}-tests.txt") + let current ← IO.FS.readFile (actual / s!"{label}-tests.txt") + if #["feature", "ordinary", "modeled"].contains label then + need ((← IO.ofExcept (hostReport expected)) == (← IO.ofExcept (hostReport current))) + s!"native host report differs: {label}" + else + need (expected == current) s!"native report differs: {label}" + if #["source", "fidelity", "claim", "modeled"].contains label then + need ((← IO.FS.readFile (frozen / s!"evidence/c7/{label}-loader.txt")) == + (← IO.FS.readFile (actual / s!"{label}-loader.txt"))) s!"loader report differs: {label}" + for (old, current) in #[ + ("c5/inputs", "inputs"), ("c6/fidelity-inputs", "fidelity-inputs"), + ("c7/claim-inputs", "claim-inputs"), ("c7/modeled-inputs", "modeled-inputs")] do + compareTree (frozen / "evidence" / old) (actual / current) + IO.println "Native reports and all generated source/envelope fixtures match frozen adapter bytes." + +private def compareCLI (frozen actual : FilePath) : IO Unit := do + for (old, current) in #[ + ("c5/cli-inputs", "cli-source"), ("c7/claim-cli-inputs", "cli-claims"), + ("c7/modeled-cli-inputs", "cli-modeled")] do + -- The new Lean driver prints JSON differently. Compare parsed protocol + -- values; source, envelope, stdout and stderr remain byte-exact checks. + compareTree (frozen / "evidence" / old) (actual / current) true + IO.println "All CLI scenarios match the frozen inventory, protocol values, source/envelope bytes and process results." + +private def runNative (frozen output : FilePath) : IO Unit := do + for (label, executable, directory) in nativeCases do + let args := directory.toArray.map (fun item => (output / FilePath.mk item).toString) + let result ← run s!".lake/build/bin/{executable}" args + IO.FS.writeFile (output / s!"{label}-tests.txt") result.stdout + IO.FS.writeFile (output / s!"{label}-loader.txt") result.stderr + IO.println s!"Native {label} tests passed." + compareNative frozen output + +private def runCLI (frozen output : FilePath) : IO Unit := do + for (kind, inputs, target) in #[ + ("source", "inputs", "cli-source"), ("claims", "claim-inputs", "cli-claims"), + ("modeled", "modeled-inputs", "cli-modeled")] do + let result ← run ".lake/build/bin/certified-cli-tests" #[kind, + ".lake/build/bin/certified-check", ".lake/build/bin/certified-claim-check", + (output / inputs).toString, (output / target).toString] + IO.print s!"CLI {kind}: {result.stdout}" + compareCLI frozen output + +def main (args : List String) : IO UInt32 := do + match args with + | [] => + IO.FS.withTempDir fun directory => do + let frozen := directory / "frozen" + let output := directory / "actual" + unpack frozen + IO.FS.createDirAll output + runNative frozen output + runCLI frozen output + IO.println "Certified adapter checks passed." + return 0 + | ["--compare", frozen, actual] => + compareNative frozen actual + compareCLI frozen actual + return 0 + | _ => + IO.eprintln "usage: certified-adapter-tests [--compare FROZEN_DIRECTORY ACTUAL_DIRECTORY]" + return 2 + +end Tests.Certified.Check + +def main := Tests.Certified.Check.main diff --git a/Tests/Certified/Claims.lean b/Tests/Certified/Claims.lean new file mode 100644 index 000000000..b9ee1f2d5 --- /dev/null +++ b/Tests/Certified/Claims.lean @@ -0,0 +1,375 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.FeatureCases +import Tests.Certified.Source +import Ix.Certified.ClaimSuggest +import Ix.Certified.ClaimCommand +import Tests.Theory.Claims + +/-! Native tests of the versioned claim byte boundary. All hints are built +outside the checker and every outcome goes through `acceptsClaimBytes`. -/ + +namespace Tests.Certified.Claims + +open Ix.Theory Ix.Theory.Certified Ix.Theory.Model Ix.Certified Serialize +open Lean (toJson) + +set_option maxRecDepth 32768 +set_option maxHeartbeats 32000000 + +def fuel : Nat := 6400 + +def tree : List Address → Ix.AssumptionTree + | [] => .padding + | [a] => .leaf a + | a :: rest => .node (.leaf a) (tree rest) + +def optionalRoot (addresses : List Address) : Option Address := + if addresses.isEmpty then none else some (treeRoot (tree addresses)) + +def optionalBytes (addresses : List Address) : Option ByteArray := + if addresses.isEmpty then none else some (treeBytes (tree addresses)) + +structure Fixture where + name : String + source : Case + envelope : Envelope + hint : LogicalHint + witness : LogicalWitness + +def Fixture.bytes (f : Fixture) : ByteArray := envelopeBytes f.envelope +def Fixture.address (f : Fixture) : Address := Address.blake3 f.bytes +def Fixture.accepted (f : Fixture) : Bool := + acceptsClaimBytes.{0} fuel (Source.source f.source) f.address f.bytes (.logical f.witness) + +/-- Untrusted test producer computes the logical-use tree from the checked +leaf manifest. The public acceptance call independently recomputes it. -/ +def finish? (name : String) (c : Case) (claim : Ix.Claim) (hint : LogicalHint) : Option Fixture := do + let envelope : Envelope := ⟨Protocol.current, c.profile, claim, none⟩ + let source := Source.source c + let witness ← suggestLogical? fuel source envelope hint + let (snapshot, _) ← readSnapshot? fuel source hint.selection {} + let signature ← readSignature? c.profile snapshot.decodedObjects + let store ← readStore? fuel snapshot.decodedObjects snapshot.decodedNaturals + let leaves ← witness.leaves.mapM (readLeafInput? fuel snapshot.decodedObjects) + let batch ← checkBatch?.{0,0} fuel signature store witness.frontier + (leaves.map (fun leaf => leaf.prepared.node signature)) + let axioms := hint.selection.objects.filter fun address => + (subjectReferences? snapshot.decodedObjects address).any fun refs => + !refs.isEmpty && refs.all batch.logicalUses.contains + let axiomTree := optionalBytes axioms + return ⟨name, c, { envelope with logicalAxioms := optionalRoot axioms }, + { hint with axiomTree }, { witness with axiomTree }⟩ + +def single? (c : Case) : Option Fixture := + let claim : Ix.Claim := .check c.target none + finish? (c.name ++ "-check") c claim + ⟨Source.selection c, [⟨claim, none, none⟩], none, none, none, none, []⟩ + +def environment? (c : Case) : Option Fixture := + let subjects := tree (Source.subjects c) + let claim : Ix.Claim := .checkEnv (treeRoot subjects) none + finish? (c.name ++ "-environment") c claim + ⟨Source.selection c, [⟨claim, some (treeBytes subjects), none⟩], + some (treeBytes subjects), none, none, none, []⟩ + +def rejectsEnvelope (f : Fixture) (envelope : Envelope) : Bool := + let bytes := envelopeBytes envelope + !acceptsClaimBytes.{0} fuel (Source.source f.source) (Address.blake3 bytes) bytes (.logical f.witness) + +def hostile (f : Fixture) : Bool := Id.run do + let source := Source.source f.source + let check := fun w => acceptsClaimBytes.{0} fuel source f.address f.bytes (.logical w) + if !f.accepted then return false + if acceptsClaimBytes.{0} 0 source f.address f.bytes (.logical f.witness) then return false + if acceptsClaimBytes.{0} fuel source f.source.target f.bytes (.logical f.witness) then return false + let trailing := f.bytes.push 0 + if acceptsClaimBytes.{0} fuel source (Address.blake3 trailing) trailing (.logical f.witness) then return false + for protocol in [ + { Protocol.current with format := 2 }, { Protocol.current with codec := 2 }, + { Protocol.current with checker := Protocol.current.checker + 1 }, { Protocol.current with policy := 2 }, + { Protocol.current with aggregation := 2 }] do + if !rejectsEnvelope f { f.envelope with protocol } then return false + if !rejectsEnvelope f { f.envelope with profile := { f.envelope.profile with + falseType := f.source.profile.falseElim, falseElim := f.source.profile.falseType } } then return false + if check { f.witness with leaves := [] } then return false + if check { f.witness with leaves := f.witness.leaves.map fun leaf => { leaf with declarations := [] } } then + return false + if check { f.witness with selection := { f.witness.selection with + objects := f.source.target :: f.witness.selection.objects } } then return false + if check { f.witness with selection := { f.witness.selection with + objects := f.witness.selection.objects.filter (· != f.source.target) } } then return false + let forged := treeBytes (.leaf f.source.target) + if check { f.witness with frontierTree := some forged } then return false + if check { f.witness with axiomTree := some forged } then return false + if check { f.witness with leaves := f.witness.leaves.map fun leaf => + { leaf with + claim := .contains (treeRoot (.leaf f.source.target)) f.source.target, + subjects := none } } then return false + if !rejectsEnvelope f { f.envelope with claim := .eval f.source.target f.source.target none } then + return false + if f.envelope.logicalAxioms.isSome && !rejectsEnvelope f { f.envelope with logicalAxioms := none } then + return false + return true + +def diamondCase? : Option Case := + let T := (Tests.Theory.Checker.identityType (.param 0)).erase + let store := Tests.Theory.Claims.store fun n c => if n = 14 then + .defn 1 .theorem T (.app (.lam T (.bvar 0)) (.const (.member 12 0) [.param 0])) .safe else c + make? "diamond" Tests.Theory.Certified.primitives + ⟨store, 1, .const (.member 15 0) [.param 0], T⟩ + +def checkLeaf (subject : Address) (frontier : List Address) : LeafHint := + ⟨.check subject (optionalRoot frontier), none, optionalBytes frontier⟩ + +def envLeaf (subjects frontier : List Address) : LeafHint := + ⟨.checkEnv (treeRoot (tree subjects)) (optionalRoot frontier), + some (treeBytes (tree subjects)), optionalBytes frontier⟩ + +def diamond? (openFrontier : Bool := false) (catalog : Bool := false) : Option Fixture := do + let c ← diamondCase? + let a ← reference c.references (.member 12 0) + let b ← reference c.references (.member 13 0) + let d ← reference c.references (.member 14 0) + let e ← reference c.references (.member 15 0) + let specs := if openFrontier then [([b], [a]), ([d], [a]), ([e], [b, d])] + else [([a], []), ([b], [a]), ([d], [a]), ([e], [b, d])] + let leaves := specs.map fun (subjects, frontier) => + if catalog then envLeaf subjects frontier else checkLeaf subjects[0]! frontier + let content := tree (specs.flatMap Prod.fst) + let frontier := if openFrontier then [a] else [] + let members := tree (leaves.filterMap fun leaf => environmentRoot? leaf.claim) + let claim := if catalog then .catalog (treeRoot members) (treeRoot content) (optionalRoot frontier) + else .checkEnv (treeRoot content) (optionalRoot frontier) + finish? s!"diamond-{openFrontier}-{catalog}" c claim + ⟨Source.selection c, leaves, some (treeBytes content), + if catalog then some (treeBytes members) else none, optionalBytes frontier, none, []⟩ + +def diamondTests (f : Fixture) : Bool := Id.run do + if !f.accepted then return false + let source := Source.source f.source + let check := fun w => acceptsClaimBytes.{0} fuel source f.address f.bytes (.logical w) + if check { f.witness with leaves := f.witness.leaves.reverse } then return false + if check { f.witness with leaves := f.witness.leaves.drop 1 } then return false + if !check { f.witness with leaves := f.witness.leaves ++ f.witness.leaves } then return false + if check { f.witness with frontier := [] } && (claimFrontier f.envelope.claim).isSome then return false + if check { f.witness with members := f.witness.subjects } && f.witness.members.isSome then return false + return true + +def warm (f : Fixture) : Bool := Id.run do + let source := Source.source f.source + let step := Ix.Kernel.certifiedClaimStep.{0} fuel source f.address f.bytes (.logical f.witness) + let .ok _ cold := step.run Ix.Kernel.initialCertifiedState | return false + let start := { cold with checker := Source.poisonedChecker f.source } + let .ok _ cached := step.run start | return false + let size := f.witness.selection.objects.length + f.witness.selection.naturals.length + if cached.inputCache.hits != size || cached.inputCache.misses != size then return false + let .error _ failed := (Ix.Kernel.certifiedClaimStep.{0} fuel source f.address f.bytes + (.logical { f.witness with leaves := [] })).run cached | return false + if failed.inputCache.hits != cached.inputCache.hits || failed.inputCache.misses != cached.inputCache.misses then + return false + let changed := { source with consts := source.consts.erase f.source.target } + let .error _ absent := (Ix.Kernel.certifiedClaimStep.{0} fuel changed f.address f.bytes (.logical f.witness)).run failed + | return false + if absent.inputCache.hits != cached.inputCache.hits || absent.inputCache.misses != cached.inputCache.misses then + return false + let .ok _ retry := step.run absent | return false + return retry.inputCache.hits == 2 * size && retry.inputCache.misses == size && retry.checker.inferOnly + +structure WireCase where + name : String + source : Case + envelope : Envelope + hint : ClaimCommand.Hint + expected : Bool := true + +def WireCase.bytes (w : WireCase) : ByteArray := envelopeBytes w.envelope +def WireCase.request (w : WireCase) : ClaimCommand.Request := ⟨Address.blake3 w.bytes, w.hint⟩ +def WireCase.passes (w : WireCase) : Bool := + (ClaimCommand.run.{0} fuel (Source.source w.source) w.bytes w.request).isOk == w.expected + +def Fixture.wire (f : Fixture) : WireCase := ⟨f.name, f.source, f.envelope, .logical f.hint, true⟩ + +def rawFalseAlias (index : UInt64) : Ixon.MutConst := .defn { + kind := .thm, safety := .safe, lvls := 0, typ := .ref 0 #[], value := .recur index #[] } + +/-- Self-block indices make this a finite, canonically hashed source cycle; +there is no assumed collision or circular hash-address construction. -/ +def cycleCase : Case := + let block := Fixtures.encode ⟨.muts #[rawFalseAlias 1, rawFalseAlias 0], #[], #[Fixtures.profile.falseType], #[]⟩ + let a := Fixtures.encode ⟨.dPrj ⟨0, block.1⟩, #[], #[], #[]⟩ + let b := Fixtures.encode ⟨.dPrj ⟨1, block.1⟩, #[], #[], #[]⟩ + ⟨"cycle", Fixtures.profile, a.1, Fixtures.prelude ++ [block, a, b], [], + [(.member 20 0, a.1), (.member 20 1, b.1)], [(20, block.1)]⟩ + +def cycleWires? : Option (List WireCase) := do + let c := cycleCase + let a ← reference c.references (.member 20 0) + let b ← reference c.references (.member 20 1) + let left := checkLeaf a [b] + let right := checkLeaf b [a] + let one := fun leaf => LogicalHint.mk (Source.selection c) [leaf] none none leaf.frontierTree none [] + let subjects := tree [a, b] + let envelope : Envelope := ⟨Protocol.current, c.profile, .checkEnv (treeRoot subjects) none, none⟩ + let both := fun leaves => LogicalHint.mk (Source.selection c) leaves (some (treeBytes subjects)) none none none [] + return [ + (← finish? "cycle-A-assuming-B" c left.claim (one left)).wire, + (← finish? "cycle-B-assuming-A" c right.claim (one right)).wire, + ⟨"cycle-closed-AB", c, envelope, .logical (both [left, right]), false⟩, + ⟨"cycle-closed-BA", c, envelope, .logical (both [right, left]), false⟩, + ⟨"cycle-own-assumption", c, ⟨Protocol.current, c.profile, (checkLeaf a [a]).claim, none⟩, + .logical (one (checkLeaf a [a])), false⟩] + +def containsWires (c : Case) : List WireCase := + let content : Ix.AssumptionTree := .node (.leaf c.target) (.node .padding (.leaf c.profile.falseType)) + let claim := Ix.Claim.contains (treeRoot content) c.target + let envelope : Envelope := ⟨Protocol.current, c.profile, claim, none⟩ + [⟨"contains-padding", c, envelope, .contains (treeBytes content), true⟩, + ⟨"contains-absent", c, { envelope with claim := .contains (treeRoot content) c.profile.falseElim }, + .contains (treeBytes content), false⟩, + ⟨"contains-wrong-root", c, { envelope with claim := .contains c.target c.target }, + .contains (treeBytes content), false⟩, + ⟨"contains-trailing-tree", c, envelope, .contains ((treeBytes content).push 0), false⟩, + ⟨"contains-logical-axioms", c, { envelope with logicalAxioms := some (treeRoot content) }, + .contains (treeBytes content), false⟩, + ⟨"contains-as-logical", c, envelope, + .logical ⟨Source.selection c, [⟨claim, none, none⟩], none, none, none, none, []⟩, false⟩] + +def revealCtor (ctor : Ixon.Constructor) : Ix.RevealConstructorInfo := + ⟨some ctor.isUnsafe, some ctor.lvls, some ctor.cidx, some ctor.params, some ctor.fields, + some (expressionAddress ctor.typ)⟩ + +def revealCtors (ctors : Array Ixon.Constructor) : Option (Array (UInt64 × Ix.RevealConstructorInfo)) := + some (ctors.toList.zipIdx.map fun (ctor, index) => (index.toUInt64, revealCtor ctor)).toArray + +def revealRules (rules : Array Ixon.RecursorRule) : Option (Array Ix.RevealRecursorRule) := + some (rules.toList.zipIdx.map fun (rule, index) => + ⟨index.toUInt64, rule.fields, expressionAddress rule.rhs⟩).toArray + +def revealMut : Ixon.MutConst → Ix.RevealMutConstInfo + | .defn d => .defn (some d.kind) (some d.safety) (some d.lvls) + (some (expressionAddress d.typ)) (some (expressionAddress d.value)) + | .indc d => .indc (some d.isUnsafe) (some d.lvls) (some d.params) (some d.indices) + (some (expressionAddress d.typ)) (revealCtors d.ctors) + | .recr d => .recr (some d.k) (some d.isUnsafe) (some d.lvls) (some d.params) (some d.indices) + (some d.motives) (some d.minors) (some (expressionAddress d.typ)) (revealRules d.rules) + +def revealInfo : Ixon.ConstantInfo → Ix.RevealConstantInfo + | .defn d => .defn (some d.kind) (some d.safety) (some d.lvls) + (some (expressionAddress d.typ)) (some (expressionAddress d.value)) + | .recr d => .recr (some d.k) (some d.isUnsafe) (some d.lvls) (some d.params) (some d.indices) + (some d.motives) (some d.minors) (some (expressionAddress d.typ)) (revealRules d.rules) + | .axio d => .axio (some d.isUnsafe) (some d.lvls) (some (expressionAddress d.typ)) + | .quot d => .quot (some d.kind) (some d.lvls) (some (expressionAddress d.typ)) + | .cPrj d => .cPrj (some d.idx) (some d.cidx) (some d.block) + | .iPrj d => .iPrj (some d.idx) (some d.block) + | .rPrj d => .rPrj (some d.idx) (some d.block) + | .dPrj d => .dPrj (some d.idx) (some d.block) + | .muts ds => .muts (ds.toList.zipIdx.map fun (d, index) => (index.toUInt64, revealMut d)).toArray + +def corruptInfo : Ix.RevealConstantInfo → Ix.RevealConstantInfo + | .defn k s u t b => .defn k s ((u.getD 0 + 1) |> some) t b + | .recr k s u p i m n t r => .recr k s u p i (some (m.getD 0 + 1)) n t r + | .axio s u t => .axio (some (!(s.getD false))) u t + | .quot k u t => .quot k (some (u.getD 0 + 1)) t + | .cPrj i c b => .cPrj i (some (c.getD 0 + 1)) b + | .iPrj i b => .iPrj (some (i.getD 0 + 1)) b + | .rPrj i b => .rPrj (some (i.getD 0 + 1)) b + | .dPrj i b => .dPrj (some (i.getD 0 + 1)) b + | .muts ds => .muts (ds.push (100000, .defn none none none none none)) + +def revealWires? (c : Case) : Option (List WireCase) := do + let mut result := [] + for ((address, bytes), index) in c.blobs.zipIdx do + let object ← decodeObject? address bytes + let info := revealInfo object.val.info + let opening : Ixon.Comm := ⟨Address.blake3 "C6 reveal secret".toUTF8, address⟩ + let envelope : Envelope := ⟨Protocol.current, c.profile, .reveal opening.commit info, none⟩ + result := result ++ [ + ⟨s!"{c.name}-reveal-{index}", c, envelope, .reveal ⟨opening⟩, true⟩, + ⟨s!"{c.name}-reveal-altered-{index}", c, + { envelope with claim := .reveal opening.commit (corruptInfo info) }, .reveal ⟨opening⟩, false⟩, + ⟨s!"{c.name}-reveal-secret-{index}", c, envelope, + .reveal ⟨{ opening with secret := c.target }⟩, false⟩] + return result + +def hexJson (bytes : Option ByteArray) : Lean.Json := toJson (bytes.map hexOfBytes) + +def leafJson (hint : LeafHint) : Lean.Json := Lean.Json.mkObj [ + ("claim", toJson (hexOfBytes (Ix.Claim.ser hint.claim))), + ("subjects", hexJson hint.subjects), ("frontier", hexJson hint.frontierTree)] + +def requestJson (request : ClaimCommand.Request) : Lean.Json := + let fields := match request.hint with + | .logical hint => [ + ("kind", toJson "logical"), + ("objects", toJson (hint.selection.objects.map fun a => hexOfBytes a.hash)), + ("naturals", toJson (hint.selection.naturals.map fun a => hexOfBytes a.hash)), + ("leaves", toJson (hint.leaves.map leafJson)), + ("subjects", hexJson hint.subjects), ("members", hexJson hint.members), + ("frontier", hexJson hint.frontierTree), ("axioms", hexJson hint.axiomTree)] ++ + (if hint.models.isEmpty then [] else [("models", toJson (hint.models.map ModelHint.json))]) + | .contains bytes => [("kind", toJson "contains"), ("tree", toJson (hexOfBytes bytes))] + | .reveal witness => [("kind", toJson "reveal"), + ("secret", toJson (hexOfBytes witness.opening.secret.hash)), + ("payload", toJson (hexOfBytes witness.opening.payload.hash))] + Lean.Json.mkObj (("address", toJson (hexOfBytes request.address.hash)) :: fields) + +def writeWire (directory : System.FilePath) (w : WireCase) : IO Unit := do + let directory := directory / w.name + IO.FS.createDirAll directory + let .ok source := Ixon.serEnv (Source.source w.source) + | throw (IO.userError s!"cannot serialize {w.name}") + IO.FS.writeBinFile (directory / "source.ixe") source + IO.FS.writeBinFile (directory / "envelope.bin") w.bytes + IO.FS.writeFile (directory / "request.json") ((requestJson w.request).pretty ++ "\n") + IO.FS.writeFile (directory / "expected.json") + ((Lean.Json.mkObj [("accepted", toJson w.expected)]).compress ++ "\n") + +def runWire (directory : Option System.FilePath) (w : WireCase) : IO Unit := do + unless w.passes do throw (IO.userError s!"claim command outcome failed: {w.name}") + let .ok request := ClaimCommand.readRequest (requestJson w.request) + | throw (IO.userError s!"claim request parsing failed: {w.name}") + unless (ClaimCommand.run.{0} fuel (Source.source w.source) w.bytes request).isOk == w.expected do + throw (IO.userError s!"claim parsed request outcome failed: {w.name}") + if let some directory := directory then writeWire directory w + +def run (directory : Option System.FilePath) : IO Unit := do + let mut count := 0 + let mut axioms := 0 + let mut revelations := 0 + for c in Source.cases do + for (label, produce) in [("check", single?), ("environment", environment?)] do + let some f := produce c | throw (IO.userError s!"claim producer declined {c.name}/{label}") + unless f.accepted do throw (IO.userError s!"claim rejected {f.name}") + unless hostile f do throw (IO.userError s!"claim mutation escaped {f.name}") + unless warm f do throw (IO.userError s!"claim cache rollback failed {f.name}") + runWire directory f.wire + count := count + 1 + if f.envelope.logicalAxioms.isSome then axioms := axioms + 1 + let some reveals := revealWires? c | throw (IO.userError s!"reveal producer declined {c.name}") + for w in reveals do runWire directory w + revelations := revelations + reveals.length + for openFrontier in [false, true] do + for catalog in [false, true] do + let some f := diamond? openFrontier catalog | throw (IO.userError s!"diamond producer declined {openFrontier}/{catalog}") + unless diamondTests f do throw (IO.userError s!"diamond failed {f.name}") + runWire directory f.wire + let some cycles := cycleWires? | throw (IO.userError "cycle producer declined") + for w in cycles do runWire directory w + let some cycleReveals := revealWires? cycleCase | throw (IO.userError "cycle reveal producer declined") + for w in cycleReveals do runWire directory w + revelations := revelations + cycleReveals.length + for w in containsWires cycleCase do runWire directory w + IO.println <| (Lean.Json.mkObj [ + ("sourceClaimsAccepted", toJson count), ("nonemptyAxiomRoots", toJson axioms), + ("sourceMutationScenarios", toJson count), ("diamondScenarios", toJson (4 : Nat)), + ("warmClaimScenarios", toJson count), ("cycleScenarios", toJson cycles.length), + ("containsScenarios", toJson (containsWires cycleCase).length), + ("revealScenarios", toJson revelations), + ("unexpectedErrors", toJson (0 : Nat))]).compress + +end Tests.Certified.Claims diff --git a/Tests/Certified/ClaimsMain.lean b/Tests/Certified/ClaimsMain.lean new file mode 100644 index 000000000..ab82d621b --- /dev/null +++ b/Tests/Certified/ClaimsMain.lean @@ -0,0 +1,13 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.Claims + +def main (args : List String) : IO UInt32 := do + if args.length > 1 then + IO.eprintln "usage: certified-claim-tests [OUTPUT_DIRECTORY]" + return 2 + Tests.Certified.Claims.run (args.head?.map System.FilePath.mk) + return 0 diff --git a/Tests/Certified/FeatureCases.lean b/Tests/Certified/FeatureCases.lean new file mode 100644 index 000000000..52341ee1e --- /dev/null +++ b/Tests/Certified/FeatureCases.lean @@ -0,0 +1,284 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.Serialize +import Ix.Certified.Corpus +import Tests.Theory.Standard +import Tests.Theory.Quotient +import Tests.Theory.Structure +import Tests.Theory.Natural + +/-! Canonical serialized acceptance corpus. All certificates are generated +from decoded stores, and all outcomes run the independent serialized gate. -/ + +namespace Tests.Certified.Features + +open Ix.Theory Ix.Theory.Model Ix.Theory.Certified Ix.Certified Serialize +open Tests.Theory.Certified (primitives) +open Lean (toJson) + +set_option maxRecDepth 32768 +set_option maxHeartbeats 32000000 + +abbrev std := Tests.Theory.Standard.input +abbrev quo := Tests.Theory.Quotient.input +abbrev struc := Tests.Theory.Structure.input +abbrev natural := Tests.Theory.Natural.input + +structure Scenario where + name : String + input : ProofInput Nat + signature : PrimitiveSignature Nat := primitives + +def positive : List Scenario := [ + ⟨"propext", Tests.Theory.Standard.propextInput, primitives⟩, + ⟨"choice-Prop", std 0 (.const Tests.Theory.Standard.choiceRef [.zero]) + (Tests.Theory.Standard.choiceSpec.type.instL [.zero]), primitives⟩, + ⟨"choice-universe", std 1 (Tests.Theory.Standard.choiceRefl (.param 0)) + (Tests.Theory.Standard.choiceReflType (.param 0)), primitives⟩, + ⟨"choice-Type", std 0 (Tests.Theory.Standard.choiceRefl (.succ .zero)) + (Tests.Theory.Standard.choiceReflType (.succ .zero)), primitives⟩, + ⟨"choice-Type1", std 0 (Tests.Theory.Standard.choiceRefl (.succ (.succ .zero))) + (Tests.Theory.Standard.choiceReflType (.succ (.succ .zero))), primitives⟩, + ⟨"Eq-K", std 0 Tests.Theory.Standard.kProof Tests.Theory.Standard.kProposition, primitives⟩, + ⟨"Quot-sound", quo 1 (.const Tests.Theory.Quotient.refs.sound [.param 0]) + (Certified.Quotient.soundType Tests.Theory.Quotient.refs), primitives⟩, + ⟨"Quot-ind", quo 1 (.const Tests.Theory.Quotient.refs.ind [.param 0]) + (Certified.Quotient.indType Tests.Theory.Quotient.refs), primitives⟩, + ⟨"Quot-lift-universe", Tests.Theory.Quotient.betaInput, primitives⟩, + ⟨"Quot-lift-Prop", quo 0 (Tests.Theory.Quotient.betaProof .zero) + (Tests.Theory.Quotient.betaProposition .zero), primitives⟩, + ⟨"Quot-lift-Type", quo 0 (Tests.Theory.Quotient.betaProof (.succ .zero)) + (Tests.Theory.Quotient.betaProposition (.succ .zero)), primitives⟩, + ⟨"Quot-proof-universe", quo 1 (Tests.Theory.Quotient.propLiftProof (.param 0)) + (Tests.Theory.Quotient.propLiftProposition (.param 0)), primitives⟩, + ⟨"Quot-proof-Prop", quo 0 (Tests.Theory.Quotient.propLiftProof .zero) + (Tests.Theory.Quotient.propLiftProposition .zero), primitives⟩, + ⟨"Box-dependent-projection", Tests.Theory.Structure.boxInput, primitives⟩, + ⟨"Box-eta-Prop", struc Tests.Theory.Structure.box 0 (Tests.Theory.Structure.etaProof .zero) + (Tests.Theory.Structure.etaProposition .zero), primitives⟩, + ⟨"Box-eta-universe", struc Tests.Theory.Structure.box 1 (Tests.Theory.Structure.etaProof (.param 0)) + (Tests.Theory.Structure.etaProposition (.param 0)), primitives⟩, + ⟨"Pair-projection", struc Tests.Theory.Structure.pair 0 Tests.Theory.Structure.pairProof + Tests.Theory.Structure.boxProposition, primitives⟩, + ⟨"Box-field-Prop", struc Tests.Theory.Structure.box 0 (Tests.Theory.Structure.fieldProof .zero) + (Tests.Theory.Structure.fieldProposition .zero), primitives⟩, + ⟨"Box-field-Type", struc Tests.Theory.Structure.box 0 (Tests.Theory.Structure.fieldProof (.succ .zero)) + (Tests.Theory.Structure.fieldProposition (.succ .zero)), primitives⟩, + ⟨"Box-field-universe", struc Tests.Theory.Structure.box 1 (Tests.Theory.Structure.fieldProof (.param 0)) + (Tests.Theory.Structure.fieldProposition (.param 0)), primitives⟩, + ⟨"Pair-eta-Prop", struc Tests.Theory.Structure.pair 0 (Tests.Theory.Structure.pairEtaProof .zero) + (Tests.Theory.Structure.pairEtaProposition .zero), primitives⟩, + ⟨"Pair-eta-universe", struc Tests.Theory.Structure.pair 1 (Tests.Theory.Structure.pairEtaProof (.param 0)) + (Tests.Theory.Structure.pairEtaProposition (.param 0)), primitives⟩, + ⟨"Nat-zero", natural Tests.Theory.Natural.zero 0, Tests.Theory.Natural.profile⟩, + ⟨"Nat-literal", natural (Tests.Theory.Natural.numeral 4) 4, Tests.Theory.Natural.profile⟩, + ⟨"Nat-succ", natural (Tests.Theory.Natural.succ (.natLit 8)) 9, Tests.Theory.Natural.profile⟩, + ⟨"Nat-definition", natural (.const (.member 302 0) []) 3, Tests.Theory.Natural.profile⟩, + ⟨"Nat-add-zero", natural (Tests.Theory.Natural.add (.natLit 0) (.natLit 0)) 0, Tests.Theory.Natural.profile⟩, + ⟨"Nat-add", Tests.Theory.Natural.sampleInput, Tests.Theory.Natural.profile⟩, + ⟨"Nat-mul", natural (Tests.Theory.Natural.mul (.natLit 2) (.natLit 3)) 6, Tests.Theory.Natural.profile⟩, + ⟨"Nat-mul-zero", natural (Tests.Theory.Natural.mul (.natLit 5) (.natLit 0)) 0, Tests.Theory.Natural.profile⟩ +] + +#guard positive.length = 30 + +def witness? (c : Case) : Option (PreparedInput × ProofWitness Address) := do + let p ← prepare? 6400 c.profile c.target c.blobs c.literals + let w ← Ix.Theory.Certificate.proofWitness? 6400 p.signature p.input + return (p, w) + +def accepted (c : Case) : Bool := + (witness? c).any fun (_, w) => acceptsSerialized.{0} 6400 c.profile c.target c.blobs w c.literals + +#guard positive.all fun s => (make? s.name s.signature s.input).any accepted + +structure Mutation where + name : String + original : ProofInput Nat + altered : ProofInput Nat + signature : PrimitiveSignature Nat := primitives + +def mutatedSources : List Mutation := + [Tests.Theory.Standard.falseAxiom, Tests.Theory.Standard.unsafeAxiom, + Tests.Theory.Standard.wrongArity].zipIdx.map (fun (alter, i) => + ⟨s!"bad-standard-{i}", Tests.Theory.Standard.propextInput, + { Tests.Theory.Standard.propextInput with store := Tests.Theory.Standard.store alter }, primitives⟩) ++ + [Tests.Theory.Quotient.wrongKind, Tests.Theory.Quotient.wrongArity, + Tests.Theory.Quotient.falseSound, Tests.Theory.Quotient.unsafeSound, + Tests.Theory.Quotient.wrongLift].zipIdx.map (fun (alter, i) => + ⟨s!"bad-quotient-{i}", Tests.Theory.Quotient.betaInput, + { Tests.Theory.Quotient.betaInput with store := Tests.Theory.Quotient.store alter }, primitives⟩) ++ + [Tests.Theory.Structure.wrongFieldCount, Tests.Theory.Structure.wrongRecursor].zipIdx.map (fun (alter, i) => + ⟨s!"bad-structure-{i}", Tests.Theory.Structure.boxInput, + { Tests.Theory.Structure.boxInput with store := Tests.Theory.Structure.store Tests.Theory.Structure.box alter }, primitives⟩) ++ + [Tests.Theory.Natural.unsafeNat, Tests.Theory.Natural.forgedRule, + Tests.Theory.Natural.changedAdd].zipIdx.map (fun (alter, i) => + ⟨s!"bad-natural-{i}", Tests.Theory.Natural.sampleInput, + { Tests.Theory.Natural.sampleInput with store := Tests.Theory.Natural.store alter }, Tests.Theory.Natural.profile⟩) ++ + [(.member 200 0, 2), (.member 100 0, 1)].zipIdx.map (fun ((r, field), i) => + ⟨s!"bad-projection-{i}", Tests.Theory.Structure.boxInput, + { Tests.Theory.Structure.boxInput with proof := (Tests.Theory.Structure.badProjectionProof r field).erase }, primitives⟩) ++ + [⟨"bad-Nat-answer", Tests.Theory.Natural.sampleInput, + { Tests.Theory.Natural.sampleInput with proposition := + (Tests.Theory.Natural.proposition (Tests.Theory.Natural.add (.natLit 2) (.natLit 3)) (.natLit 6)).erase }, + Tests.Theory.Natural.profile⟩] + +/-- The altered bytes are validly hashed. A certificate is obtained for the +original complete declarations at these addresses and first validated on the +control input. Reusing it on the altered authenticated input must fail. -/ +def rejectsSource (m : Mutation) : Bool := Id.run do + let some c := make? m.name m.signature m.altered | return false + let some p := repaired? c m.original | return false + let some w := Ix.Theory.Certificate.proofWitness? 6400 p.signature p.input | return false + return acceptsCertified.{0,0} 6400 p.signature p.input w && + !acceptsSerialized.{0} 6400 c.profile c.target c.blobs w c.literals + +#guard mutatedSources.length = 16 +#guard mutatedSources.all rejectsSource + + +structure WitnessMutation where + scenario : Nat + name : String + alter : ProofWitness Address → ProofWitness Address + +def mapDeclarations (f : DeclarationWitness Address → DeclarationWitness Address) + (w : ProofWitness Address) : ProofWitness Address := + { w with declarations := w.declarations.map f } + +def witnessMutations : List WitnessMutation := [ + ⟨0, "standard-before-prerequisites", fun w => { w with declarations := w.declarations.reverse }⟩, + ⟨8, "quotient-missing-type", mapDeclarations fun d => match d with + | .quotient q => .quotient { q with types := q.types.drop 1 } + | other => other⟩, + ⟨8, "quotient-wrong-rule", mapDeclarations fun d => match d with + | .quotient q => .quotient { q with liftRule := q.indRule } + | other => other⟩, + ⟨8, "quotient-wrong-owner", mapDeclarations fun d => match d with + | .quotient q => .quotient { q with refs := { q.refs with ctor := q.refs.type } } + | other => other⟩, + ⟨13, "structure-without-facts", mapDeclarations fun d => match d with + | .structure s => .ordinary s.facts.block + | other => other⟩, + ⟨13, "structure-wrong-field-sorts", mapDeclarations fun d => match d with + | .structure s => .structure { s with facts := { s.facts with description := + { s.facts.description with fields := s.facts.description.fields.map fun f => { f with level := .zero } } } } + | other => other⟩, + ⟨13, "structure-dependent-rule-order", mapDeclarations fun d => match d with + | .structure s => .structure { s with iota := s.iota.reverse } + | other => other⟩, + ⟨27, "natural-without-facts", mapDeclarations fun d => match d with + | .natural n => .ordinary n + | other => other⟩ +] + +def rejectsWitness (m : WitnessMutation) : Bool := Id.run do + let some s := positive[m.scenario]? | return false + let some c := make? s.name s.signature s.input | return false + let some (_, w) := witness? c | return false + return acceptsSerialized.{0} 6400 c.profile c.target c.blobs w c.literals && + !acceptsSerialized.{0} 6400 c.profile c.target c.blobs (m.alter w) c.literals + +#guard witnessMutations.all rejectsWitness + +def naturalCase := make? "Nat-add" Tests.Theory.Natural.profile Tests.Theory.Natural.sampleInput + +def missingPin (c : Case) : Case := { c with profile := { c.profile with natType := none } } +def wrongPin (c : Case) : Case := + { c with profile := { c.profile with natType := reference c.references (.member 100 0) } } + +def rejectsProfile (alter : Case → Case) : Bool := Id.run do + let some c := naturalCase | return false + let some (_, w) := witness? c | return false + let changed := alter c + return !acceptsSerialized.{0} 6400 changed.profile changed.target changed.blobs w changed.literals + +#guard [missingPin, wrongPin].all rejectsProfile + +structure IngressMutation where + name : String + altered : Option Case + +def ingressMutations : List IngressMutation := [ + ⟨"missing-literal-blob", naturalCase.map fun c => { c with literals := [] }⟩, + ⟨"literal-bytes-under-old-hash", naturalCase.map fun c => + { c with literals := c.literals.map fun (a, bytes) => (a, bytes.push 1) }⟩, + ⟨"noncanonical-literal-new-hash", naturalCase.bind fun c => rehash? c (fun bytes => bytes.push 0)⟩, + ⟨"duplicate-literal-blob", naturalCase.map fun c => { c with literals := c.literals ++ c.literals }⟩, + ⟨"literal-in-constant-domain", naturalCase.map fun c => { c with blobs := c.blobs ++ c.literals, literals := [] }⟩, + ⟨"constant-in-literal-domain", naturalCase.bind fun c => do + let eq ← reference c.references (.member 100 0) + rehash? c id fun a source => + if a = c.target then match source.info with + | .defn d => { source with + refs := source.refs.push eq + info := .defn { d with + typ := mapLiterals source.refs.size.toUInt64 d.typ + value := mapLiterals source.refs.size.toUInt64 d.value } } + | _ => source + else source⟩, + ⟨"projection-wrapper-wrong-kind", do + let c ← make? "Box-dependent-projection" primitives Tests.Theory.Structure.boxInput + let owner ← reference c.references (.member 200 0) + rehash? c id fun a source => if a = owner then match source.info with + | .iPrj p => { source with info := .rPrj ⟨p.idx, p.block⟩ } + | _ => source + else source⟩ +] + +def rejectsIngress (m : IngressMutation) : Bool := + m.altered.any fun c => (prepare? 6400 c.profile c.target c.blobs c.literals).isNone + +#guard ingressMutations.length = 7 +#guard ingressMutations.all rejectsIngress + +def writeCase (directory : System.FilePath) (c : Case) : IO Unit := do + let directory := directory / c.name + IO.FS.createDirAll directory + for (a, bytes) in c.blobs do + IO.FS.writeBinFile (directory / s!"{hexOfBytes a.hash}.ixon") bytes + for (a, bytes) in c.literals do + IO.FS.writeBinFile (directory / s!"{hexOfBytes a.hash}.nat") bytes + let metadata := Lean.Json.mkObj [ + ("target", toJson (hexOfBytes c.target.hash)), + ("falseType", toJson (hexOfBytes c.profile.falseType.hash)), + ("falseElim", toJson (hexOfBytes c.profile.falseElim.hash)), + ("natType", toJson (c.profile.natType.map fun a => hexOfBytes a.hash)), + ("constants", toJson (c.blobs.map fun (a, _) => hexOfBytes a.hash)), + ("naturals", toJson (c.literals.map fun (a, _) => hexOfBytes a.hash))] + IO.FS.writeFile (directory / "target.json") (metadata.pretty ++ "\n") + +def run (directory : Option System.FilePath) : IO Unit := do + for s in positive do + let some c := make? s.name s.signature s.input | throw (IO.userError s!"fixture construction failed: {s.name}") + unless accepted c do throw (IO.userError s!"serialized acceptance failed: {s.name}") + if let some directory := directory then writeCase directory c + for m in mutatedSources do + unless rejectsSource m do throw (IO.userError s!"source rejection failed: {m.name}") + if let some directory := directory then + let some c := make? m.name m.signature m.altered | throw (IO.userError s!"mutation construction failed: {m.name}") + writeCase directory c + for m in witnessMutations do + unless rejectsWitness m do throw (IO.userError s!"witness rejection failed: {m.name}") + for (name, alter) in [("missing-Nat-pin", missingPin), ("wrong-Nat-pin", wrongPin)] do + unless rejectsProfile alter do throw (IO.userError s!"profile rejection failed: {name}") + if let some directory := directory then + let some c := naturalCase | throw (IO.userError "natural fixture construction failed") + writeCase directory { (alter c) with name } + for m in ingressMutations do + unless rejectsIngress m do throw (IO.userError s!"ingress rejection failed: {m.name}") + if let some directory := directory then + let some c := m.altered | throw (IO.userError s!"ingress mutation construction failed: {m.name}") + writeCase directory { c with name := m.name } + IO.println <| (Lean.Json.mkObj [ + ("serializedAccepted", toJson positive.length), + ("sourceRejectedWithValidWitness", toJson mutatedSources.length), + ("forgedWitnessRejected", toJson witnessMutations.length), + ("profileRejected", toJson (2 : Nat)), + ("ingressRejected", toJson ingressMutations.length), + ("unexpectedErrors", toJson (0 : Nat))]).compress + +end Tests.Certified.Features diff --git a/Tests/Certified/Features.lean b/Tests/Certified/Features.lean new file mode 100644 index 000000000..4b1be4415 --- /dev/null +++ b/Tests/Certified/Features.lean @@ -0,0 +1,13 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.FeatureCases + +def main (args : List String) : IO UInt32 := do + if args.length > 1 then + IO.eprintln "usage: certified-feature-tests [OUTPUT_DIRECTORY]" + return 2 + Tests.Certified.Features.run (args.head?.map System.FilePath.mk) + return 0 diff --git a/Tests/Certified/Fidelity.lean b/Tests/Certified/Fidelity.lean new file mode 100644 index 000000000..ff5a89e65 --- /dev/null +++ b/Tests/Certified/Fidelity.lean @@ -0,0 +1,132 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.Source +import Ix.Certified.SourceMeaning + +namespace Tests.Certified.Fidelity + +open Ix.Theory Ix.Theory.Certified Ix.Certified Ix.Kernel Serialize +open Lean (toJson) + +set_option maxRecDepth 32768 +set_option maxHeartbeats 32000000 + +def whole (source : Ixon.Constant) : Ixon.Constant := + match source.info with + | .defn value => { source with + info := .defn { value with typ := .share 0, value := .share 1 }, + sharing := #[value.typ, value.value] } + | _ => source + +def base := whole Fixtures.identity + +def nested : Ixon.Constant := + match base.info with + | .defn value => { base with + info := .defn { value with typ := .share 2, value := .share 3 }, + sharing := base.sharing ++ #[.share 0, .share 1] } + | _ => base + +def permuted : Ixon.Constant := + match base.info with + | .defn value => { base with + info := .defn { value with typ := .share 1, value := .share 0 }, + sharing := #[Corpus.idBody 0, Corpus.idType 0] } + | _ => base + +def underBinders : Ixon.Constant := + match base.info with + | .defn value => { base with + info := .defn { value with + typ := .leanAll (.sort 0) (.share 0), value := .leanLam (.sort 0) (.share 1) }, + sharing := #[.leanAll (.var 0) (.var 1), .leanLam (.var 0) (.var 0)] } + | _ => base + +def input (name : String) (source : Ixon.Constant) (dependencies : List Ixon.Constant := []) : Case := + let c := Corpus.one name source dependencies + { name, profile := Fixtures.profile, target := c.target, blobs := c.blobs, + literals := [], references := [], blocks := c.blobs.map fun (a, _) => (0, a) } + +def positive : List Case := [ + input "sharing-whole-identity" base, + input "sharing-nested-identity" nested, + input "sharing-permuted-identity" permuted, + input "sharing-under-binders" underBinders, + input "sharing-beta-statement" (whole Corpus.betaStatement), + input "sharing-eta-statement" (whole Corpus.etaStatement), + input "sharing-dependent-polymorphic" (whole (Corpus.dependent 1 (.var 0))), + input "sharing-defined-polymorphic-use" (whole (Corpus.polyUse .defn true)) [Corpus.polyId .defn] +] + +#guard positive.length = 8 +#guard positive.all Source.accepted +#guard positive.all Source.storeAccepted +#guard positive.all Source.ixeAccepted +#guard positive.all Source.warmAndRollback + +def negative : List Case := [ + input "sharing-out-of-bounds" { base with sharing := #[.share 999, Corpus.idBody 0] }, + input "sharing-self-cycle" { base with sharing := #[.share 0, Corpus.idBody 0] }, + input "sharing-mutual-cycle" { base with sharing := #[.share 1, .share 0] }, + input "sharing-altered-statement" { base with + sharing := #[.ref 0 #[], Corpus.idBody 0], refs := #[Fixtures.falseObject.1] }, + input "sharing-linear-body" { base with + sharing := #[Corpus.idType 0, .lam .linear (.sort 0) (.leanLam (.var 0) (.var 0))] }, + input "sharing-missing-universe" { base with univs := #[] }, + input "sharing-free-variable" { base with sharing := #[Corpus.idType 0, .var 0] }, + input "sharing-missing-reference" { base with sharing := #[Corpus.idType 0, .ref 999 #[]] } +] + +/-- The control certificate checks the complete original declaration at the +altered address. It is then submitted to the actual authenticated source +gate, so witness-search refusal cannot explain these rejections. -/ +def validControlRejected (c : Case) : Bool := Id.run do + let some objects := decodeObjects? c.blobs | return false + let original := objects.map fun (a, value) => (a, if a = c.target then base else value) + let some signature := readSignature? c.profile original | return false + let some prepared := readProofInput? 6400 original c.target | return false + let some witness := Ix.Theory.Certificate.proofWitness? 6400 signature prepared | return false + return acceptsCertified.{0,0} 6400 signature prepared witness && + !acceptsCertifiedSource.{0} 6400 (Source.source c) c.profile c.target (Source.selection c) witness && + !acceptsCertifiedStoreSource.{0} 6400 (Source.source c) c.profile [c.target] (Source.selection c) witness.declarations + +#guard negative.length = 8 +#guard negative.all validControlRejected + +/-- Equal expanded statements do not identify their different wire encodings. +The current bytes must still authenticate under the exact requested address. -/ +def distinctEncoding : Bool := Id.run do + let first := input "first" base + let second := input "second" permuted + if first.target = second.target then return false + let some a := prepare? 6400 first.profile first.target first.blobs | return false + let some b := prepare? 6400 second.profile second.target second.blobs | return false + if a.input.proposition != b.input.proposition then return false + let some witness := suggestSource? 6400 (Source.source first) first.profile first.target (Source.selection first) + | return false + let some value := (Source.source second).consts.get? second.target | return false + let changed := { (Source.source first) with + consts := (Source.source first).consts.insert first.target value } + return !acceptsCertifiedSource.{0} 6400 changed first.profile first.target (Source.selection first) witness + +#guard distinctEncoding + +def run (directory : Option System.FilePath) : IO Unit := do + for c in positive do + unless Source.accepted c && Source.storeAccepted c && Source.ixeAccepted c && Source.warmAndRollback c do + throw (IO.userError s!"source fidelity acceptance failed: {c.name}") + if let some directory := directory then Source.writeCase directory c + for c in negative do + unless validControlRejected c do throw (IO.userError s!"source fidelity mutation escaped: {c.name}") + if let some directory := directory then Source.writeCase directory c + unless distinctEncoding do throw (IO.userError "semantic equality was used as byte identity") + IO.println <| (Lean.Json.mkObj [ + ("proofAccepted", toJson positive.length), ("storesAccepted", toJson positive.length), + ("ixeAccepted", toJson positive.length), ("warmProofScenarios", toJson positive.length), + ("validControlSourceMutationsRejected", toJson negative.length), + ("distinctEncodingRejected", toJson distinctEncoding), ("unexpectedErrors", toJson (0 : Nat))]).compress + +end Tests.Certified.Fidelity diff --git a/Tests/Certified/FidelityMain.lean b/Tests/Certified/FidelityMain.lean new file mode 100644 index 000000000..3076e1835 --- /dev/null +++ b/Tests/Certified/FidelityMain.lean @@ -0,0 +1,13 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.Fidelity + +def main (args : List String) : IO UInt32 := do + if args.length > 1 then + IO.eprintln "usage: certified-fidelity-tests [OUTPUT_DIRECTORY]" + return 2 + Tests.Certified.Fidelity.run (args.head?.map System.FilePath.mk) + return 0 diff --git a/Tests/Certified/ImportManifest.lean b/Tests/Certified/ImportManifest.lean new file mode 100644 index 000000000..64ebc47de --- /dev/null +++ b/Tests/Certified/ImportManifest.lean @@ -0,0 +1,82 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +/-! Frozen certified adapter identities. The archive includes the original +patches, source identities, reports and differential corpora. Maintained code +uses Ix.Theory and Ix.Kernel; five audits now traverse full checked declarations. +The historical VM pilot, packet encoder, VM test and native profiling counters +are preserved in the archive for a later change. Host tests omit the +pilot-specific assertions; maintained hashes record all local adaptations. -/ + +namespace Tests.Certified.ImportManifest + +def archive : String := "Tests/Fixtures/Certified/c7-handoff.tar.gz" +def archiveSha256 : String := "94d7b43e2942f9a9f5c3407964905beddb834b8223ce9eb52d8df494fb17faf0" +def ixBaseRevision : String := "3e7586a7adb0c6f3cd3ff5854da832701288ec90" + +structure SourceFile where + source : String + target : Option String + sourceSha256 : String + importedSha256 : String + deriving Repr + +def selected : Array SourceFile := #[ + ⟨"Ix/Certified/Audit.lean", some "Ix/Certified/Audit.lean", "06635e487e0db2bbe57f110245c0dc6e2a9c633ebfe074797567e114da8aec52", "793ea6e189ab20f68120c58d4d5483c08124715c67ffa511424c1522e249080f"⟩, + ⟨"Ix/Certified/Bytes.lean", some "Ix/Certified/Bytes.lean", "5b01039400a830a3f80420cb011cb76c6a52511b901905f4bf7f811e19986328", "278a9cd43907eeb885e1db5c672b227d59a15713f73317941df09a3d5ca61046"⟩, + ⟨"Ix/Certified/ClaimAccept.lean", some "Ix/Certified/ClaimAccept.lean", "0c179bd4ea2c1a9d8a3b239ffe2feb60b88038f8f9f09c5d9fd8e1e83011f981", "198d8b9b436b937c311bf7ae7e47d4523bdc80022447e42dcc03a131fb01ef38"⟩, + ⟨"Ix/Certified/ClaimAudit.lean", some "Ix/Certified/ClaimAudit.lean", "8916803f12bb53e22fa1c94318a6b2a736ec9634ffae811f710b579d3d278bf4", "363f6524397b56c2225d2bdc5cadee29522959d043cfa8a5ace854078a5c30bb"⟩, + ⟨"Ix/Certified/ClaimCheck.lean", some "Ix/Certified/ClaimCheck.lean", "e4d598badcb189897a339e187b9529658e2ef75445645e1463704cc6b349a196", "8f8f6c94581ed08c8b8b00d3157bd351e7aed29cd8aa53e491cb53dc48e8845f"⟩, + ⟨"Ix/Certified/ClaimCommand.lean", some "Ix/Certified/ClaimCommand.lean", "8f360b0d0a586ab15e3b8bb3a375f5dc56ad6157344295a67673d876bf8650eb", "e053cb7bab6e1ca19e36de92bcb44c60be9764fc30ab160b92224f4703a4fb4d"⟩, + ⟨"Ix/Certified/ClaimInput.lean", some "Ix/Certified/ClaimInput.lean", "d2d0df3ef446690600e843c84683a8f2056e1d8a843a523fc57b550763963f32", "861b0cfd3a1dac9c683dbd1b71088065a00d9a47be9ddbdce304722271027451"⟩, + ⟨"Ix/Certified/ClaimMain.lean", some "Ix/Certified/ClaimMain.lean", "ed1f1b0edaec4e0928d90a814f35673a8989e55037c9cc023a6e0e287c7574e7", "ed1f1b0edaec4e0928d90a814f35673a8989e55037c9cc023a6e0e287c7574e7"⟩, + ⟨"Ix/Certified/ClaimMeaning.lean", some "Ix/Certified/ClaimMeaning.lean", "78edb69d209768d8010b28b16d334fd2fa8bc6225490f9b2bbe5fd66cc906f36", "5f2550f0235fe84927d654a360a4298f426e7ca2e7911245c84f91dbd11eef6f"⟩, + ⟨"Ix/Certified/ClaimSuggest.lean", some "Ix/Certified/ClaimSuggest.lean", "5f83e6b65542661c4efacd6389c5c6ca0a0eeaffb2d0d24cb58168be514a10f6", "285ed4b14540aa47afa67e28f20bc44e7fdce93fd94d0742971711f15df8336b"⟩, + ⟨"Ix/Certified/Command.lean", some "Ix/Certified/Command.lean", "f9f8a32be2761dc97bf7215585cde40b0e310153482707a570f7c1a106252abe", "c6803f699ed2edd6508e2db73b55f4abb163f6425bcf6b755da11b885991ad17"⟩, + ⟨"Ix/Certified/Corpus.lean", some "Ix/Certified/Corpus.lean", "fc1d66c81430461bed9e0045e6a26a1e01c85de90854eccea2343f24fe5dde97", "fc1d66c81430461bed9e0045e6a26a1e01c85de90854eccea2343f24fe5dde97"⟩, + ⟨"Ix/Certified/Envelope.lean", some "Ix/Certified/Envelope.lean", "da0269803ff6f48c6d0347627d57a7f7699c0ea06e54f959406e3d8570a326f1", "da0269803ff6f48c6d0347627d57a7f7699c0ea06e54f959406e3d8570a326f1"⟩, + ⟨"Ix/Certified/Fixtures.lean", some "Ix/Certified/Fixtures.lean", "fe7a503a0e436a2ecf924b48d9b66ed3f6ef901c7bcbe6098853c62c7748675a", "f85f883f498cdee55ab674876dd1fb19bae5dbe8aa729118cffd29ab626c8b25"⟩, + ⟨"Ix/Certified/Ingress.lean", some "Ix/Certified/Ingress.lean", "1fe00c0a512ae94fddd2847196f1bafa415ff2c452412f0e69e9e060883dd0cf", "afd9e82827fed62d453c3979fbfdb1238f83573f19af3b6728574f97ff1a86a4"⟩, + ⟨"Ix/Certified/Ixon.lean", some "Ix/Certified/Ixon.lean", "9b7f0d64f08c03ed3a215ff5b23e136bd85c71f953e9198fb940b597d7b54410", "5e37eaa6b5cb872edad7954cde413706f30996950c71d21417174f8166377bcb"⟩, + ⟨"Ix/Certified/Main.lean", some "Ix/Certified/Main.lean", "c571357f5e1120efbe23c7db4906fc3eeaebffccf2956e1899212494800d38a5", "c571357f5e1120efbe23c7db4906fc3eeaebffccf2956e1899212494800d38a5"⟩, + ⟨"Ix/Certified/ModelHints.lean", some "Ix/Certified/ModelHints.lean", "74fd6763d56ac5c8aa9af4507172879739c2dc681969a3f342aadbc30ab27837", "de098f48fc03893643c8de08c3bf2bed315f91767c71e9e229816784abb8f124"⟩, + ⟨"Ix/Certified/ModeledAudit.lean", some "Ix/Certified/ModeledAudit.lean", "55101ebfee84fd89e4c99f08d88aac7edb7000302ef6d022a8c639e331fb3ec2", "c37969f6a69e11d62547bc91b685695cd08f002c115db70a05069f34fe111de1"⟩, + ⟨"Ix/Certified/Native.lean", none, "7b617483cbeef932b9caaf6ca3e118be93e5621aaf1ca6bb8132821b336b1c82", ""⟩, + ⟨"Ix/Certified/Packet.lean", none, "a694ff77c95d6fe3bd31b99e28597769604b901926d4e0a3dfea7802fb57711d", ""⟩, + ⟨"Ix/Certified/Reveal.lean", some "Ix/Certified/Reveal.lean", "2d31e94a72208eddbd52e51ff819131430e374403e8411a9fd90b909f965af2b", "2d31e94a72208eddbd52e51ff819131430e374403e8411a9fd90b909f965af2b"⟩, + ⟨"Ix/Certified/SourceAudit.lean", some "Ix/Certified/SourceAudit.lean", "fb916b0e7eede60d3d225d7fd8045acf175dc327e83c8705379fd01a52c7866f", "c945ca007d28ad54bcceb25c5d3dafd38029ea2280b7f22a7e85d57f637ecbb6"⟩, + ⟨"Ix/Certified/SourceExpr.lean", some "Ix/Certified/SourceExpr.lean", "f4de024bc68cb991bbad57bbe0d1c147cfe32329fb9a34dc91a4dbde1177f805", "03417c4f256de2158e71407560d60abeaf77bbacd00533654c67c9c5b4f63334"⟩, + ⟨"Ix/Certified/SourceMeaning.lean", some "Ix/Certified/SourceMeaning.lean", "69f916348389e4e7d93b67b3d2c3d8abf8e30b89b417de828620627c6012209a", "f96eedf1b7d46564f6c3abf0bf3450bffb5ffca85a68071f567d75837c84ee14"⟩, + ⟨"Ix/Certified/SourceStore.lean", some "Ix/Certified/SourceStore.lean", "7b963da22cb0d2199ce4bf02353cfff0a6e8a3d571a82e19b3c9edb99336d545", "390d260608e9f4f638758751306e1cf06d4a129379a4ebcf902f5873969d832d"⟩, + ⟨"Ix/Certified/Store.lean", some "Ix/Certified/Store.lean", "23cd4434c7e1f1784a438bdeecd66378bda1ad280f28f452cb6d51443dd7e3be", "86394770b2c96176e7478a6cdd64bc0a1057b30968b4301030ffdb59751ad733"⟩, + ⟨"Ix/Certified/Suggest.lean", some "Ix/Certified/Suggest.lean", "cec35a4826b6b6d55bbcf62563d99d192bcb511a25c9d00be7d4341c64189d53", "214b6a2652c46ee93720a8a6f017268f7f06173cfa2e146ce6c067f08b0fa861"⟩, + ⟨"Ix/Certified/TcAudit.lean", some "Ix/Certified/TcAudit.lean", "a0c0177157fa1a4a891f80e3aa437901a48c2c3814bc66cb26eeaaf5808f6862", "912cae64335baa42740fffea5e26035f4a90bd107fe2e17c603d3071a623e00a"⟩, + ⟨"Ix/Certified/Trees.lean", some "Ix/Certified/Trees.lean", "cf96fa2ee3ea6263c62c630c848b8f90449d8380a454ba291ed5e7e67011c3a5", "cf96fa2ee3ea6263c62c630c848b8f90449d8380a454ba291ed5e7e67011c3a5"⟩, + ⟨"Ix/IxVM/Certified/Accept.lean", none, "8c35df5d77369c3bc77747fa872399da1b9709fdfb53f28623809cea60637e71", ""⟩, + ⟨"Ix/IxVM/Certified/Checker.lean", none, "7da05836aa7701570a6cc35c0dd856ff0ce1b09cfbce58cbec942e9a066c76a3", ""⟩, + ⟨"Ix/IxVM/Certified/Expr.lean", none, "63906b989d6ade2f3a8b72c3e84c68e887a857227a9f3bacf6a94a6c873a9a1b", ""⟩, + ⟨"Ix/IxVM/Certified/Levels.lean", none, "c59aea708f0ef66dc61d32754fa3956e597268514917546cd9ce48a1cce71be4", ""⟩, + ⟨"Ix/IxVM/Certified/Read.lean", none, "6e25a90521af8c0dc1ba9dfb9c849a2dd4e95854484688461f1962c85f1bc650", ""⟩, + ⟨"Ix/IxVM/Certified/Types.lean", none, "a5bc3333435eee693e5c2af7b444c4ea5de8ca56f9aed37dde6e80f23690a87a", ""⟩, + ⟨"Ix/Tc/Certified.lean", some "Ix/Kernel/Certified.lean", "ef7be3a4a372fe1c781c4d3e407fd14c55ba0f9289392ab7e8ab5806972ad90b", "cf7d2b617336af369fa5678bcfede46c6e4a9a06f91d5334c8b7b8a6a3b85f2c"⟩, + ⟨"Ix/Tc/CertifiedClaims.lean", some "Ix/Kernel/CertifiedClaims.lean", "ef79fbdc511c9ae90b729e639f0d57a54f68e40caab1f66d84ebba35501a30a6", "fa6d66105ade421b155c76165f7ad77c900313120e8436ce563b16e0f2451421"⟩, + ⟨"Tests/Certified/Claims.lean", some "Tests/Certified/Claims.lean", "1a678f07b5645c1f88ff07028793663c37ab74164759953dab5a2a3e311c6a22", "1b358ef41f6b701ca1dad5f309f65e9931a2fe120aa5e22f4feae7500535db49"⟩, + ⟨"Tests/Certified/ClaimsMain.lean", some "Tests/Certified/ClaimsMain.lean", "01f900c1a61940910c7131fc42a3757d2f7ea1a508f55668f6d54da8ee6eb136", "01f900c1a61940910c7131fc42a3757d2f7ea1a508f55668f6d54da8ee6eb136"⟩, + ⟨"Tests/Certified/FeatureCases.lean", some "Tests/Certified/FeatureCases.lean", "d68e7731b4864cdf823bdcf94af492158bf8f9a4da3d5dcfc659cf8582795591", "2478888475a43b4d4e07f4d07910f765788870568b96ec282afba6153e44cdeb"⟩, + ⟨"Tests/Certified/Features.lean", some "Tests/Certified/Features.lean", "65b70e67a51698b4921c6592419658e8b528ac544cdd1b0fedc84a69effa9470", "65b70e67a51698b4921c6592419658e8b528ac544cdd1b0fedc84a69effa9470"⟩, + ⟨"Tests/Certified/Fidelity.lean", some "Tests/Certified/Fidelity.lean", "7d8fdea26a63bc94ace55943f6c062340ab3b263867ecd21705c70b288784946", "b64958afa2dfbdb90de98f6a0908a8aa18c78f944bcfd6060db317636c8c4f9a"⟩, + ⟨"Tests/Certified/FidelityMain.lean", some "Tests/Certified/FidelityMain.lean", "47dbf7899235312d4ea171879940cf6eb98028eccbbdaeaa86b8a41a6449bb17", "47dbf7899235312d4ea171879940cf6eb98028eccbbdaeaa86b8a41a6449bb17"⟩, + ⟨"Tests/Certified/ModelSerialize.lean", some "Tests/Certified/ModelSerialize.lean", "d470f6a95bc48ccc65f141d90abb99d2211ba82b9fa3b9d13e42f7698c755f2b", "86f064fcdd3940bd1385463a6ad65e2a455e5de8950eb025ffbae0397c8cd3e2"⟩, + ⟨"Tests/Certified/Modeled.lean", some "Tests/Certified/Modeled.lean", "772dcd81eee47d73bbd40b25d068ce4e2f209df6fe22740db456c0b5e6e6353a", "ef4a5257a39154724a8c0c7d0c105aff571cec119353e14309e236f577cc1eb7"⟩, + ⟨"Tests/Certified/ModeledAdversarial.lean", some "Tests/Certified/ModeledAdversarial.lean", "6147577fa6afdf0b2f05813462c99c32846443717eaea86cfbf6547d42b82e42", "ec7a790339751ba9c0e4760de959faa8eaa4682c50d3afd06d8cacfe57df2dcf"⟩, + ⟨"Tests/Certified/ModeledMain.lean", some "Tests/Certified/ModeledMain.lean", "459171f71e7d845d1aadead559b1224a07b4d86e9be7ff97f5182fd1a88b974d", "459171f71e7d845d1aadead559b1224a07b4d86e9be7ff97f5182fd1a88b974d"⟩, + ⟨"Tests/Certified/Ordinary.lean", some "Tests/Certified/Ordinary.lean", "59cbe0be253cda1854481989f9d02d44624db0fa3493dd7dac9cdf68480e0684", "804eca674eb8e663429a74de6710dc612d110c4dbc892da8fa6e6f08a4ac52ba"⟩, + ⟨"Tests/Certified/Serialize.lean", some "Tests/Certified/Serialize.lean", "ef9286ca27377f034c97e8549e91484e67612aeb83dc0baf1926dff640d07f74", "593acdcb84d7d350bc258df2ad841233e946bf123583f844b516a45669a71af2"⟩, + ⟨"Tests/Certified/Source.lean", some "Tests/Certified/Source.lean", "78a98301be394278ad90d55599aa1deba55f9463b735626c4cc1965a01200ce0", "703c39031d8211f9d156039e03ede0a5e81adb2b955932596421b2fa6686a31a"⟩, + ⟨"Tests/Certified/SourceMain.lean", some "Tests/Certified/SourceMain.lean", "5a07d03d9f3e37b5e6e3fd84af66241c2e530054fa01c8157a8f938172c84d58", "5a07d03d9f3e37b5e6e3fd84af66241c2e530054fa01c8157a8f938172c84d58"⟩, + ⟨"Tests/Certified/VM.lean", none, "7699c996e3238243314318ef63c7e4436bce81264420d9db231b19535552a828", ""⟩ +] + +end Tests.Certified.ImportManifest diff --git a/Tests/Certified/ModelSerialize.lean b/Tests/Certified/ModelSerialize.lean new file mode 100644 index 000000000..6f7709f0b --- /dev/null +++ b/Tests/Certified/ModelSerialize.lean @@ -0,0 +1,113 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.Serialize +import Ix.Certified.ModelHints + +/-! General test serializer for complete mutual blocks, including recursors +and every public member/constructor projection. All model declarations are +ordinary source objects in the same authenticated .ixe environment. -/ + +namespace Tests.Certified.ModelSerialize + +open Ix.Theory Ix.Theory.Certified Ix.Certified Serialize + +def mutualInfo (self : Nat) (resolve : ConstRef Nat → Option Address) (source : Const Nat) : + Write Ixon.MutConst := do + match ← constantInfo self resolve source with + | .muts #[.indc family] => return .indc family + | .defn definition => return .defn definition + | .recr recursor => return .recr recursor + | _ => failure + +def block (self : Nat) (resolve : ConstRef Nat → Option Address) (source : Block Nat) : + Option (Ixon.Constant × ConstantBlobs) := do + let action : Write Ixon.ConstantInfo := match source.members with + | [member] => constantInfo self resolve member + | [] => failure + | members => return .muts (← members.mapM (mutualInfo self resolve)).toArray + let (info, tables) ← action {} + return (⟨info, #[], tables.refs, tables.univs⟩, tables.literals) + +def memberProjection? (kind : ConstKind) (index : Nat) (address : Address) : Option Ixon.Constant := + match kind with + | .induct => some ⟨.iPrj ⟨index.toUInt64, address⟩, #[], #[], #[]⟩ + | .recursor => some ⟨.rPrj ⟨index.toUInt64, address⟩, #[], #[], #[]⟩ + | .defn _ => some ⟨.dPrj ⟨index.toUInt64, address⟩, #[], #[], #[]⟩ + | _ => none + +/-- The finite domain is in source dependency order; unused empty slots are +omitted. Every nonempty member and source field is serialized literally. -/ +def make? (name : String) (signature : PrimitiveSignature Nat) (input : ProofInput Nat) : Option Case := do + if 900 ∈ input.store.dom then none else do + let mut blobs : ConstantBlobs := [] + let mut literals : ConstantBlobs := [] + let mut references : List (ConstRef Nat × Address) := [] + let mut blocks : List (Nat × Address) := [] + for b in input.store.dom do + let source ← input.store.blocks b + if !source.members.isEmpty then + let (raw, extra) ← block b (reference references) source + let encoded := Fixtures.encode raw + blobs := blobs ++ [encoded] + literals := literals ++ extra + blocks := blocks ++ [(b, encoded.1)] + for (member, index) in source.members.zipIdx do + let address ← match raw.info with + | .muts _ => do + let projection ← memberProjection? member.kind index encoded.1 + let projection := Fixtures.encode projection + blobs := blobs ++ [projection] + pure projection.1 + | _ => pure encoded.1 + references := references ++ [(.member b index, address)] + match member with + | .induct _ _ _ _ ctors _ => + for ctor in List.range ctors.length do + let projection := Fixtures.encode ⟨.cPrj ⟨index.toUInt64, ctor.toUInt64, encoded.1⟩, #[], #[], #[]⟩ + blobs := blobs ++ [projection] + references := references ++ [(.ctor b index ctor, projection.1)] + | _ => pure () + let (raw, extra) ← constant 900 (reference references) + (.defn input.universes .theorem input.proposition input.proof .safe) + let target := Fixtures.encode raw + let falseType ← reference references signature.falseType + let falseElim ← reference references signature.falseElim + let natType ← signature.natType.mapM (reference references) + return ⟨name, ⟨falseType, falseElim, natType⟩, target.1, uniqueBlobs (blobs ++ [target]), + uniqueBlobs (literals ++ extra), references ++ [(.member 900 0, target.1)], blocks ++ [(900, target.1)]⟩ + +def hint? (c : Case) (candidate : Certificate.Modeled.Candidate Nat) : Option ModelHint := do + let source ← ((c.blocks.find? (fun (key, _) => key = candidate.source)).map Prod.snd) + let recursors ← candidate.recursors.mapM (reference c.references) + let targets ← candidate.models.mapM (reference c.references) + let proofs ← candidate.proofs.mapM fun (owner, proofs) => do + let owner ← reference c.references owner + let proofs ← proofs.mapM fun proof => proof.mapM fun proof => do + let .const term _ := proof.proof | none + return (⟨← reference c.references proof.equality, ← reference c.references proof.reflexivity, + ← reference c.references proof.recursor, ← reference c.references term⟩ : ModelProofHint) + return (⟨owner, proofs⟩ : ModelRuleHints) + return ⟨source, recursors, targets, proofs⟩ + +/-- Reconstruct every original mutual member at the mutated wire addresses. +This deliberately unauthenticated control is used only to obtain a complete, +valid certificate before attacking the authenticated acceptance gate. -/ +def repaired? (c : Case) (original : ProofInput Nat) : Option PreparedInput := do + let prepared ← prepare? 6400 c.profile c.target c.blobs c.literals + let mapping := fun b => ((c.blocks.find? fun (key, _) => key = b).map Prod.snd).getD c.target + let originals := c.blocks.map fun (b, a) => (a, (if b = 900 then + some (⟨[.defn original.universes .theorem original.proposition original.proof .safe]⟩ : Block Nat) + else original.store.blocks b).map (fun source => + (⟨source.members.map (renameConstant mapping)⟩ : Block Address))) + let old := prepared.input.store + let store : Store Address := { + dom := old.dom, nodup := old.nodup, + blocks := fun a => (old.blocks a).map fun block => ((lookup originals a).join).getD block, + mem_dom := by intro a; simp [old.mem_dom] } + let .defn _ _ proposition proof _ ← store.lookup (.member c.target 0) | none + return { prepared with input := { prepared.input with store, proposition, proof } } + +end Tests.Certified.ModelSerialize diff --git a/Tests/Certified/Modeled.lean b/Tests/Certified/Modeled.lean new file mode 100644 index 000000000..6afd6f9a5 --- /dev/null +++ b/Tests/Certified/Modeled.lean @@ -0,0 +1,140 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.FeatureCases +import Tests.Certified.ModelSerialize +import Tests.Certified.Claims +import Ix.Certified.Command +import Tests.Theory.ModeledNested +import Tests.Theory.ModeledPermutation +import Tests.Theory.ModeledEquations + +/-! Modeled inductive tests exercise canonical mutual Ixon blocks, lazy .ixe loading, +checked model declarations, public TcM execution and versioned claims. -/ + +namespace Tests.Certified.Modeled + +open Ix.Theory Ix.Theory.Certified Ix.Certified Ix.Kernel Serialize +open Tests.Theory.Certified (primitives) +open Lean (toJson) + +set_option maxRecDepth 32768 +set_option maxHeartbeats 64000000 + +def fuel := 6400 + +structure Scenario where + name : String + input : ProofInput Nat + candidate : Certificate.Modeled.Candidate Nat + +def scenarios : List Scenario := [ + ⟨"mutual-unequal", Tests.Theory.Modeled.input, Tests.Theory.Modeled.candidate⟩, + ⟨"mutual-permuted", Tests.Theory.ModeledPermutation.input, Tests.Theory.ModeledPermutation.candidate⟩, + ⟨"auxiliary-merged", Tests.Theory.ModeledPermutation.mergedInput, Tests.Theory.ModeledPermutation.mergedCandidate⟩, + ⟨"nested-parameter", Tests.Theory.ModeledNested.input false, Tests.Theory.ModeledNested.candidate⟩, + ⟨"nested-recursive-Pi", Tests.Theory.ModeledNested.input true, Tests.Theory.ModeledNested.candidate⟩, + ⟨"propositional-equations", Tests.Theory.ModeledEquations.input, Tests.Theory.ModeledEquations.candidate⟩] + +structure Fixture where + scenario : Scenario + source : Case + model : ModelHint + +def fixture? (scenario : Scenario) : Option Fixture := do + let source ← ModelSerialize.make? scenario.name primitives scenario.input + let model ← ModelSerialize.hint? source scenario.candidate + return ⟨scenario, source, model⟩ + +def Fixture.request (f : Fixture) : Command.Request := + ⟨f.source.profile, f.source.target, Source.subjects f.source, Source.selection f.source, [f.model]⟩ + +def requestJson (request : Command.Request) : Lean.Json := Lean.Json.mkObj [ + ("falseType", toJson (hexOfBytes request.profile.falseType.hash)), + ("falseElim", toJson (hexOfBytes request.profile.falseElim.hash)), + ("natType", toJson (request.profile.natType.map (hexOfBytes ·.hash))), + ("target", toJson (hexOfBytes request.target.hash)), + ("subjects", toJson (request.subjects.map (hexOfBytes ·.hash))), + ("objects", toJson (request.selection.objects.map (hexOfBytes ·.hash))), + ("naturals", toJson (request.selection.naturals.map (hexOfBytes ·.hash))), + ("models", toJson (request.models.map ModelHint.json))] + +def sourceAccepted (f : Fixture) : Bool := Id.run do + let some (_, env) := Source.loadedIxe? f.source | return false + let .ok request := Command.readRequest (requestJson f.request) | return false + return (Command.run.{0} "proof" fuel env request).isOk && (Command.run.{0} "store" fuel env request).isOk + +/-- Poisoned legacy caches do not skip either a model declaration or an +equation proof. Failed model checks leave the actual byte cache unchanged. -/ +def warmAndRollback (f : Fixture) : Bool := Id.run do + let some (_, env) := Source.loadedIxe? f.source | return false + let c := f.source + let count := c.blobs.length + c.literals.length + let some witness := suggestSource? fuel env c.profile c.target (Source.selection c) [f.model] | return false + let .ok _ cold := (certifiedStep.{0} fuel env c.profile c.target (Source.selection c) witness).run initialCertifiedState + | return false + if cold.inputCache.misses != count || cold.inputCache.hits != 0 then return false + let start := { cold with checker := Source.poisonedChecker c } + let .ok _ warm := (certifiedStep.{0} fuel env c.profile c.target (Source.selection c) witness).run start | return false + if warm.inputCache.hits != count || warm.inputCache.misses != count then return false + let bad := { witness with declarations := witness.declarations.map fun declaration => match declaration with + | .modeled model => .modeled { model with equations := model.equations.map (fun proofs => + proofs.map (fun proof => { proof with proof := .conversion .refl })) } + | declaration => declaration } + let .error _ failed := (certifiedStep.{0} fuel env c.profile c.target (Source.selection c) bad).run warm | return false + if failed.inputCache.hits != warm.inputCache.hits || failed.inputCache.misses != warm.inputCache.misses then return false + let .error _ exhausted := (certifiedStep.{0} 0 env c.profile c.target (Source.selection c) witness).run failed | return false + if exhausted.inputCache.hits != warm.inputCache.hits || exhausted.inputCache.misses != warm.inputCache.misses then return false + let .ok _ retry := (certifiedStep.{0} fuel env c.profile c.target (Source.selection c) witness).run exhausted | return false + return retry.inputCache.hits == 2 * count && retry.inputCache.misses == count + +def checkClaim? (f : Fixture) : Option Claims.Fixture := + Claims.finish? s!"{f.scenario.name}-check" f.source (.check f.source.target none) + ⟨Source.selection f.source, [⟨.check f.source.target none, none, none⟩], none, none, none, none, [f.model]⟩ + +def environmentClaim? (f : Fixture) : Option Claims.Fixture := do + let subjects := Claims.tree (Source.subjects f.source) + let claim := Ix.Claim.checkEnv (treeRoot subjects) none + Claims.finish? s!"{f.scenario.name}-environment" f.source claim + ⟨Source.selection f.source, [⟨claim, some (treeBytes subjects), none⟩], + some (treeBytes subjects), none, none, none, [f.model]⟩ + +def sharedClaim? (f : Fixture) : Option Claims.Fixture := do + let model ← f.model.targets.getLast? + let subjects := Claims.tree [model, f.source.target] + let claim := Ix.Claim.checkEnv (treeRoot subjects) none + Claims.finish? s!"{f.scenario.name}-shared-model" f.source claim + ⟨Source.selection f.source, [⟨.check model none, none, none⟩, ⟨.check f.source.target none, none, none⟩], + some (treeBytes subjects), none, none, none, [f.model]⟩ + +def claimCases? (f : Fixture) : Option (List Claims.WireCase) := do + let fixtures ← [checkClaim? f, environmentClaim? f, sharedClaim? f].mapM id + return fixtures.flatMap fun fixture => [ + ⟨fixture.name, fixture.source, fixture.envelope, .logical fixture.hint, true⟩, + ⟨s!"{fixture.name}-old-checker", fixture.source, + { fixture.envelope with protocol := { fixture.envelope.protocol with checker := 1 } }, + .logical fixture.hint, false⟩] + +def writeSource (directory : System.FilePath) (f : Fixture) : IO Unit := do + let directory := directory / f.scenario.name + IO.FS.createDirAll directory + let some (bytes, _) := Source.loadedIxe? f.source | throw (IO.userError "cannot write modeled .ixe") + IO.FS.writeBinFile (directory / "source.ixe") bytes + IO.FS.writeFile (directory / "request.json") ((requestJson f.request).pretty ++ "\n") + IO.FS.writeFile (directory / "expected.json") + ((Lean.Json.mkObj [("proof", toJson true), ("store", toJson true)]).compress ++ "\n") + +def run (directory : Option System.FilePath := none) : IO Unit := do + for scenario in scenarios do + let some f := fixture? scenario | throw (IO.userError s!"modeled serialization failed: {scenario.name}") + unless sourceAccepted f do throw (IO.userError s!"modeled source acceptance failed: {scenario.name}") + unless warmAndRollback f do throw (IO.userError s!"modeled cache or rollback failed: {scenario.name}") + let some claims := claimCases? f | throw (IO.userError s!"modeled claim construction failed: {scenario.name}") + for claim in claims do Claims.runWire (directory.map (· / "claims")) claim + if let some directory := directory then writeSource (directory / "source") f + IO.println <| (Lean.Json.mkObj [("case", toJson scenario.name), ("source", toJson true), + ("cacheRollback", toJson true), ("claims", toJson claims.length)]).compress + +end Tests.Certified.Modeled diff --git a/Tests/Certified/ModeledAdversarial.lean b/Tests/Certified/ModeledAdversarial.lean new file mode 100644 index 000000000..adae735f6 --- /dev/null +++ b/Tests/Certified/ModeledAdversarial.lean @@ -0,0 +1,232 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.Modeled + +namespace Tests.Certified.ModeledAdversarial + +open Ix.Theory Ix.Theory.Certified Ix.Certified Ix.Kernel Serialize Modeled +open Lean (toJson) + +set_option maxRecDepth 32768 +set_option maxHeartbeats 64000000 + +def changeBlock (input : ProofInput Nat) (key : Nat) (alter : Block Nat → Block Nat) : ProofInput Nat := + let old := input.store + { input with store := { + dom := old.dom, nodup := old.nodup, + blocks := fun b => (old.blocks b).map fun block => if b = key then alter block else block, + mem_dom := by intro b; simp [old.mem_dom] } } + +def changeMembers (input : ProofInput Nat) (key : Nat) (alter : Const Nat → Const Nat) : ProofInput Nat := + changeBlock input key fun block => ⟨block.members.map alter⟩ + +def changeRecursor (tag : String) : Const Nat → Const Nat + | .recursor u p i m n t rs k s => match tag with + | "global-rule-order" => .recursor u p i m n t rs.reverse k s + | "omitted-global-rule" => .recursor u p i m n t (rs.take 2) k s + | "rule-fields" => .recursor u p i m n t (rs.map fun r => { r with nfields := r.nfields + 1 }) k s + | "rule-rhs" => .recursor u p i m n t (rs.map fun r => { r with rhs := .sort .zero }) k s + | "rule-telescope" => .recursor u p i m n t (rs.map fun r => { r with rhs := match r.rhs with + | .lam _ body => .lam (.sort .zero) body | body => body }) k s + | "k" => .recursor u p i m n t rs true s + | "unsafe-recursor" => .recursor u p i m n t rs k .unsafe + | "parameters" => .recursor u (p + 1) i m n t rs k s + | "indices" => .recursor u p (i + 1) m n t rs k s + | "motives" => .recursor u p i (m + 1) n t rs k s + | "minors" => .recursor u p i m (n + 1) t rs k s + | "levels" => .recursor (u + 1) p i m n t rs k s + | "level-permutation" => .recursor u p i m n (t.instL [.param 1, .param 0]) rs k s + | _ => .recursor u p i m n t rs k s + | c => c + +def changeFamily (tag : String) : Const Nat → Const Nat + | .induct u p i t cs s => match tag with + | "constructor-order" => .induct u p i t cs.reverse s + | "constructor-fields" => .induct u p i t (cs.map fun c => { c with nfields := c.nfields + 1 }) s + | "constructor-levels" => .induct u p i t (cs.map fun c => { c with uvars := c.uvars + 1 }) s + | "constructor-parameters" => .induct u p i t (cs.map fun c => { c with nparams := c.nparams + 1 }) s + | "unsafe-family" => .induct u p i t cs .unsafe + | "unsafe-constructor" => .induct u p i t (cs.map fun c => { c with safety := .unsafe }) s + | _ => .induct u p i t cs s + | c => c + +structure SourceMutation where + name : String + original : Scenario + input : ProofInput Nat + +def mutualCase : Scenario := ⟨"mutual-unequal", Tests.Theory.Modeled.input, Tests.Theory.Modeled.candidate⟩ +def nested : Scenario := ⟨"nested-parameter", Tests.Theory.ModeledNested.input false, Tests.Theory.ModeledNested.candidate⟩ +def recursivePi : Scenario := ⟨"nested-recursive-Pi", Tests.Theory.ModeledNested.input true, Tests.Theory.ModeledNested.candidate⟩ +def propositional : Scenario := ⟨"propositional-equations", Tests.Theory.ModeledEquations.input, Tests.Theory.ModeledEquations.candidate⟩ + +def sourceMutations : List SourceMutation := + (["global-rule-order", "omitted-global-rule", "rule-fields", "rule-rhs", "rule-telescope", + "k", "unsafe-recursor", "parameters", "indices", "motives", "minors", "levels"].map fun tag => + ⟨s!"mutual-{tag}", mutualCase, changeMembers mutualCase.input 31 (changeRecursor tag)⟩) ++ + (["constructor-order", "constructor-fields", "constructor-levels", "constructor-parameters", + "unsafe-family", "unsafe-constructor"].map fun tag => + ⟨s!"mutual-{tag}", mutualCase, changeMembers mutualCase.input 30 (changeFamily tag)⟩) ++ [ + ⟨"mutual-family-type", mutualCase, changeMembers mutualCase.input 30 fun c => match c with + | .induct u p i _ cs s => .induct u p i (.sort (.succ (.succ .zero))) cs s | c => c⟩, + ⟨"mutual-recursor-order", mutualCase, changeBlock mutualCase.input 31 fun b => ⟨b.members.reverse⟩⟩, + ⟨"unproved-model-axiom", mutualCase, changeMembers mutualCase.input 40 fun c => .axiom c.uvars c.type .safe⟩, + ⟨"changed-model-body", mutualCase, changeMembers mutualCase.input 40 fun c => match c with + | .defn n k t _ s => .defn n k t (.lam Tests.Theory.Modeled.natType (.const (.ctor 20 0 0) [])) s + | c => c⟩, + ⟨"circular-model", mutualCase, changeMembers mutualCase.input 40 fun c => match c with + | .defn n k t _ s => .defn n k t (.const (.ctor 30 1 0) []) s | c => c⟩, + ⟨"nested-level-permutation", nested, changeMembers nested.input 41 (changeRecursor "level-permutation")⟩, + ⟨"nested-rule-fields", nested, changeMembers nested.input 41 (changeRecursor "rule-fields")⟩, + ⟨"recursive-Pi-level-permutation", recursivePi, + changeMembers recursivePi.input 41 (changeRecursor "level-permutation")⟩, + ⟨"recursive-Pi-rule-telescope", recursivePi, + changeMembers recursivePi.input 41 (changeRecursor "rule-telescope")⟩, + ⟨"unproved-equation-axiom", propositional, + changeMembers propositional.input 70 fun c => .axiom c.uvars c.type .safe⟩, + ⟨"unrelated-equation-proof", propositional, + changeMembers propositional.input 70 fun c => match c with + | .defn n k t _ s => .defn n k t (.const (.member 40 0) []) s + | c => c⟩] + +def mutationFixture? (m : SourceMutation) : Option Fixture := + fixture? { m.original with name := m.name, input := m.input } + +def control? (f : Fixture) (original : ProofInput Nat) : Option (PreparedInput × ProofWitness Address) := do + let prepared ← ModelSerialize.repaired? f.source original + let objects ← decodeObjects? f.source.blobs + let models ← modelCandidates? objects prepared.input.store [f.model] + let witness ← Certificate.proofWitness? fuel prepared.signature prepared.input models + return (prepared, witness) + +/-- A complete semantic certificate succeeds on the original declarations at +the new addresses, then fails on the actual authenticated altered source. +The same declaration certificate is submitted to the claim acceptance root. -/ +def rejectsSource (f : Fixture) (original : ProofInput Nat) : Bool := Id.run do + let some (prepared, witness) := control? f original | return false + unless acceptsCertified.{0,0} fuel prepared.signature prepared.input witness do return false + let some (_, env) := Source.loadedIxe? f.source | return false + if acceptsCertifiedSource.{0} fuel env f.source.profile f.source.target (Source.selection f.source) witness then + return false + if acceptsCertifiedStoreSource.{0} fuel env f.source.profile (Source.subjects f.source) + (Source.selection f.source) witness.declarations then return false + let claim := Ix.Claim.check f.source.target none + let envelope : Envelope := ⟨Protocol.current, f.source.profile, claim, none⟩ + let leaf : LeafWitness := ⟨claim, none, none, [], witness.declarations⟩ + let logical : LogicalWitness := ⟨Source.selection f.source, [leaf], none, none, none, [], none⟩ + let bytes := envelopeBytes envelope + return !acceptsCertifiedClaim.{0} fuel env (Address.blake3 bytes) bytes (.logical logical) + +def witnessMutations : List (String × (Ix.Theory.Certified.Modeled.Witness Address → + Ix.Theory.Certified.Modeled.Witness Address)) := [ + ("recursor-order", fun w => { w with recursors := w.recursors.reverse }), + ("companion-order", fun w => { w with companions := w.companions.reverse }), + ("missing-companion", fun w => { w with companions := w.companions.drop 1 }), + ("missing-equation", fun w => { w with equations := w.equations.drop 1 }), + ("self-model", fun w => { w with companions := w.companions.map fun c => { c with model := c.header.ref } }), + ("unrelated-left-side", fun w => { w with companions := w.companions.map fun c => + { c with rules := c.rules.map fun r => { r with lhs := r.rhs } } }), + ("forged-conversion", fun w => { w with equations := w.equations.map (fun ps => + ps.map fun p => { p with proof := .conversion .refl }) })] + +def rejectsWitnesses (f : Fixture) : Bool := Id.run do + let env := Source.source f.source + let some witness := suggestSource? fuel env f.source.profile f.source.target (Source.selection f.source) [f.model] + | return false + return witnessMutations.all fun (_, alter) => + let witness := { witness with declarations := witness.declarations.map fun declaration => match declaration with + | .modeled model => .modeled (alter model) | declaration => declaration } + !acceptsCertifiedSource.{0} fuel env f.source.profile f.source.target (Source.selection f.source) witness && + !acceptsCertifiedStoreSource.{0} fuel env f.source.profile (Source.subjects f.source) + (Source.selection f.source) witness.declarations + +def negativeWire (f : Fixture) : Claims.WireCase := + let claim := Ix.Claim.check f.source.target none + ⟨f.scenario.name, f.source, ⟨Protocol.current, f.source.profile, claim, none⟩, + .logical ⟨Source.selection f.source, [⟨claim, none, none⟩], none, none, none, none, [f.model]⟩, false⟩ + +def writeNegative (directory : System.FilePath) (f : Fixture) : IO Unit := do + let directory := directory / f.scenario.name + IO.FS.createDirAll directory + let some (bytes, _) := Source.loadedIxe? f.source | throw (IO.userError "cannot write mutated .ixe") + IO.FS.writeBinFile (directory / "source.ixe") bytes + IO.FS.writeFile (directory / "request.json") ((Modeled.requestJson f.request).pretty ++ "\n") + IO.FS.writeFile (directory / "expected.json") + ((Lean.Json.mkObj [("proof", toJson false), ("store", toJson false)]).compress ++ "\n") + +def ingressNames : List String := ["family-order", "constructor-index", "family-wrapper-kind", + "family-wrapper-slot", "recursor-wrapper-kind", "recursor-wrapper-slot", "constructor-wrapper-slot", + "missing-universe-table", "missing-reference-table"] + +/-- These mutations preserve fresh hashes and update every dependent address. +Malformed mutual projections and tables must fail even before model search. -/ +def ingressFixture? (name : String) : Option Fixture := do + let original ← fixture? mutualCase + let family ← reference original.source.references (.member 30 0) + let recursor ← reference original.source.references (.member 31 0) + let constructor ← reference original.source.references (.ctor 30 1 0) + let source ← rehash? original.source id fun address source => + if address = original.model.source && name = "family-order" then + match source.info with + | .muts members => { source with info := .muts members.reverse } + | _ => source + else if address = original.model.source && name = "constructor-index" then + match source.info with + | .muts members => { source with info := .muts (members.map fun member => match member with + | .indc family => .indc { family with ctors := family.ctors.map fun ctor => { ctor with cidx := ctor.cidx + 1 } } + | member => member) } + | _ => source + else if address = family && name = "family-wrapper-kind" then + match source.info with + | .iPrj p => { source with info := .rPrj ⟨p.idx, p.block⟩ } | _ => source + else if address = family && name = "family-wrapper-slot" then + match source.info with + | .iPrj p => { source with info := .iPrj { p with idx := 999 } } | _ => source + else if address = recursor && name = "recursor-wrapper-kind" then + match source.info with + | .rPrj p => { source with info := .dPrj ⟨p.idx, p.block⟩ } | _ => source + else if address = recursor && name = "recursor-wrapper-slot" then + match source.info with + | .rPrj p => { source with info := .rPrj { p with idx := 999 } } | _ => source + else if address = constructor && name = "constructor-wrapper-slot" then + match source.info with + | .cPrj p => { source with info := .cPrj { p with cidx := 999 } } | _ => source + else if address = original.source.target && name = "missing-universe-table" then { source with univs := #[] } + else if address = original.source.target && name = "missing-reference-table" then { source with refs := #[] } + else source + let name := s!"ingress-{name}" + let model ← ModelSerialize.hint? source mutualCase.candidate + return ⟨{ mutualCase with name }, { source with name }, model⟩ + +def run (directory : Option System.FilePath := none) : IO Unit := do + for scenario in scenarios do + let some f := fixture? scenario | throw (IO.userError s!"modeled witness fixture failed: {scenario.name}") + unless rejectsWitnesses f do throw (IO.userError s!"modeled forged witness escaped: {scenario.name}") + for m in sourceMutations do + let some f := mutationFixture? m | throw (IO.userError s!"modeled mutation serialization failed: {m.name}") + unless rejectsSource f m.original.input do throw (IO.userError s!"modeled valid-control source mutation escaped: {m.name}") + let some (_, env) := Source.loadedIxe? f.source | throw (IO.userError s!"modeled mutation load failed: {m.name}") + if (Command.run.{0} "proof" fuel env f.request).isOk || (Command.run.{0} "store" fuel env f.request).isOk then + throw (IO.userError s!"modeled mutated command accepted: {m.name}") + Claims.runWire (directory.map (· / "claims")) (negativeWire f) + if let some directory := directory then writeNegative (directory / "source") f + IO.println <| (Lean.Json.mkObj [("sourceMutation", toJson m.name), ("controlAccepted", toJson true), + ("sourceRejected", toJson true), ("claimRejected", toJson true)]).compress + for name in ingressNames do + let some f := ingressFixture? name | throw (IO.userError s!"modeled ingress construction failed: {name}") + unless (prepare? fuel f.source.profile f.source.target f.source.blobs f.source.literals).isNone do + throw (IO.userError s!"modeled malformed mutual source decoded: {name}") + let some (_, env) := Source.loadedIxe? f.source | throw (IO.userError s!"modeled ingress .ixe load failed: {name}") + if (Command.run.{0} "proof" fuel env f.request).isOk || (Command.run.{0} "store" fuel env f.request).isOk then + throw (IO.userError s!"modeled malformed mutual command accepted: {name}") + Claims.runWire (directory.map (· / "claims")) (negativeWire f) + if let some directory := directory then writeNegative (directory / "source") f + IO.println <| (Lean.Json.mkObj [("sourceMutations", toJson sourceMutations.length), + ("forgedWitnesses", toJson (scenarios.length * witnessMutations.length)), + ("ingressMutations", toJson ingressNames.length), + ("unexpectedErrors", toJson (0 : Nat))]).compress + +end Tests.Certified.ModeledAdversarial diff --git a/Tests/Certified/ModeledMain.lean b/Tests/Certified/ModeledMain.lean new file mode 100644 index 000000000..45dedc808 --- /dev/null +++ b/Tests/Certified/ModeledMain.lean @@ -0,0 +1,11 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.ModeledAdversarial + +def main (args : List String) : IO Unit := do + let directory := (args.head?).map System.FilePath.mk + Tests.Certified.Modeled.run directory + Tests.Certified.ModeledAdversarial.run directory diff --git a/Tests/Certified/Ordinary.lean b/Tests/Certified/Ordinary.lean new file mode 100644 index 000000000..d68a9e49e --- /dev/null +++ b/Tests/Certified/Ordinary.lean @@ -0,0 +1,236 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Corpus +import Tests.Theory.OrdinaryAcceptance + +/-! Actual canonical Ixon bytes for ordinary source blocks and closed proofs. +The serializer is test infrastructure. Witness generation receives only the +decoded store and original target, and the serialized acceptance gate reruns +all independent checks. -/ + +namespace Tests.Certified.Ordinary + +open Ix.Theory Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certified.Ordinary +open Ix.Certified Ix.Certified.Fixtures +open Tests.Theory.OrdinaryAcceptance +open Lean (toJson) + +set_option maxRecDepth 8192 +set_option maxHeartbeats 8000000 + +local instance : DecidableEq Address := Ix.Certified.addressDecidableEq + +structure Tables where + refs : Array Address := #[] + univs : Array Ixon.Univ := #[] + +abbrev Write := StateT Tables Option + +def univ : VLevel → Ixon.Univ + | .zero => .zero + | .succ u => .succ (univ u) + | .max u v => .max (univ u) (univ v) + | .imax u v => .imax (univ u) (univ v) + | .param i => .var i.toUInt64 + +def level (u : VLevel) : Write UInt64 := do + let s ← get + set { s with univs := s.univs.push (univ u) } + return s.univs.size.toUInt64 + +def address (a : Address) : Write UInt64 := do + let s ← get + set { s with refs := s.refs.push a } + return s.refs.size.toUInt64 + +def expression (self : Nat) (resolve : ConstRef Nat → Option Address) : + VExpr Nat → Write Ixon.Expr + | .sort u => return .sort (← level u) + | .bvar i => return .var i.toUInt64 + | .const r us => do + let us ← us.mapM level + match r with + | .member block member => + if block = self then return .recur member.toUInt64 us.toArray + else return .ref (← address (← resolve r)) us.toArray + | .ctor .. => return .ref (← address (← resolve r)) us.toArray + | .app f a => return .app (← expression self resolve f) (← expression self resolve a) + | .lam A b => return .leanLam (← expression self resolve A) (← expression self resolve b) + | .forallE A B => return .leanAll (← expression self resolve A) (← expression self resolve B) + | .proj .. | .natLit .. => failure + +def constructor (self : Nat) (resolve : ConstRef Nat → Option Address) + (ctor : Ctor Nat) (index : Nat) : Write Ixon.Constructor := do + return { + isUnsafe := ctor.safety != .safe, lvls := ctor.uvars.toUInt64, + cidx := index.toUInt64, params := ctor.nparams.toUInt64, fields := ctor.nfields.toUInt64, + typ := ← expression self resolve ctor.type } + +def constantInfo (self : Nat) (resolve : ConstRef Nat → Option Address) : + Const Nat → Write Ixon.ConstantInfo + | .induct n p i type ctors safety => do + let typ ← expression self resolve type + let ctors ← ctors.zipIdx.mapM fun (ctor, index) => constructor self resolve ctor index + return .muts #[.indc { + isUnsafe := safety != .safe, + lvls := n.toUInt64, params := p.toUInt64, indices := i.toUInt64, typ, ctors := ctors.toArray }] + | .recursor n p i m b type rules k safety => do + let typ ← expression self resolve type + let rules ← rules.mapM fun rule => do + return ({ + fields := rule.nfields.toUInt64, + rhs := ← expression self resolve rule.rhs } : Ixon.RecursorRule) + return .recr { + k, isUnsafe := safety != .safe, lvls := n.toUInt64, + params := p.toUInt64, indices := i.toUInt64, motives := m.toUInt64, + minors := b.toUInt64, typ, rules := rules.toArray } + | .defn n _ type body .safe => do + return .defn { + kind := .thm, safety := .safe, lvls := n.toUInt64, + typ := ← expression self resolve type, value := ← expression self resolve body } + | _ => failure + +def constant (self : Nat) (resolve : ConstRef Nat → Option Address) (source : Const Nat) : + Option Ixon.Constant := do + let (info, tables) ← constantInfo self resolve source {} + return ⟨info, #[], tables.refs, tables.univs⟩ + +structure Case extends Corpus.Case where + source : Address + recursor : Address + mode : Inductive.ElimMode + +def make? (name : String) (shape : Shape Nat) (mode : Inductive.ElimMode) + (body proposition : AExpr Nat) (mutateRec : Const Nat → Const Nat := id) + (mutateFamily : Ixon.Constant → Ixon.Constant := id) : Option Case := do + let family := mutateFamily (← constant 100 (fun _ => none) (shape.source 100)) + let source := encode family + let projection := encode ⟨.iPrj ⟨0, source.1⟩, #[], #[], #[]⟩ + let ctors := (List.range shape.constructors.length).map fun index => + encode ⟨.cPrj ⟨0, index.toUInt64, source.1⟩, #[], #[], #[]⟩ + let resolve := fun r => match r with + | .member 100 0 => some projection.1 + | .ctor 100 0 index => (ctors[index]?).map Prod.fst + | _ => none + let recursor ← constant 101 resolve (mutateRec (shape.recursorSource 100 101 mode)) + let recursor := encode recursor + let resolve := fun r => if r = .member 101 0 then some recursor.1 else resolve r + let target ← constant 200 resolve (.defn 0 .theorem proposition.erase body.erase .safe) + let target := encode target + return { + name, target := target.1, + blobs := prelude ++ [source, projection] ++ ctors ++ [recursor, target], + source := source.1, recursor := recursor.1, mode } + +def acceptedCase (c : Case) : Bool := + match prepare? 2000 profile c.target c.blobs with + | none => false + | some prepared => (Ix.Theory.Certificate.proofWitness? 2000 prepared.signature prepared.input).any + (acceptsSerialized.{0} 2000 profile c.target c.blobs) + +def positive : List (Option Case) := [ + make? "Nat-iota" Tests.Theory.Ordinary.natShape .large identity (proposition natComputed), + make? "List-distinct-universes" Tests.Theory.Ordinary.listShape .large identity (proposition listComputed), + make? "indexed-iota" Tests.Theory.Ordinary.indexedShape .large identity (proposition indexedComputed), + make? "function-field-iota" functionalShape .large identity (proposition functionalComputed), + make? "multiple-Prop-small" Tests.Theory.Ordinary.manyProp .small smallProof identityType +] + +#guard positive.length = 5 +#guard positive.all (fun c => c.any acceptedCase) + +def corruptRule : Const Nat → Const Nat + | .recursor n p i m b type (_ :: rules) k safety => + .recursor n p i m b type (⟨0, .sort .zero⟩ :: rules) k safety + | other => other + +def unsafeRecursor : Const Nat → Const Nat + | .recursor n p i m b type rules k _ => .recursor n p i m b type rules k .unsafe + | other => other + +def enableK : Const Nat → Const Nat + | .recursor n p i m b type rules _ safety => .recursor n p i m b type rules true safety + | other => other + +def replaceBlock (store : Store Address) (address : Address) (block : Block Address) : Store Address where + dom := store.dom + nodup := store.nodup + blocks a := (store.blocks a).map fun old => if a = address then block else old + mem_dom a := by simp [store.mem_dom] + +/-- Construct a valid certificate with the original canonical recursor at the +new address, then submit it against the authenticated altered source. This +tests the acceptance boundary independently of producer refusal. -/ +def rejectsWithValidWitness (c : Case) : Bool := Id.run do + let some prepared := prepare? 2000 profile c.target c.blobs | return false + let some raw := prepared.input.store.lookup (.member c.source 0) | return false + let some shape := Ix.Theory.Certificate.Ordinary.description? 2000 + prepared.signature.environment c.source raw | return false + let repaired := replaceBlock prepared.input.store c.recursor + ⟨[shape.recursorSource c.source c.recursor c.mode]⟩ + let input := { prepared.input with store := repaired } + let some witness := Ix.Theory.Certificate.proofWitness? 2000 prepared.signature input | return false + return acceptsCertified.{0,0} 2000 prepared.signature input witness && + !acceptsSerialized.{0} 2000 profile c.target c.blobs witness + +#guard [corruptRule, unsafeRecursor, enableK].all fun mutation => + (make? "forged-recursor" Tests.Theory.Ordinary.natShape .large identity + (proposition natComputed) mutation).any rejectsWithValidWitness + +def wrongPosition (source : Ixon.Constant) : Ixon.Constant := + match source.info with + | .muts #[.indc family] => { source with info := .muts #[.indc + { family with ctors := family.ctors.map fun ctor => { ctor with cidx := ctor.cidx + 1 } }] } + | _ => source + +#guard (make? "wrong-constructor-position" Tests.Theory.Ordinary.natShape .large identity + (proposition natComputed) id wrongPosition).any fun c => + (prepare? 2000 profile c.target c.blobs).isNone + +def writeCase (directory : System.FilePath) (c : Case) : IO Unit := do + let directory := directory / c.name + IO.FS.createDirAll directory + for (address, bytes) in c.blobs do + IO.FS.writeBinFile (directory / s!"{hexOfBytes address.hash}.ixon") bytes + let metadata := Lean.Json.mkObj [ + ("target", toJson (hexOfBytes c.target.hash)), + ("falseType", toJson (hexOfBytes profile.falseType.hash)), + ("falseElim", toJson (hexOfBytes profile.falseElim.hash))] + IO.FS.writeFile (directory / "target.json") (metadata.pretty ++ "\n") + +def run (directory : Option System.FilePath) : IO Unit := do + let mut accepted := 0 + for candidate in positive do + let some c := candidate | throw (IO.userError "serialized fixture construction failed") + unless acceptedCase c do throw (IO.userError s!"serialized acceptance failed: {c.name}") + accepted := accepted + 1 + if let some directory := directory then writeCase directory c + let mut rejected := 0 + for (name, mutation) in [("changed-rule", corruptRule), ("unsafe-recursor", unsafeRecursor), + ("unsupported-K", enableK)] do + let some c := make? name Tests.Theory.Ordinary.natShape .large identity + (proposition natComputed) mutation | throw (IO.userError "malformed fixture construction failed") + unless rejectsWithValidWitness c do throw (IO.userError s!"malformed source accepted: {name}") + rejected := rejected + 1 + if let some directory := directory then writeCase directory c + let some wrong := make? "wrong-constructor-position" Tests.Theory.Ordinary.natShape .large identity + (proposition natComputed) id wrongPosition | throw (IO.userError "position fixture construction failed") + unless (prepare? 2000 profile wrong.target wrong.blobs).isNone do + throw (IO.userError "wrong constructor position accepted") + if let some directory := directory then writeCase directory wrong + IO.println <| (Lean.Json.mkObj [ + ("serializedAccepted", toJson accepted), ("serializedRejected", toJson rejected), + ("ingressRejected", toJson (1 : Nat)), + ("unexpectedErrors", toJson (0 : Nat))]).compress + +end Tests.Certified.Ordinary + +def main (args : List String) : IO UInt32 := do + if args.length > 1 then + IO.eprintln "usage: certified-ordinary-tests [OUTPUT_DIRECTORY]" + return 2 + Tests.Certified.Ordinary.run (args.head?.map System.FilePath.mk) + return 0 diff --git a/Tests/Certified/Serialize.lean b/Tests/Certified/Serialize.lean new file mode 100644 index 000000000..5289854c6 --- /dev/null +++ b/Tests/Certified/Serialize.lean @@ -0,0 +1,243 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Fixtures + +/-! Test-only serializer for singleton source stores. It preserves every +source kind and field, emits real content-addressed projection wrappers, and +places natural literal bytes in their separate authenticated blob domain. -/ + +namespace Tests.Certified.Serialize + +open Ix.Theory Ix.Theory.Certified Ix.Certified Ix.Certified.Fixtures + +structure Tables where + refs : Array Address := #[] + univs : Array Ixon.Univ := #[] + literals : ConstantBlobs := [] + +abbrev Write := StateT Tables Option + +def univ : VLevel → Ixon.Univ + | .zero => .zero + | .succ u => .succ (univ u) + | .max u v => .max (univ u) (univ v) + | .imax u v => .imax (univ u) (univ v) + | .param i => .var i.toUInt64 + +def level (u : VLevel) : Write UInt64 := do + let s ← get + set { s with univs := s.univs.push (univ u) } + return s.univs.size.toUInt64 + +def address (a : Address) : Write UInt64 := do + let s ← get + set { s with refs := s.refs.push a } + return s.refs.size.toUInt64 + +def expression (self : Nat) (resolve : ConstRef Nat → Option Address) : + VExpr Nat → Write Ixon.Expr + | .sort u => return .sort (← level u) + | .bvar i => return .var i.toUInt64 + | .const r us => do + let us ← us.mapM level + match r with + | .member block member => + if block = self then return .recur member.toUInt64 us.toArray + else return .ref (← address (← resolve r)) us.toArray + | .ctor .. => return .ref (← address (← resolve r)) us.toArray + | .app f a => return .app (← expression self resolve f) (← expression self resolve a) + | .lam A b => return .leanLam (← expression self resolve A) (← expression self resolve b) + | .forallE A B => return .leanAll (← expression self resolve A) (← expression self resolve B) + | .proj r i s => return .prj (← address (← resolve r)) i.toUInt64 (← expression self resolve s) + | .natLit n => do + let bytes := ByteArray.mk n.toBytesLE + let a := Address.blake3 bytes + modify fun s => { s with literals := s.literals ++ [(a, bytes)] } + return .nat (← address a) + +def safety : Safety → Ix.DefinitionSafety + | .safe => .safe + | .unsafe => .unsaf + | .partial => .part + +def kind : Ix.Theory.DefKind → Ix.DefKind + | .definition => .defn + | .theorem => .thm + | .opaque => .opaq + +def quotKind : Ix.Theory.QuotKind → Ix.QuotKind + | .type => .type + | .ctor => .ctor + | .lift => .lift + | .ind => .ind + +def constantInfo (self : Nat) (resolve : ConstRef Nat → Option Address) : + Const Nat → Write Ixon.ConstantInfo + | .induct n p i type ctors s => do + let typ ← expression self resolve type + let ctors ← ctors.zipIdx.mapM fun (ctor, index) => do + return ({ + isUnsafe := ctor.safety != .safe, lvls := ctor.uvars.toUInt64, + cidx := index.toUInt64, params := ctor.nparams.toUInt64, fields := ctor.nfields.toUInt64, + typ := ← expression self resolve ctor.type } : Ixon.Constructor) + return .muts #[.indc { + isUnsafe := s != .safe, lvls := n.toUInt64, + params := p.toUInt64, indices := i.toUInt64, typ, ctors := ctors.toArray }] + | .recursor n p i m b type rules k s => do + let typ ← expression self resolve type + let rules ← rules.mapM fun rule => do + return ({ + fields := rule.nfields.toUInt64, + rhs := ← expression self resolve rule.rhs } : Ixon.RecursorRule) + return .recr { + k, isUnsafe := s != .safe, lvls := n.toUInt64, + params := p.toUInt64, indices := i.toUInt64, motives := m.toUInt64, + minors := b.toUInt64, typ, rules := rules.toArray } + | .defn n k type body s => do + return .defn { + kind := kind k, safety := safety s, lvls := n.toUInt64, + typ := ← expression self resolve type, value := ← expression self resolve body } + | .axiom n type s => do + return .axio { isUnsafe := s != .safe, lvls := n.toUInt64, typ := ← expression self resolve type } + | .quot k n type => do + return .quot { kind := quotKind k, lvls := n.toUInt64, typ := ← expression self resolve type } + +def constant (self : Nat) (resolve : ConstRef Nat → Option Address) (source : Const Nat) : + Option (Ixon.Constant × ConstantBlobs) := do + let (info, tables) ← constantInfo self resolve source {} + return (⟨info, #[], tables.refs, tables.univs⟩, tables.literals) + +structure Case where + name : String + profile : Profile + target : Address + blobs : ConstantBlobs + literals : ConstantBlobs + references : List (ConstRef Nat × Address) + blocks : List (Nat × Address) + +def reference (references : List (ConstRef Nat × Address)) (r : ConstRef Nat) : Option Address := + (references.find? fun (key, _) => key = r).map Prod.snd + +def uniqueBlobs (blobs : ConstantBlobs) : ConstantBlobs := + blobs.foldl (fun acc entry => if (lookup acc entry.1).isSome then acc else acc ++ [entry]) [] + +/-- Source domains are supplied in dependency order. Each fixture must provide +all declarations; witness construction receives only the decoded result. -/ +def make? (name : String) (signature : PrimitiveSignature Nat) (input : ProofInput Nat) : + Option Case := do + if signature.falseType != .member 10 0 || signature.falseElim != .member 11 0 || 900 ∈ input.store.dom then + none + else do + let mut blobs := prelude + let mut literals := [] + let mut references := [(.member 10 0, falseObject.1), (.member 11 0, falseElimObject.1)] + let mut blocks := [(10, falseBlockObject.1), (11, falseElimObject.1)] + for b in input.store.dom.filter (fun b => b != 10 && b != 11) do + let source ← input.store.lookup (.member b 0) + let (raw, extra) ← constant b (reference references) source + let encoded := encode raw + blobs := blobs ++ [encoded] + literals := literals ++ extra + blocks := blocks ++ [(b, encoded.1)] + match source with + | .induct _ _ _ _ ctors _ => + let projection := encode ⟨.iPrj ⟨0, encoded.1⟩, #[], #[], #[]⟩ + blobs := blobs ++ [projection] + references := references ++ [(.member b 0, projection.1)] + for i in List.range ctors.length do + let ctor := encode ⟨.cPrj ⟨0, i.toUInt64, encoded.1⟩, #[], #[], #[]⟩ + blobs := blobs ++ [ctor] + references := references ++ [(.ctor b 0 i, ctor.1)] + | _ => references := references ++ [(.member b 0, encoded.1)] + let (raw, extra) ← constant 900 (reference references) + (.defn input.universes .theorem input.proposition input.proof .safe) + let target := encode raw + let natType ← match signature.natType with + | none => some none + | some r => (reference references r).map some + return { + name, profile := { profile with natType }, target := target.1, + blobs := blobs ++ [target], literals := uniqueBlobs (literals ++ extra), + references := references ++ [(.member 900 0, target.1)], blocks := blocks ++ [(900, target.1)] } + +def renameConstant (mapping : Nat → Address) : Const Nat → Const Address + | .axiom n type s => .axiom n (type.rename mapping) s + | .defn n k type body s => .defn n k (type.rename mapping) (body.rename mapping) s + | .quot k n type => .quot k n (type.rename mapping) + | .induct n p i type ctors s => .induct n p i (type.rename mapping) + (ctors.map fun c => ⟨c.uvars, c.nparams, c.nfields, c.type.rename mapping, c.safety⟩) s + | .recursor n p i m b type rules k s => .recursor n p i m b (type.rename mapping) + (rules.map fun r => ⟨r.nfields, r.rhs.rename mapping⟩) k s + +/-- A control input with original declarations under the altered source's +addresses. It intentionally bypasses authentication only to obtain an +independently valid certificate to attack the real serialized gate. -/ +def repaired? (c : Case) (original : ProofInput Nat) : Option PreparedInput := do + let prepared ← prepare? 6400 c.profile c.target c.blobs c.literals + let mapping := fun b => ((c.blocks.find? fun (key, _) => key = b).map Prod.snd).getD c.target + let originals := c.blocks.map fun (b, a) => (a, (if b = 900 then + some (Const.defn original.universes .theorem original.proposition original.proof .safe) + else original.store.lookup (.member b 0)).map (fun source => + (⟨[renameConstant mapping source]⟩ : Block Address))) + let old := prepared.input.store + let store : Store Address := { + dom := old.dom, nodup := old.nodup, + blocks := fun a => (old.blocks a).map fun block => ((lookup originals a).join).getD block, + mem_dom := by intro a; simp [old.mem_dom] } + let target ← store.lookup (.member c.target 0) + return { prepared with input := { prepared.input with store, proposition := target.type } } + +end Tests.Certified.Serialize + +namespace Tests.Certified.Serialize + +open Ix.Theory Ix.Theory.Certified Ix.Certified Ix.Certified.Fixtures + +/-- Rehash an entire fixture after changing one raw blob or constant. Every +reference and projection wrapper is updated in dependency order, so tests of +canonical encoding and field ownership do not merely fail at an old hash. -/ +def rehash? (c : Case) (alterLiteral : ByteArray → ByteArray := id) + (alterConstant : Address → Ixon.Constant → Ixon.Constant := fun _ source => source) : Option Case := do + let mut changed : List (Address × Address) := [] + let mut literals := [] + for (a, bytes) in c.literals do + let bytes := alterLiteral bytes + let a' := Address.blake3 bytes + changed := changed ++ [(a, a')] + literals := literals ++ [(a', bytes)] + let mut blobs := [] + for (a, bytes) in c.blobs do + let source ← decodeObject? a bytes + let rewrite := fun a => (lookup changed a).getD a + let info := match source.val.info with + | .iPrj p => .iPrj { p with block := rewrite p.block } + | .rPrj p => .rPrj { p with block := rewrite p.block } + | .dPrj p => .dPrj { p with block := rewrite p.block } + | .cPrj p => .cPrj { p with block := rewrite p.block } + | info => info + let source := alterConstant a { source.val with info, refs := source.val.refs.map rewrite } + let encoded := encode source + changed := changed ++ [(a, encoded.1)] + blobs := blobs ++ [encoded] + let rewrite := fun a => (lookup changed a).getD a + return { c with + profile := { + falseType := rewrite c.profile.falseType, falseElim := rewrite c.profile.falseElim, + natType := c.profile.natType.map rewrite }, + target := rewrite c.target, blobs, literals, + references := c.references.map fun (r, a) => (r, rewrite a), + blocks := c.blocks.map fun (b, a) => (b, rewrite a) } + +def mapLiterals (index : UInt64) : Ixon.Expr → Ixon.Expr + | .nat _ => .nat index + | .app f a => .app (mapLiterals index f) (mapLiterals index a) + | .lam u A b => .lam u (mapLiterals index A) (mapLiterals index b) + | .all u c A B => .all u c (mapLiterals index A) (mapLiterals index B) + | .prj owner field value => .prj owner field (mapLiterals index value) + | other => other + +end Tests.Certified.Serialize diff --git a/Tests/Certified/Source.lean b/Tests/Certified/Source.lean new file mode 100644 index 000000000..270227d4b --- /dev/null +++ b/Tests/Certified/Source.lean @@ -0,0 +1,272 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.FeatureCases +import Ix.Kernel.Certified +import Ix.Certified.Suggest + +/-! Actual lazy Ixon environments, empty/cached TcM runs, full declaration +subjects and hostile cache/state/selection inputs. -/ + +namespace Tests.Certified.Source + +open Ix.Theory Ix.Theory.Certified Ix.Certified Ix.Kernel Serialize +open Lean (toJson) + +set_option maxRecDepth 32768 +set_option maxHeartbeats 32000000 + +def cases : List Case := + (Corpus.positive.map fun c => { + name := c.name, profile := Fixtures.profile, + target := c.target, blobs := c.blobs, literals := [], references := [], + blocks := c.blobs.map fun (a, _) => (0, a) }) ++ + Features.positive.filterMap fun s => make? s.name s.signature s.input + +#guard cases.length = 42 + +def selection (c : Case) : InputSelection := ⟨c.blobs.map Prod.fst, c.literals.map Prod.fst⟩ + +/-- All constants are real offset windows with no materialized cache. -/ +def source (c : Case) : Ixon.Env := Id.run do + let mut env : Ixon.Env := { main := some c.target } + for (a, bytes) in c.blobs do + let backing := (ByteArray.mk #[17, 19]) ++ bytes ++ (ByteArray.mk #[23]) + env := { env with consts := env.consts.insert a (Ixon.LazyConstant.ofSlice backing 2 bytes.size) } + for (a, bytes) in c.literals do env := { env with blobs := env.blobs.insert a bytes } + return env + +def subjects (c : Case) : List Address := + c.blocks.map Prod.snd + +def accepted (c : Case) : Bool := + let env := source c + (suggestSource? 6400 env c.profile c.target (selection c)).any fun w => + acceptsCertifiedSource.{0} 6400 env c.profile c.target (selection c) w + +def storeAccepted (c : Case) : Bool := + let env := source c + (suggestStore? 6400 env c.profile (subjects c) (selection c)).any fun w => + acceptsCertifiedStoreSource.{0} 6400 env c.profile (subjects c) (selection c) w + +#guard cases.all accepted +#guard cases.all storeAccepted + +/-- A forged legacy equivalence, type cache, block verdict and inference-only +flag are carried through the actual TcM state. Certified checking is full and +independent of each of these fields. -/ +def poisonedChecker (c : Case) : TcState .anon := + let state := TcState.ofEnvAnon {} + let lhs : KExpr .anon := KExpr.mkNatLit 0 + let rhs : KExpr .anon := KExpr.mkConst ⟨c.profile.falseType, ()⟩ #[] + { state with + inferOnly := true, eagerReduce := true, recFuel := 0, noAccel := false, + equivManager := state.equivManager.addEquiv ⟨lhs.addr, state.ctxId, 0, 0⟩ ⟨rhs.addr, state.ctxId, 0, 0⟩, + env := { state.env with + inferCache := state.env.inferCache.insert (lhs.addr, state.ctxId) rhs, + inferOnlyCache := state.env.inferOnlyCache.insert (lhs.addr, state.ctxId) rhs, + whnfCache := state.env.whnfCache.insert (lhs.addr, state.ctxId) rhs, + defEqCache := state.env.defEqCache.insert (lhs.addr, rhs.addr, state.ctxId) true, + blockCheckResults := state.env.blockCheckResults.insert ⟨c.target, ()⟩ (.ok ()) } } + +def warmAndRollback (c : Case) : Bool := Id.run do + let env := source c + let count := c.blobs.length + c.literals.length + let some w := suggestSource? 6400 env c.profile c.target (selection c) | return false + let .ok _ cold := (certifiedStep.{0} 6400 env c.profile c.target (selection c) w).run initialCertifiedState | return false + if cold.inputCache.misses != count || cold.inputCache.hits != 0 then return false + let start := { cold with checker := poisonedChecker c } + let .ok _ warm := (certifiedStep.{0} 6400 env c.profile c.target (selection c) w).run start | return false + if warm.inputCache.hits != count || warm.inputCache.misses != count then return false + if !warm.checker.inferOnly || warm.checker.recFuel != 0 then return false + let bad := { w with proofWitness := .sort } + let .error _ failed := (certifiedStep.{0} 6400 env c.profile c.target (selection c) bad).run warm | return false + if failed.inputCache.hits != warm.inputCache.hits || failed.inputCache.misses != warm.inputCache.misses then return false + let .error _ exhausted := (certifiedStep.{0} 0 env c.profile c.target (selection c) w).run failed | return false + if exhausted.inputCache.hits != warm.inputCache.hits || exhausted.inputCache.misses != warm.inputCache.misses then return false + let .ok _ retry := (certifiedStep.{0} 6400 env c.profile c.target (selection c) w).run exhausted | return false + return retry.inputCache.hits == 2 * count && retry.inputCache.misses == count + +#guard cases.all warmAndRollback + +def loadedIxe? (c : Case) : Option (ByteArray × Ixon.Env) := do + let bytes ← (Ixon.serEnv (source c)).toOption + let parts ← (Ixon.deEnvVerifiedLazy bytes).toOption + return (bytes, parts.env) + +def ixeAccepted (c : Case) : Bool := Id.run do + let some (_, env) := loadedIxe? c | return false + let some target := env.consts.get? c.target | return false + if target.cache.isSome || target.buf.size ≤ target.len then return false + let some w := suggestSource? 6400 env c.profile c.target (selection c) | return false + return acceptsCertifiedSource.{0} 6400 env c.profile c.target (selection c) w + +#guard cases.all ixeAccepted + +def extraMalformed : Address := Address.blake3 "C5-unvisited-malformed-constant".toUTF8 + +def lazyOnlySelected (c : Case) : Bool := Id.run do + let raw := source c + let env := { raw with + consts := raw.consts.insert extraMalformed + (Ixon.LazyConstant.ofSlice (ByteArray.mk #[255, 254]) 0 2) } + let some w := suggestSource? 6400 env c.profile c.target (selection c) | return false + return env.consts.size > c.blobs.length && + acceptsCertifiedSource.{0} 6400 env c.profile c.target (selection c) w && + !acceptsCertifiedSource.{0} 6400 env c.profile c.target + ⟨extraMalformed :: (selection c).objects, (selection c).naturals⟩ w + +#guard cases.all lazyOnlySelected + +def materializedCacheIgnored (c : Case) : Bool := Id.run do + let raw := source c + let some entry := raw.consts.get? c.target | return false + let bogus : Ixon.Constant := ⟨.axio ⟨false, 0, .sort 0⟩, #[], #[], #[.zero]⟩ + let env := { raw with consts := raw.consts.insert c.target { entry with cache := some bogus } } + let some w := suggestSource? 6400 env c.profile c.target (selection c) | return false + return acceptsCertifiedSource.{0} 6400 env c.profile c.target (selection c) w + +#guard cases.all materializedCacheIgnored + +/-- Warm byte caches must not hide changed source bytes, windows, pins, +missing dependencies, or a modified selection. -/ +def hostileSource (c : Case) : Bool := Id.run do + let env := source c + let some w := suggestSource? 6400 env c.profile c.target (selection c) | return false + let .ok _ warm := (certifiedStep.{0} 6400 env c.profile c.target (selection c) w).run initialCertifiedState | return false + let some entry := env.consts.get? c.target | return false + let changed := { env with + consts := env.consts.insert c.target + (Ixon.LazyConstant.ofSlice (entry.rawBytes.push 0) 0 (entry.rawBytes.size + 1)) } + let .error _ _ := (certifiedStep.{0} 6400 changed c.profile c.target (selection c) w).run warm | return false + let outside := { env with consts := env.consts.insert c.target { entry with off := entry.buf.size + 1 } } + let .error _ _ := (certifiedStep.{0} 6400 outside c.profile c.target (selection c) w).run warm | return false + let truncated := { env with consts := env.consts.insert c.target { entry with len := entry.buf.size + 1 } } + let .error _ _ := (certifiedStep.{0} 6400 truncated c.profile c.target (selection c) w).run warm | return false + let missing := { (selection c) with objects := (selection c).objects.filter (· != c.target) } + let .error _ _ := (certifiedStep.{0} 6400 env c.profile c.target missing w).run warm | return false + let duplicate := { (selection c) with objects := c.target :: (selection c).objects } + let .error _ _ := (certifiedStep.{0} 6400 env c.profile c.target duplicate w).run warm | return false + let badProfile := { c.profile with falseType := c.profile.falseElim, falseElim := c.profile.falseType } + let .error _ _ := (certifiedStep.{0} 6400 env badProfile c.target (selection c) w).run warm | return false + let reordered := { (selection c) with objects := (selection c).objects.reverse, naturals := (selection c).naturals.reverse } + let .ok _ _ := (certifiedStep.{0} 6400 env c.profile c.target reordered w).run warm | return false + return true + +#guard cases.all hostileSource + +def rejectsMutation (m : Features.Mutation) : Bool := Id.run do + let some c := make? m.name m.signature m.altered | return false + let some p := repaired? c m.original | return false + let some w := Ix.Theory.Certificate.proofWitness? 6400 p.signature p.input | return false + return acceptsCertified.{0,0} 6400 p.signature p.input w && + !acceptsCertifiedSource.{0} 6400 (source c) c.profile c.target (selection c) w + +#guard Features.mutatedSources.all rejectsMutation + + +def rejectsStoreMutation (m : Features.Mutation) : Bool := Id.run do + let some c := make? m.name m.signature m.altered | return false + let some p := repaired? c m.original | return false + let some w := Ix.Theory.Certificate.proofWitness? 6400 p.signature p.input | return false + return acceptsStoreCertified.{0,0} 6400 p.signature p.input.store [.member c.target 0] w.declarations && + !acceptsCertifiedStoreSource.{0} 6400 (source c) c.profile [c.target] (selection c) w.declarations + +#guard Features.mutatedSources.all rejectsStoreMutation + +def rejectsIngressMutation (m : Features.IngressMutation) : Bool := + m.altered.any fun c => + match readSnapshot? 6400 (source c) (selection c) {} with + | none => true + | some (snapshot, _) => (snapshot.prepare? 6400 c.profile c.target).isNone + +#guard Features.ingressMutations.all rejectsIngressMutation + +def naturalState : Bool := Id.run do + let some c := Features.naturalCase | return false + let env := source c + let some w := suggestSource? 6400 env c.profile c.target (selection c) | return false + let .ok _ warm := (certifiedStep.{0} 6400 env c.profile c.target (selection c) w).run initialCertifiedState | return false + for alter in [Features.missingPin, Features.wrongPin] do + let other := alter c + let .error _ _ := (certifiedStep.{0} 6400 env other.profile c.target (selection c) w).run warm | return false + let some (literal, bytes) := c.literals.head? | return false + let changed := { env with blobs := env.blobs.insert literal (bytes.push 1) } + let .error _ _ := (certifiedStep.{0} 6400 changed c.profile c.target (selection c) w).run warm | return false + let missing := { env with blobs := env.blobs.erase literal } + let .error _ _ := (certifiedStep.{0} 6400 missing c.profile c.target (selection c) w).run warm | return false + let some recursor := reference c.references (.member 201 0) | return false + let thin := { (selection c) with objects := (selection c).objects.filter (· != recursor) } + let assumed := { env with assumptions := env.assumptions.insert recursor } + let .error _ _ := (certifiedStep.{0} 6400 assumed c.profile c.target thin w).run warm | return false + let reversed := { w with declarations := w.declarations.reverse } + let .error _ _ := (certifiedStep.{0} 6400 env c.profile c.target (selection c) reversed).run warm | return false + return true + +#guard naturalState + +def storeRollback (c : Case) : Bool := Id.run do + let env := source c + let some w := suggestStore? 6400 env c.profile (subjects c) (selection c) | return false + let .ok _ cold := (certifiedStoreStep.{0} 6400 env c.profile (subjects c) (selection c) w).run initialCertifiedState | return false + let start := { cold with checker := poisonedChecker c } + let .ok _ warm := (certifiedStoreStep.{0} 6400 env c.profile (subjects c) (selection c) w).run start | return false + let .error _ failed := (certifiedStoreStep.{0} 6400 env c.profile (subjects c) (selection c) []).run warm | return false + if failed.inputCache.hits != warm.inputCache.hits || failed.inputCache.misses != warm.inputCache.misses then return false + let .ok _ retry := (certifiedStoreStep.{0} 6400 env c.profile (subjects c) (selection c) w).run failed | return false + return retry.inputCache.misses == cold.inputCache.misses + +#guard cases.all storeRollback + +def emptyBlockRejected : Bool := Id.run do + let empty := Fixtures.encode ⟨.muts #[], #[], #[], #[]⟩ + let c : Case := { + name := "empty-source-block", profile := Fixtures.profile, target := empty.1, + blobs := Fixtures.prelude ++ [empty], literals := [], references := [], blocks := [] } + return !acceptsCertifiedStoreSource.{0} 6400 (source c) c.profile [empty.1] (selection c) [] + +#guard emptyBlockRejected + +def writeCase (directory : System.FilePath) (c : Case) : IO Unit := do + let some (bytes, _) := loadedIxe? c | throw (IO.userError s!"cannot serialize source case: {c.name}") + let directory := directory / c.name + IO.FS.createDirAll directory + IO.FS.writeBinFile (directory / "source.ixe") bytes + let request := Lean.Json.mkObj [ + ("target", toJson (hexOfBytes c.target.hash)), + ("subjects", toJson ((subjects c).map fun a => hexOfBytes a.hash)), + ("falseType", toJson (hexOfBytes c.profile.falseType.hash)), + ("falseElim", toJson (hexOfBytes c.profile.falseElim.hash)), + ("natType", toJson (c.profile.natType.map fun a => hexOfBytes a.hash)), + ("objects", toJson ((selection c).objects.map fun a => hexOfBytes a.hash)), + ("naturals", toJson ((selection c).naturals.map fun a => hexOfBytes a.hash))] + IO.FS.writeFile (directory / "request.json") (request.pretty ++ "\n") + +def run (directory : Option System.FilePath) : IO Unit := do + for c in cases do + for (name, test) in [("proof", accepted), ("declarations", storeAccepted), + ("cache-and-rollback", warmAndRollback), ("ixe", ixeAccepted), + ("lazy-selection", lazyOnlySelected), ("materialized-cache", materializedCacheIgnored), + ("hostile-source", hostileSource), ("store-rollback", storeRollback)] do + unless test c do throw (IO.userError s!"{name} failed: {c.name}") + if let some directory := directory then writeCase directory c + for m in Features.mutatedSources do + unless rejectsMutation m && rejectsStoreMutation m do + throw (IO.userError s!"source mutation escaped a TcM gate: {m.name}") + for m in Features.ingressMutations do + unless rejectsIngressMutation m do throw (IO.userError s!"ingress mutation escaped: {m.name}") + unless naturalState && emptyBlockRejected do throw (IO.userError "profile/dependency or empty-block rejection failed") + IO.println <| (Lean.Json.mkObj [ + ("proofAccepted", toJson cases.length), ("storesAccepted", toJson cases.length), + ("ixeAccepted", toJson cases.length), ("warmProofScenarios", toJson cases.length), + ("warmStoreScenarios", toJson cases.length), ("lazySelectionScenarios", toJson cases.length), + ("materializedCacheScenarios", toJson cases.length), ("hostileSourceScenarios", toJson cases.length), + ("proofSourceMutationsRejected", toJson Features.mutatedSources.length), + ("storeSourceMutationsRejected", toJson Features.mutatedSources.length), + ("ingressMutationsRejected", toJson Features.ingressMutations.length), + ("naturalStateScenario", toJson true), ("emptyBlockRejected", toJson true), + ("unexpectedErrors", toJson (0 : Nat))]).compress + +end Tests.Certified.Source diff --git a/Tests/Certified/SourceMain.lean b/Tests/Certified/SourceMain.lean new file mode 100644 index 000000000..78bb696fc --- /dev/null +++ b/Tests/Certified/SourceMain.lean @@ -0,0 +1,13 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Certified.Source + +def main (args : List String) : IO UInt32 := do + if args.length > 1 then + IO.eprintln "usage: certified-source-tests [OUTPUT_DIRECTORY]" + return 2 + Tests.Certified.Source.run (args.head?.map System.FilePath.mk) + return 0 diff --git a/Tests/Certified/foundation.txt b/Tests/Certified/foundation.txt new file mode 100644 index 000000000..5bd8291bd --- /dev/null +++ b/Tests/Certified/foundation.txt @@ -0,0 +1,4243 @@ +ROOT Ix.Certified.decodeObject? +(address : Address) → (bytes : ByteArray) → Option (DecodedObject address bytes) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.decodeNatural? +(address : Address) → + (bytes : ByteArray) → + Option + { value // + address.hash.size = 32 ∧ + Address.blake3 bytes = address ∧ Nat.fromBytesLE bytes.data = value ∧ { data := value.toBytesLE } = bytes } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.readSignature? +Profile → Objects → Option (Theory.Certified.PrimitiveSignature Address) +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.prepare? +Nat → Profile → Address → ConstantBlobs → optParam ConstantBlobs [] → Option PreparedInput +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.acceptsSerialized_prepared +∀ {fuel : Nat} {profile : Profile} {target : Address} {blobs literalBlobs : ConstantBlobs} + {witness : Theory.Certified.ProofWitness Address}, + acceptsSerialized fuel profile target blobs witness literalBlobs = true → + ∃ prepared, + prepare? fuel profile target blobs literalBlobs = some prepared ∧ + Theory.Certified.acceptsCertified fuel prepared.signature prepared.input witness = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.accepted_serialized_has_model +∀ {fuel : Nat} {profile : Profile} {target : Address} {blobs literalBlobs : ConstantBlobs} + {witness : Theory.Certified.ProofWitness Address}, + acceptsSerialized fuel profile target blobs witness literalBlobs = true → + ∀ (V : Type v) [inst : Theory.Model.SetTheory V] (levels : List Nat) (env : Nat → V), + ∃ prepared, + prepare? fuel profile target blobs literalBlobs = some prepared ∧ + ∃ result, + Theory.Certified.checkProofCertified fuel prepared.signature prepared.input witness = some result ∧ + ∃ constants, + prepared.signature.Compatible result.environment.entries constants ∧ + Theory.Model.WellDenoted constants levels env result.proof.val ∧ + Theory.Model.WellDenoted constants levels env result.proposition.val ∧ + Theory.Model.SetTheory.Mem (Theory.Model.interp constants levels env result.proof.val) + (Theory.Model.interp constants levels env result.proposition.val) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.no_serialized_proof_of_False +∀ {fuel : Nat} {profile : Profile} {target : Address} {blobs literalBlobs : ConstantBlobs} + {witness : Theory.Certified.ProofWitness Address} (V : Type v) [Theory.Model.SetTheory V], + isFalseStatement fuel profile target blobs literalBlobs = true → + acceptsSerialized fuel profile target blobs witness literalBlobs = true → False +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.constantBytes? +Ixon.Env → Address → Option ByteArray +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.decodeObject_complete +∀ {address : Address} {bytes : ByteArray} (value : DecodedObject address bytes), + decodeObject? address bytes = some value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.decodeNatural_complete +∀ {address : Address} {bytes : ByteArray} (value : DecodedNatural address bytes), + decodeNatural? address bytes = some value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.SourceSnapshot.prepare_eq +∀ {source : Ixon.Env} (fuel : Nat) (profile : Profile) (target : Address) (snapshot : SourceSnapshot source), + prepare? fuel profile target snapshot.blobs snapshot.literalBlobs = + SourceSnapshot.prepare? fuel profile target snapshot +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.SourceSnapshot.prepareStore_eq +∀ {source : Ixon.Env} (fuel : Nat) (profile : Profile) (subjects : List Address) (snapshot : SourceSnapshot source), + prepareStore? fuel profile subjects snapshot.blobs snapshot.literalBlobs = + SourceSnapshot.prepareStore? fuel profile subjects snapshot +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.SourceSnapshot.objects_from_source +∀ {source : Ixon.Env} (snapshot : SourceSnapshot source) {address : Address} {bytes : ByteArray}, + (address, bytes) ∈ snapshot.blobs → constantBytes? source address = some bytes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.SourceSnapshot.naturals_from_source +∀ {source : Ixon.Env} (snapshot : SourceSnapshot source) {address : Address} {bytes : ByteArray}, + (address, bytes) ∈ snapshot.literalBlobs → source.getBlob? address = some bytes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.SourceReceipt.serialized +∀ {source : Ixon.Env} {fuel : Nat} {profile : Profile} {target : Address} + {witness : Theory.Certified.ProofWitness Address} (receipt : SourceReceipt source fuel profile target witness), + acceptsSerialized fuel profile target receipt.snapshot.blobs witness receipt.snapshot.literalBlobs = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.StoreReceipt.serialized +∀ {source : Ixon.Env} {fuel : Nat} {profile : Profile} {subjects : List Address} + {witness : List (Theory.Certified.DeclarationWitness Address)} + (receipt : StoreReceipt source fuel profile subjects witness), + acceptsSerializedStore fuel profile subjects receipt.snapshot.blobs witness receipt.snapshot.literalBlobs = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.accepted_serialized_store_has_model +∀ {fuel : Nat} {profile : Profile} {subjects : List Address} {blobs literalBlobs : ConstantBlobs} + {witness : List (Theory.Certified.DeclarationWitness Address)}, + acceptsSerializedStore fuel profile subjects blobs witness literalBlobs = true → + ∀ (V : Type v) [inst : Theory.Model.SetTheory V], + ∃ prepared, + prepareStore? fuel profile subjects blobs literalBlobs = some prepared ∧ + ∃ result, + Theory.Certified.checkStoreCertified fuel prepared.signature prepared.store prepared.targets witness = + some result ∧ + ∃ constants, + prepared.signature.Compatible result.environment.entries constants ∧ + ∀ (r : Theory.ConstRef Address), + r ∈ prepared.targets → + ∃ entry, + result.environment.entries r = some entry ∧ + Theory.Certified.EntrySource prepared.signature prepared.store r entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Theory.Model.WellDenoted constants levels env entry.type ∧ + Theory.Model.SetTheory.Mem (constants r levels) + (Theory.Model.interp constants levels env entry.type) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.TcM.checkCertified_success +∀ {m : Kernel.Mode} {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} {selection : InputSelection} + {witness : Theory.Certified.ProofWitness Address} {cache nextCache : InputCache} {before after : Kernel.TcState m} + {receipt : SourceReceipt source fuel profile target witness}, + EStateM.run (Kernel.TcM.checkCertified fuel source profile target selection witness cache) before = + EStateM.Result.ok (receipt, nextCache) after → + checkSource? fuel source profile target selection witness cache = some (receipt, nextCache) ∧ after = before +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.TcM.checkCertified_failure +∀ {m : Kernel.Mode} {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} {selection : InputSelection} + {witness : Theory.Certified.ProofWitness Address} {cache : InputCache} {before after : Kernel.TcState m} + {error : Kernel.TcError m}, + EStateM.run (Kernel.TcM.checkCertified fuel source profile target selection witness cache) before = + EStateM.Result.error error after → + checkSource? fuel source profile target selection witness cache = none ∧ after = before +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.TcM.checkStoreCertified_success +∀ {m : Kernel.Mode} {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} + {selection : InputSelection} {witness : List (Theory.Certified.DeclarationWitness Address)} + {cache nextCache : InputCache} {before after : Kernel.TcState m} + {receipt : StoreReceipt source fuel profile subjects witness}, + EStateM.run (Kernel.TcM.checkStoreCertified fuel source profile subjects selection witness cache) before = + EStateM.Result.ok (receipt, nextCache) after → + checkSourceStore? fuel source profile subjects selection witness cache = some (receipt, nextCache) ∧ after = before +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.certifiedStep_success +∀ {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} {selection : InputSelection} + {witness : Theory.Certified.ProofWitness Address} {before after : Kernel.CertifiedState} + {receipt : SourceReceipt source fuel profile target witness}, + (Kernel.certifiedStep fuel source profile target selection witness).run before = EStateM.Result.ok receipt after → + checkSource? fuel source profile target selection witness before.inputCache = some (receipt, after.inputCache) ∧ + after.checker = before.checker +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.certifiedStep_failure +∀ {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} {selection : InputSelection} + {witness : Theory.Certified.ProofWitness Address} {before after : Kernel.CertifiedState} + {error : Kernel.TcError Kernel.Mode.anon}, + (Kernel.certifiedStep fuel source profile target selection witness).run before = EStateM.Result.error error after → + after = before +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.certifiedStoreStep_success +∀ {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} {selection : InputSelection} + {witness : List (Theory.Certified.DeclarationWitness Address)} {before after : Kernel.CertifiedState} + {receipt : StoreReceipt source fuel profile subjects witness}, + (Kernel.certifiedStoreStep fuel source profile subjects selection witness).run before = + EStateM.Result.ok receipt after → + checkSourceStore? fuel source profile subjects selection witness before.inputCache = + some (receipt, after.inputCache) ∧ + after.checker = before.checker +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.certifiedStoreStep_failure +∀ {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} {selection : InputSelection} + {witness : List (Theory.Certified.DeclarationWitness Address)} {before after : Kernel.CertifiedState} + {error : Kernel.TcError Kernel.Mode.anon}, + (Kernel.certifiedStoreStep fuel source profile subjects selection witness).run before = + EStateM.Result.error error after → + after = before +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.initialCertifiedState +Kernel.CertifiedState +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.accepted_tc_has_model +∀ {fuel : Nat} {source : Ixon.Env} {profile : Profile} {target : Address} {selection : InputSelection} + {witness : Theory.Certified.ProofWitness Address}, + Kernel.acceptsCertifiedSource fuel source profile target selection witness = true → + ∀ (V : Type v) [inst : Theory.Model.SetTheory V] (levels : List Nat) (env : Nat → V), + ∃ receipt, + Kernel.runCertified fuel source profile target selection witness = some receipt ∧ + (∀ (address : Address) (bytes : ByteArray), + (address, bytes) ∈ receipt.snapshot.blobs → constantBytes? source address = some bytes) ∧ + (∀ (address : Address) (bytes : ByteArray), + (address, bytes) ∈ receipt.snapshot.literalBlobs → source.getBlob? address = some bytes) ∧ + ∃ constants, + receipt.prepared.signature.Compatible receipt.proof.environment.entries constants ∧ + Theory.Model.WellDenoted constants levels env receipt.proof.proof.val ∧ + Theory.Model.WellDenoted constants levels env receipt.proof.proposition.val ∧ + Theory.Model.SetTheory.Mem (Theory.Model.interp constants levels env receipt.proof.proof.val) + (Theory.Model.interp constants levels env receipt.proof.proposition.val) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.accepted_tc_store_has_model +∀ {fuel : Nat} {source : Ixon.Env} {profile : Profile} {subjects : List Address} {selection : InputSelection} + {witness : List (Theory.Certified.DeclarationWitness Address)}, + Kernel.acceptsCertifiedStoreSource fuel source profile subjects selection witness = true → + ∀ (V : Type v) [inst : Theory.Model.SetTheory V], + ∃ receipt, + Kernel.runCertifiedStore fuel source profile subjects selection witness = some receipt ∧ + (∀ (address : Address) (bytes : ByteArray), + (address, bytes) ∈ receipt.snapshot.blobs → constantBytes? source address = some bytes) ∧ + (∀ (address : Address) (bytes : ByteArray), + (address, bytes) ∈ receipt.snapshot.literalBlobs → source.getBlob? address = some bytes) ∧ + ∃ constants, + receipt.prepared.signature.Compatible receipt.result.environment.entries constants ∧ + ∀ (r : Theory.ConstRef Address), + r ∈ receipt.prepared.targets → + ∃ entry, + receipt.result.environment.entries r = some entry ∧ + Theory.Certified.EntrySource receipt.prepared.signature receipt.prepared.store r entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Theory.Model.WellDenoted constants levels env entry.type ∧ + Theory.Model.SetTheory.Mem (constants r levels) + (Theory.Model.interp constants levels env entry.type) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.no_tc_proof_of_False +∀ {source : Ixon.Env} {fuel : Nat} {profile : Profile} {target : Address} + {witness : Theory.Certified.ProofWitness Address} (receipt : SourceReceipt source fuel profile target witness) + (V : Type v) [Theory.Model.SetTheory V], + receipt.prepared.input.proposition = receipt.prepared.signature.falseExpr → False +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.Command.run_success +∀ {mode : String} {fuel : Nat} {source : Ixon.Env} {request : Command.Request}, + Command.run mode fuel source request = Except.ok () → + (mode = "proof" ∧ + ∃ witness, + Kernel.acceptsCertifiedSource fuel source request.profile request.target request.selection witness = true) ∨ + mode = "store" ∧ + ∃ witness, + Kernel.acceptsCertifiedStoreSource fuel source request.profile request.subjects request.selection witness = + true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.resolveReference_iff +∀ {objects : Objects} {address : Address} {ref : Theory.ConstRef Address}, + resolveReference? objects address = some ref ↔ ReferenceMeaning objects address ref +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.readLevel_value +∀ (level : Ixon.Univ) (levels : List Nat), Theory.VLevel.eval levels (readLevel level) = sourceLevelValue levels level +AXIOMS [propext] +ROOT Ix.Certified.readExpr_sound +∀ {fuel : Nat} {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} + {expression : Ixon.Expr} {reading : Theory.VExpr Address}, + readExpr? fuel objects naturals block source expression = some reading → + ExprReading objects naturals block source expression reading +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.ExprReading.unique +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {expression : Ixon.Expr} + {left right : Theory.VExpr Address}, + ExprReading objects naturals block source expression left → + ExprReading objects naturals block source expression right → left = right +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.readExpr_fuel_independent +∀ {fuel₁ fuel₂ : Nat} {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} + {expression : Ixon.Expr} {left right : Theory.VExpr Address}, + readExpr? fuel₁ objects naturals block source expression = some left → + readExpr? fuel₂ objects naturals block source expression = some right → left = right +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.readBlock_sourceHeader +∀ {fuel : Nat} {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} + {result : Theory.Block Address} {ref : Theory.ConstRef Address} {universes : Nat} {type : Theory.VExpr Address}, + readBlock? fuel objects naturals block source = some result → + blockHeader? result ref = some (universes, type) → + ∃ raw, rawHeader? source ref = some (universes, raw) ∧ ExprReading objects naturals block source raw type +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.readStore_sourceHeader +∀ {fuel : Nat} {objects : Objects} {naturals : Naturals} {store : Theory.Store Address} {ref : Theory.ConstRef Address} + {entry : Theory.Model.ConstantEntry Address}, + readStore? fuel objects naturals = some store → + Theory.Certified.SourceHeader store ref entry → + ∃ source raw, + lookup objects ref.block = some source ∧ + rawHeader? source ref = some (entry.universes, raw) ∧ + ExprReading objects naturals ref.block source raw entry.type.erase +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.SourceSnapshot.object_bytes +∀ {source : Ixon.Env} (snapshot : SourceSnapshot source) {address : Address} {value : Ixon.Constant}, + lookup snapshot.decodedObjects address = some value → ∃ bytes, ObjectBytes source address bytes value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.SourceSnapshot.natural_bytes +∀ {source : Ixon.Env} (snapshot : SourceSnapshot source) {address : Address} {value : Nat}, + lookup snapshot.decodedNaturals address = some value → ∃ bytes, NaturalBytes source address bytes value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.readSignature_sound +∀ {profile : Profile} {objects : Objects} {signature : Theory.Certified.PrimitiveSignature Address}, + readSignature? profile objects = some signature → SignatureReading profile objects signature +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.StoreReceipt.subject_meaning +∀ {source : Ixon.Env} {fuel : Nat} {profile : Profile} {subjects : List Address} + {witness : List (Theory.Certified.DeclarationWitness Address)} + (receipt : StoreReceipt source fuel profile subjects witness) {ref : Theory.ConstRef Address}, + ref ∈ receipt.prepared.targets → + ∃ entry, + receipt.result.environment.entries ref = some entry ∧ + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry ∧ + ∀ (V : Type v) [inst : Theory.Model.SetTheory V] (constants : Theory.Model.Assignment Address V), + receipt.prepared.signature.Compatible receipt.result.environment.entries constants → + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Theory.Model.WellDenoted constants levels env entry.type ∧ + Theory.Model.SetTheory.Mem (constants ref levels) + (Theory.Model.interp constants levels env entry.type) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.SourceReceipt.proposition_meaning +∀ {source : Ixon.Env} {fuel : Nat} {profile : Profile} {target : Address} + {witness : Theory.Certified.ProofWitness Address} (receipt : SourceReceipt source fuel profile target witness), + SignatureReading profile receipt.snapshot.decodedObjects receipt.prepared.signature ∧ + ∃ ref bytes declaration rawType, + ReferenceMeaning receipt.snapshot.decodedObjects target ref ∧ + ObjectBytes source ref.block bytes declaration ∧ + rawHeader? declaration ref = some (receipt.prepared.input.universes, rawType) ∧ + ExprReading receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref.block declaration rawType + receipt.proof.proposition.val.erase ∧ + ∀ (V : Type v) [inst : Theory.Model.SetTheory V] (constants : Theory.Model.Assignment Address V), + receipt.prepared.signature.Compatible receipt.proof.environment.entries constants → + ∀ (levels : List Nat) (env : Nat → V), + Theory.Model.WellDenoted constants levels env receipt.proof.proposition.val ∧ + Theory.Model.SetTheory.Mem + (Theory.Model.interp constants levels env receipt.proof.proposition.val) + (Theory.Model.SetTheory.univ 0) ∧ + Theory.Model.SetTheory.Mem (Theory.Model.interp constants levels env receipt.proof.proof.val) + (Theory.Model.interp constants levels env receipt.proof.proposition.val) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.StoreReceipt.subject_coverage +∀ {source : Ixon.Env} {fuel : Nat} {profile : Profile} {subjects : List Address} + {witness : List (Theory.Certified.DeclarationWitness Address)} + (receipt : StoreReceipt source fuel profile subjects witness) (ref : Theory.ConstRef Address), + ref ∈ receipt.prepared.targets ↔ + ∃ subject, subject ∈ subjects ∧ ∃ refs, SubjectReading receipt.snapshot.decodedObjects subject refs ∧ ref ∈ refs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.TreeOpening.membership +∀ {fuel : Nat} {root : Address} {bytes : ByteArray} (opening : TreeOpening fuel root bytes) {target : Address}, + target ∈ treeLeaves opening.tree → TreeMembership root target +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.TreeOpening.unique +∀ {fuel : Nat} {root : Address} {bytes : ByteArray} {a b : TreeOpening fuel root bytes}, a.tree = b.tree +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.treeLeaves_join +∀ (left right : AssumptionTree) (address : Address), + address ∈ treeLeaves (left.node right) ↔ address ∈ treeLeaves left ∨ address ∈ treeLeaves right +AXIOMS [propext] +ROOT Ix.Certified.EnvelopeReading.unique +∀ {address : Address} {bytes : ByteArray} {a b : EnvelopeReading address bytes}, a.envelope = b.envelope +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.readEnvelope? +Nat → (address : Address) → (bytes : ByteArray) → Option (EnvelopeReading address bytes) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.readTree? +(fuel : Nat) → (root : Address) → (bytes : ByteArray) → Option (TreeOpening fuel root bytes) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.LogicalChecking.original_subject +∀ {source : Ixon.Env} {snapshot : SourceSnapshot source} {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + (checked : LogicalChecking snapshot fuel envelope witness) {ref : Theory.ConstRef Address}, + ref ∈ checked.subjects → + ∃ entry, + checked.batch.receipt.checked.result.entries ref = some entry ∧ + SourceDeclarationReading source snapshot.decodedObjects snapshot.decodedNaturals ref entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.LogicalChecking.original_frontier +∀ {source : Ixon.Env} {snapshot : SourceSnapshot source} {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + (checked : LogicalChecking snapshot fuel envelope witness) {ref : Theory.ConstRef Address}, + ref ∈ checked.frontierRefs → + ∃ entry, + checked.batch.receipt.frontier.interface.entries ref = some entry ∧ + SourceDeclarationReading source snapshot.decodedObjects snapshot.decodedNaturals ref entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.LogicalChecking.logical_policy +∀ {source : Ixon.Env} {snapshot : SourceSnapshot source} {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + (checked : LogicalChecking snapshot fuel envelope witness) {ref : Theory.ConstRef Address}, + ref ∈ checked.axiomRefs → + ∃ entry, + Theory.Certified.Standard.EntrySource checked.store ref entry ∨ + Theory.Certified.Quotient.EntrySource checked.store ref entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.LogicalChecking.closed_frontier +∀ {source : Ixon.Env} {snapshot : SourceSnapshot source} {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + (checked : LogicalChecking snapshot fuel envelope witness), + claimFrontier envelope.claim = none → checked.batch.receipt.frontier.refs = [] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.LogicalReceipt.subject_meaning +∀ {source : Ixon.Env} {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + (receipt : LogicalReceipt source fuel envelope witness) (V : Type v) [inst : Theory.Model.SetTheory V] + (constants : Theory.Model.Assignment Address V), + receipt.checked.signature.Compatible receipt.checked.batch.receipt.frontier.interface.entries constants → + ∃ constants', + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants' ∧ + Theory.Model.Assignment.AgreesOn receipt.checked.batch.receipt.frontier.interface.entries constants constants' ∧ + ∀ (ref : Theory.ConstRef Address), + ref ∈ receipt.checked.subjects → + ∃ entry, + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref + entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Theory.Model.WellDenoted constants' levels env entry.type ∧ + Theory.Model.SetTheory.Mem (constants' ref levels) + (Theory.Model.interp constants' levels env entry.type) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.LogicalReceipt.closed_subject_meaning +∀ {source : Ixon.Env} {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + (receipt : LogicalReceipt source fuel envelope witness), + claimFrontier envelope.claim = none → + ∀ (V : Type v) [inst : Theory.Model.SetTheory V], + ∃ constants, + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants ∧ + ∀ (ref : Theory.ConstRef Address), + ref ∈ receipt.checked.subjects → + ∃ entry, + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref + entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Theory.Model.WellDenoted constants levels env entry.type ∧ + Theory.Model.SetTheory.Mem (constants ref levels) + (Theory.Model.interp constants levels env entry.type) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.LogicalReceipt.no_False +∀ {source : Ixon.Env} {fuel : Nat} {envelope : Envelope} {witness : LogicalWitness} + (receipt : LogicalReceipt source fuel envelope witness), + claimFrontier envelope.claim = none → + ∀ {ref : Theory.ConstRef Address}, + ref ∈ receipt.checked.subjects → + receipt.checked.store.type ref = some receipt.checked.signature.falseExpr → + ∀ (V : Type v) [Theory.Model.SetTheory V], False +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.RevealReceipt.meaning +∀ {source : Ixon.Env} {commitment : Address} {info : RevealConstantInfo} {witness : RevealWitness} + (receipt : RevealReceipt source commitment info witness), RevealMeaning source commitment info +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.ClaimReceipt.meaning +∀ {source : Ixon.Env} {fuel : Nat} {address : Address} {bytes : ByteArray} + (receipt : ClaimReceipt source fuel address bytes), SemanticClaimMeaning source fuel receipt.reading.envelope +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.accepted_claim_meaning +∀ {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} {witness : ClaimWitness}, + acceptsClaimBytes fuel source address bytes witness = true → + ∃ receipt cache, + checkClaimBytes? fuel source address bytes witness { } = some (receipt, cache) ∧ + Address.blake3 bytes = address ∧ + envelopeBytes receipt.reading.envelope = bytes ∧ SemanticClaimMeaning source fuel receipt.reading.envelope +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.evaluation_not_semantic +∀ {source : Ixon.Env} {fuel : Nat} {envelope : Envelope} {input output : Address} {frontier : Option Address}, + envelope.claim = Claim.eval input output frontier → ¬SemanticClaimMeaning source fuel envelope +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.membership_not_leaf +∀ {fuel : Nat} {root target : Address} {bytes : Option ByteArray}, + readSubjectView? fuel (Claim.contains root target) bytes = none +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.revelation_not_leaf +∀ {fuel : Nat} {commitment : Address} {info : RevealConstantInfo} {bytes : Option ByteArray}, + readSubjectView? fuel (Claim.reveal commitment info) bytes = none +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.TcM.checkClaimCertified_success +∀ {m : Kernel.Mode} {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} {witness : ClaimWitness} + {cache nextCache : InputCache} {before after : Kernel.TcState m} {receipt : ClaimReceipt source fuel address bytes}, + EStateM.run (Kernel.TcM.checkClaimCertified fuel source address bytes witness cache) before = + EStateM.Result.ok (receipt, nextCache) after → + checkClaimBytes? fuel source address bytes witness cache = some (receipt, nextCache) ∧ after = before +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.certifiedClaimStep_failure +∀ {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} {witness : ClaimWitness} + {before after : Kernel.CertifiedState} {error : Kernel.TcError Kernel.Mode.anon}, + (Kernel.certifiedClaimStep fuel source address bytes witness).run before = EStateM.Result.error error after → + after = before +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.certifiedClaimStep_success +∀ {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} {witness : ClaimWitness} + {before after : Kernel.CertifiedState} {receipt : ClaimReceipt source fuel address bytes}, + (Kernel.certifiedClaimStep fuel source address bytes witness).run before = EStateM.Result.ok receipt after → + checkClaimBytes? fuel source address bytes witness before.inputCache = some (receipt, after.inputCache) ∧ + after.checker = before.checker +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.accepted_tc_claim_meaning +∀ {fuel : Nat} {source : Ixon.Env} {address : Address} {bytes : ByteArray} {witness : ClaimWitness}, + Kernel.acceptsCertifiedClaim fuel source address bytes witness = true → + ∃ receipt, + Kernel.runCertifiedClaim fuel source address bytes witness = some receipt ∧ + Address.blake3 bytes = address ∧ + envelopeBytes receipt.reading.envelope = bytes ∧ SemanticClaimMeaning source fuel receipt.reading.envelope +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.ClaimCommand.readRequest +Lean.Json → Except String ClaimCommand.Request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.ClaimCommand.run_success +∀ {fuel : Nat} {source : Ixon.Env} {bytes : ByteArray} {request : ClaimCommand.Request}, + ClaimCommand.run fuel source bytes request = Except.ok () → + ∃ witness, Kernel.acceptsCertifiedClaim fuel source request.address bytes witness = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.ClaimCommand.run_meaning +∀ {fuel : Nat} {source : Ixon.Env} {bytes : ByteArray} {request : ClaimCommand.Request}, + ClaimCommand.run fuel source bytes request = Except.ok () → + ∃ receipt, + Address.blake3 bytes = request.address ∧ + envelopeBytes receipt.reading.envelope = bytes ∧ SemanticClaimMeaning source fuel receipt.reading.envelope +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Theory.Certified.Modeled.check?_sound +∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Theory.Model.Environment β} {store : Theory.Store β} + {witness : Theory.Certified.Modeled.Witness β} + {result : Theory.Certified.CheckedClaim (Theory.Certified.Modeled.Checked entries store witness)}, + Theory.Certified.Modeled.check? fuel entries store witness = some result → + Theory.Certified.Modeled.Checked entries store witness +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Theory.Certified.Modeled.checkEquation?_sound +∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Theory.Model.Environment β} + {rule : Theory.Certified.Signature.Rule β} {witness : Theory.Certified.Modeled.EquationWitness β} + {result : Theory.Certified.CheckedClaim (Theory.Certified.Modeled.CheckedEquation entries rule)}, + Theory.Certified.Modeled.checkEquation? fuel entries rule witness = some result → + Theory.Certified.Modeled.CheckedEquation entries rule +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Theory.Certified.Modeled.assignment_realizes +∀ {β : Type u} [inst : DecidableEq β] {V : Type v} [inst_1 : Theory.Model.SetTheory V] + {entries : Theory.Model.Environment β} {companions : List (Theory.Certified.Modeled.Companion β)}, + Theory.Certified.Modeled.CheckedCompanions entries companions → + entries.WF → + ∀ (constants : Theory.Model.Assignment β V), + Theory.Model.Realizes constants entries → + Theory.Model.Realizes (Theory.Certified.Modeled.assignment constants companions) + (Theory.Certified.Modeled.environment entries companions) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Theory.Certified.Modeled.assignment_agrees +∀ {β : Type u} [inst : DecidableEq β] {V : Type v} {entries : Theory.Model.Environment β} + {companions : List (Theory.Certified.Modeled.Companion β)}, + Theory.Certified.Modeled.CheckedCompanions entries companions → + ∀ (constants : Theory.Model.Assignment β V), + Theory.Model.Assignment.AgreesOn entries constants (Theory.Certified.Modeled.assignment constants companions) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Theory.Certified.checkModeledExtension? +{β : Type u} → + [DecidableEq β] → + Nat → + {signature : Theory.Certified.PrimitiveSignature β} → + {store : Theory.Store β} → + (state : Theory.Certified.CheckedInterface signature) → + Theory.Certified.Modeled.Witness β → Option (Theory.Certified.CheckedExtension signature store state) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Theory.Certificate.Modeled.witness? +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Theory.Model.Environment β → + Theory.Store β → + β → + List (Theory.ConstRef β) → + List (Theory.ConstRef β) → + (optParam (Theory.ConstRef β → Nat → Option (Theory.Certificate.Modeled.ProofHint β)) fun x x_1 => + none) → + Option (Theory.Certified.Modeled.Witness β) +AXIOMS [propext, Quot.sound] +ROOT Ix.Theory.Certificate.sourceGroup? +{β : Type u} → + [DecidableEq β] → + Theory.Store β → + Theory.ConstRef β → + optParam (Option (Theory.ConstRef β)) none → + optParam (List (Theory.Certificate.Modeled.Candidate β)) [] → Option (Theory.Certificate.SourceGroup β) +AXIOMS [propext, Quot.sound] +ROOT Ix.Theory.Certificate.proofWitness? +{β : Type u} → + [DecidableEq β] → + Nat → + Theory.Certified.PrimitiveSignature β → + Theory.Certified.ProofInput β → + optParam (List (Theory.Certificate.Modeled.Candidate β)) [] → Option (Theory.Certified.ProofWitness β) +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.modelCandidate? +Objects → Theory.Store Address → ModelHint → Option (Theory.Certificate.Modeled.Candidate Address) +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.modelCandidates? +Objects → Theory.Store Address → List ModelHint → Option (List (Theory.Certificate.Modeled.Candidate Address)) +AXIOMS [propext, Quot.sound] +ROOT Ix.Certified.ModelHint.readOptional +Lean.Json → Except String (List ModelHint) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.ModelHint.read +Lean.Json → Except String ModelHint +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.suggestSource? +Nat → + Ixon.Env → + Profile → Address → InputSelection → optParam (List ModelHint) [] → Option (Theory.Certified.ProofWitness Address) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.suggestStore? +Nat → + Ixon.Env → + Profile → + List Address → + InputSelection → optParam (List ModelHint) [] → Option (List (Theory.Certified.DeclarationWitness Address)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.Command.readRequest +Lean.Json → Except String Command.Request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Certified.suggestLogical? +Nat → Ixon.Env → Envelope → LogicalHint → Option LogicalWitness +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.acceptsCertifiedSource +Nat → Ixon.Env → Profile → Address → InputSelection → Theory.Certified.ProofWitness Address → Bool +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Ix.Kernel.acceptsCertifiedStoreSource +Nat → Ixon.Env → Profile → List Address → InputSelection → List (Theory.Certified.DeclarationWitness Address) → Bool +AXIOMS [propext, Classical.choice, Quot.sound] +PREMISE Ix.Certified.InputCache.mk +List CachedObject → List CachedNatural → Nat → Nat → InputCache +PREMISE Ix.Certified.CachedObject.mk +(address : Address) → (bytes : ByteArray) → DecodedObject address bytes → CachedObject +PREMISE Ix.Certified.CachedNatural.mk +(address : Address) → (bytes : ByteArray) → DecodedNatural address bytes → CachedNatural +PREMISE Ix.Certified.DecodedObject +Address → ByteArray → Type +DEFINITION +fun address bytes => + { value // + address.hash.size = 32 ∧ + Address.blake3 bytes = address ∧ + Ixon.runGetExact Ixon.getConstant bytes = Except.ok value ∧ Ixon.serConstant value = bytes } +PREMISE Ix.Certified.DecodedNatural +Address → ByteArray → Type +DEFINITION +fun address bytes => + { value // + address.hash.size = 32 ∧ + Address.blake3 bytes = address ∧ Nat.fromBytesLE bytes.data = value ∧ { data := value.toBytesLE } = bytes } +PREMISE Ix.Certified.SourceObject.mk +{source : Ixon.Env} → + (toCachedObject : CachedObject) → + constantBytes? source toCachedObject.address = some toCachedObject.bytes → SourceObject source +PREMISE Ix.Certified.SourceNatural.mk +{source : Ixon.Env} → + (toCachedNatural : CachedNatural) → + source.getBlob? toCachedNatural.address = some toCachedNatural.bytes → SourceNatural source +PREMISE Ix.Certified.SourceReceipt.mk +{source : Ixon.Env} → + {fuel : Nat} → + {profile : Profile} → + {target : Address} → + {witness : Theory.Certified.ProofWitness Address} → + (snapshot : SourceSnapshot source) → + (prepared : PreparedInput) → + SourceSnapshot.prepare? fuel profile target snapshot = some prepared → + (proof : Theory.Certified.CheckedProof prepared.signature prepared.input) → + Theory.Certified.checkProofCertified fuel prepared.signature prepared.input witness = some proof → + SourceReceipt source fuel profile target witness +PREMISE Ix.Certified.StoreReceipt.mk +{source : Ixon.Env} → + {fuel : Nat} → + {profile : Profile} → + {subjects : List Address} → + {witness : List (Theory.Certified.DeclarationWitness Address)} → + (snapshot : SourceSnapshot source) → + (prepared : PreparedStore) → + SourceSnapshot.prepareStore? fuel profile subjects snapshot = some prepared → + (result : Theory.Certified.CheckedStore prepared.signature prepared.store prepared.targets) → + Theory.Certified.checkStoreCertified fuel prepared.signature prepared.store prepared.targets witness = + some result → + StoreReceipt source fuel profile subjects witness +PREMISE Ix.Certified.InputSelection.mk +List Address → List Address → InputSelection +PREMISE Ix.Certified.subjectReferences? +Objects → Address → Option (List (Theory.ConstRef Address)) +DEFINITION +fun objects subject => do + let source ← lookup objects subject + match source.info with + | Ixon.ConstantInfo.muts members => + if members.isEmpty = true then none + else + pure + (List.flatMap + (fun x => + match x with + | (member, index) => + Theory.ConstRef.member subject index :: + match member with + | Ixon.MutConst.indc family => + List.map (fun x => Theory.ConstRef.ctor subject index x) (List.range family.ctors.size) + | x => []) + members.toList.zipIdx) + | x => do + let __do_lift ← resolveReference? objects subject + pure [__do_lift] +PREMISE Ix.Kernel.CertifiedState.mk +Kernel.TcState Kernel.Mode.anon → InputCache → Kernel.CertifiedState +PREMISE Ix.Certified.MemberMeaning +Objects → Address → UInt64 → Ixon.MutConst → Prop +DEFINITION +fun objects block index member => + ∃ source members, + lookup objects block = some source ∧ + source.info = Ixon.ConstantInfo.muts members ∧ members[index.toNat]? = some member +PREMISE Ix.Certified.ReferenceTarget +Objects → Address → Ixon.Constant → Theory.ConstRef Address → Prop +DEFINITION +fun objects address source ref => + match source.info with + | Ixon.ConstantInfo.defn a => ref = Theory.ConstRef.member address 0 + | Ixon.ConstantInfo.recr a => ref = Theory.ConstRef.member address 0 + | Ixon.ConstantInfo.axio a => ref = Theory.ConstRef.member address 0 + | Ixon.ConstantInfo.quot a => ref = Theory.ConstRef.member address 0 + | Ixon.ConstantInfo.iPrj projection => + (∃ family, MemberMeaning objects projection.block projection.idx (Ixon.MutConst.indc family)) ∧ + ref = Theory.ConstRef.member projection.block projection.idx.toNat + | Ixon.ConstantInfo.rPrj projection => + (∃ recursor, MemberMeaning objects projection.block projection.idx (Ixon.MutConst.recr recursor)) ∧ + ref = Theory.ConstRef.member projection.block projection.idx.toNat + | Ixon.ConstantInfo.dPrj projection => + (∃ definition, MemberMeaning objects projection.block projection.idx (Ixon.MutConst.defn definition)) ∧ + ref = Theory.ConstRef.member projection.block projection.idx.toNat + | Ixon.ConstantInfo.cPrj projection => + (∃ family ctor, + MemberMeaning objects projection.block projection.idx (Ixon.MutConst.indc family) ∧ + family.ctors[projection.cidx.toNat]? = some ctor) ∧ + ref = Theory.ConstRef.ctor projection.block projection.idx.toNat projection.cidx.toNat + | Ixon.ConstantInfo.muts a => False +PREMISE Ix.Certified.ReferenceMeaning +Objects → Address → Theory.ConstRef Address → Prop +DEFINITION +fun objects address ref => ∃ source, lookup objects address = some source ∧ ReferenceTarget objects address source ref +PREMISE Ix.Certified.LevelsReading.nil +∀ {source : Ixon.Constant}, LevelsReading source [] [] +PREMISE Ix.Certified.LevelsReading.cons +∀ {source : Ixon.Constant} {index : UInt64} {indices : List UInt64} {level : Ixon.Univ} {levels : List Theory.VLevel}, + source.univs[index.toNat]? = some level → + LevelsReading source indices levels → LevelsReading source (index :: indices) (readLevel level :: levels) +PREMISE Ix.Certified.ExprReading.var +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} (index : UInt64), + ExprReading objects naturals block source (Ixon.Expr.var index) (Theory.VExpr.bvar index.toNat) +PREMISE Ix.Certified.ExprReading.sort +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {index : UInt64} + {level : Ixon.Univ}, + source.univs[index.toNat]? = some level → + ExprReading objects naturals block source (Ixon.Expr.sort index) (Theory.VExpr.sort (readLevel level)) +PREMISE Ix.Certified.ExprReading.ref +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {index : UInt64} + {indices : Array UInt64} {address : Address} {ref : Theory.ConstRef Address} {levels : List Theory.VLevel}, + source.refs[index.toNat]? = some address → + ReferenceMeaning objects address ref → + LevelsReading source indices.toList levels → + ExprReading objects naturals block source (Ixon.Expr.ref index indices) (Theory.VExpr.const ref levels) +PREMISE Ix.Certified.ExprReading.recur +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {index : UInt64} + {indices : Array UInt64} {levels : List Theory.VLevel}, + LevelsReading source indices.toList levels → + ExprReading objects naturals block source (Ixon.Expr.recur index indices) + (Theory.VExpr.const (Theory.ConstRef.member block index.toNat) levels) +PREMISE Ix.Certified.ExprReading.app +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {f a : Ixon.Expr} + {fr ar : Theory.VExpr Address}, + ExprReading objects naturals block source f fr → + ExprReading objects naturals block source a ar → ExprReading objects naturals block source (f.app a) (fr.app ar) +PREMISE Ix.Certified.ExprReading.lam +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {A b : Ixon.Expr} + {Ar br : Theory.VExpr Address}, + ExprReading objects naturals block source A Ar → + ExprReading objects naturals block source b br → + ExprReading objects naturals block source (Ixon.Expr.lam Ixon.Uses.many A b) (Ar.lam br) +PREMISE Ix.Certified.ExprReading.all +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {A B : Ixon.Expr} + {Ar Br : Theory.VExpr Address}, + ExprReading objects naturals block source A Ar → + ExprReading objects naturals block source B Br → + ExprReading objects naturals block source (Ixon.Expr.all Ixon.Uses.many Ixon.Owned.shared A B) (Ar.forallE Br) +PREMISE Ix.Certified.ExprReading.prj +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {owner field : UInt64} + {value : Ixon.Expr} {address : Address} {ownerSource : Ixon.Constant} {projection : Ixon.InductiveProj} + {ref : Theory.ConstRef Address} {reading : Theory.VExpr Address}, + source.refs[owner.toNat]? = some address → + lookup objects address = some ownerSource → + ownerSource.info = Ixon.ConstantInfo.iPrj projection → + ReferenceMeaning objects address ref → + ExprReading objects naturals block source value reading → + ExprReading objects naturals block source (Ixon.Expr.prj owner field value) + (Theory.VExpr.proj ref field.toNat reading) +PREMISE Ix.Certified.ExprReading.nat +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {index : UInt64} + {address : Address} {value : Nat}, + source.refs[index.toNat]? = some address → + lookup naturals address = some value → + ExprReading objects naturals block source (Ixon.Expr.nat index) (Theory.VExpr.natLit value) +PREMISE Ix.Certified.ExprReading.share +∀ {objects : Objects} {naturals : Naturals} {block : Address} {source : Ixon.Constant} {index : UInt64} + {shared : Ixon.Expr} {reading : Theory.VExpr Address}, + source.sharing[index.toNat]? = some shared → + ExprReading objects naturals block source shared reading → + ExprReading objects naturals block source (Ixon.Expr.share index) reading +PREMISE Ix.Certified.rawHeader? +Ixon.Constant → Theory.ConstRef Address → Option (Nat × Ixon.Expr) +DEFINITION +fun source x => + match x with + | Theory.ConstRef.member b index => + match source.info with + | Ixon.ConstantInfo.muts members => Option.map memberRawHeader members[index]? + | Ixon.ConstantInfo.defn value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | Ixon.ConstantInfo.recr value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | Ixon.ConstantInfo.axio value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | Ixon.ConstantInfo.quot value => if index = 0 then some (value.lvls.toNat, value.typ) else none + | x => none + | Theory.ConstRef.ctor b index field => + match source.info with + | Ixon.ConstantInfo.muts members => do + let __x ← members[index]? + match __x with + | Ixon.MutConst.indc family => do + let ctor ← family.ctors[field]? + pure (ctor.lvls.toNat, ctor.typ) + | x => none + | x => none +PREMISE Ix.Certified.ObjectBytes +Ixon.Env → Address → ByteArray → Ixon.Constant → Prop +DEFINITION +fun source address bytes value => + constantBytes? source address = some bytes ∧ + address.hash.size = 32 ∧ + Address.blake3 bytes = address ∧ + Ixon.runGetExact Ixon.getConstant bytes = Except.ok value ∧ Ixon.serConstant value = bytes +PREMISE Ix.Certified.NaturalBytes +Ixon.Env → Address → ByteArray → Nat → Prop +DEFINITION +fun source address bytes value => + source.getBlob? address = some bytes ∧ + address.hash.size = 32 ∧ + Address.blake3 bytes = address ∧ Nat.fromBytesLE bytes.data = value ∧ { data := value.toBytesLE } = bytes +PREMISE Ix.Certified.SignatureReading +Profile → Objects → Theory.Certified.PrimitiveSignature Address → Prop +DEFINITION +fun profile objects signature => + ReferenceMeaning objects profile.falseType signature.falseType ∧ + ReferenceMeaning objects profile.falseElim signature.falseElim ∧ + match profile.natType, signature.natType with + | none, none => True + | some address, some ref => ReferenceMeaning objects address ref + | x, x_1 => False +PREMISE Ix.Certified.SourceDeclarationReading +Ixon.Env → Objects → Naturals → Theory.ConstRef Address → Theory.Model.ConstantEntry Address → Prop +DEFINITION +fun source objects naturals ref entry => + ∃ bytes declaration rawType, + ObjectBytes source ref.block bytes declaration ∧ + lookup objects ref.block = some declaration ∧ + rawHeader? declaration ref = some (entry.universes, rawType) ∧ + ExprReading objects naturals ref.block declaration rawType entry.type.erase +PREMISE Ix.Certified.SubjectReading +Objects → Address → List (Theory.ConstRef Address) → Prop +DEFINITION +fun objects subject refs => + ∃ source, + lookup objects subject = some source ∧ + match source.info with + | Ixon.ConstantInfo.muts members => + members.isEmpty = false ∧ + refs = + List.flatMap + (fun x => + match x with + | (member, index) => + Theory.ConstRef.member subject index :: + match member with + | Ixon.MutConst.indc family => + List.map (fun x => Theory.ConstRef.ctor subject index x) (List.range family.ctors.size) + | x => []) + members.toList.zipIdx + | x => ∃ ref, ReferenceMeaning objects subject ref ∧ refs = [ref] +PREMISE Ix.Certified.Protocol.current +Protocol +DEFINITION +{ checker := 2 } +PREMISE Ix.Certified.envelopeMagic +ByteArray +DEFINITION +"IX-CERTIFIED-CLAIM".toUTF8 ++ { data := #[0] } +PREMISE Ix.Certified.putEnvelope +Envelope → Ixon.PutM Unit +DEFINITION +fun envelope => do + Ixon.putBytes envelopeMagic + Ixon.putTag0 { size := envelope.protocol.format } + Ixon.putTag0 { size := envelope.protocol.codec } + Ixon.putTag0 { size := envelope.protocol.checker } + Ixon.putTag0 { size := envelope.protocol.policy } + Ixon.putTag0 { size := envelope.protocol.aggregation } + Ixon.Serialize.put envelope.profile.falseType + Ixon.Serialize.put envelope.profile.falseElim + Claim.putOptAddr envelope.profile.natType + envelope.claim.put + Claim.putOptAddr envelope.logicalAxioms +PREMISE Ix.Certified.getEnvelope +Ixon.GetM Envelope +DEFINITION +do + let __do_lift ← Ixon.getBytes envelopeMagic.size + have __do_jp : Unit → Ixon.GetM Envelope := fun __r => do + let __do_lift ← Ixon.getTag0 + have format : UInt64 := __do_lift.size + let __do_lift ← Ixon.getTag0 + have codec : UInt64 := __do_lift.size + let __do_lift ← Ixon.getTag0 + have checker : UInt64 := __do_lift.size + let __do_lift ← Ixon.getTag0 + have policy : UInt64 := __do_lift.size + let __do_lift ← Ixon.getTag0 + have aggregation : UInt64 := __do_lift.size + let falseType ← Ixon.Serialize.get + let falseElim ← Ixon.Serialize.get + let natType ← Claim.getOptAddr + let claim ← Claim.get + let logicalAxioms ← Claim.getOptAddr + pure + { + protocol := + { format := format, codec := codec, checker := checker, policy := policy, aggregation := aggregation }, + profile := { falseType := falseType, falseElim := falseElim, natType := natType }, claim := claim, + logicalAxioms := logicalAxioms } + if (__do_lift != envelopeMagic) = true then do + let __r ← throw "invalid certified claim magic" + __do_jp __r + else __do_jp () +PREMISE Ix.Certified.EnvelopeReading.mk +{address : Address} → + {bytes : ByteArray} → + (envelope : Envelope) → + address.hash.size = 32 → + Address.blake3 bytes = address → + Ixon.runGetExact getEnvelope bytes = Except.ok envelope → + envelopeBytes envelope = bytes → envelope.protocol = Protocol.current → EnvelopeReading address bytes +PREMISE Ix.Certified.TreeOpening.mk +{fuel : Nat} → + {root : Address} → + {bytes : ByteArray} → + (tree : AssumptionTree) → + Ixon.runGetExact (getTree fuel) bytes = Except.ok tree → + treeBytes tree = bytes → + treeRoot tree = root → + (∀ (address : Address), address ∈ treeLeaves tree → address.hash.size = 32) → TreeOpening fuel root bytes +PREMISE Ix.Certified.OptionalTreeOpening.mk +{fuel : Nat} → + {root : Option Address} → + {bytes : Option ByteArray} → + (leaves : List Address) → + (match root, bytes with + | none, none => leaves = [] + | some root, some bytes => ∃ opening, treeLeaves opening.tree = leaves + | x, x_1 => False) → + OptionalTreeOpening fuel root bytes +PREMISE Ix.Certified.SubjectView.mk +{fuel : Nat} → + {claim : Claim} → + {bytes : Option ByteArray} → + (addresses : List Address) → + (match claim with + | Claim.check address assumptions => bytes = none ∧ addresses = [address] + | Claim.checkEnv root assumptions => ∃ raw, bytes = some raw ∧ ∃ opening, treeLeaves opening.tree = addresses + | x => False) → + SubjectView fuel claim bytes +PREMISE Ix.Certified.PreparedLeaf.mk +{fuel : Nat} → + {objects : Objects} → + {witness : LeafWitness} → + (subjectView : SubjectView fuel witness.claim witness.subjects) → + (subjectRefs : List (Theory.ConstRef Address)) → + List.flatMapM (subjectReferences? objects) subjectView.addresses = some subjectRefs → + (frontierView : OptionalTreeOpening fuel (claimFrontier witness.claim) witness.frontierTree) → + (frontierRefs : List (Theory.ConstRef Address)) → + List.flatMapM (subjectReferences? objects) frontierView.leaves = some frontierRefs → + (∀ (ref : Theory.ConstRef Address), + ref ∈ List.map (fun x => x.ref) witness.frontier ↔ ref ∈ frontierRefs) → + PreparedLeaf fuel objects witness +PREMISE Ix.Certified.ContentView.mk +{fuel : Nat} → + {claim : Claim} → + {subjects members : Option ByteArray} → + {objects : Objects} → + {leaves : List (LeafInput fuel objects)} → + (addresses : List Address) → + (∀ (address : Address), address ∈ addresses ↔ address ∈ leafAddresses leaves) → + (match claim with + | Claim.check address assumptions => subjects = none ∧ members = none ∧ addresses = [address] + | Claim.checkEnv root assumptions => + members = none ∧ ∃ raw, subjects = some raw ∧ ∃ opening, treeLeaves opening.tree = addresses + | Claim.catalog memberRoot contentRoot assumptions => + ∃ rawContent rawMembers, + subjects = some rawContent ∧ + members = some rawMembers ∧ + ∃ content membership, + treeLeaves content.tree = addresses ∧ + ∃ roots, + List.mapM (fun leaf => environmentRoot? leaf.witness.claim) leaves = some roots ∧ + ∀ (root : Address), root ∈ treeLeaves membership.tree ↔ root ∈ roots + | x => False) → + ContentView fuel claim subjects members leaves +PREMISE Ix.Certified.ownedReferences +Theory.Certified.PrimitiveSignature Address → List (Theory.ConstRef Address) → List (Theory.ConstRef Address) +DEFINITION +fun signature refs => (List.filter (fun ref => ref != signature.falseType && ref != signature.falseElim) refs).eraseDups +PREMISE Ix.Certified.claimFrontier +Claim → Option Address +DEFINITION +fun x => + match x with + | Claim.check const frontier => frontier + | Claim.checkEnv root frontier => frontier + | Claim.catalog members content frontier => frontier + | Claim.eval input output frontier => frontier + | x => none +PREMISE Ix.Certified.LogicalChecking.mk +{source : Ixon.Env} → + {snapshot : SourceSnapshot source} → + {fuel : Nat} → + {envelope : Envelope} → + {witness : LogicalWitness} → + (List.map Prod.fst (snapshot.blobs ++ snapshot.literalBlobs)).Nodup → + (signature : Theory.Certified.PrimitiveSignature Address) → + readSignature? envelope.profile snapshot.decodedObjects = some signature → + (store : Theory.Store Address) → + readStore? fuel snapshot.decodedObjects snapshot.decodedNaturals = some store → + (leaves : List (LeafInput fuel snapshot.decodedObjects)) → + List.mapM (readLeafInput? fuel snapshot.decodedObjects) witness.leaves = some leaves → + (content : ContentView fuel envelope.claim witness.subjects witness.members leaves) → + (subjects : List (Theory.ConstRef Address)) → + List.flatMapM (subjectReferences? snapshot.decodedObjects) content.addresses = + some subjects → + (frontier : + OptionalTreeOpening fuel (claimFrontier envelope.claim) witness.frontierTree) → + (frontierRefs : List (Theory.ConstRef Address)) → + List.flatMapM (subjectReferences? snapshot.decodedObjects) frontier.leaves = + some frontierRefs → + (batch : + Theory.Certified.CheckedBatch fuel signature store + (List.map (fun leaf => leaf.prepared.node signature) leaves)) → + Theory.Certified.checkBatch? fuel signature store witness.frontier + (List.map (fun leaf => leaf.prepared.node signature) leaves) = + some batch → + (∀ (ref : Theory.ConstRef Address), + ref ∈ Theory.Certified.nodeSubjects batch.nodes ↔ + ref ∈ ownedReferences signature subjects) → + (∀ (ref : Theory.ConstRef Address), + ref ∈ batch.receipt.frontier.refs ↔ ref ∈ frontierRefs) → + (axioms : + OptionalTreeOpening fuel envelope.logicalAxioms witness.axiomTree) → + (axiomRefs : List (Theory.ConstRef Address)) → + List.flatMapM (subjectReferences? snapshot.decodedObjects) + axioms.leaves = + some axiomRefs → + (∀ (ref : Theory.ConstRef Address), + ref ∈ batch.logicalUses ↔ ref ∈ axiomRefs) → + LogicalChecking snapshot fuel envelope witness +PREMISE Ix.Certified.LogicalReceipt.mk +{source : Ixon.Env} → + {fuel : Nat} → + {envelope : Envelope} → + {witness : LogicalWitness} → + (snapshot : SourceSnapshot source) → + LogicalChecking snapshot fuel envelope witness → + envelope.protocol = Protocol.current → LogicalReceipt source fuel envelope witness +PREMISE Ix.Certified.SubjectsInterpreted +{source : Ixon.Env} → + {fuel : Nat} → + {envelope : Envelope} → + {witness : LogicalWitness} → + LogicalReceipt source fuel envelope witness → + (V : Type v) → [Theory.Model.SetTheory V] → Theory.Model.Assignment Address V → Prop +DEFINITION +fun {source} {fuel} {envelope} {witness} receipt V [Theory.Model.SetTheory V] constants => + ∀ (ref : Theory.ConstRef Address), + ref ∈ receipt.checked.subjects → + ∃ entry, + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Theory.Model.WellDenoted constants levels env entry.type ∧ + Theory.Model.SetTheory.Mem (constants ref levels) + (Theory.Model.interp constants levels env entry.type) +PREMISE Ix.Certified.LogicalMeaning +Ixon.Env → Nat → Envelope → Prop +DEFINITION +fun source fuel envelope => + ∃ witness receipt, + SignatureReading envelope.profile receipt.snapshot.decodedObjects receipt.checked.signature ∧ + (∀ (ref : Theory.ConstRef Address), + ref ∈ receipt.checked.frontierRefs → + ∃ entry, + receipt.checked.batch.receipt.frontier.interface.entries ref = some entry ∧ + SourceDeclarationReading source receipt.snapshot.decodedObjects receipt.snapshot.decodedNaturals ref + entry) ∧ + (∀ (ref : Theory.ConstRef Address), + ref ∈ receipt.checked.axiomRefs → + ∃ entry, + Theory.Certified.Standard.EntrySource receipt.checked.store ref entry ∨ + Theory.Certified.Quotient.EntrySource receipt.checked.store ref entry) ∧ + (∀ (V : Type v) [inst : Theory.Model.SetTheory V] (constants : Theory.Model.Assignment Address V), + receipt.checked.signature.Compatible receipt.checked.batch.receipt.frontier.interface.entries constants → + ∃ constants', + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants' ∧ + Theory.Model.Assignment.AgreesOn receipt.checked.batch.receipt.frontier.interface.entries constants + constants' ∧ + SubjectsInterpreted receipt V constants') ∧ + (claimFrontier envelope.claim = none → + ∀ (V : Type v) [inst : Theory.Model.SetTheory V], + ∃ constants, + receipt.checked.signature.Compatible receipt.checked.batch.receipt.checked.result.entries constants ∧ + SubjectsInterpreted receipt V constants) +PREMISE Ix.Certified.RevealMatches +RevealConstantInfo → Ixon.ConstantInfo → Prop +DEFINITION +fun expected actual => + match expected, actual with + | RevealConstantInfo.defn kind safety levels type value, Ixon.ConstantInfo.defn actual => + Selected kind actual.kind ∧ + Selected safety actual.safety ∧ + Selected levels actual.lvls ∧ + Selected type (expressionAddress actual.typ) ∧ Selected value (expressionAddress actual.value) + | RevealConstantInfo.recr k safety levels params indices motives minors type rules, Ixon.ConstantInfo.recr actual => + Selected k actual.k ∧ + Selected safety actual.isUnsafe ∧ + Selected levels actual.lvls ∧ + Selected params actual.params ∧ + Selected indices actual.indices ∧ + Selected motives actual.motives ∧ + Selected minors actual.minors ∧ + Selected type (expressionAddress actual.typ) ∧ RulesMatch rules actual.rules + | RevealConstantInfo.axio safety levels type, Ixon.ConstantInfo.axio actual => + Selected safety actual.isUnsafe ∧ Selected levels actual.lvls ∧ Selected type (expressionAddress actual.typ) + | RevealConstantInfo.quot kind levels type, Ixon.ConstantInfo.quot actual => + Selected kind actual.kind ∧ Selected levels actual.lvls ∧ Selected type (expressionAddress actual.typ) + | RevealConstantInfo.cPrj index constructor block, Ixon.ConstantInfo.cPrj actual => + Selected index actual.idx ∧ Selected constructor actual.cidx ∧ Selected block actual.block + | RevealConstantInfo.iPrj index block, Ixon.ConstantInfo.iPrj actual => + Selected index actual.idx ∧ Selected block actual.block + | RevealConstantInfo.rPrj index block, Ixon.ConstantInfo.rPrj actual => + Selected index actual.idx ∧ Selected block actual.block + | RevealConstantInfo.dPrj index block, Ixon.ConstantInfo.dPrj actual => + Selected index actual.idx ∧ Selected block actual.block + | RevealConstantInfo.muts components, Ixon.ConstantInfo.muts actual => ComponentsMatch components actual + | x, x_1 => False +PREMISE Ix.Certified.ConstructorMatches +RevealConstructorInfo → Ixon.Constructor → Prop +DEFINITION +fun expected actual => + Selected expected.isUnsafe actual.isUnsafe ∧ + Selected expected.lvls actual.lvls ∧ + Selected expected.cidx actual.cidx ∧ + Selected expected.params actual.params ∧ + Selected expected.fields actual.fields ∧ Selected expected.typ (expressionAddress actual.typ) +PREMISE Ix.Certified.ConstructorsMatch +Option (Array (UInt64 × RevealConstructorInfo)) → Array Ixon.Constructor → Prop +DEFINITION +fun expected actual => + match expected with + | none => True + | some constructors => + ∀ (pair : UInt64 × RevealConstructorInfo), + pair ∈ constructors.toList → + match actual[pair.fst.toNat]? with + | none => False + | some constructor => ConstructorMatches pair.snd constructor +PREMISE Ix.Certified.MutMatches +RevealMutConstInfo → Ixon.MutConst → Prop +DEFINITION +fun expected actual => + match expected, actual with + | RevealMutConstInfo.defn kind safety levels type value, Ixon.MutConst.defn actual => + Selected kind actual.kind ∧ + Selected safety actual.safety ∧ + Selected levels actual.lvls ∧ + Selected type (expressionAddress actual.typ) ∧ Selected value (expressionAddress actual.value) + | RevealMutConstInfo.indc safety levels params indices type ctors, Ixon.MutConst.indc actual => + Selected safety actual.isUnsafe ∧ + Selected levels actual.lvls ∧ + Selected params actual.params ∧ + Selected indices actual.indices ∧ + Selected type (expressionAddress actual.typ) ∧ ConstructorsMatch ctors actual.ctors + | RevealMutConstInfo.recr k safety levels params indices motives minors type rules, Ixon.MutConst.recr actual => + Selected k actual.k ∧ + Selected safety actual.isUnsafe ∧ + Selected levels actual.lvls ∧ + Selected params actual.params ∧ + Selected indices actual.indices ∧ + Selected motives actual.motives ∧ + Selected minors actual.minors ∧ + Selected type (expressionAddress actual.typ) ∧ RulesMatch rules actual.rules + | x, x_1 => False +PREMISE Ix.Certified.ComponentsMatch +Array (UInt64 × RevealMutConstInfo) → Array Ixon.MutConst → Prop +DEFINITION +fun expected actual => + ∀ (pair : UInt64 × RevealMutConstInfo), + pair ∈ expected.toList → + match actual[pair.fst.toNat]? with + | none => False + | some member => MutMatches pair.snd member +PREMISE Ix.Certified.RulesMatch +Option (Array RevealRecursorRule) → Array Ixon.RecursorRule → Prop +DEFINITION +fun expected actual => + match expected with + | none => True + | some rules => + ∀ (rule : RevealRecursorRule), + rule ∈ rules.toList → + match actual[rule.ruleIdx.toNat]? with + | none => False + | some actual => rule.fields = actual.fields ∧ rule.rhs = expressionAddress actual.rhs +PREMISE Ix.Certified.RevealMeaning +Ixon.Env → Address → RevealConstantInfo → Prop +DEFINITION +fun source commitment info => + ∃ opening, + opening.secret.hash.size = 32 ∧ + opening.payload.hash.size = 32 ∧ + opening.commit = commitment ∧ + ∃ bytes object, ObjectBytes source opening.payload bytes object ∧ RevealMatches info object.info +PREMISE Ix.Certified.SemanticClaimMeaning +Ixon.Env → Nat → Envelope → Prop +DEFINITION +fun source fuel envelope => + envelope.protocol = Protocol.current ∧ + match envelope.claim with + | Claim.check const assumptions => LogicalMeaning source fuel envelope + | Claim.checkEnv root assumptions => LogicalMeaning source fuel envelope + | Claim.catalog members content assumptions => LogicalMeaning source fuel envelope + | Claim.contains root target => envelope.logicalAxioms = none ∧ TreeMembership root target + | Claim.reveal commitment info => envelope.logicalAxioms = none ∧ RevealMeaning source commitment info + | Claim.eval input output assumptions => False +PREMISE Ix.Certified.ModelHint.mk +Address → List Address → List Address → List ModelRuleHints → ModelHint +PREMISE Ix.Certified.ModelRuleHints.mk +Address → List (Option ModelProofHint) → ModelRuleHints +PREMISE Ix.Certified.ModelProofHint.mk +Address → Address → Address → Address → ModelProofHint +PREMISE Ix.Theory.Certificate.Modeled.Candidate.mk +{β : Type u} → + β → + List (Theory.ConstRef β) → + List (Theory.ConstRef β) → + List (Theory.ConstRef β × List (Option (Theory.Certificate.Modeled.ProofHint β))) → + Theory.Certificate.Modeled.Candidate β +PREMISE Ix.Theory.Certificate.Modeled.ProofHint.mk +{β : Type u} → + Theory.ConstRef β → Theory.ConstRef β → Theory.ConstRef β → Theory.VExpr β → Theory.Certificate.Modeled.ProofHint β +PREMISE Ix.Theory.Certified.Modeled.Witness.mk +{β : Type u} → + β → + List (Theory.ConstRef β) → + List (Theory.Certified.Modeled.Companion β) → + List (List (Theory.Certified.Modeled.EquationWitness β)) → Theory.Certified.Modeled.Witness β +PREMISE Ix.Theory.Certified.Modeled.Checked.mk +∀ {β : Type u} [inst : DecidableEq β] {entries : Theory.Model.Environment β} {store : Theory.Store β} + {witness : Theory.Certified.Modeled.Witness β}, + Theory.Certified.Modeled.sourceRefs? store witness.source witness.recursors = + some (List.map (fun x => x.header.ref) witness.companions) → + (∀ (companion : Theory.Certified.Modeled.Companion β), + companion ∈ witness.companions → Theory.Certified.Modeled.SourceMatches store companion) → + Theory.Certified.Modeled.CheckedCompanions entries witness.companions → + Theory.Certified.Modeled.Checked entries store witness +PREMISE Ix.Theory.Certified.Modeled.SourceMatches +{β : Type u} → [DecidableEq β] → Theory.Store β → Theory.Certified.Modeled.Companion β → Prop +DEFINITION +fun {β} [DecidableEq β] store companion => + store.type companion.header.ref = some companion.header.type.erase ∧ + store.uvars companion.header.ref = some companion.header.universes ∧ + Theory.Certified.Modeled.sourceRules? store companion.header.ref = + some (List.map Theory.Certified.Modeled.eraseRule companion.rules) +PREMISE Ix.Theory.Certified.Modeled.sourceRefs? +{β : Type u} → [DecidableEq β] → Theory.Store β → β → List (Theory.ConstRef β) → Option (List (Theory.ConstRef β)) +DEFINITION +fun {β} [DecidableEq β] store source recursors => do + let families ← Theory.Certified.Modeled.sourceFamilies? store source + if recursors.length < families.length then none + else do + let majors ← + List.mapM + (fun ref => do + let info ← Theory.Certified.Modeled.recursorSource? store ref + let major ← Theory.Certified.Modeled.majorSource? store info + pure major.family) + recursors + if (List.take families.length majors != families) = true then none + else do + let members ← + List.mapM + (fun family => do + let ctors ← Theory.Certified.Modeled.familyConstructors? store family + pure (family :: ctors)) + families + pure (members.flatten ++ recursors) +PREMISE Ix.Theory.Certified.Modeled.recursorSource? +{β : Type u} → Theory.Store β → Theory.ConstRef β → Option (Theory.Certified.Modeled.RecursorSource β) +DEFINITION +fun {β} store ref => do + let __x ← store.lookup ref + match __x with + | Theory.Const.recursor universes parameters indices motives minors type rules false Theory.Safety.safe => + pure + { universes := universes, parameters := parameters, indices := indices, motives := motives, minors := minors, + type := type, rules := rules } + | x => none +PREMISE Ix.Theory.Certified.Modeled.majorSource? +{β : Type u} → + [DecidableEq β] → + Theory.Store β → Theory.Certified.Modeled.RecursorSource β → Option (Theory.Certified.Modeled.MajorSource β) +DEFINITION +fun {β} [DecidableEq β] store source => do + let __x ← Theory.Certified.Modeled.splitPi? source.prefix source.type + match __x with + | (prefixDomains, tail) => do + let __x ← Theory.Certified.Modeled.splitPi? source.indices tail + match __x with + | (fst, major.forallE body) => do + let major ← Theory.Certified.Modeled.betaHead? 512 major + match major.appHead with + | Theory.VExpr.const family levels => do + let info ← Theory.Certified.Modeled.familySource? store family + if (info.indices != source.indices || levels.length != info.universes) = true then none + else + have arguments := major.appArgs []; + if (arguments.length != info.parameters + source.indices) = true then none + else + if (List.drop info.parameters arguments != Theory.VExpr.bvarRevRange 0 source.indices) = true then + none + else + have actual := List.take info.parameters arguments; + have parameters := List.map (fun p => p.unliftN source.indices 0) actual; + if (List.map (fun x => Theory.VExpr.liftN source.indices x) parameters != actual) = true then none + else + pure + { family := family, levels := levels, parameters := parameters, + prefixDomains := prefixDomains } + | x => none + | x => none +PREMISE Ix.Theory.Certified.Modeled.ruleSource? +{β : Type u} → + [DecidableEq β] → + Theory.Store β → + Theory.ConstRef β → + Theory.Certified.Modeled.RecursorSource β → + Theory.Certified.Modeled.MajorSource β → Theory.ConstRef β → Option (Theory.Certified.Modeled.RawRule β) +DEFINITION +fun {β} [DecidableEq β] store recursor source major constructor => + match constructor with + | Theory.ConstRef.ctor block member c => + if (major.family != Theory.ConstRef.member block member) = true then none + else do + let family ← Theory.Certified.Modeled.familySource? store major.family + let ctor ← store.lookupCtor constructor + if + (ctor.safety != Theory.Safety.safe || ctor.uvars != family.universes || ctor.nparams != family.parameters) = + true then + none + else + match store.ctorRuleIndex? constructor with + | some slot => do + let stored ← source.rules[slot]? + if (stored.nfields != ctor.nfields) = true then none + else do + let specialized ← + Theory.Certified.Modeled.applyPi? + (Theory.VExpr.liftN source.prefix (Theory.VExpr.instL major.levels ctor.type)) major.parameters + let __x ← Theory.Certified.Modeled.splitPi? ctor.nfields specialized + match __x with + | (fields, result) => + if (result.appHead != Theory.VExpr.const major.family major.levels) = true then none + else + have args := result.appArgs []; + have parameters := List.map (fun x => Theory.VExpr.liftN ctor.nfields x) major.parameters; + if + (args.length != ctor.nparams + source.indices || List.take ctor.nparams args != parameters) = + true then + none + else + have constructorValue := + (Theory.VExpr.const constructor major.levels).appN + (parameters ++ Theory.VExpr.bvarRevRange 0 ctor.nfields); + have callArgs := + Theory.VExpr.bvarRevRange ctor.nfields source.prefix ++ List.drop ctor.nparams args ++ + [constructorValue]; + do + let resultType ← + Theory.Certified.Modeled.applyPi? + (Theory.VExpr.liftN (source.prefix + ctor.nfields) source.type) callArgs + have telescope : List (Theory.VExpr β) := major.prefixDomains ++ fields + let _ ← Theory.Certified.Modeled.splitLam? telescope.length stored.rhs + pure + { universes := source.universes, type := Theory.VExpr.forallN telescope resultType, + lhs := + Theory.VExpr.lamN telescope + ((Theory.VExpr.const recursor + (List.map Theory.VLevel.param (List.range source.universes))).appN + callArgs), + rhs := stored.rhs } + | x => none + | x => none +PREMISE Ix.Theory.Certified.Modeled.Companion.entry +{β : Type u} → Theory.Certified.Modeled.Companion β → Theory.Model.ConstantEntry β +DEFINITION +fun {β} companion => + { universes := companion.header.universes, type := companion.header.type, body := none, + equations := List.map (fun rule => { lhs := rule.lhs, rhs := rule.rhs }) companion.rules } +PREMISE Ix.Theory.Certified.Modeled.CompanionChecked.mk +∀ {β : Type u} [inst : DecidableEq β] {entries : Theory.Model.Environment β} + {companions : List (Theory.Certified.Modeled.Companion β)} {companion : Theory.Certified.Modeled.Companion β}, + (∃ entry, + entries companion.model = some entry ∧ + entry.universes = companion.header.universes ∧ + entry.type = Theory.Model.AExpr.mapRefs (Theory.Certified.Modeled.mapping companions) companion.header.type) → + Theory.Model.AExpr.Scope companion.header.universes 0 companion.header.type → + Theory.Model.AExpr.ReferencesIn (Theory.Certified.Modeled.environment entries companions) companion.header.type → + (∀ (rule : Theory.Certified.Signature.Rule β), + rule ∈ companion.rules → + rule.universes = companion.header.universes ∧ + Theory.Model.AExpr.Scope companion.header.universes 0 rule.lhs ∧ + Theory.Model.AExpr.Scope companion.header.universes 0 rule.rhs) → + (∀ (rule : Theory.Certified.Signature.Rule β), + rule ∈ companion.rules → + Theory.Model.AExpr.ReferencesIn (Theory.Certified.Modeled.environment entries companions) rule.lhs ∧ + Theory.Model.AExpr.ReferencesIn (Theory.Certified.Modeled.environment entries companions) rule.rhs) → + (∀ (rule : Theory.Certified.Signature.Rule β), + rule ∈ companion.rules → + Theory.Certified.Modeled.CheckedEquation entries (Theory.Certified.Modeled.mapRule companions rule)) → + Theory.Certified.Modeled.CompanionChecked entries companions companion +PREMISE Ix.Theory.Certified.Modeled.CheckedCompanions.mk +∀ {β : Type u} [inst : DecidableEq β] {entries : Theory.Model.Environment β} + {companions : List (Theory.Certified.Modeled.Companion β)}, + (List.map (fun x => x.header.ref) companions).Nodup → + (∀ (companion : Theory.Certified.Modeled.Companion β), + companion ∈ companions → entries companion.header.ref = none) → + (∀ (companion : Theory.Certified.Modeled.Companion β), + companion ∈ companions → Theory.Certified.Modeled.CompanionChecked entries companions companion) → + Theory.Certified.Modeled.CheckedCompanions entries companions +PREMISE Ix.Theory.Certified.Modeled.CheckedEquation.mk +∀ {β : Type u} {entries : Theory.Model.Environment β} {rule : Theory.Certified.Signature.Rule β}, + Theory.Certified.Signature.RuleFormed entries rule → + Theory.Model.ConversionClaim entries [] rule.lhs rule.rhs → Theory.Certified.Modeled.CheckedEquation entries rule +PREMISE Ix.Theory.Certified.Modeled.checkEquation? +{β : Type u} → + [DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (rule : Theory.Certified.Signature.Rule β) → + Theory.Certified.Modeled.EquationWitness β → + Option (Theory.Certified.CheckedClaim (Theory.Certified.Modeled.CheckedEquation entries rule)) +DEFINITION +fun {β} [DecidableEq β] fuel entries rule witness => do + let formed ← Theory.Certified.Signature.checkRule fuel entries rule witness.formation + match witness.proof with + | Theory.Certified.Modeled.EquationProof.conversion witness => do + let equality ← Theory.Certified.verifyConversion fuel rule.universes entries [] rule.lhs rule.rhs witness + pure { down := ⋯ } + | Theory.Certified.Modeled.EquationProof.propositional family reflexivity recursor proof typing => + if hi : Theory.Certified.Basis.Equality.Interface entries family reflexivity recursor then do + let type ← + Theory.Certified.verifyType fuel rule.universes entries [] rule.type + (Theory.Model.AExpr.sort witness.formation.level) witness.formation.type + let checked ← + Theory.Certified.verifyType fuel rule.universes entries [] proof + (Theory.Certified.Basis.Equality.applied family witness.formation.level rule.type rule.lhs rule.rhs) + typing + pure { down := ⋯ } + else none +RUNTIME EXTERN Blake3.Rust.hasherFinalize +Blake3.Rust.Hasher → (length : USize) → { r // r.size = length.toNat } +RUNTIME EXTERN Blake3.Rust.hasherInit +Unit → Blake3.Rust.Hasher +RUNTIME EXTERN Blake3.Rust.hasherInitDeriveKey +ByteArray → Blake3.Rust.Hasher +RUNTIME EXTERN Blake3.Rust.hasherInitKeyed +Blake3.Blake3Key → Blake3.Rust.Hasher +RUNTIME EXTERN Blake3.Rust.hasherUpdate +Blake3.Rust.Hasher → ByteArray → Blake3.Rust.Hasher +RECURSION WORKER Ixon.getExprAllBinders._unsafe_rec +Ixon.GetM Ixon.Expr → Nat → Ixon.GetM (List (Ixon.Uses × Ixon.Owned × Ixon.Expr)) +IMPLEMENTATION +fun recur x => + match x with + | 0 => pure [] + | count.succ => do + let mode ← Ixon.getU8 + have __do_jp : Unit → Ixon.GetM (List (Ixon.Uses × Ixon.Owned × Ixon.Expr)) := fun __r => + match Ixon.Uses.ofBits? (mode &&& 3) with + | some uses => + match Ixon.Owned.ofBits? (mode >>> 2 &&& 1) with + | some owned => do + let ty ← recur + let tail ← Ixon.getExprAllBinders._unsafe_rec recur count + pure ((uses, owned, ty) :: tail) + | x => throw (toString "getExpr: invalid forall ownership mode " ++ toString mode) + | x => throw (toString "getExpr: invalid forall usage mode " ++ toString mode) + if mode > 7 then do + let __r ← throw (toString "getExpr: invalid forall mode " ++ toString mode) + __do_jp __r + else __do_jp () +RECURSION WORKER Ixon.getExprAppArgs._unsafe_rec +Ixon.GetM Ixon.Expr → Nat → Ixon.Expr → Ixon.GetM Ixon.Expr +IMPLEMENTATION +fun recur x x_1 => + match x, x_1 with + | 0, result => pure result + | count.succ, result => do + let arg ← recur + Ixon.getExprAppArgs._unsafe_rec recur count (result.app arg) +RECURSION WORKER Ixon.getExprFuel._unsafe_rec +Nat → Ixon.GetM Ixon.Expr +IMPLEMENTATION +fun x => + match x with + | 0 => throw "getExpr: recursion budget exhausted" + | fuel.succ => Ixon.getTag4 >>= Ixon.getExprFromTag (Ixon.getExprFuel._unsafe_rec fuel) +RECURSION WORKER Ixon.getExprLamBinders._unsafe_rec +Ixon.GetM Ixon.Expr → Nat → Ixon.GetM (List (Ixon.Uses × Ixon.Expr)) +IMPLEMENTATION +fun recur x => + match x with + | 0 => pure [] + | count.succ => do + let mode ← Ixon.getU8 + match Ixon.Uses.ofBits? mode with + | some uses => do + let ty ← recur + let tail ← Ixon.getExprLamBinders._unsafe_rec recur count + pure ((uses, ty) :: tail) + | x => throw (toString "getExpr: invalid lambda mode " ++ toString mode) +RECURSION WORKER Ixon.getTag0Sizes._unsafe_rec +Nat → Ixon.GetM (List UInt64) +IMPLEMENTATION +fun x => + match x with + | 0 => pure [] + | count.succ => do + let __do_lift ← Ixon.getTag0 + let head : UInt64 := __do_lift.size + let tail ← Ixon.getTag0Sizes._unsafe_rec count + pure (head :: tail) +RECURSION WORKER Ixon.getU64TrimmedLEAux._unsafe_rec +Nat → Ixon.GetM UInt64 +IMPLEMENTATION +fun x => + match x with + | 0 => pure 0 + | len.succ => do + let low ← Ixon.getU8 + let high ← Ixon.getU64TrimmedLEAux._unsafe_rec len + pure (low.toUInt64 ||| high <<< 8) +RECURSION WORKER Ixon.getUnivFuel._unsafe_rec +Nat → Ixon.GetM Ixon.Univ +IMPLEMENTATION +fun x => + match x with + | 0 => throw "getUniv: recursion budget exhausted" + | fuel.succ => Ixon.getTag2 >>= Ixon.getUnivFromTag (Ixon.getUnivFuel._unsafe_rec fuel) +RECURSION WORKER Ixon.putExpr._unsafe_rec +Ixon.Expr → Ixon.PutM Unit +IMPLEMENTATION +fun x => + match x with + | Ixon.Expr.sort idx => Ixon.putTag4 { flag := Ixon.Expr.FLAG_SORT, size := idx } + | Ixon.Expr.var idx => Ixon.putTag4 { flag := Ixon.Expr.FLAG_VAR, size := idx } + | Ixon.Expr.ref refIdx univIdxs => do + Ixon.putTag4 { flag := Ixon.Expr.FLAG_REF, size := univIdxs.size.toUInt64 } + Ixon.putTag0 { size := refIdx } + forIn univIdxs PUnit.unit fun idx __s => do + Ixon.putTag0 { size := idx } + pure (ForInStep.yield PUnit.unit) + pure () + | Ixon.Expr.recur recIdx univIdxs => do + Ixon.putTag4 { flag := Ixon.Expr.FLAG_REC, size := univIdxs.size.toUInt64 } + Ixon.putTag0 { size := recIdx } + forIn univIdxs PUnit.unit fun idx __s => do + Ixon.putTag0 { size := idx } + pure (ForInStep.yield PUnit.unit) + pure () + | Ixon.Expr.prj typeRefIdx fieldIdx val => do + Ixon.putTag4 { flag := Ixon.Expr.FLAG_PRJ, size := fieldIdx } + Ixon.putTag0 { size := typeRefIdx } + Ixon.putExpr._unsafe_rec val + | Ixon.Expr.str refIdx => Ixon.putTag4 { flag := Ixon.Expr.FLAG_STR, size := refIdx } + | Ixon.Expr.nat refIdx => Ixon.putTag4 { flag := Ixon.Expr.FLAG_NAT, size := refIdx } + | e@h:(a.app a_1) => do + Ixon.putTag4 { flag := Ixon.Expr.FLAG_APP, size := e.collectAppArgs.fst.length.toUInt64 } + Ixon.putExpr._unsafe_rec e.collectAppArgs.snd + forIn e.collectAppArgs.fst PUnit.unit fun arg __s => do + Ixon.putExpr._unsafe_rec arg + pure (ForInStep.yield PUnit.unit) + pure () + | e@h:(Ixon.Expr.lam a a_1 a_2) => do + Ixon.putTag4 { flag := Ixon.Expr.FLAG_LAM, size := e.collectLamBinders.fst.length.toUInt64 } + forIn e.collectLamBinders.fst PUnit.unit fun binder __s => do + Ixon.putU8 binder.fst.toBits + Ixon.putExpr._unsafe_rec binder.snd + pure (ForInStep.yield PUnit.unit) + Ixon.putExpr._unsafe_rec e.collectLamBinders.snd + | e@h:(Ixon.Expr.all a a_1 a_2 a_3) => do + Ixon.putTag4 { flag := Ixon.Expr.FLAG_ALL, size := e.collectAllBinders.fst.length.toUInt64 } + forIn e.collectAllBinders.fst PUnit.unit fun binder __s => do + Ixon.putU8 (binder.fst.toBits ||| binder.snd.fst.toBits <<< 2) + Ixon.putExpr._unsafe_rec binder.snd.snd + pure (ForInStep.yield PUnit.unit) + Ixon.putExpr._unsafe_rec e.collectAllBinders.snd + | Ixon.Expr.letE nonDep ty val body => do + Ixon.putTag4 { flag := Ixon.Expr.FLAG_LET, size := if nonDep = true then 1 else 0 } + Ixon.putExpr._unsafe_rec ty + Ixon.putExpr._unsafe_rec val + Ixon.putExpr._unsafe_rec body + | Ixon.Expr.share idx => Ixon.putTag4 { flag := Ixon.Expr.FLAG_SHARE, size := idx } +RECURSION WORKER Ixon.putU64TrimmedLEAux._unsafe_rec +UInt64 → Nat → Ixon.PutM Unit +IMPLEMENTATION +fun x x_1 => + match x_1 with + | 0 => pure () + | len.succ => do + Ixon.putU8 x.toUInt8 + Ixon.putU64TrimmedLEAux._unsafe_rec (x >>> 8) len +RECURSION WORKER Ixon.putUniv._unsafe_rec +Ixon.Univ → Ixon.PutM Unit +IMPLEMENTATION +fun x => + match x with + | Ixon.Univ.zero => Ixon.putTag2 { flag := Ixon.Univ.FLAG_ZERO_SUCC, size := 0 } + | u@h:a.succ => do + Ixon.putTag2 { flag := Ixon.Univ.FLAG_ZERO_SUCC, size := u.succCount } + Ixon.putUniv._unsafe_rec u.succBase + | a.max b => do + Ixon.putTag2 { flag := Ixon.Univ.FLAG_MAX, size := 0 } + Ixon.putUniv._unsafe_rec a + Ixon.putUniv._unsafe_rec b + | a.imax b => do + Ixon.putTag2 { flag := Ixon.Univ.FLAG_IMAX, size := 0 } + Ixon.putUniv._unsafe_rec a + Ixon.putUniv._unsafe_rec b + | Ixon.Univ.var idx => Ixon.putTag2 { flag := Ixon.Univ.FLAG_VAR, size := idx } +RECURSION WORKER _private.Ix.Address.0.bytesOfHex.go._unsafe_rec +List Char → Option (List UInt8) +IMPLEMENTATION +fun a => + match a with + | hi :: lo :: rest => do + let b ← byteOfHex hi lo + let bs ← bytesOfHex.go._unsafe_rec✝ rest + some (b :: bs) + | [] => pure [] + | x => none +RECURSION WORKER Ix.Certified.frontierOrder?._unsafe_rec +Nat → + Theory.Certified.PrimitiveSignature Address → + Theory.Store Address → + List (Theory.ConstRef Address) → + List (Theory.ConstRef Address) → + List (Theory.ConstRef Address) → List (Theory.ConstRef Address) → Option (List (Theory.ConstRef Address)) +IMPLEMENTATION +fun fuel signature store allowed pending visited active => + match fuel, pending with + | x, [] => some visited + | 0, head :: tail => none + | fuel.succ, ref :: rest => + if ref = signature.falseType ∨ ref = signature.falseElim ∨ ref ∈ visited then + frontierOrder?._unsafe_rec fuel signature store allowed rest visited active + else + if ref ∈ active ∨ ¬ref ∈ allowed then none + else do + let type ← store.type ref + let visited ← frontierOrder?._unsafe_rec fuel signature store allowed type.refs visited (ref :: active) + frontierOrder?._unsafe_rec fuel signature store allowed rest (visited ++ [ref]) active +RECURSION WORKER Ix.Certified.getTreeBody._unsafe_rec +Nat → Ixon.GetM AssumptionTree +IMPLEMENTATION +fun x => + match x with + | 0 => throw "certified tree depth limit" + | fuel.succ => do + let __do_lift ← Ixon.getU8 + match __do_lift with + | 0 => do + let __do_lift ← Ixon.Serialize.get + pure (AssumptionTree.leaf __do_lift) + | 1 => pure AssumptionTree.padding + | 2 => do + let __do_lift ← getTreeBody._unsafe_rec fuel + let __do_lift_1 ← getTreeBody._unsafe_rec fuel + pure (__do_lift.node __do_lift_1) + | x => throw "invalid certified tree node" +RECURSION WORKER Ix.Certified.lookup._unsafe_rec +{α : Type u_1} → List (Address × α) → Address → Option α +IMPLEMENTATION +fun {α} entries address => + match entries with + | [] => none + | (key, value) :: rest => if address = key then some value else lookup._unsafe_rec rest address +RECURSION WORKER Ix.Certified.putTreeBody._unsafe_rec +AssumptionTree → Ixon.PutM Unit +IMPLEMENTATION +fun x => + match x with + | AssumptionTree.leaf address => do + Ixon.putU8 0 + Ixon.Serialize.put address + | AssumptionTree.padding => Ixon.putU8 1 + | left.node right => do + Ixon.putU8 2 + putTreeBody._unsafe_rec left + putTreeBody._unsafe_rec right +RECURSION WORKER Ix.Certified.readBlocks?._unsafe_rec +Nat → Objects → Naturals → Objects → Option (List (Address × Theory.Block Address)) +IMPLEMENTATION +fun fuel objects naturals x => + match x with + | [] => some [] + | (address, source) :: rest => + if isProjection source.info = true then do + let _ ← resolveReference? objects address + readBlocks?._unsafe_rec fuel objects naturals rest + else do + let block ← readBlock? fuel objects naturals address source + let rest ← readBlocks?._unsafe_rec fuel objects naturals rest + pure ((address, block) :: rest) +RECURSION WORKER Ix.Certified.readExpr?._unsafe_rec +Nat → Objects → Naturals → Address → Ixon.Constant → Ixon.Expr → Option (Theory.VExpr Address) +IMPLEMENTATION +fun fuel objects naturals block source => + match (motive := Nat → Ixon.Expr → Option (Theory.VExpr Address)) fuel with + | 0 => fun x => none + | fuel.succ => fun expression => + match expression with + | Ixon.Expr.var index => some (Theory.VExpr.bvar index.toNat) + | Ixon.Expr.sort index => Option.map (Theory.VExpr.sort ∘ readLevel) source.univs[index.toNat]? + | Ixon.Expr.ref index levels => do + let address ← source.refs[index.toNat]? + let reference ← resolveReference? objects address + let levels ← readLevels? source levels + pure (Theory.VExpr.const reference levels) + | Ixon.Expr.recur index levels => do + let levels ← readLevels? source levels + pure (Theory.VExpr.const (Theory.ConstRef.member block index.toNat) levels) + | f.app a => do + let f ← readExpr?._unsafe_rec fuel objects naturals block source f + let a ← readExpr?._unsafe_rec fuel objects naturals block source a + pure (f.app a) + | Ixon.Expr.lam Ixon.Uses.many A b => do + let A ← readExpr?._unsafe_rec fuel objects naturals block source A + let b ← readExpr?._unsafe_rec fuel objects naturals block source b + pure (A.lam b) + | Ixon.Expr.all Ixon.Uses.many Ixon.Owned.shared A B => do + let A ← readExpr?._unsafe_rec fuel objects naturals block source A + let B ← readExpr?._unsafe_rec fuel objects naturals block source B + pure (A.forallE B) + | Ixon.Expr.prj owner field value => do + let address ← source.refs[owner.toNat]? + let ownerSource ← lookup objects address + match ownerSource.info with + | Ixon.ConstantInfo.iPrj a => do + let reference ← resolveReference? objects address + let value ← readExpr?._unsafe_rec fuel objects naturals block source value + pure (Theory.VExpr.proj reference field.toNat value) + | x => none + | Ixon.Expr.nat index => do + let address ← source.refs[index.toNat]? + let __do_lift ← lookup naturals address + pure (Theory.VExpr.natLit __do_lift) + | Ixon.Expr.share index => do + let shared ← source.sharing[index.toNat]? + readExpr?._unsafe_rec fuel objects naturals block source shared + | x => none +RECURSION WORKER Ix.Certified.readLevel._unsafe_rec +Ixon.Univ → Theory.VLevel +IMPLEMENTATION +fun x => + match x with + | Ixon.Univ.zero => Theory.VLevel.zero + | u.succ => (readLevel._unsafe_rec u).succ + | u.max v => (readLevel._unsafe_rec u).max (readLevel._unsafe_rec v) + | u.imax v => (readLevel._unsafe_rec u).imax (readLevel._unsafe_rec v) + | Ixon.Univ.var i => Theory.VLevel.param i.toNat +RECURSION WORKER Ix.Certified.sourceLevelValue._unsafe_rec +List Nat → Ixon.Univ → Nat +IMPLEMENTATION +fun levels x => + match x with + | Ixon.Univ.zero => 0 + | level.succ => sourceLevelValue._unsafe_rec levels level + 1 + | left.max right => max (sourceLevelValue._unsafe_rec levels left) (sourceLevelValue._unsafe_rec levels right) + | left.imax right => + if sourceLevelValue._unsafe_rec levels right = 0 then 0 + else max (sourceLevelValue._unsafe_rec levels left) (sourceLevelValue._unsafe_rec levels right) + | Ixon.Univ.var index => levels.getD index.toNat 0 +RECURSION WORKER Ix.Certified.treeLeaves._unsafe_rec +AssumptionTree → List Address +IMPLEMENTATION +fun x => + match x with + | AssumptionTree.leaf address => [address] + | AssumptionTree.padding => [] + | left.node right => treeLeaves._unsafe_rec left ++ treeLeaves._unsafe_rec right +RECURSION WORKER Ix.Certified.treeRoot._unsafe_rec +AssumptionTree → Address +IMPLEMENTATION +fun x => + match x with + | AssumptionTree.leaf address => Merkle.leafHash address + | AssumptionTree.padding => Merkle.zeroAddress + | left.node right => Merkle.nodeHash (treeRoot._unsafe_rec left) (treeRoot._unsafe_rec right) +RECURSION WORKER Ixon.Expr.collectAllBinders._unsafe_rec +Ixon.Expr → List (Ixon.Uses × Ixon.Owned × Ixon.Expr) × Ixon.Expr +IMPLEMENTATION +fun x => + match x with + | Ixon.Expr.all uses owned ty body => + match Ixon.Expr.collectAllBinders._unsafe_rec body with + | (binders, base) => ((uses, owned, ty) :: binders, base) + | e => ([], e) +RECURSION WORKER Ixon.Expr.collectAppArgs._unsafe_rec +Ixon.Expr → List Ixon.Expr × Ixon.Expr +IMPLEMENTATION +fun x => + match x with + | f.app a => + match Ixon.Expr.collectAppArgs._unsafe_rec f with + | (args, base) => (args ++ [a], base) + | e => ([], e) +RECURSION WORKER Ixon.Expr.collectLamBinders._unsafe_rec +Ixon.Expr → List (Ixon.Uses × Ixon.Expr) × Ixon.Expr +IMPLEMENTATION +fun x => + match x with + | Ixon.Expr.lam uses ty body => + match Ixon.Expr.collectLamBinders._unsafe_rec body with + | (binders, base) => ((uses, ty) :: binders, base) + | e => ([], e) +RECURSION WORKER Ixon.Expr.nodeCount._unsafe_rec +Ixon.Expr → Nat +IMPLEMENTATION +fun x => + match x with + | Ixon.Expr.sort a => 1 + | Ixon.Expr.var a => 1 + | Ixon.Expr.ref a a_1 => 1 + | Ixon.Expr.recur a a_1 => 1 + | Ixon.Expr.str a => 1 + | Ixon.Expr.nat a => 1 + | Ixon.Expr.share a => 1 + | Ixon.Expr.prj a a_1 val => Ixon.Expr.nodeCount._unsafe_rec val + 1 + | fn.app arg => Ixon.Expr.nodeCount._unsafe_rec fn + Ixon.Expr.nodeCount._unsafe_rec arg + 1 + | Ixon.Expr.lam a fn arg => Ixon.Expr.nodeCount._unsafe_rec fn + Ixon.Expr.nodeCount._unsafe_rec arg + 1 + | Ixon.Expr.all a a_1 fn arg => Ixon.Expr.nodeCount._unsafe_rec fn + Ixon.Expr.nodeCount._unsafe_rec arg + 1 + | Ixon.Expr.letE a ty val body => + Ixon.Expr.nodeCount._unsafe_rec ty + Ixon.Expr.nodeCount._unsafe_rec val + Ixon.Expr.nodeCount._unsafe_rec body + 1 +RECURSION WORKER Ixon.Univ.addSucc._unsafe_rec +Nat → Ixon.Univ → Ixon.Univ +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | 0, base => base + | count.succ, base => (Ixon.Univ.addSucc._unsafe_rec count base).succ +RECURSION WORKER Ixon.Univ.succBase._unsafe_rec +Ixon.Univ → Ixon.Univ +IMPLEMENTATION +fun x => + match x with + | inner.succ => Ixon.Univ.succBase._unsafe_rec inner + | u => u +RECURSION WORKER Ixon.Univ.succCountNat._unsafe_rec +Ixon.Univ → Nat +IMPLEMENTATION +fun x => + match x with + | inner.succ => 1 + Ixon.Univ.succCountNat._unsafe_rec inner + | x => 0 +RECURSION WORKER _private.Ix.Common.0.Nat.toBytesLE.go._unsafe_rec +Nat → Nat → List UInt8 +IMPLEMENTATION +fun a a_1 => + match a, a_1 with + | x, 0 => [] + | 0, x => [] + | f.succ, x => x.toUInt8 :: Nat.toBytesLE.go._unsafe_rec✝ f (x / 256) +RECURSION WORKER Ix.Certified.InputCache.natural?._unsafe_rec +(address : Address) → (bytes : ByteArray) → List CachedNatural → Option (DecodedNatural address bytes) +IMPLEMENTATION +fun address bytes x => + match x with + | [] => none + | entry :: rest => + if ha : entry.address = address then + if hb : entry.bytes = bytes then some (⋯.mpr entry.decoded) + else InputCache.natural?._unsafe_rec address bytes rest + else InputCache.natural?._unsafe_rec address bytes rest +RECURSION WORKER Ix.Certified.InputCache.object?._unsafe_rec +(address : Address) → (bytes : ByteArray) → List CachedObject → Option (DecodedObject address bytes) +IMPLEMENTATION +fun address bytes x => + match x with + | [] => none + | entry :: rest => + if ha : entry.address = address then + if hb : entry.bytes = bytes then some (⋯.mpr entry.decoded) else InputCache.object?._unsafe_rec address bytes rest + else InputCache.object?._unsafe_rec address bytes rest +RECURSION WORKER Ix.Theory.Certificate.annotations._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → Theory.Model.AnnotationTree +IMPLEMENTATION +fun {β} x => + match x with + | Theory.Model.AExpr.bvar index => Theory.Model.AnnotationTree.leaf + | Theory.Model.AExpr.sort level => Theory.Model.AnnotationTree.leaf + | Theory.Model.AExpr.const ref levels => Theory.Model.AnnotationTree.leaf + | Theory.Model.AExpr.natLit value => Theory.Model.AnnotationTree.leaf + | f.app a => (Theory.Certificate.annotations._unsafe_rec f).app (Theory.Certificate.annotations._unsafe_rec a) + | Theory.Model.AExpr.lam p A b => + Theory.Model.AnnotationTree.lam p.toRaw (Theory.Certificate.annotations._unsafe_rec A) + (Theory.Certificate.annotations._unsafe_rec b) + | Theory.Model.AExpr.forallE p A B => + Theory.Model.AnnotationTree.forallE p.toRaw (Theory.Certificate.annotations._unsafe_rec A) + (Theory.Certificate.annotations._unsafe_rec B) + | Theory.Model.AExpr.proj ref field e => (Theory.Certificate.annotations._unsafe_rec e).proj +RECURSION WORKER Ix.Theory.Certificate.applicationArgs._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → List (Theory.Model.AExpr β) → List (Theory.Model.AExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | f.app a, args => Theory.Certificate.applicationArgs._unsafe_rec f (a :: args) + | x, args => args +RECURSION WORKER Ix.Theory.Certificate.applyFact?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + Theory.Certificate.Suggestion β → List (Theory.Model.AExpr β) → Option (Theory.Certificate.Suggestion β) +IMPLEMENTATION +fun {β} [inst : DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ fact args => + match fuel with + | 0 => none + | fuel.succ => + match args with + | [] => some fact + | arg :: rest => + match fact.expression with + | Theory.Model.AExpr.lam p D body => + match fact.type with + | Theory.Model.AExpr.forallE q A B => + if (p != q || D != A) = true then none + else do + let a ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ arg + let aw ← Theory.Certificate.castWith?._unsafe_rec fuel n entries Γ a D + Theory.Certificate.applyFact?._unsafe_rec fuel n entries Γ + { expression := body.inst arg, type := B.inst arg, + witness := Theory.Certified.TypingWitness.betaResult p D body arg B fact.witness aw } + rest + | x => none + | x => none +RECURSION WORKER Ix.Theory.Certificate.beta?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + Theory.Model.AExpr β → Option (Theory.Model.AExpr β × Theory.Certified.ConversionWitness β) +IMPLEMENTATION +fun {β} [inst : DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ e => + match fuel with + | 0 => none + | fuel.succ => + match e with + | (Theory.Model.AExpr.lam p D body).app arg => do + let fn ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ (Theory.Model.AExpr.lam p D body) + let a ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ arg + let aw ← Theory.Certificate.castWith?._unsafe_rec fuel n entries Γ a D + pure (body.inst arg, Theory.Certified.ConversionWitness.beta fn.type fn.witness aw) + | x => none +RECURSION WORKER Ix.Theory.Certificate.castWith?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + Theory.Certificate.Suggestion β → Theory.Model.AExpr β → Option (Theory.Certified.TypingWitness β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ suggestion type => + match fuel with + | 0 => none + | fuel.succ => + match Theory.Certificate.cast? n suggestion type with + | some witness => some witness + | none => do + let target ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ type + let target ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ target + match target.type with + | Theory.Model.AExpr.sort l => do + let witness ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ suggestion.type type + pure (Theory.Certified.TypingWitness.conv suggestion.type l suggestion.witness target.witness witness) + | x => none +RECURSION WORKER Ix.Theory.Certificate.conversion?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + Theory.Model.AExpr β → Theory.Model.AExpr β → Option (Theory.Certified.ConversionWitness β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ a b => + match fuel with + | 0 => none + | fuel.succ => + if a = b then some Theory.Certified.ConversionWitness.refl + else + match Theory.Certificate.headStep?._unsafe_rec fuel n entries Γ a with + | some (a', w) => do + let __do_lift ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ a' b + pure (Theory.Certified.ConversionWitness.trans a' w __do_lift) + | none => + match Theory.Certificate.headStep?._unsafe_rec fuel n entries Γ b with + | some (b', w) => do + let __do_lift ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ a b' + pure (Theory.Certified.ConversionWitness.trans b' __do_lift w.symm) + | none => + let congruence := fun x => + match a, b with + | Theory.Model.AExpr.sort l, Theory.Model.AExpr.sort l' => + if Theory.Certified.LevelEq.check n l l' = true then some Theory.Certified.ConversionWitness.sort + else none + | f.app x, g.app y => do + let __do_lift ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ f g + let __do_lift_1 ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ x y + pure (__do_lift.app __do_lift_1) + | Theory.Model.AExpr.proj r i x, Theory.Model.AExpr.proj q j y => + if r = q ∧ i = j then + (fun x => x.proj) <$> Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ x y + else none + | Theory.Model.AExpr.lam p D body, Theory.Model.AExpr.lam q D' body' => + if (p != q) = true then none + else do + let domain ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ D + match domain.type with + | Theory.Model.AExpr.sort l => do + let __do_lift ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ D D' + let __do_lift_1 ← + Theory.Certificate.conversion?._unsafe_rec fuel n entries (Theory.Model.Context.push D Γ) body + body' + pure (Theory.Certified.ConversionWitness.lam l domain.witness __do_lift __do_lift_1) + | x => none + | Theory.Model.AExpr.forallE p D B, Theory.Model.AExpr.forallE q D' B' => + if (p != q) = true then none + else do + let domain ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ D + match domain.type with + | Theory.Model.AExpr.sort l => do + let __do_lift ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ D D' + let __do_lift_1 ← + Theory.Certificate.conversion?._unsafe_rec fuel n entries (Theory.Model.Context.push D Γ) B B' + pure (Theory.Certified.ConversionWitness.forallE l domain.witness __do_lift __do_lift_1) + | x => none + | x, x_1 => none; + let proofIrrel := fun x => do + let left ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ a + let type ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ left.type + let typeWitness ← Theory.Certificate.cast? n type (Theory.Model.AExpr.sort Theory.VLevel.zero) + let right ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ b + let rightWitness ← Theory.Certificate.castWith?._unsafe_rec fuel n entries Γ right left.type + pure (Theory.Certified.ConversionWitness.proofIrrel left.type typeWitness left.witness rightWitness); + Theory.Certificate.eta?._unsafe_rec fuel n entries Γ a b <|> + (fun x => x.symm) <$> Theory.Certificate.eta?._unsafe_rec fuel n entries Γ b a <|> + congruence () <|> + match Theory.Certificate.equationStep?._unsafe_rec fuel n entries Γ a with + | some (a', w) => do + let __do_lift ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ a' b + pure (Theory.Certified.ConversionWitness.trans a' w __do_lift) + | none => + match Theory.Certificate.equationStep?._unsafe_rec fuel n entries Γ b with + | some (b', w) => do + let __do_lift ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ a b' + pure (Theory.Certified.ConversionWitness.trans b' __do_lift w.symm) + | none => proofIrrel () +RECURSION WORKER Ix.Theory.Certificate.declarationWitnesses?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Theory.Store β → + Theory.Model.Environment β → + List (Theory.Certificate.DeclarationSource β) → + Option (Theory.Model.Environment β × List (Theory.Certified.DeclarationWitness β)) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel store entries x => + match x with + | [] => some (entries, []) + | Theory.Certificate.DeclarationSource.definition r :: rest => do + let source ← store.lookup r + let witness ← Theory.Certificate.definitionWitness? fuel entries r source + let reading ← Theory.Certified.readDefinition? source witness.typeAnnotations witness.bodyAnnotations + let __x ← Theory.Certificate.declarationWitnesses?._unsafe_rec fuel store (entries.insert r reading.val.entry) rest + match __x with + | (entries', witnesses) => pure (entries', Theory.Certified.DeclarationWitness.definition witness :: witnesses) + | Theory.Certificate.DeclarationSource.ordinary source recursor :: rest => do + let witness ← Theory.Certificate.Ordinary.sourceBlock? fuel entries store source recursor + if Theory.Certificate.Hints.natural = some (Theory.ConstRef.member source 0) then + if (witness.shape.shape != Theory.Certified.Natural.shape) = true then none + else do + let __x ← + Theory.Certificate.declarationWitnesses?._unsafe_rec fuel store + (Theory.Certified.Natural.environment entries source recursor witness.mode) rest + match __x with + | (entries', witnesses) => pure (entries', Theory.Certified.DeclarationWitness.natural witness :: witnesses) + else + match Theory.Certificate.Structure.witness? fuel entries witness with + | some structured => do + let __x ← + Theory.Certificate.declarationWitnesses?._unsafe_rec fuel store + (structured.facts.description.publishedEnvironment entries source recursor witness.mode) rest + match __x with + | (entries', witnesses) => + pure (entries', Theory.Certified.DeclarationWitness.structure structured :: witnesses) + | none => do + let __x ← + Theory.Certificate.declarationWitnesses?._unsafe_rec fuel store + (witness.shape.shape.publishedEnvironment entries source recursor witness.mode) rest + match __x with + | (entries', witnesses) => + pure (entries', Theory.Certified.DeclarationWitness.ordinary witness :: witnesses) + | Theory.Certificate.DeclarationSource.standard ref :: rest => do + let source ← store.lookup ref + let witness ← Theory.Certificate.Standard.witness? fuel store entries ref source + let __x ← + Theory.Certificate.declarationWitnesses?._unsafe_rec fuel store (entries.insert ref witness.spec.entry) rest + match __x with + | (entries', witnesses) => pure (entries', Theory.Certified.DeclarationWitness.standard witness :: witnesses) + | Theory.Certificate.DeclarationSource.quotient refs :: rest => do + let witness ← Theory.Certificate.Quotient.witness? fuel entries refs + let __x ← Theory.Certificate.declarationWitnesses?._unsafe_rec fuel store (refs.environment entries) rest + match __x with + | (entries', witnesses) => pure (entries', Theory.Certified.DeclarationWitness.quotient witness :: witnesses) + | Theory.Certificate.DeclarationSource.modeled candidate :: rest => do + let witness ← candidate.witness? fuel entries store + let __x ← + Theory.Certificate.declarationWitnesses?._unsafe_rec fuel store + (Theory.Certified.Modeled.environment entries witness.companions) rest + match __x with + | (entries', witnesses) => pure (entries', Theory.Certified.DeclarationWitness.modeled witness :: witnesses) +RECURSION WORKER Ix.Theory.Certificate.dependencyOrder?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + Theory.Certified.PrimitiveSignature β → + Theory.Store β → + List (Theory.ConstRef β) → + List (Theory.ConstRef β) → + List (Theory.ConstRef β) → + optParam (List (Theory.Certificate.DeclarationSource β)) [] → + optParam (List (Theory.Certificate.Modeled.Candidate β)) [] → + Option (List (Theory.ConstRef β) × List (Theory.Certificate.DeclarationSource β)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel signature store pending visited active order models => + match fuel, pending with + | x, [] => some (visited, order) + | 0, head :: tail => none + | fuel.succ, r :: rest => + if r = signature.falseType ∨ r = signature.falseElim ∨ r ∈ visited then + Theory.Certificate.dependencyOrder?._unsafe_rec fuel signature store rest visited active order models + else + if r ∈ active then none + else do + let group ← Theory.Certificate.sourceGroup? store r signature.natType models + if (group.references.any fun x => active.contains x) = true then none + else do + let __x ← + Theory.Certificate.dependencyOrder?._unsafe_rec fuel signature store group.dependencies visited + (group.references ++ active) order models + match __x with + | (visited, order) => + Theory.Certificate.dependencyOrder?._unsafe_rec fuel signature store rest (visited ++ group.references) + active (order ++ [group.declaration]) models +RECURSION WORKER Ix.Theory.Certificate.equationStep?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + Theory.Model.AExpr β → Option (Theory.Model.AExpr β × Theory.Certified.ConversionWitness β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ e => + match fuel with + | 0 => none + | fuel.succ => + have __do_jp := fun __x => + match __x with + | (ref, levels) => do + let entry ← entries ref + if (levels.length != entry.universes) = true then none + else + List.findSome? + (fun x => + match x with + | (law, i) => + let lhs := Theory.Model.AExpr.instL levels law.lhs; + let rhs := Theory.Model.AExpr.instL levels law.rhs; + do + let args ← + Theory.Certificate.equationArguments? lhs e <|> + (match Theory.Certificate.lambdaBody lhs with + | (fst, fn.app constructor) => do + let __x ← Theory.Certificate.headConstant? constructor + match __x with + | (Theory.ConstRef.ctor b i c, snd) => + match e with + | fn.app major => do + let expanded ← Theory.Certificate.etaMajor?._unsafe_rec fuel n entries Γ major + Theory.Certificate.equationArguments? lhs (fn.app expanded) + | x => none + | x => none + | x => none) <|> + match e with + | fn.app major => do + let typed ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ major + let type ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ typed.type + let _ ← Theory.Certificate.cast? n type (Theory.Model.AExpr.sort Theory.VLevel.zero) + Theory.Certificate.equationProofArguments? lhs e + | x => none + let lhsApplied : Theory.Model.AExpr β := List.foldl Theory.Model.AExpr.app lhs args + let rhsApplied : Theory.Model.AExpr β := List.foldl Theory.Model.AExpr.app rhs args + let beta ← Theory.Certificate.conversion?._unsafe_rec fuel n entries Γ lhsApplied e + let equation : Theory.Certified.ConversionWitness β := + List.foldl (fun w x => w.app Theory.Certified.ConversionWitness.refl) + (Theory.Certified.ConversionWitness.equation ref i levels) args + pure (rhsApplied, Theory.Certified.ConversionWitness.trans lhsApplied beta.symm equation)) + entry.equations.zipIdx; + match e with + | Theory.Model.AExpr.proj ref field major => do + let typed ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ major + let typed ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ typed + let __x ← Theory.Certificate.headConstant? typed.type + match __x with + | (owner, levels) => + if owner = ref then do + let __x ← some (ref, levels) + __do_jp __x + else do + let __x ← none + __do_jp __x + | x => do + let __x ← Theory.Certificate.headConstant? e + match __x with + | (ref, levels) => + let owner := + match ref with + | Theory.ConstRef.ctor source member c => Theory.ConstRef.member source member + | x => ref; + do + let __x ← some (owner, levels) + __do_jp __x +RECURSION WORKER Ix.Theory.Certificate.eta?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + Theory.Model.AExpr β → Theory.Model.AExpr β → Option (Theory.Certified.ConversionWitness β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ a b => + match fuel with + | 0 => none + | fuel.succ => + match a with + | Theory.Model.AExpr.lam p D body => do + let fn ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ b + let fn ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ fn + match fn.type with + | Theory.Model.AExpr.forallE q D' B => + if p = q ∧ D = D' ∧ body = (Theory.Model.AExpr.liftN 1 b).app (Theory.Model.AExpr.bvar 0) then + pure (Theory.Certified.ConversionWitness.eta B fn.witness) + else none + | x => none + | x => none +RECURSION WORKER Ix.Theory.Certificate.etaMajor?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → Theory.Model.Environment β → Theory.Model.Context β → Theory.Model.AExpr β → Option (Theory.Model.AExpr β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ major => + match fuel with + | 0 => none + | fuel.succ => do + let typed ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ major + let typed ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ typed + let __x ← Theory.Certificate.headConstant? typed.type + match __x with + | (family, levels) => do + let entry ← entries family + if (levels.length != entry.universes) = true then none + else + List.findSome? + (fun law => + let arguments := Theory.Certificate.applicationArgs typed.type [] ++ [major]; + do + let rhs ← Theory.Certificate.instantiateLambdas? (Theory.Model.AExpr.instL levels law.rhs) arguments + if (rhs != major) = true then none + else do + let lhs ← Theory.Certificate.instantiateLambdas? (Theory.Model.AExpr.instL levels law.lhs) arguments + if lhs = major then none else some lhs) + entry.equations +RECURSION WORKER Ix.Theory.Certificate.frontierWitnesses?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Theory.Store β → + Theory.Model.Environment β → + List (Theory.ConstRef β) → Option (Theory.Model.Environment β × List (Theory.Certified.FrontierWitness β)) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel store entries x => + match x with + | [] => some (entries, []) + | ref :: refs => + match store.uvars ref, store.type ref with + | some universes, some type => do + let inferred ← Theory.Certificate.inferSource? fuel universes entries [] type + match inferred.type with + | Theory.Model.AExpr.sort level => + let witness := + { ref := ref, annotations := Theory.Certificate.annotations inferred.expression, level := level, + typing := inferred.witness }; + do + let reading ← Theory.Certified.readFrontierHeader? store witness + let __x ← + Theory.Certificate.frontierWitnesses?._unsafe_rec fuel store (entries.insert ref reading.header.entry) refs + match __x with + | (entries', rest) => pure (entries', witness :: rest) + | x => none + | x, x_1 => none +RECURSION WORKER Ix.Theory.Certificate.hasLiteral._unsafe_rec +{β : Type u} → Theory.VExpr β → Bool +IMPLEMENTATION +fun {β} x => + match x with + | Theory.VExpr.natLit value => true + | a.app b => Theory.Certificate.hasLiteral._unsafe_rec a || Theory.Certificate.hasLiteral._unsafe_rec b + | a.lam b => Theory.Certificate.hasLiteral._unsafe_rec a || Theory.Certificate.hasLiteral._unsafe_rec b + | a.forallE b => Theory.Certificate.hasLiteral._unsafe_rec a || Theory.Certificate.hasLiteral._unsafe_rec b + | Theory.VExpr.proj ref index e => Theory.Certificate.hasLiteral._unsafe_rec e + | x => false +RECURSION WORKER Ix.Theory.Certificate.headConstant?._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → Option (Theory.ConstRef β × List Theory.VLevel) +IMPLEMENTATION +fun {β} x => + match x with + | Theory.Model.AExpr.const r levels => some (r, levels) + | f.app arg => Theory.Certificate.headConstant?._unsafe_rec f + | x => none +RECURSION WORKER Ix.Theory.Certificate.headStep?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + Theory.Model.AExpr β → Option (Theory.Model.AExpr β × Theory.Certified.ConversionWitness β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ e => + match fuel with + | 0 => none + | fuel.succ => + let delta := fun x => + match e with + | Theory.Model.AExpr.const r ls => do + let entry ← entries r + if (ls.length != entry.universes) = true then none + else do + let body ← entry.body + pure (Theory.Model.AExpr.instL ls body, Theory.Certified.ConversionWitness.delta) + | x => none; + let app := fun x => + match e with + | f.app x => do + let __x ← + Theory.Certificate.headStep?._unsafe_rec fuel n entries Γ f <|> + Theory.Certificate.equationStep?._unsafe_rec fuel n entries Γ f + match __x with + | (f', w) => pure (f'.app x, w.app Theory.Certified.ConversionWitness.refl) + | x => none; + let argument := fun x => + match e with + | f.app x => do + let __x ← + Theory.Certificate.headStep?._unsafe_rec fuel n entries Γ x <|> + Theory.Certificate.equationStep?._unsafe_rec fuel n entries Γ x + match __x with + | (x', w) => pure (f.app x', Theory.Certified.ConversionWitness.refl.app w) + | x => none; + let projection := fun x => + match e with + | Theory.Model.AExpr.proj r i x => do + let __x ← + Theory.Certificate.headStep?._unsafe_rec fuel n entries Γ x <|> + Theory.Certificate.equationStep?._unsafe_rec fuel n entries Γ x + match __x with + | (x', w) => pure (Theory.Model.AExpr.proj r i x', w.proj) + | x => none; + let literal := fun x => + match e with + | Theory.Model.AExpr.natLit value => do + let ref ← Theory.Certificate.Hints.natural + let entry ← entries ref + if (entry.universes != 0) = true then none + else + List.findSome? + (fun x => + match x with + | (fact, i) => + match fact with + | Theory.Model.ConstantFact.natural zero succ => + some + (match value with + | 0 => Theory.Model.AExpr.const zero [] + | n.succ => (Theory.Model.AExpr.const succ []).app (Theory.Model.AExpr.natLit n), + Theory.Certified.ConversionWitness.natLiteral ref i) + | x => none) + entry.facts.zipIdx + | x => none; + Theory.Certificate.beta?._unsafe_rec fuel n entries Γ e <|> + delta () <|> app () <|> argument () <|> projection () <|> literal () +RECURSION WORKER Ix.Theory.Certificate.inferAnnotated?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → Theory.Model.AExpr β → Option (Theory.Certificate.Suggestion β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ e => + match fuel with + | 0 => none + | fuel.succ => do + let result ← Theory.Certificate.inferSource?._unsafe_rec fuel n entries Γ e.erase + if result.expression = e then some result else none +RECURSION WORKER Ix.Theory.Certificate.inferSource?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → Theory.VExpr β → Option (Theory.Certificate.Suggestion β) +IMPLEMENTATION +fun {β} [inst : DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ => + match (motive := Nat → Theory.VExpr β → Option (Theory.Certificate.Suggestion β)) fuel with + | 0 => fun x => none + | fuel.succ => fun source => + match source with + | Theory.VExpr.bvar i => do + let A ← Γ[i]? + pure { expression := Theory.Model.AExpr.bvar i, type := A, witness := Theory.Certified.TypingWitness.bvar } + | Theory.VExpr.sort l => + if Theory.VLevel.WF n l then + some + { expression := Theory.Model.AExpr.sort l, type := Theory.Model.AExpr.sort l.succ, + witness := Theory.Certified.TypingWitness.sort } + else none + | Theory.VExpr.const r ls => do + let entry ← entries r + if ls.length = entry.universes ∧ ∀ (l : Theory.VLevel), l ∈ ls → Theory.VLevel.WF n l then + pure + { expression := Theory.Model.AExpr.const r ls, type := Theory.Model.AExpr.instL ls entry.type, + witness := Theory.Certified.TypingWitness.const } + else none + | A.forallE B => do + let a ← Theory.Certificate.inferSource?._unsafe_rec fuel n entries Γ A + let a ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ a + match a.type with + | Theory.Model.AExpr.sort lA => do + let b ← + Theory.Certificate.inferSource?._unsafe_rec fuel n entries (Theory.Model.Context.push a.expression Γ) B + let b ← + Theory.Certificate.normalizeType?._unsafe_rec fuel n entries (Theory.Model.Context.push a.expression Γ) b + match b.type with + | Theory.Model.AExpr.sort lB => + pure + { + expression := + Theory.Model.AExpr.forallE (Theory.Certified.zeroCondition lB) a.expression b.expression, + type := Theory.Model.AExpr.sort (lA.imax lB), + witness := Theory.Certified.TypingWitness.forallE lA lB a.witness b.witness } + | x => none + | x => none + | A.lam body => do + let a ← Theory.Certificate.inferSource?._unsafe_rec fuel n entries Γ A + let a ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ a + match a.type with + | Theory.Model.AExpr.sort lA => do + let b ← + Theory.Certificate.inferSource?._unsafe_rec fuel n entries (Theory.Model.Context.push a.expression Γ) body + let b ← + Theory.Certificate.normalizeType?._unsafe_rec fuel n entries (Theory.Model.Context.push a.expression Γ) b + let B ← + Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries (Theory.Model.Context.push a.expression Γ) + b.type + let B ← + Theory.Certificate.normalizeType?._unsafe_rec fuel n entries (Theory.Model.Context.push a.expression Γ) B + match B.type with + | Theory.Model.AExpr.sort lB => + pure + { expression := Theory.Model.AExpr.lam (Theory.Certified.zeroCondition lB) a.expression b.expression, + type := Theory.Model.AExpr.forallE (Theory.Certified.zeroCondition lB) a.expression b.type, + witness := Theory.Certified.TypingWitness.lam lA lB b.type a.witness B.witness b.witness } + | x => none + | x => none + | f.app arg => do + let fn ← Theory.Certificate.inferSource?._unsafe_rec fuel n entries Γ f + let fn ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ fn + match fn.type with + | Theory.Model.AExpr.forallE p A B => do + let a ← Theory.Certificate.inferSource?._unsafe_rec fuel n entries Γ arg + let aw ← Theory.Certificate.castWith?._unsafe_rec fuel n entries Γ a A + pure + { expression := fn.expression.app a.expression, type := B.inst a.expression, + witness := Theory.Certified.TypingWitness.app p A B fn.witness aw } + | x => none + | Theory.VExpr.proj ref index major => do + let major ← Theory.Certificate.inferSource?._unsafe_rec fuel n entries Γ major + let typed ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ major + let __x ← Theory.Certificate.headConstant? typed.type + match __x with + | (owner, ls) => + if (owner != ref) = true then none + else do + let entry ← entries ref + if (ls.length != entry.universes) = true then none + else + List.findSome? + (fun x => + match x with + | (fact, factIndex) => + match fact with + | Theory.Model.ConstantFact.typed expression type => + match Theory.Certificate.lambdaBody expression with + | (fst, Theory.Model.AExpr.proj family field major_1) => + if (family != ref || field != index) = true then none + else do + let result ← + Theory.Certificate.applyFact?._unsafe_rec fuel n entries Γ + { expression := Theory.Model.AExpr.instL ls expression, + type := Theory.Model.AExpr.instL ls type, + witness := Theory.Certified.TypingWitness.fact ref factIndex ls } + (Theory.Certificate.applicationArgs typed.type [] ++ [major.expression]) + if result.expression = Theory.Model.AExpr.proj ref index major.expression then some result + else none + | x => none + | x => none) + entry.facts.zipIdx + | Theory.VExpr.natLit value => do + let ref ← Theory.Certificate.Hints.natural + let entry ← entries ref + if (entry.universes != 0) = true then none + else + List.findSome? + (fun x => + match x with + | (fact, i) => + match fact with + | Theory.Model.ConstantFact.natural zero succ => + some + { expression := Theory.Model.AExpr.natLit value, type := Theory.Model.AExpr.const ref [], + witness := Theory.Certified.TypingWitness.natLit ref i } + | x => none) + entry.facts.zipIdx +RECURSION WORKER Ix.Theory.Certificate.instantiateLambdas?._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → List (Theory.Model.AExpr β) → Option (Theory.Model.AExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | e, [] => some e + | Theory.Model.AExpr.lam condition domain body, arg :: rest => + Theory.Certificate.instantiateLambdas?._unsafe_rec (body.inst arg) rest + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certificate.lambdaBody._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → Nat × Theory.Model.AExpr β +IMPLEMENTATION +fun {β} x => + match x with + | Theory.Model.AExpr.lam condition domain body => + match Theory.Certificate.lambdaBody._unsafe_rec body with + | (n, result) => (n + 1, result) + | e => (0, e) +RECURSION WORKER Ix.Theory.Certificate.matchEquationArgs?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Theory.Model.AExpr β → + Theory.Model.AExpr β → List (Option (Theory.Model.AExpr β)) → Option (List (Option (Theory.Model.AExpr β))) +IMPLEMENTATION +fun {β} [DecidableEq β] x x_1 x_2 => + match x, x_1, x_2 with + | Theory.Model.AExpr.bvar i, actual, slots => do + let slot ← slots[i]? + match slot with + | none => some (slots.set i (some actual)) + | some previous => if previous = actual then some slots else none + | f.app x, g.app y, slots => do + let slots ← Theory.Certificate.matchEquationArgs?._unsafe_rec f g slots + Theory.Certificate.matchEquationArgs?._unsafe_rec x y slots + | Theory.Model.AExpr.const r ls, Theory.Model.AExpr.const q ms, slots => if r = q ∧ ls = ms then some slots else none + | Theory.Model.AExpr.sort l, Theory.Model.AExpr.sort m, slots => if l = m then some slots else none + | Theory.Model.AExpr.proj r i major, Theory.Model.AExpr.proj q j actual, slots => + if r = q ∧ i = j then Theory.Certificate.matchEquationArgs?._unsafe_rec major actual slots else none + | Theory.Model.AExpr.lam condition domain body, Theory.Model.AExpr.lam condition_1 domain_1 body_1, slots => + some slots + | Theory.Model.AExpr.forallE condition domain body, Theory.Model.AExpr.forallE condition_1 domain_1 body_1, slots => + some slots + | x, x_3, x_4 => none +RECURSION WORKER Ix.Theory.Certificate.normalizeType?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → Theory.Certificate.Suggestion β → Option (Theory.Certificate.Suggestion β) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ suggestion => + match fuel with + | 0 => none + | fuel.succ => + match suggestion.type with + | Theory.Model.AExpr.sort level => some suggestion + | Theory.Model.AExpr.forallE condition domain body => some suggestion + | x => + match + Theory.Certificate.headStep?._unsafe_rec fuel n entries Γ suggestion.type <|> + Theory.Certificate.equationStep?._unsafe_rec fuel n entries Γ suggestion.type with + | none => some suggestion + | some (type, conversion) => do + let formed ← Theory.Certificate.inferAnnotated?._unsafe_rec fuel n entries Γ type + let formed ← Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ formed + match formed.type with + | Theory.Model.AExpr.sort level => + Theory.Certificate.normalizeType?._unsafe_rec fuel n entries Γ + { expression := suggestion.expression, type := type, + witness := + Theory.Certified.TypingWitness.conv suggestion.type level suggestion.witness formed.witness + conversion } + | x => none +RECURSION WORKER Ix.Theory.Certificate.recursorFamily?._unsafe_rec +{β : Type u} → Theory.VExpr β → Option β +IMPLEMENTATION +fun {β} x => + match x with + | binderType.forallE (A.forallE B) => Theory.Certificate.recursorFamily?._unsafe_rec (A.forallE B) + | A.forallE body => + match A.appHead with + | Theory.VExpr.const (Theory.ConstRef.member source 0) levels => some source + | x => none + | x => none +RECURSION WORKER Ix.Theory.Certified.checkDeclarationExtensions?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + {signature : Theory.Certified.PrimitiveSignature β} → + {store : Theory.Store β} → + (state : Theory.Certified.CheckedInterface signature) → + List (Theory.Certified.DeclarationWitness β) → + Option (Theory.Certified.CheckedExtension signature store state) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel {signature} {store} state x => + match x with + | [] => some (Theory.Certified.CheckedExtension.refl state) + | witness :: rest => do + let step ← Theory.Certified.checkDeclarationExtension? fuel state witness + let rest ← Theory.Certified.checkDeclarationExtensions?._unsafe_rec fuel step.result rest + pure (step.trans rest) +RECURSION WORKER Ix.Theory.Certified.replayDeclarations?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + {signature : Theory.Certified.PrimitiveSignature β} → + {store : Theory.Store β} → + (state : Theory.Certified.CheckedInterface signature) → + List (Theory.Certified.DeclarationWitness β) → + Option (Theory.Certified.CheckedExtension signature store state) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel {signature} {store} state x => + match x with + | [] => some (Theory.Certified.CheckedExtension.refl state) + | witness :: rest => + have __do_jp := fun step => do + let rest ← Theory.Certified.replayDeclarations?._unsafe_rec fuel step.result rest + pure (step.trans rest); + if (witness.outputs.all fun ref => (state.entries ref).isSome) = true then do + let step ← some (Theory.Certified.CheckedExtension.refl state) + __do_jp step + else do + let step ← Theory.Certified.checkDeclarationExtension? fuel state witness + __do_jp step +RECURSION WORKER Ix.Theory.Certified.replayNodes?._unsafe_rec +{β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Theory.Certified.PrimitiveSignature β} → + {store : Theory.Store β} → + (state : Theory.Certified.CheckedInterface signature) → + (known : List (Theory.ConstRef β)) → + (nodes : List (Theory.Certified.CheckedNode fuel signature store)) → + Option (Theory.Certified.ReplayResult state known nodes) +IMPLEMENTATION +fun {β} [DecidableEq β] {fuel} {signature} {store} state known x => + match x with + | [] => some { checked := Theory.Certified.CheckedExtension.refl state, order := ⋯, subjects := ⋯, frontiers := ⋯ } + | node :: nodes => + if available : (node.receipt.frontier.refs.all fun x => known.contains x) = true then + if aligned : + (node.receipt.frontier.headers.all fun h => decide (Theory.Certified.HeaderPresent state.entries h)) = + true then + do + let step ← Theory.Certified.replayDeclarations? fuel state node.input.declarations + if present : (node.input.subjects.all fun ref => (step.result.entries ref).isSome) = true then do + let tail ← Theory.Certified.replayNodes?._unsafe_rec step.result (known ++ node.input.subjects) nodes + pure { checked := step.trans tail.checked, order := ⋯, subjects := ⋯, frontiers := ⋯ } + else none + else none + else none +RECURSION WORKER Ix.Theory.Certified.verifyArguments._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Theory.Model.Environment β) → + (Γ : Theory.Model.Context β) → + (domains args : List (Theory.Model.AExpr β)) → + List (Theory.Certified.TypingWitness β) → + Option (Theory.Certified.CheckedClaim (Theory.Certified.ArgumentsFit entries Γ domains args)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel n entries Γ x x_1 x_2 => + match x, x_1, x_2 with + | [], [], [] => some { down := ⋯ } + | A :: domains, a :: args, witness :: witnesses => do + let ha ← Theory.Certified.verifyType fuel n entries Γ a A witness + let hrest ← + Theory.Certified.verifyArguments._unsafe_rec fuel n entries Γ (Theory.Model.Telescope.inst a domains) args + witnesses + pure { down := ⋯ } + | x, x_3, x_4 => none +RECURSION WORKER Ix.Theory.Certified.verifyConversion._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Theory.Model.Environment β) → + (Γ : Theory.Model.Context β) → + (a b : Theory.Model.AExpr β) → + Theory.Certified.ConversionWitness β → + Option (Theory.Certified.CheckedClaim (Theory.Model.ConversionClaim entries Γ a b)) +IMPLEMENTATION +fun {β} [inst : DecidableEq β] fuel n entries Γ a b witness => + match fuel with + | 0 => none + | fuel.succ => + if Theory.Model.AExpr.Scope n (List.length Γ) a ∧ Theory.Model.AExpr.Scope n (List.length Γ) b then + match a, b, witness with + | a, b, Theory.Certified.ConversionWitness.refl => if h : a = b then some { down := ⋯ } else none + | a, b, w.symm => do + let h ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ b a w + pure { down := ⋯ } + | a, b, Theory.Certified.ConversionWitness.trans c w₁ w₂ => do + let h₁ ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ a c w₁ + let h₂ ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ c b w₂ + pure { down := ⋯ } + | f.app a, f'.app a', wf.app wa => do + let hf ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ f f' wf + let ha ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ a a' wa + pure { down := ⋯ } + | Theory.Model.AExpr.proj r i a, Theory.Model.AExpr.proj r' i' b, w.proj => + if hr : r = r' then + if hi : i = i' then do + let h ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ a b w + pure { down := ⋯ } + else none + else none + | Theory.Model.AExpr.lam p D body, Theory.Model.AExpr.lam p' D' body', + Theory.Certified.ConversionWitness.lam lD wD wd wb => + if hp : p = p' then do + let hD ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ D (Theory.Model.AExpr.sort lD) wD + let hd ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ D D' wd + let hb ← + Theory.Certified.verifyConversion._unsafe_rec fuel n entries (Theory.Model.Context.push D Γ) body body' wb + pure { down := ⋯ } + else none + | Theory.Model.AExpr.forallE p D B, Theory.Model.AExpr.forallE p' D' B', + Theory.Certified.ConversionWitness.forallE lD wD wd wb => + if hp : p = p' then do + let hD ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ D (Theory.Model.AExpr.sort lD) wD + let hd ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ D D' wd + let hb ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries (Theory.Model.Context.push D Γ) B B' wb + pure { down := ⋯ } + else none + | (Theory.Model.AExpr.lam p D body).app arg, result, Theory.Certified.ConversionWitness.beta T wl wa => + if hr : result = body.inst arg then do + let hl ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ (Theory.Model.AExpr.lam p D body) T wl + let ha ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ arg D wa + pure { down := ⋯ } + else none + | Theory.Model.AExpr.lam p D body, f, Theory.Certified.ConversionWitness.eta B wf => + if hb : body = (Theory.Model.AExpr.liftN 1 f).app (Theory.Model.AExpr.bvar 0) then do + let hf ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ f (Theory.Model.AExpr.forallE p D B) wf + pure { down := ⋯ } + else none + | a, b, Theory.Certified.ConversionWitness.proofIrrel A wA wa wb => do + let hA ← + Theory.Certified.verifyType._unsafe_rec fuel n entries Γ A (Theory.Model.AExpr.sort Theory.VLevel.zero) wA + let ha ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ a A wa + let hb ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ b A wb + pure { down := ⋯ } + | Theory.Model.AExpr.const r ls, b, Theory.Certified.ConversionWitness.delta => + match h : entries r with + | none => none + | some entry => + match h_1 : entry.body with + | none => none + | some body => + if hn : ls.length = entry.universes then + if hB : b = Theory.Model.AExpr.instL ls body then some { down := ⋯ } else none + else none + | Theory.Model.AExpr.sort l, Theory.Model.AExpr.sort l', Theory.Certified.ConversionWitness.sort => + if h : Theory.Certified.LevelEq.check n l l' = true then some { down := ⋯ } else none + | a, b, Theory.Certified.ConversionWitness.equation r index ls => + match h : entries r with + | none => none + | some entry => + match he : entry.equations[index]? with + | none => none + | some law => + if hn : ls.length = entry.universes then + if hls : ∀ (l : Theory.VLevel), l ∈ ls → Theory.VLevel.WF n l then + if ha : a = Theory.Model.AExpr.instL ls law.lhs then + if hb : b = Theory.Model.AExpr.instL ls law.rhs then some { down := ⋯ } else none + else none + else none + else none + | Theory.Model.AExpr.natLit value, result, Theory.Certified.ConversionWitness.natLiteral r index => + match h : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (Theory.Model.ConstantFact.natural zero succ) => + if hn : entry.universes = 0 then + match value with + | 0 => if he : result = Theory.Model.AExpr.const zero [] then some { down := ⋯ } else none + | value.succ => + if he : result = (Theory.Model.AExpr.const succ []).app (Theory.Model.AExpr.natLit value) then + some { down := ⋯ } + else none + else none + | x => none + | x, x_1, x_2 => none + else none +RECURSION WORKER Ix.Theory.Certified.verifyPropTelescope._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Theory.Model.Environment β) → + (atLevel : Theory.VLevel) → + (Γ : Theory.Model.Context β) → + (domains : List (Theory.Model.AExpr β)) → + List (Theory.Certified.DomainWitness β) → + Option (Theory.Certified.CheckedClaim (Theory.Certified.TelescopeProp entries Γ domains atLevel)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel n entries atLevel x x_1 x_2 => + match x, x_1, x_2 with + | Γ, [], [] => some { down := ⋯ } + | Γ, A :: rest, witness :: witnesses => + if hl : Theory.Certified.checkZeroImplies atLevel witness.level = true then do + let hA ← Theory.Certified.verifyType fuel n entries Γ A (Theory.Model.AExpr.sort witness.level) witness.typing + let htail ← + Theory.Certified.verifyPropTelescope._unsafe_rec fuel n entries atLevel (Theory.Model.Context.push A Γ) rest + witnesses + pure { down := ⋯ } + else none + | x, x_3, x_4 => none +RECURSION WORKER Ix.Theory.Certified.verifyTelescope._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Theory.Model.Environment β) → + (bound : Option Theory.VLevel) → + (Γ : Theory.Model.Context β) → + (domains : List (Theory.Model.AExpr β)) → + List (Theory.Certified.DomainWitness β) → + Option + (Theory.Certified.CheckedClaim + (Theory.Model.Telescope.Formed entries Γ domains ∧ + Theory.Certified.TelescopeBound entries Γ domains bound)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel n entries bound x x_1 x_2 => + match x, x_1, x_2 with + | Γ, [], [] => some { down := ⋯ } + | Γ, A :: rest, witness :: witnesses => + if hl : Theory.Certified.checkDomainBound n bound witness.level = true then do + let hA ← Theory.Certified.verifyType fuel n entries Γ A (Theory.Model.AExpr.sort witness.level) witness.typing + let hrest ← + Theory.Certified.verifyTelescope._unsafe_rec fuel n entries bound (Theory.Model.Context.push A Γ) rest witnesses + pure { down := ⋯ } + else none + | x, x_3, x_4 => none +RECURSION WORKER Ix.Theory.Certified.verifyType._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Theory.Model.Environment β) → + (Γ : Theory.Model.Context β) → + (e A : Theory.Model.AExpr β) → + Theory.Certified.TypingWitness β → + Option (Theory.Certified.CheckedClaim (Theory.Model.TypingClaim entries Γ e A)) +IMPLEMENTATION +fun {β} [inst : DecidableEq β] fuel n entries Γ e A witness => + match fuel with + | 0 => none + | fuel.succ => + if Theory.Model.AExpr.Scope n (List.length Γ) e ∧ Theory.Model.AExpr.Scope n (List.length Γ) A then + match e, witness with + | Theory.Model.AExpr.sort l, Theory.Certified.TypingWitness.sort => + if h : A = Theory.Model.AExpr.sort l.succ then some { down := ⋯ } else none + | Theory.Model.AExpr.bvar i, Theory.Certified.TypingWitness.bvar => + match h : Γ[i]? with + | none => none + | some B => if hA : A = B then some { down := ⋯ } else none + | Theory.Model.AExpr.const r ls, Theory.Certified.TypingWitness.const => + match h : entries r with + | none => none + | some entry => + if hn : ls.length = entry.universes then + if hA : A = Theory.Model.AExpr.instL ls entry.type then some { down := ⋯ } else none + else none + | f.app a, Theory.Certified.TypingWitness.app p D B wf wa => + if hA : A = B.inst a then do + let hf ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ f (Theory.Model.AExpr.forallE p D B) wf + let ha ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ a D wa + pure { down := ⋯ } + else none + | Theory.Model.AExpr.lam p D body, Theory.Certified.TypingWitness.lam lD lB B wD wB wb => + if hp : p = Theory.Certified.zeroCondition lB then + if hA : A = Theory.Model.AExpr.forallE p D B then do + let hD ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ D (Theory.Model.AExpr.sort lD) wD + let hB ← + Theory.Certified.verifyType._unsafe_rec fuel n entries (Theory.Model.Context.push D Γ) B + (Theory.Model.AExpr.sort lB) wB + let hb ← Theory.Certified.verifyType._unsafe_rec fuel n entries (Theory.Model.Context.push D Γ) body B wb + pure { down := ⋯ } + else none + else none + | Theory.Model.AExpr.forallE p D B, Theory.Certified.TypingWitness.forallE lD lB wD wB => + if hp : p = Theory.Certified.zeroCondition lB then + if hA : A = Theory.Model.AExpr.sort (lD.imax lB) then do + let hD ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ D (Theory.Model.AExpr.sort lD) wD + let hB ← + Theory.Certified.verifyType._unsafe_rec fuel n entries (Theory.Model.Context.push D Γ) B + (Theory.Model.AExpr.sort lB) wB + pure { down := ⋯ } + else none + else none + | e, Theory.Certified.TypingWitness.conv B lA we wA wc => do + let he ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ e B we + let hA ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ A (Theory.Model.AExpr.sort lA) wA + let hc ← Theory.Certified.verifyConversion._unsafe_rec fuel n entries Γ B A wc + pure { down := ⋯ } + | e, Theory.Certified.TypingWitness.fact r index ls => + match h : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (Theory.Model.ConstantFact.typed value type) => + if hn : ls.length = entry.universes then + if ∀ (l : Theory.VLevel), l ∈ ls → Theory.VLevel.WF n l then + if he : e = Theory.Model.AExpr.instL ls value then + if hA : A = Theory.Model.AExpr.instL ls type then some { down := ⋯ } else none + else none + else none + else none + | x => none + | Theory.Model.AExpr.natLit value, Theory.Certified.TypingWitness.natLit r index => + match h : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (Theory.Model.ConstantFact.natural zero succ) => + if hn : entry.universes = 0 then if hA : A = Theory.Model.AExpr.const r [] then some { down := ⋯ } else none + else none + | x => none + | e, Theory.Certified.TypingWitness.betaResult p D body arg B wl wa => + if he : e = body.inst arg then + if hA : A = B.inst arg then do + let hl ← + Theory.Certified.verifyType._unsafe_rec fuel n entries Γ (Theory.Model.AExpr.lam p D body) + (Theory.Model.AExpr.forallE p D B) wl + let ha ← Theory.Certified.verifyType._unsafe_rec fuel n entries Γ arg D wa + pure { down := ⋯ } + else none + else none + | x, x_1 => none + else none +RECURSION WORKER Ix.Theory.Certified.zeroCondition._unsafe_rec +Theory.VLevel → Theory.Certified.PropWhen +IMPLEMENTATION +fun x => + match x with + | Theory.VLevel.zero => Theory.Certified.PropWhen.always + | a.succ => Theory.Certified.PropWhen.never + | a.max b => (Theory.Certified.zeroCondition._unsafe_rec a).inter (Theory.Certified.zeroCondition._unsafe_rec b) + | a.imax b => Theory.Certified.zeroCondition._unsafe_rec b + | Theory.VLevel.param i => Theory.Certified.PropWhen.param i +RECURSION WORKER Ix.Theory.Model.WellDenoted._unsafe_rec +{β : Type u} → + {V : Type v} → + [Theory.Model.SetTheory V] → Theory.Model.Assignment β V → List Nat → (Nat → V) → Theory.Model.AExpr β → Prop +IMPLEMENTATION +fun {β} {V} [Theory.Model.SetTheory V] constants levels env x => + match x with + | Theory.Model.AExpr.bvar index => True + | Theory.Model.AExpr.sort level => True + | Theory.Model.AExpr.const ref levels => True + | f.app a => + Theory.Model.WellDenoted._unsafe_rec constants levels env f ∧ + Theory.Model.WellDenoted._unsafe_rec constants levels env a ∧ + ∃ v A B, + Theory.Model.SetTheory.Mem (Theory.Model.interp constants levels env f) (Theory.Model.SetModel.piR v A B) ∧ + Theory.Model.SetTheory.Mem (Theory.Model.interp constants levels env a) A ∧ + ∀ (x : V), + Theory.Model.SetTheory.Mem x A → Theory.Model.SetTheory.Mem (B x) (Theory.Model.SetTheory.univ v) + | Theory.Model.AExpr.lam p A b => + Theory.Model.WellDenoted._unsafe_rec constants levels env A ∧ + (∀ (x : V), + Theory.Model.SetTheory.Mem x (Theory.Model.interp constants levels env A) → + Theory.Model.WellDenoted._unsafe_rec constants levels (Theory.Model.Valuation.cons x env) b) ∧ + ∃ v B, + (Theory.Model.regime p levels = 0 ↔ v = 0) ∧ + ∀ (x : V), + Theory.Model.SetTheory.Mem x (Theory.Model.interp constants levels env A) → + Theory.Model.SetTheory.Mem (Theory.Model.interp constants levels (Theory.Model.Valuation.cons x env) b) + (B x) ∧ + Theory.Model.SetTheory.Mem (B x) (Theory.Model.SetTheory.univ v) + | Theory.Model.AExpr.forallE p A B => + Theory.Model.WellDenoted._unsafe_rec constants levels env A ∧ + (∀ (x : V), + Theory.Model.SetTheory.Mem x (Theory.Model.interp constants levels env A) → + Theory.Model.WellDenoted._unsafe_rec constants levels (Theory.Model.Valuation.cons x env) B) ∧ + ∃ v, + (Theory.Model.regime p levels = 0 ↔ v = 0) ∧ + ∀ (x : V), + Theory.Model.SetTheory.Mem x (Theory.Model.interp constants levels env A) → + Theory.Model.SetTheory.Mem (Theory.Model.interp constants levels (Theory.Model.Valuation.cons x env) B) + (Theory.Model.SetTheory.univ v) + | Theory.Model.AExpr.proj ref field e => Theory.Model.WellDenoted._unsafe_rec constants levels env e + | Theory.Model.AExpr.natLit value => True +RECURSION WORKER Ix.Theory.Model.readAnnotations?._unsafe_rec +{β : Type u} → + (n k : Nat) → (source : Theory.VExpr β) → Theory.Model.AnnotationTree → Option (Theory.Model.Reading n k source) +IMPLEMENTATION +fun {β} n k source tree => + match source, tree with + | Theory.VExpr.bvar i, Theory.Model.AnnotationTree.leaf => + if h : i < k then some ⟨Theory.Model.AExpr.bvar i, ⋯⟩ else none + | Theory.VExpr.sort l, Theory.Model.AnnotationTree.leaf => + if h : Theory.VLevel.WF n l then some ⟨Theory.Model.AExpr.sort l, ⋯⟩ else none + | Theory.VExpr.const r ls, Theory.Model.AnnotationTree.leaf => + if h : ∀ (l : Theory.VLevel), l ∈ ls → Theory.VLevel.WF n l then some ⟨Theory.Model.AExpr.const r ls, ⋯⟩ else none + | f.app a, tf.app ta => do + let f' ← Theory.Model.readAnnotations?._unsafe_rec n k f tf + let a' ← Theory.Model.readAnnotations?._unsafe_rec n k a ta + pure ⟨f'.val.app a'.val, ⋯⟩ + | a.lam b, Theory.Model.AnnotationTree.lam raw ta tb => + match Ix.Theory.Model.readCondition?✝ n raw with + | none => none + | some p => do + let a' ← Theory.Model.readAnnotations?._unsafe_rec n k a ta + let b' ← Theory.Model.readAnnotations?._unsafe_rec n (k + 1) b tb + pure ⟨Theory.Model.AExpr.lam p.val a'.val b'.val, ⋯⟩ + | a.forallE b, Theory.Model.AnnotationTree.forallE raw ta tb => + match Ix.Theory.Model.readCondition?✝ n raw with + | none => none + | some p => do + let a' ← Theory.Model.readAnnotations?._unsafe_rec n k a ta + let b' ← Theory.Model.readAnnotations?._unsafe_rec n (k + 1) b tb + pure ⟨Theory.Model.AExpr.forallE p.val a'.val b'.val, ⋯⟩ + | Theory.VExpr.proj r i e, te.proj => do + let e' ← Theory.Model.readAnnotations?._unsafe_rec n k e te + pure ⟨Theory.Model.AExpr.proj r i e'.val, ⋯⟩ + | Theory.VExpr.natLit v, Theory.Model.AnnotationTree.leaf => some ⟨Theory.Model.AExpr.natLit v, ⋯⟩ + | x, x_1 => none +RECURSION WORKER Ix.Theory.VExpr.appArgs._unsafe_rec +{β : Type u_1} → Theory.VExpr β → List (Theory.VExpr β) → List (Theory.VExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | f.app a, acc => Theory.VExpr.appArgs._unsafe_rec f (a :: acc) + | x, acc => acc +RECURSION WORKER Ix.Theory.VExpr.appHead._unsafe_rec +{β : Type u_1} → Theory.VExpr β → Theory.VExpr β +IMPLEMENTATION +fun {β} x => + match x with + | f.app arg => Theory.VExpr.appHead._unsafe_rec f + | e => e +RECURSION WORKER Ix.Theory.VExpr.appN._unsafe_rec +{β : Type u_1} → Theory.VExpr β → List (Theory.VExpr β) → Theory.VExpr β +IMPLEMENTATION +fun {β} f x => + match x with + | [] => f + | a :: as => Theory.VExpr.appN._unsafe_rec (f.app a) as +RECURSION WORKER Ix.Theory.VExpr.bvarRevRange._unsafe_rec +{β : Type u_1} → Nat → Nat → List (Theory.VExpr β) +IMPLEMENTATION +fun {β} off x => + match x with + | 0 => [] + | m.succ => Theory.VExpr.bvar (off + m) :: Theory.VExpr.bvarRevRange._unsafe_rec off m +RECURSION WORKER Ix.Theory.VExpr.forallN._unsafe_rec +{β : Type u_1} → List (Theory.VExpr β) → Theory.VExpr β → Theory.VExpr β +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | [], e => e + | A :: As, e => A.forallE (Theory.VExpr.forallN._unsafe_rec As e) +RECURSION WORKER Ix.Theory.VExpr.inst._unsafe_rec +{β : Type u_1} → Theory.VExpr β → Theory.VExpr β → optParam Nat 0 → Theory.VExpr β +IMPLEMENTATION +fun {β} x x_1 x_2 => + match x, x_1, x_2 with + | Theory.VExpr.bvar i, e, k => Theory.VExpr.instVar i e k + | Theory.VExpr.sort u, x, x_3 => Theory.VExpr.sort u + | Theory.VExpr.const r us, x, x_3 => Theory.VExpr.const r us + | fn.app arg, e, k => (Theory.VExpr.inst._unsafe_rec fn e k).app (Theory.VExpr.inst._unsafe_rec arg e k) + | ty.lam body, e, k => (Theory.VExpr.inst._unsafe_rec ty e k).lam (Theory.VExpr.inst._unsafe_rec body e (k + 1)) + | ty.forallE body, e, k => + (Theory.VExpr.inst._unsafe_rec ty e k).forallE (Theory.VExpr.inst._unsafe_rec body e (k + 1)) + | Theory.VExpr.proj r i p, e, k => Theory.VExpr.proj r i (Theory.VExpr.inst._unsafe_rec p e k) + | Theory.VExpr.natLit value, x, x_3 => Theory.VExpr.natLit value +RECURSION WORKER Ix.Theory.VExpr.instL._unsafe_rec +List Theory.VLevel → {β : Type u_1} → Theory.VExpr β → Theory.VExpr β +IMPLEMENTATION +fun levels {β} x => + match x with + | Theory.VExpr.bvar i => Theory.VExpr.bvar i + | Theory.VExpr.sort u => Theory.VExpr.sort (Theory.VLevel.inst levels u) + | Theory.VExpr.const r us => Theory.VExpr.const r (List.map (Theory.VLevel.inst levels) us) + | fn.app arg => (Theory.VExpr.instL._unsafe_rec levels fn).app (Theory.VExpr.instL._unsafe_rec levels arg) + | ty.lam body => (Theory.VExpr.instL._unsafe_rec levels ty).lam (Theory.VExpr.instL._unsafe_rec levels body) + | ty.forallE body => (Theory.VExpr.instL._unsafe_rec levels ty).forallE (Theory.VExpr.instL._unsafe_rec levels body) + | Theory.VExpr.proj r i e => Theory.VExpr.proj r i (Theory.VExpr.instL._unsafe_rec levels e) + | Theory.VExpr.natLit value => Theory.VExpr.natLit value +RECURSION WORKER Ix.Theory.VExpr.lamN._unsafe_rec +{β : Type u_1} → List (Theory.VExpr β) → Theory.VExpr β → Theory.VExpr β +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | [], e => e + | A :: As, e => A.lam (Theory.VExpr.lamN._unsafe_rec As e) +RECURSION WORKER Ix.Theory.VExpr.liftN._unsafe_rec +Nat → {β : Type u_1} → Theory.VExpr β → optParam Nat 0 → Theory.VExpr β +IMPLEMENTATION +fun n {β} x x_1 => + match x, x_1 with + | Theory.VExpr.bvar i, k => Theory.VExpr.bvar (Theory.liftVar n i k) + | Theory.VExpr.sort u, x => Theory.VExpr.sort u + | Theory.VExpr.const r us, x => Theory.VExpr.const r us + | fn.app arg, k => (Theory.VExpr.liftN._unsafe_rec n fn k).app (Theory.VExpr.liftN._unsafe_rec n arg k) + | ty.lam body, k => (Theory.VExpr.liftN._unsafe_rec n ty k).lam (Theory.VExpr.liftN._unsafe_rec n body (k + 1)) + | ty.forallE body, k => + (Theory.VExpr.liftN._unsafe_rec n ty k).forallE (Theory.VExpr.liftN._unsafe_rec n body (k + 1)) + | Theory.VExpr.proj r i e, k => Theory.VExpr.proj r i (Theory.VExpr.liftN._unsafe_rec n e k) + | Theory.VExpr.natLit value, x => Theory.VExpr.natLit value +RECURSION WORKER Ix.Theory.VExpr.mapRefs._unsafe_rec +{β : Type u} → {γ : Type v} → (Theory.ConstRef β → Theory.ConstRef γ) → Theory.VExpr β → Theory.VExpr γ +IMPLEMENTATION +fun {β} {γ} mapping x => + match x with + | Theory.VExpr.bvar i => Theory.VExpr.bvar i + | Theory.VExpr.sort level => Theory.VExpr.sort level + | Theory.VExpr.const ref levels => Theory.VExpr.const (mapping ref) levels + | f.app a => (Theory.VExpr.mapRefs._unsafe_rec mapping f).app (Theory.VExpr.mapRefs._unsafe_rec mapping a) + | type.lam body => (Theory.VExpr.mapRefs._unsafe_rec mapping type).lam (Theory.VExpr.mapRefs._unsafe_rec mapping body) + | type.forallE body => + (Theory.VExpr.mapRefs._unsafe_rec mapping type).forallE (Theory.VExpr.mapRefs._unsafe_rec mapping body) + | Theory.VExpr.proj ref index major => + Theory.VExpr.proj (mapping ref) index (Theory.VExpr.mapRefs._unsafe_rec mapping major) + | Theory.VExpr.natLit n => Theory.VExpr.natLit n +RECURSION WORKER Ix.Theory.VExpr.refs._unsafe_rec +{β : Type u_1} → Theory.VExpr β → List (Theory.ConstRef β) +IMPLEMENTATION +fun {β} x => + match x with + | Theory.VExpr.bvar deBruijnIndex => [] + | Theory.VExpr.sort u => [] + | Theory.VExpr.natLit value => [] + | Theory.VExpr.const r levels => [r] + | e₁.app e₂ => Theory.VExpr.refs._unsafe_rec e₁ ++ Theory.VExpr.refs._unsafe_rec e₂ + | e₁.lam e₂ => Theory.VExpr.refs._unsafe_rec e₁ ++ Theory.VExpr.refs._unsafe_rec e₂ + | e₁.forallE e₂ => Theory.VExpr.refs._unsafe_rec e₁ ++ Theory.VExpr.refs._unsafe_rec e₂ + | Theory.VExpr.proj r index e => r :: Theory.VExpr.refs._unsafe_rec e +RECURSION WORKER Ix.Theory.VExpr.unliftN._unsafe_rec +{β : Type u_1} → Theory.VExpr β → Nat → Nat → Theory.VExpr β +IMPLEMENTATION +fun {β} e n k => + match n with + | 0 => e + | n.succ => Theory.VExpr.unliftN._unsafe_rec (e.inst default k) n k +RECURSION WORKER Ix.Theory.VLevel.WF._unsafe_rec +Nat → Theory.VLevel → Prop +IMPLEMENTATION +fun n x => + match x with + | Theory.VLevel.zero => True + | l.succ => Theory.VLevel.WF._unsafe_rec n l + | l₁.max l₂ => Theory.VLevel.WF._unsafe_rec n l₁ ∧ Theory.VLevel.WF._unsafe_rec n l₂ + | l₁.imax l₂ => Theory.VLevel.WF._unsafe_rec n l₁ ∧ Theory.VLevel.WF._unsafe_rec n l₂ + | Theory.VLevel.param i => i < n +RECURSION WORKER Ix.Theory.VLevel.decidable_WF._unsafe_rec +{n : Nat} → {l : Theory.VLevel} → Decidable (Theory.VLevel.WF n l) +IMPLEMENTATION +fun {n} x => + match x with + | Theory.VLevel.zero => instDecidableTrue + | l.succ => Theory.VLevel.decidable_WF._unsafe_rec + | a.max a_1 => instDecidableAnd + | a.imax a_1 => instDecidableAnd + | Theory.VLevel.param a => a.decLt n +RECURSION WORKER Ix.Theory.VLevel.eval._unsafe_rec +List Nat → Theory.VLevel → Nat +IMPLEMENTATION +fun ls x => + match x with + | Theory.VLevel.zero => 0 + | l.succ => Theory.VLevel.eval._unsafe_rec ls l + 1 + | l₁.max l₂ => (Theory.VLevel.eval._unsafe_rec ls l₁).max (Theory.VLevel.eval._unsafe_rec ls l₂) + | l₁.imax l₂ => Theory.VLevel.natIMax (Theory.VLevel.eval._unsafe_rec ls l₁) (Theory.VLevel.eval._unsafe_rec ls l₂) + | Theory.VLevel.param i => ls.getD i 0 +RECURSION WORKER Ix.Theory.VLevel.inst._unsafe_rec +List Theory.VLevel → Theory.VLevel → Theory.VLevel +IMPLEMENTATION +fun ls x => + match x with + | Theory.VLevel.zero => Theory.VLevel.zero + | l.succ => (Theory.VLevel.inst._unsafe_rec ls l).succ + | l₁.max l₂ => (Theory.VLevel.inst._unsafe_rec ls l₁).max (Theory.VLevel.inst._unsafe_rec ls l₂) + | l₁.imax l₂ => (Theory.VLevel.inst._unsafe_rec ls l₁).imax (Theory.VLevel.inst._unsafe_rec ls l₂) + | Theory.VLevel.param i => ls.getD i Theory.VLevel.zero +RECURSION WORKER Ix.Theory.instDecidableEqVExpr.decEq._unsafe_rec +{β : Type u_1} → [DecidableEq β] → (x x_1 : Theory.VExpr β) → Decidable (x = x_1) +IMPLEMENTATION +fun {β} [inst : DecidableEq β] x x_1 => + match x, x_1 with + | Theory.VExpr.bvar a, Theory.VExpr.bvar b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | Theory.VExpr.bvar deBruijnIndex, Theory.VExpr.sort u => isFalse ⋯ + | Theory.VExpr.bvar deBruijnIndex, Theory.VExpr.const ref levels => isFalse ⋯ + | Theory.VExpr.bvar deBruijnIndex, fn.app arg => isFalse ⋯ + | Theory.VExpr.bvar deBruijnIndex, binderType.lam body => isFalse ⋯ + | Theory.VExpr.bvar deBruijnIndex, binderType.forallE body => isFalse ⋯ + | Theory.VExpr.bvar deBruijnIndex, Theory.VExpr.proj ref index expr => isFalse ⋯ + | Theory.VExpr.bvar deBruijnIndex, Theory.VExpr.natLit value => isFalse ⋯ + | Theory.VExpr.sort u, Theory.VExpr.bvar deBruijnIndex => isFalse ⋯ + | Theory.VExpr.sort a, Theory.VExpr.sort b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | Theory.VExpr.sort u, Theory.VExpr.const ref levels => isFalse ⋯ + | Theory.VExpr.sort u, fn.app arg => isFalse ⋯ + | Theory.VExpr.sort u, binderType.lam body => isFalse ⋯ + | Theory.VExpr.sort u, binderType.forallE body => isFalse ⋯ + | Theory.VExpr.sort u, Theory.VExpr.proj ref index expr => isFalse ⋯ + | Theory.VExpr.sort u, Theory.VExpr.natLit value => isFalse ⋯ + | Theory.VExpr.const ref levels, Theory.VExpr.bvar deBruijnIndex => isFalse ⋯ + | Theory.VExpr.const ref levels, Theory.VExpr.sort u => isFalse ⋯ + | Theory.VExpr.const a a_1, Theory.VExpr.const b b_1 => + if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯ + | Theory.VExpr.const ref levels, fn.app arg => isFalse ⋯ + | Theory.VExpr.const ref levels, binderType.lam body => isFalse ⋯ + | Theory.VExpr.const ref levels, binderType.forallE body => isFalse ⋯ + | Theory.VExpr.const ref levels, Theory.VExpr.proj ref_1 index expr => isFalse ⋯ + | Theory.VExpr.const ref levels, Theory.VExpr.natLit value => isFalse ⋯ + | fn.app arg, Theory.VExpr.bvar deBruijnIndex => isFalse ⋯ + | fn.app arg, Theory.VExpr.sort u => isFalse ⋯ + | fn.app arg, Theory.VExpr.const ref levels => isFalse ⋯ + | a.app a_1, b.app b_1 => + let inst_1 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a a; + let inst_3 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | fn.app arg, binderType.lam body => isFalse ⋯ + | fn.app arg, binderType.forallE body => isFalse ⋯ + | fn.app arg, Theory.VExpr.proj ref index expr => isFalse ⋯ + | fn.app arg, Theory.VExpr.natLit value => isFalse ⋯ + | binderType.lam body, Theory.VExpr.bvar deBruijnIndex => isFalse ⋯ + | binderType.lam body, Theory.VExpr.sort u => isFalse ⋯ + | binderType.lam body, Theory.VExpr.const ref levels => isFalse ⋯ + | binderType.lam body, fn.app arg => isFalse ⋯ + | a.lam a_1, b.lam b_1 => + let inst_1 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a a; + let inst_3 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | binderType.lam body, binderType_1.forallE body_1 => isFalse ⋯ + | binderType.lam body, Theory.VExpr.proj ref index expr => isFalse ⋯ + | binderType.lam body, Theory.VExpr.natLit value => isFalse ⋯ + | binderType.forallE body, Theory.VExpr.bvar deBruijnIndex => isFalse ⋯ + | binderType.forallE body, Theory.VExpr.sort u => isFalse ⋯ + | binderType.forallE body, Theory.VExpr.const ref levels => isFalse ⋯ + | binderType.forallE body, fn.app arg => isFalse ⋯ + | binderType.forallE body, binderType_1.lam body_1 => isFalse ⋯ + | a.forallE a_1, b.forallE b_1 => + let inst_1 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a a; + let inst_3 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | binderType.forallE body, Theory.VExpr.proj ref index expr => isFalse ⋯ + | binderType.forallE body, Theory.VExpr.natLit value => isFalse ⋯ + | Theory.VExpr.proj ref index expr, Theory.VExpr.bvar deBruijnIndex => isFalse ⋯ + | Theory.VExpr.proj ref index expr, Theory.VExpr.sort u => isFalse ⋯ + | Theory.VExpr.proj ref index expr, Theory.VExpr.const ref_1 levels => isFalse ⋯ + | Theory.VExpr.proj ref index expr, fn.app arg => isFalse ⋯ + | Theory.VExpr.proj ref index expr, binderType.lam body => isFalse ⋯ + | Theory.VExpr.proj ref index expr, binderType.forallE body => isFalse ⋯ + | Theory.VExpr.proj a a_1 a_2, Theory.VExpr.proj b b_1 b_2 => + if h : a = b then + h ▸ + if h : a_1 = b_1 then + h ▸ + let inst_1 := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Theory.instDecidableEqVExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Theory.VExpr.proj ref index expr, Theory.VExpr.natLit value => isFalse ⋯ + | Theory.VExpr.natLit value, Theory.VExpr.bvar deBruijnIndex => isFalse ⋯ + | Theory.VExpr.natLit value, Theory.VExpr.sort u => isFalse ⋯ + | Theory.VExpr.natLit value, Theory.VExpr.const ref levels => isFalse ⋯ + | Theory.VExpr.natLit value, fn.app arg => isFalse ⋯ + | Theory.VExpr.natLit value, binderType.lam body => isFalse ⋯ + | Theory.VExpr.natLit value, binderType.forallE body => isFalse ⋯ + | Theory.VExpr.natLit value, Theory.VExpr.proj ref index expr => isFalse ⋯ + | Theory.VExpr.natLit a, Theory.VExpr.natLit b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ +RECURSION WORKER Ix.Theory.instDecidableEqVLevel.decEq._unsafe_rec +(x x_1 : Theory.VLevel) → Decidable (x = x_1) +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | Theory.VLevel.zero, Theory.VLevel.zero => isTrue ⋯ + | Theory.VLevel.zero, a.succ => isFalse ⋯ + | Theory.VLevel.zero, a.max a_1 => isFalse ⋯ + | Theory.VLevel.zero, a.imax a_1 => isFalse ⋯ + | Theory.VLevel.zero, Theory.VLevel.param a => isFalse ⋯ + | a.succ, Theory.VLevel.zero => isFalse ⋯ + | a.succ, b.succ => + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a a; + isTrue ⋯ + else isFalse ⋯ + | a.succ, a_1.max a_2 => isFalse ⋯ + | a.succ, a_1.imax a_2 => isFalse ⋯ + | a.succ, Theory.VLevel.param a_1 => isFalse ⋯ + | a.max a_1, Theory.VLevel.zero => isFalse ⋯ + | a.max a_1, a_2.succ => isFalse ⋯ + | a.max a_1, b.max b_1 => + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a a; + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | a.max a_1, a_2.imax a_3 => isFalse ⋯ + | a.max a_1, Theory.VLevel.param a_2 => isFalse ⋯ + | a.imax a_1, Theory.VLevel.zero => isFalse ⋯ + | a.imax a_1, a_2.succ => isFalse ⋯ + | a.imax a_1, a_2.max a_3 => isFalse ⋯ + | a.imax a_1, b.imax b_1 => + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a a; + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Theory.instDecidableEqVLevel.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | a.imax a_1, Theory.VLevel.param a_2 => isFalse ⋯ + | Theory.VLevel.param a, Theory.VLevel.zero => isFalse ⋯ + | Theory.VLevel.param a, a_1.succ => isFalse ⋯ + | Theory.VLevel.param a, a_1.max a_2 => isFalse ⋯ + | Theory.VLevel.param a, a_1.imax a_2 => isFalse ⋯ + | Theory.VLevel.param a, Theory.VLevel.param b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ +RECURSION WORKER Ix.Theory.Certificate.Ordinary.arguments?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → + List (Theory.Model.AExpr β) → + List (Theory.Model.AExpr β) → Option (List (Theory.Certified.TypingWitness β)) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries Γ x x_1 => + match x, x_1 with + | [], [] => some [] + | A :: domains, a :: args => do + let typed ← Theory.Certificate.inferAnnotated? fuel n entries Γ a + let witness ← Theory.Certificate.castWith? fuel n entries Γ typed A + let tail ← + Theory.Certificate.Ordinary.arguments?._unsafe_rec fuel n entries Γ (Theory.Model.Telescope.inst a domains) args + pure (witness :: tail) + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certificate.Ordinary.domains?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → List (Theory.Model.AExpr β) → Option (List (Theory.Certified.DomainWitness β)) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries x x_1 => + match x, x_1 with + | x, [] => some [] + | Γ, A :: rest => do + let typed ← Theory.Certificate.inferAnnotated? fuel n entries Γ A + match typed.type with + | Theory.Model.AExpr.sort level => do + let tail ← Theory.Certificate.Ordinary.domains?._unsafe_rec fuel n entries (Theory.Model.Context.push A Γ) rest + pure ({ level := level, typing := typed.witness } :: tail) + | x => none +RECURSION WORKER Ix.Theory.Certificate.Ordinary.sourceDomains?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Nat → + Theory.Model.Environment β → + Theory.Model.Context β → List (Theory.VExpr β) → Option (List (Theory.Model.AExpr β)) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel n entries x x_1 => + match x, x_1 with + | x, [] => some [] + | Γ, A :: rest => do + let typed ← Theory.Certificate.inferSource? fuel n entries Γ A + match typed.type with + | Theory.Model.AExpr.sort level => do + let tail ← + Theory.Certificate.Ordinary.sourceDomains?._unsafe_rec fuel n entries + (Theory.Model.Context.push typed.expression Γ) rest + pure (typed.expression :: tail) + | x => none +RECURSION WORKER Ix.Theory.Certificate.Ordinary.telescope._unsafe_rec +{β : Type u} → Theory.VExpr β → List (Theory.VExpr β) × Theory.VExpr β +IMPLEMENTATION +fun {β} x => + match x with + | A.forallE B => + match Theory.Certificate.Ordinary.telescope._unsafe_rec B with + | (tail, result) => (A :: tail, result) + | e => ([], e) +RECURSION WORKER Ix.Theory.Certificate.Quotient.typeWitnesses?._unsafe_rec +{β : Type u} → + [DecidableEq β] → + [Theory.Certificate.Hints β] → + Nat → + Theory.Model.Environment β → + List (Theory.Certified.Signature.Header β) → Option (List (Theory.Certified.Signature.TypeWitness β)) +IMPLEMENTATION +fun {β} [DecidableEq β] [Theory.Certificate.Hints β] fuel entries x => + match x with + | [] => some [] + | header :: headers => do + let inferred ← Theory.Certificate.inferAnnotated? fuel header.universes entries [] header.type + match inferred.type with + | Theory.Model.AExpr.sort level => do + let rest ← + Theory.Certificate.Quotient.typeWitnesses?._unsafe_rec fuel (entries.insert header.ref header.entry) headers + pure ({ level := level, typing := inferred.witness } :: rest) + | x => none +RECURSION WORKER Ix.Theory.Certified.IndexSet.insert._unsafe_rec +Nat → List Nat → List Nat +IMPLEMENTATION +fun x x_1 => + match x_1 with + | [] => [x] + | y :: ys => + if x < y then x :: y :: ys else if x = y then y :: ys else y :: Theory.Certified.IndexSet.insert._unsafe_rec x ys +RECURSION WORKER Ix.Theory.Certified.IndexSet.normalize._unsafe_rec +List Nat → List Nat +IMPLEMENTATION +fun x => + match x with + | [] => [] + | x :: xs => Theory.Certified.IndexSet.insert x (Theory.Certified.IndexSet.normalize._unsafe_rec xs) +RECURSION WORKER Ix.Theory.Certified.LevelEq.leq._unsafe_rec +Theory.VLevel → Theory.VLevel → Bool +IMPLEMENTATION +fun a b => + if a = b then true + else + match a, b with + | Theory.VLevel.zero, x => true + | a.max b, c => Theory.Certified.LevelEq.leq._unsafe_rec a c && Theory.Certified.LevelEq.leq._unsafe_rec b c + | a, b.max c => Theory.Certified.LevelEq.leq._unsafe_rec a b || Theory.Certified.LevelEq.leq._unsafe_rec a c + | a.succ, b.succ => Theory.Certified.LevelEq.leq._unsafe_rec a b + | a, b.succ => Theory.Certified.LevelEq.leq._unsafe_rec a b + | a.imax b, c => Theory.Certified.LevelEq.leq._unsafe_rec a c && Theory.Certified.LevelEq.leq._unsafe_rec b c + | x, x_1 => false +RECURSION WORKER Ix.Theory.Certified.LevelEq.normalize._unsafe_rec +Theory.VLevel → Theory.VLevel +IMPLEMENTATION +fun x => + match x with + | Theory.VLevel.zero => Theory.VLevel.zero + | Theory.VLevel.param i => Theory.VLevel.param i + | a.succ => (Theory.Certified.LevelEq.normalize._unsafe_rec a).succ + | a.max b => + Theory.Certified.LevelEq.max (Theory.Certified.LevelEq.normalize._unsafe_rec a) + (Theory.Certified.LevelEq.normalize._unsafe_rec b) + | a.imax b => + Theory.Certified.LevelEq.imax (Theory.Certified.LevelEq.normalize._unsafe_rec a) + (Theory.Certified.LevelEq.normalize._unsafe_rec b) +RECURSION WORKER Ix.Theory.Certified.Modeled.applyPi?._unsafe_rec +{β : Type u} → Theory.VExpr β → List (Theory.VExpr β) → Option (Theory.VExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | type, [] => some type + | binderType.forallE body, argument :: rest => Theory.Certified.Modeled.applyPi?._unsafe_rec (body.inst argument) rest + | x, head :: tail => none +RECURSION WORKER Ix.Theory.Certified.Modeled.betaHead?._unsafe_rec +{β : Type u} → Nat → Theory.VExpr β → Option (Theory.VExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | 0, x => none + | fuel.succ, function.app argument => do + let function ← Theory.Certified.Modeled.betaHead?._unsafe_rec fuel function + match function with + | binderType.lam body => Theory.Certified.Modeled.betaHead?._unsafe_rec fuel (body.inst argument) + | x => some (function.app argument) + | n.succ, expression => some expression +RECURSION WORKER Ix.Theory.Certified.Modeled.checkEach?._unsafe_rec +{β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (companions pending : List (Theory.Certified.Modeled.Companion β)) → + List (List (Theory.Certified.Modeled.EquationWitness β)) → + Option + (Theory.Certified.CheckedClaim + (∀ (companion : Theory.Certified.Modeled.Companion β), + companion ∈ pending → Theory.Certified.Modeled.CompanionChecked entries companions companion)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries companions x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | companion :: rest, witnesses :: remaining => do + let first ← Theory.Certified.Modeled.checkCompanion? fuel entries companions companion witnesses + let others ← Theory.Certified.Modeled.checkEach?._unsafe_rec fuel entries companions rest remaining + pure { down := ⋯ } + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certified.Modeled.checkRules?._unsafe_rec +{β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (companions : List (Theory.Certified.Modeled.Companion β)) → + (rules : List (Theory.Certified.Signature.Rule β)) → + List (Theory.Certified.Modeled.EquationWitness β) → + Option + (Theory.Certified.CheckedClaim + (∀ (rule : Theory.Certified.Signature.Rule β), + rule ∈ rules → + Theory.Certified.Modeled.CheckedEquation entries + (Theory.Certified.Modeled.mapRule companions rule))) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries companions x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | rule :: rules, witness :: witnesses => do + let first ← + Theory.Certified.Modeled.checkEquation? fuel entries (Theory.Certified.Modeled.mapRule companions rule) witness + let rest ← Theory.Certified.Modeled.checkRules?._unsafe_rec fuel entries companions rules witnesses + pure { down := ⋯ } + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certified.Modeled.lookupCompanion._unsafe_rec +{β : Type u} → + [DecidableEq β] → + List (Theory.Certified.Modeled.Companion β) → Theory.ConstRef β → Option (Theory.Certified.Modeled.Companion β) +IMPLEMENTATION +fun {β} [DecidableEq β] x x_1 => + match x, x_1 with + | [], x => none + | companion :: rest, ref => + if companion.header.ref = ref then some companion else Theory.Certified.Modeled.lookupCompanion._unsafe_rec rest ref +RECURSION WORKER Ix.Theory.Certified.Modeled.splitLam?._unsafe_rec +{β : Type u} → Nat → Theory.VExpr β → Option (List (Theory.VExpr β) × Theory.VExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | 0, expression => some ([], expression) + | n.succ, domain.lam body => do + let __x ← Theory.Certified.Modeled.splitLam?._unsafe_rec n body + match __x with + | (domains, result) => pure (domain :: domains, result) + | n.succ, x => none +RECURSION WORKER Ix.Theory.Certified.Modeled.splitPi?._unsafe_rec +{β : Type u} → Nat → Theory.VExpr β → Option (List (Theory.VExpr β) × Theory.VExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | 0, type => some ([], type) + | n.succ, domain.forallE body => do + let __x ← Theory.Certified.Modeled.splitPi?._unsafe_rec n body + match __x with + | (domains, result) => pure (domain :: domains, result) + | n.succ, x => none +RECURSION WORKER Ix.Theory.Certified.Ordinary.checkConstructors._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (shape : Theory.Certified.Ordinary.Shape β) → + (ctors : List (Theory.Certified.Ordinary.Constructor β)) → + List (Theory.Certified.Ordinary.ConstructorWitness β) → + Option + (Theory.Certified.CheckedClaim + (∀ (ctor : Theory.Certified.Ordinary.Constructor β), + ctor ∈ ctors → Theory.Certified.Ordinary.ConstructorEvidence entries shape ctor)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries shape x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | ctor :: ctors, witness :: witnesses => + if hrefs : + ∀ (e : Theory.Model.AExpr β), e ∈ ctor.fields ++ ctor.indices → Theory.Model.AExpr.ReferencesIn entries e then + do + let fields ← + Theory.Certified.verifyTelescope fuel shape.universes entries (some shape.level) shape.parameterContext + ctor.fields witness.fields + let indices ← + Theory.Certified.verifyArguments fuel shape.universes entries (ctor.context shape) + (Theory.Model.Telescope.lift ctor.fields.length shape.indices) ctor.indices witness.indices + let recursive ← Theory.Certified.Ordinary.checkRecursive fuel entries shape ctor ctor.recursive witness.recursive + let rest ← Theory.Certified.Ordinary.checkConstructors._unsafe_rec fuel entries shape ctors witnesses + pure { down := ⋯ } + else none + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certified.Ordinary.checkRecursive._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (shape : Theory.Certified.Ordinary.Shape β) → + (ctor : Theory.Certified.Ordinary.Constructor β) → + (fields : List (Theory.Certified.Ordinary.RecursiveField β)) → + List (Theory.Certified.Ordinary.RecursiveWitness β) → + Option + (Theory.Certified.CheckedClaim + (∀ (field : Theory.Certified.Ordinary.RecursiveField β), + field ∈ fields → Theory.Certified.Ordinary.RecursiveEvidence entries shape ctor field)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries shape ctor x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | field :: fields, witness :: witnesses => + if hrefs : + ∀ (e : Theory.Model.AExpr β), + e ∈ field.domains ++ field.indices → Theory.Model.AExpr.ReferencesIn entries e then + do + let domains ← + Theory.Certified.verifyTelescope fuel shape.universes entries (some shape.level) (ctor.context shape) + field.domains witness.domains + let indices ← + Theory.Certified.verifyArguments fuel shape.universes entries + (Theory.Model.Telescope.context (ctor.context shape) field.domains) + (Theory.Model.Telescope.lift (ctor.fields.length + field.domains.length) shape.indices) field.indices + witness.indices + let rest ← Theory.Certified.Ordinary.checkRecursive._unsafe_rec fuel entries shape ctor fields witnesses + pure { down := ⋯ } + else none + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certified.Ordinary.parameterVars._unsafe_rec +{β : Type u} → Nat → Nat → List (Theory.Model.AExpr β) +IMPLEMENTATION +fun {β} offset x => + match x with + | 0 => [] + | n.succ => Theory.Model.AExpr.bvar (offset + n) :: Theory.Certified.Ordinary.parameterVars._unsafe_rec offset n +RECURSION WORKER Ix.Theory.Certified.PropWhen.bindList._unsafe_rec +(Nat → Theory.Certified.PropWhen) → List Nat → Theory.Certified.PropWhen +IMPLEMENTATION +fun f x => + match x with + | [] => Theory.Certified.PropWhen.always + | i :: ps => (f i).inter (Theory.Certified.PropWhen.bindList._unsafe_rec f ps) +RECURSION WORKER Ix.Theory.Certified.Signature.checkTypes._unsafe_rec +{β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (headers : List (Theory.Certified.Signature.Header β)) → + List (Theory.Certified.Signature.TypeWitness β) → + Option (Theory.Certified.CheckedClaim (Theory.Certified.Signature.Formed entries headers)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | header :: headers, witness :: witnesses => + if hf : entries header.ref = none then + if hs : Theory.Model.AExpr.Scope header.universes 0 header.type then + if hr : Theory.Model.AExpr.ReferencesIn entries header.type then do + let ht ← + Theory.Certified.verifyType fuel header.universes entries [] header.type + (Theory.Model.AExpr.sort witness.level) witness.typing + let rest ← + Theory.Certified.Signature.checkTypes._unsafe_rec fuel (entries.insert header.ref header.entry) headers + witnesses + pure { down := ⋯ } + else none + else none + else none + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certified.Signature.environment._unsafe_rec +{β : Type u} → + [DecidableEq β] → Theory.Model.Environment β → List (Theory.Certified.Signature.Header β) → Theory.Model.Environment β +IMPLEMENTATION +fun {β} [DecidableEq β] entries x => + match x with + | [] => entries + | header :: rest => Theory.Certified.Signature.environment._unsafe_rec (entries.insert header.ref header.entry) rest +RECURSION WORKER Ix.Theory.Certified.Structure.checkFields._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Theory.Model.Environment β) → + (w : Theory.VLevel) → + (Γ : Theory.Model.Context β) → + (fields : List (Theory.Certified.Structure.Field β)) → + List (Theory.Certified.TypingWitness β) → + Option (Theory.Certified.CheckedClaim (Theory.Certified.Structure.FieldsFormed entries w Γ fields)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel n entries w x x_1 x_2 => + match x, x_1, x_2 with + | x, [], [] => some { down := ⋯ } + | Γ, field :: fields, witness :: witnesses => + if hz : Theory.Certified.checkZeroImplies w field.level = true then do + let hA ← Theory.Certified.verifyType fuel n entries Γ field.domain (Theory.Model.AExpr.sort field.level) witness + let rest ← + Theory.Certified.Structure.checkFields._unsafe_rec fuel n entries w (Theory.Model.Context.push field.domain Γ) + fields witnesses + pure { down := ⋯ } + else none + | x, x_3, x_4 => none +RECURSION WORKER Ix.Theory.Certified.Structure.checkIota._unsafe_rec +{β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (d : Theory.Certified.Structure.Description β) → + (source recursor : β) → + (mode : Theory.Inductive.ElimMode) → + (fields : List (Theory.Certified.Structure.Field β × Nat)) → + List (Theory.Certified.Signature.RuleWitness β) → + Option + (Theory.Certified.CheckedClaim + (∀ (field : Theory.Certified.Structure.Field β) (i : Nat), + (field, i) ∈ fields → + Theory.Certified.Signature.RuleFormed (d.iotaEnvironment entries source recursor mode i) + (d.iotaRule source i field))) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries d source recursor mode x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | (field, i) :: fields, witness :: witnesses => do + let ht ← + Theory.Certified.Signature.checkRule fuel (d.iotaEnvironment entries source recursor mode i) + (d.iotaRule source i field) witness + let rest ← Theory.Certified.Structure.checkIota._unsafe_rec fuel entries d source recursor mode fields witnesses + pure { down := ⋯ } + | x, x_2 => none +RECURSION WORKER Ix.Theory.Model.AExpr.Scope._unsafe_rec +{β : Type u_1} → Nat → Nat → Theory.Model.AExpr β → Prop +IMPLEMENTATION +fun {β} universes depth x => + match x with + | Theory.Model.AExpr.bvar i => i < depth + | Theory.Model.AExpr.sort l => Theory.VLevel.WF universes l + | Theory.Model.AExpr.const ref ls => ∀ (l : Theory.VLevel), l ∈ ls → Theory.VLevel.WF universes l + | f.app a => + Theory.Model.AExpr.Scope._unsafe_rec universes depth f ∧ Theory.Model.AExpr.Scope._unsafe_rec universes depth a + | Theory.Model.AExpr.lam p a b => + Theory.Certified.PropWhen.WF universes p ∧ + Theory.Model.AExpr.Scope._unsafe_rec universes depth a ∧ + Theory.Model.AExpr.Scope._unsafe_rec universes (depth + 1) b + | Theory.Model.AExpr.forallE p a b => + Theory.Certified.PropWhen.WF universes p ∧ + Theory.Model.AExpr.Scope._unsafe_rec universes depth a ∧ + Theory.Model.AExpr.Scope._unsafe_rec universes (depth + 1) b + | Theory.Model.AExpr.proj ref field e => Theory.Model.AExpr.Scope._unsafe_rec universes depth e + | Theory.Model.AExpr.natLit value => True +RECURSION WORKER Ix.Theory.Model.AExpr.appN._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → List (Theory.Model.AExpr β) → Theory.Model.AExpr β +IMPLEMENTATION +fun {β} f x => + match x with + | [] => f + | x :: xs => Theory.Model.AExpr.appN._unsafe_rec (f.app x) xs +RECURSION WORKER Ix.Theory.Model.AExpr.decidableScope._unsafe_rec +{β : Type u_1} → {n k : Nat} → {e : Theory.Model.AExpr β} → Decidable (Theory.Model.AExpr.Scope n k e) +IMPLEMENTATION +fun {β} {n k} x => + match x with + | Theory.Model.AExpr.bvar i => Theory.Model.AExpr.decidableScope._aux_1 i + | Theory.Model.AExpr.sort l => Theory.VLevel.decidable_WF + | Theory.Model.AExpr.const ref ls => Theory.Model.AExpr.decidableScope._aux_3 ref ls + | f.app a => instDecidableAnd + | Theory.Model.AExpr.lam p A b => instDecidableAnd + | Theory.Model.AExpr.forallE p A b => instDecidableAnd + | Theory.Model.AExpr.proj ref field e => Theory.Model.AExpr.decidableScope._unsafe_rec + | Theory.Model.AExpr.natLit value => instDecidableTrue +RECURSION WORKER Ix.Theory.Model.AExpr.erase._unsafe_rec +{β : Type u_1} → Theory.Model.AExpr β → Theory.VExpr β +IMPLEMENTATION +fun {β} x => + match x with + | Theory.Model.AExpr.bvar i => Theory.VExpr.bvar i + | Theory.Model.AExpr.sort l => Theory.VExpr.sort l + | Theory.Model.AExpr.const r ls => Theory.VExpr.const r ls + | f.app a => (Theory.Model.AExpr.erase._unsafe_rec f).app (Theory.Model.AExpr.erase._unsafe_rec a) + | Theory.Model.AExpr.lam condition a b => + (Theory.Model.AExpr.erase._unsafe_rec a).lam (Theory.Model.AExpr.erase._unsafe_rec b) + | Theory.Model.AExpr.forallE condition a b => + (Theory.Model.AExpr.erase._unsafe_rec a).forallE (Theory.Model.AExpr.erase._unsafe_rec b) + | Theory.Model.AExpr.proj r i e => Theory.VExpr.proj r i (Theory.Model.AExpr.erase._unsafe_rec e) + | Theory.Model.AExpr.natLit v => Theory.VExpr.natLit v +RECURSION WORKER Ix.Theory.Model.AExpr.forallN._unsafe_rec +{β : Type u} → Theory.Certified.PropWhen → List (Theory.Model.AExpr β) → Theory.Model.AExpr β → Theory.Model.AExpr β +IMPLEMENTATION +fun {β} p x x_1 => + match x, x_1 with + | [], B => B + | A :: rest, B => Theory.Model.AExpr.forallE p A (Theory.Model.AExpr.forallN._unsafe_rec p rest B) +RECURSION WORKER Ix.Theory.Model.AExpr.inst._unsafe_rec +{β : Type u_1} → Theory.Model.AExpr β → Theory.Model.AExpr β → optParam Nat 0 → Theory.Model.AExpr β +IMPLEMENTATION +fun {β} x x_1 x_2 => + match x, x_1, x_2 with + | Theory.Model.AExpr.bvar i, a, k => Theory.Model.AExpr.instVar i a k + | Theory.Model.AExpr.sort l, x, x_3 => Theory.Model.AExpr.sort l + | Theory.Model.AExpr.const r ls, x, x_3 => Theory.Model.AExpr.const r ls + | f.app a, e, k => (Theory.Model.AExpr.inst._unsafe_rec f e k).app (Theory.Model.AExpr.inst._unsafe_rec a e k) + | Theory.Model.AExpr.lam p a b, e, k => + Theory.Model.AExpr.lam p (Theory.Model.AExpr.inst._unsafe_rec a e k) + (Theory.Model.AExpr.inst._unsafe_rec b e (k + 1)) + | Theory.Model.AExpr.forallE p a b, e, k => + Theory.Model.AExpr.forallE p (Theory.Model.AExpr.inst._unsafe_rec a e k) + (Theory.Model.AExpr.inst._unsafe_rec b e (k + 1)) + | Theory.Model.AExpr.proj r i e, a, k => Theory.Model.AExpr.proj r i (Theory.Model.AExpr.inst._unsafe_rec e a k) + | Theory.Model.AExpr.natLit v, x, x_3 => Theory.Model.AExpr.natLit v +RECURSION WORKER Ix.Theory.Model.AExpr.instL._unsafe_rec +{β : Type u_1} → List Theory.VLevel → Theory.Model.AExpr β → Theory.Model.AExpr β +IMPLEMENTATION +fun {β} levels x => + match x with + | Theory.Model.AExpr.bvar i => Theory.Model.AExpr.bvar i + | Theory.Model.AExpr.sort l => Theory.Model.AExpr.sort (Theory.VLevel.inst levels l) + | Theory.Model.AExpr.const r ls => Theory.Model.AExpr.const r (List.map (Theory.VLevel.inst levels) ls) + | f.app a => (Theory.Model.AExpr.instL._unsafe_rec levels f).app (Theory.Model.AExpr.instL._unsafe_rec levels a) + | Theory.Model.AExpr.lam p a b => + Theory.Model.AExpr.lam (Theory.Certified.instCondition levels p) (Theory.Model.AExpr.instL._unsafe_rec levels a) + (Theory.Model.AExpr.instL._unsafe_rec levels b) + | Theory.Model.AExpr.forallE p a b => + Theory.Model.AExpr.forallE (Theory.Certified.instCondition levels p) (Theory.Model.AExpr.instL._unsafe_rec levels a) + (Theory.Model.AExpr.instL._unsafe_rec levels b) + | Theory.Model.AExpr.proj r i e => Theory.Model.AExpr.proj r i (Theory.Model.AExpr.instL._unsafe_rec levels e) + | Theory.Model.AExpr.natLit v => Theory.Model.AExpr.natLit v +RECURSION WORKER Ix.Theory.Model.AExpr.instRev._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → List (Theory.Model.AExpr β) → Theory.Model.AExpr β +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | e, [] => e + | e, a :: rest => Theory.Model.AExpr.instRev._unsafe_rec (e.inst a rest.length) rest +RECURSION WORKER Ix.Theory.Model.AExpr.lamN._unsafe_rec +{β : Type u} → Theory.Certified.PropWhen → List (Theory.Model.AExpr β) → Theory.Model.AExpr β → Theory.Model.AExpr β +IMPLEMENTATION +fun {β} p x x_1 => + match x, x_1 with + | [], body => body + | A :: rest, body => Theory.Model.AExpr.lam p A (Theory.Model.AExpr.lamN._unsafe_rec p rest body) +RECURSION WORKER Ix.Theory.Model.AExpr.liftN._unsafe_rec +{β : Type u_1} → Nat → Theory.Model.AExpr β → optParam Nat 0 → Theory.Model.AExpr β +IMPLEMENTATION +fun {β} count x x_1 => + match x, x_1 with + | Theory.Model.AExpr.bvar i, k => Theory.Model.AExpr.bvar (Theory.liftVar count i k) + | Theory.Model.AExpr.sort l, x => Theory.Model.AExpr.sort l + | Theory.Model.AExpr.const r ls, x => Theory.Model.AExpr.const r ls + | f.app a, k => (Theory.Model.AExpr.liftN._unsafe_rec count f k).app (Theory.Model.AExpr.liftN._unsafe_rec count a k) + | Theory.Model.AExpr.lam p a b, k => + Theory.Model.AExpr.lam p (Theory.Model.AExpr.liftN._unsafe_rec count a k) + (Theory.Model.AExpr.liftN._unsafe_rec count b (k + 1)) + | Theory.Model.AExpr.forallE p a b, k => + Theory.Model.AExpr.forallE p (Theory.Model.AExpr.liftN._unsafe_rec count a k) + (Theory.Model.AExpr.liftN._unsafe_rec count b (k + 1)) + | Theory.Model.AExpr.proj r i e, k => Theory.Model.AExpr.proj r i (Theory.Model.AExpr.liftN._unsafe_rec count e k) + | Theory.Model.AExpr.natLit v, x => Theory.Model.AExpr.natLit v +RECURSION WORKER Ix.Theory.Model.AExpr.mapRefs._unsafe_rec +{β : Type u} → {γ : Type v} → (Theory.ConstRef β → Theory.ConstRef γ) → Theory.Model.AExpr β → Theory.Model.AExpr γ +IMPLEMENTATION +fun {β} {γ} mapping x => + match x with + | Theory.Model.AExpr.bvar i => Theory.Model.AExpr.bvar i + | Theory.Model.AExpr.sort level => Theory.Model.AExpr.sort level + | Theory.Model.AExpr.const ref levels => Theory.Model.AExpr.const (mapping ref) levels + | f.app a => (Theory.Model.AExpr.mapRefs._unsafe_rec mapping f).app (Theory.Model.AExpr.mapRefs._unsafe_rec mapping a) + | Theory.Model.AExpr.lam condition type body => + Theory.Model.AExpr.lam condition (Theory.Model.AExpr.mapRefs._unsafe_rec mapping type) + (Theory.Model.AExpr.mapRefs._unsafe_rec mapping body) + | Theory.Model.AExpr.forallE condition type body => + Theory.Model.AExpr.forallE condition (Theory.Model.AExpr.mapRefs._unsafe_rec mapping type) + (Theory.Model.AExpr.mapRefs._unsafe_rec mapping body) + | Theory.Model.AExpr.proj ref index major => + Theory.Model.AExpr.proj (mapping ref) index (Theory.Model.AExpr.mapRefs._unsafe_rec mapping major) + | Theory.Model.AExpr.natLit n => Theory.Model.AExpr.natLit n +RECURSION WORKER Ix.Theory.Model.AExpr.references._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → List (Theory.ConstRef β) +IMPLEMENTATION +fun {β} x => + match x with + | Theory.Model.AExpr.bvar index => [] + | Theory.Model.AExpr.sort level => [] + | Theory.Model.AExpr.natLit value => [] + | Theory.Model.AExpr.const r levels => [r] + | f.app a => Theory.Model.AExpr.references._unsafe_rec f ++ Theory.Model.AExpr.references._unsafe_rec a + | Theory.Model.AExpr.lam condition f a => + Theory.Model.AExpr.references._unsafe_rec f ++ Theory.Model.AExpr.references._unsafe_rec a + | Theory.Model.AExpr.forallE condition f a => + Theory.Model.AExpr.references._unsafe_rec f ++ Theory.Model.AExpr.references._unsafe_rec a + | Theory.Model.AExpr.proj r field e => r :: Theory.Model.AExpr.references._unsafe_rec e +RECURSION WORKER Ix.Theory.Model.Telescope.context._unsafe_rec +{β : Type u} → Theory.Model.Context β → List (Theory.Model.AExpr β) → Theory.Model.Context β +IMPLEMENTATION +fun {β} Γ x => + match x with + | [] => Γ + | A :: rest => Theory.Model.Telescope.context._unsafe_rec (Theory.Model.Context.push A Γ) rest +RECURSION WORKER Ix.Theory.Model.Telescope.extend._unsafe_rec +{V : Type v} → (Nat → V) → List V → Nat → V +IMPLEMENTATION +fun {V} env x => + match (motive := List V → Nat → V) x with + | [] => env + | x :: xs => Theory.Model.Telescope.extend._unsafe_rec (Theory.Model.Valuation.cons x env) xs +RECURSION WORKER Ix.Theory.Model.Telescope.independent._unsafe_rec +{β : Type u} → List (Theory.Model.AExpr β) → optParam Nat 0 → List (Theory.Model.AExpr β) +IMPLEMENTATION +fun {β} x x_1 => + match x, x_1 with + | [], x => [] + | A :: rest, offset => + Theory.Model.AExpr.liftN offset A :: Theory.Model.Telescope.independent._unsafe_rec rest (offset + 1) +RECURSION WORKER Ix.Theory.Model.Telescope.inst._unsafe_rec +{β : Type u} → Theory.Model.AExpr β → List (Theory.Model.AExpr β) → optParam Nat 0 → List (Theory.Model.AExpr β) +IMPLEMENTATION +fun {β} arg x x_1 => + match x, x_1 with + | [], x => [] + | A :: rest, k => A.inst arg k :: Theory.Model.Telescope.inst._unsafe_rec arg rest (k + 1) +RECURSION WORKER Ix.Theory.Model.Telescope.lift._unsafe_rec +{β : Type u} → Nat → List (Theory.Model.AExpr β) → optParam Nat 0 → List (Theory.Model.AExpr β) +IMPLEMENTATION +fun {β} count x x_1 => + match x, x_1 with + | [], x => [] + | A :: rest, k => Theory.Model.AExpr.liftN count A k :: Theory.Model.Telescope.lift._unsafe_rec count rest (k + 1) +RECURSION WORKER Ix.Theory.Model.Telescope.simple._unsafe_rec +{V : Type v} → (domains : List V) → Theory.Model.SetTheory.Tower.TeleS V domains.length +IMPLEMENTATION +fun {V} x => + match x with + | [] => Theory.Model.SetTheory.Tower.TeleS.nil + | A :: rest => Theory.Model.SetTheory.Tower.TeleS.cons A fun x => Theory.Model.Telescope.simple._unsafe_rec rest +RECURSION WORKER Ix.Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec +{β : Type u_1} → [DecidableEq β] → (x x_1 : Theory.Model.AExpr β) → Decidable (x = x_1) +IMPLEMENTATION +fun {β} [inst : DecidableEq β] x x_1 => + match x, x_1 with + | Theory.Model.AExpr.bvar a, Theory.Model.AExpr.bvar b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | Theory.Model.AExpr.bvar index, Theory.Model.AExpr.sort level => isFalse ⋯ + | Theory.Model.AExpr.bvar index, Theory.Model.AExpr.const ref levels => isFalse ⋯ + | Theory.Model.AExpr.bvar index, fn.app arg => isFalse ⋯ + | Theory.Model.AExpr.bvar index, Theory.Model.AExpr.lam condition domain body => isFalse ⋯ + | Theory.Model.AExpr.bvar index, Theory.Model.AExpr.forallE condition domain body => isFalse ⋯ + | Theory.Model.AExpr.bvar index, Theory.Model.AExpr.proj ref field major => isFalse ⋯ + | Theory.Model.AExpr.bvar index, Theory.Model.AExpr.natLit value => isFalse ⋯ + | Theory.Model.AExpr.sort level, Theory.Model.AExpr.bvar index => isFalse ⋯ + | Theory.Model.AExpr.sort a, Theory.Model.AExpr.sort b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | Theory.Model.AExpr.sort level, Theory.Model.AExpr.const ref levels => isFalse ⋯ + | Theory.Model.AExpr.sort level, fn.app arg => isFalse ⋯ + | Theory.Model.AExpr.sort level, Theory.Model.AExpr.lam condition domain body => isFalse ⋯ + | Theory.Model.AExpr.sort level, Theory.Model.AExpr.forallE condition domain body => isFalse ⋯ + | Theory.Model.AExpr.sort level, Theory.Model.AExpr.proj ref field major => isFalse ⋯ + | Theory.Model.AExpr.sort level, Theory.Model.AExpr.natLit value => isFalse ⋯ + | Theory.Model.AExpr.const ref levels, Theory.Model.AExpr.bvar index => isFalse ⋯ + | Theory.Model.AExpr.const ref levels, Theory.Model.AExpr.sort level => isFalse ⋯ + | Theory.Model.AExpr.const a a_1, Theory.Model.AExpr.const b b_1 => + if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯ + | Theory.Model.AExpr.const ref levels, fn.app arg => isFalse ⋯ + | Theory.Model.AExpr.const ref levels, Theory.Model.AExpr.lam condition domain body => isFalse ⋯ + | Theory.Model.AExpr.const ref levels, Theory.Model.AExpr.forallE condition domain body => isFalse ⋯ + | Theory.Model.AExpr.const ref levels, Theory.Model.AExpr.proj ref_1 field major => isFalse ⋯ + | Theory.Model.AExpr.const ref levels, Theory.Model.AExpr.natLit value => isFalse ⋯ + | fn.app arg, Theory.Model.AExpr.bvar index => isFalse ⋯ + | fn.app arg, Theory.Model.AExpr.sort level => isFalse ⋯ + | fn.app arg, Theory.Model.AExpr.const ref levels => isFalse ⋯ + | a.app a_1, b.app b_1 => + let inst_1 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a a; + let inst_3 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | fn.app arg, Theory.Model.AExpr.lam condition domain body => isFalse ⋯ + | fn.app arg, Theory.Model.AExpr.forallE condition domain body => isFalse ⋯ + | fn.app arg, Theory.Model.AExpr.proj ref field major => isFalse ⋯ + | fn.app arg, Theory.Model.AExpr.natLit value => isFalse ⋯ + | Theory.Model.AExpr.lam condition domain body, Theory.Model.AExpr.bvar index => isFalse ⋯ + | Theory.Model.AExpr.lam condition domain body, Theory.Model.AExpr.sort level => isFalse ⋯ + | Theory.Model.AExpr.lam condition domain body, Theory.Model.AExpr.const ref levels => isFalse ⋯ + | Theory.Model.AExpr.lam condition domain body, fn.app arg => isFalse ⋯ + | Theory.Model.AExpr.lam a a_1 a_2, Theory.Model.AExpr.lam b b_1 b_2 => + if h : a = b then + h ▸ + let inst_1 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst_2 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 a_1; + let inst_3 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Theory.Model.AExpr.lam condition domain body, Theory.Model.AExpr.forallE condition_1 domain_1 body_1 => isFalse ⋯ + | Theory.Model.AExpr.lam condition domain body, Theory.Model.AExpr.proj ref field major => isFalse ⋯ + | Theory.Model.AExpr.lam condition domain body, Theory.Model.AExpr.natLit value => isFalse ⋯ + | Theory.Model.AExpr.forallE condition domain body, Theory.Model.AExpr.bvar index => isFalse ⋯ + | Theory.Model.AExpr.forallE condition domain body, Theory.Model.AExpr.sort level => isFalse ⋯ + | Theory.Model.AExpr.forallE condition domain body, Theory.Model.AExpr.const ref levels => isFalse ⋯ + | Theory.Model.AExpr.forallE condition domain body, fn.app arg => isFalse ⋯ + | Theory.Model.AExpr.forallE condition domain body, Theory.Model.AExpr.lam condition_1 domain_1 body_1 => isFalse ⋯ + | Theory.Model.AExpr.forallE a a_1 a_2, Theory.Model.AExpr.forallE b b_1 b_2 => + if h : a = b then + h ▸ + let inst_1 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst_2 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 a_1; + let inst_3 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Theory.Model.AExpr.forallE condition domain body, Theory.Model.AExpr.proj ref field major => isFalse ⋯ + | Theory.Model.AExpr.forallE condition domain body, Theory.Model.AExpr.natLit value => isFalse ⋯ + | Theory.Model.AExpr.proj ref field major, Theory.Model.AExpr.bvar index => isFalse ⋯ + | Theory.Model.AExpr.proj ref field major, Theory.Model.AExpr.sort level => isFalse ⋯ + | Theory.Model.AExpr.proj ref field major, Theory.Model.AExpr.const ref_1 levels => isFalse ⋯ + | Theory.Model.AExpr.proj ref field major, fn.app arg => isFalse ⋯ + | Theory.Model.AExpr.proj ref field major, Theory.Model.AExpr.lam condition domain body => isFalse ⋯ + | Theory.Model.AExpr.proj ref field major, Theory.Model.AExpr.forallE condition domain body => isFalse ⋯ + | Theory.Model.AExpr.proj a a_1 a_2, Theory.Model.AExpr.proj b b_1 b_2 => + if h : a = b then + h ▸ + if h : a_1 = b_1 then + h ▸ + let inst_1 := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Theory.Model.AExpr.proj ref field major, Theory.Model.AExpr.natLit value => isFalse ⋯ + | Theory.Model.AExpr.natLit value, Theory.Model.AExpr.bvar index => isFalse ⋯ + | Theory.Model.AExpr.natLit value, Theory.Model.AExpr.sort level => isFalse ⋯ + | Theory.Model.AExpr.natLit value, Theory.Model.AExpr.const ref levels => isFalse ⋯ + | Theory.Model.AExpr.natLit value, fn.app arg => isFalse ⋯ + | Theory.Model.AExpr.natLit value, Theory.Model.AExpr.lam condition domain body => isFalse ⋯ + | Theory.Model.AExpr.natLit value, Theory.Model.AExpr.forallE condition domain body => isFalse ⋯ + | Theory.Model.AExpr.natLit value, Theory.Model.AExpr.proj ref field major => isFalse ⋯ + | Theory.Model.AExpr.natLit a, Theory.Model.AExpr.natLit b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ +RECURSION WORKER Ix.Theory.Certified.Ordinary.Shape.checkConstructorTypes._unsafe_rec +{β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (shape : Theory.Certified.Ordinary.Shape β) → + (source : β) → + (ctors : List (Theory.Certified.Ordinary.Constructor β)) → + List (Theory.Certified.Ordinary.Shape.TypeWitness β) → + Option + (Theory.Certified.CheckedClaim + (∀ (ctor : Theory.Certified.Ordinary.Constructor β), + ctor ∈ ctors → + Theory.Model.EntryClosed (shape.familyEnvironment entries source) + (shape.constructorEntry source ctor) ∧ + ∃ l, + Theory.Model.TypingClaim (shape.familyEnvironment entries source) [] + (ctor.type shape source) (Theory.Model.AExpr.sort l))) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries shape source x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | ctor :: ctors, witness :: witnesses => + if hs : Theory.Model.AExpr.Scope shape.universes 0 (ctor.type shape source) then + if hr : Theory.Model.AExpr.ReferencesIn (shape.familyEnvironment entries source) (ctor.type shape source) then do + let ht ← + Theory.Certified.verifyType fuel shape.universes (shape.familyEnvironment entries source) [] + (ctor.type shape source) (Theory.Model.AExpr.sort witness.level) witness.witness + let rest ← + Theory.Certified.Ordinary.Shape.checkConstructorTypes._unsafe_rec fuel entries shape source ctors witnesses + pure { down := ⋯ } + else none + else none + | x, x_2 => none +RECURSION WORKER Ix.Theory.Certified.Ordinary.Shape.checkRules._unsafe_rec +{β : Type u} → + [DecidableEq β] → + Nat → + (entries : Theory.Model.Environment β) → + (shape : Theory.Certified.Ordinary.Shape β) → + (source recursor : β) → + (mode : Theory.Inductive.ElimMode) → + (ctors : List (Theory.Certified.Ordinary.Constructor β × Nat)) → + List (Theory.Certified.Ordinary.RuleWitness β) → + Option + (Theory.Certified.CheckedClaim + (∀ (ctor : Theory.Certified.Ordinary.Constructor β) (i : Nat), + (ctor, i) ∈ ctors → + Theory.Certified.Ordinary.Shape.RuleFormation entries shape source recursor mode i ctor)) +IMPLEMENTATION +fun {β} [DecidableEq β] fuel entries shape source recursor mode x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | (ctor, i) :: ctors, witness :: witnesses => do + let rule ← Theory.Certified.Ordinary.Shape.checkRule fuel entries shape source recursor mode i ctor witness + let rest ← + Theory.Certified.Ordinary.Shape.checkRules._unsafe_rec fuel entries shape source recursor mode ctors witnesses + pure { down := ⋯ } + | x, x_2 => none +RECURSION WORKER Ix.Theory.Model.SetTheory.Tower.BoundS._unsafe_rec +{V : Type u} → [Theory.Model.SetTheory V] → Nat → {n : Nat} → Theory.Model.SetTheory.Tower.TeleS V n → Prop +IMPLEMENTATION +fun {V} [Theory.Model.SetTheory V] w x x_1 => + match x, x_1 with + | .(0), Theory.Model.SetTheory.Tower.TeleS.nil => True + | .(n + 1), Theory.Model.SetTheory.Tower.TeleS.cons A B => + Theory.Model.SetTheory.Mem A (Theory.Model.SetTheory.univ w) ∧ + ∀ (a : V), Theory.Model.SetTheory.Mem a A → Theory.Model.SetTheory.Tower.BoundS._unsafe_rec w (B a) +RECURSION WORKER Ix.Theory.Model.SetTheory.Tower.FitsS._unsafe_rec +{V : Type u} → [Theory.Model.SetTheory V] → {n : Nat} → Theory.Model.SetTheory.Tower.TeleS V n → List V → Prop +IMPLEMENTATION +fun {V} [Theory.Model.SetTheory V] x x_1 x_2 => + match x, x_1, x_2 with + | .(0), Theory.Model.SetTheory.Tower.TeleS.nil, [] => True + | .(0), Theory.Model.SetTheory.Tower.TeleS.nil, head :: tail => False + | .(n + 1), Theory.Model.SetTheory.Tower.TeleS.cons A B, [] => False + | .(n + 1), Theory.Model.SetTheory.Tower.TeleS.cons A B, a :: as => + Theory.Model.SetTheory.Mem a A ∧ Theory.Model.SetTheory.Tower.FitsS._unsafe_rec (B a) as +RECURSION WORKER Ix.Theory.Model.SetTheory.Tower.PropS._unsafe_rec +{V : Type u} → [Theory.Model.SetTheory V] → {n : Nat} → Theory.Model.SetTheory.Tower.TeleS V n → Prop +IMPLEMENTATION +fun {V} [Theory.Model.SetTheory V] x x_1 => + match x, x_1 with + | .(0), Theory.Model.SetTheory.Tower.TeleS.nil => True + | .(n + 1), Theory.Model.SetTheory.Tower.TeleS.cons A B => + Theory.Model.SetTheory.Mem A Theory.Model.SetTheory.univZero ∧ + ∀ (a : V), Theory.Model.SetTheory.Mem a A → Theory.Model.SetTheory.Tower.PropS._unsafe_rec (B a) +Certified host adapters ROOTS 86; LOGICAL DECLARATIONS 9682; WITH RUNTIME 10957 +RUNTIME EXTERNS [Blake3.Rust.hasherFinalize, + Blake3.Rust.hasherInit, + Blake3.Rust.hasherInitDeriveKey, + Blake3.Rust.hasherInitKeyed, + Blake3.Rust.hasherUpdate] +RECURSION WORKERS 130 +All inventoried recursion workers have safe logical sources; no partial opaque source or executable replacement is permitted. Runtime diagnostics cover Ix and Blake3 modules, including private constants. Lean/Std execution and the BLAKE3 foreign interface remain external runtime boundaries. +These host-adapter roots establish semantic claims under the enforced profile and explicit model premises. They do not establish full production-checker refinement or Aiur compiler/AIR soundness. diff --git a/Tests/Fixtures/Certified/README.md b/Tests/Fixtures/Certified/README.md new file mode 100644 index 000000000..0ff6ec05b --- /dev/null +++ b/Tests/Fixtures/Certified/README.md @@ -0,0 +1,27 @@ +# Frozen certified adapter evidence + +`c7-handoff.tar.gz` preserves the 53 original certified adapter source files, +their authenticated patches and source identities, and the historical +reports and regression corpora. Its SHA-256 and the source-to-local mappings +are recorded in [`ImportManifest.lean`](../../Certified/ImportManifest.lean). + +Run `lake run check-certified` from the repository root. The gate checks the +archive and maintained host source identities, the exact declaration audit, six +native test programs and three command-line corpora. Generated source and +envelope bytes and process output must match the frozen evidence. JSON +requests and aggregate CLI records are compared as parsed values because the +maintained Lean driver uses different whitespace and object-key ordering. + +The historical VM pilot and packet producer stay in the archive for a later +change. Host reports are compared after removing only the `pilotDeclined` +and `pilotDeclines` fields. All source/envelope fixtures and CLI outcomes +retain their original comparisons. + +The archive's historical Python and shell drivers are provenance, not test +dependencies. Current tests use Lean. Execution requires the usual Linux +build tools, including `tar`, `sha256sum` and `timeout`. + +The complete historical Ix base commit is not included. The preserved patch +sequence is sufficient to reconstruct the selected adapter files because +each first appears as a new file. The historical reproduction script still +requires its original base checkouts; current Ix validation is self-contained. diff --git a/Tests/Fixtures/Certified/c7-handoff.tar.gz b/Tests/Fixtures/Certified/c7-handoff.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..38e00ee7e1667d2ee5f408a7875a6259d618f605 GIT binary patch literal 3510635 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%0D@mn}KaLQoUFcH)u(POmy5KY_g*o%+E#HdibO`gZ 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�>luxt&GLvi{gEc|x86V9DqL)r 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≺H9`t*PXb73qS?c(uF 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%0DaSXHJhmnxm_ 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%0A*33(;@P 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�>->_v=MHm&>~~ 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 z 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

oDzxe6Ngwk-7;uVVMZSp6Q^@s(UI75)?_li~Y%N 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 z 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≤Amnp8b>2WyNwOW9f{}1S4#G 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

%Q=o112i3d|EzxE? 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 z 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%0Dhic@mBhTwf(!9d+j;@J`*%Yj3 zRQoo}rrh^|=>^}1N8JZXf;69J+8-&2tqnh>qO#vsbGN2tZ;7W^gxuC+r4<4?d$nz( zo#N_ZSXY_~l$PzbRielyww
DaB3S65oT3%@??Y>eFzaWlb#de3i5-2N1`{%uFV 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%0D996)0i0yz&qF+b!< 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

wTGhU^qqQ^diT|=SqQR#xc6;q^ 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

&py6GrB0da8Y1W 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 z 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%0D}Q^!w|v^=~v!nNi2@J)KC66f4b* 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åg8aDD3tuk*NY)HUJ{^#1eYu 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

%6a?V;KTxfD4&q76zUVMeY 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�sP|2MuieXPNe;bYol&+p5+n43}s6A{4a(HI0JR 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 z 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

RSY6iR#d~~iln9b;>stWQd;gbrE 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%0Dd!UxFJfM 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μ16PCEZg?@@N^#P_x#;9hPrk{fN4Xh=_MAfndQjaqDf+Ks-xVH6NPR z_pO%dzi}w_Pyn`Oe%r8<)ewpk{&D(L8p(g#W)MZ~Yg5c`veG z`}#VT@tniEm${ZNIml7)7m0n_%k>C_A;M3dkSO8^6cgAECu~I}8CqGMZ`<3GMoza>t z(w#z8McYnssvjH{@6AtkC~fYHB!g7nfB&upsdC6^G-&TCbiA|NL>5I|(!(gbYf#KxG4+=sjaqc=lU) zJHW?p-OnvzzfB0Nd)SuwR#@@j-M!jWgi*bHM&23fQ31h+YlYFUXWMg#zKEU`xqFE)S#ig+)Tqf z4E!*JzG2|44ts8!(G&3P?Y*bGf8oZ)R$*ca{YcdWC*2;YiYrskcfu3NxyE5*U6*bW zE{yB-`5CW(z~OF8f~k#1$Q%Evo83=?m94vpgu2&`?&4i14;S_WQ_ho4K$?SN%uk)h zeS<4~3_P86wHKW@M%Z1g2(VW-Xep<3eS%n{4VqvD* zto?zH=up`&+7vcYffuP8m8=42$Z=F9rVz7(#|~?RVtiLrjr0f zY~kuSG_SgWJKG-|oI{xaM8aa`#&C-cqea205E8zZc`PU4zND2s)|!lajrD?l$Kx5_ zkAPtcq9vTquTp`XYW8yfOs+Td(($yd1Ct!~QjOIaPcH}_&XiEoFQg0mS8 zz+zL)K)bkgl2h1~XcgmuJjB?|OwpV~<5uF6qc|p3;~jY?IFTkA zzwxe;K4u_EX1Y&IOgHlEp}MF4SBV&7_8Yt zC;uu06kJN157DAYfpwWruE1HNngO&AvmgHcKSA7nnUfbzO-7#NnGA##YasSGB&2po zq0j4?KgkZ?0;o?jylObfR}in^pJZ3v&@@29 z)ggzz?jgVO4!Jd%PuOA}Ipr@Rr#uXy{c)f4dLRBJd}@=W%e!2>zE=eUI=-cvhso17 z1UV7$T+%%$M5|-_dux>Zr^Qk08C~_ot6kFBMQHFfFQ8p$_>L&sixMI-vog3Hqp#{W zp3p9l!GpbDAi^u1@{TYl`!n*-V|?!0k8f2c?quKUA@acb(;x3q>WeO^`a7 z8Zj?hoIEid_@n7iU=a7uXTm!Zdsccn8D=_IXtYJImFPyYvmli#6TuUHHnt{`_-C5d z@JAgFx?hrhJ6geOQF`?meYa`<@Sc-%U~4`DKiEVvQyO4jcR?da7(XIc#QlVNxXaby zj|gt!>OZ3_b+1I9U$G(k z@2GaPJap6fpkC5uNFSgp=hwsLkmBAZ2x{WTwV*mOShX!V*IKZ-Plj()KmbZ#=!ANY zUlr)Ee_71lUau6eGesHBs=5IG`1NK56)I;GE}(-1h*CpE`5GMer7u3kaljI*DF#oV z+kU2ya$8N$7x`wy=I6JmCHdypWwnOkmMeAt<;yIu6(Ts{3Th(jVza%wr#R_- zKkZ!;!O|q_8=h0r!17JP7qe04cP)~YbnfhLZ+Q`mZmWmKy2q|$?%J7BZ5Jk$8Ftn+ zOiuT~Iu~MMcB-0ydUYDPT@0#&;t6nQ)^u#xHg}6B$A14!Bs4VWpe;7E9-1XMXR_51 zW@64|M`u_%xz`KItfPso4KiOFLA`)ZnN6QQ?}e};uCvyf`~BA=eY~j7)L$^K_7G36 zai+9>IV|(cxehFzMK{ul zwBQ9%b-zi>cWAKY?>cXI<;lmqbF?5S4ZrfF-s}3PRGvySQGY=J68a|`ECC0hN5u!8 zg0JI~d{GzVk293&$Fg88ptVTpdc`NO8nZF-O{C} z2+OOR&V%makf9&9TaTziMl<{(wasvM+;IBwaHCVfpJDOSYi4LCG>(%Xb?j+8_D0l| zl0W;`w^SmzFI>w0b(1v|XqS_4U{`2J1*WJ%qEfQr=2n|GKox9l+yr>8O8^4BJYdsh zZKUpoUiVm^T8%lcg{0qM)LnL0b2nBN_O8NxS6Zxn94 zgI0|H z;DIElsKI(=GotIH%=P(+!kkxe7YnGAj`zOt)**}Asp>^1nCbe>MBDqMmDZFyHbF$O z>)O&LO740EqYo_@=5-q!2vC5^8W6OEYeQm>tGYC+YOD#XR|_XfFJ?jta2+mU*9soGeTzKY*3d~o9$Nl=8VY4j+~$bh{y`ME*EB>-+gd2Rh) z14VRdWmKgTDp*=hP(*Kc>;$}kJm)QPHMSrHEf{ON%YIh)rp5DnYiixrGhgI3J{3lU_Pua6l zh@pCS0)9%>Yy?ivhQm6gJ2f6wxT%xJO;itvPCciBiW|Fjt4JP0ltf}cu z<_(5ay_B{yntk3jnu{#3J&wQapp+SJI}?F~`fMQ0R0CZ5P|j2Q*P6g(|x1MeUrz1t=VHgyKRaCkFnoGnW+aWD(vi}t~HSGagRb%_ES2~ zE?bQmnqCb9qs*xWIDM+Mp1yI$)8uI+rE-mY3e&(_5p7HH{lSq4|gZmkvcOj)HDn5qkgrkAGJ>f zd@t)5Fc-ibvxfK0y0vIB`>A@ghsZwDAFi-_pC%lkq3b;;n%hxfk)K@$7toVVaJhbd z{qcOYm>sD@{AtD@>U(9#@m$Avi&Q^8HSS&F8GckpLQ2Sjs2z@IH;W>l zlXarTEWXgin;<5TeP$pRfcab@@c%a=N zuG@*!eNJAR;_#J^QPhQd4o z_9f)Xz{`eULf6XB4&?jXwEAZ_et;0!PHA)?@5r+=B@$-^NAp6(Pb0k5nBrr-S*@T# z8KfjpSU|7NH;R^26w``9yPs_-+lV6j#mjTmaXycaJ;(=FUJSmfc<)*%TJ*% zH-7ox+VRUx;Pt&kzs3{-WA1A? zB>!K2>Li1Dq|dk~S)x{0-7s1ujK_*ijK@PyYhG6OJO;*@fNS9k4WN?^uuh{)%#SUA z-K~c9JN%!9jY@+M18zUH>PDH>b+#em0ylgh~BLO7M{NpZD;EwWq7vqoH0Q$GmVewdb; z5#HYtDd0xoy(x*6iCRoh7`ob@$)v%U(7C|1;V0Rk?+Hk3Tv*2f>wAtA zZk#{%x*kSZZYN(*7e>3=SOG6CsyHehL(3iek6zs^H>N1XwHRe&-v4BgS7+Y0&yRIF zIAD|pV@M^MEuwjG7F2FYo6-lR*!VFiWwO$2#(1un)5QYRFk*1*UT7pma0-op-3P$k z6!T&O8G7rx17HES@l!Lu&z9yZI%`LdFV`EVfq_gp7VEOCUiig`d$G-r9Rw7lf~2v% zkPB&Ok;EuCK%_`W(%?AJKzxgqv{Wzjf*DdKK{`EU^2#qq*`_$H&Wg!WjknRnR}}VX zwAUzFRj%ufjjeHqGXl3N<2%w8O`Ilk$n+^PS*MiuU8V07mavs)Z4TBpdTYh+|NEFaZQx zt>H1nd+AyL&)Jb;THqgM6y#WzA9(&LU=J|Uk6)_3kE66M#Y%vOljR$R!FxVJ{JFw| zx=?J*U`#30HKTAabS_U^W)rI~sBNd&H&JSR!rfJPtpMPrlZI6^k+{eWBVYwe|6ncG z;NbYO3D~$D)5kwnAL&i}-4ow+Hbg4Z8}@^id%}eBu?Al`#&aatIkEf4YEYk_g*xW( zwmg|sM|=Iq-$RQjll*j3fS_<^x3Q69;Vre#$49uH-&j7~e(!9&=*qU>o!7j*?UlA) z153$9b44^ua6UDzzNm<)i^V(}kJX)>7&dmkz)1U5S@7OuFlfF#SCH5g(?Zcn#d~dQ zYqW)O4a`xT6mx)>u(ZB)f3-2LtyD)sNoQl#e}ybuz9bHMsV-|Zh0_96X^QZwkF>%K z%)4AsLK)k~jp9b*xY371k?Z=FDrb&0i>PmZjE)Nk8O@4{G(Xs zELVWrG;8VYbhh3YjuR)^P;zCUt@v0KU;^6VsK$RdK5Uz!lTN>NZ(}#B6rlAASdQ+F zGJy#iAV9qVlgSX|Zhhd50)!bw$XcD7SS}F<9gr<#yM1WtndC;3I$f-4wU0s%5bS`t zMt$yEO<4pso838C&91WYg!hHQ_)dDZSmYO3xd`k5;-+M6zb>J!aEIoyaQc~3@rqqK zn%_(T0pktW!3yrS?PLi5)x7xN-S=jF4dLEM!WRDidw0(iZbNtyws4c)f2^I9Zqg{; z)e5d9Bmy?qIct`DBBGke13G}hYII6RQj;62RQAIk{xK2|nLPrnvwCM$)D*H6Zwh}v z^Zydq)L>Szl5K&Ighe2YDU46Z^=Xnf=$)E z{u|JxE}myfvX3jLUf{s6 zCRV&eE*ZQF6dtH2AFoymbM-!}>e$y27~0@78fGc{3d?7$Ml9w>DV4*JrZ*3M@VP6d67FmaRF zcJe`b<|<+*Tz_AL7}rp4{*Dcdo7E_HT0b@)2OKKNnCTzoIfvlA@& zg^b~bxkLgfO2H*m+W1b9DNMfnoj4cd->m+C@`!vS6i29~82C<8)eBOTa*Kx0<%umb zMi}BoFAtnBXqH!8Ld(wAuGf~~HmA%CD|l}5Sv4g`zsRg|J*PYh%2N&|j6(^eBg9DPMxjWX080%!;W1Yxls-@@$QRgJg?V@g^m*<$<1uz{@ z8~)Q);&f;$q#3!C+ynO{;wTz513gx|fFoOW5^wVPyZO7bysvoUj3b1bcMk5Hqc6E6 z$Hf)nbBhv+y}@>rM>^h!5q<4=s}ZsBX0&){{<_z2zd5g(bi=kcb?I?>PJQbQ&@Ta4 zebX;#*02io5tg9lPe$2M)LSI(gAsbo1!m}oG4q~0e|oBqn!kyC5^=TEulo919s!56 zO?X^JCN@G(B2t7AERT|!^kZ|4oo+I|7v|?nV0bU3E)f#+fja5atel~-6#MNU3Vo3+%tU1mKi$mT07#$3iu+OI?{X{>SZT2#1Um{ zMA7O?6fuJg4s<K&qWwVw9$R;ZrD>iY660xHD$z6Rw((#Rp*LK zv9m(N^S4{!lK{GbP3(0Cluy*k2~2qF^~6wLbnoZ^YaZPAXe}dAGu}xUqW_p8*qhwC zkY%sgzoy}q{Yki&8Pip)Zh+p(9uDo%ArZJkkz(>j`uF_43^r*j!B(cusdk^b370sl z6SKt`ZVA4wVHT9MUO0lQ>}>3(H_L*TDZN19qnfgmu4Q@g9sFA;&py`>ImAnc~|LTxJ1tJRkb?5eGlWy8@d95 z49(Xk%iRWsu{1O-z2-``XpDD}%g)nKrbRX1erY<^xgPXM1~cMbc|> z7DfFreldPP|Hpljjh-5UY8tu|g!q-Gk+yoREB(k34|vNRFK$)cEV!QVG$c{*9Gh8&Fs9CP8CA4BV(2wJ`} z`ah#w%+mFf-2)(Q^ZlNLD~v1E-FGkNe6thM9{Mu2^mIde1Ro;wP=ld&+;Ho9i;HlJ zNzthG7_7*Qr4zd!)s_rd`dY(u=8!zJ)(JZK)aX2&-hNiwd$-Chcg3CE_k+_FQ#EeM zCrR~t5W8zQjl!teE0Go!cwFnIX9X>F+pF7{7>%uo?9U@X$$Ee=t7#p1cvT1C1nG&Y zM^PT<2@;w=PcEmOiD7*R8`ib78WxcHp1B>+5m}ChJ{z_3KtEO1hsO(8Jhj0eg9<}S z{co5>vH`8hOHWFjj(ku**{sgm7%S~05-?UDiz~`a2;7>l+qs`~#bzG0a|!eAU~}Yd zQ|~;!W47ham*@`LiKP)gj;7pT@H?grgOn}y4LZEsL)^*{A_R-4R9}JfM|kNZoG@4? zwpFJsk4T{Wldh%$+ODyT9i5x?N!Nd%+DhKORaR=_#gcd zP>!e|j1~m%Q%jV+y~yrohr&xt_*<#>=Og>^qMcX20S z1II2zS~McQ(a*Dg{-@#a_8gJI8D1xWY5KkloRPYk&2P^dZf(Ik@7umSrF!A6K$ctD zP2W+=Xo}T8j^;LEHI_=*!o>9o<@A&D<&?7ppRFgeVs4VyvX25dc>y6wc`ImOL`>2M zpH_?Xv2TeEuQO?jHb&?-XMo-d!tUR>&lK7H5m~K$%xbkzhdI;)y6m}NXOz!K7wK%V z$=y_@1TW&MNldnatp-`S zP3{bGycX0@k$f)lbtg3>E)X@;1}4&;n2&&Unb(PG*J7YgFxlB|WgK|ZVu8VxQC9b0 zPdI__n`cluP2`QTD4l0`x0n>NB?dQ3B5{8YxMdY7%Tg?ZKyy^w?w4(7%|gS+;ro`0 zJ-pAKSH~ae1VHe>t9y_*$N?lP!!wwYiv2G3eU~b*w@in|mQLQb`X`{v7K3aB$0<3R z&+BfuH(?a|iE^%OsIGgvJ$%0|E9_KTN{AuihPFK0YHsS&K|;3UC`S2|iSTOL0hj3H z+%ZblcYFVQ%p7xD8rQf(G?d5fbNSKL*H#0h-{CP;L5#l6kD$Ae3p`OCWU!XL5G5f^ zNne!oRgy~U4d{4ZP{j^ZRqlFqXcO;L_l7m>fMutt0x+E$?F7>fCKvher)K!EgA<7! zzzx!r4-cJO_E{JvUe-u^Am}6?jxdHrTVgtmB*h;Z?7MXg1iTr_V>D$3&EQm1Rhr~R zOk}wg(VZAd`|Qx`>kOl(Jd9kvf`W|#iWl)r=uyFj3fJg$P(_&wy&h52p2hu(V{tm; z${0~{$Y+21eK)ZP>g3qF7-c~*awaP7Hnpz&vUWjl*3W3OpY>mR9i55;&Fdy?&CJp` zIgX#Wu=8YYCM&v5)7>X^VE9F+6oLou%-(%x{!afCf|2n=D#3RT?_8pEJ>_Rt>hidZ z=Sj1f(jiMLWI2<}II+#2BcYlg(HbCRA7;9BBI_)D_}8x>#mYm@Y(&>WM6QA^K@~&I z#iusgEH;s|ahf$%_ZDBOJunwZL$z;FnMaN|%4{zao;v~~EC((lxxo%zWxviGh=|0Y z&KTC-YkHtF2z}hAwQ#-aUwdGrK9NX46-EN)@rP6v%xHPN6**PP@3{rY#d5Dxj2!1r zg_@xv@^p1}7UUX@BjGJ2^~=oYdrI$T6X|^-*{U~@O^+DDdM9OxO~ofTk*s%CJ#0@> z)+nLf2qfiLHa>i=bMa+Wkd3dOz;{>kzh$pI`s!qaJ6ml%C*f=8!kRQ)9z~92h`WXc zV-Tmw!=5^gAg!z88exeL*$vTfKEpfFQyx&WXB~miX$DfFg^p;5$PMTy z^z3|7^?O~07SfA;KFWgImw174*#l=@Ia4aB}mf ztC_KKIn>^7o>g0Csf!h-?uz3PyclIXe?SkI@DKmje>R43_1np!eO4`38;l66C*X7S zldy=i-4lBV3wY!A%o!=+|W9^N)CMu%1K& z@7f8P*WOVRwkEENDuv7GaQ9Sp9xq_kg~H(~lEp(?AserQ1}`j)V5yDMcZj~L(%xZ# zlT_Czv8w#Zd3WCQjqt*lWYY;xIojIYspl`Oj7brg_Kvx>O?FQbO?NBpK521ax9t#} zrfKj4o{1HSo*omuc?E$-Hf~bfp1T{ zdzC`+D^JsKtz59P%PgARm$KKkr3Bn5TvL$2>k@WI`D(Qt1Go+qK13}-91x$*-c+{PzYWaWw^ZxD26l3NPXPxTXxr0tm8SwxPUDV7-QM%Oq``#4S3 z>8Ep?N$QLMzwd`aBPv`XDun3a)UDsT{xZBvC&kt3TGz4>;W%G(cF=scYWEp!p`<#E z$@o`yUar4{2-2P3#mx@(^=-v0y{&lA^!_SY01UjU4b@qV?Y2h&q^UOoNZR0Zq7@tt zyi{JuV%V%zo!7_q2^Vw?OwSyyrh<3o80`p5tOof z0mDqRUncDQAXK(*hsUAjh|q9CcsHLRnhAf|cq@I`<(JF*@7Ao=(@WyjOYiuV)p(ugch?CQX4xgBI6@vwilM; z)fVtlS}F{)gv@~Zi1t$_5yWEbDQ&vW=7{+mSIa^qbc9D%)h;4?#hkblI`9|Jlo&_S zvdm_N%`-7%ryB)r>U7{5PP~ZmxiRtpp+7SY^<3mU5@?3JpW{&#@!Y!wx2k=|n+;4Q zPxkMptp7Ud#^C_gfg4{~2XTMu{$14=xSC<6?{rv?s0so+Ft`c=P+~5FU6e-Re7deR zgF=>yWQj>g&M+4Ps00L+NGff{?f{|#xAS3C&)hTKElIY#2sjPeuykfZW@6oPTg2&F zL(mQaf0-Rj+*!6(WStbs=?Ys5;k(~tdtCdiIGIuX31>YGa#{ziw)DQ8G+MhWZ6Au( z+5~Yd^hmnt?4-LB(wmj1ZZ5R9{8`5869K%B@l84m8X9+?d;>=8n>2%zfe0tgujBEh z33}8CIXe@R>JtllqfVlJplo=lb-vDa$)n<5cAbpR^Ny)}ooJtA@}h30|77s(kHDh8 zVq@gCDx z4J?c>-bXnbGL|4dssEI%H6lX~0IhMyHOLuB3vhVGe+O<{_}W%oYm@B?4Mq9}WN%Y@C9JX(a%eI8*jRnw^mRaRrv`Jx_I%l5Q@ob* zOP2%PpiR>W^7dkFMzH_rjLqea#^waS=2@F>&x%~$h85XvzkeaP_GN*T5xNiiZftCp zL5vs+kG;;cNXoXm-WEi>XZCDIbQU;*TWwzkM1;-FdSCxJiN0@K;_V>H?M@A1f|nok znH0OA@tg87uDr~KhAK3Q9X#hVL!VPz@uOGdPg@r=I=p-iOyjoGpoq}Gzf57>^C z0zX{oXVDAcrkqOd>UD63sP~T|#!~uC$e{n-JSS|IZ^C(EUmg?JyI4bQUmds=VEz!W z;Tf-j=396#&Jg~7NBtr8Klv_h5xYV>^l<2ff%|7s`gt}~fnaW@zoT{WI{6>M+#GHWV2dxx*HdCPT1Svh~K7ux*i3+?9% z?a%E(+i)7oukvbf$8sfH^Rhyy+<`lbtJ2bRd^bRc5cF}K*sFss&CS=uNz`b}z@{6% zDMg$g-oH9KTLH)qv-@cqgfX!@!y&-0$&*C7K4I|`dm7PV>@UQ|vv`=a;^dM#2p#x_qL9 zv?#BehKPie`v-S4@_aiye-Bhb#GG5Ydwq2C@BreJsP~C(n@+xBGiwk+x4!4(@uW6<%F-Yl~B8_#LpOW3-loMLVz zZW~wTR|<&vh%EJ|*GXhIAV6Cr2kr9rjJqf{22cE;UE61KjmlCwqee?WpeU^Z`99^SE~i7I2N^CkX?wGAuBx67jG(@ zJSyaIzQeR|*mg0Gi%nh^JDD=|jjr~nyT|{?%;^0S(L#se zD|TwV$frPV^Xx2tp<1Z#S98V2Rf~n1=gaeIqpr$4gNn*Cdii#>*{BQXRjzK)x9(5r z1W)sA0b-eAC&TK<*@k`f=c~m+9oQMD`JrV#JFB*^3INbJ1KI-k`ixdr|78qSxdIen z8i5z@GsWeh%`W@l5C28|^LJF4DS|Dk;dA)o7+Z?ngcstW*-de z?J8)lXZd!jF3+eD(-<(n({oeY%1n0%POfl^4N}YPx`?67JV$mGGs}^#_x2rhpoSk; z^%FSYqHJ8O@dUJA{I70b(I!82h|(7T9EE97+T=+gJ;;@dEb#sKWU-olQ`=A33R?{Bb7AqkE+Y{S88L5kL5k$50u-2H8G#5`xVLScTs zROfvb-)Q1J6)!%~3-T|k&-04}I&|K9)Nc&TZTpgxH*{PD`RI2CsJ*j9{qts`Zf@*$ z`X9NjWr4OBAet)f#bBfzxk5m>-!pK+8&WniVmppBgy2;n2GI? z7qeSkP$SHf)#i+LtZ}IkocCd+&uKrZVd@0ph4xHyb-SGl=x46(!6^Mt12zuON66_x zm!w-jxG11fWOu)v>#{o;-2YVU4{lb_$>Q%%7I}5X8lZlIK0kJ7XIhss7}p?aEX=(z z1?AII*Y8PV-|;UbG1L_~7b!ACN;3^I1+W0mi_C$M82_5=WKK#{+_?HN-=?>t*@$ZO-)pOJ2=MT9tTI;ZY8UAlLQDE7l% z7%`izq?H*o;7aBO)1#VMHNS!Zc|#FD+t#t$`7!F@j^~Kcm3YXZ`N{v4eQpXxjF)iT zssCs68Zl;!GJH0&?m7liI!m%3QZR*y!>0@eK#_v)L+>LYG3{@oL!V*kWd z=o9Bh*k)*ff&Cx*8vpRy`{4AL-B zC;RMVHM_!RtY&u_TUz6N5q(iGr|J)(pWBc8vF5<2cwfOY`Gr)1HP(9$O^_Oh!mzlb z4YE5c=5>%{PDMLAeh2PUm{ywF)nbe^r zvEJQ&XPId+#iokejkjg2j&_9k(EHhUI}_SppQ>Akk@=_R&&Dxo;0}3^Fa@VyJ z8=5WiW^A+38nHmkJVpS8K7}(9#})_1W2Y{RaBBV5VS%T0G$k@!|`g)*8y)sy8sD(Ieo7b z+~n2CHm^_zgIWr(IzbN9r(;sbT8|)H5}(KTW#m(_V);s*>Ol!%+!KZkH&bn5DN}(y zPlm(sVO!T2gtD>T0H%rKgN;tx5#D?P7Z2kBI~_&D4>|-QYt!Z;H;Esojy^oC9GjS_ zMMV6-|4*%tbJ95g0C8Ty??WA~deY{&RyfTW+5 z^Zwn;Z`h>@W3v1BRM`(YIaM8g@cz7*@9tD3hLc`Z@4a`|ys8-MgQn~aWgMTzpECmq zv;T{??jJ4Hp6B3cvEr^QX{~AX*<;0s7)GVITq~xk2FpcNXUIN~!wKB+o7MSg$*vyj zMK!H-p6<7evz1~(KExKBo%@@jSl1b3L|$DiGu=!+_RERhJ6hdP8<_SWEbxr996X9L=n&>uz3V=wm9Jve?Zu8!r`ZY)pkKnci2s zrFP9jJj{Om9Z_BG{W14$WOW|J1j9Kzmha%zEh2D86BMrT9cF4KL}n1*CDvFMMUKE- zpgxFZo;17@IV9+f(dIkr&I>VO*`cmQWs8Zpt~?Y|;INlAO0xeR>ZNlvtJtc$u9K(m z!Wd(@j61WuYD@$zJ4|^93Kq0_;l-K6XRVu~xE}iB>DMRbweOjyTVRR#Scy>Q#0;AK zsl)hO+{csP$sq&8j1?TZdZEr#Zqlvj!apYvpf|`fb)Tt!W&)j?%3s@@;;LJdG90^^ znH=IL>Tjod&vSRs6H!Zb2BB^K8J!J}eH_w>cdmm<#(gJ!T4b`DeO7OCXaU!u*o78w zK3Z84FS^b*d=BDBb~2Rn?uB8w{&T<`3H*BATFa_l2sM>ostO{T?F<{LQF$e(PIzI% z;jz2DyI!xmZf<9q;zW`0g(Nc&ktWHze!F*@DwAn?bdnAwi?IZ-Y&!a_980eQ-_Lii zOExFp{|=L{?1S~%;Y6=7nzDH_b=xU4O?t)aR!iF|4E;CwvwjuaT6pND!&Zh7?yd+! zxPE1s!4x;R46l`?=JNz;(KA^JcFrMQQ}up{!QjC~bqFu+EBb>i55%42s0H@5-Cg(3 z0enEt_QjO1y>Qr217eSTWJZk{^~9%sQX)Tlk%71p(LRR5ytzFldq1!>H`((ha2^Au zwS&%d7CUgs^DGjm>@Fo-Pf~#W`$XYLbo1I=I+`!c+mju1s;WoLxvFkS)L7(a`;#+x zX*&uVnlpj5e3g_*LBYg!Nz4n`wa@d{!V^Hbtas+ng9-T=i zah4ZT>A18`!D6%7)Ui~o$y#LY!A4Pf-k1sVd_!bR|A?4a zLOzBdIAGyU=mHxNf~@OucsbW~20wO~n=W!S>@-KEBNr@dhTVGW!HVVt;gz3e4+R?r zE^6vP2`_HJwmR9z)p8*6N~oZylZDL`nEG}Ygpks-t}zihEDDfzKD*Dzq#}V%JJ)na z2Rr{3^i!b#%O|I2keRLRBIoG z#p{GU9j6rF(QY%->TA!dHj*q5fX}DWV277-Fph?u79>um*S-giTEY`?MLgP$GR0v{ z)+_iz{EeSROJu0)6_eWC3Jym%BAT`lx;RkF|KSgR_}~9I8vx(%Z()|yjc2_yx%!l7 z0+9mbR*H_LCcz+hW$IprZX98g*SrT4>oxx{;Z_ebd))vx^-Tb`?_mxO$fEA{Q33=@ zzDE2~Pe=EznL_{c$Lyi62hr}%UxT}I*Smx|e2w@6KuMH8f%h6&r2VL4@s9S}!U9as zfQI=3ej+)jpHzDq%bfb2lneLLPz(fyC-O#5-1TN^`5^SZ_Lv^S^AKaSChur``czD& zL^pGVG-@M7s?6^)mqU`-Tg}}&5&t(Zw+#mgV6Q{@oIbL??dmoA%+nMteaE8}nVF7b zY|A4}m&A`clk^mex7|!G=|z5aJISOYi@5Q0(wcYhb4tgKZpUGq)9oafPDFUzp=-gV zW1XYL9fICF*R!9|7x4f9126qd$kZ5c(rt0Zu_zrnYfJUZmvw1~j|R5XX1?++M+Mo| zS}|c9Q3vAg;~17n89D^G6~lB4(awnWI+-Nl`)j8)zhMq%_gv^Z9Reet?PIYn36$Esah#CdJ>NCi;1c^^-^{h6)!N9N;w3b&Ytn!h z7b}Oi!f(FA2_TWWy~qe%w6VPqs5&56i~fdUEDE;cm#R0-DrAFJo_eTH3x96P0!DDL zN7WnsB98A|$$LW8&v^O>{qmJoj@XDYW^bTqziG>H_d@xL4z1 zN7>0rb)e4MdZh?QMjkG8S*>e~cSe?$BB<2{O*5npzc2-FFgrk&R|h+5&}x*L^Y#Kjf>Kr z)%NMM!LiHKnNai?wGHOoMwQvF&li2NT;KQ+6s{kVe0NKFElEj3#-uptoQ&5uedurG z*n5e#H+wz!`#Ahzu5LV@53}&N;$8gs^c)8$#$}*B_ymMZ0=SHY+?@D+` zSAkLQ4BQ(b`(OVN=P)FyfGzxs!DQ@hx*XvC$3Cl(h~EC;4}ZvLc+p9gUGpX((=F9X zlfHtSH{SRP+Ic*DNYgO+=o{K7`9F^bCU97mr77@yR19+ zNdPpnWx?MZ6?*^(`Jwr}thy)CTyDsA?&Jg=pRH93l5Es@`A#&4WT%wstoTqX6`;x& zpucFN)eSWrMLDq9g2{;V75W%-Os>5;tG1zkYqhkxe>|`gm=;u++|9)%nwXMVDAg*; zLdmR@{n40j;L34_zh-jBs3|}2kaFwfM%_DFE-QELR!!Zp%h=`Nb!jxyUh+is&$l{( z;+WEfX|*Z%0X@o^G{tr{_Nz5j7UR^3j)GcD9$YuzHqc5%Q;z)GY%^aNX$NjluHOy` z`PS_4O{W8Lq3HsDPzz3KI(Z(060Y-(^FS5*repJ)QuaMIT99t~KDT{0mEXzySMML> zyQuuU(PZ4j;oZv$h!I-7VkX8$p>?++C$ha!;n#t&y|bHRqf;Z0YYYZsjr;zKq`Re+ zJ312Fs82xR7E_%~Gh&L6NekoJwCNZu5DBaCEnBe%<(XPFh_g5!3xbBAJmcJcVVLc? zS%`Nx`W{^u@m0C55k}t-nqtA;MzjN_mYsDp*AA@2efvwOIS-}dAFpJNE19FkTy5^0A`o1o ze*I0g2E;cQh!5Hj=immBIffqT@9cW?ingxp9o93^-*C10tT8Z%L!4#{X8_e@kBo^GsfqQb@U zQn*gwc2P@@@Mym;|8Pv0oR`ZX$fdl6CCtAhmlQPs2>g6zQ)dAUOJZNe#plsLPN~g% zuB3)=ujTHN0TH;%MYX-kR&zI-@ghGvndNWiCu%gs`4>8!akZQ-&hf&qm)eL7e&jSU z$_h;1%w7tLQ>kiBgABrv*f~@C8@Nl&)u2DQ6@>TB()6ne!@*70_m-rNuE`sDQBVzB zQdg;en#F2>Kd+8I(gmVfly$`IuHKX>$(w+hlDvEL9u>mf-lO4PG_jG++%uAS;6{`% z0Mi5*Un0#yU@m`nlOSYF|I9{(G;m_6U@M_hqOmp0?u)cpA8vL^V(+6t9Q>w`OqgJf zaTdX@F&M~y4 zE|gG=GwwZRc`NhuPE&Bnc<*h8ET=Y<(D*_l#94QQ4&w;e1+k}eC7CpN~2G z-3OFdOy996Na|PWDiibbNRcDNm(f##aIptrHJ_Xo+sBLI>?2@&*k=*e+XHTv$LZ8u z@h0WmpT58Md_;wJpuNu_GYSF%IVKZOwgmP_^Ft+!5)G+v_yS!{GWgU zBh*C`s4_Kdq!iyU;6z~NW4g(3=r&U$+pqc<9GSW3Xl|6PI~p6`fA7Kj(_M^>&RD|K z_~4g!FT%itL&PnOXcIJMMPu9BQ&u&7DMd<8Yc&DYKm;x|X-8z6R44l&UTv{T*Shy4 z7aDV@a4aC&fTU9&`s9%NQS<`}oGCV4ap_kw!tON?Z=GimLy?O)yf31Dorb)U{Wi+- zG^p-(dIC$L`J){IRI6$UB7?n6;4L7d)BVzyra0K8$f9{As)14Cxp`~fS&HtgS=d(O zu#}tn>qszZ=e1ta`m)011hobWCOY!%4`h~?pOb&*Avt*-Mc@!YmKxysZv zf0_rHGGXhOySZ;CcxzZV(G`A zqc@NNai@c;C9|KiCAQ2go^vdXGk(5A2W#Tl64btU{oQ5)MR$Tt=@em-qs*D}D6@n! zl7P&Na=eEWgSYB=hi91y`I}Zld&2YG&FFJ&@4XjB{gk9!(A%7Qv*+je3#)n3wKcKF zwLXEqSD?-^^TxabFZVEDe?K!|CG-sN)|iX!ZK^f!bJm^KS%q15ZbkNOcONq{am1|B zRt71R;3s|q?v&yuaRZT=mq-ePQpB9XY&-KYegP2$7#c^96QhgXipW=r|Z&*Q+xuf^yCC((!aOIDB?>e@$&9 z*w`5ABf=rQS5e)_PK(G012KIapX!)fQ{V+a?w&Zqc^xQg*o8Fi47CqW(RLpxlCQ7f z`iY5Jpmq1~}Dz^j^1m!$p&> z83$7MH|seC!!C(~c5#!>OpI6PLK;c0rnjVIfn^ zE`jlAsJD1K_hzrFKTBMx2{rTntJP(R0#UI_pTovNc8O0c3A~O@OH6lv^xEjZ1cjy3 zPBbB3lRFcV1jBl%ldG_eW8HD6#Uk2fUe_RDT zOoS?)6jv)l14ABRg2REv<3%=5>=EX+;TQ*3llWIQ4xc2#Qd^i-G z6H3>qi-SQLbz;4Ji6Xl)dQ?tajK8BjTWkwxt`+{Rj_`y?%1OoU)Vc*?KZ7<|BvF)ZDLmhT#~nnh`B$MC^II{-3)_ zisooEe>b4dA@u?7!Zo6Ge?&?ifwHkIN1l#HthRH7u|9yWw9U#@^~`ApS~ZeF2a%_g z9`hi&Pp(N_qsHHW9m60>#bMHHkRE2;i|B<+;$q+<@G4-=jfuS&@)M-d9&P@@bB(7f zajP%ET*MHF4Rl30iv0{C10xb3--INrMHE;g+5mfHfs{LeVEmi!f7W~INZ|Sj>m6!9b(y31$*d-nsmIar|&OGwDBe0(F)@ik;)oz!p85DeZyWbP<1cOa+@M3D)r zmb2+UU4ro=Vn&(*a_#A#ZPIs`fB)H}{3iMLpUu-hLGv_|y^irTyLfl*SZ~hU=GWi} zuE`2`&Y-s{yB!Bfd~Qm5yX)rkTe0)qqJ=La=r+rXxI=ME-xP}hB~*y5c><=8-@%C- zUr@quVMcru6A$A-_6-sCv~vGqKZ{8HK&c4T&1_ng+zJXXS;@3BS&L}5{qzbwbln}) z+@9K6FuPWZJ$29IpseuPMOJGe-@cJD>PwOJhb3%rK?fs z0$T6M2UMWx&x|F{FYc6aJMNJ4+C#AzK*$rL%I-(h%9)?YRrqH_FfNfoGgtt7V%%r~ zTWk0kxX8il9S+CaO}e%Dy>QmJYbwOM+^WauRSO4xiR3VdceDY;x-$Y)&09rTVm)B}A zxs3}W;S{L4GBTcY34CEsR3yGl({OVtEfqJ9n2u9FTzVuClBAQWK!Ot}DgsN|%oqBR zjaL#O%3@|zzy@VAXzCgsyz;bY-cc+Obvp2a*n-qd4e93QLhL3{SKm&?o0jN)P78N~@?Cr6>y1fz9frOonQyN%*-iS}*A&b>)iFf5 zzeM<^X8NO)5>xh+c*4RT!GZ#@w<%L%#E{-ST`9BB5fx+iK7^Au)q*Mo-J*g}Zl$Dl z?B?_GNkdVo9f<1C4Sf8RUFawq!{lPl{%e2wqiw^v8)Q3rWFbS%aVNT_4QS%jB8fL9 zk^ghM6Pe{m`&_NIxmk|bE0H4s_Vbbx;BPFA%j98N{PeyM>kMc9cv}5 z7$_E>nQfaclngx1j+BtLGNtWV)Kxsiw3unas_qR_1>wkl28Gb`Y*qjZ4A7giGtgW2 zSFa%B330O-P|3|wT{|4-!nG8E9&bz4#T>0%R2dQLvMXvLiZ{G~Ngl{$6VO7*$1Q`ZX}XOAf_r1p(GQ$toY7#!z1!zWdRFnP01pm?bo zZByv!ymcRHtAD7=!NZaa88@}-)uWf^)rRT?t8=@>=>V%tMdJ0ojWzOg$r0ve2Mg1C zIW_6s6chuI@M~zR!)svb!lgQ09*2<btkbXK z*?_J!N6OZcn4OV9NdACF7C(CfETcOM5?L-EsKk5@zwQp2HP*oN0-; z*yMFFiO*}Q4w;>u_7!%U!YUtOPAd5kdEb&Kk0U5y?`!-8(|uaJdWtm`+;KE>RZ*rq zbsXu%uRr{kcyCWYll9yge-!C;B*#70kf+Ot=-bhH9Zjmm^yeY{ayEw-pF}0tJ^h1| zh=EPy%WOb$ulnyj45!Fo@HU5O?-Na|_ynaEGjPN7 zos;*3*J%|3+WQ}FQw$Y<6H>tLzpwo(xI)64H&mFvN`|!Pwr}mv`%-Cq5@QB+JIv{ zRb5!};9t zt!y7E485WvyxmjB_>7_h@(AAU7gv&~ATK~&BzRAF(0)KV;X#LPcEf|nrpI?VvdP|N zO0emn0mgJT4V=w|HVSD%)RKwYXA&br<LhxYo4&(FN|&|E4aH+2KuIandP&y zY71e8g+QLw=B@j=t}>eCHAEtk<}1gKDxIM{D|67MouL*GD~<{Uim(eeW2t9X_HH71 z7kXqEan>k2P{sUAe~G=0PZq1`H>NBL+ffz&!C@QPG>!i`My4Rk=9{7h!#3=Yj0YCC zCw(w7+p$qygQEd4&!!pmQHVYogu~Q%LS;OrXnQF6glG83=Q<8Nz05QI5a!Vk-aJZk zO%3BX>ZF#_9=(mF#%VWd;Xp8=lWJXegrp{qT0%kjyK1{E>bk3n@>Be+KT2rcR4?kl zIgJv^$(GSQ!FSie8x@+#Y2sOJnV^5J6MD){6OT4((^7h~Z>*XImoSo6vvx4yp<0wu zzxTO}g}4&Ek-I1@tPV7`8}M37h2+$vR!(I3lSN*gDNO&KZhLzZX`i6JH_(ukug{N1 zaM;1Kj%h7>2Qzj3PA8mwXokAr8LLP9XJLy+RP#(1zPT=k3aZ?tI*%G8i(+d|CnOV5 zw5^(7Swch$#{Ko_pWzY$)U~U~cb4V)%CJ5mw&z={ zdqwb{$Y-OT}EV*qu#Cg?mq>Wgby+Iz?ga#2nG8GdT>m&Wt1=jJ%9IEHhw8SItf%8-Ru#py)3QlU!Z)UG8 zE&RT@Xj2f7@mkPAT?aKu3srLk!t=#e2MkP98#^0`T1^B{6E5n@5ZIl_C}x(xesBlc z-9FnKK7YGfRMV@pqo;V^$-#4eGJEIn{RbT#JZ0~~vGeeq!#C>KNlu$b;BuI6!5^@T z+vfj~{dQBGRjBo?aM0})dK!X%V6{{)z*(}GF7gd~2;$=5d(|KK3nFY$-&|WSPcTwK zT}12w^J4J1AP33SI)8ay$bJ=FK(AzEdUB)aK3UDK#@S~y5ACE_Tuv9~Glg-hlNZHw z`}QJVo}TBYY8IE(>a6|{4`EgpKpnQ~kF6Rq-^_55bqzh7Z1Ux_%uIFdnmk?6K@=S^ z)%a&Q_+^6s_S=;$UAorLBHzneQS2#vrz8-~JDF=5eMQw~E1K%8l}Keh1`v{7ALdJd z{e=k+$ghgchvbB+=At%c%23&4XXlDfMc;H-U!m{<0rl4XlVT2MP`H5R&cLA7pH7Rl znsFBo&nCytCQm;yS@1ljK!WGh={e6~UR@G9Q5OPOx^jQ!PP06Z--Al<3$f3_b@YKz*0f=4@dE*N|cG{#kXp%<)l5*_tZ?k55^jM|N}b z3IYPcS2M-ZSIa4Q9@!3l`1}84zkyb2WbWCpuC8U?Tr75P?C+nzLlB^lv3>~YAGV}G#y6-ecm{;$oD>IxOZ|#|bMwpJ z(~j7AE0BCeUV6LCoxFD*X9M$>w+?~}dFl;_Ny-jvxy+W&a`2fXXVb%>{);{rYxq;Zj)6B>VN&eMOYE;1r~~-(HQZGrJ-r@H@xw zb)GM}zSb5+47u|a_?-X~5ilQSAFoymh7(C{i`D9z^K}&eAL)9C{x1KEe?j=u)B_R- z-9zM^=ufhcddZN)V1LWz>6%#>z*5^snc6Nm#Q$EizU{C{fQC)t-JsJ2I9@^3=X&bK zh@#BnSp4a~4ZEErntAN)e~aD>k7A%1^MrUl-i;A_ z0*@n~*qh`LI-{1T`ZS-K*XHWrJ|@)?_#+^;8X)9OXf7Q&1AZu6(QHrp`(ez3-cZR& zC-7^-f9E~0P5s#j0v*B<+#=ofD2B`z=`}DVd{gVtggA;95p)vk(Hs{rSBlXk830bq zYL3LZP(3Kl9JG0g_kymlIbX%ZRzL*R;v$C{G`ZqNYZ40Jo+36>!6~mWRO$r8C(r_{ z7K_ydzXb8ll5``PM=p7t7@*sY7IzPREUs|>0@sfFjqJ>@3oBsXb?B{;Lx_i+>;@8_ zg8RLgh?CS!Z}BF;f9_&}dY9Rr=0l1);5|G7?zhyTE6+&l1CBtyQ+)jRcTdC*+>#Lo zEU8z=TAvW-i{WT|ns0N^H9_FvjKW{@If&qZx`Ksy`x}MX$cJb-K}o+Tb&<4Ipqz#7 zQ6Pg{p-!=`i9O%<%di>Xu=NcDD6Ls)GaiTCdA~1^qRAg~Mqe&{vLrSxG1`w-JpF zjPHoLq(ABDT9KJzv%Lb#8NIYme)xy~YE;msZg1i+1pOTb{T&_~gSBHs(?l7OPcb7e zNX0Z*8cP}<`>#!a&wykq;PmkieUtUTjR4oiIKF}`nO>;hEbNhOPvNCPhh}0=WOOYq zQPYcKD)zMu0ln^e68K5e?6op=1%X2H&M%GU*=cQ2jeM&jep7%dwm}mw8gx>{|LT|T z&EEaxuez$@W%n}4!n?n`BS{v1%lh)Dvi>n7ZK+x8@2rT;I6XtLC6&JYoe02>YihIC zU+W*QzR#Z9?!G?mqHi>vcHj|R#TMT^pKwYQ`b}CgMWqiQmdhx|Mu?^(_W412>Btf- zohhQ5=1U`eQ}5DgKG3`P7CSAKZ`h-#nr9Jl6v2#!X{#&2xf%mv{5#YX*zY25-Cpz^ z6382N&Lnk27UuKu5)5s6AKnL-y%!xEcbXKg_F5BbQ6{xbbCi8qjO(kjvxt7hNu(#I zZnJ9yQ-5uIfJvjzmfsl0n*46yQW0J1MlTGz0DhX;G&BAqP~w`^oiCMu?uLLseob8X zdQsV5|NKv!d682j!XV>n`64Sn)Cm?L5YhRj(^u4JrDmxP+*Io~;fN{1UBiSLoPwO- zC1Ygngoj4+nE0#-LYNu)JAIB~mUWs;k(n3@%AT(;kL1SZ$W3P#fjN;!~ z8pE_+PmxC)Q*pM)-Zpq^_}k9z8Ogo(w_UH+gxL+W1DNmK716Z#r%110V-QC}OU#=a zO#o|XtP+HimKF~fW*}z+*Q6-UNreVkGUyud7t9vt>OlojXdFVnT{&_%1sd07wN|{= zXG>zIr{@buXKLR;4@d!6ke-&SRgIUZYLufQay2KzVi2Up6I?WhsM(}$iq) zI*daz&H_!zMU94^$_0^k+kz{M*w!&B#`$|6QO-EWR1oQmFd^9^5;)T%@rPb_1I~Sl z>9r3~jcQMX1)xqWXwCrt_g;7y81?O>%wP9H0LO`-*f>3&=>+QfFupe(Al+{~3+z2J zf87x4GdlAdA7RPH-z>v9h>jx1F`WH9IdTM*9%bbh9?tNtLB4jH8f4w$g^v$)jzLPA zu9i6tJ{?AIr?JxqiBA2`5knLunxfEzygyv!x!u?ZUH7)#a?2V!J2B06k)8SFc68^C z_`HSesa;r#Wgcj_QgnpO6J_Tm;L~{S2b{YfiI2;n+Ac-{6j7eqpLCq1zUIVT@-k=x zb?cfsGTodMJG7cK5pqorXbT^?i?3UJQW%lR*Ec%((6Fz_VNGp}#Idd20FgOzP8DLN10o8VgefT;3266B9IdKU}r1v$XZuVvqR@x+03krs9u_x-HSS&s*6n9n3?(nhtot930}K>GRyFi{^Q8jmip;3eK5X?*RE4pf5T60qz1P@JEd2 zKs^ z6f9BJ4>7t4w?)NeP>45_G0xmN$+bmE?{zE%#{neD=WqpT6g`)n^y%p zH`8268YThN6js#ye@fM9{nUy+Co)YYK z09~J-DCFC8gu6T^{^~|ThiY#naoO;(vXBjE75IY-ev2w&IAm_CpeBuOFpa2AxOX3M4e_7vBDKXv;kdoM z7**q{Yir{vnNQT$zv30?0xy!of!V<1wP+oRj10+P=1!EO(RfW7)j$oJviQx_`QnS% z1N8Meis~{#6G4m^coqT)pNohye!`G5{@oK_0O64A25(6x{JP~{&&*zzn_zoW-jz1$ ziuaf*hoRJ=QQ0IUa0;Ts15piqwVBk#VorFW$CqRpCew-i*z*aGFc-Z~xX&~sTx8Q{ zzlps4cq!VA@1A5-G!E0HP1q}sM~KnK*V=77oj>pB4c<_1ez1LChPQO%rXAdOblhWa z`UcNE(V~;<-n+m0;8*$dmz`brWdFi<@11uJ-l*>$$I0u0C?-&zQy*lYd4MxSy1yDr z9OcW^^6G4LUPmHeFwgIi{Q?4QiV7{Ho?;tQk6YLP)_D)DxyJHCfK$ z0nz7B4+Lg2&Yr2eZn{+%RxPKB{XyLaMq6g5pj84-&rQMhJ`Tf%s~AJa?NAgHMB*Ea z%#rDK<}^7B63WUIBpKpF0CgcDGAruoraCDI=`YFx7n^gf8PzLIT77qw%~lvnp(D57 zx=)P%Lj=b{GF#SD;Ys`wN!dI^URO_lq zfVW&IYH=mQR_7RaYSux^g;U0Bo|CfyVg~BY-=1SuQ%snFIv~|xm7SQPOgdPWo#k(AhvJu9}_d5XO}FtGYdQPo0g&h-xW?7-T&bG5f<;vta5#l_O=Cw}2^TRl zw)R#Q_bai$mmi8&<|A1!Tj%>y7+4}RZOea4*`vnH6b5uDz|lbHPjOj~f16jE3rO=k zPy_!OYe0Z%M!<6zX|r!&u1+B23Nw{mK{6l6cBO{E)vtMUoARvl29SE_@=EB3M6GJS zW1})MW(ClHe+!y$P@{*b*S;k^I_b$Vbfw6C_z(XbMwEH(FccU20DbggJ0b50nAf1Z z!U2XuwQ7@XC^GH14&2j&EnP)em!(QW513)po*?w?d*WEWWosgTL#(7ds00ot6P;+T z=Bv2P)7*K&E4bpWiC`@uQ#r`wohTJ!6q2G#AXJtN3~W!Abu_RNIVaQT^|zhKjO>-^ zOe1yC6}htK=F3s`|B9Vj+wbQmD%`iGqUzS4-@r{``zR;VOmJ zdYfR+=*JaQ5Jt4Y(W3x7EtbUw01xZD3IWOl=j!Z?uQ-Gso;bBe)dn&$Oejcr!t6Sn zKD6jnU_4VmXH#j;mMEBaHN;kB72PHpi;kd}lt*@Df0xjoN5N1dla0qi{jDX;mWT+t ze5rPJ1O-`}Y4c^|(<}P)s^wE-4I~BFCG0RU6OOIWya)X_II4A9p#AVle0W8WZv8TK zC6nNVQ^9@%8cFYvFqS|TV>B@Q=*oU{55Bq=`|RG>VxCzYcnZQ+DX7V>%sbc%umRgw z4rwNq#K2lD@pO|Nx|b*15m1-+%4k67j;Or-1JkfLc>iDc@%R4;$Tg>@sOZuRw$`kn z;v*25C~u`5tb3F-GxKxD4deGU^e9BYQno&6*x=9kp|3P^`WWQ=rMpf zn5PS4pFYzPyyWq1Ar37hTi?;|NNA)#RrmiEq|pJFP;|U$h~8&h3^PGeV`V%cOZIVF#d%+l!q7G?SvXo!sMHAx)|#k=5|e%{a>2J5Ir}>5a0uWKB=`u^8o#31kCW;rI>E72hIa^>z$GVnm0*)aP zwY*+uFU61?F0dZcTpndF=`UEw8h#2BKO*HCc@z5krB^u=zcjgWP=3z_ue76(@VxRN z1K`ptICG^gwe?6bL8?8#52wFY6b150xzp!#j8Jyj zo9_T~C$AF>VH~h1e7!)?U=IIPfJM#3A*mxUUyH!V64#E2%nIo8hd=y1!lTF1*|Uh& z@2`85o$zOcqMkI4ey9G60!_*WR+@{-Twvnz!m-tELxKqJvlm(ULVQ@h08qWad$Q8^ zBwmtbHednv#ZdJ6Tzz4(`h8Uf8o~-wSge-S6g=>(k_>aEuzNNp(=4_Z1>6j*dP5yu zj&#sy5|wCyYEv#hPO0W2!UOHDPXvW(0~mkr1dI%-14Yz-zic3pg5PISCVB6dF6*s{ zoe6fc*X~P&SuZVPPS|0tcHtp>Fm&&0K*@EtVY_u5o0ZE_1ya*mN=+|opBeXfKj9bn zNRQui{sixP!Lzp{VC2&TVzGk3mdpkIy`1ddo5?!zPPfUbU+V_Lf;BZt$fo4&dgI;Q2C5bFtn~JVIhves|=zZV{9)ZbEbb zh=7{HNS-zk*9U%%!1B#xrgShgD1I8P-5*k-8ukAsyY3vy2m?vL^Sy=20VaLT@1BTk z7#=?XKYV`TtIc_eoj}y(O#=-6HC1!3&>39ur>~br(X)2=r-zoa%?4^h%WOT2Gfix} zRc+u`wVW55iSFMdl0tg|Sw%E$^yua|`yyYESpf1OEB+eN@Iun#^X=QK`P*1b)wSd3 z+##b(fwaW5R5`eQEYLtkH<3~OpH6pQzf1NDGmm29kK>yhZJ zP}N9$>R8Ab%(yx=Q<9gqUxgsDbt0oda8IW*t&4PJyilE5-ERH{Ird=9K3a$y#Q<%Y zZIH#L#SR^|8{YizhyS9UAPRZ-18>EhqM=9*4BS1DxDS~ktUu(}IKU{wEM_rCOLrcp zC!rK~T?$g(lqcwBNObN)s|!bRP@V|gaLhxXImFv+hsk!GJdP~R02B>@6FXobPJrlg zck7$kyjPRab1(dhf8lUNop|1aG%49f9FFgwv`B!4EeILOSYN70VHnhh zR}EQ7D?F*dcD82Q8E)(xbPxkG%pBxjIe2>DCQ4{%u;dm3=FJ&Z z?idj~yY`Ug#V6IK@^F_a)E;D@0bW=)1-L{FZEI=f(;fO&KD&TElW(Nr*x4KykVjJ4 zQL(V)Oq}?r17ea6hu6I?SsX2aLrnuy^9cb=2W``1^`9#h>h9UhFRa^eTacx~$li`r z%FK*2B5au_WZ7X95rJ*G*lD9YB}6syMpjquh1Ty$1!H7GFK%a}%nn@$-D@N8g`v{{ zepbfFIf9gRwkhJli#K{({v)kt#ZL9z*V3!G0<|@wxmQ-+CN^7`2)KKxyPcCxO(rln z!Ca!8jaUHEVjhla=x+kWqCB0Rfy2^qPZpo_pCMN#E=;0ocxA?vnG;%uU_GN(H!Wor z-rG0@0#w`8?ahSEozCfe1q>^9<`HY&zE^5Ld>8}ZAuL1O`!R3>JCJgja)nep(V8pp z50=LiI5$SZQ_5Z+gsDQ{L-TwE-wG!H0*&Ek2A~l(<|)9{G9v|C`GOQXFU)ID>mCn> z9$$pJq`>n{D}Z8BvSFFN89D?IWchEX#!Cn=M9~BT6`^$^SR*3H5kTZ#OIHg7kD4X? z9$IHqe!Wr4wyCxlI>E{(kXp(a~)>HIi_ke($d2J~dOk zMxCjK{H3u{?x3XmEtS8b!Uu>rFBxbeOPQL$k{xxi_7o`b$P~gU;Iq%R zwN7uQi+i23wPcZBkTTDWGGD4rudId+JJMTdvcG=h7D|2Hnou=XC6Etm4aMKobM{vM z3??xLsGClQvXH8t%ecLms+lg={j;;=%6~92-b9q?8%s&D8#E*$Fhk)(r^F?EIX1Z( zu{WNg?uf$XZ0%JYsDt`=6Ns-CgtMI0kvYmS2JpR`M^wHaN^6K`xD&2AI*$T6*_q|Z z$PQ2_GYqJpuGQ1gP58C?+@>_4WMJ?=Q-_n&r#(Ul$XH18*0u9s0tz!15!#69A8L0t zi9XI!eVD`rPA>#HMU&-1OcbW>+Grf@vPRI3^UL`=rBl7B$&|Tjn6rkG>oh~LktQUE z6};xlR3`vr7$$d}nyYol)q9bj(S@^}MklAk%)Q6iY*yCln$TjS`*i2f|=BIV1Z@JP7Ltum-+i2 zeDGdh2G|)#*5Uo-2X}=3H3-5X;|)!nh|UI9+4R|565v`qv<#)7QZ~Ah1(mUQNOdMa zSfIQ+?5_(eq;)*Wt zZ(BlWq%V4P*Wp6pwaD);rcsCUU=T|>1EnHx7;syV5Vtmi>_ z0a)_0XdVbl1MGsFnJlXL_9@ijjI7dji7g~_AB-~nCBl!2vFk^lm$mogDL?UHtRS_+ z=v2ks8=RlmvH3x2=*PfKJR=4rgnz6YsK_=C`VAMyM{WtrfrEcTO~C0fvqkvEnbQ-@ zrQHu3T4v=6G;%`PXTrG1bc2HMmf84l zzmV~ESw}O(X}&fSxn>O#Mc&-yz!RVyb%X}Nr-EBV9!(!^|1{Zlte|Xd@XgT}$-IBCpP{ zGPr)?0n<_MpdQDh%GGXV@@0r5!oLhYnEM|%H~>^YtH0wrqm@M$%yIfFUi!ZglY(bc zGI#1ScUp^6Zc%`;dy4x3$GMi$Q*>y}qv(f-uU_|ySog61j%?<1n?xU{mBDiTR3fXG zKy_0S&<8?4GH5-{_BqU&LPX1X?at}wrWVk^&1IOC7df|ly>zzQ+>(7r#R_b2lGiOs(aD0D)K zu-txxfC};~<<_v33(uevAp||OTn%+vOFsp}9>O#}im*6di5cP4`wI95wG1f8~Qh`(bE;poeT_&e4R3lQ3NSj08bjE<0KNDrci&cbF=L-p%xqn9UW zYF(NITVap5$?2}B##W@ti? zhQaHp*EBtRz3`egOrY|bqN|tNGNSk(M?j0YBf?^}^T#RFrb{Kj?Xawvz+UOWAP{&X zQ5LaKpF54zLHRI2fcjSt%j^35Y%Q|M^~rSSe!N4PJHLZO7kxWPcGJJ3xc9u($n|3$ zJQQ)FiCw;GqNVN9+RCEb0CM3CbTPrNHH-1A=fgLoi{q=RBtF*Y0!+01S-!@!4T_s1 zwVu74>9@Ku75g@Hq1Rl+G$>c})U%_8_iamAu&|;Limh%@BQBEd97-AAXKxhn^Mh9C zS0GHN_|jIBkdY;}(Z;k8RugNl#rv}B?sus6;UGvu4WUiSRvloBsl3q!1JC=8ESBD0 zjsjkx91FF>aRN$g8Q%w-Gyu946B{JqH1ruC}H~zg4MkyH|Q;CtZ z2+iWCsRS2Q`HgIY{CGJg)eZJBaF4E6lL8s+jYy%HrGtxH_X8?Sv&Wq>#cmq*LJLU_ z=l4<{0K?`*5nihh45BAr346UwvQtp%TL2iu4{@fQa;)`WV~jLpYdu-eL(DG4py;ns z2qa3yrJpDIq;n;DB%bW~`SFgQBcB$0p1ratQ`lk5TRpolHyFmD&@_m=aDesTa$2C zTRuBTcCh8kmYr<*2h)@JgLgmZYs+`Wk+%E~-n(nId_Ginz)o+t*%;seMW2|ty;1BDt55T+PRaT1Osnr&+HrNe6sg{1ZUt($ z9C;EnZqvA$L44PbSJg@S?>56KH;LA^OKtc~cPJZ#O>6?BOa9>xf2U>WKozJaaBKqFKmo8VNlflNBiG;F1KI{Lsmwi>=}y=7Knlp`P77Z z7-_8*O=SWr&@5{|K8Um61QlT^`?oS5R9x z-2zOn3BKlIv~5LRDETqD4p6beh$T!<;HL*(Xp)3*`0}R*WL+hON;U1o3-Ud%z_dc< z7SQ!-=pq0wfCVN9`h(W#=;}1zNPbea886Cu{0wK~x~xLwVRa2dlTEsb7f6W{wU9+U z%y${;Qvj6b#F_Jcu$qrFC?UfX*7rghzK}Fr%}#17O5+hSMgWf=&=3ihY^M>}=fe&V z*$jdmqL-fdu4>9l3~0i66Gf_yNQ{_5DN#LG2T{8fUKYuKUEJUpxrv z2rAMxnJ!j!(V5f-I=Z;Dimd4;+;bXx8iZ8oYQT!Ji+NT)w(rnxo-i_!92M6n^J(5< zuSDA>X)7V^n$eJQfwd1c4xc!krZ!~2quEo{Jmj#)m=yO}Qf&qIj$vuCEZaX2WXu1G zCc#C-%p~S*ZE=K>(YqMxB)fkVv2-7JJ%-RD2^#PoYE}icFqB zL*JVX1exlwgS`_LmegZF7Vq&}#`YiM@c=s?huBHq4#mfSH@YA$*@+W3%VHhHYL(oewMrbPNR2x!=Nj0z4FjM|DwD>g2(v1vu@v54;v$JpOQ?zXB*uj^k ze!~rH?c3~LQ@`%Mh>W#gnG_FmaGGO<$gG$yaxwzce&*^rpBKayq33LVS*@V*w<&Uy zVNJX>*&`syD)3W&vIo6Ro7e&AmJTp7cLoN^0zR{lNF`#wOu@2ivwlH=DSs!mwZi1)}*=Q~|?_F@V|9&(g< zvqs*%3sF3+h+EMBQ-RZq@uFCss;zqDiN|=PWDY*-qaXy4+=f745t%r_4;m8 z)^|oeqb_-Zk!n&rU+Z}dS=>;Dk!s@jmhPx+ArK3K?v{x9ve^y75OXjVUnpoo+g3Nl1~ zdK>y~wWA}4*|TfP7z73)PmR7`HzsSK!%|Y(SRp(2wVLEiN*k*&l^SrL0YB$86)duO ze_ptsY5E&^1svBGMZSb1sb9#63SB{~J^+c4pF~OO1!`xlX(2sQDYLfl==NQMeBZf+ z73!^!eM<@lTHXBi;)Gk0)4@&Tn?l_8_A*eP_v z#cfG_sGXFx1Gn5Z{2KR&zs_C--{b4&s^3@8Mbk#I=QAN>d@}4u4C!|9YNM@8wKjgk z+&*@G2pC7(zTh96XF8?8QT7y0i99O#T8RVruf#SCv!h}5G(IH(=4;O@PtPniJ-yj9 zylu`C6iCssecgG)QuX*~aI|i%KmmI;MAVUA||C|9Sg>)i=652fF zr<-Cy+PY#3^M7bJ*BwS-8g%{$v!g;|`t6i=(4T@9gZ@6Y?1?x*6ZWq@%F3rsz`WeV zzRS+9x9|Z(fkWIazC1Dlkc(JRnB)wVPZo-}nP(1UoL&Gt@RtCNPbDOTFlgNM;fK3! zqV)~UxNcFqMc-k&fx{1t2YM*skux;3kZ{1ua<0D^8Sv6C^T|lUor{31N7>h(!|gLJ zUP1A|uXPd7@f20EuzwS%UFB%E09FnhnsDV>V9+CRUk*)=LP38p!a#xwN_8Rp#_H#n zK4?0DU{jn{XN4#V!inU~Z?3B&L1j|@udAn!WP6Kez#InPvybpbm#_U(0j-`I6^Lwl zB+3dl(v0CS1~aCs3dvQcR6Bq!GLUi<+8;GGc#4$6EqEo!Wl1N;!56qi`{2u~T`&f3 zY(yG8oIx6R@T`ahd*N6v2I;RU-srcgWp$~Mh$heX|vhy2N0s4<-{WtdlF_g*2r|2UfuZLe0H;`G#f zOx#Hg>DV-4&8?py#Y)}|$>o8};ZeV%l$P6Je!s*iNnpN^Nt|OKXVy%V^}+IvLL2HI zq>%og3%VZ=CLi`dCKwIsBWOfFTVcu&7u&ht1AR7ftP!QSU2Z+-!Uqk9$un@!ZNe|T zVPEQVpb_AfP`;rLp4r4zFYg0*qF7R6Zvn3xBNDnw{v2ku7Zv7_lEpk!+xkQnJAbTLGGB%_wU)g-tI{oO5X-hZ~|Jo6f41o57ZN z%~Y8ktczXssMoaQ+kq2_L`c{VXpk_|3kO(}8@iKIwLVbRB7WY@BCbvBKz*O`tgS+2 zq+{xMLL*-v;M8W5Iu}5WbDAKll=nQrDb{NDr{|05r8B`m?;&RCxHa50_XL0OFxhbN zzRal?FWnpLx|2M<>xZzn4MV%KKV^@_cehKu47N#I2KGET>^7WUz<{_D#MgF;ikvA@ zbgnHHnxui10gJNh0@REA>|~a!13z1@D%b$)(U)UVSX&C}t@~abCsb}_P?+pWn)A^M z@MNV3mN8)wM^KY3L#idTW5|z*cJD<&B6GA4tqWE22T#oh5v2+D=p>uBKRyQQ?51|L zDu|mfBq&`AKstP)2#bC|t07)cp-M!B*F_QIC|e}=*`2f8QSm}Nikf)~9~5ihGD5Ky zA7|yq%`N8ar;u*3-mKJ_EZ5DgG|$CMvuBoRw$ccbnl{vYJOrf;4(&KiwQ{PDaOioK z8!3tDf15<*Q+?L*BbDNYAA|3Cx%QO)!h5W*Z7arBbw03?6RO;r3eoc#X`ec-#1h+1 zWsL^&w>hvvzq8AE)rX7D&qUYNL?knog*|zbJiA(M^UDs-B%)y_Uy}FVpZ@CPVA|K0 zL=GceN#4CHt|TtK3>uO%2kygeZYHiDNy>{v1_@wzfGGnh0|c;WBYP~)vhC`$P)Bq# z&O{u@S$>tBC_aI_scK+00CnKC!klwRW4uMD2E`vNR#++0FeYc`>Wtnvc87VQbw9Gv=^*Upj%}_ATVx2ulzkpH3atBjjVrq$dbkiPz@E36i!R~+xdaD#( zI>rfspKFgCWBupn+VRHRH~d`Y?PMoM=}}|dF7$l=(v9R6lT;+z8;ql+;%z@rgPT=meB_bqKF&IF#dWQIl*c<`HibyLP}FkF1RG_OLeOa7w@x zsWI>-kzOAQbz46_QgVRVOzBM2Vc5L)z~s+i1|DU(89QPSPr?+zH6R8Ji@XQGb#^KI zzyR6UpCjm-nuhHsHkDt0mul?HDc#KC1+~cxCg2pqmJh@?n$mu@WGPHt&X?Ql_XO>a zl|c1-%Tp^luL$Vx=f77xEx79b{^{>+9F@a(_W{pX*Nmq*y%T`MYw&JE1I8fT?l~`0 zQ6V~3#}-I&$-sK$G1v}=wm+>fz;VQU4P1w*SBDmZthkddU?vU;!s@w?Hony3zCYAa zqXD`cMv=ginh*xZa=!hx^h;+rv0h?5^#(*I*Mhq54lQiOpL(u_Gu`mWrtEHpC0#}$o>NPIu;P>yP0N!7P^UzG%Z`8({N;*Y3oT_^V3db zrH$n3mQD25+oi)cBK4pnk$SKfB6VPqrq2N~A9cX2cjLQv-7W-Sbk&QE{Gr}+k2%yV zfyWy55xY*>iza(yoKM#Gc zIOhw!Q2qjcKJZnbe`fv3)OcfDeWqyr1qB675%ltCQ-8KJEo3u;-m)r`PM;kj>jF z*R&(WL?DRC_QApK6ZP;9;}-Pvj?JCb3CVU|r@JYAFsyl<0b>Q_#7fRUPymrTpp$?0Zz7z4wBd+OtELgPO*lPZ-8HK#IWe+BzYU#S8A_x$5^(c0eTs52%pf zVLY%*dfp9={Kzo!#g+c#;S=kB+Z0X5F`Z(vdJHg90f!qp2kJK|??5+JD>Z%?Selwd zLlBAkzS&*TX)C=JBaW?!IXgc2Ef!HFv%1-o*w$Q%?A$)dXk{;0u@CfR%CqNcD#zJ*jXBBAwU1Ly#lfvJ zo^J7R80T-DRweEXoV*jnpwJqkLD<4|PW2SJ`LX{Qzvo25l71r;5bW?lG%`Oi(SVC| zW}A+fPEUE#^!h2ijxMNlnMv{l&Ql<#5h6Jhc1oXMjNyC?o&6)n!!9`#I2RJ&B`$8g zszn`XHU1$M2tOFAeHxiDTid$PoQb3Zx06>P=B??Vk4dM|oL%AMN+(V`*C!JmL+u(& z!^ag9IWXTFWdstUa04WWuhk9Cu9Hn8IscEgH1h*G#tuKI~@it`;qR~JNc>C5pQJYeZ&{pc|U3H{$*Caw1h`qY2>+!vcjZZ z7gN=6I6m~8coW2Py_Li=40h%qv#q|Q5LqXyc>-un4WD*x$ovu2WomEk!nLWT2B8fV z$wwIMX2V4+?XJ%^FStG3ziUi(jLC~GN7*HV%q6IxBNr^*rJz^9gEBvs>FeT>Swb`A zhI6HEl1n?8`MrR*Xl7T<&;iGxd6=B9FIwnCbi(%-*}pdzin%CWDq5vrYi?~^-Js!9 zm@?O;yBEaue%&RAuqB@nMV3HF$@F|vui}N$I)pKdE0RC^(%*g0`aDFn5aO;0l7Xd-h?^^ z-3fGAnj52oVu23?P|iF%8CjkT>E(&@YXC{(FGksgplXgtsY&b{`7_p5`jx+OKvzTt zMdVd)}nSAm%Jiu$uUmO191 zgbo}o$DX>m6zt5rLy4{|v{V-n<^1oo4EO4WWw<`AKkn0dU{q4HKyOuA0W}}?nnKxY z3IWq_EH@YJ{Z>jEAnyf72^AqvW8c%~R^%d*YMViz4}K14=3;3o{>1&Ue@q2&Xt z7JPl516yi0>2BaQ>6SHmI-4H8_kKrD18)H7WbpojJK|(ObqqEs=K{R~y6OHR`;3zZ zqo$57HpmRD0Jp5RMOK>?!<|?c*=k+r06h-f&z7sV?(6V58JPbt*ceRsj5y!tp9osE@%b`C?IQ?$udcoaGSL2l2$S^C`px5=ff-Bb;@o0u~!QAfAh0 zIdxH@&c_A`{%cBZ?}iDQusn5BWw11H+_+#&nOY zfQ9fD^nl^!!KO4S1H%tJ)E#OdKWA4zOsis;Jq8slRq<$Z^ar?GOydX(2LG`~lOKM72Ac~oa!Wfg@GVgMb;fjx=9157Jp zfYb{oBETKEC}-pTfM$M$6)F`^h)dDo`)SnY&g#f1z@4Wx&?||N8ZoFyayHRSFLoBvLh)PKCXHXmHTFb_CLX8J{=kk0e(NLrsUs!NS&(tft zBos+_#VLwZ%Bt{`^oy(dY{cE95R=PmWmRe0sJ{mSN_-fomM0wfVFburndrvh9P&<} z@HjJ62rJ;3<}AiH!P23Q2vm8}JHnQw^)q_-uMoIqpc&B{Lj~xjRm2Z3Mg%;|&(w{n zmj>Nn)~_?Jas_!IXb_5;cx%v zC>s!4GzR!nDnO{cj5-8y;iXD`#wRiJC&1c@i4TT=GF{AXoGL|%dt=(D6!N;Iy}MBD z#{yd>Oh*jaHoD5im3kocKjmY?$<#*Ml|7f@=Zm~(U5ZeG`9`|U}EV-IVxpJ$&YfWE6JJXH7 zsZAel+z-iMg$5>*Wz(kD1jEvl1k5Zy%`1rcR5Y&IK;tt-Hs*vPTgrxUQp};=Dd^iI z2`Y2d)AZ$ewSlJUC8$$WXh7 zXaV-Nuv-YhS^&Oz{PsoYR`J=JbrasFMd!j9Zn67t&OxyQmbEiLx%&W{=l~l#fR)LC zn*bH6Vrjt8E*C%261w6f)ZYvI8!YAep*XEHX08fnizCOn!A;2)G z<63QV_1!BdA_}Hlv}}_q-8Qsp`nT@SH>)$9ENZ#|Vxqb&3+P*YM(NKnL>U{QI3No2 zZp+Q;{Ip!1Z(S=kpF~rD_{K%OM&GHfnRj(wL2`nNvH$R#GI5TA{G+@8PJP1u7c0-Jv zNvI^HPWtLxEu#)UGYws!{bn<(mg+tqKP&UKqqv{vXVv10Rc*ZB*ZzXlXF+M zzaw0EDD}){qLe^4<2H|s)#*9*sPkgcf54J#?jvUpXhs8F9G<^A7-rN9t>Uq(F%uY@ z{rbay$%6kg1N0GRzd%sxAEZ)N?3a2VCOFE(5PS*aK66j>H};eY;Mq5fUlUQ&CKj%C zY`*t1$P{`v$H z6l)(UcjNJ9J1w@47sc5}ld~L*fg+I-{B-@ys(`?wc`5dN4JGw|wrn0=<555|ud z)fo^*R&f)MpYo@)J6}K<^rGhN@q33JJDp7P#evyOQ>jA_=xnJ!go(6ceuS0Kq=B9& z*n{V<+H9K2HP5&e)FdcIS$xVP(~f^OQ2=0h(qz}X!Je4IDASk_+&5ipeG+rTIJ{*W zbk||SUt~+o`_!JO{lE<#Wg6`@ct*IH3cxJ#mMp>s-*4s%6I6s7jAVdH645aWT8IbG zrBU0v)aJ!sdP(EDZ2B|Jm*4!kiVU>JZJ!nO zbW@?~xtVBA0+b+9r1}_$PR1)u-s5y{INsW1)%`v+Tjbd{zXX9jUqp9eT|q5Cqgofj z(f5&U()Rfs_bM`x3?{I@-J0yaNAAVnX?Hq)lG+y(dy5;tc_PE?4sjdOH5s8*C|}~q z@F*gZK?lANM=+uofkTD^1z%O5y#)A}YHuLv&rlsw*A<(sMjSE)eiI61ma2g%9tX8y zX9YU3L-Ui>tO7En&x<6jr1!`di|mtkt#dgRd8w^QOK(tgW3&PcH3U2ZqZMO5f6wQ} z**P=R9%UZ^#>|UJWTZe`h6MuhuN|nc##mg>Vz%o;!~@3GM8AYZ8Oua zi^rkP=6L@z1re^-Y*qVKF=f|Dw)Dt4|FQKFyQPQrxE-+qRJtU2^7ihBZ-Dwqun7Y@UezK*W zP_aHgc~MNa+Sm9xbd=Ujr{&Q+L)1c zFBTTKBo2TjUz3AIToCQRo;a|^;-PCSZcacW62;pvuTSg-H%#4jYXTkgY*OY>Pq7`f zhQj}TS1cBv7RwdjP}JyY73&fZMvJ7YNOrfPiVn?v$SF{SgZMVzoEF>qx9TTA5Z(Gw zNTZ7reWaTATG&(}km8Xh(Pcr2Le}(BAcS$|1WpFkx*DtSA`XXh`AkLCKbjb~1F{2t zolT;~({f>LmzF{M!kFw4K3^j(5M-xtKQ|jGKQtP})K?Dcrwv<7jBr=b{YcTRWtpE; zFmWJ9Ir8v}NT}dj_sQdF^C9^tIAl#xG_YW)?(*3TnL|bS*de04TCda>5c}@Xtb95x z)~f#r9z`eQ-dg@0!{T4ob`;mE<5Z|j*5H^0Fd|V zC{qkPNC{P4Z3~EVW~P0FN)b$f^ERG4JOb)o{Bp&&<=gB&2>bxt^hUPO$IEjC*7JO< z6)PXPj=_5oo#bE(&Zyeq8az_XQ25ZfYaM}* zdgCb?4%BF&K;uJYha>Y4{b+JKaGvTw4&&QO+$jEC8~cs0+D6>-jF_%-*<#RNBGiu| zfUd7&3RkxdfpJDudh?p+_h3o}gu>C(eknkPoF_8wdE&cCe!3~(rWW(FeYt&{rTQ>l ztWGZk@Qb;#D8mK2UU!P7+a->m9o3W$c6H6t24q9T+>LzCa3He7S4EH>R`8m6dhKxg zDBA%ws1LO`2@)COcQKDcgFe*DFoW|0J-D54h&a&0_jE0z7xrr{64BLcP6(UB*uTai zvbmJC^kLjhXCgfjbw_fTY0w-FXPVhyIP+);Wp>NLNtI3!mmB+lB*!4$O|)<#*#@2d zyO56QWC3*{%|q#Al`7pyTG-mLC2%f;3mj;4}Dxes{Y!Zn$BZnzxag) zPA3v<*?Ic;efn}pT#WLT&|Zs=^nz(Db5TqB$0tPZH*OQPce2AfyEoC*?EA{C4XU`l zyXeTWkzI@?2Jn#3Ua4^j&|pHZJyhJ&SWr%W3Rzzj6}Y-Sv(2Qt1FJ1tc4D*-iuVsc zc=v<8jJ7k5V6%Vq!5v|<4SqbeY-elsC;nzXKE^G{pjtvequHP^L7T#T_zwqv_DfJ? zhvyA!477`QLfZrAP*2a}S==7R1C_HkNCtvWp2J7b%?zFR>5JSibzqbfOki40XTNn` z3f@HN0+YlW4H$LXBb>G?-89 zr~YsfYjD(}&4DqdtHq|Cu#T^g24ie*4<0<;u-D@qdg>fT94o^m6f7;JOH%BD*OIZ& z^cCBQfwL7}g)FzORiMY|fh3LVVT7^I$45B8Z!8%X;j~S9D1A4Iu2?U|Q!ZH_HgQw) z$Mj3rI0B40&70Vot=kVNZdrNH^X6OIQE3lsK$_cxZVaq$oo5!Z8LW=G z$ex$^n7fnIQ0DhGgN!2Q19Ax*%RLF{0_B(cVKCrnj;!wZR>xcmHK7Q0pn$UF zit25s?Iq>m!s)_9W%uf1-Vkf8CE2bT1|cPP&@%X~J82poOb_3gPCJKTC&!XO*$;ks zN7M~e3gNT)ytU1jihDg`V=;C=?W&SS(g*Um#V7@VC<`ij8itMz=li1bpkhaNJvif%}r&XGYlu(tB*w>;N|k zpn$OF#t&MZ+4Hlt$nCQaO^a8Doa#;V3GudzMXolXYWdCp7)q@bFP}om3i!`7gVUq_ z`3z5~`r|3G$dbjT4tQ4vOWs^#;g6NiFw*-oS7xkJkG}X;v&DQwM00EdJV(u*Wb0bh9S-$h2SfdFmYFgl`U^FCHO%>Rs)un0ua1g~528 zZ}Kw?X{8bElVGi~u|C;m1!iogOSAG|-p`Co?xKRsEGO_m0SNQ+&F8vksN8+pd>2{F zgt)x`)KZWoGZ$B1(wOF2&KCsBaIUQfOIyL33(7d%fcyzq7PgEGkbs4ER25jvMuy!c zz9M1+1Y5NYeEk|#a*ot(cxlrGwTNr3m^Eg$1bYIHezr$Ob`aiHOT}_c^kkjwCP_Y= zQmk%(jvSTIeTLbK6bvwf)LMZNABB4#vzv-bA*~7x<1VssozJ^x#Nw+4OO#-is%jZ6 z-(Id(b%9l;p~BGDvSf5cmBT$`k3hxMa1{0x_j?|q zx=Byy$PDO|s5K2nnd0}b5{#_%=Ff|(VJ3>#a0Uq%=!{wi zZ|`bfZ@Z9dzZ{gkW!PKuwAg;Cz;xg!Ma0!G(b8P=a^lVmw%&~k)lU6TjY&d*Ny=*F9u48EyW@7Y zpVl5*d(L|sVIaKC?S1CkKkR+%kHQ_b6CY(h-zJ{$Mt0dJ?QaB?`bNkC{Z7rB7(ekF zQc%0`?u=a5FZRl&irzAeQv|j<^JP*5eWpI^%!GBS8Jj}Hpe}O{lH=T%AvHX9T2GZsQG9s$6hXq=k+UmaUL zDtZgSzKMdEpJ81#Xvp&+Z?wO%%tT}1SaCt^1Cu*R(@vIv-i&((bmacq$z;p*e4fPG zMr!JFdM?!$Xd5fsE(;@v?QJ1oXCR{?vy%@3I`jE-%P zg}QEJgiRZi;5qFFySTzf!^X!fQr)9gtR>!NI>lxd|v zV2~!MZ?P1J_L0S-Pv1#>dvITsQ08&`0FZ+9>P8`!7P6^F8~AcA^FMgAQ=RyeGwABj z8$`@=n#J{1?-nQT7M+#frgIs>a#wuoO!5*ZmIajA+-7QGy`!P! zwM@w|%eT4nQqA@A)hP<-M4%{A1XU|G7*i26iZwxnxg7?ub5&P5$^=Aw;JwC*7|P)G zshOy#B3UcBTPVOO+6&4yvvS;yLP`#_3t?6etzDPN?lD*RZ6!2qaW<4Om5Q{sdF{qr z#h7|>d~+5HHWfN`nM%5ci!VCLxe?TqRhtrO^Q)1Qs@gi^4#!pf3|v$w{M2!h^MXTN zm${n*i12`DioQ*G+%*Nk^1xnD5vH=qDUUw?t**n5Vt|I`26Lf3{ty$a*ELs}e^w@`mN(7ig2(Pn#wyg$NY&U%!|PucLPI)_^TKEW$M=UgUXoD?N2NTr6<~%Xb283v z%So2j#fDMF&?T)*ZVZRF@w592A!yo>+lhSl_T#1l-!%c$s*=ue@8LY}RM@*q-8;s- zH%7cmXUQP()m{VNrATl?LGafLfoFSAoIHXfi4{4}^Z9xtDV@J$dTd7f&OyIW8V~{W zr9GibTRN9`LYL-rE;|NBF=N{;4MDtdx7raWvkwkFIO#06C5Dnx z+=DwJ#l4|K1fOVbgtG1!5e4KZ$TOw{I7o4U*&DIkgrW#=Xl#r-IZ3HW>5OFLsWhgH zkV{}wpkE~2#S(J@%W)!mJ320GpCZKN~MWA)8v06op1W9`<7NH7-JY;`Lv zX%M!=$GVMCL8^(`%=A(n=}ref)+CgE7@ZaU1avVv^xkyG z%B_$+!fQv9EoFja|$H2|Ha46Cyq+31Ug}tHV3!IVG5*z^;)s?O)?VSs!)^Tal z{i?ssg`@{a*ANb?2)E^2FeAxS3jI21=-fB zYbt4KZ;A%CMidyjy*F_M=;o)Qi~{fnK-B- z*=L|Vzpy2&F@@a;GE`g(x57e(r-hXP00odU^%aT@b_!u6@+$ovH z7Hv%M)2rZOXR9-;ylE^B_}gg|Ont{pED`+C3|S0QTF$eZza;<%&k>;#4Ken|vW^;9pU$a#d~T`O=1X5|ch`m_J_A8|fIbVq5yVOf+X&5<>23(vwS?sIE9GUVI~6l9D}6@&K?5wfhD^%}r0BKxtyTqAX^;UO`caC$UVnCa9oNjPG=@DTVVd5cf znn8>Vw3-tC1x=l-nLptKmm!uloRg-L)OuVZsWekzLE3)M-2!AS7@e#@Uh__tpy~YZ zgZ!8M{m+8IWRC84@0>B{X_3z`&1^>_&-hbGpt|LdqTl1MRu^hbUS=t+f#_^5YRWUB zPE*M8^**dZ;KMU2VkS2Pt}RonkR*?p1{JTBfK33niO8j% zc{7Ew#i+fsH-^8I?$MjkNX?lH(|od^h0?;>288B2&YOVHtDW5%;)F!b2%%sRYxjey zuK`9irOTS5U~OPEW#ynnPTb@iknLf@Q!hd1wQ;($NhJ@wfv5sDtPhET4BMx;rZpHD zDW4++@6+KEeSET5)y0egTshUSaoZczGl~=L=O2^6p=$e)kQ_W z&b~puZIt-~neAm0g#g;0{s@DW;?kxh%hAHdkvz<;48c(22!l@hnH!X^Cv!zM70G^r z88g&`6nq6zB~G53SxD{1WTL^G!Xezp2*7fM{n6k0+3^b3&P`yfni#GA~MR=1YO zYv-(e0;+=20kgeRK(_w*Qt8AzS4OwsTb3Y0A-vTqcwSi+gEg1EucWvMXs5f$vl+#2 zCmxTqEqFiuxGp2ipWZf&LFur99{XkML6}KF9{KEuam46)nLS+;^DUI|>^0*{!&$x= zQml|0t}zG8T`MGIPUYI5Cu5LBnd_VJ=P`v_7Lz*#VvYAVjo&$OP2 zD@ig{10!JxJy80|J}5oVT>s+a{bkZ>z=p8N21fpq5EQ$|Pw&U!YRm^0?!~T8Sd{+5 z=*RAyc|y&1!_d!ZhPZgNIVB|d)~W&kUB2b~n3W(M@)|+Ku)ME{cyiJ>vxD^ndzny) z+vKl&&s;=E12}$ak6#JE%Av?OA7a=WoeN zrHiUlHtnS5JUlpg_x%qJdaF5|fuzIxohkP%9NvlV*wK-FuZe*)U!-q<2?-Sw4)W@y zsbu>>%$^O+(e>@27m-Krl4fq1kz;okR2uqBn$2rB9I&&&HsX@5i(v_wjQpFu(ol)Y z*QGICXmg3FVoaB_7s4n=l<0BfbiY!_u*k1Qe)yyFEv}Lo8n2yRh3WCw#Z^z|j^zfN zV7qIFMRf2I4}HXKXhd{lf5I^l9`r?Egrx=7wnX6GBu;nJ33jC~8Kx?jWFc-~^Y`$JCy_7UuMaJ@xZmGAG+j93nW6(mXs-EHQgRyi|*TTs8g{LbHGVCqC}pOhys9 zF@nC1#aFoyYMgI7bym$M%idTxYMfRCVm0@VN-0>8b5 zlpN$;KDJ#b>IXd}uEf$hIIQcmdTGUzrMjb{LDv zH#Jt@&vqS1S4?zEBZ~Cci9KwsdbbN6?m(f_$QYnCp&ohcNYtaCeix%QSOp`b`h{jP z(&XPm6^)UxAi8W2;ZLB#S~eaJ159uS)O6;W$orN|QZy64xL9~}Bhg&5uH z#0RJ~tQU&8H$1?_yp{NZ{IVGl%{#`MK; zxJKA1R(umrH9%QT{b~17go8N(9}qz2cu`h;Aae@GrM06AYeSNyOk-1SdXz_!tY0iC z&$akJeGB-P@7{~gc1>N>Fw6ctX`PRt4;DSW9FT3tJSP zCfZcO<`KOtPS+pYIY|=q=RkdS2v%q}9=-jYqUM?(R3@2-Kq^>|MdFh=99DJTST3tRi9==>P*T$`9lNWp4+ z7~03cn{^CUxbb$AFWmra>KDzA?RYCGVZ>Vl$>A^@B#STRY5QUx#1|v8#@)2|7|cB7 ztznkXBysMrJ=$$&Py6F-OqWYa&A;QW2JR=_fYQ9p9w~sOe!(~Pj`ZMWghr{kBFe3; z(4Nf*5;lE>r3OkU7%CG7Mq1U~FkDL^;G9 zl`E_kL#E!DPS=!g*?4EtH6bLQ>GHH;_@H0L+bH7#q1A+AbKLzO{w@pcFqG#$c1y7| ziBlk?H)rmV337cd?m-PJ{0{(OK%T$U+qK!`1CQ?2hL-pR6eLX=PflY7@nJS_S2&sh4(^{_=mH4>?KghB$$?fR^qWIe}EJSti!lZbO=0=4~79*2jLqlss zr>Eh*7-MhG+zdF4ys7gAX44lk6|O`tgL$CeM6A66;eGXtn~8Q=TzHf}$T}NO7rVf3 zyEy-JclhDUvx~!zY}(1;Cx3tb?tJ!sZ-*aeAnEY)?p-O4W*vUeQEX4{KJhTdy@V@T z679G)BfDZmyCyn)p&n9%m-+#oo|$%bwlq7DuVTn$&l{YoFEZ7o>oa{#nLSbgl4t3~ z)4}9$J%9S+_-oHyRffyGj)fccjtRtAI(DXn0KF$7m(EZ`{k6DgL&fek2kpkXG@;ue z&g`F0;3AyU<9~$#9^hxH&Kc$TfV!&RW~CDC z7Fkt#m*k}_uOoV889~jsP~44v$+07swWuOPx)lt&&Ew~-raz@Za;8z(4_9B=WO^Pb{Z2SeY(5an2f zxgfbptGFG1zr4{FKVGnmG1XX3f=Aj*LdC{|x04ra()V}fH7SAHJ z6JW#vUi=DF6W)^zc+J}=T)6^oJv<2kcjySgL9?&a&ez~RUC(O+Mli5dQ&K;~@y3KN z#R9D_iR#!)Y`pJo%u{v`@r4xD!UwtP?$KG3O{iTnMT-;V894wKF((| z4$bNn$>l)Z&JEw|2!m~pl`2pjI7UdIxlb{5N88{hBk$lNMfC06|F%| zU2mosmc(x;2t^Px@Isp^6kcC7#{FRqKVgM-V=G`f>i%geNGB&YlvL54F1#+)J)7G7 z3&E|tK@`x89WYqCFi>sV){#5g0nxk*gOET#Rbzr<(=3ci*y@>Ij36^tgVB<|;ILxu zPsGkRC?;oM@ysP#?rKLd>TK?yd851f9$ljMoSa1~Mg64nkj|dUTT5Pos-I<8ixoAy zXZefOCd2acN|J><^>ZahnI!eILT!dsdzw->tdF)agldc7HE1HRCYoE#RUSxfHI4>o z+@-i$GdI_GZToGHt<~MN36+8Ds6RvjvSH@Ul4XOerw3?>$$gE~%ZjDDg!kiI*4rqB zY7Jg*r%#~-xtC6_B}01QnwPE+xrh0A*7{x{rG4@Z*!Cp$J@GUADOKWV;@m4 zrr5^;u#k&lvYJoSBGod6zO)ewl-vp*gTiPmbmCwqOv4c7M;e89iEftt8y|qi0N|K= z4I5d_tCcku`tCNiUTcb#aSJSmz^Rwbu94^=M93gxQRo) zdL$y-O-_+wek}FxD6Q|Qn+I`m>*s4FrmJjC*}zIcPQ4j$FN0FQF~ev~!xv^IpJvG- z8q~w{jZ8&Y~{P)P$?4-Ec+)>WvqMvy6>dsfQP0Bcyw1oRF$ned;tC44%j)OL7r+qn{S)(D;b<`Ze2J!U0X)9t&irB3s;z#O`oV{;mKd8)crvEL2ckai#N`dvzU)b#>U6G@1+2=GOFA`(AF}!KT>}d#=M6!|)4pu?zvf!-I6oQJQujE?- za~^)RIY(EQeo{?G1aRHPvd(f4{qLGW$gRxr%}xfu(Mhxe^@rQHx-OU`pfO6Cq>$MK zPTphX2U2ClzJC*c>1CaCb%d+n%mkHn?JeOW$h|?3nw1Z9<{Z~QvHKi(YTdesPfTcw zae62>M7#m_=BM)PYProXySS-{mYuv*=I=f@{AJO<4yzo;DZ_eKveNj{RnU~&P0W#f zrg_O5F2m}TM?}FPRnn1d9VTf6JS2fmyQ6?xC!BDFv?2+PR=FN!a33tN2-QX>yOj?9 z$1Hz^86X+8$S9d%gv&Z4M7t^S4n`tJ)hsA=IE zP@)EwsqKTy|xB6GF4f-7q&>5V6x~AziSkPp!mj)det`yx#=6SxEk)Kn|g{)F*EmNqU*NMupWC@-2t^8T(@EymT)0oB2I;9UC zhjdXG(e5TZgLp0LtNZ#-fBfFF9=RUrRB4x0oUgTuIx0cGw^j%(qfoJUT~kgPq4by9 zcWW>PLBhctdkj#3c*4jCg&9c}A7vL(fAV~AQ(LL&n2ZJ+39oLuQZyW6^+O0Z00 z9LXBMq>s)+`Xn7~K;PbtFay1?ggH!XUD97a?j;`hgOi$MtbPe>DvwZSj?Uk@1#8mP ztEx-_aSb7dcNBzhy!ycJq89|+Vc?Y>WRhLDpe?`kVC#M>nh~T;=}B67kWZH@QZBO& zH7OmU#FXCK1|mkO`mRo4S0XCC3%YjPL9VVk8AS@L0)$Pi&OiNel$lemh0H{8Rkq^I z0lZvh@ZYK%^Ru({g2oplOOdH9sOG)O@mQAiNLF3Hatp36`_NXm*lMiYDsQ{jb&@jj z#(70oWd%r$VpRQf-~)l{JeJ=MZH-hD9^q6_r!uKtrPRG?Rnh3sMX72VcG9W-s`%yf zoq5q)rz(bV;{NW6O4Y{wk@ok;5csE%hQi|UOQG3fCuJ{0M!Ul6bo#_5>VOL!r6NKt zE{DU2ua6UhkQ#%jV=NBlQWPaH;VCBUgI|ru>5(bBzK#v?MkXH>6Z+CR6(`c{QE0Mr zobk1L-=`uh<|CYs8~yT;c+bP5trDiy0u$pTkdFJXQ9Hwt4%xy<0eu(do7Pa8OAMk( z0~-AV+W`H;-~azQf|}y-g6JrQvY9P5(}PYLC%DAy?j8o(U{081SW1K^J2-VvH5##{ z4u7=)UFZvtRoR*kp`63)6ze$E@w9`ouTciDo?ut%?;3nomM=zjy}DcUu%sdysr9b6 zzJ|JC^5DAw3uHfkNcvGt^R0%hbZuyv`+Cb0hd<1`*DVR=4M~fOv&~V!T_QUiIIZf6 zTxjVex1&K!eAoI0o0ihL7U}^Kk-sqjlQ}fZwa_xIay%=d> z8+^tnpku-wQl7UBc(|Hb8+q~CRVM+GdS2wJ>v-RSgVKxWBG~bDx!PjR9sQeCO5U2y8rlI#_Np+n+X?!2Xfsn+NC^y`11s`@KC!IE7YO$!=GZ`Tr&hpY#_PJO;{PcH)rm4PwDGK+OYD2VrBLfCIk7M zF6&Y6ED))(&rXg5h4r_Afwb09IF{aLIG-WfQX@=w&+dMDBk}$)yaju3xo49;j>C7X zy*u$nSrb7~qR>{!Hbc5SE?xKN9EvcHvQzb+QyIJ%tO$CVS0_q>19Io}QjId$jS+5W zImNsMvbV_HnJ*UjL&;I_vo0t`GIxS_hzACZt?&~yuUaF5rbF%bDOfNKOO`3vy_CFN zwh%B0P^y^tL(wo~;lLvxtL)6+Y$N6K$g7hKAUdF#t?&x9%WPAdvA-^aolbkmTSJ1s_(3 z7(%uRCtIF!aEx zmlTmvo%n&0C=Y8=u1Twyo=eWp^0l5XgtI)G82KEC44Q%z5|d4+G0~5j$xtt`b>>(y zDwsK*Fv!#pXX}_VC&QN&BfnvGZ~-hbyQ-Ys9no?J7cX9UP9QB0BDS zzy!O~cFvCbe8LE>Z@d(qH^&Y~d4tq3z~sO`=KDq@zuPtMT}t9fC@6hQAM8iA_cgNO zK6#Y76nY*DNg{9UKJo0_6#l4WrkCft+!aO>=m`NgdO7XyhH5^!usL*8_Z_cd!Jo9L zx=lJ+Q$P6NVD_uSc}HuiH-NOG{_?>cv7-_Xut`Lu*hJ1|EiH!D8#S-SiYtpq4)h7o z4jPGA4nO!J%eLs(VZ6qygNKb=At@EYRhZd00jB|VY805+8H4@kDGxa}tFyEGDtmbj zu{?7{;-F%1w#YZ9>OWk=<-=@SLe`*_qDxB714daLV5mu@LtC(Y2J)UFxVZl&8~}Y8 zXw@I17sJ51#o!Eq*&`Ej&%d$E($XZOdnnq?{HfU4K?f$R3UEA@l?-4j1qY zdwKkFj8n;$>fso3Retwf@M-j!=9bJ#k@nrq1^i{0g zT_kjtyfW$TB9w=Jn<+9zEgtC=g5gRy{%Kn5`v3j#_y37K0K+QdF4gZfu8X{FM z?Qt|Dk`H5pXIkKe#=fhOXfjheGJc@F$_GtIJh09wL)ST_*}BVUpXO}6V}gOL%}JcC z>s;z6Aq<}d$kBtxC4i#Ud3C0^gus&!QWI$c*IRJf|CsP6-FqBjJ3nTA{aIfTT?XIwa0VZ7$kJ+IP@+V-Ly&`(U>c z=`?k2rpz|y5G}EB&x||b5%~?$oI3CK;K=xB+l>#dg|F4FH!|ydUvMUfE3R4BA=9*t zu?N0ua<*Eo5XAm%1Uh@{m?HH}+&fM3l64hKmMJ3%O+1?OB9XRD?t=^Ar;dRGN9Z&G`ZnFs{IYrP$`jn8lI3Qx(^x?*dN6IAz?Y zdPU@JTcXcSu`;7fSNG&*l9BLKPTv#4RoUf)JG&~kJK*clowO8f z$gV%4Bf^f(;Km$!IIsKFuH_(Z$w)E?5Maf5csF~@Eb*Qq*W-%Id6vfVwfJJ!XuTHj+H z0JLZz&snoKMf_&s>&?IQve(HI1`!K-@kX08b79$Xqi4%}?RWEycELdTBE`n0#9!5=NN6F7nL+gy~#s zJ8YD^qP@i&ED%7KvFr~HWy!AAkkn7AZ7)uZiK|{L<~EDa(txernR#yEo2~S@1M|Ft zy^y)$Yyc~7uZ_@=eU{tNpLu3? zd#q?PWSres?Q^@!m=doWe2FC$_yIrpdzUwDVM|^95*FOZjt)K6l9<_820>h06sygO z6{nABSRME^53e;WVG49pdqHM9IPdu~B9)EXlC>3|HQj;ZkQP7HZ~mRd%bwE?Q1i6NeSjmooR6D+7~O z&d2oDpYutOt`5ia4G(3*QsL5sAqoQpmDHZq(?hPfz zd8q~RA>FKg%7GKmSNcr@&2|`X_*zckd!ewF^Mp36reGg33hDaif5ObSr0JFP*!_qy zk&fJ%Os1>NrkHNY^YjFqHjBkvPl$yWRFuQ-Ne+5*Xa)6$3+oyAN+XODqP%ZCZod6I zFu~kyUNhq<$C4gs;s-0(g%9ni$~5uj{Wc{6b5DYb$ICxI&djHA#q7>XSsVR+gF0C~ z`F-nPwWhTJF|t$+j6umMFq&W==reev&WR3$epT#X4=y$l&q zn_{8hryv5IgH2fa^i+_)u0Eg7t7(PV8&{jqbWKqNxMiLK6`t*+L`@#;H>p33Bc)+g z7?&G0q3IMGz}`|1*H?c!+y+DPPN+ZesMzjZ^zcT|6Yrx0jb&1IJuSdH ziAdgGymkNo$jpj#N@er|Ae&XL_UP(tb*?D5A_EFnDE3yHicSEGn`||mo^P-&0DJb- zXcq!xL1&k#W<)VrtwIOTjcUIn;0*M@BlPhpUMY4NI)mC`i24sva&uv&GKot-Nr zR*0NqWpmXAa?hgA(bVR>L!Y^mf-09)%Xy(@3cMVfx$xX+0~fAhs|{V4vH|V{bqqF~ z%FJXjt&5Gi`PB0oT&oaTiz`U~K3$w+ep9Td{tI?q&cRbfUI!+wXTMtUPZbNdO?_7zrXfS8k@Dl$X(=2lOFSmj{nUKu=FXL>B`2z6LbVRH@RPp1_F7YlrvA5xK^RO(03wi*-j;Ni}R1`|Pm!^fr}@VJ^= z!iU8$s_m8K4ym(&&A_cbg^(hh@Yz8ln^RDr5ae*dj{+oGjDPpU=Js}QX~MXK!VUzU zWFYQDKM=?@=Q2nBY{B}L$KMIuTO&RR1Y0wL(T=U1!JGQTcPGKS0lmDR9S$XCf)tCG zSv1a&Q4$%Ouh0<`h%U%65Fn(FKK1Z=nSG}_(>AT9!M*QX83oB0sjg>Vm?1w&Zuag z2cH27lXIxF6n&GMt_d%We7rakc##;gX;Fwu%c010*=OEI$$6g)hjG-3wl0Pd)Nk8qmsr0A!gVC9W3q1!MOVv(H|OW;qc zZ{e={Mz}{?Y&F5Sw$O?Rj!Y}}CTnV`k*=JBSwtg)`2sC(>ecvg2n9<( zNnDN}46)40D3fm=h_?@0KI_)1RLPeXkJdJyl4f3fJ#=|Rvu8=N>#2H)UCp}TQ*UUy|5_U+DY ztnSM^QTIV~A$qGdm?Vqzubu-ha-11f3E3mwY)Ko25FznR<|gAZBf<@2I3i6I%&SgR z!R3qa+YwD?L`?2jSKcOs1akK^3M7X4&fWQb6Twrm6jXEMZN4GhjJ`Bc9f7YN=~sGl zzM+?ltrcXq9?FUMN8vi>LZho*V5Jb}8~-@8pNRHDQF!M97gF$%Fh9c6Py`1;e0idO zG#`T^dJ;PHBk@0v9RapD$FRTq0l-ca{wFcY;J+CzK!19}k9WQqX&@VbsZ&0FLoal& z@N*c=J1_Kz(MUeTpJjDyy0G0B*+a&Ebsja3lkGl+`lsOh;|P0u!V{f2=lk=7njm%D zdJ4gV1#OaWVo!_2g9ZD1F()g(jIguvPZ`bN%1^=^ga*no(Kv!NAPnHzoSR+b4Lo7htIunux$h(KX=06@kx4) zi~3%ddFsFJ;aoMQ$MCDZH;iUzFYNgYmLNKq*z+k({%31ZzEk}(%ATArryO3OdYfS} zY&wS@aeqyI7vSvJ9@g8~}FukE3_Qv4a3G68p4DXzYJH5W|LoK8TlYUNa-(5W=&m!gp&fy;wpfb> zs^F$LUUpJ&JmxF|r8sHYg!bG_>Z?srNX7X=4H(sIJ71*q+uCSq{FXvpb*!JLx_igI z2q}$j+iw!nV}nBtZQWYEgj~EtO!Ao_L?6kZ>rH+UpC6+jzj>`rm(|*5zxYMA9&cAq z)yI!A=mNA7q@&5ccOtV(@!1&mTYdA9Y6TyK@!HlXiALqMG%qV^8FZxWoGdWgi2SDV zk$}^WLG&JFXiv4Zd=3MU=J%Z?$pPX!pSKz!v71@Q1W~=CYZB98s zj43y!=Aj7r9`wI@P}g7Ytq00EhyvXa+IR8zl}` zXT^s+EA@R&hC;U4Rbay`rj%UXD$rp!EUwodwL*8Wg@Yd)5D$e1db6N6U0q9}s;*#! zy;>F*3a5c7NJ01<2;KwPz-+m?Al%UtzLEk#KT9Q_{D9#`MO ze@vj4Ng{;@Ys}Z0Y70S@#b$d28ogZpJT~9TRu9}(4~$Na3~L}g<6l6z)Y7+Bkx1y{ z(O8$n#fY3s=3GyeZt$VDC&{)f!z(^%d!oM(Fh%A|fK>J5KsE*2+=cB)9JXNpNdnjX zO2FC}CK2BH*G~uLhFQI1aF_ZW`mrti<6SfWs8H>LLu)&w1t!*2xC?Q9iz!--lA)cp z+>m*P1k5)*H2F7?i$;TQlTLIN^=y(aJNY#o9?XjOr|)#|YjV04UQO@4|3;mfC?C@A zY-Rc`o-f8Dd{1?0FvfmiJq(fYAnCzI$IlgH0}rC?x94>UY(UPu%v<+C*9<|V+Y+6m z&~?@_Q^loXis1to>&jvOw5z7;y7TZ+SYDer8@;3G@;5kg1;H?$N){y~M&-yuBab&gh>cv0*Q!pI)%J(jZ!7^y*o9XQN?q9)D>CG;f_98Fp#U=lw{Gp^ zo0>{uYXVIAn6t8z)u0km3VL-u5~@jdyq6@WU-EU40-myaeQZ0|Zv7V)ZWA^g5=`{3 z1pXRk#a*`(3vjfYjXAye5oc{tyxaM7D(o|T77CyGFE9(G%ynz+Pt^Q+voazUA%#P0&InMIS(CqAqitYcW6H zma9$mEkvBMe)mJgs$}_0T_-@iDC?W&g$+y%%wb{t6m15|PnZ;$>dvVolw~bQEj-zH zPf}jB0E$mR^}~MO$a~F5WWyXqt5=vj1EO?R8*r|a3z`+vMQ(QaH*mO&?G4ZKl?nNZZTD5kxj|#8Vi%v=W7g*fXapxJ%ldpm;^-Yv^@Q?hR_pCL6~yV2Br}b z=vfUmMPNldl2Mv@RmX-=zGmNS+XTnP#N=*gnCckjq(9*yZEjZ7^V^Pa z{*bkK;LU0n^gURzo2g-)&8ClU1kS6AWwG&r+o>p><|`b;4E>1-BMZVqCHuDWIHY}U zZHE1cY+6lBP|<-=g8r<8kB7q|ANV}$a7={}FhLLbZJz{D^Q|Gn6n1r`NDNt>@>hAa zK#6m^A_Bp|D|mJ1bGTf9{?IX2{%Q!~08cUlG=D>I^O4 zdL}RRbnT66X4`xrCnl_8Q8kBe)yrNN&U`h6^QTR{=~Dv}x0BLeIR+Etg;oo2dYKm+ zN;1DGQ0+xx@GGjIlW$W@j!0=~L2`7uDT?|x%f>CVQ!{_vi-9h%C-l7hW%uH82d&N!eP2&=;&|g@remZ?IQj7j0iU-AK+rrVoM^*sUb>K|zun54FriBcG zm8dU<{<`wv{69y!>&_%tj#Idu|-_ORIsNHIeJmkO9z36xPOq)e&bs+ z%9k6`=YVYicOA+$;V8Bw2*^^Kd{#}V!crrS1ETg@G#i>|3`D6ogUWN4P6 zc8h>v0Fnl9y0Aop`crd1ex`G%?f}g6u}Z`M%V9NiL^!bXIwZaN(D{HWUy>GR4hR>X z9faI^QQ;p@KyAL@zqn8Wcj4H1t%CICL4`8NLto{|K%4t>2;dgBc!Qvmef;jpjlgSA zJ{By-@17Xz^;b1NCuIeD8vCM}O?>xp&B9`vOpkxGcK6lB9X`5gX6#L`u^apPE4_{m z0(|C(*{L;=i;57kTNnRVo1NznTU$7RMhHC75QvKNbV8ylusv+rduTj`sWS&Y$u?h$ zP07UPNFPKvf9%+qJdK8N;6o{XtDcCb^n4w%@FvUBBM75Yyp3RKF+@*iC_Z=-fJI8f;|$Z2hZf=FV;=^KFb7^& zg}Wix|5Y6hC9y=mbTP&Ir$O;^?SrH7(HeCXv@;9C{$xfcBvvxB|K^YwahrQP19 zkWzhOKCuk;CM$K446de)X^RVdfeZmDf&@dWUWK89q#G(9lkR{+n}sILhky6)yEvM7I3m3ze}af2O>g@`l_DqTVy4)4)+V;H_t-}2l}|JrVh>-8Dal8B=k^9XNp8=KzvJ7>m_|V zFcERi{4L5I580nee_!kGao9fJdy=)_`j#J}?p+YPjr!`?@RetZyJcsbrTG-U_||P? z{5cZ?)NXU@%em}EUA5=bcs1{$-|l(oexcr_%aIJzTD4s$adfPE=9`GKme?F!Lt)8u zOi#o??TEx}yBJD>IX;8@)8!ZA_Q7z?j0+7DGSn}?D{Z1R$E))+8I2i#z8JU60$N)~ zEYXT3_U=IRB>%9h0GOJh08G2jVJN1I2E*1V_XKmVh4|p^J~8;vb+VEZ%P(XVkoZdE zq$2`&(4CUrWr3i8pm*=*K?4MOtqH!BjGt)EvTFhXONU=9H!&$V>`d;Q#J)aLFz&OT zuOPR`S+2;g`WGe|5f04RI-h=%pMvwO@sc)oOU+&*m=NT{x9-c}3rYY&NqsO71G21C zT*bxq>N?9JBl=W~zMCaK#oxAj$L{XScO7@v-ABCv|J7Cl%nidS<&b*A^V+M2=>oGP zh4!9n&ar7aYRC?bqR=YoBN{jLTyM%9eLn-9uY;kqfi#%vkG(|S7M4&jfB~J7E7P{+ zSYPdy=oXXM%Pv~lm%f_zWt*P%rD4@ATj;BmCC4adv)3u2TUbe=FgXi-*kR5@O+^n@ zNH(nFjZL`|R1K94p=t^69fPW&zzM)w3jJnb>rmhjzAk~jV=xv}I00ozr|mqsmPtM@ z-kyOLf=iwn9<2Z$^_gbSAmONj0oY5R0}LF-Vo++h3oxbtWUAT{A9XpKe2p^Tjk2w% zRb#i@5Abj%{Uwe&5p&wFZ;)3xNT-y@f&!AB^xo{*cVawMe9pp9{g)*B_!+&Hfx_w69FN8_ZW(QwdGXU!sRHwKOrEuAO>Y4+t&WjsCEiX>V1%unFRa zKm1*zD#u8EG1W@)q7}icU7Zx=B=j}Ckdhf4XX~pPQT`?!E(SC=S1JCLV^5J9Eutdn zlClt!>m^`{?bmQPKJ>2T*hCtfhMFcAVM~oD{I~yO^26W$Por+TA?VZ1|8isO0*<3Q zqImP>pc)KLj!qUBX(tf(dcvM^wm#oIlHMTj(uCLC{#@kH}MO#m_8CK)ONrw~papQ^H&t7*uktt6& zTw3$F32xr^_(c7#<6-KtMxBDy-^#A$d$YS<}+|&Sgw{+1Q~t~@zcwE`x$PcPUophl>t_o{Ox}S3FR*# zY*e++DvJ9yU5}^bN(m@%)FJx&K&sAl{}cSuR&0AHM&?d&_($-EmZA8x>y{|sD0-;y zd$L~DAmvm#KOzz%<{6;B3Eq4D6esn%m}Ud{A+PVn$e#!PdNEW?30$4Hp8@o?`Dp++ zv9Nls?$*m;EJj#;NmH~n>`Xt{E4-}K$1X$!rBba%8H@n^j9frFv4r*c+2nMSuS=k3 z+3Smp3xEzv`11loV-JSe>$#MKjmB!uW*7yqxygl#rG>K#oG{E-4WY0vJ5)`=27V#r zi!f)X;r1?ISBB$aQL&p7x)@y;)`BsD#-m4o5lW&y%heM^3vfun+Nr=69rE({vLa_s zoZY0VzxsdwwLVtmh1zH6<+pjYsS#2Gbx)k;cnM&8n#xdWF22c1uEu85c2+WFCwxrZ z=uDm8*jcNMdQzQi3cY3GE}cX6+X!vB!T zg6toD@Zb*6eM8O7L`k##7jNDFjLQwx+f6lvsw4{GC?(r8-)t&K1i4ZOl~IKg#fVJR z&eX;B?JZGeoA&Fi`(J_MfzAe*<+=w<;05_IZT+P6rdm#`^`ap4Hoz z9cvK4%TLD)ff&(tfRXAMDy_u(&dpOhhEA&W>DWR!PYg`}=W%(gY~63PY;7Jp1KN4; zw&tQGcN@RWu}+xXhC!a4>MQwc%Mn4nsRQDG)?4Cu6oypl+-9foe&;~syKMa6Z#4U1 zN7PrF8h2m;FhpNvtbVhu;O)SH0=>opBan~uZ{W3s#xOq3dRwf!p{Jf3ausAK_!}6D ze}6ir6<=h3GqfQt1Ym=uT?`$@RBbli?KIcd z@o~Nv{L<^cK{Q32FzgYOi4F17*s7rMDZh?y)Sz*vY!x&_&I=r0k7l4OIYgVchPb;& zl(QD9#iFX`Lh>1Fl5r8our&FpZY$i{VPs=wDHXBDakW1>;y#{aH6V9kq1+$9ls{ju z`ZBs$2=M`?UD2l)ZLqd9Xr#F0YwZ9AxnH7L*6cv5UkoLSmu#V$D+B|m|CI3GZ`D6* z!6f1qOn~n--&$KvP9L7qx5A%4vDxV@1pc_ZFtG&RsvpfC(4LzQ*8Blzrf8+X^oaSD zSmqtI07(?sCwM};;fOqb@au1QccaurBNC=%HiQ7kRWr4MeSvvVqw;V3`SzT1)pOPZ zuJ-KRTkdlFH4U+TbAm2_z+om`{>@0P&aIz;r(|-rTCS+L1+3-c>=Vl#apV`=+u{Ub zb(QR6`2BzVJN5e$I9ohjI(SFwExpsfKk;*&oH7Zr=cZI-OCi>Fwaukag*~7^bt>$h z^34XmM$4!E)()dXpq%3gI1EFb_yU}j3t_+k%m{lJTAf4CY~yvBA$>g&y*nbh+7ze+ zQFlS7K?!X>g_IQ+2Et#ckJa6mxcGc9{|#bvfE339ltyDPF&GMTvVuC~id23y>2cXe z%7Vx_GHeYO|3Cp-mflcAbz6R&FO2y8Z`Dgp)(4HmzZ2CLO4pVPSd+VpaPCY^sW0%o zDE}HD9cmXqV0i>wizc@W6L?UPcA;2Au{Xca4 zTT#qxfmoEw-$uFIC>LFyImq_DC6N+7*usC|bm=+>_4#}bkpIvsGr;YtRwuE@^63o6m()iC+m>1)Z8eB;7tEsed?> zq9Iwxz^?i^I1Bmr^nt@9=u?y+mlGO{$1=oBvuT#aQ|m83cX&Hpa7kc!42?f`@!Uh_ z31ai41(`L4e*U@37K{+VHAx<<%>oc`ny6_CNxIdk-uQ`&9BP}apcrs28jOaLOKNQh zGRhj}67VVIFiQOt&6TIkaJw43z|Qm8JJntHBIWM&hEp``@?Vd?G2+nx-RLX|T*x~} zwM5%I9lz8i02Ex$(kub)avx1P5X1mg1m!E6P(`H4alhg?;5HG$V|`fAClGZI_O)_H zD+n$c_-I&z(Fx!Pa2_YI;c=N=C-K^4=Toe@MsqXOVN@5VlPt@7*nWj`0xYg#(=J~2 zrn)q1UP3oP!&`!sG5mLqyaAHwVA<^!>mfnO#C` zHHOc)TH2F;J?%8SJvBZzd)slV-$pU$Z$WFGRD@^0^*$$^!Kv;@y|1!?#hsyG$yyeE zIWoGrD3#;RFa10__H^3~Y(M0`wL*Y%)4@gkHy(F~;%Qx2{fL~{5ca+D`90$H+O#r; z+iMYx$yf~2$J=BaUNILyrcixY=F8Kt(;&up*ZNMv46T1!R*RY9^5{|;l<-Fs zwS<>Eqf-(SJoE$UJdKlK${MYOLo@n(V$?foNlH`__WyEqA$58?-~pLdp>(%c8*{?V z0^70hH51yPVvPW{s82)%u>>V~t!t;ZLhCm8SSO=t&`M8?u1uc{6f)H?S9c07R}wG- z37IQ)_ciWxQc@l;I>PTEIDnHgL}-QG(f#cyTdUh#BAj;JN|C-Zn;jhVbAoe65e^X# z4u5qA93reET<8%&QwK7Rjt><(NN9J6arQYNNCuXTYDs>eo8skpwSi!_VhSID(eJJM z(x(7i8XiKa(G@0tfcQRFH!(v01uRpkg91UiQ1=1k=*Nqg%v8vTz|}s^j#!mZK@rl7 zl0Lk$iWHvlJ>htPCHKhlVw`=s!X$BT&%uA9m}x!*7QV^YdWp+}FniT|Ue{`GW^Jwz z%=1`xGixVdMmdYeI>GTL?EI~7tBB2qLd zd&QW_dKfxdLua5U+f?e@R8Yk>^yPs;6gzBjOYJ(j{+OD2V64W8J_g%eckd2@H8~Ts z`f?zvnVm2RPH>zj@y9tt1xRsdp=S$MDmu)iCY|&ZG*Y--`Gvl-N+91)@LB*W=mVb*23*ORWjo;bY%oP=~} z%-AOo{q&Hq0}nI2D|_o#ITjSdPIzAwub{b{6J!NAy2J@Jv6@d{EwbXJ!`~r)3zDhY z%Q94ot_|}?!~ZtawH!ovPosDNTaxFR>g(|WgH()~M8BPTE2%fqkqG{i6qV{!h9K&(TgW^|6;`mL$P^hY6mq1p(9ifLs1RD zyZdlnO?d^9uPX@E??6Jn_34J|E~~wOPZZTu{GRI-%#Nqj(4#Eh5>b)ga&yyFlDc3Q z`sVFKW@rlQp;O;ljrFZhYN(-}LfmKa6~Jys5)ptCewq!r$iCGsmTJ<)WuQkI3|xKk zw`0X^uZzw0YJ8|p=zsX{^2vjt?g?+DAdaXoy1g>mfTDP8tJ7#NWlnM93&OW#Kf0ap z(SxkH?OnN@US@b(%6=ha`nJ;-*;a3Uv?7Rijq{rYk{W ztv4nGf>*Q`LK5QZNb@${8PFf#@?VV|%7Q8`bHEf7x$Q`PG!kEpydL1UrXA)YvQB0R z#C=-S=ZhV@HtszBZanNX#cj2lcqA~=@nv6gjob7AAou@`*lg`Wz`IHHdogbg&&qc{ zbKOb*EO(^+nB}e=+JTY;`eq0-YTA%k1f}fGaePt7N5`0!>*GXF$7(Tq*3khtro_k> zr-eGio)OadcjQ_Y00lPsY9uJnm7*cta2>8h%y^6(1CT0Y+<8XK0cq+Zhz*b4=cwpT z;J_H)l%0v>z+M3A+gDb`&g6-6QC5@cM4$=AlkQm&)opVlXM#6v5K4YVN*Ipk)ujTy zMnCm}M{|e@yjQ%~q$5vw1IvrBl+-Um+)6zL?K0y`=VRi);OUUjNj`D06KC!d3J1%A z-pEiJ>Crljali4Y4+VKaH(}LkBt>i3GPN1xUOis~`-D9Ho7kkgdvmlP3(Ne%bzx-u z6&+U}aT9=e8=x31J$F1(~2~1Pt3Q zf`LZzjpL!__cS)z86a9Z_7>6BlHb? z1T@&Ft?BP>OCv^gbcqxyUjVC>~kC;+IE4o=d9kU;#KIslt929r2dZZ)h!vj%uLG+FI>2oJOrbpe*P>_p{z>fXxogQMka%<Cdmfb)??H&@P+#+K_;OpHQ{Vm3 z>|w62VJBZ%ll`#GS=MdX$y@f_cRx6s&fn|hE$a;<+-2YU)q8iqUH1PxpPj-msq|v! zYk1n4O7eWYC`|rG^tJu8fFh)@fUO2WO)TBXl_p^jXOnO8vqCMe9_gf5BiFTo0&2*K zHWF_`oSUL|pPU2Q&CDB48wN9@aA5Sc-Jp6mtJR=tzqeZ~^j0hgstjw-^H(=Bkv~pM z&;?jmayy?27|^x)PPMcSyV6&*&B<0I@NCPrndu#H-EOm2oy)t2?CrYx((wR&z0~&t z5ImUNGezB(ME0wUjg13Uz$5r z&XA@sA3@y^=*;})K3RtYpQAiGhtV%<&wi&~bA@0vGd7>AZ?81DMiFJ6rRICY> zWYL?5i9ny4c{9twS}%+^yHteZ08c=$ze%;NpJiXcWT3$u|G@k9DNY?8>K*&aWCbN0 z{3?6uA;bj#znpX3WwjOCjpF9=g@+&$KoHTGwI&K#aB+kyr9~G~csdAE(w3G2YtV=3 z5(J4F+{fHhIA5X@sK`_og;-yBJ+<)i7%r)}18^MxxS~x%7?ybS%co5MB(A=WXQ=0G%q2EBz#Ub7>h>=M&6ekvKC?Oio zJv219=%67Rc;sa^;Coh)g(2N*I2l73t+E;e^Pw?epp8(xa(D}Y2ZYgj`vpqVSLIbe zr6Wi*Pa=@pALFcCZUlGthP^tQG6DK5CD<9;wq^ z?)*pUv)FzANc=jD-}bnsZg;(V)zhlN%buRculs(tJykAIaJ#sdc>z#F3I092c_bpC z8aRWe_Y#0@VGka`mm0SAl6*ve--93b_6J$R4A9!uY9)X@$do=C-W$w5W?G4&69lzd ziZQwsgbzaiBK%m}?=A1M`Fsq=|0@Uz@Xyq~5oDgt`y&XSz4^W7!v{z*-y@RX@k?V# z0HEvP33W%A&61RB#A^jUIi{RbyS;S)kh(`FTJFRJg!ABg^LmW1E-a{MTQpsg4o<7M`4(Vq_8e|j){7L`@%^Kr}<)Pji8TWz3I#@lwV(tWC{6$Vy z=EKshoz3jdh{u_6;KXfr?KVs>cNT!Q*ybqyur1l@ z{<3^=kzYX=eNh*iSEvN6HksBfq8&wR@+i}wLgZpG&ng8NVWXiSZLQ(fdIiYMjAx&U9Mj~`KXAH0^Zt4|(avte+@8vt~onMoCjEK6W_hi<*D z`V~{E#?!7`_}Z1kzIIfvkp5M*{K_YljfuKr61Isywh0FziYlSA;hq?cc2oW)(Txxe zMt1VuwiMHmIcdMbCkC}b>TC&^K^iexy3)B9#x_g-eBR<|BXa@jV9=E=;HV7P&>^(6 zQlYKQAd6yosvWsVO$=y3zmH%jND6_E84K*Jc_?V$I@l?EozTn4X|erOpA0>rm>y%m zopGC?qt?K$tL#X%=J(I5I< zpA@Wz_+;n>+{sSQ@^$w5PycsjQ_i5RLp{-sRNis=)BjCo5OcbWpG*PbUK;$SVP>ks zMB$$|z<(}+hulrj(;UNs=0iM3o_j$QmN0Fupo&H=o-D#;Jf@Tij-$a5<9m>k%|?Oq z0a0CmD<~|A3xzQRXdpE{IJAC*Lk$-2p}{2BgGaCor^4%z$W32T0`NT8S4C%Ep5p@7 z=pSt^=hx2V{5`5wujJ98*#Qstj2R{G0`_DUlvb~N9j8Zf8YB>-+hop_uUO=qCDjqm z6>zKStUY0#jIYLr>T~$lmA;qg8g|l^S?^1nz(4;JfI9*?U}hd=%n*IWR}=(3myjT- zq=;u}KK|4HV^5L3m8Mi9IUD@xkLo2?OwRuF{|q(U2S<-D*Bg8SFtsh@&Ge@~M(!oi z^>}?=mq480ogP}fL(?VHY8EvBhb~KIp3CvLe(878UaGr;GO*+XfIE4KB}>_Ox;m@2 zuH_t^EH!>o7n76XY89QBLsn#2NxgkI1Ncle99T+oA6(oX;ftz^ag`ccKWhGPUOFvP?SQqY=z}oX=*HyslSM`*XTFJF~wQ#e7STH0$Gn7t0gs zoGjq{9EUy=dr1oz)(QoyNWjMO6YcXAi1|9mqlbO{Ff# z6qRyOlyT5b06rG0I#4}G{M7WoAfV!pfLJ0nNt|$dq)me=(FGd!C5t%0RtYQ0KZXu@}l)9Q(L{~@QMC=5J7TkJ;Zk69Kb6YO$H8V z5KDSIk{E2N-uXx!AJCiYLEJqJi^8rq1;zW++kA;pUPpCZonno9#p5BAxcEB*NQ6d4 z7&l)Sv)toelpF(^bY>@P3)*K#G6xbWpzIQZ4-)tls7ydRq^V(FFoh7}3BqB>$V)f^ zCy{Q-S5J!4W~f?gSRj&O97qvk97}cm)RLrbJwOLid1v{9_V0aaNR#kfHOyrp!}KiW z!vzGi?`cT(j0nfdFvJ_liAg0T+THBm+yafmESB+Yd@1F!2C5WSZbr>{ZwQm-DNHg( zv%a`Ax46``k2E%Q>7gB;<~!n39Ovb~d z$}BEEI;F0+tVDwVIcWP}WdE!;3z9uVW27Ag?qnDE{qa6d{He$-7x*i!gg+CAS{IHt zGn2vZ@&$(Z_?3M>Yo)nyYFeoK6fcwNMEleRYzCrCj1o#w@SKdPG=fh!m{A^wSU7x1 zW=u2DWQm$h!Vb$~`R1FHam=ac$Vb64c)Rjjtb`+Xvk$*L!n8&XXupb0?HOqF*Ei4Ca8Ca+o9!#FdMkdk4@7cfJn-AVkvLUtS*P9z zgLb-+nhTayR{le~HgCk>-{|6`1cAF;o#FOZ=ZzWn+r2xn0Py`?p5YJu^88O<;|tGS zvrw@hBm|kYciO^YaOgj5$qzeJK-$P*K8v#=4`hUC!l&10o)a~CX*+u(<$u*bz+;0xQ6DDoPZH>>Z4 zCcDs^AeR#1((xt`iRaL7lpta0r<5hGf+URMZw*QAc30j6PZIZQYb@~!t3ekSt5_ha z)H9O^w=S{+#w%D(`=2g`Aw<_;nEX64zNrY)&}Ae>Lrt#q4x3J$fJ>n6s*a0l&V9T9>Jg(PUR7*y{KyMxo9xvlPpgKKZWcDDxG zwzT7Ifp5(PdV_Cw5b4+98*S+agK@DfFSNsy%a7k8!g2qxkAoL}K_55Z-`gW{f%ZpJ z?DH<|+S-jNUa%z|lsB|rV0W8|3`cX{k?4JAwitrPadP{*^Ge|K*6u4Kp5Q7s!@V{t z+Z;!FTicw)aXX<9(}Ff%#kb~q`2k+9H>c~3FIZC|f2S+99i9K~Y&Kinu`PMsTe@Y# z^ewC1*$?oV)$uT=CH^38*&8T|jW1PWuVm3)-w*X3)vlI`nV<()lFmFyJY{uW#gj!#i?O z9qpCUycB~DK>2Wzk1zLMuR2%X*l~}u);@ujhB2gD!nC55#L?yL>9 zj|bW7I=Fp9+q1Cy#wYhwh>tB3Amdl|=<_JnQA!;MD{g*K;AMxm{R=W)nxNVO08Adf z>A=kUzo4xquc=8K+CUn4nYITEC9R3T_Q5huC`%^Sg7qnmOwJ(H{y z&Qx%CD;fCm<4sA;gAHC!FkfjD)6F+pftjR^xO#3ZA;LAJk6DB(nZwwk_n`$V|AhfO zppiL3c&ts?C?#i%l-%t;x)>6#wB5~E7n9^J$7IdzkT9XqqV5@sX#B9m0x6@f890hz zN+R8)%0}hj7HjZAp4s<5wy?YBqMfdY8We`Cs~$-}bCn}MEEZH3bWmR&GL_#moPm@u z`IP(XA!YyL5vJp%gH!ZV@PT)Yp(vC*e!`zkBno}K&l5e)=9Gylv(8!MIPrl?`Q_VL zOK&#d94z>6WkveqK1|08qIqRC_^VqGVECu3iERo`ir0|&!i{0oMi_6urf8$U#l-=J zfY=nxcM`5ri(*(T ziYbVNPpA8OwCjkqJtQq&S1-t9uPw#}9b8eaI7ZQ58GR=^-nYv!(#Z%%IjQ+oz26=& zbv-BT_gR-jH~Ot%K<}Ry2E<_~Kr_nXtcKUGwUZ=yO8Pd^BtX=DL29;}%$iH+5#T)X z?3#m0a+eMd&{MxJk2K=chV!bKv*VF%u!7g zwC~E!9BOhP+&lBU8|GxKVLoNs%}&%*-)kF-^Pgvv4gu;z2Pe4u(KkKo{#ok}Xn9dH z8lr94tvU@FnvzBA{`NooZLhuxJA?LSfObi)u~Q>sY_);Ux;{OYC~XjYHxw|agvD-A(t_H#B{B^vk;_3Xi;FfO zYrPDRU`f^D7A_(>-?pm7#hVngh?mr~v_-X~MOBViSL8xLQmu7S6V|*re(<7cg^L;l zX^b6pIN?#^jj=(fX$2GNOJ7trWhxY{yAtA&%cbOnyUI@VpcaqgOJLLaw7`5QD!(>f zu9TYtu_V5KIV+cY!|?)u#m@c-;)u!fEtg*uSB9t7decLrRCE?6M=teJ1YUtfp3O}f`b2Yzj|SkBP_PD6%>gKBp6fe1oAN@qi?&bCa&}* zkw=Zh^aynRB5bEsH5Jp_S<=Ro0`~@$E3c?r94scM;)7q#Bv;IvJSCUV$J?x3vd>*J z7>t{!7P0i}`1UXUSE)DZ!DUh=6OmGL@7;lPZ4*fSSu5t(NilAbmFVqay!?Ww;F!+<^Tqp*DxjS3MMW8M5|5Nu4jO5Sx~W++qq< zRUDH|T|WvvJ!7;9FW}wo+3RU0VlCF%$KQ(mQ!3vvMG2O!A^dMAc^5O&!1(uI9Q?JQ zDvyu&rE&9HP*7CirpI>D^t*_&b=|W4CE-YdoLWERDLa{&n;I03uvL~DXoR(Y@w*51 zyO3L%(-~HmACFi2Zk~MC&MN}BMrHI!^X*~hOA|bz--gaPA`7h>5n99Z!<=_qr&a;)aT>ho!vXlw zj}Iuqt;OIwYbS>7)eIZGDMvS7%wEtBMG*IdhL6&$gCF*_m1~H?WL8qV>RX}+HT2-1 zjvjm`mmG&oQ@$bvX%93h-%n6&MO8lWd-esV1IpIhgT!85XA81FH?ji_dcFL?`^~y% z2ZI|M(BZoWKL8`p@f3iZFVVo9{QdLA_>#K6AO*p`)5)jkN7pX<$JsL&bK+yjbFW;= zY}wPBth}8r^Ba8YLx&aEe#X59k1a=w+3I|RT4`}JpN#u>yzWMHvg;9CpbYCe!W_Nv zWV{4whSZ7!$I%8}^d~t(t;AUMJSz)q)V;)s$Y3>HV)!|Qu@A@7vG{X2%O8k7RTwhU{Rtj8@&zL7=W28+I>${=j6zG<**FPW<#$eZ9n zL`;fmq5D2e85gg=2$VH_xg!!X{ovjy=$%LUPU5ZNx%o+|uG350!ivi|1trwevaQ{e zM5Vz%aCh4#VQ+22N3-jUhC_U0`*kso!Q@ z>cC7d{B^$v%N3=Kxhj3jZsd%6>S4G}kfbRO(aN$#HYugkiL7%0&#%ewl($uONn?X(}F#N(64B)@~JTWVm)SR|T(!3}c)96j6B>$IF`= zusnzK7mNuYyN|T;n1m1E$6w@&xD45I5M)5*;p7eH!|+IsR;|!<j<94)91)v(0~GOMz+0+;)_w~J)=Y5S?l3l%kjm2xEZxW#8&xYRfgwkp!u;sQ|GIJ|8=q_t7%`jA)EooQ=QDL z%=>lU3Sxb1F{_g?kEc0YpkCAJBQVw31`IN@CAL&SDv*b<7{lw|{+-I7*WXld3}8lf zrXv*(fBSd7X4^XSbHDCHKmT3T*MyQ{Co^xf7W=X~nZHf4WFSgT%C`}>uoIzlJnf^k zcVK(eeM6+;q7;DuLw78B*SYLcZ_ahjn6k z7hH3h^@<6o@5`CDFylid?S@;$!}kyIyIbidk4p!N%m#Tf&rgf8l!ob!qCXIBwM_r^`%sZlHv@W05&L^ zqJlvaH{!4VX7gjmVP&NC)OmCDrDIpS2(A;lh}aKAU=hynkY&?^j**d)xCd;XtLJmv4I=+LL=K2 zi6kL0F_+VdO=S9NnbJ*bQ$i>=Lz6D#uNL+FhA)C}Fbu5t1#o4*r!%`N;@U1@LYk3x zGWQ1(G1o~sJBylylMeWLtlt0EmUw)_64-D5GU%V~M5PUTW9<@KlsDgt6d0=R2FnCd zbM9#QEa|^q@Nubq^&39iTm2R$dQ6|W!cL^k*i<0h!9ur7<6!bQn!6{a`#JrvuNy)Y5wVRd|uEpyVhhCsly9f@V702RzOnuZZ z0byFBPiQZEkrzBmHp1wO2|M`Oo$L?JBu~i3*{QS|R9)1Se1d^`J@jEGMy!^Hd5kz5 z`m0UrK`3rjl458&7ViojSdAQu9(>@`fwH1q*;N+J4km*-;jm!2x;) z6kgP`xK7`i@HDc>piNYrJ)~xbVCRTakMRltHlUBlhThVRwf7H&&js@WuwK=^@nHV} zz|jz9cNKV5F23b#KKAq)kOU4u?f9udgQ6y=J`(=N^+$fNmp~TUYyf)riJKOd63z^lu~WVAbm{-# z%-r|C|F0S#U~^bc@UCwvIT*Z-Zb}NvZ`DI1CJ^W`eU0AJ3X@C{gyANFFs$60AZcUm zyLoeAQhdHxUqqZOZ+Jh4fJ37>{xfv!ZMgZ4nh|ngkGXq4-{yUM^#q3KT`|`fow#x4 z*Zy)1FUeQ3&c)4ItSU(8Ebd)3>-GGG_rl)glsE@VIph4&^F={~LZWmvw7Knsyy0c_ zn$r>G0;09sc`H{OAWf&KMWr_*i0Ur;!Cf$Y6Sq#5Cltc`)eP~ zzWw+AO%|gTtq(bY09Ceu!~*wGFw$6R!Mh7+3&8gQ{EeBx46nrIQrVFxS&n@Ewzy~ZH$b{ zC}k#8;@hkvhj(0$;t5Q=FEe*46z$_0b$nz=fJFAdxf4wx>s4b6*y40yo)reS`&r^s z*1@JSm^E)uo9Grt9ED*W8>9}|9=+K%#+$F7Z$9+1t_`XEO3201Yg@f}goA2f6G15%o2Hq3g(5;I4|li9)Y`TfaifQyRU z9M*(Qjlg-3kZ9m=U-00e_?f-_h;=>eIG8M>I@xSoW%cf(gnIYUc48{5;iHBqLzOyN zK*i>SPFlqe+p`lf?d=feOqyzt`A$=5RGy!s-JdiAn56l8gbeVar5yAftQd=<=lbsh ztd4G(8$N}48cvNlcpV;W{{eF;{`P?>bmhVIW8#Vy|z8uH} z4WN+kY(p8m9gF|m;rF+OW5s09*=WA%Y-H_W!(fd2PbhTWRUF+n<3)YDm#)P*2pFnN zfODUEcYz#ZAjNMSgJ9PRGaA~PaWmm=Io<(K^g@)21=@sBq`9}n*f|EEmp3wW9Ph+F zmh~?MeiqoxHV5Q9DQ*8@hsU_1(0hE1uQutzle`XO5OXz=5N4Y&U#(|kR44TCt5#c? zMoQLuPtH<~lBA0o;B%6l{4>HC+|4#PQ*mFLFLrpWe`>gc2Ji0*bx5;{5#*R8l4ozE zAk(dVb~mq0Lyi|rg*3eP22LES6t^~M#d5}P>b4QFC8g=2l^;iIhb_R;r*)DIQ)hJ- zFWVicvmC}yQra*Noujl4xXJBZ&tiDVXR$#5X{#Y1A-veUor>dQHZ3ZNGx*uNK8!z< zj%9cmi88a{)5W5g;2G42EzJol>9t$BIUQBq^l)#R+eKTsE0MfxNF?RZ#8xD4ZMZYh zTRnNJ*YGVqPOL5pfSMG`*;ES9QA`Y4bz*~eh)u>sp7LcKgNlngfpu9l859$|v|ITw z(rtdKo{UY=g*|72kY-)$y-zVTzB2i@OvzF^l}x{>Mx5) zL8W}0FOMN~ncsp`K}B_V3-7xm&0E3;3&n4#F zTKL^swz*b%iSldvtB&*rF}!Govr$7Qt6P=<8OwW(uzO zsv%GTy5UVj!+pX&zg5~;R6;DBJ(hZ?Q4-k)hyCK+_xlZ!$dXf-T(Y0O{{u)R(~j8=^J)UWzfj4NDIuC zt2qoO%|WX!rwG zLVwWu;IE1?(5-~3(#cxjAl-H)C(l&L?=5mn-77O&EI+ksz|ZjlW7b~Kh^@;D!azy$ z1LZ_VqK#PyMo%`~GEFGEhFPD77e$Jcq|57&8->p^GwVJ8fVZ>aa*kC5t8Z~JxT(bk z`}QHd-8x_7^N~i$J^K9&J7^K@^-~~OS0XR}QtBpQb}y|)YOuJXm}c8s z5oyR^>%?l~x z2p=x7ETv?l<86ndqeO2+IZ!Sqv;GB0je`ZI++L6HxG=SGOg=`W%^X?s6T1Mozf3C= zoTpm!5p&S%%3k@p16TOz|IS<$0yOMPLL?x(@#H-_h+0>RIuJzvC-n z%38^v@;yuKC|uER{-gXZIu&;5mSFea*Du||;McaP0~6M=Qsazn$CVgp<(2Q`Z8Yp) zh)&qDyG03Q)nQ1{s~Jg+OW|nx?OjG>FAbF=!%KaczX0UGLFtDOB>YH=o~awp7Ljrv zLM(G~4dTY}9dRSoIsKn1ZuDImMHNf@Z*PJxbu(0d|3TwWT1c3V@&iwx^_s|5GKI#j$L;rq>jmwj{G<^CV10rChDrCw(PnLP{H&UsiyZvhw2OBRWSBZ5*+S@w{^%`-fPq5 zYpTRG-F;&3uFzY<>K8Rn7MrVjn>um3lB`VOSDQs!+f6tH$y z8VreTR-s{x(^Sr^7_tf4kn)b$zwoz5Iw}b^_JsKv3k;n<1%OIHyg&f8SK8lOdPx0h zzWA5pINHi2Y^=j|%e=5>f2oRsYa8-}3*w(MN`OJD2(E5KGN7!~b#j6QVIM>69*K77 zMZ4`^&KthWmH~d-wrq(-&~(e~G$^aBrm&C9Xw!=5Y2S6rFUYoqK~w7&1zJ^Eqn{SV z01Jg-ktx!#X<<^J$Ot7^dkD_t7Rz)E2yyrUvd<2%TLx{EL{Fi3;&5h-jK-cY& z+`1}Z;-@@masvcJ7Xyc?M6~0ttdbM=I?*v19BKHdQ=$6L!^%a@{(h6NzeiOZ-%QFC zD0r7twN~R>?F(6vlj6dm?%JqJ*47UXHA3~#zHvRql#)AIhSeGCpV>?)oGVv5M)niM z8n3ub4t~?9U}H3TfEqTA=?8`%O&TXwkOXu|MHBn}KSx{%d!J$9<6bAa>g%NL^f;CG zH9>G*EG}2lf~h~sr{_rf*&bYQMaubVGGYInFCs~l(Y0S1FR}9zGo*bEQdq-^XeiHs zh@}~h7IK(y-Dh^S-v^s%)ND;z@ts+bjB^JfyB`1Dq;(e{!TUB>z>jVYx5uqur}VwE z-SqrOg^hub-5X&k*o*}6)6a1)3Eh%A0v@1kH@Sf-{tuK&(dF*|uWBfG6ZA?Po58Va zGr@m6MDyahCQP$8jZ&<=Bar-rC{mZj;)=`YVxY}9Y;Sk(zNeB%!8H%NhlU=mZiP;u|BaVa-k25YC;{vkF z6@Uv?1uDq69A#9~=aK_;q%O6#9$bS}Fwl7wr+UQ@_nImbpAXR^Ut1x5D=C%B5Us-> zUzQedi5F#!CK<0L<+FPO?2?HBtZ-PvGj5Q7-;mwP0?znMx8RQd<1}kHWa>!cCb-+5 z?3-}9wP%dcKH@w#fj{d)el*nZCm(8XUpnxo=DB9kneV^z-od-?H3p#gcDl@gw4G3F+%b@b{%TRe)Y&k<9Ao`Atn5D&AHp63ww%mR{_XxTn&!Hl ztou1E9RB<5ul~A?!B*4`0gwVH3AgN}KviA~4K-UxGv492x8Tz0l(x336P3G!v~VK4 z^ude+@?n@6$I#O1c3^|oQyFDH%bt?Vf%Ad{uxIAJcfZx04ChbsOI&GN?Z?@NAAffG z_@nHT$Df=${zA75Q}jdvEjgb6*YXf06pXH&a@`+_87sNu5AQkqhu`c`yW(Zhp~$u_ zro?skNLmp;kmy3)n74)^AwOX7`uClcyf(kzUEGy@aI&D=P^SJU2X1+-?M{U}Dh(<5GP?59D&aftRnT}R^{2D{;7ia>dXk53zRpJg}et;UmO7D59XW1FR8t_x66vbNKMUAP{djCycW>|-hF z8<7Qeu%MKL7fQ(=+^2jp6Gd-)d07lF#bytdN4p@m3T5fAdnWJqQJL!@p~VNvj&^+E zX{kmZK?f%9bLqZb(a*61cpij+mdj#J7^v^bln%;n8xr)MmnFbyLc%_Vb^~^O2!C|( zE||6^SRAlqaDXl`0cdj9)9&~ZXeD~8WXlEJUxP@10~i&XpEFV^I^a{~ESow-1bd6a zp5cpf{K_<4?G?8(hJ}wG6(XmU-DxjC?;hg?T8=1ZrQqM_4&sV>w3e=8DP5*$L)gtj znwT2P3lS)yJ4?n$kg$*tI^?3(^tZlMY|CABwC-ZJkK1g5tRwHiDnc@ik%H|b!6ijF zy-L)GeZsk0_wM&@v11RA#8#Id_!OY6Hdc?vS%}7HL&i?`CyGt)J4a$WtU1)$F?~{zctO5Ut-iULhj6c&_7&$=NT-&9Vee`k$&EMZ-{J>5hW>uHMO`1>MvZ&JfxBC zvwUl_W8}1|WCmtrfgWypciN@fT-Ifu2qwUEnpluZ065N;ar{4nzD0MEty+1__j4Yh zB}5-9S)E|@cMS26*_YY0-E4E~_hGg{`4J99+)M~%T*xw*&Y=4+d6#OFcifB7%pn|3 zbOC05w}8)y@61rGqykkoF#Wm(c%~mNg0irfA_cIZ^(NtvK7CJ+_F7t}f1{>@8)-yUL37tN-Pp&!{q>(`IS2=}?@Xyt7CweGxaF}Edf{)}ROUvT zoGEOs?iLf=fwSz4R>3}Jv_{Yd=@~LY7zqSF{{4T=7M#-h?SJ@NU_m4N-_5Pm(Y6&i zaxBKt!H^ay$bkdXr2Ch1crSkbmDEeWd1apGh0qH(l{e6}KChqQmG!Fo1<6}HPi0H- zLvCYkn6pkW&!V!|PPp<#-AlppWv-|Vl1Da!W=9cT85F^TLjj;ytTzEArSOYI5G4E+q7%(BNmmNz+US z25p5?yAiB@fX}{6AB;0%`yJFBpj<+KGXRT5Q*$ZwWV6vrZ=9|iIh{r)KG}%my~Lpv z?SsnI_zvh#u!afS1Mmw}y#|z*I4bgi0c1ObBuxmY)^~Kvff4?@0R-(v^bHW=t$>hd z76s%_O`s8_AZx6UbdTzR8jShS{t}&yheH}<%B4l|a-L0#Gq*uWi=rzvb>kVni48IE zpO^Rt{ZqV*m+1~psz}%Y;NUFDWDLekW*8@;do)iKOK9FSzw_c99N}redQJuO{*i$A z`TPH??8ei;Q|U}uz3mBtu!(bda`3XkyG|YEpb&aiWmxn>4Zo5e9;SbXzhR!%;CZz8 zp?2+y{-E%p!T%~uuE8{my7#??{bSo4cRUU3t&wUCeC8^Yt*@29w?_D<7<=2<>!)<& zxHc}{g{L|0WMcvDQ%>M?pIdBrB<|Gaw@&meTzL4No-Mr(pHJL3iE&uhmywX8tRE{7 z$>Foe;rdQntLhgS>{vQO!82rKxg0P3x8tdV0Fc2rQhLQqN`Hb5MTKz4m=V%KucGwu z9tj!5KbCGmdaZDW(~Y`^+@bI&;6@lQh>j`{6P$Vj=d8k*B>~m__vlGhU zPA4$h7tyCYetj&7O8Hn`v(OmfZgQ;ew-eDSIVa)KuLR|fPe~-fq>&SEatJbe-{GHj`p!p-l&hQ9ER!n~)-fw{x!2#> zCUT2d+uU7~I(~I$8Y&bjMr{ImTHZ>)U6#8I`me|9^cf{kd?SJfu&}TS@HhYu%UaC{ zNK!>vLqAktbX`ZUBT~|;LT+>oQl%3F7);?ACa{_1F4F|gY-=RB_@R`(2^lKl+13}( zE+KXQe7iFdCO54qDRsUj1Qjg#a-T#*p?zOg55mE&<`B#gtix>$4pOm9(i-cyRnY}}SR$?yQ(Sg8%#AESed z_oru9Ju+3qE4LtG1l3DWns5ljPZIHG?xTUyo6 z{z^_!_#HzIkZgxKV1S31bWB67wI^CjZUuuoiK}}cnw>FTBV$qSKz}>8x;W-B2&Fu7 zi)XhVdr&o`rDFqFZX?!1?}u)B>!i01M;f}+P^ZoQS6t7>{7&mM@NlxqB!wM;8=kT< zLP;Z3=n?Yy%$Xs2FUvK<9ixF%S5K{286DSPuOm zTSIH)+ol`4#7Jxkb2N9in{)J@3)<>psfBY4x67BDsBhx-=!&A0)HU~nro}Nhl2As% zfIsqdvmMzEgmIx%Yp@n}91(^%avp=OH=b&g234x`2jl+T$$dUWYj@1=V;qJN{Sm%3dq)3@to`eJP!rilkW@i2P$dx86x zQ2@3dpDnl`_Xs36FTL9PR;DS&mz<~+R^gDHNF{fm?TZHf`G$S6nR7@ zYIjt84=9Y0m=cgrYgqSy>qJcXH)#tsL(j)Wv_|;Hny`q# z$D59cKxMKfs-eyV@{)K@Za9!$Ft-G{NT*SoJbpEbB-lfH6stt#GQZV80v{?|L-MMj zBJ*v5qIB%k(aDsJKgiV$rhQ%oQb^Y5`bNOpEJTOTH=$(VU8j(qWME@_JaC6_c->r* z@K6PN`MWXxhbP_&BC}w5Bzh*IN|>caOf4<5hGFcabilL(Vc5pGx-EOJ^Wxa~##rL}`GK$27`Z%34oZnr=xr78Z!Rs7-J> zo=h@#->~}FcsdxPv#>>(We+t2P~yRI9}R|Sd@~RMIhRk;Tm42|I$o^-5@sW)r89Y2 zmAlfWfGf#g`*4Cq%=-Dng;qVYxtkuUL~4j)NR~2U#kxF{&#|s%Xc(n?=nc51cy3cQ zi8+o#Hm(+`FsDESKqD!%$IRL_yA)4EIw|O)dG0$UrNB~^pk-uThZ6#9sRoU;E6J!1 z7A>|Uaw_|f$?N%ws^P3l%t4DS0Hk703_zlWwMt+L0mKBSAncStD!77nI%IETa@#WO zydA)oNH)QEzO;{?>q&t1=_05M&^rLd)@l|;JU%*C)k2y zixoXvtcrFD+M4r)8L+d3y0OBuSP!|_6#ixR$$bnc;GpP=qD?vT1^gMr)p?tb*~68;rBT)b6!V zuR*+V?Dw@(Ym8CwRAX-##Q>&{Hc-eo3V+b>pHHup>Kxmou`bFaxn4upyd7%4IdTpXP)&GWi$ zR!QQJ0rRWHsk9cz1J`V1TG>ZvmAT1U(-}*+e4saudhPBW3*8)JlfjN0aWUB44XRgo z;))fP(8KFw4B);_S6M_VEfZHv>&RaJq2xc!@o=q?;6pA)&tIS~m`r^9R1_lrha8TM zzl{Ys{!p}**JH&o?k^!P_`29g#$bcD#wgel;{S&{Brc?#jf0FUTHILJ`meGVo$Q6i z7|1Hb+R$X^7jXz3F`)VU%$2k`D_&-;C&HJA*#!eIIg+2wBpIv4uzExf0=@W9%IniB zj-Ivjt;^YTmW}vX_gy~6#vGPr)AE&KfBP5zD;D|2rPBXoZ7sjcc;p45z8Yh<@{tFrDs4~T?J$g`E-3~ldwXdumlt1}w3hQtW1S~Pq93?cQF2i|c zltIWle-#A18`LcJMc?~BMSeldVY8Fk=^=A}aFWx>M z@=th1$1Xp+#1S}eJW^IBtrlXnU{_#>k2@%W#ly({&$%?7o%+jtS3!w3lFDB3&pHzo zJ&V!b%SApdsXH}&g_fyk?Nn>+NbxjOp>|3x(-df?Hbu{ZSp}Xe`rMG3ct3UD;RG8ZD6G{f!leuClA0Z3ZAFd9}0E^EzJ!^E|?r zL;KWOaWgKLr9$s6SF06cw?_k910xH-a=$;Cf%JY>&WnE1a3@h0A*yhkG!yLPxw|X( zy`8+^ZU}BS;W{RK@J%SBm-W$F3wiqGH5T(2 z4L=tKWK{cD8FO57TPpYBO{v_AEvej#HB>GW5qtE)!!2>yDxv|t0U&Gzit^~R%~`X6 zI`n`CXz|iq?7Q5*fRe5y2XJ~7im--6z+%4rH~&fL1bnoH3M=MQReH9idU;+1d9_(< zzblb*2`?pnxhf7TT@vi&l=bx@DOIaep>&N%`mm8O+J0WArjq-!65lr)T9Re!vHGto zwmuiF7epDX&F+5dVFxiyOAgnR)S1A2lXTwb%{bsUpgBmF6LAqqL$^2y>n+B~Ko9iT zpNkSAHXwU>O-u#cL%4VPTm{KmQFJqIr(*(FnOX7xjpOhAd{LYy+!^ojmY^^fEzvf% zDLUV|B-di(fwMW`2Ol+HDyGII)j7~WMDl8Fbxv;*8>{@vWpGtKceS56H$~ZV)e}k6 zN9DG&u-Y~j>qWs{I-cM#C09w7<)HJGYgbbh;-KVqmZ-RW@BST1Zu=V3E`kKcXKC~-G?8`N0)oRTxQ}nsb#i?^FRb44OT{VvI z7p_g5p^ULrOwLD)@uER&ECQ6Z;J9pJ9}%r)fi1}}7AAUksVemL46xrxWg#B+`>^ct zOnAj)s;@fPSMn$z9MjcnnK23FMBF)^^H*(NmX`yAYFx+8zx3w`(+0-3M*$&U*(f_r z*5aK7eCp#)_HlCk@XC|?^5X*j#`S&NhUe~NA)UYqKOP!%gdcIKW0NbF6wqCsT`^CD zIAu~0=hPWjw{*0?2E&k?SoQE5{TNlxBe9jjUY@2PX3T?uxQATLJ;)m$jnhU@Z!o3u z7h)tb%q~&RV%%0Zj84<#h(@PWtEJy3clBN(j5hE)$5sL>_NOEaHDRA(F_<<@WJF$g zz=N&Bpfs`PEM5>q5|sxyL>BOUbRLA!)BQV>a|vDsM(xr=DG@c%93Y`-V_OgGg+Uz3 zpS!O*P$M52gX9`{)9QC`6Gf8~)Y)1R$tenc7LmLm`h33L5*-?vMO}%DPoXfza^Lwp z#>i7d7x*8nH7WX4-!M2FYFcYiS*J?9%hOY)m*8SwV-A&S^~);N;tby*1&>&apfE=l zwJ4T5fC{1zEGrChR6zI3dh~+d8mKaNLai2#-45}KzjH|DK5mU^^5z!k*2l~R+U}z@ z5VRG&@&A!}+&lEVU@Tda!5Ci|>is6XKI)Aj1ASgK(2obydE zAW%4T8!1bdi^i}M6_NRp(Gn{I)?v`tYmGIkp`9KS3xdS?DShSa39S(=7WT|$S6S9} zw!+q$^|#$Jjp=~tOKaN&ddJq5Z$6NBLy9LMEW+n1mX$S|>UeeC<`16|Yb5A(;(Xy8 z(?n&dMz4P8G~Fp-yonTd~*GxVC&c-E~U(zM`*v*8lI z>D-+dMcCVkE@C$0r%6 z#0MFcBl_1J`(0~#{}81L{L_6oZR;~%;zxMv-~RcxfA+uox9AMfVu!}O)szGNS5ql- zl{ABmsI9hZ*VXF&!*9rFx1ySc*KFiNi_-r|=^5SGWpSSSGLcw>tou+NdXyb>Gm3@O zrr#Yl$pw}C$tHOX^HN_eK9Eb-EUc?L#x1sC`pKfm2iPNw@aW!s%DU-BaKUDK^pcv! zX2Y&&vnJgafv60~Gze69FfRKeRMR+(itLK^6cJ}D$aR^+RqvNSp^jZYc{09%2ZoGa z)Pjscgk1M>>Zr)2j8^kWK^8<4Ga+-V zIo9K=NqJ#p2`!;nx-pbfu1rC{2;Z2FVy6FdmtIIepHcIH$~3`UcZm*E`6E3HbsdO? zX-ze|@W>Jh4$!QS3O9iVr=tXxJcwhVJA}1;`|JNJ8^VV1zu*1}u4zk27jl2P!Ne$R zW4&d5&X)1ogf`#RYM6zsp`k#yS8D}I-?V^Gu zYbD0`1$PEn>k2*)_o-+n{7Wap|FV?_k1KO+NqnL&3;1sR_=1=5ZRN(@UEr^m8qp#; z&!RXVUl#47jhro42hf$Y@vaYJN*6t@_ojrHrZ)V{l@lE%3rQoITNGRqs^m}pddH&) zVJv=u4EB15C=wPhgr~ASEcgnbC8*08rjS@vq=bzfHnfk#1`DYW?YiD+x1;*r37(IS ziHVpI=|T|kPT1>k*Z5qsX$?Y@FIRaPV1&a1D|_&{(>KU>;HwR%|EIY7n4GLRUwU3n zn2{lU%_t;X~o5u^CA1;0dH9N%)K-yGQ<&DVIwK@-u+k% z74egEz6D4nHbLJh+4t0mq?_gSeKtuqCn9+-r z%jST)RjFQD*iEHKFAWyep>{-ljqyU{#3m+;&*tR@3x+Lkz;NRm z`^8V+d++&AFwmKfHFiRD~GNd^@kti`_ybJic zMEk=D(W>rz{6+UC-AR7=MVI0|@NVz!=F{nHNl@Gy;DV4H4Y)MybZO_fci&7xRF)bL zVFb(+j%JZhoO0Tq4Q7`)QI^G0sc;XGbHt{tLvPH=cVj%^Ytrku$|8_$EDSs!v}!LeEcCp z=0mgwY_Pt3K4#^Z)(KA(6l;X_`Uva~9vos4FhQmqqa6Yk0Yb@ajwE!pD7BM1wykT! z>VP5P@$AA`bg$Ulpl~EczsFk=5uq(I!af{RhDQn-&T)3q6_X57Fe5Nz-LHw!CA zJApsP(^1|7+BSHOn?-b>A)e?ESw9EfsIERhfZ1?AqqJgIgBY==q)PFw|FU}tjb?iq zRwbEGUFkLgyL&xfegpHCGafk`FW_K`t95j>360Q6ro9?&=?NL&az5)K1d2~BDgS*{J~K_7S8J~m1h zU5QOD*ae0^3)RNo@nI^SmUQNcLO@OOFjlNws6Y2H(ODY8dW@EszZ_}4cnm-J_KiM zXN@nlx|lDoMWF!DFbaZpP+;e45Zg;SlG*jt919-_e3ppit{lbgbhevy5wO@So4VDz z6VRwMqA0NI8C`$?A78Ad7x4P8|8-Z2)qo%@D`|fy(*o}G!z9-L7 zsmG8w3wuCO8AV0J!ah=Ba%;A__M|&m^(d1V!IW?JvngQ?U65x4Wrve^v_-xkIh8~+ zj2Bh2Jj?n*HSgW;Er5(rz9w_I4u*h+$RNZo=a5fQrD!_We-#ftC+r^17D%M=CL0?f zh{kMZMxz&Za}?s%CA(#*rvDmp*x@tPTs0ejDyuQ%8(@R9ikieLR~#>;Vis8q_#z+S zMea}X6*g%i%W8o!lsS(g_Uf1%$(7~%jBOPp6chfMackPu1j|$`foz=4co8W7?+%K~ z8K7&279k7}Cfks%hi!L6=lxVdG473UKyW>>80LUQ{YU22xD8?&V$^ZF@16s`c!#VK}2f5ev`dEu_grVJ*=W0%y|c3 zW1A8V-x2${ot;dCSKdU3e_lBg;igqx$*SB@%4Ag1=qjw%eHm}{Nib;U#Zeg0br!E( zJPp`v^-mJ3_c9aA=1#7%eAk<1dJY5{CDrNya^QtuhJo72PQn&aHG~{XbU4N$!z(w` z>n;GV{B7!$NEuJGcNQ;Mnw>2OAXm1OC#Pac;Uh)2jzhd4fJBs z;OyIf|KIdmDR1H*(Qd?CG2T2GR$@{NB(p92ff+Vxxs^20PS)U|U>k&taw?+=%G93L zlkCYhr}czR>xrCJfKL9y8=jZDG#!6`p2xp$gkO`V0sz{0qLH};$fWo3^F={&OU1B2 zdN06wyl_^5-CdC;y?;#=UF5mDyC@UgyYD4UkwIw^RQ_>^dlYv-X)5T%Wj3Ev4js_f zap`m(FQL!JynKc;jmFEYew}f_SSMfIyN{|P#<`*t_1phvkKO1P&~Zze%Pt7*ARg^9 zTY^W~*vdAJ&{9F3Tmor#e3{>1Hqm52g*m#d{M$eKSAaOj@E@^#{_3x}c1?~k5cJFc z&c8hCvVO=Gm3#NG^)o2pLl8Pik;JiqAN=aC+u5Sa$kbf~?_}L)U6BR(=^J1X$iUDN zO@DP!)B~7zpCXLsKlufD7)VdqDUB*XIY3uvW7FyhRc^+R#XE-ivr3y^5pC8<;g?5- zNHhAy6!Y%HawnpezPR0$F2mfT(N!lKz2d9joOqtJkK|EFy~h<|RxxrJjYl1EXXY#1 zC)tfh2W{`iR0@Xk_`i3ypjvMR)`+yd302#P$Xav28XA@$XLp9Jqi$}76m%0LZBH&G zpf|}SNRX&PINWg+J$FiH&H+h&Il3&+(AXFZ! z!eT(0y!F!L0Sl8zs^y}#!<(9dJ&t*6U{5_8z8>9LW}$M;Z2%Zsr%Y-d5}TNK_5j#| z3|zj&9kGEPm)6Gc0F@Ntfks-D&T){Z=#oLjhI(3Iy2^N(^M_us%;BqLZgNZQ<3}8o zv3ET#eFmhOrG18_C{94lj?s3a%!chZm-sH6Z!sBaJR3ld>9^E}Q448!j)YfKyelO) zoFv4CC+lvQ70&G?)8sWJW^YS)NJ@KRkZ}ryjRyv-c!EnGJxK^{&7_WPr8b`wCPB_m zQdp4X{l%>08_S{yb!YPO11ZOJC*@154n-isd(Etyxnj8-Pn=b#w8-OMW#H09w|qQ} z9B)jdPeK~~rYN)%;gH1%Stcy3W$NEy8zWG9iM&6t8RHKB{i*EkeqOcWJHthZ24!z? zlTbG{(u+kKv6fP)lhM|6kWjV%C{po*(EwU)tRYgU36^~ zJ6J%#?e0UQpeX-z)sBpIS#=N55#YH2Wt(7d6k0R!kF~I(fQ`F=D+0`BaFIVLI;e=_ zVD;IN=Qj+o$6iLzS`dWRj+>Wa+hxB+?rv6xBaK-JlTrtlD-iK|ft@`n1f|KHxb%S6 zBl)TaQ%r2GnAk++T71cX1H%t0sqbFFsfo^_l(C^3_rx}5+E!9vxqCRL4Jb`a(^@2X zR--YrGLH1rg2Xsjm2$#*N4bsioO5~Pxz>oJT%%wS4g>@|+yjn*(kHLrb~~d|uxu&# zolNT;(n>3+s2L#EsY0HZ5IMOYN-c&(=F3_viwv7vBHadj3Dnbw^=*d92}$kFCreH* zb+H=8)hdhS9z%el{KYz7iVG2)7W`7&%8&|tqjVF1Nr99Wy`$|n7Np+N?Ub}k%h)JUceE{sG>Ho7th5Bf{f@wO7|pT~Dbl0I`U4k1pYE(paKptqi5y|mRgumf=cO#sMUx4>>1t*STBqt?dz zm%L^h&O9_&Jb$~Qdjbjzwq5nUFfdtAeJsz9v2X|uz@BL_*rN_$zXhbnRCx)Rd+)G@^hlS8 zs`|ers{H+bZh$QvM#p@Yc@&{!!;#29X9>xW35mg;GO;HlR1yDeq)T1}x}@8kq*P0# zp&`n|k8sGhMDgpSvXlwcTTp9BdCEM!69`7p@q`xDHR#PV5+4+C(K5z$m+9SV|RM{v8(=znA@2E{!AFLcqzMfosu z*{UW~nW`H~9`B&&k14WUYh5l6aVYVa+VG<5NZ=;I{v(|zcIyErAj%i*@GO6JNME$mHoFyRcQ z-g3wmj)^h2nnCGU9=*86#1g&%nwJ$S%uBhZ<(gN90q?EV{k+i^^!Rl|z7yDQYE{J> zaS!3csCMYX8hTsREm0;3I352IwF9=-no-V~@@sAbO3280cJt}&u2V7)FX~Zm zMjxsy;d?k9w7c18HW`#s5*;qebap-6V{uV0Nstd%iMdUOC~Xwp0L2n^y(?qabAG>; zoec&XN$D4xxP2TRj?l1N@|{W?emzTG zA$V8Qt4faa(LvZxu4;Ns#6E@je`sUF*>!<;se@5KSVR^O;ns%|Q!Gv(65NwjB>cx!At+0QX56PhYqq zdXjg2^PtH}cizfU-+ZNE;IPR7lZ$92!>3`slw9|yW^s|Lx;O>j z>3lBN!>1o&@J^K;RC2tU##wJpcdz*TT<~l#-$Q?OOkG#O^BIyi4lr_G9Fach7*^Wu z3=?4luoS7Qf9BTLg+oYH!wS@t7gS0h3C-@BESWVp5IhGs;GmK8=Gonw(18#NHl|<= zG`yXr1{D5*2oBG*43L^6ti6j6h-}_fV=!E&nUgF1_3;4cz6KTRo309~EPKcZK77?A z8BrB_G7D0NRM-XxRK&~aUG=qQyQE0()-4;PT$eCKVt49sYsS<0NmX>IP;67iswp7R z5G|pghu&n?zbH61fuewilkt4NT|o#mhVhnbGY6u)7n|>34YU|-icqb$+8QpO;IqT9 z#|bkPBz}%XZ>-P5(!ic8ccU}Blr7>kuQ1FfSpgd(yl$e>*9oqM1GFuxiaH_-=kyCB zalaB{sO!+^z*li=l+dY`^{tp~pgniWBW~;KTspr6iI@D-ktgS1UA6i?BSTNYY;-uOf@N4Fha2_-v zb|2r&7hUps97%37vLoC!M!a;Nb|o~~?0~!cbgA?17)u*vPci0_OL1o16YiSAMnQzQ zG$Jag`C6AibB@(R&(TZLAI--7!Y9KbOEXisqNWIzpMP=u`M%D8_B*U3ipxoXik5%^D|9JMAIs|6Cvv0D~>;;D9YaD z3`= zdt~AefU&^NfPN0N`xB34;Axu7wmE=8UhbGBVHAQ3%+0gYr=R}(2i>QFlY(fR`ElzpG;$Qr1Y3+IqWnvl6lw*JP|C9em~RkPM9 z_ArRbkz%Ky6YUIiMdrO^!z8|(aTn-Q>BUJwaeTRJ_mS+**5QV1Xa@4MNT|2$kB)TH z4ynJi-POW;}WZkV1KIU4Ag&S$In>NW7Yc>$7Kb3`I!P#d+-Iiq(?ue`YX z+ey@8kEyMRr~L#5fP2#DlEft-Po@1)&AFL8rwyISxLmBZ9~+&}5A77Jj1+SOe=UlH z;ML(DkVTg3KnLT%WWsBb(DTw_fcu}on|FoTSJ|Irqpz|N{0o$Z0B{xc39o|kE5!S1 zL-Fc^f1+JtjHl}AB+=5Wa&dg@nrSc-Ke4a_qVI|a+{%%59?hY@EYzIkyR5iT!U>* zVJKBK9>J>uFYg3>^<->AG+sMCyM~iG>7{aR>$vCI*WzmR3nza2xWriFKuo}Eoj}&n z30|{Sm4p&76f#xj#7EyrOCc>kIg)-%mpyAMlSg}`)ftQj*D7V=yHzdYm~_lg$EejS zNbl4y(3}%69hoImBqHTiTtGoM1_czcZoE#Jjg#W5GA-)MtbBY`RX%*hD%PGwSou{3 zWbB0sD}syZ_TpcGv_h(1YT|mG;H#8Q;Fd~L(u%&Sr~?NTWxyWfMnxbv4`YH`2fqBW zst_C?wbU&>^(&6F0P{;l1EBxO2(Q2LqV!krN2NdSK{G)*wIc4*`=|!Il{+p&Bq;1x zYous-i|^}^6A5dR5c8abw*?3)Vx7A0 zEThz+j6_%eOhTAL@rs)DO{i%`B>X5;e8qnwXPF-tW++x)MlT$1PYZQ6@f2sLcY=`C z4U&@xP4Vdnb2$p+nR=+V4B62jPV{@Xn@csOEQ4gqcm#WBL`2geVUe{?sWkIGj64Aj zWkPSqwmMr3cJ{?CDy{_8-;L8dt|0d)#lNrXkqEbltl1uM1V1sqas;fanu#3pD z8ym4G+{zZyO>`1*!emZ)JYTovA<}akP!kM5>h`vhkXIKjhx+hm`r(;z;?UcpeV7 zl^9#1vURpwBxtbY>?T=^MQN)jD+6ffLQ51#U0e&7tCX zkn-=k&H2HZXG^bWOndX}G&zEOx$SPhN7FZ?3`dWu<*8PJg6Q<}b(qK9q~|NbQMb8^ z;#Lk~iz{f4$k}gOcLPz-Je)ACH=GPKv${C&5wRTXpQVTxf_()}a?` z+aGp zKv)+zC>mlVs_EYSL|9W8k<>&vO!k>fM=5>3ilI^cDlfcMeNZn&MJ?2eRl5X}&8

%Gi-fLp+UT0`CT#(5fg_=ZW@P@YU(8^k|dz%W1#4_?=3| z;6I+N=97YZ=x)&$mB5At9$t`I$_=2kuG`Pv&C1o~9@e@mT~3AT8OmjfrH0O63^x*F zpS|(4T*3vSk~_r7fH-qMLaY=5O72Pv@0i@YGMo9_NsyknrDC9NQQbN2uDHAFQkU~{ zDc{F+4%~p)iW$+mqg|e{CFNi|#qOM4YE;j;0RQkC-y)8!O~DvTgelht#^CKb^mmY# z=7dKGE0TRy#BQ#sW)uY^@yCDoP1e!|=-IHXgnLMSVBE@h4{N9Mylh^20l(#BMbCC+J6CzFS zII(VlmA0v2t8JWp?>-h4Lg-S^lnA;8n6fqDJiwq(9=xiGhO+0pJU z)}8_YOvajR=rU{O#R9XKsT!KAc85J%7pDi6!}_90D47(uCC#_o7ql3n0IX2YH(Rc zIH_yjjzMppK*grS{|M^2hl}ORwNwJ)NQpbf52WKV{m0d^ z&8`xSa0v~l;Fj-_i0?XsP!EkvrZpyaW*P#Icu18YZl}xqrg_T7z9ac}O58{o5M4ZO zf_zwtP)kOTcJP(aN9*jHj%c-p>>zegTNkmV(-<{DX}mxYm&rKUGl!rFRZN=FE0HLg zHEZguXEZ`(>apgk9QpMPJ-K~EWIDEH>XWfO6J*P=8jNErib#w~`>I*5x ztcU@n-~h2dEQRpcP~|Kj%5pdzJV3rPo@r=XFhsurUhSwrmO_wCG!+=WzEDFW{&Aru z47$HzjBE8gF~rTl{UQdq7uv_Mlf-cplD;p3*cE=b6CFN`Y%KXt0*o&+*Ca*q#2hbl zJ=PGKHK37Zd0ey7!NxR@f)z2tKPT&oVm!kof`I#Y4j+B%v+H^tr2R&EJJ zQZ!O}W=wWoieMYR@N~A~`#f3zQAf+GVKG$^L~kdve1Ofmovh%AyYwop_2{s)0P4Jj zpCdgtG1W5!(&Y)Eg}E$&Bi*2{tQ>-Zd($?NIv-;-(6GCluq#2yYZr{u6giJl;;eo+ zuOKA<Ve6lg*_58y@1)}CndX*s-M)nhnbQUhf@7?N|C|0rUI zjm4%f*rny*&>G>N*RJ{LFa*l$u>%-avr|i|tztf8_m>Ll{G|a{3?qEd!%3_fguZO# zzZS;e=o*giBPIhfW-RTt$en{>ko?|03S>wl>Tr=n=cB}Kjs;8nC{)I(QAMUqc1tmW z(q_0OK`Ouw%P0z94-$Zlkxv(bI7s9|ISpK%9)7~Q{uNNmtm0q}q5aUo+7LACaFM`Q zDUU0__7!(yJid3og2-`^Dkn#8fw?yUzS`nU9yQx4Q(#e41AF4cSe;36It}TRMem}6 zV~s94RFagczs<@xg@^YNzp8wC1cHdX5lb6G;qBZ2W!z&UTpqLgoM#`ATlw0sd4E{( z#mL=VNS_$1KvHgT`#TY9Ty^J_KB@ycDn82_?l+^kirstfB}y87rw289#lz@< z1?Th(6-BX4aVOj9K(7sIduS)3;&1*gmFy3oZvpc8Ilm-#s;sgC#O~K<&h@mYXCfUG z`S}{W$a+NO;o}Q}KK{^45_jCHcTXJRGsNeP7v~uuKzo# ze2K5Phuq($2&RL#(>6wj0PY7-%r;F>Ct=a5TLKWTa**8R7KY9MGajy`c0Amt9gj$i zUp^0|xbQ?3_XL&ob_>0O-k8wQMjGB`GMhP@VVx;LtPg6Ca0ZX$g;ondW5TQic^FDt z*3)~fdXg0)st=^}qU)VVTf{Gru3hhB_cOvod@9?^4yl3!@jMBaVto9E-@uzjU6YAv z-WHESGbao(Fo_?B&XY)p15s;*U+NgGtKid#r6Ne~a3w7k89|jaA@p~mLxvLB7`V|e zQ{Pn%S7|i6b}eMxX5AkSisZ+T=gz1t>e+L-^huNrc}-kzxRy_Z?T9LBml1^47v8K$ zM?^M6S=%D_MnucmGKWq1Mlq^S(ZyQ7HPC;UB&2nq6ro_HX%P^MMV(9nj|Q|8-sw0( z6d3@Xn@*I#!?AqS==OYEunQuxwKiz?A}1#eUpzIaJGW~oE$_tJBkw1$OW_=R$CaihjHUICyM#w1$MOlTEIzx7?S#Bl`6uM=M;~ zej_rPiX2wRh1qSIN?6a%R`Y&#o!U9p;Wk168eKt>0QtJV3^&{oey`fw0SZ#EW&Hb) zdAkb|H(^=ubxXyE5#=psOb$1=cg0@Y$jKY}mDc!Q!v`C=dEe{5-+Sk$KikU98%<;U zyze}C=X>(=Mr-(;a`Zk6>gb&!o!G+H3v`_N&azXJYG58wa@`)+kE5o|BzH+e)E1D# z>GCJ^{2o1D?*w)iaLm<&Qx0K%U`3_0S|2?=efslH_b&&X>_^9+JpS|}_}?=pmL=Bu zBd1NHXg?lerTcsL-I!$63*2J6yMzgQpg4p(V{s984uo5_K3nYWs@IktVycGCyubak zUv*$%f8EKRoV}iY`|E#q_zjY)M;ZQ-efw`gLV>^j75@d#$yfR;ebgMrHbJme019PY z_yH@;b-l?Hgw;VY2kKEwfyf8TH%0iy#RScf#iS_vvw0y!=&bovAP_)tk##RG=;ruF z#F)A#2MH`qtq~IX2!nj~>0{%(l(n%zoWdM=45BQ~=ZyoMaQw0Qmw7tWgQ+ePEyRt=raqmOaJp zrPvy(H&*?zUiF`tn{Cc>WunUuVl)w0JhW<C(@anPi8&P-Y3OyDJ`0aICNd1fAlZ|sNe=rzbUc6FD{6j ztOi(%lH9Yolwd$kz-8Zo+xJIU<&(~PQNXVyEP#E#L}w7bv?0A1G+_rZ_=-tL$WMjk+>4#g5(TG9bi=!3$gVgOX}Rak1T5M z;Dfz`cbsusyusN;QAp7!+pj0b&N@7-IO_js1vAaA%ZoA7xEA)k2HBBdsExpxXZ+;z zC5NbptAm)td;vny7$^h)ctukWu;v_H2M|EJKcTyVe?1hHxxCo>@!`P-fJ<1Qvm9|( zvR=MiQZTi|1Ka}LLiMLlK=#KsD16w@aD2lsqZVLYr5%LT_%)lPXR9UALhN6s9T_a) zm;4$m9}Qw+QMw_i$|XaOt{xUk#V65BO`~s>ov;SV$c;0u}@pWJFF0r zqFr4HIHy3*w2eKn3JlE%J0~cggnj^zL#FtZvZfK)7lR?QVJEK8IH@? zFGSF=k=}}PV{n@*46L7kbWEiwIrS7Y7!1k4emYrqJRQRQ!?(MX*$uY@7BuFO+*L03 znMa^-uTeH4*>n7wIPR!grrbe_x*>f>I`TN6N*fF~9?~gTHo)On(IX^kb?IwTJxCve zqr=NbU8kNP@}D_<4I9TInzN#B$gd^W-M14Uf(V3q#?^Q+n@VrTKPnc}Vgfj~pynlX zZ*Y$!C4h=KE0=pG?>q#+a8wM7VAw}`I>2x*K=v8-272Sz6Yf=IXg=c69%7*rS|l3n z7u^o?bf(f=ly-W)935e)SH$e@xJ!9;OJK_}ALh*D%-`-VC^lnc>0+nzA&Adl;?u0< zV`17xBj<0l?L(IRGMj=3aU?JOB0JzOk!g}{|NXJ-9-}r<$&6K#^H=aE%Cx3C_5R6n-Wb)ZK4@o0#`|4 zEAqtzIU)m<;fEe;UdNHyc(7CY^f4~Vmt|mZoprK(fMW;564afaEmlSJ!&!E8#5M!6 z5%^yT(r5T5znl8`I6Fa~2aEvB3X@VY*URtMeVyxUSP#u#1Yj~HP^u811P32+A-(UYQJ~Rc2n<2lt57pY zz#ymS6uYh}$#~iJoKo;$K9<>UPQVR7{<`v4ak`4C62k{%(x)LcZ5U zYQ#rSFcYN8fCU5%xXtTAC)G&+d1oR8ndtB-U3aMak%~^C1mh#wfKZneYzZNU{8u|RhsP? zyPUOz-bP%@Aj5Hm=bvw|y&K?P&i&g)!g?&tw_G z7^W4r&@%GCO}nz{3LmgSMPgm?yi-f^6U#dm3XdR6#w9EZ^{CuaC znDd6C>a%bE{eQ#60?&wqy$bC)@U$=9pGtN17=lGljhL6U5C9YEbckR$gFguzqx7bi z`9)E`Yf7?*D>wC-!qFko`(xP_eeHL)#jZjo?j^)lLPRu^CPYaq@oL~kxZ4D{3JsW%8{KzBnKbM#3eel9K{wP)jQoK$o$dXmTeEm`v>0{DY9GYDlltL~a%_*1l$RQ{ zLUw4Z0H(+py&OT9CK*RIL)Bf;q}vtAxocb#M{Ez&XmgikjY$(**amg8Xofr``?yyh zwvlr<3ernEZC3}zgo0JLc3u*vt_Uqd<5`ry)ZxN2%W1C_l7?PA84WqGC)Q9r z2_HHZ=(&0oBCTf_FGR`RbfUyplcJ>0t)!5aGiSDrIY2Cz-G`Z)DFAe*CbW>)Dtqi zg_#UN_;iRY%GTCqQ<-W{cT|16Y@@f@o3@|TsX}pC>l(B<6O55lxA|9i22K`mNm>3T zmdm_1Mn7pXp=xR5);q#8LTd-jgSQOLAoGf$8Ej$=EYYEk z9Qw;oKm6>|kDfkz`q`()AEVVCxUq4Gi-m!_>13c`?>V5W^DcMy$*KI4?j;#@wYb(; zLIF5HrKAjhW%tY5ImI|h61&)c(fT%-q!@jqOqc*>Bma6H=HyQ0Wlk)Jb&0RX&z(Bq zh}_v$TEn9(x8%s=X~Z5B<9S%4p@ja38vR2Tzq5|DIoZ*tt5i+6I_%hKBWoGuvoHdI ze5GVWC0o3Wb94mGpYRS91x4ekcS{_ljrrC_1hvssc{6|-i6O{C! zLk}gLRw;I>$&gf&ujk9>1n;5BHgWaH!_0{HEjPGiHPjEMAGy|Cq#RP2Ml^YkFXyH* z_JiPIT2DM^h~lb%5?PWx*CuTC7Mh}AO2gjMl$IOD9;WR#U zvhI1Y{0QAui_0}P9nCc#Z9L51t2xTk4d+OMk40GVT@&LAVc&Fz@laqWkb|KfPk`PE z@F>h~G#0X>PkeNSWjy)GKcKCJZ~uY$o!UHoHmA^OdKI%EO%lappxgJU$#v6Q*r%t= z2HDq#!BtBR3Gzo)YP>4Q$JLv?u%z9yxWKDHzAp&sj(*kFyF4D0wJ!0j!*LwYo8pA^PPnbGXRM?I(JQu-|Dqm6fu_fffk2clv| z+0ZDtc#(I_9ZOye5|WVmbVbfnau`icjZZnx9MrI=0Mq|8XxMUu?F zWg@m$N5P&2b!#u_)GHPv90Ti&TJ9hEK5nejW3oi+JPAXW`U+m`ii7DUsIWh}tUKzI z5_@|5$>Xd9m5GDbSzn@4UKffCFquy*XjoR`a zE6XuX-MjCMULwcCg~c<$LFm}R(Cv;35QFz_6Y@Ks2$wFYM>Q#ZFD9?{TFg86jxmpK z^hS~pV&DRsKt8H9Nx|-Lw9Occ;~0$fqPrWj!}-$VDN2+ijK(M&iKZmHy4NH8Rs(q8 zY^Xu*O?fO`Np{hU0|aa$WrS-@NO~M#6MyD(AYXREgr@D^yZ?ERO_EiUNwRdhOWM>% z)ha^Q8e$-*8EE4)?#iCiJrpD10b@z?B5AK|XB=olqbgQm-K$$ZiQ;DI6#y6&e|Ckq z4@Lj7BqvhbQIkvk1k;TkbciBVi}%k!Hu>oB7f*lj_@e~xnP57=9%3^pa1_QzRvWI( zLIB2)&F+FKnNSv*m%O_|yFlvE0DoVjl0sK0;s><)y&fyTZa`YeuY94+g-iI^^@2ctvb`6XA3`12P>rq_4{L837)=jL*4{+(pxpFSj2X* zOZso36C}z`B$Zu8Y8JQk@*N!cGa}|NXz2*j_%^D@vrzFtB?qgaE47q*5>CEmHZ?9~ zCX)NZmByyK%fQQ=cF~W9-u+c`k8on<=Sb>EWy-Oiwz)hm`OgQux#(%4m6%2XN}Cp2 z4_>BFaQI|;d= zpjA~I+HwgLUD4lTYy~MSSB1pCbQ5=xy{QyZ;_4;E&1QbBd<~yYRv8JM4IHwk9g0l8 z9GX|iT;AaX)v3$V;xpiaw=El*M{$x|2~m@*B(8M9b>hg0B#vW@gG80^_p1oVK(@vJK+;mVo zDNG|&kBLDWb(COXWlc=M+(CG4ib5P`bCVkyEq%FEXP`Ve&JmTYi(+!S$Ke(x%fFOV z??rFCT;z+}y^@Pf4Dw~Jj+$2YF}2qLR$ea0uoBdLa^UAo;AArowdi&+USzvQ4c*PI zbI=#CxGQTg>+BbS3waa%hGZfUt{b4NYr;W9twrTc(P#JX|63J}52_xys+Y)}1{#aj z*cs|pR#!5panYbeg`Hd+F`KIF+`HehsmBLEd?u58UV;d?pcGEh`}U|t9I`5y39y30 zRq7~ET%@P*@e#c-MSCj8ruAavJ%tNTh*8N|tL450RY=ZLjZW=-z-=sKmxxob317BA zkn;S4xW>S(as`{@io{uSwOki0iE$^AFd|)vii1qX7X`t!H3dC@Bc0nQyLJqn&=M3B zOGTI6(TMK1|KYE3&)@!szp1-Q2sV2T*226WrDCF7r10`Gpf7IxWw2&kp_Wy^Zljnu z93N3s=jZ?fAa2Bzw=owR}P-!^(f%;>jbJZvS+m5MCMUvF(K@R}M@ zEmT_udrRa7z!ZSSV&AmVMvl0W66|bor8zj#u2M-Nlq4xhP_uc-`35?#U@2oGhpS;9 zhDv27smr7@I05yyZKlbHNA3TN@7Klu=Da&675_?brKvVQvh2ZO`IhFy^=GuVzu z?|tVTkt);w^D2_nu-sLCGoEqz5nxLIp+9}{?Z5heviW3%1!1#)_|0B_gbEl?q@ORa z`w-9rpof`OGAOkkk*&ng#|8}b(qh8M)Ax0Pv}OU8=+EVqFrB z5G^TXaNpPaTJAA}#0}C`nSt)^f=~chL8Tr+PwY@~?s$6M;a*bknLYb3LI?Q^Xp{?j zj#ADGat#pXm4Gmph4hyR4(Q(f^a<_max&V7^xOe8bn>4M>GQY0`s*&|rs->=*=)dG zjDeW?fRBOXb%Uq%EMJrtW1y19xJAsTKi-!wK?>ac|NVcEYOa8RE{bt~M3p-JDCfpf zuW~ev?sl>#patz`p8#6#XFmnDaQMMb-v{db-uvJF>M!5_piSBgS!{q2543a@G4ZkJ z+JI&&jB2CmQm{t5eZLW4-KRf4&fe){k8kGt+0zc(I;ziggMD_MPDzVmE2A{mrbsoQ^f;{raFkvH{VMyUm`s3je972CSMI^V;Rl`U@Bij-{{djg zmv9;juI1x*jK{4hHlu#3$$>) zMQ{g#%S=UKcvr2;elmWQ zFFYofaAV+hFK&ClS^5ZPT0qDTP{3iZ?*eqmjxrg)0wl%@&h@Rz?67qRH~jE}4-U9^ z+D8T49rELVB6cOVOeV#-lx>(T2IT(s9ww@ww+j^Y3r`h+#F5bjk9&{RGp3W0H*<;l zv|}QCPC5B!oQcF&T5hZ|I zu8+cScWrYX!bE4k{qNkxs|$ay@zY!~Hp{SOcT7Isect(pOs8CFDbf9$N0Hw%H{Xx9IDh zCaC3ss6-f{YlG82EkLf>APn$XuuOr4*9g2+Sc-kY2wX0!m=6XNSv?(~Tfxd*NJo|r z6*zr&y5&ln>SSt7zATpc9vx7J4xhe8HiUZ-^uT(1TCS^WkmHF#4H{yn^ku!Ix;y(_ zK<31Gj|?&EX88n_z*}Huqj3+7l2T8OXbGHfT(OI~iYZ&;Nr({nbhS=Ki_t!KSmTPh zamVyDB#&m<(Mp|6-y{z8g;G=Lqm%J-{?IANIz8l}Pt@co~T!t8~NT;tO&E%B=96{-+>@R?}mxeI7tzz5&kqHoT z(d?K#k^1P$P+7Du8M6^15xiG9$c;<1g(il~ZYBF5^H3-2MDJGalh7+CqXCGp9G>Z% zNrr9`>vut{1f78DVGdWE@qc; zGC!HU+NnPLYDYf6OVm^jzQB+8;nhw&#x)Oc4XfmQ#6J%f0D>G3a~&iftkWb!x)61s zsss?WC-i_Lx{O5slX_6B2Hd-E^?+wol4G@y!H5uW=u^@PH%^Uwc<(-lvb*S- zE|zsm-i4=r3Qv(Hn$d$mIk0LM;{C3WH8F{~m@%BsjLT^>@=%KoOd#-p?~ocpX%ej3 zNZN?&MB9c%yaS8yf)M3+kq?BY5&B29`t5yUIR$<|Gl5wJ9PUSOapq&G3+-P*Y2Oh6 zG6%r4PIX#hrE5g?+<9G^kCpOjsIm(L_Dmem5SH$_YuXoBOL=Xu3D5^}) z8JAgm@g+Ee8lkQvD8e7*at}d%I|DsCh3xvy;{cvVOnsExbDi26e-ye^wSs_iJ9Qi@ z{Djc$1}6L~`CIUiTt+(m=X`ueB4kf;!L5}^$$+K55--W$(qBED_sc1j?G@43&nvLf2}^p;FMji~(VT5o>jseJ z-h_*lpKo}rNE~kYw_Eap{Eb51fm=C@&M}w7(1z=C94e^Zu7w5>ckJSI@budGSGRPc zL7y1n#ed)ElD=@4SrfIK28G0Cl#|)K3#_5LcL|sD5+p?BL%bwU4rEQVpbm#tdAPM5 zp^aeq_y1X?tWS)TC3x4*zPI&UER21LZuG#w2FflF!~S@=|4_o*jIM*WATblR9mR2WL{qv_ckqnZ7HRBku`Rq+ zQ7V_X1&&K6UO87wmSLDeWvVllNrK8c2*;K&YPRhssoLCjgdAt)g?Z;`twbJ6|8)4Q z8!+)VB6lb2T3IRqr?cgGy!Jr)s%#`w`yFp%@0sw>GvI^Ixi=QRf?;d1766fxZ zFwg|X-Lh)+DN!k@%M9Q(oeaclOKNHo(u^;$H4@wx2uz3SfH-dWn0|c#v05o&?SFM(7JoD9u8wCLr@4nOT_ut5Yk?b^S~AlNe2Eqmu-i8^xXw8+ahzEOml-IY(T(RZzM|sXA+R-1P;ky2tE9GM$yP zmJ$4PAyca)NP!q`354bsTure&lPx$ymUqfHCrs7~oG|2pInpS}Oq)WHOq}h)n7g_H z6(~Cr-|u4#j7*3_a5@uOe7u*aoEOw5O#{(5Ev(Dv#HkmY`bb%ilteHL9SzM}cT}za z4Y@op+G*zSfqW6j__CG44ze!;h4ZE`hC@*v^V~r&vxUKB%E(F=hgVMq+{5_ zi2j-Hn2zu?E(L5>-k?M#O?!7Kt@yr86M!+J*+<8cUf>q*ZcQhcb3yCEWod(JvmH&a z0sxQtmBJ#pk-hr8R9~RYXcz6|cBIH^1V(#tw_HRTpljD4RlN)~8cAkY_Srmtxw8G_ zT$o4;4WjDPdyLdLaOmYr&{KOL?qy$Nw)|k#M>YSsCsb?0bhnb${p6b^X#Z?8S^b^7 zm%snPU1W7LlNHrJ_0j9K?}LgU8fx6BfrURx=wk)qi`Nc<3vRX`oUiRwm&Jp z57AQDI-TWNK}mcf&J=7)7Q@ir|7T}pNH!K9(J2tE-SZqNFsHeEy2J3*TOiN)KR6^? zw#UHN+6dhsZG6{YLnpF49tbyZ<#%p7VsR0}(j`y-ic1FZ2FRc^0zCswFebSp!1p@o z*EM0sC01lw3t|iUu*-Vul}gSA;-gY$VtqwtveZpX4rZadp>d0yuId2Pkc?M28z22z=t+B)={- zi3NerN;WzBGZVteVdTW_C#Z8^Z&8kBvR(hy%fms3sZVDqrdh=#Oxa5y)7kQRc1G`@ z7qF+dFvq{N8Bvd_0$@&LPrk_!<)}AiiVHTuFZRPz)w+%N)eMmYdqgt|(FY6S^=hVC z*r_USVr{y-*8ub0mS(~h;)be;dAN~oGR)sCJ{UZ>i*914GRnz=cOQJe+KFAq@1lAl zj)c#b4Rw?!anv^j?Dr*FTm|t(e(l>Po8$m?TJC0Dw(2~|j)B0xX1?$w6SLn9o6W!R zmhCWWFAO}V5H%aB^-!p$);QCC5@Sr0!oPi^b^Q1&KNpK&hVBREufj=jJD{|)j5 zEJgEo0RR};02}%C-~M^_nu12?qN7|yTN%n$R#R@CX<>$JL(4vJOo!AFdB`Krm(uaU z7uwIyIoZkehnWpaS0`af2G|z9dqyv@Dh7fYm>WY+l@Jrg(~#%{8YwG}RT>0aqH zzF{{22Mgu9^iMMP?sc&q43}}Ci{9!^@=MD5m%5E(93`j_(1rLj%`ez8jqEv_jwz+t8YnJ>CO!6kixZQB7# zOhP}Kmtx+Ml2aJs4rF54AF0F0kEVhCWFY4fBPct3_qwm^=^I>95E$w%d7a+J@3o$I zhg&=40inR6maCX{A<`zichhc%z7A)k%wC&Ozd^spT=XMWlIJ3pcp{}iOM#b#N+M*B z!a3C%N(-~I(_mVwC7xfjGc%zn%TkfQL-FW_ZLv32%@6FcEmq%%)RC-D5o5P0oqDc85|0_NHIVU0q;P^T$<)qg=64 zSrQ237?xg#|495>$XBX9zaf{2CNJN7$zDB)@NAXE+=YAUe}`CV8zFV;uSo7{w+zGn zlgv0w%@SIOqN49U6!`w&nTLWg;`TF@Y>o}L<4vNiZyNd6<{0f?EuW0b0i7F^dpHkN zxLyx4qgbGCY)H3-x)`ydp*!rk9cs-Q97E9Xwo`=!p(E;?J>57n_Fihk>gXJ!-QheN z4WB#Z6~m*qKL)HjgF2m=O{QhXJZ_CdLXf zUl3ScQB;^byI@iyuA$JWh0ZqswDSuot?+Tk>f%z}>{Tc6=ITLb@0dr~`N88YmzBxHy}u_C{cRi=O!F{uJvc`Xz9Vc#q?)yvlE{Mr)QBbxxh}zkg z$YpT=jU@TfG1rrIFw=*tK$BnO?vK9QALf@##VHKn*aCv5f@c^|lsY>)p(UrmE?E;J@S872~Dux3iTUp zNke!WKMe9=FeIiNcpNi52cZsM?$2G{OZ*g(L!?ytW$BF zn9vS2{Rr)YUTJRT8rgsuZz|*}DGpRZw2a{Hz!GuYC)6b92@%AI?}vrJt%^V|Rb<$*K_#zzbE?3j`_?|81Eg=6k597+Ib+KtLlKwN5+oeIVn+J#l=?}jvv64p{-zOx}M zPT>#|=5}T64h7e&-ceqe(a_c{Z^I7HBhw+dm^(|#C#JxWV8#yOCb^?9C_-gl$#ntr zVaEj5t^yj#0r6ci9PD6Q_kxt}&I% z&5RY~uV(?4YW0eH_vK9<^n6jcG%STEeMbmP)il(sKQ2wNAIvM+-6g2*?y?ISqf~mu z^17hz_L8QKaSiGrlQvwwgcemEBiF$-HlU-4Im>S98r+Ykpd6y>lCQPHz%#z;TKzBh z+5e_4O7>$!9?ZaTDG@#ugS?Nqn~7pD^cK^=Dj%sgw-j%fuzp*Ey9NX{G`b79`{8bzKQe#4baB#=Pz7e&D$zpL_!e zKEkv5o2kw6>V?hGu#?90k?+*&f{MbbO;mXG(#sr`fD^Tu!9_s2p0dlOXnj^C^;A{` zh<6y6!_ta8tuaAb-6(5C2ZZeycnEA#5Fs#i1cI&m!kb~8IT+`%T@m0Dl$}rZe7z~D z_HgmN^Z19Im_}FZ7b59njU)K$oNXBBhCbgG6*fF^ZgNCzSi$JKN(LjI^7g_lKOW8- z##-u=jRGw(qVb&%^1B3Dx_N@$4c~K=rCY@BaEK+EL>mTK!bl|&H*7C+L$ML#DHS=Q z`lh+5&%<)s;rs8mHN;IjP*KIG!5I4(O>VgxAtmMS?s7Xt7y*lNPmzA2(_@JdU0SR5 zkET?Q{o7ytrPQ{Zq*kP62&0zoajhkiZD)%P5Hpa9r&ukLN>rM)Q(Xn5I+Nl2l$x(R zp%BVH%U)x4va~>euYU}5Aa&{ zRhOGIBPqjAT3wWgiW~+Gy(oYSm0bBCH${M+1g_QJQQfF>_mVl6QWb?Npi)d;m-sFd~Omv`;k9ch52MkUzkA7j+e zr=LaZl=LP#e4jTE6e{pF)Fif$zy=)D$Y-Jp!CGA9Q%9h^S|rLOVO+O$ig)Ll*bM*K zHh*^kO}Yj{JYH~FcCjZs!AMDd%yn(+au+_Fsh3lK1J^MWAMJ86Nz`!rSP-0ulGkuG z%_95w_>ZMg3ilEr6)y?ARu}zFA7f3c59#-(Q(E)K-L{EjmS&`Q9k4}_RO+Vo$xG=j z!JU)&2GdbsiMRM-RSReHA5Yrd!tzi?;3@WGzJ`VBqSl{%V?%2J`0>Rrh}25`kbG4eL!xxkUt?x&}&6)1)F z4Wz@2d&hm%Z6D#8adU;Gn`9+`DHN#EGF$YI>(OlDs3~B>rq2cc?LK=^~N8c>Lj)Uz`GeqEmJxnJUl!m^`O8y`mQ@+Z{d>L*XeH(wNei;O07 ziHP{vNaj>ZIT@$^5J6Gi0=C?IFA>btV9t3kN5y203W#qbcWeqB=Lwo^v+;r^q+XYi zlx*xQ*^NtM>QL0x@FAyoahcn&e-7t>hdKi_+N`=kO$#(r+|73IvmIwqQFz6fnp%2I zObxFRPa6$@6RWU;D~R~iS9G?ZXwYl6G%bb`%&)pu<2`5$t}`fidd1Ri|0xV_R5(>0 z5DUU9?J{{Q!}9mE#IteWi^i3~a>!W^8aqx)mW%6lJK;N~jAd64(6fK6x$T58rdv{h zs&W$ORgU1VI{DnGZCEWZjx!98L!ghr9l48Bi_U=UWXaPX<&k?^P@FR&Qk31``ZQZB zpBz!!nu=J+!d2H+*>*g!CBSH7Fu9hyv6ZyHO6?FsH$-9+wESvKh&MM8t(96yc;o}r zjqL9FPDz0zD29g$6w2VrYo8e*YEu}cB_gA0SGmZDA(v}+BIydR_<{_-sM2yngt+2! zyDmydM5O@4^+lr+vI<3&dvt46t4Ott2M~<~UsVSAD)6U##pwhS&DOWZWMS286|%SF ziAfredb)|lx|iyo)sK?=%5562To>a>gxTD#hbZYny+|)m*`$1XKpEzr&XH)#?Pb$fA)OUDZh8Q%) zUP87UAT1vrYqr$% zC}#1O3}u7;HST+rC*?_wDB(w#FgS_wEArpV3b0psE53g;F+5jAa-dceI_zOe2ab^1 zWALH#04WVRtns#kcs3c@giVS3r!J<6JxSLvtf<&xWXCg7Ccgq(LrJm$*dNb2oJk`$wP0&61dDR&wCryI6 zJ?_t$!hdcuXrng+ag?5{Ba>Wx=d>z^C8sr+iarJ{P4OUXB{t%f!j6`Gb{lB8{vNX!pTnH@;z$Xj$XKFKeedm8oOM$X23&^zdV zuw9Gz#8lSb__KrW-QVce@jL8t1TfsYzg;EyyL%_mJj^wgh0vGAJ&9zOdS*BFQ+kv5 z?k9auY~x6a62ZqDSIswJ$3aBt&okQNjG2#r{f>4$ui{BS1i0o zpnCS%v*V9LUt1Qq+FmR65^)pb?rBo>8MR zy_4M20wZj3X($cqvb-Wrw-#sl3N-yhub*)T?@) zLaF2uoXPDV00q0~er`jt>-Y8ZTWbd^OFtcUr1B+zDx>cn7 zO#JFb_ZVJDKT)*e@j6dgu;e-_X<^!mHq<7Wx8h3Ma4hwEO}N#3HK5V>2jXOtE0p%K z@sAZtm7vw6hz}^~W-|bE=iqo`=n8nB{S=N3u#Zom3T7J z$VC_01JuM@JumgqB}BUhZn{vyGj6)d4@LqGK6_D6{`!;lT6bL_deyq@n(t=KUP7;( z{kgH%&g#UQ+;)N$RnJ|>k=D@mgr(d4Y&DFQcUuG$rkx->m7VD zNaW=+%6W8ao0LvK~f4C@n#2X z-B~65pl|EQygzh}SG1yqv%^!Rq(G67Q?AzttM`MJK{{QV^$zrzjwAnS%^DhLF*4d( z#wLzfM4h8G+U&Zu*IOL2IvGz*ee1-`G@oPvQ&v4GEUUjG^M>AX|7;^?`FroZ^X>;fy;EkcnaTRf-}#<% zbIme-hh62GB+@WL_vw@p^KM<2MpnJ(%R+`If53Nt__U>n2_(mqc z%VEY{*Qs$gNdGY*qnOQS5_!3gw-nNm96L<+`u5lVnmZ+;dp3^Ex&l`IX|cM@r_-!l z_4`Fxf}GHul9w6&{q_Hqy`Fx9u5J6|;Rg?X+Eyng*7q1s&ws*o^ZTrmmYTiV{fFOl zu_Qv)0}y*tGIq+w=HFPHq>MwocFEdhlax_dy?5Uk%_LuWYFb^PyF;>h^(F79#645$ zn{9`w33a|DX50~zx~~=CclYi~oF)3TsXa`uaN%k`o|^;I(0CX2=|qQVe>Gc`lUsJ) zcCV)Sl0_+PFHg51h6%yZ;SV>u#~|p3noVp{bnsD9J*DUu&vAjdvgB#Pi;uZb*z*K` z!s;yDb_X-8D}{|T9)k;G@M%(iQPTni*1phuKi(9rfZ;?7*)=)J`SjKw4d;) zPUf(KX>QuxQPBNjfuv(VIl)Wn7lT0_=rhs9A?Rgk8CE4-c*GdZW`k@nE4a;1xf%|s z_j~sjX9~f4_azVBtw-Cu;}-YZ-=E{W{-Vkit@E*5;nRT0frq>|o^q{q>{5X4!)c{@ zFTeNtRW{9}ONk}{@-I^|%IkNyj=#k=1^BqF3_=gHAfuB8O$%%@^a(ow;}uV%d8Ggm zeXKNKvm??IzB!~H(d{7WK^b?jY(;CDS}%7%osJyE&4}Q3s-)JPnsIHrA$$abu@MH% zB30dxO2z=iX`q9+J@I$JLY2TZV$^+Z9RI2#v!K1Z) zQI7s{-x;E*q8I7Z(y5c@gGUtCTteqmiU3c~{a11CRNwLz_|lmNh+T>4o_lEB`2KtB z&U@I7L1KQ#`41vt{)uV5`(b>K9^+d@>$%wlO;G*>&Y;w1ViMHh>07*y>%0(l3U zsoUzrX1&0NF7?ZxeDdY2gX@VZ2aD~>ypmi%e5yPeo_VS@OOV7+L*@vScp*5SA*#T9 zks3C}q$EDmA0TT@mV(r;FS3c)m2t_x2cPijBoLjxnZ$-ve0_8=;V;xwJt3i;Q6Eb` z(7m8VYM>cdo~h5&nke#(wYWtY=sXXCP+O&LU@5bj%4W$SpRYX`rm9h zySybx@($o|ewmGmm-z4bGGHkJKWQ|WI#w0&aG195W=>+3@byL@}LXe{~O z&=l<+ZDfi5>3f60yZ!!MEYW@t^j1ORo=j)OJg z$n;urjWyG&+9e=y-!XuWzDiHppDAiQVWtkAadmQ{e%M);8yNOPSb6>xmeO8nCsw#L;ZnrbJI`-t!y%Tbqw?@l zPYWZRUm)17Bp?mPikGY%%dzC06a=1z5J7`6cNFiw{`S}Z+BCm*owzTGLL$RV+gEDx zn&ns_Um~W%p2%1*P%(e0y`%LT)0UpHd%iF8V(BoW3x~I+nIkYYUqPF=i8lMpt1TGe z;n%OU8nrhd(hs@V4<7}+GpT767O%V1rk}1tNT|;jlksIXhRZqVWGp{bI{!`2SvE3l zW3wZjTzjrkBE7VF#TDqnO#@}~Rn^958jl*lxDK#1Sz9*Awh7bGwP(E7mtjB1bSqac zbZci5Y=!!eyO`Lek8arm{wk6t34*W02$FXydy^4e3srk7yEz$~sZA}lyr&CZi!08? z+>!%u7^Bcp%;{CkMebcfpI(eW?q}-tYs}EOn4#sd5V0cr^Ouc!Z(2A9;=e;s2DcaY zN7?T^{Cz40wA7k84*VkNSB^yt*!;bpAItH&DQ_E3d#?I#$zf;j_&I~Qj4{5SmW(Z?YT z8P0blmsSVQgVn_|1dx@$J5;RsEfkw!%NujWP@*{*mWN{ z4oF@o<#Y%10i}t^%GCGmP{R8Knjv+#Xj_ZUs88QneDJ+Jwuh@;%R!}o7*-24(2q`V zWa5ss+lY&yVsIcGq7-;fmdf5^Q6sqHc6cD=s$fv;m0-@LQz%#S-T z;|`*6d-1p%$4sJ6FNHk@EPyDvVo8q>;~|Gq2w+fco=oyNj=Y@B_(8%T6q33XB*LDA zy*!CUJbleNr3caI0j~3b<5c0mgPMUKs0CCovzKcv*g-BxD&y(S2fT9yzUd3o!w`Tjupyz(59wHsq z5iZ_tWuPaNUhiSedV9Lw9<8@G2ml!3$$;-p2vqsQp;iTBYFEUqbiOAr25%0kq|C(% zyf#v&zo8rB1sV|k$faWJhZP-Fifzz@s(X5Um6XqW_fnD;vJzGo$ zRnLskd}&r{7*x49nrAf3-$RP6)SFG4b7JlOiy~J12>> zqKC4IcClW@Ql-T1&ufI*DU2K}e5#e%fh^aod(C?4<+Cjo+5F(};Qe>un%>2-xvbbVAH4HD7o*ZO{0>_+w~VfR7Lu?|21=SMwbYSP4+qMv zi>G$URtn)E2@LMPEvIhQQq zNE}!eEflsh=F}!yI*do2$5JaKP-!F})w{dXSvJU*Id><^3eb%QRJDWpm|>LYe2G;X zsBjjJ@#DjT4<1SdpXCzgyv|GCv2poiQIsP!9%@%d+rLqKp0pPc=+FgH7K^K5fXJEVvX1*9t`{VhfAb$^8FE3Xm1-9nKFnEo7%HS=+)E00xjN61eze_A**TiK~2+<7K z;}|PIIGgDdB@`ToCug@hL~3N0m(+Pa+P7DQkQ5B#xLen*xKFPiEsKAPhO2 zGOp4OGNdE%hhZ-#?z+aVOgvD`T<;@M^ZTizv7G2{h#5% z{mYB21^oF@_JEW-{u3x%H@g^9X*YbW`vojNw)kteWzD#R6Bl6Cb+XmCNgZ z4xcjmb%Ksnj79!5hrPh9nA2d4A+TM{Z^J@cI7$qP3^01>O0#czN0pYY8Y zCYvwDv+Tos0T*onsv1>@AydED_~98O(7QC$CAIe2A%8_VhTB0eo{x*{lVUP~(-vY) z*$od44uSrZ%X}#{R&$Dm&SW>ZTE{3=@5D)F}6{T@9x#JwcdmPlgE?Z~6POf-|wpn1&8sPKZ?P7}gat?^dK zGnV)F>~^}uSKtjd&{_y+s-v4x{rjGS0)H7m+5Fj9kd#4sN#W&)bu%FQ}v_L z6JAF=3YWY=H;k5Kj}VVdn1taxM^wQQ`tr(PUzEaC9B)#7)!lCg zN}t|~<{X=9C#$W5xtfoBa(Dyq*r6J!mbBKhG+z=N{I z<&21y<0RCw8^zb6qI1WJ_I?^jRp&(vr-U6Z2`W&RN7p8*FH*e4cMxHVDLNcB6~3mf zN)a{ie(1~##r5~ux#dVARpbost-rMPzJ{08$=iCY)w?5uMbMM$sIShKiVxuc(amdi z?d-fRdP`)`Iy`bBs=JG>$|)0?>)8rqu^s~OyqI!D&sMj3<*?rMY|+<9Fp3+P;d@MV zL!Z0pamR^iu)G)>Yf*7~Jj5%Tw*HTtxr{L`q!hW{%rrFp-IBg_wCh%nX%j)=dd98l z> zA{9zEM@jj$juZzVs)aokn9Ux>t!Fg*rB2phV4`Wr>FGSPr7CqGKAvYj>Qw;kL?WDof}6we*H01xKcPHkje<^935kOJieg`B zbv|Ee@lU&IS5WX-?b=;w5PVikZ#-+$2f;VpM~E|GrkAnkHa!bVI(@!IAvp?^G$svn z`XK4wyN|?h&l9$~Vyrqj7h^rnPISA+@W=7`?c%d1=|`}cAaVsJqppj)`*`98>E-sZ zlkl7#`Wj$S=fyT3X(an++&TEyjU1D_-ZhJCuA zmYTw<&zh@@M{-F~Uj!aa>S9Mz>^D|B^;#nKfTZd+dYfUqIlI^N5~lm+;g;PnuXUJj zYE>$)9{cM)C+m!-$w8G&eSs`^pmb}z{}fSRH20|!0Ro^nG4G_V8UdeE@8F>`2{ED& zzE>pZhUC_JdHjTyF9x$}_Qoq8`p<;@Rol%t>SSj!p*{|yMot-7Lkh615&k`ISJ{#U zts^x0r8;I1DpebHRmqqe&IJ40%mX|G-YKKcal8 z*j)qR7+oJ(=AXnK{l+LI^9k(F))6 zOGvZ{c{WJRaTjTHS+fWgr|l9F;&vq-$&JyUP0ts2+Aqy{)1^TQ_|m7gRFB<#^RnX1 z_GMO)XsA{|O2I~Gc9Qp?HKHpsZ$IAviB1BUDSdJDl8EV?hg!hrcKdk}CIP#&SX2WF zCw)6h_FDr+P;@pD#z3_VdL6Vk;mG>2Shkn0OlP&h7fy_o)PqPM5M35C3#67pwN;p% z8yDy)?Xw2LtRBNNi-IjDl0B=o+YSz(6>+C$?Ke1)AZ9aQxizxavotq%Rr&k?NfCiw z6|UU;tljs#R30BM!lp%1JaxV7H)Vl+thT_aAcyAv)=hRB#4*P{fRF=UMc2=~EzX3r ze#T5TeTUB?CNDe2@m}Yd%pinMqg-S%)sj>Rj)j9!LOjAvF#W!%8lKGHH!@}{Rf(dm zCZmq;b>Hz0Gd6Dr8kTzaq|Q;xUBPy`p2@Z;l)TQjRkI`liOH0-wMVcP2^-za7q+a4 zQ`D;O#h-)M+M&~B^X~OBzD*E>_Lfa>5crR7w_iEa+PA!PYaNN#&IS?kUEm2C*loRh zd#B&d@*DGXvmx@ejJZ4l@5sXxw&X_$Nzc5!DUr8am&v;>@s@3~^QG5>UtYbC5?Y`oe}-}!#y)%+@c$0ODnMyvhL5*x~w7nA`dhi=nQ^enX)O9tDzrc{^L2|(f#_^Z|}Jj7R13m9uJoo_%j5dygTgb z>~0=0u5-9E1}Jr3QaMWm9Y`;*?L|?-gE^5sSn0{2HVz~DB=OWpJf^n_4@ zB%F0zN&H1GbHORdw7SG2m{PHieK7N-I;&CStTx?fnsU$^-q$^H15 z5=()Q(zbGrUSX*p!wr|WbB-`9E~(8Ot$H_WUFOUF$k(P2y4^m)#!h6tmZ(VFBQ9o- zXfq!&x%yxvjF`&G@t~lbb7}O1Z``|oKBJ9rp#_{G0=LFZji(gnf=Dh)>^NIG*2iE( zbfJqt5e5?}(Rqyi3JK6^5lQTl$vhJs?)%J}PF&WG+{8}ptu<=okC++y8X-tjz9>M8 z04n13i?Ap<;~8@BU(z)VvK8{c^xq3UwW4_aXl>L@T6H#E2(AN$=h;Xlf1Ri23g3`g zQe=Mweqt$oE1Ahp`y_VhI9^eTW@v}Iq?|SVWQ=TDYG`Ci z4bjPra!koO3+(2j9CM~b+ZC9?bCpMO_Xq*;jB612hsIRZ4*orK4>HWo=vnI0Nc|bZ zm*D&T!w&zn{~${E?aKbKfg{IvQfkqdFuG13ektLh46`89yO;x@h}`#Z88LKY--e77 zo{I>x3V3;jA3<|oFF2nVMSStBWUe9qy}ykRk--ow;gS8=OL*%lB?kEUj#+kKR1s?r?&1}o;6i*S^0~z(*S3ae z;m^*<<19TjFOTe75kLS22nq+63P7S0X`NAyraO7tgK`ak+6fY3+!*c{H3}=nl2MKY z(45(MjYH81BcuhH$jjQeN|hg5t4upb1uVdILL}D6&cdWL#jZp16Ok4R6?kaF^5e^I z<*RiYVA&+vLcV?zb8&Xs6$Y0@$7M}f#{Oo*m6gll*0fTB!S~n->lGi5e@mW=y`kRN zOkmcFPei+u%2wO-Xll10OT37;`%<@yf4od>#xyGVbIef-nb%9a5EYoD_KyRi^W|j< zE)E|45$CdX9$O!37Hn1tvVue2Hv~u?Z>dkOO&2b94ZqcS$c1O-(T=l>lAs!0a(c~Y zpFZY@Q55Jwv$`ynF6CkZB5E057Pw_YP;@_g_AeiQ!2!LIJgf~KSvkZ$h<@OmQv2}$ zkyXK&mn5o%yrHw<3wm>DO&pXGPPw0DpUzl=1G1Yh3m2B>XXcVoTw;C6JoZ zsGtU#-#Bu~_{$^)ZpCbStxy~OB0Jv6zSt3RqRfPTI?Cujw$bm(MccqzNBC;`*MKJN z`1VHycJ>Lbp-f)6&$Kq*wMxh01^rEOjOc>%?#vzc*QJMIDEzNKDdoOI#0OUzdX8~# zM7rfFO1RBRWQ?FcP4BisHy)B0BKMjqH~7Dw2W@Z=l2nJ2UBIw8It~9oU3k$B-D#}J zQ1=8vWYi0!o>5QsQ(*u&Ilu=r&i~}+R)VqWIQReRxjwq#G3!sKSglyJaqNt4^rZ%-oSp@C(Y;0X0 zz?d)NDx<1&w9?OeKg|eGZv8&;=KF9lu?{?#f8m-Sn;Uj5F<3P+_Hir*P|#tRZrSlB z$XbzmL3R2AY5QeD+Sa~&4dp=+%d6eeYhn^{5!`V2?!qcZJ7px}H~b4*n8)}E2`k2Z zQAaxY$r#B<#}&$*G>VOV>dHo27#qU)A^ORM24VDv6HSRzQ$PsXw>f{mJff>9z8QlE z`I1c6>hM89R+?l5Mr&u)#=I7`bk`w($3ZlTg!ik86ZIUXF&q9zL#vlfnfwN9ONwwW z8)>X-7$r-go5fF(KI?z%X`G*wI1es5!M;^7g~>%w>hmwMAO9E_>fR75Ku|L@xEm|U zNhz+z1EMP}E(CFS@BzK1u1ZOXM|}%xQY?3O0bZzONv^}>)(y?>%iVl>yL<1xE0{Q@ z0teoqbrk4u`2w`F1y&4o`HVgXoOLz4_LNOW&K@EHlK8I;!$?^KV!6baAxAq^^TlLk z@~jaAVZB{RaHODQ?D6#}#n!?WR*OY}K+e=R%Mr9($m-sG1P%}p;J~o0e&*qMzRDK^ zoS;8h4a6kg-9yL?vT`z8q8?f#on^aPgJ7475Ku)3 ze0Wvbe-z7yXW!2jEif9q$3pTjk_V_X+V!EkvNDkfk6=T;_s`h%C9XGKOui zbdilOFIUro{ix&8mwEQ>>~K>A)?5^RldI^Df?S#G^V{R0VPlJYP>>0Q3ZQr}OFD8@ zisswX2fYHI$K@4_NlWDEjuRvf>8miA!7HM4C>`5ImzYTWStQdoN1w=lOkF|N*YJ`G zZDhjh#i=lP-TU35?_=j0|Ju6K^4i|;9#s$Ipl|$=Xh$Glr`4MIva_ZUEsBl)Q>Z#u zMSF%7qlrRm9jtU4qRhS#NV41m#Uv!hfKi1R>q^{){u0#>LVrohM|n~qDS&dCI$M=LDU z`;~8y9VO1bYB>_VT%Xg5%Y2<{!O_>@LW9;3@L(=!T(6>KzN#pJC0l~l*hY=X9C0lt z^X{MhYA&|Gv}I@%iUqOXg+( z_cs3UimZ(#5IrnO@x0dAn%bY_7`{^X#G1U^=pDPP=xx6)`Zdf*@eR3LFj@j<9IjAx z1C7^_-kYzS)mGc;#c8uRiR2ObIbKGyv_>N1hSvryBX}(++c3NFCVpMhBl+uPqqZQ$ zJZx}U6Rk6kqjkvY-R2ZSn}^r`xa8DK;W=f4eT| zX^SCL9Dd7Hcu&XYmw8i3)jiutRvjE1zW+{fa3@*S&t%(-z56}488gfH9Tr%($Zz3?0j3Qz9+J`6lyxvGU zW(OsHdE0SmcqhoRNX`xM+Eo^UFUHgJqx!}*i7liXC%HmzYrsg|bI@M@f^T=nrEoY@ zs+|>aq%~jXO~!ijb5m=wx88Hig~V!=AdY>z(^3(M-_BB7H4=Z@=`Ue9G(|7&8T|TK z1f3Hr=BVhWn0SB)5v2Jy#;l5hBV$HoP@Zjt!g>+8%l3YM4~q|NPyi@%n|hv?m8 zVH5y$U0IjPh;CVC9Va_xDaQXC$&BoZJRzA8Ub&$Te8~m7FLshGkc*dej@ZW;L3Pc{ z2Ky2HQasU8oFF*%PKX6zP)$^lL}KHNtvyiEU{fRbA2ppbI#Kuw)hgpk2Df(~rp4p5 zeg73VTD(b$pg{P*A5;xaOwTUH~!#e+gGZrb8Ddx|O%MC2#EC5OL( zbH@>?Xg8_eCUm8#Ip@Z6TLxRgPs=3u!;p5II-QYqB9@>Qb8no61)H{hO^D%saED&4 zt#Wr_z>xyWM39*U8%|iMxv`8iQ+YmT#BrXlbUCllQv6T{rq&rQc68uxHM{1ncl<5E zh1A|xuSiEYztdosaY$WoF`8^P*a>`qX$=&r_Xq`+v#PAba*R3apy8~tD}1Qr;=Wx$u;Hv7&NcqeYOb1(rQ~cof%Hb`WAskR-1FBNL+$MqVT^(uI46 zYw>~K9>q!S4~{l55gqMC;%GNciHz9N#Y|GVL${V1PMISc;Ul0bo<#W7P)nQakq#3d=Dc(25d{9e1Gx* z!ureQO#A!p;TE-Iu||>|L=6NSPvE+Qo7jC?kw7No&hRaAVar{j0*YsM5OJT|_>r(C zA|>-w%h}iIN6Jx0&qF^=qd$?MQ1Wn>pPuA&o_LZwJdBPid@EB#iZALQl zR`_dEvZEpp1zz- zXAFc%aRw{mhKB;+(Xk6f6Tk52Mnbd_Z?d7CUOl7ZCN1>4t0(2~g4r2Mdc+srp5Fxl z+0gCc9&O}xdH?kSCP$&p?P^*S1Bw!ddq+$j$3TGm;tc-4;ZeY&>}zcH zE7)X-h0Jo=i;>iFmP$g;VmY4cWoWPE*yM+HCvU~6Av3T2fLLskj!rU7I2<7 ze=((AE;F810EXdLf@Qt{(_z;|UwPyL0F_y9HJ&V);BZlFP(lU=o&m_I*24Eb<%xx&POD{LSqPAyFsk0o!)J@-`*5#R;T4LQ28Ie#tCh9NQE zV~MHoV*8{5I$LT$GF{s>gyjg9z>rV>GCNT2{HK(Pk6%r*`v6M$TJIZt_aI1gb>d7W zr7}?>afRAVooHL^_45S4lZ9K$YLARiOnE)^t_%Egs;&zW0oN7G(`Y^Ntpgd>?bwq>Z!@y2B4Bt9zhvi12 z_YSz@iJVC4IOwIzG?GfDaC{UI47BY{d;kd%*~4FCZonmwnRy!RXBWbLnm8AfhF@Q1 z29e>fOTgp*gK$&UcUf8AG?h+iPl%QTK=LZg#OMZU*9j`C^NWm2oJJ`cgc*ZDNV*36 zJwsCw)km^FB7#zoC+kH!n69a511?Ij1rxNQA!%tlZ7nC&s+`=k9gPyLp9#$FZi-A| zmKM2^L6+LxRX()}5Pt=dhlMislg0v%WZCJivfqPmh)tTJ;KT-;ys_h{SH@l8fc#?T zIAp@Y#WW%#KhH67EL#-k7_ot4wZgV$9BuOH43rqjrGjk?u%aR*>t$swoowmXsZ??4 z=hGvvzf<7%?rvXMAU6DEDUYxZ1Hf@Z+3uz5QnX8f+#W8gE{Fg((mEIGLQZJl9+i5) zIFpr>>Gr)TVH7eVq1?j3HVni8R+G6zM`$j!V}LzBm4gvz(&AkDpU5CMwN!n?DTQ}% zNDr-MhHWpUwhT*M7@Layl3C_MIjPKkM1n6eNwkx#x<6vEZ-zy2a_+RJ#VVsScIVoW zd_H+f3Tvi#)$~PR0-?Jd)NgnsXofc(^M0?Awg(lq zS&JUnz*ifSbvK)3N>v^o5_q5TBvKbzv1EyzME_Z)>qa7L(7eKmYDTPRvL|0Aev3V= ze1-G$u2$7j?+x}W8dGDRW zJ5?$VC$pBNpS}D2TbBGveuu3~pG)uS26m#f+Qq`dV4R;*yTe=o1+Kr9zpFG&(bj2p{I~ z@&X-%?liqPdrI~lnH7i2eIg$L-N}TzER`W_9{Y0d6#a;B7L!efdysar9sqBFj&O?F zv@S@X8i1v`9C-FVb&^T8gq z5&k~vf6LtpOb+4eUusO+=2jl~;&{r{CPrUw+eXAG-prd{-%1*t4;}rIj6a$#cN=`t zULfeW!B@Y*wk*<1>C64Y3`e7Hwp&)EU{{0Hksh|q>K@#EeWBw1+Ohb^?=C-~5^ z#m;QcEG06IW4Hn(SSQssh%khBMSLdDw2v?nm@m7Q8j-D+61#{@1f=Lo?sXycVdTmS z<;H4SQ&juV%y{bw;#dmf@aVeM@hhdD%CfMy%_Z{9fzNLtO@6Oe80tgm%eazl+e;ZT zpS^wx9D&{9PZDnNr${OM(YHqU@Tnr83uuKA&?F8J}3#)<;TpHkrC6AFx`x=E*1 zEE2_25at0q0@D&CFgcE54)zGO7B3LDe(AytKnKKDUPB)CFaBfpC9pXU=R&i?L92Vh zG1*V$F{+b=d%^cV!lg*oGXenr`i;Ky4e}s1I}YKX*90EkMJi*$xyzwO{#n17Q0q6=L@_F zFCzQoNUfSL62HB`@@mqx9(EksRp?SNf&IcrP$C8%#pF?>s1+!77}+x%_ZGz-HlJ39 z9apLwcoENdvbH5*oXaZ>GwR8gjp`xt^`tJ8=ZX7F9FF((#J}wOlUeGi_19XKTX_WZ z_b*7ZuPy26c;XYz$u)!HO}*pby>RgOg)N)Jd85r50ikMIG5}1_x!cIF#GUJE^0Fjh z%{R9}`8?EJoW_Pidof|e)iNDj7GGNYpKpKtuiH|Mtiv_QzS)|g`o4*j7EuG2RHnq2 zai#=;Zx!W!7~aT4^??(@WETeDRqhhEWXyi~`$6ZxcKih~VNMo`5FQ8)EX9`ExN&`{ zDSa(xr3_d*EbLHpv7WueO_|oZv<(yZnGWWR&sZ+9a}=2pm*)!cx8#b z)e<1Bx1+^fJ&I);4(WV+mA*kp6!iAQ2r3Dnqv1`g$DGEGI=Ee@arwpoqY)%L4j70G zIhEB)Q46=w>r}DA>Ff+7jWgOGyU1IWw_~9zA!;`#DZTO35S6zgbm)+g+#y1np<$Iy z(Nwc@OEL1|EsIPS36V*bUg>IW+dYr+_S@MID(bSGboHlN-l#R98pz3cU=Lts$%kfC zus!mvp`w*vjwcj3AQtIu85ay-uh~zBsuF;w z@m0=WE#9D}K~`a%Gxkhl9K%HFKwP%pAhv3>K8`Agp_BNAb@6uq0F1pF?ZmNE;bWI? z;=vxDPxB>8k7WmndX^xOa9-B2zMamvvP=-(@K{~0Qdll+$B#VA1h)|t!)mt!n>*`G+E zNg+-cBK&xIHD1i72#S3jq6Hro*qAIIaAkOupUs2WZ~sfX@{MtjEGX=QqDcJ+3wM#| zYG4IYoaPpv^`G>2EFe!;O;$oKZd~tiiCYerOSZ>+x-2!V;mACOOT%hE>-Q2pA8bZ~ z&zkLtB8O!e`f9u>zh3`D^)#Mfsr062L4ARF(Z~rF49!lk)<+iV$Q~SU;U`?1Wx@%( zIK!*^dh>dKZ7nj2-6)q|z^33EhQMo{T7CimJf_e11`+JK#X1@;bGwtT-5uM>N&BWq z!ms5G5DTAg+9hTVH`%4KV^ooKVSHxprFIn(Yk;5w`tho8*b)Rdq^OR01YpnB6fF^4 zc?Dki^K3;X1$mmLKukcLg%lyO=K~lP^z|rzC>gF)B%*joSuTrwFm~Z63jOL`KFiM+ z1+2CamaPZ9K(h&LuwU&T(+WPDx-;-2_`w|bWl(eCMuwmY>T(<-OANL;lEjH@c@m2T zNAdV(zSsvGEf!edvwS*rTWogYQ3s?!VoVMORiL)3zqD#GI|0+t;?9_zxbgv(yU{H{ zH|J3Eekc2k%%%I|@)TY>!*>Hxqu2cj)=GT?Kx3^{Lp^Y~2;{?f1`GA-kN;c&uL)GX z$BPD4VQe_6Y#7yLBq+M5`!+S6BjBWP!%k_{8cbty71?LK$@pAi4|D2SI+YZ?awSn| z7=(~7a~8bVQ;KsE@&9l_@du98R~dY(j%hgFe+|k~fzZRIGN=97yb#)WyN}=O^H=ab-WvW>4)Wn7VGmc(?6liB$Oc@FNB@ zA_YjUUdO1cd(A-UwWKAiKYp?ut!s@Q8wUT!Pn?PBQ(0FtG1uNPoi>y!*N{M%)`(J- z<|;9h=kcWeOiH&xMl4VHhGf2&I#X7mXt58a@)T2k9k7L zBQi^tb+p%PGJ2!BiH(~@LOGgz@5dN&47&)6kl|CwRe%3`s>GdC4>G})cuiO?P9-Yu zQrl{P2ReXt)%&#=sHG8O?Lr#A9j_vF48+Su!|xrpJaZ0KU=hndl3wpW=5~_%F{dHx zSVtD3H>#U3FDE1MuM&~?DrbCAu#aI&ZOSY66}x~_sXl?La$AE>nQ3)sydM*dIyPn)Hc?|s=C%@(g&f&+ed3r0R$184Ws4|mzCiZJ_$ z|LF&~Y-LV0OAmhj0WKe@?1jR|kzS|8zRj^42v525+7k$*CI{-R>)ujkOgv)9ige&KE=CC+CY=0Hv@&FtBnjJW`>R*4%9j}OLD)5 zf>ZsFi38AI*G(Fm)8X%rivD;&2i&T)sB_ngDg5?SrZ@&k!MwTka@#J{BS4VAl+6OG zEyfU;rd?Q$oDX->F1Y(Ox_D)XsTkOdxpK<(G)ATsphC94kFQLz!h3Qx0q&+2Qj5aX zWrdhV%c>xou8ZP6DBc6{TG~Ru$LGmaHpacQvA-4zham_WBch9&sq-#`7-%erwxSj@ z9vT5-zlDP(kOhAwJU!DTG`<(j*Z1a^q&YOhVkKOnjk{W$S(!Z`B*ru8{@O`+CyisL z?*5W#8U7o@6_l_xGcbOmV@W{65nl#wid0O4N^!pN9&N@9EidEqxc&I|o$!G~L{;HK z!YHqNdSx6(${#r1LZlG*+;Z(H*;DDa|GcfGtdxn2hUl8okSq3#4tK;g+Txgw5yhy` z$Or_A|I4We0oS%YLz7$^7iUMwd6c}tC@fIK!x(oK0}exRchHTsBdieF-#k0U9He7R zL;7W=JkWj{Ztj?ub$r*&rB-#URfD-X%OQV&@v+;Yg#OC$^tJ_uoR=`_F<^uVkxMLQ zES=w9W}}xp!%H&*qKu|xzyvROX97-b7Gduv_Fns_n9i2P;GfAQ{bRqQx|@ovNRyAf z;e}m$=@uI0-w-E*yVmSwgIE>(G5hV%0*8wZC%-H@byWI{{y#pc2FUdf=8HGExNicW z-rEKcmhwgbVfy1n03A04P)`9AUw3T{c8AMdf476RAg0z|=-OMHxOpHUUHI5ya%npe z^+GNt{BI|?oe@zO14y&qgK;?Y?g~CV;+MvE=CQMTv;VC0&bXSY&3l=^t zDZWCjyW^O9_`bc5jmKP}lG94u59V!5IT{*Speq5lpPd$$Fe^N|V2iwzfda^5%}%U= zsj)sCJXx$;G%#JSZ9I<+cUY&}t&7_U+z3wTNC)t4AK%kt!=`tF*5ApN{CCdoZ`*TAIjYSFc!Ou>qq#xpfty#D^-55T(42A<{Ebttc^2j@0awY2-c z_McIy0QgKVWgiv`TGrq#8RM1H568<=Wp~7gwamSln&?CTP$T##geWH;U); zPhc^pS<5vYNOOE188C$ghp}!-TUdxX8JF2BxDq$0@ZOR=^%WC>W;5UfZF~`4@qrI>nZp*eT5a&*a%Cw7$stZdtan0k26HO}>k9>I|U7`zs`T9BTof48e8PI^M zG1g5ReVc6GdkYV~(ucX6fGJ+VGU{z^MDSk$&22Z$k0!hK5daI&)~u@iOg#0 zRbpXI;8tS!gjSC}!%xq2d*xaO!f*eQ-3Lq54Si+UrE&jGZG$$C^=X1rGCrf9G!}V2kLMk1|7{Z%Y5jCX?ol$my_;&5xdhd}FQt z>ISBg73-ecZq%p`VQ;^HizH8QC&IP`(ngbRi?BXxMJL-d(QyUq4rIL72}k zv;T>B1JEAf+BsRoVg~McDsl)c(mE1OIu?HA3u$42hZ`72o;0c4nMlhj9pNsK& zDPE^v7`Ot7GoXc+>>Eq2+e2%pW9BV*XMesbM>xU$AvT9})Q2knz#Jq#kl%^8JMe$v zqf|1c^i_U%Qmi+;D9*>gQ>y2ysom5T{;#s&Ea}@y<5ujNJeow^TY3DmaQOZG7|ysz z+*HTbFoGR3T-x|Uu!2swb1JJ-gUEHzT!Y($F(>V|n`QJWTo?sz>)NQCa3>4Dc)%iu z8)4H1A5^!9v-(?A_Zm-ys2QNA3seIt^97eHsUJZ*QTgU2n537Z7jQoIEiOhAY7I{4 zN2Rvbtf`&Uiy5=W#tj4 zYwwe|vsJ8IjmC~5@@Hs`C+jgP@2k=`ZoJHwOY9Y}bQQw(SmZ?Uxi_Y=tFASzFQ%b% zW-ivc1g=aKLWB$L5-XZ_h?QS_HYHG8*bl0FRUsSZn3 zBe`ng^EJE8C)fFHSp!& z{TE$}CZ2>`oN>5<_zU-0S_J)*nrnS4oynDplV`3#r~UcT_57Q0kt=EyNZ--C+RG9) zTL64v>R7MFK+Fhh;{X!g*-ra<5 z{5MfMo=Hw!8Yc6zZ7xlFIiq7z%ISwPZ;~#7ku~!0P1|AyKdAehEw~V^tK@%me~JD5?Z_9;OvSOJpH z^=#cUO8q4(E4ovpWU~8UOJ}h$@}@J5NH9LaxwjCFnblDeBO$R8lL##agA_O#?A5v39RAtk+Vi$%_z z#OmbY>k+zbNE}&`b&m_8x!y#wAR=+xxsD`oOdumN;ha3>yy&}@h}^_>Jf-f${eD56 z2w~;R#j0E$ffQNvFEEjHHNl$x@EtBqJb*wK_EA>Qn(z)hpfgNn*VLE^6y_H|r~pEj zJBtMP)8wk1f*Gd_x{*wou?js73| z>9gxQdg_t#SxfrX9(tiX)oAW8+s@=nrSj`IRe}?uo-H`>)TGiW)!bq<#!>zD~<%SefBW7S({eIE*$MZRz)Vq8PReeT6a`$`kxQX+`=eK2Zca0Roq zqRG}R_c-){t(~aGoZD-!IfMZCMnsNm+*kNldo9Se*hT#b)onrM-~$QVXEkSJ!-G%$ zX`ItZ<(%Z0ez@myk^(&iF`sEF?dB{KdCg}2K9gj_RPxPaJY0VImV%k9)U@Sd_M7L) zw2FOR6ovJh7^bFJP+kBpn{t?ady9yCZ{E3cd^{({(egW4l-Yq<9WJ9o9tjssnHDwx z9Y;RHo)~KewgWmdAGX3-j+ZMgp*SgLRBy31goNzt`U*f-ySxIYcXAqwSr{`)VcA$l zzR)6zRAKR!8$nb9L@c_YK@+hp|BmoYu}$qCIL}sibAfh##GBlWQEV8)5jZ~-Y_k9v z;X=bRwwhP)cB>mhaLw_;Y>(|O^@OMM&Vey(oYG~S&CI5M;*_1t|NRTh=o*a!^nC8# zG^1Y7u#a?DH*mgjWO%nzrCzRjX&w#OY`l26ns3vioEm@4wf|4yI{l1>*yE%J|6IZF zo$LhDa4zvH{O2Ul5(2|Su1pl+^%89EuIdRR;6@nHhXL~ zdqO^AyGQR~hk^W_@FjE@`*%Xuan%Uxl7#Bq=@(?QsNjwmr9*;Bre&h4wK%f=Jxikb zQhOrJ|4$Qeud(w{g9Er}ui1Rf%N0hkaeX|SUnN33jZz^XGV4Nc`j?@J6+rMiT*;`v2;O|n!0fI6B zJD?Ko%j#tQc2pSP?bZd@iBK(`yQ$XmkAhje*!8F-8#>br^mX`@9It*H39X+YS-Z-~ zEZGC~g!&|X^D=f;%m%(*)hjZ}_%6YO3;q$IMX3y|>s z8NmA0a5(OdsfHNGQ;@B-nESv8Ue1n$!r*IuDdZ=rSDI*hYs+M2uPZ3&`@IBsDSl@k z&E-7M=xFW*ikb5=Pc~^$F3y-SsO|Ny>n5+}fxgzn-niBbvjvs!iRKg-ebz@Rqjq5T ziZ7ckwQFDY)44mV!qmhGQ)l&Zc9aqX!UD@hF-r{;w%iFh*Xi#;NI4S`C=`EOlKdK( zgX26Z;)V%y;U&VqXXHK9(mg(&^F(8B1q~$0X>Md74t}|!Xy;dyX*BoLNd=b?K+H$k z$nN~`54LdQJuAv(`IBRE(_n$B*o&9^y;yl?1{&NpMVhQj~)^H>QfVlo6+wPz7!`U{aabV z=RWdA=UOv2a1vx@JVzBI6dQ;c$-FfF7(S?j%5OZ>KIa*RD|<>lZwhvs4f%s#2{w`E zyVA)HI_84%xceZ)mPIF=I`~cUEhA9Oh8_sP$6#j62~ORbedcO)ILto_vkFN^{A%@7 zWW7H=U*(H|L;{qapuPqY|4sJpfw}Y%AXB?k2%rq{5gJ@1%-J-Y%%o(aMh1DhTdyY@q6NnxcLO?C|-O`!;{5f+e8f|z=VaQEZO|*7WYW^{LQvRvQ<5x;56z0^5(OM&i-9aF`MTvSH-#+ zKvLh!K9_LRJr`s(wgp(6uNQ49F1*Ve;;i3aEy^q}X*4XA+JDdc2G=Cy7ZZodCNv)4u`SbTNJs={VAATBZ7g`s^@eY=JRrij@ZG)t4Xy3_wguJL2IySJ9y zGRx-pObQg`h)>_y5-X%JW`VkJUJOp)izJh(H4plSn% z5^dbMob|tGMkC{GZb$0xI!SX%f7clr68g`27z&)_H{%(_GE*2%fo3`&@Qc~%oFkPj z3SoNT{&wqIcc(U?1T774ViP)e1jsgR`jc^qCO!06&5NAe1OUHl*bWDIm&L?qsr1KG z2!A}m{0roD6gR#l01~{o-GEe7C8g)vWB6N|d4r7B$upUw8UJ=<`g)cU?Ca!mi0fCy1T<1w4a*3RJRC2RK`wJQ(p zwM-1EFRAsHBx3W1ll%RuyohV;y0jKC?b3fl-i^d)`x8ozJQ2jN1>t1y4Va_}}_XpVn zuX*Vc&nKVlaV-2yRYw;N>h*++;YB>qehsz zT-@YHCVRReGt(|&}RILI=AUMIyNHJQ;%&g3$ zNR~>#of%+IXU~^|+k?Fe>@LpT#RAg{9N^%dy1*{5-{yX=^B?M$TsJd+zrrIjNl{X8 zrb}dmhq=4Cxw)CSJ#J*B z%C2`kE>41YA@QlW=-x)@Ui>wHzvL$9A^Oyua02W zO5kUtOt3Z8&R6A}Wx3PZ&K6#`T|rh8DJFVa_ykAS=e2SGK^I+P5V2O)KnCtW>N?(X zk=f&PTYn_VxEXWRRo)lyPJXYq(%gDE-#~c}kZhaJc7gpn)C1~-&uI@Cdg%Jhb;U5g zOc=>_#YmJj+UHObas}B)*QQ$K!-L;(#_!O=wN5FsBbo}vd&(b-++-lCFABJyFGl>X zE<2&CYn5YcIhn1r`>6G1xsj#D$!TUhP?DC#qjM;!OPE%&G5m|5y@5kBcYRN{f1#3lvJkCoIWk#;uw&+silX~;^&FH;pC!M zV24TZAckFWoa4Mg>&KH=4a~7OB5XC-=+V|koTRX~s%@x6u`z0RzztEVW|zVhe?rw_ zlvva8J>Pbp8*1f2GXxo9^vsrUgRPz{7KN0)b}FPV6eAyf->0oIh?vRA+$w$#0MM=x zjQe-(AGOKcPmM4vpV2t>ap3yG?9_|$K|s9kC`a+LJpHLf z(8}|m@?gJe*}94BC(`?ETYOZyPOk%7xOs3>?A{J^L(V$BuDlipt`NuU4U@b)acbx~ z?~<$yw{8{NgWbIpYl8+^kEh;ww>gpd>J0N$(WfEC3=+@)M#9}n0^!wqqz!g> zn;Y=DE}E3XnijTG2eX4+1GUlvF0-2Lna#u!$ecC_wrR0oNC%{KMD`x#AEr3Jl zXP6wh%l@~^{k3Waw z&+rT6gAgCe@5Eqbo_Wu3Av-V3MPl0-WOjcx6aKQDqkJ_ye#|=xjszig`%oPs{<0VhWA+A9Ahr)G)9mpBponZbZS=s~= z)o^cm=~9yOm@B0O8(qRY36W@{XTS6zxs`a#r`|yjxQd~9Q8XQMuegc(2 zhB-LXVQta}XQH6yizcs7<8thW*iEHb?!b>iZ=6@Ia2x z384$gB#tlnWe7Bty4Gr)(*w9pEz0?-F95Iy<0bfq2-e_QL`UUvcnqO?Y)j7I>K)ga zk*nNy==(?s!YCOT6j;D|7l~L*oi-EHt*vIwGd4>`UXQTC$zS~yLU|@e&p+ZLlBnSP zQ1V6o?~Ma#P+Jsa)t13m7s8-+RA^C(u(>Arif`%^%KVK*nzYEgy9VD=%NN@Rzk#Z? z^v5p!@q+#u9Q>xoU+f(G24acX44?9VGquo5MhIvlEY2D81k=9o&XEPV*V}$jZl0Dn zjdXs~N#U)6c&y#BMi(*S6kCWmI)yliyAcdv62VTyagiSnHB~5aSlTH^JOLVzyu?JB zDY(YmK+%QY*4aX4;O0FnCXzr$GS09oPN+?dmFFv|7eQ$chK|eO#c)y%>B#p4=1-V^9c? z@`&KcM{0xEIgqdf54{fsigb|!{8xEK%4IgsAyV_`bd^nu5~BXHVYwKdGNGI8p;56w z{)1}f#T}= z#jVDBV)D0dQ6UaMA9F(qQ26uU0n3GAVhKjLH_Cru~tx=0AfI$zm9EHCUXLghCp>Xj)Z){4V|zP zadyJS)Tg;=8@9&8q((u`&(e5 zqB9G+_152+-B&koVL^88$bH3=*(%4IwZNT)^*-s|;^?TjG1|G2aBpEl*X}OfaVl6U z%h!KGsmEUz{V#Y?9IM^q@*FJAOV#pkFhlvOkQE?BiRaHI`NiyXr3DOP9Y!VriO2`4 zIxA1EQh+oPeE^>UVV5$YLlIZl9~dsgk5d^Jgc}6hoTQVrc!iOQpKL*Cc8n$ZEMMRq z1X~YLYLV?M@Qs2anNiwsQ65npSKcopXXx{{cpr(?9U}!4i5k^v%bOR8wJeTE6^b;? zSC8|Pa&pl>eVs3;$eA0k#9BQsi!(R^{)o-`n4Actb$@FECPXxaAefeB1p}@T;Qol3 zsn6W;Mj+$3B>%EN(&{qGhp;sj9BfsBxQDmNDG=06axdfHc6{LEI~VNogo)bTfh9uf z2xJfpq7IIbu2FjeGmM-0(D+=1_tR{0al)9uF;pm}jUZhaN%rH0n?*67FyfS@u*K&1 zlpKk8fn8&#P{GtuF=3m4LX@(Xc&@H6-WR+cm+T7)%cJ_;dQ2WS{&`n}PkG>-EnggS z(&BhEBN82|wma3=D%xqC-c)9P0{mqT<=*fBW5j@GgxVTiVXr5$7u6-%K&Ey<6Fztd z4#Klx`jY99_wdkB`$hw%iY{ZP<}~$o?u4P1iTiZA)aI^%Br3P+qKGf_{P$aAKocG!r6ac_wgL=KFy4r0Y#s z)?DNINEx5$)z2XWtM6Oe+4ztRj^j0Lefh#TI23E?StPO2p;hFUHx|f4FEIVKfg9|2 z3LT?5#*+QB9G9Zj2I2*iZw+TCkMcv2&}!bS@a&VEZvZb4^bYrFev82V<=q-Sd%#-QZPDxgi>MXFVmugZrvOVixj^d1GMhAb8GwB zIPUNr($)PAU^YS?PbT(yT zz$x3Pe7i$FtsYrug_5o35}cnN0c$1IjA3eVA?ntUM=>Vi_+)D|W8K=W)QnF~CdJ}2 zc@?xMfGvx}gbTxq1v`g)Qx!QpB)*$FC&_10mgcbHZc0sEjs`b9K1b+*A*_;jg?WBE z=7Xev!foJWDi6Z4N>-^72VhjUGYV*ScO76?);onBR~PeQ+xgUW%;a7Z`HDwt811R2 z9f^=JDgcn(j8p-Tc+C_{yE5{W{vU_IjdDg{DuIUPA{bSc$&}3oJuN;>e86oB^hZ~V zWmUiGgS}rd*nu-xZJgc#bd9k@25@o;I~lvZo85<%(uQCn>jlSbPmKD&f+D@)5sn7q zg&7LW;q+lD@(-v-w4}lHD7l*Z$$kBk`}!yLP@Zz3ZfTE3&6kOU5O+nQ9oGse9%*+V zDum&U3U*g=MtDLD1JoG?v7g=lbg5TVLRS!e)%H84Ckbo8CtE1rFp@5oY*?h{NV$fO z3e&3sgd@h`SHx+7YYI*ZQ@{+Y$kcGMFq&^+=qt?!$MALHK25L@cQExCjB*FDYWy{z z8+m90|L%!@`SZP<1Fg$%@^azt5PYkG1K5>a?ivHw)dsMOzscvA!vUX*_k(P3(Ep*F z8u?DhCBJDf?PC#7K8B9#pJSYo>yc1Vu& z!u(3Sz$5dOxC`81HOb4uep# zXQM<*bMmx!{S>?v7!BXRKEyD!LDJc%JUAt<(tU1g7C;fcw>7Gr{0KaNe_{%f5GC;J zIG+n$fHl-U8dQBG=VY5U}X}v_LtaEHjtfkAcL-;SPRIZfN`MZt_e5*tE0~ROF95UNlvIY z7;^vyhSFak%3v*S>HLX6sOv1*O~- zt6Uy^{D-}aX+TT}TZG5Y@923uVz@$D>%d1AP8G7{m7#J7RzsFIn(~oxtGUE|sYqd>&gD$G;{5Qn00`aL**5b_f)|yT;<1cn<~qgf66n zk?I~ho7e3oOY2B;EXL1KY6N&sK$iL(+`p6yCXi2S1Is*WVZh zy-Jjl(QV{d33MrJm!vS`F6D*F(xNHFdh}t>dQEZGW&4OE<^3xHmA545=KSSCm#t427ThLPmof)+}DrJf6@Vx2{1$xt?L z*fK~oJaZU(ZBzh|+k}ejxSZY4@bscO?k=D~Xe5t337vofIjOx6v;Y!)OnSLRA>As8 zE)dFPN^U#^Nb|xy(wu;IdD1|Ju_K{nqH>9S$N;M&Z5YUCKz8-KK6~u zm=+8U{gY3?Z;Jh@Y9RcWsjPIT**q&VCZ1<2&h%ep$oTzD_&~8`7n%x)6z0YyWqv^N zTsqz$rdsFzZ|X5P>dwPTC0ya+ZW@~)b?2fy0@L?urYf$j@}o)7&z?8+J|tm z!F?FAE3CXW!q|fEsi=0AAAvs%0K%Fd%1wp4g8qrYD#vuSxn#!`q6=`VxyM#2K-5apOK$5cLW?CVuYG5GK>6Ly$%WmT(hg&R^i)Z-@4^2sYa z;dwwQ$2a=JQ?q3@qg-9n;!Ja1qG%0y{f-6|m3WY#h^<{tnOq_bV4muDord}*(=y*^ zsN-I*TAeID~`GFv4%IE{+iqut_Wx`UI| zhvw;Y=hnM*^S51YD!g*!L^hB+C?RK%(Kk|9%uQ!-bNBXM#7}2;$Mn-FzK0ue*B=K6 z`R2Ct<(c?f5#ioM!d38wA$WtN+r^vm677DzESG((g;K6A`b+)7@1}O)cXJT^!n*Ba z@NbISKGZ`LpeevH5ZZtm!}RN``Kb9Yns0+&mBDVIyy)e>Tn zonn`A*91;3P-0!h#F6AN8wmVj;SRPfa*Iq|JV9mmXz$Q9fbHeFJA-31s~w!1>N$5xG;J7qE!Z+ zL-02yt_tXQ?m`eRTzKIhybudq7a--~7b<8;;Pb@+jZ6Rn=mce$FIQ|j$CclUzB#h3 z`Q_YellWlz%;*;;h>*8K9WHyNz zP4-gn>^lA{aobSh)DwlBY}VjxsP7WZP&z>PO={h=7ln>af7Ra5cGVyF<89ZiIDVOf zCo3rxh*s0!_EK{ShZ&mQ**Up5;cN&8lrZ}aIcRoW2yZo4A-)sS=3ik%>D08M!1g6W z3g5`emcqF>7*n|Y0%VVU3M3%Qf)o!7^B(BKOYW%4Z!#zn{RA^hAou)a3zM-C;!4PM z!ia#&EnJMH?SY?iNe8oDOyK|m(+EZmDY-+8MY~e>C5({wa_{gY;M}kV`yWs8)t7wD z);R&92LQ~DB(i%EURuHQbzmqKxPp@@SkNAqI6X4}OmFLSyo602#xD-KFQ(aN>|=04 zUd@2U&HHpW3sgicyVb~f@Rs2`sLi^GZUzHChB5?3UR{r84*D7Vp`2Pp!;z+XV$pka z;`Fj$UR{Z;x}HG9Ujqz4I~9Zp6ta|xll}#v3g>wXbU^*@K^L=<3TeP<&9uPo0dV6= zp9{78=y+j{l)GU#4;`lr=_*vuF~b&h>N{q5A#`0ArhQxTsXHoE-W~I`T)WV+4XkC` zriD33vQ8>HS+$w+EA~f4?4{Nu$v}DY#&|T?IZ8KB>Kzzym^a=l^CV5<9fS@Btd$gp zv`L%g(d-=E_`Q0QboQqv2Hynown{0;jDwI7`9S1ZP|qo(O~y!2BXoPz{oYTZN9vHf z&oi8SQ*t)ay^?{dKtbPVd*rK6(8_xFGR0kLRp~k^)kZA5 ziEc%BoC;WuUm&1^u1eJ*mw6+d?8G|3mD@-+yV1EY*@9^TUgFUDq7cGZmt2@~mQOl* zC}16ermFSe!qP)+D}DJYI(!YLCE5TQ64R{^ftk?opyt z_S=t?U$Ao@h=9NDvfVga=r349u!+d`jNhWW8iYieHSDIy6|>op;SE!+Ek*shMS&{I zCkBe}SHtGYb8Ud~v*G>FOca7rP#Gw`sXp^mK zM6khk9qokDP|+2=?P|U44l2L0dT0IYy1lDlIBgGUU{Yeq9)t5SSI0cdl^ij4qmj~g zW7oNhTdr{#N4S0_B1(J&>E9x65rTFX!oA%YR_=T+0)!{WGwl04dM0*4XJV69g{kY zZJZk8Z5K2&W4%KXZ)E_u{+$R0zo{1^2~XcQVX$@kIgM`i=I8Sv|36CBa7aGI9A)_I z#Xus2{TauHs+FUjt6AI!^IgI$j3}4D0n4La>K(0I#`T}ATHuZ&!O8d@J-A+lw=0(? zu>Nl=u-v^BBs-zya6y}oQ1>}I0)dT-XOK&0Nm(eg>=l%yB0oJZC#3>1qs+}rYWvi# zbD}v72wygUP^@xOt|Of|b!m*?e3J_+1R9ZF9BVSQ;=oQ$aHAK^QV?0!8_v3_a-281 zdg1~q92HX;_-8k}W+DXpZ=>F)R!)j%!mrGs;LD=G^$%?d;VIvWO!-!~s|kfYeQ-7N zGr)*0i!633$)fRsi`ndMoPNx-6Ds3`!m*dQwCKE>2C@NQR(b|`Fd7nCN1imsV=HOH4J&=bP9*b# zc{-B{Mmr84jt#6AiL*G+<__eAitAzB84rvr|9fze-1 zW(mAA;DJU4@@wXqkPlEJ^f>t4@HzwD@HzwD*y-vTfR=Wm0ymf9BW3T?s(Ww`Hl0BE zs(GvzJ#SwG`PSE^QZts`^i~RJmg1&No0*|zSeIZ)ZbRY0+8MxPTt2@Vdw~|09(nf4 zFa&+*5Gzov73rBHY5~W&rlrR4&2n$svno!aj13IL%5>oyi*VJgnO@^c2UkBSM;e91 z7(k=tZ~|0nLUhu4h#VA&8ZtVoFtY!aJFK8hl_G%+g;uo1P-M~AD@p1eZUVCSnjPly zTc)j2KN6&9h30;q28wPP7@kNH^C_fz;z~iL)6mACE)}%#b8B8mJ~i?`;9#`eTPQ#3 z4=L-KFVmWlM_*6%k?A%8T{f31;Y887mbO;ybA?$H)Nq2DZK#ZT=-rOXs{A6A%LbGk0tmHAz zFfi4F>{Ygs6q&)3$Hb?k2otJ^qxViDo)RP`Z8b;`;<#;V2|`Ty&`c0g=lqlNHBJ$^ znEKOZi5`L}Cps&v&+vuR{RdL_2b(5+OyKPl5Z8QWz^M{4i)@2?vpYwsVS2_`si+Ad zZ^M4EKd-wXrKn6B^WZt@w&1k0SV+aa{cR8yp-Jkd%OJKJ&_`EQ)&J~ z$yl_%e93UpM`WeDhpbXk?RPrz`lB+ve%I${kmO4;=WZl){rD*A&B=xL@rcezBpb8Q{5H1)~B119=yTkzWmlsAa^9ORTQ%a z{ zCJCF@$+&#!fqjlu6N4bmX4#mXrpH1gbUogdOvho&@EGD7pr&&^Srqw5IlLi(Q+?=i zp$>dF6nG)%v#D)pVZWAOXw8>~8y&%1YDJw2wr@uF<7Xh_?Q}YIteqFAE;O)0dQ*-l z8c3~}-@TiS4yv2_L8Z^X>2XCc9yEx;4V_zDG`?|Q?;eBKffEzuS2{3`HyY1(4G%ee zAznBG%3fHrJ<$8~Y)E@BjSj!~nA8q5N73XUa(ZI$`Eg_~bNZnq7iwUK*=ppIa!j#} z_`%m6NJyk;(A<;QDWomurp_XBxw_V_`)2)fNuQRp+iIUt8Z>*Kd}E(iL3^%lOpF+H zzk*n*eB!s{>MxVbx3{*7J3HeW3Fcb^v~IKAzIhF7w$D~<^%&M;Mq56Erj}Z^`j|!} zl9Mt}n>V#kY?WQst`s|kEtu{5%Crh|=FT?X&-4Y}--kZo<|D}hxLS+B6jS}Ht^>lu zWe5;S!$SU;GE!hGpb0?|3<)r32cQ@bl4rKaI?D&aKc9A$@8=9D95|C5ZYT!#M&GG) zyC>?-a`no_7B_w#p+hFGP;1UtaIF3m(thJYbbJq|n5vK*F|oe64G0*x*`DjRqY=6! zo9*QxVDxJ~2t=jG84~L^jyK_3@`47b+jA;9%Q`&PMg}*i*Z>jk#HIrDb5cn`p5g9p zOI7K`w3nTTL+Nz#F0sSle8D*Lb_#xQ_R=3GiYPX#H4rth5k)}t8ro{xNskWNXF&IC zmnlXknEld>tKAmO2eIZ(fbBMZLFR8^@S|&)kz05{?K++`iEjlng%SZ7Bm?0T;{&o2 z0>ajhx9^B0-|gz(Vo3>c^7M5~A61lf4EWawf4)QEXAsrWUJRgEG(?$i!!O(Hw;lLx z2Y%ay-*)M@odZLMV_Fs)YdP{OZ@>QZQys{fo(GmySsT*8Mpu=@Xp)Fmm80rlqAy55 z7uh0CA~Cr{#rK&}h8(vj2dUT4(vwU1LF*aBBzSn}=|ED?)To7pb1~-85g8+R*HM=_ z6tyXx7I|-WiCF2O#29oU2SDw3Ln%}%FZIe1Y0hwzoEFuBd;Ayp96zXVmV^6cd32L~ z$0#&si`zH%oc5mFmL%M4yU(TEu-DD@Jg@l?#&LAJ+s*EHTDcr|M{wL-Pjlk?;-u*6 zzjwWZG(Onr>O7|lg`S-c@VE$laI@-z8}5)e$I8L<^~7A+%F(GWMWlsg4~bBK)}wA! z*P+=i-sVd;*{aMws3)G3?R4HG-O2Qanq%3Njy4KX2Dc-6j(_4!u2#5X#&n+&@_O>J z@Z(ceTmuVxjq`FsmxXXgD8*9l$psl3snFLcFx3?zZX^qNu;G;_;9fReo-z7kA~uwv zSV0rUl90fm5(H$+93F#hZq!f5*KgumPu(GC)WJVb?gU*aWBt65BoPZof>T7Y>feL~oEinU6t0k^yS? zNHoNKph2lzW6!3y(>@#1l9`{W(iohBog;A|b!5E+nF>-9rC=;5(%eHC6a^J;xkB#w zF-6x4a<}VnWnL!yZJ2Eqz+2+^2Ps$xNl_`N~Ge z#1oakHTXrRI_oblf(K`;pxdtOBaQ>kjrL(*)W^ZDSh^%RUsi(;{;keDF3ZcYDlbz> zYdviNd)h>l?O)G$_Xyusf1vH=hoRnB`FiW0?wFbK{rf5$-c6;$7v! z`%Voc>y$X>)djB_Q4UOmOX)bnrE6!~S3rd>LJIeGK>e_?(AQ>#74`}$+|cAG2yOuD_fYi?k&PgCPw zzs5@PLV|=6tz6w#MTw<>LERAXWBCYxPkFQniLQ|5k@Dt40(5W+;)fj*ySRr$Go(mg zL$#?mfyx6}_tUf%*NFYt^jc`kV1zn4`;H1wn7DP%TaCxZj$Dzt)_>sYZ_`pW-`qJG z-$^=d4cPhx-tB8~+M<;}3^H~ki+Owj=440@nbKJJ&pf-BuJUu|i^t_TTp2A@1jgU+ z7(sF|`VHv!j9QEHVlgb)FKFqe)L5^9u!p#l@LPrzXnnyL4Y3)}+u46%mwmED2D@CH z)@&a>|B`KIwwrUd-)88EOJm?JL=m|{qKnG}bd{-O3KtW+VSK`rf9+AIGM6$_Gr4!F zd09YFQKp#AraV)lbkHY}9~3)V>W`SW>1)S!4fbKLP7maVZkKpiv8K zr#{H89I6Cvth;*4O&+|OU_My~r|71yj^zquT73$fYLDZnRSk7?I8S4U_Vz{M&zfCz z?dhp}3rrR$MhR&4XhczJ)-ms5Tklt(T0D#4c_3QpGdCZ_Fzj~WptoKRU1KJasg=tZ zH(0a4fXgqmk^?ceA%@14_vc>ay-}ic1^c0OfH`T|)df1?q&K-YvZqL8PGt;OT zBg0YOn^}D)t;fIq(Mi_14NqxBv{&^8Hn7q>*7$TMkau0MRzZDYV=+MY`oeFBM>8-5p&X(XPr6mahGmM(%kZS$xHIQ<73F52vQOy~vCdMxkfS~sePH@T^ye~-&uoT5 zt~G&5$;vMWyzo-68r*Ky5gp2b?RMoLIH~Su)8b{0_t~me2=NKH(I`H%^7#m^lVchU zo&|<&-YHS5x+UiZs!_2VF3LIhmKNvv5VBP-3R1e+B58#owfjR(%yMA$Wl@*0*o=Np z`O<5qtOT^~WgRgviPpWY9IPH*&i;Hz*jhuHwg-NL1|DT&YP2`BTuU?-Ip`Z*dzgYw z(KPoBTfquK<-^rN`-M&#`Pfzudgj7~>P}Hnf@zImh4nla@+e>B^&q>`@M$=59d2eF ziB-7*H@gbe?kBf29pCuuR@X$d`|0hhBXA|Zy4{udb3eGlxH3n9{NPSkqQ!sYxnnn8 z`^Wejqm45n^R?>VCGGW8WV$Q%D9I9j$Le5>H^m&cS&qHRaj^UzA|8%={hLy1K2y>7K z7YP~$ChowTAKYXlT`qVok^{}BqGS3zqi)1Ihsld;j(a>G2y2H;5HTXnNcLBMCBS85 z_3G>51|-dRGCG$o2UumJmz8>LUVHSDeDwfpag+z2Yg3>f4>r^*#LDos1zSz@bW%J$ zmRauPisOVzbd6DSHX&pj1sno?(UEp!aV$xQ>~Jb!AUblaf!Nq~2B3OWSRcMN+*PC# zAKy}bs+Sf*Yop!SmVWKg@0C%3X>4}}X&)K(9gl(K&Q2N}+al*Ti{05xgU0nUrr6xs zOZ&o+sF}EX=SJGM@}y=*(Vd%&Rh^(~c=Q`ncwoohom;Xql?O*epaz*2+ywA$19jtW1utx&GyvL1w z2t3o@nk=%b^$9DpJhL68?K_bho;wjpPKG7oHU2F@9%5!M`_9J#qfd~HArT;;+Yj%I zcxx2S@XYZFmy^}bJK)qy|GfEtt4GTZQ5f?B3$lOw923sji-V5#w+OGGE)+y3RE;}( zR!=q1)hleC(u<1qCjZgkq$sU?WHx4RzOML_jy@suKvgrbwv>JY?JS#bhh_fJ1f?sQ zwYnJOF0AI*m4~*&%hCk|_uC5L!2O`UVBo@NDipYoVgiBNI!zdGzl#e3Zu^)JAhf6I zUM8A>>oIspq1!Q7R#lf-J^^uhetN_f5{1QCR`3e$edz{%!j?#W5p=0oaJd_@yt4yV z2*tOzMP4>>o^K1oqGbq&lU=hS=*PX7b?0@lD90BMqz9S2DhG|k8tIDzzbmL|Pp6AG zF==IEx{bFW+nCTuyL0z=PYL&w1m7v;>KgZ=vf3s2Qyq=(6vff7hCh|vi|$!k zMhN;;xgN|B&#e2WvDg5 zvNcqlQ2jy(`Grk`AbTzw`aUl{H0vZY9;IWpX)j`Jm?)Ba=&(lq6xd=BV@E{6=I zr^${~raO1TED^GBV>nSna$;Wzt0NB>by^t5fHJk3oKJEzVFHU~pxE2Kb2E~F;(F<0_co$=hE%W80=)tR6s0N^M(SNDhTB{*WVkdn#({V-fEPkU zbJb1g-mh!IpnT!sG6=FJ5&8^}7*>Sb<#T=}I(4;x+^HkPkgVnCm6egy(5+1mqSWib zaacOmHKQe|h><=eoM##6?%1D|feT`oi^fLz7p}Z}pN`lx)V5m9$vXWkm~vErl8> zb`@%2vawJr$=)o1@Hd_omh>lE$U7U;NF*KBy-8d0$yt7}bc7@GofToSEu3ux=y)Vf zpbPiCFObDaouK9D4CYQikFDnY%M_AY?glODyY3F<*$s?nTVw3B`NW~|jnjU@=4iw{XcyJU{tHHsk8Wc=6*Ki|0J;QGq`&=<( z9Q(fd#t!J>vqsN2rq|bNjF5`5cHW-7(2ooK_-r1uG}%t6c$Wh+(PmRkvuz zUnfs`eX-FUsEMynSv`}$j6O9=kyuWqH?IKW081c7)(cD{LWs8L7@!^)$x?Hz#ZI!yOCTEeR`d}sFpHh?Nop303Er@71_1xLYB5C z(DqQ`Utc|wLCO)5LQd}^BJR}h)IQnfd$ikikzgsU`eby?P*fS@7g>;tg$g5rr#CMQ zcmz@#-CBd0D~AMZ<%op3-%_?3P216v(lB&ARhR5`_7##=Wsq9HO2k*Mq7WkjOuy>DRRn?4g+#s2FxZ_*!}yD)={FZ&z#)N2+78M@3CMl0w!AE~8z{6z zYga(OBR6JH2#1-j_hH&{csI$<5EeP_k5@ckABMINWl+h{Z$YWWiqWz!rPfEhAAVCX zl7$W3Tc)6^guMG@L&1zz&cc6@pDnFr@4nbR_}p{9D{gm#*G!gv$aO2$b$@cal;uW^ z1nl^B5qQf1cvvHq9MeUl#6lBwo+C+7VZ009O?PS!yb1=R8N6X(bT(R) zugRGXZbAJ(`HEKAe**a^BgIlog*Q#V#p5BI%g|D>wS<;@7HO)vo7mDqVH4HM52=~t z?1#0Exao(uzJ%b1Tkp{QR>hOd^TiTw6DP|VZYWOfnqQ+T1xK}FPT-zub(~K#yf$Ir zRMZQG&-Jq>tBeGRWjSFGFqq|J26T|?Au_y&;e}Sz*Ss0*llw)_x-jh9eikZa8PUI| z;;r_r-1Tvb=s*V$fIToJDsgc2=4PbOc-y|($4Jc-7N0hPH>YjVe8Hj zd+)Z^ugAH;>mMQ6cFcc3%yQk@5}T3Ijyg(4f3;xBV9Iwn5JM@B)r}=!Bp0nL) zzu8l%j+1iZ4=_`Gf-eAXjydToF8l>#1TAxl+k8~C8hBd8^)Z#Fm}mBfB^Hn|21vXe zIBx;@;_Z&}7FIyK-F4owWe_j-oR_#3{1zGmKJxRD37y+c-Z~x-&ud5UBB{J)Ef?pa z3F_In;Xk|ZpS=UaS>=*4@ylT*d7Y>{`)YcZo<*PM@s^40t7Yqo?DNwk$=SY@tI>Zv z*ZkDIFsqQ$cY|_zP(=5Cq8qsN?j+j;vj3bD9Bu)sOB|C9!r$Vy>6)1iA3^*xF*j7f zNT(CRC$<(%48^f`b1cDxkP31g3_Ly zGY+%@35G0A;#{^(T?1)SQ?oJCVtCFSY=t)u@R7%WWNH zKIu~Kinx!2W(nN446^&kB)`fALW_0kQQ(-_NqVXp?`X~&`kjg@u*xQzgE0RZ1V^^Y zY{ak4G2aI^P(ALiqyhBBelL@w?FplLM3&k~QMzq3U zwDdABZAnzNBKcUMR=sq=Z0leIc5DdZk~{jbeO2iW!}Rr6&ShUPJXVsH%XmU0fIVbR zxh$O}8q01CBZVX@=uvd&yICEO=}DWjzINVmRIHx~POPC1k}vbNArCbqDw)1IscMTQ z4#{C?*wTPmRv^q{^S5wRuT#LG4|`Z>nLefqvX)j5KrcjqBiLV{5pj)T4Ehjuyt0M} zHY8!gGZIt^pP?+&Xe4`lB&0$OTzwM=-mGq*YG`b*-vr@Jlw6~}-Sq%UZ#I}6V>yte z`ZyyF5{hvLvdUPyP}PmsM8e!(*!61InAM+e4x}+yRzL zieW*hTxNzm4seV6CjiHD87;7BIm*)@RG7aebH(bV4hua4wpMdZRr*0l6q z7#VMqE{tvrj&^qLq|_NVVe1!0yYDudcB2NC~FX483s@;?63WE$nz3-{sK?f_&u~7{8P0@aMJY%F) z)%=#ad*U5Dn^P7cxvG-<@r|ZH^A7;iyw0rY;{^DUPU<`4@~*YnmG&DNYEs7xGuRk# zEYPRHyn!%3n!B_C-G@CHk8SWfqQS1&z=6DjZS+dm1G*`Li++fRv?1?_RyRDY9PoSC zP((t~hc^j_lG-?I@%k2CZ%L9c-X>quU2&D`0bKA6;DV1$8UAwv{&N%lb87>ouA|_! z#8K^a-DO_ah283!d(`Q+H-1&1F?#Uv);9{>lZQW5JYR(tX*&r%m+q>OAq={2Z>#;(2(R{dKY%-(edM&-- zPN(2m3Q0QP-jOUGLiAeAGVKZoY!cvGnlFyZ)dE61_jx*KHnYBUZcb7x$hKSmY1E}Z zax*o-`vz%T=Ie3lGdRlv32LYm6P0xB;Y3lNMkA<0H->asm^k2s`FM@n`da7)WP9Qj zMr{L(d9mO?GVc|VfSDf!fm+SP&U?kvXm`G;+H1Zwh}B#CCi{kW@#PHnOLZ5)I3D59 zuD`E4p3XP&`Z641#z!o}tk{_6c1%q*BdUm7bY1n$_{DE}5@+A^`2XW5`2FQ8Uzksb zB~(ZHWcEu*6Eb^(_G?#-!FTeloijm<$Z6mkm9|jg7R=e$oVB0ie`1=zd{LZ0xw;Z- zJ}5>^i#!`^6*3D>Uu2M`(jHo#ybQ^1NZNF^FVi~Bi^WOFjoO%&pKYA%Z<(aC$|0== z#O{v}78RSIj?2ZOm=v!ua}*Zpgs)Zpkl8B7KoqcwLxE1TovVVEo-5UDK_vP*X>87t z_@AB5L2+OHZPxkazk!fKA^yDazyB9o&RX9pOrXk8%&}^iiPtU z^ovqBTOc$h$NNyQ=G0&3q)V2@xRxnqAk%+#Caf#JxhE_`myh*;DPEd^qo#N`fdQ`p zTfF`{$rwMnIo<)&Qi?I&0Ipl(Z@k;8!LAuSY-;Co_)u)^N3(Owaw`_;p%$%a7=Z>n zfQtPpvQx<7gig6a5l*Fi3;7$0tnxJ1)9N=Fnmr~lRL=mkkqw-YslP1C?kJYX!$Y(-mc>}(G-gSOr{>mp%WSF5dUK`5@vL0nY=5c0RB;$iQ5uLMQ6IBsRU&Q)@pC0#fc0*hB-;R8)+6KJ(Jl| zNb9C)$Sxa5_bp7JIXM+6iXq~5$?wArXMgTPZp5iUKCk6+d`h9Xnqdu6zEfnH5fuRT zHZZ+nvL-B>jG9$}hPz_PmbkCkyD>}2gW2h{VT=Wjx*_xoO|u#=F*?PJZIo&bOJ>R3 zZoVcRD!L>brcrx-!y#wWG0zZl4_xZIT5dOq_aXe{nDu2MyLIAvypxoP>83m}-Gb&p zMY0a{$;O)k{ZvlKiuh2g*E8qoxhV)xeaxC^>u_(>ruN+p!2Xu^1CkBoaMp1$ncuhHW0P=E$tEWP zmN?GiJT7QY-$b~AVu+Y=T$$D3&TqI{QVM;8xJRa+W-5*(hTgDQRm2-y14O95-(=kQ zj|iba4UQc#4`uif^=IHmHq#SQaZr*cdYbgq9g8%xAcGQ3c+~M z%K(uIzcJ=bUTs%~9lTb>R2{mP1vbvHA_*-#q=lpC^{J|=RmzNs*`wD5cf!k#nfUtI z(P=q>P<1h1ot*fk?aKw^FF?sch!2?lv0RCyqTKu8l1=#sJ(sAwWZoA$4ZSVbe@K#$NL9I(~$W8pL$QSIu z=Grdku&nFy2&+L(;6PiRj#=LjmUuTSFv}DuvrKoIF17sGpKNJ0CzVBm zK`C||oTn-`aelg*(QKGv;!PQBU9(x)@pqdf5{m~Ws1b==wA|j|Ht3Y2hs796)y<|f zV#bHXgKp|43}I}OpCq@R&GYY13vcr`ncLpfZSa2h37^>?m%>->tq+=VG%``}8>>eR zO|mz2`E}3lk|;#4htjV}^J^8-mtcdR5r>5kh-GJ* z@@LPOev6(0DA_@@1Kf#pz+q#*i!bhH=Y0_}$H%a*4Z$*hKKCih(&VYTGb`(-ersns zdkfp8xBb8>Kw)1t2vtRVt{jkqA1Q00Z?3)@VrRZ;kk*{li}ZO1ze%6F^`SlgovQgi zu>-rz`G@=v=8Ix-I-)o(FWsE_pOXQb`zClcx;3sr=8f(Mf3WS?nPY83H!BI>c;Y!g zgJMe2>FTrD_%qDDt%8%-0mF_#CfJjSl!{|$X9N`omM2Kx%Vm6nG3?+TaY#FW{Q?oN z-HYGKocF)|8(tIH5sab@xh!a{99WMR9VHFI^dk8mUSFxM7w64(d_=A5;wiS;I~g zn+DZA!(s1i_XfM!*3N(ppZ)!sXW-7>fKPu0JLN3^RI(LqOZMzD5Mlmd2!_~yKy@8* zUqWY+-jFPc6{Hb6DqfaTN-MX@{$VyAFN@Vbpz!e-U3syV%TFQi8Cd1%y|RvCxIL=fI;r)7f7#4HdrWN}~u70T?)lEIagIi$m>x^4TY!{U2X|9~JtB!FezGKb#cP zm+Z8=3->)VB7H#JK7W6YKc;fOY&ZZdd%?dsU_E3g-(5^sOvxyR6!XV8;$n7Qp70VA zW3ogo*(q6qi9Mh4O-Udykb(ce>LK#mhULYZVngm@Fg z_pQBcT2a`Ja?P}Ll*A#H^1I^#Q=;UGT2Ar{DS1F;?G-vSFN)={T4aKLb+|dB@?e6q?O`Wk@Q~+4>>)`vDz3`o5PvE#?bYG&Obs51s;2 zW@C~|NjwE?s20!xiaKQT5?%dBcMtH4kA$%BM?SC5mXnzz#My9oIxiK!#4kP*m_gsv z8CjkLK}!mjQ-@JO%s=+c!{}M>1O9+4F6_a!J(4WP@C-&TxmGJ)tdZ)HJ^3TszDrp` zM62UTW*K@dcNITNKg%-x^%iQEeVTw6%To%5Rf|4GJgDK=^QXW0jx~|MiP6G?I74i7 z;MpdI!Oc{I=-7UwH9IGQeT%Vcc1Jc$123r?Yb2aCgO`8XC`p0d5%rfW=DUF_1>PB#Tmr_X2J=F_h!1<_zzkN!h&lZn8hcgwJjG_fc5FFg>?cBMQ zZ4GYqZo@nZ(`Tm#tuxnNI>h9X=?p<9Q7`|OsG`l8jo?fu+be2D%wipEl1{~fp z1U}PqzBt^tsfQ~>o+9|ZA4|T4E~K}bMf^@+{h5EZOPlEB@hyEuWw^d9Kbf|J6wSbF zC8dpeN=g;L1{ug?P93D?cJQ_aW{*3Ve2D6gw{CUEl7d344+yW`AoO)R34I4kMsbyL z{ei!GSj|g@w36N$?>YI&3j=+W^tvKy7;X`c=xOwehO7G_{?jT}#%JxBA%u;kDa*kO zRF1{HV)1Xb3|_X2@hi~OIDBJ36s%UrQ#_? zWxzFmt+Rdf2R|?q`7JQNGS~aDu3F4PHtCm|=TT0+ByUZ0wtf#<0v%>|aUC%uqnunh zvkm{}ssI$K|B=@VkEarX4kv4axz;2CgOLdnkEcZjc=#k5uLCAh|9K`(yn`u>@uqmU z`&Z2t`iCB0!!eW3=jnHbe(2H1Z9EaZnaC8I_Nf^$3Wg|MIx%u}V1C3B!E8*`>l$uP zY|;Ru!{rp|laFNUU^23ZhNHKaRpOtgaFCPpYCPJ|;rGK28s4RXy>~Jr#Tmw5!8u)= zwFDntan8SrjS#f_Mj)Tbl*;I97h>E7az}^svWyvfN&cA{8s}4eTnmmbn>D)G59*jhf;beKfRv^E#{C?ScbDpyM3kRdL8|7gqyk^e?tMbnUM}eB?xqPChh#W}9V`up#H3baB zR~}tv0=sXNVDO7X9YTxyYmFj_F>fYJpjkyqVI!|1d(7zzf5r>Ll+g=(oqx-pF#FF0 z{CiPckUf>l%Ko|Y9PLdG8?IxL(OwBfOGAy~>g6G^{PGm@@#<~S{3=rQoYa2l3vJ$BYKOHZ@D z6EP#)e`%uP1&6i7QP464G3r1Z^J*uamM9aZ2>O7aCL4Xe-;=16Tu{CgzZIHex%^#QgF}Q2KgmM7zQnq zV<#IZJG;kkGzW$MK?35HQPWMOZYMNlYx4kw4%J8^A02kUJ|CtoQ1KX>1WV5nW??%! zg9CM1Ks>_?F5A^g6T8V6#D@jBWJr&2;;CXS#t(hFMO#@-EHrq#WRHA|NdXSpdTE$H z?v4WK^mk z@zD0AHWz4eSH?)8=vJlYkzyJvE|lf7AXZSCMFlWx2K9%$5cM%gOj{f8YlxBn{f%^z zzB`iaT2rw*m)u|Y0ea0i2#yYxmV!F5Jfl>k*j2ExSCXnl>LkS3AA(Sr@vpYHH1!|nP}q1*P6G(JXAN|J3x6-hw#Yh@yE$PPLBX+~ zdf82U+DZ2w+Fz4;ws4QP{N8`y{1s{4r7<2-X6QTTf7B4DLE9pjYVan!(#pa@8V=V< zg3RqhGU$*PdJ9%KuuNxAE{$TrwR({^Sff;%h!R%d70#?vn!(V(-jMH=2yjl0(z-p> z;p!;UXhe7PUV?C$b8-T8{Iw0I>zp;otH;*fCZ*|vp9__)3oQ5Z%zjv8N$VD&1ok^m z7DV!STaU(nVA<>U&cteNjFK#mFEpF6(`x^Eurp!h4$5}<>kIv?rOjH@{qXy$7gktm zx2yd(MJmk&kTJcpPN}P_8g|&yqz!fq9y0w1UNXPn1*BX4+E?E z%EZs131iYcenJF!c{$1xVvJc4Qs~_-%aL?Q)^R|W6BR`PXxW5{@Le^(x>%kMYMtBN z0pcC@`{JCsw^cywx1ep>eG0|>jvSwsJbsbc1{=~}slWCi{T|;U@v-dkPd{p7&t5yG zkollAirR*ZP;$qcu~$W(=sGkccopx%bl5rp@nTVR$3%KNTjFAi<9zhG9Q$h2?5u2N zC&LB95>Y5eE%ESq4IS{A3!TR&YvOGDCFOyM9P9GTkqg?nepQ251n0{wf0A8LaYrfC z8LTwiF@Lu9p!`mQU`#4LiT3W%I0QXh;diEIIK>-(GXLXb&&XWpM`A=12-9d{PEHb$ z+49tU?`9LNLFrKzmJM_sr3uJ~bYsGxD14cs1nh_~?kD~)DNZtd>^;P*t9!oWtp#De zcnGJQM@ZY}3Qz7HG<|D_DeI{f)lf1DYq9HNVllSoT~jQUchRND&HG}Az>~8bf?YH%gazp z^t}NGx4;2UvC~8h^(IR4aOO~$&5(g8*Tq?!yk#28!8{Iquvdf@Id0hEhIGuLirJb~ z>@3l5Ir4WEZRzY8-cdDE7t9{Ea>VKf9dZM=x542<$G$v&T2uM&o2V|$LtYJx)~6tQ zCUOE9ziY{ag6_8Q>p%US#qWo{r{#La)CjyEy>SNn?whSjP=cGSb30fx`8>?mV_Nn_ zIXQ`Y(o;E>!^t+m`_h5?v#Hw+D_fxE+t4+5mmX{pZjaO%^nM3%i`zq2DB^;V`Y7~5 zt+Wi`%Hm)yiJXVA_AoXQ}Le)Md`nG8g)es24SDZJXC%mS$j1<1d8dX$HI8A@_HPT%<&vg} zzEw!^NH|@5ip}*bl*6(VzKY%gNc(uT4!5`YnlX^4TYKUo21VW z75a7dhOshC-Y?(%0mk!^u3$%EG3;D8$oF2X8!GzQbAruAR<8;a$l#E)l_ddV>hAY) zI;;zk*NSYYTyKM3V{f8KRb{5->n+HsU0}@XIQ8(m>4-4Df?fS}t^!^-i~AQvuZ>-_ zO+s%tJeKiOa|0~Jo|dm-j!i5I5cU7^Gmr<77W+jZg%De@gi+ue2Ayb49^lM!U^B|kZ6-ufYOV!8U$XWpc9@q+Nn z?|I)QQ8UF3^k6mcO4YRqGTg=KY#z@*dogTf%tn*+waspCd^+VnWCt!~3ha?y+?l#r zlX8y}+A_DWZ-^WKdSa;Mwv^Eyd~vD}dQ_cPQW3~47}hMdLrdcKYF2F1fV#s8AWQ-3 z7O8B9)EYX`hjFlO%LTd552{uo4ytaPbKcutRU{y+{9CAl3RocHHEh# zs_eF4FICo!fIST$WVqA5Tvd$%>Qn`6hf>m83?{|_b?9S2m;m%aX#)>fg1OT+_XEKT z2<3NbEB`Z;t4V-U8*ITQkYyYJXFaT1DUSzUJO=Own`c$D3g_W~5<{=zE6yl(r-e&N z%4+Fn4LImThdJLj%!~$NG@Oyu^25_6rN#f;#vS3$nyWE-+6A*pII^ot#55*Eu zo?U%wDqFEBu7w%EE}WXjFO|b8Xn1Q>AO%(^lCjN$Fl<1QlQHb5=Vog%TZDOdh;1Rh z(vx8IY4PH)izBt%X@g|RvRVQ#hcsz{(@AedKr2fELw6fwX#>{AB-0er8^MY2CGB@rM`3A4>Y*el7I#m`cIxRYH_wnfDi}y8i3MPjFg!gNMXQ9 zNk3HXI%LAV8uW%0kXLG#Kn|vaKB+Z@vJ<)j>AOMsH3krZembtQb8%DJf~^Bbo<^Dk zAn$?0->VI3{Q2xeKk_cgZs`|N6WfXa|K)zCCaPhqx)s660@Q$=|4gKCcUqMAgp8Ja z1g^4dOW;9~@^L_4CXm&6-Ic%|fPEaGcn4G5;c#FH5V z^u^bX0nzG3tch+4*|L7^9ooLCS7f3f2rUA&hsX(1OKVuc&f}N34{ZEop4^RM?w?KN^ zH!yxWASPcdX)VG95gzWejfi4fu&b#)V_hy=5zeXqCIP#e181G+>Ya8l?zH`3)>$ni zLM^H8v|dYzz$fPy@={jSH~?8y5Em!_Ei)h|q=Rm@n)d1VY=c7)?#10{6ApC#Q-Z)w zbnf4=M^*oDs&j!7kIy>*a_VY7WpxGgKcyLqy z6FRxqiX&R%o$tzc^VVoMwbHsd&X_^54UpF;n3W;JO-G|GAOAT4(}&Ob<1Rq+tf}2d z`EEL(c#ntQ@9^i_^Nyns^39Ngi&7~;Z|?jl2sDEDPwn!VxkuWdgoB8 z%0a_z1* z@Dl5;eoogHhp(6VNlrRMy1)_zpv2ojZ>1dP%M$PsA;68-tb+-KpJWGaiT`;m3FlFk zKhTIl2A`$&FStN*cm!@*S(@6Rei_HAaE>J&4j6o#c*Y-5peC0#=zY(8Gq!)UOui%p z^=@x?jXeEDj5vS4J@}Q&JH6{S^XLK;0M?SJDDYXU()Hj}!n^ zxleFKwP;^blYsJv>?p}pA`Lb)lX}Q6QAT{bJHTAIFCwU*sX~nm$_P@)*pKA^2V8svHzF! zZctrQGE9V@UO2^yZGdib^Fx;N+96c|+ZwikzL-%ZWO~Rd--(Hlu%PffMmekz)dpV` z>Q-OG=V!2X$v^hx?yd>^-h)toTQn9v&uJHd_(%^^B%^?euVhn01Q7JsCBlRULJiqV2n5M8}BpSB|_h@{cbyL4~{8oI5|?fm^}%zz_PM zs#uH|vUvUoLM^m5*@g?`&n5J9UAJ1UFPaTT7+4r)wD2t*s8T^pN*=f19%p7$+$$02 z*8;s+F=TlWI9!ptB%~lauvzH`+BA@t>UK|gE2dXa%LlA^lHQ+hvM@9^nI0Xnrra(s zAhsyLMBgt^C3!qNq9QNX6lT!)3m6c%QzgGBpKwDBP!ezbM{nFb?#lkPoy?q+WH@t4 zY8;T0%Z^{n7;v9aW0+%QHigVPIDm{bnbAZbi?2QN&M|k-vpks*6(n*lbagb+&nd4@ zW}pTv-I(pT!qj6H?i2N?hZ*>OB#r(t%^dan+JvL^C+ya9>WJ^i(c!G0oUvnE{EWD6 z4w^}rk>Ep4j5iztS-q^bmn(LeWuv5>>1)>rAY`Z;=`k8_qh~ zj}5>Qz16*_V>Hta*-(7M@c7g~p!UI=wf!QEDCDpj`byR#wD>;OOcpVaTcZKx;+l-~ z2BYA8QJq7=EGM>CwMsvb?Cl;&(bbBl=0hLFX-%mIbLlrrk+^Fyy~cr=Yqw^GP{J2l z>qYqiMK^2v12ZW_CXgaW&rkVt!&Zuk&QbCmcoDO$*5 zFQ@4=YmhyEqNLbI0Hb z>>A2ws9jdAa=kHG<%z2E+q3_sC#@qhti)$REzZ`tXd7=ldP3g#-6MZp0u&|Bu)ShP z`+c~pC9DN;%g9Y2FaXxA#sByBQ7o^B;gdMlNfxgAKrt2AFL6UBGHKfL<)+pKQ^qcb+o-?jNOOyEB);3 zlyxELhpD5JXieg^i`)I0I!`zzPn~7a6EWe7`LwApL#pPzTX(ePf)L&S8Ki>eAlCL!9m_iwaJ}uY`Q2Iwk-{6 zT@x#FJ%u=kGN;eq=e|7Ll)#ZO?2EDD-k6ZiM5b8x zyfy#E4p!_{)bx1Y?I5EfpI|aL!?ir$b=@lV_&RoshQ87(pY6y>HSYMv`Tx+CSoL*n z_Gc128GZ6t{q!0NDy;u=k)h2g;Mq2MJi<4*;+#+uLwSfyafZWu=&DGNT@5>W0HKc` z2b16>BQVyAYr*KLOZN}Daen(sWT@Ue<)?r=#E<)4nb5>}Wb|6v)jXJyPpey)b4%5j z`&|o|RArTem~szAM9ykz5r&jDzr5o_D|hYbV=L_)2DoVXw_KxKE0{LeppY@!Ty)wT zTwe99^E3RffDTXtwtKiP%`zLbl&N86D_r?hT04 zPdXmms-uaHo=Qxh1S<&g!>BmzKld4!6^JE;XL{j%1((XHl z|FP<*h5ewMM@A^Z0v!i+=;mdh+Ql2#v|=`BH6+EJ3i(|LHVlngKSN9B6|&SNKu?^C zpCX8i3Tl8AULW?mbuhS)FD_rV4e%YKE;pE|DsG?4(1464i_D3IzMpmJBlG)v4CA0k z4-G}2f?tF}F8uhPsYv!gO~j1cojDgn$}bvvV;}LdmzAWt!JqT^6ho#-NbsXJZ>tvU znQ*an3h5uwQo5tpOJgrQFUSiICk#)Kl@WQNK< z$vt!`6rZVrGRjpLgmOOznu|#j+uBAMF;4pU-()T;z9O<^B~GmqX?Qlc+S>qd&0Wd( zbDnd*<7~D&-JyQ-jV`Skuq$8PjOx54Ks*9tY0ma)IZdRv(@GyV{e-haB1eGTOYSio&760cC;6P%jV^G6yqY1NgUJ`mFHj~ z=_plIOZ=jik@A;02N=9>;z#W-layccfpdE-n@qS$>CYk zyzc}T=hGZ$raY$i9|WvD2K&oSm_*Y4EW&qAAzel_x9g+l*WR4^AoOo%#z?$i`KL}s zhE{f#9R_;spCvod^g3g$8n@3w22ZcVF4pl2D!Nl0X%VSm}8<= z{xJ>a>|-D#9Qu>V<+RzRbyGD0p8)pj8WZ_CdM{9U-qMjLM+;jzgbf&hG-h~ksH>u- z6YhV*61eEQ(Q$$-f0lk*DlbKTazDTGEG!HN{Oa4s^CX zkS`q@AT|@LIzeZqdFvj-b}qvh?QdV%7~pQKbordPV%LRx+P-oB{G_1Z8#;#WI0JJl z%F9_3O))_o?QuNkCfZKpqNsDm>PnrO2>$EKAI%ts*pqt({lw6#O`!$N<}@R39WQVx z{d>d`sr8A zUMP9~M&!IbF+XQy%u{Ti$ghg@MwPmZ245T^!ofAZE=(PLJvLj>KB+AU=qv@=)fFvj)z`U0)DyRGGu4sf>~y zaj@mM?Z&7gW4a__bJVQEXqrWjC-z=b;Z<)`thl8kW!r+>KF;u71!GMkwXWQlu{Mu% zNJf*p>N(i9ep0ma-&=>`o-hV^(goH_k!OQkWkh1=BoyZ3lp-3EpTqsYubh zC}r8ZveQPFe`p=CG;Z)H>O=@b8PIrO{^A9)2jM?^%F^k*hKbzF_H1!u~>k> znd1-KdRMa3JL=kNbjuyjmcM#W!=Di{_Wj_n{7lO%`INyDeP7ww`vMf;4&Nqo1m8}N zA@9ru1AKi&yKbkdKFU8BIyp+*w(KEIzh!#jSmx3YNzxgGk*EF5Ba;#`W~c1b71}O< zui^E^s!e0v`sez=;CwI(gJ@kr((T#281Xf9S)+-@5$3{C$Qrc5Qn249s?>&DyIkRP z5i8ymvlkxfw$&Y z7&XPsy6c?r>1rXKuA3a^g5nYz?w-=G+K7tVzRv*>>;!@iA3WhTrGs(UqrByo18R)=SfHIk;i+G-PaqYB%z_7kLkut!UyO}$DpR6 z`m!XAH`B>FND5ILEXdY;A311J;3{}(_a{M{ZliYl;hb#iuXT(eC#O<}1~%rB){A#L zq(3`<&r^a8wquKHCWd5gZ1)zHl8*szXTm=BeztQGFKECDEM*u2N2dNog*U{043yY8 zSW5xaGzzAoron|d%9`T!1v}S}4F@zI&t&fXvgeUtJT#eWexFusqH zGHX+1Qk>sidW_v@ff#7e<;ol`Krf7=GUPxLEi}BPDJd~g0CGlaR(P9o;6q|}cQzbw z{Q#iYp(8m74cd*TlhkNFV9 zy<9#63X56q?~IsYbst*v^%==$4ydN5MQzj4DImM2S3jeB+;o532ZAhVh2DRkIz7xG z*4(Z5xNwL1&BA9NU-o?>6K+K9=_y~ZJBYbIi7r+~%%`$_H~5Sj3`0p!&vf6RLmQY7lLQ5s4>T0PadT(}JkBvl5 zB}?S1-j_%9;CIkQ7Q56ja`O*bzh;cMdn zsx8e9;=G|5St>z;%4@uuVtNAfA(9Qz9DpwG2S27q1ojQgeY8E(DlB5JU+)}sni1D2 z9gFu6JUy79L(l46Gn$0tZ>n$jM8B<5-|>k1?#5gM2nCq@5~P?A-}mp#6l>)wT{Ght z%Y}siNB>wt5hJ)p4OZ31arqVPF}A5fEk78ckH_ysbr;Cp#H{E!r`e!zlG zDBf^RAH!*2*NzcSruw82w=#;jP>(Qs>eg@TqvfytL%H%N+8@-W71G_Tm=Isp4~$a?N38DtehC-k|oJ45OaWU1MVZ&0>$}bKP0# zDD}5+a+)SF0R;ife!3ZXCf2dxZyw1^qaF#m-wXcU}x=;@fN1y$`b zVeiX|-1guRfr>W#!pcVZta1)qgE0s_m>VH>uiNmGK-P0=$8Ezjb7NtZe0Tl`>dM=T zg5eLDtT9T)$O18&vFc&pj=vu)w?RLC@{APma09@1vyc2!iY3Q!d(hHb3i?fCck8?1 z%6P^-FqsTT4^PlW-ya3Oia&tlJUx9Pc72Wu+*5*2FuIU3y7{d?*y~O9Q|wMFKw`FpJ)I^H+1U+ zlXe&A^x&T?xGip#BxNqJHjvLp$Gi$yspKZMubn%t$!C2cfMb!vCBsARB~`iB=n-!@HJfDHWS?Q@QkUK2 zyK+X(^*mzBK@yojZFkAFO6Q4vQh1JorTT`r>KonWpu^yrn`f=V-@ku^!F_t7CXO@r zOltf<&C~Rqwlgvd`zD$r#43Cr{-OexjS;Zs-IV8DgwCm7HG+v!x3z#{uJ5`(Z;%h% zUvT|Ken=YIquV$nXwe+K_5D@w!z90)k1ZaXN>Gnhecqr=WsJ8`8XEET{JIpPd1Sh@ zJdbIw;s}w5{O3GWAH;V3UIqTGTQjHr=pygK5Y|)#<6Y!Cr=`57sKj!afFXnYaC~L{ z4oC*1*pyztFNmDEdS+Um~S)H@&w2R9-i`mYq<%j@o#$ z%V?H6_N(22*<~xAmL4~E*oCgn{{2zkqa7GxPHhBdx6Eulqg~h>K7T`rP$K*OK>@<| z;68{L#Md%!FO6LFT!P1thVX&EG``lJSdF1Vo>*RKp?%Adid<8xEou0-*e{!vo6wSLAbAPrSCONf-ZY=LTVZt~B-4f>KZeHwOI7eB>xWITd3LS|cE8alN zxVz!;U|X)qj)g4{gCRrvO;AO&g+g?`h0_3aeEw^wW>cupe96@(;Qjl176@1ly&gI- zL?a0YJI)B`L4OEn9%tf%^sRO-S~U-MwsY{WvxSk#ilyA=2;eVg?b;;35)^!?@bnO7 z^2LY}uBnx$p^PHp=lvIwOw27d@tPKjsxZ@~6;IMi)lkeBmiWZ9e0TzX{(z$4JJm<_ z@y%hpOAKJ<*WVA6!kLE5E^5o!+NjpK0e?^#KIpQl9G!TwxieQ~-JA<`I`T4mi&ze? z9@~BN`@HN^mu=~Jf|hw)v_u>)40LGIVw%gK7bb7#F9k!TIJ>^}?-%VoddbVKVj+%q zD#H}`oynfUI373?{1irY*WMAxak%1A8r7zI&Y%**AweBO=_~AtC7!$M!=mK^-y`!G zY9d@ccQ+aEyPjw?>PTV0wR8V(B2)j<^*USP$ko)ppWo;_d z%?1IZ7MQvy0{h0_#&sT}MC)dBezrA?x9~15v=($N2Aj@p*RQohjZ5uI<6^iek>Ftb z3u&&jSTKE(4GN3#j_f3z3#dBmbgj^JX;ra$m9SizCQT8 z63Lp7od$az)%=b`={dJoUHQOEA+hSE=Zi)!y(|;unTBYtWt*dopC#m$Gs90z6|QN! z$l^Xy08PbG4Fgj}5&7CHnH+jKIY6cjGQ?Hbs3qHxI?)wfx>Z^+zKJ!(M1gr|E+sx6z z=Jtpx$Z}AK( zN`~cSj?MY9Y6e$0reReQzca$?>1GRzQYQLMjknO?2mwp5+SvZ{==F{wu%o=6N5^36 z@tDWPqrYfbyvSHtVK1_5jB%~fyct+3Y$U}@DiqIQgU@hqK=4M0OGpayN`zn=E}YWk}MjM7IpQd&^J7!SbIpd6kNT zY$ZP~n%>}6+49>eMCR=4J1MsJiVNkJMjrSnhgiOatTJIdohd;I%g-@l{Dx(%%KJj- zvhMqlEw5@5eHdHAJ-oeIY4GHw+zFJg&NzKKP(ne`DE0E+h}1gDVJbQqThREqy_l^F zqW-f@2I;P~nHUNj_VaF@$1b!+&B8~XWJbkrqTP=A3xBYeMeM8@RRO!r=r$Z=8}+P- z$db(5+O?$jwJ%>D5e>o~c2mijzm)fq5TLrXFH%i=53GB^SaX(xmVWcB{>31CTYVwl zpmBdnKcYQ>5D#1u8aKXy={%2|lnpw951UfU?|bb0y?o0UO^>>sZ4pkFuC=X;GLeHG z>4qYn(pHJZ`pn*p*WaPLaZ)k)2xG~x#;;a!oh@U)TNkDI1M+#Oju0!?C;|1j1M7J{ z!oH?PuYAYqbg`DVa&WV>ZOkuc8 zi_q-ls=IcD{8hL33wr8e9T8bV{}ZQ!2nHqjaS zC>Ug2rcy7Sta+sX>mm+M`&Q!>f@0L!j^TVty}Ht>wr?zB0ETk@RMn*t{s>kxwK(3M zN_9R*uu_@Tp|5%Go$zz}9K~XaJcpfcpo7UKmq2#>(4JXoDSZHfgMmFk3=fP`D-t)e zHxNSG%F{KYj@N3fx>oHS!OfG5zoBZ|CHkmW`e&C7QKjWm(;5f+Q2G-`{IDXDEPcaS z`%(*lQ0=f;jl}&KMar_k(%Pviy1Hq$iM?G-$;HKz-{81xr9PKXX)DV_xK95sAi{Aa zPVMlPKK8T}SXM3U_LD!##W=#KoD#gQI*-wll+K{%v+C)VR5)rD7gt9QI_M$#EHIpcN7TmBkI4K?#s_Er3uVta*L^Q-p zEK|W{h@1D^=v=zAQoQ-s@=to7*9I?27TW#$Pr8|yq)Wmej#K6-^LK;kH0BubjAiUb zZ)DrBZKg}3x^cJa9m0qqnco?B5Q(gUJ7IX%PDa1#6^w*=wDd~aok>@RujiE*q-I+2 ztn=aza^g&vSTVb4|r`wxgbDp5aI9&+uCech$V^2c}V~K7;2ZSRemP+&d`MfQDYzxkMLF3d202 z{Yt*D^F#&RTMs;#>%4qCdpG)Yr!*m`>ti=MG2Uy`u$M%$rX3@Jt1++7sO+Gm?qM8a=v;I18{Xs4!0ZdYF`@V z(5$K+Ig#ka0#gyouoS>uxO%u2L56VAPMZ*@7H@?<1}?@@O6QTVW`kNf=~tO7M|dq<8iliQ5H;s!99S`qzbmR*~Th42j5X=)`QV-|!Q(H>K3f zc>!@6q3vOn;j-JNJlb}6l67>!mc6&qh2t{pkp}1s+q_RFz)ywQvqMg4In(>t$em@1 z)lqc|(5D`jEAV3bvzzSVQ*L+X?2eQ{A`FCKfYnG-UG4XVVTLv+Z|hXV#4CS7zYSdL zCv)_ULIv`S5ibyeQ2NSO`aPmmmyfnT6}~9QM+};jowAb==T+U}m<%L?!5xh#SU=*m zw!{33QF|oN`UVTe0%I+cq`~g^9dGnMkMWEWsH$45S zaLqWx9k1{hgVOZaTlzPP#-~!PC%kZ?WWF;PZ&j{_&kP?z1u6OaieJrrQ%E_$1v672 z`Dv~}R%~X0mKS#&r|Pn9l_2x7PLty}|8FrO$+3a5&K-&)z4S*nM;nH#t81bmGXH~i z;y59S!!dQ`Z&(;(?r#4~5rUWemj+b_%<%XIykfCeAV^q1-ex3zW_9SNAFuN%+i zx)nV;S|4cF))esf4bt8>h5_f?+>-J05!brRz3crhBm_A8O|Kl6K!s(@GZz<|LF4xG z{4(nVAL}s#dX^sTyGQL_wgSK?u{}nKE@^6TO<#QaMgQ`_WYMA*|FeKm;F*a;3T+nR zPsx9cm@7m&EgT(FkPZeHRxR%&^^6IX*TVMsKb47A579TN3NU=N4@jH$gG%H_IO+xd z;M$2Qu?LWR!N93t!?i!!=8_kVGz^8CR2=U+UuW~V{j$v+l34_&frnNtSm{M*x93?E zdB9)b>teU~d|X~%c1mxjVDY4l>zT;Zh}?XrQFNckI2MiLdB-j@=;rJjgbsa6t-$Z> zDw30>Z81gRd&K{^sR1e@rRzdUi{*kR`+?YR!2zE}=MQrc2a<9{Sc%Txt+3U*>JvS} zGi!ox95Wtn)WtWV2@$A1p97E6Pg=8>m&_~0pEff*pG3d81`G3C8u~C6C4Q(g4+H-m z;7u#L1-2BRk7PSLnS<2sL=Df?HsEk|vO3>#>OMtY5B11X*HC_YpJ*W}#d7fC=qAs{ z6GHe-Y&p@&Q@(5eaH~_MzT_?E4Cm(b<_y!_C3>|#$gzMqM(q=Jr6{BeYK0jo&fbir z1~aS59HND}YiQZS;Sj4=1Yx@#fu9KV@~~d`_&`YJmNHLt=oGf#nLNH98xofrf)6I@ z&TF7bn_uHbp`GD?+TgA`sDc0a`DvAfZ~A(8T?Y|%DB)}B2 zoOAt&G>ilOW~}=*;;K>&a^=I$pKWry+O=)^+|~8+&h^w!S5k8?Hl_wcQB}3_Y-RqE z0RC1Q56}Amx=#BQlED3_&eE^i;R$Yc@J&5E0gaLTJ~t>GXi7( za1CE&&$u{s70mxU<(qYg8@CR5%HU4ux8Z^h-l$e?QB=+*1J%1nv^lST>ut%~s;5YinoU`mR z5mc*qJJh=RIw9V=#1#(j;n}fQt$Yv8fJW}f^+vbyZqE|;b|+y=%(eYLnLX+>4B=ZJ zC^)ZC%8hr!5}y%sBBi9-5EvpF1WaYpj`0gbxpAn4V=pO!_B)q(`>fTVImi8BEsm_q z)x{j0RJ^Zci$KCJ&DT8bPXkymAsa%wh%k%KdlY3+$&YRUYLX`#3QBw{Wl=9IYLaSm z&7^ZOnZ{MpwF_ijuBrg2ZdZfioYTB1k=dg>v!c^+H(v_EhRv{43~v|cN&^!jngClb{y61Tg^{N%BIR(h-cJ6S~|;{!R<5-7Sw+SH=TKWtwmB6JBF z$_%m=sRDJ09^lqV5u(mLH}!Kfun6AM1I4*eLZV{W-6T=l-$=mJ-)wee zGG{j@n)w)HRfIyaGCbI@h>1A{X6V(zqM~Hahx#BjcB{H3s*soJJ5n~iu`aGkH4f!x ziCnqpY;9JR%^Q$=Jk#)jg`70I-O@K*hxm+KPb-ZRa*ghz1hp!Sc?~aY@1XUzT~YEO z{02%1C`R4?5sus6K%BpHzZrs&Y*uZi#5YkJXnmhW&o>pvZSU zJnI06%Pn(Fg^2(y474&}ZhjB~jEUX+tiWTTTwAQC^E*3j`}a7Uzt$9V_fG)Y+~~wT zIQK&2>8v!u^<(bvFOiFM+-vKOv%j8^=q9}agpa13bsYDNqJ8_o7}^xIwFN~&(^AmW znR_uGC8i@_3~{NzuzaRO5Uv-TnZCgneZ+0&n-*fA+SHlqE%-2dFN-H_Mc)3a{_ zfH4%X5fz{J(Mk1^v6eONx7AzXo&H;iVE15UGpCNQ+G-p+hljroRI~QlG4Jv2o64gG z-Fm;CDigMPSRyRk~3*((?KH)5j^ z71@7VrReUgQx2PlF6h^d1DI_b4Ycv8E$>-?e!d>AcgYB{irLu%3}nK_>$oU6^_WmL zPi^Qy!L$an2s-|p3%Z3( zKLQ<(UEKQlsY@7Zw2ex0rzd{Zod}Nvn2N-h7`hzBK3~++V_7jK2vr~)oV>W{sJJs6 zDb?I=B*-N{W)bmCPLR+noC++t4W_|J7QO|ccyo@QMq)w{`A}u}a`NcIIgiDoReFnzTN!&xWM7G>R${YDcIW(qNha|FgW#M30iKwaAkBWppVnWW% zZlCONZ&D96>#6_T;iBm%j3E-9WI6;BWzkAq_Y&AhLt)|;PR3hCX(l1mHFD=>nPWAT zNEqC#Sa~O_s%y>`MZ3h*c)#yafeoIe?t#2{kA6CO=FA>#=)r+@jTJA9j-7|fX)+Ao z>s!8KE2y=x-t~AZ8F>kD_t>0fqdYGv_tFN+mp*wNRVvly@r$$3}jxldl^{&HqR`q6*-83gy z(T+7ITsX%Y)mTa?u=Oj*VgSq*eg?vV4&a&~*Gz_M+P;y>?yzs;$(jtPd!v{q;q6;C z>{umGUGPPusdTe+IPchS0fz>{}1drcONhh0|=k72&<8H3&# z<-fGtYEk9eOH*T&y2O^2qZG~$&NNyOTVuz;kC{~|BwG;#8QS@Zpqryk1)hteO%!CU z!|Xno^w9Q$QGoens@E@8suEGWh$ShSAVN#r$HHNC?O{=nJ9ne@wl%jU~Lef_j7PBW9S zY20u_w<$80FJKmYAKPa&2QN&zi8+i2#`RYNcIr@2`(t4FaxQ#`=~cDG7id-ZzxTfv z1+R`L99E(H?Uky37)e>@M2*xf>rE90dnc5$hv5(@FC6V#ck3L?7j@Br*VL$>qbq?g8S(K_%Na44MK*#k4~y9KhLFS>M* zv$#RF*T~7khF@B(EgF(W`9F+MHLrvxa46Y&nI2Dv9$GC8%ZjIzrDWJ`9zGPO?=wi; znH5E-8NGywg~%So`Fuk_W_hW?#^xYl?@caG2Oyt)I4Bv|DF%C#$49Go^{>J2iCrxI zLEW3Yn%;sUpKin^(ULmeB#$>MDpB*WC@Psq&8Zfd4t0l7`)SXv{Ck_N`+(?~I9@PO z8;M^ebUPetn5-Vtj!Wp{)QIDcL|0}{pI|McXW)`Z6KbysR7ZDX1CL~?%a+hvFd{(i zZ3mTVp*?%+V8}5uEKi>#ghEL*lP3>d)*xT1J8!gvVhKl`ObC1bEFh~K@#C3vl-jAT z(Pc34XKQPJZ%JQvW>sAYx&b@IU?YQzy3s!ior~(K$W0!muO>M_DlJnB`yisG!pI4R z52rWMtVnJU%fDhx0!G#_$-l3kFvM$Z$ytA!;ECHE(!cm%h%E*JAC}b#2vq8TKd4Gn z?X}QLLL%-##gKIp8(ph(SI&Z~blvbDgx}&KT<~)a94Q3ElKVJ%J}PyhOFa|rOCxPc z6k0HdW|+z0E?@DN_OrZnn*g{9A&ou0SO3S?JI0CYN+qP}n zw(b4aIX5>s-%0NKQ{5TqKb>^XIjd@nQL5WMUs=4S)>#)WR~n4oGFVgtN3J9vSf=M|D&=~>2q_#|b%2ImGe{QMlxq$JRew@j&n|dv`Z^C+WF6|6bJ>*3 zXN8|4C20c)>(o(x539yE>tHc%2&gAI`QI7Z3aziR&TDF@a$HIq2cyGjEUfLAt{=Y| zbCpv$t}fTvBA3Kk{aWrsNk)q%oGaoJ{Sh!;Z4|Q_+0(y#J40-DR`w%FJy0V-JXaL> zJq{Z`R?XkGLmpgbMnGBnHSb96!@p(wB>z|NUHmit1c^Hb=`r@3d45%frtzw!(w3}KP4vLv+H zjC3OXq?XAB)8cDNx`#9)t(f;H4(oPBBb!$83yJS->WGeQckRp7G}lN|)hn?{cM6WD zB8{$YG3;I$Mq+A7F1ty#*VG7ly?5#QeCER%z~hy%*VY}OuQz>Reuk)xM>{8A>T4yl z;7a3sP)NMZjP3A}s50RGI z=?@{I2f*$y^Sm*4b?O37an8OvR+pK8R=#3x57{TEPDMcH2?wG)Qjp^Z?k%ogq+{b8xo?0%I%5Q+E~Yp-%uPzuwO25 z;UH8K1H&agWMIEOt$zp6P1(a(n{0Ru{WFa@N))lWUvK=L0g+!{Xz42N|&dPg8 z`7VgNmyd|V3txZOQWEkQ`k4i?GsDty%#73HC8YdUw;u&3Rn+`=#;I6#Iv+fFD$ZvH zQ`9r&`^@yV(f$wa(V*u)xzOnfg64$Yrcw#d4DHjtOoG}#gf%ay`siLzU61CWRSl!vdAAO zw8k@MK_cSV(B9)em)v4ki3cw>4hKu{*`;b2*)>!;0^T+FhAZLqFSMOL@axXFcvZ&4 zJUrOGc2=uX^yimLsWA$FE*j`p(K~NpT>kreN=f(Gn^Kkn&Fa-gfkg(qEO)DAb*#=T zS@qf86(jNHUG|8V^V-o~FbaVvV*E?0Jj1spY>q@=WFq0y?)sa|( z@onxhpbJ`PiJRi<-lu}xtLsQoL+3yrwm;gx<>d-8vd4(CH(SQ)uL= zL(d_bTbQ95B%~jLRk%yB;X6wD*8o?&2(TgAcRC%3IYCE4>CVry?9e<=|9atfMYX-V zp@dKWW`>Ww?a zkVnwgW^zqhaSE4j&nQ&c8| z+T=rNq2%-=F_CPAq5)d2sUm&V`<@(oK@8FfUXms7IS8a%F&f<^YTlS;Cy-p z!(%gMN5Zz#NoHM0|33-!s>iy3g1gr&${~1>co#72N2GlO+oWdw;%NreQH$Ms&&Bn- zo%)p89xo8k-M)Pf4-a5ju687LVVZ-DHcWB(@r(|ftdDsH?OSk+9`~!8tuN9&Hl#As z8D!?b@3Dfp_cA^L@y1}Yn^M~Ygk8+t#G};`K7XU%rEe^VJ#&E2Cuq}U4NnCSHR~ZX znOWgm*%;OQRJX*pyf&=%u4;~LeyRTt5I@wr%0?rSO9f~lLO;*CN*6b(?A|~qnV|rX zEHL{>8W`1dQ02HvQZ12PHM~%;{Ch6BW972txxyQy3~vXSY4f6ptrl5_rAch0t&peaHqv8J8*6oc}t`saAuI zJR!|zrLD}K9&zE83TsDxsXcY=%vyLE7euSe)fu|J@%Iyidi_REAbN#KCE-`mg=*SY zswP;4a`+7)aysSqmxB>TF0;>E6P&>MqJ;FH|lImOIRv=`>R- zTw3Tft0Pta8(3zsYogQ4WbFHm{}xs*xX5 z%0Q}-9WH~u5V;5sug45s%IbCM-oES@PwA z>8w-r!r^;cYq2y{hR+yT`Y&e5-+3;hz7RLYTOKeI*OMJ6>nOhi`-CyFcI3&05B5Wl$^djt)D>qbRXv2p4 zmvGNZk@;}K7|&THK08~4k!GU3SX@IXyvT4~4(ZI6I8=gw2?=~djuU6m|-*Ev&ik{phEGGybYYQ`J4Kv!J2IJ>an(TEB5$&rsMb|vv z_yu^#3Ouw9Gewhxc$uT{dC(jO(b9>r3C~&SGms$gexConH4)*=&InWzdyBo-l%SSY zURU>)1$}G9W=pEp^|7jFyEAPQJuf#i6n>~9PoJU3YUjj!R(JZuCo{^~jmhl3(ZTl7 zp#i8K|DYb0sS{Z{oZb_8<9g*{JKbO+mU!7jNmxOY2U}M;^3 zj4ARS3~O;_7@d0=-5?6ARKPv#JCfGA=c?)!!NscT8``?&n+u$TF7Dz{Ukv;@xU*=- z@WbGi&sCCw)qW03SHvbq`{>P0BFJjBe+w_&%3K;l-^rx;*>9{SmfPArC!e{#wJzl? zaVx@*k>B(ZK;{U#p$~-BSc~n&T zHec+r66LjA>}oRC{Xb9n*>DJwcJXKZGG@;1IP~yx0M6txwot5jklM4DOwOQ%*nZ2q zgxmq{Z$$le0Y7#I0djQxZ{EAV&Rp?B^l(_BR?k86gvuUcmmfB8B@=)?yx`8kb(GlO z%=SuRLVjY+I;)AIdb|GJ>AUVawU5nSGnbxOqr8K==D17Po7mK7yBqnM+{%`r7T5CC zxE0Mp%`RmtaLfM-On0F$2joMt5w1247NlMoK?bxQ>MGLuW%)>qu?r0a z*ap}Z1A_2_W+obIKg1&Gc7nA_P5)_fJ(ab5Fq6Tn9xr5dZz79bIhxPl(M%NkU!XlD z8GQaa9-Ju*0Jj`JU80!EmCF?U>8kI$8WXKkA1>$>D6g^M9`f6Bsc&N4z%#(y3W1-i zvu%R!KYH^z!~h5hyIY)avenX0@i5h!x%W4QfqK5zAV$ z{|VkJtWo2kJsNNsJp2RYmPvc?R*u5-*Ma9At~|f8!WyG~4dH>|VT*!F4X(*PSsoA& z?be)U3=2tM@vZfXb4ME*k9WLEQer3hHBQL=8&e9xD~7gO(9K7aZ6b9YQp~o zhLvH?CqjH1Bh2+==`lhL5I@?9trRu>mED>tP? ztSHWFQfW$wSeBd7qW%Y1Q(6pk`=}85?<>x{y-}1BmurGDG18tJD$rN8ed$?{QW?m#S&?6l_bl9soDvjZYgC$OAsRMeUdXRoCtYf_{ zbDNlX#Kd!YuoeTaBXgX){*@7%Nt0T{ve>K|r8>EwS+PkqVnuRZlkz{nE@0~5Y*#@t zVK-YI3O)_?cM<>sdPrZ;NYCGqcFsin1QUmtwTI`iWd8U#O89j#1a2B|oF_jRXkaY3 zQ4szLPC1dr?%UJ4>P>OK;!bP2&SBZi?E+TyCa}mA{dp`J%|H>$Ix|?b>i+)#hnKNv z-f(-p@~luxvID4B>8-dy&1R*K8Wcr5XpvQOsACs4X=Uy7w1~^_Cg;rT?`&Dr6N^lAM z8!#Z@mzym~cm#79zUuK(*7qi|+?Aun3@^<@Im?It03YMiz2pmdg@YSdKR{rZQw>w@ zwNimvNR1^CZeLU9$jyBBI14mVR#-01=1CpWnx(Z;Z7s~FX{ytUSsR;7QdXuGGBh-q zr7TVUH&~OLZp?KEhW7IBmP%~I#ENFwoj8yAN=mJx9{@>Qw7#d`L@AvrO)@v9yg=n# zE4kBZV|+pb>!D2d*;71+*%s5x6g0LXm(0ivYTI%Rc{wHXEwPcuGlR6Pw?ol zA(O$`zrKVB8}-mZQte-g5AcBFKayPLdbe^bGT9HAmm^d2lst0WY9p|AxUpVe(P56o z4g~8cF@B*?3o}>dxtZO(;$KhPT@x#1$B`x{@9YrICW;WfK)l_1=>lI4G(8topb*Ir zNrcFD&Jy1Ts(=K!s5`WB%Kdh0V|dtC;gj?U6DZw9%D-YAI>fok)3j|}KfSz_)#YpG zbp*}ximokReyI9Upib9*wn4NK7-cNe*)T59Eh!-?)7mC-X^HE5_g40bQB3pj0f}V9 z?mYcA#)ZQM6b;vrz*alCIE${|!}m;ntd=XHza9X40fN+d08j3q!EX=u3rlWa@eGsB z2VplEWL>hXE1fO#^v0KMAp^CiVQ}3zi1`UA1xoPC%5rOyvpCZEGIIpb<_KTjY#D%g z67>@!!u-8IlfDlIz-rJ6NI|RM2pp<@?g6MtL)1-agLM#_!^ z%S$Beb$deU>D%to5o1)xde*c>PLDab>0q%~tN%=t5TBx48ar!Cv$7x&)%&0b739u9 z=C%t7yO;!95uiR5Qstx*qx)9-A`$hG{KfoG&T9FpOp zUkcKHrXzB!I8#F=#JlT^5(7XCMcJzmdgryCVoxU`YcYCo{)cg2B3>=#Ik^g^`_xdl zeg>pFi1nydA(&>p$C-x(BHJM^=rj4YmkA>t(T#SrJc+ge{Pu0Fc8Qcj=U-uwp9S5@ zsO*V+ym_>*6>O7Sl>S9HgN@K$RXx5A&w zzBn>^y3Wn3=>B5urXlfbzP0V}#uzVpn%zAAlM=@H+q2nnauMVM6C>EbaO)*-(O4Ka zr;ALBFa2Yra$CN04K{ik$@847SM%jM9h{gFmH+#Q0ZnXc`U<&qhN^=@qOYFEw9p;@ z(tmJqBSTARYk6?TM4|xBhHW7g-u^PLhVH>jQ&T+mp%DZp!iOzy<@mBXqt^4T$j92u zHO`x+cD?)$xIblcp2oGd6|+m8i*v%cFDrKT45|h9Rw?=O)%i=4(mDZRgF%~E9G19f zKx%#6^XIAr5myqc`EWrm$ibbTr9p`T05vQtpu=WdcM0DgF3*%6DDTS+2d~badRFod zrs!%eEY&taC~~@petljJ<2H*1;(ld;M=*-Rs~W+9Wm^SnmULsVg(|=t`?zdId^}$~ z;S6}+8jAo*k|nZgJ$1+B`8G4+2B>tBFF zd)#Nk#D;^T0)W^}m(SC}hH3D$+9XG=HO@^LTbz0n9xCZZZ?sYssTmd~TiZ`l7?w+VA!t{0 zx$J&$U1BEbQ@3SeQew3`O72$M<`0;-z@77SCqBIzuRX~u+Pl#M1pRc!O}i>7usG0! z4U9`!@egOTzlXsFcvF+85V0WBb>Rz9jC%R%QmUO-)|ziuKpCJP36QVjtmt_x|3f|m zU=VA+ToDC+BL9$Ff8pR&?ypP9f!A-vb4jqvI%#Y}uPf;CY4@Ek(0;P^%AXLNR+V7a zN~2K%)55JT!;H-UDt$3C0~{NQ_8ighLN0Pu?(uw*Xw!xzW6cc&=+_O#i|E!x!3G9y zCQ=?!@^he_DhHT#W_>_z;{Jj*=x_-S}LEPo#l ziSt1ebHfzl+w&5+jtjrYi8+Py_MW>bV-_Fbh48%HnzMrDA0CaN6hRv?HB|qjLLw)9 zVz(trIEL?`xzWFCqJa$^Z1y^-%fr9pksP?WweM)hdjw0DZ!bik3DGOrEDABz=P1XP zgSQ9MO#rB}* z_G*M}hpDQBDe}4kQ$nDNk<%Xt2N|C+a(%`$L%$v)zm6Q2Ti0T~STu3O1k@yEV)&^? zBSs^W<)u8{)Ue2w22>yxFkiK+ElA7U5^~MHm3@bQ>x?4BEM-ZU6HNkE@%*}bWc8)n z*9)Su=d6iKhmLwozHOB?np{f0bxq*4J8>s8NjN$slaD{xbc}sRo<@(lWj&+8rr0d8 zGM(D+n^&-q`>w?)A~#AsB+@t9S8a5&)1>GRB29p5RztZPGWh}>&b?R1c)xc8)Z}#c&z{OSj^=^3gciizh;%#i+L+tt?-3w?_F0tlb zEAgs?@4J|f(fjB8Cl|ZtfnJW1m;fpI(+$wcc$si+Deal_Nt`nAhINtUhx$tu;&dw3 z`~2-G;9S7bEb9F^^O@vEtI6~2zhLHcdRDT*RQ5I0%PO96y@0*Nc~fmhZ(K;jU>Y*f z1q$P!Jx>YdeA zbI)Rs%6-lp&6~+Hq)l5{d*&%JM}iKc{9t`xWq%2Vk!9y76^a-y)g za(-ti>T$`Az@hNy|2AaEUK0EOauO-XLf4hpzmV(xo|5p-wqUlx$@)Uk;XP>n$fz3i zep{1uF$OEjU{6Ad2G~OL3NY8K@+5sfwyRXS;mQn_Le(TlV>b2DmJ$c*6b{Jsm!sjT zKV8p=#1KdW6wrs?7Hra|&I-_ydG>@#ecoHaOFJcZm=uXA@OZ1FV4y$R z3S=^sOeKz&d7EE`8p+M!jIpBIq7qPN4S^y#k=vgFPa|#-n0VW?tY{>b7^6i>6<#LE z6X$=t_IgJ7Rw&Q!(nJ*FJ(>{>;;ySbomOWGbUo-b@A&9(KB-%6+-{|PnSJOs` zfMCVfVaN`bOxZP zXAe@0I#7c`z3}LA7enzj<*vZfE2TOocTN{i;ALVnAoJ3|v_x+X5(f}ZV=4O#y+%;k zTsPQzTFx64jAAki2J~Cnf<0rZ%+_&e;+a$L zCQ*w@A-%%OU)%LP?7y8oij{<-zCab>xH_>4_-ne{W*v}o&%Pkz)%rpEFO%0Ya{*b5 zYIZnbA$ivXf0hej=@#2c_+>VTP=BqW<2-SvEa}R)`~&Ki_{wk=gbN%l23Bx5TW--y zWHL;R9y~U3w82VSRH;nm=b1$*M@;O>{g|qqM7!97ift@1FYE}3Y!S}Zp7H`TMVVi# zNeFnJ=SawhUqinnICUoIM*N>sam2ob+t=|)ulb=a&%w@%9l~P8*+m1sar&GES#P=V z&}IP0rub#BUSHPXFEUDUpq5;ws?VU)3X%IjOAnsCD&(}YK?7ZBv0*2-`)42!m<-x! zLa*lW$?a(C82p|M;@Q;Prkwm(Qv>udxIu7XMp<5>B?Q1Kc-wuEFfIxrjx-TapCR}d z!g*oEbIkGmu$#{;^e5~3RuA<%WCZ(0fR|t!)ZlAV9N`GAzso#bH-Sx`I}P|px4J%g z_y#%MyXI5kU6V&D>E&>w|AWSQ&bJEABV4;A)$e|VY3N(hgcL=BRcq74yx-&^Xbkhr(@!G6nGg&PwenmB7Ih1DFl`}i2N;HjFU)A6F*%crcCYX%39Qdx}JRZ z6zs_9JsbCc!d*5Rfejy()kZDChRPnR!V!s{H>I*x5(`Ymle3|??YN8_epW7h_2 zk-u8!wjp|lbRTb07VS*Eg}wXo8oMaL-F4>6$J@W-*)|Zt48s6v%C0r;&zev!bPb>P z$4JF+vQI8@d$j)Elh2IK9;nKJH5fM?mtltk=K~%9l9^pdfc62xOG_uvTOF8LpR!I7 z5cU96{j)h$0R<&BJjR^nD~hbGXQdQ%I?O6S%D*XCbi6S+96<5gQVGVXDI)Oq^F?a2 zF_4NG&SxYEQu`Bk&JfdRP2EmvGPc7fWeZf89y*lBPMxtCOoq_elbY)Fs$!J!#UYbU z&(^^TmxDUGjIfBThmgz%f|<*m6#K}QPaODEwLZOrt`kwi8EPUnXJVE?M?1<1IO}s% zNU~=s4I{cYl(N@=25izmCIj=HJ8_6XhgN<@EmYr)Sx+dJ9Pg#>&!u?;kdSPyuZKgd zEpBpv!KJ}T7)miD)ThO6l`D} z>2*m@>PcK-HK7+CV>V6PQ88O8cIW)pNsem9j{Abn1wm$-2Lz5EbFv)tlEg)SvkJpm7H`>*B~ufLbeC+6gb!vkRfmFI*SIC`P&cC z@J53TQC7a_&tYW984T7R4jf3-Wcd#%D~0M>VD*K0Txj)QQIf2YRKHsfu&{AwqCw~S zClHa(Gz)|yU>buC7lfNNkeS2`*-{_|*&MbhUxG!n^^ZF?O#4uvHCnlI4K;8oM!DJN zX?*t-l+XzgJxM`0Q?ez*3{QzK#QBt1#s{(sjk}=D=nAIuT@ZRr*mdim+j@8(JWnY+ z-%-xk@ffY|70wgPLEJpOi-*$(6$mJ%)kp-ZSw-z>)Gu$Ozf-Un24&BWb+-2cnMQam zl!oby8TuGUUtE*;P4WZfOoL=@>Z(8nRN`%xJ>ba{2V^WMg3noITMwxO^3(5k`us`q|?lb zeu6ILJU5&UfOm)5vuAuB9pYzWS>dnESB0?Z3@?Z}&``T|U8$G*E5&WeZX##Br;2|c;JnJz=aO0pK)A ze@fJw18dXBS{j|ubSn?Vq#qYXASNFq2~8TRSH!-${bhv?KU|hgRFBIO6=q6uXO?}b+`orz^J_x%ws)GbH-mdITsl*+c>t%w!bw#Po^aJvkq|VqqZi-|;bB7{8b+Zd-*9At z?hSx{YK9||8+frIqqK)qy3_jriwGbmnZK?QDg1uS8Vt@tOa@Kg_o0D9^XQ1nQzLTE zFyZ7^b)Fdf$uw!s)sotH9Guo<;MH9ft>ueOl$A;cd^hNEjyR0NEi>-p`cg-ue#N@T zcLo1A4D>LOujeT*H{VYpit==PM7X2sx>dCdW!FG?>&3=dmNYzB<+AjPH$F!gf= z;sQ1jDi9u&iYm%Ti(Xk)@8aviCDW!a`~0+=%`CGkd-Gau93u1lihJMSA;zHW-K*aZ z6GV=d!%paaJ+)4Z?TV^OopwS;Bc`}$tp2<>W{u(FhT8?C81*osOGzf2W)vgh;6B1| z?tdZ!+Hd}60lRlp2Zj2d3Z357h7(QLdBeCH?8mg))3w+|=M5odI3hmc2P8t=&s9UY zh3{{TNxsudn@uWSBe872)?yI@#r|6ya!QWD3NrN)A*z2$d4ezi-CpwiK+{R7F~qAI zBY80^`U6wkl(mpH;E6aScWCx%Oq;U^d}C~zB<5s{`g`KwPU%q@>=Y|&NNH+Qr-u&j zu-f@~rBYb<+C4+4?2g51fL5_Y$Jg1-9VL|RQcu96ap6uQoKG4W@#vHM^(BQUn?`icHu;a?J`g>j^{0nh8= zKWvvFi_EJAsGV$OGz-E4&zm?Nf<7KS&@4qzw^-_1eG2V&!5P`2#y3uag@ZTdPQtK3 z4!Kyy%q}@5I(sL>{*lLd_mmLBK!k8ErqzP2$kX-dA&VS)VsYdl^HH3*AQ^FTi<1y2 z6p{&}t!Q16N%aQ6)+CN1Ya&?ua_DU+KT(Qh@!2s?Q9p`p0p4wZxY{aVG5F09X zV`TE++TiYVtiq6E6>%4-RmSj5o1q^i7ad5OML5{q5q%(r$eKWz;iiv2nK##W%1<}a zYWj6-mjL*Aj$pMu;5+_8At zD=UwR4V)odTJ(Th9a^(Fac5N>mWGw@u9l;XI<3+aU-qjTBPU$T+we|mj_IKium#JM z%dVzZ^^s25*rIo&PXfBSvb!^!n*heh}))mN`M1{;cZMni@D6 z&DHGbHUoKXb)V?X)e#E{cE#QTb(<8yo7(Yd1yPU_r~Qr}JTjr2$pw|h;EmQ!AyQMI z4D{u(=^f6pM+V7~BbzH;gZknF-@z2U_}#{!&Fj4re?ZwBU@7K%(Dgn(n#jnROR+^!XKYrLDL@HH( z28bV^s1RQw!r^x~60mD0TFM|(8-UWSz}ibt(zzzUX}uh{p_fZD0&`exZLlgUT?QE< zX4WgyV`d6nkTzQ#!*lxUq!*jNA<@!-_M_CqSSm(;Z0=g(92*05SVd`Dn96AHMQEMq zRyeC06IZoUkPnugl?*DCk1VM6`3E!$VwIP6)5s&29xg!D?eL*|w&jv4lcoC%#p(}| z+;BKjRf_z-i*qJ;)Q(&x6LHj(-XL$A&1snya`TbKi~Q$^N2iWVNurUW9TJfUSr`W= zSzw-ZKfG>sb~<~q7(j|895AGCJ}52OM?{+<7H`z*jaGvG!YWK#Zx^oIMn<}SY$Nik z4a(IguSLqO67sbw>FyK{GuuDkGW)}+@=0^ zHz#8&wKc|pW5>?}X|3oiy5^ZCf)an)AX4Wk$(lLL^zHX2-MJ_gHGF|0ZD*$L86X}X zuVB?^|G3H~!NXiex@>QULtX2%{hXYcj=dkaosW8+<9%AXJU2B^%ekoiOO_afTnfzM z)4c^e!sE}F^;?PdE)&1&861LbxSp$lk9_PM0h-`R1wNxYmlIUvO`lj6Pj6ejt?9U( zc(#~xy=q#~kc#M#&|!Iw?SQv>z6e^yz?L!$L>;hn1dqGOG^$-W(<=y~&SE`cO3b37 zfmi|9zE#25?ob^oaTz4t3}1X)<90%zzjOr^Sk!99Yz%lR8;Iekf)bXl$$ZY(N)5*vl(9VYq` zdmzz8YWj7O-;v0?3D^shHfmnO#BKJhB8tkF(erLvr+fqN?QyYCqMb*TO}P-=(Unyx z93<*ny=uU@lLP)tbtAPtN)^_2AwET}A<-d1v(m(EnBBZZ?Q_Sgr=n>HiEh%~<%^-S z(waoVf6H0`HUq?!D8W1Id=3iKnK3u8CESUS@hyL!sELcNvs?e7bK11Mbd=b%~C#JWAig&y4R;wu)cF@2D&iA}b zUuG5TOb%?(H1)SGtJP-63rK^Hk_N0L&dt>OC`z}Z0Z%lplJ)*R6R$>m?<;Z?1)v}g zM^%8Km|l94Z(%o08}`t!4P)lJ%xGbN7E9$3r@2k1F900XgtXb|@HIaC{7Je8aS1Dq zzP)w3ti;A|=F<@lR>Sr0dS8xaAQgKHDQBRfzVE8?E^lS2Lk1T?*iSFD*-A(0*`91t zM@E>0_vpCA`;t(7=?qE7W%iAr7TNBA+igP*kYgcLtktJGodU3sfuXiWS|DgwhB3V_ zx*=p0*KYf8&< zj=H@B+X394%#=05Ev`wmk~>dbBn3vZ4>_v&1NeZNnqQ8isbT3#gz znH!5dus!`o%k*8g1oEehHAv<8cW@A=cGBa81OJ`mT6M+2y`hkkBCT>1l}^{QTtyBY z29}^nRTUqwiU-xp zD827YQ&1rfZIpM)yBHDX6DA4YJgzC$G&EnwQ~3TvZ1$d}t0e);hiKjY(K*A7-wg z1ku|&ouK4$4vNv&7v+c#shL7R?5_yI5lOjR0|VG}1mrRj?r)i%F)*_G8*IeR6^7S! zDW`5AXfkCO#bp!=k0i^2fzxzr$6%;gfADsE7{O0|7C&ZoZ8L!4clVaa+~Q0r-B2dX!_Xn4 zT9w0b+2Su>!f`tMgm$wdh|m$1xAII+%$2m6F^Sn5!9b>|UjP^b);F;`xnrCR9mc~w z$w<;qjn6XRIs!>&@tFqR1husUElgnxj4>-)RxMyPx~R%EeFS_lf>n^MM9=VF%!c)t z6)F9W(&p*WM} z&FrZ`8!$!3$f$DadiAsjRSGRhc&HkkMuCQ9xRg*^`%*Dm(BaIOq_jzyTGrqt^lgMr zc6{>ZAv1@Glfo2X$VaIxurv)2l+>k!fSHWK%KRFlsl`TiPz8TQ+ich*p5}pg?2IrWc40+@7^Ti; z4oiIenhdfH^NNsro`J$LT@!@kQLwIWq3@oj7p%6bqg6Ag1fh7b-;8+Je9!bUB+1ER z`f_n)_n-R=*-3LUED)%W>U%;%v*0n`IuUQ@hk3{0CAR`RD8m`s#pYzmn~Nwje1<<9hwPl7`% zd5!v;Nx!9W!0=|o=3a0OyC@SNlTXhpyF97>mD4$a%W-`&ItISGY>K{oJ_kSiBY8q6 z%VtQOCQ>E}=$B>pTUeZ1-cvXUjwHiQD=pQr0y42*CP#~RUwg7o@_7>$2oInTdX_B{ z9ol200;=5YJ=0SZrDx{N$Z`JS)8!{rQm1IR*ai^L==)7u+Dj=6A@nS6PPA|1lN)kf z5Wc%rEwuSwB<#vcYlVyZu}ka?$nCy%JCj%Kie{ddLy8^^d#@m0+Y1t?ebVeH@{79k z*zc$&2MrzLo!048J9SskRV{_1o_*tMx4YZXWK(1C`D7XJ?1p~^b3jtdW|vqI!nkH7 zbGvZ@-A!$WrJ7=sck$({6&KYT)dMCQf_1UphyLrn#xdiLbX+fy6k;?pldD&*1y3hu zJY~8c87SS@gFZS=HW_6vilSNKsyo9w#ltT(wQ>d*E}dX%GV#y3QKOmYkM*Nq20txA zB@A6{L9yP}ozT#FDOJ~1El#%z=m2S?Yn}rSg>B8o9>8MFvVs7gbb(S5dW?wCs}dBe!<)^=_TUD|JUZCU4z@b33LTufmVQ;x%83YGW7Fu7 z>lz(-+X7yVq4nYZS81gg_<7D#9&o(;M;#vlBMr5(Dsxa+)&eTxMO)4Jy4gK-eD2D( zek_>YN<<$XK<3rF=y4tNI>I%)CEFzDF5tylu}wHU)^`;#*6v%z;}32LC#U+dSd>IX z&E?NF6G*gcgec(Ts!A$v7HqV#C#m+dbIN*lwV+2B$Vp(aS@it7X(t4PD{A=KUbeEK zadoxN-2$3xzRp9vtf#C=V1YfqrINiYo8(fTM9f}xpnu$T*-|8|_1UW^R@N~N)y{5DiYe z!GAdb)qV7L(jY3!cY$^N9#VcIQ8hXCL*y(xIgIVVm3#nz#^TqS6R&+ZL`+%$%EV0N z34Byx1o78;Y?yC-b`TtxV8P8gj@e#%3u0@bZ*}ubT_H3P@y-I2Ym%5)6KEN2CMp_& z*hZg0vROvC9}|X=(eyp6DCwY1hTIF9Hr&U>AVY&IpY)N-Leg<6sc0Bq>kazM^Wucg z%Z8kqz|bwTr%>i%jh$ySX|Fg=J{nm@oR-j(0*&B_S%@Do{QdVjC_OwG6rgIrRI3o(TW_|_X^w5@aby&f@0hME!xewr~k|#E^`C< zY_uIE9uo!~adkm0B;g$L4~FTl(>Y^85c!J{s1)L7{TOUsV*l5jT3uPNtgLL$=QiS| zAUgX@@H+@{^nv*_@4_M3a!+jr0CLu0;&cdMg?U_&SS%3cnP%rMs}xFlE1W584_<_i z3JoTjgI>yRWjrJbTVVi>K2pBWk4+lP76GT~F1fgfT|;tR!+?IGY} zbWaTd@N*DQW;#5*ayfJl3mYz9UNtgx=kY(dfUW&s9}jrOTiu+!?bV(9VxLoN&9-Jn z1_do>=Eh<7AS{D0p`~&QQt+DTF44bKoXCfd73u=G@Y7*j8r$+PgQ~FJ+JmU!)NWG0 z2Iqs<$OTJDf?(%Mz!Co+0Chl$zvXFMv6KdZrfTLXQy!lxRr3^+wxKp@53)STUluB5 zl1H=eX8U+@`*cq2>)iMC_d`%#aWFZ;sfj++eK&=`rf9^O#j!YF`SGLAzux2*#r$2* z`}5W`iTW0Y5Cx{7958I_j}@MPWX~?Q}#3h69XGo@4u{8Rj6IU@goc-eO3r7N(8cS2$Qj@^aiw$@Q%jIkg25d zZ-3wEiH6M~KRVBct7_{`xL4Qs6Se3p;43ogh%^EJL)Lj!PR$e%vX{SQZ$wTAYz28B zJni5e%Ce?es000>stFCc!bC)mxs3?lG(z4wl@Tg18oXEay$E94=^4>4MPK7~1yKUH z_?*2^w=9S+#5|K6G~|(0jpGg)qUD3Nki{72AaW`;^js@!u^^n}kbQ{FE+cm-b$%xSi=p_T)*{*j1bWul6l4RIUJ*YalrWH68n=S3q(P`&sx3(Y`;byM$7h%17}V`Cs2L1Q_6 zoi9qZ?tn*w243S1xSx%!@Nu``(I)V1Fit}I_f9A7?GoHijy=#8#avu0C%c+`vnWqW zNb#*?k_WSsIis?pNo53ks`j`Punn=&?OKYUm6B_k@&&1rPJD)?04_c2DyJ_yPGtFsa$v<8U!tri zd-3J|26520hMGg0kPV|7gjPW0nbuHkxPFUUy=qWQahv1|vYP$+(_gsyFnkBJ>#k2%i{N1VrEZV8kS&*f`Z6(@K<%m$55PGS&Sf7!@ z)XDgbqc3E-Z*EnEvAPCU*f(nO-Z~~4^;`61eCZ8-NdDHV$<_GUpX0w40AG1%1AwF< z_7Co$1duvV+}=e5DXFK|qw`fU9WATQsXFJ6I(+!QpN38$&6H`SW$BW4`Gr$JMR2li zPrvRq64x^pCp$LZIkrx9{B~oRFG)XQ6>ofozR0(gad`Kgs(H3sri?K9m)SPrni z|8h|j%de-NL8wmyCOu9c+PPpaZYrhij~K12j5;*cM$3AHr(6Zx&^TR;hzm#7@y{Fg zzk6&inOc=^7R6GtHM!QMrbO;?fe6)mrHs&t?u|LCvnzTg$@UWI-rKKEaUMFc=a5Qr z+b@Qr$k}uS^~ejm$8Kk&`Tx7AOu8BAn@0O!&U$UWhRjmO4zJjBSLlgfQ487l2V39t(8d%|nC4PN*f}P8@j3uwo?W zwq^>|fBdh%{^$P>HISKHDDoXzk7hLUNx{&$D&W}uPg#(ZKBvLaKxB>(@jZ{pk9=>E zq5xLRg)FloU~@nzn*uz6S85h@w!siKly)-Wsx3d54Z-<^^30L_C+&lfz#v65rzeR& zNBzgab+4YvBV)usK5bx4h(Aa`wYNbcDQX*nvmI+sbnqR9$%)(*b#}y}m{0NxZ5-`R zXm^70-9FA=7un(AXmi>cV1)!*_=BQNUh z^?>)PQkrnE9$V6N-usN!b^w|>Gbqg83wKPG9UUV}1ne7pgR*{!iyMlD99>2ELGp%Tw6d%gYeMtUv4CQL^^l zdjTI`9nDT~v*nAIid|Z^doN408LMqZOy;A;wVL)^V)${n(oO05h`UV$wy6&7JUc%e zu>b9toV5p!d-z=Eu|57jjn|IwTr#-gKCnbS%pN2bxr>AC>Eavz6}hIN%^c^}E+l$G zQgVk6nMoWq=GY_TMX1&TmQ%pD#iUrm#Y`WCid;;pOXMQwpy@eYgdjS1;XivY-KKj^ z-LJgon~rj}B;1f`yF||2veZ{?sLHFU9MbZ{w^2Z(^pWF{ByxQ}VN11`+dYGO4`cMA||M@5Hkm2Q8qt1C34%~lQ z5AG0XlR-&E2$o6%w2VKc-#%qaMGwz%@6^ZZ4RFkQVm(+u{l`HKY~~DTo;qoLE6o?P zKV^%oR5{f2=bvWfr$oK@x9(*R8v>l0FkI|YW8aC_C3{`6*X5^SiF8fsM_%NWJiT*= zA7_ht9+^0rfjp0Z601>qM{tHzRCvKI9yySxETJ^J^@E#f6X!EC|yGUXn?zFF%CT|o-7ua2Jvhk zNE2C)E6?mVo#B3!Q^nbSl9ZD|a4?D7g68Ke3D6+a!w?mlcr8Gc9T1J?HigGRm8P@;kx!9Co1o@W(@G&ZuCiE)d8RQ>3CGFdWWnlPA# zt+k#m80Bsv6Vw9g)E4L2WO-#&R7fI{(PuAk5C@;vr>IGOwo!t@@J|W`%|t1TZjUVm zxSLKWUnplk-#x}P@`A3y7nJ zsMj=chQ25k;PJyr@T%x*BD4ulWKp*f zPlKZzoc2g)G~2>JROr&4dvM^OUK}(bj2~$LrUA{KmC=32?H@mWao`bybTa9N$Cpg5 z-p4#In@Oy?5#D&Y*2N9P_$a&fwX`EMj2mTrd?w^nTeEh>Q|ETa<86abD(`pd-0;X{ zfHm=6@em@`yyX$-taH`#%b(M(dZ69DaK{N=@JOTf@x%}wP-ysjw)LN!K*3-&RHGhT z#1AGSq9=;wR^>VI=L&E0jIP85v0C%wtrc1kpBBF_qJCEP{ZdREH@M2iE}X78pE$x) zgLlP_dw-dQ?@bosApXXgduM6osnhrhTpD@U(0#bxnB?tryLI%7=O# zc~J0TJBjVkyskadxwx+UCi#B50D7!a&ENC0OfSl}m?j48gxi;Jfxp1gp#_tOw=mo3x zySUfcfL$Hrf)O`@!|!3UdV{;24c+SC^;Jl`;X{wy=|rWYCUOz|tbL(FE8{Vphwphp z1jt)`ocB7xMHaGslbf0J)ru?&co6XrGa=ZakInsnQ;{Ha*PkeKp5BkT9qEooVdZ@j zen=6K+qW%Er=`nqTiVp2O2)m7++fKpSBdtas``?`HiM7u&t{XTxkTVA9E9j<^qiTX z@z8CfD#?f20F?}-a7Y$e;gb^hL{Lx7&!i$R>M?TrQ$L?xP{nY;$TWYNe!2XLtz%bN z(-u5d+o5&uaHK~efW;KT+;*ftub=?AGGljAI`_A_aDBRqamIR?jM&otiAvP*=5>hF zkmmh_O2>BQB$}Fk#~GE62E$~hxt5vO5+M8e@!IFc7=y8NnQg+#u)=mJGH6WXvR^!rq9m5#rE25DMz4x?he zII5QR?jEUD2u8vs^WcLhV*W z%Zan2B14NrZW5ho9U`5gAgs@tKMM^CSd7}FlpX+=e%rtwJyQ&;8eAftmgNrtar@HA z!0tN2twK#xC&{{fmj{c}KOHQz<*VmFlI(ZIWb&|>&Q?qYO20qfKpibnc?SRJ$b_@q zkftR{t^_r$>hfA#M=7SS8>wU8Ca7cnHe5+!nu1c3R7>%~eMe4m@e zP9Q5i6rs9rB+s{S+yAnV-UKMa&jVxgSK>nWUAM?e!(MW@)b~_uL0jlK*h0HKFYI&p zPLiC}?|sOp6RJ?=SG(s7-qAX1X-uP|kH2a$&QlPzA54CmJWAdRlzzfZNL=+Cz;~IB z=A$K(k~n}x@v=NA7{+9AsqG9>UcZLlJfsoA#m4c`kPfTxLgeHvD-`IjCjBW3;J#Km z@8hFEo39`Ze)JURw+W|Hmu2ok%UA>2@|=&hy^YSsR1pRW1gKo@$$9^>&NO>PDgAg> zey8MvA&j`$;)SOjHBe{}81= z){1^x8M#g1T4nqxUaM47DAK{00aD-QwZ6?+@AR$6BR&2UvPkp%D`rAzvYvvRauh-< zd$-8XU`i_`#}HY%`%c&`1s^f0}V zbOI8{bL2Tp)=hY1o%qlxj@=MS#rqbmmY7n7+UI6U9bkxs$ed&BwxZS?8N)5i9pfHz z&|Ppu;=HP0iay?=KGnh6*PYcz9}VQeWVS3u0V9Nd;vEj?%rk1Z%;u|a@U{cA@9i`# zJHc>eo>H&ycz|QbIaE%$`BkaH&%Nq$pqc5TVKo^~Rn`$4LJ(oBDQf|) zx*+z6-l7$dR~MC#@phGO9NB?nD3{jBb5o)t8%I&uR{>Z^B~CnSzk8fcoZhNKl@$5M z*d?bT#Zhs8aa#Uq`ouNoxa8z}PeKdgM~V@D6t+1(;X>n}NJ1@4u|&cvz*-LkT=0}} zL6ov@3QQj-DInPBpETG&!{U5me!3>jHeswucLE{S%69e? zySX-u*2Nw8+fewt5TCiwH&Oj_N>rPK9n z9Gf)W&%HRHKThNYoyMm-0AMRS=>kULlfb@C(vdM@XG#qch!%BRcW-a^Bmt|t%3gK^ ztZsqMq*4p!)rbOf0Bx6-N>O0y?hWdz25w?IVxxG1*mNCH7=ymQC$bj-nnv(7)ZyD zQIKocn0OwbKpQv)ppi$ksRGYr4g?Qhgxa9YQ3$CcB;BO;WKm&SZ?4Ho$rm=yhwr_NsRwqxMj{gBeZ>cZI#-gf9L?%fNiy?Ay)RZq6n zGQI=6(2C$L*aY=6+2g7O$Apvdfk@i&K>m$ol8U8y23VudIuD3u3)Yf{%5}4%hD^zU z?l(OpeMqrot&N?K1*Nw+*F=ayluKDU=cO~PtRu^kAoI>8%0LdUqiq6|Z;LuIRx;A+ zi065#&~>g$>Qd@@MN$_>$txwJ`=$qZbC*i7PsJ2tRPUoCs_|EQ26aVHa4D@}Q?m$V zTzf0ku%Z3;f3)?r|Nf7{1vV=UHf)&El0?ij>5_)f37`su%m4n5#(CCpxn%Z<>Vhm3VuIGpbq-X_hVG|r!Oxmp z#8pxITGw$pxeHpKG9gWPGf_E#9HQZgU<_}5*qs!Q+MdhB-YqaMm2+I?fxvDlGvxtJmejej9J#+ znoB_K61qZAKBhBuxXrZ2?qS3WUOefX#+TdC+#&XUstn?HK-N2U4c7zCk+hI<&uQzt z_3&?}jTwsH%U0}+EYQ?0O7}u-F?!0^$#65!zX&6rZtQu>AAhW9`A@v1)}8P?xT5ZK zXN1e|(mbKXHE(n!s=AQyQ@6|_>9mPx<$9s;hF6~<>emlr+o)+iw~b!rTQ}{*i^YM5 zrqxQ@SfN$k+KRl6`^&5e(C;ME9H@`-0PaEwHSX7Sh-#Xj)VOlh#F*2=9WKalD!Wp# zMNpmn?2^P6v3EGavamRFIvrA?6w-^Z#IPm?xCmFW4gb^-aU$&nbk6iCk%~{$iNK(b z3|S}AS`#~XZvkN^p+`&FN$b@TcFY7V&?GY?p6II4$JN~j1)z->?x_&T*MSrXm+i_@ zd5`ZKo_3L6_X2-;dbC{Os-(}?(UU}cj?^fdT2pzr)iq%_M7}f#J~DW(#|NP2xkYw7 z_Z~sv#Aikm_>}h!YlqA?xT(LXGC=N6N1{nt*~Y*&S|)So z_={8v7kyqpux8jF$+Hn6xpOA5RFf7iw*$Dd2ZTi!wJbXJX6VGeV~xAmx}w!Tbt|?7 zJAIyfSq;y)Li0ERoiY4`a z=`3lWRd`9O!Iw4Q#}?ASPW6%+`~1=ObndY&{pkBO4bUBuOYGbN8na{z4o#X>->GMi z&U^Y_m`0Na&_fm1BZ`ba&VK#B{Qt6Y2}~B#_+kuvxqJ+EXLwL$=eF&8wLkS4TWSC? zeHLqcs42U;s?iLBZTP5-1v_d8$fpS$Tc!^H5cd!<3vTSw+*tTc(3Ux(8bl#JOdzDithb5`{h+59$fVclTA21^_QQn}0N!yM!(b0v?mBgwh4Fsbn8&=fyNBcmu? zxpPS(6!)`wBoqBUk$6JOAjpUzD2b3la4Jbk_vfiaM(&3Z(s3In?f#s;0!ll=Uv&zD zbP;ff!eM+bOFQowJs$loK%n$EBU%)HXx;48>L&l42gGh25Nuv-x*8bo)={sWk?UR8 z>^L_%#?Iy5RL^~T(*M+?fYfak_@;7exzv`*mEA8ZH;`vCHFr`3LS#!tzDn9#-tQ~; zCM6u=`w_ot_v3rIAHB=39v%*iZN_aUHE1w($3;NY*?Oi&XVdNHgOaudeP7nyh9-=P ztr+~ySVMu*!1}3-SA0)PQ0=~c|M#_zCL3%^ADBc<#nW3OWhDZqQeTODD>o=xiAo*R z3nxj>@P1iO)u;lIsBIvaoKxP8K@+6C9m&wO^o_gDcB#ix*x=Xz?F}Qk-@)#8yrt|s zLukBfci?}&bAkDGZg}_B-Pe`GoVX=T|I-G0(FdS%6Z$@?VgE5dPug_mC-rt)@Y}>~ z=9_IjyAX$vTZ`M=2v^@=E^psL7IS3?r+jF2&EP4PZe{cDIroRgcC*^5DpxLo&35|L zU`5k1xvhJh=n=ih(ZHEipxu#}ktvknbs**2SBAyj1APM#`?p-XpNn4X5V6pH!aK?hhb6Ek7t*ItU zh!W}rkK7jMVWP;95x--Y1&mtoib)*xGOHkWU?yw?!|bpADxu*~Hk5q`6*RezBM4+p z8jPBUWu!>!#~5O>FS*uosTfo>JsQ-57w{{#WU@nXb8lkTxz>DQAAFs}NkHj$<$$c} z#uNHnAm|UA4m-WAr>J~r4CSQ`q7HpvNg4Jp6OAVq-;~KU&thR!{+P+AR*_(gg^`HN zju@5*59n3!wot|wva>;iVx`SJ>i`6v&rbvoYJpm8c*jLP0>Dre833nN+;InRRIGBy z=AMjwZ*bejF)qT}v~p#q#f0jg}#0CJr$w+ zu3SwS61@;IPX6YzOb7P>a9E5UO!D%?ZYGM8$~k3sJp^P-!l~N{Kk9oZ%_Go)xq`yb z_`ouOehsnm*KS2PhrPx~)gFL}$<8!3`-bi4vniMu!D#iC+Guzp&e{V2usT3K@Cag+ zVeU3ZC>P6BfE^%_ORRhzoP+9I_Nh9UF#&n8jP>AbqhLpPWXP#dA6V(li<9#nPrbXw zNq_@oI}4bT=ksUf%W1x1IPJr%16#WWV{ktXafTYaL2w6{guxix z(R;Z^yMzqMIpB$6B6azO zK##>XY9L8;t~$m2AL-NGs9{!u>u&L@%jG4L+3eNnT<*&{{KOY{n6&Y|Y4L<$TJdc? z60MW9Qwgx1a|@heG|QT7(Fggyz+_k1J#3}w{3ec1VAv=hYt0*1WJI^ zLtW?;cP4)Wq++)*M}5BDM#Zt$(7oT~io%%8wZv4S-c_{S)oQGyt&Lyrh5UNK#Qc15 zAtYGF{uZah)ohWPtT)7THzB<(kMp@HwaDQmwZIX#XoA1-B65Mc@ zUKCjK2#9a^8pJoki>c4~U_E+Wj*989kfH#s0=!yF79%j5QsNLRcWF{VF-)F}$B_1s zVG%J}Nb1`c+yx3g2psh>b<`3PPU4>>Q-p^k`0AhanUqj008z^)O0X^Hq&2ILbAXIz zs3lTs@VZ!(8&Rh+N% zshEVp5oEn1e;hH>$UyhG;b>VgQ0#xm2ZOD;<~TZpOgVAPH?9wxS7qT{@WFM>MG=$X zf9td1%90KJ(aCI#EMjg{V8CgNBP9;(~-K<7;LC_NA3iiBEPRVQ^Kc8t#d`3ER-V8ixqc9fzu`9iS~eb zN;c;`VI;`N`9dHzaLORC4IMQcO?UbHHh0({ygrxe;JBd&>z_9Qg zX(&Kld{7Ao^_XGZoC-IYVm4?!iUC?L&7-{k3{Ow~ojQ-U#Ur#gnV}FU9avzz=ei9- zJK@ENaJ({)P46LpAIF#u0cf~;Qo_#KF8r^d%G|sBc$$cF7 zXoWMRwpjdEXmHULYwsRx@x#qI;5-jDcmS$N7m7Eeo`2pO4j-rSUVZqON)ST5U9C2B z{Dja1HhtT=PEM6*N~a6*eyX)bs1-`Wd`zO=CFsA_pLGuq*8a?lB(~(&U;Zos3ENOW zzYMFo3K?+~*FBHEMXpe(*w#9Y%)us1KQP11wzAYHD@+1giT32DBB`FNSv*W@EA_@#Ypi3s$fb&hPJWS_UmaJ-Rjjg z%`sO+HaqXK#&r=QYqr$nd2gVgkzSIAe5vL~Y?;sgvZei1fk61cU#K;=#@m3=BflXtq-%*K*7@a!R zaHzgtyw#DXH$kEedXz=|>h~&2^=4XyJ^8ExUg3c!C|yAlPwJ95O)B|pas`1}=TqGy zYo4m~+y_kDr@!}=o#-5@Q-OzUPFltNql#(GRikCj+ zw-dvJ5E6M2@0w_>R}VU3=Uq=a9L`Rss}wx?L__C@CznB(8%T!)yY!ysQbcSd9VQEg zu2ksOwx(f@y`o{LwO>Thtz*)mCZyA>!J?kN7?-L+n?W^rm=sd_z3;)(uZIio|@wtv17W;}HIn@@f_?X@H z?`GUq`HPeMPqT%0z}V2F6Z#~11PD9KEv5lhk>tXzf47h>uWO5&8qcVT5l`RnqK=CQ z0SIq$UklsZ?rS5@WVz*EEDoY~w0@kilX+_^rCs1MRuT93D!O#{)RlD0PfYD91wBp^ zfYrVlVKDNOI`?+!7(6}P;Rhk7@b~K2t1qes4mz=;IV$DQ7v0M17Z>@_6ED)dnbD*U z{N$$V8APsZNEOD8*s_+%9bc{?#EBNHcRDHW>LkTpHIHuJU;bR_p76_`Exlc#B043n zOYJ`T(bhADs9qSDVmb=o?YS-R%WN=OOxklZPfQRu&);Un^tFYX&dCfsO~Luh2dwLj zMtJ>+-@79=D}lP_?2yM%A@^c17`S?FAF3A+J0R_1jaZN{jd=_o^#djAB&rfpj%GaK z5stR`2ozQEZeN|lm53nHRxy`@8g?Zec*-4Q10&}~Fb55$BtF;eF}_gV7_P+?WN=TQuV0^JBiQvK5qpo$u( zDgB$8GY>xsRyIw6=qkpWfND7r3e!?rJ^BhkZA4!oV72JWUZKWR76(*=S83(le8hBQ)Q1dGudk9~HDxD|x;xJr zbQ(ueb83ylU5{qtu>W`Vu5Cw>8@cXteMP$WK@z4fB$G*IY79f8S!q46R+2TcV8B>N zymr@abyX>|N;7RiPkymK#6PxQ;uFlec3rc&XVh4$F;ZVL86@L!B7#LS=9&u@chTMb zL=S54lI5NBbyu?k+PSOQQRud)I7kJC=*Mm4P1_puUBagaR5|@#oY2{}VyEBd-3dK< z&C|}^KYroUUHZ|@o_A5{ZoRuG9qnay5$NPucFz7}7jq=V4!-6{ik-ulJ#;&Gi&Qjp zUO#hFwOUVT7hA4RK!Ous=TQy#6e!wi!ViKZK}@`l3G-QrG%K+&s~t0YAUp~B@A)Rl zZ4k8^rn&;y2_~_DN)Su?GARgN-%;rPgsx5sj*q0>3DNc<@yV#xfocb2>p-sQw13j}EFG^!y~W>p;H~;%ytu$v}6QSOboX(7#*{VyYf3|Sy$Be__sQr-d+d71OpEutB z7;&v(=MNK)|GaR0fP-M-`R+$8_g5ieFP-Bw_V^K;qPs^^KUs^n^^kP6Rp29+vUV~1 zl!e>f4&i`0K4AU!A$@LJ#(e<2_q3XO%sAf5vhG8yLp2qt4X$p(8j2B92>GcnC~9%4*^x4Eo^u zVizgwUTxg|-fy7w8)*G%pmo4p4#39paaTB4ZF#`V4|mcj7CT6;dn{&VPW# z@ekX6FNbLxIs}vY`P={eZ^oIB?OF$K86`eiyq%6Io!vX_xY_&JM;~2Y*Q4n;QN5Rq zKJL&~F{Z;PF_tqrMLKIS=nn&a-2}5vQis;15pELN*G&;Fze zj;ZACMrq?GR$}j@lEJgG2fK=!JVKTEJr#jlwjQkDM_-Rx68NFT=C_rb-}Pp;klm!d zdpQ_2REeaml^V@$e{i?EJjS8=BP|uTQq!LLm{+n$mF!n9=HK@9xBvdHY_O*e%X0i} zg{xVWsw2lwC*;}^vgr<*RzZ)N+r9f_+K(L{R#s)T_s1%x(kjx&tri?n-)ehp#rvgx z*-oZy6l>gDW$|b+?d@)@Cgb*sjJpeM-JjaK(40fH92dXdE8cau;_#8Mzemq@6t~}B zr19NVWZX70sG23lx z^KxAY+P9ljydHr80vRYb8Eq&gT7*|;#N&%unuF>vf|d!3_GfV)=_A2bjMqv z@bOD&-9J|U>1aCiuMb@%FfTfLk4E<0pV!v2ejctCpV{8w{Dy(y;R;;e{j#;kH^=DR z<%jH}^L<00%Lj;kZRL};$uQl>u)o>t27*ts_4}5VFaIgrF0aL1{+XP7_GT^OOkiWE zg4dQliHyl!?BV35=%_yCr|H(JQ`O<~{-k-RHgwm5m0NmFQHU<(8;;V8Ib^Ns#!=0v z+%Q4b#I(wlR+&%HuK5TaKp@?QZJND$niOnNVC00%qL1r7q zP(k2F1epza%@Jnd2Qyls3Xa_IaMFj5H&frAWMBQu#~Eil+o>o`)*t=^QH7wAoIZuOr7L~uz>F1s)y%GK?eW5y*p36OzD?d`A&FMM|Z){TIImF z^eS~oDH}=iCQuCJKp!trPIO(H@y+V2BB5&=XDuhB3RSL+=y}Fvk++K8%863;E-o&zD<6Kk z8cqj;-m_=Vj_u@=PqGVk&a!9xoXax%~~4{?0nYtr#@*5wJeqMf*EjMF|P~lf_Eh^6gN^9x?)vj3srbF zYYO&KAxg<3ugu1XR%mnM!AWT%XD(L0 z3^osW#X=Ce@|=UoOf%_oykJePe8CtOp;TpV48yN0wB3yvUMJ3-z3{$;2AH@RBHAU_ z80zO)d#|HUHq$^lFodC>Tj3a%*<_Q^JtuP3_VCMjCwcrK)JSEoKD!-H?z+omU+WF| zh@!H&%~eqeg+E0bN>Os7nNl_=#)IUQ%Y&?hEQD2pl`634r3~EUk*j_3(E^f=PN>pF z;Thy>^2!Tc>fETR(8?$%hSi1P1s>qV=pj$-IJeGP@zmw>I*d=2&X%?tvN6hl=_Z$q zY()fK$*R;ofTx9ZWh|wJ2~`D)l@hk_dG3@`Arwp&rVwGDY=l%o0*P$JwU4EiS_7*J zSYVLa1}#~1Ja8MTsLCQ1(X%2q4mixc^-e!^*?evK^~u87)_6lYWx-=rNM7pb94o95 zQ9`e6$vGE33hgQ$av348Lgo;MiBj>rWHErRUhk7mRRsrT=h2(e_&nyJ)PWh{rHueo z?=^5NlttyEtxC_l;o2EyIiObaTt0Q_{M&5Z_+$y~BCzRyv=P!uE&)X)SSr1--d0w{ zvUIWnFcokUfWKIJ=@^j7c%@2VO|bCJexH=0aIhgI5J;hokly*q8yB5dr7dM)VU1-W z0DTcoALe8ngY&7ZEbxqnr!J+hC#PG`M$-++RC%m|FIBFKs15!xCZXt2C@x$m9UQs? zSCtDo_ckh*d!?Cx%|)ey*^6$u5dx;hWnPs|OFil8~O z_^*mW!f0ZdN6n%!aj)&TU{r2O%Q?kpCG60a9$}n_h83_($trC$uL`Ae09_1lg=JZ= z+(Y*4$xG;~+i-187SPt#8}f0?3KpDa&H>vrLTAO`a|%Ozg5@B$D7CdtA&}-()WSKH zQ|v9G4n?sywl+p9TWA@yQ4z+WoHJ#t5J&q`I|}6xz#*M+dF2RDx#3lg2(I8I0+BV` ze3J4Z2l62Ab5J^gvl8ClmBLq!d3YcM*0SObHd0u|DI4)z@S>6$9$dl0!-Fs_D@1h_ z=X>$Z!}UWVJkKfb;X#x(Ad8BK6JS9So(yqawCKQrpo6o41s9c8a8B#k`9!4Ca{8-r z7f{>TWYC6N_L>8*(Y0k_#N3l5kH zdCq;V42zbT0@;i;9`QOaVy>&gc`NWwMp!F16|x}C5WgWn0KC1AEHwMl)b;2MTG1lX zr>5zX)SISwm|NX`$;&GpU0+&wiYaCjBs+oYTSc z_LJB1EPaj?YFfgYg!=ZPxf@Q*+gS(A19PqZ_3i0+y0!I&mT*%duXPq-Mg^`=E}@qJ(l#$6sc z3&_Qg0hP*oTXKYz$Z89R$Zwxyn1XB}ZU<{H261TR956E?K}NX9Z9w>$E3ZWfk!ukt zc@v0(n1ec$rh2lHG1u3@zn*phwgW9UV|c5i53$gtjb&k-K*Xjka7Ds;s;W}KIxir+ zP-w&k0vWS52s3$v+Yx@R#pDtB6nvPK9xV;%A{2nN0Ira-d7nFEcgTg2L%=m5c?04p z6S5` zLIdIO6h2*6`=p_02_3>No%7n}63)rP<2W6dM_z3sB#sw6=ROEy6@ztZD>WRA$RVbu zDvfV~ORGJdC9Tk70XP2 zc!HtqY`Gy9sfi&5I;v!jga%nIlvf9&pI$J0repdaIpZFbpUH^#5<0;eR8qU z6^`Pp5V(Tb6p9xdCQ|0Y!h|HZ7KT{TXTKcYrc{XAA*@_z?U2+wL2thvQ2i^?+moZQ zZH+hA?u>UiIg!E@D)+iVBrB176wWa&$f=hx798;xT(pBM;d884S_9OOn%I5P@uA?d zM7#}&%oemOkjbNup@J&FVF9uLkA}gzJcmQ$g#w7>g(=Y6dz21+`*ZKvFTLOG`ntRd zKlMGGe7JJ@^49Ns@d017n?y_*R+9vv+R9z z^%TGU@gFWOdM`)gySjgUGs!-5A7z3GmA$C1r|H1K%XR}*jUQ^LTwBes_xkHU{QJch z?UtE~S5%6RHb>PTXMcM2ZT8hS*>ZbL@8aU0dcEIgFZFBz%cm_zgC>i#!+AQHnnBWN zIxC5Xiv_Qy*Ms3_Zn5!dwmTXok~S_G=fZf>>?M&+ZtBtW`lh$mb=nkWhO|xVGJCQ7 ztu--F%7Uo}m`+-Lo7Wl~+%2fAZ1hT-{?gLkq&CB5U?$6v((c8}?6aRjeV4(A?SS@z z&GvTp!jElb$gJNi7?ZZ4naR9+susC8_+bP16;e-gMi}>3b4_;^^u|*==r=dPUuLhT z;7ilQDOlof`%T(d*H)-(vXI7-COqlWMS$Zv#QxhETfo8|{?LS)SZ4-<#X!>Kip?eD z`1|bj?1av!#;fDeFo8#6|9na_$<4=CCm_qFO_B!*E(vTl3p*IOzkUF1NJpE_v)gcM z@ivWR<%C`~szKv2dj)}ypsM{LD9m|DI?znAk;AXV!5w1S>Ms`02l zoXpIcRO%ujWCqnw)Tlr-MoLjp!dQYE@PN7<^e1;SDFOBxnqC6NEcDZ~>|HCsx3B^# z8NF~X#8NU9f=j?%-U62`zum;o6GK}a$Vzvv(44b6)P)h_9VfPrzT zfc9`Pv({-CGS51+lWq~1pyfRC^=MXeySFr(RwHRZ(`HU??n2s8fjef{3NIm*Gj!ZP zn{90Et#}TSd}}`Q+j$D14p5 z2e|MgIE;1zkze-y7+_6F`f1De+Wv8}lt8trhod@!upznMQI>t$;?e9q%AH zgO4_f>-B#4E*&7gHREqWY<@_u{P5!5-)Q78qq(gjowEC=7F7Bieo+vzM^BHb!s0OZS=CA)>n%qBZ9Z<-!yWXj4sA@kaE zY65Euz&%pegc<}tu%cT+=7pKG;EX73fDrJ)n*U?(%evb*vNY!zzakC$6oDd^+!xxc zE{dj4amunZl3Y_YG>6P3lEN4S&;Te=CFz`bn&&xZ9{P9mZ|L{_5&cW%yEh_oK_*C0 zQn{+Sgkw`cF0tIW%Xe?wh#*x4hP`5BH>y$_5LU3^;587`N?Hb>)o2MLU`$x3$TVt_ zt!@^adQXgdBeUl-X-0=^fQ%ff1~`zI@ETwqM&X*kBboxsmnlq8U?c+5cyt?#A-F`V zCBXKC7E>8G(T1}_w&P}&O6lf>-{|J`{1sJBU6BYVr;??lE@@fC5Jqi58kf#T=E_%d zR$Qe$*J@32gr>|)yat&te#<$qzt}_=%8pAslQMNlsMh703|^p>U}W(oT817mvPj-2 zf+$&#iW{`QMI8w>8Ftn1EE_T;7Apd%2Jr_St6Wo%6_PU7{-aIWW9f=tKA zcnrEtV3a!r_R?D;@R-Nb)ts<=seb2EEsMpY2MQ=EDTj5fRL!ROO1Wo3L0T?J?cx6V zCHr?!NfO)8AikPpBtoT~DKUoBUThL-ih>3mNI*e0B@aownlQ}ils>?RNQCiCtXguOG5dY`T@P)sW~*m^?azk%$kQp4U}D8DXXK+WZ4x`HY*@4 zXr)xciHVdhmQf8~N~gGhDhz@OP$nHdYCQLwUz&=m7*>JPMpCNa@^tmB$WQ+H(qI&# zG$=FzWD%N0JC)3bO?Jx};S=*J0W86yg!uIQs`LAbi$&MvDlVgL)SnimtHDM2tY9_r z?bJG$#q7_n&U&WItZ+5?)7jAzhq<#BA+C#yh;R0~}*XK`u;4~npm6h@|p~tVw;6r>v5<-j6DzOCV z2z1DyDx9Ipm;ih)LV<-GklZXw^rxv$ zig`XQw1|Xrox;4B=#9TGJ5E)jGrJn+{1NEduBogXTScn{p(*F z6CHD0N$(c63_Kw{Gzt&Oe&)O-#-KxzpAIxW9#-&id3didlKS@vt{x>`Ewf@qvigH&z zA(jJx|93?=FosooXB^kCxda(vnNHZGE`$>Dcb#{`;gJ7F36CXLAB`U=#Qb{B4}UR|~%qYH6=_Af?}x%-3b$4qUi3;bdlaN>uUAc%s3dqyuEQ)ZOevasNvAByo?5z$&0TSyp^&a!9zc zOWrZ|-~aVeD+1mB%SZEDqo?lnFVTpn1$wUlS=p)id_6APTP5cXb^QCk^5XDnRmIQ@ z3+TVtTKi^oPZ@bNBS`OzqguRJg$nAXsjk8fxv+P&E?foGF|`tFo8t z^IjT^m3kSj8Ktam*L`AL2*Jv*BRv$_%~;8u4>lm0#>yP3oKH1oCFKLN>)NE8uL_AO z_wu1w@Ql{MU&m7wnasdLEAm-%OHxu*)i_s&C3m1gvV$@Zjqm!D_G+}a z2oBd}d{7H>#!PJova8gmX)3|vk{%o92~z}6|kIF~IOwp>=W z*%%q8w|lE%M-olwH`Sm`CnuhG^!?HAPaINGVsbSr!Hc9EjVRccyk6zd>b*P2_?%If|Mk>5o2D9csXdIo2 zX?HO&=CS=B|NH+P`*`xI2>Hk^E07`MWh)gztqOP!^vK>I%Ms}qXfK(#l6_6n`Y2Nc zvXv9T-70MjkJ2WJx25JO=VADzQpi+PM}~>K(5)&HZk9K2J-4D!IQ{{f&V5(Cfh_*a z5p+Ew8Vly*{4Mfx7=H!N%_>Z7mm#wUGJ zhKd?Bb-??FuudVYqKF8VlsBNi*iAl518L$%3))_Ys;U0&SMq%fy&FpBGEQ7u1d*^~ zSJ=Mg#ZDUgB9B5R^DHxW0@w6{*ah(EX_V=o18zlbYAm_ccM` z)hu4DUe4Er2Uai|hUC8!8?g+yBgYw81LGMvBGxDh>BrMI>zCjwrwD+cW8ZyuY7nB& zs+klAozCUu7*evGAM z8E0_wQdS?sAt1$@Ay+m`Dffjc>2$sWC$dAL=`BI=iv6J(r`in7XlPjnFc8s(?I139 zed-98+xcJfgm*gPX*p64VgA8 z56MHu5l|K2P}o9;w>xMfOZZ%w-fPJVRW{iWo{<3;Q(5n-c(QxFO+GnOz&MU59w7+9 zGl#@I*or!ouleAd&@YV#WQBIR-R`rS*~V;^f{tZ$nsXP)-f7^hVWmXjluILBKNQ#L zsHA8z#riw%LsvIkgDycG1agTxaa1V{1>f7ik{_QRLBQ-hF>vMp8K_0K} zz?pS$E{l|}kFI|Pkm*t45B!uv+LCf0=c_K}Kl4xdvG1bU5|%jXP_**_oD%1z<_-Ymt1WCS&=)Cv6+jyvuh`li|v;gI*jEek38(W?*iI>UPu59#)+ zw2{3X$=i3lESAf=UdHY6XIqz|)QN{bpaH9!Ddr7S_vrue%wLu%wd~dt@+3tZM zN2IIfb#Xxr>{)T?{QbSnpUgO7O-f$ot}7kT(vvNXMzhK=;?n5x6l=9dwQk@a__sUGEEmnwE z(>Li<43CDK<2IRH4Ig#UPn z&DL&tS+OqOtthVEb_1-6VfEdwv_Vtuj&k%fZ3Uf`QgL1sD$!91S!htf2s&=k-3=*K zm7dJ*k~iuKjJRtuyAj33V*K_G4Xe2N3W6WgGz#S7eQ}kBmPLxDM!K(;b4W!tp?E(r z?&>APb*ObZE>to$hO8~l>uu4~GlvYuN0|@{`l1bgzxFWoimHZPtk-I&pRiCS6l`9FLwR15$DYoHfQ{!@jSTx@5KBxKgexO`nLR%4*10O{xmqqK6P;s5SIQ zaCX5N^Mtb@yXV?CH}7D$`t7{Z&2HqXC)gQ&x}AtEob%xgmQ!q8(b@TyW?jpCvti}g zT^m&;xts#W>l2wA_rrX)UC4IpMy)GF`G;I|7 zC5IO}Q?6{}ulbU6wOG=3T}iXc6(Vtw_fY7As8pqts$^ek)YeA}TIHplc+2m-{{@*6 zq5@q=;goKBb6d0-t$P{jcXn$ijb(|HdrJ9U6i7<_E=$l?bT5bpbW;e}Uaxu^PDeXF zC@Xz%odbC?OkbnQ0t0+w+=CpIG}EzBuj2GZ=K9LKKZOT-MQo<4r;8O1+7@YGe`H&v zK_;9?m`*qnZbJ!m2Q?={_hJ)&cjf#qKLha1j^DBh#CQyOQLt)EpTUa;P$$dfd`T6X z?>Bph;;!iouX}n(T^O)8bMdoyBco9DZZ4LS*)A`^LF!<@E-r`%E-u&vU0hHg^5R0- zAQ_eXq%&MQ#s4eGE*~-ja8LX{FimeW{_on>=lK6G@%d}U|4&qEFeQ;x^Sf%vy!Wla z_>__Vr%#@rzBv8E$#YUlEOA|#dN_p2phXdE#^sfTN*!hsu9Ikoyi|y<$)wp~ky@x? z2m1Q5$d!FMp~n~1^w(jLu!^_d>nRDM(1kW9g{735q3P7s9XbuwWd0#{L#NhNuHDRj zo>3%&uV`T15(ZM73%EfA?IAu6`9Vef47vR8>Y7Zp&*IMm8@LS?b26T%F&PL zCU6&3*~PUA#@ZQxNX9%YL5Lz3fsmSCu072SQrGQ0XT@)pRE8jGE^A|iS{;$H7&MZP z6KgN6b!_V;@~yLO#i43?)@@#Ooe%CWv*J|Oi`(Fz){=_ke)v*L!E0ozfuve_HSTLI zO+K+pSsRRcPic$!Vrxm841RY}XG4pq*6cmqxM!>%Qo(&g-4L+*M(2)lH-jiGLrVlS zTO5BKH&NW*DPHH97UfZHis&TQRmg9$d};MdVO^=mHm-9q_3M-(Ig|_L+7uLh z)YFyKbS*`cOX})cnyVbrqQZ}gwe6(N=)?Osl#HhdxA|BzcDF&irk~0s!`bHBJMeas z7h9>awIbd0P5mg#Z42nh1tEvVjNpD{iej@s@~^5sdDFd?p#XAmS~=*z=-$Ihv`eG9 zw2iIk)52N@q)#iHcJIq=EJ)RtzursnYp0hE9~?F{jJYL()F#Yw%BXl|$9xR$1M)HI zUXAhm$&b&DPcBaWcw!uXe{}kozj1EHbCr_uTzPbAj$7OcmBTH+{>>$2P%Lv`Y)j2( zOfw94;0}qA%diOlyf0OQDr#nI;Hx}89(`5OntrpKzhD-}UoIu%)1+B|k(qLgq}l+P zUg>-&lPyZV>&vm)mU2-~uc#HNr`X#k@~`FWE&WqY4K;P-2c*X|Ub`oerKS6YsC`7L z$pdI{XHr9j6WUW{RNDt1n$Gf%oy20iCBb+HCGpVSSzer+<(gxe}OM22im&O7z zaA&fKZh#8DbE#sj+`2|8M791;kP-1WlGIR@DE*uQz`(z16Crh#7nnAjlMNz{phGw2 zJL(fIj2PG#E0A$(!4l%=p&S^yc!?W-qVAZ_7+oET!{n`J821ibhWdVkdNQ3Br3Ik&YHR}Yf2Bm z2g-KEhiSsghb2;NjPboX?Blhs)!bb2`!k zT2@Tw@7A;?6?EE?_MT-|uIv2HCuSSmBR%FY{`DsDHKs>(W3nKxJN z*P*?Js-9HUesS1niO%~h6$b0dU?*KkDw4Mo8B`a(4r<$n40vY{y&N0W(ZXq3>#3*L zexa#7$`kleV|H|Mn*sdK~hG*ec1q?6AC_YLc!WQ{13Iq!G|sY zy*vNI3@Z0@{)c0KKL6tv`TR}fe^gF|s4SP{E#K>FLDg0Qya$(p&2s0Azk}tUH6i-X zzW!51r?+AA2d@3ZS1R!H@E8=5M ztqUBWa@z9#ZCR$~tiRaOz)uvXswPNwIaUaw_ZkL@O~$rWam`%C#=@K;k0U4TH(X3+ z^(>xZ2JsUum%B47tx|Gjoe|mZn0prUK{m|?NJ9{>6t`6A=Xd4gG)S>aTOP0)s$SbB zk?*LCAA0ddEj?@WX@_*6dQm4+wS=UxI&k~qzIt%(ldNZJTklaXaw3n87|MerWq~Rt zr^>BGLA52hY?KDIWvJU?q<@vAJxr~m(k8mLrrfH2^>cXc zFC3n0jsG+^LHwvX?vDT1RuF8S|LR%p=k-6o$Y&$|LwjQW0>K|T@^C0_=Eh>O5VS{n zhc+cX?0(ftGXsC2+}PB2zk2)V==tw1WNs$x72xK0G{S#f<5#~j7O%5@mxSo-%=qd{ zV+eoPHr~DC?^kQXG0xAwmb;O{w5KoUhK|jAWg4e{yg2^d$?@->{P@B+dHnRnpDs4z zF2-4NSI_gV@ta>!Dm!N>*`0jSncS-B?xOitrE$t%?tW!=J5<;O7lYq#orB?f-T2`Q zua&p?{rUyKv1V&p`X{sW)p0cFXtj(+%VpivWZ6uvm)p{tu8iSPd86NL)}?f33B~yw zuS6KUM=I*pg>Kf%K^tSZD2p%2Bq>;FjwB;bSsm&da);|~=L#jJQ`$LpI8>+74TrP& z5MQ(DWcKq4MG<3l@o(jo;c@Z1+_iK#%*2{E<==51-9}Mz$J?O_T*{iq**sm1Y4=xX zSvp*BT;I#L*&tcUL*BlR0tJJ13(Afsx0Ra9Yc1s1bz|Vx;&vkmj0_)i(jZBrq>nFQ zhqk27M>S-Z*LP`!`*E$<;q_fw;eA{yc6fc4R`?&+iXC3xr4_-)wW4@k>fO42KfF)B zSCl4efbnP=|6CX8woA&*?MQ!R5idC>SDk^nk{e5ZZDeyDEz$;oyTRp+zoNHl`k%d! zg)xlLW?EwcMRQ0;TD87cYp=Q}Lq-$)lSv1!+Bo@O(M0)EZsRR`GgiAlx3#-ab`NWI zS=j_TFCIn(hsZJ^uNWem#E~+n&F-br-zeUft-> z+mqX4yZ*9#Oq&GtjI(H{n1NtD>wb>^{cZIXBe#WyCT+mYD!q`P_MW^?}~C@yww%H-|Khu;zzLJ zSPu1GM;^&gn?_?xpk}&yXM520)cN7@o}4D*7eSuA>56y9U-8{P^IxgAvpq?6{O0qx zDb{608L({zv?uH;w$~3A0)DTn%#PSJ=KNM#i2gCS@JtQidTl~`Fx75 zPiA}PmD#!eXtkJvSbIO2AcC4`r%e z>PSk0f5!wu*Md$QZ zPs`lXv#Jc06FI6y76rk7{$ZvdFt)X1Z@&_?DY*{`CY#lUdx>uMl-nE=h?iR*kGNVJM^pP#)N%J6Q zlZr*gh^A*H6sg-G-`ZmO+C!IRT67Vz-QW8O&v%~wsY6q?X#r#i540YRvXRmP-t6>^ z-xzhbygYWQYuLZ}l~opA@jVTL`fChxV@tn{n*|+uT@KL>uSkqI9KNQAlF`V#;gif7 z2}b4bT*Q>((0ERtG2FQE>bh}BAC}atj5mL8zq;9w+TnY~>Fwya=;vd3>xhpPtKDh2 z^dfD!D9`I`xp7QwDXzar>qE=5{pdlZ5F>v%y&V@dkGWEQpkAjs3ai0Tq^*qM%^g9K zwpZ^cw$sGP++PlhZefsawWYN?m6q;SZk@qu1=nvqj0SD*-c|4}Wwvzm4kGN>e=SF~ zp6iPb>vR3B_QF0X?z%Io)leBbSUcho!hso-A1#tJ;~I zJ5jFw#yut7NwI2^+S72{GhVJdQxDZMzrzV$Q zHKdZlIlFUUn|M~b`hZ~}+uv4NNvxdUweWQgv>n}BxNpb&y z>ZGmQyDEK9nXO9Yj+WjbBz}`RTj{prI8>lxP3-7utAZ#VZ<1f$d?4)`C2p;2_tIKP zzO8k4&^y>5L_2*RtkSDzHSMg?OEAB6oHj0R)$#h~hmdx=zTaBv4g}t!`!{aw$kH_r zr&3=1^yO~Dx2&E>UT185`+=<8QtBNwKBUA}2H)PwJ4axXEZgYyU^cIBf%U=A<>69s zZ;!S}M(fGs4;q(k(s5_WJB?1OgtXl3$n*)l>1}bo{a9`d+p^WII#>Ja>e;V!(rZT9 zT9l+X<&%@u)&+b-sy*B|{#712TV`dbtg_Kq9oze<5B;osc#+>j&i^z6H?TgR|M^RN z%JF}!XA}rEf6_Yc+5g)yEo&qH&jts4&j0%*KI5VBos9RVH`g~)xoHY%kDxe-zJ72s zohNS$$DIzJPqm0s+L1*TaU@?@$u*R6V(q{A+rJp{Ti-Z1G`>6| z@2|Th8b}$;rtdqRaKk{DSz;%N@Pgd3OxyKRGfRD8$5HA#j!1GrS|bWPKMFOab9xSm(&WPBy&Y#VL+ycEkN7!~ATWRDvRv7z<9S4pt(#Ut*JdXuBk_VQV zctMmonH_{l?ryK=m@H9Ik8m?D3X?cX6Dy3uD2N>=5>^-_k!MG~7YbYCf#%rLcR(I9Gh@m{ODs<~Nth%~>;zu!WvS=KnQwW4-v6V`lcyD*GWUy51ly7ZPW9Gg>l10 zFolz+UXXa68Tbz9nLF*=#`QdoC$o}pnU!0KDKfCAE6m6avk1&*xw!-OMNJ^4K)Ftk zMrmr=PV5U)*kOtsX(n87h;S^^@*Fp` z12c%dz{~@Pnq~U7XUB=yQVFeXE9*!tA^=9iF39t1OxlA?Z=idtu*v95t*Uq z3J7>?JFb)4ZZ5nGm)i&DMDNH{a9V8Iene85`?(vYer7su;M+mw1#yrEeiWsqh)rL3 zZXS8iPQCz3qetk!pSSCR?d3zGKRrUkpgR(b?Z-G-BFc0_$av7y@oI}_#EEZ%ta)jsG7Oq(-OivP8 zFqgKKI2bcXQF|Rv3E?6&gEm-ax z>Kc_sIgDJK+wJD18WS$$F@b4@mI{Q(Aa7)GZ7&NjK2R`mnp**knPUgA`DqxKo)e%h z(}Jx@gV6WeMMYM0a=TcT^|+Y;MuKV&QxMBaV5DKH5`ZWxwcH>DA#KNw(4N?Fp-8RR zMXxbx0kDnP&d#!)O$+0L3Kqab=n#*IAd8&D4-)h&g}#bmfrSHP6D6({WFoXf--b30 zQXeQER;gXZ$f};xg0Kp+!Nz8>Z3CHQHo#XZ0L5S&p|bKkH(?`T8_-QF4sC$5#7QG? zc@%-$GSA)8r&<+|`OI}47vcc}9fWS|Iw8m+V8{So@HMt#C^s{=Lr5)Jf|4z~k!1lm zv)#OG8p>3pju*p1!C2D!UXr9a>=QZ{MHv_wx)^XXw!JjUOfvyV(IhMNU8tSRb6P8@ zPD8TPKp|r+0f~V9Vi$8o z3v7v>!=?yF#J=sb-S8a~U@1%hVNKTs!gWG3c0D(V?Z^_D2gdgU!qrYqWuD&t;c?Xi zsKe$E^vZzp0sz-2brM)7AblX00N^>okR(w6SrvVG&gU3<<*cPREk_r!!1sLtxB7&9n)4-3N?KRb;6MEM4 z6JWdyuoc)JfG-I!8qh8fSP_On3`1|*0W^)1KrQ$&loKEcpdo;Bvb~z`q1UFBA@ZUa z+7M$3lji#{ELH~X0z?rzWXGUEZ9fDDM^HSjpJpUeA)JL2WJ`p*y`pC#E>Ri0FfWE{ z1WliZyb#592E`oFiV>G^H2#NdMPQcD13pNB&$m}Y>wwGd#2zdmJ}x{$ z0T==6lG-pzENjYF?yeEhQ{RQ4kRqUIiR7 zprQ~kHgfI$8yuiN-fa4@L3=RXeizb z>_~to0C9l*FgV}=*MucaEE=@X6;R&}+yN^F4k&=~3kp(hqVftVgBOHx2Lgigl|uSM z@NZxe%5b2}QYSzUT+4R@F9LAN(3RMR;dan0Kt=oRYHHxg1oQ#|M2!}JS7ez0V}KDU zzzh7d0A5BQpoKi}q38KNG)%_JhcJdBv7D_v`c5X4@Ya7Na0Ydt2`r#k-%YbTv;hgA zi(KF+fHDsbEVK{I8QB8d0E0nbLk}K7GPi19Az6XQ^bp>1tpq^0SR2D!iyS8EC z*-STD<<6>^b*-GNpF-0H{;%&irvS-^_c3G+;lbKyg|p(9W(0Q>;wDJ-Sq0{b~o z&<+qe43TXC7o-8XaUm>JTmWDz69@>f#D?z`6@ zwd$Gx_8zF4z^Q}ec}{#!Jx67vz2pzzC_v0S_G8!{RF=bbSdI(L25bVL>w;zufIWN% zkP${B_dPVuwG-eIcdLM@D(j;L#tkS?127P}UIs`FjsbRv5}+tIhM2oq=!*zwAUyHGz)G(nf>i_NumP%ISy^erqXNc*j{t1s+rWt?2Fr~I^ki`w zK?Z%;d=oBR=x(d1$r*waDO?3Ra6m*jzwqV->VtD=!B9Z(eDWs~IEff2co2l};VfhD zppJv>HOU=i$^b|lQ2-5!9kv?3z&pSo#E@*PtQ8s>hh z6e}=X9VEOIz>CjdwBar=Z#h8rP)t6^W~Fc`9MdG@OCbcnix`Ru5Dcb2bTcp9R@EOK zm%X8|Kot3e-b34U$TzV<*mgLp0^H^Un1q%M#CJgYX_n~fBq_;a{ec^hbrQ~k}G~bSsi!I|G>bxjq_h^c!;0pe}0LNoZlYOiq?3% zWgf;zw%zH>#A}}Dkvrj7JkA|jU~p^b;T(-DKTkv=!p?9wG{%{DHJ;r}r=9)%{X0tj z?Qe~tIWUcVYY;fbZ-3j_9}heG58s$#{{j0_><`DC{m#Bx;z;W?iXXL9d7eL_C&$At zI{PnP3S*`1TgLln7jtJX&*dq zTl*#D58&xoE=HP8QVjg^W=7jLmJ3s8j!zR~j%!Q`{xdq6#)+ZA@^rhL1#GTHp!+lv zNSPDmOduEY1MTi1Cjj>iR2vh1>wW`TT5NeUdjRy1;+DPtrN{X0e>SqE#up@#%a<3;EEq-ei`~(Le6lvATSU zYyH+vQ@!-YXbta{R-XO1f|FR32C2A~iy5iZ*OT>2df}ZhTED!eLg}Q78(|#&Mt&K| zznjIVchJz;gI}62;(xvo4}J||f0M4;UZd?nR-^TtX(6A!pu1n5)u>9#tSOg;sXLvo zNHFM3FHPE$axeS7(IZ|ZHpk7$YF$#ePZa=1tpphNz@SUd#hRGy?fZW10zD{6t;;H@ zeRfU_q%!1h-j3#g_i0??j;v#n^AjVIEJ)N!K1Iv6i}q9V`5j%9++Er{T^qBq!|$LIc&9?pf8)JguVhxb-^W-m(ZFj|X1}%2&OQ{w zMS7i4k~XTCf@oCQfBc{SYk&nX8g!L6+?vayzNDbbr{(iylR*EnxBS98KIr>3@5yC! zD;ks)<$q0S1fGTUv!^6dGbP){L}0$(d4mM z$D_r9;*O=V!Of#To<4c}T-CCYRS-G3J-p2}2C7$MIvP~PFq&~je9rlEvQ)kN1~fGi z;<*^NRi4K;MpFFf>q@R~=*SgXj=9wwoL8TPW}m{ekib_mNy<0=?O!TlUwOZ}ZD-jr zO*u$y4|=~pnyj8KMLxNGqBfR%_l|GOXIpMPq9jMB?PfXjy~`uH#b@&|-p*maSenc& zpR7)p9!%*{dlW=E)L%!7o7GExqEbX5VZ6$mo>nGE0tHgkr*vu(5m020-uzR&nzGe( zLLb(C%bI&~DKl5pzq1LwdK-?P1JaDp3u?{tHR*XYqCdKh7gg2wG3^1PeJj#wq5PFV zYa$*JU#P(wJp}2qt8^dGmBOSr2rBw%q?#(0+Np7jL$ffO`s60JmAuXan{EjdQNcc*H@eL5XS?Y2GYl2N4SNekB9?nsr{W}EI#d1p6A%JE{~LW}Qrq$(v>94X5R z{wkhSja;N)w|fpXmxETztADFcRPW0b(e+;=z`GaZ6}_R-Zf3lxr7&Jek8KDKOsupl z(UB7h8yRYIW-tQ$3Ar87JZIiniK$%HFOQufCZWNCWE0Eq!PhH;wqKp1fkyI%e71Oo zdrUfV;$VIiz$B-QGbs00>m>j)+1aPEJmWP~0xS4p(_%7vvRTDt+JLxvxw9W9$x^&B zG$4O8ohPg|8RPZTgJdmDstjGKT&C?EPDhWJi`Jik)Zv3h!)SPQ+wnBV5G0)*=xLq=NpEu=1B(}w@MhU~GYxfR_y)ahci|(U=}?Tk%GF7;);%3ho8rj$ zrl->C{irLy2*X@`-{!);ALifrdaH*ITOHrD8`OKyd#evtsa*Z>@BinvqjMdsK%5mT zQa2;PBW)w0aVX+n0c8hTg)d+~yAIoz&o|$-V`3NKIVkh)xvpAAeBp=I{q(CBn8dpe zwl~+&k$LvQwnRB%+(SR-+yxU9{6YFW-S_>>T6Zgs+q50sGS2{_0xbFCKm21`8RW&e z;J@VAYU?lX$^7vj{!?_u+I|Or95T%gT%)68jU|mvWy2uNlMR)_(*!!7tq77^o;!=XeKC2i1TQ%E2F_GuS(amqe{#S8nI7<{9&Fxp1lfaN#s zfZL%@S^nh9?fNp@ve`A&OAJ&@?;7?hi!*5MpZUspXf%lAFIR0>%`ncp=SK|$<@Od0 z@c98p4+in?|1X0Udwy*w2fpZ@J?kF?TYxJLcwwliW3(yc4fpzb*Aa)*U7}cw{P4xF z1{)t+8EA5@TNBXwC0#3+HbyK$yklnhVm-XE5?f%=(W;JTFi z=DVmBsIFeXVC;ht3-$5Uo)H2MFaSe3vQ)t;1sX8nE%ZYXe7K_*6Mzzy3SGYJpKfBb z04Y6sYyz~qHtxD3?K!Ruu*CE5?yk2}2LaA^VS^?Fw!jM~4GL+w@VCvMyfgA$>DIY7qS#}R&GLw@x?%$JZdjh@;4U;`#Mdj zCNcsoLZefH3j)N-&6cP$x$_cEmaM*VJXD1~_AgYc0r#7gYF!DleRI9v0N7r?h>k_P z)f#$Zy<2@$Jp8DNx?#-W3ws*>oSD37=^L~Z4EW2_)wi7^xBBMk>f|D1H?{%)s1D=y z06xR4{KwTdKZ~fat>(Hl&?n@KM&s4U%$?%WMSz;iJHpGI=rW>blQvp4u|C2zXczw}ND0DB>OSgLA zdSvqU3)_!oH9{IwO2v^yK6>VU|BO?@e>*thdnEw&nDE3m9OMf%7mL0n3OzXGI1LsL zemX7=T~w8+>e}8NhaNUP3`EO6PfE`y5Z#`Zyd{k#4!?^@58nvt%mx{Wzyy5ro5xrC zB0FsZR1HUPEdvD}U0keA&ROa>YHVn?!S^rKc9onqAH?Zt-^qs?`{w9QeyuKNJBidlA4oe+cKL6PHzri0}KV7Jei4<)L3;zf?Ch@D)itnGTcFH?g4gScF zXRC{s7a<@m&KS7mr-pRNS(7Ugz6ujfRzV5zHj|Lv5q5Q1Sl;itKN!<*{)#h!Uix7; zm)}56<|cD;L7mcAiFcS=_;UZ^@|HO!hjWbY_Y-A3I}T&G>B*}QhfCGGEKd0`66TZ( z2ReX6fBCI=+HJ#zP*wLs^7JkOp1649?MbuhoY?83eego*ce+dOGEesSHo25`TJ&sm#6bc2ns!hrH!IFy~vz?akSkqnbb-Y~n>Q z$wQ;tr`xQw+bgsQd(;HvC>br#rQ3~mdO!=ea0A=Ijs8)C-21+H{-SLU?Q@GTbQN_! zui`w9Y|bZoi1YJkj4?M)G(pP1{Rw!nRt_7*rMcW{>c~fEmhMp9_U** zUR_0@T~tr=qCED44|La9C8W1%w;!+H-iaQII&YC4@r`+U3}^Hs#42###rhJ;XusM1 zxtOs3)Z&GwbCg_sa6$VYEHhscN1>76JjFdGZqRmHaqU;PkhI^H;~CL@H!ddYHif46 z#negec4wy!a=TEB0-TJRIc+Z&o-SDH)DE-f+Zg4+%94oh$I(X2-fy|Z4A}t8Vn_TL z-fWZT))5H)CvTBq?(QgI|59DI@8hR$;|oulfKbH6yRa?U4z3x+Dx~0Z!uQ&nB<^(= z>6~@Hbqewn59`%cn~%Gy@;E5F-{#4K#tEx&9&L2i@bl!OJmM zf39c#GVPh)4PGX+dC&y{?~S2O|JdZI`G-Pm;z6(A?#(H?_wI*;|G#{GqqeqV$a4if zL)c(K5^iKSzU&P<-vUJ7Q zAH>%mG~L~6T77&Va81wsgWvbpTQOewQyPdFZ~Po9M;J-4L0jl60hO zSFT-3=0tzqq*NTFQ8uxbF?{vp;_vt2vD} zIJGv&mkf@~hpfwcOPFgI*SahDvH>zp1YyA>_Lg>(bvUqjO|IPsOQ~FZ?qn_rt<9cl zM-tQ{Y`6LDZX|Wd^0>ed-~`hO%zF2mE6N5R2yKlbIn*VW?H_mzYc&h7B7Qnsg_BN$ zlL$XNJp?~7vBeJ`yA3n;6Z~R|6Z)S<55tP^K{`Z-Bxz8^`TEQ4@Ax4(JLutD05zON zoYwwpfFlNgZ90~|=h4GW#_Aobvvp?Msj-KWvmxIc zH2SoUb~h&O&*Gck>Ture%H9!bKVq@()CMhm4pz7QVf@&Kb50K58h8=kj@#^(qJd1y zX|FTshwl&aMrSk2hN*^quEoFm535-KG28*7p`BpO=Y%rg6 zG>Q$x$4}1yc0h^0)zzET$;=LC^26fvP6rsP8`pRl$Ln-1nqb|d72!_EWekT~n5EBS z2^SGqzy|;XCc{~^S3C^9RJ{h8nhqaO;ta&r_ zc_29*(YXi@b{stY{psltYJx`1Wt+`FZvub^hzz-E&D6rBf#U?w^E-xhxFDkKerq%y+$CRdROvQHk`{6vy8+e=MNoz5eFu`y(e`b&{U@#hbH@g+n z{uC|y!9))zKKgZ*=)KQ<*wB>hGmjinJ{%CgMa1u-Jl{Xc$NDkUCTV||8SeoBN53`- z_R~$gW(DlO-`?!@-QH9iD{6NM_x%Bb!5K3iEr``zLThX8PF`<7SROlVyr8q7rZ3%= z;V2bM4ADq?xGh$OC0vTTRIataVYpv~RzgJSAg8Uv9k(NdBNE%Xys9Q8Kb*wbY-ucm zrf7c;ilUEohQ(`7GY-BEVQ7Yh`tJtkx4s{K9a^O46kKz6soi#N6)}q@48<1y;%-zm z+eYWL4FzH5$)~5y?1yk{xEiyut1f`D9KGranoomE-493RUP+VInLgqSaNqDCVkML6 z&lRzX2Y=_oRFSTsoYG&$v!yZTxvitbiViV}wGH-z$6|=1yK1Us0Jap8U)z`4B-mgM zn-Br_QMxF}=GB$k?p~~~AJRtPxAu12rUq0K@#V7Y;#t*DpNY}tMytEm*XnB5rN_o& zK|pGn4)DXs-0$6Q^AC3CXqY!RwbA9+C`B}++r~;dA#Bk?y)}~-SU8Hpqb^u9C!T@} zcziW;a4FW7if0VMHBy{Ks0+1q{TU?2$eD|ZrrX^#s<}wHt_aj|XSF9Mvq#UZgW;gQ zjVShG=00*kKKVWL+wiZ})u65DN{a;3(i~b1$5naMGk)lks9?dq=4q4@{iZo*qJGhQ z(Cvp8zu-}jfaGG@RFj$+^A=tN75QStdO6Rx5Qgp?Z0PER>oevqHk_Su z3eWv6Snrri+la&FYKA~paN4?KL9y4T@fSL`;e|JG!s{2EA?j0wdvZ2O!r_JZlz#K9 z;hFxZbVJ>L^^4f$Gj4+P-S+2hf88W&c6o5|cuM#>4lhJ@IP~zL`7Ufy-h^-Cwq@Ve z&1v(@rFxA=UWSMGdGyTiub1r`>)|WwB=Pi$Mjt;7vW_rx2?Tp90PgpMHM> zI~C6H2fcIBVY+6_Nym@edKj4B$vODAJ@YIKbigu$#LD zZ~gJ_|Ia>K?YR2@KwJ$nB%4f$Cq_wkG9{vKj*;(7xJ?p)J_Z zGH_nt)jIEj42N*g6G_oCcQwADZuO7*7pfhEMI+p=MbF+GCiY@3c7sH98O#I&1y) z=DQ)*V^e*^uK9&YiTt5)8=G%Kx*@-g8HvN5Svj@uy8CO`cl%}A1+&pYA5DFrKQy+P z-|<899ZREz@A#obmsd7AI#+fw{bm~PV$mA6cF}4N!kW#GeSZfKeF2~E``Sr&b6MXZ zY1Hk*^6bYuG!Z=Dn28VtDXjkB0fy@v;Bzu$rokiO6j_`EhtW`M!0v-*uh{R9oGl}Cr0WJgV1@3xn1nU`wnwE6G+y<;HECJXS7Lrv z^KBq|BwhEwcgd(PwjTh7W&~ z`l;9E{YlJd=y;6RWM}|KyI2Qy389#h%AkCpGistb5JLPjQmk`k7zt-Fl{4o=08=0R)=;vgF6uTE9 zs_6clOm8sQQ8;%n*1n?Fmi{C{2gTfO zKYn$&-PdUMi@;KmPmwTO7<>`PpaNqniyJhgxafvg=N|hQ}+?_ZxYy!`zO2Q*ROUN3 zf0g3kr{lDkDs^hKJ0ksW*!1wo>YwR0#aoW7wi@n9Q$BLnG0CTX-Q@-TrpwYD)aY4V zhgo*{vt6Pf^kKL(@p^r+*@vV&8t5L=4Gh&T9uyze$c)K{(YOb7xK&p>jy0CjjFtIf zK_Q0vL)5NGhHY-D=gWKc8H#L&{A!)&Di*uhqSf z+L35>s)I+#Pp(=h_I_;PH&^TZ2(|*1{QLj=s>t)Sh~8ZS=1+bQ2lK*kT6P&L&x4lL@i18dg~UPsB!wu z{A|?VR*k<1*J>=yscpBp6BJK|Q%YenWan@z3oovVErwHEb`yrnpZdhC2!efkjBSt! z6iiV!&emgY(sN>-S3K_jFaN3=j^ZEuc0JsH;nTlspBMAbw;z7jACsYb=>p#{=W#R| zaLwy3$?(7a=LL$gz1O?uf+&80KR}$%R&2F9EwZ_??IsLMY5bNHpPPC_H0`Y0(9Olg z|Hz!Y*KO`bJHs&iIDl?Ojpd8Lc(#u=zi-$@Nb0*7Hy#>jg91#>YcA8{6S99o^&fQ` zL6|(9-uiTt$Jaib4VJex@T?@cdNj#rAU1!FGK&)i7Y+eNyeFAf|aeq)V7;&l}hM8{MatNbLsl=>7co_n8&6IzJCQ zruM%E-S7v4I8p3xu2=>QIuk;Tla> zs2lX~`N`kYb(*fy+qCf(Yt@7??^v?S5JPOv(8l|zLKS6vm>h&&UcQOK2rJgE*JzpA z6&kF=^~!=Aul(wj>e8LMMVaGY+w(6!wRe>H;UB{l10cE3?82^I;otjFFWG?K?BKJW z@5B!O82z%Jta0o$_BmYZrM~8S=!y3d1G!MESB`XgW!g52@i?0n)vysaB1}WowsPbv zGcZH#m%$V_e;mUDkhO~gqw(hQa`kE?wZm@PlnFxAm07(4sN9a^H_XXQU%Qxou^n(y z%R?jf>7Mk{FD5*~rBZ{{I^c}a3XK|?eleBznbr?@;q6-wML_p~bn1{D_QOUm=46Af z2f=IJEf?gfS3Dd4c)JaD8d5ZxPBpeJolqRG-juTe()Zoy>lvLQlHj~{#-&X{8sr@v zsH7(KXvmJumeE8hwRd;-YAN>8)L@?E7|nJz-uD}J*&a}t^w~sgrd@U$lcR0j*)HS$ z8C3adH!_?2a5XU-VFenZ4X;{4PF@F2t z!Rjlg!r8)b-2qhWRopo;;HbET(BFo-va#E*FD^nP z1+a@@9aefW7dN5HsE@+Q&Hmu^c{{IGM4tr_eHJJ%9{sAlh<Q?!Mzw>Pnb=u+HhACPa{ zwZ5xs*rjuh_+7dV>4ej+qfKPWVE319|B7Zf&b2%1)*7nt?Qh#V+XmmWo8R_#xdmS| z$mVgkDxTgdA59SY)oS^&yM=Ir7;yZ_flN$p|6u*Z)32oPGU{gX)UB zzZ(Aajsxr(o0S4Ll7j2@ua2>YrKzSrv@K5Y%(zAU6>h6}Pn@bm7VZlh^$3+gu8*0J3#Aj=J#qe-Var@ zH1tr`d-jRP$HTEt?HG^<`6aP|d(#Hp>UT2@hWd!(2G3bN_qJAYi_$SFfWu1-}RT}Y~o%a*ggo-`>P>OkM|SX8g6(`#k>8++l}YkMFyx4WvpW!n+)TM zOcQ%Qo!t~{c2}mGf{$N+^VwjJ?orrCAM6Y+|9;%|pwKq;RiT%*2XASAxJM}dY{x82s@NA3Oe%!23@%Yy(PV|k9|GTyVcfJV5|v)lKBT4w3yP<`XQ z`wildh-v5aEIOmVz_RPuT4K{X?EHpH1DV{i(8P1pMli0)O z+!Z<-jJ->1n!fU6yKlzvQGmIz9d59kG#6hCI&LoNJnZ<<_4Ud0yAQun+mld7Z1$IA z(DuwcuFslj9=;xb9n7t@=%<6yq+zXl2^lQ&*~$$*ukGviSHB8Nk1noWp7D=n`PFU* zo_gkf{}(6b8Q#ICX06!*CYFrW7f5J^G_wT$A7k4onr)Y%TDf=vn+zG!N zJo?d-m~|Sn<;gMe{~pAMpV(r(M&>O-d;SQv{iJzhk!{1;Z5!quEFHd@u3K~T z;q4arW9P32Zl8rkB#dd z7kxUH*z2)R2M2%pc=&Su`B(et!+}5NpVdb_dn-SW=!$<2X>-hrksAE>l&S-U3J7R~sr%^a`ibaL)!+4qHReJ{0(+Q${0Z zj$Kb?uzEmc7&{Ihr``R~5#ahpH$(`q?Zh)1=l#{Uzxo9{zo)QM(PNC1nEd9t-vUW~ zHNtNU5PuM?{dqhT1DUy0-??W^x=-v0>tUV&AfGh-jEu9pvkfP-|dhHx%6T3y7?4NmKl`$qx6mzN>%8C+(= z&A>|+F7U<3c9UmbUN%4W1!v}d_rp1XAolY;+iAvA0sBB`m{YpKQ0xzTWir?xFLhk3L8?3Od{oAN#1um0k>x4Ielz zLY6qGT;=N{BV?lvMj^7|pGb)8lfXz#BrN2-uNe(v?{Pb~sW$zQ9PO#Duim@=w+G4I z=goZoHr}q=B&9>>?Db~N6F3Yut$EDo(%ChG_xu<#*x$R~*U=6E+|{F?v|`8$uU)Hs zIF-{>!N!*wGx|l$Ti;x`HiG4EupCX$WX;PO*8AqJU&hA5E^im%YBNJ(q$_OFwv}x+ z`eOaOrT1~MuSV{s!LR62x6txx3M6TdD5TD|`yOgSSA~ zwn_l4>PVIU1gm}${rO84f9?-M1)n()VJUcyIa55Js)-eq_Mni8$09I#?Zv3uoB)Xlqk%Hk% zjMc*51DC@Nzfz~SP==4=A+>$}uFJ$xcAy9CpySga)ES_K-i>M@Ls(nC6c@EkTd(}_ zjfD}|Fzp%Y{90X}T;SIW9qGddb-*>Z(1wJ9yS5`!=h2 zNT;_I-65IYj^=hDqF@8P?Nm0d-0SFwafdIC$c{AOtv&MXK=0Wu;}Yw)X(`5o!n(~Y zGN{t7aa`cr7I#3xe?kj8tCJsprd~HQ>lO3Qu;9xL9WMXf%Q~;FU!LH-3(WkLqpac| zGhU_JXXE1XySLB_3&T`lm}=Y*(~*}N(xEL3_aN*OU`hAtov@?_BYFf&NS&VrmZ)V| zqVIww98@6MS4}SbT^y}vj8xailQ)-_Y#;3$MeMmYzGiCuiNUWI_-8xip4(cb-Qs)4 zFS?2Rww)UYP3SurS~b}J_o&Y)4%U0QX) zWZp7kzVUm!A>%6x)4o+3|Ndvxh_}(s#$g|;L}ry}x5FVPO0!#l#;P4h|K6${Nq)TW z->82J^*?lbb+T`i%}*%kWcz1_E9H*{4|)NEH~TYh2gCP=TJf#1c1N;LKryqi8^!>F zGWrShMR%jmLgEJO;o9#z;v~@y-I=s;HPl<`xqAY5RVD=9>EFi#-e&Fvb39#Gt>UKIXLw;F8u+!+~(3ho7>R*lR5aE*d93e z1Ib+gPj3+zx<&Kw!OJ7`d{d&Q8G8Ho)nJeW+2n46t|w+}#vg8hrp z=kC|zLeEZTD$9*MGW6WHK8!o3|5W16zizfS?hdQQ!UE%%YV-{z-b-*1q94=vDR=MB zH-7ZMfjD5$zv>v~l^?5!iviak#uEQ(IrV1U40c9(CVJypqc^%i><&kzeyr&2`h*Llwgkqn-lpnhy4QtafkfZDBNVkG*+HoCd>rIId{7{z(k0 z_q!pte>*(M_Q5Lo+pvqKxS!#+YR8R@U#$LC48D#xZ8sUp+jvm!ylL&D@X&g*zOv`yH4S*@?!?{A>|_HWKRp=wosCsu>8#=j2&0prw< zMJYRJbo^PX!v_L4#npIds{2Pm*bFcd{(@@zY^JG33eTp3`Mb6;Gy^I8-R#RllYMp| zk}!RjyVEIKHL0q23F7)MdubgHH@-X9XD6>`hu*b5=xw-EvFX8DMYlSR;*JN^NPJG_ z<@)T<`!x`V(?gsb>PLOhEc%eszmJ(u=w3wfw@z6b zP#0$h&gTCrCL3xJCG(-c;EK#7znPo;#`}pyo#yMmt7&}}1kv4YL1Rk?#xo9V(DW*j z+MPwx&-zhOL$8|&o(?W`|KT?CyFAXJiJf)wh7#M+c#xjgPK37i?9OM@aL9`m_+TLM z_v446ZW~G?lqjQoL`z=kxjBe*~8|aAjsr*QW;@x77RXqkCtT z|I?0b1|>af&TbB@NV`uOc^w~)V|51fduAV|#0FKpe|>iFTR8H-0H#_G#bNyWEmk$g znR{b8noN8oG`&QCup!Yqhn>Y-Cc)eQ2gAB!NO9L=dcLrUd3NI%>{)LIXG&wplxiu2 zQ=yiQR6&D1?Zb5$9OGG7pKt?szedxbW*gewg}82G6yvqw17DyyJ2G}EM+RLCMiauq zp^32xZ;gIWuzrylDxR_6lNBE%chAxLCkwMhWjq@O8z}2r!erYPT}*@N&qjgro(65S ze7@18;Ms&8gQgCW;U~W@2G5?&N2zXW>GqzM!eKvOM?X4D9%I4Ff%3uc$A!vMuS~66 zd1R=3*#0P3F8_%H%fF5X1@4ZOH+SDoqUEFL^&nu5&mT1xK_4Z+7efIaZ^TXIb9%1* z?tu8!OfYo)_wk6p^$Emm%@ z1Y_fNF=yD8cSnA4F!=7r(9A8<9mk#+Af}dXRT84VF8*$W7lFmkQHRYwTU}0fj?@!Mr;szY~W`7I;179re zIxrLY&HgwVPSS*XKYt{5q2S3+Vl!?n&JqeW++|blF7L8lssOQQXr2vPj%8im!m@-7 zww*KMV9N|)8|FW~^=Cal%phOST37kj_ixj()je3xw^T0YkK{vCDmJ~)LZHE77BHlezQt!NWevP zGb6IEM|%ZRGEHeaPug+V?-tTtzaJ@ZNYhBb>w!k<)%&8h9})9)n}{=>K{LzUt%~*% z@_IL(9V^#&L9o$s=^kf1n@6>3j0W0((+FF%0fXt@lN#@`&Zx}8t<`z!^D|LpVa|(G zX>9%oceg`3%#pZ@Q+%JC6RRJD{eh7E z*OqW-t|4sh@rwmWW8^#*CS9{0!m!YCH{G*PU6k`>Nzv7-H7_7U&*tb-387kcAEk7# zsBNjcR_8q8mK1-U>~)RGU2WB?uKZT$ zmbIxz^#?VNkqGX1+*Hp3+dKh$$@ui6NG# zAzE^XDLn)UB9hw2!0GrWa4(;U9Lax09^=0v*L1L;We5H%E-)L8OU8f2Mc}_8S^2L>DE=!>ox_Ne zd3rjdv|2qfR9sXcQ{6SxGjmETl>;p{)lg%FhDYZ{(iBDQt0{)6z>{LCd-eR7a&jun zVEo)*rlV(Lg}^&njQ|+EPpdW#D-p(Cn~H;zT8^UKhd$wzr;EKc4Ss}YM$IwnVKZs; zU|XII!3mv9+8q*h5M+4wYLzoFguAO(zP^LX{e!!MC)K(c3fthVR`TaR+-S_m@2la`M9oHZTFdkX@=N{SP#i3>0a;$IBfD1+N z*GI_jAbIa@1vm&0{z_q zI^hT=oF?TTp#~0&`=r|YyD9Z!*MDj4=g+Ynp*!YF<=)P$2l{62ox_oJ33hXOW75Sz zo!!oK|Hxt8r3H_h$}p#TI-C5T-E0Oq*mvuTab?SqzW6$n(En4wf?*xXSp{(LAO(C* zx(}ZW0(6Aryvw56pKDPk@4Pw?>q)JP*_RGj?)H}sC^uK#@d#PJIH1Z=7V|g&^HUJ> zV0_0AbN*(EJ6@VE8Gif(*yDx)?S>Fr8p$ZyRgi~J3;bS2lvDL z3{o3kI=F6VQjzK|N-h*hyxV+?D-e#%2iyG9n2%Atz-0jW>KGy&Hrmt=JOWD|timzc z=m0L?zI5@W1JrulRHkJNk1&gerstUP9We26;~P{r{Mii6yQ!+9CUmEMJB|u7)enC* zb^lMF8i%C_k5KXlhWDK$@h4N)hqIcL_?u3t{Aujgak%ktbgZTqFyFzzsw2Wx#|-Q( zk8c^voIB{%X12!aiv(q5G-A+!NB> zbrn$G;gPq^buZjp?UZ-V{KYLJ?dEqLvk2OY!3OWnnfiB~L%d1vXPWQPH|%w9aE|+f zcV>t)zEm)bEcO;#I0CgCO(Nc^ae25~vG6pnrZw*9$KRT!++jPq^|xcVCIN*t#o8&i zlL^CYy1s=IXMof{4Kl~OVUK@&ef1Vpe(N>lZ8S%>{@qWx*aKf^bO-C)ns+p7sS)Pc zjQzV?`5=p%hfNQIgrr%0|IT@U;cV%0B4GdXahZTcQWaUAB}Zlg4w@gHyv>q7Zz|ws z>$>c}uVY?cxEm>6)_t>U>hgt}T^nO=w&95Ms0vuP0sQs##oDa*@7>oI8}r@6xWoUD zxpw>Q4OPLaKVQ94O{4Bo@zU9Y!xFTZLcwO)&3SpGx}XxWUET5yO0wYZUa%TQ42`y&-xh5d z^tyjN{5`f1dk&sX7a)9p;L}8BB`CtCD&wF8LDCf*h-WtVVS1#CNxBDD+%A?eczqUA zxtmf3ug8rsEl!14ryexf^rBYxd48aO+Wmg+;ilRo+)q8IGufQzUHvdR5JFOa4I<4R zhyMEbGtYM)I!n$DehG;O&qim;IDZk(Hw-t&Zaep-_IJ$zV5p_f*LOsVm(II&6CBNY z-O~4UL*L2Kwpc|c7Q;K>o2GD&iUo<{fu^=H(XYnLc``W@G|Dp!7s{QDEQ>TDYf-?6z+DQ)C++}d>e$9JO&*teZ34+rKJ&gK7VdL;i> z|Ex~qk0>;p=i8sXAC`&jPQ*pCs)xrK?_{81zTx1H>7-{e0momx*|lflh7;rJalzhV z=?_bn92|lD@k(g1YRT)lswKDS@PlhJ21AG~ec%6f>p%_%^QJv8c-sKp9M-~Fjfw@2 z>3U36m0{WQ!8-KkWk)=94dpjEAA54Z9^><{P1|7{ftL=;M`FGM6)?{S{i*R^{WJ&0 zZ%Y!M=a<>?ZFBWmqu`HtK^)s9|2HVy`WkEaX53Ws`{2O)K-%WIcyl%;b5|Q=d}_Vn zrXgp|v&_xas07GSI{T+xyEn%i_Me~gaQH)m{bsj>HO5EYZ&ScC=gJq9@Da*&{Oxeq zouZv++QXCTZy5yo+U@qcK@bK{Hu0Z@Uycj?c$NBEIyoEqS!#JyZ!Q0GMSTWmKhfsR zZvM9~o3oOO2S*<@*QfUngsadWle4b3?(ml&+K{odCEt=+Y;jMG`dcWln{RiLum^4`}UTKyl?4gcf-)-djH!%v=e?LyGKHN!oPlV zwca0c=Sj!$r#+80D|A9yhL-;F+oz}Jvh4>Xy|{t?JXxc;z}}}bef7;XzkvEHG59-f z=f+-|uVQ`E)%tw0#Dg!oWrUu-*trno`KcTI)jzSX%k_?N z`)&xF&DH8E?8-9s74~Fd`7z_>jfKgn!Eh!Mf@b&Y*Q=H*gtZ z;jW&y^K2gG$qL-$1IGXWx&p=hg}Z z5YDKwX%ILzwPbk_dQ?5fe)CAzkfTO?$c45U)@}|<6Db^{C1vN zgJ!@Kz-2!Sx{CVCKEWX3`Zp*j;*y5@+7TR@Ryfhy&Gly2s;fAVlW!QgKKFpF7Z;zb zPGYzC&y6vw^S=vMTH??Ccl}arVXN9tf>%HOFt9b>HtpU6L#}}pod=oiu-?`qdArkAC?g2a^cH$nW?Rx)a`l4j~_3)*?dB8pO>BA=@ z!E0wHPls(NrVKq;Up=6q*fn#bh>o?=Nzg*);b~}VD(Z9Y<&P-EFOFzxUge+vm;YyM z;lKQU2aSTw_JFNFrq!m2QL_!VKZpwL0UtfG)rN;7^B&M3$nt}JWBlF>RGkA9hcY#% zPNw}}JQM-uSNy1s20EtiqA}DDhPdHfJ82#IJ9QxxQa=KF!+ZjkAo^2|VHO26)^O&B z9}bzSwTKUPtuj4&&<9$$>oi!$4#PvM5oUfdfzUyb$NU8wdVKuF`NlUObmG0Y&y64_ zkcVjjXZrvhh)?nTWBYpbx8|7&UVn$mPSC{-e9KR^+s$@$Z%}xtMS7iGe|dQ@rjyB_ z_M7XFi%p*p}zZ-wUmugkR6EuRnHl zAp(V?hqcO9>1or}g9oce4Kjb=ICCaN#WH5R)6}VOX#c7~A`fmTWGh4N{LZ;+I7VGF zJIA7>P2!W%7k#!B*C?c4F;dEmELupk8YCmWzlKj6CP}*ATZafE@W|>9e;9tR-Chm! z+~n8EkLd8KUD?PFF)SE!{umAX5p1@~lO!2%)+}!|+fn^yz}qlb<4E;uvdCq}@LAK^ z(JXc>lg$kD{nhs{HO+fngLn%7@@ju^#dp4Z^yEp`=liRuDjp7nK|SBPxR9+XzDrx4 zG^&=K)PRG!$YuN0X{X$;-1DfT4pn3mUkQD73jKt`J&SSKQ}T4zfF0?bw^OhuQ>EUt zKT=z95yA@3QF25_tn%+-4&l9H)llmgdTSFDnVQQDv)j;8EM zPuk8~%8S!OG7oHLPwYifM?znR89!)d9G$KOvfn}U1ClGo03L8&O)oQay*G<3I>pd( zA(UxscK4(U!=Hbj{BT?(za>mth;yJumoz{h><{^|YWt?2mwRpK58Bo4&DCDLe*Zw# zG)nR0?e-f^&)2)pW6=xwA2Aq56|p3d}<07n`q#`M`^b#W?yT6J$UWqi#4e;a*>d_X06@)3+0N1tFaL^fUncxN+6)k(&@R~Z$?H(H0h7MXAcK$moz)#QzHB+u zD)|ZezVm-DA!@r?{VBTor})3`-&+C4y#C6)TnGK~{_0-p%DgI6sjN;+;ZtK%@AE3p ztg2F3CPG$~Gj($BjPEj^;9~f?(wTH+?WD?_EJUtSqYCHiDz&*td|GBnUaGW;udiQ! zN&b8CLcxCW^{Ob+Os2}GveKEWDqTD6omIZdyhw#lol!~UGhG=~C0UuO(yQE2o{OgvD+`;;w7_S~B-hp_X;Gr@!>$G!^AA6~Szq*v2hnZD7CX$YS9MZgv9OAz%E1z8p`@&tu-;&{tE|z3VA0MUmx+Dxm}*hy}Eb$W2*F&&5}HYD{7z z{;m?p8aP1}r528=EP)0pmU{~4HU|Ab52_^hpqEKhB2<|`2^x>}t4j7?NKmuZt^gxI zu#-Y~R~8054=NmJhDkr4{J!g{gciiIODu9B6DKiNs63S^S-J#VmFG6ggvou98;1^M zEemKUUliIITbbpazG%;z?YhotQ)-=oEEps7gH}pl<*g~L)ygD^6jfHL#7iwrQcEB| zuTyIw0G0G6&6Yd+as$_*R}ZSxpu2Eb+`7OzIgl=gIx5TDL&;eOg_HQaD8VnaD(WmL zOXroUAk(?OZC33*P^Vn8+~%3W@P$aM&U0T2=d=>Q6t;xsEscea1Dk;jb&+cDH%RK8 z7YakVZA#nCbx7N5yE2&t2OGSXWR)+pugfYEHbbkv$|a^)Ry8<9_`<>BWtoRe!;V2$ zz=~w)w5!$`c^D5M126x|U2)C&*=0gv+|U3z$3M_Lbzw7CN@%%4hyq#P(|g|$rQ>5HZYYI3{wgT z+#(c|ht9$7z!jK`gl5kU)KlBfXYe-$q9qD~18MQHgFZJ}LFIuU%G5*~KNn~gohz8~gTmY6Y z>m*efUV^3qDp=~|3m+V?&g8nR$O^21s%>7_)VNYXY%Fk(Eul10Q%Kl7;4~Ut2m@@I zsdJ}c!Jx|yv|q?*eAw&+4vZnjT!OFAPL==^RJl@4dT1yhEZ9Mxc?oX;L%@`^0UGqc zP|jpfBbfko=ll66-bdbRh=hhPs{kP(yP3*t2D#Bb_W&t*0&NXk=QONt4mAO2=4ydi zyG$!^TzarFv6oM-UakT3E{6=Af+(=qz|OJ)^8giB5=b&h9gwtCf|<5Tm=qIKDe$ZW zfRRSzx(0L9dVy}AyxzO3k-Zf*kx(tb55Ynt2^P05V0ewSFie;SRBM)%WnC$kVS=TA zwRb87elgk~Si#s&m-5=sS9UxTH<2TFK=lez?*@(c!KZPu6on)diFS zpbcP*7Lc*UuD*WZHrqE3KiUlSjsoinOhF`6sukqJ!46S7)E3$sEDX9?cs@b{o?9%W zKv%Gr(60FNuFgJoTZXqkxx5|#^HOGHbXmY0Neg6#831#ZAS~=`UKT(^P^Lh+n0amS zptl%g3G=C;i{+7>{%WhPU-WeK#;GEOQ~^I@N|l$nt}JFPiJ}a|8MXtKv4+V{s~lcQ z1{s0$rPjf3Sm6AFUcb0>&wFjCz+@VB7TT%s4yN9KfqV^G0;3tu9P=&7vNitFFwFu2 z4e<~aCH(+PFLe5)TK537hU*8Yk;22N6x`$#D$v0c0tLX`${~MPL14HVa!^+`u}YNi zUct>ksp1epE%iB2DnS1ttzawb3RW3{A4DN7at|12N-6`uCaTcdK%>H%!4})3)G2gZ zaV%+{xa+P<_`)))sFy@(JzPCF1qBT>F+QwlMik`WeAm9Hawt-pDJsIrO2aHW4+4XWGPqh84V+>)&G0=OhpFecZh^zAHQ`M7au!V?t$H|9l)7QOrdpJ zV*CJ4wWgL4CA>4?g)3p#C>Ny^kUddQ^C_r9z;3)T?di$hKKxMa)~1Jsq(xf6DJT=P z2ar(!VH%$%u>7z&Kxt?-En(GiAXG>lCY8W1#}a~L4j@}R$`W1VQOLx?`OaaMCD<4o z-~n#o(ku9`zzQPI6O%G_l|!xCB!vT>r-_7GNh$V19U!X7nVH@exB^BlgViiDaJtK6 zN~f-d^yUd{n554IFa@}n(2iPiyer^u50(g*U4>thr z8y6G8j3aa~fg08x z$Pic>C`U@74xsoV%?tR&AT9hmnDFwzw#A-iTvnrKvT|TuSQG~j3(h@}j7$Ls9mttL z3Oxu0JX}{mr%?TpCO5AE;M@Y?n!wMfCnxJvL91!ua?lU;;nOf$89$`20{K`@(T|d11MMUA&LqR9I6&PdUU^Ey6t7pEj3Jd%@98H18iIARRuH&cd5oKYXkQd zm<_l97{ACMCQ!*G93^;z@N3Hhzv9+jfBR{#93jG~fUgO7Cg8OuwyxnO$+R-S-U8Uh z*wVsSr4~LE=Bwcth$1N&|8R$xb+O+;pMc;1anMuHTGE9OJb-^)0BBhWsF+JD!Lqi3 zL4}I*)>bfIDKt>3L4mt@=^(IDz^KD^z%fc`)xB0(S^-iiPh%!ai7vsl5N)5rUo6wC z0-A*|RcR_seyCrTdYnj&l$uUPmP6(NMU&KE0TZ|Ym>7IIsO-chgj$8mvCKL2C?mu+ z0Wb$NU!v|fV48#ZQ>6>9O31wSuEy{o>R_b|!XXS)G0Db|1#cbAfn@=j;Sw-%yg0dE zui=xbi$MevUP=n+W#I&>QuzcvB1{p)FK75PhiZeULP^4O%gb3sVDp zLJfl%WSt0#XDVUg1n^F!v?@SEXcU|TD&W@84_5##0Mc-x4ZN%@D^*66 z0k-9iOi|QyMx4|>11f<%&ESZ+G+nZsO<%Cm%$x|RC>^BIFun$;rG%=N=p>f_WxCe2 zEp<{=wbeP+2O{P?fI(e3Yf=rR0>46+YKgU*9;c=hu%iI9AVUfCMn@W$*SXq2WVOyR zWs9sXxZ?m18~s8TC=a)%V!6e2dFWJX9JhKFo`b(=m}3s=p61W zm>-4|Y?>ILtpfTN<_10t6o`d`kN$7(l|nq3W?GX8dC0v?YOR3;Dqy>;B7_6@s8S=L zsQ~8l)Mx++C}aR2Eise=&c_|oe6r^WhTf!P@RkejGvKNW&M^cP-vGV=_d-fixDBu| z0OqNwVbG*8bZsi5p(2&7m&C2<44&)nZ(RJN?~(yC3m?`d0-m=ixZ`5;k~X8RGxP`F z1(uFP$bdLY#mHKPH(+Vg!yW9V%WuZY-5dBRuoo$}sEQhVC!oEo(NGvdDpSITbg+;q zv<={%hAUIUEv0TrxepP5uO+NTju$g%9&4ZlQ)tArWQ@MbWD;Nov_G&m^n9r? zT|j=0Llkbj$;*E=d)H4k+wGf!4S68q%4Q`DT?#Y}iv_F;w8OorObe(GELaWQQupy1VEFLN>HQe!}6l0$LGyvh@3Z?HlJC~PHEhGcjih|zngU=B+`{Fr7L zd=}sWO!C%VCOQ$S-2w0!D~dc98H~FJ16Zdj0Vc+Gbz4g_$b#Ylxzxcm_kfINpL&BEub$X6|;snP`JX_I<2athFOH} zRTC`{yLk=Aa?Kg3i-%7}-b(^QpBK=*7W`~dPz(CWaaYYk3+Wm-QveL7Lg}ig7`kOd zTneRNQhn`?>FlEmwcCy30V&YBOX-gRV}eaeuss7zqA>6_6A}QBDX|P^<|*)Rp63M| z95|Z9$L5%BKLv1#nGQp?w6#hcq*7`lfa~E7<^~3bAzJCn0xC=jxM|cXc>%4MYB)Gr zfisyTGKpX=^c?W^+I+=hXuZb^c>)1Vl7p5>oiZ|H3>{qwt`*>x#KB&}e8Sss4D2%A z11Gx%7J_)@$MoEx;g8gnWhvHyfu$VOH4He!p+fsP`UOu(C>oytGBO5dDux4LBN)+! zR|Q|Q3gI6x^)dZ_zS&+fl{3)%Q?6$X%M-M}~jL7->M(ZB#@5{ee8r&1Pp-DiN- z@N?>p%pbS zL0WllD>>bMyQ9;u-19Xs&UTnhmLz3Wf~%_v`nAX{H?U#10B*DgO966}3{QB@+CzWA zYc6Z;QVVy_=SLCxD+l&oPja!0l{xq*gKTNo-73o+Y>I)lfW`;FPb5G`qQPzo$~1%Q zd1DoTc;TUR@}t=55X(V<00etbTETUM$;rt%d9Hy6iY&1uKz|0MDFf2VBm`UMi7_Q! zVVwG|UU`<}*PG{G4RAz2`CEK1#p#xdkB|JIoMf~B_1wK*fPikkQp-~xG5yd(n}7@*K?+Q zX!)=z23{bVu*^9W0*X-s{g#jkIDs&wHGoi3Nai7BIW$pKV&)aRffCc3;nz<$+fS5v z!Ct=UwLZN6qIBT1s)8G>3F`rYGj5g9f>+Gq15Ad4s|_F$+&2khuQQNMPd5u~-Ad=GFC{T-Tagoi?tnY`FSa=)* zh6B!80<__q@7Zk9op(P1nS=TcQk4YvjUTE>*&kd${T9lwdS(GRBQ z928is0RBtGM41v^8RUl1utYI?kg0r`t%1cYgODjaM!09DV5hR4QQMENc6*)>97b{- z^bR~Rz)*;8p6DWnQ%T+zN(K)A{FtOAh-!1=;Sd7yc)A-z>iG4rm$8oo7XnY#CJ{ta za4)1vOr0<&3(a6e1;fe&lbpfM9QGW#iZKhP62N~yvq-G7)7v)S0jxp_rQ$&(%mAL8 zpj(l-8bosv8p_h=f=!3>XETPBN&_GZe`AgZe!Vg3Vwx+%S(h46y#zSZ%$k!}50hI} zLj`1cUL`PGP;(eZ4wk5dhN}k9l2~r9&)DrR+wu-QJ5v|KK}Zs2#?++;>=rp3?~up~ zbZw!FEVBS5RE^{YX`0efd6Bzvk|`DY*l!0JmGH9}R|15Fp{?>t+B(E!;LXAD0mF(K zQd`1gLO~dO3V|r#0!i(vg_K*S02a8mLd6>2i=Qxp>g-2Q#2>cAs zvX{>{_U8I;+?zr45!#5rMS)GAU=zc*l*^0~G$IL*UkO*zVELe%pq8bQPM8Xwg@cMr z7HIax)(%W%%8kFumM-&_@djpCdFZ|rhD%E;67Lw3goVRG*c@`F(h}mNphD(^oIQNW zGuFVWSNkdDEDSANF;GQ&4`XREc!Ws>QNsuXQ(Pplo6i8xod%fUUO#M{UYQL1w*el@x`@XlVHhJUDnQkRX^bAW)E)*$LG``wu_l zWhP&4H_cJf0k$a85~~8Rtf3$icx`ZzN+3$~0f(YUa+9mPB!1N#hNR{Z9?7&{;0K^j=)VluoLk?37*xDUlo{jQ3Jg?$?u%W{ z#r+DPI}2LUBy+_D}XX?q~#g(IslY|qX1@rJt=tF2$(miM8!Qn{3Gxz;ai$5uG<(z zK^nn{63U>0w*V+2(Q2VmU?l~}?x{^_7Y#jas9dFMnG$kCr~y-FG~l2Y2z9@Ym^e}L zSU|=+D}c95z+rP)UMoOP2cHtWZgOd|n%kpRc(}AYw+L$k+gmJl6gMota>}klnVlY$ zV3oDhxzEv}774H%gImG^8)Wp_f!F~V;V6qz**pQSLPQuUVVGhD^~4T8+t`oSFFSGT zBQQ{cKnS_!vVcNBx&`-4N9nQkOt`X()V{W%zb5h=qVuCvK57`mUZ_ zJG1V>YJ)8^kO(3MZw0EOkO`bq1F)K;U`g<54z1}p!3ux?Y8j5Gr`rbyHiH=W8PnhO z{P7?+5nvH5T1ajJ2m=!=wDquE0_q)}5oAmNd@$if3pi#5ey)OyXH4Gkm78(IyKa7E zdY*)XpYptgHZ?c*;Jsm43IOFwkUzLhE?h{pfX;yH?|@cI_AgwSrgP!JVK-3zu_ROP zQ&a$!ng<|ZT;OcM1>$BRI#ziF7n$B;4cuHXH3KF>OXrHB2ATmd*K_c!>knMnqZ)?d z=qzjUqYJJpdp_p%1KR?Gn}Gpr}{wv}+Xg~7u)F!_<)PP~*P#ZoeF6kfk5>y#lL z$DB9`*B9`(%7Gk2UC`ad11Tn)!#;v%bNCeXqJBB_7lCV1=-{;E?yyYY09UGpO;0mM zSPfRWg4b<s$2|1&yCkvSO623A}UXg{E zIY2Ix%86Yd^+^VZQNkB10RR&??$zQ-K4}Yyf3jB}sq5)kUO14zU~r4H@I2lM!;K-p z<%BV;g~WBv;eXEC>h*rYy&ZC)lM-dwuvlbfv{MYZY@tCLki zS#BQ#M`QY$o5+=BzGVuS36pD6=A{&H)0t0SXK+IW7DdlQRGVHmn+x+|cr=Sfs3fF> z`hwq)rKxq&*Gj{?B1q)n;f&Ewrkn#23g9(BDRf*d)RP41Wd_gC;6^Q9*$<%1) zQemOcAc-#HY2K;;i(*Q^m%thsllU0bf{7^Rq#^FcFL?--u6S8Mn_~GfAqA7GYMEm# zbCaYzSXQMuK5!cey2Vu`Cx{({4z3Z4uwxl17X8e~^WE6@g(Mu5n?(PKQtR)G_1a$#e*P}bpb663=03v zd$>prO17pJlhD-QC#d<5S1X+aC*|p!6im80oSkFogDTS%oB?ZiiVAiX62QaK+`6g- zxQ8doY7Hx2RnGCiz4!2#fOF<_=pZ-miR!%tsTt<1p{d|==V@v35>|)@7I`8F+9b7% z$)xbR!A>;xnX3iQxFp=Xn%Oy7O3;&5IaoGuAG|AAau78IsPx8zD;+d7&&)~-`G!MM zP_@DO(-nv2vtXX(p623};CxseNUJkg2!KyhaEHO^3OI_vSXmX8UO8+q&s3)XFQu;1 zGAV#B#PYmG$?h0F-hzII`;+I+l??uPsQ@0l2CtKFwWYMd6Ni`;w$?SBb?KRzJBQty zUT*d`>SCEe7{i3t<>^cIYjSSI!-s^^q7@G+08w#E7b*rbte_7(+#z~;zN|Ab=MKe= zm#~x68ur`5n}hwT6Bx2AS5628B6sDY8 zMevXSRmucjPZdsXmk=|ESjK%s#S^tWW2S2lhN|nM`ub+=UiJ1Tp)*v}5L$3%0nLG4 zYj1cO1R5kun41VCO-B$AxJuz=%0d*-?(h!XvY3yvR?AG%Ef;y>VO%mmro2i@*852F z+yI&~`3Un#YRjN*IDiaPSSk8WVwp+5a-q7TT`~{`7CgzB5d#^qERDk4nG&vZu81mJ zVN#_Djd?^)VqkTxLgHp!Nm0+iq$ULv*yzITfk4M$79NmEnb*l}A;zUNler2B2M;G1r#v%~Lg)Yzp=#^0Sk~BmUz4m%n6|1+jNwAU0A-bidkyJA2fnVo&kWB?r@+yf z%yXSM5l;O>Itu9W*`VX7$G--^4jY?ev4<-{wlg5Ear8~l19TV-K8q$um$eL%~ zPY%<}l)C~evWQ0y`u$SvfdqPLW3n)ff{_GWl#;2+xg)OO;q;uH7D<7{2XuwU1E_6y zn#40INgveC{4g_s38CzARQF5pq+iK(RqBzoHc z3^HjQuucwdqV!B~696M3E4W(;IHusR!`LzVf-%5cgDG=h8Tbfrb729ixx~V0*Fpck z92J97u*E4Rs^H;CXe-0y2!Kmp`%>`uR|XU&d^ltX>}(mat6|nP4^`c*L8eLFEXHM7 z2|z-3c?GA+KvBswbwyT+#BgI7&Z+av{;!A*HAATs`&1WqvepRu!3@KmR$y1Ac3CUn zfC<*{khuiq;HaAddJG&#w&tlBRT}(PI;a3f zg;4-S;2p)|tMqP7!6R;jwJ-&S>F37IM%|A})Hg5%P|7Z42ogXq%~PIcSGi}{EOQmC zonoQ1j74u??ox)%QsyJ1JiK~Wzf)}?GGP+~Tr04SRaTZZRY?NSi>{4@+nF&x6)TXy zBC&ANN_Rb}pIT}y^AwU<@ti}O-ECCk4yO#MqAgjUeHVcmJ~H8w~`vo%w?P(hd}|NVnA4BvNRsN z2e`u!mz9EW4!*24ISg!pCwyGWBqFc%&W}+Ot5|Vn59m)8P(UVy)&TzV-l$M)))X-5Ifj$5f@N4tdqK zlrm*Dv4NccE5K7^N`O#)MhA|2obHTgECK=k))=t>;LpoM1CD_2vW#UufZu=#>1w+g zAm7sy)^y5Mt(i@KSAR>JXi3djQl3g4p#V}sTb`*6S&gNtQbIEj+A(%iFarkOsR2lK zLe$&>xVzsQ(|c1nFd=ka3cy)GibTzzY-J^|uYj`33TQmI=P5KLi$+2XLR+%vm#x4# z;JN1X1P0OnoNH5HC7v$AR&~Vy z)N!3oc2vgO(-mYg(DRcCU^hLs_tJz@s zal@E$0kk~y7|7t5r&XnNTr|*x$eEKOBpe;qlHoRA2p1Rox6@M z)}(h}B!+k4Ruu58ptqPL2Eb)u32Mn=N%Rxa!b+B&;7&=#WF%l)U@h;CBf?ycLRF_l zZW#0coB_ly$?1$}vUZOwrOTjab&-YK_qq&4ewfh1A~?X(%W!R>>mXYkGL6 zB7;_fKMGizu)=B1`q$2|q>i>w6!ti6I6H*T2m6x=ONc@%00*iP{gV1AaH59c2fzmq z^Qjfk*sROpiM^|wsY^K{0Oj0Kr{hL390N=s&!A^k8B;KVR(Ob=D4?1d0xp3s3Z4RI zK`Sd*rPjh}hOLsUv^|&Df7}?p*gm=%BqmZY3&-OMNvgqbSH6_C%9$v6uG4ui!BWDh`fh-iz z3YN*362b$)nF(XxI)o?9m2w9s)&a-3#aOWTv`aOs!o#0Qz;G$^YoHk{cLq&~6@s}U zL}cOg1m1HwcZ_*{6ifLbFpU;iFa#IMysBydR>v)@np-G zr8~}3m_%kXR^8ChJ5{D?o`kZ@a!?BXoq$_F-x8XUhkgZYq{^5nP;d)2Wvsq9ZrXRH zUdY@_XKTp=&Yr1oIvn@Nl9XXTrkNy6+^?C%Z6wQKLsU&_z^Db!xEwWzS#0Rw$4g+n zN-76Mm%(2FM}eWo>q7B31CV;bQ&6=9MWCgX27awlZuCi5$5IzZVzj~51Mh?zj{viUQ$Tkp z3)n-siuD1YaRgkl0&W22&NN7$&>(1L@1-muqktT+GRKWzn9$oRV52fZV3uP8B7jd) z*8qi3N8mG5aGeK2oPwN?q>Wclnhhk z?at;bWy+H+HEY6^wx}^*mDd?dF~G-iye9(^2xtsH+{93%2$(J%;oe;8OVbPMKtzTbnT|rTB3{Ky#kipi z8w~|Tpb~CB$a&^jl{t`p1%=M4->mz|D&vMb*~=sxZ{IPx?pa@*Me35AZlmPA1@Klg z76C|sOp1irvk<9LyUe+or3?fdMo}fpQQL!~YOpR=RU%_x4&q)_Fa*%X28zk03HTKj zfiY4bLns4S0aNqHmtt)Vps;0AFq=`!v@V(WywX6vuI3>z$RE8R9`JK;3~S3HPf!CE zj+f7U>5U4vE5S&X%Q|=IpjuioMV;k&y+|Cde93*`Ws%h^nvM=CmdeVZVBvDfw169& zh7$LsP2id?Pw(?#Da=Z7L!dIIEDP9gRf8L~tP-#X3~8A#FA;uR&B|BsZ~-+k$+DQv zq_O~G+}cZ1UUoCsB(d-Y@`}ajp*>-w04EeAw}KN>vS2w6ib0Z~-gp@saU;{b3_*+l z;Jl?fo=lrYmqh}knt~s|A_=Rt@M4jIxAX|sflz{HO*ON|>!8mI%NzsdL&~gjb7}IU z?helI!pX}EZl~#*n*-M)#Rw5&?WJ0El{D)CbvT|<0Yy;BSEgVz zr>Jt?P+>~u#qn|?VBv~)Af?kx|hH(e8?i10=s$-#}Uj|msA)v z3)QAPN?)>y4BZ7xw%~OIwSjBB%qRcDli}tdOQU#r1qHAlTpn2zbpniv7J*^tGqJX4 z$%$$RgXGm@HkB23FrdV4iB-;W`nM!(^s#j-fsP+Hw}s)1t0f zHZOxQXPxPUCF_=*!9iz}&B2&)?0Gw-An^#xDoi#DwYhnO5ma`zDu6|yF#*$ju3 zgwok9;x_E^@s)R5e$j^)fSb;^{v%1tQq?uVs3CBEr1wF0dK52M&5Tz9EMkSax0A~wh zojc+*?s|kY%SwuZ1q6Xh5*7{S*)#!sp3r?F=+vwO1ZBYO21toADeojHi%_Is*$mF- zq2|2vr-Hv5?luJogZAW|ZiP%L_z@bKlND|A1a`wn-n?4dvgEBg)c3`*=Kki_AMJa$ zBu`SGz^Xc@0mK+*PGKSp6DDB=eNi%9Cre>{Ez{D{5DViqdSEI$$Pc(s-?;~u>T2zI zTKqR<6=HtV6==;*q{)VgM!Mxa-C(Wws=K<=U8AJ}@l z+xJPhs=B{6xU}AZ?o6hKTMV_17PQS_PAlH>#oSm^u!IAAI3;<09&iN~$MTRt+1#HI zhW+($)coR_SL<#c@?-Y?%j`T&&!eQ@n17m;IIpX7u{y~rUes!wTFFEf z50d&pB2MFbMs1&O1}}!cyBAAHE>AI&tX`Ts`PFp!ot7z;K74iTYvBV{rk7~ z@UQ>%>Vc5iS+%;)|A=ITZ>;kx#k}CJ98aM*yLx~1A+-1E{SRn`F3H5JSL;0ko4;JG zoBXd2FE)DD{q=?Bt5Cam?giia!|G~tL=stzaI>+`;sHPA4eF;JNzw>u=({5tHE5yQyl&B?(-b< zwAtGAmD;{pX&y=qT};0EA;6N=U#M{B+wKXF6?Yl{O}|fmSfxp_f|d8{3pd|ie0#Mz zxsKIOR^ZofXP$g|+K~Lc)qBg5_4suY@S5^`_d_F51ru8{?at3j-e*=<{uYVqU!IYs z{zpnuc_z};ef&G47_Bdv?YesW`kYU_*Zv)FD8B3(!JJkPAN<985B_q+2UqK>>l@51 z+6>NnwSVEToY(G(M0o(#2|@jpXc(PJ%9aTz3ZMd^lNsjJqz-o5xX{S zcgCli)5xpMt1H;C7whYX-{EKc*6{H=-W$)2x1e6t51-hdQLLWr`()<~P{8-1}hD+t~CGR%TwWs^I1O*wQczujEE z_aHRAYbw2{ieW??eW-NoncG{Y|f?wrQP_se$wyV=d43R?ZmtJ zxht-YUA=Hy%&ASOz(6k7JJOXjX?f-1&3pGj;r(`P_Pd@~T#Rd&fVZZ|d-o4WvRb6b z>cK-Y81G8jT`S{OBc>0QCxgimFg;n`$P7)-Hk>PtJ6OM5o%kCE%d`4i?N3)Ho1hM$ zT31mq?C@RGMDMR2SRIs<%I1yu8?*?>8Vq`^|NzwLku@5&igOYdXVdzJ0nn=?A~w z{pMTh$0HH`;)D2HoK=7=VGivp?=XwdMKg!N;+*{P zAO11?)Gy0fe0I1h%~uec3)_9g?$6rh`f1#?B7gjc{{;5@i0YeYVr3jfxWoGUDSwfdKTMN->kQRog%s*-1z3R7UbM}4<^&L zJVgfEQ)fSkAI39}Mv3%;O%i8yOGd{hPIl|(7$KY|yx#4LJn6pdwERhgUwnup41Wyy zF-(&m8m>H{7P;7LzPq_@kXzT&d2p5(>^*&(7nti5bngXp;p$}I3WUc`SFeU1Q&6no z!9%a)R(E9VjP!ooYT9A@TlZSGjL+uQHVEaoNxy&VO9=~uEUIF$|u|I?wT z){{C}Q@O>}1}8>M(Q$f%L@@v6mmz1hYNcT?P=tUFK3!bP!56b^*GQUqp{}00-DDu2 zyr!eLda@7Bz{#%z+ckgvFaOi((RQoe1ob`uOSHBjQZQgE{J1`!^ZsAJX#5f^*6`FG z{pw5UXX3mM-voVV(DbsZsQ!*@Z1XV><^T|IAg&%(olHEEt+4W1^c z#*}MEyVu7M zfy;mK2~=k27XP_1W_A8|Zo2_fo(z81FV%LHoVK6DDSi(_Y+R3TV+5_BWR&I4BN-?6 z!ty*&-TK@+TMaDUt041p_U(`|bL?_@Htr{a-v?W)`j6^pz&3psjrM*pG-L1DNgo}* zLsY?5r=8b%w`9b}n*rOK>x)pX?N2)7Sxdq=^ZXBQGrf7cGi`hD%YYb-P(Enw&VyYm zo<~#UK(4!9gMoTFjg?Q4-`~4(uT~+D&)9AYU?ae7HyF>)O;#3pmR14T zKD6%T!>gN%iv=V*ZlBVhoF#C)&SWkj{qNm>_~5Ovf#19TjeF^tXL~_1WXES6_U!dUVY#{s;0L zp5}vx@7;gzejlmtMt9COZ+7#)#kJ{vYa{ycj+u5^kHVISx-yPkJbdsMt4D^hjFnNa ztPq5Y7^~NB0H#8WzVm+?1kt!bA)I`%*~Pg1#xp$p^$Uh!o6Qz@F1uAgWa}%xRc$QR zov&KE@I0o@Qh{%saUov5xw;7P#`o@nM>iovPk(J0%ZJ)dSSr-)U`m`(6&2ROb z!Qidi-q4qXz8{95n>~f|RU~yE4UW|6iQ3YQPi^pWOV*COpD|tHaQo!&n?X~dq0!T$ z2iwiiagVnwWcS$WWWV`0J2(X#?#}I>ZDQ2uQoa7lnUC?pi&Z6RIsNgko!aiTQ~TYj zic-S{E|?<@s_h~@-(P*~%-S-}|H=(KDfT^$q>(6 zt;2(aCF}G3<~NV8_C?lC>!NL+KF1B0bI zcj3FhEWX`byzE?{ukbA6#e?8#KkjI41Dfm}ic<*;!|z+>pso$f(MGEy<_y8Guu2`H z1cMB)f?;yV=DZgwTBaHF{UuaTKiCQ;)&t=8t|yf9=~1 z^i?2Jhbtgs zR@C+N3QRa`gqfWp(Mk^+Cph>uzP`1AM|X6f+YVZPYC?TfgrrKXGxx=2p9{6Pt+0tZDH5 zp+pU85%g-JA;kC1o>;p>gWtohQWG`*ix1)s&Dn}OL*1`85UyRvyA6Kkep&#@97zA; zD()b4?_PB~O6>!2o2!4I+x8kY&+rr;xoth#JvT>%HXymW+CRSXn;)&SVt8jpXMHs2 zrL{lZlko}ldD+{xE_4l>>@_Ls{a~OJ!@vza73q&RzEy#sJm^l1seKZ zLW2Yv)A8P|zWYh29NP-&k)L|<^3P$@{pM~*snvj~`S=o3hnHXM?qclF1fTn%-M{P( z{Nk6>@!Ekl+kVZyJG*t+=GLoy^{tleaubts@b%?kQ%Y4;P@Fd3d&;IfL4akL_Pvo^{)R$4vYPRTDPjS1;AYjl1j7Fy>}D&z7tL zl*hZPr)dB>nt(W)=Gl>&8iPex4!=2zDPU+UsFk7C98IR_>H8sK{Nq3TV{8ImL)%UO zk=-8w-2U+&{?pi9`AF@!&9{f!xLZZ<`#gNtIWXP4nyJQ48_^$q8)6g;7q&OAaA%7C zV@u^r^&L}!=#6qOI0Oz!Ip#(2i}2q_`Ng(c;~Q3V6eC?dYT+#3zoDB12^}s-Sh)T# zN{?;Zi!XdSN-pZws`I3VtA}^{oTEUq(UP`#N|422(2fZ{ zz&t+J4m%p{-M8WIr@xHz;@y(xez$L5>{hBDTO$mUl@;Bn2i({!Zu`!YZjr+ajN%uEXqZakZ18yebS@eLp+nv~&Eg=3IkM6)b@nO0kKD`$ z+PSw4KW$p;<*Mbzvk~=snw>>0*J0Zjk8?K2|4Gm`_;fnR-M`;@uT3!dmn3GNp>58a zIhyl0rHhW&(z|uc|22mUas(vb=9ND&mG0dFh zY5E^+V;$8?x8F86h~lz4NIi zd-t|+#q$b(^CJiJY~aM-@hCau2zoWiJK?@PfT6JWMOR=mO66<=qk~X;mt!1X9faUV zFZX_n-CPEP9`d*F2fw@8*qiJA+wdp9Z}q-K|`~dekUz_HmxI;oZi-Ckv=04o0}sV9QqL}I%eO_`Xyb@{Tuj51Uz)kn#60SGR-A2 zHA4PDKgb_Oq2L%u(Z0r5i{R{W{3;$tA25MS7f1!3SemGx)Q}3O|*4weSM@m~&br@QyoQLk?+t{{u!@;Eqckpl-Z7 z{*nxTu+ewue;^~6w$42{pbI?=cbtNeF+qa6XWNwe6U_c*=eC~&SLfa!(aOgprGDEk zc+3hDu=kpn@y*o*&BG`JWYG0&+hDf&G_Kg@`>XGx0Q@j%eeBlW*8E2@KD=_T&Be{G zAMat?LlSqNq1EEALppb#yI#Pq~_1ivi zvq|b5SkTim@P9O-y)m4c)jqv6JR5JsLUVs}uQRx(PZyXbYVojV@lGc87$dvHkC*C# z^~2wa9hcDdZLHJx(^%D(DZn}-#u=_z_xYz~jfe?p$9n4j)Hd{Otmx9(^kKBSmZn*l z1=AZkYt3)`V`PFmwwxVBB-C6zgKiDuAb!l+giab;alKu`j3wi#h;s$PtWcT zd3(8RD&``g0Q zg~Ymtg!Yj8cyING0~>EvdH(XB-EVLIH2q%tJ1_ne4E{afFTCchGE(vRXWS3O=e5yb z6N^K$GVQU3ACLutH~k9@3hnjUE=ato>BVm<-opc)@Z6jrUWE-|&zZu!zP#7ueO&|Z zLklQh<4Lj;Sh(=<#x@lPcP?!lT79ATn0Cr8>(R|;iKAqubWoMtTraVGInU?dVqZB@ zGhbVIiEK`-&ur8+J2CUoHHQ$X1`^d|#TUdmV9I)morr^Ow*mrdO#X84){ z1gjP(eVgXRoMx8YP}2tu+}gT#amH@;o*&aOo&@+dTdkIcipDM~Q| z`2SGLUJ11Rhgt^VxA=!zHbx6^sD#CR_Ze_@nd5i-5ve5mRasb@GjjuRX}r<{TX|;Z ztTi5%Xg;4-e5% z^`<%cRBP;7K~p+?aTp{f$GQpWkf1C&SA8lXl8m7ybVhe%Rno*ERlb92wf*~ zsnqJ@6`Q5&t(n)}wy-#P8-0c^yeA~yu09i`$s1*!!!gHaap`H@7@E|HUdh+Up%Ex7 zwdM?YBYvkgDc01Wisywb6WEiGK(;~TEZsE2u)Ornhh-+J$O)>Am)=ir16o4&x7eD?Q3Pr-O(YeU|D~Uy|E8Aaze05kl8y^>)QH zZLy%KGD;mQ?Ftb<|JGW^!=9?>hR0=u9k6QeoahD-D!3gIk}_CEDE>L;uwSgtSZbl^ zCbW1zeq|;voZg`)BeyS75dI;|mplhglR`J;g3cE=0gxRx8&})OuZvWDGHl%1-L56@ zbyM&B*v*idfnC7Z?{S$kD@6k5Je=RO+WCZh`+ebNYTRfjNwHc&TkfJ!W-vq^YuMrZ zB*kmZ0_g6HpKR?$zg4K!2#VEeT_0dI;LqYn|I}!jl<<~*8~ZSI&CvS&0gNq+iRXGW zAT?mi$h=B~)RZStbyVoPb#4$Gl}z}RrMWDGbD8YUUQJ|LyU>qQ#YjcYG>ky-jXrzf zwQ+8u_CXb?Y)hankm|H|mc_mKbq8%4=Nc7Z>IE?$pI#XbD_b3ni#KEAw5S~pNsxaQ zwI;GKnWm?n9A}ZrFpsyzX3^4xM_WXYgRtJPVOqAvGda|AX@eqnvZD8k?F@H#H*?Gk zNeCx(wxPXhx!|2c{_F+Q2hbrlq+6vU4BJ8q2B0UdRdoovhox<)r>SR~z%jo}dGtV#O5NuEK zI|Y-nrrQGh6xjp%Vuj`y@Kiq z>vE-j_nV}KIk#js*}x=WEBB(zWDFIVR_=htnp2bu<1>2!9R5l9FhCi42>T5d&bYOg z)iPa+rx3aQ-z&5Kf(CThshz5qMpo3kCryePm{vB7!{Jw<>czGcF@Sh$-x;^M@}hvk zH8>{n)W-%_VtO!iCU&%04gG9TVUN=B_Xj07v|C~EvgV*u;&htV0Ddb7*fI+*nr~Z{ z5B5#$&S?ZRQ3XjcdlKt`KY^iT9HYH{bkQ0_atbTBqTGUv62=y(@?SFP*taH>Z~|Sq z7-mhU->ktwf;=tgNxUR7CdrQvN)!f=mYV|aw5nlV@I^1IMr{ib1KnIG*xEjtD8v_7J|2D0LL2yU+ppSvZi@?S=DMA~!hH`*`(%jNB#JA6=no_pq zdpe!){!=SQph%h#J!|GBg$!?8!?1}<#v(6(o9rmc;$+q`KWwaUjB%C%9SZuxCum{= zyyUV>(5OLl-b>MVEj6f_d6G}B^eMJ#@06=Cgt|ONj!NR-1O^pAALSZGcaE^B8pzQD zyK|sLU5T@KqTW4&tPd|ALU9jp(OB;BIZ;>GI(eA!Uc#r@UBZ?G;ec7d?fgu~ZvRb5 zaKv{TKdvRQ=RZfjp@65o(Qd3EJKhHb+qA>{zB@!vnnQ9EfwFLSGl(&%&tMf86vE3| z)WwTxVeE@&r)xCDDfAcu;*e_a@c7yd>*sXFV|nb5gq6a1LkFc~7C}vk^emiZd8sO< zxb_}4a;U)%T|K3b7dd@X0zH5)DgShH)Rh@CuD`+Yq=6A_1MFlSLhOM#l=);l?ty0e zcZ!PX1EWHNXIJJAk{zEKGFwU<3;0rgcaPB}3xcY1Wje;ZI6&YcvC!A+l+Ta$QHQ5&a=zEMk z#Lu~ZdBF`~hIIs`1pTnG?mI(wUui$hhbzt3o5?;V(e#1I6irJW*8@*S^Y$<({Rwcxt8VPpThY zB&yYzZCsej!7UI->ujuCYWi4Y zH4W!T)RUf=m&Qg0LzU}<{#aeBqvZgCsY)Kv8#!L|I#$il0$G0NOvrbX7Ku66jaWBd z$5;GGT;exC0U$v)c6W0u-%6-8CGr|o+N9^G&{tW>_nsm00X9Ch=?do864pD9u-&NF z83sIfn>xDj!C@Jr{$*$lyzK$bP!*nEtb4Sfz&e3n_A(?nP72sXELm7miT8ngK+297 zg4a9I2s?3}(vI?`IO-<2PZZ~i+A5rq)y0$6mu$djuwB$zR9{njAC7_|Y3b;8HE}Y9 zx*U{7w&-})0{?H4hC4K~yO#%hACKg&cbBLZgCp7agowd`hBM`onJ3=krQpD+Vw}3U zUw%{rjAi&;ngs=CA18fUW?iegYV}69?nWb^2n+jqd349VQ=JL+!XqK!b!B}r`8Gbo z4ZTtc6~60%j>#!DKV&-(T?~l;zJg#O2qMARdPTetT9#McvEf}VQaa3^Vtui!nt?q2 zSe{Yx#abGVcI71@_TIT+GJ9}aFU-B;M&#)?(e}0#izWJVbMW=6M2|UIS z&Ns$CH>xDH`D`pw8kj5^CL+l0A2dAl1Ub^a-&9CH@Co!%;mJ??$_W8g<3cE)q72#*2zENU{|AAr=g8J3`a# zwt4Vxb7#2rI86>tua+g>p~gh*W<5V---^#e8T=FB;r!5qNH8lN&Pa{)rVtx z_&-QLeu1;Abvc{YYFia6jikgp9v-Dl>~9|}{7i8B?QjM5ZRns!e|Vj@g2CKb@{V;c z;;b$hGr-8=F>T4+MXr6K_%&Y;!Kb$?sQ&!bL`x_v{UV2T*|61|Z4^PVTMOYLBTpwK z^&4zNtV9>7?5M@?Tti-PwT2<~0H*&2Pi~^b93HR6uqflD#wx)8sJYD^1yXKtD`sY*)-+6nmu(r zk7$vY1#D+ySH)L_o<|rE>3+s8PxNbpAW>R>xIONWhQs+_$H|@R7_FGuA7@w~a3r9usH!2S{E( zC%3S{j`5EO!^5xD-yPJ{(@;vh?8&8jCc@fh2!kc6;yfjcJM1m;@y4!*RwnyJxy$FKm(Vd_Mz7dmI`X=mBs4>-3T zPGy9?S^9OqvDvvX&E5TYANSe`^(%S$sm*E8nkINd>R@3ULj?H`>WE8>R|`$$&Ow(k zrX*x>gC1rG_WekmQynCLetfXCab4{wqd~{glx?$grzh}jlM#MW{+u%d&?tUZKFv2v z2C6NKkx*oXGNeLBPt~OCnoPME81w<-8(OU^@U2%T++0tHU9&*C(9!psE_@o`J6@L( zv9})nv|)8R2tw|9bra9pjX1R84T5+onjvj8$&WN*q?jXQb-<4jZ&F?yAJF9u@heaZ zg(KXNDA}klwGlR<*?2Mg-r5Lm*43-PwV=P zgTCed?0iZNta)q(%<0hhgj_|$%J{ZZ9Chpvl;ah(`7rL9WRVeWb#vLTEW(FrW{CU_oScusIgB88}<%YhF#fCdC(x`l!M(4=)(D4oMr1NH+E13TTEq=oA2@ zBULhteU-;mD*~|{QvcC$xk$KuY%2J2NGTcXsUnUKS%@k;PL*D#^b%u~{eYBvk zR{_fNs%E0FA0j`ZsDzjt?F4Kk;P6Xe+M=&UQ;tp0&ufjp24++vNDwDnEhC)sq@SW` z(sT-$X+N*On{{n9QkOxr`a$`RfZ?zj7`F>VGj1RS+jC6ZDsBpb=n+9>c8k;`oKl+~ zv$$Z_);0QL1sU^L#*sHmJsyNBP$1@4m&QQQVr1FoAH6Bt1w&_znW)jxH zy~^#qh7R#kH`QPDI#z2NulZ3;VTP>e@Ccq_pVb0>??+iDDvmus4f-$m3N1g)H^Elc zdjNjkSS!8`LDRd+WN+}3JQ6J{HmJvLu82>uUC!t8HZO3yo;Hg_^~m2nm(+|>VU~RR zb`%RhV5&84+Aq;yf=9IRXhHW6oChdGlHJG$mxWX-JL`UuOSF|JP8C{^GBcO0J?)(o zKQ=TP>H9e=Pmuq&_Mr7Kve6c&o-31uS1ZI$!kwtHAQxA3M};{nyq)4$AEDGL>Y5P_ z2xSwh2IG_XnFC4zx5E-4M0I?KbaE?7V&ewgFIO=v8cQb3G_r}o;TX{X9;gCboR-LP zgPhzhDz-10F{RWc6o)YbhRnAET^vL*IDMaj6AwAQERC_k`LRkj$8Rj2WJZQimi>)Y z7L!MG#8gZA1K%CeZ5XmBlO<9xBxJ@}A06z?d|Fc#IT*Ofw1-8+MH>k0Blc9K3Nv%r zS}_WWbJc?^R82?G_s26L@`tK(T7}~RITIsDpZ0dHeY#njRr{V~x;SC*qISn;vw%zy zY0j0ACO!1PM)lqCax#6SW3^tjddA=Uvy|P$vb0rL4;l8 zY1q$<@N>Z>eD3Uhom6Mfr*l?NLm&GjM6o+!T!a{1D;uBUlM)Jx888?&cUnSt#GIDy-L8av2P3PRo%CBExdzH1vW>`}o+e8Shg^LFm(W3A!L4Z>(HXE9AClRw> zV+H;M8L_G2-D7xkE0baD<2@QTg^tmdd6?`v zQYLio?I_sGZdQm(L7|mu--}HC-HD?kMwQRJXM@LQ9*8~BDeqtnB7(`saGwtur)2#M z3XpX1jf8C(!~6@~bWLxPB&^1R*f}&&?@_qeIsU|x79!x<_}60~e#8Dn9qWQ{gZ`Hw z9{v7&e{L;qmbgsIoWAM|oWn}*nG1u0I!eoW6c9u+?1G3r9=%6ZzicUDjt$-+A4Rz5 zJupPduVXgLkR}snmfeI%F(K!=o@D57Z*P1!^s(SQJiq*NG;aQnq#;kPX`8!BCYGV4 z6|HxLFjvdsT&8HEw_w>DKXXiDLSB-U1#%+B-{YY4EP+)Jtvtc-7+;6T6KKV4R=mFj zqY}ZQ|1Fc1Ml{YcWZJWrD`}ERkzc1O%v-lO6`O^WepEI^0C2OU{ZS{`7YCxo9RM2P zE~`ujdJcKp@HRn6$>?U> z78xasm6a~qKs59YT_&HX&03->-ZT~4$JnInNyGqvW+GFYMThm{B;%^1-SV-x0o_nm zEI$u?Spl@5P?G=BPF94>@G4RdPJrcH#h5By)Hj<4?Pq#iN>Iz@UC%}ZZSFK0fi^5a%o==VFDISA=;n8)K01yK``aIDE9sfux0KG*<5ZjL%M zVZfA1It7Cx5N<7alJQRwR3`VY2%6`f8rsxi}>gnI(;J!eRJq4FEb+Mr0$A!_)%teHZhgh)H}&fVvYEcY8j{#LpVGkDJ0AwD^13U2!Pwb} zZ*r}qeju-r{mqA7_IEJ<+tGFZ+x7lZJgBOKWN8t8idI@@+d^Y3g5D=jyNpt|zU8B6aYSI*(>G55+;PEZ;~&q{c&|0^U%TxaQQ~ZS ztAd6AoVml_is(*@!T^RI&@F7%M_fBEp_~w09}A* zquJ3Ge6@zIHsOYoKj|&;c9G0W0SWQSo-@pZkD0E5KO4XEYFJcCk02_^=C55O->6fn{<9#xsZ(-6B=JXL)$W|eu4W_~^#;Bn>X-Tt2ec`k z*37T;1xy0CAs5$09I1jl zKNyra)a!0V!vj^Z=wwal`EXR|DPQ=cxt97E*X*R`AjqWt#env}eNlp_3m}F9|48f|)$P&}+yB6T zQi|o)0+QkW{{H$UUg#(`oyYi#r79lNhz>FQVVn)o>bLw`mfZ~&T*JS^u6{KDiM0d_ zxRcAB`vkf;NmNZ`|1zKg|6)M5VuMz>{T7FwdK66WAPY4bD9%R6Ws9}o=Cs@Q=v2q)+oKSy&cm!|wrvhp*WJVzw;dSTZ zSM`qWSE<#?c7hqxhv9eJ<3GvEJs&L@spYc5=(-dx|EmIuaVPxf*qze#ZK)(FY6sCl zq>3jMr&Wm=#HN zX#)w0T*&2sp;!n2J;5QUVp{mXLDZXcotl!n%#Q8Ymmw^tTkId3`Z0=2J^jAcbTRkT76AEeIIbKK%4SYDQdNEYA3Xh1?ZjpugBOX-iZt zi%;Zo5-?mn`n{b_O}h%19ycgDfi-v-=eJ~QIp4dCIOQBd;`C4?eG}<1lQf0q9+{0S zljHl29Kn*b-Mc*jf=MoI6R981eO`V2fb69uR?S3-TI4ac+U)xks>n?Gnp+;T%}{_d zJuIg^kkuWgC87LTf(`2vk@7NE$Y^>?7pOb!24731%WsjT55B25r4RS6D$Ozg5 zPaR03>1n}9vdOH0D{4k`Z>mXa!DDwsewbMG7XZb%{lw$*W|(^=35}^^(w@4urv)p> z>=o<6+RVj*sM?>z0h~0M>SpOUqLhw%gO=f1oV299-GnV?uxRs-%gPG$)-gXlIrKd|X>i9`u zF}w#q5zpCL;Qf|`<<80Y=7mSHjFB-eaT7LJ_bL>C{1Xmt_J!NaHP72!@s*=_%BstH zJp5-{+DE?wOXSYmhr>J_+Nh&O*j8XA$<*92VN(L)aYWdW@opbxjs)_4N}tcM{J`^8 zN0$$A@siXz^R^GY_`k3}$Ny!2R(}fnU-oB68;F{i03I+|tgVxn6%9dB_}^fvHqR5y zT5e3Ht!S;g9Z|_QN;?@)pO5CGlBrOU9c|E??}V5w4+I^T+t9eEtt9||_U`KJ>(s)h zv9&_7%qfa$ay2_E7R7Y@5l6m~M*-W^aaaa_L(|U)-E@pDvl}&8ltZVTo-|vd+kKax z&Utz;*BcE9&iSvWjd(sRp~!ELi&~BAmxxb#r8@|7%rXG9MbQkiN|9kg$OSUlYq;v+g5D6LMt0yU;4JoyJ{Bsia`U(Bl-ag@7>}OwXr1=@c*IFjFW-;%8 zT8M0dSn-~dn$A-iqJ~yvKXSN7(2`e=!d{^Q1cHycCkQM@$(eR4v-RCNY|hfjx(!}A zj}}F=JjS6VSfh}#2WY4;a|Vt4$|Q{DeO6}0HaxV-fq0D{t0lf&j0mQ7ySdm1zl(^a zp>aqv!6VcqAyk_dQ8R8&Ox}OR^dI==mw&@Q4Ou0rrM`iW2i6a4w^{(b?I=z?F=;~a zV^@n6flNcS22da@e>KEHENVeqOOsc_c6#tjDr{`v_qcb<)|f*>Q;>z48@B#K&>ype z2;)V;1=Jc4#lQd-!8*e?Wa-92caT%v{=&Q*YLE5xc-`&eL<#o5=GNwkfoy|NiRuk; z+Ez&H^p7Tm?}g~YHVk{T*TgvY;|;N@=iP@?gh@{$nMI$JJ9{Gpgoo*p7O)wl@(wyd z*MS&b#)fsxtd%XM&XLh7aDHZ^uam~Bb)&7;)S8D@u+B%EmM(&lFEdlrQ?M=5h6UkK zL}FoIpl66wzif@V$Mb4$s9thlS~Z&73=PgO?Jw>_?%OE3lt5UV`4d0KM>k@WY^=OTl~`Zo)^5XN_O6|3B$ZxjCy(0I_0@ z#(Zb~z{X36kXZi&eRmIx4^KBXcb-avNCFGie1x`IWA1KyBuO~-&T4i45sj_I9cB8f zjoNhU+}7Ztz&cD5WstFkFprxxRN|f? zq#ZZ@Mgo7=>a_wgb~&1-1H@e7;x4Q9nZ$Cj6PD|*MLCv%(7qc@?iuNC&T^-p+JjPslaoJUJ2DBTWpNRee zC${Hrsy;Rr9F-ELVDT0Dcr!J(`m)?QC~0MiuS}rpWmJV|#GKx~w)mhpcs6#bllRIP z(tV=v(dfU?pVtNd1N|BMzDew%aws)0(GbugYrdh=(1;oHH`sh&pB1X8&{U4x${snZ zETY>Yuo;z3K#0h8xt@#ugZ>;zCdT<6=ufU{TKz{ee)KsB;;4VfpAF)xe%OEI&uH!^ zS*cnvsh-2?lmYKagZJ_juyri@1Wq+73^VkWuR%_WisI`LMMf8pg!a9k z@{11Fhj7_3&d?2~u?)NGt?Z4wY(tTw(z-A8`mF=FmD|vk^B3ZtcplQKA z8a;(t7iZ{_*6R*4;?(e?d2pOUd9wdOe>MzM{U`dfhC<|7ANbz>Re3@HXN+=*3r>#) zT${Z4b+%N_z4nU;lI$If1RfPpg(gA7|5u)0?QmlMj=0jMj6X%j%MU2 z0?rN3Lh$9an&5+ieX{Ex}}Dm}rJp5cGcpN%8w|NqgS^+VbJ zPJbrTDO}WgIkZpj7)3<1KWz#7nYBpA=ZPmM(~dZVwscA>3}6vua?a|-W>&M~;mu}o zkrEm~-;Bx!&NwQ~TMJrQvn{BXgwW;@rt`Lt^9-};{3rU8M+EdA^yiK-`x|E#LV=J> zadsRrM=#tb&4}I|xufLT5h^aTg2jAXDNY>oH9iiX)f~!i47#4i(5M$eTTFO?46Zv# z)!CuNThxxW+TzHDbUzF#3uqlUtu`*8ds1e>*+h2hXu?Fj^u6elzYbe1p~n4m$A6x5?d=$nFsjRvgfnZ z9>kuYM{b-^yz9zwd4(4OCi5>Q{s;TBRo3f?+`rkMS{(nfKY!IIRQ%uBpD=7>3sKf& z{hK6;vU-xr3WQK8kz88XFE7AZ>nmC6@NPC|d8}RfN1w12p$YHM?L3*LO6}#DlFN*N z9$L>S?PabbT|~BIZyzsvm4-=lFE%Xg3jq%Us7Xia85T!C4Y0OGE}RHJ9$0lsPN0`h zbiC+D2$<$=98&YFSAb(_p1YE|@%xl2&ekTpye(#twk~R6np{<7a4=flzKYeWBve^e zSKQR^o&{<54-sZrs@aqo=gp;&LqP!h&hXVG^w+>VA9KmAb=J#`1)5)A@L48ppFo}Vx z4IS4byj=7}75Yg#A&>5zA0OrV2QkM9z7qO*`=BlyBv+6V(%*(&7uY+)FJp$2tX*Bl z-)77a|6oQy?ihLRK*s19Z_ImBCv@)IM0OKH7q94I=KSyW=W*s=`_r<#1HptfkcM{aGs7*LV4e0 zvrZPop-fiI4ga0~)UI?cceWbdsv<0|nth}hx^dSWS+k+)Ji_(Y{Dv_$GzxgvXJVsh z>>kXt#m^cDT4B-Ht5(sa{~P@Y|KI6PUOhSnEd&_T>=H>b$=9JfB)b~RmN?Fn&&uU5 zDiM8AHC0?$%s>niax^ks1e5DKfbC;Za%-|B{Z@u9)A53K#Gj4j6?$i`s_kb-(VaZ}-R5 z&zrNO6ImFM96!T;kfAlf2BY~+LN=)2RXq4F{OPI}Ix%mud#_FvK(<|7SZ0nZi%{qD zNobqoK4T-KeH>W3?gloP6|HE~ZcUt3#buba5~owO%+9elum6-PmDN*ac=7i~Xps55 z(8*Td=%OvZ3Syx7q+QW%2a~LE?w|Xqd^9>~juSG+Tt9Sdd2S)+2^o#uGp;J(?xeIyq?k0#0cRz+t+-;Glfh$39}dh4dB{bTefjdo*Cn%1gm``06)bd zX2OdrmLue~BNBUc$`Ca0hj24u@3oh5cRS#iR>&99Lizs!f3}DK;sgET#~g7cHW)JSY;2tFqyXC*qlbf#njfMW?IOz1_W_cR8n|la|6ya4^0m zzISM~l(S@Ry*B}|ZE8uckXH^jQw6Z)#+cmYpRPu@JFS_cd`j=iS=+f)!j~NcP&>X3< zKBN?NJ8&PCLx%AZtMk5bY@Rh*7H-#%qZGIKsHRXCT;Fcv#(2Bfrqg6#?VeomS#4@p z4gaL`G==MkmFs17e6-r1@?3$CLu>_3>ZHI$3V{=r9N5QE)zR_g0G=<2tcYKwb@xv{ zu1zdhzLlLLYUnmCpbBjAXIcjS2mE;uA@_fPKX(<4{*(K;{}1=mvUebQhDHHA`fR@< z{^C`@+PkrWYvR4d>T65j(cBb7sBm7g96h;<|1gnHKi}g+WBCp1h>AjdI!fFYG68C=IyP&Ibu>Auu;~Eh?(3 z#ObxBYpspfigp_TsVJlfyFNp(KN6kH6$XotiJKwSGF8SccZEvG+2SC>dBz|)AIeeDA?!=SFxS6WDZ6`I!g>;@9?6O(zbi-c`kAw|N1GiB`c_V{ zN{t@`B;8NE*h%?P(V*hU25$FLXil%B|CPI<@Wd%#l{#+86fd8Uh1f>}Lf|wK9oo~G z3;*u#gL~d>q|jqZ(;omqWD&SJz>ON?za4doY<*BUl6@N=glXCd{nH^Z!W&`lWq6T@ zpjZlA(R+m!Xuf+n5+SAc@T9!uvI4S>ue#&$QCFeaH zifiEy5u8s<{a{;n)z?PiswGY$${R(4&_HID;DN()#0wlQU9(*hm6hX#eQtc@S!32* zh;2tU5tbNcRd>B9Okx6!K!}|UFeO7gVG~LXaR<*h>*DW3p=V=X`7(}B1W#c(CHxEh z#P}!q{Va1k>BA<>6C1=S81{Et%(i6B=T}v?|B^ctE_9S8y71DGR~ftd9f%+vt%|hh z8^P75)?xA|0F!3OYfz<=lSZe%Pkw)~Wj^J#aQZ{$<5m#!k&=p+WS`46a1Tgl)hPsz zaup6u(EbPddF97V9WWNM^U{c_t9V!}lvgLXs754d*0r&>tSs0vGK0HJpq(N6eV;J& z!H?X&&r>~L%)>-kRkN=zMp}m}q4wK)FZrsvN_oLiO!k?mZ9Pr)9 zIRPK`(2rpCl}emcYfS2lQB3|=JaJ?n_G&|=f8zz@IhcV85|=G>P&EM21WcB>QU{cc z2I(LwT_$5SUyh#GE#!;8WO)f?GdBRnVCuEEZ>Q*q5DZ}9mm<(puz|`7HDy$;IsILy zcF#L*IHQgoL()4O8S)=6uRu87^X2R_Il1GO_eAO$|l?8V^`2z|w35O{zglOSjdUA=GDZK<`SDI88L z*G^kf2tFiND_2}

I+@mY;3zuhOF+f!*ZG#CHM3P*;`4q`htS*jx@>6ET)nRe_d z^6``?Et^|GBO?ajeI0@J_wA;peg^P6ULX=~wjkGF)%7p+^Uw2}-%VOR99k6WKaqo= zG3t{v%ZD;g2L0mg=A6ae$QD~6)m&ZXN*ExU09so66Edcg^I@HK9)ERn=c*%b7l*?q zX^pcP#rNPVrK|2g<&jh0mEHhwWYFhN;O5^-;AWX*h~Z|>`qKKk`Z2=W!ARWKPF$za zYnm45$2r#z4&8R)_PiowhVQYDGwH1bvuek$9|6USv-9`TegRdaR{Pu#4MNCz-c zsE}1+1yE|_FNF;2zBSA>nZkR1e2(q~b|#Q(vjVIEn$`Xv!5`p>exEnkAG^EG*4%4V zo$zxw3tAfS7RuBEvzOx6WUx30&@tIIF|R+6s`Bc@TRhk8>{a|A>xXks#xXwo*^cfr zTi{zaDxF&9)U0`qbc4hm($EqKNw^p-mS4eh+Ut{Ze1l{s}%lGk;TJ*H0Ddc%?-B*aS&s3=e&J9}hpu4k(1h*Z@o*3w?(jx?2M- zj&cDAQp!kRsns?luT8;UpaxdbLrz5OwxjH5FC!1dlf|niS>2{0raQl5uBJMSTEt$VVC3};!S~;$S-^6cbQj?PQEl^EbESq-TY)M|W6H!C6|Pdn z?w^fiot^NWF@Jj3yDhT$yvPYoUjJepTQ)0mOcz87L{=*GyS=JvGajG4B|eZvjL@QE zKF)QQdCCee&Bf%$%RatUNMHd-HxK1I@5k7)lDV^k#jwQ_L#6rE2CxIX0C9RL(MB(= zdxPR4v-UaDTLfr1;_n{`CITbLli^0<`}mJh@w+P=daI@&8J6f@3vC`H@>I3dE`dgF za%e8tjalz>jb8q^#%St?ka<%pd|Cn1W)bZ&oJXf4ag8@+1^OgkrG5BjZ81=mmU;ml z)#JlJ)hGd{uvTc1Ikf@<^nvAX`fRIr zE+VdPn*?@woc$Dht$;jOi8I*uZ{Auqr!@BrHk`r(SiUW{h=}1ot=*+%B}8ROrhbL^ zAA?n_Yq=^~3Bl`H=Gal%f&|zPbj3*-Yo&^GnS^m^)jlE?wei7S(-pDrwt#zXI>z#} z;@VMe0KOjpHF#4W?D%tU3d@Hrzd$1<4RS*E$Lcxn3$hOT?DK;Ie=eS#0$`wMyb;;m z6BXbO{NtAZpMsh?Wx=3D249=IhQ*U~nG?oE2_EDbvS}8}Kh;aciQyP)=>{}g5 zD$~y%a^JgzKaQ$YKim;C^BC2!4>fVx!Kx^K2%|mKofRy2g5s3IY9*}Z-xah1BiD&- z4)Xsz98qVJ9knhC5uq69-Ky4R5o70>fH4ES@hMJnRE$Kt?Fr%Y3QI~Rt9tw~`c5&U zDqo%uDoWLY^qJsRX~W}uG%{+mqBCvtOV)P2HU8aVI2lared^y)T%`^Ye^I~UsSKY# zmUVo>bl+1Wr~$X21F_Ghtfc+Gr;~uL-NvR6`a=;1(Frz!MAxDZk2oZ(c@|UJEhuSjlk69+jIS9X!f@>N% z16F6chh2q{Rc1drd!LNtk+m44g`|jGr`ARrv$JyPY;!*|EFAp#^HZQwnWd8Hj6!a< zE7W!!A2^C1ier_Wt;(9j%39uAMoe;!^O0)@thrSwZzJ&`wbPI$WeoRb1pjxO@$_4W zE=13^$GnS{5a3X8U3Hn=lPL0eY*>?-zc?`*$nUPq z!p~(VTwp0y#_sE_l|RmGqA_)1p<&fZH{@7*WK?0Cvh`@J)bi(jz_!-4e`sg@{){*o zSKY&*q4#8dV3Z=sBPRhtN+UlN{ASX0<9qsNCA&&^A; zzRvelTrMxdluviA&(kA+574+zbswf`A^5|*#k}pc!CBn$X5=a_5w5vax`hsjq_Gdg zmE(piRp#4VzV%bTJ}XeLS=j5-WZO2#1gt$tLmsj@O;N{R%$l#sZ{ zJ?eF8zxV0_=ck1~2|y81v0}Y`fDqMmoz;JAM;g2mM7!7GH0&g3cR+7dPj2NZ4m+&67OXtVLaS)nA}&(ix(Vt$nvPX&M}jSPrW_3KNEl7 z5_U9u*2caK&|TgD7&(=Murl0}fPE8y`VC2sp&u;echL&xwfT~fUwufGx@`qNsS;x* z?%r*NP-}>j{;mmsexdyPm-7C?*-q8Eshj_OYqCMqjF7Z{XGxt~@M`>5iomf`hhHau z9xR%tZ@B%C?Xtb2DS7UuxPEcu*-ys5@RPIPN5C(Wg~D-p#R&0FA-g->mKW1WG`IQ& z2Hb09I@%dT+0D0DUoY!zQQMxZhew|87E{9OX`b@fw_BG~2-G@x z8>ho4;|*PJ`<4=t3wD2Td}DeGc28d34}Fet^?lWTw7oZY;o5k*RfuKbxO*PzUM661 z*>vlz6>S~JZHkty5)?P?%j=|{R-qWTD*2(} zrWYibq@VZmt`md82^4SfLmip3o>CKttB7m6Czfz;(*#QyIWYYCKocx$Bwxt*=Xc7E zx}*-JwZdNDalNQjUc)CZ?0ukxpyyXXVLPd;1M)U9-Lu%8zwxsF2R1;-zpQ^$pIVmd zexP2woRlc0KKF~+{5$mJHD!|X@oaw4EYVTLnViySomo#!?Wk+Hpv#1L`0HH_=^k9y_JPkxpOK9O~(C%VVBVXD7A}o7ju{jI&f+`u%GgEm0g#wG0Wyt)ALR!c^%kzDH^%?pd{k#OWDjXbj*}~N-3y+ zG@3zrl84X@qWmO}Iy|?SHyZ`#_=9(1XJ|w6`wZ zGiN{I-Gy6V@piE`jNr(u{y&hwoFY^=kM*$FAG4MYg*#=}>dCQ7m)3Xbc2s$tTJDA> zSEfb#%J$&1(4%e4UHqF7Qm-Z}gsv9SB4P7ZJ=#)O_|!!p>f^KZ;lsf9Gkl;~>H%L* zjKNmpijt#0{-^(S87>)&2*`_M>$E??9%gar<{5WSv%$~P2Z-74hS*Z>YwJ9&+GTy z?mFVz6OC_R*ns=-$lKnQ+3>qXv?lNUw4^=hg|MC`4&a;7t7_s z+KRNTlH0QVscwI&^iOC5$VNI%Ht3Rcfs5jr>jT*JqXCCMa79h@hAZ}d=~f(7FPrBVmsguZmT4naZ!jCqX|}_~ZdsL{?46Wg_?#h!uDuBh zh{`J8u9=}lcgd`+V{gHBZCg9xfrnLkl=dqZgsIaRwlp&f+E!^u+Ql?iZw0L<|KUID zUMYf^_RgYD&3e>5t9vu%pXIzAanN$!s&kl(J~csR{6?(%jU=(s-_?6Z_aKf%iAXx_ zcZ=OVW@Nha80&$VHf7B^Tj7PJwesC~+gNdq-B^yh+_2BeJB79d_Btv~lF)k)`zKl4 zdO-|aWiau}T53xDb<2)R4!>_^9f(LCA+VhX4>7gY2dh+lqXX9S_kWEaF4prm7g9NS zZ5HxWUet3e6PA5R@1_%_O%42^?mbZMWv!Feil6E7ty5Vk8^zFy~kb@dVl=q z|I^k!E9nXy>50VK_K@_S|4&;9lO@rkOOe{w&vell9qCZs9P*;VwsW)dpY&rON&C%X z)4(SxtPfiLd-MLO&DIJ6Gy2Cn`l<`F-O8QGU7b~`io#!D{HhRG{Vd>L;fc3u7Wk>6 z39sYf4_t=+U}S}fCpGmw>hBasq&ggy6{_Nn6}CeR?B%h0(A__FACOjm&pa62GkPl2 zmU-Zu1Y>uw7J`OL!$=-kmNJE-2U5XA?X^{nAO__L)Uu`BEZlTs)|T&8pcvRSDqwjl zb}Xw?Dv`3Q*rN80vaJ}017+E^Fuil0_=A36r<^WydqKALq~mw@I)viP$A9?$ID_lZ zQ-@93vL{_Zkm!iIH&OD$4&Fc&7n}5C2^~F|y`ECOl_=|WX-OMX>#h9_`Jtkq0amae z=u$T^ge+skw~c-#H<+F+V&#;9n8b7?XT&X15vOd*~zM-S@{NnBMCoL(+E6ybI z84(S<)p=N#D^D~VdZmvzQ>z(d+J4mzx$?s`FKT7J5bNFEm9CcOmzcKto+sbS>PkJ| zFvGk&C!{zR^NY>_ds!~#Z%n>#A`QjKMODem&H80KlA92?-a=D5>W zcD!C0cPQ9Sy_UP0?WQ_oJ7F5u?Q{(HrVU?f|Jg1+xJDOyHFs{mRy-JkR4W)vjdX<4 zg3>Hb3+!hf{gbz!Y=gS+tlL-ZBTbBE^rTxu6Wgo(x^44gx9p$1k6X)*XTxRxq?i5U z=gu9dF6t3}1KmU&N>ySFrg?UW>AJ@5 zzus4SHspGKe(C*qcKJ$oYIJ9U(}Md`Ms$;}P=EPBeJ{M_#o~jm>Lhfi}Y3Htm2Y@zGgYp7wbbtnD>vxqzY0wJAhq4Ol;%=*XSoB%rA+4EZmO zRvIy4x7kq0Gii6Rowg3&i8lajSX&iQr|0&s*P7t~;hkS@KDc{W2RzCZGiI*A!`fX8 zfVsAjes*|kDOS~4hx_L1uZTWgwr$@z?E7q}?#~ggaZTs75L=#xDc8 z|G7Y6ufJ$wS#GHP^>E7BCH@o2zwq%cT|m+OnRqL`GuZ*F>(g}C8?T3rhI6QUrnk^* z`SWWI3IDbLs@ZXZ(o1SGJP7H%96Lwp7Z^E8=@(ED$|<98)!$_Bnw_==Gj03ez?I=& zc5gZ>)?mZ3urf}^^Y-;QM(pCMc zb>uLY>Gn*~nVu0A(*4va{~_-Y4sjfR@_)2HMSl zO$;7=vPUe3ly=H;rfadPJ685L+Yg=ctuK{Ze)zCgzcuyt8yGxwzA&b>UislOBN2Wz z!VLXSUgY~NxsT4SUBe?w&Dg;|j+6u>&;$ljo#rJ@>Y^bZa9)k^5%={77ja*!NdA;3 zvRUe8Ibb9$6y!zemEJon82;Y0G|ULb*!!RUMu%#%T=#RypC#F?`e~!`ld%ftm);v2 zb7wuJM50S!b)|JMVsrRQVx| zmOo$3SIQ$$r}iLF{^1)-1@}$Y0mt8BxC`OE1LfiG%Jw|%&xYx@aJwqqU(_2`CspcT z)MUAt^HA|f^UDCzD8=j9ImY>0um-IK_*~s0a93AhxaTWSDYSDeEc@KfcHZ{6*U!yX zKfB4cd~2~0wwA&?TrXD}`z-LyvZz>DcUjcIb8jV_v@A|;6K5I@ULBOuY_?Z_%en09 zL+X<%9#n~rC_f1pO&a?rfh&6@C;#ZMgC>;>W9ppA>frBoSgPBV?w!4K*vFie&5VJ%V3ere>H2E!yHAi>a zd}BESw5RpqoB^BrJwb@~QYBIHj&!n|C-bY-?C*|$vHh;nF&IP%NX>RfHaOPIG^6#t z^DAuKlDVTaRMZu0RVcmRk5s6f2l^GxB%kf5mBC_;i_Wi}_4m%NdmQART-Eb&MAp3-17yzI5j^I+H4bu_a*!(&HC>2vxxN$?9l>VZF^Kx8 z&4sXBZn}g@Ojb5y_IFP1U;aoA_m91AdyZ-+gO}5q_zCIl8a4Hudq%$QAG;4fwt-L zP|TisNI3q954t%CW0l?F!Nb#g51uYBKdk0&&LBvuV=wf>6g2YYN|}nDF3&G{zZrg5 zT`rBo=)DIozx(pvoqj#9cJpbPN_J#KZw0I^@!x_LFJp}JPn4j~C z;y!s=O9kIQJpGl&?w=}qOFOqKDnZ`b-a68z{h)8_dXPU4xOw&A-UCyF(JBfRstDH; zg}Ic|qQZw8botacEPc=aSx)*6I1$3E#rQ~<)3p#0kEkoDX<5Ae0gWTpyN6G3aboE4Q7HXARLMhv9 zjkf4;ajgOmXtDCHY)o70s(Pj8?8aC8Cw<_Rh>GY+Q;hWae&&%iLr&Av~ z1fd3MD{78+zZZ7hOd>b8a*DaH@pxwiPxdrW+6J5iXv0RHEEczGyAEmH`E5X8{5{!ka~?*{^Pzg`9Zft`JO+0EPu}#m^waZ_-Fz0u7Z3)4@dcl6Od0H3yz;Gk)hB*oAq zG)VR1iN^rx_N@xCYPal3R}YiTu$0Z7X9{>aDN6hOMVlnW7SNenx&mz`m#ro^O+0Yh zF;g~`jAUqwvoJc-%5i^Vs`&1|{86W)Xs5)TkoCwkTx@r(8{?%jur~MaV~5G9+%zX< z4b7NaY2$r*)nz@<2@f>!oI^Y~iJyMDEeSapyj0?@v5Z~QB-5>!N}#o4#h9*Z&x+aP zT-}1Tw^QQHV8v82h_)v`oqYDiG8wt}_#c%C|7wohhkIq1Gp@%a%5|v=%<8>D7 z(EhfaP)Q$tvb`ATgDUW`oyJx&{dDX0`;zA7Ql`r|(+ZklaN$w^fd9Y$$1V3SR}DI1 zo`Dmct{(4{)NtitA7kmpKf1aQvvBD;pfcNvlz!CyqV%>u{-^(|ePEH%abJ6XD%P^o z-7l2U&X|1pV9UFL4~Gs_Z3Ny>W8bCC8&iP}^lJS$k9wdqPblV8$ zqifVpk{A$!6KB+!G1w2M-WlLn{cA1af07?gyw^&)<45RND<{}!-C-Xr4KSHDX-vBd z4ox3jm?J&M7y4jIRFx+$HY=5~iP;3q!B+cx7997C@#+N?IQ~G4tV+E)Hii}YXPQjO z+O(waPFP=EUM^@3n)577Uyx9J;O!Jp6}@MIx!kpFNZZJH!_K@0tuX(!djRsU+7q$X zuba~g5h4{!R|Y!QDO8_ebfLiK&O)c z1+B!2;FU&Ra$?c%zxpflV{kmkW9_mII)sE8}YPAL0^=pF@e>CM^wRJd)=&G}-TTVS@zRgcc-z`sU>)o{WGoLxu zB3B)HZT_br@N36pq{rmgu)ASF2RyE95`yUIF;+%}13r#BgVvAu!D zgU`3lp9fSv5rE!$uCGk+`St*<2v-s3E^KY#KPAyg2b1WpX@61XDchq@C(f|+PqW}; z2V2l(Ku<0|=s|}q=5XBBcNi^jUHy}`H^;9|Cin^py2Uzhjao7O7WW=uu9Qnw7lh-S z3-rx2y=0=38cX}=h|gxaJt2k1f5f7bwQlJy-ILMk4lyzH-%eJeHkD>o z)|prN^fCRew)cP!Si_C_Q7ioXaimT@*6Ju&Q#ZhaEE;2_cK5rrUug4%>G!JZRYl(742RA$d%^?~kO z9nPBTc)jw&rQoY!o$UyiG z!_re=j$Q)CGS3PDCliF&p^X64J?Rd#gtjqdV2f>VPa0#3S2N3zKpUC|RWr?Ks#Yzu z^|U+qvDf0Qqa#(GNxgQdJ7r(pIi8`VFWWY419qI+(q`+m#6k!oRGl>5GeahNpcqvL zkQL9?ik#lxw#qTd)4p?skNa>Se-!F&-%rCvJywND4YKMm6V>w{2dvS~t1kRXXSM#K zpVRQToufr}5(1Fe>-zt%YSMhdb(i&k8pp$kL0sppu4l28LXXzjhomsXWRTvk2by+Ka zlM&UQ`NO;ohwLqzdk?xqUu~AJ)<>qh+LF0~c^Bh3S_Ug^#C*Z{atwx4ue{|PPRZZ< zd{VJ^>#^-*snTgt+uvw2u5Emo`lbuN={c+SEqB{b%*J@#ZSyX%=(x?m>co}4<+?RJ zIqBWp#7@TPWm1Kw64RYzaveIZJ$~5QnAMH`9`0G|(m{3ts z?62D+S9esU>%TKTBwfTE&va(H;hcftMP>@kcNf%||p_R4`lj;&Qefy0q%PUS0p|y8F7m{?}Fab#?8p)l|^9XpT^O zOJixR-7JFV^6flYHcUfx>)_MPvhwHAH)HDNKXnak8&OEGTy8`@t-z@q zDsgo{JAY0F$!?ZgJk}W$Pu!%ElOrgTjbDL+j0aHr`@uCiZaxzi zCvLqNsYMkwH7$XfmAa;W*pGd7dLn-%MK2V2=lh%cA@{3s+>j$b{FAsL@4$d#j>*a+$c$J&iOAQ*&#rqes`V!N3=0#za z=EJvtFU4w8VhC%z_thWA`FXuj@^73bw4T$J{rPISUDguFpsYHT8>`vS%b>V*Uf=q_ z5RfhIo;kn7rV^|9a>u#z_*os_>_6($sv@_`QQoi5Z zKbe|WQ$Y3T#A$_R0Jf6qYzek;imqRxBCeAU)m6LrPE@Nu;komV$_xEfXH47q#mh@+ z?0w9X^L6|6o~~ItiRoUjrxo;Tfe~mIb^rLlzVR!CP@FIK^ozy2DLbT3$~j*R`Uc%{ zKR%#m!410BZ{&tu98@yZ)n`AS{zKcvi3W69s9kTZF=VP0vW-)K@rxR5k+B35#NF~2 z?YGY_K%a&b90Kpyb^C=XtY%@@q<(AjV<&);gxY+TR(oix2J0L7RB8Q-|$h)j4JCb?4ns$3#nH^Dr;i6MXTN`kE$LX-b}#D}%lD@(0z2(Ygd-x-0)%q;eka+oN~~fh zAPG2jR5r$N?d!uxdRYD%V`oQu;&NYSM}+BCXAhC36FokFkiHZ1Rez;+_nN0sBND@X zt-5Wyx?}VQ$PZ4cQbzA&{Z&oZq5%8FHE2M0w*@D6)7=BH%Vf6?V|-or?}~_fLpYp_ zNBVylAs@^s3>i=MfbXAOlU;P*97ry0mk*w9)$JYg-Rt&sW_+aY2h2J2r&Esb{zVB0l!wYqr5{vA+QWtWDrrethf|*KDT? z#d2FSP_sR%q!r3PR#`ZsYc?S2dbku5gF(q|ENIR7`S{vvgvz#rdpm35{Bj|UbiY=u z=T`@;Itq1t51nyD7)N^j77v`hUbD&dr|;ea*j2KcTwL}U7yFP57xWwn^2xodXk(soB5 z5}MR?@0P22JvJL?zZZ`!SF7d9xqs6>U;gCY!Z|`bG={dpu1DJKeLYilvbEFfS~sgZ zY-jv#YU|Bf-+=ec)yCw#nl#`|x-;>mbR$NIhMD;-yRNa5If@L*&rTNP6cpAlS>c8zX=Mklf@rxxWU zO+k}Y=|$0HcGjiZq~?3=HL-cfM%QG-Rx`aI+l6dl{5Ig2Q3ES#bCg?vhOx7)YTH}_6kBar2G|E>y5pg4AtpN#O^)lxuf&48J&(D zW7Q?vKKJuVXvIOM-t&6Kvv4Pg65XFG?YBl8cdl{V zxr5`*XSOeYu-M!HO{a=W?FwXl(JOq_PS}pm-nmTT`s%_+)#mrHiiV$7*R+F{4c-hR#Hf&zEhtL-OZUJe{bH`KgD$l2}7mf?n zmoCX4F#z6qGFIR8YwJ$CDpM5Fcm2t0q5W`DopXE$l{Opg zslH(t(n6|yqhM}w4L(aL^G;_HI;>kOsSJAFC&$o`pLB_8PtWITa)i^3HWUx%UL_KC z(g*hy#Wn}-&;88vAMrr-jSvDc|DJva(TS5@_>^@muQsPDb^EpZ-f@d{ z|7L@=N+Q3WIX4_!qfcr!^$7rz)ZM;c-S2G*E}g4hO{?jw-B9alHNPAn53egWb4%!| z+B7yJMP??cjddYy^!9BG^{LEz_)?puKk5Hncfz`}PVSLY73c6d=4`&)2t7>x)G?R6 z{SC8|HktA*NzR%@FZu*`G1&)W=ycGF<@5@^3^?+B6r(d47$en>KrluezWVhp1ma+y zX&ctA3XF~M(c{h@TkXXqw*VKn1u91d&#}{^kYy+$T}1Lbdl89VH?!t8Vnt75Yxmy` z()Vi|E$+~w@Vog%-`r}OwVw0+!0B!ZdZE+I0K`xxwVM?pAXA&FTO*C@Ro}%yxlZl_ zMfKRmgE{1HuN*qEC{1-jg*W#N%)4N`yCk=#T9w40i;vJ9s~mdXNrd{tjug%BmLScq zEs2}oM@aI=js#BH1$*TZW}8sReBn$(YkpTT&y$Av*VZo3v(2kC_pZXAR(snPKWc{W zIQ8?3H>*+1K910pHQNaXvxGA5SJR@`VfC&Tss)l}T2DFM-6@uupk7dTOYZ&Pu^v*r z-&RJA`c#EXpDuw4s88>x+!`B3TIg6&7u3-Ob(s)e^_$M;8yxq0giYQ0l(%EOknhI2 zRMJ1M9k7iHtV~iEWh7u?n65GZ*lnu5x?CtN^>%Yw_4124zm3lH{NmI`T%PJ|N(VLA z1}s_j-)rh*=OVZ5p>5lZ(Wd+J=|HQ`qP~gW$3*g|z&+U(iPUnH+vSK-B#)Ip*A08Mo$M3Tm&WzA&tz zP1bj49r}Y$UF2Px)}^0dNQI~CNA9{irce{QYmom>+7H%U;L2o9QG$Qcz0bX;W1p$C zt6Rq!9YR0hf%IbuN7sA+)$~F&doo(Zxtz`G_a`>&kumvB$%rCxD@XT#%{j2*Q&*b}Wn=iC&S>4d`X*Pcksz2@`iw_FBzF}M7 z#BNh6N?LA2EwoO^{WfFB(CnP)(=;&fyrcV?2(X`ZM3Hyo)NM&bHF0bMFpuuHF{V?W zZ3Ux_*1*`)gKA*GVGRaqJKv9othUj&TXW`A*4{nct4^mzba9AIO|q*dBM|!)jbfU~ zx?XiOtEga`1k9q%e!o`qbz~Qs*UM}+A1K}L|9iY?nF*V8_n85eTib19kE#1iNUCkH zQ$L>m8p^Z2{pbioyIRZDGX1RDbl>pxtBZw7t!^EGD&~He zsCYc4a8J#B$DUo)KMi$ZPrk1fSL3skE z=X}@P=py=qUf0iW)O9Q4Zg843(Zh4A#*EX&pqt(SbGK#nAD=yIf7&&DHs$EP`BNNU z=W|m7R!slLqgEZGk>pY#=}x!harS);wYt|<-93Ia(Q9iq(8~FA&#m|$>G|EQd*A#p z)|2+`wjH~F_u7867Lw}N8eh(hv9n$AElqiR?kvjMwc@6#&%R^!Zw%X$yVxMDhInDF zRx^9`laWC{>=&EGh4-)jppWiHAwNxy;TY9}Z)1A3umQ`XpXXFu?G+-$zC zg3+T>2S_MK8S|B`t^0b*iaGq=Y=`YHk3y5zyDMuZe!J`hICffbgvue4b9Eu#U#dpb zs=H{yx7~VmJfjbSMb%?j72H^LeRN9$r!r>Qh-H)QSPOn=j#1c&{<*&2(L(*d@dAf% zK^)Rj$Nj6dcq1QK?+IC-HoE20jmqTo+t?KlyMs0u zj-STyU+BPmzyEI#WKkH|XZm>%`(gSQo__~z@BMQHguL>+U!ti$$3GwMdER|>z2Xb` zc22Z+|B-iJlyNAtLWUxiVHzYNszfTAB9H1M@S7-${Uj4nexG+T-k-mBzl~&;ZE%GSL{2^q!PZ2k~AplAPr>M#CaGbX;_s_Ektd5^)wt*oTq6NhmmNaFfU`7=VgJ9 zWi6UKZh|OiB8i&wCNA?zHv#5zND~(^a6~}{$lPVW72$Cp?g3ymD{F{YooYX}j ziZaZLs^R2T1-jgnVcbN8NaCbOinxl>Ja;CUOl6HaKdRf8?;A^%zR|Qx5~Fg%sFn*M ziaSPyE}EpS(?X_o6*RIeRLfiKd znafq%Oc`*}il(gn#xDXttAnt@DwcInRZUvUBoTR#B{FF8pb=@_Br>X-GDw>=%FJ4C zH3QW6R$fpqY8#3JS?3_VpuiZCtd7H?siQ!o_!l+hvF|ss2rD$%WI~`sk%mDD+AE{V zm(_SfFQll>L^)rOUD~GVG>ub{)JYT;q7KR`39BfoF;OXKsg`jW1Zj;yfF`P_3~Ih^ z60DdA^DxbZO*yV(55KsYFSlLp(Tlug_eQS9d#CM_-EAPedm(^`cxkAs42 zyveHs^qPpKs3W|I4rxr|p|;7e2r`VO4x1*#bk>rOtPbuZF0h~mthsB z;D8mm6ZSvob7yN;Z{7gov~2}h80U2^F=e2Trl~X8$PmI*G9yevoA#*f7I`AeHPx z83m9j=+I;f4>izl8>(bfWQh=|$iv1DeNm@X5sD-wZ%^u|EHNqp_|g<;AOkOuc`1q- zTVFta$Q=#UN->7g(YBSA*qt(sWRsV92xgyxvLx!s_()>q3re>nhFAr8U7Vnu1kf{qtBz@UX0saTY?- zhhgr6fnut$$M&{$0p+q04(CY0?&7E@uyml4D$X0U6^H=zP$YgC)nyh}0!*+fiwvY1 zg%HS)09oGTbzJROI^81A5za52=}fRs{UU4%OinJr1tW^JBrPyf369}MAVx?Z0FV-G zgRkX&RaYUFwTzN_idCV(r)RSI$q||04qydoUV>|cbx{GHq*;iKS_u(^S(G((ku`-x z?QxVPNr^2Mgbf6PEb=55(=DmHa=S�N;e40L?U&FMLdv4*?3cP}Dg%ah9c!J?Oqn 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

LHyiDJh1qd#cZthupr%a1Co2ZEVP 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

V1Di=8cG7 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 Uho28We~v%@FL_T#BLLvz1mZasbpQYW literal 0 HcmV?d00001 diff --git a/Tests/Ix/Catalog.lean b/Tests/Ix/Catalog.lean index 5443fee08..7d5a1bd00 100644 --- a/Tests/Ix/Catalog.lean +++ b/Tests/Ix/Catalog.lean @@ -18,8 +18,8 @@ members_root drift, non-topo deps, path-traversal labels). - Strict-anon compile (`rs_compile_env_anon`): §5 empty, §3 hints SURVIVE (the `finalize_hints` ordering pin from the plan's risk - table), and the env root equals the named compile's — the - anon-invariance the old C5 suite asserted, now structural. + table), and the env root equals the named compile's: content + identity is independent of source names. -/ module diff --git a/Tests/Ix/CatalogDedup.lean b/Tests/Ix/CatalogDedup.lean index 8d613d446..dea1b36b7 100644 --- a/Tests/Ix/CatalogDedup.lean +++ b/Tests/Ix/CatalogDedup.lean @@ -1,6 +1,6 @@ /- Cross-process anonymous dedup gate (`--ignored catalog-dedup`) — the - re-homed C2/C5 invariant from the retired union-loader suites. + content-identity invariant from the retired union-loader suites. The RelocFixture collision pair (packages A and B, both declaring `Collision.Tree` with DIFFERENT definitions, sharing the toolchain @@ -13,8 +13,7 @@ in anon space (names play no part in catalog identity). - Shared content dedups: the union is strictly smaller than the sum of the pieces — the shared base's constants got IDENTICAL - addresses in both processes (the old C5 audit's invariant, now - structural: content addressing is name-independent). + addresses in both processes: content addressing is name-independent. - Genuine difference survives: the union is strictly larger than either piece — the two `Collision.Tree`s are distinct content at distinct addresses, coexisting without any namespace work. diff --git a/Tests/Ix/Compile/LevelSpellings.lean b/Tests/Ix/Compile/LevelSpellings.lean index edf68641c..6f318dbe3 100644 --- a/Tests/Ix/Compile/LevelSpellings.lean +++ b/Tests/Ix/Compile/LevelSpellings.lean @@ -19,7 +19,7 @@ Consumed by: `validateAuxClosure` (validate-aux / aux-gen-diff / decompile-diff), and — via the Tests binary env — the whole-env tc-roundtrip and kernel-ixon-roundtrip suites, where the stage-1 - spelling decorations (Lean `Ix.Tc` + Rust kernel) are load-bearing. + spelling decorations (Lean `Ix.Kernel` + Rust kernel) are load-bearing. Import note: `Lean.Elab.BuiltinEvalCommand` (the `run_cmd` elab), NOT all of `Lean` — the roundtrip suites' envs are this file's module diff --git a/Tests/Ix/ImportIxe.lean b/Tests/Ix/ImportIxe.lean index e20e70b63..517822166 100644 --- a/Tests/Ix/ImportIxe.lean +++ b/Tests/Ix/ImportIxe.lean @@ -1,5 +1,5 @@ /- - Materialization FFI + `import_ixe` tests (plan C6/C8). + Materialization FFI + `import_ixe` tests. A self-contained fixture environment is built by direct kernel `addDecl` on an empty env (no Init, so the compiled `.ixe` is closed @@ -11,7 +11,7 @@ max/imax level polymorphism, and opaques. Gates: - - C6 parity: `rs_decompile_env_consts` output matches the original + - Materialization parity: `rs_decompile_env_consts` output matches the original constants field-for-field (types, values, level params, hints, recursor rules — the round trip is exact on this fixture). - Root equality: recompiling the materialized constants reproduces @@ -263,7 +263,7 @@ private def roundtripTest : IO (Bool × Nat × Nat × Option String) := do if status.ungrounded.size > 0 then return (false, 0, 0, some s!"fixture compile ungrounded: {status.ungrounded}") - -- C6 parity: materialize everything and compare per constant. + -- Materialize everything and compare per constant. let materialized ← Ix.ImportIxe.materializeIxe path if materialized.size != original.size then return (false, 0, 0, some s!"constant count: original \ diff --git a/Tests/Ix/IxVM/Exploits.lean b/Tests/Ix/IxVM/Exploits.lean index 33419a0a7..81201043f 100644 --- a/Tests/Ix/IxVM/Exploits.lean +++ b/Tests/Ix/IxVM/Exploits.lean @@ -430,7 +430,7 @@ position, the type reconstruction — EXCEPT `minor_var` (`Kernel/Check.lean:2573`), where `n_minors` ALONE selects which binder each canonical body points at. IxVM never compares the prover's declared `motives`/`minors` against the reconstruction; both references do -(`inductive.rs:4945`, `Ix/Tc/Inductive.lean:2346`, error "arity metadata +(`inductive.rs:4945`, `Ix/Kernel/Inductive.lean:2346`, error "arity metadata mismatch"). -/ /-- Replace the innermost (non-`lam`) body of a `lam` telescope, keeping @@ -592,7 +592,7 @@ argument — the `[self : SizeOf Unit]` instance is never read. But `SizeOf` is a one-field class, so its instance is prover-chosen: `@SizeOf.sizeOf Unit ⟨fun _ => 5⟩ ()` is `5` in Lean (project the field, apply). lean4lean unfolds the instance and computes `5`; IxVM answers -`1`. The reference IxVM kernels (`whnf.rs`, `Ix/Tc/Whnf.lean`) share the +`1`. The reference IxVM kernels (`whnf.rs`, `Ix/Kernel/Whnf.lean`) share the blindness, but lean4lean — the ground truth — does not, so the three do NOT agree and IxVM is free to follow Lean. -/ diff --git a/Tests/Ix/Tc/AccelDiff.lean b/Tests/Ix/Kernel/AccelDiff.lean similarity index 93% rename from Tests/Ix/Tc/AccelDiff.lean rename to Tests/Ix/Kernel/AccelDiff.lean index e9f096ae1..b7ad2f9a5 100644 --- a/Tests/Ix/Tc/AccelDiff.lean +++ b/Tests/Ix/Kernel/AccelDiff.lean @@ -1,8 +1,8 @@ module public import LSpec -public import Ix.Tc -public import Tests.Ix.Tc.ParityEnv +public import Ix.Kernel +public import Tests.Ix.Kernel.ParityEnv /-! `tc-accel-diff` (ignored runner): differential fixtures for the @@ -12,7 +12,7 @@ BOTH kernels (BitVec natives, Decidable natives, `reduceBool`/`reduceNat` markers, `Fin.val`-through-`Decidable.rec`), so cross-kernel diffing is structurally blind to a common bug — these fixtures check accelerated results against genuine pure reduction over the real env (compiled on -demand — see `Tests.Tc.ParityEnv`; the pure path needs real definitions +demand — see `Tests.Kernel.ParityEnv`; the pure path needs real definitions to delta-unfold). Small literals only: the pure path is exponential in literal size by design (see `TcState.noAccel`). @@ -23,10 +23,10 @@ Comparison discipline: representation-producing accels (BitVec→Nat, the canonical accel proof term is a different-but-def-eq witness. -/ -namespace Tests.Tc.AccelDiff +namespace Tests.Kernel.AccelDiff open LSpec -open Ix.Tc +open Ix.Kernel abbrev AE := KExpr .anon @@ -73,7 +73,7 @@ def ctorCase (ixonEnv : Ixon.Env) (name : String) (e : AE) public def run : IO UInt32 := do IO.println "tc-accel-diff" - let path ← Tests.Tc.ParityEnv.ensure + let path ← Tests.Kernel.ParityEnv.ensure let bytes ← IO.FS.readBinFile path match Ixon.deEnvAnon bytes with | .error e => @@ -99,4 +99,4 @@ public def run : IO UInt32 := do ok false == ok true && ok false) : Bool) lspecIO (.ofList [("tc-accel-diff", [seq])]) [] -end Tests.Tc.AccelDiff +end Tests.Kernel.AccelDiff diff --git a/Tests/Ix/Tc/AnonDiff.lean b/Tests/Ix/Kernel/AnonDiff.lean similarity index 96% rename from Tests/Ix/Tc/AnonDiff.lean rename to Tests/Ix/Kernel/AnonDiff.lean index 7ef55e177..865018fe2 100644 --- a/Tests/Ix/Tc/AnonDiff.lean +++ b/Tests/Ix/Kernel/AnonDiff.lean @@ -1,7 +1,7 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel public import Ix.CompileM public import Ix.KernelCheck public import Ix.Meta @@ -12,7 +12,7 @@ Anon verdict differential (`tc-anon-diff`, ignored suite). Compiles Lean closures through the Rust compiler, writes the serialized env to a temp `.ixe`, and compares per-target verdicts: Rust kernel -(`rsCheckAnonFFI`) vs pure-Lean `Ix.Tc.checkEnvAnon` over the same bytes. +(`rsCheckAnonFFI`) vs pure-Lean `Ix.Kernel.checkEnvAnon` over the same bytes. Lean verdicts carrying a "not yet ported" stub message are counted and skipped — a guard from the incremental port, now expected to count zero @@ -20,10 +20,10 @@ since inductive/recursor validation is in. Every other verdict must agree (pass/fail; messages are not compared). -/ -namespace Tests.Tc.AnonDiff +namespace Tests.Kernel.AnonDiff open LSpec -open Ix.Tc +open Ix.Kernel public section @@ -126,4 +126,4 @@ public def suite : List TestSeq := [diffSuite] end -end Tests.Tc.AnonDiff +end Tests.Kernel.AnonDiff diff --git a/Tests/Ix/Kernel/CheckPrimeGaps.lean b/Tests/Ix/Kernel/CheckPrimeGaps.lean index c972e606b..d876b270c 100644 --- a/Tests/Ix/Kernel/CheckPrimeGaps.lean +++ b/Tests/Ix/Kernel/CheckPrimeGaps.lean @@ -71,7 +71,7 @@ def testRustCheckPrimeGaps : TestSeq := ) .done def testLeanCheckPrimeGaps : TestSeq := - .individualIO s!"Ix.Tc check {focusConsts.size} inlined PrimeGaps consts" none (do + .individualIO s!"Ix.Kernel check {focusConsts.size} inlined PrimeGaps consts" none (do let names ← filterFocusConsts focusConsts let leanEnv ← get_env! let (_, closedConsts) := diff --git a/Tests/Ix/Kernel/CheckTauCetiReduction.lean b/Tests/Ix/Kernel/CheckTauCetiReduction.lean index 3af61243b..fc9cbb78f 100644 --- a/Tests/Ix/Kernel/CheckTauCetiReduction.lean +++ b/Tests/Ix/Kernel/CheckTauCetiReduction.lean @@ -58,7 +58,7 @@ def testRustCheckTauCetiReduction : TestSeq := ) .done def testLeanCheckTauCetiReduction : TestSeq := - .individualIO s!"Ix.Tc check {focusConsts.size} inlined TauCeti reductions" none (do + .individualIO s!"Ix.Kernel check {focusConsts.size} inlined TauCeti reductions" none (do let leanEnv ← get_env! let (_, closedConsts) := Tests.Ix.Kernel.TutorialMeta.collectDepsWithExtras leanEnv {} focusConsts.toList diff --git a/Tests/Ix/Tc/CheckTests.lean b/Tests/Ix/Kernel/CheckTests.lean similarity index 98% rename from Tests/Ix/Tc/CheckTests.lean rename to Tests/Ix/Kernel/CheckTests.lean index f5026dc06..6e22b7481 100644 --- a/Tests/Ix/Tc/CheckTests.lean +++ b/Tests/Ix/Kernel/CheckTests.lean @@ -1,24 +1,24 @@ module public import LSpec -public import Ix.Tc -public import Tests.Ix.Tc.IxonFixtures -public import Tests.Ix.Tc.IngressMetaTests +public import Ix.Kernel +public import Tests.Ix.Kernel.IxonFixtures +public import Tests.Ix.Kernel.IngressMetaTests /-! Constant-checking tests: `checkConst` dispatch (axio/defn/theorem/quot paths), well-scopedness validation, the safety lattice, defn-block coordination with failure replay, the lazy-fault driver end-to-end (`TcState.newLazyAnon`, -`checkEnvAnon`), and the parallel driver (`Ix.Tc.ParCheck`: +`checkEnvAnon`), and the parallel driver (`Ix.Kernel.ParCheck`: `ingressAnonEnvParallel`/`ingressMetaEnvParallel` + `buildCheckWork` + `checkEnvParallel`) against the sequential verdicts. -/ -namespace Tests.Tc.CheckTests +namespace Tests.Kernel.CheckTests open LSpec -open Ix.Tc -open Tests.Tc.Fixtures (storeConst storeMutsWithProjs axiomA envA) +open Ix.Kernel +open Tests.Kernel.Fixtures (storeConst storeMutsWithProjs axiomA envA) abbrev AE := KExpr .anon @@ -515,7 +515,7 @@ def cacheIsolationTests : TestSeq := Acceleration substitutes native semantics for the declarations at the hardcoded primitive addresses, so those must verify even when the caller -skips integrity checking (`Ix/Tc/Primitive.lean` at `primAddrSet`). -/ +skips integrity checking (`Ix/Kernel/Primitive.lean` at `primAddrSet`). -/ def primVerifyTests : TestSeq := test "prim-addressed constant is verified even under verify := false" @@ -912,7 +912,7 @@ def recursorTests : TestSeq := failsContaining ixon recAddr "populate_recursor_rules_from_block: canonical header mismatch" : Bool)) -/-! ### Parallel driver (`Ix.Tc.ParCheck`) -/ +/-! ### Parallel driver (`Ix.Kernel.ParCheck`) -/ /-- Env with two passing standalones (A, idA) and a passing inductive block (B, B.mk) — 4 targets, mirrors the `checkEnvAnon` lazy test. -/ @@ -1003,7 +1003,7 @@ def parallelTests : TestSeq := run2 passed={r2.passed} fails={r2.failures.size}") | e1, e2 => return (false, 0, 0, some s!"{e1.isOk} {e2.isOk}")) .done ++ .individualIO "parallel meta check over meta fixture env" none (do - let (env, _, _) := Tests.Tc.IngressMeta.envMetaDefn + let (env, _, _) := Tests.Kernel.IngressMeta.envMetaDefn match ingressMetaEnvParallel env (chunkSize := 1) with | .error e => return (false, 0, 0, some s!"ingress: {e}") | .ok kenv => @@ -1023,4 +1023,4 @@ public def suite : List TestSeq := lazyTests, cacheIsolationTests, primVerifyTests, inductiveTests, recursorTests, parallelTests] -end Tests.Tc.CheckTests +end Tests.Kernel.CheckTests diff --git a/Tests/Ix/Tc/Roundtrip.lean b/Tests/Ix/Kernel/CheckerRoundtrip.lean similarity index 92% rename from Tests/Ix/Tc/Roundtrip.lean rename to Tests/Ix/Kernel/CheckerRoundtrip.lean index 44a990b5b..783f0cd54 100644 --- a/Tests/Ix/Tc/Roundtrip.lean +++ b/Tests/Ix/Kernel/CheckerRoundtrip.lean @@ -1,13 +1,13 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel public import Ix.CompileM public import Ix.CanonM public import Ix.Meta public import Ix.Common -public import Tests.Ix.Tc.AnonDiff -public import Tests.Ix.Tc.IxonFixtures +public import Tests.Ix.Kernel.AnonDiff +public import Tests.Ix.Kernel.IxonFixtures /-! Kernel ↔ Ixon roundtrip (`tc-roundtrip` ignored suite + `tc-unit` entries). @@ -18,12 +18,12 @@ Two halves, mirroring the Rust `kernel-ixon-roundtrip`'s scope: ingressed into the pure-Lean kernel, egressed back to an `Ixon.Constant`, and compared **structurally** against the original (canonical forms — sharing expanded, tables renumbered, universes reduced; see -`Ix.Tc.Egress`). Projections compare byte-exact. Certifies exactly the +`Ix.Kernel.Egress`). Projections compare byte-exact. Certifies exactly the kernel-held, hash-relevant structure. **Meta** (full fidelity): the whole env is meta-ingressed (phase-parallel: chunked local envs merged via `KEnv.union`), every named entry is egressed -back to `Ix.ConstantInfo` (`Ix.Tc.EgressLean`), and compared against +back to `Ix.ConstantInfo` (`Ix.Kernel.EgressLean`), and compared against `CanonM.canonConst` of the source Lean constant with Rust `compare_envs` semantics — LEON content hashes are name/info/mdata-sensitive, so this certifies metadata fidelity too. Skipped with counts: aux-rewritten @@ -41,18 +41,18 @@ Layers: this module's closure plus the level-spelling fixtures) — anon and meta. Parallel over the task pool. Arbitrary Lean files (and external `.ixe` images) go through `ix validate-lean` instead, which - shares the same drivers (`Ix.Tc.Validate`). + shares the same drivers (`Ix.Kernel.Validate`). -/ -namespace Tests.Tc.Roundtrip +namespace Tests.Kernel.Roundtrip open LSpec -open Ix.Tc +open Ix.Kernel public section /-- Roundtrip every work item of an env (shared driver: - `Ix.Tc.anonRoundtripEnv`). -/ + `Ix.Kernel.anonRoundtripEnv`). -/ def roundtripAll (ixonEnv : Ixon.Env) : Nat × Option String := anonRoundtripEnv ixonEnv @@ -66,7 +66,7 @@ def fixtureEnv : IO Lean.Environment := /-! ### Fixture roundtrips + tamper negatives (`tc-unit`) -/ -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- All hand-built fixture envs roundtrip clean. Exercises: axioms, defns with refs, nat/str literal blobs, `share` normalization, mutual `recur` blocks with projections, inductive blocks with ctor projections. -/ @@ -92,7 +92,7 @@ def fixtureTests : TestSeq := Id.run do ts := ts ++ .individualIO s!"roundtrip fixture: {label}" none testIO .done return ts -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Ingress a standalone fixture constant and hand back `(original, kernel constant)` for tampering. -/ def ingressedStandalone (env : Ixon.Env) (addr : Address) : @@ -119,7 +119,7 @@ def tamperCaught (original : Ixon.Constant) (tampered : KConst .anon) | .ok (some _) => true | .error _ => true -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Standalone recursor fixture (`R.rec`-shaped): one rule, for the dropped-rule tamper. -/ def envRecrStandalone : Ixon.Env × Address := Id.run do @@ -130,7 +130,7 @@ def envRecrStandalone : Ixon.Env × Address := Id.run do let addr := Address.blake3 (Ixon.serConstant c) return (env.storeConst addr c, addr) -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Standalone defn whose value is a `letE` (for the nonDep-flip tamper). -/ def envLetDefn : Ixon.Env × Address := Id.run do let (env, aAddr) := envA @@ -143,7 +143,7 @@ def envLetDefn : Ixon.Env × Address := Id.run do /-- Tamper 1: swap a defn's value for its type. -/ def tamperDefnValue : Bool := - let (env, _, idAddr) := Tests.Tc.Fixtures.envIdA + let (env, _, idAddr) := Tests.Kernel.Fixtures.envIdA match ingressedStandalone env idAddr with | .error _ => false | .ok (orig, kc) => @@ -209,7 +209,7 @@ def unitTests : List TestSeq := [fixtureTests, negativeTests] constant of the resulting env. -/ def roundtripOnSeeds (leanEnv : Lean.Environment) (label : String) (seeds : List Lean.Name) : IO (Nat × Option String) := do - let consts := Tests.Tc.AnonDiff.closureOf leanEnv seeds + let consts := Tests.Kernel.AnonDiff.closureOf leanEnv seeds if consts.isEmpty then return (0, some s!"empty closure for {seeds}") let dir ← IO.FS.createTempDir @@ -222,7 +222,7 @@ def roundtripOnSeeds (leanEnv : Lean.Environment) (label : String) | .ok ixonEnv => return roundtripAll ixonEnv def seedSets : List (String × List Lean.Name) := - Tests.Tc.AnonDiff.seedSets ++ + Tests.Kernel.AnonDiff.seedSets ++ [ ("inductives-recursors", [`Nat.rec, `List.rec, `Acc.rec, `WellFounded.fix, `Prod.rec, `PSigma.rec, `Or.rec]), @@ -254,7 +254,7 @@ def closureSuite : TestSeq := Id.run do let mut ts : TestSeq := .done for (label, seeds) in seedSets do ts := ts ++ .individualIO s!"roundtrip closure: {label}" none (do - let env ← Tests.Tc.Roundtrip.fixtureEnv + let env ← Tests.Kernel.Roundtrip.fixtureEnv let (rows, err?) ← roundtripOnSeeds env label seeds return (err?.isNone, rows, 0, err?)) .done return ts @@ -266,7 +266,7 @@ def closureSuite : TestSeq := Id.run do `ix roundtrip-tc ` instead. -/ def wholeEnvSuite : TestSeq := .individualIO "roundtrip whole get_env environment" none (do - let leanEnv ← Tests.Tc.Roundtrip.fixtureEnv + let leanEnv ← Tests.Kernel.Roundtrip.fixtureEnv let consts := leanEnv.constants.toList let dir ← IO.FS.createTempDir let path := dir / "tc-roundtrip-whole-env.ixe" @@ -293,10 +293,10 @@ names are informational `notFound`; aux-rewritten entries fidelity is covered by the anon roundtrip above). -/ /-- Compile `consts` through the Rust compiler and run the shared meta - roundtrip driver (`Ix.Tc.metaRoundtripEnv`) against `leanEnv`. -/ + roundtrip driver (`Ix.Kernel.metaRoundtripEnv`) against `leanEnv`. -/ def metaRoundtripOn (leanEnv : Lean.Environment) (label : String) (consts : List (Lean.Name × Lean.ConstantInfo)) : - IO (Ix.Tc.MetaRoundtripReport × Option String) := do + IO (Ix.Kernel.MetaRoundtripReport × Option String) := do let dir ← IO.FS.createTempDir let path := dir / s!"tc-meta-roundtrip-{label}.ixe" let _ ← Ix.CompileM.rsCompileEnvBytesFFI consts path.toString true @@ -322,8 +322,8 @@ def metaClosureSuite : TestSeq := Id.run do let mut ts : TestSeq := .done for (label, seeds) in seedSets do ts := ts ++ .individualIO s!"meta roundtrip closure: {label}" none (do - let env ← Tests.Tc.Roundtrip.fixtureEnv - let consts := Tests.Tc.AnonDiff.closureOf env seeds + let env ← Tests.Kernel.Roundtrip.fixtureEnv + let consts := Tests.Kernel.AnonDiff.closureOf env seeds let (report, err?) ← metaRoundtripOn env label consts return (err?.isNone, report.checked, 0, err?)) .done return ts @@ -331,7 +331,7 @@ def metaClosureSuite : TestSeq := Id.run do /-- The centerpiece: meta roundtrip of the WHOLE current Lean env. -/ def metaWholeEnvSuite : TestSeq := .individualIO "meta roundtrip whole get_env environment" none (do - let leanEnv ← Tests.Tc.Roundtrip.fixtureEnv + let leanEnv ← Tests.Kernel.Roundtrip.fixtureEnv let (report, err?) ← metaRoundtripOn leanEnv "whole-env" leanEnv.constants.toList IO.println s!"[tc-meta-roundtrip] checked {report.checked}, \ @@ -344,4 +344,4 @@ public def suite : List TestSeq := end -end Tests.Tc.Roundtrip +end Tests.Kernel.Roundtrip diff --git a/Tests/Ix/Kernel/FocusedLeanCheck.lean b/Tests/Ix/Kernel/FocusedLeanCheck.lean index 50a507c00..7919cd400 100644 --- a/Tests/Ix/Kernel/FocusedLeanCheck.lean +++ b/Tests/Ix/Kernel/FocusedLeanCheck.lean @@ -32,7 +32,7 @@ def checkClosure (tag fileStem : String) {status.ungrounded.size} constant(s); first: {first}") let bytes ← IO.FS.readBinFile path - let cfg : Ix.Tc.ParCheckCfg := { + let cfg : Ix.Kernel.ParCheckCfg := { workers := 1 verbose := true progressMs := 0 @@ -43,7 +43,7 @@ def checkClosure (tag fileStem : String) let only := names.map fun name => toString name match ← Ix.Cli.CheckLeanCmd.runMetaCheck bytes cfg true none only none with | .error err => - return (false, 0, names.size, some s!"[{tag}] Ix.Tc driver failed: {err}") + return (false, 0, names.size, some s!"[{tag}] Ix.Kernel driver failed: {err}") | .ok (report, workItems) => IO.println s!"[{tag}] {report.passed}/{report.targetsCovered} passed in \ {report.elapsedMs}ms" diff --git a/Tests/Ix/Tc/InferDefEq.lean b/Tests/Ix/Kernel/InferDefEq.lean similarity index 97% rename from Tests/Ix/Tc/InferDefEq.lean rename to Tests/Ix/Kernel/InferDefEq.lean index 4d88638d0..e47097904 100644 --- a/Tests/Ix/Tc/InferDefEq.lean +++ b/Tests/Ix/Kernel/InferDefEq.lean @@ -1,22 +1,22 @@ module public import LSpec -public import Ix.Tc -public import Tests.Ix.Tc.IxonFixtures -public import Tests.Ix.Tc.WhnfTests +public import Ix.Kernel +public import Tests.Ix.Kernel.IxonFixtures +public import Tests.Ix.Kernel.WhnfTests /-! Type inference and definitional equality with the real knot -(`Ix.Tc.methodsN`). Exercises the tiers that were inert under stub methods: +(`Ix.Kernel.methodsN`). Exercises the tiers that were inert under stub methods: K-like ctor synthesis in iota, proof irrelevance, lambda eta, struct eta, and unit-like equality. -/ -namespace Tests.Tc.InferDefEq +namespace Tests.Kernel.InferDefEq open LSpec -open Ix.Tc -open Tests.Tc.Fixtures (storeConst storeMutsWithProjs axiomA) +open Ix.Kernel +open Tests.Kernel.Fixtures (storeConst storeMutsWithProjs axiomA) abbrev AE := KExpr .anon @@ -137,7 +137,7 @@ def ingressEnvOf (p : Ixon.Env × Address) : AnonEnv := /-- `A : Sort 1` plus `idA : A → A := λ a. a` and an axiom `c : A`. -/ def baseEnv : AnonEnv × Address × Address × Address := Id.run do - let (ixon, aAddr) := Tests.Tc.Fixtures.envA + let (ixon, aAddr) := Tests.Kernel.Fixtures.envA let idDefn : Ixon.Constant := ⟨.defn ⟨.defn, .safe, 0, .leanAll (.ref 0 #[]) (.ref 0 #[]), .leanLam (.ref 0 #[]) (.var 0)⟩, @@ -151,7 +151,7 @@ def baseEnv : AnonEnv × Address × Address × Address := Id.run do `idA`. The hint channel is separate from the content-addressed constant. -/ def sameHeadEnv (hints : Lean.ReducibilityHints) : AnonEnv × Address × Address × Address × Address := Id.run do - let (ixon, aAddr) := Tests.Tc.Fixtures.envA + let (ixon, aAddr) := Tests.Kernel.Fixtures.envA let idDefn : Ixon.Constant := ⟨.defn ⟨.defn, .safe, 0, .leanAll (.ref 0 #[]) (.ref 0 #[]), .leanLam (.ref 0 #[]) (.var 0)⟩, @@ -302,7 +302,7 @@ def defEqAdvanced : TestSeq := -- irrelevance can. defEq env (pAddr hAddr) (pAddr hoAddr) : Bool)) ++ test "lambda eta (λ x. f x ≡ f)" - ((let (ixon, aAddr) := Tests.Tc.Fixtures.envA + ((let (ixon, aAddr) := Tests.Kernel.Fixtures.envA let fAxio : Ixon.Constant := ⟨.axio ⟨false, 0, .leanAll (.ref 0 #[]) (.ref 0 #[])⟩, #[], #[aAddr], #[]⟩ let (ixon, fAddr) := storeConst ixon fAxio @@ -411,4 +411,4 @@ def natOffsetTests : TestSeq := public def suite : List TestSeq := [knotFuelTests, inferTests, defEqBasics, defEqAdvanced, natOffsetTests] -end Tests.Tc.InferDefEq +end Tests.Kernel.InferDefEq diff --git a/Tests/Ix/Tc/IngressMetaTests.lean b/Tests/Ix/Kernel/IngressMetaTests.lean similarity index 96% rename from Tests/Ix/Tc/IngressMetaTests.lean rename to Tests/Ix/Kernel/IngressMetaTests.lean index 17fe3b422..0801df2f3 100644 --- a/Tests/Ix/Tc/IngressMetaTests.lean +++ b/Tests/Ix/Kernel/IngressMetaTests.lean @@ -1,12 +1,12 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel public import Ix.CompileM public import Ix.Meta public import Ix.Common -public import Tests.Ix.Tc.AnonDiff -public import Tests.Ix.Tc.IxonFixtures +public import Tests.Ix.Kernel.AnonDiff +public import Tests.Ix.Kernel.IxonFixtures /-! Meta-mode ingress tests (`tc-unit` entries + `tc-ingress-meta` ignored). @@ -26,10 +26,10 @@ item, and check per-named-entry address parity against the anon ingress of the same env. Whole-env meta scale is exercised by the R3 roundtrip. -/ -namespace Tests.Tc.IngressMeta +namespace Tests.Kernel.IngressMeta open LSpec -open Ix.Tc +open Ix.Kernel public section @@ -64,7 +64,7 @@ def nId : Ix.Name := Ix.Name.mkStr Ix.Name.mkAnon "idA" def nX : Ix.Name := Ix.Name.mkStr Ix.Name.mkAnon "x" def nKey : Ix.Name := Ix.Name.mkStr Ix.Name.mkAnon "key" -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Axiom `A : Sort 1` with `.axio` metadata: name `A`, one level param `u`, leaf arena. -/ def envMetaAxiom : Ixon.Env × Address := Id.run do @@ -74,7 +74,7 @@ def envMetaAxiom : Ixon.Env × Address := Id.run do let env := withNamed env nA aAddr cm (extraNames := [nU]) return (env, aAddr) -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Definition `idA : A → A := fun (x : A) => x` with full arena metadata: binder name `x` (implicit), and an mdata layer on the value root. -/ def envMetaDefn : Ixon.Env × Address × Address := Id.run do @@ -118,7 +118,7 @@ def metaAxiomChecks : Bool × Bool × Bool := Id.run do | some (.axio name levelParams _ _ _) => -- Address parity with the anon ingress of the same env. let anonOk := Id.run do - match Tests.Tc.Fixtures.runIngress + match Tests.Kernel.Fixtures.runIngress (ingressAnonAddrShallow env aAddr) with | .ok (_, aenv) => match aenv.get? ⟨aAddr, ()⟩, kenv.get? ⟨aAddr, nA⟩ with @@ -156,7 +156,7 @@ def metaDefnChecks : Bool × Bool × Bool × Bool := Id.run do def metaDefnAddrParity : Bool := Id.run do let (env, dAddr, _) := envMetaDefn match ingressAllMeta env, - Tests.Tc.Fixtures.runIngress (ingressAnonAddrShallow env dAddr) with + Tests.Kernel.Fixtures.runIngress (ingressAnonAddrShallow env dAddr) with | .ok kenv, .ok (_, aenv) => match kenv.get? ⟨dAddr, nId⟩, aenv.get? ⟨dAddr, ()⟩ with | some (.defn (ty := mty) (val := mval) ..), @@ -165,7 +165,7 @@ def metaDefnAddrParity : Bool := Id.run do | _, _ => return false | _, _ => return false -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- `ref` without an arena `.ref` node is a hard error. -/ def metaRefMissingArenaCaught : Bool := Id.run do let (env, aAddr) := envA @@ -179,7 +179,7 @@ def metaRefMissingArenaCaught : Bool := Id.run do | .error e => return (e.splitOn "has no metadata name").length > 1 | .ok _ => return false -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- `lam` without an arena binder soft-falls-back to a synthetic name. -/ def metaLamSynthFallback : Bool := Id.run do let (env, aAddr) := envA @@ -201,7 +201,7 @@ def metaLamSynthFallback : Bool := Id.run do return n == Ix.Name.mkStr Ix.Name.mkAnon "_s0" | _ => return false -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- A `callSite` arena node distributes canonical-arg metadata and names the head from the call-site's `name` field. -/ def metaCallSiteFixture : Bool := Id.run do @@ -271,7 +271,7 @@ def weirdULevel : Ix.Level := (Ix.Level.mkParam nU)) (Ix.Level.mkParam nU) -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Axiom `W.{u} : Sort (imax (imax 1 u) u)` — one weird table entry. -/ def envWeirdSort : Ixon.Env × Address := Id.run do let c : Ixon.Constant := ⟨.axio ⟨false, 1, .sort 0⟩, #[], #[], #[weirdU]⟩ @@ -298,7 +298,7 @@ def decorSortChecks : Bool × Bool × Bool := Id.run do ty.addr == (KExpr.mkSort (m := .anon) (.mkParam 0 ())).addr -- Anon parity (tc-meta-addr survives the decoration). let parityOk := Id.run do - match Tests.Tc.Fixtures.runIngress + match Tests.Kernel.Fixtures.runIngress (ingressAnonAddrShallow env wAddr) with | .ok (_, aenv) => match aenv.get? ⟨wAddr, ()⟩ with @@ -326,7 +326,7 @@ def decorSortEgress : Bool × Bool := Id.run do | _ => return (false, false) | _ => return (false, false) -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Axiom `T.{u} : Sort (imax (imax 1 u) u) → Sort u` — BOTH spellings of one Géran class in one constant (the Design-A killer): the two sort occurrences share a semantic address but differ in decoration. -/ @@ -373,7 +373,7 @@ def decorTwinChecks : Bool × Bool × Bool := Id.run do | _ => return (false, false, false) | _ => return (false, false, false) -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- `gpoly.{u} : @fpoly.{imax (imax 1 u) u} → @fpoly.{u}` — const-arg twins: the two `const` occurrences share a semantic address but only the weird one carries a decoration (full original list). -/ @@ -422,7 +422,7 @@ def decorConstChecks : Bool × Bool × Bool := Id.run do | _ => return (false, false, false) | _ => return (false, false, false) -open Tests.Tc.Fixtures in +open Tests.Kernel.Fixtures in /-- Control: an already-normal spelling (`max u v`) gets NO decoration. -/ def decorNormalControl : Bool := Id.run do let c : Ixon.Constant := @@ -479,7 +479,7 @@ def unitTests : List TestSeq := `(namedChecked, firstErr?)`. -/ def closureParity (leanEnv : Lean.Environment) (label : String) (seeds : List Lean.Name) : IO (Nat × Option String) := do - let consts := Tests.Tc.AnonDiff.closureOf leanEnv seeds + let consts := Tests.Kernel.AnonDiff.closureOf leanEnv seeds if consts.isEmpty then return (0, some s!"empty closure for {seeds}") let dir ← IO.FS.createTempDir @@ -495,7 +495,7 @@ def closureParity (leanEnv : Lean.Environment) (label : String) | .error e => return (0, some s!"meta ingress failed: {e}") | .ok kenv => pure kenv -- Anon ingress of the whole env. - let aenv ← match Tests.Tc.Fixtures.runIngress (do + let aenv ← match Tests.Kernel.Fixtures.runIngress (do match buildAnonWork ixonEnv with | .error e => throw e | .ok work => @@ -529,7 +529,7 @@ def closureParity (leanEnv : Lean.Environment) (label : String) return (checked, firstErr) def suite : List TestSeq := - (Tests.Tc.AnonDiff.seedSets ++ + (Tests.Kernel.AnonDiff.seedSets ++ [("inductives-recursors", [`Nat.rec, `List.rec, `Acc.rec, `Prod.rec, `PSigma.rec])]).map fun (label, seeds) => @@ -540,4 +540,4 @@ def suite : List TestSeq := end -end Tests.Tc.IngressMeta +end Tests.Kernel.IngressMeta diff --git a/Tests/Ix/Tc/InitScale.lean b/Tests/Ix/Kernel/InitScale.lean similarity index 94% rename from Tests/Ix/Tc/InitScale.lean rename to Tests/Ix/Kernel/InitScale.lean index 19553e059..7bff70048 100644 --- a/Tests/Ix/Tc/InitScale.lean +++ b/Tests/Ix/Kernel/InitScale.lean @@ -1,9 +1,9 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel public import Ix.KernelCheck -public import Tests.Ix.Tc.AnonDiff +public import Tests.Ix.Kernel.AnonDiff /-! Init-scale anon verdict differential (`tc-init`, ignored suite). @@ -20,10 +20,10 @@ Two modes: Acceptance: zero verdict mismatches vs `rsCheckAnonFFI`. -/ -namespace Tests.Tc.InitScale +namespace Tests.Kernel.InitScale open LSpec -open Ix.Tc +open Ix.Kernel /-- Broad Init-representative seeds: arithmetic, containers, characters, strings, well-founded recursion, decidability, structures with @@ -89,11 +89,11 @@ def envGatedSuite : TestSeq := Id.run do | none => let env ← get_env! let (compared, skipped, diff?) ← - Tests.Tc.AnonDiff.diffOnSeeds env "init-scale" initSeeds + Tests.Kernel.AnonDiff.diffOnSeeds env "init-scale" initSeeds let msg := diff?.map (s!"compared {compared}, skipped {skipped}: " ++ ·) return (diff?.isNone && skipped == 0, compared, skipped, msg)) .done return ts public def suite : List TestSeq := [envGatedSuite] -end Tests.Tc.InitScale +end Tests.Kernel.InitScale diff --git a/Tests/Ix/Tc/IxonFixtures.lean b/Tests/Ix/Kernel/IxonFixtures.lean similarity index 98% rename from Tests/Ix/Tc/IxonFixtures.lean rename to Tests/Ix/Kernel/IxonFixtures.lean index d636767f7..e516d38d1 100644 --- a/Tests/Ix/Tc/IxonFixtures.lean +++ b/Tests/Ix/Kernel/IxonFixtures.lean @@ -1,26 +1,26 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel /-! -Hand-built `Ixon.Env` fixtures for `Ix.Tc` ingress tests (no FFI, no +Hand-built `Ixon.Env` fixtures for `Ix.Kernel` ingress tests (no FFI, no compiler): constants stored at `blake3 (serConstant c)`, mutual blocks stored together with all their projection constants (mirroring what the compiler emits), plus ingress negative cases (index OOB, missing blob, missing projection, integrity violation). The accept tests assert exact kernel node addresses computed independently -via the `Ix.Tc` smart constructors — a pure-Lean end-to-end check of the +via the `Ix.Kernel` smart constructors — a pure-Lean end-to-end check of the index-resolution + Blake3 pipeline. -/ public section -namespace Tests.Tc.Fixtures +namespace Tests.Kernel.Fixtures open LSpec -open Ix.Tc +open Ix.Kernel /-! ### Builders -/ @@ -322,6 +322,6 @@ def rejectTests : TestSeq := public def suite : List TestSeq := [acceptTests, rejectTests] -end Tests.Tc.Fixtures +end Tests.Kernel.Fixtures end diff --git a/Tests/Ix/Tc/ParityEnv.lean b/Tests/Ix/Kernel/ParityEnv.lean similarity index 97% rename from Tests/Ix/Tc/ParityEnv.lean rename to Tests/Ix/Kernel/ParityEnv.lean index 9b2afb0bf..672280506 100644 --- a/Tests/Ix/Tc/ParityEnv.lean +++ b/Tests/Ix/Kernel/ParityEnv.lean @@ -16,7 +16,7 @@ plus the checked-in seed list when the file isn't already present, so the tests run unconditionally instead of skipping when no fixture is supplied. -/ -namespace Tests.Tc.ParityEnv +namespace Tests.Kernel.ParityEnv open Lean @@ -49,4 +49,4 @@ public def ensure : IO System.FilePath := do let _ ← Ix.CompileM.rsCompileEnvBytesFFI closed out.toString false return out -end Tests.Tc.ParityEnv +end Tests.Kernel.ParityEnv diff --git a/Tests/Ix/Tc/Pins.lean b/Tests/Ix/Kernel/Pins.lean similarity index 94% rename from Tests/Ix/Tc/Pins.lean rename to Tests/Ix/Kernel/Pins.lean index 0fb67426a..847d9c3e6 100644 --- a/Tests/Ix/Tc/Pins.lean +++ b/Tests/Ix/Kernel/Pins.lean @@ -1,26 +1,26 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel public import Ix.Cli.CheckLeanCmd -public import Tests.Ix.Tc.ParityEnv +public import Tests.Ix.Kernel.ParityEnv /-! `tc-pins` (ignored runner): regression pins for the pure-Lean kernel -against a real serialized env (compiled on demand — see `Tests.Tc.ParityEnv`). +against a real serialized env (compiled on demand — see `Tests.Kernel.ParityEnv`). Each pin is a constant that previously OOMed, was falsely rejected at depth 2001, or blew the worker stack (see the short-circuit note in -`Ix/Tc/DefEq.lean` and `ParCheckCfg.stackBytes`); the suite ingresses +`Ix/Kernel/DefEq.lean` and `ParCheckCfg.stackBytes`); the suite ingresses the env once and checks each pin subject-only under a wall-clock budget. Budgets are generous — the pins guard ∞/OOM regression classes, not micro-perf. Known-slow pins (open perf issues) run only with `IX_PINS_SLOW=1`. -/ -namespace Tests.Tc.Pins +namespace Tests.Kernel.Pins open LSpec -open Ix.Tc +open Ix.Kernel structure Pin where /-- Fail-out-style label (meta-mode Lean name rendering). -/ @@ -76,7 +76,7 @@ def checkPin (kenv : MetaEnv) (prims : Primitives .meta) public def run : IO UInt32 := do IO.println "tc-pins" - let path ← Tests.Tc.ParityEnv.ensure + let path ← Tests.Kernel.ParityEnv.ensure let includeSlow := (← IO.getEnv "IX_PINS_SLOW").isSome let t0 ← IO.monoMsNow let bytes ← IO.FS.readBinFile path @@ -99,4 +99,4 @@ public def run : IO UInt32 := do seq := seq ++ (← checkPin kenv prims work pin) lspecIO (.ofList [("tc-pins", [seq])]) [] -end Tests.Tc.Pins +end Tests.Kernel.Pins diff --git a/Tests/Ix/Kernel/PrimAddrs.lean b/Tests/Ix/Kernel/PrimAddrs.lean index 68f638e96..3615c1721 100644 --- a/Tests/Ix/Kernel/PrimAddrs.lean +++ b/Tests/Ix/Kernel/PrimAddrs.lean @@ -19,7 +19,7 @@ This test closes that class. It reads the byte arrays out of the ELABORATED toplevel — not the source text — and compares each against - the address computed at test runtime from `Ix.Tc.PrimAddrs`, which is + the address computed at test runtime from `Ix.Kernel.PrimAddrs`, which is the same table the host-side closure walker and ingress verifier use. Any drift between the two sources of truth fails here. @@ -32,7 +32,7 @@ import Ix.Meta import Ix.Aiur.Compiler import Ix.IxVM import Ix.IxVM.Toplevel -import Ix.Tc.Primitive +import Ix.Kernel.Primitive import LSpec open LSpec @@ -68,12 +68,12 @@ private def collectAddrFns (t : Aiur.Source.Toplevel) : /-- The canonical address set, computed at test runtime from the Lean parity table + reserved markers — the same source the host closure - walker (`Ix.Tc.primAddrSet`) consults. -/ + walker (`Ix.Kernel.primAddrSet`) consults. -/ private def canonical : Std.HashMap Address String := Id.run do let mut m : Std.HashMap Address String := {} - for (name, a) in Ix.Tc.PrimAddrs.leanParityTable do + for (name, a) in Ix.Kernel.PrimAddrs.leanParityTable do m := m.insert a name - for (name, a) in Ix.Tc.PrimAddrs.reservedMarkerAddrs do + for (name, a) in Ix.Kernel.PrimAddrs.reservedMarkerAddrs do m := m.insert a name return m diff --git a/Tests/Ix/Tc/Substrate.lean b/Tests/Ix/Kernel/Substrate.lean similarity index 98% rename from Tests/Ix/Tc/Substrate.lean rename to Tests/Ix/Kernel/Substrate.lean index c5fadfb1d..ebf1139df 100644 --- a/Tests/Ix/Tc/Substrate.lean +++ b/Tests/Ix/Kernel/Substrate.lean @@ -1,10 +1,10 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel /-! -Unit tests for the `Ix.Tc` substrate (Equiv/Primitive/Env/Subst/Lctx/Monad): +Unit tests for the `Ix.Kernel` substrate (Equiv/Primitive/Env/Subst/Lctx/Monad): subst/lift/instantiateRev/abstractFVars round-trips (ported from subst.rs tests), cheap-beta cases, ctx-id chain determinism, suffix-aware cache keys, fuel/tick semantics under EStateM, union-find behavior, local-context @@ -12,10 +12,10 @@ open/close, universe instantiation, and the primitives parity check against the live Rust `PrimAddrs::new()` table (FFI). -/ -namespace Tests.Tc.Substrate +namespace Tests.Kernel.Substrate open LSpec -open Ix.Tc +open Ix.Kernel /-! ### Helpers -/ @@ -473,4 +473,4 @@ public def suite : List TestSeq := cheapBetaTests, internTests, equivTests, ctxTests, fuelTests, openBinderTests, univInstTests, envTests, primsParity] -end Tests.Tc.Substrate +end Tests.Kernel.Substrate diff --git a/Tests/Ix/Tc/TutorialTc.lean b/Tests/Ix/Kernel/TutorialTc.lean similarity index 96% rename from Tests/Ix/Tc/TutorialTc.lean rename to Tests/Ix/Kernel/TutorialTc.lean index a65055b61..91c30e44c 100644 --- a/Tests/Ix/Tc/TutorialTc.lean +++ b/Tests/Ix/Kernel/TutorialTc.lean @@ -1,11 +1,11 @@ /- - Kernel tutorial test cases through the pure-Lean `Ix.Tc` kernel + Kernel tutorial test cases through the pure-Lean `Ix.Kernel` kernel (`tc-tutorial`, ignored suite). Mirrors `Tests/Ix/Kernel/Tutorial.lean` (the Rust-kernel runner): reads the same good/bad test cases registered by `TutorialDefs.lean`, compiles each batch through the Rust compiler to Ixon bytes, and checks verdicts - with `Ix.Tc.checkEnvAnon` instead of `rsCheckConstsFFI`. + with `Ix.Kernel.checkEnvAnon` instead of `rsCheckConstsFFI`. Differences from the Rust runner, by necessity: - Renaming test cases are skipped (their collision check is Lean-side @@ -26,14 +26,14 @@ import Ix.Common import Ix.Meta import Ix.CompileM -import Ix.Tc +import Ix.Kernel import Tests.Ix.Kernel.TutorialMeta import Tests.Ix.Kernel.TutorialDefs import LSpec open LSpec -namespace Tests.Tc.TutorialTc +namespace Tests.Kernel.TutorialTc /-- Same closure walk as `Tutorial.lean`'s `collectDepsWithExtras` (that one is `private`). -/ @@ -83,7 +83,7 @@ partial def collectDepsWithExtras let closed := env.constants.toList.filter fun (n, _) => needed.contains n return (needed, closed) -/-- Compile a batch and check it through Ix.Tc. Returns +/-- Compile a batch and check it through Ix.Kernel. Returns `name ↦ (none = passed | some err)`; `.error` when the whole batch failed to compile (callers decide how that maps to expectations). -/ def checkBatchTc (consts : List (Lean.Name × Lean.ConstantInfo)) @@ -106,12 +106,12 @@ def checkBatchTc (consts : List (Lean.Name × Lean.ConstantInfo)) let fullEnv ← match Ixon.deEnv bytes with | .ok env => pure env | .error e => return .error s!"deEnv failed: {e}" - let verdicts ← match Ix.Tc.checkIxeBytesAnon bytes with + let verdicts ← match Ix.Kernel.checkIxeBytesAnon bytes with | .ok results => pure (results.foldl (init := (Std.HashMap.emptyWithCapacity results.size : Std.HashMap Address (Option String))) fun acc r => acc.insert r.addr r.err?) - | .error e => return .error s!"Ix.Tc driver failed: {e}" + | .error e => return .error s!"Ix.Kernel driver failed: {e}" let mut out : Std.HashMap Lean.Name (Option String) := {} for n in names do let ixName := Ix.Name.fromLeanName n @@ -124,7 +124,7 @@ def checkBatchTc (consts : List (Lean.Name × Lean.ConstantInfo)) return .ok out def testTutorialTc : TestSeq := - .individualIO "Ix.Tc kernel tutorial checks" none (do + .individualIO "Ix.Kernel kernel tutorial checks" none (do let leanEnv ← get_env! let testCases := Tests.Ix.Kernel.TutorialMeta.getTestCases leanEnv let rawConsts := Tests.Ix.Kernel.TutorialMeta.getRawConsts leanEnv @@ -256,4 +256,4 @@ def testTutorialTc : TestSeq := def suite : List TestSeq := [testTutorialTc] -end Tests.Tc.TutorialTc +end Tests.Kernel.TutorialTc diff --git a/Tests/Ix/Tc/Unit.lean b/Tests/Ix/Kernel/Unit.lean similarity index 98% rename from Tests/Ix/Tc/Unit.lean rename to Tests/Ix/Kernel/Unit.lean index 40e8cbc1d..7a3dc1766 100644 --- a/Tests/Ix/Tc/Unit.lean +++ b/Tests/Ix/Kernel/Unit.lean @@ -1,12 +1,12 @@ module public import LSpec -public import Ix.Tc +public import Ix.Kernel public import Ix.IxonUniv public import Tests.Gen.Ixon /-! -Unit tests for the `Ix.Tc` foundations (Mode/Id/Level/Expr/Const): +Unit tests for the `Ix.Kernel` foundations (Mode/Id/Level/Expr/Const): - raw-node address parity with the existing `Ix.Level` wire constructors (shared tag bytes ⇒ shared preimages for closed levels) @@ -17,10 +17,10 @@ Unit tests for the `Ix.Tc` foundations (Mode/Id/Level/Expr/Const): - seeded property tests (xorshift PRNG ported from level.rs) -/ -namespace Tests.Tc.Unit +namespace Tests.Kernel.Unit open LSpec -open Ix.Tc +open Ix.Kernel /-! ### Helpers -/ @@ -412,7 +412,7 @@ linearizer bug found during development lived there), plus: - P4 against the kernel's own Géran machinery (`Level.normalizeLevel` on the mk*-rebuilt `KUniv`s), modulo subsumption's empty-entry artifacts — see the `Ix/IxonUniv.lean` module-doc O1 note; -- the `Ixon.reduceUniv` ≍ `Ix.Tc.reduceIxonUniv` twin pin (same +- the `Ixon.reduceUniv` ≍ `Ix.Kernel.reduceIxonUniv` twin pin (same closure, one via transliterated rules, one via the kernel's actual smart constructors — drift here would desync the stage-1 decoration test from what ingress really does). -/ @@ -479,7 +479,7 @@ def canonUnivTests : TestSeq := ++ test "canonUniv P4: kernel Géran oracle, modulo empty entries \ (exhaustive ≤6)" p4 ++ test "canonUniv P6: mk* rebuild absorbed (exhaustive ≤6)" p6 - ++ test "reduceUniv ≍ Tc.reduceIxonUniv twin agreement (exhaustive ≤6)" + ++ test "reduceUniv ≍ Kernel.reduceIxonUniv twin agreement (exhaustive ≤6)" agree public def suite : List TestSeq := @@ -487,4 +487,4 @@ public def suite : List TestSeq := canonicalTotalizationTests, occurrenceTests, exprInfo, smartCtors, levelAlgebra, props, modeTests, canonUnivTests] -end Tests.Tc.Unit +end Tests.Kernel.Unit diff --git a/Tests/Ix/Tc/WhnfTests.lean b/Tests/Ix/Kernel/WhnfTests.lean similarity index 98% rename from Tests/Ix/Tc/WhnfTests.lean rename to Tests/Ix/Kernel/WhnfTests.lean index 88c2e1cb1..08f764f4e 100644 --- a/Tests/Ix/Tc/WhnfTests.lean +++ b/Tests/Ix/Kernel/WhnfTests.lean @@ -1,8 +1,8 @@ module public import LSpec -public import Ix.Tc -public import Tests.Ix.Tc.IxonFixtures +public import Ix.Kernel +public import Tests.Ix.Kernel.IxonFixtures /-! Whnf tests, run with throw-stub `Methods`: the infer/isDefEq back-edges @@ -13,11 +13,11 @@ reduction in isolation. Assertions are by exact node address. public section -namespace Tests.Tc.WhnfTests +namespace Tests.Kernel.WhnfTests open LSpec -open Ix.Tc -open Tests.Tc.Fixtures (storeConst storeMutsWithProjs runIngress axiomA) +open Ix.Kernel +open Tests.Kernel.Fixtures (storeConst storeMutsWithProjs runIngress axiomA) abbrev AE := KExpr .anon @@ -417,6 +417,6 @@ public def suite : List TestSeq := [pureHelperTests, structuralTests, iotaTests, natTests, nativeTests, cacheTests] -end Tests.Tc.WhnfTests +end Tests.Kernel.WhnfTests end diff --git a/Tests/Ix/Lean4Lean.lean b/Tests/Ix/Lean4Lean.lean deleted file mode 100644 index 00ead89ce..000000000 --- a/Tests/Ix/Lean4Lean.lean +++ /dev/null @@ -1,37 +0,0 @@ -import LSpec -import Benchmarks.Lean4Lean - -/-! -Smoke tests for the lean4lean dependency (ignored runner `lean4lean`): -the reference Lean4-in-Lean4 kernel accepts a real closure replayed from -the test env and rejects an ill-typed declaration. Guards the pinned -require (toolchain drift or an API change in `Lean4Lean.addDecl` surfaces -here and in `bench-lean4lean`, which shares the replay machinery). --/ - -namespace Tests.Ix.Lean4Lean - -open LSpec - -def run (env : Lean.Environment) : IO UInt32 := do - IO.println "lean4lean" - let newConstants := env.constants.fold - (init := ({} : Std.HashMap Lean.Name Lean.ConstantInfo)) fun m n ci => m.insert n ci - -- Accept: replay a real constant's whole closure into a fresh kernel env - -- (the `bench-lean4lean --consts` path). - let closRes ← (BenchLean4Lean.replayClosure env newConstants `Nat.add_comm false).toBaseIO - -- Reject: an axiom whose type is a Nat literal (not a sort) must fail - -- `checkConstantVal`. - let bogus : Lean.AxiomVal := - { name := `l4lTestBogusAxiom, levelParams := [], type := Lean.mkRawNatLit 0 - isUnsafe := false } - let rejected := !(Lean4Lean.addAxiom env.toKernelEnv bogus).isOk - let seq : TestSeq := - (match closRes with - | .ok n => test s!"Nat.add_comm closure replays through lean4lean ({n} declarations)" - (n > 0) - | .error e => test s!"Nat.add_comm closure replay failed: {e}" false) - ++ test "ill-typed axiom (type = Nat literal) is rejected" rejected - lspecIO (.ofList [("lean4lean", [seq])]) [] - -end Tests.Ix.Lean4Lean diff --git a/Tests/Main.lean b/Tests/Main.lean index 486d41861..0e7753500 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -34,19 +34,19 @@ import Tests.Ix.RustSerialize import Tests.Ix.RustDecompile import Tests.Ix.Sharing import Tests.Ix.BenchMeasures -import Tests.Ix.Tc.Unit -import Tests.Ix.Tc.Substrate -import Tests.Ix.Tc.IxonFixtures -import Tests.Ix.Tc.WhnfTests -import Tests.Ix.Tc.InferDefEq -import Tests.Ix.Tc.CheckTests -import Tests.Ix.Tc.AnonDiff -import Tests.Ix.Tc.InitScale -import Tests.Ix.Tc.TutorialTc -import Tests.Ix.Tc.Roundtrip -import Tests.Ix.Tc.IngressMetaTests -import Tests.Ix.Tc.Pins -import Tests.Ix.Tc.AccelDiff +import Tests.Ix.Kernel.Unit +import Tests.Ix.Kernel.Substrate +import Tests.Ix.Kernel.IxonFixtures +import Tests.Ix.Kernel.WhnfTests +import Tests.Ix.Kernel.InferDefEq +import Tests.Ix.Kernel.CheckTests +import Tests.Ix.Kernel.AnonDiff +import Tests.Ix.Kernel.InitScale +import Tests.Ix.Kernel.TutorialTc +import Tests.Ix.Kernel.CheckerRoundtrip +import Tests.Ix.Kernel.IngressMetaTests +import Tests.Ix.Kernel.Pins +import Tests.Ix.Kernel.AccelDiff import Tests.Ix.CanonM import Tests.Ix.GraphM import Tests.Ix.CondenseM @@ -60,7 +60,6 @@ import Tests.Cli import Tests.Ix.Ixes import Tests.ShardMap import Tests.Ix.EnvBody -import Tests.Ix.Lean4Lean import Tests.Ix.MetaEnv import Tests.Ix.Catalog import Tests.Ix.CatalogDedup @@ -106,10 +105,10 @@ def primarySuites : Std.HashMap String (List LSpec.TestSeq) := .ofList [ ("primitive-address-parity", Tests.Ix.Kernel.BuildPrimitives.paritySuite ++ Tests.Ix.Kernel.BuildPrimOrigs.paritySuite), ("decompile-unit", Tests.Decompile.unitSuite), - ("tc-unit", Tests.Tc.Unit.suite ++ Tests.Tc.Substrate.suite - ++ Tests.Tc.Fixtures.suite ++ Tests.Tc.WhnfTests.suite - ++ Tests.Tc.InferDefEq.suite ++ Tests.Tc.CheckTests.suite - ++ Tests.Tc.Roundtrip.unitTests ++ Tests.Tc.IngressMeta.unitTests), + ("tc-unit", Tests.Kernel.Unit.suite ++ Tests.Kernel.Substrate.suite + ++ Tests.Kernel.Fixtures.suite ++ Tests.Kernel.WhnfTests.suite + ++ Tests.Kernel.InferDefEq.suite ++ Tests.Kernel.CheckTests.suite + ++ Tests.Kernel.Roundtrip.unitTests ++ Tests.Kernel.IngressMeta.unitTests), ] /-- Ignored test suites - expensive, run only when explicitly requested. These require significant RAM -/ @@ -148,11 +147,11 @@ def ignoredSuites : Std.HashMap String (List LSpec.TestSeq) := .ofList [ ("kernel-check-tauceti-reduction", Tests.Ix.Kernel.CheckTauCetiReduction.suite), ("rust-kernel-build-primitives", Tests.Ix.Kernel.BuildPrimitives.suite), ("rust-kernel-build-prim-origs", Tests.Ix.Kernel.BuildPrimOrigs.suite), - ("tc-anon-diff", Tests.Tc.AnonDiff.suite), - ("tc-init", Tests.Tc.InitScale.suite), - ("tc-tutorial", Tests.Tc.TutorialTc.suite), - ("tc-roundtrip", Tests.Tc.Roundtrip.suite), - ("tc-ingress-meta", Tests.Tc.IngressMeta.suite), + ("tc-anon-diff", Tests.Kernel.AnonDiff.suite), + ("tc-init", Tests.Kernel.InitScale.suite), + ("tc-tutorial", Tests.Kernel.TutorialTc.suite), + ("tc-roundtrip", Tests.Kernel.Roundtrip.suite), + ("tc-ingress-meta", Tests.Kernel.IngressMeta.suite), ] /-- Primary test runners — quick suites run by default alongside @@ -287,15 +286,12 @@ def ignoredRunners (env : Lean.Environment) : List (String × IO UInt32) := [ -- Tests.Ix.Compile.AuxGenDiff). ("aux-gen-diff", Tests.Compile.AuxGenDiff.run env), ("decompile-diff", Tests.Compile.DecompileDiff.run env), - -- lean4lean dependency smoke: accept a real closure, reject an - -- ill-typed decl (see Tests.Ix.Lean4Lean). - ("lean4lean", Tests.Ix.Lean4Lean.run env), -- Pure-Lean kernel regression pins against a real .ixe, compiled on - -- demand (see Tests.Tc.ParityEnv). - ("tc-pins", Tests.Tc.Pins.run), + -- demand (see Tests.Kernel.ParityEnv). + ("tc-pins", Tests.Kernel.Pins.run), -- Accelerated-vs-pure reduction differentials over that same real env - -- (see Tests.Tc.AccelDiff and TcState.noAccel). - ("tc-accel-diff", Tests.Tc.AccelDiff.run), + -- (see Tests.Kernel.AccelDiff and TcState.noAccel). + ("tc-accel-diff", Tests.Kernel.AccelDiff.run), ] def main (args : List String) : IO UInt32 := do diff --git a/Tests/Theory.lean b/Tests/Theory.lean new file mode 100644 index 000000000..71dc8f405 --- /dev/null +++ b/Tests/Theory.lean @@ -0,0 +1,22 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Theory.Audit.Certified +import Tests.Theory.Certified +import Tests.Theory.Checker +import Tests.Theory.Acceptance +import Tests.Theory.Operations +import Tests.Theory.Suggestions +import Tests.Theory.Ordinary +import Tests.Theory.OrdinaryAcceptance +import Tests.Theory.Standard +import Tests.Theory.Quotient +import Tests.Theory.Structure +import Tests.Theory.Natural +import Tests.Theory.Claims +import Tests.Theory.Modeled +import Tests.Theory.ModeledNested +import Tests.Theory.ModeledPermutation +import Tests.Theory.ModeledEquations diff --git a/Tests/Theory/Acceptance.lean b/Tests/Theory/Acceptance.lean new file mode 100644 index 000000000..2c40186bb --- /dev/null +++ b/Tests/Theory/Acceptance.lean @@ -0,0 +1,161 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Accept +import Tests.Theory.Checker +import Tests.Theory.Certified + +open Ix.Theory + +namespace Tests.Theory.Acceptance + +open Ix.Theory.Certified Ix.Theory.Model +open Tests.Theory.Checker (identity identityType identityWitness) +open Tests.Theory.Certified (primitives primitiveStore) + +def prelude : Store Nat := + primitiveStore PrimitiveSignature.falseDeclaration primitives.falseElimDeclaration + +def identityAnnotations (l : VLevel) : AnnotationTree := + .lam (zeroCondition l).toRaw .leaf (.lam (zeroCondition l).toRaw .leaf .leaf) + +def identityTypeAnnotations (l : VLevel) : AnnotationTree := + .forallE (zeroCondition l).toRaw .leaf (.forallE (zeroCondition l).toRaw .leaf .leaf) + +def identityTypeLevel (l : VLevel) : VLevel := .imax (.succ l) (.imax l l) + +def identityTypeWitness (l : VLevel) : TypingWitness Nat := + .forallE (.succ l) (.imax l l) .sort (.forallE l l .bvar .bvar) + +def identityPropositionWitness : TypingWitness Nat := + .conv (.sort (identityTypeLevel .zero)) (.succ .zero) (identityTypeWitness .zero) .sort .sort + +def identityInput : ProofInput Nat := + ⟨prelude, 0, (identity .zero).erase, (identityType .zero).erase⟩ + +def identityProofWitness : ProofWitness Nat := + ⟨[], identityAnnotations .zero, identityTypeAnnotations .zero, + identityWitness .zero, identityPropositionWitness⟩ + +#guard acceptsCertified.{0,0} 50 primitives identityInput identityProofWitness + +def withDefinition (declaration : Const Nat) : Store Nat where + dom := [10, 11, 12] + nodup := by decide + blocks b := + if b = 10 then some ⟨[PrimitiveSignature.falseDeclaration]⟩ + else if b = 11 then some ⟨[primitives.falseElimDeclaration]⟩ + else if b = 12 then some ⟨[declaration]⟩ else none + mem_dom b := by + by_cases h : b = 10 <;> by_cases h' : b = 11 <;> by_cases h'' : b = 12 <;> simp_all + +def idRef : ConstRef Nat := .member 12 0 + +def idDeclaration (kind : DefKind := .definition) : Const Nat := + .defn 1 kind (identityType (.param 0)).erase (identity (.param 0)).erase .safe + +def idDefinitionWitness : DefinitionWitness Nat := + ⟨idRef, identityTypeAnnotations (.param 0), identityAnnotations (.param 0), + identityTypeLevel (.param 0), identityTypeWitness (.param 0), identityWitness (.param 0)⟩ + +def idDefinitionInput (kind : DefKind := .definition) : ProofInput Nat := + ⟨withDefinition (idDeclaration kind), 0, .const idRef [.zero], (identityType .zero).erase⟩ + +def idDefinitionProofWitness : ProofWitness Nat := + { identityProofWitness with + declarations := [.definition idDefinitionWitness] + proofAnnotations := .leaf + proofWitness := .const } + +#guard acceptsCertified.{0,0} 50 primitives (idDefinitionInput .definition) idDefinitionProofWitness +#guard acceptsCertified.{0,0} 50 primitives (idDefinitionInput .theorem) idDefinitionProofWitness +#guard acceptsCertified.{0,0} 50 primitives (idDefinitionInput .opaque) idDefinitionProofWitness + +-- Positive-universe instantiation of the same admitted definition occurs as +-- an argument to a proposition-valued function. +def largeIdentityUse : AExpr Nat := + .app (.lam .always (identityType (.succ .zero)) (identity .zero)) + (.const idRef [.succ .zero]) + +def largeIdentityUseAnnotations : AnnotationTree := + .app (.lam (some []) (identityTypeAnnotations (.succ .zero)) (identityAnnotations .zero)) .leaf + +def largeIdentityUseWitness : TypingWitness Nat := + .app .always (identityType (.succ .zero)) (identityType .zero) + (.lam (identityTypeLevel (.succ .zero)) .zero (identityType .zero) + (identityTypeWitness (.succ .zero)) identityPropositionWitness (identityWitness .zero)) + .const + +#guard acceptsCertified.{0,0} 70 primitives + { idDefinitionInput with proof := largeIdentityUse.erase } + { idDefinitionProofWitness with + proofAnnotations := largeIdentityUseAnnotations + proofWitness := largeIdentityUseWitness } + +-- Every declaration kind still checks its supplied body. +def forgedBodyInput (kind : DefKind) : ProofInput Nat := + { idDefinitionInput kind with + store := withDefinition (.defn 1 kind (identityType (.param 0)).erase (.sort .zero) .safe) } +#guard !acceptsCertified.{0,0} 50 primitives (forgedBodyInput .definition) idDefinitionProofWitness +#guard !acceptsCertified.{0,0} 50 primitives (forgedBodyInput .theorem) idDefinitionProofWitness +#guard !acceptsCertified.{0,0} 50 primitives (forgedBodyInput .opaque) idDefinitionProofWitness + +-- Object axioms cannot enter through the declaration fold. +#guard !acceptsCertified.{0,0} 50 primitives + { idDefinitionInput with + store := withDefinition (.axiom 1 (identityType (.param 0)).erase .safe) } + idDefinitionProofWitness + +-- Missing, repeated, forward, and self dependencies fail at admission. +#guard !acceptsCertified.{0,0} 50 primitives (idDefinitionInput) + { idDefinitionProofWitness with declarations := [] } +#guard !acceptsCertified.{0,0} 50 primitives (idDefinitionInput) + { idDefinitionProofWitness with declarations := [.definition idDefinitionWitness, .definition idDefinitionWitness] } +#guard !acceptsCertified.{0,0} 50 primitives + { idDefinitionInput with + store := withDefinition + (.defn 1 .definition (identityType (.param 0)).erase (.const idRef [.param 0]) .safe) } + { idDefinitionProofWitness with + declarations := [.definition { idDefinitionWitness with bodyAnnotations := .leaf, bodyWitness := .const }] } + +-- A changed original statement is checked, even with an otherwise valid proof. +#guard !acceptsCertified.{0,0} 50 primitives + { identityInput with proposition := primitives.falseExpr } + { identityProofWitness with propositionAnnotations := .leaf, propositionWitness := .const } + +-- Complete primitive metadata is checked before even a constant-free proof. +#guard !acceptsCertified.{0,0} 50 primitives + { identityInput with + store := primitiveStore (.axiom 0 (.sort .zero) .safe) primitives.falseElimDeclaration } + identityProofWitness + +def falseA : AExpr Nat := .const primitives.falseType [] +def eliminatorProposition : AExpr Nat := primitives.falseElimReading.instL [.zero] +def eliminatorAnnotations : AnnotationTree := + .forallE (some []) (.forallE none .leaf .leaf) + (.forallE (some []) .leaf (.app .leaf .leaf)) + +def eliminatorTypeLevel : VLevel := + .imax (.imax .zero (.succ .zero)) (.imax .zero .zero) + +def eliminatorPropositionWitness : TypingWitness Nat := + .conv (.sort eliminatorTypeLevel) (.succ .zero) + (.forallE (.imax .zero (.succ .zero)) (.imax .zero .zero) + (.forallE .zero (.succ .zero) .const .sort) + (.forallE .zero .zero .const (.app .never falseA (.sort .zero) .bvar .bvar))) + .sort .sort + +def eliminatorInput : ProofInput Nat := + ⟨prelude, 0, .const primitives.falseElim [.zero], eliminatorProposition.erase⟩ +def eliminatorProofWitness : ProofWitness Nat := + ⟨[], .leaf, eliminatorAnnotations, .const, eliminatorPropositionWitness⟩ + +#guard acceptsCertified.{0,0} 50 primitives eliminatorInput eliminatorProofWitness +#guard !acceptsCertified.{0,0} 50 primitives + { eliminatorInput with proof := .const primitives.falseElim [] } eliminatorProofWitness +#guard !acceptsCertified.{0,0} 50 primitives + { eliminatorInput with proof := .const primitives.falseElim [.param 0] } eliminatorProofWitness + +end Tests.Theory.Acceptance diff --git a/Tests/Theory/Audit/Certified.lean b/Tests/Theory/Audit/Certified.lean new file mode 100644 index 000000000..2239e242a --- /dev/null +++ b/Tests/Theory/Audit/Certified.lean @@ -0,0 +1,484 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean +import Ix.Theory.Certified + +open Ix.Theory + +/-! +# Certified mathematical dependency audit + +This audit names the implemented checking, admission, and no-False roots. +The generated report includes theorem types so that explicit +mathematical hypotheses remain visible alongside the transitive axiom leaves. +-/ + +open Lean Lean.Elab Command + +namespace Tests.Theory.Audit.Certified + +def roots : Array Name := #[ + `Ix.Theory.Model.SetTheory.empty_exists, + `Ix.Theory.Model.SetTheory.not_mem_empty, + `Ix.Theory.VLevel.eval_inst, + `Ix.Theory.Certified.PropWhen.eq_iff_holds, + `Ix.Theory.Certified.validateZero?_sound, + `Ix.Theory.Certified.zeroCondition_correct, + `Ix.Theory.Certified.zeroCondition_inst, + `Ix.Theory.Certified.instCondition_comp, + `Ix.Theory.Model.readAnnotations?, + `Ix.Theory.Model.interp_inst, + `Ix.Theory.Model.interp_instL, + `Ix.Theory.Model.interp_rename, + `Ix.Theory.Model.piR_mem_univ, + `Ix.Theory.Model.falseValue_uninhabited, + `Ix.Theory.Model.falseElimValue_mem, + `Ix.Theory.Certified.PrimitiveSignature.validate_iff, + `Ix.Theory.Certified.readDefinition?, + `Ix.Theory.Certified.LevelEq.check_sound, + `Ix.Theory.Certified.LevelEq.leq_sound, + `Ix.Theory.Model.wellDenoted_inst, + `Ix.Theory.Model.wellDenoted_beta, + `Ix.Theory.Model.extend_definition, + `Ix.Theory.Model.ConversionClaim.equation, + `Ix.Theory.Model.IndexedContainer.closed_exists, + `Ix.Theory.Model.IndexedContainer.carrier_eq, + `Ix.Theory.Model.IndexedContainer.induction, + `Ix.Theory.Model.IndexedContainer.child_wellFounded, + `Ix.Theory.Model.IndexedContainer.fold_node, + `Ix.Theory.Model.IndexedContainer.fold_mem, + `Ix.Theory.Model.IndexedContainer.small_elim, + `Ix.Theory.Model.Telescope.applyN_curry, + `Ix.Theory.Model.Telescope.curry_applyN, + `Ix.Theory.Certified.verifyTelescope_sound, + `Ix.Theory.Certified.verifyArguments_sound, + `Ix.Theory.Certified.Ordinary.checkShape_sound, + `Ix.Theory.Certified.Ordinary.checkLarge_sound, + `Ix.Theory.Certified.Ordinary.Shape.container_wf, + `Ix.Theory.Certified.Ordinary.Shape.constructorValue_mem, + `Ix.Theory.Certified.Ordinary.Shape.decodeField_branches, + `Ix.Theory.Certified.Ordinary.Shape.branches_decodeFields, + `Ix.Theory.Certified.Ordinary.Shape.container_large, + `Ix.Theory.Certified.Ordinary.Shape.largeValue_iota, + `Ix.Theory.Certified.Ordinary.Shape.constructorType_interp, + `Ix.Theory.Certified.Ordinary.Shape.recursorType_interp, + `Ix.Theory.Certified.Ordinary.Shape.closedRecursorValue_mem_source, + `Ix.Theory.Certified.Ordinary.Shape.produced_rule_eq, + `Ix.Theory.Certified.Ordinary.checkBlock_sound, + `Ix.Theory.Certified.Ordinary.Shape.publishedAssignment_realizes, + `Ix.Theory.Certified.admitOrdinary?_extends, + `Ix.Theory.Model.ConversionClaim.proofIrrel, + `Ix.Theory.Certified.Basis.Equality.Interface.of_checked, + `Ix.Theory.Certified.Basis.Equality.value_eq_eqv, + `Ix.Theory.Certified.Basis.Iff.Interface.of_checked, + `Ix.Theory.Certified.Basis.Iff.eq_of_mem, + `Ix.Theory.Certified.Basis.Nonempty.Interface.of_checked, + `Ix.Theory.Certified.Basis.Nonempty.value_eq_truthVal, + `Ix.Theory.Certified.Standard.Spec.value_mem, + `Ix.Theory.Certified.Standard.check_sound, + `Ix.Theory.Certified.Standard.assignment_realizes, + `Ix.Theory.Certified.admitStandard?_extends, + `Ix.Theory.Model.SetTheory.quotSet_mem_univ, + `Ix.Theory.Model.SetTheory.quotSound, + `Ix.Theory.Certified.Signature.checkTypes_sound, + `Ix.Theory.Certified.Signature.Formed.realizes, + `Ix.Theory.Certified.Quotient.value_mem, + `Ix.Theory.Certified.Quotient.liftValue_apply, + `Ix.Theory.Certified.Quotient.liftRule_eq, + `Ix.Theory.Certified.Quotient.check_sound, + `Ix.Theory.Certified.Quotient.assignment_realizes, + `Ix.Theory.Certified.admitQuotient?_extends, + `Ix.Theory.Model.TypingClaim.fact, + `Ix.Theory.Model.TypingClaim.natLit, + `Ix.Theory.Model.TypingClaim.betaResult, + `Ix.Theory.Model.ConversionClaim.natZero, + `Ix.Theory.Model.ConversionClaim.natSucc, + `Ix.Theory.Model.ConversionClaim.proj, + `Ix.Theory.Certified.Structure.Description.projections_fit, + `Ix.Theory.Certified.Structure.Description.constructor_eta, + `Ix.Theory.Certified.Structure.Description.constructor_iota, + `Ix.Theory.Certified.Structure.Description.projection_meaning, + `Ix.Theory.Certified.Structure.Description.eta_eq, + `Ix.Theory.Certified.Structure.Description.iota_eq, + `Ix.Theory.Certified.Structure.check_sound, + `Ix.Theory.Certified.Structure.Description.factAssignment_realizes, + `Ix.Theory.Certified.Structure.Description.publishedAssignment_realizes, + `Ix.Theory.Certified.admitStructure?_extends, + `Ix.Theory.Certified.Natural.value_mem, + `Ix.Theory.Certified.Natural.meaning, + `Ix.Theory.Certified.Natural.check_sound, + `Ix.Theory.Certified.Natural.assignment_realizes, + `Ix.Theory.Certified.admitNatural?_extends, + `Ix.Theory.Model.interp_mapRefs, + `Ix.Theory.Model.wellDenoted_mapRefs, + `Ix.Theory.Model.AExpr.mapRefs_restore, + `Ix.Theory.Model.interp_mapRefs_restore, + `Ix.Theory.Model.interp_mapRefs_permutation, + `Ix.Theory.Model.wellDenoted_mapRefs_permutation, + `Ix.Theory.Model.interp_mapRefs_merge, + `Ix.Theory.Model.wellDenoted_mapRefs_merge, + `Ix.Theory.Certified.Modeled.propositional_equation, + `Ix.Theory.Certified.Modeled.checkEquation?_sound, + `Ix.Theory.Certified.Modeled.CheckedCompanions.fixed_old, + `Ix.Theory.Certified.Modeled.environment_wf, + `Ix.Theory.Certified.Modeled.assignment_agrees, + `Ix.Theory.Certified.Modeled.assignment_realizes, + `Ix.Theory.Certified.Modeled.check?_sound, + `Ix.Theory.Certified.Modeled.EntrySource.not_axiom, + `Ix.Theory.Certified.Modeled.EntrySource.header, + `Ix.Theory.Certified.checkModeledExtension?, + `Ix.Theory.Certified.admitModeled?_extends, + `Ix.Theory.Certified.PrimitiveSignature.compatible_assignment, + `Ix.Theory.Certified.checkTypeCertified_sound, + `Ix.Theory.Certified.defeqCertified_sound, + `Ix.Theory.Certified.inferCertified_sound, + `Ix.Theory.Certified.whnfCertified_sound, + `Ix.Theory.Certified.admitDefinition?_extends, + `Ix.Theory.Certified.checkStoreCertified, + `Ix.Theory.Certified.accepted_store_has_model, + `Ix.Theory.Certified.EntrySource.header, + `Ix.Theory.Certified.CheckedStore.subject_sound, + `Ix.Theory.Certified.accepted_store_source_sound, + `Ix.Theory.Certified.checkDeclarationExtensions?, + `Ix.Theory.Certified.CheckedExtension.admit, + `Ix.Theory.Certified.checkFrontier?_refs, + `Ix.Theory.Certified.CheckedFrontier.compatible, + `Ix.Theory.Certified.ConditionalStore.subject_sound, + `Ix.Theory.Certified.EntrySource.axiom_policy, + `Ix.Theory.Certified.ConditionalStore.logical_axioms_authorized, + `Ix.Theory.Certified.acceptsBatch, + `Ix.Theory.Certified.CheckedBatch.closed_has_model, + `Ix.Theory.Certified.CheckedBatch.compatible_leaves, + `Ix.Theory.Certified.CheckedBatch.frontier_coverage, + `Ix.Theory.Certified.DependencyOrder.before, + `Ix.Theory.Certified.DependencyOrder.edge_for, + `Ix.Theory.Certified.CheckedBatch.acyclic, + `Ix.Theory.Certified.CheckedBatch.no_circular_discharge, + `Ix.Theory.Certified.CheckedBatch.leaf_axiom_retained, + `Ix.Theory.Certified.CheckedBatch.logicalUses_authorized, + `Ix.Theory.Certified.checkBatch?_assoc, + `Ix.Theory.Certified.CheckedBatch.no_False, + `Ix.Theory.Certified.acceptsCertified, + `Ix.Theory.Certified.accepted_has_model, + `Ix.Theory.Certified.accepted_proof_sound, + `Ix.Theory.Certified.no_proof_of_False, + `Ix.Theory.Certified.no_proof_of_empty] + +private def baseline : Array Name := #[`propext, `Classical.choice, `Quot.sound] + +/-- Definitions whose logical content is hidden behind a name in a root's +pretty-printed type. Changes to their bodies must change the frozen report. -/ +private def premiseDefinitions : Array Name := #[ + `Ix.Theory.Model.AExpr.mapRefs, + `Ix.Theory.Certified.Modeled.EquationWitness.mk, + `Ix.Theory.Certified.Modeled.EquationProof.propositional, + `Ix.Theory.Certified.Modeled.CheckedEquation.mk, + `Ix.Theory.Certified.Modeled.checkEquation?, + `Ix.Theory.Certified.Modeled.Companion.mk, + `Ix.Theory.Certified.Modeled.Companion.entry, + `Ix.Theory.Certified.Modeled.mapping, + `Ix.Theory.Certified.Modeled.CompanionChecked.mk, + `Ix.Theory.Certified.Modeled.CheckedCompanions.mk, + `Ix.Theory.Certified.Modeled.checkCompanions?, + `Ix.Theory.Certified.Modeled.assignment, + `Ix.Theory.Certified.Modeled.SourceMatches, + `Ix.Theory.Certified.Modeled.sourceRefs?, + `Ix.Theory.Certified.Modeled.sourceRules?, + `Ix.Theory.Certified.Modeled.betaHead?, + `Ix.Theory.Certified.Modeled.majorSource?, + `Ix.Theory.Certified.Modeled.ruleSource?, + `Ix.Theory.Certified.Modeled.Witness.mk, + `Ix.Theory.Certified.Modeled.Checked.mk, + `Ix.Theory.Certified.Modeled.EntrySource, + `Ix.Theory.Model.Equinumerous, `Ix.Theory.Model.IsTGUniverse, + `Ix.Theory.Model.SetTheory.mk, + `Ix.Theory.Model.AExpr.Scope, `Ix.Theory.Model.Reading, + `Ix.Theory.Certified.DefinitionReading.mk, + `Ix.Theory.Certified.PrimitiveSignature.mk, + `Ix.Theory.Certified.CheckedStore.mk, + `Ix.Theory.Certified.SourceHeader.mk, + `Ix.Theory.Certified.CheckedInterface.mk, + `Ix.Theory.Certified.CheckedExtension.mk, + `Ix.Theory.Certified.FrontierWitness.mk, + `Ix.Theory.Certified.FrontierHeader.mk, + `Ix.Theory.Certified.deferredSource, + `Ix.Theory.Certified.CheckedFrontier.mk, + `Ix.Theory.Certified.CheckedFrontier.interface, + `Ix.Theory.Certified.HeaderPresent, + `Ix.Theory.Certified.ConditionalStore.mk, + `Ix.Theory.Certified.ClaimNode.mk, + `Ix.Theory.Certified.CheckedNode.mk, + `Ix.Theory.Certified.ReplayResult.mk, + `Ix.Theory.Certified.CheckedBatch.mk, + `Ix.Theory.Certified.DependencyOrder.nil, + `Ix.Theory.Certified.DependencyOrder.cons, + `Ix.Theory.Certified.DependencyEdge, + `Ix.Theory.Certified.outstanding, + `Ix.Theory.Certified.logicalAxioms, + `Ix.Theory.Certified.CheckedBatch.logicalUses, + `Ix.Theory.Model.WellDenoted, `Ix.Theory.Model.Context.Valid, + `Ix.Theory.Model.TypingClaim, `Ix.Theory.Model.ConversionClaim, + `Ix.Theory.Model.ConstantEntry.mk, `Ix.Theory.Model.Realizes.mk, + `Ix.Theory.Model.ConstantEquation.mk, + `Ix.Theory.Model.ConstantFact.typed, + `Ix.Theory.Model.ConstantFact.natural, + `Ix.Theory.Model.ConstantFact.Meaning, + `Ix.Theory.Model.ConstantFact.Scope, + `Ix.Theory.Model.ConstantFact.ReferencesIn, + `Ix.Theory.Model.NaturalMeaning.mk, + `Ix.Theory.Model.projectValue, + `Ix.Theory.Model.Numeral.zero, + `Ix.Theory.Model.Numeral.succ, + `Ix.Theory.Model.Numeral.value, + `Ix.Theory.Model.Environment.WF.mk, `Ix.Theory.Model.Assignment.AgreesOn, + `Ix.Theory.Model.IndexedContainer.mk, `Ix.Theory.Model.IndexedContainer.WF.mk, + `Ix.Theory.Model.IndexedContainer.LargeElim, `Ix.Theory.Model.IndexedContainer.AlgebraTyping, + `Ix.Theory.Certified.TelescopeBound, `Ix.Theory.Certified.TelescopeProp, + `Ix.Theory.Certified.ArgumentsFit, + `Ix.Theory.Certified.Ordinary.Shape.mk, + `Ix.Theory.Certified.Ordinary.Constructor.mk, + `Ix.Theory.Certified.Ordinary.RecursiveField.mk, + `Ix.Theory.Certified.Ordinary.CheckedShape.mk, + `Ix.Theory.Certified.Ordinary.ConstructorEvidence, + `Ix.Theory.Certified.Ordinary.RecursiveEvidence, + `Ix.Theory.Certified.Ordinary.LargeEvidence, + `Ix.Theory.Certified.Ordinary.Shape.container, + `Ix.Theory.Certified.Ordinary.FamilyReading.mk, + `Ix.Theory.Certified.Ordinary.ConstructorReading.mk, + `Ix.Theory.Certified.Ordinary.RecursorReading.mk, + `Ix.Theory.Certified.Ordinary.ModeEvidence, + `Ix.Theory.Certified.Ordinary.Shape.ConstructorFormation, + `Ix.Theory.Certified.Ordinary.Shape.RecursorFormation.mk, + `Ix.Theory.Certified.Ordinary.Shape.SupportsK, + `Ix.Theory.Certified.Ordinary.Shape.RecursorSourceMatches, + `Ix.Theory.Certified.Ordinary.Shape.RuleFormation.mk, + `Ix.Theory.Certified.Ordinary.CheckedBlock.mk, + `Ix.Theory.Certified.Ordinary.EntrySource, + `Ix.Theory.Certified.Ordinary.Shape.recursorAt, + `Ix.Theory.Certified.Ordinary.BlockWitness.mk, + `Ix.Theory.Certified.DeclarationWitness.definition, + `Ix.Theory.Certified.DeclarationWitness.ordinary, + `Ix.Theory.Certified.DeclarationWitness.standard, + `Ix.Theory.Certified.DeclarationWitness.quotient, + `Ix.Theory.Certified.DeclarationWitness.structure, + `Ix.Theory.Certified.DeclarationWitness.natural, + `Ix.Theory.Certified.Natural.shape, + `Ix.Theory.Certified.Natural.fact, + `Ix.Theory.Certified.Natural.entry, + `Ix.Theory.Certified.Natural.environment, + `Ix.Theory.Certified.Natural.Checked.mk, + `Ix.Theory.Certified.Natural.EntrySource, + `Ix.Theory.Certified.Structure.Field.mk, + `Ix.Theory.Certified.Structure.Description.mk, + `Ix.Theory.Certified.Structure.Description.ordinary, + `Ix.Theory.Certified.Structure.FieldsFormed.nil, + `Ix.Theory.Certified.Structure.FieldsFormed.cons, + `Ix.Theory.Certified.Structure.fieldResult, + `Ix.Theory.Certified.Structure.Description.facts, + `Ix.Theory.Certified.Structure.Description.equations, + `Ix.Theory.Certified.Structure.Description.iotaEnvironment, + `Ix.Theory.Certified.Structure.Description.etaRule, + `Ix.Theory.Certified.Structure.Description.iotaRule, + `Ix.Theory.Certified.Structure.FactsWitness.mk, + `Ix.Theory.Certified.Structure.Witness.mk, + `Ix.Theory.Certified.Structure.FactsChecked.mk, + `Ix.Theory.Certified.Structure.Checked.mk, + `Ix.Theory.Certified.Structure.EntrySource, + `Ix.Theory.Model.Environment.HasType, + `Ix.Theory.Certified.Basis.Equality.Interface.mk, + `Ix.Theory.Certified.Basis.Equality.shape, + `Ix.Theory.Certified.Basis.Equality.type, + `Ix.Theory.Certified.Basis.Equality.reflType, + `Ix.Theory.Certified.Basis.Equality.recType, + `Ix.Theory.Certified.Basis.Iff.Interface.mk, + `Ix.Theory.Certified.Basis.Iff.shape, + `Ix.Theory.Certified.Basis.Iff.type, + `Ix.Theory.Certified.Basis.Iff.introType, + `Ix.Theory.Certified.Basis.Iff.recType, + `Ix.Theory.Certified.Basis.Nonempty.Interface.mk, + `Ix.Theory.Certified.Basis.Nonempty.shape, + `Ix.Theory.Certified.Basis.Nonempty.type, + `Ix.Theory.Certified.Basis.Nonempty.introType, + `Ix.Theory.Certified.Basis.Nonempty.recType, + `Ix.Theory.Certified.Standard.Spec.Prerequisites, + `Ix.Theory.Certified.Standard.Spec.type, + `Ix.Theory.Certified.Standard.Spec.value, + `Ix.Theory.Certified.Standard.chooseSet, + `Ix.Theory.Certified.Standard.Witness.mk, + `Ix.Theory.Certified.Standard.Checked.mk, + `Ix.Theory.Certified.Standard.EntrySource, + `Ix.Theory.Certified.Signature.Header.mk, + `Ix.Theory.Certified.Signature.Formed.nil, + `Ix.Theory.Certified.Signature.Formed.cons, + `Ix.Theory.Certified.Signature.TypeWitness.mk, + `Ix.Theory.Certified.Signature.Rule.mk, + `Ix.Theory.Certified.Signature.RuleFormed.mk, + `Ix.Theory.Certified.Signature.RuleWitness.mk, + `Ix.Theory.Model.SetTheory.quotSet, + `Ix.Theory.Model.SetTheory.quotClass, + `Ix.Theory.Model.SetTheory.qrep, + `Ix.Theory.Model.SetTheory.QuotRel.base, + `Ix.Theory.Model.SetTheory.QuotRel.refl, + `Ix.Theory.Model.SetTheory.QuotRel.symm, + `Ix.Theory.Model.SetTheory.QuotRel.trans, + `Ix.Theory.Certified.Quotient.Refs.mk, + `Ix.Theory.Certified.Quotient.Refs.ExactSource, + `Ix.Theory.Certified.Quotient.Refs.environment, + `Ix.Theory.Certified.Quotient.Refs.assignment, + `Ix.Theory.Certified.Quotient.Refs.entryType, + `Ix.Theory.Certified.Quotient.Refs.source, + `Ix.Theory.Certified.Quotient.Refs.equations, + `Ix.Theory.Certified.Quotient.Reading.mk, + `Ix.Theory.Certified.Quotient.Witness.mk, + `Ix.Theory.Certified.Quotient.Checked.mk, + `Ix.Theory.Certified.Quotient.EntrySource, + `Ix.Theory.Certified.Quotient.formerValue, + `Ix.Theory.Certified.Quotient.constructorValue, + `Ix.Theory.Certified.Quotient.liftValue, + `Ix.Theory.Certified.PrimitiveSignature.Compatible.mk, + `Ix.Theory.Certified.EntrySource, `Ix.Theory.Certified.Extends.mk, + `Ix.Theory.Certified.AdmittedEnvironment.mk, + `Ix.Theory.Certified.CheckedClaim.mk, + `Ix.Theory.Certified.InferenceResult.mk, `Ix.Theory.Certified.WhnfResult.mk, + `Ix.Theory.Store.mk, `Ix.Theory.Certified.ProofInput.mk, + `Ix.Theory.Certified.ProofWitness.mk, `Ix.Theory.Certified.CheckedProof.mk] + +private def directConstants (info : ConstantInfo) : Array Name := + info.type.getUsedConstants ++ match info with + | .thmInfo value => value.value.getUsedConstants + | .defnInfo value => value.value.getUsedConstants + | .opaqueInfo value => value.value.getUsedConstants + | .inductInfo value => value.ctors.toArray + | _ => #[] + +private partial def closure (env : Environment) (pending : List Name) + (seen : NameSet := {}) : NameSet := + match pending with + | [] => seen + | name :: rest => + if seen.contains name then closure env rest seen + else match env.checked.get.find? name with + | some info => closure env ((directConstants info).toList ++ rest) (seen.insert name) + | none => closure env rest (seen.insert name) + +private def axiomsIn (env : Environment) (dependencies : NameSet) : Array Name := + dependencies.toList.toArray.filter fun name => + match env.checked.get.find? name with + | some (.axiomInfo _) => true + | _ => false + +private def forbiddenModule (name : Name) : Bool := + ((`Ix).isPrefixOf name && !(`Ix.Theory).isPrefixOf name) || + #[`Ix.Theory.Named, `Tests, `Benchmarks, `Ix.Theory.Fixtures, `Ix.Theory.Tests, `Ix.Theory.Harness, + `Ix.Theory.Audit, `Ix.Theory.Typing.Conjectures, + `Ix.Theory.Typing.UniqueTyping].any (·.isPrefixOf name) + +run_cmd do + let env ← getEnv + let modules := env.allImportedModuleNames + let some boundary := modules.toList.idxOf? `Ix.Theory.Certified | + throwError "certified audit: public target is missing" + -- The audit's own Lean import is outside the certified boundary. Walk the + -- mathematical import graph from that boundary. Meta-only tactic imports + -- are tooling, and are outside this graph; proof constants remain audited. + let mut pending := [boundary] + let mut visited : List Nat := [] + while let index :: rest := pending do + pending := rest + unless visited.contains index do + visited := index :: visited + let name := modules[index]! + if forbiddenModule name || (`Lean).isPrefixOf name then + throwError m!"certified target imports forbidden module {name}" + for dependency in env.header.moduleData[index]!.imports do + unless dependency.isMeta do + if let some depIndex := modules.toList.idxOf? dependency.module then + pending := depIndex :: pending + + -- Freeze the foundational premise's complete fields. It must never acquire + -- a field that postulates kernel acceptance or semantic soundness. + let some foundation := getStructureInfo? env `Ix.Theory.Model.SetTheory | + throwError "certified audit: SetTheory is missing" + let expectedFields : Array Name := #[ + `Mem, `ext, `upair, `mem_upair, `sUnion, `mem_sUnion, `power, `mem_power, + `regularity, `image, `mem_image, `univChain, `univChain_mem, `univChain_tg] + unless foundation.fieldNames == expectedFields do + throwError m!"certified audit: foundational fields changed: {foundation.fieldNames}" + + let mut declarations : Nat := 0 + let mut recursionWorkers : Array Name := #[] + let mut projectDeclarations : List Name := [] + for (name, _) in env.constants.toList do + if let some index := env.getModuleIdxFor? name then + if visited.contains index.toNat && (`Ix.Theory).isPrefixOf modules[index.toNat]! then + declarations := declarations + 1 + projectDeclarations := name :: projectDeclarations + -- Compiled replacements and unsafe implementations are a separate + -- boundary from proof axioms. User-authored escapes are forbidden; + -- the compiler's recursion workers are inventoried in full below. + if (Lean.Compiler.getImplementedBy? env name).isSome || Lean.isExtern env name || + Lean.Elab.ComputedFields.computedFieldAttr.hasTag env name then + throwError m!"certified declaration has an unreviewed runtime replacement: {name}" + if let some replacement := (Lean.Compiler.CSimp.ext.getState env).map.find? name then + throwError m!"certified declaration has an unreviewed csimp replacement: {name} -> {replacement.toDeclName}" + if let some info := env.find? name then + match info with + | .defnInfo value => + unless value.safety == .safe do + let some parent := Lean.Compiler.isUnsafeRecName? name | + throwError m!"certified declaration is unsafe or partial: {name}" + let some (.defnInfo original) := env.find? parent | + throwError m!"recursion worker has no source definition: {name}" + unless original.safety == .safe do + throwError m!"recursion worker's source is not safe: {name}" + recursionWorkers := recursionWorkers.push name + | .opaqueInfo value => + if value.isUnsafe then throwError m!"certified opaque declaration is unsafe: {name}" + | _ => pure () + unless declarations > 0 do throwError "certified audit measured no project declarations" + + -- Traverse the checked declarations, including every constructor field. + -- Imported axiom summaries can omit dependencies of recursive groups. + for axiomName in axiomsIn env (closure env projectDeclarations) do + unless baseline.contains axiomName do + throwError m!"certified foundation reaches unapproved axiom {axiomName}" + + for root in roots do + let some info := env.find? root | + throwError m!"certified audit: missing root {root}" + let dependencies := closure env [root] + unless dependencies.size > 1 do + throwError m!"certified audit: empty dependency measurement for {root}" + let type ← liftTermElabM <| Meta.ppExpr info.type + let axioms := (axiomsIn env dependencies).qsort Name.lt + let mut projectModules : NameSet := {} + for dependency in dependencies.toList do + if let some index := env.getModuleIdxFor? dependency then + let moduleName := modules[index.toNat]! + if (`Ix.Theory).isPrefixOf moduleName then + projectModules := projectModules.insert moduleName + let moduleRows := projectModules.toList.toArray.qsort Name.lt + logInfo m!"certified root {root}\n type: {type}\n axioms: {axioms}\n constants: {dependencies.size}\n project modules: {moduleRows}" + for name in premiseDefinitions do + let some info := env.find? name | + throwError m!"certified audit: missing premise definition {name}" + let type ← liftTermElabM <| Meta.ppExpr info.type + match info with + | .defnInfo value => + let body ← liftTermElabM <| Meta.ppExpr value.value + logInfo m!"premise definition {name}\n type: {type}\n definition: {body}" + | .ctorInfo _ => logInfo m!"premise constructor {name}\n type: {type}" + | _ => throwError m!"certified audit: unclassified premise definition {name}" + for name in recursionWorkers.qsort Name.lt do + let some (.defnInfo value) := env.find? name | + throwError m!"certified audit: missing recursion worker {name}" + let type ← liftTermElabM <| Meta.ppExpr value.type + let body ← liftTermElabM <| Meta.ppExpr value.value + logInfo m!"compiler recursion worker {name}\n type: {type}\n implementation: {body}" + logInfo m!"Certified project runtime audit OK: {recursionWorkers.size} compiler recursion workers inventoried; no other unsafe/partial declarations, extern, implemented_by, computed_field, or csimp replacements in the mathematical import graph" + logInfo m!"Certified foundation audit OK: {declarations} declarations; {roots.size} named roots; explicit SetTheory hypothesis; baseline axioms only" + +end Tests.Theory.Audit.Certified diff --git a/Tests/Theory/Certified.lean b/Tests/Theory/Certified.lean new file mode 100644 index 000000000..75734ccc5 --- /dev/null +++ b/Tests/Theory/Certified.lean @@ -0,0 +1,76 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified + +open Ix.Theory + +/-! Structural and universe-validation regressions. These do not yet exercise +proof acceptance; that gate will add its own corpus when implemented. -/ + +namespace Tests.Theory.Certified + +open Ix.Theory.Certified Ix.Theory.Model + +#guard (PropWhen.ofList [2, 0, 2]).toRaw == some [0, 2] +#guard PropWhen.fromRaw? 2 (some [0, 1]) |>.isSome +#guard PropWhen.fromRaw? 2 (some [1, 0]) |>.isNone +#guard PropWhen.fromRaw? 1 (some [0, 0]) |>.isNone +#guard PropWhen.fromRaw? 1 (some [1]) |>.isNone +#guard validateZero? 1 (.param 0) (some [0]) |>.isSome +#guard validateZero? 1 (.param 0) none |>.isNone +#guard validateZero? 1 (.param 0) (some []) |>.isNone +#guard validateZero? 0 (.succ (.param 0)) none |>.isNone +#guard validateZero? 0 (.imax (.param 0) .zero) (some []) |>.isNone +#guard validateZero? 2 (.imax (.param 0) (.param 1)) (some [1]) |>.isSome +#guard (zeroCondition (.imax (.param 0) (.param 1))).holds ([5, 0].getD · 0) +#guard !(zeroCondition (.imax (.param 0) (.param 1))).holds ([0, 5].getD · 0) +#guard (instCondition [.succ .zero] (.param 0)).toRaw == none +#guard (instCondition [.zero] (.param 0)).toRaw == some [] + +-- Equal zero conditions do not imply equal universes. +example : zeroCondition (.succ .zero) = zeroCondition (.succ (.succ .zero)) := rfl +example : VLevel.eval [] (.succ .zero) ≠ VLevel.eval [] (.succ (.succ .zero)) := by decide + +def identity : VExpr Nat := .lam (.sort (.param 0)) (.lam (.bvar 0) (.bvar 0)) +def identityAnnotations : AnnotationTree := + .lam (some [0]) .leaf (.lam (some [0]) .leaf .leaf) + +#guard readAnnotations? 1 0 identity identityAnnotations |>.isSome +#guard ((readAnnotations? 1 0 identity identityAnnotations).map (·.val.erase)) == some identity +#guard readAnnotations? 0 0 identity identityAnnotations |>.isNone +#guard readAnnotations? 1 0 identity .leaf |>.isNone +-- The same source node at two context depths is checked separately. +#guard readAnnotations? 0 1 (VExpr.bvar (β := Nat) 0) .leaf |>.isSome +#guard readAnnotations? 0 0 (VExpr.bvar (β := Nat) 0) .leaf |>.isNone + +def primitives : PrimitiveSignature Nat := ⟨.member 10 0, .member 11 0, by decide, none⟩ + +def primitiveStore (falseDecl recDecl : Const Nat) : Store Nat where + dom := [10, 11] + nodup := by decide + blocks b := if b = 10 then some ⟨[falseDecl]⟩ else if b = 11 then some ⟨[recDecl]⟩ else none + mem_dom b := by + by_cases h : b = 10 <;> by_cases h' : b = 11 <;> simp_all + +#guard primitives.validate (primitiveStore PrimitiveSignature.falseDeclaration + primitives.falseElimDeclaration) +#guard !primitives.validate (primitiveStore (.axiom 0 (.sort .zero) .safe) + primitives.falseElimDeclaration) +#guard !primitives.validate (primitiveStore PrimitiveSignature.falseDeclaration + (.recursor 0 0 0 1 0 primitives.falseElimType [] false .safe)) +#guard !primitives.validate (primitiveStore PrimitiveSignature.falseDeclaration + (.recursor 1 0 0 1 0 primitives.falseElimType [] true .safe)) +#guard !primitives.validate (primitiveStore + (.induct 0 0 0 (.sort .zero) [⟨0, 0, 0, primitives.falseExpr, .safe⟩] .safe) + primitives.falseElimDeclaration) + +#guard readDefinition? (Const.axiom 0 primitives.falseExpr .safe) .leaf .leaf |>.isNone +#guard readDefinition? (Const.axiom (β := Nat) 0 (.forallE (.sort .zero) (.bvar 0)) .safe) + .leaf .leaf |>.isNone +#guard readDefinition? (Const.defn 0 .opaque primitives.falseExpr (.sort .zero) .unsafe) + .leaf .leaf |>.isNone + +end Tests.Theory.Certified diff --git a/Tests/Theory/Checker.lean b/Tests/Theory/Checker.lean new file mode 100644 index 000000000..0d0a8e61f --- /dev/null +++ b/Tests/Theory/Checker.lean @@ -0,0 +1,86 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Checker + +open Ix.Theory + +namespace Tests.Theory.Checker + +open Ix.Theory.Certified Ix.Theory.Model + +def emptyEnvironment : Environment Nat := fun _ => none + +def identity (l : VLevel) : AExpr Nat := + .lam (zeroCondition l) (.sort l) (.lam (zeroCondition l) (.bvar 0) (.bvar 0)) + +def identityType (l : VLevel) : AExpr Nat := + .forallE (zeroCondition l) (.sort l) (.forallE (zeroCondition l) (.bvar 0) (.bvar 1)) + +def identityWitness (l : VLevel) : TypingWitness Nat := + .lam (.succ l) (.imax l l) (.forallE (zeroCondition l) (.bvar 0) (.bvar 1)) + .sort (.forallE l l .bvar .bvar) + (.lam l l (.bvar 1) .bvar .bvar .bvar) + +#guard checkTypeCertified.{0,0} 30 1 emptyEnvironment [] (identity (.param 0)) + (identityType (.param 0)) (identityWitness (.param 0)) +#guard checkTypeCertified.{0,0} 30 0 emptyEnvironment [] (identity .zero) + (identityType .zero) (identityWitness .zero) +#guard checkTypeCertified.{0,0} 30 0 emptyEnvironment [] (identity (.succ .zero)) + (identityType (.succ .zero)) (identityWitness (.succ .zero)) + +-- The same parameterized expression is rejected with a missing universe slot. +#guard !checkTypeCertified.{0,0} 30 0 emptyEnvironment [] (identity (.param 0)) + (identityType (.param 0)) (identityWitness (.param 0)) + +-- Structural erasure alone would permit this false annotation. +def wrongIdentity : AExpr Nat := .lam .never (.sort .zero) (.lam .never (.bvar 0) (.bvar 0)) +def wrongIdentityType : AExpr Nat := + .forallE .never (.sort .zero) (.forallE .never (.bvar 0) (.bvar 1)) +#guard !checkTypeCertified.{0,0} 30 0 emptyEnvironment [] wrongIdentity wrongIdentityType + (identityWitness .zero) + +def betaSource : AExpr Nat := .app (identity (.succ .zero)) (.sort .zero) +def betaResult : AExpr Nat := .lam .never (.sort .zero) (.bvar 0) +def betaWitness : ConversionWitness Nat := + .beta (identityType (.succ .zero)) (identityWitness (.succ .zero)) .sort +#guard defeqCertified.{0,0} 30 0 emptyEnvironment [] betaSource betaResult betaWitness + +-- A proposed beta step cannot substitute an argument outside the lambda domain. +#guard !defeqCertified.{0,0} 30 0 emptyEnvironment [] + (.app (identity (.succ .zero)) (.sort (.succ .zero))) + (.lam .never (.sort (.succ .zero)) (.bvar 0)) betaWitness +-- This check is required in the proof-point regime too. +#guard !defeqCertified.{0,0} 30 0 emptyEnvironment [] + (.app (identity .zero) (.sort .zero)) + (.lam .always (.sort .zero) (.bvar 0)) + (.beta (identityType .zero) (identityWitness .zero) .sort) + +def etaSource : AExpr Nat := + .lam .never (.sort (.succ .zero)) + (.app ((identity (.succ .zero)).liftN 1) (.bvar 0)) +#guard defeqCertified.{0,0} 30 0 emptyEnvironment [] etaSource (identity (.succ .zero)) + (.eta (.forallE .never (.bvar 0) (.bvar 1)) (identityWitness (.succ .zero))) + +def proofContext : Context Nat := + Context.push (.bvar 1) (Context.push (.bvar 0) (Context.push (.sort .zero) [])) +#guard defeqCertified.{0,0} 30 0 emptyEnvironment proofContext (.bvar 0) (.bvar 1) + (.proofIrrel (.bvar 2) .bvar .bvar .bvar) + +#guard LevelEq.check 1 (.imax (.param 0) (.param 0)) (.param 0) +#guard LevelEq.check 0 (.imax (.succ .zero) .zero) .zero +#guard !LevelEq.check 0 (.succ .zero) (.succ (.succ .zero)) +#guard !LevelEq.check 0 (.imax (.param 0) .zero) .zero +#guard defeqCertified.{0,0} 10 1 emptyEnvironment [] + (.sort (.imax (.param 0) (.param 0))) (.sort (.param 0)) .sort +#guard !defeqCertified.{0,0} 10 0 emptyEnvironment [] + (.sort (.succ .zero)) (.sort (.succ (.succ .zero))) .sort + +#guard !checkTypeCertified.{0,0} 0 1 emptyEnvironment [] (identity (.param 0)) + (identityType (.param 0)) (identityWitness (.param 0)) +#guard !checkTypeCertified.{0,0} 30 0 emptyEnvironment [] (.natLit 0) (.sort .zero) .const +#guard !checkTypeCertified.{0,0} 30 0 emptyEnvironment [] (.const (.member 42 0) []) (.sort .zero) .const + +end Tests.Theory.Checker diff --git a/Tests/Theory/Claims.lean b/Tests/Theory/Claims.lean new file mode 100644 index 000000000..f8376371c --- /dev/null +++ b/Tests/Theory/Claims.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Claims +import Ix.Theory.Certified.ClaimComposition +import Tests.Theory.Acceptance +import Tests.Theory.Standard + +open Ix.Theory + +namespace Tests.Theory.Claims + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certificate +open Tests.Theory.Certified (primitives) +open Tests.Theory.Checker (identity identityType) + +set_option maxRecDepth 8192 +set_option maxHeartbeats 8000000 + +def ref (n : Nat) : ConstRef Nat := .member n 0 +def aliasDeclaration (n : Nat) : Const Nat := + .defn 1 .theorem (identityType (.param 0)).erase (.const (ref n) [.param 0]) .safe + +def declaration : Nat → Const Nat + | 10 => PrimitiveSignature.falseDeclaration + | 11 => primitives.falseElimDeclaration + | 12 => Acceptance.idDeclaration + | 13 | 14 => aliasDeclaration 12 + | 15 => .defn 1 .theorem (identityType (.param 0)).erase + (.app (.lam (identityType (.param 0)).erase (.const (ref 13) [.param 0])) + (.const (ref 14) [.param 0])) .safe + | _ => .axiom 0 primitives.falseExpr .safe + +def store (alter : Nat → Const Nat → Const Nat := fun _ c => c) : Store Nat where + dom := [10, 11, 12, 13, 14, 15] + nodup := by decide + blocks b := if b ∈ [10, 11, 12, 13, 14, 15] then some ⟨[alter b (declaration b)]⟩ else none + mem_dom b := by split <;> simp_all + +def specs : List (List (ConstRef Nat) × List (ConstRef Nat)) := + [([], [ref 12]), ([ref 12], [ref 13]), ([ref 12], [ref 14]), ([ref 13, ref 14], [ref 15])] + +def nodes? (source : Store Nat := store) : Option (List (ClaimNode Nat)) := + specs.mapM fun (frontier, subjects) => claimNode? 1000 primitives source frontier subjects + +def accepted (source : Store Nat) (nodes : List (ClaimNode Nat)) : Bool := + (batchFrontier? 1000 primitives source nodes).any fun frontier => + acceptsBatch.{0,0} 1000 primitives source frontier nodes + +def positive : Bool := (nodes?).any (accepted store) +#guard positive + +-- Each leaf is independently a valid conditional check. +#guard (nodes?).any fun nodes => nodes.all fun node => + (checkNode?.{0,0} 1000 primitives store node).isSome + +-- The same diamond can retain A as a genuine external obligation. +#guard (nodes?).any fun nodes => accepted store (nodes.drop 1) +#guard (nodes?).any fun nodes => + (batchFrontier? 1000 primitives store (nodes.drop 1)).any fun frontier => + (checkBatch?.{0,0} 1000 primitives store frontier (nodes.drop 1)).any fun result => + result.receipt.frontier.refs == [ref 12] + +-- Structural discharge closes all four subjects and produces their model. +#guard (nodes?).any fun nodes => + (checkBatch?.{0,0} 1000 primitives store [] nodes).any fun result => + result.receipt.frontier.refs.isEmpty && nodeSubjects result.nodes == [ref 12, ref 13, ref 14, ref 15] + +-- A reverse dependency cannot be supplied by a later node. +#guard (nodes?).any fun nodes => !accepted store nodes.reverse +#guard (nodes?).any fun nodes => !accepted store (nodes[0]! :: nodes[3]! :: [nodes[1]!, nodes[2]!]) +-- Repeated subjects share an existing checked interpretation. +#guard (nodes?).any fun nodes => accepted store (nodes ++ nodes) +#guard (nodes?).any fun nodes => + !(acceptsBatch.{0,0} 1000 primitives store [] (nodes.drop 1)) +#guard (nodes?).any fun nodes => + !(acceptsBatch.{0,0} 0 primitives store [] nodes) + +-- Source changes reject an original valid leaf certificate. +#guard (nodes?).any fun nodes => + !accepted (store fun n c => if n = 15 then + .defn 1 .theorem primitives.falseExpr (.const (ref 13) [.param 0]) .safe else c) nodes +#guard (nodes?).any fun nodes => + !accepted (store fun n c => if n = 12 then .axiom 1 (identityType (.param 0)).erase .safe else c) nodes + +def cyclicStore : Store Nat := store fun n c => + if n = 12 then .defn 0 .theorem primitives.falseExpr (.const (ref 13) []) .safe + else if n = 13 then .defn 0 .theorem primitives.falseExpr (.const (ref 12) []) .safe else c + +def cyclicNodes? : Option (List (ClaimNode Nat)) := do + return [← claimNode? 1000 primitives cyclicStore [ref 13] [ref 12], + ← claimNode? 1000 primitives cyclicStore [ref 12] [ref 13]] + +-- Both conditional implications pass, but neither circular ordering closes. +#guard cyclicNodes?.any fun nodes => nodes.all fun node => + (checkNode?.{0,0} 1000 primitives cyclicStore node).isSome +#guard cyclicNodes?.any fun nodes => !accepted cyclicStore nodes +#guard cyclicNodes?.any fun nodes => !accepted cyclicStore nodes.reverse + +-- Claiming a deferred member as an owned subject is rejected. +#guard (claimNode? 1000 primitives store [ref 12] [ref 12]).any fun node => + (checkNode?.{0,0} 1000 primitives store node).isNone + +-- A source axiom cannot enter as a deferred assumption, including supported +-- schemas: their semantic producer must run, and their use remains recorded. +#guard (frontierWitnesses? 1000 Standard.store primitives.environment [Standard.propextRef]).isNone + +def standardNodes? : Option (List (ClaimNode Nat)) := do + return [← claimNode? 2000 primitives Standard.store [] [Standard.propextRef], + ← claimNode? 2000 primitives Standard.store [] [Standard.choiceRef]] + +#guard standardNodes?.any fun nodes => + (checkBatch?.{0,0} 2000 primitives Standard.store [] nodes).any fun result => + result.receipt.frontier.refs.isEmpty && + result.logicalUses == [Standard.propextRef, Standard.choiceRef] + +-- The recorded axiom remains even when that same reference is a checked subject. +#guard standardNodes?.any fun nodes => + (checkBatch?.{0,0} 2000 primitives Standard.store [] (nodes.take 1)).any fun result => + Standard.propextRef ∈ nodeSubjects result.nodes && + Standard.propextRef ∈ result.logicalUses + +-- Regrouping composition has identical acceptance and complete subjects. +#guard nodes?.any fun nodes => + accepted store (composeClaims (composeClaims (nodes.take 1) ((nodes.drop 1).take 1)) (nodes.drop 2)) && + accepted store (composeClaims (nodes.take 1) (composeClaims ((nodes.drop 1).take 1) (nodes.drop 2))) + +end Tests.Theory.Claims diff --git a/Tests/Theory/ImportManifest.lean b/Tests/Theory/ImportManifest.lean new file mode 100644 index 000000000..43e9e7b9c --- /dev/null +++ b/Tests/Theory/ImportManifest.lean @@ -0,0 +1,176 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +/-! Import provenance, recorded from the Lean4Ix working tree on 2026-09-11. +The working tree contained the new, uncommitted consistency model; the base +revision alone does not identify these inputs. Source hashes identify each file. +The selected file inventory is enforced by `Tests/Theory/Provenance.lean`. +The generated `Ix/Theory.lean` umbrella records its sole upstream import. -/ + +namespace Tests.Theory.ImportManifest + +def lean4IxBaseRevision : String := "ab42e79e2a4e2615a3ca6ef983d510f374057a38" +def conLecheRevision : String := "86cd20a65660d757cedc81561a44579099b565d0" + +structure SourceFile where + source : String + target : String + sourceSha256 : String + deriving Repr + +def selected : Array SourceFile := #[ + ⟨"Lean4Ix/Certificate/Build.lean", "Ix/Theory/Certificate/Build.lean", "833e462fae9934f3d7809fc78b7c791d7ede3ab4398732079f26ea73f53abc4c"⟩, + ⟨"Lean4Ix/Certificate/Claims.lean", "Ix/Theory/Certificate/Claims.lean", "c3532bd7b49d0657f52913f4da285580aa2de467ecd27b41f5263a165ae34d0f"⟩, + ⟨"Lean4Ix/Certificate/Modeled.lean", "Ix/Theory/Certificate/Modeled.lean", "28d4f7cd3bdb5945d31b8f6f10c686d6c22889e96511c765b7a28c59b17ac47a"⟩, + ⟨"Lean4Ix/Certificate/Ordinary.lean", "Ix/Theory/Certificate/Ordinary.lean", "7c85145faf3bef4f934087fe9694171dd457c2e84190000f8c5c355af9d357c3"⟩, + ⟨"Lean4Ix/Certificate/OrdinarySource.lean", "Ix/Theory/Certificate/OrdinarySource.lean", "291704dd2ff2d53d70ac73876ff1505eb99c96e4a029f46e9428dc64eadd24f4"⟩, + ⟨"Lean4Ix/Certificate/Quotient.lean", "Ix/Theory/Certificate/Quotient.lean", "8c5a44003cc09313a600d3e53ebf0de1bfbee5d64c6c24fa6753fc87659aad83"⟩, + ⟨"Lean4Ix/Certificate/Standard.lean", "Ix/Theory/Certificate/Standard.lean", "54605d2a22c2671429fe65e9cd210677deee90dc38f629991f1f0f1dc157bea8"⟩, + ⟨"Lean4Ix/Certificate/Structure.lean", "Ix/Theory/Certificate/Structure.lean", "a0e5c274ed5c5ced8854841144086396d11c105b080bdb2c46b8ccf44d34a1d2"⟩, + ⟨"Lean4Ix/Certificate/Suggest.lean", "Ix/Theory/Certificate/Suggest.lean", "d7863536599fa0554d4ce34427b496b306301982cdef8a9bda2395380fd1ee2a"⟩, + ⟨"Lean4Ix/Certified.lean", "Ix/Theory/Certified.lean", "db42519eb53c5c24965b27879cb1ad81eca1010513fc67cf486f324c942fce98"⟩, + ⟨"Lean4Ix/Certified/Accept.lean", "Ix/Theory/Certified/Accept.lean", "ce3975aa6a82f020ad6c92a5644945d3bb68ea323f97ef7eace8ba9d5d5aa80e"⟩, + ⟨"Lean4Ix/Certified/Admission.lean", "Ix/Theory/Certified/Admission.lean", "ea6a1b8d3126190332557d424957551af7d780abe98aa0af5433a928d97ba991"⟩, + ⟨"Lean4Ix/Certified/Basis/Equality.lean", "Ix/Theory/Certified/Basis/Equality.lean", "fa4886a2d0d764ba85c0711a258d0d94888a30cf39db2842290d220b1d7213c0"⟩, + ⟨"Lean4Ix/Certified/Basis/Iff.lean", "Ix/Theory/Certified/Basis/Iff.lean", "368fa1c9c359a29a5877af993f16698025d84aed967ce4720122280532644fc8"⟩, + ⟨"Lean4Ix/Certified/Basis/Interface.lean", "Ix/Theory/Certified/Basis/Interface.lean", "6bcd43996a8101c48f3f11a17f1950b3db74ca1a7cb970de324cd0fe78f8d4ce"⟩, + ⟨"Lean4Ix/Certified/Basis/Nonempty.lean", "Ix/Theory/Certified/Basis/Nonempty.lean", "5f62092f92138ee8433f9f56977aec6c03827819342bb7417080cdc2c19b35d4"⟩, + ⟨"Lean4Ix/Certified/Checker.lean", "Ix/Theory/Certified/Checker.lean", "677f0f68b1422d9ccc467234acaa12737fd97f9ecdc43755b46e12f36be9858a"⟩, + ⟨"Lean4Ix/Certified/ClaimComposition.lean", "Ix/Theory/Certified/ClaimComposition.lean", "d99702d5199447cb696e365ccbb246b3bf9663b432ead0563b6572101f19f731"⟩, + ⟨"Lean4Ix/Certified/Claims.lean", "Ix/Theory/Certified/Claims.lean", "fe28187c7eeabd148c8b737532f0559f0424397b8ba70cf2b990edd7d9623738"⟩, + ⟨"Lean4Ix/Certified/Frontier.lean", "Ix/Theory/Certified/Frontier.lean", "a0dfec4872d5e7ef728494a0a71bef107cfb243a42107fe92185e3fb0d371fb0"⟩, + ⟨"Lean4Ix/Certified/Level.lean", "Ix/Theory/Certified/Level.lean", "37c6fa05fddfc0a01a70288cf49d870a77625119be6c73bd0061fe76c0d27420"⟩, + ⟨"Lean4Ix/Certified/LevelEq.lean", "Ix/Theory/Certified/LevelEq.lean", "a6402afba171af4b4df58ea4de64b3e1517fae90bd8ce145bb96775bb4862923"⟩, + ⟨"Lean4Ix/Certified/LogicalPolicy.lean", "Ix/Theory/Certified/LogicalPolicy.lean", "763a20bd20133c2cf235c27cec875f2c67bb0ec0c5a7c25c5df82562531a496a"⟩, + ⟨"Lean4Ix/Certified/Modeled/Admission.lean", "Ix/Theory/Certified/Modeled/Admission.lean", "68c0ef0b5e19984d08e8d34c296548eceeb4f5c4f4d86d5df3174be9ae0d939c"⟩, + ⟨"Lean4Ix/Certified/Modeled/Equation.lean", "Ix/Theory/Certified/Modeled/Equation.lean", "bb49b60d019b57819c030e0ea41f853727f4d0aecb0174e31c236639747dde4d"⟩, + ⟨"Lean4Ix/Certified/Modeled/Source.lean", "Ix/Theory/Certified/Modeled/Source.lean", "ac4a72a22fc77f5a512511a19c0b0c01925cf2eca5b1c1de4f00c111b048c88d"⟩, + ⟨"Lean4Ix/Certified/Modeled/Transport.lean", "Ix/Theory/Certified/Modeled/Transport.lean", "d0d020ca9fd123fb036cd35d662b237778f9e1c24119250185cb2946bd3d99ab"⟩, + ⟨"Lean4Ix/Certified/Natural/Admission.lean", "Ix/Theory/Certified/Natural/Admission.lean", "8d7ce4e7f0da80d5ffe45b45aeba72320ec7da35bbad3eb3fdc321512ff74a1a"⟩, + ⟨"Lean4Ix/Certified/Natural/Checked.lean", "Ix/Theory/Certified/Natural/Checked.lean", "2dd7ad9e96c65a5d74a84f8c6c6cec3ba2693ab6f77aefcd7a29089529d6172b"⟩, + ⟨"Lean4Ix/Certified/Natural/Publish.lean", "Ix/Theory/Certified/Natural/Publish.lean", "fac41bc4b4a409d0266d64b4375a638ed1ec281c28ec20c993d7166072d15ca1"⟩, + ⟨"Lean4Ix/Certified/Natural/Value.lean", "Ix/Theory/Certified/Natural/Value.lean", "db39def05ce46d1da7b78209acfba10596e67642a2942ad438b38a049ab5d51b"⟩, + ⟨"Lean4Ix/Certified/Operations.lean", "Ix/Theory/Certified/Operations.lean", "9c7bb4b947421dfbaa12b7dc7ddbac0021847a0f2b2c092decfb3dd2e582fc34"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Admission.lean", "Ix/Theory/Certified/Ordinary/Admission.lean", "b19b0077e451aae6cc608d9007def64bd66523e89e2a5f558d0cf7abf77926ad"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Checked.lean", "Ix/Theory/Certified/Ordinary/Checked.lean", "04ffd22d2d6b5c0070f8e8bb6b8504b408046ae39ffd07625f2708f7994bed8e"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Computation.lean", "Ix/Theory/Certified/Ordinary/Computation.lean", "27dc5c8f9d2a7990e64c13c2fab256da3dd99d5fa5ba8eeea9134f3d39f44792"⟩, + ⟨"Lean4Ix/Certified/Ordinary/ConstructorStage.lean", "Ix/Theory/Certified/Ordinary/ConstructorStage.lean", "ebd00026aff885831dc52fa28f33be3a562d19980bbbb50ec0111b9ebbbb60b2"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Constructors.lean", "Ix/Theory/Certified/Ordinary/Constructors.lean", "e57eac74ac4190013c6fc603b14fbf747985266a1369bf1b7d8cdf3785da718c"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Container.lean", "Ix/Theory/Certified/Ordinary/Container.lean", "a5f560feda487c89356faa1e775a4133f2dfc9bfaa8002472a217a227ddac582"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Eliminator.lean", "Ix/Theory/Certified/Ordinary/Eliminator.lean", "8e2162333ed48c3fbeeef2ce15ccc2406628dfa71f927550204eb1c295a2dde2"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Family.lean", "Ix/Theory/Certified/Ordinary/Family.lean", "b668e27738cbe8336059f8cd0313feb8709ab112ee64126d53e28998aac77568"⟩, + ⟨"Lean4Ix/Certified/Ordinary/LargeElim.lean", "Ix/Theory/Certified/Ordinary/LargeElim.lean", "af7d28444877b6a7524aaaf277944c6fc9b75bdadfa4baf481bdc3edf4ee337f"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Reading.lean", "Ix/Theory/Certified/Ordinary/Reading.lean", "8da97d7af13f89fc5a1983c45f1988bb5c8dea391481825b5040a102599b7cbb"⟩, + ⟨"Lean4Ix/Certified/Ordinary/RecursorReading.lean", "Ix/Theory/Certified/Ordinary/RecursorReading.lean", "0013a5e2233423cc0bfc5e6db6259a86d45649098912594cf5e9bb844d6f1043"⟩, + ⟨"Lean4Ix/Certified/Ordinary/RecursorStage.lean", "Ix/Theory/Certified/Ordinary/RecursorStage.lean", "9e6cbbfee2e9748be9042845d5d7f702b60aaa0516483892d16d974d8315ea26"⟩, + ⟨"Lean4Ix/Certified/Ordinary/RecursorSyntax.lean", "Ix/Theory/Certified/Ordinary/RecursorSyntax.lean", "df1bef5d63e0e84506bc7f3c9be345d080ace1e226b3573073b005a493b9c4fb"⟩, + ⟨"Lean4Ix/Certified/Ordinary/RecursorValue.lean", "Ix/Theory/Certified/Ordinary/RecursorValue.lean", "ab4328139fc3b76b25b71a42e01ddb089ae17e04d811dbc63aead88450370f30"⟩, + ⟨"Lean4Ix/Certified/Ordinary/RuleChecks.lean", "Ix/Theory/Certified/Ordinary/RuleChecks.lean", "ef1fe53fa44205b23ef384cb6b72e0129d3341e07834339184d694a8951225bb"⟩, + ⟨"Lean4Ix/Certified/Ordinary/RuleEquations.lean", "Ix/Theory/Certified/Ordinary/RuleEquations.lean", "40b04a47431f9c12aaf8450c408cddc849aa6da53c77b11c33612fbcfb9b7236"⟩, + ⟨"Lean4Ix/Certified/Ordinary/RuleReading.lean", "Ix/Theory/Certified/Ordinary/RuleReading.lean", "263f59728e844b9d905c7e28ba20eefc7f3c708b2237157814248490e40d19bd"⟩, + ⟨"Lean4Ix/Certified/Ordinary/Shape.lean", "Ix/Theory/Certified/Ordinary/Shape.lean", "e071e91be7609ed73c995623153a28d96cae1c1e057e3b0464373d85f9084c7e"⟩, + ⟨"Lean4Ix/Certified/Policy.lean", "Ix/Theory/Certified/Policy.lean", "67f69859dfed1dd21bdb6b253a578b1473d34fca6d408d13bbcd0176644373d9"⟩, + ⟨"Lean4Ix/Certified/Prelude.lean", "Ix/Theory/Certified/Prelude.lean", "1cdc62000e9c5532b989c905d7bf1b37c3c1578cd15c19a6cccfae7a1581892c"⟩, + ⟨"Lean4Ix/Certified/PropWhen.lean", "Ix/Theory/Certified/PropWhen.lean", "c4d80fc1af048f6bf97841d4b63f8528cf7891a71f6e05744fd33edabc757343"⟩, + ⟨"Lean4Ix/Certified/Quotient/Admission.lean", "Ix/Theory/Certified/Quotient/Admission.lean", "4efb5df9a2703a1aaed2f286e47fc0445ea05c0a4891499e9b58e3ddaac7a347"⟩, + ⟨"Lean4Ix/Certified/Quotient/Checked.lean", "Ix/Theory/Certified/Quotient/Checked.lean", "d093c1dd39f35be954c8ddbc0267f00cbf6119262a512efb5c9ad96250e208ba"⟩, + ⟨"Lean4Ix/Certified/Quotient/Publish.lean", "Ix/Theory/Certified/Quotient/Publish.lean", "e637fa623b20d14592b09fbf8101bd08a741d525dab462404a057fbcafc004bd"⟩, + ⟨"Lean4Ix/Certified/Quotient/Reading.lean", "Ix/Theory/Certified/Quotient/Reading.lean", "b20e0748f126fa0281d4c552e242f22d9ba3c2ce2d578de0604794504b199f60"⟩, + ⟨"Lean4Ix/Certified/Quotient/Syntax.lean", "Ix/Theory/Certified/Quotient/Syntax.lean", "25ec7aebc6499c1a2778355bef69c0dc262b66a00fe12124c78c38dd7a867adb"⟩, + ⟨"Lean4Ix/Certified/Quotient/Value.lean", "Ix/Theory/Certified/Quotient/Value.lean", "08575dd364648ad62fadba8b2d67e514b03e775354c17b029dea6a6b4c7c0985"⟩, + ⟨"Lean4Ix/Certified/Signature.lean", "Ix/Theory/Certified/Signature.lean", "7be85d7fa465ce50f0dfc8ab65e364c5562e81763914fa779857a636d97a64b7"⟩, + ⟨"Lean4Ix/Certified/Source.lean", "Ix/Theory/Certified/Source.lean", "f1bbfea2e6e31b9969c3acc70da1182b015c2a11700f92ce8d6304c74128b3ec"⟩, + ⟨"Lean4Ix/Certified/Standard/Admission.lean", "Ix/Theory/Certified/Standard/Admission.lean", "cfd3c5d8662b25116d3c58cf3fa7429368b36071f0ebc032df154e154fa05ff4"⟩, + ⟨"Lean4Ix/Certified/Standard/Checked.lean", "Ix/Theory/Certified/Standard/Checked.lean", "cb58c99a87d53fa919f1a742fef8727df0690d77b2713b42d1c815e880666cfd"⟩, + ⟨"Lean4Ix/Certified/Standard/Realization.lean", "Ix/Theory/Certified/Standard/Realization.lean", "2a90165564c1f56591d6b68501dbfa846673f4fe59cf47aeaa16d0fb79e6c172"⟩, + ⟨"Lean4Ix/Certified/Store.lean", "Ix/Theory/Certified/Store.lean", "84ab117484c092edd994dff513cea86042f23bb5d076c61bcb640fda3d146842"⟩, + ⟨"Lean4Ix/Certified/Structure/Admission.lean", "Ix/Theory/Certified/Structure/Admission.lean", "b38964cc9ff83d383c8a4d110cb3e11d9d0ea66c0b3498e9e7481a31cd560483"⟩, + ⟨"Lean4Ix/Certified/Structure/Checked.lean", "Ix/Theory/Certified/Structure/Checked.lean", "1d92b154e7a69cf25bbfbf138aca9f0a77172e55be1e2f5392cc0a2d84f27f33"⟩, + ⟨"Lean4Ix/Certified/Structure/Computation.lean", "Ix/Theory/Certified/Structure/Computation.lean", "c537302f6d91deb46c5b9eb29641124fc30fb0acc84d231d51d6ae7c3be4c65f"⟩, + ⟨"Lean4Ix/Certified/Structure/Publish.lean", "Ix/Theory/Certified/Structure/Publish.lean", "48015840ff11abaea77db702acca3ec29e479395f4509a5fc409cba7cb2f923d"⟩, + ⟨"Lean4Ix/Certified/Structure/Reading.lean", "Ix/Theory/Certified/Structure/Reading.lean", "36074e7c2f8a23d4ea5cece00a703773cdc9bc8907304072038b78845b359ddd"⟩, + ⟨"Lean4Ix/Certified/Structure/Syntax.lean", "Ix/Theory/Certified/Structure/Syntax.lean", "ffdbc5cced526a36b7f5139af30cdb2fb3be03222194b56b0f68edb5e72775d4"⟩, + ⟨"Lean4Ix/Certified/Structure/Value.lean", "Ix/Theory/Certified/Structure/Value.lean", "6e96be97f9894a209efdc79d2ff96c21f4202ad11afb7afa639f9d5bc5c553ee"⟩, + ⟨"Lean4Ix/Certified/Telescope.lean", "Ix/Theory/Certified/Telescope.lean", "40fecfc7cf9d1abafb855079b8c8d55cff471e6ffb9b7ddd919ea90951b78987"⟩, + ⟨"Lean4Ix/Theory/Const.lean", "Ix/Theory/Const.lean", "bfb95d9f4af666804e79e34933e2fd094c0a783bce5b5d3da7b8b6061f4d0f0a"⟩, + ⟨"Lean4Ix/Theory/Expr.lean", "Ix/Theory/Expr.lean", "c848e36c9654d211718ef4fedba3c338ac0428e4e54024c770022263aecf437b"⟩, + ⟨"Lean4Ix/Theory/Inductive/Levels.lean", "Ix/Theory/Inductive/Levels.lean", "59c8752ec02adbe0860adf60eadedd480152d5bf352058f647512158f0a9a6cb"⟩, + ⟨"Lean4Ix/Model/Annotated.lean", "Ix/Theory/Model/Annotated.lean", "55f71adb9e40f4a85aae2fbb4349498f4f2007d568a6bc84fffbdec437741a04"⟩, + ⟨"Lean4Ix/Model/Context.lean", "Ix/Theory/Model/Context.lean", "b0ce5e4808fc1a4a4d4ca8bf5faf850420675eb9065d3912ce9156de4ba93c37"⟩, + ⟨"Lean4Ix/Model/Environment.lean", "Ix/Theory/Model/Environment.lean", "bd646827350485bde61df1825f47a4ff20861ebf6f45853ddb2f3cf611858e38"⟩, + ⟨"Lean4Ix/Model/Extension.lean", "Ix/Theory/Model/Extension.lean", "c1f649360ad30417e9ddb84d6dea939e77c0aebc80279fa5b56d806feb22f109"⟩, + ⟨"Lean4Ix/Model/Inductive/Codes.lean", "Ix/Theory/Model/Inductive/Codes.lean", "9855264e0038c77b57491c3818c192bbd0bd4fba210e33bf5a2d9dfded591939"⟩, + ⟨"Lean4Ix/Model/Inductive/Container.lean", "Ix/Theory/Model/Inductive/Container.lean", "e14328e0152de4f8017a28b0500e96615bc432f98b1475babb229b34967394ba"⟩, + ⟨"Lean4Ix/Model/Inductive/Recursor.lean", "Ix/Theory/Model/Inductive/Recursor.lean", "3028689c3bb11d90e38170e680560c8a9d123bce42d46b00f1bfd4e78d4c9026"⟩, + ⟨"Lean4Ix/Model/Inductive/Telescope.lean", "Ix/Theory/Model/Inductive/Telescope.lean", "8867df5a379798d10615f7c7b068f4982c3e846b1511cdb18bfc600ec66c7c18"⟩, + ⟨"Lean4Ix/Model/Instantiation.lean", "Ix/Theory/Model/Instantiation.lean", "994e4027343d62e996fb814fc32d12c86571d4557fe7a157349a6eaf5b2e81f6"⟩, + ⟨"Lean4Ix/Model/Interpret.lean", "Ix/Theory/Model/Interpret.lean", "a505d97b1c6658d72391f0187462c443396cdce88fe6256f070842d71ea3fdf9"⟩, + ⟨"Lean4Ix/Model/Judgment.lean", "Ix/Theory/Model/Judgment.lean", "a98aff0288e2db11369e658f7e083309ff4e6794bc66e0b3cab7465aac0a7591"⟩, + ⟨"Lean4Ix/Model/PrimitiveValues.lean", "Ix/Theory/Model/PrimitiveValues.lean", "84d16a4015cc253f731494e4c5213170d8b4174b6e33871becc598f9c1a46d55"⟩, + ⟨"Lean4Ix/Model/ReferenceMap.lean", "Ix/Theory/Model/ReferenceMap.lean", "a9d50c7c0f6ae0f4258ecfaa828a127361c277a242ae8111b9d149c137acb29e"⟩, + ⟨"Lean4Ix/Model/SetModel/Container.lean", "Ix/Theory/Model/SetModel/Container.lean", "bfc5c926aee16b6456151f48832bd8c41bbb9582f541ccc864eec753277c3a25"⟩, + ⟨"Lean4Ix/Model/SetModel/Iter.lean", "Ix/Theory/Model/SetModel/Iter.lean", "6962b64d8ccd7b34df2dce7c7e0dff6bf4872b6d11de2ab608807b4787e230a0"⟩, + ⟨"Lean4Ix/Model/SetModel/Ops.lean", "Ix/Theory/Model/SetModel/Ops.lean", "17a7e331d36a0fb0a5153bad2e115f3795cdb2db24f20e1a96a3102e845b1955"⟩, + ⟨"Lean4Ix/Model/SetModel/RecGraph.lean", "Ix/Theory/Model/SetModel/RecGraph.lean", "e6ca5ce2ab2681efbc6d3f549d596e6c7522860d1656db7bbe3528a874b8593c"⟩, + ⟨"Lean4Ix/Model/SetModel/TaggedSum.lean", "Ix/Theory/Model/SetModel/TaggedSum.lean", "3f8f97c2b4d752a97bada45b5e7bc6dd3cb20a054f703a72c5e06af1646286dc"⟩, + ⟨"Lean4Ix/Model/SetModel/TupleTower.lean", "Ix/Theory/Model/SetModel/TupleTower.lean", "0665b318c36faad149ccc4ef213fe81be47d36d7283c372ff70f26d80c0fd8a9"⟩, + ⟨"Lean4Ix/Model/SetTheory/Core.lean", "Ix/Theory/Model/SetTheory/Core.lean", "1ad5614af10cf9d8eb3e390ee279d1161a0704d3af1ba36d50012e8683aa06d5"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Choice.lean", "Ix/Theory/Model/SetTheory/Derive/Choice.lean", "a451c14971f8be37fcc35534a45b6b8f569a87abb87920aa3efb02c352d4ffa5"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Empty.lean", "Ix/Theory/Model/SetTheory/Derive/Empty.lean", "72408fc268cf2d0bd6a39d27873a69576a67f8b75a1539dc26fd6147c11bcbb2"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Graphs.lean", "Ix/Theory/Model/SetTheory/Derive/Graphs.lean", "fcea63a8b11704d8f25b8dcf92fa05c494097a7195673859fe45288503deae00"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Lfp.lean", "Ix/Theory/Model/SetTheory/Derive/Lfp.lean", "9a4f8d03a9b8dca4b112e89862540aa9cf4d53efe7580f7dc6d61690783101b2"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/LfpFam.lean", "Ix/Theory/Model/SetTheory/Derive/LfpFam.lean", "862fce7477e11f1a18c5e07336ba5331b5325e7f9efc6926a87eac836f6715e7"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Omega.lean", "Ix/Theory/Model/SetTheory/Derive/Omega.lean", "aa76b574e7a6fe136cca8f9ba3d87cbd6a9577cec39cbdb91a193c265185d39d"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Pair.lean", "Ix/Theory/Model/SetTheory/Derive/Pair.lean", "99ecac13fda8ad3f3e87e0a2d4bf2f5dd72e8e859dfb98d0da17ca0b14c77134"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Pt.lean", "Ix/Theory/Model/SetTheory/Derive/Pt.lean", "3a2213814398c232d3a1f46365f22fc71d028f0e40f9c55fd1e135d07b304260"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Quot.lean", "Ix/Theory/Model/SetTheory/Derive/Quot.lean", "de5148118f48b3042609d813fdfe930924330af6ca0a5cd1b831560a035a51bc"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Sep.lean", "Ix/Theory/Model/SetTheory/Derive/Sep.lean", "24624815b917df8747786c56e2e47be740fc1e1be9f685f5fd053ac1001dbdc7"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Sigma.lean", "Ix/Theory/Model/SetTheory/Derive/Sigma.lean", "ca545076118e71a0235b6f3f6ada2e6c4c96830ca606e31dade4f3a2e060e681"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Univ.lean", "Ix/Theory/Model/SetTheory/Derive/Univ.lean", "3d59dcca1339d8e1e28bee7efe8792f44c0917fb1d1c749c61ed5a5976fcdeae"⟩, + ⟨"Lean4Ix/Model/SetTheory/Derive/Universe.lean", "Ix/Theory/Model/SetTheory/Derive/Universe.lean", "f2c24862145d6624dcd9dacfcd68b845b6c68522d0fc81c1eac06839b455b61e"⟩, + ⟨"Lean4Ix/Model/Signature.lean", "Ix/Theory/Model/Signature.lean", "5c6d3f9467466e3d677865a1536309bc05b96aafadf4312f7dc1679710929837"⟩, + ⟨"Lean4Ix/Model/Support.lean", "Ix/Theory/Model/Support.lean", "020dc36c6376e3f7f725db8d4fd6a559f4e1ad303cdfb41c5e738f00c6ac05de"⟩, + ⟨"Lean4Ix/Model/TelescopeSemantics.lean", "Ix/Theory/Model/TelescopeSemantics.lean", "a717a653a8d8d88d69a52acba0a8fe81b0c5635194c408bfdb503382ec9d0d66"⟩, + ⟨"Lean4Ix/Model/Value.lean", "Ix/Theory/Model/Value.lean", "b2cf0796c8bcf6e138136c3f9f017d3df551b2a243d2e860fa943bb8d1411524"⟩, + ⟨"Lean4Ix/Model/WellDenoted.lean", "Ix/Theory/Model/WellDenoted.lean", "8fc3eeb787fcc0182da41c880cf416c214d7930a433d0f35f77f393a2e9526e8"⟩, + ⟨"Lean4Ix/Theory/Quot.lean", "Ix/Theory/Quot.lean", "321d4c7739af0b052da2a5c59ba875fe1ec35ec334a382d6107e02aeac238b49"⟩, + ⟨"Lean4Ix/Theory/Ref.lean", "Ix/Theory/Ref.lean", "885181febe5ce0e1f9c6baac03e4604efb4acea27e0e8b61fde9900c14112f00"⟩, + ⟨"Lean4Ix/Theory/Rename.lean", "Ix/Theory/Rename.lean", "3ce70afd260f3d9f68b830e11c5d1937f0d9ccf3b3f8a4e70ffc139a84fb8322"⟩, + ⟨"Lean4Ix/Std/Basic.lean", "Ix/Theory/Std/Basic.lean", "450413877e701f1d906d13cf3074149127bb1637a9e5a4bd723d20769662fe89"⟩, + ⟨"Lean4Ix/Theory/Store.lean", "Ix/Theory/Store.lean", "316c34c9f083a5d751f0fe9a478c50d6f3fc511a7aa8529042776a5b774fd763"⟩, + ⟨"Lean4Ix/Theory/VLevel.lean", "Ix/Theory/VLevel.lean", "fc91db763262069edc1181dcb0ff12ac78d1efdd370a8acb2b297d3fcec963ee"⟩, + ⟨"Lean4Ix/Certified.lean", "Ix/Theory.lean", "db42519eb53c5c24965b27879cb1ad81eca1010513fc67cf486f324c942fce98"⟩] + +structure ConLecheFile where + source : String + target : String + sourceSha256 : String + lean4IxSha256 : String + targetSha256 : String + deriving Repr + +def conLeche : Array ConLecheFile := #[ + ⟨"ConLeche/SetTheory/Core.lean", "Ix/Theory/Model/SetTheory/Core.lean", "52f54c7f8664a0d00ba04083d428ff81c2b89e7e68fbd6e24ffb349ef441f19a", "1ad5614af10cf9d8eb3e390ee279d1161a0704d3af1ba36d50012e8683aa06d5", "9e8d3537a66ded9e4d9142765c9ebda3eb4c3a8f780927cea6657e076933657b"⟩, + ⟨"ConLeche/SetTheory/Derive/Empty.lean", "Ix/Theory/Model/SetTheory/Derive/Empty.lean", "259b3b365926256fbe8281a7066be601e419c3e492452b62086e0fd44e1a3f16", "72408fc268cf2d0bd6a39d27873a69576a67f8b75a1539dc26fd6147c11bcbb2", "b9a961b71e8a0576ceb00fbdc0288231d360576cd7afa72375606c793da15541"⟩, + ⟨"ConLeche/SetTheory/Derive/Sep.lean", "Ix/Theory/Model/SetTheory/Derive/Sep.lean", "a6a452a34028ff2e194987de8fc5bc8f847ff8950f962b5d33c6c6ee5045a52e", "24624815b917df8747786c56e2e47be740fc1e1be9f685f5fd053ac1001dbdc7", "38536c268957fe0ad6e0127a1f07677bbfe4a17de82d0a2738b9042db55be2c7"⟩, + ⟨"ConLeche/SetTheory/Derive/Pair.lean", "Ix/Theory/Model/SetTheory/Derive/Pair.lean", "851f954187fcc05ba2f43a6b81112df27c91e34f7de54352eaf461380fee1bd7", "99ecac13fda8ad3f3e87e0a2d4bf2f5dd72e8e859dfb98d0da17ca0b14c77134", "a72c5b13f5657a8299b060bd344068f56c3e2fadfc3619e64b9bc28e98085c91"⟩, + ⟨"ConLeche/SetTheory/Derive/Universe.lean", "Ix/Theory/Model/SetTheory/Derive/Universe.lean", "57a24b4144088ac14dabdb9b6f88c49cf251a0659f8d4c073aad6682baeb099d", "f2c24862145d6624dcd9dacfcd68b845b6c68522d0fc81c1eac06839b455b61e", "c3eb55ee316ce142c16fa5c9a3e06ac45721767bad845ce8cd4c485ac7cce494"⟩, + ⟨"ConLeche/SetTheory/Derive/Pt.lean", "Ix/Theory/Model/SetTheory/Derive/Pt.lean", "93f9ed86375f7af7a004f3ef2612ce8c9d8c6626ce73dbf6c3d6702f95f67eae", "3a2213814398c232d3a1f46365f22fc71d028f0e40f9c55fd1e135d07b304260", "520286bf987d29f56976d32ed2527ddf494ac80592fba05c1ffc4ad7627d9934"⟩, + ⟨"ConLeche/SetTheory/Derive/Graphs.lean", "Ix/Theory/Model/SetTheory/Derive/Graphs.lean", "f61433765add5a733b38e95e38e217273f526a5e710b7109f24eb0f83f70faaf", "fcea63a8b11704d8f25b8dcf92fa05c494097a7195673859fe45288503deae00", "5bff626e2b77ea3d83302dd8959ef0e0816e9d9da59d52d573134f139e69316c"⟩, + ⟨"ConLeche/SetTheory/Derive/Omega.lean", "Ix/Theory/Model/SetTheory/Derive/Omega.lean", "c0b20ecd0cc88a74ff6091e5a88506269b587bbc6f1919f72cc63083d2f7e55a", "aa76b574e7a6fe136cca8f9ba3d87cbd6a9577cec39cbdb91a193c265185d39d", "0cf178fada4077bfc8ba7dc257d8ceb77e7db8a452a9fba09eb736ad84f475be"⟩, + ⟨"ConLeche/SetTheory/Derive/Univ.lean", "Ix/Theory/Model/SetTheory/Derive/Univ.lean", "e1084f7c82d9c0d144281491ceb05b015001d1215947d0d687e4dc07497ff911", "3d59dcca1339d8e1e28bee7efe8792f44c0917fb1d1c749c61ed5a5976fcdeae", "33e83e18da0a782904f42acc563c1c4259b60a1833bf2b22af41a28f1bd797e0"⟩, + ⟨"ConLeche/SetModel/Ops.lean", "Ix/Theory/Model/SetModel/Ops.lean", "b19d965f92d1e281afd40a7ee4b2edd1a324b9bdf6d8f26425944dbafe987a11", "17a7e331d36a0fb0a5153bad2e115f3795cdb2db24f20e1a96a3102e845b1955", "6ce498a847103c32824e40f22e51db42163da98c09374f6a69e2a85a69f1e732"⟩, + ⟨"ConLeche/SetTheory/Derive/Sigma.lean", "Ix/Theory/Model/SetTheory/Derive/Sigma.lean", "1a844ecb6709ae0ccefd43a4eb8d6da92b3753033e882ce74cfbd27c6890545f", "ca545076118e71a0235b6f3f6ada2e6c4c96830ca606e31dade4f3a2e060e681", "59cfd35485e1b90d199089aea2886fe7ed12bd9f02637d2d7cd5e21536ec6ef5"⟩, + ⟨"ConLeche/SetTheory/Derive/Lfp.lean", "Ix/Theory/Model/SetTheory/Derive/Lfp.lean", "d6c1a824ee0b358f4007c2d297c4e29011c95914c2241d402f5bf27da333614f", "9a4f8d03a9b8dca4b112e89862540aa9cf4d53efe7580f7dc6d61690783101b2", "65e44e5bfe2fa0720b334cd31aff2c2eff511364feadfd5fd60c1ebf150b9a89"⟩, + ⟨"ConLeche/SetTheory/Derive/LfpFam.lean", "Ix/Theory/Model/SetTheory/Derive/LfpFam.lean", "18fa2c12b37d9786b9a1961ed526e7d411869d93cfa241ebbdf2910d4418ac97", "862fce7477e11f1a18c5e07336ba5331b5325e7f9efc6926a87eac836f6715e7", "0657c96c6dffb7a49fec92c97769356595ec8a6f06b5f73594d4732d2fef8b8f"⟩, + ⟨"ConLeche/SetTheory/Derive/Choice.lean", "Ix/Theory/Model/SetTheory/Derive/Choice.lean", "a8404566f4d831874e044dcfba6865b750fda3c9427e13c3d2b68d7ac45d5b48", "a451c14971f8be37fcc35534a45b6b8f569a87abb87920aa3efb02c352d4ffa5", "47e64bd1d52287230b993398ba5ee584d7b15e256b86f4fa0eaf1735c4510b93"⟩, + ⟨"ConLeche/SetModel/TupleTower.lean", "Ix/Theory/Model/SetModel/TupleTower.lean", "143b965d29faae965c16288021ba1cf401c3f10e76550386ddb81d9ca1f5cbee", "0665b318c36faad149ccc4ef213fe81be47d36d7283c372ff70f26d80c0fd8a9", "1089b4ea6d9e7ff3ed9902a3c3d8f6697332b2aac23f94e503584b9cdf972750"⟩, + ⟨"ConLeche/SetModel/TaggedSum.lean", "Ix/Theory/Model/SetModel/TaggedSum.lean", "eb64def578bf85bc2b197b83648749996ebcd243be573752f617a5f91f3332d8", "3f8f97c2b4d752a97bada45b5e7bc6dd3cb20a054f703a72c5e06af1646286dc", "53b565da9a2ce8848ca2442e52bfa0ff13b3f044017858fe69be42a9b2614aff"⟩, + ⟨"ConLeche/SetModel/Iter.lean", "Ix/Theory/Model/SetModel/Iter.lean", "0688fa56fad4dcac618589cd9bafc2860c43b95978dc6dcf6c3e292cafc4b149", "6962b64d8ccd7b34df2dce7c7e0dff6bf4872b6d11de2ab608807b4787e230a0", "019ef9fa62f5d141ccc8c7e41259ff52dfba56412b3a57917ba60c28a2bfb378"⟩, + ⟨"ConLeche/SetModel/RecGraph.lean", "Ix/Theory/Model/SetModel/RecGraph.lean", "66de7b97c640cec3987f89c31ae19c4daa27b6da53ba6943767e0078802f1faf", "e6ca5ce2ab2681efbc6d3f549d596e6c7522860d1656db7bbe3528a874b8593c", "da698d1a7346eaaa2f5b4734de06c955a05791ff52728d554082814328bd5caa"⟩, + ⟨"ConLeche/SetModel/Container.lean", "Ix/Theory/Model/SetModel/Container.lean", "47b7bbab4764309ad1a11d7e6a3d2061c2968928367e2285e2a7e549bf7e6c0c", "bfc5c926aee16b6456151f48832bd8c41bbb9582f541ccc864eec753277c3a25", "08928de8de78f1fabc535b65e8511b068ad3c8b517055aa363674c2c90cebd4e"⟩, + ⟨"ConLeche/SetTheory/Derive/Quot.lean", "Ix/Theory/Model/SetTheory/Derive/Quot.lean", "cadc387495c563d796ba4ca45cc0125cbe8ff5168d81bc47b364bd6776c3898b", "de5148118f48b3042609d813fdfe930924330af6ca0a5cd1b831560a035a51bc", "356b3b639fad5c6a9990bf106a38d49b32d0b0ae80537aba2719aaab8f9d9c84"⟩] + +end Tests.Theory.ImportManifest diff --git a/Tests/Theory/Modeled.lean b/Tests/Theory/Modeled.lean new file mode 100644 index 000000000..6f62ff1d2 --- /dev/null +++ b/Tests/Theory/Modeled.lean @@ -0,0 +1,165 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Modeled +import Ix.Theory.Certificate.Build +import Tests.Theory.Ordinary +import Tests.Theory.Certified +import Tests.Theory.ModeledFixtures + +open Ix.Theory + +/-! Model declarations and certificates are generated from actual anonymous +source data, then checked through the public store entry point. This corpus +does not substitute a caller-supplied realization for declaration checking. -/ + +namespace Tests.Theory.Modeled + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certificate Ix.Theory.Inductive +open Tests.Theory.Certified (primitives) + +set_option maxRecDepth 8192 +set_option maxHeartbeats 16000000 + +def ref (block member : Nat := 0) : ConstRef Nat := .member block member +def const (block member : Nat := 0) (levels : List VLevel := []) : VExpr Nat := .const (ref block member) levels +def type0 : VExpr Nat := .sort (.succ .zero) +def natType : VExpr Nat := const 20 + +def mutualSource : Block Nat := ModeledFixtures.mutualSource +def mutualRecursors : Block Nat := ModeledFixtures.mutualRecursors + +/-- Both families are modeled by Nat. B's constructor is identity; A has zero +and successor. The dependent mutual fold is built from the checked Nat fold. -/ +def modelTargets : List (ConstRef Nat) := + [ref 20, .ctor 20 0 0, .ctor 20 0 1, ref 20, ref 40, ref 41, ref 42] +def modelPairs : List (ConstRef Nat × ConstRef Nat) := + [ref 30, .ctor 30 0 0, .ctor 30 0 1, ref 30 1, .ctor 30 1 0, ref 31, ref 31 1].zip modelTargets +def mapped (expression : VExpr Nat) : VExpr Nat := expression.mapRefs (Certificate.Modeled.target modelPairs) +def recursorType (index : Nat) : VExpr Nat := + mapped ((mutualRecursors.members[index]?).map Const.type |>.getD type0) +def recPrefix : List (VExpr Nat) := (recursorType 0).telN 5 + +def modelA : VExpr Nat := + .lamN recPrefix (.appN (const 21 0 [.param 0]) [ + .bvar 4, .bvar 2, + .lam natType (.lam (.app (.bvar 5) (.bvar 0)) + (.appN (.bvar 3) [.bvar 1, .appN (.bvar 2) [.bvar 1, .bvar 0]]))]) + +def modelB : VExpr Nat := + .lamN (recPrefix ++ [natType]) (.appN (.bvar 1) + [.bvar 0, .appN (const 41 0 [.param 0]) (VExpr.bvarRevRange 1 5 ++ [.bvar 0])]) + +def block : Nat → Block Nat + | 10 => ⟨[PrimitiveSignature.falseDeclaration]⟩ + | 11 => ⟨[primitives.falseElimDeclaration]⟩ + | 20 => ⟨[Tests.Theory.Ordinary.natShape.source 20]⟩ + | 21 => ⟨[Tests.Theory.Ordinary.natShape.recursorSource 20 21 .large]⟩ + | 30 => mutualSource + | 31 => mutualRecursors + | 40 => ⟨[.defn 0 .definition (.forallE natType natType) (.lam natType (.bvar 0)) .safe]⟩ + | 41 => ⟨[.defn 1 .definition (recursorType 0) modelA .safe]⟩ + | 42 => ⟨[.defn 1 .definition (recursorType 1) modelB .safe]⟩ + | _ => ⟨[]⟩ + +def store (alter : Nat → Block Nat → Block Nat := fun _ b => b) : Store Nat where + dom := List.range 43 + nodup := List.nodup_range + blocks b := if b < 43 then some (alter b (block b)) else none + mem_dom b := by split <;> simp_all + +def prefixWitnesses? : Option (Environment Nat × List (DeclarationWitness Nat)) := + declarationWitnesses? 3000 store primitives.environment + [.ordinary 20 21, .definition (ref 40), .definition (ref 41), .definition (ref 42)] + +def modeledWitness? : Option (Ix.Theory.Certified.Modeled.Witness Nat) := do + let (entries, _) ← prefixWitnesses? + Certificate.Modeled.witness? 3000 entries store 30 [ref 31, ref 31 1] modelTargets + +def witnesses? : Option (List (DeclarationWitness Nat)) := do + let (_, earlier) ← prefixWitnesses? + return earlier ++ [.modeled (← modeledWitness?)] + +def accepted : Bool := witnesses?.any fun witnesses => + acceptsStoreCertified.{0,0} 3000 primitives store [ref 30, ref 30 1, ref 31, ref 31 1] witnesses + +#guard (Ix.Theory.Certified.Modeled.sourceRefs? store 30 [ref 31, ref 31 1]).isSome +#guard (Ix.Theory.Certified.Modeled.recursorRules? store (ref 31)).any (fun rules => rules.length == 2) +#guard (Ix.Theory.Certified.Modeled.recursorRules? store (ref 31 1)).any (fun rules => rules.length == 1) +#guard store.ctorRuleIndex? (.ctor 30 1 0) == some 2 +#guard prefixWitnesses?.isSome +#guard modeledWitness?.isSome +#guard accepted + +def candidate : Certificate.Modeled.Candidate Nat := ⟨30, [ref 31, ref 31 1], modelTargets, []⟩ +def generated? : Option (List (DeclarationWitness Nat)) := + Certificate.storeWitness? 3000 primitives store [ref 31, ref 31 1] [candidate] +#guard generated?.any (acceptsStoreCertified.{0,0} 3000 primitives store [ref 31, ref 31 1]) + +def computed : VExpr Nat := .appN (const 31 0 [.succ .zero]) [ + .lam (const 30) (.sort .zero), .lam (const 30 1) (.sort .zero), .bvar 1, + .lam (const 30 1) (.lam (.sort .zero) (.bvar 0)), + .lam (const 30) (.lam (.sort .zero) (.bvar 0)), + .app (.const (.ctor 30 0 1) []) + (.app (.const (.ctor 30 1 0) []) (.const (.ctor 30 0 0) []))] +def proof : VExpr Nat := .lam (.sort .zero) (.lam (.bvar 0) (.bvar 0)) +def proposition : VExpr Nat := .forallE (.sort .zero) (.forallE (.bvar 0) computed) +def input : ProofInput Nat := ⟨store, 0, proof, proposition⟩ +def proofAccepted : Bool := (Certificate.proofWitness? 3000 primitives input [candidate]).any + (acceptsCertified.{0,0} 3000 primitives input) +#guard proofAccepted + +def withRecursor (alter : Const Nat → Const Nat) : Store Nat := + store fun n b => if n = 31 then ⟨b.members.map alter⟩ else b +def withRules (alter : List (RecRule Nat) → List (RecRule Nat)) : Store Nat := + withRecursor fun c => match c with + | .recursor u p i m n t rules k s => .recursor u p i m n t (alter rules) k s + | c => c +def sourceRejected (source : Store Nat) : Bool := witnesses?.any fun witnesses => + !(acceptsStoreCertified.{0,0} 3000 primitives source [ref 31, ref 31 1] witnesses) + +-- Both families contribute to the same table. Slot 2 must not become slot 1, +-- and an equation about the other recursor cannot justify the selected rule. +#guard sourceRejected (withRules fun rules => rules.reverse) +#guard sourceRejected (withRules fun rules => rules.take 2) +#guard sourceRejected (withRules fun rules => rules.map fun r => { r with nfields := r.nfields + 1 }) +#guard sourceRejected (withRules fun rules => rules.map fun r => { r with rhs := .sort .zero }) +#guard sourceRejected (withRecursor fun c => match c with + | .recursor u p i m n t rs _ s => .recursor u p i m n t rs true s | c => c) +#guard sourceRejected (withRecursor fun c => match c with + | .recursor u p i m n t rs k _ => .recursor u p i m n t rs k .unsafe | c => c) +#guard sourceRejected (store fun n b => if n = 40 then + ⟨[.axiom 0 (.forallE natType natType) .safe]⟩ else b) +#guard sourceRejected (store fun n b => if n = 40 then + ⟨[.defn 0 .definition (.forallE natType natType) (.const (.ctor 30 1 0) []) .safe]⟩ else b) + +def witnessRejected (alter : Ix.Theory.Certified.Modeled.Witness Nat → Ix.Theory.Certified.Modeled.Witness Nat) : Bool := + (prefixWitnesses?).any fun (_, declarations) => (modeledWitness?).any fun witness => + !(acceptsStoreCertified.{0,0} 3000 primitives store [ref 31, ref 31 1] + (declarations ++ [.modeled (alter witness)])) + +#guard witnessRejected fun w => { w with recursors := w.recursors.reverse } +#guard witnessRejected fun w => { w with companions := w.companions.reverse } +#guard witnessRejected fun w => { w with companions := w.companions.drop 1 } +#guard witnessRejected fun w => { w with equations := w.equations.drop 1 } +#guard witnessRejected fun w => { w with companions := w.companions.map fun c => { c with model := c.header.ref } } +#guard witnessRejected fun w => { w with companions := w.companions.map fun c => + { c with rules := c.rules.map fun r => { r with lhs := r.rhs } } } +#guard witnessRejected fun w => { w with equations := w.equations.map (fun es => + es.map (fun e => { e with proof := .conversion .refl })) } + +-- The generic dependency walker rejects a model that depends on the new +-- source, and does not turn a missing model witness into ordinary admission. +#guard (Certificate.storeWitness? 3000 primitives store [ref 31] [{ candidate with models := + [ref 30, .ctor 30 0 0, .ctor 30 0 1, ref 30 1, .ctor 30 1 0, ref 31, ref 31 1] }]).isNone +#guard (Certificate.storeWitness? 3000 primitives store [ref 31]).isNone + +-- Model admission supplies no projection or eta facts for the new families. +#guard (modeledWitness?).all fun w => w.companions.all (fun c => c.entry.facts.isEmpty) +#guard (prefixWitnesses?).any fun (entries, _) => (modeledWitness?).any fun w => + (inferSource? 3000 0 (Ix.Theory.Certified.Modeled.environment entries w.companions) [] + (.proj (ref 30 1) 0 (.app (.const (.ctor 30 1 0) []) (.const (.ctor 30 0 0) [])))).isNone + +end Tests.Theory.Modeled diff --git a/Tests/Theory/ModeledEquations.lean b/Tests/Theory/ModeledEquations.lean new file mode 100644 index 000000000..449e18a8e --- /dev/null +++ b/Tests/Theory/ModeledEquations.lean @@ -0,0 +1,99 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Theory.Modeled + +open Ix.Theory + +namespace Tests.Theory.ModeledEquations + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certificate +open Tests.Theory.Certified (primitives) +open Tests.Theory.Modeled (ref) + +set_option maxRecDepth 16384 +set_option maxHeartbeats 32000000 + +def eqRef : ConstRef Nat := ref 60 +def reflRef : ConstRef Nat := .ctor 60 0 0 +def eqRec : ConstRef Nat := ref 61 +def block : Nat → Block Nat + | 60 => ⟨[Basis.Equality.shape.source 60]⟩ + | 61 => ⟨[Basis.Equality.shape.recursorSource 60 61 .large true]⟩ + | n => Tests.Theory.Modeled.block n +def store : Store Nat where + dom := List.range 62 + nodup := List.nodup_range + blocks b := if b < 62 then some (block b) else none + mem_dom b := by split <;> simp_all + +def prefixWitnesses? := declarationWitnesses? 4000 store primitives.environment + [.ordinary 60 61, .ordinary 20 21, .definition (ref 40), .definition (ref 41), .definition (ref 42)] + +/-- Use a checked proof of equality of the complete functions, with their +entire telescopes as endpoints. No equation is reflected into Theory.IsDefEq. -/ +def propositional? (entries : Environment Nat) (rule : Signature.Rule Nat) + (witness : Ix.Theory.Certified.Modeled.EquationWitness Nat) : + Option (Ix.Theory.Certified.Modeled.EquationWitness Nat) := do + let proof := Basis.Equality.reflexivity reflRef witness.formation.level rule.type rule.lhs + let inferred ← inferAnnotated? 4000 rule.universes entries [] proof + let typed ← castWith? 4000 rule.universes entries [] inferred + (Basis.Equality.applied eqRef witness.formation.level rule.type rule.lhs rule.rhs) + return { witness with proof := .propositional eqRef reflRef eqRec proof typed } + +def witness? : Option (Ix.Theory.Certified.Modeled.Witness Nat) := do + let (entries, _) ← prefixWitnesses? + let witness ← Tests.Theory.Modeled.candidate.witness? 4000 entries store + let equations ← (witness.companions.zip witness.equations).mapM fun (companion, proofs) => + (companion.rules.zip proofs).mapM fun (rule, proof) => + propositional? entries (Ix.Theory.Certified.Modeled.mapRule witness.companions rule) proof + return { witness with equations } + +def accepted (alter : Ix.Theory.Certified.Modeled.Witness Nat → Ix.Theory.Certified.Modeled.Witness Nat := id) : Bool := + prefixWitnesses?.any fun (_, earlier) => witness?.any fun witness => + acceptsStoreCertified.{0,0} 4000 primitives store [ref 31, ref 31 1] (earlier ++ [.modeled (alter witness)]) + +#guard accepted +#guard !accepted fun w => { w with equations := w.equations.map (fun proofs => proofs.map fun proof => + { proof with proof := .propositional eqRef reflRef eqRec (.sort .zero) .sort }) } +#guard !accepted fun w => { w with equations := w.equations.map (fun proofs => proofs.map fun proof => + match proof.proof with + | .propositional _ r rec term typed => { proof with proof := .propositional (ref 20) r rec term typed } + | _ => proof) } +#guard !accepted fun w => { w with companions := w.companions.map (fun c => + { c with rules := c.rules.map fun rule => { rule with lhs := rule.rhs } }) } + +/-- Actual model equation declarations for serialization and command tests. +Each proof is part of the source store and checked as a normal theorem. -/ +def equationDeclarations? : Option (List (Const Nat)) := do + let (entries, _) ← prefixWitnesses? + let witness ← Tests.Theory.Modeled.candidate.witness? 4000 entries store + return (witness.companions.zip witness.equations).flatMap fun (companion, proofs) => + (companion.rules.zip proofs).map fun (rule, proof) => + let rule := Ix.Theory.Certified.Modeled.mapRule witness.companions rule + let type := Basis.Equality.applied eqRef proof.formation.level rule.type rule.lhs rule.rhs + let body := Basis.Equality.reflexivity reflRef proof.formation.level rule.type rule.lhs + .defn rule.universes .theorem type.erase body.erase .safe + +def proofBlock (n : Nat) : Block Nat := + if n < 70 then block n else ⟨((equationDeclarations?.getD [])[n - 70]?).toList⟩ +def proofStore : Store Nat where + dom := List.range 73 + nodup := List.nodup_range + blocks b := if b < 73 then some (proofBlock b) else none + mem_dom b := by split <;> simp_all +def hint (n : Nat) : Certificate.Modeled.ProofHint Nat := + ⟨eqRef, reflRef, eqRec, .const (ref n) [.param 0]⟩ +def candidate : Certificate.Modeled.Candidate Nat := + { Tests.Theory.Modeled.candidate with proofs := + [(ref 31, [some (hint 70), some (hint 71)]), (ref 31 1, [some (hint 72)])] } +def input : ProofInput Nat := ⟨proofStore, 0, Tests.Theory.Modeled.proof, Tests.Theory.Modeled.proposition⟩ +def generatedAccepted : Bool := (Certificate.proofWitness? 4000 primitives input [candidate]).any + (acceptsCertified.{0,0} 4000 primitives input) +#guard generatedAccepted +#guard (Certificate.proofWitness? 4000 primitives input + [{ candidate with proofs := [(ref 31, [some (hint 71), some (hint 70)])] }]).isNone + +end Tests.Theory.ModeledEquations diff --git a/Tests/Theory/ModeledFixtures.lean b/Tests/Theory/ModeledFixtures.lean new file mode 100644 index 000000000..2369379d7 --- /dev/null +++ b/Tests/Theory/ModeledFixtures.lean @@ -0,0 +1,83 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Const + +open Ix.Theory + +namespace Tests.Theory.ModeledFixtures + +/- Frozen source and recursor blocks from Lean4Ix's generator. The model +tests validate these inputs without importing the old metatheory. -/ + +def mutualSource : Block Nat := ⟨[ + .induct 0 0 0 (.sort (.succ .zero)) [ + ⟨0, 0, 0, (.const (.member 30 0) []), .safe⟩, + ⟨0, 0, 1, (.forallE (.const (.member 30 1) []) (.const (.member 30 0) [])), .safe⟩ + ] .safe, + .induct 0 0 0 (.sort (.succ .zero)) [ + ⟨0, 0, 1, (.forallE (.const (.member 30 0) []) (.const (.member 30 1) [])), .safe⟩ + ] .safe + ]⟩ + +def mutualRecursors : Block Nat := ⟨[ + .recursor 1 0 0 2 3 (.forallE (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.forallE (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.forallE (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.forallE (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.forallE (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.forallE (.const (.member 30 0) []) (.app (.bvar 5) (.bvar 0)))))))) [ + ⟨0, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.bvar 2))))))⟩, + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.lam (.const (.member 30 1) []) (.app (.app (.bvar 2) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 1) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩, + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.lam (.const (.member 30 0) []) (.app (.app (.bvar 1) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 0) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩ + ] false .safe, + .recursor 1 0 0 2 3 (.forallE (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.forallE (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.forallE (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.forallE (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.forallE (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.forallE (.const (.member 30 1) []) (.app (.bvar 4) (.bvar 0)))))))) [ + ⟨0, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.bvar 2))))))⟩, + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.lam (.const (.member 30 1) []) (.app (.app (.bvar 2) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 1) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩, + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.app (.bvar 1) (.const (.ctor 30 0 0) [])) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 0 1) []) (.bvar 1))))) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 0) []) (.bvar 1))))) (.lam (.const (.member 30 0) []) (.app (.app (.bvar 1) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 0) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩ + ] false .safe + ]⟩ + +def permutedSource : Block Nat := ⟨[ + .induct 0 0 0 (.sort (.succ .zero)) [ + ⟨0, 0, 1, (.forallE (.const (.member 30 1) []) (.const (.member 30 0) [])), .safe⟩ + ] .safe, + .induct 0 0 0 (.sort (.succ .zero)) [ + ⟨0, 0, 0, (.const (.member 30 1) []), .safe⟩, + ⟨0, 0, 1, (.forallE (.const (.member 30 0) []) (.const (.member 30 1) [])), .safe⟩ + ] .safe + ]⟩ + +def permutedRecursors : Block Nat := ⟨[ + .recursor 1 0 0 2 3 (.forallE (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.forallE (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.forallE (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.forallE (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.forallE (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.forallE (.const (.member 30 0) []) (.app (.bvar 5) (.bvar 0)))))))) [ + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.lam (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.lam (.const (.member 30 1) []) (.app (.app (.bvar 3) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 1) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩, + ⟨0, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.lam (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.bvar 1))))))⟩, + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.lam (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.lam (.const (.member 30 0) []) (.app (.app (.bvar 1) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 0) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩ + ] false .safe, + .recursor 1 0 0 2 3 (.forallE (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.forallE (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.forallE (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.forallE (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.forallE (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.forallE (.const (.member 30 1) []) (.app (.bvar 4) (.bvar 0)))))))) [ + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.lam (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.lam (.const (.member 30 1) []) (.app (.app (.bvar 3) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 1) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩, + ⟨0, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.lam (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.bvar 1))))))⟩, + ⟨1, (.lam (.forallE (.const (.member 30 0) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.sort (.param 0))) (.lam (.forallE (.const (.member 30 1) []) (.forallE (.app (.bvar 1) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 30 0 0) []) (.bvar 1))))) (.lam (.app (.bvar 1) (.const (.ctor 30 1 0) [])) (.lam (.forallE (.const (.member 30 0) []) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.const (.ctor 30 1 1) []) (.bvar 1))))) (.lam (.const (.member 30 0) []) (.app (.app (.bvar 1) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.const (.member 31 0) [(.param 0)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0)))))))))⟩ + ] false .safe + ]⟩ + +def nestedRecursors : Block Nat := ⟨[ + .recursor 2 1 0 2 3 (.forallE (.sort (.succ (.param 1))) (.forallE (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 1)) (.sort (.param 0))) (.forallE (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.forallE (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 4)) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 6)) (.bvar 1))))) (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5)) (.app (.bvar 5) (.bvar 0))))))))) [ + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 4)) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 6)) (.bvar 1))))) (.lam (.bvar 5) (.app (.bvar 3) (.bvar 0)))))))))⟩, + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 4)) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 6)) (.bvar 1))))) (.lam (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 5)) (.app (.app (.bvar 2) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.app (.const (.member 41 1) [(.param 0), (.param 1)]) (.bvar 6)) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0))))))))))⟩, + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 4)) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 6)) (.bvar 1))))) (.lam (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5)) (.app (.app (.bvar 1) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.app (.const (.member 41 0) [(.param 0), (.param 1)]) (.bvar 6)) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0))))))))))⟩ + ] false .safe, + .recursor 2 1 0 2 3 (.forallE (.sort (.succ (.param 1))) (.forallE (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 1)) (.sort (.param 0))) (.forallE (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.forallE (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 4)) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 6)) (.bvar 1))))) (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 5)) (.app (.bvar 4) (.bvar 0))))))))) [ + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 4)) (.forallE (.app (.bvar 4) (.bvar 0)) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)))) (.bvar 6)) (.bvar 1))))) (.lam (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5)) (.app (.app (.bvar 1) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.app (.const (.member 41 0) [(.param 0), (.param 1)]) (.bvar 6)) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0))))))))))⟩ + ] false .safe + ]⟩ + +def nestedPiRecursors : Block Nat := ⟨[ + .recursor 2 1 0 2 3 (.forallE (.sort (.succ (.param 1))) (.forallE (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 1)) (.sort (.param 0))) (.forallE (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.forallE (.forallE (.forallE (.bvar 4) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5))) (.forallE (.forallE (.bvar 5) (.app (.bvar 5) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 6)) (.bvar 1))))) (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5)) (.app (.bvar 5) (.bvar 0))))))))) [ + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.forallE (.bvar 4) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5))) (.forallE (.forallE (.bvar 5) (.app (.bvar 5) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 6)) (.bvar 1))))) (.lam (.bvar 5) (.app (.bvar 3) (.bvar 0)))))))))⟩, + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.forallE (.bvar 4) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5))) (.forallE (.forallE (.bvar 5) (.app (.bvar 5) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 6)) (.bvar 1))))) (.lam (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 5)) (.app (.app (.bvar 2) (.bvar 0)) (.app (.app (.app (.app (.app (.app (.app (.const (.member 41 1) [(.param 0), (.param 1)]) (.bvar 6)) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0))))))))))⟩, + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.forallE (.bvar 4) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5))) (.forallE (.forallE (.bvar 5) (.app (.bvar 5) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 6)) (.bvar 1))))) (.lam (.forallE (.bvar 5) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 6))) (.app (.app (.bvar 1) (.bvar 0)) (.lam (.bvar 6) (.app (.app (.app (.app (.app (.app (.app (.const (.member 41 0) [(.param 0), (.param 1)]) (.bvar 7)) (.bvar 6)) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.app (.bvar 1) (.bvar 0))))))))))))⟩ + ] false .safe, + .recursor 2 1 0 2 3 (.forallE (.sort (.succ (.param 1))) (.forallE (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 1)) (.sort (.param 0))) (.forallE (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.forallE (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.forallE (.forallE (.forallE (.bvar 4) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5))) (.forallE (.forallE (.bvar 5) (.app (.bvar 5) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 6)) (.bvar 1))))) (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 5)) (.app (.bvar 4) (.bvar 0))))))))) [ + ⟨1, (.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 40 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 1)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 40 0 0) [(.param 1)]) (.bvar 3)) (.bvar 0)))) (.lam (.forallE (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.member 20 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 3)) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 4) (.app (.app (.const (.ctor 40 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1))))) (.lam (.forallE (.forallE (.bvar 4) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 5))) (.forallE (.forallE (.bvar 5) (.app (.bvar 5) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 4) (.app (.app (.lam (.sort (.succ (.param 1))) (.app (.const (.ctor 20 0 0) [(.param 1)]) (.forallE (.bvar 0) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 1))))) (.bvar 6)) (.bvar 1))))) (.lam (.forallE (.bvar 5) (.app (.const (.member 40 0) [(.param 1)]) (.bvar 6))) (.app (.app (.bvar 1) (.bvar 0)) (.lam (.bvar 6) (.app (.app (.app (.app (.app (.app (.app (.const (.member 41 0) [(.param 0), (.param 1)]) (.bvar 7)) (.bvar 6)) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.app (.bvar 1) (.bvar 0))))))))))))⟩ + ] false .safe + ]⟩ + +end Tests.Theory.ModeledFixtures diff --git a/Tests/Theory/ModeledNested.lean b/Tests/Theory/ModeledNested.lean new file mode 100644 index 000000000..54bd19390 --- /dev/null +++ b/Tests/Theory/ModeledNested.lean @@ -0,0 +1,177 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Theory.Modeled + +open Ix.Theory + +namespace Tests.Theory.ModeledNested + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certificate Ix.Theory.Inductive +open Tests.Theory.Certified (primitives) +open Tests.Theory.Modeled (ref const) + +set_option maxRecDepth 16384 +set_option maxHeartbeats 32000000 + +def boxShape : Ix.Theory.Certified.Ordinary.Shape Nat := + ⟨1, [.sort (.succ (.param 0))], [], .succ (.param 0), [⟨[.bvar 0], [], []⟩]⟩ + +def unaryShape (recursivePi : Bool) : Ix.Theory.Certified.Ordinary.Shape Nat := + ⟨1, [.sort (.succ (.param 0))], [], .succ (.param 0), + [⟨[.bvar 0], [], []⟩, ⟨[], [⟨if recursivePi then [.bvar 0] else [], []⟩], []⟩]⟩ + +def tree (level : VLevel) (parameter : VExpr Nat) : VExpr Nat := .app (const 40 0 [level]) parameter +def box (level : VLevel) (parameter : VExpr Nat) : VExpr Nat := .app (const 20 0 [level]) parameter +def unary (level : VLevel) (parameter : VExpr Nat) : VExpr Nat := .app (const 30 0 [level]) parameter +def branch (recursivePi : Bool) (parameter family : VExpr Nat) : VExpr Nat := + if recursivePi then .forallE parameter (family.liftN 1) else family + +def boxMk (level : VLevel) (parameter value : VExpr Nat) : VExpr Nat := + .appN (.const (.ctor 20 0 0) [level]) [parameter, value] + +/-- Tree α = leaf α | node (Box (Tree α)), or node (Box (α → Tree α)). +Both are parameterized nested occurrences with a restored Box recursor. -/ +def treeSource (recursivePi : Bool) : Const Nat := .induct 1 1 0 + (.forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))) [ + ⟨1, 1, 1, .forallE (.sort (.succ (.param 0))) + (.forallE (.bvar 0) (tree (.param 0) (.bvar 1))), .safe⟩, + ⟨1, 1, 1, .forallE (.sort (.succ (.param 0))) + (.forallE (box (.param 0) (branch recursivePi (.bvar 0) (tree (.param 0) (.bvar 0)))) (tree (.param 0) (.bvar 1))), .safe⟩] .safe + +def sourceBlock (recursivePi : Bool) : Nat → Block Nat + | 10 => ⟨[PrimitiveSignature.falseDeclaration]⟩ + | 11 => ⟨[primitives.falseElimDeclaration]⟩ + | 20 => ⟨[boxShape.source 20]⟩ + | 21 => ⟨[boxShape.recursorSource 20 21 .large]⟩ + | 30 => ⟨[(unaryShape recursivePi).source 30]⟩ + | 31 => ⟨[(unaryShape recursivePi).recursorSource 30 31 .large]⟩ + | 40 => ⟨[treeSource recursivePi]⟩ + | _ => ⟨[]⟩ + +def storeFor (blocks : Nat → Block Nat) : Store Nat where + dom := List.range 53 + nodup := List.nodup_range + blocks b := if b < 53 then some (blocks b) else none + mem_dom b := by split <;> simp_all + +def sourceStore (recursivePi : Bool) : Store Nat := storeFor (sourceBlock recursivePi) +def treeRecursors (recursivePi : Bool) : Block Nat := + if recursivePi then ModeledFixtures.nestedPiRecursors else ModeledFixtures.nestedRecursors + +def modelTargets : List (ConstRef Nat) := [ref 30, .ctor 30 0 0, ref 50, ref 51, ref 52] +def modelPairs : List (ConstRef Nat × ConstRef Nat) := + [ref 40, .ctor 40 0 0, .ctor 40 0 1, ref 41, ref 41 1].zip modelTargets +def mapped (expression : VExpr Nat) : VExpr Nat := expression.mapRefs (Certificate.Modeled.target modelPairs) +def recursorType (recursivePi : Bool) (index : Nat) : VExpr Nat := + mapped (((treeRecursors recursivePi).members[index]?).map Const.type |>.getD (.sort .zero)) +def recPrefix (recursivePi : Bool) : List (VExpr Nat) := (recursorType recursivePi 0).telN 6 + +def nodeType (recursivePi : Bool) : VExpr Nat := + match treeSource recursivePi with + | .induct _ _ _ _ ctors _ => mapped ((ctors[1]?).map Ctor.type |>.getD (.sort .zero)) + | _ => .sort .zero +def nodeBody (recursivePi : Bool) : VExpr Nat := .lam (.sort (.succ (.param 0))) + (.lam (box (.param 0) (branch recursivePi (.bvar 0) (unary (.param 0) (.bvar 0)))) + (.appN (.const (.ctor 30 0 1) [.param 0]) [.bvar 1, .proj (ref 20) 0 (.bvar 0)])) + +/-- Ordinary unary recursion supplies both nested calls. The constructor +and auxiliary recursor use Box's independently checked projection and eta. -/ +def treeModel (recursivePi : Bool) : VExpr Nat := .lamN (recPrefix recursivePi) + (.appN (const 31 0 [.param 0, .param 1]) [ + .bvar 5, .bvar 4, .bvar 2, + .lam (branch recursivePi (.bvar 5) (unary (.param 1) (.bvar 5))) + (.lam (if recursivePi then .forallE (.bvar 6) (.app (.bvar 6) (.app (.bvar 1) (.bvar 0))) + else .app (.bvar 5) (.bvar 0)) + (.appN (.bvar 3) [boxMk (.param 1) (branch recursivePi (.bvar 7) (unary (.param 1) (.bvar 7))) (.bvar 1), + .appN (.bvar 2) [.bvar 1, .bvar 0]]))]) + +def boxModel (recursivePi : Bool) : VExpr Nat := .lamN (recPrefix recursivePi) + (.appN (const 21 0 [.param 0, .param 1]) [ + branch recursivePi (.bvar 5) (unary (.param 1) (.bvar 5)), .bvar 3, + .lam (branch recursivePi (.bvar 5) (unary (.param 1) (.bvar 5))) + (.appN (.bvar 1) [.bvar 0, + if recursivePi then .lam (.bvar 6) + (.appN (const 51 0 [.param 0, .param 1]) (VExpr.bvarRevRange 2 6 ++ [.app (.bvar 1) (.bvar 0)])) + else .appN (const 51 0 [.param 0, .param 1]) (VExpr.bvarRevRange 1 6 ++ [.bvar 0])])]) + +def block (recursivePi : Bool) : Nat → Block Nat + | 41 => treeRecursors recursivePi + | 50 => ⟨[.defn 1 .definition (nodeType recursivePi) (nodeBody recursivePi) .safe]⟩ + | 51 => ⟨[.defn 2 .definition (recursorType recursivePi 0) (treeModel recursivePi) .safe]⟩ + | 52 => ⟨[.defn 2 .definition (recursorType recursivePi 1) (boxModel recursivePi) .safe]⟩ + | n => sourceBlock recursivePi n +def store (recursivePi : Bool) : Store Nat := storeFor (block recursivePi) +def candidate : Certificate.Modeled.Candidate Nat := ⟨40, [ref 41, ref 41 1], modelTargets, []⟩ + +def prefixWitnesses? (recursivePi : Bool) : Option (Environment Nat × List (DeclarationWitness Nat)) := + declarationWitnesses? 4000 (store recursivePi) primitives.environment + [.ordinary 20 21, .ordinary 30 31, .definition (ref 50), .definition (ref 51), .definition (ref 52)] +def modeledWitness? (recursivePi : Bool) : Option (Ix.Theory.Certified.Modeled.Witness Nat) := do + let (entries, _) ← prefixWitnesses? recursivePi + candidate.witness? 4000 entries (store recursivePi) +def generated? (recursivePi : Bool) : Option (List (DeclarationWitness Nat)) := + Certificate.storeWitness? 4000 primitives (store recursivePi) [ref 41, ref 41 1] [candidate] +def accepted (recursivePi : Bool) : Bool := (generated? recursivePi).any + (acceptsStoreCertified.{0,0} 4000 primitives (store recursivePi) [ref 40, ref 41, ref 41 1]) + +#guard [false, true].all fun recursivePi => (treeRecursors recursivePi).members.length == 2 +#guard [false, true].all fun recursivePi => + (Ix.Theory.Certified.Modeled.sourceRefs? (store recursivePi) 40 [ref 41, ref 41 1]).isSome +#guard [false, true].all fun recursivePi => + (Ix.Theory.Certified.Modeled.recursorRules? (store recursivePi) (ref 41)).any (fun rules => rules.length == 2) +#guard [false, true].all fun recursivePi => + (Ix.Theory.Certified.Modeled.recursorRules? (store recursivePi) (ref 41 1)).any (fun rules => rules.length == 1) +#guard [false, true].all fun recursivePi => (prefixWitnesses? recursivePi).isSome +#guard [false, true].all fun recursivePi => (modeledWitness? recursivePi).isSome +#guard [false, true].all accepted + +def computed (recursivePi : Bool) : VExpr Nat := + let treeType := tree .zero (.sort .zero) + let fieldType := branch recursivePi (.sort .zero) treeType + let boxType := box .zero fieldType + let leaf := fun value => VExpr.appN (.const (.ctor 40 0 0) [.zero]) [.sort .zero, value] + let field := if recursivePi then .lam (.sort .zero) (leaf (.bvar 0)) else leaf (.bvar 1) + .appN (const 41 0 [.succ .zero, .zero]) [ + .sort .zero, + .lam treeType (.sort .zero), .lam boxType (.sort .zero), + .lam (.sort .zero) (.bvar 0), + .lam boxType (.lam (.sort .zero) (.bvar 0)), + .lam fieldType (.lam + (if recursivePi then .forallE (.sort .zero) (.sort .zero) else .sort .zero) + (if recursivePi then .app (.bvar 0) (.bvar 3) else .bvar 0)), + .appN (.const (.ctor 40 0 1) [.zero]) [.sort .zero, boxMk .zero fieldType field]] + +def input (recursivePi : Bool) : ProofInput Nat := + ⟨store recursivePi, 0, Tests.Theory.Modeled.proof, + .forallE (.sort .zero) (.forallE (.bvar 0) (computed recursivePi))⟩ +def proofAccepted (recursivePi : Bool) : Bool := + (Certificate.proofWitness? 4000 primitives (input recursivePi) [candidate]).any + (acceptsCertified.{0,0} 4000 primitives (input recursivePi)) + +#guard [false, true].all proofAccepted + +def tampered (recursivePi : Bool) (alter : Const Nat → Const Nat) : Store Nat := + storeFor fun n => if n = 41 then ⟨(treeRecursors recursivePi).members.map alter⟩ else block recursivePi n + +def rejected (recursivePi : Bool) (source : Store Nat) : Bool := (generated? recursivePi).any fun witnesses => + !(acceptsStoreCertified.{0,0} 4000 primitives source [ref 41, ref 41 1] witnesses) + +#guard [false, true].all fun recursivePi => rejected recursivePi (tampered recursivePi fun c => match c with + | .recursor u p i m n t rs k s => .recursor u p i m n (t.instL [.param 1, .param 0]) rs k s + | c => c) +#guard [false, true].all fun recursivePi => rejected recursivePi (tampered recursivePi fun c => match c with + | .recursor u p i m n t rs k s => .recursor u p i m n t (rs.map fun r => { r with nfields := 0 }) k s + | c => c) + +-- Swapping the restored auxiliary with its root, or substituting its model +-- for the root's model, cannot preserve the actual selected rule statements. +#guard [false, true].all fun recursivePi => (prefixWitnesses? recursivePi).any fun (entries, _) => + (Certificate.Modeled.witness? 4000 entries (store recursivePi) 40 [ref 41 1, ref 41] modelTargets).isNone +#guard [false, true].all fun recursivePi => (prefixWitnesses? recursivePi).any fun (entries, _) => + (Certificate.Modeled.witness? 4000 entries (store recursivePi) 40 [ref 41, ref 41 1] + [ref 30, .ctor 30 0 0, ref 50, ref 52, ref 51]).isNone + +end Tests.Theory.ModeledNested diff --git a/Tests/Theory/ModeledPermutation.lean b/Tests/Theory/ModeledPermutation.lean new file mode 100644 index 000000000..8b1eeeaff --- /dev/null +++ b/Tests/Theory/ModeledPermutation.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Theory.Modeled + +open Ix.Theory + +namespace Tests.Theory.ModeledPermutation + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certificate Ix.Theory.Inductive +open Tests.Theory.Certified (primitives) +open Tests.Theory.Modeled (ref const) + +set_option maxRecDepth 16384 +set_option maxHeartbeats 32000000 + +def swap : ConstRef Nat → ConstRef Nat + | .member 30 0 => .member 30 1 + | .member 30 1 => .member 30 0 + | .ctor 30 0 c => .ctor 30 1 c + | .ctor 30 1 c => .ctor 30 0 c + | .member 31 0 => .member 31 1 + | .member 31 1 => .member 31 0 + | ref => ref + +def source : Block Nat := ModeledFixtures.permutedSource +def recursors : Block Nat := ModeledFixtures.permutedRecursors +def targets : List (ConstRef Nat) := + [ref 20, ref 40, ref 20, .ctor 20 0 0, .ctor 20 0 1, ref 43, ref 44] +def pairs : List (ConstRef Nat × ConstRef Nat) := + [ref 30, .ctor 30 0 0, ref 30 1, .ctor 30 1 0, .ctor 30 1 1, ref 31, ref 31 1].zip targets +def type (index : Nat) : VExpr Nat := + (((recursors.members[index]?).map Const.type).getD (.sort .zero)).mapRefs (Certificate.Modeled.target pairs) + +/-- Reorder the complete motive/minor telescope when wrapping the earlier +models. Merely permuting addresses or constructor counts would not typecheck. -/ +def body (index : Nat) : VExpr Nat := .lamN ((type index).telN 5) + (.appN (const (if index = 0 then 42 else 41) 0 [.param 0]) [.bvar 3, .bvar 4, .bvar 1, .bvar 0, .bvar 2]) +def block : Nat → Block Nat + | 30 => source + | 31 => recursors + | 43 => ⟨[.defn 1 .definition (type 0) (body 0) .safe]⟩ + | 44 => ⟨[.defn 1 .definition (type 1) (body 1) .safe]⟩ + | n => Tests.Theory.Modeled.block n +def store : Store Nat where + dom := List.range 45 + nodup := List.nodup_range + blocks b := if b < 45 then some (block b) else none + mem_dom b := by split <;> simp_all +def candidate : Certificate.Modeled.Candidate Nat := ⟨30, [ref 31, ref 31 1], targets, []⟩ +def witnesses? := Certificate.storeWitness? 4000 primitives store [ref 31, ref 31 1] [candidate] +def accepted : Bool := witnesses?.any + (acceptsStoreCertified.{0,0} 4000 primitives store [ref 30, ref 30 1, ref 31, ref 31 1]) + +#guard store.ctorRuleIndex? (.ctor 30 1 0) == some 1 +#guard store.ctorRuleIndex? (.ctor 30 1 1) == some 2 +#guard accepted +#guard (Certificate.storeWitness? 4000 primitives store [ref 31] + [{ candidate with models := Tests.Theory.Modeled.modelTargets }]).isNone + +def computed : VExpr Nat := .appN (const 31 1 [.succ .zero]) [ + .lam (const 30) (.sort .zero), .lam (const 30 1) (.sort .zero), + .lam (const 30 1) (.lam (.sort .zero) (.bvar 0)), .bvar 1, + .lam (const 30) (.lam (.sort .zero) (.bvar 0)), + .app (.const (.ctor 30 1 1) []) + (.app (.const (.ctor 30 0 0) []) (.const (.ctor 30 1 0) []))] +def input : ProofInput Nat := ⟨store, 0, Tests.Theory.Modeled.proof, + .forallE (.sort .zero) (.forallE (.bvar 0) computed)⟩ +def proofAccepted : Bool := (Certificate.proofWitness? 4000 primitives input [candidate]).any + (acceptsCertified.{0,0} 4000 primitives input) +#guard proofAccepted + +/-- Two fresh source auxiliary recursors may share one already checked model. +Their complete types and own rule statements still pass independent checks. -/ +def mergedBlock : Nat → Block Nat + | 45 => ⟨(Tests.Theory.Modeled.mutualRecursors.members[1]?).toList⟩ + | n => Tests.Theory.Modeled.block n +def mergedStore : Store Nat where + dom := List.range 46 + nodup := List.nodup_range + blocks b := if b < 46 then some (mergedBlock b) else none + mem_dom b := by split <;> simp_all +def mergedCandidate : Certificate.Modeled.Candidate Nat := + ⟨30, [ref 31, ref 31 1, ref 45], Tests.Theory.Modeled.modelTargets ++ [ref 42], []⟩ +def mergedWitnesses? := Certificate.storeWitness? 4000 primitives mergedStore [ref 31 1, ref 45] [mergedCandidate] +def mergedAccepted : Bool := mergedWitnesses?.any + (acceptsStoreCertified.{0,0} 4000 primitives mergedStore [ref 31 1, ref 45]) +#guard mergedAccepted +#guard (Certificate.storeWitness? 4000 primitives mergedStore [ref 45] + [{ mergedCandidate with models := Tests.Theory.Modeled.modelTargets ++ [ref 41] }]).isNone + +def mergedComputed : VExpr Nat := .appN (const 45 0 [.succ .zero]) [ + .lam (const 30) (.sort .zero), .lam (const 30 1) (.sort .zero), .bvar 1, + .lam (const 30 1) (.lam (.sort .zero) (.bvar 0)), + .lam (const 30) (.lam (.sort .zero) (.bvar 0)), + .app (.const (.ctor 30 1 0) []) (.const (.ctor 30 0 0) [])] +def mergedInput : ProofInput Nat := ⟨mergedStore, 0, Tests.Theory.Modeled.proof, + .forallE (.sort .zero) (.forallE (.bvar 0) mergedComputed)⟩ +def mergedProofAccepted : Bool := (Certificate.proofWitness? 4000 primitives mergedInput [mergedCandidate]).any + (acceptsCertified.{0,0} 4000 primitives mergedInput) +#guard mergedProofAccepted + +end Tests.Theory.ModeledPermutation diff --git a/Tests/Theory/NamedManifest.lean b/Tests/Theory/NamedManifest.lean new file mode 100644 index 000000000..6bdf540cd --- /dev/null +++ b/Tests/Theory/NamedManifest.lean @@ -0,0 +1,123 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +/-! Retained named-specification source inventory. Original modules, +revision and attribution are recorded in `Ix/Theory/Named/NOTICE`. +Hashes identify the original inputs, before Ix integration. -/ + +namespace Tests.Theory.NamedManifest + +structure SourceFile where + target : String + sourceSha256 : String + +def selected : Array SourceFile := #[ + ⟨"Ix/Theory/Named/Reference/Declaration.lean", "cefbf66e2134bec472aa9fd643122a3052bbbfd12ab04e6dbd85fe21e32fb0fa"⟩, + ⟨"Ix/Theory/Named/Reference/Environment.lean", "8de5b7407e225c96ed4116bc46e2e3bad5009b6bfb0cb4f68d4ce2799eff4f11"⟩, + ⟨"Ix/Theory/Named/Reference/Environment/Basic.lean", "cc39f3a7ae819fed332407c01239dc604a49c8a5dffb379564aade970ff1bcf9"⟩, + ⟨"Ix/Theory/Named/Reference/Expr.lean", "6cb6f0e5df484973fc282bb86968bb51a1c73ec32d726010b1d7b2133229ac81"⟩, + ⟨"Ix/Theory/Named/Reference/ForEachExprV.lean", "260167ef5e882a5bd2482734dd72749b809857dbe99bc2aa32e28c6b4b2fb37e"⟩, + ⟨"Ix/Theory/Named/Reference/FuelConfig.lean", "3ab65df013711059ef867c2683a7516b77cea87a526cf47c1772e9c8a529d35a"⟩, + ⟨"Ix/Theory/Named/Reference/Inductive/Add.lean", "17dda89d60cac89cba4fc9a4db8233eee8199ce7aee4de337bcd677d076eceb6"⟩, + ⟨"Ix/Theory/Named/Reference/Inductive/EliminationTrace.lean", "d14f7bc2aeb2037701ac12d0217f405b94812fdc441942458656bb543627d095"⟩, + ⟨"Ix/Theory/Named/Reference/Inductive/Reduce.lean", "c6daf4dcec4ffc6c27a64e1054500ec025646d6d15c7c2d61c1323e4928dcc17"⟩, + ⟨"Ix/Theory/Named/Reference/Inductive/ValidationTrace.lean", "7b4e36920a1286b319237a4db632acfac09e203cb3699835fa7440e31f52bbbd"⟩, + ⟨"Ix/Theory/Named/Reference/Instantiate.lean", "ae08b31657faf3b54de22688ae287d0bff362c573d6a2dd09f12f417b1975ec2"⟩, + ⟨"Ix/Theory/Named/Reference/Level.lean", "75932c6c1d406cbbf75e60c56b75e4a9b33f743651f5aa50814c7c369edbed76"⟩, + ⟨"Ix/Theory/Named/Reference/List.lean", "4ddde2232aff649a50a8d1bec44e9495e2387dd3fcc29833d4f9c67c514431a4"⟩, + ⟨"Ix/Theory/Named/Reference/LocalContext.lean", "5baf7b6b379cbbd3902578c5da9d454558031b52f2af508481bc4647c0d91a1b"⟩, + ⟨"Ix/Theory/Named/Reference/Primitive.lean", "a8407d6fdb55c15225c5535b89a1c647af7b20729adb810b9887372b1a9ea745"⟩, + ⟨"Ix/Theory/Named/Reference/PtrEq.lean", "395e6b6907e548582d9e40e37f5344d6919e597500608c597048e621f27f0aa2"⟩, + ⟨"Ix/Theory/Named/Reference/Quot.lean", "79c51dae8b2ac0e09537aaabfb32075fe4a9d5dd34a1a78d47a88229a74926c5"⟩, + ⟨"Ix/Theory/Named/Std/Basic.lean", "885fd60674f7ceec447d20b56f34a2945dccc9d1193041d552162b7220ba6d67"⟩, + ⟨"Ix/Theory/Named/Std/Control.lean", "71dd61bc6bb315f1590ae79e276ada1c0c5c8eb31e67b0f994ed29f92b05fcc2"⟩, + ⟨"Ix/Theory/Named/Std/HashMap.lean", "67afa618c36314613b553eb95dafbbf7c5cca01b9e7d8749b4c024de966c37db"⟩, + ⟨"Ix/Theory/Named/Std/NodupKeys.lean", "b0a5f079a7f034f0c436de4ca120fd07197775cba26c625d2a2e1c8054ef460e"⟩, + ⟨"Ix/Theory/Named/Std/Ord.lean", "26380558d7e4fd742274d4f4d9396eb2d10feaa0ad945cfd57c0a37b12a04fa4"⟩, + ⟨"Ix/Theory/Named/Std/PersistentHashMap.lean", "c619b8962018a8b4fe3afb9fb0ee7c77bb92e75c323fc3f849ed4d8c199a4c59"⟩, + ⟨"Ix/Theory/Named/Std/SMap.lean", "574b0996076ccb5814ba381f13f288259fbb821abd33c20f9b891bac6c1e1fb0"⟩, + ⟨"Ix/Theory/Named/Std/ToExpr.lean", "5068adbd3d6c0b2d33ec84420efd66e8025dad2b6ed7171b7d10d1453db08e82"⟩, + ⟨"Ix/Theory/Named/Std/VariableBang.lean", "783456566db97120957903fc5beccf549507ed8e1f0fcd76cde4d0175f02a012"⟩, + ⟨"Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean", "ee30b121ece1f5ea7ca2bb315b8e02557b75b5ef33a9986edb12b7b7dab76de0"⟩, + ⟨"Ix/Theory/Named/ConstructorValidityFixtures.lean", "4743314f7fd0e0323463cc7fd403a68792c5e0dabbdbcaaba9e1289136527cde"⟩, + ⟨"Ix/Theory/Named/Inductive.lean", "5cf6f5c19b301396b35d141a90b6b0281ae984e0e64c502d657d6dc15fb5dc57"⟩, + ⟨"Ix/Theory/Named/InductiveFixtures.lean", "4e663484b880adc47045c4d3760456e3c9192951ff9b0f188eea34eff5adcc55"⟩, + ⟨"Ix/Theory/Named/Literals.lean", "cfb64f593c6e3643d83d479d29129d0e73522327529143ef41fd62e162d6998a"⟩, + ⟨"Ix/Theory/Named/LocalContext.lean", "e31fe96e8ec2e2718c65bd2eb8a4b9c01286d54956d1a4a23ef47b83706c7d1f"⟩, + ⟨"Ix/Theory/Named/Meta.lean", "37f47b54a8b855ee7f0c4f2a322fb3c7ad319d1749861c386d9b966142f2c8b7"⟩, + ⟨"Ix/Theory/Named/MutualInductiveFixtures.lean", "907e4cc7a7855eec5b32bf22457baf0eb482b15529e56d8eb2f2369eaaf79414"⟩, + ⟨"Ix/Theory/Named/NestedInductive.lean", "c88720c864cd7a4c62d44b116779c7ddb93aacd2b9b51c2fea87e4c1afeddfaf"⟩, + ⟨"Ix/Theory/Named/NestedInductiveFixtures.lean", "2b31e2f7691a631007a5a3e4c83227515476c13d812c391e7ab111ceba4b8d99"⟩, + ⟨"Ix/Theory/Named/Projection.lean", "9f5108d2192b951a2b8ee05f102fe03bea5c40563f4f10fa27b74c34853884e6"⟩, + ⟨"Ix/Theory/Named/Quot.lean", "3742bc54150fb1b410d5807cd64355cc169fd6ea809dbb71662dc9d28a64c617"⟩, + ⟨"Ix/Theory/Named/SingletonParity.lean", "018c3ea29f04d2274bd47362ed09d959ab3873abf59f0ad23c79afb03f37eb52"⟩, + ⟨"Ix/Theory/Named/Typing/Basic.lean", "24827047806ee6ffb9af8ed457143cbb6b0c57326557e0f433339840272114a5"⟩, + ⟨"Ix/Theory/Named/Typing/Env.lean", "72949fadf8565117631d4ce822a2d44ebd671843e52a70a8617f0c9c85411cfa"⟩, + ⟨"Ix/Theory/Named/Typing/EnvLemmas.lean", "bd9f777d16b60d6bfa74e5e4e2dbf2423df1c1478c38970144a849078623e80b"⟩, + ⟨"Ix/Theory/Named/Typing/InductiveCertificate.lean", "ef4b4970be4680efda15c6ed921584f30d174a462c2643c6bb60c43d2248d353"⟩, + ⟨"Ix/Theory/Named/Typing/InductiveLemmas.lean", "90bb4f3964705de120018360d7bcf14ab81f05c621fd7c0c0c49539af301fa77"⟩, + ⟨"Ix/Theory/Named/Typing/InductivePattern.lean", "45480de8808c6311c0635ab0afc7fcdbe0c3534558cb1902f7d97d80886c423a"⟩, + ⟨"Ix/Theory/Named/Typing/InductivePatternWF.lean", "884955ce4111aed9540b7d02ebc2469aa26168a8efa476b2ee1cdd01ee402926"⟩, + ⟨"Ix/Theory/Named/Typing/Injectivity.lean", "e7233bde95305b46aa1d22d3e13e21aea93f7e3f903eeb46865c226ffe0bba88"⟩, + ⟨"Ix/Theory/Named/Typing/Lemmas.lean", "f183e28ec58a52dadba983cb53a55537cb9a497d9e8e4f78d2c2ca4cc9427a38"⟩, + ⟨"Ix/Theory/Named/Typing/Meta.lean", "16b0fb88d6719cdd1293108ca2520c1ef2c601819ef5562d0aa7c2d007021d9b"⟩, + ⟨"Ix/Theory/Named/Typing/NestedInductiveLemmas.lean", "f1dcef8e876386abfbebc5a36ca751dafaa75257b7c6c9f506c7447c4be9cd49"⟩, + ⟨"Ix/Theory/Named/Typing/Pattern.lean", "db05a0847000f4d3e2a69f4b053112bfca31dbc2b11082a804052bb44562f4e3"⟩, + ⟨"Ix/Theory/Named/Typing/QuotLemmas.lean", "63abdab93b43679259fc25df480afa1b2086edc8cf52cca5b08b2f36be847309"⟩, + ⟨"Ix/Theory/Named/Typing/Strong.lean", "266fbcb98287ad2f53c0c7ed11960aaa620471b71d4289def448ec259019d46a"⟩, + ⟨"Ix/Theory/Named/Typing/UniqueTyping.lean", "c297cd16f1ec43d6ea4fba930ddd490555cf212d59389f39765beb986dde5a3f"⟩, + ⟨"Ix/Theory/Named/VDecl.lean", "94f3032a2aa1e9e71056b1373fb456b242ede7405c88abe593e7f8432f760a66"⟩, + ⟨"Ix/Theory/Named/VEnv.lean", "16c9bb411f7482d5c08585a278b8ad8209eb8deb023bcb77f7bad675825a83a9"⟩, + ⟨"Ix/Theory/Named/VExpr.lean", "469c797a6eaee8883060470e0830dbe56b4b64f7ca91d9ae63304e288849ac8c"⟩, + ⟨"Ix/Theory/Named/VLevel.lean", "a570dff7d2065ca64acd1bb920628ec332b4e39f18a2dc423cbf3a7bd469ba58"⟩, + ⟨"Ix/Theory/Named/Reference/TypeChecker.lean", "40f99258932cfa5f2c99a2c2b5f7b59b467c10348cd238b70453f95e61dd7383"⟩, + ⟨"Ix/Theory/Named/Verify/Axioms.lean", "4c890728353a1df1b754b09bec3635b75bbfade362aff83a35005b2f316f5863"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/Basic.lean", "161d0abd5c8f4a8a8a09db2ab3bdcd988171aba2c7dcb4a997bd6a8cb32a89ae"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean", "2ce3772020b93feed5e88a0a27d3dcdcb32801b0aca24c7c1e5fb694d9cf382e"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean", "4245035c98958b93c3daefa2efd78f1f0c9779d5bd2a5633db0c2f60958b88b7"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/Elimination.lean", "89365c4a39346bcd7b1f94b7f568a272e4e02b64ff1b897df38f598079890011"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/EliminationFixturesCommon.lean", "1a2dbd72b2538f673c5080abd023c639bee0c200f9d2fd832158f312f726e8b9"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean", "86aaa7338723cdc0005d3646b68c77099ad8e1c113ac283b9d6048783bda4910"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean", "371f2bd76c849048b8c27b741af65214e6345374e09c1658e00eceef0bd5e9d4"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean", "08d2a0352b9a7652ee0c3296b8e6de36e3f3d16b44c77fa962855b355412479a"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean", "5fc23bf4dacc65a476fa6416fbf548c75b563574aad7d1c670d28df5a27ce541"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean", "993466ee37f03b2f7494116d58dca184614f32308b851d0bceb275ddd4c3a79f"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean", "65d5114cba03dbc1e25b5ec644f35d72ac27dc370a376a37536ffb8c9d4e1409"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/IndexedVecCandidate.lean", "ba5fc7e4d21f85c1fbd091bdcdecc51c7c252a00329c6e4ce41cf703cfbfb280"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/IndexedVecConsReplay.lean", "5fc8c9d63d58a208f0318894f9ba77d87cff021f2dc413575da4e8e5ae42d738"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/IndexedVecConstructors.lean", "effb4340d8f020607ef34f0bb0195ee5e4217f15385e0c690b354c1c2aa23b04"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/IndexedVecOuterReplay.lean", "b15ebd574638b1f728439045f06b85421402dabfcc1df1e92fda97198d7de7e8"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean", "d2793f18d3052acac81951e18e01d5a5a20c3569cae1d831e3064c251bcf05c9"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean", "5da7e485923a6e5d9db14361844d48c9628f22b7088072d861f9d24e01acd934"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/Lemmas.lean", "fe1c3fcec718f780e29af9051b62a906b3f6aa53502ac8740d01f8477ab49576"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/MutualInductiveFixtures.lean", "cab86779e590746367fb013f95ecb48f0a3f86b06a56ccf1ac43ae7fec78514d"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/NestedReplay.lean", "c76e7291e064a68f64b3d545de4c887fd8321950d514b485832dce76108bfa28"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean", "7e5cd82cf41d35a6844d2cbc1f5af67ab5ccad33f81e199984e4017348487b2d"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/NestedTransformation.lean", "fd1aefd95d4374e0ae87cff11b10c468b7743c822f0f4cbb1a4f3923baee0b0f"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/Normalization.lean", "a9df5c28f597dc88f0cc496a1ad8a2c189ef82fddd194007e2bda7de15c27cdc"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean", "0495afd91d4770ec0dc998431828b370c65b4cc1b894994c06b4a50525b44342"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean", "abc03daf11487f774a89f18506995d3e1f45e817f99dcc361219da73dd586322"⟩, + ⟨"Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean", "19cf222cf463ad9882c7c2ce278150678310b00141fa712684cb68061d1761c2"⟩, + ⟨"Ix/Theory/Named/Verify/Expr.lean", "520da96e974f708a15b738479cea37bdc3458adaca6523975f69b15f7bf52cd4"⟩, + ⟨"Ix/Theory/Named/Verify/Level.lean", "66f0ffcb59ae63498e8c6fb9cee87fa4003c67f1628fb87ec7661714975a4e02"⟩, + ⟨"Ix/Theory/Named/Verify/LevelStd.lean", "8aada81455e9c6a88eba0dcce86e30daf34ec9215e26ae4dfc9f396a49b8f57c"⟩, + ⟨"Ix/Theory/Named/Verify/LocalContext.lean", "91718812c4d727d27f8723e039b5e7d490e03a7d8bb4163ffed26ee1df030fe8"⟩, + ⟨"Ix/Theory/Named/Verify/Name.lean", "8a3ae08cc776deba9354b28010327470f241e4c924c335dff142b3f8ec326c78"⟩, + ⟨"Ix/Theory/Named/Verify/NameGenerator.lean", "3d7305876fcfc487c625aaee8c737a4bdb1a80b62f70a4fc3cfeaf3cf39219af"⟩, + ⟨"Ix/Theory/Named/Verify/NormLt.lean", "970149d18191ecbd889136507e6dd68ea43b833b6170ab825b69a90b4561e2f5"⟩, + ⟨"Ix/Theory/Named/Verify/QSort.lean", "79cbf8f96fb223526690c12333a095aa87ecf7d889b4ba2abacd328609550b9a"⟩, + ⟨"Ix/Theory/Named/Verify/TypeChecker.lean", "0a8441fa3354c7002b2b4b7491f04eaac94bd137d7eaaf8a1859bae0af6f58be"⟩, + ⟨"Ix/Theory/Named/Verify/TypeChecker/Basic.lean", "a9cc58cb6b86a6f84b30f41f520f3b9f26a30bdd56885107efc6f3e03b3df8dc"⟩, + ⟨"Ix/Theory/Named/Verify/TypeChecker/InferType.lean", "ddc9fa7ec80b958169d6515a92a723dbe6042ca4b3cdd7d6cfcc6fb859b1f90f"⟩, + ⟨"Ix/Theory/Named/Verify/TypeChecker/IsDefEq.lean", "3b9d09d09029eec24514e9905dd00c7435ba103717e506a46939818a80a39c9b"⟩, + ⟨"Ix/Theory/Named/Verify/TypeChecker/Reduce.lean", "ddc6abecc09ad21769b83b857d11bbecd3859be58debab62360fa9d9a5ec31cf"⟩, + ⟨"Ix/Theory/Named/Verify/TypeChecker/WHNF.lean", "745637e76413130151c0fb21401a3ee10cbb420aa8c9de4203afff147c2bd9cd"⟩, + ⟨"Ix/Theory/Named/Verify/Typing/ConditionallyTyped.lean", "2df5d00a10e4497b631a4d2a90b93cf811ab13cbfb735234a5815963928c3255"⟩, + ⟨"Ix/Theory/Named/Verify/Typing/Expr.lean", "2f9cb98009b6dcd0d45ec4b967e22756f4af1a32a4d45949ad5b4152b8e416c5"⟩, + ⟨"Ix/Theory/Named/Verify/Typing/Lemmas.lean", "ac1a2960dc945d5d9b5b998b438da6dd7ad6160b08a646f3e2c0b56cede54669"⟩, + ⟨"Ix/Theory/Named/Verify/VLCtx.lean", "f99f9fb85d79b2f9acd201323cc493f737285c34c064fc2bc68680c595878aa3"⟩ +] + +end Tests.Theory.NamedManifest diff --git a/Tests/Theory/Natural.lean b/Tests/Theory/Natural.lean new file mode 100644 index 000000000..a0bfa450a --- /dev/null +++ b/Tests/Theory/Natural.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Theory.Standard + +open Ix.Theory + +namespace Tests.Theory.Natural + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certified.Basis Ix.Theory.Certificate +open Tests.Theory.Certified (primitives) + +set_option maxRecDepth 16384 +set_option maxHeartbeats 16000000 + +def nat : AExpr Nat := .const (.member 200 0) [] +def zero : AExpr Nat := .const (.ctor 200 0 0) [] +def succ (n : AExpr Nat) : AExpr Nat := .app (.const (.ctor 200 0 1) []) n +def numeral : Nat → AExpr Nat + | 0 => zero + | n + 1 => succ (numeral n) + +def profile : PrimitiveSignature Nat := { primitives with natType := some (.member 200 0) } +def binaryType : AExpr Nat := .forallE .never nat (.forallE .never nat nat) +def motive : AExpr Nat := .lam .never nat nat +def addBody : AExpr Nat := + .lam .never nat (.lam .never nat + (.appN (.const (.member 201 0) [.succ .zero]) + [motive, .bvar 1, .lam .never nat (.lam .never nat (succ (.bvar 0))), .bvar 0])) +def add (n m : AExpr Nat) : AExpr Nat := .appN (.const (.member 300 0) []) [n, m] +def mulBody : AExpr Nat := + .lam .never nat (.lam .never nat + (.appN (.const (.member 201 0) [.succ .zero]) + [motive, .natLit 0, .lam .never nat (.lam .never nat (add (.bvar 3) (.bvar 0))), .bvar 0])) +def mul (n m : AExpr Nat) : AExpr Nat := .appN (.const (.member 301 0) []) [n, m] + +def declaration : Nat → Const Nat + | 200 => Certified.Natural.shape.source 200 + | 201 => Certified.Natural.shape.recursorSource 200 201 .large + | 300 => .defn 0 .definition binaryType.erase addBody.erase .safe + | 301 => .defn 0 .definition binaryType.erase mulBody.erase .safe + | 302 => .defn 0 .definition nat.erase (.natLit 3) .safe + | b => Standard.declaration b + +def store (alter : Nat → Const Nat → Const Nat := fun _ c => c) : Store Nat where + dom := [10, 11, 100, 101, 200, 201, 300, 301, 302] + nodup := by decide + blocks b := if b ∈ [10, 11, 100, 101, 200, 201, 300, 301, 302] then some ⟨[alter b (declaration b)]⟩ else none + mem_dom b := by split <;> simp_all + +def proposition (lhs rhs : AExpr Nat) : AExpr Nat := Equality.applied Standard.eq (.succ .zero) nat lhs rhs +def proof (n : Nat) : AExpr Nat := Equality.reflexivity Standard.refl (.succ .zero) nat (.natLit n) +def input (lhs : AExpr Nat) (value : Nat) : ProofInput Nat := + ⟨store, 0, (proof value).erase, (proposition lhs (.natLit value)).erase⟩ +def accepted (lhs : AExpr Nat) (value : Nat) : Bool := + let input := input lhs value + (Certificate.proofWitness? 3200 profile input).any (acceptsCertified.{0,0} 6400 profile input) + +#guard accepted zero 0 +#guard accepted (numeral 4) 4 +#guard accepted (succ (.natLit 8)) 9 +#guard accepted (.const (.member 302 0) []) 3 +#guard accepted (add (.natLit 0) (.natLit 0)) 0 +#guard accepted (add (.natLit 2) (.natLit 3)) 5 +#guard accepted (mul (.natLit 2) (.natLit 3)) 6 +#guard accepted (mul (.natLit 5) (.natLit 0)) 0 + +def sampleInput := input (add (.natLit 2) (.natLit 3)) 5 +def sampleWitness := Certificate.proofWitness? 3200 profile sampleInput + +#guard sampleWitness.isSome +#guard sampleWitness.any fun witness => witness.declarations.any fun declaration => match declaration with + | .natural _ => true + | _ => false + +-- The original successful witness must fail when the primitive selection, +-- authenticated source, claimed answer or admitted literal fact is changed. +#guard sampleWitness.any fun witness => !acceptsCertified.{0,0} 6400 primitives sampleInput witness +#guard sampleWitness.any fun witness => + !acceptsCertified.{0,0} 6400 { profile with natType := some (.member 100 0) } sampleInput witness +#guard sampleWitness.any fun witness => !acceptsCertified.{0,0} 6400 profile + { sampleInput with proposition := (proposition (add (.natLit 2) (.natLit 3)) (.natLit 6)).erase } witness +#guard sampleWitness.any fun witness => + let declarations := witness.declarations.map fun declaration => match declaration with + | .natural block => .ordinary block + | _ => declaration + !acceptsCertified.{0,0} 6400 profile sampleInput { witness with declarations } + +def unsafeNat (b : Nat) (c : Const Nat) : Const Nat := + if b = 200 then match c with + | .induct n p i type ctors _ => .induct n p i type ctors .unsafe + | _ => c + else c +def forgedRule (b : Nat) (c : Const Nat) : Const Nat := + if b = 201 then match c with + | .recursor n p i m r type rules k safety => + .recursor n p i m r type (rules.map fun rule => { rule with rhs := zero.erase }) k safety + | _ => c + else c +def changedAdd (b : Nat) (c : Const Nat) : Const Nat := + if b = 300 then .defn 0 .definition binaryType.erase (.lam nat.erase (.lam nat.erase (.natLit 0))) .safe else c + +#guard [unsafeNat, forgedRule, changedAdd].all fun alter => sampleWitness.any fun witness => + !acceptsCertified.{0,0} 6400 profile { sampleInput with store := store alter } witness + +end Tests.Theory.Natural diff --git a/Tests/Theory/Operations.lean b/Tests/Theory/Operations.lean new file mode 100644 index 000000000..b281555e1 --- /dev/null +++ b/Tests/Theory/Operations.lean @@ -0,0 +1,49 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certified.Operations +import Tests.Theory.Acceptance + +open Ix.Theory + +namespace Tests.Theory.Operations + +open Ix.Theory.Certified Ix.Theory.Model +open Tests.Theory.Checker +open Tests.Theory.Acceptance (identityAnnotations) + +def betaType : AExpr Nat := .forallE .never (.sort .zero) (.sort .zero) + +def betaInference : InferenceWitness Nat := { + annotations := .app (identityAnnotations (.succ .zero)) .leaf + type := betaType + typing := .app .never (.sort (.succ .zero)) (.forallE .never (.bvar 0) (.bvar 1)) + (identityWitness (.succ .zero)) .sort +} + +def betaWhnf : WhnfWitness Nat := { + source := betaInference + result := betaResult + resultTyping := .lam (.succ .zero) (.succ .zero) (.sort .zero) .sort .sort .bvar + conversion := betaWitness +} + +#guard inferCertified.{0,0} 50 0 emptyEnvironment [] betaSource.erase betaInference |>.isSome +#guard whnfCertified.{0,0} 50 0 emptyEnvironment [] betaSource.erase betaWhnf |>.isSome + +-- Valid typing plus reflexive conversion does not certify a remaining redex. +#guard whnfCertified.{0,0} 50 0 emptyEnvironment [] betaSource.erase + { betaWhnf with + result := betaSource + resultTyping := betaInference.typing + conversion := .refl } |>.isNone + +-- Neither the input reading nor the proposed normal form can change unchecked. +#guard whnfCertified.{0,0} 50 0 emptyEnvironment [] + (.app (identity .zero).erase (.sort .zero)) betaWhnf |>.isNone +#guard whnfCertified.{0,0} 50 0 emptyEnvironment [] betaSource.erase + { betaWhnf with result := .sort .zero, resultTyping := .sort } |>.isNone + +end Tests.Theory.Operations diff --git a/Tests/Theory/Ordinary.lean b/Tests/Theory/Ordinary.lean new file mode 100644 index 000000000..0ba2acd5d --- /dev/null +++ b/Tests/Theory/Ordinary.lean @@ -0,0 +1,203 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Ordinary +import Ix.Theory.Certified.Ordinary.LargeElim +import Ix.Theory.Certified.Ordinary.RecursorSyntax +import Tests.Theory.RecursorGoldens + +open Ix.Theory + +/-! These exercise shape and evidence production. They do not claim closed +proof acceptance or VM coverage of inductives. -/ + +namespace Tests.Theory.Ordinary + +open Model Certified Certified.Ordinary + +private structure SourceFamily where + type : VExpr Nat + ctors : List (Ctor Nat) + +def natSourceBlock : Nat := 10 +def functionalSourceBlock : Nat := 50 +def indexedSourceBlock : Nat := 60 + +private def natType : VExpr Nat := .const (.member natSourceBlock 0) [] +private def natFamily : SourceFamily := ⟨.sort (.succ .zero), [ + ⟨0, 0, 0, natType, .safe⟩, + ⟨0, 0, 1, .forallE natType natType, .safe⟩]⟩ + +private def functionalType : VExpr Nat := .const (.member functionalSourceBlock 0) [] +private def functionalFamily : SourceFamily := ⟨.sort (.succ .zero), [ + ⟨0, 0, 1, .forallE (.forallE (.sort .zero) functionalType) functionalType, .safe⟩]⟩ + +private def indexedFamily : SourceFamily := + ⟨.forallE (.sort (.succ .zero)) (.sort (.succ .zero)), [ + ⟨0, 0, 0, .app (.const (.member indexedSourceBlock 0) []) (.sort .zero), .safe⟩]⟩ + +def noEntries : Environment Nat := fun _ => none + +def singletonStore (source : Nat) (decl : Const Nat) : Store Nat where + dom := [source] + nodup := by simp + blocks b := if b = source then some ⟨[decl]⟩ else none + mem_dom b := by by_cases h : b = source <;> simp [h] + +def checked (source : Nat) (decl : Const Nat) (shape : Shape Nat) : Bool := + match Certificate.Ordinary.shape? 100 noEntries shape with + | none => false + | some witness => (checkShape.{0,0} 100 noEntries (singletonStore source decl) source witness).isSome + +def largeChecked (shape : Shape Nat) : Bool := + match Certificate.Ordinary.shape? 100 noEntries shape with + | none => false + | some witness => (checkLarge.{0,0} 100 noEntries witness).isSome + +def natShape : Shape Nat := + ⟨0, [], [], .succ .zero, [⟨[], [], []⟩, ⟨[], [⟨[], []⟩], []⟩]⟩ + +#guard natShape.source natSourceBlock = + .induct 0 0 0 natFamily.type natFamily.ctors .safe +#guard checked natSourceBlock (.induct 0 0 0 natFamily.type natFamily.ctors .safe) natShape +#guard largeChecked natShape + +def functionalShape : Shape Nat := + ⟨0, [], [], .succ .zero, [⟨[], [⟨[.sort .zero], []⟩], []⟩]⟩ + +#guard functionalShape.source functionalSourceBlock = + .induct 0 0 0 functionalFamily.type functionalFamily.ctors .safe +#guard checked functionalSourceBlock + (.induct 0 0 0 functionalFamily.type functionalFamily.ctors .safe) functionalShape + +def indexedShape : Shape Nat := + ⟨0, [], [.sort (.succ .zero)], .succ .zero, [⟨[], [], [.sort .zero]⟩]⟩ + +#guard indexedShape.source indexedSourceBlock = + .induct 0 0 1 indexedFamily.type indexedFamily.ctors .safe +#guard checked indexedSourceBlock + (.induct 0 0 1 indexedFamily.type indexedFamily.ctors .safe) indexedShape + +def listShape : Shape Nat := + ⟨1, [.sort (.succ (.param 0))], [], .succ (.param 0), + [⟨[], [], []⟩, ⟨[.bvar 0], [⟨[], []⟩], []⟩]⟩ + +def listType : VExpr Nat := .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0))) +def listDecl : Const Nat := .induct 1 1 0 listType [ + ⟨1, 1, 0, .forallE (.sort (.succ (.param 0))) (.app (.const (.member 70 0) [.param 0]) (.bvar 0)), .safe⟩, + ⟨1, 1, 2, .forallE (.sort (.succ (.param 0))) <| .forallE (.bvar 0) <| + .forallE (.app (.const (.member 70 0) [.param 0]) (.bvar 1)) + (.app (.const (.member 70 0) [.param 0]) (.bvar 2)), .safe⟩] .safe + +#guard listShape.source 70 = listDecl +#guard checked 70 listDecl listShape +#guard largeChecked listShape + +-- The branch domain depends on the constructor's ordinary field and a +-- parameter function: W (A : Type) (B : A → Type), node a (B a → W A B). +def wShape : Shape Nat := + ⟨0, [.sort (.succ .zero), .forallE .never (.bvar 0) (.sort (.succ .zero))], [], .succ .zero, + [⟨[.bvar 1], [⟨[.app (.bvar 1) (.bvar 0)], []⟩], []⟩]⟩ +#guard checked 71 (wShape.source 71) wShape +#guard largeChecked wShape + +-- The second index depends on the first. Checking only a list of arities +-- would miss an ill-typed second argument. +def dependentIndices : Shape Nat := + ⟨0, [], [.sort .zero, .bvar 0], .succ .zero, + [⟨[.sort .zero, .bvar 0], [], [.bvar 1, .bvar 0]⟩]⟩ +#guard checked 72 (dependentIndices.source 72) dependentIndices + +def wrongIndices : Shape Nat := + { dependentIndices with constructors := [⟨[.sort .zero, .bvar 0], [], [.bvar 1, .sort .zero]⟩] } +#guard !checked 72 (wrongIndices.source 72) wrongIndices + +def tooLarge : Shape Nat := ⟨0, [], [], .succ .zero, [⟨[.sort (.succ .zero)], [], []⟩]⟩ +#guard !checked 73 (tooLarge.source 73) tooLarge + +-- A negative occurrence and a same-block recursive domain are rejected even +-- when the proposed descriptor exactly reproduces the source declaration. +def negative : Shape Nat := + ⟨0, [], [], .succ .zero, [⟨[.forallE .never (.const (.member 74 0) []) (.sort .zero)], [], []⟩]⟩ +#guard !checked 74 (negative.source 74) negative +def recursiveDomain : Shape Nat := + ⟨0, [], [], .succ .zero, [⟨[], [⟨[.const (.member 75 0) []], []⟩], []⟩]⟩ +#guard !checked 75 (recursiveDomain.source 75) recursiveDomain + +def emptyProp : Shape Nat := ⟨0, [], [], .zero, []⟩ +def singletonProp : Shape Nat := ⟨0, [.sort .zero], [], .zero, [⟨[.bvar 0], [], []⟩]⟩ +def manyProp : Shape Nat := ⟨0, [], [], .zero, [⟨[], [], []⟩, ⟨[], [], []⟩]⟩ +def dataProp : Shape Nat := ⟨0, [], [], .zero, [⟨[.sort .zero], [], []⟩]⟩ + +#guard checked 76 (emptyProp.source 76) emptyProp +#guard checked 77 (singletonProp.source 77) singletonProp +#guard checked 78 (manyProp.source 78) manyProp +#guard checked 79 (dataProp.source 79) dataProp +#guard largeChecked emptyProp +#guard largeChecked singletonProp +#guard !largeChecked manyProp +#guard !largeChecked dataProp + +#guard !checked natSourceBlock (.induct 0 0 0 natFamily.type natFamily.ctors .unsafe) natShape +#guard !checked (natSourceBlock + 1) (.induct 0 0 0 natFamily.type natFamily.ctors .safe) natShape +#guard !checked natSourceBlock (.induct 1 0 0 natFamily.type natFamily.ctors .safe) natShape + +def recursorSyntaxMatches (name : String) (shape : Shape Nat) (source recursor : Nat) + (mode : Inductive.ElimMode) : Bool := + match recursorGoldens.find? (·.1 == name) with + | none => false + | some (_, expectedType, expectedRules) => + (shape.recursorType source mode).erase == expectedType && + (shape.constructors.zipIdx.map fun (ctor, i) => + ((shape.ruleRhs source recursor mode i ctor).erase, + (shape.ruleType source mode i ctor).erase)) == expectedRules + +#guard recursorSyntaxMatches "nat" natShape natSourceBlock 90 .large +#guard recursorSyntaxMatches "list" listShape 70 91 .large +#guard recursorSyntaxMatches "indexed" indexedShape indexedSourceBlock 92 .large +#guard recursorSyntaxMatches "functional" functionalShape functionalSourceBlock 93 .large +#guard recursorSyntaxMatches "w" wShape 71 94 .large +#guard recursorSyntaxMatches "dependentIndices" dependentIndices 72 95 .large +#guard recursorSyntaxMatches "manyProp" manyProp 78 96 .small +#guard recursorSyntaxMatches "singletonProp" singletonProp 77 97 .large + +def pairedStore (source recursor : Nat) (h : source ≠ recursor) (decl rec : Const Nat) : Store Nat where + dom := [source, recursor] + nodup := by simp [h] + blocks b := if b = source then some ⟨[decl]⟩ else if b = recursor then some ⟨[rec]⟩ else none + mem_dom b := by by_cases hs : b = source <;> by_cases hr : b = recursor <;> simp [hs, hr, Ne.symm h] + +def signaturesChecked (shape : Shape Nat) (source recursor : Nat) (mode : Inductive.ElimMode) : Bool := Id.run do + if hne : source ≠ recursor then + let store := pairedStore source recursor hne (shape.source source) (shape.recursorSource source recursor mode) + let some sw := Certificate.Ordinary.shape? 500 noEntries shape | return false + let some _ := checkShape.{0,0} 500 noEntries store source sw | return false + let some _ := checkMode.{0,0} 500 noEntries sw mode | return false + let some cws := Certificate.Ordinary.constructorTypes? 500 noEntries shape source | return false + let some _ := shape.checkConstructorTypes.{0,0} 500 noEntries source shape.constructors cws | return false + let some rw := Certificate.Ordinary.recursorType? 500 noEntries shape source mode | return false + let some _ := shape.checkRecursorType.{0,0} 500 noEntries store source recursor mode rw | return false + let some rules := Certificate.Ordinary.rules? 500 noEntries shape source recursor mode | return false + return (shape.checkRules.{0,0} 500 (shape.recursorEnvironment noEntries source recursor mode) + source recursor mode shape.constructors.zipIdx rules).isSome + else return false + +#guard signaturesChecked natShape natSourceBlock 90 .large +#guard signaturesChecked listShape 70 91 .large +#guard signaturesChecked indexedShape indexedSourceBlock 92 .large +#guard signaturesChecked functionalShape functionalSourceBlock 93 .large +#guard signaturesChecked wShape 71 94 .large +#guard signaturesChecked dependentIndices 72 95 .large +#guard signaturesChecked manyProp 78 96 .small +#guard signaturesChecked singletonProp 77 97 .large +#guard !signaturesChecked manyProp 78 96 .large + +-- Formation of a signature alone publishes no equation. +def formedSignature : Environment Nat := fun r => + if r = .member 80 0 then some ⟨0, .sort (.succ .zero), none, [], []⟩ else none +#guard !(verifyConversion.{0,0} 10 0 formedSignature [] (.sort .zero) (.sort (.succ .zero)) + (.equation (.member 80 0) 0 [])).isSome + +end Tests.Theory.Ordinary diff --git a/Tests/Theory/OrdinaryAcceptance.lean b/Tests/Theory/OrdinaryAcceptance.lean new file mode 100644 index 000000000..3d98da6eb --- /dev/null +++ b/Tests/Theory/OrdinaryAcceptance.lean @@ -0,0 +1,162 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Theory.Ordinary +import Tests.Theory.Acceptance +import Ix.Theory.Certificate.Build + +open Ix.Theory + +/-! Closed acceptance through atomic ordinary admission and generated equation +certificates. These are abstract-source tests; serialized VM coverage has its +own adapter and corpus. -/ + +namespace Tests.Theory.OrdinaryAcceptance + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certified.Ordinary Ix.Theory.Certificate +open Tests.Theory.Certified (primitives) +open Tests.Theory.Ordinary (natShape listShape indexedShape emptyProp singletonProp manyProp dataProp) + +set_option maxRecDepth 4096 +set_option maxHeartbeats 8000000 + +def storeFor (shape : Shape Nat) (mode : Inductive.ElimMode) + (recursorOverride : Option (Const Nat) := none) : Store Nat where + dom := [10, 11, 100, 101] + nodup := by decide + blocks b := + if b = 10 then some ⟨[PrimitiveSignature.falseDeclaration]⟩ + else if b = 11 then some ⟨[primitives.falseElimDeclaration]⟩ + else if b = 100 then some ⟨[shape.source 100]⟩ + else if b = 101 then some ⟨[recursorOverride.getD (shape.recursorSource 100 101 mode)]⟩ else none + mem_dom b := by + by_cases h0 : b = 10 <;> by_cases h1 : b = 11 <;> + by_cases hs : b = 100 <;> by_cases hr : b = 101 <;> simp_all + +def admitted (shape : Shape Nat) (mode : Inductive.ElimMode) : Bool := + match initialize?.{0,0} primitives (storeFor shape mode), + Certificate.Ordinary.block? 1000 primitives.environment shape 100 101 mode with + | some state, some witness => (admitOrdinary?.{0,0} 1000 state witness).isSome + | _, _ => false + +#guard admitted natShape .large +#guard admitted listShape .large +#guard admitted indexedShape .large +#guard admitted emptyProp .large +#guard admitted singletonProp .large +#guard admitted manyProp .small +#guard !admitted manyProp .large +#guard !admitted dataProp .large + +def identity : AExpr Nat := .lam .always (.sort .zero) (.lam .always (.bvar 0) (.bvar 0)) +def identityType : AExpr Nat := .forallE .always (.sort .zero) (.forallE .always (.bvar 0) (.bvar 1)) +def proposition (computed : AExpr Nat) : AExpr Nat := + .forallE .always (.sort .zero) (.forallE .always (.bvar 0) computed) + +def proofWitness? (shape : Shape Nat) (mode : Inductive.ElimMode) (proof proposition : AExpr Nat) : + Option (ProofWitness Nat) := do + let block ← Certificate.Ordinary.block? 1000 primitives.environment shape 100 101 mode + let entries := shape.publishedEnvironment primitives.environment 100 101 mode + let P ← inferAnnotated? 1000 0 entries [] proposition + let Pw ← castWith? 1000 0 entries [] P (.sort .zero) + let e ← inferAnnotated? 1000 0 entries [] proof + let ew ← castWith? 1000 0 entries [] e proposition + return ⟨[.ordinary block], annotations proof, annotations proposition, ew, Pw⟩ + +def accepted (shape : Shape Nat) (mode : Inductive.ElimMode) (proof proposition : AExpr Nat) + (recursorOverride : Option (Const Nat) := none) : Bool := + match proofWitness? shape mode proof proposition with + | none => false + | some witness => acceptsCertified.{0,0} 2000 primitives + ⟨storeFor shape mode recursorOverride, 0, proof.erase, proposition.erase⟩ witness + +def family : AExpr Nat := .const (.member 100 0) [] +def zero : AExpr Nat := .const (.ctor 100 0 0) [] +def succ (n : AExpr Nat) : AExpr Nat := .app (.const (.ctor 100 0 1) []) n + +def natComputed : AExpr Nat := .appN (.const (.member 101 0) [.succ .zero]) + [.lam .never family (.sort .zero), .bvar 1, + .lam .never family (.lam .never (.sort .zero) (.bvar 0)), succ zero] + +#guard (proofWitness? natShape .large identity (proposition natComputed)).isSome +#guard accepted natShape .large identity (proposition natComputed) + +def listType : AExpr Nat := .app (.const (.member 100 0) [.zero]) (.sort .zero) +def nil : AExpr Nat := .app (.const (.ctor 100 0 0) [.zero]) (.sort .zero) +def cons : AExpr Nat := .appN (.const (.ctor 100 0 1) [.zero]) [.sort .zero, .bvar 1, nil] +def listComputed : AExpr Nat := .appN (.const (.member 101 0) [.succ .zero, .zero]) + [.sort .zero, .lam .never listType (.sort .zero), .bvar 1, + .lam .never (.sort .zero) (.lam .never listType (.lam .never (.sort .zero) (.bvar 0))), cons] + +#guard (proofWitness? listShape .large identity (proposition listComputed)).isSome +#guard accepted listShape .large identity (proposition listComputed) + +def indexedComputed : AExpr Nat := .appN (.const (.member 101 0) [.succ .zero]) + [.lam .never (.sort (.succ .zero)) (.lam .never (.app family (.bvar 0)) (.sort .zero)), + .bvar 1, .sort .zero, zero] + +#guard accepted indexedShape .large identity (proposition indexedComputed) + +def functionalShape : Shape Nat := + ⟨0, [], [], .succ .zero, [⟨[], [], []⟩, ⟨[], [⟨[.sort .zero], []⟩], []⟩]⟩ +def functionalComputed : AExpr Nat := .appN (.const (.member 101 0) [.succ .zero]) + [.lam .never family (.sort .zero), .bvar 1, + .lam .never (.forallE .never (.sort .zero) family) + (.lam .never (.forallE .never (.sort .zero) (.sort .zero)) (.app (.bvar 0) (.bvar 3))), + succ (.lam .never (.sort .zero) zero)] + +#guard admitted functionalShape .large +#guard (proofWitness? functionalShape .large identity (proposition functionalComputed)).isSome +#guard accepted functionalShape .large identity (proposition functionalComputed) + +def smallProof : AExpr Nat := .lam .always (.sort .zero) (.lam .always (.bvar 0) + (.appN (.const (.member 101 0) []) [.lam .never family (.bvar 2), .bvar 0, .bvar 0, zero])) +#guard accepted manyProp .small smallProof identityType + +-- Source rule tampering cannot be repaired by a valid shape/type certificate. +def forgedNatRecursor : Const Nat := + match natShape.recursorSource 100 101 .large with + | .recursor u p i m n type (_ :: rules) k safety => + .recursor u p i m n type (⟨0, .sort .zero⟩ :: rules) k safety + | other => other +#guard !accepted natShape .large identity (proposition natComputed) (some forgedNatRecursor) + +-- A staged signature has no equation; the public environment gets the law +-- only after the entire block checker succeeds. +def natEquationLicensed (entries : Environment Nat) : Bool := Id.run do + let some law := (natShape.recursorLaws 100 101 .large)[0]? | return false + return (verifyConversion.{0,0} 1000 0 entries [] + (law.lhs.instL [.succ .zero]) (law.rhs.instL [.succ .zero]) + (.equation (.member 101 0) 0 [.succ .zero])).isSome + +#guard natEquationLicensed (natShape.publishedEnvironment primitives.environment 100 101 .large) +#guard !natEquationLicensed (natShape.recursorEnvironment primitives.environment 100 101 .large) + +/-- The generic driver recovers its shape and declaration order from the raw +store. No description is provided to witness construction. -/ +def sourceAccepted (shape : Shape Nat) (mode : Inductive.ElimMode) + (proof proposition : AExpr Nat) : Bool := + let input : ProofInput Nat := ⟨storeFor shape mode, 0, proof.erase, proposition.erase⟩ + (Certificate.proofWitness? 2000 primitives input).any + (acceptsCertified.{0,0} 2000 primitives input) + +#guard sourceAccepted natShape .large identity (proposition natComputed) +#guard sourceAccepted listShape .large identity (proposition listComputed) +#guard sourceAccepted indexedShape .large identity (proposition indexedComputed) +#guard sourceAccepted functionalShape .large identity (proposition functionalComputed) +#guard sourceAccepted manyProp .small smallProof identityType + +-- The source parser also reconstructs dependent telescopes and more than one +-- recursive field. It never silently removes a recursive dependency. +#guard [Tests.Theory.Ordinary.wShape, Tests.Theory.Ordinary.dependentIndices].all fun shape => + (Certificate.Ordinary.description? 1000 primitives.environment 100 (shape.source 100)).isSome + +def multipleFields : Shape Nat := + ⟨0, [], [], .succ .zero, [⟨[], [], []⟩, ⟨[], [⟨[], []⟩, ⟨[], []⟩], []⟩]⟩ +#guard (Certificate.Ordinary.description? 1000 primitives.environment 100 + (multipleFields.source 100)).isSome +#guard (Certificate.Ordinary.removeVariables? 1 (.bvar 0 : VExpr Nat)).isNone + +end Tests.Theory.OrdinaryAcceptance diff --git a/Tests/Theory/Provenance.lean b/Tests/Theory/Provenance.lean new file mode 100644 index 000000000..b430036a3 --- /dev/null +++ b/Tests/Theory/Provenance.lean @@ -0,0 +1,57 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean +import Tests.Theory.ImportManifest +import Tests.Theory.NamedManifest + +open System Tests.Theory.ImportManifest + +private def need (ok : Bool) (message : String) : IO Unit := + unless ok do throw (IO.userError message) + +private def sha256 (path : FilePath) : IO String := do + let result ← IO.Process.output { cmd := "sha256sum", args := #["--", path.toString] } + need (result.exitCode == 0) result.stderr + return (result.stdout.splitOn " ").headD "" + +private def sameFiles (actual expected : Array String) : IO Unit := + need (actual.qsort (· < ·) == expected.qsort (· < ·)) "theory source inventory changed; review import provenance" + +def main (args : List String) : IO Unit := do + need (args.length ≤ 1) "usage: lake env lean --run Tests/Theory/Provenance.lean [CON_LECHE_REPOSITORY]" + let actual := ((← (FilePath.mk "Ix/Theory").walkDir).filter (·.extension == some "lean")).map (·.toString) + let named := actual.filter (·.startsWith "Ix/Theory/Named/") + sameFiles ((actual.filter (!·.startsWith "Ix/Theory/Named/")).push "Ix/Theory.lean") + (selected.map (·.target)) + sameFiles named ((Tests.Theory.NamedManifest.selected.map (·.target)).push + "Ix/Theory/Named/Std/AxiomAudit.lean") + need (← (FilePath.mk "Ix/Theory/Named/LICENSE").pathExists) "missing named-specification Apache license" + need (← (FilePath.mk "Ix/Theory/Named/NOTICE").pathExists) "missing named-specification attribution" + for row in selected do + let contents ← IO.FS.readFile row.target + need (!(contents.contains "import Ix.Theory.Named")) + s!"set-model foundation depends on named checker proof support: {row.target}" + let mut ports := #[] + for directory in ["Ix/Theory/Model/SetTheory", "Ix/Theory/Model/SetModel"] do + ports := ports ++ ((← (FilePath.mk directory).walkDir).filter (·.extension == some "lean")).map (·.toString) + sameFiles ports (conLeche.map (·.target)) + need (← (FilePath.mk "Ix/Theory/LICENSE-APACHE").pathExists) "missing con-leche Apache license" + for row in conLeche do + need ((← sha256 row.target) == row.targetSha256) s!"con-leche port changed: {row.target}" + let contents ← IO.FS.readFile row.target + need (contents.startsWith s!"/-\nPorted from con-leche ({conLecheRevision}).\nSource: {row.source}\n" && + contents.contains "SPDX-License-Identifier: Apache-2.0 AND (MIT OR Apache-2.0)") + s!"con-leche notice changed: {row.target}" + if let some repository := args.head? then + let blob ← IO.Process.output { + cmd := "git", args := #["-C", repository, "show", s!"{conLecheRevision}:{row.source}"] } + need (blob.exitCode == 0) blob.stderr + IO.FS.withTempFile fun handle path => do + handle.putStr blob.stdout + handle.flush + need ((← sha256 path) == row.sourceSha256) s!"con-leche upstream hash mismatch: {row.source}" + IO.println s!"Theory provenance OK: {selected.size} selected source files; {conLeche.size} con-leche ports, exact content and notices." + IO.println s!"Named proof support: {named.size} local source files; separate from the set-model foundation." diff --git a/Tests/Theory/Quotient.lean b/Tests/Theory/Quotient.lean new file mode 100644 index 000000000..792d56c09 --- /dev/null +++ b/Tests/Theory/Quotient.lean @@ -0,0 +1,144 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Build +import Tests.Theory.Certified + +open Ix.Theory + +namespace Tests.Theory.Quotient + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certified.Basis +open Tests.Theory.Certified (primitives) + +set_option maxRecDepth 8192 +set_option maxHeartbeats 12000000 + +def refs : Certified.Quotient.Refs Nat where + eq := .member 100 0 + eqRefl := .ctor 100 0 0 + eqRec := .member 101 0 + type := .member 200 0 + ctor := .member 201 0 + lift := .member 202 0 + ind := .member 203 0 + sound := .member 204 0 + +def declaration : Nat → Const Nat + | 10 => PrimitiveSignature.falseDeclaration + | 11 => primitives.falseElimDeclaration + | 100 => Equality.shape.source 100 + | 101 => Equality.shape.recursorSource 100 101 .large true + | 200 => refs.source .type + | 201 => refs.source .ctor + | 202 => refs.source .lift + | 203 => refs.source .ind + | 204 => refs.source .sound + | _ => .axiom 0 (.sort .zero) .safe + +def addresses : List Nat := [10, 11, 100, 101, 200, 201, 202, 203, 204] + +def store (alter : Nat → Const Nat → Const Nat := fun _ c => c) : Store Nat where + dom := addresses + nodup := by decide + blocks b := if b ∈ addresses then some ⟨[alter b (declaration b)]⟩ else none + mem_dom b := by split <;> simp_all + +def input (n : Nat) (proof proposition : AExpr Nat) : ProofInput Nat := + ⟨store, n, proof.erase, proposition.erase⟩ + +def accepted (n : Nat) (proof proposition : AExpr Nat) : Bool := + let input := input n proof proposition + (Certificate.proofWitness? 3000 primitives input).any (acceptsCertified.{0,0} 3000 primitives input) + +#guard (Certificate.Quotient.refs? store refs.type).isSome +#guard (Certificate.Quotient.refs? store refs.sound).isSome + +-- Exact soundness and dependent Prop induction are themselves closed logical +-- propositions, admitted through source discovery and executable validation. +#guard accepted 1 (.const refs.sound [.param 0]) (Certified.Quotient.soundType refs) +#guard accepted 1 (.const refs.ind [.param 0]) (Certified.Quotient.indType refs) + +def relation (u : VLevel) (A : AExpr Nat) : AExpr Nat := + .lam .never A (.lam .never (A.liftN 1) + (Equality.applied refs.eq u (A.liftN 2) (.bvar 1) (.bvar 0))) + +def constantInvariant (u v : VLevel) (A B b : AExpr Nat) : AExpr Nat := + .lamN .always [A, A.liftN 1, .appN ((relation u A).liftN 2) [.bvar 1, .bvar 0]] + (Equality.reflexivity refs.eqRefl v (B.liftN 3) (b.liftN 3)) + +def computed (u v : VLevel) (A B b a : AExpr Nat) : AExpr Nat := + .appN (.const refs.lift [u, v]) [A, relation u A, B, + .lam (zeroCondition v) A (b.liftN 1), constantInvariant u v A B b, + Certified.Quotient.constructed refs u A (relation u A) a] + +def binders (u : VLevel) : List (AExpr Nat) := [.sort u, .bvar 0, .sort .zero, .bvar 0] +def betaProof (u : VLevel) : AExpr Nat := .lamN .always (binders u) (.bvar 0) +def betaProposition (u : VLevel) : AExpr Nat := + .forallN .always (binders u) (computed u (.succ .zero) (.bvar 3) (.sort .zero) (.bvar 1) (.bvar 2)) + +-- The original statement contains a quotient lift returning a proposition. +-- Conversion to that statement requires the newly admitted computation law. +#guard accepted 1 (betaProof (.param 0)) (betaProposition (.param 0)) +#guard accepted 0 (betaProof .zero) (betaProposition .zero) +#guard accepted 0 (betaProof (.succ .zero)) (betaProposition (.succ .zero)) + +def propLiftProof (u : VLevel) : AExpr Nat := + .lamN .always (binders u) (computed u .zero (.bvar 3) (.bvar 1) (.bvar 0) (.bvar 2)) +def propLiftProposition (u : VLevel) : AExpr Nat := .forallN .always (binders u) (.bvar 1) + +#guard accepted 1 (propLiftProof (.param 0)) (propLiftProposition (.param 0)) +#guard accepted 0 (propLiftProof .zero) (propLiftProposition .zero) + +def betaInput := input 1 (betaProof (.param 0)) (betaProposition (.param 0)) +def betaWitness := Certificate.proofWitness? 3000 primitives betaInput + +#guard betaWitness.isSome + +def wrongKind (b : Nat) (c : Const Nat) : Const Nat := + if b = 200 then .quot .ctor 1 Certified.Quotient.typeType.erase else c +def wrongArity (b : Nat) (c : Const Nat) : Const Nat := + if b = 201 then .quot .ctor 2 (Certified.Quotient.ctorType refs).erase else c +def falseSound (b : Nat) (c : Const Nat) : Const Nat := + if b = 204 then .axiom 1 primitives.falseExpr .safe else c +def unsafeSound (b : Nat) (c : Const Nat) : Const Nat := + if b = 204 then .axiom 1 (Certified.Quotient.soundType refs).erase .unsafe else c +def wrongLift (b : Nat) (c : Const Nat) : Const Nat := + if b = 202 then .quot .lift 2 (Certified.Quotient.indType refs).erase else c + +-- A valid certificate for the original declarations must fail against each +-- altered source store; this tests the validator, not just producer decline. +#guard [wrongKind, wrongArity, falseSound, unsafeSound, wrongLift].all fun alter => + betaWitness.any fun witness => + !acceptsCertified.{0,0} 3000 primitives { betaInput with store := store alter } witness + +#guard betaWitness.any fun witness => + let declarations := witness.declarations.map fun declaration => match declaration with + | .quotient q => DeclarationWitness.quotient { q with types := q.types.drop 1 } + | other => other + !acceptsCertified.{0,0} 3000 primitives betaInput { witness with declarations } + +#guard betaWitness.any fun witness => + let declarations := witness.declarations.map fun declaration => match declaration with + | .quotient q => DeclarationWitness.quotient { q with liftRule := q.indRule } + | other => other + !acceptsCertified.{0,0} 3000 primitives betaInput { witness with declarations } + +#guard betaWitness.any fun witness => + let declarations := witness.declarations.map fun declaration => match declaration with + | .quotient q => DeclarationWitness.quotient { q with refs := { q.refs with ctor := q.refs.type } } + | other => other + !acceptsCertified.{0,0} 3000 primitives betaInput { witness with declarations } + +#guard betaWitness.any fun witness => + let quotient := witness.declarations.filter fun declaration => match declaration with + | .quotient _ => true + | _ => false + let rest := witness.declarations.filter fun declaration => match declaration with + | .quotient _ => false + | _ => true + !acceptsCertified.{0,0} 3000 primitives betaInput { witness with declarations := quotient ++ rest } + +end Tests.Theory.Quotient diff --git a/Tests/Theory/RecursorGoldens.lean b/Tests/Theory/RecursorGoldens.lean new file mode 100644 index 000000000..c02b6b8f0 --- /dev/null +++ b/Tests/Theory/RecursorGoldens.lean @@ -0,0 +1,45 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Expr + +open Ix.Theory + +namespace Tests.Theory + +/-- Frozen outputs of the former inductive generator, captured during the +model import. These retain the independent recursor comparisons without +depending on the old typing/metatheory implementation. -/ +def recursorGoldens : List (String × VExpr Nat × List (VExpr Nat × VExpr Nat)) := [ + ("nat", (.forallE (.forallE (.const (.member 10 0) []) (.sort (.param 0))) (.forallE (.app (.bvar 0) (.const (.ctor 10 0 0) [])) (.forallE (.forallE (.const (.member 10 0) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 10 0 1) []) (.bvar 1))))) (.forallE (.const (.member 10 0) []) (.app (.bvar 3) (.bvar 0)))))), [ + ((.lam (.forallE (.const (.member 10 0) []) (.sort (.param 0))) (.lam (.app (.bvar 0) (.const (.ctor 10 0 0) [])) (.lam (.forallE (.const (.member 10 0) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 10 0 1) []) (.bvar 1))))) (.bvar 1)))), (.forallE (.forallE (.const (.member 10 0) []) (.sort (.param 0))) (.forallE (.app (.bvar 0) (.const (.ctor 10 0 0) [])) (.forallE (.forallE (.const (.member 10 0) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 10 0 1) []) (.bvar 1))))) (.app (.bvar 2) (.const (.ctor 10 0 0) [])))))), + ((.lam (.forallE (.const (.member 10 0) []) (.sort (.param 0))) (.lam (.app (.bvar 0) (.const (.ctor 10 0 0) [])) (.lam (.forallE (.const (.member 10 0) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 10 0 1) []) (.bvar 1))))) (.lam (.const (.member 10 0) []) (.app (.app (.bvar 1) (.bvar 0)) (.app (.app (.app (.app (.const (.member 90 0) [(.param 0)]) (.bvar 3)) (.bvar 2)) (.bvar 1)) (.bvar 0))))))), (.forallE (.forallE (.const (.member 10 0) []) (.sort (.param 0))) (.forallE (.app (.bvar 0) (.const (.ctor 10 0 0) [])) (.forallE (.forallE (.const (.member 10 0) []) (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.bvar 3) (.app (.const (.ctor 10 0 1) []) (.bvar 1))))) (.forallE (.const (.member 10 0) []) (.app (.bvar 3) (.app (.const (.ctor 10 0 1) []) (.bvar 0)))))))) + ]), + ("list", (.forallE (.sort (.succ (.param 1))) (.forallE (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.forallE (.app (.bvar 0) (.app (.const (.ctor 70 0 0) [(.param 1)]) (.bvar 1))) (.forallE (.forallE (.bvar 2) (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 3)) (.forallE (.app (.bvar 3) (.bvar 0)) (.app (.bvar 4) (.app (.app (.app (.const (.ctor 70 0 1) [(.param 1)]) (.bvar 5)) (.bvar 2)) (.bvar 1)))))) (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 3)) (.app (.bvar 3) (.bvar 0))))))), [ + ((.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.app (.bvar 0) (.app (.const (.ctor 70 0 0) [(.param 1)]) (.bvar 1))) (.lam (.forallE (.bvar 2) (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 3)) (.forallE (.app (.bvar 3) (.bvar 0)) (.app (.bvar 4) (.app (.app (.app (.const (.ctor 70 0 1) [(.param 1)]) (.bvar 5)) (.bvar 2)) (.bvar 1)))))) (.bvar 1))))), (.forallE (.sort (.succ (.param 1))) (.forallE (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.forallE (.app (.bvar 0) (.app (.const (.ctor 70 0 0) [(.param 1)]) (.bvar 1))) (.forallE (.forallE (.bvar 2) (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 3)) (.forallE (.app (.bvar 3) (.bvar 0)) (.app (.bvar 4) (.app (.app (.app (.const (.ctor 70 0 1) [(.param 1)]) (.bvar 5)) (.bvar 2)) (.bvar 1)))))) (.app (.bvar 2) (.app (.const (.ctor 70 0 0) [(.param 1)]) (.bvar 3)))))))), + ((.lam (.sort (.succ (.param 1))) (.lam (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.lam (.app (.bvar 0) (.app (.const (.ctor 70 0 0) [(.param 1)]) (.bvar 1))) (.lam (.forallE (.bvar 2) (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 3)) (.forallE (.app (.bvar 3) (.bvar 0)) (.app (.bvar 4) (.app (.app (.app (.const (.ctor 70 0 1) [(.param 1)]) (.bvar 5)) (.bvar 2)) (.bvar 1)))))) (.lam (.bvar 3) (.lam (.app (.const (.member 70 0) [(.param 1)]) (.bvar 4)) (.app (.app (.app (.bvar 2) (.bvar 1)) (.bvar 0)) (.app (.app (.app (.app (.app (.const (.member 91 0) [(.param 0), (.param 1)]) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.bvar 2)) (.bvar 0))))))))), (.forallE (.sort (.succ (.param 1))) (.forallE (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 0)) (.sort (.param 0))) (.forallE (.app (.bvar 0) (.app (.const (.ctor 70 0 0) [(.param 1)]) (.bvar 1))) (.forallE (.forallE (.bvar 2) (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 3)) (.forallE (.app (.bvar 3) (.bvar 0)) (.app (.bvar 4) (.app (.app (.app (.const (.ctor 70 0 1) [(.param 1)]) (.bvar 5)) (.bvar 2)) (.bvar 1)))))) (.forallE (.bvar 3) (.forallE (.app (.const (.member 70 0) [(.param 1)]) (.bvar 4)) (.app (.bvar 4) (.app (.app (.app (.const (.ctor 70 0 1) [(.param 1)]) (.bvar 5)) (.bvar 1)) (.bvar 0)))))))))) + ]), + ("indexed", (.forallE (.forallE (.sort (.succ .zero)) (.forallE (.app (.const (.member 60 0) []) (.bvar 0)) (.sort (.param 0)))) (.forallE (.app (.app (.bvar 0) (.sort .zero)) (.const (.ctor 60 0 0) [])) (.forallE (.sort (.succ .zero)) (.forallE (.app (.const (.member 60 0) []) (.bvar 0)) (.app (.app (.bvar 3) (.bvar 1)) (.bvar 0)))))), [ + ((.lam (.forallE (.sort (.succ .zero)) (.forallE (.app (.const (.member 60 0) []) (.bvar 0)) (.sort (.param 0)))) (.lam (.app (.app (.bvar 0) (.sort .zero)) (.const (.ctor 60 0 0) [])) (.bvar 0))), (.forallE (.forallE (.sort (.succ .zero)) (.forallE (.app (.const (.member 60 0) []) (.bvar 0)) (.sort (.param 0)))) (.forallE (.app (.app (.bvar 0) (.sort .zero)) (.const (.ctor 60 0 0) [])) (.app (.app (.bvar 1) (.sort .zero)) (.const (.ctor 60 0 0) []))))) + ]), + ("functional", (.forallE (.forallE (.const (.member 50 0) []) (.sort (.param 0))) (.forallE (.forallE (.forallE (.sort .zero) (.const (.member 50 0) [])) (.forallE (.forallE (.sort .zero) (.app (.bvar 2) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 2) (.app (.const (.ctor 50 0 0) []) (.bvar 1))))) (.forallE (.const (.member 50 0) []) (.app (.bvar 2) (.bvar 0))))), [ + ((.lam (.forallE (.const (.member 50 0) []) (.sort (.param 0))) (.lam (.forallE (.forallE (.sort .zero) (.const (.member 50 0) [])) (.forallE (.forallE (.sort .zero) (.app (.bvar 2) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 2) (.app (.const (.ctor 50 0 0) []) (.bvar 1))))) (.lam (.forallE (.sort .zero) (.const (.member 50 0) [])) (.app (.app (.bvar 1) (.bvar 0)) (.lam (.sort .zero) (.app (.app (.app (.const (.member 93 0) [(.param 0)]) (.bvar 3)) (.bvar 2)) (.app (.bvar 1) (.bvar 0)))))))), (.forallE (.forallE (.const (.member 50 0) []) (.sort (.param 0))) (.forallE (.forallE (.forallE (.sort .zero) (.const (.member 50 0) [])) (.forallE (.forallE (.sort .zero) (.app (.bvar 2) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 2) (.app (.const (.ctor 50 0 0) []) (.bvar 1))))) (.forallE (.forallE (.sort .zero) (.const (.member 50 0) [])) (.app (.bvar 2) (.app (.const (.ctor 50 0 0) []) (.bvar 0))))))) + ]), + ("w", (.forallE (.sort (.succ .zero)) (.forallE (.forallE (.bvar 0) (.sort (.succ .zero))) (.forallE (.forallE (.app (.app (.const (.member 71 0) []) (.bvar 1)) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.bvar 2) (.forallE (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.app (.const (.member 71 0) []) (.bvar 4)) (.bvar 3))) (.forallE (.forallE (.app (.bvar 3) (.bvar 1)) (.app (.bvar 3) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 3) (.app (.app (.app (.app (.const (.ctor 71 0 0) []) (.bvar 5)) (.bvar 4)) (.bvar 2)) (.bvar 1)))))) (.forallE (.app (.app (.const (.member 71 0) []) (.bvar 3)) (.bvar 2)) (.app (.bvar 2) (.bvar 0))))))), [ + ((.lam (.sort (.succ .zero)) (.lam (.forallE (.bvar 0) (.sort (.succ .zero))) (.lam (.forallE (.app (.app (.const (.member 71 0) []) (.bvar 1)) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.bvar 2) (.forallE (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.app (.const (.member 71 0) []) (.bvar 4)) (.bvar 3))) (.forallE (.forallE (.app (.bvar 3) (.bvar 1)) (.app (.bvar 3) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 3) (.app (.app (.app (.app (.const (.ctor 71 0 0) []) (.bvar 5)) (.bvar 4)) (.bvar 2)) (.bvar 1)))))) (.lam (.bvar 3) (.lam (.forallE (.app (.bvar 3) (.bvar 0)) (.app (.app (.const (.member 71 0) []) (.bvar 5)) (.bvar 4))) (.app (.app (.app (.bvar 2) (.bvar 1)) (.bvar 0)) (.lam (.app (.bvar 4) (.bvar 1)) (.app (.app (.app (.app (.app (.const (.member 94 0) [(.param 0)]) (.bvar 6)) (.bvar 5)) (.bvar 4)) (.bvar 3)) (.app (.bvar 1) (.bvar 0))))))))))), (.forallE (.sort (.succ .zero)) (.forallE (.forallE (.bvar 0) (.sort (.succ .zero))) (.forallE (.forallE (.app (.app (.const (.member 71 0) []) (.bvar 1)) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.bvar 2) (.forallE (.forallE (.app (.bvar 2) (.bvar 0)) (.app (.app (.const (.member 71 0) []) (.bvar 4)) (.bvar 3))) (.forallE (.forallE (.app (.bvar 3) (.bvar 1)) (.app (.bvar 3) (.app (.bvar 1) (.bvar 0)))) (.app (.bvar 3) (.app (.app (.app (.app (.const (.ctor 71 0 0) []) (.bvar 5)) (.bvar 4)) (.bvar 2)) (.bvar 1)))))) (.forallE (.bvar 3) (.forallE (.forallE (.app (.bvar 3) (.bvar 0)) (.app (.app (.const (.member 71 0) []) (.bvar 5)) (.bvar 4))) (.app (.bvar 3) (.app (.app (.app (.app (.const (.ctor 71 0 0) []) (.bvar 5)) (.bvar 4)) (.bvar 1)) (.bvar 0)))))))))) + ]), + ("dependentIndices", (.forallE (.forallE (.sort .zero) (.forallE (.bvar 0) (.forallE (.app (.app (.const (.member 72 0) []) (.bvar 1)) (.bvar 0)) (.sort (.param 0))))) (.forallE (.forallE (.sort .zero) (.forallE (.bvar 0) (.app (.app (.app (.bvar 2) (.bvar 1)) (.bvar 0)) (.app (.app (.const (.ctor 72 0 0) []) (.bvar 1)) (.bvar 0))))) (.forallE (.sort .zero) (.forallE (.bvar 0) (.forallE (.app (.app (.const (.member 72 0) []) (.bvar 1)) (.bvar 0)) (.app (.app (.app (.bvar 4) (.bvar 2)) (.bvar 1)) (.bvar 0))))))), [ + ((.lam (.forallE (.sort .zero) (.forallE (.bvar 0) (.forallE (.app (.app (.const (.member 72 0) []) (.bvar 1)) (.bvar 0)) (.sort (.param 0))))) (.lam (.forallE (.sort .zero) (.forallE (.bvar 0) (.app (.app (.app (.bvar 2) (.bvar 1)) (.bvar 0)) (.app (.app (.const (.ctor 72 0 0) []) (.bvar 1)) (.bvar 0))))) (.lam (.sort .zero) (.lam (.bvar 0) (.app (.app (.bvar 2) (.bvar 1)) (.bvar 0)))))), (.forallE (.forallE (.sort .zero) (.forallE (.bvar 0) (.forallE (.app (.app (.const (.member 72 0) []) (.bvar 1)) (.bvar 0)) (.sort (.param 0))))) (.forallE (.forallE (.sort .zero) (.forallE (.bvar 0) (.app (.app (.app (.bvar 2) (.bvar 1)) (.bvar 0)) (.app (.app (.const (.ctor 72 0 0) []) (.bvar 1)) (.bvar 0))))) (.forallE (.sort .zero) (.forallE (.bvar 0) (.app (.app (.app (.bvar 3) (.bvar 1)) (.bvar 0)) (.app (.app (.const (.ctor 72 0 0) []) (.bvar 1)) (.bvar 0)))))))) + ]), + ("manyProp", (.forallE (.forallE (.const (.member 78 0) []) (.sort .zero)) (.forallE (.app (.bvar 0) (.const (.ctor 78 0 0) [])) (.forallE (.app (.bvar 1) (.const (.ctor 78 0 1) [])) (.forallE (.const (.member 78 0) []) (.app (.bvar 3) (.bvar 0)))))), [ + ((.lam (.forallE (.const (.member 78 0) []) (.sort .zero)) (.lam (.app (.bvar 0) (.const (.ctor 78 0 0) [])) (.lam (.app (.bvar 1) (.const (.ctor 78 0 1) [])) (.bvar 1)))), (.forallE (.forallE (.const (.member 78 0) []) (.sort .zero)) (.forallE (.app (.bvar 0) (.const (.ctor 78 0 0) [])) (.forallE (.app (.bvar 1) (.const (.ctor 78 0 1) [])) (.app (.bvar 2) (.const (.ctor 78 0 0) [])))))), + ((.lam (.forallE (.const (.member 78 0) []) (.sort .zero)) (.lam (.app (.bvar 0) (.const (.ctor 78 0 0) [])) (.lam (.app (.bvar 1) (.const (.ctor 78 0 1) [])) (.bvar 0)))), (.forallE (.forallE (.const (.member 78 0) []) (.sort .zero)) (.forallE (.app (.bvar 0) (.const (.ctor 78 0 0) [])) (.forallE (.app (.bvar 1) (.const (.ctor 78 0 1) [])) (.app (.bvar 2) (.const (.ctor 78 0 1) [])))))) + ]), + ("singletonProp", (.forallE (.sort .zero) (.forallE (.forallE (.app (.const (.member 77 0) []) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.bvar 1) (.app (.bvar 1) (.app (.app (.const (.ctor 77 0 0) []) (.bvar 2)) (.bvar 0)))) (.forallE (.app (.const (.member 77 0) []) (.bvar 2)) (.app (.bvar 2) (.bvar 0)))))), [ + ((.lam (.sort .zero) (.lam (.forallE (.app (.const (.member 77 0) []) (.bvar 0)) (.sort (.param 0))) (.lam (.forallE (.bvar 1) (.app (.bvar 1) (.app (.app (.const (.ctor 77 0 0) []) (.bvar 2)) (.bvar 0)))) (.lam (.bvar 2) (.app (.bvar 1) (.bvar 0)))))), (.forallE (.sort .zero) (.forallE (.forallE (.app (.const (.member 77 0) []) (.bvar 0)) (.sort (.param 0))) (.forallE (.forallE (.bvar 1) (.app (.bvar 1) (.app (.app (.const (.ctor 77 0 0) []) (.bvar 2)) (.bvar 0)))) (.forallE (.bvar 2) (.app (.bvar 2) (.app (.app (.const (.ctor 77 0 0) []) (.bvar 3)) (.bvar 0)))))))) + ]) +] + +end Tests.Theory diff --git a/Tests/Theory/Standard.lean b/Tests/Theory/Standard.lean new file mode 100644 index 000000000..c04d45074 --- /dev/null +++ b/Tests/Theory/Standard.lean @@ -0,0 +1,132 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Build +import Tests.Theory.Certified + +open Ix.Theory + +namespace Tests.Theory.Standard + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certified.Basis Ix.Theory.Certificate +open Tests.Theory.Certified (primitives) + +set_option maxRecDepth 8192 +set_option maxHeartbeats 8000000 + +def eq : ConstRef Nat := .member 100 0 +def refl : ConstRef Nat := .ctor 100 0 0 +def iff : ConstRef Nat := .member 102 0 +def ne : ConstRef Nat := .member 104 0 +def neIntro : ConstRef Nat := .ctor 104 0 0 +def propextRef : ConstRef Nat := .member 106 0 +def choiceRef : ConstRef Nat := .member 107 0 + +def propextSpec : Certified.Standard.Spec Nat := + .propext eq refl (.member 101 0) iff (.ctor 102 0 0) (.member 103 0) +def choiceSpec : Certified.Standard.Spec Nat := .choice ne neIntro (.member 105 0) + +def declaration : Nat → Const Nat + | 10 => PrimitiveSignature.falseDeclaration + | 11 => primitives.falseElimDeclaration + | 100 => Equality.shape.source 100 + | 101 => Equality.shape.recursorSource 100 101 .large true + | 102 => Iff.shape.source 102 + | 103 => Iff.shape.recursorSource 102 103 .large + | 104 => Nonempty.shape.source 104 + | 105 => Nonempty.shape.recursorSource 104 105 .small + | 106 => propextSpec.source + | 107 => choiceSpec.source + | _ => .axiom 0 (.sort .zero) .safe + +def store (alter : Nat → Const Nat → Const Nat := fun _ c => c) : Store Nat where + dom := [10, 11, 100, 101, 102, 103, 104, 105, 106, 107] + nodup := by decide + blocks b := if b ∈ [10, 11, 100, 101, 102, 103, 104, 105, 106, 107] then + some ⟨[alter b (declaration b)]⟩ else none + mem_dom b := by split <;> simp_all + +def input (n : Nat) (proof proposition : AExpr Nat) : ProofInput Nat := + ⟨store, n, proof.erase, proposition.erase⟩ + +def accepted (n : Nat) (proof proposition : AExpr Nat) : Bool := + let input := input n proof proposition + (Certificate.proofWitness? 2000 primitives input).any (acceptsCertified.{0,0} 2000 primitives input) + +#guard accepted 0 (.const propextRef []) propextSpec.type +#guard accepted 0 (.const choiceRef [.zero]) (choiceSpec.type.instL [.zero]) + +def chosen (u : VLevel) (A a : AExpr Nat) : AExpr Nat := + .appN (.const choiceRef [u]) [A, Nonempty.introduction neIntro u A a] + +-- The choice result is used at its actual positive source universe as an +-- argument to reflexivity, under arbitrary A and a : A. +def choiceRefl (u : VLevel) : AExpr Nat := + .lam .always (.sort u) (.lam .always (.bvar 0) + (Equality.reflexivity refl u (.bvar 1) (chosen u (.bvar 1) (.bvar 0)))) +def choiceReflType (u : VLevel) : AExpr Nat := + .forallE .always (.sort u) (.forallE .always (.bvar 0) + (Equality.applied eq u (.bvar 1) (chosen u (.bvar 1) (.bvar 0)) (chosen u (.bvar 1) (.bvar 0)))) + +#guard accepted 1 (choiceRefl (.param 0)) (choiceReflType (.param 0)) +#guard accepted 0 (choiceRefl (.succ .zero)) (choiceReflType (.succ .zero)) +#guard accepted 0 (choiceRefl (.succ (.succ .zero))) (choiceReflType (.succ (.succ .zero))) + +def kDomain (P : AExpr Nat) : AExpr Nat := + Equality.applied eq (.succ .zero) (.sort .zero) P P +def kMotive (P : AExpr Nat) : AExpr Nat := + .lam .never (.sort .zero) + (.lam .never (Equality.applied eq (.succ .zero) (.sort .zero) (P.liftN 1) (.bvar 0)) (.sort .zero)) +def kComputed (P proof : AExpr Nat) : AExpr Nat := + .appN (.const (.member 101 0) [.succ .zero, .succ .zero]) + [.sort .zero, P, kMotive P, P, P, proof] +def kProof : AExpr Nat := + .lam .always (.sort .zero) (.lam .always (.bvar 0) + (.lam .always (kDomain (.bvar 1)) (.bvar 1))) +def kProposition : AExpr Nat := + .forallE .always (.sort .zero) (.forallE .always (.bvar 0) + (.forallE .always (kDomain (.bvar 1)) (kComputed (.bvar 2) (.bvar 0)))) + +-- The major premise is an arbitrary proof of reflexive equality, not a +-- constructor application. Admission permits the exact Eq K metadata, and +-- typed proof irrelevance plus the admitted iota law justify this conversion. +#guard accepted 0 kProof kProposition + +#guard Equality.shape.SupportsK (β := Nat) +#guard ¬ Nonempty.shape.SupportsK (β := Nat) + +def propextInput := input 0 (.const propextRef []) propextSpec.type +def propextWitness := Certificate.proofWitness? 2000 primitives propextInput + +#guard propextWitness.isSome + +def falseAxiom (b : Nat) (c : Const Nat) : Const Nat := + if b = 106 then .axiom 0 primitives.falseExpr .safe else c +def unsafeAxiom (b : Nat) (c : Const Nat) : Const Nat := + if b = 106 then .axiom 0 propextSpec.type.erase .unsafe else c +def wrongArity (b : Nat) (c : Const Nat) : Const Nat := + if b = 106 then .axiom 1 propextSpec.type.erase .safe else c + +#guard [falseAxiom, unsafeAxiom, wrongArity].all fun alter => propextWitness.any fun witness => + !acceptsCertified.{0,0} 2000 primitives { propextInput with store := store alter } witness + +-- A standard schema cannot be admitted before its realized prerequisites. +#guard propextWitness.any fun witness => + let axioms := witness.declarations.filter fun declaration => match declaration with + | .standard _ => true + | _ => false + let rest := witness.declarations.filter fun declaration => match declaration with + | .standard _ => false + | _ => true + !acceptsCertified.{0,0} 2000 primitives propextInput { witness with declarations := axioms ++ rest } + +-- Removing the actual dependent eliminator's certificate is also a failure. +#guard propextWitness.any fun witness => + let declarations := witness.declarations.filter fun declaration => match declaration with + | .ordinary w => w.source != 100 + | _ => true + !acceptsCertified.{0,0} 2000 primitives propextInput { witness with declarations } + +end Tests.Theory.Standard diff --git a/Tests/Theory/Structure.lean b/Tests/Theory/Structure.lean new file mode 100644 index 000000000..b4e95e2ec --- /dev/null +++ b/Tests/Theory/Structure.lean @@ -0,0 +1,159 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Theory.Standard + +open Ix.Theory + +namespace Tests.Theory.Structure + +open Ix.Theory.Model Ix.Theory.Certified Ix.Theory.Certified.Basis Ix.Theory.Certificate +open Tests.Theory.Certified (primitives) + +set_option maxRecDepth 8192 +set_option maxHeartbeats 8000000 + +def box : Certified.Structure.Description Nat := + ⟨1, [], [⟨.sort (.param 0), .succ (.param 0)⟩, ⟨.bvar 0, .param 0⟩], .succ (.param 0)⟩ + +def pair : Certified.Structure.Description Nat := + ⟨1, [.sort (.param 0)], [⟨.bvar 0, .param 0⟩, ⟨.bvar 1, .param 0⟩], .param 0⟩ + +def store (d : Certified.Structure.Description Nat) (alter : Nat → Const Nat → Const Nat := fun _ c => c) : Store Nat where + dom := [10, 11, 100, 101, 200, 201] + nodup := by decide + blocks b := if b ∈ [10, 11, 100, 101, 200, 201] then some ⟨[alter b (match b with + | 200 => d.ordinary.source 200 + | 201 => d.ordinary.recursorSource 200 201 .large + | _ => Standard.declaration b)]⟩ else none + mem_dom b := by split <;> simp_all + +def input (d : Certified.Structure.Description Nat) (n : Nat) (proof proposition : AExpr Nat) : ProofInput Nat := + ⟨store d, n, proof.erase, proposition.erase⟩ + +def accepted (d : Certified.Structure.Description Nat) (n : Nat) (proof proposition : AExpr Nat) : Bool := + let input := input d n proof proposition + (Certificate.proofWitness? 2400 primitives input).any (acceptsCertified.{0,0} 4000 primitives input) + +def boxType (u : VLevel) : AExpr Nat := .const (.member 200 0) [u] +def boxMk (u : VLevel) (A a : AExpr Nat) : AExpr Nat := .appN (.const (.ctor 200 0 0) [u]) [A, a] +def proj (i : Nat) (s : AExpr Nat) : AExpr Nat := .proj (.member 200 0) i s + +def boxProof : AExpr Nat := + .lam .always (.sort .zero) (.lam .always (.bvar 0) (proj 1 (boxMk .zero (.bvar 1) (.bvar 0)))) +def boxProposition : AExpr Nat := + .forallE .always (.sort .zero) (.forallE .always (.bvar 0) (.bvar 1)) + +#guard accepted box 0 boxProof boxProposition + +def etaProof (u : VLevel) : AExpr Nat := + .lam .always (boxType u) (Equality.reflexivity Standard.refl (.succ u) (boxType u) (.bvar 0)) +def etaProposition (u : VLevel) : AExpr Nat := + .forallE .always (boxType u) (Equality.applied Standard.eq (.succ u) (boxType u) + (boxMk u (proj 0 (.bvar 0)) (proj 1 (.bvar 0))) (.bvar 0)) + +#guard accepted box 0 (etaProof .zero) (etaProposition .zero) +#guard accepted box 1 (etaProof (.param 0)) (etaProposition (.param 0)) + +def pairProof : AExpr Nat := + .lam .always (.sort .zero) (.lam .always (.bvar 0) + (proj 1 (.appN (.const (.ctor 200 0 0) [.zero]) [.bvar 1, .bvar 0, .bvar 0]))) + +#guard accepted pair 0 pairProof boxProposition + +def fieldProof (u : VLevel) : AExpr Nat := + .lam .always (.sort u) (.lam .always (.bvar 0) + (Equality.reflexivity Standard.refl u (.bvar 1) (.bvar 0))) +def fieldProposition (u : VLevel) : AExpr Nat := + .forallE .always (.sort u) (.forallE .always (.bvar 0) + (Equality.applied Standard.eq u (.bvar 1) (proj 1 (boxMk u (.bvar 1) (.bvar 0))) (.bvar 0))) + +#guard accepted box 0 (fieldProof .zero) (fieldProposition .zero) +#guard accepted box 0 (fieldProof (.succ .zero)) (fieldProposition (.succ .zero)) +#guard accepted box 1 (fieldProof (.param 0)) (fieldProposition (.param 0)) + +def pairType (u : VLevel) (A : AExpr Nat) : AExpr Nat := .app (boxType u) A +def pairEtaProof (u : VLevel) : AExpr Nat := + .lam .always (.sort u) (.lam .always (pairType u (.bvar 0)) + (Equality.reflexivity Standard.refl u (pairType u (.bvar 1)) (.bvar 0))) +def pairEtaProposition (u : VLevel) : AExpr Nat := + .forallE .always (.sort u) (.forallE .always (pairType u (.bvar 0)) + (Equality.applied Standard.eq u (pairType u (.bvar 1)) + (.appN (.const (.ctor 200 0 0) [u]) [.bvar 1, proj 0 (.bvar 0), proj 1 (.bvar 0)]) (.bvar 0))) + +#guard accepted pair 0 (pairEtaProof .zero) (pairEtaProposition .zero) +#guard accepted pair 1 (pairEtaProof (.param 0)) (pairEtaProposition (.param 0)) + +def boxInput := input box 0 boxProof boxProposition +def boxWitness := Certificate.proofWitness? 2400 primitives boxInput + +#guard boxWitness.isSome +#guard boxWitness.any fun w => w.declarations.any fun d => match d with + | .structure _ => true + | _ => false + +-- These mutations are sent to the validator with the original successful +-- certificate, so a producer decline is not the rejection being tested. +def wrongFieldCount (b : Nat) (c : Const Nat) : Const Nat := + if b = 200 then match c with + | .induct n p i type ctors safety => .induct n p i type (ctors.map fun c => { c with nfields := 1 }) safety + | _ => c + else c +def wrongRecursor (b : Nat) (c : Const Nat) : Const Nat := + if b = 201 then match c with + | .recursor n p i m r type rules _ safety => .recursor n p i m r type rules true safety + | _ => c + else c + +#guard [wrongFieldCount, wrongRecursor].all fun alter => boxWitness.any fun w => + !acceptsCertified.{0,0} 4000 primitives { boxInput with store := store box alter } w + +def badProjectionProof (r : ConstRef Nat) (i : Nat) : AExpr Nat := + .lam .always (.sort .zero) (.lam .always (.bvar 0) + (.proj r i (boxMk .zero (.bvar 1) (.bvar 0)))) + +#guard [(.member 200 0, 2), (.member 100 0, 1)].all fun (r, i) => boxWitness.any fun w => + !acceptsCertified.{0,0} 4000 primitives { boxInput with proof := (badProjectionProof r i).erase } w + +#guard boxWitness.any fun w => + let declarations := w.declarations.map fun declaration => match declaration with + | .structure s => .ordinary s.facts.block + | _ => declaration + !acceptsCertified.{0,0} 4000 primitives boxInput { w with declarations } + +#guard boxWitness.any fun w => + let declarations := w.declarations.map fun declaration => match declaration with + | .structure s => .structure { s with facts := { s.facts with description := + { s.facts.description with fields := s.facts.description.fields.map fun f => { f with level := .zero } } } } + | _ => declaration + !acceptsCertified.{0,0} 4000 primitives boxInput { w with declarations } + +#guard boxWitness.any fun w => + let declarations := w.declarations.map fun declaration => match declaration with + | .structure s => .structure { s with iota := s.iota.reverse } + | _ => declaration + !acceptsCertified.{0,0} 4000 primitives boxInput { w with declarations } + +-- A Prop constructor with a data field remains an ordinary inductive. Even +-- a hand-built structure description cannot grant a projection from it. +def nonempty : Certified.Structure.Description Nat := + ⟨1, [.sort (.param 0)], [⟨.bvar 0, .param 0⟩], .zero⟩ +def nonemptyStore : Store Nat := store nonempty (fun b c => + if b = 201 then nonempty.ordinary.recursorSource 200 201 .small else c) +def nonemptyBlock := Certificate.Ordinary.sourceBlock? 2400 primitives.environment nonemptyStore 200 201 + +#guard nonemptyBlock.isSome +#guard nonemptyBlock.any fun block => + (Certified.Ordinary.checkBlock.{0,0} 4000 primitives.environment nonemptyStore block).isSome && + (Certificate.Structure.description? block).isNone +#guard nonemptyBlock.any fun block => + let domains := Certificate.Ordinary.domains? 2400 nonempty.universes + (nonempty.ordinary.publishedEnvironment primitives.environment 200 201 .small) [] + (nonempty.projectionDomains 200) + domains.any fun domains => + let witness : Certified.Structure.FactsWitness Nat := ⟨nonempty, block, [.bvar], domains⟩ + (Certified.Structure.checkFacts.{0,0} 4000 primitives.environment nonemptyStore witness).isNone + +end Tests.Theory.Structure diff --git a/Tests/Theory/Suggestions.lean b/Tests/Theory/Suggestions.lean new file mode 100644 index 000000000..86fbb37db --- /dev/null +++ b/Tests/Theory/Suggestions.lean @@ -0,0 +1,55 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Certificate.Build +import Tests.Theory.Acceptance + +open Ix.Theory + +namespace Tests.Theory.Suggestions + +open Ix.Theory.Certified Ix.Theory.Model Ix.Theory.Certificate +open Tests.Theory.Acceptance +open Tests.Theory.Certified (primitives) + +/-- Search success is deliberately insufficient: every test runs the public +acceptance validator on the produced ordinary witness data. -/ +def autoAccept (input : ProofInput Nat) : Bool := + (proofWitness? 300 primitives input).any (acceptsCertified.{0,0} 300 primitives input) + +#guard autoAccept identityInput +#guard autoAccept (idDefinitionInput .definition) +#guard autoAccept (idDefinitionInput .theorem) +#guard autoAccept (idDefinitionInput .opaque) +#guard autoAccept { idDefinitionInput with proof := largeIdentityUse.erase } +#guard autoAccept eliminatorInput +#guard !autoAccept { identityInput with proposition := primitives.falseExpr } + +-- Dependent application with a nonempty-domain possibility: +-- λ A B f x => f x, where B : A → Prop and f : (x : A) → B x. +def dependentApplication (u : VLevel) : VExpr Nat := + .lam (.sort u) + (.lam (.forallE (.bvar 0) (.sort .zero)) + (.lam (.forallE (.bvar 1) (.app (.bvar 1) (.bvar 0))) + (.lam (.bvar 2) (.app (.bvar 1) (.bvar 0))))) + +def dependentApplicationType (u : VLevel) : VExpr Nat := + .forallE (.sort u) + (.forallE (.forallE (.bvar 0) (.sort .zero)) + (.forallE (.forallE (.bvar 1) (.app (.bvar 1) (.bvar 0))) + (.forallE (.bvar 2) (.app (.bvar 2) (.bvar 0))))) + +def dependentInput (n : Nat) (u : VLevel) : ProofInput Nat := + ⟨prelude, n, dependentApplication u, dependentApplicationType u⟩ + +#guard autoAccept (dependentInput 1 (.param 0)) +#guard autoAccept (dependentInput 0 .zero) +#guard autoAccept (dependentInput 0 (.succ .zero)) +#guard autoAccept (dependentInput 0 (.succ (.succ .zero))) + +-- An out-of-scope universe is still rejected by the producer and validator. +#guard !autoAccept (dependentInput 0 (.param 0)) + +end Tests.Theory.Suggestions diff --git a/Tests/Theory/certified-foundation.txt b/Tests/Theory/certified-foundation.txt new file mode 100644 index 000000000..df3ab3819 --- /dev/null +++ b/Tests/Theory/certified-foundation.txt @@ -0,0 +1,10669 @@ +certified root Ix.Theory.Model.SetTheory.empty_exists + type: ∀ {V : Type u} [inst : Model.SetTheory V], ∃ e, ∀ (z : V), ¬Model.SetTheory.Mem z e + axioms: [] + constants: 55 + project modules: [Ix.Theory.Model.SetTheory.Core, Ix.Theory.Model.SetTheory.Derive.Empty] +certified root Ix.Theory.Model.SetTheory.not_mem_empty + type: ∀ {V : Type u} [inst : Model.SetTheory V] (z : V), ¬Model.SetTheory.Mem z Model.SetTheory.empty + axioms: [Classical.choice] + constants: 69 + project modules: [Ix.Theory.Model.SetTheory.Core, Ix.Theory.Model.SetTheory.Derive.Empty] +certified root Ix.Theory.VLevel.eval_inst + type: ∀ {ls : List VLevel} {ns : List Nat} {l : VLevel}, + VLevel.eval ns (VLevel.inst ls l) = VLevel.eval (List.map (VLevel.eval ns) ls) l + axioms: [propext] + constants: 669 + project modules: [Ix.Theory.VLevel] +certified root Ix.Theory.Certified.PropWhen.eq_iff_holds + type: ∀ (p q : Certified.PropWhen), + p = q ↔ ∀ (v : Nat → Nat), Certified.PropWhen.holds v p = Certified.PropWhen.holds v q + axioms: [propext, Classical.choice, Quot.sound] + constants: 1705 + project modules: [Ix.Theory.Certified.PropWhen] +certified root Ix.Theory.Certified.validateZero?_sound + type: ∀ {n : Nat} {l : VLevel} {raw : Option (List Nat)} {p : Certified.PropWhen}, + Certified.validateZero? n l raw = some p → + VLevel.WF n l ∧ p.toRaw = raw ∧ Certified.PropWhen.WF n p ∧ p = Certified.zeroCondition l + axioms: [propext, Quot.sound] + constants: 1602 + project modules: [Ix.Theory.VLevel, Ix.Theory.Certified.Level, Ix.Theory.Certified.PropWhen] +certified root Ix.Theory.Certified.zeroCondition_correct + type: ∀ (l : VLevel) (values : List Nat), + Certified.PropWhen.holds (fun x => values.getD x 0) (Certified.zeroCondition l) = (VLevel.eval values l == 0) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1753 + project modules: [Ix.Theory.VLevel, Ix.Theory.Certified.Level, Ix.Theory.Certified.PropWhen] +certified root Ix.Theory.Certified.zeroCondition_inst + type: ∀ (l : VLevel) (levels : List VLevel), + Certified.zeroCondition (VLevel.inst levels l) = Certified.instCondition levels (Certified.zeroCondition l) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1797 + project modules: [Ix.Theory.VLevel, Ix.Theory.Certified.Level, Ix.Theory.Certified.PropWhen] +certified root Ix.Theory.Certified.instCondition_comp + type: ∀ (p : Certified.PropWhen) (levels levels' : List VLevel), + Certified.instCondition levels' (Certified.instCondition levels p) = + Certified.instCondition (List.map (VLevel.inst levels') levels) p + axioms: [propext, Classical.choice, Quot.sound] + constants: 1803 + project modules: [Ix.Theory.VLevel, Ix.Theory.Certified.Level, Ix.Theory.Certified.PropWhen] +certified root Ix.Theory.Model.readAnnotations? + type: {β : Type u} → (n k : Nat) → (source : VExpr β) → Model.AnnotationTree → Option (Model.Reading n k source) + axioms: [propext] + constants: 542 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated] +certified root Ix.Theory.Model.interp_inst + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] (e a : Model.AExpr β) (constants : Model.Assignment β V) + (levels : List Nat) (env : Nat → V) (k : Nat), + Model.interp constants levels env (e.inst a k) = + Model.interp constants levels + (Model.Valuation.insert k (Model.interp constants levels (Model.Valuation.skip k 0 env) a) env) e + axioms: [propext, Classical.choice, Quot.sound] + constants: 1621 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.interp_instL + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] (e : Model.AExpr β) (constants : Model.Assignment β V) + (levels : List Nat) (env : Nat → V) (ls : List VLevel), + Model.interp constants levels env (Model.AExpr.instL ls e) = + Model.interp constants (List.map (VLevel.eval levels) ls) env e + axioms: [propext, Classical.choice, Quot.sound] + constants: 1863 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.interp_rename + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {γ : Type w} (e : Model.AExpr β) (mapping : β → γ) + (constants : Model.Assignment β V) (constants' : Model.Assignment γ V), + (∀ (r : ConstRef β) (ls : List Nat), constants' (ConstRef.rename mapping r) ls = constants r ls) → + ∀ (levels : List Nat) (env : Nat → V), + Model.interp constants' levels env (Model.AExpr.rename mapping e) = Model.interp constants levels env e + axioms: [propext, Classical.choice, Quot.sound] + constants: 725 + project modules: [Ix.Theory.Ref, + Ix.Theory.Rename, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.piR_mem_univ + type: ∀ {V : Type u} [inst : Model.SetTheory V] {a b : Nat} {A : V} {B : V → V}, + Model.SetTheory.Mem A (Model.SetTheory.univ a) → + (∀ (x : V), Model.SetTheory.Mem x A → Model.SetTheory.Mem (B x) (Model.SetTheory.univ b)) → + Model.SetTheory.Mem (Model.SetModel.piR b A B) (Model.SetTheory.univ (VLevel.natIMax a b)) + axioms: [propext, Classical.choice, Quot.sound] + constants: 379 + project modules: [Ix.Theory.VLevel, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.falseValue_uninhabited + type: ∀ {V : Type u} [inst : Model.SetTheory V] (x : V), ¬Model.SetTheory.Mem x Model.falseValue + axioms: [Classical.choice] + constants: 71 + project modules: [Ix.Theory.Model.Value, Ix.Theory.Model.SetTheory.Core, Ix.Theory.Model.SetTheory.Derive.Empty] +certified root Ix.Theory.Model.falseElimValue_mem + type: ∀ {V : Type u} [inst : Model.SetTheory V] (level : Nat), + Model.SetTheory.Mem (Model.falseElimValue level) (Model.falseElimType level) + axioms: [propext, Classical.choice, Quot.sound] + constants: 290 + project modules: [Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.PrimitiveSignature.validate_iff + type: ∀ {β : Type u} [inst : DecidableEq β] (signature : Certified.PrimitiveSignature β) (store : Store β), + signature.validate store = true ↔ + store.lookup signature.falseType = some Certified.PrimitiveSignature.falseDeclaration ∧ + store.lookup signature.falseElim = some signature.falseElimDeclaration + axioms: [propext] + constants: 895 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Policy] +certified root Ix.Theory.Certified.readDefinition? + type: {β : Type u} → + (source : Const β) → Model.AnnotationTree → Model.AnnotationTree → Option { entry // entry.erase = source } + axioms: [propext] + constants: 584 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated] +certified root Ix.Theory.Certified.LevelEq.check_sound + type: ∀ {n : Nat} {a b : VLevel}, + Certified.LevelEq.check n a b = true → + VLevel.WF n a ∧ VLevel.WF n b ∧ ∀ (values : List Nat), VLevel.eval values a = VLevel.eval values b + axioms: [propext, Quot.sound] + constants: 1747 + project modules: [Ix.Theory.VLevel, Ix.Theory.Certified.LevelEq] +certified root Ix.Theory.Certified.LevelEq.leq_sound + type: ∀ {a b : VLevel}, + Certified.LevelEq.leq a b = true → ∀ (values : List Nat), VLevel.eval values a ≤ VLevel.eval values b + axioms: [propext, Quot.sound] + constants: 1655 + project modules: [Ix.Theory.VLevel, Ix.Theory.Certified.LevelEq] +certified root Ix.Theory.Model.wellDenoted_inst + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] (e a : Model.AExpr β) (constants : Model.Assignment β V) + (levels : List Nat) (env : Nat → V) (k : Nat), + Model.WellDenoted constants levels (Model.Valuation.skip k 0 env) a → + Model.WellDenoted constants levels + (Model.Valuation.insert k (Model.interp constants levels (Model.Valuation.skip k 0 env) a) env) e → + Model.WellDenoted constants levels env (e.inst a k) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1635 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.wellDenoted_beta + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} {levels : List Nat} + {env : Nat → V} {p : Certified.PropWhen} {A b a : Model.AExpr β}, + Model.WellDenoted constants levels env (Model.AExpr.lam p A b) → + Model.WellDenoted constants levels env a → + Model.SetTheory.Mem (Model.interp constants levels env a) (Model.interp constants levels env A) → + Model.WellDenoted constants levels env (b.inst a) ∧ + Model.interp constants levels env ((Model.AExpr.lam p A b).app a) = + Model.interp constants levels env (b.inst a) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1681 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.extend_definition + type: ∀ {β : Type u} [inst : DecidableEq β] {V : Type v} [inst_1 : Model.SetTheory V] {entries : Model.Environment β} + {r : ConstRef β} {entry : Model.ConstantEntry β} {body : Model.AExpr β} {level : VLevel}, + entries.WF → + entries r = none → + entry.body = some body → + entry.equations = [] → + entry.facts = [] → + Model.AExpr.Scope entry.universes 0 body → + Model.AExpr.ReferencesIn entries entry.type → + Model.AExpr.ReferencesIn entries body → + Model.TypingClaim entries [] entry.type (Model.AExpr.sort level) → + Model.TypingClaim entries [] body entry.type → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → + ∃ constants', + Model.Realizes constants' (entries.insert r entry) ∧ + Model.Assignment.AgreesOn entries constants constants' + axioms: [propext, Classical.choice, Quot.sound] + constants: 1642 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.ConversionClaim.equation + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {r : ConstRef β} + {entry : Model.ConstantEntry β} {law : Model.ConstantEquation β} {ls : List VLevel}, + entries r = some entry → + law ∈ entry.equations → + ls.length = entry.universes → + Model.ConversionClaim entries Γ (Model.AExpr.instL ls law.lhs) (Model.AExpr.instL ls law.rhs) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1894 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.IndexedContainer.closed_exists + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat}, + D.WF w → ∃ L, Model.SetTheory.IsClosedFam w D.indices (D.step w) L + axioms: [propext, Classical.choice, Quot.sound] + constants: 1795 + project modules: [Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.IndexedContainer.carrier_eq + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat}, + D.WF w → ∀ {i : V}, Model.SetTheory.Mem i D.indices → Model.SetTheory.app (D.carrier w) i = D.fibre w (D.carrier w) i + axioms: [propext, Classical.choice, Quot.sound] + constants: 1803 + project modules: [Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.IndexedContainer.induction + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat}, + D.WF w → + ∀ (P : V → V → Prop), + (∀ (i : V), + Model.SetTheory.Mem i D.indices → + ∀ (a : V), + Model.SetTheory.Mem a (D.shapes i) → + ∀ (g : V), + Model.SetTheory.Mem g + (Model.SetTheory.piSet (D.positions a) fun p => + Model.SetTheory.app (D.carrier w) (D.target a p)) → + (∀ (p : V), Model.SetTheory.Mem p (D.positions a) → P (D.target a p) (Model.SetTheory.app g p)) → + P i (Model.IndexedContainer.node w a g)) → + ∀ (i : V), + Model.SetTheory.Mem i D.indices → + ∀ (x : V), Model.SetTheory.Mem x (Model.SetTheory.app (D.carrier w) i) → P i x + axioms: [propext, Classical.choice, Quot.sound] + constants: 1801 + project modules: [Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.IndexedContainer.child_wellFounded + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat}, + D.WF w → D.LargeElim w → WellFounded (D.Child w) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1812 + project modules: [Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.IndexedContainer.fold_node + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) (algebra : V → V → V → V → V) {i a g : V} (hi : Model.SetTheory.Mem i D.indices) + (ha : Model.SetTheory.Mem a (D.shapes i)) + (hg : + Model.SetTheory.Mem g + (Model.SetTheory.piSet (D.positions a) fun p => Model.SetTheory.app (D.carrier w) (D.target a p))), + Model.IndexedContainer.fold hD hlarge algebra ⟨(i, Model.IndexedContainer.node w a g), ⋯⟩ = + algebra i a g (Model.IndexedContainer.childResults hD hi ha hg (Model.IndexedContainer.fold hD hlarge algebra)) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1845 + project modules: [Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.IndexedContainer.fold_mem + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat} (hD : D.WF w) + (hlarge : D.LargeElim w) {M : V → V → V} {algebra : V → V → V → V → V}, + D.AlgebraTyping w M algebra → + ∀ (z : D.Element w), Model.SetTheory.Mem (Model.IndexedContainer.fold hD hlarge algebra z) (M z.val.fst z.val.snd) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1846 + project modules: [Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.IndexedContainer.small_elim + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat}, + D.WF w → + ∀ {M : V → V → V} {algebra : V → V → V → V → V}, + (∀ (i : V), + Model.SetTheory.Mem i D.indices → + ∀ (x : V), + Model.SetTheory.Mem x (Model.SetTheory.app (D.carrier w) i) → + Model.SetTheory.Mem (M i x) Model.SetTheory.univZero) → + D.AlgebraTyping w M algebra → + ∀ (i : V), + Model.SetTheory.Mem i D.indices → + ∀ (x : V), + Model.SetTheory.Mem x (Model.SetTheory.app (D.carrier w) i) → + Model.SetTheory.Mem Model.SetTheory.pt (M i x) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1809 + project modules: [Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.Telescope.applyN_curry + type: ∀ {V : Type v} [inst : Model.SetTheory V] {w n : Nat} (T : Model.SetTheory.Tower.TeleS V n) {f R : List V → V} + {xs : List V}, + Model.SetTheory.Tower.FitsS T xs → + (∀ (ys : List V), Model.SetTheory.Tower.FitsS T ys → Model.SetTheory.Mem (f ys) (R ys)) → + (w = 0 → + ∀ (ys : List V), Model.SetTheory.Tower.FitsS T ys → Model.SetTheory.Mem (R ys) Model.SetTheory.univZero) → + Model.Telescope.applyN (Model.Telescope.curry w T f) xs = f xs + axioms: [propext, Classical.choice, Quot.sound] + constants: 346 + project modules: [Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep] +certified root Ix.Theory.Model.Telescope.curry_applyN + type: ∀ {V : Type v} [inst : Model.SetTheory V] {w n : Nat} (T : Model.SetTheory.Tower.TeleS V n) {f : V} + {R : List V → V}, + Model.SetTheory.Mem f (Model.Telescope.piN w T R) → + (w = 0 → ∀ (ys : List V), Model.SetTheory.Tower.FitsS T ys → Model.SetTheory.Mem (R ys) Model.SetTheory.univZero) → + Model.Telescope.curry w T (Model.Telescope.applyN f) = f + axioms: [propext, Classical.choice, Quot.sound] + constants: 352 + project modules: [Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep] +certified root Ix.Theory.Certified.verifyTelescope_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel n : Nat} {entries : Model.Environment β} {bound : Option VLevel} + {Γ : Model.Context β} {domains : List (Model.AExpr β)} {witnesses : List (Certified.DomainWitness β)} + {result : + Certified.CheckedClaim + (Model.Telescope.Formed entries Γ domains ∧ Certified.TelescopeBound entries Γ domains bound)}, + Certified.verifyTelescope fuel n entries bound Γ domains witnesses = some result → + Model.Telescope.Formed entries Γ domains ∧ Certified.TelescopeBound entries Γ domains bound + axioms: [propext, Classical.choice, Quot.sound] + constants: 2583 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.verifyArguments_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel n : Nat} {entries : Model.Environment β} {Γ : Model.Context β} + {domains args : List (Model.AExpr β)} {witnesses : List (Certified.TypingWitness β)} + {result : Certified.CheckedClaim (Certified.ArgumentsFit entries Γ domains args)}, + Certified.verifyArguments fuel n entries Γ domains args witnesses = some result → + Certified.ArgumentsFit entries Γ domains args + axioms: [propext, Classical.choice, Quot.sound] + constants: 2579 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.checkShape_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} {store : Store β} + {source : β} {witness : Certified.Ordinary.ShapeWitness β} + {result : Certified.CheckedClaim (Certified.Ordinary.CheckedShape entries store source witness.shape)}, + Certified.Ordinary.checkShape fuel entries store source witness = some result → + Certified.Ordinary.CheckedShape entries store source witness.shape + axioms: [propext, Classical.choice, Quot.sound] + constants: 2891 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.checkLarge_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} + {witness : Certified.Ordinary.ShapeWitness β} + {result : Certified.CheckedClaim (Certified.Ordinary.LargeEvidence entries witness.shape)}, + Certified.Ordinary.checkLarge fuel entries witness = some result → + Certified.Ordinary.LargeEvidence entries witness.shape + axioms: [propext, Classical.choice, Quot.sound] + constants: 2612 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.container_wf + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {constants : Model.Assignment β V} {levels : List Nat} {env : Nat → V} + {store : Store β} {source : β}, + Certified.Ordinary.CheckedShape entries store source shape → + Model.Realizes constants entries → + Model.Context.Valid constants levels shape.parameterContext env → + (shape.container constants levels env).WF (VLevel.eval levels shape.level) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2032 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.constructorValue_mem + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {constants : Model.Assignment β V} {levels : List Nat} {env : Nat → V} + {ctor : Certified.Ordinary.Constructor β} {store : Store β} {source : β}, + Certified.Ordinary.CheckedShape entries store source shape → + Model.Realizes constants entries → + Model.Context.Valid constants levels shape.parameterContext env → + ∀ {i : Nat}, + shape.constructors[i]? = some ctor → + ∀ {xs fs : List V}, + Model.SetTheory.Tower.FitsS (Model.Telescope.interpret constants levels env ctor.fields) xs → + shape.RecursiveValuesFit constants levels env ctor xs fs → + Model.SetTheory.Mem (shape.constructorValue constants levels env ctor i xs fs) + (Model.SetTheory.app (shape.carrier constants levels env) + (Model.SetTheory.Tower.mkTower + (List.map (Model.interp constants levels (Model.Telescope.extend env xs)) ctor.indices))) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2277 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.decodeField_branches + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {constants : Model.Assignment β V} {levels : List Nat} {env : Nat → V} + {ctor : Certified.Ordinary.Constructor β} {i j : Nat} {field : Certified.Ordinary.RecursiveField β}, + shape.constructors[i]? = some ctor → + ctor.recursive[j]? = some field → + Certified.Ordinary.ConstructorEvidence entries shape ctor → + Model.Realizes constants entries → + Model.Context.Valid constants levels shape.parameterContext env → + ∀ {xs fs : List V}, + Model.SetTheory.Tower.FitsS (Model.Telescope.interpret constants levels env ctor.fields) xs → + shape.RecursiveValuesFit constants levels env ctor xs fs → + shape.decodeField constants levels env xs j field (shape.branches constants levels env ctor i xs fs) = + fs.getD j Model.SetTheory.empty + axioms: [propext, Classical.choice, Quot.sound] + constants: 1230 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.branches_decodeFields + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {constants : Model.Assignment β V} {levels : List Nat} {env : Nat → V} + {ctor : Certified.Ordinary.Constructor β} {i : Nat}, + shape.constructors[i]? = some ctor → + Certified.Ordinary.ConstructorEvidence entries shape ctor → + Model.Realizes constants entries → + Model.Context.Valid constants levels shape.parameterContext env → + ∀ {xs : List V}, + Model.SetTheory.Tower.FitsS (Model.Telescope.interpret constants levels env ctor.fields) xs → + ∀ {g : V}, + Model.SetTheory.Mem g + (Model.SetTheory.piSet + (shape.positions constants levels env + (Model.SetTheory.Tower.inj i (Model.SetTheory.Tower.mkTower xs))) + fun p => + Model.SetTheory.app (shape.carrier constants levels env) + (shape.targetIndex constants levels env + (Model.SetTheory.Tower.inj i (Model.SetTheory.Tower.mkTower xs)) p)) → + shape.branches constants levels env ctor i xs (shape.decodeFields constants levels env ctor xs g) = g + axioms: [propext, Classical.choice, Quot.sound] + constants: 1269 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.container_large + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β}, + Certified.Ordinary.LargeEvidence entries shape → + ∀ {constants : Model.Assignment β V}, + Model.Realizes constants entries → + ∀ {levels : List Nat} {env : Nat → V}, + Model.Context.Valid constants levels shape.parameterContext env → + (shape.container constants levels env).LargeElim (VLevel.eval levels shape.level) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1015 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.largeValue_iota + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} {store : Store β} + {source : β} {shape : Certified.Ordinary.Shape β} {constants : Model.Assignment β V} {levels : List Nat} + {env : Nat → V}, + Certified.Ordinary.CheckedShape entries store source shape → + Model.Realizes constants entries → + Model.Context.Valid constants levels shape.parameterContext env → + ∀ {v : Nat} {m : V} {minors : List V}, + Model.SetTheory.Mem m (shape.motiveSet constants levels env v) → + shape.MinorValuesFit constants levels env v m minors → + ∀ (hD : (shape.container constants levels env).WF (VLevel.eval levels shape.level)) + (hlarge : (shape.container constants levels env).LargeElim (VLevel.eval levels shape.level)) {i : Nat} + {ctor : Certified.Ordinary.Constructor β}, + shape.constructors[i]? = some ctor → + ∀ {xs fs : List V}, + Model.SetTheory.Tower.FitsS (Model.Telescope.interpret constants levels env ctor.fields) xs → + shape.RecursiveValuesFit constants levels env ctor xs fs → + Model.Telescope.applyN (shape.largeValue constants levels env v m minors hD hlarge) + (List.map (Model.interp constants levels (Model.Telescope.extend env xs)) ctor.indices ++ + [shape.constructorValue constants levels env ctor i xs fs]) = + Model.Telescope.applyN (minors.getD i Model.SetTheory.empty) + (xs ++ fs ++ shape.recursiveCalls constants levels env v m minors hD hlarge ctor xs fs) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2417 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.constructorType_interp + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {source : β} {constants reading : Model.Assignment β V} {levels : List Nat} + {store : Store β}, + Certified.Ordinary.CheckedShape entries store source shape → + Certified.Ordinary.FamilyReading entries shape source constants reading → + Model.Realizes constants entries → + levels.length = shape.universes → + ∀ {ctor : Certified.Ordinary.Constructor β}, + ctor ∈ shape.constructors → + Model.interp reading levels (fun x => Model.SetTheory.empty) (ctor.type shape source) = + shape.constructorSet constants levels ctor + axioms: [propext, Classical.choice, Quot.sound] + constants: 2309 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.recursorType_interp + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {source : β} {constants reading : Model.Assignment β V} {levels : List Nat} + {mode : Inductive.ElimMode} {store : Store β}, + Certified.Ordinary.CheckedShape entries store source shape → + Certified.Ordinary.ConstructorReading entries shape source constants reading → + Model.Realizes constants entries → + levels.length = mode.recUvars shape.universes → + Model.interp reading levels (fun x => Model.SetTheory.empty) (shape.recursorType source mode) = + shape.closedRecursorSet constants levels mode + axioms: [propext, Classical.choice, Quot.sound] + constants: 2719 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.closedRecursorValue_mem_source + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {source : β} {store : Store β} {constants : Model.Assignment β V} + {levels : List Nat} {mode : Inductive.ElimMode}, + Certified.Ordinary.CheckedShape entries store source shape → + ∀ {reading : Model.Assignment β V}, + Certified.Ordinary.ConstructorReading entries shape source constants reading → + Certified.Ordinary.ModeEvidence entries shape mode → + Model.Realizes constants entries → + levels.length = mode.recUvars shape.universes → + Model.SetTheory.Mem (shape.closedRecursorValue constants levels mode) + (Model.interp reading levels (fun x => Model.SetTheory.empty) (shape.recursorType source mode)) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2828 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.produced_rule_eq + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {source recursor : β} {constants : Model.Assignment β V} {levels : List Nat} + {mode : Inductive.ElimMode} [inst_1 : DecidableEq β] {store : Store β}, + Certified.Ordinary.CheckedShape entries store source shape → + entries.WF → + Certified.Ordinary.Shape.ConstructorFormation entries shape source → + Certified.Ordinary.Shape.RecursorFormation entries store shape source recursor mode → + Certified.Ordinary.ModeEvidence entries shape mode → + Model.Realizes constants entries → + levels.length = mode.recUvars shape.universes → + ∀ {i : Nat} {ctor : Certified.Ordinary.Constructor β}, + shape.constructors[i]? = some ctor → + Certified.Ordinary.Shape.RuleFormation (shape.recursorEnvironment entries source recursor mode) + shape source recursor mode i ctor → + ∀ (env : Nat → V), + Model.interp (shape.recursorAssignment constants source recursor mode) levels env + (shape.ruleLhs source recursor mode i ctor) = + Model.interp (shape.recursorAssignment constants source recursor mode) levels env + (shape.ruleRhs source recursor mode i ctor) + axioms: [propext, Classical.choice, Quot.sound] + constants: 3127 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.checkBlock_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} {store : Store β} + {witness : Certified.Ordinary.BlockWitness β} + {result : + Certified.CheckedClaim + (Certified.Ordinary.CheckedBlock entries store witness.source witness.recursor witness.shape.shape witness.mode)}, + Certified.Ordinary.checkBlock fuel entries store witness = some result → + Certified.Ordinary.CheckedBlock entries store witness.source witness.recursor witness.shape.shape witness.mode + axioms: [propext, Classical.choice, Quot.sound] + constants: 3074 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Ordinary.Shape.publishedAssignment_realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {V : Type v} [inst_1 : Model.SetTheory V] {entries : Model.Environment β} + {store : Store β} {source recursor : β} {shape : Certified.Ordinary.Shape β} {mode : Inductive.ElimMode}, + Certified.Ordinary.CheckedBlock entries store source recursor shape mode → + entries.WF → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → + Model.Realizes (shape.recursorAssignment constants source recursor mode) + (shape.publishedEnvironment entries source recursor mode) + axioms: [propext, Classical.choice, Quot.sound] + constants: 3172 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.admitOrdinary?_extends + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {state : Certified.AdmittedEnvironment signature store} + {witness : Certified.Ordinary.BlockWitness β} + {result : { result // Certified.Extends signature state.entries result.entries }}, + Certified.admitOrdinary? fuel state witness = some result → + Certified.Extends signature state.entries result.val.entries + axioms: [propext, Classical.choice, Quot.sound] + constants: 4207 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.ConversionClaim.proofIrrel + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {A a b : Model.AExpr β}, + Model.TypingClaim entries Γ A (Model.AExpr.sort VLevel.zero) → + Model.TypingClaim entries Γ a A → Model.TypingClaim entries Γ b A → Model.ConversionClaim entries Γ a b + axioms: [propext, Classical.choice, Quot.sound] + constants: 752 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Basis.Equality.Interface.of_checked + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} {source recursor : β}, + Certified.Ordinary.CheckedBlock entries store source recursor Certified.Basis.Equality.shape + Inductive.ElimMode.large → + Certified.Basis.Equality.Interface + (Certified.Basis.Equality.shape.publishedEnvironment entries source recursor Inductive.ElimMode.large) + (ConstRef.member source 0) (ConstRef.ctor source 0 0) (ConstRef.member recursor 0) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2010 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Basis.Equality.value_eq_eqv + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {family refl recursor : ConstRef β} {constants : Model.Assignment β V}, + Certified.Basis.Equality.Interface entries family refl recursor → + Model.Realizes constants entries → + ∀ {u : Nat} {A a b : V}, + Model.SetTheory.Mem A (Model.SetTheory.univ u) → + Model.SetTheory.Mem a A → + Model.SetTheory.Mem b A → Certified.Basis.Equality.value constants family u A a b = Model.SetTheory.eqv a b + axioms: [propext, Classical.choice, Quot.sound] + constants: 1106 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Basis.Iff.Interface.of_checked + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} {source recursor : β}, + Certified.Ordinary.CheckedBlock entries store source recursor Certified.Basis.Iff.shape Inductive.ElimMode.large → + Certified.Basis.Iff.Interface + (Certified.Basis.Iff.shape.publishedEnvironment entries source recursor Inductive.ElimMode.large) + (ConstRef.member source 0) (ConstRef.ctor source 0 0) (ConstRef.member recursor 0) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2012 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Basis.Iff.eq_of_mem + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {family ctor recursor : ConstRef β} {constants : Model.Assignment β V}, + Certified.Basis.Iff.Interface entries family ctor recursor → + Model.Realizes constants entries → + ∀ {P Q proof : V}, + Model.SetTheory.Mem P Model.SetTheory.univZero → + Model.SetTheory.Mem Q Model.SetTheory.univZero → + Model.SetTheory.Mem proof (Certified.Basis.Iff.value constants family P Q) → P = Q + axioms: [propext, Classical.choice, Quot.sound] + constants: 1109 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Basis.Nonempty.Interface.of_checked + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} {source recursor : β}, + Certified.Ordinary.CheckedBlock entries store source recursor Certified.Basis.Nonempty.shape + Inductive.ElimMode.small → + Certified.Basis.Nonempty.Interface + (Certified.Basis.Nonempty.shape.publishedEnvironment entries source recursor Inductive.ElimMode.small) + (ConstRef.member source 0) (ConstRef.ctor source 0 0) (ConstRef.member recursor 0) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2011 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Basis.Nonempty.value_eq_truthVal + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {family ctor recursor : ConstRef β} {constants : Model.Assignment β V}, + Certified.Basis.Nonempty.Interface entries family ctor recursor → + Model.Realizes constants entries → + ∀ {u : Nat} {A : V}, + Model.SetTheory.Mem A (Model.SetTheory.univ u) → + Certified.Basis.Nonempty.value constants family u A = Model.SetTheory.truthVal (∃ a, Model.SetTheory.Mem a A) + axioms: [propext, Classical.choice, Quot.sound] + constants: 921 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Standard.Spec.value_mem + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {constants : Model.Assignment β V} (spec : Certified.Standard.Spec β), + Certified.Standard.Spec.Prerequisites entries spec → + Model.Realizes constants entries → + ∀ (levels : List Nat), + levels.length = spec.universes → + ∀ (env : Nat → V), + Model.SetTheory.Mem (spec.value constants levels) (Model.interp constants levels env spec.type) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1197 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Standard.check_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} {store : Store β} + {witness : Certified.Standard.Witness β} + {result : Certified.CheckedClaim (Certified.Standard.Checked entries store witness)}, + Certified.Standard.check fuel entries store witness = some result → Certified.Standard.Checked entries store witness + axioms: [propext, Classical.choice, Quot.sound] + constants: 2833 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Standard.assignment_realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} + {witness : Certified.Standard.Witness β} {V : Type v} [inst_1 : Model.SetTheory V], + Certified.Standard.Checked entries store witness → + entries.WF → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → + Model.Realizes (Certified.Standard.assignment constants witness) + (entries.insert witness.ref witness.spec.entry) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1407 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.admitStandard?_extends + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {state : Certified.AdmittedEnvironment signature store} {witness : Certified.Standard.Witness β} + {result : { result // Certified.Extends signature state.entries result.entries }}, + Certified.admitStandard? fuel state witness = some result → + Certified.Extends signature state.entries result.val.entries + axioms: [propext, Classical.choice, Quot.sound] + constants: 3332 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.SetTheory.quotSet_mem_univ + type: ∀ {V : Type u} [inst : Model.SetTheory V] {u : Nat} {A R : V}, + Model.SetTheory.Mem A (Model.SetTheory.univ u) → + Model.SetTheory.Mem (Model.SetTheory.quotSet u A R) (Model.SetTheory.univ u) + axioms: [propext, Classical.choice, Quot.sound] + constants: 225 + project modules: [Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.SetTheory.quotSound + type: ∀ {V : Type u} [inst : Model.SetTheory V] {u : Nat} {A R a b w : V}, + Model.SetTheory.Mem a A → + Model.SetTheory.Mem b A → + Model.SetTheory.Mem w (Model.SetTheory.app (Model.SetTheory.app R a) b) → + Model.SetTheory.quotClass u A R a = Model.SetTheory.quotClass u A R b + axioms: [propext, Classical.choice, Quot.sound] + constants: 205 + project modules: [Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep] +certified root Ix.Theory.Certified.Signature.checkTypes_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} + {headers : List (Certified.Signature.Header β)} {witnesses : List (Certified.Signature.TypeWitness β)} + {result : Certified.CheckedClaim (Certified.Signature.Formed entries headers)}, + Certified.Signature.checkTypes fuel entries headers witnesses = some result → + Certified.Signature.Formed entries headers + axioms: [propext, Classical.choice, Quot.sound] + constants: 2581 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Signature.Formed.realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {V : Type v} [inst_1 : Model.SetTheory V] {entries : Model.Environment β} + {headers : List (Certified.Signature.Header β)}, + Certified.Signature.Formed entries headers → + ∀ {constants : Model.Assignment β V}, + Model.Realizes constants entries → + (∀ (header : Certified.Signature.Header β), + header ∈ headers → + ∀ (levels : List Nat), + levels.length = header.universes → + ∀ (env : Nat → V), + Model.SetTheory.Mem (constants header.ref levels) (Model.interp constants levels env header.type)) → + Model.Realizes constants (Certified.Signature.environment entries headers) + axioms: [propext, Classical.choice, Quot.sound] + constants: 901 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Quotient.value_mem + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} + {refs : Certified.Quotient.Refs β} {entries : Model.Environment β}, + Certified.Quotient.Reading constants refs → + Certified.Basis.Equality.Interface entries refs.eq refs.eqRefl refs.eqRec → + Model.Realizes constants entries → + ∀ (kind : Certified.Quotient.Kind) (levels : List Nat), + levels.length = kind.universes → + ∀ (env : Nat → V), + Model.SetTheory.Mem (constants (refs.ref kind) levels) + (Model.interp constants levels env (refs.entryType kind)) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1236 + project modules: [Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Quotient.liftValue_apply + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {constants : Model.Assignment β V} {eq refl recursor : ConstRef β}, + Certified.Basis.Equality.Interface entries eq refl recursor → + Model.Realizes constants entries → + ∀ {u v : Nat} {A R B f h a : V}, + Model.SetTheory.Mem A (Model.SetTheory.univ u) → + Model.SetTheory.Mem R (Certified.Quotient.relationSet A) → + Model.SetTheory.Mem B (Model.SetTheory.univ v) → + Model.SetTheory.Mem f (Model.SetModel.piR (Certified.Quotient.bit v) A fun x => B) → + Model.SetTheory.Mem h (Certified.Quotient.invariantSet constants eq v A R B f) → + Model.SetTheory.Mem a A → + Model.SetTheory.app + (Model.SetTheory.app + (Model.SetTheory.app + (Model.SetTheory.app + (Model.SetTheory.app + (Model.SetTheory.app (Certified.Quotient.liftValue constants eq u v) A) R) + B) + f) + h) + (Model.SetTheory.quotClass u A R a) = + Model.SetTheory.app f a + axioms: [propext, Classical.choice, Quot.sound] + constants: 1132 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Quotient.liftRule_eq + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} + {refs : Certified.Quotient.Refs β} {entries : Model.Environment β}, + Certified.Quotient.Reading constants refs → + Certified.Basis.Equality.Interface entries refs.eq refs.eqRefl refs.eqRec → + Model.Realizes constants entries → + ∀ (u v : Nat) (env : Nat → V), + Model.interp constants [u, v] env (Certified.Quotient.liftRuleLhs refs) = + Model.interp constants [u, v] env (Certified.Quotient.liftRuleRhs refs) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1182 + project modules: [Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Quotient.check_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} {store : Store β} + {witness : Certified.Quotient.Witness β} + {result : Certified.CheckedClaim (Certified.Quotient.Checked entries store witness.refs)}, + Certified.Quotient.check fuel entries store witness = some result → + Certified.Quotient.Checked entries store witness.refs + axioms: [propext, Classical.choice, Quot.sound] + constants: 2895 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Quotient.assignment_realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} + {refs : Certified.Quotient.Refs β} {V : Type v} [inst_1 : Model.SetTheory V], + Certified.Quotient.Checked entries store refs → + entries.WF → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → Model.Realizes (refs.assignment constants) (refs.environment entries) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1556 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.admitQuotient?_extends + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {state : Certified.AdmittedEnvironment signature store} {witness : Certified.Quotient.Witness β} + {result : { result // Certified.Extends signature state.entries result.entries }}, + Certified.admitQuotient? fuel state witness = some result → + Certified.Extends signature state.entries result.val.entries + axioms: [propext, Classical.choice, Quot.sound] + constants: 3463 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.TypingClaim.fact + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {r : ConstRef β} + {entry : Model.ConstantEntry β} {e A : Model.AExpr β} {ls : List VLevel}, + entries r = some entry → + Model.ConstantFact.typed e A ∈ entry.facts → + ls.length = entry.universes → Model.TypingClaim entries Γ (Model.AExpr.instL ls e) (Model.AExpr.instL ls A) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1904 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.TypingClaim.natLit + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {r zero succ : ConstRef β} + {entry : Model.ConstantEntry β}, + entries r = some entry → + Model.ConstantFact.natural zero succ ∈ entry.facts → + entry.universes = 0 → + ∀ (value : Nat), Model.TypingClaim entries Γ (Model.AExpr.natLit value) (Model.AExpr.const r []) + axioms: [propext, Classical.choice, Quot.sound] + constants: 741 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.TypingClaim.betaResult + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {p : Certified.PropWhen} + {D body arg B : Model.AExpr β}, + Model.TypingClaim entries Γ (Model.AExpr.lam p D body) (Model.AExpr.forallE p D B) → + Model.TypingClaim entries Γ arg D → Model.TypingClaim entries Γ (body.inst arg) (B.inst arg) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1731 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.ConversionClaim.natZero + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {r zero succ : ConstRef β} + {entry : Model.ConstantEntry β}, + entries r = some entry → + Model.ConstantFact.natural zero succ ∈ entry.facts → + entry.universes = 0 → Model.ConversionClaim entries Γ (Model.AExpr.natLit 0) (Model.AExpr.const zero []) + axioms: [propext, Classical.choice, Quot.sound] + constants: 741 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.ConversionClaim.natSucc + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {r zero succ : ConstRef β} + {entry : Model.ConstantEntry β}, + entries r = some entry → + Model.ConstantFact.natural zero succ ∈ entry.facts → + entry.universes = 0 → + ∀ (value : Nat), + Model.ConversionClaim entries Γ (Model.AExpr.natLit (value + 1)) + ((Model.AExpr.const succ []).app (Model.AExpr.natLit value)) + axioms: [propext, Classical.choice, Quot.sound] + constants: 741 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.ConversionClaim.proj + type: ∀ {β : Type u} {entries : Model.Environment β} {Γ : Model.Context β} {r : ConstRef β} {i : Nat} + {a b : Model.AExpr β}, + Model.ConversionClaim entries Γ a b → + Model.ConversionClaim entries Γ (Model.AExpr.proj r i a) (Model.AExpr.proj r i b) + axioms: [propext, Classical.choice, Quot.sound] + constants: 739 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Structure.Description.projections_fit + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {d : Certified.Structure.Description β} + {constants : Model.Assignment β V} {levels : List Nat} {env : Nat → V} {entries : Model.Environment β} + {store : Store β} {source : β}, + Certified.Ordinary.CheckedShape entries store source d.ordinary → + Certified.Structure.FieldsFormed entries d.level d.ordinary.parameterContext d.fields → + Model.Realizes constants entries → + Model.Context.Valid constants levels d.ordinary.parameterContext env → + ∀ {x : V}, + Model.SetTheory.Mem x (Model.SetTheory.app (d.ordinary.carrier constants levels env) Model.SetTheory.pt) → + Model.SetTheory.Tower.FitsS (Model.Telescope.interpret constants levels env d.constructor.fields) + (Certified.Structure.projectValues d.fields.length x) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2282 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.Description.constructor_eta + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {d : Certified.Structure.Description β} + {constants : Model.Assignment β V} {levels : List Nat} {env : Nat → V} {entries : Model.Environment β} + {store : Store β} {source : β}, + Certified.Ordinary.CheckedShape entries store source d.ordinary → + Model.Realizes constants entries → + Model.Context.Valid constants levels d.ordinary.parameterContext env → + ∀ {x : V}, + Model.SetTheory.Mem x (Model.SetTheory.app (d.ordinary.carrier constants levels env) Model.SetTheory.pt) → + d.ordinary.constructorValue constants levels env d.constructor 0 + (Certified.Structure.projectValues d.fields.length x) [] = + x + axioms: [propext, Classical.choice, Quot.sound] + constants: 2270 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.Description.constructor_iota + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {d : Certified.Structure.Description β} + {constants : Model.Assignment β V} {levels : List Nat} {env : Nat → V} {entries : Model.Environment β}, + Certified.Structure.FieldsFormed entries d.level d.ordinary.parameterContext d.fields → + Model.Realizes constants entries → + Model.Context.Valid constants levels d.ordinary.parameterContext env → + ∀ {xs : List V}, + Model.SetTheory.Tower.FitsS (Model.Telescope.interpret constants levels env d.constructor.fields) xs → + Certified.Structure.projectValues d.fields.length + (d.ordinary.constructorValue constants levels env d.constructor 0 xs []) = + xs + axioms: [propext, Classical.choice, Quot.sound] + constants: 1113 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.Description.projection_meaning + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {d : Certified.Structure.Description β} + {entries : Model.Environment β} {store : Store β} {source : β} {constants reading : Model.Assignment β V} + {levels : List Nat}, + Certified.Ordinary.CheckedShape entries store source d.ordinary → + Certified.Structure.FieldsFormed entries d.level d.ordinary.parameterContext d.fields → + Certified.Ordinary.FamilyReading entries d.ordinary source constants reading → + Model.Realizes constants entries → + levels.length = d.universes → + ∀ {stage : Model.Environment β}, + Model.Realizes reading stage → + Model.Telescope.Formed stage [] (d.projectionDomains source) → + ∀ {i : Nat} {field : Certified.Structure.Field β}, + d.fields[i]? = some field → + Model.AExpr.Scope d.universes 0 (d.projection source i field) ∧ + Model.AExpr.Scope d.universes 0 (d.projectionType source i field) → + ∀ (env : Nat → V), + Model.ConstantFact.Meaning reading (ConstRef.member source 0) levels env + (Model.ConstantFact.typed (d.projection source i field) (d.projectionType source i field)) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2669 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.Description.eta_eq + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {d : Certified.Structure.Description β} + {entries : Model.Environment β} {store : Store β} {source : β} {constants reading : Model.Assignment β V} + {levels : List Nat}, + Certified.Ordinary.CheckedShape entries store source d.ordinary → + Certified.Structure.FieldsFormed entries d.level d.ordinary.parameterContext d.fields → + Certified.Ordinary.ConstructorReading entries d.ordinary source constants reading → + Model.Realizes constants entries → + levels.length = d.universes → + Model.interp reading levels (fun x => Model.SetTheory.empty) (d.etaLhs source) = + Model.interp reading levels (fun x => Model.SetTheory.empty) (d.etaRhs source) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2437 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.Description.iota_eq + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {d : Certified.Structure.Description β} + {entries : Model.Environment β} {store : Store β} {source : β} {constants reading : Model.Assignment β V} + {levels : List Nat}, + Certified.Ordinary.CheckedShape entries store source d.ordinary → + Certified.Structure.FieldsFormed entries d.level d.ordinary.parameterContext d.fields → + Certified.Ordinary.ConstructorReading entries d.ordinary source constants reading → + Model.Realizes constants entries → + levels.length = d.universes → + ∀ {i : Nat} {field : Certified.Structure.Field β}, + d.fields[i]? = some field → + Model.interp reading levels (fun x => Model.SetTheory.empty) (d.iotaLhs source i field) = + Model.interp reading levels (fun x => Model.SetTheory.empty) (d.iotaRhs i field) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2431 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.check_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} {store : Store β} + {witness : Certified.Structure.Witness β} + {result : + Certified.CheckedClaim + (Certified.Structure.Checked entries store witness.facts.description witness.facts.block.source + witness.facts.block.recursor witness.facts.block.mode)}, + Certified.Structure.check fuel entries store witness = some result → + Certified.Structure.Checked entries store witness.facts.description witness.facts.block.source + witness.facts.block.recursor witness.facts.block.mode + axioms: [propext, Classical.choice, Quot.sound] + constants: 3205 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.Description.factAssignment_realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {d : Certified.Structure.Description β} {entries : Model.Environment β} + {store : Store β} {source recursor : β} {mode : Inductive.ElimMode} {V : Type v} [inst_1 : Model.SetTheory V], + Certified.Structure.FactsChecked entries store d source recursor mode → + entries.WF → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → + Model.Realizes (d.ordinary.recursorAssignment constants source recursor mode) + (d.factEnvironment entries source recursor mode) + axioms: [propext, Classical.choice, Quot.sound] + constants: 3279 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Structure.Description.publishedAssignment_realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {d : Certified.Structure.Description β} {entries : Model.Environment β} + {store : Store β} {source recursor : β} {mode : Inductive.ElimMode} {V : Type v} [inst_1 : Model.SetTheory V], + Certified.Structure.Checked entries store d source recursor mode → + entries.WF → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → + Model.Realizes (d.ordinary.recursorAssignment constants source recursor mode) + (d.publishedEnvironment entries source recursor mode) + axioms: [propext, Classical.choice, Quot.sound] + constants: 3312 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.admitStructure?_extends + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {state : Certified.AdmittedEnvironment signature store} {witness : Certified.Structure.Witness β} + {result : { result // Certified.Extends signature state.entries result.entries }}, + Certified.admitStructure? fuel state witness = some result → + Certified.Extends signature state.entries result.val.entries + axioms: [propext, Classical.choice, Quot.sound] + constants: 4377 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Natural.value_mem + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} + {entries : Model.Environment β} {store : Store β} {source : β}, + Certified.Ordinary.CheckedShape entries store source Certified.Natural.shape → + Model.Realizes constants entries → + ∀ (n : Nat), Model.SetTheory.Mem (Model.Numeral.value n) (Certified.Natural.shape.familyValue constants []) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2299 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Natural.meaning + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} + {entries : Model.Environment β} {store : Store β} {source : β}, + Certified.Ordinary.CheckedShape entries store source Certified.Natural.shape → + ∀ {reading : Model.Assignment β V}, + Certified.Ordinary.ConstructorReading entries Certified.Natural.shape source constants reading → + Model.Realizes constants entries → + Model.NaturalMeaning reading (ConstRef.member source 0) (ConstRef.ctor source 0 0) (ConstRef.ctor source 0 1) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2324 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Natural.check_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} {store : Store β} + {pin : ConstRef β} {witness : Certified.Ordinary.BlockWitness β} + {result : + Certified.CheckedClaim (Certified.Natural.Checked entries store pin witness.source witness.recursor witness.mode)}, + Certified.Natural.check fuel entries store pin witness = some result → + Certified.Natural.Checked entries store pin witness.source witness.recursor witness.mode + axioms: [propext, Classical.choice, Quot.sound] + constants: 3124 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Natural.assignment_realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} {pin : ConstRef β} + {source recursor : β} {mode : Inductive.ElimMode} {V : Type v} [inst_1 : Model.SetTheory V], + Certified.Natural.Checked entries store pin source recursor mode → + entries.WF → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → + Model.Realizes (Certified.Natural.shape.recursorAssignment constants source recursor mode) + (Certified.Natural.environment entries source recursor mode) + axioms: [propext, Classical.choice, Quot.sound] + constants: 3196 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.admitNatural?_extends + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {state : Certified.AdmittedEnvironment signature store} + {witness : Certified.Ordinary.BlockWitness β} + {result : { result // Certified.Extends signature state.entries result.entries }}, + Certified.admitNatural? fuel state witness = some result → + Certified.Extends signature state.entries result.val.entries + axioms: [propext, Classical.choice, Quot.sound] + constants: 4275 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Model.interp_mapRefs + type: ∀ {β : Type u} {γ : Type v} {V : Type x} [inst : Model.SetTheory V] (e : Model.AExpr β) + (mapping : ConstRef β → ConstRef γ) (constants : Model.Assignment γ V) (levels : List Nat) (env : Nat → V), + Model.interp constants levels env (Model.AExpr.mapRefs mapping e) = + Model.interp (fun ref values => constants (mapping ref) values) levels env e + axioms: [propext, Classical.choice, Quot.sound] + constants: 721 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.wellDenoted_mapRefs + type: ∀ {β : Type u} {γ : Type v} {V : Type x} [inst : Model.SetTheory V] (e : Model.AExpr β) + (mapping : ConstRef β → ConstRef γ) (constants : Model.Assignment γ V) (levels : List Nat) (env : Nat → V), + Model.WellDenoted constants levels env (Model.AExpr.mapRefs mapping e) ↔ + Model.WellDenoted (fun ref values => constants (mapping ref) values) levels env e + axioms: [propext, Classical.choice, Quot.sound] + constants: 736 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.AExpr.mapRefs_restore + type: ∀ {β : Type u} {γ : Type v} (e : Model.AExpr β) (forward : ConstRef β → ConstRef γ) + (backward : ConstRef γ → ConstRef β), + (∀ (ref : ConstRef β), ref ∈ e.references → backward (forward ref) = ref) → + Model.AExpr.mapRefs backward (Model.AExpr.mapRefs forward e) = e + axioms: [propext] + constants: 169 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Support] +certified root Ix.Theory.Model.interp_mapRefs_restore + type: ∀ {β : Type u} {γ : Type v} {V : Type x} [inst : Model.SetTheory V] (e : Model.AExpr β) + (forward : ConstRef β → ConstRef γ) (backward : ConstRef γ → ConstRef β) (constants : Model.Assignment β V), + (∀ (ref : ConstRef β), ref ∈ e.references → backward (forward ref) = ref) → + ∀ (levels : List Nat) (env : Nat → V), + Model.interp constants levels env (Model.AExpr.mapRefs backward (Model.AExpr.mapRefs forward e)) = + Model.interp constants levels env e + axioms: [propext, Classical.choice, Quot.sound] + constants: 759 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.interp_mapRefs_permutation + type: ∀ {β : Type u} {γ : Type v} {V : Type x} [inst : Model.SetTheory V] (e : Model.AExpr β) + (forward : ConstRef β → ConstRef γ) (backward : ConstRef γ → ConstRef β) (constants : Model.Assignment β V), + (∀ (ref : ConstRef β), ref ∈ e.references → backward (forward ref) = ref) → + ∀ (levels : List Nat) (env : Nat → V), + Model.interp (fun ref values => constants (backward ref) values) levels env (Model.AExpr.mapRefs forward e) = + Model.interp constants levels env e + axioms: [propext, Classical.choice, Quot.sound] + constants: 755 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.wellDenoted_mapRefs_permutation + type: ∀ {β : Type u} {γ : Type v} {V : Type x} [inst : Model.SetTheory V] (e : Model.AExpr β) + (forward : ConstRef β → ConstRef γ) (backward : ConstRef γ → ConstRef β) (constants : Model.Assignment β V), + (∀ (ref : ConstRef β), ref ∈ e.references → backward (forward ref) = ref) → + ∀ (levels : List Nat) (env : Nat → V), + Model.WellDenoted (fun ref values => constants (backward ref) values) levels env (Model.AExpr.mapRefs forward e) ↔ + Model.WellDenoted constants levels env e + axioms: [propext, Classical.choice, Quot.sound] + constants: 771 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.interp_mapRefs_merge + type: ∀ {β : Type u} {γ : Type v} {V : Type x} [inst : Model.SetTheory V] (e : Model.AExpr β) + (before : Model.Assignment β V) (after : Model.Assignment γ V) (mapping : ConstRef β → ConstRef γ), + (∀ (ref : ConstRef β), ref ∈ e.references → ∀ (levels : List Nat), before ref levels = after (mapping ref) levels) → + ∀ (levels : List Nat) (env : Nat → V), + Model.interp before levels env e = Model.interp after levels env (Model.AExpr.mapRefs mapping e) + axioms: [propext, Classical.choice, Quot.sound] + constants: 755 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Model.wellDenoted_mapRefs_merge + type: ∀ {β : Type u} {γ : Type v} {V : Type x} [inst : Model.SetTheory V] (e : Model.AExpr β) + (before : Model.Assignment β V) (after : Model.Assignment γ V) (mapping : ConstRef β → ConstRef γ), + (∀ (ref : ConstRef β), ref ∈ e.references → ∀ (levels : List Nat), before ref levels = after (mapping ref) levels) → + ∀ (levels : List Nat) (env : Nat → V), + Model.WellDenoted before levels env e ↔ Model.WellDenoted after levels env (Model.AExpr.mapRefs mapping e) + axioms: [propext, Classical.choice, Quot.sound] + constants: 771 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Modeled.propositional_equation + type: ∀ {β : Type u} {entries : Model.Environment β} {family reflexivity recursor : ConstRef β}, + Certified.Basis.Equality.Interface entries family reflexivity recursor → + ∀ {rule : Certified.Signature.Rule β} {level : VLevel} {proof : Model.AExpr β}, + Model.TypingClaim entries [] rule.type (Model.AExpr.sort level) → + Model.TypingClaim entries [] rule.lhs rule.type → + Model.TypingClaim entries [] rule.rhs rule.type → + Model.TypingClaim entries [] proof + (Certified.Basis.Equality.applied family level rule.type rule.lhs rule.rhs) → + Model.ConversionClaim entries [] rule.lhs rule.rhs + axioms: [propext, Classical.choice, Quot.sound] + constants: 1115 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Modeled.checkEquation?_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} + {rule : Certified.Signature.Rule β} {witness : Certified.Modeled.EquationWitness β} + {result : Certified.CheckedClaim (Certified.Modeled.CheckedEquation entries rule)}, + Certified.Modeled.checkEquation? fuel entries rule witness = some result → + Certified.Modeled.CheckedEquation entries rule + axioms: [propext, Classical.choice, Quot.sound] + constants: 2631 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Modeled.CheckedCompanions.fixed_old + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} + {companions : List (Certified.Modeled.Companion β)}, + Certified.Modeled.CheckedCompanions entries companions → + ∀ {ref : ConstRef β} {entry : Model.ConstantEntry β}, + entries ref = some entry → Certified.Modeled.mapping companions ref = ref + axioms: [propext, Classical.choice, Quot.sound] + constants: 834 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Modeled.environment_wf + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} + {companions : List (Certified.Modeled.Companion β)}, + Certified.Modeled.CheckedCompanions entries companions → + entries.WF → (Certified.Modeled.environment entries companions).WF + axioms: [propext, Classical.choice, Quot.sound] + constants: 913 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Modeled.assignment_agrees + type: ∀ {β : Type u} [inst : DecidableEq β] {V : Type v} {entries : Model.Environment β} + {companions : List (Certified.Modeled.Companion β)}, + Certified.Modeled.CheckedCompanions entries companions → + ∀ (constants : Model.Assignment β V), + Model.Assignment.AgreesOn entries constants (Certified.Modeled.assignment constants companions) + axioms: [propext, Classical.choice, Quot.sound] + constants: 837 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Modeled.assignment_realizes + type: ∀ {β : Type u} [inst : DecidableEq β] {V : Type v} [inst_1 : Model.SetTheory V] {entries : Model.Environment β} + {companions : List (Certified.Modeled.Companion β)}, + Certified.Modeled.CheckedCompanions entries companions → + entries.WF → + ∀ (constants : Model.Assignment β V), + Model.Realizes constants entries → + Model.Realizes (Certified.Modeled.assignment constants companions) + (Certified.Modeled.environment entries companions) + axioms: [propext, Classical.choice, Quot.sound] + constants: 1030 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.Modeled.check?_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {entries : Model.Environment β} {store : Store β} + {witness : Certified.Modeled.Witness β} + {result : Certified.CheckedClaim (Certified.Modeled.Checked entries store witness)}, + Certified.Modeled.check? fuel entries store witness = some result → Certified.Modeled.Checked entries store witness + axioms: [propext, Classical.choice, Quot.sound] + constants: 2947 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.Modeled.EntrySource.not_axiom + type: ∀ {β : Type u} {store : Store β} {ref : ConstRef β} {entry : Model.ConstantEntry β}, + Certified.Modeled.EntrySource store ref entry → + ∀ {n : Nat} {type : VExpr β} {safety : Safety}, store.lookup ref = some (Const.axiom n type safety) → False + axioms: [propext] + constants: 964 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport] +certified root Ix.Theory.Certified.Modeled.EntrySource.header + type: ∀ {β : Type u} {store : Store β} {ref : ConstRef β} {entry : Model.ConstantEntry β}, + Certified.Modeled.EntrySource store ref entry → Certified.SourceHeader store ref entry + axioms: [propext] + constants: 968 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport] +certified root Ix.Theory.Certified.checkModeledExtension? + type: {β : Type u} → + [DecidableEq β] → + Nat → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (state : Certified.CheckedInterface signature) → + Certified.Modeled.Witness β → Option (Certified.CheckedExtension signature store state) + axioms: [propext, Classical.choice, Quot.sound] + constants: 3257 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.admitModeled?_extends + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {state : Certified.AdmittedEnvironment signature store} {witness : Certified.Modeled.Witness β} + {result : { result // Certified.Extends signature state.entries result.entries }}, + Certified.admitModeled? fuel state witness = some result → + Certified.Extends signature state.entries result.val.entries + axioms: [propext, Classical.choice, Quot.sound] + constants: 3277 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.PrimitiveSignature.compatible_assignment + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] (signature : Certified.PrimitiveSignature β) + [inst_1 : DecidableEq β], signature.Compatible signature.environment signature.assignment + axioms: [propext, Classical.choice, Quot.sound] + constants: 2006 + project modules: [Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.checkTypeCertified_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel n : Nat} {entries : Model.Environment β} {Γ : Model.Context β} + {e A : Model.AExpr β} {witness : Certified.TypingWitness β}, + Certified.checkTypeCertified fuel n entries Γ e A witness = true → Model.TypingClaim entries Γ e A + axioms: [propext, Classical.choice, Quot.sound] + constants: 2553 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.defeqCertified_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel n : Nat} {entries : Model.Environment β} {Γ : Model.Context β} + {a b : Model.AExpr β} {witness : Certified.ConversionWitness β}, + Certified.defeqCertified fuel n entries Γ a b witness = true → Model.ConversionClaim entries Γ a b + axioms: [propext, Classical.choice, Quot.sound] + constants: 2553 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.inferCertified_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel n : Nat} {entries : Model.Environment β} {Γ : Model.Context β} + {source : VExpr β} {witness : Certified.InferenceWitness β} {result : Certified.InferenceResult entries n Γ source}, + Certified.inferCertified fuel n entries Γ source witness = some result → + result.reading.val.erase = source ∧ + Model.AExpr.Scope n (List.length Γ) result.type ∧ Model.TypingClaim entries Γ result.reading.val result.type + axioms: [propext, Classical.choice, Quot.sound] + constants: 2610 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Operations, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.whnfCertified_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel n : Nat} {entries : Model.Environment β} {Γ : Model.Context β} + {source : VExpr β} {witness : Certified.WhnfWitness β} {result : Certified.WhnfResult entries n Γ source}, + Certified.whnfCertified fuel n entries Γ source witness = some result → + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + Model.Realizes constants entries → + ∀ (levels : List Nat) (env : Nat → V), + Model.Context.Valid constants levels Γ env → + result.input.reading.val.erase = source ∧ + Certified.whnfShape entries result.result = true ∧ + Model.WellDenoted constants levels env result.input.reading.val ∧ + Model.WellDenoted constants levels env result.result ∧ + Model.interp constants levels env result.input.reading.val = + Model.interp constants levels env result.result + axioms: [propext, Classical.choice, Quot.sound] + constants: 2632 + project modules: [Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Operations, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.admitDefinition?_extends + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {state : Certified.AdmittedEnvironment signature store} {witness : Certified.DefinitionWitness β} + {result : { result // Certified.Extends signature state.entries result.entries }}, + Certified.admitDefinition? fuel state witness = some result → + Certified.Extends signature state.entries result.val.entries + axioms: [propext, Classical.choice, Quot.sound] + constants: 3145 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.checkStoreCertified + type: {β : Type u} → + [DecidableEq β] → + Nat → + (signature : Certified.PrimitiveSignature β) → + (store : Store β) → + (targets : List (ConstRef β)) → + List (Certified.DeclarationWitness β) → Option (Certified.CheckedStore signature store targets) + axioms: [propext, Classical.choice, Quot.sound] + constants: 4954 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Store, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.accepted_store_has_model + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {targets : List (ConstRef β)} {witness : List (Certified.DeclarationWitness β)}, + Certified.acceptsStoreCertified fuel signature store targets witness = true → + ∀ (V : Type v) [inst_1 : Model.SetTheory V], + ∃ result, + Certified.checkStoreCertified fuel signature store targets witness = some result ∧ + ∃ constants, + signature.Compatible result.environment.entries constants ∧ + ∀ (r : ConstRef β), + r ∈ targets → + ∃ entry, + result.environment.entries r = some entry ∧ + Certified.EntrySource signature store r entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Model.WellDenoted constants levels env entry.type ∧ + Model.SetTheory.Mem (constants r levels) (Model.interp constants levels env entry.type) + axioms: [propext, Classical.choice, Quot.sound] + constants: 4958 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Store, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.EntrySource.header + type: ∀ {β : Type u} {signature : Certified.PrimitiveSignature β} {store : Store β} {ref : ConstRef β} + {entry : Model.ConstantEntry β}, + Certified.EntrySource signature store ref entry → Certified.SourceHeader store ref entry + axioms: [propext, Quot.sound] + constants: 2123 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Instantiation, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope] +certified root Ix.Theory.Certified.CheckedStore.subject_sound + type: ∀ {β : Type u} {signature : Certified.PrimitiveSignature β} {store : Store β} {subjects : List (ConstRef β)} + (result : Certified.CheckedStore signature store subjects) {ref : ConstRef β}, + ref ∈ subjects → + ∃ entry, + result.environment.entries ref = some entry ∧ + Certified.SourceHeader store ref entry ∧ + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + signature.Compatible result.environment.entries constants → + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Model.WellDenoted constants levels env entry.type ∧ + Model.SetTheory.Mem (constants ref levels) (Model.interp constants levels env entry.type) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2252 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Store, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.accepted_store_source_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {subjects : List (ConstRef β)} {witness : List (Certified.DeclarationWitness β)}, + Certified.acceptsStoreCertified fuel signature store subjects witness = true → + ∀ (V : Type v) [inst_1 : Model.SetTheory V], + ∃ result, + Certified.checkStoreCertified fuel signature store subjects witness = some result ∧ + ∃ constants, + signature.Compatible result.environment.entries constants ∧ + ∀ (ref : ConstRef β), + ref ∈ subjects → + ∃ entry, + result.environment.entries ref = some entry ∧ + Certified.SourceHeader store ref entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Model.WellDenoted constants levels env entry.type ∧ + Model.SetTheory.Mem (constants ref levels) + (Model.interp constants levels env entry.type) + axioms: [propext, Classical.choice, Quot.sound] + constants: 4976 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Store, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.checkDeclarationExtensions? + type: {β : Type u} → + [DecidableEq β] → + Nat → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (state : Certified.CheckedInterface signature) → + List (Certified.DeclarationWitness β) → Option (Certified.CheckedExtension signature store state) + axioms: [propext, Classical.choice, Quot.sound] + constants: 4897 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedExtension.admit + type: {β : Type u} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (state : Certified.AdmittedEnvironment signature store) → + Certified.CheckedExtension signature store state.interface → + { result // Certified.Extends signature state.entries result.entries } + axioms: [propext, Classical.choice, Quot.sound] + constants: 2246 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.checkFrontier?_refs + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {witnesses : List (Certified.FrontierWitness β)} + {result : Certified.CheckedFrontier signature store}, + Certified.checkFrontier? fuel signature store witnesses = some result → + result.refs = List.map (fun x => x.ref) witnesses + axioms: [propext, Classical.choice, Quot.sound] + constants: 2912 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedFrontier.compatible + type: ∀ {β : Type u} [inst : DecidableEq β] {signature : Certified.PrimitiveSignature β} {store : Store β} + (frontier : Certified.CheckedFrontier signature store) (provider : Certified.CheckedInterface signature), + (∀ (header : Certified.Signature.Header β), + header ∈ frontier.headers → Certified.HeaderPresent provider.entries header) → + ∀ (V : Type v) [inst_1 : Model.SetTheory V] (constants : Model.Assignment β V), + signature.Compatible provider.entries constants → signature.Compatible frontier.interface.entries constants + axioms: [propext, Classical.choice, Quot.sound] + constants: 1213 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.ConditionalStore.subject_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {signature : Certified.PrimitiveSignature β} {store : Store β} + {subjects : List (ConstRef β)} (receipt : Certified.ConditionalStore signature store subjects) (V : Type v) + [inst_1 : Model.SetTheory V] (constants : Model.Assignment β V), + signature.Compatible receipt.frontier.interface.entries constants → + ∃ constants', + signature.Compatible receipt.checked.result.entries constants' ∧ + Model.Assignment.AgreesOn receipt.frontier.interface.entries constants constants' ∧ + ∀ (ref : ConstRef β), + ref ∈ subjects → + ∃ entry, + receipt.checked.result.entries ref = some entry ∧ + Certified.EntrySource signature store ref entry ∧ + Certified.SourceHeader store ref entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Model.WellDenoted constants' levels env entry.type ∧ + Model.SetTheory.Mem (constants' ref levels) + (Model.interp constants' levels env entry.type) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2445 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.EntrySource.axiom_policy + type: ∀ {β : Type u} {signature : Certified.PrimitiveSignature β} {store : Store β} {ref : ConstRef β} + {entry : Model.ConstantEntry β} {n : Nat} {type : VExpr β} {safety : Safety}, + Certified.EntrySource signature store ref entry → + store.lookup ref = some (Const.axiom n type safety) → + Certified.Standard.EntrySource store ref entry ∨ Certified.Quotient.EntrySource store ref entry + axioms: [propext, Quot.sound] + constants: 2111 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LogicalPolicy, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Instantiation, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope] +certified root Ix.Theory.Certified.ConditionalStore.logical_axioms_authorized + type: ∀ {β : Type u} [inst : DecidableEq β] {signature : Certified.PrimitiveSignature β} {store : Store β} + {subjects : List (ConstRef β)} (receipt : Certified.ConditionalStore signature store subjects) {ref : ConstRef β}, + ref ∈ Certified.logicalAxioms store receipt.checked.result.entries → + ∃ entry, + receipt.checked.result.entries ref = some entry ∧ + (Certified.Standard.EntrySource store ref entry ∨ Certified.Quotient.EntrySource store ref entry) + axioms: [propext, Classical.choice, Quot.sound] + constants: 2596 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LogicalPolicy, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.Support, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ] +certified root Ix.Theory.Certified.acceptsBatch + type: {β : Type u} → + [DecidableEq β] → + Nat → + Certified.PrimitiveSignature β → + Store β → List (Certified.FrontierWitness β) → List (Certified.ClaimNode β) → Bool + axioms: [propext, Classical.choice, Quot.sound] + constants: 5081 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.closed_has_model + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} + (batch : Certified.CheckedBatch fuel signature store inputs), + batch.receipt.frontier.refs = [] → + ∀ (V : Type v) [inst_1 : Model.SetTheory V], + ∃ constants, + signature.Compatible batch.receipt.checked.result.entries constants ∧ + ∀ (ref : ConstRef β), + ref ∈ Certified.nodeSubjects batch.nodes → + ∃ entry, + batch.receipt.checked.result.entries ref = some entry ∧ + Certified.SourceHeader store ref entry ∧ + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Model.SetTheory.Mem (constants ref levels) (Model.interp constants levels env entry.type) + axioms: [propext, Classical.choice, Quot.sound] + constants: 5023 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.compatible_leaves + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} (batch : Certified.CheckedBatch fuel signature store inputs) + (V : Type v) [inst_1 : Model.SetTheory V] (constants : Model.Assignment β V), + signature.Compatible batch.receipt.checked.result.entries constants → + ∀ {node : Certified.CheckedNode fuel signature store}, + node ∈ batch.nodes → signature.Compatible node.receipt.frontier.interface.entries constants + axioms: [propext, Classical.choice, Quot.sound] + constants: 4993 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.frontier_coverage + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} (batch : Certified.CheckedBatch fuel signature store inputs) + {ref : ConstRef β}, + ref ∈ batch.receipt.frontier.refs ↔ + (∃ node, node ∈ inputs ∧ ref ∈ List.map (fun x => x.ref) node.frontier) ∧ + ¬∃ node, node ∈ inputs ∧ ref ∈ node.subjects + axioms: [propext, Classical.choice, Quot.sound] + constants: 5129 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.DependencyOrder.before + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {known : List (ConstRef β)} {nodes : List (Certified.CheckedNode fuel signature store)}, + Certified.DependencyOrder known nodes → + ∀ {index : Nat} {node : Certified.CheckedNode fuel signature store}, + nodes[index]? = some node → + ∀ {ref : ConstRef β}, + ref ∈ node.receipt.frontier.refs → + ref ∈ known ∨ + ∃ previous, + previous < index ∧ ∃ provider, nodes[previous]? = some provider ∧ ref ∈ provider.input.subjects + axioms: [propext, Classical.choice, Quot.sound] + constants: 4970 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.DependencyOrder.edge_for + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {known : List (ConstRef β)} {nodes : List (Certified.CheckedNode fuel signature store)}, + Certified.DependencyOrder known nodes → + ∀ {consumer : Nat} {node : Certified.CheckedNode fuel signature store}, + nodes[consumer]? = some node → + ∀ {ref : ConstRef β}, + ref ∈ node.receipt.frontier.refs → ref ∈ known ∨ ∃ provider, Certified.DependencyEdge nodes provider consumer + axioms: [propext, Classical.choice, Quot.sound] + constants: 4993 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.acyclic + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} + (batch : Certified.CheckedBatch fuel signature store inputs), WellFounded (Certified.DependencyEdge batch.nodes) + axioms: [propext, Classical.choice, Quot.sound] + constants: 5080 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.no_circular_discharge + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} (batch : Certified.CheckedBatch fuel signature store inputs) + {a b : Nat}, Certified.DependencyEdge batch.nodes a b → Certified.DependencyEdge batch.nodes b a → False + axioms: [propext, Classical.choice, Quot.sound] + constants: 5078 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.leaf_axiom_retained + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} (batch : Certified.CheckedBatch fuel signature store inputs) + {node : Certified.CheckedNode fuel signature store}, + node ∈ batch.nodes → + ∀ {ref : ConstRef β}, + ref ∈ Certified.logicalAxioms store node.receipt.checked.result.entries → ref ∈ batch.logicalUses + axioms: [propext, Classical.choice, Quot.sound] + constants: 5040 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.LogicalPolicy, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.logicalUses_authorized + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} (batch : Certified.CheckedBatch fuel signature store inputs) + {ref : ConstRef β}, + ref ∈ batch.logicalUses → + ∃ entry, Certified.Standard.EntrySource store ref entry ∨ Certified.Quotient.EntrySource store ref entry + axioms: [propext, Classical.choice, Quot.sound] + constants: 5079 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.LogicalPolicy, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.checkBatch?_assoc + type: ∀ {β : Type u} [inst : DecidableEq β] (fuel : Nat) (signature : Certified.PrimitiveSignature β) + (store : Store β) (frontier : List (Certified.FrontierWitness β)) (a b c : List (Certified.ClaimNode β)), + Certified.acceptsBatch fuel signature store frontier (Certified.composeClaims (Certified.composeClaims a b) c) = + Certified.acceptsBatch fuel signature store frontier (Certified.composeClaims a (Certified.composeClaims b c)) + axioms: [propext, Classical.choice, Quot.sound] + constants: 5084 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.CheckedBatch.no_False + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {inputs : List (Certified.ClaimNode β)} + (batch : Certified.CheckedBatch fuel signature store inputs), + batch.receipt.frontier.refs = [] → + ∀ {ref : ConstRef β}, + ref ∈ Certified.nodeSubjects batch.nodes → + store.type ref = some signature.falseExpr → ∀ (V : Type v) [Model.SetTheory V], False + axioms: [propext, Classical.choice, Quot.sound] + constants: 5028 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.ClaimComposition, + Ix.Theory.Certified.Claims, + Ix.Theory.Certified.Frontier, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Source, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.acceptsCertified + type: {β : Type u} → + [DecidableEq β] → Nat → Certified.PrimitiveSignature β → Certified.ProofInput β → Certified.ProofWitness β → Bool + axioms: [propext, Classical.choice, Quot.sound] + constants: 4969 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Accept, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.accepted_has_model + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {input : Certified.ProofInput β} {witness : Certified.ProofWitness β}, + Certified.acceptsCertified fuel signature input witness = true → + ∀ (V : Type v) [inst_1 : Model.SetTheory V] (levels : List Nat) (env : Nat → V), + ∃ result, + Certified.checkProofCertified fuel signature input witness = some result ∧ + ∃ constants, + signature.Compatible result.environment.entries constants ∧ + Model.WellDenoted constants levels env result.proof.val ∧ + Model.WellDenoted constants levels env result.proposition.val ∧ + Model.SetTheory.Mem (Model.interp constants levels env result.proof.val) + (Model.interp constants levels env result.proposition.val) + axioms: [propext, Classical.choice, Quot.sound] + constants: 4974 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Accept, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.accepted_proof_sound + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {input : Certified.ProofInput β} {witness : Certified.ProofWitness β}, + Certified.acceptsCertified fuel signature input witness = true → + ∃ result, + Certified.checkProofCertified fuel signature input witness = some result ∧ + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + signature.Compatible result.environment.entries constants → + ∀ (levels : List Nat) (env : Nat → V), + Model.SetTheory.Mem (Model.interp constants levels env result.proof.val) + (Model.interp constants levels env result.proposition.val) + axioms: [propext, Classical.choice, Quot.sound] + constants: 4974 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Accept, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.no_proof_of_False + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {input : Certified.ProofInput β} {witness : Certified.ProofWitness β} (V : Type v) [Model.SetTheory V], + input.proposition = signature.falseExpr → Certified.acceptsCertified fuel signature input witness = true → False + axioms: [propext, Classical.choice, Quot.sound] + constants: 4978 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Accept, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +certified root Ix.Theory.Certified.no_proof_of_empty + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {input : Certified.ProofInput β} {witness : Certified.ProofWitness β} (V : Type v) [inst_1 : Model.SetTheory V], + (∀ (result : Certified.CheckedProof signature input), + Certified.checkProofCertified fuel signature input witness = some result → + ∀ (constants : Model.Assignment β V), + signature.Compatible result.environment.entries constants → + Model.interp constants [] (fun x => Model.SetTheory.empty) result.proposition.val = Model.SetTheory.empty) → + Certified.acceptsCertified fuel signature input witness = true → False + axioms: [propext, Classical.choice, Quot.sound] + constants: 4975 + project modules: [Ix.Theory.Const, + Ix.Theory.Expr, + Ix.Theory.Quot, + Ix.Theory.Ref, + Ix.Theory.Store, + Ix.Theory.VLevel, + Ix.Theory.Certified.Accept, + Ix.Theory.Certified.Admission, + Ix.Theory.Certified.Checker, + Ix.Theory.Certified.Level, + Ix.Theory.Certified.LevelEq, + Ix.Theory.Certified.Policy, + Ix.Theory.Certified.Prelude, + Ix.Theory.Certified.PropWhen, + Ix.Theory.Certified.Signature, + Ix.Theory.Certified.Telescope, + Ix.Theory.Inductive.Levels, + Ix.Theory.Model.Annotated, + Ix.Theory.Model.Context, + Ix.Theory.Model.Environment, + Ix.Theory.Model.Extension, + Ix.Theory.Model.Instantiation, + Ix.Theory.Model.Interpret, + Ix.Theory.Model.Judgment, + Ix.Theory.Model.PrimitiveValues, + Ix.Theory.Model.ReferenceMap, + Ix.Theory.Model.Signature, + Ix.Theory.Model.Support, + Ix.Theory.Model.TelescopeSemantics, + Ix.Theory.Model.Value, + Ix.Theory.Model.WellDenoted, + Ix.Theory.Certified.Basis.Equality, + Ix.Theory.Certified.Basis.Iff, + Ix.Theory.Certified.Basis.Interface, + Ix.Theory.Certified.Basis.Nonempty, + Ix.Theory.Certified.Modeled.Admission, + Ix.Theory.Certified.Modeled.Equation, + Ix.Theory.Certified.Modeled.Source, + Ix.Theory.Certified.Modeled.Transport, + Ix.Theory.Certified.Natural.Admission, + Ix.Theory.Certified.Natural.Checked, + Ix.Theory.Certified.Natural.Publish, + Ix.Theory.Certified.Natural.Value, + Ix.Theory.Certified.Ordinary.Admission, + Ix.Theory.Certified.Ordinary.Checked, + Ix.Theory.Certified.Ordinary.Computation, + Ix.Theory.Certified.Ordinary.ConstructorStage, + Ix.Theory.Certified.Ordinary.Constructors, + Ix.Theory.Certified.Ordinary.Container, + Ix.Theory.Certified.Ordinary.Eliminator, + Ix.Theory.Certified.Ordinary.Family, + Ix.Theory.Certified.Ordinary.LargeElim, + Ix.Theory.Certified.Ordinary.Reading, + Ix.Theory.Certified.Ordinary.RecursorReading, + Ix.Theory.Certified.Ordinary.RecursorStage, + Ix.Theory.Certified.Ordinary.RecursorSyntax, + Ix.Theory.Certified.Ordinary.RecursorValue, + Ix.Theory.Certified.Ordinary.RuleChecks, + Ix.Theory.Certified.Ordinary.RuleEquations, + Ix.Theory.Certified.Ordinary.RuleReading, + Ix.Theory.Certified.Ordinary.Shape, + Ix.Theory.Certified.Quotient.Admission, + Ix.Theory.Certified.Quotient.Checked, + Ix.Theory.Certified.Quotient.Publish, + Ix.Theory.Certified.Quotient.Reading, + Ix.Theory.Certified.Quotient.Syntax, + Ix.Theory.Certified.Quotient.Value, + Ix.Theory.Certified.Standard.Admission, + Ix.Theory.Certified.Standard.Checked, + Ix.Theory.Certified.Standard.Realization, + Ix.Theory.Certified.Structure.Admission, + Ix.Theory.Certified.Structure.Checked, + Ix.Theory.Certified.Structure.Computation, + Ix.Theory.Certified.Structure.Publish, + Ix.Theory.Certified.Structure.Reading, + Ix.Theory.Certified.Structure.Syntax, + Ix.Theory.Certified.Structure.Value, + Ix.Theory.Model.Inductive.Codes, + Ix.Theory.Model.Inductive.Container, + Ix.Theory.Model.Inductive.Recursor, + Ix.Theory.Model.Inductive.Telescope, + Ix.Theory.Model.SetModel.Container, + Ix.Theory.Model.SetModel.Iter, + Ix.Theory.Model.SetModel.Ops, + Ix.Theory.Model.SetModel.RecGraph, + Ix.Theory.Model.SetModel.TaggedSum, + Ix.Theory.Model.SetModel.TupleTower, + Ix.Theory.Model.SetTheory.Core, + Ix.Theory.Model.SetTheory.Derive.Choice, + Ix.Theory.Model.SetTheory.Derive.Empty, + Ix.Theory.Model.SetTheory.Derive.Graphs, + Ix.Theory.Model.SetTheory.Derive.Lfp, + Ix.Theory.Model.SetTheory.Derive.LfpFam, + Ix.Theory.Model.SetTheory.Derive.Omega, + Ix.Theory.Model.SetTheory.Derive.Pair, + Ix.Theory.Model.SetTheory.Derive.Pt, + Ix.Theory.Model.SetTheory.Derive.Quot, + Ix.Theory.Model.SetTheory.Derive.Sep, + Ix.Theory.Model.SetTheory.Derive.Sigma, + Ix.Theory.Model.SetTheory.Derive.Univ, + Ix.Theory.Model.SetTheory.Derive.Universe] +premise definition Ix.Theory.Model.AExpr.mapRefs + type: {β : Type u} → {γ : Type v} → (ConstRef β → ConstRef γ) → Model.AExpr β → Model.AExpr γ + definition: fun {β} {γ} mapping x => Model.AExpr.brecOn x (Model.AExpr.mapRefs._f mapping) +premise constructor Ix.Theory.Certified.Modeled.EquationWitness.mk + type: {β : Type u} → + Certified.Signature.RuleWitness β → Certified.Modeled.EquationProof β → Certified.Modeled.EquationWitness β +premise constructor Ix.Theory.Certified.Modeled.EquationProof.propositional + type: {β : Type u} → + ConstRef β → ConstRef β → ConstRef β → Model.AExpr β → Certified.TypingWitness β → Certified.Modeled.EquationProof β +premise constructor Ix.Theory.Certified.Modeled.CheckedEquation.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {rule : Certified.Signature.Rule β}, + Certified.Signature.RuleFormed entries rule → + Model.ConversionClaim entries [] rule.lhs rule.rhs → Certified.Modeled.CheckedEquation entries rule +premise definition Ix.Theory.Certified.Modeled.checkEquation? + type: {β : Type u} → + [DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (rule : Certified.Signature.Rule β) → + Certified.Modeled.EquationWitness β → + Option (Certified.CheckedClaim (Certified.Modeled.CheckedEquation entries rule)) + definition: fun {β} [DecidableEq β] fuel entries rule witness => do + let formed ← Certified.Signature.checkRule fuel entries rule witness.formation + match witness.proof with + | Certified.Modeled.EquationProof.conversion witness => do + let equality ← Certified.verifyConversion fuel rule.universes entries [] rule.lhs rule.rhs witness + pure { down := ⋯ } + | Certified.Modeled.EquationProof.propositional family reflexivity recursor proof typing => + if hi : Certified.Basis.Equality.Interface entries family reflexivity recursor then do + let type ← + Certified.verifyType fuel rule.universes entries [] rule.type (Model.AExpr.sort witness.formation.level) + witness.formation.type + let checked ← + Certified.verifyType fuel rule.universes entries [] proof + (Certified.Basis.Equality.applied family witness.formation.level rule.type rule.lhs rule.rhs) typing + pure { down := ⋯ } + else none +premise constructor Ix.Theory.Certified.Modeled.Companion.mk + type: {β : Type u} → + Certified.Signature.Header β → ConstRef β → List (Certified.Signature.Rule β) → Certified.Modeled.Companion β +premise definition Ix.Theory.Certified.Modeled.Companion.entry + type: {β : Type u} → Certified.Modeled.Companion β → Model.ConstantEntry β + definition: fun {β} companion => + { universes := companion.header.universes, type := companion.header.type, body := none, + equations := List.map (fun rule => { lhs := rule.lhs, rhs := rule.rhs }) companion.rules } +premise definition Ix.Theory.Certified.Modeled.mapping + type: {β : Type u} → [DecidableEq β] → List (Certified.Modeled.Companion β) → ConstRef β → ConstRef β + definition: fun {β} [DecidableEq β] companions ref => + match Certified.Modeled.lookupCompanion companions ref with + | none => ref + | some companion => companion.model +premise constructor Ix.Theory.Certified.Modeled.CompanionChecked.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} + {companions : List (Certified.Modeled.Companion β)} {companion : Certified.Modeled.Companion β}, + (∃ entry, + entries companion.model = some entry ∧ + entry.universes = companion.header.universes ∧ + entry.type = Model.AExpr.mapRefs (Certified.Modeled.mapping companions) companion.header.type) → + Model.AExpr.Scope companion.header.universes 0 companion.header.type → + Model.AExpr.ReferencesIn (Certified.Modeled.environment entries companions) companion.header.type → + (∀ (rule : Certified.Signature.Rule β), + rule ∈ companion.rules → + rule.universes = companion.header.universes ∧ + Model.AExpr.Scope companion.header.universes 0 rule.lhs ∧ + Model.AExpr.Scope companion.header.universes 0 rule.rhs) → + (∀ (rule : Certified.Signature.Rule β), + rule ∈ companion.rules → + Model.AExpr.ReferencesIn (Certified.Modeled.environment entries companions) rule.lhs ∧ + Model.AExpr.ReferencesIn (Certified.Modeled.environment entries companions) rule.rhs) → + (∀ (rule : Certified.Signature.Rule β), + rule ∈ companion.rules → + Certified.Modeled.CheckedEquation entries (Certified.Modeled.mapRule companions rule)) → + Certified.Modeled.CompanionChecked entries companions companion +premise constructor Ix.Theory.Certified.Modeled.CheckedCompanions.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} + {companions : List (Certified.Modeled.Companion β)}, + (List.map (fun x => x.header.ref) companions).Nodup → + (∀ (companion : Certified.Modeled.Companion β), companion ∈ companions → entries companion.header.ref = none) → + (∀ (companion : Certified.Modeled.Companion β), + companion ∈ companions → Certified.Modeled.CompanionChecked entries companions companion) → + Certified.Modeled.CheckedCompanions entries companions +premise definition Ix.Theory.Certified.Modeled.checkCompanions? + type: {β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (companions : List (Certified.Modeled.Companion β)) → + List (List (Certified.Modeled.EquationWitness β)) → + Option (Certified.CheckedClaim (Certified.Modeled.CheckedCompanions entries companions)) + definition: fun {β} [DecidableEq β] fuel entries companions witnesses => + if hu : (List.map (fun x => x.header.ref) companions).Nodup then + if hf : + ∀ (companion : Certified.Modeled.Companion β), companion ∈ companions → entries companion.header.ref = none then + do + let checked ← Certified.Modeled.checkEach? fuel entries companions companions witnesses + pure { down := ⋯ } + else none + else none +premise definition Ix.Theory.Certified.Modeled.assignment + type: {β : Type u} → + [DecidableEq β] → {V : Type v} → Model.Assignment β V → List (Certified.Modeled.Companion β) → Model.Assignment β V + definition: fun {β} [DecidableEq β] {V} constants companions ref levels => + constants (Certified.Modeled.mapping companions ref) levels +premise definition Ix.Theory.Certified.Modeled.SourceMatches + type: {β : Type u} → [DecidableEq β] → Store β → Certified.Modeled.Companion β → Prop + definition: fun {β} [DecidableEq β] store companion => + store.type companion.header.ref = some companion.header.type.erase ∧ + store.uvars companion.header.ref = some companion.header.universes ∧ + Certified.Modeled.sourceRules? store companion.header.ref = + some (List.map Certified.Modeled.eraseRule companion.rules) +premise definition Ix.Theory.Certified.Modeled.sourceRefs? + type: {β : Type u} → [DecidableEq β] → Store β → β → List (ConstRef β) → Option (List (ConstRef β)) + definition: fun {β} [DecidableEq β] store source recursors => do + let families ← Certified.Modeled.sourceFamilies? store source + if recursors.length < families.length then none + else do + let majors ← + List.mapM + (fun ref => do + let info ← Certified.Modeled.recursorSource? store ref + let major ← Certified.Modeled.majorSource? store info + pure major.family) + recursors + if (List.take families.length majors != families) = true then none + else do + let members ← + List.mapM + (fun family => do + let ctors ← Certified.Modeled.familyConstructors? store family + pure (family :: ctors)) + families + pure (members.flatten ++ recursors) +premise definition Ix.Theory.Certified.Modeled.sourceRules? + type: {β : Type u} → [DecidableEq β] → Store β → ConstRef β → Option (List (Certified.Modeled.RawRule β)) + definition: fun {β} [DecidableEq β] store ref => + match ref with + | ConstRef.ctor block member c => do + let _ ← Certified.Modeled.familySource? store (ConstRef.member block member) + let ctor ← store.lookupCtor ref + if ctor.safety = Safety.safe then some [] else none + | ConstRef.member b i => + match store.lookup ref with + | some (Const.induct uvars nparams nindices type ctors Safety.safe) => some [] + | some (Const.recursor uvars nparams nindices nmotives nminors type rules k safety) => + Certified.Modeled.recursorRules? store ref + | x => none +premise definition Ix.Theory.Certified.Modeled.betaHead? + type: {β : Type u} → Nat → VExpr β → Option (VExpr β) + definition: fun {β} x x_1 => + Nat.brecOn (motive := fun x => VExpr β → Option (VExpr β)) x Certified.Modeled.betaHead?._f x_1 +premise definition Ix.Theory.Certified.Modeled.majorSource? + type: {β : Type u} → + [DecidableEq β] → Store β → Certified.Modeled.RecursorSource β → Option (Certified.Modeled.MajorSource β) + definition: fun {β} [DecidableEq β] store source => do + let __x ← Certified.Modeled.splitPi? source.prefix source.type + match __x with + | (prefixDomains, tail) => do + let __x ← Certified.Modeled.splitPi? source.indices tail + match __x with + | (fst, major.forallE body) => do + let major ← Certified.Modeled.betaHead? 512 major + match major.appHead with + | VExpr.const family levels => do + let info ← Certified.Modeled.familySource? store family + if (info.indices != source.indices || levels.length != info.universes) = true then none + else + have arguments := major.appArgs []; + if (arguments.length != info.parameters + source.indices) = true then none + else + if (List.drop info.parameters arguments != VExpr.bvarRevRange 0 source.indices) = true then none + else + have actual := List.take info.parameters arguments; + have parameters := List.map (fun p => p.unliftN source.indices 0) actual; + if (List.map (fun x => VExpr.liftN source.indices x) parameters != actual) = true then none + else + pure + { family := family, levels := levels, parameters := parameters, + prefixDomains := prefixDomains } + | x => none + | x => none +premise definition Ix.Theory.Certified.Modeled.ruleSource? + type: {β : Type u} → + [DecidableEq β] → + Store β → + ConstRef β → + Certified.Modeled.RecursorSource β → + Certified.Modeled.MajorSource β → ConstRef β → Option (Certified.Modeled.RawRule β) + definition: fun {β} [DecidableEq β] store recursor source major constructor => + match constructor with + | ConstRef.ctor block member c => + if (major.family != ConstRef.member block member) = true then none + else do + let family ← Certified.Modeled.familySource? store major.family + let ctor ← store.lookupCtor constructor + if (ctor.safety != Safety.safe || ctor.uvars != family.universes || ctor.nparams != family.parameters) = true then + none + else + match store.ctorRuleIndex? constructor with + | some slot => do + let stored ← source.rules[slot]? + if (stored.nfields != ctor.nfields) = true then none + else do + let specialized ← + Certified.Modeled.applyPi? (VExpr.liftN source.prefix (VExpr.instL major.levels ctor.type)) + major.parameters + let __x ← Certified.Modeled.splitPi? ctor.nfields specialized + match __x with + | (fields, result) => + if (result.appHead != VExpr.const major.family major.levels) = true then none + else + have args := result.appArgs []; + have parameters := List.map (fun x => VExpr.liftN ctor.nfields x) major.parameters; + if + (args.length != ctor.nparams + source.indices || List.take ctor.nparams args != parameters) = + true then + none + else + have constructorValue := + (VExpr.const constructor major.levels).appN (parameters ++ VExpr.bvarRevRange 0 ctor.nfields); + have callArgs := + VExpr.bvarRevRange ctor.nfields source.prefix ++ List.drop ctor.nparams args ++ + [constructorValue]; + do + let resultType ← + Certified.Modeled.applyPi? (VExpr.liftN (source.prefix + ctor.nfields) source.type) callArgs + have telescope : List (VExpr β) := major.prefixDomains ++ fields + let _ ← Certified.Modeled.splitLam? telescope.length stored.rhs + pure + { universes := source.universes, type := VExpr.forallN telescope resultType, + lhs := + VExpr.lamN telescope + ((VExpr.const recursor (List.map VLevel.param (List.range source.universes))).appN + callArgs), + rhs := stored.rhs } + | x => none + | x => none +premise constructor Ix.Theory.Certified.Modeled.Witness.mk + type: {β : Type u} → + β → + List (ConstRef β) → + List (Certified.Modeled.Companion β) → + List (List (Certified.Modeled.EquationWitness β)) → Certified.Modeled.Witness β +premise constructor Ix.Theory.Certified.Modeled.Checked.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} + {witness : Certified.Modeled.Witness β}, + Certified.Modeled.sourceRefs? store witness.source witness.recursors = + some (List.map (fun x => x.header.ref) witness.companions) → + (∀ (companion : Certified.Modeled.Companion β), + companion ∈ witness.companions → Certified.Modeled.SourceMatches store companion) → + Certified.Modeled.CheckedCompanions entries witness.companions → Certified.Modeled.Checked entries store witness +premise definition Ix.Theory.Certified.Modeled.EntrySource + type: {β : Type u} → Store β → ConstRef β → Model.ConstantEntry β → Prop + definition: fun {β} store ref entry => + ∃ decision companion, + Certified.Modeled.SourceMatches store companion ∧ ref = companion.header.ref ∧ entry = companion.entry +premise definition Ix.Theory.Model.Equinumerous + type: {V : Type u} → (V → V → Prop) → V → V → Prop + definition: fun {V} mem y u => + ∃ f, + (∀ (z : V), mem z y → mem (f z) u) ∧ + (∀ (z z' : V), mem z y → mem z' y → f z = f z' → z = z') ∧ ∀ (w : V), mem w u → ∃ z, mem z y ∧ f z = w +premise definition Ix.Theory.Model.IsTGUniverse + type: {V : Type u} → (V → V → Prop) → V → Prop + definition: fun {V} mem u => + (∀ (y z : V), mem y u → mem z y → mem z u) ∧ + (∀ (y z : V), mem y u → (∀ (w : V), mem w z → mem w y) → mem z u) ∧ + (∀ (y : V), mem y u → ∃ p, mem p u ∧ ∀ (z : V), (∀ (w : V), mem w z → mem w y) → mem z p) ∧ + ∀ (y : V), (∀ (w : V), mem w y → mem w u) → Model.Equinumerous mem y u ∨ mem y u +premise constructor Ix.Theory.Model.SetTheory.mk + type: {V : Type u} → + (Mem : V → V → Prop) → + (∀ {x y : V}, (∀ (z : V), Mem z x ↔ Mem z y) → x = y) → + (upair : V → V → V) → + (∀ {z a b : V}, Mem z (upair a b) ↔ z = a ∨ z = b) → + (sUnion : V → V) → + (∀ {z x : V}, Mem z (sUnion x) ↔ ∃ y, Mem y x ∧ Mem z y) → + (power : V → V) → + (∀ {z x : V}, Mem z (power x) ↔ ∀ (w : V), Mem w z → Mem w x) → + (∀ (x : V), (∃ y, Mem y x) → ∃ y, Mem y x ∧ ¬∃ z, Mem z y ∧ Mem z x) → + (image : (V → V) → V → V) → + (∀ {f : V → V} {a z : V}, Mem z (image f a) ↔ ∃ w, Mem w a ∧ z = f w) → + (univChain : Nat → V) → + (∀ (n : Nat), Mem (univChain n) (univChain (n + 1))) → + (∀ (n : Nat), Model.IsTGUniverse Mem (univChain n)) → Model.SetTheory V +premise definition Ix.Theory.Model.AExpr.Scope + type: {β : Type u_1} → Nat → Nat → Model.AExpr β → Prop + definition: fun {β} universes depth x => + Model.AExpr.brecOn (motive := fun x => Nat → Prop) x (Model.AExpr.Scope._f universes) depth +premise definition Ix.Theory.Model.Reading + type: {β : Type u} → Nat → Nat → VExpr β → Type (max 0 u) + definition: fun {β} n k source => { e // e.erase = source ∧ Model.AExpr.Scope n k e } +premise constructor Ix.Theory.Certified.DefinitionReading.mk + type: {β : Type u} → + (universes : Nat) → + Ix.Theory.DefKind → + (type body : Model.AExpr β) → + Model.AExpr.Scope universes 0 type → Model.AExpr.Scope universes 0 body → Certified.DefinitionReading β +premise constructor Ix.Theory.Certified.PrimitiveSignature.mk + type: {β : Type u} → + (falseType falseElim : ConstRef β) → falseType ≠ falseElim → Option (ConstRef β) → Certified.PrimitiveSignature β +premise constructor Ix.Theory.Certified.CheckedStore.mk + type: {β : Type u} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + {targets : List (ConstRef β)} → + (environment : Certified.AdmittedEnvironment signature store) → + (∀ (r : ConstRef β), r ∈ targets → (environment.entries r).isSome = true) → + Certified.CheckedStore signature store targets +premise constructor Ix.Theory.Certified.SourceHeader.mk + type: ∀ {β : Type u} {store : Store β} {ref : ConstRef β} {entry : Model.ConstantEntry β}, + store.type ref = some entry.type.erase → + store.uvars ref = some entry.universes → Certified.SourceHeader store ref entry +premise constructor Ix.Theory.Certified.CheckedInterface.mk + type: {β : Type u} → + {signature : Certified.PrimitiveSignature β} → + (entries : Model.Environment β) → entries.WF → signature.Present entries → Certified.CheckedInterface signature +premise constructor Ix.Theory.Certified.CheckedExtension.mk + type: {β : Type u} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + {input : Certified.CheckedInterface signature} → + (result : Certified.CheckedInterface signature) → + Certified.Extends signature input.entries result.entries → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + result.entries r = some entry → + input.entries r = some entry ∨ Certified.EntrySource signature store r entry) → + Certified.CheckedExtension signature store input +premise constructor Ix.Theory.Certified.FrontierWitness.mk + type: {β : Type u} → + ConstRef β → Model.AnnotationTree → VLevel → Certified.TypingWitness β → Certified.FrontierWitness β +premise constructor Ix.Theory.Certified.FrontierHeader.mk + type: {β : Type u} → + {store : Store β} → + (header : Certified.Signature.Header β) → + Certified.SourceHeader store header.ref header.entry → + Certified.deferredSource store header.ref = true → Certified.FrontierHeader store +premise definition Ix.Theory.Certified.deferredSource + type: {β : Type u} → Store β → ConstRef β → Bool + definition: fun {β} store ref => + match store.lookup ref with + | some (Const.defn uvars kind type value Safety.safe) => true + | some (Const.induct uvars nparams nindices type ctors Safety.safe) => true + | some (Const.recursor uvars nparams nindices nmotives nminors type rules k Safety.safe) => true + | some val => false + | none => + match store.lookupCtor ref with + | some ctor => ctor.safety == Safety.safe + | none => false +premise constructor Ix.Theory.Certified.CheckedFrontier.mk + type: {β : Type u} → + [inst : DecidableEq β] → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (readings : List (Certified.FrontierHeader store)) → + signature.validate store = true → + Certified.Signature.Formed signature.environment (List.map (fun x => x.header) readings) → + Certified.CheckedFrontier signature store +premise definition Ix.Theory.Certified.CheckedFrontier.interface + type: {β : Type u} → + [inst : DecidableEq β] → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → Certified.CheckedFrontier signature store → Certified.CheckedInterface signature + definition: fun {β} [DecidableEq β] {signature} {store} frontier => + { entries := Certified.Signature.environment signature.environment frontier.headers, wf := ⋯, present := ⋯ } +premise definition Ix.Theory.Certified.HeaderPresent + type: {β : Type u} → Model.Environment β → Certified.Signature.Header β → Prop + definition: fun {β} entries header => + match entries header.ref with + | none => False + | some entry => entry.universes = header.universes ∧ entry.type = header.type +premise constructor Ix.Theory.Certified.ConditionalStore.mk + type: {β : Type u} → + [inst : DecidableEq β] → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + {subjects : List (ConstRef β)} → + (frontier : Certified.CheckedFrontier signature store) → + (checked : Certified.CheckedExtension signature store frontier.interface) → + (∀ (r : ConstRef β), r ∈ subjects → frontier.interface.entries r = none) → + (∀ (r : ConstRef β), r ∈ subjects → (checked.result.entries r).isSome = true) → + Certified.ConditionalStore signature store subjects +premise constructor Ix.Theory.Certified.ClaimNode.mk + type: {β : Type u} → + List (ConstRef β) → List (Certified.FrontierWitness β) → List (Certified.DeclarationWitness β) → Certified.ClaimNode β +premise constructor Ix.Theory.Certified.CheckedNode.mk + type: {β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (input : Certified.ClaimNode β) → + (receipt : Certified.ConditionalStore signature store input.subjects) → + Certified.checkConditionalStore? fuel signature store input.frontier input.subjects input.declarations = + some receipt → + Certified.CheckedNode fuel signature store +premise constructor Ix.Theory.Certified.ReplayResult.mk + type: {β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + {state : Certified.CheckedInterface signature} → + {known : List (ConstRef β)} → + {nodes : List (Certified.CheckedNode fuel signature store)} → + (checked : Certified.CheckedExtension signature store state) → + Certified.DependencyOrder known nodes → + (∀ (ref : ConstRef β), + ref ∈ Certified.nodeSubjects nodes → (checked.result.entries ref).isSome = true) → + (∀ (node : Certified.CheckedNode fuel signature store), + node ∈ nodes → + ∀ (header : Certified.Signature.Header β), + header ∈ node.receipt.frontier.headers → + Certified.HeaderPresent checked.result.entries header) → + Certified.ReplayResult state known nodes +premise constructor Ix.Theory.Certified.CheckedBatch.mk + type: {β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + {inputs : List (Certified.ClaimNode β)} → + (nodes : List (Certified.CheckedNode fuel signature store)) → + List.map (fun x => x.input) nodes = inputs → + (receipt : Certified.ConditionalStore signature store (Certified.nodeSubjects nodes)) → + (∀ (ref : ConstRef β), ref ∈ receipt.frontier.refs ↔ ref ∈ Certified.outstanding nodes) → + Certified.DependencyOrder (receipt.frontier.refs ++ [signature.falseType, signature.falseElim]) + nodes → + (∀ (node : Certified.CheckedNode fuel signature store), + node ∈ nodes → + ∀ (header : Certified.Signature.Header β), + header ∈ node.receipt.frontier.headers → + Certified.HeaderPresent receipt.checked.result.entries header) → + Certified.CheckedBatch fuel signature store inputs +premise constructor Ix.Theory.Certified.DependencyOrder.nil + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} (known : List (ConstRef β)), Certified.DependencyOrder known [] +premise constructor Ix.Theory.Certified.DependencyOrder.cons + type: ∀ {β : Type u} [inst : DecidableEq β] {fuel : Nat} {signature : Certified.PrimitiveSignature β} + {store : Store β} {known : List (ConstRef β)} {node : Certified.CheckedNode fuel signature store} + {rest : List (Certified.CheckedNode fuel signature store)}, + (∀ (ref : ConstRef β), ref ∈ node.receipt.frontier.refs → ref ∈ known) → + Certified.DependencyOrder (known ++ node.input.subjects) rest → Certified.DependencyOrder known (node :: rest) +premise definition Ix.Theory.Certified.DependencyEdge + type: {β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → List (Certified.CheckedNode fuel signature store) → Nat → Nat → Prop + definition: fun {β} [DecidableEq β] {fuel} {signature} {store} nodes provider consumer => + ∃ a b ref, + nodes[provider]? = some a ∧ + nodes[consumer]? = some b ∧ + ref ∈ a.input.subjects ∧ + ref ∈ b.receipt.frontier.refs ∧ + ∀ (previous : Nat), + previous < provider → + ∀ (other : Certified.CheckedNode fuel signature store), + nodes[previous]? = some other → ¬ref ∈ other.input.subjects +premise definition Ix.Theory.Certified.outstanding + type: {β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → List (Certified.CheckedNode fuel signature store) → List (ConstRef β) + definition: fun {β} [DecidableEq β] {fuel} {signature} {store} nodes => + (List.filter (fun ref => !(Certified.nodeSubjects nodes).contains ref) (Certified.nodeFrontiers nodes)).eraseDups +premise definition Ix.Theory.Certified.logicalAxioms + type: {β : Type u} → Store β → Model.Environment β → List (ConstRef β) + definition: fun {β} store entries => + List.filter (fun ref => Certified.isLogicalAxiom store ref && (entries ref).isSome) (Certified.sourceMembers store) +premise definition Ix.Theory.Certified.CheckedBatch.logicalUses + type: {β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + {inputs : List (Certified.ClaimNode β)} → + Certified.CheckedBatch fuel signature store inputs → List (ConstRef β) + definition: fun {β} [DecidableEq β] {fuel} {signature} {store} {inputs} batch => + (Certified.logicalAxioms store batch.receipt.checked.result.entries ++ + List.flatMap (fun node => Certified.logicalAxioms store node.receipt.checked.result.entries) + batch.nodes).eraseDups +premise definition Ix.Theory.Model.WellDenoted + type: {β : Type u} → + {V : Type v} → [Model.SetTheory V] → Model.Assignment β V → List Nat → (Nat → V) → Model.AExpr β → Prop + definition: fun {β} {V} [Model.SetTheory V] constants levels env x => + Model.AExpr.brecOn (motive := fun x => (Nat → V) → Prop) x (Model.WellDenoted._f constants levels) env +premise definition Ix.Theory.Model.Context.Valid + type: {β : Type u} → + {V : Type v} → [Model.SetTheory V] → Model.Assignment β V → List Nat → Model.Context β → (Nat → V) → Prop + definition: fun {β} {V} [Model.SetTheory V] constants levels Γ env => + ∀ (i : Nat) (A : Model.AExpr β), + Γ[i]? = some A → + Model.WellDenoted constants levels env A ∧ Model.SetTheory.Mem (env i) (Model.interp constants levels env A) +premise definition Ix.Theory.Model.TypingClaim + type: {β : Type u} → Model.Environment β → Model.Context β → Model.AExpr β → Model.AExpr β → Prop + definition: fun {β} entries Γ e A => + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + Model.Realizes constants entries → + ∀ (levels : List Nat) (env : Nat → V), + Model.Context.Valid constants levels Γ env → + Model.WellDenoted constants levels env e ∧ + Model.WellDenoted constants levels env A ∧ + Model.SetTheory.Mem (Model.interp constants levels env e) (Model.interp constants levels env A) +premise definition Ix.Theory.Model.ConversionClaim + type: {β : Type u} → Model.Environment β → Model.Context β → Model.AExpr β → Model.AExpr β → Prop + definition: fun {β} entries Γ a b => + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + Model.Realizes constants entries → + ∀ (levels : List Nat) (env : Nat → V), + Model.Context.Valid constants levels Γ env → + Model.interp constants levels env a = Model.interp constants levels env b +premise constructor Ix.Theory.Model.ConstantEntry.mk + type: {β : Type u} → + Nat → + Model.AExpr β → + Option (Model.AExpr β) → List (Model.ConstantEquation β) → List (Model.ConstantFact β) → Model.ConstantEntry β +premise constructor Ix.Theory.Model.Realizes.mk + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} + {entries : Model.Environment β}, + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (levels : List Nat), + levels.length = entry.universes → ∀ (env : Nat → V), Model.WellDenoted constants levels env entry.type) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Model.SetTheory.Mem (constants r levels) (Model.interp constants levels env entry.type)) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (body : Model.AExpr β), + entry.body = some body → + ∀ (levels : List Nat), + levels.length = entry.universes → ∀ (env : Nat → V), Model.WellDenoted constants levels env body) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (body : Model.AExpr β), + entry.body = some body → + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), constants r levels = Model.interp constants levels env body) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (equation : Model.ConstantEquation β), + equation ∈ entry.equations → + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), + Model.interp constants levels env equation.lhs = + Model.interp constants levels env equation.rhs) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (fact : Model.ConstantFact β), + fact ∈ entry.facts → + ∀ (levels : List Nat), + levels.length = entry.universes → + ∀ (env : Nat → V), Model.ConstantFact.Meaning constants r levels env fact) → + Model.Realizes constants entries +premise constructor Ix.Theory.Model.ConstantEquation.mk + type: {β : Type u} → Model.AExpr β → Model.AExpr β → Model.ConstantEquation β +premise constructor Ix.Theory.Model.ConstantFact.typed + type: {β : Type u} → Model.AExpr β → Model.AExpr β → Model.ConstantFact β +premise constructor Ix.Theory.Model.ConstantFact.natural + type: {β : Type u} → ConstRef β → ConstRef β → Model.ConstantFact β +premise definition Ix.Theory.Model.ConstantFact.Meaning + type: {β : Type u} → + {V : Type v} → + [Model.SetTheory V] → Model.Assignment β V → ConstRef β → List Nat → (Nat → V) → Model.ConstantFact β → Prop + definition: fun {β} {V} [Model.SetTheory V] constants owner levels env x => + match x with + | Model.ConstantFact.typed e type => + Model.WellDenoted constants levels env e ∧ + Model.WellDenoted constants levels env type ∧ + Model.SetTheory.Mem (Model.interp constants levels env e) (Model.interp constants levels env type) + | Model.ConstantFact.natural zero succ => levels = [] ∧ Model.NaturalMeaning constants owner zero succ +premise definition Ix.Theory.Model.ConstantFact.Scope + type: {β : Type u} → Nat → Model.ConstantFact β → Prop + definition: fun {β} n x => + match x with + | Model.ConstantFact.typed e type => Model.AExpr.Scope n 0 e ∧ Model.AExpr.Scope n 0 type + | Model.ConstantFact.natural zero succ => n = 0 +premise definition Ix.Theory.Model.ConstantFact.ReferencesIn + type: {β : Type u} → Model.Environment β → Model.ConstantFact β → Prop + definition: fun {β} entries fact => ∀ (r : ConstRef β), r ∈ fact.references → (entries r).isSome = true +premise constructor Ix.Theory.Model.NaturalMeaning.mk + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} + {family zero succ : ConstRef β}, + (∀ (n : Nat), Model.SetTheory.Mem (Model.Numeral.value n) (constants family [])) → + constants zero [] = Model.Numeral.value 0 → + (∀ (n : Nat), Model.SetTheory.app (constants succ []) (Model.Numeral.value n) = Model.Numeral.value (n + 1)) → + Model.NaturalMeaning constants family zero succ +premise definition Ix.Theory.Model.projectValue + type: {V : Type u} → [Model.SetTheory V] → Nat → V → V + definition: fun {V} [Model.SetTheory V] field value => + Model.SetTheory.Tower.projS field (Model.SetTheory.ssnd (Model.SetTheory.sfst value)) +premise definition Ix.Theory.Model.Numeral.zero + type: {V : Type u} → [Model.SetTheory V] → V + definition: fun {V} [Model.SetTheory V] => + Model.SetTheory.spair (Model.SetTheory.Tower.inj 0 Model.SetTheory.pt) Model.SetTheory.empty +premise definition Ix.Theory.Model.Numeral.succ + type: {V : Type u} → [Model.SetTheory V] → V → V + definition: fun {V} [Model.SetTheory V] n => + Model.SetTheory.spair (Model.SetTheory.Tower.inj 1 Model.SetTheory.pt) + (Model.SetTheory.graph (fun x => n) (Model.SetTheory.sing (Model.SetTheory.Tower.inj 0 Model.SetTheory.pt))) +premise definition Ix.Theory.Model.Numeral.value + type: {V : Type u} → [Model.SetTheory V] → Nat → V + definition: fun {V} [Model.SetTheory V] x => Nat.brecOn x Model.Numeral.value._f +premise constructor Ix.Theory.Model.Environment.WF.mk + type: ∀ {β : Type u} {entries : Model.Environment β}, + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → Model.AExpr.Scope entry.universes 0 entry.type) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (body : Model.AExpr β), entry.body = some body → Model.AExpr.Scope entry.universes 0 body) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → Model.AExpr.ReferencesIn entries entry.type) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (body : Model.AExpr β), entry.body = some body → Model.AExpr.ReferencesIn entries body) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (equation : Model.ConstantEquation β), + equation ∈ entry.equations → + Model.AExpr.Scope entry.universes 0 equation.lhs ∧ + Model.AExpr.Scope entry.universes 0 equation.rhs) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (equation : Model.ConstantEquation β), + equation ∈ entry.equations → + Model.AExpr.ReferencesIn entries equation.lhs ∧ Model.AExpr.ReferencesIn entries equation.rhs) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (fact : Model.ConstantFact β), + fact ∈ entry.facts → Model.ConstantFact.Scope entry.universes fact) → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → + ∀ (fact : Model.ConstantFact β), + fact ∈ entry.facts → Model.ConstantFact.ReferencesIn entries fact) → + entries.WF +premise definition Ix.Theory.Model.Assignment.AgreesOn + type: {β : Type u} → {V : Type u_1} → Model.Environment β → Model.Assignment β V → Model.Assignment β V → Prop + definition: fun {β} {V} entries constants constants' => + ∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → ∀ (levels : List Nat), constants' r levels = constants r levels +premise constructor Ix.Theory.Model.IndexedContainer.mk + type: {V : Type u} → V → (V → V) → (V → V) → (V → V → V) → Model.IndexedContainer V +premise constructor Ix.Theory.Model.IndexedContainer.WF.mk + type: ∀ {V : Type u} [inst : Model.SetTheory V] {D : Model.IndexedContainer V} {w : Nat}, + (w ≠ 0 → ∀ (i : V), Model.SetTheory.Mem i D.indices → Model.SetTheory.Mem (D.shapes i) (Model.SetTheory.univ w)) → + (w ≠ 0 → + ∀ (i a : V), + Model.SetTheory.Mem i D.indices → + Model.SetTheory.Mem a (D.shapes i) → Model.SetTheory.Mem (D.positions a) (Model.SetTheory.univ w)) → + (∀ (i a p : V), + Model.SetTheory.Mem i D.indices → + Model.SetTheory.Mem a (D.shapes i) → + Model.SetTheory.Mem p (D.positions a) → Model.SetTheory.Mem (D.target a p) D.indices) → + D.WF w +premise definition Ix.Theory.Model.IndexedContainer.LargeElim + type: {V : Type u} → [Model.SetTheory V] → Model.IndexedContainer V → Nat → Prop + definition: fun {V} [Model.SetTheory V] D w => + w = 0 → + ∀ (i : V), + Model.SetTheory.Mem i D.indices → + ∀ (a b : V), Model.SetTheory.Mem a (D.shapes i) → Model.SetTheory.Mem b (D.shapes i) → a = b +premise definition Ix.Theory.Model.IndexedContainer.AlgebraTyping + type: {V : Type u} → [Model.SetTheory V] → Model.IndexedContainer V → Nat → (V → V → V) → (V → V → V → V → V) → Prop + definition: fun {V} [Model.SetTheory V] D w M algebra => + ∀ (i : V), + Model.SetTheory.Mem i D.indices → + ∀ (a : V), + Model.SetTheory.Mem a (D.shapes i) → + ∀ (g : V), + Model.SetTheory.Mem g + (Model.SetTheory.piSet (D.positions a) fun p => Model.SetTheory.app (D.carrier w) (D.target a p)) → + ∀ (ih : V), + Model.SetTheory.Mem ih + (Model.SetTheory.piSet (D.positions a) fun p => M (D.target a p) (Model.SetTheory.app g p)) → + Model.SetTheory.Mem (algebra i a g ih) (M i (Model.IndexedContainer.node w a g)) +premise definition Ix.Theory.Certified.TelescopeBound + type: {β : Type u} → Model.Environment β → Model.Context β → List (Model.AExpr β) → Option VLevel → Prop + definition: fun {β} entries Γ domains bound => + ∀ (w : VLevel), + bound = some w → + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + Model.Realizes constants entries → + ∀ (levels : List Nat) (env : Nat → V), + Model.Context.Valid constants levels Γ env → + VLevel.eval levels w ≠ 0 → + Model.SetTheory.Tower.BoundS (VLevel.eval levels w) + (Model.Telescope.interpret constants levels env domains) +premise definition Ix.Theory.Certified.TelescopeProp + type: {β : Type u} → Model.Environment β → Model.Context β → List (Model.AExpr β) → VLevel → Prop + definition: fun {β} entries Γ domains atLevel => + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + Model.Realizes constants entries → + ∀ (levels : List Nat) (env : Nat → V), + Model.Context.Valid constants levels Γ env → + VLevel.eval levels atLevel = 0 → + Model.SetTheory.Tower.PropS (Model.Telescope.interpret constants levels env domains) +premise definition Ix.Theory.Certified.ArgumentsFit + type: {β : Type u} → Model.Environment β → Model.Context β → List (Model.AExpr β) → List (Model.AExpr β) → Prop + definition: fun {β} entries Γ domains args => + ∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + Model.Realizes constants entries → + ∀ (levels : List Nat) (env : Nat → V), + Model.Context.Valid constants levels Γ env → + Model.SetTheory.Tower.FitsS (Model.Telescope.interpret constants levels env domains) + (List.map (Model.interp constants levels env) args) +premise constructor Ix.Theory.Certified.Ordinary.Shape.mk + type: {β : Type u} → + Nat → + List (Model.AExpr β) → + List (Model.AExpr β) → VLevel → List (Certified.Ordinary.Constructor β) → Certified.Ordinary.Shape β +premise constructor Ix.Theory.Certified.Ordinary.Constructor.mk + type: {β : Type u} → + List (Model.AExpr β) → + List (Certified.Ordinary.RecursiveField β) → List (Model.AExpr β) → Certified.Ordinary.Constructor β +premise constructor Ix.Theory.Certified.Ordinary.RecursiveField.mk + type: {β : Type u} → List (Model.AExpr β) → List (Model.AExpr β) → Certified.Ordinary.RecursiveField β +premise constructor Ix.Theory.Certified.Ordinary.CheckedShape.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {store : Store β} {source : β} + {shape : Certified.Ordinary.Shape β}, + store.blocks source = some { members := [shape.source source] } → + (∀ (r : ConstRef β), r ∈ shape.references source → entries r = none) → + (∀ (e : Model.AExpr β), e ∈ shape.parameters ++ shape.indices → Model.AExpr.ReferencesIn entries e) → + Model.AExpr.Scope shape.universes 0 shape.type → + (∀ (ctor : Certified.Ordinary.Constructor β), + ctor ∈ shape.constructors → Model.AExpr.Scope shape.universes 0 (ctor.type shape source)) → + Model.Telescope.Formed entries [] shape.parameters → + Model.Telescope.Formed entries shape.parameterContext shape.indices → + (∀ (ctor : Certified.Ordinary.Constructor β), + ctor ∈ shape.constructors → Certified.Ordinary.ConstructorEvidence entries shape ctor) → + Certified.Ordinary.CheckedShape entries store source shape +premise definition Ix.Theory.Certified.Ordinary.ConstructorEvidence + type: {β : Type u} → Model.Environment β → Certified.Ordinary.Shape β → Certified.Ordinary.Constructor β → Prop + definition: fun {β} entries shape ctor => + (∀ (e : Model.AExpr β), e ∈ ctor.fields ++ ctor.indices → Model.AExpr.ReferencesIn entries e) ∧ + Model.Telescope.Formed entries shape.parameterContext ctor.fields ∧ + Certified.TelescopeBound entries shape.parameterContext ctor.fields (some shape.level) ∧ + Certified.ArgumentsFit entries (ctor.context shape) (Model.Telescope.lift ctor.fields.length shape.indices) + ctor.indices ∧ + ∀ (field : Certified.Ordinary.RecursiveField β), + field ∈ ctor.recursive → Certified.Ordinary.RecursiveEvidence entries shape ctor field +premise definition Ix.Theory.Certified.Ordinary.RecursiveEvidence + type: {β : Type u} → + Model.Environment β → + Certified.Ordinary.Shape β → Certified.Ordinary.Constructor β → Certified.Ordinary.RecursiveField β → Prop + definition: fun {β} entries shape ctor field => + (∀ (e : Model.AExpr β), e ∈ field.domains ++ field.indices → Model.AExpr.ReferencesIn entries e) ∧ + Model.Telescope.Formed entries (ctor.context shape) field.domains ∧ + Certified.TelescopeBound entries (ctor.context shape) field.domains (some shape.level) ∧ + Certified.ArgumentsFit entries (Model.Telescope.context (ctor.context shape) field.domains) + (Model.Telescope.lift (ctor.fields.length + field.domains.length) shape.indices) field.indices +premise definition Ix.Theory.Certified.Ordinary.LargeEvidence + type: {β : Type u} → Model.Environment β → Certified.Ordinary.Shape β → Prop + definition: fun {β} entries shape => + (∀ (levels : List Nat), VLevel.eval levels shape.level ≠ 0) ∨ + shape.constructors = [] ∨ + ∃ ctor, + shape.constructors = [ctor] ∧ Certified.TelescopeProp entries shape.parameterContext ctor.fields shape.level +premise definition Ix.Theory.Certified.Ordinary.Shape.container + type: {β : Type u} → + {V : Type v} → + [Model.SetTheory V] → + Certified.Ordinary.Shape β → Model.Assignment β V → List Nat → (Nat → V) → Model.IndexedContainer V + definition: fun {β} {V} [Model.SetTheory V] shape constants levels env => + { indices := shape.indexSet constants levels env, + shapes := fun i => + Model.SetTheory.sep (shape.allShapes constants levels env) fun a => shape.resultIndex constants levels env a = i, + positions := shape.positions constants levels env, target := shape.targetIndex constants levels env } +premise constructor Ix.Theory.Certified.Ordinary.FamilyReading.mk + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {source : β} {constants reading : Model.Assignment β V}, + Model.Assignment.AgreesOn entries constants reading → + (∀ (levels : List Nat), + levels.length = shape.universes → + reading (ConstRef.member source 0) levels = shape.familyValue constants levels) → + Certified.Ordinary.FamilyReading entries shape source constants reading +premise constructor Ix.Theory.Certified.Ordinary.ConstructorReading.mk + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {source : β} {constants reading : Model.Assignment β V}, + Certified.Ordinary.FamilyReading entries shape source constants reading → + (∀ (levels : List Nat), + levels.length = shape.universes → + ∀ (i : Nat) (ctor : Certified.Ordinary.Constructor β), + shape.constructors[i]? = some ctor → + reading (ConstRef.ctor source 0 i) levels = shape.constructorClosedValue constants levels i ctor) → + Certified.Ordinary.ConstructorReading entries shape source constants reading +premise constructor Ix.Theory.Certified.Ordinary.RecursorReading.mk + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {entries : Model.Environment β} + {shape : Certified.Ordinary.Shape β} {source recursor : β} {mode : Inductive.ElimMode} + {constants reading : Model.Assignment β V}, + Certified.Ordinary.ConstructorReading entries shape source constants reading → + (∀ (levels : List Nat), + levels.length = mode.recUvars shape.universes → + reading (ConstRef.member recursor 0) levels = shape.closedRecursorValue constants levels mode) → + Certified.Ordinary.RecursorReading entries shape source recursor mode constants reading +premise definition Ix.Theory.Certified.Ordinary.ModeEvidence + type: {β : Type u} → Model.Environment β → Certified.Ordinary.Shape β → Inductive.ElimMode → Prop + definition: fun {β} entries shape x => + match x with + | Inductive.ElimMode.small => True + | Inductive.ElimMode.large => Certified.Ordinary.LargeEvidence entries shape +premise definition Ix.Theory.Certified.Ordinary.Shape.ConstructorFormation + type: {β : Type u} → [DecidableEq β] → Model.Environment β → Certified.Ordinary.Shape β → β → Prop + definition: fun {β} [DecidableEq β] entries shape source => + ∀ (ctor : Certified.Ordinary.Constructor β), + ctor ∈ shape.constructors → + Model.EntryClosed (shape.familyEnvironment entries source) (shape.constructorEntry source ctor) ∧ + ∃ l, Model.TypingClaim (shape.familyEnvironment entries source) [] (ctor.type shape source) (Model.AExpr.sort l) +premise constructor Ix.Theory.Certified.Ordinary.Shape.RecursorFormation.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} + {shape : Certified.Ordinary.Shape β} {source recursor : β} {mode : Inductive.ElimMode}, + shape.RecursorSourceMatches store source recursor mode → + shape.constructorEnvironment entries source (ConstRef.member recursor 0) = none → + Model.EntryClosed (shape.constructorEnvironment entries source) (shape.recursorEntry source mode) → + (∃ l, + Model.TypingClaim (shape.constructorEnvironment entries source) [] (shape.recursorType source mode) + (Model.AExpr.sort l)) → + Certified.Ordinary.Shape.RecursorFormation entries store shape source recursor mode +premise definition Ix.Theory.Certified.Ordinary.Shape.SupportsK + type: {β : Type u} → Certified.Ordinary.Shape β → Prop + definition: fun {β} shape => + shape.level = VLevel.zero ∧ ∃ ctor, shape.constructors = [ctor] ∧ ctor.fields = [] ∧ ctor.recursive = [] +premise definition Ix.Theory.Certified.Ordinary.Shape.RecursorSourceMatches + type: {β : Type u} → Certified.Ordinary.Shape β → Store β → β → β → Inductive.ElimMode → Prop + definition: fun {β} shape store source recursor mode => + store.blocks recursor = some { members := [shape.recursorSource source recursor mode] } ∨ + shape.SupportsK ∧ store.blocks recursor = some { members := [shape.recursorSource source recursor mode true] } +premise constructor Ix.Theory.Certified.Ordinary.Shape.RuleFormation.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {shape : Certified.Ordinary.Shape β} {source recursor : β} + {mode : Inductive.ElimMode} {i : Nat} {ctor : Certified.Ordinary.Constructor β}, + Model.AExpr.Scope (mode.recUvars shape.universes) 0 (shape.ruleLhs source recursor mode i ctor) ∧ + Model.AExpr.Scope (mode.recUvars shape.universes) 0 (shape.ruleRhs source recursor mode i ctor) → + Model.AExpr.ReferencesIn entries (shape.ruleLhs source recursor mode i ctor) ∧ + Model.AExpr.ReferencesIn entries (shape.ruleRhs source recursor mode i ctor) → + (∃ l, + Model.TypingClaim entries [] (shape.ruleType source mode i ctor) (Model.AExpr.sort l) ∧ + (mode = Inductive.ElimMode.small → ∀ (levels : List Nat), VLevel.eval levels l = 0)) → + Model.TypingClaim entries [] (shape.ruleLhs source recursor mode i ctor) (shape.ruleType source mode i ctor) → + Model.TypingClaim entries [] (shape.ruleRhs source recursor mode i ctor) (shape.ruleType source mode i ctor) → + Certified.Ordinary.Shape.RuleFormation entries shape source recursor mode i ctor +premise constructor Ix.Theory.Certified.Ordinary.CheckedBlock.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} {source recursor : β} + {shape : Certified.Ordinary.Shape β} {mode : Inductive.ElimMode}, + Certified.Ordinary.CheckedShape entries store source shape → + Certified.Ordinary.Shape.ConstructorFormation entries shape source → + Certified.Ordinary.Shape.RecursorFormation entries store shape source recursor mode → + Certified.Ordinary.ModeEvidence entries shape mode → + (∀ (i : Nat) (ctor : Certified.Ordinary.Constructor β), + shape.constructors[i]? = some ctor → + Certified.Ordinary.Shape.RuleFormation (shape.recursorEnvironment entries source recursor mode) shape + source recursor mode i ctor) → + Certified.Ordinary.CheckedBlock entries store source recursor shape mode +premise definition Ix.Theory.Certified.Ordinary.EntrySource + type: {β : Type u} → Store β → ConstRef β → Model.ConstantEntry β → Prop + definition: fun {β} store r entry => + ∃ shape source recursor mode, + store.blocks source = some { members := [shape.source source] } ∧ + shape.RecursorSourceMatches store source recursor mode ∧ + (r = ConstRef.member source 0 ∧ entry = shape.familyEntry ∨ + (∃ i ctor, + shape.constructors[i]? = some ctor ∧ + r = ConstRef.ctor source 0 i ∧ entry = shape.constructorEntry source ctor) ∨ + r = ConstRef.member recursor 0 ∧ entry = shape.publishedRecursorEntry source recursor mode) +premise definition Ix.Theory.Certified.Ordinary.Shape.recursorAt + type: {β : Type u} → + {V : Type v} → + [Model.SetTheory V] → + Certified.Ordinary.Shape β → Model.Assignment β V → List Nat → (Nat → V) → Inductive.ElimMode → V → List V → V + definition: fun {β} {V} [Model.SetTheory V] shape constants levels env mode m minors => + match mode with + | Inductive.ElimMode.small => Model.SetTheory.pt + | Inductive.ElimMode.large => + if hD : + (shape.container constants (mode.sourceArgs levels) env).WF + (VLevel.eval (mode.sourceArgs levels) shape.level) then + if hlarge : + (shape.container constants (mode.sourceArgs levels) env).LargeElim + (VLevel.eval (mode.sourceArgs levels) shape.level) then + shape.largeValue constants (mode.sourceArgs levels) env (VLevel.eval levels mode.motiveLevel) m minors hD hlarge + else Model.SetTheory.pt + else Model.SetTheory.pt +premise constructor Ix.Theory.Certified.Ordinary.BlockWitness.mk + type: {β : Type u} → + β → + β → + Certified.Ordinary.ShapeWitness β → + Inductive.ElimMode → + List (Certified.Ordinary.Shape.TypeWitness β) → + Certified.Ordinary.Shape.TypeWitness β → + List (Certified.Ordinary.RuleWitness β) → Certified.Ordinary.BlockWitness β +premise constructor Ix.Theory.Certified.DeclarationWitness.definition + type: {β : Type u} → Certified.DefinitionWitness β → Certified.DeclarationWitness β +premise constructor Ix.Theory.Certified.DeclarationWitness.ordinary + type: {β : Type u} → Certified.Ordinary.BlockWitness β → Certified.DeclarationWitness β +premise constructor Ix.Theory.Certified.DeclarationWitness.standard + type: {β : Type u} → Certified.Standard.Witness β → Certified.DeclarationWitness β +premise constructor Ix.Theory.Certified.DeclarationWitness.quotient + type: {β : Type u} → Certified.Quotient.Witness β → Certified.DeclarationWitness β +premise constructor Ix.Theory.Certified.DeclarationWitness.structure + type: {β : Type u} → Certified.Structure.Witness β → Certified.DeclarationWitness β +premise constructor Ix.Theory.Certified.DeclarationWitness.natural + type: {β : Type u} → Certified.Ordinary.BlockWitness β → Certified.DeclarationWitness β +premise definition Ix.Theory.Certified.Natural.shape + type: {β : Type u} → Certified.Ordinary.Shape β + definition: fun {β} => + { universes := 0, parameters := [], indices := [], level := VLevel.zero.succ, + constructors := [Certified.Natural.zeroConstructor, Certified.Natural.succConstructor] } +premise definition Ix.Theory.Certified.Natural.fact + type: {β : Type u} → β → Model.ConstantFact β + definition: fun {β} source => Model.ConstantFact.natural (ConstRef.ctor source 0 0) (ConstRef.ctor source 0 1) +premise definition Ix.Theory.Certified.Natural.entry + type: {β : Type u} → β → Model.ConstantEntry β + definition: fun {β} source => + have __src := Certified.Natural.shape.familyEntry; + { universes := __src.universes, type := __src.type, body := __src.body, equations := __src.equations, + facts := [Certified.Natural.fact source] } +premise definition Ix.Theory.Certified.Natural.environment + type: {β : Type u} → [DecidableEq β] → Model.Environment β → β → β → Inductive.ElimMode → Model.Environment β + definition: fun {β} [DecidableEq β] entries source recursor mode => + (Certified.Natural.shape.publishedEnvironment entries source recursor mode).insert (ConstRef.member source 0) + (Certified.Natural.entry source) +premise constructor Ix.Theory.Certified.Natural.Checked.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} {pin : ConstRef β} + {source recursor : β} {mode : Inductive.ElimMode}, + Certified.Ordinary.CheckedBlock entries store source recursor Certified.Natural.shape mode → + pin = ConstRef.member source 0 → + Model.ConstantFact.ReferencesIn (Certified.Natural.shape.publishedEnvironment entries source recursor mode) + (Certified.Natural.fact source) → + Certified.Natural.Checked entries store pin source recursor mode +premise definition Ix.Theory.Certified.Natural.EntrySource + type: {β : Type u} → Option (ConstRef β) → Store β → ConstRef β → Model.ConstantEntry β → Prop + definition: fun {β} pin store r e => + pin = some r ∧ + ∃ source recursor mode, + store.blocks source = some { members := [Certified.Natural.shape.source source] } ∧ + Certified.Natural.shape.RecursorSourceMatches store source recursor mode ∧ + r = ConstRef.member source 0 ∧ e = Certified.Natural.entry source +premise constructor Ix.Theory.Certified.Structure.Field.mk + type: {β : Type u} → Model.AExpr β → VLevel → Certified.Structure.Field β +premise constructor Ix.Theory.Certified.Structure.Description.mk + type: {β : Type u} → + Nat → List (Model.AExpr β) → List (Certified.Structure.Field β) → VLevel → Certified.Structure.Description β +premise definition Ix.Theory.Certified.Structure.Description.ordinary + type: {β : Type u} → Certified.Structure.Description β → Certified.Ordinary.Shape β + definition: fun {β} d => + { universes := d.universes, parameters := d.parameters, indices := [], level := d.level, + constructors := [d.constructor] } +premise constructor Ix.Theory.Certified.Structure.FieldsFormed.nil + type: ∀ {β : Type u} {entries : Model.Environment β} {w : VLevel} {Γ : Model.Context β}, + Certified.Structure.FieldsFormed entries w Γ [] +premise constructor Ix.Theory.Certified.Structure.FieldsFormed.cons + type: ∀ {β : Type u} {entries : Model.Environment β} {w : VLevel} {Γ : Model.Context β} + {field : Certified.Structure.Field β} {rest : List (Certified.Structure.Field β)}, + Model.TypingClaim entries Γ field.domain (Model.AExpr.sort field.level) → + (∀ (levels : List Nat), VLevel.eval levels w = 0 → VLevel.eval levels field.level = 0) → + Certified.Structure.FieldsFormed entries w (Model.Context.push field.domain Γ) rest → + Certified.Structure.FieldsFormed entries w Γ (field :: rest) +premise definition Ix.Theory.Certified.Structure.fieldResult + type: {β : Type u} → β → Nat → Certified.Structure.Field β → Model.AExpr β + definition: fun {β} source index field => + (Model.AExpr.liftN 1 field.domain index).instRev (Certified.Structure.projections source index) +premise definition Ix.Theory.Certified.Structure.Description.facts + type: {β : Type u} → Certified.Structure.Description β → β → List (Model.ConstantFact β) + definition: fun {β} d source => + List.map + (fun x => + match x with + | (field, i) => Model.ConstantFact.typed (d.projection source i field) (d.projectionType source i field)) + d.fields.zipIdx +premise definition Ix.Theory.Certified.Structure.Description.equations + type: {β : Type u} → Certified.Structure.Description β → β → List (Model.ConstantEquation β) + definition: fun {β} d source => + { lhs := d.etaLhs source, rhs := d.etaRhs source } :: + List.map + (fun x => + match x with + | (field, i) => { lhs := d.iotaLhs source i field, rhs := d.iotaRhs i field }) + d.fields.zipIdx +premise definition Ix.Theory.Certified.Structure.Description.iotaEnvironment + type: {β : Type u} → + [DecidableEq β] → + Certified.Structure.Description β → Model.Environment β → β → β → Inductive.ElimMode → Nat → Model.Environment β + definition: fun {β} [DecidableEq β] d entries source recursor mode count => + (d.ordinary.publishedEnvironment entries source recursor mode).insert (ConstRef.member source 0) + (have __src := d.factEntry source; + { universes := __src.universes, type := __src.type, body := __src.body, + equations := List.take count (List.drop 1 (d.equations source)), facts := __src.facts }) +premise definition Ix.Theory.Certified.Structure.Description.etaRule + type: {β : Type u} → Certified.Structure.Description β → β → Certified.Signature.Rule β + definition: fun {β} d source => + { universes := d.universes, + type := + Model.AExpr.forallN (Certified.zeroCondition d.level) (d.projectionDomains source) + (d.ordinary.familyApp source 1 []), + lhs := d.etaLhs source, rhs := d.etaRhs source } +premise definition Ix.Theory.Certified.Structure.Description.iotaRule + type: {β : Type u} → + Certified.Structure.Description β → β → Nat → Certified.Structure.Field β → Certified.Signature.Rule β + definition: fun {β} d source i field => + { universes := d.universes, + type := + Model.AExpr.forallN (Certified.zeroCondition field.level) (d.parameters ++ d.constructor.fields) + (Model.AExpr.liftN (d.fields.length - i) field.domain), + lhs := d.iotaLhs source i field, rhs := d.iotaRhs i field } +premise constructor Ix.Theory.Certified.Structure.FactsWitness.mk + type: {β : Type u} → + Certified.Structure.Description β → + Certified.Ordinary.BlockWitness β → + List (Certified.TypingWitness β) → List (Certified.DomainWitness β) → Certified.Structure.FactsWitness β +premise constructor Ix.Theory.Certified.Structure.Witness.mk + type: {β : Type u} → + Certified.Structure.FactsWitness β → + Certified.Signature.RuleWitness β → List (Certified.Signature.RuleWitness β) → Certified.Structure.Witness β +premise constructor Ix.Theory.Certified.Structure.FactsChecked.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} + {d : Certified.Structure.Description β} {source recursor : β} {mode : Inductive.ElimMode}, + Certified.Ordinary.CheckedBlock entries store source recursor d.ordinary mode → + Certified.Structure.FieldsFormed entries d.level d.ordinary.parameterContext d.fields → + Model.Telescope.Formed (d.ordinary.publishedEnvironment entries source recursor mode) [] + (d.projectionDomains source) → + (∀ (fact : Model.ConstantFact β), fact ∈ d.facts source → Model.ConstantFact.Scope d.universes fact) → + (∀ (fact : Model.ConstantFact β), + fact ∈ d.facts source → + Model.ConstantFact.ReferencesIn (d.ordinary.publishedEnvironment entries source recursor mode) fact) → + Certified.Structure.FactsChecked entries store d source recursor mode +premise constructor Ix.Theory.Certified.Structure.Checked.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} + {d : Certified.Structure.Description β} {source recursor : β} {mode : Inductive.ElimMode}, + Certified.Structure.FactsChecked entries store d source recursor mode → + Certified.Signature.RuleFormed (d.factEnvironment entries source recursor mode) (d.etaRule source) → + (∀ (field : Certified.Structure.Field β) (i : Nat), + (field, i) ∈ d.fields.zipIdx → + Certified.Signature.RuleFormed (d.iotaEnvironment entries source recursor mode i) + (d.iotaRule source i field)) → + Certified.Structure.Checked entries store d source recursor mode +premise definition Ix.Theory.Certified.Structure.EntrySource + type: {β : Type u} → Store β → ConstRef β → Model.ConstantEntry β → Prop + definition: fun {β} store r entry => + ∃ d source recursor mode, + store.blocks source = some { members := [d.ordinary.source source] } ∧ + d.ordinary.RecursorSourceMatches store source recursor mode ∧ + r = ConstRef.member source 0 ∧ entry = d.publishedEntry source +premise definition Ix.Theory.Model.Environment.HasType + type: {β : Type u} → Model.Environment β → ConstRef β → Nat → Model.AExpr β → Prop + definition: fun {β} entries ref n type => ∃ entry, entries ref = some entry ∧ entry.universes = n ∧ entry.type = type +premise constructor Ix.Theory.Certified.Basis.Equality.Interface.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {family refl recursor : ConstRef β}, + entries.HasType family 1 Certified.Basis.Equality.type → + entries.HasType refl 1 (Certified.Basis.Equality.reflType family) → + entries.HasType recursor 2 (Certified.Basis.Equality.recType family refl) → + Certified.Basis.Equality.Interface entries family refl recursor +premise definition Ix.Theory.Certified.Basis.Equality.shape + type: {β : Type u} → Certified.Ordinary.Shape β + definition: fun {β} => + { universes := 1, parameters := [Model.AExpr.sort (VLevel.param 0), Model.AExpr.bvar 0], + indices := [Model.AExpr.bvar 1], level := VLevel.zero, + constructors := [{ fields := [], recursive := [], indices := [Model.AExpr.bvar 0] }] } +premise definition Ix.Theory.Certified.Basis.Equality.type + type: {β : Type u} → Model.AExpr β + definition: fun {β} => + Model.AExpr.forallE Certified.PropWhen.never (Model.AExpr.sort (VLevel.param 0)) + (Model.AExpr.forallE Certified.PropWhen.never (Model.AExpr.bvar 0) + (Model.AExpr.forallE Certified.PropWhen.never (Model.AExpr.bvar 1) (Model.AExpr.sort VLevel.zero))) +premise definition Ix.Theory.Certified.Basis.Equality.reflType + type: {β : Type u} → ConstRef β → Model.AExpr β + definition: fun {β} family => + Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.sort (VLevel.param 0)) + (Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.bvar 0) + (Certified.Basis.Equality.applied family (VLevel.param 0) (Model.AExpr.bvar 1) (Model.AExpr.bvar 0) + (Model.AExpr.bvar 0))) +premise definition Ix.Theory.Certified.Basis.Equality.recType + type: {β : Type u} → ConstRef β → ConstRef β → Model.AExpr β + definition: fun {β} family refl => + Model.AExpr.forallE (Certified.PropWhen.param 0) (Model.AExpr.sort (VLevel.param 1)) + (Model.AExpr.forallE (Certified.PropWhen.param 0) (Model.AExpr.bvar 0) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + (Model.AExpr.forallE Certified.PropWhen.never (Model.AExpr.bvar 1) + (Model.AExpr.forallE Certified.PropWhen.never + (Certified.Basis.Equality.applied family (VLevel.param 1) (Model.AExpr.bvar 2) (Model.AExpr.bvar 1) + (Model.AExpr.bvar 0)) + (Model.AExpr.sort (VLevel.param 0)))) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + ((Model.AExpr.bvar 0).appN + [Model.AExpr.bvar 1, + Certified.Basis.Equality.reflexivity refl (VLevel.param 1) (Model.AExpr.bvar 2) (Model.AExpr.bvar 1)]) + (Model.AExpr.forallE (Certified.PropWhen.param 0) (Model.AExpr.bvar 3) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + (Certified.Basis.Equality.applied family (VLevel.param 1) (Model.AExpr.bvar 4) (Model.AExpr.bvar 3) + (Model.AExpr.bvar 0)) + ((Model.AExpr.bvar 3).appN [Model.AExpr.bvar 1, Model.AExpr.bvar 0])))))) +premise constructor Ix.Theory.Certified.Basis.Iff.Interface.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {family ctor recursor : ConstRef β}, + entries.HasType family 0 Certified.Basis.Iff.type → + entries.HasType ctor 0 (Certified.Basis.Iff.introType family) → + entries.HasType recursor 1 (Certified.Basis.Iff.recType family ctor) → + Certified.Basis.Iff.Interface entries family ctor recursor +premise definition Ix.Theory.Certified.Basis.Iff.shape + type: {β : Type u} → Certified.Ordinary.Shape β + definition: fun {β} => + { universes := 0, parameters := [Model.AExpr.sort VLevel.zero, Model.AExpr.sort VLevel.zero], indices := [], + level := VLevel.zero, constructors := [Certified.Basis.Iff.constructor] } +premise definition Ix.Theory.Certified.Basis.Iff.type + type: {β : Type u} → Model.AExpr β + definition: fun {β} => + Model.AExpr.forallE Certified.PropWhen.never (Model.AExpr.sort VLevel.zero) + (Model.AExpr.forallE Certified.PropWhen.never (Model.AExpr.sort VLevel.zero) (Model.AExpr.sort VLevel.zero)) +premise definition Ix.Theory.Certified.Basis.Iff.introType + type: {β : Type u} → ConstRef β → Model.AExpr β + definition: fun {β} family => + Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.sort VLevel.zero) + (Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.sort VLevel.zero) + (Model.AExpr.forallE Certified.PropWhen.always + (Certified.Basis.Iff.arrow (Model.AExpr.bvar 1) (Model.AExpr.bvar 0)) + (Model.AExpr.forallE Certified.PropWhen.always + (Certified.Basis.Iff.arrow (Model.AExpr.bvar 1) (Model.AExpr.bvar 2)) + (Certified.Basis.Iff.applied family (Model.AExpr.bvar 3) (Model.AExpr.bvar 2))))) +premise definition Ix.Theory.Certified.Basis.Iff.recType + type: {β : Type u} → ConstRef β → ConstRef β → Model.AExpr β + definition: fun {β} family ctor => + Model.AExpr.forallE (Certified.PropWhen.param 0) (Model.AExpr.sort VLevel.zero) + (Model.AExpr.forallE (Certified.PropWhen.param 0) (Model.AExpr.sort VLevel.zero) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + (Model.AExpr.forallE Certified.PropWhen.never + (Certified.Basis.Iff.applied family (Model.AExpr.bvar 1) (Model.AExpr.bvar 0)) + (Model.AExpr.sort (VLevel.param 0))) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + (Certified.Basis.Iff.arrow (Model.AExpr.bvar 2) (Model.AExpr.bvar 1)) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + (Certified.Basis.Iff.arrow (Model.AExpr.bvar 2) (Model.AExpr.bvar 3)) + ((Model.AExpr.bvar 2).app + (Certified.Basis.Iff.introduction ctor (Model.AExpr.bvar 4) (Model.AExpr.bvar 3) (Model.AExpr.bvar 1) + (Model.AExpr.bvar 0))))) + (Model.AExpr.forallE (Certified.PropWhen.param 0) + (Certified.Basis.Iff.applied family (Model.AExpr.bvar 3) (Model.AExpr.bvar 2)) + ((Model.AExpr.bvar 2).app (Model.AExpr.bvar 0)))))) +premise constructor Ix.Theory.Certified.Basis.Nonempty.Interface.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {family ctor recursor : ConstRef β}, + entries.HasType family 1 Certified.Basis.Nonempty.type → + entries.HasType ctor 1 (Certified.Basis.Nonempty.introType family) → + entries.HasType recursor 1 (Certified.Basis.Nonempty.recType family ctor) → + Certified.Basis.Nonempty.Interface entries family ctor recursor +premise definition Ix.Theory.Certified.Basis.Nonempty.shape + type: {β : Type u} → Certified.Ordinary.Shape β + definition: fun {β} => + { universes := 1, parameters := [Model.AExpr.sort (VLevel.param 0)], indices := [], level := VLevel.zero, + constructors := [Certified.Basis.Nonempty.constructor] } +premise definition Ix.Theory.Certified.Basis.Nonempty.type + type: {β : Type u} → Model.AExpr β + definition: fun {β} => + Model.AExpr.forallE Certified.PropWhen.never (Model.AExpr.sort (VLevel.param 0)) (Model.AExpr.sort VLevel.zero) +premise definition Ix.Theory.Certified.Basis.Nonempty.introType + type: {β : Type u} → ConstRef β → Model.AExpr β + definition: fun {β} family => + Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.sort (VLevel.param 0)) + (Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.bvar 0) + (Certified.Basis.Nonempty.applied family (VLevel.param 0) (Model.AExpr.bvar 1))) +premise definition Ix.Theory.Certified.Basis.Nonempty.recType + type: {β : Type u} → ConstRef β → ConstRef β → Model.AExpr β + definition: fun {β} family ctor => + Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.sort (VLevel.param 0)) + (Model.AExpr.forallE Certified.PropWhen.always + (Model.AExpr.forallE Certified.PropWhen.never + (Certified.Basis.Nonempty.applied family (VLevel.param 0) (Model.AExpr.bvar 0)) (Model.AExpr.sort VLevel.zero)) + (Model.AExpr.forallE Certified.PropWhen.always + (Model.AExpr.forallE Certified.PropWhen.always (Model.AExpr.bvar 1) + ((Model.AExpr.bvar 1).app + (Certified.Basis.Nonempty.introduction ctor (VLevel.param 0) (Model.AExpr.bvar 2) (Model.AExpr.bvar 0)))) + (Model.AExpr.forallE Certified.PropWhen.always + (Certified.Basis.Nonempty.applied family (VLevel.param 0) (Model.AExpr.bvar 2)) + ((Model.AExpr.bvar 2).app (Model.AExpr.bvar 0))))) +premise definition Ix.Theory.Certified.Standard.Spec.Prerequisites + type: {β : Type u} → Model.Environment β → Certified.Standard.Spec β → Prop + definition: fun {β} entries x => + match x with + | Certified.Standard.Spec.propext eq eqRefl eqRec iff iffIntro iffRec => + Certified.Basis.Equality.Interface entries eq eqRefl eqRec ∧ + Certified.Basis.Iff.Interface entries iff iffIntro iffRec + | Certified.Standard.Spec.choice nonempty intro recursor => + Certified.Basis.Nonempty.Interface entries nonempty intro recursor +premise definition Ix.Theory.Certified.Standard.Spec.type + type: {β : Type u} → Certified.Standard.Spec β → Model.AExpr β + definition: fun {β} x => + match x with + | Certified.Standard.Spec.propext eq eqRefl eqRec iff iffIntro iffRec => Certified.Standard.propextType eq iff + | Certified.Standard.Spec.choice nonempty intro recursor => Certified.Standard.choiceType nonempty +premise definition Ix.Theory.Certified.Standard.Spec.value + type: {β : Type u} → + {V : Type v} → [Model.SetTheory V] → Certified.Standard.Spec β → Model.Assignment β V → List Nat → V + definition: fun {β} {V} [Model.SetTheory V] spec constants levels => + match spec with + | Certified.Standard.Spec.propext eq eqRefl eqRec iff iffIntro iffRec => Model.SetTheory.pt + | Certified.Standard.Spec.choice nonempty intro recursor => + Certified.Standard.choiceValue constants nonempty (levels.getD 0 0) +premise definition Ix.Theory.Certified.Standard.chooseSet + type: {V : Type v} → [Model.SetTheory V] → V → V + definition: fun {V} [Model.SetTheory V] A => + if h : ∃ a, Model.SetTheory.Mem a A then Classical.choose h else Model.SetTheory.empty +premise constructor Ix.Theory.Certified.Standard.Witness.mk + type: {β : Type u} → + ConstRef β → Certified.Standard.Spec β → VLevel → Certified.TypingWitness β → Certified.Standard.Witness β +premise constructor Ix.Theory.Certified.Standard.Checked.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {store : Store β} {witness : Certified.Standard.Witness β}, + store.lookup witness.ref = some witness.spec.source → + entries witness.ref = none → + Certified.Standard.Spec.Prerequisites entries witness.spec → + Model.AExpr.Scope witness.spec.universes 0 witness.spec.type → + Model.AExpr.ReferencesIn entries witness.spec.type → + Model.TypingClaim entries [] witness.spec.type (Model.AExpr.sort witness.level) → + Certified.Standard.Checked entries store witness +premise definition Ix.Theory.Certified.Standard.EntrySource + type: {β : Type u} → Store β → ConstRef β → Model.ConstantEntry β → Prop + definition: fun {β} store ref entry => ∃ spec, store.lookup ref = some spec.source ∧ entry = spec.entry +premise constructor Ix.Theory.Certified.Signature.Header.mk + type: {β : Type u} → ConstRef β → Nat → Model.AExpr β → Certified.Signature.Header β +premise constructor Ix.Theory.Certified.Signature.Formed.nil + type: ∀ {β : Type u} [inst : DecidableEq β] (entries : Model.Environment β), Certified.Signature.Formed entries [] +premise constructor Ix.Theory.Certified.Signature.Formed.cons + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {header : Certified.Signature.Header β} + {rest : List (Certified.Signature.Header β)}, + entries header.ref = none → + Model.AExpr.Scope header.universes 0 header.type → + Model.AExpr.ReferencesIn entries header.type → + ∀ {level : VLevel}, + Model.TypingClaim entries [] header.type (Model.AExpr.sort level) → + Certified.Signature.Formed (entries.insert header.ref header.entry) rest → + Certified.Signature.Formed entries (header :: rest) +premise constructor Ix.Theory.Certified.Signature.TypeWitness.mk + type: {β : Type u} → VLevel → Certified.TypingWitness β → Certified.Signature.TypeWitness β +premise constructor Ix.Theory.Certified.Signature.Rule.mk + type: {β : Type u} → Nat → Model.AExpr β → Model.AExpr β → Model.AExpr β → Certified.Signature.Rule β +premise constructor Ix.Theory.Certified.Signature.RuleFormed.mk + type: ∀ {β : Type u} {entries : Model.Environment β} {rule : Certified.Signature.Rule β}, + Model.AExpr.Scope rule.universes 0 rule.type ∧ + Model.AExpr.Scope rule.universes 0 rule.lhs ∧ Model.AExpr.Scope rule.universes 0 rule.rhs → + Model.AExpr.ReferencesIn entries rule.type ∧ + Model.AExpr.ReferencesIn entries rule.lhs ∧ Model.AExpr.ReferencesIn entries rule.rhs → + (∃ level, Model.TypingClaim entries [] rule.type (Model.AExpr.sort level)) → + Model.TypingClaim entries [] rule.lhs rule.type → + Model.TypingClaim entries [] rule.rhs rule.type → Certified.Signature.RuleFormed entries rule +premise constructor Ix.Theory.Certified.Signature.RuleWitness.mk + type: {β : Type u} → + VLevel → + Certified.TypingWitness β → + Certified.TypingWitness β → Certified.TypingWitness β → Certified.Signature.RuleWitness β +premise definition Ix.Theory.Model.SetTheory.quotSet + type: {V : Type u} → [Model.SetTheory V] → Nat → V → V → V + definition: fun {V} [Model.SetTheory V] u A R => + if u = 0 then Model.SetTheory.image (fun x => Model.SetTheory.pt) A + else Model.SetTheory.image (fun a => Model.SetTheory.qclass A R a) A +premise definition Ix.Theory.Model.SetTheory.quotClass + type: {V : Type u} → [Model.SetTheory V] → Nat → V → V → V → V + definition: fun {V} [Model.SetTheory V] u A R a => if u = 0 then Model.SetTheory.pt else Model.SetTheory.qclass A R a +premise definition Ix.Theory.Model.SetTheory.qrep + type: {V : Type u} → [Model.SetTheory V] → Nat → V → V → V → V + definition: fun {V} [Model.SetTheory V] u A R q => + if h : ∃ a, Model.SetTheory.Mem a A ∧ q = Model.SetTheory.quotClass u A R a then Classical.choose h + else Model.SetTheory.empty +premise constructor Ix.Theory.Model.SetTheory.QuotRel.base + type: ∀ {V : Type u} [inst : Model.SetTheory V] {A R a b : V}, + Model.SetTheory.Mem a A → + Model.SetTheory.Mem b A → + (∃ w, Model.SetTheory.Mem w (Model.SetTheory.app (Model.SetTheory.app R a) b)) → Model.SetTheory.QuotRel A R a b +premise constructor Ix.Theory.Model.SetTheory.QuotRel.refl + type: ∀ {V : Type u} [inst : Model.SetTheory V] {A R a : V}, Model.SetTheory.Mem a A → Model.SetTheory.QuotRel A R a a +premise constructor Ix.Theory.Model.SetTheory.QuotRel.symm + type: ∀ {V : Type u} [inst : Model.SetTheory V] {A R a b : V}, + Model.SetTheory.QuotRel A R a b → Model.SetTheory.QuotRel A R b a +premise constructor Ix.Theory.Model.SetTheory.QuotRel.trans + type: ∀ {V : Type u} [inst : Model.SetTheory V] {A R a b c : V}, + Model.SetTheory.QuotRel A R a b → Model.SetTheory.QuotRel A R b c → Model.SetTheory.QuotRel A R a c +premise constructor Ix.Theory.Certified.Quotient.Refs.mk + type: {β : Type u} → Store.QuotRefs β → ConstRef β → ConstRef β → ConstRef β → Certified.Quotient.Refs β +premise definition Ix.Theory.Certified.Quotient.Refs.ExactSource + type: {β : Type u} → Certified.Quotient.Refs β → Store β → Prop + definition: fun {β} refs store => + ∀ (kind : Certified.Quotient.Kind), + kind ∈ Certified.Quotient.kinds → store.lookup (refs.ref kind) = some (refs.source kind) +premise definition Ix.Theory.Certified.Quotient.Refs.environment + type: {β : Type u} → [DecidableEq β] → Certified.Quotient.Refs β → Model.Environment β → Model.Environment β + definition: fun {β} [DecidableEq β] refs entries r => + match refs.kind? r with + | some kind => some (refs.entry kind) + | none => entries r +premise definition Ix.Theory.Certified.Quotient.Refs.assignment + type: {β : Type u} → + [DecidableEq β] → + {V : Type v} → [Model.SetTheory V] → Certified.Quotient.Refs β → Model.Assignment β V → Model.Assignment β V + definition: fun {β} [DecidableEq β] {V} [Model.SetTheory V] refs constants r levels => + match refs.kind? r with + | some kind => refs.value constants kind levels + | none => constants r levels +premise definition Ix.Theory.Certified.Quotient.Refs.entryType + type: {β : Type u} → Certified.Quotient.Refs β → Certified.Quotient.Kind → Model.AExpr β + definition: fun {β} refs x => + match x with + | Certified.Quotient.Kind.type => Certified.Quotient.typeType + | Certified.Quotient.Kind.ctor => Certified.Quotient.ctorType refs + | Certified.Quotient.Kind.lift => Certified.Quotient.liftType refs + | Certified.Quotient.Kind.ind => Certified.Quotient.indType refs + | Certified.Quotient.Kind.sound => Certified.Quotient.soundType refs +premise definition Ix.Theory.Certified.Quotient.Refs.source + type: {β : Type u} → Certified.Quotient.Refs β → Certified.Quotient.Kind → Const β + definition: fun {β} refs x => + match x with + | Certified.Quotient.Kind.type => Const.quot Ix.Theory.QuotKind.type 1 Certified.Quotient.typeType.erase + | Certified.Quotient.Kind.ctor => Const.quot Ix.Theory.QuotKind.ctor 1 (Certified.Quotient.ctorType refs).erase + | Certified.Quotient.Kind.lift => Const.quot Ix.Theory.QuotKind.lift 2 (Certified.Quotient.liftType refs).erase + | Certified.Quotient.Kind.ind => Const.quot Ix.Theory.QuotKind.ind 1 (Certified.Quotient.indType refs).erase + | Certified.Quotient.Kind.sound => Const.axiom 1 (Certified.Quotient.soundType refs).erase Safety.safe +premise definition Ix.Theory.Certified.Quotient.Refs.equations + type: {β : Type u} → Certified.Quotient.Refs β → Certified.Quotient.Kind → List (Model.ConstantEquation β) + definition: fun {β} refs x => + match x with + | Certified.Quotient.Kind.lift => + [{ lhs := Certified.Quotient.liftRuleLhs refs, rhs := Certified.Quotient.liftRuleRhs refs }] + | Certified.Quotient.Kind.ind => + [{ lhs := Certified.Quotient.indRuleLhs refs, rhs := Certified.Quotient.indRuleRhs refs }] + | x => [] +premise constructor Ix.Theory.Certified.Quotient.Reading.mk + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {constants : Model.Assignment β V} + {refs : Certified.Quotient.Refs β}, + (∀ (u : Nat), constants refs.type [u] = Certified.Quotient.formerValue u) → + (∀ (u : Nat), constants refs.ctor [u] = Certified.Quotient.constructorValue u) → + (∀ (u v : Nat), constants refs.lift [u, v] = Certified.Quotient.liftValue constants refs.eq u v) → + (∀ (u : Nat), constants refs.ind [u] = Model.SetTheory.pt) → + (∀ (u : Nat), constants refs.sound [u] = Model.SetTheory.pt) → Certified.Quotient.Reading constants refs +premise constructor Ix.Theory.Certified.Quotient.Witness.mk + type: {β : Type u} → + Certified.Quotient.Refs β → + List (Certified.Signature.TypeWitness β) → + Certified.Signature.RuleWitness β → Certified.Signature.RuleWitness β → Certified.Quotient.Witness β +premise constructor Ix.Theory.Certified.Quotient.Checked.mk + type: ∀ {β : Type u} [inst : DecidableEq β] {entries : Model.Environment β} {store : Store β} + {refs : Certified.Quotient.Refs β}, + refs.ExactSource store → + refs.Fresh entries → + Certified.Basis.Equality.Interface entries refs.eq refs.eqRefl refs.eqRec → + Certified.Signature.Formed entries refs.headers → + Certified.Signature.RuleFormed (refs.typeEnvironment entries) refs.liftRule → + Certified.Signature.RuleFormed (refs.typeEnvironment entries) refs.indRule → + Certified.Quotient.Checked entries store refs +premise definition Ix.Theory.Certified.Quotient.EntrySource + type: {β : Type u} → Store β → ConstRef β → Model.ConstantEntry β → Prop + definition: fun {β} store r entry => ∃ refs kind, refs.ExactSource store ∧ r = refs.ref kind ∧ entry = refs.entry kind +premise definition Ix.Theory.Certified.Quotient.formerValue + type: {V : Type v} → [Model.SetTheory V] → Nat → V + definition: fun {V} [Model.SetTheory V] u => + Model.SetModel.lamR 1 (Model.SetTheory.univ u) fun A => + Model.SetModel.lamR 1 (Certified.Quotient.relationSet A) fun R => Model.SetTheory.quotSet u A R +premise definition Ix.Theory.Certified.Quotient.constructorValue + type: {V : Type v} → [Model.SetTheory V] → Nat → V + definition: fun {V} [Model.SetTheory V] u => + Model.SetModel.lamR (Certified.Quotient.bit u) (Model.SetTheory.univ u) fun A => + Model.SetModel.lamR (Certified.Quotient.bit u) (Certified.Quotient.relationSet A) fun R => + Model.SetModel.lamR (Certified.Quotient.bit u) A fun a => Model.SetTheory.quotClass u A R a +premise definition Ix.Theory.Certified.Quotient.liftValue + type: {β : Type u} → {V : Type v} → [Model.SetTheory V] → Model.Assignment β V → ConstRef β → Nat → Nat → V + definition: fun {β} {V} [Model.SetTheory V] constants eq u v => + Model.SetModel.lamR (Certified.Quotient.bit v) (Model.SetTheory.univ u) fun A => + Model.SetModel.lamR (Certified.Quotient.bit v) (Certified.Quotient.relationSet A) fun R => + Model.SetModel.lamR (Certified.Quotient.bit v) (Model.SetTheory.univ v) fun B => + Model.SetModel.lamR (Certified.Quotient.bit v) (Model.SetModel.piR (Certified.Quotient.bit v) A fun x => B) + fun f => + Model.SetModel.lamR (Certified.Quotient.bit v) (Certified.Quotient.invariantSet constants eq v A R B f) + fun x => + Model.SetModel.lamR (Certified.Quotient.bit v) (Model.SetTheory.quotSet u A R) fun q => + Model.SetTheory.app f (Model.SetTheory.qrep u A R q) +premise constructor Ix.Theory.Certified.PrimitiveSignature.Compatible.mk + type: ∀ {β : Type u} {V : Type v} [inst : Model.SetTheory V] {signature : Certified.PrimitiveSignature β} + {entries : Model.Environment β} {constants : Model.Assignment β V}, + Model.Realizes constants entries → + (∀ (levels : List Nat), constants signature.falseType levels = Model.SetTheory.empty) → + (∀ (levels : List Nat), constants signature.falseElim levels = Model.falseElimValue (levels.getD 0 0)) → + signature.Compatible entries constants +premise definition Ix.Theory.Certified.EntrySource + type: {β : Type u} → Certified.PrimitiveSignature β → Store β → ConstRef β → Model.ConstantEntry β → Prop + definition: fun {β} signature store r entry => + r = signature.falseType ∧ + entry = Certified.PrimitiveSignature.falseEntry ∧ + store.lookup r = some Certified.PrimitiveSignature.falseDeclaration ∨ + r = signature.falseElim ∧ entry = signature.falseElimEntry ∧ store.lookup r = some signature.falseElimDeclaration ∨ + (∃ kind body, + entry.body = some body ∧ + entry.equations = [] ∧ + entry.facts = [] ∧ + store.lookup r = some (Const.defn entry.universes kind entry.type.erase body.erase Safety.safe)) ∨ + Certified.Ordinary.EntrySource store r entry ∨ + Certified.Standard.EntrySource store r entry ∨ + Certified.Quotient.EntrySource store r entry ∨ + Certified.Structure.EntrySource store r entry ∨ + Certified.Natural.EntrySource signature.natType store r entry ∨ + Certified.Modeled.EntrySource store r entry +premise constructor Ix.Theory.Certified.Extends.mk + type: ∀ {β : Type u} {signature : Certified.PrimitiveSignature β} {entries entries' : Model.Environment β}, + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), entries r = some entry → entries' r = some entry) → + (∀ (V : Type v) [inst : Model.SetTheory V] (constants : Model.Assignment β V), + signature.Compatible entries constants → + ∃ constants', + signature.Compatible entries' constants' ∧ Model.Assignment.AgreesOn entries constants constants') → + Certified.Extends signature entries entries' +premise constructor Ix.Theory.Certified.AdmittedEnvironment.mk + type: {β : Type u} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (entries : Model.Environment β) → + entries.WF → + signature.Present entries → + (∀ (r : ConstRef β) (entry : Model.ConstantEntry β), + entries r = some entry → Certified.EntrySource signature store r entry) → + (∀ (V : Type v) [inst : Model.SetTheory V], ∃ constants, signature.Compatible entries constants) → + Certified.AdmittedEnvironment signature store +premise constructor Ix.Theory.Certified.CheckedClaim.mk + type: {claim : Prop} → claim → Certified.CheckedClaim claim +premise constructor Ix.Theory.Certified.InferenceResult.mk + type: {β : Type u} → + {entries : Model.Environment β} → + {n : Nat} → + {Γ : Model.Context β} → + {source : VExpr β} → + (reading : Model.Reading n (List.length Γ) source) → + (type : Model.AExpr β) → + Model.AExpr.Scope n (List.length Γ) type → + Model.TypingClaim entries Γ reading.val type → Certified.InferenceResult entries n Γ source +premise constructor Ix.Theory.Certified.WhnfResult.mk + type: {β : Type u} → + {entries : Model.Environment β} → + {n : Nat} → + {Γ : Model.Context β} → + {source : VExpr β} → + (input : Certified.InferenceResult entries n Γ source) → + (result : Model.AExpr β) → + Model.AExpr.Scope n (List.length Γ) result → + Certified.whnfShape entries result = true → + Model.TypingClaim entries Γ result input.type → + Model.ConversionClaim entries Γ input.reading.val result → Certified.WhnfResult entries n Γ source +premise constructor Ix.Theory.Store.mk + type: {β : Type u} → + (dom : List β) → + dom.Nodup → (blocks : β → Option (Block β)) → (∀ (b : β), (blocks b).isSome = true ↔ b ∈ dom) → Store β +premise constructor Ix.Theory.Certified.ProofInput.mk + type: {β : Type u} → Store β → Nat → VExpr β → VExpr β → Certified.ProofInput β +premise constructor Ix.Theory.Certified.ProofWitness.mk + type: {β : Type u} → + List (Certified.DeclarationWitness β) → + Model.AnnotationTree → + Model.AnnotationTree → Certified.TypingWitness β → Certified.TypingWitness β → Certified.ProofWitness β +premise constructor Ix.Theory.Certified.CheckedProof.mk + type: {β : Type u} → + {signature : Certified.PrimitiveSignature β} → + {input : Certified.ProofInput β} → + (environment : Certified.AdmittedEnvironment signature input.store) → + (proof : Model.Reading input.universes 0 input.proof) → + (proposition : Model.Reading input.universes 0 input.proposition) → + Model.AExpr.ReferencesIn environment.entries proof.val → + Model.AExpr.ReferencesIn environment.entries proposition.val → + Model.TypingClaim environment.entries [] proof.val proposition.val → + Model.TypingClaim environment.entries [] proposition.val (Model.AExpr.sort VLevel.zero) → + Certified.CheckedProof signature input +compiler recursion worker Ix.Theory.Certified.admitDefinitions?._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (state : Certified.AdmittedEnvironment signature store) → + List (Certified.DefinitionWitness β) → + Option { result // Certified.Extends signature state.entries result.entries } + implementation: fun {β} [DecidableEq β] fuel {signature} {store} state x => + match x with + | [] => some ⟨state, ⋯⟩ + | witness :: rest => do + let step ← Certified.admitDefinition? fuel state witness + let rest ← Certified.admitDefinitions?._unsafe_rec fuel step.val rest + pure ⟨rest.val, ⋯⟩ +compiler recursion worker Ix.Theory.Certified.checkDeclarationExtensions?._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (state : Certified.CheckedInterface signature) → + List (Certified.DeclarationWitness β) → Option (Certified.CheckedExtension signature store state) + implementation: fun {β} [DecidableEq β] fuel {signature} {store} state x => + match x with + | [] => some (Certified.CheckedExtension.refl state) + | witness :: rest => do + let step ← Certified.checkDeclarationExtension? fuel state witness + let rest ← Certified.checkDeclarationExtensions?._unsafe_rec fuel step.result rest + pure (step.trans rest) +compiler recursion worker Ix.Theory.Certified.replayDeclarations?._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (state : Certified.CheckedInterface signature) → + List (Certified.DeclarationWitness β) → Option (Certified.CheckedExtension signature store state) + implementation: fun {β} [DecidableEq β] fuel {signature} {store} state x => + match x with + | [] => some (Certified.CheckedExtension.refl state) + | witness :: rest => + have __do_jp := fun step => do + let rest ← Certified.replayDeclarations?._unsafe_rec fuel step.result rest + pure (step.trans rest); + if (witness.outputs.all fun ref => (state.entries ref).isSome) = true then do + let step ← some (Certified.CheckedExtension.refl state) + __do_jp step + else do + let step ← Certified.checkDeclarationExtension? fuel state witness + __do_jp step +compiler recursion worker Ix.Theory.Certified.replayNodes?._unsafe_rec + type: {β : Type u} → + [inst : DecidableEq β] → + {fuel : Nat} → + {signature : Certified.PrimitiveSignature β} → + {store : Store β} → + (state : Certified.CheckedInterface signature) → + (known : List (ConstRef β)) → + (nodes : List (Certified.CheckedNode fuel signature store)) → + Option (Certified.ReplayResult state known nodes) + implementation: fun {β} [DecidableEq β] {fuel} {signature} {store} state known x => + match x with + | [] => some { checked := Certified.CheckedExtension.refl state, order := ⋯, subjects := ⋯, frontiers := ⋯ } + | node :: nodes => + if available : (node.receipt.frontier.refs.all fun x => known.contains x) = true then + if aligned : + (node.receipt.frontier.headers.all fun h => decide (Certified.HeaderPresent state.entries h)) = true then do + let step ← Certified.replayDeclarations? fuel state node.input.declarations + if present : (node.input.subjects.all fun ref => (step.result.entries ref).isSome) = true then do + let tail ← Certified.replayNodes?._unsafe_rec step.result (known ++ node.input.subjects) nodes + pure { checked := step.trans tail.checked, order := ⋯, subjects := ⋯, frontiers := ⋯ } + else none + else none + else none +compiler recursion worker Ix.Theory.Certified.verifyArguments._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Model.Environment β) → + (Γ : Model.Context β) → + (domains args : List (Model.AExpr β)) → + List (Certified.TypingWitness β) → + Option (Certified.CheckedClaim (Certified.ArgumentsFit entries Γ domains args)) + implementation: fun {β} [DecidableEq β] fuel n entries Γ x x_1 x_2 => + match x, x_1, x_2 with + | [], [], [] => some { down := ⋯ } + | A :: domains, a :: args, witness :: witnesses => do + let ha ← Certified.verifyType fuel n entries Γ a A witness + let hrest ← Certified.verifyArguments._unsafe_rec fuel n entries Γ (Model.Telescope.inst a domains) args witnesses + pure { down := ⋯ } + | x, x_3, x_4 => none +compiler recursion worker Ix.Theory.Certified.verifyConversion._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Model.Environment β) → + (Γ : Model.Context β) → + (a b : Model.AExpr β) → + Certified.ConversionWitness β → Option (Certified.CheckedClaim (Model.ConversionClaim entries Γ a b)) + implementation: fun {β} [inst : DecidableEq β] fuel n entries Γ a b witness => + match fuel with + | 0 => none + | fuel.succ => + if Model.AExpr.Scope n (List.length Γ) a ∧ Model.AExpr.Scope n (List.length Γ) b then + match a, b, witness with + | a, b, Certified.ConversionWitness.refl => if h : a = b then some { down := ⋯ } else none + | a, b, w.symm => do + let h ← Certified.verifyConversion._unsafe_rec fuel n entries Γ b a w + pure { down := ⋯ } + | a, b, Certified.ConversionWitness.trans c w₁ w₂ => do + let h₁ ← Certified.verifyConversion._unsafe_rec fuel n entries Γ a c w₁ + let h₂ ← Certified.verifyConversion._unsafe_rec fuel n entries Γ c b w₂ + pure { down := ⋯ } + | f.app a, f'.app a', wf.app wa => do + let hf ← Certified.verifyConversion._unsafe_rec fuel n entries Γ f f' wf + let ha ← Certified.verifyConversion._unsafe_rec fuel n entries Γ a a' wa + pure { down := ⋯ } + | Model.AExpr.proj r i a, Model.AExpr.proj r' i' b, w.proj => + if hr : r = r' then + if hi : i = i' then do + let h ← Certified.verifyConversion._unsafe_rec fuel n entries Γ a b w + pure { down := ⋯ } + else none + else none + | Model.AExpr.lam p D body, Model.AExpr.lam p' D' body', Certified.ConversionWitness.lam lD wD wd wb => + if hp : p = p' then do + let hD ← Certified.verifyType._unsafe_rec fuel n entries Γ D (Model.AExpr.sort lD) wD + let hd ← Certified.verifyConversion._unsafe_rec fuel n entries Γ D D' wd + let hb ← Certified.verifyConversion._unsafe_rec fuel n entries (Model.Context.push D Γ) body body' wb + pure { down := ⋯ } + else none + | Model.AExpr.forallE p D B, Model.AExpr.forallE p' D' B', Certified.ConversionWitness.forallE lD wD wd wb => + if hp : p = p' then do + let hD ← Certified.verifyType._unsafe_rec fuel n entries Γ D (Model.AExpr.sort lD) wD + let hd ← Certified.verifyConversion._unsafe_rec fuel n entries Γ D D' wd + let hb ← Certified.verifyConversion._unsafe_rec fuel n entries (Model.Context.push D Γ) B B' wb + pure { down := ⋯ } + else none + | (Model.AExpr.lam p D body).app arg, result, Certified.ConversionWitness.beta T wl wa => + if hr : result = body.inst arg then do + let hl ← Certified.verifyType._unsafe_rec fuel n entries Γ (Model.AExpr.lam p D body) T wl + let ha ← Certified.verifyType._unsafe_rec fuel n entries Γ arg D wa + pure { down := ⋯ } + else none + | Model.AExpr.lam p D body, f, Certified.ConversionWitness.eta B wf => + if hb : body = (Model.AExpr.liftN 1 f).app (Model.AExpr.bvar 0) then do + let hf ← Certified.verifyType._unsafe_rec fuel n entries Γ f (Model.AExpr.forallE p D B) wf + pure { down := ⋯ } + else none + | a, b, Certified.ConversionWitness.proofIrrel A wA wa wb => do + let hA ← Certified.verifyType._unsafe_rec fuel n entries Γ A (Model.AExpr.sort VLevel.zero) wA + let ha ← Certified.verifyType._unsafe_rec fuel n entries Γ a A wa + let hb ← Certified.verifyType._unsafe_rec fuel n entries Γ b A wb + pure { down := ⋯ } + | Model.AExpr.const r ls, b, Certified.ConversionWitness.delta => + match h : entries r with + | none => none + | some entry => + match h_1 : entry.body with + | none => none + | some body => + if hn : ls.length = entry.universes then + if hB : b = Model.AExpr.instL ls body then some { down := ⋯ } else none + else none + | Model.AExpr.sort l, Model.AExpr.sort l', Certified.ConversionWitness.sort => + if h : Certified.LevelEq.check n l l' = true then some { down := ⋯ } else none + | a, b, Certified.ConversionWitness.equation r index ls => + match h : entries r with + | none => none + | some entry => + match he : entry.equations[index]? with + | none => none + | some law => + if hn : ls.length = entry.universes then + if hls : ∀ (l : VLevel), l ∈ ls → VLevel.WF n l then + if ha : a = Model.AExpr.instL ls law.lhs then + if hb : b = Model.AExpr.instL ls law.rhs then some { down := ⋯ } else none + else none + else none + else none + | Model.AExpr.natLit value, result, Certified.ConversionWitness.natLiteral r index => + match h : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (Model.ConstantFact.natural zero succ) => + if hn : entry.universes = 0 then + match value with + | 0 => if he : result = Model.AExpr.const zero [] then some { down := ⋯ } else none + | value.succ => + if he : result = (Model.AExpr.const succ []).app (Model.AExpr.natLit value) then some { down := ⋯ } + else none + else none + | x => none + | x, x_1, x_2 => none + else none +compiler recursion worker Ix.Theory.Certified.verifyPropTelescope._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Model.Environment β) → + (atLevel : VLevel) → + (Γ : Model.Context β) → + (domains : List (Model.AExpr β)) → + List (Certified.DomainWitness β) → + Option (Certified.CheckedClaim (Certified.TelescopeProp entries Γ domains atLevel)) + implementation: fun {β} [DecidableEq β] fuel n entries atLevel x x_1 x_2 => + match x, x_1, x_2 with + | Γ, [], [] => some { down := ⋯ } + | Γ, A :: rest, witness :: witnesses => + if hl : Certified.checkZeroImplies atLevel witness.level = true then do + let hA ← Certified.verifyType fuel n entries Γ A (Model.AExpr.sort witness.level) witness.typing + let htail ← + Certified.verifyPropTelescope._unsafe_rec fuel n entries atLevel (Model.Context.push A Γ) rest witnesses + pure { down := ⋯ } + else none + | x, x_3, x_4 => none +compiler recursion worker Ix.Theory.Certified.verifyTelescope._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Model.Environment β) → + (bound : Option VLevel) → + (Γ : Model.Context β) → + (domains : List (Model.AExpr β)) → + List (Certified.DomainWitness β) → + Option + (Certified.CheckedClaim + (Model.Telescope.Formed entries Γ domains ∧ Certified.TelescopeBound entries Γ domains bound)) + implementation: fun {β} [DecidableEq β] fuel n entries bound x x_1 x_2 => + match x, x_1, x_2 with + | Γ, [], [] => some { down := ⋯ } + | Γ, A :: rest, witness :: witnesses => + if hl : Certified.checkDomainBound n bound witness.level = true then do + let hA ← Certified.verifyType fuel n entries Γ A (Model.AExpr.sort witness.level) witness.typing + let hrest ← Certified.verifyTelescope._unsafe_rec fuel n entries bound (Model.Context.push A Γ) rest witnesses + pure { down := ⋯ } + else none + | x, x_3, x_4 => none +compiler recursion worker Ix.Theory.Certified.verifyType._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Model.Environment β) → + (Γ : Model.Context β) → + (e A : Model.AExpr β) → + Certified.TypingWitness β → Option (Certified.CheckedClaim (Model.TypingClaim entries Γ e A)) + implementation: fun {β} [inst : DecidableEq β] fuel n entries Γ e A witness => + match fuel with + | 0 => none + | fuel.succ => + if Model.AExpr.Scope n (List.length Γ) e ∧ Model.AExpr.Scope n (List.length Γ) A then + match e, witness with + | Model.AExpr.sort l, Certified.TypingWitness.sort => + if h : A = Model.AExpr.sort l.succ then some { down := ⋯ } else none + | Model.AExpr.bvar i, Certified.TypingWitness.bvar => + match h : Γ[i]? with + | none => none + | some B => if hA : A = B then some { down := ⋯ } else none + | Model.AExpr.const r ls, Certified.TypingWitness.const => + match h : entries r with + | none => none + | some entry => + if hn : ls.length = entry.universes then + if hA : A = Model.AExpr.instL ls entry.type then some { down := ⋯ } else none + else none + | f.app a, Certified.TypingWitness.app p D B wf wa => + if hA : A = B.inst a then do + let hf ← Certified.verifyType._unsafe_rec fuel n entries Γ f (Model.AExpr.forallE p D B) wf + let ha ← Certified.verifyType._unsafe_rec fuel n entries Γ a D wa + pure { down := ⋯ } + else none + | Model.AExpr.lam p D body, Certified.TypingWitness.lam lD lB B wD wB wb => + if hp : p = Certified.zeroCondition lB then + if hA : A = Model.AExpr.forallE p D B then do + let hD ← Certified.verifyType._unsafe_rec fuel n entries Γ D (Model.AExpr.sort lD) wD + let hB ← Certified.verifyType._unsafe_rec fuel n entries (Model.Context.push D Γ) B (Model.AExpr.sort lB) wB + let hb ← Certified.verifyType._unsafe_rec fuel n entries (Model.Context.push D Γ) body B wb + pure { down := ⋯ } + else none + else none + | Model.AExpr.forallE p D B, Certified.TypingWitness.forallE lD lB wD wB => + if hp : p = Certified.zeroCondition lB then + if hA : A = Model.AExpr.sort (lD.imax lB) then do + let hD ← Certified.verifyType._unsafe_rec fuel n entries Γ D (Model.AExpr.sort lD) wD + let hB ← Certified.verifyType._unsafe_rec fuel n entries (Model.Context.push D Γ) B (Model.AExpr.sort lB) wB + pure { down := ⋯ } + else none + else none + | e, Certified.TypingWitness.conv B lA we wA wc => do + let he ← Certified.verifyType._unsafe_rec fuel n entries Γ e B we + let hA ← Certified.verifyType._unsafe_rec fuel n entries Γ A (Model.AExpr.sort lA) wA + let hc ← Certified.verifyConversion._unsafe_rec fuel n entries Γ B A wc + pure { down := ⋯ } + | e, Certified.TypingWitness.fact r index ls => + match h : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (Model.ConstantFact.typed value type) => + if hn : ls.length = entry.universes then + if ∀ (l : VLevel), l ∈ ls → VLevel.WF n l then + if he : e = Model.AExpr.instL ls value then + if hA : A = Model.AExpr.instL ls type then some { down := ⋯ } else none + else none + else none + else none + | x => none + | Model.AExpr.natLit value, Certified.TypingWitness.natLit r index => + match h : entries r with + | none => none + | some entry => + match hf : entry.facts[index]? with + | some (Model.ConstantFact.natural zero succ) => + if hn : entry.universes = 0 then if hA : A = Model.AExpr.const r [] then some { down := ⋯ } else none + else none + | x => none + | e, Certified.TypingWitness.betaResult p D body arg B wl wa => + if he : e = body.inst arg then + if hA : A = B.inst arg then do + let hl ← + Certified.verifyType._unsafe_rec fuel n entries Γ (Model.AExpr.lam p D body) (Model.AExpr.forallE p D B) + wl + let ha ← Certified.verifyType._unsafe_rec fuel n entries Γ arg D wa + pure { down := ⋯ } + else none + else none + | x, x_1 => none + else none +compiler recursion worker Ix.Theory.Certified.whnfShape._unsafe_rec + type: {β : Type u} → Model.Environment β → Model.AExpr β → Bool + implementation: fun {β} entries x => + match x with + | Model.AExpr.bvar index => true + | Model.AExpr.sort level => true + | Model.AExpr.lam condition domain body => true + | Model.AExpr.forallE condition domain body => true + | Model.AExpr.const r levels => Option.any (fun entry => entry.body.isNone) (entries r) + | (Model.AExpr.lam condition domain body).app arg => false + | f.app arg => Certified.whnfShape._unsafe_rec entries f + | Model.AExpr.natLit value => false + | Model.AExpr.proj ref field major => false +compiler recursion worker Ix.Theory.Certified.zeroCondition._unsafe_rec + type: VLevel → Certified.PropWhen + implementation: fun x => + match x with + | VLevel.zero => Certified.PropWhen.always + | a.succ => Certified.PropWhen.never + | a.max b => (Certified.zeroCondition._unsafe_rec a).inter (Certified.zeroCondition._unsafe_rec b) + | a.imax b => Certified.zeroCondition._unsafe_rec b + | VLevel.param i => Certified.PropWhen.param i +compiler recursion worker Ix.Theory.Lift.comp._unsafe_rec + type: Lift → Lift → Lift + implementation: fun l₁ l₂ => + match l₂, l₁ with + | Lift.refl, l₁ => l₁ + | l₂.skip, l₁ => (Lift.comp._unsafe_rec l₁ l₂).skip + | l₂.cons, Lift.refl => l₂.cons + | l₂.cons, l₁.skip => (Lift.comp._unsafe_rec l₁ l₂).skip + | l₂.cons, l₁.cons => (Lift.comp._unsafe_rec l₁ l₂).cons +compiler recursion worker Ix.Theory.Lift.consN._unsafe_rec + type: Lift → Nat → Lift + implementation: fun l x => + match x with + | 0 => l + | n.succ => (Lift.consN._unsafe_rec l n).cons +compiler recursion worker Ix.Theory.Lift.depth._unsafe_rec + type: Lift → Nat + implementation: fun x => + match x with + | Lift.refl => 0 + | l.skip => Lift.depth._unsafe_rec l + 1 + | l.cons => Lift.depth._unsafe_rec l +compiler recursion worker Ix.Theory.Lift.diff._unsafe_rec + type: Lift → Lift → Lift + implementation: fun x x_1 => + match x, x_1 with + | Lift.refl, x => Lift.refl + | l, Lift.refl => l + | l₁.skip, l₂.skip => Lift.diff._unsafe_rec l₁ l₂ + | l₁.cons, l₂.skip => Lift.diff._unsafe_rec l₁ l₂ + | l₁.skip, l₂.cons => (Lift.diff._unsafe_rec l₁ l₂).skip + | l₁.cons, l₂.cons => (Lift.diff._unsafe_rec l₁ l₂).cons +compiler recursion worker Ix.Theory.Lift.dom._unsafe_rec + type: Lift → Nat + implementation: fun x => + match x with + | Lift.refl => 0 + | l.skip => Lift.dom._unsafe_rec l + | l.cons => Lift.dom._unsafe_rec l + 1 +compiler recursion worker Ix.Theory.Lift.liftVar._unsafe_rec + type: Lift → Nat → Nat + implementation: fun x x_1 => + match x, x_1 with + | Lift.refl, n => n + | l.skip, n => Lift.liftVar._unsafe_rec l n + 1 + | tail.cons, 0 => 0 + | l.cons, n.succ => Lift.liftVar._unsafe_rec l n + 1 +compiler recursion worker Ix.Theory.Lift.size._unsafe_rec + type: Lift → Nat + implementation: fun x => + match x with + | Lift.refl => 0 + | l.skip => Lift.size._unsafe_rec l + 1 + | l.cons => Lift.size._unsafe_rec l + 1 +compiler recursion worker Ix.Theory.Lift.skipN._unsafe_rec + type: Lift → Nat → Lift + implementation: fun l x => + match x with + | 0 => l + | n.succ => (Lift.skipN._unsafe_rec l n).skip +compiler recursion worker Ix.Theory.Model.WellDenoted._unsafe_rec + type: {β : Type u} → + {V : Type v} → [Model.SetTheory V] → Model.Assignment β V → List Nat → (Nat → V) → Model.AExpr β → Prop + implementation: fun {β} {V} [Model.SetTheory V] constants levels env x => + match x with + | Model.AExpr.bvar index => True + | Model.AExpr.sort level => True + | Model.AExpr.const ref levels => True + | f.app a => + Model.WellDenoted._unsafe_rec constants levels env f ∧ + Model.WellDenoted._unsafe_rec constants levels env a ∧ + ∃ v A B, + Model.SetTheory.Mem (Model.interp constants levels env f) (Model.SetModel.piR v A B) ∧ + Model.SetTheory.Mem (Model.interp constants levels env a) A ∧ + ∀ (x : V), Model.SetTheory.Mem x A → Model.SetTheory.Mem (B x) (Model.SetTheory.univ v) + | Model.AExpr.lam p A b => + Model.WellDenoted._unsafe_rec constants levels env A ∧ + (∀ (x : V), + Model.SetTheory.Mem x (Model.interp constants levels env A) → + Model.WellDenoted._unsafe_rec constants levels (Model.Valuation.cons x env) b) ∧ + ∃ v B, + (Model.regime p levels = 0 ↔ v = 0) ∧ + ∀ (x : V), + Model.SetTheory.Mem x (Model.interp constants levels env A) → + Model.SetTheory.Mem (Model.interp constants levels (Model.Valuation.cons x env) b) (B x) ∧ + Model.SetTheory.Mem (B x) (Model.SetTheory.univ v) + | Model.AExpr.forallE p A B => + Model.WellDenoted._unsafe_rec constants levels env A ∧ + (∀ (x : V), + Model.SetTheory.Mem x (Model.interp constants levels env A) → + Model.WellDenoted._unsafe_rec constants levels (Model.Valuation.cons x env) B) ∧ + ∃ v, + (Model.regime p levels = 0 ↔ v = 0) ∧ + ∀ (x : V), + Model.SetTheory.Mem x (Model.interp constants levels env A) → + Model.SetTheory.Mem (Model.interp constants levels (Model.Valuation.cons x env) B) + (Model.SetTheory.univ v) + | Model.AExpr.proj ref field e => Model.WellDenoted._unsafe_rec constants levels env e + | Model.AExpr.natLit value => True +compiler recursion worker Ix.Theory.Model.readAnnotations?._unsafe_rec + type: {β : Type u} → (n k : Nat) → (source : VExpr β) → Model.AnnotationTree → Option (Model.Reading n k source) + implementation: fun {β} n k source tree => + match source, tree with + | VExpr.bvar i, Model.AnnotationTree.leaf => if h : i < k then some ⟨Model.AExpr.bvar i, ⋯⟩ else none + | VExpr.sort l, Model.AnnotationTree.leaf => if h : VLevel.WF n l then some ⟨Model.AExpr.sort l, ⋯⟩ else none + | VExpr.const r ls, Model.AnnotationTree.leaf => + if h : ∀ (l : VLevel), l ∈ ls → VLevel.WF n l then some ⟨Model.AExpr.const r ls, ⋯⟩ else none + | f.app a, tf.app ta => do + let f' ← Model.readAnnotations?._unsafe_rec n k f tf + let a' ← Model.readAnnotations?._unsafe_rec n k a ta + pure ⟨f'.val.app a'.val, ⋯⟩ + | a.lam b, Model.AnnotationTree.lam raw ta tb => + match Ix.Theory.Model.readCondition?✝ n raw with + | none => none + | some p => do + let a' ← Model.readAnnotations?._unsafe_rec n k a ta + let b' ← Model.readAnnotations?._unsafe_rec n (k + 1) b tb + pure ⟨Model.AExpr.lam p.val a'.val b'.val, ⋯⟩ + | a.forallE b, Model.AnnotationTree.forallE raw ta tb => + match Ix.Theory.Model.readCondition?✝ n raw with + | none => none + | some p => do + let a' ← Model.readAnnotations?._unsafe_rec n k a ta + let b' ← Model.readAnnotations?._unsafe_rec n (k + 1) b tb + pure ⟨Model.AExpr.forallE p.val a'.val b'.val, ⋯⟩ + | VExpr.proj r i e, te.proj => do + let e' ← Model.readAnnotations?._unsafe_rec n k e te + pure ⟨Model.AExpr.proj r i e'.val, ⋯⟩ + | VExpr.natLit v, Model.AnnotationTree.leaf => some ⟨Model.AExpr.natLit v, ⋯⟩ + | x, x_1 => none +compiler recursion worker Ix.Theory.VExpr.ClosedN._unsafe_rec + type: {β : Type u_1} → VExpr β → optParam Nat 0 → Prop + implementation: fun {β} x x_1 => + match x, x_1 with + | VExpr.bvar i, k => i < k + | VExpr.sort u, x => True + | VExpr.const ref levels, x => True + | VExpr.natLit value, x => True + | fn.app arg, k => VExpr.ClosedN._unsafe_rec fn k ∧ VExpr.ClosedN._unsafe_rec arg k + | ty.lam body, k => VExpr.ClosedN._unsafe_rec ty k ∧ VExpr.ClosedN._unsafe_rec body (k + 1) + | ty.forallE body, k => VExpr.ClosedN._unsafe_rec ty k ∧ VExpr.ClosedN._unsafe_rec body (k + 1) + | VExpr.proj ref index e, k => VExpr.ClosedN._unsafe_rec e k +compiler recursion worker Ix.Theory.VExpr.LevelWF._unsafe_rec + type: {β : Type u_1} → Nat → VExpr β → Prop + implementation: fun {β} U x => + match x with + | VExpr.bvar deBruijnIndex => True + | VExpr.natLit value => True + | VExpr.sort l => VLevel.WF U l + | VExpr.const ref levels => ∀ (l : VLevel), l ∈ levels → VLevel.WF U l + | e₁.app e₂ => VExpr.LevelWF._unsafe_rec U e₁ ∧ VExpr.LevelWF._unsafe_rec U e₂ + | e₁.lam e₂ => VExpr.LevelWF._unsafe_rec U e₁ ∧ VExpr.LevelWF._unsafe_rec U e₂ + | e₁.forallE e₂ => VExpr.LevelWF._unsafe_rec U e₁ ∧ VExpr.LevelWF._unsafe_rec U e₂ + | VExpr.proj ref index e => VExpr.LevelWF._unsafe_rec U e +compiler recursion worker Ix.Theory.VExpr.Skips'._unsafe_rec + type: {β : Type u_1} → Nat → VExpr β → optParam Nat 0 → Prop + implementation: fun {β} n x x_1 => + match x, x_1 with + | VExpr.bvar i, k => i < k + n → i < k + | VExpr.sort u, x => True + | VExpr.const ref levels, x => True + | VExpr.natLit value, x => True + | fn.app arg, k => VExpr.Skips'._unsafe_rec n fn k ∧ VExpr.Skips'._unsafe_rec n arg k + | ty.lam body, k => VExpr.Skips'._unsafe_rec n ty k ∧ VExpr.Skips'._unsafe_rec n body (k + 1) + | ty.forallE body, k => VExpr.Skips'._unsafe_rec n ty k ∧ VExpr.Skips'._unsafe_rec n body (k + 1) + | VExpr.proj ref index e, k => VExpr.Skips'._unsafe_rec n e k +compiler recursion worker Ix.Theory.VExpr.appArgs._unsafe_rec + type: {β : Type u_1} → VExpr β → List (VExpr β) → List (VExpr β) + implementation: fun {β} x x_1 => + match x, x_1 with + | f.app a, acc => VExpr.appArgs._unsafe_rec f (a :: acc) + | x, acc => acc +compiler recursion worker Ix.Theory.VExpr.appHead._unsafe_rec + type: {β : Type u_1} → VExpr β → VExpr β + implementation: fun {β} x => + match x with + | f.app arg => VExpr.appHead._unsafe_rec f + | e => e +compiler recursion worker Ix.Theory.VExpr.appN._unsafe_rec + type: {β : Type u_1} → VExpr β → List (VExpr β) → VExpr β + implementation: fun {β} f x => + match x with + | [] => f + | a :: as => VExpr.appN._unsafe_rec (f.app a) as +compiler recursion worker Ix.Theory.VExpr.bvarRevRange._unsafe_rec + type: {β : Type u_1} → Nat → Nat → List (VExpr β) + implementation: fun {β} off x => + match x with + | 0 => [] + | m.succ => VExpr.bvar (off + m) :: VExpr.bvarRevRange._unsafe_rec off m +compiler recursion worker Ix.Theory.VExpr.dropN._unsafe_rec + type: {β : Type u_1} → Nat → VExpr β → VExpr β + implementation: fun {β} x x_1 => + match x, x_1 with + | 0, e => e + | n.succ, binderType.forallE rest => VExpr.dropN._unsafe_rec n rest + | n.succ, e => e +compiler recursion worker Ix.Theory.VExpr.forallN._unsafe_rec + type: {β : Type u_1} → List (VExpr β) → VExpr β → VExpr β + implementation: fun {β} x x_1 => + match x, x_1 with + | [], e => e + | A :: As, e => A.forallE (VExpr.forallN._unsafe_rec As e) +compiler recursion worker Ix.Theory.VExpr.inst._unsafe_rec + type: {β : Type u_1} → VExpr β → VExpr β → optParam Nat 0 → VExpr β + implementation: fun {β} x x_1 x_2 => + match x, x_1, x_2 with + | VExpr.bvar i, e, k => VExpr.instVar i e k + | VExpr.sort u, x, x_3 => VExpr.sort u + | VExpr.const r us, x, x_3 => VExpr.const r us + | fn.app arg, e, k => (VExpr.inst._unsafe_rec fn e k).app (VExpr.inst._unsafe_rec arg e k) + | ty.lam body, e, k => (VExpr.inst._unsafe_rec ty e k).lam (VExpr.inst._unsafe_rec body e (k + 1)) + | ty.forallE body, e, k => (VExpr.inst._unsafe_rec ty e k).forallE (VExpr.inst._unsafe_rec body e (k + 1)) + | VExpr.proj r i p, e, k => VExpr.proj r i (VExpr.inst._unsafe_rec p e k) + | VExpr.natLit value, x, x_3 => VExpr.natLit value +compiler recursion worker Ix.Theory.VExpr.instL._unsafe_rec + type: List VLevel → {β : Type u_1} → VExpr β → VExpr β + implementation: fun levels {β} x => + match x with + | VExpr.bvar i => VExpr.bvar i + | VExpr.sort u => VExpr.sort (VLevel.inst levels u) + | VExpr.const r us => VExpr.const r (List.map (VLevel.inst levels) us) + | fn.app arg => (VExpr.instL._unsafe_rec levels fn).app (VExpr.instL._unsafe_rec levels arg) + | ty.lam body => (VExpr.instL._unsafe_rec levels ty).lam (VExpr.instL._unsafe_rec levels body) + | ty.forallE body => (VExpr.instL._unsafe_rec levels ty).forallE (VExpr.instL._unsafe_rec levels body) + | VExpr.proj r i e => VExpr.proj r i (VExpr.instL._unsafe_rec levels e) + | VExpr.natLit value => VExpr.natLit value +compiler recursion worker Ix.Theory.VExpr.instRev._unsafe_rec + type: {β : Type u_1} → VExpr β → List (VExpr β) → VExpr β + implementation: fun {β} x x_1 => + match x, x_1 with + | C, [] => C + | C, e :: es => VExpr.instRev._unsafe_rec (C.inst e es.length) es +compiler recursion worker Ix.Theory.VExpr.instRevAt._unsafe_rec + type: {β : Type u_1} → VExpr β → List (VExpr β) → Nat → VExpr β + implementation: fun {β} x x_1 x_2 => + match x, x_1, x_2 with + | e, [], x => e + | e, a :: as, k => VExpr.instRevAt._unsafe_rec (e.inst a (k + as.length)) as k +compiler recursion worker Ix.Theory.VExpr.instTelN._unsafe_rec + type: {β : Type u_1} → VExpr β → List (VExpr β) → Nat → List (VExpr β) + implementation: fun {β} a x x_1 => + match x, x_1 with + | [], x => [] + | A :: As, k => A.inst a k :: VExpr.instTelN._unsafe_rec a As (k + 1) +compiler recursion worker Ix.Theory.VExpr.lamN._unsafe_rec + type: {β : Type u_1} → List (VExpr β) → VExpr β → VExpr β + implementation: fun {β} x x_1 => + match x, x_1 with + | [], e => e + | A :: As, e => A.lam (VExpr.lamN._unsafe_rec As e) +compiler recursion worker Ix.Theory.VExpr.lift'._unsafe_rec + type: {β : Type u_1} → VExpr β → Lift → VExpr β + implementation: fun {β} x x_1 => + match x, x_1 with + | VExpr.bvar i, ρ => VExpr.bvar (ρ.liftVar i) + | VExpr.sort u, x => VExpr.sort u + | VExpr.const r us, x => VExpr.const r us + | fn.app arg, ρ => (VExpr.lift'._unsafe_rec fn ρ).app (VExpr.lift'._unsafe_rec arg ρ) + | ty.lam body, ρ => (VExpr.lift'._unsafe_rec ty ρ).lam (VExpr.lift'._unsafe_rec body ρ.cons) + | ty.forallE body, ρ => (VExpr.lift'._unsafe_rec ty ρ).forallE (VExpr.lift'._unsafe_rec body ρ.cons) + | VExpr.proj r i e, ρ => VExpr.proj r i (VExpr.lift'._unsafe_rec e ρ) + | VExpr.natLit value, x => VExpr.natLit value +compiler recursion worker Ix.Theory.VExpr.liftN._unsafe_rec + type: Nat → {β : Type u_1} → VExpr β → optParam Nat 0 → VExpr β + implementation: fun n {β} x x_1 => + match x, x_1 with + | VExpr.bvar i, k => VExpr.bvar (liftVar n i k) + | VExpr.sort u, x => VExpr.sort u + | VExpr.const r us, x => VExpr.const r us + | fn.app arg, k => (VExpr.liftN._unsafe_rec n fn k).app (VExpr.liftN._unsafe_rec n arg k) + | ty.lam body, k => (VExpr.liftN._unsafe_rec n ty k).lam (VExpr.liftN._unsafe_rec n body (k + 1)) + | ty.forallE body, k => (VExpr.liftN._unsafe_rec n ty k).forallE (VExpr.liftN._unsafe_rec n body (k + 1)) + | VExpr.proj r i e, k => VExpr.proj r i (VExpr.liftN._unsafe_rec n e k) + | VExpr.natLit value, x => VExpr.natLit value +compiler recursion worker Ix.Theory.VExpr.liftTelN._unsafe_rec + type: {β : Type u_1} → Nat → List (VExpr β) → Nat → List (VExpr β) + implementation: fun {β} n x x_1 => + match x, x_1 with + | [], x => [] + | A :: As, k => VExpr.liftN n A k :: VExpr.liftTelN._unsafe_rec n As (k + 1) +compiler recursion worker Ix.Theory.VExpr.mapRefs._unsafe_rec + type: {β : Type u} → {γ : Type v} → (ConstRef β → ConstRef γ) → VExpr β → VExpr γ + implementation: fun {β} {γ} mapping x => + match x with + | VExpr.bvar i => VExpr.bvar i + | VExpr.sort level => VExpr.sort level + | VExpr.const ref levels => VExpr.const (mapping ref) levels + | f.app a => (VExpr.mapRefs._unsafe_rec mapping f).app (VExpr.mapRefs._unsafe_rec mapping a) + | type.lam body => (VExpr.mapRefs._unsafe_rec mapping type).lam (VExpr.mapRefs._unsafe_rec mapping body) + | type.forallE body => (VExpr.mapRefs._unsafe_rec mapping type).forallE (VExpr.mapRefs._unsafe_rec mapping body) + | VExpr.proj ref index major => VExpr.proj (mapping ref) index (VExpr.mapRefs._unsafe_rec mapping major) + | VExpr.natLit n => VExpr.natLit n +compiler recursion worker Ix.Theory.VExpr.mentions._unsafe_rec + type: {β : Type u_1} → [DecidableEq β] → VExpr β → ConstRef β → Bool + implementation: fun {β} [DecidableEq β] x x_1 => + match x, x_1 with + | VExpr.bvar deBruijnIndex, x => false + | VExpr.sort u, x => false + | VExpr.natLit value, x => false + | VExpr.const r levels, target => decide (r = target) + | e₁.app e₂, target => VExpr.mentions._unsafe_rec e₁ target || VExpr.mentions._unsafe_rec e₂ target + | e₁.lam e₂, target => VExpr.mentions._unsafe_rec e₁ target || VExpr.mentions._unsafe_rec e₂ target + | e₁.forallE e₂, target => VExpr.mentions._unsafe_rec e₁ target || VExpr.mentions._unsafe_rec e₂ target + | VExpr.proj r index e, target => decide (r = target) || VExpr.mentions._unsafe_rec e target +compiler recursion worker Ix.Theory.VExpr.refs._unsafe_rec + type: {β : Type u_1} → VExpr β → List (ConstRef β) + implementation: fun {β} x => + match x with + | VExpr.bvar deBruijnIndex => [] + | VExpr.sort u => [] + | VExpr.natLit value => [] + | VExpr.const r levels => [r] + | e₁.app e₂ => VExpr.refs._unsafe_rec e₁ ++ VExpr.refs._unsafe_rec e₂ + | e₁.lam e₂ => VExpr.refs._unsafe_rec e₁ ++ VExpr.refs._unsafe_rec e₂ + | e₁.forallE e₂ => VExpr.refs._unsafe_rec e₁ ++ VExpr.refs._unsafe_rec e₂ + | VExpr.proj r index e => r :: VExpr.refs._unsafe_rec e +compiler recursion worker Ix.Theory.VExpr.rename._unsafe_rec + type: {β : Type u_1} → {γ : Type u_2} → (β → γ) → VExpr β → VExpr γ + implementation: fun {β} {γ} mapping x => + match x with + | VExpr.bvar index => VExpr.bvar index + | VExpr.sort level => VExpr.sort level + | VExpr.const ref levels => VExpr.const (ConstRef.rename mapping ref) levels + | function.app argument => (VExpr.rename._unsafe_rec mapping function).app (VExpr.rename._unsafe_rec mapping argument) + | domain.lam body => (VExpr.rename._unsafe_rec mapping domain).lam (VExpr.rename._unsafe_rec mapping body) + | domain.forallE body => (VExpr.rename._unsafe_rec mapping domain).forallE (VExpr.rename._unsafe_rec mapping body) + | VExpr.proj ref field major => + VExpr.proj (ConstRef.rename mapping ref) field (VExpr.rename._unsafe_rec mapping major) + | VExpr.natLit value => VExpr.natLit value +compiler recursion worker Ix.Theory.VExpr.resultOf._unsafe_rec + type: {β : Type u_1} → VExpr β → VExpr β + implementation: fun {β} x => + match x with + | binderType.forallE rest => VExpr.resultOf._unsafe_rec rest + | e => e +compiler recursion worker Ix.Theory.VExpr.substConst._unsafe_rec + type: {β : Type u_1} → (ConstRef β → Option (VExpr β)) → VExpr β → VExpr β + implementation: fun {β} interp x => + match x with + | VExpr.bvar index => VExpr.bvar index + | VExpr.sort level => VExpr.sort level + | VExpr.const ref levels => + match interp ref with + | some value => VExpr.instL levels value + | none => VExpr.const ref levels + | function.app argument => + (VExpr.substConst._unsafe_rec interp function).app (VExpr.substConst._unsafe_rec interp argument) + | domain.lam body => (VExpr.substConst._unsafe_rec interp domain).lam (VExpr.substConst._unsafe_rec interp body) + | domain.forallE body => + (VExpr.substConst._unsafe_rec interp domain).forallE (VExpr.substConst._unsafe_rec interp body) + | VExpr.proj ref field expression => VExpr.proj ref field (VExpr.substConst._unsafe_rec interp expression) + | VExpr.natLit value => VExpr.natLit value +compiler recursion worker Ix.Theory.VExpr.telN._unsafe_rec + type: {β : Type u_1} → Nat → VExpr β → List (VExpr β) + implementation: fun {β} x x_1 => + match x, x_1 with + | 0, x => [] + | n.succ, A.forallE rest => A :: VExpr.telN._unsafe_rec n rest + | n.succ, x => [] +compiler recursion worker Ix.Theory.VExpr.unliftN._unsafe_rec + type: {β : Type u_1} → VExpr β → Nat → Nat → VExpr β + implementation: fun {β} e n k => + match n with + | 0 => e + | n.succ => VExpr.unliftN._unsafe_rec (e.inst default k) n k +compiler recursion worker Ix.Theory.VLevel.WF._unsafe_rec + type: Nat → VLevel → Prop + implementation: fun n x => + match x with + | VLevel.zero => True + | l.succ => VLevel.WF._unsafe_rec n l + | l₁.max l₂ => VLevel.WF._unsafe_rec n l₁ ∧ VLevel.WF._unsafe_rec n l₂ + | l₁.imax l₂ => VLevel.WF._unsafe_rec n l₁ ∧ VLevel.WF._unsafe_rec n l₂ + | VLevel.param i => i < n +compiler recursion worker Ix.Theory.VLevel.decidable_WF._unsafe_rec + type: {n : Nat} → {l : VLevel} → Decidable (VLevel.WF n l) + implementation: fun {n} x => + match x with + | VLevel.zero => instDecidableTrue + | l.succ => VLevel.decidable_WF._unsafe_rec + | a.max a_1 => instDecidableAnd + | a.imax a_1 => instDecidableAnd + | VLevel.param a => a.decLt n +compiler recursion worker Ix.Theory.VLevel.eval._unsafe_rec + type: List Nat → VLevel → Nat + implementation: fun ls x => + match x with + | VLevel.zero => 0 + | l.succ => VLevel.eval._unsafe_rec ls l + 1 + | l₁.max l₂ => (VLevel.eval._unsafe_rec ls l₁).max (VLevel.eval._unsafe_rec ls l₂) + | l₁.imax l₂ => VLevel.natIMax (VLevel.eval._unsafe_rec ls l₁) (VLevel.eval._unsafe_rec ls l₂) + | VLevel.param i => ls.getD i 0 +compiler recursion worker Ix.Theory.VLevel.inst._unsafe_rec + type: List VLevel → VLevel → VLevel + implementation: fun ls x => + match x with + | VLevel.zero => VLevel.zero + | l.succ => (VLevel.inst._unsafe_rec ls l).succ + | l₁.max l₂ => (VLevel.inst._unsafe_rec ls l₁).max (VLevel.inst._unsafe_rec ls l₂) + | l₁.imax l₂ => (VLevel.inst._unsafe_rec ls l₁).imax (VLevel.inst._unsafe_rec ls l₂) + | VLevel.param i => ls.getD i VLevel.zero +compiler recursion worker Ix.Theory.instDecidableEqVExpr.decEq._unsafe_rec + type: {β : Type u_1} → [DecidableEq β] → (x x_1 : VExpr β) → Decidable (x = x_1) + implementation: fun {β} [inst : DecidableEq β] x x_1 => + match x, x_1 with + | VExpr.bvar a, VExpr.bvar b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | VExpr.bvar deBruijnIndex, VExpr.sort u => isFalse ⋯ + | VExpr.bvar deBruijnIndex, VExpr.const ref levels => isFalse ⋯ + | VExpr.bvar deBruijnIndex, fn.app arg => isFalse ⋯ + | VExpr.bvar deBruijnIndex, binderType.lam body => isFalse ⋯ + | VExpr.bvar deBruijnIndex, binderType.forallE body => isFalse ⋯ + | VExpr.bvar deBruijnIndex, VExpr.proj ref index expr => isFalse ⋯ + | VExpr.bvar deBruijnIndex, VExpr.natLit value => isFalse ⋯ + | VExpr.sort u, VExpr.bvar deBruijnIndex => isFalse ⋯ + | VExpr.sort a, VExpr.sort b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | VExpr.sort u, VExpr.const ref levels => isFalse ⋯ + | VExpr.sort u, fn.app arg => isFalse ⋯ + | VExpr.sort u, binderType.lam body => isFalse ⋯ + | VExpr.sort u, binderType.forallE body => isFalse ⋯ + | VExpr.sort u, VExpr.proj ref index expr => isFalse ⋯ + | VExpr.sort u, VExpr.natLit value => isFalse ⋯ + | VExpr.const ref levels, VExpr.bvar deBruijnIndex => isFalse ⋯ + | VExpr.const ref levels, VExpr.sort u => isFalse ⋯ + | VExpr.const a a_1, VExpr.const b b_1 => + if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯ + | VExpr.const ref levels, fn.app arg => isFalse ⋯ + | VExpr.const ref levels, binderType.lam body => isFalse ⋯ + | VExpr.const ref levels, binderType.forallE body => isFalse ⋯ + | VExpr.const ref levels, VExpr.proj ref_1 index expr => isFalse ⋯ + | VExpr.const ref levels, VExpr.natLit value => isFalse ⋯ + | fn.app arg, VExpr.bvar deBruijnIndex => isFalse ⋯ + | fn.app arg, VExpr.sort u => isFalse ⋯ + | fn.app arg, VExpr.const ref levels => isFalse ⋯ + | a.app a_1, b.app b_1 => + let inst_1 := instDecidableEqVExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := instDecidableEqVExpr.decEq._unsafe_rec a a; + let inst_3 := instDecidableEqVExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := instDecidableEqVExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | fn.app arg, binderType.lam body => isFalse ⋯ + | fn.app arg, binderType.forallE body => isFalse ⋯ + | fn.app arg, VExpr.proj ref index expr => isFalse ⋯ + | fn.app arg, VExpr.natLit value => isFalse ⋯ + | binderType.lam body, VExpr.bvar deBruijnIndex => isFalse ⋯ + | binderType.lam body, VExpr.sort u => isFalse ⋯ + | binderType.lam body, VExpr.const ref levels => isFalse ⋯ + | binderType.lam body, fn.app arg => isFalse ⋯ + | a.lam a_1, b.lam b_1 => + let inst_1 := instDecidableEqVExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := instDecidableEqVExpr.decEq._unsafe_rec a a; + let inst_3 := instDecidableEqVExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := instDecidableEqVExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | binderType.lam body, binderType_1.forallE body_1 => isFalse ⋯ + | binderType.lam body, VExpr.proj ref index expr => isFalse ⋯ + | binderType.lam body, VExpr.natLit value => isFalse ⋯ + | binderType.forallE body, VExpr.bvar deBruijnIndex => isFalse ⋯ + | binderType.forallE body, VExpr.sort u => isFalse ⋯ + | binderType.forallE body, VExpr.const ref levels => isFalse ⋯ + | binderType.forallE body, fn.app arg => isFalse ⋯ + | binderType.forallE body, binderType_1.lam body_1 => isFalse ⋯ + | a.forallE a_1, b.forallE b_1 => + let inst_1 := instDecidableEqVExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := instDecidableEqVExpr.decEq._unsafe_rec a a; + let inst_3 := instDecidableEqVExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := instDecidableEqVExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | binderType.forallE body, VExpr.proj ref index expr => isFalse ⋯ + | binderType.forallE body, VExpr.natLit value => isFalse ⋯ + | VExpr.proj ref index expr, VExpr.bvar deBruijnIndex => isFalse ⋯ + | VExpr.proj ref index expr, VExpr.sort u => isFalse ⋯ + | VExpr.proj ref index expr, VExpr.const ref_1 levels => isFalse ⋯ + | VExpr.proj ref index expr, fn.app arg => isFalse ⋯ + | VExpr.proj ref index expr, binderType.lam body => isFalse ⋯ + | VExpr.proj ref index expr, binderType.forallE body => isFalse ⋯ + | VExpr.proj a a_1 a_2, VExpr.proj b b_1 b_2 => + if h : a = b then + h ▸ + if h : a_1 = b_1 then + h ▸ + let inst_1 := instDecidableEqVExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := instDecidableEqVExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | VExpr.proj ref index expr, VExpr.natLit value => isFalse ⋯ + | VExpr.natLit value, VExpr.bvar deBruijnIndex => isFalse ⋯ + | VExpr.natLit value, VExpr.sort u => isFalse ⋯ + | VExpr.natLit value, VExpr.const ref levels => isFalse ⋯ + | VExpr.natLit value, fn.app arg => isFalse ⋯ + | VExpr.natLit value, binderType.lam body => isFalse ⋯ + | VExpr.natLit value, binderType.forallE body => isFalse ⋯ + | VExpr.natLit value, VExpr.proj ref index expr => isFalse ⋯ + | VExpr.natLit a, VExpr.natLit b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ +compiler recursion worker Ix.Theory.instDecidableEqVLevel.decEq._unsafe_rec + type: (x x_1 : VLevel) → Decidable (x = x_1) + implementation: fun x x_1 => + match x, x_1 with + | VLevel.zero, VLevel.zero => isTrue ⋯ + | VLevel.zero, a.succ => isFalse ⋯ + | VLevel.zero, a.max a_1 => isFalse ⋯ + | VLevel.zero, a.imax a_1 => isFalse ⋯ + | VLevel.zero, VLevel.param a => isFalse ⋯ + | a.succ, VLevel.zero => isFalse ⋯ + | a.succ, b.succ => + let inst := instDecidableEqVLevel.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := instDecidableEqVLevel.decEq._unsafe_rec a a; + isTrue ⋯ + else isFalse ⋯ + | a.succ, a_1.max a_2 => isFalse ⋯ + | a.succ, a_1.imax a_2 => isFalse ⋯ + | a.succ, VLevel.param a_1 => isFalse ⋯ + | a.max a_1, VLevel.zero => isFalse ⋯ + | a.max a_1, a_2.succ => isFalse ⋯ + | a.max a_1, b.max b_1 => + let inst := instDecidableEqVLevel.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := instDecidableEqVLevel.decEq._unsafe_rec a a; + let inst := instDecidableEqVLevel.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := instDecidableEqVLevel.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | a.max a_1, a_2.imax a_3 => isFalse ⋯ + | a.max a_1, VLevel.param a_2 => isFalse ⋯ + | a.imax a_1, VLevel.zero => isFalse ⋯ + | a.imax a_1, a_2.succ => isFalse ⋯ + | a.imax a_1, a_2.max a_3 => isFalse ⋯ + | a.imax a_1, b.imax b_1 => + let inst := instDecidableEqVLevel.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := instDecidableEqVLevel.decEq._unsafe_rec a a; + let inst := instDecidableEqVLevel.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := instDecidableEqVLevel.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | a.imax a_1, VLevel.param a_2 => isFalse ⋯ + | VLevel.param a, VLevel.zero => isFalse ⋯ + | VLevel.param a, a_1.succ => isFalse ⋯ + | VLevel.param a, a_1.max a_2 => isFalse ⋯ + | VLevel.param a, a_1.imax a_2 => isFalse ⋯ + | VLevel.param a, VLevel.param b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ +compiler recursion worker Ix.Theory.instHashableVExpr.hash._unsafe_rec + type: {β : Type u_1} → [Hashable β] → VExpr β → UInt64 + implementation: fun {β} [Hashable β] x => + match x with + | VExpr.bvar a => mixHash 0 (hash a) + | VExpr.sort a => mixHash 1 (hash a) + | VExpr.const a a_1 => mixHash (mixHash 2 (hash a)) (hash a_1) + | a.app a_1 => mixHash (mixHash 3 (instHashableVExpr.hash._unsafe_rec a)) (instHashableVExpr.hash._unsafe_rec a_1) + | a.lam a_1 => mixHash (mixHash 4 (instHashableVExpr.hash._unsafe_rec a)) (instHashableVExpr.hash._unsafe_rec a_1) + | a.forallE a_1 => mixHash (mixHash 5 (instHashableVExpr.hash._unsafe_rec a)) (instHashableVExpr.hash._unsafe_rec a_1) + | VExpr.proj a a_1 a_2 => mixHash (mixHash (mixHash 6 (hash a)) (hash a_1)) (instHashableVExpr.hash._unsafe_rec a_2) + | VExpr.natLit a => mixHash 7 (hash a) +compiler recursion worker Ix.Theory.instHashableVLevel.hash._unsafe_rec + type: VLevel → UInt64 + implementation: fun x => + match x with + | VLevel.zero => 0 + | a.succ => mixHash 1 (instHashableVLevel.hash._unsafe_rec a) + | a.max a_1 => mixHash (mixHash 2 (instHashableVLevel.hash._unsafe_rec a)) (instHashableVLevel.hash._unsafe_rec a_1) + | a.imax a_1 => mixHash (mixHash 3 (instHashableVLevel.hash._unsafe_rec a)) (instHashableVLevel.hash._unsafe_rec a_1) + | VLevel.param a => mixHash 4 (hash a) +compiler recursion worker Ix.Theory.Certified.IndexSet.insert._unsafe_rec + type: Nat → List Nat → List Nat + implementation: fun x x_1 => + match x_1 with + | [] => [x] + | y :: ys => + if x < y then x :: y :: ys else if x = y then y :: ys else y :: Certified.IndexSet.insert._unsafe_rec x ys +compiler recursion worker Ix.Theory.Certified.IndexSet.normalize._unsafe_rec + type: List Nat → List Nat + implementation: fun x => + match x with + | [] => [] + | x :: xs => Certified.IndexSet.insert x (Certified.IndexSet.normalize._unsafe_rec xs) +compiler recursion worker Ix.Theory.Certified.LevelEq.leq._unsafe_rec + type: VLevel → VLevel → Bool + implementation: fun a b => + if a = b then true + else + match a, b with + | VLevel.zero, x => true + | a.max b, c => Certified.LevelEq.leq._unsafe_rec a c && Certified.LevelEq.leq._unsafe_rec b c + | a, b.max c => Certified.LevelEq.leq._unsafe_rec a b || Certified.LevelEq.leq._unsafe_rec a c + | a.succ, b.succ => Certified.LevelEq.leq._unsafe_rec a b + | a, b.succ => Certified.LevelEq.leq._unsafe_rec a b + | a.imax b, c => Certified.LevelEq.leq._unsafe_rec a c && Certified.LevelEq.leq._unsafe_rec b c + | x, x_1 => false +compiler recursion worker Ix.Theory.Certified.LevelEq.normalize._unsafe_rec + type: VLevel → VLevel + implementation: fun x => + match x with + | VLevel.zero => VLevel.zero + | VLevel.param i => VLevel.param i + | a.succ => (Certified.LevelEq.normalize._unsafe_rec a).succ + | a.max b => + Certified.LevelEq.max (Certified.LevelEq.normalize._unsafe_rec a) (Certified.LevelEq.normalize._unsafe_rec b) + | a.imax b => + Certified.LevelEq.imax (Certified.LevelEq.normalize._unsafe_rec a) (Certified.LevelEq.normalize._unsafe_rec b) +compiler recursion worker Ix.Theory.Certified.Modeled.applyPi?._unsafe_rec + type: {β : Type u} → VExpr β → List (VExpr β) → Option (VExpr β) + implementation: fun {β} x x_1 => + match x, x_1 with + | type, [] => some type + | binderType.forallE body, argument :: rest => Certified.Modeled.applyPi?._unsafe_rec (body.inst argument) rest + | x, head :: tail => none +compiler recursion worker Ix.Theory.Certified.Modeled.betaHead?._unsafe_rec + type: {β : Type u} → Nat → VExpr β → Option (VExpr β) + implementation: fun {β} x x_1 => + match x, x_1 with + | 0, x => none + | fuel.succ, function.app argument => do + let function ← Certified.Modeled.betaHead?._unsafe_rec fuel function + match function with + | binderType.lam body => Certified.Modeled.betaHead?._unsafe_rec fuel (body.inst argument) + | x => some (function.app argument) + | n.succ, expression => some expression +compiler recursion worker Ix.Theory.Certified.Modeled.checkEach?._unsafe_rec + type: {β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (companions pending : List (Certified.Modeled.Companion β)) → + List (List (Certified.Modeled.EquationWitness β)) → + Option + (Certified.CheckedClaim + (∀ (companion : Certified.Modeled.Companion β), + companion ∈ pending → Certified.Modeled.CompanionChecked entries companions companion)) + implementation: fun {β} [DecidableEq β] fuel entries companions x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | companion :: rest, witnesses :: remaining => do + let first ← Certified.Modeled.checkCompanion? fuel entries companions companion witnesses + let others ← Certified.Modeled.checkEach?._unsafe_rec fuel entries companions rest remaining + pure { down := ⋯ } + | x, x_2 => none +compiler recursion worker Ix.Theory.Certified.Modeled.checkRules?._unsafe_rec + type: {β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (companions : List (Certified.Modeled.Companion β)) → + (rules : List (Certified.Signature.Rule β)) → + List (Certified.Modeled.EquationWitness β) → + Option + (Certified.CheckedClaim + (∀ (rule : Certified.Signature.Rule β), + rule ∈ rules → + Certified.Modeled.CheckedEquation entries (Certified.Modeled.mapRule companions rule))) + implementation: fun {β} [DecidableEq β] fuel entries companions x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | rule :: rules, witness :: witnesses => do + let first ← Certified.Modeled.checkEquation? fuel entries (Certified.Modeled.mapRule companions rule) witness + let rest ← Certified.Modeled.checkRules?._unsafe_rec fuel entries companions rules witnesses + pure { down := ⋯ } + | x, x_2 => none +compiler recursion worker Ix.Theory.Certified.Modeled.lookupCompanion._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → List (Certified.Modeled.Companion β) → ConstRef β → Option (Certified.Modeled.Companion β) + implementation: fun {β} [DecidableEq β] x x_1 => + match x, x_1 with + | [], x => none + | companion :: rest, ref => + if companion.header.ref = ref then some companion else Certified.Modeled.lookupCompanion._unsafe_rec rest ref +compiler recursion worker Ix.Theory.Certified.Modeled.splitLam?._unsafe_rec + type: {β : Type u} → Nat → VExpr β → Option (List (VExpr β) × VExpr β) + implementation: fun {β} x x_1 => + match x, x_1 with + | 0, expression => some ([], expression) + | n.succ, domain.lam body => do + let __x ← Certified.Modeled.splitLam?._unsafe_rec n body + match __x with + | (domains, result) => pure (domain :: domains, result) + | n.succ, x => none +compiler recursion worker Ix.Theory.Certified.Modeled.splitPi?._unsafe_rec + type: {β : Type u} → Nat → VExpr β → Option (List (VExpr β) × VExpr β) + implementation: fun {β} x x_1 => + match x, x_1 with + | 0, type => some ([], type) + | n.succ, domain.forallE body => do + let __x ← Certified.Modeled.splitPi?._unsafe_rec n body + match __x with + | (domains, result) => pure (domain :: domains, result) + | n.succ, x => none +compiler recursion worker Ix.Theory.Certified.Ordinary.checkConstructors._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (shape : Certified.Ordinary.Shape β) → + (ctors : List (Certified.Ordinary.Constructor β)) → + List (Certified.Ordinary.ConstructorWitness β) → + Option + (Certified.CheckedClaim + (∀ (ctor : Certified.Ordinary.Constructor β), + ctor ∈ ctors → Certified.Ordinary.ConstructorEvidence entries shape ctor)) + implementation: fun {β} [DecidableEq β] fuel entries shape x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | ctor :: ctors, witness :: witnesses => + if hrefs : ∀ (e : Model.AExpr β), e ∈ ctor.fields ++ ctor.indices → Model.AExpr.ReferencesIn entries e then do + let fields ← + Certified.verifyTelescope fuel shape.universes entries (some shape.level) shape.parameterContext ctor.fields + witness.fields + let indices ← + Certified.verifyArguments fuel shape.universes entries (ctor.context shape) + (Model.Telescope.lift ctor.fields.length shape.indices) ctor.indices witness.indices + let recursive ← Certified.Ordinary.checkRecursive fuel entries shape ctor ctor.recursive witness.recursive + let rest ← Certified.Ordinary.checkConstructors._unsafe_rec fuel entries shape ctors witnesses + pure { down := ⋯ } + else none + | x, x_2 => none +compiler recursion worker Ix.Theory.Certified.Ordinary.checkRecursive._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (shape : Certified.Ordinary.Shape β) → + (ctor : Certified.Ordinary.Constructor β) → + (fields : List (Certified.Ordinary.RecursiveField β)) → + List (Certified.Ordinary.RecursiveWitness β) → + Option + (Certified.CheckedClaim + (∀ (field : Certified.Ordinary.RecursiveField β), + field ∈ fields → Certified.Ordinary.RecursiveEvidence entries shape ctor field)) + implementation: fun {β} [DecidableEq β] fuel entries shape ctor x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | field :: fields, witness :: witnesses => + if hrefs : ∀ (e : Model.AExpr β), e ∈ field.domains ++ field.indices → Model.AExpr.ReferencesIn entries e then do + let domains ← + Certified.verifyTelescope fuel shape.universes entries (some shape.level) (ctor.context shape) field.domains + witness.domains + let indices ← + Certified.verifyArguments fuel shape.universes entries + (Model.Telescope.context (ctor.context shape) field.domains) + (Model.Telescope.lift (ctor.fields.length + field.domains.length) shape.indices) field.indices + witness.indices + let rest ← Certified.Ordinary.checkRecursive._unsafe_rec fuel entries shape ctor fields witnesses + pure { down := ⋯ } + else none + | x, x_2 => none +compiler recursion worker Ix.Theory.Certified.Ordinary.parameterVars._unsafe_rec + type: {β : Type u} → Nat → Nat → List (Model.AExpr β) + implementation: fun {β} offset x => + match x with + | 0 => [] + | n.succ => Model.AExpr.bvar (offset + n) :: Certified.Ordinary.parameterVars._unsafe_rec offset n +compiler recursion worker Ix.Theory.Certified.PropWhen.bindList._unsafe_rec + type: (Nat → Certified.PropWhen) → List Nat → Certified.PropWhen + implementation: fun f x => + match x with + | [] => Certified.PropWhen.always + | i :: ps => (f i).inter (Certified.PropWhen.bindList._unsafe_rec f ps) +compiler recursion worker Ix.Theory.Certified.Signature.checkTypes._unsafe_rec + type: {β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (headers : List (Certified.Signature.Header β)) → + List (Certified.Signature.TypeWitness β) → + Option (Certified.CheckedClaim (Certified.Signature.Formed entries headers)) + implementation: fun {β} [DecidableEq β] fuel entries x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | header :: headers, witness :: witnesses => + if hf : entries header.ref = none then + if hs : Model.AExpr.Scope header.universes 0 header.type then + if hr : Model.AExpr.ReferencesIn entries header.type then do + let ht ← + Certified.verifyType fuel header.universes entries [] header.type (Model.AExpr.sort witness.level) + witness.typing + let rest ← + Certified.Signature.checkTypes._unsafe_rec fuel (entries.insert header.ref header.entry) headers witnesses + pure { down := ⋯ } + else none + else none + else none + | x, x_2 => none +compiler recursion worker Ix.Theory.Certified.Signature.environment._unsafe_rec + type: {β : Type u} → [DecidableEq β] → Model.Environment β → List (Certified.Signature.Header β) → Model.Environment β + implementation: fun {β} [DecidableEq β] entries x => + match x with + | [] => entries + | header :: rest => Certified.Signature.environment._unsafe_rec (entries.insert header.ref header.entry) rest +compiler recursion worker Ix.Theory.Certified.Structure.checkFields._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + Nat → + (entries : Model.Environment β) → + (w : VLevel) → + (Γ : Model.Context β) → + (fields : List (Certified.Structure.Field β)) → + List (Certified.TypingWitness β) → + Option (Certified.CheckedClaim (Certified.Structure.FieldsFormed entries w Γ fields)) + implementation: fun {β} [DecidableEq β] fuel n entries w x x_1 x_2 => + match x, x_1, x_2 with + | x, [], [] => some { down := ⋯ } + | Γ, field :: fields, witness :: witnesses => + if hz : Certified.checkZeroImplies w field.level = true then do + let hA ← Certified.verifyType fuel n entries Γ field.domain (Model.AExpr.sort field.level) witness + let rest ← + Certified.Structure.checkFields._unsafe_rec fuel n entries w (Model.Context.push field.domain Γ) fields + witnesses + pure { down := ⋯ } + else none + | x, x_3, x_4 => none +compiler recursion worker Ix.Theory.Certified.Structure.checkIota._unsafe_rec + type: {β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (d : Certified.Structure.Description β) → + (source recursor : β) → + (mode : Inductive.ElimMode) → + (fields : List (Certified.Structure.Field β × Nat)) → + List (Certified.Signature.RuleWitness β) → + Option + (Certified.CheckedClaim + (∀ (field : Certified.Structure.Field β) (i : Nat), + (field, i) ∈ fields → + Certified.Signature.RuleFormed (d.iotaEnvironment entries source recursor mode i) + (d.iotaRule source i field))) + implementation: fun {β} [DecidableEq β] fuel entries d source recursor mode x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | (field, i) :: fields, witness :: witnesses => do + let ht ← + Certified.Signature.checkRule fuel (d.iotaEnvironment entries source recursor mode i) (d.iotaRule source i field) + witness + let rest ← Certified.Structure.checkIota._unsafe_rec fuel entries d source recursor mode fields witnesses + pure { down := ⋯ } + | x, x_2 => none +compiler recursion worker Ix.Theory.Model.AExpr.Scope._unsafe_rec + type: {β : Type u_1} → Nat → Nat → Model.AExpr β → Prop + implementation: fun {β} universes depth x => + match x with + | Model.AExpr.bvar i => i < depth + | Model.AExpr.sort l => VLevel.WF universes l + | Model.AExpr.const ref ls => ∀ (l : VLevel), l ∈ ls → VLevel.WF universes l + | f.app a => Model.AExpr.Scope._unsafe_rec universes depth f ∧ Model.AExpr.Scope._unsafe_rec universes depth a + | Model.AExpr.lam p a b => + Certified.PropWhen.WF universes p ∧ + Model.AExpr.Scope._unsafe_rec universes depth a ∧ Model.AExpr.Scope._unsafe_rec universes (depth + 1) b + | Model.AExpr.forallE p a b => + Certified.PropWhen.WF universes p ∧ + Model.AExpr.Scope._unsafe_rec universes depth a ∧ Model.AExpr.Scope._unsafe_rec universes (depth + 1) b + | Model.AExpr.proj ref field e => Model.AExpr.Scope._unsafe_rec universes depth e + | Model.AExpr.natLit value => True +compiler recursion worker Ix.Theory.Model.AExpr.appN._unsafe_rec + type: {β : Type u} → Model.AExpr β → List (Model.AExpr β) → Model.AExpr β + implementation: fun {β} f x => + match x with + | [] => f + | x :: xs => Model.AExpr.appN._unsafe_rec (f.app x) xs +compiler recursion worker Ix.Theory.Model.AExpr.decidableScope._unsafe_rec + type: {β : Type u_1} → {n k : Nat} → {e : Model.AExpr β} → Decidable (Model.AExpr.Scope n k e) + implementation: fun {β} {n k} x => + match x with + | Model.AExpr.bvar i => Model.AExpr.decidableScope._aux_1 i + | Model.AExpr.sort l => VLevel.decidable_WF + | Model.AExpr.const ref ls => Model.AExpr.decidableScope._aux_3 ref ls + | f.app a => instDecidableAnd + | Model.AExpr.lam p A b => instDecidableAnd + | Model.AExpr.forallE p A b => instDecidableAnd + | Model.AExpr.proj ref field e => Model.AExpr.decidableScope._unsafe_rec + | Model.AExpr.natLit value => instDecidableTrue +compiler recursion worker Ix.Theory.Model.AExpr.erase._unsafe_rec + type: {β : Type u_1} → Model.AExpr β → VExpr β + implementation: fun {β} x => + match x with + | Model.AExpr.bvar i => VExpr.bvar i + | Model.AExpr.sort l => VExpr.sort l + | Model.AExpr.const r ls => VExpr.const r ls + | f.app a => (Model.AExpr.erase._unsafe_rec f).app (Model.AExpr.erase._unsafe_rec a) + | Model.AExpr.lam condition a b => (Model.AExpr.erase._unsafe_rec a).lam (Model.AExpr.erase._unsafe_rec b) + | Model.AExpr.forallE condition a b => (Model.AExpr.erase._unsafe_rec a).forallE (Model.AExpr.erase._unsafe_rec b) + | Model.AExpr.proj r i e => VExpr.proj r i (Model.AExpr.erase._unsafe_rec e) + | Model.AExpr.natLit v => VExpr.natLit v +compiler recursion worker Ix.Theory.Model.AExpr.forallN._unsafe_rec + type: {β : Type u} → Certified.PropWhen → List (Model.AExpr β) → Model.AExpr β → Model.AExpr β + implementation: fun {β} p x x_1 => + match x, x_1 with + | [], B => B + | A :: rest, B => Model.AExpr.forallE p A (Model.AExpr.forallN._unsafe_rec p rest B) +compiler recursion worker Ix.Theory.Model.AExpr.inst._unsafe_rec + type: {β : Type u_1} → Model.AExpr β → Model.AExpr β → optParam Nat 0 → Model.AExpr β + implementation: fun {β} x x_1 x_2 => + match x, x_1, x_2 with + | Model.AExpr.bvar i, a, k => Model.AExpr.instVar i a k + | Model.AExpr.sort l, x, x_3 => Model.AExpr.sort l + | Model.AExpr.const r ls, x, x_3 => Model.AExpr.const r ls + | f.app a, e, k => (Model.AExpr.inst._unsafe_rec f e k).app (Model.AExpr.inst._unsafe_rec a e k) + | Model.AExpr.lam p a b, e, k => + Model.AExpr.lam p (Model.AExpr.inst._unsafe_rec a e k) (Model.AExpr.inst._unsafe_rec b e (k + 1)) + | Model.AExpr.forallE p a b, e, k => + Model.AExpr.forallE p (Model.AExpr.inst._unsafe_rec a e k) (Model.AExpr.inst._unsafe_rec b e (k + 1)) + | Model.AExpr.proj r i e, a, k => Model.AExpr.proj r i (Model.AExpr.inst._unsafe_rec e a k) + | Model.AExpr.natLit v, x, x_3 => Model.AExpr.natLit v +compiler recursion worker Ix.Theory.Model.AExpr.instL._unsafe_rec + type: {β : Type u_1} → List VLevel → Model.AExpr β → Model.AExpr β + implementation: fun {β} levels x => + match x with + | Model.AExpr.bvar i => Model.AExpr.bvar i + | Model.AExpr.sort l => Model.AExpr.sort (VLevel.inst levels l) + | Model.AExpr.const r ls => Model.AExpr.const r (List.map (VLevel.inst levels) ls) + | f.app a => (Model.AExpr.instL._unsafe_rec levels f).app (Model.AExpr.instL._unsafe_rec levels a) + | Model.AExpr.lam p a b => + Model.AExpr.lam (Certified.instCondition levels p) (Model.AExpr.instL._unsafe_rec levels a) + (Model.AExpr.instL._unsafe_rec levels b) + | Model.AExpr.forallE p a b => + Model.AExpr.forallE (Certified.instCondition levels p) (Model.AExpr.instL._unsafe_rec levels a) + (Model.AExpr.instL._unsafe_rec levels b) + | Model.AExpr.proj r i e => Model.AExpr.proj r i (Model.AExpr.instL._unsafe_rec levels e) + | Model.AExpr.natLit v => Model.AExpr.natLit v +compiler recursion worker Ix.Theory.Model.AExpr.instRev._unsafe_rec + type: {β : Type u} → Model.AExpr β → List (Model.AExpr β) → Model.AExpr β + implementation: fun {β} x x_1 => + match x, x_1 with + | e, [] => e + | e, a :: rest => Model.AExpr.instRev._unsafe_rec (e.inst a rest.length) rest +compiler recursion worker Ix.Theory.Model.AExpr.lamN._unsafe_rec + type: {β : Type u} → Certified.PropWhen → List (Model.AExpr β) → Model.AExpr β → Model.AExpr β + implementation: fun {β} p x x_1 => + match x, x_1 with + | [], body => body + | A :: rest, body => Model.AExpr.lam p A (Model.AExpr.lamN._unsafe_rec p rest body) +compiler recursion worker Ix.Theory.Model.AExpr.liftN._unsafe_rec + type: {β : Type u_1} → Nat → Model.AExpr β → optParam Nat 0 → Model.AExpr β + implementation: fun {β} count x x_1 => + match x, x_1 with + | Model.AExpr.bvar i, k => Model.AExpr.bvar (liftVar count i k) + | Model.AExpr.sort l, x => Model.AExpr.sort l + | Model.AExpr.const r ls, x => Model.AExpr.const r ls + | f.app a, k => (Model.AExpr.liftN._unsafe_rec count f k).app (Model.AExpr.liftN._unsafe_rec count a k) + | Model.AExpr.lam p a b, k => + Model.AExpr.lam p (Model.AExpr.liftN._unsafe_rec count a k) (Model.AExpr.liftN._unsafe_rec count b (k + 1)) + | Model.AExpr.forallE p a b, k => + Model.AExpr.forallE p (Model.AExpr.liftN._unsafe_rec count a k) (Model.AExpr.liftN._unsafe_rec count b (k + 1)) + | Model.AExpr.proj r i e, k => Model.AExpr.proj r i (Model.AExpr.liftN._unsafe_rec count e k) + | Model.AExpr.natLit v, x => Model.AExpr.natLit v +compiler recursion worker Ix.Theory.Model.AExpr.mapRefs._unsafe_rec + type: {β : Type u} → {γ : Type v} → (ConstRef β → ConstRef γ) → Model.AExpr β → Model.AExpr γ + implementation: fun {β} {γ} mapping x => + match x with + | Model.AExpr.bvar i => Model.AExpr.bvar i + | Model.AExpr.sort level => Model.AExpr.sort level + | Model.AExpr.const ref levels => Model.AExpr.const (mapping ref) levels + | f.app a => (Model.AExpr.mapRefs._unsafe_rec mapping f).app (Model.AExpr.mapRefs._unsafe_rec mapping a) + | Model.AExpr.lam condition type body => + Model.AExpr.lam condition (Model.AExpr.mapRefs._unsafe_rec mapping type) + (Model.AExpr.mapRefs._unsafe_rec mapping body) + | Model.AExpr.forallE condition type body => + Model.AExpr.forallE condition (Model.AExpr.mapRefs._unsafe_rec mapping type) + (Model.AExpr.mapRefs._unsafe_rec mapping body) + | Model.AExpr.proj ref index major => + Model.AExpr.proj (mapping ref) index (Model.AExpr.mapRefs._unsafe_rec mapping major) + | Model.AExpr.natLit n => Model.AExpr.natLit n +compiler recursion worker Ix.Theory.Model.AExpr.references._unsafe_rec + type: {β : Type u} → Model.AExpr β → List (ConstRef β) + implementation: fun {β} x => + match x with + | Model.AExpr.bvar index => [] + | Model.AExpr.sort level => [] + | Model.AExpr.natLit value => [] + | Model.AExpr.const r levels => [r] + | f.app a => Model.AExpr.references._unsafe_rec f ++ Model.AExpr.references._unsafe_rec a + | Model.AExpr.lam condition f a => Model.AExpr.references._unsafe_rec f ++ Model.AExpr.references._unsafe_rec a + | Model.AExpr.forallE condition f a => Model.AExpr.references._unsafe_rec f ++ Model.AExpr.references._unsafe_rec a + | Model.AExpr.proj r field e => r :: Model.AExpr.references._unsafe_rec e +compiler recursion worker Ix.Theory.Model.AExpr.rename._unsafe_rec + type: {β : Type u_1} → {γ : Type u_2} → (β → γ) → Model.AExpr β → Model.AExpr γ + implementation: fun {β} {γ} mapping x => + match x with + | Model.AExpr.bvar i => Model.AExpr.bvar i + | Model.AExpr.sort l => Model.AExpr.sort l + | Model.AExpr.const r ls => Model.AExpr.const (ConstRef.rename mapping r) ls + | f.app a => (Model.AExpr.rename._unsafe_rec mapping f).app (Model.AExpr.rename._unsafe_rec mapping a) + | Model.AExpr.lam p a b => + Model.AExpr.lam p (Model.AExpr.rename._unsafe_rec mapping a) (Model.AExpr.rename._unsafe_rec mapping b) + | Model.AExpr.forallE p a b => + Model.AExpr.forallE p (Model.AExpr.rename._unsafe_rec mapping a) (Model.AExpr.rename._unsafe_rec mapping b) + | Model.AExpr.proj r i e => Model.AExpr.proj (ConstRef.rename mapping r) i (Model.AExpr.rename._unsafe_rec mapping e) + | Model.AExpr.natLit v => Model.AExpr.natLit v +compiler recursion worker Ix.Theory.Model.Telescope.context._unsafe_rec + type: {β : Type u} → Model.Context β → List (Model.AExpr β) → Model.Context β + implementation: fun {β} Γ x => + match x with + | [] => Γ + | A :: rest => Model.Telescope.context._unsafe_rec (Model.Context.push A Γ) rest +compiler recursion worker Ix.Theory.Model.Telescope.extend._unsafe_rec + type: {V : Type v} → (Nat → V) → List V → Nat → V + implementation: fun {V} env x => + match (motive := List V → Nat → V) x with + | [] => env + | x :: xs => Model.Telescope.extend._unsafe_rec (Model.Valuation.cons x env) xs +compiler recursion worker Ix.Theory.Model.Telescope.independent._unsafe_rec + type: {β : Type u} → List (Model.AExpr β) → optParam Nat 0 → List (Model.AExpr β) + implementation: fun {β} x x_1 => + match x, x_1 with + | [], x => [] + | A :: rest, offset => Model.AExpr.liftN offset A :: Model.Telescope.independent._unsafe_rec rest (offset + 1) +compiler recursion worker Ix.Theory.Model.Telescope.inst._unsafe_rec + type: {β : Type u} → Model.AExpr β → List (Model.AExpr β) → optParam Nat 0 → List (Model.AExpr β) + implementation: fun {β} arg x x_1 => + match x, x_1 with + | [], x => [] + | A :: rest, k => A.inst arg k :: Model.Telescope.inst._unsafe_rec arg rest (k + 1) +compiler recursion worker Ix.Theory.Model.Telescope.lift._unsafe_rec + type: {β : Type u} → Nat → List (Model.AExpr β) → optParam Nat 0 → List (Model.AExpr β) + implementation: fun {β} count x x_1 => + match x, x_1 with + | [], x => [] + | A :: rest, k => Model.AExpr.liftN count A k :: Model.Telescope.lift._unsafe_rec count rest (k + 1) +compiler recursion worker Ix.Theory.Model.Telescope.simple._unsafe_rec + type: {V : Type v} → (domains : List V) → Model.SetTheory.Tower.TeleS V domains.length + implementation: fun {V} x => + match x with + | [] => Model.SetTheory.Tower.TeleS.nil + | A :: rest => Model.SetTheory.Tower.TeleS.cons A fun x => Model.Telescope.simple._unsafe_rec rest +compiler recursion worker Ix.Theory.Model.instDecidableEqAExpr.decEq._unsafe_rec + type: {β : Type u_1} → [DecidableEq β] → (x x_1 : Model.AExpr β) → Decidable (x = x_1) + implementation: fun {β} [inst : DecidableEq β] x x_1 => + match x, x_1 with + | Model.AExpr.bvar a, Model.AExpr.bvar b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | Model.AExpr.bvar index, Model.AExpr.sort level => isFalse ⋯ + | Model.AExpr.bvar index, Model.AExpr.const ref levels => isFalse ⋯ + | Model.AExpr.bvar index, fn.app arg => isFalse ⋯ + | Model.AExpr.bvar index, Model.AExpr.lam condition domain body => isFalse ⋯ + | Model.AExpr.bvar index, Model.AExpr.forallE condition domain body => isFalse ⋯ + | Model.AExpr.bvar index, Model.AExpr.proj ref field major => isFalse ⋯ + | Model.AExpr.bvar index, Model.AExpr.natLit value => isFalse ⋯ + | Model.AExpr.sort level, Model.AExpr.bvar index => isFalse ⋯ + | Model.AExpr.sort a, Model.AExpr.sort b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ + | Model.AExpr.sort level, Model.AExpr.const ref levels => isFalse ⋯ + | Model.AExpr.sort level, fn.app arg => isFalse ⋯ + | Model.AExpr.sort level, Model.AExpr.lam condition domain body => isFalse ⋯ + | Model.AExpr.sort level, Model.AExpr.forallE condition domain body => isFalse ⋯ + | Model.AExpr.sort level, Model.AExpr.proj ref field major => isFalse ⋯ + | Model.AExpr.sort level, Model.AExpr.natLit value => isFalse ⋯ + | Model.AExpr.const ref levels, Model.AExpr.bvar index => isFalse ⋯ + | Model.AExpr.const ref levels, Model.AExpr.sort level => isFalse ⋯ + | Model.AExpr.const a a_1, Model.AExpr.const b b_1 => + if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯ + | Model.AExpr.const ref levels, fn.app arg => isFalse ⋯ + | Model.AExpr.const ref levels, Model.AExpr.lam condition domain body => isFalse ⋯ + | Model.AExpr.const ref levels, Model.AExpr.forallE condition domain body => isFalse ⋯ + | Model.AExpr.const ref levels, Model.AExpr.proj ref_1 field major => isFalse ⋯ + | Model.AExpr.const ref levels, Model.AExpr.natLit value => isFalse ⋯ + | fn.app arg, Model.AExpr.bvar index => isFalse ⋯ + | fn.app arg, Model.AExpr.sort level => isFalse ⋯ + | fn.app arg, Model.AExpr.const ref levels => isFalse ⋯ + | a.app a_1, b.app b_1 => + let inst_1 := Model.instDecidableEqAExpr.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst_2 := Model.instDecidableEqAExpr.decEq._unsafe_rec a a; + let inst_3 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | fn.app arg, Model.AExpr.lam condition domain body => isFalse ⋯ + | fn.app arg, Model.AExpr.forallE condition domain body => isFalse ⋯ + | fn.app arg, Model.AExpr.proj ref field major => isFalse ⋯ + | fn.app arg, Model.AExpr.natLit value => isFalse ⋯ + | Model.AExpr.lam condition domain body, Model.AExpr.bvar index => isFalse ⋯ + | Model.AExpr.lam condition domain body, Model.AExpr.sort level => isFalse ⋯ + | Model.AExpr.lam condition domain body, Model.AExpr.const ref levels => isFalse ⋯ + | Model.AExpr.lam condition domain body, fn.app arg => isFalse ⋯ + | Model.AExpr.lam a a_1 a_2, Model.AExpr.lam b b_1 b_2 => + if h : a = b then + h ▸ + let inst_1 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst_2 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 a_1; + let inst_3 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Model.AExpr.lam condition domain body, Model.AExpr.forallE condition_1 domain_1 body_1 => isFalse ⋯ + | Model.AExpr.lam condition domain body, Model.AExpr.proj ref field major => isFalse ⋯ + | Model.AExpr.lam condition domain body, Model.AExpr.natLit value => isFalse ⋯ + | Model.AExpr.forallE condition domain body, Model.AExpr.bvar index => isFalse ⋯ + | Model.AExpr.forallE condition domain body, Model.AExpr.sort level => isFalse ⋯ + | Model.AExpr.forallE condition domain body, Model.AExpr.const ref levels => isFalse ⋯ + | Model.AExpr.forallE condition domain body, fn.app arg => isFalse ⋯ + | Model.AExpr.forallE condition domain body, Model.AExpr.lam condition_1 domain_1 body_1 => isFalse ⋯ + | Model.AExpr.forallE a a_1 a_2, Model.AExpr.forallE b b_1 b_2 => + if h : a = b then + h ▸ + let inst_1 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst_2 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_1 a_1; + let inst_3 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Model.AExpr.forallE condition domain body, Model.AExpr.proj ref field major => isFalse ⋯ + | Model.AExpr.forallE condition domain body, Model.AExpr.natLit value => isFalse ⋯ + | Model.AExpr.proj ref field major, Model.AExpr.bvar index => isFalse ⋯ + | Model.AExpr.proj ref field major, Model.AExpr.sort level => isFalse ⋯ + | Model.AExpr.proj ref field major, Model.AExpr.const ref_1 levels => isFalse ⋯ + | Model.AExpr.proj ref field major, fn.app arg => isFalse ⋯ + | Model.AExpr.proj ref field major, Model.AExpr.lam condition domain body => isFalse ⋯ + | Model.AExpr.proj ref field major, Model.AExpr.forallE condition domain body => isFalse ⋯ + | Model.AExpr.proj a a_1 a_2, Model.AExpr.proj b b_1 b_2 => + if h : a = b then + h ▸ + if h : a_1 = b_1 then + h ▸ + let inst_1 := Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Model.instDecidableEqAExpr.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Model.AExpr.proj ref field major, Model.AExpr.natLit value => isFalse ⋯ + | Model.AExpr.natLit value, Model.AExpr.bvar index => isFalse ⋯ + | Model.AExpr.natLit value, Model.AExpr.sort level => isFalse ⋯ + | Model.AExpr.natLit value, Model.AExpr.const ref levels => isFalse ⋯ + | Model.AExpr.natLit value, fn.app arg => isFalse ⋯ + | Model.AExpr.natLit value, Model.AExpr.lam condition domain body => isFalse ⋯ + | Model.AExpr.natLit value, Model.AExpr.forallE condition domain body => isFalse ⋯ + | Model.AExpr.natLit value, Model.AExpr.proj ref field major => isFalse ⋯ + | Model.AExpr.natLit a, Model.AExpr.natLit b => if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯ +compiler recursion worker Ix.Theory.Model.instDecidableEqAnnotationTree.decEq._unsafe_rec + type: (x x_1 : Model.AnnotationTree) → Decidable (x = x_1) + implementation: fun x x_1 => + match x, x_1 with + | Model.AnnotationTree.leaf, Model.AnnotationTree.leaf => isTrue ⋯ + | Model.AnnotationTree.leaf, fn.app arg => isFalse ⋯ + | Model.AnnotationTree.leaf, Model.AnnotationTree.lam condition domain body => isFalse ⋯ + | Model.AnnotationTree.leaf, Model.AnnotationTree.forallE condition domain body => isFalse ⋯ + | Model.AnnotationTree.leaf, major.proj => isFalse ⋯ + | fn.app arg, Model.AnnotationTree.leaf => isFalse ⋯ + | a.app a_1, b.app b_1 => + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a a; + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_1 a_1; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + | fn.app arg, Model.AnnotationTree.lam condition domain body => isFalse ⋯ + | fn.app arg, Model.AnnotationTree.forallE condition domain body => isFalse ⋯ + | fn.app arg, major.proj => isFalse ⋯ + | Model.AnnotationTree.lam condition domain body, Model.AnnotationTree.leaf => isFalse ⋯ + | Model.AnnotationTree.lam condition domain body, fn.app arg => isFalse ⋯ + | Model.AnnotationTree.lam a a_1 a_2, Model.AnnotationTree.lam b b_1 b_2 => + if h : a = b then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_1 a_1; + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Model.AnnotationTree.lam condition domain body, Model.AnnotationTree.forallE condition_1 domain_1 body_1 => + isFalse ⋯ + | Model.AnnotationTree.lam condition domain body, major.proj => isFalse ⋯ + | Model.AnnotationTree.forallE condition domain body, Model.AnnotationTree.leaf => isFalse ⋯ + | Model.AnnotationTree.forallE condition domain body, fn.app arg => isFalse ⋯ + | Model.AnnotationTree.forallE condition domain body, Model.AnnotationTree.lam condition_1 domain_1 body_1 => + isFalse ⋯ + | Model.AnnotationTree.forallE a a_1 a_2, Model.AnnotationTree.forallE b b_1 b_2 => + if h : a = b then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_1 b_1; + if h : a_1 = b_1 then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_1 a_1; + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_2 b_2; + if h : a_2 = b_2 then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a_2 a_2; + isTrue ⋯ + else isFalse ⋯ + else isFalse ⋯ + else isFalse ⋯ + | Model.AnnotationTree.forallE condition domain body, major.proj => isFalse ⋯ + | major.proj, Model.AnnotationTree.leaf => isFalse ⋯ + | major.proj, fn.app arg => isFalse ⋯ + | major.proj, Model.AnnotationTree.lam condition domain body => isFalse ⋯ + | major.proj, Model.AnnotationTree.forallE condition domain body => isFalse ⋯ + | a.proj, b.proj => + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a b; + if h : a = b then + h ▸ + let inst := Model.instDecidableEqAnnotationTree.decEq._unsafe_rec a a; + isTrue ⋯ + else isFalse ⋯ +compiler recursion worker Ix.Theory.Model.instReprAnnotationTree.repr._unsafe_rec + type: Model.AnnotationTree → Nat → Format + implementation: fun x prec => + match x with + | Model.AnnotationTree.leaf => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Ix.Theory.Model.AnnotationTree.leaf")).group prec + | a.app a_1 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Ix.Theory.Model.AnnotationTree.app" ++ Format.line ++ + Model.instReprAnnotationTree.repr._unsafe_rec a 1024 ++ + Format.line ++ + Model.instReprAnnotationTree.repr._unsafe_rec a_1 1024)).group + prec + | Model.AnnotationTree.lam a a_1 a_2 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Ix.Theory.Model.AnnotationTree.lam" ++ Format.line ++ reprArg a ++ Format.line ++ + Model.instReprAnnotationTree.repr._unsafe_rec a_1 1024 ++ + Format.line ++ + Model.instReprAnnotationTree.repr._unsafe_rec a_2 1024)).group + prec + | Model.AnnotationTree.forallE a a_1 a_2 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Ix.Theory.Model.AnnotationTree.forallE" ++ Format.line ++ reprArg a ++ Format.line ++ + Model.instReprAnnotationTree.repr._unsafe_rec a_1 1024 ++ + Format.line ++ + Model.instReprAnnotationTree.repr._unsafe_rec a_2 1024)).group + prec + | a.proj => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Ix.Theory.Model.AnnotationTree.proj" ++ Format.line ++ + Model.instReprAnnotationTree.repr._unsafe_rec a 1024)).group + prec +compiler recursion worker Ix.Theory.Certified.Ordinary.Shape.checkConstructorTypes._unsafe_rec + type: {β : Type u} → + [inst : DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (shape : Certified.Ordinary.Shape β) → + (source : β) → + (ctors : List (Certified.Ordinary.Constructor β)) → + List (Certified.Ordinary.Shape.TypeWitness β) → + Option + (Certified.CheckedClaim + (∀ (ctor : Certified.Ordinary.Constructor β), + ctor ∈ ctors → + Model.EntryClosed (shape.familyEnvironment entries source) + (shape.constructorEntry source ctor) ∧ + ∃ l, + Model.TypingClaim (shape.familyEnvironment entries source) [] (ctor.type shape source) + (Model.AExpr.sort l))) + implementation: fun {β} [DecidableEq β] fuel entries shape source x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | ctor :: ctors, witness :: witnesses => + if hs : Model.AExpr.Scope shape.universes 0 (ctor.type shape source) then + if hr : Model.AExpr.ReferencesIn (shape.familyEnvironment entries source) (ctor.type shape source) then do + let ht ← + Certified.verifyType fuel shape.universes (shape.familyEnvironment entries source) [] (ctor.type shape source) + (Model.AExpr.sort witness.level) witness.witness + let rest ← Certified.Ordinary.Shape.checkConstructorTypes._unsafe_rec fuel entries shape source ctors witnesses + pure { down := ⋯ } + else none + else none + | x, x_2 => none +compiler recursion worker Ix.Theory.Certified.Ordinary.Shape.checkRules._unsafe_rec + type: {β : Type u} → + [DecidableEq β] → + Nat → + (entries : Model.Environment β) → + (shape : Certified.Ordinary.Shape β) → + (source recursor : β) → + (mode : Inductive.ElimMode) → + (ctors : List (Certified.Ordinary.Constructor β × Nat)) → + List (Certified.Ordinary.RuleWitness β) → + Option + (Certified.CheckedClaim + (∀ (ctor : Certified.Ordinary.Constructor β) (i : Nat), + (ctor, i) ∈ ctors → + Certified.Ordinary.Shape.RuleFormation entries shape source recursor mode i ctor)) + implementation: fun {β} [DecidableEq β] fuel entries shape source recursor mode x x_1 => + match x, x_1 with + | [], [] => some { down := ⋯ } + | (ctor, i) :: ctors, witness :: witnesses => do + let rule ← Certified.Ordinary.Shape.checkRule fuel entries shape source recursor mode i ctor witness + let rest ← Certified.Ordinary.Shape.checkRules._unsafe_rec fuel entries shape source recursor mode ctors witnesses + pure { down := ⋯ } + | x, x_2 => none +compiler recursion worker Ix.Theory.Model.SetTheory.Tower.BoundS._unsafe_rec + type: {V : Type u} → [Model.SetTheory V] → Nat → {n : Nat} → Model.SetTheory.Tower.TeleS V n → Prop + implementation: fun {V} [Model.SetTheory V] w x x_1 => + match x, x_1 with + | .(0), Model.SetTheory.Tower.TeleS.nil => True + | .(n + 1), Model.SetTheory.Tower.TeleS.cons A B => + Model.SetTheory.Mem A (Model.SetTheory.univ w) ∧ + ∀ (a : V), Model.SetTheory.Mem a A → Model.SetTheory.Tower.BoundS._unsafe_rec w (B a) +compiler recursion worker Ix.Theory.Model.SetTheory.Tower.FitsS._unsafe_rec + type: {V : Type u} → [Model.SetTheory V] → {n : Nat} → Model.SetTheory.Tower.TeleS V n → List V → Prop + implementation: fun {V} [Model.SetTheory V] x x_1 x_2 => + match x, x_1, x_2 with + | .(0), Model.SetTheory.Tower.TeleS.nil, [] => True + | .(0), Model.SetTheory.Tower.TeleS.nil, head :: tail => False + | .(n + 1), Model.SetTheory.Tower.TeleS.cons A B, [] => False + | .(n + 1), Model.SetTheory.Tower.TeleS.cons A B, a :: as => + Model.SetTheory.Mem a A ∧ Model.SetTheory.Tower.FitsS._unsafe_rec (B a) as +compiler recursion worker Ix.Theory.Model.SetTheory.Tower.PropS._unsafe_rec + type: {V : Type u} → [Model.SetTheory V] → {n : Nat} → Model.SetTheory.Tower.TeleS V n → Prop + implementation: fun {V} [Model.SetTheory V] x x_1 => + match x, x_1 with + | .(0), Model.SetTheory.Tower.TeleS.nil => True + | .(n + 1), Model.SetTheory.Tower.TeleS.cons A B => + Model.SetTheory.Mem A Model.SetTheory.univZero ∧ + ∀ (a : V), Model.SetTheory.Mem a A → Model.SetTheory.Tower.PropS._unsafe_rec (B a) +Certified project runtime audit OK: 101 compiler recursion workers inventoried; no other unsafe/partial declarations, extern, implemented_by, computed_field, or csimp replacements in the mathematical import graph +Certified foundation audit OK: 6568 declarations; 145 named roots; explicit SetTheory hypothesis; baseline axioms only diff --git a/crates/kernel/src/def_eq.rs b/crates/kernel/src/def_eq.rs index 7e04e0170..8e0010007 100644 --- a/crates/kernel/src/def_eq.rs +++ b/crates/kernel/src/def_eq.rs @@ -563,7 +563,7 @@ impl TypeChecker<'_, M> { break; } - // C6: Before unfolding a definition, try reducing projection apps + // Before unfolding a definition, try reducing projection apps // on the non-definition side (lean4lean tryUnfoldProjApp). if a_delta && !b_delta { if let Some(wb2) = self.try_unfold_proj_app(wb)? { @@ -1566,7 +1566,7 @@ impl TypeChecker<'_, M> { } // ----------------------------------------------------------------------- - // Post-delta congruence and projection unfolding (C5, C6) + // Post-delta congruence and projection unfolding // ----------------------------------------------------------------------- /// Structural congruence after lazy delta exhaustion (lean4lean isDefEqConst/Proj). diff --git a/crates/kernel/src/inductive.rs b/crates/kernel/src/inductive.rs index b5f0bc436..222ec5254 100644 --- a/crates/kernel/src/inductive.rs +++ b/crates/kernel/src/inductive.rs @@ -4949,7 +4949,7 @@ flat[{gi}].id={}, rec_ids[{gi}]={}; complete recursor types differ", Ok(()) }, None => { - // C2: No generated recursor found — MUST NOT silently pass. + // Reject a recursor with no generated candidate for its major type. // If we can't generate a canonical recursor, we can't verify the provided one. Err(TcError::Other(format!( "check_recursor: no generated recursor for major {}", diff --git a/docs/benchmarking.md b/docs/benchmarking.md index e5a566412..e545248f6 100644 --- a/docs/benchmarking.md +++ b/docs/benchmarking.md @@ -85,11 +85,6 @@ ix bench fetch-main --sha $(git merge-base origin/main HEAD) \ ix bench compare --backend aiur --env InitStd --mode prove \ --base main.json --pr .lake/benches/aiur-InitStd-prove.json -# The lean4lean reference kernel over InitStd — whole-library replay plus -# per-constant closure rows, from oleans (no .ixe needed). Read next to the -# ooc cell's rows for the Rust-vs-reference-kernel gap on the same library: -ix bench run --backend lean4lean --env InitStd -ix bench compare --backend lean4lean --env InitStd ``` `--repo ` points the run at another checkout: the *measured* tools @@ -104,7 +99,6 @@ a PR tree and compare them — exactly what the PR workflow does. | `zisk` | ZisK VM execute: cycles, execute-time, throughput, peak-rss, constants (pre-shard closure count, same universe as aiur's), shards (the runtime-planned partition size; 1 when the closure fits) | `zisk-host` | | `sp1` | SP1 VM execute (currently disabled in the registry) | `sp1-host` | | `ooc` | out-of-circuit Rust kernel: whole-env row + one full-closure row per constant (`check-time` wraps only the check — the env loads once, outside every row's timed window) | `ix check-rs --json` | -| `lean4lean` | the reference Lean4-in-Lean4 kernel ([digama0/lean4lean](https://github.com/digama0/lean4lean), required by the lakefile at a pinned rev) — the external yardstick for the Ix kernels on the same libraries. Olean-driven (no `.ixe`): the whole-library row replays every module in the env's import closure through lean4lean, module-parallel (check-time, constants, throughput, peak-rss; tune parallelism with `LEAN_NUM_THREADS`), plus one full-closure row per constant (the name's transitive closure into a fresh kernel env), mirroring ooc's row shape. Registry-disabled for CI (no bencher testbed yet); `ix bench run --backend lean4lean` works locally regardless | `bench-lean4lean` | | `compile` | `ix compile .lean → .ixe`: compile-time, file-size, constants, throughput | `ix compile --json` | | `decompile` | inverse of compile — `ix decompile .ixe → Lean consts`: decompile-time, throughput, peak-rss, constants, file-size (input `.ixe`). Consumes the compile cell's `.ixe` rather than producing one; a malformed decompile reddens the cell. Deep roundtrip fidelity is gated by the canonical checks (`ix validate` / roundtrip tests), which need the original Lean env the `.ixe` can't supply | `ix decompile --json` | diff --git a/docs/certified-checking.md b/docs/certified-checking.md new file mode 100644 index 000000000..c0f8b6057 --- /dev/null +++ b/docs/certified-checking.md @@ -0,0 +1,160 @@ +# Certified source and claim checking + +Ix contains certified source and claim adapters under +`Ix.Certified`, with checker wrappers in `Ix.Kernel.Certified` and +`Ix.Kernel.CertifiedClaims`. Successful validation constructs receipts that +connect the authenticated Ixon source to the set model in `Ix.Theory`. +The maintained implementation and its regression evidence are local to this +repository. + +The certificate profile checks a specific collection of declaration forms +and logical schemas. Witness search supplies proposals; the certified +validator checks every proposal before reporting success. Unsupported forms, +missing models and unsuccessful searches decline. These commands provide an +explicit entry point for that profile. + +## Commands + +Build the source and claim commands: + +```sh +lake build --wfail certified-check certified-claim-check +``` + +Source checking takes a lazy `.ixe` file and a JSON request that selects the +target or subjects, primitive addresses, source objects and natural values: + +```sh +.lake/build/bin/certified-check proof SOURCE.ixe REQUEST.json +.lake/build/bin/certified-check store SOURCE.ixe REQUEST.json +``` + +The request fields are `target`, `subjects`, `objects`, `naturals`, +`falseType`, `falseElim`, nullable `natType`, and optional `models`. Addresses +are 32-byte hexadecimal strings. Model hints select earlier source +declarations; the validator checks their types and complete source equations. +The request parser is defined in +[`Command.lean`](../Ix/Certified/Command.lean). + +For a runnable source example: + +```sh +lake build certified-source-tests +.lake/build/bin/certified-source-tests /tmp/ix-certified-examples +.lake/build/bin/certified-check proof \ + /tmp/ix-certified-examples/identity/source.ixe \ + /tmp/ix-certified-examples/identity/request.json +``` + +Claim checking also takes the exact serialized envelope. The JSON request +selects its expected address and supplies logical, membership or revelation +witness hints: + +```sh +.lake/build/bin/certified-claim-check SOURCE.ixe ENVELOPE.bin REQUEST.json +``` + +The envelope binds the claim, primitive profile, logical-axiom manifest and +protocol versions. The current checker version is **2**; format, codec, +policy and aggregation versions are **1**. Exact decoding, canonical +re-encoding, the expected content address and all versions are checked. +Trailing bytes and older checker envelopes reject. See +[`Envelope.lean`](../Ix/Certified/Envelope.lean) and +[`ClaimCommand.lean`](../Ix/Certified/ClaimCommand.lean). + +Both commands currently use fuel 6,400. Success exits 0 and prints a JSON +acceptance record; a rejected request exits 1. Fuel or witness-search failure +can reject a valid source, so success and completeness are separate +properties. + +## Semantic contract + +`ClaimCommand.run_meaning` proves that successful pure command execution +produces a receipt for the exact envelope bytes and establishes +`SemanticClaimMeaning`. For logical claims, the receipt preserves the +original source statements and constructs a compatible interpretation while +preserving the declared frontier. Model companions for mutual and nested +inductives must already have been checked; their complete recursor equations +are validated before the new source package is admitted. + +For a logical receipt with no structural frontier, +`LogicalReceipt.closed_subject_meaning` constructs its model. +`LogicalReceipt.no_False` then rules out a checked subject whose type is the +profile's false proposition, under the explicit `[SetTheory V]` hypothesis. +The admitted logical schemas have realizations in that model. A closed +structural frontier does not imply an empty logical-axiom manifest; the +manifest records admitted source axioms under the enforced policy. + +Membership and revelation establish their respective structural meanings. +Evaluation claims are excluded from this semantic profile. The relevant +definitions and statements are in +[`ClaimAccept.lean`](../Ix/Certified/ClaimAccept.lean), +[`ClaimMeaning.lean`](../Ix/Certified/ClaimMeaning.lean) and +[`LogicalPolicy.lean`](../Ix/Theory/Certified/LogicalPolicy.lean). + +The mathematical contract concerns the Lean functions. Native Lean +execution, filesystem loading and the BLAKE3 foreign interface remain +execution boundaries. Full production-checker refinement and execution +of this certification inside an authenticated Aiur proof remain separate +obligations described in +[`kernel-verification.md`](kernel-verification.md). + +## Audits and regression evidence + +Run the complete local gate with: + +```sh +lake run check-certified +``` + +The gate builds the adapters, audits and test programs with warnings treated +as errors. It compares the exact foundation report, checks the frozen source +archive and maintained import identities, runs six native host test programs, +and exercises the actual source and claim executables on all three CLI +corpora. CI runs the same gate. + +The combined audit covers **86 distinct roots**, **74 premise definitions or +constructor types**, **9,682 logical declarations** and **10,957 declarations +including runtime dependencies**. The five historical component audits +remain independently callable. All 90 historical root occurrences and 75 +premise occurrences retain their statements after namespace qualification is +normalized. The exact report is +[`Tests/Certified/foundation.txt`](../Tests/Certified/foundation.txt). + +The audit traverses full checked types, bodies and inductive constructors. +It checks exact axiom sets and follows compiler recursion workers and +executable replacements transitively, including private constants. These +roots use only `propext`, `Classical.choice` and `Quot.sound`. The runtime +inventory records five BLAKE3 foreign operations and 130 recursion workers +with safe source definitions; it permits no partial opaque worker source or +executable replacement. + +This stronger traversal exposed a native-evaluation axiom that the historical +imported axiom summaries missed. It came from the BLAKE3 helper's 32-byte +output bound. `Address.blake3` now supplies a kernel-checked proof of that +bound. The wrapper is definitionally equal to the former hash operation, +and generated source/envelope corpora are unchanged. +The affected kernel and source-compiler audits also remove this dependency. + +| Actual command corpus | Fixtures | Accepted | Rejected | +| --- | ---: | ---: | ---: | +| Source proof/store | 42 source fixtures | 84 | 562 | +| Versioned claims | 1,578 claim fixtures | 584 | 5,454 | +| Modeled source and claims | 44 source and 74 claim fixtures | 30 | 540 | + +The native modeled tests additionally cover 29 source mutations with accepted +controls, 42 forged witnesses and nine malformed mutual inputs. The other +native suites cover source fidelity, lazy loading, cold/warm caches, +rollback, claim cycles, shared dependencies, membership and revelation. + +All generated source and envelope bytes and CLI process outputs are +compared against the frozen adapter evidence. Host reports preserve every +non-VM field; only `pilotDeclined` and `pilotDeclines` are projected away +from the three historical reports that mixed host and VM checks. The VM +pilot, packet encoder and VM execution suite are archived for a later change. +CLI JSON requests and aggregate records are compared as parsed values because +the maintained Lean driver formats JSON differently. The archive, source mappings, licenses and +historical reproduction limits are documented in +[`Tests/Fixtures/Certified`](../Tests/Fixtures/Certified/README.md). The archive +recovers the selected adapter sources and fixtures; it does not include the +complete historical Ix base checkout. diff --git a/docs/ix_canonicity.md b/docs/ix_canonicity.md index 0616e2197..bdaa5bc19 100644 --- a/docs/ix_canonicity.md +++ b/docs/ix_canonicity.md @@ -1490,7 +1490,7 @@ this rule closes that gap. **The quotient.** Universe-level spellings are presentation, not content. Two levels are identified in canonical form exactly when the kernels' semantic level equality holds — `univEq` -(`Ix/Tc/Level.lean`), the relation all three kernels decide during +(`Ix/Kernel/Level.lean`), the relation all three kernels decide during defeq. `univEq`'s normal-form comparison ignores EMPTY subsumption entries (constant 0, no vars — bookkeeping the subsumption pass leaves behind rather than removing; `normLevelLe` always ignored @@ -1518,7 +1518,7 @@ unnormalized substitution results). **Canonical representative.** `canonUniv : Univ → Univ` is `linearize ∘ subsumption ∘ normalizeAux` — the kernels' Géran -comparison form (`normalizeLevel`, `Ix/Tc/Level.lean:227-472`; +comparison form (`normalizeLevel`, `Ix/Kernel/Level.lean:227-472`; `crates/kernel/src/level.rs:335-696`; `Ix/IxVM/Kernel/Levels.lean:336-386`), transliterated to positional `Ixon.Univ` and then linearized back into a level term. The Géran @@ -1556,7 +1556,7 @@ tests in both languages: - **P5 (mirror parity):** Rust and Lean `canonUniv` agree byte-for-byte on serialized output. - **P6 (mk\* absorption):** `canonUniv ∘ reduceIxonUniv = canonUniv` - (`reduceIxonUniv`, `Ix/Tc/Ingress.lean`, is the retained oracle + (`reduceIxonUniv`, `Ix/Kernel/Ingress.lean`, is the retained oracle for this). `canonUniv` lives next to the wire type (`crates/ixon/src/univ.rs` @@ -1565,13 +1565,13 @@ and probes share one implementation per language; the three kernel `NormLevel` implementations stay untouched as the P4 oracle. Worst case, canonical forms are exponential in nested `imax`-of-`max` depth (the Géran distribution rules duplicate the left subterm, -`Ix/Tc/Level.lean:333-351`); real levels are a handful of nodes, and +`Ix/Kernel/Level.lean:333-351`); real levels are a handful of nodes, and the blowup is paid once at compile time by whoever writes a pathological spelling — never by readers of stored canonical forms. **The kernel-rebuild rule set.** The `mk*` simplification rules — Lean `kernel/level.cpp:81-103`/`:112-120`, mirrored at -`Ix/Tc/Level.lean:144-197`, `crates/kernel/src/level.rs:162-247`, +`Ix/Kernel/Level.lean:144-197`, `crates/kernel/src/level.rs:162-247`, `Ix/IxVM/Kernel/Levels.lean:637-680` — are normative here in three roles: the P3 fixpoint target (kernel ingress rebuilds through them), the stage-1 decoration-presence test (below), and the P6 oracle. @@ -1601,7 +1601,7 @@ They are **not** the address quotient (they miss commutative twins). | I6 | otherwise raw `imax a b` | — | with predicates `isZero` / `isExplicit` (`succ^n zero`) / -`isNeverZero` / `offset` exactly as in `Ix/Tc/Level.lean:64-95` / +`isNeverZero` / `offset` exactly as in `Ix/Kernel/Level.lean:64-95` / `crates/kernel/src/level.rs:111-150`. Both rule sets — `mk*` and the Géran linearization — are **frozen** at the pinned toolchain's behavior; upstream drift mints new spellings, which simply @@ -1663,11 +1663,11 @@ class as binder names, and is caught by the strict roundtrip gates). one kernel-side consumer: the original spelling rides as a **decoration** on meta-mode `sort`/`const` occurrence nodes — folded into the metadata-aware `metaAddr` (so interning and egress -memoization never collapse spelling twins, `Ix/Tc/Expr.lean:61-72`) +memoization never collapse spelling twins, `Ix/Kernel/Expr.lean:61-72`) and **never** into the semantic `addr` (anon/meta address parity, `tc-meta-addr`, is preserved; checking never sees spellings). Meta egress replays the decoration at its `sort`/`const` arms -(`Ix/Tc/EgressLean.lean:119-128`) instead of egressing the +(`Ix/Kernel/EgressLean.lean:119-128`) instead of egressing the normalized kernel level. Decorations must not live on `KUniv` nodes — KUniv interning is semantic-address-keyed and would collapse spelling twins first-wins, the same lossiness as table-keyed @@ -1677,7 +1677,7 @@ comparison and is an active spelling-fidelity gate through the kernel's data path, complementing the decompiler gate (phase 5). With stored content canonical, the anon roundtrip comparison is strict too (the `reduceIxonUniv` modulo in `canonExpr` was deleted; -`Ix/Tc/Egress.lean` module doc). +`Ix/Kernel/Egress.lean` module doc). **Decoration source.** Patches are the primary source: meta ingress looks the occurrence's (post-mdata) arena index up in `univPatches` @@ -2309,13 +2309,13 @@ Phase 2 paths already were). Remaining audit items: `restoreLeanSourceNameHints` / `restoreSourceNamesSameContent` in `Ix/AuxGen/Kernel.lean`) match arm-for-arm; what diverged — and produced the Mathlib redStep instance — was the **key - equivalence**: the Lean side keys hints by `Ix.Tc.KExpr` content + equivalence**: the Lean side keys hints by `Ix.Kernel.KExpr` content addresses, while the Rust side keyed by `KExpr::hash_key()`, which is an intern-assigned uid, fresh for every un-interned `to_kexpr_static` construction — so no restore-time key ever matched a collect-time key and the Rust hint pass restored nothing. Originally fixed by `kexpr_content_key` (a pure name-erased structural - digest mirroring the `ExprKey`/`Ix.Tc` equivalence) and by making the + digest mirroring the `ExprKey`/`Ix.Kernel` equivalence) and by making the WHNF no-op test structural (`==`) rather than uid equality. The hint pass now uses exact, pass-local structural identities instead of that digest, with full shallow-key equality on hash collisions. Any future @@ -2378,7 +2378,7 @@ pipelines; decompile patch replay; the decoration source switch to patches (stage-1 rule retained as the patchless fallback); phase 3 strict; `univEq` empty-entry-insensitive (the exact semantic quotient, §10.6); primitive pins regenerated in all mirrors -(`prim_addrs.rs`, `Ix/Tc/Primitive.lean`, the IxVM address +(`prim_addrs.rs`, `Ix/Kernel/Primitive.lean`, the IxVM address literals); artifacts regenerated with the format-break hint. **Acceptance evidence:** `ix validate` and `ix validate-lean` at diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md new file mode 100644 index 000000000..7dfc385f7 --- /dev/null +++ b/docs/kernel-verification.md @@ -0,0 +1,144 @@ +# Kernel verification + +`Ix.Kernel` is the production Lean checker. `Ix.Kernel.Verify` contains its +implementation proofs; `Ix.Compile.Verify` contains the Lean-to-Ixon compiler +proofs. Their named specification and reference implementation lemmas are local +under `Ix.Theory.Named`. Building or checking them requires no external +formalization repository. + +The named development retains the 104 source modules needed by the existing +proof dependency graph, including the inductive fixtures consumed by Ix. +Standalone applications, benchmarks, and unrelated tests are excluded. Its +original source hashes and attribution are recorded in `Ix/Theory/Named/NOTICE` +and `Tests/Theory/NamedManifest.lean`; the Apache license is preserved alongside +the sources. The added axiom-audit helper is authored in Ix. + +## Connection to the consistency model + +The name-indexed specification and the set model use the same +`Ix.Theory.VLevel`. The set model and its foundational audit remain independent +of the named development. Mathlib is confined to the separate +[set-theory model package](../Models/SetTheory/README.md). + +That package's `IxSetTheoryModel.setTheoryOfCarneiro` constructs the exact +`Ix.Theory.Model.SetTheory` interface on Mathlib's `ZFSet`. It takes an explicit +`OmegaInaccessibles` hypothesis: a strictly increasing countable sequence of +strongly inaccessible cardinals. The universe chain is `V_ (κ n).ord`. +`carneiro_implies_ix` proves model existence under this hypothesis, with a full +dependency audit restricted to Lean's three standard axioms. + +`Ix.Kernel.Verify.Consistency` proves the following direct connections: + +- Production universe equality and ordering agree with model evaluation, + under the existing finite address-faithfulness and arithmetic bounds. +- A structural reader maps kernel expressions to model syntax, resolves + addresses to explicit store references, preserves projections and natural + literals, and substitutes let values. Free variables, unresolved addresses, + and string literals are outside the current reader's domain. +- Hash equality and intern-table reuse preserve that reading under their + stated address/key collision assumptions. Metadata cannot change it. +- `inferUncached_sort_sound` interprets an actual successful execution of the + production sort-inference branch. It proves the model typing postcondition + for the returned type, including intern-table reuse. +- `ModelTyping.no_false` rules out a closed model-typed kernel expression at + primitive False when its environment has been admitted by the certified + interface and the set-theory assumption has an instance. + +The last theorem assumes semantic typing; it does not assume or prove that +arbitrary checker success supplies it. A complete checker consistency theorem +still requires the remaining inference/conversion cases, cache invariants, +address-to-store resolution, and declaration admission to establish that +postcondition for `checkEnvAnon`. The existing named-calculus proofs are retained +to support this refinement, rather than being treated as a set-model proof. + +## Trust checks + +The audits traverse checked declaration types and bodies, including inductive +constructors. They compare exact axiom sets and record direct origins of +`sorryAx`; they do not rely on cached imported axiom summaries. During the +migration, full traversal of the original sources exposed two wrapper reports +that listed 3 axioms but depended on 30. Their boundaries now include the +existing implementation assumptions and unfinished metatheory. All 441 retained +named-specification assertions use the original full dependency graphs as their +migration baseline. + +The same traversal covers 2,034 kernel manifest roots. Thirteen entries omitted +logical or native dependencies through constructor fields; their corrected +boundaries were checked against freshly compiled pre-migration sources. Direct +dependency lookups are cached within a fixed environment, while each root's +reachable declarations, axioms, and proof-hole origins are computed separately. + +`Ix.Kernel.Frontier.Pending` quarantines the remaining explicit metatheory +axioms. Completed roots cannot depend on that namespace. Named-specification +proof holes and implementation bridge axioms are tracked separately from +Lean's logical axioms and generated native proofs. No direct consistency root +permits a proof hole or a metatheory/implementation bridge axiom. Both the +context hash and content-address hash now use kernel-checked proofs of their +32-byte output bounds on both platform sizes. Their former generated native +assumptions have been removed from the affected exact audits. + +Run the complete local kernel-certification gate: + +```sh +lake run check-kernel --with-model +``` + +It combines the following checks. Omit `--with-model` to skip the separate +Mathlib package. Ordinary PR CI covers the root checks in its build, theory, +and test jobs. The model has a separate workflow triggered by changes to the +package, interface, or configuration; the merge queue adds the expensive +parity corpus. + +```sh +lake build IxKernelVerify IxCompileVerify +lake build --wfail IxKernelConsistency +lake run check-theory +lake run check-certified +lake test --wfail -- tc-unit +lake -d Models/SetTheory build --wfail +``` + +The consistency target checks 18 exact theorem boundaries. Its remaining +native assumptions are explicitly named proofs reached through production +smart-constructor code; the model's no-False theorem itself uses only +`propext`, `Classical.choice`, and `Quot.sound`, with set theory as a hypothesis. + +## Certified host adapters + +The certified source and claim adapters are maintained under +`Ix.Certified`, with explicit certified entry points in `Ix.Kernel`. +`ClaimCommand.run_meaning` connects successful source validation to the exact +versioned envelope and its semantic meaning. A closed logical receipt +constructs its model and excludes a checked subject of the profile's false +type under the set-theory hypothesis. + +Run `lake run check-certified` for the exact 86-root foundation audit and +native/CLI regressions against the locally preserved adapter evidence. The audit +permits only the three standard Lean axioms in these roots and inventories +the separate BLAKE3 and native execution boundaries. See +[the command interface, theorem contracts and evidence](certified-checking.md). + +These host results do not cover the full production inference dispatcher or +prove that an Aiur public verifier executes the host validator. The VM pilot +remains in the frozen archive for a later change; its build target and execution +tests are outside the host gate. + +## Review entry points + +| Area | Entry point | +| --- | --- | +| Certified checker contracts | [`Ix/Kernel/Certified.lean`](../Ix/Kernel/Certified.lean), [`CertifiedClaims.lean`](../Ix/Kernel/CertifiedClaims.lean) | +| Direct production refinement and its audit | [`Ix/Kernel/Verify/Consistency.lean`](../Ix/Kernel/Verify/Consistency.lean) | +| Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | +| Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | +| Concrete set-theory instance | [Separate model package](../Models/SetTheory/README.md) | + +## Change scope + +The kernel, theory and certified host scaffolding is extracted from +`jcb/monorepo` at `7b06b754` in a single change. Existing callers move from +`Ix.Tc` to `Ix.Kernel`. Existing `Ix.Compile.Verify` proofs receive the +necessary named-specification imports and exact hash-axiom audit updates. +The new compiler development, circuit changes and certificate VM pilot +are deferred. The external `lean4lean` dependency and its benchmark/test +targets are removed; all verification dependencies are local to Ix. diff --git a/docs/tc-context-digest-collision-boundary.md b/docs/tc-context-digest-collision-boundary.md index f7b4fb1a4..63e539edc 100644 --- a/docs/tc-context-digest-collision-boundary.md +++ b/docs/tc-context-digest-collision-boundary.md @@ -1,4 +1,4 @@ -# Ix.Tc context-digest collision boundary +# Ix.Kernel context-digest collision boundary Snapshot: 2026-07-31. This note records a proof boundary for the K1/K2 cache soundness argument. diff --git a/docs/tc-k0-backedge-audit.md b/docs/tc-k0-backedge-audit.md index 243e79e71..b9cc4aef4 100644 --- a/docs/tc-k0-backedge-audit.md +++ b/docs/tc-k0-backedge-audit.md @@ -1,4 +1,4 @@ -# Ix.Tc K0 recursion and back-edge audit +# Ix.Kernel K0 recursion and back-edge audit Snapshot: 2026-07-27. This is the named K0 tick/measure artifact required by the formal-verification plan. Its production scope is the kernel call graph @@ -67,7 +67,7 @@ The direct-read audit is: ```text rg -n '\(← read\)\.(whnf|whnfCore|whnfMode|whnfCoreFlags|infer|isDefEq)' \ - Ix/Tc --glob '*.lean' + Ix/Kernel --glob '*.lean' ``` The live edges have the following roles: @@ -116,11 +116,11 @@ adversarial inputs that could previously diverge in an unbounded loop now return `.maxRecDepth` at the documented cap. Valid-corpus verdict and headroom parity is the A5 closure gate. Rust and Aiur are deliberately unchanged in K0; any corresponding hardening is a later transport obligation -after the Ix.Tc theorem interface is stable. +after the Ix.Kernel theorem interface is stable. ## Proof and regression surface -`Ix.Tc.Verify.Totalization` exposes, and the completed trust manifest audits: +`Ix.Kernel.Verify.Totalization` exposes, and the completed trust manifest audits: - zero/successor equations for all six `methodsN` fields; - unchanged-error-state equations for all six `methodsOut` fields; @@ -142,11 +142,11 @@ The reproducible source audits are: ```text rg -n '^\s*partial def' \ - Ix/Tc/{Whnf,Infer,DefEq,Inductive,Check}.lean + Ix/Kernel/{Whnf,Infer,DefEq,Inductive,Check}.lean rg -n '^\s*(while|repeat)\b' \ - Ix/Tc/{Whnf,Infer,DefEq,Inductive,Check}.lean + Ix/Kernel/{Whnf,Infer,DefEq,Inductive,Check}.lean rg -n 'TcM\.tick' \ - Ix/Tc/{Whnf,Infer,DefEq,Inductive,Check}.lean + Ix/Kernel/{Whnf,Infer,DefEq,Inductive,Check}.lean ``` The first two must return no matches; the last must return exactly the WHNF @@ -168,7 +168,7 @@ The 2026-07-27 K0 closure run passed all of the following: - exact four-statement sorry-frontier check; - completed (295 roots) and statement (4 roots) trust audits; -- `lake build IxTcVerify` and the default `lake build`; +- `lake build IxKernelVerify` and the default `lake build`; - strict `tc-unit` with warnings treated as failures; - pinned Init/Std stress constants and accelerated-versus-pure differential; - Init-scale anon verdict parity; @@ -176,5 +176,5 @@ The 2026-07-27 K0 closure run passed all of the following: - Lean4Lean replay and tutorial suites. No production source in the Rust kernel or Aiur IxVM was changed. Their -acceptance simulation/refinement work remains downstream of the Ix.Tc +acceptance simulation/refinement work remains downstream of the Ix.Kernel soundness theorem. diff --git a/docs/theory.md b/docs/theory.md new file mode 100644 index 000000000..be2cd142e --- /dev/null +++ b/docs/theory.md @@ -0,0 +1,68 @@ +# Consistency model + +`Ix.Theory` contains Ix's set-theoretic consistency model, its certified acceptance +interface, and certificate construction. Build it with `lake build IxTheory`; +run the selected regression tests, provenance check, and exact foundation +audit with `lake run check-theory`. + +`Ix.Theory.Certified.accepted_has_model` constructs a model for accepted +declarations. `accepted_proof_sound` and `no_proof_of_False` give the corresponding semantic +and consistency results. These theorems explicitly assume a type `V` equipped +with `Ix.Theory.Model.SetTheory V`: set operations and laws together with a +countable tower of Grothendieck universes. The separate +[`Models/SetTheory`](../Models/SetTheory/README.md) package constructs this +structure on Mathlib's `ZFSet` from a strictly increasing countable sequence +of strongly inaccessible cardinals. Its `carneiro_implies_ix` theorem retains +that large-cardinal hypothesis explicitly and passes an axiom guard for +`propext`, `Classical.choice`, and `Quot.sound`. User-supplied logical axioms and +open frontiers retain their stated model hypotheses. + +These are relative consistency results for the certified interface. The +[kernel verification](kernel-verification.md) now shares its universe syntax +and proves direct model results for universe comparison, structural expression +reading, interning, and the production sort-inference branch. The certified +host adapters connect authenticated serialized Ixon to model admission. +A complete bridge from arbitrary `Ix.Kernel.checkEnvAnon` success or +compiler/backend execution remains unfinished. + +`Ix.Theory.Named` retains the local name-indexed specification and proof +support needed by the existing kernel and compiler verification. It shares +`Ix.Theory.VLevel`; its expression calculus remains separate from the store +references and annotated semantics of the set model. The `IxTheory` build and +foundation import graph exclude this auxiliary development. + +The foundation audit freezes 145 named roots, their types and dependencies, +the fields of the set-theory assumption, and the compiler-generated recursion +workers. It rejects proof holes and unapproved axioms, native implementations, +and mathematical imports from the checker, compiler, test harnesses, or older +metatheory. Its exact report is `Tests/Theory/certified-foundation.txt`. +The axiom checks read checked declaration types, bodies, and constructor fields +directly, including the full graph of every declaration in the mathematical +import boundary. + +## Provenance and scope + +The port contains 120 selected source modules and a certified umbrella, from +the Lean4Ix working tree on 2026-09-11, +based on commit `ab42e79e2a4e2615a3ca6ef983d510f374057a38`. The new model included +uncommitted files, so that revision alone is insufficient to identify the +input. `Tests/Theory/ImportManifest.lean` records each selected source path and +SHA-256. Namespace changes move `Lean4Ix` to `Ix.Theory` and flatten the former +`Lean4Ix.Theory` syntax helpers. + +The import includes the exact dependencies of the certified interface and +certificate builders. The old full theory umbrella, generators, conjecture +frontier, and harness are excluded. Matching model tests live in `Tests/Theory`. +Tests that formerly invoked the old generators use frozen constructor and +recursor data extracted from their upstream compiled test fixtures. + +The model's 20 con-leche foundation files derive from revision +`86cd20a65660d757cedc81561a44579099b565d0`. Their upstream and intermediate hashes, +ported content hashes, and notices are retained and checked. Imported license +and notice texts are under `Ix/Theory`; `PORTING.md` explains their scope. + +On recompilation in the monorepo, two roots—`Modeled.CheckedCompanions.fixed_old` +and `Modeled.assignment_agrees`—acquire `Classical.choice` and `Quot.sound` in +addition to `propext`, all already permitted baseline axioms. The reviewed +report also accounts for namespace qualification and module ordering. All root +types, constant counts, and module sets otherwise match the source report. diff --git a/flake.nix b/flake.nix index 84079f7f7..07981c6a9 100644 --- a/flake.nix +++ b/flake.nix @@ -194,22 +194,6 @@ }; lakeDeps = lake2nix.buildDeps { src = leanSrc; - depOverride = { - # lean4-nix guesses a dep's library target by capitalizing the - # package name ("lean4lean" -> "Lean4lean"), but this package's - # library is `Lean4Lean`. Build the stock default targets - # (Lean4Lean, the lean4lean exe, Theory, Verify, Tests) plus the - # shared/static facets so consumers linking exes find the - # module `.o` files in the read-only store path. - lean4lean = { - buildPhase = '' - runHook preBuild - lake build - lake build Lean4Lean:shared Lean4Lean:static - runHook postBuild - ''; - }; - }; depOverrideDeriv = { Blake3 = blake3-lean.packages.${system}.rust; }; diff --git a/lake-manifest.json b/lake-manifest.json index 1f571e9bb..d10016758 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -1,17 +1,7 @@ {"version": "1.2.0", "packagesDir": ".lake/packages", "packages": - [{"url": "https://github.com/argumentcomputer/lean4ix", - "type": "git", - "subDir": null, - "scope": "", - "rev": "a4188d7c2979378d85c6bb41fdd96c3a48a71371", - "name": "lean4lean", - "manifestFile": "lake-manifest.json", - "inputRev": "a4188d7c2979378d85c6bb41fdd96c3a48a71371", - "inherited": false, - "configFile": "lakefile.toml"}, - {"url": "https://github.com/leanprover-community/batteries", + [{"url": "https://github.com/leanprover-community/batteries", "type": "git", "subDir": null, "scope": "", diff --git a/lakefile.lean b/lakefile.lean index 98fe391ce..5ac660b42 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -10,7 +10,7 @@ require LSpec from git /- Blake3 precompiles its libraries, so Lake loads their shared objects -- which bundle the C and Rust FFI objects -- into any process elaborating a module that imports them. That is what supplies the BLAKE3 backend to Lean's native evaluator -for the `native_decide` proofs in `IxTcVerify`, so this pin must stay at or after +for the `native_decide` proofs in `IxKernelVerify`, so this pin must stay at or after the revision that turned precompilation on. Before it, Blake3 exposed a `blake3_rs_shared` cdylib that `ix_native_decide_dynlib` had to fetch and link; that target no longer exists. -/ @@ -23,20 +23,6 @@ require Cli from git require batteries from git "https://github.com/leanprover-community/batteries" @ "v4.33.0" -/- Reference Lean4-in-Lean4 theory and checker. `IxTcVerify` imports its -Theory/Verify specification surface, while `bench-lean4lean` and the ignored -`lean4lean` test runner exercise the implementation. The default `ix` target -still does not build this dependency. Pin `argumentcomputer/lean4ix` exactly -- -the Argument development line, a standalone repository rather than a GitHub -fork of digama0/lean4lean: this revision carries the upstream v4.32/v4.33 -kernel hardening — including the `checkNoMVarNoFVar` check on an opaque's -value (leanprover/lean4#14498), which the replay path in -`Benchmarks/Lean4Lean.lean` reaches — on top of that line's certified -inductive-environment and projection development, and tracks Lean v4.33.1 as -this package does. -/ -require lean4lean from git - "https://github.com/argumentcomputer/lean4ix" @ "a4188d7c2979378d85c6bb41fdd96c3a48a71371" - /-! ## FFI The Rust static libraries use `target` + `moreLinkObjs` instead of `extern_lib` because different Lean executables need different Cargo features: @@ -194,18 +180,6 @@ lean_exe «bench-aggregate-policy» where -- symbols are then resolved from ix_ffi and not pulled twice. moreLinkObjs := #[ix_rs] -/- The lean4lean replay machinery as an importable lib: the -`bench-lean4lean` exe root and the ignored `lean4lean` test runner both -import `Benchmarks.Lean4Lean`, and modules under `Benchmarks/` belong to -no other lib target, so without this Lake cannot schedule the module from -the Tests import graph. -/ -lean_lib Lean4LeanBench where - globs := #[.one `Benchmarks.Lean4Lean] - -lean_exe «bench-lean4lean» where - root := `Benchmarks.Lean4LeanMain - supportInterpreter := true - lean_exe «bench-compile-init» where root := `Benchmarks.CompileInit @@ -228,9 +202,13 @@ lean_exe truthmines where end Benchmarks -section IxTcVerify +lean_lib IxTheoryNamed where + roots := #[] + globs := #[.submodules `Ix.Theory.Named] -/-- Loadable FFI for Lean's native evaluator while `IxTcVerify` is elaborated. +section IxKernelVerify + +/-- Loadable FFI for Lean's native evaluator while `IxKernelVerify` is elaborated. `native_decide` runs compiled Lean before any executable is linked, so for each opaque `@[extern]` it reaches, both symbol layers must be loadable up front: @@ -255,31 +233,37 @@ target ix_native_decide_dynlib pkg : Dynlib := do (pkg.buildDir / nameToSharedLib "ix_native_decide") (boxedObjs.push ixCdylib) #[] -/- Formal verification of `Ix.Tc` against the lean4lean `Theory` spec. +/- Formal verification of `Ix.Kernel` against the internal named specification. Non-default: `lake build ix` never touches it, and `build-all` (the lint driver) skips it by name because its -pinned Lean4Lean dependencies still emit named `sorry` warnings — `lake lint +internal named-specification proofs still emit named `sorry` warnings — `lake lint -- --wfail` would otherwise fail even though the Ix verification source has no local `sorry` tokens. Required CI builds it separately without `--wfail`, audits the exact local sorry frontier, and checks exact per-root transitive axiom plus direct-`sorryAx`-origin manifests. Dev loop: -`lake build IxTcVerify`; focused trust audit: -`lake build Ix.Tc.Verify.Audit.Completed Ix.Tc.Verify.Audit.Conditional -Ix.Tc.Verify.Audit.Statements`. -/ -lean_lib IxTcVerify where - globs := #[.submodules `Ix.Tc.Verify] +`lake build IxKernelVerify`; focused trust audit: +`lake build Ix.Kernel.Verify.Audit.Completed Ix.Kernel.Verify.Audit.Conditional +Ix.Kernel.Verify.Audit.Statements`. -/ +lean_lib IxKernelVerify where + globs := #[.submodules `Ix.Kernel.Verify] -- `supportInterpreter` is a `lean_exe` option and takes effect only when -- that executable is linked, after its modules have been elaborated. -- These native-decide proofs need the boxed FFI symbols while the library -- modules are being elaborated, so they must be supplied as a dynlib. dynlibs := #[ix_native_decide_dynlib] -end IxTcVerify +end IxKernelVerify + +/- Direct refinement of production operations into the set model, with its +own exact axiom audit. This is distinct from whole-checker soundness. -/ +lean_lib IxKernelConsistency where + roots := #[`Ix.Kernel.Verify.Consistency] + globs := #[.andSubmodules `Ix.Kernel.Verify.Consistency] section IxCompileVerify /- Formal verification of the Lean-to-Ixon compiler against the same -Lean4Lean Theory endpoint as `IxTcVerify`. Kept as a separate non-default +internal named-specification endpoint as `IxKernelVerify`. Kept as a separate non-default library so compiler proofs cannot accidentally inherit checker acceptance theorems as their specification. -/ lean_lib IxCompileVerify where @@ -344,10 +328,11 @@ script "build-all" (args) := do let pkg ← getRootPackage let libNames := pkg.configTargets LeanLib.configKind |>.map (·.name.toString) let exeNames := pkg.configTargets LeanExe.configKind |>.map (·.name.toString) - -- IxTcVerify is the WIP proofs lib: sorry-bearing by design while the - -- verification frontier is open, so it must not run under `--wfail`. - -- Required CI builds it separately and audits the exact frontier. - let allNames := (libNames ++ exeNames |>.toList).filter (· != "IxTcVerify") + -- The named specification and its implementation proofs retain an audited + -- frontier. CI builds them separately without `--wfail`. The set model, + -- direct consistency roots, and certified adapters are checked strictly. + let allNames := (libNames ++ exeNames |>.toList).filter fun name => + name != "IxKernelVerify" && name != "IxCompileVerify" && name != "IxTheoryNamed" for name in allNames do IO.println s!"Building: {name}" let child ← IO.Process.spawn { @@ -358,3 +343,144 @@ script "build-all" (args) := do return 0 end Scripts + +section Theory + +lean_lib IxTheory where + roots := #[`Ix.Theory] + -- Keep the set-model foundation independent of named checker proof support. + globs := #[.one `Ix.Theory, .one `Ix.Theory.Certified, + .one `Ix.Theory.Const, .one `Ix.Theory.Expr, .one `Ix.Theory.Quot, + .one `Ix.Theory.Ref, .one `Ix.Theory.Rename, .one `Ix.Theory.Store, + .one `Ix.Theory.VLevel, .submodules `Ix.Theory.Certificate, + .submodules `Ix.Theory.Certified, .submodules `Ix.Theory.Inductive, + .submodules `Ix.Theory.Model, .submodules `Ix.Theory.Std] + +lean_lib IxTheoryCertified where + roots := #[`Ix.Theory.Certified] + +lean_lib IxTheoryTests where + roots := #[`Tests.Theory] + +lean_exe «theory-provenance» where + root := `Tests.Theory.Provenance + +end Theory + +section Certified + +lean_lib IxCertified where + roots := #[`Ix.Certified] + moreLinkObjs := #[ix_rs] + +lean_lib IxCertifiedAudit where + roots := #[`Ix.Certified.AuditAll] + +lean_exe «certified-cli-tests» where + root := `Tests.Certified.CLI + supportInterpreter := true + +lean_exe «certified-adapter-tests» where + root := `Tests.Certified.Check + supportInterpreter := true + +lean_exe «certified-check» where + root := `Ix.Certified.Main + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +lean_exe «certified-claim-check» where + root := `Ix.Certified.ClaimMain + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +lean_exe «certified-feature-tests» where + root := `Tests.Certified.Features + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +lean_exe «certified-ordinary-tests» where + root := `Tests.Certified.Ordinary + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +lean_exe «certified-source-tests» where + root := `Tests.Certified.SourceMain + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +lean_exe «certified-fidelity-tests» where + root := `Tests.Certified.FidelityMain + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +lean_exe «certified-claim-tests» where + root := `Tests.Certified.ClaimsMain + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +lean_exe «certified-modeled-tests» where + root := `Tests.Certified.ModeledMain + supportInterpreter := true + moreLinkObjs := #[ix_rs] + +end Certified + +namespace KernelChecks + +private def run (command : String) (args : Array String := #[]) : IO Unit := do + let child ← IO.Process.spawn { cmd := command, args, stdout := .inherit, stderr := .inherit } + let code ← child.wait + unless code == 0 do throw (IO.userError s!"{command} failed ({code})") + +private def checkReport (module expectedPath : String) : IO Unit := do + let report ← IO.Process.output { + cmd := "lake", args := #["env", "lean", "-DwarningAsError=true", module] } + unless report.exitCode == 0 do throw (IO.userError s!"{report.stdout}{report.stderr}") + unless report.stdout == (← IO.FS.readFile expectedPath) do + IO.FS.withTempFile fun handle path => do + handle.putStr report.stdout + handle.flush + let child ← IO.Process.spawn { + cmd := "diff", args := #["-u", expectedPath, path.toString] + stdout := .inherit, stderr := .inherit } + let _ ← child.wait + throw (IO.userError s!"foundation report differs from {expectedPath}") + +end KernelChecks + +open KernelChecks + +/-- Check the set model, its provenance, and its exact foundation report. -/ +script "check-theory" := do + run "lake" #["build", "--wfail", "IxTheory", "IxTheoryTests", "theory-provenance"] + run ".lake/build/bin/theory-provenance" + checkReport "Tests/Theory/Audit/Certified.lean" "Tests/Theory/certified-foundation.txt" + IO.println "Theory checks passed: exact root types, axioms, dependencies, and runtime inventory." + return 0 + +/-- Check host certification against exact audits and frozen source/claim evidence. -/ +script "check-certified" := do + run "lake" #["build", "--wfail", "IxCertified", "IxCertifiedAudit", + "certified-check", "certified-claim-check", "certified-feature-tests", + "certified-ordinary-tests", "certified-source-tests", "certified-fidelity-tests", + "certified-claim-tests", "certified-modeled-tests", "certified-cli-tests", + "certified-adapter-tests"] + checkReport "Ix/Certified/AuditAll.lean" "Tests/Certified/foundation.txt" + run ".lake/build/bin/certified-adapter-tests" + return 0 + +/-- Run the kernel implementation, consistency, foundation, and host checks. -/ +script "check-kernel" (args) := do + unless args.isEmpty || args == ["--with-model"] do + IO.eprintln "usage: lake run check-kernel [--with-model]" + return 2 + run "lake" #["build", "IxKernelVerify", "IxCompileVerify"] + run "lake" #["build", "--wfail", "IxKernelConsistency"] + run "lake" #["run", "check-theory"] + run "lake" #["run", "check-certified"] + run "lake" #["test", "--wfail", "--", "tc-unit"] + if args == ["--with-model"] then + run "lake" #["-d", "Models/SetTheory", "build", "--wfail"] + IO.println "Kernel certification checks passed." + return 0 From 76dc310214d26800e290c267b0f129e4ca59ef08 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 06:53:42 -0400 Subject: [PATCH 02/30] Prove relative consistency for an atomic checkEnvAnon fragment Connect all-success production checkEnvAnon results to model extension for monomorphic standalone aliases and closed universe terms. The proof follows the actual lazy lookup, standalone routing, reset, validation, inference, and conversion calls. Its operational witnesses require uncached value inference and the initial hash-equality conversion path with explicit representation faithfulness; they do not assume a checker-soundness callback or supplied typing proof. Start the model interface with exactly the source axioms, then add fresh definitions in dependency order while retaining their actual serial work positions. Every model of the axiom interface extends without changing any axiom interpretation. Source representation includes the checked type, universe arity, and definition body. The no-False corollary preserves an initial empty interpretation, and a separate theorem excludes fresh self aliases. All result rows must succeed; the public outer ok is insufficient. The full checker and independent serialized-Ixon reader refinement remain outside this fragment. Runtime checker behavior is unchanged. Validation: - lake build --wfail IxKernelConsistency: 36 exact full-dependency audits, no proof holes or checker/certificate soundness shortcuts; four existing generated 32-byte length proofs are enumerated explicitly. - lake test --wfail -- tc-unit: 403 checks, including eight new production regressions for aliases, sorts, cache clearing, and failed result rows. - git diff --check --- Ix/Kernel/Verify/Consistency.lean | 8 +- Ix/Kernel/Verify/Consistency/Atomic.lean | 217 +++++++++ Ix/Kernel/Verify/Consistency/Audit.lean | 42 +- Ix/Kernel/Verify/Consistency/Environment.lean | 455 ++++++++++++++++++ Ix/Kernel/Verify/Consistency/Production.lean | 246 ++++++++++ README.md | 8 +- Tests/Ix/Kernel/Consistency.lean | 91 ++++ Tests/Main.lean | 2 + docs/kernel-verification.md | 89 +++- docs/theory.md | 6 + lakefile.lean | 4 +- 11 files changed, 1154 insertions(+), 14 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/Atomic.lean create mode 100644 Ix/Kernel/Verify/Consistency/Environment.lean create mode 100644 Ix/Kernel/Verify/Consistency/Production.lean create mode 100644 Tests/Ix/Kernel/Consistency.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index c00dfe950..13dc8657e 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -7,6 +7,9 @@ import Ix.Kernel.Verify.Consistency.Level import Ix.Kernel.Verify.Consistency.Expr import Ix.Kernel.Verify.Consistency.Judgment import Ix.Kernel.Verify.Consistency.Infer +import Ix.Kernel.Verify.Consistency.Atomic +import Ix.Kernel.Verify.Consistency.Production +import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Consistency.Audit /-! @@ -14,6 +17,7 @@ import Ix.Kernel.Verify.Consistency.Audit This library connects production kernel operations to `Ix.Theory`. Each transport keeps its representation, arithmetic, and dependency assumptions -explicit. The component theorems are distinct from a full soundness theorem -for `checkEnvAnon`. +explicit. A production `checkEnvAnon` fragment now preserves models of its +axiom set for monomorphic aliases and closed sorts under the stated execution +resources. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Atomic.lean b/Ix/Kernel/Verify/Consistency/Atomic.lean new file mode 100644 index 000000000..12565de84 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Atomic.lean @@ -0,0 +1,217 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Infer +import Ix.Theory.Model.Extension + +/-! +# Atomic production inference + +The first declaration fragment admits closed sorts and monomorphic references. +References use the type of an already admitted interface entry. The premises +below describe concrete cache misses, lookup results, and finite interning +support; none assumes a typing judgment or the soundness of a checker method. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +private theorem runTcBind {α β : Type} (x : TcM .anon α) (k : α → TcM .anon β) + (state : TcState .anon) : + EStateM.bind x k state = match x state with + | .ok value after => k value after + | .error err after => .error err after := by + show EStateM.bind x k state = _ + unfold EStateM.bind + cases x state <;> rfl + +/-- The two inference-cache partitions miss at the actual key computed by +production. Both misses are required, so this applies in either policy mode. -/ +structure UncachedInference (before : TcState .anon) (term : KExpr .anon) where + key : Address × Address + keyed : TcState .anon + keyRun : TcM.inferKey term before = .ok key keyed + fullMiss : keyed.env.inferCache[key]? = none + onlyMiss : keyed.env.inferOnlyCache[key]? = none + +/-- Strip only key lookup and the final cache write from an actual successful +inference. The recursive method table and returned type are unchanged. -/ +theorem infer_uncached_success {term type : KExpr .anon} + {methods : Methods .anon} {before after : TcState .anon} + (miss : UncachedInference before term) + (accepted : RecM.infer term methods before = .ok type after) : + ∃ inferredState, RecM.inferUncached RecM.inferCall before.inferOnly term + methods miss.keyed = .ok type inferredState := by + change (RecM.infer term).run methods before = .ok type after at accepted + unfold RecM.infer RecM.inferWith at accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.inferKey term) _ before = _ at accepted + rw [runTcBind, miss.keyRun] at accepted + change EStateM.bind (get : TcM .anon (TcState .anon)) _ miss.keyed = _ at accepted + rw [runTcBind, show (get : TcM .anon (TcState .anon)) miss.keyed = + .ok miss.keyed miss.keyed from rfl] at accepted + simp only at accepted + rw [miss.fullMiss] at accepted + cases policy : before.inferOnly with + | false => + simp only [policy, Bool.false_eq_true, if_false] at accepted + change EStateM.bind (RecM.inferUncached RecM.inferCall false term methods) + _ miss.keyed = _ at accepted + cases run : RecM.inferUncached RecM.inferCall false term methods miss.keyed with + | error err failed => rw [runTcBind, run] at accepted; contradiction + | ok ty state => + rw [runTcBind, run] at accepted + change EStateM.Result.ok ty { state with env := { state.env with + inferCache := state.env.inferCache.insert miss.key ty } } = .ok type after at accepted + cases accepted + exact ⟨state, rfl⟩ + | true => + simp only [policy, if_true] at accepted + simp only [ReaderT.run_bind] at accepted + change EStateM.bind (get : TcM .anon (TcState .anon)) _ miss.keyed = _ at accepted + rw [runTcBind, show (get : TcM .anon (TcState .anon)) miss.keyed = + .ok miss.keyed miss.keyed from rfl] at accepted + simp only at accepted + rw [miss.onlyMiss] at accepted + change EStateM.bind (RecM.inferUncached RecM.inferCall true term methods) + _ miss.keyed = _ at accepted + cases run : RecM.inferUncached RecM.inferCall true term methods miss.keyed with + | error err failed => rw [runTcBind, run] at accepted; contradiction + | ok ty state => + rw [runTcBind, run] at accepted + change EStateM.Result.ok ty { state with env := { state.env with + inferOnlyCache := state.env.inferOnlyCache.insert miss.key ty } } = .ok type after at accepted + cases accepted + exact ⟨state, rfl⟩ + +/-- Supported syntax plus the concrete resources needed by its uncached +production branch. A constant's semantic type comes from an existing entry, +while `lookup` checks agreement with the actual lazy-loaded declaration. +The monomorphic type is explicitly stable under the empty level substitution. -/ +inductive AtomicInferenceSupport {β : Type u} + (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) : + KExpr .anon → TcState .anon → AExpr β → AExpr β → Prop + | sort {level : KUniv .anon} {info : ExprInfo .anon} {before : TcState .anon} + (closed : (readLevel level).WF 0) + (coherent : before.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun e => + before.env.intern.ExprSupport e ∨ e = KExpr.mkSort (KUniv.mkSucc level)) : + AtomicInferenceSupport resolve entries (.sort level info) before + (.sort (readLevel level)) (.sort (.succ (readLevel level))) + | const {id : KId .anon} {info : ExprInfo .anon} {before : TcState .anon} + {ref : ConstRef β} {entry : ConstantEntry β} + (resolved : resolve id.addr = some ref) + (found : entries ref = some entry) + (monomorphic : entry.universes = 0) + (stable : entry.type.instL [] = entry.type) + (lookup : ∀ concrete loaded, + TcM.getConst id before = .ok concrete loaded → + readExpr? resolve concrete.ty = some entry.type.erase) : + AtomicInferenceSupport resolve entries (.const id #[] info) before + (.const ref []) entry.type + +namespace AtomicInferenceSupport + +/-- This fragment's typing rule is proved from the sort rule or an existing +constant interface, independently of any production success assumption. -/ +theorem typing {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {term : KExpr .anon} {before : TcState .anon} + {body type : AExpr β} (support : AtomicInferenceSupport resolve entries term before body type) : + TypingClaim.{u,v} entries [] body type := by + cases support with + | sort => exact TypingClaim.sort _ + | const resolved found monomorphic stable lookup => + simpa only [stable] using + (TypingClaim.const (ls := []) found (by simpa using monomorphic.symm)) + +theorem reads {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {term : KExpr .anon} {before : TcState .anon} + {body type : AExpr β} (support : AtomicInferenceSupport resolve entries term before body type) : + readExpr? resolve term = some body.erase := by + cases support with + | sort => rfl + | const resolved found monomorphic stable lookup => + simp [readExpr?, resolved, AExpr.erase] + +/-- Exact output refinement for the production syntax dispatcher. -/ +theorem output {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {term inferred : KExpr .anon} + {before after : TcState .anon} {body type : AExpr β} + (support : AtomicInferenceSupport resolve entries term before body type) + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} + {inferOnly : Bool} {methods : Methods .anon} + (accepted : RecM.inferUncached inferRec inferOnly term methods before = + .ok inferred after) : + readExpr? resolve inferred = some type.erase := by + cases support with + | sort closed coherent faithful => + change EStateM.Result.ok + (before.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc _))).1 + _ = .ok inferred after at accepted + cases accepted + rw [internExpr_readExpr? coherent faithful] + simp only [readExpr?_mkSort, readLevel_mkSucc, AExpr.erase] + | @const id info before ref entry resolved found monomorphic stable lookup => + change (RecM.inferUncached inferRec inferOnly (.const id #[] info)).run + methods before = .ok inferred after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.getConst id) _ before = _ at accepted + cases got : TcM.getConst id before with + | error err failed => rw [runTcBind, got] at accepted; contradiction + | ok concrete loaded => + rw [runTcBind, got] at accepted + simp only at accepted + split at accepted + · contradiction + · change EStateM.Result.ok concrete.ty loaded = .ok inferred after at accepted + cases accepted + exact lookup concrete _ got + +theorem scopeAndReferences {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {term : KExpr .anon} {before : TcState .anon} + {body type : AExpr β} (support : AtomicInferenceSupport resolve entries term before body type) + (wellFormed : entries.WF) : + body.Scope 0 0 ∧ type.Scope 0 0 ∧ + body.ReferencesIn entries ∧ type.ReferencesIn entries := by + cases support with + | sort closed coherent faithful => + exact ⟨closed, closed, by simp [AExpr.ReferencesIn, AExpr.references], + by simp [AExpr.ReferencesIn, AExpr.references]⟩ + | const resolved found monomorphic stable lookup => + refine ⟨by simp [AExpr.Scope], ?_, ?_, wellFormed.typeReferences _ _ found⟩ + · simpa only [monomorphic] using wellFormed.typeScope _ _ found + · intro ref href + simp only [AExpr.references, List.mem_singleton] at href + subst ref + simp only [found, Option.isSome_some] + +end AtomicInferenceSupport + +/-- Resources at the actual inference entry and its computed cache key. -/ +structure AtomicInference {β : Type u} (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) (before : TcState .anon) (term : KExpr .anon) + (body type : AExpr β) where + misses : UncachedInference before term + support : AtomicInferenceSupport resolve entries term misses.keyed body type + +/-- A successful public inference in this fragment returns the semantic type +of the exact source tree. The inference implementation supplies the output +agreement; callers do not supply a typing or method-soundness premise. -/ +theorem AtomicInference.sound {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {before after : TcState .anon} + {term inferred : KExpr .anon} {body type : AExpr β} {methods : Methods .anon} + (fragment : AtomicInference resolve entries before term body type) + (accepted : RecM.infer term methods before = .ok inferred after) : + readExpr? resolve term = some body.erase ∧ + readExpr? resolve inferred = some type.erase ∧ + TypingClaim.{u,v} entries [] body type := by + obtain ⟨state, run⟩ := infer_uncached_success fragment.misses accepted + exact ⟨fragment.support.reads, fragment.support.output run, fragment.support.typing⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 9fc86756d..7d49bf4a3 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -4,6 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Infer +import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -21,6 +22,39 @@ private def levelNative : Lean.Name := private def expressionNative : Lean.Name := nativeAxiom `Ix.Kernel.Expr `Ix.Kernel.KExpr.mkVar._native.native_decide.ax_1 +/-- The public driver reaches these additional generated output-length +proofs through the full production method table, including inactive branches. +No new native proof is introduced by the fragment verification. -/ +private def productionNative : Array Lean.Name := #[ + expressionNative, levelNative, + nativeAxiom `Ix.Environment `Ix.Name.mkStr._native.native_decide.ax_1, + nativeAxiom `Ix.Kernel.Inductive `Ix.Kernel.RecM.canonicalAuxOrder._native.native_decide.ax_9 +] + +private def atomicRoots : Array Lean.Name := #[ + ``infer_uncached_success, ``AtomicInferenceSupport.typing, + ``AtomicInferenceSupport.reads, ``AtomicInferenceSupport.output, + ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound +] + +private def productionRoots : Array Lean.Name := #[ + ``StandalonePrefix.member_success, ``definition_body_trace, + ``AtomicDefinitionRun.sound, ``AtomicDefinitionRun.no_self_alias, + ``WorkPosition.check_success, ``AtomicDefinitionPlan.extends, + ``AtomicDefinitionPlan.sound, ``AtomicDefinitionPlan.represents, + ``checkEnvAnon_atomic_preserves_model, ``checkEnvAnon_atomic_represents_source, + ``checkEnvAnon_atomic_no_false +] + +/-- The new production roots must not acquire a checker-soundness assumption +or invoke the independent certificate validator to establish acceptance. -/ +private def forbiddenProduction : Array Lean.Name := #[ + `Ix.Kernel.CheckSuccessSound, + `Ix.Kernel.SupportedCheckFragment, + `Ix.Theory.Certified.checkProofCertified, + `Ix.Certified.acceptsSerializedStore +] + def roots : Array RootAllowance := #[ { root := ``readLevel_eq, standardAxioms := #[``propext] }, { root := ``readLevel_eval, standardAxioms := #[``propext] }, @@ -44,7 +78,13 @@ def roots : Array RootAllowance := #[ { root := ``sort_conversion, standardAxioms := standard }, { root := ``inferUncached_sort_sound, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative] } -] +] ++ atomicRoots.map (fun root => { + root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], + forbiddenDependencies := forbiddenProduction +}) ++ productionRoots.map (fun root => { + root, standardAxioms := standard, nativeAxioms := productionNative, + forbiddenDependencies := forbiddenProduction +}) ++ #[{ root := ``extend_atomic_definition, standardAxioms := standard }] run_cmd Kernel.Verify.Audit.check roots diff --git a/Ix/Kernel/Verify/Consistency/Environment.lean b/Ix/Kernel/Verify/Consistency/Environment.lean new file mode 100644 index 000000000..f30a54e1f --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Environment.lean @@ -0,0 +1,455 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Production + +/-! +# Relative consistency of a production environment fragment + +The initial interface contains exactly the supplied axiom declarations. A +dependency order adds fresh monomorphic definitions, using successful calls +from the real serial `checkEnvAnon` run. Each addition constructs its value in +every model of the previous interface. Thus definitions preserve any given +model of the axiom set; no axiom is silently assumed to be inhabited. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model Theory.Model.SetTheory + +universe u v + +/-- A location in the exact work array, retaining the preceding work so the +checker state is the one actually reached by the production serial loop. -/ +structure WorkPosition (work : Array AnonWorkItem) (item : AnonWorkItem) where + leading : List AnonWorkItem + trailing : List AnonWorkItem + split : work.toList = leading ++ item :: trailing + +def WorkPosition.state {work : Array AnonWorkItem} {item : AnonWorkItem} + (position : WorkPosition work item) (env : Ixon.Env) (cfg : CheckCfg) : + AnonCheckLoopState := + runAnonCheckList cfg position.leading (initialAnonCheckLoopState env cfg) + +private theorem runList_append (cfg : CheckCfg) (left right : List AnonWorkItem) + (before : AnonCheckLoopState) : + runAnonCheckList cfg (left ++ right) before = + runAnonCheckList cfg right (runAnonCheckList cfg left before) := by + induction left generalizing before with + | nil => rfl + | cons item rest ih => exact ih (runAnonCheckItem cfg before item) + +private theorem finish_results (cfg : CheckCfg) (before : AnonCheckLoopState) + (item : AnonWorkItem) (checker : TcState .anon) (err : Option String) : + (finishAnonCheckItem cfg before item checker err).results = + before.results ++ item.targets.map (fun addr => ⟨addr, err⟩) := by + unfold finishAnonCheckItem + dsimp only + split <;> rfl + +private theorem item_keeps_result (cfg : CheckCfg) (before : AnonCheckLoopState) + (item : AnonWorkItem) {result : CheckResult} (found : result ∈ before.results) : + result ∈ (runAnonCheckItem cfg before item).results := by + cases run : TcM.checkConst (⟨item.primary, ()⟩ : KId .anon) before.checker with + | ok value after => + cases value + simp only [runAnonCheckItem, EStateM.run, run, finish_results] + exact Array.mem_append.mpr (.inl found) + | error err after => + simp only [runAnonCheckItem, EStateM.run, run, finish_results] + exact Array.mem_append.mpr (.inl found) + +private theorem list_keeps_result (cfg : CheckCfg) (work : List AnonWorkItem) + (before : AnonCheckLoopState) {result : CheckResult} (found : result ∈ before.results) : + result ∈ (runAnonCheckList cfg work before).results := by + induction work generalizing before with + | nil => exact found + | cons item rest ih => exact ih _ (item_keeps_result cfg before item found) + +/-- All-success result rows expose a successful call at this exact work +position. This rules out the public `.ok` result that contains failed rows. -/ +theorem WorkPosition.check_success {env : Ixon.Env} {cfg : CheckCfg} + {work : Array AnonWorkItem} {addr : Address} + (position : WorkPosition work (.standalone addr)) + (succeeded : ∀ result ∈ (runAnonCheckList cfg work.toList + (initialAnonCheckLoopState env cfg)).results, result.err? = none) : + ∃ after, TcM.checkConst (⟨addr, ()⟩ : KId .anon) + (position.state env cfg).checker = .ok () after := by + rw [position.split, runList_append] at succeeded + change ∀ result ∈ (runAnonCheckList cfg position.trailing + (runAnonCheckItem cfg (position.state env cfg) (.standalone addr))).results, + result.err? = none at succeeded + cases run : TcM.checkConst (⟨addr, ()⟩ : KId .anon) (position.state env cfg).checker with + | ok value after => + cases value + exact ⟨after, rfl⟩ + | error err after => + let failed : CheckResult := ⟨addr, some (toString err)⟩ + have appears : failed ∈ + (runAnonCheckItem cfg (position.state env cfg) (.standalone addr)).results := by + simp only [runAnonCheckItem, EStateM.run, AnonWorkItem.primary, run, finish_results, + AnonWorkItem.targets] + apply Array.mem_append.mpr + exact .inr (by simp [failed]) + have contradiction := succeeded failed + (list_keeps_result cfg position.trailing _ appears) + simp [failed] at contradiction + +/-- The semantic entry published for a monomorphic definition. No reduction +equations or extra typed facts are manufactured by this fragment. -/ +def definitionEntry {β : Type u} (body type : AExpr β) : ConstantEntry β := + { universes := 0, type, body := some body } + +/-- Body typing already includes hereditary validity of the declared type. +This constructs a model extension directly, without separately assuming a +model for the pending declaration. -/ +theorem extend_atomic_definition {β : Type u} [DecidableEq β] + {entries : Model.Environment β} {ref : ConstRef β} {body type : AExpr β} + (wellFormed : entries.WF) (fresh : entries ref = none) + (bodyScope : body.Scope 0 0) + (bodyRefs : body.ReferencesIn entries) (typeRefs : type.ReferencesIn entries) + (typed : TypingClaim.{u,v} entries [] body type) + {V : Type v} [SetTheory V] (constants : Assignment β V) (realizes : Realizes constants entries) : + ∃ next : Assignment β V, + Realizes next (entries.insert ref (definitionEntry body type)) ∧ + Assignment.AgreesOn entries constants next := by + let next := constants.insert ref (fun levels => interp constants levels (fun _ => empty) body) + have agrees : Assignment.AgreesOn entries constants next := + Assignment.insert_agrees fresh constants _ + have value (levels : List Nat) (env : Nat → V) : + next ref levels = interp constants levels env body := by + simp only [next, Assignment.insert, if_true] + exact interp_closed body constants levels bodyScope _ env + refine ⟨next, (realizes.of_agrees wellFormed agrees).insert ?_, agrees⟩ + constructor + · intro levels _ env + exact (agrees.wellDenoted typeRefs levels env).mpr + (typed V constants realizes levels env (Context.valid_nil constants levels env)).2.1 + · intro levels _ env + change next ref levels ∈ˢ interp next levels env type + rw [value, agrees.interp typeRefs] + exact (typed V constants realizes levels env (Context.valid_nil constants levels env)).2.2 + · intro candidate present levels _ env + change some body = some candidate at present + cases Option.some.inj present + exact (agrees.wellDenoted bodyRefs levels env).mpr + (typed V constants realizes levels env (Context.valid_nil constants levels env)).1 + · intro candidate present levels _ env + change some body = some candidate at present + cases Option.some.inj present + rw [value, agrees.interp bodyRefs] + · intro law present + exact (List.not_mem_nil present).elim + · intro fact present + exact (List.not_mem_nil present).elim + +/-- A declaration's source data and its annotated semantic interface. The +production run must establish both erasure agreements and body typing. -/ +structure DefinitionSpec (β : Type u) where + input : DefinitionInput + ref : ConstRef β + body : AExpr β + type : AExpr β + +def DefinitionSpec.entry {β : Type u} (spec : DefinitionSpec β) : ConstantEntry β := + definitionEntry spec.body spec.type + +private theorem insert_definition_wf {β : Type u} [DecidableEq β] + {entries : Model.Environment β} {ref : ConstRef β} {body type : AExpr β} + (wellFormed : entries.WF) (bodyScope : body.Scope 0 0) (typeScope : type.Scope 0 0) + (bodyRefs : body.ReferencesIn entries) (typeRefs : type.ReferencesIn entries) : + (entries.insert ref (definitionEntry body type)).WF := by + apply wellFormed.insert typeScope + · intro candidate present + change some body = some candidate at present + cases Option.some.inj present + exact bodyScope + · exact typeRefs + · intro candidate present + change some body = some candidate at present + cases Option.some.inj present + exact bodyRefs + · simp [definitionEntry] + · simp [definitionEntry] + · simp [definitionEntry] + · simp [definitionEntry] + +/-- A dependency order over the checked definitions. Each reference is fresh +and each atomic body reads only the preceding interface. The work position +retains the original serial order, which may differ from this dependency +order. No semantic acceptance premise appears in this plan. -/ +inductive AtomicDefinitionPlan {β : Type u} [DecidableEq β] + (env : Ixon.Env) (cfg : CheckCfg) (work : Array AnonWorkItem) + (resolve : Address → Option (ConstRef β)) : + Model.Environment β → List (DefinitionSpec β) → Model.Environment β → Prop + | nil (entries) : AtomicDefinitionPlan env cfg work resolve entries [] entries + | cons {before after : Model.Environment β} {rest : List (DefinitionSpec β)} + (spec : DefinitionSpec β) + (resolved : resolve spec.input.id.addr = some spec.ref) + (fresh : before spec.ref = none) + (position : WorkPosition work (.standalone spec.input.id.addr)) + (run : AtomicDefinitionRun resolve before spec.input + (position.state env cfg).checker spec.body spec.type) + (tail : AtomicDefinitionPlan env cfg work resolve + (before.insert spec.ref spec.entry) rest after) : + AtomicDefinitionPlan env cfg work resolve before (spec :: rest) after + +/-- Every old interface entry is retained by a dependency plan. -/ +theorem AtomicDefinitionPlan.extends {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {work : Array AnonWorkItem} + {resolve : Address → Option (ConstRef β)} + {before after : Model.Environment β} {definitions : List (DefinitionSpec β)} + (plan : AtomicDefinitionPlan env cfg work resolve before definitions after) : + ∀ ref entry, before ref = some entry → after ref = some entry := by + induction plan with + | nil entries => exact fun _ _ h => h + | cons spec resolved fresh position run tail ih => + intro ref entry present + exact ih ref entry (Model.Environment.insert_old fresh present) + +/-- Model preservation keeps every old reference's interpretation fixed. -/ +def PreservesModels {β : Type u} (before after : Model.Environment β) : Prop := + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + Realizes constants before → ∃ next : Assignment β V, + Realizes next after ∧ Assignment.AgreesOn before constants next + +private theorem anon_id (id : KId .anon) : (⟨id.addr, ()⟩ : KId .anon) = id := by + cases id with + | mk addr name => cases name; rfl + +/-- Every accepted definition in the dependency order extends the preceding +model. The initial interface need only have a model; its axioms need not be +part of a fixed whitelist. -/ +theorem AtomicDefinitionPlan.sound {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {work : Array AnonWorkItem} + {resolve : Address → Option (ConstRef β)} + {before after : Model.Environment β} {definitions : List (DefinitionSpec β)} + (plan : AtomicDefinitionPlan env cfg work resolve before definitions after) + (wellFormed : before.WF) + (succeeded : ∀ result ∈ (runAnonCheckList cfg work.toList + (initialAnonCheckLoopState env cfg)).results, result.err? = none) : + after.WF ∧ PreservesModels.{u,v} before after := by + induction plan with + | nil entries => + exact ⟨wellFormed, fun _ _ constants realizes => + ⟨constants, realizes, fun _ _ _ _ => rfl⟩⟩ + | @cons before after rest spec resolved fresh position run tail ih => + obtain ⟨checkedState, accepted⟩ := position.check_success succeeded + rw [anon_id] at accepted + have bodySound := run.sound wellFormed accepted + have formed : (before.insert spec.ref spec.entry).WF := + insert_definition_wf wellFormed bodySound.2.2.1 bodySound.2.2.2.1 + bodySound.2.2.2.2.1 bodySound.2.2.2.2.2.1 + obtain ⟨finalFormed, preserve⟩ := ih formed + refine ⟨finalFormed, ?_⟩ + intro V _ constants realizes + obtain ⟨next, nextModel, agrees⟩ := extend_atomic_definition wellFormed fresh + bodySound.2.2.1 bodySound.2.2.2.2.1 bodySound.2.2.2.2.2.1 + bodySound.2.2.2.2.2.2 constants realizes + obtain ⟨final, finalModel, finalAgrees⟩ := preserve V next nextModel + refine ⟨final, finalModel, ?_⟩ + intro ref entry present levels + exact (finalAgrees ref entry (Model.Environment.insert_old fresh present) levels).trans + (agrees ref entry present levels) + +/-- Every published definition interface reads the actual checked type and +body. Freshness ensures later definitions cannot overwrite that interface. -/ +theorem AtomicDefinitionPlan.represents {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {work : Array AnonWorkItem} + {resolve : Address → Option (ConstRef β)} + {before after : Model.Environment β} {definitions : List (DefinitionSpec β)} + (plan : AtomicDefinitionPlan env cfg work resolve before definitions after) + (wellFormed : before.WF) + (succeeded : ∀ result ∈ (runAnonCheckList cfg work.toList + (initialAnonCheckLoopState env cfg)).results, result.err? = none) : + ∀ spec ∈ definitions, + resolve spec.input.id.addr = some spec.ref ∧ after spec.ref = some spec.entry ∧ + readExpr? resolve spec.input.value = some spec.body.erase ∧ + readExpr? resolve spec.input.type = some spec.type.erase := by + induction plan with + | nil entries => simp + | @cons before after rest spec resolved fresh position run tail ih => + obtain ⟨checkedState, accepted⟩ := position.check_success succeeded + rw [anon_id] at accepted + have bodySound := AtomicDefinitionRun.sound.{u,0} run wellFormed accepted + have formed : (before.insert spec.ref spec.entry).WF := + insert_definition_wf wellFormed bodySound.2.2.1 bodySound.2.2.2.1 + bodySound.2.2.2.2.1 bodySound.2.2.2.2.2.1 + intro candidate present + rcases List.mem_cons.mp present with same | later + · subst candidate + exact ⟨resolved, tail.extends _ _ (Model.Environment.insert_same ..), + bodySound.1, bodySound.2.1⟩ + · exact ih formed candidate later + +private theorem AtomicDefinitionPlan.locations {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {work : Array AnonWorkItem} + {resolve : Address → Option (ConstRef β)} + {before after : Model.Environment β} {definitions : List (DefinitionSpec β)} + (plan : AtomicDefinitionPlan env cfg work resolve before definitions after) : + ∀ spec ∈ definitions, ∃ position : WorkPosition work (.standalone spec.input.id.addr), + Nonempty (StandalonePrefix spec.input.id (position.state env cfg).checker spec.input.constant) := by + induction plan with + | nil => simp + | cons spec resolved fresh position run tail ih => + intro candidate present + rcases List.mem_cons.mp present with same | later + · subst candidate + exact ⟨position, ⟨run.path⟩⟩ + · exact ih candidate later + +/-- An axiom has no value or computational equations in the initial model. -/ +structure AxiomSpec (β : Type u) where + id : KId .anon + ref : ConstRef β + isUnsafe : Bool + sourceType : KExpr .anon + type : AExpr β + +def AxiomSpec.constant {β : Type u} (spec : AxiomSpec β) : KConst .anon := + .axio () () spec.isUnsafe 0 spec.sourceType + +def AxiomSpec.entry {β : Type u} (spec : AxiomSpec β) : ConstantEntry β := + { universes := 0, type := spec.type, body := none } + +/-- Exactly the declared axiom interface, starting with no other entries. -/ +def axiomEnvironment {β : Type u} [DecidableEq β] : List (AxiomSpec β) → Model.Environment β + | [] => fun _ => none + | spec :: rest => (axiomEnvironment rest).insert spec.ref spec.entry + +/-- Syntactic provenance of one axiom at a real work position. The model +hypothesis supplies its inhabitant; this record only identifies its source +declaration and exact type. -/ +structure AxiomObservation {β : Type u} (env : Ixon.Env) (cfg : CheckCfg) + (work : Array AnonWorkItem) (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) (spec : AxiomSpec β) where + position : WorkPosition work (.standalone spec.id.addr) + path : StandalonePrefix spec.id (position.state env cfg).checker spec.constant + resolved : resolve spec.id.addr = some spec.ref + installed : entries spec.ref = some spec.entry + reads : readExpr? resolve spec.sourceType = some spec.type.erase + +/-- Complete support for the selected production environment fragment. +Every source key is checked, every work item is represented, and the axiom +interface contains exactly the listed source axioms. All definition resources +refer to concrete states of this same production run. -/ +structure AtomicEnvironmentFragment {β : Type u} [DecidableEq β] + (env : Ixon.Env) (cfg : CheckCfg) (resolve : Address → Option (ConstRef β)) where + work : Array AnonWorkItem + enumerated : buildAnonWork env = .ok work + axioms : List (AxiomSpec β) + definitions : List (DefinitionSpec β) + entries : Model.Environment β + axiomRuns : ∀ spec ∈ axioms, + Nonempty (AxiomObservation env cfg work resolve (axiomEnvironment axioms) spec) + plan : AtomicDefinitionPlan env cfg work resolve (axiomEnvironment axioms) definitions entries + sourceCovered : ∀ addr ∈ env.consts.keys, .standalone addr ∈ work + workCovered : ∀ item ∈ work, + (∃ spec ∈ axioms, item = .standalone spec.id.addr) ∨ + (∃ spec ∈ definitions, item = .standalone spec.input.id.addr) + +private theorem AtomicEnvironmentFragment.serial_success {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {resolve : Address → Option (ConstRef β)} + (fragment : AtomicEnvironmentFragment env cfg resolve) {results : Array CheckResult} + (accepted : checkEnvAnon env cfg = .ok results) + (succeeded : ∀ result ∈ results, result.err? = none) : + ∀ result ∈ (runAnonCheckList cfg fragment.work.toList + (initialAnonCheckLoopState env cfg)).results, result.err? = none := by + unfold checkEnvAnon at accepted + rw [fragment.enumerated] at accepted + cases accepted + exact succeeded + +/-- A successful `checkEnvAnon` run in the supported fragment extends every +model of its axiom set while preserving all axiom interpretations. This is a +relative model theorem, not a claim that arbitrary axioms are consistent. -/ +theorem checkEnvAnon_atomic_preserves_model {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {resolve : Address → Option (ConstRef β)} + (fragment : AtomicEnvironmentFragment env cfg resolve) + (wellFormed : (axiomEnvironment fragment.axioms).WF) + {results : Array CheckResult} (accepted : checkEnvAnon env cfg = .ok results) + (succeeded : ∀ result ∈ results, result.err? = none) : + fragment.entries.WF ∧ PreservesModels.{u,v} + (axiomEnvironment fragment.axioms) fragment.entries := + fragment.plan.sound wellFormed (fragment.serial_success accepted succeeded) + +/-- Exact type, universe arity, and value agreement with the declaration +returned by production lookup. Axiom entries contain no body. -/ +def DeclarationReading {β : Type u} (resolve : Address → Option (ConstRef β)) + (concrete : KConst .anon) (entry : ConstantEntry β) : Prop := + readExpr? resolve concrete.ty = some entry.type.erase ∧ + entry.universes = concrete.lvls.toNat ∧ + match concrete with + | .axio .. => entry.body = none + | .defn (val := value) .. => + ∃ body, entry.body = some body ∧ readExpr? resolve value = some body.erase + | _ => False + +/-- Every source address receives an interface entry whose type reads the +declaration actually reached by production lookup. Definitions additionally +have the exact checked body in their model entry. -/ +theorem checkEnvAnon_atomic_represents_source {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {resolve : Address → Option (ConstRef β)} + (fragment : AtomicEnvironmentFragment env cfg resolve) + (wellFormed : (axiomEnvironment fragment.axioms).WF) + {results : Array CheckResult} (accepted : checkEnvAnon env cfg = .ok results) + (succeeded : ∀ result ∈ results, result.err? = none) : + ∀ addr ∈ env.consts.keys, ∃ ref entry, + resolve addr = some ref ∧ fragment.entries ref = some entry ∧ + ∃ concrete : KConst .anon, + (∃ before after, TcM.checkConst (⟨addr, ()⟩ : KId .anon) before = .ok () after ∧ + Nonempty (StandalonePrefix (⟨addr, ()⟩ : KId .anon) before concrete)) ∧ + DeclarationReading resolve concrete entry := by + have serial := fragment.serial_success accepted succeeded + have represented := fragment.plan.represents wellFormed serial + intro addr present + rcases fragment.workCovered (.standalone addr) (fragment.sourceCovered addr present) with + ⟨spec, listed, same⟩ | ⟨spec, listed, same⟩ + · cases AnonWorkItem.standalone.inj same + obtain ⟨observation⟩ := fragment.axiomRuns spec listed + obtain ⟨after, run⟩ := observation.position.check_success serial + refine ⟨spec.ref, spec.entry, observation.resolved, + fragment.plan.extends _ _ observation.installed, spec.constant, + ⟨(observation.position.state env cfg).checker, after, run, ?_⟩, + observation.reads, rfl, rfl⟩ + simpa only [anon_id] using Nonempty.intro observation.path + · cases AnonWorkItem.standalone.inj same + have represents := represented spec listed + obtain ⟨position, path⟩ := fragment.plan.locations spec listed + obtain ⟨after, run⟩ := position.check_success serial + refine ⟨spec.ref, spec.entry, represents.1, represents.2.1, spec.input.constant, + ⟨(position.state env cfg).checker, after, run, ?_⟩, represents.2.2.2, + rfl, spec.body, rfl, represents.2.2.1⟩ + simpa only [anon_id] using path + +/-- No declaration in the resulting environment can inhabit a type whose +axiom-model interpretation is empty. In particular this applies to `False`. +The empty interpretation is preserved, rather than assumed for the completed +environment. -/ +theorem checkEnvAnon_atomic_no_false {β : Type u} [DecidableEq β] + {env : Ixon.Env} {cfg : CheckCfg} {resolve : Address → Option (ConstRef β)} + (fragment : AtomicEnvironmentFragment env cfg resolve) + (wellFormed : (axiomEnvironment fragment.axioms).WF) + {results : Array CheckResult} (accepted : checkEnvAnon env cfg = .ok results) + (succeeded : ∀ result ∈ results, result.err? = none) + {V : Type v} [SetTheory V] (axiomValues : Assignment β V) + (axiomModel : Realizes axiomValues (axiomEnvironment fragment.axioms)) + {falseRef : ConstRef β} {falseEntry : ConstantEntry β} + (hasFalse : axiomEnvironment fragment.axioms falseRef = some falseEntry) + (falseEmpty : axiomValues falseRef [] = empty) + {ref : ConstRef β} {entry : ConstantEntry β} + (present : fragment.entries ref = some entry) + (isFalse : entry.type.erase = .const falseRef []) : False := by + obtain ⟨_, preserve⟩ := checkEnvAnon_atomic_preserves_model fragment wellFormed accepted succeeded + obtain ⟨values, model, agrees⟩ := preserve V axiomValues axiomModel + have emptyValue : values falseRef [] = empty := (agrees _ _ hasFalse []).trans falseEmpty + have typeEq := AExpr.eq_const_of_erase_eq isFalse + have member := model.member ref entry present (List.replicate entry.universes 0) + (by simp) (fun _ => empty) + rw [typeEq] at member + simp only [interp, List.map_nil, emptyValue] at member + exact not_mem_empty _ member + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Production.lean b/Ix/Kernel/Verify/Consistency/Production.lean new file mode 100644 index 000000000..320b46722 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Production.lean @@ -0,0 +1,246 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Driver +import Ix.Kernel.Verify.Consistency.Atomic + +/-! +# Standalone production declaration checks + +These theorems invert the real public checker, including its error isolation, +initial lazy lookup, block routing, per-constant reset, validation, type +inference, theorem guard, value inference, and conversion. The supported +conversion path is the initial address-equality branch. Finite address +faithfulness connects that comparison to the exact model syntax. + +The resource records contain operational equations and structural interface +agreement. They do not contain a typing proof, a method-soundness callback, +or an assumption that an accepted declaration already has a model. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +private theorem runTcBind {α β : Type} (x : TcM .anon α) (k : α → TcM .anon β) + (state : TcState .anon) : + EStateM.bind x k state = match x state with + | .ok value after => k value after + | .error err after => .error err after := by + unfold EStateM.bind + cases x state <;> rfl + +/-- The concrete path of a standalone public check. This ties the member +declaration to both production lookup and the actual reset, without assuming +that block coordination or lazy ingress preserves an arbitrary predicate. -/ +structure StandalonePrefix (id : KId .anon) (before : TcState .anon) + (concrete : KConst .anon) where + first : KConst .anon + loaded : TcState .anon + routed : TcState .anon + reset : TcState .anon + ready : TcState .anon + firstGet : TcM.getConst id before = .ok first loaded + route : (RecM.coordinatedBlockFor first).run (methodsN before.recFuel.toNat) + loaded = .ok none routed + resetRun : TcM.reset routed = .ok () reset + memberGet : TcM.getConst id reset = .ok concrete ready + +/-- Success at the public boundary entails success of the exact member +identified by the standalone path. In particular, an error cannot be +turned into acceptance by the public cache rollback wrapper. -/ +theorem StandalonePrefix.member_success {id : KId .anon} + {before after : TcState .anon} {concrete : KConst .anon} + (path : StandalonePrefix id before concrete) + (accepted : TcM.checkConst id before = .ok () after) : + (RecM.checkConstMember id concrete).run (methodsN before.recFuel.toNat) + path.ready = .ok () after := by + unfold TcM.checkConst TcM.isolateCheckErrors at accepted + cases run : TcM.runRec (RecM.checkConst id) before with + | error err failed => rw [run] at accepted; contradiction + | ok result finished => + rw [run] at accepted + cases accepted + change (RecM.checkConst id).run (methodsN before.recFuel.toNat) before = + .ok () after at run + unfold RecM.checkConst at run + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at run + change EStateM.bind (TcM.getConst id) _ before = _ at run + rw [runTcBind, path.firstGet] at run + change EStateM.bind + ((RecM.coordinatedBlockFor path.first).run (methodsN before.recFuel.toNat)) + _ path.loaded = _ at run + rw [runTcBind, path.route] at run + change (RecM.checkConstMemberFresh id).run (methodsN before.recFuel.toNat) + path.routed = .ok () after at run + unfold RecM.checkConstMemberFresh at run + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at run + change EStateM.bind TcM.reset _ path.routed = _ at run + rw [runTcBind, path.resetRun] at run + change EStateM.bind (TcM.getConst id) _ path.reset = _ at run + rw [runTcBind, path.memberGet] at run + exact run + +/-- Monomorphic definition data. Its complete concrete declaration is the +one returned by the production lookup, including kind, safety, and block. -/ +structure DefinitionInput where + id : KId .anon + kind : Ix.DefKind + safety : Ix.DefinitionSafety + hints : Lean.ReducibilityHints + type : KExpr .anon + value : KExpr .anon + block : KId .anon + +def DefinitionInput.constant (input : DefinitionInput) : KConst .anon := + .defn () () input.kind input.safety input.hints 0 input.type input.value () input.block + +/-- Exact successful observations through a definition's value-conversion +call. Later safety checks may still reject; the extraction theorem requires +the entire member check to have succeeded. -/ +structure DefinitionBodyTrace (input : DefinitionInput) (methods : Methods .anon) + (before : TcState .anon) where + validated : TcState .anon + inferredType : KExpr .anon + typeState : TcState .anon + level : KUniv .anon + valueStart : TcState .anon + inferredValue : KExpr .anon + conversionStart : TcState .anon + conversionEnd : TcState .anon + validationRun : (RecM.validateConstWellScoped input.constant).run methods before = + .ok () validated + typeRun : (RecM.infer input.type).run methods validated = .ok inferredType typeState + sortRun : (RecM.ensureSortDirect inferredType).run methods typeState = .ok level valueStart + theoremGuard : (input.kind == .thm && !univEq level .mkZero) = false + valueRun : (RecM.infer input.value).run methods valueStart = .ok inferredValue conversionStart + conversionRun : (RecM.isDefEq inferredValue input.type).run methods conversionStart = + .ok true conversionEnd + +/-- Invert the production declaration branch rather than assuming that its +acceptance establishes either type or value typing. -/ +theorem definition_body_trace {input : DefinitionInput} {methods : Methods .anon} + {before after : TcState .anon} + (accepted : (RecM.checkConstMember input.id input.constant).run methods before = + .ok () after) : Nonempty (DefinitionBodyTrace input methods before) := by + unfold RecM.checkConstMember at accepted + simp only [DefinitionInput.constant, Mode.F.hasDups, Bool.false_eq_true, if_false, + ReaderT.run_bind] at accepted + cases validation : (RecM.validateConstWellScoped input.constant).run methods before with + | error err failed => + change EStateM.bind ((RecM.validateConstWellScoped input.constant).run methods) + _ before = _ at accepted + rw [runTcBind, validation] at accepted + contradiction + | ok result validated => + cases result + change EStateM.bind ((RecM.validateConstWellScoped input.constant).run methods) + _ before = _ at accepted + rw [runTcBind, validation] at accepted + change EStateM.bind ((RecM.infer input.type).run methods) _ validated = _ at accepted + cases typeRun : (RecM.infer input.type).run methods validated with + | error err failed => rw [runTcBind, typeRun] at accepted; contradiction + | ok inferredType typeState => + rw [runTcBind, typeRun] at accepted + change EStateM.bind ((RecM.ensureSortDirect inferredType).run methods) + _ typeState = _ at accepted + cases sortRun : (RecM.ensureSortDirect inferredType).run methods typeState with + | error err failed => rw [runTcBind, sortRun] at accepted; contradiction + | ok level valueStart => + rw [runTcBind, sortRun] at accepted + simp only at accepted + by_cases guard : input.kind == .thm && !univEq level .mkZero + · simp only [guard, if_true] at accepted + contradiction + · simp only [guard, Bool.false_eq_true, if_false, ReaderT.run_bind] at accepted + cases valueRun : (RecM.infer input.value).run methods valueStart with + | error err failed => + change EStateM.bind ((RecM.infer input.value).run methods) + _ valueStart = _ at accepted + rw [runTcBind, valueRun] at accepted + contradiction + | ok inferredValue conversionStart => + change EStateM.bind ((RecM.infer input.value).run methods) + _ valueStart = _ at accepted + rw [runTcBind, valueRun] at accepted + change EStateM.bind ((RecM.isDefEq inferredValue input.type).run methods) + _ conversionStart = _ at accepted + cases conversionRun : (RecM.isDefEq inferredValue input.type).run methods + conversionStart with + | error err failed => rw [runTcBind, conversionRun] at accepted; contradiction + | ok answer conversionEnd => + rw [runTcBind, conversionRun] at accepted + cases answer with + | false => + simp only [Bool.not_false, if_true] at accepted + contradiction + | true => + exact ⟨{ + validated, inferredType, typeState, level, valueStart, + inferredValue, conversionStart, conversionEnd, + validationRun := validation, typeRun, sortRun, + theoremGuard := Bool.eq_false_iff.mpr guard, + valueRun, conversionRun }⟩ + +/-- Operational support for the selected production definition fragment. +Resources are required only at the states exposed by successful body traces. +The conversion guard records the actual initial hash-equality path. -/ +structure AtomicDefinitionRun {β : Type u} (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) (input : DefinitionInput) (before : TcState .anon) + (body type : AExpr β) where + path : StandalonePrefix input.id before input.constant + inference : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, + AtomicInference resolve entries trace.valueStart input.value body type + hashPath : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, + (trace.inferredValue == input.type) = true + faithful : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, + trace.inferredValue.AddrFaithful input.type + +/-- Successful production checking yields a model typing judgment for the +actual value and declared type, with syntactic closure and dependency support +needed to extend a model. -/ +theorem AtomicDefinitionRun.sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {input : DefinitionInput} {before after : TcState .anon} {body type : AExpr β} + (fragment : AtomicDefinitionRun resolve entries input before body type) + (wellFormed : entries.WF) + (accepted : TcM.checkConst input.id before = .ok () after) : + readExpr? resolve input.value = some body.erase ∧ + readExpr? resolve input.type = some type.erase ∧ + body.Scope 0 0 ∧ type.Scope 0 0 ∧ + body.ReferencesIn entries ∧ type.ReferencesIn entries ∧ + TypingClaim.{u,v} entries [] body type := by + obtain ⟨trace⟩ := definition_body_trace (fragment.path.member_success accepted) + have result := (fragment.inference trace).sound trace.valueRun + have same := beq_readExpr? (resolve := resolve) + (fragment.faithful trace) (fragment.hashPath trace) + have scope := (fragment.inference trace).support.scopeAndReferences wellFormed + exact ⟨result.1, same.symm.trans result.2.1, scope.1, scope.2.1, + scope.2.2.1, scope.2.2.2, result.2.2⟩ + +/-- A fresh definition cannot use itself as the atomic value that justifies +its own type. This exclusion follows from the preceding interface, without +any assumption about the consistency of the axioms. -/ +theorem AtomicDefinitionRun.no_self_alias {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {input : DefinitionInput} {before after : TcState .anon} {body type : AExpr β} + (fragment : AtomicDefinitionRun resolve entries input before body type) + (wellFormed : entries.WF) {ref : ConstRef β} + (resolved : resolve input.id.addr = some ref) (fresh : entries ref = none) + {info : ExprInfo .anon} (self : input.value = .const input.id #[] info) + (accepted : TcM.checkConst input.id before = .ok () after) : False := by + have result := AtomicDefinitionRun.sound.{u,0} fragment wellFormed accepted + have reads := result.1 + rw [self] at reads + simp [readExpr?, resolved] at reads + have bodyEq := AExpr.eq_const_of_erase_eq reads.symm + have references := result.2.2.2.2.1 + rw [bodyEq] at references + have present := references ref (by simp [AExpr.references]) + simp only [fresh, Option.isSome_none, Bool.false_eq_true] at present + +end Ix.Kernel.Consistency diff --git a/README.md b/README.md index 37832c63a..c9bc8f732 100644 --- a/README.md +++ b/README.md @@ -176,9 +176,11 @@ Ix consists of the following core components: `Ix.Kernel` includes audited implementation proofs and a certified receipt interface with relative consistency theorems under an explicit set-theory -assumption. Full consistency of the production `checkEnvAnon` checker remains -open. See the [kernel verification guide](docs/kernel-verification.md) for the -theorem boundaries and remaining obligations, and +assumption. A production `checkEnvAnon` fragment for monomorphic aliases and +closed universe terms preserves any given model of its source axioms. Full +checker consistency remains open. See the +[kernel verification guide](docs/kernel-verification.md) for the fragment's +execution premises and remaining obligations, and [certified checking](docs/certified-checking.md) for runnable examples. Run `lake run check-kernel` to validate the implementation proofs, consistency diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean new file mode 100644 index 000000000..7b9376856 --- /dev/null +++ b/Tests/Ix/Kernel/Consistency.lean @@ -0,0 +1,91 @@ +module + +public import LSpec +public import Ix.Kernel +public import Tests.Ix.Kernel.IxonFixtures + +/-! +Production regressions for the atomic consistency fragment. These execute +the real lazy serial driver on content-addressed Ixon declarations. The +formal results and their resource premises are checked separately by +`IxKernelConsistency`; these tests do not substitute for those proofs. +-/ + +namespace Tests.Kernel.Consistency + +open LSpec Ix.Kernel Tests.Kernel.Fixtures + +private def allSucceeded (env : Ixon.Env) (expected : Nat) (cfg : CheckCfg := {}) : Bool := + match checkEnvAnon env cfg with + | .ok results => results.size == expected && results.all (·.err?.isNone) + | .error _ => false + +private def rowFailed (env : Ixon.Env) (target : Address) : Bool := + match checkEnvAnon env with + | .ok results => results.any fun row => row.addr == target && row.err?.isSome + | .error _ => false + +/-- `P : Prop`, `p : P`, then definition/theorem/opaque aliases of `p`. +The axiom set supplies `p`; the definitions introduce no additional axiom. -/ +private def aliasEnvironment : Ixon.Env := Id.run do + let (env, proposition) := storeConst {} + ⟨.axio ⟨false, 0, .sort 0⟩, #[], #[], #[.zero]⟩ + let (env, witness) := storeConst env + ⟨.axio ⟨false, 0, .ref 0 #[]⟩, #[], #[proposition], #[]⟩ + let (env, first) := storeConst env + ⟨.defn ⟨.defn, .safe, 0, .ref 0 #[], .ref 1 #[]⟩, + #[], #[proposition, witness], #[]⟩ + let (env, second) := storeConst env + ⟨.defn ⟨.thm, .safe, 0, .ref 0 #[], .ref 1 #[]⟩, + #[], #[proposition, first], #[]⟩ + let (env, _) := storeConst env + ⟨.defn ⟨.opaq, .safe, 0, .ref 0 #[], .ref 1 #[]⟩, + #[], #[proposition, second], #[]⟩ + return env + +private def sortEnvironment : Ixon.Env := Id.run do + let definition : Ix.DefKind → Ixon.Constant := fun kind => + ⟨.defn ⟨kind, .safe, 0, .sort 1, .sort 0⟩, #[], #[], #[.zero, .succ .zero]⟩ + let (env, _) := storeConst {} (definition .defn) + let (env, _) := storeConst env (definition .opaq) + return env + +private def failedAlias : Ixon.Env × Address := Id.run do + let (env, carrier) := envA + let (env, witness) := storeConst env + ⟨.axio ⟨false, 0, .ref 0 #[]⟩, #[], #[carrier], #[]⟩ + -- The witness has type A, whereas this definition declares Prop. + return storeConst env + ⟨.defn ⟨.defn, .safe, 0, .sort 0, .ref 0 #[]⟩, + #[], #[witness], #[.zero]⟩ + +private def mismatchedSort : Ixon.Env × Address := + storeConst {} + ⟨.defn ⟨.defn, .safe, 0, .sort 0, .sort 0⟩, #[], #[], #[.zero]⟩ + +private def missingReference : Ixon.Env × Address := + storeConst {} + ⟨.defn ⟨.defn, .safe, 0, .sort 0, .ref 0 #[]⟩, + #[], #[Address.blake3 "atomic-fragment-missing-reference".toUTF8], #[.zero]⟩ + +private def cases : TestSeq := + test "atomic fragment: source axioms and transitive aliases check" + (allSucceeded aliasEnvironment 5) + ++ test "atomic fragment: alias checks survive cache clearing at every item" + (allSucceeded aliasEnvironment 5 { clearEvery := 1 }) + ++ test "atomic fragment: closed sort definitions check with persistent caches" + (allSucceeded sortEnvironment 2 { clearEvery := 0 }) + ++ test "atomic fragment: closed sort definitions check with fresh caches" + (allSucceeded sortEnvironment 2 { clearEvery := 1 }) + ++ test "atomic fragment: value/type mismatch is an error row inside public ok" + (let (env, target) := failedAlias; rowFailed env target) + ++ test "atomic fragment: Sort 0 does not inhabit Sort 0" + (let (env, target) := mismatchedSort; rowFailed env target) + ++ test "atomic fragment: an unresolved reference is not an admitted axiom" + (let (env, target) := missingReference; rowFailed env target) + ++ test "atomic fragment: empty input returns an empty successful result" + (allSucceeded {} 0) + +public def suite : List TestSeq := [cases] + +end Tests.Kernel.Consistency diff --git a/Tests/Main.lean b/Tests/Main.lean index 0e7753500..3650fcb55 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -40,6 +40,7 @@ import Tests.Ix.Kernel.IxonFixtures import Tests.Ix.Kernel.WhnfTests import Tests.Ix.Kernel.InferDefEq import Tests.Ix.Kernel.CheckTests +import Tests.Ix.Kernel.Consistency import Tests.Ix.Kernel.AnonDiff import Tests.Ix.Kernel.InitScale import Tests.Ix.Kernel.TutorialTc @@ -108,6 +109,7 @@ def primarySuites : Std.HashMap String (List LSpec.TestSeq) := .ofList [ ("tc-unit", Tests.Kernel.Unit.suite ++ Tests.Kernel.Substrate.suite ++ Tests.Kernel.Fixtures.suite ++ Tests.Kernel.WhnfTests.suite ++ Tests.Kernel.InferDefEq.suite ++ Tests.Kernel.CheckTests.suite + ++ Tests.Kernel.Consistency.suite ++ Tests.Kernel.Roundtrip.unitTests ++ Tests.Kernel.IngressMeta.unitTests), ] diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 7dfc385f7..3f8eabaf7 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -43,14 +43,80 @@ dependency audit restricted to Lean's three standard axioms. - `ModelTyping.no_false` rules out a closed model-typed kernel expression at primitive False when its environment has been admitted by the certified interface and the set-theory assumption has an instance. +- `checkEnvAnon_atomic_preserves_model` connects a supported production + environment run to model extension. `checkEnvAnon_atomic_no_false` excludes + a declaration at an axiom type interpreted as empty, including False. -The last theorem assumes semantic typing; it does not assume or prove that -arbitrary checker success supplies it. A complete checker consistency theorem +`ModelTyping.no_false` assumes semantic typing. The production fragment below +constructs that typing from its supported inference and conversion paths. +A complete checker consistency theorem still requires the remaining inference/conversion cases, cache invariants, address-to-store resolution, and declaration admission to establish that postcondition for `checkEnvAnon`. The existing named-calculus proofs are retained to support this refinement, rather than being treated as a set-model proof. +## Production environment fragment + +The axiom policy is relative: **every model of the source axioms extends to a +model of the checked environment, preserving the axiom interpretations**. +The axiom interface starts empty and contains exactly the listed source +axioms. Its types must be closed and refer only to that interface. A concrete +`Realizes` witness supplies their interpretation; checking an axiom's type +does not manufacture an inhabitant. This model-existence hypothesis is not +identified with syntactic consistency of an arbitrary axiom theory. + +The initial fragment covers monomorphic standalone definitions, theorems, +and opaque definitions whose values are either closed universe terms or +references to preceding interface entries. Examples include: + +```lean +axiom P : Prop +axiom p : P +def q : P := p +theorem r : P := q +def typeAlias : Type := Prop +``` + +`AtomicEnvironmentFragment` records the precise execution boundary: + +- Every source key occurs in the exact `buildAnonWork` result, and every work + item is represented by an axiom or a definition. Standalone lookup, routing, + and reset witnesses identify the actual checked `KConst`. +- Value inference misses both cache partitions. Constant lookup agrees with + an already admitted monomorphic type; empty level substitution preserves + that type. Sort inference retains the finite interning coherence and + address-faithfulness premises. +- Conversion takes the initial hash-equality path, with faithfulness of the + compared expressions. General reduction and conversion caches are outside + this fragment. +- Definitions are added in a dependency order with fresh references. Their + runtime observations still use the states reached in the original serial + work order, including cache clearing. `AtomicDefinitionRun.no_self_alias` + proves that a fresh definition cannot justify its own type by referring to + itself. +- `checkEnvAnon` returns `.ok results` **and every result row has no error**. + The outer `.ok` alone does not mean that the declarations passed. + +These are operational and representation witnesses, not a checker-soundness +callback or a supplied typing proof. A caller must establish them for a run; +this change does not automatically derive them from arbitrary Ixon syntax. +The proof follows the public checker through validation, type inference, +the theorem guard, value inference, and conversion. Successful value +inference constructs the body typing used to extend the preceding model. +Lambdas, applications, polymorphic instantiation, inductives, coordinated +blocks, and other conversion paths remain outside this slice. + +`checkEnvAnon_atomic_represents_source` assigns every source address an +interface whose type reads the exact declaration reached by production +lookup. Definition interfaces also retain their checked bodies. This is a +statement about the production ingress/lookup result; the independent +serialized-Ixon reader refinement remains a separate boundary. + +The no-False corollary takes a model of the initial axiom interface in which +the designated false type is empty. Model extension preserves that value, +so no resulting declaration can inhabit it. It does not blacklist axiom +names or merely exclude declarations literally written with type `False`. + ## Trust checks The audits traverse checked declaration types and bodies, including inductive @@ -98,10 +164,15 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 18 exact theorem boundaries. Its remaining -native assumptions are explicitly named proofs reached through production -smart-constructor code; the model's no-False theorem itself uses only -`propext`, `Classical.choice`, and `Quot.sound`, with set theory as a hypothesis. +The consistency target checks 36 exact theorem boundaries. The production +environment roots retain four existing generated output-length proofs, +reached through expression/universe construction, names, and the full +production method table. They introduce no new native proofs. The model +extension lemma and `ModelTyping.no_false` use only `propext`, +`Classical.choice`, and `Quot.sound`, with set theory as a hypothesis. +The new production roots additionally forbid the earlier abstract +`CheckSuccessSound`/`SupportedCheckFragment` interfaces and the independent +certificate validator in their dependency closures. ## Certified host adapters @@ -129,6 +200,7 @@ tests are outside the host gate. | --- | --- | | Certified checker contracts | [`Ix/Kernel/Certified.lean`](../Ix/Kernel/Certified.lean), [`CertifiedClaims.lean`](../Ix/Kernel/CertifiedClaims.lean) | | Direct production refinement and its audit | [`Ix/Kernel/Verify/Consistency.lean`](../Ix/Kernel/Verify/Consistency.lean) | +| Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | | Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | | Concrete set-theory instance | [Separate model package](../Models/SetTheory/README.md) | @@ -142,3 +214,8 @@ necessary named-specification imports and exact hash-axiom audit updates. The new compiler development, circuit changes and certificate VM pilot are deferred. The external `lean4lean` dependency and its benchmark/test targets are removed; all verification dependencies are local to Ix. + +The subsequent production-fragment change adds direct inference, declaration, +and serial-environment proofs on top of that extraction. It changes no +production checker behavior and adds regression cases to the existing kernel +unit gate. diff --git a/docs/theory.md b/docs/theory.md index be2cd142e..6aa76b3a2 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -22,6 +22,12 @@ These are relative consistency results for the certified interface. The and proves direct model results for universe comparison, structural expression reading, interning, and the production sort-inference branch. The certified host adapters connect authenticated serialized Ixon to model admission. +A production fragment for monomorphic aliases and closed universe terms now +proves that `checkEnvAnon` preserves a supplied model of its source axiom set, +under explicit operational and representation witnesses. Its no-False +corollary preserves the axiom model's empty interpretation of the false type; +it does not assume that arbitrary source axioms are consistent. See the +[fragment contract](kernel-verification.md#production-environment-fragment). A complete bridge from arbitrary `Ix.Kernel.checkEnvAnon` success or compiler/backend execution remains unfinished. diff --git a/lakefile.lean b/lakefile.lean index 5ac660b42..b174c29c0 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -254,8 +254,8 @@ lean_lib IxKernelVerify where end IxKernelVerify -/- Direct refinement of production operations into the set model, with its -own exact axiom audit. This is distinct from whole-checker soundness. -/ +/- Direct production refinement, including the atomic environment fragment, +with its own exact axiom audit. Whole-checker soundness remains separate. -/ lean_lib IxKernelConsistency where roots := #[`Ix.Kernel.Verify.Consistency] globs := #[.andSubmodules `Ix.Kernel.Verify.Consistency] From 8172135c663d562caf15f91d48f20de0a5aa84c1 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 07:51:29 -0400 Subject: [PATCH 03/30] Simplify kernel certification proofs and documentation Replace repeated state-monad case splits with a local bind-success lemma and direct EStateM.bind unfolding. Name the components of soundness results and simplify result-preservation and entry-equality proofs. Keep model extension's explicit import in the environment layer. Public theorem statements and their assumptions are unchanged. Tighten comments and documentation around the supported production fragment, the source-axiom model hypothesis, and remaining refinement obligations. Collect provenance details together and link the Mathlib model to the fragment contract. Validation: - lake build --wfail IxKernelConsistency: 36 exact theorem audits passed. - lake test --wfail -- tc-unit: 403 checks passed. - git diff --check: passed. --- Ix/Kernel/Verify/Consistency.lean | 2 +- Ix/Kernel/Verify/Consistency/Atomic.lean | 43 ++--- Ix/Kernel/Verify/Consistency/Audit.lean | 2 +- Ix/Kernel/Verify/Consistency/Environment.lean | 84 ++++------ Ix/Kernel/Verify/Consistency/Production.lean | 150 +++++++----------- Models/SetTheory/README.md | 10 +- Tests/Ix/Kernel/Consistency.lean | 5 +- docs/certified-checking.md | 14 +- docs/kernel-verification.md | 139 +++++++--------- docs/theory.md | 23 +-- 10 files changed, 189 insertions(+), 283 deletions(-) diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 13dc8657e..e6c5a00b0 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -17,7 +17,7 @@ import Ix.Kernel.Verify.Consistency.Audit This library connects production kernel operations to `Ix.Theory`. Each transport keeps its representation, arithmetic, and dependency assumptions -explicit. A production `checkEnvAnon` fragment now preserves models of its +explicit. A production `checkEnvAnon` fragment preserves models of its axiom set for monomorphic aliases and closed sorts under the stated execution resources. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Atomic.lean b/Ix/Kernel/Verify/Consistency/Atomic.lean index 12565de84..d6317d312 100644 --- a/Ix/Kernel/Verify/Consistency/Atomic.lean +++ b/Ix/Kernel/Verify/Consistency/Atomic.lean @@ -4,15 +4,14 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Infer -import Ix.Theory.Model.Extension /-! # Atomic production inference -The first declaration fragment admits closed sorts and monomorphic references. -References use the type of an already admitted interface entry. The premises -below describe concrete cache misses, lookup results, and finite interning -support; none assumes a typing judgment or the soundness of a checker method. +The declaration fragment admits closed sorts and monomorphic references. +References use the type of an existing interface entry. Cache misses, lookup +agreement, and finite interning support connect each production result to its +model type. -/ namespace Ix.Kernel.Consistency @@ -21,15 +20,6 @@ open Theory Theory.Model universe u v -private theorem runTcBind {α β : Type} (x : TcM .anon α) (k : α → TcM .anon β) - (state : TcState .anon) : - EStateM.bind x k state = match x state with - | .ok value after => k value after - | .error err after => .error err after := by - show EStateM.bind x k state = _ - unfold EStateM.bind - cases x state <;> rfl - /-- The two inference-cache partitions miss at the actual key computed by production. Both misses are required, so this applies in either policy mode. -/ structure UncachedInference (before : TcState .anon) (term : KExpr .anon) where @@ -51,9 +41,9 @@ theorem infer_uncached_success {term type : KExpr .anon} unfold RecM.infer RecM.inferWith at accepted simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted change EStateM.bind (TcM.inferKey term) _ before = _ at accepted - rw [runTcBind, miss.keyRun] at accepted + rw [EStateM.bind, miss.keyRun] at accepted change EStateM.bind (get : TcM .anon (TcState .anon)) _ miss.keyed = _ at accepted - rw [runTcBind, show (get : TcM .anon (TcState .anon)) miss.keyed = + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) miss.keyed = .ok miss.keyed miss.keyed from rfl] at accepted simp only at accepted rw [miss.fullMiss] at accepted @@ -63,9 +53,9 @@ theorem infer_uncached_success {term type : KExpr .anon} change EStateM.bind (RecM.inferUncached RecM.inferCall false term methods) _ miss.keyed = _ at accepted cases run : RecM.inferUncached RecM.inferCall false term methods miss.keyed with - | error err failed => rw [runTcBind, run] at accepted; contradiction + | error err failed => rw [EStateM.bind, run] at accepted; contradiction | ok ty state => - rw [runTcBind, run] at accepted + rw [EStateM.bind, run] at accepted change EStateM.Result.ok ty { state with env := { state.env with inferCache := state.env.inferCache.insert miss.key ty } } = .ok type after at accepted cases accepted @@ -74,16 +64,16 @@ theorem infer_uncached_success {term type : KExpr .anon} simp only [policy, if_true] at accepted simp only [ReaderT.run_bind] at accepted change EStateM.bind (get : TcM .anon (TcState .anon)) _ miss.keyed = _ at accepted - rw [runTcBind, show (get : TcM .anon (TcState .anon)) miss.keyed = + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) miss.keyed = .ok miss.keyed miss.keyed from rfl] at accepted simp only at accepted rw [miss.onlyMiss] at accepted change EStateM.bind (RecM.inferUncached RecM.inferCall true term methods) _ miss.keyed = _ at accepted cases run : RecM.inferUncached RecM.inferCall true term methods miss.keyed with - | error err failed => rw [runTcBind, run] at accepted; contradiction + | error err failed => rw [EStateM.bind, run] at accepted; contradiction | ok ty state => - rw [runTcBind, run] at accepted + rw [EStateM.bind, run] at accepted change EStateM.Result.ok ty { state with env := { state.env with inferOnlyCache := state.env.inferOnlyCache.insert miss.key ty } } = .ok type after at accepted cases accepted @@ -117,8 +107,7 @@ inductive AtomicInferenceSupport {β : Type u} namespace AtomicInferenceSupport -/-- This fragment's typing rule is proved from the sort rule or an existing -constant interface, independently of any production success assumption. -/ +/-- The model's sort and constant rules type each supported syntax form. -/ theorem typing {β : Type u} {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} {term : KExpr .anon} {before : TcState .anon} {body type : AExpr β} (support : AtomicInferenceSupport resolve entries term before body type) : @@ -163,9 +152,9 @@ theorem output {β : Type u} {resolve : Address → Option (ConstRef β)} simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted change EStateM.bind (TcM.getConst id) _ before = _ at accepted cases got : TcM.getConst id before with - | error err failed => rw [runTcBind, got] at accepted; contradiction + | error err failed => rw [EStateM.bind, got] at accepted; contradiction | ok concrete loaded => - rw [runTcBind, got] at accepted + rw [EStateM.bind, got] at accepted simp only at accepted split at accepted · contradiction @@ -200,9 +189,7 @@ structure AtomicInference {β : Type u} (resolve : Address → Option (ConstRef misses : UncachedInference before term support : AtomicInferenceSupport resolve entries term misses.keyed body type -/-- A successful public inference in this fragment returns the semantic type -of the exact source tree. The inference implementation supplies the output -agreement; callers do not supply a typing or method-soundness premise. -/ +/-- Successful production inference returns the model type of the source tree. -/ theorem AtomicInference.sound {β : Type u} {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} {before after : TcState .anon} {term inferred : KExpr .anon} {body type : AExpr β} {methods : Methods .anon} diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 7d49bf4a3..3a6684b17 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -46,7 +46,7 @@ private def productionRoots : Array Lean.Name := #[ ``checkEnvAnon_atomic_no_false ] -/-- The new production roots must not acquire a checker-soundness assumption +/-- Production roots must not acquire a checker-soundness assumption or invoke the independent certificate validator to establish acceptance. -/ private def forbiddenProduction : Array Lean.Name := #[ `Ix.Kernel.CheckSuccessSound, diff --git a/Ix/Kernel/Verify/Consistency/Environment.lean b/Ix/Kernel/Verify/Consistency/Environment.lean index f30a54e1f..9569ef804 100644 --- a/Ix/Kernel/Verify/Consistency/Environment.lean +++ b/Ix/Kernel/Verify/Consistency/Environment.lean @@ -4,15 +4,15 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Production +import Ix.Theory.Model.Extension /-! # Relative consistency of a production environment fragment -The initial interface contains exactly the supplied axiom declarations. A -dependency order adds fresh monomorphic definitions, using successful calls -from the real serial `checkEnvAnon` run. Each addition constructs its value in -every model of the previous interface. Thus definitions preserve any given -model of the axiom set; no axiom is silently assumed to be inhabited. +The initial interface contains exactly the supplied axiom declarations. +Successful calls from the serial `checkEnvAnon` run add fresh monomorphic +definitions in dependency order. Each addition extends every model of the +previous interface and preserves its existing interpretations. -/ namespace Ix.Kernel.Consistency @@ -52,14 +52,9 @@ private theorem finish_results (cfg : CheckCfg) (before : AnonCheckLoopState) private theorem item_keeps_result (cfg : CheckCfg) (before : AnonCheckLoopState) (item : AnonWorkItem) {result : CheckResult} (found : result ∈ before.results) : result ∈ (runAnonCheckItem cfg before item).results := by - cases run : TcM.checkConst (⟨item.primary, ()⟩ : KId .anon) before.checker with - | ok value after => - cases value - simp only [runAnonCheckItem, EStateM.run, run, finish_results] - exact Array.mem_append.mpr (.inl found) - | error err after => - simp only [runAnonCheckItem, EStateM.run, run, finish_results] - exact Array.mem_append.mpr (.inl found) + cases run : TcM.checkConst (⟨item.primary, ()⟩ : KId .anon) before.checker <;> + simp only [runAnonCheckItem, EStateM.run, run, finish_results] <;> + exact Array.mem_append.mpr (.inl found) private theorem list_keeps_result (cfg : CheckCfg) (work : List AnonWorkItem) (before : AnonCheckLoopState) {result : CheckResult} (found : result ∈ before.results) : @@ -97,14 +92,12 @@ theorem WorkPosition.check_success {env : Ixon.Env} {cfg : CheckCfg} (list_keeps_result cfg position.trailing _ appears) simp [failed] at contradiction -/-- The semantic entry published for a monomorphic definition. No reduction -equations or extra typed facts are manufactured by this fragment. -/ +/-- A monomorphic definition entry, with its body and no additional laws or facts. -/ def definitionEntry {β : Type u} (body type : AExpr β) : ConstantEntry β := { universes := 0, type, body := some body } -/-- Body typing already includes hereditary validity of the declared type. -This constructs a model extension directly, without separately assuming a -model for the pending declaration. -/ +/-- Interpret a fresh definition's body to extend the preceding model. +Body typing supplies hereditary validity of the declared type. -/ theorem extend_atomic_definition {β : Type u} [DecidableEq β] {entries : Model.Environment β} {ref : ConstRef β} {body type : AExpr β} (wellFormed : entries.WF) (fresh : entries ref = none) @@ -133,12 +126,12 @@ theorem extend_atomic_definition {β : Type u} [DecidableEq β] exact (typed V constants realizes levels env (Context.valid_nil constants levels env)).2.2 · intro candidate present levels _ env change some body = some candidate at present - cases Option.some.inj present + cases present exact (agrees.wellDenoted bodyRefs levels env).mpr (typed V constants realizes levels env (Context.valid_nil constants levels env)).1 · intro candidate present levels _ env change some body = some candidate at present - cases Option.some.inj present + cases present rw [value, agrees.interp bodyRefs] · intro law present exact (List.not_mem_nil present).elim @@ -164,22 +157,21 @@ private theorem insert_definition_wf {β : Type u} [DecidableEq β] apply wellFormed.insert typeScope · intro candidate present change some body = some candidate at present - cases Option.some.inj present + cases present exact bodyScope · exact typeRefs · intro candidate present change some body = some candidate at present - cases Option.some.inj present + cases present exact bodyRefs · simp [definitionEntry] · simp [definitionEntry] · simp [definitionEntry] · simp [definitionEntry] -/-- A dependency order over the checked definitions. Each reference is fresh -and each atomic body reads only the preceding interface. The work position -retains the original serial order, which may differ from this dependency -order. No semantic acceptance premise appears in this plan. -/ +/-- Definitions in dependency order, with fresh references and bodies that +read the preceding interface. Work positions retain the runtime serial order, +which may differ from this dependency order. -/ inductive AtomicDefinitionPlan {β : Type u} [DecidableEq β] (env : Ixon.Env) (cfg : CheckCfg) (work : Array AnonWorkItem) (resolve : Address → Option (ConstRef β)) : @@ -219,9 +211,7 @@ private theorem anon_id (id : KId .anon) : (⟨id.addr, ()⟩ : KId .anon) = id cases id with | mk addr name => cases name; rfl -/-- Every accepted definition in the dependency order extends the preceding -model. The initial interface need only have a model; its axioms need not be -part of a fixed whitelist. -/ +/-- Accepted definitions extend every model of the preceding interface. -/ theorem AtomicDefinitionPlan.sound {β : Type u} [DecidableEq β] {env : Ixon.Env} {cfg : CheckCfg} {work : Array AnonWorkItem} {resolve : Address → Option (ConstRef β)} @@ -238,16 +228,15 @@ theorem AtomicDefinitionPlan.sound {β : Type u} [DecidableEq β] | @cons before after rest spec resolved fresh position run tail ih => obtain ⟨checkedState, accepted⟩ := position.check_success succeeded rw [anon_id] at accepted - have bodySound := run.sound wellFormed accepted + obtain ⟨_, _, bodyScope, typeScope, bodyRefs, typeRefs, typed⟩ := + run.sound wellFormed accepted have formed : (before.insert spec.ref spec.entry).WF := - insert_definition_wf wellFormed bodySound.2.2.1 bodySound.2.2.2.1 - bodySound.2.2.2.2.1 bodySound.2.2.2.2.2.1 + insert_definition_wf wellFormed bodyScope typeScope bodyRefs typeRefs obtain ⟨finalFormed, preserve⟩ := ih formed refine ⟨finalFormed, ?_⟩ intro V _ constants realizes obtain ⟨next, nextModel, agrees⟩ := extend_atomic_definition wellFormed fresh - bodySound.2.2.1 bodySound.2.2.2.2.1 bodySound.2.2.2.2.2.1 - bodySound.2.2.2.2.2.2 constants realizes + bodyScope bodyRefs typeRefs typed constants realizes obtain ⟨final, finalModel, finalAgrees⟩ := preserve V next nextModel refine ⟨final, finalModel, ?_⟩ intro ref entry present levels @@ -273,15 +262,15 @@ theorem AtomicDefinitionPlan.represents {β : Type u} [DecidableEq β] | @cons before after rest spec resolved fresh position run tail ih => obtain ⟨checkedState, accepted⟩ := position.check_success succeeded rw [anon_id] at accepted - have bodySound := AtomicDefinitionRun.sound.{u,0} run wellFormed accepted + obtain ⟨valueReads, typeReads, bodyScope, typeScope, bodyRefs, typeRefs, _⟩ := + AtomicDefinitionRun.sound.{u,0} run wellFormed accepted have formed : (before.insert spec.ref spec.entry).WF := - insert_definition_wf wellFormed bodySound.2.2.1 bodySound.2.2.2.1 - bodySound.2.2.2.2.1 bodySound.2.2.2.2.2.1 + insert_definition_wf wellFormed bodyScope typeScope bodyRefs typeRefs intro candidate present rcases List.mem_cons.mp present with same | later · subst candidate exact ⟨resolved, tail.extends _ _ (Model.Environment.insert_same ..), - bodySound.1, bodySound.2.1⟩ + valueReads, typeReads⟩ · exact ih formed candidate later private theorem AtomicDefinitionPlan.locations {β : Type u} [DecidableEq β] @@ -362,9 +351,8 @@ private theorem AtomicEnvironmentFragment.serial_success {β : Type u} [Decidabl cases accepted exact succeeded -/-- A successful `checkEnvAnon` run in the supported fragment extends every -model of its axiom set while preserving all axiom interpretations. This is a -relative model theorem, not a claim that arbitrary axioms are consistent. -/ +/-- A successful `checkEnvAnon` run in the fragment extends every model of +its axiom set while preserving all axiom interpretations. -/ theorem checkEnvAnon_atomic_preserves_model {β : Type u} [DecidableEq β] {env : Ixon.Env} {cfg : CheckCfg} {resolve : Address → Option (ConstRef β)} (fragment : AtomicEnvironmentFragment env cfg resolve) @@ -416,18 +404,16 @@ theorem checkEnvAnon_atomic_represents_source {β : Type u} [DecidableEq β] observation.reads, rfl, rfl⟩ simpa only [anon_id] using Nonempty.intro observation.path · cases AnonWorkItem.standalone.inj same - have represents := represented spec listed + obtain ⟨resolved, installed, valueReads, typeReads⟩ := represented spec listed obtain ⟨position, path⟩ := fragment.plan.locations spec listed obtain ⟨after, run⟩ := position.check_success serial - refine ⟨spec.ref, spec.entry, represents.1, represents.2.1, spec.input.constant, - ⟨(position.state env cfg).checker, after, run, ?_⟩, represents.2.2.2, - rfl, spec.body, rfl, represents.2.2.1⟩ + refine ⟨spec.ref, spec.entry, resolved, installed, spec.input.constant, + ⟨(position.state env cfg).checker, after, run, ?_⟩, typeReads, + rfl, spec.body, rfl, valueReads⟩ simpa only [anon_id] using path -/-- No declaration in the resulting environment can inhabit a type whose -axiom-model interpretation is empty. In particular this applies to `False`. -The empty interpretation is preserved, rather than assumed for the completed -environment. -/ +/-- No declaration can inhabit an axiom type interpreted as empty, such as +`False`: model extension preserves the initial empty interpretation. -/ theorem checkEnvAnon_atomic_no_false {β : Type u} [DecidableEq β] {env : Ixon.Env} {cfg : CheckCfg} {resolve : Address → Option (ConstRef β)} (fragment : AtomicEnvironmentFragment env cfg resolve) diff --git a/Ix/Kernel/Verify/Consistency/Production.lean b/Ix/Kernel/Verify/Consistency/Production.lean index 320b46722..b48ea8f97 100644 --- a/Ix/Kernel/Verify/Consistency/Production.lean +++ b/Ix/Kernel/Verify/Consistency/Production.lean @@ -9,15 +9,13 @@ import Ix.Kernel.Verify.Consistency.Atomic /-! # Standalone production declaration checks -These theorems invert the real public checker, including its error isolation, +These theorems invert the public checker, including its error isolation, initial lazy lookup, block routing, per-constant reset, validation, type inference, theorem guard, value inference, and conversion. The supported conversion path is the initial address-equality branch. Finite address faithfulness connects that comparison to the exact model syntax. -The resource records contain operational equations and structural interface -agreement. They do not contain a typing proof, a method-soundness callback, -or an assumption that an accepted declaration already has a model. +Operational equations and interface agreement suffice to derive body typing. -/ namespace Ix.Kernel.Consistency @@ -26,17 +24,19 @@ open Theory Theory.Model universe u v -private theorem runTcBind {α β : Type} (x : TcM .anon α) (k : α → TcM .anon β) - (state : TcState .anon) : - EStateM.bind x k state = match x state with - | .ok value after => k value after - | .error err after => .error err after := by - unfold EStateM.bind - cases x state <;> rfl - -/-- The concrete path of a standalone public check. This ties the member -declaration to both production lookup and the actual reset, without assuming -that block coordination or lazy ingress preserves an arbitrary predicate. -/ +private theorem bind_success {α β : Type} {x : TcM .anon α} {k : α → TcM .anon β} + {before after : TcState .anon} {value : β} + (accepted : EStateM.bind x k before = .ok value after) : + ∃ intermediate state, x before = .ok intermediate state ∧ + k intermediate state = .ok value after := by + rw [EStateM.bind] at accepted + cases run : x before with + | error err state => rw [run] at accepted; contradiction + | ok intermediate state => + rw [run] at accepted + exact ⟨intermediate, state, rfl, accepted⟩ + +/-- The lookup, routing, and reset states reached by a standalone public check. -/ structure StandalonePrefix (id : KId .anon) (before : TcState .anon) (concrete : KConst .anon) where first : KConst .anon @@ -50,9 +50,7 @@ structure StandalonePrefix (id : KId .anon) (before : TcState .anon) resetRun : TcM.reset routed = .ok () reset memberGet : TcM.getConst id reset = .ok concrete ready -/-- Success at the public boundary entails success of the exact member -identified by the standalone path. In particular, an error cannot be -turned into acceptance by the public cache rollback wrapper. -/ +/-- Public success entails member success through the error-isolation wrapper. -/ theorem StandalonePrefix.member_success {id : KId .anon} {before after : TcState .anon} {concrete : KConst .anon} (path : StandalonePrefix id before concrete) @@ -70,19 +68,19 @@ theorem StandalonePrefix.member_success {id : KId .anon} unfold RecM.checkConst at run simp only [ReaderT.run_bind, ReaderT.run_monadLift] at run change EStateM.bind (TcM.getConst id) _ before = _ at run - rw [runTcBind, path.firstGet] at run + rw [EStateM.bind, path.firstGet] at run change EStateM.bind ((RecM.coordinatedBlockFor path.first).run (methodsN before.recFuel.toNat)) _ path.loaded = _ at run - rw [runTcBind, path.route] at run + rw [EStateM.bind, path.route] at run change (RecM.checkConstMemberFresh id).run (methodsN before.recFuel.toNat) path.routed = .ok () after at run unfold RecM.checkConstMemberFresh at run simp only [ReaderT.run_bind, ReaderT.run_monadLift] at run change EStateM.bind TcM.reset _ path.routed = _ at run - rw [runTcBind, path.resetRun] at run + rw [EStateM.bind, path.resetRun] at run change EStateM.bind (TcM.getConst id) _ path.reset = _ at run - rw [runTcBind, path.memberGet] at run + rw [EStateM.bind, path.memberGet] at run exact run /-- Monomorphic definition data. Its complete concrete declaration is the @@ -99,9 +97,8 @@ structure DefinitionInput where def DefinitionInput.constant (input : DefinitionInput) : KConst .anon := .defn () () input.kind input.safety input.hints 0 input.type input.value () input.block -/-- Exact successful observations through a definition's value-conversion -call. Later safety checks may still reject; the extraction theorem requires -the entire member check to have succeeded. -/ +/-- The execution prefix through value conversion. A successful member check +also passes the subsequent safety checks. -/ structure DefinitionBodyTrace (input : DefinitionInput) (methods : Methods .anon) (before : TcState .anon) where validated : TcState .anon @@ -121,8 +118,7 @@ structure DefinitionBodyTrace (input : DefinitionInput) (methods : Methods .anon conversionRun : (RecM.isDefEq inferredValue input.type).run methods conversionStart = .ok true conversionEnd -/-- Invert the production declaration branch rather than assuming that its -acceptance establishes either type or value typing. -/ +/-- Extract the execution trace from a successful production member check. -/ theorem definition_body_trace {input : DefinitionInput} {methods : Methods .anon} {before after : TcState .anon} (accepted : (RecM.checkConstMember input.id input.constant).run methods before = @@ -130,61 +126,33 @@ theorem definition_body_trace {input : DefinitionInput} {methods : Methods .anon unfold RecM.checkConstMember at accepted simp only [DefinitionInput.constant, Mode.F.hasDups, Bool.false_eq_true, if_false, ReaderT.run_bind] at accepted - cases validation : (RecM.validateConstWellScoped input.constant).run methods before with - | error err failed => - change EStateM.bind ((RecM.validateConstWellScoped input.constant).run methods) - _ before = _ at accepted - rw [runTcBind, validation] at accepted - contradiction - | ok result validated => - cases result - change EStateM.bind ((RecM.validateConstWellScoped input.constant).run methods) - _ before = _ at accepted - rw [runTcBind, validation] at accepted - change EStateM.bind ((RecM.infer input.type).run methods) _ validated = _ at accepted - cases typeRun : (RecM.infer input.type).run methods validated with - | error err failed => rw [runTcBind, typeRun] at accepted; contradiction - | ok inferredType typeState => - rw [runTcBind, typeRun] at accepted - change EStateM.bind ((RecM.ensureSortDirect inferredType).run methods) - _ typeState = _ at accepted - cases sortRun : (RecM.ensureSortDirect inferredType).run methods typeState with - | error err failed => rw [runTcBind, sortRun] at accepted; contradiction - | ok level valueStart => - rw [runTcBind, sortRun] at accepted - simp only at accepted - by_cases guard : input.kind == .thm && !univEq level .mkZero - · simp only [guard, if_true] at accepted - contradiction - · simp only [guard, Bool.false_eq_true, if_false, ReaderT.run_bind] at accepted - cases valueRun : (RecM.infer input.value).run methods valueStart with - | error err failed => - change EStateM.bind ((RecM.infer input.value).run methods) - _ valueStart = _ at accepted - rw [runTcBind, valueRun] at accepted - contradiction - | ok inferredValue conversionStart => - change EStateM.bind ((RecM.infer input.value).run methods) - _ valueStart = _ at accepted - rw [runTcBind, valueRun] at accepted - change EStateM.bind ((RecM.isDefEq inferredValue input.type).run methods) - _ conversionStart = _ at accepted - cases conversionRun : (RecM.isDefEq inferredValue input.type).run methods - conversionStart with - | error err failed => rw [runTcBind, conversionRun] at accepted; contradiction - | ok answer conversionEnd => - rw [runTcBind, conversionRun] at accepted - cases answer with - | false => - simp only [Bool.not_false, if_true] at accepted - contradiction - | true => - exact ⟨{ - validated, inferredType, typeState, level, valueStart, - inferredValue, conversionStart, conversionEnd, - validationRun := validation, typeRun, sortRun, - theoremGuard := Bool.eq_false_iff.mpr guard, - valueRun, conversionRun }⟩ + change EStateM.bind ((RecM.validateConstWellScoped input.constant).run methods) + _ before = _ at accepted + obtain ⟨⟨⟩, validated, validationRun, accepted⟩ := bind_success accepted + change EStateM.bind ((RecM.infer input.type).run methods) _ validated = _ at accepted + obtain ⟨inferredType, typeState, typeRun, accepted⟩ := bind_success accepted + change EStateM.bind ((RecM.ensureSortDirect inferredType).run methods) + _ typeState = _ at accepted + obtain ⟨level, valueStart, sortRun, accepted⟩ := bind_success accepted + by_cases guard : input.kind == .thm && !univEq level .mkZero + · simp only [guard, if_true] at accepted + contradiction + · simp only [guard, Bool.false_eq_true, if_false, ReaderT.run_bind] at accepted + change EStateM.bind ((RecM.infer input.value).run methods) _ valueStart = _ at accepted + obtain ⟨inferredValue, conversionStart, valueRun, accepted⟩ := bind_success accepted + change EStateM.bind ((RecM.isDefEq inferredValue input.type).run methods) + _ conversionStart = _ at accepted + obtain ⟨answer, conversionEnd, conversionRun, accepted⟩ := bind_success accepted + cases answer with + | false => + simp only [Bool.not_false, if_true] at accepted + contradiction + | true => + exact ⟨{ + validated, inferredType, typeState, level, valueStart, + inferredValue, conversionStart, conversionEnd, + validationRun, typeRun, sortRun, + theoremGuard := Bool.eq_false_iff.mpr guard, valueRun, conversionRun }⟩ /-- Operational support for the selected production definition fragment. Resources are required only at the states exposed by successful body traces. @@ -215,16 +183,15 @@ theorem AtomicDefinitionRun.sound {β : Type u} body.ReferencesIn entries ∧ type.ReferencesIn entries ∧ TypingClaim.{u,v} entries [] body type := by obtain ⟨trace⟩ := definition_body_trace (fragment.path.member_success accepted) - have result := (fragment.inference trace).sound trace.valueRun + obtain ⟨valueReads, typeReads, typed⟩ := (fragment.inference trace).sound trace.valueRun have same := beq_readExpr? (resolve := resolve) (fragment.faithful trace) (fragment.hashPath trace) - have scope := (fragment.inference trace).support.scopeAndReferences wellFormed - exact ⟨result.1, same.symm.trans result.2.1, scope.1, scope.2.1, - scope.2.2.1, scope.2.2.2, result.2.2⟩ + obtain ⟨bodyScope, typeScope, bodyRefs, typeRefs⟩ := + (fragment.inference trace).support.scopeAndReferences wellFormed + exact ⟨valueReads, same.symm.trans typeReads, bodyScope, typeScope, bodyRefs, typeRefs, typed⟩ -/-- A fresh definition cannot use itself as the atomic value that justifies -its own type. This exclusion follows from the preceding interface, without -any assumption about the consistency of the axioms. -/ +/-- A fresh definition cannot justify its type through a self-reference: +its atomic value must reference the preceding interface. -/ theorem AtomicDefinitionRun.no_self_alias {β : Type u} {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} {input : DefinitionInput} {before after : TcState .anon} {body type : AExpr β} @@ -233,12 +200,11 @@ theorem AtomicDefinitionRun.no_self_alias {β : Type u} (resolved : resolve input.id.addr = some ref) (fresh : entries ref = none) {info : ExprInfo .anon} (self : input.value = .const input.id #[] info) (accepted : TcM.checkConst input.id before = .ok () after) : False := by - have result := AtomicDefinitionRun.sound.{u,0} fragment wellFormed accepted - have reads := result.1 + obtain ⟨reads, _, _, _, references, _, _⟩ := + AtomicDefinitionRun.sound.{u,0} fragment wellFormed accepted rw [self] at reads simp [readExpr?, resolved] at reads have bodyEq := AExpr.eq_const_of_erase_eq reads.symm - have references := result.2.2.2.2.1 rw [bodyEq] at references have present := references ref (by simp [AExpr.references]) simp only [fresh, Option.isSome_none, Bool.false_eq_true] at present diff --git a/Models/SetTheory/README.md b/Models/SetTheory/README.md index e74498555..74f64fe7e 100644 --- a/Models/SetTheory/README.md +++ b/Models/SetTheory/README.md @@ -17,16 +17,16 @@ The construction includes the interface's Lean-level replacement scheme: Mathlib's `Classical.allZFSetDefinable` supplies images of arbitrary functions `ZFSet → ZFSet`. The audit traverses the theorem's checked types, bodies, and constructor fields and permits exactly `propext`, `Classical.choice`, and -`Quot.sound`. Inaccessible cardinals remain an explicit -hypothesis, rather than an added Lean axiom. +`Quot.sound`. Inaccessible cardinals remain an explicit theorem hypothesis. The package imports the actual Ix interface by a path dependency on the repository root. Mathlib is confined to this package; ordinary Ix and `Ix.Theory` builds do not depend on it. This construction supplies the set-theoretic assumption used by the [consistency model](../../docs/theory.md). -The connection from the production checker to the certified interface is a -separate proof obligation. A converse from the interface to inaccessible -cardinals is not proved here. +The [production fragment](../../docs/kernel-verification.md#production-environment-fragment) +uses this assumption to preserve models of source axioms. Full checker +refinement and a converse from the interface to inaccessible cardinals are +separate proof obligations. ## Build diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 7b9376856..03862215f 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -6,9 +6,8 @@ public import Tests.Ix.Kernel.IxonFixtures /-! Production regressions for the atomic consistency fragment. These execute -the real lazy serial driver on content-addressed Ixon declarations. The -formal results and their resource premises are checked separately by -`IxKernelConsistency`; these tests do not substitute for those proofs. +the lazy serial driver on content-addressed Ixon declarations. The fragment's +theorems and resource premises are checked by `IxKernelConsistency`. -/ namespace Tests.Kernel.Consistency diff --git a/docs/certified-checking.md b/docs/certified-checking.md index c0f8b6057..b565d7b30 100644 --- a/docs/certified-checking.md +++ b/docs/certified-checking.md @@ -129,12 +129,10 @@ inventory records five BLAKE3 foreign operations and 130 recursion workers with safe source definitions; it permits no partial opaque worker source or executable replacement. -This stronger traversal exposed a native-evaluation axiom that the historical -imported axiom summaries missed. It came from the BLAKE3 helper's 32-byte -output bound. `Address.blake3` now supplies a kernel-checked proof of that -bound. The wrapper is definitionally equal to the former hash operation, -and generated source/envelope corpora are unchanged. -The affected kernel and source-compiler audits also remove this dependency. +`Address.blake3` supplies a kernel-checked proof of its 32-byte output bound, +replacing a native-evaluation axiom missed by the historical imported summaries. +The wrapper is definitionally equal to the former hash operation. The frozen +corpora check that source and envelope bytes are unchanged. | Actual command corpus | Fixtures | Accepted | Rejected | | --- | ---: | ---: | ---: | @@ -153,8 +151,8 @@ non-VM field; only `pilotDeclined` and `pilotDeclines` are projected away from the three historical reports that mixed host and VM checks. The VM pilot, packet encoder and VM execution suite are archived for a later change. CLI JSON requests and aggregate records are compared as parsed values because -the maintained Lean driver formats JSON differently. The archive, source mappings, licenses and -historical reproduction limits are documented in +the maintained Lean driver formats JSON differently. The archive, source +mappings, licenses and historical reproduction limits are documented in [`Tests/Fixtures/Certified`](../Tests/Fixtures/Certified/README.md). The archive recovers the selected adapter sources and fixtures; it does not include the complete historical Ix base checkout. diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 3f8eabaf7..1cd6c31b5 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -6,26 +6,16 @@ proofs. Their named specification and reference implementation lemmas are local under `Ix.Theory.Named`. Building or checking them requires no external formalization repository. -The named development retains the 104 source modules needed by the existing -proof dependency graph, including the inductive fixtures consumed by Ix. -Standalone applications, benchmarks, and unrelated tests are excluded. Its -original source hashes and attribution are recorded in `Ix/Theory/Named/NOTICE` -and `Tests/Theory/NamedManifest.lean`; the Apache license is preserved alongside -the sources. The added axiom-audit helper is authored in Ix. +The certified receipt interface and a fragment of production `checkEnvAnon` +have relative consistency theorems. Full checker consistency remains open. ## Connection to the consistency model -The name-indexed specification and the set model use the same -`Ix.Theory.VLevel`. The set model and its foundational audit remain independent -of the named development. Mathlib is confined to the separate -[set-theory model package](../Models/SetTheory/README.md). - -That package's `IxSetTheoryModel.setTheoryOfCarneiro` constructs the exact -`Ix.Theory.Model.SetTheory` interface on Mathlib's `ZFSet`. It takes an explicit -`OmegaInaccessibles` hypothesis: a strictly increasing countable sequence of -strongly inaccessible cardinals. The universe chain is `V_ (κ n).ord`. -`carneiro_implies_ix` proves model existence under this hypothesis, with a full -dependency audit restricted to Lean's three standard axioms. +The named specification and the set model share `Ix.Theory.VLevel`. The +[model foundation](theory.md) and its audit are independent of the named +development. The separate [Mathlib package](../Models/SetTheory/README.md) +constructs `Ix.Theory.Model.SetTheory` on `ZFSet` from a countable strictly +increasing sequence of strongly inaccessible cardinals. `Ix.Kernel.Verify.Consistency` proves the following direct connections: @@ -47,25 +37,22 @@ dependency audit restricted to Lean's three standard axioms. environment run to model extension. `checkEnvAnon_atomic_no_false` excludes a declaration at an axiom type interpreted as empty, including False. -`ModelTyping.no_false` assumes semantic typing. The production fragment below -constructs that typing from its supported inference and conversion paths. -A complete checker consistency theorem -still requires the remaining inference/conversion cases, cache invariants, -address-to-store resolution, and declaration admission to establish that -postcondition for `checkEnvAnon`. The existing named-calculus proofs are retained -to support this refinement, rather than being treated as a set-model proof. +`ModelTyping.no_false` assumes semantic typing; the production fragment below +derives it for its supported paths. Full checker refinement still requires the +remaining inference and conversion cases, cache invariants, address-to-store +resolution, and declaration admission. The named-calculus proofs provide +support for these obligations. ## Production environment fragment The axiom policy is relative: **every model of the source axioms extends to a model of the checked environment, preserving the axiom interpretations**. -The axiom interface starts empty and contains exactly the listed source -axioms. Its types must be closed and refer only to that interface. A concrete -`Realizes` witness supplies their interpretation; checking an axiom's type -does not manufacture an inhabitant. This model-existence hypothesis is not -identified with syntactic consistency of an arbitrary axiom theory. +The initial interface contains exactly the source axioms, with closed types +that refer only to that interface. A `Realizes` witness supplies a model of +these axioms. The hypothesis is model existence; a theorem connecting +arbitrary syntactic consistency to model existence is outside this result. -The initial fragment covers monomorphic standalone definitions, theorems, +The fragment covers monomorphic standalone definitions, theorems, and opaque definitions whose values are either closed universe terms or references to preceding interface entries. Examples include: @@ -79,9 +66,9 @@ def typeAlias : Type := Prop `AtomicEnvironmentFragment` records the precise execution boundary: -- Every source key occurs in the exact `buildAnonWork` result, and every work - item is represented by an axiom or a definition. Standalone lookup, routing, - and reset witnesses identify the actual checked `KConst`. +- Every source key occurs in the `buildAnonWork` result, and every work item + represents an axiom or a definition. Lookup, routing, and reset witnesses + identify the checked `KConst`. - Value inference misses both cache partitions. Constant lookup agrees with an already admitted monomorphic type; empty level substitution preserves that type. Sort inference retains the finite interning coherence and @@ -89,44 +76,38 @@ def typeAlias : Type := Prop - Conversion takes the initial hash-equality path, with faithfulness of the compared expressions. General reduction and conversion caches are outside this fragment. -- Definitions are added in a dependency order with fresh references. Their - runtime observations still use the states reached in the original serial - work order, including cache clearing. `AtomicDefinitionRun.no_self_alias` +- Definitions are added in dependency order with fresh references. Their + observations use the states reached in the original serial work order, + including cache clearing. `AtomicDefinitionRun.no_self_alias` proves that a fresh definition cannot justify its own type by referring to itself. - `checkEnvAnon` returns `.ok results` **and every result row has no error**. The outer `.ok` alone does not mean that the declarations passed. -These are operational and representation witnesses, not a checker-soundness -callback or a supplied typing proof. A caller must establish them for a run; -this change does not automatically derive them from arbitrary Ixon syntax. -The proof follows the public checker through validation, type inference, -the theorem guard, value inference, and conversion. Successful value -inference constructs the body typing used to extend the preceding model. -Lambdas, applications, polymorphic instantiation, inductives, coordinated -blocks, and other conversion paths remain outside this slice. - -`checkEnvAnon_atomic_represents_source` assigns every source address an -interface whose type reads the exact declaration reached by production -lookup. Definition interfaces also retain their checked bodies. This is a -statement about the production ingress/lookup result; the independent +Callers must establish these operational and representation witnesses for +the run. They supply no typing or checker-soundness premise. The proof +extracts the validation, type-inference, theorem-guard, value-inference, and +conversion steps from public success, then derives body typing to extend +the preceding model. Automatic witness construction, lambdas, applications, +polymorphic instantiation, inductives, coordinated blocks, and other conversion +paths remain outside the fragment. + +`checkEnvAnon_atomic_represents_source` ties every source address to an +interface with the type and body reached by production lookup. The independent serialized-Ixon reader refinement remains a separate boundary. -The no-False corollary takes a model of the initial axiom interface in which -the designated false type is empty. Model extension preserves that value, -so no resulting declaration can inhabit it. It does not blacklist axiom -names or merely exclude declarations literally written with type `False`. +The no-False corollary assumes the designated false type is empty in the +initial axiom model. Extension preserves that value, so no resulting +declaration can inhabit it. No axiom-name restriction is needed. ## Trust checks The audits traverse checked declaration types and bodies, including inductive constructors. They compare exact axiom sets and record direct origins of -`sorryAx`; they do not rely on cached imported axiom summaries. During the -migration, full traversal of the original sources exposed two wrapper reports -that listed 3 axioms but depended on 30. Their boundaries now include the -existing implementation assumptions and unfinished metatheory. All 441 retained -named-specification assertions use the original full dependency graphs as their -migration baseline. +`sorryAx`. Full traversal includes dependencies missed by cached imported +axiom summaries, including implementation assumptions and unfinished +metatheory. All 441 retained named-specification assertions use their original +full dependency graphs as the migration baseline. The same traversal covers 2,034 kernel manifest roots. Thirteen entries omitted logical or native dependencies through constructor fields; their corrected @@ -138,12 +119,11 @@ reachable declarations, axioms, and proof-hole origins are computed separately. axioms. Completed roots cannot depend on that namespace. Named-specification proof holes and implementation bridge axioms are tracked separately from Lean's logical axioms and generated native proofs. No direct consistency root -permits a proof hole or a metatheory/implementation bridge axiom. Both the -context hash and content-address hash now use kernel-checked proofs of their -32-byte output bounds on both platform sizes. Their former generated native -assumptions have been removed from the affected exact audits. +permits a proof hole or a metatheory/implementation bridge axiom. The context +hash and content-address hash use kernel-checked proofs of their 32-byte output +bounds on both platform sizes. -Run the complete local kernel-certification gate: +Run the complete local certification gate: ```sh lake run check-kernel --with-model @@ -170,7 +150,7 @@ reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model extension lemma and `ModelTyping.no_false` use only `propext`, `Classical.choice`, and `Quot.sound`, with set theory as a hypothesis. -The new production roots additionally forbid the earlier abstract +The production roots additionally forbid the abstract `CheckSuccessSound`/`SupportedCheckFragment` interfaces and the independent certificate validator in their dependency closures. @@ -189,10 +169,8 @@ permits only the three standard Lean axioms in these roots and inventories the separate BLAKE3 and native execution boundaries. See [the command interface, theorem contracts and evidence](certified-checking.md). -These host results do not cover the full production inference dispatcher or -prove that an Aiur public verifier executes the host validator. The VM pilot -remains in the frozen archive for a later change; its build target and execution -tests are outside the host gate. +Aiur execution of the host validator remains a separate proof obligation. +The VM pilot is preserved in the frozen archive and excluded from the host gate. ## Review entry points @@ -205,17 +183,16 @@ tests are outside the host gate. | Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | | Concrete set-theory instance | [Separate model package](../Models/SetTheory/README.md) | -## Change scope +## Provenance and scope -The kernel, theory and certified host scaffolding is extracted from -`jcb/monorepo` at `7b06b754` in a single change. Existing callers move from -`Ix.Tc` to `Ix.Kernel`. Existing `Ix.Compile.Verify` proofs receive the -necessary named-specification imports and exact hash-axiom audit updates. -The new compiler development, circuit changes and certificate VM pilot -are deferred. The external `lean4lean` dependency and its benchmark/test -targets are removed; all verification dependencies are local to Ix. +The kernel, theory, and certified host scaffolding comes from `jcb/monorepo` +at `7b06b754`. The checker namespace is `Ix.Kernel` (formerly `Ix.Tc`), and +verification dependencies are local to Ix. The external `lean4lean` dependency +and its benchmark/test targets have been removed. The new compiler development, +circuit changes, and certificate VM pilot are deferred. -The subsequent production-fragment change adds direct inference, declaration, -and serial-environment proofs on top of that extraction. It changes no -production checker behavior and adds regression cases to the existing kernel -unit gate. +The named development retains 104 source modules, including the inductive +fixtures used by the existing proofs. Original hashes and attribution are +recorded in `Ix/Theory/Named/NOTICE` and `Tests/Theory/NamedManifest.lean`; the +Apache license is preserved alongside the sources. The axiom-audit helper and +direct production-fragment proofs are authored in Ix. diff --git a/docs/theory.md b/docs/theory.md index 6aa76b3a2..8c348f3aa 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -6,8 +6,8 @@ run the selected regression tests, provenance check, and exact foundation audit with `lake run check-theory`. `Ix.Theory.Certified.accepted_has_model` constructs a model for accepted -declarations. `accepted_proof_sound` and `no_proof_of_False` give the corresponding semantic -and consistency results. These theorems explicitly assume a type `V` equipped +declarations. `accepted_proof_sound` and `no_proof_of_False` give the corresponding +semantic and consistency results. These theorems assume a type `V` equipped with `Ix.Theory.Model.SetTheory V`: set operations and laws together with a countable tower of Grothendieck universes. The separate [`Models/SetTheory`](../Models/SetTheory/README.md) package constructs this @@ -17,19 +17,12 @@ that large-cardinal hypothesis explicitly and passes an axiom guard for `propext`, `Classical.choice`, and `Quot.sound`. User-supplied logical axioms and open frontiers retain their stated model hypotheses. -These are relative consistency results for the certified interface. The -[kernel verification](kernel-verification.md) now shares its universe syntax -and proves direct model results for universe comparison, structural expression -reading, interning, and the production sort-inference branch. The certified -host adapters connect authenticated serialized Ixon to model admission. -A production fragment for monomorphic aliases and closed universe terms now -proves that `checkEnvAnon` preserves a supplied model of its source axiom set, -under explicit operational and representation witnesses. Its no-False -corollary preserves the axiom model's empty interpretation of the false type; -it does not assume that arbitrary source axioms are consistent. See the -[fragment contract](kernel-verification.md#production-environment-fragment). -A complete bridge from arbitrary `Ix.Kernel.checkEnvAnon` success or -compiler/backend execution remains unfinished. +The [certified host adapters](certified-checking.md) connect authenticated +serialized Ixon to model admission. Separately, a production `checkEnvAnon` +[fragment](kernel-verification.md#production-environment-fragment) for +monomorphic aliases and closed universe terms extends every model of its +source axioms under explicit execution witnesses. Full checker consistency +and compiler/backend refinement remain open. `Ix.Theory.Named` retains the local name-indexed specification and proof support needed by the existing kernel and compiler verification. It shares From 4abe7af422dc0a8fd57c248824c7ef665cdf19eb Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 08:04:26 -0400 Subject: [PATCH 04/30] Make verification documentation self-contained --- Ix/Compile/Verify/Catalog.lean | 4 +- Ix/Compile/Verify/Codec.lean | 8 +- Ix/Kernel/Driver.lean | 4 +- Ix/Kernel/Inductive.lean | 18 +-- Ix/Kernel/Infer.lean | 2 +- Ix/Kernel/Level.lean | 2 +- Ix/Kernel/Verify/Audit/Completed.lean | 116 ++++++++-------- Ix/Kernel/Verify/Audit/Statements.lean | 9 +- Ix/Kernel/Verify/Cache.lean | 22 +-- Ix/Kernel/Verify/Check/Acceptance.lean | 8 +- Ix/Kernel/Verify/Check/BinderRoundTrip.lean | 2 +- Ix/Kernel/Verify/Check/BlockAcceptance.lean | 5 +- Ix/Kernel/Verify/Check/BlockCache.lean | 2 +- Ix/Kernel/Verify/Check/BlockDefinition.lean | 18 +-- Ix/Kernel/Verify/Check/BlockIdentity.lean | 6 +- Ix/Kernel/Verify/Check/BlockNatFixture.lean | 4 +- Ix/Kernel/Verify/Check/BlockOracle.lean | 19 ++- Ix/Kernel/Verify/Check/BlockTransaction.lean | 14 +- Ix/Kernel/Verify/Check/BoundedPipelines.lean | 10 +- .../Verify/Check/CheckConstTransaction.lean | 11 +- Ix/Kernel/Verify/Check/CheckerEvidence.lean | 2 +- .../Verify/Check/DeclarationValidation.lean | 2 +- Ix/Kernel/Verify/Check/FullInference.lean | 6 +- .../Check/FullInferenceApplications.lean | 14 +- .../Verify/Check/FullInferenceBinders.lean | 4 +- .../Verify/Check/FullInferenceCache.lean | 8 +- .../Verify/Check/FullInferenceDispatcher.lean | 8 +- Ix/Kernel/Verify/Check/FullInferenceKnot.lean | 10 +- .../Verify/Check/FullInferenceLeaves.lean | 4 +- .../Check/FullInferenceProjections.lean | 10 +- Ix/Kernel/Verify/Check/InferencePolicy.lean | 8 +- Ix/Kernel/Verify/Check/MemberEvidence.lean | 2 +- Ix/Kernel/Verify/Check/PositiveFuelSort.lean | 14 +- .../Verify/Check/PreTranslationScopes.lean | 4 +- Ix/Kernel/Verify/Check/PublicBlocks.lean | 6 +- Ix/Kernel/Verify/Check/PublicStandalone.lean | 10 +- Ix/Kernel/Verify/Check/QuotientBoundary.lean | 4 +- Ix/Kernel/Verify/Check/SafetyFrame.lean | 2 +- Ix/Kernel/Verify/Check/Scoped.lean | 2 +- Ix/Kernel/Verify/Check/ScopedActiveBlock.lean | 4 +- .../Verify/Check/ScopedBoundedPipelines.lean | 6 +- .../Check/ScopedPositiveFuelCertificate.lean | 2 +- .../Verify/Check/SingletonInductive.lean | 14 +- Ix/Kernel/Verify/Check/StandaloneDriver.lean | 4 +- Ix/Kernel/Verify/Check/ValidatorFrame.lean | 2 +- Ix/Kernel/Verify/Ctx.lean | 4 +- Ix/Kernel/Verify/Decl.lean | 15 +-- Ix/Kernel/Verify/DefEq.lean | 16 +-- Ix/Kernel/Verify/DefEq/BoolTrue.lean | 2 +- Ix/Kernel/Verify/DefEq/CheapReduction.lean | 2 +- Ix/Kernel/Verify/DefEq/EqualRankCache.lean | 2 +- Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean | 2 +- Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean | 4 +- .../DefEq/FinalWhnf/StringExpansion.lean | 2 +- Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean | 2 +- .../Verify/DefEq/LazyDeltaIteration.lean | 4 +- .../Verify/DefEq/PropositionClassifier.lean | 8 +- Ix/Kernel/Verify/DefEq/StringLiteral.lean | 6 +- Ix/Kernel/Verify/DefEq/Structural.lean | 2 +- .../Verify/Driver/BooleanAcceptance.lean | 16 +-- Ix/Kernel/Verify/Driver/Dependencies.lean | 2 +- Ix/Kernel/Verify/Driver/Enumeration.lean | 2 +- Ix/Kernel/Verify/Driver/Fixtures.lean | 2 +- Ix/Kernel/Verify/Driver/Model.lean | 4 +- Ix/Kernel/Verify/Driver/Serial.lean | 2 +- .../Verify/Driver/SupportedAcceptance.lean | 62 ++++----- .../Driver/SupportedAcceptanceFixtures.lean | 20 +-- Ix/Kernel/Verify/Env.lean | 10 +- Ix/Kernel/Verify/Execution.lean | 2 +- Ix/Kernel/Verify/Inductive.lean | 14 +- .../Inductive/AliasFormerAdmission.lean | 2 +- .../Inductive/AliasFormerCertificate.lean | 6 +- .../Verify/Inductive/AliasRecAdmission.lean | 2 +- .../Inductive/AnnotatedPiAdmission.lean | 2 +- .../Inductive/AnnotatedPiCertificate.lean | 9 +- .../Verify/Inductive/BlockCertificate.lean | 4 +- .../ConstructorPositivityTraversal.lean | 2 +- .../ConstructorValidationTraversal.lean | 2 +- .../Inductive/EliminationBreadthFixture.lean | 2 +- .../Verify/Inductive/EnumerationFixture.lean | 6 +- .../Verify/Inductive/ExactLeanSyntax.lean | 4 +- .../GeneratedRecursorAcceptanceClosure.lean | 4 +- .../Inductive/GeneratedRecursorAdmission.lean | 4 +- .../GeneratedRecursorCheckerFixture.lean | 8 +- .../GeneratedRecursorInitialInvariant.lean | 4 +- .../GeneratedRecursorMemberCheck.lean | 2 +- .../GeneratedRecursorMemberFixture.lean | 4 +- .../Inductive/GeneratedRecursorSelection.lean | 2 +- .../Inductive/GeneratedRecursorSemantics.lean | 2 +- .../Inductive/IndexedCandidateSyntax.lean | 2 +- .../IndexedCandidateTransaction.lean | 4 +- .../Inductive/IndexedPositivityTransport.lean | 2 +- .../Inductive/IndexedProducerClosure.lean | 2 +- .../IndexedRecursiveCertificate.lean | 6 +- .../Inductive/IndexedRecursiveSoundness.lean | 2 +- Ix/Kernel/Verify/Inductive/IotaPattern.lean | 2 +- .../Inductive/MutualBlockCertificate.lean | 8 +- .../Inductive/MutualRecursorAdmission.lean | 2 +- .../Inductive/NestedRecursiveFixture.lean | 2 +- .../Verify/Inductive/OccurrenceClosure.lean | 6 +- .../Inductive/OccurrenceValidation.lean | 6 +- .../Verify/Inductive/PositivityTraversal.lean | 2 +- .../ProducedGenerationTransaction.lean | 8 +- .../Inductive/RecursivePiAdmission.lean | 2 +- .../Inductive/RecursivePiCertificate.lean | 5 +- .../Inductive/RecursivePiSoundness.lean | 2 +- .../Inductive/SingletonEnumeration.lean | 16 +-- .../Verify/Inductive/SingletonFamily.lean | 8 +- .../Verify/Inductive/SingletonOracle.lean | 2 +- .../Verify/Inductive/SingletonRecursor.lean | 8 +- .../Inductive/StructuralCacheSemantics.lean | 6 +- Ix/Kernel/Verify/Infer.lean | 8 +- Ix/Kernel/Verify/Infer/CacheSoundness.lean | 4 +- Ix/Kernel/Verify/Infer/Callbacks.lean | 2 +- Ix/Kernel/Verify/Infer/CheapBeta.lean | 2 +- Ix/Kernel/Verify/Infer/Constants.lean | 4 +- Ix/Kernel/Verify/Ingress/LiteralBlobs.lean | 4 +- Ix/Kernel/Verify/Ingress/Representation.lean | 7 +- .../Verify/Ingress/SerializedBoolean.lean | 12 +- Ix/Kernel/Verify/Knot.lean | 28 ++-- Ix/Kernel/Verify/NatFixture.lean | 51 ++++--- .../Verify/RecursiveMethods/Closure.lean | 2 +- .../RecursiveMethods/ScopedCallDomains.lean | 6 +- .../RecursiveMethods/ScopedSortInference.lean | 2 +- Ix/Kernel/Verify/Run.lean | 6 +- Ix/Kernel/Verify/State.lean | 14 +- Ix/Kernel/Verify/Statements.lean | 22 +-- Ix/Kernel/Verify/Suffix.lean | 6 +- Ix/Kernel/Verify/Support.lean | 2 +- Ix/Kernel/Verify/Totalization.lean | 2 +- Ix/Kernel/Verify/Whnf.lean | 125 +++++++++--------- Ix/Kernel/Verify/Whnf/Closure.lean | 32 +++-- .../Verify/Whnf/Delta/CacheExecution.lean | 2 +- Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean | 4 +- .../Verify/Whnf/Iota/ApplicationRequests.lean | 2 +- .../Verify/Whnf/Iota/ConstructorDispatch.lean | 2 +- Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean | 4 +- .../Verify/Whnf/Iota/OptionalReduction.lean | 2 +- Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean | 2 +- .../Verify/Whnf/Iota/StructEtaControl.lean | 2 +- .../Verify/Whnf/Iota/SynthesisRequests.lean | 2 +- .../Whnf/NoDelta/QuotientReflection.lean | 2 +- .../Whnf/Projection/StringExpansion.lean | 4 +- Ix/Kernel/Verify/Whnf/README.md | 5 +- .../Verify/Whnf/Runtime/LazyIngress.lean | 2 +- .../Verify/Whnf/StructEta/RebuildTail.lean | 2 +- .../Verify/Whnf/Structural/BasicStep.lean | 2 +- .../Whnf/Structural/ProjectionStep.lean | 2 +- Ix/Kernel/Verify/World.lean | 18 ++- Ix/Kernel/Whnf.lean | 2 +- .../Named/ConstructorValidityFixtures.lean | 2 +- .../Fixtures/ProjectionExpressibility.lean | 2 +- Ix/Theory/Named/Inductive.lean | 9 +- Ix/Theory/Named/InductiveFixtures.lean | 2 +- Ix/Theory/Named/MutualInductiveFixtures.lean | 2 +- Ix/Theory/Named/NestedInductive.lean | 26 ++-- Ix/Theory/Named/NestedInductiveFixtures.lean | 6 +- Ix/Theory/Named/Projection.lean | 9 +- Ix/Theory/Named/SingletonParity.lean | 4 +- .../Named/Typing/InductiveCertificate.lean | 2 +- Ix/Theory/Named/Typing/InductivePattern.lean | 8 +- .../Named/Typing/InductivePatternWF.lean | 6 +- .../Named/Typing/NestedInductiveLemmas.lean | 2 +- .../Environment/ConstructorValidation.lean | 8 +- .../ConstructorValidityMatrix.lean | 2 +- .../Environment/EliminationFixturesEdges.lean | 2 +- .../Environment/EliminationFixturesEq.lean | 2 +- .../Environment/EliminationFixturesEqNat.lean | 2 +- .../Environment/EliminationFixturesNat.lean | 2 +- .../Environment/EliminationFixturesOrAnd.lean | 2 +- .../Environment/EliminationFixturesSmall.lean | 2 +- .../Environment/IndexedVecSemanticReplay.lean | 4 +- .../Verify/Environment/InductiveFixtures.lean | 8 +- .../Verify/Environment/NestedReplay.lean | 2 +- .../Environment/NestedRepresentation.lean | 35 +++-- .../Environment/NestedTransformation.lean | 8 +- .../Environment/NormalizationMatrix.lean | 2 +- .../Environment/SingletonParityMatrix.lean | 4 +- .../Environment/SingletonParityReplay.lean | 6 +- Tests/Ix/Kernel/CheckEnv.lean | 2 +- Tests/Ix/Kernel/CheckTauCeti.lean | 1 - Tests/Ix/Kernel/CheckTests.lean | 2 +- ...-backedge-audit.md => kernel-recursion.md} | 59 ++++----- docs/kernel-verification.md | 36 +++-- docs/tc-context-digest-collision-boundary.md | 18 +-- docs/theory.md | 8 +- 186 files changed, 739 insertions(+), 777 deletions(-) rename docs/{tc-k0-backedge-audit.md => kernel-recursion.md} (77%) diff --git a/Ix/Compile/Verify/Catalog.lean b/Ix/Compile/Verify/Catalog.lean index 4eafad6c1..0f931e270 100644 --- a/Ix/Compile/Verify/Catalog.lean +++ b/Ix/Compile/Verify/Catalog.lean @@ -5,7 +5,7 @@ import Std.Data.HashMap.Lemmas /-! # Immutable compiler catalog and representation well-formedness -This module states the X1 representation boundary without running Ix.Kernel. It +This module states the representation boundary without running Ix.Kernel. It separates content-address integrity, finite immutable lookup support, logical environment views, wire representability, and expression-table resolution. @@ -392,7 +392,7 @@ structure Catalog.Finite (catalog : Catalog) : Prop where anonHints : FinitelySupported catalog.anonHints memberAddrs : FinitelySupported catalog.memberAddrs -/-- X1 in-memory catalog integrity. This is representation +/-- In-memory catalog integrity. This is representation well-formedness, not Ix.Theory.Named `VEnv.WF`. -/ structure Catalog.WF (catalog : Catalog) : Prop where finite : catalog.Finite diff --git a/Ix/Compile/Verify/Codec.lean b/Ix/Compile/Verify/Codec.lean index 15c0753f9..3fc3f2da9 100644 --- a/Ix/Compile/Verify/Codec.lean +++ b/Ix/Compile/Verify/Codec.lean @@ -4,7 +4,7 @@ import Std.Tactic.BVDecide /-! # Proof-visible v2 codecs -These X1 slices make universe serialization kernel-visible end to end. +These proofs make universe serialization kernel-visible end to end. `Reads` records exact cursor movement in arbitrary surrounding bytes, while `Writes` records append-only writer behavior. The public theorem covers both the one-byte and trimmed 1–8-byte `Tag2` forms, subject only to the format's @@ -1422,7 +1422,7 @@ theorem getUniv_reads (u : Ixon.Univ) (h : WireWF u) : have hread := getUnivFuel_reads u h _ hfuel before after exact hread -/-- X1-U64: exact full-buffer universe round trip for every representable +/-- Exact full-buffer universe round trip for every representable compressed successor count. -/ theorem deUniv_serUniv (u : Ixon.Univ) (h : WireWF u) : Ixon.deUniv (Ixon.serUniv u) = .ok u := by @@ -1467,13 +1467,13 @@ abbrev UnivWireWF : Ixon.Univ → Prop := abbrev SmallUnivWireWF : Ixon.Univ → Prop := Codec.Ixon.Univ.SmallWireWF -/-- X1-U64: exact full-buffer universe round trip across both the one-byte +/-- Exact full-buffer universe round trip across both the one-byte and trimmed large-size `Tag2` forms. -/ theorem deUniv_serUniv (u : Ixon.Univ) (h : UnivWireWF u) : Ixon.deUniv (Ixon.serUniv u) = .ok u := Codec.Ixon.Univ.deUniv_serUniv u h -/-- X1-U8: exact full-buffer universe round trip for the one-byte tag domain. +/-- Exact full-buffer universe round trip for the one-byte tag domain. This domain contains `.succ .zero`, the encoding of `Sort 1`. -/ theorem deUniv_serUniv_small (u : Ixon.Univ) (h : SmallUnivWireWF u) : Ixon.deUniv (Ixon.serUniv u) = .ok u := diff --git a/Ix/Kernel/Driver.lean b/Ix/Kernel/Driver.lean index be0310eeb..400b00eb5 100644 --- a/Ix/Kernel/Driver.lean +++ b/Ix/Kernel/Driver.lean @@ -107,7 +107,7 @@ def constantInfoTag : Ixon.ConstantInfo → Ixon.ConstTag | .rPrj _ => .rPrj | .dPrj _ => .dPrj -/-- Deterministic source-key order shared by the implementation and E1's +/-- Deterministic source-key order shared by the implementation and serial composition's coverage certificate. -/ def orderedAnonConstAddrs (env : Ixon.Env) : Array Address := env.consts.keys.toArray.qsort fun a b => a.cmpBytes b == .lt @@ -228,7 +228,7 @@ structure CheckResult where deriving Repr, Inhabited /-- Explicit accumulator for the serial anonymous driver. Naming this -state makes the production loop available to E1's trace theorem without +state makes the production loop available to serial composition's trace theorem without changing its persistent-checker semantics. -/ structure AnonCheckLoopState where results : Array CheckResult diff --git a/Ix/Kernel/Inductive.lean b/Ix/Kernel/Inductive.lean index 18b78eb1e..e57d3a91e 100644 --- a/Ix/Kernel/Inductive.lean +++ b/Ix/Kernel/Inductive.lean @@ -579,7 +579,7 @@ def checkPositiveParametersFrom (id : KId m) checkPositiveParametersFrom id args params (index + 1) remaining /-- The exact stateful parameter-comparison loop used by positivity. Naming - it separately exposes the successful recursive `isDefEq` trace to E2c + it separately exposes the successful recursive `isDefEq` trace to inductive verification without changing the production comparison order or diagnostics. -/ def checkPositiveParameters (id : KId m) (args params : Array (KExpr m)) (nParams : Nat) : RecM m Unit := @@ -593,7 +593,7 @@ def positiveIndicesIndependent (args : Array (KExpr m)) (nParams : Nat) !exprMentionsAnyAddr index rootAddrs /-- The stateless prefix of recursive-application validation. Keeping the - original error values here makes the production control flow and the E2c + original error values here makes the production control flow and the inductive verification success characterization share one definition. -/ def checkPositiveRecursiveApplicationPreconditions (us : Array (KUniv m)) (args : Array (KExpr m)) @@ -618,7 +618,7 @@ def checkPositiveRecursiveApplicationPreconditions s!"positivity: recursive occurrence has wrong argument count: expected {nParams + nIndices}, got {args.size}") /-- Validate the already-resolved inductive header of an active recursive - application. Separating the lookup/match from these guards gives E2c an + application. Separating the lookup/match from these guards gives inductive verification an exact successful-branch seam while preserving their production order. -/ def checkPositiveRecursiveApplicationHeader (id : KId m) (us : Array (KUniv m)) (args : Array (KExpr m)) @@ -769,7 +769,7 @@ def checkNestedPositivityApplicationResolvedFuel (fuel : Nat) (id : KId m) parameter specialization mentions the root block. The caller has already reduced the field domain to this constant-headed spine and established that the head is not a root-family address. Keeping the lookup and - resolved continuation as named production actions gives E2c an exact + resolved continuation as named production actions gives inductive verification an exact successful-header boundary without changing execution order. -/ def checkNestedPositivityApplicationFuel (fuel : Nat) (id : KId m) (us : Array (KUniv m)) (args : Array (KExpr m)) @@ -1020,7 +1020,7 @@ def checkCtorMetadataAgainstParent (ctorId inductId : KId m) /-- Complete A1–A4 validation of one constructor after its parent inductive header and block context have been resolved. Naming this shared sequence keeps member-wide and standalone-constructor checking on the same production -path and gives E2c one exact seam at which successful positivity can be +path and gives inductive verification one exact seam at which successful positivity can be retained before the later universe and return-type checks. -/ def checkInductiveConstructor (ctorId inductId : KId m) (expectedCidx indParams indIndices : Nat) (indLvls : UInt64) @@ -1228,7 +1228,7 @@ def mkIndUnivs (indLvls offset : UInt64) : /-- Reuse or append the exact auxiliary specialization discovered by the flat-block scan. Keeping this decision as a named production action - exposes the shared specialization key to the E2c transport without + exposes the shared specialization key to the inductive verification transport without changing the source-ordered queue traversal around it. -/ def appendNestedAuxiliary (headId : KId m) (occurrenceUs : Array (KUniv m)) (specParams : Array (KExpr m)) @@ -1388,7 +1388,7 @@ def scanFlatConstructors (allBlockAddrs : Array Address) /-- One source-ordered production queue step. Naming the callback preserves the executable traversal while exposing the dynamically growing flat array -and its deduplication set to E2c proofs. -/ +and its deduplication set to inductive verification proofs. -/ def buildFlatBlockQueueStep (allBlockAddrs : Array Address) (nRecParams univOffset : UInt64) (state : FlatBlockQueueState m) : RecM m (BoundedStep (FlatBlockQueueState m) @@ -2856,7 +2856,7 @@ def checkGeneratedRecursorCandidate (ty : KExpr m) throw (.other "check_recursor: type mismatch") let generatedRules := generated.rules if generatedRules.isEmpty && !storedRules.isEmpty then - -- C1: cannot verify stored rules against a missing canonical form. + -- Cannot verify stored rules against a missing canonical form. throw (.other s!"check_recursor: rule generation failed, cannot verify {storedRules.size} stored rules") else if !generatedRules.isEmpty && storedRules.isEmpty then throw (.other s!"check_recursor: stored recursor has no rules (expected {generatedRules.size})") @@ -2913,7 +2913,7 @@ def collectGeneratedRecursorTypeMatches (ty : KExpr m) /-- Select the generated recursor corresponding to one frozen stored declaration. Complete recursor types are closed, unlike major domains peeled from under forall binders, so the stateful DefEq calls remain inside the -top-level K2 translation context. Returning the index separately gives +top-level inference/conversion translation context. Returning the index separately gives verification an exact boundary between selection and exhaustive comparison. -/ def selectGeneratedRecursorIndex (recBlock id : KId m) (ty : KExpr m) (params motives minors : UInt64) (indId : KId m) diff --git a/Ix/Kernel/Infer.lean b/Ix/Kernel/Infer.lean index abfedbfcc..2fc49e7ed 100644 --- a/Ix/Kernel/Infer.lean +++ b/Ix/Kernel/Infer.lean @@ -146,7 +146,7 @@ def inferWith (inferRec : KExpr m → RecM m (KExpr m)) TcM.withInferOnly (methods.infer e) /-- Tie Infer's structural recursive calls through the indexed method table. - `inferWith` is the transparent one-layer body consumed by K0/K1 proofs. -/ + `inferWith` is the transparent one-layer body consumed by totalization/WHNF proofs. -/ def infer (e : KExpr m) : RecM m (KExpr m) := inferWith inferCall e diff --git a/Ix/Kernel/Level.lean b/Ix/Kernel/Level.lean index 62b99ecdb..2f8fd5362 100644 --- a/Ix/Kernel/Level.lean +++ b/Ix/Kernel/Level.lean @@ -372,7 +372,7 @@ decreasing_by all_goals simp [KUniv.size]; omega end -/-! ### Subsumption (Phase 2) -/ +/-! ### Subsumption -/ /-- Keep only the `xs` entries not dominated by a `ys` entry (merge-walk over sorted var lists). Mirrors level.rs `subsume_vars`. Written as index diff --git a/Ix/Kernel/Verify/Audit/Completed.lean b/Ix/Kernel/Verify/Audit/Completed.lean index a9659a1d4..b4751da2d 100644 --- a/Ix/Kernel/Verify/Audit/Completed.lean +++ b/Ix/Kernel/Verify/Audit/Completed.lean @@ -2495,11 +2495,11 @@ private def booleanEnumerationNative : Array Lean.Name := `Ix.Kernel.BooleanEnumerationFixture.recursorOwnerNative._native.native_decide.ax_1_1 ] ++ booleanSemanticFixtureNative -/- The E3-S family-body bridge consumes only the family-side slice of the +/- The supported fragment family-body bridge consumes only the family-side slice of the full end-to-end Boolean witness. Keep this narrower than `booleanEnumerationNative`: in particular it must not inherit the executable recursor run, kernel-run, generated-rule, or recursor-ingress facts merely -because the larger E2b witness uses them. -/ +because the larger singleton certification witness uses them. -/ private def booleanFamilyBodyNative : Array Lean.Name := inductiveNative ++ #[ enumerationAcceptanceNativeAxiom `Ix.Kernel.BooleanEnumerationFixture.familyBlockLoadedNative._native.native_decide.ax_1_1, @@ -2581,7 +2581,7 @@ private def booleanFamilyBodyNative : Array Lean.Name := inductiveNative ++ #[ `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 ] -/-- Exact evaluator boundary of the final E3-S Boolean whole-driver witness. +/-- Exact evaluator boundary of the Boolean whole-driver witness. This is intentionally narrower than `booleanEnumerationNative`: the release root consumes the generated Theory certificate and exact physical links, but does not inherit the earlier standalone body/kernel executions as semantic @@ -2769,7 +2769,7 @@ def booleanDriverNative : Array Lean.Name := inductiveNative ++ #[ `Ix.Kernel.BooleanEnumerationFixture.trueTypeNative._native.native_decide.ax_1_2 ] -/-- Exact evaluator boundary of the serialized T0 Boolean certificate. Each +/-- Exact evaluator boundary of the serialized Boolean certificate. Each closed computation is named so changes in the byte, eager, lazy, dependency, or driver slices are visible independently in the trust manifest. -/ def serializedBooleanNative : Array Lean.Name := booleanDriverNative ++ #[ @@ -2907,7 +2907,7 @@ def serializedBooleanNative : Array Lean.Name := booleanDriverNative ++ #[ `Ix.Kernel.BooleanSerialized.trueProjectionLookupNative._native.native_decide.ax_1_1 ] -/- Exact evaluator boundary of the non-vacuous literal/blob T0 fixture. -/ +/- Exact evaluator boundary of the non-vacuous literal/blob serialization fixture. -/ private def literalRoundTripNative : Array Lean.Name := nameNative ++ #[ literalBlobsNativeAxiom `Ix.Kernel.SerializedLiteralBlobs.blobKeysClassifiedNative._native.native_decide.ax_1_1, @@ -2982,7 +2982,7 @@ than allowing the remainder of the executable inductive-fixture debt. -/ private def projectionDebt : Array Lean.Name := typingDebt.push ``Ix.Theory.Named.VEnv.WF.registeredStructureHeadInversion -/- The empty legacy whole-`KEnv` inductive path is forbidden from every G2b +/- The empty legacy whole-`KEnv` inductive path is forbidden from every catalog lookup consumer root. Keeping this list in the executable audit prevents an innocent-looking helper from reintroducing the old `nomatch` dependency. -/ private def legacyWholeEnv : Array Lean.Name := #[ @@ -2992,7 +2992,7 @@ private def legacyWholeEnv : Array Lean.Name := #[ ``Ix.Kernel.TrKEnv ] -/- E2a is intentionally a Theory-only certificate consumer. These +/- The generation adapter is a Theory-only certificate consumer. These checker/catalog/pattern declarations must not enter its dependency graph. -/ private def certificateAdapterForbidden : Array Lean.Name := #[ ``Ix.Kernel.Catalog, @@ -3016,7 +3016,7 @@ private def annotatedPiCertificateForbidden : Array Lean.Name := #[ ] /- The pre-TrustedBody delta route admitted successful unfolding through a broad -reflection oracle and arbitrary cache-write authority. The final K1 closure +reflection oracle and arbitrary cache-write authority. The final WHNF closure must use exact trusted declaration certificates instead. -/ private def legacyDeltaAuthority : Array Lean.Name := #[ ``Ix.Kernel.UnfoldCacheWriteOracle, @@ -3045,8 +3045,8 @@ private def legacyAllDepthKnot : Array Lean.Name := #[ private def boundedKnotForbiddenDependencies : Array Lean.Name := k1ForbiddenDependencies ++ legacyAllDepthKnot -/- E2c occurrence-validation roots must be derived from the production run, -not from the ambient semantic inductive oracle retained by E2b. -/ +/- Occurrence-validation roots must be derived from the production run, +not from the ambient semantic inductive oracle retained by singleton certification. -/ private def occurrenceValidationForbiddenDependencies : Array Lean.Name := boundedKnotForbiddenDependencies.push ``Ix.Kernel.InductiveOracle @@ -3074,7 +3074,7 @@ private def oracleWorldMaterialization : Array Lean.Name := #[ private def existingSemanticBlockForbiddenDependencies : Array Lean.Name := boundedKnotForbiddenDependencies ++ oracleWorldMaterialization -/- K2S keeps the global suffix model as a compatibility surface only. The +/- Scoped method proofs keep the global suffix model as a compatibility surface only. The finite positive-fuel construction must neither manufacture that model nor reach the older public adapters that consume it. -/ private def legacyGlobalSuffix : Array Lean.Name := #[ @@ -3124,7 +3124,7 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Kernel.TcM.instantiateUnivParams_wf, standardAxioms := standard, nativeAxioms := levelNative }, - -- G3a finite run support and generated-term resource bounds. Universe + -- Finite run support and generated-term resource bounds. Universe -- instantiation can rebuild sorts/constants and therefore reaches the now -- total expression serializer's standard `UInt8` quotient implementation. { root := ``Ix.Kernel.KExpr.LiftReach.finite, @@ -3175,7 +3175,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - -- G3b closes the remaining formalized walker/direct-intern families and + -- Execution-indexed support covers the formalized walker/direct-intern families and -- ties the exact finite request list to an actual TcM computation. The -- simultaneous/reverse instantiation specs can likewise rebuild serialized -- expressions and inherit the same standard quotient footprint. @@ -3321,7 +3321,7 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Kernel.TrKExpr.defeq, standardAxioms := standard, sorryOrigins := typingDebt }, - -- Legacy whole-environment compatibility interfaces. G2b consumer roots + -- Legacy whole-environment compatibility interfaces. Catalog lookup consumer roots -- below are forbidden from depending on these declarations. { root := ``Ix.Kernel.TrKEnv.wf, standardAxioms := standard }, @@ -3343,7 +3343,7 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Kernel.CtxRecon.fvar_resolves, standardAxioms := standard }, - -- G1a's non-circular world and one-way lazy-load boundary. + -- Non-circular world model and one-way lazy-load boundary. { root := ``Ix.Kernel.VerifyWorld.ofCatalog_catalogued_not_trusted, standardAxioms := standardWithoutChoice }, { root := ``Ix.Kernel.VerifyWorld.LE.trans, @@ -3361,7 +3361,7 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Kernel.VerifyWorld.ofCatalog_loaded_not_trusted, standardAxioms := standard }, - -- G1b's raw/pending boundary. Raw correspondence has no declaration-WF + -- Pending-declaration isolation. Raw correspondence has no declaration-WF -- premise; the fixture roots pin the concrete non-WF pending case. { root := ``Ix.Kernel.RawExprRel.mono, standardAxioms := standard }, @@ -3380,7 +3380,7 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Kernel.IllTypedPending.loaded_pending_but_not_wf, standardAxioms := standard }, - -- G1c's trusted-only catalog log and explicit-WF promotion boundary. + -- Trusted-only catalog log and explicit-WF promotion boundary. { root := ``Ix.Kernel.RawDeclRel.wf_le, standardAxioms := standard }, { root := ``Ix.Kernel.TrustedCatalogLog.wf, @@ -3414,7 +3414,7 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Kernel.WellTypedPromotion.promotes, standardAxioms := standard }, - -- G1d's world-based concrete-state invariant. Loading stays + -- World-based concrete-state invariant. Loading stays -- representation-only, promotion requires a fresh WF witness, and the -- fixed-world Hoare roots pin no-promotion behavior on both outcomes. { root := ``Ix.Kernel.TcStateWF.of_consts_eq, @@ -3434,7 +3434,7 @@ private def roots : Array RootAllowance := #[ { root := ``Ix.Kernel.TcM.instantiateUnivParams.tcStateWF, standardAxioms := standard, nativeAxioms := levelNative }, - -- Pin A / E2a: the certified-generation adapter may use only Ix.Theory.Named + -- The certified-generation adapter may use only Ix.Theory.Named -- Theory transaction facts, never Ix checker/catalog/pattern authority. { root := ``Ix.Kernel.CertifiedGenerationTransaction.trace, standardAxioms := standardWithoutChoice, @@ -3446,7 +3446,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - -- Spec-08's Theory-only block adapter preserves the same quarantine while + -- The Theory-only block adapter preserves the same quarantine while -- exposing one atomic all-families/all-constructors/all-recursors/all-rules -- transaction rather than a sequence of singleton admissions. { root := ``Ix.Kernel.CertifiedBlockGenerationTransaction.trace, @@ -3459,7 +3459,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standardWithoutChoice, forbiddenDependencies := certificateAdapterForbidden }, - -- E2c retains the exact Ix.Theory.Named candidate-producer equation alongside + -- Inductive verification retains the exact Ix.Theory.Named candidate-producer equation alongside -- the certified Theory transaction. Unlike the Theory-only adapter above, -- this Verify-backed bridge deliberately inherits the pinned analyzer debt. { root := ``Ix.Kernel.ProducedGenerationTransaction.facts, @@ -3494,7 +3494,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, nativeAxioms := mutualFamilyNative }, - -- E2c's first concrete breadth witness is the exact staged `IndexedVec` + -- The concrete breadth witness is the exact staged `IndexedVec` -- certificate: one parameter, one changing index, a recursive field, large -- elimination, and both generated rules. It remains Theory-only here; -- production Ix catalog correspondence is audited in the later linkage. @@ -3611,7 +3611,7 @@ private def roots : Array RootAllowance := #[ sorryOrigins := aliasRecUpstreamDebt, forbiddenDependencies := annotatedPiCertificateForbidden }, - -- E2c occurrence-validation seam. These roots expose the selected loaded + -- Occurrence-validation boundary. These roots expose the selected loaded -- family and strengthen every production guard into the elementwise -- valid-inductive-application invariant, without oracle authority. { root := @@ -3651,7 +3651,7 @@ private def roots : Array RootAllowance := #[ ``Ix.Kernel.RecM.PositiveParameterComparisonTrace.theoryDefEqScoped, standardAxioms := standard, nativeAxioms := inferNative, - -- This is the K2S instantiation bridge, not the oracle-free occurrence + -- This is the scoped method instantiation bridge, not the oracle-free occurrence -- theorem above. `ScopedWhnfStateInv` contains `TrustedCatalogLog`, whose -- ambient constructor names `InductiveOracle`; semantic use remains -- confined to the projected `ScopedWFAtOn.isDefEq` field. @@ -3695,7 +3695,7 @@ private def roots : Array RootAllowance := #[ nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- E2c production-traversal seam. Root-free domains are state-preserving; + -- Production-traversal boundary. Root-free domains are state-preserving; -- direct recursive-family applications inherit the oracle-free occurrence -- invariant; and forall success exposes the decremented recursive run plus -- exact local-context restoration. @@ -3810,7 +3810,7 @@ private def roots : Array RootAllowance := #[ nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- E2c nested auxiliary expansion. The complete positivity trace emits an + -- Nested auxiliary expansion. The complete positivity trace emits an -- exact existing-or-fresh request; the flat scanner classifies every -- successful detector call as an unchanged pair or one fresh exact append. -- The source-ordered constructor and bounded-queue histories prove that the @@ -3936,7 +3936,7 @@ private def roots : Array RootAllowance := #[ nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- Concrete E2c nested reachability. The compiler-shaped Box/Tree fixture + -- Concrete nested reachability. The compiler-shaped Box/Tree fixture -- runs production ingress, positivity, and flat-block construction on the -- same `Box Tree` occurrence. Its headline root proves that the exact -- fresh positivity request is retained under the audited queue invariant. @@ -4187,7 +4187,7 @@ private def roots : Array RootAllowance := #[ sorryOrigins := nestedRestoredPatternUpstreamDebt, forbiddenDependencies := existingSemanticBlockForbiddenDependencies }, - -- E2c generated-recursor metadata. The seven cached header fields are + -- Generated-recursor metadata. The seven cached header fields are -- derived positionally from the certified flat block and are invariant -- under both best-effort and complete rule population. The final root -- covers the actual anonymous-mode cache insertion phase; none of these @@ -4267,7 +4267,7 @@ private def roots : Array RootAllowance := #[ nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- E2c generated-recursor type closure. Production closes the accumulated + -- Generated-recursor type closure. Production closes the accumulated -- domains through explicit right-to-left intern requests. These roots prove -- exact finite-support execution, operation-shaped structural translation, -- and equality with Ix.Theory.Named's public canonical mixed recursor type. @@ -4339,9 +4339,9 @@ private def roots : Array RootAllowance := #[ nativeAxioms := generatedRecursorRuleFixtureNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- E2c generated-recursor commit, selection, and exhaustive comparison. + -- Generated-recursor commit, selection, and exhaustive comparison. -- Production selection compares complete closed types through an explicit - -- finite fold; one K2S successor layer preserves the scoped state across + -- finite fold; one scoped method successor layer preserves the scoped state across -- selection and gives semantic meaning to the repeated type and positional -- rule comparisons. { root := ``Ix.Kernel.RecM.checkGeneratedRecursorFromCache_success, @@ -4373,7 +4373,7 @@ private def roots : Array RootAllowance := #[ nativeAxioms := generatedRecursorCanonicalFixtureNative, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, - -- E2c outer member closure and exact semantic admission. The explicit + -- Outer member closure and exact semantic admission. The explicit -- transition bridge fixes both Theory environments and requires complete -- trusted provenance for every exact physical member; the existing-block -- specialization keeps that environment unchanged for the recursor block. @@ -4442,7 +4442,7 @@ private def roots : Array RootAllowance := #[ sorryOrigins := aliasRecUpstreamDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, - -- E2c flat semantic transport. The refined flat production trace erases + -- Flat semantic transport. The refined flat production trace erases -- to the exhaustive classifier, and the operation-shaped cross-kernel -- contract recursively constructs Ix.Theory.Named's retained positivity trace. -- Nested auxiliary expansion remains a separate explicit bridge. @@ -4456,18 +4456,18 @@ private def roots : Array RootAllowance := #[ nativeAxioms := inferNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- E2c's concrete cross-kernel trace bridge. These roots start at the + -- Concrete cross-kernel trace bridge. These roots start at the -- exact positivity calls selected by the production IndexedVec family -- checker, transport those operations to Ix.Theory.Named, and replay the complete -- retained constructor validator. The direct recursive fixture has no - -- nested auxiliary expansion; that remains the next generic E2c bridge. + -- nested auxiliary expansion; that remains a separate generic proof obligation. { root := ``Ix.Kernel.IndexedRecursiveFixture.indexedVecConsConstructorValidationRun, standardAxioms := standard, nativeAxioms := indexedConstructorValidationNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- E2c's first production-linked indexed/recursive vertical slice. The + -- Production-linked indexed/recursive fixture. The -- generated cons equation includes its predecessor recursive call; the -- oracle is then instantiated by exact anonymous ingress, production -- family/recursor checking, exact ownership, and atomic admission. The @@ -4509,7 +4509,7 @@ private def roots : Array RootAllowance := #[ nativeAxioms := kTargetAcceptanceNative, forbiddenDependencies := occurrenceValidationForbiddenDependencies }, - -- E2b's singleton link and legacy oracle constructors remain audited as + -- The singleton link and legacy oracle constructors remain audited as -- compatibility surfaces. The concrete Boolean closure below no longer -- consumes those oracle constructors: its family block advances the exact -- generated Theory environment, and its recursor block consumes entries @@ -4552,7 +4552,7 @@ private def roots : Array RootAllowance := #[ sorryOrigins := typingDebt, forbiddenDependencies := canonicalRecursorForbiddenDependencies }, - -- G2a's explicit ambient-inductive assumption boundary. Audit every + -- Explicit ambient-inductive assumption boundary. Audit every -- oracle projection so adding a field changes this manifest, then pin the -- constructive Nat model and its adversarial loaded-state witness. { root := ``Ix.Kernel.RawInductiveConstRel.mono, @@ -4633,7 +4633,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - -- G4's lookup isolation, exhaustive semantic-cache provenance, monotone + -- Lookup isolation, exhaustive semantic-cache provenance, monotone -- warm-world transport, and transactional public-check error boundary. { root := ``Ix.Kernel.PendingDecl.lookup_isolation, standardAxioms := standard }, @@ -4682,7 +4682,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - -- K1's concrete Theory reduction meaning, exact five-way cache overlay, + -- WHNF's concrete Theory reduction meaning, exact five-way cache overlay, -- and real ambient-Nat warm-hit witness. The only sorries are the already -- named upstream inductive-environment boundary. { root := ``Ix.Kernel.WhnfMeaning.refl, @@ -6762,7 +6762,7 @@ private def roots : Array RootAllowance := #[ forbiddenDependencies := legacyWholeEnv }, -- StringExpansion: the remaining String-expansion premise is reduced to a pure, -- finite plan. The actual primitive read, seven prefix interns, recursive - -- character fold, and final intern preserve the complete K1 invariant and + -- character fold, and final intern preserve the complete WHNF invariant and -- return the exact structurally translated generated expression. { root := ``Ix.Kernel.RecM.strLitListToConstructor_plan_wf, standardAxioms := standard, nativeAxioms := expressionNative, @@ -6821,7 +6821,7 @@ private def roots : Array RootAllowance := #[ -- NatOffset: the actual post-major iota preprocessing path. Bounded Nat-offset -- parsing, Nat constructor expansion, cleanup, lazy constructor lookup, -- finite String expansion, the policy-selected recursive callback, and the - -- constructor/struct-eta dispatch all preserve the complete K1 invariant. + -- constructor/struct-eta dispatch all preserve the complete WHNF invariant. -- Only the ordinary-constructor and struct-eta tails remain named inputs. { root := ``Ix.Kernel.RecM.prims_state_wf, standardAxioms := standardWithoutChoice, @@ -8124,7 +8124,7 @@ private def roots : Array RootAllowance := #[ nativeAxioms := contextNative.push nameDecideNative, forbiddenDependencies := legacyWholeEnv }, - -- K2a: suffix semantics reduce open-context cache validity to one explicit + -- Suffix semantics reduce open-context cache validity to one explicit -- operational model. The recursive method table closes by induction from -- an exact one-layer contract split between WHNF and Infer/DefEq ownership. { root := ``Ix.Kernel.WhnfSuffixModel.keyRepresents, @@ -8149,7 +8149,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := legacyWholeEnv }, - -- K2a also assigns exact meanings to the remaining cache families. A + -- Exact meanings for the remaining cache families. A -- positive DefEq result carries Theory equality; negative results are -- intentionally vacuous for the one-way soundness claim. { root := ``Ix.Kernel.InferMeaning.mono, @@ -8183,7 +8183,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - -- K2b: production key executions now generate the canonical operational + -- Production key executions generate the canonical operational -- context witnesses. Physical inference/DefEq writes preserve every -- cache partition, including the rejection-only same-head failure set. { root := ``Ix.Kernel.CacheInvariant.insertInfer, @@ -8359,7 +8359,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, forbiddenDependencies := legacyWholeEnv }, - -- First production K2 branches: both inference hit partitions, collision- + -- Production inference/conversion branches: both inference hit partitions, collision- -- safe DefEq address reflexivity, and a positive full DefEq hit including -- canonical ordering and its final union-find mutation. { root := ``Ix.Kernel.RecM.isDefEq_fullHit_true, @@ -9072,7 +9072,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, nativeAxioms := levelNative, forbiddenDependencies := k1ForbiddenDependencies }, - -- C1A's usable production boundary: a finite schedule closes only the + -- Bounded production methods: a finite schedule closes only the -- method-table depths selected by this run's recursion fuel. The public -- adapters consume the terminal successor-layer domain and have no -- `sorryAx` dependency. @@ -9114,7 +9114,7 @@ private def roots : Array RootAllowance := #[ sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - -- K3 reconstructs the typed source translation from untyped/scoped + -- Declaration checking reconstructs the typed source translation from untyped/scoped -- checker ingress. These roots are usable before the final checkConst -- assembly and do not depend on its statement placeholder. { root := ``Ix.Kernel.KUniv.scoped_iff_toVLevel_wf, @@ -9440,7 +9440,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, nativeAxioms := inferNative, forbiddenDependencies := k1ForbiddenDependencies }, - -- K3 closes the concrete operational policy and retains the old strong + -- Declaration checking closes the concrete operational policy and retains the old strong -- all-support inference roots below as compatibility artifacts. The -- public checker now consumes the bounded successor-layer resources above. { root := ``Ix.Kernel.Methods.next_preservesInferOnly, @@ -9497,10 +9497,10 @@ private def roots : Array RootAllowance := #[ sorryOrigins := typingDebt, forbiddenDependencies := scopedK2SForbiddenDependencies }, - -- E0 closes the atomic coordinated-block transaction around the real + -- Block admission closes the atomic coordinated-block transaction around the real -- production router, classifier, body, and block-result cache. The - -- singleton-definition adapter consumes K3; inductive/recursor bodies keep - -- their E2 oracle premise explicit. Quotients are audited as excluded from + -- singleton-definition adapter consumes the declaration-checking theorem; inductive/recursor bodies keep + -- their inductive certification oracle premise explicit. Quotients are audited as excluded from -- this authority rather than being silently admitted by the block theorem. { root := ``Ix.Kernel.ExactCheckBlock.rebaseWorld, standardAxioms := standardWithoutChoice, @@ -9628,7 +9628,7 @@ private def roots : Array RootAllowance := #[ standardAxioms := standard, forbiddenDependencies := boundedKnotForbiddenDependencies }, - -- E1 models semantic declaration dependencies in the production Address + -- Serial composition models semantic declaration dependencies in the production Address -- domain, proves buildAnonWork is an exact duplicate-free partition, and -- composes successful items in a constructive collapsed-block order. The -- serial roots recover real successful checkConst calls from the public @@ -9754,10 +9754,10 @@ private def roots : Array RootAllowance := #[ standardAxioms := propextOnly, forbiddenDependencies := boundedKnotForbiddenDependencies }, - -- E3-S assembles the scoped K3 standalone theorem and E0's exact atomic - -- disposition into E1's concrete-call adapter. The operational body sum - -- remains transparent: singleton definitions use the scoped K3 certificate - -- and fresh inductive/recursor bodies retain an explicit E2 oracle resource. + -- The supported fragment combines the scoped standalone theorem and atomic + -- block disposition in the serial driver's concrete-call adapter. Singleton + -- definitions use the scoped checking certificate; fresh inductive/recursor + -- bodies retain an explicit inductive-certification oracle resource. -- Separately, the certificate-backed replay adapter consumes already- -- installed member provenance, admits exact arrays idempotently, and gives -- all-block consumers a path which cannot reach oracle materialization. @@ -9844,7 +9844,7 @@ private def roots : Array RootAllowance := #[ sorryOrigins := typingDebt, forbiddenDependencies := boundedKnotForbiddenDependencies }, - -- K2S closed-context vertical slice. These roots certify the exact + -- Scoped methods in a closed context. These roots certify the exact -- fuel-one public trace, package its finite requests and bounded recursive -- schedule, instantiate `ScopedKernelSuffixModel.finiteOperational`, and -- retain `StateInScope` through successful semantic promotion. None may diff --git a/Ix/Kernel/Verify/Audit/Statements.lean b/Ix/Kernel/Verify/Audit/Statements.lean index 976bd7d50..c07319c0a 100644 --- a/Ix/Kernel/Verify/Audit/Statements.lean +++ b/Ix/Kernel/Verify/Audit/Statements.lean @@ -9,8 +9,9 @@ All seven roots are concrete results over the bounded production recursion schedule and checker. The three recursive-method adapters have no `sorryAx` dependency; the standalone and atomic-block checker roots retain only the two named Ix.Theory.Named typing lemmas through their singleton-definition branch. The -E3-S root executes the exact Boolean serial workset and composes its actual -runtime success gates with E1 and fixed certificate-backed E2 entries. This +supported-fragment root executes the exact Boolean serial workset and composes +its runtime success gates with serial composition and fixed inductive +certificate entries. This module permits no local statement placeholder and additionally forbids the Boolean/serialized roots from reaching oracle construction, restaging, or world materialization. @@ -48,7 +49,7 @@ private def legacyAllDepthKnot : Array Lean.Name := #[ private def forbidden : Array Lean.Name := legacyWholeEnv ++ legacyAllDepthKnot -/- K2S public recursive roots may retain the legacy declarations in the +/- Scoped public recursive roots may retain the legacy declarations in the library, but must not manufacture a global suffix model or pass through the old proposition-classifier/run-context path. -/ private def legacyGlobalSuffix : Array Lean.Name := #[ @@ -65,7 +66,7 @@ private def legacyGlobalSuffix : Array Lean.Name := #[ private def scopedForbidden : Array Lean.Name := forbidden ++ legacyGlobalSuffix -/- The all-block E3-S statement must consume fixed semantic entries and may +/- The all-block statement for the supported fragment must consume fixed semantic entries and may not regain the retired residual-oracle/world-materialization path through an adapter refactor. -/ private def oracleWorldMaterialization : Array Lean.Name := #[ diff --git a/Ix/Kernel/Verify/Cache.lean b/Ix/Kernel/Verify/Cache.lean index d35ea1e8a..4050f57c3 100644 --- a/Ix/Kernel/Verify/Cache.lean +++ b/Ix/Kernel/Verify/Cache.lean @@ -8,7 +8,7 @@ import Std.Data.HashSet.Lemmas /-! # Cache provenance and pending-declaration isolation -This is the G4 boundary between an optimization hit and a semantic fact. +Cache provenance connects an optimization hit to a semantic fact. `KEnv` stores only compact address keys, values, and booleans; it does not store the world or expression witnesses under which an entry was produced. The verification therefore carries that missing data as ghost provenance: @@ -25,10 +25,10 @@ The verification therefore carries that missing data as ghost provenance: * `CacheEntry.ReferencesAuthorized` records that every direct constant root behind an entry is trusted (or, for a structural block artifact only, is an active block member); and -* `CacheSemantics.Valid` is the exact family of C1/K1/K2 semantic meanings. - G4 keeps it parametric and requires its world monotonicity. A run chooses - its final finite support up front; K1 and K2 instantiate and preserve the - contract at each concrete insertion site. +* `CacheSemantics.Valid` gives each cache family's semantic meaning and + requires monotonicity under world extension. A run chooses its final finite + support up front; reduction, inference, and conversion proofs instantiate + and preserve the contract at each insertion site. The split is deliberate. This file proves generic cache-hit, world-extension, support-witness weakening, reset, clearing, error-restoration, and @@ -49,8 +49,8 @@ the active atomic block. Every reduction/delta/cache fact is role (3), so a pending target cannot justify its own type or value. These roles are proof-side labels: the production `TcM.getConst` API is not -yet intrinsically capability-tagged. G4 proves the standalone raw-translation -barrier and the stable-cache barrier. K1/K2 must still classify and discharge +yet intrinsically capability-tagged. This module proves the standalone +raw-translation and stable-cache barriers. Each operation's proof must discharge `LookupScope.Allows` at each whnf/infer/defeq/inductive call site; this audit does not treat an untagged concrete lookup as trusted merely because it was listed here. @@ -357,8 +357,8 @@ def CacheEntry.ReferencesAuthorized (authority : CacheAuthority) authority.world.trusted id ∨ (entry.SubjectScoped ∧ authority.active id) -/-- The semantic meaning of each tagged cache family. K1/K2 provide the -concrete `Valid`; G4 requires world monotonicity so a warm entry remains +/-- The semantic meaning of each tagged cache family. Reduction, inference, +and conversion supply `Valid`; world monotonicity keeps a warm entry usable after declarations are admitted. A composite run chooses its final finite support up front, so changing support is deliberately not hidden in this interface. -/ @@ -739,8 +739,8 @@ theorem insertBlockError {semantics : CacheSemantics} (CacheProvenance.blockError semantics authority support block err) /-- Insert one certified full-whnf result while retaining provenance for all -old entries. The four policy-specific siblings below cover every other K1 -WHNF expression map; their exact semantic payload is supplied by +old entries. The four policy-specific siblings below cover the other WHNF +expression maps; their exact semantic payload is supplied by `Verify/Whnf.lean`. -/ theorem insertWhnf {semantics : CacheSemantics} {authority : CacheAuthority} {support : RunSupport} diff --git a/Ix/Kernel/Verify/Check/Acceptance.lean b/Ix/Kernel/Verify/Check/Acceptance.lean index 39eaf2b06..67a9650f1 100644 --- a/Ix/Kernel/Verify/Check/Acceptance.lean +++ b/Ix/Kernel/Verify/Check/Acceptance.lean @@ -11,7 +11,7 @@ The operational checker should produce only the typing fact which differs by declaration kind. Fresh installation and trusted-world promotion are then pure consequences of the existing pending-declaration model. -This keeps K3's critical implication explicit: +This keeps the declaration checker's critical implication explicit: * an axiom is accepted only when its declared type is a Theory type; * a definition, opaque definition, or theorem is accepted only when its @@ -123,7 +123,7 @@ theorem accepted end StandaloneCheckEvidence -/-- The complete declaration-local result expected from K3: a validated raw +/-- The complete declaration-local result expected from declaration-checking: a validated raw declaration has an exact untyped Theory translation, and the checker has supplied the semantic evidence appropriate to its declaration kind. -/ structure StandaloneCheckResult (trProj : RawProjRel) @@ -206,7 +206,7 @@ theorem promoteOfAccepted ⟨concrete, hcatalog, hraw, huntrusted, hclosed, hfresh⟩ hwf /-- Validator scope, exact raw ingress, and successful checker evidence -assemble into the K3 result and one trusted-world promotion. In particular, +assemble into the declaration-checking result and one trusted-world promotion. In particular, scope alone cannot promote a declaration, and semantic evidence alone cannot choose a translation for the concrete Ix syntax. -/ theorem checkResultAndPromote @@ -230,7 +230,7 @@ theorem checkResultAndPromote exact ⟨⟨hingress, hevidence⟩, promoteOfAccepted hstate hpending hevidence.accepted⟩ -/-- End-to-end K3 assembly at the standalone validation boundary. The exact +/-- End-to-end declaration-checking assembly at the standalone validation boundary. The exact production validator supplies raw scoping, while checker evidence supplies semantic acceptance; together they produce the pre-translation result and a fresh trusted-world promotion. -/ diff --git a/Ix/Kernel/Verify/Check/BinderRoundTrip.lean b/Ix/Kernel/Verify/Check/BinderRoundTrip.lean index cc6b44acb..88529396e 100644 --- a/Ix/Kernel/Verify/Check/BinderRoundTrip.lean +++ b/Ix/Kernel/Verify/Check/BinderRoundTrip.lean @@ -6,7 +6,7 @@ import Ix.Kernel.Verify.Infer.BinderClosing The Ix.Theory.Named checker closes a freshly opened binder with `FVarsIn.abstract_instantiate1`. Ix uses address-carrying `KExpr` smart -constructors and separate cached walkers, so K3 needs the corresponding pure +constructors and separate cached walkers, so declaration-checking needs the corresponding pure syntax theorem for `instantiateRevSpec` followed by singleton `abstractFVarsSpec`. -/ diff --git a/Ix/Kernel/Verify/Check/BlockAcceptance.lean b/Ix/Kernel/Verify/Check/BlockAcceptance.lean index d0d14584e..579cc85ce 100644 --- a/Ix/Kernel/Verify/Check/BlockAcceptance.lean +++ b/Ix/Kernel/Verify/Check/BlockAcceptance.lean @@ -356,9 +356,8 @@ theorem fresh {trProj : RawProjRel} {world : VerifyWorld} certificate.oracle.fresh ((certificate.memberIff id).2 hid) /-- Commit an oracle-backed block as one exact ghost transaction and one -trusted-log event. This theorem is intentionally semantic: E2 supplies the -future operational proof that a production inductive/recursor block success -constructs this certificate. -/ +trusted-log event. A separate operational proof must construct the certificate +from a successful production inductive/recursor block check. -/ theorem admit {trProj : RawProjRel} {world : VerifyWorld} {block : KId .anon} {members : Array (KId .anon)} {kind : CheckBlockKind} diff --git a/Ix/Kernel/Verify/Check/BlockCache.lean b/Ix/Kernel/Verify/Check/BlockCache.lean index 777a0c4ed..505be6e40 100644 --- a/Ix/Kernel/Verify/Check/BlockCache.lean +++ b/Ix/Kernel/Verify/Check/BlockCache.lean @@ -89,7 +89,7 @@ theorem closeExactBlockSuccess closeBlockSuccess hcaches hle hexact.blockLookup haccepted /-- A stable physical success hit covers every catalog declaration owned by -the exact block. This is the member-level replay theorem used by E0. -/ +the exact block. This is the member-level replay theorem used by block admission. -/ theorem replayCoordinatedMember {semantics : CacheSemantics} {support : RunSupport} {world : VerifyWorld} {env : KEnv .anon} diff --git a/Ix/Kernel/Verify/Check/BlockDefinition.lean b/Ix/Kernel/Verify/Check/BlockDefinition.lean index 573636b84..dfb91e859 100644 --- a/Ix/Kernel/Verify/Check/BlockDefinition.lean +++ b/Ix/Kernel/Verify/Check/BlockDefinition.lean @@ -8,10 +8,10 @@ import Ix.Kernel.Verify.Check.StandaloneDriver The production definition-block branch iterates `checkConstMemberFresh` over the complete array and then publishes the peak DefEq depth. Ix.Theory.Named does -not yet have an atomic mutual-definition declaration, so the constructive E0 +not yet have an atomic mutual-definition declaration, so the constructive block admission bridge is intentionally the singleton specialization. It extracts the -actual member run from `checkClassifiedBlock`, invokes K3 without performing -K3's standalone promotion, and packages that evidence for the enclosing +actual member run from `checkClassifiedBlock`, invokes declaration-checking without performing +the declaration checker's standalone promotion, and packages that evidence for the enclosing atomic block transaction. -/ @@ -47,13 +47,13 @@ theorem checkClassifiedBlock_singleton_definition_success simp [UInt32.max_def] /-- Construct the certified singleton-definition body from the actual -production trace and K3's fixed-world member theorem. Classifier correctness +production trace and the declaration checker's fixed-world member theorem. Classifier correctness is applied to the exact observed classification equation, so no invariant for an unexecuted branch can satisfy it. -`hblocksAfter` is the remaining representation frame for the legacy K1/K2 -invariant, which tracks loaded constants and intern/cache state but predates -E0's explicit block-array agreement layer. -/ +`hblocksAfter` supplies block-array agreement in addition to the reduction, +inference, and conversion invariant, which tracks loaded constants and +intern/cache state. -/ theorem certifySingletonDefinition {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {model : KernelSuffixModel trProj world} @@ -109,8 +109,8 @@ theorem certifySingletonDefinition activePost := ActiveBlockStateWF.ofKernel hevidence.2.1 hblocksAfter evidence := .singletonDefinition hpending hevidence.1 } -/-- Run-scoped singleton-definition certification for the E3-S adapter. -This is the atomic-block analogue of K3's scoped standalone theorem: the +/-- Run-scoped singleton-definition certification for the supported fragment adapter. +This is the atomic-block analogue of the declaration checker's scoped standalone theorem: the member run produces evidence in the original world and retains the finite suffix-model witness, while the enclosing block transaction remains the sole semantic commit point. -/ diff --git a/Ix/Kernel/Verify/Check/BlockIdentity.lean b/Ix/Kernel/Verify/Check/BlockIdentity.lean index b3e6bc8ef..b12fa2c85 100644 --- a/Ix/Kernel/Verify/Check/BlockIdentity.lean +++ b/Ix/Kernel/Verify/Check/BlockIdentity.lean @@ -22,7 +22,7 @@ namespace Ix.Kernel /-! ## Concrete/world block agreement -/ -/-- E0's representation invariant. The existing `TcStateWF` continues to +/-- Block admission's representation invariant. The existing `TcStateWF` continues to separate loaded constants from semantic trust; this layer adds the one-way agreement for lazily loaded block arrays. -/ structure BlockStateWF (trProj : RawProjRel) (s : TcState .anon) @@ -177,7 +177,7 @@ theorem coordinated_trusted {world : VerifyWorld} {block id : KId .anon} end ExactCheckBlock -/-- Global coherence required of E0's immutable inputs: every catalogued +/-- Global coherence required of block admission's immutable inputs: every catalogued declaration which records coordinated ownership has one exact block entry of the same kind. The premise does not trust or type the declaration. -/ def ExactCoordinatedCatalog (world : VerifyWorld) : Prop := @@ -257,7 +257,7 @@ theorem block_targets {blocks : BlockCatalog} {blockAddr primary : Address} exact hprimary /-- `provenTargets` is the exact target array plus the original Muts block -address. This is the extra coverage later consumed by E1; it is not smuggled +address. This is the extra coverage later consumed by serial composition; it is not smuggled into the member array or treated as a trusted declaration. -/ theorem block_provenTargets {blocks : BlockCatalog} {blockAddr primary : Address} {targets : Array Address} diff --git a/Ix/Kernel/Verify/Check/BlockNatFixture.lean b/Ix/Kernel/Verify/Check/BlockNatFixture.lean index f53bbba2d..6126bbfb7 100644 --- a/Ix/Kernel/Verify/Check/BlockNatFixture.lean +++ b/Ix/Kernel/Verify/Check/BlockNatFixture.lean @@ -2,11 +2,11 @@ import Ix.Kernel.Verify.Check.PublicBlocks import Ix.Kernel.Verify.NatFixture /-! -# Concrete Nat block fixture for E0 +# Concrete Nat block fixture for block admission The existing ambient-Nat oracle is instantiated here against an exact physical block table. This fixture exercises the semantic transaction and -the adversarial cache rule without pretending that E2 has already connected +the adversarial cache rule without pretending that inductive certification has already connected the production inductive checker to the oracle. -/ diff --git a/Ix/Kernel/Verify/Check/BlockOracle.lean b/Ix/Kernel/Verify/Check/BlockOracle.lean index 744ae1c60..0c9a32317 100644 --- a/Ix/Kernel/Verify/Check/BlockOracle.lean +++ b/Ix/Kernel/Verify/Check/BlockOracle.lean @@ -4,13 +4,12 @@ import Ix.Kernel.Verify.Inductive.Certificate /-! # Oracle-backed inductive and recursor blocks -E0 proves the transaction and cache ordering around production block checks. -The semantic meaning of a successful inductive/recursor body remains the -explicit E2b boundary: E2b must connect the actual Ix validators and generated -recursor patterns to an `InductiveOracle`. The Ix.Theory.Named -`CertifiedGenerationTransaction` supplies the Theory-owned portion of that -future construction, but cannot determine Ix addresses, member arrays, or -checker execution on its own. +Block admission proves the transaction and cache ordering around production +block checks. Certifying an inductive/recursor body additionally requires a +connection from the Ix validators and generated recursor patterns to an +`InductiveOracle`. The Ix.Theory.Named `CertifiedGenerationTransaction` +supplies the Theory-owned part of that construction; Ix addresses, member +arrays, and checker execution remain separate obligations. This module packages exactly that remaining boundary and ties it to the real classified-body trace. It introduces no unindexed “block succeeded” axiom. @@ -18,8 +17,8 @@ classified-body trace. It introduces no unindexed “block succeeded” axiom. namespace Ix.Kernel -/-- The E2b resources which remain after E0 has fixed the exact physical -array and production classifier kind. The post-state uses temporary block +/-- Semantic resources required after block admission fixes the physical +array and production classifier kind. The post-state uses temporary block authority; it cannot be exposed as a stable success until the oracle's exact member set is atomically admitted. -/ structure OracleBackedBlockResources @@ -35,7 +34,7 @@ structure OracleBackedBlockResources namespace RecM -/-- Package an actual successful inductive/recursor body for E0. The trace, +/-- Package an actual successful inductive/recursor body for block admission. The trace, exact block, active post-state, and oracle all share the same `members` and `kind` indices. -/ theorem certifyOracleBackedBlock diff --git a/Ix/Kernel/Verify/Check/BlockTransaction.lean b/Ix/Kernel/Verify/Check/BlockTransaction.lean index 86a4e96b0..c7641fd77 100644 --- a/Ix/Kernel/Verify/Check/BlockTransaction.lean +++ b/Ix/Kernel/Verify/Check/BlockTransaction.lean @@ -11,10 +11,10 @@ successful verdict. There are exactly two currently supported semantic sources: -* a singleton definition, whose successful K3 result supplies ordinary +* a singleton definition, whose successful declaration-checking result supplies ordinary declaration acceptance; and * an inductive or recursor block, relative to the explicit inductive oracle - which E2 must construct from the corresponding production checker. + which inductive certification must construct from the corresponding production checker. Ix.Theory.Named does not yet expose an atomic mutual-definition declaration, so no constructor below decomposes a multi-definition production block into a @@ -43,8 +43,8 @@ namespace ActiveBlockStateWF /-- Enter temporary block authority from an ordinary stable kernel state. The additional authority does not validate any new cache entry; it only weakens the authority relation under which already-valid entries are viewed. -Exact loaded-block agreement is supplied separately because the legacy K1/K2 -kernel invariant intentionally tracks constants but not block arrays. -/ +Exact loaded-block agreement is supplied separately because the reduction, +inference, and conversion invariant tracks constants but not block arrays. -/ theorem ofKernel {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -93,13 +93,13 @@ end ActiveBlockStateWF /-! ## Semantic evidence tied to one classified array -/ -/-- Semantic evidence admitted by E0. Its indices are the production array +/-- Semantic evidence admitted by block admission. Its indices are the production array and classified kind; this rules out pairing an operational trace with a certificate for a different block shape. -The singleton-definition constructor retains the actual K3 checker result, +The singleton-definition constructor retains the actual declaration checker result, not merely an assumed `VDecl.WF`. The oracle-backed constructor is limited -definitionally to inductive/recursor kinds and remains the named E2 boundary. +definitionally to inductive/recursor kinds and retains the certification premise. -/ inductive BlockAdmissionEvidence (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (block : KId .anon) : diff --git a/Ix/Kernel/Verify/Check/BoundedPipelines.lean b/Ix/Kernel/Verify/Check/BoundedPipelines.lean index 8fd014a12..a280d0812 100644 --- a/Ix/Kernel/Verify/Check/BoundedPipelines.lean +++ b/Ix/Kernel/Verify/Check/BoundedPipelines.lean @@ -6,7 +6,7 @@ import Ix.Kernel.Verify.RecursiveMethods.CallDomains /-! # Bounded standalone-checker pipelines -The legacy K3 checker proof quantified strong full inference over every +The legacy declaration checker proof quantified strong full inference over every expression in one finite `RunSupport`. That is too strong: a successful sort inference places its successor sort in the result footprint, and reusing the same footprint as the next input domain demands an infinite successor tower. @@ -34,8 +34,8 @@ def AdmitsEnsureSortDirect (calls : CallDomain) : KExpr .anon → Prop end CallDomain -/-- Strong K3 inference, restricted to the inference calls admitted at one -finite method-table depth. Unlike ordinary C1A inference, the premise is an +/-- Strong full inference, restricted to the inference calls admitted at one +finite method-table depth. Unlike ordinary bounded inference, the premise is an untyped `PreTrKExprS` and the successful postcondition constructs the typed translation. -/ def FullInferenceWFAtOn @@ -58,7 +58,7 @@ def FullInferenceWFAtOn namespace FullInferenceWFAtOn -/-- Ordinary bounded inference already implies the stronger K3 contract on +/-- Ordinary bounded inference already implies the stronger declaration-checking contract on an input domain whose pretranslations can be upgraded without running the checker. This covers syntax-directed typed leaves such as sorts while retaining the independent inference-policy frame on both outcomes. -/ @@ -307,7 +307,7 @@ private theorem ensureSortDirect_wfAtOn all_goals exact TcM.WF.throw fun _ => trivial -/-- A bounded successful type pipeline constructs the same K3 evidence as +/-- A bounded successful type pipeline constructs the same declaration-checking evidence as the legacy proof, but every method call is justified by the declaration's successor-layer call domain. -/ theorem checkTypePipeline_bounded_sound diff --git a/Ix/Kernel/Verify/Check/CheckConstTransaction.lean b/Ix/Kernel/Verify/Check/CheckConstTransaction.lean index 57dd9c9b0..100f7614f 100644 --- a/Ix/Kernel/Verify/Check/CheckConstTransaction.lean +++ b/Ix/Kernel/Verify/Check/CheckConstTransaction.lean @@ -6,11 +6,12 @@ import Ix.Kernel.Verify.Check.CheckConstExecution This module joins the real top-level dispatcher to exact coordinated-block admission. The success theorem is exhaustive: a routed call yields semantic block acceptance; an unrouted call is returned as the standalone branch -already covered by K3. +already covered by declaration-checking. The body certifier is relative to the remaining checker-specific semantic -source: K3 supplies singleton definitions, while E2 supplies inductive and -recursor oracles. Before invoking it, this module proves that the body's +source: declaration checking supplies singleton-definition evidence; +inductive certification supplies inductive and recursor oracles. Before +invoking it, this module proves that the body's second block lookup and classifier selected the same ordered members and kind as the route. Thus the certifier cannot be applied to a TOCTOU-substituted block. @@ -18,7 +19,7 @@ block. namespace Ix.Kernel -/-- Stable kernel state plus E0's physical/ghost block-table agreement. -/ +/-- Stable kernel state plus block admission's physical/ghost block-table agreement. -/ structure CoordinatedKernelStateWF (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (state : TcState .anon) : Prop where @@ -38,7 +39,7 @@ end CoordinatedKernelStateWF /-- Exhaustive semantic disposition of a successful production call. The standalone constructor is intentionally operational: its semantic result is -the existing K3 theorem, with declaration-specific premises. -/ +the existing declaration-checking theorem, with declaration-specific premises. -/ inductive CheckConstSuccessDisposition (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (methods : Methods .anon) diff --git a/Ix/Kernel/Verify/Check/CheckerEvidence.lean b/Ix/Kernel/Verify/Check/CheckerEvidence.lean index 7dc5c6ad8..02664b721 100644 --- a/Ix/Kernel/Verify/Check/CheckerEvidence.lean +++ b/Ix/Kernel/Verify/Check/CheckerEvidence.lean @@ -6,7 +6,7 @@ import Ix.Kernel.Verify.Check.FullInferenceCache This module connects the two sequential computation fragments used by `checkConstMember` to the declaration-local evidence consumed by acceptance. -The inference premise is K3's stronger full-mode contract: it starts from a +The inference premise is the declaration checker's stronger full-mode contract: it starts from a raw pretranslation and establishes the typed structural translation itself. The value pipeline is parameterized by the semantic contract for the actual diff --git a/Ix/Kernel/Verify/Check/DeclarationValidation.lean b/Ix/Kernel/Verify/Check/DeclarationValidation.lean index 68824d8c1..af934dbd6 100644 --- a/Ix/Kernel/Verify/Check/DeclarationValidation.lean +++ b/Ix/Kernel/Verify/Check/DeclarationValidation.lean @@ -6,7 +6,7 @@ import Ix.Kernel.Verify.Check.DeclarationIngress This module lifts expression-validator soundness to the production `validateConstWellScoped` boundary for the standalone declaration kinds -handled by K3. Finite-run coverage and no-wrap size budgets are explicit +handled by declaration-checking. Finite-run coverage and no-wrap size budgets are explicit resources; neither is inferred from a successful validator return. -/ diff --git a/Ix/Kernel/Verify/Check/FullInference.lean b/Ix/Kernel/Verify/Check/FullInference.lean index 197c96b91..e685a8a0f 100644 --- a/Ix/Kernel/Verify/Check/FullInference.lean +++ b/Ix/Kernel/Verify/Check/FullInference.lean @@ -4,8 +4,8 @@ import Ix.Kernel.Verify.Infer.CacheSoundness /-! # Full inference from untyped checker ingress -The ordinary K2 contract starts from `TrKExprS`, which already contains the -typing facts checked by full inference. K3 instead starts from +The ordinary inference contract starts from `TrKExprS`, which already contains +the typing facts checked by full inference. Declaration checking starts from `PreTrKExprS` and must return the missing typed translation together with the usual inference result. @@ -31,7 +31,7 @@ def FullInferPost (trProj : RawProjRel) (world : VerifyWorld) namespace FullInferPost -/-- Strengthen the ordinary K2 inference post once the current source has +/-- Strengthen the ordinary inference post once the current source has independently been upgraded to a typed structural translation. -/ theorem of_typed {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} diff --git a/Ix/Kernel/Verify/Check/FullInferenceApplications.lean b/Ix/Kernel/Verify/Check/FullInferenceApplications.lean index 263823f25..263114b41 100644 --- a/Ix/Kernel/Verify/Check/FullInferenceApplications.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceApplications.lean @@ -4,12 +4,12 @@ import Ix.Kernel.Verify.Check.InferencePolicy /-! # Full inference for applications -K2 proves application inference from an already typed `TrKExprS` source. +The ordinary application-inference proof starts from a typed `TrKExprS` source. That premise is circular at checker ingress: the application constructor of `TrKExprS` already says that the function and argument have compatible types. -This file proves the corresponding K3 branch from `PreTrKExprS`. Its +This file proves the corresponding declaration-checking branch from `PreTrKExprS`. Its callback context deliberately records the additional operational fact needed by full checking: recursive inference, Pi exposure, and DefEq all restore `inferOnly = false`, including on partial errors. The later concrete-knot @@ -23,7 +23,7 @@ open Ix.Theory.Named (VExpr) /-- Strong recursive services used while reconstructing a typed translation from successful full inference. These are properties of one concrete -smaller method table, rather than consequences of the ordinary K2 method +smaller method table, rather than consequences of the ordinary inference/conversion method contract. -/ structure FullInferenceStepContext (semantics : CacheSemantics) (trProj : RawProjRel) @@ -84,9 +84,9 @@ structure FullInferenceStepContext namespace FullInferenceStepContext -/-- Assemble the strong K3 callback record from independent semantic proofs +/-- Assemble the strong declaration-checking callback record from independent semantic proofs and the outcome-sensitive operational policy frame. The separation matters: -ordinary K2 soundness does not mention `inferOnly`, while the policy audit +ordinary inference/conversion soundness does not mention `inferOnly`, while the policy audit does not claim typing. -/ theorem of_semantic_and_policy {semantics : CacheSemantics} {trProj : RawProjRel} @@ -243,7 +243,7 @@ private theorem throwApplicationMismatch_full_wf exact hrec methods hmethods /-- Semantic reconstruction for a fully checked application. In contrast -to K2's application lemma, argument compatibility is obtained from the +to the typed application's inference lemma, argument compatibility is obtained from the actual recursive inference and true DefEq result, not from the source translation premise. -/ private theorem fullApplicationResult @@ -342,7 +342,7 @@ private theorem finishFullApplication_wf /-- The full-mode application branch, starting from an untyped structural translation. This theorem is deliberately indexed by one concrete smaller -method table and its stronger K3 callback context. -/ +method table and its stronger declaration-checking callback context. -/ theorem inferUncached_app_full_wf {alpha : Type} {initial : TcState .anon} {program : TcM .anon alpha} {requests : List WalkerRequest} {support : RunSupport} diff --git a/Ix/Kernel/Verify/Check/FullInferenceBinders.lean b/Ix/Kernel/Verify/Check/FullInferenceBinders.lean index 6000b42af..1bbfee7ad 100644 --- a/Ix/Kernel/Verify/Check/FullInferenceBinders.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceBinders.lean @@ -9,8 +9,8 @@ open Ix.Theory (VLevel) /-! # Full inference for binding forms -K2's lambda and forall proofs assume the complete source translation is -already typed. These K3 branches instead start from `PreTrKExprS`, validate +The ordinary lambda and forall inference proofs assume a typed source +translation. These full-inference branches start from `PreTrKExprS`, validate the domain, infer the freshly opened body, and close its newly established typed translation back to the original de Bruijn syntax. -/ diff --git a/Ix/Kernel/Verify/Check/FullInferenceCache.lean b/Ix/Kernel/Verify/Check/FullInferenceCache.lean index 17d4a6c3e..9355a9be2 100644 --- a/Ix/Kernel/Verify/Check/FullInferenceCache.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceCache.lean @@ -4,10 +4,10 @@ import Ix.Kernel.Verify.Infer.CacheSoundness /-! # Full-inference cache shell -The K3 uncached dispatcher establishes a typed source translation from +The full-inference uncached dispatcher establishes a typed source translation from `PreTrKExprS`. This module closes the production `inferWith` cache shell around that result. Full-cache hits are reconciled with the current raw -translation; misses construct ordinary collision-robust K2 provenance before +translation; misses construct ordinary collision-robust inference/conversion provenance before writing the validated cache partition. -/ @@ -37,7 +37,7 @@ private theorem cacheReferences · exact context.base.references hty hresult /-- Execute a full-mode cache miss and install its result only after the -typed source translation has supplied ordinary K2 inference provenance. +typed source translation has supplied ordinary inference provenance. Both the uncached body and the cache write preserve full mode on errors. -/ private theorem missTail_full_wf {alpha : Type} {initial : TcState .anon} {program : TcM .anon alpha} @@ -95,7 +95,7 @@ namespace RecM /-- Complete production `inferWith` in full mode from untyped structural ingress. A hit upgrades the current raw translation from cache provenance; -a miss runs the exhaustive K3 dispatcher and writes validated provenance. -/ +a miss runs the exhaustive full-inference dispatcher and writes validated provenance. -/ theorem inferWith_full_wf {alpha : Type} {initial : TcState .anon} {program : TcM .anon alpha} {requests : List WalkerRequest} {trProj : RawProjRel} diff --git a/Ix/Kernel/Verify/Check/FullInferenceDispatcher.lean b/Ix/Kernel/Verify/Check/FullInferenceDispatcher.lean index 0e0549307..1a0097058 100644 --- a/Ix/Kernel/Verify/Check/FullInferenceDispatcher.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceDispatcher.lean @@ -4,8 +4,8 @@ import Ix.Kernel.Verify.Infer.Dispatcher /-! # Exhaustive full-mode inference dispatcher -This module assembles the constructor-local K3 proofs for -`inferUncached inferCall false`. Unlike the K2 dispatcher, its input is only +This module assembles the constructor-local declaration-checking proofs for +`inferUncached inferCall false`. Unlike the inference/conversion dispatcher, its input is only `PreTrKExprS`; successful execution establishes the missing typed source translation as part of `FullInferPost`. @@ -19,7 +19,7 @@ namespace Ix.Kernel namespace FullUncachedInference /-- Resources for one full-mode layer over a fixed smaller method table. -`uncachedPolicy` covers the leaf actions reused from K2, while +`uncachedPolicy` covers the leaf actions reused from inference/conversion, while `projectionPolicy` exposes the corresponding frame for the projection helper itself. Both are purely operational obligations to be discharged by the concrete policy closure proof. -/ @@ -69,7 +69,7 @@ private theorem strengthenFullLeaf · intro _ _ post exact post.1 -/-- Exhaustive K3 correctness of `inferUncached` in full mode. Every syntax +/-- Exhaustive declaration-checking correctness of `inferUncached` in full mode. Every syntax constructor is covered from untyped structural ingress, and both outcomes retain `inferOnly = false`. -/ theorem inferUncached_full_wf diff --git a/Ix/Kernel/Verify/Check/FullInferenceKnot.lean b/Ix/Kernel/Verify/Check/FullInferenceKnot.lean index b6eedb221..77f888682 100644 --- a/Ix/Kernel/Verify/Check/FullInferenceKnot.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceKnot.lean @@ -5,8 +5,8 @@ import Ix.Kernel.Verify.RecursiveMethods.Closure /-! # Full-inference closure of the production recursion knot -K2 closes the ordinary six-field semantic contract from an already typed -source. K3 needs a stronger contract for the inference field: when the +The ordinary six-field semantic contract assumes a typed source. +Declaration checking needs a stronger inference contract: when the caller is in full mode, successful inference must construct the typed source translation from `PreTrKExprS`, and both success and partial errors must restore full mode. @@ -21,8 +21,8 @@ namespace Ix.Kernel namespace Methods -/-- Strong K3 contract for the inference field of one fixed method table. -Unlike ordinary K2 inference, this starts from untyped structural ingress and +/-- Strong declaration-checking contract for the inference field of one fixed method table. +Unlike ordinary inference, this starts from untyped structural ingress and records the full-mode frame on both outcomes. -/ def FullInferenceWFAt (semantics : CacheSemantics) (trProj : RawProjRel) @@ -101,7 +101,7 @@ def fullInferenceContext · exact ProjectionInference.preservesInferOnlyAt methods hpolicy hnextPolicy.whnf -/-- One unfolded production inference layer satisfies K3 whenever its +/-- One unfolded production inference layer satisfies the full-mode contract whenever its strictly smaller callback table satisfies the three independent premises. -/ theorem next_fullInferenceWFAt {alpha : Type} {initial : TcState .anon} {program : TcM .anon alpha} diff --git a/Ix/Kernel/Verify/Check/FullInferenceLeaves.lean b/Ix/Kernel/Verify/Check/FullInferenceLeaves.lean index 46d13aafe..dc7af501d 100644 --- a/Ix/Kernel/Verify/Check/FullInferenceLeaves.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceLeaves.lean @@ -6,9 +6,9 @@ open Ix.Theory (VLevel) # Full inference for untyped leaf ingress The leaf constructors of `PreTrKExprS` already contain every premise of the -corresponding `TrKExprS` constructor. They therefore reuse the completed K2 +corresponding `TrKExprS` constructor. They therefore reuse the ordinary inference operational proofs directly and strengthen only the postcondition. The -application and binder constructors remain genuinely new K3 work because +application and binder constructors require separate full-inference proofs because their typed constructors contain the checks full inference must establish. -/ diff --git a/Ix/Kernel/Verify/Check/FullInferenceProjections.lean b/Ix/Kernel/Verify/Check/FullInferenceProjections.lean index cfe360bb4..ade2a4fee 100644 --- a/Ix/Kernel/Verify/Check/FullInferenceProjections.lean +++ b/Ix/Kernel/Verify/Check/FullInferenceProjections.lean @@ -4,8 +4,8 @@ import Ix.Kernel.Verify.Infer.ProjectionTypes /-! # Full inference for projections -The K2 projection branch starts from a typed `TrKExprS` source. At checker -ingress K3 instead has only `PreTrKExprS`: it first establishes a typed +The ordinary projection-inference branch starts from a typed `TrKExprS` source. +At checker ingress only `PreTrKExprS` is available: full inference establishes a typed translation for the projected value, then delegates to the already verified `inferProj` helper. @@ -27,7 +27,7 @@ def PreservesInferOnlyAt (methods : Methods .anon) : Prop := ∀ structId field val valTy, ((RecM.inferProj structId field val valTy).run methods).PreservesInferOnly -/-- Strong projection-helper contract needed by K3 full inference. It is +/-- Strong projection-helper contract needed by full inference. It is fixed to the smaller production method table and retains full mode on both success and error. -/ def FullWFAt (semantics : CacheSemantics) (trProj : RawProjRel) @@ -50,9 +50,9 @@ def FullWFAt (semantics : CacheSemantics) (trProj : RawProjRel) InferPost trProj world uvars Delta projectedV result) (fun _ after => after.inferOnly = false) -/-- Combine K2 projection soundness with the independent full-mode frame. +/-- Combine projection-inference soundness with the independent full-mode frame. This is the only adapter from the ordinary, method-parametric projection -contract to K3's fixed-table contract. -/ +contract to the declaration checker's fixed-table contract. -/ theorem FullWFAt.of_semantic_and_policy {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} diff --git a/Ix/Kernel/Verify/Check/InferencePolicy.lean b/Ix/Kernel/Verify/Check/InferencePolicy.lean index cba828a38..1441a0aaa 100644 --- a/Ix/Kernel/Verify/Check/InferencePolicy.lean +++ b/Ix/Kernel/Verify/Check/InferencePolicy.lean @@ -7,7 +7,7 @@ import Ix.Kernel.Verify.Whnf.StructEta.RecursionClassifier # Inference-policy frames Full inference is selected by the mutable `TcState.inferOnly` bit. The -ordinary K1/K2 semantic contracts intentionally ignore operational flags, so +ordinary reduction, inference, and conversion semantic contracts intentionally ignore operational flags, so they cannot by themselves justify that a recursive callback which starts in full mode returns in full mode. @@ -421,7 +421,7 @@ theorem withInferOnly (x : TcM .anon alpha) : cases x {before with inferOnly := true} <;> rfl /-- Combine an existing semantic Hoare proof with an independent policy -frame. This is the adapter used by K3 callback contexts. -/ +frame. This is the adapter used by declaration-checking callback contexts. -/ theorem strengthenWF {I : TcState .anon → Prop} {before : TcState .anon} {x : TcM .anon alpha} {Q : alpha → TcState .anon → Prop} @@ -642,8 +642,8 @@ theorem methodsN_preservesInferOnly simpa [Methods.methodsN_succ, Nat.succ_eq_add_one] using hclosed (methodsN n) ih -/-- The ordinary K2 DefEq contract plus its independent operational frame is -exactly the strong DefEq callback required by K3 full inference. -/ +/-- The ordinary DefEq contract plus its independent operational frame is +exactly the strong DefEq callback required by full inference. -/ theorem PreservesInferOnly.isDefEq_full_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} diff --git a/Ix/Kernel/Verify/Check/MemberEvidence.lean b/Ix/Kernel/Verify/Check/MemberEvidence.lean index 33589ff34..84a3fa286 100644 --- a/Ix/Kernel/Verify/Check/MemberEvidence.lean +++ b/Ix/Kernel/Verify/Check/MemberEvidence.lean @@ -439,7 +439,7 @@ theorem checkConstMember_validation_success cases validationValue exact ⟨afterValidation, rfl⟩ -/-- End-to-end member-level K3 result from an untyped pending declaration. +/-- End-to-end member-level declaration-checking result from an untyped pending declaration. Successful production validation constructs the pretranslation; successful checking constructs semantic evidence; the pure acceptance layer then promotes exactly the pending target in the ghost world. -/ diff --git a/Ix/Kernel/Verify/Check/PositiveFuelSort.lean b/Ix/Kernel/Verify/Check/PositiveFuelSort.lean index 39cc0d1be..493a4020e 100644 --- a/Ix/Kernel/Verify/Check/PositiveFuelSort.lean +++ b/Ix/Kernel/Verify/Check/PositiveFuelSort.lean @@ -6,8 +6,8 @@ import Ix.Kernel.Verify.ScopedSuffix.ClosedContext /-! # Positive-fuel bounded checker witness -This fixture instantiates the corrected C1A/K3 interfaces at recursion fuel -one. Its method-call domain contains exactly one closed sort inference; its +This fixture instantiates bounded method and declaration-checking contracts +at recursion fuel one. Its call domain contains one closed sort inference; its finite result footprint contains that source and its successor-sort result. The joint suffix model remains an explicit semantic parameter, but the call schedule, syntax, reduction of collision freedom to two exact digest @@ -124,7 +124,7 @@ def theory (uvars : Nat) : /-! ## Concrete run-scoped suffix instance -/ -/-- K2S's production suffix model for this closed fixture. Unlike the +/-- Scoped production suffix model for this closed fixture. Unlike the legacy theorems below, this value contains only the singleton normalized context input reached by the run. -/ def scopedModel : ScopedKernelSuffixModel RawProjRel.none VerifyWorld.empty := @@ -268,7 +268,7 @@ theorem scheduleAtFuelOne Methods.SortSchedule.two (support_collisionFree separation) source_supported result_supported (theory model.keys.uvars) trustedReferences -/-- Concrete C1A contract for the outer production body at fuel one. Its +/-- Concrete bounded method contract for the outer production body at fuel one. Its only admitted method call is inference of `source`. -/ theorem methodContractAtFuelOne (separation : AddressSeparation) @@ -281,7 +281,7 @@ theorem methodContractAtFuelOne simpa [Methods.SortSchedule.calls] using (scheduleAtFuelOne separation model).nextSelected -/-- Concrete strong K3 inference contract obtained from the bounded C1A +/-- Concrete strong full inference contract obtained from the bounded method contract because sort pretranslation is already typed. -/ theorem fullInferenceAtFuelOne (separation : AddressSeparation) @@ -296,7 +296,7 @@ theorem fullInferenceAtFuelOne (Methods.next_preservesInferOnly _ (Methods.methodsN_concrete_preservesInferOnly 1)) -/-- Declaration-local K3 pipeline resources at fuel one. The type pipeline +/-- Declaration-local pipeline resources at fuel one. The type pipeline admits one sort inference and no WHNF/DefEq callback. -/ def pipelinesAtFuelOne (separation : AddressSeparation) @@ -310,7 +310,7 @@ def pipelinesAtFuelOne def concreteAxiom : KConst .anon := .axio () () false 0 source -/-- The concrete sort axiom is covered by the positive-fuel K3 resources. -/ +/-- The concrete sort axiom is covered by the positive-fuel declaration-checking resources. -/ theorem pipelines_cover_concreteAxiom (separation : AddressSeparation) (model : KernelSuffixModel RawProjRel.none VerifyWorld.empty) : diff --git a/Ix/Kernel/Verify/Check/PreTranslationScopes.lean b/Ix/Kernel/Verify/Check/PreTranslationScopes.lean index d1bf29d5c..822ef8b4a 100644 --- a/Ix/Kernel/Verify/Check/PreTranslationScopes.lean +++ b/Ix/Kernel/Verify/Check/PreTranslationScopes.lean @@ -7,7 +7,7 @@ import Ix.Kernel.Verify.Infer.LetScopes # Binder scopes for pre-typed checker ingress The ordinary inference scope theorem assumes the binder body already has a -typed `TrKExprS` witness. K3 cannot make that assumption: full inference is +typed `TrKExprS` witness. Declaration checking cannot make that assumption: full inference is the operation which must construct the witness. This wrapper combines the factored operational binder-opening core with `PreTrKExprS.openFVarZero` and the independent inference-policy frame. @@ -138,7 +138,7 @@ end TcM namespace RecM /-- Scope a pre-translated binder around one fixed recursive method table. -Unlike the ordinary K2 scope rule, the body need not be typed before the +Unlike the ordinary inference/conversion scope rule, the body need not be typed before the continuation runs: the continuation receives its exact opened pre-translation and may establish typing by recursive full inference. -/ theorem withLctxScope_openBinder_pre_wf diff --git a/Ix/Kernel/Verify/Check/PublicBlocks.lean b/Ix/Kernel/Verify/Check/PublicBlocks.lean index 3817f3e11..48393fc4a 100644 --- a/Ix/Kernel/Verify/Check/PublicBlocks.lean +++ b/Ix/Kernel/Verify/Check/PublicBlocks.lean @@ -6,7 +6,7 @@ import Ix.Kernel.Verify.Check.QuotientBoundary /-! # Public coordinated-block checker theorem -This is E0's stable public import frontier. It instantiates the recursive +This is block admission's stable public import frontier. It instantiates the recursive driver with the exact finite method table chosen by `TcM.runRec` and crosses the public error-isolation wrapper. Successful isolation is transparent, so the semantic disposition is indexed by the public checker's exact final @@ -19,8 +19,8 @@ namespace TcM.checkConst /-- A successful public checker call either atomically accepts the exact routed block or executes the separately verified standalone branch. The -coordinated body certifier is explicitly relative to K3 singleton-definition -evidence or E2's inductive/recursor oracle resources. -/ +coordinated body certifier is explicitly relative to declaration-checking singleton-definition +evidence or inductive/recursor oracle resources. -/ theorem blockDisposition {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} diff --git a/Ix/Kernel/Verify/Check/PublicStandalone.lean b/Ix/Kernel/Verify/Check/PublicStandalone.lean index dae7ce08d..e0b98c862 100644 --- a/Ix/Kernel/Verify/Check/PublicStandalone.lean +++ b/Ix/Kernel/Verify/Check/PublicStandalone.lean @@ -4,13 +4,13 @@ import Ix.Kernel.Verify.RecursiveMethods.Public /-! # Public standalone constant checking -The member and driver proofs establish K3 for a fixed method table. This +The member and driver proofs establish declaration-checking for a fixed method table. This module instantiates that table with the exact finite approximation selected by production `TcM.runRec`, and then crosses `isolateCheckErrors`. The latter is transparent on success, so the certified final state is exactly the state returned by the public checker. -Whole-block coordination remains the separately named E0 boundary. The +Whole-block coordination remains the separately named block admission boundary. The theorem below therefore requires `StandaloneRoute`; axioms discharge it definitionally, while standalone definitions may supply a finite routing proof for their concrete block environment. @@ -60,7 +60,7 @@ theorem rollback_preserves_kernel hbefore.restoreCheckCachesOnError hfailedCore hfailedIntern⟩ /-- Successful public checking of a pending standalone declaration produces -the concrete K3 acceptance result and promotes exactly that declaration into +the concrete declaration-checking acceptance result and promotes exactly that declaration into a trusted ghost world. The recursive callbacks and the stronger checker inference pipeline are both restricted to the successor-layer call domain selected by the finite production schedule. -/ @@ -209,7 +209,7 @@ theorem wf /-- An intrinsically ill-typed pending standalone declaration cannot be accepted by the public checker. The contradiction uses the raw pending -translation and freshness to turn K3's successful semantic evidence into the +translation and freshness to turn the declaration checker's successful semantic evidence into the forbidden Theory declaration transition; no typing fact is assumed at ingress. -/ theorem rejected_of_no_decl_wf @@ -260,7 +260,7 @@ theorem rejected_of_no_decl_wf hfresh⟩ := hpending exact False.elim <| hnotWF (hraw.wfOfAccepted hfresh hresult.1.accepted) -/-- Axioms take the standalone route by definition, so their public K3 +/-- Axioms take the standalone route by definition, so their public declaration-checking theorem has no residual block-coordination premise. -/ theorem axiom_pending_sound {before : TcState .anon} {id : KId .anon} diff --git a/Ix/Kernel/Verify/Check/QuotientBoundary.lean b/Ix/Kernel/Verify/Check/QuotientBoundary.lean index 1ea1fb437..e868282b9 100644 --- a/Ix/Kernel/Verify/Check/QuotientBoundary.lean +++ b/Ix/Kernel/Verify/Check/QuotientBoundary.lean @@ -12,7 +12,7 @@ member where it is observed. The semantic catalog relation likewise has no coordinated quotient constructor. Quotient acceptance therefore uses the separate four-check atomic bridge; it -never acquires inductive-oracle or block-cache authority through E0. +never acquires inductive-oracle or block-cache authority through block admission. -/ namespace Ix.Kernel @@ -91,7 +91,7 @@ end Catalog namespace StandaloneRoute /-- Quotient declarations take the operational standalone branch, while -their semantic acceptance remains deliberately outside K3/E0. -/ +their semantic acceptance is outside these standalone and block-admission theorems. -/ theorem quotientRoute (I : TcState .anon → Prop) (methods : Methods .anon) (name : Mode.anon.F Name) (levelParams : Mode.anon.F (Array Name)) diff --git a/Ix/Kernel/Verify/Check/SafetyFrame.lean b/Ix/Kernel/Verify/Check/SafetyFrame.lean index 816416774..85544605c 100644 --- a/Ix/Kernel/Verify/Check/SafetyFrame.lean +++ b/Ix/Kernel/Verify/Check/SafetyFrame.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Check.ValidatorFrame /-! # State framing for the unsafe-reference traversal -`checkNoUnsafeRefs` is semantically a safety guard. For K3 its important +`checkNoUnsafeRefs` is semantically a safety guard. For declaration-checking its important operational property is that the iterative expression walk changes checker state only through optional constant lookup. Consequently every outcome preserves any invariant framed by the installed lazy-ingress hook. diff --git a/Ix/Kernel/Verify/Check/Scoped.lean b/Ix/Kernel/Verify/Check/Scoped.lean index 9f4ced707..7ae9d0ad6 100644 --- a/Ix/Kernel/Verify/Check/Scoped.lean +++ b/Ix/Kernel/Verify/Check/Scoped.lean @@ -6,7 +6,7 @@ open Ix.Theory (VLevel) /-! # Successful well-scopedness validation -`PendingDecl` deliberately permits raw, ill-scoped syntax. K3 therefore +`PendingDecl` deliberately permits raw, ill-scoped syntax. Declaration checking therefore cannot assume universe-parameter or de Bruijn bounds when it starts checking a declaration: those facts have to be recovered from the successful production `validateExprWellScoped` pass. diff --git a/Ix/Kernel/Verify/Check/ScopedActiveBlock.lean b/Ix/Kernel/Verify/Check/ScopedActiveBlock.lean index 4768295e6..73c10e0a0 100644 --- a/Ix/Kernel/Verify/Check/ScopedActiveBlock.lean +++ b/Ix/Kernel/Verify/Check/ScopedActiveBlock.lean @@ -20,7 +20,7 @@ can consume the active-member disjunct. namespace Ix.Kernel -/-- The complete K1/K2 state invariant while one exact coordinated block is +/-- The complete reduction, inference, and conversion state invariant while one exact coordinated block is active, refined by membership in a finite suffix-model state domain. -/ structure ScopedActiveWhnfStateInv {trProj : RawProjRel} {world : VerifyWorld} @@ -121,7 +121,7 @@ theorem of_internSemanticFrame /-- Changing only operational bookkeeping fields preserves the complete active scoped invariant. The suffix-domain frame is separate from the semantic-state equations because context-digest scope also observes memo and -fault fields which ordinary K1 cache provenance intentionally ignores. -/ +fault fields which ordinary WHNF cache provenance intentionally ignores. -/ theorem of_semantic_fields_eq {trProj : RawProjRel} {world : VerifyWorld} {model : ScopedKernelSuffixModel trProj world} diff --git a/Ix/Kernel/Verify/Check/ScopedBoundedPipelines.lean b/Ix/Kernel/Verify/Check/ScopedBoundedPipelines.lean index b81ed4d73..7b2f4c650 100644 --- a/Ix/Kernel/Verify/Check/ScopedBoundedPipelines.lean +++ b/Ix/Kernel/Verify/Check/ScopedBoundedPipelines.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Run-scoped standalone-checker pipelines -This is K3's bounded type/value pipeline with `StateInScope` retained across +This is the declaration checker's bounded type/value pipeline with `StateInScope` retained across every method callback. It deliberately consumes `Methods.ScopedWFAtOn` directly and contains no conversion to the legacy global suffix model. -/ @@ -38,7 +38,7 @@ def ScopedFullInferenceWFAtOn namespace ScopedFullInferenceWFAtOn -/-- Ordinary scoped inference upgrades to the K3 contract wherever raw +/-- Ordinary scoped inference upgrades to the declaration-checking contract wherever raw ingress is intrinsically typed. -/ theorem ofTypedIngress {trProj : RawProjRel} {world : VerifyWorld} @@ -88,7 +88,7 @@ end ScopedFullInferenceWFAtOn end Methods -/-- Declaration-local K3 resources whose method contracts preserve the +/-- Declaration-local resources whose method contracts preserve the finite suffix-state witness. -/ structure ScopedStandalonePipelineResources {trProj : RawProjRel} {world : VerifyWorld} diff --git a/Ix/Kernel/Verify/Check/ScopedPositiveFuelCertificate.lean b/Ix/Kernel/Verify/Check/ScopedPositiveFuelCertificate.lean index bb9f4a65c..58067dc8d 100644 --- a/Ix/Kernel/Verify/Check/ScopedPositiveFuelCertificate.lean +++ b/Ix/Kernel/Verify/Check/ScopedPositiveFuelCertificate.lean @@ -299,7 +299,7 @@ theorem runAssumptions (separation : AddressSeparation) : ⟨by simpa [requests] using public_requests separation, support_collisionFree separation, request_coverage, request_bounds⟩ -/-- The complete K2S public-run package for a real fuel-one checker +/-- The complete scoped method public-run package for a real fuel-one checker execution. Its method-call schedule and its suffix-state domain are both finite, but deliberately separate: the call domain contains the source sort, while the run support also contains the constructed successor sort. -/ diff --git a/Ix/Kernel/Verify/Check/SingletonInductive.lean b/Ix/Kernel/Verify/Check/SingletonInductive.lean index 4e0679e3c..059dd873f 100644 --- a/Ix/Kernel/Verify/Check/SingletonInductive.lean +++ b/Ix/Kernel/Verify/Check/SingletonInductive.lean @@ -6,9 +6,9 @@ import Ix.Kernel.Verify.Inductive.SingletonOracle /-! # Certificate-backed singleton family blocks -E0 fixes the exact physical block, classifier, execution trace, and active +Block admission fixes the exact physical block, classifier, execution trace, and active post-state. `SingletonFamilyCatalogLink` fixes the same member array and -constructs its semantic oracle from the E2a transaction. This module joins +constructs its semantic oracle from the certified generation transaction. This module joins those independently audited indices, so a successful production family block does not need an additional ambient inductive oracle. @@ -22,7 +22,7 @@ namespace Ix.Kernel namespace SingletonFamilyCatalogLink /-- The exact family/constructor link supplies all oracle-backed resources -for an E0 inductive-block trace. -/ +for an inductive-block admission trace. -/ def blockResources {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -72,7 +72,7 @@ end SingletonRecursorCatalogLink namespace RecM /-- Certify one actual successful singleton family/constructor block by -combining E0's exact trace with E2a/E2b's exact catalog link. -/ +combining block admission's exact trace with the certified singleton catalog link. -/ theorem certifySingletonFamilyBlock {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} @@ -91,7 +91,7 @@ theorem certifySingletonFamilyBlock certifyOracleBackedBlock trace hexact (link.blockResources activePost) /-- Certify one actual successful singleton enumeration recursor block by -combining E0's exact trace with E2a/E2b's generated-rule correspondence. -/ +combining block admission's exact trace with the certified singleton generated-rule correspondence. -/ theorem certifySingletonRecursorBlock {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} @@ -221,7 +221,7 @@ theorem certifySingletonRecursorIngressBlock /-- Join one actual anonymous family-block ingress execution to one actual successful production checker-body execution. The semantic catalog link is constructed internally from the conversion interpretation, publication -trace, loaded-catalog invariant, trusted log, and E2a transaction. -/ +trace, loaded-catalog invariant, trusted log, and certified generation transaction. -/ theorem certifySingletonFamilyIngressExecution {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {methods : Methods .anon} @@ -255,7 +255,7 @@ theorem certifySingletonFamilyIngressExecution /-- Join one actual anonymous recursor-block ingress execution to one actual successful production recursor checker-body execution. Positional generated -equation and iota-pattern facts remain derived from the E2a certificate and +equation and iota-pattern facts remain derived from the certified generation certificate and the supported enumeration shape. -/ theorem certifySingletonRecursorIngressExecution {semantics : CacheSemantics} {trProj : RawProjRel} diff --git a/Ix/Kernel/Verify/Check/StandaloneDriver.lean b/Ix/Kernel/Verify/Check/StandaloneDriver.lean index 5e4f707c1..6abd32a65 100644 --- a/Ix/Kernel/Verify/Check/StandaloneDriver.lean +++ b/Ix/Kernel/Verify/Check/StandaloneDriver.lean @@ -12,7 +12,7 @@ changing which pending declaration is certified. namespace Ix.Kernel -/-- Operational boundary separating K3 standalone checking from E0 block +/-- Operational boundary separating standalone declaration checking from block coordination. The exact production router must preserve the checker invariant and select no coordinated block. This condition is definitionally inhabited for axioms; definition-family instances are discharged when their @@ -203,7 +203,7 @@ theorem checkConstMemberFresh_pending_evidence /-- Lift the fresh-member theorem through the exact standalone branch of `RecM.checkConst`. The first required lookup and router are both executed -before the production reset; `StandaloneRoute` makes the E0 boundary +before the production reset; `StandaloneRoute` makes the block admission boundary explicit and rules out silently treating block acceptance as member acceptance. -/ theorem checkConst_standalone_pending_sound diff --git a/Ix/Kernel/Verify/Check/ValidatorFrame.lean b/Ix/Kernel/Verify/Check/ValidatorFrame.lean index adee2bc3b..27cf4caf9 100644 --- a/Ix/Kernel/Verify/Check/ValidatorFrame.lean +++ b/Ix/Kernel/Verify/Check/ValidatorFrame.lean @@ -286,7 +286,7 @@ theorem validateExprWellScoped_frame /-- Standalone declaration validation preserves the checker invariant on both outcomes. The resource witness restricts this theorem to the axiom and -definition shapes owned by K3. -/ +definition shapes owned by declaration-checking. -/ theorem validateConstWellScoped_frame {support : RunSupport} {c : KConst .anon} (hresources : StandaloneValidationResources support c) diff --git a/Ix/Kernel/Verify/Ctx.lean b/Ix/Kernel/Verify/Ctx.lean index 6cc948568..6fbce5403 100644 --- a/Ix/Kernel/Verify/Ctx.lean +++ b/Ix/Kernel/Verify/Ctx.lean @@ -39,8 +39,8 @@ equations) so they are robust to record-update spelling; the pop lemmas require the Δ-head to be the popped `(none, d)` entry — Δ is per-call ghost data, so the soundness layers always know the head form at a pop site (popping under live newer fvars would be a scoping bug and is -deliberately unrepresentable). K0 has replaced the `truncate` and -`restoreDepth` `while` loops with explicit Nat recursion; their exact +deliberately unrepresentable). The `truncate` and `restoreDepth` loops use +explicit Nat recursion; their exact production equations live in `Verify/Totalization`. Preservation lemmas for `CtxRecon` over more than one pop remain part of the checker-soundness layer. -/ diff --git a/Ix/Kernel/Verify/Decl.lean b/Ix/Kernel/Verify/Decl.lean index 0d46a008d..b3f583445 100644 --- a/Ix/Kernel/Verify/Decl.lean +++ b/Ix/Kernel/Verify/Decl.lean @@ -8,8 +8,8 @@ open Ix.Theory (VLevel) /-! # Raw, pending, and trusted declarations -This is the additive G1b boundary between a catalogued declaration and a -Theory declaration. The distinction is deliberately sharp: +This module separates catalogued declarations from well-formed Theory +declarations: * `RawExprRel` is syntax-directed. In particular, it has no typing premises, no level-well-formedness premises, and no literal-well-formedness premises. @@ -18,8 +18,7 @@ Theory declaration. The distinction is deliberately sharp: * `RawDeclRel` preserves the standalone declaration kind and translates its type and (for definitions) value. This slice covers axioms and the three definition kinds. Quotient and inductive-family declarations require an - atomic multi-target relation and are intentionally left to the corresponding - block milestone. + atomic multi-target relation and are outside this standalone relation. * `PendingDecl` contains raw correspondence, catalog closure, and absence of the target from both the trusted index and the Theory constant table. It contains no `VConstant.WF`, `VDecl.WF`, or equivalent field. @@ -397,7 +396,7 @@ end RawDeclRel /-- The target's Theory name is not already installed. Together with an untrusted target id, this blocks self-justification through constant lookup. -Warm-cache provenance and isolation are state-specific G4 obligations. -/ +Warm-cache provenance and isolation additionally depend on the checker state. -/ def TargetFresh (world : VerifyWorld) (id : KId .anon) : Prop := ∀ ⦃name⦄, world.nameOf id.addr = some name → world.venv.constants name = none @@ -488,8 +487,8 @@ theorem no_target_lookup {trProj : RawProjRel} {world : VerifyWorld} exact ⟨name, hname, hfresh hname⟩ /-- The pending target cannot occur as a constant/projection head in its own -translated type or value. This is the G1b self-unfolding barrier; cache -provenance and collision-mediated aliasing are addressed in G4/G3. -/ +translated type or value. Cache provenance and collision-mediated aliasing +are addressed separately in `Verify.Cache` and `Verify.Support`. -/ theorem no_self_expr_reference {trProj : RawProjRel} {world : VerifyWorld} {id : KId .anon} {d : VDecl} (h : PendingDecl trProj world id d) : ∃ concrete, world.catalog id = some concrete ∧ @@ -582,7 +581,7 @@ theorem theoryDecl_not_wf : cases hwf with | «axiom» hconstant _ => exact theoryConstant_not_wf hconstant -/-- Machine-checked G1b acceptance witness: raw correspondence and pending +/-- Adversarial isolation witness: raw correspondence and pending status are constructible for a declaration whose Theory WF judgment is false. -/ theorem pending_but_not_wf : diff --git a/Ix/Kernel/Verify/DefEq.lean b/Ix/Kernel/Verify/DefEq.lean index 9bd1dfb45..37823e989 100644 --- a/Ix/Kernel/Verify/DefEq.lean +++ b/Ix/Kernel/Verify/DefEq.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Whnf.Closure import Batteries.Data.UInt /-! -# K2 definitional-equality cache semantics +# Definitional-equality cache semantics For checker soundness, a cached `true` must denote Theory definitional equality. A cached `false` (including the narrow failure set) can only reject @@ -563,8 +563,8 @@ they may later be proved from a finite context-digest collision hypothesis and the declarative suffix-closure theorem, but must not be inferred from a bare address equality. -/ -/-- One context-key interpretation sufficient for every K1/K2 semantic cache -family. Operational representation is shared, while WHNF, inference, DefEq, +/-- One context-key interpretation sufficient for every reduction, inference, +and conversion cache family. Operational representation is shared, while WHNF, inference, DefEq, and the auxiliary proposition classifier each state their own context-transport consequence. -/ structure KernelSuffixModel (trProj : RawProjRel) (world : VerifyWorld) where @@ -671,7 +671,7 @@ theorem defEqCtxKey_model_matches_wf end TcM /-- Declarative sufficiency of one normalized context-digest input. This is -the semantic half of K2's suffix theorem: equality of the exact input—not +the semantic half of the suffix theorem: equality of the exact input—not equality of its Blake3 output—must preserve each judgment family at the radius that production requested. -/ structure ContextSuffixSemantics {trProj : RawProjRel} {world : VerifyWorld} @@ -824,7 +824,7 @@ def transports {trProj : RawProjRel} {world : VerifyWorld} end ScopedKernelSuffixModel /-- The ordinary checker invariant refined by membership in one explicit -suffix-model state domain. K2S uses this predicate at every model-dependent +suffix-model state domain. Scoped method proofs use this predicate at every model-dependent key boundary; the unscoped invariant remains available for model-independent helpers and legacy compatibility theorems. -/ def ScopedWhnfStateInv {trProj : RawProjRel} {world : VerifyWorld} @@ -1033,7 +1033,7 @@ end TcM namespace KernelSuffixModel -/-- Forget the K2 transports and recover exactly the K1 suffix model. -/ +/-- Forget the inference/conversion transports and recover exactly the WHNF suffix model. -/ def toWhnfSuffixModel {trProj : RawProjRel} {world : VerifyWorld} (model : KernelSuffixModel trProj world) : WhnfSuffixModel trProj world where @@ -1223,7 +1223,7 @@ theorem result {keys : WhnfContextKeys} {trProj : RawProjRel} end DefEqCacheValid -/-- Overlay K2 def-eq meanings on K1+inference cache semantics. -/ +/-- Overlay definitional-equality meanings on WHNF+inference cache semantics. -/ def defEqCacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) (fallback : CacheSemantics) : CacheSemantics where Valid := DefEqCacheValid keys trProj fallback @@ -1241,7 +1241,7 @@ def defEqCacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) intro authority support block h exact fallback.blockSuccessSound authority support block h -/-- Canonical K1+K2 semantic stack. K1's WHNF and fixed-universe unfold +/-- Canonical reduction and typing semantic stack. WHNF and fixed-universe unfold layers stay outermost; inference and def-eq occupy precisely the fallback families they own. -/ def kernelCacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) : diff --git a/Ix/Kernel/Verify/DefEq/BoolTrue.lean b/Ix/Kernel/Verify/DefEq/BoolTrue.lean index 515983494..fe11f7d7e 100644 --- a/Ix/Kernel/Verify/DefEq/BoolTrue.lean +++ b/Ix/Kernel/Verify/DefEq/BoolTrue.lean @@ -113,7 +113,7 @@ theorem boolTrueReductionAllowed_wf rcases hread with ⟨rfl, rfl⟩ exact RecM.WF.pure (E := fun _ _ => True) fun _ => rfl -/-- Direct WHNF contract used by the eager Boolean tier. K1 supplies this +/-- Direct WHNF contract used by the eager Boolean tier. WHNF supplies this for the current unfolded layer; keeping it generic avoids confusing the current reducer with the predecessor-table callback. -/ def DefEqDirectWhnf.WFAt (layer : WhnfLayer) diff --git a/Ix/Kernel/Verify/DefEq/CheapReduction.lean b/Ix/Kernel/Verify/DefEq/CheapReduction.lean index 52500b8f2..d85fbaaec 100644 --- a/Ix/Kernel/Verify/DefEq/CheapReduction.lean +++ b/Ix/Kernel/Verify/DefEq/CheapReduction.lean @@ -144,7 +144,7 @@ structure DefEqCheapReductionContext namespace DefEqCheapReductionContext -/-- Construct the public cheap reducers from their unwrapped K1/K2 body +/-- Construct the public cheap reducers from their unwrapped reduction, inference, and conversion body contracts. -/ theorem ofBodies {layer : WhnfLayer} {semantics : CacheSemantics} diff --git a/Ix/Kernel/Verify/DefEq/EqualRankCache.lean b/Ix/Kernel/Verify/DefEq/EqualRankCache.lean index b4ce02801..59d78da98 100644 --- a/Ix/Kernel/Verify/DefEq/EqualRankCache.lean +++ b/Ix/Kernel/Verify/DefEq/EqualRankCache.lean @@ -44,7 +44,7 @@ end CacheEntry namespace DefEqFailureCacheResources -/-- The joint K2 suffix model supplies failure-marker provenance without any +/-- The joint inference/conversion suffix model supplies failure-marker provenance without any semantic equality premise; validity of this partition is deliberately vacuous on acceptance. -/ theorem ofKernelSuffixModel diff --git a/Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean b/Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean index b8135d0bb..f1d73194a 100644 --- a/Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean +++ b/Ix/Kernel/Verify/DefEq/EqualRankPrefix.lean @@ -84,7 +84,7 @@ theorem ofPrefix exact (defEqLazyDeltaStepWithEqualRank_wf hfault hcached hafter hI.2.1.wf hpair) methods hmethods hI -/-- Concrete no-acceleration/K2 construction of the equal-rank branch. -/ +/-- Concrete no-acceleration/inference/conversion construction of the equal-rank branch. -/ theorem ofKernelResources {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} (model : KernelSuffixModel trProj world) diff --git a/Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean index 36c1c5e6b..983c19e8f 100644 --- a/Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/Closure.lean @@ -12,14 +12,14 @@ import Ix.Kernel.Verify.DefEq.PropositionClassifier The final comparator consists of an exhaustive structural prefix followed by the ordered Nat, lambda-eta, String, structure-eta, unit-like, and proof- irrelevance fallbacks. This module assembles those independently verified -phases under one canonical K2 suffix model. +phases under one canonical inference/conversion suffix model. -/ namespace Ix.Kernel namespace RecM /-- Concrete resources for every production phase of `isDefEqWhnf`. The -proposition-classifier context fixes the canonical K2 suffix model used by +proposition-classifier context fixes the canonical inference/conversion suffix model used by all cache-aware fields. -/ structure FinalWhnfClosureResources {trProj : RawProjRel} {world : VerifyWorld} (support : RunSupport) diff --git a/Ix/Kernel/Verify/DefEq/FinalWhnf/StringExpansion.lean b/Ix/Kernel/Verify/DefEq/FinalWhnf/StringExpansion.lean index 82744e37e..fc81b3960 100644 --- a/Ix/Kernel/Verify/DefEq/FinalWhnf/StringExpansion.lean +++ b/Ix/Kernel/Verify/DefEq/FinalWhnf/StringExpansion.lean @@ -5,7 +5,7 @@ import Ix.Kernel.Verify.DefEq.StringLiteral # Final-WHNF String-literal expansion This module verifies the ordered, bidirectional String-expansion phase in the -final-WHNF comparator. Each compact literal is expanded by the exact K1 plan, +final-WHNF comparator. Each compact literal is expanded by the exact WHNF plan, whose result translates to the same Theory literal as the source syntax. -/ diff --git a/Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean b/Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean index 1716ac4dc..4105ca82a 100644 --- a/Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean +++ b/Ix/Kernel/Verify/DefEq/LazyDeltaClosure.lean @@ -6,7 +6,7 @@ import Ix.Kernel.Verify.DefEq.StoppedContinuationClosure The bounded driver needs one verified iteration and one verified continuation for a stopped pair. This module joins those independently proved executable -surfaces under the canonical K2 suffix/cache model. +surfaces under the canonical inference/conversion suffix/cache model. -/ namespace Ix.Kernel diff --git a/Ix/Kernel/Verify/DefEq/LazyDeltaIteration.lean b/Ix/Kernel/Verify/DefEq/LazyDeltaIteration.lean index bf6b3180a..dcb9cdca8 100644 --- a/Ix/Kernel/Verify/DefEq/LazyDeltaIteration.lean +++ b/Ix/Kernel/Verify/DefEq/LazyDeltaIteration.lean @@ -9,7 +9,7 @@ module records their exact shared inputs and composes them, in execution order, into the contract for one complete bounded lazy-delta iteration. The remaining inputs are deliberately concrete contracts rather than -acceptance oracles: Nat-offset decomposition, the K1 reducers reused by +acceptance oracles: Nat-offset decomposition, the WHNF reducers reused by DefEq, and finite run-scoped resources for same-head comparison and cache writes. -/ @@ -19,7 +19,7 @@ namespace Ix.Kernel namespace RecM /-- Run-scoped resources needed to assemble every branch of one production -lazy-delta iteration under the canonical K2 cache semantics. -/ +lazy-delta iteration under the canonical inference/conversion cache semantics. -/ structure LazyDeltaIterationResources {trProj : RawProjRel} {world : VerifyWorld} (support : RunSupport) (model : KernelSuffixModel trProj world) where diff --git a/Ix/Kernel/Verify/DefEq/PropositionClassifier.lean b/Ix/Kernel/Verify/DefEq/PropositionClassifier.lean index 28d2118fa..a19aaf3fd 100644 --- a/Ix/Kernel/Verify/DefEq/PropositionClassifier.lean +++ b/Ix/Kernel/Verify/DefEq/PropositionClassifier.lean @@ -6,9 +6,9 @@ open Ix.Theory (VLevel) # Memoized proposition classification This module verifies the production `isPropType` implementation used by -proof irrelevance. Cache hits are interpreted through the joint K2 suffix +proof irrelevance. Cache hits are interpreted through the joint inference/conversion suffix model. Cache misses infer the queried expression, normalize its inferred -type with the direct K1 reducer, and install only a provenance-certified +type with the direct WHNF reducer, and install only a provenance-certified classification. -/ @@ -17,8 +17,8 @@ namespace Ix.Kernel open Ix.Theory.Named (VExpr) /-- Resources needed by the concrete proposition classifier. Direct WHNF -is the already-closed K1 reducer; inference remains a predecessor-table edge -until K2 ties the recursive method-table knot. -/ +is the already-closed WHNF reducer; inference remains a predecessor-table edge +until inference/conversion ties the recursive method-table knot. -/ structure PropositionClassifierContext (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) where model : KernelSuffixModel trProj world diff --git a/Ix/Kernel/Verify/DefEq/StringLiteral.lean b/Ix/Kernel/Verify/DefEq/StringLiteral.lean index 0a89eb4b4..cbc536cfc 100644 --- a/Ix/Kernel/Verify/DefEq/StringLiteral.lean +++ b/Ix/Kernel/Verify/DefEq/StringLiteral.lean @@ -5,7 +5,7 @@ import Ix.Kernel.Verify.Whnf.Projection.StringExpansion # String-literal definitional equality The third recursive tier expands compact String syntax before either side is -normalized. K1's expansion plan proves that the concrete intern transaction +normalized. WHNF's expansion plan proves that the concrete intern transaction terminates with a supported, structurally translatable term. DefEq needs the stronger fact recorded here: that exact generated term translates to the same Theory literal as the compact source syntax. @@ -15,7 +15,7 @@ namespace Ix.Kernel open Ix.Theory.Named (VExpr) -/-- A K1 String-expansion plan together with the exact Theory meaning needed +/-- A WHNF String-expansion plan together with the exact Theory meaning needed by DefEq. Merely knowing that the generated expression has *some* translation would not justify comparing it in place of the source literal. -/ structure DefEqStringExpansionPlan @@ -40,7 +40,7 @@ namespace RecM attribute [local irreducible] strLitToConstructor strLitToConstructorWithPrimitives -/-- A concrete semantic plan strengthens K1's exact-result expansion theorem +/-- A concrete semantic plan strengthens WHNF's exact-result expansion theorem with the particular Theory literal required by DefEq. -/ theorem strLitToConstructor_defeq_plan_wf {layer : WhnfLayer} {semantics : CacheSemantics} diff --git a/Ix/Kernel/Verify/DefEq/Structural.lean b/Ix/Kernel/Verify/DefEq/Structural.lean index 2fc370351..e48f143f4 100644 --- a/Ix/Kernel/Verify/DefEq/Structural.lean +++ b/Ix/Kernel/Verify/DefEq/Structural.lean @@ -262,7 +262,7 @@ namespace DefEqAfterQuick /-- Semantic contract for the production-owned tail after Tier 1 misses. Later tier modules refine and discharge this boundary; keeping it generic in -the cache semantics lets the structural proof be reused at the final K2 +the cache semantics lets the structural proof be reused at the final inference/conversion stack. -/ def WF (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) diff --git a/Ix/Kernel/Verify/Driver/BooleanAcceptance.lean b/Ix/Kernel/Verify/Driver/BooleanAcceptance.lean index 2690273ea..23b075397 100644 --- a/Ix/Kernel/Verify/Driver/BooleanAcceptance.lean +++ b/Ix/Kernel/Verify/Driver/BooleanAcceptance.lean @@ -4,8 +4,8 @@ import Ix.Kernel.Verify.Inductive.EnumerationAcceptance /-! # Certificate-backed Boolean driver acceptance -This module connects the concrete E2 Boolean generation certificate to the -E3-S production-driver adapter. The runtime checker call remains a required +This module connects the concrete Boolean generation certificate to the +supported fragment production-driver adapter. The runtime checker call remains a required gate, but semantic authority for these two coordinated blocks comes from the fixed family transition and existing-recursor certificates. In particular, the proof does not reinterpret the runtime cache order as a topological @@ -56,7 +56,7 @@ deriving instance DecidableEq for Ixon.LazyConstant deriving instance DecidableEq for AnonWorkItem deriving instance DecidableEq for CheckResult -/-- The E2-certified Theory result, with no concrete Ix declaration trusted +/-- The certified Theory result, with no concrete Ix declaration trusted yet. Catalog, block table, names, and the empty trust predicate are inherited unchanged from the concrete ingress fixture. -/ def stagedWorld : VerifyWorld := @@ -509,7 +509,7 @@ def stagedRecursorResources : theoryAfter recursorId exact familyRecursorSemanticEntry -/-- Transport the fixed family certificate to an arbitrary monotone E1 world. +/-- Transport the fixed family certificate to a world extended by serial checking. No freshness premise is needed: replay unions all exact members idempotently. -/ def familyCertificateResources @@ -519,7 +519,7 @@ def familyCertificateResources stagedFamilyResources.rebaseWorld hle /-- Transport the fixed generated-recursor certificate to an arbitrary -monotone E1 world. -/ +world extended by serial checking. -/ def recursorCertificateResources (current : VerifyWorld) (hle : stagedWorld ≤ current) : CertificateBackedBlockResources current recursorBlockAddress recursorId.addr @@ -532,7 +532,7 @@ def recursorCertificateResources certificate-backed evidence at its *current* semantic world. The actual successful `checkConst` equation remains in the provider interface and hence in `CheckSuccessSound`; it is deliberately not used as a substitute for the -E2 semantic certificate. -/ +inductive semantic certificate. -/ def supportedFragment : CertificateBackedCheckFragment stagedWorld dependencyGraph booleanWork where resources := by @@ -581,10 +581,10 @@ theorem allResultsSucceeded : simp [successfulResults] at hresult rcases hresult with rfl | rfl | rfl | rfl <;> rfl -/-- Whole-driver E3-S witness for a real environment containing an inductive +/-- Whole-driver supported fragment witness for a real environment containing an inductive family and its generated recursor. The theorem consumes the actual `checkEnvAnon` success, the exact finite source domain, the collapsed -dependency schedule, and fixed E2 semantic entries for both coordinated +dependency schedule, and fixed inductive semantic entries for both coordinated blocks. Its dependency path contains no oracle-selected world materialization. -/ theorem subjectWF : SubjectWF stagedWorld dependencyGraph diff --git a/Ix/Kernel/Verify/Driver/Dependencies.lean b/Ix/Kernel/Verify/Driver/Dependencies.lean index ace78133c..2d5101d70 100644 --- a/Ix/Kernel/Verify/Driver/Dependencies.lean +++ b/Ix/Kernel/Verify/Driver/Dependencies.lean @@ -5,7 +5,7 @@ import Ix.Kernel.Verify.Driver.Model `Ixon.Constant.refs` is an intern table, not itself a dependency list. Nat and String nodes index blobs through the same table, and malformed/unused -table entries must not become declaration assumptions. E1 therefore follows +table entries must not become declaration assumptions. Serial composition follows the expression constructors which ingress turns into kernel constants: * `.ref i` contributes `refs[i]`; diff --git a/Ix/Kernel/Verify/Driver/Enumeration.lean b/Ix/Kernel/Verify/Driver/Enumeration.lean index 8bb44fac5..dd39d8d68 100644 --- a/Ix/Kernel/Verify/Driver/Enumeration.lean +++ b/Ix/Kernel/Verify/Driver/Enumeration.lean @@ -557,7 +557,7 @@ theorem expectedAnonWork_matchesCatalog {env : Ixon.Env} intro item hitem addr hcovered exact h.matches_blockOfAddr hitem hcovered -/-- Public production-facing E1 enumeration result. -/ +/-- Production enumeration result used by serial composition. -/ theorem buildAnonWork_exact {env : Ixon.Env} (h : AnonWorkEnvWF env) (hblock : IxonEnv.BlockOfIdempotent env) : ∃ work, diff --git a/Ix/Kernel/Verify/Driver/Fixtures.lean b/Ix/Kernel/Verify/Driver/Fixtures.lean index 1d3567768..f6d4343f8 100644 --- a/Ix/Kernel/Verify/Driver/Fixtures.lean +++ b/Ix/Kernel/Verify/Driver/Fixtures.lean @@ -1,7 +1,7 @@ import Ix.Kernel.Verify.Driver.Serial /-! -# Adversarial E1 fixtures +# Adversarial serial composition fixtures These small, Blake3-independent fixtures exercise the checked-set contracts themselves. They deliberately use fixed distinct addresses so failures in diff --git a/Ix/Kernel/Verify/Driver/Model.lean b/Ix/Kernel/Verify/Driver/Model.lean index 6428b01fa..4865a19ce 100644 --- a/Ix/Kernel/Verify/Driver/Model.lean +++ b/Ix/Kernel/Verify/Driver/Model.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Check.BlockIdentity /-! # Workset and dependency model -This file is the semantic half of E1. It deliberately keeps three address +This file is the semantic half of serial composition. It deliberately keeps three address roles distinct while representing all of them with the production `Address` type: @@ -127,7 +127,7 @@ namespace VerifyWorld /-- Semantic acceptance for a raw address. Declaration projection and standalone addresses are accepted by `trusted`; a Muts envelope address is -accepted by the atomic `AcceptedBlock` fact established in E0. -/ +accepted by the atomic `AcceptedBlock` fact established in block admission. -/ def AcceptsAddress (world : VerifyWorld) (addr : Address) : Prop := world.trusted (⟨addr, ()⟩ : KId .anon) ∨ world.AcceptedBlock (⟨addr, ()⟩ : KId .anon) diff --git a/Ix/Kernel/Verify/Driver/Serial.lean b/Ix/Kernel/Verify/Driver/Serial.lean index 5a7de4f2c..cc91c904c 100644 --- a/Ix/Kernel/Verify/Driver/Serial.lean +++ b/Ix/Kernel/Verify/Driver/Serial.lean @@ -189,7 +189,7 @@ theorem checkEnvAnon_eq_serial {env : Ixon.Env} rw [h.buildAnonWork_eq_expected] rfl -/-- E1's production serial-driver corollary. All emitted rows succeeding is +/-- Production serial-driver corollary. All emitted rows succeeding is converted to concrete per-item success traces, those traces are interpreted through the per-item success rule, and the resulting admissions are reordered by the proved collapsed-block schedule. -/ diff --git a/Ix/Kernel/Verify/Driver/SupportedAcceptance.lean b/Ix/Kernel/Verify/Driver/SupportedAcceptance.lean index e2c019ad2..3ff087e21 100644 --- a/Ix/Kernel/Verify/Driver/SupportedAcceptance.lean +++ b/Ix/Kernel/Verify/Driver/SupportedAcceptance.lean @@ -5,25 +5,25 @@ import Ix.Kernel.Verify.Driver.Serial /-! # Supported production-checker acceptance -This module is the concrete adapter between the per-call K3/E0 theorems and -E1's serial checked-set composition. It intentionally does not contain an +This module connects per-call declaration and block-admission theorems to +the serial checked-set composition. It does not contain an opaque `checkConst succeeded, therefore the declaration is sound` callback. Instead, every reusable successful call must expose: -* one finite, run-scoped recursive-method context; +* one finite, run-scoped method context; * the exact physical/world cache and block-table invariants for that call; * agreement between the source work item and the block selected by the production router; -* declaration-local K3 resources for an observed standalone route; and +* declaration-local resources for an observed standalone route; and * either constructive scoped singleton-definition evidence or an explicit - E2 oracle-backed resource for every fresh coordinated body; + inductive oracle resource for every fresh coordinated body; * certificate-backed replay resources for coordinated blocks whose semantic entries are already installed in the current Theory environment. The composition theorems below turn those resources into `CheckSuccessSound`, which `Driver.Serial` then composes into `SubjectWF`. The source-to-kernel route agreement remains an explicit representation -premise until the later ingress/refinement phase discharges it generically. +premise requiring a general ingress/refinement proof. -/ namespace Ix.Kernel @@ -32,7 +32,7 @@ namespace AnonWorkItem /-- Exact relation between a production work item and the result observed from `coordinatedBlockFor`. A standalone source entry may be checked either -through K3 (axioms) or through its singleton coordinated block +through declaration-checking (axioms) or through its singleton coordinated block (definitions/recursors). A Muts work item must route to its advertised envelope address. -/ def SelectedBlockMatches (item : AnonWorkItem) : @@ -44,10 +44,10 @@ def SelectedBlockMatches (item : AnonWorkItem) : end AnonWorkItem -/-! ## Standalone K3 resources -/ +/-! ## Standalone declaration-checking resources -/ /-- The declaration-local premises needed when the actual production router -selects K3's standalone path. None of these fields assumes a declaration-WF +selects the declaration checker's standalone path. None of these fields assumes a declaration-WF transition or target trust; `PendingDecl` explicitly asserts the opposite. -/ structure SupportedStandaloneResources {initial : TcState .anon} {id : KId .anon} @@ -76,8 +76,8 @@ structure SupportedStandaloneResources namespace SupportedStandaloneResources -/-- Apply K3 to the exact successful public call and retain only the world -extension and target-trust facts required by E1. -/ +/-- Apply declaration-checking to the exact successful public call and retain only the world +extension and target-trust facts required by serial composition. -/ theorem promotes {initial after : TcState .anon} {id : KId .anon} {requests : List WalkerRequest} {trProj : RawProjRel} @@ -105,11 +105,11 @@ end SupportedStandaloneResources /-! ## Coordinated-body resources -/ -/-- Exhaustive body evidence supported by the E3-S adapter. +/-- Exhaustive body evidence accepted by the fragment adapter. -The first constructor is constructive K3 evidence for the only definition +The first constructor is constructive declaration-checking evidence for the only definition block shape currently modeled atomically by Ix.Theory.Named: one definition. The -second constructor keeps the E2 inductive/recursor oracle visible. In +second constructor keeps the inductive/recursor oracle visible. In particular there is no constructor containing a prebuilt `CertifiedBlockBodySuccess`. -/ inductive SupportedBlockBodyResources @@ -154,7 +154,7 @@ inductive SupportedBlockBodyResources namespace SupportedBlockBodyResources -/-- Turn one transparent supported-body constructor into the exact E0 body +/-- Turn one transparent supported-body constructor into the exact block admission body certificate for the observed trace. -/ theorem certify {initial : TcState .anon} {id : KId .anon} @@ -201,8 +201,8 @@ end SupportedBlockBodyResources namespace CheckBlockKind -/-- Kinds which E3-S may replay from already-installed semantic entries. -Definitions remain on the constructive K3 route; this adapter is only for +/-- Kinds the supported-fragment adapter may replay from installed semantic entries. +Definitions remain on the constructive declaration-checking route; this adapter is only for inductive-family and generated-recursor blocks. -/ def CertificateBacked : CheckBlockKind → Prop | .inductive' | .recursor => True @@ -213,7 +213,7 @@ end CheckBlockKind /-- A coordinated block whose complete semantic entries are already installed in `world.venv`. -This is the reusable E3-S form of E2's fixed semantic certificates. Unlike an +This reuses fixed inductive certificates in the supported fragment. Unlike an `ExistingSemanticBlockCertificate`, it deliberately has no freshness premise: checked-set composition may replay a block in a monotone world which already trusts a proper subset of its exact members. Admission is therefore the @@ -294,7 +294,7 @@ theorem le_admittedWorld ⟨rfl, rfl, rfl, fun {_} hold => Or.inr hold, Ix.Theory.Named.VEnv.LE.rfl⟩ /-- Reindex installed semantic entries across an arbitrary monotone current -world. This is the reusable bridge used by E1 after prior work items have +world. This is the reusable bridge used by serial composition after prior work items have possibly trusted a proper subset of this block. -/ def rebaseWorld {before current : VerifyWorld} {blockAddr primary : Address} @@ -414,7 +414,7 @@ structure SupportedCheckRun (world : VerifyWorld) (item : AnonWorkItem) namespace SupportedCheckRun -/-- K3/E0 assembly for one actual successful production call. -/ +/-- Assemble declaration and block evidence for a successful production call. -/ theorem accepts {world : VerifyWorld} {item : AnonWorkItem} {initial after : TcState .anon} @@ -483,11 +483,11 @@ theorem accepts end SupportedCheckRun -/-! ## Reusable fragment and E1 composition -/ +/-! ## Reusable fragment and serial composition -/ -/-- Exhaustive semantic resources accepted by the supported-fragment -adapter. `operational` is the full K3/E0 state-and-cache route. -`certificateBackedBlock` is the narrower E2 replay route for +/-- Exhaustive semantic resources accepted by the supported fragment +adapter. `operational` is the full declaration and block checking state-and-cache route. +`certificateBackedBlock` is the narrower inductive certification replay route for inductive/recursor blocks whose complete semantic entries are already installed; it does not manufacture a standalone recursive-method context or an oracle-selected future world. -/ @@ -521,7 +521,7 @@ end SupportedCheckEvidence /-- Exact all-block evidence used when every row in a fragment is backed by already-installed semantic entries. Keeping this narrow evidence separate from `SupportedCheckEvidence` gives all-block consumers a dependency path -which cannot reach the operational oracle-backed E0 branch. -/ +which cannot reach the operational oracle-backed block admission branch. -/ inductive CertificateBackedCheckEvidence (world : VerifyWorld) : AnonWorkItem → Type | block {blockAddr primary targets} : @@ -564,7 +564,7 @@ structure CertificateBackedCheckFragment (baseline : VerifyWorld) namespace CertificateBackedCheckFragment -/-- The oracle-free all-block adapter demanded by E1. -/ +/-- The oracle-free all-block adapter demanded by serial composition. -/ theorem checkSuccessSound {baseline : VerifyWorld} {catalog : DependencyCatalog} {work : Array AnonWorkItem} @@ -581,7 +581,7 @@ end CertificateBackedCheckFragment /-- A precisely scoped fragment provider. Resources are requested only when the item is not already accepted in `current`; this keeps the pending/fresh -K3 premise honest while allowing E1 to reuse the rule at arbitrary monotone +declaration-checking premise honest while allowing serial composition to reuse the rule at arbitrary monotone world extensions. The provider may use the accepted external dependencies to establish the run's cache and declaration premises, but cannot assume its own `WorkItemAccepted` conclusion. -/ @@ -601,7 +601,7 @@ structure SupportedCheckFragment (baseline : VerifyWorld) namespace SupportedCheckFragment -/-- The concrete K3/E0 adapter demanded by E1. -/ +/-- The concrete declaration and block checking adapter demanded by serial composition. -/ theorem checkSuccessSound {baseline : VerifyWorld} {catalog : DependencyCatalog} {work : Array AnonWorkItem} @@ -618,8 +618,8 @@ end SupportedCheckFragment namespace AnonWorkEnvWF -/-- E3-S composition specialized to an all-block certificate-backed fragment. -This route keeps the public serial success gate and E1 schedule unchanged while +/-- Serial composition specialized to an all-block certificate-backed fragment. +This route retains the public success gate and serial schedule while excluding the operational oracle-backed body branch from its dependency closure. -/ theorem checkEnvAnon_certificateBacked_subjectWF @@ -642,7 +642,7 @@ theorem checkEnvAnon_certificateBacked_subjectWF exact h.checkEnvAnon_subjectWF hblock hdeps hwf hassumptions hdisjoint fragment.checkSuccessSound cfg hrun hresults -/-- E3-S supported-fragment composition theorem. Successful `checkEnvAnon` +/-- Supported-fragment composition theorem. Successful `checkEnvAnon` rows imply `SubjectWF` for the exact enumerated work/subject sets and the explicit assumption set, provided every still-pending successful call belongs to the transparent supported fragment above. -/ diff --git a/Ix/Kernel/Verify/Driver/SupportedAcceptanceFixtures.lean b/Ix/Kernel/Verify/Driver/SupportedAcceptanceFixtures.lean index 4feb1f616..ef2daa361 100644 --- a/Ix/Kernel/Verify/Driver/SupportedAcceptanceFixtures.lean +++ b/Ix/Kernel/Verify/Driver/SupportedAcceptanceFixtures.lean @@ -5,10 +5,10 @@ import Ix.Kernel.Verify.Inductive.EnumerationAcceptance /-! # Supported-acceptance adversarial and inductive fixtures -These fixtures guard the two representation-sensitive edges of the E3-S +These fixtures guard the two representation-sensitive edges of the supported fragment adapter. The first pair proves that a Muts work item cannot be discharged by an unrouted call or a call routed to a different envelope. The second joins -E2b's concrete Boolean family execution to the adapter's oracle-backed body +the concrete Boolean family execution to the adapter's oracle-backed body constructor; the only remaining inputs are the explicitly advertised scoped recursive context and active cache invariant. -/ @@ -32,23 +32,23 @@ theorem block_rejects_wrong_route : simp [blockItem, AnonWorkItem.SelectedBlockMatches] /-- Standalone source entries deliberately admit either operational branch: -axioms use K3 directly, while singleton definitions and recursors are -committed through E0. -/ +axioms use declaration-checking directly, while singleton definitions and recursors are +committed through block admission. -/ theorem standalone_allows_coordinated_route (selected : Option (KId .anon)) : (AnonWorkItem.standalone E1Fixture.first).SelectedBlockMatches selected := trivial -/-- The fixed-certificate replay surface cannot bypass K3 for definition +/-- The fixed-certificate replay surface cannot bypass declaration-checking for definition blocks. -/ theorem certificate_backed_definition_excluded : ¬ CheckBlockKind.CertificateBacked .defn := by intro h exact h -/-! ## Concrete E2b body bridge -/ +/-! ## Concrete singleton certification body bridge -/ -/-- E2b's actual Boolean family/constructor block inhabits the exact -oracle-backed constructor consumed by E3-S. This theorem is indexed by the +/-- The Boolean family/constructor block inhabits the exact oracle-backed +constructor consumed by the supported-fragment adapter. This theorem is indexed by the real production body states and exact physical member array from `BooleanEnumerationFixture`; it does not replace them with an abstract inductive environment. -/ @@ -72,8 +72,8 @@ def booleanFamilyBodyResources .oracleBacked (BooleanEnumerationFixture.familyLink.blockResources activePost) -/-- The adapter turns that E2b resource and the actual successful production -trace into E0's exact atomic-body certificate. -/ +/-- The adapter turns that singleton certification resource and the actual successful production +trace into block admission's exact atomic-body certificate. -/ theorem booleanFamilyBody_certified {requests : List WalkerRequest} {support : RunSupport} (context : ScopedRecursiveMethodRunContext diff --git a/Ix/Kernel/Verify/Env.lean b/Ix/Kernel/Verify/Env.lean index f80f9f6d9..4957b692e 100644 --- a/Ix/Kernel/Verify/Env.lean +++ b/Ix/Kernel/Verify/Env.lean @@ -41,7 +41,7 @@ content-addressed environment. The structural divergences: `AddInduct` is an empty `-- TODO`). Thus this legacy relation remains uninhabited for envs containing inductives. The trusted-world log below retains `TrustedCatalogLog.ambient` and its explicit `InductiveOracle` as a - compatibility constructor. Certificate-backed E2c paths instead use + compatibility constructor. Certificate-backed inductive verification paths instead use `semanticBlock` and `existingBlock`; migrating the remaining ambient users depends on completing the broader inductive fragment. -/ @@ -184,7 +184,7 @@ theorem TrKDefVal.mono {safety : Ix.DefinitionSafety} /-- Block-level inductive translation in the legacy whole-`KEnv` relation — upstream-parity STUB (their `AddInduct` is an empty inductive pending the - `addInduct` spec). `TrustedCatalogLog.ambient` below is the live G2 path; + `addInduct` spec). `TrustedCatalogLog.ambient` below is the live inductive interface path; this constructor remains only as a quarantined compatibility interface. -/ inductive AddKInduct : HashMap (KId .anon) (KConst .anon) → VEnv → VInductDecl → @@ -377,7 +377,7 @@ theorem TrKEnv.find? {safety : Ix.DefinitionSafety} let ⟨_, H⟩ := H H.find? h hs -/-! ## G1c: trusted-catalog log +/-! ## Trusted-catalog log The legacy `TrKEnv'` above indexes its semantic log by the entire concrete hash map, forcing pending declarations to be WF before `checkConst` runs. @@ -994,7 +994,7 @@ theorem TrustedCatalogRel.promote TrustedCatalogRel.promoteExact hrel hpending hwf exact ⟨world', hexact.promotes, hworld, hdecl⟩ -/-- The G1b ill-typed pending world already satisfies the G1c trusted-log +/-- The ill-typed pending world satisfies the trusted-log invariant: its catalog entry remains completely outside the empty log. -/ theorem IllTypedPending.trustedCatalogRel : TrustedCatalogRel RawProjRel.none IllTypedPending.world := @@ -1076,7 +1076,7 @@ theorem trustedCatalogRel : TrustedCatalogRel RawProjRel.none world := TrustedCatalogLog.empty -/-- Positive G1c fixture: supplying the new WF derivation promotes exactly +/-- Positive trusted-catalog log fixture: supplying the new WF derivation promotes exactly the pending id and immediately yields trusted lookup evidence. -/ theorem promotes : ∃ world', diff --git a/Ix/Kernel/Verify/Execution.lean b/Ix/Kernel/Verify/Execution.lean index 4cac142ea..049890d12 100644 --- a/Ix/Kernel/Verify/Execution.lean +++ b/Ix/Kernel/Verify/Execution.lean @@ -1,7 +1,7 @@ import Ix.Kernel.Verify.Support /-! -# G3b: execution-indexed finite run assumptions +# Execution-indexed finite run assumptions An explicit request list is not evidence that it describes a checker run: choosing `[]` would make coverage and bounds vacuous. `ExecutionRequests` is diff --git a/Ix/Kernel/Verify/Inductive.lean b/Ix/Kernel/Verify/Inductive.lean index 82567cb06..416ae2e1f 100644 --- a/Ix/Kernel/Verify/Inductive.lean +++ b/Ix/Kernel/Verify/Inductive.lean @@ -8,9 +8,7 @@ open Ix.Theory (VLevel) /-! # Ambient inductive oracle -G2 introduced this interface before Ix.Theory.Named had a usable inductive -specification, so it records the semantic consequences needed by the checker -directly: +This interface records the semantic consequences needed by the checker: * every admitted concrete inductive-family constant has an exact raw Theory translation and lookup; @@ -19,15 +17,15 @@ directly: * every concrete recursor rule has an explicit, well-formed Theory defeq witness headed by that recursor. -Pin A now provides Ix.Theory.Named's proved normalized `GenerationCertificate` and +Ix.Theory.Named provides the normalized `GenerationCertificate` and proved `addInductCertified` transaction. `Inductive/Certificate.lean` derives the Theory-owned environment, lookup, freshness, and rule-registration facts from that certificate. It intentionally cannot supply the Ix-owned catalog/name translation, checker-execution, and recursor-pattern fields below. `InductiveOracle` therefore remains an explicit assumption boundary, not a -claim that Ix's inductive checker has already been verified. E2b must combine -the certificate facts with actual Ix block checking and pattern-generation +claim that Ix's inductive checker has already been verified. The singleton +adapters combine certificate facts with Ix block checking and pattern-generation proofs. Keeping the interface in terms of semantic consequences permits a closed Nat model while the recursor clause prevents WHNF proofs from treating computation rules as an unrecorded ambient fact. @@ -372,7 +370,7 @@ structure RecursorRulePattern where (constructorParams.toNat + constructorFields.toNat)).Check /-- Finite production metadata required by one recursor pattern, separated -from its semantic rewrite law so E2 adapters can show exactly which part is +from its semantic rewrite law so inductive certification adapters can show exactly which part is discharged by catalog/layout correspondence. -/ structure RawRecursorRulePatternMetadataRel (catalog : Catalog) (nameOf : Address → Option Lean.Name) (id : KId .anon) @@ -519,7 +517,7 @@ oracle from re-certifying an existing trusted id. The oracle records `before ≤ after` rather than requiring every consumer to carry a transaction equation. `CertifiedGenerationFacts` now derives this -Theory-owned portion; the remaining fields are the E2b Ix correspondence +Theory-owned portion; the remaining fields are the singleton certification Ix correspondence boundary. -/ structure InductiveOracle (trProj : RawProjRel) (catalog : Catalog) (nameOf : Address → Option Lean.Name) (trusted : KId .anon → Prop) diff --git a/Ix/Kernel/Verify/Inductive/AliasFormerAdmission.lean b/Ix/Kernel/Verify/Inductive/AliasFormerAdmission.lean index e0ad3d12c..ddb7f9896 100644 --- a/Ix/Kernel/Verify/Inductive/AliasFormerAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/AliasFormerAdmission.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free family-result-normalizing singleton admission -This module closes the concrete `AliasFormer` E2c transaction. The +This module closes the concrete `AliasFormer` inductive verification transaction. The transparent `TypeFamilyAlias` dependency is promoted first, the family/constructor block advances that explicit Theory world, and the independently stored generated recursor is then admitted from semantic entries already present in diff --git a/Ix/Kernel/Verify/Inductive/AliasFormerCertificate.lean b/Ix/Kernel/Verify/Inductive/AliasFormerCertificate.lean index 54c3894b8..7c4018e68 100644 --- a/Ix/Kernel/Verify/Inductive/AliasFormerCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/AliasFormerCertificate.lean @@ -53,14 +53,14 @@ theorem beforeWF : typeFamilyAliasEnv.WF := /-- Exact post-environment selected by that certificate. -/ def finalEnv : VEnv := aliasFormerFinalEnv -/-- The exact Spec-01E package. Its producer-shape index is deliberately +/-- The exact producer-selected package. Its producer-shape index is deliberately inferred here because Ix.Theory.Named keeps the fixture's concrete shape witness private while exposing this public dependent existence theorem. -/ def exactPackage := Classical.choice aliasFormerExactProducedGenerationCandidatePackage_exists /-- The exact successful outer metadata producer, dependent semantic package, -and certified Theory insertion retained as one E2c transaction. Construction +and certified Theory insertion retained as one inductive verification transaction. Construction keeps the producer-selected source and generation indices intact. -/ def exactProducedTransaction := ExactProducedGenerationTransaction.mk @@ -75,7 +75,7 @@ def exactProducedTransaction := exact aliasFormer_addInductCertified_checked) beforeWF -/-- Intentional operational erasure of the exact Spec-01E indices. -/ +/-- Operational erasure of the exact source and generation indices. -/ def producedTransaction : ProducedGenerationTransaction typeFamilyAliasEnv finalEnv [] := exactProducedTransaction.toProduced diff --git a/Ix/Kernel/Verify/Inductive/AliasRecAdmission.lean b/Ix/Kernel/Verify/Inductive/AliasRecAdmission.lean index a1027c0ee..dbd0a63e4 100644 --- a/Ix/Kernel/Verify/Inductive/AliasRecAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/AliasRecAdmission.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free recursive-field-normalizing direct-recursive admission -This module closes the concrete `AliasRec` E2c transaction. The +This module closes the concrete `AliasRec` inductive verification transaction. The transparent `RecAlias` dependency is promoted first, the family/constructor block advances that explicit Theory world, and the independently stored generated recursor is then admitted from semantic entries already present in diff --git a/Ix/Kernel/Verify/Inductive/AnnotatedPiAdmission.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiAdmission.lean index b5e2899b8..7673958b9 100644 --- a/Ix/Kernel/Verify/Inductive/AnnotatedPiAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiAdmission.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free annotation-normalizing recursive-Pi admission -This module closes the concrete `AnnotatedPi` E2c transaction. The +This module closes the concrete `AnnotatedPi` inductive verification transaction. The transparent `outParam` dependency is promoted first, the family/constructor block advances that explicit Theory world, and the independently stored generated recursor is then admitted from semantic entries already present in diff --git a/Ix/Kernel/Verify/Inductive/AnnotatedPiCertificate.lean b/Ix/Kernel/Verify/Inductive/AnnotatedPiCertificate.lean index cef1c052a..891f50b68 100644 --- a/Ix/Kernel/Verify/Inductive/AnnotatedPiCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/AnnotatedPiCertificate.lean @@ -6,8 +6,7 @@ import Ix.Theory.Named.Verify.Environment.InductiveFixtures `AnnotatedPi.mk` retains the raw binder domain `outParam Prop`, while the Ix.Theory.Named analyzer classifies recursion through the normalized domain `Prop`. -This is the first Ix transaction whose certified generation is deliberately -non-identity: the stored family and generated artifacts preserve raw syntax, +The certified generation is non-identity: the stored family and generated artifacts preserve raw syntax, but recursive classification is owned by the checked view produced by the ordinary Ix.Theory.Named candidate pipeline. @@ -59,14 +58,14 @@ theorem beforeWF : outParamEnv.WF := /-- Exact post-environment selected by that certificate. -/ def finalEnv : VEnv := annotatedPiFinalEnv -/-- The exact Spec-01E package. Its producer-shape index is deliberately +/-- The exact producer-selected package. Its producer-shape index is deliberately inferred here because Ix.Theory.Named keeps the fixture's concrete shape witness private while exposing this public dependent existence theorem. -/ def exactPackage := Classical.choice annotatedPiExactProducedGenerationCandidatePackage_exists /-- The exact successful outer metadata producer, dependent semantic package, -and certified Theory insertion retained as one E2c transaction. Construction +and certified Theory insertion retained as one inductive verification transaction. Construction keeps the producer-selected source and generation indices intact. -/ def exactProducedTransaction := ExactProducedGenerationTransaction.mk @@ -81,7 +80,7 @@ def exactProducedTransaction := exact annotatedPi_addInductCertified) beforeWF -/-- Intentional operational erasure of the exact Spec-01E indices. -/ +/-- Operational erasure of the exact source and generation indices. -/ def producedTransaction : ProducedGenerationTransaction outParamEnv finalEnv [] := exactProducedTransaction.toProduced diff --git a/Ix/Kernel/Verify/Inductive/BlockCertificate.lean b/Ix/Kernel/Verify/Inductive/BlockCertificate.lean index 7f9c1c284..1ca0fde33 100644 --- a/Ix/Kernel/Verify/Inductive/BlockCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/BlockCertificate.lean @@ -3,7 +3,7 @@ import Ix.Theory.Named.Typing.InductiveCertificate /-! # Certified mutual-inductive block transactions -This is the Theory-only consumer boundary for Ix.Theory.Named's Spec-08 block +This is the Theory-only consumer boundary for Ix.Theory.Named's block generation certificate. A mutual block is one atomic semantic transaction: all family constants are inserted before any constructors, all constructors before any recursors, and all recursors before the globally flattened iota @@ -65,7 +65,7 @@ def toBlockCertificate {source : VInductDecl} {before after : VEnv} success := tx.success beforeWF := tx.beforeWF -/-- Recover Spec-08's exact four-phase trace for the atomic block. -/ +/-- Recover the exact four-phase generation trace for the atomic block. -/ theorem trace {source : VInductDecl} {before after : VEnv} (tx : CertifiedBlockGenerationTransaction source before after) : Nonempty (VEnv.AddInductBlockGenerationTrace before after diff --git a/Ix/Kernel/Verify/Inductive/ConstructorPositivityTraversal.lean b/Ix/Kernel/Verify/Inductive/ConstructorPositivityTraversal.lean index 7df19c39f..efdcdfd41 100644 --- a/Ix/Kernel/Verify/Inductive/ConstructorPositivityTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/ConstructorPositivityTraversal.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Inductive.RecursivePositivityTraversal # Complete constructor-positivity traversal `PositivityDomainTrace` starts after production has already opened the shared -parameter prefix and selected a constructor field. E2c also needs evidence +parameter prefix and selected a constructor field. Inductive verification also needs evidence that those field calls are the ones reached by the enclosing `checkPositivity` execution. This module retains that missing outer spine: parameter opening, source-ordered field traversal, and final local-context diff --git a/Ix/Kernel/Verify/Inductive/ConstructorValidationTraversal.lean b/Ix/Kernel/Verify/Inductive/ConstructorValidationTraversal.lean index 106a2826f..e1f3e162e 100644 --- a/Ix/Kernel/Verify/Inductive/ConstructorValidationTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/ConstructorValidationTraversal.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Inductive.ConstructorPositivityTraversal # Production constructor-validation traversal `ConstructorPositivityTrace` classifies a successful strict-positivity call, -but E2c must also establish that the call is the one selected by production's +but inductive verification must also establish that the call is the one selected by production's complete constructor-validation branch. This module retains the exact A1–A4 execution around that call: derived metadata, shared-parameter agreement, safety gating, field-universe validation, and constructor-return validation. diff --git a/Ix/Kernel/Verify/Inductive/EliminationBreadthFixture.lean b/Ix/Kernel/Verify/Inductive/EliminationBreadthFixture.lean index 7d8f4403d..0eebd5367 100644 --- a/Ix/Kernel/Verify/Inductive/EliminationBreadthFixture.lean +++ b/Ix/Kernel/Verify/Inductive/EliminationBreadthFixture.lean @@ -8,7 +8,7 @@ import Ix.Theory.Named.Verify.Environment.EliminationFixturesSmall /-! # Concrete small-elimination and K-target breadth -Ix.Theory.Named's Spec-06 fixtures retain the exact kernel elimination traversal and +Ix.Theory.Named's elimination fixtures retain the exact kernel traversal and align it with the generated Theory metadata. This module takes the remaining Ix step: it compiles those same kernel declarations to production Ixon blocks, ingresses the family and recursor projections, and runs both production block diff --git a/Ix/Kernel/Verify/Inductive/EnumerationFixture.lean b/Ix/Kernel/Verify/Inductive/EnumerationFixture.lean index c02c71f8e..f4ac6d198 100644 --- a/Ix/Kernel/Verify/Inductive/EnumerationFixture.lean +++ b/Ix/Kernel/Verify/Inductive/EnumerationFixture.lean @@ -7,7 +7,7 @@ open Ix.Theory (VLevel) /-! # Concrete singleton-enumeration fixture -This module closes E2b's executable witness with a two-constructor Boolean +This module closes singleton certification's executable witness with a two-constructor Boolean enumeration. The Theory side uses Ix.Theory.Named's checked identity-generation certificate; the concrete side below is built from the actual Ixon block encoding and production anonymous ingress/checker functions. @@ -663,7 +663,7 @@ theorem rawConstZero {expected : KId .anon} {expression : KExpr .anon} /-- Translate the closed core syntax used by the Boolean family and recursor. The partiality is intentional: free variables, lets, projections, and -literals are outside this E2b fixture. Constant translation consults the +literals are outside this singleton certification fixture. Constant translation consults the same immutable Theory environment and address-to-name interpretation used by `RawExprRel`. -/ def translateCore? : KExpr .anon → Option VExpr @@ -771,7 +771,7 @@ private theorem recursorRulesSizeNative : recursorRules.size = 2 := by theorem recursorRulesSize : recursorRules.size = 2 := recursorRulesSizeNative -/-- Total finite selector; the accompanying size theorem proves that E2b +/-- Total finite selector; the accompanying size theorem proves that singleton certification uses it only at actual rule positions. -/ def concreteRuleAt (index : Nat) : RecRule .anon := recursorRules[index]! diff --git a/Ix/Kernel/Verify/Inductive/ExactLeanSyntax.lean b/Ix/Kernel/Verify/Inductive/ExactLeanSyntax.lean index c7bfa00c3..59a3de7c0 100644 --- a/Ix/Kernel/Verify/Inductive/ExactLeanSyntax.lean +++ b/Ix/Kernel/Verify/Inductive/ExactLeanSyntax.lean @@ -5,7 +5,7 @@ import Ix.Kernel.Verify.Inductive.CandidateSyntax Lean's kernel `Level` and `Expr` values expose fast Boolean equality but do not provide the proof-producing decidable equality needed to certify a -native-evaluated checker result. The E2c constructor bridge needs exactly +native-evaluated checker result. The inductive verification constructor bridge needs exactly that implication: a finite computation may observe an expression, but the public proof must recover structural equality without importing reflected implementation equations. @@ -57,7 +57,7 @@ def literalCheck : Lean.Literal → Lean.Literal → Bool All fields which contribute to kernel expression equality are compared, including binder names and annotations. Metavariable nodes are supported so -the checker remains useful for exact failure diagnostics, although E2c's +the checker remains useful for exact failure diagnostics, although inductive verification's successful constructor candidates contain none. -/ def exprCheck : Lean.Expr → Lean.Expr → Bool | .bvar left, .bvar right => decide (left = right) diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean index 78c4e2a5b..6af991ade 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAcceptanceClosure.lean @@ -7,7 +7,7 @@ import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains The exhaustive recursor comparison retains exactly one type DefEq call and one RHS DefEq call per positional rule. This module interprets those calls -through K2S's finite successor-layer method contract. It does not require a +through the finite successor-layer contract for scoped methods. It does not require a global DefEq oracle or place every expression in an unbounded call domain. -/ @@ -74,7 +74,7 @@ end Methods.ActiveScopedWFAtOn namespace RecM /-- A successful selected-candidate comparison is semantically canonical -under the same finite K2S successor-layer contract used by the production +under the same finite scoped method successor-layer contract used by the production recursive-method knot. -/ theorem checkGeneratedRecursorCandidate_canonicalScoped {trProj : RawProjRel} {world : VerifyWorld} diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorAdmission.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAdmission.lean index 6709d5c35..cb69f6640 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorAdmission.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Canonical generated-recursor admission -This module closes the first E2c production recursor transaction. The +This module proves admission for a production-generated recursor. The certified family transaction has already installed `IndexedVec.rec` and its two equations in Ix.Theory.Named's Theory environment. Ix nevertheless keeps the separately ingressed recursor block untrusted while @@ -173,7 +173,7 @@ theorem familyMemberCheckStable : /-- One premise-free statement joins the real outer member run, exhaustive canonical artifact comparison, exact oracle-free admission, and stable cache -publication. This is the first E2c recursor transaction closed at the same +publication. This recursor transaction is proved at the same boundary used by coordinated block checking. -/ structure CanonicalRecursorAtomicClosure : Prop where memberRun : diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorCheckerFixture.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorCheckerFixture.lean index f6fcce8c8..090f0ea08 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorCheckerFixture.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorCheckerFixture.lean @@ -244,7 +244,7 @@ theorem familyAcceptedWorld_nameOf_eq : familyAcceptedWorld.nameOf = nameOf := rfl /-- Transport the concrete closed-type translations to the exact suffix-model -universe count selected by K2S. -/ +universe count selected by the scoped method contract. -/ theorem familySelectionTranslationsScoped {model : ScopedKernelSuffixModel RawProjRel.none familyAcceptedWorld} (uvars : transaction.certificate.generation.recursor.uvars = @@ -256,7 +256,7 @@ theorem familySelectionTranslationsScoped familyAcceptedWorld_nameOf_eq, ← uvars] using familySelectionTranslations -/-- The concrete selection phase preserves the scoped K2 invariant under the +/-- The concrete selection phase preserves the scoped inference/conversion invariant under the same finite successor layer later used for exhaustive artifact comparison. -/ theorem familySelectionInvariantScoped {model : ScopedKernelSuffixModel RawProjRel.none familyAcceptedWorld} @@ -284,7 +284,7 @@ theorem familySelectionInvariantScoped successor initialInvariant selection /-- All concrete production and representation premises are discharged. The -remaining semantic inputs are selection-state preservation and the K2 meaning +remaining semantic inputs are selection-state preservation and the inference/conversion meaning of the exact three comparison calls. -/ theorem familyCacheCheckCanonical {invariant : TcState .anon → Prop} @@ -309,7 +309,7 @@ theorem familyCacheCheckCanonical familyInstalledRecursorCanonicalAt familyStoredArtifactTranslations familyArtifactCallPlanAt selectionInvariant defEq -/-- Concrete E2c checker closure: one finite K2S successor-layer contract +/-- Concrete checker closure: one finite scoped method successor-layer contract accounts for the selection call, the repeated full-type comparison, and both positional rule comparisons. -/ theorem familyCacheCheckCanonicalScoped diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorInitialInvariant.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorInitialInvariant.lean index 125320ce2..ff507a98a 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorInitialInvariant.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorInitialInvariant.lean @@ -1062,7 +1062,7 @@ private theorem familyMemberNatReferenceWhnf : familyMemberWhnfTheory.projections.wf trivial) /-- Lift one finite WHNF census fact to complete provenance in the full -inductive-aware K1/K2 semantic stack. -/ +inductive-aware reduction, inference, and conversion semantic stack. -/ private theorem familyMemberWhnfEntryProvenance {kind : ExprCacheKind} (isWhnf : kind.IsWhnf) {key : Address × Address} {value : KExpr .anon} @@ -1619,7 +1619,7 @@ private theorem familyMemberBlockResultProvenance /-- Every physical semantic cache entry in the reached production state has finite support, authorized direct roots, and the meaning assigned by the -complete K1/K2/inductive cache stack. -/ +complete reduction, inference, conversion, and inductive cache stack. -/ theorem familyMemberInitial_cacheInvariant : CacheInvariant (kernelCacheSemanticsWithInductives familyMemberModel.keys diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberCheck.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberCheck.lean index bb6320dc7..e67b630e2 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberCheck.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberCheck.lean @@ -13,7 +13,7 @@ cache entry. Its tail selects one generated entry and exhaustively compares the frozen stored type and rules. This module proves the exact operational handoff. It intentionally does not -postulate that the prelude preserves the K2S invariant; subsequent modules +postulate that the prelude preserves the scoped method invariant; subsequent modules must prove that from the individual production operations. -/ diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberFixture.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberFixture.lean index 17324a966..fd3e7e8c9 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberFixture.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorMemberFixture.lean @@ -213,7 +213,7 @@ theorem familyMemberInitial_preservesScoped recursive fixture the `TrustedReferences` premise cannot be instantiated: the installed `cons` rule names `IndexedVec.rec`, which has not yet crossed the recursor-block admission boundary. The active theorem below is the -constructive E2c path. -/ +constructive inductive verification path. -/ theorem familyInstalledRecursorsProvenance {model : ScopedKernelSuffixModel RawProjRel.none familyAcceptedWorld} {layer : WhnfLayer} {support : RunSupport} @@ -2234,7 +2234,7 @@ theorem familyMemberCheckExecution : /-! ## Scoped semantic closure of the reached tail -/ -/-- Selection from the actual post-prelude state preserves the scoped K2S +/-- Selection from the actual post-prelude state preserves the scoped method invariant under the same finite call contract as the cache-only fixture. -/ theorem familyPreparedSelectionInvariantScoped {model : ScopedKernelSuffixModel RawProjRel.none familyAcceptedWorld} diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorSelection.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSelection.lean index 9183b0c16..973034adc 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorSelection.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSelection.lean @@ -219,7 +219,7 @@ theorem selectGeneratedRecursorIndex_preserves rw [run] at post exact post.1 -/-- K2S's finite successor-layer contract supplies state preservation for +/-- The finite successor-layer contract for scoped methods preserves state during exactly the complete closed type calls named by a selection plan. -/ theorem selectGeneratedRecursorIndex_preservesScoped {trProj : RawProjRel} {world : VerifyWorld} diff --git a/Ix/Kernel/Verify/Inductive/GeneratedRecursorSemantics.lean b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSemantics.lean index 90a3e53e1..821b8e1a0 100644 --- a/Ix/Kernel/Verify/Inductive/GeneratedRecursorSemantics.lean +++ b/Ix/Kernel/Verify/Inductive/GeneratedRecursorSemantics.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Trans /-! # Canonical semantics of generated recursor artifacts -This is the representation boundary for E2c's generated artifacts. It names +This is the representation boundary for inductive verification's generated artifacts. It names the exact structural correspondence that the production builders must prove: the generated type is Ix.Theory.Named's `GenerationChecked.recType`, and rule `i` is Ix.Theory.Named's `GenerationChecked.rule i` for constructor `i`. Rule lookup is diff --git a/Ix/Kernel/Verify/Inductive/IndexedCandidateSyntax.lean b/Ix/Kernel/Verify/Inductive/IndexedCandidateSyntax.lean index 3629e913a..202490ea7 100644 --- a/Ix/Kernel/Verify/Inductive/IndexedCandidateSyntax.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedCandidateSyntax.lean @@ -24,7 +24,7 @@ The upstream replay exposes the right executable values, but its public trace. Merely mentioning that projection therefore imports the replay's reflection axioms into a downstream theorem statement. Reconstruct the same post-family context and constructor-local binders directly from transparent -data. These are the values E2c relates to production Ix execution. +data. These are the values inductive verification relates to production Ix execution. -/ /-- Post-family context in which the two IndexedVec constructors are checked. diff --git a/Ix/Kernel/Verify/Inductive/IndexedCandidateTransaction.lean b/Ix/Kernel/Verify/Inductive/IndexedCandidateTransaction.lean index 75bfda340..5f19f90ed 100644 --- a/Ix/Kernel/Verify/Inductive/IndexedCandidateTransaction.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedCandidateTransaction.lean @@ -19,7 +19,7 @@ open Ix.Theory.Named open Ix.Theory.Named.InductiveFixtures open Ix.Theory.Named.InductiveReplayFixtures -/-- The Spec-01E package retains the exact source declaration and checked +/-- The producer-selected package retains the exact source declaration and checked generation selected by the ordinary metadata producer. -/ noncomputable def exactPackage : VInductDecl.ExactProducedGenerationCandidatePackage natFinalEnv [`u] @@ -45,7 +45,7 @@ noncomputable def exactProducedTransaction : exact indexedVecSemantic_addInductCertified beforeWF := natWF -/-- Intentional operational erasure of the exact Spec-01E indices. -/ +/-- Operational erasure of the exact source and generation indices. -/ noncomputable def producedTransaction : ProducedGenerationTransaction natFinalEnv indexedVecFinalEnv [`u] := exactProducedTransaction.toProduced diff --git a/Ix/Kernel/Verify/Inductive/IndexedPositivityTransport.lean b/Ix/Kernel/Verify/Inductive/IndexedPositivityTransport.lean index c9fda586b..c0c3cc0e7 100644 --- a/Ix/Kernel/Verify/Inductive/IndexedPositivityTransport.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedPositivityTransport.lean @@ -20,7 +20,7 @@ open Ix.Theory.Named.InductiveReplayFixtures The upstream replay modules are useful for naming the exact candidate states, but their proof lemmas intentionally depend on reflected implementation -equations. E2c does not inherit that trust. Recheck the finite observations +equations. Inductive verification does not inherit that trust. Recheck the finite observations consumed below with private native facts, so the exported transport depends on the concrete executions without admitting those reflected equations. -/ diff --git a/Ix/Kernel/Verify/Inductive/IndexedProducerClosure.lean b/Ix/Kernel/Verify/Inductive/IndexedProducerClosure.lean index 82113542d..e8495a95e 100644 --- a/Ix/Kernel/Verify/Inductive/IndexedProducerClosure.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedProducerClosure.lean @@ -6,7 +6,7 @@ import Ix.Kernel.Verify.Inductive.IndexedCandidateTransaction The trust-minimal `IndexedVec` Theory transaction and the executable Ix.Theory.Named candidate replay are intentionally audited separately. This module -joins them only at a stronger E2c root: the exact producer-selected package +joins them only at a stronger inductive verification root: the exact producer-selected package erases to the same certificate transaction consumed by the Ix family and generated-recursor admission, while all three anonymous ingress calls and both production block checks remain explicit. diff --git a/Ix/Kernel/Verify/Inductive/IndexedRecursiveCertificate.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursiveCertificate.lean index cb47c4ea1..a3dac73ee 100644 --- a/Ix/Kernel/Verify/Inductive/IndexedRecursiveCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursiveCertificate.lean @@ -7,7 +7,7 @@ import Ix.Theory.Named.Verify.Environment.InductiveFixtures Ix.Theory.Named's `IndexedVec` fixture is the first certificate in the dependency whose source is simultaneously parameterized, indexed, and recursive. This module reconstructs it through the Theory-only proof-carrying transaction -boundary and records the exact breadth facts that distinguish it from E2b's +boundary and records the exact breadth facts that distinguish it from singleton certification's Boolean enumeration. The ambient `Nat` environment is reconstructed through its own certified @@ -75,7 +75,7 @@ normalization candidate; it is not an independently regenerated artifact. -/ transaction.certificate.generation = indexedVecChecked.identityGeneration := rfl -/-- Auditable shape of the first non-enumeration E2c certificate. +/-- Auditable shape of the indexed recursive certificate. The recursive argument is the third constructor field and targets the sole family at the predecessor index. The constructor result advances that index @@ -111,7 +111,7 @@ structure BreadthFacts : Prop where theorem breadth : BreadthFacts := by constructor <;> rfl -/-- Stable semantic consequences obtained only from the Ix E2a adapter. -/ +/-- Stable semantic consequences obtained only from the Ix certified generation adapter. -/ theorem certifiedFacts : CertifiedGenerationFacts natFinalEnv indexedVecFinalEnv transaction.certificate := diff --git a/Ix/Kernel/Verify/Inductive/IndexedRecursiveSoundness.lean b/Ix/Kernel/Verify/Inductive/IndexedRecursiveSoundness.lean index 5c2bedecf..639f00d79 100644 --- a/Ix/Kernel/Verify/Inductive/IndexedRecursiveSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/IndexedRecursiveSoundness.lean @@ -6,7 +6,7 @@ open Ix.Theory (VLevel) # Indexed recursive iota soundness This module opens the two generated `IndexedVec.rec` equations selected by -the E2a certificate and relates them to the dependent patterns consumed by +the certified generation certificate and relates them to the dependent patterns consumed by production WHNF. All equation shapes below reduce from the retained `GenerationChecked.rule`; no independently supplied rewrite law is used. -/ diff --git a/Ix/Kernel/Verify/Inductive/IotaPattern.lean b/Ix/Kernel/Verify/Inductive/IotaPattern.lean index 7022c09d1..b7d826c79 100644 --- a/Ix/Kernel/Verify/Inductive/IotaPattern.lean +++ b/Ix/Kernel/Verify/Inductive/IotaPattern.lean @@ -8,7 +8,7 @@ open Ix.Theory (VLevel) `Pattern.varN` captures application arguments from left to right, but its dependent `Path` type represents the newest argument as `none` and every older argument under another `some`. The definitions and proofs below make -that ordering explicit. E2b uses them to select the certified minor premise +that ordering explicit. Singleton certification uses them to select the certified minor premise at a constructor's exact rule index; an off-by-one or reversed-spine adapter cannot satisfy the positional theorem. -/ diff --git a/Ix/Kernel/Verify/Inductive/MutualBlockCertificate.lean b/Ix/Kernel/Verify/Inductive/MutualBlockCertificate.lean index 15731b877..8794dafb1 100644 --- a/Ix/Kernel/Verify/Inductive/MutualBlockCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/MutualBlockCertificate.lean @@ -4,13 +4,13 @@ import Ix.Theory.Named.Verify.Environment.MutualInductiveFixtures /-! # Genuine mutual-block certificate fixture -`Tree`/`TreeList` is the first E2c witness that cannot be represented honestly -by a singleton transaction. It has two mutually visible families, five +`Tree`/`TreeList` requires one atomic mutual-block transaction. It has two +mutually visible families, five globally flattened constructors, one generated recursor per family, and five globally flattened iota rules. Recursive fields target both the sibling family and their own family, including one recursive occurrence below a Pi. -This module consumes Ix.Theory.Named's retained Spec-08 certificate through Ix's +This module consumes Ix.Theory.Named's block-generation certificate through Ix's Theory-only block adapter. Physical Ix ingress, checker execution, catalog linkage, and recursor admission remain separate obligations. -/ @@ -80,7 +80,7 @@ theorem breadth : BreadthFacts where treeListTargetsItself := rfl /-- Complete block-wide family/constructor/recursor/rule consequences from -the exact retained Spec-08 transaction. -/ +the exact block-generation transaction. -/ theorem certifiedFacts : CertifiedBlockGenerationFacts VEnv.empty treeFinalEnv transaction.certificate := diff --git a/Ix/Kernel/Verify/Inductive/MutualRecursorAdmission.lean b/Ix/Kernel/Verify/Inductive/MutualRecursorAdmission.lean index f2368aad5..d8bcc18b8 100644 --- a/Ix/Kernel/Verify/Inductive/MutualRecursorAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/MutualRecursorAdmission.lean @@ -1017,7 +1017,7 @@ theorem familyRecursorBlockAccepted : familyRecursorAcceptedWorld.AcceptedBlock recursorBlockId := familyRecursorAtomicAdmission.accepted -/-- E3-FP's first conditional mutual checkpoint. Every physical and +/-- Conditional mutual-inductive admission. Every physical and semantic fact is closed for the two-family/five-constructor/two-recursor transaction. Its transitive trust boundary retains exactly the two quarantined upstream witnesses: reversed-family generation WF and generated diff --git a/Ix/Kernel/Verify/Inductive/NestedRecursiveFixture.lean b/Ix/Kernel/Verify/Inductive/NestedRecursiveFixture.lean index 65551c631..ed52f7f89 100644 --- a/Ix/Kernel/Verify/Inductive/NestedRecursiveFixture.lean +++ b/Ix/Kernel/Verify/Inductive/NestedRecursiveFixture.lean @@ -5,7 +5,7 @@ import Ix.Kernel.Verify.Ingress.AnonStructural /-! # Concrete nested-recursive reachability fixture -This fixture isolates the cross-stage E2c obligation with two compiler-shaped +This fixture isolates the cross-stage inductive verification obligation with two compiler-shaped anonymous blocks: * `Box (α : Sort 1) : Sort 1`, with `wrap : α → Box α`; diff --git a/Ix/Kernel/Verify/Inductive/OccurrenceClosure.lean b/Ix/Kernel/Verify/Inductive/OccurrenceClosure.lean index d66f5f8fb..9c24aa2d1 100644 --- a/Ix/Kernel/Verify/Inductive/OccurrenceClosure.lean +++ b/Ix/Kernel/Verify/Inductive/OccurrenceClosure.lean @@ -4,10 +4,10 @@ import Ix.Kernel.Verify.RecursiveMethods.ScopedCallDomains /-! # Run-scoped recursive-occurrence closure -The first E2c occurrence slice exposes the exact `isDefEq` calls made while +Occurrence verification exposes the exact `isDefEq` calls made while checking uniform recursive parameters, but deliberately leaves their semantic meaning behind `PositiveParameterDefEqContract`. This module closes that -boundary against K2S's actual finite successor-layer method contract. +boundary against the finite successor-layer contract for scoped methods. The call evidence is positional. We require only the parameter pairs that the successful production loop executed, rather than admitting every pair of @@ -29,7 +29,7 @@ def PositiveParameterCallPlan (calls : Methods.CallDomain) namespace RecM.PositiveParameterComparisonTrace /-- Interpret every successful parameter comparison through the real -successor method-table layer selected by K2S. +successor method-table layer selected by the scoped method contract. `Methods.next methods` is definitionally the six production algorithms run with `methods` as their recursive callback table. Its `isDefEq` field is diff --git a/Ix/Kernel/Verify/Inductive/OccurrenceValidation.lean b/Ix/Kernel/Verify/Inductive/OccurrenceValidation.lean index 2751b612c..d1edee567 100644 --- a/Ix/Kernel/Verify/Inductive/OccurrenceValidation.lean +++ b/Ix/Kernel/Verify/Inductive/OccurrenceValidation.lean @@ -7,7 +7,7 @@ import Ix.Kernel.Verify.World /-! # Recursive-occurrence validation -E2c consumes the successful branch of production positivity checking. This +Inductive verification consumes the successful branch of production positivity checking. This module makes that branch proof-visible: a success identifies the active family, the exact loaded inductive header, every pure arity/universe/index guard, and the complete state-threaded parameter-definitional-equality loop. @@ -101,8 +101,8 @@ def TranslatedParameterDefEq This contract intentionally stops at the production `isDefEq` call. It does not grant positivity access to the complete DefEq closure, proposition -classification, or inductive authority. K2 may instantiate it from an -oracle-free recursive-method closure; E2c only consumes the successful-call +classification, or inductive authority. Inference/conversion proofs may instantiate it from an +oracle-free recursive-method closure; inductive verification only consumes the successful-call meaning and state preservation recorded here. -/ def PositiveParameterDefEqContract (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) diff --git a/Ix/Kernel/Verify/Inductive/PositivityTraversal.lean b/Ix/Kernel/Verify/Inductive/PositivityTraversal.lean index 338a5867d..12196da49 100644 --- a/Ix/Kernel/Verify/Inductive/PositivityTraversal.lean +++ b/Ix/Kernel/Verify/Inductive/PositivityTraversal.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Inductive.OccurrenceValidation /-! # Production positivity traversal -E2c must account for the recursive control flow that reaches occurrence +Inductive verification must account for the recursive control flow that reaches occurrence validation, rather than assuming that a particular constructor field was already reduced to an active-family application. This module starts that assembly at the production `checkPositivityDomainFuel` entry point. diff --git a/Ix/Kernel/Verify/Inductive/ProducedGenerationTransaction.lean b/Ix/Kernel/Verify/Inductive/ProducedGenerationTransaction.lean index 0f6b94cc2..2674524d6 100644 --- a/Ix/Kernel/Verify/Inductive/ProducedGenerationTransaction.lean +++ b/Ix/Kernel/Verify/Inductive/ProducedGenerationTransaction.lean @@ -9,7 +9,7 @@ generation certificate and the exact `VEnv.addInductCertified` result, but it does not remember which ordinary Ix.Theory.Named metadata execution selected that certificate. -For E2c we need both facts at once. A successful outer producer call must not +For inductive verification we need both facts at once. A successful outer producer call must not be allowed to justify Theory semantics by itself, and an independently chosen Theory certificate must not be passed off as the result of that producer. The record below therefore owns Ix.Theory.Named's dependent @@ -50,7 +50,7 @@ def certificate {before after : VEnv} {Us : List Name} /-- Erase only the Verify-side producer provenance, preserving the exact package-owned source, certificate, successful post-environment, and input WF -evidence in E2a's Theory-only transaction. -/ +evidence in the Theory-only transaction. -/ def toCertified {before after : VEnv} {Us : List Name} (tx : ProducedGenerationTransaction before after Us) : CertifiedGenerationTransaction tx.source before after where @@ -67,7 +67,7 @@ def toCertified {before after : VEnv} {Us : List Name} tx.toCertified.certificate.generation = tx.package.package.generation := rfl -/-- Exact producer and semantic-transition facts retained at the E2c +/-- Exact producer and semantic-transition facts retained at the inductive verification boundary. In particular, the outer producer equation and the Theory certificate are projections of one dependent package rather than unrelated premises. -/ @@ -98,7 +98,7 @@ end ProducedGenerationTransaction /-! ## Exact dependent producer transactions -/ -/-- The Spec-01E producer closure before source and generation indices are +/-- The producer closure before source and generation indices are erased. Its type retains the exact raw family, kernel source, producer arguments, normalized source declaration, and checked generation selected by one successful outer candidate execution. diff --git a/Ix/Kernel/Verify/Inductive/RecursivePiAdmission.lean b/Ix/Kernel/Verify/Inductive/RecursivePiAdmission.lean index 0d02dcc1b..da7441e39 100644 --- a/Ix/Kernel/Verify/Inductive/RecursivePiAdmission.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiAdmission.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Inductive.OneFamilyAdmission /-! # Oracle-free recursive-Pi admission -This module closes the concrete `Acc` E2c transaction. The family and its +This module closes the concrete `Acc` inductive verification transaction. The family and its constructor are admitted by the exact certified Theory-environment transition. The separately ingressed and production-checked `Acc.rec` block is then admitted from semantic entries already installed by that transition. diff --git a/Ix/Kernel/Verify/Inductive/RecursivePiCertificate.lean b/Ix/Kernel/Verify/Inductive/RecursivePiCertificate.lean index f6f4a4824..19e36c0d8 100644 --- a/Ix/Kernel/Verify/Inductive/RecursivePiCertificate.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiCertificate.lean @@ -5,8 +5,7 @@ import Ix.Theory.Named.InductiveFixtures # Certified recursive-Pi generation fixture `Acc.intro` contains a recursive occurrence beneath a two-binder function -telescope. This is the next one-family E2c breadth case after `IndexedVec`: -the recursive argument is not a direct family application, and its induction +telescope. The recursive argument is not a direct family application, and its induction hypothesis is itself a function. This module stays on the Theory-only side of the boundary. It constructs the @@ -81,7 +80,7 @@ structure BreadthFacts : Prop where theorem breadth : BreadthFacts := by constructor <;> rfl -/-- Stable semantic consequences obtained through the same generic E2a +/-- Stable semantic consequences obtained through the same generic certified generation adapter used by the IndexedVec transaction. -/ theorem certifiedFacts : CertifiedGenerationFacts VEnv.empty finalEnv transaction.certificate := diff --git a/Ix/Kernel/Verify/Inductive/RecursivePiSoundness.lean b/Ix/Kernel/Verify/Inductive/RecursivePiSoundness.lean index e880344ef..c0f5dfbe6 100644 --- a/Ix/Kernel/Verify/Inductive/RecursivePiSoundness.lean +++ b/Ix/Kernel/Verify/Inductive/RecursivePiSoundness.lean @@ -6,7 +6,7 @@ open Ix.Theory (VLevel) # Recursive-Pi iota soundness This module proves that the production `Acc.intro` iota pattern denotes the -exact registered equation generated by the E2a certificate. Both uniform +exact registered equation generated by the certified generation certificate. Both uniform parameters and the result index are aligned semantically before the closed equation is applied. The pattern RHS remains the exact registered RHS application, so the functional induction hypothesis beneath two lambdas is diff --git a/Ix/Kernel/Verify/Inductive/SingletonEnumeration.lean b/Ix/Kernel/Verify/Inductive/SingletonEnumeration.lean index ff64eaac0..8d6a4a3b5 100644 --- a/Ix/Kernel/Verify/Inductive/SingletonEnumeration.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonEnumeration.lean @@ -5,14 +5,14 @@ open Ix.Theory (VLevel) /-! # Certified singleton enumerations -This module is E2b's first executable inductive fragment. A singleton +This module certifies a fragment of singleton inductives. A singleton enumeration has no declaration universes, parameters, indices, constructor fields, or recursive arguments. It may have several nullary constructors, so its generated iota rules are non-vacuous: rule `i` returns the exact `i`-th minor premise. The restriction is intentionally stated over the normalized generation -retained by E2a. It is therefore a decidable fragment boundary around the +retained by certified generation. It is therefore a decidable fragment boundary around the actual generated artifacts, not a second inductive-declaration model. -/ @@ -22,16 +22,16 @@ open Ix.Theory.Named (VConstVal VEnv VExpr VInductDecl) namespace CertifiedSingletonGeneration -/-- The first executable E2b fragment: one nonempty, universe-free, +/-- The executable singleton fragment: one nonempty, universe-free, parameter-free, index-free family whose constructors are nullary and nonrecursive. -/ structure IsEnumeration {source : VInductDecl} (generation : source.GenerationChecked) : Prop where noUniverses : source.uvars = 0 noParameters : source.nparams = 0 - /-- E2b's enumeration pattern currently covers the ordinary large - eliminator. Small and K elimination use the Spec-06 universe layout and - remain explicit E2c breadth cases. -/ + /-- The enumeration pattern covers the ordinary large + eliminator. Small and K elimination use the certified universe layout and + require separate inductive-verification proofs. -/ largeElimination : generation.elimination = .large noIndices : generation.block.rawIndices = [] nonempty : 0 < generation.block.ctorPairs.length @@ -416,7 +416,7 @@ theorem enumerationConstructorAt | _ => simp [KConst.IsCertifiedSingletonConstructor] at hconcrete /-- All finite pattern metadata for an enum rule is forced by the two exact -catalog links and the E2a generation position. No semantic rewrite premise +catalog links and the certified generation position. No semantic rewrite premise is used here. -/ theorem enumerationPatternMetadata {trProj : RawProjRel} {catalog : Catalog} @@ -465,7 +465,7 @@ theorem enumerationPatternMetadata · simpa [enumerationPattern] using hruleFields /-- The compiled enum pattern is semantically justified by the exact -registered generated equation. This is the central E2b bridge: a successful +registered generated equation. This is the central singleton certification bridge: a successful pattern match is reduced through Ix.Theory.Named's registered equality, rather than through an independently postulated iota law. -/ theorem enumerationPatternSound diff --git a/Ix/Kernel/Verify/Inductive/SingletonFamily.lean b/Ix/Kernel/Verify/Inductive/SingletonFamily.lean index 57e960a1a..c69f0a4de 100644 --- a/Ix/Kernel/Verify/Inductive/SingletonFamily.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonFamily.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Inductive /-! # Certified singleton-family admission -This module is the first production-facing half of E2b. A Ix.Theory.Named +This module links singleton certificates to production declarations. An Ix.Theory.Named `CertifiedGenerationTransaction` already owns the semantic generation of one family, all of its constructors, its recursor, and its iota equations. What that transaction cannot know is which anonymous Ix addresses contain the @@ -22,7 +22,7 @@ link for the physical family block: The structure deliberately contains no `InductiveOracle`, environment-WF, environment-extension, constant-WF, or recursor-rule premise. Those facts -are derived below from the E2a transaction. The later checker adapter must +are derived below from the certified generation transaction. The later checker adapter must construct this link from ingress plus a successful production block run. -/ @@ -134,7 +134,7 @@ end CertifiedSingletonGeneration /-! ## Exact supported production shapes -/ -/-- The concrete family shape supported by the singleton E2b adapter. +/-- The concrete family shape supported by the singleton adapter. The singleton family is member zero of its physical inductive block. Its stored parameter and index counters must agree with the raw/view generation @@ -428,7 +428,7 @@ theorem noRecursorRuleAt exact hshape.noRecursorRuleAt ruleIndex rule /-- Construct the complete family-block oracle from the exact Ix/source link -and E2a's certified transaction. The recursor clauses are vacuous for this +and the certified generation transaction. The recursor clauses are vacuous for this physical block because it contains only the family and its constructors. -/ def oracle {trProj : RawProjRel} {catalog : Catalog} diff --git a/Ix/Kernel/Verify/Inductive/SingletonOracle.lean b/Ix/Kernel/Verify/Inductive/SingletonOracle.lean index b35038ec6..b6aeac4ca 100644 --- a/Ix/Kernel/Verify/Inductive/SingletonOracle.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonOracle.lean @@ -18,7 +18,7 @@ namespace SingletonRecursorCatalogLink /-- Construct a complete `InductiveOracle` for the actual singleton recursor block. Every rule and pattern is selected by its concrete array position and -is justified by the equation installed by the E2a transaction. -/ +is justified by the equation installed by the certified generation transaction. -/ def oracle {trProj : RawProjRel} {catalog : Catalog} {nameOf : Address → Option Lean.Name} {trusted : KId .anon → Prop} diff --git a/Ix/Kernel/Verify/Inductive/SingletonRecursor.lean b/Ix/Kernel/Verify/Inductive/SingletonRecursor.lean index f4e04c4d1..31dff523a 100644 --- a/Ix/Kernel/Verify/Inductive/SingletonRecursor.lean +++ b/Ix/Kernel/Verify/Inductive/SingletonRecursor.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Inductive.SingletonFamily /-! # Certified singleton-recursor correspondence -The Ix.Theory.Named transaction used by E2a installs a singleton family's recursor +The Ix.Theory.Named transaction used by certified generation installs a singleton family's recursor and all of its iota equations atomically with the family. Anonymous Ix ingress does not: the family/constructor block and the recursor block are distinct physical blocks. This module links the latter block to the exact @@ -70,7 +70,7 @@ end CertifiedSingletonGeneration /-! ## Exact supported recursor shape -/ -/-- Concrete recursor metadata supported by E2b's singleton adapter. +/-- Concrete recursor metadata supported by the singleton adapter. `motives = 1` is the explicit no-mutual/no-nested boundary of this adapter. The exact rule count is retained, and `RecursorMajorIdxCoherent` rules out the @@ -165,7 +165,7 @@ end KConst.IsCertifiedSingletonRecursor /-! ## Exact recursor/rule correspondence -/ /-- Positional correspondence between the one physical Ix recursor block and -the recursor/equations already installed by an E2a transaction. +the recursor/equations already installed by a certified generation transaction. The structure contains representation facts only. Registration, equation WF, recursor WF, and recursor-headedness are derived from the transaction and @@ -271,7 +271,7 @@ theorem ruleAt CertifiedSingletonGeneration.generatedRuleAt _ hnormalized, hfields, hraw, htyped⟩ -/-- E2a registration plus the exact positional Ix link yields the complete +/-- Certified registration plus the exact positional Ix link yields the complete registered-rule semantic relation. -/ theorem registeredRuleAt {trProj : RawProjRel} {catalog : Catalog} diff --git a/Ix/Kernel/Verify/Inductive/StructuralCacheSemantics.lean b/Ix/Kernel/Verify/Inductive/StructuralCacheSemantics.lean index 1a240ec47..d19cf0487 100644 --- a/Ix/Kernel/Verify/Inductive/StructuralCacheSemantics.lean +++ b/Ix/Kernel/Verify/Inductive/StructuralCacheSemantics.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.DefEq /-! # Certified semantics for inductive structural caches -The K1/K2 semantic stack deliberately gives no meaning to the three caches +The reduction, inference, and conversion semantic stack deliberately gives no meaning to the three caches owned only by inductive checking: generated recursors, the major-set to block index, and the peer-agreement marker. Rejecting those entries makes every stable post-inductive state uninhabitable, while accepting them without a @@ -52,7 +52,7 @@ theorem authorizesBlock_of_accepted {world : VerifyWorld} end CacheAuthority /-- Semantic ownership of the three inductive-only cache families. The -fallback retains the complete K1/K2 and block-result meanings. -/ +fallback retains the complete reduction, inference, and conversion and block-result meanings. -/ def StructuralInductiveCacheValid (fallback : CacheSemantics) (authority : CacheAuthority) (support : RunSupport) : CacheEntry → Prop | .recursor block generated => @@ -114,7 +114,7 @@ def structuralInductiveCacheSemantics intro authority support block h exact fallback.blockSuccessSound authority support block h -/-- The production K1/K2 stack with a non-vacuous meaning for every +/-- The production reduction, inference, and conversion stack with a non-vacuous meaning for every inductive structural cache family. -/ def kernelCacheSemanticsWithInductives (keys : WhnfContextKeys) (trProj : RawProjRel) : CacheSemantics := diff --git a/Ix/Kernel/Verify/Infer.lean b/Ix/Kernel/Verify/Infer.lean index b97f376b9..981a60b5f 100644 --- a/Ix/Kernel/Verify/Infer.lean +++ b/Ix/Kernel/Verify/Infer.lean @@ -2,9 +2,9 @@ import Ix.Kernel.Verify.Suffix import Ix.Kernel.Verify.Knot /-! -# K2 inference semantics +# Inference semantics -This module replaces the inference-cache portion of K1's fallback semantics +This module replaces the inference-cache portion of WHNF's fallback semantics with its exact Theory meaning. Algorithmic branch proofs will consume the hit and insertion interfaces defined here. -/ @@ -235,7 +235,7 @@ inductive IsInfer : ExprCacheKind → Prop end ExprCacheKind /-- Exact validity of the two inference cache families. All other entries -retain the semantics already established by the caller (normally K1 WHNF). +retain the semantics already established by the caller (normally WHNF). Persistent entries created under a later-popped local scope are required to carry semantic meaning only when their source is structurally in scope in the represented context. -/ @@ -283,7 +283,7 @@ theorem expr {keys : WhnfContextKeys} {trProj : RawProjRel} end InferCacheValid -/-- Overlay K2's inference meanings on the already-selected cache semantics. -/ +/-- Overlay inference meanings on the already-selected cache semantics. -/ def inferCacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) (fallback : CacheSemantics) : CacheSemantics where Valid := InferCacheValid keys trProj fallback diff --git a/Ix/Kernel/Verify/Infer/CacheSoundness.lean b/Ix/Kernel/Verify/Infer/CacheSoundness.lean index 54061b764..0915a3683 100644 --- a/Ix/Kernel/Verify/Infer/CacheSoundness.lean +++ b/Ix/Kernel/Verify/Infer/CacheSoundness.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Infer.Dispatcher # Inference cache soundness This module closes the production `inferWith` shell around the exhaustive -uncached dispatcher. Cache hits are accepted only through canonical K2 +uncached dispatcher. Cache hits are accepted only through canonical inference/conversion provenance. Cache misses build new provenance from the exact key execution, finite expression collision freedom, suffix transport, and the concrete uncached typing result before mutating either cache partition. @@ -14,7 +14,7 @@ namespace Ix.Kernel namespace TcM -/-- A joint K2 suffix model turns the actual inference-key execution into the +/-- A joint inference/conversion suffix model turns the actual inference-key execution into the same operational match used to validate both hits and writes. -/ theorem inferKey_model_matches_wf {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} diff --git a/Ix/Kernel/Verify/Infer/Callbacks.lean b/Ix/Kernel/Verify/Infer/Callbacks.lean index 849a4183c..409466eda 100644 --- a/Ix/Kernel/Verify/Infer/Callbacks.lean +++ b/Ix/Kernel/Verify/Infer/Callbacks.lean @@ -14,7 +14,7 @@ namespace Ix.Kernel namespace DirectWhnf /-- Semantic contract for the direct `RecM.whnf` body at one universe count. -K1's fixed-universe closure constructs this contract when K2 assembles the +WHNF's fixed-universe closure constructs this contract when inference/conversion assembles the joint layer. -/ def WFAt (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) : Prop := diff --git a/Ix/Kernel/Verify/Infer/CheapBeta.lean b/Ix/Kernel/Verify/Infer/CheapBeta.lean index f7feb33a0..0f6dc5d9d 100644 --- a/Ix/Kernel/Verify/Infer/CheapBeta.lean +++ b/Ix/Kernel/Verify/Infer/CheapBeta.lean @@ -209,7 +209,7 @@ theorem cheapBetaPlan?_simul cases hplan /-- Cheap beta reduction preserves the Theory meaning of a structurally -translated source. A successful plan is discharged by K1's constructive +translated source. A successful plan is discharged by WHNF's constructive multi-beta theorem; an absent plan is reflexive. -/ theorem KExpr.cheapBetaReduceResult_meaning {trProj : RawProjRel} {world : VerifyWorld} {uvars : Nat} diff --git a/Ix/Kernel/Verify/Infer/Constants.lean b/Ix/Kernel/Verify/Infer/Constants.lean index d40014ef9..cbebc9303 100644 --- a/Ix/Kernel/Verify/Infer/Constants.lean +++ b/Ix/Kernel/Verify/Infer/Constants.lean @@ -9,7 +9,7 @@ open Ix.Theory (VLevel) This module verifies required constant lookup, universe-arity checking, and type instantiation. The trusted world currently retains only `RawExprRel` for declaration types; inference needs the stronger typed `TrKExprS` -relation. `TrustedConstTypes` names that boundary explicitly so the final K2 +relation. `TrustedConstTypes` names that boundary explicitly so the final inference/conversion closure must derive it from declaration admission rather than silently upgrading raw syntax correspondence. -/ @@ -76,7 +76,7 @@ theorem getConst_loaded_wf {I : TcState .anon → Prop} end TcM /-- Typed declaration-type evidence missing from the current raw trusted -catalog interface. K2 closure must construct this for every trusted +catalog interface. Inference/conversion closure must construct this for every trusted constant that a supported run can infer. -/ def TrustedConstTypes (trProj : RawProjRel) (world : VerifyWorld) : Prop := ∀ {id : KId .anon} {c : KConst .anon}, diff --git a/Ix/Kernel/Verify/Ingress/LiteralBlobs.lean b/Ix/Kernel/Verify/Ingress/LiteralBlobs.lean index 4b266d104..3da42d29c 100644 --- a/Ix/Kernel/Verify/Ingress/LiteralBlobs.lean +++ b/Ix/Kernel/Verify/Ingress/LiteralBlobs.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Ingress.Representation /-! # Serialized literal/blob ingress -This T0 fixture makes the blob side of the serialized representation +This fixture makes the blob side of the serialized representation contract non-vacuous. A Nat literal and a String literal are stored in one Ixon environment, serialized, decoded with the pure reference decoder, and ingressed through the production anonymous lazy-fault path. Separate @@ -418,7 +418,7 @@ def literalCertificate : LiteralBlobRoundTrip where stringRun := stringRun stringLoaded := stringLoadedNative -/-- Non-vacuous T0 literal/blob round-trip through serialized bytes and the +/-- Non-vacuous literal/blob round-trip through serialized bytes and the actual anonymous ingress implementation. -/ theorem literalRoundTrip : Nonempty LiteralBlobRoundTrip := ⟨literalCertificate⟩ diff --git a/Ix/Kernel/Verify/Ingress/Representation.lean b/Ix/Kernel/Verify/Ingress/Representation.lean index 4711d3c26..b122a56b5 100644 --- a/Ix/Kernel/Verify/Ingress/Representation.lean +++ b/Ix/Kernel/Verify/Ingress/Representation.lean @@ -12,10 +12,9 @@ hashes, blob hashes, the canonical constant Merkle root, sorted table keys, the optional main pointer, and trailing-byte exhaustion. The predicates below retain the resulting facts in the exact form consumed by ingress. -The mmap-backed Rust decoder `Ixon.deEnvAnon` is intentionally not equated to -the pure decoder here. That implementation/refinement result belongs to the -later Rust transport phase; T0 reasons from the pure decoder and the actual -Lean eager/lazy ingress functions. +The mmap-backed Rust decoder `Ixon.deEnvAnon` requires a separate refinement +proof relating it to the pure decoder. This module reasons from the pure +decoder and the actual Lean eager/lazy ingress functions. -/ namespace Ix.Kernel diff --git a/Ix/Kernel/Verify/Ingress/SerializedBoolean.lean b/Ix/Kernel/Verify/Ingress/SerializedBoolean.lean index fbd208d02..7d05c3948 100644 --- a/Ix/Kernel/Verify/Ingress/SerializedBoolean.lean +++ b/Ix/Kernel/Verify/Ingress/SerializedBoolean.lean @@ -5,10 +5,10 @@ import Ix.Kernel.Verify.Ingress.Representation /-! # Serialized Boolean acceptance -This is the first complete T0 vertical slice. It serializes the certified +This fixture serializes the certified Boolean Ixon environment, decodes the resulting bytes with the pure reference decoder, erases anonymous-irrelevant metadata, and reconnects the decoded -source to the existing E3-S semantic world. +source to the semantic world of the supported Boolean fragment. -/ namespace Ix.Kernel @@ -879,7 +879,7 @@ private theorem originalFamilyProjectionLookupNative : some familyProjectionConstant := by native_decide -/-- Successful lookups in the in-memory source used by E3-S have the exact +/-- Successful lookups in the in-memory source used by the Boolean proof have the exact same materialized value after serialization and pure decoding. The finite key classification avoids any appeal to injectivity of content hashes. -/ private theorem decodedGetConst_of_original {addr : Address} @@ -927,7 +927,7 @@ private theorem decodedGetConst_of_original {addr : Address} subst constant exact familyProjectionEntry.getConst -/-- Every dependency used by the E3-S Boolean proof is a reference stored in +/-- Every dependency used by the Boolean proof is a reference stored in the corresponding constant recovered from the decoded byte array. -/ theorem dependencyBound : SerializedDependencyBound env dependencyGraph := by @@ -968,7 +968,7 @@ theorem checkEnvAnon_eq : checkEnvAnon env checkCfg = .ok successfulResults := checkEnvAnonNative -/-! ## Public T0 certificate -/ +/-! ## Public serialized-ingress certificate -/ def certificate : SerializedSubjectCertificate bytes stagedWorld dependencyGraph @@ -987,7 +987,7 @@ def certificate : resultsSucceeded := allResultsSucceeded semantic := semanticSubjectWF -/-- T0-S: the serialized Boolean environment passes pure decoding, integrity +/-- The serialized Boolean environment passes pure decoding, integrity checks, exact eager and cold-lazy ingress, production checking, dependency binding, and the existing semantic acceptance theorem. -/ theorem subjectWF : diff --git a/Ix/Kernel/Verify/Knot.lean b/Ix/Kernel/Verify/Knot.lean index a4fda3c5c..4b9f5c253 100644 --- a/Ix/Kernel/Verify/Knot.lean +++ b/Ix/Kernel/Verify/Knot.lean @@ -13,9 +13,9 @@ finite method table. This file isolates the non-circular proof shape: * `methodsOut_wf` and `methodsN_wf` close every finite approximation; and * `TcM.runRec_wf` transports a reader-level proof to the public knot runner. -The remaining K2 work is therefore deliberately visible in `Methods.Closed`: -K1 supplies the four WHNF fields and K2 supplies inference and definitional -equality. No theorem below assumes the recursive table is already closed. +`Methods.Closed` retains the four WHNF fields and the inference and +definitional-equality fields as explicit obligations. No theorem below +assumes the recursive table is already closed. -/ namespace Ix.Kernel @@ -39,7 +39,7 @@ def LayerWFAt (layer : WhnfLayer) (semantics : CacheSemantics) (uvars : Nat) (methods : Methods .anon) : Prop := Methods.WFAt layer semantics trProj world support uvars (next methods) -/-- K1's four fields for one unfolded method-table layer at a fixed universe +/-- WHNF's four fields for one unfolded method-table layer at a fixed universe count. This is the closure shape used by universe-indexed WHNF and unfold cache semantics. -/ structure WhnfLayerWFAt (layer : WhnfLayer) (semantics : CacheSemantics) @@ -78,7 +78,7 @@ structure WhnfLayerWFAt (layer : WhnfLayer) (semantics : CacheSemantics) (fun result _ => support result ∧ WhnfPost trProj world uvars Delta sourceV result) -/-- K2's two fields for one unfolded method-table layer at a fixed universe +/-- The two inference/conversion fields for one unfolded method-table layer at a fixed universe count. -/ structure InferDefEqLayerWFAt (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) @@ -103,7 +103,7 @@ structure InferDefEqLayerWFAt (layer : WhnfLayer) (fun answer _ => answer = true → world.venv.IsDefEqU uvars Delta.toCtx va vb) -/-- The fixed-universe K1 and K2 records assemble the exact next layer. -/ +/-- The fixed-universe WHNF and inference/conversion records assemble the exact next layer. -/ theorem LayerWFAt.of_parts {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -129,8 +129,8 @@ def ClosedAt (layer : WhnfLayer) (semantics : CacheSemantics) Methods.WFAt layer semantics trProj world support uvars methods → LayerWFAt layer semantics trProj world support uvars methods -/-- K1's fixed-universe closure obligation, independent of construction of -the two K2 fields. -/ +/-- WHNF's fixed-universe closure obligation, independent of construction of +the two inference/conversion fields. -/ def WhnfClosedAt (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) : Prop := @@ -138,7 +138,7 @@ def WhnfClosedAt (layer : WhnfLayer) (semantics : CacheSemantics) Methods.WFAt layer semantics trProj world support uvars methods → WhnfLayerWFAt layer semantics trProj world support uvars methods -/-- K2's fixed-universe closure obligation. -/ +/-- Fixed-universe inference/conversion closure obligation. -/ def InferDefEqClosedAt (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) : Prop := @@ -165,7 +165,7 @@ def LayerWF (layer : WhnfLayer) (semantics : CacheSemantics) (methods : Methods .anon) : Prop := Methods.WF layer semantics trProj world support (next methods) -/-- K1's four fields for one unfolded method-table layer. -/ +/-- WHNF's four fields for one unfolded method-table layer. -/ structure WhnfLayerWF (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (methods : Methods .anon) : Prop where @@ -198,7 +198,7 @@ structure WhnfLayerWF (layer : WhnfLayer) (semantics : CacheSemantics) (fun result _ => support result ∧ WhnfPost trProj world uvars Delta sourceV result) -/-- K2's two fields for one unfolded method-table layer. -/ +/-- The two inference/conversion fields for one unfolded method-table layer. -/ structure InferDefEqLayerWF (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) @@ -220,7 +220,7 @@ structure InferDefEqLayerWF (layer : WhnfLayer) (fun answer _ => answer = true → world.venv.IsDefEqU uvars Delta.toCtx va vb) -/-- The independently proved K1 and K2 fields assemble the exact next-layer +/-- The independently proved WHNF and inference/conversion fields assemble the exact next-layer record; no field may use the table it is currently proving. -/ theorem LayerWF.of_parts {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -242,13 +242,13 @@ def Closed (layer : WhnfLayer) (semantics : CacheSemantics) ∀ methods, Methods.WF layer semantics trProj world support methods → LayerWF layer semantics trProj world support methods -/-- K1 closure obligation, separate from inference and def-eq. -/ +/-- WHNF closure obligation, separate from inference and def-eq. -/ def WhnfClosed (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) : Prop := ∀ methods, Methods.WF layer semantics trProj world support methods → WhnfLayerWF layer semantics trProj world support methods -/-- K2 closure obligation, assuming only the smaller table's six contracts. -/ +/-- Inference/conversion closure obligation, assuming only the smaller table's six contracts. -/ def InferDefEqClosed (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) : Prop := ∀ methods, Methods.WF layer semantics trProj world support methods → diff --git a/Ix/Kernel/Verify/NatFixture.lean b/Ix/Kernel/Verify/NatFixture.lean index ce4d55760..f904fef0a 100644 --- a/Ix/Kernel/Verify/NatFixture.lean +++ b/Ix/Kernel/Verify/NatFixture.lean @@ -5,7 +5,7 @@ import Ix.Kernel.Verify.Whnf.Structural.BetaBoundary open Ix.Theory (VLevel) /-! -# G2a ambient-Nat fixture +# Ambient Nat fixture This file instantiates `InductiveOracle` with a small, closed Theory model of `Nat`, `Nat.zero`, and `Nat.succ`. The concrete catalog entries retain their @@ -18,15 +18,12 @@ it does not claim an eliminator or pretend that Ix.Theory.Named's still-opaque The fixture then promotes one ordinary axiom whose type is `Nat` and leaves a second, raw-translatable but ill-typed axiom pending. Thus adding an ambient -inductive family does not collapse the pending/trusted boundary established -in G1. G3a first instantiated finite run support for lift, substitution, and -universe instantiation. As in the G1 -adversarial fixture, fixed distinct addresses keep this logical model -independent of the Blake3 FFI; it establishes semantic -inhabitation, not ingress hash-integrity or Rust parity. G3b extends that -witness to direct expression/universe interning, every currently formalized -walker family, and a non-empty `ExecutionRequests` certificate for the exact -same request list. +inductive family preserves the pending/trusted boundary. Fixed distinct +addresses keep this logical model independent of the Blake3 FFI; it establishes +semantic inhabitation, not ingress hash-integrity or Rust parity. Finite +execution support covers lifting, substitution, universe instantiation, direct +expression/universe interning, every formalized walker family, and a non-empty +`ExecutionRequests` certificate for the same request list. -/ namespace Ix.Kernel @@ -366,7 +363,7 @@ theorem succRaw : RawInductiveConstRel natEnv nameOf RawProjRel.none · exact RawExprRel.const nameOf_nat natEnv_nat rfl · exact RawExprRel.const nameOf_nat natEnv_nat rfl -/-- A real model of the G2a assumption boundary. This particular block has +/-- A real model of the ambient-inductive interface assumption boundary. This particular block has no recursor declaration, so `recursorFacts` and `recursorPatterns` are vacuous; any later block that contains a `.recr` entry must supply both its Theory equation and exact iota-pattern witnesses explicitly. -/ @@ -652,7 +649,7 @@ theorem stateWF (prims : Primitives .anon) : TcStateWF RawProjRel.none (state prims) worldGood := ⟨trustedCatalogRelGood, loadedAgrees, InternTable.WF.empty⟩ -/-- The G2b consumer lookup is inhabited by an ambient inductive member in a +/-- Catalog lookup is inhabited by an ambient inductive member in a real concrete state; no legacy whole-environment translation is involved. -/ theorem natResolved (prims : Primitives .anon) : ∃ name ci, @@ -688,7 +685,7 @@ theorem natResolvedInv (prims : Primitives .anon) : TrustedConstRel RawProjRel.none world natId natConcrete name ci := (stateWF prims).tcInv.resolve loadedEnv_nat nat_trusted_good -/-! ## G3 finite run-support and execution witness -/ +/-! ## Finite run support and execution witness -/ /-- A constructed constant reference to the ambient Nat family. Recording the smart constructor's own info makes it both a concrete Nat reference and a @@ -816,7 +813,7 @@ theorem checkSupport (prims : Primitives .anon) : · exact fun _ hu => False.elim hu /-- Source traversal and generated-result arithmetic are simultaneously -bounded for the concrete G3b request list. -/ +bounded for the concrete execution request list. -/ theorem resourceBounds : ResourceBounds supportRequests := by constructor intro request hmem @@ -852,7 +849,7 @@ theorem resourceBounds : ResourceBounds supportRequests := by /-- A small real `TcM` computation containing exactly the eight recorded interning operations. It is a proof fixture, not a claim about `checkConst`; -later K1--K3 proofs build the same certificate compositionally for the +reducer, inference, and declaration proofs build the certificate compositionally for the production entry points. -/ def supportProgram : TcM .anon Unit := do let _ ← TcM.intern supportExpr @@ -884,7 +881,7 @@ theorem runAssumptions (prims : Primitives .anon) : RunSupport.pair_collisionFree supportExpr zeroLevel, checkSupport prims, resourceBounds⟩ -/-- G3b is non-vacuous in the same state that contains a trusted ambient Nat +/-- Execution-indexed support is non-vacuous in a state containing a trusted ambient Nat family and a loaded ill-typed pending declaration. Its execution list cannot be replaced by `[]`: it is indexed by the concrete eight-operation program. -/ theorem supportAcceptance (prims : Primitives .anon) : @@ -897,14 +894,14 @@ theorem supportAcceptance (prims : Primitives .anon) : ⟨stateWF prims, nat_trusted_good, badPending, runAssumptions prims⟩ -/-! ## K1 exact nonempty warm-cache witness -/ +/-! ## WHNF exact nonempty warm-cache witness -/ /-- This fixture contains only closed source expressions, so its context-key model relates the distinguished empty key to the empty semantic context. -/ def whnfContextKeys : WhnfContextKeys := WhnfContextKeys.closed 0 -/-- Exact K1 semantics for all five WHNF cache families. Non-WHNF semantic +/-- Exact WHNF semantics for all five WHNF cache families. Non-WHNF semantic caches are absent from the fixture; cached block errors remain replayable. -/ def whnfSemantics : CacheSemantics := whnfCacheSemantics whnfContextKeys RawProjRel.none @@ -912,7 +909,7 @@ def whnfSemantics : CacheSemantics := /-- The closed Nat reference is definitionally equal to itself in the real ambient-Nat Theory world. This is the semantic fact stored by the warm -cache, replacing G4's former address-only identity contract. -/ +cache, including its Theory meaning as well as its address. -/ theorem supportExpr_whnfMeaning : WhnfMeaning RawProjRel.none worldNat 0 [] supportExpr supportExpr := by obtain ⟨name, ci, hresolved⟩ := @@ -948,7 +945,7 @@ def warmState (prims : Primitives .anon) : TcState .anon := { env := warmEnv, prims, ctxId := natAddress } /-- The loaded ambient-Nat environment has constants but no semantic cache -entries. This is the fresh side of the G4 fresh/warm comparison. -/ +entries. This is the fresh state in the provenance comparison. -/ theorem loadedEnv_noCacheEntries (entry : CacheEntry) : ¬loadedEnv.HasCacheEntry entry := by intro hentry @@ -1041,7 +1038,7 @@ theorem whnfLeafTheoryWF : VExpr.WF worldGood.venv 0 [] (.sort .zero) := ⟨_, VEnv.HasType.sort trivial⟩ -/-- The concrete ambient-Nat state inhabits the syntax-directed K1 fixture +/-- The concrete ambient-Nat state inhabits the syntax-directed WHNF fixture layer with acceleration disabled. Its primitive table remains intentionally parametric; production closure uses `productionNoAccelStateInv` below. -/ theorem noAccelStateInv (prims : Primitives .anon) : @@ -1096,7 +1093,7 @@ theorem noAccelInvariant_rejects_mismatched_primitives /-- A real Nat-containing state instantiates the first conditional `RecM.whnf` theorem. This branch returns before any cache, fuel, native, or -recursive-method operation, but still preserves the complete K1 invariant on +recursive-method operation, but still preserves the complete WHNF invariant on both EStateM outcomes. -/ theorem whnfLeaf_noAccel_wf (prims : Primitives .anon) : RecM.WF .structuralNoAccel whnfSemantics RawProjRel.none worldGood support 0 [] @@ -1189,7 +1186,7 @@ theorem warmCache_cannotResolvePending (prims : Primitives .anon) : ¬warmEntry.References support IllTypedPending.targetId := (warmKernelStateWF prims).pendingCacheIsolation badPending warmEnv_hit -/-- G4's formal acceptance witness contains both the fresh and nonempty warm +/-- The cache-provenance acceptance witness contains both the fresh and nonempty warm states, transported provenance, and pending-declaration isolation. The executable failed-then-valid regression lives in `Tests.Ix.Kernel.CheckTests`. -/ theorem cacheAcceptance (prims : Primitives .anon) : @@ -1209,7 +1206,7 @@ theorem zero_trusted_good : worldGood.trusted zeroId := theorem succ_trusted_good : worldGood.trusted succId := TrustInsert.old succ_trusted -/-! ### K1 structural beta witness -/ +/-! ### WHNF structural beta witness -/ /-- A closed, typed beta redex over the ambient Nat family. Smart constructors supply its actual content metadata; the proof below does not @@ -1287,7 +1284,7 @@ theorem whnfCoreConst_noAccel_acceptance (prims : Primitives .anon) (.const natName []) result) := ⟨noAccelStateInv prims, whnfCoreConst_noAccel_wf prims flags⟩ -/-- Nontrivial K1 semantic witness: the concrete Nat identity application +/-- Nontrivial WHNF semantic witness: the concrete Nat identity application is definitionally equal to the exact output of the verified substitution specification. -/ theorem betaIdentityMeaning : @@ -1402,7 +1399,7 @@ theorem betaResultMeaning : /-- Small operational harness for the single recursive-head callback used by this fixture. It is not claimed to satisfy `Methods.WF` or to be the tied production knot; the generic theorem above isolates the exact callback -equation that K2 must later prove for `methodsN`. -/ +equation required to use `methodsN` in its place. -/ def betaHarnessMethods : Methods .anon where whnf := fun e => pure e whnfCore := fun e => pure e @@ -6452,7 +6449,7 @@ theorem multiBetaMiddleRebase : hlaterTr.rebase worldGood.venvWF (by trivial) hthroughTr hthroughEq exact ⟨priorArgs, laterArgs, resultV, hlater, hresultTr, hresultEq⟩ -/-- G2a acceptance witness: one concrete state simultaneously contains a +/-- Ambient-inductive acceptance witness: one concrete state simultaneously contains a trusted, well-formed ambient Nat family; a successfully promoted standalone declaration that uses Nat; and an independently loaded pending declaration for which declaration WF is impossible. -/ diff --git a/Ix/Kernel/Verify/RecursiveMethods/Closure.lean b/Ix/Kernel/Verify/RecursiveMethods/Closure.lean index 495ea8a56..124ac3614 100644 --- a/Ix/Kernel/Verify/RecursiveMethods/Closure.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/Closure.lean @@ -12,7 +12,7 @@ This module performs that final fixed-universe assembly. namespace Ix.Kernel -/-- The semantic cache layers beneath K1's outer WHNF and delta layers. -/ +/-- The semantic cache layers beneath the outer WHNF and delta layers. -/ def kernelCacheFallback (keys : WhnfContextKeys) (trProj : RawProjRel) : CacheSemantics := inferCacheSemantics keys trProj <| diff --git a/Ix/Kernel/Verify/RecursiveMethods/ScopedCallDomains.lean b/Ix/Kernel/Verify/RecursiveMethods/ScopedCallDomains.lean index 1de663397..6306dd3e5 100644 --- a/Ix/Kernel/Verify/RecursiveMethods/ScopedCallDomains.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/ScopedCallDomains.lean @@ -2,10 +2,10 @@ import Ix.Kernel.Verify.DefEq import Ix.Kernel.Verify.RecursiveMethods.CallDomains /-! -# Run-scoped recursive-method call domains +# Run-scoped method call domains -The original bounded call-domain contract carries the kernel invariant but -not the finite context-digest state domain. K2S must retain both: a method +The bounded call-domain contract carries the kernel invariant but +not the finite context-digest state domain. Scoped method contracts retain both: a method may construct or reuse a suffix key only while its concrete pre-state belongs to `ScopedKernelSuffixModel.StateInScope`, and both success and partial-error states must remain in that domain. diff --git a/Ix/Kernel/Verify/RecursiveMethods/ScopedSortInference.lean b/Ix/Kernel/Verify/RecursiveMethods/ScopedSortInference.lean index f099c235f..1b4ab55a3 100644 --- a/Ix/Kernel/Verify/RecursiveMethods/ScopedSortInference.lean +++ b/Ix/Kernel/Verify/RecursiveMethods/ScopedSortInference.lean @@ -203,7 +203,7 @@ theorem sort_scoped_wf_fuel_one exact sort_scoped_wf_bounded hcollision hsourceSupport hresultSupport theory references hsource -/-- The K2S construction can be consumed at the public positive-fuel entry +/-- The scoped method construction can be consumed at the public positive-fuel entry without first manufacturing a universally quantified suffix model. -/ theorem sort_finiteOperational_wf_fuel_one {initial : TcState .anon} diff --git a/Ix/Kernel/Verify/Run.lean b/Ix/Kernel/Verify/Run.lean index 0c53a2472..019f4cbce 100644 --- a/Ix/Kernel/Verify/Run.lean +++ b/Ix/Kernel/Verify/Run.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Execution import Ix.Kernel.Verify.Frame /-! -# G3b: execution-indexed run assumptions +# Execution-indexed run assumptions An explicit request list is not, by itself, evidence that it describes a checker run: choosing `[]` would make coverage and bounds vacuous. This file @@ -21,8 +21,8 @@ existing walker masters and retain both finite intern ranges in post-states. namespace Ix.Kernel -/-- State invariant used by run-level adapters and top-level statements. G4 -adds stable-world provenance for every warm cache entry. -/ +/-- State invariant used by run-level adapters and top-level statements. +It includes stable-world provenance for every warm cache entry. -/ def SupportedState (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (s : TcState .anon) : Prop := diff --git a/Ix/Kernel/Verify/State.lean b/Ix/Kernel/Verify/State.lean index d40d7b0eb..0d0bd0d89 100644 --- a/Ix/Kernel/Verify/State.lean +++ b/Ix/Kernel/Verify/State.lean @@ -26,10 +26,10 @@ monotone extension proof from the caller's baseline. Fixed-world Hoare triples are proved first below; their error branches retain exactly the same world, so ordinary state mutation cannot silently promote a declaration. -Ambient-inductive admission is carried by the trusted log beginning in G2a. -G4 layers finite-support cache provenance onto this deliberately small core -through `KernelStateWF` below. Dual-context agreement and the concrete -reduction/inference/native semantic contracts remain K1/K2 obligations. +The trusted log carries ambient-inductive admission. `KernelStateWF` adds +finite-support cache provenance to this core. Dual-context agreement and +the concrete reduction, inference, and native semantic contracts remain +obligations of the operation-specific proofs. -/ namespace Ix.Kernel @@ -103,7 +103,7 @@ def TcInv (trProj : RawProjRel) (world₀ : VerifyWorld) (s : TcState .anon) : Prop := ∃ world, world₀ ≤ world ∧ TcStateWF trProj s world -/-! ## G4 semantic-cache layer -/ +/-! ## Semantic-cache layer -/ /-- The complete stable checker invariant at a finite run boundary. @@ -122,7 +122,7 @@ structure KernelStateWF (semantics : CacheSemantics) (trProj : RawProjRel) equivalences : EquivManager.WF (semantics.Equiv (CacheAuthority.stable world) support) s.equivManager -/-- Existential current-world form of the complete G4 state invariant. -/ +/-- Existential current-world form of the complete cache provenance state invariant. -/ def KernelTcInv (semantics : CacheSemantics) (trProj : RawProjRel) (world₀ : VerifyWorld) (support : RunSupport) (s : TcState .anon) : Prop := @@ -301,7 +301,7 @@ theorem stateWF (prims : Primitives .anon) : exact loaded_pending_but_not_wf.1 · exact InternTable.WF.empty -/-- G1's central adversarial witness: the complete state invariant and +/-- An adversarial world: the complete state invariant and pending precondition are inhabited even though declaration WF is impossible. This rules out a hidden whole-`KEnv` typing premise in `TcInv`. -/ theorem tcInv_pending_but_not_wf (prims : Primitives .anon) : diff --git a/Ix/Kernel/Verify/Statements.lean b/Ix/Kernel/Verify/Statements.lean index b37e30cce..8b86280b3 100644 --- a/Ix/Kernel/Verify/Statements.lean +++ b/Ix/Kernel/Verify/Statements.lean @@ -7,33 +7,33 @@ import Ix.Kernel.Verify.RecursiveMethods.Public /-! # Public checker theorem frontier -All seven public theorem roots now use the concrete verification relations and +All seven public theorem roots use concrete verification relations and a finite, fuel-indexed production call schedule: -* `TcM.whnf.wf`, `TcM.infer.wf`, and `TcM.isDefEq.wf` are the C1A adapters - from `RecursiveMethods/Public.lean`; -* `TcM.checkConst.wf` is K3's standalone axiom/definition-family theorem, +* `TcM.whnf.wf`, `TcM.infer.wf`, and `TcM.isDefEq.wf` are bounded + recursive-method adapters from `RecursiveMethods/Public.lean`; +* `TcM.checkConst.wf` is the standalone axiom/definition-family theorem, starting from `PendingDecl` and untyped validator ingress and producing a real `StandaloneCheckResult`, a `VDecl.WF`-backed trusted-world promotion, and the promoted post-state invariant; and -* `TcM.checkConst.blockDisposition` is E0's exhaustive successful-dispatch +* `TcM.checkConst.blockDisposition` is the exhaustive successful-dispatch theorem: the production call either performs one exact atomic coordinated admission or takes the separately verified standalone branch; and -* `BooleanEnumerationFixture.subjectWF` is the E3-S acceptance root: the +* `BooleanEnumerationFixture.subjectWF` is the supported fragment acceptance root: the production serial driver successfully checks the exact six-entry Boolean source environment, and its two coordinated work rows satisfy `SubjectWF` - through transparent run-scoped K3/E0 resources, an explicit empty - assumption set, and certificate-backed E2 inductive evidence. -* `BooleanSerialized.subjectWF` is the T0-S representation root: the same + through run-scoped declaration and block-checking resources, an explicit empty + assumption set, and certificate-backed inductive evidence. +* `BooleanSerialized.subjectWF` is the serialized-ingress representation root: the same semantic result is connected to a successful pure Ixon byte decode, exact hash-verified eager and cold-lazy ingress, serialized dependency refs, and a successful run of the production anonymous driver. -The K3 statement deliberately exposes `StandaloneRoute`. E0 now closes the +The standalone theorem exposes `StandaloneRoute`. Block admission covers the coordinated transaction, physical/ghost identity, and cache-publication layers. Singleton definition blocks are constructive. Inductive and recursor bodies remain relative in the generic adapter to an explicitly -supplied `InductiveOracle` resource; the public E3-S root instantiates both +supplied `InductiveOracle` resource; the public supported fragment root instantiates both resources from the Ix.Theory.Named Boolean generation certificate. Quotient semantics, mutual/nested inductives, indexed or parameterized families, and multi-definition blocks remain outside this certificate-backed release diff --git a/Ix/Kernel/Verify/Suffix.lean b/Ix/Kernel/Verify/Suffix.lean index 3dc7f5df8..195d47e8c 100644 --- a/Ix/Kernel/Verify/Suffix.lean +++ b/Ix/Kernel/Verify/Suffix.lean @@ -1,7 +1,7 @@ import Ix.Kernel.Verify.Whnf /-! -# K2 suffix-context transport boundary +# Suffix-context transport boundary WHNF cache keys hash only the de-Bruijn suffix reachable from an expression. The hash itself is not semantic evidence. This module states the two facts a @@ -505,8 +505,8 @@ namespace WhnfSuffixModel /-- Construct the operational model once the actual semantic sufficiency theorem for equal emitted suffix addresses is available. This removes the -former representation oracle entirely: only semantic transport remains K2 -proof debt. -/ +former representation oracle entirely: semantic transport remains an explicit +proof obligation. -/ def operational {trProj : RawProjRel} {world : VerifyWorld} (uvars : Nat) (htransport : ∀ {ctxAddr : Address} {Delta Delta' : KVLCtx} {source result : KExpr .anon}, diff --git a/Ix/Kernel/Verify/Support.lean b/Ix/Kernel/Verify/Support.lean index 4fef22776..9a85439e4 100644 --- a/Ix/Kernel/Verify/Support.lean +++ b/Ix/Kernel/Verify/Support.lean @@ -2,7 +2,7 @@ import Ix.Kernel.Verify.InstUniv import Std.Data.HashMap.Lemmas /-! -# G3: finite run-scoped collision and arithmetic support +# Finite run-scoped collision and arithmetic support The expression walkers were already proved against an abstract predicate `S`, with separate hypotheses that their reach relation and the initial diff --git a/Ix/Kernel/Verify/Totalization.lean b/Ix/Kernel/Verify/Totalization.lean index e9eeb84e3..1efd15ff4 100644 --- a/Ix/Kernel/Verify/Totalization.lean +++ b/Ix/Kernel/Verify/Totalization.lean @@ -3,7 +3,7 @@ import Ix.Kernel.CanonicalCheck import Ix.Kernel.Check /-! -# K0: equations for the total recursive-methods knot +# Totalization: equations for the total recursive-methods knot These equations expose the production definitions needed by the later `Methods.WF` induction. They also pin the runtime boundary precisely: diff --git a/Ix/Kernel/Verify/Whnf.lean b/Ix/Kernel/Verify/Whnf.lean index a3113ecbe..bc3334848 100644 --- a/Ix/Kernel/Verify/Whnf.lean +++ b/Ix/Kernel/Verify/Whnf.lean @@ -8,11 +8,12 @@ open Ix.Theory (VLevel) /-! # WHNF soundness boundary -This file starts K1 at the semantic boundary shared by reduction, caches, and +This file defines the semantic boundary shared by reduction, caches, and the recursive method knot. It intentionally does not identify a context hash with a typing context by fiat. `WhnfContextKeys.Represents` is the one named ghost relation whose production implementation must be connected to -`TcM.ctxAddrForLbr`; K2 supplies the suffix-sufficiency transport theorem. +`TcM.ctxAddrForLbr`. The suffix model in `Verify.DefEq` supplies the semantic +transport contract for equal suffix keys. The semantic payload is already concrete: `WhnfMeaning` says that source and result have structural `TrKExprS` translations in the same `KVLCtx`, and that @@ -21,9 +22,9 @@ Consequently a cache hit is useful only after supplying both its finite source witness and the represented context. Address equality alone carries no semantic meaning. -K1 has five expression-cache policies. The inference caches are excluded +WHNF has five expression-cache policies. The inference caches are excluded from this layer and continue through a caller-supplied fallback semantics; -K2 replaces that fallback with their exact typing contracts. +`Verify.Infer` supplies their exact typing contracts. -/ namespace Ix.Kernel @@ -82,7 +83,7 @@ end WhnfMeaning /-! ## Cache-policy partition -/ /-- The five semantic policies implemented by the WHNF expression caches. -The policy records operational strength; every policy has the same C1 +The policy records operational strength; every policy has the same cache soundness consequence (`WhnfMeaning`). -/ inductive WhnfCachePolicy where | full @@ -94,7 +95,8 @@ inductive WhnfCachePolicy where namespace ExprCacheKind -/-- Classify exactly the K1 cache families. Inference caches are K2. -/ +/-- Classify exactly the WHNF cache families. Inference caches belong to the +separate inference layer. -/ def whnfPolicy? : ExprCacheKind → Option WhnfCachePolicy | .whnf => some .full | .whnfNoDelta => some .noDelta @@ -124,7 +126,7 @@ def whnfPolicy? : ExprCacheKind → Option WhnfCachePolicy @[simp] theorem whnfPolicy?_inferOnly : ExprCacheKind.inferOnly.whnfPolicy? = none := rfl -/-- Proof-relevant membership in the K1 cache partition. -/ +/-- Proof-relevant membership in the WHNF cache partition. -/ inductive IsWhnf : ExprCacheKind → Prop | whnf : IsWhnf .whnf | whnfNoDelta : IsWhnf .whnfNoDelta @@ -169,9 +171,10 @@ end ExprCacheKind /-! ## Context-key interpretation and exact cache semantics -/ /-- Ghost interpretation of suffix-aware context addresses. `Represents` -may relate one key to several definitionally equal contexts; K1 cache -validity is deliberately quantified over every represented context. K2 -constructs this model from `ctxAddrForLbr` plus suffix sufficiency. -/ +may relate one key to several definitionally equal contexts; WHNF cache +validity is deliberately quantified over every represented context. The +suffix-model adapter constructs this interpretation from `ctxAddrForLbr` +plus suffix sufficiency. -/ structure WhnfContextKeys where uvars : Nat /-- `Represents lbr key Δ` interprets `key` as the suffix requested at @@ -194,7 +197,7 @@ def closed (uvars : Nat) : WhnfContextKeys where /-- A represented semantic context tied to the actual production cache-key computation in a concrete state. Constructing this witness—not merely -postulating `Represents`—is the K1/K2 context-key proof obligation. -/ +postulating `Represents`—is the reduction, inference, and conversion context-key proof obligation. -/ def Matches (keys : WhnfContextKeys) (trProj : RawProjRel) (world : VerifyWorld) (s : TcState .anon) (Δ : KVLCtx) (source : KExpr .anon) (key : Address × Address) : Prop := @@ -216,7 +219,7 @@ def InternUpdateFrame (before after : TcState .anon) : Prop := after = { before with env := { before.env with intern := after.env.intern } } /-- The empty projection relation satisfies every structural closure law -vacuously. This is the canonical K1 fixture interpretation for fragments +vacuously. This is the canonical WHNF fixture interpretation for fragments that contain no projection nodes. -/ theorem RawProjRel.none_ok (env : Ix.Theory.Named.VEnv) (uvars : Nat) : TrProjOK env uvars RawProjRel.none := by @@ -339,8 +342,8 @@ def blockResults : CacheSemantics where intro authority support block h exact h -/-- Compatibility spelling retained for existing K1/K2 clients. Unlike its -pre-E0 definition, successful block verdicts now have the exact sound meaning +/-- Compatibility spelling for block-result cache semantics. +Successful block verdicts have the exact sound meaning specified by `blockResults`. -/ abbrev blockErrorsOnly : CacheSemantics := blockResults @@ -405,7 +408,7 @@ def isRecCacheSemantics (fallback : CacheSemantics) : CacheSemantics where intro authority support block h exact fallback.blockSuccessSound authority support block h -/-- Exact K1 validity for one tagged entry. The fallback owns every non-K1 +/-- Exact WHNF validity for one tagged entry. The fallback owns every non-WHNF cache family. A WHNF entry must be sound for every finite-support source whose address is its first key component and every context represented by its second component whenever that source is structurally in scope there. @@ -465,7 +468,7 @@ theorem mono {keys : WhnfContextKeys} {trProj : RawProjRel} recursor | recMajors | blockPeer | blockResult => exact fallback.mono hle h -/-- Project the concrete reduction meaning from any of the five K1 cache +/-- Project the concrete reduction meaning from any of the five WHNF cache families. -/ theorem expr {keys : WhnfContextKeys} {trProj : RawProjRel} {fallback : CacheSemantics} {authority : CacheAuthority} @@ -492,7 +495,7 @@ theorem natSuccStuck {keys : WhnfContextKeys} {trProj : RawProjRel} end WhnfCacheValid -/-- Overlay the exact K1 meanings on an existing semantic family. -/ +/-- Overlay the exact WHNF meanings on an existing semantic family. -/ def whnfCacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) (fallback : CacheSemantics) : CacheSemantics where Valid := WhnfCacheValid keys trProj fallback @@ -512,7 +515,7 @@ def whnfCacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) namespace CacheProvenance -/-- Construct K1 provenance for a negative successor marker. Unlike a +/-- Construct WHNF provenance for a negative successor marker. Unlike a cached expression result, the marker needs no Theory reduction witness; it still records a supported source address and proves that every supported source sharing that address refers only to trusted declarations. -/ @@ -532,7 +535,7 @@ theorem whnfNatSuccStuck intro id href exact .inl (hreferences href) -/-- A provenance-certified K1 hit exposes concrete Theory reduction +/-- A provenance-certified WHNF hit exposes concrete Theory reduction meaning; support and dependency facts remain available in `h`. -/ theorem whnfMeaning {keys : WhnfContextKeys} {trProj : RawProjRel} {fallback : CacheSemantics} {authority : CacheAuthority} @@ -566,7 +569,7 @@ end CacheProvenance namespace CacheInvariant -/-- Physical hit plus the exact K1 cache invariant yields its Theory +/-- Physical hit plus the exact WHNF cache invariant yields its Theory meaning. -/ theorem whnfHit {keys : WhnfContextKeys} {trProj : RawProjRel} {fallback : CacheSemantics} {authority : CacheAuthority} @@ -601,7 +604,7 @@ end CacheInvariant /-! ## Conditional recursive-method interface -/ -/-- The theorem layers used by K1. `structuralNoAccel` is deliberately +/-- The theorem layers used by WHNF. `structuralNoAccel` is deliberately restricted to syntax-directed fixtures: it pins the acceleration gate but does not claim that the state's primitive table is the production anon table. The two production layers both bind every observable table address to @@ -856,7 +859,7 @@ end WhnfStateInv namespace ContextKeyFrame -/-- Populating the suffix-key memo preserves the complete K1 invariant. +/-- Populating the suffix-key memo preserves the complete WHNF invariant. The proof projects the exact frame rather than treating the memo operation as pure; this catches future writes to context, environment, fuel, or flags. -/ theorem whnfStateInv {layer : WhnfLayer} {semantics : CacheSemantics} @@ -913,7 +916,7 @@ theorem trans {s₀ s₁ s₂ : TcState .anon} rw [h₂, h₁] /-- Intern-table growth preserves the context and acceleration components of -the K1 invariant once the post-state kernel invariant has been re-established. +the WHNF invariant once the post-state kernel invariant has been re-established. Keeping the kernel premise explicit lets the finite-support walker proofs supply its new intern-table coherence and coverage facts. -/ theorem whnfStateInv {layer : WhnfLayer} {semantics : CacheSemantics} @@ -953,7 +956,7 @@ end InternUpdateFrame namespace TcM -/-- Lift an exact `InternM` specification to the complete K1 state invariant. +/-- Lift an exact `InternM` specification to the complete WHNF state invariant. This is the common state bridge for beta/zeta walkers: the intern table may grow, but contexts, flags, loaded declarations, and semantic caches frame. -/ theorem runIntern_whnf_wf {layer : WhnfLayer} @@ -1143,7 +1146,7 @@ theorem ctxAddrForLbr_wf {I : TcState .anon → Prop} · intro _ after hafter exact TcM.WF.pure fun _ => hafter -/-- `whnfKey` preserves K1 state and fixes the expression-address component +/-- `whnfKey` preserves WHNF state and fixes the expression-address component of the returned key. -/ theorem whnfKey_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -1160,8 +1163,8 @@ theorem whnfKey_wf {layer : WhnfLayer} {semantics : CacheSemantics} exact TcM.WF.pure fun _ => ⟨rfl, hframe⟩ /-- Operational context-match constructor. `hrep` is deliberately the only -remaining ghost obligation: K1 cannot infer suffix sufficiency from a hash, -and K2 will discharge it from the concrete context-closure algorithm. -/ +remaining ghost obligation: suffix sufficiency must follow from the concrete +context-closure algorithm and its semantic transport contract. -/ theorem whnfKey_matches_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {keys : WhnfContextKeys} @@ -1289,7 +1292,7 @@ end TcM namespace RunAssumptions /-- One certified expression-intern request returns the requested raw -expression exactly, preserves the complete K1 invariant, and changes only the +expression exactly, preserves the complete WHNF invariant, and changes only the intern table. Collision freedom and finite support are supplied by the execution-indexed request rather than assumed for an arbitrary expression. -/ theorem internExpr_whnf_eval {α : Type} {initial : TcState .anon} @@ -1308,7 +1311,7 @@ theorem internExpr_whnf_eval {α : Type} {initial : TcState .anon} exact TcM.runIntern_whnf_eval (fun _ hwf hsup => h.internExpr_spec hmem hwf hsup) hI -/-- The verified single-substitution walker preserves the complete K1 +/-- The verified single-substitution walker preserves the complete WHNF invariant. This is the explicit-let sibling of `simulSubst_whnf_wf`: production substitutes the let value into its body while only the intern table may grow. -/ @@ -1347,7 +1350,7 @@ theorem subst_whnf_eval {α : Type} {initial : TcState .anon} TcM.runIntern_whnf_eval (fun _ hwf hsup => h.subst_spec hmem hwf hsup) hI -/-- The verified lifting walker preserves the complete K1 invariant. This +/-- The verified lifting walker preserves the complete WHNF invariant. This is the legacy-zeta sibling of `simulSubst_whnf_wf`: the stored let value is rebased to the current de Bruijn depth while only the intern table may grow. -/ theorem lift_whnf_wf {α : Type} {initial : TcState .anon} @@ -1385,7 +1388,7 @@ theorem lift_whnf_eval {α : Type} {initial : TcState .anon} TcM.runIntern_whnf_eval (fun _ hwf hsup => h.lift_spec hmem hwf hsup) hI -/-- The verified simultaneous-substitution walker preserves the complete K1 +/-- The verified simultaneous-substitution walker preserves the complete WHNF invariant, not merely intern-table coherence. Its request membership keeps finite collision/support and UInt64 resource assumptions tied to an actual execution certificate. -/ @@ -1689,7 +1692,7 @@ theorem meaning {trProj : RawProjRel} {world : VerifyWorld} end WhnfPost /-- Successful inference callback postcondition used inside WHNF's K/struct -fallbacks. K2 proves this field for the concrete method table. -/ +fallbacks. Closing the concrete method table requires a proof of this field. -/ def InferPost (trProj : RawProjRel) (world : VerifyWorld) (uvars : Nat) (Δ : KVLCtx) (sourceV : VExpr) (ty : KExpr .anon) : Prop := @@ -1755,9 +1758,9 @@ structure WFAt (layer : WhnfLayer) (semantics : CacheSemantics) (fun answer _ => answer = true → world.venv.IsDefEqU uvars Δ.toCtx va vb) -/-- Conditional semantic closure of all six K0 method-table back-edges. -K1 consumes this record while proving WHNF; K2 proves the inference/defeq -fields and closes `methodsN` by induction. -/ +/-- Conditional semantic closure of all six recursive method-table calls. +The reducer proofs consume this record; closing `methodsN` by induction +also requires the inference and definitional-equality fields. -/ structure WF (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (methods : Methods .anon) : Prop where @@ -1880,8 +1883,8 @@ structure InductiveReductionOracle (layer : WhnfLayer) namespace RecM /-- Reader-level Hoare triple conditional on a semantically closed method -table. Quantification over every `Methods.WF` table is what lets K1 land -before K2 ties the total recursive knot. -/ +table. Quantification over every `Methods.WF` table lets branch proofs use +the callback contracts without depending on the concrete recursive knot. -/ def WF (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) (Δ : KVLCtx) (s : TcState .anon) (x : RecM .anon α) @@ -2008,7 +2011,7 @@ theorem liftTcM {layer : WhnfLayer} {semantics : CacheSemantics} intro methods hmethods exact hx -/-- Reader-level state observation preserves the K1 invariant exactly. -/ +/-- Reader-level state observation preserves the WHNF invariant exactly. -/ theorem get {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Delta : KVLCtx} {s : TcState .anon} @@ -2328,7 +2331,7 @@ theorem whnfNatReducerArg_wf · intro _ _ _ trivial -/-- Generic invariant rule for K0's total bounded-loop driver. Exhaustion +/-- Generic invariant rule for the total bounded-loop driver. Exhaustion is explicit in `hexhaust`; every successful `.next` re-establishes `P`, and every `.done` establishes the final postcondition. -/ theorem runBounded_wf {layer : WhnfLayer} {semantics : CacheSemantics} @@ -2462,7 +2465,7 @@ theorem no_zero {layer : WhnfLayer} {semantics : CacheSemantics} /-- A local semantic contract is sufficient to reconstruct the exact execution-indexed trace for every successful bounded run. On failure, - the same induction preserves the K1 invariant and says whether the loop + the same induction preserves the WHNF invariant and says whether the loop exhausted its own bound or the production step raised the error. -/ theorem complete {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -2591,7 +2594,7 @@ theorem eval {layer : WhnfLayer} {semantics : CacheSemantics} rw [hstep] exact ih -/-- The first state in a trace satisfies the same fixed K1 invariant carried +/-- The first state in a trace satisfies the same fixed WHNF invariant carried by every later state. -/ theorem initialInv {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -2603,7 +2606,7 @@ theorem initialInv {layer : WhnfLayer} {semantics : CacheSemantics} WhnfStateInv layer semantics trProj world support uvars Δ s := by cases h <;> assumption -/-- The last state in a trace still satisfies the fixed K1 invariant. -/ +/-- The last state in a trace still satisfies the fixed WHNF invariant. -/ theorem finalInv {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {uvars : Nat} {Δ : KVLCtx} {methods : Methods .anon} @@ -2645,7 +2648,7 @@ theorem uncached_eval {layer : WhnfLayer} {semantics : CacheSemantics} unfold whnfCoreWithFlagsUncached exact h.eval -/-- K1 structural-loop acceptance package: exact production execution, +/-- WHNF structural-loop acceptance package: exact production execution, initial/final fixed-world invariants, and the transitively composed Theory meaning. -/ theorem uncached_acceptance {layer : WhnfLayer} @@ -3180,7 +3183,7 @@ theorem whnfCoreWithFlags_transient_acceptance /-- Execution-indexed semantic certificate for the production no-delta WHNF loop. Each constructor records the exact named step equation, the -fixed K1 invariant on both sides, and the local Theory meaning. -/ +fixed WHNF invariant on both sides, and the local Theory meaning. -/ inductive WhnfNoDeltaTrace (layer : WhnfLayer) (semantics : CacheSemantics) (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) (uvars : Nat) @@ -3754,7 +3757,7 @@ def Represents (keys : WhnfContextKeys) (trProj : RawProjRel) TcM.whnfKey source before = .ok key after -> keys.Represents source.lbr key.2 Delta -/-- K2's suffix transport is unnecessary for a syntactically closed source: +/-- Suffix transport is unnecessary for a syntactically closed source: production returns the distinguished empty-context key exactly. -/ theorem closed_represents {uvars : Nat} {source : KExpr .anon} {trProj : RawProjRel} {world : VerifyWorld} @@ -3786,7 +3789,7 @@ end TransientNatWork sites. A meaning proof for the executed source alone is insufficient: cache validity quantifies over every supported source sharing the key's address and every represented context. Keeping this interface explicit - prevents a hash-collision assumption from entering K1 unnoticed. -/ + prevents a hash-collision assumption from entering WHNF unnoticed. -/ structure WhnfCacheWriteOracle (keys : WhnfContextKeys) (trProj : RawProjRel) (fallback : CacheSemantics) (world : VerifyWorld) (support : RunSupport) : Prop where @@ -3819,8 +3822,8 @@ namespace WhnfCacheWriteOracle /-- Construct all three outer write rules for closed expressions. Expression collision freedom identifies every supported source at the address key; the remaining premise is exactly direct-reference authorization for the - concrete cache entry. Open-context transport is deliberately absent and - remains K2 work. -/ + concrete cache entry. Open-context transport remains a separate semantic + proof obligation. -/ theorem closed {uvars : Nat} {trProj : RawProjRel} {fallback : CacheSemantics} {world : VerifyWorld} {support : RunSupport} @@ -4770,7 +4773,7 @@ theorem whnfWithNatSuccMode_nonLeaf_wf hcharge hstep hwrites hsupport hsource /-- The full-WHNF trace/statistics prefix preserves every semantic component - of the K1 state invariant, independently of instrumentation settings. -/ + of the WHNF state invariant, independently of instrumentation settings. -/ theorem whnfWithNatSuccModePrefix_wf {semantics : CacheSemantics} {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} @@ -4789,7 +4792,7 @@ theorem whnfWithNatSuccModePrefix_wf (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) s1 -/-- The full-WHNF miss charge preserves the K1 invariant on both outcomes. +/-- The full-WHNF miss charge preserves the WHNF invariant on both outcomes. Its only possible error is the underlying `.maxRecFuel`; the bounded-loop `.maxRecDepth` classification remains separate in `WhnfLoopError`. -/ theorem whnfWithNatSuccModeMissCharge_wf @@ -5033,8 +5036,8 @@ theorem whnfNoDelta_wf WhnfPost trProj world keys.uvars Delta sourceV result) := whnfNoDeltaImpl_wf theory hkeyRep htransient hstep hwrites hsupport hsource -/-- Public `RecM.whnf` specialization. K2 can use this theorem directly - when proving the corresponding `Methods.WF.whnf` field for `methodsN`. -/ +/-- Public `RecM.whnf` specialization, used to prove the corresponding + `Methods.WF.whnf` field for `methodsN`. -/ theorem whnf_wf {keys : WhnfContextKeys} {fallback : CacheSemantics} {layer : WhnfLayer} {trProj : RawProjRel} {world : VerifyWorld} @@ -7250,7 +7253,7 @@ theorem whnfCoreWithFlagsUncached_betaOne_wf exact ⟨s', whnfCoreWithFlagsUncached_betaOne hhead hwalk hleaf, hI', hframe⟩ -/-- First algorithmic K1 slice: all immediate-return WHNF forms preserve the +/-- All immediate-return WHNF forms preserve the complete fixed-world/context/cache invariant and their exact Theory meaning. The theorem is layer-polymorphic because these branches never inspect `noAccel` and never consume a `NativeOracle`. -/ @@ -7283,7 +7286,7 @@ theorem whnf_leaf_wf_of_theory {layer : WhnfLayer} exact TcM.WF.pure fun hI => WhnfPost.refl htr (theory.exprWF hI.2.1 htr) -/-- Immediate structural-WHNF forms preserve the complete K1 invariant and +/-- Immediate structural-WHNF forms preserve the complete WHNF invariant and have reflexive Theory meaning. This covers the actual flag-parametric core entry point, including constants and the cheap projection policy. -/ theorem whnfCoreWithFlags_leaf_wf {layer : WhnfLayer} @@ -7586,7 +7589,7 @@ structure NoDeltaInputSupport (support : RunSupport) : Prop where source.collectSpine = (head, args) → support head ∧ ∀ (i : Nat) (hi : i < args.size), support args[i] -/-- The concrete K1 input for active no-delta primitive proofs. It binds the +/-- The concrete WHNF input for active no-delta primitive proofs. It binds the canonical anon table to trusted Theory names, carries Ix.Theory.Named's primitive reflection laws, records the quotient lift equation, and scopes generated syntax to actual supported executions. This is necessary but intentionally @@ -12595,7 +12598,7 @@ theorem recordNatSuccStuck_eval (recordNatSuccStuck visited).run methods s = .ok () after := by rfl -/-- The shared memo commit preserves every K1 state component when each +/-- The shared memo commit preserves every WHNF state component when each visited marker has explicit cache provenance. -/ theorem recordNatSuccStuck_wf {layer : WhnfLayer} {semantics : CacheSemantics} @@ -13057,7 +13060,7 @@ structure NatSuccStuckWriteOracle (semantics : CacheSemantics) namespace NatSuccStuckWriteOracle -/-- Construct the marker oracle for K1's WHNF semantic overlay once every +/-- Construct the marker oracle for the WHNF semantic overlay once every finite-support expression is known to reference trusted declarations. -/ theorem forWhnfCache {keys : WhnfContextKeys} {trProj : RawProjRel} @@ -13129,7 +13132,7 @@ structure NatSuccLinearReflection (layer : WhnfLayer) world.venv.IsDefEqU uvars Delta.toCtx (natSuccIterV offset curV) reducedV -/-- The syntactic step recognizer preserves K1 state through its sole +/-- The syntactic step recognizer preserves WHNF state through its sole recursive WHNF callback. All later lambda/spine/address tests and primitive reads are state-transparent. -/ theorem isNatSuccIhStep_wf @@ -13585,7 +13588,7 @@ theorem tryReduceNatSuccIterStep_wf /-- The public successor-collapse helper satisfies its semantic result contract for arbitrary successor chains. The entry memo hit is a safe miss; the miss path seeds certified provenance and invokes the generic bounded-loop -driver, whose exhaustion and callback errors still preserve K1 state. -/ +driver, whose exhaustion and callback errors still preserve WHNF state. -/ theorem tryReduceNatSuccIter_wf {semantics : CacheSemantics} {trProj : RawProjRel} {world : VerifyWorld} {support : RunSupport} {flags : WhnfFlags} @@ -14058,7 +14061,7 @@ theorem tryReduceNatWithSuccMode_collapse_optional_wf rw [hrun] exact ⟨hI, trivial⟩ -/-- K1's narrow collapse-mode Nat closure surface. The implementation proof +/-- WHNF's narrow collapse-mode Nat closure surface. The implementation proof constructs both former whole-computation assumptions: descriptor ingress plus callback closure yield the linear recognizer's effect contract, while successful callback meaning plus canonical result-shape separation yields an @@ -14084,7 +14087,7 @@ theorem tryReduceNatWithSuccMode_collapse_optional_wf_of_boundaries (NatSuccLinearOracle.of_reflection context partsPreserve reflection) (NatCollapseRequestCensus.of_result_shape context theory shape) -/-- K1's stuck-mode Nat closure surface. Unary `Nat.succ` is deliberately +/-- WHNF's stuck-mode Nat closure surface. Unary `Nat.succ` is deliberately reserved for the surrounding successor loop, so this mode needs neither the linear Nat.rec reflection boundary nor stuck-cache writes. Canonical Nat/Bool result-shape separation is the only semantic boundary beyond the diff --git a/Ix/Kernel/Verify/Whnf/Closure.lean b/Ix/Kernel/Verify/Whnf/Closure.lean index 6a4acd990..1ccdad0e5 100644 --- a/Ix/Kernel/Verify/Whnf/Closure.lean +++ b/Ix/Kernel/Verify/Whnf/Closure.lean @@ -4,9 +4,9 @@ import Ix.Kernel.Verify.Knot /-! # Four-field fixed-universe WHNF closure -The structural, no-delta, full-WHNF, and trusted-delta reducers now expose +The structural, no-delta, full-WHNF, and trusted-delta reducers expose fixed-universe contracts. This module assembles those contracts into the -four K1 fields of one unfolded production method-table layer. +four WHNF fields of one unfolded production method-table layer. The context retains the exact construction boundary: @@ -19,17 +19,16 @@ The context retains the exact construction boundary: In particular, the full reducer is constructed with `FullWhnfStepContext.ofTrustedDelta`; callers cannot replace delta unfolding -with a free successful-reduction oracle. The `tryNatOffsetStuck` stage added -after the original K1 driver proof remains an explicit closure obligation -until its callbacks and intern operations are decomposed into finite -run-scoped inputs. +with a free successful-reduction oracle. The `tryNatOffsetStuck` stage remains +an explicit closure obligation requiring its callbacks and intern operations +to be decomposed into finite run-scoped inputs. -## K1 acceptance boundary +## WHNF acceptance boundary -`K1ClosureContext.closedAt` below is the K1 closure result: it supplies exactly +`K1ClosureContext.closedAt` below is the WHNF closure result: it supplies exactly the four fixed-universe WHNF fields of `Methods.next`. It deliberately does -not tie the complete six-method production knot. That later step also needs -K2's `infer` and `isDefEq` fields before `Methods.ClosedAt.of_parts`, +not tie the complete six-method production knot. That also requires the +`infer` and `isDefEq` fields before `Methods.ClosedAt.of_parts`, `Methods.methodsN_wfAt`, and the public runner can be used. The universally quantified caller context is not assumed well formed merely @@ -37,12 +36,12 @@ to construct `K1ClosureContext`. Each reducer instead recovers that fact from the `CtxRecon` component of the runtime invariant at its point of use. The concrete successful, absent, stuck, and partial-error executions in `NatFixture` separately keep the branch contracts inhabited; they are not a -substitute for K2's two missing recursive fields. +substitute for the two remaining inference and conversion fields. -/ namespace Ix.Kernel -/-- The final K1 cache composition at the universe count encoded by `keys`: +/-- The final WHNF cache composition at the universe count encoded by `keys`: WHNF expression entries outside, universe-sensitive delta bodies underneath, and the caller's remaining cache families as the base. -/ def k1CacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) @@ -52,7 +51,7 @@ def k1CacheSemantics (keys : WhnfContextKeys) (trProj : RawProjRel) namespace RecM -/-- Complete input family needed to prove the four K1 method-table fields at +/-- Complete input family needed to prove the four WHNF method-table fields at one universe count. -/ structure K1ClosureContext {alpha : Type} (initial : TcState .anon) (program : TcM .anon alpha) @@ -63,8 +62,7 @@ structure K1ClosureContext NoDeltaDriverContext initial program requests keys (unfoldCacheSemantics keys.uvars trProj fallback) trProj world support Delta .FULL - /-- Exact closure obligation for the compact symbolic-Nat stage introduced - after the original K1 driver proof. -/ + /-- Closure obligation for the compact symbolic-Nat reduction stage. -/ natOffsetStuck : OptionalReduction.WFAt .noAccel (k1CacheSemantics keys trProj fallback) trProj world support keys.uvars tryNatOffsetStuck @@ -78,7 +76,7 @@ structure K1ClosureContext namespace K1ClosureContext -/-- Assemble K1's four fixed-universe fields for one smaller, already +/-- Assemble WHNF's four fixed-universe fields for one smaller, already well-formed method table. -/ theorem layer {alpha : Type} {initial : TcState .anon} {program : TcM .anon alpha} @@ -122,7 +120,7 @@ theorem layer (context.structuralFlags Delta flags) hsourceSupport hsource) methods hmethods -/-- K1's headline fixed-universe closure result: any semantically valid +/-- WHNF's headline fixed-universe closure result: any semantically valid smaller method table proves all four WHNF fields of the next production layer. -/ theorem closedAt diff --git a/Ix/Kernel/Verify/Whnf/Delta/CacheExecution.lean b/Ix/Kernel/Verify/Whnf/Delta/CacheExecution.lean index 71e63f63f..4ac644dec 100644 --- a/Ix/Kernel/Verify/Whnf/Delta/CacheExecution.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/CacheExecution.lean @@ -3,7 +3,7 @@ import Ix.Kernel.Verify.Whnf.Delta.StableCache /-! # Certified production unfold-cache execution -The public K1 cache contract is a WHNF overlay whose fallback owns delta +The public WHNF cache contract is a WHNF overlay whose fallback owns delta entries. StableCache constructs the exact fallback provenance for a trusted body; this module transports that provenance through the overlay and verifies both physical paths of production's `unfoldConstValue`: diff --git a/Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean b/Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean index b42339ef3..f358bbfaa 100644 --- a/Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean +++ b/Ix/Kernel/Verify/Whnf/Delta/TrustedBody.lean @@ -7,7 +7,7 @@ open Ix.Theory (VLevel) `UnfoldingState` closes the operational state and support behavior of delta unfolding, but its two remaining semantic inputs are intentionally too broad for final -K1 closure: one can certify an unfold-cache write for an arbitrary supported +WHNF closure: one can certify an unfold-cache write for an arbitrary supported head/result pair, and the other can reflect any observed successful delta run. @@ -200,7 +200,7 @@ private theorem sourceStructural (.const id us info) (.const ci.name (instantiatedLevels us)) := .const h.nameEq h.lookup hus harity -/-- Exact K1 semantics of unfolding one trusted definition or theorem body. +/-- Exact WHNF semantics of unfolding one trusted definition or theorem body. Ordinary definitions use their registered equation. Theorem constants are not registered as reducible Theory equations, so the proof uses the diff --git a/Ix/Kernel/Verify/Whnf/Iota/ApplicationRequests.lean b/Ix/Kernel/Verify/Whnf/Iota/ApplicationRequests.lean index 95ba62c0f..578e4b3b3 100644 --- a/Ix/Kernel/Verify/Whnf/Iota/ApplicationRequests.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ApplicationRequests.lean @@ -36,7 +36,7 @@ inductive IotaArgsInternRequests (requests : List WalkerRequest) : namespace IotaArgsInternRequests -/-- A certified non-transient list fold preserves the complete K1 invariant +/-- A certified non-transient list fold preserves the complete WHNF invariant and returns its indexed final application. -/ theorem wfList {α : Type} {initial : TcState .anon} {program : TcM .anon α} diff --git a/Ix/Kernel/Verify/Whnf/Iota/ConstructorDispatch.lean b/Ix/Kernel/Verify/Whnf/Iota/ConstructorDispatch.lean index b281ccd9a..f740dc992 100644 --- a/Ix/Kernel/Verify/Whnf/Iota/ConstructorDispatch.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/ConstructorDispatch.lean @@ -503,7 +503,7 @@ theorem tryIotaWithFlags_regularCtor /-- Headline ConstructorDispatch contract: the actual parameter-free regular-constructor branch executes the checked rule selected at the runtime constructor index. The mutable preprocessing prefix must supply its intern-only frame and the -invariant at dispatch ingress; later K1 slices discharge those facts for the +invariant at dispatch ingress; later WHNF slices discharge those facts for the cleanup, callback, and lazy-lookup helpers themselves. -/ theorem tryIotaWithFlags_regularCtor_checkedAcceptance_empty {layer : WhnfLayer} {semantics : CacheSemantics} diff --git a/Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean b/Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean index fb5b60aca..bb7264b90 100644 --- a/Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/NatOffset.lean @@ -229,7 +229,7 @@ successful Nat-offset cleanup. The oracle is indexed by the actual production execution and assumes neither state preservation nor callback behavior. A later primitive/parser trace -construction supplies this field; K1 uses it only to recover the support and +construction supplies this field; WHNF uses it only to recover the support and structural translation required by `Methods.WF` for the selected major. -/ structure NatOffsetCleanupInputOracle (trProj : RawProjRel) (world : VerifyWorld) (support : RunSupport) : Prop where @@ -492,7 +492,7 @@ theorem tryIotaAfterCleanup_state_wf | prj id field value info => exact hdispatch (.prj id field value info) s | nat value blob info => exact hdispatch (.nat value blob info) s -/-- The complete post-major preprocessing stage preserves the fixed K1 +/-- The complete post-major preprocessing stage preserves the fixed WHNF invariant. Nat conversion and both cleanup passes are now concrete. String conversion uses the finite StringExpansion plan and the predecessor method-table contract for its one policy-selected callback. -/ diff --git a/Ix/Kernel/Verify/Whnf/Iota/OptionalReduction.lean b/Ix/Kernel/Verify/Whnf/Iota/OptionalReduction.lean index 262a58432..89aee4202 100644 --- a/Ix/Kernel/Verify/Whnf/Iota/OptionalReduction.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/OptionalReduction.lean @@ -4,7 +4,7 @@ import Ix.Kernel.Verify.Whnf.Iota.Ingress # Exhaustive iota optional-reduction contract `Ingress` proves that every result or partial error of the production -`tryIotaWithFlags` dispatcher preserves the complete K1 state invariant. This +`tryIotaWithFlags` dispatcher preserves the complete WHNF state invariant. This slice separates the two remaining concerns: * `IotaCallbackFrameOracle` retains the trusted-reference and diff --git a/Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean b/Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean index 680fd94ca..a2e5c43d4 100644 --- a/Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/SelectedRule.lean @@ -156,7 +156,7 @@ end RecM namespace TcM -/-- A successful universe-instantiation run preserves the complete K1 +/-- A successful universe-instantiation run preserves the complete WHNF invariant, changes only the intern table, and returns an expression in the walk's finite support. RuleInstantiation used the walker equation semantically; this is the state/resource half needed before the three ArgumentExecution traces can start. -/ diff --git a/Ix/Kernel/Verify/Whnf/Iota/StructEtaControl.lean b/Ix/Kernel/Verify/Whnf/Iota/StructEtaControl.lean index 8ebcb7d67..82da3ada9 100644 --- a/Ix/Kernel/Verify/Whnf/Iota/StructEtaControl.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/StructEtaControl.lean @@ -886,7 +886,7 @@ theorem eval h.selection.eval (h.probes.success h.admissible h.instantiation h.rebuild) -/-- K1 acceptance at the honest semantic boundary. The operational trace is +/-- WHNF acceptance at the honest semantic boundary. The operational trace is constructed here; state preservation, finite support, and Theory meaning are explicit premises because structure-likeness alone does not supply the registered struct-eta equation or projection interpretation. -/ diff --git a/Ix/Kernel/Verify/Whnf/Iota/SynthesisRequests.lean b/Ix/Kernel/Verify/Whnf/Iota/SynthesisRequests.lean index 69221e64e..3d4f82c82 100644 --- a/Ix/Kernel/Verify/Whnf/Iota/SynthesisRequests.lean +++ b/Ix/Kernel/Verify/Whnf/Iota/SynthesisRequests.lean @@ -233,7 +233,7 @@ theorem state_wf end FinishAppRequests -/-- Candidate construction preserves the complete K1 invariant from the +/-- Candidate construction preserves the complete WHNF invariant from the finite intern plan plus the two exact callback authorities. -/ theorem verifyKSynthCandidate_state_wf_of_requests {α : Type} {initial : TcState .anon} {program : TcM .anon α} diff --git a/Ix/Kernel/Verify/Whnf/NoDelta/QuotientReflection.lean b/Ix/Kernel/Verify/Whnf/NoDelta/QuotientReflection.lean index 549a76cbe..fbc1907da 100644 --- a/Ix/Kernel/Verify/Whnf/NoDelta/QuotientReflection.lean +++ b/Ix/Kernel/Verify/Whnf/NoDelta/QuotientReflection.lean @@ -17,7 +17,7 @@ namespace Ix.Kernel open Ix.Theory.Named (VExpr) -/-- Theory-only quotient contraction laws expected from Ix.Theory.Named Spec-19B. +/-- Theory-only quotient contraction laws required from Ix.Theory.Named. Both laws are deliberately phrased after the quotient major has been related to an exact `Quot.mk` application. The Ix adapter below owns the proof of that diff --git a/Ix/Kernel/Verify/Whnf/Projection/StringExpansion.lean b/Ix/Kernel/Verify/Whnf/Projection/StringExpansion.lean index ad7a264f4..78f4badb7 100644 --- a/Ix/Kernel/Verify/Whnf/Projection/StringExpansion.lean +++ b/Ix/Kernel/Verify/Whnf/Projection/StringExpansion.lean @@ -111,7 +111,7 @@ inductive StringListPlan (support : RunSupport) StringListPlan support charOfNat cons (c :: chars) list result /-- The actual recursive String-list builder executes any finite pure plan, -returning its exact result and preserving the complete K1 invariant. -/ +returning its exact result and preserving the complete WHNF invariant. -/ theorem strLitListToConstructor_plan_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} @@ -264,7 +264,7 @@ theorem strLitToConstructorWithPrimitives_plan_exact_wf rw [hrun] exact ⟨hI9, rfl, plan.final, plan.translation uvars Delta⟩ -/-- Compatibility form used by K1 callers that need only support and some +/-- Compatibility form used by WHNF callers that need only support and some structural translation of the generated constructor term. -/ theorem strLitToConstructorWithPrimitives_plan_wf {layer : WhnfLayer} {semantics : CacheSemantics} {trProj : RawProjRel} diff --git a/Ix/Kernel/Verify/Whnf/README.md b/Ix/Kernel/Verify/Whnf/README.md index f204baea5..c3a257534 100644 --- a/Ix/Kernel/Verify/Whnf/README.md +++ b/Ix/Kernel/Verify/Whnf/README.md @@ -1,8 +1,7 @@ # WHNF verification modules -The WHNF formalization is organized by proof responsibility rather than by -project milestone. The directories are conceptual layers; imports retain the -precise proof-dependency order needed by Lean. +The WHNF formalization is organized by proof responsibility. The directories +group related contracts; imports retain the proof-dependency order needed by Lean. - `RuntimeContracts.lean` defines the common state, callback, and result contracts used by the reducer proofs. diff --git a/Ix/Kernel/Verify/Whnf/Runtime/LazyIngress.lean b/Ix/Kernel/Verify/Whnf/Runtime/LazyIngress.lean index 99045d5ce..db2656c95 100644 --- a/Ix/Kernel/Verify/Whnf/Runtime/LazyIngress.lean +++ b/Ix/Kernel/Verify/Whnf/Runtime/LazyIngress.lean @@ -102,7 +102,7 @@ theorem ctxRecon simpa [TcM.lazyIngressPost, frame.nextFVarId] using hold · simpa [TcM.lazyIngressPost] using h.lets -/-- One callback outcome preserves the entire K1 invariant, including the +/-- One callback outcome preserves the entire WHNF invariant, including the address mark retained by production on both success and failure. -/ theorem whnfStateInv {layer : WhnfLayer} {semantics : CacheSemantics} diff --git a/Ix/Kernel/Verify/Whnf/StructEta/RebuildTail.lean b/Ix/Kernel/Verify/Whnf/StructEta/RebuildTail.lean index ff2231721..a7e0da5fb 100644 --- a/Ix/Kernel/Verify/Whnf/StructEta/RebuildTail.lean +++ b/Ix/Kernel/Verify/Whnf/StructEta/RebuildTail.lean @@ -14,7 +14,7 @@ namespace Ix.Kernel namespace TcM -/-- Universe instantiation preserves the complete K1 invariant on both +/-- Universe instantiation preserves the complete WHNF invariant on both outcomes. On success it additionally returns the pure-spec equation and a result in finite run support. The error proof is important here: production uses non-backtracking `EStateM`, so a failed walk may retain intern-table diff --git a/Ix/Kernel/Verify/Whnf/Structural/BasicStep.lean b/Ix/Kernel/Verify/Whnf/Structural/BasicStep.lean index f9d33dd5c..a4a390df2 100644 --- a/Ix/Kernel/Verify/Whnf/Structural/BasicStep.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/BasicStep.lean @@ -18,7 +18,7 @@ namespace Ix.Kernel namespace RecM /-- Runtime safety needed by production's unchanged let-fvar return. This -property is indexed by every state satisfying the fixed K1 invariant so it +property is indexed by every state satisfying the fixed WHNF invariant so it can be consumed by the uniform `WhnfStep.WF` contract rather than by one hand-picked execution fixture. -/ def FVarZetaSafety (layer : WhnfLayer) (semantics : CacheSemantics) diff --git a/Ix/Kernel/Verify/Whnf/Structural/ProjectionStep.lean b/Ix/Kernel/Verify/Whnf/Structural/ProjectionStep.lean index 5cb237693..a0e641c7b 100644 --- a/Ix/Kernel/Verify/Whnf/Structural/ProjectionStep.lean +++ b/Ix/Kernel/Verify/Whnf/Structural/ProjectionStep.lean @@ -11,7 +11,7 @@ lazy ingress. `ProjectionHelper.WF` records exactly that remaining implementation boundary: for a supported callback result, the actual `tryProjReduce` computation -preserves the fixed K1 state invariant on hits, misses, and errors, and any +preserves the fixed WHNF state invariant on hits, misses, and errors, and any successful result remains in finite run support. The step theorem below then proves every concrete projection outcome. Semantic authority for a hit stays with `InductiveReductionOracle`; a syntax-directed helper execution alone is diff --git a/Ix/Kernel/Verify/World.lean b/Ix/Kernel/Verify/World.lean index 3876b7358..576960bfe 100644 --- a/Ix/Kernel/Verify/World.lean +++ b/Ix/Kernel/Verify/World.lean @@ -4,8 +4,8 @@ import Ix.Theory.Named.Typing.Env /-! # Non-circular verification worlds -This is the additive G1a model. It separates four things which the old -whole-`KEnv` relation conflates: +The verification world separates the catalog, trusted declarations, and +concrete lazy-load state: * `Catalog`: immutable ghost input, including pending and unrelated declarations; @@ -21,14 +21,12 @@ whole-`KEnv` relation conflates: Crucially, being catalogued is not a typing fact. `VerifyWorld.ofCatalog` accepts an arbitrary catalog while trusting nothing, and `LoadedAgrees` does not require every catalog entry to be loaded. The trusted-catalog semantic -log is deliberately not faked as a bare structure field: G1c's -`TrustedCatalogRel` in `Verify/Env.lean` is an explicit proof object connecting +log is an explicit proof object: `TrustedCatalogRel` in `Verify/Env.lean` connects `trusted` to `venv`. Consumers must carry that relation before treating trusted membership as a WF witness. -This module was introduced beside the old whole-`KEnv` relation in G1a. -`Verify/State.lean` now uses it for `TcInv`, and G2b consumers resolve exact -constants through `TrustedConstRel`. The legacy `TrKEnv` remains only as a +`Verify/State.lean` uses this model for `TcInv`; lookup consumers resolve exact +constants through `TrustedConstRel`. The legacy `TrKEnv` remains a quarantined compatibility proof interface. -/ @@ -86,7 +84,7 @@ structure VerifyWorld where venvWF : venv.WF trustedCatalogued : ∀ {id}, trusted id → Catalog.Contains catalog id /-- Exact block identity is immutable ghost input. The default preserves - the pre-E0 standalone fixtures, which do not exercise coordinated blocks. -/ + standalone fixtures, which do not exercise coordinated blocks. -/ blocks : BlockCatalog := BlockCatalog.empty namespace VerifyWorld @@ -257,8 +255,8 @@ section Insert variable [LawfulBEq (KId .anon)] [LawfulHashable (KId .anon)] /-- A lazy-load insertion preserves agreement when the inserted declaration -is the catalog entry. The lawfulness instances are hypotheses here; G1a -does not move the existing global instances out of `Verify/Env.lean`. -/ +is the catalog entry. Lawfulness instances are explicit hypotheses; the +global instances are defined in `Verify/Env.lean`. -/ theorem insert {catalog : Catalog} {env : KEnv .anon} (h : LoadedAgrees catalog env) {id : KId .anon} {c : KConst .anon} (hc : catalog id = some c) : LoadedAgrees catalog (env.insert id c) := by diff --git a/Ix/Kernel/Whnf.lean b/Ix/Kernel/Whnf.lean index d74511c4f..f19786d71 100644 --- a/Ix/Kernel/Whnf.lean +++ b/Ix/Kernel/Whnf.lean @@ -382,7 +382,7 @@ def natOffsetStuckHead (p : Primitives m) : KExpr m → Bool These helpers used to live in the large recursive WHNF mutual block even though none of them takes a recursive edge. Keeping them outside that block -makes their equations transparent to the K0 proofs without adding runtime +makes their equations transparent to the totalization proofs without adding runtime fuel or changing their operational behavior. -/ diff --git a/Ix/Theory/Named/ConstructorValidityFixtures.lean b/Ix/Theory/Named/ConstructorValidityFixtures.lean index 7d5348b7b..a04903c68 100644 --- a/Ix/Theory/Named/ConstructorValidityFixtures.lean +++ b/Ix/Theory/Named/ConstructorValidityFixtures.lean @@ -11,7 +11,7 @@ open Ix.Theory (VLevel) /-! # Constructor-validity parity fixtures -Focused singleton declarations for Spec-05. The positive declarations retain +Focused singleton constructor-validity declarations. The positive declarations retain real kernel metadata while remaining inside the already-supported large- elimination and non-K fragment. The failed declarations pin the nearest Lean elaborator/kernel rejection for each neighboring positivity or universe diff --git a/Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean b/Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean index e5c89c2ca..b06bed1fb 100644 --- a/Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean +++ b/Ix/Theory/Named/Fixtures/ProjectionExpressibility.lean @@ -1139,7 +1139,7 @@ theorem dependentRecord_rules_registered : /-! ## Frozen legacy surface -The seven fields below preserve the exact pre-Spec-13 theorem shapes. They +The seven fields below preserve the earlier projection theorem shapes. They are intentionally only statement data: constructing this bundle would reintroduce the old proof obligations. In particular, `wf` permits unrelated contexts, `uniq` permits unrelated structure names, and every diff --git a/Ix/Theory/Named/Inductive.lean b/Ix/Theory/Named/Inductive.lean index 2e67b9fd2..de7598221 100644 --- a/Ix/Theory/Named/Inductive.lean +++ b/Ix/Theory/Named/Inductive.lean @@ -898,9 +898,8 @@ def checkedFamilies? (source : VInductDecl) (params : List VExpr) : /-- Source-indexed checked representation of a complete inductive block. Shared parameters are stored once; every per-family component lives in the -dependent `families` spine indexed by `source.types` itself. This is the -Spec-08A analysis boundary and intentionally has no generation or insertion -projection. -/ +dependent `families` spine indexed by `source.types` itself. This analysis +artifact contains no generation or insertion result. -/ structure CheckedBlock (source : VInductDecl) where params : List VExpr params_eq : params = blockParams source.nparams source.types @@ -1312,7 +1311,7 @@ structure GenerationChecked (source : VInductDecl) where /-- Identity normalization always satisfies the mixed generator's positional layout gate. The only non-reflexive facts are the parameter and constructor -parameter lengths already certified by Stage 3. -/ +parameter lengths certified by `Checked.direct_layout`. -/ theorem Checked.identityBlock_generationShape {decl : VInductDecl} (checked : decl.Checked) : checked.identityBlock.generationShape = true := by @@ -2991,7 +2990,7 @@ def VEnv.addInduct (env : VEnv) (decl : VInductDecl) : Option VEnv := do let generation ← decl.identityBlockGeneration? env.addInductBlockGeneration generation -/-- Compatibility wrapper for the pre-Spec-08C one-family raw transaction. +/-- Compatibility wrapper for the one-family raw transaction. Unlike `addInduct`, this deliberately projects the legacy `Checked` artifact and therefore rejects every genuinely mutual declaration. It remains only diff --git a/Ix/Theory/Named/InductiveFixtures.lean b/Ix/Theory/Named/InductiveFixtures.lean index f1b2ff3be..480b6e8aa 100644 --- a/Ix/Theory/Named/InductiveFixtures.lean +++ b/Ix/Theory/Named/InductiveFixtures.lean @@ -12,7 +12,7 @@ import Ix.Theory.Named.Typing.Meta open Ix.Theory (VLevel) -/-! Adequacy fixtures for `VEnv.addInduct` (stage 3): run the generator on +/-! Adequacy fixtures for `VEnv.addInduct`: run the generator on hand-written declarations and check the output against the real kernel's constants, translated by the `vconst`/`vdefeq` macros. A mismatch in telescope order, universe conventions, or de Bruijn arithmetic fails these diff --git a/Ix/Theory/Named/MutualInductiveFixtures.lean b/Ix/Theory/Named/MutualInductiveFixtures.lean index 23cfbdb48..c6548c444 100644 --- a/Ix/Theory/Named/MutualInductiveFixtures.lean +++ b/Ix/Theory/Named/MutualInductiveFixtures.lean @@ -14,7 +14,7 @@ import Ix.Theory.Named.Meta These real kernel declarations pin shared parameters, per-family indices/results, constructor order, and cross-family recursive target ordinals at the `VInductDecl.CheckedBlock` boundary, then exercise the -block-wide public generation transaction added by Spec-08C. The Verify mutual +block-wide public generation transaction. The Verify mutual fixture supplies semantic preservation, complete kernel metadata comparison, and environment replay. -/ diff --git a/Ix/Theory/Named/NestedInductive.lean b/Ix/Theory/Named/NestedInductive.lean index 2b469231a..45fc9759d 100644 --- a/Ix/Theory/Named/NestedInductive.lean +++ b/Ix/Theory/Named/NestedInductive.lean @@ -9,11 +9,11 @@ import Ix.Theory.Named.Inductive open Ix.Theory (VLevel) /-! -# Nested-inductive flattening (Spec-09B) +# Nested-inductive flattening The Theory mirror of the kernel's `ElimNestedInductive` transformation, -following the committed Spec-09A design -(`Ix.Theory.Named/Verify/Environment/NestedRepresentation.lean`): the stored +with representation probes in `Verify/Environment/NestedRepresentation.lean`: +the stored payload of a nested declaration is the source `VInductDecl`, and nested support flows through an additive artifact coupling @@ -45,16 +45,15 @@ The transformation mirrors the kernel phase for phase: block is stable. - Auxiliary names are canonical: `(`_nested` ++ familyName).appendIndexAfter i` with a global counter, matching the kernel's choice whenever the ambient - environment contains no colliding `_nested.*` constant. The Spec-09A + environment contains no colliding `_nested.*` constant. The representation collision probe shows the choice is erased from all final artifacts, and in-block collisions are rejected downstream by `blockNamesOK` exactly where the kernel's `checkName` rejects its own collisions. Acceptance (`nestedStage3`) is flattening success plus generation -readiness of the flattened block through the unchanged Spec-08 machinery. -No generated recursor, rule, or environment replay is claimed at this -checkpoint; the restoration substitution over generation artifacts is -Spec-09C's obligation. +readiness of the flattened block through the block analyzer and generator. +Generation artifacts are subsequently restored by the substitution defined +in this module; environment replay is verified separately. -/ namespace Ix.Theory.Named @@ -287,9 +286,8 @@ def NestedElimination.numNested {source : VInductDecl} elim.specs.length /-- A flattened declaration accepted by the unchanged arbitrary-block -machinery: the complete Spec-09B validation gate. Positivity, name, level, -anatomy, and generation-shape checking of the flattened block reuse the -Spec-08 analyzers verbatim. -/ +machinery. Positivity, name, level, anatomy, and generation-shape checking +reuse the block analyzers. -/ structure NestedBlockChecked (source : VInductDecl) where elim : NestedElimination source generation : BlockGenerationChecked elim.flat @@ -306,7 +304,7 @@ def nestedStage3 (targets : List NestedTargetBlock) (source : VInductDecl) (fuel : Nat := 1000) : Bool := (nestedBlockChecked? targets source fuel).isSome -/-! ## Restoration (Spec-09C) +/-! ## Restoration The restoration substitution σ maps the flattened block's generation artifacts back to the stored metadata surface: auxiliary family constants @@ -477,8 +475,8 @@ well formed at their exact insertion environments. The phase environments are determined by the deterministic constant folds, so each later field takes the earlier folds as hypotheses; a fixture discharges them by computation. Inhabiting this package from the flattened block's staged -semantic certificate is the σ-transport route recorded by the Spec-09A -design note; fixtures may equally inhabit it from direct checker +semantic certificate requires typing transport along σ; fixtures may also +inhabit it from direct checker executions on the restored artifacts. -/ structure NestedBlockChecked.WF {source : VInductDecl} (nested : NestedBlockChecked source) (env : VEnv) : Prop where diff --git a/Ix/Theory/Named/NestedInductiveFixtures.lean b/Ix/Theory/Named/NestedInductiveFixtures.lean index 8ca84b912..015ce17ad 100644 --- a/Ix/Theory/Named/NestedInductiveFixtures.lean +++ b/Ix/Theory/Named/NestedInductiveFixtures.lean @@ -7,7 +7,7 @@ Source attribution and revision: Ix/Theory/Named/NOTICE. import Ix.Theory.Named.NestedInductive /-! -# Nested flattening fixtures (Spec-09B) +# Nested flattening fixtures Executable pins for `nestedElimination?` on the two ladder fixtures — a universe-polymorphic rose tree through `List` and a nested indexed family @@ -85,7 +85,7 @@ def roseSource : VInductDecl where /-- The expected flattened rose block: the rewritten source family plus one auxiliary family, exactly the shapes pinned against the kernel by the -Spec-09A probes. -/ +representation probes. -/ def roseFlat : VInductDecl where uvars := 1 nparams := 1 @@ -266,7 +266,7 @@ def collisionSource : VInductDecl where #guard (nestedElimination? [listTarget] collisionSource).isSome #guard !nestedStage3 [listTarget] collisionSource -/-! ## Restoration pins (Spec-09C) +/-! ## Restoration checks Structural pins for the restored generation artifacts; the exact comparison against Lean's stored recursor types and rule RHSs lives in the diff --git a/Ix/Theory/Named/Projection.lean b/Ix/Theory/Named/Projection.lean index b4ed1ed5c..c3df2c34c 100644 --- a/Ix/Theory/Named/Projection.lean +++ b/Ix/Theory/Named/Projection.lean @@ -3447,7 +3447,7 @@ remains the proved `projector_constructor_exact` theorem. Its eventual proof uses `IsDefEqU.weakN_iff` together with injectivity of registered inductive heads. Keeping the boundary in Theory makes the -temporary Spec-16/17 dependency explicit instead of leaving Verify's +remaining inversion and injectivity dependencies explicit instead of leaving Verify's structural laws as local holes. -/ structure RegisteredStructureHeadInversion (env : VEnv) : Prop where weak'_inv : @@ -3499,10 +3499,9 @@ structure RegisteredStructureHeadInversion (env : VEnv) : Prop where code constructorName runtimeMajor runtimeField) set_option warn.sorry false in -/-- Public Tier-R registered-head inversion statement. Spec-16/17 discharge -the underlying constant-head theorem; projection structural laws consume only -this stable interface and therefore shed `sorryAx` automatically when it is -proved. -/ +/-- Registered-head inversion statement. The constant-head inversion proof +remains unfinished. Projection structural laws consume this interface and +inherit its `sorryAx` dependency until that proof is supplied. -/ theorem WF.registeredStructureHeadInversion (self : VEnv.WF env) : RegisteredStructureHeadInversion env := by sorry diff --git a/Ix/Theory/Named/SingletonParity.lean b/Ix/Theory/Named/SingletonParity.lean index 32a76e7d4..aa1b08e7a 100644 --- a/Ix/Theory/Named/SingletonParity.lean +++ b/Ix/Theory/Named/SingletonParity.lean @@ -12,7 +12,7 @@ open Ix.Theory (VLevel) /-! # Complete singleton-family parity inputs -This module is the Theory-side inventory for Spec-07. Each row owns the exact +This module inventories singleton Theory fixtures. Each row owns the exact raw declaration together with the one checked generation artifact consumed by the kernel differential and environment-replay matrix. `Unit` is represented honestly by the kernel's polymorphic `PUnit` family; the reducible `Unit` @@ -135,7 +135,7 @@ def constructorNames (artifact : SingletonParityArtifact) : List Name := end SingletonParityArtifact -/-- The fixed Spec-07 positive matrix, in roadmap order. The `Unit` row points +/-- The positive matrix in fixed order. The `Unit` row points to `PUnit`, matching the actual v4.31 kernel representation rather than inventing alias-level inductive metadata. -/ def singletonPositiveArtifacts : List SingletonParityArtifact := diff --git a/Ix/Theory/Named/Typing/InductiveCertificate.lean b/Ix/Theory/Named/Typing/InductiveCertificate.lean index 3f0afdf3e..991c81b97 100644 --- a/Ix/Theory/Named/Typing/InductiveCertificate.lean +++ b/Ix/Theory/Named/Typing/InductiveCertificate.lean @@ -320,7 +320,7 @@ theorem recursorPattern .mk hentry /-- Rule-level consumer bundle: exact global position, generated-list -membership, registration, well-formedness, and the corresponding Spec-10 +membership, registration, well-formedness, and the corresponding iota-pattern pattern all come from the same completed block. -/ structure RecursorRuleFacts (certificate : BlockCertificate source before after) diff --git a/Ix/Theory/Named/Typing/InductivePattern.lean b/Ix/Theory/Named/Typing/InductivePattern.lean index b853952d7..75a95627f 100644 --- a/Ix/Theory/Named/Typing/InductivePattern.lean +++ b/Ix/Theory/Named/Typing/InductivePattern.lean @@ -34,9 +34,9 @@ Church–Rosser `Params` interface demands of one certified block: same-recursor rules comes from the analyzer's terminal `blockTarget?` arity equation. -No open-environment `Params` instance is installed here; the block supplies -the facts, and soundness (`pat_wf`) plus the block-local environment -assembler belong to the pattern-soundness milestone. -/ +The block supplies the `Params` facts. Pattern soundness (`pat_wf`) and the +block-local environment assembler are defined in `Typing/InductivePatternWF.lean`. +This module installs no open-environment `Params` instance. -/ namespace Ix.Theory.Named @@ -535,7 +535,7 @@ theorem rulePattern_inj {i i' : Nat} {c c' : NormalizedBlockCtor} /-- Closedness inputs for one certified block's rule payloads: the towers a rule's RHS template and checks embed as fixed template constants. Concrete -fixtures discharge this bundle by `decide`; the pattern-soundness milestone +fixtures discharge this bundle by `decide`; the pattern-soundness proof derives it from the staged environment's rule well-formedness. -/ structure RuleClosure : Prop where rhs_closed : ∀ ⦃i : Nat⦄ ⦃constructor : NormalizedBlockCtor⦄, diff --git a/Ix/Theory/Named/Typing/InductivePatternWF.lean b/Ix/Theory/Named/Typing/InductivePatternWF.lean index d01b7305a..ab8ef68d9 100644 --- a/Ix/Theory/Named/Typing/InductivePatternWF.lean +++ b/Ix/Theory/Named/Typing/InductivePatternWF.lean @@ -12,7 +12,7 @@ open Ix.Theory (VLevel) /-! # Pattern soundness for generated iota rules -The typed β-collapse layer for Spec-10B: applying a lambda tower to a +Typed β-collapse: applying a lambda tower to a well-typed argument spine is definitionally equal to the iterated instantiation of its body (`IsDefEq.appN_lamN`), applications are congruent along spines (`IsDefEq.appN_congr`, `IsDefEq.appN_defEq` over @@ -921,8 +921,8 @@ end Ix.Theory.Named The typed β-collapse layer is sorry-free. `pat_wf` composes typed defeqs through `IsDefEqU.of_l`/`IsDefEqU.trans` and therefore carries exactly the transitional unique-typing closure the Church–Rosser development itself -carries; it sheds `sorryAx` automatically when the Spec-16/17 inversion -milestones land, with no restatement. -/ +carries. The `sorryAx` dependency remains until the underlying inversion +and unique-typing proofs are complete. -/ #guard_named_axioms Ix.Theory.Named.VEnv.IsDefEq.appN_lamN [propext, Quot.sound] diff --git a/Ix/Theory/Named/Typing/NestedInductiveLemmas.lean b/Ix/Theory/Named/Typing/NestedInductiveLemmas.lean index 1a8ad71d8..9c856542e 100644 --- a/Ix/Theory/Named/Typing/NestedInductiveLemmas.lean +++ b/Ix/Theory/Named/Typing/NestedInductiveLemmas.lean @@ -8,7 +8,7 @@ import Ix.Theory.Named.NestedInductive import Ix.Theory.Named.Typing.InductiveLemmas /-! -# Nested transaction facts and preservation (Spec-09C) +# Nested transaction facts and preservation The `addInductNested` analog of the block-wide transaction lemma suite: exact phase recovery, atomicity, monotonicity, freshness, lookup and rule diff --git a/Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean b/Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean index 78ff92f85..375fdd742 100644 --- a/Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean +++ b/Ix/Theory/Named/Verify/Environment/ConstructorValidation.lean @@ -2024,8 +2024,8 @@ evidence, not caller-supplied Theory judgments. /-- Executable fragment on which strict kernel-to-Theory translation has a syntactically unique endpoint. Projections are excluded because the current `TrProj` contract determines their result only up to definitional equality; -projection-bearing inductives remain outside the singleton subset until the -projection milestones establish an exact structural API. -/ +projection-bearing inductives require an exact structural projection API +before they can be included in the singleton subset. -/ def theoryTranslationUnique : Expr → Bool | .bvar _ | .fvar _ @@ -4231,8 +4231,8 @@ namespace VInductDecl The ordinary outer producer deliberately remains unchanged: its successful equation records kernel validation, while this additive wrapper retains the -verified universe-semantic audit introduced by Spec-01D1 and extended by -Spec-02C. The normalized branch intersects the ordinary core decision with +verified audit of constructor-universe comparisons. The normalized branch +intersects the ordinary core decision with the proved project comparison, without making bare `buildNormalizationCandidate` success carry Theory meaning. -/ diff --git a/Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean b/Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean index 1692e8052..cc2391518 100644 --- a/Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean +++ b/Ix/Theory/Named/Verify/Environment/ConstructorValidityMatrix.lean @@ -8,7 +8,7 @@ import Ix.Theory.Named.ConstructorValidityFixtures import Ix.Theory.Named.Verify.Environment.InductiveFixtures /-! -# Spec-05 constructor-validity differential matrix +# Constructor-validity differential matrix The positive half quotes real Lean metadata, runs the ordinary normalization candidate producer, then runs both strengthened constructor gates at their diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean index 4f9c11fa7..8eeccab9e 100644 --- a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEdges.lean @@ -8,7 +8,7 @@ import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon open Ix.Theory (VLevel) -/-! Exact Spec-06C `Unit`/`PUnit` and `Empty` edge-shape fixtures. +/-! Exact `Unit`/`PUnit` and `Empty` elimination edge-shape fixtures. `Unit` is a reducible alias for `PUnit` on this Lean revision. The alias has definition metadata but no independent inductive/constructor/recursor records, diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean index 11b50dbb2..69e1bb788 100644 --- a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEq.lean @@ -6,7 +6,7 @@ Source attribution and revision: Ix/Theory/Named/NOTICE. import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon -/-! Exact Spec-06B Eq differential fixture. -/ +/-! Exact Eq elimination differential fixture. -/ namespace Ix.Theory.Named.InductiveReplayFixtures open Lean Meta Elab Term diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean index ba3fbfbc4..c86c38b17 100644 --- a/Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesEqNat.lean @@ -7,4 +7,4 @@ Source attribution and revision: Ix/Theory/Named/NOTICE. import Ix.Theory.Named.Verify.Environment.EliminationFixturesEq import Ix.Theory.Named.Verify.Environment.EliminationFixturesNat -/-! Umbrella for the exact Spec-06A Eq and Nat differential fixtures. -/ +/-! Umbrella for the exact Eq and Nat elimination differential fixtures. -/ diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean index 5da576adb..17fd8314c 100644 --- a/Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesNat.lean @@ -6,7 +6,7 @@ Source attribution and revision: Ix/Theory/Named/NOTICE. import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon -/-! Exact Spec-06B Nat never-zero elimination and non-K fixture. -/ +/-! Exact Nat never-zero elimination and non-K fixture. -/ namespace Ix.Theory.Named.InductiveReplayFixtures open Lean Meta Elab Term diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean index 3688cf991..bf50f1151 100644 --- a/Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesOrAnd.lean @@ -6,7 +6,7 @@ Source attribution and revision: Ix/Theory/Named/NOTICE. import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon -/-! Exact Spec-06B Or/And differential fixtures. -/ +/-! Exact Or/And elimination differential fixtures. -/ namespace Ix.Theory.Named.InductiveReplayFixtures open Lean Meta Elab Term diff --git a/Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean b/Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean index 309021ddf..88999bce7 100644 --- a/Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean +++ b/Ix/Theory/Named/Verify/Environment/EliminationFixturesSmall.lean @@ -6,7 +6,7 @@ Source attribution and revision: Ix/Theory/Named/NOTICE. import Ix.Theory.Named.Verify.Environment.EliminationFixturesCommon -/-! Exact Spec-06B source-universe small-elimination differential fixture. -/ +/-! Exact source-universe small-elimination differential fixture. -/ namespace Ix.Theory.Named.InductiveReplayFixtures open Lean Meta Elab Term diff --git a/Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean b/Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean index 1a12306a7..d153fb0f5 100644 --- a/Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean +++ b/Ix/Theory/Named/Verify/Environment/IndexedVecSemanticReplay.lean @@ -12,7 +12,7 @@ import Ix.Theory.Named.Verify.Environment.IndexedVecOuterReplay This module connects the exact executable family/`nil`/`cons` candidate produced by `buildNormalizationCandidate` to its Theory generation -certificate and the E1 kernel-environment replay. Every retained candidate +certificate and the kernel-environment replay. Every retained candidate node is interpreted in its exact pre-family or post-family verifier context; the final transaction therefore consumes the certificate projected from the same producer-selected package rather than an independently supplied @@ -3231,7 +3231,7 @@ theorem indexedVecSemantic_aligned_checked : indexedVecSemantic_trEnv'_checked.aligned /- -The semantic assembly, executable producer, and final E1 replay intentionally +The semantic assembly, executable producer, and final environment replay inherit the existing transitional verifier closure. These guards make additions to that closure visible at the public roots of this module. -/ diff --git a/Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean b/Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean index 0d9cb3079..b6efeea82 100644 --- a/Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean +++ b/Ix/Theory/Named/Verify/Environment/InductiveFixtures.lean @@ -7594,11 +7594,9 @@ theorem aliasFormerAlignmentRun : aliasFormerNormalizationCandidate.families.singleton.constructors { aliasFormerNormalizationCandidate.families.singleton.familyType.type.trace.terminalContext with env := aliasFormerCtorCandidateContext.env } = .ok () := by - -- Tier V (Spec-19B, v4.33 reconciliation repair debt): the premerge proof - -- stepped `ConstructorCandidateAlignmentTrace.build` with `rw [build.eq_def]`, - -- which the v4.33 elaborator no longer matches (and eq_def-in-simp loops). - -- The statement is an exact closed checker run and remains true; the - -- stepping proof needs a rework against the new equation-lemma shapes. + -- This exact checker-run proof needs updated equation lemmas for Lean 4.33. + -- `rw [build.eq_def]` no longer matches `ConstructorCandidateAlignmentTrace.build`, + -- and using that equation in `simp` loops. sorry private def aliasFormerStagedPostFamilyInput : diff --git a/Ix/Theory/Named/Verify/Environment/NestedReplay.lean b/Ix/Theory/Named/Verify/Environment/NestedReplay.lean index e06fb7d68..e23eb4c19 100644 --- a/Ix/Theory/Named/Verify/Environment/NestedReplay.lean +++ b/Ix/Theory/Named/Verify/Environment/NestedReplay.lean @@ -9,7 +9,7 @@ import Ix.Theory.Named.Verify.Environment.SingletonParityReplay import Ix.Theory.Named.Verify.Environment.NestedTransformation /-! -# Nested environment replay (Spec-09C) +# Nested environment replay Both ladder fixtures replayed from real stored metadata: the rose tree over the completed `List` environment and the nested-indexed family over diff --git a/Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean b/Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean index 765a88594..84291cdc6 100644 --- a/Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean +++ b/Ix/Theory/Named/Verify/Environment/NestedRepresentation.lean @@ -11,14 +11,11 @@ import Ix.Theory.Named.Meta open Ix.Theory (VLevel) /-! -# Spec-09A: nested-inductive representation audit and decision +# Nested-inductive representation and restoration -This file is the committed design note and the executable metadata probes -for the nested-inductive representation decision. Every claim below is -pinned by a build-failing probe in this file unless it is explicitly marked -as a forward-looking obligation. This checkpoint changes no acceptance -behavior: the probes only observe the implementation and the existing -Theory analyzers. +The executable probes in this module check nested-inductive metadata and +its Theory representation. The remaining semantic proof obligations are +listed separately from those concrete checks. ## Audit: how the implementation represents nested inductives @@ -42,8 +39,7 @@ Theory analyzers. restoration (`Result.restoreNested`), each auxiliary family's recursor is re-added under the name `(mkRecName mainName).appendIndexAfter i` with restored type and rules, and finally every `aux2nested` value - `I Ds` is type-checked (the lean4#14577 escape-hatch check, regression - tested in `Tests/NestedInductive.lean`). The auxiliary families, + `I Ds` is type-checked. The auxiliary families, constructors, and recursor names never enter the final environment. The stored metadata therefore has this shape (probes P1, P2): @@ -74,13 +70,12 @@ new field: `numNested` is implementation metadata recoverable as the number of auxiliary specifications, and parity fixtures pin it per row exactly as they already pin `numNested == 0` for non-nested rows. -Nested support is an additive checked-block artifact (built in Spec-09B/C), -coupling: +Nested support is a checked-block artifact coupling: 1. the flattened block as an ordinary `VInductDecl` — probe P4 shows both target fixtures' flattened blocks are already accepted by the existing `identityBlockGeneration?` machinery, so flattening reuses the complete - Spec-08 block analyzer and generator unchanged; + block analyzer and generator; 2. one auxiliary specification per auxiliary family, in flattened family order: the auxiliary name, the nested value `I Ds` open over the block parameters (the Theory analog of `aux2nested`), and the restored @@ -124,15 +119,15 @@ Rejected alternatives: relation alone would force Verify to re-synthesize them. The artifact's executable coherence checks subsume the relation. -## Obligations recorded for Spec-09B/09C (not claimed here) +## Semantic proof obligations -- 09B: Theory-side flattening and auxiliary-specification validation — +- Theory-side flattening and auxiliary-specification validation — positivity through the existing block analyzer on the flattened block; executable instantiation checks of auxiliary family/constructor types against `I`'s metadata at `Ds`; nearest rejection differentials (ill-typed `Ds` — the lean4#14577 class — wrong specification order, non-matching instantiation). -- 09C: σ as a total Theory function. The spine rule needs a simultaneous +- Restoration by a total Theory function σ. The spine rule needs a simultaneous `instantiateRev`-style multi-substitution for `nparams > 1`: iterating single `VExpr.inst` is wrong once parameter arguments mention bvars. Generation, preservation (typing transport along σ: auxiliary constants @@ -430,7 +425,7 @@ run_meta do /-! ## P3: exact flattening pins The flattened blocks, translated to binder-erased `VExpr` form. These are -the descriptors the Spec-09B transformation must produce. -/ +the descriptors the flattening transformation must produce. -/ def roseFlatFamilies : List (Name × VExpr) := [(``RoseTree, .forallE (.sort (.succ (.param 0))) (.sort (.succ (.param 0)))), @@ -563,10 +558,10 @@ run_meta do /-! ## P5: the restoration substitution σ `restoreV09A` mirrors `ElimNestedInductive.Result.restoreNested` on -`VExpr`. It is probe-local: the Spec-09C artifact path must define the -total Theory version (with a simultaneous parameter substitution once -`nparams > 1` is in scope; the probe fixtures have `nparams ≤ 1`, where -iterated `VExpr.inst` coincides with it). -/ +`VExpr`. It is local to these probes; `NestedInductive.lean` defines the +total restoration function with simultaneous parameter substitution. +The probe fixtures have `nparams ≤ 1`, where iterated `VExpr.inst` agrees +with simultaneous substitution. -/ structure AuxSpec09A where aux : Name diff --git a/Ix/Theory/Named/Verify/Environment/NestedTransformation.lean b/Ix/Theory/Named/Verify/Environment/NestedTransformation.lean index d32c26af8..3968fce5a 100644 --- a/Ix/Theory/Named/Verify/Environment/NestedTransformation.lean +++ b/Ix/Theory/Named/Verify/Environment/NestedTransformation.lean @@ -8,7 +8,7 @@ import Ix.Theory.Named.Verify.Environment.NestedRepresentation import Ix.Theory.Named.NestedInductiveFixtures /-! -# Nested flattening differential (Spec-09B) +# Nested flattening differential Ties the Theory transformation `nestedElimination?` to the implementation: @@ -264,13 +264,13 @@ run_meta do unless !nestedStage3 [] roseV do throwError "noTarget: Theory gate accepted without target metadata" -/-! ## Restoration parity (Spec-09C) +/-! ## Restoration parity The Theory restoration over the flattened block's generation artifacts reproduces Lean's stored metadata exactly: every restored recursor name, universe count, and type, and every rule RHS in the globally flattened order, on all three real fixtures. This runs the product σ -(`NestedBlockChecked.recursors`/`generatedRules`), not the Spec-09A design +(`NestedBlockChecked.recursors`/`generatedRules`), not the representation probe. -/ open Elab in @@ -319,7 +319,7 @@ run_meta do checkRestoreParity "nv" ``NVTree [] 0 [pvecStoredTarget] checkRestoreParity "cu" ``CURose [] 0 [listTarget] -/-! ## Real-output round-trip (Spec-09C) +/-! ## Real-output round-trip Run the port's complete `Environment.addInductive` on a dependency-only kernel environment and compare its entire output — not the ambient diff --git a/Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean b/Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean index 4c68f01b9..abedd29a3 100644 --- a/Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean +++ b/Ix/Theory/Named/Verify/Environment/NormalizationMatrix.lean @@ -12,7 +12,7 @@ open Ix.Theory (VLevel) /-! # Normalization differential matrix -Executable and semantic replay for the Spec-04 matrix. The fixture deliberately +Executable and semantic replay for normalized inductives. The fixture deliberately places reducible aliases at every inductive-analysis boundary, including a Pi-producing alias around a recursive target. This file observes the actual kernel declarations, pins the exact analyzer output and its fuel boundary, and diff --git a/Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean b/Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean index f60012ae8..73df928be 100644 --- a/Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean +++ b/Ix/Theory/Named/Verify/Environment/SingletonParityMatrix.lean @@ -13,7 +13,7 @@ import Ix.Theory.Named.Verify.Environment.EliminationFixturesEdges import Ix.Theory.Named.Verify.Environment.NormalizationMatrix /-! -# Spec-07 complete singleton kernel matrix +# Complete singleton kernel matrix The rows below join the single Theory artifact inventory to Lean's actual `inductInfo`/`ctorInfo`/`recInfo` records. The executable predicate compares @@ -380,7 +380,7 @@ def recursorEliminationRejected07 (info : ConstantInfo) (sourceUvars : Nat) : def typeCollisionEnv07 : VEnv := (VEnv.empty.addConst ``Nat ⟨0, .sort .zero⟩).get (by decide) -/-- The complete Spec-07 negative matrix. Earlier phase-specific fixtures +/-- The complete negative matrix. Individual stage-specific fixtures retain their exact kernel error messages; this table makes their coverage and combined acceptance result executable from one public artifact path. -/ def singletonNegativeRows : List SingletonNegativeRow := diff --git a/Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean b/Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean index 944cc6aab..14ef0134e 100644 --- a/Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean +++ b/Ix/Theory/Named/Verify/Environment/SingletonParityReplay.lean @@ -10,7 +10,7 @@ import Ix.Theory.Named.Verify.Environment.SingletonParityMatrix open Ix.Theory (VLevel) /-! -# Spec-07 environment replay inventory +# Singleton environment replay inventory This module is the sole public environment-facing inventory for singleton parity. A row packages the actual implementation map, the Theory input and @@ -2701,7 +2701,7 @@ def emptyReplay07 : SingletonReplayArtifact where transaction := emptyAddInduct07 aligned := emptyAligned07 -/-- Every fixed Spec-07 positive row, in exactly the same order as the +/-- Every fixed positive row, in exactly the same order as the Theory/kernel parity matrix. Each entry carries an actual `ConstantInfo` transaction and final environment alignment, including the real dependency environments required by `Fin` and `Vector`. -/ @@ -2717,7 +2717,7 @@ def singletonNormalizationReplays : [aliasFormerReplay07, aliasRecReplay07, normalizationMatrixReplay07, annotatedPiReplay07, annotatedParamReplay07] -/-- The sole public Spec-07 environment replay inventory. -/ +/-- The public singleton environment replay inventory. -/ def singletonReplayMatrix : List SingletonReplayArtifact := singletonFixedReplays ++ singletonNormalizationReplays diff --git a/Tests/Ix/Kernel/CheckEnv.lean b/Tests/Ix/Kernel/CheckEnv.lean index ebaf6fc4d..edb6a5e7a 100644 --- a/Tests/Ix/Kernel/CheckEnv.lean +++ b/Tests/Ix/Kernel/CheckEnv.lean @@ -174,7 +174,7 @@ def focusConsts : Array Lean.Name := #[ `Tests.Ix.Compile.Mutual.PropRecMotives.pa_eq, `Tests.Ix.Compile.Mutual.PropRecMotives.pb2_length, `Tests.Ix.Compile.Mutual.PropRecMotives.pa2_eq, - -- Call-site shape coverage (plans/callsite-adapter-generalization.md): + -- Call-site shape coverage: -- direct full application at the Const head, inner-full redex, and -- dead-binder split redex (Collapsed-entry fallback), each in both -- source orders. diff --git a/Tests/Ix/Kernel/CheckTauCeti.lean b/Tests/Ix/Kernel/CheckTauCeti.lean index c2a3a5299..c6f03c040 100644 --- a/Tests/Ix/Kernel/CheckTauCeti.lean +++ b/Tests/Ix/Kernel/CheckTauCeti.lean @@ -52,7 +52,6 @@ def focusConsts : Array Lean.Name := #[ -- (`chebyshevMeasureT_eq_withDensity`, proved by measure ext), so -- every whnf of the stuck cast retries K-like reduction, whose -- `measureT ≟ withDensity …` def-eq must exhaust unfoldings and fail. - -- Optimization work items: plans/kernel-rec-fuel.md. `TauCeti.chebyshevWeightL2Isometry_apply, `TauCeti.chebyshevWeightL2Isometry_symm_apply, diff --git a/Tests/Ix/Kernel/CheckTests.lean b/Tests/Ix/Kernel/CheckTests.lean index 6e22b7481..3d54dcfb5 100644 --- a/Tests/Ix/Kernel/CheckTests.lean +++ b/Tests/Ix/Kernel/CheckTests.lean @@ -134,7 +134,7 @@ def wellScopedTests : TestSeq := | .error (.unknownConst _) => true | _ => false) : Bool)) -/-! ### K0 totalization boundaries -/ +/-! ### Totalization boundaries -/ def totalizationTests : TestSeq := test "universe validation preserves LIFO error order" diff --git a/docs/tc-k0-backedge-audit.md b/docs/kernel-recursion.md similarity index 77% rename from docs/tc-k0-backedge-audit.md rename to docs/kernel-recursion.md index b9cc4aef4..717c80a87 100644 --- a/docs/tc-k0-backedge-audit.md +++ b/docs/kernel-recursion.md @@ -1,14 +1,13 @@ -# Ix.Kernel K0 recursion and back-edge audit +# Kernel recursion and back-edge audit -Snapshot: 2026-07-27. This is the named K0 tick/measure artifact required by -the formal-verification plan. Its production scope is the kernel call graph -rooted at `TcM.checkConst`: `Whnf`, `Infer`, `DefEq`, `Inductive`, and +This audit covers the kernel call graph rooted at `TcM.checkConst`: +`Whnf`, `Infer`, `DefEq`, `Inductive`, and `Check`, together with the shared monad, expression, local-context, union-find, and canonical-checking helpers they call. Ingress, egress, parallel scheduling, and the meta-level trust-audit visitor are not on that call graph. -The audit result is now: +The call graph has: - zero `partial def` declarations in the production kernel call graph; - zero `while` or `repeat` terms in the five recursive kernel modules; @@ -17,8 +16,8 @@ The audit result is now: component that Lean could not accept structurally; - exact equations and fuel-boundary regressions for the totalization seams. -A finite bound is operational evidence, not a soundness proof. K1 and K2 -must still prove the semantic WF properties of the transparent algorithms. +Finite bounds establish termination. Soundness additionally requires proofs +that each operation preserves its semantic invariant. ## Shared runtime fuel @@ -111,12 +110,10 @@ context-suffix closure, and union-find path halving use finite container-size bounds. These replacements preserve the old traversal order where errors are observable; unit regressions pin the LIFO universe-validation order. -The operational behavior change is intentionally narrow: malformed or -adversarial inputs that could previously diverge in an unbounded loop now -return `.maxRecDepth` at the documented cap. Valid-corpus verdict and -headroom parity is the A5 closure gate. Rust and Aiur are deliberately -unchanged in K0; any corresponding hardening is a later transport obligation -after the Ix.Kernel theorem interface is stable. +Inputs that exhaust a bounded loop return `.maxRecDepth` at its documented +cap. Verdict and fuel-headroom regressions check the behavior on valid +corpora. Transporting these contracts to Rust and Aiur is a separate +verification obligation. ## Proof and regression surface @@ -152,29 +149,23 @@ rg -n 'TcM\.tick' \ The first two must return no matches; the last must return exactly the WHNF and DefEq charge sites described above. -## Boundary to K1/K2 +## Semantic proof obligations -K0 establishes total, equation-visible production functions and preserves -their tested operational behavior. It does **not** establish checker -soundness. `Methods.WF`, the conditional WHNF/Infer/DefEq WF theorems, and -the knot-closing induction `(methodsN n).WF` belong to K1/K2. In particular, -the method index closes Lean termination for tick-free cycles, but K1/K2 -must still prove that each field preserves `VerifyWorld`, run support, cache -coherence, and the declared native/inductive oracle boundaries. +Total production functions expose equations for the semantic proofs. +`Methods.WF`, the conditional WHNF/Infer/DefEq WF theorems, and the +knot-closing induction `(methodsN n).WF` require each field to preserve +`VerifyWorld`, run support, cache coherence, and the declared native/inductive +oracle boundaries. The method index establishes termination even for cycles +that consume no runtime fuel; semantic preservation is a further obligation. -## Closure validation +## Validation -The 2026-07-27 K0 closure run passed all of the following: +Build the implementation proofs and run the kernel regressions: -- exact four-statement sorry-frontier check; -- completed (295 roots) and statement (4 roots) trust audits; -- `lake build IxKernelVerify` and the default `lake build`; -- strict `tc-unit` with warnings treated as failures; -- pinned Init/Std stress constants and accelerated-versus-pure differential; -- Init-scale anon verdict parity; -- focused anon differential, full anon/meta roundtrip, and `tc-init` suites; -- Lean4Lean replay and tutorial suites. +```sh +lake build IxKernelVerify +lake test --wfail -- tc-unit +``` -No production source in the Rust kernel or Aiur IxVM was changed. Their -acceptance simulation/refinement work remains downstream of the Ix.Kernel -soundness theorem. +The [kernel verification guide](kernel-verification.md#trust-checks) describes +the exact trust audits and the complete local validation command. diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 1cd6c31b5..b6836b2fd 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -9,6 +9,10 @@ formalization repository. The certified receipt interface and a fragment of production `checkEnvAnon` have relative consistency theorems. Full checker consistency remains open. +The [recursion audit](kernel-recursion.md) explains the production call graph +and fuel bounds. The [context-digest guide](tc-context-digest-collision-boundary.md) +details the collision and suffix-transport assumptions for cache soundness. + ## Connection to the consistency model The named specification and the set model share `Ix.Theory.VLevel`. The @@ -104,16 +108,13 @@ declaration can inhabit it. No axiom-name restriction is needed. The audits traverse checked declaration types and bodies, including inductive constructors. They compare exact axiom sets and record direct origins of -`sorryAx`. Full traversal includes dependencies missed by cached imported -axiom summaries, including implementation assumptions and unfinished -metatheory. All 441 retained named-specification assertions use their original -full dependency graphs as the migration baseline. +`sorryAx`. Full traversal includes implementation assumptions and unfinished +metatheory. The named-specification audit checks 441 assertions against exact +dependency manifests. -The same traversal covers 2,034 kernel manifest roots. Thirteen entries omitted -logical or native dependencies through constructor fields; their corrected -boundaries were checked against freshly compiled pre-migration sources. Direct -dependency lookups are cached within a fixed environment, while each root's -reachable declarations, axioms, and proof-hole origins are computed separately. +The same traversal covers 2,034 kernel manifest roots. Direct dependency +lookups are cached within a fixed environment, while each root's reachable +declarations, axioms, and proof-hole origins are computed separately. `Ix.Kernel.Frontier.Pending` quarantines the remaining explicit metatheory axioms. Completed roots cannot depend on that namespace. Named-specification @@ -183,16 +184,11 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | | Concrete set-theory instance | [Separate model package](../Models/SetTheory/README.md) | -## Provenance and scope - -The kernel, theory, and certified host scaffolding comes from `jcb/monorepo` -at `7b06b754`. The checker namespace is `Ix.Kernel` (formerly `Ix.Tc`), and -verification dependencies are local to Ix. The external `lean4lean` dependency -and its benchmark/test targets have been removed. The new compiler development, -circuit changes, and certificate VM pilot are deferred. +## Source inventory The named development retains 104 source modules, including the inductive -fixtures used by the existing proofs. Original hashes and attribution are -recorded in `Ix/Theory/Named/NOTICE` and `Tests/Theory/NamedManifest.lean`; the -Apache license is preserved alongside the sources. The axiom-audit helper and -direct production-fragment proofs are authored in Ix. +fixtures used by the existing proofs. Source hashes and attribution are in +[`Ix/Theory/Named/NOTICE`](../Ix/Theory/Named/NOTICE) and +[`Tests/Theory/NamedManifest.lean`](../Tests/Theory/NamedManifest.lean); the +Apache license is preserved alongside the sources. The axiom-audit helper +and direct production-fragment proofs are authored in Ix. diff --git a/docs/tc-context-digest-collision-boundary.md b/docs/tc-context-digest-collision-boundary.md index 63e539edc..c847a5a9b 100644 --- a/docs/tc-context-digest-collision-boundary.md +++ b/docs/tc-context-digest-collision-boundary.md @@ -1,7 +1,7 @@ # Ix.Kernel context-digest collision boundary -Snapshot: 2026-07-31. This note records a proof boundary for the K1/K2 cache -soundness argument. +This note records the context-digest assumptions needed for sound reduction, +inference, and definitional-equality caches. ## Two distinct collision obligations @@ -103,20 +103,20 @@ establish a genuinely global specification. The `ContextDigestSpec.execution` premise includes memo hits and requires `ContextDigestSpec.StateValid` for the pre-state. This is load-bearing: a successful lookup in `ctxAddrCache` is not evidence that the -cached address is the digest of the current normalized suffix. Concrete K2 -must define that validity predicate from execution history or a strengthened -state invariant. The interface now requires both `memoValid` and `preserves`, +cached address is the digest of the current normalized suffix. Production +proofs must establish that validity predicate from execution history or a +strengthened state invariant. The interface requires both `memoValid` and `preserves`, so an implementation cannot label an initial state valid while leaving later memoized calls outside the proof domain. -Production now exposes the pure calculation as +Production exposes the pure calculation as `TcM.ctxAddrForLbrUncached`. The exact fast-path, cache-hit, and cache-miss equations prove immediate replay stability and preservation of -`TcM.ContextAddrMemoValid`. This closes the operational memo-mutation part of -K2; it does not yet prove that the pure hash input is the chosen semantic +`TcM.ContextAddrMemoValid`. These establish the operational memo-mutation +contract; they do not prove that the pure hash input is the chosen semantic normalization of the reconciled `KVLCtx`. -## Required K2 discharge +## Production proof obligations Instantiating the finite construction for production must: diff --git a/docs/theory.md b/docs/theory.md index 8c348f3aa..0537cf56f 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -60,8 +60,6 @@ The model's 20 con-leche foundation files derive from revision ported content hashes, and notices are retained and checked. Imported license and notice texts are under `Ix/Theory`; `PORTING.md` explains their scope. -On recompilation in the monorepo, two roots—`Modeled.CheckedCompanions.fixed_old` -and `Modeled.assignment_agrees`—acquire `Classical.choice` and `Quot.sound` in -addition to `propext`, all already permitted baseline axioms. The reviewed -report also accounts for namespace qualification and module ordering. All root -types, constant counts, and module sets otherwise match the source report. +The exact report records each root's checked type, axioms, and dependencies. +For example, `Modeled.CheckedCompanions.fixed_old` and +`Modeled.assignment_agrees` use `propext`, `Classical.choice`, and `Quot.sound`. From 9615301e3a9fa758bda28f875195d5ac5bc635de Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 10:11:42 -0400 Subject: [PATCH 05/30] Add typed Ixon inputs to certified checking commands --- Ix/Certified.lean | 3 +- Ix/Certified/CLI.lean | 167 +++++++++++ Ix/Certified/ClaimCommand.lean | 26 +- Ix/Certified/ClaimMain.lean | 2 +- Ix/Certified/Command.lean | 21 +- Ix/Certified/InputText.lean | 430 ++++++++++++++++++++++++++++ Ix/Certified/Main.lean | 2 +- Ix/Certified/ModelHints.lean | 2 +- Ix/Certified/RequestCodec.lean | 202 +++++++++++++ Ix/Certified/TextCodec.lean | 190 ++++++++++++ Tests/Certified/CLI.lean | 6 +- Tests/Certified/Check.lean | 2 + Tests/Certified/ImportManifest.lean | 10 +- Tests/Certified/Inputs.lean | 262 +++++++++++++++++ docs/certified-checking.md | 140 +++++++-- docs/kernel-verification.md | 7 +- lakefile.lean | 7 +- 17 files changed, 1395 insertions(+), 84 deletions(-) create mode 100644 Ix/Certified/CLI.lean create mode 100644 Ix/Certified/InputText.lean create mode 100644 Ix/Certified/RequestCodec.lean create mode 100644 Ix/Certified/TextCodec.lean create mode 100644 Tests/Certified/Inputs.lean diff --git a/Ix/Certified.lean b/Ix/Certified.lean index 05cb4f0ef..1108d6f0e 100644 --- a/Ix/Certified.lean +++ b/Ix/Certified.lean @@ -3,8 +3,7 @@ Copyright (c) 2026 Argument Computer Corporation. SPDX-License-Identifier: MIT OR Apache-2.0 -/ -import Ix.Certified.Command -import Ix.Certified.ClaimCommand +import Ix.Certified.CLI /-! Source and claim adapters for the explicit certified profile. Their validation receipts connect authenticated Ixon inputs to the set model. diff --git a/Ix/Certified/CLI.lean b/Ix/Certified/CLI.lean new file mode 100644 index 000000000..8bf8d3252 --- /dev/null +++ b/Ix/Certified/CLI.lean @@ -0,0 +1,167 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.InputText + +/-! File input for the certified commands. Binary Ixon is the default; +readable `.ixon` data uses the same Lean request and envelope types. JSON +requests remain an explicit compatibility format for the frozen CLI corpus. +All input formats reach the same certified acceptance functions. +-/ + +namespace Ix.Certified.CLI + +inductive Format where + | binary + | text + | json + deriving BEq, Repr + +structure Options where + requestFormat : Format := .binary + envelopeFormat : Format := .binary + positional : List String := [] + help : Bool := false + deriving Repr + +private def readFormat (envelope : Bool) : String → Except String Format + | "binary" => .ok .binary + | "text" => .ok .text + | "json" => if envelope then .error "envelope format must be binary or text" else .ok .json + | _ => .error (if envelope then "envelope format must be binary or text" + else "request format must be binary, text or json") + +def parseArgs (claim : Bool) (args : List String) : Except String Options := + go args {} false false +where + go : List String → Options → Bool → Bool → Except String Options + | [], options, _, _ => .ok options + | "--" :: rest, options, _, _ => .ok { options with positional := options.positional ++ rest } + | "--help" :: _, options, _, _ + | "-h" :: _, options, _, _ => .ok { options with help := true } + | "--request-format" :: value :: rest, options, requestSeen, envelopeSeen => do + if requestSeen then throw "duplicate --request-format" + let format ← readFormat false value + go rest { options with requestFormat := format } true envelopeSeen + | ["--request-format"], _, _, _ => .error "--request-format requires a value" + | "--envelope-format" :: value :: rest, options, requestSeen, envelopeSeen => do + unless claim do throw "--envelope-format is only available for certified-claim-check" + if envelopeSeen then throw "duplicate --envelope-format" + let format ← readFormat true value + go rest { options with envelopeFormat := format } requestSeen true + | ["--envelope-format"], _, _, _ => .error "--envelope-format requires a value" + | arg :: rest, options, requestSeen, envelopeSeen => do + if arg.startsWith "--request-format=" then + if requestSeen then throw "duplicate --request-format" + let format ← readFormat false (arg.dropPrefix "--request-format=" |>.toString) + go rest { options with requestFormat := format } true envelopeSeen + else if arg.startsWith "--envelope-format=" then + unless claim do throw "--envelope-format is only available for certified-claim-check" + if envelopeSeen then throw "duplicate --envelope-format" + let format ← readFormat true (arg.dropPrefix "--envelope-format=" |>.toString) + go rest { options with envelopeFormat := format } requestSeen true + else if arg.startsWith "-" then throw s!"unknown option: {arg}" + else go rest { options with positional := options.positional ++ [arg] } requestSeen envelopeSeen + +def sourceUsage : String := + "usage: certified-check [--request-format binary|text|json] proof|store SOURCE.ixe REQUEST\n" ++ + " binary (default): Ixon request bytes; text: a typed .ixon data definition\n" ++ + " json: legacy request compatibility" + +def claimUsage : String := + "usage: certified-claim-check [--request-format binary|text|json] " ++ + "[--envelope-format binary|text] SOURCE.ixe ENVELOPE REQUEST\n" ++ + " binary (default): Ixon bytes; text: a typed .ixon data definition\n" ++ + " request and envelope formats are independent; json is legacy request compatibility" + +def readSourceRequest (format : Format) (path : System.FilePath) : IO (Except String Command.Request) := do + match format with + | .binary => return Command.Request.ofIxon (← IO.FS.readBinFile path) + | .text => return Command.Request.ofText (← IO.FS.readFile path) + | .json => + let text ← IO.FS.readFile path + return Lean.Json.parse text >>= Command.readRequest + +def readClaimRequest (format : Format) (path : System.FilePath) : IO (Except String ClaimCommand.Request) := do + match format with + | .binary => return ClaimCommand.Request.ofIxon (← IO.FS.readBinFile path) + | .text => return ClaimCommand.Request.ofText (← IO.FS.readFile path) + | .json => + let text ← IO.FS.readFile path + return Lean.Json.parse text >>= ClaimCommand.readRequest + +/-- Binary input retains the original bytes for authentication. Text input +denotes an envelope whose canonical Ixon encoding is the authenticated object. -/ +def readEnvelope (format : Format) (path : System.FilePath) : IO (Except String ByteArray) := do + match format with + | .binary => return .ok (← IO.FS.readBinFile path) + | .text => return Envelope.toIxon <$> Envelope.ofText (← IO.FS.readFile path) + | .json => return .error "envelope format must be binary or text" + +end Ix.Certified.CLI + +namespace Ix.Certified.Command + +def main (args : List String) : IO UInt32 := do + let parsed := CLI.parseArgs false args + let .ok options := parsed | do + match parsed with + | .error error => IO.eprintln error + | .ok _ => pure () + IO.eprintln CLI.sourceUsage + return 2 + if options.help then IO.println CLI.sourceUsage; return 0 + let [mode, sourcePath, requestPath] := options.positional | do + IO.eprintln CLI.sourceUsage + return 2 + try + let bytes ← IO.FS.readBinFile sourcePath + let parsed ← CLI.readSourceRequest options.requestFormat requestPath + let result := do + let request ← parsed + let parts ← Ixon.deEnvVerifiedLazy bytes + run.{0} mode 6400 parts.env request + match result with + | .error error => IO.eprintln error; return 1 + | .ok () => + IO.println <| (Lean.Json.mkObj [("accepted", Lean.toJson true), ("mode", Lean.toJson mode)]).compress + return 0 + catch error => IO.eprintln error; return 1 + +end Ix.Certified.Command + +namespace Ix.Certified.ClaimCommand + +def main (args : List String) : IO UInt32 := do + let parsed := CLI.parseArgs true args + let .ok options := parsed | do + match parsed with + | .error error => IO.eprintln error + | .ok _ => pure () + IO.eprintln CLI.claimUsage + return 2 + if options.help then IO.println CLI.claimUsage; return 0 + let [sourcePath, envelopePath, requestPath] := options.positional | do + IO.eprintln CLI.claimUsage + return 2 + try + let sourceBytes ← IO.FS.readBinFile sourcePath + let envelope ← CLI.readEnvelope options.envelopeFormat envelopePath + let parsed ← CLI.readClaimRequest options.requestFormat requestPath + let result := do + let request ← parsed + let envelope ← envelope + let parts ← Ixon.deEnvVerifiedLazy sourceBytes + run.{0} 6400 parts.env envelope request + return request.address + match result with + | .error error => IO.eprintln error; return 1 + | .ok address => + IO.println <| (Lean.Json.mkObj [("accepted", Lean.toJson true), + ("address", Lean.toJson (hexOfBytes address.hash))]).compress + return 0 + catch error => IO.eprintln error; return 1 + +end Ix.Certified.ClaimCommand diff --git a/Ix/Certified/ClaimCommand.lean b/Ix/Certified/ClaimCommand.lean index 659c87de0..d62572974 100644 --- a/Ix/Certified/ClaimCommand.lean +++ b/Ix/Certified/ClaimCommand.lean @@ -6,9 +6,10 @@ SPDX-License-Identifier: MIT OR Apache-2.0 import Ix.Certified.ClaimSuggest import Ix.Kernel.CertifiedClaims -/-! Generic command for the versioned public claim protocol. Public bytes -and their expected address are inputs; JSON supplies only untrusted search -hints. Each successful command ends in the certified TcM claim checker. -/ +/-! Typed checking for the versioned public claim protocol. Public bytes and +their expected address are inputs; requests supply untrusted search hints. +The JSON reader supports legacy requests. Command-line input formats are in +`Ix.Certified.CLI`. Each successful run ends in the certified TcM claim checker. -/ namespace Ix.Certified.ClaimCommand @@ -95,23 +96,4 @@ theorem run_meaning {fuel : Nat} {source : Ixon.Env} {bytes : ByteArray} {reques obtain ⟨receipt, _, ha, hb, hm⟩ := Kernel.accepted_tc_claim_meaning hw exact ⟨receipt, ha, hb, hm⟩ -def main (args : List String) : IO UInt32 := do - let [sourcePath, envelopePath, requestPath] := args | do - IO.eprintln "usage: certified-claim-check SOURCE.ixe ENVELOPE.bin REQUEST.json" - return 2 - let sourceBytes ← IO.FS.readBinFile sourcePath - let envelope ← IO.FS.readBinFile envelopePath - let requestText ← IO.FS.readFile requestPath - let result := do - let request ← readRequest (← Lean.Json.parse requestText) - let parts ← Ixon.deEnvVerifiedLazy sourceBytes - run.{0} 6400 parts.env envelope request - return request.address - match result with - | .error error => IO.eprintln error; return 1 - | .ok address => - IO.println <| (Lean.Json.mkObj [("accepted", Lean.toJson true), - ("address", Lean.toJson (hexOfBytes address.hash))]).compress - return 0 - end Ix.Certified.ClaimCommand diff --git a/Ix/Certified/ClaimMain.lean b/Ix/Certified/ClaimMain.lean index 2028b1f52..feca20f5c 100644 --- a/Ix/Certified/ClaimMain.lean +++ b/Ix/Certified/ClaimMain.lean @@ -3,6 +3,6 @@ Copyright (c) 2026 Argument Computer Corporation. SPDX-License-Identifier: MIT OR Apache-2.0 -/ -import Ix.Certified.ClaimCommand +import Ix.Certified.CLI def main := Ix.Certified.ClaimCommand.main diff --git a/Ix/Certified/Command.lean b/Ix/Certified/Command.lean index 0ad2ba24c..177762ea0 100644 --- a/Ix/Certified/Command.lean +++ b/Ix/Certified/Command.lean @@ -6,10 +6,11 @@ SPDX-License-Identifier: MIT OR Apache-2.0 import Ix.Certified.Suggest import Ix.Kernel.Certified -/-! Generic source-file driver for the certified profile. The JSON request +/-! Typed source checking for the certified profile. The request selects the expected target/subjects, primitive signature and finite source closure. Witness search is untrusted and always followed by certified TcM -validation. There is no inference-only or unchecked fallback command. -/ +validation. The JSON reader supports legacy request files; the command-line +input formats are defined in `Ix.Certified.CLI`. -/ namespace Ix.Certified.Command @@ -77,20 +78,4 @@ theorem run_success {mode : String} {fuel : Nat} {source : Ixon.Env} {request : · simp [run, hs, hw, ha] at h · simp [run, hp, hs] at h -def main (args : List String) : IO UInt32 := do - let [mode, sourcePath, requestPath] := args | do - IO.eprintln "usage: certified-check proof|store SOURCE.ixe REQUEST.json" - return 2 - let bytes ← IO.FS.readBinFile sourcePath - let requestText ← IO.FS.readFile requestPath - let result := do - let request ← readRequest (← Lean.Json.parse requestText) - let parts ← Ixon.deEnvVerifiedLazy bytes - run.{0} mode 6400 parts.env request - match result with - | .error error => IO.eprintln error; return 1 - | .ok () => - IO.println <| (Lean.Json.mkObj [("accepted", Lean.toJson true), ("mode", Lean.toJson mode)]).compress - return 0 - end Ix.Certified.Command diff --git a/Ix/Certified/InputText.lean b/Ix/Certified/InputText.lean new file mode 100644 index 000000000..fe9bc165c --- /dev/null +++ b/Ix/Certified/InputText.lean @@ -0,0 +1,430 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.TextCodec + +/-! Readable Ixon data values for certified requests and envelopes. The codecs +cover all claim variants, model hints, and selective-revelation fields. Each +constructor is decoded to its existing Lean type before witness search. +-/ + +namespace Ix.Certified.Text + +instance : Codec Ix.DefKind where + type := ref "Ix.DefKind" + encode + | .defn => + ref "Ix.DefKind.defn" + | .opaq => + ref "Ix.DefKind.opaq" + | .thm => + ref "Ix.DefKind.thm" + decode term := do + let (name, args) ← constructor term + match name with + | "Ix.DefKind.defn" => do + arity name 0 args + return .defn + | "Ix.DefKind.opaq" => do + arity name 0 args + return .opaq + | "Ix.DefKind.thm" => do + arity name 0 args + return .thm + | _ => throw "expected a Ix.DefKind constructor" + +instance : Codec Ix.DefinitionSafety where + type := ref "Ix.DefinitionSafety" + encode + | .safe => + ref "Ix.DefinitionSafety.safe" + | .unsaf => + ref "Ix.DefinitionSafety.unsaf" + | .part => + ref "Ix.DefinitionSafety.part" + decode term := do + let (name, args) ← constructor term + match name with + | "Ix.DefinitionSafety.safe" => do + arity name 0 args + return .safe + | "Ix.DefinitionSafety.unsaf" => do + arity name 0 args + return .unsaf + | "Ix.DefinitionSafety.part" => do + arity name 0 args + return .part + | _ => throw "expected a Ix.DefinitionSafety constructor" + +instance : Codec Ix.QuotKind where + type := ref "Ix.QuotKind" + encode + | .type => + ref "Ix.QuotKind.type" + | .ctor => + ref "Ix.QuotKind.ctor" + | .lift => + ref "Ix.QuotKind.lift" + | .ind => + ref "Ix.QuotKind.ind" + decode term := do + let (name, args) ← constructor term + match name with + | "Ix.QuotKind.type" => do + arity name 0 args + return .type + | "Ix.QuotKind.ctor" => do + arity name 0 args + return .ctor + | "Ix.QuotKind.lift" => do + arity name 0 args + return .lift + | "Ix.QuotKind.ind" => do + arity name 0 args + return .ind + | _ => throw "expected a Ix.QuotKind constructor" + +instance : Codec Ix.RevealConstructorInfo where + type := ref "Ix.RevealConstructorInfo" + encode value := ctor "Ix.RevealConstructorInfo.mk" #[ + encode value.isUnsafe, encode value.lvls, encode value.cidx, encode value.params, + encode value.fields, encode value.typ] + decode term := do + let args ← arguments "Ix.RevealConstructorInfo.mk" 6 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!, ← decode args[3]!, + ← decode args[4]!, ← decode args[5]!⟩ + +instance : Codec Ix.RevealRecursorRule where + type := ref "Ix.RevealRecursorRule" + encode value := ctor "Ix.RevealRecursorRule.mk" #[ + encode value.ruleIdx, encode value.fields, encode value.rhs] + decode term := do + let args ← arguments "Ix.RevealRecursorRule.mk" 3 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!⟩ + +instance : Codec Ix.RevealMutConstInfo where + type := ref "Ix.RevealMutConstInfo" + encode + | .defn kind safety lvls typ value => + ctor "Ix.RevealMutConstInfo.defn" #[ + encode kind, encode safety, encode lvls, encode typ, encode value] + | .indc isUnsafe lvls params indices typ ctors => + ctor "Ix.RevealMutConstInfo.indc" #[ + encode isUnsafe, encode lvls, encode params, encode indices, encode typ, encode ctors] + | .recr k isUnsafe lvls params indices motives minors typ rules => + ctor "Ix.RevealMutConstInfo.recr" #[ + encode k, encode isUnsafe, encode lvls, encode params, encode indices, encode motives, + encode minors, encode typ, encode rules] + decode term := do + let (name, args) ← constructor term + match name with + | "Ix.RevealMutConstInfo.defn" => do + arity name 5 args + return .defn + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) (← decode args[3]!) (← decode args[4]!) + | "Ix.RevealMutConstInfo.indc" => do + arity name 6 args + return .indc + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) (← decode args[3]!) (← decode args[4]!) (← decode args[5]!) + | "Ix.RevealMutConstInfo.recr" => do + arity name 9 args + return .recr + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) (← decode args[3]!) (← decode args[4]!) (← decode args[5]!) (← decode args[6]!) (← decode args[7]!) (← decode args[8]!) + | _ => throw "expected a Ix.RevealMutConstInfo constructor" + +instance : Codec Ix.RevealConstantInfo where + type := ref "Ix.RevealConstantInfo" + encode + | .defn kind safety lvls typ value => + ctor "Ix.RevealConstantInfo.defn" #[ + encode kind, encode safety, encode lvls, encode typ, encode value] + | .recr k isUnsafe lvls params indices motives minors typ rules => + ctor "Ix.RevealConstantInfo.recr" #[ + encode k, encode isUnsafe, encode lvls, encode params, encode indices, encode motives, + encode minors, encode typ, encode rules] + | .axio isUnsafe lvls typ => + ctor "Ix.RevealConstantInfo.axio" #[ + encode isUnsafe, encode lvls, encode typ] + | .quot kind lvls typ => + ctor "Ix.RevealConstantInfo.quot" #[ + encode kind, encode lvls, encode typ] + | .cPrj idx cidx block => + ctor "Ix.RevealConstantInfo.cPrj" #[ + encode idx, encode cidx, encode block] + | .rPrj idx block => + ctor "Ix.RevealConstantInfo.rPrj" #[ + encode idx, encode block] + | .iPrj idx block => + ctor "Ix.RevealConstantInfo.iPrj" #[ + encode idx, encode block] + | .dPrj idx block => + ctor "Ix.RevealConstantInfo.dPrj" #[ + encode idx, encode block] + | .muts components => + ctor "Ix.RevealConstantInfo.muts" #[ + encode components] + decode term := do + let (name, args) ← constructor term + match name with + | "Ix.RevealConstantInfo.defn" => do + arity name 5 args + return .defn + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) (← decode args[3]!) (← decode args[4]!) + | "Ix.RevealConstantInfo.recr" => do + arity name 9 args + return .recr + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) (← decode args[3]!) (← decode args[4]!) (← decode args[5]!) (← decode args[6]!) (← decode args[7]!) (← decode args[8]!) + | "Ix.RevealConstantInfo.axio" => do + arity name 3 args + return .axio + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) + | "Ix.RevealConstantInfo.quot" => do + arity name 3 args + return .quot + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) + | "Ix.RevealConstantInfo.cPrj" => do + arity name 3 args + return .cPrj + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) + | "Ix.RevealConstantInfo.rPrj" => do + arity name 2 args + return .rPrj + (← decode args[0]!) (← decode args[1]!) + | "Ix.RevealConstantInfo.iPrj" => do + arity name 2 args + return .iPrj + (← decode args[0]!) (← decode args[1]!) + | "Ix.RevealConstantInfo.dPrj" => do + arity name 2 args + return .dPrj + (← decode args[0]!) (← decode args[1]!) + | "Ix.RevealConstantInfo.muts" => do + arity name 1 args + return .muts + (← decode args[0]!) + | _ => throw "expected a Ix.RevealConstantInfo constructor" + +instance : Codec Ix.Claim where + type := ref "Ix.Claim" + encode + | .eval input output assumptions => + ctor "Ix.Claim.eval" #[ + encode input, encode output, encode assumptions] + | .check const assumptions => + ctor "Ix.Claim.check" #[ + encode const, encode assumptions] + | .checkEnv root assumptions => + ctor "Ix.Claim.checkEnv" #[ + encode root, encode assumptions] + | .reveal comm info => + ctor "Ix.Claim.reveal" #[ + encode comm, encode info] + | .contains tree const => + ctor "Ix.Claim.contains" #[ + encode tree, encode const] + | .catalog members content assumptions => + ctor "Ix.Claim.catalog" #[ + encode members, encode content, encode assumptions] + decode term := do + let (name, args) ← constructor term + match name with + | "Ix.Claim.eval" => do + arity name 3 args + return .eval + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) + | "Ix.Claim.check" => do + arity name 2 args + return .check + (← decode args[0]!) (← decode args[1]!) + | "Ix.Claim.checkEnv" => do + arity name 2 args + return .checkEnv + (← decode args[0]!) (← decode args[1]!) + | "Ix.Claim.reveal" => do + arity name 2 args + return .reveal + (← decode args[0]!) (← decode args[1]!) + | "Ix.Claim.contains" => do + arity name 2 args + return .contains + (← decode args[0]!) (← decode args[1]!) + | "Ix.Claim.catalog" => do + arity name 3 args + return .catalog + (← decode args[0]!) (← decode args[1]!) (← decode args[2]!) + | _ => throw "expected a Ix.Claim constructor" + +instance : Codec Ix.Certified.Profile where + type := ref "Ix.Certified.Profile" + encode value := ctor "Ix.Certified.Profile.mk" #[ + encode value.falseType, encode value.falseElim, encode value.natType] + decode term := do + let args ← arguments "Ix.Certified.Profile.mk" 3 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!⟩ + +instance : Codec Ix.Certified.Protocol where + type := ref "Ix.Certified.Protocol" + encode value := ctor "Ix.Certified.Protocol.mk" #[ + encode value.format, encode value.codec, encode value.checker, encode value.policy, + encode value.aggregation] + decode term := do + let args ← arguments "Ix.Certified.Protocol.mk" 5 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!, ← decode args[3]!, + ← decode args[4]!⟩ + +instance : Codec Ix.Certified.Envelope where + type := ref "Ix.Certified.Envelope" + encode value := ctor "Ix.Certified.Envelope.mk" #[ + encode value.protocol, encode value.profile, encode value.claim, encode value.logicalAxioms] + decode term := do + let args ← arguments "Ix.Certified.Envelope.mk" 4 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!, ← decode args[3]!⟩ + +instance : Codec Ix.Certified.InputSelection where + type := ref "Ix.Certified.InputSelection" + encode value := ctor "Ix.Certified.InputSelection.mk" #[ + encode value.objects, encode value.naturals] + decode term := do + let args ← arguments "Ix.Certified.InputSelection.mk" 2 term + return ⟨ + ← decode args[0]!, ← decode args[1]!⟩ + +instance : Codec Ix.Certified.ModelProofHint where + type := ref "Ix.Certified.ModelProofHint" + encode value := ctor "Ix.Certified.ModelProofHint.mk" #[ + encode value.equality, encode value.reflexivity, encode value.eliminator, encode value.proof] + decode term := do + let args ← arguments "Ix.Certified.ModelProofHint.mk" 4 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!, ← decode args[3]!⟩ + +instance : Codec Ix.Certified.ModelRuleHints where + type := ref "Ix.Certified.ModelRuleHints" + encode value := ctor "Ix.Certified.ModelRuleHints.mk" #[ + encode value.owner, encode value.proofs] + decode term := do + let args ← arguments "Ix.Certified.ModelRuleHints.mk" 2 term + return ⟨ + ← decode args[0]!, ← decode args[1]!⟩ + +instance : Codec Ix.Certified.ModelHint where + type := ref "Ix.Certified.ModelHint" + encode value := ctor "Ix.Certified.ModelHint.mk" #[ + encode value.source, encode value.recursors, encode value.targets, encode value.proofs] + decode term := do + let args ← arguments "Ix.Certified.ModelHint.mk" 4 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!, ← decode args[3]!⟩ + +instance : Codec Ix.Certified.Command.Request where + type := ref "Ix.Certified.Command.Request" + encode value := ctor "Ix.Certified.Command.Request.mk" #[ + encode value.profile, encode value.target, encode value.subjects, encode value.selection, + encode value.models] + decode term := do + let args ← arguments "Ix.Certified.Command.Request.mk" 5 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!, ← decode args[3]!, + ← decode args[4]!⟩ + +instance : Codec Ix.Certified.LeafHint where + type := ref "Ix.Certified.LeafHint" + encode value := ctor "Ix.Certified.LeafHint.mk" #[ + encode value.claim, encode value.subjects, encode value.frontierTree] + decode term := do + let args ← arguments "Ix.Certified.LeafHint.mk" 3 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!⟩ + +instance : Codec Ix.Certified.LogicalHint where + type := ref "Ix.Certified.LogicalHint" + encode value := ctor "Ix.Certified.LogicalHint.mk" #[ + encode value.selection, encode value.leaves, encode value.subjects, encode value.members, + encode value.frontierTree, encode value.axiomTree, encode value.models] + decode term := do + let args ← arguments "Ix.Certified.LogicalHint.mk" 7 term + return ⟨ + ← decode args[0]!, ← decode args[1]!, ← decode args[2]!, ← decode args[3]!, + ← decode args[4]!, ← decode args[5]!, ← decode args[6]!⟩ + +instance : Codec Ixon.Comm where + type := ref "Ixon.Comm" + encode value := ctor "Ixon.Comm.mk" #[ + encode value.secret, encode value.payload] + decode term := do + let args ← arguments "Ixon.Comm.mk" 2 term + return ⟨ + ← decode args[0]!, ← decode args[1]!⟩ + +instance : Codec Ix.Certified.RevealWitness where + type := ref "Ix.Certified.RevealWitness" + encode value := ctor "Ix.Certified.RevealWitness.mk" #[ + encode value.opening] + decode term := do + let args ← arguments "Ix.Certified.RevealWitness.mk" 1 term + return ⟨ + ← decode args[0]!⟩ + +instance : Codec Ix.Certified.ClaimCommand.Hint where + type := ref "Ix.Certified.ClaimCommand.Hint" + encode + | .logical hint => + ctor "Ix.Certified.ClaimCommand.Hint.logical" #[ + encode hint] + | .contains tree => + ctor "Ix.Certified.ClaimCommand.Hint.contains" #[ + encode tree] + | .reveal witness => + ctor "Ix.Certified.ClaimCommand.Hint.reveal" #[ + encode witness] + decode term := do + let (name, args) ← constructor term + match name with + | "Ix.Certified.ClaimCommand.Hint.logical" => do + arity name 1 args + return .logical + (← decode args[0]!) + | "Ix.Certified.ClaimCommand.Hint.contains" => do + arity name 1 args + return .contains + (← decode args[0]!) + | "Ix.Certified.ClaimCommand.Hint.reveal" => do + arity name 1 args + return .reveal + (← decode args[0]!) + | _ => throw "expected a Ix.Certified.ClaimCommand.Hint constructor" + +instance : Codec Ix.Certified.ClaimCommand.Request where + type := ref "Ix.Certified.ClaimCommand.Request" + encode value := ctor "Ix.Certified.ClaimCommand.Request.mk" #[ + encode value.address, encode value.hint] + decode term := do + let args ← arguments "Ix.Certified.ClaimCommand.Request.mk" 2 term + return ⟨ + ← decode args[0]!, ← decode args[1]!⟩ + +end Ix.Certified.Text + +namespace Ix.Certified + +def Command.Request.toText (request : Command.Request) : String := Text.write "request" request + +def Command.Request.ofText (text : String) : Except String Command.Request := Text.read text + +def ClaimCommand.Request.toText (request : ClaimCommand.Request) : String := Text.write "request" request + +def ClaimCommand.Request.ofText (text : String) : Except String ClaimCommand.Request := Text.read text + +def Envelope.toText (envelope : Envelope) : String := Text.write "envelope" envelope + +def Envelope.ofText (text : String) : Except String Envelope := Text.read text + +end Ix.Certified + diff --git a/Ix/Certified/Main.lean b/Ix/Certified/Main.lean index 0570b7cec..3c14b8ca4 100644 --- a/Ix/Certified/Main.lean +++ b/Ix/Certified/Main.lean @@ -3,6 +3,6 @@ Copyright (c) 2026 Argument Computer Corporation. SPDX-License-Identifier: MIT OR Apache-2.0 -/ -import Ix.Certified.Command +import Ix.Certified.CLI def main := Ix.Certified.Command.main diff --git a/Ix/Certified/ModelHints.lean b/Ix/Certified/ModelHints.lean index 4d65dec82..14f5d8c66 100644 --- a/Ix/Certified/ModelHints.lean +++ b/Ix/Certified/ModelHints.lean @@ -7,7 +7,7 @@ import Ix.Certified.Bytes import Ix.Theory.Certificate.Modeled /-! Optional untrusted model-package hints refer to actual stored objects. -No mathematical declaration is imported from JSON: model definitions and +No mathematical declaration is supplied by a hint: model definitions and equation proofs come from the selected authenticated source store and are admitted before the original block by the ordinary certified checker. -/ diff --git a/Ix/Certified/RequestCodec.lean b/Ix/Certified/RequestCodec.lean new file mode 100644 index 000000000..98f6888aa --- /dev/null +++ b/Ix/Certified/RequestCodec.lean @@ -0,0 +1,202 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.Command +import Ix.Certified.ClaimCommand + +/-! Ixon serialization for the typed certified requests. Request frames carry +their own version and distinguish source requests from claim requests. Public +envelopes keep their existing Ixon representation and content addresses. +The public decoders consume the complete input and require canonical bytes. +-/ + +namespace Ix.Certified + +namespace RequestCodec + +open Ixon + +def magic : ByteArray := "IX-CERTIFIED-REQUEST".toUTF8 ++ ⟨#[0]⟩ + +/-- Bound transport decoding before allocating collections or parsing claims. -/ +def maxBytes : Nat := 1 <<< 20 + +def putHeader (kind : UInt8) : PutM Unit := do + putBytes magic + putTag0 ⟨1⟩ + putU8 kind + +def getHeader (kind : UInt8) : GetM Unit := do + if (← getBytes magic.size) != magic then throw "invalid certified request magic" + if (← getTag0).size != 1 then throw "unsupported certified request version" + if (← getU8) != kind then throw "incorrect certified request kind" + +def putList (putValue : α → PutM Unit) (values : List α) : PutM Unit := do + putTag0 ⟨values.length.toUInt64⟩ + values.forM putValue + +/-- Every item used by this codec consumes at least one byte. Check the count +against the remaining input before allocating the collection. -/ +def getList (getValue : GetM α) : GetM (List α) := do + let count := (← getTag0).size.toNat + let state ← get + if count > state.bytes.size - state.idx then throw "certified request list exceeds remaining input" + let mut values := [] + for _ in [:count] do values := (← getValue) :: values + return values.reverse + +def putOption (putValue : α → PutM Unit) : Option α → PutM Unit + | none => putU8 0 + | some value => do putU8 1; putValue value + +def getOption (getValue : GetM α) : GetM (Option α) := do + match ← getU8 with + | 0 => return none + | 1 => return some (← getValue) + | _ => throw "invalid certified request option tag" + +def putBlob (bytes : ByteArray) : PutM Unit := do + putTag0 ⟨bytes.size.toUInt64⟩ + putBytes bytes + +def getBlob : GetM ByteArray := do + getBytes (← getTag0).size.toNat + +def putProfile (profile : Profile) : PutM Unit := do + Serialize.put profile.falseType + Serialize.put profile.falseElim + putOption Serialize.put profile.natType + +def getProfile : GetM Profile := + return ⟨← Serialize.get, ← Serialize.get, ← getOption Serialize.get⟩ + +def putSelection (selection : InputSelection) : PutM Unit := do + putList Serialize.put selection.objects + putList Serialize.put selection.naturals + +def getSelection : GetM InputSelection := + return ⟨← getList Serialize.get, ← getList Serialize.get⟩ + +def putModelProof (hint : ModelProofHint) : PutM Unit := do + Serialize.put hint.equality + Serialize.put hint.reflexivity + Serialize.put hint.eliminator + Serialize.put hint.proof + +def getModelProof : GetM ModelProofHint := + return ⟨← Serialize.get, ← Serialize.get, ← Serialize.get, ← Serialize.get⟩ + +def putModelRules (hint : ModelRuleHints) : PutM Unit := do + Serialize.put hint.owner + putList (putOption putModelProof) hint.proofs + +def getModelRules : GetM ModelRuleHints := + return ⟨← Serialize.get, ← getList (getOption getModelProof)⟩ + +def putModel (hint : ModelHint) : PutM Unit := do + Serialize.put hint.source + putList Serialize.put hint.recursors + putList Serialize.put hint.targets + putList putModelRules hint.proofs + +def getModel : GetM ModelHint := + return ⟨← Serialize.get, ← getList Serialize.get, ← getList Serialize.get, + ← getList getModelRules⟩ + +def putSourceRequest (request : Command.Request) : PutM Unit := do + putHeader 0 + putProfile request.profile + Serialize.put request.target + putList Serialize.put request.subjects + putSelection request.selection + putList putModel request.models + +def getSourceRequest : GetM Command.Request := do + getHeader 0 + return ⟨← getProfile, ← Serialize.get, ← getList Serialize.get, + ← getSelection, ← getList getModel⟩ + +def putLeaf (hint : LeafHint) : PutM Unit := do + Ix.Claim.put hint.claim + putOption putBlob hint.subjects + putOption putBlob hint.frontierTree + +def getLeaf : GetM LeafHint := + return ⟨← Ix.Claim.get, ← getOption getBlob, ← getOption getBlob⟩ + +def putLogical (hint : LogicalHint) : PutM Unit := do + putSelection hint.selection + putList putLeaf hint.leaves + putOption putBlob hint.subjects + putOption putBlob hint.members + putOption putBlob hint.frontierTree + putOption putBlob hint.axiomTree + putList putModel hint.models + +def getLogical : GetM LogicalHint := + return ⟨← getSelection, ← getList getLeaf, ← getOption getBlob, + ← getOption getBlob, ← getOption getBlob, ← getOption getBlob, + ← getList getModel⟩ + +def putHint : ClaimCommand.Hint → PutM Unit + | .logical hint => do putU8 0; putLogical hint + | .contains tree => do putU8 1; putBlob tree + | .reveal witness => do + putU8 2 + Serialize.put witness.opening.secret + Serialize.put witness.opening.payload + +def getHint : GetM ClaimCommand.Hint := do + match ← getU8 with + | 0 => return .logical (← getLogical) + | 1 => return .contains (← getBlob) + | 2 => return .reveal ⟨⟨← Serialize.get, ← Serialize.get⟩⟩ + | _ => throw "invalid certified claim hint tag" + +def putClaimRequest (request : ClaimCommand.Request) : PutM Unit := do + putHeader 1 + Serialize.put request.address + putHint request.hint + +def getClaimRequest : GetM ClaimCommand.Request := do + getHeader 1 + return ⟨← Serialize.get, ← getHint⟩ + +def decode (getValue : GetM α) (putValue : α → PutM Unit) (bytes : ByteArray) : Except String α := do + if bytes.size > maxBytes then throw "certified input exceeds the 1 MiB transport limit" + let value ← runGetExact getValue bytes + if runPut (putValue value) != bytes then throw "noncanonical certified input bytes" + return value + +end RequestCodec + +instance : Ixon.Serialize Command.Request where + put := RequestCodec.putSourceRequest + get := RequestCodec.getSourceRequest + +instance : Ixon.Serialize ClaimCommand.Request where + put := RequestCodec.putClaimRequest + get := RequestCodec.getClaimRequest + +instance : Ixon.Serialize Envelope where + put := putEnvelope + get := getEnvelope + +def Command.Request.toIxon (request : Command.Request) : ByteArray := Ixon.ser request + +def Command.Request.ofIxon (bytes : ByteArray) : Except String Command.Request := + RequestCodec.decode RequestCodec.getSourceRequest RequestCodec.putSourceRequest bytes + +def ClaimCommand.Request.toIxon (request : ClaimCommand.Request) : ByteArray := Ixon.ser request + +def ClaimCommand.Request.ofIxon (bytes : ByteArray) : Except String ClaimCommand.Request := + RequestCodec.decode RequestCodec.getClaimRequest RequestCodec.putClaimRequest bytes + +def Envelope.toIxon (envelope : Envelope) : ByteArray := envelopeBytes envelope + +def Envelope.ofIxon (bytes : ByteArray) : Except String Envelope := + RequestCodec.decode getEnvelope putEnvelope bytes + +end Ix.Certified diff --git a/Ix/Certified/TextCodec.lean b/Ix/Certified/TextCodec.lean new file mode 100644 index 000000000..5e024391b --- /dev/null +++ b/Ix/Certified/TextCodec.lean @@ -0,0 +1,190 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.RequestCodec +import Ix.IxonSyntax + +/-! Data codecs using the existing Ixon constructor-expression syntax. +Readers recognize concrete constructors and literal helpers. They do not +evaluate user code, resolve imports, or run Lean elaboration. +-/ + +namespace Ix.Certified.Text + +open Ixon.Syntax + +/-- A convenient literal helper for Lean authors. Text input checks the same +hexadecimal form and rejects invalid addresses before constructing a value. -/ +def address! (hex : String) : Address := (Address.fromString hex).get! + +/-- A byte-string literal for Lean authors and Ixon constructor expressions. -/ +def bytes! (hex : String) : ByteArray := (bytesOfHex hex).get! + +def ref (name : String) : Term := + .ref { name := some { parts := (name.splitOn ".").toArray.map NameComponent.str } } + +def ctor (name : String) (args : Array Term := #[]) : Term := + if args.isEmpty then ref name else .app (ref name) args {} + +class Codec (α : Type) where + type : Term + encode : α → Term + decode : Term → Except String α + +def typeOf (α : Type) [Codec α] : Term := Codec.type (α := α) +def encode [Codec α] (value : α) : Term := Codec.encode value +def decode [Codec α] (term : Term) : Except String α := Codec.decode term + +def expectType [Codec α] (term : Term) : Except String Unit := do + if printTerm term != printTerm (typeOf α) then + throw s!"expected Ixon type {printTerm (typeOf α)}" + +/-- Parenthesized application spines have the same constructor arguments. -/ +def spine : Term → Term × Array Term + | .app head args _ => + let (head, previous) := spine head + (head, previous ++ args) + | term => (term, #[]) + +def constructor (term : Term) : Except String (String × Array Term) := do + let (head, args) := spine term + let .ref reference := head | throw "expected an Ixon data constructor" + let some name := reference.name | throw "expected a named Ixon data constructor" + if reference.hash.isSome || reference.levels.isSome then + throw "data constructors must use unpinned names with default universe levels" + let parts ← name.parts.toList.mapM fun + | .str value => pure value + | .num _ => throw "invalid data constructor name" + return (String.intercalate "." parts, args) + +def arguments (name : String) (count : Nat) (term : Term) : Except String (Array Term) := do + let (actual, args) ← constructor term + if actual != name || args.size != count then + throw s!"expected {name} with {count} arguments" + return args + +def arity (name : String) (count : Nat) (args : Array Term) : Except String Unit := do + if args.size != count then throw s!"expected {count} arguments to {name}" + +instance : Codec Address where + type := ref "Address" + encode value := ctor "Ix.Certified.Text.address!" #[.strLit (hexOfBytes value.hash) {}] + decode term := do + let args ← arguments "Ix.Certified.Text.address!" 1 term + let .strLit hex _ := args[0]! | throw "expected a hexadecimal address string" + match Address.fromString hex with + | some value => return value + | none => throw "expected a 32-byte hexadecimal address" + +instance : Codec ByteArray where + type := ref "ByteArray" + encode value := ctor "Ix.Certified.Text.bytes!" #[.strLit (hexOfBytes value) {}] + decode term := do + let args ← arguments "Ix.Certified.Text.bytes!" 1 term + let .strLit hex _ := args[0]! | throw "expected a hexadecimal byte string" + match bytesOfHex hex with + | some value => return value + | none => throw "expected an even-length hexadecimal byte string" + +instance : Codec Bool where + type := ref "Bool" + encode value := ref (if value then "Bool.true" else "Bool.false") + decode term := do + let (name, args) ← constructor term + arity name 0 args + match name with + | "Bool.true" => return true + | "Bool.false" => return false + | _ => throw "expected Bool.true or Bool.false" + +instance : Codec UInt64 where + type := ref "UInt64" + encode value := ctor "UInt64.ofNat" #[.natLit value.toNat {}] + decode term := do + let args ← arguments "UInt64.ofNat" 1 term + let .natLit value _ := args[0]! | throw "expected an unsigned integer literal" + if value >= 2 ^ 64 then throw "unsigned integer exceeds UInt64" + return value.toUInt64 + +instance [Codec α] : Codec (Option α) where + type := ctor "Option" #[typeOf α] + encode + | none => ctor "Option.none" #[typeOf α] + | some value => ctor "Option.some" #[typeOf α, encode value] + decode term := do + let (name, args) ← constructor term + if name == "Option.none" then + arity name 1 args + expectType (α := α) args[0]! + return none + else if name == "Option.some" then + arity name 2 args + expectType (α := α) args[0]! + return some (← decode args[1]!) + else throw "expected Option.none or Option.some" + +def encodeList [Codec α] : List α → Term + | [] => ctor "List.nil" #[typeOf α] + | value :: rest => ctor "List.cons" #[typeOf α, encode value, encodeList rest] + +def decodeList [Codec α] : Nat → Term → Except String (List α) + | 0, _ => .error "Ixon data list exceeds the nesting limit" + | fuel + 1, term => do + let (name, args) ← constructor term + if name == "List.nil" then + arity name 1 args + expectType (α := α) args[0]! + return [] + else if name == "List.cons" then + arity name 3 args + expectType (α := α) args[0]! + return (← decode args[1]!) :: (← decodeList fuel args[2]!) + else throw "expected List.nil or List.cons" + +instance [Codec α] : Codec (List α) where + type := ctor "List" #[typeOf α] + encode := encodeList + decode := decodeList 1024 + +instance [Codec α] : Codec (Array α) where + type := ctor "Array" #[typeOf α] + encode values := ctor "List.toArray" #[typeOf α, encode values.toList] + decode term := do + let args ← arguments "List.toArray" 2 term + expectType (α := α) args[0]! + return (← decode (α := List α) args[1]!).toArray + +instance [Codec α] [Codec β] : Codec (α × β) where + type := ctor "Prod" #[typeOf α, typeOf β] + encode value := ctor "Prod.mk" #[typeOf α, typeOf β, encode value.1, encode value.2] + decode term := do + let args ← arguments "Prod.mk" 4 term + expectType (α := α) args[0]! + expectType (α := β) args[1]! + return (← decode args[2]!, ← decode args[3]!) + +/-- Print a single typed definition in the standard `.ixon` file grammar. -/ +def write [Codec α] (name : String) (value : α) : String := + printFile { version := VERSION, decls := #[.defn { + kw := .defn, name := some { parts := #[.str name] }, + ty := typeOf α, value := encode value }] } + +/-- A data file contains one safe monomorphic definition or one annotated main +expression. Its type annotation and every constructor are checked explicitly. -/ +def read [Codec α] (text : String) : Except String α := do + let file ← (parseFile text).mapError toString + unless file.imports.isEmpty do throw "Ixon data files cannot import code" + let (type, value) ← match file.decls.toList, file.main with + | [], some main => pure (main.ty, main.value) + | [.defn declaration], none => do + unless declaration.kw == .defn && !declaration.mods.isUnsafe && + !declaration.mods.isPartial && declaration.uparams.isEmpty do + throw "expected a safe monomorphic data definition" + pure (declaration.ty, declaration.value) + | _, _ => throw "expected exactly one typed Ixon data value" + expectType (α := α) type + decode value + +end Ix.Certified.Text diff --git a/Tests/Certified/CLI.lean b/Tests/Certified/CLI.lean index b96ed8668..34fbd3b74 100644 --- a/Tests/Certified/CLI.lean +++ b/Tests/Certified/CLI.lean @@ -6,7 +6,8 @@ SPDX-License-Identifier: MIT OR Apache-2.0 import Lean /-! Native command regressions ported from the frozen source and claim CLI drivers. -JSON is retained for the existing command protocol and differential evidence. -/ +JSON compatibility is selected explicitly to preserve the frozen protocol +and differential evidence. Binary and text inputs have separate regressions. -/ open Lean System @@ -51,7 +52,8 @@ private def check (executable : String) (directory : FilePath) (source : ByteArr IO.FS.writeBinFile envelopePath envelope pure (#[sourcePath.toString, envelopePath.toString, requestPath.toString], Json.mkObj [("accepted", .bool true), ("address", field request "address")]) - let result ← IO.Process.output { cmd := "timeout", args := #["60", executable] ++ args } + let result ← IO.Process.output { + cmd := "timeout", args := #["60", executable, "--request-format", "json"] ++ args } IO.FS.writeFile (directory / "stdout.txt") result.stdout IO.FS.writeFile (directory / "stderr.txt") result.stderr unless result.exitCode == 0 || result.exitCode == 1 do diff --git a/Tests/Certified/Check.lean b/Tests/Certified/Check.lean index 25ac2055e..b601b0b6e 100644 --- a/Tests/Certified/Check.lean +++ b/Tests/Certified/Check.lean @@ -129,6 +129,8 @@ def main (args : List String) : IO UInt32 := do IO.FS.createDirAll output runNative frozen output runCLI frozen output + let formats ← run ".lake/build/bin/certified-input-tests" #[frozen.toString, (output / "formats").toString] + IO.print formats.stdout IO.println "Certified adapter checks passed." return 0 | ["--compare", frozen, actual] => diff --git a/Tests/Certified/ImportManifest.lean b/Tests/Certified/ImportManifest.lean index 64ebc47de..8e989babb 100644 --- a/Tests/Certified/ImportManifest.lean +++ b/Tests/Certified/ImportManifest.lean @@ -29,19 +29,19 @@ def selected : Array SourceFile := #[ ⟨"Ix/Certified/ClaimAccept.lean", some "Ix/Certified/ClaimAccept.lean", "0c179bd4ea2c1a9d8a3b239ffe2feb60b88038f8f9f09c5d9fd8e1e83011f981", "198d8b9b436b937c311bf7ae7e47d4523bdc80022447e42dcc03a131fb01ef38"⟩, ⟨"Ix/Certified/ClaimAudit.lean", some "Ix/Certified/ClaimAudit.lean", "8916803f12bb53e22fa1c94318a6b2a736ec9634ffae811f710b579d3d278bf4", "363f6524397b56c2225d2bdc5cadee29522959d043cfa8a5ace854078a5c30bb"⟩, ⟨"Ix/Certified/ClaimCheck.lean", some "Ix/Certified/ClaimCheck.lean", "e4d598badcb189897a339e187b9529658e2ef75445645e1463704cc6b349a196", "8f8f6c94581ed08c8b8b00d3157bd351e7aed29cd8aa53e491cb53dc48e8845f"⟩, - ⟨"Ix/Certified/ClaimCommand.lean", some "Ix/Certified/ClaimCommand.lean", "8f360b0d0a586ab15e3b8bb3a375f5dc56ad6157344295a67673d876bf8650eb", "e053cb7bab6e1ca19e36de92bcb44c60be9764fc30ab160b92224f4703a4fb4d"⟩, + ⟨"Ix/Certified/ClaimCommand.lean", some "Ix/Certified/ClaimCommand.lean", "8f360b0d0a586ab15e3b8bb3a375f5dc56ad6157344295a67673d876bf8650eb", "0c409330af91cbb31169fd6636f4e2f8146efd035fa470cb87f80b6d43d5e844"⟩, ⟨"Ix/Certified/ClaimInput.lean", some "Ix/Certified/ClaimInput.lean", "d2d0df3ef446690600e843c84683a8f2056e1d8a843a523fc57b550763963f32", "861b0cfd3a1dac9c683dbd1b71088065a00d9a47be9ddbdce304722271027451"⟩, - ⟨"Ix/Certified/ClaimMain.lean", some "Ix/Certified/ClaimMain.lean", "ed1f1b0edaec4e0928d90a814f35673a8989e55037c9cc023a6e0e287c7574e7", "ed1f1b0edaec4e0928d90a814f35673a8989e55037c9cc023a6e0e287c7574e7"⟩, + ⟨"Ix/Certified/ClaimMain.lean", some "Ix/Certified/ClaimMain.lean", "ed1f1b0edaec4e0928d90a814f35673a8989e55037c9cc023a6e0e287c7574e7", "b4c32e74a11fc97d74c484e561ee9093492b0a7e754fa5c13f50a490d16e73ee"⟩, ⟨"Ix/Certified/ClaimMeaning.lean", some "Ix/Certified/ClaimMeaning.lean", "78edb69d209768d8010b28b16d334fd2fa8bc6225490f9b2bbe5fd66cc906f36", "5f2550f0235fe84927d654a360a4298f426e7ca2e7911245c84f91dbd11eef6f"⟩, ⟨"Ix/Certified/ClaimSuggest.lean", some "Ix/Certified/ClaimSuggest.lean", "5f83e6b65542661c4efacd6389c5c6ca0a0eeaffb2d0d24cb58168be514a10f6", "285ed4b14540aa47afa67e28f20bc44e7fdce93fd94d0742971711f15df8336b"⟩, - ⟨"Ix/Certified/Command.lean", some "Ix/Certified/Command.lean", "f9f8a32be2761dc97bf7215585cde40b0e310153482707a570f7c1a106252abe", "c6803f699ed2edd6508e2db73b55f4abb163f6425bcf6b755da11b885991ad17"⟩, + ⟨"Ix/Certified/Command.lean", some "Ix/Certified/Command.lean", "f9f8a32be2761dc97bf7215585cde40b0e310153482707a570f7c1a106252abe", "b44c0fd7a770e1e6d41cadc880db15f9f0b6dd20a180e7ba11bdbc52bc3f03f0"⟩, ⟨"Ix/Certified/Corpus.lean", some "Ix/Certified/Corpus.lean", "fc1d66c81430461bed9e0045e6a26a1e01c85de90854eccea2343f24fe5dde97", "fc1d66c81430461bed9e0045e6a26a1e01c85de90854eccea2343f24fe5dde97"⟩, ⟨"Ix/Certified/Envelope.lean", some "Ix/Certified/Envelope.lean", "da0269803ff6f48c6d0347627d57a7f7699c0ea06e54f959406e3d8570a326f1", "da0269803ff6f48c6d0347627d57a7f7699c0ea06e54f959406e3d8570a326f1"⟩, ⟨"Ix/Certified/Fixtures.lean", some "Ix/Certified/Fixtures.lean", "fe7a503a0e436a2ecf924b48d9b66ed3f6ef901c7bcbe6098853c62c7748675a", "f85f883f498cdee55ab674876dd1fb19bae5dbe8aa729118cffd29ab626c8b25"⟩, ⟨"Ix/Certified/Ingress.lean", some "Ix/Certified/Ingress.lean", "1fe00c0a512ae94fddd2847196f1bafa415ff2c452412f0e69e9e060883dd0cf", "afd9e82827fed62d453c3979fbfdb1238f83573f19af3b6728574f97ff1a86a4"⟩, ⟨"Ix/Certified/Ixon.lean", some "Ix/Certified/Ixon.lean", "9b7f0d64f08c03ed3a215ff5b23e136bd85c71f953e9198fb940b597d7b54410", "5e37eaa6b5cb872edad7954cde413706f30996950c71d21417174f8166377bcb"⟩, - ⟨"Ix/Certified/Main.lean", some "Ix/Certified/Main.lean", "c571357f5e1120efbe23c7db4906fc3eeaebffccf2956e1899212494800d38a5", "c571357f5e1120efbe23c7db4906fc3eeaebffccf2956e1899212494800d38a5"⟩, - ⟨"Ix/Certified/ModelHints.lean", some "Ix/Certified/ModelHints.lean", "74fd6763d56ac5c8aa9af4507172879739c2dc681969a3f342aadbc30ab27837", "de098f48fc03893643c8de08c3bf2bed315f91767c71e9e229816784abb8f124"⟩, + ⟨"Ix/Certified/Main.lean", some "Ix/Certified/Main.lean", "c571357f5e1120efbe23c7db4906fc3eeaebffccf2956e1899212494800d38a5", "34a3e5137991cce17b3c36fc40451fc02450b9aa9da2a4368e38c2770c3e5a18"⟩, + ⟨"Ix/Certified/ModelHints.lean", some "Ix/Certified/ModelHints.lean", "74fd6763d56ac5c8aa9af4507172879739c2dc681969a3f342aadbc30ab27837", "de8128c9496e82468403d4954999a5c2fc607114028dc307ec705d0b0e8519b7"⟩, ⟨"Ix/Certified/ModeledAudit.lean", some "Ix/Certified/ModeledAudit.lean", "55101ebfee84fd89e4c99f08d88aac7edb7000302ef6d022a8c639e331fb3ec2", "c37969f6a69e11d62547bc91b685695cd08f002c115db70a05069f34fe111de1"⟩, ⟨"Ix/Certified/Native.lean", none, "7b617483cbeef932b9caaf6ca3e118be93e5621aaf1ca6bb8132821b336b1c82", ""⟩, ⟨"Ix/Certified/Packet.lean", none, "a694ff77c95d6fe3bd31b99e28597769604b901926d4e0a3dfea7802fb57711d", ""⟩, diff --git a/Tests/Certified/Inputs.lean b/Tests/Certified/Inputs.lean new file mode 100644 index 000000000..bad648641 --- /dev/null +++ b/Tests/Certified/Inputs.lean @@ -0,0 +1,262 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Certified.CLI +import Tests.Certified.ImportManifest + +/-! Binary/text roundtrips over the frozen source, claim, and modeled corpora, +plus process regressions for format selection and malformed transport inputs. +Equality compares all typed fields, independently of their encoded bytes. +-/ + +open Ix.Certified System Lean + +deriving instance BEq for Profile, Protocol, InputSelection, ModelProofHint, + ModelRuleHints, ModelHint, Command.Request, LeafHint, LogicalHint, + RevealWitness, ClaimCommand.Hint, ClaimCommand.Request, Envelope + +namespace Tests.Certified.Inputs + +private def need (condition : Bool) (message : String) : IO Unit := + unless condition do throw (IO.userError message) + +private def readJson (path : FilePath) : IO Json := do + IO.ofExcept (Json.parse (← IO.FS.readFile path)) + +private def sourceRequest (directory : FilePath) : IO Command.Request := do + IO.ofExcept (Command.readRequest (← readJson (directory / "request.json"))) + +private def claimRequest (directory : FilePath) : IO ClaimCommand.Request := do + IO.ofExcept (ClaimCommand.readRequest (← readJson (directory / "request.json"))) + +private def directories (path : FilePath) : IO (Array FilePath) := do + let mut result := #[] + for entry in ← path.readDir do + if ← entry.path.isDir then result := result.push entry.path + return result.qsort (fun a b => a.toString < b.toString) + +private def roundtrip [BEq α] (label : String) (expected : α) (actual : Except String α) : IO Unit := do + let value ← IO.ofExcept (actual.mapError (fun error => s!"{label}: {error}")) + need (value == expected) s!"{label}: decoded fields differ" + +private def rejected (label : String) (actual : Except String α) : IO Unit := + need (!actual.isOk) s!"{label}: malformed input accepted" + +private def sourceRoundtrip (directory : FilePath) : IO Unit := do + let request ← sourceRequest directory + roundtrip s!"{directory}: binary" request (Command.Request.ofIxon request.toIxon) + roundtrip s!"{directory}: text" request (Command.Request.ofText request.toText) + +private def claimRoundtrip (directory : FilePath) : IO Unit := do + let request ← claimRequest directory + roundtrip s!"{directory}: binary" request (ClaimCommand.Request.ofIxon request.toIxon) + roundtrip s!"{directory}: text" request (ClaimCommand.Request.ofText request.toText) + let bytes ← IO.FS.readBinFile (directory / "envelope.bin") + let envelope ← IO.ofExcept (Envelope.ofIxon bytes) + need (envelope.toIxon == bytes) s!"{directory}: public envelope bytes changed" + roundtrip s!"{directory}: envelope" envelope (Envelope.ofText envelope.toText) + let decoded ← IO.ofExcept (Envelope.ofText envelope.toText) + need (decoded.toIxon == bytes) s!"{directory}: text changed the authenticated object" + +private def malformedSource (request : Command.Request) : IO Unit := do + let bytes := request.toIxon + let header := RequestCodec.magic.size + let optionOffset := header + 2 + 64 + let countOffset := optionOffset + 1 + (if request.profile.natType.isSome then 32 else 0) + 32 + let hugeCount := ByteArray.mk #[0x87, 255, 255, 255, 255, 255, 255, 255, 255] + let variants := #[ + ("empty", ByteArray.empty), ("trailing", bytes.push 0), + ("truncated", bytes.extract 0 (bytes.size - 1)), + ("bad magic", bytes.set! 0 0), ("unsupported version", bytes.set! header 2), + ("wrong kind", bytes.set! (header + 1) 1), + ("noncanonical version", bytes.extract 0 header ++ ⟨#[0x80, 1]⟩ ++ bytes.extract (header + 1) bytes.size), + ("invalid option", bytes.set! optionOffset 2), + ("unbounded count", bytes.extract 0 countOffset ++ hugeCount ++ bytes.extract (countOffset + 1) bytes.size), + ("oversize", ByteArray.mk (Array.replicate (RequestCodec.maxBytes + 1) 0))] + for (label, changed) in variants do rejected label (Command.Request.ofIxon changed) + let text := request.toText + for (label, changed) in #[ + ("trailing definition", text ++ "\ndef extra : Nat := 0\n"), + ("unsafe definition", text.replace "def request" "unsafe def request"), + ("partial definition", text.replace "def request" "partial def request"), + ("wrong type", text.replace "def request : Ix.Certified.Command.Request" + "def request : Ix.Certified.ClaimCommand.Request"), + ("unknown constructor", text.replace "Ix.Certified.Command.Request.mk" "Unknown.mk"), + ("short address", text.replace (hexOfBytes request.profile.falseType.hash) "01"), + ("import", "import #" ++ hexOfBytes request.target.hash ++ "\n" ++ text), + ("unsupported grammar", "ixon 999\n" ++ text)] do + rejected label (Command.Request.ofText changed) + roundtrip "text comments" request + (Command.Request.ofText ("/- input comment -/\n" ++ text ++ "\n-- trailing comment\n")) + +private def malformedClaim (request : ClaimCommand.Request) (envelope : Envelope) : IO Unit := do + let bytes := request.toIxon + rejected "claim trailing bytes" (ClaimCommand.Request.ofIxon (bytes.push 0)) + rejected "claim truncation" (ClaimCommand.Request.ofIxon (bytes.extract 0 (bytes.size - 1))) + rejected "claim kind confusion" (Command.Request.ofIxon bytes) + rejected "claim invalid hint" (ClaimCommand.Request.ofIxon + (bytes.set! (RequestCodec.magic.size + 2 + 32) 255)) + rejected "claim text type confusion" (Command.Request.ofText request.toText) + rejected "envelope trailing bytes" (Envelope.ofIxon (envelope.toIxon.push 0)) + rejected "envelope truncated bytes" + (Envelope.ofIxon (envelope.toIxon.extract 0 (envelope.toIxon.size - 1))) + rejected "envelope integer overflow" (Envelope.ofText + (envelope.toText.replace "UInt64.ofNat 1" "UInt64.ofNat 18446744073709551616")) + +private def process (executable : String) (args : Array String) (expected : UInt32) + (success : Option Json := none) : IO Unit := do + let result ← IO.Process.output { cmd := "timeout", args := #["30", executable] ++ args } + need (result.exitCode == expected) + s!"{executable} {args}: expected exit {expected}, got {result.exitCode}\n{result.stderr}" + if let some expected := success then + need ((← IO.ofExcept (Json.parse result.stdout)) == expected) "incorrect acceptance record" + else if expected != 0 then + need result.stdout.trimAscii.isEmpty "rejected input printed an acceptance record" + +private def writeSource (directory : FilePath) (source : ByteArray) (request : Command.Request) : IO Unit := do + IO.FS.createDirAll directory + IO.FS.writeBinFile (directory / "source.ixe") source + IO.FS.writeBinFile (directory / "request.ix") request.toIxon + IO.FS.writeFile (directory / "request.ixon") request.toText + +private def writeClaim (directory : FilePath) (source : ByteArray) + (request : ClaimCommand.Request) (envelope : Envelope) : IO Unit := do + IO.FS.createDirAll directory + IO.FS.writeBinFile (directory / "source.ixe") source + IO.FS.writeBinFile (directory / "request.ix") request.toIxon + IO.FS.writeFile (directory / "request.ixon") request.toText + IO.FS.writeBinFile (directory / "envelope.ix") envelope.toIxon + IO.FS.writeFile (directory / "envelope.ixon") envelope.toText + +private def formats : Array (String × String) := #[("binary", "ix"), ("text", "ixon")] + +private def sourceCLI (fixture output : FilePath) : IO Unit := do + let source ← IO.FS.readBinFile (fixture / "source.ixe") + let request ← sourceRequest fixture + let good := output / "source" + let bad := output / "bad-source" + writeSource good source request + writeSource bad source { request with profile := { request.profile with falseType := request.target } } + malformedSource request + for (format, extension) in formats do + for mode in #["proof", "store"] do + for (directory, accepted) in #[(good, true), (bad, false)] do + let args := #[mode, (directory / "source.ixe").toString, + (directory / s!"request.{extension}").toString, s!"--request-format={format}"] + let success := if accepted then some (Json.mkObj [("accepted", .bool true), ("mode", .str mode)]) else none + process ".lake/build/bin/certified-check" args (if accepted then 0 else 1) success + let success := Json.mkObj [("accepted", .bool true), ("mode", .str "proof")] + process ".lake/build/bin/certified-check" + #["proof", (good / "source.ixe").toString, (good / "request.ix").toString] 0 (some success) + process ".lake/build/bin/certified-check" + #["proof", (good / "source.ixe").toString, (good / "request.ixon").toString] 1 + process ".lake/build/bin/certified-check" + #["--request-format", "text", "proof", (good / "source.ixe").toString, (good / "request.ix").toString] 1 + +private def claimCLI (fixture output : FilePath) : IO Unit := do + let source ← IO.FS.readBinFile (fixture / "source.ixe") + let request ← claimRequest fixture + let envelope ← IO.ofExcept (Envelope.ofIxon (← IO.FS.readBinFile (fixture / "envelope.bin"))) + let good := output / "good" + let bad := output / "bad" + let old := output / "unsupported-version" + writeClaim good source request envelope + writeClaim bad source { request with address := Address.blake3 "wrong digest".toUTF8 } envelope + let oldEnvelope := { envelope with protocol := { envelope.protocol with checker := 1 } } + writeClaim old source { request with address := Address.blake3 oldEnvelope.toIxon } oldEnvelope + malformedClaim request envelope + for (requestFormat, requestExtension) in formats do + for (envelopeFormat, envelopeExtension) in formats do + for (directory, accepted) in #[(good, true), (bad, false), (old, false)] do + let args := #["--request-format", requestFormat, s!"--envelope-format={envelopeFormat}", + (directory / "source.ixe").toString, (directory / s!"envelope.{envelopeExtension}").toString, + (directory / s!"request.{requestExtension}").toString] + let success := if accepted then some (Json.mkObj [("accepted", .bool true), + ("address", .str (hexOfBytes request.address.hash))]) else none + process ".lake/build/bin/certified-claim-check" args (if accepted then 0 else 1) success + IO.FS.writeBinFile (good / "trailing.ix") (envelope.toIxon.push 0) + process ".lake/build/bin/certified-claim-check" #[(good / "source.ixe").toString, + (good / "trailing.ix").toString, (good / "request.ix").toString] 1 + let success := Json.mkObj [("accepted", .bool true), ("address", .str (hexOfBytes request.address.hash))] + process ".lake/build/bin/certified-claim-check" #[(good / "source.ixe").toString, + (good / "envelope.ix").toString, (good / "request.ix").toString] 0 (some success) + +private def flagErrors : IO Unit := do + for executable in #["certified-check", "certified-claim-check"] do + let executable := s!".lake/build/bin/{executable}" + process executable #["--help"] 0 + for args in #[#[], #["--unknown"], #["--request-format"], + #["--request-format", "garbage"], #["--request-format=json", "--request-format", "text"]] do + process executable args 2 + process ".lake/build/bin/certified-check" #["--envelope-format", "text"] 2 + process ".lake/build/bin/certified-claim-check" #["--envelope-format", "json"] 2 + +private def run (frozen output : FilePath) : IO Unit := do + let sources ← directories (frozen / "evidence/c5/inputs") + let modeledSources ← directories (frozen / "evidence/c7/modeled-inputs/source") + let claims ← directories (frozen / "evidence/c7/claim-inputs") + let modeledClaims ← directories (frozen / "evidence/c7/modeled-inputs/claims") + need (sources.size == 42 && modeledSources.size == 44 && claims.size == 1578 && modeledClaims.size == 74) + "incomplete transport fixture coverage" + for directory in sources ++ modeledSources do sourceRoundtrip directory + for directory in claims ++ modeledClaims do claimRoundtrip directory + IO.println "Typed binary/text roundtrips passed: 86 source requests, 1,652 claim requests and envelopes." + sourceCLI (frozen / "evidence/c5/inputs/identity") output + let mut selected : Array String := #[] + for directory in claims do + let request ← claimRequest directory + let kind := match request.hint with + | .logical _ => "logical" | .contains _ => "contains" | .reveal _ => "reveal" + if selected.contains kind then continue + let expected ← readJson (directory / "expected.json") + unless (← IO.ofExcept (expected.getObjValAs? Bool "accepted")) do continue + claimCLI directory (output / kind) + selected := selected.push kind + need (selected.size == 3) "missing logical, membership, or revelation process coverage" + flagErrors + IO.println "Certified input format, malformed input, digest, version, and CLI regressions passed." + +private def examples (frozen output : FilePath) : IO Unit := do + let source := frozen / "evidence/c5/inputs/identity" + writeSource (output / "source") (← IO.FS.readBinFile (source / "source.ixe")) (← sourceRequest source) + for directory in ← directories (frozen / "evidence/c7/claim-inputs") do + let request ← claimRequest directory + let .logical _ := request.hint | continue + let expected ← readJson (directory / "expected.json") + unless (← IO.ofExcept (expected.getObjValAs? Bool "accepted")) do continue + let envelope ← IO.ofExcept (Envelope.ofIxon (← IO.FS.readBinFile (directory / "envelope.bin"))) + writeClaim (output / "claim") (← IO.FS.readBinFile (directory / "source.ixe")) request envelope + break + IO.println s!"Wrote Lean-typed Ixon inputs in binary and text form to {output}." + +private def withArchive (action : FilePath → IO Unit) : IO Unit := do + let archive := Tests.Certified.ImportManifest.archive + let digest ← IO.Process.output { cmd := "sha256sum", args := #["--", archive] } + need (digest.exitCode == 0 && (digest.stdout.splitOn " ").headD "" == + Tests.Certified.ImportManifest.archiveSha256) "frozen adapter archive identity changed" + IO.FS.withTempDir fun directory => do + let unpack ← IO.Process.output { + cmd := "tar", args := #["-xzf", archive, "--no-same-owner", "--no-same-permissions", "-C", directory.toString] } + need (unpack.exitCode == 0) unpack.stderr + action directory + +def main (args : List String) : IO UInt32 := do + match args with + | [] => + withArchive fun frozen => IO.FS.withTempDir (run frozen) + return 0 + | ["--examples", output] => + withArchive fun frozen => examples frozen output + return 0 + | [frozen, output] => + run frozen output + return 0 + | _ => + IO.eprintln "usage: certified-input-tests [FROZEN OUTPUT | --examples OUTPUT]" + return 2 + +end Tests.Certified.Inputs + +def main := Tests.Certified.Inputs.main diff --git a/docs/certified-checking.md b/docs/certified-checking.md index b565d7b30..ecc5e963f 100644 --- a/docs/certified-checking.md +++ b/docs/certified-checking.md @@ -21,39 +21,116 @@ Build the source and claim commands: lake build --wfail certified-check certified-claim-check ``` -Source checking takes a lazy `.ixe` file and a JSON request that selects the -target or subjects, primitive addresses, source objects and natural values: +Source checking takes a lazy `.ixe` file and a typed request that selects the +target or subjects, primitive addresses, source objects and natural values. +Binary Ixon is the default input format: ```sh -.lake/build/bin/certified-check proof SOURCE.ixe REQUEST.json -.lake/build/bin/certified-check store SOURCE.ixe REQUEST.json +.lake/build/bin/certified-check proof SOURCE.ixe REQUEST.ix +.lake/build/bin/certified-check store SOURCE.ixe REQUEST.ix +.lake/build/bin/certified-claim-check SOURCE.ixe ENVELOPE.ix REQUEST.ix ``` -The request fields are `target`, `subjects`, `objects`, `naturals`, -`falseType`, `falseElim`, nullable `natType`, and optional `models`. Addresses -are 32-byte hexadecimal strings. Model hints select earlier source -declarations; the validator checks their types and complete source equations. -The request parser is defined in -[`Command.lean`](../Ix/Certified/Command.lean). - -For a runnable source example: +Use `--request-format text` for a readable `.ixon` request. Claim checking +selects the request and envelope encodings independently: ```sh -lake build certified-source-tests -.lake/build/bin/certified-source-tests /tmp/ix-certified-examples -.lake/build/bin/certified-check proof \ - /tmp/ix-certified-examples/identity/source.ixe \ - /tmp/ix-certified-examples/identity/request.json +.lake/build/bin/certified-check --request-format text proof SOURCE.ixe REQUEST.ixon +.lake/build/bin/certified-check --request-format text store SOURCE.ixe REQUEST.ixon +.lake/build/bin/certified-claim-check \ + --request-format text --envelope-format text \ + SOURCE.ixe ENVELOPE.ixon REQUEST.ixon +.lake/build/bin/certified-claim-check \ + --request-format text --envelope-format binary \ + SOURCE.ixe ENVELOPE.ix REQUEST.ixon ``` -Claim checking also takes the exact serialized envelope. The JSON request -selects its expected address and supplies logical, membership or revelation -witness hints: +Both flags accept `binary` or `text`, including `--request-format=text` +syntax. The selected flag determines the encoding independently of the file +suffix. `SOURCE.ixe` always contains a serialized Ixon environment. + +For runnable examples in both encodings: ```sh -.lake/build/bin/certified-claim-check SOURCE.ixe ENVELOPE.bin REQUEST.json +lake build certified-input-tests +.lake/build/bin/certified-input-tests --examples /tmp/ix-certified-examples +.lake/build/bin/certified-check --request-format text proof \ + /tmp/ix-certified-examples/source/source.ixe \ + /tmp/ix-certified-examples/source/request.ixon +.lake/build/bin/certified-claim-check --request-format text --envelope-format binary \ + /tmp/ix-certified-examples/claim/source.ixe \ + /tmp/ix-certified-examples/claim/envelope.ix \ + /tmp/ix-certified-examples/claim/request.ixon ``` +Both commands use fuel 6,400. Success exits 0 and prints a JSON acceptance +record; rejection or a file-reading error exits 1, and invalid command-line +arguments exit 2. Fuel or witness-search failure can reject a valid source, +so success and completeness are separate properties. + +### Lean API + +Import `Ix.Certified` to construct the actual Lean values: + +| Value | Type | +| --- | --- | +| Source proof/store request | `Ix.Certified.Command.Request` | +| Claim request and witness hints | `Ix.Certified.ClaimCommand.Request` | +| Public claim envelope | `Ix.Certified.Envelope` | + +Source requests contain `profile`, `target`, `subjects`, `selection`, and +`models`. The profile pins `falseType`, `falseElim`, and optional `natType`; +the selection lists object and natural-value addresses. Model hints select +earlier source declarations whose types and complete equations the validator +checks. Claim requests contain the expected envelope `address` and a typed +`.logical`, `.contains`, or `.reveal` hint. + +Each of the three types provides `toIxon`/`ofIxon` and `toText`/`ofText`. +They also have `Ixon.Serialize` instances. Use the named `ofIxon` decoders +when reading a complete input: they reject trailing and noncanonical bytes. +For example, a Lean program can export a source request without JSON: + +```lean +import Ix.Certified + +def saveRequest (directory : System.FilePath) + (request : Ix.Certified.Command.Request) : IO Unit := do + IO.FS.createDirAll directory + IO.FS.writeBinFile (directory / "request.ix") request.toIxon + IO.FS.writeFile (directory / "request.ixon") request.toText +``` + +`Command.run` and `ClaimCommand.run` also accept these typed requests directly +when the source environment is already loaded. Lean authoring supports normal +record syntax and computation; the exported `.ixon` file contains the resulting +data value. + +### Input representations + +Text inputs use the existing Ixon parser and printer. Each file contains one +safe monomorphic `def` or one annotated main expression. The reader checks +the type annotation, constructor names, argument counts, and literal values. +Lists, options, claims, model hints, and revelation fields use their actual +Lean constructors, with explicit type arguments as required by Ixon syntax. +`Ix.Certified.Text.address!` and `bytes!` provide hexadecimal literals. +The data reader accepts constructor expressions and checks their contents; +imports, extra declarations, and arbitrary computation are rejected. + +Binary requests have an `IX-CERTIFIED-REQUEST` header, request-format version +1, and a distinct source/claim tag. Addresses occupy 32 bytes; list and byte +lengths use Ixon `Tag0` encoding, and options use tags 0 and 1. Complete binary +decoding requires canonical re-encoding. Request decoding is capped at 1 MiB; +text additionally uses the standard Ixon parser's node and depth limits. +See [`RequestCodec.lean`](../Ix/Certified/RequestCodec.lean), +[`TextCodec.lean`](../Ix/Certified/TextCodec.lean), and +[`InputText.lean`](../Ix/Certified/InputText.lean). + +Claim envelopes retain their existing canonical Ixon representation. With +binary input, authentication checks the exact bytes read from the file. +With text input, the authenticated object is the parsed envelope's canonical +binary encoding. The request's expected address must match the BLAKE3 hash +of those bytes. Text formatting therefore does not change the claim address. + The envelope binds the claim, primitive profile, logical-axiom manifest and protocol versions. The current checker version is **2**; format, codec, policy and aggregation versions are **1**. Exact decoding, canonical @@ -62,10 +139,10 @@ Trailing bytes and older checker envelopes reject. See [`Envelope.lean`](../Ix/Certified/Envelope.lean) and [`ClaimCommand.lean`](../Ix/Certified/ClaimCommand.lean). -Both commands currently use fuel 6,400. Success exits 0 and prints a JSON -acceptance record; a rejected request exits 1. Fuel or witness-search failure -can reject a valid source, so success and completeness are separate -properties. +Existing JSON requests remain available with `--request-format json` for +compatibility. The frozen CLI corpus selects this mode explicitly. All +formats pass through the same witness search and certified validation. +The file interface is implemented in [`CLI.lean`](../Ix/Certified/CLI.lean). ## Semantic contract @@ -93,7 +170,7 @@ definitions and statements are in [`LogicalPolicy.lean`](../Ix/Theory/Certified/LogicalPolicy.lean). The mathematical contract concerns the Lean functions. Native Lean -execution, filesystem loading and the BLAKE3 foreign interface remain +execution, transport parsing, filesystem loading and the BLAKE3 foreign interface remain execution boundaries. Full production-checker refinement and execution of this certification inside an authenticated Aiur proof remain separate obligations described in @@ -110,8 +187,9 @@ lake run check-certified The gate builds the adapters, audits and test programs with warnings treated as errors. It compares the exact foundation report, checks the frozen source archive and maintained import identities, runs six native host test programs, -and exercises the actual source and claim executables on all three CLI -corpora. CI runs the same gate. +and exercises the actual source and claim executables on all three legacy CLI +corpora. It also checks the binary/text input codecs and format-selection +regressions. CI runs the same gate. The combined audit covers **86 distinct roots**, **74 premise definitions or constructor types**, **9,682 logical declarations** and **10,957 declarations @@ -151,7 +229,11 @@ non-VM field; only `pilotDeclined` and `pilotDeclines` are projected away from the three historical reports that mixed host and VM checks. The VM pilot, packet encoder and VM execution suite are archived for a later change. CLI JSON requests and aggregate records are compared as parsed values because -the maintained Lean driver formats JSON differently. The archive, source +the maintained Lean driver formats JSON differently. Typed binary/text +roundtrips cover all 86 source requests and 1,652 claim requests and envelopes +from the source, claim, and modeled corpora. Additional process tests exercise +mixed input formats, malformed encodings, wrong digests, unsupported versions, +and command-line errors. The archive, source mappings, licenses and historical reproduction limits are documented in [`Tests/Fixtures/Certified`](../Tests/Fixtures/Certified/README.md). The archive recovers the selected adapter sources and fixtures; it does not include the diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index b6836b2fd..820c8ed0d 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -6,8 +6,11 @@ proofs. Their named specification and reference implementation lemmas are local under `Ix.Theory.Named`. Building or checking them requires no external formalization repository. -The certified receipt interface and a fragment of production `checkEnvAnon` -have relative consistency theorems. Full checker consistency remains open. +Certified acceptance has model-construction and relative consistency theorems, +with a concrete set-model construction in the separate Mathlib package. A +direct theorem also connects a fragment of production `checkEnvAnon` to that +semantics. Extending this connection to all paths of the ordinary Lean checker +requires the remaining production-refinement proofs described below. The [recursion audit](kernel-recursion.md) explains the production call graph and fuel bounds. The [context-digest guide](tc-context-digest-collision-boundary.md) diff --git a/lakefile.lean b/lakefile.lean index b174c29c0..e2c94dad0 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -380,6 +380,11 @@ lean_exe «certified-cli-tests» where root := `Tests.Certified.CLI supportInterpreter := true +lean_exe «certified-input-tests» where + root := `Tests.Certified.Inputs + supportInterpreter := true + moreLinkObjs := #[ix_rs] + lean_exe «certified-adapter-tests» where root := `Tests.Certified.Check supportInterpreter := true @@ -464,7 +469,7 @@ script "check-certified" := do run "lake" #["build", "--wfail", "IxCertified", "IxCertifiedAudit", "certified-check", "certified-claim-check", "certified-feature-tests", "certified-ordinary-tests", "certified-source-tests", "certified-fidelity-tests", - "certified-claim-tests", "certified-modeled-tests", "certified-cli-tests", + "certified-claim-tests", "certified-modeled-tests", "certified-cli-tests", "certified-input-tests", "certified-adapter-tests"] checkReport "Ix/Certified/AuditAll.lean" "Tests/Certified/foundation.txt" run ".lake/build/bin/certified-adapter-tests" From 1bd7a44d74aeb054382ad43b061862a44fdd7a26 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 10:43:15 -0400 Subject: [PATCH 06/30] Refine polymorphic constant inference into the set model --- Ix/Kernel/Verify/Consistency.lean | 5 + Ix/Kernel/Verify/Consistency/Audit.lean | 20 +- Ix/Kernel/Verify/Consistency/Constant.lean | 98 +++++++ Ix/Kernel/Verify/Consistency/InstUniv.lean | 305 +++++++++++++++++++++ Ix/Kernel/Verify/InstL.lean | 104 +------ Ix/Kernel/Verify/UniverseSupport.lean | 116 ++++++++ Ix/Theory/Model/LevelCongruence.lean | 224 +++++++++++++++ Tests/Ix/Kernel/Consistency.lean | 99 ++++++- Tests/Theory/ImportManifest.lean | 6 +- Tests/Theory/Provenance.lean | 10 +- docs/kernel-verification.md | 30 +- 11 files changed, 899 insertions(+), 118 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/Constant.lean create mode 100644 Ix/Kernel/Verify/Consistency/InstUniv.lean create mode 100644 Ix/Kernel/Verify/UniverseSupport.lean create mode 100644 Ix/Theory/Model/LevelCongruence.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index e6c5a00b0..121f7e437 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -7,6 +7,8 @@ import Ix.Kernel.Verify.Consistency.Level import Ix.Kernel.Verify.Consistency.Expr import Ix.Kernel.Verify.Consistency.Judgment import Ix.Kernel.Verify.Consistency.Infer +import Ix.Kernel.Verify.Consistency.InstUniv +import Ix.Kernel.Verify.Consistency.Constant import Ix.Kernel.Verify.Consistency.Atomic import Ix.Kernel.Verify.Consistency.Production import Ix.Kernel.Verify.Consistency.Environment @@ -20,4 +22,7 @@ transport keeps its representation, arithmetic, and dependency assumptions explicit. A production `checkEnvAnon` fragment preserves models of its axiom set for monomorphic aliases and closed sorts under the stated execution resources. General checker soundness remains outside this fragment. +Separately, polymorphic constant inference refines the model for arbitrary +readable entry types, using the actual universe-instantiation walker and +explicit lookup, scope, and finite-support resources. -/ diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 3a6684b17..f9e0c91f6 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -4,6 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Infer +import Ix.Kernel.Verify.Consistency.Constant import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Audit.Basic @@ -37,6 +38,11 @@ private def atomicRoots : Array Lean.Name := #[ ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound ] +private def instantiationRoots : Array Lean.Name := #[ + ``instUnivSpec_readExpr?, ``instantiateUnivParams_readExpr?, + ``instantiateUnivParams_readAnnotated, ``inferUncached_const_sound, ``infer_const_sound +] + private def productionRoots : Array Lean.Name := #[ ``StandalonePrefix.member_success, ``definition_body_trace, ``AtomicDefinitionRun.sound, ``AtomicDefinitionRun.no_self_alias, @@ -77,8 +83,18 @@ def roots : Array RootAllowance := #[ { root := ``ModelTyping.no_false, standardAxioms := standard }, { root := ``sort_conversion, standardAxioms := standard }, { root := ``inferUncached_sort_sound, standardAxioms := standard, - nativeAxioms := #[expressionNative, levelNative] } -] ++ atomicRoots.map (fun root => { + nativeAxioms := #[expressionNative, levelNative] }, + { root := ``Theory.VExpr.LevelEquivalent.refl, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``Theory.VExpr.LevelEquivalent.liftN, standardAxioms := #[``propext] }, + { root := ``Theory.VExpr.LevelEquivalent.inst, standardAxioms := #[``propext] }, + { root := ``Theory.VExpr.instL_liftN, standardAxioms := #[``propext] }, + { root := ``Theory.VExpr.instL_inst, standardAxioms := #[``propext] }, + { root := ``Theory.VExpr.LevelWF.instL_nil, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``Theory.Model.AExpr.reannotate_levels, standardAxioms := #[``propext] }, + { root := ``Theory.Model.AExpr.LevelEquivalent.interp, standardAxioms := standard }, + { root := ``Theory.Model.AExpr.LevelEquivalent.wellDenoted, standardAxioms := standard }, + { root := ``Theory.Model.AExpr.LevelEquivalent.typing, standardAxioms := standard } +] ++ (atomicRoots ++ instantiationRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], forbiddenDependencies := forbiddenProduction }) ++ productionRoots.map (fun root => { diff --git a/Ix/Kernel/Verify/Consistency/Constant.lean b/Ix/Kernel/Verify/Consistency/Constant.lean new file mode 100644 index 000000000..babefe0b4 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Constant.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Atomic +import Ix.Kernel.Verify.Consistency.InstUniv + +/-! +# Production inference of polymorphic constants + +Successful constant inference supplies its own arity check and runs the actual +memoized universe-instantiation routine. Lookup agreement identifies the +loaded declaration's universe count and type with an existing model entry. +No restriction to monomorphic entries or sort-shaped types is needed. + +The remaining operational assumptions are explicit: lookup agreement, the +loaded state's finite interning and level-substitution resources, and (for +the cached entry point) misses at the actual inference key. This does not yet +establish these invariants for arbitrary loader states or cache hits. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +/-- Agreement with the concrete declaration returned by lazy lookup, together +with the resources needed by the walker at that exact post-lookup state. -/ +structure ConstantInferenceSupport {β : Type u} + (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) + (before : TcState .anon) (id : KId .anon) (arguments : Array (KUniv .anon)) + (ref : ConstRef β) (entry : ConstantEntry β) : Prop where + resolved : resolve id.addr = some ref + found : entries ref = some entry + lookup : ∀ concrete loaded, TcM.getConst id before = .ok concrete loaded → + concrete.lvls.toNat = entry.universes ∧ + readExpr? resolve concrete.ty = some entry.type.erase ∧ + UniverseInstantiationSupport loaded concrete.ty arguments + +/-- A successful uncached production branch types its exact returned tree in +every model of the preceding interface. The runtime guard establishes arity; +the model environment's well-formedness supplies the declaration type's scope. -/ +theorem inferUncached_const_sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {context : Model.Context β} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} + (support : ConstantInferenceSupport resolve entries before id arguments ref entry) + (wellFormed : entries.WF) + (accepted : RecM.inferUncached inferRec inferOnly (.const id arguments info) + methods before = .ok type after) : + ModelTyping.{u,v} resolve entries context (.const id arguments info) type := by + change (RecM.inferUncached inferRec inferOnly (.const id arguments info)).run + methods before = .ok type after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.getConst id) _ before = _ at accepted + cases got : TcM.getConst id before with + | error err failed => rw [EStateM.bind, got] at accepted; contradiction + | ok concrete loaded => + rw [EStateM.bind, got] at accepted + obtain ⟨count, reading, resources⟩ := support.lookup concrete loaded got + by_cases arity : concrete.lvls.toNat = arguments.size + · simp only [arity, bne_self_eq_false, Bool.false_eq_true, if_false] at accepted + change TcM.instantiateUnivParams concrete.ty arguments loaded = .ok type after at accepted + have length : (arguments.toList.map readLevel).length = entry.universes := by + simpa only [List.length_map, Array.length_toList] using arity.symm.trans count + have scope : entry.type.erase.LevelWF arguments.size := by + rw [← arity, count] + exact (wellFormed.typeScope ref entry support.found).erase.1 + obtain ⟨output, outputReads, same⟩ := + instantiateUnivParams_readAnnotated resources scope reading accepted + refine ⟨.const ref (arguments.toList.map readLevel), output, ?_, outputReads, + same.typing (TypingClaim.const support.found length)⟩ + simp [readExpr?, support.resolved, AExpr.erase] + · simp only [bne_iff_ne] at accepted + rw [if_pos arity] at accepted + contradiction + +/-- The ordinary production inference entry point, including its actual key +lookup and final cache write, refines polymorphic constant typing on misses. -/ +theorem infer_const_sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {context : Model.Context β} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} + {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} + (miss : UncachedInference before (.const id arguments info)) + (support : ConstantInferenceSupport resolve entries miss.keyed id arguments ref entry) + (wellFormed : entries.WF) + (accepted : RecM.infer (.const id arguments info) methods before = .ok type after) : + ModelTyping.{u,v} resolve entries context (.const id arguments info) type := by + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + exact inferUncached_const_sound support wellFormed run + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/InstUniv.lean b/Ix/Kernel/Verify/Consistency/InstUniv.lean new file mode 100644 index 000000000..f945aa0d2 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/InstUniv.lean @@ -0,0 +1,305 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Expr +import Ix.Kernel.Verify.UniverseSupport +import Ix.Theory.Model.LevelCongruence + +/-! +# Production universe instantiation in the consistency model + +The existing walker proof establishes equality with its memo-free specification +under finite interning support. This module connects that specification to +the structural reader, including simplifying universe constructors and lets. +Its final theorem supplies an annotated reading of the actual returned tree, +with the same interpretation and hereditary validity as model substitution. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u +variable {β : Type u} + +/-- The precise level-side assumptions used by the simplifying constructors. -/ +structure UniverseSubstitutionSupport (arguments : Array (KUniv .anon)) + (term : KExpr .anon) : Prop where + faithful : ∀ left right, KExpr.LevelReach arguments term left → + KExpr.LevelReach arguments term right → left.AddrFaithful right + bounded : ∀ level, KExpr.LevelReach arguments term level → level.size < UInt64.size + +private theorem substUniv_readLevel {arguments : Array (KUniv .anon)} + {level result : KUniv .anon} + (run : TcM.substUniv level arguments = .ok result) + (faithful : ∀ left right, KUniv.SubstUnivReach arguments level left → + KUniv.SubstUnivReach arguments level right → left.AddrFaithful right) + (bounded : ∀ value, KUniv.SubstUnivReach arguments level value → + value.size < UInt64.size) : + (readLevel level).inst (arguments.toList.map readLevel) ≈ readLevel result := by + rw [show (readLevel : KUniv .anon → VLevel) = KUniv.toVLevel from funext readLevel_eq] + exact VLevel.equiv_def.mpr fun valuation => + (VLevel.equiv_def.mp (TcM.substUniv_toVLevel run faithful bounded) valuation).symm + +private theorem list_substUniv_readLevels {arguments : Array (KUniv .anon)} : + ∀ {levels results : List (KUniv .anon)}, + levels.mapM (TcM.substUniv · arguments) = .ok results → + (∀ level ∈ levels, ∀ left right, KUniv.SubstUnivReach arguments level left → + KUniv.SubstUnivReach arguments level right → left.AddrFaithful right) → + (∀ level ∈ levels, ∀ value, KUniv.SubstUnivReach arguments level value → + value.size < UInt64.size) → + ∀ valuation, + ((levels.map readLevel).map (VLevel.inst (arguments.toList.map readLevel))).map + (VLevel.eval valuation) = (results.map readLevel).map (VLevel.eval valuation) := by + intro levels + induction levels with + | nil => + intro results run _ _ valuation + simp only [List.mapM_nil] at run + cases run + rfl + | cons level rest ih => + intro results run faithful bounded valuation + rw [List.mapM_cons] at run + cases first : TcM.substUniv level arguments with + | error err => rw [first] at run; contradiction + | ok result => + cases tail : rest.mapM (TcM.substUniv · arguments) with + | error err => rw [first, tail] at run; contradiction + | ok remaining => + rw [first, tail] at run + cases run + simp only [List.map_cons, List.cons.injEq] + exact ⟨VLevel.equiv_def.mp (substUniv_readLevel first + (faithful level List.mem_cons_self) (bounded level List.mem_cons_self)) valuation, + ih tail + (fun level member => faithful level (List.mem_cons_of_mem _ member)) + (fun level member => bounded level (List.mem_cons_of_mem _ member)) valuation⟩ + +private theorem array_substUniv_readLevels {arguments levels results : Array (KUniv .anon)} + (run : levels.mapM (TcM.substUniv · arguments) = .ok results) + (faithful : ∀ level ∈ levels, ∀ left right, KUniv.SubstUnivReach arguments level left → + KUniv.SubstUnivReach arguments level right → left.AddrFaithful right) + (bounded : ∀ level ∈ levels, ∀ value, KUniv.SubstUnivReach arguments level value → + value.size < UInt64.size) : + ∀ valuation, + ((levels.toList.map readLevel).map (VLevel.inst (arguments.toList.map readLevel))).map + (VLevel.eval valuation) = (results.toList.map readLevel).map (VLevel.eval valuation) := by + have listRun : levels.toList.mapM (TcM.substUniv · arguments) = .ok results.toList := by + rw [← Array.toList_mapM, run] + rfl + exact list_substUniv_readLevels listRun + (fun level member => faithful level (by simpa using member)) + (fun level member => bounded level (by simpa using member)) + +private theorem except_bind_success {ε α γ : Type _} {action : Except ε α} + {next : α → Except ε γ} {result : γ} (run : action.bind next = .ok result) : + ∃ intermediate, action = .ok intermediate ∧ next intermediate = .ok result := by + cases action with + | error err => contradiction + | ok value => exact ⟨value, rfl, run⟩ + +private theorem option_bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ intermediate, action = some intermediate ∧ next intermediate = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +/-- Successful pure instantiation reads as model substitution, up to equivalent +universe levels. All expression positions are covered; the reader's existing +exclusions of free variables, strings, and unresolved references are retained. -/ +theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : VExpr β} + (support : UniverseSubstitutionSupport arguments term) + (reading : readExpr? resolve term = some source) + (run : KExpr.instUnivSpec term arguments = .ok result) : + ∃ output, readExpr? resolve result = some output ∧ + VExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output := by + induction term generalizing source result with + | var index name info => + cases run + cases reading + exact ⟨_, rfl, .bvar _⟩ + | fvar _ _ _ | str _ _ _ => contradiction + | nat value name info => + cases run + cases reading + exact ⟨_, rfl, .natLit _⟩ + | sort level info => + cases reading + rw [KExpr.instUnivSpec] at run + obtain ⟨value, substituted, run⟩ := except_bind_success run + cases run + exact ⟨_, rfl, .sort (substUniv_readLevel substituted + (fun left right hl hr => support.faithful left right + ⟨level, .sort, hl⟩ ⟨level, .sort, hr⟩) + (fun value hv => support.bounded value ⟨level, .sort, hv⟩))⟩ + | const id levels info => + cases resolved : resolve id.addr with + | none => simp [readExpr?, resolved] at reading + | some ref => + simp [readExpr?, resolved] at reading + subst source + rw [KExpr.instUnivSpec] at run + obtain ⟨values, substituted, run⟩ := except_bind_success run + cases run + refine ⟨.const ref (values.toList.map readLevel), ?_, .const ref ?_⟩ + · change readExpr? resolve (.const id values _) = _ + simp [readExpr?, resolved] + · exact array_substUniv_readLevels substituted + (fun level member left right hl hr => support.faithful left right + ⟨level, .const member, hl⟩ ⟨level, .const member, hr⟩) + (fun level member value hv => support.bounded value ⟨level, .const member, hv⟩) + | app fn arg info hf ha => + rw [readExpr?] at reading + obtain ⟨f, fReads, reading⟩ := option_bind_success reading + obtain ⟨a, aReads, reading⟩ := option_bind_success reading + cases reading + rw [KExpr.instUnivSpec] at run + obtain ⟨f', fRun, run⟩ := except_bind_success run + obtain ⟨a', aRun, run⟩ := except_bind_success run + cases run + obtain ⟨vf, vfReads, vfSame⟩ := hf + ⟨fun x y hx hy => support.faithful x y hx.app_f hy.app_f, + fun x hx => support.bounded x hx.app_f⟩ fReads fRun + obtain ⟨va, vaReads, vaSame⟩ := ha + ⟨fun x y hx hy => support.faithful x y hx.app_a hy.app_a, + fun x hx => support.bounded x hx.app_a⟩ aReads aRun + refine ⟨.app vf va, ?_, .app vfSame vaSame⟩ + change readExpr? resolve (.app f' a' _) = _ + simp [readExpr?, vfReads, vaReads] + | lam name bi domain body info hA hb => + rw [readExpr?] at reading + obtain ⟨A, aReads, reading⟩ := option_bind_success reading + obtain ⟨b, bReads, reading⟩ := option_bind_success reading + cases reading + rw [KExpr.instUnivSpec] at run + obtain ⟨A', aRun, run⟩ := except_bind_success run + obtain ⟨b', bRun, run⟩ := except_bind_success run + cases run + obtain ⟨vA, vAReads, vASame⟩ := hA + ⟨fun x y hx hy => support.faithful x y hx.lam_ty hy.lam_ty, + fun x hx => support.bounded x hx.lam_ty⟩ aReads aRun + obtain ⟨vb, vbReads, vbSame⟩ := hb + ⟨fun x y hx hy => support.faithful x y hx.lam_body hy.lam_body, + fun x hx => support.bounded x hx.lam_body⟩ bReads bRun + refine ⟨.lam vA vb, ?_, .lam vASame vbSame⟩ + change readExpr? resolve (.lam name bi A' b' _) = _ + simp [readExpr?, vAReads, vbReads] + | all name bi domain body info hA hb => + rw [readExpr?] at reading + obtain ⟨A, aReads, reading⟩ := option_bind_success reading + obtain ⟨b, bReads, reading⟩ := option_bind_success reading + cases reading + rw [KExpr.instUnivSpec] at run + obtain ⟨A', aRun, run⟩ := except_bind_success run + obtain ⟨b', bRun, run⟩ := except_bind_success run + cases run + obtain ⟨vA, vAReads, vASame⟩ := hA + ⟨fun x y hx hy => support.faithful x y hx.all_ty hy.all_ty, + fun x hx => support.bounded x hx.all_ty⟩ aReads aRun + obtain ⟨vb, vbReads, vbSame⟩ := hb + ⟨fun x y hx hy => support.faithful x y hx.all_body hy.all_body, + fun x hx => support.bounded x hx.all_body⟩ bReads bRun + refine ⟨.forallE vA vb, ?_, .forallE vASame vbSame⟩ + change readExpr? resolve (.all name bi A' b' _) = _ + simp [readExpr?, vAReads, vbReads] + | letE name domain value body nonDep info hA hv hb => + rw [readExpr?] at reading + obtain ⟨A, aReads, reading⟩ := option_bind_success reading + obtain ⟨value, valueReads, reading⟩ := option_bind_success reading + obtain ⟨body, bodyReads, reading⟩ := option_bind_success reading + cases reading + rw [KExpr.instUnivSpec] at run + obtain ⟨A', aRun, run⟩ := except_bind_success run + obtain ⟨v', vRun, run⟩ := except_bind_success run + obtain ⟨b', bRun, run⟩ := except_bind_success run + cases run + obtain ⟨vA, vAReads, _⟩ := hA + ⟨fun x y hx hy => support.faithful x y hx.letE_ty hy.letE_ty, + fun x hx => support.bounded x hx.letE_ty⟩ aReads aRun + obtain ⟨vv, vvReads, vvSame⟩ := hv + ⟨fun x y hx hy => support.faithful x y hx.letE_val hy.letE_val, + fun x hx => support.bounded x hx.letE_val⟩ valueReads vRun + obtain ⟨vb, vbReads, vbSame⟩ := hb + ⟨fun x y hx hy => support.faithful x y hx.letE_body hy.letE_body, + fun x hx => support.bounded x hx.letE_body⟩ bodyReads bRun + refine ⟨vb.inst vv, ?_, ?_⟩ + · change readExpr? resolve (.letE name A' v' b' nonDep _) = _ + simp [readExpr?, vAReads, vvReads, vbReads] + · rw [VExpr.instL_inst] + exact vbSame.inst vvSame + | prj id index value info ih => + cases resolved : resolve id.addr with + | none => simp [readExpr?, resolved] at reading + | some ref => + rw [readExpr?, resolved] at reading + change (readExpr? resolve value).bind + (fun value => some (.proj ref index.toNat value)) = some source at reading + obtain ⟨source, sourceReads, reading⟩ := option_bind_success reading + cases reading + rw [KExpr.instUnivSpec] at run + obtain ⟨value', valueRun, run⟩ := except_bind_success run + cases run + obtain ⟨output, outputReads, outputSame⟩ := ih + ⟨fun x y hx hy => support.faithful x y hx.prj hy.prj, + fun x hx => support.bounded x hx.prj⟩ sourceReads valueRun + refine ⟨.proj ref index.toNat output, ?_, .proj ref index.toNat outputSame⟩ + change readExpr? resolve (.prj id index value' _) = _ + simp [readExpr?, resolved, outputReads] + +/-- Runtime resources for the memoized walker, all on its actual finite support. -/ +structure UniverseInstantiationSupport (before : TcState .anon) + (term : KExpr .anon) (arguments : Array (KUniv .anon)) : Prop where + coherent : before.env.intern.WF + faithful : KExpr.CollisionFree fun candidate => before.env.intern.ExprSupport candidate ∨ + KExpr.InstUnivReach arguments term candidate + levels : UniverseSubstitutionSupport arguments term + +/-- Connect the actual memoized and interned execution to model substitution. +The empty-argument shortcut requires scope because production skips its usual +parameter-range checks on that path. -/ +theorem instantiateUnivParams_readExpr? {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : VExpr β} + {before after : TcState .anon} + (support : UniverseInstantiationSupport before term arguments) + (scope : source.LevelWF arguments.size) + (reading : readExpr? resolve term = some source) + (run : TcM.instantiateUnivParams term arguments before = .ok result after) : + ∃ output, readExpr? resolve result = some output ∧ + VExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output := by + have post := TcM.instantiateUnivParams_wf support.faithful + (fun _ h => Or.inr h) ⟨support.coherent, fun _ h => Or.inl h⟩ + rw [run] at post + have spec := post.2.1 + by_cases empty : arguments.isEmpty = true + · have args : arguments = #[] := Array.isEmpty_iff.mp empty + subst arguments + change Except.ok term = .ok result at spec + cases spec + refine ⟨source, reading, ?_⟩ + simpa only [Array.toList_empty, List.map_nil, scope.instL_nil] using + VExpr.LevelEquivalent.refl source + · rw [KExpr.instantiateUnivParamsSpec, if_neg empty] at spec + exact instUnivSpec_readExpr? support.levels reading spec + +/-- An annotated reading of the returned tree, preserving all binder conditions +after their model-side universe substitution. -/ +theorem instantiateUnivParams_readAnnotated {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : AExpr β} + {before after : TcState .anon} + (support : UniverseInstantiationSupport before term arguments) + (scope : source.erase.LevelWF arguments.size) + (reading : readExpr? resolve term = some source.erase) + (run : TcM.instantiateUnivParams term arguments before = .ok result after) : + ∃ output : AExpr β, readExpr? resolve result = some output.erase ∧ + AExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output := by + obtain ⟨raw, rawReads, same⟩ := instantiateUnivParams_readExpr? support scope reading run + rw [← AExpr.erase_instL] at same + obtain ⟨output, erased, equivalent⟩ := AExpr.reannotate_levels _ same + exact ⟨output, erased ▸ rawReads, equivalent⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/InstL.lean b/Ix/Kernel/Verify/InstL.lean index e80a4eb37..71d9a77a2 100644 --- a/Ix/Kernel/Verify/InstL.lean +++ b/Ix/Kernel/Verify/InstL.lean @@ -1,5 +1,5 @@ import Ix.Kernel.Verify.Trans -import Ix.Kernel.Verify.InstUniv +import Ix.Kernel.Verify.UniverseSupport open Ix.Theory (VLevel) @@ -26,108 +26,6 @@ namespace Ix.Kernel open Ix.Theory.Named (VExpr VEnv) -/-! ### Level occurrences and the reach set -/ - -/-- The levels of an expression: `sort` payloads and `const` level - arguments, through all subterms. -/ -inductive KExpr.HasLevel {m : Mode} : KExpr m → KUniv m → Prop - | sort {u : KUniv m} {md : ExprInfo m} : HasLevel (.sort u md) u - | const {id : KId m} {us : Array (KUniv m)} {md : ExprInfo m} - {u : KUniv m} : - u ∈ us → HasLevel (.const id us md) u - | app_f {f a : KExpr m} {md : ExprInfo m} {u : KUniv m} : - HasLevel f u → HasLevel (.app f a md) u - | app_a {f a : KExpr m} {md : ExprInfo m} {u : KUniv m} : - HasLevel a u → HasLevel (.app f a md) u - | lam_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} {ty body : KExpr m} - {md : ExprInfo m} {u : KUniv m} : - HasLevel ty u → HasLevel (.lam n bi ty body md) u - | lam_body {n : m.F Name} {bi : m.F Lean.BinderInfo} - {ty body : KExpr m} {md : ExprInfo m} {u : KUniv m} : - HasLevel body u → HasLevel (.lam n bi ty body md) u - | all_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} {ty body : KExpr m} - {md : ExprInfo m} {u : KUniv m} : - HasLevel ty u → HasLevel (.all n bi ty body md) u - | all_body {n : m.F Name} {bi : m.F Lean.BinderInfo} - {ty body : KExpr m} {md : ExprInfo m} {u : KUniv m} : - HasLevel body u → HasLevel (.all n bi ty body md) u - | letE_ty {n : m.F Name} {ty val body : KExpr m} {nd : Bool} - {md : ExprInfo m} {u : KUniv m} : - HasLevel ty u → HasLevel (.letE n ty val body nd md) u - | letE_val {n : m.F Name} {ty val body : KExpr m} {nd : Bool} - {md : ExprInfo m} {u : KUniv m} : - HasLevel val u → HasLevel (.letE n ty val body nd md) u - | letE_body {n : m.F Name} {ty val body : KExpr m} {nd : Bool} - {md : ExprInfo m} {u : KUniv m} : - HasLevel body u → HasLevel (.letE n ty val body nd md) u - | prj {id : KId m} {field : UInt64} {val : KExpr m} {md : ExprInfo m} - {u : KUniv m} : - HasLevel val u → HasLevel (.prj id field val md) u - -/-- Level-side reach set of the instantiation walk on `e`: everything - `substUniv us` can address-compare while rewriting `e`'s levels. - Finite and spec-determined (union of `SubstUnivReach` over the - levels of `e`) — never closed under constructors. -/ -def KExpr.LevelReach {m : Mode} (us : Array (KUniv m)) (e : KExpr m) - (x : KUniv m) : Prop := - ∃ u, KExpr.HasLevel e u ∧ KUniv.SubstUnivReach us u x - -namespace KExpr.LevelReach - -variable {m : Mode} {us : Array (KUniv m)} {x : KUniv m} - -theorem app_f {f a : KExpr m} {md : ExprInfo m} - (h : LevelReach us f x) : LevelReach us (.app f a md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .app_f hu, hr⟩ - -theorem app_a {f a : KExpr m} {md : ExprInfo m} - (h : LevelReach us a x) : LevelReach us (.app f a md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .app_a hu, hr⟩ - -theorem lam_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} - {ty body : KExpr m} {md : ExprInfo m} - (h : LevelReach us ty x) : LevelReach us (.lam n bi ty body md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .lam_ty hu, hr⟩ - -theorem lam_body {n : m.F Name} {bi : m.F Lean.BinderInfo} - {ty body : KExpr m} {md : ExprInfo m} - (h : LevelReach us body x) : - LevelReach us (.lam n bi ty body md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .lam_body hu, hr⟩ - -theorem all_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} - {ty body : KExpr m} {md : ExprInfo m} - (h : LevelReach us ty x) : LevelReach us (.all n bi ty body md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .all_ty hu, hr⟩ - -theorem all_body {n : m.F Name} {bi : m.F Lean.BinderInfo} - {ty body : KExpr m} {md : ExprInfo m} - (h : LevelReach us body x) : - LevelReach us (.all n bi ty body md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .all_body hu, hr⟩ - -theorem letE_ty {n : m.F Name} {ty val body : KExpr m} {nd : Bool} - {md : ExprInfo m} (h : LevelReach us ty x) : - LevelReach us (.letE n ty val body nd md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .letE_ty hu, hr⟩ - -theorem letE_val {n : m.F Name} {ty val body : KExpr m} {nd : Bool} - {md : ExprInfo m} (h : LevelReach us val x) : - LevelReach us (.letE n ty val body nd md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .letE_val hu, hr⟩ - -theorem letE_body {n : m.F Name} {ty val body : KExpr m} {nd : Bool} - {md : ExprInfo m} (h : LevelReach us body x) : - LevelReach us (.letE n ty val body nd md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .letE_body hu, hr⟩ - -theorem prj {id : KId m} {field : UInt64} {val : KExpr m} - {md : ExprInfo m} (h : LevelReach us val x) : - LevelReach us (.prj id field val md) x := - let ⟨u, hu, hr⟩ := h; ⟨u, .prj hu, hr⟩ - -end KExpr.LevelReach - /-! ### `Except`-valued `mapM` decomposition -/ private theorem list_mapM_ok {ε α β : Type _} {f : α → Except ε β} : diff --git a/Ix/Kernel/Verify/UniverseSupport.lean b/Ix/Kernel/Verify/UniverseSupport.lean new file mode 100644 index 000000000..4e63ad9b3 --- /dev/null +++ b/Ix/Kernel/Verify/UniverseSupport.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.InstUniv + +/-! Universe occurrences and finite substitution support shared by the named +translation and the direct set-theoretic refinement. -/ + +namespace Ix.Kernel + +/-! ### Level occurrences and the reach set -/ + +/-- The levels of an expression: `sort` payloads and `const` level + arguments, through all subterms. -/ +inductive KExpr.HasLevel {m : Mode} : KExpr m → KUniv m → Prop + | sort {u : KUniv m} {md : ExprInfo m} : HasLevel (.sort u md) u + | const {id : KId m} {us : Array (KUniv m)} {md : ExprInfo m} + {u : KUniv m} : + u ∈ us → HasLevel (.const id us md) u + | app_f {f a : KExpr m} {md : ExprInfo m} {u : KUniv m} : + HasLevel f u → HasLevel (.app f a md) u + | app_a {f a : KExpr m} {md : ExprInfo m} {u : KUniv m} : + HasLevel a u → HasLevel (.app f a md) u + | lam_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} {ty body : KExpr m} + {md : ExprInfo m} {u : KUniv m} : + HasLevel ty u → HasLevel (.lam n bi ty body md) u + | lam_body {n : m.F Name} {bi : m.F Lean.BinderInfo} + {ty body : KExpr m} {md : ExprInfo m} {u : KUniv m} : + HasLevel body u → HasLevel (.lam n bi ty body md) u + | all_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} {ty body : KExpr m} + {md : ExprInfo m} {u : KUniv m} : + HasLevel ty u → HasLevel (.all n bi ty body md) u + | all_body {n : m.F Name} {bi : m.F Lean.BinderInfo} + {ty body : KExpr m} {md : ExprInfo m} {u : KUniv m} : + HasLevel body u → HasLevel (.all n bi ty body md) u + | letE_ty {n : m.F Name} {ty val body : KExpr m} {nd : Bool} + {md : ExprInfo m} {u : KUniv m} : + HasLevel ty u → HasLevel (.letE n ty val body nd md) u + | letE_val {n : m.F Name} {ty val body : KExpr m} {nd : Bool} + {md : ExprInfo m} {u : KUniv m} : + HasLevel val u → HasLevel (.letE n ty val body nd md) u + | letE_body {n : m.F Name} {ty val body : KExpr m} {nd : Bool} + {md : ExprInfo m} {u : KUniv m} : + HasLevel body u → HasLevel (.letE n ty val body nd md) u + | prj {id : KId m} {field : UInt64} {val : KExpr m} {md : ExprInfo m} + {u : KUniv m} : + HasLevel val u → HasLevel (.prj id field val md) u + +/-- Level-side reach set of the instantiation walk on `e`: everything + `substUniv us` can address-compare while rewriting `e`'s levels. + Finite and spec-determined (union of `SubstUnivReach` over the + levels of `e`) — never closed under constructors. -/ +def KExpr.LevelReach {m : Mode} (us : Array (KUniv m)) (e : KExpr m) + (x : KUniv m) : Prop := + ∃ u, KExpr.HasLevel e u ∧ KUniv.SubstUnivReach us u x + +namespace KExpr.LevelReach + +variable {m : Mode} {us : Array (KUniv m)} {x : KUniv m} + +theorem app_f {f a : KExpr m} {md : ExprInfo m} + (h : LevelReach us f x) : LevelReach us (.app f a md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .app_f hu, hr⟩ + +theorem app_a {f a : KExpr m} {md : ExprInfo m} + (h : LevelReach us a x) : LevelReach us (.app f a md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .app_a hu, hr⟩ + +theorem lam_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} + {ty body : KExpr m} {md : ExprInfo m} + (h : LevelReach us ty x) : LevelReach us (.lam n bi ty body md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .lam_ty hu, hr⟩ + +theorem lam_body {n : m.F Name} {bi : m.F Lean.BinderInfo} + {ty body : KExpr m} {md : ExprInfo m} + (h : LevelReach us body x) : + LevelReach us (.lam n bi ty body md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .lam_body hu, hr⟩ + +theorem all_ty {n : m.F Name} {bi : m.F Lean.BinderInfo} + {ty body : KExpr m} {md : ExprInfo m} + (h : LevelReach us ty x) : LevelReach us (.all n bi ty body md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .all_ty hu, hr⟩ + +theorem all_body {n : m.F Name} {bi : m.F Lean.BinderInfo} + {ty body : KExpr m} {md : ExprInfo m} + (h : LevelReach us body x) : + LevelReach us (.all n bi ty body md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .all_body hu, hr⟩ + +theorem letE_ty {n : m.F Name} {ty val body : KExpr m} {nd : Bool} + {md : ExprInfo m} (h : LevelReach us ty x) : + LevelReach us (.letE n ty val body nd md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .letE_ty hu, hr⟩ + +theorem letE_val {n : m.F Name} {ty val body : KExpr m} {nd : Bool} + {md : ExprInfo m} (h : LevelReach us val x) : + LevelReach us (.letE n ty val body nd md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .letE_val hu, hr⟩ + +theorem letE_body {n : m.F Name} {ty val body : KExpr m} {nd : Bool} + {md : ExprInfo m} (h : LevelReach us body x) : + LevelReach us (.letE n ty val body nd md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .letE_body hu, hr⟩ + +theorem prj {id : KId m} {field : UInt64} {val : KExpr m} + {md : ExprInfo m} (h : LevelReach us val x) : + LevelReach us (.prj id field val md) x := + let ⟨u, hu, hr⟩ := h; ⟨u, .prj hu, hr⟩ + +end KExpr.LevelReach + +end Ix.Kernel + diff --git a/Ix/Theory/Model/LevelCongruence.lean b/Ix/Theory/Model/LevelCongruence.lean new file mode 100644 index 000000000..3662d96b5 --- /dev/null +++ b/Ix/Theory/Model/LevelCongruence.lean @@ -0,0 +1,224 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Judgment + +/-! +# Replacing universe levels by equivalent levels + +Kernel universe substitution uses simplifying constructors. Its result can +therefore differ from structural substitution while denoting the same type. +The relations below retain every term constructor, reference, index, and +binder annotation. Only universe expressions may change, and their values +must agree under every universe valuation. + +This congruence preserves hereditary validity as well as interpretation. +Consequently it transports typing without assuming that an arbitrary +semantically equal expression is a valid type. +-/ + +namespace Ix.Theory + +universe u v +variable {β : Type u} + +namespace VExpr + +/-- Structural equality except for semantically equivalent universe levels. -/ +inductive LevelEquivalent : VExpr β → VExpr β → Prop + | bvar (index) : LevelEquivalent (.bvar index) (.bvar index) + | sort {left right} (levels : left ≈ right) : + LevelEquivalent (.sort left) (.sort right) + | const (ref) {left right} + (levels : ∀ valuation, left.map (VLevel.eval valuation) = + right.map (VLevel.eval valuation)) : + LevelEquivalent (.const ref left) (.const ref right) + | app {f f' a a'} (fn : LevelEquivalent f f') (arg : LevelEquivalent a a') : + LevelEquivalent (.app f a) (.app f' a') + | lam {A A' b b'} (domain : LevelEquivalent A A') (body : LevelEquivalent b b') : + LevelEquivalent (.lam A b) (.lam A' b') + | forallE {A A' B B'} (domain : LevelEquivalent A A') (body : LevelEquivalent B B') : + LevelEquivalent (.forallE A B) (.forallE A' B') + | proj (ref index) {e e'} (major : LevelEquivalent e e') : + LevelEquivalent (.proj ref index e) (.proj ref index e') + | natLit (value) : LevelEquivalent (.natLit value) (.natLit value) + +namespace LevelEquivalent + +theorem refl (e : VExpr β) : LevelEquivalent e e := by + induction e with + | bvar i => exact .bvar i + | sort l => exact .sort (VLevel.equiv_def.mpr fun _ => rfl) + | const r ls => exact .const r fun _ => rfl + | app _ _ hf ha => exact .app hf ha + | lam _ _ hA hb => exact .lam hA hb + | forallE _ _ hA hB => exact .forallE hA hB + | proj r i _ he => exact .proj r i he + | natLit n => exact .natLit n + +theorem liftN {e e' : VExpr β} (h : LevelEquivalent e e') (n k : Nat) : + LevelEquivalent (e.liftN n k) (e'.liftN n k) := by + induction h generalizing k with + | bvar i => exact .bvar _ + | sort h => exact .sort h + | const r h => exact .const r h + | app _ _ hf ha => exact .app (hf k) (ha k) + | lam _ _ hA hb => exact .lam (hA k) (hb (k + 1)) + | forallE _ _ hA hB => exact .forallE (hA k) (hB (k + 1)) + | proj r i _ he => exact .proj r i (he k) + | natLit n => exact .natLit n + +theorem inst {e e' a a' : VExpr β} (h : LevelEquivalent e e') + (ha : LevelEquivalent a a') (k : Nat := 0) : + LevelEquivalent (e.inst a k) (e'.inst a' k) := by + induction h generalizing k with + | bvar i => + by_cases hi : i < k + · simpa [VExpr.inst, instVar, hi] using LevelEquivalent.bvar (β := β) i + · by_cases hik : i = k + · simpa [VExpr.inst, instVar, hi, hik] using ha.liftN k 0 + · simpa [VExpr.inst, instVar, hi, hik] using LevelEquivalent.bvar (β := β) (i - 1) + | sort h => exact .sort h + | const r h => exact .const r h + | app _ _ hf hb => exact .app (hf k) (hb k) + | lam _ _ hA hb => exact .lam (hA k) (hb (k + 1)) + | forallE _ _ hA hB => exact .forallE (hA k) (hB (k + 1)) + | proj r i _ he => exact .proj r i (he k) + | natLit n => exact .natLit n + +end LevelEquivalent + +theorem instL_liftN (e : VExpr β) (levels : List VLevel) (n k : Nat) : + (e.liftN n k).instL levels = (e.instL levels).liftN n k := by + induction e generalizing k <;> simp_all [VExpr.liftN, VExpr.instL] + +theorem instL_inst (e a : VExpr β) (levels : List VLevel) (k : Nat := 0) : + (e.inst a k).instL levels = (e.instL levels).inst (a.instL levels) k := by + induction e generalizing k with + | bvar i => + by_cases hi : i < k + · simp [VExpr.inst, VExpr.instL, instVar, hi] + · by_cases hik : i = k <;> + simp [VExpr.inst, VExpr.instL, instVar, hi, hik, instL_liftN] + | _ => simp_all [VExpr.inst, VExpr.instL] + +/-- The production empty-argument fast path is justified by universe scope. -/ +theorem LevelWF.instL_nil {e : VExpr β} (scope : e.LevelWF 0) : + e.instL [] = e := by + induction e with + | bvar _ | natLit _ => rfl + | sort l => + exact congrArg VExpr.sort (VLevel.inst_id scope) + | const r ls => + simp only [VExpr.instL, VExpr.const.injEq, true_and] + simpa using List.map_congr_left (f := VLevel.inst []) (g := id) + (fun l hl => VLevel.inst_id (scope l hl)) + | app _ _ hf ha => simp only [VExpr.instL, hf scope.1, ha scope.2] + | lam _ _ hA hb => simp only [VExpr.instL, hA scope.1, hb scope.2] + | forallE _ _ hA hB => simp only [VExpr.instL, hA scope.1, hB scope.2] + | proj r i _ he => exact congrArg (VExpr.proj r i) (he scope) + +end VExpr + +namespace Model +namespace AExpr + +/-- Universe congruence with the same binder annotations at every occurrence. -/ +inductive LevelEquivalent : AExpr β → AExpr β → Prop + | bvar (index) : LevelEquivalent (.bvar index) (.bvar index) + | sort {left right} (levels : left ≈ right) : + LevelEquivalent (.sort left) (.sort right) + | const (ref) {left right} + (levels : ∀ valuation, left.map (VLevel.eval valuation) = + right.map (VLevel.eval valuation)) : + LevelEquivalent (.const ref left) (.const ref right) + | app {f f' a a'} (fn : LevelEquivalent f f') (arg : LevelEquivalent a a') : + LevelEquivalent (.app f a) (.app f' a') + | lam (condition) {A A' b b'} + (domain : LevelEquivalent A A') (body : LevelEquivalent b b') : + LevelEquivalent (.lam condition A b) (.lam condition A' b') + | forallE (condition) {A A' B B'} + (domain : LevelEquivalent A A') (body : LevelEquivalent B B') : + LevelEquivalent (.forallE condition A B) (.forallE condition A' B') + | proj (ref index) {e e'} (major : LevelEquivalent e e') : + LevelEquivalent (.proj ref index e) (.proj ref index e') + | natLit (value) : LevelEquivalent (.natLit value) (.natLit value) + +/-- Copy occurrence annotations to a structurally congruent expression. -/ +theorem reannotate_levels (e : AExpr β) {source : VExpr β} + (same : VExpr.LevelEquivalent e.erase source) : + ∃ result : AExpr β, result.erase = source ∧ LevelEquivalent e result := by + induction e generalizing source with + | bvar i => cases same; exact ⟨.bvar i, rfl, .bvar i⟩ + | sort l => cases same with | sort h => exact ⟨.sort _, rfl, .sort h⟩ + | const r ls => cases same with | const _ h => exact ⟨.const r _, rfl, .const r h⟩ + | app f a hf ha => + cases same with + | app sf sa => + obtain ⟨f', rfl, ef⟩ := hf sf + obtain ⟨a', rfl, ea⟩ := ha sa + exact ⟨.app f' a', rfl, .app ef ea⟩ + | lam p A b hA hb => + cases same with + | lam sA sb => + obtain ⟨A', rfl, eA⟩ := hA sA + obtain ⟨b', rfl, eb⟩ := hb sb + exact ⟨.lam p A' b', rfl, .lam p eA eb⟩ + | forallE p A B hA hB => + cases same with + | forallE sA sB => + obtain ⟨A', rfl, eA⟩ := hA sA + obtain ⟨B', rfl, eB⟩ := hB sB + exact ⟨.forallE p A' B', rfl, .forallE p eA eB⟩ + | proj r i e ih => + cases same with + | proj _ _ se => + obtain ⟨e', rfl, ee⟩ := ih se + exact ⟨.proj r i e', rfl, .proj r i ee⟩ + | natLit n => cases same; exact ⟨.natLit n, rfl, .natLit n⟩ + +namespace LevelEquivalent + +theorem interp {e e' : AExpr β} (same : LevelEquivalent e e') + {V : Type v} [SetTheory V] (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) : + Model.interp constants levels env e = Model.interp constants levels env e' := by + induction same generalizing env with + | bvar _ | natLit _ => rfl + | sort h => exact congrArg SetTheory.univ (VLevel.equiv_def.mp h levels) + | const r h => exact congrArg (constants r) (h levels) + | app _ _ hf ha => simp only [Model.interp, hf, ha] + | lam p _ _ hA hb | forallE p _ _ hA hb => + simp only [Model.interp, hA] + congr 1 + funext x + exact hb _ + | proj r i _ he => exact congrArg (projectValue i) (he env) + +theorem wellDenoted {e e' : AExpr β} (same : LevelEquivalent e e') + {V : Type v} [SetTheory V] (constants : Assignment β V) + (levels : List Nat) (env : Nat → V) : + WellDenoted constants levels env e ↔ WellDenoted constants levels env e' := by + induction same generalizing env with + | bvar _ | sort _ | const _ _ | natLit _ => rfl + | app sf sa hf ha => + simp only [WellDenoted, hf, ha, sf.interp constants levels, sa.interp constants levels] + | lam p sA sb hA hb | forallE p sA sb hA hb => + simp only [WellDenoted, hA, hb, sA.interp constants levels, sb.interp constants levels] + | proj r i se he => exact he env + +/-- Type transport uses hereditary validity, not just equality of denotations. -/ +theorem typing {entries : Environment β} {context : Context β} {e A B : AExpr β} + (same : LevelEquivalent A B) (typed : TypingClaim.{u,v} entries context e A) : + TypingClaim.{u,v} entries context e B := by + intro V _ constants realizes levels env valid + obtain ⟨termValid, typeValid, member⟩ := typed V constants realizes levels env valid + exact ⟨termValid, (same.wellDenoted constants levels env).mp typeValid, + same.interp constants levels env ▸ member⟩ + +end LevelEquivalent +end AExpr +end Model +end Ix.Theory diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 03862215f..526856d6d 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -5,9 +5,10 @@ public import Ix.Kernel public import Tests.Ix.Kernel.IxonFixtures /-! -Production regressions for the atomic consistency fragment. These execute -the lazy serial driver on content-addressed Ixon declarations. The fragment's -theorems and resource premises are checked by `IxKernelConsistency`. +Production regressions for the atomic consistency fragment and polymorphic +constant inference. These execute the lazy loader, inference, and serial driver +on content-addressed Ixon declarations. The theorems and their resource +premises are checked separately by `IxKernelConsistency`. -/ namespace Tests.Kernel.Consistency @@ -85,6 +86,96 @@ private def cases : TestSeq := ++ test "atomic fragment: empty input returns an empty successful result" (allSucceeded {} 0) -public def suite : List TestSeq := [cases] +/-- A polymorphic identity axiom with a dependent function type. Inferring its +reference substitutes under binders without invoking binder inference. -/ +private def polymorphicIdentity : Ixon.Env × Address := + storeConst {} + ⟨.axio ⟨false, 1, .leanAll (.sort 0) (.leanAll (.var 0) (.var 1))⟩, + #[], #[], #[.var 0]⟩ + +private def levelOne : KUniv .anon := .mkSucc .mkZero +private def levelTwo : KUniv .anon := .mkSucc levelOne + +private def identityType : KExpr .anon := + .mkAll () () (.mkSort levelOne) (.mkAll () () (.mkVar 0 ()) (.mkVar 1 ())) + +/-- Two occurrences of the same instantiated reference exercise both the +level-argument array and the walker's per-call memo reuse. -/ +private def polymorphicReferences : Ixon.Env × Address × Address := Id.run do + let (env, carrier) := storeConst {} + ⟨.axio ⟨false, 1, .sort 0⟩, #[], #[], #[.var 0]⟩ + let (env, function) := storeConst env + ⟨.axio ⟨false, 1, .leanAll (.ref 0 #[0]) (.ref 0 #[0])⟩, + #[], #[carrier], #[.var 0]⟩ + return (env, function, carrier) + +private def polymorphicLet : Ixon.Env × Address := + storeConst {} + ⟨.axio ⟨false, 1, + .letE false (.sort 1) (.sort 0) (.leanAll (.var 0) (.var 1))⟩, + #[], #[], #[.var 0, .succ (.var 0)]⟩ + +private def simplifyingUniverses : Ixon.Env × Address := + storeConst {} + ⟨.axio ⟨false, 2, .sort 0⟩, #[], #[], + #[.imax (.max (.var 0) (.var 1)) (.var 1)]⟩ + +private def inferStored (fixture : Ixon.Env × Address) (arguments : Array (KUniv .anon)) + (expected : KExpr .anon) (inferOnly := false) (warmIntern := false) : Bool := + let action : TcM .anon (KExpr .anon) := do + if warmIntern then + let _ ← TcM.intern expected + TcM.infer (.mkConst ⟨fixture.2, ()⟩ arguments) + match action { TcState.newLazyAnon fixture.1 with inferOnly } with + | .ok type after => + type.addr == expected.addr && after.env.consts.size > 0 && + (if inferOnly then after.env.inferOnlyCache.size == 1 + else after.env.inferCache.size == 1) + | .error _ _ => false + +private def arityRejected (arguments : Array (KUniv .anon)) : Bool := + match TcM.infer (.mkConst ⟨polymorphicIdentity.2, ()⟩ arguments) + (TcState.newLazyAnon polymorphicIdentity.1) with + | .error (.univParamMismatch expected actual) after => + expected == 1 && actual == arguments.size && after.env.inferCache.isEmpty + | _ => false + +private def polymorphicCases : TestSeq := + test "polymorphic constant: lazy inference substitutes a dependent function type" + (inferStored polymorphicIdentity #[levelOne] identityType) + ++ test "polymorphic constant: inference-only policy records its own cache partition" + (inferStored polymorphicIdentity #[levelOne] identityType true) + ++ test "polymorphic constant: an existing interned result is reused on a cache miss" + (inferStored polymorphicIdentity #[levelOne] identityType false true) + ++ test "polymorphic constant: shared nested references retain their universe arguments" + (let (env, function, carrier) := polymorphicReferences + let type := KExpr.mkConst ⟨carrier, ()⟩ #[levelOne] + inferStored (env, function) #[levelOne] (.mkAll () () type type)) + ++ test "polymorphic constant: substitution preserves let and de Bruijn structure" + (inferStored polymorphicLet #[levelOne] + (.mkLet () (.mkSort levelTwo) (.mkSort levelOne) + (.mkAll () () (.mkVar 0 ()) (.mkVar 1 ())) false)) + ++ test "polymorphic constant: imax with zero simplifies the returned sort" + (inferStored simplifyingUniverses #[levelTwo, .mkZero] (.mkSort .mkZero)) + ++ test "polymorphic constant: swapped universe arguments change imax's result" + (inferStored simplifyingUniverses #[.mkZero, levelTwo] (.mkSort levelTwo)) + ++ test "polymorphic constant: missing universe arguments reject before cache insertion" + (arityRejected #[]) + ++ test "polymorphic constant: excess universe arguments reject before cache insertion" + (arityRejected #[levelOne, levelTwo]) + ++ test "universe instantiation: nonempty arguments reject an out-of-range parameter" + (match TcM.instantiateUnivParams (.mkSort (.mkParam 1 ())) #[.mkZero] + (TcState.ofEnvAnon {}) with + | .error (.univParamOutOfRange index count) _ => index == 1 && count == 1 + | _ => false : Bool) + -- This deliberately invalid input records why the refinement theorem needs + -- declaration scope: the production empty shortcut performs no range check. + ++ test "universe instantiation: empty shortcut requires an external scope invariant" + (match TcM.instantiateUnivParams (.mkSort (.mkParam 0 ())) #[] + (TcState.ofEnvAnon {}) with + | .ok (.sort (.param index _ _) _) _ => index == 0 + | _ => false : Bool) + +public def suite : List TestSeq := [cases, polymorphicCases] end Tests.Kernel.Consistency diff --git a/Tests/Theory/ImportManifest.lean b/Tests/Theory/ImportManifest.lean index 43e9e7b9c..f074c0b9f 100644 --- a/Tests/Theory/ImportManifest.lean +++ b/Tests/Theory/ImportManifest.lean @@ -6,7 +6,8 @@ SPDX-License-Identifier: MIT OR Apache-2.0 /-! Import provenance, recorded from the Lean4Ix working tree on 2026-09-11. The working tree contained the new, uncommitted consistency model; the base revision alone does not identify these inputs. Source hashes identify each file. -The selected file inventory is enforced by `Tests/Theory/Provenance.lean`. +The selected and Ix-authored file inventories are enforced separately by +`Tests/Theory/Provenance.lean`. The generated `Ix/Theory.lean` umbrella records its sole upstream import. -/ namespace Tests.Theory.ImportManifest @@ -14,6 +15,9 @@ namespace Tests.Theory.ImportManifest def lean4IxBaseRevision : String := "ab42e79e2a4e2615a3ca6ef983d510f374057a38" def conLecheRevision : String := "86cd20a65660d757cedc81561a44579099b565d0" +/-- New mathematical modules authored in Ix, with no imported source hash. -/ +def authored : Array String := #["Ix/Theory/Model/LevelCongruence.lean"] + structure SourceFile where source : String target : String diff --git a/Tests/Theory/Provenance.lean b/Tests/Theory/Provenance.lean index b430036a3..0c0c4fc79 100644 --- a/Tests/Theory/Provenance.lean +++ b/Tests/Theory/Provenance.lean @@ -25,15 +25,15 @@ def main (args : List String) : IO Unit := do let actual := ((← (FilePath.mk "Ix/Theory").walkDir).filter (·.extension == some "lean")).map (·.toString) let named := actual.filter (·.startsWith "Ix/Theory/Named/") sameFiles ((actual.filter (!·.startsWith "Ix/Theory/Named/")).push "Ix/Theory.lean") - (selected.map (·.target)) + (selected.map (·.target) ++ authored) sameFiles named ((Tests.Theory.NamedManifest.selected.map (·.target)).push "Ix/Theory/Named/Std/AxiomAudit.lean") need (← (FilePath.mk "Ix/Theory/Named/LICENSE").pathExists) "missing named-specification Apache license" need (← (FilePath.mk "Ix/Theory/Named/NOTICE").pathExists) "missing named-specification attribution" - for row in selected do - let contents ← IO.FS.readFile row.target + for path in selected.map (·.target) ++ authored do + let contents ← IO.FS.readFile path need (!(contents.contains "import Ix.Theory.Named")) - s!"set-model foundation depends on named checker proof support: {row.target}" + s!"set-model foundation depends on named checker proof support: {path}" let mut ports := #[] for directory in ["Ix/Theory/Model/SetTheory", "Ix/Theory/Model/SetModel"] do ports := ports ++ ((← (FilePath.mk directory).walkDir).filter (·.extension == some "lean")).map (·.toString) @@ -53,5 +53,5 @@ def main (args : List String) : IO Unit := do handle.putStr blob.stdout handle.flush need ((← sha256 path) == row.sourceSha256) s!"con-leche upstream hash mismatch: {row.source}" - IO.println s!"Theory provenance OK: {selected.size} selected source files; {conLeche.size} con-leche ports, exact content and notices." + IO.println s!"Theory provenance OK: {selected.size} selected source files; {authored.size} Ix-authored modules; {conLeche.size} con-leche ports, exact content and notices." IO.println s!"Named proof support: {named.size} local source files; separate from the set-model foundation." diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 820c8ed0d..c1a069d4c 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -37,6 +37,18 @@ increasing sequence of strongly inaccessible cardinals. - `inferUncached_sort_sound` interprets an actual successful execution of the production sort-inference branch. It proves the model typing postcondition for the returned type, including intern-table reuse. +- `instantiateUnivParams_readAnnotated` connects the actual memoized universe + substitution walker to model substitution for every readable expression. + Simplifying `max` and `imax` may change the returned syntax; the proof + preserves both interpretation and hereditary validity, including beneath + binders and through let substitution. The empty-argument shortcut is + justified by the source type's universe scope. +- `inferUncached_const_sound` and `infer_const_sound` derive model typing for + polymorphic constant references with arbitrary readable declaration types. + Production success supplies the universe-arity check. The premises retain + a well-formed model interface, agreement with the actual lazy-loaded + declaration, finite interning and level-substitution resources, and (for + `infer`) misses in both cache partitions at the computed key. - `ModelTyping.no_false` rules out a closed model-typed kernel expression at primitive False when its environment has been admitted by the certified interface and the set-theory assumption has an instance. @@ -96,8 +108,10 @@ the run. They supply no typing or checker-soundness premise. The proof extracts the validation, type-inference, theorem-guard, value-inference, and conversion steps from public success, then derives body typing to extend the preceding model. Automatic witness construction, lambdas, applications, -polymorphic instantiation, inductives, coordinated blocks, and other conversion -paths remain outside the fragment. +inductives, coordinated blocks, and other conversion paths remain outside the +fragment. The polymorphic constant-inference theorem above is a separate proof +increment; composing it into general declaration admission and environment +model extension remains to be done. `checkEnvAnon_atomic_represents_source` ties every source address to an interface with the type and body reached by production lookup. The independent @@ -148,7 +162,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 36 exact theorem boundaries. The production +The consistency target checks 51 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -158,6 +172,13 @@ The production roots additionally forbid the abstract `CheckSuccessSound`/`SupportedCheckFragment` interfaces and the independent certificate validator in their dependency closures. +The polymorphic inference and substitution roots retain only the two existing +expression/universe output-length proofs, alongside the standard Lean axioms. +Their model-side level congruence introduces no native proof dependency. +Kernel unit regressions cover lazy loading, both inference policies, interning +reuse, dependent function types, shared references, lets, `imax` simplification, +argument order, and rejection of wrong arities and out-of-range parameters. + ## Certified host adapters The certified source and claim adapters are maintained under @@ -182,6 +203,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | --- | --- | | Certified checker contracts | [`Ix/Kernel/Certified.lean`](../Ix/Kernel/Certified.lean), [`CertifiedClaims.lean`](../Ix/Kernel/CertifiedClaims.lean) | | Direct production refinement and its audit | [`Ix/Kernel/Verify/Consistency.lean`](../Ix/Kernel/Verify/Consistency.lean) | +| Polymorphic inference and universe substitution | [`Consistency/Constant.lean`](../Ix/Kernel/Verify/Consistency/Constant.lean), [`InstUniv.lean`](../Ix/Kernel/Verify/Consistency/InstUniv.lean), [`Model/LevelCongruence.lean`](../Ix/Theory/Model/LevelCongruence.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | | Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | @@ -195,3 +217,5 @@ fixtures used by the existing proofs. Source hashes and attribution are in [`Tests/Theory/NamedManifest.lean`](../Tests/Theory/NamedManifest.lean); the Apache license is preserved alongside the sources. The axiom-audit helper and direct production-fragment proofs are authored in Ix. +`Model/LevelCongruence.lean` is an Ix-authored mathematical addition, listed +separately from the imported files in the theory provenance manifest. From ec40b6fc3dcfc3bf3846507140d97bf252e11474 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 11:08:34 -0400 Subject: [PATCH 07/30] Extend production environment consistency to polymorphic specializations --- Ix/Kernel/Verify/Consistency.lean | 11 +- Ix/Kernel/Verify/Consistency/Audit.lean | 21 ++- Ix/Kernel/Verify/Consistency/Constant.lean | 70 +++++++-- Ix/Kernel/Verify/Consistency/Environment.lean | 8 +- Ix/Kernel/Verify/Consistency/InstUniv.lean | 138 +++++++++++++++--- Ix/Kernel/Verify/Consistency/Production.lean | 77 ++++++++-- Ix/Theory/Model/LevelCongruence.lean | 123 ++++++++++++++++ Tests/Ix/Kernel/Consistency.lean | 64 +++++++- docs/kernel-verification.md | 39 +++-- docs/theory.md | 5 +- 10 files changed, 490 insertions(+), 66 deletions(-) diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 121f7e437..447f78de8 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -20,9 +20,10 @@ import Ix.Kernel.Verify.Consistency.Audit This library connects production kernel operations to `Ix.Theory`. Each transport keeps its representation, arithmetic, and dependency assumptions explicit. A production `checkEnvAnon` fragment preserves models of its -axiom set for monomorphic aliases and closed sorts under the stated execution -resources. General checker soundness remains outside this fragment. -Separately, polymorphic constant inference refines the model for arbitrary -readable entry types, using the actual universe-instantiation walker and -explicit lookup, scope, and finite-support resources. +axiom set for monomorphic aliases, closed sorts, and monomorphic +specializations of polymorphic constants under the stated execution resources. +Constant inference supports arbitrary readable entry types, using the actual +universe-instantiation walker and explicit lookup and finite-support resources. +The returned type's scope and references justify declaration admission. +General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index f9e0c91f6..944c66c80 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -35,12 +35,16 @@ private def productionNative : Array Lean.Name := #[ private def atomicRoots : Array Lean.Name := #[ ``infer_uncached_success, ``AtomicInferenceSupport.typing, ``AtomicInferenceSupport.reads, ``AtomicInferenceSupport.output, - ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound + ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound, + ``DefinitionBodySupport.sound ] private def instantiationRoots : Array Lean.Name := #[ - ``instUnivSpec_readExpr?, ``instantiateUnivParams_readExpr?, - ``instantiateUnivParams_readAnnotated, ``inferUncached_const_sound, ``infer_const_sound + ``instUnivSpec_readExpr?, ``instUnivSpec_readExpr?_withScope, + ``instantiateUnivParams_readExpr?, ``instantiateUnivParams_readAnnotated, + ``instantiateUnivParams_readAnnotated_scoped, + ``inferUncached_const_refinement, ``infer_const_refinement, + ``inferUncached_const_sound, ``infer_const_sound ] private def productionRoots : Array Lean.Name := #[ @@ -84,13 +88,24 @@ def roots : Array RootAllowance := #[ { root := ``sort_conversion, standardAxioms := standard }, { root := ``inferUncached_sort_sound, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative] }, + { root := ``Theory.VExpr.LevelWF.liftN, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``Theory.VExpr.LevelWF.inst, standardAxioms := #[``propext, ``Quot.sound] }, { root := ``Theory.VExpr.LevelEquivalent.refl, standardAxioms := #[``propext, ``Quot.sound] }, { root := ``Theory.VExpr.LevelEquivalent.liftN, standardAxioms := #[``propext] }, { root := ``Theory.VExpr.LevelEquivalent.inst, standardAxioms := #[``propext] }, { root := ``Theory.VExpr.instL_liftN, standardAxioms := #[``propext] }, { root := ``Theory.VExpr.instL_inst, standardAxioms := #[``propext] }, { root := ``Theory.VExpr.LevelWF.instL_nil, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``Theory.Model.AExpr.eq_of_erase_annotations, standardAxioms := #[``propext] }, + { root := ``Theory.Model.AExpr.Scope.instL, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``Theory.Model.AExpr.references_instL, standardAxioms := #[``propext, ``Quot.sound] }, { root := ``Theory.Model.AExpr.reannotate_levels, standardAxioms := #[``propext] }, + { root := ``Theory.Model.AExpr.LevelEquivalent.annotations, standardAxioms := #[``propext] }, + { root := ``Theory.Model.AExpr.LevelEquivalent.erase, standardAxioms := #[``propext] }, + { root := ``Theory.Model.AExpr.LevelEquivalent.scope, standardAxioms := #[``propext] }, + { root := ``Theory.Model.AExpr.LevelEquivalent.references, standardAxioms := #[``propext] }, + { root := ``Theory.Model.AExpr.LevelEquivalent.of_erase_annotations, + standardAxioms := #[``propext] }, { root := ``Theory.Model.AExpr.LevelEquivalent.interp, standardAxioms := standard }, { root := ``Theory.Model.AExpr.LevelEquivalent.wellDenoted, standardAxioms := standard }, { root := ``Theory.Model.AExpr.LevelEquivalent.typing, standardAxioms := standard } diff --git a/Ix/Kernel/Verify/Consistency/Constant.lean b/Ix/Kernel/Verify/Consistency/Constant.lean index babefe0b4..6b2a3b297 100644 --- a/Ix/Kernel/Verify/Consistency/Constant.lean +++ b/Ix/Kernel/Verify/Consistency/Constant.lean @@ -39,12 +39,11 @@ structure ConstantInferenceSupport {β : Type u} readExpr? resolve concrete.ty = some entry.type.erase ∧ UniverseInstantiationSupport loaded concrete.ty arguments -/-- A successful uncached production branch types its exact returned tree in -every model of the preceding interface. The runtime guard establishes arity; -the model environment's well-formedness supplies the declaration type's scope. -/ -theorem inferUncached_const_sound {β : Type u} +/-- Refine the returned type, including its arity, scope, and references. +The only scope premise concerns the preceding interface and actual arguments. -/ +theorem inferUncached_const_refinement {β : Type u} {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} - {context : Model.Context β} {id : KId .anon} {arguments : Array (KUniv .anon)} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} @@ -52,7 +51,11 @@ theorem inferUncached_const_sound {β : Type u} (wellFormed : entries.WF) (accepted : RecM.inferUncached inferRec inferOnly (.const id arguments info) methods before = .ok type after) : - ModelTyping.{u,v} resolve entries context (.const id arguments info) type := by + ∃ output : AExpr β, readExpr? resolve type = some output.erase ∧ + AExpr.LevelEquivalent (entry.type.instL (arguments.toList.map readLevel)) output ∧ + (arguments.toList.map readLevel).length = entry.universes ∧ + (∀ n, (∀ level ∈ arguments, (readLevel level).WF n) → output.Scope n 0) ∧ + output.references = entry.type.references := by change (RecM.inferUncached inferRec inferOnly (.const id arguments info)).run methods before = .ok type after at accepted unfold RecM.inferUncached at accepted @@ -68,18 +71,61 @@ theorem inferUncached_const_sound {β : Type u} change TcM.instantiateUnivParams concrete.ty arguments loaded = .ok type after at accepted have length : (arguments.toList.map readLevel).length = entry.universes := by simpa only [List.length_map, Array.length_toList] using arity.symm.trans count - have scope : entry.type.erase.LevelWF arguments.size := by + have scope : entry.type.Scope arguments.size 0 := by rw [← arity, count] - exact (wellFormed.typeScope ref entry support.found).erase.1 + exact wellFormed.typeScope ref entry support.found obtain ⟨output, outputReads, same⟩ := - instantiateUnivParams_readAnnotated resources scope reading accepted - refine ⟨.const ref (arguments.toList.map readLevel), output, ?_, outputReads, - same.typing (TypingClaim.const support.found length)⟩ - simp [readExpr?, support.resolved, AExpr.erase] + instantiateUnivParams_readAnnotated resources scope.erase.1 reading accepted + refine ⟨output, outputReads, same, length, ?_, + same.references.symm.trans (AExpr.references_instL entry.type _)⟩ + intro n argumentsWF + obtain ⟨closedOutput, scopedReads, scopedSame, scopedWF, _⟩ := + instantiateUnivParams_readAnnotated_scoped resources scope argumentsWF reading accepted + have equal := AExpr.eq_of_erase_annotations + (Option.some.inj (scopedReads.symm.trans outputReads)) + (scopedSame.annotations.symm.trans same.annotations) + exact equal ▸ scopedWF · simp only [bne_iff_ne] at accepted rw [if_pos arity] at accepted contradiction +/-- A successful uncached production branch types its exact returned tree in +every model of the preceding interface. The runtime guard establishes arity. -/ +theorem inferUncached_const_sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {context : Model.Context β} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} + (support : ConstantInferenceSupport resolve entries before id arguments ref entry) + (wellFormed : entries.WF) + (accepted : RecM.inferUncached inferRec inferOnly (.const id arguments info) + methods before = .ok type after) : + ModelTyping.{u,v} resolve entries context (.const id arguments info) type := by + obtain ⟨output, reads, same, length, _, _⟩ := + inferUncached_const_refinement support wellFormed accepted + refine ⟨.const ref (arguments.toList.map readLevel), output, ?_, reads, + same.typing (TypingClaim.const support.found length)⟩ + simp [readExpr?, support.resolved, AExpr.erase] + +/-- The same structural refinement through the ordinary inference entry point. -/ +theorem infer_const_refinement {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} + {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} + (miss : UncachedInference before (.const id arguments info)) + (support : ConstantInferenceSupport resolve entries miss.keyed id arguments ref entry) + (wellFormed : entries.WF) + (accepted : RecM.infer (.const id arguments info) methods before = .ok type after) : + ∃ output : AExpr β, readExpr? resolve type = some output.erase ∧ + AExpr.LevelEquivalent (entry.type.instL (arguments.toList.map readLevel)) output ∧ + (arguments.toList.map readLevel).length = entry.universes ∧ + (∀ n, (∀ level ∈ arguments, (readLevel level).WF n) → output.Scope n 0) ∧ + output.references = entry.type.references := by + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + exact inferUncached_const_refinement support wellFormed run + /-- The ordinary production inference entry point, including its actual key lookup and final cache write, refines polymorphic constant typing on misses. -/ theorem infer_const_sound {β : Type u} diff --git a/Ix/Kernel/Verify/Consistency/Environment.lean b/Ix/Kernel/Verify/Consistency/Environment.lean index 9569ef804..1456669ce 100644 --- a/Ix/Kernel/Verify/Consistency/Environment.lean +++ b/Ix/Kernel/Verify/Consistency/Environment.lean @@ -289,19 +289,21 @@ private theorem AtomicDefinitionPlan.locations {β : Type u} [DecidableEq β] exact ⟨position, ⟨run.path⟩⟩ · exact ih candidate later -/-- An axiom has no value or computational equations in the initial model. -/ +/-- An axiom retains its declared universe arity and has no value or +computational equations in the initial model. -/ structure AxiomSpec (β : Type u) where id : KId .anon ref : ConstRef β isUnsafe : Bool + universes : UInt64 := 0 sourceType : KExpr .anon type : AExpr β def AxiomSpec.constant {β : Type u} (spec : AxiomSpec β) : KConst .anon := - .axio () () spec.isUnsafe 0 spec.sourceType + .axio () () spec.isUnsafe spec.universes spec.sourceType def AxiomSpec.entry {β : Type u} (spec : AxiomSpec β) : ConstantEntry β := - { universes := 0, type := spec.type, body := none } + { universes := spec.universes.toNat, type := spec.type, body := none } /-- Exactly the declared axiom interface, starting with no other entries. -/ def axiomEnvironment {β : Type u} [DecidableEq β] : List (AxiomSpec β) → Model.Environment β diff --git a/Ix/Kernel/Verify/Consistency/InstUniv.lean b/Ix/Kernel/Verify/Consistency/InstUniv.lean index f945aa0d2..2381f2840 100644 --- a/Ix/Kernel/Verify/Consistency/InstUniv.lean +++ b/Ix/Kernel/Verify/Consistency/InstUniv.lean @@ -94,6 +94,37 @@ private theorem array_substUniv_readLevels {arguments levels results : Array (KU (fun level member => faithful level (by simpa using member)) (fun level member => bounded level (by simpa using member)) +private theorem substUniv_readLevel_wf {arguments : Array (KUniv .anon)} {n : Nat} + (argumentsWF : ∀ level ∈ arguments, (readLevel level).WF n) + {level result : KUniv .anon} (run : TcM.substUniv level arguments = .ok result) : + (readLevel result).WF n := by + simpa only [readLevel_eq] using TcM.substUniv_wf + (fun level member => readLevel_eq level ▸ argumentsWF level member) run + +private theorem list_substUniv_readLevels_wf {arguments : Array (KUniv .anon)} {n : Nat} + (argumentsWF : ∀ level ∈ arguments, (readLevel level).WF n) : + ∀ {levels results : List (KUniv .anon)}, + levels.mapM (TcM.substUniv · arguments) = .ok results → + ∀ result ∈ results, (readLevel result).WF n := by + intro levels + induction levels with + | nil => intro results run; cases run; simp + | cons level rest ih => + intro results run + rw [List.mapM_cons] at run + cases first : TcM.substUniv level arguments with + | error err => rw [first] at run; contradiction + | ok result => + cases tail : rest.mapM (TcM.substUniv · arguments) with + | error err => rw [first, tail] at run; contradiction + | ok remaining => + rw [first, tail] at run + cases run + intro value member + rcases List.mem_cons.mp member with rfl | member + · exact substUniv_readLevel_wf argumentsWF first + · exact ih tail value member + private theorem except_bind_success {ε α γ : Type _} {action : Except ε α} {next : α → Except ε γ} {result : γ} (run : action.bind next = .ok result) : ∃ intermediate, action = .ok intermediate ∧ next intermediate = .ok result := by @@ -111,23 +142,24 @@ private theorem option_bind_success {α γ : Type _} {action : Option α} /-- Successful pure instantiation reads as model substitution, up to equivalent universe levels. All expression positions are covered; the reader's existing exclusions of free variables, strings, and unresolved references are retained. -/ -theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} +theorem instUnivSpec_readExpr?_withScope {resolve : Address → Option (ConstRef β)} {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : VExpr β} (support : UniverseSubstitutionSupport arguments term) (reading : readExpr? resolve term = some source) (run : KExpr.instUnivSpec term arguments = .ok result) : ∃ output, readExpr? resolve result = some output ∧ - VExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output := by + VExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output ∧ + ∀ n, (∀ level ∈ arguments, (readLevel level).WF n) → output.LevelWF n := by induction term generalizing source result with | var index name info => cases run cases reading - exact ⟨_, rfl, .bvar _⟩ + exact ⟨_, rfl, .bvar _, fun _ _ => trivial⟩ | fvar _ _ _ | str _ _ _ => contradiction | nat value name info => cases run cases reading - exact ⟨_, rfl, .natLit _⟩ + exact ⟨_, rfl, .natLit _, fun _ _ => trivial⟩ | sort level info => cases reading rw [KExpr.instUnivSpec] at run @@ -136,7 +168,8 @@ theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} exact ⟨_, rfl, .sort (substUniv_readLevel substituted (fun left right hl hr => support.faithful left right ⟨level, .sort, hl⟩ ⟨level, .sort, hr⟩) - (fun value hv => support.bounded value ⟨level, .sort, hv⟩))⟩ + (fun value hv => support.bounded value ⟨level, .sort, hv⟩)), + fun _ argumentsWF => substUniv_readLevel_wf argumentsWF substituted⟩ | const id levels info => cases resolved : resolve id.addr with | none => simp [readExpr?, resolved] at reading @@ -146,13 +179,18 @@ theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} rw [KExpr.instUnivSpec] at run obtain ⟨values, substituted, run⟩ := except_bind_success run cases run - refine ⟨.const ref (values.toList.map readLevel), ?_, .const ref ?_⟩ + refine ⟨.const ref (values.toList.map readLevel), ?_, .const ref ?_, ?_⟩ · change readExpr? resolve (.const id values _) = _ simp [readExpr?, resolved] · exact array_substUniv_readLevels substituted (fun level member left right hl hr => support.faithful left right ⟨level, .const member, hl⟩ ⟨level, .const member, hr⟩) (fun level member value hv => support.bounded value ⟨level, .const member, hv⟩) + · intro n argumentsWF level member + obtain ⟨value, valueMember, rfl⟩ := List.mem_map.mp member + have listRun : levels.toList.mapM (TcM.substUniv · arguments) = + .ok values.toList := by rw [← Array.toList_mapM, substituted]; rfl + exact list_substUniv_readLevels_wf argumentsWF listRun value valueMember | app fn arg info hf ha => rw [readExpr?] at reading obtain ⟨f, fReads, reading⟩ := option_bind_success reading @@ -162,13 +200,14 @@ theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} obtain ⟨f', fRun, run⟩ := except_bind_success run obtain ⟨a', aRun, run⟩ := except_bind_success run cases run - obtain ⟨vf, vfReads, vfSame⟩ := hf + obtain ⟨vf, vfReads, vfSame, vfWF⟩ := hf ⟨fun x y hx hy => support.faithful x y hx.app_f hy.app_f, fun x hx => support.bounded x hx.app_f⟩ fReads fRun - obtain ⟨va, vaReads, vaSame⟩ := ha + obtain ⟨va, vaReads, vaSame, vaWF⟩ := ha ⟨fun x y hx hy => support.faithful x y hx.app_a hy.app_a, fun x hx => support.bounded x hx.app_a⟩ aReads aRun - refine ⟨.app vf va, ?_, .app vfSame vaSame⟩ + refine ⟨.app vf va, ?_, .app vfSame vaSame, + fun n h => ⟨vfWF n h, vaWF n h⟩⟩ change readExpr? resolve (.app f' a' _) = _ simp [readExpr?, vfReads, vaReads] | lam name bi domain body info hA hb => @@ -180,13 +219,14 @@ theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} obtain ⟨A', aRun, run⟩ := except_bind_success run obtain ⟨b', bRun, run⟩ := except_bind_success run cases run - obtain ⟨vA, vAReads, vASame⟩ := hA + obtain ⟨vA, vAReads, vASame, vAWF⟩ := hA ⟨fun x y hx hy => support.faithful x y hx.lam_ty hy.lam_ty, fun x hx => support.bounded x hx.lam_ty⟩ aReads aRun - obtain ⟨vb, vbReads, vbSame⟩ := hb + obtain ⟨vb, vbReads, vbSame, vbWF⟩ := hb ⟨fun x y hx hy => support.faithful x y hx.lam_body hy.lam_body, fun x hx => support.bounded x hx.lam_body⟩ bReads bRun - refine ⟨.lam vA vb, ?_, .lam vASame vbSame⟩ + refine ⟨.lam vA vb, ?_, .lam vASame vbSame, + fun n h => ⟨vAWF n h, vbWF n h⟩⟩ change readExpr? resolve (.lam name bi A' b' _) = _ simp [readExpr?, vAReads, vbReads] | all name bi domain body info hA hb => @@ -198,13 +238,14 @@ theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} obtain ⟨A', aRun, run⟩ := except_bind_success run obtain ⟨b', bRun, run⟩ := except_bind_success run cases run - obtain ⟨vA, vAReads, vASame⟩ := hA + obtain ⟨vA, vAReads, vASame, vAWF⟩ := hA ⟨fun x y hx hy => support.faithful x y hx.all_ty hy.all_ty, fun x hx => support.bounded x hx.all_ty⟩ aReads aRun - obtain ⟨vb, vbReads, vbSame⟩ := hb + obtain ⟨vb, vbReads, vbSame, vbWF⟩ := hb ⟨fun x y hx hy => support.faithful x y hx.all_body hy.all_body, fun x hx => support.bounded x hx.all_body⟩ bReads bRun - refine ⟨.forallE vA vb, ?_, .forallE vASame vbSame⟩ + refine ⟨.forallE vA vb, ?_, .forallE vASame vbSame, + fun n h => ⟨vAWF n h, vbWF n h⟩⟩ change readExpr? resolve (.all name bi A' b' _) = _ simp [readExpr?, vAReads, vbReads] | letE name domain value body nonDep info hA hv hb => @@ -218,16 +259,16 @@ theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} obtain ⟨v', vRun, run⟩ := except_bind_success run obtain ⟨b', bRun, run⟩ := except_bind_success run cases run - obtain ⟨vA, vAReads, _⟩ := hA + obtain ⟨vA, vAReads, _, _⟩ := hA ⟨fun x y hx hy => support.faithful x y hx.letE_ty hy.letE_ty, fun x hx => support.bounded x hx.letE_ty⟩ aReads aRun - obtain ⟨vv, vvReads, vvSame⟩ := hv + obtain ⟨vv, vvReads, vvSame, vvWF⟩ := hv ⟨fun x y hx hy => support.faithful x y hx.letE_val hy.letE_val, fun x hx => support.bounded x hx.letE_val⟩ valueReads vRun - obtain ⟨vb, vbReads, vbSame⟩ := hb + obtain ⟨vb, vbReads, vbSame, vbWF⟩ := hb ⟨fun x y hx hy => support.faithful x y hx.letE_body hy.letE_body, fun x hx => support.bounded x hx.letE_body⟩ bodyReads bRun - refine ⟨vb.inst vv, ?_, ?_⟩ + refine ⟨vb.inst vv, ?_, ?_, fun n h => (vbWF n h).inst (vvWF n h)⟩ · change readExpr? resolve (.letE name A' v' b' nonDep _) = _ simp [readExpr?, vAReads, vvReads, vbReads] · rw [VExpr.instL_inst] @@ -244,13 +285,24 @@ theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} rw [KExpr.instUnivSpec] at run obtain ⟨value', valueRun, run⟩ := except_bind_success run cases run - obtain ⟨output, outputReads, outputSame⟩ := ih + obtain ⟨output, outputReads, outputSame, outputWF⟩ := ih ⟨fun x y hx hy => support.faithful x y hx.prj hy.prj, fun x hx => support.bounded x hx.prj⟩ sourceReads valueRun - refine ⟨.proj ref index.toNat output, ?_, .proj ref index.toNat outputSame⟩ + refine ⟨.proj ref index.toNat output, ?_, .proj ref index.toNat outputSame, outputWF⟩ change readExpr? resolve (.prj id index value' _) = _ simp [readExpr?, resolved, outputReads] +/-- The unscoped refinement remains useful in arbitrary inference contexts. -/ +theorem instUnivSpec_readExpr? {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : VExpr β} + (support : UniverseSubstitutionSupport arguments term) + (reading : readExpr? resolve term = some source) + (run : KExpr.instUnivSpec term arguments = .ok result) : + ∃ output, readExpr? resolve result = some output ∧ + VExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output := by + obtain ⟨output, reads, same, _⟩ := instUnivSpec_readExpr?_withScope support reading run + exact ⟨output, reads, same⟩ + /-- Runtime resources for the memoized walker, all on its actual finite support. -/ structure UniverseInstantiationSupport (before : TcState .anon) (term : KExpr .anon) (arguments : Array (KUniv .anon)) : Prop where @@ -302,4 +354,48 @@ theorem instantiateUnivParams_readAnnotated {resolve : Address → Option (Const obtain ⟨output, erased, equivalent⟩ := AExpr.reannotate_levels _ same exact ⟨output, erased ▸ rawReads, equivalent⟩ +/-- Scope and dependencies of the actual returned annotated type. Nonempty +substitution checks every source parameter; the empty shortcut uses source +scope. Neither syntactic property follows from semantic equivalence alone. -/ +theorem instantiateUnivParams_readAnnotated_scoped + {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : AExpr β} + {before after : TcState .anon} {n depth : Nat} + (support : UniverseInstantiationSupport before term arguments) + (scope : source.Scope arguments.size depth) + (argumentsWF : ∀ level ∈ arguments, (readLevel level).WF n) + (reading : readExpr? resolve term = some source.erase) + (run : TcM.instantiateUnivParams term arguments before = .ok result after) : + ∃ output : AExpr β, readExpr? resolve result = some output.erase ∧ + AExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output ∧ + output.Scope n depth ∧ output.references = source.references := by + obtain ⟨output, reads, same⟩ := + instantiateUnivParams_readAnnotated support scope.erase.1 reading run + have args : ∀ level ∈ arguments.toList.map readLevel, level.WF n := by + intro level member + obtain ⟨value, valueMember, rfl⟩ := List.mem_map.mp member + exact argumentsWF value (by simpa using valueMember) + have outputWF : output.erase.LevelWF n := by + have post := TcM.instantiateUnivParams_wf support.faithful + (fun _ h => Or.inr h) ⟨support.coherent, fun _ h => Or.inl h⟩ + rw [run] at post + have spec := post.2.1 + by_cases empty : arguments.isEmpty = true + · have emptyArgs : arguments = #[] := Array.isEmpty_iff.mp empty + subst arguments + change Except.ok term = .ok result at spec + cases spec + have equal := Option.some.inj (reads.symm.trans reading) + rw [equal] + have substituted := (scope.instL args).erase.1 + simpa only [AExpr.erase_instL, Array.toList_empty, List.map_nil, + scope.erase.1.instL_nil] using substituted + · rw [KExpr.instantiateUnivParamsSpec, if_neg empty] at spec + obtain ⟨raw, rawReads, _, rawWF⟩ := + instUnivSpec_readExpr?_withScope support.levels reading spec + have equal := Option.some.inj (reads.symm.trans rawReads) + exact equal ▸ rawWF n argumentsWF + exact ⟨output, reads, same, same.scope (scope.instL args) outputWF, + same.references.symm.trans (AExpr.references_instL source _)⟩ + end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Production.lean b/Ix/Kernel/Verify/Consistency/Production.lean index b48ea8f97..0ae6cc111 100644 --- a/Ix/Kernel/Verify/Consistency/Production.lean +++ b/Ix/Kernel/Verify/Consistency/Production.lean @@ -4,7 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Driver -import Ix.Kernel.Verify.Consistency.Atomic +import Ix.Kernel.Verify.Consistency.Constant /-! # Standalone production declaration checks @@ -97,6 +97,68 @@ structure DefinitionInput where def DefinitionInput.constant (input : DefinitionInput) : KConst .anon := .defn () () input.kind input.safety input.hints 0 input.type input.value () input.block +/-- Closed sort/alias inference, or a specialization of an existing constant. +The declared type supplies only raw syntax and occurrence annotations. Its +typing, scope, and references are derived from successful production inference. -/ +inductive DefinitionBodySupport {β : Type u} + (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) + (before : TcState .anon) (declared : KExpr .anon) : + KExpr .anon → AExpr β → AExpr β → Type u + | atomic {term : KExpr .anon} {body type : AExpr β} + (inference : AtomicInference resolve entries before term body type) : + DefinitionBodySupport resolve entries before declared term body type + | specialization {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + (misses : UncachedInference before (.const id arguments info)) + (support : ConstantInferenceSupport resolve entries misses.keyed id arguments ref entry) + (closed : ∀ level ∈ arguments, (readLevel level).WF 0) + (reading : readExpr? resolve declared = some type.erase) + (conditions : (entry.type.instL (arguments.toList.map readLevel)).annotations = + type.annotations) : + DefinitionBodySupport resolve entries before declared (.const id arguments info) + (.const ref (arguments.toList.map readLevel)) type + +theorem DefinitionBodySupport.sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {before after : TcState .anon} {term declared inferred : KExpr .anon} + {body type : AExpr β} {methods : Methods .anon} + (fragment : DefinitionBodySupport resolve entries before declared term body type) + (wellFormed : entries.WF) + (accepted : RecM.infer term methods before = .ok inferred after) + (faithful : inferred.AddrFaithful declared) (hashPath : (inferred == declared) = true) : + readExpr? resolve term = some body.erase ∧ + readExpr? resolve declared = some type.erase ∧ + body.Scope 0 0 ∧ type.Scope 0 0 ∧ + body.ReferencesIn entries ∧ type.ReferencesIn entries ∧ + TypingClaim.{u,v} entries [] body type := by + have hashReads := beq_readExpr? (resolve := resolve) faithful hashPath + cases fragment with + | atomic inference => + obtain ⟨valueReads, typeReads, typed⟩ := inference.sound accepted + obtain ⟨bodyScope, typeScope, bodyRefs, typeRefs⟩ := + inference.support.scopeAndReferences wellFormed + exact ⟨valueReads, hashReads.symm.trans typeReads, + bodyScope, typeScope, bodyRefs, typeRefs, typed⟩ + | specialization misses support closed reading conditions => + obtain ⟨output, reads, same, arity, scope, references⟩ := + infer_const_refinement misses support wellFormed accepted + have equal := AExpr.eq_of_erase_annotations + (Option.some.inj (reads.symm.trans (hashReads.trans reading))) + (same.annotations.symm.trans conditions) + refine ⟨?_, reading, ?_, equal ▸ scope 0 closed, ?_, ?_, + equal ▸ same.typing (TypingClaim.const support.found arity)⟩ + · simp [readExpr?, support.resolved, AExpr.erase] + · intro level member + obtain ⟨value, valueMember, rfl⟩ := List.mem_map.mp member + exact closed value (by simpa using valueMember) + · intro ref member + simp only [AExpr.references, List.mem_singleton] at member + subst ref + simp only [support.found, Option.isSome_some] + · intro ref member + rw [← equal, references] at member + exact wellFormed.typeReferences _ _ support.found ref member + /-- The execution prefix through value conversion. A successful member check also passes the subsequent safety checks. -/ structure DefinitionBodyTrace (input : DefinitionInput) (methods : Methods .anon) @@ -162,7 +224,7 @@ structure AtomicDefinitionRun {β : Type u} (resolve : Address → Option (Const (body type : AExpr β) where path : StandalonePrefix input.id before input.constant inference : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, - AtomicInference resolve entries trace.valueStart input.value body type + DefinitionBodySupport resolve entries trace.valueStart input.type input.value body type hashPath : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, (trace.inferredValue == input.type) = true faithful : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, @@ -183,22 +245,19 @@ theorem AtomicDefinitionRun.sound {β : Type u} body.ReferencesIn entries ∧ type.ReferencesIn entries ∧ TypingClaim.{u,v} entries [] body type := by obtain ⟨trace⟩ := definition_body_trace (fragment.path.member_success accepted) - obtain ⟨valueReads, typeReads, typed⟩ := (fragment.inference trace).sound trace.valueRun - have same := beq_readExpr? (resolve := resolve) + exact (fragment.inference trace).sound wellFormed trace.valueRun (fragment.faithful trace) (fragment.hashPath trace) - obtain ⟨bodyScope, typeScope, bodyRefs, typeRefs⟩ := - (fragment.inference trace).support.scopeAndReferences wellFormed - exact ⟨valueReads, same.symm.trans typeReads, bodyScope, typeScope, bodyRefs, typeRefs, typed⟩ /-- A fresh definition cannot justify its type through a self-reference: -its atomic value must reference the preceding interface. -/ +its value, at any universe arguments, must reference the preceding interface. -/ theorem AtomicDefinitionRun.no_self_alias {β : Type u} {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} {input : DefinitionInput} {before after : TcState .anon} {body type : AExpr β} (fragment : AtomicDefinitionRun resolve entries input before body type) (wellFormed : entries.WF) {ref : ConstRef β} (resolved : resolve input.id.addr = some ref) (fresh : entries ref = none) - {info : ExprInfo .anon} (self : input.value = .const input.id #[] info) + {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + (self : input.value = .const input.id arguments info) (accepted : TcM.checkConst input.id before = .ok () after) : False := by obtain ⟨reads, _, _, _, references, _, _⟩ := AtomicDefinitionRun.sound.{u,0} fragment wellFormed accepted diff --git a/Ix/Theory/Model/LevelCongruence.lean b/Ix/Theory/Model/LevelCongruence.lean index 3662d96b5..907b361ff 100644 --- a/Ix/Theory/Model/LevelCongruence.lean +++ b/Ix/Theory/Model/LevelCongruence.lean @@ -4,6 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Theory.Model.Judgment +import Ix.Theory.Model.Support /-! # Replacing universe levels by equivalent levels @@ -26,6 +27,22 @@ variable {β : Type u} namespace VExpr +theorem LevelWF.liftN {e : VExpr β} {n : Nat} (scope : e.LevelWF n) + (count cutoff : Nat) : (e.liftN count cutoff).LevelWF n := by + induction e generalizing cutoff <;> simp_all [VExpr.liftN, VExpr.LevelWF] + +theorem LevelWF.inst {e a : VExpr β} {n : Nat} + (scope : e.LevelWF n) (argument : a.LevelWF n) (cutoff : Nat := 0) : + (e.inst a cutoff).LevelWF n := by + induction e generalizing cutoff with + | bvar i => + by_cases hi : i < cutoff + · simp [VExpr.inst, instVar, hi, VExpr.LevelWF] + · by_cases he : i = cutoff + · simpa [VExpr.inst, instVar, hi, he] using argument.liftN cutoff 0 + · simp [VExpr.inst, instVar, hi, he, VExpr.LevelWF] + | _ => simp_all [VExpr.inst, VExpr.LevelWF] + /-- Structural equality except for semantically equivalent universe levels. -/ inductive LevelEquivalent : VExpr β → VExpr β → Prop | bvar (index) : LevelEquivalent (.bvar index) (.bvar index) @@ -125,6 +142,71 @@ end VExpr namespace Model namespace AExpr +/-- The binder conditions at their exact expression occurrences. -/ +def annotations : AExpr β → AnnotationTree + | .bvar _ | .sort _ | .const _ _ | .natLit _ => .leaf + | .app f a => .app f.annotations a.annotations + | .lam p A b => .lam p.toRaw A.annotations b.annotations + | .forallE p A B => .forallE p.toRaw A.annotations B.annotations + | .proj _ _ e => .proj e.annotations + +/-- Raw syntax and occurrence annotations uniquely determine a reading. -/ +theorem eq_of_erase_annotations {left right : AExpr β} + (shape : left.erase = right.erase) (conditions : left.annotations = right.annotations) : + left = right := by + induction left generalizing right with + | app f a hf ha => + cases right <;> simp [erase] at shape + next f' a' => + simp only [annotations, AnnotationTree.app.injEq] at conditions + rw [hf shape.1 conditions.1, ha shape.2 conditions.2] + | lam p A b hA hb => + cases right <;> simp [erase] at shape + next q A' b' => + simp only [annotations, AnnotationTree.lam.injEq] at conditions + have equal := Certified.PropWhen.toRaw_injective conditions.1 + subst q + rw [hA shape.1 conditions.2.1, hb shape.2 conditions.2.2] + | forallE p A b hA hb => + cases right <;> simp [erase] at shape + next q A' b' => + simp only [annotations, AnnotationTree.forallE.injEq] at conditions + have equal := Certified.PropWhen.toRaw_injective conditions.1 + subst q + rw [hA shape.1 conditions.2.1, hb shape.2 conditions.2.2] + | proj r i e he => + cases right <;> simp [erase] at shape + next r' i' e' => + obtain ⟨rfl, rfl, equal⟩ := shape + exact congrArg (AExpr.proj r i) (he equal (AnnotationTree.proj.inj conditions)) + | _ => cases right <;> simp_all [erase] + +theorem Scope.instL {e : AExpr β} {n depth target : Nat} {levels : List VLevel} + (scope : e.Scope n depth) (arguments : ∀ level ∈ levels, level.WF target) : + (e.instL levels).Scope target depth := by + have condition : ∀ p : Certified.PropWhen, p.WF n → + (Certified.instCondition levels p).WF target := by + intro p hp + apply hp.bind + intro i _ + apply Certified.zeroCondition_wf + exact VLevel.WF.inst (l := .param i) arguments + induction e generalizing depth with + | bvar _ | natLit _ => exact scope + | sort _ => exact VLevel.WF.inst arguments + | const r ls => + intro level member + obtain ⟨source, _, rfl⟩ := List.mem_map.mp member + exact VLevel.WF.inst arguments + | app _ _ hf ha => exact ⟨hf scope.1, ha scope.2⟩ + | lam p _ _ hA hb | forallE p _ _ hA hb => + exact ⟨condition p scope.1, hA scope.2.1, hb scope.2.2⟩ + | proj _ _ _ he => exact he scope + +theorem references_instL (e : AExpr β) (levels : List VLevel) : + (e.instL levels).references = e.references := by + induction e <;> simp_all [instL, references] + /-- Universe congruence with the same binder annotations at every occurrence. -/ inductive LevelEquivalent : AExpr β → AExpr β → Prop | bvar (index) : LevelEquivalent (.bvar index) (.bvar index) @@ -181,6 +263,47 @@ theorem reannotate_levels (e : AExpr β) {source : VExpr β} namespace LevelEquivalent +theorem annotations {e e' : AExpr β} (same : LevelEquivalent e e') : + e.annotations = e'.annotations := by + induction same <;> simp_all [AExpr.annotations] + +theorem erase {e e' : AExpr β} (same : LevelEquivalent e e') : + VExpr.LevelEquivalent e.erase e'.erase := by + induction same with + | bvar i => exact .bvar i + | sort h => exact .sort h + | const r h => exact .const r h + | app _ _ hf ha => exact .app hf ha + | lam _ _ _ hA hb => exact .lam hA hb + | forallE _ _ _ hA hb => exact .forallE hA hb + | proj r i _ he => exact .proj r i he + | natLit n => exact .natLit n + +/-- Equivalent levels need not have the same scope: the actual target levels +must separately be well scoped. Indices and binder annotations are preserved. -/ +theorem scope {e e' : AExpr β} {n depth : Nat} (same : LevelEquivalent e e') + (source : e.Scope n depth) (levels : e'.erase.LevelWF n) : e'.Scope n depth := by + induction same generalizing depth with + | bvar _ | natLit _ => exact source + | sort _ | const _ _ => exact levels + | app _ _ hf ha => exact ⟨hf source.1 levels.1, ha source.2 levels.2⟩ + | lam _ _ _ hA hb | forallE _ _ _ hA hb => + exact ⟨source.1, hA source.2.1 levels.1, hb source.2.2 levels.2⟩ + | proj _ _ _ he => exact he source levels + +theorem references {e e' : AExpr β} (same : LevelEquivalent e e') : + e.references = e'.references := by + induction same <;> simp_all [AExpr.references] + +/-- A fixed declared reading agrees when its raw tree is congruent and its +occurrence annotations match. These are syntactic premises, not typing. -/ +theorem of_erase_annotations {e e' : AExpr β} + (shape : VExpr.LevelEquivalent e.erase e'.erase) + (conditions : e.annotations = e'.annotations) : LevelEquivalent e e' := by + obtain ⟨output, erased, same⟩ := reannotate_levels e shape + have equal := eq_of_erase_annotations erased (same.annotations.symm.trans conditions) + exact equal ▸ same + theorem interp {e e' : AExpr β} (same : LevelEquivalent e e') {V : Type v} [SetTheory V] (constants : Assignment β V) (levels : List Nat) (env : Nat → V) : diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 526856d6d..9a067b61d 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -93,6 +93,30 @@ private def polymorphicIdentity : Ixon.Env × Address := ⟨.axio ⟨false, 1, .leanAll (.sort 0) (.leanAll (.var 0) (.var 1))⟩, #[], #[], #[.var 0]⟩ +/-- Specializations at Prop and Type, followed by ordinary aliases. The source +axiom stays polymorphic while each admitted definition is monomorphic. -/ +private def specializationEnvironment : Ixon.Env := Id.run do + let (env, identity) := polymorphicIdentity + let type := Ixon.Expr.leanAll (.sort 0) (.leanAll (.var 0) (.var 1)) + let (env, propIdentity) := storeConst env + ⟨.defn ⟨.defn, .safe, 0, type, .ref 0 #[0]⟩, #[], #[identity], #[.zero]⟩ + let (env, typeIdentity) := storeConst env + ⟨.defn ⟨.opaq, .safe, 0, type, .ref 0 #[0]⟩, #[], #[identity], #[.succ .zero]⟩ + let (env, _) := storeConst env + ⟨.defn ⟨.thm, .safe, 0, type, .ref 0 #[]⟩, #[], #[propIdentity], #[.zero]⟩ + let (env, _) := storeConst env + ⟨.defn ⟨.defn, .safe, 0, type, .ref 0 #[]⟩, + #[], #[typeIdentity], #[.succ .zero]⟩ + return env + +private def failedSpecialization (arguments : Array UInt64) (level : Ixon.Univ) : + Ixon.Env × Address := + let (env, identity) := polymorphicIdentity + storeConst env + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), .ref 0 arguments⟩, + #[], #[identity], #[level]⟩ + private def levelOne : KUniv .anon := .mkSucc .mkZero private def levelTwo : KUniv .anon := .mkSucc levelOne @@ -120,6 +144,26 @@ private def simplifyingUniverses : Ixon.Env × Address := ⟨.axio ⟨false, 2, .sort 0⟩, #[], #[], #[.imax (.max (.var 0) (.var 1)) (.var 1)]⟩ +private def referenceSpecialization : Ixon.Env := + let (env, function, carrier) := polymorphicReferences + (storeConst env + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.ref 0 #[0]) (.ref 0 #[0]), .ref 1 #[0]⟩, + #[], #[carrier, function], #[.succ .zero]⟩).1 + +private def simplifiedSpecialization : Ixon.Env := + let (env, source) := simplifyingUniverses + (storeConst env + ⟨.defn ⟨.defn, .safe, 0, .sort 0, .ref 0 #[1, 0]⟩, + #[], #[source], #[.zero, .succ (.succ .zero)]⟩).1 + +private def wrongSpecializationType : Ixon.Env × Address := + let (env, identity) := polymorphicIdentity + storeConst env + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), .ref 0 #[1]⟩, + #[], #[identity], #[.zero, .succ .zero]⟩ + private def inferStored (fixture : Ixon.Env × Address) (arguments : Array (KUniv .anon)) (expected : KExpr .anon) (inferOnly := false) (warmIntern := false) : Bool := let action : TcM .anon (KExpr .anon) := do @@ -176,6 +220,24 @@ private def polymorphicCases : TestSeq := | .ok (.sort (.param index _ _) _) _ => index == 0 | _ => false : Bool) -public def suite : List TestSeq := [cases, polymorphicCases] +private def specializationCases : TestSeq := + test "polymorphic environment: Prop and Type specializations and transitive aliases check" + (allSucceeded specializationEnvironment 5 { clearEvery := 0 }) + ++ test "polymorphic environment: specializations check with fresh per-item caches" + (allSucceeded specializationEnvironment 5 { clearEvery := 1 }) + ++ test "polymorphic environment: specialized types preserve nested interface references" + (allSucceeded referenceSpecialization 3) + ++ test "polymorphic environment: simplified imax type passes declaration conversion" + (allSucceeded simplifiedSpecialization 2) + ++ test "polymorphic environment: a different declared specialization fails conversion" + (let (env, target) := wrongSpecializationType; rowFailed env target) + ++ test "polymorphic environment: missing universe arguments fail declaration admission" + (let (env, target) := failedSpecialization #[] .zero; rowFailed env target) + ++ test "polymorphic environment: excess universe arguments fail declaration admission" + (let (env, target) := failedSpecialization #[0, 0] .zero; rowFailed env target) + ++ test "polymorphic environment: a monomorphic body cannot retain a universe parameter" + (let (env, target) := failedSpecialization #[0] (.var 0); rowFailed env target) + +public def suite : List TestSeq := [cases, polymorphicCases, specializationCases] end Tests.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index c1a069d4c..10357a0c9 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -43,6 +43,10 @@ increasing sequence of strongly inaccessible cardinals. preserves both interpretation and hereditary validity, including beneath binders and through let substitution. The empty-argument shortcut is justified by the source type's universe scope. +- `instantiateUnivParams_readAnnotated_scoped` also proves scope and reference + preservation for the actual returned type. Scope comes from the successful + substitution and scoped arguments; semantic level equivalence alone would + not exclude an out-of-range parameter in a simplified expression. - `inferUncached_const_sound` and `infer_const_sound` derive model typing for polymorphic constant references with arbitrary readable declaration types. Production success supplies the universe-arity check. The premises retain @@ -66,14 +70,18 @@ support for these obligations. The axiom policy is relative: **every model of the source axioms extends to a model of the checked environment, preserving the axiom interpretations**. -The initial interface contains exactly the source axioms, with closed types -that refer only to that interface. A `Realizes` witness supplies a model of +The initial interface contains exactly the source axioms, retaining their +declared universe arities. Their types have no free term variables, use only +their declared universe parameters, and refer only to that interface. +A `Realizes` witness supplies a model of these axioms. The hypothesis is model existence; a theorem connecting arbitrary syntactic consistency to model existence is outside this result. The fragment covers monomorphic standalone definitions, theorems, and opaque definitions whose values are either closed universe terms or -references to preceding interface entries. Examples include: +references to preceding interface entries, including monomorphic +specializations of polymorphic constants. Referenced types may contain +dependent functions and other readable expression forms. Examples include: ```lean axiom P : Prop @@ -81,6 +89,8 @@ axiom p : P def q : P := p theorem r : P := q def typeAlias : Type := Prop +axiom ident.{u} : (α : Sort u) → α → α +def propIdent : (α : Prop) → α → α := ident.{0} ``` `AtomicEnvironmentFragment` records the precise execution boundary: @@ -89,9 +99,13 @@ def typeAlias : Type := Prop represents an axiom or a definition. Lookup, routing, and reset witnesses identify the checked `KConst`. - Value inference misses both cache partitions. Constant lookup agrees with - an already admitted monomorphic type; empty level substitution preserves - that type. Sort inference retains the finite interning coherence and - address-faithfulness premises. + an already admitted type and universe count. A specialization supplies + closed universe arguments and finite interning/substitution resources at + the actual post-lookup state. The occurrence annotations on the declared + type agree with the substituted entry's annotations. These are structural + data checks; successful inference derives typing, scope, and references. + Ordinary aliases retain the simpler empty-substitution path. Sort inference + retains finite interning coherence and address-faithfulness premises. - Conversion takes the initial hash-equality path, with faithfulness of the compared expressions. General reduction and conversion caches are outside this fragment. @@ -109,9 +123,10 @@ extracts the validation, type-inference, theorem-guard, value-inference, and conversion steps from public success, then derives body typing to extend the preceding model. Automatic witness construction, lambdas, applications, inductives, coordinated blocks, and other conversion paths remain outside the -fragment. The polymorphic constant-inference theorem above is a separate proof -increment; composing it into general declaration admission and environment -model extension remains to be done. +fragment. Polymorphic constant inference is composed into declaration +admission and model extension for the monomorphic specializations described +above. Definitions with their own universe parameters remain outside this +environment fragment. `checkEnvAnon_atomic_represents_source` ties every source address to an interface with the type and body reached by production lookup. The independent @@ -162,7 +177,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 51 exact theorem boundaries. The production +The consistency target checks 66 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -178,6 +193,10 @@ Their model-side level congruence introduces no native proof dependency. Kernel unit regressions cover lazy loading, both inference policies, interning reuse, dependent function types, shared references, lets, `imax` simplification, argument order, and rejection of wrong arities and out-of-range parameters. +Environment regressions additionally check Prop/Type specializations, +transitive aliases, nested references, simplified declaration types, cache +clearing, and admission failures for wrong arities, open parameters, and a +mismatched declared specialization. ## Certified host adapters diff --git a/docs/theory.md b/docs/theory.md index 0537cf56f..880ed6d3f 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -20,8 +20,9 @@ open frontiers retain their stated model hypotheses. The [certified host adapters](certified-checking.md) connect authenticated serialized Ixon to model admission. Separately, a production `checkEnvAnon` [fragment](kernel-verification.md#production-environment-fragment) for -monomorphic aliases and closed universe terms extends every model of its -source axioms under explicit execution witnesses. Full checker consistency +monomorphic aliases, closed universe terms, and monomorphic specializations +of polymorphic constants extends every model of its source axioms under +explicit execution witnesses. Full checker consistency and compiler/backend refinement remain open. `Ix.Theory.Named` retains the local name-indexed specification and proof From 2e45671189c7b5c74787b6babb8d577a020bffa1 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 12:06:17 -0400 Subject: [PATCH 08/30] Extend production consistency to dependent function bodies --- Ix/Kernel/Verify/Consistency.lean | 13 +- Ix/Kernel/Verify/Consistency/Audit.lean | 41 ++- .../Verify/Consistency/BinderInference.lean | 286 ++++++++++++++++ .../Verify/Consistency/BinderOpening.lean | 323 ++++++++++++++++++ Ix/Kernel/Verify/Consistency/Context.lean | 297 ++++++++++++++++ Ix/Kernel/Verify/Consistency/Level.lean | 9 + Ix/Kernel/Verify/Consistency/Production.lean | 43 ++- Ix/Kernel/Verify/Consistency/ScopedExpr.lean | 258 ++++++++++++++ Ix/Theory/Model/Checking.lean | 69 ++++ Tests/Ix/Kernel/Consistency.lean | 71 +++- Tests/Theory/ImportManifest.lean | 4 +- docs/kernel-verification.md | 51 ++- docs/theory.md | 8 +- 13 files changed, 1443 insertions(+), 30 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/BinderInference.lean create mode 100644 Ix/Kernel/Verify/Consistency/BinderOpening.lean create mode 100644 Ix/Kernel/Verify/Consistency/Context.lean create mode 100644 Ix/Kernel/Verify/Consistency/ScopedExpr.lean create mode 100644 Ix/Theory/Model/Checking.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 447f78de8..3ab048595 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -10,6 +10,10 @@ import Ix.Kernel.Verify.Consistency.Infer import Ix.Kernel.Verify.Consistency.InstUniv import Ix.Kernel.Verify.Consistency.Constant import Ix.Kernel.Verify.Consistency.Atomic +import Ix.Kernel.Verify.Consistency.ScopedExpr +import Ix.Kernel.Verify.Consistency.Context +import Ix.Kernel.Verify.Consistency.BinderOpening +import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.Production import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Consistency.Audit @@ -20,10 +24,15 @@ import Ix.Kernel.Verify.Consistency.Audit This library connects production kernel operations to `Ix.Theory`. Each transport keeps its representation, arithmetic, and dependency assumptions explicit. A production `checkEnvAnon` fragment preserves models of its -axiom set for monomorphic aliases, closed sorts, and monomorphic -specializations of polymorphic constants under the stated execution resources. +axiom set for monomorphic aliases, closed sorts, monomorphic specializations of +polymorphic constants, and closed function bodies built from sorts, locals, +dependent functions, and full-mode lambdas under the stated execution resources. Constant inference supports arbitrary readable entry types, using the actual universe-instantiation walker and explicit lookup and finite-support resources. The returned type's scope and references justify declaration admission. +The binder case also requires explicit syntactic scope and empty constant +reference lists. Its separate declared-type inference turns semantic checking +into typing. Local cache hits agree with the actual declaration type; other +inference nodes retain cache-miss boundaries. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 944c66c80..fc7c05645 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -36,6 +36,9 @@ private def atomicRoots : Array Lean.Name := #[ ``infer_uncached_success, ``AtomicInferenceSupport.typing, ``AtomicInferenceSupport.reads, ``AtomicInferenceSupport.output, ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound, + ``inferUncached_fvar_sound, ``infer_fvar_sound, + ``FVarInferenceSupport.output, ``FVarInferenceSupport.sound, + ``ForallInferenceTrace.output, ``LambdaInferenceTrace.output, ``BinderInference.sound, ``DefinitionBodySupport.sound ] @@ -56,6 +59,25 @@ private def productionRoots : Array Lean.Name := #[ ``checkEnvAnon_atomic_no_false ] +private def scopedRoots : Array Lean.Name := #[ + ``localIndex?_mem, ``localIndex?_getElem, ``localIndex?_fresh, + ``readScopedExpr?_closed, ``readScopedExpr?_eraseMeta, + ``beq_readScopedExpr?, ``internExpr_readScopedExpr?, ``readScopedExpr?_push, + ``LocalContextReading.empty +] + +private def contextRoots : Array Lean.Name := #[ + ``localContext_find?_push_same, ``localContext_find?_push_ne, + ``LocalContextReading.push, ``ScopedModelTyping.closed +] + +private def binderWalkerRoots : Array Lean.Name := #[ + ``inferKey_lctx, ``UncachedInference.localContext, + ``readScopedExpr?_instantiateRevSpec, ``readScopedExpr?_abstractFVarsSpec, + ``openBinder_eq, ``openBinder_sound, + ``abstractFVars_singleton_spec, ``abstractFVars_readScopedExpr? +] + /-- Production roots must not acquire a checker-soundness assumption or invoke the independent certificate validator to establish acceptance. -/ private def forbiddenProduction : Array Lean.Name := #[ @@ -72,11 +94,15 @@ def roots : Array RootAllowance := #[ { root := ``readLevel_eraseMeta, standardAxioms := #[``propext] }, { root := ``readLevel_mkSucc, standardAxioms := #[``propext, ``Classical.choice], nativeAxioms := #[levelNative] }, + { root := ``readLevel_mkIMax, standardAxioms := standard, + nativeAxioms := #[levelNative] }, { root := ``univEq_sound, standardAxioms := standard }, { root := ``univGeq_sound, standardAxioms := standard }, { root := ``readExpr?_mkSort, standardAxioms := standard, nativeAxioms := #[expressionNative] }, { root := ``readExpr?_eraseMeta, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``readScopedExpr?_lam_parts }, + { root := ``readScopedExpr?_all_parts }, { root := ``beq_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, { root := ``internExpr_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, { root := ``ModelTyping.sort, standardAxioms := standard, @@ -108,8 +134,19 @@ def roots : Array RootAllowance := #[ standardAxioms := #[``propext] }, { root := ``Theory.Model.AExpr.LevelEquivalent.interp, standardAxioms := standard }, { root := ``Theory.Model.AExpr.LevelEquivalent.wellDenoted, standardAxioms := standard }, - { root := ``Theory.Model.AExpr.LevelEquivalent.typing, standardAxioms := standard } -] ++ (atomicRoots ++ instantiationRoots).map (fun root => { + { root := ``Theory.Model.AExpr.LevelEquivalent.typing, standardAxioms := standard }, + { root := ``Theory.Model.TypingClaim.checking, standardAxioms := standard }, + { root := ``Theory.Model.CheckingClaim.typing, standardAxioms := standard }, + { root := ``Theory.Model.CheckingClaim.typingSort, standardAxioms := standard }, + { root := ``Theory.Model.CheckingClaim.lam, standardAxioms := standard } +] ++ scopedRoots.map (fun root => { + root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction +}) ++ contextRoots.map (fun root => { + root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction +}) ++ binderWalkerRoots.map (fun root => { + root, standardAxioms := standard, nativeAxioms := #[expressionNative], + forbiddenDependencies := forbiddenProduction +}) ++ (atomicRoots ++ instantiationRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], forbiddenDependencies := forbiddenProduction }) ++ productionRoots.map (fun root => { diff --git a/Ix/Kernel/Verify/Consistency/BinderInference.lean b/Ix/Kernel/Verify/Consistency/BinderInference.lean new file mode 100644 index 000000000..d7da09fca --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/BinderInference.lean @@ -0,0 +1,286 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.BinderOpening +import Ix.Kernel.Knot +import Ix.Theory.Model.Checking + +/-! +# Production dependent function inference + +Finite inference trees follow the production method table's decreasing fuel. +Their premises record cache misses, actual execution prefixes, local-context +frames, finite interning support, and index bounds. Semantic checking is +derived from these trees. A declaration's separate type inference supplies +the expected type's hereditary validity before checking becomes typing. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +private theorem withLctxScope_eq (action : RecM .anon α) + (methods : Methods .anon) (before : TcState .anon) : + (RecM.withLctxScope action).run methods before = + match action.run methods before with + | .ok value after => + .ok value {after with lctx := after.lctx.truncate before.lctx.size} + | .error err after => + .error err {after with lctx := after.lctx.truncate before.lctx.size} := by + unfold RecM.withLctxScope + rw [ReaderT.run_bind] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ + unfold EStateM.bind + rw [show (get : TcM .anon (TcState .anon)) before = .ok before before from rfl] + simp only + unfold tryFinally + change EStateM.map (fun pair : α × PUnit => pair.1) + (tryFinally' (action.run methods) (fun _ => + (modify (fun after : TcState .anon => + {after with lctx := after.lctx.truncate before.lctx.size}) : + TcM .anon PUnit))) before = _ + unfold EStateM.map MonadFinally.tryFinally' EStateM.instMonadFinally + cases run : action.run methods before <;> simp only [run] <;> rfl + +private theorem withLctxScope_success {action : RecM .anon α} + {methods : Methods .anon} {before after : TcState .anon} {result : α} + (accepted : (RecM.withLctxScope action).run methods before = .ok result after) : + ∃ state, action.run methods before = .ok result state := by + rw [withLctxScope_eq] at accepted + cases run : action.run methods before with + | error err state => rw [run] at accepted; contradiction + | ok value state => + rw [run] at accepted + cases accepted + exact ⟨state, rfl⟩ + +/-- The exact recursive calls and opening prefix of a forall branch. +Both sort exposures take the production syntactic fast path. -/ +structure ForallInferenceTrace (fuel : Nat) (before : TcState .anon) + (name : Mode.anon.F Name) (bi : Mode.anon.F Lean.BinderInfo) + (domain body : KExpr .anon) where + domainLevel : KUniv .anon + domainInfo : ExprInfo .anon + domainState : TcState .anon + opened : KExpr .anon + fresh : FVarId + openedState : TcState .anon + bodyLevel : KUniv .anon + bodyInfo : ExprInfo .anon + bodyState : TcState .anon + domainRun : RecM.infer domain (methodsN fuel) before = + .ok (.sort domainLevel domainInfo) domainState + openRun : TcM.openBinder name bi domain body domainState = .ok (opened, fresh) openedState + bodyRun : RecM.infer opened (methodsN fuel) openedState = + .ok (.sort bodyLevel bodyInfo) bodyState + contextPreserved : domainState.lctx = before.lctx + +/-- Inversion reaches the actual final interning operation after both recursive +calls, sort exposures, and binder opening. -/ +theorem ForallInferenceTrace.output {fuel : Nat} {before after : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {domain body result : KExpr .anon} {info : ExprInfo .anon} {inferOnly : Bool} + (trace : ForallInferenceTrace fuel before name bi domain body) + (accepted : RecM.inferUncached RecM.inferCall inferOnly (.all name bi domain body info) + (methodsN (fuel + 1)) before = .ok result after) : + result = (trace.bodyState.env.intern.internExpr + (KExpr.mkSort (KUniv.mkIMax trace.domainLevel trace.bodyLevel))).1 := by + change (RecM.inferUncached RecM.inferCall inferOnly (.all name bi domain body info)).run + (methodsN (fuel + 1)) before = .ok result after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind] at accepted + change EStateM.bind (RecM.infer domain (methodsN fuel)) _ before = _ at accepted + rw [EStateM.bind, trace.domainRun] at accepted + change (RecM.withLctxScope _).run (methodsN (fuel + 1)) trace.domainState = _ at accepted + obtain ⟨scopedState, accepted⟩ := withLctxScope_success accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.openBinder name bi domain body) _ trace.domainState = + .ok result scopedState at accepted + rw [EStateM.bind, trace.openRun] at accepted + have bodyRun : (RecM.inferCall trace.opened).run (methodsN (fuel + 1)) + trace.openedState = .ok (.sort trace.bodyLevel trace.bodyInfo) trace.bodyState := trace.bodyRun + change EStateM.bind ((RecM.inferCall trace.opened).run (methodsN (fuel + 1))) + _ trace.openedState = .ok result scopedState at accepted + rw [EStateM.bind, bodyRun] at accepted + cases accepted + rfl + +/-- Full-mode lambda inference validates its domain, opens the binder, and +infers the body. The current fragment takes the unchanged cheap-beta path. -/ +structure LambdaInferenceTrace (fuel : Nat) (before : TcState .anon) + (name : Mode.anon.F Name) (bi : Mode.anon.F Lean.BinderInfo) + (domain body : KExpr .anon) where + domainLevel : KUniv .anon + domainInfo : ExprInfo .anon + domainState : TcState .anon + opened : KExpr .anon + fresh : FVarId + openedState : TcState .anon + bodyType : KExpr .anon + bodyState : TcState .anon + domainRun : RecM.infer domain (methodsN fuel) before = + .ok (.sort domainLevel domainInfo) domainState + openRun : TcM.openBinder name bi domain body domainState = .ok (opened, fresh) openedState + bodyRun : RecM.infer opened (methodsN fuel) openedState = .ok bodyType bodyState + contextPreserved : domainState.lctx = before.lctx + betaUnchanged : cheapBetaPlan? bodyType = none + +def LambdaInferenceTrace.abstracted {fuel : Nat} {before : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {domain body : KExpr .anon} (trace : LambdaInferenceTrace fuel before name bi domain body) := + abstractFVars trace.bodyType #[trace.fresh] trace.bodyState.env.intern + +/-- The returned lambda type is the actual abstracted body type, wrapped in +the production Pi constructor and passed through the final intern table. -/ +theorem LambdaInferenceTrace.output {fuel : Nat} {before after : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {domain body result : KExpr .anon} {info : ExprInfo .anon} + (trace : LambdaInferenceTrace fuel before name bi domain body) + (accepted : RecM.inferUncached RecM.inferCall false (.lam name bi domain body info) + (methodsN (fuel + 1)) before = .ok result after) : + result = (trace.abstracted.2.internExpr (KExpr.mkAll () () domain trace.abstracted.1)).1 := by + change (RecM.inferUncached RecM.inferCall false (.lam name bi domain body info)).run + (methodsN (fuel + 1)) before = .ok result after at accepted + unfold RecM.inferUncached at accepted + simp only [Bool.not_false, if_true, ReaderT.run_bind] at accepted + change EStateM.bind (RecM.infer domain (methodsN fuel)) _ before = _ at accepted + rw [EStateM.bind, trace.domainRun] at accepted + change (RecM.withLctxScope _).run (methodsN (fuel + 1)) trace.domainState = _ at accepted + obtain ⟨scopedState, accepted⟩ := withLctxScope_success accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.openBinder name bi domain body) _ trace.domainState = + .ok result scopedState at accepted + rw [EStateM.bind, trace.openRun] at accepted + have bodyRun : (RecM.inferCall trace.opened).run (methodsN (fuel + 1)) + trace.openedState = .ok trace.bodyType trace.bodyState := trace.bodyRun + change EStateM.bind ((RecM.inferCall trace.opened).run (methodsN (fuel + 1))) + _ trace.openedState = .ok result scopedState at accepted + rw [EStateM.bind, bodyRun] at accepted + simp only [cheapBetaReduce, trace.betaUnchanged] at accepted + cases accepted + rfl + +/-- Structural and operational support for a finite production inference +tree. The source reading and local-context agreement are inputs to soundness, +so each recursive body's reading must be derived by opening its binder. -/ +inductive BinderInference {β : Type u} + (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) : + List FVarId → Model.Context β → Nat → TcState .anon → KExpr .anon → + AExpr β → AExpr β → Type u + | sort {locals context fuel before level info} + (miss : UncachedInference before (.sort level info)) + (coherent : miss.keyed.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun term => + miss.keyed.env.intern.ExprSupport term ∨ term = KExpr.mkSort (KUniv.mkSucc level)) : + BinderInference resolve entries locals context fuel before (.sort level info) + (.sort (readLevel level)) (.sort (.succ (readLevel level))) + | fvar {locals context fuel before id name info index A} + (cache : FVarInferenceSupport before id name info) + (registered : localIndex? locals id = some index) + (atIndex : context[index]? = some A) : + BinderInference resolve entries locals context fuel before (.fvar id name info) (.bvar index) A + | forallE {locals context fuel before name bi domain body info A B} + (miss : UncachedInference before (.all name bi domain body info)) + (trace : ForallInferenceTrace fuel miss.keyed name bi domain body) + (opening : BinderOpeningSupport trace.domainState body) + (absent : (⟨trace.domainState.env.nextFVarId⟩ : FVarId) ∉ locals) + (domainTree : BinderInference resolve entries locals context fuel miss.keyed domain + A (.sort (readLevel trace.domainLevel))) + (bodyTree : BinderInference resolve entries (trace.fresh :: locals) (context.push A) + fuel trace.openedState trace.opened B (.sort (readLevel trace.bodyLevel))) + (levelFaithful : ∀ a b, + (KUniv.Sub a trace.domainLevel ∨ KUniv.Sub a trace.bodyLevel) → + (KUniv.Sub b trace.domainLevel ∨ KUniv.Sub b trace.bodyLevel) → a.AddrFaithful b) + (domainBound : trace.domainLevel.size < UInt64.size) + (bodyBound : trace.bodyLevel.size < UInt64.size) + (coherent : trace.bodyState.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun term => trace.bodyState.env.intern.ExprSupport term ∨ + term = KExpr.mkSort (KUniv.mkIMax trace.domainLevel trace.bodyLevel)) : + BinderInference resolve entries locals context (fuel + 1) before (.all name bi domain body info) + (.forallE (Certified.zeroCondition (readLevel trace.bodyLevel)) A B) + (.sort (readLevel (KUniv.mkIMax trace.domainLevel trace.bodyLevel))) + | lam {locals context fuel before name bi domain body info A b B condition} + (full : before.inferOnly = false) + (miss : UncachedInference before (.lam name bi domain body info)) + (trace : LambdaInferenceTrace fuel miss.keyed name bi domain body) + (opening : BinderOpeningSupport trace.domainState body) + (absent : (⟨trace.domainState.env.nextFVarId⟩ : FVarId) ∉ locals) + (bodyTree : BinderInference resolve entries (trace.fresh :: locals) (context.push A) + fuel trace.openedState trace.opened b B) + (constructed : trace.bodyType.Constructed) + (bound : trace.bodyType.size + 1 < UInt64.size) + (coherent : trace.bodyState.env.intern.WF) + (closingFaithful : KExpr.CollisionFree fun term => trace.bodyState.env.intern.ExprSupport term ∨ + KExpr.AbstractReach ((∅ : Std.HashMap FVarId UInt64).insert trace.fresh 0) + 1 trace.bodyType 0 term) + (faithful : KExpr.KeyCollisionFree fun term => trace.abstracted.2.ExprSupport term ∨ + term = KExpr.mkAll () () domain trace.abstracted.1) : + BinderInference resolve entries locals context (fuel + 1) before (.lam name bi domain body info) + (.lam condition A b) (.forallE condition A B) + +/-- Successful production inference reads the expected model type and checks +the actual source term against it. No recursive semantic premise is supplied +by the caller: induction follows the finite operational support tree. -/ +theorem BinderInference.sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {fuel : Nat} + {before after : TcState .anon} {term result : KExpr .anon} {e A : AExpr β} + (support : BinderInference resolve entries locals context fuel before term e A) + (agreement : LocalContextReading resolve locals before.lctx context) + (reading : readScopedExpr? resolve locals term = some e.erase) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : + readScopedExpr? resolve locals result = some A.erase ∧ + CheckingClaim.{u,v} entries context e A := by + induction support generalizing result after with + | sort miss coherent faithful => + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + change EStateM.Result.ok + (miss.keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc _))).1 _ = + .ok result state at run + cases run + refine ⟨?_, (TypingClaim.sort _).checking⟩ + rw [internExpr_readScopedExpr? coherent faithful] + simp [AExpr.erase] + | fvar cache registered atIndex => + obtain ⟨typeReads, typed⟩ := cache.sound agreement registered atIndex accepted + exact ⟨typeReads, typed.checking⟩ + | forallE miss trace opening absent domainTree bodyTree levelFaithful domainBound bodyBound + coherent faithful ihDomain ihBody => + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + obtain ⟨domainReads, bodyReads⟩ := readScopedExpr?_all_parts reading + have keyedAgreement := miss.localContext.symm ▸ agreement + obtain ⟨_, domainChecked⟩ := ihDomain keyedAgreement domainReads trace.domainRun + have domainAgreement := trace.contextPreserved.symm ▸ keyedAgreement + obtain ⟨_, openedReads, openedAgreement, _⟩ := + openBinder_sound opening domainAgreement absent domainReads bodyReads trace.openRun + obtain ⟨_, bodyChecked⟩ := ihBody openedAgreement openedReads trace.bodyRun + refine ⟨?_, ?_⟩ + · rw [trace.output run, internExpr_readScopedExpr? coherent faithful] + rfl + · have formed := TypingClaim.forallE domainChecked.typingSort bodyChecked.typingSort rfl + exact (AExpr.LevelEquivalent.sort + (Theory.VLevel.equiv_def.mpr fun levels => + (Theory.VLevel.equiv_def.mp (readLevel_mkIMax levelFaithful domainBound bodyBound) + levels).symm) |>.typing formed).checking + | lam full miss trace opening absent bodyTree constructed bound coherent closingFaithful + faithful ihBody => + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + rw [full] at run + obtain ⟨domainReads, bodyReads⟩ := readScopedExpr?_lam_parts reading + have keyedAgreement := miss.localContext.symm ▸ agreement + have domainAgreement := trace.contextPreserved.symm ▸ keyedAgreement + obtain ⟨_, openedReads, openedAgreement, _⟩ := + openBinder_sound opening domainAgreement absent domainReads bodyReads trace.openRun + obtain ⟨bodyTypeReads, bodyChecked⟩ := ihBody openedAgreement openedReads trace.bodyRun + obtain ⟨closedReads, closedCoherent⟩ := abstractFVars_readScopedExpr? constructed bound coherent + closingFaithful bodyTypeReads + refine ⟨?_, bodyChecked.lam⟩ + rw [trace.output run, + internExpr_readScopedExpr? (table := trace.abstracted.2) closedCoherent faithful] + simp [LambdaInferenceTrace.abstracted, domainReads, closedReads, AExpr.erase] + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/BinderOpening.lean b/Ix/Kernel/Verify/Consistency/BinderOpening.lean new file mode 100644 index 000000000..16c35701e --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/BinderOpening.lean @@ -0,0 +1,323 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Context +import Ix.Kernel.Verify.Subst + +/-! +# Reading the production binder walkers + +Opening a syntactic binder and registering its fresh free variable preserve +the same model de Bruijn expression. Closing performs the inverse change of +representation. The bounds below prevent production's `UInt64` depth from +wrapping; they impose no semantic typing assumptions. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u +variable {β : Type u} + +private theorem bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ intermediate, action = some intermediate ∧ next intermediate = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +private theorem depth_succ {depth : UInt64} (bound : depth.toNat + 1 < UInt64.size) : + (depth + 1).toNat = depth.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt bound] + +/-- A fresh local replaces exactly the removed syntactic binder, even below +nested binders and in occurrences of older dependent locals. -/ +theorem readScopedExpr?_instantiateRevSpec + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {body : KExpr .anon} {source : VExpr β} {depth : UInt64} {fresh : FVarId} + (absent : fresh ∉ locals) + (bound : depth.toNat + body.size + 1 < UInt64.size) + (reading : readScopedExpr? resolve locals body (depth.toNat + 1) = some source) : + readScopedExpr? resolve (fresh :: locals) + (KExpr.instantiateRevSpec body #[KExpr.mkFVar fresh ()] depth) depth.toNat = + some source := by + induction body generalizing source depth with + | var index name info => + simp only [readScopedExpr?] at reading + split at reading + next inScope => + cases reading + have next := depth_succ (depth := depth) (by simp only [KExpr.size] at bound; omega) + by_cases equal : index = depth + · subst index + simp [KExpr.instantiateRevSpec, UInt64.lt_iff_toNat_lt, next, + localIndex?] + · have smaller : index.toNat < depth.toNat := by + have : index.toNat ≠ depth.toNat := fun h => equal (UInt64.toNat_inj.mp h) + omega + have before : ¬ index ≥ depth := by + simp only [UInt64.le_iff_toNat_le]; omega + have beforeNext : ¬ index ≥ depth + 1 := by + simp only [UInt64.le_iff_toNat_le, next]; omega + simp [KExpr.instantiateRevSpec, before, beforeNext, readScopedExpr?, smaller] + · contradiction + | fvar id name info => + rw [readScopedExpr?] at reading + obtain ⟨index, found, reading⟩ := Option.map_eq_some_iff.mp reading + cases reading + simp [KExpr.instantiateRevSpec, readScopedExpr?, localIndex?_fresh absent found, + Nat.add_assoc, Nat.add_comm 1] + | sort _ _ | const _ _ _ | nat _ _ _ => exact reading + | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | app fn arg info hf ha => + rw [readScopedExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.instantiateRevSpec, + hf (by omega) fReads, ha (by omega) aReads] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readScopedExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := bind_success reading + obtain ⟨B, bodyReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyBound : (depth + 1).toNat + body.size + 1 < UInt64.size := by + rw [next]; omega + have bodyReads' : readScopedExpr? resolve locals body ((depth + 1).toNat + 1) = + some B := by simpa only [next] using bodyReads + have bodyOut : readScopedExpr? resolve (fresh :: locals) + (KExpr.instantiateRevSpec body #[KExpr.mkFVar fresh ()] (depth + 1)) + (depth.toNat + 1) = some B := by + simpa only [next] using hb bodyBound bodyReads' + simp [KExpr.instantiateRevSpec, hd (by omega) domainReads, bodyOut] + | prj id index value info ih => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.instantiateRevSpec, resolved, + ih (by omega) valueReads] + +private local instance : LawfulBEq FVarId where + eq_of_beq := by + intro left right equal + cases left + cases right + congr 1 + exact eq_of_beq equal + rfl {a} := by + cases a with + | mk x => show (x == x) = true; exact beq_self_eq_true x + +/-- Closing the newest local restores the syntactic binder without changing +the model expression. Unknown locals and loose variables cannot pass the +source reading. -/ +theorem readScopedExpr?_abstractFVarsSpec + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {body : KExpr .anon} {source : VExpr β} {depth : UInt64} {fresh : FVarId} + (bound : depth.toNat + body.size + 1 < UInt64.size) + (reading : readScopedExpr? resolve (fresh :: locals) body depth.toNat = some source) : + readScopedExpr? resolve locals + (KExpr.abstractFVarsSpec body ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) + 1 depth) (depth.toNat + 1) = some source := by + induction body generalizing source depth with + | var index name info => + simp only [readScopedExpr?] at reading + split at reading + next inScope => + cases reading + have before : ¬ index ≥ depth := by + simp only [UInt64.le_iff_toNat_le]; omega + simp [KExpr.abstractFVarsSpec, before, readScopedExpr?, show index.toNat < + depth.toNat + 1 by omega] + · contradiction + | fvar id name info => + by_cases equal : id = fresh + · subst id + simp [readScopedExpr?, localIndex?] at reading + cases reading + simp [KExpr.abstractFVarsSpec] + · simp only [readScopedExpr?, localIndex?, equal, if_false, Option.map_map] at reading + obtain ⟨index, found, reading⟩ := Option.map_eq_some_iff.mp reading + cases reading + simp [KExpr.abstractFVarsSpec, Ne.symm equal, + readScopedExpr?, found, + Nat.add_assoc, Nat.add_comm 1] + | sort _ _ | const _ _ _ | nat _ _ _ => exact reading + | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | app fn arg info hf ha => + rw [readScopedExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.abstractFVarsSpec, + hf (by omega) fReads, ha (by omega) aReads] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readScopedExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := bind_success reading + obtain ⟨B, bodyReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyBound : (depth + 1).toNat + body.size + 1 < UInt64.size := by + rw [next]; omega + have bodyReads' : readScopedExpr? resolve (fresh :: locals) body (depth + 1).toNat = + some B := by simpa only [next] using bodyReads + have bodyOut : readScopedExpr? resolve locals + (KExpr.abstractFVarsSpec body ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) + 1 (depth + 1)) (depth.toNat + 1 + 1) = some B := by + simpa only [next] using hb bodyBound bodyReads' + simp [KExpr.abstractFVarsSpec, hd (by omega) domainReads, bodyOut] + | prj id index value info ih => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.abstractFVarsSpec, resolved, + ih (by omega) valueReads] + +/-- The exact successful-state shape of production binder opening. -/ +theorem openBinder_eq (name : Mode.anon.F Name) (bi : Mode.anon.F Lean.BinderInfo) + (type body : KExpr .anon) (before : TcState .anon) : + TcM.openBinder name bi type body before = + if before.env.nextFVarId.toNat + 1 < UInt64.size then + let fresh : FVarId := ⟨before.env.nextFVarId⟩ + let internedLocal := before.env.intern.internExpr (KExpr.mkFVar fresh name) + let opened := instantiateRev body #[internedLocal.1] internedLocal.2 + .ok (opened.1, fresh) {before with + env := {before.env with + nextFVarId := before.env.nextFVarId + 1 + intern := opened.2} + lctx := before.lctx.push fresh (.cdecl name bi type)} + else .error (.other "free-variable id space exhausted") before := by + unfold TcM.openBinder + change EStateM.bind TcM.freshFVarId _ before = _ + rw [EStateM.bind, TcM.freshFVarId] + by_cases room : before.env.nextFVarId.toNat + 1 < UInt64.size + · simp only [room, if_true] + rfl + · simp only [room, if_false] + +/-- Finite production resources for one binder opening. Collision freedom is +needed only on the existing table, the new local, and this walker's reach. -/ +structure BinderOpeningSupport (before : TcState .anon) (body : KExpr .anon) : Prop where + constructed : body.Constructed + bound : body.size + 1 < UInt64.size + coherent : before.env.intern.WF + faithful : KExpr.CollisionFree fun term => + before.env.intern.ExprSupport term ∨ + term = KExpr.mkFVar ⟨before.env.nextFVarId⟩ () ∨ + KExpr.InstRevReach #[KExpr.mkFVar ⟨before.env.nextFVarId⟩ ()] body 0 term + +/-- Successful binder opening preserves the model body and implements the +model's dependent context extension, using the actual allocated id. -/ +theorem openBinder_sound + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {context : Model.Context β} {type body opened : KExpr .anon} + {A : AExpr β} {b : VExpr β} {fresh : FVarId} {before after : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + (support : BinderOpeningSupport before body) + (agreement : LocalContextReading resolve locals before.lctx context) + (absent : (⟨before.env.nextFVarId⟩ : FVarId) ∉ locals) + (typeReads : readScopedExpr? resolve locals type = some A.erase) + (bodyReads : readScopedExpr? resolve locals body 1 = some b) + (accepted : TcM.openBinder name bi type body before = .ok (opened, fresh) after) : + fresh = ⟨before.env.nextFVarId⟩ ∧ + readScopedExpr? resolve (fresh :: locals) opened = some b ∧ + LocalContextReading resolve (fresh :: locals) after.lctx (context.push A) ∧ + after.env.intern.WF := by + have nameUnit : name = () := Subsingleton.elim _ _ + have biUnit : bi = () := Subsingleton.elim _ _ + subst name bi + have interned : (before.env.intern.internExpr + (KExpr.mkFVar ⟨before.env.nextFVarId⟩ ())).1 = + KExpr.mkFVar ⟨before.env.nextFVarId⟩ () := by + have keyFaithful : KExpr.KeyCollisionFree (fun term => + before.env.intern.ExprSupport term ∨ term = KExpr.mkFVar ⟨before.env.nextFVarId⟩ ()) := + KExpr.keyCollisionFree_anon.mpr + (support.faithful.mono fun term h => h.elim Or.inl (fun equal => .inr (.inl equal))) + simpa only [KExpr.eraseMeta_anon] using + before.env.intern.internExpr_eraseMeta support.coherent keyFaithful + have walk := instantiateRev_spec (fvars := #[KExpr.mkFVar ⟨before.env.nextFVarId⟩ ()]) + support.faithful support.constructed (by simpa using support.bound) + (fun _ reached => .inr (.inr reached)) + (support.coherent.internExpr (KExpr.mkFVar ⟨before.env.nextFVarId⟩ ())) + (fun _ member => (InternTable.ExprSupport.of_internExpr member).elim + Or.inl (fun equal => .inr (.inl equal))) + rw [openBinder_eq] at accepted + split at accepted + · simp only [interned] at accepted + cases accepted + refine ⟨rfl, ?_, agreement.push (decl := .cdecl () () type) absent typeReads, walk.2.1⟩ + rw [walk.1] + exact readScopedExpr?_instantiateRevSpec absent (by simpa using support.bound) bodyReads + · contradiction + +private theorem abstractFVars_singleton_eq (body : KExpr .anon) (fresh : FVarId) : + abstractFVars body #[fresh] = + if (!body.hasFVars && body.lbr == 0) then pure body + else runWalk (abstractFVarsCached body + ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) 1 0) := by + unfold abstractFVars + simp only [show #[fresh].isEmpty = false from rfl, Bool.false_or] + by_cases fast : (!body.hasFVars && body.lbr == 0) = true + · simp only [fast, if_true] + · simp only [fast, ← Array.forIn_toList] + simp + +/-- Exact refinement of the production singleton abstraction, including its +no-free-variable fast path and its memoized recursive walk. -/ +theorem abstractFVars_singleton_spec {body : KExpr .anon} {fresh : FVarId} + {table : InternTable .anon} {support : KExpr .anon → Prop} + (constructed : body.Constructed) (bound : body.size < UInt64.size) + (faithful : KExpr.CollisionFree support) (coherent : table.WF) + (initial : ∀ term, table.ExprSupport term → support term) + (reachable : ∀ term, KExpr.AbstractReach + ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) 1 body 0 term → support term) : + (abstractFVars body #[fresh] table).1 = KExpr.abstractFVarsSpec body + ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) 1 0 ∧ + (abstractFVars body #[fresh] table).2.WF := by + rw [abstractFVars_singleton_eq] + split + next fast => + have noFVars : body.hasFVars = false := by + have := (Bool.and_eq_true_iff.mp fast).1 + simpa using this + have noLoose : body.lbr ≤ (0 : UInt64) := by + rw [eq_of_beq (Bool.and_eq_true_iff.mp fast).2] + exact UInt64.le_refl _ + exact ⟨(KExpr.abstractFVarsSpec_id constructed (by simpa using bound) noFVars noLoose).symm, + coherent⟩ + · have post := abstractFVarsCached_spec faithful constructed (depth := 0) + (by simpa using bound) reachable coherent initial + (WalkScratchInv.empty support _) + exact ⟨post.result, post.wf⟩ + +/-- Production abstraction recovers the model body under the closed binder. -/ +theorem abstractFVars_readScopedExpr? + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {body : KExpr .anon} {fresh : FVarId} {source : VExpr β} + {table : InternTable .anon} + (constructed : body.Constructed) (bound : body.size + 1 < UInt64.size) + (coherent : table.WF) + (faithful : KExpr.CollisionFree fun term => table.ExprSupport term ∨ + KExpr.AbstractReach ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) 1 body 0 term) + (reading : readScopedExpr? resolve (fresh :: locals) body = some source) : + readScopedExpr? resolve locals (abstractFVars body #[fresh] table).1 1 = some source ∧ + (abstractFVars body #[fresh] table).2.WF := by + obtain ⟨result, coherent⟩ := abstractFVars_singleton_spec constructed (by omega) + faithful coherent (fun _ => Or.inl) (fun _ => Or.inr) + refine ⟨?_, coherent⟩ + rw [result] + exact readScopedExpr?_abstractFVarsSpec (by simpa using bound) reading + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Context.lean b/Ix/Kernel/Verify/Consistency/Context.lean new file mode 100644 index 000000000..12f49aaaf --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Context.lean @@ -0,0 +1,297 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.ScopedExpr +import Ix.Kernel.Verify.Consistency.Atomic +import Std.Data.HashMap.Lemmas + +/-! +# Production locals and model contexts + +`LocalContextReading` identifies the actual declaration returned by each +active free-variable lookup and reads its type in the full model context. +It contains structural agreement only. The model variable rule supplies +typing for every valuation satisfying that context. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +private local instance : LawfulBEq FVarId where + eq_of_beq := by + intro left right equal + cases left + cases right + congr 1 + exact eq_of_beq equal + rfl {a} := by + cases a with + | mk x => show (x == x) = true; exact beq_self_eq_true x + +theorem localContext_find?_push_same {m : Mode} (context : LocalContext m) + (id : FVarId) (decl : LocalDecl m) : + (context.push id decl).find? id = some decl := by + simp [LocalContext.find?, LocalContext.push, Array.getElem?_push] + +theorem localContext_find?_push_ne {m : Mode} {context : LocalContext m} + {id fresh : FVarId} {decl added : LocalDecl m} + (different : id ≠ fresh) (found : context.find? id = some decl) : + (context.push fresh added).find? id = some decl := by + cases index : context.index[id]? with + | none => simp [LocalContext.find?, index] at found + | some position => + cases value : context.decls[position]? with + | none => simp [LocalContext.find?, index, value] at found + | some pair => + have bound := (Array.getElem?_eq_some_iff.mp value).1 + simp [LocalContext.find?, index, value] at found + simp [LocalContext.find?, LocalContext.push, Std.HashMap.getElem?_insert, + Ne.symm different, index, Array.getElem?_push, Nat.ne_of_lt bound, value, found] + +/-- Every registered id corresponds to the exact type returned by production +lookup. All types are expressed in the full current model context. -/ +structure LocalContextReading {β : Type u} (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (concrete : LocalContext .anon) (context : Model.Context β) : Prop where + distinct : locals.Nodup + length : context.length = locals.length + lookup : ∀ id index, localIndex? locals id = some index → + ∃ decl type, concrete.find? id = some decl ∧ context[index]? = some type ∧ + readScopedExpr? resolve locals decl.ty = some type.erase + +theorem LocalContextReading.empty {β : Type u} + (resolve : Address → Option (ConstRef β)) (concrete : LocalContext .anon) : + LocalContextReading resolve [] concrete [] := by + refine ⟨List.nodup_nil, rfl, ?_⟩ + intro id index found + contradiction + +/-- Pushing a fresh production declaration implements the model's lifted +context extension, including the types of older dependent locals. -/ +theorem LocalContextReading.push {β : Type u} + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {concrete : LocalContext .anon} {context : Model.Context β} + {fresh : FVarId} {decl : LocalDecl .anon} {type : AExpr β} + (agreement : LocalContextReading resolve locals concrete context) + (absent : fresh ∉ locals) + (reading : readScopedExpr? resolve locals decl.ty = some type.erase) : + LocalContextReading resolve (fresh :: locals) (concrete.push fresh decl) + (context.push type) := by + refine ⟨List.nodup_cons.mpr ⟨absent, agreement.distinct⟩, ?_, ?_⟩ + · simp [Model.Context.push, agreement.length] + · intro id index found + by_cases equal : id = fresh + · subst id + simp only [localIndex?, if_true, Option.some.injEq] at found + subst index + refine ⟨decl, type.liftN 1, localContext_find?_push_same _ _ _, rfl, ?_⟩ + simpa only [AExpr.erase_liftN] using readScopedExpr?_push absent reading + · simp only [localIndex?, equal, if_false] at found + obtain ⟨previous, hit, rfl⟩ := Option.map_eq_some_iff.mp found + obtain ⟨oldDecl, oldType, oldFound, oldIndex, oldReads⟩ := agreement.lookup id previous hit + refine ⟨oldDecl, oldType.liftN 1, localContext_find?_push_ne equal oldFound, ?_, ?_⟩ + · simp [Model.Context.push, oldIndex] + · simpa only [AExpr.erase_liftN] using readScopedExpr?_push absent oldReads + +/-- Semantic typing tied to the exact opened expression and returned type. -/ +def ScopedModelTyping {β : Type u} (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) (locals : List FVarId) (context : Model.Context β) + (term type : KExpr .anon) : Prop := + ∃ e A : AExpr β, + readScopedExpr? resolve locals term = some e.erase ∧ + readScopedExpr? resolve locals type = some A.erase ∧ + TypingClaim.{u,v} entries context e A + +theorem ScopedModelTyping.closed {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {term type : KExpr .anon} + (typed : ScopedModelTyping.{u,v} resolve entries [] [] term type) : + ModelTyping.{u,v} resolve entries [] term type := by + obtain ⟨e, A, he, hA, typed⟩ := typed + exact ⟨e, A, readScopedExpr?_closed he, readScopedExpr?_closed hA, typed⟩ + +/-- Computing an inference key changes only its memo table, preserving the +actual free-variable context in every fast, hit, and miss branch. -/ +theorem inferKey_lctx {term : KExpr .anon} {before after : TcState .anon} + {key : Address × Address} + (run : TcM.inferKey term before = .ok key after) : after.lctx = before.lctx := by + unfold TcM.inferKey at run + change EStateM.bind (TcM.ctxAddrForLbr term.lbr) _ before = _ at run + unfold TcM.ctxAddrForLbr at run + change EStateM.bind (fun state => EStateM.bind (get : TcM .anon (TcState .anon)) + _ state) _ before = _ at run + simp only [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] at run + by_cases fast : (term.lbr == 0 || before.ctx.isEmpty) = true + · rw [if_pos fast] at run + cases run; rfl + · rw [if_neg fast] at run + cases cached : before.ctxAddrCache[(before.ctxId, term.lbr)]? with + | none => rw [cached] at run; cases run; rfl + | some address => rw [cached] at run; cases run; rfl + +theorem UncachedInference.localContext {term : KExpr .anon} {before : TcState .anon} + (miss : UncachedInference before term) : miss.keyed.lctx = before.lctx := + inferKey_lctx miss.keyRun + +/-- The actual free-variable inference branch reads its type from the local +context; model typing follows from that same context entry. -/ +theorem inferUncached_fvar_sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {id : FVarId} {index : Nat} + {info : ExprInfo .anon} {name : Mode.anon.F Name} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} + (agreement : LocalContextReading resolve locals before.lctx context) + (registered : localIndex? locals id = some index) + (accepted : RecM.inferUncached inferRec inferOnly (.fvar id name info) + methods before = .ok type after) : + ∃ A : AExpr β, context[index]? = some A ∧ + readScopedExpr? resolve locals type = some A.erase ∧ + TypingClaim.{u,v} entries context (.bvar index) A := by + obtain ⟨decl, A, found, atIndex, reading⟩ := agreement.lookup id index registered + change (RecM.inferUncached inferRec inferOnly (.fvar id name info)).run + methods before = .ok type after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind] at accepted + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ at accepted + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] at accepted + simp only [found] at accepted + cases accepted + exact ⟨A, atIndex, reading, TypingClaim.bvar atIndex⟩ + +/-- Free-variable inference through both cache lookups and the final cache +write, under the same explicit miss boundary as constant inference. -/ +theorem infer_fvar_sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {id : FVarId} {index : Nat} + {info : ExprInfo .anon} {name : Mode.anon.F Name} + {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} + (miss : UncachedInference before (.fvar id name info)) + (agreement : LocalContextReading resolve locals miss.keyed.lctx context) + (registered : localIndex? locals id = some index) + (accepted : RecM.infer (.fvar id name info) methods before = .ok type after) : + ScopedModelTyping.{u,v} resolve entries locals context (.fvar id name info) type := by + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + obtain ⟨A, _, reading, typed⟩ := inferUncached_fvar_sound agreement registered run + exact ⟨.bvar index, A, by simp [readScopedExpr?, registered, AExpr.erase], reading, typed⟩ + +/-- A free-variable cache entry must be the exact type returned by its +current production declaration. This is a check on concrete data at one key; +it does not assert semantic typing of a cached answer. -/ +structure FVarInferenceSupport (before : TcState .anon) (id : FVarId) + (name : Mode.anon.F Name) (info : ExprInfo .anon) where + key : Address × Address + keyed : TcState .anon + keyRun : TcM.inferKey (.fvar id name info) before = .ok key keyed + fullMatches : ∀ cached decl, keyed.env.inferCache[key]? = some cached → + keyed.lctx.find? id = some decl → cached = decl.ty + onlyMatches : ∀ cached decl, keyed.env.inferOnlyCache[key]? = some cached → + keyed.lctx.find? id = some decl → cached = decl.ty + +def FVarInferenceSupport.ofMiss {before : TcState .anon} {id : FVarId} + {name : Mode.anon.F Name} {info : ExprInfo .anon} + (miss : UncachedInference before (.fvar id name info)) : + FVarInferenceSupport before id name info := { + key := miss.key, keyed := miss.keyed, keyRun := miss.keyRun + fullMatches := by intros; simp_all [miss.fullMiss] + onlyMatches := by intros; simp_all [miss.onlyMiss] +} + +/-- Local inference returns the actual declaration type through either cache +partition or the uncached lookup, including the final cache insertion. -/ +theorem FVarInferenceSupport.output {before after : TcState .anon} {id : FVarId} + {name : Mode.anon.F Name} {info : ExprInfo .anon} {decl : LocalDecl .anon} + {methods : Methods .anon} {type : KExpr .anon} + (support : FVarInferenceSupport before id name info) + (found : support.keyed.lctx.find? id = some decl) + (accepted : RecM.infer (.fvar id name info) methods before = .ok type after) : + type = decl.ty := by + change (RecM.infer (.fvar id name info)).run methods before = .ok type after at accepted + unfold RecM.infer RecM.inferWith at accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.inferKey (.fvar id name info)) _ before = _ at accepted + rw [EStateM.bind, support.keyRun] at accepted + change EStateM.bind (get : TcM .anon (TcState .anon)) _ support.keyed = _ at accepted + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) support.keyed = + .ok support.keyed support.keyed from rfl] at accepted + cases full : support.keyed.env.inferCache[support.key]? with + | some cached => + simp only [full] at accepted + cases accepted + exact support.fullMatches _ _ full found + | none => + simp only [full] at accepted + cases policy : before.inferOnly with + | false => + simp only [policy, Bool.false_eq_true, if_false] at accepted + have lookup : RecM.inferUncached RecM.inferCall false (.fvar id name info) + methods support.keyed = .ok decl.ty support.keyed := by + change (RecM.inferUncached RecM.inferCall false (.fvar id name info)).run + methods support.keyed = _ + unfold RecM.inferUncached + simp only [ReaderT.run_bind] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ support.keyed = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) support.keyed = + .ok support.keyed support.keyed from rfl] + simp only [found] + rfl + change EStateM.bind (RecM.inferUncached RecM.inferCall false (.fvar id name info) methods) + _ support.keyed = _ at accepted + rw [EStateM.bind, lookup] at accepted + cases accepted + rfl + | true => + simp only [policy, if_true, ReaderT.run_bind] at accepted + change EStateM.bind (get : TcM .anon (TcState .anon)) _ support.keyed = _ at accepted + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) support.keyed = + .ok support.keyed support.keyed from rfl] at accepted + cases only : support.keyed.env.inferOnlyCache[support.key]? with + | some cached => + simp only [only] at accepted + cases accepted + exact support.onlyMatches _ _ only found + | none => + simp only [only] at accepted + have lookup : RecM.inferUncached RecM.inferCall true (.fvar id name info) + methods support.keyed = .ok decl.ty support.keyed := by + change (RecM.inferUncached RecM.inferCall true (.fvar id name info)).run + methods support.keyed = _ + unfold RecM.inferUncached + simp only [ReaderT.run_bind] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ support.keyed = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) support.keyed = + .ok support.keyed support.keyed from rfl] + simp only [found] + rfl + change EStateM.bind (RecM.inferUncached RecM.inferCall true + (.fvar id name info) methods) _ support.keyed = _ at accepted + rw [EStateM.bind, lookup] at accepted + cases accepted + rfl + +theorem FVarInferenceSupport.sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {before after : TcState .anon} + {id : FVarId} {name : Mode.anon.F Name} {info : ExprInfo .anon} + {index : Nat} {A : AExpr β} {methods : Methods .anon} {type : KExpr .anon} + (support : FVarInferenceSupport before id name info) + (agreement : LocalContextReading resolve locals before.lctx context) + (registered : localIndex? locals id = some index) + (atIndex : context[index]? = some A) + (accepted : RecM.infer (.fvar id name info) methods before = .ok type after) : + readScopedExpr? resolve locals type = some A.erase ∧ + TypingClaim.{u,v} entries context (.bvar index) A := by + have keyedAgreement := (inferKey_lctx support.keyRun).symm ▸ agreement + obtain ⟨decl, B, found, position, reading⟩ := keyedAgreement.lookup id index registered + have equal := Option.some.inj (position.symm.trans atIndex) + subst B + rw [support.output found accepted] + exact ⟨reading, TypingClaim.bvar atIndex⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Level.lean b/Ix/Kernel/Verify/Consistency/Level.lean index 59441f43d..f6155f54c 100644 --- a/Ix/Kernel/Verify/Consistency/Level.lean +++ b/Ix/Kernel/Verify/Consistency/Level.lean @@ -43,6 +43,15 @@ theorem readLevel_eq (u : KUniv m) : readLevel u = u.toVLevel := by readLevel (KUniv.mkSucc u) = .succ (readLevel u) := by rw [readLevel_eq, KUniv.toVLevel_mkSucc, ← readLevel_eq] +/-- The simplifying Pi-universe constructor preserves evaluation on its +finite input subterms, including its Prop and nonzero branches. -/ +theorem readLevel_mkIMax {left right : KUniv m} + (faithful : ∀ a b, (KUniv.Sub a left ∨ KUniv.Sub a right) → + (KUniv.Sub b left ∨ KUniv.Sub b right) → a.AddrFaithful b) + (leftBound : left.size < UInt64.size) (rightBound : right.size < UInt64.size) : + readLevel (KUniv.mkIMax left right) ≈ .imax (readLevel left) (readLevel right) := by + simpa only [readLevel_eq] using KUniv.toVLevel_mkIMax faithful leftBound rightBound + /-- The structural reader preserves universe evaluation. -/ theorem readLevel_eval (levels : List Nat) (u : KUniv m) : (readLevel u).eval levels = u.toVLevel.eval levels := by diff --git a/Ix/Kernel/Verify/Consistency/Production.lean b/Ix/Kernel/Verify/Consistency/Production.lean index 0ae6cc111..f064fabaa 100644 --- a/Ix/Kernel/Verify/Consistency/Production.lean +++ b/Ix/Kernel/Verify/Consistency/Production.lean @@ -5,6 +5,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 import Ix.Kernel.Driver import Ix.Kernel.Verify.Consistency.Constant +import Ix.Kernel.Verify.Consistency.BinderInference /-! # Standalone production declaration checks @@ -97,16 +98,20 @@ structure DefinitionInput where def DefinitionInput.constant (input : DefinitionInput) : KConst .anon := .defn () () input.kind input.safety input.hints 0 input.type input.value () input.block -/-- Closed sort/alias inference, or a specialization of an existing constant. -The declared type supplies only raw syntax and occurrence annotations. Its -typing, scope, and references are derived from successful production inference. -/ +/-- Closed sort/alias inference, a specialization of an existing constant, +or a finite binder inference tree with a separately checked declared type. +Specializations supply raw syntax and occurrence annotations; successful +inference derives their typing, scope, and references. Binder definitions +also supply syntactic scope and empty constant-reference inventories. Every +case derives body typing without a semantic typing premise. -/ inductive DefinitionBodySupport {β : Type u} (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) + (methods : Methods .anon) (before : TcState .anon) (declared : KExpr .anon) : KExpr .anon → AExpr β → AExpr β → Type u | atomic {term : KExpr .anon} {body type : AExpr β} (inference : AtomicInference resolve entries before term body type) : - DefinitionBodySupport resolve entries before declared term body type + DefinitionBodySupport resolve entries methods before declared term body type | specialization {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} (misses : UncachedInference before (.const id arguments info)) @@ -115,14 +120,25 @@ inductive DefinitionBodySupport {β : Type u} (reading : readExpr? resolve declared = some type.erase) (conditions : (entry.type.instL (arguments.toList.map readLevel)).annotations = type.annotations) : - DefinitionBodySupport resolve entries before declared (.const id arguments info) + DefinitionBodySupport resolve entries methods before declared (.const id arguments info) (.const ref (arguments.toList.map readLevel)) type + | binder {fuel : Nat} {term inferredType : KExpr .anon} + {body type : AExpr β} {level : VLevel} {typeBefore typeAfter : TcState .anon} + (tied : methods = methodsN fuel) + (valueInference : BinderInference resolve entries [] [] fuel before term body type) + (typeInference : BinderInference resolve entries [] [] fuel typeBefore declared type (.sort level)) + (typeRun : RecM.infer declared methods typeBefore = .ok inferredType typeAfter) + (valueReading : readScopedExpr? resolve [] term = some body.erase) + (typeReading : readScopedExpr? resolve [] declared = some type.erase) + (scope : body.Scope 0 0 ∧ type.Scope 0 0) + (noConstants : body.references = [] ∧ type.references = []) : + DefinitionBodySupport resolve entries methods before declared term body type theorem DefinitionBodySupport.sound {β : Type u} {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} {before after : TcState .anon} {term declared inferred : KExpr .anon} {body type : AExpr β} {methods : Methods .anon} - (fragment : DefinitionBodySupport resolve entries before declared term body type) + (fragment : DefinitionBodySupport resolve entries methods before declared term body type) (wellFormed : entries.WF) (accepted : RecM.infer term methods before = .ok inferred after) (faithful : inferred.AddrFaithful declared) (hashPath : (inferred == declared) = true) : @@ -158,6 +174,18 @@ theorem DefinitionBodySupport.sound {β : Type u} · intro ref member rw [← equal, references] at member exact wellFormed.typeReferences _ _ support.found ref member + | binder tied valueInference typeInference typeRun valueReading typeReading scope noConstants => + subst methods + obtain ⟨_, typeChecked⟩ := typeInference.sound (LocalContextReading.empty _ _) + typeReading typeRun + obtain ⟨_, valueChecked⟩ := valueInference.sound (LocalContextReading.empty _ _) + valueReading accepted + refine ⟨readScopedExpr?_closed valueReading, readScopedExpr?_closed typeReading, + scope.1, scope.2, ?_, ?_, valueChecked.typing typeChecked.typingSort⟩ + · intro ref member + simp only [noConstants.1, List.not_mem_nil] at member + · intro ref member + simp only [noConstants.2, List.not_mem_nil] at member /-- The execution prefix through value conversion. A successful member check also passes the subsequent safety checks. -/ @@ -224,7 +252,8 @@ structure AtomicDefinitionRun {β : Type u} (resolve : Address → Option (Const (body type : AExpr β) where path : StandalonePrefix input.id before input.constant inference : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, - DefinitionBodySupport resolve entries trace.valueStart input.type input.value body type + DefinitionBodySupport resolve entries (methodsN before.recFuel.toNat) + trace.valueStart input.type input.value body type hashPath : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, (trace.inferredValue == input.type) = true faithful : ∀ trace : DefinitionBodyTrace input (methodsN before.recFuel.toNat) path.ready, diff --git a/Ix/Kernel/Verify/Consistency/ScopedExpr.lean b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean new file mode 100644 index 000000000..94caa9729 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean @@ -0,0 +1,258 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Expr +import Ix.Theory.Model.LevelCongruence + +/-! +# Reading opened binders + +The production binder paths use free variables for their active locals. +`readScopedExpr?` maps those identifiers to model de Bruijn indices, keeping +syntactically bound variables distinct from active locals. Unknown free +variables and loose legacy variables fail. This binder fragment also excludes +lets and strings; the original closed reader remains available independently. + +The local identifier list is newest first, matching `Model.Context.push`. +No local declaration's type or semantic validity is assumed by this reader. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u +variable {β : Type u} {m : Mode} + +def localIndex? (locals : List FVarId) (id : FVarId) : Option Nat := + match locals with + | [] => none + | head :: rest => if id = head then some 0 else (localIndex? rest id).map Nat.succ + +theorem localIndex?_mem {locals : List FVarId} {id : FVarId} {index : Nat} + (found : localIndex? locals id = some index) : id ∈ locals := by + induction locals generalizing index with + | nil => contradiction + | cons head rest ih => + by_cases equal : id = head + · simp [equal] + · simp only [localIndex?, equal, if_false] at found + obtain ⟨previous, found, _⟩ := Option.map_eq_some_iff.mp found + exact List.mem_cons_of_mem _ (ih found) + +theorem localIndex?_getElem {locals : List FVarId} {id : FVarId} {index : Nat} + (found : localIndex? locals id = some index) : locals[index]? = some id := by + induction locals generalizing index with + | nil => contradiction + | cons head rest ih => + by_cases equal : id = head + · simp only [localIndex?, equal, if_true, Option.some.injEq] at found + subst index + simp [equal] + · simp only [localIndex?, equal, if_false] at found + obtain ⟨previous, hit, rfl⟩ := Option.map_eq_some_iff.mp found + exact ih hit + +theorem localIndex?_fresh {locals : List FVarId} {id fresh : FVarId} {index : Nat} + (absent : fresh ∉ locals) (found : localIndex? locals id = some index) : + localIndex? (fresh :: locals) id = some (index + 1) := by + have different : id ≠ fresh := fun equal => absent (equal ▸ localIndex?_mem found) + simp [localIndex?, different, found] + +/-- Structural reading in the currently opened local context. `depth` counts +only syntactic binders still present inside the expression. -/ +def readScopedExpr? (resolve : Address → Option (ConstRef β)) (locals : List FVarId) : + KExpr m → (depth : Nat := 0) → Option (VExpr β) + | .var index _ _, depth => + if index.toNat < depth then some (.bvar index.toNat) else none + | .fvar id _ _, depth => + (localIndex? locals id).map (fun index => .bvar (depth + index)) + | .sort level _, _ => some (.sort (readLevel level)) + | .const id levels _, _ => do + return .const (← resolve id.addr) (levels.toList.map readLevel) + | .app fn arg _, depth => do + return .app (← readScopedExpr? resolve locals fn depth) + (← readScopedExpr? resolve locals arg depth) + | .lam _ _ domain body _, depth => do + return .lam (← readScopedExpr? resolve locals domain depth) + (← readScopedExpr? resolve locals body (depth + 1)) + | .all _ _ domain body _, depth => do + return .forallE (← readScopedExpr? resolve locals domain depth) + (← readScopedExpr? resolve locals body (depth + 1)) + | .prj id index value _, depth => do + return .proj (← resolve id.addr) index.toNat + (← readScopedExpr? resolve locals value depth) + | .nat value _ _, _ => some (.natLit value) + | .letE .., _ | .str .., _ => none + +@[simp] theorem readScopedExpr?_mkVar (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (index : UInt64) (name : m.F Name) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkVar index name) depth = + if index.toNat < depth then some (.bvar index.toNat) else none := rfl + +@[simp] theorem readScopedExpr?_mkFVar (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (id : FVarId) (name : m.F Name) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkFVar id name) depth = + (localIndex? locals id).map (fun index => .bvar (depth + index)) := rfl + +@[simp] theorem readScopedExpr?_mkSort (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (level : KUniv m) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkSort level) depth = some (.sort (readLevel level)) := rfl + +@[simp] theorem readScopedExpr?_mkApp (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (fn arg : KExpr m) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkApp fn arg) depth = do + return .app (← readScopedExpr? resolve locals fn depth) + (← readScopedExpr? resolve locals arg depth) := rfl + +@[simp] theorem readScopedExpr?_mkLam (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (name : m.F Name) (bi : m.F Lean.BinderInfo) + (domain body : KExpr m) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkLam name bi domain body) depth = do + return .lam (← readScopedExpr? resolve locals domain depth) + (← readScopedExpr? resolve locals body (depth + 1)) := rfl + +@[simp] theorem readScopedExpr?_mkAll (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (name : m.F Name) (bi : m.F Lean.BinderInfo) + (domain body : KExpr m) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkAll name bi domain body) depth = do + return .forallE (← readScopedExpr? resolve locals domain depth) + (← readScopedExpr? resolve locals body (depth + 1)) := rfl + +@[simp] theorem readScopedExpr?_mkPrj (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (id : KId m) (index : UInt64) (value : KExpr m) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkPrj id index value) depth = do + return .proj (← resolve id.addr) index.toNat + (← readScopedExpr? resolve locals value depth) := rfl + +private theorem option_bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ intermediate, action = some intermediate ∧ next intermediate = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +theorem readScopedExpr?_lam_parts {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {name : m.F Name} {bi : m.F Lean.BinderInfo} + {domain body : KExpr m} {info : ExprInfo m} {A b : VExpr β} {depth : Nat} + (reading : readScopedExpr? resolve locals (.lam name bi domain body info) depth = + some (.lam A b)) : + readScopedExpr? resolve locals domain depth = some A ∧ + readScopedExpr? resolve locals body (depth + 1) = some b := by + rw [readScopedExpr?] at reading + obtain ⟨A', domainReads, reading⟩ := option_bind_success reading + obtain ⟨b', bodyReads, reading⟩ := option_bind_success reading + cases reading + exact ⟨domainReads, bodyReads⟩ + +theorem readScopedExpr?_all_parts {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {name : m.F Name} {bi : m.F Lean.BinderInfo} + {domain body : KExpr m} {info : ExprInfo m} {A B : VExpr β} {depth : Nat} + (reading : readScopedExpr? resolve locals (.all name bi domain body info) depth = + some (.forallE A B)) : + readScopedExpr? resolve locals domain depth = some A ∧ + readScopedExpr? resolve locals body (depth + 1) = some B := by + rw [readScopedExpr?] at reading + obtain ⟨A', domainReads, reading⟩ := option_bind_success reading + obtain ⟨B', bodyReads, reading⟩ := option_bind_success reading + cases reading + exact ⟨domainReads, bodyReads⟩ + +/-- Closing the local context recovers the original reader exactly. -/ +theorem readScopedExpr?_closed {resolve : Address → Option (ConstRef β)} + {term : KExpr m} {source : VExpr β} {depth : Nat} + (reading : readScopedExpr? resolve [] term depth = some source) : + readExpr? resolve term = some source := by + induction term generalizing source depth with + | var index name info => + simp only [readScopedExpr?] at reading + split at reading + · exact reading + · contradiction + | fvar _ _ _ | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | sort _ _ | const _ _ _ | nat _ _ _ => exact reading + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readScopedExpr?] at reading + obtain ⟨f, fReads, reading⟩ := option_bind_success reading + obtain ⟨a, aReads, reading⟩ := option_bind_success reading + cases reading + simp [readExpr?, hf fReads, ha aReads] + | prj id index value info ih => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := option_bind_success reading + obtain ⟨value, valueReads, reading⟩ := option_bind_success reading + cases reading + simp [readExpr?, resolved, ih valueReads] + +@[simp] theorem readScopedExpr?_eraseMeta + (resolve : Address → Option (ConstRef β)) (locals : List FVarId) + (term : KExpr m) (depth : Nat) : + readScopedExpr? resolve locals term.eraseMeta depth = + readScopedExpr? resolve locals term depth := by + induction term generalizing depth <;> + simp_all [readScopedExpr?, KExpr.eraseMeta, KId.eraseMeta, + Array.toList_map, List.map_map, Function.comp_def] + +theorem beq_readScopedExpr? {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {left right : KExpr m} {depth : Nat} + (faithful : left.AddrFaithful right) (equal : (left == right) = true) : + readScopedExpr? resolve locals left depth = readScopedExpr? resolve locals right depth := by + have erased := faithful (KExpr.beq_def left right ▸ equal) + simpa only [readScopedExpr?_eraseMeta] using + congrArg (fun term => readScopedExpr? resolve locals term depth) erased + +theorem internExpr_readScopedExpr? {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {table : InternTable m} {term : KExpr m} {depth : Nat} + (coherent : table.WF) + (faithful : KExpr.KeyCollisionFree fun value => table.ExprSupport value ∨ value = term) : + readScopedExpr? resolve locals (table.internExpr term).1 depth = + readScopedExpr? resolve locals term depth := by + simpa only [readScopedExpr?_eraseMeta] using + congrArg (fun term => readScopedExpr? resolve locals term depth) + (table.internExpr_eraseMeta coherent faithful) + +/-- A fresh local shifts every existing local occurrence by one, below the +syntactic binders. Reading success excludes a hidden occurrence of the new id. -/ +theorem readScopedExpr?_push {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {term : KExpr m} {source : VExpr β} {depth : Nat} + {fresh : FVarId} (absent : fresh ∉ locals) + (reading : readScopedExpr? resolve locals term depth = some source) : + readScopedExpr? resolve (fresh :: locals) term depth = some (source.liftN 1 depth) := by + induction term generalizing source depth with + | var index name info => + simp only [readScopedExpr?] at reading ⊢ + split at reading + next bound => + cases reading + simp [bound, VExpr.liftN, liftVar] + · contradiction + | fvar id name info => + rw [readScopedExpr?] at reading + obtain ⟨index, found, reading⟩ := Option.map_eq_some_iff.mp reading + cases reading + simp [readScopedExpr?, localIndex?_fresh absent found, VExpr.liftN, liftVar, + Nat.not_lt.mpr (Nat.le_add_right depth index), Nat.add_assoc, Nat.add_comm 1] + | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | sort level info => cases reading; rfl + | nat value name info => cases reading; rfl + | const id levels info => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := option_bind_success reading + cases reading + simp [readScopedExpr?, resolved, VExpr.liftN] + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readScopedExpr?] at reading + obtain ⟨f, fReads, reading⟩ := option_bind_success reading + obtain ⟨a, aReads, reading⟩ := option_bind_success reading + cases reading + simp [readScopedExpr?, hf fReads, ha aReads, VExpr.liftN] + | prj id index value info ih => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := option_bind_success reading + obtain ⟨value, valueReads, reading⟩ := option_bind_success reading + cases reading + simp [readScopedExpr?, resolved, ih valueReads, VExpr.liftN] + +end Ix.Kernel.Consistency diff --git a/Ix/Theory/Model/Checking.lean b/Ix/Theory/Model/Checking.lean new file mode 100644 index 000000000..3e9836ae3 --- /dev/null +++ b/Ix/Theory/Model/Checking.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Judgment + +/-! +# Checking against a formed type + +Inference of a lambda constructs a dependent function type from the body's +inferred type. It does not independently infer the sort of that codomain. +`CheckingClaim` defers hereditary validity of the expected type until the +declaration's separate type check establishes it. Its rule producers still +quantify over every dependency model, level valuation, and valid context. +-/ + +namespace Ix.Theory.Model + +open SetTheory SetModel Certified + +universe u v +variable {β : Type u} {entries : Environment β} {Γ : Context β} + +def CheckingClaim (entries : Environment β) (Γ : Context β) (e A : AExpr β) : Prop := + ∀ (V : Type v) [SetTheory V] (constants : Assignment β V), + Realizes constants entries → ∀ levels env, Γ.Valid constants levels env → + WellDenoted constants levels env A → + WellDenoted constants levels env e ∧ + interp constants levels env e ∈ˢ interp constants levels env A + +theorem TypingClaim.checking {e A : AExpr β} (typed : TypingClaim.{u,v} entries Γ e A) : + CheckingClaim.{u,v} entries Γ e A := by + intro V _ constants realizes levels env valid _ + have checked := typed V constants realizes levels env valid + exact ⟨checked.1, checked.2.2⟩ + +namespace CheckingClaim + +theorem typing {e A : AExpr β} {level : VLevel} + (checked : CheckingClaim.{u,v} entries Γ e A) + (formed : TypingClaim.{u,v} entries Γ A (.sort level)) : + TypingClaim.{u,v} entries Γ e A := by + intro V _ constants realizes levels env valid + have typeValid := (formed V constants realizes levels env valid).1 + have result := checked V constants realizes levels env valid typeValid + exact ⟨result.1, typeValid, result.2⟩ + +theorem typingSort {e : AExpr β} {level : VLevel} + (checked : CheckingClaim.{u,v} entries Γ e (.sort level)) : + TypingClaim.{u,v} entries Γ e (.sort level) := + checked.typing (TypingClaim.sort level) + +/-- The expected Pi supplies a uniform codomain universe and hereditary +validity, including the Prop regime when the domain is empty. -/ +theorem lam {A B body : AExpr β} {condition : PropWhen} + (checked : CheckingClaim.{u,v} entries (Γ.push A) body B) : + CheckingClaim.{u,v} entries Γ (.lam condition A body) (.forallE condition A B) := by + intro V _ constants realizes levels env valid formed + obtain ⟨domainValid, bodyValid, codomainLevel, regimeAgrees, inUniverse⟩ := formed + have bodyChecked x hx := checked V constants realizes levels (Valuation.cons x env) + (valid.push domainValid hx) (bodyValid x hx) + refine ⟨⟨domainValid, fun x hx => (bodyChecked x hx).1, codomainLevel, + (fun x => interp constants levels (Valuation.cons x env) B), regimeAgrees, + fun x hx => ⟨(bodyChecked x hx).2, inUniverse x hx⟩⟩, ?_⟩ + exact lamR_mem (fun x hx => (bodyChecked x hx).2) + +end CheckingClaim +end Ix.Theory.Model diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 9a067b61d..780b03081 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -5,8 +5,8 @@ public import Ix.Kernel public import Tests.Ix.Kernel.IxonFixtures /-! -Production regressions for the atomic consistency fragment and polymorphic -constant inference. These execute the lazy loader, inference, and serial driver +Production regressions for the consistency fragment, polymorphic constant +inference, and dependent binders. These execute the lazy loader, inference, and serial driver on content-addressed Ixon declarations. The theorems and their resource premises are checked separately by `IxKernelConsistency`. -/ @@ -238,6 +238,71 @@ private def specializationCases : TestSeq := ++ test "polymorphic environment: a monomorphic body cannot retain a universe parameter" (let (env, target) := failedSpecialization #[0] (.var 0); rowFailed env target) -public def suite : List TestSeq := [cases, polymorphicCases, specializationCases] +/-- Real function bodies, with no source axiom supplying their values: +`idProp (P : Prop) (p : P) : P := p`, its Type analogue, and a theorem alias. -/ +private def binderEnvironment : Ixon.Env := Id.run do + let type := Ixon.Expr.leanAll (.sort 0) (.leanAll (.var 0) (.var 1)) + let value := Ixon.Expr.leanLam (.sort 0) (.leanLam (.var 0) (.var 0)) + let (env, propIdentity) := storeConst {} + ⟨.defn ⟨.defn, .safe, 0, type, value⟩, #[], #[], #[.zero]⟩ + let (env, _) := storeConst env + ⟨.defn ⟨.opaq, .safe, 0, type, value⟩, #[], #[], #[.succ .zero]⟩ + let (env, _) := storeConst env + ⟨.defn ⟨.thm, .safe, 0, type, .ref 0 #[]⟩, #[], #[propIdentity], #[.zero]⟩ + return env + +private def failedBinder (body : Ixon.Expr) : Ixon.Env × Address := + storeConst {} + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), + .leanLam (.sort 0) (.leanLam (.var 0) body)⟩, #[], #[], #[.zero]⟩ + +/-- Inferring the same older local after a dependent push must reuse its +concrete type. Both cache partitions and scope cleanup are observable here. -/ +private def dependentLocalCache (inferOnly : Bool) : Bool := + let propType := KExpr.mkSort (m := .anon) .mkZero + let action : RecM .anon Bool := RecM.withLctxScope do + let (first, firstId) ← TcM.openBinder () () propType (.mkVar 0 ()) + let firstType ← RecM.inferCall first + let (_, secondId) ← TcM.openBinder () () first (.mkVar 1 ()) + let cachedType ← RecM.inferCall first + let state ← get + let key ← TcM.inferKey first + return firstId != secondId && firstType.addr == propType.addr && + cachedType.addr == propType.addr && state.lctx.size == 2 && + (if inferOnly then state.env.inferOnlyCache[key]?.isSome + else state.env.inferCache[key]?.isSome) + match TcM.runRec action { TcState.ofEnvAnon {} with inferOnly } with + | .ok passed after => passed && after.lctx.size == 0 && after.env.nextFVarId == 2 + | .error _ _ => false + +private def nestedBinderInference (inferOnly : Bool) : Bool := + let propType := KExpr.mkSort (m := .anon) .mkZero + let type := KExpr.mkAll () () propType (.mkAll () () (.mkVar 0 ()) (.mkVar 1 ())) + let body := KExpr.mkLam () () propType (.mkLam () () (.mkVar 0 ()) (.mkVar 0 ())) + match TcM.infer body { TcState.ofEnvAnon {} with inferOnly } with + | .ok inferred after => inferred.addr == type.addr && after.lctx.size == 0 && + after.env.nextFVarId == 2 + | .error _ _ => false + +private def binderCases : TestSeq := + test "binder environment: real Prop and Type identity bodies and theorem alias check" + (allSucceeded binderEnvironment 3 { clearEvery := 0 }) + ++ test "binder environment: identity bodies check with fresh per-item caches" + (allSucceeded binderEnvironment 3 { clearEvery := 1 }) + ++ test "binder inference: nested dependent lambdas close their local context" + (nestedBinderInference false) + ++ test "binder inference: inference-only lambdas return the same closed type" + (nestedBinderInference true) + ++ test "binder cache: full-mode lookup survives a newer dependent local" + (dependentLocalCache false) + ++ test "binder cache: inference-only lookup survives a newer dependent local" + (dependentLocalCache true) + ++ test "binder environment: returning the type variable instead of its witness fails" + (let (env, target) := failedBinder (.var 1); rowFailed env target) + ++ test "binder environment: an escaping bound variable fails validation" + (let (env, target) := failedBinder (.var 2); rowFailed env target) + +public def suite : List TestSeq := [cases, polymorphicCases, specializationCases, binderCases] end Tests.Kernel.Consistency diff --git a/Tests/Theory/ImportManifest.lean b/Tests/Theory/ImportManifest.lean index f074c0b9f..ee4f7d141 100644 --- a/Tests/Theory/ImportManifest.lean +++ b/Tests/Theory/ImportManifest.lean @@ -16,7 +16,9 @@ def lean4IxBaseRevision : String := "ab42e79e2a4e2615a3ca6ef983d510f374057a38" def conLecheRevision : String := "86cd20a65660d757cedc81561a44579099b565d0" /-- New mathematical modules authored in Ix, with no imported source hash. -/ -def authored : Array String := #["Ix/Theory/Model/LevelCongruence.lean"] +def authored : Array String := #[ + "Ix/Theory/Model/Checking.lean", "Ix/Theory/Model/LevelCongruence.lean" +] structure SourceFile where source : String diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 10357a0c9..92485e5b5 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -30,8 +30,10 @@ increasing sequence of strongly inaccessible cardinals. under the existing finite address-faithfulness and arithmetic bounds. - A structural reader maps kernel expressions to model syntax, resolves addresses to explicit store references, preserves projections and natural - literals, and substitutes let values. Free variables, unresolved addresses, - and string literals are outside the current reader's domain. + literals, and substitutes let values. This closed reader excludes free + variables, unresolved addresses, and string literals. The binder reader + `readScopedExpr?` maps registered free variables to model context indices; + unknown locals, loose legacy variables, lets, and strings fail that reader. - Hash equality and intern-table reuse preserve that reading under their stated address/key collision assumptions. Metadata cannot change it. - `inferUncached_sort_sound` interprets an actual successful execution of the @@ -56,6 +58,15 @@ increasing sequence of strongly inaccessible cardinals. - `ModelTyping.no_false` rules out a closed model-typed kernel expression at primitive False when its environment has been admitted by the certified interface and the set-theory assumption has an instance. +- `BinderInference.sound` follows finite production inference trees for sorts, + locals, dependent functions, and full-mode lambdas. `LocalContextReading.push` + and `openBinder_sound` connect actual declaration lookup and fresh-variable + opening to the model's dependent context. Singleton abstraction closes the + resulting function type, and the simplifying `imax` constructor preserves + its universe interpretation. +- `FVarInferenceSupport.sound` handles both local-variable cache partitions + when a cached answer equals the current declaration's concrete type. These + are structural cache checks, with no assumed semantic typing of cached data. - `checkEnvAnon_atomic_preserves_model` connects a supported production environment run to model extension. `checkEnvAnon_atomic_no_false` excludes a declaration at an axiom type interpreted as empty, including False. @@ -78,9 +89,9 @@ these axioms. The hypothesis is model existence; a theorem connecting arbitrary syntactic consistency to model existence is outside this result. The fragment covers monomorphic standalone definitions, theorems, -and opaque definitions whose values are either closed universe terms or -references to preceding interface entries, including monomorphic -specializations of polymorphic constants. Referenced types may contain +and opaque definitions whose values are closed universe terms, references to +preceding interface entries, monomorphic specializations of polymorphic +constants, or closed function bodies in the binder fragment. Referenced types may contain dependent functions and other readable expression forms. Examples include: ```lean @@ -91,6 +102,7 @@ theorem r : P := q def typeAlias : Type := Prop axiom ident.{u} : (α : Sort u) → α → α def propIdent : (α : Prop) → α → α := ident.{0} +def idProp (P : Prop) (p : P) : P := p ``` `AtomicEnvironmentFragment` records the precise execution boundary: @@ -98,7 +110,9 @@ def propIdent : (α : Prop) → α → α := ident.{0} - Every source key occurs in the `buildAnonWork` result, and every work item represents an axiom or a definition. Lookup, routing, and reset witnesses identify the checked `KConst`. -- Value inference misses both cache partitions. Constant lookup agrees with +- Sort, constant, forall, and lambda nodes in the inference witnesses miss both cache partitions. + Local-variable hits must match the current production declaration type. + Constant lookup agrees with an already admitted type and universe count. A specialization supplies closed universe arguments and finite interning/substitution resources at the actual post-lookup state. The occurrence annotations on the declared @@ -106,6 +120,16 @@ def propIdent : (α : Prop) → α → α := ident.{0} data checks; successful inference derives typing, scope, and references. Ordinary aliases retain the simpler empty-substitution path. Sort inference retains finite interning coherence and address-faithfulness premises. +- Binder definitions supply finite inference trees for both the value and its + separately checked declared type, exact source readings, closed annotated + syntax, and empty constant-reference lists. Recursive calls use the actual + smaller method table. Binder-opening and abstraction resources cover fresh + ids, context preservation during domain inference, intern-table coherence, + finite collision freedom, and bounds preventing index overflow. Sort + exposures are syntactic; lambdas use full mode and the unchanged cheap-beta + path. `CheckingClaim` derives body validity and membership once declared-type + inference establishes hereditary validity. No codomain-typing premise is + added to the production proof. - Conversion takes the initial hash-equality path, with faithfulness of the compared expressions. General reduction and conversion caches are outside this fragment. @@ -121,9 +145,9 @@ Callers must establish these operational and representation witnesses for the run. They supply no typing or checker-soundness premise. The proof extracts the validation, type-inference, theorem-guard, value-inference, and conversion steps from public success, then derives body typing to extend -the preceding model. Automatic witness construction, lambdas, applications, -inductives, coordinated blocks, and other conversion paths remain outside the -fragment. Polymorphic constant inference is composed into declaration +the preceding model. Automatic witness construction, application inference, +lets, more general lambda paths, inductives, coordinated blocks, and other +conversion paths remain outside the fragment. Polymorphic constant inference is composed into declaration admission and model extension for the monomorphic specializations described above. Definitions with their own universe parameters remain outside this environment fragment. @@ -177,7 +201,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 66 exact theorem boundaries. The production +The consistency target checks 101 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -187,9 +211,10 @@ The production roots additionally forbid the abstract `CheckSuccessSound`/`SupportedCheckFragment` interfaces and the independent certificate validator in their dependency closures. -The polymorphic inference and substitution roots retain only the two existing +The polymorphic inference, substitution, and binder inference roots retain only the two existing expression/universe output-length proofs, alongside the standard Lean axioms. Their model-side level congruence introduces no native proof dependency. +Semantic checking against a formed type also uses only standard Lean axioms. Kernel unit regressions cover lazy loading, both inference policies, interning reuse, dependent function types, shared references, lets, `imax` simplification, argument order, and rejection of wrong arities and out-of-range parameters. @@ -223,6 +248,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Certified checker contracts | [`Ix/Kernel/Certified.lean`](../Ix/Kernel/Certified.lean), [`CertifiedClaims.lean`](../Ix/Kernel/CertifiedClaims.lean) | | Direct production refinement and its audit | [`Ix/Kernel/Verify/Consistency.lean`](../Ix/Kernel/Verify/Consistency.lean) | | Polymorphic inference and universe substitution | [`Consistency/Constant.lean`](../Ix/Kernel/Verify/Consistency/Constant.lean), [`InstUniv.lean`](../Ix/Kernel/Verify/Consistency/InstUniv.lean), [`Model/LevelCongruence.lean`](../Ix/Theory/Model/LevelCongruence.lean) | +| Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | | Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | @@ -236,5 +262,6 @@ fixtures used by the existing proofs. Source hashes and attribution are in [`Tests/Theory/NamedManifest.lean`](../Tests/Theory/NamedManifest.lean); the Apache license is preserved alongside the sources. The axiom-audit helper and direct production-fragment proofs are authored in Ix. -`Model/LevelCongruence.lean` is an Ix-authored mathematical addition, listed +`Model/LevelCongruence.lean` and `Model/Checking.lean` are Ix-authored mathematical +additions, listed separately from the imported files in the theory provenance manifest. diff --git a/docs/theory.md b/docs/theory.md index 880ed6d3f..a470dd06a 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -20,9 +20,11 @@ open frontiers retain their stated model hypotheses. The [certified host adapters](certified-checking.md) connect authenticated serialized Ixon to model admission. Separately, a production `checkEnvAnon` [fragment](kernel-verification.md#production-environment-fragment) for -monomorphic aliases, closed universe terms, and monomorphic specializations -of polymorphic constants extends every model of its source axioms under -explicit execution witnesses. Full checker consistency +monomorphic aliases, closed universe terms, monomorphic specializations of +polymorphic constants, and a fragment of closed dependent function bodies +extends every model of its source axioms under explicit execution witnesses. +Binder inference uses the declared type's separate formation check to turn +`Model.CheckingClaim` into semantic typing. Full checker consistency and compiler/backend refinement remain open. `Ix.Theory.Named` retains the local name-indexed specification and proof From 7ee64b4618c9a033577aaf9ab297ba6d9fc364ac Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 12:32:57 -0400 Subject: [PATCH 09/30] Refine applications and constant references in function bodies --- Ix/Kernel/Verify/Consistency.lean | 11 +- Ix/Kernel/Verify/Consistency/Application.lean | 239 ++++++++++++++++++ Ix/Kernel/Verify/Consistency/Audit.lean | 7 +- .../Verify/Consistency/BinderInference.lean | 144 ++++++++++- Ix/Kernel/Verify/Consistency/Production.lean | 14 +- Ix/Kernel/Verify/Consistency/ScopedExpr.lean | 12 + Ix/Theory/Model/Checking.lean | 12 + Tests/Ix/Kernel/Consistency.lean | 106 +++++++- docs/kernel-verification.md | 36 ++- docs/theory.md | 5 +- 10 files changed, 552 insertions(+), 34 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/Application.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 3ab048595..414d1a0df 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -13,6 +13,7 @@ import Ix.Kernel.Verify.Consistency.Atomic import Ix.Kernel.Verify.Consistency.ScopedExpr import Ix.Kernel.Verify.Consistency.Context import Ix.Kernel.Verify.Consistency.BinderOpening +import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.Production import Ix.Kernel.Verify.Consistency.Environment @@ -26,13 +27,17 @@ transport keeps its representation, arithmetic, and dependency assumptions explicit. A production `checkEnvAnon` fragment preserves models of its axiom set for monomorphic aliases, closed sorts, monomorphic specializations of polymorphic constants, and closed function bodies built from sorts, locals, -dependent functions, and full-mode lambdas under the stated execution resources. +monomorphic references, applications, dependent functions, and full-mode lambdas +under the stated execution resources. Constant inference supports arbitrary readable entry types, using the actual universe-instantiation walker and explicit lookup and finite-support resources. The returned type's scope and references justify declaration admission. -The binder case also requires explicit syntactic scope and empty constant -reference lists. Its separate declared-type inference turns semantic checking +The binder case also requires explicit syntactic scope and references to the +preceding interface. Its separate declared-type inference turns semantic checking into typing. Local cache hits agree with the actual declaration type; other inference nodes retain cache-miss boundaries. +Applications use syntactic Pi exposure, full argument checking, hash conversion, +and the ordinary eager-marker path. Constant- and local-headed spines derive +type validity from the admitted model or local context; their arguments may be lambdas. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Application.lean b/Ix/Kernel/Verify/Consistency/Application.lean new file mode 100644 index 000000000..acdee2e99 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/Application.lean @@ -0,0 +1,239 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.BinderOpening +import Ix.Kernel.Knot + +/-! +# Production application and dependent substitution + +The application result is the actual memoized substitution of its argument +into the inferred Pi codomain. Registered locals remain free in the kernel +tree while their model indices move below each syntactic binder. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u +variable {β : Type u} + +private theorem bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ intermediate, action = some intermediate ∧ next intermediate = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +private theorem depth_succ {depth : UInt64} (bound : depth.toNat + 1 < UInt64.size) : + (depth + 1).toNat = depth.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt bound] + +/-- Lifting a term with no loose legacy variables shifts the reading of its +registered locals beneath the new syntactic binders. -/ +theorem readScopedExpr?_liftSpec + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {term : KExpr .anon} {source : VExpr β} {depth shift : UInt64} + (bound : depth.toNat + term.size < UInt64.size) + (reading : readScopedExpr? resolve locals term depth.toNat = some source) : + readScopedExpr? resolve locals (KExpr.liftSpec term shift depth) + (depth.toNat + shift.toNat) = some (source.liftN shift.toNat depth.toNat) := by + induction term generalizing source depth with + | var index name info => + simp only [readScopedExpr?] at reading + split at reading + next inScope => + cases reading + have below : ¬ index ≥ depth := by + simp only [UInt64.le_iff_toNat_le]; omega + simp [KExpr.liftSpec, below, readScopedExpr?, show index.toNat < + depth.toNat + shift.toNat by omega, VExpr.liftN, liftVar, inScope] + · contradiction + | fvar id name info => + rw [readScopedExpr?] at reading + obtain ⟨index, found, reading⟩ := Option.map_eq_some_iff.mp reading + cases reading + simp only [KExpr.liftSpec, readScopedExpr?, found, Option.map_some, VExpr.liftN, liftVar, + Nat.not_lt.mpr (Nat.le_add_right depth.toNat index), if_false] + congr 2 + omega + | sort _ _ | nat _ _ _ => cases reading; rfl + | const id levels info => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + cases reading + simp [KExpr.liftSpec, readScopedExpr?, resolved, VExpr.liftN] + | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | app fn arg info hf ha => + rw [readScopedExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.liftSpec, hf (by omega) fReads, ha (by omega) aReads, VExpr.liftN] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readScopedExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := bind_success reading + obtain ⟨B, bodyReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bodyReads) + simp only [next] at bodyOut + simp [KExpr.liftSpec, hd (by omega) domainReads, VExpr.liftN, + show depth.toNat + shift.toNat + 1 = depth.toNat + 1 + shift.toNat by omega, + bodyOut] + | prj id index value info ih => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.liftSpec, resolved, ih (by omega) valueReads, VExpr.liftN] + +/-- Removing one syntactic binder agrees with model substitution, including +arguments that contain registered locals and their own nested binders. -/ +theorem readScopedExpr?_substSpec + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {body arg : KExpr .anon} {source argument : VExpr β} {depth : UInt64} + (bound : depth.toNat + body.size + 1 < UInt64.size) + (argBound : arg.size < UInt64.size) + (bodyReads : readScopedExpr? resolve locals body (depth.toNat + 1) = some source) + (argReads : readScopedExpr? resolve locals arg = some argument) : + readScopedExpr? resolve locals (KExpr.substSpec body arg depth) depth.toNat = + some (source.inst argument depth.toNat) := by + induction body generalizing source depth with + | var index name info => + simp only [readScopedExpr?] at bodyReads + split at bodyReads + next inScope => + cases bodyReads + by_cases equal : index = depth + · subst index + simp only [KExpr.substSpec, beq_self_eq_true, if_true, VExpr.inst, VExpr.instVar, + Nat.lt_irrefl, if_false] + simpa only [UInt64.toNat_zero, Nat.zero_add] using + (readScopedExpr?_liftSpec (depth := 0) (shift := depth) + (by simpa using argBound) argReads) + · have smaller : index.toNat < depth.toNat := by + have : index.toNat ≠ depth.toNat := fun h => equal (UInt64.toNat_inj.mp h) + omega + have below : ¬ index > depth := by + simp only [UInt64.lt_iff_toNat_lt]; omega + simp [KExpr.substSpec, equal, below, readScopedExpr?, smaller, + VExpr.inst, VExpr.instVar] + · contradiction + | fvar id name info => + rw [readScopedExpr?] at bodyReads + obtain ⟨index, found, bodyReads⟩ := Option.map_eq_some_iff.mp bodyReads + cases bodyReads + have greater : depth.toNat < depth.toNat + 1 + index := by omega + simp [KExpr.substSpec, readScopedExpr?, found, VExpr.inst, VExpr.instVar, + Nat.not_lt.mpr (by omega : depth.toNat ≤ depth.toNat + 1 + index), + Nat.ne_of_gt greater, show depth.toNat + 1 + index - 1 = depth.toNat + index by omega] + | sort _ _ | nat _ _ _ => cases bodyReads; rfl + | const id levels info => + rw [readScopedExpr?] at bodyReads + obtain ⟨ref, resolved, bodyReads⟩ := bind_success bodyReads + cases bodyReads + simp [KExpr.substSpec, readScopedExpr?, resolved, VExpr.inst] + | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | app fn value info hf ha => + rw [readScopedExpr?] at bodyReads + obtain ⟨f, fReads, bodyReads⟩ := bind_success bodyReads + obtain ⟨a, aReads, bodyReads⟩ := bind_success bodyReads + cases bodyReads + simp only [KExpr.size] at bound + simp [KExpr.substSpec, hf (by omega) fReads, ha (by omega) aReads, VExpr.inst] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readScopedExpr?] at bodyReads + obtain ⟨A, domainReads, bodyReads⟩ := bind_success bodyReads + obtain ⟨B, innerReads, reading⟩ := bind_success bodyReads + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using innerReads) + simp only [next] at bodyOut + simp [KExpr.substSpec, hd (by omega) domainReads, bodyOut, VExpr.inst] + | prj id index value info ih => + rw [readScopedExpr?] at bodyReads + obtain ⟨ref, resolved, bodyReads⟩ := bind_success bodyReads + obtain ⟨value, valueReads, bodyReads⟩ := bind_success bodyReads + cases bodyReads + simp only [KExpr.size] at bound + simp [KExpr.substSpec, resolved, ih (by omega) valueReads, VExpr.inst] + +/-- The actual memoized, interned walker inherits the structural substitution +reading under finite collision freedom and bounds excluding index overflow. -/ +theorem subst_readScopedExpr? + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {body arg : KExpr .anon} {source argument : VExpr β} {table : InternTable .anon} + (bodyConstructed : body.Constructed) (argConstructed : arg.Constructed) + (bodyBound : body.size + 1 < UInt64.size) (argBound : arg.size < UInt64.size) + (coherent : table.WF) + (faithful : KExpr.CollisionFree fun term => table.ExprSupport term ∨ + KExpr.SubstReach arg body 0 term) + (bodyReads : readScopedExpr? resolve locals body 1 = some source) + (argReads : readScopedExpr? resolve locals arg = some argument) : + readScopedExpr? resolve locals (subst body arg 0 table).1 = some (source.inst argument) ∧ + (subst body arg 0 table).2.WF := by + obtain ⟨result, coherent, _⟩ := subst_spec faithful bodyConstructed argConstructed + (by simpa using (show body.size < UInt64.size by omega)) argBound + (fun _ h => Or.inr h) coherent (fun _ h => Or.inl h) + refine ⟨?_, coherent⟩ + rw [result] + exact readScopedExpr?_substSpec (depth := 0) (by simpa using bodyBound) + argBound bodyReads argReads + +/-- Full-mode application takes a syntactic Pi, infers its argument, and +compares the inferred argument type with the domain. Eager markers are outside +this trace; the comparison and substitution states are the actual ones. -/ +structure ApplicationInferenceTrace (fuel : Nat) (before : TcState .anon) + (fn arg : KExpr .anon) where + name : Mode.anon.F Name + bi : Mode.anon.F Lean.BinderInfo + domain : KExpr .anon + codomain : KExpr .anon + info : ExprInfo .anon + functionState : TcState .anon + argumentType : KExpr .anon + argumentState : TcState .anon + comparedState : TcState .anon + functionRun : RecM.infer fn (methodsN fuel) before = + .ok (.all name bi domain codomain info) functionState + argumentRun : RecM.infer arg (methodsN fuel) functionState = .ok argumentType argumentState + ordinary : TcM.isEagerReduce arg argumentState = .ok false argumentState + compareRun : RecM.isDefEq argumentType domain (methodsN fuel) argumentState = + .ok true comparedState + contextPreserved : functionState.lctx = before.lctx + +/-- Inverting the successful production branch reaches its exact interned +codomain substitution after the real argument check. -/ +theorem ApplicationInferenceTrace.output {fuel : Nat} {before after : TcState .anon} + {fn arg result : KExpr .anon} {info : ExprInfo .anon} + (trace : ApplicationInferenceTrace fuel before fn arg) + (accepted : RecM.inferUncached RecM.inferCall false (.app fn arg info) + (methodsN (fuel + 1)) before = .ok result after) : + result = (subst trace.codomain arg 0 trace.comparedState.env.intern).1 := by + change (RecM.inferUncached RecM.inferCall false (.app fn arg info)).run + (methodsN (fuel + 1)) before = .ok result after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind] at accepted + change EStateM.bind (RecM.infer fn (methodsN fuel)) _ before = _ at accepted + rw [EStateM.bind, trace.functionRun] at accepted + change EStateM.bind (RecM.infer arg (methodsN fuel)) _ trace.functionState = _ at accepted + rw [EStateM.bind, trace.argumentRun] at accepted + change EStateM.bind (TcM.isEagerReduce arg) _ trace.argumentState = _ at accepted + rw [EStateM.bind, trace.ordinary] at accepted + change EStateM.bind (RecM.isDefEq trace.argumentType trace.domain (methodsN fuel)) + _ trace.argumentState = _ at accepted + rw [EStateM.bind, trace.compareRun] at accepted + cases accepted + rfl + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index fc7c05645..dc93d5cc0 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -39,6 +39,8 @@ private def atomicRoots : Array Lean.Name := #[ ``inferUncached_fvar_sound, ``infer_fvar_sound, ``FVarInferenceSupport.output, ``FVarInferenceSupport.sound, ``ForallInferenceTrace.output, ``LambdaInferenceTrace.output, ``BinderInference.sound, + ``inferUncached_monomorphic_const_scoped, ``ApplicationInferenceTrace.output, + ``BinderInference.soundWithSynthesis, ``BinderInference.synthesis, ``DefinitionBodySupport.sound ] @@ -75,7 +77,8 @@ private def binderWalkerRoots : Array Lean.Name := #[ ``inferKey_lctx, ``UncachedInference.localContext, ``readScopedExpr?_instantiateRevSpec, ``readScopedExpr?_abstractFVarsSpec, ``openBinder_eq, ``openBinder_sound, - ``abstractFVars_singleton_spec, ``abstractFVars_readScopedExpr? + ``abstractFVars_singleton_spec, ``abstractFVars_readScopedExpr?, + ``readScopedExpr?_liftSpec, ``readScopedExpr?_substSpec, ``subst_readScopedExpr? ] /-- Production roots must not acquire a checker-soundness assumption @@ -102,6 +105,7 @@ def roots : Array RootAllowance := #[ nativeAxioms := #[expressionNative] }, { root := ``readExpr?_eraseMeta, standardAxioms := #[``propext, ``Quot.sound] }, { root := ``readScopedExpr?_lam_parts }, + { root := ``readScopedExpr?_app_parts }, { root := ``readScopedExpr?_all_parts }, { root := ``beq_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, { root := ``internExpr_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, @@ -136,6 +140,7 @@ def roots : Array RootAllowance := #[ { root := ``Theory.Model.AExpr.LevelEquivalent.wellDenoted, standardAxioms := standard }, { root := ``Theory.Model.AExpr.LevelEquivalent.typing, standardAxioms := standard }, { root := ``Theory.Model.TypingClaim.checking, standardAxioms := standard }, + { root := ``Theory.Model.TypingClaim.appChecking, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.typing, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.typingSort, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.lam, standardAxioms := standard } diff --git a/Ix/Kernel/Verify/Consistency/BinderInference.lean b/Ix/Kernel/Verify/Consistency/BinderInference.lean index d7da09fca..64688b4fd 100644 --- a/Ix/Kernel/Verify/Consistency/BinderInference.lean +++ b/Ix/Kernel/Verify/Consistency/BinderInference.lean @@ -3,8 +3,7 @@ Copyright (c) 2026 Argument Computer Corporation. SPDX-License-Identifier: MIT OR Apache-2.0 -/ -import Ix.Kernel.Verify.Consistency.BinderOpening -import Ix.Kernel.Knot +import Ix.Kernel.Verify.Consistency.Application import Ix.Theory.Model.Checking /-! @@ -23,6 +22,42 @@ open Theory Theory.Model universe u v +/-- Application spines whose type validity comes from the current local +declaration or an admitted constant. Lambda arguments may still be checked +against the domain supplied by such a function. -/ +inductive SynthesisHead {β : Type u} : AExpr β → Prop + | bvar (index : Nat) : SynthesisHead (.bvar index) + | const (ref : ConstRef β) (levels : List VLevel) : SynthesisHead (.const ref levels) + | app {fn arg : AExpr β} (head : SynthesisHead fn) : SynthesisHead (.app fn arg) + +/-- Empty universe instantiation returns the exact declaration type reached +by lazy lookup. The scoped reading can include dependent Pi types. -/ +theorem inferUncached_monomorphic_const_scoped {β : Type u} + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {id : KId .anon} {info : ExprInfo .anon} {type : AExpr β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {result : KExpr .anon} + (lookup : ∀ concrete loaded, TcM.getConst id before = .ok concrete loaded → + readScopedExpr? resolve locals concrete.ty = some type.erase) + (accepted : RecM.inferUncached inferRec inferOnly (.const id #[] info) + methods before = .ok result after) : + readScopedExpr? resolve locals result = some type.erase := by + change (RecM.inferUncached inferRec inferOnly (.const id #[] info)).run + methods before = .ok result after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.getConst id) _ before = _ at accepted + cases got : TcM.getConst id before with + | error err failed => rw [EStateM.bind, got] at accepted; contradiction + | ok concrete loaded => + rw [EStateM.bind, got] at accepted + simp only at accepted + split at accepted + · contradiction + · change EStateM.Result.ok concrete.ty loaded = .ok result after at accepted + cases accepted + exact lookup concrete _ got + private theorem withLctxScope_eq (action : RecM .anon α) (methods : Methods .anon) (before : TcState .anon) : (RecM.withLctxScope action).run methods before = @@ -183,6 +218,36 @@ inductive BinderInference {β : Type u} (registered : localIndex? locals id = some index) (atIndex : context[index]? = some A) : BinderInference resolve entries locals context fuel before (.fvar id name info) (.bvar index) A + | const {locals context fuel before id info ref entry} + (miss : UncachedInference before (.const id #[] info)) + (resolved : resolve id.addr = some ref) + (found : entries ref = some entry) + (monomorphic : entry.universes = 0) + (stable : entry.type.instL [] = entry.type) + (lookup : ∀ concrete loaded, TcM.getConst id miss.keyed = .ok concrete loaded → + readScopedExpr? resolve locals concrete.ty = some entry.type.erase) : + BinderInference resolve entries locals context fuel before (.const id #[] info) + (.const ref []) entry.type + | app {locals context fuel before fn arg info f a A A' B condition} + (full : before.inferOnly = false) + (miss : UncachedInference before (.app fn arg info)) + (trace : ApplicationInferenceTrace fuel miss.keyed fn arg) + (functionTree : BinderInference resolve entries locals context fuel miss.keyed fn + f (.forallE condition A B)) + (head : SynthesisHead f) + (argumentTree : BinderInference resolve entries locals context fuel trace.functionState arg a A') + (conditions : A'.annotations = A.annotations) + (hashPath : (trace.argumentType == trace.domain) = true) + (comparisonFaithful : trace.argumentType.AddrFaithful trace.domain) + (bodyConstructed : trace.codomain.Constructed) + (argConstructed : arg.Constructed) + (bodyBound : trace.codomain.size + 1 < UInt64.size) + (argBound : arg.size < UInt64.size) + (coherent : trace.comparedState.env.intern.WF) + (faithful : KExpr.CollisionFree fun term => trace.comparedState.env.intern.ExprSupport term ∨ + KExpr.SubstReach arg trace.codomain 0 term) : + BinderInference resolve entries locals context (fuel + 1) before (.app fn arg info) + (.app f a) (B.inst a) | forallE {locals context fuel before name bi domain body info A B} (miss : UncachedInference before (.all name bi domain body info)) (trace : ForallInferenceTrace fuel miss.keyed name bi domain body) @@ -225,7 +290,7 @@ inductive BinderInference {β : Type u} /-- Successful production inference reads the expected model type and checks the actual source term against it. No recursive semantic premise is supplied by the caller: induction follows the finite operational support tree. -/ -theorem BinderInference.sound {β : Type u} +theorem BinderInference.soundWithSynthesis {β : Type u} {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} {locals : List FVarId} {context : Model.Context β} {fuel : Nat} {before after : TcState .anon} {term result : KExpr .anon} {e A : AExpr β} @@ -234,7 +299,8 @@ theorem BinderInference.sound {β : Type u} (reading : readScopedExpr? resolve locals term = some e.erase) (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : readScopedExpr? resolve locals result = some A.erase ∧ - CheckingClaim.{u,v} entries context e A := by + CheckingClaim.{u,v} entries context e A ∧ + (SynthesisHead e → TypingClaim.{u,v} entries context e A) := by induction support generalizing result after with | sort miss coherent faithful => obtain ⟨state, run⟩ := infer_uncached_success miss accepted @@ -242,23 +308,50 @@ theorem BinderInference.sound {β : Type u} (miss.keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc _))).1 _ = .ok result state at run cases run - refine ⟨?_, (TypingClaim.sort _).checking⟩ + refine ⟨?_, (TypingClaim.sort _).checking, fun head => by cases head⟩ rw [internExpr_readScopedExpr? coherent faithful] simp [AExpr.erase] | fvar cache registered atIndex => obtain ⟨typeReads, typed⟩ := cache.sound agreement registered atIndex accepted - exact ⟨typeReads, typed.checking⟩ + exact ⟨typeReads, typed.checking, fun _ => typed⟩ + | @const locals context fuel before id info ref entry miss resolved found monomorphic stable lookup => + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + have typed : TypingClaim.{u,v} entries context (.const ref []) entry.type := by + simpa only [stable] using + (TypingClaim.const (Γ := context) (ls := []) found (by simpa using monomorphic.symm)) + exact ⟨inferUncached_monomorphic_const_scoped lookup run, typed.checking, fun _ => typed⟩ + | @app locals context fuel before fn arg info f a A A' B condition + full miss trace functionTree head argumentTree conditions hashPath comparisonFaithful + bodyConstructed argConstructed bodyBound argBound coherent faithful ihFunction ihArgument => + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + rw [full] at run + obtain ⟨fnReads, argReads⟩ := readScopedExpr?_app_parts reading + have keyedAgreement := miss.localContext.symm ▸ agreement + obtain ⟨functionTypeReads, _, functionTyped⟩ := ihFunction keyedAgreement fnReads trace.functionRun + obtain ⟨domainReads, codomainReads⟩ := readScopedExpr?_all_parts functionTypeReads + have argumentAgreement := trace.contextPreserved.symm ▸ keyedAgreement + obtain ⟨argumentTypeReads, argumentChecked, _⟩ := ihArgument argumentAgreement argReads trace.argumentRun + have sameReading := beq_readScopedExpr? (resolve := resolve) (locals := locals) + (depth := 0) comparisonFaithful hashPath + have sameType := AExpr.eq_of_erase_annotations + (Option.some.inj (argumentTypeReads.symm.trans (sameReading.trans domainReads))) conditions + have checked := sameType ▸ argumentChecked + have typed := (functionTyped head).appChecking checked + refine ⟨?_, typed.checking, fun _ => typed⟩ + rw [trace.output run, AExpr.erase_inst] + exact (subst_readScopedExpr? bodyConstructed argConstructed bodyBound argBound + coherent faithful codomainReads argReads).1 | forallE miss trace opening absent domainTree bodyTree levelFaithful domainBound bodyBound coherent faithful ihDomain ihBody => obtain ⟨state, run⟩ := infer_uncached_success miss accepted obtain ⟨domainReads, bodyReads⟩ := readScopedExpr?_all_parts reading have keyedAgreement := miss.localContext.symm ▸ agreement - obtain ⟨_, domainChecked⟩ := ihDomain keyedAgreement domainReads trace.domainRun + obtain ⟨_, domainChecked, _⟩ := ihDomain keyedAgreement domainReads trace.domainRun have domainAgreement := trace.contextPreserved.symm ▸ keyedAgreement obtain ⟨_, openedReads, openedAgreement, _⟩ := openBinder_sound opening domainAgreement absent domainReads bodyReads trace.openRun - obtain ⟨_, bodyChecked⟩ := ihBody openedAgreement openedReads trace.bodyRun - refine ⟨?_, ?_⟩ + obtain ⟨_, bodyChecked, _⟩ := ihBody openedAgreement openedReads trace.bodyRun + refine ⟨?_, ?_, fun head => by cases head⟩ · rw [trace.output run, internExpr_readScopedExpr? coherent faithful] rfl · have formed := TypingClaim.forallE domainChecked.typingSort bodyChecked.typingSort rfl @@ -275,12 +368,41 @@ theorem BinderInference.sound {β : Type u} have domainAgreement := trace.contextPreserved.symm ▸ keyedAgreement obtain ⟨_, openedReads, openedAgreement, _⟩ := openBinder_sound opening domainAgreement absent domainReads bodyReads trace.openRun - obtain ⟨bodyTypeReads, bodyChecked⟩ := ihBody openedAgreement openedReads trace.bodyRun + obtain ⟨bodyTypeReads, bodyChecked, _⟩ := ihBody openedAgreement openedReads trace.bodyRun obtain ⟨closedReads, closedCoherent⟩ := abstractFVars_readScopedExpr? constructed bound coherent closingFaithful bodyTypeReads - refine ⟨?_, bodyChecked.lam⟩ + refine ⟨?_, bodyChecked.lam, fun head => by cases head⟩ rw [trace.output run, internExpr_readScopedExpr? (table := trace.abstracted.2) closedCoherent faithful] simp [LambdaInferenceTrace.abstracted, domainReads, closedReads, AExpr.erase] +/-- The checking conclusion applies to all supported finite trees. -/ +theorem BinderInference.sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {fuel : Nat} + {before after : TcState .anon} {term result : KExpr .anon} {e A : AExpr β} + (support : BinderInference resolve entries locals context fuel before term e A) + (agreement : LocalContextReading resolve locals before.lctx context) + (reading : readScopedExpr? resolve locals term = some e.erase) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : + readScopedExpr? resolve locals result = some A.erase ∧ + CheckingClaim.{u,v} entries context e A := by + obtain ⟨reads, checked, _⟩ := support.soundWithSynthesis agreement reading accepted + exact ⟨reads, checked⟩ + +/-- Constant- and local-headed application spines synthesize full typing, +including hereditary validity of the exact returned dependent type. -/ +theorem BinderInference.synthesis {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {fuel : Nat} + {before after : TcState .anon} {term result : KExpr .anon} {e A : AExpr β} + (support : BinderInference resolve entries locals context fuel before term e A) + (head : SynthesisHead e) + (agreement : LocalContextReading resolve locals before.lctx context) + (reading : readScopedExpr? resolve locals term = some e.erase) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : + readScopedExpr? resolve locals result = some A.erase ∧ TypingClaim.{u,v} entries context e A := by + obtain ⟨reads, _, typed⟩ := support.soundWithSynthesis agreement reading accepted + exact ⟨reads, typed head⟩ + end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Production.lean b/Ix/Kernel/Verify/Consistency/Production.lean index f064fabaa..894a75e71 100644 --- a/Ix/Kernel/Verify/Consistency/Production.lean +++ b/Ix/Kernel/Verify/Consistency/Production.lean @@ -102,7 +102,7 @@ def DefinitionInput.constant (input : DefinitionInput) : KConst .anon := or a finite binder inference tree with a separately checked declared type. Specializations supply raw syntax and occurrence annotations; successful inference derives their typing, scope, and references. Binder definitions -also supply syntactic scope and empty constant-reference inventories. Every +also supply syntactic scope and references to the preceding interface. Every case derives body typing without a semantic typing premise. -/ inductive DefinitionBodySupport {β : Type u} (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) @@ -131,7 +131,7 @@ inductive DefinitionBodySupport {β : Type u} (valueReading : readScopedExpr? resolve [] term = some body.erase) (typeReading : readScopedExpr? resolve [] declared = some type.erase) (scope : body.Scope 0 0 ∧ type.Scope 0 0) - (noConstants : body.references = [] ∧ type.references = []) : + (references : body.ReferencesIn entries ∧ type.ReferencesIn entries) : DefinitionBodySupport resolve entries methods before declared term body type theorem DefinitionBodySupport.sound {β : Type u} @@ -174,18 +174,14 @@ theorem DefinitionBodySupport.sound {β : Type u} · intro ref member rw [← equal, references] at member exact wellFormed.typeReferences _ _ support.found ref member - | binder tied valueInference typeInference typeRun valueReading typeReading scope noConstants => + | binder tied valueInference typeInference typeRun valueReading typeReading scope references => subst methods obtain ⟨_, typeChecked⟩ := typeInference.sound (LocalContextReading.empty _ _) typeReading typeRun obtain ⟨_, valueChecked⟩ := valueInference.sound (LocalContextReading.empty _ _) valueReading accepted - refine ⟨readScopedExpr?_closed valueReading, readScopedExpr?_closed typeReading, - scope.1, scope.2, ?_, ?_, valueChecked.typing typeChecked.typingSort⟩ - · intro ref member - simp only [noConstants.1, List.not_mem_nil] at member - · intro ref member - simp only [noConstants.2, List.not_mem_nil] at member + exact ⟨readScopedExpr?_closed valueReading, readScopedExpr?_closed typeReading, + scope.1, scope.2, references.1, references.2, valueChecked.typing typeChecked.typingSort⟩ /-- The execution prefix through value conversion. A successful member check also passes the subsequent safety checks. -/ diff --git a/Ix/Kernel/Verify/Consistency/ScopedExpr.lean b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean index 94caa9729..3b6eb6957 100644 --- a/Ix/Kernel/Verify/Consistency/ScopedExpr.lean +++ b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean @@ -147,6 +147,18 @@ theorem readScopedExpr?_lam_parts {resolve : Address → Option (ConstRef β)} cases reading exact ⟨domainReads, bodyReads⟩ +theorem readScopedExpr?_app_parts {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {fn arg : KExpr m} {info : ExprInfo m} + {f a : VExpr β} {depth : Nat} + (reading : readScopedExpr? resolve locals (.app fn arg info) depth = some (.app f a)) : + readScopedExpr? resolve locals fn depth = some f ∧ + readScopedExpr? resolve locals arg depth = some a := by + rw [readScopedExpr?] at reading + obtain ⟨f', fnReads, reading⟩ := option_bind_success reading + obtain ⟨a', argReads, reading⟩ := option_bind_success reading + cases reading + exact ⟨fnReads, argReads⟩ + theorem readScopedExpr?_all_parts {resolve : Address → Option (ConstRef β)} {locals : List FVarId} {name : m.F Name} {bi : m.F Lean.BinderInfo} {domain body : KExpr m} {info : ExprInfo m} {A B : VExpr β} {depth : Nat} diff --git a/Ix/Theory/Model/Checking.lean b/Ix/Theory/Model/Checking.lean index 3e9836ae3..4e69f9f70 100644 --- a/Ix/Theory/Model/Checking.lean +++ b/Ix/Theory/Model/Checking.lean @@ -35,6 +35,18 @@ theorem TypingClaim.checking {e A : AExpr β} (typed : TypingClaim.{u,v} entries have checked := typed V constants realizes levels env valid exact ⟨checked.1, checked.2.2⟩ +/-- A synthesized function supplies the domain's hereditary validity, so its +argument may be checked without a separate universe-formation derivation. -/ +theorem TypingClaim.appChecking {f a A B : AExpr β} {condition : PropWhen} + (function : TypingClaim.{u,v} entries Γ f (.forallE condition A B)) + (argument : CheckingClaim.{u,v} entries Γ a A) : + TypingClaim.{u,v} entries Γ (.app f a) (B.inst a) := by + apply function.app + intro V _ constants realizes levels env valid + have domainValid := (function V constants realizes levels env valid).2.1.1 + obtain ⟨argumentValid, member⟩ := argument V constants realizes levels env valid domainValid + exact ⟨argumentValid, domainValid, member⟩ + namespace CheckingClaim theorem typing {e A : AExpr β} {level : VLevel} diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 780b03081..0074c0ebe 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -6,7 +6,7 @@ public import Tests.Ix.Kernel.IxonFixtures /-! Production regressions for the consistency fragment, polymorphic constant -inference, and dependent binders. These execute the lazy loader, inference, and serial driver +inference, dependent binders, and applications. These execute the lazy loader, inference, and serial driver on content-addressed Ixon declarations. The theorems and their resource premises are checked separately by `IxKernelConsistency`. -/ @@ -303,6 +303,108 @@ private def binderCases : TestSeq := ++ test "binder environment: an escaping bound variable fails validation" (let (env, target) := failedBinder (.var 2); rowFailed env target) -public def suite : List TestSeq := [cases, polymorphicCases, specializationCases, binderCases] +private def monomorphicIdentity (level : Ixon.Univ) (env : Ixon.Env := {}) : Ixon.Env × Address := + storeConst env + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), + .leanLam (.sort 0) (.leanLam (.var 0) (.var 0))⟩, #[], #[], #[level]⟩ + +/-- Real definitions call an earlier identity at Prop and Type. A theorem +then calls the first wrapper, exercising a second semantic dependency. -/ +private def applicationEnvironment : Ixon.Env := Id.run do + let (env, propIdentity) := monomorphicIdentity .zero + let (env, typeIdentity) := monomorphicIdentity (.succ .zero) env + let type := Ixon.Expr.leanAll (.sort 0) (.leanAll (.var 0) (.var 1)) + let value := Ixon.Expr.leanLam (.sort 0) (.leanLam (.var 0) + (.app (.app (.ref 0 #[]) (.var 1)) (.var 0))) + let (env, wrapper) := storeConst env + ⟨.defn ⟨.defn, .safe, 0, type, value⟩, #[], #[propIdentity], #[.zero]⟩ + let (env, _) := storeConst env + ⟨.defn ⟨.thm, .safe, 0, type, value⟩, #[], #[wrapper], #[.zero]⟩ + let (env, _) := storeConst env + ⟨.defn ⟨.opaq, .safe, 0, type, value⟩, #[], #[typeIdentity], #[.succ .zero]⟩ + return env + +/-- `(P Q : Prop) → (P → Q) → P → Q`, with body `f p`. -/ +private def localApplication : Ixon.Env := + let functionType := Ixon.Expr.leanAll (.var 1) (.var 1) + (storeConst {} + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll (.sort 0) + (.leanAll functionType (.leanAll (.var 2) (.var 2)))), + .leanLam (.sort 0) (.leanLam (.sort 0) + (.leanLam functionType (.leanLam (.var 2) (.app (.var 1) (.var 0)))))⟩, + #[], #[], #[.zero]⟩).1 + +/-- `(A : Type) → (B : A → Type) → ((x : A) → B x) → (x : A) → B x`. +Substitution must retain both active locals in the resulting `B x`. -/ +private def dependentApplication : Ixon.Env := + let familyType := Ixon.Expr.leanAll (.var 0) (.sort 0) + let functionType := Ixon.Expr.leanAll (.var 1) (.app (.var 1) (.var 0)) + (storeConst {} + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll familyType + (.leanAll functionType (.leanAll (.var 2) (.app (.var 2) (.var 0))))), + .leanLam (.sort 0) (.leanLam familyType + (.leanLam functionType (.leanLam (.var 2) (.app (.var 1) (.var 0)))))⟩, + #[], #[], #[.succ .zero]⟩).1 + +/-- `(P : Prop) → ((P → P) → P) → P`, with body `f (fun p => p)`. +The function supplies the expected Pi's validity for the lambda argument. -/ +private def lambdaArgument : Ixon.Env := + let functionType := Ixon.Expr.leanAll (.leanAll (.var 0) (.var 1)) (.var 1) + (storeConst {} + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll functionType (.var 1)), + .leanLam (.sort 0) (.leanLam functionType + (.app (.var 0) (.leanLam (.var 1) (.var 0))))⟩, + #[], #[], #[.zero]⟩).1 + +private def failedApplication : Ixon.Env × Address := + let (env, identity) := monomorphicIdentity .zero + storeConst env + ⟨.defn ⟨.defn, .safe, 0, + .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), + .leanLam (.sort 0) (.leanLam (.var 0) + (.app (.app (.ref 0 #[]) (.var 1)) (.var 1)))⟩, + #[], #[identity], #[.zero]⟩ + +/-- Inspect the exact dependent result before leaving the scope. A repeated +application must preserve it when the production inference cache is warm. -/ +private def applicationLocalResult : Bool := + let (env, identity) := monomorphicIdentity .zero + let propType := KExpr.mkSort (m := .anon) .mkZero + let action : RecM .anon Bool := RecM.withLctxScope do + let (proposition, _) ← TcM.openBinder () () propType (.mkVar 0 ()) + let (witness, _) ← TcM.openBinder () () proposition (.mkVar 0 ()) + let term := KExpr.mkApp (.mkApp (.mkConst ⟨identity, ()⟩ #[]) proposition) witness + let first ← RecM.inferCall term + let second ← RecM.inferCall term + let state ← get + return first.addr == proposition.addr && second.addr == proposition.addr && state.lctx.size == 2 + match TcM.runRec action (TcState.newLazyAnon env) with + | .ok passed after => passed && after.lctx.size == 0 && after.env.nextFVarId == 2 + | .error _ _ => false + +private def applicationCases : TestSeq := + test "application environment: Prop/Type identity calls and transitive theorem calls check" + (allSucceeded applicationEnvironment 5 { clearEvery := 0 }) + ++ test "application environment: calls check with fresh per-item caches" + (allSucceeded applicationEnvironment 5 { clearEvery := 1 }) + ++ test "application environment: a local function checks its argument against a distinct domain" + (allSucceeded localApplication 1) + ++ test "application environment: a dependent local function returns the substituted family" + (allSucceeded dependentApplication 1) + ++ test "application environment: a local function accepts a checked lambda argument" + (allSucceeded lambdaArgument 1) + ++ test "application inference: exact local result survives cache reuse and scope cleanup" + applicationLocalResult + ++ test "application environment: passing the proposition instead of its witness fails" + (let (env, target) := failedApplication; rowFailed env target) + ++ test "application environment: applying a proof with no function type fails" + (let (env, target) := failedBinder (.app (.var 0) (.var 0)); rowFailed env target) + +public def suite : List TestSeq := + [cases, polymorphicCases, specializationCases, binderCases, applicationCases] end Tests.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 92485e5b5..66174de9c 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -59,11 +59,19 @@ increasing sequence of strongly inaccessible cardinals. primitive False when its environment has been admitted by the certified interface and the set-theory assumption has an instance. - `BinderInference.sound` follows finite production inference trees for sorts, - locals, dependent functions, and full-mode lambdas. `LocalContextReading.push` + locals, monomorphic constants, applications, dependent functions, and + full-mode lambdas. `LocalContextReading.push` and `openBinder_sound` connect actual declaration lookup and fresh-variable opening to the model's dependent context. Singleton abstraction closes the resulting function type, and the simplifying `imax` constructor preserves its universe interpretation. +- `BinderInference.synthesis` derives full typing for application spines + headed by a local or an admitted monomorphic constant. The function's type + supplies hereditary validity of its domain, so arguments may be checked + lambdas. Faithful hash conversion identifies the argument's inferred type + with that domain, with matching occurrence annotations. + `subst_readScopedExpr?` connects the actual memoized and interned codomain + substitution to model substitution, including active locals and nested binders. - `FVarInferenceSupport.sound` handles both local-variable cache partitions when a cached answer equals the current declaration's concrete type. These are structural cache checks, with no assumed semantic typing of cached data. @@ -103,6 +111,8 @@ def typeAlias : Type := Prop axiom ident.{u} : (α : Sort u) → α → α def propIdent : (α : Prop) → α → α := ident.{0} def idProp (P : Prop) (p : P) : P := p +def useId (P : Prop) (p : P) : P := idProp P p +def applyProp (P Q : Prop) (f : P → Q) (p : P) : Q := f p ``` `AtomicEnvironmentFragment` records the precise execution boundary: @@ -110,7 +120,7 @@ def idProp (P : Prop) (p : P) : P := p - Every source key occurs in the `buildAnonWork` result, and every work item represents an axiom or a definition. Lookup, routing, and reset witnesses identify the checked `KConst`. -- Sort, constant, forall, and lambda nodes in the inference witnesses miss both cache partitions. +- Sort, constant, application, forall, and lambda nodes in the inference witnesses miss both cache partitions. Local-variable hits must match the current production declaration type. Constant lookup agrees with an already admitted type and universe count. A specialization supplies @@ -122,7 +132,7 @@ def idProp (P : Prop) (p : P) : P := p retains finite interning coherence and address-faithfulness premises. - Binder definitions supply finite inference trees for both the value and its separately checked declared type, exact source readings, closed annotated - syntax, and empty constant-reference lists. Recursive calls use the actual + syntax, and references to the preceding interface. Recursive calls use the actual smaller method table. Binder-opening and abstraction resources cover fresh ids, context preservation during domain inference, intern-table coherence, finite collision freedom, and bounds preventing index overflow. Sort @@ -130,6 +140,14 @@ def idProp (P : Prop) (p : P) : P := p path. `CheckingClaim` derives body validity and membership once declared-type inference establishes hereditary validity. No codomain-typing premise is added to the production proof. +- Applications use full mode, syntactic Pi exposure, an ordinary argument + without an eager-reduction marker, and the hash-equality conversion path. + Their witnesses retain the actual recursive calls, context preservation + during function inference, and finite substitution resources. Function + spines start with locals or monomorphic constants; the latter use exact + lazy-lookup agreement and empty universe substitution. Applying a lambda + directly, polymorphic references within binder trees, and reduction to + expose a Pi require further refinement. - Conversion takes the initial hash-equality path, with faithfulness of the compared expressions. General reduction and conversion caches are outside this fragment. @@ -145,8 +163,8 @@ Callers must establish these operational and representation witnesses for the run. They supply no typing or checker-soundness premise. The proof extracts the validation, type-inference, theorem-guard, value-inference, and conversion steps from public success, then derives body typing to extend -the preceding model. Automatic witness construction, application inference, -lets, more general lambda paths, inductives, coordinated blocks, and other +the preceding model. Automatic witness construction, broader application and +lambda paths, lets, inductives, coordinated blocks, and other conversion paths remain outside the fragment. Polymorphic constant inference is composed into declaration admission and model extension for the monomorphic specializations described above. Definitions with their own universe parameters remain outside this @@ -201,7 +219,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 101 exact theorem boundaries. The production +The consistency target checks 110 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -222,6 +240,10 @@ Environment regressions additionally check Prop/Type specializations, transitive aliases, nested references, simplified declaration types, cache clearing, and admission failures for wrong arities, open parameters, and a mismatched declared specialization. +Function-body regressions cover calls to earlier Prop/Type identities, +transitive theorem calls, local functions with distinct domains and codomains, +dependent result families, lambda arguments, exact local results through cache +reuse and scope cleanup, and rejected argument/function types. ## Certified host adapters @@ -248,7 +270,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Certified checker contracts | [`Ix/Kernel/Certified.lean`](../Ix/Kernel/Certified.lean), [`CertifiedClaims.lean`](../Ix/Kernel/CertifiedClaims.lean) | | Direct production refinement and its audit | [`Ix/Kernel/Verify/Consistency.lean`](../Ix/Kernel/Verify/Consistency.lean) | | Polymorphic inference and universe substitution | [`Consistency/Constant.lean`](../Ix/Kernel/Verify/Consistency/Constant.lean), [`InstUniv.lean`](../Ix/Kernel/Verify/Consistency/InstUniv.lean), [`Model/LevelCongruence.lean`](../Ix/Theory/Model/LevelCongruence.lean) | -| Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | +| Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | | Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | diff --git a/docs/theory.md b/docs/theory.md index a470dd06a..3a9f63013 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -24,7 +24,10 @@ monomorphic aliases, closed universe terms, monomorphic specializations of polymorphic constants, and a fragment of closed dependent function bodies extends every model of its source axioms under explicit execution witnesses. Binder inference uses the declared type's separate formation check to turn -`Model.CheckingClaim` into semantic typing. Full checker consistency +`Model.CheckingClaim` into semantic typing. Application spines headed by locals +or admitted monomorphic constants derive their type's validity from the context +or dependency model, then check arguments and substitute the dependent result. +Full checker consistency and compiler/backend refinement remain open. `Ix.Theory.Named` retains the local name-indexed specification and proof From 4835e6e600f27ecfdadf59243cf1913cd34b83af Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 13:03:16 -0400 Subject: [PATCH 10/30] Refine polymorphic constant calls inside function bodies --- Ix/Kernel/Verify/Consistency.lean | 10 +- Ix/Kernel/Verify/Consistency/Audit.lean | 9 +- .../Verify/Consistency/BinderInference.lean | 12 ++ .../Verify/Consistency/ScopedConstant.lean | 194 ++++++++++++++++++ Ix/Kernel/Verify/Consistency/ScopedExpr.lean | 22 ++ .../Verify/Consistency/ScopedInstUniv.lean | 128 ++++++++++++ Tests/Ix/Kernel/Consistency.lean | 93 ++++++++- docs/kernel-verification.md | 30 ++- docs/theory.md | 2 +- 9 files changed, 486 insertions(+), 14 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/ScopedConstant.lean create mode 100644 Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 414d1a0df..a4e64c077 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -11,6 +11,8 @@ import Ix.Kernel.Verify.Consistency.InstUniv import Ix.Kernel.Verify.Consistency.Constant import Ix.Kernel.Verify.Consistency.Atomic import Ix.Kernel.Verify.Consistency.ScopedExpr +import Ix.Kernel.Verify.Consistency.ScopedInstUniv +import Ix.Kernel.Verify.Consistency.ScopedConstant import Ix.Kernel.Verify.Consistency.Context import Ix.Kernel.Verify.Consistency.BinderOpening import Ix.Kernel.Verify.Consistency.Application @@ -27,7 +29,7 @@ transport keeps its representation, arithmetic, and dependency assumptions explicit. A production `checkEnvAnon` fragment preserves models of its axiom set for monomorphic aliases, closed sorts, monomorphic specializations of polymorphic constants, and closed function bodies built from sorts, locals, -monomorphic references, applications, dependent functions, and full-mode lambdas +polymorphic references, applications, dependent functions, and full-mode lambdas under the stated execution resources. Constant inference supports arbitrary readable entry types, using the actual universe-instantiation walker and explicit lookup and finite-support resources. @@ -37,7 +39,9 @@ preceding interface. Its separate declared-type inference turns semantic checkin into typing. Local cache hits agree with the actual declaration type; other inference nodes retain cache-miss boundaries. Applications use syntactic Pi exposure, full argument checking, hash conversion, -and the ordinary eager-marker path. Constant- and local-headed spines derive -type validity from the admitted model or local context; their arguments may be lambdas. +and arguments without eager-reduction markers. Constant- and local-headed spines +derive type validity from the admitted model or local context; their arguments may be lambdas. +Polymorphic nodes use closed source readings, finite substitution resources, +and a pure prediction of the returned syntax with matching occurrence annotations. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index dc93d5cc0..916e7fd0b 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -48,8 +48,13 @@ private def instantiationRoots : Array Lean.Name := #[ ``instUnivSpec_readExpr?, ``instUnivSpec_readExpr?_withScope, ``instantiateUnivParams_readExpr?, ``instantiateUnivParams_readAnnotated, ``instantiateUnivParams_readAnnotated_scoped, + ``instUnivSpec_scoped_eq, ``instantiateUnivParamsSpec_scoped_eq, + ``instantiateUnivParams_scoped_eq, ``instantiateUnivParams_readScopedAnnotated, ``inferUncached_const_refinement, ``infer_const_refinement, - ``inferUncached_const_sound, ``infer_const_sound + ``inferUncached_const_sound, ``infer_const_sound, + ``inferUncached_const_instantiation, ``ScopedConstantInferenceSupport.closed, + ``inferUncached_const_scoped_refinement, ``inferUncached_const_scoped_sound, + ``inferUncached_const_predicted_type, ``infer_const_scoped_annotated ] private def productionRoots : Array Lean.Name := #[ @@ -63,7 +68,7 @@ private def productionRoots : Array Lean.Name := #[ private def scopedRoots : Array Lean.Name := #[ ``localIndex?_mem, ``localIndex?_getElem, ``localIndex?_fresh, - ``readScopedExpr?_closed, ``readScopedExpr?_eraseMeta, + ``readScopedExpr?_closed, ``readScopedExpr?_weaken_closed, ``readScopedExpr?_eraseMeta, ``beq_readScopedExpr?, ``internExpr_readScopedExpr?, ``readScopedExpr?_push, ``LocalContextReading.empty ] diff --git a/Ix/Kernel/Verify/Consistency/BinderInference.lean b/Ix/Kernel/Verify/Consistency/BinderInference.lean index 64688b4fd..4b47a4a33 100644 --- a/Ix/Kernel/Verify/Consistency/BinderInference.lean +++ b/Ix/Kernel/Verify/Consistency/BinderInference.lean @@ -4,6 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Application +import Ix.Kernel.Verify.Consistency.ScopedConstant import Ix.Theory.Model.Checking /-! @@ -228,6 +229,14 @@ inductive BinderInference {β : Type u} readScopedExpr? resolve locals concrete.ty = some entry.type.erase) : BinderInference resolve entries locals context fuel before (.const id #[] info) (.const ref []) entry.type + | polymorphic {locals context fuel before id arguments info ref entry type} + (miss : UncachedInference before (.const id arguments info)) + (support : ScopedConstantInferenceSupport resolve entries miss.keyed id arguments ref entry) + (prediction : ∀ concrete loaded, TcM.getConst id miss.keyed = .ok concrete loaded → + readInstantiatedType? resolve concrete.ty arguments = some type.erase) + (conditions : (entry.type.instL (arguments.toList.map readLevel)).annotations = type.annotations) : + BinderInference resolve entries locals context fuel before (.const id arguments info) + (.const ref (arguments.toList.map readLevel)) type | app {locals context fuel before fn arg info f a A A' B condition} (full : before.inferOnly = false) (miss : UncachedInference before (.app fn arg info)) @@ -320,6 +329,9 @@ theorem BinderInference.soundWithSynthesis {β : Type u} simpa only [stable] using (TypingClaim.const (Γ := context) (ls := []) found (by simpa using monomorphic.symm)) exact ⟨inferUncached_monomorphic_const_scoped lookup run, typed.checking, fun _ => typed⟩ + | polymorphic miss support prediction conditions => + obtain ⟨typeReads, typed⟩ := infer_const_scoped_annotated miss support prediction conditions accepted + exact ⟨typeReads, typed.checking, fun _ => typed⟩ | @app locals context fuel before fn arg info f a A A' B condition full miss trace functionTree head argumentTree conditions hashPath comparisonFaithful bodyConstructed argConstructed bodyBound argBound coherent faithful ihFunction ihArgument => diff --git a/Ix/Kernel/Verify/Consistency/ScopedConstant.lean b/Ix/Kernel/Verify/Consistency/ScopedConstant.lean new file mode 100644 index 000000000..e67317935 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/ScopedConstant.lean @@ -0,0 +1,194 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.Constant +import Ix.Kernel.Verify.Consistency.Context +import Ix.Kernel.Verify.Consistency.ScopedInstUniv + +/-! +# Polymorphic constant inference inside function bodies + +Lookup supplies a closed declaration type and finite resources for its actual +universe-instantiation walker. The resulting type remains closed while the +surrounding function's locals are active. A pure prediction of the substituted +syntax fixes an inference tree's annotated result type without assuming its +semantic validity or typing. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +/-- The runtime arity guard and the precise state passed to universe +instantiation follow from successful production constant inference. -/ +theorem inferUncached_const_instantiation + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {result : KExpr .anon} + (accepted : RecM.inferUncached inferRec inferOnly (.const id arguments info) + methods before = .ok result after) : + ∃ concrete loaded, TcM.getConst id before = .ok concrete loaded ∧ + concrete.lvls.toNat = arguments.size ∧ + TcM.instantiateUnivParams concrete.ty arguments loaded = .ok result after := by + change (RecM.inferUncached inferRec inferOnly (.const id arguments info)).run + methods before = .ok result after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted + change EStateM.bind (TcM.getConst id) _ before = _ at accepted + cases got : TcM.getConst id before with + | error err failed => rw [EStateM.bind, got] at accepted; contradiction + | ok concrete loaded => + rw [EStateM.bind, got] at accepted + by_cases arity : concrete.lvls.toNat = arguments.size + · simp only [arity, bne_self_eq_false, Bool.false_eq_true, if_false] at accepted + exact ⟨concrete, loaded, rfl, arity, accepted⟩ + · simp only [bne_iff_ne] at accepted + rw [if_pos arity] at accepted + contradiction + +/-- The selected admitted type is scoped at its declared universe arity. +Lookup uses the closed binder reader, retaining its exclusion of lets and +loose variables. All mutable resources concern the actual post-lookup state. -/ +structure ScopedConstantInferenceSupport {β : Type u} + (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) + (before : TcState .anon) (id : KId .anon) (arguments : Array (KUniv .anon)) + (ref : ConstRef β) (entry : ConstantEntry β) : Prop where + resolved : resolve id.addr = some ref + found : entries ref = some entry + scope : entry.type.Scope entry.universes 0 + lookup : ∀ concrete loaded, TcM.getConst id before = .ok concrete loaded → + concrete.lvls.toNat = entry.universes ∧ + readScopedExpr? resolve [] concrete.ty = some entry.type.erase ∧ + UniverseInstantiationSupport loaded concrete.ty arguments + +/-- The stronger closed binder reading also supplies the earlier constant +refinement's lookup interface. -/ +theorem ScopedConstantInferenceSupport.closed {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {before : TcState .anon} {id : KId .anon} {arguments : Array (KUniv .anon)} + {ref : ConstRef β} {entry : ConstantEntry β} + (support : ScopedConstantInferenceSupport resolve entries before id arguments ref entry) : + ConstantInferenceSupport resolve entries before id arguments ref entry := by + refine ⟨support.resolved, support.found, ?_⟩ + intro concrete loaded got + obtain ⟨count, reading, resources⟩ := support.lookup concrete loaded got + exact ⟨count, readScopedExpr?_closed reading, resources⟩ + +/-- Refinement derives the exact returned type's scoped reading, arity, +universe congruence, reference inventory, and scope for scoped arguments. -/ +theorem inferUncached_const_scoped_refinement {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {result : KExpr .anon} + (support : ScopedConstantInferenceSupport resolve entries before id arguments ref entry) + (accepted : RecM.inferUncached inferRec inferOnly (.const id arguments info) + methods before = .ok result after) : + ∃ output : AExpr β, readScopedExpr? resolve locals result = some output.erase ∧ + AExpr.LevelEquivalent (entry.type.instL (arguments.toList.map readLevel)) output ∧ + (arguments.toList.map readLevel).length = entry.universes ∧ + output.references = entry.type.references ∧ + (∀ n, (∀ level ∈ arguments, (readLevel level).WF n) → output.Scope n 0) := by + obtain ⟨concrete, loaded, got, arity, instantiated⟩ := inferUncached_const_instantiation accepted + obtain ⟨count, reading, resources⟩ := support.lookup concrete loaded got + have scope : entry.type.Scope arguments.size 0 := by + rw [← arity, count] + exact support.scope + obtain ⟨output, outputReads, same⟩ := instantiateUnivParams_readScopedAnnotated + (locals := locals) resources scope.erase.1 reading instantiated + refine ⟨output, outputReads, same, ?_, + same.references.symm.trans (AExpr.references_instL entry.type _), ?_⟩ + · simpa only [List.length_map, Array.length_toList] using arity.symm.trans count + · intro n argumentsWF + obtain ⟨scopedOutput, scopedReads, scopedSame, scopedWF, _⟩ := + instantiateUnivParams_readAnnotated_scoped resources scope argumentsWF + (readScopedExpr?_closed reading) instantiated + have closedOutputReads := + (instantiateUnivParams_scoped_eq locals resources reading instantiated).symm.trans outputReads + have sameOutput := AExpr.eq_of_erase_annotations + (Option.some.inj (scopedReads.symm.trans closedOutputReads)) + (scopedSame.annotations.symm.trans same.annotations) + exact sameOutput ▸ scopedWF + +/-- Polymorphic references synthesize full typing in every active model +context. The dependency model supplies the instantiated type's validity. -/ +theorem inferUncached_const_scoped_sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {ref : ConstRef β} {entry : ConstantEntry β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {result : KExpr .anon} + (support : ScopedConstantInferenceSupport resolve entries before id arguments ref entry) + (accepted : RecM.inferUncached inferRec inferOnly (.const id arguments info) + methods before = .ok result after) : + ScopedModelTyping.{u,v} resolve entries locals context (.const id arguments info) result := by + obtain ⟨output, outputReads, same, arity, _, _⟩ := + inferUncached_const_scoped_refinement support accepted + refine ⟨.const ref (arguments.toList.map readLevel), output, ?_, outputReads, + same.typing (TypingClaim.const support.found arity)⟩ + simp [readScopedExpr?, support.resolved, AExpr.erase] + +/-- Read a pure prediction of the instantiated declaration type. This is a +computable syntax check, independent of interning and semantic typing. -/ +def readInstantiatedType? {β : Type u} (resolve : Address → Option (ConstRef β)) + (type : KExpr .anon) (arguments : Array (KUniv .anon)) : Option (VExpr β) := + match KExpr.instantiateUnivParamsSpec type arguments with + | .ok result => readScopedExpr? resolve [] result + | .error _ => none + +/-- The actual interned result agrees with the pure prediction under the +walker's finite resource assumptions. Its reading is closed under locals. -/ +theorem inferUncached_const_predicted_type {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {result : KExpr .anon} + (support : ScopedConstantInferenceSupport resolve entries before id arguments ref entry) + (prediction : ∀ concrete loaded, TcM.getConst id before = .ok concrete loaded → + readInstantiatedType? resolve concrete.ty arguments = some type.erase) + (accepted : RecM.inferUncached inferRec inferOnly (.const id arguments info) + methods before = .ok result after) : + readScopedExpr? resolve locals result = some type.erase := by + obtain ⟨concrete, loaded, got, _, instantiated⟩ := inferUncached_const_instantiation accepted + obtain ⟨_, _, resources⟩ := support.lookup concrete loaded got + have post := TcM.instantiateUnivParams_wf resources.faithful + (fun _ h => Or.inr h) ⟨resources.coherent, fun _ h => Or.inl h⟩ + rw [instantiated] at post + have predicted := prediction concrete loaded got + rw [readInstantiatedType?, post.2.1] at predicted + exact readScopedExpr?_weaken_closed predicted locals + +/-- Fix an inference tree's result annotation from the pure substituted tree. +The semantic conclusion follows from the admitted entry and actual execution, +including any universe simplification; it is not a witness premise. -/ +theorem infer_const_scoped_annotated {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + {methods : Methods .anon} {before after : TcState .anon} {result : KExpr .anon} + (miss : UncachedInference before (.const id arguments info)) + (support : ScopedConstantInferenceSupport resolve entries miss.keyed id arguments ref entry) + (prediction : ∀ concrete loaded, TcM.getConst id miss.keyed = .ok concrete loaded → + readInstantiatedType? resolve concrete.ty arguments = some type.erase) + (conditions : (entry.type.instL (arguments.toList.map readLevel)).annotations = type.annotations) + (accepted : RecM.infer (.const id arguments info) methods before = .ok result after) : + readScopedExpr? resolve locals result = some type.erase ∧ + TypingClaim.{u,v} entries context (.const ref (arguments.toList.map readLevel)) type := by + obtain ⟨state, run⟩ := infer_uncached_success miss accepted + have predicted := inferUncached_const_predicted_type (locals := locals) support prediction run + obtain ⟨output, outputReads, same, arity, _, _⟩ := + inferUncached_const_scoped_refinement (locals := locals) support run + have sameOutput := AExpr.eq_of_erase_annotations + (Option.some.inj (outputReads.symm.trans predicted)) + (same.annotations.symm.trans conditions) + exact ⟨predicted, sameOutput ▸ same.typing (TypingClaim.const support.found arity)⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/ScopedExpr.lean b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean index 3b6eb6957..82dd5ebff 100644 --- a/Ix/Kernel/Verify/Consistency/ScopedExpr.lean +++ b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean @@ -172,6 +172,28 @@ theorem readScopedExpr?_all_parts {resolve : Address → Option (ConstRef β)} cases reading exact ⟨domainReads, bodyReads⟩ +/-- A term readable without registered locals keeps that reading in any +local context. Its syntactic binders retain the same indices. -/ +theorem readScopedExpr?_weaken_closed {resolve : Address → Option (ConstRef β)} + {term : KExpr m} {source : VExpr β} {depth : Nat} + (reading : readScopedExpr? resolve [] term depth = some source) (locals : List FVarId) : + readScopedExpr? resolve locals term depth = some source := by + induction term generalizing source depth with + | var _ _ _ | sort _ _ | const _ _ _ | nat _ _ _ => exact reading + | fvar _ _ _ | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readScopedExpr?] at reading + obtain ⟨f, fReads, reading⟩ := option_bind_success reading + obtain ⟨a, aReads, reading⟩ := option_bind_success reading + cases reading + simp [readScopedExpr?, hf fReads, ha aReads] + | prj id index value info ih => + rw [readScopedExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := option_bind_success reading + obtain ⟨value, valueReads, reading⟩ := option_bind_success reading + cases reading + simp [readScopedExpr?, resolved, ih valueReads] + /-- Closing the local context recovers the original reader exactly. -/ theorem readScopedExpr?_closed {resolve : Address → Option (ConstRef β)} {term : KExpr m} {source : VExpr β} {depth : Nat} diff --git a/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean b/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean new file mode 100644 index 000000000..427e7b588 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.ScopedExpr +import Ix.Kernel.Verify.Consistency.InstUniv + +/-! +# Universe instantiation of closed types in an active local context + +The universe walker preserves the term binders of a closed declaration type. +Its returned type therefore has the same scoped reading in every active local +context. Simplifying levels retain the existing exact annotation and semantic +congruence guarantees. No runtime result reading is assumed. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u +variable {β : Type u} + +private theorem option_bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ intermediate, action = some intermediate ∧ next intermediate = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +private theorem except_bind_success {ε α γ : Type _} {action : Except ε α} + {next : α → Except ε γ} {result : γ} (run : action.bind next = .ok result) : + ∃ intermediate, action = .ok intermediate ∧ next intermediate = .ok result := by + cases action with + | error err => contradiction + | ok value => exact ⟨value, rfl, run⟩ + +/-- Pure universe substitution preserves exactly the term-binding structure +needed to read a closed declaration type in an arbitrary local context. -/ +theorem instUnivSpec_scoped_eq {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} + {source : VExpr β} {depth : Nat} (locals : List FVarId) + (reading : readScopedExpr? resolve [] term depth = some source) + (run : KExpr.instUnivSpec term arguments = .ok result) : + readScopedExpr? resolve locals result depth = readExpr? resolve result := by + induction term generalizing source result depth with + | var index name info => + cases run + simp only [readScopedExpr?] at reading ⊢ + split at reading + next bound => simp [bound, readExpr?] + · contradiction + | fvar _ _ _ | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | nat _ _ _ => cases run; rfl + | sort _ _ | const _ _ _ => + rw [KExpr.instUnivSpec] at run + obtain ⟨_, _, run⟩ := except_bind_success run + cases run + rfl + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readScopedExpr?] at reading + obtain ⟨f, fReads, reading⟩ := option_bind_success reading + obtain ⟨a, aReads, reading⟩ := option_bind_success reading + rw [KExpr.instUnivSpec] at run + obtain ⟨fn', fRun, run⟩ := except_bind_success run + obtain ⟨arg', aRun, run⟩ := except_bind_success run + cases run + simp only [readScopedExpr?_mkApp, readScopedExpr?_mkLam, readScopedExpr?_mkAll] + rw [hf fReads fRun, ha aReads aRun] + rfl + | prj id index value info ih => + rw [readScopedExpr?] at reading + obtain ⟨ref, _, reading⟩ := option_bind_success reading + obtain ⟨value, valueReads, _⟩ := option_bind_success reading + rw [KExpr.instUnivSpec] at run + obtain ⟨value', valueRun, run⟩ := except_bind_success run + cases run + simp only [readScopedExpr?_mkPrj] + rw [ih valueReads valueRun] + rfl + +/-- Include the production empty-argument shortcut in the structural result. -/ +theorem instantiateUnivParamsSpec_scoped_eq {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} + {source : VExpr β} {depth : Nat} (locals : List FVarId) + (reading : readScopedExpr? resolve [] term depth = some source) + (run : KExpr.instantiateUnivParamsSpec term arguments = .ok result) : + readScopedExpr? resolve locals result depth = readExpr? resolve result := by + unfold KExpr.instantiateUnivParamsSpec at run + split at run + · cases run + exact (readScopedExpr?_weaken_closed reading locals).trans + (readScopedExpr?_closed reading).symm + · exact instUnivSpec_scoped_eq locals reading run + +/-- The real memoized and interned execution preserves closed term scope, +including when its universe constructors simplify the returned syntax. -/ +theorem instantiateUnivParams_scoped_eq {resolve : Address → Option (ConstRef β)} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} + {source : VExpr β} {depth : Nat} {before after : TcState .anon} + (locals : List FVarId) (support : UniverseInstantiationSupport before term arguments) + (reading : readScopedExpr? resolve [] term depth = some source) + (run : TcM.instantiateUnivParams term arguments before = .ok result after) : + readScopedExpr? resolve locals result depth = readExpr? resolve result := by + have post := TcM.instantiateUnivParams_wf support.faithful + (fun _ h => Or.inr h) ⟨support.coherent, fun _ h => Or.inl h⟩ + rw [run] at post + exact instantiateUnivParamsSpec_scoped_eq locals reading post.2.1 + +/-- Read the actual returned annotated type in an active local context. +Universe scope justifies the empty shortcut; all annotation occurrences and +hereditary validity are preserved by the level congruence. -/ +theorem instantiateUnivParams_readScopedAnnotated + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : AExpr β} + {before after : TcState .anon} + (support : UniverseInstantiationSupport before term arguments) + (scope : source.erase.LevelWF arguments.size) + (reading : readScopedExpr? resolve [] term = some source.erase) + (run : TcM.instantiateUnivParams term arguments before = .ok result after) : + ∃ output : AExpr β, readScopedExpr? resolve locals result = some output.erase ∧ + AExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output := by + obtain ⟨output, outputReads, same⟩ := instantiateUnivParams_readAnnotated support scope + (readScopedExpr?_closed reading) run + exact ⟨output, (instantiateUnivParams_scoped_eq locals support reading run).trans outputReads, same⟩ + +end Ix.Kernel.Consistency diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 0074c0ebe..0e9f7e93a 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -404,7 +404,98 @@ private def applicationCases : TestSeq := ++ test "application environment: applying a proof with no function type fails" (let (env, target) := failedBinder (.app (.var 0) (.var 0)); rowFailed env target) +/-- Call a polymorphic identity from a monomorphic function body. Universe +indices select entries in the declaration's explicit level table. -/ +private def storePolymorphicCall (env : Ixon.Env) (identity : Address) + (levels : Array Ixon.Univ) (domain : UInt64) (arguments : Array UInt64) + (kind : Ix.DefKind := .defn) : Ixon.Env × Address := + storeConst env + ⟨.defn ⟨kind, .safe, 0, + .leanAll (.sort domain) (.leanAll (.var 0) (.var 1)), + .leanLam (.sort domain) (.leanLam (.var 0) + (.app (.app (.ref 0 arguments) (.var 1)) (.var 0)))⟩, + #[], #[identity], levels⟩ + +private def polymorphicApplicationEnvironment : Ixon.Env := Id.run do + let (env, identity) := polymorphicIdentity + let (env, propCall) := storePolymorphicCall env identity #[.zero] 0 #[0] + let (env, _) := storePolymorphicCall env identity #[.succ .zero] 0 #[0] .opaq + let (env, _) := storePolymorphicCall env propCall #[.zero] 0 #[] .thm + return env + +/-- The source type retains a compound level until its two parameters are +substituted. This exercises simplification inside the returned Pi domain. -/ +private def computedIdentity (level : Ixon.Univ) : Ixon.Env × Address := + storeConst {} + ⟨.axio ⟨false, 2, .leanAll (.sort 0) (.leanAll (.var 0) (.var 1))⟩, + #[], #[], #[level]⟩ + +private def simplifiedPolymorphicCall (imax : Bool) : Ixon.Env := + let (env, identity) := computedIdentity + (if imax then .imax (.var 0) (.var 1) else .max (.var 0) (.var 1)) + let levels := if imax then #[.succ (.succ .zero), .zero] else #[.zero, .succ .zero] + (storePolymorphicCall env identity levels 1 #[0, 1]).1 + +/-- A declaration type containing instantiated references must stay closed +when inferred beneath an unrelated active local. -/ +private def scopedPolymorphicReferences : Bool := + let (env, function, carrier) := polymorphicReferences + let propType := KExpr.mkSort (m := .anon) .mkZero + let carrierType := KExpr.mkConst (m := .anon) ⟨carrier, ()⟩ #[levelOne] + let expected := KExpr.mkAll () () carrierType carrierType + let action : RecM .anon Bool := RecM.withLctxScope do + let _ ← TcM.openBinder () () propType (.mkVar 0 ()) + let inferred ← RecM.inferCall (.mkConst ⟨function, ()⟩ #[levelOne]) + return inferred.addr == expected.addr && inferred.lbr == 0 && (← get).lctx.size == 1 + match TcM.runRec action (TcState.newLazyAnon env) with + | .ok passed after => passed && after.lctx.size == 0 && after.env.nextFVarId == 1 + | .error _ _ => false + +/-- Different level instances use different inference keys, while neither +returned type can capture the active local. -/ +private def scopedPolymorphicInstances : Bool := + let propType := KExpr.mkSort (m := .anon) .mkZero + let propIdentity := KExpr.mkAll () () propType (.mkAll () () (.mkVar 0 ()) (.mkVar 1 ())) + let action : RecM .anon Bool := RecM.withLctxScope do + let _ ← TcM.openBinder () () propType (.mkVar 0 ()) + let first ← RecM.inferCall (.mkConst ⟨polymorphicIdentity.2, ()⟩ #[.mkZero]) + let second ← RecM.inferCall (.mkConst ⟨polymorphicIdentity.2, ()⟩ #[levelOne]) + let state ← get + return first.addr == propIdentity.addr && second.addr == identityType.addr && + first.addr != second.addr && first.lbr == 0 && second.lbr == 0 && + state.env.inferCache.size == 2 && state.lctx.size == 1 + match TcM.runRec action (TcState.newLazyAnon polymorphicIdentity.1) with + | .ok passed after => passed && after.lctx.size == 0 && after.env.nextFVarId == 1 + | .error _ _ => false + +private def polymorphicApplicationCases : TestSeq := + test "polymorphic calls: Prop/Type instances and a transitive theorem check" + (allSucceeded polymorphicApplicationEnvironment 4 { clearEvery := 0 }) + ++ test "polymorphic calls: function bodies check with fresh per-item caches" + (allSucceeded polymorphicApplicationEnvironment 4 { clearEvery := 1 }) + ++ test "polymorphic calls: max simplification exposes the Type domain" + (allSucceeded (simplifiedPolymorphicCall false) 2) + ++ test "polymorphic calls: imax simplification exposes the Prop domain" + (allSucceeded (simplifiedPolymorphicCall true) 2) + ++ test "polymorphic inference: nested reference arguments stay closed under an active local" + scopedPolymorphicReferences + ++ test "polymorphic inference: distinct instances retain closed types and separate cache keys" + scopedPolymorphicInstances + ++ test "polymorphic calls: a Type argument cannot use the Prop instance" + (let (env, identity) := polymorphicIdentity + let (env, target) := storePolymorphicCall env identity #[.zero, .succ .zero] 1 #[0] + rowFailed env target) + ++ test "polymorphic calls: missing universe arguments reject inside a function body" + (let (env, identity) := polymorphicIdentity + let (env, target) := storePolymorphicCall env identity #[.zero] 0 #[] + rowFailed env target) + ++ test "polymorphic calls: excess universe arguments reject inside a function body" + (let (env, identity) := polymorphicIdentity + let (env, target) := storePolymorphicCall env identity #[.zero] 0 #[0, 0] + rowFailed env target) + public def suite : List TestSeq := - [cases, polymorphicCases, specializationCases, binderCases, applicationCases] + [cases, polymorphicCases, specializationCases, binderCases, applicationCases, + polymorphicApplicationCases] end Tests.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 66174de9c..029f6ed39 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -59,19 +59,26 @@ increasing sequence of strongly inaccessible cardinals. primitive False when its environment has been admitted by the certified interface and the set-theory assumption has an instance. - `BinderInference.sound` follows finite production inference trees for sorts, - locals, monomorphic constants, applications, dependent functions, and + locals, polymorphic constants, applications, dependent functions, and full-mode lambdas. `LocalContextReading.push` and `openBinder_sound` connect actual declaration lookup and fresh-variable opening to the model's dependent context. Singleton abstraction closes the resulting function type, and the simplifying `imax` constructor preserves its universe interpretation. - `BinderInference.synthesis` derives full typing for application spines - headed by a local or an admitted monomorphic constant. The function's type + headed by a local or an admitted constant. The function's type supplies hereditary validity of its domain, so arguments may be checked lambdas. Faithful hash conversion identifies the argument's inferred type with that domain, with matching occurrence annotations. `subst_readScopedExpr?` connects the actual memoized and interned codomain substitution to model substitution, including active locals and nested binders. +- `instantiateUnivParams_readScopedAnnotated` brings the actual substituted + declaration type into any active local context, preserving its closed term + scope and occurrence annotations. `infer_const_scoped_annotated` uses this + result for polymorphic references in binder trees. A pure substitution and + syntax-reading check fixes the tree's result annotation; the admitted model + and actual execution establish typing. Runtime success supplies arity, while + scoped arguments also give scope of the returned type. - `FVarInferenceSupport.sound` handles both local-variable cache partitions when a cached answer equals the current declaration's concrete type. These are structural cache checks, with no assumed semantic typing of cached data. @@ -113,6 +120,7 @@ def propIdent : (α : Prop) → α → α := ident.{0} def idProp (P : Prop) (p : P) : P := p def useId (P : Prop) (p : P) : P := idProp P p def applyProp (P Q : Prop) (f : P → Q) (p : P) : Q := f p +def usePoly (P : Prop) (p : P) : P := ident.{0} P p ``` `AtomicEnvironmentFragment` records the precise execution boundary: @@ -144,10 +152,13 @@ def applyProp (P Q : Prop) (f : P → Q) (p : P) : Q := f p without an eager-reduction marker, and the hash-equality conversion path. Their witnesses retain the actual recursive calls, context preservation during function inference, and finite substitution resources. Function - spines start with locals or monomorphic constants; the latter use exact - lazy-lookup agreement and empty universe substitution. Applying a lambda - directly, polymorphic references within binder trees, and reduction to - expose a Pi require further refinement. + spines start with locals or admitted constants. Polymorphic constants supply + exact lazy-lookup agreement, a closed scoped reading of the selected entry's + type, and finite universe-substitution resources. Their result type is fixed + by a pure `readInstantiatedType?` check with the substituted occurrence + annotations, including when levels simplify. Monomorphic references retain + their simpler empty-substitution rule. Applying a lambda directly and + reduction to expose a Pi require further refinement. - Conversion takes the initial hash-equality path, with faithfulness of the compared expressions. General reduction and conversion caches are outside this fragment. @@ -219,7 +230,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 110 exact theorem boundaries. The production +The consistency target checks 121 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -244,6 +255,10 @@ Function-body regressions cover calls to earlier Prop/Type identities, transitive theorem calls, local functions with distinct domains and codomains, dependent result families, lambda arguments, exact local results through cache reuse and scope cleanup, and rejected argument/function types. +Polymorphic-call regressions include Prop/Type instances in real function +bodies, `max`/`imax` simplification inside Pi domains, closed nested references +under active locals, separate cache keys for different universe instances, +and rejected universe arities and argument types. ## Certified host adapters @@ -270,6 +285,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Certified checker contracts | [`Ix/Kernel/Certified.lean`](../Ix/Kernel/Certified.lean), [`CertifiedClaims.lean`](../Ix/Kernel/CertifiedClaims.lean) | | Direct production refinement and its audit | [`Ix/Kernel/Verify/Consistency.lean`](../Ix/Kernel/Verify/Consistency.lean) | | Polymorphic inference and universe substitution | [`Consistency/Constant.lean`](../Ix/Kernel/Verify/Consistency/Constant.lean), [`InstUniv.lean`](../Ix/Kernel/Verify/Consistency/InstUniv.lean), [`Model/LevelCongruence.lean`](../Ix/Theory/Model/LevelCongruence.lean) | +| Polymorphic calls inside binders | [`Consistency/ScopedConstant.lean`](../Ix/Kernel/Verify/Consistency/ScopedConstant.lean), [`ScopedInstUniv.lean`](../Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | diff --git a/docs/theory.md b/docs/theory.md index 3a9f63013..da733f35e 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -25,7 +25,7 @@ polymorphic constants, and a fragment of closed dependent function bodies extends every model of its source axioms under explicit execution witnesses. Binder inference uses the declared type's separate formation check to turn `Model.CheckingClaim` into semantic typing. Application spines headed by locals -or admitted monomorphic constants derive their type's validity from the context +or admitted polymorphic constants derive their type's validity from the context or dependency model, then check arguments and substitute the dependent result. Full checker consistency and compiler/backend refinement remain open. From caa982650646d008b946587008081006a838a855 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 13:39:28 -0400 Subject: [PATCH 11/30] Refine constant cache hits in function inference --- Ix/Kernel/Verify/Consistency.lean | 9 +- Ix/Kernel/Verify/Consistency/Atomic.lean | 29 +++- Ix/Kernel/Verify/Consistency/Audit.lean | 8 +- .../Verify/Consistency/BinderInference.lean | 11 +- .../Verify/Consistency/ConstantCache.lean | 150 ++++++++++++++++++ .../Verify/Consistency/ScopedInstUniv.lean | 30 ++++ Tests/Ix/Kernel/Consistency.lean | 111 ++++++++++++- docs/kernel-verification.md | 34 +++- docs/theory.md | 3 + 9 files changed, 366 insertions(+), 19 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/ConstantCache.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index a4e64c077..74022d49c 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -13,6 +13,7 @@ import Ix.Kernel.Verify.Consistency.Atomic import Ix.Kernel.Verify.Consistency.ScopedExpr import Ix.Kernel.Verify.Consistency.ScopedInstUniv import Ix.Kernel.Verify.Consistency.ScopedConstant +import Ix.Kernel.Verify.Consistency.ConstantCache import Ix.Kernel.Verify.Consistency.Context import Ix.Kernel.Verify.Consistency.BinderOpening import Ix.Kernel.Verify.Consistency.Application @@ -36,12 +37,16 @@ universe-instantiation walker and explicit lookup and finite-support resources. The returned type's scope and references justify declaration admission. The binder case also requires explicit syntactic scope and references to the preceding interface. Its separate declared-type inference turns semantic checking -into typing. Local cache hits agree with the actual declaration type; other -inference nodes retain cache-miss boundaries. +into typing. Local cache hits agree with the actual declaration type. Constant +hits agree with pure universe substitution of a loaded, admitted declaration; +the other inference nodes retain cache-miss boundaries. Applications use syntactic Pi exposure, full argument checking, hash conversion, and arguments without eager-reduction markers. Constant- and local-headed spines derive type validity from the admitted model or local context; their arguments may be lambdas. Polymorphic nodes use closed source readings, finite substitution resources, and a pure prediction of the returned syntax with matching occurrence annotations. +Cache hits additionally check arity because they skip the runtime guard. Exact +cache selection and successful constant writes are proved; general preservation +of cache agreement across checker operations remains an explicit obligation. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Atomic.lean b/Ix/Kernel/Verify/Consistency/Atomic.lean index d6317d312..e17b55c20 100644 --- a/Ix/Kernel/Verify/Consistency/Atomic.lean +++ b/Ix/Kernel/Verify/Consistency/Atomic.lean @@ -29,14 +29,20 @@ structure UncachedInference (before : TcState .anon) (term : KExpr .anon) where fullMiss : keyed.env.inferCache[key]? = none onlyMiss : keyed.env.inferOnlyCache[key]? = none -/-- Strip only key lookup and the final cache write from an actual successful -inference. The recursive method table and returned type are unchanged. -/ -theorem infer_uncached_success {term type : KExpr .anon} +/-- Recover the uncached execution and the exact final cache write from a +successful miss. The policy is read before production computes the key. -/ +theorem infer_uncached_success_state {term type : KExpr .anon} {methods : Methods .anon} {before after : TcState .anon} (miss : UncachedInference before term) (accepted : RecM.infer term methods before = .ok type after) : ∃ inferredState, RecM.inferUncached RecM.inferCall before.inferOnly term - methods miss.keyed = .ok type inferredState := by + methods miss.keyed = .ok type inferredState ∧ + after = if before.inferOnly then + { inferredState with env := { inferredState.env with + inferOnlyCache := inferredState.env.inferOnlyCache.insert miss.key type } } + else + { inferredState with env := { inferredState.env with + inferCache := inferredState.env.inferCache.insert miss.key type } } := by change (RecM.infer term).run methods before = .ok type after at accepted unfold RecM.infer RecM.inferWith at accepted simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted @@ -59,7 +65,7 @@ theorem infer_uncached_success {term type : KExpr .anon} change EStateM.Result.ok ty { state with env := { state.env with inferCache := state.env.inferCache.insert miss.key ty } } = .ok type after at accepted cases accepted - exact ⟨state, rfl⟩ + exact ⟨state, rfl, rfl⟩ | true => simp only [policy, if_true] at accepted simp only [ReaderT.run_bind] at accepted @@ -77,7 +83,18 @@ theorem infer_uncached_success {term type : KExpr .anon} change EStateM.Result.ok ty { state with env := { state.env with inferOnlyCache := state.env.inferOnlyCache.insert miss.key ty } } = .ok type after at accepted cases accepted - exact ⟨state, rfl⟩ + exact ⟨state, rfl, rfl⟩ + +/-- Strip only key lookup and the final cache write from an actual successful +inference. The recursive method table and returned type are unchanged. -/ +theorem infer_uncached_success {term type : KExpr .anon} + {methods : Methods .anon} {before after : TcState .anon} + (miss : UncachedInference before term) + (accepted : RecM.infer term methods before = .ok type after) : + ∃ inferredState, RecM.inferUncached RecM.inferCall before.inferOnly term + methods miss.keyed = .ok type inferredState := by + obtain ⟨state, run, _⟩ := infer_uncached_success_state miss accepted + exact ⟨state, run⟩ /-- Supported syntax plus the concrete resources needed by its uncached production branch. A constant's semantic type comes from an existing entry, diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 916e7fd0b..e0f399783 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -33,11 +33,12 @@ private def productionNative : Array Lean.Name := #[ ] private def atomicRoots : Array Lean.Name := #[ - ``infer_uncached_success, ``AtomicInferenceSupport.typing, + ``infer_uncached_success_state, ``infer_uncached_success, ``AtomicInferenceSupport.typing, ``AtomicInferenceSupport.reads, ``AtomicInferenceSupport.output, ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound, ``inferUncached_fvar_sound, ``infer_fvar_sound, ``FVarInferenceSupport.output, ``FVarInferenceSupport.sound, + ``InferenceCacheHit.run, ``ForallInferenceTrace.output, ``LambdaInferenceTrace.output, ``BinderInference.sound, ``inferUncached_monomorphic_const_scoped, ``ApplicationInferenceTrace.output, ``BinderInference.soundWithSynthesis, ``BinderInference.synthesis, @@ -50,11 +51,14 @@ private def instantiationRoots : Array Lean.Name := #[ ``instantiateUnivParams_readAnnotated_scoped, ``instUnivSpec_scoped_eq, ``instantiateUnivParamsSpec_scoped_eq, ``instantiateUnivParams_scoped_eq, ``instantiateUnivParams_readScopedAnnotated, + ``instantiateUnivParamsSpec_readScopedAnnotated, ``inferUncached_const_refinement, ``infer_const_refinement, ``inferUncached_const_sound, ``infer_const_sound, ``inferUncached_const_instantiation, ``ScopedConstantInferenceSupport.closed, ``inferUncached_const_scoped_refinement, ``inferUncached_const_scoped_sound, - ``inferUncached_const_predicted_type, ``infer_const_scoped_annotated + ``inferUncached_const_predicted_type, ``infer_const_scoped_annotated, + ``infer_const_cache_write, ``CachedConstantInferenceSupport.refinement, + ``CachedConstantInferenceSupport.sound ] private def productionRoots : Array Lean.Name := #[ diff --git a/Ix/Kernel/Verify/Consistency/BinderInference.lean b/Ix/Kernel/Verify/Consistency/BinderInference.lean index 4b47a4a33..c0950986e 100644 --- a/Ix/Kernel/Verify/Consistency/BinderInference.lean +++ b/Ix/Kernel/Verify/Consistency/BinderInference.lean @@ -4,14 +4,14 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Application -import Ix.Kernel.Verify.Consistency.ScopedConstant +import Ix.Kernel.Verify.Consistency.ConstantCache import Ix.Theory.Model.Checking /-! # Production dependent function inference Finite inference trees follow the production method table's decreasing fuel. -Their premises record cache misses, actual execution prefixes, local-context +Their premises record cache observations, actual execution prefixes, local-context frames, finite interning support, and index bounds. Semantic checking is derived from these trees. A declaration's separate type inference supplies the expected type's hereditary validity before checking becomes typing. @@ -237,6 +237,10 @@ inductive BinderInference {β : Type u} (conditions : (entry.type.instL (arguments.toList.map readLevel)).annotations = type.annotations) : BinderInference resolve entries locals context fuel before (.const id arguments info) (.const ref (arguments.toList.map readLevel)) type + | cachedConst {locals context fuel before id arguments info ref entry type} + (cache : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) : + BinderInference resolve entries locals context fuel before (.const id arguments info) + (.const ref (arguments.toList.map readLevel)) type | app {locals context fuel before fn arg info f a A A' B condition} (full : before.inferOnly = false) (miss : UncachedInference before (.app fn arg info)) @@ -332,6 +336,9 @@ theorem BinderInference.soundWithSynthesis {β : Type u} | polymorphic miss support prediction conditions => obtain ⟨typeReads, typed⟩ := infer_const_scoped_annotated miss support prediction conditions accepted exact ⟨typeReads, typed.checking, fun _ => typed⟩ + | cachedConst cache => + obtain ⟨typeReads, typed⟩ := cache.sound accepted + exact ⟨typeReads, typed.checking, fun _ => typed⟩ | @app locals context fuel before fn arg info f a A A' B condition full miss trace functionTree head argumentTree conditions hashPath comparisonFaithful bodyConstructed argConstructed bodyBound argBound coherent faithful ihFunction ihArgument => diff --git a/Ix/Kernel/Verify/Consistency/ConstantCache.lean b/Ix/Kernel/Verify/Consistency/ConstantCache.lean new file mode 100644 index 000000000..728b72934 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/ConstantCache.lean @@ -0,0 +1,150 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.ScopedConstant + +/-! +# Constant inference cache hits + +Production cache selection gives full checking priority and consults the +inference-only partition only under that policy. A selected constant result +must equal pure universe substitution of its current loaded declaration. +The admitted entry then supplies typing; no semantic cache invariant is an +input. These witnesses check individual entries, not global cache maintenance. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +/-- The exact cache entry eligible at production's computed inference key. +An inference-only result cannot witness a full-mode hit or override a full +result. No declaration lookup or recursive inference is performed on a hit. -/ +structure InferenceCacheHit (before : TcState .anon) (term : KExpr .anon) where + key : Address × Address + keyed : TcState .anon + cached : KExpr .anon + keyRun : TcM.inferKey term before = .ok key keyed + selected : keyed.env.inferCache[key]? = some cached ∨ + (keyed.env.inferCache[key]? = none ∧ before.inferOnly = true ∧ + keyed.env.inferOnlyCache[key]? = some cached) + +/-- Cache selection determines both the returned type and state, without +executing the uncached branch or rewriting either cache partition. -/ +theorem InferenceCacheHit.run {before : TcState .anon} {term : KExpr .anon} + (hit : InferenceCacheHit before term) (methods : Methods .anon) : + RecM.infer term methods before = .ok hit.cached hit.keyed := by + change (RecM.infer term).run methods before = _ + unfold RecM.infer RecM.inferWith + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.inferKey term) _ before = _ + rw [EStateM.bind, hit.keyRun] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ hit.keyed = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) hit.keyed = + .ok hit.keyed hit.keyed from rfl] + rcases hit.selected with full | ⟨full, policy, only⟩ + · simp only [full]; rfl + · simp only [full, policy, if_true, ReaderT.run_bind] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ hit.keyed = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) hit.keyed = + .ok hit.keyed hit.keyed from rfl] + simp only [only] + rfl + +/-- A successful constant miss inserts the exact pure substituted type in +the selected partition. This establishes the concrete substitution agreement +used by later hits; preserving it across other operations remains explicit. -/ +theorem infer_const_cache_write {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {before after : TcState .anon} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} + {methods : Methods .anon} {result : KExpr .anon} + (miss : UncachedInference before (.const id arguments info)) + (support : ScopedConstantInferenceSupport resolve entries miss.keyed id arguments ref entry) + (accepted : RecM.infer (.const id arguments info) methods before = .ok result after) : + ∃ concrete loaded, TcM.getConst id miss.keyed = .ok concrete loaded ∧ + concrete.lvls.toNat = arguments.size ∧ + KExpr.instantiateUnivParamsSpec concrete.ty arguments = .ok result ∧ + (if before.inferOnly then after.env.inferOnlyCache[miss.key]? + else after.env.inferCache[miss.key]?) = some result := by + obtain ⟨state, run, written⟩ := infer_uncached_success_state miss accepted + obtain ⟨concrete, loaded, got, arity, instantiated⟩ := inferUncached_const_instantiation run + obtain ⟨_, _, resources⟩ := support.lookup concrete loaded got + have post := TcM.instantiateUnivParams_wf resources.faithful + (fun _ h => Or.inr h) ⟨resources.coherent, fun _ h => Or.inl h⟩ + rw [instantiated] at post + refine ⟨concrete, loaded, got, arity, post.2.1, ?_⟩ + cases policy : before.inferOnly <;> simp [policy, written] + +/-- Concrete coherence for one selected constant cache entry. Both arity +equalities are explicit because a hit skips the runtime arity guard. The +cached syntax equals pure substitution of a loaded declaration whose type +reads as the admitted entry. Prediction and annotations select the result +of a finite inference tree; they do not assert typing or validity. -/ +structure CachedConstantInferenceSupport {β : Type u} + (resolve : Address → Option (ConstRef β)) (entries : Model.Environment β) + (before : TcState .anon) (id : KId .anon) (arguments : Array (KUniv .anon)) + (info : ExprInfo .anon) (ref : ConstRef β) (entry : ConstantEntry β) (type : AExpr β) where + hit : InferenceCacheHit before (.const id arguments info) + concrete : KConst .anon + loaded : hit.keyed.env.get? id = some concrete + resolved : resolve id.addr = some ref + found : entries ref = some entry + count : concrete.lvls.toNat = entry.universes + arity : concrete.lvls.toNat = arguments.size + scope : entry.type.Scope entry.universes 0 + reading : readScopedExpr? resolve [] concrete.ty = some entry.type.erase + levels : UniverseSubstitutionSupport arguments concrete.ty + substitution : KExpr.instantiateUnivParamsSpec concrete.ty arguments = .ok hit.cached + prediction : readInstantiatedType? resolve concrete.ty arguments = some type.erase + conditions : (entry.type.instL (arguments.toList.map readLevel)).annotations = type.annotations + +/-- The pure prediction and concrete cache agreement derive the cached +type's reading in every active context and its congruence with the admitted +entry's instantiated type. Mutable interning resources are unnecessary. -/ +theorem CachedConstantInferenceSupport.refinement {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {before : TcState .anon} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + (support : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) + (locals : List FVarId) : + readScopedExpr? resolve locals support.hit.cached = some type.erase ∧ + AExpr.LevelEquivalent (entry.type.instL (arguments.toList.map readLevel)) type ∧ + (arguments.toList.map readLevel).length = entry.universes := by + have scope : entry.type.Scope arguments.size 0 := by + rw [← support.arity, support.count] + exact support.scope + obtain ⟨output, outputReads, same⟩ := instantiateUnivParamsSpec_readScopedAnnotated + (locals := locals) support.levels scope.erase.1 support.reading support.substitution + have predicted := support.prediction + rw [readInstantiatedType?, support.substitution] at predicted + have typeReads := readScopedExpr?_weaken_closed predicted locals + have equal := AExpr.eq_of_erase_annotations + (Option.some.inj (outputReads.symm.trans typeReads)) + (same.annotations.symm.trans support.conditions) + refine ⟨typeReads, equal ▸ same, ?_⟩ + simpa only [List.length_map, Array.length_toList] using support.arity.symm.trans support.count + +/-- An actual cache hit has the admitted constant's full model typing. The +semantic conclusion is derived from concrete cache coherence, pure universe +substitution, and the dependency model, including simplifying levels. -/ +theorem CachedConstantInferenceSupport.sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} + {before after : TcState .anon} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + {methods : Methods .anon} {result : KExpr .anon} + (support : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) + (accepted : RecM.infer (.const id arguments info) methods before = .ok result after) : + readScopedExpr? resolve locals result = some type.erase ∧ + TypingClaim.{u,v} entries context (.const ref (arguments.toList.map readLevel)) type := by + rw [support.hit.run methods] at accepted + cases accepted + obtain ⟨typeReads, same, arity⟩ := support.refinement locals + exact ⟨typeReads, same.typing (TypingClaim.const support.found arity)⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean b/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean index 427e7b588..1cb237e01 100644 --- a/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean +++ b/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean @@ -108,6 +108,36 @@ theorem instantiateUnivParams_scoped_eq {resolve : Address → Option (ConstRef rw [run] at post exact instantiateUnivParamsSpec_scoped_eq locals reading post.2.1 +/-- The pure substituted tree has the admitted type's meaning, including the +empty shortcut and simplifying universe constructors. Cache verification uses +only level resources here; it does not run an interning operation. -/ +theorem instantiateUnivParamsSpec_readScopedAnnotated + {resolve : Address → Option (ConstRef β)} {locals : List FVarId} + {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : AExpr β} + (support : UniverseSubstitutionSupport arguments term) + (scope : source.erase.LevelWF arguments.size) + (reading : readScopedExpr? resolve [] term = some source.erase) + (run : KExpr.instantiateUnivParamsSpec term arguments = .ok result) : + ∃ output : AExpr β, readScopedExpr? resolve locals result = some output.erase ∧ + AExpr.LevelEquivalent (source.instL (arguments.toList.map readLevel)) output := by + have raw : ∃ output, readExpr? resolve result = some output ∧ + VExpr.LevelEquivalent (source.erase.instL (arguments.toList.map readLevel)) output := by + by_cases empty : arguments.isEmpty = true + · have args : arguments = #[] := Array.isEmpty_iff.mp empty + subst arguments + change Except.ok term = .ok result at run + cases run + refine ⟨source.erase, readScopedExpr?_closed reading, ?_⟩ + simpa only [Array.toList_empty, List.map_nil, scope.instL_nil] using + VExpr.LevelEquivalent.refl source.erase + · rw [KExpr.instantiateUnivParamsSpec, if_neg empty] at run + exact instUnivSpec_readExpr? support (readScopedExpr?_closed reading) run + obtain ⟨raw, rawReads, same⟩ := raw + rw [← AExpr.erase_instL] at same + obtain ⟨output, erased, equivalent⟩ := AExpr.reannotate_levels _ same + exact ⟨output, (instantiateUnivParamsSpec_scoped_eq locals reading run).trans + (erased ▸ rawReads), equivalent⟩ + /-- Read the actual returned annotated type in an active local context. Universe scope justifies the empty shortcut; all annotation occurrences and hereditary validity are preserved by the level congruence. -/ diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 0e9f7e93a..c293e6a66 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -494,8 +494,117 @@ private def polymorphicApplicationCases : TestSeq := let (env, target) := storePolymorphicCall env identity #[.zero] 0 #[0, 0] rowFailed env target) +/-- Every wrapper repeats the same closed carrier in its declared domain, +codomain, and lambda domain. The second and later references hit the cache +even when the driver clears caches before every declaration. -/ +private def repeatedReferenceEnvironment : Ixon.Env := Id.run do + let (env, function, carrier) := polymorphicReferences + let wrapper : Address → Ixon.Univ → Array UInt64 → Ix.DefKind → Ixon.Constant := + fun callee level arguments kind => + ⟨.defn ⟨kind, .safe, 0, + .leanAll (.ref 0 #[0]) (.ref 0 #[0]), + .leanLam (.ref 0 #[0]) (.app (.ref 1 arguments) (.var 0))⟩, + #[], #[carrier, callee], #[level]⟩ + let (env, first) := storeConst env (wrapper function .zero #[0] .defn) + let (env, _) := storeConst env (wrapper function (.succ .zero) #[0] .opaq) + let (env, _) := storeConst env (wrapper first .zero #[] .thm) + return env + +/-- The selected entry is populated by real inference, then reused in two +different local scopes. Cache keys and closed returned types stay stable. -/ +private def cachedConstantAcrossScopes (source : Ixon.Env × Address) + (arguments : Array (KUniv .anon)) (expected : KExpr .anon) (inferOnly : Bool) : Bool := + let term := KExpr.mkConst (m := .anon) ⟨source.2, ()⟩ arguments + let propType := KExpr.mkSort (m := .anon) .mkZero + let action : RecM .anon Bool := do + let first ← RecM.inferCall term + let key ← TcM.inferKey term + let initial ← get + let reuse : RecM .anon Bool := RecM.withLctxScope do + let _ ← TcM.openBinder () () propType (.mkVar 0 ()) + let activeKey ← TcM.inferKey term + let result ← RecM.inferCall term + return activeKey == key && result.addr == expected.addr && result.lbr == 0 && + (← get).lctx.size == 1 + let second ← reuse + let third ← reuse + let final ← get + return first.addr == expected.addr && second && third && + (if inferOnly then initial.env.inferOnlyCache[key]?.isSome && + final.env.inferOnlyCache.size == initial.env.inferOnlyCache.size && final.env.inferCache.isEmpty + else initial.env.inferCache[key]?.isSome && + final.env.inferCache.size == initial.env.inferCache.size && final.env.inferOnlyCache.isEmpty) + match TcM.runRec action { TcState.newLazyAnon source.1 with inferOnly } with + | .ok passed after => passed && after.lctx.size == 0 && after.env.nextFVarId == 2 + | .error _ _ => false + +/-- A deliberately different result in the ineligible partition makes the +selection policy observable. Full mode must compute a checked answer when +only that entry exists; inference-only mode must prefer a full result. -/ +private def constantCachePriority (fullHit : Bool) : Bool := + let term := KExpr.mkConst (m := .anon) ⟨polymorphicIdentity.2, ()⟩ #[levelOne] + let sentinel := KExpr.mkSort (m := .anon) .mkZero + let action : RecM .anon Bool := do + let expected ← RecM.inferOnlyCall term + let key ← TcM.inferKey term + modify fun state => { state with inferOnly := fullHit, env := { state.env with + inferCache := if fullHit then state.env.inferCache.insert key expected else state.env.inferCache + inferOnlyCache := state.env.inferOnlyCache.insert key sentinel } } + let result ← RecM.inferCall term + let state ← get + return result.addr == identityType.addr && result.addr != sentinel.addr && + state.env.inferCache[key]?.any (fun cached => cached.addr == expected.addr) && + state.env.inferOnlyCache[key]?.any (fun cached => cached.addr == sentinel.addr) + match TcM.runRec action (TcState.newLazyAnon polymorphicIdentity.1) with + | .ok passed _ => passed + | .error _ _ => false + +/-- Alternating two instances after their first use must retrieve the type +for that instance, while retaining only two closed constant cache entries. -/ +private def repeatedConstantInstances : Bool := + let propType := KExpr.mkSort (m := .anon) .mkZero + let propIdentity := KExpr.mkAll () () propType (.mkAll () () (.mkVar 0 ()) (.mkVar 1 ())) + let propTerm := KExpr.mkConst (m := .anon) ⟨polymorphicIdentity.2, ()⟩ #[.mkZero] + let typeTerm := KExpr.mkConst (m := .anon) ⟨polymorphicIdentity.2, ()⟩ #[levelOne] + let action : RecM .anon Bool := do + let _ ← RecM.inferCall propTerm + let _ ← RecM.inferCall typeTerm + let propResult ← RecM.inferCall propTerm + let typeResult ← RecM.inferCall typeTerm + return propTerm.addr != typeTerm.addr && propResult.addr == propIdentity.addr && + typeResult.addr == identityType.addr && (← get).env.inferCache.size == 2 + match TcM.runRec action (TcState.newLazyAnon polymorphicIdentity.1) with + | .ok passed _ => passed + | .error _ _ => false + +private def constantCacheCases : TestSeq := + test "constant cache: repeated carrier references and transitive calls check" + (allSucceeded repeatedReferenceEnvironment 5 { clearEvery := 0 }) + ++ test "constant cache: repeated references within one declaration survive per-item clearing" + (allSucceeded repeatedReferenceEnvironment 5 { clearEvery := 1 }) + ++ test "constant cache: polymorphic full results survive two fresh local scopes" + (cachedConstantAcrossScopes polymorphicIdentity #[levelOne] identityType false) + ++ test "constant cache: polymorphic inference-only results survive two fresh local scopes" + (cachedConstantAcrossScopes polymorphicIdentity #[levelOne] identityType true) + ++ test "constant cache: empty universe substitution reuses a monomorphic definition type" + (cachedConstantAcrossScopes (monomorphicIdentity (.succ .zero)) #[] identityType false) + ++ test "constant cache: repeated max substitution retains its simplified type" + (cachedConstantAcrossScopes (computedIdentity (.max (.var 0) (.var 1))) + #[.mkZero, levelOne] identityType false) + ++ test "constant cache: repeated imax substitution retains its simplified type" + (let propType := KExpr.mkSort (m := .anon) .mkZero + let expected := KExpr.mkAll () () propType (.mkAll () () (.mkVar 0 ()) (.mkVar 1 ())) + cachedConstantAcrossScopes (computedIdentity (.imax (.var 0) (.var 1))) + #[levelOne, .mkZero] expected true) + ++ test "constant cache: inference-only mode gives the full result priority" + (constantCachePriority true) + ++ test "constant cache: full mode ignores an inference-only answer and checks the constant" + (constantCachePriority false) + ++ test "constant cache: alternating universe instances retrieve their own cached types" + repeatedConstantInstances + public def suite : List TestSeq := [cases, polymorphicCases, specializationCases, binderCases, applicationCases, - polymorphicApplicationCases] + polymorphicApplicationCases, constantCacheCases] end Tests.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 029f6ed39..93725fbc4 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -82,6 +82,15 @@ increasing sequence of strongly inaccessible cardinals. - `FVarInferenceSupport.sound` handles both local-variable cache partitions when a cached answer equals the current declaration's concrete type. These are structural cache checks, with no assumed semantic typing of cached data. +- `CachedConstantInferenceSupport.sound` brings monomorphic and polymorphic + constant hits into binder trees. The selected cached value equals pure + universe substitution of the current loaded declaration, whose type agrees + with the admitted entry. Pure substitution establishes semantic congruence, + including simplifying levels, without mutable interning resources. + `InferenceCacheHit.run` proves the exact cache selection and returned state; + full results take priority, and inference-only results require that policy. + `infer_const_cache_write` establishes substitution agreement for a successful + miss's insertion. General preservation of that agreement remains open. - `checkEnvAnon_atomic_preserves_model` connects a supported production environment run to model extension. `checkEnvAnon_atomic_no_false` excludes a declaration at an axiom type interpreted as empty, including False. @@ -121,6 +130,9 @@ def idProp (P : Prop) (p : P) : P := p def useId (P : Prop) (p : P) : P := idProp P p def applyProp (P Q : Prop) (f : P → Q) (p : P) : Q := f p def usePoly (P : Prop) (p : P) : P := ident.{0} P p +axiom T.{u} : Sort u +axiom f.{u} : T.{u} → T.{u} +def useF (x : T.{1}) : T.{1} := f.{1} x ``` `AtomicEnvironmentFragment` records the precise execution boundary: @@ -128,10 +140,13 @@ def usePoly (P : Prop) (p : P) : P := ident.{0} P p - Every source key occurs in the `buildAnonWork` result, and every work item represents an axiom or a definition. Lookup, routing, and reset witnesses identify the checked `KConst`. -- Sort, constant, application, forall, and lambda nodes in the inference witnesses miss both cache partitions. +- Sort, application, forall, and lambda nodes in the inference witnesses miss both cache partitions. Local-variable hits must match the current production declaration type. - Constant lookup agrees with - an already admitted type and universe count. A specialization supplies + Constant nodes use either the existing miss rule or a selected cache hit. + A hit checks the loaded declaration, universe arity, finite level resources, + and equality of the cached value with pure substitution of its type. + Its arity agreement is explicit because no runtime arity guard executes. + A miss's lookup agrees with an already admitted type and universe count. A specialization supplies closed universe arguments and finite interning/substitution resources at the actual post-lookup state. The occurrence annotations on the declared type agree with the substituted entry's annotations. These are structural @@ -153,8 +168,9 @@ def usePoly (P : Prop) (p : P) : P := ident.{0} P p Their witnesses retain the actual recursive calls, context preservation during function inference, and finite substitution resources. Function spines start with locals or admitted constants. Polymorphic constants supply - exact lazy-lookup agreement, a closed scoped reading of the selected entry's - type, and finite universe-substitution resources. Their result type is fixed + lazy-lookup agreement on misses or loaded-declaration agreement on hits, a + closed scoped reading of the selected entry's type, and finite + universe-substitution resources. Their result type is fixed by a pure `readInstantiatedType?` check with the substituted occurrence annotations, including when levels simplify. Monomorphic references retain their simpler empty-substitution rule. Applying a lambda directly and @@ -230,7 +246,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 121 exact theorem boundaries. The production +The consistency target checks 127 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -259,6 +275,11 @@ Polymorphic-call regressions include Prop/Type instances in real function bodies, `max`/`imax` simplification inside Pi domains, closed nested references under active locals, separate cache keys for different universe instances, and rejected universe arities and argument types. +Constant-cache regressions cover repeated carrier references within declared +types and bodies, including per-item cache clearing; full and inference-only +reuse across fresh local scopes; monomorphic and simplifying substitutions; +partition priority; and alternating universe instances. Deliberately different +values in an ineligible partition make the selection tests observable. ## Certified host adapters @@ -286,6 +307,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Direct production refinement and its audit | [`Ix/Kernel/Verify/Consistency.lean`](../Ix/Kernel/Verify/Consistency.lean) | | Polymorphic inference and universe substitution | [`Consistency/Constant.lean`](../Ix/Kernel/Verify/Consistency/Constant.lean), [`InstUniv.lean`](../Ix/Kernel/Verify/Consistency/InstUniv.lean), [`Model/LevelCongruence.lean`](../Ix/Theory/Model/LevelCongruence.lean) | | Polymorphic calls inside binders | [`Consistency/ScopedConstant.lean`](../Ix/Kernel/Verify/Consistency/ScopedConstant.lean), [`ScopedInstUniv.lean`](../Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean) | +| Constant cache selection, writes, and typing | [`Consistency/ConstantCache.lean`](../Ix/Kernel/Verify/Consistency/ConstantCache.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | diff --git a/docs/theory.md b/docs/theory.md index da733f35e..73a5a39c9 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -27,6 +27,9 @@ Binder inference uses the declared type's separate formation check to turn `Model.CheckingClaim` into semantic typing. Application spines headed by locals or admitted polymorphic constants derive their type's validity from the context or dependency model, then check arguments and substitute the dependent result. +Constant cache hits derive the same typing from concrete agreement with pure +universe substitution of a loaded declaration. Cache selection and successful +miss writes are proved; general cache maintenance remains a separate obligation. Full checker consistency and compiler/backend refinement remain open. From 6ff0ccaa5fb90d6e43561e31abcb86b99c4c6a8a Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 15:09:41 -0400 Subject: [PATCH 12/30] Prove inference cache preservation for sorts and loaded constants --- Ix/Kernel/Verify/Consistency.lean | 16 +- Ix/Kernel/Verify/Consistency/Atomic.lean | 8 +- Ix/Kernel/Verify/Consistency/Audit.lean | 34 +- .../Verify/Consistency/BinderInference.lean | 54 +-- .../Verify/Consistency/ConstantCache.lean | 201 +++++++++-- Ix/Kernel/Verify/Consistency/Context.lean | 5 +- .../Verify/Consistency/InferenceCache.lean | 323 ++++++++++++++++++ Ix/Kernel/Verify/Consistency/SortCache.lean | 109 ++++++ Tests/Ix/Kernel/Consistency.lean | 138 +++++++- docs/kernel-verification.md | 46 ++- docs/theory.md | 9 +- 11 files changed, 854 insertions(+), 89 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/InferenceCache.lean create mode 100644 Ix/Kernel/Verify/Consistency/SortCache.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 74022d49c..f7e00969d 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -13,6 +13,8 @@ import Ix.Kernel.Verify.Consistency.Atomic import Ix.Kernel.Verify.Consistency.ScopedExpr import Ix.Kernel.Verify.Consistency.ScopedInstUniv import Ix.Kernel.Verify.Consistency.ScopedConstant +import Ix.Kernel.Verify.Consistency.InferenceCache +import Ix.Kernel.Verify.Consistency.SortCache import Ix.Kernel.Verify.Consistency.ConstantCache import Ix.Kernel.Verify.Consistency.Context import Ix.Kernel.Verify.Consistency.BinderOpening @@ -39,14 +41,20 @@ The binder case also requires explicit syntactic scope and references to the preceding interface. Its separate declared-type inference turns semantic checking into typing. Local cache hits agree with the actual declaration type. Constant hits agree with pure universe substitution of a loaded, admitted declaration; -the other inference nodes retain cache-miss boundaries. +sort hits return the canonical successor sort. Application, forall, and lambda +nodes retain misses in every eligible cache partition. Full mode leaves the +inference-only partition unconstrained at a miss. Applications use syntactic Pi exposure, full argument checking, hash conversion, and arguments without eager-reduction markers. Constant- and local-headed spines derive type validity from the admitted model or local context; their arguments may be lambdas. Polymorphic nodes use closed source readings, finite substitution resources, and a pure prediction of the returned syntax with matching occurrence annotations. -Cache hits additionally check arity because they skip the runtime guard. Exact -cache selection and successful constant writes are proved; general preservation -of cache agreement across checker operations remains an explicit obligation. +Constant hits additionally check arity because they skip the runtime guard. +Concrete cache agreement is preserved by sort and already-loaded constant +inference. Cache frames compose through interning, key computation, binder +opening, unrelated writes, and scope/policy cleanup, including errors. +These frames transport closed constant witnesses; maintained agreement also +constructs sort leaves. Initial agreement, finite execution resources, lazy +loading, and preservation through composite inference remain explicit obligations. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Atomic.lean b/Ix/Kernel/Verify/Consistency/Atomic.lean index e17b55c20..ebc75a988 100644 --- a/Ix/Kernel/Verify/Consistency/Atomic.lean +++ b/Ix/Kernel/Verify/Consistency/Atomic.lean @@ -20,14 +20,14 @@ open Theory Theory.Model universe u v -/-- The two inference-cache partitions miss at the actual key computed by -production. Both misses are required, so this applies in either policy mode. -/ +/-- Every eligible inference-cache partition misses at the actual production +key. Full mode does not inspect or constrain the inference-only partition. -/ structure UncachedInference (before : TcState .anon) (term : KExpr .anon) where key : Address × Address keyed : TcState .anon keyRun : TcM.inferKey term before = .ok key keyed fullMiss : keyed.env.inferCache[key]? = none - onlyMiss : keyed.env.inferOnlyCache[key]? = none + onlyMiss : before.inferOnly = true → keyed.env.inferOnlyCache[key]? = none /-- Recover the uncached execution and the exact final cache write from a successful miss. The policy is read before production computes the key. -/ @@ -73,7 +73,7 @@ theorem infer_uncached_success_state {term type : KExpr .anon} rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) miss.keyed = .ok miss.keyed miss.keyed from rfl] at accepted simp only at accepted - rw [miss.onlyMiss] at accepted + rw [miss.onlyMiss policy] at accepted change EStateM.bind (RecM.inferUncached RecM.inferCall true term methods) _ miss.keyed = _ at accepted cases run : RecM.inferUncached RecM.inferCall true term methods miss.keyed with diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index e0f399783..18977e082 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -38,7 +38,8 @@ private def atomicRoots : Array Lean.Name := #[ ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound, ``inferUncached_fvar_sound, ``infer_fvar_sound, ``FVarInferenceSupport.output, ``FVarInferenceSupport.sound, - ``InferenceCacheHit.run, + ``InferenceCacheHit.run, ``infer_sort_cached_sound, + ``infer_sort_cache_agreement, ``infer_sort_cache_frame, ``BinderInference.sortOfAgreement, ``ForallInferenceTrace.output, ``LambdaInferenceTrace.output, ``BinderInference.sound, ``inferUncached_monomorphic_const_scoped, ``ApplicationInferenceTrace.output, ``BinderInference.soundWithSynthesis, ``BinderInference.synthesis, @@ -58,7 +59,30 @@ private def instantiationRoots : Array Lean.Name := #[ ``inferUncached_const_scoped_refinement, ``inferUncached_const_scoped_sound, ``inferUncached_const_predicted_type, ``infer_const_scoped_annotated, ``infer_const_cache_write, ``CachedConstantInferenceSupport.refinement, - ``CachedConstantInferenceSupport.sound + ``CachedConstantInferenceSupport.sound, + ``instantiateUnivParams_cache_frame, ``infer_const_cache_frame, + ``infer_const_cache_agreement, ``CachedConstantInferenceSupport.transport, + ``CachedConstantInferenceSupport.openBinder, ``CachedConstantInferenceSupport.sound_after_frame +] + +private def cacheFrameRoots : Array Lean.Name := #[ + ``InferenceCacheFrame.refl, ``InferenceCacheFrame.trans, ``InferenceCacheAgreement.frame, + ``cacheInferResult_eq, ``PreservesInferenceCache.pure, ``PreservesInferenceCache.bind, + ``PreservesInferenceCache.runIntern, ``InferenceCacheFrame.localContext, + ``InferenceCacheAgreement.policy, ``withInferOnly_eq, + ``PreservesInferenceCache.withInferOnly, ``getConst_loaded +] + +private def cacheMapRoots : Array Lean.Name := #[ + ``InferenceCacheAgreement.write, ``PreservesInferenceCache.write_other, + ``InferenceCacheAgreement.clearReductionCaches +] + +private def cacheKeyRoots : Array Lean.Name := #[ + ``inferKey_closed, ``InferenceCacheHit.key_closed, ``observeInferenceCache, + ``InferenceCacheAgreement.selected, ``InferenceCacheHit.transport, + ``PreservesInferenceCache.inferKey, ``PreservesInferenceCache.openBinder, + ``withLctxScope_eq, ``PreservesInferenceCache.withLctxScope ] private def productionRoots : Array Lean.Name := #[ @@ -153,11 +177,11 @@ def roots : Array RootAllowance := #[ { root := ``Theory.Model.CheckingClaim.typing, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.typingSort, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.lam, standardAxioms := standard } -] ++ scopedRoots.map (fun root => { +] ++ (scopedRoots ++ cacheFrameRoots).map (fun root => { root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction -}) ++ contextRoots.map (fun root => { +}) ++ (contextRoots ++ cacheMapRoots).map (fun root => { root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction -}) ++ binderWalkerRoots.map (fun root => { +}) ++ (binderWalkerRoots ++ cacheKeyRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative], forbiddenDependencies := forbiddenProduction }) ++ (atomicRoots ++ instantiationRoots).map (fun root => { diff --git a/Ix/Kernel/Verify/Consistency/BinderInference.lean b/Ix/Kernel/Verify/Consistency/BinderInference.lean index c0950986e..7d503b5f1 100644 --- a/Ix/Kernel/Verify/Consistency/BinderInference.lean +++ b/Ix/Kernel/Verify/Consistency/BinderInference.lean @@ -5,6 +5,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.ConstantCache +import Ix.Kernel.Verify.Consistency.SortCache import Ix.Theory.Model.Checking /-! @@ -59,29 +60,6 @@ theorem inferUncached_monomorphic_const_scoped {β : Type u} cases accepted exact lookup concrete _ got -private theorem withLctxScope_eq (action : RecM .anon α) - (methods : Methods .anon) (before : TcState .anon) : - (RecM.withLctxScope action).run methods before = - match action.run methods before with - | .ok value after => - .ok value {after with lctx := after.lctx.truncate before.lctx.size} - | .error err after => - .error err {after with lctx := after.lctx.truncate before.lctx.size} := by - unfold RecM.withLctxScope - rw [ReaderT.run_bind] - change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ - unfold EStateM.bind - rw [show (get : TcM .anon (TcState .anon)) before = .ok before before from rfl] - simp only - unfold tryFinally - change EStateM.map (fun pair : α × PUnit => pair.1) - (tryFinally' (action.run methods) (fun _ => - (modify (fun after : TcState .anon => - {after with lctx := after.lctx.truncate before.lctx.size}) : - TcM .anon PUnit))) before = _ - unfold EStateM.map MonadFinally.tryFinally' EStateM.instMonadFinally - cases run : action.run methods before <;> simp only [run] <;> rfl - private theorem withLctxScope_success {action : RecM .anon α} {methods : Methods .anon} {before after : TcState .anon} {result : α} (accepted : (RecM.withLctxScope action).run methods before = .ok result after) : @@ -214,6 +192,11 @@ inductive BinderInference {β : Type u} miss.keyed.env.intern.ExprSupport term ∨ term = KExpr.mkSort (KUniv.mkSucc level)) : BinderInference resolve entries locals context fuel before (.sort level info) (.sort (readLevel level)) (.sort (.succ (readLevel level))) + | cachedSort {locals context fuel before level info} + (hit : InferenceCacheHit before (.sort level info)) + (canonical : hit.cached = KExpr.mkSort (KUniv.mkSucc level)) : + BinderInference resolve entries locals context fuel before (.sort level info) + (.sort (readLevel level)) (.sort (.succ (readLevel level))) | fvar {locals context fuel before id name info index A} (cache : FVarInferenceSupport before id name info) (registered : localIndex? locals id = some index) @@ -300,6 +283,28 @@ inductive BinderInference {β : Type u} BinderInference resolve entries locals context (fuel + 1) before (.lam name bi domain body info) (.lam condition A b) (.forallE condition A B) +/-- Construct the sort leaf from a maintained cache invariant. The production +key and eligible hit/miss observation are derived, including when only the +ignored partition is populated in full mode. -/ +def BinderInference.sortOfAgreement {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {fuel : Nat} + {before : TcState .anon} {level : KUniv .anon} {info : ExprInfo .anon} + (closed : (KExpr.sort level info).lbr = 0) + (agreement : InferenceCacheAgreement before ((KExpr.sort level info).addr, emptyCtxAddr) + (KExpr.mkSort (KUniv.mkSucc level))) + (coherent : before.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun term => before.env.intern.ExprSupport term ∨ + term = KExpr.mkSort (KUniv.mkSucc level)) : + BinderInference resolve entries locals context fuel before (.sort level info) + (.sort (readLevel level)) (.sort (.succ (readLevel level))) := by + rcases observeInferenceCache (inferKey_closed closed before) with + ⟨hit, keyEq, stateEq⟩ | ⟨miss, _, stateEq⟩ + · refine .cachedSort hit (InferenceCacheAgreement.selected hit ?_) + simpa only [keyEq, stateEq] using agreement + · exact .sort miss (by simpa only [stateEq] using coherent) + (by simpa only [stateEq] using faithful) + /-- Successful production inference reads the expected model type and checks the actual source term against it. No recursive semantic premise is supplied by the caller: induction follows the finite operational support tree. -/ @@ -324,6 +329,9 @@ theorem BinderInference.soundWithSynthesis {β : Type u} refine ⟨?_, (TypingClaim.sort _).checking, fun head => by cases head⟩ rw [internExpr_readScopedExpr? coherent faithful] simp [AExpr.erase] + | cachedSort hit canonical => + obtain ⟨typeReads, typed⟩ := infer_sort_cached_sound hit canonical accepted + exact ⟨typeReads, typed.checking, fun head => by cases head⟩ | fvar cache registered atIndex => obtain ⟨typeReads, typed⟩ := cache.sound agreement registered atIndex accepted exact ⟨typeReads, typed.checking, fun _ => typed⟩ diff --git a/Ix/Kernel/Verify/Consistency/ConstantCache.lean b/Ix/Kernel/Verify/Consistency/ConstantCache.lean index 728b72934..0b4a7e80d 100644 --- a/Ix/Kernel/Verify/Consistency/ConstantCache.lean +++ b/Ix/Kernel/Verify/Consistency/ConstantCache.lean @@ -4,6 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.ScopedConstant +import Ix.Kernel.Verify.Consistency.InferenceCache /-! # Constant inference cache hits @@ -12,7 +13,10 @@ Production cache selection gives full checking priority and consults the inference-only partition only under that policy. A selected constant result must equal pure universe substitution of its current loaded declaration. The admitted entry then supplies typing; no semantic cache invariant is an -input. These witnesses check individual entries, not global cache maintenance. +input. Structural frames transport these witnesses through operations that +retain the watched entries and loaded declarations. Inference of an already +loaded constant preserves concrete agreement at its key and frames other keys; +lazy loading and general recursive inference need further preservation proofs. -/ namespace Ix.Kernel.Consistency @@ -21,39 +25,104 @@ open Theory Theory.Model universe u v -/-- The exact cache entry eligible at production's computed inference key. -An inference-only result cannot witness a full-mode hit or override a full -result. No declaration lookup or recursive inference is performed on a hit. -/ -structure InferenceCacheHit (before : TcState .anon) (term : KExpr .anon) where - key : Address × Address - keyed : TcState .anon - cached : KExpr .anon - keyRun : TcM.inferKey term before = .ok key keyed - selected : keyed.env.inferCache[key]? = some cached ∨ - (keyed.env.inferCache[key]? = none ∧ before.inferOnly = true ∧ - keyed.env.inferOnlyCache[key]? = some cached) - -/-- Cache selection determines both the returned type and state, without -executing the uncached branch or rewriting either cache partition. -/ -theorem InferenceCacheHit.run {before : TcState .anon} {term : KExpr .anon} - (hit : InferenceCacheHit before term) (methods : Methods .anon) : - RecM.infer term methods before = .ok hit.cached hit.keyed := by - change (RecM.infer term).run methods before = _ - unfold RecM.infer RecM.inferWith - simp only [ReaderT.run_bind, ReaderT.run_monadLift] - change EStateM.bind (TcM.inferKey term) _ before = _ - rw [EStateM.bind, hit.keyRun] - change EStateM.bind (get : TcM .anon (TcState .anon)) _ hit.keyed = _ - rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) hit.keyed = - .ok hit.keyed hit.keyed from rfl] - rcases hit.selected with full | ⟨full, policy, only⟩ - · simp only [full]; rfl - · simp only [full, policy, if_true, ReaderT.run_bind] - change EStateM.bind (get : TcM .anon (TcState .anon)) _ hit.keyed = _ - rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) hit.keyed = - .ok hit.keyed hit.keyed from rfl] - simp only [only] +/-- Looking up an already loaded declaration does not invoke lazy loading +or change any checker state. -/ +theorem getConst_loaded {before : TcState .anon} {id : KId .anon} {concrete : KConst .anon} + (loaded : before.env.get? id = some concrete) : + TcM.getConst id before = .ok concrete before := by + have found : TcM.tryGetConst id before = .ok (some concrete) before := by + unfold TcM.tryGetConst + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] + simp only [loaded] rfl + unfold TcM.getConst + change EStateM.bind (TcM.tryGetConst id) _ before = _ + rw [EStateM.bind, found] + rfl + +/-- The verified universe walker changes only its intern table, preserving +both inference partitions and the loaded declarations at every key. -/ +theorem instantiateUnivParams_cache_frame {before after : TcState .anon} + {term result : KExpr .anon} {arguments : Array (KUniv .anon)} + (support : UniverseInstantiationSupport before term arguments) + (run : TcM.instantiateUnivParams term arguments before = .ok result after) + (key : Address × Address) : InferenceCacheFrame key before after := by + have post := TcM.instantiateUnivParams_wf support.faithful + (fun _ h => Or.inr h) ⟨support.coherent, fun _ h => Or.inl h⟩ + rw [run] at post + rw [post.2.2.1] + exact ⟨rfl, rfl, rfl⟩ + +/-- Inference of an already loaded constant frames all other cache keys, +including on a miss that runs universe substitution and writes a result. +Lazy loading needs its own preservation proof when the declaration is absent. -/ +theorem infer_const_cache_frame {before keyed after : TcState .anon} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {key other : Address × Address} {concrete : KConst .anon} + {methods : Methods .anon} {result : KExpr .anon} + (keyRun : TcM.inferKey (.const id arguments info) before = .ok key keyed) + (different : key ≠ other) + (loaded : keyed.env.get? id = some concrete) + (resources : UniverseInstantiationSupport keyed concrete.ty arguments) + (accepted : RecM.infer (.const id arguments info) methods before = .ok result after) : + InferenceCacheFrame other before after := by + have keyFrame := PreservesInferenceCache.inferKey other (.const id arguments info) before + rw [keyRun] at keyFrame + rcases observeInferenceCache keyRun with ⟨hit, _, stateEq⟩ | ⟨miss, keyEq, stateEq⟩ + · rw [hit.run methods] at accepted + cases accepted + simpa only [stateEq] using keyFrame + · obtain ⟨state, run, written⟩ := infer_uncached_success_state miss accepted + rw [stateEq] at run + obtain ⟨actual, foundState, got, _, instantiated⟩ := inferUncached_const_instantiation run + rw [getConst_loaded loaded] at got + cases got + have substitution := instantiateUnivParams_cache_frame resources instantiated other + have wrote : RecM.cacheInferResult before.inferOnly key result methods state = .ok () after := by + rw [cacheInferResult_eq] + rw [keyEq] at written + rw [written] + have tail := PreservesInferenceCache.write_other different before.inferOnly result methods state + rw [wrote] at tail + exact keyFrame.trans (substitution.trans tail) + +/-- A maintained agreement at a loaded constant's key survives its actual +inference. The pure substituted tree determines both cache writes and hits; +the two partition witnesses no longer need to be re-established afterward. -/ +theorem infer_const_cache_agreement {before keyed after : TcState .anon} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {key : Address × Address} {concrete : KConst .anon} {expected result : KExpr .anon} + {methods : Methods .anon} + (keyRun : TcM.inferKey (.const id arguments info) before = .ok key keyed) + (agreement : InferenceCacheAgreement keyed key expected) + (loaded : keyed.env.get? id = some concrete) + (resources : UniverseInstantiationSupport keyed concrete.ty arguments) + (prediction : KExpr.instantiateUnivParamsSpec concrete.ty arguments = .ok expected) + (accepted : RecM.infer (.const id arguments info) methods before = .ok result after) : + result = expected ∧ InferenceCacheAgreement after key expected := by + rcases observeInferenceCache keyRun with ⟨hit, keyEq, stateEq⟩ | ⟨miss, keyEq, stateEq⟩ + · rw [hit.run methods] at accepted + cases accepted + refine ⟨InferenceCacheAgreement.selected hit ?_, ?_⟩ + · simpa only [keyEq, stateEq] using agreement + · simpa only [stateEq] using agreement + · obtain ⟨state, run, written⟩ := infer_uncached_success_state miss accepted + rw [stateEq] at run + obtain ⟨actual, foundState, got, _, instantiated⟩ := inferUncached_const_instantiation run + rw [getConst_loaded loaded] at got + cases got + have post := TcM.instantiateUnivParams_wf resources.faithful + (fun _ h => Or.inr h) ⟨resources.coherent, fun _ h => Or.inl h⟩ + rw [instantiated] at post + have equal := Except.ok.inj (post.2.1.symm.trans prediction) + refine ⟨equal, ?_⟩ + have unchanged := agreement.frame (instantiateUnivParams_cache_frame resources instantiated key) + apply unchanged.write (policy := before.inferOnly) (methods := methods) + rw [cacheInferResult_eq] + rw [keyEq, equal] at written + rw [written] /-- A successful constant miss inserts the exact pure substituted type in the selected partition. This establishes the concrete substitution agreement @@ -103,6 +172,54 @@ structure CachedConstantInferenceSupport {β : Type u} prediction : readInstantiatedType? resolve concrete.ty arguments = some type.erase conditions : (entry.type.instL (arguments.toList.map readLevel)).annotations = type.annotations +/-- A preserved closed cache entry and unchanged loaded declarations carry +the complete constant witness into a later checker state. Only checking +policy matters for the eligibility of an inference-only hit. -/ +def CachedConstantInferenceSupport.transport {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {before after : TcState .anon} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + (support : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) + (closed : (KExpr.const id arguments info).lbr = 0) + (frame : InferenceCacheFrame ((KExpr.const id arguments info).addr, emptyCtxAddr) before after) + (policy : after.inferOnly = before.inferOnly) : + CachedConstantInferenceSupport resolve entries after id arguments info ref entry type := { + hit := support.hit.transport closed frame policy + concrete := support.concrete + loaded := by + change after.env.get? id = some support.concrete + have loaded := support.loaded + rw [(support.hit.key_closed closed).2] at loaded + simpa only [KEnv.get?, frame.constants] using loaded + resolved := support.resolved, found := support.found + count := support.count, arity := support.arity, scope := support.scope + reading := support.reading, levels := support.levels + substitution := support.substitution, prediction := support.prediction + conditions := support.conditions +} + +/-- Actual binder opening supplies the cache frame and policy equality. No +new lookup, substitution prediction, or cache-hit observation is supplied. -/ +def CachedConstantInferenceSupport.openBinder {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {before after : TcState .anon} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {domain body opened : KExpr .anon} {fresh : FVarId} + (support : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) + (closed : (KExpr.const id arguments info).lbr = 0) + (run : TcM.openBinder name bi domain body before = .ok (opened, fresh) after) : + CachedConstantInferenceSupport resolve entries after id arguments info ref entry type := + support.transport closed (by + have frame := PreservesInferenceCache.openBinder + ((KExpr.const id arguments info).addr, emptyCtxAddr) name bi domain body before + rw [run] at frame + exact frame) (by + rw [openBinder_eq] at run + split at run + · cases run; rfl + · contradiction) + /-- The pure prediction and concrete cache agreement derive the cached type's reading in every active context and its congruence with the admitted entry's instantiated type. Mutable interning resources are unnecessary. -/ @@ -147,4 +264,22 @@ theorem CachedConstantInferenceSupport.sound {β : Type u} obtain ⟨typeReads, same, arity⟩ := support.refinement locals exact ⟨typeReads, same.typing (TypingClaim.const support.found arity)⟩ +/-- Reuse the proved constant type after a sequence of operations whose +cache frames compose. The later hit observation and declaration agreement +are transported from the earlier witness. -/ +theorem CachedConstantInferenceSupport.sound_after_frame {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} + {before later after : TcState .anon} {id : KId .anon} {arguments : Array (KUniv .anon)} + {info : ExprInfo .anon} {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + {methods : Methods .anon} {result : KExpr .anon} + (support : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) + (closed : (KExpr.const id arguments info).lbr = 0) + (frame : InferenceCacheFrame ((KExpr.const id arguments info).addr, emptyCtxAddr) before later) + (policy : later.inferOnly = before.inferOnly) + (accepted : RecM.infer (.const id arguments info) methods later = .ok result after) : + readScopedExpr? resolve locals result = some type.erase ∧ + TypingClaim.{u,v} entries context (.const ref (arguments.toList.map readLevel)) type := + (support.transport closed frame policy).sound accepted + end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Context.lean b/Ix/Kernel/Verify/Consistency/Context.lean index 12f49aaaf..d79f61833 100644 --- a/Ix/Kernel/Verify/Consistency/Context.lean +++ b/Ix/Kernel/Verify/Consistency/Context.lean @@ -191,7 +191,8 @@ structure FVarInferenceSupport (before : TcState .anon) (id : FVarId) keyRun : TcM.inferKey (.fvar id name info) before = .ok key keyed fullMatches : ∀ cached decl, keyed.env.inferCache[key]? = some cached → keyed.lctx.find? id = some decl → cached = decl.ty - onlyMatches : ∀ cached decl, keyed.env.inferOnlyCache[key]? = some cached → + onlyMatches : before.inferOnly = true → + ∀ cached decl, keyed.env.inferOnlyCache[key]? = some cached → keyed.lctx.find? id = some decl → cached = decl.ty def FVarInferenceSupport.ofMiss {before : TcState .anon} {id : FVarId} @@ -255,7 +256,7 @@ theorem FVarInferenceSupport.output {before after : TcState .anon} {id : FVarId} | some cached => simp only [only] at accepted cases accepted - exact support.onlyMatches _ _ only found + exact support.onlyMatches policy _ _ only found | none => simp only [only] at accepted have lookup : RecM.inferUncached RecM.inferCall true (.fvar id name info) diff --git a/Ix/Kernel/Verify/Consistency/InferenceCache.lean b/Ix/Kernel/Verify/Consistency/InferenceCache.lean new file mode 100644 index 000000000..5f62028d0 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/InferenceCache.lean @@ -0,0 +1,323 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.BinderOpening + +/-! +# Structural inference-cache invariants + +Agreement records concrete types in both cache partitions. Frame lemmas +preserve the entries at a fixed key and the loaded constants through actual +checker operations. Scope changes and unrelated cache writes do not require +a new semantic typing premise for each cached answer. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u + +/-- Closed source expressions use one key in every local context. Computing +that key leaves the entire checker state unchanged. -/ +theorem inferKey_closed {term : KExpr .anon} (closed : term.lbr = 0) + (before : TcState .anon) : + TcM.inferKey term before = .ok (term.addr, emptyCtxAddr) before := by + unfold TcM.inferKey + change EStateM.bind (TcM.ctxAddrForLbr term.lbr) _ before = _ + rw [closed] + rfl + +/-- The exact cache entry eligible at production's computed inference key. +An inference-only result cannot override a full result or serve full mode. -/ +structure InferenceCacheHit (before : TcState .anon) (term : KExpr .anon) where + key : Address × Address + keyed : TcState .anon + cached : KExpr .anon + keyRun : TcM.inferKey term before = .ok key keyed + selected : keyed.env.inferCache[key]? = some cached ∨ + (keyed.env.inferCache[key]? = none ∧ before.inferOnly = true ∧ + keyed.env.inferOnlyCache[key]? = some cached) + +/-- Cache selection determines both the returned type and state. -/ +theorem InferenceCacheHit.run {before : TcState .anon} {term : KExpr .anon} + (hit : InferenceCacheHit before term) (methods : Methods .anon) : + RecM.infer term methods before = .ok hit.cached hit.keyed := by + change (RecM.infer term).run methods before = _ + unfold RecM.infer RecM.inferWith + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.inferKey term) _ before = _ + rw [EStateM.bind, hit.keyRun] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ hit.keyed = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) hit.keyed = + .ok hit.keyed hit.keyed from rfl] + rcases hit.selected with full | ⟨full, policy, only⟩ + · simp only [full]; rfl + · simp only [full, policy, if_true, ReaderT.run_bind] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ hit.keyed = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) hit.keyed = + .ok hit.keyed hit.keyed from rfl] + simp only [only] + rfl + +theorem InferenceCacheHit.key_closed {before : TcState .anon} {term : KExpr .anon} + (hit : InferenceCacheHit before term) (closed : term.lbr = 0) : + hit.key = (term.addr, emptyCtxAddr) ∧ hit.keyed = before := by + have run := hit.keyRun + rw [inferKey_closed closed] at run + exact ⟨(EStateM.Result.ok.inj run).1.symm, (EStateM.Result.ok.inj run).2.symm⟩ + +/-- Inspect the two concrete maps under production's policy and construct +the corresponding hit or miss witness at the supplied actual key. -/ +def observeInferenceCache {before keyed : TcState .anon} {term : KExpr .anon} + {key : Address × Address} (keyRun : TcM.inferKey term before = .ok key keyed) : + {hit : InferenceCacheHit before term // hit.key = key ∧ hit.keyed = keyed} ⊕ + {miss : UncachedInference before term // miss.key = key ∧ miss.keyed = keyed} := by + cases full : keyed.env.inferCache[key]? with + | some cached => + exact .inl ⟨⟨key, keyed, cached, keyRun, .inl full⟩, rfl, rfl⟩ + | none => + by_cases policy : before.inferOnly = true + · cases only : keyed.env.inferOnlyCache[key]? with + | some cached => + exact .inl ⟨⟨key, keyed, cached, keyRun, .inr ⟨full, policy, only⟩⟩, rfl, rfl⟩ + | none => exact .inr ⟨⟨key, keyed, keyRun, full, fun _ => only⟩, rfl, rfl⟩ + · exact .inr ⟨⟨key, keyed, keyRun, full, fun active => False.elim (policy active)⟩, rfl, rfl⟩ + +/-- Any populated entry at this key is the specified concrete type. Both +partitions are covered so agreement survives a change in checking policy. -/ +structure InferenceCacheAgreement (before : TcState .anon) + (key : Address × Address) (type : KExpr .anon) : Prop where + full : ∀ cached, before.env.inferCache[key]? = some cached → cached = type + only : ∀ cached, before.env.inferOnlyCache[key]? = some cached → cached = type + +/-- Relevant data retained by an operation: the two entries at one key and +the loaded declarations. Other keys and checker fields may change. -/ +structure InferenceCacheFrame (key : Address × Address) + (before after : TcState .anon) : Prop where + full : after.env.inferCache[key]? = before.env.inferCache[key]? + only : after.env.inferOnlyCache[key]? = before.env.inferOnlyCache[key]? + constants : after.env.consts = before.env.consts + +theorem InferenceCacheFrame.refl (key : Address × Address) (state : TcState .anon) : + InferenceCacheFrame key state state := ⟨rfl, rfl, rfl⟩ + +theorem InferenceCacheFrame.trans {key : Address × Address} + {before middle after : TcState .anon} + (first : InferenceCacheFrame key before middle) + (second : InferenceCacheFrame key middle after) : + InferenceCacheFrame key before after := + ⟨second.full.trans first.full, second.only.trans first.only, + second.constants.trans first.constants⟩ + +theorem InferenceCacheAgreement.frame {key : Address × Address} {type : KExpr .anon} + {before after : TcState .anon} (agreement : InferenceCacheAgreement before key type) + (frame : InferenceCacheFrame key before after) : InferenceCacheAgreement after key type := by + refine ⟨?_, ?_⟩ + · intro cached found; exact agreement.full cached (frame.full.symm.trans found) + · intro cached found; exact agreement.only cached (frame.only.symm.trans found) + +theorem InferenceCacheAgreement.selected {before : TcState .anon} {term : KExpr .anon} + {type : KExpr .anon} (hit : InferenceCacheHit before term) + (agreement : InferenceCacheAgreement hit.keyed hit.key type) : hit.cached = type := by + rcases hit.selected with full | ⟨_, _, only⟩ + · exact agreement.full _ full + · exact agreement.only _ only + +/-- Reuse a closed expression's selected hit after an operation preserving +its entries and checking policy. Its key and result are derived, not supplied +as another observation of inference. -/ +def InferenceCacheHit.transport {before after : TcState .anon} {term : KExpr .anon} + (hit : InferenceCacheHit before term) (closed : term.lbr = 0) + (frame : InferenceCacheFrame (term.addr, emptyCtxAddr) before after) + (policy : after.inferOnly = before.inferOnly) : InferenceCacheHit after term := { + key := (term.addr, emptyCtxAddr), keyed := after, cached := hit.cached + keyRun := inferKey_closed closed after + selected := by + obtain ⟨key, state⟩ := hit.key_closed closed + have selected := hit.selected + rw [key, state] at selected + rcases selected with full | ⟨full, onlyPolicy, only⟩ + · exact .inl (frame.full.trans full) + · exact .inr ⟨frame.full.trans full, policy.trans onlyPolicy, frame.only.trans only⟩ +} + +/-- The final write is an exact state update, with the policy captured at +entry rather than inferred from any intervening recursive call. -/ +theorem cacheInferResult_eq (policy : Bool) (key : Address × Address) + (type : KExpr .anon) (methods : Methods .anon) (before : TcState .anon) : + RecM.cacheInferResult policy key type methods before = .ok () + (if policy then {before with env := {before.env with + inferOnlyCache := before.env.inferOnlyCache.insert key type}} + else {before with env := {before.env with + inferCache := before.env.inferCache.insert key type}}) := by + cases policy <;> rfl + +/-- Writing a matching result preserves agreement at the written key. -/ +theorem InferenceCacheAgreement.write {before after : TcState .anon} + {key : Address × Address} {type : KExpr .anon} {policy : Bool} {methods : Methods .anon} + (agreement : InferenceCacheAgreement before key type) + (run : RecM.cacheInferResult policy key type methods before = .ok () after) : + InferenceCacheAgreement after key type := by + rw [cacheInferResult_eq] at run + cases policy <;> cases run + · refine ⟨?_, agreement.only⟩ + intro cached found + simpa using found.symm + · refine ⟨agreement.full, ?_⟩ + intro cached found + simpa using found.symm + +/-- Every outcome preserves the observed entries, including failure. -/ +def PreservesInferenceCache (key : Address × Address) (action : TcM .anon α) : Prop := + ∀ before, match action before with + | .ok _ after | .error _ after => InferenceCacheFrame key before after + +theorem PreservesInferenceCache.pure (key : Address × Address) (value : α) : + PreservesInferenceCache key (pure value) := fun before => .refl key before + +theorem PreservesInferenceCache.bind {key : Address × Address} + {action : TcM .anon α} {next : α → TcM .anon γ} + (first : PreservesInferenceCache key action) + (rest : ∀ value, PreservesInferenceCache key (next value)) : + PreservesInferenceCache key (action >>= next) := by + intro before + change (match EStateM.bind action next before with + | .ok _ after | .error _ after => InferenceCacheFrame key before after) + have initial := first before + cases run : action before with + | error err after => + rw [EStateM.bind, run] + simpa only [run] using initial + | ok value middle => + rw [run] at initial + rw [EStateM.bind, run] + simp only + have final := rest value middle + cases result : next value middle <;> rw [result] at final <;> exact initial.trans final + +theorem PreservesInferenceCache.runIntern (key : Address × Address) (action : InternM .anon α) : + PreservesInferenceCache key (TcM.runIntern action) := fun _ => ⟨rfl, rfl, rfl⟩ + +theorem PreservesInferenceCache.inferKey (key : Address × Address) (term : KExpr .anon) : + PreservesInferenceCache key (TcM.inferKey term) := by + intro before + cases run : TcM.inferKey term before + all_goals + unfold TcM.inferKey at run + change EStateM.bind (TcM.ctxAddrForLbr term.lbr) _ before = _ at run + unfold TcM.ctxAddrForLbr at run + change EStateM.bind (fun state => EStateM.bind (get : TcM .anon (TcState .anon)) + _ state) _ before = _ at run + simp only [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] at run + by_cases fast : (term.lbr == 0 || before.ctx.isEmpty) = true + · rw [if_pos fast] at run + cases run <;> exact ⟨rfl, rfl, rfl⟩ + · rw [if_neg fast] at run + cases cached : before.ctxAddrCache[(before.ctxId, term.lbr)]? <;> + rw [cached] at run <;> cases run <;> exact ⟨rfl, rfl, rfl⟩ + +theorem PreservesInferenceCache.openBinder (key : Address × Address) + (name : Mode.anon.F Name) (bi : Mode.anon.F Lean.BinderInfo) (type body : KExpr .anon) : + PreservesInferenceCache key (TcM.openBinder name bi type body) := by + intro before + rw [openBinder_eq] + by_cases room : before.env.nextFVarId.toNat + 1 < UInt64.size + · simp only [room, if_true]; exact ⟨rfl, rfl, rfl⟩ + · simp only [room, if_false]; exact ⟨rfl, rfl, rfl⟩ + +/-- An actual insertion at another key leaves this key's entries and loaded +declarations unchanged, for either validation policy. -/ +theorem PreservesInferenceCache.write_other {key other : Address × Address} + (different : other ≠ key) (policy : Bool) (type : KExpr .anon) (methods : Methods .anon) : + PreservesInferenceCache key (RecM.cacheInferResult policy other type methods) := by + intro before + rw [cacheInferResult_eq] + cases policy <;> refine ⟨?_, ?_, rfl⟩ <;> simp [Std.HashMap.getElem?_insert, different] + +/-- Exact scope cleanup on either outcome, retaining the body's other state +updates. Shared by inference inversion and cache-preservation proofs. -/ +theorem withLctxScope_eq (action : RecM .anon α) + (methods : Methods .anon) (before : TcState .anon) : + (RecM.withLctxScope action).run methods before = + match action.run methods before with + | .ok value after => + .ok value {after with lctx := after.lctx.truncate before.lctx.size} + | .error err after => + .error err {after with lctx := after.lctx.truncate before.lctx.size} := by + unfold RecM.withLctxScope + rw [ReaderT.run_bind] + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ + unfold EStateM.bind + rw [show (get : TcM .anon (TcState .anon)) before = .ok before before from rfl] + simp only + unfold tryFinally + change EStateM.map (fun pair : α × PUnit => pair.1) + (tryFinally' (action.run methods) (fun _ => + (modify (fun after : TcState .anon => + {after with lctx := after.lctx.truncate before.lctx.size}) : + TcM .anon PUnit))) before = _ + unfold EStateM.map MonadFinally.tryFinally' EStateM.instMonadFinally + cases run : action.run methods before <;> simp only [run] <;> rfl + +theorem PreservesInferenceCache.withLctxScope {key : Address × Address} + {action : RecM .anon α} {methods : Methods .anon} + (preserved : PreservesInferenceCache key (action.run methods)) : + PreservesInferenceCache key ((RecM.withLctxScope action).run methods) := by + intro before + rw [withLctxScope_eq] + have frame := preserved before + cases run : action.run methods before <;> rw [run] at frame <;> + exact ⟨frame.full, frame.only, frame.constants⟩ + +/-- Changing only local declarations never changes closed cache data. -/ +theorem InferenceCacheFrame.localContext (key : Address × Address) + (before : TcState .anon) (context : LocalContext .anon) : + InferenceCacheFrame key before {before with lctx := context} := ⟨rfl, rfl, rfl⟩ + +/-- Agreement itself is independent of the currently selected policy. -/ +theorem InferenceCacheAgreement.policy {before : TcState .anon} + {key : Address × Address} {type : KExpr .anon} + (agreement : InferenceCacheAgreement before key type) (policy : Bool) : + InferenceCacheAgreement {before with inferOnly := policy} key type := + ⟨agreement.full, agreement.only⟩ + +/-- Cache clearing establishes agreement vacuously, while retaining loaded +declarations for subsequent misses. -/ +theorem InferenceCacheAgreement.clearReductionCaches (before : TcState .anon) + (key : Address × Address) (type : KExpr .anon) : + InferenceCacheAgreement {before with env := before.env.clearReductionCaches} key type := by + constructor <;> intro cached found <;> simp [KEnv.clearReductionCaches] at found + +/-- Exact policy restoration, including after an error from the body. -/ +theorem withInferOnly_eq (action : TcM .anon α) (before : TcState .anon) : + TcM.withInferOnly action before = + match action {before with inferOnly := true} with + | .ok value after => .ok value {after with inferOnly := before.inferOnly} + | .error err after => .error err {after with inferOnly := before.inferOnly} := by + unfold TcM.withInferOnly + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] + unfold tryFinally + change EStateM.map (fun pair : α × PUnit => pair.1) + (tryFinally' action (fun _ => + (modify (fun after : TcState .anon => + {after with inferOnly := before.inferOnly}) : TcM .anon PUnit))) + {before with inferOnly := true} = _ + unfold EStateM.map MonadFinally.tryFinally' EStateM.instMonadFinally + cases run : action {before with inferOnly := true} <;> simp only [run] <;> rfl + +theorem PreservesInferenceCache.withInferOnly {key : Address × Address} {action : TcM .anon α} + (preserved : PreservesInferenceCache key action) : + PreservesInferenceCache key (TcM.withInferOnly action) := by + intro before + rw [withInferOnly_eq] + have frame := preserved {before with inferOnly := true} + cases run : action {before with inferOnly := true} <;> rw [run] at frame <;> + exact ⟨frame.full, frame.only, frame.constants⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/SortCache.lean b/Ix/Kernel/Verify/Consistency/SortCache.lean new file mode 100644 index 000000000..9119c9da3 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/SortCache.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.InferenceCache + +/-! +# Sort inference and cache preservation + +The canonical type of `Sort u` is the production tree for `Sort (succ u)`. +Concrete cache agreement derives both typing and its own preservation through +the actual inference call. Other cache keys and loaded declarations are framed. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +/-- Cached sorts synthesize their canonical type under any active locals. +No intern-table resources are needed when the selected result is cached. -/ +theorem infer_sort_cached_sound {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} + {before after : TcState .anon} {level : KUniv .anon} {info : ExprInfo .anon} + {methods : Methods .anon} {result : KExpr .anon} + (hit : InferenceCacheHit before (.sort level info)) + (canonical : hit.cached = KExpr.mkSort (KUniv.mkSucc level)) + (accepted : RecM.infer (.sort level info) methods before = .ok result after) : + readScopedExpr? resolve locals result = some (.sort (.succ (readLevel level))) ∧ + TypingClaim.{u,v} entries context (.sort (readLevel level)) (.sort (.succ (readLevel level))) := by + rw [hit.run methods] at accepted + cases accepted + rw [canonical] + exact ⟨by simp, TypingClaim.sort _⟩ + +/-- Both policies return the exact canonical sort tree and retain agreement +at its key. The miss branch establishes this through interning and the real +cache write; the hit branch reads it from the maintained invariant. -/ +theorem infer_sort_cache_agreement {before keyed after : TcState .anon} + {level : KUniv .anon} {info : ExprInfo .anon} {key : Address × Address} + {methods : Methods .anon} {result : KExpr .anon} + (keyRun : TcM.inferKey (.sort level info) before = .ok key keyed) + (agreement : InferenceCacheAgreement keyed key (KExpr.mkSort (KUniv.mkSucc level))) + (coherent : keyed.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun term => keyed.env.intern.ExprSupport term ∨ + term = KExpr.mkSort (KUniv.mkSucc level)) + (accepted : RecM.infer (.sort level info) methods before = .ok result after) : + result = KExpr.mkSort (KUniv.mkSucc level) ∧ + InferenceCacheAgreement after key (KExpr.mkSort (KUniv.mkSucc level)) := by + rcases observeInferenceCache keyRun with ⟨hit, keyEq, stateEq⟩ | ⟨miss, keyEq, stateEq⟩ + · rw [hit.run methods] at accepted + cases accepted + refine ⟨InferenceCacheAgreement.selected hit ?_, ?_⟩ + · simpa only [keyEq, stateEq] using agreement + · simpa only [stateEq] using agreement + · obtain ⟨state, run, written⟩ := infer_uncached_success_state miss accepted + rw [stateEq] at run + change EStateM.Result.ok + (keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).1 + {keyed with env := {keyed.env with intern := + (keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).2}} = + .ok result state at run + cases run + have canonical := keyed.env.intern.internExpr_eraseMeta coherent faithful + simp only [KExpr.eraseMeta_anon] at canonical + refine ⟨canonical, ?_⟩ + have unchanged : InferenceCacheAgreement + {keyed with env := {keyed.env with intern := + (keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).2}} + key (KExpr.mkSort (KUniv.mkSucc level)) := ⟨agreement.full, agreement.only⟩ + apply unchanged.write (policy := before.inferOnly) (methods := methods) + rw [cacheInferResult_eq] + rw [keyEq, canonical] at written + rw [written] + +/-- A successful sort call preserves every other cache key and all loaded +declarations. This frame is operational and needs no typing or cache +agreement premise, even when the call writes a new result at its own key. -/ +theorem infer_sort_cache_frame {before keyed after : TcState .anon} + {level : KUniv .anon} {info : ExprInfo .anon} {key other : Address × Address} + {methods : Methods .anon} {result : KExpr .anon} + (keyRun : TcM.inferKey (.sort level info) before = .ok key keyed) + (different : key ≠ other) + (accepted : RecM.infer (.sort level info) methods before = .ok result after) : + InferenceCacheFrame other before after := by + have keyFrame := PreservesInferenceCache.inferKey other (.sort level info) before + rw [keyRun] at keyFrame + rcases observeInferenceCache keyRun with ⟨hit, keyEq, stateEq⟩ | ⟨miss, keyEq, stateEq⟩ + · rw [hit.run methods] at accepted + cases accepted + simpa only [stateEq] using keyFrame + · obtain ⟨state, run, written⟩ := infer_uncached_success_state miss accepted + rw [stateEq] at run + change EStateM.Result.ok + (keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).1 + {keyed with env := {keyed.env with intern := + (keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).2}} = + .ok result state at run + cases run + apply keyFrame.trans + rw [keyEq] at written + rw [written] + cases policy : before.inferOnly <;> + refine ⟨?_, ?_, rfl⟩ <;> simp [Std.HashMap.getElem?_insert, different] + +end Ix.Kernel.Consistency diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index c293e6a66..4d49329b4 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -512,9 +512,9 @@ private def repeatedReferenceEnvironment : Ixon.Env := Id.run do /-- The selected entry is populated by real inference, then reused in two different local scopes. Cache keys and closed returned types stay stable. -/ -private def cachedConstantAcrossScopes (source : Ixon.Env × Address) - (arguments : Array (KUniv .anon)) (expected : KExpr .anon) (inferOnly : Bool) : Bool := - let term := KExpr.mkConst (m := .anon) ⟨source.2, ()⟩ arguments +private def cachedInferenceAcrossScopes (term expected : KExpr .anon) + (state : TcState .anon) : Bool := + let inferOnly := state.inferOnly let propType := KExpr.mkSort (m := .anon) .mkZero let action : RecM .anon Bool := do let first ← RecM.inferCall term @@ -534,15 +534,20 @@ private def cachedConstantAcrossScopes (source : Ixon.Env × Address) final.env.inferOnlyCache.size == initial.env.inferOnlyCache.size && final.env.inferCache.isEmpty else initial.env.inferCache[key]?.isSome && final.env.inferCache.size == initial.env.inferCache.size && final.env.inferOnlyCache.isEmpty) - match TcM.runRec action { TcState.newLazyAnon source.1 with inferOnly } with + match TcM.runRec action state with | .ok passed after => passed && after.lctx.size == 0 && after.env.nextFVarId == 2 | .error _ _ => false +private def cachedConstantAcrossScopes (source : Ixon.Env × Address) + (arguments : Array (KUniv .anon)) (expected : KExpr .anon) (inferOnly : Bool) : Bool := + cachedInferenceAcrossScopes (.mkConst ⟨source.2, ()⟩ arguments) expected + { TcState.newLazyAnon source.1 with inferOnly } + /-- A deliberately different result in the ineligible partition makes the selection policy observable. Full mode must compute a checked answer when only that entry exists; inference-only mode must prefer a full result. -/ -private def constantCachePriority (fullHit : Bool) : Bool := - let term := KExpr.mkConst (m := .anon) ⟨polymorphicIdentity.2, ()⟩ #[levelOne] +private def inferenceCachePriority (term knownType : KExpr .anon) + (initial : TcState .anon) (fullHit : Bool) : Bool := let sentinel := KExpr.mkSort (m := .anon) .mkZero let action : RecM .anon Bool := do let expected ← RecM.inferOnlyCall term @@ -552,13 +557,17 @@ private def constantCachePriority (fullHit : Bool) : Bool := inferOnlyCache := state.env.inferOnlyCache.insert key sentinel } } let result ← RecM.inferCall term let state ← get - return result.addr == identityType.addr && result.addr != sentinel.addr && + return result.addr == knownType.addr && result.addr != sentinel.addr && state.env.inferCache[key]?.any (fun cached => cached.addr == expected.addr) && state.env.inferOnlyCache[key]?.any (fun cached => cached.addr == sentinel.addr) - match TcM.runRec action (TcState.newLazyAnon polymorphicIdentity.1) with + match TcM.runRec action initial with | .ok passed _ => passed | .error _ _ => false +private def constantCachePriority (fullHit : Bool) : Bool := + inferenceCachePriority (.mkConst ⟨polymorphicIdentity.2, ()⟩ #[levelOne]) identityType + (TcState.newLazyAnon polymorphicIdentity.1) fullHit + /-- Alternating two instances after their first use must retrieve the type for that instance, while retaining only two closed constant cache entries. -/ private def repeatedConstantInstances : Bool := @@ -603,8 +612,119 @@ private def constantCacheCases : TestSeq := ++ test "constant cache: alternating universe instances retrieve their own cached types" repeatedConstantInstances +/-- Repeated `Sort u` domains in both the declaration and its value exercise +sort hits under fresh local scopes: `fun P Q p q => p`, at Prop and Type. -/ +private def repeatedSortEnvironment : Ixon.Env := Id.run do + let definition : Ixon.Univ → Ix.DefKind → Ixon.Constant := fun level kind => + ⟨.defn ⟨kind, .safe, 0, + .leanAll (.sort 0) (.leanAll (.sort 0) + (.leanAll (.var 1) (.leanAll (.var 1) (.var 3)))), + .leanLam (.sort 0) (.leanLam (.sort 0) + (.leanLam (.var 1) (.leanLam (.var 1) (.var 1))))⟩, #[], #[], #[level]⟩ + let (env, _) := storeConst {} (definition .zero .defn) + let (env, _) := storeConst env (definition (.succ .zero) .opaq) + return env + +/-- Warm a constant, then infer a sort and another instance of the loaded +constant inside a scope. Both successful cleanup and an error from an +inference-only call retain the original entry and the intervening writes. -/ +private def constantCacheThroughInference (inferOnly fail : Bool) : Bool := + let id : KId .anon := ⟨polymorphicIdentity.2, ()⟩ + let term := KExpr.mkConst (m := .anon) id #[levelOne] + let other := KExpr.mkConst (m := .anon) id #[.mkZero] + let propType := KExpr.mkSort (m := .anon) .mkZero + let propIdentity := KExpr.mkAll () () propType (.mkAll () () (.mkVar 0 ()) (.mkVar 1 ())) + let action : RecM .anon Bool := do + let first ← RecM.inferCall term + let key ← TcM.inferKey term + let otherKey ← TcM.inferKey other + let sortKey ← TcM.inferKey propType + let initial ← get + let expectedExit ← try + RecM.withLctxScope do + let _ ← TcM.openBinder () () propType (.mkVar 0 ()) + let _ ← RecM.inferCall propType + let _ ← RecM.inferCall other + if fail then + let _ ← RecM.inferOnlyCall (.mkFVar ⟨99⟩ ()) + return false + return true + catch _ => pure fail + let later ← get + let cache := if inferOnly then later.env.inferOnlyCache else later.env.inferCache + let opposite := if inferOnly then later.env.inferCache else later.env.inferOnlyCache + let reused ← RecM.inferCall term + return expectedExit && first.addr == identityType.addr && reused.addr == first.addr && + key != otherKey && key != sortKey && otherKey != sortKey && + cache[key]?.any (fun cached => cached.addr == first.addr) && + cache[otherKey]?.any (fun cached => cached.addr == propIdentity.addr) && + cache[sortKey]?.any (fun cached => cached.addr == (.mkSort levelOne : KExpr .anon).addr) && + opposite.isEmpty && later.env.consts.size == initial.env.consts.size && + (later.env.get? id).map (·.ty.addr) == (initial.env.get? id).map (·.ty.addr) && + later.lctx.size == 0 && later.env.nextFVarId == 1 && later.inferOnly == inferOnly + match TcM.runRec action { TcState.newLazyAnon polymorphicIdentity.1 with inferOnly } with + | .ok passed _ => passed + | .error _ _ => false + +/-- Populate both partitions, clear them through the production operation, +then re-infer with a loaded source under the selected policy. -/ +private def inferenceAfterClearing (inferOnly : Bool) : Bool := + let id : KId .anon := ⟨polymorphicIdentity.2, ()⟩ + let term := KExpr.mkConst (m := .anon) id #[levelOne] + let propType := KExpr.mkSort (m := .anon) .mkZero + let action : RecM .anon Bool := do + let _ ← RecM.inferOnlyCall term + let _ ← RecM.inferCall term + let _ ← RecM.inferOnlyCall propType + let _ ← RecM.inferCall propType + let key ← TcM.inferKey term + let sortKey ← TcM.inferKey propType + let populated ← get + modify fun state => { state with inferOnly, env := state.env.clearReductionCaches } + let cleared ← get + let constantResult ← RecM.inferCall term + let sortResult ← RecM.inferCall propType + let final ← get + let cache := if inferOnly then final.env.inferOnlyCache else final.env.inferCache + let opposite := if inferOnly then final.env.inferCache else final.env.inferOnlyCache + return populated.env.inferCache.size == 2 && populated.env.inferOnlyCache.size == 2 && + cleared.env.inferCache.isEmpty && cleared.env.inferOnlyCache.isEmpty && + (cleared.env.get? id).isSome && cleared.env.consts.size == populated.env.consts.size && + constantResult.addr == identityType.addr && sortResult.addr == (.mkSort levelOne : KExpr .anon).addr && + cache[key]?.isSome && cache[sortKey]?.isSome && cache.size == 2 && opposite.isEmpty + match TcM.runRec action (TcState.newLazyAnon polymorphicIdentity.1) with + | .ok passed _ => passed + | .error _ _ => false + +private def cacheInvariantCases : TestSeq := + test "cache invariants: repeated sort domains check with persistent caches" + (allSucceeded repeatedSortEnvironment 2 { clearEvery := 0 }) + ++ test "cache invariants: repeated sort domains check with per-item clearing" + (allSucceeded repeatedSortEnvironment 2 { clearEvery := 1 }) + ++ test "cache invariants: full sort results survive two fresh scopes" + (cachedInferenceAcrossScopes (.mkSort .mkZero) (.mkSort levelOne) (TcState.ofEnvAnon {})) + ++ test "cache invariants: inference-only sort results survive two fresh scopes" + (cachedInferenceAcrossScopes (.mkSort .mkZero) (.mkSort levelOne) + { TcState.ofEnvAnon {} with inferOnly := true }) + ++ test "cache invariants: sort inference gives the full result priority" + (inferenceCachePriority (.mkSort .mkZero) (.mkSort levelOne) (TcState.ofEnvAnon {}) true) + ++ test "cache invariants: full sort inference ignores the inference-only entry" + (inferenceCachePriority (.mkSort .mkZero) (.mkSort levelOne) (TcState.ofEnvAnon {}) false) + ++ test "cache invariants: full entries survive other inference and scope cleanup" + (constantCacheThroughInference false false) + ++ test "cache invariants: inference-only entries survive other inference and scope cleanup" + (constantCacheThroughInference true false) + ++ test "cache invariants: full entries and policy survive failed inference-only scope" + (constantCacheThroughInference false true) + ++ test "cache invariants: inference-only entries and policy survive failed scope" + (constantCacheThroughInference true true) + ++ test "cache invariants: clearing both partitions permits fresh full inference" + (inferenceAfterClearing false) + ++ test "cache invariants: clearing both partitions permits fresh inference-only synthesis" + (inferenceAfterClearing true) + public def suite : List TestSeq := [cases, polymorphicCases, specializationCases, binderCases, applicationCases, - polymorphicApplicationCases, constantCacheCases] + polymorphicApplicationCases, constantCacheCases, cacheInvariantCases] end Tests.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 93725fbc4..dac7f0cb6 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -39,6 +39,8 @@ increasing sequence of strongly inaccessible cardinals. - `inferUncached_sort_sound` interprets an actual successful execution of the production sort-inference branch. It proves the model typing postcondition for the returned type, including intern-table reuse. + `infer_sort_cached_sound` derives the same typing when the eligible cached + value is the canonical successor sort. - `instantiateUnivParams_readAnnotated` connects the actual memoized universe substitution walker to model substitution for every readable expression. Simplifying `max` and `imax` may change the returned syntax; the proof @@ -54,7 +56,8 @@ increasing sequence of strongly inaccessible cardinals. Production success supplies the universe-arity check. The premises retain a well-formed model interface, agreement with the actual lazy-loaded declaration, finite interning and level-substitution resources, and (for - `infer`) misses in both cache partitions at the computed key. + `infer`) misses in every eligible cache partition at the computed key. + Full mode imposes no condition on the ignored inference-only partition. - `ModelTyping.no_false` rules out a closed model-typed kernel expression at primitive False when its environment has been admitted by the certified interface and the set-theory assumption has an instance. @@ -90,7 +93,20 @@ increasing sequence of strongly inaccessible cardinals. `InferenceCacheHit.run` proves the exact cache selection and returned state; full results take priority, and inference-only results require that policy. `infer_const_cache_write` establishes substitution agreement for a successful - miss's insertion. General preservation of that agreement remains open. + miss's insertion. +- `InferenceCacheAgreement` records the expected concrete value in both + partitions at one key. Sort inference and inference of an already-loaded + constant preserve this agreement at their own key and leave other keys and + loaded declarations unchanged. The miss proofs use the actual interning or + universe-substitution operation and its final cache write. + `PreservesInferenceCache` composes structural preservation through key + computation, interning, binder opening, unrelated writes, and scope/policy + cleanup, including errors. Cache clearing establishes empty-cache agreement. + `CachedConstantInferenceSupport.transport` reuses a closed constant witness + after such a frame; `BinderInference.sortOfAgreement` constructs a sort leaf + from maintained agreement. Initial agreement and finite execution resources + remain premises. General preservation through lazy loading, environment + extension, and composite inference remains open. - `checkEnvAnon_atomic_preserves_model` connects a supported production environment run to model extension. `checkEnvAnon_atomic_no_false` excludes a declaration at an axiom type interpreted as empty, including False. @@ -130,6 +146,7 @@ def idProp (P : Prop) (p : P) : P := p def useId (P : Prop) (p : P) : P := idProp P p def applyProp (P Q : Prop) (f : P → Q) (p : P) : Q := f p def usePoly (P : Prop) (p : P) : P := ident.{0} P p +def chooseLeft (P Q : Prop) (p : P) (q : Q) : P := p axiom T.{u} : Sort u axiom f.{u} : T.{u} → T.{u} def useF (x : T.{1}) : T.{1} := f.{1} x @@ -140,7 +157,10 @@ def useF (x : T.{1}) : T.{1} := f.{1} x - Every source key occurs in the `buildAnonWork` result, and every work item represents an axiom or a definition. Lookup, routing, and reset witnesses identify the checked `KConst`. -- Sort, application, forall, and lambda nodes in the inference witnesses miss both cache partitions. +- Application, forall, and lambda nodes in the inference witnesses miss every + eligible cache partition. Full mode may have a populated inference-only + partition. Sort nodes use a miss or a hit equal to the canonical successor + sort; a maintained agreement can construct that leaf's cache observation. Local-variable hits must match the current production declaration type. Constant nodes use either the existing miss rule or a selected cache hit. A hit checks the loaded declaration, universe arity, finite level resources, @@ -151,8 +171,15 @@ def useF (x : T.{1}) : T.{1} := f.{1} x the actual post-lookup state. The occurrence annotations on the declared type agree with the substituted entry's annotations. These are structural data checks; successful inference derives typing, scope, and references. - Ordinary aliases retain the simpler empty-substitution path. Sort inference - retains finite interning coherence and address-faithfulness premises. + Ordinary aliases retain the simpler empty-substitution path. Sort misses + retain finite interning coherence and address-faithfulness premises. +- Cache agreement covers both partitions so it survives policy changes. + Closed constant witnesses can be transported through composed frames that + preserve their key's entries and the loaded-constant map. Actual sort and + already-loaded constant inference provide frames for other keys. These + results reduce repeated witnesses; they do not yet derive initial agreement + or preservation through lazy loading, environment extension, or the entire + recursive inference tree. - Binder definitions supply finite inference trees for both the value and its separately checked declared type, exact source readings, closed annotated syntax, and references to the preceding interface. Recursive calls use the actual @@ -190,7 +217,7 @@ Callers must establish these operational and representation witnesses for the run. They supply no typing or checker-soundness premise. The proof extracts the validation, type-inference, theorem-guard, value-inference, and conversion steps from public success, then derives body typing to extend -the preceding model. Automatic witness construction, broader application and +the preceding model. General automatic witness construction, broader application and lambda paths, lets, inductives, coordinated blocks, and other conversion paths remain outside the fragment. Polymorphic constant inference is composed into declaration admission and model extension for the monomorphic specializations described @@ -246,7 +273,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 127 exact theorem boundaries. The production +The consistency target checks 161 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -280,6 +307,10 @@ types and bodies, including per-item cache clearing; full and inference-only reuse across fresh local scopes; monomorphic and simplifying substitutions; partition priority; and alternating universe instances. Deliberately different values in an ineligible partition make the selection tests observable. +Cache-preservation regressions add repeated sort domains, sort reuse and +partition priority, preservation through intervening sort and loaded-constant +inference, successful and failed scope cleanup, policy restoration, and +fresh inference after clearing both partitions. ## Certified host adapters @@ -308,6 +339,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Polymorphic inference and universe substitution | [`Consistency/Constant.lean`](../Ix/Kernel/Verify/Consistency/Constant.lean), [`InstUniv.lean`](../Ix/Kernel/Verify/Consistency/InstUniv.lean), [`Model/LevelCongruence.lean`](../Ix/Theory/Model/LevelCongruence.lean) | | Polymorphic calls inside binders | [`Consistency/ScopedConstant.lean`](../Ix/Kernel/Verify/Consistency/ScopedConstant.lean), [`ScopedInstUniv.lean`](../Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean) | | Constant cache selection, writes, and typing | [`Consistency/ConstantCache.lean`](../Ix/Kernel/Verify/Consistency/ConstantCache.lean) | +| Cache invariants and sort cache typing | [`Consistency/InferenceCache.lean`](../Ix/Kernel/Verify/Consistency/InferenceCache.lean), [`SortCache.lean`](../Ix/Kernel/Verify/Consistency/SortCache.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | diff --git a/docs/theory.md b/docs/theory.md index 73a5a39c9..5f0808c89 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -28,8 +28,13 @@ Binder inference uses the declared type's separate formation check to turn or admitted polymorphic constants derive their type's validity from the context or dependency model, then check arguments and substitute the dependent result. Constant cache hits derive the same typing from concrete agreement with pure -universe substitution of a loaded declaration. Cache selection and successful -miss writes are proved; general cache maintenance remains a separate obligation. +universe substitution of a loaded declaration; sort hits use the canonical +successor sort. Sort and already-loaded constant inference preserve agreement +at their cache key and retain other entries. Structural preservation composes +through binder opening, interning, unrelated writes, and scope/policy cleanup, +including errors. It transports closed constant witnesses, and maintained +agreement constructs sort leaves. Initial agreement, lazy loading, environment +extension, and preservation through composite inference remain obligations. Full checker consistency and compiler/backend refinement remain open. From cc67fffa597878c948e1fb129883803cfe8a48d6 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 16:11:28 -0400 Subject: [PATCH 13/30] Carry cache preservation through recursive inference --- Ix/Kernel/Verify/Consistency.lean | 10 +- Ix/Kernel/Verify/Consistency/Application.lean | 16 +- Ix/Kernel/Verify/Consistency/Audit.lean | 15 +- .../Verify/Consistency/BinderInference.lean | 48 ++- .../Verify/Consistency/RecursiveCache.lean | 368 ++++++++++++++++++ Tests/Ix/Kernel/Consistency.lean | 87 ++++- docs/kernel-verification.md | 31 +- docs/theory.md | 8 +- 8 files changed, 559 insertions(+), 24 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/RecursiveCache.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index f7e00969d..94f9f3ef5 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -20,6 +20,7 @@ import Ix.Kernel.Verify.Consistency.Context import Ix.Kernel.Verify.Consistency.BinderOpening import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference +import Ix.Kernel.Verify.Consistency.RecursiveCache import Ix.Kernel.Verify.Consistency.Production import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Consistency.Audit @@ -54,7 +55,12 @@ Concrete cache agreement is preserved by sort and already-loaded constant inference. Cache frames compose through interning, key computation, binder opening, unrelated writes, and scope/policy cleanup, including errors. These frames transport closed constant witnesses; maintained agreement also -constructs sort leaves. Initial agreement, finite execution resources, lazy -loading, and preservation through composite inference remain explicit obligations. +constructs sort leaves. A finite InferenceCacheTrace computes the keys written +by recursive applications, dependent functions, and full-mode lambdas, including +domain validation and outer cache writes. Successful inference preserves entries +outside that footprint, loaded declarations, and checking policy. This derives +later constant witnesses and sort leaves without new cache-hit observations. +Initial agreement, finite execution resources, trace construction, lazy loading, +and preservation for keys inside the footprint remain explicit obligations. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Application.lean b/Ix/Kernel/Verify/Consistency/Application.lean index acdee2e99..9af94b268 100644 --- a/Ix/Kernel/Verify/Consistency/Application.lean +++ b/Ix/Kernel/Verify/Consistency/Application.lean @@ -214,12 +214,14 @@ structure ApplicationInferenceTrace (fuel : Nat) (before : TcState .anon) /-- Inverting the successful production branch reaches its exact interned codomain substitution after the real argument check. -/ -theorem ApplicationInferenceTrace.output {fuel : Nat} {before after : TcState .anon} +theorem ApplicationInferenceTrace.output_state {fuel : Nat} {before after : TcState .anon} {fn arg result : KExpr .anon} {info : ExprInfo .anon} (trace : ApplicationInferenceTrace fuel before fn arg) (accepted : RecM.inferUncached RecM.inferCall false (.app fn arg info) (methodsN (fuel + 1)) before = .ok result after) : - result = (subst trace.codomain arg 0 trace.comparedState.env.intern).1 := by + result = (subst trace.codomain arg 0 trace.comparedState.env.intern).1 ∧ + after = {trace.comparedState with env := {trace.comparedState.env with + intern := (subst trace.codomain arg 0 trace.comparedState.env.intern).2}} := by change (RecM.inferUncached RecM.inferCall false (.app fn arg info)).run (methodsN (fuel + 1)) before = .ok result after at accepted unfold RecM.inferUncached at accepted @@ -234,6 +236,14 @@ theorem ApplicationInferenceTrace.output {fuel : Nat} {before after : TcState .a _ trace.argumentState = _ at accepted rw [EStateM.bind, trace.compareRun] at accepted cases accepted - rfl + exact ⟨rfl, rfl⟩ + +theorem ApplicationInferenceTrace.output {fuel : Nat} {before after : TcState .anon} + {fn arg result : KExpr .anon} {info : ExprInfo .anon} + (trace : ApplicationInferenceTrace fuel before fn arg) + (accepted : RecM.inferUncached RecM.inferCall false (.app fn arg info) + (methodsN (fuel + 1)) before = .ok result after) : + result = (subst trace.codomain arg 0 trace.comparedState.env.intern).1 := + (trace.output_state accepted).1 end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 18977e082..3af2d24df 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -6,6 +6,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 import Ix.Kernel.Verify.Consistency.Infer import Ix.Kernel.Verify.Consistency.Constant import Ix.Kernel.Verify.Consistency.Environment +import Ix.Kernel.Verify.Consistency.RecursiveCache import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -79,12 +80,22 @@ private def cacheMapRoots : Array Lean.Name := #[ ] private def cacheKeyRoots : Array Lean.Name := #[ - ``inferKey_closed, ``InferenceCacheHit.key_closed, ``observeInferenceCache, + ``inferKey_closed, ``inferKey_policy, ``InferenceCacheHit.key_closed, ``observeInferenceCache, ``InferenceCacheAgreement.selected, ``InferenceCacheHit.transport, ``PreservesInferenceCache.inferKey, ``PreservesInferenceCache.openBinder, ``withLctxScope_eq, ``PreservesInferenceCache.withLctxScope ] +private def recursiveCacheRoots : Array Lean.Name := #[ + ``ApplicationInferenceTrace.output_state, ``ForallInferenceTrace.output_state, + ``LambdaInferenceTrace.output_state, ``isDefEq_hash_state, ``isDefEq_hash_frame, + ``InferenceCacheTrace.writes, ``InferenceCacheTrace.sortOfKey, + ``InferenceCacheTrace.fvarOfKey, ``InferenceCacheTrace.constOfKey, + ``InferenceCacheTrace.frame, ``InferenceCacheTrace.agreement, + ``InferenceCacheHit.afterInference, ``CachedConstantInferenceSupport.afterInference, + ``CachedConstantInferenceSupport.sound_after_inference, ``BinderInference.sortAfterInference +] + private def productionRoots : Array Lean.Name := #[ ``StandalonePrefix.member_success, ``definition_body_trace, ``AtomicDefinitionRun.sound, ``AtomicDefinitionRun.no_self_alias, @@ -184,7 +195,7 @@ def roots : Array RootAllowance := #[ }) ++ (binderWalkerRoots ++ cacheKeyRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative], forbiddenDependencies := forbiddenProduction -}) ++ (atomicRoots ++ instantiationRoots).map (fun root => { +}) ++ (atomicRoots ++ instantiationRoots ++ recursiveCacheRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], forbiddenDependencies := forbiddenProduction }) ++ productionRoots.map (fun root => { diff --git a/Ix/Kernel/Verify/Consistency/BinderInference.lean b/Ix/Kernel/Verify/Consistency/BinderInference.lean index 7d503b5f1..6ca510094 100644 --- a/Ix/Kernel/Verify/Consistency/BinderInference.lean +++ b/Ix/Kernel/Verify/Consistency/BinderInference.lean @@ -63,14 +63,15 @@ theorem inferUncached_monomorphic_const_scoped {β : Type u} private theorem withLctxScope_success {action : RecM .anon α} {methods : Methods .anon} {before after : TcState .anon} {result : α} (accepted : (RecM.withLctxScope action).run methods before = .ok result after) : - ∃ state, action.run methods before = .ok result state := by + ∃ state, action.run methods before = .ok result state ∧ + after = {state with lctx := state.lctx.truncate before.lctx.size} := by rw [withLctxScope_eq] at accepted cases run : action.run methods before with | error err state => rw [run] at accepted; contradiction | ok value state => rw [run] at accepted cases accepted - exact ⟨state, rfl⟩ + exact ⟨state, rfl, rfl⟩ /-- The exact recursive calls and opening prefix of a forall branch. Both sort exposures take the production syntactic fast path. -/ @@ -95,14 +96,18 @@ structure ForallInferenceTrace (fuel : Nat) (before : TcState .anon) /-- Inversion reaches the actual final interning operation after both recursive calls, sort exposures, and binder opening. -/ -theorem ForallInferenceTrace.output {fuel : Nat} {before after : TcState .anon} +theorem ForallInferenceTrace.output_state {fuel : Nat} {before after : TcState .anon} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {domain body result : KExpr .anon} {info : ExprInfo .anon} {inferOnly : Bool} (trace : ForallInferenceTrace fuel before name bi domain body) (accepted : RecM.inferUncached RecM.inferCall inferOnly (.all name bi domain body info) (methodsN (fuel + 1)) before = .ok result after) : result = (trace.bodyState.env.intern.internExpr - (KExpr.mkSort (KUniv.mkIMax trace.domainLevel trace.bodyLevel))).1 := by + (KExpr.mkSort (KUniv.mkIMax trace.domainLevel trace.bodyLevel))).1 ∧ + after = {trace.bodyState with + env := {trace.bodyState.env with intern := (trace.bodyState.env.intern.internExpr + (KExpr.mkSort (KUniv.mkIMax trace.domainLevel trace.bodyLevel))).2} + lctx := trace.bodyState.lctx.truncate trace.domainState.lctx.size} := by change (RecM.inferUncached RecM.inferCall inferOnly (.all name bi domain body info)).run (methodsN (fuel + 1)) before = .ok result after at accepted unfold RecM.inferUncached at accepted @@ -110,7 +115,7 @@ theorem ForallInferenceTrace.output {fuel : Nat} {before after : TcState .anon} change EStateM.bind (RecM.infer domain (methodsN fuel)) _ before = _ at accepted rw [EStateM.bind, trace.domainRun] at accepted change (RecM.withLctxScope _).run (methodsN (fuel + 1)) trace.domainState = _ at accepted - obtain ⟨scopedState, accepted⟩ := withLctxScope_success accepted + obtain ⟨scopedState, accepted, cleanup⟩ := withLctxScope_success accepted simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted change EStateM.bind (TcM.openBinder name bi domain body) _ trace.domainState = .ok result scopedState at accepted @@ -121,7 +126,17 @@ theorem ForallInferenceTrace.output {fuel : Nat} {before after : TcState .anon} _ trace.openedState = .ok result scopedState at accepted rw [EStateM.bind, bodyRun] at accepted cases accepted - rfl + exact ⟨rfl, cleanup⟩ + +theorem ForallInferenceTrace.output {fuel : Nat} {before after : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {domain body result : KExpr .anon} {info : ExprInfo .anon} {inferOnly : Bool} + (trace : ForallInferenceTrace fuel before name bi domain body) + (accepted : RecM.inferUncached RecM.inferCall inferOnly (.all name bi domain body info) + (methodsN (fuel + 1)) before = .ok result after) : + result = (trace.bodyState.env.intern.internExpr + (KExpr.mkSort (KUniv.mkIMax trace.domainLevel trace.bodyLevel))).1 := + (trace.output_state accepted).1 /-- Full-mode lambda inference validates its domain, opens the binder, and infers the body. The current fragment takes the unchanged cheap-beta path. -/ @@ -150,13 +165,17 @@ def LambdaInferenceTrace.abstracted {fuel : Nat} {before : TcState .anon} /-- The returned lambda type is the actual abstracted body type, wrapped in the production Pi constructor and passed through the final intern table. -/ -theorem LambdaInferenceTrace.output {fuel : Nat} {before after : TcState .anon} +theorem LambdaInferenceTrace.output_state {fuel : Nat} {before after : TcState .anon} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} {domain body result : KExpr .anon} {info : ExprInfo .anon} (trace : LambdaInferenceTrace fuel before name bi domain body) (accepted : RecM.inferUncached RecM.inferCall false (.lam name bi domain body info) (methodsN (fuel + 1)) before = .ok result after) : - result = (trace.abstracted.2.internExpr (KExpr.mkAll () () domain trace.abstracted.1)).1 := by + result = (trace.abstracted.2.internExpr (KExpr.mkAll () () domain trace.abstracted.1)).1 ∧ + after = {trace.bodyState with + env := {trace.bodyState.env with + intern := (trace.abstracted.2.internExpr (KExpr.mkAll () () domain trace.abstracted.1)).2} + lctx := trace.bodyState.lctx.truncate trace.domainState.lctx.size} := by change (RecM.inferUncached RecM.inferCall false (.lam name bi domain body info)).run (methodsN (fuel + 1)) before = .ok result after at accepted unfold RecM.inferUncached at accepted @@ -164,7 +183,7 @@ theorem LambdaInferenceTrace.output {fuel : Nat} {before after : TcState .anon} change EStateM.bind (RecM.infer domain (methodsN fuel)) _ before = _ at accepted rw [EStateM.bind, trace.domainRun] at accepted change (RecM.withLctxScope _).run (methodsN (fuel + 1)) trace.domainState = _ at accepted - obtain ⟨scopedState, accepted⟩ := withLctxScope_success accepted + obtain ⟨scopedState, accepted, cleanup⟩ := withLctxScope_success accepted simp only [ReaderT.run_bind, ReaderT.run_monadLift] at accepted change EStateM.bind (TcM.openBinder name bi domain body) _ trace.domainState = .ok result scopedState at accepted @@ -176,7 +195,16 @@ theorem LambdaInferenceTrace.output {fuel : Nat} {before after : TcState .anon} rw [EStateM.bind, bodyRun] at accepted simp only [cheapBetaReduce, trace.betaUnchanged] at accepted cases accepted - rfl + exact ⟨rfl, cleanup⟩ + +theorem LambdaInferenceTrace.output {fuel : Nat} {before after : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {domain body result : KExpr .anon} {info : ExprInfo .anon} + (trace : LambdaInferenceTrace fuel before name bi domain body) + (accepted : RecM.inferUncached RecM.inferCall false (.lam name bi domain body info) + (methodsN (fuel + 1)) before = .ok result after) : + result = (trace.abstracted.2.internExpr (KExpr.mkAll () () domain trace.abstracted.1)).1 := + (trace.output_state accepted).1 /-- Structural and operational support for a finite production inference tree. The source reading and local-context agreement are inputs to soundness, diff --git a/Ix/Kernel/Verify/Consistency/RecursiveCache.lean b/Ix/Kernel/Verify/Consistency/RecursiveCache.lean new file mode 100644 index 000000000..d42bc9fe1 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/RecursiveCache.lean @@ -0,0 +1,368 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.BinderInference + +/-! +# Cache preservation through recursive inference + +Finite operational trees follow the actual smaller method table, recording +the keys written by successful misses. An entry outside those writes and its +loaded declaration survive the entire inference, so a closed cached witness +can be reused afterward. No semantic typing or per-call cache frame is an input. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u v + +/-- Key computation may memoize a context digest but cannot change policy. -/ +theorem inferKey_policy {term : KExpr .anon} {before after : TcState .anon} + {key : Address × Address} (run : TcM.inferKey term before = .ok key after) : + after.inferOnly = before.inferOnly := by + unfold TcM.inferKey at run + change EStateM.bind (TcM.ctxAddrForLbr term.lbr) _ before = _ at run + unfold TcM.ctxAddrForLbr at run + change EStateM.bind (fun state => EStateM.bind (get : TcM .anon (TcState .anon)) + _ state) _ before = _ at run + simp only [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] at run + by_cases fast : (term.lbr == 0 || before.ctx.isEmpty) = true + · rw [if_pos fast] at run + cases run; rfl + · rw [if_neg fast] at run + cases cached : before.ctxAddrCache[(before.ctxId, term.lbr)]? <;> + rw [cached] at run <;> cases run <;> rfl + +/-- Hash conversion executes only tracing and its optional statistics update. +The exact state includes that counter update; it is not assumed unchanged. -/ +theorem isDefEq_hash_state {left right : KExpr .anon} + (equal : (left.addr == right.addr) = true) + (methods : Methods .anon) (before : TcState .anon) : + RecM.isDefEq left right methods before = .ok true + (if before.stats then {before with deqCalls := before.deqCalls + 1} else before) := by + have traced : TcM.stepTrace "deq" + (fun _ => s!"{TcM.addr8 left.addr} ~ {TcM.addr8 right.addr}") before = .ok () before := by + unfold TcM.stepTrace + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = .ok before before from rfl] + dsimp only + split <;> rfl + have bumped : TcM.bumpStats + (fun state : TcState .anon => {state with deqCalls := state.deqCalls + 1}) before = + .ok () (if before.stats then {before with deqCalls := before.deqCalls + 1} else before) := by + unfold TcM.bumpStats + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = .ok before before from rfl] + dsimp only + by_cases enabled : before.stats = true + · rw [if_pos enabled, if_pos enabled]; rfl + · rw [if_neg enabled, if_neg enabled]; rfl + change (RecM.isDefEq left right).run methods before = _ + unfold RecM.isDefEq + rw [ReaderT.run_bind] + change EStateM.bind (TcM.stepTrace "deq" + (fun _ => s!"{TcM.addr8 left.addr} ~ {TcM.addr8 right.addr}")) _ before = _ + rw [EStateM.bind, traced] + simp only [ReaderT.run_bind] + change EStateM.bind (TcM.bumpStats + (fun state : TcState .anon => {state with deqCalls := state.deqCalls + 1})) _ before = _ + rw [EStateM.bind, bumped] + simp only [equal, if_true] + rfl + +/-- The supported conversion path retains inference caches, loaded sources, +and the caller's checking policy even when statistics are enabled. -/ +theorem isDefEq_hash_frame {left right : KExpr .anon} + {methods : Methods .anon} {before after : TcState .anon} + (equal : (left.addr == right.addr) = true) + (run : RecM.isDefEq left right methods before = .ok true after) + (key : Address × Address) : + InferenceCacheFrame key before after ∧ after.inferOnly = before.inferOnly := by + rw [isDefEq_hash_state equal] at run + split at run <;> cases run <;> exact ⟨⟨rfl, rfl, rfl⟩, rfl⟩ + +private theorem openBinder_policy {name : Mode.anon.F Name} + {bi : Mode.anon.F Lean.BinderInfo} {domain body opened : KExpr .anon} + {fresh : FVarId} {before after : TcState .anon} + (run : TcM.openBinder name bi domain body before = .ok (opened, fresh) after) : + after.inferOnly = before.inferOnly := by + rw [openBinder_eq] at run + split at run + · cases run; rfl + · contradiction + +private theorem openBinder_frame {name : Mode.anon.F Name} + {bi : Mode.anon.F Lean.BinderInfo} {domain body opened : KExpr .anon} + {fresh : FVarId} {before after : TcState .anon} (key : Address × Address) + (run : TcM.openBinder name bi domain body before = .ok (opened, fresh) after) : + InferenceCacheFrame key before after := by + have frame := PreservesInferenceCache.openBinder key name bi domain body before + rw [run] at frame + exact frame + +private theorem infer_miss_frame {term result : KExpr .anon} + {methods : Methods .anon} {before after : TcState .anon} {key : Address × Address} + (miss : UncachedInference before term) (different : miss.key ≠ key) + (accepted : RecM.infer term methods before = .ok result after) + (uncached : ∀ middle, + RecM.inferUncached RecM.inferCall before.inferOnly term methods miss.keyed = .ok result middle → + InferenceCacheFrame key miss.keyed middle ∧ middle.inferOnly = miss.keyed.inferOnly) : + InferenceCacheFrame key before after ∧ after.inferOnly = before.inferOnly := by + obtain ⟨middle, run, written⟩ := infer_uncached_success_state miss accepted + obtain ⟨bodyFrame, bodyPolicy⟩ := uncached middle run + have keyFrame := PreservesInferenceCache.inferKey key term before + rw [miss.keyRun] at keyFrame + have writeRun : RecM.cacheInferResult before.inferOnly miss.key result methods middle = + .ok () after := by + rw [cacheInferResult_eq, written] + have tail := PreservesInferenceCache.write_other different before.inferOnly result methods middle + rw [writeRun] at tail + have policy : after.inferOnly = middle.inferOnly := by + rw [written] + cases before.inferOnly <;> rfl + exact ⟨keyFrame.trans (bodyFrame.trans tail), + policy.trans (bodyPolicy.trans (inferKey_policy miss.keyRun))⟩ + +/-- Operational support for the successful recursive fragment. Hits write +nothing, including repeated uses of the watched entry. Misses record their +actual key; constant misses require a loaded source and finite walker resources. +The lambda domain call is included even though semantic checking can omit its +typing subtree once the declared type's formation has been established. -/ +inductive InferenceCacheTrace : Nat → TcState .anon → KExpr .anon → Type + | hit {fuel before term} (hit : InferenceCacheHit before term) : + InferenceCacheTrace fuel before term + | sort {fuel before level info} (miss : UncachedInference before (.sort level info)) : + InferenceCacheTrace fuel before (.sort level info) + | fvar {fuel before id name info} (miss : UncachedInference before (.fvar id name info)) : + InferenceCacheTrace fuel before (.fvar id name info) + | const {fuel before id arguments info} + (miss : UncachedInference before (.const id arguments info)) + (concrete : KConst .anon) (loaded : miss.keyed.env.get? id = some concrete) + (resources : UniverseInstantiationSupport miss.keyed concrete.ty arguments) : + InferenceCacheTrace fuel before (.const id arguments info) + | app {fuel before fn arg info} (full : before.inferOnly = false) + (miss : UncachedInference before (.app fn arg info)) + (trace : ApplicationInferenceTrace fuel miss.keyed fn arg) + (hashPath : (trace.argumentType.addr == trace.domain.addr) = true) + (functionTree : InferenceCacheTrace fuel miss.keyed fn) + (argumentTree : InferenceCacheTrace fuel trace.functionState arg) : + InferenceCacheTrace (fuel + 1) before (.app fn arg info) + | forallE {fuel before name bi domain body info} + (miss : UncachedInference before (.all name bi domain body info)) + (trace : ForallInferenceTrace fuel miss.keyed name bi domain body) + (domainTree : InferenceCacheTrace fuel miss.keyed domain) + (bodyTree : InferenceCacheTrace fuel trace.openedState trace.opened) : + InferenceCacheTrace (fuel + 1) before (.all name bi domain body info) + | lam {fuel before name bi domain body info} (full : before.inferOnly = false) + (miss : UncachedInference before (.lam name bi domain body info)) + (trace : LambdaInferenceTrace fuel miss.keyed name bi domain body) + (domainTree : InferenceCacheTrace fuel miss.keyed domain) + (bodyTree : InferenceCacheTrace fuel trace.openedState trace.opened) : + InferenceCacheTrace (fuel + 1) before (.lam name bi domain body info) + +/-- The finite write footprint is computed from the operational tree. Cache +hits contribute no key; recursive calls and each outer insertion are included. -/ +def InferenceCacheTrace.writes {fuel : Nat} {before : TcState .anon} {term : KExpr .anon} : + InferenceCacheTrace fuel before term → List (Address × Address) + | .hit _ => [] + | .sort miss | .fvar miss | .const miss .. => [miss.key] + | .app _ miss _ _ first second | .forallE miss _ first second | .lam _ miss _ first second => + miss.key :: (first.writes ++ second.writes) + +/-- Leaf construction inspects the real cache policy; callers need not +provide a separate hit/miss observation for a sort. -/ +def InferenceCacheTrace.sortOfKey {fuel : Nat} {before keyed : TcState .anon} + {level : KUniv .anon} {info : ExprInfo .anon} {key : Address × Address} + (keyRun : TcM.inferKey (.sort level info) before = .ok key keyed) : + InferenceCacheTrace fuel before (.sort level info) := by + rcases observeInferenceCache keyRun with ⟨hit, _, _⟩ | ⟨miss, _, _⟩ + · exact .hit hit + · exact .sort miss + +def InferenceCacheTrace.fvarOfKey {fuel : Nat} {before keyed : TcState .anon} + {id : FVarId} {name : Mode.anon.F Name} {info : ExprInfo .anon} {key : Address × Address} + (keyRun : TcM.inferKey (.fvar id name info) before = .ok key keyed) : + InferenceCacheTrace fuel before (.fvar id name info) := by + rcases observeInferenceCache keyRun with ⟨hit, _, _⟩ | ⟨miss, _, _⟩ + · exact .hit hit + · exact .fvar miss + +def InferenceCacheTrace.constOfKey {fuel : Nat} {before keyed : TcState .anon} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {key : Address × Address} {concrete : KConst .anon} + (keyRun : TcM.inferKey (.const id arguments info) before = .ok key keyed) + (loaded : keyed.env.get? id = some concrete) + (resources : UniverseInstantiationSupport keyed concrete.ty arguments) : + InferenceCacheTrace fuel before (.const id arguments info) := by + rcases observeInferenceCache keyRun with ⟨hit, _, _⟩ | ⟨miss, _, stateEq⟩ + · exact .hit hit + · exact .const miss concrete (by simpa only [stateEq] using loaded) + (by simpa only [stateEq] using resources) + +/-- Every successful call in the finite tree preserves entries outside its +computed write footprint and retains the loaded declarations and policy. +The proof follows the recursive calls, then their real outer cache insertion. -/ +theorem InferenceCacheTrace.frame {fuel : Nat} {before after : TcState .anon} + {term result : KExpr .anon} (tree : InferenceCacheTrace fuel before term) + {key : Address × Address} (outside : key ∉ tree.writes) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : + InferenceCacheFrame key before after ∧ after.inferOnly = before.inferOnly := by + induction tree generalizing result after with + | @hit fuel before term hit => + rw [hit.run] at accepted + cases accepted + have frame := PreservesInferenceCache.inferKey key term before + rw [hit.keyRun] at frame + exact ⟨frame, inferKey_policy hit.keyRun⟩ + | @sort fuel before level info miss => + simp only [writes, List.mem_singleton] at outside + apply infer_miss_frame miss (Ne.symm outside) accepted + intro middle run + change EStateM.Result.ok + (miss.keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).1 + {miss.keyed with env := {miss.keyed.env with intern := + (miss.keyed.env.intern.internExpr (KExpr.mkSort (KUniv.mkSucc level))).2}} = + .ok result middle at run + cases run + exact ⟨⟨rfl, rfl, rfl⟩, rfl⟩ + | @fvar fuel before id name info miss => + simp only [writes, List.mem_singleton] at outside + apply infer_miss_frame miss (Ne.symm outside) accepted + intro middle run + change (RecM.inferUncached RecM.inferCall before.inferOnly (.fvar id name info)).run + (methodsN fuel) miss.keyed = _ at run + unfold RecM.inferUncached at run + simp only [ReaderT.run_bind] at run + change EStateM.bind (get : TcM .anon (TcState .anon)) _ miss.keyed = _ at run + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) miss.keyed = + .ok miss.keyed miss.keyed from rfl] at run + dsimp only at run + split at run + · cases run; exact ⟨.refl key _, rfl⟩ + · contradiction + | const miss concrete loaded resources => + simp only [writes, List.mem_singleton] at outside + apply infer_miss_frame miss (Ne.symm outside) accepted + intro middle run + obtain ⟨actual, foundState, got, _, instantiated⟩ := inferUncached_const_instantiation run + rw [getConst_loaded loaded] at got + cases got + have post := TcM.instantiateUnivParams_wf resources.faithful + (fun _ h => Or.inr h) ⟨resources.coherent, fun _ h => Or.inl h⟩ + rw [instantiated] at post + rw [post.2.2.1] + exact ⟨⟨rfl, rfl, rfl⟩, rfl⟩ + | app full miss trace hashPath functionTree argumentTree functionIH argumentIH => + simp only [writes, List.mem_cons, List.mem_append, not_or] at outside + apply infer_miss_frame miss (Ne.symm outside.1) accepted + intro middle run + rw [full] at run + obtain ⟨functionFrame, functionPolicy⟩ := functionIH outside.2.1 trace.functionRun + obtain ⟨argumentFrame, argumentPolicy⟩ := argumentIH outside.2.2 trace.argumentRun + obtain ⟨comparisonFrame, comparisonPolicy⟩ := isDefEq_hash_frame hashPath trace.compareRun key + have state := (trace.output_state run).2 + rw [state] + exact ⟨(functionFrame.trans (argumentFrame.trans comparisonFrame)).trans ⟨rfl, rfl, rfl⟩, + comparisonPolicy.trans (argumentPolicy.trans functionPolicy)⟩ + | forallE miss trace domainTree bodyTree domainIH bodyIH => + simp only [writes, List.mem_cons, List.mem_append, not_or] at outside + apply infer_miss_frame miss (Ne.symm outside.1) accepted + intro middle run + obtain ⟨domainFrame, domainPolicy⟩ := domainIH outside.2.1 trace.domainRun + obtain ⟨bodyFrame, bodyPolicy⟩ := bodyIH outside.2.2 trace.bodyRun + have opening := openBinder_frame key trace.openRun + have state := (trace.output_state run).2 + rw [state] + exact ⟨(domainFrame.trans (opening.trans bodyFrame)).trans ⟨rfl, rfl, rfl⟩, + bodyPolicy.trans ((openBinder_policy trace.openRun).trans domainPolicy)⟩ + | lam full miss trace domainTree bodyTree domainIH bodyIH => + simp only [writes, List.mem_cons, List.mem_append, not_or] at outside + apply infer_miss_frame miss (Ne.symm outside.1) accepted + intro middle run + rw [full] at run + obtain ⟨domainFrame, domainPolicy⟩ := domainIH outside.2.1 trace.domainRun + obtain ⟨bodyFrame, bodyPolicy⟩ := bodyIH outside.2.2 trace.bodyRun + have opening := openBinder_frame key trace.openRun + have state := (trace.output_state run).2 + rw [state] + exact ⟨(domainFrame.trans (opening.trans bodyFrame)).trans ⟨rfl, rfl, rfl⟩, + bodyPolicy.trans ((openBinder_policy trace.openRun).trans domainPolicy)⟩ + +/-- Concrete agreement at an unwritten key is retained by the entire tree. -/ +theorem InferenceCacheTrace.agreement {fuel : Nat} {before after : TcState .anon} + {term result expected : KExpr .anon} (tree : InferenceCacheTrace fuel before term) + {key : Address × Address} (outside : key ∉ tree.writes) + (agreement : InferenceCacheAgreement before key expected) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : + InferenceCacheAgreement after key expected := + agreement.frame (tree.frame outside accepted).1 + +/-- Reconstruct the later selected hit from the earlier closed hit and the +whole recursive call, with no additional cache or policy observation. -/ +def InferenceCacheHit.afterInference {fuel : Nat} {before after : TcState .anon} + {cachedTerm term result : KExpr .anon} (hit : InferenceCacheHit before cachedTerm) + (closed : cachedTerm.lbr = 0) (tree : InferenceCacheTrace fuel before term) + (outside : (cachedTerm.addr, emptyCtxAddr) ∉ tree.writes) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : + InferenceCacheHit after cachedTerm := + hit.transport closed (tree.frame outside accepted).1 (tree.frame outside accepted).2 + +/-- Carry the admitted declaration, substitution prediction, and selected +constant hit through inference of an entire supported function body. -/ +def CachedConstantInferenceSupport.afterInference {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {fuel : Nat} {before after : TcState .anon} {term result : KExpr .anon} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} + (support : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) + (closed : (KExpr.const id arguments info).lbr = 0) + (tree : InferenceCacheTrace fuel before term) + (outside : ((KExpr.const id arguments info).addr, emptyCtxAddr) ∉ tree.writes) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) : + CachedConstantInferenceSupport resolve entries after id arguments info ref entry type := + support.transport closed (tree.frame outside accepted).1 (tree.frame outside accepted).2 + +/-- A later constant's actual returned type inherits typing from its earlier +witness after recursive inference; no semantic premise about caches is added. -/ +theorem CachedConstantInferenceSupport.sound_after_inference {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} + {fuel : Nat} {before middle after : TcState .anon} {term result cachedResult : KExpr .anon} + {id : KId .anon} {arguments : Array (KUniv .anon)} {info : ExprInfo .anon} + {ref : ConstRef β} {entry : ConstantEntry β} {type : AExpr β} {methods : Methods .anon} + (support : CachedConstantInferenceSupport resolve entries before id arguments info ref entry type) + (closed : (KExpr.const id arguments info).lbr = 0) + (tree : InferenceCacheTrace fuel before term) + (outside : ((KExpr.const id arguments info).addr, emptyCtxAddr) ∉ tree.writes) + (inferred : RecM.infer term (methodsN fuel) before = .ok result middle) + (accepted : RecM.infer (.const id arguments info) methods middle = .ok cachedResult after) : + readScopedExpr? resolve locals cachedResult = some type.erase ∧ + TypingClaim.{u,v} entries context (.const ref (arguments.toList.map readLevel)) type := + (support.afterInference closed tree outside inferred).sound accepted + +/-- Construct a later sort leaf using agreement preserved by a whole +recursive call, deriving its current key and cache selection automatically. -/ +def BinderInference.sortAfterInference {β : Type u} + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {locals : List FVarId} {context : Model.Context β} {fuel nextFuel : Nat} + {before after : TcState .anon} {term result : KExpr .anon} + {level : KUniv .anon} {info : ExprInfo .anon} + (closed : (KExpr.sort level info).lbr = 0) + (agreement : InferenceCacheAgreement before ((KExpr.sort level info).addr, emptyCtxAddr) + (KExpr.mkSort (KUniv.mkSucc level))) + (tree : InferenceCacheTrace fuel before term) + (outside : ((KExpr.sort level info).addr, emptyCtxAddr) ∉ tree.writes) + (accepted : RecM.infer term (methodsN fuel) before = .ok result after) + (coherent : after.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun candidate => after.env.intern.ExprSupport candidate ∨ + candidate = KExpr.mkSort (KUniv.mkSucc level)) : + BinderInference resolve entries locals context nextFuel after (.sort level info) + (.sort (readLevel level)) (.sort (.succ (readLevel level))) := + .sortOfAgreement closed (tree.agreement outside agreement accepted) coherent faithful + +end Ix.Kernel.Consistency diff --git a/Tests/Ix/Kernel/Consistency.lean b/Tests/Ix/Kernel/Consistency.lean index 4d49329b4..92bfa5368 100644 --- a/Tests/Ix/Kernel/Consistency.lean +++ b/Tests/Ix/Kernel/Consistency.lean @@ -723,8 +723,93 @@ private def cacheInvariantCases : TestSeq := ++ test "cache invariants: clearing both partitions permits fresh inference-only synthesis" (inferenceAfterClearing true) +/-- Preserve warm constant and sort entries through entire recursive calls. +The application checks a lambda argument; the lambda itself uses the watched +constant twice. Replaying the composite result also exercises a root cache hit. +These are operational preservation cases; composite cache-hit typing remains +a separate refinement boundary. -/ +private def cacheAfterComposite (shape : Nat) (inferOnly stats surroundingScope : Bool) : Bool := + let id : KId .anon := ⟨polymorphicIdentity.2, ()⟩ + let watched := KExpr.mkConst (m := .anon) id #[levelOne] + let sortType := KExpr.mkSort (m := .anon) levelOne + let useIdentity : KExpr .anon → KExpr .anon := fun arg => + .mkApp (.mkApp watched (.mkVar 1 ())) arg + let body := KExpr.mkLam () () sortType + (.mkLam () () (.mkVar 0 ()) (useIdentity (useIdentity (.mkVar 0 ())))) + let application := KExpr.mkApp (.mkApp (.mkConst id #[levelTwo]) identityType) body + let term := if shape == 0 then identityType else if shape == 1 then body else application + let expected := if shape == 0 then KExpr.mkSort levelTwo else identityType + let action : RecM .anon Bool := do + let constantType ← RecM.inferCall watched + let sortResult ← RecM.inferCall sortType + let key ← TcM.inferKey watched + let sortKey ← TcM.inferKey sortType + let initial ← get + RecM.withLctxScope do + if surroundingScope then + let _ ← TcM.openBinder () () sortType (.mkVar 0 ()) + pure () + let activeSize := (← get).lctx.size + let rootKey ← TcM.inferKey term + let result ← RecM.inferCall term + let after ← get + let cache := if inferOnly then after.env.inferOnlyCache else after.env.inferCache + let oldCache := if inferOnly then initial.env.inferOnlyCache else initial.env.inferCache + let opposite := if inferOnly then after.env.inferCache else after.env.inferOnlyCache + let replay ← RecM.inferCall term + let constantReuse ← RecM.inferCall watched + let sortReuse ← RecM.inferCall sortType + let final ← get + return result.addr == expected.addr && result.lbr == 0 && replay.addr == result.addr && + constantReuse.addr == constantType.addr && constantType.addr == identityType.addr && + sortReuse.addr == sortResult.addr && sortResult.addr == (.mkSort levelTwo : KExpr .anon).addr && + rootKey != key && rootKey != sortKey && key != sortKey && + cache[key]?.map (·.addr) == oldCache[key]?.map (·.addr) && + cache[sortKey]?.map (·.addr) == oldCache[sortKey]?.map (·.addr) && + cache[rootKey]?.any (fun cached => cached.addr == result.addr) && + cache.size > oldCache.size && opposite.isEmpty && + after.env.consts.size == initial.env.consts.size && + (after.env.get? id).map (·.ty.addr) == (initial.env.get? id).map (·.ty.addr) && + after.lctx.size == activeSize && after.inferOnly == inferOnly && + (if stats && shape != 0 then after.deqCalls > initial.deqCalls + else after.deqCalls == initial.deqCalls) && final.deqCalls == after.deqCalls + match TcM.runRec action { TcState.newLazyAnon polymorphicIdentity.1 with inferOnly, stats } with + | .ok passed after => passed && after.lctx.size == 0 && after.inferOnly == inferOnly + | .error _ _ => false + +private def recursiveCacheEnvironment : Ixon.Env := Id.run do + let (env, identity) := polymorphicIdentity + let nestedCall : Ixon.Expr → Ixon.Expr := fun arg => + .app (.app (.ref 0 #[0]) (.var 1)) arg + let definition : Ixon.Univ → Ix.DefKind → Ixon.Constant := fun level kind => + ⟨.defn ⟨kind, .safe, 0, + .leanAll (.sort 0) (.leanAll (.var 0) (.var 1)), + .leanLam (.sort 0) (.leanLam (.var 0) (nestedCall (nestedCall (.var 0))))⟩, + #[], #[identity], #[level]⟩ + let (env, _) := storeConst env (definition (.succ .zero) .defn) + let (env, _) := storeConst env (definition (.succ (.succ .zero)) .opaq) + return env + +private def recursiveCacheCases : TestSeq := + test "recursive cache: full dependent type inference retains warm sort and constant entries" + (cacheAfterComposite 0 false false false) + ++ test "recursive cache: inference-only dependent type inference retains warm entries" + (cacheAfterComposite 0 true false false) + ++ test "recursive cache: nested lambda applications retain repeatedly used constant entries" + (cacheAfterComposite 1 false false false) + ++ test "recursive cache: application with a lambda argument retains warm entries" + (cacheAfterComposite 2 false false false) + ++ test "recursive cache: hash-conversion statistics preserve entries and root replay is read-only" + (cacheAfterComposite 2 false true false) + ++ test "recursive cache: nested inference preserves an existing outer local scope" + (cacheAfterComposite 2 false true true) + ++ test "recursive cache: nested polymorphic calls check with persistent caches" + (allSucceeded recursiveCacheEnvironment 3 { clearEvery := 0 }) + ++ test "recursive cache: nested polymorphic calls check with per-item clearing" + (allSucceeded recursiveCacheEnvironment 3 { clearEvery := 1 }) + public def suite : List TestSeq := [cases, polymorphicCases, specializationCases, binderCases, applicationCases, - polymorphicApplicationCases, constantCacheCases, cacheInvariantCases] + polymorphicApplicationCases, constantCacheCases, cacheInvariantCases, recursiveCacheCases] end Tests.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index dac7f0cb6..22496e4d0 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -106,7 +106,18 @@ increasing sequence of strongly inaccessible cardinals. after such a frame; `BinderInference.sortOfAgreement` constructs a sort leaf from maintained agreement. Initial agreement and finite execution resources remain premises. General preservation through lazy loading, environment - extension, and composite inference remains open. + extension, and all recursive paths remains open. +- `InferenceCacheTrace.frame` carries preservation through finite recursive + application, forall, and full-mode lambda trees. The trace computes the keys + written by misses, including recursive calls and the final outer insertion; + hits contribute no writes. Entries outside this footprint, loaded declarations, + and checking policy survive the entire successful call. The proof accounts + for lambda domain validation, binder cleanup, and hash conversion's optional + statistics update. `CachedConstantInferenceSupport.afterInference` transports + a closed constant witness through that call, and `BinderInference.sortAfterInference` + constructs a later sort leaf from preserved agreement. Neither needs another + cache-hit observation after the call. The operational tree and exclusion of + the protected key from its writes remain explicit inputs. - `checkEnvAnon_atomic_preserves_model` connects a supported production environment run to model extension. `checkEnvAnon_atomic_no_false` excludes a declaration at an axiom type interpreted as empty, including False. @@ -178,8 +189,14 @@ def useF (x : T.{1}) : T.{1} := f.{1} x preserve their key's entries and the loaded-constant map. Actual sort and already-loaded constant inference provide frames for other keys. These results reduce repeated witnesses; they do not yet derive initial agreement - or preservation through lazy loading, environment extension, or the entire - recursive inference tree. + or preservation through lazy loading or environment extension. + A separate `InferenceCacheTrace` derives a frame for an entire supported + recursive call at any key outside its computed writes. It shares the existing + application and binder execution traces and additionally follows lambda-domain + inference. Constant misses require already-loaded declarations and finite + universe-walker resources; applications use full mode and hash conversion. + The operational trace can frame any selected cache hit, while semantic typing + of composite hits remains outside `BinderInference`. - Binder definitions supply finite inference trees for both the value and its separately checked declared type, exact source readings, closed annotated syntax, and references to the preceding interface. Recursive calls use the actual @@ -273,7 +290,7 @@ lake test --wfail -- tc-unit lake -d Models/SetTheory build --wfail ``` -The consistency target checks 161 exact theorem boundaries. The production +The consistency target checks 177 exact theorem boundaries. The production environment roots retain four existing generated output-length proofs, reached through expression/universe construction, names, and the full production method table. They introduce no new native proofs. The model @@ -311,6 +328,11 @@ Cache-preservation regressions add repeated sort domains, sort reuse and partition priority, preservation through intervening sort and loaded-constant inference, successful and failed scope cleanup, policy restoration, and fresh inference after clearing both partitions. +Recursive preservation regressions retain warm sort and constant entries +through dependent types in both policies, nested lambda applications, and +applications with lambda arguments. They also check reuse of the whole cached +result, statistics updates during hash conversion, an existing outer local +scope, and nested polymorphic declarations with persistent or cleared caches. ## Certified host adapters @@ -340,6 +362,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Polymorphic calls inside binders | [`Consistency/ScopedConstant.lean`](../Ix/Kernel/Verify/Consistency/ScopedConstant.lean), [`ScopedInstUniv.lean`](../Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean) | | Constant cache selection, writes, and typing | [`Consistency/ConstantCache.lean`](../Ix/Kernel/Verify/Consistency/ConstantCache.lean) | | Cache invariants and sort cache typing | [`Consistency/InferenceCache.lean`](../Ix/Kernel/Verify/Consistency/InferenceCache.lean), [`SortCache.lean`](../Ix/Kernel/Verify/Consistency/SortCache.lean) | +| Recursive cache preservation and witness reuse | [`Consistency/RecursiveCache.lean`](../Ix/Kernel/Verify/Consistency/RecursiveCache.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | diff --git a/docs/theory.md b/docs/theory.md index 5f0808c89..78da02b32 100644 --- a/docs/theory.md +++ b/docs/theory.md @@ -33,8 +33,12 @@ successor sort. Sort and already-loaded constant inference preserve agreement at their cache key and retain other entries. Structural preservation composes through binder opening, interning, unrelated writes, and scope/policy cleanup, including errors. It transports closed constant witnesses, and maintained -agreement constructs sort leaves. Initial agreement, lazy loading, environment -extension, and preservation through composite inference remain obligations. +agreement constructs sort leaves. A finite operational trace now carries +preservation through recursive applications, dependent types, and full-mode +lambdas for keys absent from the recorded writes. It derives later constant +witnesses and sort leaves without repeated cache-hit observations. Initial +agreement, trace construction, lazy loading, environment extension, and +preservation for keys that are written remain obligations. Full checker consistency and compiler/backend refinement remain open. From 3cec1f86cfe13728b93c8b853526f0cc7d2a1668 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 10:00:48 -0400 Subject: [PATCH 14/30] fix(aiur): reject forged results and cyclic call traces Constrain inactive provider multiplicities, enforce range-checked call ranks, validate lookup message boundaries, and gate lookups in circuits whose control flow does not establish a unique writer. Check control counts, fixed-table shapes, and the global lookup budget. Align compiler layouts and witness generation with the rank constraints, retain supplied-witness regressions, and update the measured FFT baselines. --- Ix/Aiur/Compiler/Layout.lean | 8 +- Tests/Ix/IxVM.lean | 169 ++++---- Tests/Main.lean | 7 +- crates/aiur/src/call_order.rs | 27 ++ crates/aiur/src/constraints.rs | 82 +++- crates/aiur/src/execute.rs | 9 +- crates/aiur/src/gadgets/bytes2.rs | 9 + crates/aiur/src/lib.rs | 5 + crates/aiur/src/lookup_budget.rs | 34 ++ crates/aiur/src/lookup_shapes.rs | 138 ++++++ crates/aiur/src/memory.rs | 4 +- crates/aiur/src/querymap.rs | 70 +++- crates/aiur/src/row_counts.rs | 210 ++++++++++ crates/aiur/src/synthesis.rs | 113 +++-- crates/aiur/src/synthesis/tests/acceptance.rs | 219 ++++++++++ crates/aiur/src/synthesis/tests/branchless.rs | 124 ++++++ .../aiur/src/synthesis/tests/byte_shapes.rs | 103 +++++ crates/aiur/src/synthesis/tests/call_order.rs | 396 ++++++++++++++++++ .../aiur/src/synthesis/tests/lookup_budget.rs | 115 +++++ .../aiur/src/synthesis/tests/lookup_shapes.rs | 143 +++++++ crates/aiur/src/trace.rs | 49 ++- crates/aiur/src/trace_heights.rs | 37 ++ docs/aiur-soundness.md | 75 ++++ 23 files changed, 2002 insertions(+), 144 deletions(-) create mode 100644 crates/aiur/src/call_order.rs create mode 100644 crates/aiur/src/lookup_budget.rs create mode 100644 crates/aiur/src/lookup_shapes.rs create mode 100644 crates/aiur/src/row_counts.rs create mode 100644 crates/aiur/src/synthesis/tests/acceptance.rs create mode 100644 crates/aiur/src/synthesis/tests/branchless.rs create mode 100644 crates/aiur/src/synthesis/tests/byte_shapes.rs create mode 100644 crates/aiur/src/synthesis/tests/call_order.rs create mode 100644 crates/aiur/src/synthesis/tests/lookup_budget.rs create mode 100644 crates/aiur/src/synthesis/tests/lookup_shapes.rs create mode 100644 crates/aiur/src/trace_heights.rs create mode 100644 docs/aiur-soundness.md diff --git a/Ix/Aiur/Compiler/Layout.lean b/Ix/Aiur/Compiler/Layout.lean index a43f1469b..6676a7dfc 100644 --- a/Ix/Aiur/Compiler/Layout.lean +++ b/Ix/Aiur/Compiler/Layout.lean @@ -109,7 +109,8 @@ structure LayoutMState where degrees : Array Nat @[inline] def LayoutMState.new (inputSize : Nat) : LayoutMState := - ⟨{ inputSize, selectors := 0, auxiliaries := 1, lookups := 0 }, .empty, Array.replicate inputSize 1⟩ + -- Multiplicity plus six rank bytes, with three byte-pair range lookups. + ⟨{ inputSize, selectors := 0, auxiliaries := 7, lookups := 3 }, .empty, Array.replicate inputSize 1⟩ abbrev LayoutM := StateM LayoutMState @@ -174,7 +175,10 @@ def opLayout : Bytecode.Op → LayoutM Unit | .call _ _ outputSize unconstrained => do pushDegrees $ .replicate outputSize 1 bumpAuxiliaries outputSize - if !unconstrained then bumpLookups + if !unconstrained then + -- Callee rank and six bytes for (callee rank - caller rank - 1). + bumpAuxiliaries 7 + bumpLookups 4 | .store values => do pushDegree 1; bumpAuxiliaries; bumpLookups; addMemSize values.size | .load size _ => do diff --git a/Tests/Ix/IxVM.lean b/Tests/Ix/IxVM.lean index 615339efd..d1f74f2f9 100644 --- a/Tests/Ix/IxVM.lean +++ b/Tests/Ix/IxVM.lean @@ -436,91 +436,92 @@ private def nameOfString (str : String) : Lean.Name := /-- Exact FFT-cost pins, one per checked constant. These are equality assertions, not budgets: any kernel change that shifts the cost of a listed constant fails the suite, so a regression cannot land quietly - and an improvement has to be acknowledged by re-pinning. -/ + and an improvement has to be acknowledged by re-pinning. These pins + include the range-checked call ranks that exclude cyclic proof traces. -/ private def kernelCheckEntries : List (String × Nat) := [ - ("HEq", 129_561_906), - ("HEq.rec", 133_623_510), - ("Eq.rec", 133_010_671), - ("Nat", 129_621_454), - ("Nat.add", 170_017_266), - ("Nat.add_comm", 320_320_758), - ("Nat.decEq", 373_889_414), - ("Nat.decLe", 806_851_440), - ("Nat.sub_le_of_le_add", 1_934_072_047), - ("Nat.shiftRight_succ", 1_440_427_524), - ("Trans.mk", 137_030_955), - ("Array.append_assoc", 8_942_722_073), - ("Vector.append", 9_146_677_300), - ("IxVMPrim.nat_add_lit", 212_562_390), - ("IxVMPrim.nat_sub_lit", 227_018_404), - ("IxVMPrim.nat_mul_lit", 203_023_243), - ("IxVMPrim.nat_mul_big", 201_532_839), - ("IxVMPrim.nat_div_lit", 1_404_629_363), - ("IxVMPrim.nat_mod_lit", 1_431_635_704), - ("IxVMPrim.nat_succ_lit", 144_182_615), - ("IxVMPrim.nat_pred_lit", 165_781_989), - ("IxVMPrim.nat_gcd_lit", 2_205_281_085), - ("IxVMPrim.nat_land_lit", 3_614_023_887), - ("IxVMPrim.nat_lor_lit", 3_616_139_531), - ("IxVMPrim.nat_xor_lit", 3_635_365_296), - ("IxVMPrim.nat_shl_lit", 232_546_611), - ("IxVMPrim.nat_shr_lit", 1_419_952_900), - ("IxVMPrim.nat_pow_big", 394_444_673), - ("IxVMPrim.nat_beq_lit", 200_563_953), - ("IxVMPrim.nat_ble_lit", 196_027_245), - ("IxVMPrim.nat_cases_big", 165_979_714), - ("IxVMPrim.nat_dec_le", 824_803_643), - ("IxVMPrim.nat_dec_lt", 836_382_068), - ("IxVMPrim.nat_dec_eq", 413_163_878), - ("IxVMPrim.str_size_lit", 2_535_275_859), - ("IxVMPrim.bv_to_nat_lit", 2_110_179_170), - ("IxVMInd.Even", 206_433_604), - ("IxVMInd.Odd", 206_438_231), - ("IxVMInd.Even.rec", 225_289_131), - ("IxVMInd.Odd.rec", 225_288_202), - ("IxVMInd.IdxTeleN.rec", 160_786_136), - ("IxVMInd.IdxTeleB.rec", 160_784_445), - ("IxVMInd.SoloA.rec", 155_960_075), - ("IxVMInd.SoloB.rec", 155_959_238), - ("IxVMInd.UnsafeSquash", 131_441_226), - ("IxVMInd.Tree", 131_235_133), - ("IxVMInd.Tree.rec", 141_939_288), - ("IxVMInd.DedupM", 134_567_476), - ("IxVMInd.DedupM.rec", 148_905_382), - ("IxVMInd.DepthM", 132_968_937), - ("IxVMInd.DepthM.rec", 144_439_261), - ("String.Internal.append", 2_505_741_376), - ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 3_705_214_978), - ("Lean.Syntax.rec", 2_568_020_495), - ("IxVMInd.AuxTie", 324_084_157), - ("IxVMInd.AuxTie.rec", 369_734_259), - ("IxVMInd.HiddenIdx", 130_534_316), - ("IxVMInd.HiddenIdx.rec", 133_887_001), - ("IxVMInd.thmMajorUse", 513_390_983), - ("IxVMInd.partialKRec", 150_145_230), - ("IxVMInd.deepRebase", 221_120_959), - ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 3_482_661_414), - ("Lean.Widget.TaggedText.rec", 2_537_347_634), - ("Lean.Doc.Part.rec", 2_582_681_092), - ("Lean.Doc.Block.rec", 2_815_192_541), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 132_539_812), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 136_173_435), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 135_089_400), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 135_089_400), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 135_089_400), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 132_835_071), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 144_806_931), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 144_805_348), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 135_089_400), - ("strOfListFoldSize", 2_817_854_521), - ("strOfListFoldSizeAscii", 2_818_697_757), - ("IxVMPrim.lazy_ble_offset", 233_714_099), - ("IxVMPrim.lazy_unit_cast", 552_027_642), - ("IxVMPrim.sizeof_unit", 160_797_387), - ("IxVMPerf.let_continuations", 163_740_427), - ("IxVMPerf.mul_row", 420_640_365), - ("IxVMPerf.context_tower", 514_164_080), - ("IxVMPerf.mul_wide", 266_740_297), + ("HEq", 130_092_790), + ("HEq.rec", 137_362_242), + ("Eq.rec", 136_027_876), + ("Nat", 130_060_261), + ("Nat.add", 197_695_257), + ("Nat.add_comm", 447_620_334), + ("Nat.decEq", 567_581_286), + ("Nat.decLe", 1_315_310_972), + ("Nat.sub_le_of_le_add", 3_328_720_460), + ("Nat.shiftRight_succ", 2_445_999_615), + ("Trans.mk", 145_076_422), + ("Array.append_assoc", 16_621_232_050), + ("Vector.append", 16_965_462_208), + ("IxVMPrim.nat_add_lit", 262_801_388), + ("IxVMPrim.nat_sub_lit", 284_521_561), + ("IxVMPrim.nat_mul_lit", 246_518_065), + ("IxVMPrim.nat_mul_big", 244_385_255), + ("IxVMPrim.nat_div_lit", 2_381_418_249), + ("IxVMPrim.nat_mod_lit", 2_425_927_469), + ("IxVMPrim.nat_succ_lit", 151_050_620), + ("IxVMPrim.nat_pred_lit", 183_486_510), + ("IxVMPrim.nat_gcd_lit", 3_785_736_196), + ("IxVMPrim.nat_land_lit", 6_215_635_638), + ("IxVMPrim.nat_lor_lit", 6_218_494_242), + ("IxVMPrim.nat_xor_lit", 6_246_434_034), + ("IxVMPrim.nat_shl_lit", 291_579_290), + ("IxVMPrim.nat_shr_lit", 2_403_043_114), + ("IxVMPrim.nat_pow_big", 624_316_509), + ("IxVMPrim.nat_beq_lit", 245_012_105), + ("IxVMPrim.nat_ble_lit", 236_989_197), + ("IxVMPrim.nat_cases_big", 184_684_065), + ("IxVMPrim.nat_dec_le", 1_342_961_129), + ("IxVMPrim.nat_dec_lt", 1_361_042_944), + ("IxVMPrim.nat_dec_eq", 628_894_977), + ("IxVMPrim.str_size_lit", 4_285_000_756), + ("IxVMPrim.bv_to_nat_lit", 3_606_708_590), + ("IxVMInd.Even", 251_494_925), + ("IxVMInd.Odd", 251_504_665), + ("IxVMInd.Even.rec", 282_364_930), + ("IxVMInd.Odd.rec", 282_364_002), + ("IxVMInd.IdxTeleN.rec", 177_402_027), + ("IxVMInd.IdxTeleB.rec", 177_400_336), + ("IxVMInd.SoloA.rec", 169_266_008), + ("IxVMInd.SoloB.rec", 169_265_171), + ("IxVMInd.UnsafeSquash", 132_544_402), + ("IxVMInd.Tree", 132_484_806), + ("IxVMInd.Tree.rec", 149_744_671), + ("IxVMInd.DedupM", 136_883_294), + ("IxVMInd.DedupM.rec", 160_258_504), + ("IxVMInd.DepthM", 134_821_747), + ("IxVMInd.DepthM.rec", 154_000_589), + ("String.Internal.append", 4_239_729_239), + ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 6_331_329_170), + ("Lean.Syntax.rec", 4_337_298_464), + ("IxVMInd.AuxTie", 421_081_929), + ("IxVMInd.AuxTie.rec", 496_204_215), + ("IxVMInd.HiddenIdx", 131_311_692), + ("IxVMInd.HiddenIdx.rec", 136_869_443), + ("IxVMInd.thmMajorUse", 803_735_348), + ("IxVMInd.partialKRec", 162_145_600), + ("IxVMInd.deepRebase", 278_922_839), + ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 6_023_770_121), + ("Lean.Widget.TaggedText.rec", 4_295_817_454), + ("Lean.Doc.Part.rec", 4_370_674_121), + ("Lean.Doc.Block.rec", 4_812_252_515), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 134_133_524), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 139_577_096), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 139_282_130), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 139_282_130), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 139_282_130), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 134_632_062), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 153_819_023), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 153_817_441), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 139_282_130), + ("strOfListFoldSize", 4_742_118_434), + ("strOfListFoldSizeAscii", 4_743_185_354), + ("IxVMPrim.lazy_ble_offset", 296_886_064), + ("IxVMPrim.lazy_unit_cast", 853_952_001), + ("IxVMPrim.sizeof_unit", 174_561_290), + ("IxVMPerf.let_continuations", 196_207_899), + ("IxVMPerf.mul_row", 566_690_116), + ("IxVMPerf.context_tower", 866_051_473), + ("IxVMPerf.mul_wide", 379_467_156), ] /-- Variant of `kernelChecks`, pinned to the baseline diff --git a/Tests/Main.lean b/Tests/Main.lean index 3650fcb55..8c2fb2d25 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -273,12 +273,13 @@ def ignoredRunners (env : Lean.Environment) : List (String × IO UInt32) := [ | .ok (_, _, qc) => -- Exact pin, same convention as `kernelCheckEntries` -- (`.round.toUInt64.toNat`): any cost shift must be an - -- explicit, reviewed bump. + -- explicit, reviewed bump. Includes call-order rank columns + -- and their byte-range lookups. let actual := (Aiur.computeStats v2Env.compiled qc v2Env.shapes).totalFftCost.round.toUInt64.toNat pure (LSpec.test - s!"Shard pipeline FFT matches: expected 6_972_965_120, got {actual}" - (actual = 6_972_965_120)) + s!"Shard pipeline FFT matches: expected 10_627_864_237, got {actual}" + (actual = 10_627_864_237)) LSpec.lspecIO (.ofList [("ixvm", [fullSeq, aiurSeq, arenaSeq, exploitSeq, paritySeq, shardSeq])]) []), diff --git a/crates/aiur/src/call_order.rs b/crates/aiur/src/call_order.rs new file mode 100644 index 000000000..214b40aee --- /dev/null +++ b/crates/aiur/src/call_order.rs @@ -0,0 +1,27 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use multi_stark::p3_field::PrimeCharacteristicRing; +use rustc_hash::FxHashMap; + +use crate::G; + +/// Ranks and positive call-order gaps are below 2^48. Their sum is below +/// 2^49, well below the Goldilocks modulus, so an AIR equality cannot wrap. +pub(crate) const RANK_BYTES: usize = 6; +pub(crate) const RANK_BOUND: u64 = 1 << (8 * RANK_BYTES); +pub(crate) const RANK_LOOKUPS: usize = RANK_BYTES / 2; + +/// Extra byte-table queries generated by call-order witnesses. Each worker +/// accumulates locally; the prover merges these before building Bytes2. +pub(crate) type RankRanges = FxHashMap<[u8; 2], G>; + +pub(crate) fn merge_ranges( + mut left: RankRanges, + right: RankRanges, +) -> RankRanges { + for (pair, count) in right { + *left.entry(pair).or_insert(G::ZERO) += count; + } + left +} diff --git a/crates/aiur/src/constraints.rs b/crates/aiur/src/constraints.rs index 8691198b2..b5c784412 100644 --- a/crates/aiur/src/constraints.rs +++ b/crates/aiur/src/constraints.rs @@ -7,6 +7,7 @@ use std::{array, ops::Range, sync::LazyLock}; use crate::{ FxIndexMap, G, bytecode::{Block, Ctrl, Op, Toplevel, ValIdx}, + call_order::{RANK_BYTES, RANK_LOOKUPS}, function_channel, gadgets::{ AiurGadget, @@ -67,9 +68,10 @@ pub struct Constraints { struct ConstraintState { /// Index of the circuit member currently being walked. function_index: G, - /// Exactly one selector: the circuit backs a single function with a - /// single leaf block (no matches), so every lookup slot is written by - /// exactly one branch. + /// Packed 48-bit rank of this row, shared across circuit members. + rank: Expr, + /// One function with terminal control and one selector: operation slots + /// have one writer. Selector count alone does not exclude empty branches. branchless: bool, /// Input size of the current member (inputs live in columns /// `0..input_size` for every member; the circuit reserves the max). @@ -122,6 +124,17 @@ impl ConstraintState { var(self.column - 1) } + fn range_pair(&mut self, sel: &Expr, a: Expr, b: Expr) { + let args = vec![ + self.gate(sel, konst(u8_range_check_channel())), + self.gate(sel, a), + self.gate(sel, b), + ]; + let lookup = self.next_lookup(); + combine_lookup_args(lookup, args); + lookup.multiplicity = lookup.multiplicity.clone() + sel.clone(); + } + fn save(&mut self) -> SharedState { SharedState { column: self.column, @@ -138,6 +151,20 @@ impl ConstraintState { } impl Toplevel { + /// Ungated lookup arguments are safe only with one writer per slot. + /// A branch with no return/yield still writes lookups, so counting the + /// terminal selectors alone does not establish that condition. + pub(crate) fn circuit_is_branchless(&self, circuit_index: usize) -> bool { + let circuit = &self.circuits[circuit_index]; + let [member] = circuit.members.as_slice() else { + return false; + }; + circuit.layout.selectors == 1 + && self.functions.get(*member).is_some_and(|function| { + matches!(function.body.ctrl, Ctrl::Return(..) | Ctrl::Yield(..)) + }) + } + /// Build the constraints of one circuit. The circuit's members are walked /// like branches of a single function: each walk restarts the auxiliary /// column / lookup-slot counters (so members share those, like match arms @@ -158,7 +185,8 @@ impl Toplevel { }; let mut state = ConstraintState { function_index: G::ZERO, - branchless: layout.selectors == 1, + rank: konst(G::ZERO), + branchless: self.circuit_is_branchless(circuit_index), input_size: 0, sel_base: 0, column: 0, @@ -171,8 +199,13 @@ impl Toplevel { // The shared multiplicity column: first auxiliary, right after the // selectors. The return lookup occupies the first lookup slot. let multiplicity = var(layout.input_size + layout.selectors); - state.lookups[0].multiplicity = -multiplicity; + state.lookups[0].multiplicity = -multiplicity.clone(); let aux_start = layout.input_size + layout.selectors + 1; + let rank_bytes: [Expr; RANK_BYTES] = array::from_fn(|i| var(aux_start + i)); + state.rank = + rank_bytes.iter().enumerate().fold(konst(G::ZERO), |acc, (i, byte)| { + acc + byte.clone() * konst(G::from_u64(1 << (8 * i))) + }); let mut sel_base = layout.input_size; let mut circuit_sel = Expr::from(G::ZERO); for &member in &circuit.members { @@ -180,8 +213,8 @@ impl Toplevel { state.function_index = G::from_usize(member); state.input_size = function.layout.input_size; state.sel_base = sel_base; - state.column = aux_start; - state.lookup = 1; + state.column = aux_start + RANK_BYTES; + state.lookup = 1 + RANK_LOOKUPS; state.map.clear(); (0..function.layout.input_size).for_each(|i| state.map.push((var(i), 1))); let body_sel = function.body.get_block_selector(&state); @@ -205,8 +238,19 @@ impl Toplevel { state .constraints .zeros - .push(circuit_sel.clone() * (Expr::from(G::ONE) - circuit_sel)); + .push(circuit_sel.clone() * (Expr::from(G::ONE) - circuit_sel.clone())); + } + // Rank bytes are shared across members and checked once for an active + // circuit row. An inactive row emits no byte-table queries. + state.lookup = 1; + for pair in rank_bytes.as_chunks::<2>().0 { + state.range_pair(&circuit_sel, pair[0].clone(), pair[1].clone()); } + // Only an active member can supply a return lookup. In particular, + // branchless return arguments are ungated, so an inactive row with a + // nonzero multiplicity could otherwise supply an arbitrary result. + // Keep the lookup multiplicity linear and constrain its activity here. + state.constraints.zeros.push(multiplicity * (konst(G::ONE) - circuit_sel)); (state.constraints, state.lookups) } } @@ -312,6 +356,9 @@ impl Ctrl { args.extend( values.iter().map(|arg| state.gate(&sel, state.map[*arg].0.clone())), ); + // The public root rank is zero. Lookup compression zero-pads short + // messages, preserving the public claim's existing byte encoding. + args.push(state.gate(&sel, state.rank.clone())); let lookup = &mut state.lookups[0]; combine_lookup_args(lookup, args); // multiplicity is already set @@ -462,9 +509,28 @@ impl Op { lookup_args .extend(output.into_iter().map(|col| state.gate(sel, col))); + let callee_rank = state.next_auxiliary(); + lookup_args.push(state.gate(sel, callee_rank.clone())); + let lookup = state.next_lookup(); combine_lookup_args(lookup, lookup_args); lookup.multiplicity = lookup.multiplicity.clone() + sel.clone(); + + let gap_bytes: [Expr; RANK_BYTES] = + array::from_fn(|_| state.next_auxiliary()); + let gap = gap_bytes.iter().enumerate().fold( + konst(G::ZERO), + |acc, (i, byte)| { + acc + byte.clone() * konst(G::from_u64(1 << (8 * i))) + }, + ); + state.constraints.zeros.push( + sel.clone() + * (callee_rank - state.rank.clone() - konst(G::ONE) - gap), + ); + for pair in gap_bytes.as_chunks::<2>().0 { + state.range_pair(sel, pair[0].clone(), pair[1].clone()); + } } }, Op::Store(values) => { diff --git a/crates/aiur/src/execute.rs b/crates/aiur/src/execute.rs index cfa91823c..11bbfb8fe 100644 --- a/crates/aiur/src/execute.rs +++ b/crates/aiur/src/execute.rs @@ -1,6 +1,7 @@ use multi_stark::p3_field::{Field, PrimeCharacteristicRing, PrimeField64}; use rustc_hash::FxHashMap; use std::collections::hash_map::Entry; +use std::sync::{Arc, atomic::AtomicU64}; use crate::{ FxIndexMap, G, @@ -37,10 +38,11 @@ pub struct QueryRecord { impl QueryRecord { pub fn new(toplevel: &Toplevel) -> Self { + let clock = Arc::new(AtomicU64::new(0)); let function_queries = toplevel .functions .iter() - .map(|f| QueryMap::new(f.layout.input_size)) + .map(|f| QueryMap::new_function(f.layout.input_size, Arc::clone(&clock))) .collect(); let memory_queries = toplevel .memory_sizes @@ -1094,14 +1096,15 @@ fn build_klimbs_u64( /// Approximate retained bytes of a record's query maps: field elements /// (keys + outputs) at 8 bytes plus ~21 bytes of per-entry index -/// overhead (hash-table slot, stored hash, multiplicity). Feeds the +/// overhead (hash-table slot, stored hash, multiplicity), and 8 bytes per +/// function entry for completion order. Feeds the /// witness phase of the prover RAM model /// ([`crate::synthesis::AiurSystem::peak_prove_bytes`]). pub fn record_retained_bytes(record: &QueryRecord) -> usize { let mut elems = 0usize; let mut entries = 0usize; for m in &record.function_queries { - elems += m.retained_elems(); + elems += m.retained_elems() + m.len(); entries += m.len(); } for (_, m) in &record.memory_queries { diff --git a/crates/aiur/src/gadgets/bytes2.rs b/crates/aiur/src/gadgets/bytes2.rs index e013a6a34..189f42edb 100644 --- a/crates/aiur/src/gadgets/bytes2.rs +++ b/crates/aiur/src/gadgets/bytes2.rs @@ -424,6 +424,15 @@ impl Bytes2Queries { self.bump_multiplicity_for(i, j, 6) } + pub(crate) fn add_rank_ranges( + &mut self, + ranges: crate::call_order::RankRanges, + ) { + for ([i, j], count) in ranges { + self.0[256 * usize::from(i) + usize::from(j)][6] += count; + } + } + pub(crate) fn bump_mul(&mut self, i: &G, j: &G) { self.bump_multiplicity_for(i, j, 7) } diff --git a/crates/aiur/src/lib.rs b/crates/aiur/src/lib.rs index 3acf6666a..d2459b459 100644 --- a/crates/aiur/src/lib.rs +++ b/crates/aiur/src/lib.rs @@ -1,11 +1,16 @@ pub mod bytecode; +mod call_order; pub mod constraints; pub mod execute; pub mod gadgets; +mod lookup_budget; +mod lookup_shapes; pub mod memory; pub mod querymap; +mod row_counts; pub mod synthesis; pub mod trace; +mod trace_heights; pub mod vk_codec; use indexmap::IndexMap; diff --git a/crates/aiur/src/lookup_budget.rs b/crates/aiur/src/lookup_budget.rs new file mode 100644 index 000000000..023d466c1 --- /dev/null +++ b/crates/aiur/src/lookup_budget.rs @@ -0,0 +1,34 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use multi_stark::p3_field::PrimeField64; + +use crate::G; + +/// Upper bound on unit lookup consumers: one public claim plus every +/// lookup slot of every active trace row. Provider slots also count, making +/// this conservative without relying on witness multiplicities. Degrees +/// are indexed by active position; slot counts use canonical circuit order. +/// Reject malformed alignment and any bound reaching the characteristic. +pub(crate) fn lookup_query_bound( + slot_counts: impl ExactSizeIterator, + active: &[bool], + log_degrees: &[u8], +) -> Option { + if slot_counts.len() != active.len() || !active.contains(&true) { + return None; + } + let mut degrees = log_degrees.iter(); + let mut total = 1_u64; + for (slots, &is_active) in slot_counts.zip(active) { + if is_active { + let height = 1_u64.checked_shl(u32::from(*degrees.next()?))?; + let count = height.checked_mul(u64::try_from(slots).ok()?)?; + total = total.checked_add(count)?; + if total >= G::ORDER_U64 { + return None; + } + } + } + degrees.next().is_none().then_some(total) +} diff --git a/crates/aiur/src/lookup_shapes.rs b/crates/aiur/src/lookup_shapes.rs new file mode 100644 index 000000000..a361b01bf --- /dev/null +++ b/crates/aiur/src/lookup_shapes.rs @@ -0,0 +1,138 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Structural checks required by zero-padded function lookup messages. +//! Inputs, outputs and the final rank have no separators in the message. +//! Their boundaries must agree at every constrained call and public claim. + +use multi_stark::p3_field::PrimeField64; + +use crate::{ + G, + bytecode::{Block, Ctrl, Op, Toplevel}, + function_channel, +}; + +fn canonical_size(size: usize) -> bool { + u64::try_from(size).is_ok_and(|size| size < G::ORDER_U64) +} + +impl Block { + /// Every function return, including an early return from a continuation + /// arm, has this output arity. Yields return to their own continuation. + pub(crate) fn returns_have_size(&self, size: usize) -> bool { + match &self.ctrl { + Ctrl::Return(_, values) => values.len() == size, + Ctrl::Yield(..) => true, + Ctrl::Match(_, branches, fallback) => { + branches.values().all(|block| block.returns_have_size(size)) + && fallback.as_ref().is_none_or(|block| block.returns_have_size(size)) + }, + Ctrl::MatchContinue(_, branches, fallback, _, _, _, continuation) => { + branches.values().all(|block| block.returns_have_size(size)) + && fallback.as_ref().is_none_or(|block| block.returns_have_size(size)) + && continuation.returns_have_size(size) + }, + } + } + + fn check_lookup_shapes( + &self, + program: &Toplevel, + yield_size: Option, + ) -> Result<(), &'static str> { + for op in &self.ops { + match op { + Op::Call(index, inputs, outputs, false) => { + let Some(callee) = program.functions.get(*index) else { + return Err("constrained call refers to a missing function"); + }; + if !callee.constrained { + return Err("constrained call refers to an unconstrained function"); + } + if callee.layout.input_size != inputs.len() { + return Err("constrained call input arity differs from its callee"); + } + if !callee.body.returns_have_size(*outputs) { + return Err( + "constrained call output arity differs from its callee", + ); + } + }, + Op::Store(values) if !canonical_size(values.len()) => { + return Err("memory width is not a canonical field element"); + }, + Op::Load(size, _) if !canonical_size(*size) => { + return Err("memory width is not a canonical field element"); + }, + _ => {}, + } + } + match &self.ctrl { + Ctrl::Return(..) => {}, + Ctrl::Yield(_, values) => { + if yield_size != Some(values.len()) { + return Err("yield arity differs from its enclosing continuation"); + } + }, + Ctrl::Match(_, branches, fallback) => { + for block in branches.values() { + block.check_lookup_shapes(program, yield_size)?; + } + if let Some(block) = fallback { + block.check_lookup_shapes(program, yield_size)?; + } + }, + Ctrl::MatchContinue(_, branches, fallback, size, _, _, continuation) => { + for block in branches.values() { + block.check_lookup_shapes(program, Some(*size))?; + } + if let Some(block) = fallback { + block.check_lookup_shapes(program, Some(*size))?; + } + continuation.check_lookup_shapes(program, yield_size)?; + }, + } + Ok(()) + } +} + +impl Toplevel { + /// Check the static boundaries of all constrained function messages. + /// This does not check value indices, layouts or arithmetic constraints. + pub fn validate_lookup_shapes(&self) -> Result<(), &'static str> { + if !canonical_size(self.functions.len()) { + return Err("function index domain exceeds the field characteristic"); + } + if self.memory_sizes.iter().any(|&size| !canonical_size(size)) { + return Err("memory width is not a canonical field element"); + } + for function in &self.functions { + if function.constrained { + function.body.check_lookup_shapes(self, None)?; + } + } + Ok(()) + } + + pub(crate) fn valid_claim_shape(&self, claim: &[G]) -> bool { + let [channel, index, arguments @ ..] = claim else { + return false; + }; + if *channel != function_channel() { + return false; + } + let Ok(index) = usize::try_from(index.as_canonical_u64()) else { + return false; + }; + let Some(function) = self.functions.get(index) else { + return false; + }; + function.entry + && function.constrained + && arguments.len() >= function.layout.input_size + && function + .body + .returns_have_size(arguments.len() - function.layout.input_size) + } +} diff --git a/crates/aiur/src/memory.rs b/crates/aiur/src/memory.rs index c3fd487d0..64dc80ea1 100644 --- a/crates/aiur/src/memory.rs +++ b/crates/aiur/src/memory.rs @@ -46,7 +46,7 @@ impl Memory { } let width = Self::width(size); // pull = negated multiplicity. - let lookups = vec![Lookup { multiplicity: -multiplicity, args }]; + let lookups = vec![Lookup { multiplicity: -multiplicity.clone(), args }]; // Transition constraints (formerly the `Air::eval` body): the selector is // boolean; a real next row implies a real current row; and the pointer @@ -59,6 +59,8 @@ impl Memory { let is_real_transition = is_real_next * Expr::IsTransition; let constraints = vec![ is_real.clone() * (is_real.clone() - one()), + // Padding cannot supply a memory lookup with nonzero multiplicity. + multiplicity * (one() - is_real.clone()), is_real_transition.clone() * (is_real - one()), is_real_transition * (ptr + one() - ptr_next), ]; diff --git a/crates/aiur/src/querymap.rs b/crates/aiur/src/querymap.rs index c82df6928..9cc8997cd 100644 --- a/crates/aiur/src/querymap.rs +++ b/crates/aiur/src/querymap.rs @@ -1,12 +1,17 @@ use multi_stark::p3_field::{PrimeCharacteristicRing, PrimeField64}; +use std::sync::{ + Arc, + atomic::{AtomicU64, Ordering}, +}; -use crate::G; +use crate::{G, call_order::RANK_BOUND}; /// Immutable view of one query entry. #[derive(Clone, Copy)] pub struct QueryRef<'a> { pub(crate) output: &'a [G], pub multiplicity: G, + pub(crate) rank: u64, } /// Mutable view of one query entry: the output is fixed at insertion, @@ -215,6 +220,10 @@ impl SegU64s { self.segs[i >> SEG_BITS].slice(i & SEG_MASK, 1)[0] } + fn set(&mut self, i: usize, value: u64) { + self.segs[i >> SEG_BITS].slice_mut(i & SEG_MASK, 1)[0] = value; + } + #[inline] fn push(&mut self, h: u64) { let seg = self.entries >> SEG_BITS; @@ -226,6 +235,30 @@ impl SegU64s { } } +/// Shared completion order across function maps. Memory maps omit it. +/// Reverse completion order gives the root rank zero and every constrained +/// callee a strictly greater rank than its caller. +struct CompletionOrder { + clock: Arc, + times: SegU64s, +} + +impl CompletionOrder { + fn next(&self) -> u64 { + let time = self.clock.fetch_add(1, Ordering::Relaxed); + assert!( + time < RANK_BOUND, + "function completion count exceeds 48-bit rank bound" + ); + time + } + + fn rank(&self, i: usize) -> u64 { + let last = self.clock.load(Ordering::Relaxed) - 1; + last - self.times.at(i) + } +} + /// Append-only query store with a hash index. /// /// Functionally the insertion-ordered map `args -> (output, multiplicity)` @@ -252,6 +285,7 @@ pub struct QueryMap { mults: SegStore, hashes: SegU64s, table: hashbrown::HashTable, + completion: Option, } impl QueryMap { @@ -263,9 +297,20 @@ impl QueryMap { mults: SegStore::new(1), hashes: SegU64s::new(), table: hashbrown::HashTable::new(), + completion: None, } } + pub(crate) fn new_function(key_stride: usize, clock: Arc) -> Self { + let mut map = Self::new(key_stride); + map.completion = Some(CompletionOrder { clock, times: SegU64s::new() }); + map + } + + fn rank_at(&self, i: usize) -> u64 { + self.completion.as_ref().map_or(0, |order| order.rank(i)) + } + #[inline] pub fn len(&self) -> usize { self.mults.entries @@ -296,6 +341,7 @@ impl QueryMap { Some(QueryRef { output: self.outs.at(i), multiplicity: self.mults.at(i)[0], + rank: self.rank_at(i), }) } @@ -334,6 +380,12 @@ impl QueryMap { debug_assert_eq!(self.outs.at(i), output); if constrained { self.bump_multiplicity(i); + // Promotion executes/promotes children first, so its new completion + // time must follow them even when the hint entry was inserted early. + if let Some(order) = &mut self.completion { + let time = order.next(); + order.times.set(i, time); + } } } else { self.insert(key, output, G::from_bool(constrained)); @@ -358,6 +410,10 @@ impl QueryMap { self.outs.push(output); self.mults.push(&[multiplicity]); self.hashes.push(hash); + if let Some(order) = &mut self.completion { + let time = order.next(); + order.times.push(time); + } let hashes = &self.hashes; self.table.insert_unique(hash, i, |&j| hashes.at(j as usize)); } @@ -377,7 +433,11 @@ impl QueryMap { } Some(( self.keys.at(i), - QueryRef { output: self.outs.at(i), multiplicity: self.mults.at(i)[0] }, + QueryRef { + output: self.outs.at(i), + multiplicity: self.mults.at(i)[0], + rank: self.rank_at(i), + }, )) } @@ -385,7 +445,11 @@ impl QueryMap { (0..self.len()).map(|i| { ( self.keys.at(i), - QueryRef { output: self.outs.at(i), multiplicity: self.mults.at(i)[0] }, + QueryRef { + output: self.outs.at(i), + multiplicity: self.mults.at(i)[0], + rank: self.rank_at(i), + }, ) }) } diff --git a/crates/aiur/src/row_counts.rs b/crates/aiur/src/row_counts.rs new file mode 100644 index 000000000..76cb19d1c --- /dev/null +++ b/crates/aiur/src/row_counts.rs @@ -0,0 +1,210 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Witness-independent bounds for branch selection and terminal counts. +//! Every return/yield allocates a selector, including consumed yields. + +use multi_stark::p3_field::PrimeField64; + +use crate::{ + G, + bytecode::{Block, Circuit, Ctrl, Toplevel}, +}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub(crate) struct ControlCounts { + pub(crate) nodes: usize, + pub(crate) leaves: usize, + pub(crate) returns: usize, + pub(crate) yields: usize, +} + +impl ControlCounts { + fn checked_add(self, other: Self) -> Option { + Some(Self { + nodes: self.nodes.checked_add(other.nodes)?, + leaves: self.leaves.checked_add(other.leaves)?, + returns: self.returns.checked_add(other.returns)?, + yields: self.yields.checked_add(other.yields)?, + }) + } + + fn branches<'a>(blocks: impl Iterator) -> Option { + let mut counts = Self::default(); + for block in blocks { + counts = counts.checked_add(block.control_counts()?)?; + } + counts.nodes = counts.nodes.checked_add(1)?; + Some(counts) + } + + fn continued(self, continuation: Self) -> Option { + Some(Self { + nodes: self.nodes.checked_add(continuation.nodes)?, + leaves: self.leaves.checked_add(continuation.leaves)?, + returns: self.returns.checked_add(continuation.returns)?, + yields: continuation.yields, + }) + } +} + +impl Block { + pub(crate) fn control_counts(&self) -> Option { + match &self.ctrl { + Ctrl::Return(..) => { + Some(ControlCounts { nodes: 1, leaves: 1, returns: 1, yields: 0 }) + }, + Ctrl::Yield(..) => { + Some(ControlCounts { nodes: 1, leaves: 1, returns: 0, yields: 1 }) + }, + Ctrl::Match(_, branches, fallback) => { + ControlCounts::branches(branches.values().chain(fallback.as_deref())) + }, + Ctrl::MatchContinue(_, branches, fallback, _, _, _, continuation) => { + ControlCounts::branches(branches.values().chain(fallback.as_deref()))? + .continued(continuation.control_counts()?) + }, + } + } +} + +fn canonical_count(count: usize) -> bool { + u64::try_from(count).is_ok_and(|count| count < G::ORDER_U64) +} + +impl Circuit { + pub(crate) fn validate_row_counts( + &self, + program: &Toplevel, + ) -> Result<(), &'static str> { + if !canonical_count(self.members.len()) { + return Err("circuit member count exceeds the field characteristic"); + } + let mut leaves = 0usize; + for &index in &self.members { + let Some(function) = program.functions.get(index) else { + return Err("circuit refers to a missing function"); + }; + let Some(counts) = function.body.control_counts() else { + return Err("function control count overflows"); + }; + if !canonical_count(counts.nodes) { + return Err("function control count exceeds the field characteristic"); + } + leaves = leaves + .checked_add(counts.leaves) + .ok_or("circuit leaf count overflows")?; + } + if leaves > self.layout.selectors { + return Err("circuit has fewer selectors than return/yield leaves"); + } + Ok(()) + } +} + +impl Toplevel { + pub fn validate_row_counts(&self) -> Result<(), &'static str> { + for circuit in &self.circuits { + circuit.validate_row_counts(self)?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use multi_stark::{ + p3_field::PrimeCharacteristicRing, + types::{CommitmentParameters, FriParameters}, + }; + + use super::*; + use crate::{ + FxIndexMap, + bytecode::{Function, FunctionLayout}, + synthesis::AiurSystem, + }; + + fn continued_body() -> Block { + let mut branches = FxIndexMap::default(); + branches + .insert(G::ZERO, Block { ops: vec![], ctrl: Ctrl::Return(0, vec![]) }); + branches + .insert(G::ONE, Block { ops: vec![], ctrl: Ctrl::Yield(1, vec![]) }); + Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + branches, + None, + 0, + 0, + 0, + Box::new(Block { ops: vec![], ctrl: Ctrl::Return(2, vec![]) }), + ), + } + } + + fn continued_program(selectors: usize) -> Toplevel { + let layout = + FunctionLayout { input_size: 1, selectors, auxiliaries: 7, lookups: 4 }; + Toplevel { + functions: vec![Function { + body: continued_body(), + layout, + entry: true, + constrained: true, + }], + memory_sizes: vec![], + circuits: vec![Circuit { members: vec![0], layout }], + } + } + + #[test] + fn counts_include_consumed_yields_and_empty_matches() { + assert_eq!( + continued_body().control_counts(), + Some(ControlCounts { nodes: 4, leaves: 3, returns: 2, yields: 0 }) + ); + let empty = + Block { ops: vec![], ctrl: Ctrl::Match(0, FxIndexMap::default(), None) }; + assert_eq!( + empty.control_counts(), + Some(ControlCounts { nodes: 1, ..ControlCounts::default() }) + ); + assert!(continued_program(3).validate_row_counts().is_ok()); + assert!(continued_program(2).validate_row_counts().is_err()); + assert!(continued_program(1).validate_row_counts().is_err()); + } + + #[test] + fn count_bounds_reject_machine_overflow_and_field_wrap() { + let maximal = ControlCounts { nodes: usize::MAX, ..Default::default() }; + let one = ControlCounts { nodes: 1, ..Default::default() }; + assert!(maximal.checked_add(one).is_none()); + assert!(maximal.continued(one).is_none()); + if let Ok(order) = usize::try_from(G::ORDER_U64) { + assert!(canonical_count(order - 1)); + assert!(!canonical_count(order)); + assert!(!canonical_count(usize::MAX)); + } + } + + #[test] + #[should_panic(expected = "invalid Aiur control counts")] + fn system_construction_rejects_missing_leaf_selectors() { + let top = continued_program(1); + top.validate_lookup_shapes().unwrap(); + AiurSystem::build( + top, + CommitmentParameters { log_blowup: 1, cap_height: 0 }, + FriParameters { + log_final_poly_len: 0, + max_log_arity: 1, + num_queries: 64, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + }, + ); + } +} diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index ae7e2ac89..f32d90b6c 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -20,7 +20,9 @@ use crate::{ execute::{ExecError, IOBuffer, QueryRecord}, function_channel, gadgets::{AiurGadget, bytes1::Bytes1, bytes2::Bytes2}, + lookup_budget::lookup_query_bound, memory::Memory, + trace_heights::fixed_trace_heights, }; /// The concrete STARK configuration Aiur instantiates multi-stark with. @@ -134,6 +136,8 @@ impl AiurSystem { commitment_parameters: CommitmentParameters, fri_parameters: FriParameters, ) -> Self { + toplevel.validate_lookup_shapes().expect("invalid Aiur lookup shapes"); + toplevel.validate_row_counts().expect("invalid Aiur control counts"); let mut circuit_inputs: Vec> = Vec::new(); let mut slot_widths: Vec> = Vec::new(); @@ -164,7 +168,7 @@ impl AiurSystem { // superposed arguments are degree 2, and grouping would push the // logUp constraints past the quotient budget. let group_size = - if toplevel.circuits[i].layout.selectors == 1 && lookups.len() >= 2 { + if toplevel.circuit_is_branchless(i) && lookups.len() >= 2 { 2 } else { 1 @@ -404,11 +408,14 @@ impl AiurSystem { fun_idx: FunIdx, input: &[G], io_buffer: &IOBuffer, - query_record: QueryRecord, + mut query_record: QueryRecord, output: &[G], ) -> (Vec, AiurProof) { let _g = tracing::info_span!("aiur/witness").entered(); - let circuit_types = self.circuit_types(); + let mut circuit_types = self.circuit_types(); + // Function traces supply call-order range queries. Bytes2 consumes the + // merged counts after the other circuits finish their parallel work. + assert!(matches!(circuit_types.pop(), Some(CircuitType::Bytes2))); let witness_data = circuit_types .into_par_iter() .enumerate() @@ -422,19 +429,33 @@ impl AiurSystem { &slot_arg_widths, ), CircuitType::Memory { width } => { - Memory::witness_data(width, &query_record, &slot_arg_widths) + let (trace, lookups) = + Memory::witness_data(width, &query_record, &slot_arg_widths); + (trace, lookups, crate::call_order::RankRanges::default()) }, CircuitType::Bytes1 => { - Bytes1.witness_data(&query_record, &slot_arg_widths) + let (trace, lookups) = + Bytes1.witness_data(&query_record, &slot_arg_widths); + (trace, lookups, crate::call_order::RankRanges::default()) }, CircuitType::Bytes2 => { - Bytes2.witness_data(&query_record, &slot_arg_widths) + unreachable!("Bytes2 is built after rank queries") }, } }) .collect::>(); + let mut traces = Vec::with_capacity(witness_data.len() + 1); + let mut lookups = Vec::with_capacity(witness_data.len() + 1); + for (trace, lookup, ranges) in witness_data { + traces.push(trace); + lookups.push(lookup); + query_record.bytes2_queries.add_rank_ranges(ranges); + } + let (trace, lookup) = + Bytes2.witness_data(&query_record, &self.slot_arg_widths(traces.len())); + traces.push(trace); + lookups.push(lookup); drop(query_record); // Early drop to free memory. - let (traces, lookups) = witness_data.into_iter().unzip(); let witness = SystemWitness { traces, lookups }; drop(_g); @@ -574,6 +595,25 @@ impl AiurSystem { claim: &[G], proof: &AiurProof, ) -> Result<(), VerificationError> { + if !self.toplevel.valid_claim_shape(claim) { + return Err(VerificationError::InvalidClaim); + } + if !fixed_trace_heights( + self.system.circuits.iter().map(|circuit| circuit.preprocessed_height), + &proof.active, + &proof.log_degrees, + ) { + return Err(VerificationError::InvalidProofShape); + } + if lookup_query_bound( + self.slot_widths.iter().map(Vec::len), + &proof.active, + &proof.log_degrees, + ) + .is_none() + { + return Err(VerificationError::InvalidProofShape); + } self.system.verify(claim, proof) } @@ -591,6 +631,13 @@ impl AiurSystem { #[cfg(test)] mod tests { + mod acceptance; + mod branchless; + mod byte_shapes; + mod call_order; + mod lookup_budget; + mod lookup_shapes; + use super::*; use crate::{ bytecode::{Block, Ctrl, Function, FunctionLayout, Op, Toplevel}, @@ -636,12 +683,12 @@ mod tests { /// Layout — matched against how `constraints.rs`/`trace.rs` walk the block: /// - `input_size = 2`: the two inputs `a`, `b`. /// - `selectors = 1`: the single `Return` (selector index 0). - /// - `auxiliaries = 2`: the multiplicity column (allocated first for every - /// function) plus one auxiliary for the `Mul` — `a` and `b` each have + /// - `auxiliaries = 8`: multiplicity, six rank bytes and one auxiliary + /// for the `Mul` — `a` and `b` each have /// degree 1, so `a*b` has degree 2 and `constraints.rs` spills it into a /// fresh auxiliary column pinned by `sel * (col - a*b)`. - /// - `lookups = 1`: the function-provide (return) lookup in slot 0, which - /// pulls the claim `[function_channel, fun_idx, a, b, a*b]`. + /// - `lookups = 4`: the function return in slot 0, followed by three rank + /// range lookups. Rank zero preserves the public multiplication claim. /// /// Test-side singleton partition (production circuits come pre-built from /// the Lean compiler). @@ -669,8 +716,8 @@ mod tests { layout: FunctionLayout { input_size: 2, selectors: 1, - auxiliaries: 2, - lookups: 1, + auxiliaries: 8, + lookups: 4, }, entry: true, constrained: true, @@ -688,8 +735,8 @@ mod tests { layout: FunctionLayout { input_size: 2, selectors: 1, - auxiliaries: 5, - lookups: 3, + auxiliaries: 11, + lookups: 6, }, entry: true, constrained: true, @@ -733,7 +780,7 @@ mod tests { /// - `f` (idx 0, entry): `f(a, b) = g(a) * b`, but routing `b` through /// memory so the memory path is live: /// - `Call(1, [a], 1, false)` → `g(a)` at value idx 2, allocating one - /// output auxiliary + one function-channel lookup slot. + /// output auxiliary, seven order auxiliaries and four lookup slots. /// - `Store([b])` → pointer at value idx 3, allocating one pointer /// auxiliary + one memory-channel lookup slot (multiplicity pushed). /// - `Load(1, 3)` → the loaded `b` at value idx 4, allocating one value @@ -746,15 +793,15 @@ mod tests { /// the block: /// - `input_size = 2` (`a`, `b`). /// - `selectors = 1` (the single `Return`). - /// - `auxiliaries = 5`: multiplicity(1) + call output(1) + store ptr(1) + - /// load value(1) + mul spill(1). - /// - `lookups = 4`: return(slot 0) + call(1) + store(1) + load(1). + /// - `auxiliaries = 18`: multiplicity(1), rank bytes(6), call output(1), + /// call order(7), store pointer(1), load value(1), multiplication(1). + /// - `lookups = 10`: return(1), rank ranges(3), call/order(4), memory(2). /// /// - `g` (idx 1): `g(x) = x + 1`: /// - `Const(1)` at value idx 1, `Add(0, 1)` at value idx 2, /// `Return(0, [2])`. `Const`/`Add` allocate no auxiliaries. - /// - Layout: `input_size = 1`, `selectors = 1`, `auxiliaries = 1` - /// (multiplicity only), `lookups = 1` (return only). + /// - Layout: `input_size = 1`, `selectors = 1`, `auxiliaries = 7` + /// (multiplicity and rank), `lookups = 4` (return and rank ranges). /// /// `memory_sizes = [1]`: a memory of size-1 values, which materializes one /// `Memory` circuit. The single `Store` inserts the entry (memory @@ -777,8 +824,8 @@ mod tests { layout: FunctionLayout { input_size: 2, selectors: 1, - auxiliaries: 5, - lookups: 4, + auxiliaries: 18, + lookups: 10, }, entry: true, constrained: true, @@ -793,8 +840,8 @@ mod tests { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 1, - lookups: 1, + auxiliaries: 7, + lookups: 4, }, entry: false, constrained: true, @@ -857,8 +904,8 @@ mod tests { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 3, - lookups: 2, + auxiliaries: 16, + lookups: 8, }, entry: true, constrained: true, @@ -872,8 +919,8 @@ mod tests { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 2, - lookups: 2, + auxiliaries: 15, + lookups: 8, }, entry: false, constrained: true, @@ -887,8 +934,8 @@ mod tests { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 1, - lookups: 1, + auxiliaries: 7, + lookups: 4, }, entry: false, constrained: true, @@ -968,8 +1015,8 @@ mod tests { // Function circuits: main width = inputs + selectors + auxiliaries, no // preprocessed matrix. - assert_eq!(shapes[0].main_width, 2 + 1 + 5); - assert_eq!(shapes[1].main_width, 1 + 1 + 1); + assert_eq!(shapes[0].main_width, 2 + 1 + 18); + assert_eq!(shapes[1].main_width, 1 + 1 + 7); // Memory of size 1: multiplicity + selector + pointer + 1 value. assert_eq!(shapes[2].main_width, 3 + 1); for shape in &shapes[..3] { diff --git a/crates/aiur/src/synthesis/tests/acceptance.rs b/crates/aiur/src/synthesis/tests/acceptance.rs new file mode 100644 index 000000000..d40eb9683 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/acceptance.rs @@ -0,0 +1,219 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use multi_stark::eval::{VarValues, eval_expr}; + +fn values<'a>(row: &'a [G], next: &'a [G]) -> VarValues<'a, G> { + VarValues { + preprocessed: [&[], &[]], + main: [row, next], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ONE, + is_last_row: G::ZERO, + is_transition: G::ONE, + } +} + +/// Retain the entry singleton and group the nested callees, whose auxiliary +/// and lookup widths differ and whose selectors occupy separate columns. +fn grouped_promotion_toplevel() -> Toplevel { + let mut top = unconstrained_call_promotion_toplevel(); + top.circuits.truncate(1); + top.circuits.push(crate::bytecode::Circuit { + members: vec![1, 2], + layout: FunctionLayout { + input_size: 1, + selectors: 2, + auxiliaries: 15, + lookups: 8, + }, + }); + top +} + +#[test] +fn inactive_function_multiplicity_is_constrained_in_every_partition() { + for mut top in [mul_toplevel(), grouped_promotion_toplevel()] { + // Generate a concrete active row for each member. Entry visibility is + // only an executor guard and does not alter these AIR constraints. + for function in &mut top.functions { + function.entry = true; + } + for (idx, circuit) in top.circuits.iter().enumerate() { + let (constraints, lookups) = top.build_constraints(idx); + let mut row = vec![G::ZERO; constraints.width]; + let multiplicity = circuit.layout.input_size + circuit.layout.selectors; + for nonzero in [G::ONE, -G::ONE, G::from_u8(7)] { + row[multiplicity] = nonzero; + assert!( + constraints + .zeros + .iter() + .any(|c| eval_expr(c, &values(&row, &row)) != G::ZERO), + "inactive circuit {idx} accepted multiplicity {nonzero}" + ); + // Every fixture member has one return selector. Activating any + // member must permit the multiplicity, including the later members + // of a group. These are local constraint checks; the roundtrip + // below also checks global lookup balance for an honest execution. + for &member in &circuit.members { + assert_eq!(top.functions[member].layout.selectors, 1); + let mut io_buffer = empty_io_buffer(); + let input = vec![G::ZERO; top.functions[member].layout.input_size]; + let (record, _) = top.execute(member, input, &mut io_buffer).unwrap(); + let widths = + lookups.iter().map(|lookup| lookup.args.len()).collect::>(); + let (trace, _, _) = + top.witness_data(idx, &record, &io_buffer, &widths); + let mut active = trace.values[..constraints.width].to_vec(); + active[multiplicity] = nonzero; + assert!( + constraints + .zeros + .iter() + .all(|c| eval_expr(c, &values(&active, &active)) == G::ZERO), + "active member {member} rejected multiplicity {nonzero}" + ); + } + } + row[multiplicity] = G::ZERO; + assert!( + constraints + .zeros + .iter() + .all(|c| eval_expr(c, &values(&row, &row)) == G::ZERO) + ); + } + } +} + +#[test] +fn inactive_memory_multiplicity_is_constrained() { + for width in [1, 4, 8] { + let (memory, constraints, _) = Memory::build(width); + let mut row = vec![G::ZERO; memory.width]; + let next = row.clone(); + for nonzero in [G::ONE, -G::ONE, G::from_u8(7)] { + row[0] = nonzero; + assert!( + constraints + .iter() + .any(|c| eval_expr(c, &values(&row, &next)) != G::ZERO) + ); + row[1] = G::ONE; + assert!( + constraints + .iter() + .all(|c| eval_expr(c, &values(&row, &next)) == G::ZERO) + ); + row[1] = G::ZERO; + } + row[0] = G::ZERO; + assert!( + constraints.iter().all(|c| eval_expr(c, &values(&row, &next)) == G::ZERO) + ); + } +} + +#[test] +fn active_grouped_returns_verify() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(grouped_promotion_toplevel(), cp, fp); + let input = [G::from_u8(3)]; + let (claim, proof) = system.prove(0, &input, &mut empty_io_buffer()); + assert_eq!( + claim, + vec![function_channel(), G::ZERO, input[0], input[0] + G::ONE] + ); + system.verify(&claim, &proof).expect("active grouped returns must verify"); +} + +/// Exercise the public verifier with supplied trace rows, independently of +/// the execution record. A successful honest execution alone cannot check +/// whether inactive rows are permitted to provide a function result. +#[test] +fn inactive_return_cannot_supply_claim() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(mul_toplevel(), cp, fp); + let a = G::from_u8(3); + let b = G::from_u8(5); + let wrong_result = G::from_u8(16); + assert_ne!(a * b, wrong_result); + let claim = vec![function_channel(), G::ZERO, a, b, wrong_result]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(i, shape)| { + let height = if i == 0 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if i == 0 { + // Inputs, inactive selector, return multiplicity, six rank bytes, + // then unconstrained product advice. + rows[..4].copy_from_slice(&[a, b, G::ZERO, G::ONE]); + rows[10] = wrong_result; + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "an inactive function row supplied an incorrect public result" + ); +} + +/// A function that only calls itself has no finite execution. Its return +/// lookup must not be justified by the same row's recursive call lookup. +#[test] +fn recursive_cycle_cannot_supply_claim() { + let function = Function { + body: Block { + ops: vec![Op::Call(0, vec![0], 1, false)], + ctrl: Ctrl::Return(0, vec![1]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 15, + lookups: 8, + }, + entry: true, + constrained: true, + }; + let top = with_singleton_circuits(vec![function], vec![]); + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(top, cp, fp); + let input = G::from_u8(3); + let output = G::from_u8(7); + let claim = vec![function_channel(), G::ZERO, input, output]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(i, shape)| { + let height = if i == 0 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if i == 0 { + // One active row provides twice: once to its own recursive call, + // and once to the public claim. No evaluator is used. + rows[..3].copy_from_slice(&[input, G::ONE, G::from_u8(2)]); + rows[9] = output; + } else if i == system.toplevel.circuits.len() + 1 { + // Six zero-byte pairs: three for the row rank and three for the + // call gap. Balance these lookups so rejection tests call order. + rows[6] = G::from_u8(6); + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "a recursive cycle supplied a public return value without a finite execution" + ); +} diff --git a/crates/aiur/src/synthesis/tests/branchless.rs b/crates/aiur/src/synthesis/tests/branchless.rs new file mode 100644 index 000000000..3cac25114 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/branchless.rs @@ -0,0 +1,124 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use crate::FxIndexMap; +use multi_stark::eval::{VarValues, eval_expr}; + +fn empty_branch_toplevel() -> Toplevel { + let dead = Block { + ops: vec![Op::Store(vec![])], + ctrl: Ctrl::Match(0, FxIndexMap::default(), None), + }; + let called = Block { + ops: vec![Op::Call(1, vec![], 1, false)], + ctrl: Ctrl::Return(0, vec![1]), + }; + let caller = Function { + body: Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + [(G::ZERO, dead), (G::ONE, called)].into_iter().collect(), + None, + ), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 15, + lookups: 8, + }, + entry: true, + constrained: true, + }; + let callee = Function { + body: Block { + ops: vec![Op::Const(G::ONE)], + ctrl: Ctrl::Return(0, vec![0]), + }, + layout: FunctionLayout { + input_size: 0, + selectors: 1, + auxiliaries: 7, + lookups: 4, + }, + entry: false, + constrained: true, + }; + with_singleton_circuits(vec![caller, callee], vec![0, 1]) +} + +#[test] +fn empty_branch_preserves_honest_execution() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(empty_branch_toplevel(), cp, fp); + let (claim, proof) = system.prove(0, &[G::ONE], &mut empty_io_buffer()); + assert_eq!(claim, vec![function_channel(), G::ZERO, G::ONE, G::ONE]); + system.verify(&claim, &proof).unwrap(); +} + +/// A zero-leaf branch can still emit a lookup. Its inactive store must not +/// turn the selected call's function channel into a memory channel merely +/// because the entire circuit has one return selector. +#[test] +fn empty_branch_cannot_redirect_a_call_to_memory() { + let top = empty_branch_toplevel(); + top.validate_lookup_shapes().unwrap(); + top.validate_row_counts().unwrap(); + assert!(!top.circuit_is_branchless(0)); + assert!(top.circuit_is_branchless(1)); + let (_, expected) = + top.execute(0, vec![G::ONE], &mut empty_io_buffer()).unwrap(); + assert_eq!(expected, vec![G::ONE]); + let forged = G::from_u8(7); + assert_ne!(expected, vec![forged]); + let (constraints, lookups) = top.build_constraints(0); + let mut row = vec![G::ZERO; constraints.width]; + row[0] = G::ONE; + row[1] = G::ONE; + row[2] = G::ONE; + row[9] = forged; + row[10] = G::ONE; + let values = VarValues { + preprocessed: [&[], &[]], + main: [&row, &row], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ONE, + is_last_row: G::ZERO, + is_transition: G::ONE, + }; + assert!(constraints.zeros.iter().all(|c| eval_expr(c, &values) == G::ZERO)); + let combined: Vec<_> = + lookups[4].args.iter().map(|arg| eval_expr(arg, &values)).collect(); + assert_eq!(combined, vec![function_channel(), G::ONE, forged, G::ONE]); + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(top, cp, fp); + let claim = vec![function_channel(), G::ZERO, G::ONE, forged]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(index, shape)| { + let height = if index < 4 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if index == 0 { + rows[..shape.main_width].copy_from_slice(&row); + } else if index == 3 { + // Supply the redirected memory lookup, with no callee row. + rows[..4].copy_from_slice(&[G::ONE, G::ONE, forged + forged, G::ONE]); + } else if index == 5 { + // The caller's root rank and all three call-gap pairs are zero. + rows[6] = G::from_u8(6); + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "an inactive empty branch redirected a call to memory and supplied a false public result" + ); +} diff --git a/crates/aiur/src/synthesis/tests/byte_shapes.rs b/crates/aiur/src/synthesis/tests/byte_shapes.rs new file mode 100644 index 000000000..e980fa2e5 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/byte_shapes.rs @@ -0,0 +1,103 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; + +fn fixed(heights: &[usize], active: &[bool], degrees: &[u8]) -> bool { + fixed_trace_heights(heights.iter().copied(), active, degrees) +} + +#[test] +fn fixed_heights_follow_active_positions_and_require_fixed_tables() { + assert!(fixed(&[], &[], &[])); + assert!(fixed(&[0, 0], &[false, false], &[])); + assert!(fixed(&[0, 256, 0, 65536], &[true, true, false, true], &[3, 8, 16])); + assert!(fixed(&[0, 256, 0, 65536], &[false, true, false, true], &[8, 16])); + // The separate global budget guard bounds unfixed circuit degrees. + assert!(fixed(&[0], &[true], &[255])); + for (heights, active, degrees) in [ + (vec![256, 65536], vec![false, false], vec![]), + (vec![], vec![false], vec![]), + (vec![256], vec![], vec![]), + (vec![256], vec![true], vec![]), + (vec![256], vec![false], vec![8]), + (vec![256], vec![true], vec![7]), + (vec![256], vec![true], vec![9]), + (vec![65536], vec![true], vec![15]), + (vec![65536], vec![true], vec![17]), + (vec![256, 65536], vec![true, true], vec![16, 8]), + (vec![256, 65536], vec![false, true], vec![8, 16]), + (vec![usize::MAX], vec![true], vec![255]), + ] { + assert!(!fixed(&heights, &active, °rees)); + } +} + +#[test] +fn public_verify_checks_fixed_byte_heights_before_openings() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(mul_toplevel(), cp, fp); + let (claim, mut proof) = + system.prove(0, &[G::ONE, G::ONE], &mut empty_io_buffer()); + system.verify(&claim, &proof).unwrap(); + let mut position = 0; + for (circuit, &active) in system.system.circuits.iter().zip(&proof.active) { + if active { + let original = proof.log_degrees[position]; + if circuit.preprocessed_height != 0 { + for changed in [original - 1, original + 1] { + proof.log_degrees[position] = changed; + // The generic shape check has no direct fixed-height condition. + // Aiur must establish it before relying on fixed byte-table rows. + system.system.verify_shape(&proof).unwrap(); + assert!(matches!( + system.verify(&claim, &proof), + Err(VerificationError::InvalidProofShape) + )); + } + } + proof.log_degrees[position] = original; + position += 1; + } + } + system.verify(&claim, &proof).unwrap(); +} + +#[test] +fn public_verify_checks_fixed_byte_activity_before_openings() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(mul_toplevel(), cp, fp); + let claim = [function_channel(), G::ZERO, G::ONE, G::ONE, G::ONE]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(index, shape)| { + let height = if index == 0 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if index == 0 { + rows[..4].fill(G::ONE); + rows[10] = G::ONE; + } else if index == 2 { + rows[6] = G::from_u8(3); + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let mut witness = SystemWitness::from_stage_1(traces, &system.system); + // There are no unary-byte queries. The generic shape check permits + // omission, but the PCS rejects a matrix without opening points. Aiur + // makes the required activity explicit before entering that verifier. + witness.traces[1].values.clear(); + witness.lookups[1] = + multi_stark::lookup::LookupValues::builder(0, &system.slot_arg_widths(1)) + .finish(); + let proof = system.system.prove(&system.key, &claim, witness); + assert_eq!(proof.active, vec![true, false, true]); + assert_eq!(proof.log_degrees, vec![2, 16]); + system.system.verify_shape(&proof).unwrap(); + assert!(matches!( + system.verify(&claim, &proof), + Err(VerificationError::InvalidProofShape) + )); +} diff --git a/crates/aiur/src/synthesis/tests/call_order.rs b/crates/aiur/src/synthesis/tests/call_order.rs new file mode 100644 index 000000000..d005e3fcc --- /dev/null +++ b/crates/aiur/src/synthesis/tests/call_order.rs @@ -0,0 +1,396 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use crate::call_order::{RANK_BOUND, RANK_BYTES, RankRanges}; +use multi_stark::eval::{VarValues, eval_expr}; + +fn cycle_toplevel(grouped: bool) -> Toplevel { + // Public f calls g; g and h call each other without a base case. + let functions = [1, 2, 1] + .into_iter() + .enumerate() + .map(|(i, callee)| Function { + body: Block { + ops: vec![Op::Call(callee, vec![0], 1, false)], + ctrl: Ctrl::Return(0, vec![1]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 15, + lookups: 8, + }, + entry: i == 0, + constrained: true, + }) + .collect(); + let mut top = with_singleton_circuits(functions, vec![]); + if grouped { + top.circuits.truncate(1); + top.circuits.push(crate::bytecode::Circuit { + members: vec![1, 2], + layout: FunctionLayout { + input_size: 1, + selectors: 2, + auxiliaries: 15, + lookups: 8, + }, + }); + } + top +} + +fn fill_bytes(row: &mut [G], value: u64, ranges: &mut RankRanges) { + assert!(value < RANK_BOUND); + let bytes = value.to_le_bytes(); + for (field, byte) in row.iter_mut().zip(&bytes[..RANK_BYTES]) { + *field = G::from_u8(*byte); + } + for pair in bytes[..RANK_BYTES].as_chunks::<2>().0 { + *ranges.entry([pair[0], pair[1]]).or_insert(G::ZERO) += G::ONE; + } +} + +fn row_values(row: &[G]) -> VarValues<'_, G> { + VarValues { + preprocessed: [&[], &[]], + main: [row, row], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ONE, + is_last_row: G::ZERO, + is_transition: G::ONE, + } +} + +fn normalized(mut args: Vec) -> Vec { + while args.last() == Some(&G::ZERO) { + args.pop(); + } + args +} + +/// Verify exact tuple balance independently of random lookup compression. +fn assert_lookup_balance( + top: &Toplevel, + traces: &[RowMajorMatrix], + ranges: &RankRanges, + claim: &[G], +) { + let mut balance = FxHashMap::, G>::default(); + *balance.entry(normalized(claim.to_vec())).or_insert(G::ZERO) += G::ONE; + for (i, circuit) in top.circuits.iter().enumerate() { + let (_, lookups) = top.build_constraints(i); + for row in traces[i].values.chunks_exact(circuit.layout.width()) { + let values = row_values(row); + for lookup in &lookups { + let args = + lookup.args.iter().map(|arg| eval_expr(arg, &values)).collect(); + *balance.entry(normalized(args)).or_insert(G::ZERO) += + eval_expr(&lookup.multiplicity, &values); + } + } + } + for ([a, b], count) in ranges { + *balance + .entry(normalized(vec![ + crate::u8_range_check_channel(), + G::from_u8(*a), + G::from_u8(*b), + ])) + .or_insert(G::ZERO) -= *count; + } + assert!( + balance.values().all(|count| *count == G::ZERO), + "unbalanced supplied witness" + ); +} + +#[test] +fn mutual_cycles_reject_with_balanced_lookups_in_both_partitions() { + for grouped in [false, true] { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(cycle_toplevel(grouped), cp, fp); + let input = G::from_u8(3); + let output = G::from_u8(7); + let claim = vec![function_channel(), G::ZERO, input, output]; + let mut ranges = RankRanges::default(); + let mut traces = Vec::new(); + let mut violated = 0; + for (i, shape) in system.circuit_shapes().iter().enumerate() { + let is_function = i < system.toplevel.circuits.len(); + let height = if is_function { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if is_function { + let circuit = &system.toplevel.circuits[i]; + let (constraints, _) = system.toplevel.build_constraints(i); + for (offset, &member) in circuit.members.iter().enumerate() { + let row = &mut rows + [offset * shape.main_width..(offset + 1) * shape.main_width]; + row[0] = input; + row[1 + offset] = G::ONE; + let aux = 1 + circuit.layout.selectors; + row[aux] = if member == 1 { G::from_u8(2) } else { G::ONE }; + fill_bytes(&mut row[aux + 1..aux + 7], member as u64, &mut ranges); + row[aux + 7] = output; + row[aux + 8] = + G::from_usize(if member == 2 { 1 } else { member + 1 }); + let gap = if member == 2 { RANK_BOUND - 2 } else { 0 }; + fill_bytes(&mut row[aux + 9..aux + 15], gap, &mut ranges); + violated += constraints + .zeros + .iter() + .filter(|expr| eval_expr(expr, &row_values(row)) != G::ZERO) + .count(); + } + } else if i == system.toplevel.circuits.len() + 1 { + // Bytes2 is the last circuit (there are no memories). + for ([a, b], count) in &ranges { + rows[(256 * usize::from(*a) + usize::from(*b)) * shape.main_width + + 6] = *count; + } + } + traces.push(RowMajorMatrix::new(rows, shape.main_width)); + } + assert_eq!( + violated, 1, + "only the closing h -> g call should violate a polynomial" + ); + assert_lookup_balance(&system.toplevel, &traces, &ranges, &claim); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "cyclic return accepted (grouped={grouped})" + ); + } +} + +#[test] +fn call_order_polynomial_checks_strict_unsigned_order() { + let top = cycle_toplevel(false); + let (constraints, _) = top.build_constraints(0); + for (parent, child, gap, accepted) in [ + (0, 1, 0, true), + (0, RANK_BOUND - 1, RANK_BOUND - 2, true), + (RANK_BOUND - 2, RANK_BOUND - 1, 0, true), + (0, 0, 0, false), + (1, 0, RANK_BOUND - 2, false), + (RANK_BOUND - 1, 0, 0, false), + ] { + let mut row = vec![G::ZERO; constraints.width]; + let mut ranges = RankRanges::default(); + row[1] = G::ONE; + row[2] = G::ONE; + fill_bytes(&mut row[3..9], parent, &mut ranges); + row[10] = G::from_u64(child); + fill_bytes(&mut row[11..17], gap, &mut ranges); + let satisfied = constraints + .zeros + .iter() + .all(|expr| eval_expr(expr, &row_values(&row)) == G::ZERO); + assert_eq!(satisfied, accepted, "ranks {parent} -> {child}, gap {gap}"); + } +} + +#[test] +fn out_of_range_gaps_cannot_hide_a_cycle_in_field_arithmetic() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(cycle_toplevel(false), cp, fp); + let claim = vec![function_channel(), G::ZERO, G::from_u8(3), G::from_u8(7)]; + let traces = + system + .circuit_shapes() + .iter() + .enumerate() + .map(|(i, shape)| { + let mut rows = vec![ + G::ZERO; + if i < 3 { + 4 * shape.main_width + } else { + shape.preprocessed_height * shape.main_width + } + ]; + if i < 3 { + rows[0] = claim[2]; + rows[1] = G::ONE; + rows[2] = G::from_u8(if i == 1 { 2 } else { 1 }); + rows[9] = claim[3]; + // All ranks are zero. A forged "byte" -1 makes 0 - 0 - 1 - gap + // vanish as a field expression, but cannot pass the byte table. + rows[11] = -G::ONE; + let (constraints, _) = system.toplevel.build_constraints(i); + assert!(constraints.zeros.iter().all(|expr| eval_expr( + expr, + &row_values(&rows[..shape.main_width]) + ) == G::ZERO)); + } else if i == 4 { + // Five valid zero-byte pairs per function, plus one impossible + // (-1, 0) pair. Supply every valid pair and no fabricated table row. + rows[6] = G::from_u8(15); + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "unbounded gap allowed cyclic justification" + ); +} + +#[test] +fn out_of_range_function_rank_is_rejected_by_the_byte_table() { + let mut top = cycle_toplevel(false); + top.functions.truncate(2); + top.circuits.truncate(2); + top.functions[1].body = Block { + ops: vec![Op::Const(G::from_u8(7))], + ctrl: Ctrl::Return(0, vec![1]), + }; + top.functions[1].layout.auxiliaries = 7; + top.functions[1].layout.lookups = 4; + top.circuits[1].layout = top.functions[1].layout; + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(top, cp, fp); + let claim = vec![function_channel(), G::ZERO, G::from_u8(3), G::from_u8(7)]; + let traces = + system + .circuit_shapes() + .iter() + .enumerate() + .map(|(i, shape)| { + let mut rows = vec![ + G::ZERO; + if i < 2 { + 4 * shape.main_width + } else { + shape.preprocessed_height * shape.main_width + } + ]; + if i < 2 { + rows[0] = claim[2]; + rows[1] = G::ONE; + rows[2] = G::ONE; + if i == 0 { + rows[9] = claim[3]; + rows[10] = G::from_u64(RANK_BOUND); + rows[11..17].fill(G::from_u8(255)); + } else { + // 256 in the high byte packs to 2^48. The edge's field equality + // and all ordinary constraints hold; the rank range check must fail. + rows[8] = G::from_u64(256); + } + let (constraints, _) = system.toplevel.build_constraints(i); + assert!(constraints.zeros.iter().all(|expr| eval_expr( + expr, + &row_values(&rows[..shape.main_width]) + ) == G::ZERO)); + } else if i == 3 { + rows[6] = G::from_u8(5); + rows[(256 * 255 + 255) * shape.main_width + 6] = G::from_u8(3); + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "unbounded function rank accepted" + ); +} + +#[test] +fn finite_recursive_calls_verify() { + let base = Block { + ops: vec![Op::Const(G::from_u8(7))], + ctrl: Ctrl::Return(0, vec![1]), + }; + let step = Block { + ops: vec![Op::Const(G::ONE), Op::Sub(0, 1), Op::Call(0, vec![2], 1, false)], + ctrl: Ctrl::Return(1, vec![3]), + }; + let function = Function { + body: Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + [(G::ZERO, base)].into_iter().collect(), + Some(Box::new(step)), + ), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 2, + auxiliaries: 16, + lookups: 8, + }, + entry: true, + constrained: true, + }; + let (cp, fp) = test_parameters(); + let system = + AiurSystem::build(with_singleton_circuits(vec![function], vec![]), cp, fp); + for n in [0, 1, 7] { + let (claim, proof) = + system.prove(0, &[G::from_u8(n)], &mut empty_io_buffer()); + assert_eq!( + claim, + vec![function_channel(), G::ZERO, G::from_u8(n), G::from_u8(7)] + ); + system.verify(&claim, &proof).expect("finite recursion must verify"); + } +} + +#[test] +fn shared_callee_keeps_one_consistent_rank() { + let root = Function { + body: Block { + ops: vec![ + Op::Call(1, vec![0], 1, false), + Op::Call(1, vec![0], 1, false), + Op::Add(1, 2), + ], + ctrl: Ctrl::Return(0, vec![3]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 23, + lookups: 12, + }, + entry: true, + constrained: true, + }; + let leaf = Function { + body: Block { + ops: vec![Op::Const(G::ONE), Op::Add(0, 1)], + ctrl: Ctrl::Return(0, vec![2]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 7, + lookups: 4, + }, + entry: false, + constrained: true, + }; + let (cp, fp) = test_parameters(); + let system = AiurSystem::build( + with_singleton_circuits(vec![root, leaf], vec![]), + cp, + fp, + ); + let (claim, proof) = + system.prove(0, &[G::from_u8(3)], &mut empty_io_buffer()); + assert_eq!( + claim, + vec![function_channel(), G::ZERO, G::from_u8(3), G::from_u8(8)] + ); + system.verify(&claim, &proof).expect("shared callee must verify"); +} diff --git a/crates/aiur/src/synthesis/tests/lookup_budget.rs b/crates/aiur/src/synthesis/tests/lookup_budget.rs new file mode 100644 index 000000000..a4fc44cb8 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/lookup_budget.rs @@ -0,0 +1,115 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; + +fn bound(slots: &[usize], active: &[bool], degrees: &[u8]) -> Option { + lookup_query_bound(slots.iter().copied(), active, degrees) +} + +#[test] +fn query_budget_uses_canonical_slots_and_active_heights() { + assert_eq!( + bound(&[2, 999, 3, 999], &[true, false, true, false], &[4, 5]), + Some(129) + ); + assert_eq!( + bound(&[999, 3, 999, 2], &[false, true, false, true], &[5, 4]), + Some(129) + ); + assert_eq!(bound(&[0], &[true], &[0]), Some(1)); + assert_eq!(bound(&[1], &[true], &[63]), Some((1_u64 << 63) + 1)); +} + +#[test] +fn query_budget_rejects_malformed_alignment_and_shifts() { + for (slots, active, degrees) in [ + (vec![], vec![], vec![]), + (vec![1], vec![false], vec![]), + (vec![1], vec![], vec![]), + (vec![], vec![true], vec![0]), + (vec![1, 2], vec![true], vec![0]), + (vec![1], vec![true, false], vec![0]), + (vec![1], vec![true], vec![]), + (vec![1], vec![true], vec![0, 0]), + (vec![1, 2], vec![false, true], vec![0, 0]), + ] { + assert_eq!(bound(&slots, &active, °rees), None); + } + for degree in 64..=255 { + for slots in [0, 1, usize::MAX] { + assert_eq!(bound(&[slots], &[true], &[degree]), None); + } + } +} + +#[cfg(target_pointer_width = "64")] +#[test] +fn query_budget_checks_the_global_sum_and_both_overflows() { + use multi_stark::p3_field::PrimeField64; + let p = usize::try_from(G::ORDER_U64).unwrap(); + assert_eq!(bound(&[p - 2], &[true], &[0]), Some(G::ORDER_U64 - 1)); + assert_eq!(bound(&[p - 1], &[true], &[0]), None); + assert_eq!( + bound(&[p - 3, 1], &[true, true], &[0, 0]), + Some(G::ORDER_U64 - 1) + ); + assert_eq!(bound(&[p - 3, 2], &[true, true], &[0, 0]), None); + assert_eq!(bound(&[usize::MAX], &[true], &[1]), None); + assert_eq!(bound(&[usize::MAX], &[true], &[0]), None); + assert_eq!(bound(&[1, usize::MAX], &[true, false], &[0]), Some(2)); + let slots = (p - 2) >> 31; + assert!(bound(&[slots], &[true], &[31]).is_some()); + assert_eq!(bound(&[slots + 1], &[true], &[31]), None); +} + +#[test] +fn public_verify_checks_lookup_metadata() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(mul_toplevel(), cp, fp); + let (claim, mut proof) = + system.prove(0, &[G::ONE, G::ONE], &mut empty_io_buffer()); + system.verify(&claim, &proof).unwrap(); + assert!( + lookup_query_bound( + system.slot_widths.iter().map(Vec::len), + &proof.active, + &proof.log_degrees + ) + .is_some() + ); + let degrees = proof.log_degrees.clone(); + for malformed in + [vec![], vec![0; degrees.len() + 1], vec![255; degrees.len()]] + { + proof.log_degrees = malformed; + assert!(matches!( + system.verify(&claim, &proof), + Err(VerificationError::InvalidProofShape) + )); + } + proof.log_degrees = degrees; + let active = proof.active.clone(); + for malformed in + [vec![], vec![false; active.len()], vec![true; active.len() + 1]] + { + proof.active = malformed; + assert!(matches!( + system.verify(&claim, &proof), + Err(VerificationError::InvalidProofShape) + )); + } + proof.active = active; + system.verify(&claim, &proof).unwrap(); +} + +#[test] +fn serialized_key_maximum_lookup_budget_fits_characteristic() { + use multi_stark::p3_field::PrimeField64; + let slots = vec![65535; 65535]; + let active = vec![true; 65535]; + let degrees = vec![32; 65535]; + let maximum = 1 + 65535_u64.pow(2) * (1_u64 << 32); + assert!(maximum < G::ORDER_U64); + assert_eq!(bound(&slots, &active, °rees), Some(maximum)); +} diff --git a/crates/aiur/src/synthesis/tests/lookup_shapes.rs b/crates/aiur/src/synthesis/tests/lookup_shapes.rs new file mode 100644 index 000000000..9d92bc356 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/lookup_shapes.rs @@ -0,0 +1,143 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; + +/// The public claim omits rank zero. A short return at rank seven must not +/// be interpreted as a public return value of seven through zero padding. +#[test] +fn public_output_cannot_be_supplied_by_a_displaced_rank() { + let function = Function { + body: Block { ops: vec![], ctrl: Ctrl::Return(0, vec![]) }, + layout: FunctionLayout { + input_size: 0, + selectors: 1, + auxiliaries: 7, + lookups: 4, + }, + entry: true, + constrained: true, + }; + let (cp, fp) = test_parameters(); + let system = + AiurSystem::build(with_singleton_circuits(vec![function], vec![]), cp, fp); + let claim = [function_channel(), G::ZERO, G::from_u8(7)]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(index, shape)| { + let height = if index == 0 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if index == 0 { + // Active empty return, multiplicity one, rank seven. + rows[..3].copy_from_slice(&[G::ONE, G::ONE, G::from_u8(7)]); + } else if index == 2 { + // All three rank pairs are supplied by the fixed byte table. + rows[6] = G::from_u8(2); + rows[(7 * 256) * shape.main_width + 6] = G::ONE; + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "a call-order rank was accepted as a function output" + ); +} + +#[test] +fn public_claim_shape_checks_channel_visibility_and_arity() { + let top = mul_toplevel(); + assert!(top.valid_claim_shape(&[G::ZERO, G::ZERO, G::ONE, G::ONE, G::ONE])); + for claim in [ + vec![], + vec![G::ZERO], + vec![G::ONE, G::ZERO, G::ONE, G::ONE, G::ONE], + vec![G::ZERO, G::ONE, G::ONE, G::ONE, G::ONE], + vec![G::ZERO, G::ZERO, G::ONE], + vec![G::ZERO, G::ZERO, G::ONE, G::ONE], + vec![G::ZERO, G::ZERO, G::ONE, G::ONE, G::ONE, G::ZERO], + ] { + assert!(!top.valid_claim_shape(&claim)); + } + for constrained in [true, false] { + let mut top = mul_toplevel(); + top.functions[0].entry = !constrained; + top.functions[0].constrained = constrained; + assert!(!top.valid_claim_shape(&[G::ZERO; 5])); + } +} + +#[test] +fn constrained_calls_check_both_message_boundaries() { + let top = call_and_memory_toplevel(); + top.validate_lookup_shapes().unwrap(); + for malformed in [ + Op::Call(1, vec![], 1, false), + Op::Call(1, vec![0], 0, false), + Op::Call(1, vec![0], 2, false), + Op::Call(99, vec![0], 1, false), + ] { + let mut top = call_and_memory_toplevel(); + top.functions[0].body.ops.push(malformed); + assert!(top.validate_lookup_shapes().is_err()); + } + let mut top = call_and_memory_toplevel(); + top.functions[1].constrained = false; + assert!(top.validate_lookup_shapes().is_err()); + // An unconstrained call supplies advice and emits no function lookup. + let mut top = mul_toplevel(); + top.functions[0].body.ops.push(Op::Call(99, vec![], 17, true)); + top.validate_lookup_shapes().unwrap(); +} + +#[test] +fn nested_continuations_check_returns_and_yields() { + fn returning(size: usize) -> Block { + Block { ops: vec![], ctrl: Ctrl::Return(0, vec![0; size]) } + } + fn yielding(size: usize) -> Block { + Block { ops: vec![], ctrl: Ctrl::Yield(0, vec![0; size]) } + } + fn continuation(arm: Block, continued: Block) -> Block { + Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + [(G::ZERO, arm)].into_iter().collect(), + Some(Box::new(yielding(2))), + 2, + 0, + 0, + Box::new(continued), + ), + } + } + for arm in [returning(1), yielding(2)] { + let body = continuation(arm, returning(1)); + assert!(body.returns_have_size(1)); + assert!(!body.returns_have_size(0)); + let mut top = mul_toplevel(); + top.functions[0].body = body; + top.validate_lookup_shapes().unwrap(); + } + assert!(!continuation(returning(0), returning(1)).returns_have_size(1)); + assert!(!continuation(yielding(2), returning(0)).returns_have_size(1)); + for body in [ + yielding(2), + continuation(yielding(1), returning(1)), + continuation(yielding(2), yielding(2)), + continuation(continuation(yielding(2), yielding(1)), returning(1)), + ] { + let mut top = mul_toplevel(); + top.functions[0].body = body; + assert!(top.validate_lookup_shapes().is_err()); + } + let mut top = mul_toplevel(); + top.functions[0].body = + continuation(continuation(returning(1), yielding(2)), returning(1)); + top.validate_lookup_shapes().unwrap(); +} diff --git a/crates/aiur/src/trace.rs b/crates/aiur/src/trace.rs index 66e88cf92..957c4900a 100644 --- a/crates/aiur/src/trace.rs +++ b/crates/aiur/src/trace.rs @@ -13,6 +13,7 @@ use rayon::{ use crate::{ FxIndexMap, G, bytecode::{Block, Ctrl, Function, FunctionLayout, Op, Toplevel}, + call_order::{RANK_BOUND, RANK_BYTES, RankRanges, merge_ranges}, execute::{ IOBuffer, IOKeyInfo, QueryRecord, find_unconstrained_big_uint_div_mod, g_inverse_value, @@ -37,6 +38,7 @@ struct ColumnMutSlice<'a, 'b> { selectors: &'a mut [G], auxiliaries: &'a mut [G], lookups: &'a mut LookupRowMut<'b, G>, + rank_ranges: &'a mut RankRanges, } type Degree = u8; @@ -66,6 +68,7 @@ impl<'a, 'b> ColumnMutSlice<'a, 'b> { sel_offset: usize, slice: &'a mut [G], lookups: &'a mut LookupRowMut<'b, G>, + rank_ranges: &'a mut RankRanges, ) -> Self { let (inputs, slice) = slice.split_at_mut(circuit_layout.input_size); let (selectors, auxiliaries) = slice.split_at_mut(circuit_layout.selectors); @@ -73,7 +76,7 @@ impl<'a, 'b> ColumnMutSlice<'a, 'b> { let inputs = &mut inputs[..function.layout.input_size]; let selectors = &mut selectors[sel_offset..sel_offset + function.layout.selectors]; - Self { inputs, selectors, auxiliaries, lookups } + Self { inputs, selectors, auxiliaries, lookups, rank_ranges } } fn push_auxiliary(&mut self, index: &mut ColumnIndex, t: G) { @@ -90,12 +93,29 @@ impl<'a, 'b> ColumnMutSlice<'a, 'b> { self.lookups.push(index.lookup, multiplicity, args); index.lookup += 1; } + + fn push_rank_bytes(&mut self, index: &mut ColumnIndex, rank: u64) { + assert!(rank < RANK_BOUND, "call-order rank exceeds 48 bits"); + let bytes = rank.to_le_bytes(); + for &byte in &bytes[..RANK_BYTES] { + self.push_auxiliary(index, G::from_u8(byte)); + } + for pair in bytes[..RANK_BYTES].as_chunks::<2>().0 { + self.push_lookup( + index, + G::ONE, + &[u8_range_check_channel(), G::from_u8(pair[0]), G::from_u8(pair[1])], + ); + *self.rank_ranges.entry([pair[0], pair[1]]).or_insert(G::ZERO) += G::ONE; + } + } } #[derive(Clone, Copy)] struct TraceContext<'a> { function_index: G, multiplicity: G, + rank: u64, inputs: &'a [G], output: &'a [G], query_record: &'a QueryRecord, @@ -113,13 +133,13 @@ struct RowMeta<'a> { } impl Toplevel { - pub fn witness_data( + pub(crate) fn witness_data( &self, circuit_index: usize, query_record: &QueryRecord, io_buffer: &IOBuffer, slot_arg_widths: &[usize], - ) -> (RowMajorMatrix, LookupValues) { + ) -> (RowMajorMatrix, LookupValues, RankRanges) { let circuit = &self.circuits[circuit_index]; let layout = &circuit.layout; let width = layout.width(); @@ -157,11 +177,11 @@ impl Toplevel { // rows need no writes at all. let mut builder = LookupValues::builder(height, slot_arg_widths); let mut row_writers = builder.rows_mut(); - rows_no_padding + let rank_ranges = rows_no_padding .par_chunks_mut(width) .zip(row_writers[..height_no_padding].par_iter_mut()) .enumerate() - .for_each(|(i, (row, lookups))| { + .fold(RankRanges::default, |mut rank_ranges, (i, (row, lookups))| { let meta = &rows_meta[i]; let index = &mut ColumnIndex { auxiliary: 0, @@ -174,19 +194,23 @@ impl Toplevel { meta.sel_offset, row, lookups, + &mut rank_ranges, ); let context = TraceContext { function_index: meta.function_index, inputs: meta.inputs, multiplicity: meta.result.multiplicity, + rank: meta.result.rank, output: meta.result.output, query_record, }; meta.function.populate_row(index, slice, context, io_buffer); - }); + rank_ranges + }) + .reduce(RankRanges::default, merge_ranges); drop(row_writers); let trace = RowMajorMatrix::new(rows, width); - (trace, builder.finish()) + (trace, builder.finish(), rank_ranges) } } @@ -217,6 +241,7 @@ impl Function { .for_each(|(i, arg)| slice.inputs[i] = *arg); // Push the multiplicity slice.push_auxiliary(index, context.multiplicity); + slice.push_rank_bytes(index, context.rank); let _ = self.body.populate_row(map, index, slice, context, io_buffer); } } @@ -279,6 +304,7 @@ impl Ctrl { context.function_index, context.inputs, context.output, + context.rank, ); // The first lookup slot is reserved for the function return, which // pulls the query claim with the query's multiplicity. @@ -391,8 +417,15 @@ impl Op { G::from_usize(*function_index), &inputs, result.output, + result.rank, ); + slice.push_auxiliary(index, G::from_u64(result.rank)); slice.push_lookup(index, G::ONE, &args); + let gap = result + .rank + .checked_sub(context.rank + 1) + .expect("constrained call does not increase rank"); + slice.push_rank_bytes(index, gap); } }, Op::Store(values) => { @@ -696,9 +729,11 @@ fn function_lookup_args( function_index: G, inputs: &[G], output: &[G], + rank: u64, ) -> Vec { let mut args = vec![function_channel(), function_index]; args.extend(inputs); args.extend(output); + args.push(G::from_u64(rank)); args } diff --git a/crates/aiur/src/trace_heights.rs b/crates/aiur/src/trace_heights.rs new file mode 100644 index 000000000..7c758a137 --- /dev/null +++ b/crates/aiur/src/trace_heights.rs @@ -0,0 +1,37 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +/// Match active-order degrees to canonical fixed preprocessed heights. +/// Zero denotes a circuit without a fixed height; inactive unfixed circuits +/// consume no degree. Fixed circuits must be active. This check precedes PCS +/// verification so fixed-table extraction +/// has an explicit height condition at the Aiur verifier boundary. +pub(crate) fn fixed_trace_heights( + heights: impl ExactSizeIterator, + active: &[bool], + log_degrees: &[u8], +) -> bool { + if heights.len() != active.len() { + return false; + } + let mut degrees = log_degrees.iter(); + for (height, &is_active) in heights.zip(active) { + if height != 0 && !is_active { + return false; + } + if is_active { + let Some(°ree) = degrees.next() else { + return false; + }; + if height != 0 { + let Some(actual) = 1_u64.checked_shl(u32::from(degree)) else { + return false; + }; + if u64::try_from(height) != Ok(actual) { + return false; + } + } + } + } + degrees.next().is_none() +} diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md new file mode 100644 index 000000000..7cc97ba22 --- /dev/null +++ b/docs/aiur-soundness.md @@ -0,0 +1,75 @@ +# Aiur verifier soundness repairs + +Aiur's verifier must reject a false result even when a prover supplies trace +rows directly, without running the interpreter. The regressions in +`crates/aiur/src/synthesis/tests/` exercise four failures at that boundary. + +| Failure | Required invariant | Regression | +| --- | --- | --- | +| An inactive function row supplied a public proof of `3 * 5 = 16`. | Function and memory rows satisfy `multiplicity * (1 - selector) = 0`. | [Inactive rows](../crates/aiur/src/synthesis/tests/acceptance.rs) | +| Self-recursive and mutually recursive rows balanced their own calls without a finite execution. | Every constrained call strictly increases a range-checked rank. | [Self recursion](../crates/aiur/src/synthesis/tests/acceptance.rs), [call ordering](../crates/aiur/src/synthesis/tests/call_order.rs) | +| An empty return at rank seven supplied a public claim with output seven because lookup messages are zero-padded. | Public claims and constrained calls agree with the function's input and output arities; yields agree with their continuation. | [Message shapes](../crates/aiur/src/synthesis/tests/lookup_shapes.rs) | +| An inactive branch's store arguments changed a live call's lookup channel and supplied output seven for a program returning one. | Ungated arguments require a single function with terminal control and one selector. Constraint emission and lookup grouping use the same predicate. | [Empty branches](../crates/aiur/src/synthesis/tests/branchless.rs) | + +## Call ranks and witness generation + +Each function row has six little-endian rank bytes. A constrained call adds a +callee rank and six bytes for `callee_rank - caller_rank - 1`. Three byte-pair +lookups range-check each six-byte value. Ranks and gaps are below `2^48`, so +their sum is below `2^49`, below the Goldilocks characteristic. A satisfied +call-order equation therefore cannot wrap around the field to permit a cycle. + +Function query maps share a completion counter. Reversing completion order +assigns the root rank zero and gives each constrained callee a larger rank. +Promoting an earlier advice query refreshes its completion time after its +children are promoted. Shared callees retain a consistent rank. Witness +workers accumulate their byte-range queries locally; the prover merges those +counts before constructing the binary byte-table trace. + +The compiler reserves six additional columns and three lookup slots per +function, and seven columns and three additional lookup slots per constrained +call. These columns belong to the compiled proving layout and witness +generator. Regenerating the IxVM, aggregation and recursive-verifier execution +sources produces identical files because their instructions and function +indices are preserved. + +## Structural bounds + +System construction validates constrained-call arities, continuation yields, +canonical function-index and memory-width domains, circuit membership and +control counts. A circuit must reserve at least as many selectors as its +return/yield leaves, including yields consumed by a continuation. + +Before checking proof openings, the public verifier validates the claim's +channel, entry visibility and arity. It also requires fixed byte tables to be +active at their exact preprocessed heights, and bounds the total number of +lookup consumers below the field characteristic. The bound includes the +public claim and every slot of each active trace row. Malformed metadata, +integer overflow and a bound reaching the characteristic are rejected. + +These additional guards make the counting and byte-range assumptions explicit; +the fixed-table and global-count regressions do not claim another demonstrated +false-result acceptance. See [metadata bounds](../crates/aiur/src/synthesis/tests/lookup_budget.rs) +and [fixed tables](../crates/aiur/src/synthesis/tests/byte_shapes.rs). + +## Compatibility and validation + +The activity, call-order and branch-gating repairs change affected AIR +expressions and verification keys. Rebuild proving systems and keys, and +regenerate stored proofs against the repaired systems. Public claim encoding +is preserved: its omitted rank is zero under lookup padding. + +The native regressions cover supplied false witnesses as well as honest +execution, finite recursion, shared callees, advice promotion and grouped +circuits. Run them with: + +```sh +cargo test --locked --release -p aiur --features parallel +cargo clippy --locked --release -p aiur --all-targets --features parallel -- -D warnings +lake exe ix codegen --check +lake test -- aiur-cross aiur-cost aiur-prove recursive-verifier ix-aggr +lake test -- --ignored ixvm +``` + +These repairs and regression tests address the defects above. They do not +establish complete compiler preservation or cryptographic soundness. From fd9b62bd77e7475e2420bff70c7fcfa6cf730240 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 10:41:40 -0400 Subject: [PATCH 15/30] perf(aiur): derive callee ranks and cache claim shapes --- Ix/Aiur/Compiler/Layout.lean | 4 +- Tests/Ix/IxVM.lean | 166 +++++++++--------- Tests/Main.lean | 4 +- crates/aiur/src/constraints.rs | 20 +-- crates/aiur/src/lookup_shapes.rs | 145 ++++++++++++--- crates/aiur/src/synthesis.rs | 22 ++- crates/aiur/src/synthesis/tests/acceptance.rs | 4 +- crates/aiur/src/synthesis/tests/branchless.rs | 3 +- crates/aiur/src/synthesis/tests/call_order.rs | 76 ++++---- .../aiur/src/synthesis/tests/lookup_shapes.rs | 84 ++++++++- crates/aiur/src/trace.rs | 1 - docs/aiur-soundness.md | 16 +- 12 files changed, 364 insertions(+), 181 deletions(-) diff --git a/Ix/Aiur/Compiler/Layout.lean b/Ix/Aiur/Compiler/Layout.lean index 6676a7dfc..7ed54e940 100644 --- a/Ix/Aiur/Compiler/Layout.lean +++ b/Ix/Aiur/Compiler/Layout.lean @@ -176,8 +176,8 @@ def opLayout : Bytecode.Op → LayoutM Unit pushDegrees $ .replicate outputSize 1 bumpAuxiliaries outputSize if !unconstrained then - -- Callee rank and six bytes for (callee rank - caller rank - 1). - bumpAuxiliaries 7 + -- Six gap bytes; the lookup derives the callee rank as caller + 1 + gap. + bumpAuxiliaries 6 bumpLookups 4 | .store values => do pushDegree 1; bumpAuxiliaries; bumpLookups; addMemSize values.size diff --git a/Tests/Ix/IxVM.lean b/Tests/Ix/IxVM.lean index d1f74f2f9..674257010 100644 --- a/Tests/Ix/IxVM.lean +++ b/Tests/Ix/IxVM.lean @@ -439,89 +439,89 @@ private def nameOfString (str : String) : Lean.Name := and an improvement has to be acknowledged by re-pinning. These pins include the range-checked call ranks that exclude cyclic proof traces. -/ private def kernelCheckEntries : List (String × Nat) := [ - ("HEq", 130_092_790), - ("HEq.rec", 137_362_242), - ("Eq.rec", 136_027_876), - ("Nat", 130_060_261), - ("Nat.add", 197_695_257), - ("Nat.add_comm", 447_620_334), - ("Nat.decEq", 567_581_286), - ("Nat.decLe", 1_315_310_972), - ("Nat.sub_le_of_le_add", 3_328_720_460), - ("Nat.shiftRight_succ", 2_445_999_615), - ("Trans.mk", 145_076_422), - ("Array.append_assoc", 16_621_232_050), - ("Vector.append", 16_965_462_208), - ("IxVMPrim.nat_add_lit", 262_801_388), - ("IxVMPrim.nat_sub_lit", 284_521_561), - ("IxVMPrim.nat_mul_lit", 246_518_065), - ("IxVMPrim.nat_mul_big", 244_385_255), - ("IxVMPrim.nat_div_lit", 2_381_418_249), - ("IxVMPrim.nat_mod_lit", 2_425_927_469), - ("IxVMPrim.nat_succ_lit", 151_050_620), - ("IxVMPrim.nat_pred_lit", 183_486_510), - ("IxVMPrim.nat_gcd_lit", 3_785_736_196), - ("IxVMPrim.nat_land_lit", 6_215_635_638), - ("IxVMPrim.nat_lor_lit", 6_218_494_242), - ("IxVMPrim.nat_xor_lit", 6_246_434_034), - ("IxVMPrim.nat_shl_lit", 291_579_290), - ("IxVMPrim.nat_shr_lit", 2_403_043_114), - ("IxVMPrim.nat_pow_big", 624_316_509), - ("IxVMPrim.nat_beq_lit", 245_012_105), - ("IxVMPrim.nat_ble_lit", 236_989_197), - ("IxVMPrim.nat_cases_big", 184_684_065), - ("IxVMPrim.nat_dec_le", 1_342_961_129), - ("IxVMPrim.nat_dec_lt", 1_361_042_944), - ("IxVMPrim.nat_dec_eq", 628_894_977), - ("IxVMPrim.str_size_lit", 4_285_000_756), - ("IxVMPrim.bv_to_nat_lit", 3_606_708_590), - ("IxVMInd.Even", 251_494_925), - ("IxVMInd.Odd", 251_504_665), - ("IxVMInd.Even.rec", 282_364_930), - ("IxVMInd.Odd.rec", 282_364_002), - ("IxVMInd.IdxTeleN.rec", 177_402_027), - ("IxVMInd.IdxTeleB.rec", 177_400_336), - ("IxVMInd.SoloA.rec", 169_266_008), - ("IxVMInd.SoloB.rec", 169_265_171), - ("IxVMInd.UnsafeSquash", 132_544_402), - ("IxVMInd.Tree", 132_484_806), - ("IxVMInd.Tree.rec", 149_744_671), - ("IxVMInd.DedupM", 136_883_294), - ("IxVMInd.DedupM.rec", 160_258_504), - ("IxVMInd.DepthM", 134_821_747), - ("IxVMInd.DepthM.rec", 154_000_589), - ("String.Internal.append", 4_239_729_239), - ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 6_331_329_170), - ("Lean.Syntax.rec", 4_337_298_464), - ("IxVMInd.AuxTie", 421_081_929), - ("IxVMInd.AuxTie.rec", 496_204_215), - ("IxVMInd.HiddenIdx", 131_311_692), - ("IxVMInd.HiddenIdx.rec", 136_869_443), - ("IxVMInd.thmMajorUse", 803_735_348), - ("IxVMInd.partialKRec", 162_145_600), - ("IxVMInd.deepRebase", 278_922_839), - ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 6_023_770_121), - ("Lean.Widget.TaggedText.rec", 4_295_817_454), - ("Lean.Doc.Part.rec", 4_370_674_121), - ("Lean.Doc.Block.rec", 4_812_252_515), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 134_133_524), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 139_577_096), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 139_282_130), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 139_282_130), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 139_282_130), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 134_632_062), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 153_819_023), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 153_817_441), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 139_282_130), - ("strOfListFoldSize", 4_742_118_434), - ("strOfListFoldSizeAscii", 4_743_185_354), - ("IxVMPrim.lazy_ble_offset", 296_886_064), - ("IxVMPrim.lazy_unit_cast", 853_952_001), - ("IxVMPrim.sizeof_unit", 174_561_290), - ("IxVMPerf.let_continuations", 196_207_899), - ("IxVMPerf.mul_row", 566_690_116), - ("IxVMPerf.context_tower", 866_051_473), - ("IxVMPerf.mul_wide", 379_467_156), + ("HEq", 130_063_964), + ("HEq.rec", 137_144_830), + ("Eq.rec", 135_853_875), + ("Nat", 130_038_091), + ("Nat.add", 196_113_905), + ("Nat.add_comm", 440_435_264), + ("Nat.decEq", 556_459_970), + ("Nat.decLe", 1_286_115_140), + ("Nat.sub_le_of_le_add", 3_248_665_220), + ("Nat.shiftRight_succ", 2_388_210_480), + ("Trans.mk", 144_551_603), + ("Array.append_assoc", 16_174_150_842), + ("Vector.append", 16_510_547_185), + ("IxVMPrim.nat_add_lit", 259_971_314), + ("IxVMPrim.nat_sub_lit", 281_296_898), + ("IxVMPrim.nat_mul_lit", 244_082_273), + ("IxVMPrim.nat_mul_big", 241_982_822), + ("IxVMPrim.nat_div_lit", 2_325_278_806), + ("IxVMPrim.nat_mod_lit", 2_368_797_473), + ("IxVMPrim.nat_succ_lit", 150_684_613), + ("IxVMPrim.nat_pred_lit", 182_525_416), + ("IxVMPrim.nat_gcd_lit", 3_695_290_130), + ("IxVMPrim.nat_land_lit", 6_067_448_237), + ("IxVMPrim.nat_lor_lit", 6_070_270_621), + ("IxVMPrim.nat_xor_lit", 6_097_744_386), + ("IxVMPrim.nat_shl_lit", 288_279_659), + ("IxVMPrim.nat_shr_lit", 2_346_576_264), + ("IxVMPrim.nat_pow_big", 613_539_648), + ("IxVMPrim.nat_beq_lit", 242_500_472), + ("IxVMPrim.nat_ble_lit", 234_680_923), + ("IxVMPrim.nat_cases_big", 183_664_406), + ("IxVMPrim.nat_dec_le", 1_313_242_714), + ("IxVMPrim.nat_dec_lt", 1_330_953_467), + ("IxVMPrim.nat_dec_eq", 616_553_367), + ("IxVMPrim.str_size_lit", 4_185_234_171), + ("IxVMPrim.bv_to_nat_lit", 3_521_018_085), + ("IxVMInd.Even", 248_955_631), + ("IxVMInd.Odd", 248_965_174), + ("IxVMInd.Even.rec", 279_138_584), + ("IxVMInd.Odd.rec", 279_137_655), + ("IxVMInd.IdxTeleN.rec", 176_475_354), + ("IxVMInd.IdxTeleB.rec", 176_473_662), + ("IxVMInd.SoloA.rec", 168_533_822), + ("IxVMInd.SoloB.rec", 168_532_985), + ("IxVMInd.UnsafeSquash", 132_487_201), + ("IxVMInd.Tree", 132_417_126), + ("IxVMInd.Tree.rec", 149_294_954), + ("IxVMInd.DedupM", 136_761_695), + ("IxVMInd.DedupM.rec", 159_608_637), + ("IxVMInd.DepthM", 134_723_038), + ("IxVMInd.DepthM.rec", 153_452_640), + ("String.Internal.append", 4_140_807_948), + ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 6_181_591_136), + ("Lean.Syntax.rec", 4_236_356_723), + ("IxVMInd.AuxTie", 415_758_887), + ("IxVMInd.AuxTie.rec", 489_153_212), + ("IxVMInd.HiddenIdx", 131_272_312), + ("IxVMInd.HiddenIdx.rec", 136_701_447), + ("IxVMInd.thmMajorUse", 786_940_447), + ("IxVMInd.partialKRec", 161_480_092), + ("IxVMInd.deepRebase", 275_651_442), + ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 5_878_736_958), + ("Lean.Widget.TaggedText.rec", 4_195_436_311), + ("Lean.Doc.Part.rec", 4_268_571_152), + ("Lean.Doc.Block.rec", 4_697_476_168), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 134_049_039), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 139_391_417), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 139_039_561), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 139_039_561), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 139_039_561), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 134_536_025), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 153_305_989), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 153_304_407), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 139_039_561), + ("strOfListFoldSize", 4_632_656_203), + ("strOfListFoldSizeAscii", 4_633_712_616), + ("IxVMPrim.lazy_ble_offset", 293_329_152), + ("IxVMPrim.lazy_unit_cast", 836_781_702), + ("IxVMPrim.sizeof_unit", 173_827_975), + ("IxVMPerf.let_continuations", 194_323_668), + ("IxVMPerf.mul_row", 558_915_114), + ("IxVMPerf.context_tower", 844_858_461), + ("IxVMPerf.mul_wide", 372_109_314), ] /-- Variant of `kernelChecks`, pinned to the baseline diff --git a/Tests/Main.lean b/Tests/Main.lean index 8c2fb2d25..61709b0d0 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -278,8 +278,8 @@ def ignoredRunners (env : Lean.Environment) : List (String × IO UInt32) := [ let actual := (Aiur.computeStats v2Env.compiled qc v2Env.shapes).totalFftCost.round.toUInt64.toNat pure (LSpec.test - s!"Shard pipeline FFT matches: expected 10_627_864_237, got {actual}" - (actual = 10_627_864_237)) + s!"Shard pipeline FFT matches: expected 10_431_803_035, got {actual}" + (actual = 10_431_803_035)) LSpec.lspecIO (.ofList [("ixvm", [fullSeq, aiurSeq, arenaSeq, exploitSeq, paritySeq, shardSeq])]) []), diff --git a/crates/aiur/src/constraints.rs b/crates/aiur/src/constraints.rs index b5c784412..9d070be47 100644 --- a/crates/aiur/src/constraints.rs +++ b/crates/aiur/src/constraints.rs @@ -509,13 +509,6 @@ impl Op { lookup_args .extend(output.into_iter().map(|col| state.gate(sel, col))); - let callee_rank = state.next_auxiliary(); - lookup_args.push(state.gate(sel, callee_rank.clone())); - - let lookup = state.next_lookup(); - combine_lookup_args(lookup, lookup_args); - lookup.multiplicity = lookup.multiplicity.clone() + sel.clone(); - let gap_bytes: [Expr; RANK_BYTES] = array::from_fn(|_| state.next_auxiliary()); let gap = gap_bytes.iter().enumerate().fold( @@ -524,10 +517,15 @@ impl Op { acc + byte.clone() * konst(G::from_u64(1 << (8 * i))) }, ); - state.constraints.zeros.push( - sel.clone() - * (callee_rank - state.rank.clone() - konst(G::ONE) - gap), - ); + // Bind the derived rank directly through the callee's return + // lookup. Both row ranks and gaps are range checked, so this + // cannot wrap the field to close a cycle. The expression stays + // linear and needs no separate rank column or equality. + let callee_rank = state.rank.clone() + konst(G::ONE) + gap; + lookup_args.push(state.gate(sel, callee_rank)); + let lookup = state.next_lookup(); + combine_lookup_args(lookup, lookup_args); + lookup.multiplicity = lookup.multiplicity.clone() + sel.clone(); for pair in gap_bytes.as_chunks::<2>().0 { state.range_pair(sel, pair[0].clone(), pair[1].clone()); } diff --git a/crates/aiur/src/lookup_shapes.rs b/crates/aiur/src/lookup_shapes.rs index a361b01bf..64dc430c2 100644 --- a/crates/aiur/src/lookup_shapes.rs +++ b/crates/aiur/src/lookup_shapes.rs @@ -17,9 +17,63 @@ fn canonical_size(size: usize) -> bool { u64::try_from(size).is_ok_and(|size| size < G::ORDER_U64) } +#[derive(Clone, Copy)] +enum ReturnArity { + NoReturns, + Exact(usize), + Inconsistent, +} + +impl ReturnArity { + fn merge(self, other: Self) -> Self { + match (self, other) { + (Self::NoReturns, arity) | (arity, Self::NoReturns) => arity, + (Self::Exact(a), Self::Exact(b)) if a == b => Self::Exact(a), + _ => Self::Inconsistent, + } + } + + fn accepts(self, size: usize) -> bool { + match self { + Self::NoReturns => true, + Self::Exact(arity) => arity == size, + Self::Inconsistent => false, + } + } +} + +/// Cached for public constrained entries in the system's immutable program. +pub(crate) struct ClaimShape { + inputs: usize, + outputs: ReturnArity, +} + impl Block { + fn return_arity(&self) -> ReturnArity { + match &self.ctrl { + Ctrl::Return(_, values) => ReturnArity::Exact(values.len()), + Ctrl::Yield(..) => ReturnArity::NoReturns, + Ctrl::Match(_, branches, fallback) => branches + .values() + .chain(fallback.iter().map(Box::as_ref)) + .fold(ReturnArity::NoReturns, |arity, block| { + arity.merge(block.return_arity()) + }), + Ctrl::MatchContinue(_, branches, fallback, _, _, _, continuation) => { + branches + .values() + .chain(fallback.iter().map(Box::as_ref)) + .fold(continuation.return_arity(), |arity, block| { + arity.merge(block.return_arity()) + }) + }, + } + } + /// Every function return, including an early return from a continuation /// arm, has this output arity. Yields return to their own continuation. + /// Kept as an independent recursive reference for the cached summary. + #[cfg(test)] pub(crate) fn returns_have_size(&self, size: usize) -> bool { match &self.ctrl { Ctrl::Return(_, values) => values.len() == size, @@ -39,6 +93,7 @@ impl Block { fn check_lookup_shapes( &self, program: &Toplevel, + return_arities: &[ReturnArity], yield_size: Option, ) -> Result<(), &'static str> { for op in &self.ops { @@ -53,7 +108,7 @@ impl Block { if callee.layout.input_size != inputs.len() { return Err("constrained call input arity differs from its callee"); } - if !callee.body.returns_have_size(*outputs) { + if !return_arities[*index].accepts(*outputs) { return Err( "constrained call output arity differs from its callee", ); @@ -77,20 +132,24 @@ impl Block { }, Ctrl::Match(_, branches, fallback) => { for block in branches.values() { - block.check_lookup_shapes(program, yield_size)?; + block.check_lookup_shapes(program, return_arities, yield_size)?; } if let Some(block) = fallback { - block.check_lookup_shapes(program, yield_size)?; + block.check_lookup_shapes(program, return_arities, yield_size)?; } }, Ctrl::MatchContinue(_, branches, fallback, size, _, _, continuation) => { for block in branches.values() { - block.check_lookup_shapes(program, Some(*size))?; + block.check_lookup_shapes(program, return_arities, Some(*size))?; } if let Some(block) = fallback { - block.check_lookup_shapes(program, Some(*size))?; + block.check_lookup_shapes(program, return_arities, Some(*size))?; } - continuation.check_lookup_shapes(program, yield_size)?; + continuation.check_lookup_shapes( + program, + return_arities, + yield_size, + )?; }, } Ok(()) @@ -101,38 +160,70 @@ impl Toplevel { /// Check the static boundaries of all constrained function messages. /// This does not check value indices, layouts or arithmetic constraints. pub fn validate_lookup_shapes(&self) -> Result<(), &'static str> { + self.checked_claim_shapes().map(|_| ()) + } + + pub(crate) fn checked_claim_shapes( + &self, + ) -> Result>, &'static str> { if !canonical_size(self.functions.len()) { return Err("function index domain exceeds the field characteristic"); } if self.memory_sizes.iter().any(|&size| !canonical_size(size)) { return Err("memory width is not a canonical field element"); } + // Summarize each constrained body once, then reuse the result at every + // call site and public verification. Yields do not return from functions. + let return_arities: Vec<_> = self + .functions + .iter() + .map(|function| { + if function.constrained { + function.body.return_arity() + } else { + ReturnArity::NoReturns + } + }) + .collect(); for function in &self.functions { if function.constrained { - function.body.check_lookup_shapes(self, None)?; + function.body.check_lookup_shapes(self, &return_arities, None)?; } } - Ok(()) + Ok( + self + .functions + .iter() + .zip(return_arities) + .map(|(function, outputs)| { + (function.entry && function.constrained).then_some(ClaimShape { + inputs: function.layout.input_size, + outputs, + }) + }) + .collect(), + ) } +} - pub(crate) fn valid_claim_shape(&self, claim: &[G]) -> bool { - let [channel, index, arguments @ ..] = claim else { - return false; - }; - if *channel != function_channel() { - return false; - } - let Ok(index) = usize::try_from(index.as_canonical_u64()) else { - return false; - }; - let Some(function) = self.functions.get(index) else { - return false; - }; - function.entry - && function.constrained - && arguments.len() >= function.layout.input_size - && function - .body - .returns_have_size(arguments.len() - function.layout.input_size) +pub(crate) fn valid_claim_shape( + shapes: &[Option], + claim: &[G], +) -> bool { + let [channel, index, arguments @ ..] = claim else { + return false; + }; + if *channel != function_channel() { + return false; } + let Ok(index) = usize::try_from(index.as_canonical_u64()) else { + return false; + }; + let Some(Some(shape)) = shapes.get(index) else { + return false; + }; + arguments + .len() + .checked_sub(shape.inputs) + .is_some_and(|outputs| shape.outputs.accepts(outputs)) } diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index f32d90b6c..6d49e5d11 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -21,6 +21,7 @@ use crate::{ function_channel, gadgets::{AiurGadget, bytes1::Bytes1, bytes2::Bytes2}, lookup_budget::lookup_query_bound, + lookup_shapes::{ClaimShape, valid_claim_shape}, memory::Memory, trace_heights::fixed_trace_heights, }; @@ -76,6 +77,7 @@ pub enum GatedProve { pub struct AiurSystem { toplevel: Toplevel, + claim_shapes: Vec>, // perhaps remove the key from the system in verifier only mode? key: ProverKey, /// The parameters the system's config was built from, kept for the @@ -136,7 +138,8 @@ impl AiurSystem { commitment_parameters: CommitmentParameters, fri_parameters: FriParameters, ) -> Self { - toplevel.validate_lookup_shapes().expect("invalid Aiur lookup shapes"); + let claim_shapes = + toplevel.checked_claim_shapes().expect("invalid Aiur lookup shapes"); toplevel.validate_row_counts().expect("invalid Aiur control counts"); let mut circuit_inputs: Vec> = Vec::new(); let mut slot_widths: Vec> = Vec::new(); @@ -211,6 +214,7 @@ impl AiurSystem { system, key, toplevel, + claim_shapes, commitment_parameters, fri_parameters, slot_widths, @@ -595,7 +599,7 @@ impl AiurSystem { claim: &[G], proof: &AiurProof, ) -> Result<(), VerificationError> { - if !self.toplevel.valid_claim_shape(claim) { + if !valid_claim_shape(&self.claim_shapes, claim) { return Err(VerificationError::InvalidClaim); } if !fixed_trace_heights( @@ -780,7 +784,7 @@ mod tests { /// - `f` (idx 0, entry): `f(a, b) = g(a) * b`, but routing `b` through /// memory so the memory path is live: /// - `Call(1, [a], 1, false)` → `g(a)` at value idx 2, allocating one - /// output auxiliary, seven order auxiliaries and four lookup slots. + /// output auxiliary, six gap auxiliaries and four lookup slots. /// - `Store([b])` → pointer at value idx 3, allocating one pointer /// auxiliary + one memory-channel lookup slot (multiplicity pushed). /// - `Load(1, 3)` → the loaded `b` at value idx 4, allocating one value @@ -793,8 +797,8 @@ mod tests { /// the block: /// - `input_size = 2` (`a`, `b`). /// - `selectors = 1` (the single `Return`). - /// - `auxiliaries = 18`: multiplicity(1), rank bytes(6), call output(1), - /// call order(7), store pointer(1), load value(1), multiplication(1). + /// - `auxiliaries = 17`: multiplicity(1), rank bytes(6), call output(1), + /// call gap(6), store pointer(1), load value(1), multiplication(1). /// - `lookups = 10`: return(1), rank ranges(3), call/order(4), memory(2). /// /// - `g` (idx 1): `g(x) = x + 1`: @@ -824,7 +828,7 @@ mod tests { layout: FunctionLayout { input_size: 2, selectors: 1, - auxiliaries: 18, + auxiliaries: 17, lookups: 10, }, entry: true, @@ -904,7 +908,7 @@ mod tests { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 16, + auxiliaries: 15, lookups: 8, }, entry: true, @@ -919,7 +923,7 @@ mod tests { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 15, + auxiliaries: 14, lookups: 8, }, entry: false, @@ -1015,7 +1019,7 @@ mod tests { // Function circuits: main width = inputs + selectors + auxiliaries, no // preprocessed matrix. - assert_eq!(shapes[0].main_width, 2 + 1 + 18); + assert_eq!(shapes[0].main_width, 2 + 1 + 17); assert_eq!(shapes[1].main_width, 1 + 1 + 7); // Memory of size 1: multiplicity + selector + pointer + 1 value. assert_eq!(shapes[2].main_width, 3 + 1); diff --git a/crates/aiur/src/synthesis/tests/acceptance.rs b/crates/aiur/src/synthesis/tests/acceptance.rs index d40eb9683..3d2e584a7 100644 --- a/crates/aiur/src/synthesis/tests/acceptance.rs +++ b/crates/aiur/src/synthesis/tests/acceptance.rs @@ -26,7 +26,7 @@ fn grouped_promotion_toplevel() -> Toplevel { layout: FunctionLayout { input_size: 1, selectors: 2, - auxiliaries: 15, + auxiliaries: 14, lookups: 8, }, }); @@ -178,7 +178,7 @@ fn recursive_cycle_cannot_supply_claim() { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 15, + auxiliaries: 14, lookups: 8, }, entry: true, diff --git a/crates/aiur/src/synthesis/tests/branchless.rs b/crates/aiur/src/synthesis/tests/branchless.rs index 3cac25114..809b9aae2 100644 --- a/crates/aiur/src/synthesis/tests/branchless.rs +++ b/crates/aiur/src/synthesis/tests/branchless.rs @@ -26,7 +26,7 @@ fn empty_branch_toplevel() -> Toplevel { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 15, + auxiliaries: 14, lookups: 8, }, entry: true, @@ -79,7 +79,6 @@ fn empty_branch_cannot_redirect_a_call_to_memory() { row[1] = G::ONE; row[2] = G::ONE; row[9] = forged; - row[10] = G::ONE; let values = VarValues { preprocessed: [&[], &[]], main: [&row, &row], diff --git a/crates/aiur/src/synthesis/tests/call_order.rs b/crates/aiur/src/synthesis/tests/call_order.rs index d005e3fcc..8d274f00f 100644 --- a/crates/aiur/src/synthesis/tests/call_order.rs +++ b/crates/aiur/src/synthesis/tests/call_order.rs @@ -18,7 +18,7 @@ fn cycle_toplevel(grouped: bool) -> Toplevel { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 15, + auxiliaries: 14, lookups: 8, }, entry: i == 0, @@ -33,7 +33,7 @@ fn cycle_toplevel(grouped: bool) -> Toplevel { layout: FunctionLayout { input_size: 1, selectors: 2, - auxiliaries: 15, + auxiliaries: 14, lookups: 8, }, }); @@ -71,13 +71,13 @@ fn normalized(mut args: Vec) -> Vec { args } -/// Verify exact tuple balance independently of random lookup compression. -fn assert_lookup_balance( +/// Compute exact tuple balance independently of random lookup compression. +fn lookup_balance( top: &Toplevel, traces: &[RowMajorMatrix], ranges: &RankRanges, claim: &[G], -) { +) -> FxHashMap, G> { let mut balance = FxHashMap::, G>::default(); *balance.entry(normalized(claim.to_vec())).or_insert(G::ZERO) += G::ONE; for (i, circuit) in top.circuits.iter().enumerate() { @@ -101,14 +101,12 @@ fn assert_lookup_balance( ])) .or_insert(G::ZERO) -= *count; } - assert!( - balance.values().all(|count| *count == G::ZERO), - "unbalanced supplied witness" - ); + balance.retain(|_, count| *count != G::ZERO); + balance } #[test] -fn mutual_cycles_reject_with_balanced_lookups_in_both_partitions() { +fn mutual_cycles_reject_at_the_closing_lookup_in_both_partitions() { for grouped in [false, true] { let (cp, fp) = test_parameters(); let system = AiurSystem::build(cycle_toplevel(grouped), cp, fp); @@ -134,10 +132,8 @@ fn mutual_cycles_reject_with_balanced_lookups_in_both_partitions() { row[aux] = if member == 1 { G::from_u8(2) } else { G::ONE }; fill_bytes(&mut row[aux + 1..aux + 7], member as u64, &mut ranges); row[aux + 7] = output; - row[aux + 8] = - G::from_usize(if member == 2 { 1 } else { member + 1 }); let gap = if member == 2 { RANK_BOUND - 2 } else { 0 }; - fill_bytes(&mut row[aux + 9..aux + 15], gap, &mut ranges); + fill_bytes(&mut row[aux + 8..aux + 14], gap, &mut ranges); violated += constraints .zeros .iter() @@ -153,11 +149,17 @@ fn mutual_cycles_reject_with_balanced_lookups_in_both_partitions() { } traces.push(RowMajorMatrix::new(rows, shape.main_width)); } + assert_eq!(violated, 0, "all local polynomial constraints hold"); + // Only the closing h -> g lookup fails: its derived rank exceeds the + // bounded rank on g's return. All byte-range lookups balance exactly. + let message = + |rank| vec![function_channel(), G::ONE, input, output, G::from_u64(rank)]; assert_eq!( - violated, 1, - "only the closing h -> g call should violate a polynomial" + lookup_balance(&system.toplevel, &traces, &ranges, &claim), + [(message(RANK_BOUND + 1), G::ONE), (message(1), -G::ONE)] + .into_iter() + .collect() ); - assert_lookup_balance(&system.toplevel, &traces, &ranges, &claim); let witness = SystemWitness::from_stage_1(traces, &system.system); let proof = system.system.prove(&system.key, &claim, witness); assert!( @@ -168,9 +170,9 @@ fn mutual_cycles_reject_with_balanced_lookups_in_both_partitions() { } #[test] -fn call_order_polynomial_checks_strict_unsigned_order() { +fn call_lookup_checks_strict_unsigned_order() { let top = cycle_toplevel(false); - let (constraints, _) = top.build_constraints(0); + let (constraints, lookups) = top.build_constraints(0); for (parent, child, gap, accepted) in [ (0, 1, 0, true), (0, RANK_BOUND - 1, RANK_BOUND - 2, true), @@ -184,13 +186,20 @@ fn call_order_polynomial_checks_strict_unsigned_order() { row[1] = G::ONE; row[2] = G::ONE; fill_bytes(&mut row[3..9], parent, &mut ranges); - row[10] = G::from_u64(child); - fill_bytes(&mut row[11..17], gap, &mut ranges); - let satisfied = constraints - .zeros - .iter() - .all(|expr| eval_expr(expr, &row_values(&row)) == G::ZERO); - assert_eq!(satisfied, accepted, "ranks {parent} -> {child}, gap {gap}"); + fill_bytes(&mut row[10..16], gap, &mut ranges); + assert!( + constraints + .zeros + .iter() + .all(|expr| eval_expr(expr, &row_values(&row)) == G::ZERO) + ); + let requested_rank = + eval_expr(lookups[4].args.last().unwrap(), &row_values(&row)); + assert_eq!( + requested_rank == G::from_u64(child), + accepted, + "ranks {parent} -> {child}, gap {gap}" + ); } } @@ -218,9 +227,9 @@ fn out_of_range_gaps_cannot_hide_a_cycle_in_field_arithmetic() { rows[1] = G::ONE; rows[2] = G::from_u8(if i == 1 { 2 } else { 1 }); rows[9] = claim[3]; - // All ranks are zero. A forged "byte" -1 makes 0 - 0 - 1 - gap - // vanish as a field expression, but cannot pass the byte table. - rows[11] = -G::ONE; + // All ranks are zero. A forged "byte" -1 makes caller + 1 + gap + // request rank zero, but cannot pass the byte table. + rows[10] = -G::ONE; let (constraints, _) = system.toplevel.build_constraints(i); assert!(constraints.zeros.iter().all(|expr| eval_expr( expr, @@ -277,11 +286,10 @@ fn out_of_range_function_rank_is_rejected_by_the_byte_table() { rows[2] = G::ONE; if i == 0 { rows[9] = claim[3]; - rows[10] = G::from_u64(RANK_BOUND); - rows[11..17].fill(G::from_u8(255)); + rows[10..16].fill(G::from_u8(255)); } else { - // 256 in the high byte packs to 2^48. The edge's field equality - // and all ordinary constraints hold; the rank range check must fail. + // 256 in the high byte packs to 2^48. The call lookup matches + // this rank, but the function's rank range check must fail. rows[8] = G::from_u64(256); } let (constraints, _) = system.toplevel.build_constraints(i); @@ -326,7 +334,7 @@ fn finite_recursive_calls_verify() { layout: FunctionLayout { input_size: 1, selectors: 2, - auxiliaries: 16, + auxiliaries: 15, lookups: 8, }, entry: true, @@ -360,7 +368,7 @@ fn shared_callee_keeps_one_consistent_rank() { layout: FunctionLayout { input_size: 1, selectors: 1, - auxiliaries: 23, + auxiliaries: 21, lookups: 12, }, entry: true, diff --git a/crates/aiur/src/synthesis/tests/lookup_shapes.rs b/crates/aiur/src/synthesis/tests/lookup_shapes.rs index 9d92bc356..d3f7c6082 100644 --- a/crates/aiur/src/synthesis/tests/lookup_shapes.rs +++ b/crates/aiur/src/synthesis/tests/lookup_shapes.rs @@ -51,7 +51,11 @@ fn public_output_cannot_be_supplied_by_a_displaced_rank() { #[test] fn public_claim_shape_checks_channel_visibility_and_arity() { let top = mul_toplevel(); - assert!(top.valid_claim_shape(&[G::ZERO, G::ZERO, G::ONE, G::ONE, G::ONE])); + let shapes = top.checked_claim_shapes().unwrap(); + assert!(valid_claim_shape( + &shapes, + &[G::ZERO, G::ZERO, G::ONE, G::ONE, G::ONE] + )); for claim in [ vec![], vec![G::ZERO], @@ -61,13 +65,16 @@ fn public_claim_shape_checks_channel_visibility_and_arity() { vec![G::ZERO, G::ZERO, G::ONE, G::ONE], vec![G::ZERO, G::ZERO, G::ONE, G::ONE, G::ONE, G::ZERO], ] { - assert!(!top.valid_claim_shape(&claim)); + assert!(!valid_claim_shape(&shapes, &claim)); } for constrained in [true, false] { let mut top = mul_toplevel(); top.functions[0].entry = !constrained; top.functions[0].constrained = constrained; - assert!(!top.valid_claim_shape(&[G::ZERO; 5])); + assert!(!valid_claim_shape( + &top.checked_claim_shapes().unwrap(), + &[G::ZERO; 5] + )); } } @@ -94,6 +101,77 @@ fn constrained_calls_check_both_message_boundaries() { top.validate_lookup_shapes().unwrap(); } +#[test] +fn cached_arities_match_recursive_checks_for_nested_control_flow() { + fn returning(size: usize) -> Block { + Block { ops: vec![], ctrl: Ctrl::Return(0, vec![0; size]) } + } + fn yielding() -> Block { + Block { ops: vec![], ctrl: Ctrl::Yield(0, vec![0; 2]) } + } + fn matching(arms: Vec, fallback: Option) -> Block { + Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + arms + .into_iter() + .enumerate() + .map(|(i, b)| (G::from_usize(i), b)) + .collect(), + fallback.map(Box::new), + ), + } + } + fn continued(arm: Block, continuation: Block) -> Block { + Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + [(G::ZERO, arm)].into_iter().collect(), + Some(Box::new(yielding())), + 2, + 0, + 0, + Box::new(continuation), + ), + } + } + let mut bodies = vec![ + matching(vec![], None), + matching(vec![], Some(returning(0))), + continued(yielding(), matching(vec![], None)), + ]; + for a in 0..3 { + bodies.push(returning(a)); + bodies.push(continued(yielding(), returning(a))); + bodies.push(continued(continued(returning(a), yielding()), returning(a))); + for b in 0..3 { + bodies.push(matching(vec![returning(a), returning(b)], None)); + bodies.push(matching(vec![returning(a)], Some(returning(b)))); + bodies.push(continued(returning(a), returning(b))); + bodies.push(continued(continued(returning(a), yielding()), returning(b))); + } + } + for body in bodies { + let mut top = call_and_memory_toplevel(); + // Test the cached public boundary and each call-site boundary against + // the original recursive predicate, including vacuous and mixed returns. + top.functions[0].body.ops.clear(); + top.functions[1].entry = true; + top.functions[1].body = body; + let shapes = top.checked_claim_shapes().unwrap(); + for outputs in 0..4 { + let expected = top.functions[1].body.returns_have_size(outputs); + let mut claim = vec![function_channel(), G::ONE, G::ZERO]; + claim.resize(3 + outputs, G::ZERO); + assert_eq!(valid_claim_shape(&shapes, &claim), expected); + top.functions[0].body.ops = vec![Op::Call(1, vec![0], outputs, false)]; + assert_eq!(top.validate_lookup_shapes().is_ok(), expected); + } + } +} + #[test] fn nested_continuations_check_returns_and_yields() { fn returning(size: usize) -> Block { diff --git a/crates/aiur/src/trace.rs b/crates/aiur/src/trace.rs index 957c4900a..342f800d1 100644 --- a/crates/aiur/src/trace.rs +++ b/crates/aiur/src/trace.rs @@ -419,7 +419,6 @@ impl Op { result.output, result.rank, ); - slice.push_auxiliary(index, G::from_u64(result.rank)); slice.push_lookup(index, G::ONE, &args); let gap = result .rank diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index 7cc97ba22..22fac33c0 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -13,11 +13,13 @@ rows directly, without running the interpreter. The regressions in ## Call ranks and witness generation -Each function row has six little-endian rank bytes. A constrained call adds a -callee rank and six bytes for `callee_rank - caller_rank - 1`. Three byte-pair +Each function row has six little-endian rank bytes. A constrained call adds +six bytes for `callee_rank - caller_rank - 1` and requests the derived rank +`caller_rank + 1 + gap` in its lookup. The callee's return binds this rank +without a separate callee-rank column or equality constraint. Three byte-pair lookups range-check each six-byte value. Ranks and gaps are below `2^48`, so -their sum is below `2^49`, below the Goldilocks characteristic. A satisfied -call-order equation therefore cannot wrap around the field to permit a cycle. +the derived rank is below `2^49`, below the Goldilocks characteristic. The +call lookup therefore cannot wrap around the field to permit a cycle. Function query maps share a completion counter. Reversing completion order assigns the root rank zero and gives each constrained callee a larger rank. @@ -27,7 +29,7 @@ workers accumulate their byte-range queries locally; the prover merges those counts before constructing the binary byte-table trace. The compiler reserves six additional columns and three lookup slots per -function, and seven columns and three additional lookup slots per constrained +function, and six columns and three additional lookup slots per constrained call. These columns belong to the compiled proving layout and witness generator. Regenerating the IxVM, aggregation and recursive-verifier execution sources produces identical files because their instructions and function @@ -39,6 +41,10 @@ System construction validates constrained-call arities, continuation yields, canonical function-index and memory-width domains, circuit membership and control counts. A circuit must reserve at least as many selectors as its return/yield leaves, including yields consumed by a continuation. +Each constrained function's return arity is summarized once and reused at +every call site. Public-entry shapes are retained with the immutable program +so verifying a claim's shape takes constant time. Summaries include early +returns from nested continuations and reject inconsistent return arities. Before checking proof openings, the public verifier validates the claim's channel, entry visibility and arity. It also requires fixed byte tables to be From 9c390fd2bd0267ed2692ed6b0385b17df9ab5740 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 11:12:18 -0400 Subject: [PATCH 16/30] fix(aiur): reject Merkle caps that omit trace matrices --- Cargo.lock | 3 + crates/aiur/Cargo.toml | 6 + crates/aiur/src/synthesis.rs | 10 +- crates/aiur/src/synthesis/tests/mmcs.rs | 141 ++++++++++++++++++++++++ crates/aiur/src/trace_heights.rs | 20 ++++ docs/aiur-soundness.md | 23 +++- 6 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 crates/aiur/src/synthesis/tests/mmcs.rs diff --git a/Cargo.lock b/Cargo.lock index c8c03e78f..ee41938d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,6 +55,9 @@ dependencies = [ "libc", "multi-stark", "num-bigint 0.4.6", + "p3-blake3", + "p3-commit", + "p3-symmetric", "rayon", "rustc-hash", "tracing", diff --git a/crates/aiur/Cargo.toml b/crates/aiur/Cargo.toml index cf9e4321e..26c92ad6d 100644 --- a/crates/aiur/Cargo.toml +++ b/crates/aiur/Cargo.toml @@ -15,6 +15,12 @@ rustc-hash = { workspace = true } tracing = { workspace = true } tracing-texray = { workspace = true } +[dev-dependencies] +# Exercise the native MMCS at the same Plonky3 revision as multi-stark. +p3-blake3 = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +p3-commit = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +p3-symmetric = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } + [features] default = [] parallel = ["multi-stark/parallel"] diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index 6d49e5d11..d36a2eb1e 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -23,7 +23,7 @@ use crate::{ lookup_budget::lookup_query_bound, lookup_shapes::{ClaimShape, valid_claim_shape}, memory::Memory, - trace_heights::fixed_trace_heights, + trace_heights::{fixed_trace_heights, trace_cap_coverage}, }; /// The concrete STARK configuration Aiur instantiates multi-stark with. @@ -609,6 +609,13 @@ impl AiurSystem { ) { return Err(VerificationError::InvalidProofShape); } + if !trace_cap_coverage( + self.commitment_parameters.log_blowup, + self.commitment_parameters.cap_height, + &proof.log_degrees, + ) { + return Err(VerificationError::InvalidProofShape); + } if lookup_query_bound( self.slot_widths.iter().map(Vec::len), &proof.active, @@ -641,6 +648,7 @@ mod tests { mod call_order; mod lookup_budget; mod lookup_shapes; + mod mmcs; use super::*; use crate::{ diff --git a/crates/aiur/src/synthesis/tests/mmcs.rs b/crates/aiur/src/synthesis/tests/mmcs.rs new file mode 100644 index 000000000..e04dd1db3 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/mmcs.rs @@ -0,0 +1,141 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Native binary Merkle authentication and the cap coverage boundary. + +use super::*; + +#[cfg(not(feature = "cuda"))] +#[test] +fn native_cap_can_omit_a_shorter_matrix() { + use multi_stark::p3_matrix::Matrix; + use multi_stark::types::Mmcs; + use p3_blake3::Blake3; + use p3_commit::Mmcs as _; + use p3_symmetric::{CompressionFunctionFromHasher, SerializingHasher}; + + for cap_height in 0..=4 { + let mmcs = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + cap_height, + ); + let tall = RowMajorMatrix::new((1..=8).map(G::from_u32).collect(), 1); + let short = RowMajorMatrix::new(vec![G::from_u32(21), G::from_u32(22)], 1); + let dimensions = vec![tall.dimensions(), short.dimensions()]; + let (commitment, data) = mmcs.commit(vec![tall.clone(), short]); + let mut changed = mmcs.open_batch(5, &data); + mmcs.verify_batch(&commitment, &dimensions, 5, (&changed).into()).unwrap(); + changed.opened_values[1][0] += G::ONE; + let accepted = + mmcs.verify_batch(&commitment, &dimensions, 5, (&changed).into()).is_ok(); + assert_eq!(accepted, cap_height > 1); + + let indices = [5, 0, 5, 7]; + let (mut rows, proof) = mmcs.open_multi_batch(&indices, &data); + mmcs + .verify_multi_batch(&commitment, &dimensions, &indices, &rows, &proof) + .unwrap(); + for query in &mut rows { + query[1][0] += G::ONE; + } + let accepted = mmcs + .verify_multi_batch(&commitment, &dimensions, &indices, &rows, &proof) + .is_ok(); + assert_eq!(accepted, cap_height > 1); + + let different = + RowMajorMatrix::new(vec![G::from_u32(31), G::from_u32(32)], 1); + let (other_commitment, _) = mmcs.commit(vec![tall, different]); + assert_eq!(commitment == other_commitment, cap_height > 1); + } +} + +#[cfg(not(feature = "cuda"))] +#[test] +fn public_verify_rejects_a_cap_above_the_shortest_trace_lde() { + let (mut cp, fp) = test_parameters(); + cp.cap_height = 2; + let system = AiurSystem::build(mul_toplevel(), cp, fp); + let (claim, proof) = + system.prove(0, &[G::ONE, G::ONE], &mut empty_io_buffer()); + assert_eq!(proof.log_degrees[0], 0); + system.system.verify(&claim, &proof).unwrap(); + assert!(matches!( + system.verify(&claim, &proof), + Err(VerificationError::InvalidProofShape) + )); +} + +#[test] +fn public_verify_accepts_a_cap_at_the_shortest_trace_lde() { + let (mut cp, fp) = test_parameters(); + #[cfg(not(feature = "cuda"))] + { + cp.cap_height = 1; + } + #[cfg(feature = "cuda")] + { + cp.cap_height = 0; + } + let system = AiurSystem::build(mul_toplevel(), cp, fp); + let (claim, proof) = + system.prove(0, &[G::from_u32(3), G::from_u32(5)], &mut empty_io_buffer()); + assert_eq!(proof.log_degrees[0], 0); + system.verify(&claim, &proof).unwrap(); + let mut changed = claim.clone(); + *changed.last_mut().unwrap() += G::ONE; + assert!(system.verify(&changed, &proof).is_err()); +} + +#[test] +fn cap_coverage_matches_injection_geometry_at_integer_boundaries() { + let parameters = [ + 0, + 1, + 2, + 3, + 8, + 16, + 31, + 32, + 63, + 64, + 255, + 256, + 65535, + usize::MAX - 255, + usize::MAX, + ]; + let mut total = 0; + for blowup in parameters { + for cap in parameters { + assert!(trace_cap_coverage(blowup, cap, &[])); + total += 1; + for degree in 0..=255 { + for degrees in [ + vec![degree], + vec![degree, 0], + vec![degree, 8, 16], + vec![degree, degree], + vec![255, degree], + ] { + // Check the direct tree-height condition with wide arithmetic, + // independently of the production guard's saturating subtraction. + let tallest = u128::from(*degrees.iter().max().unwrap()); + let effective_cap = (cap as u128).min(blowup as u128 + tallest); + let expected = degrees.iter().all(|&height| { + effective_cap <= blowup as u128 + u128::from(height) + }); + assert_eq!( + trace_cap_coverage(blowup, cap, °rees), + expected, + "blowup={blowup}, cap={cap}, degrees={degrees:?}" + ); + total += 1; + } + } + } + } + assert_eq!(total, 288225); +} diff --git a/crates/aiur/src/trace_heights.rs b/crates/aiur/src/trace_heights.rs index 7c758a137..35e5ffaf6 100644 --- a/crates/aiur/src/trace_heights.rs +++ b/crates/aiur/src/trace_heights.rs @@ -35,3 +35,23 @@ pub(crate) fn fixed_trace_heights( } degrees.next().is_none() } + +/// Every input matrix must be injected before the path reaches the cap. +/// The native MMCS clamps a cap to the tallest matrix's tree depth; that +/// still omits shorter matrices when the cap lies below their injection. +/// Subtract the shared blowup first, avoiding machine addition overflow. +pub(crate) fn trace_cap_coverage( + log_blowup: usize, + cap_height: usize, + log_degrees: &[u8], +) -> bool { + // Every nonempty trace's LDE has at least 2^log_blowup rows. The default + // root cap therefore needs no extra traversal of the circuit degrees. + if cap_height <= log_blowup { + return true; + } + let maximum = log_degrees.iter().copied().max().unwrap_or(0); + let effective = + cap_height.saturating_sub(log_blowup).min(usize::from(maximum)); + log_degrees.iter().all(|°ree| effective <= usize::from(degree)) +} diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index 22fac33c0..83289df00 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -2,7 +2,8 @@ Aiur's verifier must reject a false result even when a prover supplies trace rows directly, without running the interpreter. The regressions in -`crates/aiur/src/synthesis/tests/` exercise four failures at that boundary. +`crates/aiur/src/synthesis/tests/` exercise four supplied-trace failures and +a native Merkle commitment-binding defect. | Failure | Required invariant | Regression | | --- | --- | --- | @@ -10,6 +11,7 @@ rows directly, without running the interpreter. The regressions in | Self-recursive and mutually recursive rows balanced their own calls without a finite execution. | Every constrained call strictly increases a range-checked rank. | [Self recursion](../crates/aiur/src/synthesis/tests/acceptance.rs), [call ordering](../crates/aiur/src/synthesis/tests/call_order.rs) | | An empty return at rank seven supplied a public claim with output seven because lookup messages are zero-padded. | Public claims and constrained calls agree with the function's input and output arities; yields agree with their continuation. | [Message shapes](../crates/aiur/src/synthesis/tests/lookup_shapes.rs) | | An inactive branch's store arguments changed a live call's lookup channel and supplied output seven for a program returning one. | Ungated arguments require a single function with terminal control and one selector. Constraint emission and lookup grouping use the same predicate. | [Empty branches](../crates/aiur/src/synthesis/tests/branchless.rs) | +| A large native Merkle cap omitted a shorter matrix: changing its values preserved the commitment, and altered openings verified. | The cap retains the injection layer of every committed matrix. | [Merkle cap coverage](../crates/aiur/src/synthesis/tests/mmcs.rs) | ## Call ranks and witness generation @@ -58,6 +60,25 @@ the fixed-table and global-count regressions do not claim another demonstrated false-result acceptance. See [metadata bounds](../crates/aiur/src/synthesis/tests/lookup_budget.rs) and [fixed tables](../crates/aiur/src/synthesis/tests/byte_shapes.rs). +## Native Merkle cap coverage + +The native binary MMCS injects shorter matrices while walking from the +tallest matrix's leaves toward the root. A cap can stop that walk before a +shorter matrix is included. For an eight-row and a two-row matrix, cap +heights two and above omit the shorter matrix; changing that matrix leaves +the commitment unchanged and altered single and multiple openings verify. + +Aiur rejects this geometry before checking openings. With trace log-degrees +`d`, LDE log-blowup `b`, and configured cap height `c`, it requires +`min(c, b + max(d)) <= b + d_i` for every active matrix. The implementation +avoids addition overflow and accounts for the native cap's height clamping. +Fixed-table activity makes the preprocessed matrices part of this check too. + +Cap heights at most `b`, including the default root cap, satisfy the condition +without scanning degrees. Larger caps require a linear metadata check. No +AIR, trace width, FFT cost or proof encoding changes. Unsafe configurations +are rejected; the recursive verifier already requires cap height zero. + ## Compatibility and validation The activity, call-order and branch-gating repairs change affected AIR From 9df053217c1d3ad84c497c8bd6065955290cbddb Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 12:07:27 -0400 Subject: [PATCH 17/30] perf(aiur): specialize IxVM call ranks by checked components --- Ix/Aiur/Compiler.lean | 51 +--- Ix/Aiur/Compiler/CallOrder.lean | 182 ++++++++++++ Ix/Aiur/Compiler/Layout.lean | 80 ++++-- Ix/Aiur/Compiler/Lower.lean | 4 +- Ix/Aiur/Meta.lean | 1 + Ix/Aiur/Stages/Bytecode.lean | 16 ++ Ix/Aiur/Stages/Source.lean | 9 +- Ix/IxVM/Toplevel.lean | 3 +- Tests/Aiur.lean | 1 + Tests/Aiur/CallOrder.lean | 100 +++++++ Tests/Ix/IxVM.lean | 166 +++++------ Tests/Main.lean | 16 +- crates/aiur/src/bytecode.rs | 9 + crates/aiur/src/call_order.rs | 92 ++++++- crates/aiur/src/constraints.rs | 96 ++++--- crates/aiur/src/row_counts.rs | 1 + crates/aiur/src/synthesis.rs | 3 +- crates/aiur/src/synthesis/tests/call_order.rs | 260 +++++++++++++++++- crates/aiur/src/trace.rs | 48 +++- crates/ffi/src/aiur/toplevel.rs | 12 +- crates/ffi/src/lean.rs | 3 +- docs/aiur-soundness.md | 71 ++++- 22 files changed, 984 insertions(+), 240 deletions(-) create mode 100644 Ix/Aiur/Compiler/CallOrder.lean create mode 100644 Tests/Aiur/CallOrder.lean diff --git a/Ix/Aiur/Compiler.lean b/Ix/Aiur/Compiler.lean index 5eb558e18..9350ada61 100644 --- a/Ix/Aiur/Compiler.lean +++ b/Ix/Aiur/Compiler.lean @@ -3,6 +3,7 @@ public import Ix.Aiur.Compiler.Lower public import Ix.Aiur.Compiler.Dedup public import Ix.Aiur.Compiler.Concretize public import Ix.Aiur.Compiler.Simple +public import Ix.Aiur.Compiler.CallOrder /-! Aiur compiler pipeline: type-check, simplify, concretize, lower, deduplicate. @@ -108,55 +109,6 @@ def CompiledToplevel.groupFunctions (ct : CompiledToplevel) else throw "groupFunctions: partition already grouped; group from a freshly compiled toplevel" pure { ct with bytecode := { t with circuits } } - -/-- Termination helper for the `Block`/`Ctrl` traversal below. -/ -private theorem Bytecode.Block.sizeOf_ctrl_lt'' (b : Bytecode.Block) : - sizeOf b.ctrl < sizeOf b := by - rcases b with ⟨ops, ctrl⟩ - show sizeOf ctrl < 1 + sizeOf ops + sizeOf ctrl - omega - -mutual -/-- Collect all callee `FunIdx` values from constrained `Op.call` nodes in a -block tree. Unconstrained calls are skipped because cascading into unconstrained -mode removes the need for the callee's own circuit. -/ -def Bytecode.Ctrl.collectConstrainedCallees (c : Bytecode.Ctrl) : - Array Bytecode.FunIdx := match c with - | .match _ cases default? => - let branchCallees := cases.attach.foldl (init := #[]) fun acc ⟨(_, block), _⟩ => - acc ++ block.collectConstrainedCallees - match default? with - | some block => branchCallees ++ block.collectConstrainedCallees - | none => branchCallees - | .matchContinue _ cases default? _ _ _ continuation => - let branchCallees := cases.attach.foldl (init := #[]) fun acc ⟨(_, block), _⟩ => - acc ++ block.collectConstrainedCallees - let withDefault := match default? with - | some block => branchCallees ++ block.collectConstrainedCallees - | none => branchCallees - withDefault ++ continuation.collectConstrainedCallees - | .return _ _ | .yield _ _ => #[] -termination_by (sizeOf c, 0) -decreasing_by - all_goals first - | decreasing_tactic - | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) - | grind - -def Bytecode.Block.collectConstrainedCallees (b : Bytecode.Block) : - Array Bytecode.FunIdx := - let opCallees := b.ops.foldl (init := #[]) fun acc op => - match op with - | .call idx _ _ false => acc.push idx - | _ => acc - opCallees ++ b.ctrl.collectConstrainedCallees -termination_by (sizeOf b, 1) -decreasing_by - all_goals first - | decreasing_tactic - | (apply Prod.Lex.left; exact Bytecode.Block.sizeOf_ctrl_lt'' _) -end - /-- The default circuit partition: one singleton circuit per constrained function, in function-index order, named by `nameOf`. -/ def Bytecode.Toplevel.singletonCircuits (t : Bytecode.Toplevel) @@ -200,6 +152,7 @@ def Source.Toplevel.compile (t : Source.Toplevel) : Except String CompiledToplev let bytecode : Bytecode.Toplevel := { bytecodeDedup with functions := bytecodeDedup.functions.mapIdx fun i f => { f with constrained := needs[i]! } } + let bytecode := if t.componentRanks then bytecode.withCallComponents else bytecode let nameMap := preNameMap.fold (init := (∅ : Std.HashMap Global Bytecode.FunIdx)) fun acc name idx => acc.insert name (remap idx) -- Singleton circuits are labeled with (one of) the function's source names. diff --git a/Ix/Aiur/Compiler/CallOrder.lean b/Ix/Aiur/Compiler/CallOrder.lean new file mode 100644 index 000000000..da656161b --- /dev/null +++ b/Ix/Aiur/Compiler/CallOrder.lean @@ -0,0 +1,182 @@ +module +public import Ix.Aiur.Compiler.Layout + +public section +@[expose] section +namespace Aiur + +/-- Termination helper for the `Block`/`Ctrl` traversal below. -/ +private theorem Bytecode.Block.sizeOf_ctrl_lt'' (b : Bytecode.Block) : + sizeOf b.ctrl < sizeOf b := by + rcases b with ⟨ops, ctrl⟩ + show sizeOf ctrl < 1 + sizeOf ops + sizeOf ctrl + omega + +mutual +/-- Collect all callee `FunIdx` values from constrained `Op.call` nodes in a +block tree. Unconstrained calls are skipped because cascading into unconstrained +mode removes the need for the callee's own circuit. -/ +def Bytecode.Ctrl.collectConstrainedCallees (c : Bytecode.Ctrl) : + Array Bytecode.FunIdx := match c with + | .match _ cases default? => + let branchCallees := cases.attach.foldl (init := #[]) fun acc ⟨(_, block), _⟩ => + acc ++ block.collectConstrainedCallees + match default? with + | some block => branchCallees ++ block.collectConstrainedCallees + | none => branchCallees + | .matchContinue _ cases default? _ _ _ continuation => + let branchCallees := cases.attach.foldl (init := #[]) fun acc ⟨(_, block), _⟩ => + acc ++ block.collectConstrainedCallees + let withDefault := match default? with + | some block => branchCallees ++ block.collectConstrainedCallees + | none => branchCallees + withDefault ++ continuation.collectConstrainedCallees + | .return _ _ | .yield _ _ => #[] +termination_by (sizeOf c, 0) +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + | grind + +def Bytecode.Block.collectConstrainedCallees (b : Bytecode.Block) : + Array Bytecode.FunIdx := + let opCallees := b.ops.foldl (init := #[]) fun acc op => + match op with + | .call idx _ _ false => acc.push idx + | _ => acc + opCallees ++ b.ctrl.collectConstrainedCallees +termination_by (sizeOf b, 1) +decreasing_by + all_goals first + | decreasing_tactic + | (apply Prod.Lex.left; exact Bytecode.Block.sizeOf_ctrl_lt'' _) +end + +namespace Bytecode + +/-- Every cross-component edge advances the static order. An internal edge +must retain the existing dynamic rank relation at both endpoints. -/ +def CallComponent.permits (parent child : CallComponent) : Bool := + parent.order < child.order || + (parent.order == child.order && parent.ranked && child.ranked) + +/-- The accepted call relation is well founded once every row has a bounded +component order and rank, and same-component calls strictly increase rank. +Cross-component calls need no comparison between their endpoint ranks. + +This is the order argument used by the specialization, independent of how +the candidate components are produced. Relating AIR lookups to these row +premises still requires activity, exact lookup balance, and byte bounds. -/ +theorem CallComponent.wellFounded_calls {α : Type} (component : α → CallComponent) + (rank : α → Nat) (componentCount rankBound : Nat) + (hc : ∀ row, (component row).order < componentCount) + (hr : ∀ row, rank row < rankBound) : + WellFounded (fun child parent => + (component parent).permits (component child) = true ∧ + ((component parent).order = (component child).order → rank parent < rank child)) := by + let measure := fun row => (componentCount - (component row).order, rankBound - rank row) + apply Subrelation.wf (r := InvImage (Prod.Lex Nat.lt Nat.lt) measure) + · intro child parent h + rcases h with ⟨horder, hrank⟩ + simp only [CallComponent.permits, Bool.or_eq_true, decide_eq_true_eq, + Bool.and_eq_true, beq_iff_eq] at horder + rcases horder with horder | ⟨⟨horder, _⟩, _⟩ + · apply Prod.Lex.left + have := hc child + change componentCount - (component child).order < componentCount - (component parent).order + omega + · have h := hrank horder + have := hr child + change Prod.Lex Nat.lt Nat.lt + (componentCount - (component child).order, rankBound - rank child) + (componentCount - (component parent).order, rankBound - rank parent) + rw [horder] + apply Prod.Lex.right + change rankBound - rank child < rankBound - rank parent + omega + · exact InvImage.wf measure (Prod.lex Nat.lt_wfRel Nat.lt_wfRel).wf + +/-- A candidate certificate is checked independently of the SCC algorithm. +The native constructor repeats this check before using it to omit constraints. -/ +def Toplevel.validCallComponents (t : Toplevel) : Bool := + t.callComponents.size == t.functions.size && + t.callComponents.all (fun c => c.order < t.functions.size) && + (t.functions.mapIdx fun i f => !f.constrained || + f.body.collectConstrainedCallees.all (fun j => + match t.callComponents[i]?, t.callComponents[j]? with + | some parent, some child => parent.permits child + | _, _ => false)).all id + +def callOrderFinishDfs (graph : Array (Array Nat)) : + Nat → Nat → (Array Bool × Array Nat) → (Array Bool × Array Nat) + | 0, _, state => state + | fuel + 1, node, state => + if state.1[node]! then state else + let state := (state.1.set! node true, state.2) + let state := graph[node]!.foldl + (fun state child => callOrderFinishDfs graph fuel child state) state + (state.1, state.2.push node) + +def callOrderComponentDfs (graph : Array (Array Nat)) (component : Nat) : + Nat → Nat → Array Nat → Array Nat + | 0, _, labels => labels + | fuel + 1, node, labels => + if labels[node]! < graph.size then labels else + graph[node]!.foldl + (fun labels child => callOrderComponentDfs graph component fuel child labels) + (labels.set! node component) + +/-- Kosaraju traversal with an explicit depth bound. Graph construction uses +only constrained call edges of constrained functions. The result is checked +before it can affect a compiled layout, so correctness of this producer is +not a premise for omitting rank constraints. -/ +def Toplevel.findCallComponents (t : Toplevel) : Array CallComponent := Id.run do + let n := t.functions.size + let graph := t.functions.map fun f => + if f.constrained then f.body.collectConstrainedCallees else #[] + let mut reverse := Array.replicate n #[] + for i in [:n] do + for j in graph[i]! do + reverse := reverse.set! j (reverse[j]!.push i) + let mut visited := (Array.replicate n false, (#[] : Array Nat)) + for i in [:n] do + visited := callOrderFinishDfs graph n i visited + let mut labels := Array.replicate n n + let mut count := 0 + for i in visited.2.reverse do + if labels[i]! == n then + labels := callOrderComponentDfs reverse count n i labels + count := count + 1 + let mut sizes := Array.replicate count 0 + for label in labels do + sizes := sizes.set! label (sizes[label]! + 1) + return labels.mapIdx fun i label => + { order := label, ranked := sizes[label]! > 1 || graph[i]!.contains i } + +/-- Native and compiler layout selection agree on these three cases. -/ +def Toplevel.callRanksFor (t : Toplevel) (parent : Nat) : Array CallRank := + t.callComponents.map fun child => + if t.callComponents[parent]!.order == child.order then .ordered + else if child.ranked then .bound else .zero + +/-- Recompute every function and continuation layout after selecting ranks. +Run before constructing the circuit partition. The instruction stream, +value indices and function indices are preserved. -/ +def Toplevel.withCallComponents (t : Toplevel) : Toplevel := + let callComponents := t.findCallComponents + let candidate := { t with callComponents } + if !candidate.validCallComponents then t else + let functions := t.functions.mapIdx fun i function => + let initial := Concrete.Bytecode.LayoutMState.withCallRanks + function.layout.inputSize callComponents[i]!.ranked (candidate.callRanksFor i) + let (body, state) := Concrete.Bytecode.relayoutBlock function.body |>.run initial + { function with body, layout := { state.functionLayout with + lookups := state.functionLayout.lookups + 1 } } + { candidate with functions } + +end Bytecode + +end Aiur +end +end diff --git a/Ix/Aiur/Compiler/Layout.lean b/Ix/Aiur/Compiler/Layout.lean index 7ed54e940..7e51539ea 100644 --- a/Ix/Aiur/Compiler/Layout.lean +++ b/Ix/Aiur/Compiler/Layout.lean @@ -107,10 +107,23 @@ structure LayoutMState where functionLayout : Aiur.Bytecode.FunctionLayout memSizes : MemSizes degrees : Array Nat + /-- Empty retains the general six-byte gap at every constrained call. -/ + callRanks : Array Aiur.Bytecode.CallRank := #[] @[inline] def LayoutMState.new (inputSize : Nat) : LayoutMState := -- Multiplicity plus six rank bytes, with three byte-pair range lookups. - ⟨{ inputSize, selectors := 0, auxiliaries := 7, lookups := 3 }, .empty, Array.replicate inputSize 1⟩ + ⟨{ inputSize, selectors := 0, auxiliaries := 7, lookups := 3 }, .empty, Array.replicate inputSize 1, #[]⟩ + +def LayoutMState.withCallRanks (inputSize : Nat) (ranked : Bool) + (callRanks : Array Aiur.Bytecode.CallRank) : LayoutMState := + { functionLayout := { + inputSize := inputSize + selectors := 0 + auxiliaries := if ranked then 7 else 1 + lookups := if ranked then 3 else 0 } + memSizes := .empty + degrees := Array.replicate inputSize 1 + callRanks } abbrev LayoutM := StateM LayoutMState @@ -172,13 +185,15 @@ def opLayout : Bytecode.Op → LayoutM Unit let degree ← getDegree a if degree = 0 then pushDegree 0 else do pushDegree 1; bumpAuxiliaries 2 - | .call _ _ outputSize unconstrained => do + | .call function _ outputSize unconstrained => do pushDegrees $ .replicate outputSize 1 bumpAuxiliaries outputSize if !unconstrained then - -- Six gap bytes; the lookup derives the callee rank as caller + 1 + gap. - bumpAuxiliaries 6 - bumpLookups 4 + bumpLookups + match (← get).callRanks[function]?.getD .ordered with + | .zero => pure () + | .bound => bumpAuxiliaries + | .ordered => bumpAuxiliaries 6; bumpLookups 3 | .store values => do pushDegree 1; bumpAuxiliaries; bumpLookups; addMemSize values.size | .load size _ => do @@ -239,54 +254,58 @@ private theorem Bytecode.Block.sizeOf_ctrl_lt_layout (b : Bytecode.Block) : mutual -def ctrlLayout (c : Bytecode.Ctrl) : LayoutM Unit := match c with - | .match _ branches defaultBranch => do +def relayoutCtrl (c : Bytecode.Ctrl) : LayoutM Bytecode.Ctrl := match c with + | .match value branches defaultBranch => do let initSharedData ← getSharedData let degrees ← getDegrees -- Fold over branches, tracking the running maximum shared data. - let maximalSharedData ← branches.attach.foldlM (init := initSharedData) - fun currMax ⟨(_, block), _⟩ => do + let (branches, maximalSharedData) ← branches.attach.foldlM (init := (#[], initSharedData)) + fun (done, currMax) ⟨(value, block), _⟩ => do setSharedData initSharedData - blockLayout block + let block ← relayoutBlock block let blockSharedData ← getSharedData setDegrees degrees - pure (currMax.maximals blockSharedData) + pure (done.push (value, block), currMax.maximals blockSharedData) -- Apply default branch if present. - let finalMax ← match defaultBranch with - | none => pure maximalSharedData + let (defaultBranch, finalMax) ← match defaultBranch with + | none => pure (none, maximalSharedData) | some defaultBlock => do setSharedData initSharedData bumpAuxiliaries branches.size - blockLayout defaultBlock + let defaultBlock ← relayoutBlock defaultBlock let defaultBlockSharedData ← getSharedData setDegrees degrees - pure (maximalSharedData.maximals defaultBlockSharedData) + pure (some defaultBlock, maximalSharedData.maximals defaultBlockSharedData) setSharedData finalMax - | .return .. => bumpSelectors - | .yield .. => bumpSelectors - | .matchContinue _ branches defaultBranch outputSize _sharedAux _sharedLookups continuation => do + pure (.match value branches defaultBranch) + | .return .. => do bumpSelectors; pure c + | .yield .. => do bumpSelectors; pure c + | .matchContinue value branches defaultBranch outputSize _sharedAux _sharedLookups continuation => do let initSharedData ← getSharedData let degrees ← getDegrees - let maximalSharedData ← branches.attach.foldlM (init := initSharedData) - fun currMax ⟨(_, block), _⟩ => do + let (branches, maximalSharedData) ← branches.attach.foldlM (init := (#[], initSharedData)) + fun (done, currMax) ⟨(value, block), _⟩ => do setSharedData initSharedData - blockLayout block + let block ← relayoutBlock block let blockSharedData ← getSharedData setDegrees degrees - pure (currMax.maximals blockSharedData) - let finalMax ← match defaultBranch with - | none => pure maximalSharedData + pure (done.push (value, block), currMax.maximals blockSharedData) + let (defaultBranch, finalMax) ← match defaultBranch with + | none => pure (none, maximalSharedData) | some defaultBlock => do setSharedData initSharedData bumpAuxiliaries branches.size - blockLayout defaultBlock + let defaultBlock ← relayoutBlock defaultBlock let defaultBlockSharedData ← getSharedData setDegrees degrees - pure (maximalSharedData.maximals defaultBlockSharedData) + pure (some defaultBlock, maximalSharedData.maximals defaultBlockSharedData) setSharedData finalMax bumpAuxiliaries outputSize pushDegrees (.replicate outputSize 1) - blockLayout continuation + let continuation ← relayoutBlock continuation + pure (.matchContinue value branches defaultBranch outputSize + (finalMax.auxiliaries - initSharedData.auxiliaries) + (finalMax.lookups - initSharedData.lookups) continuation) termination_by (sizeOf c, 0) decreasing_by all_goals first @@ -294,9 +313,9 @@ decreasing_by | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) | grind -def blockLayout (block : Bytecode.Block) : LayoutM Unit := do +def relayoutBlock (block : Bytecode.Block) : LayoutM Bytecode.Block := do block.ops.forM opLayout - ctrlLayout block.ctrl + return { block with ctrl := ← relayoutCtrl block.ctrl } termination_by (sizeOf block, 1) decreasing_by all_goals first @@ -305,6 +324,9 @@ decreasing_by end +def blockLayout (block : Bytecode.Block) : LayoutM Unit := + discard (relayoutBlock block) + end Bytecode end Concrete diff --git a/Ix/Aiur/Compiler/Lower.lean b/Ix/Aiur/Compiler/Lower.lean index 039eb7dcc..115fc3872 100644 --- a/Ix/Aiur/Compiler/Lower.lean +++ b/Ix/Aiur/Compiler/Lower.lean @@ -395,7 +395,7 @@ def Concrete.computeSharedLayout let degrees := (← get).degrees let initLS : Bytecode.LayoutMState := ⟨{ inputSize := 0, selectors := 0, auxiliaries := 0, lookups := 0 }, - .empty, degrees⟩ + .empty, degrees, #[]⟩ let (sharedAux, sharedLookups) := matchCases.foldl (init := (0, 0)) fun (maxA, maxL) (_, block) => let (_, ls) := Bytecode.blockLayout block |>.run initLS @@ -633,7 +633,7 @@ def Concrete.Decls.toBytecode (decls : Concrete.Decls) : let memSizes := layoutMState.memSizes.foldl (·.insert ·) memSizes pure (functions.push function, memSizes, nameMap) | _ => pure acc - pure (⟨functions, memSizes.toArray, #[]⟩, nameMap) + pure (⟨functions, memSizes.toArray, #[], #[]⟩, nameMap) end Aiur diff --git a/Ix/Aiur/Meta.lean b/Ix/Aiur/Meta.lean index 5f8c13d32..d8fc0c423 100644 --- a/Ix/Aiur/Meta.lean +++ b/Ix/Aiur/Meta.lean @@ -813,6 +813,7 @@ def elabToplevel : ElabStxCat `aiur_toplevel ← mkArrayLit (mkConst ``DataType) dataTypes.toList, ← mkArrayLit (mkConst ``TypeAlias) typeAliases.toList, ← mkArrayLit (mkConst ``Source.Function) functions.toList, + mkConst ``Bool.false, ] | stx => throw $ .error stx "Invalid syntax for toplevel" diff --git a/Ix/Aiur/Stages/Bytecode.lean b/Ix/Aiur/Stages/Bytecode.lean index 21c52fd66..a7e051d12 100644 --- a/Ix/Aiur/Stages/Bytecode.lean +++ b/Ix/Aiur/Stages/Bytecode.lean @@ -142,6 +142,19 @@ def FunctionLayout.merge (a b : FunctionLayout) : FunctionLayout where auxiliaries := a.auxiliaries.max b.auxiliaries lookups := a.lookups.max b.lookups +inductive CallRank where + | zero + | bound + | ordered + deriving Inhabited, Repr, BEq + +/-- A checked static component order. Equal-component calls require both +endpoints to retain dynamic ranks; all other calls increase `order`. -/ +structure CallComponent where + order : Nat + ranked : Bool + deriving Inhabited, Repr, BEq + structure Toplevel where functions : Array Function memorySizes : Array Nat @@ -149,6 +162,9 @@ structure Toplevel where order. Built by `Source.Toplevel.compile` (singletons by default; see `CompiledToplevel.groupFunctions`); empty on a freshly lowered toplevel. -/ circuits : Array Circuit := #[] + /-- Empty selects the general dynamic-rank layout. Otherwise there is one + entry per function, including functions used only as unconstrained hints. -/ + callComponents : Array CallComponent := #[] deriving Repr end Bytecode diff --git a/Ix/Aiur/Stages/Source.lean b/Ix/Aiur/Stages/Source.lean index b7a1694a2..924082ea2 100644 --- a/Ix/Aiur/Stages/Source.lean +++ b/Ix/Aiur/Stages/Source.lean @@ -550,18 +550,21 @@ structure Toplevel where dataTypes : Array DataType typeAliases : Array TypeAlias functions : Array Function + /-- Compile component-local call ranks. The resulting certificate is checked + against the bytecode before native constraint construction. -/ + componentRanks : Bool := false deriving Repr def Toplevel.getFuncIdx (toplevel : Toplevel) (funcName : Lean.Name) : Option Nat := do toplevel.functions.findIdx? fun function => function.name.toName == funcName def Toplevel.merge (x y : Toplevel) : Except Global Toplevel := do - let ⟨xDT, xTA, xF⟩ := x - let ⟨yDT, yTA, yF⟩ := y + let ⟨xDT, xTA, xF, xRanks⟩ := x + let ⟨yDT, yTA, yF, yRanks⟩ := y let (globals, dataTypes) ← mergeArrays DataType.name ∅ xDT yDT let (globals, typeAliases) ← mergeArrays TypeAlias.name globals xTA yTA let (_, functions) ← mergeArrays Function.name globals xF yF - pure ⟨dataTypes, typeAliases, functions⟩ + pure ⟨dataTypes, typeAliases, functions, xRanks || yRanks⟩ where mergeArrays {α : Type} (getName : α → Global) (globals : Std.HashSet Global) (xs ys : Array α) : Except Global (Std.HashSet Global × Array α) := do diff --git a/Ix/IxVM/Toplevel.lean b/Ix/IxVM/Toplevel.lean index 8af0a4b4c..8e1aba98e 100644 --- a/Ix/IxVM/Toplevel.lean +++ b/Ix/IxVM/Toplevel.lean @@ -206,7 +206,8 @@ def ixVMFull : Except Aiur.Global Aiur.Source.Toplevel := do let vm ← vm.merge canonicalCheck let vm ← vm.merge check let vm ← vm.merge claim - vm.merge entrypoints + let vm ← vm.merge entrypoints + pure { vm with componentRanks := true } /-- Pruned production toplevel: `verify_claim` and nothing else. diff --git a/Tests/Aiur.lean b/Tests/Aiur.lean index dcdafc545..fcc0baf0e 100644 --- a/Tests/Aiur.lean +++ b/Tests/Aiur.lean @@ -2,6 +2,7 @@ module public import Tests.Aiur.Common public import Tests.Aiur.Aiur +public import Tests.Aiur.CallOrder public import Tests.Aiur.Cost public import Tests.Aiur.Hashes public import Tests.Aiur.RBTreeMap diff --git a/Tests/Aiur/CallOrder.lean b/Tests/Aiur/CallOrder.lean new file mode 100644 index 000000000..a6dacab23 --- /dev/null +++ b/Tests/Aiur/CallOrder.lean @@ -0,0 +1,100 @@ +module + +public import Tests.Aiur.Aiur + +public section + +open LSpec Aiur + +namespace AiurTests.CallOrder + +def graphToplevel (graph : Array (Array Bool)) : Bytecode.Toplevel where + functions := graph.map fun edges => { + body := { + ops := (edges.mapIdx fun i edge => if edge then #[.call i #[] 0 false] else #[]).flatten + ctrl := .return 0 #[] } + layout := ⟨0, 1, 7, 4⟩ + entry := true + constrained := true } + memorySizes := #[] + +/-- Floyd-Warshall is an independent reachability oracle for the DFS-based +component producer. Exhaust all 512 directed graphs on three vertices, +including self-loops, disconnected cycles and multiple components. -/ +def allThreeVertexGraphs : Bool := Id.run do + for bits in [:512] do + let graph := (Array.range 3).map fun i => + (Array.range 3).map fun j => bits / 2 ^ (3 * i + j) % 2 == 1 + let top := graphToplevel graph + let components := top.findCallComponents + if !({ top with callComponents := components }).validCallComponents then return false + let mut reach := graph + for k in [:3] do + for i in [:3] do + for j in [:3] do + if reach[i]![k]! && reach[k]![j]! then + reach := reach.set! i (reach[i]!.set! j true) + for i in [:3] do + if components[i]!.ranked != reach[i]![i]! then return false + for j in [:3] do + let same := components[i]!.order == components[j]!.order + if same != (i == j || (reach[i]![j]! && reach[j]![i]!)) then return false + return true + +def graphChecks : TestSeq := + let cyclic := graphToplevel #[#[true]] + let advice : Bytecode.Toplevel := { cyclic with + functions := cyclic.functions.map fun (f : Bytecode.Function) => + { f with body := { f.body with ops := #[.call 0 #[] 0 true] } } } + test "component producer agrees with reachability on all three-vertex graphs" + allThreeVertexGraphs ++ + test "an unconstrained call does not introduce a recursive component" + (!(advice.findCallComponents[0]!).ranked) ++ + test "an unranked self-cycle fails the independent certificate checker" + (!({ cyclic with callComponents := #[⟨0, false⟩] }).validCallComponents) ++ + test "a ranked self-cycle passes the static checker and retains dynamic checks" + (({ cyclic with callComponents := #[⟨0, true⟩] } : Bytecode.Toplevel).validCallComponents) + +def structureChecks (base specialized : CompiledToplevel) : TestSeq := + let t := specialized.bytecode + let idx := fun name => specialized.getFuncIdx name |>.get! + let ranked := fun name => t.callComponents[idx name]!.ranked + let callRank := fun parent child => (t.callRanksFor (idx parent))[idx child]! + test "generic Aiur retains the default dynamic layout" base.bytecode.callComponents.isEmpty ++ + test "specialized bytecode carries a valid component certificate" t.validCallComponents ++ + test "acyclic group members omit row ranks" + (!ranked `grouped_double && !ranked `grouped_pick && !ranked `calls_grouped) ++ + test "recursive group member retains its row rank" (ranked `grouped_sum_range) ++ + test "acyclic callees use rank zero" (callRank `calls_grouped `grouped_pick == .zero) ++ + test "a boundary call binds the recursive callee rank" + (callRank `calls_grouped `grouped_sum_range == .bound) ++ + test "recursive internal calls retain ordered gaps" + (callRank `grouped_sum_range `grouped_sum_range == .ordered) ++ + test "specialization preserves indices, inputs and selectors and never widens a function" + (t.functions.size == base.bytecode.functions.size && + (t.functions.mapIdx fun i f => + let old := base.bytecode.functions[i]!.layout + f.layout.inputSize == old.inputSize && f.layout.selectors == old.selectors && + f.layout.auxiliaries ≤ old.auxiliaries && f.layout.lookups ≤ old.lookups).all id) + +/-- Run the existing proving corpus with component layouts as well as the +generic layout. It covers nested shared continuations, empty branches, +early returns, memories, advice and grouped recursion through the FFI. -/ +def suite : IO UInt32 := do + let .ok base := toplevel.compile | IO.eprintln "Generic Aiur compilation failed"; return 1 + let source := { toplevel with componentRanks := true } + let .ok env := AiurTestEnv.build (pure source) + | IO.eprintln "Aiur component setup failed"; return 1 + let r1 ← LSpec.lspecIO + (.ofList [("aiur-components", [graphChecks, structureChecks base env.compiled])]) [] + let r2 ← LSpec.lspecEachIO aiurTestCases fun tc => pure (env.runTestCase tc) + let .ok grouped := AiurTestEnv.build (pure source) testGroups + | IO.eprintln "Grouped Aiur component setup failed"; return 1 + let r3 ← LSpec.lspecEachIO groupedTestCases fun tc => pure (grouped.runTestCase tc) + let r4 ← LSpec.lspecIO + (.ofList [("aiur-component-groups", [groupingStructureChecks grouped.compiled])]) [] + return if r1 == 0 && r2 == 0 && r3 == 0 && r4 == 0 then 0 else 1 + +end AiurTests.CallOrder + +end diff --git a/Tests/Ix/IxVM.lean b/Tests/Ix/IxVM.lean index 674257010..c26d570e9 100644 --- a/Tests/Ix/IxVM.lean +++ b/Tests/Ix/IxVM.lean @@ -439,89 +439,89 @@ private def nameOfString (str : String) : Lean.Name := and an improvement has to be acknowledged by re-pinning. These pins include the range-checked call ranks that exclude cyclic proof traces. -/ private def kernelCheckEntries : List (String × Nat) := [ - ("HEq", 130_063_964), - ("HEq.rec", 137_144_830), - ("Eq.rec", 135_853_875), - ("Nat", 130_038_091), - ("Nat.add", 196_113_905), - ("Nat.add_comm", 440_435_264), - ("Nat.decEq", 556_459_970), - ("Nat.decLe", 1_286_115_140), - ("Nat.sub_le_of_le_add", 3_248_665_220), - ("Nat.shiftRight_succ", 2_388_210_480), - ("Trans.mk", 144_551_603), - ("Array.append_assoc", 16_174_150_842), - ("Vector.append", 16_510_547_185), - ("IxVMPrim.nat_add_lit", 259_971_314), - ("IxVMPrim.nat_sub_lit", 281_296_898), - ("IxVMPrim.nat_mul_lit", 244_082_273), - ("IxVMPrim.nat_mul_big", 241_982_822), - ("IxVMPrim.nat_div_lit", 2_325_278_806), - ("IxVMPrim.nat_mod_lit", 2_368_797_473), - ("IxVMPrim.nat_succ_lit", 150_684_613), - ("IxVMPrim.nat_pred_lit", 182_525_416), - ("IxVMPrim.nat_gcd_lit", 3_695_290_130), - ("IxVMPrim.nat_land_lit", 6_067_448_237), - ("IxVMPrim.nat_lor_lit", 6_070_270_621), - ("IxVMPrim.nat_xor_lit", 6_097_744_386), - ("IxVMPrim.nat_shl_lit", 288_279_659), - ("IxVMPrim.nat_shr_lit", 2_346_576_264), - ("IxVMPrim.nat_pow_big", 613_539_648), - ("IxVMPrim.nat_beq_lit", 242_500_472), - ("IxVMPrim.nat_ble_lit", 234_680_923), - ("IxVMPrim.nat_cases_big", 183_664_406), - ("IxVMPrim.nat_dec_le", 1_313_242_714), - ("IxVMPrim.nat_dec_lt", 1_330_953_467), - ("IxVMPrim.nat_dec_eq", 616_553_367), - ("IxVMPrim.str_size_lit", 4_185_234_171), - ("IxVMPrim.bv_to_nat_lit", 3_521_018_085), - ("IxVMInd.Even", 248_955_631), - ("IxVMInd.Odd", 248_965_174), - ("IxVMInd.Even.rec", 279_138_584), - ("IxVMInd.Odd.rec", 279_137_655), - ("IxVMInd.IdxTeleN.rec", 176_475_354), - ("IxVMInd.IdxTeleB.rec", 176_473_662), - ("IxVMInd.SoloA.rec", 168_533_822), - ("IxVMInd.SoloB.rec", 168_532_985), - ("IxVMInd.UnsafeSquash", 132_487_201), - ("IxVMInd.Tree", 132_417_126), - ("IxVMInd.Tree.rec", 149_294_954), - ("IxVMInd.DedupM", 136_761_695), - ("IxVMInd.DedupM.rec", 159_608_637), - ("IxVMInd.DepthM", 134_723_038), - ("IxVMInd.DepthM.rec", 153_452_640), - ("String.Internal.append", 4_140_807_948), - ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 6_181_591_136), - ("Lean.Syntax.rec", 4_236_356_723), - ("IxVMInd.AuxTie", 415_758_887), - ("IxVMInd.AuxTie.rec", 489_153_212), - ("IxVMInd.HiddenIdx", 131_272_312), - ("IxVMInd.HiddenIdx.rec", 136_701_447), - ("IxVMInd.thmMajorUse", 786_940_447), - ("IxVMInd.partialKRec", 161_480_092), - ("IxVMInd.deepRebase", 275_651_442), - ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 5_878_736_958), - ("Lean.Widget.TaggedText.rec", 4_195_436_311), - ("Lean.Doc.Part.rec", 4_268_571_152), - ("Lean.Doc.Block.rec", 4_697_476_168), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 134_049_039), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 139_391_417), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 139_039_561), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 139_039_561), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 139_039_561), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 134_536_025), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 153_305_989), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 153_304_407), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 139_039_561), - ("strOfListFoldSize", 4_632_656_203), - ("strOfListFoldSizeAscii", 4_633_712_616), - ("IxVMPrim.lazy_ble_offset", 293_329_152), - ("IxVMPrim.lazy_unit_cast", 836_781_702), - ("IxVMPrim.sizeof_unit", 173_827_975), - ("IxVMPerf.let_continuations", 194_323_668), - ("IxVMPerf.mul_row", 558_915_114), - ("IxVMPerf.context_tower", 844_858_461), - ("IxVMPerf.mul_wide", 372_109_314), + ("HEq", 129_902_362), + ("HEq.rec", 135_719_723), + ("Eq.rec", 134_721_481), + ("Nat", 129_858_617), + ("Nat.add", 186_636_625), + ("Nat.add_comm", 397_590_325), + ("Nat.decEq", 489_311_794), + ("Nat.decLe", 1_116_803_161), + ("Nat.sub_le_of_le_add", 2_788_278_330), + ("Nat.shiftRight_succ", 2_056_813_337), + ("Trans.mk", 140_772_036), + ("Array.append_assoc", 13_728_577_860), + ("Vector.append", 14_018_670_718), + ("IxVMPrim.nat_add_lit", 242_677_455), + ("IxVMPrim.nat_sub_lit", 261_801_013), + ("IxVMPrim.nat_mul_lit", 229_615_579), + ("IxVMPrim.nat_mul_big", 227_685_285), + ("IxVMPrim.nat_div_lit", 2_004_547_538), + ("IxVMPrim.nat_mod_lit", 2_042_357_932), + ("IxVMPrim.nat_succ_lit", 148_404_937), + ("IxVMPrim.nat_pred_lit", 176_619_587), + ("IxVMPrim.nat_gcd_lit", 3_174_004_542), + ("IxVMPrim.nat_land_lit", 5_220_684_861), + ("IxVMPrim.nat_lor_lit", 5_223_321_528), + ("IxVMPrim.nat_xor_lit", 5_248_107_752), + ("IxVMPrim.nat_shl_lit", 268_740_688), + ("IxVMPrim.nat_shr_lit", 2_024_069_102), + ("IxVMPrim.nat_pow_big", 579_150_476), + ("IxVMPrim.nat_beq_lit", 227_350_938), + ("IxVMPrim.nat_ble_lit", 220_750_813), + ("IxVMPrim.nat_cases_big", 177_261_421), + ("IxVMPrim.nat_dec_le", 1_140_682_160), + ("IxVMPrim.nat_dec_lt", 1_156_120_001), + ("IxVMPrim.nat_dec_eq", 541_543_503), + ("IxVMPrim.str_size_lit", 3_612_596_962), + ("IxVMPrim.bv_to_nat_lit", 3_026_839_361), + ("IxVMInd.Even", 233_700_149), + ("IxVMInd.Odd", 233_707_552), + ("IxVMInd.Even.rec", 259_591_321), + ("IxVMInd.Odd.rec", 259_590_392), + ("IxVMInd.IdxTeleN.rec", 170_416_005), + ("IxVMInd.IdxTeleB.rec", 170_414_314), + ("IxVMInd.SoloA.rec", 163_719_901), + ("IxVMInd.SoloB.rec", 163_719_064), + ("IxVMInd.UnsafeSquash", 132_141_826), + ("IxVMInd.Tree", 131_889_662), + ("IxVMInd.Tree.rec", 146_285_824), + ("IxVMInd.DedupM", 135_837_240), + ("IxVMInd.DedupM.rec", 155_200_872), + ("IxVMInd.DepthM", 133_949_059), + ("IxVMInd.DepthM.rec", 149_696_625), + ("String.Internal.append", 3_572_298_590), + ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 5_320_050_458), + ("Lean.Syntax.rec", 3_654_823_020), + ("IxVMInd.AuxTie", 383_926_597), + ("IxVMInd.AuxTie.rec", 446_507_007), + ("IxVMInd.HiddenIdx", 131_017_184), + ("IxVMInd.HiddenIdx.rec", 135_576_974), + ("IxVMInd.thmMajorUse", 689_746_612), + ("IxVMInd.partialKRec", 157_250_810), + ("IxVMInd.deepRebase", 255_520_668), + ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 5_037_942_193), + ("Lean.Widget.TaggedText.rec", 3_617_889_956), + ("Lean.Doc.Part.rec", 3_679_734_499), + ("Lean.Doc.Block.rec", 4_040_375_211), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 133_464_042), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 138_164_164), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 137_402_699), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 137_402_699), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 137_402_699), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 133_825_940), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 149_898_054), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 149_896_472), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 137_402_699), + ("strOfListFoldSize", 4_003_481_843), + ("strOfListFoldSizeAscii", 4_004_495_937), + ("IxVMPrim.lazy_ble_offset", 272_065_748), + ("IxVMPrim.lazy_unit_cast", 733_066_610), + ("IxVMPrim.sizeof_unit", 169_076_166), + ("IxVMPerf.let_continuations", 181_924_142), + ("IxVMPerf.mul_row", 510_801_740), + ("IxVMPerf.context_tower", 731_464_127), + ("IxVMPerf.mul_wide", 303_686_118), ] /-- Variant of `kernelChecks`, pinned to the baseline diff --git a/Tests/Main.lean b/Tests/Main.lean index 61709b0d0..9b24b1b59 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -163,6 +163,7 @@ execute at module initialization for unrelated invocations. All are seconds-scale (measured 2026-08-05: aiur-prove ~11s, the rest 2-4s each). -/ def primaryRunners : List (String × IO UInt32) := [ + ("aiur-components", AiurTests.CallOrder.suite), ("aiur-prove", do IO.println "aiur-prove" match AiurTestEnv.build (pure toplevel) with @@ -230,6 +231,11 @@ def ignoredRunners (env : Lean.Environment) : List (String × IO UInt32) := [ | .error e, _ | _, .error e => IO.eprintln s!"IxVM env build failed: {e}"; return 1 | .ok v2Env, .ok v2FullEnv => + let componentSeq := + LSpec.test "production IxVM has a checked component certificate" + v2Env.compiled.bytecode.validCallComponents ++ + LSpec.test "full IxVM has a checked component certificate" + v2FullEnv.compiled.bytecode.validCallComponents -- Kernel-arena fixtures: the repo's NEGATIVE corpus (every -- `bad_*` must be rejected by an in-kernel assert_eq!). Runs -- through the kernel's subject-only `verify_const` debug @@ -273,16 +279,16 @@ def ignoredRunners (env : Lean.Environment) : List (String × IO UInt32) := [ | .ok (_, _, qc) => -- Exact pin, same convention as `kernelCheckEntries` -- (`.round.toUInt64.toNat`): any cost shift must be an - -- explicit, reviewed bump. Includes call-order rank columns - -- and their byte-range lookups. + -- explicit, reviewed bump. Includes component-local call ranks + -- and their remaining byte-range lookups. let actual := (Aiur.computeStats v2Env.compiled qc v2Env.shapes).totalFftCost.round.toUInt64.toNat pure (LSpec.test - s!"Shard pipeline FFT matches: expected 10_431_803_035, got {actual}" - (actual = 10_431_803_035)) + s!"Shard pipeline FFT matches: expected 9_407_996_708, got {actual}" + (actual = 9_407_996_708)) LSpec.lspecIO (.ofList [("ixvm", - [fullSeq, aiurSeq, arenaSeq, exploitSeq, paritySeq, shardSeq])]) []), + [componentSeq, fullSeq, aiurSeq, arenaSeq, exploitSeq, paritySeq, shardSeq])]) []), ("validate-aux", runCompileValidateAux env), -- Cross-compiler differential over the same fixture corpus: pure-Lean -- Ix.CompileM per-block vs Rust, root-cause classified (see diff --git a/crates/aiur/src/bytecode.rs b/crates/aiur/src/bytecode.rs index 3349906ff..732c08725 100644 --- a/crates/aiur/src/bytecode.rs +++ b/crates/aiur/src/bytecode.rs @@ -10,6 +10,15 @@ pub struct Toplevel { /// `CompiledToplevel.groupFunctions` regroups); every constrained /// function appears in exactly one circuit. pub circuits: Vec, + /// Empty uses general dynamic ranks. Otherwise one checked component + /// assignment per function selects which rank constraints are necessary. + pub call_components: Vec, +} + +#[derive(Clone, Copy, Debug)] +pub struct CallComponent { + pub order: usize, + pub ranked: bool, } /// A circuit of the proving system, backing one or more functions. Ungrouped diff --git a/crates/aiur/src/call_order.rs b/crates/aiur/src/call_order.rs index 214b40aee..0b6084dbd 100644 --- a/crates/aiur/src/call_order.rs +++ b/crates/aiur/src/call_order.rs @@ -4,7 +4,10 @@ use multi_stark::p3_field::PrimeCharacteristicRing; use rustc_hash::FxHashMap; -use crate::G; +use crate::{ + G, + bytecode::{CallComponent, Ctrl, Op, Toplevel}, +}; /// Ranks and positive call-order gaps are below 2^48. Their sum is below /// 2^49, well below the Goldilocks modulus, so an AIR equality cannot wrap. @@ -12,6 +15,93 @@ pub(crate) const RANK_BYTES: usize = 6; pub(crate) const RANK_BOUND: u64 = 1 << (8 * RANK_BYTES); pub(crate) const RANK_LOOKUPS: usize = RANK_BYTES / 2; +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(crate) enum CallRank { + Zero, + Bound, + Ordered, +} + +pub(crate) fn row_uses_rank( + components: &[CallComponent], + function: usize, +) -> bool { + components.is_empty() || components[function].ranked +} + +/// Used only after the component certificate has been checked. A boundary +/// call still binds a ranked callee's return, without imposing a rank gap. +pub(crate) fn call_rank( + components: &[CallComponent], + parent: usize, + child: usize, +) -> CallRank { + if components.is_empty() + || components[parent].order == components[child].order + { + CallRank::Ordered + } else if components[child].ranked { + CallRank::Bound + } else { + CallRank::Zero + } +} + +impl Toplevel { + /// Check the certificate from the actual constrained bytecode edges, + /// including branches, defaults and shared continuations. Every cycle + /// must stay within one component, where both endpoints retain ranks. + pub fn validate_call_components(&self) -> Result<(), &'static str> { + if self.call_components.is_empty() { + return Ok(()); + } + if self.call_components.len() != self.functions.len() { + return Err("call component count differs from function count"); + } + if self + .call_components + .iter() + .any(|component| component.order >= self.functions.len()) + { + return Err("call component order exceeds function count"); + } + for (index, function) in self.functions.iter().enumerate() { + if !function.constrained { + continue; + } + let parent = self.call_components[index]; + let mut blocks = vec![&function.body]; + while let Some(block) = blocks.pop() { + for op in &block.ops { + if let Op::Call(child, _, _, false) = op { + let Some(child) = self.call_components.get(*child) else { + return Err("call component refers to a missing function"); + }; + if !(parent.order < child.order + || (parent.order == child.order && parent.ranked && child.ranked)) + { + return Err("call violates the static component order"); + } + } + } + match &block.ctrl { + Ctrl::Return(..) | Ctrl::Yield(..) => {}, + Ctrl::Match(_, branches, fallback) => { + blocks.extend(branches.values()); + blocks.extend(fallback.as_deref()); + }, + Ctrl::MatchContinue(_, branches, fallback, _, _, _, continuation) => { + blocks.extend(branches.values()); + blocks.extend(fallback.as_deref()); + blocks.push(continuation); + }, + } + } + } + Ok(()) + } +} + /// Extra byte-table queries generated by call-order witnesses. Each worker /// accumulates locally; the prover merges these before building Bytes2. pub(crate) type RankRanges = FxHashMap<[u8; 2], G>; diff --git a/crates/aiur/src/constraints.rs b/crates/aiur/src/constraints.rs index 9d070be47..a737f918f 100644 --- a/crates/aiur/src/constraints.rs +++ b/crates/aiur/src/constraints.rs @@ -6,8 +6,8 @@ use std::{array, ops::Range, sync::LazyLock}; use crate::{ FxIndexMap, G, - bytecode::{Block, Ctrl, Op, Toplevel, ValIdx}, - call_order::{RANK_BYTES, RANK_LOOKUPS}, + bytecode::{Block, CallComponent, Ctrl, Op, Toplevel, ValIdx}, + call_order::{CallRank, RANK_BYTES, RANK_LOOKUPS, call_rank, row_uses_rank}, function_channel, gadgets::{ AiurGadget, @@ -65,10 +65,13 @@ pub struct Constraints { pub width: usize, } -struct ConstraintState { +struct ConstraintState<'a> { + function: usize, + call_components: &'a [CallComponent], /// Index of the circuit member currently being walked. function_index: G, - /// Packed 48-bit rank of this row, shared across circuit members. + /// Packed 48-bit row rank, or zero for an acyclic member. Ranked members + /// share their byte columns with each other and with acyclic operations. rank: Expr, /// One function with terminal control and one selector: operation slots /// have one writer. Selector count alone does not exclude empty branches. @@ -95,7 +98,7 @@ struct SharedState { map_len: usize, } -impl ConstraintState { +impl ConstraintState<'_> { fn selector_index(&self, sel: usize) -> usize { sel + self.sel_base } @@ -184,6 +187,8 @@ impl Toplevel { width: layout.width(), }; let mut state = ConstraintState { + function: 0, + call_components: &self.call_components, function_index: G::ZERO, rank: konst(G::ZERO), branchless: self.circuit_is_branchless(circuit_index), @@ -202,22 +207,31 @@ impl Toplevel { state.lookups[0].multiplicity = -multiplicity.clone(); let aux_start = layout.input_size + layout.selectors + 1; let rank_bytes: [Expr; RANK_BYTES] = array::from_fn(|i| var(aux_start + i)); - state.rank = + let packed_rank = rank_bytes.iter().enumerate().fold(konst(G::ZERO), |acc, (i, byte)| { acc + byte.clone() * konst(G::from_u64(1 << (8 * i))) }); let mut sel_base = layout.input_size; let mut circuit_sel = Expr::from(G::ZERO); + let mut ranked_sel = Expr::from(G::ZERO); + let mut has_ranked_member = false; for &member in &circuit.members { let function = &self.functions[member]; + let ranked = row_uses_rank(&self.call_components, member); + state.function = member; state.function_index = G::from_usize(member); + state.rank = if ranked { packed_rank.clone() } else { konst(G::ZERO) }; state.input_size = function.layout.input_size; state.sel_base = sel_base; - state.column = aux_start + RANK_BYTES; - state.lookup = 1 + RANK_LOOKUPS; + state.column = aux_start + if ranked { RANK_BYTES } else { 0 }; + state.lookup = 1 + if ranked { RANK_LOOKUPS } else { 0 }; state.map.clear(); (0..function.layout.input_size).for_each(|i| state.map.push((var(i), 1))); let body_sel = function.body.get_block_selector(&state); + if ranked { + ranked_sel = ranked_sel + body_sel.clone(); + has_ranked_member = true; + } circuit_sel = circuit_sel + body_sel.clone(); function.body.collect_constraints(body_sel, &mut state); debug_assert!(state.yield_info.is_empty()); @@ -240,11 +254,13 @@ impl Toplevel { .zeros .push(circuit_sel.clone() * (Expr::from(G::ONE) - circuit_sel.clone())); } - // Rank bytes are shared across members and checked once for an active - // circuit row. An inactive row emits no byte-table queries. - state.lookup = 1; - for pair in rank_bytes.as_chunks::<2>().0 { - state.range_pair(&circuit_sel, pair[0].clone(), pair[1].clone()); + // Check rank bytes only for an active ranked member. Acyclic members + // reuse these columns and lookup slots for their ordinary operations. + if has_ranked_member { + state.lookup = 1; + for pair in rank_bytes.as_chunks::<2>().0 { + state.range_pair(&ranked_sel, pair[0].clone(), pair[1].clone()); + } } // Only an active member can supply a return lookup. In particular, // branchless return arguments are ungated, so an inactive row with a @@ -260,7 +276,7 @@ fn empty_lookup() -> Lookup { } impl Block { - fn collect_constraints(&self, sel: Expr, state: &mut ConstraintState) { + fn collect_constraints(&self, sel: Expr, state: &mut ConstraintState<'_>) { // Boolean constraint for this block's selector let block_sel = self.get_block_selector(state); state @@ -277,7 +293,7 @@ impl Block { /// selectors — crucially excluding the MatchContinue's continuation, /// whose return selector fires alongside a yield selector and must not /// be double-counted. - fn get_block_selector(&self, state: &ConstraintState) -> Expr { + fn get_block_selector(&self, state: &ConstraintState<'_>) -> Expr { match &self.ctrl { Ctrl::Return(sel, _) | Ctrl::Yield(sel, _) => { var(state.selector_index(*sel)) @@ -303,7 +319,7 @@ fn collect_branch_constraints( var_idx: ValIdx, cases: &FxIndexMap, def: &Option>, - state: &mut ConstraintState, + state: &mut ConstraintState<'_>, ) -> (usize, usize) { let (matched, _) = state.map[var_idx].clone(); let init = state.save(); @@ -339,7 +355,7 @@ fn collect_branch_constraints( impl Ctrl { #[allow(clippy::needless_pass_by_value)] - fn collect_constraints(&self, sel: Expr, state: &mut ConstraintState) { + fn collect_constraints(&self, sel: Expr, state: &mut ConstraintState<'_>) { match self { Ctrl::Return(_, values) => { // channel and function index @@ -429,7 +445,7 @@ impl Ctrl { } impl Op { - fn collect_constraints(&self, sel: &Expr, state: &mut ConstraintState) { + fn collect_constraints(&self, sel: &Expr, state: &mut ConstraintState<'_>) { match self { Op::Const(f) => state.map.push(((*f).into(), 0)), Op::Add(a, b) => { @@ -509,25 +525,37 @@ impl Op { lookup_args .extend(output.into_iter().map(|col| state.gate(sel, col))); - let gap_bytes: [Expr; RANK_BYTES] = - array::from_fn(|_| state.next_auxiliary()); - let gap = gap_bytes.iter().enumerate().fold( - konst(G::ZERO), - |acc, (i, byte)| { - acc + byte.clone() * konst(G::from_u64(1 << (8 * i))) + let mut gap_bytes = None; + let callee_rank = match call_rank( + state.call_components, + state.function, + *function_index, + ) { + CallRank::Zero => konst(G::ZERO), + // The provider binds and range-checks this field. Static + // component order makes a dynamic gap unnecessary here. + CallRank::Bound => state.next_auxiliary(), + CallRank::Ordered => { + let bytes: [Expr; RANK_BYTES] = + array::from_fn(|_| state.next_auxiliary()); + let gap = bytes.iter().enumerate().fold( + konst(G::ZERO), + |acc, (i, byte)| { + acc + byte.clone() * konst(G::from_u64(1 << (8 * i))) + }, + ); + gap_bytes = Some(bytes); + state.rank.clone() + konst(G::ONE) + gap }, - ); - // Bind the derived rank directly through the callee's return - // lookup. Both row ranks and gaps are range checked, so this - // cannot wrap the field to close a cycle. The expression stays - // linear and needs no separate rank column or equality. - let callee_rank = state.rank.clone() + konst(G::ONE) + gap; + }; lookup_args.push(state.gate(sel, callee_rank)); let lookup = state.next_lookup(); combine_lookup_args(lookup, lookup_args); lookup.multiplicity = lookup.multiplicity.clone() + sel.clone(); - for pair in gap_bytes.as_chunks::<2>().0 { - state.range_pair(sel, pair[0].clone(), pair[1].clone()); + if let Some(bytes) = gap_bytes { + for pair in bytes.as_chunks::<2>().0 { + state.range_pair(sel, pair[0].clone(), pair[1].clone()); + } } } }, @@ -872,7 +900,7 @@ fn bytes1_constraints( op: &Bytes1Op, channel: G, sel: Expr, - state: &mut ConstraintState, + state: &mut ConstraintState<'_>, ) { let size = Bytes1.output_size(op); @@ -901,7 +929,7 @@ fn bytes2_constraints( op: &Bytes2Op, channel: G, sel: Expr, - state: &mut ConstraintState, + state: &mut ConstraintState<'_>, ) { let size = Bytes2.output_size(op); diff --git a/crates/aiur/src/row_counts.rs b/crates/aiur/src/row_counts.rs index 76cb19d1c..beff543aa 100644 --- a/crates/aiur/src/row_counts.rs +++ b/crates/aiur/src/row_counts.rs @@ -157,6 +157,7 @@ mod tests { }], memory_sizes: vec![], circuits: vec![Circuit { members: vec![0], layout }], + call_components: vec![], } } diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index d36a2eb1e..6a7295c7d 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -140,6 +140,7 @@ impl AiurSystem { ) -> Self { let claim_shapes = toplevel.checked_claim_shapes().expect("invalid Aiur lookup shapes"); + toplevel.validate_call_components().expect("invalid Aiur call components"); toplevel.validate_row_counts().expect("invalid Aiur control counts"); let mut circuit_inputs: Vec> = Vec::new(); let mut slot_widths: Vec> = Vec::new(); @@ -717,7 +718,7 @@ mod tests { layout: f.layout, }) .collect(); - Toplevel { functions, memory_sizes, circuits } + Toplevel { functions, memory_sizes, circuits, call_components: vec![] } } fn mul_toplevel() -> Toplevel { diff --git a/crates/aiur/src/synthesis/tests/call_order.rs b/crates/aiur/src/synthesis/tests/call_order.rs index 8d274f00f..5e5b6a0cb 100644 --- a/crates/aiur/src/synthesis/tests/call_order.rs +++ b/crates/aiur/src/synthesis/tests/call_order.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use super::*; +use crate::bytecode::{CallComponent, Circuit}; use crate::call_order::{RANK_BOUND, RANK_BYTES, RankRanges}; use multi_stark::eval::{VarValues, eval_expr}; @@ -28,7 +29,7 @@ fn cycle_toplevel(grouped: bool) -> Toplevel { let mut top = with_singleton_circuits(functions, vec![]); if grouped { top.circuits.truncate(1); - top.circuits.push(crate::bytecode::Circuit { + top.circuits.push(Circuit { members: vec![1, 2], layout: FunctionLayout { input_size: 1, @@ -41,6 +42,237 @@ fn cycle_toplevel(grouped: bool) -> Toplevel { top } +fn component_cycle_toplevel(grouped: bool) -> Toplevel { + let mut top = cycle_toplevel(grouped); + top.call_components = vec![ + CallComponent { order: 0, ranked: false }, + CallComponent { order: 1, ranked: true }, + CallComponent { order: 1, ranked: true }, + ]; + // The acyclic root keeps only multiplicity, output and the bound callee + // rank. The mutually recursive providers retain all their rank checks. + top.functions[0].layout.auxiliaries = 3; + top.functions[0].layout.lookups = 2; + top.circuits[0].layout = top.functions[0].layout; + top +} + +#[test] +fn component_certificates_reject_unranked_cycles_and_invalid_orders() { + let mut top = component_cycle_toplevel(false); + assert_eq!(top.validate_call_components(), Ok(())); + top.call_components[1].ranked = false; + assert!(top.validate_call_components().is_err()); + top.call_components[1].ranked = true; + top.call_components[2].order = 2; + assert!(top.validate_call_components().is_err(), "backward edge"); + top.call_components[2].order = 1; + top.call_components[0].order = 3; + assert!(top.validate_call_components().is_err(), "out-of-bounds order"); + top.call_components.pop(); + assert!(top.validate_call_components().is_err(), "missing component"); + + let mut top = component_cycle_toplevel(false); + top.functions[0].body.ops = vec![Op::Call(3, vec![0], 1, false)]; + assert!(top.validate_call_components().is_err(), "missing callee"); +} + +#[test] +fn component_checker_visits_branches_defaults_and_continuations() { + for location in 0..3 { + let mut top = component_cycle_toplevel(false); + let backedge = || Block { + ops: vec![Op::Call(0, vec![0], 1, false)], + ctrl: Ctrl::Yield(0, vec![1]), + }; + let empty = || Block { ops: vec![], ctrl: Ctrl::Yield(0, vec![0]) }; + top.functions[1].body = Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + [(G::ZERO, if location == 0 { backedge() } else { empty() })] + .into_iter() + .collect(), + Some(Box::new(if location == 1 { backedge() } else { empty() })), + 1, + 0, + 0, + Box::new(if location == 2 { backedge() } else { empty() }), + ), + }; + assert!( + top.validate_call_components().is_err(), + "hidden edge at {location}" + ); + } +} + +#[test] +#[should_panic(expected = "call violates the static component order")] +fn system_construction_rejects_a_forged_component_certificate() { + let mut top = component_cycle_toplevel(false); + top.call_components[2].ranked = false; + let (cp, fp) = test_parameters(); + let _ = AiurSystem::build(top, cp, fp); +} + +/// f promotes and shares g(n); g recurses to zero, then calls acyclic h. +/// Values above 255 also detect accidental range checks on acyclic members +/// when their operation columns overlap a recursive member's rank bytes. +fn component_promotion_toplevel(grouped: bool) -> Toplevel { + let root = Function { + body: Block { + ops: vec![ + Op::Call(1, vec![0], 1, true), + Op::Call(1, vec![0], 1, false), + Op::Call(1, vec![0], 1, false), + Op::Add(2, 3), + ], + ctrl: Ctrl::Return(0, vec![4]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 6, + lookups: 3, + }, + entry: true, + constrained: true, + }; + let recursive = Function { + body: Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + [( + G::ZERO, + Block { + ops: vec![Op::Call(2, vec![0], 1, false)], + ctrl: Ctrl::Return(0, vec![1]), + }, + )] + .into_iter() + .collect(), + Some(Box::new(Block { + ops: vec![ + Op::Const(G::ONE), + Op::Sub(0, 1), + Op::Call(1, vec![2], 1, false), + ], + ctrl: Ctrl::Return(1, vec![3]), + })), + ), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 2, + auxiliaries: 15, + lookups: 8, + }, + entry: false, + constrained: true, + }; + let leaf = Function { + body: Block { + ops: vec![Op::Const(G::from_u64(1_000)), Op::Add(0, 1)], + ctrl: Ctrl::Return(0, vec![2]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 1, + lookups: 1, + }, + entry: false, + constrained: true, + }; + let mut top = with_singleton_circuits(vec![root, recursive, leaf], vec![]); + top.call_components = vec![ + CallComponent { order: 0, ranked: false }, + CallComponent { order: 1, ranked: true }, + CallComponent { order: 2, ranked: false }, + ]; + if grouped { + top.circuits = vec![Circuit { + members: vec![0, 1, 2], + layout: FunctionLayout { + input_size: 1, + selectors: 4, + auxiliaries: 15, + lookups: 8, + }, + }]; + } + top +} + +#[test] +fn component_boundaries_preserve_promotion_sharing_and_mixed_groups() { + for grouped in [false, true] { + let (cp, fp) = test_parameters(); + let system = + AiurSystem::build(component_promotion_toplevel(grouped), cp, fp); + for n in [0, 4] { + let (claim, proof) = + system.prove(0, &[G::from_u8(n)], &mut empty_io_buffer()); + assert_eq!( + claim, + vec![function_channel(), G::ZERO, G::from_u8(n), G::from_u64(2_000)] + ); + system + .verify(&claim, &proof) + .expect("component boundary proof must verify"); + } + } +} + +#[test] +fn component_boundary_cannot_displace_a_recursive_provider_rank() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(component_promotion_toplevel(false), cp, fp); + let mut io = empty_io_buffer(); + let input = vec![G::from_u8(4)]; + let (mut record, output) = + system.toplevel.execute(0, input.clone(), &mut io).unwrap(); + let mut traces = Vec::new(); + let mut ranges = RankRanges::default(); + for i in 0..system.toplevel.circuits.len() { + let (trace, _, counts) = + system.toplevel.witness_data(i, &record, &io, &system.slot_arg_widths(i)); + ranges = crate::call_order::merge_ranges(ranges, counts); + traces.push(trace); + } + record.bytes2_queries.add_rank_ranges(ranges.clone()); + traces.push(Bytes1.witness_data(&record, &system.slot_arg_widths(3)).0); + traces.push(Bytes2.witness_data(&record, &system.slot_arg_widths(4)).0); + let mut claim = vec![function_channel(), G::ZERO]; + claim.extend(input); + claim.extend(output); + assert!( + lookup_balance(&system.toplevel, &traces, &ranges, &claim).is_empty() + ); + + // Root columns: input, selector, multiplicity, hint output, call output, + // bound rank, second call output, bound rank. Replace only one binding. + assert_ne!(traces[0].values[5], G::ZERO); + traces[0].values[5] = G::ZERO; + let (constraints, _) = system.toplevel.build_constraints(0); + assert!(constraints.zeros.iter().all(|expr| eval_expr( + expr, + &row_values(&traces[0].values[..constraints.width]) + ) == G::ZERO)); + assert_eq!( + lookup_balance(&system.toplevel, &traces, &ranges, &claim).len(), + 2 + ); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert!( + system.verify(&claim, &proof).is_err(), + "boundary rank must bind the provider" + ); +} + fn fill_bytes(row: &mut [G], value: u64, ranges: &mut RankRanges) { assert!(value < RANK_BOUND); let bytes = value.to_le_bytes(); @@ -107,9 +339,16 @@ fn lookup_balance( #[test] fn mutual_cycles_reject_at_the_closing_lookup_in_both_partitions() { - for grouped in [false, true] { + for (grouped, specialized) in + [(false, false), (true, false), (false, true), (true, true)] + { let (cp, fp) = test_parameters(); - let system = AiurSystem::build(cycle_toplevel(grouped), cp, fp); + let top = if specialized { + component_cycle_toplevel(grouped) + } else { + cycle_toplevel(grouped) + }; + let system = AiurSystem::build(top, cp, fp); let input = G::from_u8(3); let output = G::from_u8(7); let claim = vec![function_channel(), G::ZERO, input, output]; @@ -130,10 +369,15 @@ fn mutual_cycles_reject_at_the_closing_lookup_in_both_partitions() { row[1 + offset] = G::ONE; let aux = 1 + circuit.layout.selectors; row[aux] = if member == 1 { G::from_u8(2) } else { G::ONE }; - fill_bytes(&mut row[aux + 1..aux + 7], member as u64, &mut ranges); - row[aux + 7] = output; - let gap = if member == 2 { RANK_BOUND - 2 } else { 0 }; - fill_bytes(&mut row[aux + 8..aux + 14], gap, &mut ranges); + if specialized && member == 0 { + row[aux + 1] = output; + row[aux + 2] = G::ONE; + } else { + fill_bytes(&mut row[aux + 1..aux + 7], member as u64, &mut ranges); + row[aux + 7] = output; + let gap = if member == 2 { RANK_BOUND - 2 } else { 0 }; + fill_bytes(&mut row[aux + 8..aux + 14], gap, &mut ranges); + } violated += constraints .zeros .iter() @@ -164,7 +408,7 @@ fn mutual_cycles_reject_at_the_closing_lookup_in_both_partitions() { let proof = system.system.prove(&system.key, &claim, witness); assert!( system.verify(&claim, &proof).is_err(), - "cyclic return accepted (grouped={grouped})" + "cyclic return accepted (grouped={grouped}, specialized={specialized})" ); } } diff --git a/crates/aiur/src/trace.rs b/crates/aiur/src/trace.rs index 342f800d1..01aa5c754 100644 --- a/crates/aiur/src/trace.rs +++ b/crates/aiur/src/trace.rs @@ -12,8 +12,13 @@ use rayon::{ use crate::{ FxIndexMap, G, - bytecode::{Block, Ctrl, Function, FunctionLayout, Op, Toplevel}, - call_order::{RANK_BOUND, RANK_BYTES, RankRanges, merge_ranges}, + bytecode::{ + Block, CallComponent, Ctrl, Function, FunctionLayout, Op, Toplevel, + }, + call_order::{ + CallRank, RANK_BOUND, RANK_BYTES, RankRanges, call_rank, merge_ranges, + row_uses_rank, + }, execute::{ IOBuffer, IOKeyInfo, QueryRecord, find_unconstrained_big_uint_div_mod, g_inverse_value, @@ -113,6 +118,8 @@ impl<'a, 'b> ColumnMutSlice<'a, 'b> { #[derive(Clone, Copy)] struct TraceContext<'a> { + function: usize, + call_components: &'a [CallComponent], function_index: G, multiplicity: G, rank: u64, @@ -196,11 +203,19 @@ impl Toplevel { lookups, &mut rank_ranges, ); + let function = usize::try_from(meta.function_index.as_canonical_u64()) + .expect("function index fits usize"); let context = TraceContext { + function, + call_components: &self.call_components, function_index: meta.function_index, inputs: meta.inputs, multiplicity: meta.result.multiplicity, - rank: meta.result.rank, + rank: if row_uses_rank(&self.call_components, function) { + meta.result.rank + } else { + 0 + }, output: meta.result.output, query_record, }; @@ -241,7 +256,9 @@ impl Function { .for_each(|(i, arg)| slice.inputs[i] = *arg); // Push the multiplicity slice.push_auxiliary(index, context.multiplicity); - slice.push_rank_bytes(index, context.rank); + if row_uses_rank(context.call_components, context.function) { + slice.push_rank_bytes(index, context.rank); + } let _ = self.body.populate_row(map, index, slice, context, io_buffer); } } @@ -413,18 +430,29 @@ impl Op { slice.push_auxiliary(index, *f); } if !op_unconstrained { + let kind = call_rank( + context.call_components, + context.function, + *function_index, + ); + let rank = if kind == CallRank::Zero { 0 } else { result.rank }; let args = function_lookup_args( G::from_usize(*function_index), &inputs, result.output, - result.rank, + rank, ); slice.push_lookup(index, G::ONE, &args); - let gap = result - .rank - .checked_sub(context.rank + 1) - .expect("constrained call does not increase rank"); - slice.push_rank_bytes(index, gap); + match kind { + CallRank::Zero => {}, + CallRank::Bound => slice.push_auxiliary(index, G::from_u64(rank)), + CallRank::Ordered => { + let gap = rank + .checked_sub(context.rank + 1) + .expect("constrained call does not increase rank"); + slice.push_rank_bytes(index, gap); + }, + } } }, Op::Store(values) => { diff --git a/crates/ffi/src/aiur/toplevel.rs b/crates/ffi/src/aiur/toplevel.rs index fbead94f7..7dee74a46 100644 --- a/crates/ffi/src/aiur/toplevel.rs +++ b/crates/ffi/src/aiur/toplevel.rs @@ -309,11 +309,19 @@ pub(crate) fn decode_toplevel( obj: &LeanAiurToplevel, ) -> Toplevel { let ctor = obj.as_ctor(); - let [functions_obj, memory_sizes_obj, circuits_obj] = ctor.objs::<3>(); + let [functions_obj, memory_sizes_obj, circuits_obj, components_obj] = + ctor.objs::<4>(); let functions = functions_obj.as_array().map(|o| decode_function(o.as_ctor())); let memory_sizes = memory_sizes_obj.as_array().map(|x| lean_unbox_nat_as_usize(&x)); let circuits = circuits_obj.as_array().map(|o| decode_circuit(o.as_ctor())); - Toplevel { functions, memory_sizes, circuits } + let call_components = components_obj.as_array().map(|o| { + let component = crate::lean::LeanAiurCallComponent::from_ctor(o.as_ctor()); + aiur::bytecode::CallComponent { + order: lean_unbox_nat_as_usize(&component.get_obj(0)), + ranked: component.get_num_8(0) != 0, + } + }); + Toplevel { functions, memory_sizes, circuits, call_components } } diff --git a/crates/ffi/src/lean.rs b/crates/ffi/src/lean.rs index cf4ab2645..93ffce6bb 100644 --- a/crates/ffi/src/lean.rs +++ b/crates/ffi/src/lean.rs @@ -275,7 +275,8 @@ lean_ffi::lean_inductive! { // --- Aiur types --- - LeanAiurToplevel [ { num_obj: 3 } ]; + LeanAiurToplevel [ { num_obj: 4 } ]; + LeanAiurCallComponent [ { num_obj: 1, num_8: 1 } ]; LeanAiurFunction [ { num_obj: 2, num_8: 2 } ]; LeanAiurCircuit [ { num_obj: 3 } ]; diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index 83289df00..53370cab2 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -8,14 +8,14 @@ a native Merkle commitment-binding defect. | Failure | Required invariant | Regression | | --- | --- | --- | | An inactive function row supplied a public proof of `3 * 5 = 16`. | Function and memory rows satisfy `multiplicity * (1 - selector) = 0`. | [Inactive rows](../crates/aiur/src/synthesis/tests/acceptance.rs) | -| Self-recursive and mutually recursive rows balanced their own calls without a finite execution. | Every constrained call strictly increases a range-checked rank. | [Self recursion](../crates/aiur/src/synthesis/tests/acceptance.rs), [call ordering](../crates/aiur/src/synthesis/tests/call_order.rs) | +| Self-recursive and mutually recursive rows balanced their own calls without a finite execution. | Calls advance a checked static component order, or strictly increase a range-checked rank within one component. | [Self recursion](../crates/aiur/src/synthesis/tests/acceptance.rs), [call ordering](../crates/aiur/src/synthesis/tests/call_order.rs) | | An empty return at rank seven supplied a public claim with output seven because lookup messages are zero-padded. | Public claims and constrained calls agree with the function's input and output arities; yields agree with their continuation. | [Message shapes](../crates/aiur/src/synthesis/tests/lookup_shapes.rs) | | An inactive branch's store arguments changed a live call's lookup channel and supplied output seven for a program returning one. | Ungated arguments require a single function with terminal control and one selector. Constraint emission and lookup grouping use the same predicate. | [Empty branches](../crates/aiur/src/synthesis/tests/branchless.rs) | | A large native Merkle cap omitted a shorter matrix: changing its values preserved the commitment, and altered openings verified. | The cap retains the injection layer of every committed matrix. | [Merkle cap coverage](../crates/aiur/src/synthesis/tests/mmcs.rs) | ## Call ranks and witness generation -Each function row has six little-endian rank bytes. A constrained call adds +The general Aiur layout gives each function row six little-endian rank bytes. A constrained call adds six bytes for `callee_rank - caller_rank - 1` and requests the derived rank `caller_rank + 1 + gap` in its lookup. The callee's return binds this rank without a separate callee-rank column or equality constraint. Three byte-pair @@ -30,12 +30,56 @@ children are promoted. Shared callees retain a consistent rank. Witness workers accumulate their byte-range queries locally; the prover merges those counts before constructing the binary byte-table trace. -The compiler reserves six additional columns and three lookup slots per -function, and six columns and three additional lookup slots per constrained -call. These columns belong to the compiled proving layout and witness -generator. Regenerating the IxVM, aggregation and recursive-verifier execution -sources produces identical files because their instructions and function -indices are preserved. +## Checked IxVM component ordering + +IxVM enables a compiler pass that computes strongly connected components of +its constrained call graph after lowering and deduplication. An independent +checker validates every constrained bytecode edge: it must advance the static +component order, or stay within a component whose endpoints both retain +dynamic ranks. It also checks the assignment's size and order bounds. The +native system constructor repeats these checks over branches, defaults and +shared continuations before constructing the AIR and verification key. +The certificate is part of the fixed program, not advice from the prover. + +The resulting layouts use these rank witnesses: + +| Location | Additional columns | Additional byte-pair lookups | +| --- | ---: | ---: | +| Acyclic function row | 0; return rank is zero | 0 | +| Recursive function row | 6 rank bytes | 3 | +| Call to an acyclic function | 0; requested rank is zero | 0 | +| Call across components to a recursive function | 1 callee-rank field | 0 | +| Call within a recursive component | 6 gap bytes | 3 | + +A boundary call must still bind its recursive callee's rank through the return +lookup. Setting it to zero would break shared callees. Within a recursive +component, the bounded rank and gap retain the original strict ordering. +The Lean theorem `CallComponent.wellFounded_calls` in +[the compiler pass](../Ix/Aiur/Compiler/CallOrder.lean) proves that the bounded +static order and bounded dynamic ranks together give a well-founded call +relation. Its premises still rely on activity, exact lookup balance and the +byte-range constraints; it is not a complete AIR extraction theorem. + +The compiler recomputes function and shared-continuation layouts before +grouping. In a mixed circuit, acyclic operations reuse recursive members' +rank columns and lookup slots, so rank-range queries are gated only by ranked +members. General Aiur programs retain the dynamic layout unless explicitly +enabled through `Source.Toplevel.componentRanks`. + +For the current production IxVM, this removes row ranks from 365 of 753 +constrained functions and gap checks at 2,428 of 3,357 call sites. Of its +181 function circuits, 139 become narrower and 138 use fewer lookup slots. +Existing function groups are retained. These counts are not weighted by +execution frequency. The optimization reduces modeled FFT work on all 83 +kernel fixtures: median 6.65%, with 9.73% for `Nat.add_comm`, 15.09% for +`Vector.append`, and 9.81% for the shard pipeline, relative to the repaired +dynamic-rank layout. These are model estimates, not wall-clock timings. + +Query records still retain their completion timestamps, including for acyclic +functions; this pass reduces AIR and witness work rather than record storage. +The remaining recursive components keep explicit ranks. Regenerating the +IxVM, aggregation and recursive-verifier execution sources produces identical +files because instructions and function indices are preserved. ## Structural bounds @@ -84,17 +128,22 @@ are rejected; the recursive verifier already requires cap height zero. The activity, call-order and branch-gating repairs change affected AIR expressions and verification keys. Rebuild proving systems and keys, and regenerate stored proofs against the repaired systems. Public claim encoding -is preserved: its omitted rank is zero under lookup padding. +is preserved: its omitted rank is zero under lookup padding. Component +specialization also changes the IxVM AIR and key, and extends the internal +Lean/Rust bytecode representation; rebuild both sides of the FFI together. The native regressions cover supplied false witnesses as well as honest execution, finite recursion, shared callees, advice promotion and grouped -circuits. Run them with: +circuits. Component tests also reject forged assignments and displaced +boundary ranks, check the component producer against an independent +reachability oracle on all 512 three-vertex graphs, and run the existing +Aiur proving corpus with specialized layouts. Run them with: ```sh cargo test --locked --release -p aiur --features parallel cargo clippy --locked --release -p aiur --all-targets --features parallel -- -D warnings lake exe ix codegen --check -lake test -- aiur-cross aiur-cost aiur-prove recursive-verifier ix-aggr +lake test -- aiur-cross aiur-cost aiur-prove aiur-components recursive-verifier ix-aggr lake test -- --ignored ixvm ``` From 11fd8a5d81ace7cbc46a9544dc621f01eac50f80 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 13:07:29 -0400 Subject: [PATCH 18/30] perf(aiur): tune lookup groups using compiled degree costs --- Ix/Aiur/Stages/Bytecode.lean | 10 +- Tests/Ix/IxVM.lean | 166 ++++++++-------- Tests/Main.lean | 6 +- Tests/MultiStark.lean | 24 ++- crates/aiur/src/lib.rs | 1 + crates/aiur/src/lookup_groups.rs | 184 ++++++++++++++++++ crates/aiur/src/synthesis.rs | 23 ++- .../aiur/src/synthesis/tests/lookup_groups.rs | 146 ++++++++++++++ docs/aiur-soundness.md | 29 ++- 9 files changed, 485 insertions(+), 104 deletions(-) create mode 100644 crates/aiur/src/lookup_groups.rs create mode 100644 crates/aiur/src/synthesis/tests/lookup_groups.rs diff --git a/Ix/Aiur/Stages/Bytecode.lean b/Ix/Aiur/Stages/Bytecode.lean index a7e051d12..a2c178606 100644 --- a/Ix/Aiur/Stages/Bytecode.lean +++ b/Ix/Aiur/Stages/Bytecode.lean @@ -104,12 +104,14 @@ structure FunctionLayout where def FunctionLayout.width (l : FunctionLayout) : Nat := l.inputSize + l.selectors + l.auxiliaries +/-- Layout-only estimate of main and stage-2 width. This lacks the control +tree, compiled lookup degrees and PCS parameters; use the built system's +`circuitShapes` for actual widths after lookup tuning. -/ def FunctionLayout.totalWidth (l : FunctionLayout) : Nat := -- Stage 2 commits max(⌈L/k⌉, 1) chained partial accumulators (no message - -- inverses); see `multi_stark::lookup::stage2_width`. Mirrors the - -- synthesis grouping rule (`crates/aiur/src/synthesis.rs`): branchless - -- functions (one selector) have raw degree-1 lookup arguments, so their - -- lookups are grouped 2 per accumulator step. + -- inverses); see `multi_stark::lookup::stage2_width`. Retain the original + -- single-selector heuristic here; synthesis checks control flow and + -- retunes using compiled degrees and the FFT cost. let slots := if l.selectors == 1 && l.lookups >= 2 then (l.lookups + 1) / 2 else max l.lookups 1 diff --git a/Tests/Ix/IxVM.lean b/Tests/Ix/IxVM.lean index c26d570e9..2dd8548ea 100644 --- a/Tests/Ix/IxVM.lean +++ b/Tests/Ix/IxVM.lean @@ -439,89 +439,89 @@ private def nameOfString (str : String) : Lean.Name := and an improvement has to be acknowledged by re-pinning. These pins include the range-checked call ranks that exclude cyclic proof traces. -/ private def kernelCheckEntries : List (String × Nat) := [ - ("HEq", 129_902_362), - ("HEq.rec", 135_719_723), - ("Eq.rec", 134_721_481), - ("Nat", 129_858_617), - ("Nat.add", 186_636_625), - ("Nat.add_comm", 397_590_325), - ("Nat.decEq", 489_311_794), - ("Nat.decLe", 1_116_803_161), - ("Nat.sub_le_of_le_add", 2_788_278_330), - ("Nat.shiftRight_succ", 2_056_813_337), - ("Trans.mk", 140_772_036), - ("Array.append_assoc", 13_728_577_860), - ("Vector.append", 14_018_670_718), - ("IxVMPrim.nat_add_lit", 242_677_455), - ("IxVMPrim.nat_sub_lit", 261_801_013), - ("IxVMPrim.nat_mul_lit", 229_615_579), - ("IxVMPrim.nat_mul_big", 227_685_285), - ("IxVMPrim.nat_div_lit", 2_004_547_538), - ("IxVMPrim.nat_mod_lit", 2_042_357_932), - ("IxVMPrim.nat_succ_lit", 148_404_937), - ("IxVMPrim.nat_pred_lit", 176_619_587), - ("IxVMPrim.nat_gcd_lit", 3_174_004_542), - ("IxVMPrim.nat_land_lit", 5_220_684_861), - ("IxVMPrim.nat_lor_lit", 5_223_321_528), - ("IxVMPrim.nat_xor_lit", 5_248_107_752), - ("IxVMPrim.nat_shl_lit", 268_740_688), - ("IxVMPrim.nat_shr_lit", 2_024_069_102), - ("IxVMPrim.nat_pow_big", 579_150_476), - ("IxVMPrim.nat_beq_lit", 227_350_938), - ("IxVMPrim.nat_ble_lit", 220_750_813), - ("IxVMPrim.nat_cases_big", 177_261_421), - ("IxVMPrim.nat_dec_le", 1_140_682_160), - ("IxVMPrim.nat_dec_lt", 1_156_120_001), - ("IxVMPrim.nat_dec_eq", 541_543_503), - ("IxVMPrim.str_size_lit", 3_612_596_962), - ("IxVMPrim.bv_to_nat_lit", 3_026_839_361), - ("IxVMInd.Even", 233_700_149), - ("IxVMInd.Odd", 233_707_552), - ("IxVMInd.Even.rec", 259_591_321), - ("IxVMInd.Odd.rec", 259_590_392), - ("IxVMInd.IdxTeleN.rec", 170_416_005), - ("IxVMInd.IdxTeleB.rec", 170_414_314), - ("IxVMInd.SoloA.rec", 163_719_901), - ("IxVMInd.SoloB.rec", 163_719_064), - ("IxVMInd.UnsafeSquash", 132_141_826), - ("IxVMInd.Tree", 131_889_662), - ("IxVMInd.Tree.rec", 146_285_824), - ("IxVMInd.DedupM", 135_837_240), - ("IxVMInd.DedupM.rec", 155_200_872), - ("IxVMInd.DepthM", 133_949_059), - ("IxVMInd.DepthM.rec", 149_696_625), - ("String.Internal.append", 3_572_298_590), - ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 5_320_050_458), - ("Lean.Syntax.rec", 3_654_823_020), - ("IxVMInd.AuxTie", 383_926_597), - ("IxVMInd.AuxTie.rec", 446_507_007), - ("IxVMInd.HiddenIdx", 131_017_184), - ("IxVMInd.HiddenIdx.rec", 135_576_974), - ("IxVMInd.thmMajorUse", 689_746_612), - ("IxVMInd.partialKRec", 157_250_810), - ("IxVMInd.deepRebase", 255_520_668), - ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 5_037_942_193), - ("Lean.Widget.TaggedText.rec", 3_617_889_956), - ("Lean.Doc.Part.rec", 3_679_734_499), - ("Lean.Doc.Block.rec", 4_040_375_211), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 133_464_042), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 138_164_164), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 137_402_699), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 137_402_699), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 137_402_699), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 133_825_940), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 149_898_054), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 149_896_472), - ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 137_402_699), - ("strOfListFoldSize", 4_003_481_843), - ("strOfListFoldSizeAscii", 4_004_495_937), - ("IxVMPrim.lazy_ble_offset", 272_065_748), - ("IxVMPrim.lazy_unit_cast", 733_066_610), - ("IxVMPrim.sizeof_unit", 169_076_166), - ("IxVMPerf.let_continuations", 181_924_142), - ("IxVMPerf.mul_row", 510_801_740), - ("IxVMPerf.context_tower", 731_464_127), - ("IxVMPerf.mul_wide", 303_686_118), + ("HEq", 129_756_304), + ("HEq.rec", 135_082_916), + ("Eq.rec", 134_156_212), + ("Nat", 129_731_961), + ("Nat.add", 181_252_628), + ("Nat.add_comm", 372_875_520), + ("Nat.decEq", 457_294_242), + ("Nat.decLe", 1_025_690_654), + ("Nat.sub_le_of_le_add", 2_542_090_353), + ("Nat.shiftRight_succ", 1_878_771_758), + ("Trans.mk", 139_554_886), + ("Array.append_assoc", 12_477_827_382), + ("Vector.append", 12_740_924_143), + ("IxVMPrim.nat_add_lit", 231_914_049), + ("IxVMPrim.nat_sub_lit", 249_123_636), + ("IxVMPrim.nat_mul_lit", 219_916_033), + ("IxVMPrim.nat_mul_big", 218_191_753), + ("IxVMPrim.nat_div_lit", 1_830_701_497), + ("IxVMPrim.nat_mod_lit", 1_864_671_837), + ("IxVMPrim.nat_succ_lit", 146_495_327), + ("IxVMPrim.nat_pred_lit", 171_936_899), + ("IxVMPrim.nat_gcd_lit", 2_892_577_245), + ("IxVMPrim.nat_land_lit", 4_746_119_615), + ("IxVMPrim.nat_lor_lit", 4_748_468_876), + ("IxVMPrim.nat_xor_lit", 4_770_582_030), + ("IxVMPrim.nat_shl_lit", 255_115_733), + ("IxVMPrim.nat_shr_lit", 1_848_169_910), + ("IxVMPrim.nat_pow_big", 558_681_730), + ("IxVMPrim.nat_beq_lit", 218_051_792), + ("IxVMPrim.nat_ble_lit", 212_051_618), + ("IxVMPrim.nat_cases_big", 172_646_862), + ("IxVMPrim.nat_dec_le", 1_047_363_748), + ("IxVMPrim.nat_dec_lt", 1_061_221_796), + ("IxVMPrim.nat_dec_eq", 504_595_008), + ("IxVMPrim.str_size_lit", 3_284_940_890), + ("IxVMPrim.bv_to_nat_lit", 2_758_683_231), + ("IxVMInd.Even", 223_582_239), + ("IxVMInd.Odd", 223_589_641), + ("IxVMInd.Even.rec", 246_984_382), + ("IxVMInd.Odd.rec", 246_983_453), + ("IxVMInd.IdxTeleN.rec", 166_470_909), + ("IxVMInd.IdxTeleB.rec", 166_469_218), + ("IxVMInd.SoloA.rec", 160_411_081), + ("IxVMInd.SoloB.rec", 160_410_244), + ("IxVMInd.UnsafeSquash", 131_771_481), + ("IxVMInd.Tree", 131_606_961), + ("IxVMInd.Tree.rec", 144_650_431), + ("IxVMInd.DedupM", 135_171_041), + ("IxVMInd.DedupM.rec", 152_749_230), + ("IxVMInd.DepthM", 133_476_645), + ("IxVMInd.DepthM.rec", 147_812_742), + ("String.Internal.append", 3_248_767_759), + ("_private.Init.Prelude.0.Lean.extractMainModule._unsafe_rec", 4_830_321_949), + ("Lean.Syntax.rec", 3_323_172_229), + ("IxVMInd.AuxTie", 358_448_151), + ("IxVMInd.AuxTie.rec", 414_918_046), + ("IxVMInd.HiddenIdx", 130_768_825), + ("IxVMInd.HiddenIdx.rec", 134_916_361), + ("IxVMInd.thmMajorUse", 637_683_846), + ("IxVMInd.partialKRec", 154_653_446), + ("IxVMInd.deepRebase", 243_691_511), + ("String.Slice.Pattern.Model.NoPrefixPatternModel.rec", 4_584_658_548), + ("Lean.Widget.TaggedText.rec", 3_290_022_013), + ("Lean.Doc.Part.rec", 3_346_066_183), + ("Lean.Doc.Block.rec", 3_670_421_640), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A", 133_001_631), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec", 137_249_016), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_1", 136_604_326), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup1.A.rec_2", 136_604_326), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedup2.A.rec_1", 136_604_326), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M", 133_350_656), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec", 147_919_526), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_1", 147_917_943), + ("_private.Tests.Ix.Compile.Mutual.0.Tests.Ix.Compile.Mutual.AuxDedupMixed.M.rec_2", 136_604_326), + ("strOfListFoldSize", 3_637_783_181), + ("strOfListFoldSizeAscii", 3_638_671_503), + ("IxVMPrim.lazy_ble_offset", 258_295_729), + ("IxVMPrim.lazy_unit_cast", 677_524_581), + ("IxVMPrim.sizeof_unit", 165_195_874), + ("IxVMPerf.let_continuations", 177_556_223), + ("IxVMPerf.mul_row", 471_677_246), + ("IxVMPerf.context_tower", 668_489_345), + ("IxVMPerf.mul_wide", 287_523_670), ] /-- Variant of `kernelChecks`, pinned to the baseline diff --git a/Tests/Main.lean b/Tests/Main.lean index 9b24b1b59..542880885 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -280,12 +280,12 @@ def ignoredRunners (env : Lean.Environment) : List (String × IO UInt32) := [ -- Exact pin, same convention as `kernelCheckEntries` -- (`.round.toUInt64.toNat`): any cost shift must be an -- explicit, reviewed bump. Includes component-local call ranks - -- and their remaining byte-range lookups. + -- and cost-based grouping of the remaining lookups. let actual := (Aiur.computeStats v2Env.compiled qc v2Env.shapes).totalFftCost.round.toUInt64.toNat pure (LSpec.test - s!"Shard pipeline FFT matches: expected 9_407_996_708, got {actual}" - (actual = 9_407_996_708)) + s!"Shard pipeline FFT matches: expected 8_523_899_042, got {actual}" + (actual = 8_523_899_042)) LSpec.lspecIO (.ofList [("ixvm", [componentSeq, fullSeq, aiurSeq, arenaSeq, exploitSeq, paritySeq, shardSeq])]) []), diff --git a/Tests/MultiStark.lean b/Tests/MultiStark.lean index d55f537a0..4a131c243 100644 --- a/Tests/MultiStark.lean +++ b/Tests/MultiStark.lean @@ -102,12 +102,10 @@ def selfTestSuite : IO UInt32 := do -- `recursive-verifier`: prove factorial(5)=120, verify it, reject tampering -- ════════════════════════════════════════════════════════════════════════════ -/-- A tiny Aiur program: a BRANCHLESS entrypoint (single selector, no match) -that routes its argument through store/load before calling `factorial`. Its -circuit has 4 lookups (return, store, load, call) with raw degree-1 -arguments, so synthesis groups them 2 per chained-accumulator step -(`lookup_group_size = 2`) — the recursive verifier's grouped logUp fold is -exercised end-to-end alongside the k = 1 branching/memory circuits. -/ +/-- A branching entrypoint with enough gated store/load/call lookups for +synthesis to choose two messages per accumulator at quotient degree four. +The smaller factorial and memory circuits retain quotient degree two, so +recursive verification exercises both degrees within the same proof. -/ def factorialProgram : Source.Toplevel := ⟦ pub fn factorial(n: G) -> G { match n { @@ -117,7 +115,16 @@ def factorialProgram : Source.Toplevel := ⟦ } pub fn fact_entry(n: G) -> G { - factorial(load(store(n))) + match n { + 0 => 1, + _ => + let a = load(store(n)); + let b = load(store(n + 1)); + let c = load(store(n + 2)); + assert_eq!(b, a + 1); + assert_eq!(c, a + 2); + factorial(a), + } } ⟧ @@ -163,6 +170,8 @@ def endToEndSuite : IO UInt32 := do | .ok result => pure result | .error e => IO.eprintln s!"factorial prove failed: {e}"; return 1 let expectedClaim := buildClaim facIdx input #[Aiur.G.ofNat 120] + let mixedQuotients := facSystem.circuitShapes.any (·.quotientDegree == 4) && + facSystem.circuitShapes.any (·.quotientDegree == 2) -- Verify and serialize the proof transport consumed in-circuit. let proofBytes ← match facSystem.proofToAdviceBytes claim proof with | .ok bytes => pure bytes @@ -237,6 +246,7 @@ def endToEndSuite : IO UInt32 := do vCompiled.bytecode.executeMultiStark vIdx badClaimInput proofBytes vkBytes badClaimBytes lspecIO (.ofList [("recursive-verifier", [ test "factorial(5) claim = #[functionChannel, facIdx, 5, 120]" (claim == expectedClaim), + test "inner proof exercises quotient degrees two and four" mixedQuotients, expectOk "inner factorial proof verifies" innerVerify, expectOk "verifier accepts honest proof (vk digest bound + OOD + FRI)" honest, test "codegen'd verifier matches interpreter (output + query counts)" parity, diff --git a/crates/aiur/src/lib.rs b/crates/aiur/src/lib.rs index d2459b459..f14416cce 100644 --- a/crates/aiur/src/lib.rs +++ b/crates/aiur/src/lib.rs @@ -4,6 +4,7 @@ pub mod constraints; pub mod execute; pub mod gadgets; mod lookup_budget; +mod lookup_groups; mod lookup_shapes; pub mod memory; pub mod querymap; diff --git a/crates/aiur/src/lookup_groups.rs b/crates/aiur/src/lookup_groups.rs new file mode 100644 index 000000000..a26d29328 --- /dev/null +++ b/crates/aiur/src/lookup_groups.rs @@ -0,0 +1,184 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Choose lookup groups from the compiled degrees and the FFT tradeoff. +//! This runs before exposing the system or constructing its transcript. + +use multi_stark::{ + expr::Source, + graph::Node, + lookup::{ + MAX_LOOKUP_GROUP, logup_constraint_count, logup_max_degree, stage2_width, + }, + system::Circuit, +}; + +use crate::G; + +/// The group-dependent part of `Aiur.fftCost`, divided by row height. +/// For h >= 2 it is `slope * log2(h) + intercept`; h = 1 uses the +/// repository model's clamped transform cost. Main-trace work cancels. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct FftCost { + one: u128, + two: u128, + slope: u128, + intercept: u128, +} + +impl FftCost { + fn new( + stage2: usize, + quotient: usize, + blowup: usize, + degree: usize, + ) -> Option { + if !quotient.is_power_of_two() || !blowup.is_power_of_two() { + return None; + } + let log_q = u128::from(quotient.ilog2()); + let log_b = u128::from(blowup.ilog2()); + let qd = (quotient as u128).checked_mul(degree as u128)?; + let b = blowup as u128; + let trace = (b + 1).checked_mul(stage2 as u128)?; + let slope = (b + 1).checked_mul((stage2 as u128).checked_add(qd)?)?; + let intercept = + qd.checked_mul(log_q.checked_add(b.checked_mul(log_b)?)?)?; + let one = trace.checked_add(qd.checked_mul( + log_q.max(1).checked_add(b.checked_mul(log_b.max(1))?)?, + )?)?; + let two = slope.checked_add(intercept)?; + Some(Self { one, two, slope, intercept }) + } + + /// These three comparisons imply no larger FFT cost for every integer + /// height h >= 1, including both padded and raw-height statistics. + fn no_worse_than(self, other: Self) -> bool { + self.one <= other.one && self.two <= other.two && self.slope <= other.slope + } + + fn score(self) -> (u128, u128, u128) { + (self.slope, self.intercept, self.one) + } +} + +fn max_degree(circuit: &Circuit, group: usize) -> usize { + circuit + .graph + .max_constraint_degree + .max(logup_max_degree(&circuit.graph, group)) as usize +} + +fn quotient_degree(circuit: &Circuit, group: usize) -> Option { + (max_degree(circuit, group).max(2) - 1).checked_next_power_of_two() +} + +/// The pinned backend compiles user constraints and lookup expressions only; +/// its logUp constraints are evaluated directly from this circuit metadata. +/// Its prover key contains only preprocessed PCS data, which grouping does +/// not change. Keep all derived metadata synchronized before either is used. +pub(crate) fn set_group(circuit: &mut Circuit, group: usize, degree: usize) { + circuit.lookup_group_size = group; + circuit.stage_2_width = stage2_width(circuit.num_lookups, group, degree); + circuit.constraint_count = circuit.graph.zeros.len() + + logup_constraint_count(circuit.num_lookups, group, degree); + circuit.max_constraint_degree = max_degree(circuit, group); +} + +pub(crate) fn retune(circuit: &mut Circuit, blowup: usize, degree: usize) { + // Aiur's authored constraints never refer to stage 2. Retain the layout + // if a future circuit does: changing its column count would need a + // separate proof that those references still have the intended meaning. + if circuit + .graph + .nodes + .iter() + .any(|node| matches!(node, Node::Var(col) if col.source == Source::Stage2)) + { + return; + } + let Some(baseline) = FftCost::new( + circuit.stage_2_width, + circuit.quotient_degree(), + blowup, + degree, + ) else { + return; + }; + let mut best_group = circuit.lookup_group_size; + let mut best_cost = baseline; + for group in 1..=circuit.num_lookups.clamp(1, MAX_LOOKUP_GROUP) { + let Some(quotient) = quotient_degree(circuit, group) else { continue }; + if quotient > blowup { + continue; + } + let Some(cost) = FftCost::new( + stage2_width(circuit.num_lookups, group, degree), + quotient, + blowup, + degree, + ) else { + continue; + }; + if cost.no_worse_than(baseline) && cost.score() < best_cost.score() { + best_group = group; + best_cost = cost; + } + } + set_group(circuit, best_group, degree); +} + +#[cfg(test)] +mod tests { + use super::*; + + fn cost_at(stage2: usize, quotient: usize, blowup: usize, h: usize) -> f64 { + let [stage2, quotient, blowup, h] = [stage2, quotient, blowup, h] + .map(|n| f64::from(u32::try_from(n).unwrap())); + let transform = |n: f64| n * n.max(2.0).log2(); + (blowup + 1.0) * stage2 * transform(h) + + 2.0 * transform(quotient * h) + + 2.0 * quotient * transform(blowup * h) + } + + #[test] + fn fft_dominance_preserves_cost_at_small_and_large_heights() { + for blowup in [1, 2, 4, 8] { + for before_q in [1, 2, 4, 8] { + for after_q in [1, 2, 4, 8] { + for before_s2 in [2, 4, 8, 16, 32, 128] { + for after_s2 in [2, 4, 8, 16, 32, 128] { + let before = + FftCost::new(before_s2, before_q, blowup, 2).unwrap(); + let after = FftCost::new(after_s2, after_q, blowup, 2).unwrap(); + if after.no_worse_than(before) { + for h in [1, 2, 3, 7, 16, 255, 1_024, 65_536, 1 << 30] { + assert!( + cost_at(after_s2, after_q, blowup, h) + <= cost_at(before_s2, before_q, blowup, h) + ); + } + } + } + } + } + } + } + } + + #[test] + fn fft_cost_rejects_invalid_dimensions_and_overflow() { + assert!(FftCost::new(1, 0, 4, 2).is_none()); + assert!(FftCost::new(1, 3, 4, 2).is_none()); + assert!(FftCost::new(1, 2, 3, 2).is_none()); + assert!( + FftCost::new( + usize::MAX, + 1 << (usize::BITS - 1), + 1 << (usize::BITS - 1), + usize::MAX + ) + .is_none() + ); + } +} diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index 6a7295c7d..7720be7b9 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -1,12 +1,14 @@ use multi_stark::{ + config::StarkGenericConfig, expr::Expr, lookup::Lookup, - p3_field::PrimeCharacteristicRing, + p3_field::{BasedVectorSpace, PrimeCharacteristicRing}, p3_matrix::dense::RowMajorMatrix, prover::Proof, system::{CircuitInputs, ProverKey, System, SystemWitness}, types::{ - CommitmentParameters, FriParameters, GoldilocksBlake3Config, PcsError, + CommitmentParameters, ExtVal, FriParameters, GoldilocksBlake3Config, + PcsError, }, verifier::VerificationError, }; @@ -168,9 +170,9 @@ impl AiurSystem { // A branchless circuit's lookup arguments are sent raw (degree 1; // see `ConstraintState::gate`), so two lookups fit in one chained // accumulator step at degree 3 — within the degree the selector-gated - // constraints already pay for. Branching circuits keep k = 1: their - // superposed arguments are degree 2, and grouping would push the - // logUp constraints past the quotient budget. + // constraints already pay for. This is the conservative baseline; + // after compilation, retune against actual message degrees and the + // configured quotient budget, including the FFT cost of raising it. let group_size = if toplevel.circuit_is_branchless(i) && lookups.len() >= 2 { 2 @@ -210,7 +212,15 @@ impl AiurSystem { ); let config = AiurConfig::new(commitment_parameters, fri_parameters); - let (system, key) = System::new(config, circuit_inputs); + let (mut system, key) = System::new(config, circuit_inputs); + let blowup = system.config.max_quotient_degree(); + for circuit in &mut system.circuits { + crate::lookup_groups::retune( + circuit, + blowup, + >::DIMENSION, + ); + } AiurSystem { system, key, @@ -648,6 +658,7 @@ mod tests { mod byte_shapes; mod call_order; mod lookup_budget; + mod lookup_groups; mod lookup_shapes; mod mmcs; diff --git a/crates/aiur/src/synthesis/tests/lookup_groups.rs b/crates/aiur/src/synthesis/tests/lookup_groups.rs new file mode 100644 index 000000000..00124a1e0 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/lookup_groups.rs @@ -0,0 +1,146 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use crate::bytecode::CallComponent; + +/// f(n) = 16*n*n + f(n-1), with sixteen shared calls to g(n) = n*n. +/// Its gated lookup messages benefit from k = 2 at quotient degree 4. +fn wide_recursive_toplevel() -> Toplevel { + let mut ops: Vec<_> = + (0..16).map(|_| Op::Call(1, vec![0], 1, false)).collect(); + ops.extend([ + Op::Const(G::ONE), + Op::Sub(0, 17), + Op::Call(0, vec![18], 1, false), + ]); + let mut sum = 1; + for value in 2..=16 { + ops.push(Op::Add(sum, value)); + sum = ops.len(); + } + ops.push(Op::Add(sum, 19)); + let root = Function { + body: Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + [( + G::ZERO, + Block { + ops: vec![Op::Const(G::ZERO)], + ctrl: Ctrl::Return(0, vec![1]), + }, + )] + .into_iter() + .collect(), + Some(Box::new(Block { ops, ctrl: Ctrl::Return(1, vec![35]) })), + ), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 2, + auxiliaries: 31, + lookups: 24, + }, + entry: true, + constrained: true, + }; + let leaf = Function { + body: Block { ops: vec![Op::Mul(0, 0)], ctrl: Ctrl::Return(0, vec![1]) }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 2, + lookups: 1, + }, + entry: false, + constrained: true, + }; + let mut top = with_singleton_circuits(vec![root, leaf], vec![]); + top.call_components = vec![ + CallComponent { order: 0, ranked: true }, + CallComponent { order: 1, ranked: false }, + ]; + top +} + +fn wide_system(log_blowup: usize) -> AiurSystem { + let (mut cp, fp) = test_parameters(); + cp.log_blowup = log_blowup; + AiurSystem::build(wide_recursive_toplevel(), cp, fp) +} + +#[test] +fn larger_lookup_groups_verify_and_roundtrip_with_the_degree_budget() { + for (log_blowup, group, quotient, stage2) in [(1, 1, 2, 48), (2, 2, 4, 24)] { + let system = wide_system(log_blowup); + let circuit = &system.system.circuits[0]; + assert_eq!(circuit.lookup_group_size, group); + assert_eq!(circuit.quotient_degree(), quotient); + assert_eq!(circuit.stage_2_width, stage2); + assert!(system.system.circuits.iter().all(|c| { + c.quotient_degree() <= system.system.config.max_quotient_degree() + })); + // Grouping changes accumulator count, never the logical message count + // used by the characteristic bound on lookup consumers. + assert_eq!(system.slot_widths[0].len(), 24); + assert_eq!( + lookup_query_bound( + system.slot_widths.iter().map(Vec::len), + &[true, false, false, false], + &[3], + ), + Some(1 + 24 * 8) + ); + let bytes = crate::vk_codec::aiur_system_to_bytes(&system).unwrap(); + let (decoded, cp, fp) = crate::vk_codec::from_bytes(&bytes).unwrap(); + assert_eq!(crate::vk_codec::to_bytes(&decoded, cp, fp), bytes); + let back = &decoded.circuits[0]; + assert_eq!(back.lookup_group_size, group); + assert_eq!(back.max_constraint_degree, circuit.max_constraint_degree); + assert_eq!(back.constraint_count, circuit.constraint_count); + assert_eq!(back.stage_2_width, circuit.stage_2_width); + for n in [0_u8, 7] { + let (mut claim, proof) = + system.prove(0, &[G::from_u8(n)], &mut empty_io_buffer()); + let expected: u64 = (1..=u64::from(n)).map(|i| 16 * i * i).sum(); + assert_eq!(claim.last(), Some(&G::from_u64(expected))); + system.verify(&claim, &proof).unwrap(); + decoded.verify(&claim, &proof).unwrap(); + *claim.last_mut().unwrap() += G::ONE; + assert!(system.verify(&claim, &proof).is_err()); + assert!(decoded.verify(&claim, &proof).is_err()); + } + } +} + +/// An opt-in wall-clock check for the quotient-work/FFT tradeoff. Timings +/// exclude construction and verification; both configurations use identical +/// bytecode, commitment parameters and query workloads. No timing assertion. +#[test] +#[ignore = "manual lookup grouping performance comparison"] +fn lookup_group_proving_timings() { + use std::time::Instant; + + let grouped = wide_system(2); + let mut legacy = wide_system(2); + crate::lookup_groups::set_group(&mut legacy.system.circuits[0], 1, 2); + for n in [7, 32_768, 131_072] { + for round in 0..3 { + for pick in 0..2 { + let (name, system) = if (round + pick) % 2 == 0 { + ("legacy", &legacy) + } else { + ("grouped", &grouped) + }; + let start = Instant::now(); + let (claim, proof) = + system.prove(0, &[G::from_u32(n)], &mut empty_io_buffer()); + let elapsed = start.elapsed(); + system.verify(&claim, &proof).unwrap(); + println!("lookup timing: n={n} round={round} {name} {elapsed:?}"); + } + } + } +} diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index 53370cab2..04ec15457 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -10,7 +10,7 @@ a native Merkle commitment-binding defect. | An inactive function row supplied a public proof of `3 * 5 = 16`. | Function and memory rows satisfy `multiplicity * (1 - selector) = 0`. | [Inactive rows](../crates/aiur/src/synthesis/tests/acceptance.rs) | | Self-recursive and mutually recursive rows balanced their own calls without a finite execution. | Calls advance a checked static component order, or strictly increase a range-checked rank within one component. | [Self recursion](../crates/aiur/src/synthesis/tests/acceptance.rs), [call ordering](../crates/aiur/src/synthesis/tests/call_order.rs) | | An empty return at rank seven supplied a public claim with output seven because lookup messages are zero-padded. | Public claims and constrained calls agree with the function's input and output arities; yields agree with their continuation. | [Message shapes](../crates/aiur/src/synthesis/tests/lookup_shapes.rs) | -| An inactive branch's store arguments changed a live call's lookup channel and supplied output seven for a program returning one. | Ungated arguments require a single function with terminal control and one selector. Constraint emission and lookup grouping use the same predicate. | [Empty branches](../crates/aiur/src/synthesis/tests/branchless.rs) | +| An inactive branch's store arguments changed a live call's lookup channel and supplied output seven for a program returning one. | Ungated arguments require a single function with terminal control and one selector. Branching circuits retain argument gates. | [Empty branches](../crates/aiur/src/synthesis/tests/branchless.rs) | | A large native Merkle cap omitted a shorter matrix: changing its values preserved the commitment, and altered openings verified. | The cap retains the injection layer of every committed matrix. | [Merkle cap coverage](../crates/aiur/src/synthesis/tests/mmcs.rs) | ## Call ranks and witness generation @@ -81,6 +81,31 @@ The remaining recursive components keep explicit ranks. Regenerating the IxVM, aggregation and recursive-verifier execution sources produces identical files because instructions and function indices are preserved. +## Lookup grouping + +After compiling the constraints, synthesis chooses lookup groups using their +actual polynomial degrees and the configured PCS quotient-degree limit. A +larger group commits fewer stage-2 accumulator columns but can require more +quotient chunks. The deterministic selector accepts a change only if its FFT +cost is no larger than the previous layout at every integer row height, +including height one. Integer comparisons cover the small-height cases and +the slope of the cost for larger heights. This guarantee concerns the FFT +model; higher quotient degrees can increase constraint-evaluation work. + +Grouping retains every lookup message, multiplicity, selector gate and rank +check. The consumer bound counts logical lookup slots, independently of the +number of accumulator groups. Derived circuit metadata is updated before +transcript construction and key serialization. The key codec and recursive +verifier already support the selected group sizes and quotient degrees. +Native tests cover the degree limit, key round-trips and altered claims; +recursive-verifier tests exercise quotient degrees two and four together. + +Relative to the component-rank layout, modeled FFT work falls on all 83 kernel +fixtures by a median 4.44%: `Nat.add_comm` improves 6.22%, `Vector.append` +9.11%, and the shard pipeline 9.40%. Fixed byte-table rows and main columns +stay unchanged. For the small unary byte table, the same selector chooses +more accumulators at a lower quotient degree because that costs less FFT work. + ## Structural bounds System construction validates constrained-call arities, continuation yields, @@ -131,6 +156,8 @@ regenerate stored proofs against the repaired systems. Public claim encoding is preserved: its omitted rank is zero under lookup padding. Component specialization also changes the IxVM AIR and key, and extends the internal Lean/Rust bytecode representation; rebuild both sides of the FFI together. +Lookup retuning changes affected stage-2 layouts, quotient degrees and keys, +so it also requires rebuilding systems and regenerating proofs. The native regressions cover supplied false witnesses as well as honest execution, finite recursion, shared callees, advice promotion and grouped From 37daf7c3a5c6603f61d7f169c1c47cb830e726ee Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 14:39:09 -0400 Subject: [PATCH 19/30] perf(aiur): reduce host memory and correct shard estimates --- Ix/IxVM/Kernel/Klimbs.lean | 12 - Ix/IxVM/Kernel/NatPrim.lean | 20 +- Tests/Ix/IxVM/ByteHints.lean | 164 + Tests/Main.lean | 3 + crates/aiur/src/synthesis.rs | 56 +- .../aiur/src/synthesis/tests/host_timings.rs | 58 + crates/aiur/src/synthesis/tests/peak.rs | 147 + crates/aiur/src/trace.rs | 78 +- crates/ixvm-codegen/src/aiur_ixvm.rs | 22601 ++++++++-------- docs/aiur-soundness.md | 32 +- 10 files changed, 11772 insertions(+), 11399 deletions(-) create mode 100644 Tests/Ix/IxVM/ByteHints.lean create mode 100644 crates/aiur/src/synthesis/tests/host_timings.rs create mode 100644 crates/aiur/src/synthesis/tests/peak.rs diff --git a/Ix/IxVM/Kernel/Klimbs.lean b/Ix/IxVM/Kernel/Klimbs.lean index 334e854ef..910d5c98c 100644 --- a/Ix/IxVM/Kernel/Klimbs.lean +++ b/Ix/IxVM/Kernel/Klimbs.lean @@ -25,7 +25,6 @@ Ops covered: - klimbs_shl / klimbs_shr (via mul/div by 2^n) - u64_add / u64_mul (radix-2^16 schoolbook) / u64_sub_with_borrow / u64_and / u64_or / u64_xor_kbits (element-wise byte ops) -- divmod_256 (unconstrained witness generator for u32 byte decomposition) Aiur builtin gadgets used (compiler-provided): u8_add, u8_sub, u8_xor, u8_and, u8_or, u8_from_field_unsafe, u32_less_than, @@ -259,17 +258,6 @@ def klimbs := ⟦ klimbs_sub(a, one) } - -- Returns (remainder, quotient): remainder = x mod 256, quotient = x / 256. - -- Repeated subtraction. Only invoked from the `#split_u32` - -- unconstrained witness generator, so the O(x/256) - -- iteration cost is off-circuit (untraced). - fn divmod_256(x: G, q: G) -> (G, G) { - match u32_less_than(x, 256) { - 1 => (x, q), - 0 => divmod_256(x - 256, q + 1), - } - } - -- Radix-2^16 schoolbook multiplication: four digits per operand. -- Even with arbitrary checked carry advice, each column is < 2^35: -- at most four 16-bit products plus a 24-bit carry. Its reconstruction diff --git a/Ix/IxVM/Kernel/NatPrim.lean b/Ix/IxVM/Kernel/NatPrim.lean index b8416b197..9ced62536 100644 --- a/Ix/IxVM/Kernel/NatPrim.lean +++ b/Ix/IxVM/Kernel/NatPrim.lean @@ -1062,22 +1062,12 @@ def natPrim := ⟦ } } - -- G (< 2^32) → single-limb KLimbs via prover-provided 4-byte split. - -- Pinned by u8 range checks + reconstruction assert. `x >= 2^32` - -- rejected (assert fails), not silently truncated. + -- Constant-time advice, called only as `#split_u32`. The checking caller + -- range-checks the four bytes and reconstructs x, rejecting x >= 2^32. + -- Recursive subtraction would retain many unconstrained execution rows. fn split_u32(x: G) -> (G, G, G, G) { - match divmod_256(x, 0) { - (b0, q1) => - match divmod_256(q1, 0) { - (b1, q2) => - match divmod_256(q2, 0) { - (b2, q3) => - match divmod_256(q3, 0) { - (b3, _) => (b0, b1, b2, b3), - }, - }, - }, - } + let [b0, b1, b2, b3, _, _, _, _] = unconstrained_g_to_bytes(x); + (b0, b1, b2, b3) } -- Convert G value (< 2^32) into single-limb KLimbs. The 4-byte diff --git a/Tests/Ix/IxVM/ByteHints.lean b/Tests/Ix/IxVM/ByteHints.lean new file mode 100644 index 000000000..ad41b3f73 --- /dev/null +++ b/Tests/Ix/IxVM/ByteHints.lean @@ -0,0 +1,164 @@ +module + +public import Ix.IxVM.Toplevel +public import Tests.Aiur.Common +public import Ix.Benchmark.Bench + +/-! +The production u32 byte hint is constant-time, untrusted advice. Exercise +its real checking caller, including normalized zero, byte boundaries, +malformed in-range advice, rejected large inputs, and native proofs. +-/ + +public section + +namespace Tests.Ix.IxVM.ByteHints + +open Aiur LSpec + +private def entries := ⟦ + pub fn u32_hint(x: G) -> (G, G, G, G) { #split_u32(x) } + pub fn checked_u32(x: G) -> U64 { + let n = klimbs_from_g(x); + match x { + 0 => + assert_eq!(load(n), ListNode.Nil, "zero must stay normalized"); + [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], + _ => + let ListNode.Cons(limb, rest) = load(n); + assert_eq!(load(rest), ListNode.Nil, "u32 must fit one limb"); + limb, + } + } +⟧ + +private def source : Except Global Source.Toplevel := do + let vm ← IxVM.ixVMFull + let vm ← vm.merge entries + pure (vm.prune [`u32_hint, `checked_u32]) + +private def bytes (n width : Nat) : Array Aiur.G := + (Array.range width).map fun i => G.ofNat ((n / 256 ^ i) % 256) + +private def boundaries : List AiurTestCase := Id.run do + let mut cases := [] + for n in [0, 1, 255, 256, 65535, 65536, 16777215, 16777216, 4294967295] do + cases := cases ++ [ + .interp `u32_hint #[G.ofNat n] (bytes n 4) s!"u32 hint {n}", + .interp `checked_u32 #[G.ofNat n] (bytes n 8) s!"checked u32 {n}"] + return cases + +private def rejects (compiled : CompiledToplevel) (input : Array Aiur.G) + (label : String) : TestSeq := + match compiled.getFuncIdx `checked_u32 with + | none => test s!"{label}: entrypoint missing" false + | some i => match compiled.bytecode.execute i input default with + | .ok _ => test s!"{label}: must reject" false + | .error _ => test label true + +private def rejectionTests (src : Source.Toplevel) + (compiled : CompiledToplevel) : TestSeq := Id.run do + let mut seq := .done + for n in [2 ^ 32, 2 ^ 32 + 1, gSize.toNat - 1] do + seq := seq ++ rejects compiled #[G.ofNat n] + s!"checked u32 rejects {n} instead of truncating" + -- Change only the untrusted hint. Range-correct but value-incorrect + -- advice must still fail the unchanged production reconstruction check. + let altered : Except String CompiledToplevel := do + if !(src.functions.any fun f => f.name.toName == `split_u32) then + throw "missing split_u32 hint" + let functions := src.functions.map fun f => + if f.name.toName == `split_u32 then + { f with body := .tuple (#[0, 0, 0, 0].map Source.Term.field) } + else f + { src with functions }.compile + seq := seq ++ withExceptOk "wrong-hint fixture compiles" altered fun wrong => + rejects wrong #[1] "u32 conversion rejects wrong in-range hint" + return seq + +private def constantTimeTests (compiled : CompiledToplevel) : TestSeq := + let direct := do + let idx ← compiled.getFuncIdx `split_u32 + let function ← compiled.bytecode.functions[idx]? + match function.body.ops.toList, function.body.ctrl with + | [.unconstrainedGToBytes 0], .return _ _ => some (!function.constrained) + | _, _ => some false + test "no repeated-subtraction divider remains reachable" + (compiled.getFuncIdx `divmod_256 == none) ++ + test "split_u32 lowers to one native hint without recursion or a circuit" + (direct == some true) + +def run : IO UInt32 := do + let .ok src := source | IO.eprintln "byte-hint fixture merge failed"; return 1 + let .ok env := AiurTestEnv.build (.ok src) + | IO.eprintln "byte-hint fixture compile failed"; return 1 + let tests := constantTimeTests env.compiled ++ rejectionTests src env.compiled + let result ← lspecIO (.ofList [("ixvm-byte-hints", [tests])]) [] + let cases ← lspecEachIO boundaries fun tc => pure (env.runTestCase tc) + let proofs ← lspecEachIO [ + AiurTestCase.prove `checked_u32 #[0] (bytes 0 8) + "normalized zero conversion prove/verify", + AiurTestCase.prove `checked_u32 #[4294967295] (bytes 4294967295 8) + "max-u32 conversion prove/verify"] fun tc => pure (env.runTestCase tc) + return if result == 0 && cases == 0 && proofs == 0 then 0 else 1 + +-- Pre-change advice retained only for the optional performance comparison. +-- These functions never enter the production toplevel or verification key. +private def oldHints := ⟦ + fn divmod_256(x: G, q: G) -> (G, G) { + match u32_less_than(x, 256) { + 1 => (x, q), + 0 => divmod_256(x - 256, q + 1), + } + } + fn split_u32(x: G) -> (G, G, G, G) { + match divmod_256(x, 0) { + (b0, q1) => match divmod_256(q1, 0) { + (b1, q2) => match divmod_256(q2, 0) { + (b2, q3) => match divmod_256(q3, 0) { + (b3, _) => (b0, b1, b2, b3), + }, + }, + }, + } + } +⟧ + +/-- Compare the same hint call using the old and new helper. Setup is outside +the timer, `blackBoxIO` forces execution inside it, and outputs are checked. +No timing assertion. `IX_AIUR_QUERY_STATS=1` also reports advice-map sizes. -/ +def timings : IO UInt32 := do + let full ← IO.ofExcept ((do + let vm ← IxVM.ixVMFull + vm.merge entries).mapError toString) + let current ← IO.ofExcept ((full.prune [`u32_hint]).compile) + let oldFns := full.functions.filter fun f => f.name.toName != `split_u32 + let oldSource := { full with functions := oldFns ++ oldHints.functions } + let legacy ← IO.ofExcept ((oldSource.prune [`u32_hint]).compile) + for n in [256, 65536, 1048576] do + for round in [:3] do + let picks := if round % 2 == 0 then [("legacy", legacy), ("native", current)] + else [("native", current), ("legacy", legacy)] + for (name, compiled) in picks do + let idx := compiled.getFuncIdx `u32_hint |>.get! + IO.eprintln s!"CASE {name} n={n} round={round}" + let start ← IO.monoNanosNow + let result ← blackBoxIO (fun _ => + compiled.bytecode.execute idx #[G.ofNat n] default) () + let stop ← IO.monoNanosNow + let (output, _, _) ← IO.ofExcept result + unless output == bytes n 4 do + throw (IO.userError "incorrect hint") + IO.println s!"{name}\t{n}\t{round}\t{(stop - start).toFloat / 1000000}" + let idx := current.getFuncIdx `u32_hint |>.get! + IO.eprintln "CASE native n=4294967295" + let result ← blackBoxIO (fun _ => + current.bytecode.execute idx #[4294967295] default) () + let (output, _, _) ← IO.ofExcept result + unless output == #[255, 255, 255, 255] do + throw (IO.userError "incorrect max-u32 hint") + return 0 + +end Tests.Ix.IxVM.ByteHints + +end diff --git a/Tests/Main.lean b/Tests/Main.lean index 542880885..1837ab852 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -3,6 +3,7 @@ import Tests.Ix.Ixon import Tests.Ix.IxonCorpus import Tests.Ix.IxonSyntax import Tests.Ix.IxVM +import Tests.Ix.IxVM.ByteHints import Tests.Ix.IxVM.Exploits import Tests.Ix.Claim import Tests.Ix.Merkle @@ -163,6 +164,7 @@ execute at module initialization for unrelated invocations. All are seconds-scale (measured 2026-08-05: aiur-prove ~11s, the rest 2-4s each). -/ def primaryRunners : List (String × IO UInt32) := [ + ("ixvm-byte-hints", Tests.Ix.IxVM.ByteHints.run), ("aiur-components", AiurTests.CallOrder.suite), ("aiur-prove", do IO.println "aiur-prove" @@ -210,6 +212,7 @@ def primaryRunners : List (String × IO UInt32) := [ /-- Ignored test runners - expensive, deferred IO actions run only when explicitly requested -/ def ignoredRunners (env : Lean.Environment) : List (String × IO UInt32) := [ + ("ixvm-byte-hint-timings", Tests.Ix.IxVM.ByteHints.timings), ("ixvm", do let kernelChecks ← kernelChecks env -- the kernel CheckEnv smokes . diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index 7720be7b9..d5b5fc6fb 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -1,7 +1,7 @@ use multi_stark::{ config::StarkGenericConfig, expr::Expr, - lookup::Lookup, + lookup::{Lookup, LookupRowMut}, p3_field::{BasedVectorSpace, PrimeCharacteristicRing}, p3_matrix::dense::RowMajorMatrix, prover::Proof, @@ -48,7 +48,7 @@ pub struct PeakProveBytes { // Across the 168 completed Mathlib shard proofs at multi-stark 2892243e, // measured RSS / analytic peak had median 1.0678 and maximum under-prediction // 1.0714. A 7.5% envelope covers the full sample with a small margin. The -// workspace now pins a8aab731; retain this historical guard, but re-calibrate +// workspace now pins 9a906122; retain this historical guard, but re-calibrate // before treating it as a full-scale safety bound for the new prover. const PROVER_RSS_CALIBRATION_NUMERATOR: usize = 43; const PROVER_RSS_CALIBRATION_DENOMINATOR: usize = 40; @@ -113,19 +113,26 @@ pub struct CircuitShape { pub preprocessed_height: usize, } -/// Raw row count of a circuit under `record`, ceil-divided into `parts` -/// even shares — `parts = 1` is the record's exact heights. The byte -/// gadgets keep their fixed heights: they are the same size in every +/// Conservative row count of a circuit under `record`, ceil-divided into +/// `parts` even shares. Sum member-function rows before dividing; circuit +/// indices are not function indices. Unlike witness generation, this count +/// includes zero-multiplicity hint rows. The byte gadgets keep their fixed +/// heights: they are the same size in every /// shard and are most of the peak model's floor, which dividing cannot /// shrink. -fn raw_of( - record: &QueryRecord, +fn raw_of<'a>( + toplevel: &'a Toplevel, + record: &'a QueryRecord, parts: usize, -) -> impl Fn(usize, &CircuitType) -> usize + '_ { +) -> impl Fn(usize, &CircuitType) -> usize + 'a { move |_, ct| match ct { - CircuitType::Function { idx } => { - record.function_queries[*idx].len().div_ceil(parts) - }, + CircuitType::Function { idx } => toplevel.circuits[*idx] + .members + .iter() + .fold(0usize, |rows, &member| { + rows.saturating_add(record.function_queries[member].len()) + }) + .div_ceil(parts), CircuitType::Memory { width } => { record.memory_queries.get(width).map_or(0, |m| m.len().div_ceil(parts)) }, @@ -276,7 +283,7 @@ impl AiurSystem { /// Predicted peak prover resident bytes for a record, from circuit /// shapes alone — the analytic counterpart of an empirical GiB-per-fft /// line. The terms mirror the allocation schedule originally calibrated at - /// multi-stark rev `2892243e`. The workspace now pins `a8aab731`, so the + /// multi-stark rev `2892243e`. The workspace now pins `9a906122`, so the /// model remains useful for relative shard sizing but needs a measured /// full-scale re-calibration before its absolute bound is relied upon: /// @@ -299,7 +306,7 @@ impl AiurSystem { /// which per-fft models blur. pub fn peak_prove_bytes(&self, record: &QueryRecord) -> PeakProveBytes { self.peak_prove_bytes_by( - raw_of(record, 1), + raw_of(&self.toplevel, record, 1), crate::execute::record_retained_bytes(record), ) } @@ -336,11 +343,21 @@ impl AiurSystem { } let n = raw.next_power_of_two(); let c = &self.system.circuits[i]; - let d = c.stage_2_width / (1 + c.num_lookups); // extension degree + // Grouped accumulator width does not determine the extension degree. + let d = >::DIMENSION; let args: usize = self.slot_widths[i].iter().sum(); let q = c.quotient_degree(); - witness += - S * n * c.main_width + S * n * (c.num_lookups + args) + 40 * raw; + let metadata = match ct { + CircuitType::Function { idx } => crate::trace::witness_metadata_bytes( + self.toplevel.circuits[*idx].members.len(), + raw, + ), + _ => 0, + }; + witness += S * n * c.main_width + + S * n * (c.num_lookups + args) + + size_of::>() * n + + metadata; s1_lde += S * b * n * c.main_width; lookup_w += S * n * (c.num_lookups + args); msgs += 2 * S * d * n * c.num_lookups; @@ -390,7 +407,10 @@ impl AiurSystem { // count; stop rather than search forever. while parts < (1 << 20) { let peak = self - .peak_prove_bytes_by(raw_of(record, parts), record_bytes / parts) + .peak_prove_bytes_by( + raw_of(&self.toplevel, record, parts), + record_bytes / parts, + ) .peak; if peak <= max_bytes { break; @@ -657,10 +677,12 @@ mod tests { mod branchless; mod byte_shapes; mod call_order; + mod host_timings; mod lookup_budget; mod lookup_groups; mod lookup_shapes; mod mmcs; + mod peak; use super::*; use crate::{ diff --git a/crates/aiur/src/synthesis/tests/host_timings.rs b/crates/aiur/src/synthesis/tests/host_timings.rs new file mode 100644 index 000000000..7ada79893 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/host_timings.rs @@ -0,0 +1,58 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use crate::bytecode::CallComponent; + +/// Run the same fixture in separate processes at the old and new revisions +/// to compare peak RSS. Construction and record allocation are outside the +/// timer; no proof is needed to measure witness generation. No timing pin. +#[test] +#[ignore = "manual witness construction memory and timing measurement"] +fn witness_construction_timings() { + use std::{hint::black_box, time::Instant}; + + let n: usize = std::env::var("AIUR_WITNESS_ROWS") + .unwrap_or_else(|_| "1048576".into()) + .parse() + .expect("positive row count"); + assert!(n > 0); + let function = Function { + body: Block { ops: vec![], ctrl: Ctrl::Return(0, vec![0]) }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 1, + lookups: 1, + }, + entry: true, + constrained: true, + }; + let mut top = with_singleton_circuits(vec![function], vec![]); + top.call_components = vec![CallComponent { order: 0, ranked: false }]; + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(top, cp, fp); + let mut record = QueryRecord::new(&system.toplevel); + for value in 0..n { + let value = G::from_usize(value); + record.function_queries[0].insert(&[value], &[value], G::ONE); + } + let start = Instant::now(); + let (trace, lookups, ranges) = system.toplevel.witness_data( + 0, + &record, + &empty_io_buffer(), + &system.slot_widths[0], + ); + let elapsed = start.elapsed(); + assert_eq!(trace.values.len(), n.next_power_of_two() * 3); + assert_eq!(&trace.values[..3], &[G::ZERO, G::ONE, G::ONE]); + assert_eq!(trace.values[(n - 1) * 3], G::from_usize(n - 1)); + assert!(ranges.is_empty()); + black_box((&trace, &lookups)); + eprintln!( + "rows={n} metadata_bytes={} witness_ms={:.3}", + crate::trace::witness_metadata_bytes(1, n), + elapsed.as_secs_f64() * 1_000.0 + ); +} diff --git a/crates/aiur/src/synthesis/tests/peak.rs b/crates/aiur/src/synthesis/tests/peak.rs new file mode 100644 index 000000000..e978f6d5a --- /dev/null +++ b/crates/aiur/src/synthesis/tests/peak.rs @@ -0,0 +1,147 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use crate::bytecode::Circuit; + +fn grouped_system() -> AiurSystem { + let layout = + FunctionLayout { input_size: 1, selectors: 1, auxiliaries: 7, lookups: 4 }; + let functions = (0..3) + .map(|_| Function { + body: Block { ops: vec![], ctrl: Ctrl::Return(0, vec![0]) }, + layout, + entry: true, + constrained: true, + }) + .collect(); + let top = Toplevel { + functions, + memory_sizes: vec![1], + circuits: vec![ + Circuit { + members: vec![2, 0], + layout: FunctionLayout { selectors: 2, ..layout }, + }, + Circuit { members: vec![1], layout }, + ], + call_components: vec![], + }; + let (cp, fp) = test_parameters(); + AiurSystem::build(top, cp, fp) +} + +fn grouped_record(top: &Toplevel) -> QueryRecord { + let mut record = QueryRecord::new(top); + for (i, rows) in [2, 3, 5].into_iter().enumerate() { + for row in 0..rows { + let value = G::from_usize(10 * i + row); + // An advice-only entry in the middle must not shift query indices + // or selectors of the surrounding active rows. + let mult = G::from_bool(i != 2 || row != 1); + record.function_queries[i].insert(&[value], &[value], mult); + } + } + record.memory_queries.get_mut(&1).unwrap().insert( + &[G::ONE], + &[G::ZERO], + G::ONE, + ); + record +} + +#[test] +fn grouped_peak_counts_members_before_splitting_and_keeps_gadget_heights() { + let system = grouped_system(); + let record = grouped_record(&system.toplevel); + let types = system.circuit_types(); + for (parts, expected) in + [(1, vec![7, 3, 1, 256, 65_536]), (4, vec![2, 1, 1, 256, 65_536])] + { + let counts: Vec<_> = types + .iter() + .enumerate() + .map(|(i, ct)| raw_of(&system.toplevel, &record, parts)(i, ct)) + .collect(); + assert_eq!(counts, expected); + } + let expected = system.peak_prove_bytes_by( + |i, _| [7, 3, 1, 256, 65_536][i], + crate::execute::record_retained_bytes(&record), + ); + assert_eq!(system.peak_prove_bytes(&record).peak, expected.peak); + assert_eq!(system.suggested_split_parts(&record, expected.peak), 1); + let half_peak = system.peak_prove_bytes_by( + |i, _| [4, 2, 1, 256, 65_536][i], + crate::execute::record_retained_bytes(&record) / 2, + ); + assert!(half_peak.peak < expected.peak); + assert_eq!(system.suggested_split_parts(&record, half_peak.peak), 2); +} + +#[test] +fn peak_uses_extension_storage_even_when_accumulators_are_grouped() { + let system = grouped_system(); + let peak = system.peak_prove_bytes_by(|_, _| 8, 0); + let circuits = &system.system.circuits; + assert!(circuits.iter().any(|c| c.lookup_group_size > 1)); + // Sum actual payload types: messages and their inverse copy are extension + // values regardless of how many accumulator columns are committed. + let expected: usize = circuits + .iter() + .zip(&system.slot_widths) + .map(|(c, widths)| { + 2 * 8 * c.main_width * size_of::() + + 8 * (c.num_lookups + widths.iter().sum::()) * size_of::() + + 2 * 8 * c.num_lookups * size_of::() + + 8 * c.stage_2_width * size_of::() + }) + .sum(); + assert_eq!(peak.phase_stage2, expected + 2 * 32 * 16); + // FRI retains base-coordinate LDEs plus extension-valued quotients. + let committed: usize = circuits + .iter() + .map(|c| { + 16 * ((c.main_width + c.stage_2_width) * size_of::() + + c.quotient_degree() * size_of::()) + }) + .sum(); + assert_eq!( + peak.phase_open, + committed + 3 * 2 * 32 * 16 + (2 * 8 + 2 * 32) * 16 * 2 + 11 * 8 * 16 + ); +} + +#[test] +fn grouped_witness_skips_advice_without_shifting_members_or_ranks() { + let system = grouped_system(); + let record = grouped_record(&system.toplevel); + let (trace, _, ranges) = system.toplevel.witness_data( + 0, + &record, + &empty_io_buffer(), + &system.slot_widths[0], + ); + assert_eq!(trace.values.len(), 8 * trace.width); + for (row, (member, query)) in + [(2, 0), (2, 2), (2, 3), (2, 4), (0, 0), (0, 1)].into_iter().enumerate() + { + let values = &trace.values[row * trace.width..(row + 1) * trace.width]; + let (_, result) = record.function_queries[member].get_index(query).unwrap(); + assert_eq!(values[0], G::from_usize(10 * member + query)); + assert_eq!( + &values[1..3], + &[G::from_bool(member == 2), G::from_bool(member == 0)] + ); + assert_eq!(values[3], G::ONE); + assert_eq!( + &values[4..10], + &result.rank.to_le_bytes()[..6] + .iter() + .map(|&b| G::from_u8(b)) + .collect::>() + ); + } + assert!(trace.values[6 * trace.width..].iter().all(|&v| v == G::ZERO)); + assert_eq!(ranges.values().copied().sum::(), G::from_u8(18)); +} diff --git a/crates/aiur/src/trace.rs b/crates/aiur/src/trace.rs index 01aa5c754..6f1047c08 100644 --- a/crates/aiur/src/trace.rs +++ b/crates/aiur/src/trace.rs @@ -26,7 +26,7 @@ use crate::{ function_channel, gadgets::{bytes1::Bytes1, bytes2::Bytes2}, memory::Memory, - querymap::QueryRef, + querymap::QueryMap, u8_add_channel, u8_and_channel, u8_bit_decomposition_channel, u8_less_than_channel, u8_mul_channel, u8_or_channel, u8_range_check_channel, u8_shift_left_channel, u8_shift_right_channel, u8_sub_channel, @@ -128,15 +128,27 @@ struct TraceContext<'a> { query_record: &'a QueryRecord, } -/// One row of a circuit trace: the member function it belongs to, the -/// member's selector offset within the circuit, its function index, and the -/// recorded query. -struct RowMeta<'a> { +/// Shared by all queried rows of one member of a circuit. +struct MemberMeta<'a> { function: &'a Function, + function_id: usize, sel_offset: usize, function_index: G, - inputs: &'a [G], - result: QueryRef<'a>, + queries: &'a QueryMap, +} + +/// Query slices and function metadata stay in their original storage. Only +/// these two indices are repeated per active row (16 bytes on 64-bit hosts). +struct RowMeta { + member: usize, + query: usize, +} + +/// Metadata allocated by the function witness builder, excluding the lookup +/// row writers shared by every circuit type. The RAM estimator can pass a +/// conservative row count that includes zero-multiplicity advice. +pub(crate) fn witness_metadata_bytes(members: usize, rows: usize) -> usize { + members * size_of::>() + rows * size_of::() } impl Toplevel { @@ -151,26 +163,34 @@ impl Toplevel { let layout = &circuit.layout; let width = layout.width(); // Concatenate the members' queried rows, in member order. - let mut rows_meta = Vec::new(); + let mut members_meta = Vec::with_capacity(circuit.members.len()); let mut sel_offset = 0; for &member in &circuit.members { let function = &self.functions[member]; - let function_index = G::from_usize(member); + members_meta.push(MemberMeta { + function, + function_id: member, + sel_offset, + function_index: G::from_usize(member), + queries: &query_record.function_queries[member], + }); + sel_offset += function.layout.selectors; + } + // Count from the compact multiplicity column before allocating: no + // geometric Vec growth and no metadata for advice-only entries. + fn active_queries(queries: &QueryMap) -> impl Iterator + '_ { + (0..queries.len()).filter(|&i| !queries.mult_at(i).is_zero()) + } + let height_no_padding = members_meta + .iter() + .map(|member| active_queries(member.queries).count()) + .sum(); + let mut rows_meta = Vec::with_capacity(height_no_padding); + for (member, meta) in members_meta.iter().enumerate() { rows_meta.extend( - query_record.function_queries[member] - .iter() - .filter(|(_, res)| !res.multiplicity.is_zero()) - .map(|(inputs, result)| RowMeta { - function, - sel_offset, - function_index, - inputs, - result, - }), + active_queries(meta.queries).map(|query| RowMeta { member, query }), ); - sel_offset += function.layout.selectors; } - let height_no_padding = rows_meta.len(); // An unqueried circuit yields an EMPTY trace (not a padded height-1 one): // the prover deactivates it, so it is neither committed nor opened. let height = if height_no_padding == 0 { @@ -189,7 +209,10 @@ impl Toplevel { .zip(row_writers[..height_no_padding].par_iter_mut()) .enumerate() .fold(RankRanges::default, |mut rank_ranges, (i, (row, lookups))| { - let meta = &rows_meta[i]; + let row_meta = &rows_meta[i]; + let meta = &members_meta[row_meta.member]; + let (inputs, result) = + meta.queries.get_index(row_meta.query).expect("recorded query"); let index = &mut ColumnIndex { auxiliary: 0, // we skip the first lookup, which is reserved for return @@ -203,20 +226,19 @@ impl Toplevel { lookups, &mut rank_ranges, ); - let function = usize::try_from(meta.function_index.as_canonical_u64()) - .expect("function index fits usize"); + let function = meta.function_id; let context = TraceContext { function, call_components: &self.call_components, function_index: meta.function_index, - inputs: meta.inputs, - multiplicity: meta.result.multiplicity, + inputs, + multiplicity: result.multiplicity, rank: if row_uses_rank(&self.call_components, function) { - meta.result.rank + result.rank } else { 0 }, - output: meta.result.output, + output: result.output, query_record, }; meta.function.populate_row(index, slice, context, io_buffer); diff --git a/crates/ixvm-codegen/src/aiur_ixvm.rs b/crates/ixvm-codegen/src/aiur_ixvm.rs index cba85c86f..c14559542 100644 --- a/crates/ixvm-codegen/src/aiur_ixvm.rs +++ b/crates/ixvm-codegen/src/aiur_ixvm.rs @@ -5229,7 +5229,7 @@ fn aiur_fn_29( let __v_72: G = __r_arr[63]; match __v_2.as_canonical_u64() { 1023u64 => { - let __r_arr: [G; OUT_783] = { let __args: [G; IN_783] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[783].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[783].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[783].bump_multiplicity(__i); } let __ret: [G; OUT_783] = unsafe { *(record.function_queries[783].output_at(__i).as_ptr() as *const [G; OUT_783]) }; __ret }, _ => aiur_fn_783(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_782] = { let __args: [G; IN_782] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[782].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[782].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[782].bump_multiplicity(__i); } let __ret: [G; OUT_782] = unsafe { *(record.function_queries[782].output_at(__i).as_ptr() as *const [G; OUT_782]) }; __ret }, _ => aiur_fn_782(__args, record, io_buffer, __cu)? } }; let __v_73: G = __r_arr[0]; let __loaded: [G; 8] = { let __mq = record.memory_queries.get_mut(&8).ok_or(ExecError::InvalidMemorySize(8))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 8 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 8] = __args[..8].try_into().unwrap(); __arr }; let __v_74: G = __loaded[0]; @@ -5410,10 +5410,10 @@ fn aiur_fn_29( return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_783] = { let __args: [G; IN_783] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[783].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[783].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[783].bump_multiplicity(__i); } let __ret: [G; OUT_783] = unsafe { *(record.function_queries[783].output_at(__i).as_ptr() as *const [G; OUT_783]) }; __ret }, _ => aiur_fn_783(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_782] = { let __args: [G; IN_782] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[782].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[782].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[782].bump_multiplicity(__i); } let __ret: [G; OUT_782] = unsafe { *(record.function_queries[782].output_at(__i).as_ptr() as *const [G; OUT_782]) }; __ret }, _ => aiur_fn_782(__args, record, io_buffer, __cu)? } }; let __v_73: G = __r_arr[0]; let __v_74: G = (__v_73 * __v_7); - let __r_arr: [G; OUT_783] = { let __args: [G; IN_783] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[783].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[783].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[783].bump_multiplicity(__i); } let __ret: [G; OUT_783] = unsafe { *(record.function_queries[783].output_at(__i).as_ptr() as *const [G; OUT_783]) }; __ret }, _ => aiur_fn_783(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_782] = { let __args: [G; IN_782] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[782].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[782].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[782].bump_multiplicity(__i); } let __ret: [G; OUT_782] = unsafe { *(record.function_queries[782].output_at(__i).as_ptr() as *const [G; OUT_782]) }; __ret }, _ => aiur_fn_782(__args, record, io_buffer, __cu)? } }; let __v_75: G = __r_arr[0]; let __loaded: [G; 8] = { let __mq = record.memory_queries.get_mut(&8).ok_or(ExecError::InvalidMemorySize(8))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 8 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 8] = __args[..8].try_into().unwrap(); __arr }; let __v_76: G = __loaded[0]; @@ -7948,7 +7948,7 @@ fn aiur_fn_34( return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_769] = { let __args: [G; IN_769] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[769].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[769].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[769].bump_multiplicity(__i); } let __ret: [G; OUT_769] = unsafe { *(record.function_queries[769].output_at(__i).as_ptr() as *const [G; OUT_769]) }; __ret }, _ => aiur_fn_769(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_768] = { let __args: [G; IN_768] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[768].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[768].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[768].bump_multiplicity(__i); } let __ret: [G; OUT_768] = unsafe { *(record.function_queries[768].output_at(__i).as_ptr() as *const [G; OUT_768]) }; __ret }, _ => aiur_fn_768(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; let __v_21: G = __r_arr[2]; @@ -7969,7 +7969,7 @@ fn aiur_fn_34( return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_769] = { let __args: [G; IN_769] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[769].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[769].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[769].bump_multiplicity(__i); } let __ret: [G; OUT_769] = unsafe { *(record.function_queries[769].output_at(__i).as_ptr() as *const [G; OUT_769]) }; __ret }, _ => aiur_fn_769(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_768] = { let __args: [G; IN_768] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[768].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[768].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[768].bump_multiplicity(__i); } let __ret: [G; OUT_768] = unsafe { *(record.function_queries[768].output_at(__i).as_ptr() as *const [G; OUT_768]) }; __ret }, _ => aiur_fn_768(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; let __v_21: G = __r_arr[2]; @@ -10067,7 +10067,7 @@ fn aiur_fn_59( let __v_63: G = G::from_u64(2); let __v_64: G = (__v_63 * __v_1); let __v_65: G = (__v_0 + __v_64); - let __r_arr: [G; OUT_781] = { let __args: [G; IN_781] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[781].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[781].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[781].bump_multiplicity(__i); } let __ret: [G; OUT_781] = unsafe { *(record.function_queries[781].output_at(__i).as_ptr() as *const [G; OUT_781]) }; __ret }, _ => aiur_fn_781(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_780] = { let __args: [G; IN_780] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[780].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[780].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[780].bump_multiplicity(__i); } let __ret: [G; OUT_780] = unsafe { *(record.function_queries[780].output_at(__i).as_ptr() as *const [G; OUT_780]) }; __ret }, _ => aiur_fn_780(__args, record, io_buffer, __cu)? } }; let __v_66: G = __r_arr[0]; let __v_67: G = __r_arr[1]; let __v_68: G = __r_arr[2]; @@ -10430,7 +10430,7 @@ fn aiur_fn_64( let __v_43: G = __loaded[15]; let __v_44: G = __loaded[16]; let __v_45: G = __loaded[17]; - let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_26]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_26]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; let __v_46: G = __r_arr[0]; let __v_47: G = __r_arr[1]; let __v_48: G = __r_arr[2]; @@ -10847,7 +10847,7 @@ fn aiur_fn_70( stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_771] = { let __args: [G; IN_771] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[771].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[771].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[771].bump_multiplicity(__i); } let __ret: [G; OUT_771] = unsafe { *(record.function_queries[771].output_at(__i).as_ptr() as *const [G; OUT_771]) }; __ret }, _ => aiur_fn_771(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_770] = { let __args: [G; IN_770] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[770].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[770].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[770].bump_multiplicity(__i); } let __ret: [G; OUT_770] = unsafe { *(record.function_queries[770].output_at(__i).as_ptr() as *const [G; OUT_770]) }; __ret }, _ => aiur_fn_770(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -10878,7 +10878,7 @@ fn aiur_fn_71( stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_771] = { let __args: [G; IN_771] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[771].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[771].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[771].bump_multiplicity(__i); } let __ret: [G; OUT_771] = unsafe { *(record.function_queries[771].output_at(__i).as_ptr() as *const [G; OUT_771]) }; __ret }, _ => aiur_fn_771(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_770] = { let __args: [G; IN_770] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[770].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[770].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[770].bump_multiplicity(__i); } let __ret: [G; OUT_770] = unsafe { *(record.function_queries[770].output_at(__i).as_ptr() as *const [G; OUT_770]) }; __ret }, _ => aiur_fn_770(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -10909,7 +10909,7 @@ fn aiur_fn_72( stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_771] = { let __args: [G; IN_771] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[771].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[771].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[771].bump_multiplicity(__i); } let __ret: [G; OUT_771] = unsafe { *(record.function_queries[771].output_at(__i).as_ptr() as *const [G; OUT_771]) }; __ret }, _ => aiur_fn_771(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_770] = { let __args: [G; IN_770] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[770].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[770].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[770].bump_multiplicity(__i); } let __ret: [G; OUT_770] = unsafe { *(record.function_queries[770].output_at(__i).as_ptr() as *const [G; OUT_770]) }; __ret }, _ => aiur_fn_770(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -10997,7 +10997,7 @@ fn aiur_fn_73( let __v_51: G = __r_arr[0]; match __v_0.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_780] = { let __args: [G; IN_780] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[780].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[780].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[780].bump_multiplicity(__i); } let __ret: [G; OUT_780] = unsafe { *(record.function_queries[780].output_at(__i).as_ptr() as *const [G; OUT_780]) }; __ret }, _ => aiur_fn_780(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_779] = { let __args: [G; IN_779] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[779].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[779].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[779].bump_multiplicity(__i); } let __ret: [G; OUT_779] = unsafe { *(record.function_queries[779].output_at(__i).as_ptr() as *const [G; OUT_779]) }; __ret }, _ => aiur_fn_779(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = __r_arr[1]; let __v_54: G = __r_arr[2]; @@ -14629,7 +14629,7 @@ fn aiur_fn_115( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __r_arr: [G; OUT_768] = { let __args: [G; IN_768] = [__v_6, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[768].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[768].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[768].bump_multiplicity(__i); } let __ret: [G; OUT_768] = unsafe { *(record.function_queries[768].output_at(__i).as_ptr() as *const [G; OUT_768]) }; __ret }, _ => aiur_fn_768(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_6, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __ret: [G; OUT_115] = [__v_5, __v_7]; record.function_queries[115].finish(&inp[..], &__ret[..], !unconstrained); @@ -15004,7 +15004,7 @@ fn aiur_fn_120( return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; match __v_23.as_canonical_u64() { 1u64 => { @@ -15388,54 +15388,15 @@ fn aiur_fn_125( }) } -const INPUT_SIZE_126: usize = 2; -const IN_126: usize = 2; -const OUT_126: usize = 2; +const INPUT_SIZE_126: usize = 16; +const IN_126: usize = 16; +const OUT_126: usize = 16; fn aiur_fn_126( inp: [G; IN_126], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, ) -> Result<[G; OUT_126], ExecError> { - stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = inp[0]; - let __v_1: G = inp[1]; - let __v_2: G = G::from_u64(256); - let __v_3: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; - match __v_3.as_canonical_u64() { - 1u64 => { - let __ret: [G; OUT_126] = [__v_0, __v_1]; - record.function_queries[126].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - 0u64 => { - let __v_4: G = G::from_u64(256); - let __v_5: G = (__v_0 - __v_4); - let __v_6: G = G::from_u64(1); - let __v_7: G = (__v_1 + __v_6); - let __r_arr: [G; OUT_126] = { let __args: [G; IN_126] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[126].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[126].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[126].bump_multiplicity(__i); } let __ret: [G; OUT_126] = unsafe { *(record.function_queries[126].output_at(__i).as_ptr() as *const [G; OUT_126]) }; __ret }, _ => aiur_fn_126(__args, record, io_buffer, __cu)? } }; - let __v_8: G = __r_arr[0]; - let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_126] = [__v_8, __v_9]; - record.function_queries[126].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - _ => { - return Err(ExecError::MatchNoCase(__v_3.as_canonical_u64())); - }, - } - }) -} - -const INPUT_SIZE_127: usize = 16; -const IN_127: usize = 16; -const OUT_127: usize = 16; -fn aiur_fn_127( - inp: [G; IN_127], - record: &mut QueryRecord, - io_buffer: &mut IOBuffer, - unconstrained: bool, -) -> Result<[G; OUT_127], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -15744,21 +15705,21 @@ fn aiur_fn_127( if (__v_237 != __v_254) { return Err(ExecError::AssertEqMismatch { lhs: __v_237.as_canonical_u64(), rhs: __v_254.as_canonical_u64(), msg: Some("u64_mul: final carry exceeds one radix digit".to_string()) }); } - let __ret: [G; OUT_127] = [__v_41, __v_42, __v_72, __v_73, __v_105, __v_106, __v_140, __v_141, __v_173, __v_174, __v_204, __v_205, __v_233, __v_234, __v_235, __v_236]; - record.function_queries[127].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_126] = [__v_41, __v_42, __v_72, __v_73, __v_105, __v_106, __v_140, __v_141, __v_173, __v_174, __v_204, __v_205, __v_233, __v_234, __v_235, __v_236]; + record.function_queries[126].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_128: usize = 1; -const IN_128: usize = 1; -const OUT_128: usize = 5; -fn aiur_fn_128( - inp: [G; IN_128], +const INPUT_SIZE_127: usize = 1; +const IN_127: usize = 1; +const OUT_127: usize = 5; +fn aiur_fn_127( + inp: [G; IN_127], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_128], ExecError> { +) -> Result<[G; OUT_127], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __gb: [u8; 8] = __v_0.as_canonical_u64().to_le_bytes(); @@ -15789,21 +15750,21 @@ fn aiur_fn_128( if (__v_0 != __v_21) { return Err(ExecError::AssertEqMismatch { lhs: __v_0.as_canonical_u64(), rhs: __v_21.as_canonical_u64(), msg: Some("u64_mul: column hint does not recompose".to_string()) }); } - let __ret: [G; OUT_128] = [__v_1, __v_2, __v_3, __v_4, __v_5]; - record.function_queries[128].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_127] = [__v_1, __v_2, __v_3, __v_4, __v_5]; + record.function_queries[127].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_129: usize = 2; -const IN_129: usize = 2; -const OUT_129: usize = 1; -fn aiur_fn_129( - inp: [G; IN_129], +const INPUT_SIZE_128: usize = 2; +const IN_128: usize = 2; +const OUT_128: usize = 1; +fn aiur_fn_128( + inp: [G; IN_128], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_129], ExecError> { +) -> Result<[G; OUT_128], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -15811,23 +15772,23 @@ fn aiur_fn_129( let __v_3: G = G::from_u64(1); let __v_4: G = { let __values: [G; 10] = [__v_2, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_130] = { let __args: [G; IN_130] = [__v_0, __v_1, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[130].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[130].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[130].bump_multiplicity(__i); } let __ret: [G; OUT_130] = unsafe { *(record.function_queries[130].output_at(__i).as_ptr() as *const [G; OUT_130]) }; __ret }, _ => aiur_fn_130(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_0, __v_1, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_129] = [__v_6]; - record.function_queries[129].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_128] = [__v_6]; + record.function_queries[128].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_130: usize = 4; -const IN_130: usize = 4; -const OUT_130: usize = 1; -fn aiur_fn_130( - inp: [G; IN_130], +const INPUT_SIZE_129: usize = 4; +const IN_129: usize = 4; +const OUT_129: usize = 1; +fn aiur_fn_129( + inp: [G; IN_129], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_130], ExecError> { +) -> Result<[G; OUT_129], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -15846,8 +15807,8 @@ fn aiur_fn_130( let __v_13: G = __loaded[9]; match __v_4.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_130] = [__v_2]; - record.function_queries[130].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_129] = [__v_2]; + record.function_queries[129].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -15859,18 +15820,18 @@ fn aiur_fn_130( let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(0); - let __r_arr: [G; OUT_131] = { let __args: [G; IN_131] = [__v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_1, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[131].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[131].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[131].bump_multiplicity(__i); } let __ret: [G; OUT_131] = unsafe { *(record.function_queries[131].output_at(__i).as_ptr() as *const [G; OUT_131]) }; __ret }, _ => aiur_fn_131(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_130] = { let __args: [G; IN_130] = [__v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_1, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[130].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[130].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[130].bump_multiplicity(__i); } let __ret: [G; OUT_130] = unsafe { *(record.function_queries[130].output_at(__i).as_ptr() as *const [G; OUT_130]) }; __ret }, _ => aiur_fn_130(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_22, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_131] = { let __args: [G; IN_131] = [__v_22, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[131].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[131].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[131].bump_multiplicity(__i); } let __ret: [G; OUT_131] = unsafe { *(record.function_queries[131].output_at(__i).as_ptr() as *const [G; OUT_131]) }; __ret }, _ => aiur_fn_131(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __r_arr: [G; OUT_118] = { let __args: [G; IN_118] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[118].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[118].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[118].bump_multiplicity(__i); } let __ret: [G; OUT_118] = unsafe { *(record.function_queries[118].output_at(__i).as_ptr() as *const [G; OUT_118]) }; __ret }, _ => aiur_fn_118(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = G::from_u64(1); let __v_26: G = (__v_3 + __v_25); - let __r_arr: [G; OUT_130] = { let __args: [G; IN_130] = [__v_13, __v_1, __v_24, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[130].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[130].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[130].bump_multiplicity(__i); } let __ret: [G; OUT_130] = unsafe { *(record.function_queries[130].output_at(__i).as_ptr() as *const [G; OUT_130]) }; __ret }, _ => aiur_fn_130(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_13, __v_1, __v_24, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __ret: [G; OUT_130] = [__v_27]; - record.function_queries[130].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_129] = [__v_27]; + record.function_queries[129].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -15880,15 +15841,15 @@ fn aiur_fn_130( }) } -const INPUT_SIZE_131: usize = 17; -const IN_131: usize = 17; -const OUT_131: usize = 1; -fn aiur_fn_131( - inp: [G; IN_131], +const INPUT_SIZE_130: usize = 17; +const IN_130: usize = 17; +const OUT_130: usize = 1; +fn aiur_fn_130( + inp: [G; IN_130], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_131], ExecError> { +) -> Result<[G; OUT_130], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -15927,8 +15888,8 @@ fn aiur_fn_131( let __v_28: G = G::from_u64(1); let __v_29: G = G::from_u64(1); let __v_30: G = { let __values: [G; 10] = [__v_28, __v_29, __v_29, __v_29, __v_29, __v_29, __v_29, __v_29, __v_29, __v_29]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_131] = [__v_30]; - record.function_queries[131].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_130] = [__v_30]; + record.function_queries[130].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -15937,8 +15898,8 @@ fn aiur_fn_131( let __v_30: G = G::from_u64(1); let __v_31: G = { let __values: [G; 10] = [__v_29, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_32: G = { let __values: [G; 10] = [__v_28, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_31]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_131] = [__v_32]; - record.function_queries[131].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_130] = [__v_32]; + record.function_queries[130].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -15947,7 +15908,7 @@ fn aiur_fn_131( } }, 0u64 => { - let __r_arr: [G; OUT_127] = { let __args: [G; IN_127] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[127].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[127].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[127].bump_multiplicity(__i); } let __ret: [G; OUT_127] = unsafe { *(record.function_queries[127].output_at(__i).as_ptr() as *const [G; OUT_127]) }; __ret }, _ => aiur_fn_127(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_126] = { let __args: [G; IN_126] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[126].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[126].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[126].bump_multiplicity(__i); } let __ret: [G; OUT_126] = unsafe { *(record.function_queries[126].output_at(__i).as_ptr() as *const [G; OUT_126]) }; __ret }, _ => aiur_fn_126(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = __r_arr[1]; let __v_29: G = __r_arr[2]; @@ -15977,11 +15938,11 @@ fn aiur_fn_131( match __v_51.as_canonical_u64() { 0u64 => { let __v_52: G = G::from_u64(0); - let __r_arr: [G; OUT_131] = { let __args: [G; IN_131] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_26, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[131].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[131].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[131].bump_multiplicity(__i); } let __ret: [G; OUT_131] = unsafe { *(record.function_queries[131].output_at(__i).as_ptr() as *const [G; OUT_131]) }; __ret }, _ => aiur_fn_131(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_130] = { let __args: [G; IN_130] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_26, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[130].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[130].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[130].bump_multiplicity(__i); } let __ret: [G; OUT_130] = unsafe { *(record.function_queries[130].output_at(__i).as_ptr() as *const [G; OUT_130]) }; __ret }, _ => aiur_fn_130(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __v_54: G = { let __values: [G; 10] = [__v_52, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_53]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_131] = [__v_54]; - record.function_queries[131].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_130] = [__v_54]; + record.function_queries[130].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -15995,11 +15956,11 @@ fn aiur_fn_131( let __v_58: G = __r_arr[5]; let __v_59: G = __r_arr[6]; let __v_60: G = __r_arr[7]; - let __r_arr: [G; OUT_131] = { let __args: [G; IN_131] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_26, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[131].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[131].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[131].bump_multiplicity(__i); } let __ret: [G; OUT_131] = unsafe { *(record.function_queries[131].output_at(__i).as_ptr() as *const [G; OUT_131]) }; __ret }, _ => aiur_fn_131(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_130] = { let __args: [G; IN_130] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_26, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[130].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[130].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[130].bump_multiplicity(__i); } let __ret: [G; OUT_130] = unsafe { *(record.function_queries[130].output_at(__i).as_ptr() as *const [G; OUT_130]) }; __ret }, _ => aiur_fn_130(__args, record, io_buffer, __cu)? } }; let __v_61: G = __r_arr[0]; let __v_62: G = { let __values: [G; 10] = [__v_52, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_61]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_131] = [__v_62]; - record.function_queries[131].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_130] = [__v_62]; + record.function_queries[130].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -16011,22 +15972,22 @@ fn aiur_fn_131( }) } -const INPUT_SIZE_132: usize = 2; -const IN_132: usize = 2; -const OUT_132: usize = 1; -fn aiur_fn_132( - inp: [G; IN_132], +const INPUT_SIZE_131: usize = 2; +const IN_131: usize = 2; +const OUT_131: usize = 1; +fn aiur_fn_131( + inp: [G; IN_131], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_132], ExecError> { +) -> Result<[G; OUT_131], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_132] = [__v_0]; - record.function_queries[132].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_131] = [__v_0]; + record.function_queries[131].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -16042,25 +16003,25 @@ fn aiur_fn_132( let __v_11: G = { let __values: [G; 10] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_0]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_12: G = G::from_u64(1); let __v_13: G = (__v_1 - __v_12); - let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_11, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_131] = { let __args: [G; IN_131] = [__v_11, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[131].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[131].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[131].bump_multiplicity(__i); } let __ret: [G; OUT_131] = unsafe { *(record.function_queries[131].output_at(__i).as_ptr() as *const [G; OUT_131]) }; __ret }, _ => aiur_fn_131(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_132] = [__v_14]; - record.function_queries[132].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_131] = [__v_14]; + record.function_queries[131].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_133: usize = 1; -const IN_133: usize = 1; -const OUT_133: usize = 1; -fn aiur_fn_133( - inp: [G; IN_133], +const INPUT_SIZE_132: usize = 1; +const IN_132: usize = 1; +const OUT_132: usize = 1; +fn aiur_fn_132( + inp: [G; IN_132], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_133], ExecError> { +) -> Result<[G; OUT_132], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; @@ -16079,29 +16040,29 @@ fn aiur_fn_133( match __v_2.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_133] = [__v_12]; - record.function_queries[133].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_132] = [__v_12]; + record.function_queries[132].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_133] = [__v_12]; - record.function_queries[133].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_132] = [__v_12]; + record.function_queries[132].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_134: usize = 2; -const IN_134: usize = 2; -const OUT_134: usize = 2; -fn aiur_fn_134( - inp: [G; IN_134], +const INPUT_SIZE_133: usize = 2; +const IN_133: usize = 2; +const OUT_133: usize = 2; +fn aiur_fn_133( + inp: [G; IN_133], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_134], ExecError> { +) -> Result<[G; OUT_133], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -16116,7 +16077,7 @@ fn aiur_fn_134( let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_128] = { let __args: [G; IN_128] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[128].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[128].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[128].bump_multiplicity(__i); } let __ret: [G; OUT_128] = unsafe { *(record.function_queries[128].output_at(__i).as_ptr() as *const [G; OUT_128]) }; __ret }, _ => aiur_fn_128(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_118] = { let __args: [G; IN_118] = [__v_8, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[118].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[118].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[118].bump_multiplicity(__i); } let __ret: [G; OUT_118] = unsafe { *(record.function_queries[118].output_at(__i).as_ptr() as *const [G; OUT_118]) }; __ret }, _ => aiur_fn_118(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; @@ -16127,18 +16088,18 @@ fn aiur_fn_134( if (__v_10 != __v_11) { return Err(ExecError::AssertEqMismatch { lhs: __v_10.as_canonical_u64(), rhs: __v_11.as_canonical_u64(), msg: Some("div/mod hint: q*b + r != a".to_string()) }); } - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(1); if (__v_13 != __v_14) { return Err(ExecError::AssertEqMismatch { lhs: __v_13.as_canonical_u64(), rhs: __v_14.as_canonical_u64(), msg: Some("div/mod hint: division by zero must yield a zero quotient".to_string()) }); } - let __ret: [G; OUT_134] = [__v_5, __v_7]; - record.function_queries[134].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_133] = [__v_5, __v_7]; + record.function_queries[133].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -16150,8 +16111,8 @@ fn aiur_fn_134( if (__v_14 != __v_15) { return Err(ExecError::AssertEqMismatch { lhs: __v_14.as_canonical_u64(), rhs: __v_15.as_canonical_u64(), msg: Some("div/mod hint: remainder is not less than the divisor".to_string()) }); } - let __ret: [G; OUT_134] = [__v_5, __v_7]; - record.function_queries[134].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_133] = [__v_5, __v_7]; + record.function_queries[133].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -16161,6 +16122,27 @@ fn aiur_fn_134( }) } +const INPUT_SIZE_134: usize = 2; +const IN_134: usize = 2; +const OUT_134: usize = 1; +fn aiur_fn_134( + inp: [G; IN_134], + record: &mut QueryRecord, + io_buffer: &mut IOBuffer, + unconstrained: bool, +) -> Result<[G; OUT_134], ExecError> { + stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { + let __v_0: G = inp[0]; + let __v_1: G = inp[1]; + let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __v_2: G = __r_arr[0]; + let __v_3: G = __r_arr[1]; + let __ret: [G; OUT_134] = [__v_2]; + record.function_queries[134].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }) +} + const INPUT_SIZE_135: usize = 2; const IN_135: usize = 2; const OUT_135: usize = 1; @@ -16173,10 +16155,10 @@ fn aiur_fn_135( stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; - let __ret: [G; OUT_135] = [__v_2]; + let __ret: [G; OUT_135] = [__v_3]; record.function_queries[135].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) @@ -16194,42 +16176,21 @@ fn aiur_fn_136( stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; - let __v_2: G = __r_arr[0]; - let __v_3: G = __r_arr[1]; - let __ret: [G; OUT_136] = [__v_3]; - record.function_queries[136].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }) -} - -const INPUT_SIZE_137: usize = 2; -const IN_137: usize = 2; -const OUT_137: usize = 1; -fn aiur_fn_137( - inp: [G; IN_137], - record: &mut QueryRecord, - io_buffer: &mut IOBuffer, - unconstrained: bool, -) -> Result<[G; OUT_137], ExecError> { - stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = inp[0]; - let __v_1: G = inp[1]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_137] = [__v_0]; - record.function_queries[137].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_136] = [__v_0]; + record.function_queries[136].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_137] = [__v_4]; - record.function_queries[137].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_136] = [__v_4]; + record.function_queries[136].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -16239,19 +16200,19 @@ fn aiur_fn_137( }) } -const INPUT_SIZE_138: usize = 2; -const IN_138: usize = 2; -const OUT_138: usize = 1; -fn aiur_fn_138( - inp: [G; IN_138], +const INPUT_SIZE_137: usize = 2; +const IN_137: usize = 2; +const OUT_137: usize = 1; +fn aiur_fn_137( + inp: [G; IN_137], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_138], ExecError> { +) -> Result<[G; OUT_137], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { @@ -16268,8 +16229,8 @@ fn aiur_fn_138( let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 10] = [__v_12, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_15: G = { let __values: [G; 10] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_14]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_138] = [__v_15]; - record.function_queries[138].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_137] = [__v_15]; + record.function_queries[137].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -16286,30 +16247,30 @@ fn aiur_fn_138( let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 10] = [__v_12, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_15: G = { let __values: [G; 10] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_14]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_1, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_1, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = __r_arr[1]; - let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_0, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_128] = { let __args: [G; IN_128] = [__v_0, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[128].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[128].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[128].bump_multiplicity(__i); } let __ret: [G; OUT_128] = unsafe { *(record.function_queries[128].output_at(__i).as_ptr() as *const [G; OUT_128]) }; __ret }, _ => aiur_fn_128(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_138] = { let __args: [G; IN_138] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[138].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[138].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[138].bump_multiplicity(__i); } let __ret: [G; OUT_138] = unsafe { *(record.function_queries[138].output_at(__i).as_ptr() as *const [G; OUT_138]) }; __ret }, _ => aiur_fn_138(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; match __v_22.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_138] = [__v_21]; - record.function_queries[138].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_137] = [__v_21]; + record.function_queries[137].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_128] = { let __args: [G; IN_128] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[128].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[128].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[128].bump_multiplicity(__i); } let __ret: [G; OUT_128] = unsafe { *(record.function_queries[128].output_at(__i).as_ptr() as *const [G; OUT_128]) }; __ret }, _ => aiur_fn_128(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_138] = [__v_23]; - record.function_queries[138].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_137] = [__v_23]; + record.function_queries[137].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -16324,15 +16285,15 @@ fn aiur_fn_138( }) } -const INPUT_SIZE_139: usize = 16; -const IN_139: usize = 16; -const OUT_139: usize = 8; -fn aiur_fn_139( - inp: [G; IN_139], +const INPUT_SIZE_138: usize = 16; +const IN_138: usize = 16; +const OUT_138: usize = 8; +fn aiur_fn_138( + inp: [G; IN_138], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_139], ExecError> { +) -> Result<[G; OUT_138], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -16358,21 +16319,21 @@ fn aiur_fn_139( let __v_21: G = if unconstrained { Bytes2::and(&__v_5, &__v_13) } else { bytes2_and_value(__v_5, __v_13, record) }; let __v_22: G = if unconstrained { Bytes2::and(&__v_6, &__v_14) } else { bytes2_and_value(__v_6, __v_14, record) }; let __v_23: G = if unconstrained { Bytes2::and(&__v_7, &__v_15) } else { bytes2_and_value(__v_7, __v_15, record) }; - let __ret: [G; OUT_139] = [__v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; - record.function_queries[139].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_138] = [__v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; + record.function_queries[138].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_140: usize = 16; -const IN_140: usize = 16; -const OUT_140: usize = 8; -fn aiur_fn_140( - inp: [G; IN_140], +const INPUT_SIZE_139: usize = 16; +const IN_139: usize = 16; +const OUT_139: usize = 8; +fn aiur_fn_139( + inp: [G; IN_139], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_140], ExecError> { +) -> Result<[G; OUT_139], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -16398,21 +16359,21 @@ fn aiur_fn_140( let __v_21: G = if unconstrained { Bytes2::or(&__v_5, &__v_13) } else { bytes2_or_value(__v_5, __v_13, record) }; let __v_22: G = if unconstrained { Bytes2::or(&__v_6, &__v_14) } else { bytes2_or_value(__v_6, __v_14, record) }; let __v_23: G = if unconstrained { Bytes2::or(&__v_7, &__v_15) } else { bytes2_or_value(__v_7, __v_15, record) }; - let __ret: [G; OUT_140] = [__v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; - record.function_queries[140].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_139] = [__v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; + record.function_queries[139].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_141: usize = 16; -const IN_141: usize = 16; -const OUT_141: usize = 8; -fn aiur_fn_141( - inp: [G; IN_141], +const INPUT_SIZE_140: usize = 16; +const IN_140: usize = 16; +const OUT_140: usize = 8; +fn aiur_fn_140( + inp: [G; IN_140], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_141], ExecError> { +) -> Result<[G; OUT_140], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -16438,12 +16399,95 @@ fn aiur_fn_141( let __v_21: G = if unconstrained { Bytes2::xor(&__v_5, &__v_13) } else { bytes2_xor_value(__v_5, __v_13, record) }; let __v_22: G = if unconstrained { Bytes2::xor(&__v_6, &__v_14) } else { bytes2_xor_value(__v_6, __v_14, record) }; let __v_23: G = if unconstrained { Bytes2::xor(&__v_7, &__v_15) } else { bytes2_xor_value(__v_7, __v_15, record) }; - let __ret: [G; OUT_141] = [__v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; - record.function_queries[141].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_140] = [__v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; + record.function_queries[140].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } +const INPUT_SIZE_141: usize = 2; +const IN_141: usize = 2; +const OUT_141: usize = 1; +fn aiur_fn_141( + inp: [G; IN_141], + record: &mut QueryRecord, + io_buffer: &mut IOBuffer, + unconstrained: bool, +) -> Result<[G; OUT_141], ExecError> { + stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { + let __v_0: G = inp[0]; + let __v_1: G = inp[1]; + let __loaded: [G; 10] = { let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 10 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 10] = __args[..10].try_into().unwrap(); __arr }; + let __v_2: G = __loaded[0]; + let __v_3: G = __loaded[1]; + let __v_4: G = __loaded[2]; + let __v_5: G = __loaded[3]; + let __v_6: G = __loaded[4]; + let __v_7: G = __loaded[5]; + let __v_8: G = __loaded[6]; + let __v_9: G = __loaded[7]; + let __v_10: G = __loaded[8]; + let __v_11: G = __loaded[9]; + match __v_2.as_canonical_u64() { + 1u64 => { + let __v_12: G = G::from_u64(1); + let __v_13: G = G::from_u64(1); + let __v_14: G = { let __values: [G; 10] = [__v_12, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; + let __ret: [G; OUT_141] = [__v_14]; + record.function_queries[141].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + 0u64 => { + let __loaded: [G; 10] = { let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; let __ptr_u64 = __v_1.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 10 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 10] = __args[..10].try_into().unwrap(); __arr }; + let __v_12: G = __loaded[0]; + let __v_13: G = __loaded[1]; + let __v_14: G = __loaded[2]; + let __v_15: G = __loaded[3]; + let __v_16: G = __loaded[4]; + let __v_17: G = __loaded[5]; + let __v_18: G = __loaded[6]; + let __v_19: G = __loaded[7]; + let __v_20: G = __loaded[8]; + let __v_21: G = __loaded[9]; + match __v_12.as_canonical_u64() { + 1u64 => { + let __v_22: G = G::from_u64(1); + let __v_23: G = G::from_u64(1); + let __v_24: G = { let __values: [G; 10] = [__v_22, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; + let __ret: [G; OUT_141] = [__v_24]; + record.function_queries[141].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + 0u64 => { + let __v_22: G = G::from_u64(0); + let __r_arr: [G; OUT_138] = { let __args: [G; IN_138] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[138].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[138].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[138].bump_multiplicity(__i); } let __ret: [G; OUT_138] = unsafe { *(record.function_queries[138].output_at(__i).as_ptr() as *const [G; OUT_138]) }; __ret }, _ => aiur_fn_138(__args, record, io_buffer, __cu)? } }; + let __v_23: G = __r_arr[0]; + let __v_24: G = __r_arr[1]; + let __v_25: G = __r_arr[2]; + let __v_26: G = __r_arr[3]; + let __v_27: G = __r_arr[4]; + let __v_28: G = __r_arr[5]; + let __v_29: G = __r_arr[6]; + let __v_30: G = __r_arr[7]; + let __r_arr: [G; OUT_141] = { let __args: [G; IN_141] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[141].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[141].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[141].bump_multiplicity(__i); } let __ret: [G; OUT_141] = unsafe { *(record.function_queries[141].output_at(__i).as_ptr() as *const [G; OUT_141]) }; __ret }, _ => aiur_fn_141(__args, record, io_buffer, __cu)? } }; + let __v_31: G = __r_arr[0]; + let __v_32: G = { let __values: [G; 10] = [__v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; + let __ret: [G; OUT_141] = [__v_32]; + record.function_queries[141].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + _ => { + return Err(ExecError::MatchNoCase(__v_12.as_canonical_u64())); + }, + } + }, + _ => { + return Err(ExecError::MatchNoCase(__v_2.as_canonical_u64())); + }, + } + }) +} + const INPUT_SIZE_142: usize = 2; const IN_142: usize = 2; const OUT_142: usize = 1; @@ -16469,10 +16513,7 @@ fn aiur_fn_142( let __v_11: G = __loaded[9]; match __v_2.as_canonical_u64() { 1u64 => { - let __v_12: G = G::from_u64(1); - let __v_13: G = G::from_u64(1); - let __v_14: G = { let __values: [G; 10] = [__v_12, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_142] = [__v_14]; + let __ret: [G; OUT_142] = [__v_1]; record.function_queries[142].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, @@ -16490,10 +16531,7 @@ fn aiur_fn_142( let __v_21: G = __loaded[9]; match __v_12.as_canonical_u64() { 1u64 => { - let __v_22: G = G::from_u64(1); - let __v_23: G = G::from_u64(1); - let __v_24: G = { let __values: [G; 10] = [__v_22, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23, __v_23]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_142] = [__v_24]; + let __ret: [G; OUT_142] = [__v_0]; record.function_queries[142].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, @@ -16613,83 +16651,6 @@ fn aiur_fn_144( io_buffer: &mut IOBuffer, unconstrained: bool, ) -> Result<[G; OUT_144], ExecError> { - stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = inp[0]; - let __v_1: G = inp[1]; - let __loaded: [G; 10] = { let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 10 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 10] = __args[..10].try_into().unwrap(); __arr }; - let __v_2: G = __loaded[0]; - let __v_3: G = __loaded[1]; - let __v_4: G = __loaded[2]; - let __v_5: G = __loaded[3]; - let __v_6: G = __loaded[4]; - let __v_7: G = __loaded[5]; - let __v_8: G = __loaded[6]; - let __v_9: G = __loaded[7]; - let __v_10: G = __loaded[8]; - let __v_11: G = __loaded[9]; - match __v_2.as_canonical_u64() { - 1u64 => { - let __ret: [G; OUT_144] = [__v_1]; - record.function_queries[144].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - 0u64 => { - let __loaded: [G; 10] = { let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; let __ptr_u64 = __v_1.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 10 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 10] = __args[..10].try_into().unwrap(); __arr }; - let __v_12: G = __loaded[0]; - let __v_13: G = __loaded[1]; - let __v_14: G = __loaded[2]; - let __v_15: G = __loaded[3]; - let __v_16: G = __loaded[4]; - let __v_17: G = __loaded[5]; - let __v_18: G = __loaded[6]; - let __v_19: G = __loaded[7]; - let __v_20: G = __loaded[8]; - let __v_21: G = __loaded[9]; - match __v_12.as_canonical_u64() { - 1u64 => { - let __ret: [G; OUT_144] = [__v_0]; - record.function_queries[144].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - 0u64 => { - let __v_22: G = G::from_u64(0); - let __r_arr: [G; OUT_141] = { let __args: [G; IN_141] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[141].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[141].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[141].bump_multiplicity(__i); } let __ret: [G; OUT_141] = unsafe { *(record.function_queries[141].output_at(__i).as_ptr() as *const [G; OUT_141]) }; __ret }, _ => aiur_fn_141(__args, record, io_buffer, __cu)? } }; - let __v_23: G = __r_arr[0]; - let __v_24: G = __r_arr[1]; - let __v_25: G = __r_arr[2]; - let __v_26: G = __r_arr[3]; - let __v_27: G = __r_arr[4]; - let __v_28: G = __r_arr[5]; - let __v_29: G = __r_arr[6]; - let __v_30: G = __r_arr[7]; - let __r_arr: [G; OUT_144] = { let __args: [G; IN_144] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[144].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[144].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[144].bump_multiplicity(__i); } let __ret: [G; OUT_144] = unsafe { *(record.function_queries[144].output_at(__i).as_ptr() as *const [G; OUT_144]) }; __ret }, _ => aiur_fn_144(__args, record, io_buffer, __cu)? } }; - let __v_31: G = __r_arr[0]; - let __v_32: G = { let __values: [G; 10] = [__v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_144] = [__v_32]; - record.function_queries[144].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - _ => { - return Err(ExecError::MatchNoCase(__v_12.as_canonical_u64())); - }, - } - }, - _ => { - return Err(ExecError::MatchNoCase(__v_2.as_canonical_u64())); - }, - } - }) -} - -const INPUT_SIZE_145: usize = 2; -const IN_145: usize = 2; -const OUT_145: usize = 1; -fn aiur_fn_145( - inp: [G; IN_145], - record: &mut QueryRecord, - io_buffer: &mut IOBuffer, - unconstrained: bool, -) -> Result<[G; OUT_145], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -16706,25 +16667,25 @@ fn aiur_fn_145( let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 10] = [__v_11, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = { let __values: [G; 10] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_138] = { let __args: [G; IN_138] = [__v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[138].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[138].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[138].bump_multiplicity(__i); } let __ret: [G; OUT_138] = unsafe { *(record.function_queries[138].output_at(__i).as_ptr() as *const [G; OUT_138]) }; __ret }, _ => aiur_fn_138(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_128] = { let __args: [G; IN_128] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[128].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[128].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[128].bump_multiplicity(__i); } let __ret: [G; OUT_128] = unsafe { *(record.function_queries[128].output_at(__i).as_ptr() as *const [G; OUT_128]) }; __ret }, _ => aiur_fn_128(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_145] = [__v_16]; - record.function_queries[145].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_144] = [__v_16]; + record.function_queries[144].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_146: usize = 2; -const IN_146: usize = 2; -const OUT_146: usize = 1; -fn aiur_fn_146( - inp: [G; IN_146], +const INPUT_SIZE_145: usize = 2; +const IN_145: usize = 2; +const OUT_145: usize = 1; +fn aiur_fn_145( + inp: [G; IN_145], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_146], ExecError> { +) -> Result<[G; OUT_145], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -16741,25 +16702,25 @@ fn aiur_fn_146( let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 10] = [__v_11, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = { let __values: [G; 10] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_138] = { let __args: [G; IN_138] = [__v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[138].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[138].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[138].bump_multiplicity(__i); } let __ret: [G; OUT_138] = unsafe { *(record.function_queries[138].output_at(__i).as_ptr() as *const [G; OUT_138]) }; __ret }, _ => aiur_fn_138(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_146] = [__v_16]; - record.function_queries[146].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_145] = [__v_16]; + record.function_queries[145].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_147: usize = 0; -const IN_147: usize = 0; -const OUT_147: usize = 1; -fn aiur_fn_147( - inp: [G; IN_147], +const INPUT_SIZE_146: usize = 0; +const IN_146: usize = 0; +const OUT_146: usize = 1; +fn aiur_fn_146( + inp: [G; IN_146], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_147], ExecError> { +) -> Result<[G; OUT_146], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(80); let __v_1: G = G::from_u64(229); @@ -16794,21 +16755,21 @@ fn aiur_fn_147( let __v_30: G = G::from_u64(12); let __v_31: G = G::from_u64(140); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_147] = [__v_32]; - record.function_queries[147].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_146] = [__v_32]; + record.function_queries[146].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_148: usize = 0; -const IN_148: usize = 0; -const OUT_148: usize = 1; -fn aiur_fn_148( - inp: [G; IN_148], +const INPUT_SIZE_147: usize = 0; +const IN_147: usize = 0; +const OUT_147: usize = 1; +fn aiur_fn_147( + inp: [G; IN_147], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_148], ExecError> { +) -> Result<[G; OUT_147], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(140); let __v_1: G = G::from_u64(9); @@ -16843,21 +16804,21 @@ fn aiur_fn_148( let __v_30: G = G::from_u64(43); let __v_31: G = G::from_u64(12); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_148] = [__v_32]; - record.function_queries[148].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_147] = [__v_32]; + record.function_queries[147].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_149: usize = 0; -const IN_149: usize = 0; -const OUT_149: usize = 1; -fn aiur_fn_149( - inp: [G; IN_149], +const INPUT_SIZE_148: usize = 0; +const IN_148: usize = 0; +const OUT_148: usize = 1; +fn aiur_fn_148( + inp: [G; IN_148], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_149], ExecError> { +) -> Result<[G; OUT_148], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(252); let __v_1: G = G::from_u64(233); @@ -16892,21 +16853,21 @@ fn aiur_fn_149( let __v_30: G = G::from_u64(214); let __v_31: G = G::from_u64(78); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_149] = [__v_32]; - record.function_queries[149].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_148] = [__v_32]; + record.function_queries[148].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_150: usize = 0; -const IN_150: usize = 0; -const OUT_150: usize = 1; -fn aiur_fn_150( - inp: [G; IN_150], +const INPUT_SIZE_149: usize = 0; +const IN_149: usize = 0; +const OUT_149: usize = 1; +fn aiur_fn_149( + inp: [G; IN_149], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_150], ExecError> { +) -> Result<[G; OUT_149], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(72); let __v_1: G = G::from_u64(120); @@ -16941,21 +16902,21 @@ fn aiur_fn_150( let __v_30: G = G::from_u64(83); let __v_31: G = G::from_u64(155); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_150] = [__v_32]; - record.function_queries[150].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_149] = [__v_32]; + record.function_queries[149].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_151: usize = 0; -const IN_151: usize = 0; -const OUT_151: usize = 1; -fn aiur_fn_151( - inp: [G; IN_151], +const INPUT_SIZE_150: usize = 0; +const IN_150: usize = 0; +const OUT_150: usize = 1; +fn aiur_fn_150( + inp: [G; IN_150], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_151], ExecError> { +) -> Result<[G; OUT_150], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(207); let __v_1: G = G::from_u64(201); @@ -16990,21 +16951,21 @@ fn aiur_fn_151( let __v_30: G = G::from_u64(14); let __v_31: G = G::from_u64(80); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_151] = [__v_32]; - record.function_queries[151].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_150] = [__v_32]; + record.function_queries[150].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_152: usize = 0; -const IN_152: usize = 0; -const OUT_152: usize = 1; -fn aiur_fn_152( - inp: [G; IN_152], +const INPUT_SIZE_151: usize = 0; +const IN_151: usize = 0; +const OUT_151: usize = 1; +fn aiur_fn_151( + inp: [G; IN_151], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_152], ExecError> { +) -> Result<[G; OUT_151], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(30); let __v_1: G = G::from_u64(96); @@ -17039,21 +17000,21 @@ fn aiur_fn_152( let __v_30: G = G::from_u64(185); let __v_31: G = G::from_u64(100); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_152] = [__v_32]; - record.function_queries[152].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_151] = [__v_32]; + record.function_queries[151].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_153: usize = 0; -const IN_153: usize = 0; -const OUT_153: usize = 1; -fn aiur_fn_153( - inp: [G; IN_153], +const INPUT_SIZE_152: usize = 0; +const IN_152: usize = 0; +const OUT_152: usize = 1; +fn aiur_fn_152( + inp: [G; IN_152], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_153], ExecError> { +) -> Result<[G; OUT_152], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(13); let __v_1: G = G::from_u64(116); @@ -17088,21 +17049,21 @@ fn aiur_fn_153( let __v_30: G = G::from_u64(24); let __v_31: G = G::from_u64(77); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_153] = [__v_32]; - record.function_queries[153].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_152] = [__v_32]; + record.function_queries[152].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_154: usize = 0; -const IN_154: usize = 0; -const OUT_154: usize = 1; -fn aiur_fn_154( - inp: [G; IN_154], +const INPUT_SIZE_153: usize = 0; +const IN_153: usize = 0; +const OUT_153: usize = 1; +fn aiur_fn_153( + inp: [G; IN_153], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_154], ExecError> { +) -> Result<[G; OUT_153], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(197); let __v_1: G = G::from_u64(190); @@ -17137,21 +17098,21 @@ fn aiur_fn_154( let __v_30: G = G::from_u64(197); let __v_31: G = G::from_u64(90); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_154] = [__v_32]; - record.function_queries[154].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_153] = [__v_32]; + record.function_queries[153].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_155: usize = 0; -const IN_155: usize = 0; -const OUT_155: usize = 1; -fn aiur_fn_155( - inp: [G; IN_155], +const INPUT_SIZE_154: usize = 0; +const IN_154: usize = 0; +const OUT_154: usize = 1; +fn aiur_fn_154( + inp: [G; IN_154], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_155], ExecError> { +) -> Result<[G; OUT_154], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(188); let __v_1: G = G::from_u64(97); @@ -17186,21 +17147,21 @@ fn aiur_fn_155( let __v_30: G = G::from_u64(75); let __v_31: G = G::from_u64(162); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_155] = [__v_32]; - record.function_queries[155].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_154] = [__v_32]; + record.function_queries[154].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_156: usize = 0; -const IN_156: usize = 0; -const OUT_156: usize = 1; -fn aiur_fn_156( - inp: [G; IN_156], +const INPUT_SIZE_155: usize = 0; +const IN_155: usize = 0; +const OUT_155: usize = 1; +fn aiur_fn_155( + inp: [G; IN_155], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_156], ExecError> { +) -> Result<[G; OUT_155], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(212); let __v_1: G = G::from_u64(53); @@ -17235,21 +17196,21 @@ fn aiur_fn_156( let __v_30: G = G::from_u64(114); let __v_31: G = G::from_u64(39); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_156] = [__v_32]; - record.function_queries[156].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_155] = [__v_32]; + record.function_queries[155].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_157: usize = 0; -const IN_157: usize = 0; -const OUT_157: usize = 1; -fn aiur_fn_157( - inp: [G; IN_157], +const INPUT_SIZE_156: usize = 0; +const IN_156: usize = 0; +const OUT_156: usize = 1; +fn aiur_fn_156( + inp: [G; IN_156], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_157], ExecError> { +) -> Result<[G; OUT_156], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(62); let __v_1: G = G::from_u64(19); @@ -17284,21 +17245,21 @@ fn aiur_fn_157( let __v_30: G = G::from_u64(203); let __v_31: G = G::from_u64(14); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_157] = [__v_32]; - record.function_queries[157].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_156] = [__v_32]; + record.function_queries[156].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_158: usize = 0; -const IN_158: usize = 0; -const OUT_158: usize = 1; -fn aiur_fn_158( - inp: [G; IN_158], +const INPUT_SIZE_157: usize = 0; +const IN_157: usize = 0; +const OUT_157: usize = 1; +fn aiur_fn_157( + inp: [G; IN_157], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_158], ExecError> { +) -> Result<[G; OUT_157], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(153); let __v_1: G = G::from_u64(112); @@ -17333,21 +17294,21 @@ fn aiur_fn_158( let __v_30: G = G::from_u64(241); let __v_31: G = G::from_u64(156); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_158] = [__v_32]; - record.function_queries[158].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_157] = [__v_32]; + record.function_queries[157].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_159: usize = 0; -const IN_159: usize = 0; -const OUT_159: usize = 1; -fn aiur_fn_159( - inp: [G; IN_159], +const INPUT_SIZE_158: usize = 0; +const IN_158: usize = 0; +const OUT_158: usize = 1; +fn aiur_fn_158( + inp: [G; IN_158], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_159], ExecError> { +) -> Result<[G; OUT_158], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(134); let __v_1: G = G::from_u64(127); @@ -17382,21 +17343,21 @@ fn aiur_fn_159( let __v_30: G = G::from_u64(70); let __v_31: G = G::from_u64(246); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_159] = [__v_32]; - record.function_queries[159].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_158] = [__v_32]; + record.function_queries[158].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_160: usize = 0; -const IN_160: usize = 0; -const OUT_160: usize = 1; -fn aiur_fn_160( - inp: [G; IN_160], +const INPUT_SIZE_159: usize = 0; +const IN_159: usize = 0; +const OUT_159: usize = 1; +fn aiur_fn_159( + inp: [G; IN_159], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_160], ExecError> { +) -> Result<[G; OUT_159], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(33); let __v_1: G = G::from_u64(212); @@ -17431,21 +17392,21 @@ fn aiur_fn_160( let __v_30: G = G::from_u64(85); let __v_31: G = G::from_u64(68); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_160] = [__v_32]; - record.function_queries[160].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_159] = [__v_32]; + record.function_queries[159].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_161: usize = 0; -const IN_161: usize = 0; -const OUT_161: usize = 1; -fn aiur_fn_161( - inp: [G; IN_161], +const INPUT_SIZE_160: usize = 0; +const IN_160: usize = 0; +const OUT_160: usize = 1; +fn aiur_fn_160( + inp: [G; IN_160], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_161], ExecError> { +) -> Result<[G; OUT_160], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(135); let __v_1: G = G::from_u64(133); @@ -17480,21 +17441,21 @@ fn aiur_fn_161( let __v_30: G = G::from_u64(173); let __v_31: G = G::from_u64(134); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_161] = [__v_32]; - record.function_queries[161].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_160] = [__v_32]; + record.function_queries[160].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_162: usize = 0; -const IN_162: usize = 0; -const OUT_162: usize = 1; -fn aiur_fn_162( - inp: [G; IN_162], +const INPUT_SIZE_161: usize = 0; +const IN_161: usize = 0; +const OUT_161: usize = 1; +fn aiur_fn_161( + inp: [G; IN_161], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_162], ExecError> { +) -> Result<[G; OUT_161], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(249); let __v_1: G = G::from_u64(172); @@ -17529,21 +17490,21 @@ fn aiur_fn_162( let __v_30: G = G::from_u64(84); let __v_31: G = G::from_u64(60); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_162] = [__v_32]; - record.function_queries[162].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_161] = [__v_32]; + record.function_queries[161].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_163: usize = 0; -const IN_163: usize = 0; -const OUT_163: usize = 1; -fn aiur_fn_163( - inp: [G; IN_163], +const INPUT_SIZE_162: usize = 0; +const IN_162: usize = 0; +const OUT_162: usize = 1; +fn aiur_fn_162( + inp: [G; IN_162], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_163], ExecError> { +) -> Result<[G; OUT_162], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(223); let __v_1: G = G::from_u64(56); @@ -17578,21 +17539,21 @@ fn aiur_fn_163( let __v_30: G = G::from_u64(235); let __v_31: G = G::from_u64(9); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_163] = [__v_32]; - record.function_queries[163].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_162] = [__v_32]; + record.function_queries[162].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_164: usize = 0; -const IN_164: usize = 0; -const OUT_164: usize = 1; -fn aiur_fn_164( - inp: [G; IN_164], +const INPUT_SIZE_163: usize = 0; +const IN_163: usize = 0; +const OUT_163: usize = 1; +fn aiur_fn_163( + inp: [G; IN_163], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_164], ExecError> { +) -> Result<[G; OUT_163], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(243); let __v_1: G = G::from_u64(141); @@ -17627,21 +17588,21 @@ fn aiur_fn_164( let __v_30: G = G::from_u64(22); let __v_31: G = G::from_u64(170); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_164] = [__v_32]; - record.function_queries[164].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_163] = [__v_32]; + record.function_queries[163].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_165: usize = 0; -const IN_165: usize = 0; -const OUT_165: usize = 1; -fn aiur_fn_165( - inp: [G; IN_165], +const INPUT_SIZE_164: usize = 0; +const IN_164: usize = 0; +const OUT_164: usize = 1; +fn aiur_fn_164( + inp: [G; IN_164], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_165], ExecError> { +) -> Result<[G; OUT_164], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(104); let __v_1: G = G::from_u64(246); @@ -17676,21 +17637,21 @@ fn aiur_fn_165( let __v_30: G = G::from_u64(230); let __v_31: G = G::from_u64(253); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_165] = [__v_32]; - record.function_queries[165].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_164] = [__v_32]; + record.function_queries[164].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_166: usize = 0; -const IN_166: usize = 0; -const OUT_166: usize = 1; -fn aiur_fn_166( - inp: [G; IN_166], +const INPUT_SIZE_165: usize = 0; +const IN_165: usize = 0; +const OUT_165: usize = 1; +fn aiur_fn_165( + inp: [G; IN_165], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_166], ExecError> { +) -> Result<[G; OUT_165], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(173); let __v_1: G = G::from_u64(71); @@ -17725,21 +17686,21 @@ fn aiur_fn_166( let __v_30: G = G::from_u64(127); let __v_31: G = G::from_u64(3); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_166] = [__v_32]; - record.function_queries[166].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_165] = [__v_32]; + record.function_queries[165].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_167: usize = 0; -const IN_167: usize = 0; -const OUT_167: usize = 1; -fn aiur_fn_167( - inp: [G; IN_167], +const INPUT_SIZE_166: usize = 0; +const IN_166: usize = 0; +const OUT_166: usize = 1; +fn aiur_fn_166( + inp: [G; IN_166], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_167], ExecError> { +) -> Result<[G; OUT_166], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(246); let __v_1: G = G::from_u64(235); @@ -17774,21 +17735,21 @@ fn aiur_fn_167( let __v_30: G = G::from_u64(13); let __v_31: G = G::from_u64(123); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_167] = [__v_32]; - record.function_queries[167].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_166] = [__v_32]; + record.function_queries[166].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_168: usize = 0; -const IN_168: usize = 0; -const OUT_168: usize = 1; -fn aiur_fn_168( - inp: [G; IN_168], +const INPUT_SIZE_167: usize = 0; +const IN_167: usize = 0; +const OUT_167: usize = 1; +fn aiur_fn_167( + inp: [G; IN_167], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_168], ExecError> { +) -> Result<[G; OUT_167], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(35); let __v_1: G = G::from_u64(23); @@ -17823,21 +17784,21 @@ fn aiur_fn_168( let __v_30: G = G::from_u64(211); let __v_31: G = G::from_u64(231); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_168] = [__v_32]; - record.function_queries[168].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_167] = [__v_32]; + record.function_queries[167].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_169: usize = 0; -const IN_169: usize = 0; -const OUT_169: usize = 1; -fn aiur_fn_169( - inp: [G; IN_169], +const INPUT_SIZE_168: usize = 0; +const IN_168: usize = 0; +const OUT_168: usize = 1; +fn aiur_fn_168( + inp: [G; IN_168], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_169], ExecError> { +) -> Result<[G; OUT_168], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(143); let __v_1: G = G::from_u64(71); @@ -17872,21 +17833,21 @@ fn aiur_fn_169( let __v_30: G = G::from_u64(111); let __v_31: G = G::from_u64(59); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_169] = [__v_32]; - record.function_queries[169].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_168] = [__v_32]; + record.function_queries[168].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_170: usize = 0; -const IN_170: usize = 0; -const OUT_170: usize = 1; -fn aiur_fn_170( - inp: [G; IN_170], +const INPUT_SIZE_169: usize = 0; +const IN_169: usize = 0; +const OUT_169: usize = 1; +fn aiur_fn_169( + inp: [G; IN_169], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_170], ExecError> { +) -> Result<[G; OUT_169], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(143); let __v_1: G = G::from_u64(60); @@ -17921,21 +17882,21 @@ fn aiur_fn_170( let __v_30: G = G::from_u64(44); let __v_31: G = G::from_u64(99); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_170] = [__v_32]; - record.function_queries[170].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_169] = [__v_32]; + record.function_queries[169].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_171: usize = 0; -const IN_171: usize = 0; -const OUT_171: usize = 1; -fn aiur_fn_171( - inp: [G; IN_171], +const INPUT_SIZE_170: usize = 0; +const IN_170: usize = 0; +const OUT_170: usize = 1; +fn aiur_fn_170( + inp: [G; IN_170], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_171], ExecError> { +) -> Result<[G; OUT_170], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(128); let __v_1: G = G::from_u64(10); @@ -17970,21 +17931,21 @@ fn aiur_fn_171( let __v_30: G = G::from_u64(253); let __v_31: G = G::from_u64(31); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_171] = [__v_32]; - record.function_queries[171].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_170] = [__v_32]; + record.function_queries[170].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_172: usize = 0; -const IN_172: usize = 0; -const OUT_172: usize = 1; -fn aiur_fn_172( - inp: [G; IN_172], +const INPUT_SIZE_171: usize = 0; +const IN_171: usize = 0; +const OUT_171: usize = 1; +fn aiur_fn_171( + inp: [G; IN_171], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_172], ExecError> { +) -> Result<[G; OUT_171], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(84); let __v_1: G = G::from_u64(115); @@ -18019,21 +17980,21 @@ fn aiur_fn_172( let __v_30: G = G::from_u64(12); let __v_31: G = G::from_u64(210); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_172] = [__v_32]; - record.function_queries[172].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_171] = [__v_32]; + record.function_queries[171].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_173: usize = 0; -const IN_173: usize = 0; -const OUT_173: usize = 1; -fn aiur_fn_173( - inp: [G; IN_173], +const INPUT_SIZE_172: usize = 0; +const IN_172: usize = 0; +const OUT_172: usize = 1; +fn aiur_fn_172( + inp: [G; IN_172], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_173], ExecError> { +) -> Result<[G; OUT_172], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(27); let __v_1: G = G::from_u64(89); @@ -18068,21 +18029,21 @@ fn aiur_fn_173( let __v_30: G = G::from_u64(190); let __v_31: G = G::from_u64(213); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_173] = [__v_32]; - record.function_queries[173].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_172] = [__v_32]; + record.function_queries[172].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_174: usize = 0; -const IN_174: usize = 0; -const OUT_174: usize = 1; -fn aiur_fn_174( - inp: [G; IN_174], +const INPUT_SIZE_173: usize = 0; +const IN_173: usize = 0; +const OUT_173: usize = 1; +fn aiur_fn_173( + inp: [G; IN_173], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_174], ExecError> { +) -> Result<[G; OUT_173], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(114); let __v_1: G = G::from_u64(198); @@ -18117,21 +18078,21 @@ fn aiur_fn_174( let __v_30: G = G::from_u64(98); let __v_31: G = G::from_u64(174); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_174] = [__v_32]; - record.function_queries[174].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_173] = [__v_32]; + record.function_queries[173].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_175: usize = 0; -const IN_175: usize = 0; -const OUT_175: usize = 1; -fn aiur_fn_175( - inp: [G; IN_175], +const INPUT_SIZE_174: usize = 0; +const IN_174: usize = 0; +const OUT_174: usize = 1; +fn aiur_fn_174( + inp: [G; IN_174], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_175], ExecError> { +) -> Result<[G; OUT_174], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(195); let __v_1: G = G::from_u64(127); @@ -18166,21 +18127,21 @@ fn aiur_fn_175( let __v_30: G = G::from_u64(104); let __v_31: G = G::from_u64(142); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_175] = [__v_32]; - record.function_queries[175].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_174] = [__v_32]; + record.function_queries[174].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_176: usize = 0; -const IN_176: usize = 0; -const OUT_176: usize = 1; -fn aiur_fn_176( - inp: [G; IN_176], +const INPUT_SIZE_175: usize = 0; +const IN_175: usize = 0; +const OUT_175: usize = 1; +fn aiur_fn_175( + inp: [G; IN_175], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_176], ExecError> { +) -> Result<[G; OUT_175], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(162); let __v_1: G = G::from_u64(154); @@ -18215,21 +18176,21 @@ fn aiur_fn_176( let __v_30: G = G::from_u64(87); let __v_31: G = G::from_u64(98); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_176] = [__v_32]; - record.function_queries[176].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_175] = [__v_32]; + record.function_queries[175].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_177: usize = 0; -const IN_177: usize = 0; -const OUT_177: usize = 1; -fn aiur_fn_177( - inp: [G; IN_177], +const INPUT_SIZE_176: usize = 0; +const IN_176: usize = 0; +const OUT_176: usize = 1; +fn aiur_fn_176( + inp: [G; IN_176], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_177], ExecError> { +) -> Result<[G; OUT_176], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(221); let __v_1: G = G::from_u64(161); @@ -18264,21 +18225,21 @@ fn aiur_fn_177( let __v_30: G = G::from_u64(198); let __v_31: G = G::from_u64(62); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_177] = [__v_32]; - record.function_queries[177].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_176] = [__v_32]; + record.function_queries[176].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_178: usize = 0; -const IN_178: usize = 0; -const OUT_178: usize = 1; -fn aiur_fn_178( - inp: [G; IN_178], +const INPUT_SIZE_177: usize = 0; +const IN_177: usize = 0; +const OUT_177: usize = 1; +fn aiur_fn_177( + inp: [G; IN_177], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_178], ExecError> { +) -> Result<[G; OUT_177], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(80); let __v_1: G = G::from_u64(96); @@ -18313,21 +18274,21 @@ fn aiur_fn_178( let __v_30: G = G::from_u64(128); let __v_31: G = G::from_u64(13); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_178] = [__v_32]; - record.function_queries[178].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_177] = [__v_32]; + record.function_queries[177].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_179: usize = 0; -const IN_179: usize = 0; -const OUT_179: usize = 1; -fn aiur_fn_179( - inp: [G; IN_179], +const INPUT_SIZE_178: usize = 0; +const IN_178: usize = 0; +const OUT_178: usize = 1; +fn aiur_fn_178( + inp: [G; IN_178], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_179], ExecError> { +) -> Result<[G; OUT_178], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(132); let __v_1: G = G::from_u64(254); @@ -18362,21 +18323,21 @@ fn aiur_fn_179( let __v_30: G = G::from_u64(138); let __v_31: G = G::from_u64(37); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_179] = [__v_32]; - record.function_queries[179].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_178] = [__v_32]; + record.function_queries[178].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_180: usize = 0; -const IN_180: usize = 0; -const OUT_180: usize = 1; -fn aiur_fn_180( - inp: [G; IN_180], +const INPUT_SIZE_179: usize = 0; +const IN_179: usize = 0; +const OUT_179: usize = 1; +fn aiur_fn_179( + inp: [G; IN_179], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_180], ExecError> { +) -> Result<[G; OUT_179], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(212); let __v_1: G = G::from_u64(215); @@ -18411,21 +18372,21 @@ fn aiur_fn_180( let __v_30: G = G::from_u64(38); let __v_31: G = G::from_u64(12); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_180] = [__v_32]; - record.function_queries[180].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_179] = [__v_32]; + record.function_queries[179].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_181: usize = 0; -const IN_181: usize = 0; -const OUT_181: usize = 1; -fn aiur_fn_181( - inp: [G; IN_181], +const INPUT_SIZE_180: usize = 0; +const IN_180: usize = 0; +const OUT_180: usize = 1; +fn aiur_fn_180( + inp: [G; IN_180], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_181], ExecError> { +) -> Result<[G; OUT_180], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(32); let __v_1: G = G::from_u64(117); @@ -18460,21 +18421,21 @@ fn aiur_fn_181( let __v_30: G = G::from_u64(185); let __v_31: G = G::from_u64(93); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_181] = [__v_32]; - record.function_queries[181].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_180] = [__v_32]; + record.function_queries[180].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_182: usize = 0; -const IN_182: usize = 0; -const OUT_182: usize = 1; -fn aiur_fn_182( - inp: [G; IN_182], +const INPUT_SIZE_181: usize = 0; +const IN_181: usize = 0; +const OUT_181: usize = 1; +fn aiur_fn_181( + inp: [G; IN_181], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_182], ExecError> { +) -> Result<[G; OUT_181], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(126); let __v_1: G = G::from_u64(78); @@ -18509,21 +18470,21 @@ fn aiur_fn_182( let __v_30: G = G::from_u64(145); let __v_31: G = G::from_u64(88); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_182] = [__v_32]; - record.function_queries[182].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_181] = [__v_32]; + record.function_queries[181].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_183: usize = 0; -const IN_183: usize = 0; -const OUT_183: usize = 1; -fn aiur_fn_183( - inp: [G; IN_183], +const INPUT_SIZE_182: usize = 0; +const IN_182: usize = 0; +const OUT_182: usize = 1; +fn aiur_fn_182( + inp: [G; IN_182], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_183], ExecError> { +) -> Result<[G; OUT_182], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(128); let __v_1: G = G::from_u64(249); @@ -18558,86 +18519,86 @@ fn aiur_fn_183( let __v_30: G = G::from_u64(78); let __v_31: G = G::from_u64(108); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_183] = [__v_32]; - record.function_queries[183].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_182] = [__v_32]; + record.function_queries[182].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_184: usize = 1; -const IN_184: usize = 1; -const OUT_184: usize = 1; -fn aiur_fn_184( - inp: [G; IN_184], +const INPUT_SIZE_183: usize = 1; +const IN_183: usize = 1; +const OUT_183: usize = 1; +fn aiur_fn_183( + inp: [G; IN_183], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_184], ExecError> { +) -> Result<[G; OUT_183], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_178] = { let __args: [G; IN_178] = []; let __cu = unconstrained; let __hit = record.function_queries[178].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[178].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[178].bump_multiplicity(__i); } let __ret: [G; OUT_178] = unsafe { *(record.function_queries[178].output_at(__i).as_ptr() as *const [G; OUT_178]) }; __ret }, _ => aiur_fn_178(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_177] = { let __args: [G; IN_177] = []; let __cu = unconstrained; let __hit = record.function_queries[177].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[177].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[177].bump_multiplicity(__i); } let __ret: [G; OUT_177] = unsafe { *(record.function_queries[177].output_at(__i).as_ptr() as *const [G; OUT_177]) }; __ret }, _ => aiur_fn_177(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_184] = [__v_3]; - record.function_queries[184].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_183] = [__v_3]; + record.function_queries[183].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_179] = { let __args: [G; IN_179] = []; let __cu = unconstrained; let __hit = record.function_queries[179].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[179].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[179].bump_multiplicity(__i); } let __ret: [G; OUT_179] = unsafe { *(record.function_queries[179].output_at(__i).as_ptr() as *const [G; OUT_179]) }; __ret }, _ => aiur_fn_179(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_178] = { let __args: [G; IN_178] = []; let __cu = unconstrained; let __hit = record.function_queries[178].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[178].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[178].bump_multiplicity(__i); } let __ret: [G; OUT_178] = unsafe { *(record.function_queries[178].output_at(__i).as_ptr() as *const [G; OUT_178]) }; __ret }, _ => aiur_fn_178(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_184] = [__v_5]; - record.function_queries[184].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_183] = [__v_5]; + record.function_queries[183].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_180] = { let __args: [G; IN_180] = []; let __cu = unconstrained; let __hit = record.function_queries[180].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[180].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[180].bump_multiplicity(__i); } let __ret: [G; OUT_180] = unsafe { *(record.function_queries[180].output_at(__i).as_ptr() as *const [G; OUT_180]) }; __ret }, _ => aiur_fn_180(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_179] = { let __args: [G; IN_179] = []; let __cu = unconstrained; let __hit = record.function_queries[179].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[179].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[179].bump_multiplicity(__i); } let __ret: [G; OUT_179] = unsafe { *(record.function_queries[179].output_at(__i).as_ptr() as *const [G; OUT_179]) }; __ret }, _ => aiur_fn_179(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_184] = [__v_7]; - record.function_queries[184].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_183] = [__v_7]; + record.function_queries[183].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_181] = { let __args: [G; IN_181] = []; let __cu = unconstrained; let __hit = record.function_queries[181].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[181].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[181].bump_multiplicity(__i); } let __ret: [G; OUT_181] = unsafe { *(record.function_queries[181].output_at(__i).as_ptr() as *const [G; OUT_181]) }; __ret }, _ => aiur_fn_181(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_180] = { let __args: [G; IN_180] = []; let __cu = unconstrained; let __hit = record.function_queries[180].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[180].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[180].bump_multiplicity(__i); } let __ret: [G; OUT_180] = unsafe { *(record.function_queries[180].output_at(__i).as_ptr() as *const [G; OUT_180]) }; __ret }, _ => aiur_fn_180(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_184] = [__v_9]; - record.function_queries[184].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_183] = [__v_9]; + record.function_queries[183].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_182] = { let __args: [G; IN_182] = []; let __cu = unconstrained; let __hit = record.function_queries[182].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[182].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[182].bump_multiplicity(__i); } let __ret: [G; OUT_182] = unsafe { *(record.function_queries[182].output_at(__i).as_ptr() as *const [G; OUT_182]) }; __ret }, _ => aiur_fn_182(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_181] = { let __args: [G; IN_181] = []; let __cu = unconstrained; let __hit = record.function_queries[181].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[181].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[181].bump_multiplicity(__i); } let __ret: [G; OUT_181] = unsafe { *(record.function_queries[181].output_at(__i).as_ptr() as *const [G; OUT_181]) }; __ret }, _ => aiur_fn_181(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(1); - let __ret: [G; OUT_184] = [__v_11]; - record.function_queries[184].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_183] = [__v_11]; + record.function_queries[183].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_184] = [__v_11]; - record.function_queries[184].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_183] = [__v_11]; + record.function_queries[183].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -18652,15 +18613,15 @@ fn aiur_fn_184( }) } -const INPUT_SIZE_185: usize = 0; -const IN_185: usize = 0; -const OUT_185: usize = 1; -fn aiur_fn_185( - inp: [G; IN_185], +const INPUT_SIZE_184: usize = 0; +const IN_184: usize = 0; +const OUT_184: usize = 1; +fn aiur_fn_184( + inp: [G; IN_184], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_185], ExecError> { +) -> Result<[G; OUT_184], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(0); let __v_1: G = G::from_u64(64); @@ -18679,21 +18640,21 @@ fn aiur_fn_185( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_12, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_185] = [__v_16]; - record.function_queries[185].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_184] = [__v_16]; + record.function_queries[184].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_186: usize = 0; -const IN_186: usize = 0; -const OUT_186: usize = 1; -fn aiur_fn_186( - inp: [G; IN_186], +const INPUT_SIZE_185: usize = 0; +const IN_185: usize = 0; +const OUT_185: usize = 1; +fn aiur_fn_185( + inp: [G; IN_185], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_186], ExecError> { +) -> Result<[G; OUT_185], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(0); let __v_1: G = G::from_u64(1); @@ -18712,72 +18673,72 @@ fn aiur_fn_186( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_12, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_186] = [__v_16]; - record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_185] = [__v_16]; + record.function_queries[185].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_187: usize = 3; -const IN_187: usize = 3; -const OUT_187: usize = 2; -fn aiur_fn_187( - inp: [G; IN_187], +const INPUT_SIZE_186: usize = 3; +const IN_186: usize = 3; +const OUT_186: usize = 2; +fn aiur_fn_186( + inp: [G; IN_186], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_187], ExecError> { +) -> Result<[G; OUT_186], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_178] = { let __args: [G; IN_178] = []; let __cu = unconstrained; let __hit = record.function_queries[178].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[178].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[178].bump_multiplicity(__i); } let __ret: [G; OUT_178] = unsafe { *(record.function_queries[178].output_at(__i).as_ptr() as *const [G; OUT_178]) }; __ret }, _ => aiur_fn_178(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_177] = { let __args: [G; IN_177] = []; let __cu = unconstrained; let __hit = record.function_queries[177].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[177].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[177].bump_multiplicity(__i); } let __ret: [G; OUT_177] = unsafe { *(record.function_queries[177].output_at(__i).as_ptr() as *const [G; OUT_177]) }; __ret }, _ => aiur_fn_177(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __r_arr: [G; OUT_185] = { let __args: [G; IN_185] = []; let __cu = unconstrained; let __hit = record.function_queries[185].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[185].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[185].bump_multiplicity(__i); } let __ret: [G; OUT_185] = unsafe { *(record.function_queries[185].output_at(__i).as_ptr() as *const [G; OUT_185]) }; __ret }, _ => aiur_fn_185(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_184] = { let __args: [G; IN_184] = []; let __cu = unconstrained; let __hit = record.function_queries[184].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[184].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[184].bump_multiplicity(__i); } let __ret: [G; OUT_184] = unsafe { *(record.function_queries[184].output_at(__i).as_ptr() as *const [G; OUT_184]) }; __ret }, _ => aiur_fn_184(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_187] = [__v_5, __v_6]; - record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_186] = [__v_5, __v_6]; + record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_179] = { let __args: [G; IN_179] = []; let __cu = unconstrained; let __hit = record.function_queries[179].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[179].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[179].bump_multiplicity(__i); } let __ret: [G; OUT_179] = unsafe { *(record.function_queries[179].output_at(__i).as_ptr() as *const [G; OUT_179]) }; __ret }, _ => aiur_fn_179(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_178] = { let __args: [G; IN_178] = []; let __cu = unconstrained; let __hit = record.function_queries[178].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[178].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[178].bump_multiplicity(__i); } let __ret: [G; OUT_178] = unsafe { *(record.function_queries[178].output_at(__i).as_ptr() as *const [G; OUT_178]) }; __ret }, _ => aiur_fn_178(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __r_arr: [G; OUT_186] = { let __args: [G; IN_186] = []; let __cu = unconstrained; let __hit = record.function_queries[186].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[186].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[186].bump_multiplicity(__i); } let __ret: [G; OUT_186] = unsafe { *(record.function_queries[186].output_at(__i).as_ptr() as *const [G; OUT_186]) }; __ret }, _ => aiur_fn_186(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_185] = { let __args: [G; IN_185] = []; let __cu = unconstrained; let __hit = record.function_queries[185].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[185].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[185].bump_multiplicity(__i); } let __ret: [G; OUT_185] = unsafe { *(record.function_queries[185].output_at(__i).as_ptr() as *const [G; OUT_185]) }; __ret }, _ => aiur_fn_185(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_187] = [__v_7, __v_8]; - record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_186] = [__v_7, __v_8]; + record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_182] = { let __args: [G; IN_182] = []; let __cu = unconstrained; let __hit = record.function_queries[182].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[182].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[182].bump_multiplicity(__i); } let __ret: [G; OUT_182] = unsafe { *(record.function_queries[182].output_at(__i).as_ptr() as *const [G; OUT_182]) }; __ret }, _ => aiur_fn_182(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_181] = { let __args: [G; IN_181] = []; let __cu = unconstrained; let __hit = record.function_queries[181].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[181].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[181].bump_multiplicity(__i); } let __ret: [G; OUT_181] = unsafe { *(record.function_queries[181].output_at(__i).as_ptr() as *const [G; OUT_181]) }; __ret }, _ => aiur_fn_181(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_188] = { let __args: [G; IN_188] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[188].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[188].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[188].bump_multiplicity(__i); } let __ret: [G; OUT_188] = unsafe { *(record.function_queries[188].output_at(__i).as_ptr() as *const [G; OUT_188]) }; __ret }, _ => aiur_fn_188(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_187] = { let __args: [G; IN_187] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[187].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[187].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[187].bump_multiplicity(__i); } let __ret: [G; OUT_187] = unsafe { *(record.function_queries[187].output_at(__i).as_ptr() as *const [G; OUT_187]) }; __ret }, _ => aiur_fn_187(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_187] = [__v_9, __v_10]; - record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_186] = [__v_9, __v_10]; + record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_180] = { let __args: [G; IN_180] = []; let __cu = unconstrained; let __hit = record.function_queries[180].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[180].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[180].bump_multiplicity(__i); } let __ret: [G; OUT_180] = unsafe { *(record.function_queries[180].output_at(__i).as_ptr() as *const [G; OUT_180]) }; __ret }, _ => aiur_fn_180(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_179] = { let __args: [G; IN_179] = []; let __cu = unconstrained; let __hit = record.function_queries[179].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[179].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[179].bump_multiplicity(__i); } let __ret: [G; OUT_179] = unsafe { *(record.function_queries[179].output_at(__i).as_ptr() as *const [G; OUT_179]) }; __ret }, _ => aiur_fn_179(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_181] = { let __args: [G; IN_181] = []; let __cu = unconstrained; let __hit = record.function_queries[181].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[181].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[181].bump_multiplicity(__i); } let __ret: [G; OUT_181] = unsafe { *(record.function_queries[181].output_at(__i).as_ptr() as *const [G; OUT_181]) }; __ret }, _ => aiur_fn_181(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_180] = { let __args: [G; IN_180] = []; let __cu = unconstrained; let __hit = record.function_queries[180].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[180].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[180].bump_multiplicity(__i); } let __ret: [G; OUT_180] = unsafe { *(record.function_queries[180].output_at(__i).as_ptr() as *const [G; OUT_180]) }; __ret }, _ => aiur_fn_180(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; @@ -18789,12 +18750,12 @@ fn aiur_fn_187( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_187] = [__v_14, __v_18]; - record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_186] = [__v_14, __v_18]; + record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(1); let __v_16: G = { let __a_val = __v_14.as_canonical_u64(); let __b_val = __v_15.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -18805,31 +18766,31 @@ fn aiur_fn_187( let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_18, __v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_187] = [__v_17, __v_21]; - record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_186] = [__v_17, __v_21]; + record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_17: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_18, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_18, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_189] = { let __args: [G; IN_189] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[189].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[189].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[189].bump_multiplicity(__i); } let __ret: [G; OUT_189] = unsafe { *(record.function_queries[189].output_at(__i).as_ptr() as *const [G; OUT_189]) }; __ret }, _ => aiur_fn_189(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_188] = { let __args: [G; IN_188] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[188].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[188].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[188].bump_multiplicity(__i); } let __ret: [G; OUT_188] = unsafe { *(record.function_queries[188].output_at(__i).as_ptr() as *const [G; OUT_188]) }; __ret }, _ => aiur_fn_188(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = __r_arr[1]; - let __ret: [G; OUT_187] = [__v_20, __v_21]; - record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_186] = [__v_20, __v_21]; + record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_190] = { let __args: [G; IN_190] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[190].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[190].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[190].bump_multiplicity(__i); } let __ret: [G; OUT_190] = unsafe { *(record.function_queries[190].output_at(__i).as_ptr() as *const [G; OUT_190]) }; __ret }, _ => aiur_fn_190(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_189] = { let __args: [G; IN_189] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[189].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[189].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[189].bump_multiplicity(__i); } let __ret: [G; OUT_189] = unsafe { *(record.function_queries[189].output_at(__i).as_ptr() as *const [G; OUT_189]) }; __ret }, _ => aiur_fn_189(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = __r_arr[1]; - let __ret: [G; OUT_187] = [__v_20, __v_21]; - record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_186] = [__v_20, __v_21]; + record.function_queries[186].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -18846,18 +18807,18 @@ fn aiur_fn_187( }) } -const INPUT_SIZE_188: usize = 1; -const IN_188: usize = 1; -const OUT_188: usize = 2; -fn aiur_fn_188( - inp: [G; IN_188], +const INPUT_SIZE_187: usize = 1; +const IN_187: usize = 1; +const OUT_187: usize = 2; +fn aiur_fn_187( + inp: [G; IN_187], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_188], ExecError> { +) -> Result<[G; OUT_187], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = G::from_u64(3); let __v_3: G = { let __a_val = __v_1.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -18868,13 +18829,13 @@ fn aiur_fn_188( let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_188] = [__v_4, __v_8]; - record.function_queries[188].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_187] = [__v_4, __v_8]; + record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(2); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; @@ -18886,17 +18847,17 @@ fn aiur_fn_188( let __v_11: G = __loaded[3]; match __v_8.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_183] = { let __args: [G; IN_183] = []; let __cu = unconstrained; let __hit = record.function_queries[183].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[183].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[183].bump_multiplicity(__i); } let __ret: [G; OUT_183] = unsafe { *(record.function_queries[183].output_at(__i).as_ptr() as *const [G; OUT_183]) }; __ret }, _ => aiur_fn_183(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_182] = { let __args: [G; IN_182] = []; let __cu = unconstrained; let __hit = record.function_queries[182].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[182].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[182].bump_multiplicity(__i); } let __ret: [G; OUT_182] = unsafe { *(record.function_queries[182].output_at(__i).as_ptr() as *const [G; OUT_182]) }; __ret }, _ => aiur_fn_182(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_9, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 1u64 => { let __v_14: G = G::from_u64(1); - let __r_arr: [G; OUT_185] = { let __args: [G; IN_185] = []; let __cu = unconstrained; let __hit = record.function_queries[185].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[185].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[185].bump_multiplicity(__i); } let __ret: [G; OUT_185] = unsafe { *(record.function_queries[185].output_at(__i).as_ptr() as *const [G; OUT_185]) }; __ret }, _ => aiur_fn_185(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_184] = { let __args: [G; IN_184] = []; let __cu = unconstrained; let __hit = record.function_queries[184].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[184].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[184].bump_multiplicity(__i); } let __ret: [G; OUT_184] = unsafe { *(record.function_queries[184].output_at(__i).as_ptr() as *const [G; OUT_184]) }; __ret }, _ => aiur_fn_184(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_188] = [__v_14, __v_15]; - record.function_queries[188].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_187] = [__v_14, __v_15]; + record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -18905,8 +18866,8 @@ fn aiur_fn_188( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_188] = [__v_14, __v_18]; - record.function_queries[188].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_187] = [__v_14, __v_18]; + record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -18917,8 +18878,8 @@ fn aiur_fn_188( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_188] = [__v_12, __v_16]; - record.function_queries[188].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_187] = [__v_12, __v_16]; + record.function_queries[187].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -18927,15 +18888,15 @@ fn aiur_fn_188( }) } -const INPUT_SIZE_189: usize = 1; -const IN_189: usize = 1; -const OUT_189: usize = 2; -fn aiur_fn_189( - inp: [G; IN_189], +const INPUT_SIZE_188: usize = 1; +const IN_188: usize = 1; +const OUT_188: usize = 2; +fn aiur_fn_188( + inp: [G; IN_188], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_189], ExecError> { +) -> Result<[G; OUT_188], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -18945,11 +18906,11 @@ fn aiur_fn_189( let __v_4: G = __loaded[3]; match __v_1.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_176] = { let __args: [G; IN_176] = []; let __cu = unconstrained; let __hit = record.function_queries[176].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[176].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[176].bump_multiplicity(__i); } let __ret: [G; OUT_176] = unsafe { *(record.function_queries[176].output_at(__i).as_ptr() as *const [G; OUT_176]) }; __ret }, _ => aiur_fn_176(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_175] = { let __args: [G; IN_175] = []; let __cu = unconstrained; let __hit = record.function_queries[175].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[175].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[175].bump_multiplicity(__i); } let __ret: [G; OUT_175] = unsafe { *(record.function_queries[175].output_at(__i).as_ptr() as *const [G; OUT_175]) }; __ret }, _ => aiur_fn_175(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_177] = { let __args: [G; IN_177] = []; let __cu = unconstrained; let __hit = record.function_queries[177].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[177].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[177].bump_multiplicity(__i); } let __ret: [G; OUT_177] = unsafe { *(record.function_queries[177].output_at(__i).as_ptr() as *const [G; OUT_177]) }; __ret }, _ => aiur_fn_177(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_176] = { let __args: [G; IN_176] = []; let __cu = unconstrained; let __hit = record.function_queries[176].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[176].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[176].bump_multiplicity(__i); } let __ret: [G; OUT_176] = unsafe { *(record.function_queries[176].output_at(__i).as_ptr() as *const [G; OUT_176]) }; __ret }, _ => aiur_fn_176(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; @@ -18961,13 +18922,64 @@ fn aiur_fn_189( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_189] = [__v_10, __v_14]; - record.function_queries[189].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_188] = [__v_10, __v_14]; + record.function_queries[188].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_189] = [__v_10, __v_0]; + let __ret: [G; OUT_188] = [__v_10, __v_0]; + record.function_queries[188].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + } + }, + _ => { + let __v_5: G = G::from_u64(0); + let __v_6: G = G::from_u64(0); + let __v_7: G = G::from_u64(0); + let __v_8: G = G::from_u64(0); + let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; + let __ret: [G; OUT_188] = [__v_5, __v_9]; + record.function_queries[188].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + } + }) +} + +const INPUT_SIZE_189: usize = 1; +const IN_189: usize = 1; +const OUT_189: usize = 2; +fn aiur_fn_189( + inp: [G; IN_189], + record: &mut QueryRecord, + io_buffer: &mut IOBuffer, + unconstrained: bool, +) -> Result<[G; OUT_189], ExecError> { + stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { + let __v_0: G = inp[0]; + let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; + let __v_1: G = __loaded[0]; + let __v_2: G = __loaded[1]; + let __v_3: G = __loaded[2]; + let __v_4: G = __loaded[3]; + match __v_1.as_canonical_u64() { + 7u64 => { + match __v_2.as_canonical_u64() { + 0u64 => { + let __v_5: G = G::from_u64(1); + let __ret: [G; OUT_189] = [__v_5, __v_0]; + record.function_queries[189].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + _ => { + let __v_5: G = G::from_u64(0); + let __v_6: G = G::from_u64(0); + let __v_7: G = G::from_u64(0); + let __v_8: G = G::from_u64(0); + let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; + let __ret: [G; OUT_189] = [__v_5, __v_9]; record.function_queries[189].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, @@ -18987,66 +18999,15 @@ fn aiur_fn_189( }) } -const INPUT_SIZE_190: usize = 1; -const IN_190: usize = 1; -const OUT_190: usize = 2; +const INPUT_SIZE_190: usize = 0; +const IN_190: usize = 0; +const OUT_190: usize = 1; fn aiur_fn_190( inp: [G; IN_190], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, ) -> Result<[G; OUT_190], ExecError> { - stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = inp[0]; - let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; - let __v_1: G = __loaded[0]; - let __v_2: G = __loaded[1]; - let __v_3: G = __loaded[2]; - let __v_4: G = __loaded[3]; - match __v_1.as_canonical_u64() { - 7u64 => { - match __v_2.as_canonical_u64() { - 0u64 => { - let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_190] = [__v_5, __v_0]; - record.function_queries[190].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - _ => { - let __v_5: G = G::from_u64(0); - let __v_6: G = G::from_u64(0); - let __v_7: G = G::from_u64(0); - let __v_8: G = G::from_u64(0); - let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_190] = [__v_5, __v_9]; - record.function_queries[190].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - } - }, - _ => { - let __v_5: G = G::from_u64(0); - let __v_6: G = G::from_u64(0); - let __v_7: G = G::from_u64(0); - let __v_8: G = G::from_u64(0); - let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_190] = [__v_5, __v_9]; - record.function_queries[190].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - } - }) -} - -const INPUT_SIZE_191: usize = 0; -const IN_191: usize = 0; -const OUT_191: usize = 1; -fn aiur_fn_191( - inp: [G; IN_191], - record: &mut QueryRecord, - io_buffer: &mut IOBuffer, - unconstrained: bool, -) -> Result<[G; OUT_191], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(172); let __v_1: G = G::from_u64(217); @@ -19081,21 +19042,21 @@ fn aiur_fn_191( let __v_30: G = G::from_u64(103); let __v_31: G = G::from_u64(141); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_191] = [__v_32]; - record.function_queries[191].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_190] = [__v_32]; + record.function_queries[190].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_192: usize = 0; -const IN_192: usize = 0; -const OUT_192: usize = 1; -fn aiur_fn_192( - inp: [G; IN_192], +const INPUT_SIZE_191: usize = 0; +const IN_191: usize = 0; +const OUT_191: usize = 1; +fn aiur_fn_191( + inp: [G; IN_191], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_192], ExecError> { +) -> Result<[G; OUT_191], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(87); let __v_1: G = G::from_u64(33); @@ -19130,21 +19091,21 @@ fn aiur_fn_192( let __v_30: G = G::from_u64(219); let __v_31: G = G::from_u64(138); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_192] = [__v_32]; - record.function_queries[192].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_191] = [__v_32]; + record.function_queries[191].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_193: usize = 0; -const IN_193: usize = 0; -const OUT_193: usize = 1; -fn aiur_fn_193( - inp: [G; IN_193], +const INPUT_SIZE_192: usize = 0; +const IN_192: usize = 0; +const OUT_192: usize = 1; +fn aiur_fn_192( + inp: [G; IN_192], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_193], ExecError> { +) -> Result<[G; OUT_192], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(199); let __v_1: G = G::from_u64(25); @@ -19179,21 +19140,21 @@ fn aiur_fn_193( let __v_30: G = G::from_u64(176); let __v_31: G = G::from_u64(74); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_193] = [__v_32]; - record.function_queries[193].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_192] = [__v_32]; + record.function_queries[192].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_194: usize = 0; -const IN_194: usize = 0; -const OUT_194: usize = 1; -fn aiur_fn_194( - inp: [G; IN_194], +const INPUT_SIZE_193: usize = 0; +const IN_193: usize = 0; +const OUT_193: usize = 1; +fn aiur_fn_193( + inp: [G; IN_193], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_194], ExecError> { +) -> Result<[G; OUT_193], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(141); let __v_1: G = G::from_u64(87); @@ -19228,21 +19189,21 @@ fn aiur_fn_194( let __v_30: G = G::from_u64(30); let __v_31: G = G::from_u64(182); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_194] = [__v_32]; - record.function_queries[194].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_193] = [__v_32]; + record.function_queries[193].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_195: usize = 0; -const IN_195: usize = 0; -const OUT_195: usize = 1; -fn aiur_fn_195( - inp: [G; IN_195], +const INPUT_SIZE_194: usize = 0; +const IN_194: usize = 0; +const OUT_194: usize = 1; +fn aiur_fn_194( + inp: [G; IN_194], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_195], ExecError> { +) -> Result<[G; OUT_194], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(209); let __v_1: G = G::from_u64(16); @@ -19277,21 +19238,21 @@ fn aiur_fn_195( let __v_30: G = G::from_u64(126); let __v_31: G = G::from_u64(68); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_195] = [__v_32]; - record.function_queries[195].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_194] = [__v_32]; + record.function_queries[194].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_196: usize = 0; -const IN_196: usize = 0; -const OUT_196: usize = 1; -fn aiur_fn_196( - inp: [G; IN_196], +const INPUT_SIZE_195: usize = 0; +const IN_195: usize = 0; +const OUT_195: usize = 1; +fn aiur_fn_195( + inp: [G; IN_195], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_196], ExecError> { +) -> Result<[G; OUT_195], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(198); let __v_1: G = G::from_u64(157); @@ -19326,62 +19287,62 @@ fn aiur_fn_196( let __v_30: G = G::from_u64(111); let __v_31: G = G::from_u64(4); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_196] = [__v_32]; - record.function_queries[196].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_195] = [__v_32]; + record.function_queries[195].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_197: usize = 1; -const IN_197: usize = 1; -const OUT_197: usize = 1; -fn aiur_fn_197( - inp: [G; IN_197], +const INPUT_SIZE_196: usize = 1; +const IN_196: usize = 1; +const OUT_196: usize = 1; +fn aiur_fn_196( + inp: [G; IN_196], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_197], ExecError> { +) -> Result<[G; OUT_196], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_191] = { let __args: [G; IN_191] = []; let __cu = unconstrained; let __hit = record.function_queries[191].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[191].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[191].bump_multiplicity(__i); } let __ret: [G; OUT_191] = unsafe { *(record.function_queries[191].output_at(__i).as_ptr() as *const [G; OUT_191]) }; __ret }, _ => aiur_fn_191(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_190] = { let __args: [G; IN_190] = []; let __cu = unconstrained; let __hit = record.function_queries[190].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[190].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[190].bump_multiplicity(__i); } let __ret: [G; OUT_190] = unsafe { *(record.function_queries[190].output_at(__i).as_ptr() as *const [G; OUT_190]) }; __ret }, _ => aiur_fn_190(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_197] = [__v_3]; - record.function_queries[197].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_196] = [__v_3]; + record.function_queries[196].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_194] = { let __args: [G; IN_194] = []; let __cu = unconstrained; let __hit = record.function_queries[194].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[194].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[194].bump_multiplicity(__i); } let __ret: [G; OUT_194] = unsafe { *(record.function_queries[194].output_at(__i).as_ptr() as *const [G; OUT_194]) }; __ret }, _ => aiur_fn_194(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_193] = { let __args: [G; IN_193] = []; let __cu = unconstrained; let __hit = record.function_queries[193].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[193].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[193].bump_multiplicity(__i); } let __ret: [G; OUT_193] = unsafe { *(record.function_queries[193].output_at(__i).as_ptr() as *const [G; OUT_193]) }; __ret }, _ => aiur_fn_193(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_197] = [__v_5]; - record.function_queries[197].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_196] = [__v_5]; + record.function_queries[196].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_195] = { let __args: [G; IN_195] = []; let __cu = unconstrained; let __hit = record.function_queries[195].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[195].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[195].bump_multiplicity(__i); } let __ret: [G; OUT_195] = unsafe { *(record.function_queries[195].output_at(__i).as_ptr() as *const [G; OUT_195]) }; __ret }, _ => aiur_fn_195(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_194] = { let __args: [G; IN_194] = []; let __cu = unconstrained; let __hit = record.function_queries[194].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[194].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[194].bump_multiplicity(__i); } let __ret: [G; OUT_194] = unsafe { *(record.function_queries[194].output_at(__i).as_ptr() as *const [G; OUT_194]) }; __ret }, _ => aiur_fn_194(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_197] = [__v_7]; - record.function_queries[197].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_196] = [__v_7]; + record.function_queries[196].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_197] = [__v_7]; - record.function_queries[197].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_196] = [__v_7]; + record.function_queries[196].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -19392,61 +19353,61 @@ fn aiur_fn_197( }) } -const INPUT_SIZE_198: usize = 1; -const IN_198: usize = 1; -const OUT_198: usize = 1; -fn aiur_fn_198( - inp: [G; IN_198], +const INPUT_SIZE_197: usize = 1; +const IN_197: usize = 1; +const OUT_197: usize = 1; +fn aiur_fn_197( + inp: [G; IN_197], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_198], ExecError> { +) -> Result<[G; OUT_197], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; match __v_0.as_canonical_u64() { 0u64 => { let __v_1: G = G::from_u64(2); - let __r_arr: [G; OUT_177] = { let __args: [G; IN_177] = []; let __cu = unconstrained; let __hit = record.function_queries[177].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[177].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[177].bump_multiplicity(__i); } let __ret: [G; OUT_177] = unsafe { *(record.function_queries[177].output_at(__i).as_ptr() as *const [G; OUT_177]) }; __ret }, _ => aiur_fn_177(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_176] = { let __args: [G; IN_176] = []; let __cu = unconstrained; let __hit = record.function_queries[176].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[176].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[176].bump_multiplicity(__i); } let __ret: [G; OUT_176] = unsafe { *(record.function_queries[176].output_at(__i).as_ptr() as *const [G; OUT_176]) }; __ret }, _ => aiur_fn_176(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 4] = [__v_1, __v_2, __v_5, __v_6]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_198] = [__v_7]; - record.function_queries[198].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_197] = [__v_7]; + record.function_queries[197].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_1: G = G::from_u64(2); - let __r_arr: [G; OUT_176] = { let __args: [G; IN_176] = []; let __cu = unconstrained; let __hit = record.function_queries[176].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[176].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[176].bump_multiplicity(__i); } let __ret: [G; OUT_176] = unsafe { *(record.function_queries[176].output_at(__i).as_ptr() as *const [G; OUT_176]) }; __ret }, _ => aiur_fn_176(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_175] = { let __args: [G; IN_175] = []; let __cu = unconstrained; let __hit = record.function_queries[175].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[175].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[175].bump_multiplicity(__i); } let __ret: [G; OUT_175] = unsafe { *(record.function_queries[175].output_at(__i).as_ptr() as *const [G; OUT_175]) }; __ret }, _ => aiur_fn_175(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 4] = [__v_1, __v_2, __v_5, __v_6]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_198] = [__v_7]; - record.function_queries[198].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_197] = [__v_7]; + record.function_queries[197].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_199: usize = 2; -const IN_199: usize = 2; -const OUT_199: usize = 2; -fn aiur_fn_199( - inp: [G; IN_199], +const INPUT_SIZE_198: usize = 2; +const IN_198: usize = 2; +const OUT_198: usize = 2; +fn aiur_fn_198( + inp: [G; IN_198], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_199], ExecError> { +) -> Result<[G; OUT_198], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_202] = { let __args: [G; IN_202] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[202].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[202].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[202].bump_multiplicity(__i); } let __ret: [G; OUT_202] = unsafe { *(record.function_queries[202].output_at(__i).as_ptr() as *const [G; OUT_202]) }; __ret }, _ => aiur_fn_202(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_201] = { let __args: [G; IN_201] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[201].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[201].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[201].bump_multiplicity(__i); } let __ret: [G; OUT_201] = unsafe { *(record.function_queries[201].output_at(__i).as_ptr() as *const [G; OUT_201]) }; __ret }, _ => aiur_fn_201(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -19456,12 +19417,12 @@ fn aiur_fn_199( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 10] = [__v_6, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_199] = [__v_5, __v_8]; - record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_198] = [__v_5, __v_8]; + record.function_queries[198].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; match __v_5.as_canonical_u64() { @@ -19470,12 +19431,12 @@ fn aiur_fn_199( let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 10] = [__v_8, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_199] = [__v_7, __v_10]; - record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_198] = [__v_7, __v_10]; + record.function_queries[198].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; match __v_7.as_canonical_u64() { @@ -19484,8 +19445,8 @@ fn aiur_fn_199( let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 10] = [__v_10, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_199] = [__v_9, __v_12]; - record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_198] = [__v_9, __v_12]; + record.function_queries[198].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -19502,15 +19463,15 @@ fn aiur_fn_199( let __v_19: G = G::from_u64(1); let __v_20: G = { let __values: [G; 10] = [__v_18, __v_19, __v_19, __v_19, __v_19, __v_19, __v_19, __v_19, __v_19, __v_19]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_21: G = { let __values: [G; 10] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_20]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_138] = { let __args: [G; IN_138] = [__v_21, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[138].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[138].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[138].bump_multiplicity(__i); } let __ret: [G; OUT_138] = unsafe { *(record.function_queries[138].output_at(__i).as_ptr() as *const [G; OUT_138]) }; __ret }, _ => aiur_fn_138(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_21, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = G::from_u64(1); - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_6, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_6, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __ret: [G; OUT_199] = [__v_23, __v_25]; - record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_198] = [__v_23, __v_25]; + record.function_queries[198].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -19530,18 +19491,18 @@ fn aiur_fn_199( }) } -const INPUT_SIZE_200: usize = 1; -const IN_200: usize = 1; -const OUT_200: usize = 2; -fn aiur_fn_200( - inp: [G; IN_200], +const INPUT_SIZE_199: usize = 1; +const IN_199: usize = 1; +const OUT_199: usize = 2; +fn aiur_fn_199( + inp: [G; IN_199], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_200], ExecError> { +) -> Result<[G; OUT_199], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = G::from_u64(3); let __v_3: G = { let __a_val = __v_1.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -19552,21 +19513,21 @@ fn aiur_fn_200( let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_200] = [__v_4, __v_8]; - record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_199] = [__v_4, __v_8]; + record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(2); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_199] = { let __args: [G; IN_199] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[199].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[199].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[199].bump_multiplicity(__i); } let __ret: [G; OUT_199] = unsafe { *(record.function_queries[199].output_at(__i).as_ptr() as *const [G; OUT_199]) }; __ret }, _ => aiur_fn_199(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_198] = { let __args: [G; IN_198] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[198].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[198].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[198].bump_multiplicity(__i); } let __ret: [G; OUT_198] = unsafe { *(record.function_queries[198].output_at(__i).as_ptr() as *const [G; OUT_198]) }; __ret }, _ => aiur_fn_198(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; match __v_10.as_canonical_u64() { @@ -19576,12 +19537,12 @@ fn aiur_fn_200( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_200] = [__v_12, __v_16]; - record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_199] = [__v_12, __v_16]; + record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_199] = { let __args: [G; IN_199] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[199].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[199].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[199].bump_multiplicity(__i); } let __ret: [G; OUT_199] = unsafe { *(record.function_queries[199].output_at(__i).as_ptr() as *const [G; OUT_199]) }; __ret }, _ => aiur_fn_199(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_198] = { let __args: [G; IN_198] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[198].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[198].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[198].bump_multiplicity(__i); } let __ret: [G; OUT_198] = unsafe { *(record.function_queries[198].output_at(__i).as_ptr() as *const [G; OUT_198]) }; __ret }, _ => aiur_fn_198(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; match __v_12.as_canonical_u64() { @@ -19591,8 +19552,8 @@ fn aiur_fn_200( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_200] = [__v_14, __v_18]; - record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_199] = [__v_14, __v_18]; + record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -19601,10 +19562,10 @@ fn aiur_fn_200( let __v_15: G = __r_arr[0]; let __v_16: G = (__v_14 - __v_15); let __v_17: G = G::from_u64(1); - let __r_arr: [G; OUT_198] = { let __args: [G; IN_198] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[198].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[198].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[198].bump_multiplicity(__i); } let __ret: [G; OUT_198] = unsafe { *(record.function_queries[198].output_at(__i).as_ptr() as *const [G; OUT_198]) }; __ret }, _ => aiur_fn_198(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_197] = { let __args: [G; IN_197] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[197].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[197].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[197].bump_multiplicity(__i); } let __ret: [G; OUT_197] = unsafe { *(record.function_queries[197].output_at(__i).as_ptr() as *const [G; OUT_197]) }; __ret }, _ => aiur_fn_197(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_200] = [__v_17, __v_18]; - record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_199] = [__v_17, __v_18]; + record.function_queries[199].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -19621,18 +19582,18 @@ fn aiur_fn_200( }) } -const INPUT_SIZE_201: usize = 1; -const IN_201: usize = 1; -const OUT_201: usize = 2; -fn aiur_fn_201( - inp: [G; IN_201], +const INPUT_SIZE_200: usize = 1; +const IN_200: usize = 1; +const OUT_200: usize = 2; +fn aiur_fn_200( + inp: [G; IN_200], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_201], ExecError> { +) -> Result<[G; OUT_200], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = G::from_u64(2); let __v_3: G = { let __a_val = __v_1.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -19643,13 +19604,13 @@ fn aiur_fn_201( let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_201] = [__v_4, __v_8]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_4, __v_8]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; @@ -19661,7 +19622,7 @@ fn aiur_fn_201( let __v_11: G = __loaded[3]; match __v_8.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_196] = { let __args: [G; IN_196] = []; let __cu = unconstrained; let __hit = record.function_queries[196].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[196].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[196].bump_multiplicity(__i); } let __ret: [G; OUT_196] = unsafe { *(record.function_queries[196].output_at(__i).as_ptr() as *const [G; OUT_196]) }; __ret }, _ => aiur_fn_196(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_195] = { let __args: [G; IN_195] = []; let __cu = unconstrained; let __hit = record.function_queries[195].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[195].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[195].bump_multiplicity(__i); } let __ret: [G; OUT_195] = unsafe { *(record.function_queries[195].output_at(__i).as_ptr() as *const [G; OUT_195]) }; __ret }, _ => aiur_fn_195(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_9, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; @@ -19672,12 +19633,12 @@ fn aiur_fn_201( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_201] = [__v_14, __v_18]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_14, __v_18]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(4); let __v_16: G = { let __a_val = __v_14.as_canonical_u64(); let __b_val = __v_15.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -19688,13 +19649,13 @@ fn aiur_fn_201( let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_18, __v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_201] = [__v_17, __v_21]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_17, __v_21]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_17: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_7, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_7, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; @@ -19706,7 +19667,7 @@ fn aiur_fn_201( let __v_24: G = __loaded[3]; match __v_21.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_193] = { let __args: [G; IN_193] = []; let __cu = unconstrained; let __hit = record.function_queries[193].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[193].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[193].bump_multiplicity(__i); } let __ret: [G; OUT_193] = unsafe { *(record.function_queries[193].output_at(__i).as_ptr() as *const [G; OUT_193]) }; __ret }, _ => aiur_fn_193(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_192] = { let __args: [G; IN_192] = []; let __cu = unconstrained; let __hit = record.function_queries[192].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[192].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[192].bump_multiplicity(__i); } let __ret: [G; OUT_192] = unsafe { *(record.function_queries[192].output_at(__i).as_ptr() as *const [G; OUT_192]) }; __ret }, _ => aiur_fn_192(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_22, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; @@ -19717,12 +19678,12 @@ fn aiur_fn_201( let __v_29: G = G::from_u64(0); let __v_30: G = G::from_u64(0); let __v_31: G = { let __values: [G; 4] = [__v_28, __v_29, __v_30, __v_30]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_201] = [__v_27, __v_31]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_27, __v_31]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = G::from_u64(1); let __v_29: G = { let __a_val = __v_27.as_canonical_u64(); let __b_val = __v_28.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -19733,19 +19694,19 @@ fn aiur_fn_201( let __v_32: G = G::from_u64(0); let __v_33: G = G::from_u64(0); let __v_34: G = { let __values: [G; 4] = [__v_31, __v_32, __v_33, __v_33]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_201] = [__v_30, __v_34]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_30, __v_34]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_30: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_20, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_20, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = G::from_u64(2); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_7, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_7, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; let __v_34: G = G::from_u64(3); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_7, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_7, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = G::from_u64(0); let __v_37: G = G::from_u64(0); @@ -19756,11 +19717,11 @@ fn aiur_fn_201( let __v_42: G = { let __values: [G; 3] = [__v_38, __v_35, __v_41]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_43: G = { let __values: [G; 3] = [__v_37, __v_33, __v_42]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_44: G = { let __values: [G; 3] = [__v_36, __v_31, __v_43]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_200] = { let __args: [G; IN_200] = [__v_44]; let __cu = unconstrained; let __hit = record.function_queries[200].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[200].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[200].bump_multiplicity(__i); } let __ret: [G; OUT_200] = unsafe { *(record.function_queries[200].output_at(__i).as_ptr() as *const [G; OUT_200]) }; __ret }, _ => aiur_fn_200(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_199] = { let __args: [G; IN_199] = [__v_44]; let __cu = unconstrained; let __hit = record.function_queries[199].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[199].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[199].bump_multiplicity(__i); } let __ret: [G; OUT_199] = unsafe { *(record.function_queries[199].output_at(__i).as_ptr() as *const [G; OUT_199]) }; __ret }, _ => aiur_fn_199(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; let __v_46: G = __r_arr[1]; - let __ret: [G; OUT_201] = [__v_45, __v_46]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_45, __v_46]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -19773,8 +19734,8 @@ fn aiur_fn_201( let __v_27: G = G::from_u64(0); let __v_28: G = G::from_u64(0); let __v_29: G = { let __values: [G; 4] = [__v_26, __v_27, __v_28, __v_28]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_201] = [__v_25, __v_29]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_25, __v_29]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -19789,8 +19750,8 @@ fn aiur_fn_201( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_201] = [__v_12, __v_16]; - record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_200] = [__v_12, __v_16]; + record.function_queries[200].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -19799,15 +19760,15 @@ fn aiur_fn_201( }) } -const INPUT_SIZE_202: usize = 1; -const IN_202: usize = 1; -const OUT_202: usize = 3; -fn aiur_fn_202( - inp: [G; IN_202], +const INPUT_SIZE_201: usize = 1; +const IN_201: usize = 1; +const OUT_201: usize = 3; +fn aiur_fn_201( + inp: [G; IN_201], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_202], ExecError> { +) -> Result<[G; OUT_201], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; @@ -19820,13 +19781,13 @@ fn aiur_fn_202( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_192] = { let __args: [G; IN_192] = []; let __cu = unconstrained; let __hit = record.function_queries[192].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[192].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[192].bump_multiplicity(__i); } let __ret: [G; OUT_192] = unsafe { *(record.function_queries[192].output_at(__i).as_ptr() as *const [G; OUT_192]) }; __ret }, _ => aiur_fn_192(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_191] = { let __args: [G; IN_191] = []; let __cu = unconstrained; let __hit = record.function_queries[191].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[191].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[191].bump_multiplicity(__i); } let __ret: [G; OUT_191] = unsafe { *(record.function_queries[191].output_at(__i).as_ptr() as *const [G; OUT_191]) }; __ret }, _ => aiur_fn_191(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(2); let __v_11: G = (__v_9 - __v_10); @@ -19834,13 +19795,13 @@ fn aiur_fn_202( 0u64 => { let __v_12: G = G::from_u64(1); let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_202] = [__v_12, __v_14, __v_16]; - record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_201] = [__v_12, __v_14, __v_16]; + record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -19853,8 +19814,8 @@ fn aiur_fn_202( let __v_18: G = G::from_u64(0); let __v_19: G = G::from_u64(0); let __v_20: G = { let __values: [G; 4] = [__v_17, __v_18, __v_19, __v_19]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_202] = [__v_12, __v_16, __v_20]; - record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_201] = [__v_12, __v_16, __v_20]; + record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -19869,8 +19830,8 @@ fn aiur_fn_202( let __v_15: G = G::from_u64(0); let __v_16: G = G::from_u64(0); let __v_17: G = { let __values: [G; 4] = [__v_14, __v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_202] = [__v_9, __v_13, __v_17]; - record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_201] = [__v_9, __v_13, __v_17]; + record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -19885,34 +19846,34 @@ fn aiur_fn_202( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_202] = [__v_7, __v_11, __v_15]; - record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_201] = [__v_7, __v_11, __v_15]; + record.function_queries[201].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_203: usize = 3; -const IN_203: usize = 3; -const OUT_203: usize = 2; -fn aiur_fn_203( - inp: [G; IN_203], +const INPUT_SIZE_202: usize = 3; +const IN_202: usize = 3; +const OUT_202: usize = 2; +fn aiur_fn_202( + inp: [G; IN_202], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_203], ExecError> { +) -> Result<[G; OUT_202], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_191] = { let __args: [G; IN_191] = []; let __cu = unconstrained; let __hit = record.function_queries[191].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[191].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[191].bump_multiplicity(__i); } let __ret: [G; OUT_191] = unsafe { *(record.function_queries[191].output_at(__i).as_ptr() as *const [G; OUT_191]) }; __ret }, _ => aiur_fn_191(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_190] = { let __args: [G; IN_190] = []; let __cu = unconstrained; let __hit = record.function_queries[190].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[190].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[190].bump_multiplicity(__i); } let __ret: [G; OUT_190] = unsafe { *(record.function_queries[190].output_at(__i).as_ptr() as *const [G; OUT_190]) }; __ret }, _ => aiur_fn_190(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(2); let __v_7: G = { let __a_val = __v_5.as_canonical_u64(); let __b_val = __v_6.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -19923,20 +19884,20 @@ fn aiur_fn_203( let __v_10: G = G::from_u64(0); let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_9, __v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_203] = [__v_8, __v_12]; - record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_202] = [__v_8, __v_12]; + record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_389] = { let __args: [G; IN_389] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[389].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[389].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[389].bump_multiplicity(__i); } let __ret: [G; OUT_389] = unsafe { *(record.function_queries[389].output_at(__i).as_ptr() as *const [G; OUT_389]) }; __ret }, _ => aiur_fn_389(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_388] = { let __args: [G; IN_388] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[388].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[388].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[388].bump_multiplicity(__i); } let __ret: [G; OUT_388] = unsafe { *(record.function_queries[388].output_at(__i).as_ptr() as *const [G; OUT_388]) }; __ret }, _ => aiur_fn_388(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_199] = { let __args: [G; IN_199] = [__v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[199].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[199].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[199].bump_multiplicity(__i); } let __ret: [G; OUT_199] = unsafe { *(record.function_queries[199].output_at(__i).as_ptr() as *const [G; OUT_199]) }; __ret }, _ => aiur_fn_199(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_198] = { let __args: [G; IN_198] = [__v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[198].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[198].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[198].bump_multiplicity(__i); } let __ret: [G; OUT_198] = unsafe { *(record.function_queries[198].output_at(__i).as_ptr() as *const [G; OUT_198]) }; __ret }, _ => aiur_fn_198(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; match __v_13.as_canonical_u64() { @@ -19946,16 +19907,16 @@ fn aiur_fn_203( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_16, __v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_203] = [__v_15, __v_19]; - record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_202] = [__v_15, __v_19]; + record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_15: G = G::from_u64(1); - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_203] = [__v_15, __v_16]; - record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_202] = [__v_15, __v_16]; + record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -19966,33 +19927,33 @@ fn aiur_fn_203( } }, _ => { - let __r_arr: [G; OUT_194] = { let __args: [G; IN_194] = []; let __cu = unconstrained; let __hit = record.function_queries[194].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[194].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[194].bump_multiplicity(__i); } let __ret: [G; OUT_194] = unsafe { *(record.function_queries[194].output_at(__i).as_ptr() as *const [G; OUT_194]) }; __ret }, _ => aiur_fn_194(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_193] = { let __args: [G; IN_193] = []; let __cu = unconstrained; let __hit = record.function_queries[193].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[193].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[193].bump_multiplicity(__i); } let __ret: [G; OUT_193] = unsafe { *(record.function_queries[193].output_at(__i).as_ptr() as *const [G; OUT_193]) }; __ret }, _ => aiur_fn_193(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_204] = { let __args: [G; IN_204] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[204].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[204].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[204].bump_multiplicity(__i); } let __ret: [G; OUT_204] = unsafe { *(record.function_queries[204].output_at(__i).as_ptr() as *const [G; OUT_204]) }; __ret }, _ => aiur_fn_204(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_203] = { let __args: [G; IN_203] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[203].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[203].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[203].bump_multiplicity(__i); } let __ret: [G; OUT_203] = unsafe { *(record.function_queries[203].output_at(__i).as_ptr() as *const [G; OUT_203]) }; __ret }, _ => aiur_fn_203(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_200] = { let __args: [G; IN_200] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[200].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[200].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[200].bump_multiplicity(__i); } let __ret: [G; OUT_200] = unsafe { *(record.function_queries[200].output_at(__i).as_ptr() as *const [G; OUT_200]) }; __ret }, _ => aiur_fn_200(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_199] = { let __args: [G; IN_199] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[199].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[199].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[199].bump_multiplicity(__i); } let __ret: [G; OUT_199] = unsafe { *(record.function_queries[199].output_at(__i).as_ptr() as *const [G; OUT_199]) }; __ret }, _ => aiur_fn_199(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_203] = [__v_8, __v_9]; - record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_202] = [__v_8, __v_9]; + record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_195] = { let __args: [G; IN_195] = []; let __cu = unconstrained; let __hit = record.function_queries[195].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[195].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[195].bump_multiplicity(__i); } let __ret: [G; OUT_195] = unsafe { *(record.function_queries[195].output_at(__i).as_ptr() as *const [G; OUT_195]) }; __ret }, _ => aiur_fn_195(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_194] = { let __args: [G; IN_194] = []; let __cu = unconstrained; let __hit = record.function_queries[194].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[194].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[194].bump_multiplicity(__i); } let __ret: [G; OUT_194] = unsafe { *(record.function_queries[194].output_at(__i).as_ptr() as *const [G; OUT_194]) }; __ret }, _ => aiur_fn_194(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_201] = { let __args: [G; IN_201] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[201].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[201].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[201].bump_multiplicity(__i); } let __ret: [G; OUT_201] = unsafe { *(record.function_queries[201].output_at(__i).as_ptr() as *const [G; OUT_201]) }; __ret }, _ => aiur_fn_201(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_200] = { let __args: [G; IN_200] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[200].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[200].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[200].bump_multiplicity(__i); } let __ret: [G; OUT_200] = unsafe { *(record.function_queries[200].output_at(__i).as_ptr() as *const [G; OUT_200]) }; __ret }, _ => aiur_fn_200(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_203] = [__v_9, __v_10]; - record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_202] = [__v_9, __v_10]; + record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -20001,8 +19962,8 @@ fn aiur_fn_203( let __v_11: G = G::from_u64(0); let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_10, __v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_203] = [__v_9, __v_13]; - record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_202] = [__v_9, __v_13]; + record.function_queries[202].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -20013,19 +19974,19 @@ fn aiur_fn_203( }) } -const INPUT_SIZE_204: usize = 2; -const IN_204: usize = 2; -const OUT_204: usize = 1; -fn aiur_fn_204( - inp: [G; IN_204], +const INPUT_SIZE_203: usize = 2; +const IN_203: usize = 2; +const OUT_203: usize = 1; +fn aiur_fn_203( + inp: [G; IN_203], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_204], ExecError> { +) -> Result<[G; OUT_203], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_2.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_3: G = __loaded[0]; @@ -20033,8 +19994,8 @@ fn aiur_fn_204( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_204] = [__v_2]; - record.function_queries[204].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_203] = [__v_2]; + record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -20044,8 +20005,8 @@ fn aiur_fn_204( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_204] = [__v_2]; - record.function_queries[204].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_203] = [__v_2]; + record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -20055,14 +20016,14 @@ fn aiur_fn_204( let __v_11: G = __loaded[2]; match __v_9.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_204] = [__v_2]; - record.function_queries[204].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_203] = [__v_2]; + record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_205] = { let __args: [G; IN_205] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[205].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[205].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[205].bump_multiplicity(__i); } let __ret: [G; OUT_205] = unsafe { *(record.function_queries[205].output_at(__i).as_ptr() as *const [G; OUT_205]) }; __ret }, _ => aiur_fn_205(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_204] = { let __args: [G; IN_204] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[204].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[204].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[204].bump_multiplicity(__i); } let __ret: [G; OUT_204] = unsafe { *(record.function_queries[204].output_at(__i).as_ptr() as *const [G; OUT_204]) }; __ret }, _ => aiur_fn_204(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_205] = { let __args: [G; IN_205] = [__v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[205].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[205].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[205].bump_multiplicity(__i); } let __ret: [G; OUT_205] = unsafe { *(record.function_queries[205].output_at(__i).as_ptr() as *const [G; OUT_205]) }; __ret }, _ => aiur_fn_205(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_204] = { let __args: [G; IN_204] = [__v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[204].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[204].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[204].bump_multiplicity(__i); } let __ret: [G; OUT_204] = unsafe { *(record.function_queries[204].output_at(__i).as_ptr() as *const [G; OUT_204]) }; __ret }, _ => aiur_fn_204(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); @@ -20070,8 +20031,8 @@ fn aiur_fn_204( let __v_17: G = { let __values: [G; 3] = [__v_16, __v_13, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_18: G = { let __values: [G; 3] = [__v_15, __v_12, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_19: G = { let __values: [G; 3] = [__v_14, __v_4, __v_18]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_204] = [__v_19]; - record.function_queries[204].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_203] = [__v_19]; + record.function_queries[203].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -20091,40 +20052,40 @@ fn aiur_fn_204( }) } -const INPUT_SIZE_205: usize = 2; -const IN_205: usize = 2; -const OUT_205: usize = 1; -fn aiur_fn_205( - inp: [G; IN_205], +const INPUT_SIZE_204: usize = 2; +const IN_204: usize = 2; +const OUT_204: usize = 1; +fn aiur_fn_204( + inp: [G; IN_204], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_205], ExecError> { +) -> Result<[G; OUT_204], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_205] = [__v_5]; - record.function_queries[205].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_204] = [__v_5]; + record.function_queries[204].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_206: usize = 0; -const IN_206: usize = 0; -const OUT_206: usize = 1; -fn aiur_fn_206( - inp: [G; IN_206], +const INPUT_SIZE_205: usize = 0; +const IN_205: usize = 0; +const OUT_205: usize = 1; +fn aiur_fn_205( + inp: [G; IN_205], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_206], ExecError> { +) -> Result<[G; OUT_205], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(177); let __v_1: G = G::from_u64(246); @@ -20159,21 +20120,21 @@ fn aiur_fn_206( let __v_30: G = G::from_u64(17); let __v_31: G = G::from_u64(5); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_206] = [__v_32]; - record.function_queries[206].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_205] = [__v_32]; + record.function_queries[205].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_207: usize = 0; -const IN_207: usize = 0; -const OUT_207: usize = 1; -fn aiur_fn_207( - inp: [G; IN_207], +const INPUT_SIZE_206: usize = 0; +const IN_206: usize = 0; +const OUT_206: usize = 1; +fn aiur_fn_206( + inp: [G; IN_206], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_207], ExecError> { +) -> Result<[G; OUT_206], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(182); let __v_1: G = G::from_u64(236); @@ -20208,21 +20169,21 @@ fn aiur_fn_207( let __v_30: G = G::from_u64(113); let __v_31: G = G::from_u64(248); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_207] = [__v_32]; - record.function_queries[207].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_206] = [__v_32]; + record.function_queries[206].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_208: usize = 0; -const IN_208: usize = 0; -const OUT_208: usize = 1; -fn aiur_fn_208( - inp: [G; IN_208], +const INPUT_SIZE_207: usize = 0; +const IN_207: usize = 0; +const OUT_207: usize = 1; +fn aiur_fn_207( + inp: [G; IN_207], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_208], ExecError> { +) -> Result<[G; OUT_207], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(213); let __v_1: G = G::from_u64(77); @@ -20257,21 +20218,21 @@ fn aiur_fn_208( let __v_30: G = G::from_u64(68); let __v_31: G = G::from_u64(184); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_208] = [__v_32]; - record.function_queries[208].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_207] = [__v_32]; + record.function_queries[207].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_209: usize = 0; -const IN_209: usize = 0; -const OUT_209: usize = 1; -fn aiur_fn_209( - inp: [G; IN_209], +const INPUT_SIZE_208: usize = 0; +const IN_208: usize = 0; +const OUT_208: usize = 1; +fn aiur_fn_208( + inp: [G; IN_208], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_209], ExecError> { +) -> Result<[G; OUT_208], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(41); let __v_1: G = G::from_u64(86); @@ -20306,21 +20267,21 @@ fn aiur_fn_209( let __v_30: G = G::from_u64(107); let __v_31: G = G::from_u64(42); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_209] = [__v_32]; - record.function_queries[209].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_208] = [__v_32]; + record.function_queries[208].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_210: usize = 0; -const IN_210: usize = 0; -const OUT_210: usize = 1; -fn aiur_fn_210( - inp: [G; IN_210], +const INPUT_SIZE_209: usize = 0; +const IN_209: usize = 0; +const OUT_209: usize = 1; +fn aiur_fn_209( + inp: [G; IN_209], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_210], ExecError> { +) -> Result<[G; OUT_209], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(60); let __v_1: G = G::from_u64(1); @@ -20355,21 +20316,21 @@ fn aiur_fn_210( let __v_30: G = G::from_u64(44); let __v_31: G = G::from_u64(66); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_210] = [__v_32]; - record.function_queries[210].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_209] = [__v_32]; + record.function_queries[209].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_211: usize = 0; -const IN_211: usize = 0; -const OUT_211: usize = 1; -fn aiur_fn_211( - inp: [G; IN_211], +const INPUT_SIZE_210: usize = 0; +const IN_210: usize = 0; +const OUT_210: usize = 1; +fn aiur_fn_210( + inp: [G; IN_210], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_211], ExecError> { +) -> Result<[G; OUT_210], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(209); let __v_1: G = G::from_u64(224); @@ -20404,21 +20365,21 @@ fn aiur_fn_211( let __v_30: G = G::from_u64(136); let __v_31: G = G::from_u64(196); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_211] = [__v_32]; - record.function_queries[211].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_210] = [__v_32]; + record.function_queries[210].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_212: usize = 0; -const IN_212: usize = 0; -const OUT_212: usize = 1; -fn aiur_fn_212( - inp: [G; IN_212], +const INPUT_SIZE_211: usize = 0; +const IN_211: usize = 0; +const OUT_211: usize = 1; +fn aiur_fn_211( + inp: [G; IN_211], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_212], ExecError> { +) -> Result<[G; OUT_211], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(213); let __v_1: G = G::from_u64(84); @@ -20453,21 +20414,21 @@ fn aiur_fn_212( let __v_30: G = G::from_u64(199); let __v_31: G = G::from_u64(137); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_212] = [__v_32]; - record.function_queries[212].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_211] = [__v_32]; + record.function_queries[211].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_213: usize = 0; -const IN_213: usize = 0; -const OUT_213: usize = 1; -fn aiur_fn_213( - inp: [G; IN_213], +const INPUT_SIZE_212: usize = 0; +const IN_212: usize = 0; +const OUT_212: usize = 1; +fn aiur_fn_212( + inp: [G; IN_212], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_213], ExecError> { +) -> Result<[G; OUT_212], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(63); let __v_1: G = G::from_u64(146); @@ -20502,21 +20463,21 @@ fn aiur_fn_213( let __v_30: G = G::from_u64(11); let __v_31: G = G::from_u64(107); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_213] = [__v_32]; - record.function_queries[213].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_212] = [__v_32]; + record.function_queries[212].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_214: usize = 0; -const IN_214: usize = 0; -const OUT_214: usize = 1; -fn aiur_fn_214( - inp: [G; IN_214], +const INPUT_SIZE_213: usize = 0; +const IN_213: usize = 0; +const OUT_213: usize = 1; +fn aiur_fn_213( + inp: [G; IN_213], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_214], ExecError> { +) -> Result<[G; OUT_213], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(162); let __v_1: G = G::from_u64(163); @@ -20551,21 +20512,21 @@ fn aiur_fn_214( let __v_30: G = G::from_u64(223); let __v_31: G = G::from_u64(102); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_214] = [__v_32]; - record.function_queries[214].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_213] = [__v_32]; + record.function_queries[213].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_215: usize = 0; -const IN_215: usize = 0; -const OUT_215: usize = 1; -fn aiur_fn_215( - inp: [G; IN_215], +const INPUT_SIZE_214: usize = 0; +const IN_214: usize = 0; +const OUT_214: usize = 1; +fn aiur_fn_214( + inp: [G; IN_214], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_215], ExecError> { +) -> Result<[G; OUT_214], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(173); let __v_1: G = G::from_u64(112); @@ -20600,21 +20561,21 @@ fn aiur_fn_215( let __v_30: G = G::from_u64(235); let __v_31: G = G::from_u64(156); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_215] = [__v_32]; - record.function_queries[215].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_214] = [__v_32]; + record.function_queries[214].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_216: usize = 0; -const IN_216: usize = 0; -const OUT_216: usize = 1; -fn aiur_fn_216( - inp: [G; IN_216], +const INPUT_SIZE_215: usize = 0; +const IN_215: usize = 0; +const OUT_215: usize = 1; +fn aiur_fn_215( + inp: [G; IN_215], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_216], ExecError> { +) -> Result<[G; OUT_215], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(216); let __v_1: G = G::from_u64(56); @@ -20649,21 +20610,21 @@ fn aiur_fn_216( let __v_30: G = G::from_u64(83); let __v_31: G = G::from_u64(8); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_216] = [__v_32]; - record.function_queries[216].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_215] = [__v_32]; + record.function_queries[215].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_217: usize = 0; -const IN_217: usize = 0; -const OUT_217: usize = 1; -fn aiur_fn_217( - inp: [G; IN_217], +const INPUT_SIZE_216: usize = 0; +const IN_216: usize = 0; +const OUT_216: usize = 1; +fn aiur_fn_216( + inp: [G; IN_216], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_217], ExecError> { +) -> Result<[G; OUT_216], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(214); let __v_1: G = G::from_u64(22); @@ -20698,21 +20659,21 @@ fn aiur_fn_217( let __v_30: G = G::from_u64(251); let __v_31: G = G::from_u64(119); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_217] = [__v_32]; - record.function_queries[217].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_216] = [__v_32]; + record.function_queries[216].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_218: usize = 0; -const IN_218: usize = 0; -const OUT_218: usize = 1; -fn aiur_fn_218( - inp: [G; IN_218], +const INPUT_SIZE_217: usize = 0; +const IN_217: usize = 0; +const OUT_217: usize = 1; +fn aiur_fn_217( + inp: [G; IN_217], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_218], ExecError> { +) -> Result<[G; OUT_217], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(66); let __v_1: G = G::from_u64(136); @@ -20747,110 +20708,110 @@ fn aiur_fn_218( let __v_30: G = G::from_u64(159); let __v_31: G = G::from_u64(173); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_218] = [__v_32]; - record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_217] = [__v_32]; + record.function_queries[217].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_219: usize = 1; -const IN_219: usize = 1; -const OUT_219: usize = 1; -fn aiur_fn_219( - inp: [G; IN_219], +const INPUT_SIZE_218: usize = 1; +const IN_218: usize = 1; +const OUT_218: usize = 1; +fn aiur_fn_218( + inp: [G; IN_218], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_219], ExecError> { +) -> Result<[G; OUT_218], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_206] = { let __args: [G; IN_206] = []; let __cu = unconstrained; let __hit = record.function_queries[206].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[206].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[206].bump_multiplicity(__i); } let __ret: [G; OUT_206] = unsafe { *(record.function_queries[206].output_at(__i).as_ptr() as *const [G; OUT_206]) }; __ret }, _ => aiur_fn_206(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_205] = { let __args: [G; IN_205] = []; let __cu = unconstrained; let __hit = record.function_queries[205].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[205].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[205].bump_multiplicity(__i); } let __ret: [G; OUT_205] = unsafe { *(record.function_queries[205].output_at(__i).as_ptr() as *const [G; OUT_205]) }; __ret }, _ => aiur_fn_205(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_219] = [__v_3]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_3]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_207] = { let __args: [G; IN_207] = []; let __cu = unconstrained; let __hit = record.function_queries[207].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[207].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[207].bump_multiplicity(__i); } let __ret: [G; OUT_207] = unsafe { *(record.function_queries[207].output_at(__i).as_ptr() as *const [G; OUT_207]) }; __ret }, _ => aiur_fn_207(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_206] = { let __args: [G; IN_206] = []; let __cu = unconstrained; let __hit = record.function_queries[206].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[206].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[206].bump_multiplicity(__i); } let __ret: [G; OUT_206] = unsafe { *(record.function_queries[206].output_at(__i).as_ptr() as *const [G; OUT_206]) }; __ret }, _ => aiur_fn_206(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_219] = [__v_5]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_5]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_208] = { let __args: [G; IN_208] = []; let __cu = unconstrained; let __hit = record.function_queries[208].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[208].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[208].bump_multiplicity(__i); } let __ret: [G; OUT_208] = unsafe { *(record.function_queries[208].output_at(__i).as_ptr() as *const [G; OUT_208]) }; __ret }, _ => aiur_fn_208(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_207] = { let __args: [G; IN_207] = []; let __cu = unconstrained; let __hit = record.function_queries[207].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[207].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[207].bump_multiplicity(__i); } let __ret: [G; OUT_207] = unsafe { *(record.function_queries[207].output_at(__i).as_ptr() as *const [G; OUT_207]) }; __ret }, _ => aiur_fn_207(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_219] = [__v_7]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_7]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_213] = { let __args: [G; IN_213] = []; let __cu = unconstrained; let __hit = record.function_queries[213].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[213].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[213].bump_multiplicity(__i); } let __ret: [G; OUT_213] = unsafe { *(record.function_queries[213].output_at(__i).as_ptr() as *const [G; OUT_213]) }; __ret }, _ => aiur_fn_213(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_212] = { let __args: [G; IN_212] = []; let __cu = unconstrained; let __hit = record.function_queries[212].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[212].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[212].bump_multiplicity(__i); } let __ret: [G; OUT_212] = unsafe { *(record.function_queries[212].output_at(__i).as_ptr() as *const [G; OUT_212]) }; __ret }, _ => aiur_fn_212(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_219] = [__v_9]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_9]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_214] = { let __args: [G; IN_214] = []; let __cu = unconstrained; let __hit = record.function_queries[214].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[214].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[214].bump_multiplicity(__i); } let __ret: [G; OUT_214] = unsafe { *(record.function_queries[214].output_at(__i).as_ptr() as *const [G; OUT_214]) }; __ret }, _ => aiur_fn_214(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_213] = { let __args: [G; IN_213] = []; let __cu = unconstrained; let __hit = record.function_queries[213].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[213].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[213].bump_multiplicity(__i); } let __ret: [G; OUT_213] = unsafe { *(record.function_queries[213].output_at(__i).as_ptr() as *const [G; OUT_213]) }; __ret }, _ => aiur_fn_213(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(1); - let __ret: [G; OUT_219] = [__v_11]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_11]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_215] = { let __args: [G; IN_215] = []; let __cu = unconstrained; let __hit = record.function_queries[215].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[215].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[215].bump_multiplicity(__i); } let __ret: [G; OUT_215] = unsafe { *(record.function_queries[215].output_at(__i).as_ptr() as *const [G; OUT_215]) }; __ret }, _ => aiur_fn_215(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_214] = { let __args: [G; IN_214] = []; let __cu = unconstrained; let __hit = record.function_queries[214].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[214].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[214].bump_multiplicity(__i); } let __ret: [G; OUT_214] = unsafe { *(record.function_queries[214].output_at(__i).as_ptr() as *const [G; OUT_214]) }; __ret }, _ => aiur_fn_214(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { let __v_13: G = G::from_u64(1); - let __ret: [G; OUT_219] = [__v_13]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_13]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_217] = { let __args: [G; IN_217] = []; let __cu = unconstrained; let __hit = record.function_queries[217].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[217].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[217].bump_multiplicity(__i); } let __ret: [G; OUT_217] = unsafe { *(record.function_queries[217].output_at(__i).as_ptr() as *const [G; OUT_217]) }; __ret }, _ => aiur_fn_217(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_216] = { let __args: [G; IN_216] = []; let __cu = unconstrained; let __hit = record.function_queries[216].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[216].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[216].bump_multiplicity(__i); } let __ret: [G; OUT_216] = unsafe { *(record.function_queries[216].output_at(__i).as_ptr() as *const [G; OUT_216]) }; __ret }, _ => aiur_fn_216(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; match __v_14.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(1); - let __ret: [G; OUT_219] = [__v_15]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_15]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_219] = [__v_15]; - record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_218] = [__v_15]; + record.function_queries[218].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -20869,22 +20830,22 @@ fn aiur_fn_219( }) } -const INPUT_SIZE_220: usize = 3; -const IN_220: usize = 3; -const OUT_220: usize = 2; -fn aiur_fn_220( - inp: [G; IN_220], +const INPUT_SIZE_219: usize = 3; +const IN_219: usize = 3; +const OUT_219: usize = 2; +fn aiur_fn_219( + inp: [G; IN_219], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_220], ExecError> { +) -> Result<[G; OUT_219], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_208] = { let __args: [G; IN_208] = []; let __cu = unconstrained; let __hit = record.function_queries[208].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[208].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[208].bump_multiplicity(__i); } let __ret: [G; OUT_208] = unsafe { *(record.function_queries[208].output_at(__i).as_ptr() as *const [G; OUT_208]) }; __ret }, _ => aiur_fn_208(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_207] = { let __args: [G; IN_207] = []; let __cu = unconstrained; let __hit = record.function_queries[207].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[207].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[207].bump_multiplicity(__i); } let __ret: [G; OUT_207] = unsafe { *(record.function_queries[207].output_at(__i).as_ptr() as *const [G; OUT_207]) }; __ret }, _ => aiur_fn_207(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; @@ -20893,9 +20854,9 @@ fn aiur_fn_220( match __v_3.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_234] = { let __args: [G; IN_234] = [__v_7, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[234].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[234].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[234].bump_multiplicity(__i); } let __ret: [G; OUT_234] = unsafe { *(record.function_queries[234].output_at(__i).as_ptr() as *const [G; OUT_234]) }; __ret }, _ => aiur_fn_234(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_233] = { let __args: [G; IN_233] = [__v_7, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[233].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[233].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[233].bump_multiplicity(__i); } let __ret: [G; OUT_233] = unsafe { *(record.function_queries[233].output_at(__i).as_ptr() as *const [G; OUT_233]) }; __ret }, _ => aiur_fn_233(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; match __v_8.as_canonical_u64() { @@ -20905,8 +20866,8 @@ fn aiur_fn_220( let __v_12: G = G::from_u64(1); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_9, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_10, __v_14]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_10, __v_14]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -20915,8 +20876,8 @@ fn aiur_fn_220( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_10, __v_14]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_10, __v_14]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -20930,14 +20891,14 @@ fn aiur_fn_220( let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_6, __v_10]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_6, __v_10]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_206] = { let __args: [G; IN_206] = []; let __cu = unconstrained; let __hit = record.function_queries[206].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[206].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[206].bump_multiplicity(__i); } let __ret: [G; OUT_206] = unsafe { *(record.function_queries[206].output_at(__i).as_ptr() as *const [G; OUT_206]) }; __ret }, _ => aiur_fn_206(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_205] = { let __args: [G; IN_205] = []; let __cu = unconstrained; let __hit = record.function_queries[205].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[205].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[205].bump_multiplicity(__i); } let __ret: [G; OUT_205] = unsafe { *(record.function_queries[205].output_at(__i).as_ptr() as *const [G; OUT_205]) }; __ret }, _ => aiur_fn_205(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; @@ -20952,13 +20913,13 @@ fn aiur_fn_220( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_10, __v_14]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_10, __v_14]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_11.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_12: G = __loaded[0]; @@ -20969,17 +20930,17 @@ fn aiur_fn_220( 7u64 => { match __v_13.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __r_arr: [G; OUT_233] = { let __args: [G; IN_233] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[233].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[233].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[233].bump_multiplicity(__i); } let __ret: [G; OUT_233] = unsafe { *(record.function_queries[233].output_at(__i).as_ptr() as *const [G; OUT_233]) }; __ret }, _ => aiur_fn_233(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_232] = { let __args: [G; IN_232] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[232].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[232].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[232].bump_multiplicity(__i); } let __ret: [G; OUT_232] = unsafe { *(record.function_queries[232].output_at(__i).as_ptr() as *const [G; OUT_232]) }; __ret }, _ => aiur_fn_232(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = G::from_u64(1); let __v_19: G = G::from_u64(7); let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(0); let __v_22: G = { let __values: [G; 4] = [__v_19, __v_20, __v_17, __v_21]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_18, __v_22]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_18, __v_22]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -20988,8 +20949,8 @@ fn aiur_fn_220( let __v_18: G = G::from_u64(0); let __v_19: G = G::from_u64(0); let __v_20: G = { let __values: [G; 4] = [__v_17, __v_18, __v_19, __v_19]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_16, __v_20]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_16, __v_20]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21000,8 +20961,8 @@ fn aiur_fn_220( let __v_18: G = G::from_u64(0); let __v_19: G = G::from_u64(0); let __v_20: G = { let __values: [G; 4] = [__v_17, __v_18, __v_19, __v_19]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_16, __v_20]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_16, __v_20]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21009,63 +20970,63 @@ fn aiur_fn_220( } }, _ => { - let __r_arr: [G; OUT_213] = { let __args: [G; IN_213] = []; let __cu = unconstrained; let __hit = record.function_queries[213].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[213].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[213].bump_multiplicity(__i); } let __ret: [G; OUT_213] = unsafe { *(record.function_queries[213].output_at(__i).as_ptr() as *const [G; OUT_213]) }; __ret }, _ => aiur_fn_213(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_212] = { let __args: [G; IN_212] = []; let __cu = unconstrained; let __hit = record.function_queries[212].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[212].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[212].bump_multiplicity(__i); } let __ret: [G; OUT_212] = unsafe { *(record.function_queries[212].output_at(__i).as_ptr() as *const [G; OUT_212]) }; __ret }, _ => aiur_fn_212(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_221] = { let __args: [G; IN_221] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[221].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[221].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[221].bump_multiplicity(__i); } let __ret: [G; OUT_221] = unsafe { *(record.function_queries[221].output_at(__i).as_ptr() as *const [G; OUT_221]) }; __ret }, _ => aiur_fn_221(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_220] = { let __args: [G; IN_220] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[220].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[220].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[220].bump_multiplicity(__i); } let __ret: [G; OUT_220] = unsafe { *(record.function_queries[220].output_at(__i).as_ptr() as *const [G; OUT_220]) }; __ret }, _ => aiur_fn_220(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; - let __ret: [G; OUT_220] = [__v_10, __v_11]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_10, __v_11]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_214] = { let __args: [G; IN_214] = []; let __cu = unconstrained; let __hit = record.function_queries[214].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[214].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[214].bump_multiplicity(__i); } let __ret: [G; OUT_214] = unsafe { *(record.function_queries[214].output_at(__i).as_ptr() as *const [G; OUT_214]) }; __ret }, _ => aiur_fn_214(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_213] = { let __args: [G; IN_213] = []; let __cu = unconstrained; let __hit = record.function_queries[213].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[213].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[213].bump_multiplicity(__i); } let __ret: [G; OUT_213] = unsafe { *(record.function_queries[213].output_at(__i).as_ptr() as *const [G; OUT_213]) }; __ret }, _ => aiur_fn_213(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_221] = { let __args: [G; IN_221] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[221].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[221].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[221].bump_multiplicity(__i); } let __ret: [G; OUT_221] = unsafe { *(record.function_queries[221].output_at(__i).as_ptr() as *const [G; OUT_221]) }; __ret }, _ => aiur_fn_221(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_220] = { let __args: [G; IN_220] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[220].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[220].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[220].bump_multiplicity(__i); } let __ret: [G; OUT_220] = unsafe { *(record.function_queries[220].output_at(__i).as_ptr() as *const [G; OUT_220]) }; __ret }, _ => aiur_fn_220(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; - let __ret: [G; OUT_220] = [__v_12, __v_13]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_12, __v_13]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_215] = { let __args: [G; IN_215] = []; let __cu = unconstrained; let __hit = record.function_queries[215].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[215].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[215].bump_multiplicity(__i); } let __ret: [G; OUT_215] = unsafe { *(record.function_queries[215].output_at(__i).as_ptr() as *const [G; OUT_215]) }; __ret }, _ => aiur_fn_215(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_214] = { let __args: [G; IN_214] = []; let __cu = unconstrained; let __hit = record.function_queries[214].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[214].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[214].bump_multiplicity(__i); } let __ret: [G; OUT_214] = unsafe { *(record.function_queries[214].output_at(__i).as_ptr() as *const [G; OUT_214]) }; __ret }, _ => aiur_fn_214(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_222] = { let __args: [G; IN_222] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[222].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[222].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[222].bump_multiplicity(__i); } let __ret: [G; OUT_222] = unsafe { *(record.function_queries[222].output_at(__i).as_ptr() as *const [G; OUT_222]) }; __ret }, _ => aiur_fn_222(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_221] = { let __args: [G; IN_221] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[221].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[221].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[221].bump_multiplicity(__i); } let __ret: [G; OUT_221] = unsafe { *(record.function_queries[221].output_at(__i).as_ptr() as *const [G; OUT_221]) }; __ret }, _ => aiur_fn_221(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __ret: [G; OUT_220] = [__v_14, __v_15]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_14, __v_15]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_217] = { let __args: [G; IN_217] = []; let __cu = unconstrained; let __hit = record.function_queries[217].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[217].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[217].bump_multiplicity(__i); } let __ret: [G; OUT_217] = unsafe { *(record.function_queries[217].output_at(__i).as_ptr() as *const [G; OUT_217]) }; __ret }, _ => aiur_fn_217(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_216] = { let __args: [G; IN_216] = []; let __cu = unconstrained; let __hit = record.function_queries[216].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[216].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[216].bump_multiplicity(__i); } let __ret: [G; OUT_216] = unsafe { *(record.function_queries[216].output_at(__i).as_ptr() as *const [G; OUT_216]) }; __ret }, _ => aiur_fn_216(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; match __v_15.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_535] = { let __args: [G; IN_535] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[535].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[535].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[535].bump_multiplicity(__i); } let __ret: [G; OUT_535] = unsafe { *(record.function_queries[535].output_at(__i).as_ptr() as *const [G; OUT_535]) }; __ret }, _ => aiur_fn_535(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_534] = { let __args: [G; IN_534] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[534].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[534].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[534].bump_multiplicity(__i); } let __ret: [G; OUT_534] = unsafe { *(record.function_queries[534].output_at(__i).as_ptr() as *const [G; OUT_534]) }; __ret }, _ => aiur_fn_534(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = __r_arr[1]; - let __ret: [G; OUT_220] = [__v_16, __v_17]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_16, __v_17]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_207] = { let __args: [G; IN_207] = []; let __cu = unconstrained; let __hit = record.function_queries[207].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[207].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[207].bump_multiplicity(__i); } let __ret: [G; OUT_207] = unsafe { *(record.function_queries[207].output_at(__i).as_ptr() as *const [G; OUT_207]) }; __ret }, _ => aiur_fn_207(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_206] = { let __args: [G; IN_206] = []; let __cu = unconstrained; let __hit = record.function_queries[206].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[206].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[206].bump_multiplicity(__i); } let __ret: [G; OUT_206] = unsafe { *(record.function_queries[206].output_at(__i).as_ptr() as *const [G; OUT_206]) }; __ret }, _ => aiur_fn_206(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; @@ -21080,16 +21041,16 @@ fn aiur_fn_220( let __v_22: G = G::from_u64(0); let __v_23: G = G::from_u64(0); let __v_24: G = { let __values: [G; 4] = [__v_21, __v_22, __v_23, __v_23]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_20, __v_24]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_20, __v_24]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_20: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_21.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_24: G = __loaded[0]; @@ -21109,15 +21070,15 @@ fn aiur_fn_220( 7u64 => { match __v_29.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_26, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_26, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = G::from_u64(1); let __v_34: G = G::from_u64(7); let __v_35: G = G::from_u64(1); let __v_36: G = G::from_u64(0); let __v_37: G = { let __values: [G; 4] = [__v_34, __v_35, __v_32, __v_36]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_33, __v_37]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_33, __v_37]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21126,8 +21087,8 @@ fn aiur_fn_220( let __v_34: G = G::from_u64(0); let __v_35: G = G::from_u64(0); let __v_36: G = { let __values: [G; 4] = [__v_33, __v_34, __v_35, __v_35]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_32, __v_36]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_32, __v_36]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21138,8 +21099,8 @@ fn aiur_fn_220( let __v_34: G = G::from_u64(0); let __v_35: G = G::from_u64(0); let __v_36: G = { let __values: [G; 4] = [__v_33, __v_34, __v_35, __v_35]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_32, __v_36]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_32, __v_36]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21150,8 +21111,8 @@ fn aiur_fn_220( let __v_30: G = G::from_u64(0); let __v_31: G = G::from_u64(0); let __v_32: G = { let __values: [G; 4] = [__v_29, __v_30, __v_31, __v_31]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_28, __v_32]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_28, __v_32]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21162,8 +21123,8 @@ fn aiur_fn_220( let __v_30: G = G::from_u64(0); let __v_31: G = G::from_u64(0); let __v_32: G = { let __values: [G; 4] = [__v_29, __v_30, __v_31, __v_31]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_28, __v_32]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_28, __v_32]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21176,8 +21137,8 @@ fn aiur_fn_220( let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(0); let __v_22: G = { let __values: [G; 4] = [__v_19, __v_20, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_220] = [__v_18, __v_22]; - record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_219] = [__v_18, __v_22]; + record.function_queries[219].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21196,18 +21157,18 @@ fn aiur_fn_220( }) } -const INPUT_SIZE_221: usize = 1; -const IN_221: usize = 1; -const OUT_221: usize = 2; -fn aiur_fn_221( - inp: [G; IN_221], +const INPUT_SIZE_220: usize = 1; +const IN_220: usize = 1; +const OUT_220: usize = 2; +fn aiur_fn_220( + inp: [G; IN_220], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_221], ExecError> { +) -> Result<[G; OUT_220], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = G::from_u64(1); let __v_3: G = { let __a_val = __v_1.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -21218,13 +21179,13 @@ fn aiur_fn_221( let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_221] = [__v_4, __v_8]; - record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_220] = [__v_4, __v_8]; + record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -21235,16 +21196,16 @@ fn aiur_fn_221( 7u64 => { match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_224] = { let __args: [G; IN_224] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[224].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[224].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[224].bump_multiplicity(__i); } let __ret: [G; OUT_224] = unsafe { *(record.function_queries[224].output_at(__i).as_ptr() as *const [G; OUT_224]) }; __ret }, _ => aiur_fn_224(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_223] = { let __args: [G; IN_223] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[223].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[223].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[223].bump_multiplicity(__i); } let __ret: [G; OUT_223] = unsafe { *(record.function_queries[223].output_at(__i).as_ptr() as *const [G; OUT_223]) }; __ret }, _ => aiur_fn_223(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_233] = { let __args: [G; IN_233] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[233].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[233].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[233].bump_multiplicity(__i); } let __ret: [G; OUT_233] = unsafe { *(record.function_queries[233].output_at(__i).as_ptr() as *const [G; OUT_233]) }; __ret }, _ => aiur_fn_233(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_232] = { let __args: [G; IN_232] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[232].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[232].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[232].bump_multiplicity(__i); } let __ret: [G; OUT_232] = unsafe { *(record.function_queries[232].output_at(__i).as_ptr() as *const [G; OUT_232]) }; __ret }, _ => aiur_fn_232(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(7); let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_11, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_16: G = G::from_u64(2); - let __r_arr: [G; OUT_209] = { let __args: [G; IN_209] = []; let __cu = unconstrained; let __hit = record.function_queries[209].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[209].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[209].bump_multiplicity(__i); } let __ret: [G; OUT_209] = unsafe { *(record.function_queries[209].output_at(__i).as_ptr() as *const [G; OUT_209]) }; __ret }, _ => aiur_fn_209(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_208] = { let __args: [G; IN_208] = []; let __cu = unconstrained; let __hit = record.function_queries[208].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[208].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[208].bump_multiplicity(__i); } let __ret: [G; OUT_208] = unsafe { *(record.function_queries[208].output_at(__i).as_ptr() as *const [G; OUT_208]) }; __ret }, _ => aiur_fn_208(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = G::from_u64(1); let __v_19: G = G::from_u64(1); @@ -21255,8 +21216,8 @@ fn aiur_fn_221( let __v_24: G = G::from_u64(3); let __v_25: G = G::from_u64(0); let __v_26: G = { let __values: [G; 4] = [__v_24, __v_22, __v_15, __v_25]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_221] = [__v_23, __v_26]; - record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_220] = [__v_23, __v_26]; + record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21265,8 +21226,8 @@ fn aiur_fn_221( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_221] = [__v_10, __v_14]; - record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_220] = [__v_10, __v_14]; + record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21277,8 +21238,8 @@ fn aiur_fn_221( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_221] = [__v_10, __v_14]; - record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_220] = [__v_10, __v_14]; + record.function_queries[220].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21287,18 +21248,18 @@ fn aiur_fn_221( }) } -const INPUT_SIZE_222: usize = 1; -const IN_222: usize = 1; -const OUT_222: usize = 2; -fn aiur_fn_222( - inp: [G; IN_222], +const INPUT_SIZE_221: usize = 1; +const IN_221: usize = 1; +const OUT_221: usize = 2; +fn aiur_fn_221( + inp: [G; IN_221], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_222], ExecError> { +) -> Result<[G; OUT_221], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = G::from_u64(1); let __v_3: G = { let __a_val = __v_1.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -21309,13 +21270,13 @@ fn aiur_fn_222( let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_222] = [__v_4, __v_8]; - record.function_queries[222].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_221] = [__v_4, __v_8]; + record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -21334,15 +21295,15 @@ fn aiur_fn_222( 1u64 => { let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(2); - let __r_arr: [G; OUT_216] = { let __args: [G; IN_216] = []; let __cu = unconstrained; let __hit = record.function_queries[216].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[216].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[216].bump_multiplicity(__i); } let __ret: [G; OUT_216] = unsafe { *(record.function_queries[216].output_at(__i).as_ptr() as *const [G; OUT_216]) }; __ret }, _ => aiur_fn_216(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_215] = { let __args: [G; IN_215] = []; let __cu = unconstrained; let __hit = record.function_queries[215].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[215].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[215].bump_multiplicity(__i); } let __ret: [G; OUT_215] = unsafe { *(record.function_queries[215].output_at(__i).as_ptr() as *const [G; OUT_215]) }; __ret }, _ => aiur_fn_215(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 3] = [__v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_19: G = G::from_u64(0); let __v_20: G = { let __values: [G; 4] = [__v_14, __v_15, __v_18, __v_19]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_222] = [__v_13, __v_20]; - record.function_queries[222].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_221] = [__v_13, __v_20]; + record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21351,8 +21312,8 @@ fn aiur_fn_222( let __v_15: G = G::from_u64(0); let __v_16: G = G::from_u64(0); let __v_17: G = { let __values: [G; 4] = [__v_14, __v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_222] = [__v_13, __v_17]; - record.function_queries[222].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_221] = [__v_13, __v_17]; + record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21363,8 +21324,8 @@ fn aiur_fn_222( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_222] = [__v_10, __v_14]; - record.function_queries[222].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_221] = [__v_10, __v_14]; + record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21375,8 +21336,8 @@ fn aiur_fn_222( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_222] = [__v_10, __v_14]; - record.function_queries[222].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_221] = [__v_10, __v_14]; + record.function_queries[221].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -21385,15 +21346,15 @@ fn aiur_fn_222( }) } -const INPUT_SIZE_223: usize = 1; -const IN_223: usize = 1; -const OUT_223: usize = 0; -fn aiur_fn_223( - inp: [G; IN_223], +const INPUT_SIZE_222: usize = 1; +const IN_222: usize = 1; +const OUT_222: usize = 0; +fn aiur_fn_222( + inp: [G; IN_222], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_223], ExecError> { +) -> Result<[G; OUT_222], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -21402,17 +21363,17 @@ fn aiur_fn_223( let __v_3: G = __loaded[2]; match __v_1.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_223] = []; - record.function_queries[223].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_222] = []; + record.function_queries[222].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_227] = { let __args: [G; IN_227] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[227].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[227].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[227].bump_multiplicity(__i); } let __ret: [G; OUT_227] = unsafe { *(record.function_queries[227].output_at(__i).as_ptr() as *const [G; OUT_227]) }; __ret }, _ => aiur_fn_227(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; - let __r_arr: [G; OUT_223] = { let __args: [G; IN_223] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[223].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[223].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[223].bump_multiplicity(__i); } let __ret: [G; OUT_223] = unsafe { *(record.function_queries[223].output_at(__i).as_ptr() as *const [G; OUT_223]) }; __ret }, _ => aiur_fn_223(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_223] = []; - record.function_queries[223].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_222] = { let __args: [G; IN_222] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[222].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[222].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[222].bump_multiplicity(__i); } let __ret: [G; OUT_222] = unsafe { *(record.function_queries[222].output_at(__i).as_ptr() as *const [G; OUT_222]) }; __ret }, _ => aiur_fn_222(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_222] = []; + record.function_queries[222].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21422,35 +21383,35 @@ fn aiur_fn_223( }) } -const INPUT_SIZE_224: usize = 1; -const IN_224: usize = 1; -const OUT_224: usize = 1; -fn aiur_fn_224( - inp: [G; IN_224], +const INPUT_SIZE_223: usize = 1; +const IN_223: usize = 1; +const OUT_223: usize = 1; +fn aiur_fn_223( + inp: [G; IN_223], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_224], ExecError> { +) -> Result<[G; OUT_223], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(65); - let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_224] = { let __args: [G; IN_224] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[224].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[224].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[224].bump_multiplicity(__i); } let __ret: [G; OUT_224] = unsafe { *(record.function_queries[224].output_at(__i).as_ptr() as *const [G; OUT_224]) }; __ret }, _ => aiur_fn_224(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __ret: [G; OUT_224] = [__v_2]; - record.function_queries[224].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_223] = [__v_2]; + record.function_queries[223].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_225: usize = 2; -const IN_225: usize = 2; -const OUT_225: usize = 1; -fn aiur_fn_225( - inp: [G; IN_225], +const INPUT_SIZE_224: usize = 2; +const IN_224: usize = 2; +const OUT_224: usize = 1; +fn aiur_fn_224( + inp: [G; IN_224], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_225], ExecError> { +) -> Result<[G; OUT_224], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -21460,18 +21421,18 @@ fn aiur_fn_225( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_225] = [__v_1]; - record.function_queries[225].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_224] = [__v_1]; + record.function_queries[224].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_227] = { let __args: [G; IN_227] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[227].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[227].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[227].bump_multiplicity(__i); } let __ret: [G; OUT_227] = unsafe { *(record.function_queries[227].output_at(__i).as_ptr() as *const [G; OUT_227]) }; __ret }, _ => aiur_fn_227(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_6, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_224] = { let __args: [G; IN_224] = [__v_6, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[224].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[224].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[224].bump_multiplicity(__i); } let __ret: [G; OUT_224] = unsafe { *(record.function_queries[224].output_at(__i).as_ptr() as *const [G; OUT_224]) }; __ret }, _ => aiur_fn_224(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_225] = [__v_7]; - record.function_queries[225].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_224] = [__v_7]; + record.function_queries[224].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21481,15 +21442,15 @@ fn aiur_fn_225( }) } -const INPUT_SIZE_226: usize = 1; -const IN_226: usize = 1; -const OUT_226: usize = 1; -fn aiur_fn_226( - inp: [G; IN_226], +const INPUT_SIZE_225: usize = 1; +const IN_225: usize = 1; +const OUT_225: usize = 1; +fn aiur_fn_225( + inp: [G; IN_225], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_226], ExecError> { +) -> Result<[G; OUT_225], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(128); @@ -21502,8 +21463,8 @@ fn aiur_fn_226( 1u64 => { let __v_5: G = G::from_u64(128); let __v_6: G = (__v_0 - __v_5); - let __ret: [G; OUT_226] = [__v_6]; - record.function_queries[226].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_225] = [__v_6]; + record.function_queries[225].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21518,15 +21479,15 @@ fn aiur_fn_226( }) } -const INPUT_SIZE_227: usize = 2; -const IN_227: usize = 2; -const OUT_227: usize = 2; -fn aiur_fn_227( - inp: [G; IN_227], +const INPUT_SIZE_226: usize = 2; +const IN_226: usize = 2; +const OUT_226: usize = 2; +fn aiur_fn_226( + inp: [G; IN_226], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_227], ExecError> { +) -> Result<[G; OUT_226], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -21534,8 +21495,8 @@ fn aiur_fn_227( let __v_3: G = if unconstrained { Bytes2::less_than(&__v_0, &__v_2) } else { bytes2_less_than_value(__v_0, __v_2, record) }; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_227] = [__v_0, __v_1]; - record.function_queries[227].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_226] = [__v_0, __v_1]; + record.function_queries[226].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21557,11 +21518,11 @@ fn aiur_fn_227( let __v_12: G = (__v_0 - __v_11); let __v_13: G = G::from_u64(64); let __v_14: G = (__v_12 * __v_13); - let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = (__v_14 + __v_15); - let __ret: [G; OUT_227] = [__v_16, __v_10]; - record.function_queries[227].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_226] = [__v_16, __v_10]; + record.function_queries[226].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21590,11 +21551,11 @@ fn aiur_fn_227( let __v_17: G = (__v_0 - __v_16); let __v_18: G = G::from_u64(4096); let __v_19: G = (__v_17 * __v_18); - let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = G::from_u64(64); let __v_22: G = (__v_20 * __v_21); - let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __v_24: G = (__v_22 + __v_23); let __v_25: G = (__v_19 + __v_24); @@ -21602,8 +21563,8 @@ fn aiur_fn_227( let __v_27: G = { let __a_val = __v_25.as_canonical_u64(); let __b_val = __v_26.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_27.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_227] = [__v_25, __v_15]; - record.function_queries[227].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_226] = [__v_25, __v_15]; + record.function_queries[226].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21644,15 +21605,15 @@ fn aiur_fn_227( let __v_20: G = (__v_0 - __v_19); let __v_21: G = G::from_u64(262144); let __v_22: G = (__v_20 * __v_21); - let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __v_24: G = G::from_u64(4096); let __v_25: G = (__v_23 * __v_24); - let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = G::from_u64(64); let __v_28: G = (__v_26 * __v_27); - let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_225] = { let __args: [G; IN_225] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[225].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[225].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[225].bump_multiplicity(__i); } let __ret: [G; OUT_225] = unsafe { *(record.function_queries[225].output_at(__i).as_ptr() as *const [G; OUT_225]) }; __ret }, _ => aiur_fn_225(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = (__v_28 + __v_29); let __v_31: G = (__v_25 + __v_30); @@ -21661,8 +21622,8 @@ fn aiur_fn_227( let __v_34: G = { let __a_val = __v_32.as_canonical_u64(); let __b_val = __v_33.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_34.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_227] = [__v_32, __v_18]; - record.function_queries[227].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_226] = [__v_32, __v_18]; + record.function_queries[226].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21698,15 +21659,15 @@ fn aiur_fn_227( }) } -const INPUT_SIZE_228: usize = 1; -const IN_228: usize = 1; -const OUT_228: usize = 1; -fn aiur_fn_228( - inp: [G; IN_228], +const INPUT_SIZE_227: usize = 1; +const IN_227: usize = 1; +const OUT_227: usize = 1; +fn aiur_fn_227( + inp: [G; IN_227], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_228], ExecError> { +) -> Result<[G; OUT_227], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(0); @@ -21718,17 +21679,17 @@ fn aiur_fn_228( let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_8: G = { let __values: [G; 3] = [__v_4, __v_3, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_9: G = G::from_u64(2); - let __r_arr: [G; OUT_210] = { let __args: [G; IN_210] = []; let __cu = unconstrained; let __hit = record.function_queries[210].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[210].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[210].bump_multiplicity(__i); } let __ret: [G; OUT_210] = unsafe { *(record.function_queries[210].output_at(__i).as_ptr() as *const [G; OUT_210]) }; __ret }, _ => aiur_fn_210(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_209] = { let __args: [G; IN_209] = []; let __cu = unconstrained; let __hit = record.function_queries[209].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[209].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[209].bump_multiplicity(__i); } let __ret: [G; OUT_209] = unsafe { *(record.function_queries[209].output_at(__i).as_ptr() as *const [G; OUT_209]) }; __ret }, _ => aiur_fn_209(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_9, __v_10, __v_8, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_13: G = G::from_u64(2); - let __r_arr: [G; OUT_211] = { let __args: [G; IN_211] = []; let __cu = unconstrained; let __hit = record.function_queries[211].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[211].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[211].bump_multiplicity(__i); } let __ret: [G; OUT_211] = unsafe { *(record.function_queries[211].output_at(__i).as_ptr() as *const [G; OUT_211]) }; __ret }, _ => aiur_fn_211(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_210] = { let __args: [G; IN_210] = []; let __cu = unconstrained; let __hit = record.function_queries[210].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[210].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[210].bump_multiplicity(__i); } let __ret: [G; OUT_210] = unsafe { *(record.function_queries[210].output_at(__i).as_ptr() as *const [G; OUT_210]) }; __ret }, _ => aiur_fn_210(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_8, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = G::from_u64(2); - let __r_arr: [G; OUT_212] = { let __args: [G; IN_212] = []; let __cu = unconstrained; let __hit = record.function_queries[212].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[212].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[212].bump_multiplicity(__i); } let __ret: [G; OUT_212] = unsafe { *(record.function_queries[212].output_at(__i).as_ptr() as *const [G; OUT_212]) }; __ret }, _ => aiur_fn_212(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_211] = { let __args: [G; IN_211] = []; let __cu = unconstrained; let __hit = record.function_queries[211].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[211].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[211].bump_multiplicity(__i); } let __ret: [G; OUT_211] = unsafe { *(record.function_queries[211].output_at(__i).as_ptr() as *const [G; OUT_211]) }; __ret }, _ => aiur_fn_211(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(1); @@ -21736,7 +21697,7 @@ fn aiur_fn_228( let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 4] = [__v_17, __v_18, __v_21, __v_22]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_24: G = G::from_u64(2); - let __r_arr: [G; OUT_209] = { let __args: [G; IN_209] = []; let __cu = unconstrained; let __hit = record.function_queries[209].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[209].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[209].bump_multiplicity(__i); } let __ret: [G; OUT_209] = unsafe { *(record.function_queries[209].output_at(__i).as_ptr() as *const [G; OUT_209]) }; __ret }, _ => aiur_fn_209(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_208] = { let __args: [G; IN_208] = []; let __cu = unconstrained; let __hit = record.function_queries[208].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[208].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[208].bump_multiplicity(__i); } let __ret: [G; OUT_208] = unsafe { *(record.function_queries[208].output_at(__i).as_ptr() as *const [G; OUT_208]) }; __ret }, _ => aiur_fn_208(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(1); let __v_27: G = G::from_u64(1); @@ -21744,7 +21705,7 @@ fn aiur_fn_228( let __v_29: G = G::from_u64(0); let __v_30: G = { let __values: [G; 4] = [__v_24, __v_25, __v_28, __v_29]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_31: G = G::from_u64(2); - let __r_arr: [G; OUT_208] = { let __args: [G; IN_208] = []; let __cu = unconstrained; let __hit = record.function_queries[208].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[208].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[208].bump_multiplicity(__i); } let __ret: [G; OUT_208] = unsafe { *(record.function_queries[208].output_at(__i).as_ptr() as *const [G; OUT_208]) }; __ret }, _ => aiur_fn_208(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_207] = { let __args: [G; IN_207] = []; let __cu = unconstrained; let __hit = record.function_queries[207].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[207].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[207].bump_multiplicity(__i); } let __ret: [G; OUT_207] = unsafe { *(record.function_queries[207].output_at(__i).as_ptr() as *const [G; OUT_207]) }; __ret }, _ => aiur_fn_207(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = G::from_u64(1); let __v_34: G = G::from_u64(1); @@ -21757,26 +21718,26 @@ fn aiur_fn_228( let __v_41: G = G::from_u64(3); let __v_42: G = G::from_u64(0); let __v_43: G = { let __values: [G; 4] = [__v_41, __v_16, __v_23, __v_42]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_229] = { let __args: [G; IN_229] = [__v_0, __v_40, __v_43, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[229].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[229].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[229].bump_multiplicity(__i); } let __ret: [G; OUT_229] = unsafe { *(record.function_queries[229].output_at(__i).as_ptr() as *const [G; OUT_229]) }; __ret }, _ => aiur_fn_229(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_228] = { let __args: [G; IN_228] = [__v_0, __v_40, __v_43, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[228].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[228].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[228].bump_multiplicity(__i); } let __ret: [G; OUT_228] = unsafe { *(record.function_queries[228].output_at(__i).as_ptr() as *const [G; OUT_228]) }; __ret }, _ => aiur_fn_228(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = G::from_u64(3); let __v_46: G = G::from_u64(0); let __v_47: G = { let __values: [G; 4] = [__v_45, __v_37, __v_44, __v_46]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_228] = [__v_47]; - record.function_queries[228].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_227] = [__v_47]; + record.function_queries[227].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_229: usize = 4; -const IN_229: usize = 4; -const OUT_229: usize = 1; -fn aiur_fn_229( - inp: [G; IN_229], +const INPUT_SIZE_228: usize = 4; +const IN_228: usize = 4; +const OUT_228: usize = 1; +fn aiur_fn_228( + inp: [G; IN_228], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_229], ExecError> { +) -> Result<[G; OUT_228], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -21788,15 +21749,15 @@ fn aiur_fn_229( let __v_6: G = __loaded[2]; match __v_4.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_229] = [__v_1]; - record.function_queries[229].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_228] = [__v_1]; + record.function_queries[228].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_227] = { let __args: [G; IN_227] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[227].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[227].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[227].bump_multiplicity(__i); } let __ret: [G; OUT_227] = unsafe { *(record.function_queries[227].output_at(__i).as_ptr() as *const [G; OUT_227]) }; __ret }, _ => aiur_fn_227(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_226] = { let __args: [G; IN_226] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[226].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[226].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[226].bump_multiplicity(__i); } let __ret: [G; OUT_226] = unsafe { *(record.function_queries[226].output_at(__i).as_ptr() as *const [G; OUT_226]) }; __ret }, _ => aiur_fn_226(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __r_arr: [G; OUT_233] = { let __args: [G; IN_233] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[233].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[233].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[233].bump_multiplicity(__i); } let __ret: [G; OUT_233] = unsafe { *(record.function_queries[233].output_at(__i).as_ptr() as *const [G; OUT_233]) }; __ret }, _ => aiur_fn_233(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_232] = { let __args: [G; IN_232] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[232].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[232].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[232].bump_multiplicity(__i); } let __ret: [G; OUT_232] = unsafe { *(record.function_queries[232].output_at(__i).as_ptr() as *const [G; OUT_232]) }; __ret }, _ => aiur_fn_232(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(7); let __v_11: G = G::from_u64(0); @@ -21808,13 +21769,13 @@ fn aiur_fn_229( let __v_17: G = G::from_u64(3); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_17, __v_2, __v_16, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_229] = { let __args: [G; IN_229] = [__v_8, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[229].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[229].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[229].bump_multiplicity(__i); } let __ret: [G; OUT_229] = unsafe { *(record.function_queries[229].output_at(__i).as_ptr() as *const [G; OUT_229]) }; __ret }, _ => aiur_fn_229(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_228] = { let __args: [G; IN_228] = [__v_8, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[228].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[228].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[228].bump_multiplicity(__i); } let __ret: [G; OUT_228] = unsafe { *(record.function_queries[228].output_at(__i).as_ptr() as *const [G; OUT_228]) }; __ret }, _ => aiur_fn_228(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = G::from_u64(3); let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 4] = [__v_21, __v_19, __v_20, __v_22]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_229] = [__v_23]; - record.function_queries[229].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_228] = [__v_23]; + record.function_queries[228].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -21824,15 +21785,15 @@ fn aiur_fn_229( }) } -const INPUT_SIZE_230: usize = 2; -const IN_230: usize = 2; -const OUT_230: usize = 1; -fn aiur_fn_230( - inp: [G; IN_230], +const INPUT_SIZE_229: usize = 2; +const IN_229: usize = 2; +const OUT_229: usize = 1; +fn aiur_fn_229( + inp: [G; IN_229], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_230], ExecError> { +) -> Result<[G; OUT_229], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -21850,7 +21811,7 @@ fn aiur_fn_230( let __v_9: G = __loaded[3]; match __v_6.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_10.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_11: G = __loaded[0]; @@ -21870,7 +21831,7 @@ fn aiur_fn_230( let __v_23: G = G::from_u64(1); let __v_24: G = G::from_u64(1); let __v_25: G = { let __values: [G; 3] = [__v_23, __v_24, __v_24]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_14, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_14, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_26.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_27: G = __loaded[0]; @@ -21880,58 +21841,58 @@ fn aiur_fn_230( match __v_27.as_canonical_u64() { 4u64 => { let __v_31: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_29, __v_4, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_29, __v_4, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_32, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_32, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; - let __ret: [G; OUT_230] = [__v_33]; - record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_229] = [__v_33]; + record.function_queries[229].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_31: G = G::from_u64(3); let __v_32: G = G::from_u64(0); let __v_33: G = { let __values: [G; 4] = [__v_31, __v_26, __v_4, __v_32]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_33, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_33, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __ret: [G; OUT_230] = [__v_34]; - record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_229] = [__v_34]; + record.function_queries[229].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_230] = [__v_0]; - record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_229] = [__v_0]; + record.function_queries[229].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_230] = [__v_0]; - record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_229] = [__v_0]; + record.function_queries[229].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_230] = [__v_0]; - record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_229] = [__v_0]; + record.function_queries[229].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_231: usize = 2; -const IN_231: usize = 2; -const OUT_231: usize = 1; -fn aiur_fn_231( - inp: [G; IN_231], +const INPUT_SIZE_230: usize = 2; +const IN_230: usize = 2; +const OUT_230: usize = 1; +fn aiur_fn_230( + inp: [G; IN_230], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_231], ExecError> { +) -> Result<[G; OUT_230], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -21944,75 +21905,68 @@ fn aiur_fn_231( 7u64 => { match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_228] = { let __args: [G; IN_228] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[228].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[228].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[228].bump_multiplicity(__i); } let __ret: [G; OUT_228] = unsafe { *(record.function_queries[228].output_at(__i).as_ptr() as *const [G; OUT_228]) }; __ret }, _ => aiur_fn_228(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_227] = { let __args: [G; IN_227] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[227].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[227].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[227].bump_multiplicity(__i); } let __ret: [G; OUT_227] = unsafe { *(record.function_queries[227].output_at(__i).as_ptr() as *const [G; OUT_227]) }; __ret }, _ => aiur_fn_227(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_230] = { let __args: [G; IN_230] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[230].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[230].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[230].bump_multiplicity(__i); } let __ret: [G; OUT_230] = unsafe { *(record.function_queries[230].output_at(__i).as_ptr() as *const [G; OUT_230]) }; __ret }, _ => aiur_fn_230(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_229] = { let __args: [G; IN_229] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[229].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[229].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[229].bump_multiplicity(__i); } let __ret: [G; OUT_229] = unsafe { *(record.function_queries[229].output_at(__i).as_ptr() as *const [G; OUT_229]) }; __ret }, _ => aiur_fn_229(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_231] = [__v_7]; - record.function_queries[231].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_230] = [__v_7]; + record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_231] = [__v_0]; - record.function_queries[231].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_230] = [__v_0]; + record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_231] = [__v_0]; - record.function_queries[231].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_230] = [__v_0]; + record.function_queries[230].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_232: usize = 1; -const IN_232: usize = 1; -const OUT_232: usize = 4; -fn aiur_fn_232( - inp: [G; IN_232], +const INPUT_SIZE_231: usize = 1; +const IN_231: usize = 1; +const OUT_231: usize = 4; +fn aiur_fn_231( + inp: [G; IN_231], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_232], ExecError> { +) -> Result<[G; OUT_231], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __v_1: G = G::from_u64(0); - let __r_arr: [G; OUT_126] = { let __args: [G; IN_126] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[126].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[126].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[126].bump_multiplicity(__i); } let __ret: [G; OUT_126] = unsafe { *(record.function_queries[126].output_at(__i).as_ptr() as *const [G; OUT_126]) }; __ret }, _ => aiur_fn_126(__args, record, io_buffer, __cu)? } }; - let __v_2: G = __r_arr[0]; - let __v_3: G = __r_arr[1]; - let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_126] = { let __args: [G; IN_126] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[126].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[126].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[126].bump_multiplicity(__i); } let __ret: [G; OUT_126] = unsafe { *(record.function_queries[126].output_at(__i).as_ptr() as *const [G; OUT_126]) }; __ret }, _ => aiur_fn_126(__args, record, io_buffer, __cu)? } }; - let __v_5: G = __r_arr[0]; - let __v_6: G = __r_arr[1]; - let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_126] = { let __args: [G; IN_126] = [__v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[126].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[126].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[126].bump_multiplicity(__i); } let __ret: [G; OUT_126] = unsafe { *(record.function_queries[126].output_at(__i).as_ptr() as *const [G; OUT_126]) }; __ret }, _ => aiur_fn_126(__args, record, io_buffer, __cu)? } }; - let __v_8: G = __r_arr[0]; - let __v_9: G = __r_arr[1]; - let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_126] = { let __args: [G; IN_126] = [__v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[126].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[126].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[126].bump_multiplicity(__i); } let __ret: [G; OUT_126] = unsafe { *(record.function_queries[126].output_at(__i).as_ptr() as *const [G; OUT_126]) }; __ret }, _ => aiur_fn_126(__args, record, io_buffer, __cu)? } }; - let __v_11: G = __r_arr[0]; - let __v_12: G = __r_arr[1]; - let __ret: [G; OUT_232] = [__v_2, __v_5, __v_8, __v_11]; - record.function_queries[232].finish(&inp[..], &__ret[..], !unconstrained); + let __gb: [u8; 8] = __v_0.as_canonical_u64().to_le_bytes(); + let __v_1: G = G::from_u8(__gb[0]); + let __v_2: G = G::from_u8(__gb[1]); + let __v_3: G = G::from_u8(__gb[2]); + let __v_4: G = G::from_u8(__gb[3]); + let __v_5: G = G::from_u8(__gb[4]); + let __v_6: G = G::from_u8(__gb[5]); + let __v_7: G = G::from_u8(__gb[6]); + let __v_8: G = G::from_u8(__gb[7]); + let __ret: [G; OUT_231] = [__v_1, __v_2, __v_3, __v_4]; + record.function_queries[231].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_233: usize = 1; -const IN_233: usize = 1; -const OUT_233: usize = 1; -fn aiur_fn_233( - inp: [G; IN_233], +const INPUT_SIZE_232: usize = 1; +const IN_232: usize = 1; +const OUT_232: usize = 1; +fn aiur_fn_232( + inp: [G; IN_232], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_233], ExecError> { +) -> Result<[G; OUT_232], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_232] = { let __args: [G; IN_232] = [__v_0]; let __cu = true; let __hit = record.function_queries[232].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_232] = unsafe { *(record.function_queries[232].output_at(__i).as_ptr() as *const [G; OUT_232]) }; __ret }, _ => aiur_fn_232(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_231] = { let __args: [G; IN_231] = [__v_0]; let __cu = true; let __hit = record.function_queries[231].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_231] = unsafe { *(record.function_queries[231].output_at(__i).as_ptr() as *const [G; OUT_231]) }; __ret }, _ => aiur_fn_231(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = __r_arr[1]; let __v_3: G = __r_arr[2]; @@ -22048,25 +22002,25 @@ fn aiur_fn_233( let __v_30: G = { let __values: [G; 10] = [__v_22, __v_6, __v_8, __v_10, __v_12, __v_23, __v_24, __v_25, __v_26, __v_29]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_30]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __ret: [G; OUT_233] = [__v_31]; - record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_232] = [__v_31]; + record.function_queries[232].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_234: usize = 2; -const IN_234: usize = 2; -const OUT_234: usize = 2; -fn aiur_fn_234( - inp: [G; IN_234], +const INPUT_SIZE_233: usize = 2; +const IN_233: usize = 2; +const OUT_233: usize = 2; +fn aiur_fn_233( + inp: [G; IN_233], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_234], ExecError> { +) -> Result<[G; OUT_233], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; @@ -22078,13 +22032,13 @@ fn aiur_fn_234( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_210] = { let __args: [G; IN_210] = []; let __cu = unconstrained; let __hit = record.function_queries[210].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[210].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[210].bump_multiplicity(__i); } let __ret: [G; OUT_210] = unsafe { *(record.function_queries[210].output_at(__i).as_ptr() as *const [G; OUT_210]) }; __ret }, _ => aiur_fn_210(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_209] = { let __args: [G; IN_209] = []; let __cu = unconstrained; let __hit = record.function_queries[209].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[209].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[209].bump_multiplicity(__i); } let __ret: [G; OUT_209] = unsafe { *(record.function_queries[209].output_at(__i).as_ptr() as *const [G; OUT_209]) }; __ret }, _ => aiur_fn_209(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { @@ -22092,8 +22046,8 @@ fn aiur_fn_234( let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(1); let __v_15: G = { let __values: [G; 3] = [__v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_234] = [__v_12, __v_15]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_12, __v_15]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22101,14 +22055,14 @@ fn aiur_fn_234( let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(1); let __v_15: G = { let __values: [G; 3] = [__v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_234] = [__v_12, __v_15]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_12, __v_15]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_211] = { let __args: [G; IN_211] = []; let __cu = unconstrained; let __hit = record.function_queries[211].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[211].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[211].bump_multiplicity(__i); } let __ret: [G; OUT_211] = unsafe { *(record.function_queries[211].output_at(__i).as_ptr() as *const [G; OUT_211]) }; __ret }, _ => aiur_fn_211(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_210] = { let __args: [G; IN_210] = []; let __cu = unconstrained; let __hit = record.function_queries[210].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[210].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[210].bump_multiplicity(__i); } let __ret: [G; OUT_210] = unsafe { *(record.function_queries[210].output_at(__i).as_ptr() as *const [G; OUT_210]) }; __ret }, _ => aiur_fn_210(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; @@ -22118,19 +22072,19 @@ fn aiur_fn_234( let __v_14: G = G::from_u64(1); let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 3] = [__v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_234] = [__v_13, __v_16]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_13, __v_16]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 3u64 => { let __v_14: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __r_arr: [G; OUT_235] = { let __args: [G; IN_235] = [__v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[235].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[235].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[235].bump_multiplicity(__i); } let __ret: [G; OUT_235] = unsafe { *(record.function_queries[235].output_at(__i).as_ptr() as *const [G; OUT_235]) }; __ret }, _ => aiur_fn_235(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_234] = { let __args: [G; IN_234] = [__v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[234].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[234].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[234].bump_multiplicity(__i); } let __ret: [G; OUT_234] = unsafe { *(record.function_queries[234].output_at(__i).as_ptr() as *const [G; OUT_234]) }; __ret }, _ => aiur_fn_234(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = __r_arr[1]; match __v_16.as_canonical_u64() { @@ -22139,30 +22093,30 @@ fn aiur_fn_234( let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(1); let __v_21: G = { let __values: [G; 3] = [__v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_234] = [__v_18, __v_21]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_18, __v_21]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_18: G = G::from_u64(2); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_234] = { let __args: [G; IN_234] = [__v_19, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[234].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[234].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[234].bump_multiplicity(__i); } let __ret: [G; OUT_234] = unsafe { *(record.function_queries[234].output_at(__i).as_ptr() as *const [G; OUT_234]) }; __ret }, _ => aiur_fn_234(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_233] = { let __args: [G; IN_233] = [__v_19, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[233].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[233].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[233].bump_multiplicity(__i); } let __ret: [G; OUT_233] = unsafe { *(record.function_queries[233].output_at(__i).as_ptr() as *const [G; OUT_233]) }; __ret }, _ => aiur_fn_233(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = __r_arr[1]; match __v_20.as_canonical_u64() { 0u64 => { let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_234] = [__v_22, __v_21]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_22, __v_21]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_22: G = G::from_u64(1); - let __r_arr: [G; OUT_240] = { let __args: [G; IN_240] = [__v_17, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[240].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[240].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[240].bump_multiplicity(__i); } let __ret: [G; OUT_240] = unsafe { *(record.function_queries[240].output_at(__i).as_ptr() as *const [G; OUT_240]) }; __ret }, _ => aiur_fn_240(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_239] = { let __args: [G; IN_239] = [__v_17, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[239].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[239].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[239].bump_multiplicity(__i); } let __ret: [G; OUT_239] = unsafe { *(record.function_queries[239].output_at(__i).as_ptr() as *const [G; OUT_239]) }; __ret }, _ => aiur_fn_239(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_234] = [__v_22, __v_23]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_22, __v_23]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22180,8 +22134,8 @@ fn aiur_fn_234( let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_234] = [__v_14, __v_17]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_14, __v_17]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22195,59 +22149,59 @@ fn aiur_fn_234( let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 3] = [__v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_234] = [__v_9, __v_12]; - record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_233] = [__v_9, __v_12]; + record.function_queries[233].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_235: usize = 2; -const IN_235: usize = 2; -const OUT_235: usize = 2; -fn aiur_fn_235( - inp: [G; IN_235], +const INPUT_SIZE_234: usize = 2; +const IN_234: usize = 2; +const OUT_234: usize = 2; +fn aiur_fn_234( + inp: [G; IN_234], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_235], ExecError> { +) -> Result<[G; OUT_234], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_236] = { let __args: [G; IN_236] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[236].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[236].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[236].bump_multiplicity(__i); } let __ret: [G; OUT_236] = unsafe { *(record.function_queries[236].output_at(__i).as_ptr() as *const [G; OUT_236]) }; __ret }, _ => aiur_fn_236(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_235] = { let __args: [G; IN_235] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[235].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[235].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[235].bump_multiplicity(__i); } let __ret: [G; OUT_235] = unsafe { *(record.function_queries[235].output_at(__i).as_ptr() as *const [G; OUT_235]) }; __ret }, _ => aiur_fn_235(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; match __v_2.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_235] = [__v_4, __v_3]; - record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_234] = [__v_4, __v_3]; + record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_236] = { let __args: [G; IN_236] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[236].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[236].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[236].bump_multiplicity(__i); } let __ret: [G; OUT_236] = unsafe { *(record.function_queries[236].output_at(__i).as_ptr() as *const [G; OUT_236]) }; __ret }, _ => aiur_fn_236(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_235] = { let __args: [G; IN_235] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[235].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[235].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[235].bump_multiplicity(__i); } let __ret: [G; OUT_235] = unsafe { *(record.function_queries[235].output_at(__i).as_ptr() as *const [G; OUT_235]) }; __ret }, _ => aiur_fn_235(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_235] = [__v_5, __v_6]; - record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_234] = [__v_5, __v_6]; + record.function_queries[234].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_236: usize = 1; -const IN_236: usize = 1; -const OUT_236: usize = 2; -fn aiur_fn_236( - inp: [G; IN_236], +const INPUT_SIZE_235: usize = 1; +const IN_235: usize = 1; +const OUT_235: usize = 2; +fn aiur_fn_235( + inp: [G; IN_235], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_236], ExecError> { +) -> Result<[G; OUT_235], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -22264,7 +22218,7 @@ fn aiur_fn_236( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_209] = { let __args: [G; IN_209] = []; let __cu = unconstrained; let __hit = record.function_queries[209].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[209].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[209].bump_multiplicity(__i); } let __ret: [G; OUT_209] = unsafe { *(record.function_queries[209].output_at(__i).as_ptr() as *const [G; OUT_209]) }; __ret }, _ => aiur_fn_209(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_208] = { let __args: [G; IN_208] = []; let __cu = unconstrained; let __hit = record.function_queries[208].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[208].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[208].bump_multiplicity(__i); } let __ret: [G; OUT_208] = unsafe { *(record.function_queries[208].output_at(__i).as_ptr() as *const [G; OUT_208]) }; __ret }, _ => aiur_fn_208(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; @@ -22272,8 +22226,8 @@ fn aiur_fn_236( 0u64 => { let __v_11: G = G::from_u64(0); let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_236] = [__v_11, __v_12]; - record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_235] = [__v_11, __v_12]; + record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22286,18 +22240,18 @@ fn aiur_fn_236( 7u64 => { match __v_12.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_237] = { let __args: [G; IN_237] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[237].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[237].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[237].bump_multiplicity(__i); } let __ret: [G; OUT_237] = unsafe { *(record.function_queries[237].output_at(__i).as_ptr() as *const [G; OUT_237]) }; __ret }, _ => aiur_fn_237(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_236] = { let __args: [G; IN_236] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[236].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[236].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[236].bump_multiplicity(__i); } let __ret: [G; OUT_236] = unsafe { *(record.function_queries[236].output_at(__i).as_ptr() as *const [G; OUT_236]) }; __ret }, _ => aiur_fn_236(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __ret: [G; OUT_236] = [__v_15, __v_16]; - record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_235] = [__v_15, __v_16]; + record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); let __v_16: G = G::from_u64(0); - let __ret: [G; OUT_236] = [__v_15, __v_16]; - record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_235] = [__v_15, __v_16]; + record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22305,8 +22259,8 @@ fn aiur_fn_236( _ => { let __v_15: G = G::from_u64(0); let __v_16: G = G::from_u64(0); - let __ret: [G; OUT_236] = [__v_15, __v_16]; - record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_235] = [__v_15, __v_16]; + record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22316,8 +22270,8 @@ fn aiur_fn_236( _ => { let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_236] = [__v_9, __v_10]; - record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_235] = [__v_9, __v_10]; + record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22325,23 +22279,23 @@ fn aiur_fn_236( _ => { let __v_5: G = G::from_u64(0); let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_236] = [__v_5, __v_6]; - record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_235] = [__v_5, __v_6]; + record.function_queries[235].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_237: usize = 1; -const IN_237: usize = 1; -const OUT_237: usize = 2; -fn aiur_fn_237( - inp: [G; IN_237], +const INPUT_SIZE_236: usize = 1; +const IN_236: usize = 1; +const OUT_236: usize = 2; +fn aiur_fn_236( + inp: [G; IN_236], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_237], ExecError> { +) -> Result<[G; OUT_236], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 10] = { let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 10 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 10] = __args[..10].try_into().unwrap(); __arr }; @@ -22379,8 +22333,8 @@ fn aiur_fn_237( 0u64 => { let __v_26: G = G::from_u64(0); let __v_27: G = G::from_u64(0); - let __ret: [G; OUT_237] = [__v_26, __v_27]; - record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_236] = [__v_26, __v_27]; + record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22395,8 +22349,8 @@ fn aiur_fn_237( match __v_33.as_canonical_u64() { 1u64 => { let __v_34: G = G::from_u64(1); - let __ret: [G; OUT_237] = [__v_34, __v_31]; - record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_236] = [__v_34, __v_31]; + record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22406,8 +22360,8 @@ fn aiur_fn_237( 0u64 => { let __v_36: G = G::from_u64(0); let __v_37: G = G::from_u64(0); - let __ret: [G; OUT_237] = [__v_36, __v_37]; - record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_236] = [__v_36, __v_37]; + record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22416,15 +22370,15 @@ fn aiur_fn_237( match __v_37.as_canonical_u64() { 1u64 => { let __v_38: G = G::from_u64(1); - let __ret: [G; OUT_237] = [__v_38, __v_31]; - record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_236] = [__v_38, __v_31]; + record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_38: G = G::from_u64(0); let __v_39: G = G::from_u64(0); - let __ret: [G; OUT_237] = [__v_38, __v_39]; - record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_236] = [__v_38, __v_39]; + record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22438,8 +22392,8 @@ fn aiur_fn_237( _ => { let __v_21: G = G::from_u64(0); let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_237] = [__v_21, __v_22]; - record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_236] = [__v_21, __v_22]; + record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22447,23 +22401,23 @@ fn aiur_fn_237( _ => { let __v_11: G = G::from_u64(0); let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_237] = [__v_11, __v_12]; - record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_236] = [__v_11, __v_12]; + record.function_queries[236].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_238: usize = 2; -const IN_238: usize = 2; -const OUT_238: usize = 2; -fn aiur_fn_238( - inp: [G; IN_238], +const INPUT_SIZE_237: usize = 2; +const IN_237: usize = 2; +const OUT_237: usize = 2; +fn aiur_fn_237( + inp: [G; IN_237], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_238], ExecError> { +) -> Result<[G; OUT_237], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -22471,8 +22425,8 @@ fn aiur_fn_238( let __v_3: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_238] = [__v_0, __v_1]; - record.function_queries[238].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_237] = [__v_0, __v_1]; + record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22480,59 +22434,59 @@ fn aiur_fn_238( let __v_5: G = (__v_0 - __v_4); let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 + __v_6); - let __r_arr: [G; OUT_238] = { let __args: [G; IN_238] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[238].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[238].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[238].bump_multiplicity(__i); } let __ret: [G; OUT_238] = unsafe { *(record.function_queries[238].output_at(__i).as_ptr() as *const [G; OUT_238]) }; __ret }, _ => aiur_fn_238(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_237] = { let __args: [G; IN_237] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[237].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[237].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[237].bump_multiplicity(__i); } let __ret: [G; OUT_237] = unsafe { *(record.function_queries[237].output_at(__i).as_ptr() as *const [G; OUT_237]) }; __ret }, _ => aiur_fn_237(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_238] = [__v_8, __v_9]; - record.function_queries[238].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_237] = [__v_8, __v_9]; + record.function_queries[237].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_239: usize = 1; -const IN_239: usize = 1; -const OUT_239: usize = 4; -fn aiur_fn_239( - inp: [G; IN_239], +const INPUT_SIZE_238: usize = 1; +const IN_238: usize = 1; +const OUT_238: usize = 4; +fn aiur_fn_238( + inp: [G; IN_238], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_239], ExecError> { +) -> Result<[G; OUT_238], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(0); - let __r_arr: [G; OUT_238] = { let __args: [G; IN_238] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[238].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[238].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[238].bump_multiplicity(__i); } let __ret: [G; OUT_238] = unsafe { *(record.function_queries[238].output_at(__i).as_ptr() as *const [G; OUT_238]) }; __ret }, _ => aiur_fn_238(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_237] = { let __args: [G; IN_237] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[237].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[237].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[237].bump_multiplicity(__i); } let __ret: [G; OUT_237] = unsafe { *(record.function_queries[237].output_at(__i).as_ptr() as *const [G; OUT_237]) }; __ret }, _ => aiur_fn_237(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_238] = { let __args: [G; IN_238] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[238].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[238].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[238].bump_multiplicity(__i); } let __ret: [G; OUT_238] = unsafe { *(record.function_queries[238].output_at(__i).as_ptr() as *const [G; OUT_238]) }; __ret }, _ => aiur_fn_238(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_237] = { let __args: [G; IN_237] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[237].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[237].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[237].bump_multiplicity(__i); } let __ret: [G; OUT_237] = unsafe { *(record.function_queries[237].output_at(__i).as_ptr() as *const [G; OUT_237]) }; __ret }, _ => aiur_fn_237(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_238] = { let __args: [G; IN_238] = [__v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[238].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[238].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[238].bump_multiplicity(__i); } let __ret: [G; OUT_238] = unsafe { *(record.function_queries[238].output_at(__i).as_ptr() as *const [G; OUT_238]) }; __ret }, _ => aiur_fn_238(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_237] = { let __args: [G; IN_237] = [__v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[237].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[237].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[237].bump_multiplicity(__i); } let __ret: [G; OUT_237] = unsafe { *(record.function_queries[237].output_at(__i).as_ptr() as *const [G; OUT_237]) }; __ret }, _ => aiur_fn_237(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_239] = [__v_2, __v_5, __v_8, __v_9]; - record.function_queries[239].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_238] = [__v_2, __v_5, __v_8, __v_9]; + record.function_queries[238].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_240: usize = 2; -const IN_240: usize = 2; -const OUT_240: usize = 1; -fn aiur_fn_240( - inp: [G; IN_240], +const INPUT_SIZE_239: usize = 2; +const IN_239: usize = 2; +const OUT_239: usize = 1; +fn aiur_fn_239( + inp: [G; IN_239], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_240], ExecError> { +) -> Result<[G; OUT_239], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_239] = { let __args: [G; IN_239] = [__v_0]; let __cu = true; let __hit = record.function_queries[239].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_239] = unsafe { *(record.function_queries[239].output_at(__i).as_ptr() as *const [G; OUT_239]) }; __ret }, _ => aiur_fn_239(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_238] = { let __args: [G; IN_238] = [__v_0]; let __cu = true; let __hit = record.function_queries[238].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_238] = unsafe { *(record.function_queries[238].output_at(__i).as_ptr() as *const [G; OUT_238]) }; __ret }, _ => aiur_fn_238(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -22587,8 +22541,8 @@ fn aiur_fn_240( 1u64 => { let __v_37: G = G::from_u64(0); let __v_38: G = { let __values: [G; 3] = [__v_37, __v_0, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_240] = [__v_38]; - record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_239] = [__v_38]; + record.function_queries[239].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22604,8 +22558,8 @@ fn aiur_fn_240( let __v_44: G = G::from_u64(0); let __v_45: G = { let __values: [G; 3] = [__v_44, __v_40, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_46: G = { let __values: [G; 3] = [__v_43, __v_42, __v_45]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_240] = [__v_46]; - record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_239] = [__v_46]; + record.function_queries[239].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22625,8 +22579,8 @@ fn aiur_fn_240( let __v_50: G = { let __values: [G; 3] = [__v_49, __v_42, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_51: G = { let __values: [G; 3] = [__v_48, __v_44, __v_50]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_52: G = { let __values: [G; 3] = [__v_47, __v_46, __v_51]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_240] = [__v_52]; - record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_239] = [__v_52]; + record.function_queries[239].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22646,8 +22600,8 @@ fn aiur_fn_240( let __v_54: G = { let __values: [G; 3] = [__v_51, __v_44, __v_53]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_55: G = { let __values: [G; 3] = [__v_50, __v_46, __v_54]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_56: G = { let __values: [G; 3] = [__v_49, __v_48, __v_55]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_240] = [__v_56]; - record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_239] = [__v_56]; + record.function_queries[239].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22658,212 +22612,212 @@ fn aiur_fn_240( }) } -const INPUT_SIZE_241: usize = 1; -const IN_241: usize = 1; -const OUT_241: usize = 1; -fn aiur_fn_241( - inp: [G; IN_241], +const INPUT_SIZE_240: usize = 1; +const IN_240: usize = 1; +const OUT_240: usize = 1; +fn aiur_fn_240( + inp: [G; IN_240], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_241], ExecError> { +) -> Result<[G; OUT_240], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_3]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_3]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_5]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_5]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_7]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_7]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_163] = { let __args: [G; IN_163] = []; let __cu = unconstrained; let __hit = record.function_queries[163].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[163].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[163].bump_multiplicity(__i); } let __ret: [G; OUT_163] = unsafe { *(record.function_queries[163].output_at(__i).as_ptr() as *const [G; OUT_163]) }; __ret }, _ => aiur_fn_163(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_9]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_9]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_164] = { let __args: [G; IN_164] = []; let __cu = unconstrained; let __hit = record.function_queries[164].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[164].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[164].bump_multiplicity(__i); } let __ret: [G; OUT_164] = unsafe { *(record.function_queries[164].output_at(__i).as_ptr() as *const [G; OUT_164]) }; __ret }, _ => aiur_fn_164(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_163] = { let __args: [G; IN_163] = []; let __cu = unconstrained; let __hit = record.function_queries[163].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[163].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[163].bump_multiplicity(__i); } let __ret: [G; OUT_163] = unsafe { *(record.function_queries[163].output_at(__i).as_ptr() as *const [G; OUT_163]) }; __ret }, _ => aiur_fn_163(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_11]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_11]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_168] = { let __args: [G; IN_168] = []; let __cu = unconstrained; let __hit = record.function_queries[168].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[168].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[168].bump_multiplicity(__i); } let __ret: [G; OUT_168] = unsafe { *(record.function_queries[168].output_at(__i).as_ptr() as *const [G; OUT_168]) }; __ret }, _ => aiur_fn_168(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { let __v_13: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_13]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_13]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_166] = { let __args: [G; IN_166] = []; let __cu = unconstrained; let __hit = record.function_queries[166].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[166].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[166].bump_multiplicity(__i); } let __ret: [G; OUT_166] = unsafe { *(record.function_queries[166].output_at(__i).as_ptr() as *const [G; OUT_166]) }; __ret }, _ => aiur_fn_166(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; match __v_14.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_15]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_15]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_165] = { let __args: [G; IN_165] = []; let __cu = unconstrained; let __hit = record.function_queries[165].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[165].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[165].bump_multiplicity(__i); } let __ret: [G; OUT_165] = unsafe { *(record.function_queries[165].output_at(__i).as_ptr() as *const [G; OUT_165]) }; __ret }, _ => aiur_fn_165(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_164] = { let __args: [G; IN_164] = []; let __cu = unconstrained; let __hit = record.function_queries[164].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[164].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[164].bump_multiplicity(__i); } let __ret: [G; OUT_164] = unsafe { *(record.function_queries[164].output_at(__i).as_ptr() as *const [G; OUT_164]) }; __ret }, _ => aiur_fn_164(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; match __v_16.as_canonical_u64() { 1u64 => { let __v_17: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_17]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_17]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_166] = { let __args: [G; IN_166] = []; let __cu = unconstrained; let __hit = record.function_queries[166].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[166].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[166].bump_multiplicity(__i); } let __ret: [G; OUT_166] = unsafe { *(record.function_queries[166].output_at(__i).as_ptr() as *const [G; OUT_166]) }; __ret }, _ => aiur_fn_166(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_165] = { let __args: [G; IN_165] = []; let __cu = unconstrained; let __hit = record.function_queries[165].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[165].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[165].bump_multiplicity(__i); } let __ret: [G; OUT_165] = unsafe { *(record.function_queries[165].output_at(__i).as_ptr() as *const [G; OUT_165]) }; __ret }, _ => aiur_fn_165(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; match __v_18.as_canonical_u64() { 1u64 => { let __v_19: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_19]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_19]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_174] = { let __args: [G; IN_174] = []; let __cu = unconstrained; let __hit = record.function_queries[174].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[174].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[174].bump_multiplicity(__i); } let __ret: [G; OUT_174] = unsafe { *(record.function_queries[174].output_at(__i).as_ptr() as *const [G; OUT_174]) }; __ret }, _ => aiur_fn_174(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_173] = { let __args: [G; IN_173] = []; let __cu = unconstrained; let __hit = record.function_queries[173].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[173].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[173].bump_multiplicity(__i); } let __ret: [G; OUT_173] = unsafe { *(record.function_queries[173].output_at(__i).as_ptr() as *const [G; OUT_173]) }; __ret }, _ => aiur_fn_173(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; match __v_20.as_canonical_u64() { 1u64 => { let __v_21: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_21]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_21]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_175] = { let __args: [G; IN_175] = []; let __cu = unconstrained; let __hit = record.function_queries[175].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[175].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[175].bump_multiplicity(__i); } let __ret: [G; OUT_175] = unsafe { *(record.function_queries[175].output_at(__i).as_ptr() as *const [G; OUT_175]) }; __ret }, _ => aiur_fn_175(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_174] = { let __args: [G; IN_174] = []; let __cu = unconstrained; let __hit = record.function_queries[174].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[174].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[174].bump_multiplicity(__i); } let __ret: [G; OUT_174] = unsafe { *(record.function_queries[174].output_at(__i).as_ptr() as *const [G; OUT_174]) }; __ret }, _ => aiur_fn_174(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; match __v_22.as_canonical_u64() { 1u64 => { let __v_23: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_23]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_23]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_169] = { let __args: [G; IN_169] = []; let __cu = unconstrained; let __hit = record.function_queries[169].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[169].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[169].bump_multiplicity(__i); } let __ret: [G; OUT_169] = unsafe { *(record.function_queries[169].output_at(__i).as_ptr() as *const [G; OUT_169]) }; __ret }, _ => aiur_fn_169(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_168] = { let __args: [G; IN_168] = []; let __cu = unconstrained; let __hit = record.function_queries[168].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[168].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[168].bump_multiplicity(__i); } let __ret: [G; OUT_168] = unsafe { *(record.function_queries[168].output_at(__i).as_ptr() as *const [G; OUT_168]) }; __ret }, _ => aiur_fn_168(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; match __v_24.as_canonical_u64() { 1u64 => { let __v_25: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_25]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_25]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_170] = { let __args: [G; IN_170] = []; let __cu = unconstrained; let __hit = record.function_queries[170].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[170].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[170].bump_multiplicity(__i); } let __ret: [G; OUT_170] = unsafe { *(record.function_queries[170].output_at(__i).as_ptr() as *const [G; OUT_170]) }; __ret }, _ => aiur_fn_170(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_169] = { let __args: [G; IN_169] = []; let __cu = unconstrained; let __hit = record.function_queries[169].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[169].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[169].bump_multiplicity(__i); } let __ret: [G; OUT_169] = unsafe { *(record.function_queries[169].output_at(__i).as_ptr() as *const [G; OUT_169]) }; __ret }, _ => aiur_fn_169(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; match __v_26.as_canonical_u64() { 1u64 => { let __v_27: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_27]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_27]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_171] = { let __args: [G; IN_171] = []; let __cu = unconstrained; let __hit = record.function_queries[171].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[171].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[171].bump_multiplicity(__i); } let __ret: [G; OUT_171] = unsafe { *(record.function_queries[171].output_at(__i).as_ptr() as *const [G; OUT_171]) }; __ret }, _ => aiur_fn_171(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_170] = { let __args: [G; IN_170] = []; let __cu = unconstrained; let __hit = record.function_queries[170].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[170].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[170].bump_multiplicity(__i); } let __ret: [G; OUT_170] = unsafe { *(record.function_queries[170].output_at(__i).as_ptr() as *const [G; OUT_170]) }; __ret }, _ => aiur_fn_170(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; match __v_28.as_canonical_u64() { 1u64 => { let __v_29: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_29]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_29]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_172] = { let __args: [G; IN_172] = []; let __cu = unconstrained; let __hit = record.function_queries[172].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[172].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[172].bump_multiplicity(__i); } let __ret: [G; OUT_172] = unsafe { *(record.function_queries[172].output_at(__i).as_ptr() as *const [G; OUT_172]) }; __ret }, _ => aiur_fn_172(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_171] = { let __args: [G; IN_171] = []; let __cu = unconstrained; let __hit = record.function_queries[171].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[171].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[171].bump_multiplicity(__i); } let __ret: [G; OUT_171] = unsafe { *(record.function_queries[171].output_at(__i).as_ptr() as *const [G; OUT_171]) }; __ret }, _ => aiur_fn_171(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_29]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; match __v_30.as_canonical_u64() { 1u64 => { let __v_31: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_31]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_31]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_173] = { let __args: [G; IN_173] = []; let __cu = unconstrained; let __hit = record.function_queries[173].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[173].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[173].bump_multiplicity(__i); } let __ret: [G; OUT_173] = unsafe { *(record.function_queries[173].output_at(__i).as_ptr() as *const [G; OUT_173]) }; __ret }, _ => aiur_fn_173(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_172] = { let __args: [G; IN_172] = []; let __cu = unconstrained; let __hit = record.function_queries[172].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[172].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[172].bump_multiplicity(__i); } let __ret: [G; OUT_172] = unsafe { *(record.function_queries[172].output_at(__i).as_ptr() as *const [G; OUT_172]) }; __ret }, _ => aiur_fn_172(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; match __v_32.as_canonical_u64() { 1u64 => { let __v_33: G = G::from_u64(1); - let __ret: [G; OUT_241] = [__v_33]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_33]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_33: G = G::from_u64(0); - let __ret: [G; OUT_241] = [__v_33]; - record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_240] = [__v_33]; + record.function_queries[240].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -22900,54 +22854,54 @@ fn aiur_fn_241( }) } -const INPUT_SIZE_242: usize = 1; -const IN_242: usize = 1; -const OUT_242: usize = 1; -fn aiur_fn_242( - inp: [G; IN_242], +const INPUT_SIZE_241: usize = 1; +const IN_241: usize = 1; +const OUT_241: usize = 1; +fn aiur_fn_241( + inp: [G; IN_241], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_242], ExecError> { +) -> Result<[G; OUT_241], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_152] = { let __args: [G; IN_152] = []; let __cu = unconstrained; let __hit = record.function_queries[152].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[152].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[152].bump_multiplicity(__i); } let __ret: [G; OUT_152] = unsafe { *(record.function_queries[152].output_at(__i).as_ptr() as *const [G; OUT_152]) }; __ret }, _ => aiur_fn_152(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_151] = { let __args: [G; IN_151] = []; let __cu = unconstrained; let __hit = record.function_queries[151].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[151].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[151].bump_multiplicity(__i); } let __ret: [G; OUT_151] = unsafe { *(record.function_queries[151].output_at(__i).as_ptr() as *const [G; OUT_151]) }; __ret }, _ => aiur_fn_151(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_153] = { let __args: [G; IN_153] = []; let __cu = unconstrained; let __hit = record.function_queries[153].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[153].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[153].bump_multiplicity(__i); } let __ret: [G; OUT_153] = unsafe { *(record.function_queries[153].output_at(__i).as_ptr() as *const [G; OUT_153]) }; __ret }, _ => aiur_fn_153(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_152] = { let __args: [G; IN_152] = []; let __cu = unconstrained; let __hit = record.function_queries[152].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[152].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[152].bump_multiplicity(__i); } let __ret: [G; OUT_152] = unsafe { *(record.function_queries[152].output_at(__i).as_ptr() as *const [G; OUT_152]) }; __ret }, _ => aiur_fn_152(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_154] = { let __args: [G; IN_154] = []; let __cu = unconstrained; let __hit = record.function_queries[154].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[154].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[154].bump_multiplicity(__i); } let __ret: [G; OUT_154] = unsafe { *(record.function_queries[154].output_at(__i).as_ptr() as *const [G; OUT_154]) }; __ret }, _ => aiur_fn_154(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_153] = { let __args: [G; IN_153] = []; let __cu = unconstrained; let __hit = record.function_queries[153].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[153].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[153].bump_multiplicity(__i); } let __ret: [G; OUT_153] = unsafe { *(record.function_queries[153].output_at(__i).as_ptr() as *const [G; OUT_153]) }; __ret }, _ => aiur_fn_153(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_155] = { let __args: [G; IN_155] = []; let __cu = unconstrained; let __hit = record.function_queries[155].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[155].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[155].bump_multiplicity(__i); } let __ret: [G; OUT_155] = unsafe { *(record.function_queries[155].output_at(__i).as_ptr() as *const [G; OUT_155]) }; __ret }, _ => aiur_fn_155(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_154] = { let __args: [G; IN_154] = []; let __cu = unconstrained; let __hit = record.function_queries[154].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[154].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[154].bump_multiplicity(__i); } let __ret: [G; OUT_154] = unsafe { *(record.function_queries[154].output_at(__i).as_ptr() as *const [G; OUT_154]) }; __ret }, _ => aiur_fn_154(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_156] = { let __args: [G; IN_156] = []; let __cu = unconstrained; let __hit = record.function_queries[156].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[156].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[156].bump_multiplicity(__i); } let __ret: [G; OUT_156] = unsafe { *(record.function_queries[156].output_at(__i).as_ptr() as *const [G; OUT_156]) }; __ret }, _ => aiur_fn_156(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_155] = { let __args: [G; IN_155] = []; let __cu = unconstrained; let __hit = record.function_queries[155].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[155].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[155].bump_multiplicity(__i); } let __ret: [G; OUT_155] = unsafe { *(record.function_queries[155].output_at(__i).as_ptr() as *const [G; OUT_155]) }; __ret }, _ => aiur_fn_155(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_157] = { let __args: [G; IN_157] = []; let __cu = unconstrained; let __hit = record.function_queries[157].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[157].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[157].bump_multiplicity(__i); } let __ret: [G; OUT_157] = unsafe { *(record.function_queries[157].output_at(__i).as_ptr() as *const [G; OUT_157]) }; __ret }, _ => aiur_fn_157(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_156] = { let __args: [G; IN_156] = []; let __cu = unconstrained; let __hit = record.function_queries[156].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[156].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[156].bump_multiplicity(__i); } let __ret: [G; OUT_156] = unsafe { *(record.function_queries[156].output_at(__i).as_ptr() as *const [G; OUT_156]) }; __ret }, _ => aiur_fn_156(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_158] = { let __args: [G; IN_158] = []; let __cu = unconstrained; let __hit = record.function_queries[158].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[158].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[158].bump_multiplicity(__i); } let __ret: [G; OUT_158] = unsafe { *(record.function_queries[158].output_at(__i).as_ptr() as *const [G; OUT_158]) }; __ret }, _ => aiur_fn_158(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_157] = { let __args: [G; IN_157] = []; let __cu = unconstrained; let __hit = record.function_queries[157].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[157].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[157].bump_multiplicity(__i); } let __ret: [G; OUT_157] = unsafe { *(record.function_queries[157].output_at(__i).as_ptr() as *const [G; OUT_157]) }; __ret }, _ => aiur_fn_157(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __r_arr: [G; OUT_159] = { let __args: [G; IN_159] = []; let __cu = unconstrained; let __hit = record.function_queries[159].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[159].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[159].bump_multiplicity(__i); } let __ret: [G; OUT_159] = unsafe { *(record.function_queries[159].output_at(__i).as_ptr() as *const [G; OUT_159]) }; __ret }, _ => aiur_fn_159(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_158] = { let __args: [G; IN_158] = []; let __cu = unconstrained; let __hit = record.function_queries[158].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[158].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[158].bump_multiplicity(__i); } let __ret: [G; OUT_158] = unsafe { *(record.function_queries[158].output_at(__i).as_ptr() as *const [G; OUT_158]) }; __ret }, _ => aiur_fn_158(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __r_arr: [G; OUT_160] = { let __args: [G; IN_160] = []; let __cu = unconstrained; let __hit = record.function_queries[160].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[160].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[160].bump_multiplicity(__i); } let __ret: [G; OUT_160] = unsafe { *(record.function_queries[160].output_at(__i).as_ptr() as *const [G; OUT_160]) }; __ret }, _ => aiur_fn_160(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_159] = { let __args: [G; IN_159] = []; let __cu = unconstrained; let __hit = record.function_queries[159].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[159].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[159].bump_multiplicity(__i); } let __ret: [G; OUT_159] = unsafe { *(record.function_queries[159].output_at(__i).as_ptr() as *const [G; OUT_159]) }; __ret }, _ => aiur_fn_159(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_160] = { let __args: [G; IN_160] = []; let __cu = unconstrained; let __hit = record.function_queries[160].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[160].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[160].bump_multiplicity(__i); } let __ret: [G; OUT_160] = unsafe { *(record.function_queries[160].output_at(__i).as_ptr() as *const [G; OUT_160]) }; __ret }, _ => aiur_fn_160(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; @@ -22960,21 +22914,21 @@ fn aiur_fn_242( let __v_27: G = (__v_6 + __v_26); let __v_28: G = (__v_4 + __v_27); let __v_29: G = (__v_2 + __v_28); - let __ret: [G; OUT_242] = [__v_29]; - record.function_queries[242].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_241] = [__v_29]; + record.function_queries[241].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_243: usize = 1; -const IN_243: usize = 1; -const OUT_243: usize = 2; -fn aiur_fn_243( - inp: [G; IN_243], +const INPUT_SIZE_242: usize = 1; +const IN_242: usize = 1; +const OUT_242: usize = 2; +fn aiur_fn_242( + inp: [G; IN_242], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_243], ExecError> { +) -> Result<[G; OUT_242], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -22987,8 +22941,8 @@ fn aiur_fn_243( match __v_2.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_243] = [__v_5, __v_3]; - record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_242] = [__v_5, __v_3]; + record.function_queries[242].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -22996,14 +22950,14 @@ fn aiur_fn_243( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 10] = [__v_6, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_243] = [__v_5, __v_8]; - record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_242] = [__v_5, __v_8]; + record.function_queries[242].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 2u64 => { - let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_146] = { let __args: [G; IN_146] = []; let __cu = unconstrained; let __hit = record.function_queries[146].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[146].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[146].bump_multiplicity(__i); } let __ret: [G; OUT_146] = unsafe { *(record.function_queries[146].output_at(__i).as_ptr() as *const [G; OUT_146]) }; __ret }, _ => aiur_fn_146(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; @@ -23013,8 +22967,8 @@ fn aiur_fn_243( let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 10] = [__v_8, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_243] = [__v_7, __v_10]; - record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_242] = [__v_7, __v_10]; + record.function_queries[242].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23022,18 +22976,18 @@ fn aiur_fn_243( let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 10] = [__v_8, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_243] = [__v_7, __v_10]; - record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_242] = [__v_7, __v_10]; + record.function_queries[242].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 3u64 => { - let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_243] = [__v_5, __v_6]; - record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_242] = [__v_5, __v_6]; + record.function_queries[242].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23041,23 +22995,23 @@ fn aiur_fn_243( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 10] = [__v_6, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_243] = [__v_5, __v_8]; - record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_242] = [__v_5, __v_8]; + record.function_queries[242].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_244: usize = 2; -const IN_244: usize = 2; -const OUT_244: usize = 2; -fn aiur_fn_244( - inp: [G; IN_244], +const INPUT_SIZE_243: usize = 2; +const IN_243: usize = 2; +const OUT_243: usize = 2; +fn aiur_fn_243( + inp: [G; IN_243], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_244], ExecError> { +) -> Result<[G; OUT_243], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -23068,13 +23022,13 @@ fn aiur_fn_244( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; match __v_8.as_canonical_u64() { @@ -23082,8 +23036,8 @@ fn aiur_fn_244( let __v_10: G = G::from_u64(1); let __r_arr: [G; OUT_116] = { let __args: [G; IN_116] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[116].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[116].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[116].bump_multiplicity(__i); } let __ret: [G; OUT_116] = unsafe { *(record.function_queries[116].output_at(__i).as_ptr() as *const [G; OUT_116]) }; __ret }, _ => aiur_fn_116(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_244] = [__v_10, __v_11]; - record.function_queries[244].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_243] = [__v_10, __v_11]; + record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23091,8 +23045,8 @@ fn aiur_fn_244( let __v_11: G = G::from_u64(1); let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 10] = [__v_11, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_244] = [__v_10, __v_13]; - record.function_queries[244].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_243] = [__v_10, __v_13]; + record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23102,8 +23056,8 @@ fn aiur_fn_244( let __v_9: G = G::from_u64(1); let __v_10: G = G::from_u64(1); let __v_11: G = { let __values: [G; 10] = [__v_9, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_244] = [__v_8, __v_11]; - record.function_queries[244].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_243] = [__v_8, __v_11]; + record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23113,44 +23067,44 @@ fn aiur_fn_244( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 10] = [__v_7, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_244] = [__v_6, __v_9]; - record.function_queries[244].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_243] = [__v_6, __v_9]; + record.function_queries[243].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_245: usize = 1; -const IN_245: usize = 1; -const OUT_245: usize = 1; -fn aiur_fn_245( - inp: [G; IN_245], +const INPUT_SIZE_244: usize = 1; +const IN_244: usize = 1; +const OUT_244: usize = 1; +fn aiur_fn_244( + inp: [G; IN_244], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_245], ExecError> { +) -> Result<[G; OUT_244], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(7); let __v_2: G = G::from_u64(0); let __v_3: G = G::from_u64(0); let __v_4: G = { let __values: [G; 4] = [__v_1, __v_2, __v_0, __v_3]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_245] = [__v_4]; - record.function_queries[245].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_244] = [__v_4]; + record.function_queries[244].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_246: usize = 1; -const IN_246: usize = 1; -const OUT_246: usize = 3; -fn aiur_fn_246( - inp: [G; IN_246], +const INPUT_SIZE_245: usize = 1; +const IN_245: usize = 1; +const OUT_245: usize = 3; +fn aiur_fn_245( + inp: [G; IN_245], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_246], ExecError> { +) -> Result<[G; OUT_245], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -23167,12 +23121,12 @@ fn aiur_fn_246( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; @@ -23182,12 +23136,12 @@ fn aiur_fn_246( let __v_14: G = G::from_u64(0); let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_246] = [__v_13, __v_14, __v_15]; - record.function_queries[246].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_245] = [__v_13, __v_14, __v_15]; + record.function_queries[245].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_151] = { let __args: [G; IN_151] = []; let __cu = unconstrained; let __hit = record.function_queries[151].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[151].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[151].bump_multiplicity(__i); } let __ret: [G; OUT_151] = unsafe { *(record.function_queries[151].output_at(__i).as_ptr() as *const [G; OUT_151]) }; __ret }, _ => aiur_fn_151(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; @@ -23199,8 +23153,8 @@ fn aiur_fn_246( let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_246] = [__v_15, __v_16, __v_18]; - record.function_queries[246].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_245] = [__v_15, __v_16, __v_18]; + record.function_queries[245].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23209,8 +23163,8 @@ fn aiur_fn_246( let __v_17: G = G::from_u64(1); let __v_18: G = G::from_u64(1); let __v_19: G = { let __values: [G; 10] = [__v_17, __v_18, __v_18, __v_18, __v_18, __v_18, __v_18, __v_18, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_246] = [__v_15, __v_16, __v_19]; - record.function_queries[246].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_245] = [__v_15, __v_16, __v_19]; + record.function_queries[245].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23223,8 +23177,8 @@ fn aiur_fn_246( let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(1); let __v_15: G = { let __values: [G; 10] = [__v_13, __v_14, __v_14, __v_14, __v_14, __v_14, __v_14, __v_14, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_246] = [__v_11, __v_12, __v_15]; - record.function_queries[246].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_245] = [__v_11, __v_12, __v_15]; + record.function_queries[245].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23235,8 +23189,8 @@ fn aiur_fn_246( let __v_11: G = G::from_u64(1); let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 10] = [__v_11, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_246] = [__v_9, __v_10, __v_13]; - record.function_queries[246].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_245] = [__v_9, __v_10, __v_13]; + record.function_queries[245].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23247,41 +23201,41 @@ fn aiur_fn_246( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 10] = [__v_7, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_246] = [__v_5, __v_6, __v_9]; - record.function_queries[246].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_245] = [__v_5, __v_6, __v_9]; + record.function_queries[245].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_247: usize = 2; -const IN_247: usize = 2; -const OUT_247: usize = 1; -fn aiur_fn_247( - inp: [G; IN_247], +const INPUT_SIZE_246: usize = 2; +const IN_246: usize = 2; +const OUT_246: usize = 1; +fn aiur_fn_246( + inp: [G; IN_246], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_247], ExecError> { +) -> Result<[G; OUT_246], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = (__v_3 - __v_4); let __v_6: G = (__v_0 * __v_5); let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_6.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; break '__mc_0 [__v_7]; }, _ => { - let __r_arr: [G; OUT_151] = { let __args: [G; IN_151] = []; let __cu = unconstrained; let __hit = record.function_queries[151].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[151].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[151].bump_multiplicity(__i); } let __ret: [G; OUT_151] = unsafe { *(record.function_queries[151].output_at(__i).as_ptr() as *const [G; OUT_151]) }; __ret }, _ => aiur_fn_151(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; break '__mc_0 [__v_7]; }, @@ -23309,25 +23263,25 @@ fn aiur_fn_247( let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_10, __v_7, __v_13, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_9, __v_15, __v_16, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_247] = [__v_18]; - record.function_queries[247].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_246] = [__v_18]; + record.function_queries[246].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_248: usize = 4; -const IN_248: usize = 4; -const OUT_248: usize = 1; -fn aiur_fn_248( - inp: [G; IN_248], +const INPUT_SIZE_247: usize = 4; +const IN_247: usize = 4; +const OUT_247: usize = 1; +fn aiur_fn_247( + inp: [G; IN_247], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_248], ExecError> { +) -> Result<[G; OUT_247], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -23338,10 +23292,10 @@ fn aiur_fn_248( 0u64 => { let __r_arr: [G; OUT_118] = { let __args: [G; IN_118] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[118].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[118].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[118].bump_multiplicity(__i); } let __ret: [G; OUT_118] = unsafe { *(record.function_queries[118].output_at(__i).as_ptr() as *const [G; OUT_118]) }; __ret }, _ => aiur_fn_118(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_248] = [__v_6]; - record.function_queries[248].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_247] = [__v_6]; + record.function_queries[247].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23351,19 +23305,19 @@ fn aiur_fn_248( 1u64 => { let __r_arr: [G; OUT_123] = { let __args: [G; IN_123] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[123].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[123].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[123].bump_multiplicity(__i); } let __ret: [G; OUT_123] = unsafe { *(record.function_queries[123].output_at(__i).as_ptr() as *const [G; OUT_123]) }; __ret }, _ => aiur_fn_123(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_248] = [__v_7]; - record.function_queries[248].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_247] = [__v_7]; + record.function_queries[247].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __r_arr: [G; OUT_123] = { let __args: [G; IN_123] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[123].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[123].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[123].bump_multiplicity(__i); } let __ret: [G; OUT_123] = unsafe { *(record.function_queries[123].output_at(__i).as_ptr() as *const [G; OUT_123]) }; __ret }, _ => aiur_fn_123(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_248] = [__v_7]; - record.function_queries[248].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_247] = [__v_7]; + record.function_queries[247].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23372,34 +23326,34 @@ fn aiur_fn_248( }) } -const INPUT_SIZE_249: usize = 3; -const IN_249: usize = 3; -const OUT_249: usize = 1; -fn aiur_fn_249( - inp: [G; IN_249], +const INPUT_SIZE_248: usize = 3; +const IN_248: usize = 3; +const OUT_248: usize = 1; +fn aiur_fn_248( + inp: [G; IN_248], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_249], ExecError> { +) -> Result<[G; OUT_248], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_249] = [__v_4]; - record.function_queries[249].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_248] = [__v_4]; + record.function_queries[248].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_5 - __v_6); let __v_8: G = (__v_0 * __v_7); @@ -23408,18 +23362,18 @@ fn aiur_fn_249( let __v_9: G = G::from_u64(0); let __r_arr: [G; OUT_123] = { let __args: [G; IN_123] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[123].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[123].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[123].bump_multiplicity(__i); } let __ret: [G; OUT_123] = unsafe { *(record.function_queries[123].output_at(__i).as_ptr() as *const [G; OUT_123]) }; __ret }, _ => aiur_fn_123(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_249] = [__v_11]; - record.function_queries[249].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_248] = [__v_11]; + record.function_queries[248].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_9, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_9, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_249] = [__v_10]; - record.function_queries[249].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_248] = [__v_10]; + record.function_queries[248].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23428,21 +23382,21 @@ fn aiur_fn_249( }) } -const INPUT_SIZE_250: usize = 4; -const IN_250: usize = 4; -const OUT_250: usize = 1; -fn aiur_fn_250( - inp: [G; IN_250], +const INPUT_SIZE_249: usize = 4; +const IN_249: usize = 4; +const OUT_249: usize = 1; +fn aiur_fn_249( + inp: [G; IN_249], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_250], ExecError> { +) -> Result<[G; OUT_249], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { @@ -23450,19 +23404,19 @@ fn aiur_fn_250( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 10] = [__v_6, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_250] = [__v_9]; - record.function_queries[250].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_249] = [__v_9]; + record.function_queries[249].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = (__v_7 - __v_8); let __v_10: G = (__v_0 * __v_9); @@ -23484,48 +23438,48 @@ fn aiur_fn_250( let __v_15: G = (__v_2 - __v_14); let __v_16: G = (__v_0 + __v_15); let __v_17: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = (__v_17 - __v_18); let __v_20: G = (__v_16 * __v_19); - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_20, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_20, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_250] = [__v_21]; - record.function_queries[250].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_249] = [__v_21]; + record.function_queries[249].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_251: usize = 3; -const IN_251: usize = 3; -const OUT_251: usize = 1; -fn aiur_fn_251( - inp: [G; IN_251], +const INPUT_SIZE_250: usize = 3; +const IN_250: usize = 3; +const OUT_250: usize = 1; +fn aiur_fn_250( + inp: [G; IN_250], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_251], ExecError> { +) -> Result<[G; OUT_250], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_251] = [__v_4]; - record.function_queries[251].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_250] = [__v_4]; + record.function_queries[250].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_5 - __v_6); let __v_8: G = (__v_0 * __v_7); @@ -23556,7 +23510,7 @@ fn aiur_fn_251( let __v_22: G = { let __values: [G; 10] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_21]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __r_arr: [G; OUT_116] = { let __args: [G; IN_116] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[116].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[116].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[116].bump_multiplicity(__i); } let __ret: [G; OUT_116] = unsafe { *(record.function_queries[116].output_at(__i).as_ptr() as *const [G; OUT_116]) }; __ret }, _ => aiur_fn_116(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_23, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_23, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __r_arr: [G; OUT_124] = { let __args: [G; IN_124] = [__v_24, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[124].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[124].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[124].bump_multiplicity(__i); } let __ret: [G; OUT_124] = unsafe { *(record.function_queries[124].output_at(__i).as_ptr() as *const [G; OUT_124]) }; __ret }, _ => aiur_fn_124(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; @@ -23565,18 +23519,18 @@ fn aiur_fn_251( let __v_26: G = G::from_u64(1); let __r_arr: [G; OUT_123] = { let __args: [G; IN_123] = [__v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[123].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[123].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[123].bump_multiplicity(__i); } let __ret: [G; OUT_123] = unsafe { *(record.function_queries[123].output_at(__i).as_ptr() as *const [G; OUT_123]) }; __ret }, _ => aiur_fn_123(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_26, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_26, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_251] = [__v_28]; - record.function_queries[251].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_250] = [__v_28]; + record.function_queries[250].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_26: G = G::from_u64(0); - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_26, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_26, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __ret: [G; OUT_251] = [__v_27]; - record.function_queries[251].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_250] = [__v_27]; + record.function_queries[250].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23585,20 +23539,20 @@ fn aiur_fn_251( }) } -const INPUT_SIZE_252: usize = 3; -const IN_252: usize = 3; -const OUT_252: usize = 1; -fn aiur_fn_252( - inp: [G; IN_252], +const INPUT_SIZE_251: usize = 3; +const IN_251: usize = 3; +const OUT_251: usize = 1; +fn aiur_fn_251( + inp: [G; IN_251], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_252], ExecError> { +) -> Result<[G; OUT_251], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { @@ -23606,17 +23560,17 @@ fn aiur_fn_252( let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 10] = [__v_5, __v_6, __v_6, __v_6, __v_6, __v_6, __v_6, __v_6, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_252] = [__v_8]; - record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_251] = [__v_8]; + record.function_queries[251].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_5 - __v_6); let __v_8: G = (__v_0 * __v_7); @@ -23632,10 +23586,10 @@ fn aiur_fn_252( } }; let __v_9: G = __mc_out___mc_0[0]; - let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = (__v_11 - __v_12); let __v_14: G = (__v_0 * __v_13); @@ -23652,7 +23606,7 @@ fn aiur_fn_252( }; let __v_15: G = __mc_out___mc_1[0]; let __v_16: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = (__v_16 - __v_17); let __v_19: G = (__v_0 * __v_18); @@ -23671,16 +23625,16 @@ fn aiur_fn_252( let __v_32: G = { let __values: [G; 10] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_31]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __r_arr: [G; OUT_116] = { let __args: [G; IN_116] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[116].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[116].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[116].bump_multiplicity(__i); } let __ret: [G; OUT_116] = unsafe { *(record.function_queries[116].output_at(__i).as_ptr() as *const [G; OUT_116]) }; __ret }, _ => aiur_fn_116(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; - let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_33, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_33, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __r_arr: [G; OUT_124] = { let __args: [G; IN_124] = [__v_34, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[124].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[124].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[124].bump_multiplicity(__i); } let __ret: [G; OUT_124] = unsafe { *(record.function_queries[124].output_at(__i).as_ptr() as *const [G; OUT_124]) }; __ret }, _ => aiur_fn_124(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; match __v_35.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_19, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_19, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_36: G = __r_arr[0]; - let __ret: [G; OUT_252] = [__v_36]; - record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_251] = [__v_36]; + record.function_queries[251].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23698,10 +23652,10 @@ fn aiur_fn_252( let __v_47: G = G::from_u64(1); let __v_48: G = { let __values: [G; 10] = [__v_46, __v_47, __v_47, __v_47, __v_47, __v_47, __v_47, __v_47, __v_47, __v_47]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_49: G = { let __values: [G; 10] = [__v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_48]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_248] = { let __args: [G; IN_248] = [__v_19, __v_15, __v_36, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[248].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[248].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[248].bump_multiplicity(__i); } let __ret: [G; OUT_248] = unsafe { *(record.function_queries[248].output_at(__i).as_ptr() as *const [G; OUT_248]) }; __ret }, _ => aiur_fn_248(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_19, __v_15, __v_36, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_252] = [__v_50]; - record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_251] = [__v_50]; + record.function_queries[251].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23710,28 +23664,28 @@ fn aiur_fn_252( }) } -const INPUT_SIZE_253: usize = 3; -const IN_253: usize = 3; -const OUT_253: usize = 2; -fn aiur_fn_253( - inp: [G; IN_253], +const INPUT_SIZE_252: usize = 3; +const IN_252: usize = 3; +const OUT_252: usize = 2; +fn aiur_fn_252( + inp: [G; IN_252], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_253], ExecError> { +) -> Result<[G; OUT_252], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_155] = { let __args: [G; IN_155] = []; let __cu = unconstrained; let __hit = record.function_queries[155].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[155].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[155].bump_multiplicity(__i); } let __ret: [G; OUT_155] = unsafe { *(record.function_queries[155].output_at(__i).as_ptr() as *const [G; OUT_155]) }; __ret }, _ => aiur_fn_155(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_154] = { let __args: [G; IN_154] = []; let __cu = unconstrained; let __hit = record.function_queries[154].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[154].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[154].bump_multiplicity(__i); } let __ret: [G; OUT_154] = unsafe { *(record.function_queries[154].output_at(__i).as_ptr() as *const [G; OUT_154]) }; __ret }, _ => aiur_fn_154(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_160] = { let __args: [G; IN_160] = []; let __cu = unconstrained; let __hit = record.function_queries[160].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[160].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[160].bump_multiplicity(__i); } let __ret: [G; OUT_160] = unsafe { *(record.function_queries[160].output_at(__i).as_ptr() as *const [G; OUT_160]) }; __ret }, _ => aiur_fn_160(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_159] = { let __args: [G; IN_159] = []; let __cu = unconstrained; let __hit = record.function_queries[159].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[159].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[159].bump_multiplicity(__i); } let __ret: [G; OUT_159] = unsafe { *(record.function_queries[159].output_at(__i).as_ptr() as *const [G; OUT_159]) }; __ret }, _ => aiur_fn_159(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; @@ -23747,27 +23701,27 @@ fn aiur_fn_253( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_253] = [__v_12, __v_16]; - record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_252] = [__v_12, __v_16]; + record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; match __v_14.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_160] = { let __args: [G; IN_160] = []; let __cu = unconstrained; let __hit = record.function_queries[160].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[160].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[160].bump_multiplicity(__i); } let __ret: [G; OUT_160] = unsafe { *(record.function_queries[160].output_at(__i).as_ptr() as *const [G; OUT_160]) }; __ret }, _ => aiur_fn_160(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_159] = { let __args: [G; IN_159] = []; let __cu = unconstrained; let __hit = record.function_queries[159].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[159].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[159].bump_multiplicity(__i); } let __ret: [G; OUT_159] = unsafe { *(record.function_queries[159].output_at(__i).as_ptr() as *const [G; OUT_159]) }; __ret }, _ => aiur_fn_159(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_18.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; break '__mc_0 [__v_19]; }, @@ -23775,11 +23729,11 @@ fn aiur_fn_253( let __v_19: G = G::from_u64(1); let __v_20: G = (__v_19 - __v_15); let __v_21: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = (__v_21 - __v_22); let __v_24: G = (__v_20 * __v_23); - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_24, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_24, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; break '__mc_0 [__v_25]; }, @@ -23788,12 +23742,12 @@ fn aiur_fn_253( let __v_19: G = __mc_out___mc_0[0]; let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_3, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_3, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_253] = [__v_20, __v_23]; - record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_252] = [__v_20, __v_23]; + record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23802,8 +23756,8 @@ fn aiur_fn_253( let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_18, __v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_253] = [__v_17, __v_21]; - record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_252] = [__v_17, __v_21]; + record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23820,25 +23774,25 @@ fn aiur_fn_253( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_253] = [__v_12, __v_16]; - record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_252] = [__v_12, __v_16]; + record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; match __v_14.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_0, __v_3, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_253] = { let __args: [G; IN_253] = [__v_0, __v_3, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[253].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[253].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[253].bump_multiplicity(__i); } let __ret: [G; OUT_253] = unsafe { *(record.function_queries[253].output_at(__i).as_ptr() as *const [G; OUT_253]) }; __ret }, _ => aiur_fn_253(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; - let __ret: [G; OUT_253] = [__v_17, __v_18]; - record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_252] = [__v_17, __v_18]; + record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23847,8 +23801,8 @@ fn aiur_fn_253( let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_18, __v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_253] = [__v_17, __v_21]; - record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_252] = [__v_17, __v_21]; + record.function_queries[252].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -23859,29 +23813,29 @@ fn aiur_fn_253( }) } -const INPUT_SIZE_254: usize = 4; -const IN_254: usize = 4; -const OUT_254: usize = 2; -fn aiur_fn_254( - inp: [G; IN_254], +const INPUT_SIZE_253: usize = 4; +const IN_253: usize = 4; +const OUT_253: usize = 2; +fn aiur_fn_253( + inp: [G; IN_253], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_254], ExecError> { +) -> Result<[G; OUT_253], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_158] = { let __args: [G; IN_158] = []; let __cu = unconstrained; let __hit = record.function_queries[158].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[158].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[158].bump_multiplicity(__i); } let __ret: [G; OUT_158] = unsafe { *(record.function_queries[158].output_at(__i).as_ptr() as *const [G; OUT_158]) }; __ret }, _ => aiur_fn_158(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_157] = { let __args: [G; IN_157] = []; let __cu = unconstrained; let __hit = record.function_queries[157].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[157].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[157].bump_multiplicity(__i); } let __ret: [G; OUT_157] = unsafe { *(record.function_queries[157].output_at(__i).as_ptr() as *const [G; OUT_157]) }; __ret }, _ => aiur_fn_157(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_159] = { let __args: [G; IN_159] = []; let __cu = unconstrained; let __hit = record.function_queries[159].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[159].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[159].bump_multiplicity(__i); } let __ret: [G; OUT_159] = unsafe { *(record.function_queries[159].output_at(__i).as_ptr() as *const [G; OUT_159]) }; __ret }, _ => aiur_fn_159(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_158] = { let __args: [G; IN_158] = []; let __cu = unconstrained; let __hit = record.function_queries[158].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[158].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[158].bump_multiplicity(__i); } let __ret: [G; OUT_158] = unsafe { *(record.function_queries[158].output_at(__i).as_ptr() as *const [G; OUT_158]) }; __ret }, _ => aiur_fn_158(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_160] = { let __args: [G; IN_160] = []; let __cu = unconstrained; let __hit = record.function_queries[160].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[160].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[160].bump_multiplicity(__i); } let __ret: [G; OUT_160] = unsafe { *(record.function_queries[160].output_at(__i).as_ptr() as *const [G; OUT_160]) }; __ret }, _ => aiur_fn_160(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; @@ -23890,31 +23844,31 @@ fn aiur_fn_254( match __v_11.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; match __v_14.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_158] = { let __args: [G; IN_158] = []; let __cu = unconstrained; let __hit = record.function_queries[158].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[158].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[158].bump_multiplicity(__i); } let __ret: [G; OUT_158] = unsafe { *(record.function_queries[158].output_at(__i).as_ptr() as *const [G; OUT_158]) }; __ret }, _ => aiur_fn_158(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_157] = { let __args: [G; IN_157] = []; let __cu = unconstrained; let __hit = record.function_queries[157].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[157].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[157].bump_multiplicity(__i); } let __ret: [G; OUT_157] = unsafe { *(record.function_queries[157].output_at(__i).as_ptr() as *const [G; OUT_157]) }; __ret }, _ => aiur_fn_157(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_17.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_251] = { let __args: [G; IN_251] = [__v_2, __v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[251].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[251].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[251].bump_multiplicity(__i); } let __ret: [G; OUT_251] = unsafe { *(record.function_queries[251].output_at(__i).as_ptr() as *const [G; OUT_251]) }; __ret }, _ => aiur_fn_251(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_250] = { let __args: [G; IN_250] = [__v_2, __v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[250].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[250].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[250].bump_multiplicity(__i); } let __ret: [G; OUT_250] = unsafe { *(record.function_queries[250].output_at(__i).as_ptr() as *const [G; OUT_250]) }; __ret }, _ => aiur_fn_250(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; break '__mc_0 [__v_18]; }, _ => { - let __r_arr: [G; OUT_159] = { let __args: [G; IN_159] = []; let __cu = unconstrained; let __hit = record.function_queries[159].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[159].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[159].bump_multiplicity(__i); } let __ret: [G; OUT_159] = unsafe { *(record.function_queries[159].output_at(__i).as_ptr() as *const [G; OUT_159]) }; __ret }, _ => aiur_fn_159(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_158] = { let __args: [G; IN_158] = []; let __cu = unconstrained; let __hit = record.function_queries[158].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[158].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[158].bump_multiplicity(__i); } let __ret: [G; OUT_158] = unsafe { *(record.function_queries[158].output_at(__i).as_ptr() as *const [G; OUT_158]) }; __ret }, _ => aiur_fn_158(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; match __v_19.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_252] = { let __args: [G; IN_252] = [__v_2, __v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[252].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[252].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[252].bump_multiplicity(__i); } let __ret: [G; OUT_252] = unsafe { *(record.function_queries[252].output_at(__i).as_ptr() as *const [G; OUT_252]) }; __ret }, _ => aiur_fn_252(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_251] = { let __args: [G; IN_251] = [__v_2, __v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[251].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[251].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[251].bump_multiplicity(__i); } let __ret: [G; OUT_251] = unsafe { *(record.function_queries[251].output_at(__i).as_ptr() as *const [G; OUT_251]) }; __ret }, _ => aiur_fn_251(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; break '__mc_0 [__v_20]; }, @@ -23933,15 +23887,15 @@ fn aiur_fn_254( let __v_31: G = { let __values: [G; 10] = [__v_29, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30, __v_30]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_32: G = { let __values: [G; 10] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_31]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_33: G = G::from_u64(1); - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_15, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_15, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = (__v_33 - __v_35); let __v_37: G = (__v_2 * __v_36); - let __r_arr: [G; OUT_138] = { let __args: [G; IN_138] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[138].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[138].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[138].bump_multiplicity(__i); } let __ret: [G; OUT_138] = unsafe { *(record.function_queries[138].output_at(__i).as_ptr() as *const [G; OUT_138]) }; __ret }, _ => aiur_fn_138(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; break '__mc_0 [__v_39]; }, @@ -23952,12 +23906,12 @@ fn aiur_fn_254( let __v_18: G = __mc_out___mc_0[0]; let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_18, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_18, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_254] = [__v_19, __v_22]; - record.function_queries[254].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_253] = [__v_19, __v_22]; + record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -23966,34 +23920,34 @@ fn aiur_fn_254( let __v_18: G = G::from_u64(0); let __v_19: G = G::from_u64(0); let __v_20: G = { let __values: [G; 4] = [__v_17, __v_18, __v_19, __v_19]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_254] = [__v_16, __v_20]; - record.function_queries[254].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_253] = [__v_16, __v_20]; + record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_12: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; match __v_14.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_152] = { let __args: [G; IN_152] = []; let __cu = unconstrained; let __hit = record.function_queries[152].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[152].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[152].bump_multiplicity(__i); } let __ret: [G; OUT_152] = unsafe { *(record.function_queries[152].output_at(__i).as_ptr() as *const [G; OUT_152]) }; __ret }, _ => aiur_fn_152(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_151] = { let __args: [G; IN_151] = []; let __cu = unconstrained; let __hit = record.function_queries[151].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[151].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[151].bump_multiplicity(__i); } let __ret: [G; OUT_151] = unsafe { *(record.function_queries[151].output_at(__i).as_ptr() as *const [G; OUT_151]) }; __ret }, _ => aiur_fn_151(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __mc_out___mc_1: [G; 1] = '__mc_1: { match __v_18.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_248] = { let __args: [G; IN_248] = [__v_2, __v_3, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[248].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[248].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[248].bump_multiplicity(__i); } let __ret: [G; OUT_248] = unsafe { *(record.function_queries[248].output_at(__i).as_ptr() as *const [G; OUT_248]) }; __ret }, _ => aiur_fn_248(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_2, __v_3, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; break '__mc_1 [__v_19]; }, _ => { - let __r_arr: [G; OUT_153] = { let __args: [G; IN_153] = []; let __cu = unconstrained; let __hit = record.function_queries[153].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[153].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[153].bump_multiplicity(__i); } let __ret: [G; OUT_153] = unsafe { *(record.function_queries[153].output_at(__i).as_ptr() as *const [G; OUT_153]) }; __ret }, _ => aiur_fn_153(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_152] = { let __args: [G; IN_152] = []; let __cu = unconstrained; let __hit = record.function_queries[152].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[152].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[152].bump_multiplicity(__i); } let __ret: [G; OUT_152] = unsafe { *(record.function_queries[152].output_at(__i).as_ptr() as *const [G; OUT_152]) }; __ret }, _ => aiur_fn_152(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; @@ -24002,16 +23956,16 @@ fn aiur_fn_254( let __v_21: G = G::from_u64(1); let __v_22: G = (__v_21 - __v_15); let __v_23: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = (__v_23 - __v_24); let __v_26: G = (__v_22 * __v_25); - let __r_arr: [G; OUT_248] = { let __args: [G; IN_248] = [__v_2, __v_3, __v_26, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[248].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[248].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[248].bump_multiplicity(__i); } let __ret: [G; OUT_248] = unsafe { *(record.function_queries[248].output_at(__i).as_ptr() as *const [G; OUT_248]) }; __ret }, _ => aiur_fn_248(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_2, __v_3, __v_26, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; break '__mc_1 [__v_27]; }, _ => { - let __r_arr: [G; OUT_154] = { let __args: [G; IN_154] = []; let __cu = unconstrained; let __hit = record.function_queries[154].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[154].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[154].bump_multiplicity(__i); } let __ret: [G; OUT_154] = unsafe { *(record.function_queries[154].output_at(__i).as_ptr() as *const [G; OUT_154]) }; __ret }, _ => aiur_fn_154(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_153] = { let __args: [G; IN_153] = []; let __cu = unconstrained; let __hit = record.function_queries[153].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[153].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[153].bump_multiplicity(__i); } let __ret: [G; OUT_153] = unsafe { *(record.function_queries[153].output_at(__i).as_ptr() as *const [G; OUT_153]) }; __ret }, _ => aiur_fn_153(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; @@ -24023,34 +23977,34 @@ fn aiur_fn_254( let __v_26: G = (__v_15 - __v_25); let __v_27: G = (__v_2 + __v_26); let __v_28: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = (__v_28 - __v_29); let __v_31: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = (__v_31 - __v_32); let __v_34: G = (__v_30 * __v_33); let __v_35: G = (__v_27 * __v_34); - let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_3, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_128] = { let __args: [G; IN_128] = [__v_3, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[128].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[128].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[128].bump_multiplicity(__i); } let __ret: [G; OUT_128] = unsafe { *(record.function_queries[128].output_at(__i).as_ptr() as *const [G; OUT_128]) }; __ret }, _ => aiur_fn_128(__args, record, io_buffer, __cu)? } }; let __v_36: G = __r_arr[0]; - let __r_arr: [G; OUT_247] = { let __args: [G; IN_247] = [__v_35, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[247].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[247].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[247].bump_multiplicity(__i); } let __ret: [G; OUT_247] = unsafe { *(record.function_queries[247].output_at(__i).as_ptr() as *const [G; OUT_247]) }; __ret }, _ => aiur_fn_247(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_246] = { let __args: [G; IN_246] = [__v_35, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[246].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[246].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[246].bump_multiplicity(__i); } let __ret: [G; OUT_246] = unsafe { *(record.function_queries[246].output_at(__i).as_ptr() as *const [G; OUT_246]) }; __ret }, _ => aiur_fn_246(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; break '__mc_1 [__v_37]; }, _ => { - let __r_arr: [G; OUT_156] = { let __args: [G; IN_156] = []; let __cu = unconstrained; let __hit = record.function_queries[156].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[156].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[156].bump_multiplicity(__i); } let __ret: [G; OUT_156] = unsafe { *(record.function_queries[156].output_at(__i).as_ptr() as *const [G; OUT_156]) }; __ret }, _ => aiur_fn_156(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_155] = { let __args: [G; IN_155] = []; let __cu = unconstrained; let __hit = record.function_queries[155].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[155].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[155].bump_multiplicity(__i); } let __ret: [G; OUT_155] = unsafe { *(record.function_queries[155].output_at(__i).as_ptr() as *const [G; OUT_155]) }; __ret }, _ => aiur_fn_155(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; match __v_24.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_249] = { let __args: [G; IN_249] = [__v_2, __v_3, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[249].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[249].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[249].bump_multiplicity(__i); } let __ret: [G; OUT_249] = unsafe { *(record.function_queries[249].output_at(__i).as_ptr() as *const [G; OUT_249]) }; __ret }, _ => aiur_fn_249(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_248] = { let __args: [G; IN_248] = [__v_2, __v_3, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[248].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[248].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[248].bump_multiplicity(__i); } let __ret: [G; OUT_248] = unsafe { *(record.function_queries[248].output_at(__i).as_ptr() as *const [G; OUT_248]) }; __ret }, _ => aiur_fn_248(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; break '__mc_1 [__v_25]; }, _ => { - let __r_arr: [G; OUT_250] = { let __args: [G; IN_250] = [__v_2, __v_3, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[250].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[250].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[250].bump_multiplicity(__i); } let __ret: [G; OUT_250] = unsafe { *(record.function_queries[250].output_at(__i).as_ptr() as *const [G; OUT_250]) }; __ret }, _ => aiur_fn_250(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_249] = { let __args: [G; IN_249] = [__v_2, __v_3, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[249].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[249].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[249].bump_multiplicity(__i); } let __ret: [G; OUT_249] = unsafe { *(record.function_queries[249].output_at(__i).as_ptr() as *const [G; OUT_249]) }; __ret }, _ => aiur_fn_249(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; break '__mc_1 [__v_25]; }, @@ -24065,12 +24019,12 @@ fn aiur_fn_254( let __v_19: G = __mc_out___mc_1[0]; let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_254] = [__v_20, __v_23]; - record.function_queries[254].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_253] = [__v_20, __v_23]; + record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -24079,8 +24033,8 @@ fn aiur_fn_254( let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_18, __v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_254] = [__v_17, __v_21]; - record.function_queries[254].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_253] = [__v_17, __v_21]; + record.function_queries[253].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24089,15 +24043,15 @@ fn aiur_fn_254( }) } -const INPUT_SIZE_255: usize = 2; -const IN_255: usize = 2; -const OUT_255: usize = 1; -fn aiur_fn_255( - inp: [G; IN_255], +const INPUT_SIZE_254: usize = 2; +const IN_254: usize = 2; +const OUT_254: usize = 1; +fn aiur_fn_254( + inp: [G; IN_254], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_255], ExecError> { +) -> Result<[G; OUT_254], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -24107,18 +24061,18 @@ fn aiur_fn_255( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_255] = [__v_0]; - record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_254] = [__v_0]; + record.function_queries[254].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(3); let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 4] = [__v_5, __v_0, __v_3, __v_6]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_7, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_7, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_255] = [__v_8]; - record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_254] = [__v_8]; + record.function_queries[254].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -24128,20 +24082,20 @@ fn aiur_fn_255( }) } -const INPUT_SIZE_256: usize = 3; -const IN_256: usize = 3; -const OUT_256: usize = 2; -fn aiur_fn_256( - inp: [G; IN_256], +const INPUT_SIZE_255: usize = 3; +const IN_255: usize = 3; +const OUT_255: usize = 2; +fn aiur_fn_255( + inp: [G; IN_255], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_256], ExecError> { +) -> Result<[G; OUT_255], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; @@ -24152,14 +24106,14 @@ fn aiur_fn_256( let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_5, __v_8]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_5, __v_8]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_163] = { let __args: [G; IN_163] = []; let __cu = unconstrained; let __hit = record.function_queries[163].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[163].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[163].bump_multiplicity(__i); } let __ret: [G; OUT_163] = unsafe { *(record.function_queries[163].output_at(__i).as_ptr() as *const [G; OUT_163]) }; __ret }, _ => aiur_fn_163(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; @@ -24170,210 +24124,210 @@ fn aiur_fn_256( let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_7, __v_10]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_7, __v_10]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_164] = { let __args: [G; IN_164] = []; let __cu = unconstrained; let __hit = record.function_queries[164].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[164].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[164].bump_multiplicity(__i); } let __ret: [G; OUT_164] = unsafe { *(record.function_queries[164].output_at(__i).as_ptr() as *const [G; OUT_164]) }; __ret }, _ => aiur_fn_164(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_163] = { let __args: [G; IN_163] = []; let __cu = unconstrained; let __hit = record.function_queries[163].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[163].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[163].bump_multiplicity(__i); } let __ret: [G; OUT_163] = unsafe { *(record.function_queries[163].output_at(__i).as_ptr() as *const [G; OUT_163]) }; __ret }, _ => aiur_fn_163(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __r_arr: [G; OUT_129] = { let __args: [G; IN_129] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[129].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[129].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[129].bump_multiplicity(__i); } let __ret: [G; OUT_129] = unsafe { *(record.function_queries[129].output_at(__i).as_ptr() as *const [G; OUT_129]) }; __ret }, _ => aiur_fn_129(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_128] = { let __args: [G; IN_128] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[128].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[128].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[128].bump_multiplicity(__i); } let __ret: [G; OUT_128] = unsafe { *(record.function_queries[128].output_at(__i).as_ptr() as *const [G; OUT_128]) }; __ret }, _ => aiur_fn_128(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_9, __v_12]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_9, __v_12]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_168] = { let __args: [G; IN_168] = []; let __cu = unconstrained; let __hit = record.function_queries[168].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[168].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[168].bump_multiplicity(__i); } let __ret: [G; OUT_168] = unsafe { *(record.function_queries[168].output_at(__i).as_ptr() as *const [G; OUT_168]) }; __ret }, _ => aiur_fn_168(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(1); - let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_134] = { let __args: [G; IN_134] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[134].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[134].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[134].bump_multiplicity(__i); } let __ret: [G; OUT_134] = unsafe { *(record.function_queries[134].output_at(__i).as_ptr() as *const [G; OUT_134]) }; __ret }, _ => aiur_fn_134(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_11, __v_14]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_11, __v_14]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_166] = { let __args: [G; IN_166] = []; let __cu = unconstrained; let __hit = record.function_queries[166].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[166].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[166].bump_multiplicity(__i); } let __ret: [G; OUT_166] = unsafe { *(record.function_queries[166].output_at(__i).as_ptr() as *const [G; OUT_166]) }; __ret }, _ => aiur_fn_166(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { let __v_13: G = G::from_u64(1); - let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_135] = { let __args: [G; IN_135] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[135].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[135].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[135].bump_multiplicity(__i); } let __ret: [G; OUT_135] = unsafe { *(record.function_queries[135].output_at(__i).as_ptr() as *const [G; OUT_135]) }; __ret }, _ => aiur_fn_135(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_13, __v_16]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_13, __v_16]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_166] = { let __args: [G; IN_166] = []; let __cu = unconstrained; let __hit = record.function_queries[166].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[166].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[166].bump_multiplicity(__i); } let __ret: [G; OUT_166] = unsafe { *(record.function_queries[166].output_at(__i).as_ptr() as *const [G; OUT_166]) }; __ret }, _ => aiur_fn_166(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_165] = { let __args: [G; IN_165] = []; let __cu = unconstrained; let __hit = record.function_queries[165].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[165].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[165].bump_multiplicity(__i); } let __ret: [G; OUT_165] = unsafe { *(record.function_queries[165].output_at(__i).as_ptr() as *const [G; OUT_165]) }; __ret }, _ => aiur_fn_165(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; match __v_14.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(1); - let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_136] = { let __args: [G; IN_136] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[136].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[136].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[136].bump_multiplicity(__i); } let __ret: [G; OUT_136] = unsafe { *(record.function_queries[136].output_at(__i).as_ptr() as *const [G; OUT_136]) }; __ret }, _ => aiur_fn_136(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_15, __v_18]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_15, __v_18]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_165] = { let __args: [G; IN_165] = []; let __cu = unconstrained; let __hit = record.function_queries[165].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[165].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[165].bump_multiplicity(__i); } let __ret: [G; OUT_165] = unsafe { *(record.function_queries[165].output_at(__i).as_ptr() as *const [G; OUT_165]) }; __ret }, _ => aiur_fn_165(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_164] = { let __args: [G; IN_164] = []; let __cu = unconstrained; let __hit = record.function_queries[164].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[164].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[164].bump_multiplicity(__i); } let __ret: [G; OUT_164] = unsafe { *(record.function_queries[164].output_at(__i).as_ptr() as *const [G; OUT_164]) }; __ret }, _ => aiur_fn_164(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; match __v_16.as_canonical_u64() { 1u64 => { let __v_17: G = G::from_u64(1); - let __r_arr: [G; OUT_138] = { let __args: [G; IN_138] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[138].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[138].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[138].bump_multiplicity(__i); } let __ret: [G; OUT_138] = unsafe { *(record.function_queries[138].output_at(__i).as_ptr() as *const [G; OUT_138]) }; __ret }, _ => aiur_fn_138(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_137] = { let __args: [G; IN_137] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[137].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[137].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[137].bump_multiplicity(__i); } let __ret: [G; OUT_137] = unsafe { *(record.function_queries[137].output_at(__i).as_ptr() as *const [G; OUT_137]) }; __ret }, _ => aiur_fn_137(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_17, __v_20]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_17, __v_20]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_169] = { let __args: [G; IN_169] = []; let __cu = unconstrained; let __hit = record.function_queries[169].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[169].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[169].bump_multiplicity(__i); } let __ret: [G; OUT_169] = unsafe { *(record.function_queries[169].output_at(__i).as_ptr() as *const [G; OUT_169]) }; __ret }, _ => aiur_fn_169(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_168] = { let __args: [G; IN_168] = []; let __cu = unconstrained; let __hit = record.function_queries[168].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[168].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[168].bump_multiplicity(__i); } let __ret: [G; OUT_168] = unsafe { *(record.function_queries[168].output_at(__i).as_ptr() as *const [G; OUT_168]) }; __ret }, _ => aiur_fn_168(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; match __v_18.as_canonical_u64() { 1u64 => { let __v_19: G = G::from_u64(1); - let __r_arr: [G; OUT_142] = { let __args: [G; IN_142] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[142].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[142].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[142].bump_multiplicity(__i); } let __ret: [G; OUT_142] = unsafe { *(record.function_queries[142].output_at(__i).as_ptr() as *const [G; OUT_142]) }; __ret }, _ => aiur_fn_142(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_141] = { let __args: [G; IN_141] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[141].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[141].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[141].bump_multiplicity(__i); } let __ret: [G; OUT_141] = unsafe { *(record.function_queries[141].output_at(__i).as_ptr() as *const [G; OUT_141]) }; __ret }, _ => aiur_fn_141(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_21]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_21]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_19, __v_22]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_19, __v_22]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_170] = { let __args: [G; IN_170] = []; let __cu = unconstrained; let __hit = record.function_queries[170].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[170].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[170].bump_multiplicity(__i); } let __ret: [G; OUT_170] = unsafe { *(record.function_queries[170].output_at(__i).as_ptr() as *const [G; OUT_170]) }; __ret }, _ => aiur_fn_170(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_169] = { let __args: [G; IN_169] = []; let __cu = unconstrained; let __hit = record.function_queries[169].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[169].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[169].bump_multiplicity(__i); } let __ret: [G; OUT_169] = unsafe { *(record.function_queries[169].output_at(__i).as_ptr() as *const [G; OUT_169]) }; __ret }, _ => aiur_fn_169(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; match __v_20.as_canonical_u64() { 1u64 => { let __v_21: G = G::from_u64(1); - let __r_arr: [G; OUT_143] = { let __args: [G; IN_143] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[143].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[143].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[143].bump_multiplicity(__i); } let __ret: [G; OUT_143] = unsafe { *(record.function_queries[143].output_at(__i).as_ptr() as *const [G; OUT_143]) }; __ret }, _ => aiur_fn_143(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_142] = { let __args: [G; IN_142] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[142].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[142].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[142].bump_multiplicity(__i); } let __ret: [G; OUT_142] = unsafe { *(record.function_queries[142].output_at(__i).as_ptr() as *const [G; OUT_142]) }; __ret }, _ => aiur_fn_142(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_23]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_23]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_21, __v_24]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_21, __v_24]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_171] = { let __args: [G; IN_171] = []; let __cu = unconstrained; let __hit = record.function_queries[171].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[171].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[171].bump_multiplicity(__i); } let __ret: [G; OUT_171] = unsafe { *(record.function_queries[171].output_at(__i).as_ptr() as *const [G; OUT_171]) }; __ret }, _ => aiur_fn_171(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_170] = { let __args: [G; IN_170] = []; let __cu = unconstrained; let __hit = record.function_queries[170].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[170].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[170].bump_multiplicity(__i); } let __ret: [G; OUT_170] = unsafe { *(record.function_queries[170].output_at(__i).as_ptr() as *const [G; OUT_170]) }; __ret }, _ => aiur_fn_170(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; match __v_22.as_canonical_u64() { 1u64 => { let __v_23: G = G::from_u64(1); - let __r_arr: [G; OUT_144] = { let __args: [G; IN_144] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[144].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[144].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[144].bump_multiplicity(__i); } let __ret: [G; OUT_144] = unsafe { *(record.function_queries[144].output_at(__i).as_ptr() as *const [G; OUT_144]) }; __ret }, _ => aiur_fn_144(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_143] = { let __args: [G; IN_143] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[143].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[143].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[143].bump_multiplicity(__i); } let __ret: [G; OUT_143] = unsafe { *(record.function_queries[143].output_at(__i).as_ptr() as *const [G; OUT_143]) }; __ret }, _ => aiur_fn_143(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_23, __v_26]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_23, __v_26]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_172] = { let __args: [G; IN_172] = []; let __cu = unconstrained; let __hit = record.function_queries[172].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[172].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[172].bump_multiplicity(__i); } let __ret: [G; OUT_172] = unsafe { *(record.function_queries[172].output_at(__i).as_ptr() as *const [G; OUT_172]) }; __ret }, _ => aiur_fn_172(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_171] = { let __args: [G; IN_171] = []; let __cu = unconstrained; let __hit = record.function_queries[171].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[171].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[171].bump_multiplicity(__i); } let __ret: [G; OUT_171] = unsafe { *(record.function_queries[171].output_at(__i).as_ptr() as *const [G; OUT_171]) }; __ret }, _ => aiur_fn_171(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; match __v_24.as_canonical_u64() { 1u64 => { let __v_25: G = G::from_u64(1); - let __r_arr: [G; OUT_145] = { let __args: [G; IN_145] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[145].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[145].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[145].bump_multiplicity(__i); } let __ret: [G; OUT_145] = unsafe { *(record.function_queries[145].output_at(__i).as_ptr() as *const [G; OUT_145]) }; __ret }, _ => aiur_fn_145(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_144] = { let __args: [G; IN_144] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[144].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[144].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[144].bump_multiplicity(__i); } let __ret: [G; OUT_144] = unsafe { *(record.function_queries[144].output_at(__i).as_ptr() as *const [G; OUT_144]) }; __ret }, _ => aiur_fn_144(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_26]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_25, __v_28]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_25, __v_28]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_173] = { let __args: [G; IN_173] = []; let __cu = unconstrained; let __hit = record.function_queries[173].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[173].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[173].bump_multiplicity(__i); } let __ret: [G; OUT_173] = unsafe { *(record.function_queries[173].output_at(__i).as_ptr() as *const [G; OUT_173]) }; __ret }, _ => aiur_fn_173(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_172] = { let __args: [G; IN_172] = []; let __cu = unconstrained; let __hit = record.function_queries[172].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[172].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[172].bump_multiplicity(__i); } let __ret: [G; OUT_172] = unsafe { *(record.function_queries[172].output_at(__i).as_ptr() as *const [G; OUT_172]) }; __ret }, _ => aiur_fn_172(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; match __v_26.as_canonical_u64() { 1u64 => { let __v_27: G = G::from_u64(1); - let __r_arr: [G; OUT_146] = { let __args: [G; IN_146] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[146].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[146].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[146].bump_multiplicity(__i); } let __ret: [G; OUT_146] = unsafe { *(record.function_queries[146].output_at(__i).as_ptr() as *const [G; OUT_146]) }; __ret }, _ => aiur_fn_146(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_145] = { let __args: [G; IN_145] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[145].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[145].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[145].bump_multiplicity(__i); } let __ret: [G; OUT_145] = unsafe { *(record.function_queries[145].output_at(__i).as_ptr() as *const [G; OUT_145]) }; __ret }, _ => aiur_fn_145(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_27, __v_30]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_27, __v_30]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_174] = { let __args: [G; IN_174] = []; let __cu = unconstrained; let __hit = record.function_queries[174].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[174].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[174].bump_multiplicity(__i); } let __ret: [G; OUT_174] = unsafe { *(record.function_queries[174].output_at(__i).as_ptr() as *const [G; OUT_174]) }; __ret }, _ => aiur_fn_174(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_173] = { let __args: [G; IN_173] = []; let __cu = unconstrained; let __hit = record.function_queries[173].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[173].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[173].bump_multiplicity(__i); } let __ret: [G; OUT_173] = unsafe { *(record.function_queries[173].output_at(__i).as_ptr() as *const [G; OUT_173]) }; __ret }, _ => aiur_fn_173(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; match __v_28.as_canonical_u64() { 1u64 => { let __v_29: G = G::from_u64(1); - let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_337] = { let __args: [G; IN_337] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[337].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[337].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[337].bump_multiplicity(__i); } let __ret: [G; OUT_337] = unsafe { *(record.function_queries[337].output_at(__i).as_ptr() as *const [G; OUT_337]) }; __ret }, _ => aiur_fn_337(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __r_arr: [G; OUT_198] = { let __args: [G; IN_198] = [__v_30]; let __cu = unconstrained; let __hit = record.function_queries[198].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[198].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[198].bump_multiplicity(__i); } let __ret: [G; OUT_198] = unsafe { *(record.function_queries[198].output_at(__i).as_ptr() as *const [G; OUT_198]) }; __ret }, _ => aiur_fn_198(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_197] = { let __args: [G; IN_197] = [__v_30]; let __cu = unconstrained; let __hit = record.function_queries[197].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[197].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[197].bump_multiplicity(__i); } let __ret: [G; OUT_197] = unsafe { *(record.function_queries[197].output_at(__i).as_ptr() as *const [G; OUT_197]) }; __ret }, _ => aiur_fn_197(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_29, __v_31]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_29, __v_31]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_175] = { let __args: [G; IN_175] = []; let __cu = unconstrained; let __hit = record.function_queries[175].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[175].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[175].bump_multiplicity(__i); } let __ret: [G; OUT_175] = unsafe { *(record.function_queries[175].output_at(__i).as_ptr() as *const [G; OUT_175]) }; __ret }, _ => aiur_fn_175(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_174] = { let __args: [G; IN_174] = []; let __cu = unconstrained; let __hit = record.function_queries[174].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[174].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[174].bump_multiplicity(__i); } let __ret: [G; OUT_174] = unsafe { *(record.function_queries[174].output_at(__i).as_ptr() as *const [G; OUT_174]) }; __ret }, _ => aiur_fn_174(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_29]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; @@ -24382,10 +24336,10 @@ fn aiur_fn_256( let __v_31: G = G::from_u64(1); let __r_arr: [G; OUT_124] = { let __args: [G; IN_124] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[124].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[124].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[124].bump_multiplicity(__i); } let __ret: [G; OUT_124] = unsafe { *(record.function_queries[124].output_at(__i).as_ptr() as *const [G; OUT_124]) }; __ret }, _ => aiur_fn_124(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; - let __r_arr: [G; OUT_198] = { let __args: [G; IN_198] = [__v_32]; let __cu = unconstrained; let __hit = record.function_queries[198].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[198].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[198].bump_multiplicity(__i); } let __ret: [G; OUT_198] = unsafe { *(record.function_queries[198].output_at(__i).as_ptr() as *const [G; OUT_198]) }; __ret }, _ => aiur_fn_198(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_197] = { let __args: [G; IN_197] = [__v_32]; let __cu = unconstrained; let __hit = record.function_queries[197].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[197].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[197].bump_multiplicity(__i); } let __ret: [G; OUT_197] = unsafe { *(record.function_queries[197].output_at(__i).as_ptr() as *const [G; OUT_197]) }; __ret }, _ => aiur_fn_197(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; - let __ret: [G; OUT_256] = [__v_31, __v_33]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_31, __v_33]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -24394,8 +24348,8 @@ fn aiur_fn_256( let __v_33: G = G::from_u64(0); let __v_34: G = G::from_u64(0); let __v_35: G = { let __values: [G; 4] = [__v_32, __v_33, __v_34, __v_34]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_256] = [__v_31, __v_35]; - record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_255] = [__v_31, __v_35]; + record.function_queries[255].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24428,15 +24382,15 @@ fn aiur_fn_256( }) } -const INPUT_SIZE_257: usize = 2; -const IN_257: usize = 2; -const OUT_257: usize = 3; -fn aiur_fn_257( - inp: [G; IN_257], +const INPUT_SIZE_256: usize = 2; +const IN_256: usize = 2; +const OUT_256: usize = 3; +fn aiur_fn_256( + inp: [G; IN_256], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_257], ExecError> { +) -> Result<[G; OUT_256], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -24447,7 +24401,7 @@ fn aiur_fn_257( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; @@ -24457,22 +24411,22 @@ fn aiur_fn_257( let __v_9: G = G::from_u64(1); let __v_10: G = G::from_u64(1); let __v_11: G = { let __values: [G; 10] = [__v_9, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_257] = [__v_8, __v_0, __v_11]; - record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_256] = [__v_8, __v_0, __v_11]; + record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(2); let __v_10: G = (__v_8 - __v_9); match __v_10.as_canonical_u64() { 0u64 => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_14.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_15: G = __loaded[0]; @@ -24484,8 +24438,8 @@ fn aiur_fn_257( match __v_16.as_canonical_u64() { 0u64 => { let __v_19: G = G::from_u64(1); - let __ret: [G; OUT_257] = [__v_19, __v_12, __v_17]; - record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_256] = [__v_19, __v_12, __v_17]; + record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -24493,8 +24447,8 @@ fn aiur_fn_257( let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 10] = [__v_20, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_257] = [__v_19, __v_0, __v_22]; - record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_256] = [__v_19, __v_0, __v_22]; + record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24504,8 +24458,8 @@ fn aiur_fn_257( let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 10] = [__v_20, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_257] = [__v_19, __v_0, __v_22]; - record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_256] = [__v_19, __v_0, __v_22]; + record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24515,8 +24469,8 @@ fn aiur_fn_257( let __v_12: G = G::from_u64(1); let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 10] = [__v_12, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_257] = [__v_11, __v_0, __v_14]; - record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_256] = [__v_11, __v_0, __v_14]; + record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24528,23 +24482,23 @@ fn aiur_fn_257( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 10] = [__v_7, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_257] = [__v_6, __v_0, __v_9]; - record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_256] = [__v_6, __v_0, __v_9]; + record.function_queries[256].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_258: usize = 2; -const IN_258: usize = 2; -const OUT_258: usize = 1; -fn aiur_fn_258( - inp: [G; IN_258], +const INPUT_SIZE_257: usize = 2; +const IN_257: usize = 2; +const OUT_257: usize = 1; +fn aiur_fn_257( + inp: [G; IN_257], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_258], ExecError> { +) -> Result<[G; OUT_257], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -24566,27 +24520,27 @@ fn aiur_fn_258( let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(2); - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(1); let __v_21: G = { let __values: [G; 3] = [__v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 4] = [__v_17, __v_18, __v_21, __v_22]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; match __v_24.as_canonical_u64() { 1u64 => { let __v_25: G = G::from_u64(3); let __v_26: G = G::from_u64(0); let __v_27: G = { let __values: [G; 4] = [__v_25, __v_23, __v_0, __v_26]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_258] = [__v_27]; - record.function_queries[258].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_257] = [__v_27]; + record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_25: G = G::from_u64(2); - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = G::from_u64(1); let __v_28: G = G::from_u64(1); @@ -24606,23 +24560,23 @@ fn aiur_fn_258( let __v_42: G = G::from_u64(3); let __v_43: G = G::from_u64(0); let __v_44: G = { let __values: [G; 4] = [__v_42, __v_23, __v_41, __v_43]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_258] = [__v_44]; - record.function_queries[258].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_257] = [__v_44]; + record.function_queries[257].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_259: usize = 1; -const IN_259: usize = 1; -const OUT_259: usize = 1; -fn aiur_fn_259( - inp: [G; IN_259], +const INPUT_SIZE_258: usize = 1; +const IN_258: usize = 1; +const OUT_258: usize = 1; +fn aiur_fn_258( + inp: [G; IN_258], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_259], ExecError> { +) -> Result<[G; OUT_258], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -24632,8 +24586,8 @@ fn aiur_fn_259( let __v_4: G = __loaded[3]; match __v_1.as_canonical_u64() { 7u64 => { - let __ret: [G; OUT_259] = [__v_0]; - record.function_queries[259].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_258] = [__v_0]; + record.function_queries[258].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -24647,7 +24601,7 @@ fn aiur_fn_259( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_257] = { let __args: [G; IN_257] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[257].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[257].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[257].bump_multiplicity(__i); } let __ret: [G; OUT_257] = unsafe { *(record.function_queries[257].output_at(__i).as_ptr() as *const [G; OUT_257]) }; __ret }, _ => aiur_fn_257(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_256] = { let __args: [G; IN_256] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[256].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[256].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[256].bump_multiplicity(__i); } let __ret: [G; OUT_256] = unsafe { *(record.function_queries[256].output_at(__i).as_ptr() as *const [G; OUT_256]) }; __ret }, _ => aiur_fn_256(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; @@ -24655,33 +24609,33 @@ fn aiur_fn_259( 1u64 => { let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; match __v_15.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_259] = [__v_0]; - record.function_queries[259].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_258] = [__v_0]; + record.function_queries[258].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_258] = { let __args: [G; IN_258] = [__v_12, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[258].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[258].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[258].bump_multiplicity(__i); } let __ret: [G; OUT_258] = unsafe { *(record.function_queries[258].output_at(__i).as_ptr() as *const [G; OUT_258]) }; __ret }, _ => aiur_fn_258(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_257] = { let __args: [G; IN_257] = [__v_12, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[257].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[257].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[257].bump_multiplicity(__i); } let __ret: [G; OUT_257] = unsafe { *(record.function_queries[257].output_at(__i).as_ptr() as *const [G; OUT_257]) }; __ret }, _ => aiur_fn_257(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_259] = [__v_16]; - record.function_queries[259].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_258] = [__v_16]; + record.function_queries[258].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_259] = [__v_0]; - record.function_queries[259].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_258] = [__v_0]; + record.function_queries[258].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_259] = [__v_0]; - record.function_queries[259].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_258] = [__v_0]; + record.function_queries[258].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24690,33 +24644,33 @@ fn aiur_fn_259( }) } -const INPUT_SIZE_260: usize = 3; -const IN_260: usize = 3; -const OUT_260: usize = 2; -fn aiur_fn_260( - inp: [G; IN_260], +const INPUT_SIZE_259: usize = 3; +const IN_259: usize = 3; +const OUT_259: usize = 2; +fn aiur_fn_259( + inp: [G; IN_259], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_260], ExecError> { +) -> Result<[G; OUT_259], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_260] = [__v_4, __v_5]; - record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_259] = [__v_4, __v_5]; + record.function_queries[259].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(2); - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); @@ -24727,30 +24681,30 @@ fn aiur_fn_260( let __v_12: G = G::from_u64(3); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_12, __v_10, __v_0, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(0); let __v_17: G = { let __values: [G; 4] = [__v_11, __v_14, __v_15, __v_16]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_18: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_17, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_17, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __ret: [G; OUT_260] = [__v_18, __v_19]; - record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_259] = [__v_18, __v_19]; + record.function_queries[259].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_261: usize = 1; -const IN_261: usize = 1; -const OUT_261: usize = 1; -fn aiur_fn_261( - inp: [G; IN_261], +const INPUT_SIZE_260: usize = 1; +const IN_260: usize = 1; +const OUT_260: usize = 1; +fn aiur_fn_260( + inp: [G; IN_260], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_261], ExecError> { +) -> Result<[G; OUT_260], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -24777,26 +24731,26 @@ fn aiur_fn_261( let __v_14: G = __loaded[3]; match __v_11.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_12, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; match __v_16.as_canonical_u64() { 0u64 => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_261] = [__v_17]; - record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_260] = [__v_17]; + record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = G::from_u64(1); let __v_19: G = (__v_17 - __v_18); match __v_19.as_canonical_u64() { 0u64 => { let __v_20: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_10, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_10, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_21.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_22: G = __loaded[0]; @@ -24806,22 +24760,22 @@ fn aiur_fn_261( match __v_22.as_canonical_u64() { 0u64 => { let __v_26: G = G::from_bool((__v_23 == G::ZERO)); - let __ret: [G; OUT_261] = [__v_26]; - record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_260] = [__v_26]; + record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_26: G = G::from_u64(0); - let __ret: [G; OUT_261] = [__v_26]; - record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_260] = [__v_26]; + record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_20: G = G::from_u64(0); - let __ret: [G; OUT_261] = [__v_20]; - record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_260] = [__v_20]; + record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24830,39 +24784,39 @@ fn aiur_fn_261( }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_261] = [__v_15]; - record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_260] = [__v_15]; + record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_261] = [__v_9]; - record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_260] = [__v_9]; + record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_261] = [__v_5]; - record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_260] = [__v_5]; + record.function_queries[260].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_262: usize = 5; -const IN_262: usize = 5; -const OUT_262: usize = 2; -fn aiur_fn_262( - inp: [G; IN_262], +const INPUT_SIZE_261: usize = 5; +const IN_261: usize = 5; +const OUT_261: usize = 2; +fn aiur_fn_261( + inp: [G; IN_261], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_262], ExecError> { +) -> Result<[G; OUT_261], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -24878,14 +24832,14 @@ fn aiur_fn_262( let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_8, __v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_262] = [__v_7, __v_11]; - record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_261] = [__v_7, __v_11]; + record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; match __v_8.as_canonical_u64() { @@ -24895,17 +24849,17 @@ fn aiur_fn_262( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_262] = [__v_10, __v_14]; - record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_261] = [__v_10, __v_14]; + record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_10: G = (__v_1 + __v_2); let __v_11: G = G::from_u64(1); let __v_12: G = (__v_10 + __v_11); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_261] = { let __args: [G; IN_261] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[261].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[261].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[261].bump_multiplicity(__i); } let __ret: [G; OUT_261] = unsafe { *(record.function_queries[261].output_at(__i).as_ptr() as *const [G; OUT_261]) }; __ret }, _ => aiur_fn_261(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_260] = { let __args: [G; IN_260] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[260].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[260].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[260].bump_multiplicity(__i); } let __ret: [G; OUT_260] = unsafe { *(record.function_queries[260].output_at(__i).as_ptr() as *const [G; OUT_260]) }; __ret }, _ => aiur_fn_260(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; match __v_14.as_canonical_u64() { 0u64 => { @@ -24914,18 +24868,18 @@ fn aiur_fn_262( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_16, __v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_262] = [__v_15, __v_19]; - record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_261] = [__v_15, __v_19]; + record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(1); let __v_17: G = (__v_4 + __v_16); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; match __v_19.as_canonical_u64() { @@ -24933,20 +24887,20 @@ fn aiur_fn_262( let __v_21: G = G::from_u64(1); let __r_arr: [G; OUT_118] = { let __args: [G; IN_118] = [__v_20, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[118].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[118].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[118].bump_multiplicity(__i); } let __ret: [G; OUT_118] = unsafe { *(record.function_queries[118].output_at(__i).as_ptr() as *const [G; OUT_118]) }; __ret }, _ => aiur_fn_118(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_23, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_23, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __ret: [G; OUT_262] = [__v_21, __v_24]; - record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_261] = [__v_21, __v_24]; + record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_260] = { let __args: [G; IN_260] = [__v_15, __v_9, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[260].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[260].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[260].bump_multiplicity(__i); } let __ret: [G; OUT_260] = unsafe { *(record.function_queries[260].output_at(__i).as_ptr() as *const [G; OUT_260]) }; __ret }, _ => aiur_fn_260(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_259] = { let __args: [G; IN_259] = [__v_15, __v_9, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[259].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[259].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[259].bump_multiplicity(__i); } let __ret: [G; OUT_259] = unsafe { *(record.function_queries[259].output_at(__i).as_ptr() as *const [G; OUT_259]) }; __ret }, _ => aiur_fn_259(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = __r_arr[1]; - let __ret: [G; OUT_262] = [__v_21, __v_22]; - record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_261] = [__v_21, __v_22]; + record.function_queries[261].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -24962,26 +24916,26 @@ fn aiur_fn_262( }) } -const INPUT_SIZE_263: usize = 3; -const IN_263: usize = 3; -const OUT_263: usize = 2; -fn aiur_fn_263( - inp: [G; IN_263], +const INPUT_SIZE_262: usize = 3; +const IN_262: usize = 3; +const OUT_262: usize = 2; +fn aiur_fn_262( + inp: [G; IN_262], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_263], ExecError> { +) -> Result<[G; OUT_262], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; @@ -24996,31 +24950,31 @@ fn aiur_fn_263( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_263] = [__v_10, __v_14]; - record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_262] = [__v_10, __v_14]; + record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; match __v_12.as_canonical_u64() { 1u64 => { let __v_14: G = G::from_u64(1); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(1); let __r_arr: [G; OUT_116] = { let __args: [G; IN_116] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[116].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[116].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[116].bump_multiplicity(__i); } let __ret: [G; OUT_116] = unsafe { *(record.function_queries[116].output_at(__i).as_ptr() as *const [G; OUT_116]) }; __ret }, _ => aiur_fn_116(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_18, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_18, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __ret: [G; OUT_263] = [__v_16, __v_19]; - record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_262] = [__v_16, __v_19]; + record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25029,8 +24983,8 @@ fn aiur_fn_263( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_263] = [__v_14, __v_18]; - record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_262] = [__v_14, __v_18]; + record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -25049,33 +25003,33 @@ fn aiur_fn_263( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_263] = [__v_10, __v_14]; - record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_262] = [__v_10, __v_14]; + record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; match __v_12.as_canonical_u64() { 1u64 => { let __v_14: G = G::from_u64(1); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(1); let __r_arr: [G; OUT_125] = { let __args: [G; IN_125] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[125].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[125].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[125].bump_multiplicity(__i); } let __ret: [G; OUT_125] = unsafe { *(record.function_queries[125].output_at(__i).as_ptr() as *const [G; OUT_125]) }; __ret }, _ => aiur_fn_125(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_19, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_19, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_263] = [__v_16, __v_20]; - record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_262] = [__v_16, __v_20]; + record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25084,8 +25038,8 @@ fn aiur_fn_263( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_263] = [__v_14, __v_18]; - record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_262] = [__v_14, __v_18]; + record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -25093,11 +25047,11 @@ fn aiur_fn_263( } }, _ => { - let __r_arr: [G; OUT_264] = { let __args: [G; IN_264] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[264].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[264].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[264].bump_multiplicity(__i); } let __ret: [G; OUT_264] = unsafe { *(record.function_queries[264].output_at(__i).as_ptr() as *const [G; OUT_264]) }; __ret }, _ => aiur_fn_264(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_263] = { let __args: [G; IN_263] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[263].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[263].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[263].bump_multiplicity(__i); } let __ret: [G; OUT_263] = unsafe { *(record.function_queries[263].output_at(__i).as_ptr() as *const [G; OUT_263]) }; __ret }, _ => aiur_fn_263(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_263] = [__v_8, __v_9]; - record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_262] = [__v_8, __v_9]; + record.function_queries[262].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -25106,15 +25060,15 @@ fn aiur_fn_263( }) } -const INPUT_SIZE_264: usize = 3; -const IN_264: usize = 3; -const OUT_264: usize = 2; -fn aiur_fn_264( - inp: [G; IN_264], +const INPUT_SIZE_263: usize = 3; +const IN_263: usize = 3; +const OUT_263: usize = 2; +fn aiur_fn_263( + inp: [G; IN_263], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_264], ExecError> { +) -> Result<[G; OUT_263], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -25128,40 +25082,40 @@ fn aiur_fn_264( let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_264] = [__v_5, __v_9]; - record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_263] = [__v_5, __v_9]; + record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_256] = { let __args: [G; IN_256] = [__v_0, __v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[256].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[256].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[256].bump_multiplicity(__i); } let __ret: [G; OUT_256] = unsafe { *(record.function_queries[256].output_at(__i).as_ptr() as *const [G; OUT_256]) }; __ret }, _ => aiur_fn_256(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_0, __v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; match __v_13.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_14, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_14, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_264] = [__v_17, __v_18]; - record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_263] = [__v_17, __v_18]; + record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25170,8 +25124,8 @@ fn aiur_fn_264( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_16, __v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_264] = [__v_15, __v_19]; - record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_263] = [__v_15, __v_19]; + record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -25182,23 +25136,23 @@ fn aiur_fn_264( let __v_15: G = G::from_u64(0); let __v_16: G = G::from_u64(0); let __v_17: G = { let __values: [G; 4] = [__v_14, __v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_264] = [__v_13, __v_17]; - record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_263] = [__v_13, __v_17]; + record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_265] = { let __args: [G; IN_265] = [__v_0, __v_6, __v_12, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[265].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[265].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[265].bump_multiplicity(__i); } let __ret: [G; OUT_265] = unsafe { *(record.function_queries[265].output_at(__i).as_ptr() as *const [G; OUT_265]) }; __ret }, _ => aiur_fn_265(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_264] = { let __args: [G; IN_264] = [__v_0, __v_6, __v_12, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[264].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[264].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[264].bump_multiplicity(__i); } let __ret: [G; OUT_264] = unsafe { *(record.function_queries[264].output_at(__i).as_ptr() as *const [G; OUT_264]) }; __ret }, _ => aiur_fn_264(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_264] = [__v_13, __v_14]; - record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_263] = [__v_13, __v_14]; + record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25207,8 +25161,8 @@ fn aiur_fn_264( let __v_15: G = G::from_u64(0); let __v_16: G = G::from_u64(0); let __v_17: G = { let __values: [G; 4] = [__v_14, __v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_264] = [__v_13, __v_17]; - record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_263] = [__v_13, __v_17]; + record.function_queries[263].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -25219,35 +25173,35 @@ fn aiur_fn_264( }) } -const INPUT_SIZE_265: usize = 4; -const IN_265: usize = 4; -const OUT_265: usize = 2; -fn aiur_fn_265( - inp: [G; IN_265], +const INPUT_SIZE_264: usize = 4; +const IN_264: usize = 4; +const OUT_264: usize = 2; +fn aiur_fn_264( + inp: [G; IN_264], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_265], ExecError> { +) -> Result<[G; OUT_264], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_168] = { let __args: [G; IN_168] = []; let __cu = unconstrained; let __hit = record.function_queries[168].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[168].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[168].bump_multiplicity(__i); } let __ret: [G; OUT_168] = unsafe { *(record.function_queries[168].output_at(__i).as_ptr() as *const [G; OUT_168]) }; __ret }, _ => aiur_fn_168(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_166] = { let __args: [G; IN_166] = []; let __cu = unconstrained; let __hit = record.function_queries[166].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[166].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[166].bump_multiplicity(__i); } let __ret: [G; OUT_166] = unsafe { *(record.function_queries[166].output_at(__i).as_ptr() as *const [G; OUT_166]) }; __ret }, _ => aiur_fn_166(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = (__v_7 + __v_9); let __v_11: G = G::from_u64(1); - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = (__v_11 - __v_12); let __v_14: G = G::from_u64(1); @@ -25255,7 +25209,7 @@ fn aiur_fn_265( let __v_15: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = (__v_14 - __v_17); let __v_19: G = (__v_13 * __v_18); @@ -25268,24 +25222,24 @@ fn aiur_fn_265( let __v_24: G = G::from_u64(0); let __v_25: G = G::from_u64(0); let __v_26: G = { let __values: [G; 4] = [__v_23, __v_24, __v_25, __v_25]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_265] = [__v_22, __v_26]; - record.function_queries[265].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_264] = [__v_22, __v_26]; + record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_22: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_3, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_3, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_260] = { let __args: [G; IN_260] = [__v_1, __v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[260].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[260].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[260].bump_multiplicity(__i); } let __ret: [G; OUT_260] = unsafe { *(record.function_queries[260].output_at(__i).as_ptr() as *const [G; OUT_260]) }; __ret }, _ => aiur_fn_260(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_259] = { let __args: [G; IN_259] = [__v_1, __v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[259].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[259].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[259].bump_multiplicity(__i); } let __ret: [G; OUT_259] = unsafe { *(record.function_queries[259].output_at(__i).as_ptr() as *const [G; OUT_259]) }; __ret }, _ => aiur_fn_259(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = __r_arr[1]; match __v_24.as_canonical_u64() { 1u64 => { let __v_26: G = G::from_u64(2); - let __ret: [G; OUT_265] = [__v_26, __v_25]; - record.function_queries[265].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_264] = [__v_26, __v_25]; + record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25294,18 +25248,18 @@ fn aiur_fn_265( let __v_28: G = G::from_u64(0); let __v_29: G = G::from_u64(0); let __v_30: G = { let __values: [G; 4] = [__v_27, __v_28, __v_29, __v_29]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_265] = [__v_26, __v_30]; - record.function_queries[265].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_264] = [__v_26, __v_30]; + record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_24: G = G::from_u64(2); - let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_0, __v_1, __v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_265] = { let __args: [G; IN_265] = [__v_0, __v_1, __v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[265].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[265].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[265].bump_multiplicity(__i); } let __ret: [G; OUT_265] = unsafe { *(record.function_queries[265].output_at(__i).as_ptr() as *const [G; OUT_265]) }; __ret }, _ => aiur_fn_265(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __ret: [G; OUT_265] = [__v_24, __v_25]; - record.function_queries[265].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_264] = [__v_24, __v_25]; + record.function_queries[264].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -25314,15 +25268,15 @@ fn aiur_fn_265( }) } -const INPUT_SIZE_266: usize = 4; -const IN_266: usize = 4; -const OUT_266: usize = 1; -fn aiur_fn_266( - inp: [G; IN_266], +const INPUT_SIZE_265: usize = 4; +const IN_265: usize = 4; +const OUT_265: usize = 1; +fn aiur_fn_265( + inp: [G; IN_265], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_266], ExecError> { +) -> Result<[G; OUT_265], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -25338,27 +25292,27 @@ fn aiur_fn_266( let __v_11: G = G::from_u64(3); let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_11, __v_9, __v_1, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_10, __v_13, __v_14, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_16, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_16, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_266] = [__v_17]; - record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_265] = [__v_17]; + record.function_queries[265].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_267: usize = 10; -const IN_267: usize = 10; -const OUT_267: usize = 8; -fn aiur_fn_267( - inp: [G; IN_267], +const INPUT_SIZE_266: usize = 10; +const IN_266: usize = 10; +const OUT_266: usize = 8; +fn aiur_fn_266( + inp: [G; IN_266], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_267], ExecError> { +) -> Result<[G; OUT_266], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -25372,8 +25326,8 @@ fn aiur_fn_267( let __v_9: G = inp[9]; match __v_9.as_canonical_u64() { 8u64 => { - let __ret: [G; OUT_267] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25383,15 +25337,15 @@ fn aiur_fn_267( let __v_12: G = __loaded[2]; match __v_10.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_267] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_9.as_canonical_u64() { 0u64 => { let __v_13: G = G::from_u64(1); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_11, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_11, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25400,13 +25354,13 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_13: G = G::from_u64(2); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_1, __v_11, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_1, __v_11, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25415,13 +25369,13 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_13: G = G::from_u64(3); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_1, __v_2, __v_11, __v_4, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_1, __v_2, __v_11, __v_4, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25430,13 +25384,13 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_13: G = G::from_u64(4); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_1, __v_2, __v_3, __v_11, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_1, __v_2, __v_3, __v_11, __v_5, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25445,13 +25399,13 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_13: G = G::from_u64(5); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_11, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_11, __v_6, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25460,13 +25414,13 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_13: G = G::from_u64(6); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_11, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_11, __v_7, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25475,13 +25429,13 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_13: G = G::from_u64(7); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_11, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_11, __v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25490,13 +25444,13 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(8); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_11, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_11, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -25505,8 +25459,8 @@ fn aiur_fn_267( let __v_19: G = __r_arr[5]; let __v_20: G = __r_arr[6]; let __v_21: G = __r_arr[7]; - let __ret: [G; OUT_267] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; - record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_266] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; + record.function_queries[266].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -25520,22 +25474,22 @@ fn aiur_fn_267( }) } -const INPUT_SIZE_268: usize = 2; -const IN_268: usize = 2; -const OUT_268: usize = 1; -fn aiur_fn_268( - inp: [G; IN_268], +const INPUT_SIZE_267: usize = 2; +const IN_267: usize = 2; +const OUT_267: usize = 1; +fn aiur_fn_267( + inp: [G; IN_267], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_268], ExecError> { +) -> Result<[G; OUT_267], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_268] = [__v_0]; - record.function_queries[268].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_267] = [__v_0]; + record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25548,17 +25502,17 @@ fn aiur_fn_268( let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_268] = [__v_7]; - record.function_queries[268].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_267] = [__v_7]; + record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(1); let __v_6: G = (__v_1 - __v_5); - let __r_arr: [G; OUT_268] = { let __args: [G; IN_268] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[268].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[268].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[268].bump_multiplicity(__i); } let __ret: [G; OUT_268] = unsafe { *(record.function_queries[268].output_at(__i).as_ptr() as *const [G; OUT_268]) }; __ret }, _ => aiur_fn_268(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_268] = [__v_7]; - record.function_queries[268].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_267] = [__v_7]; + record.function_queries[267].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25570,15 +25524,15 @@ fn aiur_fn_268( }) } -const INPUT_SIZE_269: usize = 1; -const IN_269: usize = 1; -const OUT_269: usize = 1; -fn aiur_fn_269( - inp: [G; IN_269], +const INPUT_SIZE_268: usize = 1; +const IN_268: usize = 1; +const OUT_268: usize = 1; +fn aiur_fn_268( + inp: [G; IN_268], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_269], ExecError> { +) -> Result<[G; OUT_268], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(0); @@ -25590,7 +25544,7 @@ fn aiur_fn_269( let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_266] = { let __args: [G; IN_266] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[266].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[266].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[266].bump_multiplicity(__i); } let __ret: [G; OUT_266] = unsafe { *(record.function_queries[266].output_at(__i).as_ptr() as *const [G; OUT_266]) }; __ret }, _ => aiur_fn_266(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; @@ -25600,7 +25554,7 @@ fn aiur_fn_269( let __v_16: G = __r_arr[6]; let __v_17: G = __r_arr[7]; let __v_18: G = G::from_u64(8); - let __r_arr: [G; OUT_268] = { let __args: [G; IN_268] = [__v_0, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[268].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[268].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[268].bump_multiplicity(__i); } let __ret: [G; OUT_268] = unsafe { *(record.function_queries[268].output_at(__i).as_ptr() as *const [G; OUT_268]) }; __ret }, _ => aiur_fn_268(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_267] = { let __args: [G; IN_267] = [__v_0, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[267].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[267].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[267].bump_multiplicity(__i); } let __ret: [G; OUT_267] = unsafe { *(record.function_queries[267].output_at(__i).as_ptr() as *const [G; OUT_267]) }; __ret }, _ => aiur_fn_267(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_19.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_20: G = __loaded[0]; @@ -25614,7 +25568,7 @@ fn aiur_fn_269( break '__mc_0 [__v_25]; }, _ => { - let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_268] = { let __args: [G; IN_268] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[268].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[268].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[268].bump_multiplicity(__i); } let __ret: [G; OUT_268] = unsafe { *(record.function_queries[268].output_at(__i).as_ptr() as *const [G; OUT_268]) }; __ret }, _ => aiur_fn_268(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; break '__mc_0 [__v_23]; }, @@ -25641,8 +25595,8 @@ fn aiur_fn_269( let __v_35: G = G::from_u64(1); let __v_36: G = G::from_u64(1); let __v_37: G = { let __values: [G; 10] = [__v_35, __v_36, __v_36, __v_36, __v_36, __v_36, __v_36, __v_36, __v_36, __v_36]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_269] = [__v_37]; - record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_268] = [__v_37]; + record.function_queries[268].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -25651,8 +25605,8 @@ fn aiur_fn_269( let __v_37: G = G::from_u64(1); let __v_38: G = { let __values: [G; 10] = [__v_36, __v_37, __v_37, __v_37, __v_37, __v_37, __v_37, __v_37, __v_37, __v_37]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_39: G = { let __values: [G; 10] = [__v_35, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_38]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_269] = [__v_39]; - record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_268] = [__v_39]; + record.function_queries[268].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25663,23 +25617,23 @@ fn aiur_fn_269( _ => { let __v_34: G = G::from_u64(0); let __v_35: G = { let __values: [G; 10] = [__v_34, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_23]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_269] = [__v_35]; - record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_268] = [__v_35]; + record.function_queries[268].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_270: usize = 1; -const IN_270: usize = 1; -const OUT_270: usize = 1; -fn aiur_fn_270( - inp: [G; IN_270], +const INPUT_SIZE_269: usize = 1; +const IN_269: usize = 1; +const OUT_269: usize = 1; +fn aiur_fn_269( + inp: [G; IN_269], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_270], ExecError> { +) -> Result<[G; OUT_269], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 9] = { let __mq = record.memory_queries.get_mut(&9).ok_or(ExecError::InvalidMemorySize(9))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 9 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 9] = __args[..9].try_into().unwrap(); __arr }; @@ -25697,40 +25651,40 @@ fn aiur_fn_270( let __v_10: G = G::from_u64(0); let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 3] = [__v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_270] = [__v_12]; - record.function_queries[270].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_269] = [__v_12]; + record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_10: G = G::from_u64(1); - let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_10, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_270] = [__v_13]; - record.function_queries[270].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_269] = [__v_13]; + record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_10: G = G::from_u64(2); - let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = { let __values: [G; 3] = [__v_10, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_270] = [__v_13]; - record.function_queries[270].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_269] = [__v_13]; + record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_10: G = G::from_u64(3); - let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = { let __values: [G; 3] = [__v_10, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_270] = [__v_13]; - record.function_queries[270].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_269] = [__v_13]; + record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { @@ -25739,8 +25693,8 @@ fn aiur_fn_270( let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_10, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_270] = [__v_13]; - record.function_queries[270].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_269] = [__v_13]; + record.function_queries[269].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25750,15 +25704,15 @@ fn aiur_fn_270( }) } -const INPUT_SIZE_271: usize = 2; -const IN_271: usize = 2; -const OUT_271: usize = 1; -fn aiur_fn_271( - inp: [G; IN_271], +const INPUT_SIZE_270: usize = 2; +const IN_270: usize = 2; +const OUT_270: usize = 1; +fn aiur_fn_270( + inp: [G; IN_270], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_271], ExecError> { +) -> Result<[G; OUT_270], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -25778,23 +25732,23 @@ fn aiur_fn_271( let __v_12: G = G::from_u64(1); let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 3] = [__v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_271] = [__v_14]; - record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_270] = [__v_14]; + record.function_queries[270].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_11, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_11, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = { let __values: [G; 3] = [__v_14, __v_15, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_271] = [__v_17]; - record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_270] = [__v_17]; + record.function_queries[270].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -25804,15 +25758,15 @@ fn aiur_fn_271( }) } -const INPUT_SIZE_272: usize = 5; -const IN_272: usize = 5; -const OUT_272: usize = 1; -fn aiur_fn_272( - inp: [G; IN_272], +const INPUT_SIZE_271: usize = 5; +const IN_271: usize = 5; +const OUT_271: usize = 1; +fn aiur_fn_271( + inp: [G; IN_271], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_272], ExecError> { +) -> Result<[G; OUT_271], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -25842,15 +25796,15 @@ fn aiur_fn_272( 0u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = G::from_u64(1); - let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = G::from_u64(0); let __v_28: G = { let __values: [G; 4] = [__v_25, __v_26, __v_27, __v_27]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_28]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_28]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -25859,139 +25813,139 @@ fn aiur_fn_272( let __v_24: G = __r_arr[0]; let __v_25: G = G::from_u64(0); let __v_26: G = { let __values: [G; 4] = [__v_23, __v_24, __v_25, __v_25]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_26]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_26]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_14, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_14, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(2); let __v_27: G = G::from_u64(0); let __v_28: G = { let __values: [G; 4] = [__v_26, __v_24, __v_25, __v_27]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_28]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_28]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_14, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_270] = { let __args: [G; IN_270] = [__v_14, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[270].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[270].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[270].bump_multiplicity(__i); } let __ret: [G; OUT_270] = unsafe { *(record.function_queries[270].output_at(__i).as_ptr() as *const [G; OUT_270]) }; __ret }, _ => aiur_fn_270(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(2); let __v_27: G = G::from_u64(0); let __v_28: G = { let __values: [G; 4] = [__v_26, __v_24, __v_25, __v_27]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_28]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_28]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = G::from_u64(8); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_22, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_22, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = { let __values: [G; 4] = [__v_25, __v_24, __v_26, __v_27]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_28]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_28]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_284] = { let __args: [G; IN_284] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[284].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[284].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[284].bump_multiplicity(__i); } let __ret: [G; OUT_284] = unsafe { *(record.function_queries[284].output_at(__i).as_ptr() as *const [G; OUT_284]) }; __ret }, _ => aiur_fn_284(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_283] = { let __args: [G; IN_283] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[283].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[283].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[283].bump_multiplicity(__i); } let __ret: [G; OUT_283] = unsafe { *(record.function_queries[283].output_at(__i).as_ptr() as *const [G; OUT_283]) }; __ret }, _ => aiur_fn_283(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_223] = { let __args: [G; IN_223] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[223].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[223].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[223].bump_multiplicity(__i); } let __ret: [G; OUT_223] = unsafe { *(record.function_queries[223].output_at(__i).as_ptr() as *const [G; OUT_223]) }; __ret }, _ => aiur_fn_223(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_222] = { let __args: [G; IN_222] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[222].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[222].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[222].bump_multiplicity(__i); } let __ret: [G; OUT_222] = unsafe { *(record.function_queries[222].output_at(__i).as_ptr() as *const [G; OUT_222]) }; __ret }, _ => aiur_fn_222(__args, record, io_buffer, __cu)? } }; let __v_26: G = G::from_u64(7); let __v_27: G = G::from_u64(1); let __v_28: G = G::from_u64(0); let __v_29: G = { let __values: [G; 4] = [__v_26, __v_27, __v_25, __v_28]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_29]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_29]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_284] = { let __args: [G; IN_284] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[284].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[284].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[284].bump_multiplicity(__i); } let __ret: [G; OUT_284] = unsafe { *(record.function_queries[284].output_at(__i).as_ptr() as *const [G; OUT_284]) }; __ret }, _ => aiur_fn_284(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_283] = { let __args: [G; IN_283] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[283].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[283].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[283].bump_multiplicity(__i); } let __ret: [G; OUT_283] = unsafe { *(record.function_queries[283].output_at(__i).as_ptr() as *const [G; OUT_283]) }; __ret }, _ => aiur_fn_283(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_269] = { let __args: [G; IN_269] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[269].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[269].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[269].bump_multiplicity(__i); } let __ret: [G; OUT_269] = unsafe { *(record.function_queries[269].output_at(__i).as_ptr() as *const [G; OUT_269]) }; __ret }, _ => aiur_fn_269(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_268] = { let __args: [G; IN_268] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[268].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[268].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[268].bump_multiplicity(__i); } let __ret: [G; OUT_268] = unsafe { *(record.function_queries[268].output_at(__i).as_ptr() as *const [G; OUT_268]) }; __ret }, _ => aiur_fn_268(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = G::from_u64(7); let __v_28: G = G::from_u64(0); let __v_29: G = G::from_u64(0); let __v_30: G = { let __values: [G; 4] = [__v_27, __v_28, __v_26, __v_29]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_30]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_30]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_23: G = G::from_u64(3); - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_6, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_6, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_7, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_7, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(0); let __v_27: G = { let __values: [G; 4] = [__v_23, __v_24, __v_25, __v_26]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_27]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_27]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { let __v_23: G = G::from_u64(4); - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_7, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_7, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_8, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_8, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(0); let __v_27: G = { let __values: [G; 4] = [__v_23, __v_24, __v_25, __v_26]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_27]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_27]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 9u64 => { let __v_23: G = G::from_u64(5); - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_8, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_8, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_9, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_9, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(0); let __v_27: G = { let __values: [G; 4] = [__v_23, __v_24, __v_25, __v_26]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_27]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_27]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 10u64 => { let __v_23: G = G::from_u64(6); - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_14, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_14, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_15, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_15, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_16, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_16, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = { let __values: [G; 4] = [__v_23, __v_24, __v_25, __v_26]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_272] = [__v_27]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_27]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 11u64 => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_24.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_25: G = __loaded[0]; @@ -25999,10 +25953,10 @@ fn aiur_fn_272( let __v_27: G = __loaded[2]; match __v_25.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_26, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_26, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_272] = [__v_28]; - record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_271] = [__v_28]; + record.function_queries[271].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -26017,15 +25971,15 @@ fn aiur_fn_272( }) } -const INPUT_SIZE_273: usize = 17; -const IN_273: usize = 17; -const OUT_273: usize = 12; -fn aiur_fn_273( - inp: [G; IN_273], +const INPUT_SIZE_272: usize = 17; +const IN_272: usize = 17; +const OUT_272: usize = 12; +fn aiur_fn_272( + inp: [G; IN_272], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_273], ExecError> { +) -> Result<[G; OUT_272], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26046,9 +26000,9 @@ fn aiur_fn_273( let __v_16: G = inp[16]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_10, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_10, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_11, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_11, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; @@ -26056,8 +26010,8 @@ fn aiur_fn_273( 0u64 => { let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(0); - let __ret: [G; OUT_273] = [__v_20, __v_19, __v_17, __v_18, __v_1, __v_16, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; - record.function_queries[273].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_272] = [__v_20, __v_19, __v_17, __v_18, __v_1, __v_16, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; + record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -26075,15 +26029,15 @@ fn aiur_fn_273( let __v_20: G = __mc_out___mc_0[0]; let __v_21: G = G::from_u64(3); let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_273] = [__v_21, __v_19, __v_17, __v_18, __v_20, __v_22, __v_22, __v_22, __v_22, __v_22, __v_22, __v_22]; - record.function_queries[273].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_272] = [__v_21, __v_19, __v_17, __v_18, __v_20, __v_22, __v_22, __v_22, __v_22, __v_22, __v_22, __v_22]; + record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_20: G = G::from_u64(2); let __v_21: G = G::from_u64(0); - let __ret: [G; OUT_273] = [__v_20, __v_19, __v_17, __v_18, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; - record.function_queries[273].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_272] = [__v_20, __v_19, __v_17, __v_18, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; + record.function_queries[272].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -26095,15 +26049,15 @@ fn aiur_fn_273( }) } -const INPUT_SIZE_274: usize = 14; -const IN_274: usize = 14; -const OUT_274: usize = 12; -fn aiur_fn_274( - inp: [G; IN_274], +const INPUT_SIZE_273: usize = 14; +const IN_273: usize = 14; +const OUT_273: usize = 12; +fn aiur_fn_273( + inp: [G; IN_273], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_274], ExecError> { +) -> Result<[G; OUT_273], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26121,29 +26075,29 @@ fn aiur_fn_274( let __v_13: G = inp[13]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(0); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_274] = [__v_15, __v_16, __v_14, __v_0, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17]; - record.function_queries[274].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_273] = [__v_15, __v_16, __v_14, __v_0, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17]; + record.function_queries[273].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_275: usize = 14; -const IN_275: usize = 14; -const OUT_275: usize = 12; -fn aiur_fn_275( - inp: [G; IN_275], +const INPUT_SIZE_274: usize = 14; +const IN_274: usize = 14; +const OUT_274: usize = 12; +fn aiur_fn_274( + inp: [G; IN_274], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_275], ExecError> { +) -> Result<[G; OUT_274], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26161,29 +26115,29 @@ fn aiur_fn_275( let __v_13: G = inp[13]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(4); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_275] = [__v_15, __v_16, __v_14, __v_0, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17]; - record.function_queries[275].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_274] = [__v_15, __v_16, __v_14, __v_0, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17]; + record.function_queries[274].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_276: usize = 1; -const IN_276: usize = 1; -const OUT_276: usize = 1; -fn aiur_fn_276( - inp: [G; IN_276], +const INPUT_SIZE_275: usize = 1; +const IN_275: usize = 1; +const OUT_275: usize = 1; +fn aiur_fn_275( + inp: [G; IN_275], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_276], ExecError> { +) -> Result<[G; OUT_275], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 36] = { let __mq = record.memory_queries.get_mut(&36).ok_or(ExecError::InvalidMemorySize(36))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 36 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 36] = __args[..36].try_into().unwrap(); __arr }; @@ -26226,17 +26180,17 @@ fn aiur_fn_276( match __v_1.as_canonical_u64() { 1u64 => { let __v_37: G = G::from_u64(0); - let __ret: [G; OUT_276] = [__v_37]; - record.function_queries[276].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_275] = [__v_37]; + record.function_queries[275].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_276] = { let __args: [G; IN_276] = [__v_36]; let __cu = unconstrained; let __hit = record.function_queries[276].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[276].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[276].bump_multiplicity(__i); } let __ret: [G; OUT_276] = unsafe { *(record.function_queries[276].output_at(__i).as_ptr() as *const [G; OUT_276]) }; __ret }, _ => aiur_fn_276(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_275] = { let __args: [G; IN_275] = [__v_36]; let __cu = unconstrained; let __hit = record.function_queries[275].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[275].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[275].bump_multiplicity(__i); } let __ret: [G; OUT_275] = unsafe { *(record.function_queries[275].output_at(__i).as_ptr() as *const [G; OUT_275]) }; __ret }, _ => aiur_fn_275(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = G::from_u64(1); let __v_39: G = (__v_37 + __v_38); - let __ret: [G; OUT_276] = [__v_39]; - record.function_queries[276].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_275] = [__v_39]; + record.function_queries[275].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -26246,15 +26200,15 @@ fn aiur_fn_276( }) } -const INPUT_SIZE_277: usize = 2; -const IN_277: usize = 2; -const OUT_277: usize = 34; -fn aiur_fn_277( - inp: [G; IN_277], +const INPUT_SIZE_276: usize = 2; +const IN_276: usize = 2; +const OUT_276: usize = 34; +fn aiur_fn_276( + inp: [G; IN_276], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_277], ExecError> { +) -> Result<[G; OUT_276], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26299,14 +26253,14 @@ fn aiur_fn_277( 0u64 => { match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_277] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36]; - record.function_queries[277].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_276] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36]; + record.function_queries[276].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_38: G = G::from_u64(1); let __v_39: G = (__v_1 - __v_38); - let __r_arr: [G; OUT_277] = { let __args: [G; IN_277] = [__v_37, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[277].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[277].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[277].bump_multiplicity(__i); } let __ret: [G; OUT_277] = unsafe { *(record.function_queries[277].output_at(__i).as_ptr() as *const [G; OUT_277]) }; __ret }, _ => aiur_fn_277(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_276] = { let __args: [G; IN_276] = [__v_37, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[276].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[276].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[276].bump_multiplicity(__i); } let __ret: [G; OUT_276] = unsafe { *(record.function_queries[276].output_at(__i).as_ptr() as *const [G; OUT_276]) }; __ret }, _ => aiur_fn_276(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; let __v_41: G = __r_arr[1]; let __v_42: G = __r_arr[2]; @@ -26341,8 +26295,8 @@ fn aiur_fn_277( let __v_71: G = __r_arr[31]; let __v_72: G = __r_arr[32]; let __v_73: G = __r_arr[33]; - let __ret: [G; OUT_277] = [__v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73]; - record.function_queries[277].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_276] = [__v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73]; + record.function_queries[276].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -26354,15 +26308,15 @@ fn aiur_fn_277( }) } -const INPUT_SIZE_278: usize = 33; -const IN_278: usize = 33; -const OUT_278: usize = 12; -fn aiur_fn_278( - inp: [G; IN_278], +const INPUT_SIZE_277: usize = 33; +const IN_277: usize = 33; +const OUT_277: usize = 12; +fn aiur_fn_277( + inp: [G; IN_277], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_278], ExecError> { +) -> Result<[G; OUT_277], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26399,7 +26353,7 @@ fn aiur_fn_278( let __v_32: G = inp[32]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_25, __v_29, __v_30, __v_31, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_25, __v_29, __v_30, __v_31, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; let __v_34: G = G::from_u64(5); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; @@ -26408,26 +26362,26 @@ fn aiur_fn_278( let __v_36: G = __r_arr[0]; let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; - let __r_arr: [G; OUT_276] = { let __args: [G; IN_276] = [__v_26]; let __cu = unconstrained; let __hit = record.function_queries[276].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[276].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[276].bump_multiplicity(__i); } let __ret: [G; OUT_276] = unsafe { *(record.function_queries[276].output_at(__i).as_ptr() as *const [G; OUT_276]) }; __ret }, _ => aiur_fn_276(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_275] = { let __args: [G; IN_275] = [__v_26]; let __cu = unconstrained; let __hit = record.function_queries[275].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[275].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[275].bump_multiplicity(__i); } let __ret: [G; OUT_275] = unsafe { *(record.function_queries[275].output_at(__i).as_ptr() as *const [G; OUT_275]) }; __ret }, _ => aiur_fn_275(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = G::from_u64(0); - let __ret: [G; OUT_278] = [__v_34, __v_35, __v_33, __v_36, __v_37, __v_38, __v_0, __v_27, __v_28, __v_39, __v_39, __v_39]; - record.function_queries[278].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_277] = [__v_34, __v_35, __v_33, __v_36, __v_37, __v_38, __v_0, __v_27, __v_28, __v_39, __v_39, __v_39]; + record.function_queries[277].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_279: usize = 40; -const IN_279: usize = 40; -const OUT_279: usize = 12; -fn aiur_fn_279( - inp: [G; IN_279], +const INPUT_SIZE_278: usize = 40; +const IN_278: usize = 40; +const OUT_278: usize = 12; +fn aiur_fn_278( + inp: [G; IN_278], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_279], ExecError> { +) -> Result<[G; OUT_278], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26471,7 +26425,7 @@ fn aiur_fn_279( let __v_39: G = inp[39]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_33, __v_36, __v_37, __v_38, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_33, __v_36, __v_37, __v_38, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; let __v_41: G = G::from_u64(6); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; @@ -26483,23 +26437,23 @@ fn aiur_fn_279( let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; let __v_46: G = G::from_u64(0); - let __ret: [G; OUT_279] = [__v_41, __v_42, __v_40, __v_34, __v_35, __v_43, __v_44, __v_45, __v_0, __v_46, __v_46, __v_46]; - record.function_queries[279].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_278] = [__v_41, __v_42, __v_40, __v_34, __v_35, __v_43, __v_44, __v_45, __v_0, __v_46, __v_46, __v_46]; + record.function_queries[278].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_280: usize = 6; -const IN_280: usize = 6; -const OUT_280: usize = 1; -fn aiur_fn_280( - inp: [G; IN_280], +const INPUT_SIZE_279: usize = 6; +const IN_279: usize = 6; +const OUT_279: usize = 1; +fn aiur_fn_279( + inp: [G; IN_279], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_280], ExecError> { +) -> Result<[G; OUT_279], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26524,25 +26478,25 @@ fn aiur_fn_280( let __v_17: G = G::from_u64(1); let __v_18: G = G::from_u64(1); let __v_19: G = { let __values: [G; 5] = [__v_17, __v_18, __v_18, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_280] = [__v_19]; - record.function_queries[280].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_279] = [__v_19]; + record.function_queries[279].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_7.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_15, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_15, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = G::from_u64(0); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = G::from_u64(1); let __v_21: G = (__v_5 + __v_20); - let __r_arr: [G; OUT_280] = { let __args: [G; IN_280] = [__v_16, __v_1, __v_2, __v_3, __v_4, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[280].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[280].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[280].bump_multiplicity(__i); } let __ret: [G; OUT_280] = unsafe { *(record.function_queries[280].output_at(__i).as_ptr() as *const [G; OUT_280]) }; __ret }, _ => aiur_fn_280(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_279] = { let __args: [G; IN_279] = [__v_16, __v_1, __v_2, __v_3, __v_4, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[279].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[279].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[279].bump_multiplicity(__i); } let __ret: [G; OUT_279] = unsafe { *(record.function_queries[279].output_at(__i).as_ptr() as *const [G; OUT_279]) }; __ret }, _ => aiur_fn_279(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = { let __values: [G; 5] = [__v_18, __v_5, __v_19, __v_17, __v_22]; let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_280] = [__v_23]; - record.function_queries[280].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_279] = [__v_23]; + record.function_queries[279].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -26554,15 +26508,15 @@ fn aiur_fn_280( }) } -const INPUT_SIZE_281: usize = 50; -const IN_281: usize = 50; -const OUT_281: usize = 12; -fn aiur_fn_281( - inp: [G; IN_281], +const INPUT_SIZE_280: usize = 50; +const IN_280: usize = 50; +const OUT_280: usize = 12; +fn aiur_fn_280( + inp: [G; IN_280], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_281], ExecError> { +) -> Result<[G; OUT_280], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26616,10 +26570,10 @@ fn aiur_fn_281( let __v_49: G = inp[49]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_42, __v_46, __v_47, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_271] = { let __args: [G; IN_271] = [__v_42, __v_46, __v_47, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[271].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[271].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[271].bump_multiplicity(__i); } let __ret: [G; OUT_271] = unsafe { *(record.function_queries[271].output_at(__i).as_ptr() as *const [G; OUT_271]) }; __ret }, _ => aiur_fn_271(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __v_51: G = G::from_u64(0); - let __r_arr: [G; OUT_280] = { let __args: [G; IN_280] = [__v_43, __v_46, __v_47, __v_48, __v_49, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[280].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[280].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[280].bump_multiplicity(__i); } let __ret: [G; OUT_280] = unsafe { *(record.function_queries[280].output_at(__i).as_ptr() as *const [G; OUT_280]) }; __ret }, _ => aiur_fn_280(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_279] = { let __args: [G; IN_279] = [__v_43, __v_46, __v_47, __v_48, __v_49, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[279].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[279].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[279].bump_multiplicity(__i); } let __ret: [G; OUT_279] = unsafe { *(record.function_queries[279].output_at(__i).as_ptr() as *const [G; OUT_279]) }; __ret }, _ => aiur_fn_279(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = G::from_u64(7); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; @@ -26632,23 +26586,23 @@ fn aiur_fn_281( let __v_57: G = __r_arr[0]; let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_58: G = __r_arr[0]; - let __ret: [G; OUT_281] = [__v_53, __v_54, __v_50, __v_55, __v_56, __v_57, __v_58, __v_52, __v_0, __v_1, __v_44, __v_45]; - record.function_queries[281].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_280] = [__v_53, __v_54, __v_50, __v_55, __v_56, __v_57, __v_58, __v_52, __v_0, __v_1, __v_44, __v_45]; + record.function_queries[280].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_282: usize = 1; -const IN_282: usize = 1; -const OUT_282: usize = 48; -fn aiur_fn_282( - inp: [G; IN_282], +const INPUT_SIZE_281: usize = 1; +const IN_281: usize = 1; +const OUT_281: usize = 48; +fn aiur_fn_281( + inp: [G; IN_281], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_282], ExecError> { +) -> Result<[G; OUT_281], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 32] = { let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 32 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 32] = __args[..32].try_into().unwrap(); __arr }; @@ -26757,21 +26711,21 @@ fn aiur_fn_282( if (__v_89 != __v_91) { return Err(ExecError::AssertEqMismatch { lhs: __v_89.as_canonical_u64(), rhs: __v_91.as_canonical_u64(), msg: Some("trailing bytes after constant on ch 2".to_string()) }); } - let __ret: [G; OUT_282] = [__v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85]; - record.function_queries[282].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_281] = [__v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85]; + record.function_queries[281].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_283: usize = 1; -const IN_283: usize = 1; -const OUT_283: usize = 1; -fn aiur_fn_283( - inp: [G; IN_283], +const INPUT_SIZE_282: usize = 1; +const IN_282: usize = 1; +const OUT_282: usize = 1; +fn aiur_fn_282( + inp: [G; IN_282], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_283], ExecError> { +) -> Result<[G; OUT_282], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 32] = { let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 32 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 32] = __args[..32].try_into().unwrap(); __arr }; @@ -26820,8 +26774,8 @@ fn aiur_fn_283( let __v_40: G = __loaded[2]; match __v_38.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_283] = [__v_39]; - record.function_queries[283].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_282] = [__v_39]; + record.function_queries[282].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -26831,15 +26785,15 @@ fn aiur_fn_283( }) } -const INPUT_SIZE_284: usize = 1; -const IN_284: usize = 1; -const OUT_284: usize = 1; -fn aiur_fn_284( - inp: [G; IN_284], +const INPUT_SIZE_283: usize = 1; +const IN_283: usize = 1; +const OUT_283: usize = 1; +fn aiur_fn_283( + inp: [G; IN_283], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_284], ExecError> { +) -> Result<[G; OUT_283], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 32] = { let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 32 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 32] = __args[..32].try_into().unwrap(); __arr }; @@ -26883,43 +26837,43 @@ fn aiur_fn_284( let __r_arr: [G; OUT_3] = { let __args: [G; IN_3] = [__v_36, __v_34, __v_35]; let __cu = true; let __hit = record.function_queries[3].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_3] = unsafe { *(record.function_queries[3].output_at(__i).as_ptr() as *const [G; OUT_3]) }; __ret }, _ => aiur_fn_3(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __r_arr: [G; OUT_21] = { let __args: [G; IN_21] = [__v_37, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[21].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[21].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[21].bump_multiplicity(__i); } let __ret: [G; OUT_21] = unsafe { *(record.function_queries[21].output_at(__i).as_ptr() as *const [G; OUT_21]) }; __ret }, _ => aiur_fn_21(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_284] = [__v_37]; - record.function_queries[284].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_283] = [__v_37]; + record.function_queries[283].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_285: usize = 2; -const IN_285: usize = 2; -const OUT_285: usize = 1; -fn aiur_fn_285( - inp: [G; IN_285], +const INPUT_SIZE_284: usize = 2; +const IN_284: usize = 2; +const OUT_284: usize = 1; +fn aiur_fn_284( + inp: [G; IN_284], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_285], ExecError> { +) -> Result<[G; OUT_284], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_0.as_canonical_u64() { 2u64 => { let __v_2: G = G::from_u64(0); - let __ret: [G; OUT_285] = [__v_2]; - record.function_queries[285].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_284] = [__v_2]; + record.function_queries[284].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { match __v_1.as_canonical_u64() { 0u64 => { let __v_2: G = G::from_u64(1); - let __ret: [G; OUT_285] = [__v_2]; - record.function_queries[285].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_284] = [__v_2]; + record.function_queries[284].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_2: G = G::from_u64(0); - let __ret: [G; OUT_285] = [__v_2]; - record.function_queries[285].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_284] = [__v_2]; + record.function_queries[284].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -26928,14 +26882,14 @@ fn aiur_fn_285( match __v_1.as_canonical_u64() { 1u64 => { let __v_2: G = G::from_u64(0); - let __ret: [G; OUT_285] = [__v_2]; - record.function_queries[285].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_284] = [__v_2]; + record.function_queries[284].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_2: G = G::from_u64(1); - let __ret: [G; OUT_285] = [__v_2]; - record.function_queries[285].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_284] = [__v_2]; + record.function_queries[284].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -26947,15 +26901,15 @@ fn aiur_fn_285( }) } -const INPUT_SIZE_286: usize = 14; -const IN_286: usize = 14; -const OUT_286: usize = 1; -fn aiur_fn_286( - inp: [G; IN_286], +const INPUT_SIZE_285: usize = 14; +const IN_285: usize = 14; +const OUT_285: usize = 1; +fn aiur_fn_285( + inp: [G; IN_285], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_286], ExecError> { +) -> Result<[G; OUT_285], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -26973,22 +26927,22 @@ fn aiur_fn_286( let __v_13: G = inp[13]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_285] = { let __args: [G; IN_285] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[285].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[285].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[285].bump_multiplicity(__i); } let __ret: [G; OUT_285] = unsafe { *(record.function_queries[285].output_at(__i).as_ptr() as *const [G; OUT_285]) }; __ret }, _ => aiur_fn_285(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_284] = { let __args: [G; IN_284] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[284].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[284].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[284].bump_multiplicity(__i); } let __ret: [G; OUT_284] = unsafe { *(record.function_queries[284].output_at(__i).as_ptr() as *const [G; OUT_284]) }; __ret }, _ => aiur_fn_284(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; match __v_14.as_canonical_u64() { 0u64 => { let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_286] = [__v_17]; - record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_285] = [__v_17]; + record.function_queries[285].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_286] = [__v_15]; - record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_285] = [__v_15]; + record.function_queries[285].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -26997,18 +26951,18 @@ fn aiur_fn_286( }) } -const INPUT_SIZE_287: usize = 1; -const IN_287: usize = 1; -const OUT_287: usize = 1; -fn aiur_fn_287( - inp: [G; IN_287], +const INPUT_SIZE_286: usize = 1; +const IN_286: usize = 1; +const OUT_286: usize = 1; +fn aiur_fn_286( + inp: [G; IN_286], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_287], ExecError> { +) -> Result<[G; OUT_286], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = __r_arr[1]; let __v_3: G = __r_arr[2]; @@ -27061,11 +27015,11 @@ fn aiur_fn_287( _ => { match __v_1.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_283] = { let __args: [G; IN_283] = [__v_0]; let __cu = true; let __hit = record.function_queries[283].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_283] = unsafe { *(record.function_queries[283].output_at(__i).as_ptr() as *const [G; OUT_283]) }; __ret }, _ => aiur_fn_283(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = true; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_285] = { let __args: [G; IN_285] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[285].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[285].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[285].bump_multiplicity(__i); } let __ret: [G; OUT_285] = unsafe { *(record.function_queries[285].output_at(__i).as_ptr() as *const [G; OUT_285]) }; __ret }, _ => aiur_fn_285(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_284] = { let __args: [G; IN_284] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[284].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[284].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[284].bump_multiplicity(__i); } let __ret: [G; OUT_284] = unsafe { *(record.function_queries[284].output_at(__i).as_ptr() as *const [G; OUT_284]) }; __ret }, _ => aiur_fn_284(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; match __v_50.as_canonical_u64() { 0u64 => { @@ -27087,7 +27041,7 @@ fn aiur_fn_287( } }; let __v_50: G = __mc_out___mc_0[0]; - let __r_arr: [G; OUT_273] = { let __args: [G; IN_273] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_46, __v_47, __v_50, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[273].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[273].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[273].bump_multiplicity(__i); } let __ret: [G; OUT_273] = unsafe { *(record.function_queries[273].output_at(__i).as_ptr() as *const [G; OUT_273]) }; __ret }, _ => aiur_fn_273(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_46, __v_47, __v_50, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; let __v_52: G = __r_arr[1]; let __v_53: G = __r_arr[2]; @@ -27101,15 +27055,15 @@ fn aiur_fn_287( let __v_61: G = __r_arr[10]; let __v_62: G = __r_arr[11]; let __v_63: G = { let __values: [G; 12] = [__v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_287] = [__v_63]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_63]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_49: G = G::from_u64(1); let __v_50: G = G::from_u64(1); let __v_51: G = { let __values: [G; 3] = [__v_49, __v_50, __v_50]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_274] = { let __args: [G; IN_274] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_46, __v_47, __v_51, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[274].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[274].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[274].bump_multiplicity(__i); } let __ret: [G; OUT_274] = unsafe { *(record.function_queries[274].output_at(__i).as_ptr() as *const [G; OUT_274]) }; __ret }, _ => aiur_fn_274(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_273] = { let __args: [G; IN_273] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_46, __v_47, __v_51, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[273].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[273].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[273].bump_multiplicity(__i); } let __ret: [G; OUT_273] = unsafe { *(record.function_queries[273].output_at(__i).as_ptr() as *const [G; OUT_273]) }; __ret }, _ => aiur_fn_273(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = __r_arr[1]; let __v_54: G = __r_arr[2]; @@ -27123,15 +27077,15 @@ fn aiur_fn_287( let __v_62: G = __r_arr[10]; let __v_63: G = __r_arr[11]; let __v_64: G = { let __values: [G; 12] = [__v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_287] = [__v_64]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_64]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_49: G = G::from_u64(1); let __v_50: G = G::from_u64(1); let __v_51: G = { let __values: [G; 3] = [__v_49, __v_50, __v_50]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_275] = { let __args: [G; IN_275] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_46, __v_47, __v_51, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[275].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[275].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[275].bump_multiplicity(__i); } let __ret: [G; OUT_275] = unsafe { *(record.function_queries[275].output_at(__i).as_ptr() as *const [G; OUT_275]) }; __ret }, _ => aiur_fn_275(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_274] = { let __args: [G; IN_274] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_46, __v_47, __v_51, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[274].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[274].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[274].bump_multiplicity(__i); } let __ret: [G; OUT_274] = unsafe { *(record.function_queries[274].output_at(__i).as_ptr() as *const [G; OUT_274]) }; __ret }, _ => aiur_fn_274(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = __r_arr[1]; let __v_54: G = __r_arr[2]; @@ -27145,17 +27099,17 @@ fn aiur_fn_287( let __v_62: G = __r_arr[10]; let __v_63: G = __r_arr[11]; let __v_64: G = { let __values: [G; 12] = [__v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_287] = [__v_64]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_64]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_288] = { let __args: [G; IN_288] = [__v_0, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[288].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[288].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[288].bump_multiplicity(__i); } let __ret: [G; OUT_288] = unsafe { *(record.function_queries[288].output_at(__i).as_ptr() as *const [G; OUT_288]) }; __ret }, _ => aiur_fn_288(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __ret: [G; OUT_287] = [__v_49]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_49]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -27165,10 +27119,10 @@ fn aiur_fn_287( _ => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_10, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_288] = { let __args: [G; IN_288] = [__v_10, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[288].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[288].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[288].bump_multiplicity(__i); } let __ret: [G; OUT_288] = unsafe { *(record.function_queries[288].output_at(__i).as_ptr() as *const [G; OUT_288]) }; __ret }, _ => aiur_fn_288(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_287] = [__v_50]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_50]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -27180,10 +27134,10 @@ fn aiur_fn_287( let __v_49: G = __r_arr[0]; let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_18, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_18, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __ret: [G; OUT_287] = [__v_51]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_51]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -27193,10 +27147,10 @@ fn aiur_fn_287( _ => { let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_291] = { let __args: [G; IN_291] = [__v_10, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[291].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[291].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[291].bump_multiplicity(__i); } let __ret: [G; OUT_291] = unsafe { *(record.function_queries[291].output_at(__i).as_ptr() as *const [G; OUT_291]) }; __ret }, _ => aiur_fn_291(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_10, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_287] = [__v_50]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_50]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -27208,7 +27162,7 @@ fn aiur_fn_287( let __v_52: G = { let __values: [G; 3] = [__v_50, __v_51, __v_51]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_53: G = { let __values: [G; 3] = [__v_49, __v_0, __v_52]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_54: G = G::from_u64(0); - let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_0, __v_54, __v_46, __v_47, __v_53, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_280] = { let __args: [G; IN_280] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_0, __v_54, __v_46, __v_47, __v_53, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[280].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[280].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[280].bump_multiplicity(__i); } let __ret: [G; OUT_280] = unsafe { *(record.function_queries[280].output_at(__i).as_ptr() as *const [G; OUT_280]) }; __ret }, _ => aiur_fn_280(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __v_56: G = __r_arr[1]; let __v_57: G = __r_arr[2]; @@ -27222,8 +27176,8 @@ fn aiur_fn_287( let __v_65: G = __r_arr[10]; let __v_66: G = __r_arr[11]; let __v_67: G = { let __values: [G; 12] = [__v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_287] = [__v_67]; - record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_286] = [__v_67]; + record.function_queries[286].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -27235,15 +27189,15 @@ fn aiur_fn_287( }) } -const INPUT_SIZE_288: usize = 10; -const IN_288: usize = 10; -const OUT_288: usize = 1; -fn aiur_fn_288( - inp: [G; IN_288], +const INPUT_SIZE_287: usize = 10; +const IN_287: usize = 10; +const OUT_287: usize = 1; +fn aiur_fn_287( + inp: [G; IN_287], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_288], ExecError> { +) -> Result<[G; OUT_287], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -27255,7 +27209,7 @@ fn aiur_fn_288( let __v_7: G = inp[7]; let __v_8: G = inp[8]; let __v_9: G = inp[9]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; @@ -27308,7 +27262,7 @@ fn aiur_fn_288( _ => { match __v_10.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_779] = { let __args: [G; IN_779] = [__v_11, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[779].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[779].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[779].bump_multiplicity(__i); } let __ret: [G; OUT_779] = unsafe { *(record.function_queries[779].output_at(__i).as_ptr() as *const [G; OUT_779]) }; __ret }, _ => aiur_fn_779(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_778] = { let __args: [G; IN_778] = [__v_11, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[778].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[778].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[778].bump_multiplicity(__i); } let __ret: [G; OUT_778] = unsafe { *(record.function_queries[778].output_at(__i).as_ptr() as *const [G; OUT_778]) }; __ret }, _ => aiur_fn_778(__args, record, io_buffer, __cu)? } }; let __v_58: G = __r_arr[0]; let __v_59: G = __r_arr[1]; let __v_60: G = __r_arr[2]; @@ -27356,11 +27310,11 @@ fn aiur_fn_288( let __v_102: G = __r_arr[44]; match __v_58.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_283] = { let __args: [G; IN_283] = [__v_0]; let __cu = true; let __hit = record.function_queries[283].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_283] = unsafe { *(record.function_queries[283].output_at(__i).as_ptr() as *const [G; OUT_283]) }; __ret }, _ => aiur_fn_283(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = true; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if true => { let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; let __v_103: G = __r_arr[0]; - let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_11, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_285] = { let __args: [G; IN_285] = [__v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_11, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[285].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[285].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[285].bump_multiplicity(__i); } let __ret: [G; OUT_285] = unsafe { *(record.function_queries[285].output_at(__i).as_ptr() as *const [G; OUT_285]) }; __ret }, _ => aiur_fn_285(__args, record, io_buffer, __cu)? } }; let __v_104: G = __r_arr[0]; - let __r_arr: [G; OUT_273] = { let __args: [G; IN_273] = [__v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_55, __v_56, __v_104, __v_57, __v_103]; let __cu = unconstrained; let __hit = record.function_queries[273].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[273].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[273].bump_multiplicity(__i); } let __ret: [G; OUT_273] = unsafe { *(record.function_queries[273].output_at(__i).as_ptr() as *const [G; OUT_273]) }; __ret }, _ => aiur_fn_273(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_272] = { let __args: [G; IN_272] = [__v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_55, __v_56, __v_104, __v_57, __v_103]; let __cu = unconstrained; let __hit = record.function_queries[272].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[272].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[272].bump_multiplicity(__i); } let __ret: [G; OUT_272] = unsafe { *(record.function_queries[272].output_at(__i).as_ptr() as *const [G; OUT_272]) }; __ret }, _ => aiur_fn_272(__args, record, io_buffer, __cu)? } }; let __v_105: G = __r_arr[0]; let __v_106: G = __r_arr[1]; let __v_107: G = __r_arr[2]; @@ -27374,8 +27328,8 @@ fn aiur_fn_288( let __v_115: G = __r_arr[10]; let __v_116: G = __r_arr[11]; let __v_117: G = { let __values: [G; 12] = [__v_105, __v_106, __v_107, __v_108, __v_109, __v_110, __v_111, __v_112, __v_113, __v_114, __v_115, __v_116]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_288] = [__v_117]; - record.function_queries[288].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_287] = [__v_117]; + record.function_queries[287].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -27392,19 +27346,19 @@ fn aiur_fn_288( }) } -const INPUT_SIZE_289: usize = 2; -const IN_289: usize = 2; -const OUT_289: usize = 1; -fn aiur_fn_289( - inp: [G; IN_289], +const INPUT_SIZE_288: usize = 2; +const IN_288: usize = 2; +const OUT_288: usize = 1; +fn aiur_fn_288( + inp: [G; IN_288], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_289], ExecError> { +) -> Result<[G; OUT_288], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -27457,7 +27411,7 @@ fn aiur_fn_289( _ => { match __v_2.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_291] = { let __args: [G; IN_291] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[291].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[291].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[291].bump_multiplicity(__i); } let __ret: [G; OUT_291] = unsafe { *(record.function_queries[291].output_at(__i).as_ptr() as *const [G; OUT_291]) }; __ret }, _ => aiur_fn_291(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __v_51: G = __r_arr[1]; let __v_52: G = __r_arr[2]; @@ -27505,9 +27459,9 @@ fn aiur_fn_289( let __v_94: G = __r_arr[44]; match __v_50.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; let __v_95: G = __r_arr[0]; - let __r_arr: [G; OUT_278] = { let __args: [G; IN_278] = [__v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_0, __v_1, __v_47, __v_48, __v_95, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[278].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[278].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[278].bump_multiplicity(__i); } let __ret: [G; OUT_278] = unsafe { *(record.function_queries[278].output_at(__i).as_ptr() as *const [G; OUT_278]) }; __ret }, _ => aiur_fn_278(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_277] = { let __args: [G; IN_277] = [__v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_0, __v_1, __v_47, __v_48, __v_95, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[277].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[277].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[277].bump_multiplicity(__i); } let __ret: [G; OUT_277] = unsafe { *(record.function_queries[277].output_at(__i).as_ptr() as *const [G; OUT_277]) }; __ret }, _ => aiur_fn_277(__args, record, io_buffer, __cu)? } }; let __v_96: G = __r_arr[0]; let __v_97: G = __r_arr[1]; let __v_98: G = __r_arr[2]; @@ -27521,8 +27475,8 @@ fn aiur_fn_289( let __v_106: G = __r_arr[10]; let __v_107: G = __r_arr[11]; let __v_108: G = { let __values: [G; 12] = [__v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_289] = [__v_108]; - record.function_queries[289].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_288] = [__v_108]; + record.function_queries[288].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -27539,20 +27493,20 @@ fn aiur_fn_289( }) } -const INPUT_SIZE_290: usize = 3; -const IN_290: usize = 3; -const OUT_290: usize = 1; -fn aiur_fn_290( - inp: [G; IN_290], +const INPUT_SIZE_289: usize = 3; +const IN_289: usize = 3; +const OUT_289: usize = 1; +fn aiur_fn_289( + inp: [G; IN_289], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_290], ExecError> { +) -> Result<[G; OUT_289], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = __r_arr[2]; @@ -27605,7 +27559,7 @@ fn aiur_fn_290( _ => { match __v_3.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_291] = { let __args: [G; IN_291] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[291].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[291].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[291].bump_multiplicity(__i); } let __ret: [G; OUT_291] = unsafe { *(record.function_queries[291].output_at(__i).as_ptr() as *const [G; OUT_291]) }; __ret }, _ => aiur_fn_291(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; let __v_52: G = __r_arr[1]; let __v_53: G = __r_arr[2]; @@ -27655,7 +27609,7 @@ fn aiur_fn_290( 1u64 => { match __v_52.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_277] = { let __args: [G; IN_277] = [__v_78, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[277].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[277].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[277].bump_multiplicity(__i); } let __ret: [G; OUT_277] = unsafe { *(record.function_queries[277].output_at(__i).as_ptr() as *const [G; OUT_277]) }; __ret }, _ => aiur_fn_277(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_276] = { let __args: [G; IN_276] = [__v_78, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[276].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[276].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[276].bump_multiplicity(__i); } let __ret: [G; OUT_276] = unsafe { *(record.function_queries[276].output_at(__i).as_ptr() as *const [G; OUT_276]) }; __ret }, _ => aiur_fn_276(__args, record, io_buffer, __cu)? } }; let __v_96: G = __r_arr[0]; let __v_97: G = __r_arr[1]; let __v_98: G = __r_arr[2]; @@ -27690,9 +27644,9 @@ fn aiur_fn_290( let __v_127: G = __r_arr[31]; let __v_128: G = __r_arr[32]; let __v_129: G = __r_arr[33]; - let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_4, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_4, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; let __v_130: G = __r_arr[0]; - let __r_arr: [G; OUT_279] = { let __args: [G; IN_279] = [__v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107, __v_108, __v_109, __v_110, __v_111, __v_112, __v_113, __v_114, __v_115, __v_116, __v_117, __v_118, __v_119, __v_120, __v_121, __v_122, __v_123, __v_124, __v_125, __v_126, __v_127, __v_128, __v_129, __v_0, __v_1, __v_48, __v_49, __v_130, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[279].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[279].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[279].bump_multiplicity(__i); } let __ret: [G; OUT_279] = unsafe { *(record.function_queries[279].output_at(__i).as_ptr() as *const [G; OUT_279]) }; __ret }, _ => aiur_fn_279(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_278] = { let __args: [G; IN_278] = [__v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107, __v_108, __v_109, __v_110, __v_111, __v_112, __v_113, __v_114, __v_115, __v_116, __v_117, __v_118, __v_119, __v_120, __v_121, __v_122, __v_123, __v_124, __v_125, __v_126, __v_127, __v_128, __v_129, __v_0, __v_1, __v_48, __v_49, __v_130, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[278].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[278].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[278].bump_multiplicity(__i); } let __ret: [G; OUT_278] = unsafe { *(record.function_queries[278].output_at(__i).as_ptr() as *const [G; OUT_278]) }; __ret }, _ => aiur_fn_278(__args, record, io_buffer, __cu)? } }; let __v_131: G = __r_arr[0]; let __v_132: G = __r_arr[1]; let __v_133: G = __r_arr[2]; @@ -27706,8 +27660,8 @@ fn aiur_fn_290( let __v_141: G = __r_arr[10]; let __v_142: G = __r_arr[11]; let __v_143: G = { let __values: [G; 12] = [__v_131, __v_132, __v_133, __v_134, __v_135, __v_136, __v_137, __v_138, __v_139, __v_140, __v_141, __v_142]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_290] = [__v_143]; - record.function_queries[290].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_289] = [__v_143]; + record.function_queries[289].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -27726,19 +27680,19 @@ fn aiur_fn_290( }) } -const INPUT_SIZE_291: usize = 2; -const IN_291: usize = 2; -const OUT_291: usize = 1; -fn aiur_fn_291( - inp: [G; IN_291], +const INPUT_SIZE_290: usize = 2; +const IN_290: usize = 2; +const OUT_290: usize = 1; +fn aiur_fn_290( + inp: [G; IN_290], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_291], ExecError> { +) -> Result<[G; OUT_290], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -27791,7 +27745,7 @@ fn aiur_fn_291( _ => { match __v_2.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_291] = { let __args: [G; IN_291] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[291].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[291].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[291].bump_multiplicity(__i); } let __ret: [G; OUT_291] = unsafe { *(record.function_queries[291].output_at(__i).as_ptr() as *const [G; OUT_291]) }; __ret }, _ => aiur_fn_291(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __v_51: G = __r_arr[1]; let __v_52: G = __r_arr[2]; @@ -27839,9 +27793,9 @@ fn aiur_fn_291( let __v_94: G = __r_arr[44]; match __v_50.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; let __v_95: G = __r_arr[0]; - let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_0, __v_1, __v_47, __v_48, __v_95, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_280] = { let __args: [G; IN_280] = [__v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_0, __v_1, __v_47, __v_48, __v_95, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[280].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[280].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[280].bump_multiplicity(__i); } let __ret: [G; OUT_280] = unsafe { *(record.function_queries[280].output_at(__i).as_ptr() as *const [G; OUT_280]) }; __ret }, _ => aiur_fn_280(__args, record, io_buffer, __cu)? } }; let __v_96: G = __r_arr[0]; let __v_97: G = __r_arr[1]; let __v_98: G = __r_arr[2]; @@ -27855,8 +27809,8 @@ fn aiur_fn_291( let __v_106: G = __r_arr[10]; let __v_107: G = __r_arr[11]; let __v_108: G = { let __values: [G; 12] = [__v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_291] = [__v_108]; - record.function_queries[291].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_290] = [__v_108]; + record.function_queries[290].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -27873,15 +27827,15 @@ fn aiur_fn_291( }) } -const INPUT_SIZE_292: usize = 2; -const IN_292: usize = 2; -const OUT_292: usize = 45; -fn aiur_fn_292( - inp: [G; IN_292], +const INPUT_SIZE_291: usize = 2; +const IN_291: usize = 2; +const OUT_291: usize = 45; +fn aiur_fn_291( + inp: [G; IN_291], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_292], ExecError> { +) -> Result<[G; OUT_291], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -27937,14 +27891,14 @@ fn aiur_fn_292( 0u64 => { match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_292] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47]; - record.function_queries[292].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_291] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47]; + record.function_queries[291].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_49: G = G::from_u64(1); let __v_50: G = (__v_1 - __v_49); - let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_48, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_291] = { let __args: [G; IN_291] = [__v_48, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[291].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[291].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[291].bump_multiplicity(__i); } let __ret: [G; OUT_291] = unsafe { *(record.function_queries[291].output_at(__i).as_ptr() as *const [G; OUT_291]) }; __ret }, _ => aiur_fn_291(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; let __v_52: G = __r_arr[1]; let __v_53: G = __r_arr[2]; @@ -27990,8 +27944,8 @@ fn aiur_fn_292( let __v_93: G = __r_arr[42]; let __v_94: G = __r_arr[43]; let __v_95: G = __r_arr[44]; - let __ret: [G; OUT_292] = [__v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_95]; - record.function_queries[292].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_291] = [__v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_95]; + record.function_queries[291].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -28003,15 +27957,15 @@ fn aiur_fn_292( }) } -const INPUT_SIZE_293: usize = 1; -const IN_293: usize = 1; -const OUT_293: usize = 8; -fn aiur_fn_293( - inp: [G; IN_293], +const INPUT_SIZE_292: usize = 1; +const IN_292: usize = 1; +const OUT_292: usize = 8; +fn aiur_fn_292( + inp: [G; IN_292], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_293], ExecError> { +) -> Result<[G; OUT_292], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __gb: [u8; 8] = __v_0.as_canonical_u64().to_le_bytes(); @@ -28032,26 +27986,26 @@ fn aiur_fn_293( if (__v_9 != __v_0) { return Err(ExecError::AssertEqMismatch { lhs: __v_9.as_canonical_u64(), rhs: __v_0.as_canonical_u64(), msg: Some("projection index bytes do not recompose to the index".to_string()) }); } - let __ret: [G; OUT_293] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; - record.function_queries[293].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_292] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; + record.function_queries[292].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_294: usize = 3; -const IN_294: usize = 3; -const OUT_294: usize = 1; -fn aiur_fn_294( - inp: [G; IN_294], +const INPUT_SIZE_293: usize = 3; +const IN_293: usize = 3; +const OUT_293: usize = 1; +fn aiur_fn_293( + inp: [G; IN_293], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_294], ExecError> { +) -> Result<[G; OUT_293], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_291] = { let __args: [G; IN_291] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[291].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[291].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[291].bump_multiplicity(__i); } let __ret: [G; OUT_291] = unsafe { *(record.function_queries[291].output_at(__i).as_ptr() as *const [G; OUT_291]) }; __ret }, _ => aiur_fn_291(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = __r_arr[2]; @@ -28097,7 +28051,7 @@ fn aiur_fn_294( let __v_45: G = __r_arr[42]; let __v_46: G = __r_arr[43]; let __v_47: G = __r_arr[44]; - let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; let __v_49: G = __r_arr[1]; let __v_50: G = __r_arr[2]; @@ -28188,42 +28142,42 @@ fn aiur_fn_294( let __v_113: G = __r_arr[0]; let __r_arr: [G; OUT_22] = { let __args: [G; IN_22] = [__v_113]; let __cu = unconstrained; let __hit = record.function_queries[22].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[22].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[22].bump_multiplicity(__i); } let __ret: [G; OUT_22] = unsafe { *(record.function_queries[22].output_at(__i).as_ptr() as *const [G; OUT_22]) }; __ret }, _ => aiur_fn_22(__args, record, io_buffer, __cu)? } }; let __v_114: G = __r_arr[0]; - let __ret: [G; OUT_294] = [__v_114]; - record.function_queries[294].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_293] = [__v_114]; + record.function_queries[293].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_295: usize = 2; -const IN_295: usize = 2; -const OUT_295: usize = 1; -fn aiur_fn_295( - inp: [G; IN_295], +const INPUT_SIZE_294: usize = 2; +const IN_294: usize = 2; +const OUT_294: usize = 1; +fn aiur_fn_294( + inp: [G; IN_294], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_295], ExecError> { +) -> Result<[G; OUT_294], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = G::from_u64(0); - let __r_arr: [G; OUT_296] = { let __args: [G; IN_296] = [__v_0, __v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[296].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[296].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[296].bump_multiplicity(__i); } let __ret: [G; OUT_296] = unsafe { *(record.function_queries[296].output_at(__i).as_ptr() as *const [G; OUT_296]) }; __ret }, _ => aiur_fn_296(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_0, __v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __ret: [G; OUT_295] = [__v_3]; - record.function_queries[295].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_294] = [__v_3]; + record.function_queries[294].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_296: usize = 4; -const IN_296: usize = 4; -const OUT_296: usize = 1; -fn aiur_fn_296( - inp: [G; IN_296], +const INPUT_SIZE_295: usize = 4; +const IN_295: usize = 4; +const OUT_295: usize = 1; +fn aiur_fn_295( + inp: [G; IN_295], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_296], ExecError> { +) -> Result<[G; OUT_295], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28282,21 +28236,21 @@ fn aiur_fn_296( let __v_51: G = G::from_u64(1); let __v_52: G = G::from_u64(1); let __v_53: G = { let __values: [G; 3] = [__v_51, __v_52, __v_52]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_296] = [__v_53]; - record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_295] = [__v_53]; + record.function_queries[295].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_51: G = G::from_u64(0); - let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = G::from_u64(1); let __v_54: G = (__v_3 + __v_53); - let __r_arr: [G; OUT_296] = { let __args: [G; IN_296] = [__v_0, __v_1, __v_50, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[296].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[296].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[296].bump_multiplicity(__i); } let __ret: [G; OUT_296] = unsafe { *(record.function_queries[296].output_at(__i).as_ptr() as *const [G; OUT_296]) }; __ret }, _ => aiur_fn_296(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_0, __v_1, __v_50, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __v_56: G = { let __values: [G; 3] = [__v_51, __v_52, __v_55]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_296] = [__v_56]; - record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_295] = [__v_56]; + record.function_queries[295].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28306,15 +28260,15 @@ fn aiur_fn_296( }) } -const INPUT_SIZE_297: usize = 1; -const IN_297: usize = 1; -const OUT_297: usize = 1; -fn aiur_fn_297( - inp: [G; IN_297], +const INPUT_SIZE_296: usize = 1; +const IN_296: usize = 1; +const OUT_296: usize = 1; +fn aiur_fn_296( + inp: [G; IN_296], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_297], ExecError> { +) -> Result<[G; OUT_296], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -28324,57 +28278,57 @@ fn aiur_fn_297( match __v_1.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_297] = [__v_4]; - record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_296] = [__v_4]; + record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_297] = [__v_4]; - record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_296] = [__v_4]; + record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_297] = [__v_4]; - record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_296] = [__v_4]; + record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_296] = { let __args: [G; IN_296] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[296].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[296].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[296].bump_multiplicity(__i); } let __ret: [G; OUT_296] = unsafe { *(record.function_queries[296].output_at(__i).as_ptr() as *const [G; OUT_296]) }; __ret }, _ => aiur_fn_296(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_296] = { let __args: [G; IN_296] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[296].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[296].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[296].bump_multiplicity(__i); } let __ret: [G; OUT_296] = unsafe { *(record.function_queries[296].output_at(__i).as_ptr() as *const [G; OUT_296]) }; __ret }, _ => aiur_fn_296(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { match __v_5.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_297] = [__v_6]; - record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_296] = [__v_6]; + record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_297] = [__v_6]; - record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_296] = [__v_6]; + record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_297] = [__v_6]; - record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_296] = [__v_6]; + record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 3u64 => { - let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_296] = { let __args: [G; IN_296] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[296].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[296].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[296].bump_multiplicity(__i); } let __ret: [G; OUT_296] = unsafe { *(record.function_queries[296].output_at(__i).as_ptr() as *const [G; OUT_296]) }; __ret }, _ => aiur_fn_296(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_297] = [__v_4]; - record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_296] = [__v_4]; + record.function_queries[296].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28384,15 +28338,15 @@ fn aiur_fn_297( }) } -const INPUT_SIZE_298: usize = 2; -const IN_298: usize = 2; -const OUT_298: usize = 1; -fn aiur_fn_298( - inp: [G; IN_298], +const INPUT_SIZE_297: usize = 2; +const IN_297: usize = 2; +const OUT_297: usize = 1; +fn aiur_fn_297( + inp: [G; IN_297], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_298], ExecError> { +) -> Result<[G; OUT_297], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28409,14 +28363,14 @@ fn aiur_fn_298( match __v_5.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_298] = [__v_8]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_8]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_298] = [__v_8]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_8]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -28428,16 +28382,16 @@ fn aiur_fn_298( let __v_7: G = __loaded[2]; match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_298] = [__v_8]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_8]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_298] = [__v_8]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_8]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -28449,19 +28403,19 @@ fn aiur_fn_298( let __v_7: G = __loaded[2]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = (__v_8 * __v_9); - let __ret: [G; OUT_298] = [__v_10]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_10]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_298] = [__v_8]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_8]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -28473,19 +28427,19 @@ fn aiur_fn_298( let __v_7: G = __loaded[2]; match __v_5.as_canonical_u64() { 3u64 => { - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = (__v_8 * __v_9); - let __ret: [G; OUT_298] = [__v_10]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_10]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_298] = [__v_8]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_8]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -28499,14 +28453,14 @@ fn aiur_fn_298( 4u64 => { let __v_8: G = (__v_3 - __v_6); let __v_9: G = G::from_bool((__v_8 == G::ZERO)); - let __ret: [G; OUT_298] = [__v_9]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_9]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_298] = [__v_8]; - record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_297] = [__v_8]; + record.function_queries[297].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -28518,15 +28472,15 @@ fn aiur_fn_298( }) } -const INPUT_SIZE_299: usize = 2; -const IN_299: usize = 2; -const OUT_299: usize = 1; -fn aiur_fn_299( - inp: [G; IN_299], +const INPUT_SIZE_298: usize = 2; +const IN_298: usize = 2; +const OUT_298: usize = 1; +fn aiur_fn_298( + inp: [G; IN_298], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_299], ExecError> { +) -> Result<[G; OUT_298], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28543,14 +28497,14 @@ fn aiur_fn_299( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_299] = [__v_8]; - record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_298] = [__v_8]; + record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_299] = [__v_8]; - record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_298] = [__v_8]; + record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28566,8 +28520,8 @@ fn aiur_fn_299( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_299] = [__v_8]; - record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_298] = [__v_8]; + record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28575,8 +28529,8 @@ fn aiur_fn_299( match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_299] = [__v_9]; - record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_298] = [__v_9]; + record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28584,15 +28538,15 @@ fn aiur_fn_299( match __v_9.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(2); - let __ret: [G; OUT_299] = [__v_10]; - record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_298] = [__v_10]; + record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_299] = [__v_10]; - record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_298] = [__v_10]; + record.function_queries[298].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28617,15 +28571,15 @@ fn aiur_fn_299( }) } -const INPUT_SIZE_300: usize = 2; -const IN_300: usize = 2; -const OUT_300: usize = 1; -fn aiur_fn_300( - inp: [G; IN_300], +const INPUT_SIZE_299: usize = 2; +const IN_299: usize = 2; +const OUT_299: usize = 1; +fn aiur_fn_299( + inp: [G; IN_299], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_300], ExecError> { +) -> Result<[G; OUT_299], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28636,8 +28590,8 @@ fn aiur_fn_300( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_300] = [__v_5]; - record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_299] = [__v_5]; + record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28648,8 +28602,8 @@ fn aiur_fn_300( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_300] = [__v_8]; - record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_299] = [__v_8]; + record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28657,25 +28611,25 @@ fn aiur_fn_300( match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_300] = [__v_9]; - record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_299] = [__v_9]; + record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_9: G = { let __a_val = __v_6.as_canonical_u64(); let __b_val = __v_3.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_300] = { let __args: [G; IN_300] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[300].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[300].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[300].bump_multiplicity(__i); } let __ret: [G; OUT_300] = unsafe { *(record.function_queries[300].output_at(__i).as_ptr() as *const [G; OUT_300]) }; __ret }, _ => aiur_fn_300(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_300] = [__v_10]; - record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_299] = [__v_10]; + record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_300] = { let __args: [G; IN_300] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[300].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[300].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[300].bump_multiplicity(__i); } let __ret: [G; OUT_300] = unsafe { *(record.function_queries[300].output_at(__i).as_ptr() as *const [G; OUT_300]) }; __ret }, _ => aiur_fn_300(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_300] = [__v_10]; - record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_299] = [__v_10]; + record.function_queries[299].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28700,15 +28654,15 @@ fn aiur_fn_300( }) } -const INPUT_SIZE_301: usize = 2; -const IN_301: usize = 2; -const OUT_301: usize = 1; -fn aiur_fn_301( - inp: [G; IN_301], +const INPUT_SIZE_300: usize = 2; +const IN_300: usize = 2; +const OUT_300: usize = 1; +fn aiur_fn_300( + inp: [G; IN_300], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_301], ExecError> { +) -> Result<[G; OUT_300], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28725,14 +28679,14 @@ fn aiur_fn_301( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_301] = [__v_8]; - record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_300] = [__v_8]; + record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_301] = [__v_8]; - record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_300] = [__v_8]; + record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28748,15 +28702,15 @@ fn aiur_fn_301( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_301] = [__v_8]; - record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_300] = [__v_8]; + record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_301] = { let __args: [G; IN_301] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[301].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[301].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[301].bump_multiplicity(__i); } let __ret: [G; OUT_301] = unsafe { *(record.function_queries[301].output_at(__i).as_ptr() as *const [G; OUT_301]) }; __ret }, _ => aiur_fn_301(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_300] = { let __args: [G; IN_300] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[300].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[300].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[300].bump_multiplicity(__i); } let __ret: [G; OUT_300] = unsafe { *(record.function_queries[300].output_at(__i).as_ptr() as *const [G; OUT_300]) }; __ret }, _ => aiur_fn_300(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_301] = [__v_8]; - record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_300] = [__v_8]; + record.function_queries[300].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28771,15 +28725,15 @@ fn aiur_fn_301( }) } -const INPUT_SIZE_302: usize = 2; -const IN_302: usize = 2; -const OUT_302: usize = 2; -fn aiur_fn_302( - inp: [G; IN_302], +const INPUT_SIZE_301: usize = 2; +const IN_301: usize = 2; +const OUT_301: usize = 2; +fn aiur_fn_301( + inp: [G; IN_301], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_302], ExecError> { +) -> Result<[G; OUT_301], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28795,8 +28749,8 @@ fn aiur_fn_302( let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_10: G = { let __values: [G; 3] = [__v_6, __v_0, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_302] = [__v_5, __v_10]; - record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_301] = [__v_5, __v_10]; + record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28806,8 +28760,8 @@ fn aiur_fn_302( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 3] = [__v_7, __v_0, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_302] = [__v_6, __v_8]; - record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_301] = [__v_6, __v_8]; + record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28815,18 +28769,18 @@ fn aiur_fn_302( match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_302] = [__v_7, __v_1]; - record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_301] = [__v_7, __v_1]; + record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_302] = { let __args: [G; IN_302] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[302].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[302].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[302].bump_multiplicity(__i); } let __ret: [G; OUT_302] = unsafe { *(record.function_queries[302].output_at(__i).as_ptr() as *const [G; OUT_302]) }; __ret }, _ => aiur_fn_302(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_301] = { let __args: [G; IN_301] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[301].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[301].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[301].bump_multiplicity(__i); } let __ret: [G; OUT_301] = unsafe { *(record.function_queries[301].output_at(__i).as_ptr() as *const [G; OUT_301]) }; __ret }, _ => aiur_fn_301(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 3] = [__v_9, __v_3, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_302] = [__v_7, __v_10]; - record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_301] = [__v_7, __v_10]; + record.function_queries[301].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28846,15 +28800,15 @@ fn aiur_fn_302( }) } -const INPUT_SIZE_303: usize = 3; -const IN_303: usize = 3; -const OUT_303: usize = 1; -fn aiur_fn_303( - inp: [G; IN_303], +const INPUT_SIZE_302: usize = 3; +const IN_302: usize = 3; +const OUT_302: usize = 1; +fn aiur_fn_302( + inp: [G; IN_302], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_303], ExecError> { +) -> Result<[G; OUT_302], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28871,8 +28825,8 @@ fn aiur_fn_303( let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = { let __values: [G; 3] = [__v_6, __v_7, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_303] = [__v_11]; - record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_302] = [__v_11]; + record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28887,8 +28841,8 @@ fn aiur_fn_303( let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 2] = [__v_1, __v_2]; let __mq = record.memory_queries.get_mut(&2).ok_or(ExecError::InvalidMemorySize(2))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = { let __values: [G; 3] = [__v_9, __v_10, __v_0]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_303] = [__v_11]; - record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_302] = [__v_11]; + record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28896,11 +28850,11 @@ fn aiur_fn_303( match __v_9.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_303] = { let __args: [G; IN_303] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[303].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[303].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[303].bump_multiplicity(__i); } let __ret: [G; OUT_303] = unsafe { *(record.function_queries[303].output_at(__i).as_ptr() as *const [G; OUT_303]) }; __ret }, _ => aiur_fn_303(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_302] = { let __args: [G; IN_302] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[302].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[302].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[302].bump_multiplicity(__i); } let __ret: [G; OUT_302] = unsafe { *(record.function_queries[302].output_at(__i).as_ptr() as *const [G; OUT_302]) }; __ret }, _ => aiur_fn_302(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = { let __values: [G; 3] = [__v_10, __v_4, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_303] = [__v_12]; - record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_302] = [__v_12]; + record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -28910,13 +28864,13 @@ fn aiur_fn_303( let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 2] = [__v_6, __v_2]; let __mq = record.memory_queries.get_mut(&2).ok_or(ExecError::InvalidMemorySize(2))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_303] = [__v_13]; - record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_302] = [__v_13]; + record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_303] = [__v_0]; - record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_302] = [__v_0]; + record.function_queries[302].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28943,15 +28897,15 @@ fn aiur_fn_303( }) } -const INPUT_SIZE_304: usize = 2; -const IN_304: usize = 2; -const OUT_304: usize = 1; -fn aiur_fn_304( - inp: [G; IN_304], +const INPUT_SIZE_303: usize = 2; +const IN_303: usize = 2; +const OUT_303: usize = 1; +fn aiur_fn_303( + inp: [G; IN_303], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_304], ExecError> { +) -> Result<[G; OUT_303], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -28968,14 +28922,14 @@ fn aiur_fn_304( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_304] = [__v_8]; - record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_303] = [__v_8]; + record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_304] = [__v_8]; - record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_303] = [__v_8]; + record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -28991,8 +28945,8 @@ fn aiur_fn_304( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_304] = [__v_8]; - record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_303] = [__v_8]; + record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29012,24 +28966,24 @@ fn aiur_fn_304( let __v_13: G = (__v_9 - __v_11); match __v_13.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_304] = { let __args: [G; IN_304] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[304].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[304].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[304].bump_multiplicity(__i); } let __ret: [G; OUT_304] = unsafe { *(record.function_queries[304].output_at(__i).as_ptr() as *const [G; OUT_304]) }; __ret }, _ => aiur_fn_304(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_303] = { let __args: [G; IN_303] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[303].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[303].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[303].bump_multiplicity(__i); } let __ret: [G; OUT_303] = unsafe { *(record.function_queries[303].output_at(__i).as_ptr() as *const [G; OUT_303]) }; __ret }, _ => aiur_fn_303(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_304] = [__v_14]; - record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_303] = [__v_14]; + record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(0); - let __ret: [G; OUT_304] = [__v_14]; - record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_303] = [__v_14]; + record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_304] = [__v_13]; - record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_303] = [__v_13]; + record.function_queries[303].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -29050,15 +29004,15 @@ fn aiur_fn_304( }) } -const INPUT_SIZE_305: usize = 1; -const IN_305: usize = 1; -const OUT_305: usize = 1; -fn aiur_fn_305( - inp: [G; IN_305], +const INPUT_SIZE_304: usize = 1; +const IN_304: usize = 1; +const OUT_304: usize = 1; +fn aiur_fn_304( + inp: [G; IN_304], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_305], ExecError> { +) -> Result<[G; OUT_304], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -29068,8 +29022,8 @@ fn aiur_fn_305( match __v_1.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_305] = [__v_4]; - record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_304] = [__v_4]; + record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29078,18 +29032,18 @@ fn aiur_fn_305( let __v_5: G = __loaded[1]; match __v_4.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_305] = { let __args: [G; IN_305] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[305].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[305].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[305].bump_multiplicity(__i); } let __ret: [G; OUT_305] = unsafe { *(record.function_queries[305].output_at(__i).as_ptr() as *const [G; OUT_305]) }; __ret }, _ => aiur_fn_305(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_304] = { let __args: [G; IN_304] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[304].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[304].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[304].bump_multiplicity(__i); } let __ret: [G; OUT_304] = unsafe { *(record.function_queries[304].output_at(__i).as_ptr() as *const [G; OUT_304]) }; __ret }, _ => aiur_fn_304(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = { let __a_val = __v_6.as_canonical_u64(); let __b_val = __v_5.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_7.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_305] = [__v_5]; - record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_304] = [__v_5]; + record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_305] = [__v_6]; - record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_304] = [__v_6]; + record.function_queries[304].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29106,15 +29060,15 @@ fn aiur_fn_305( }) } -const INPUT_SIZE_306: usize = 2; -const IN_306: usize = 2; -const OUT_306: usize = 1; -fn aiur_fn_306( - inp: [G; IN_306], +const INPUT_SIZE_305: usize = 2; +const IN_305: usize = 2; +const OUT_305: usize = 1; +fn aiur_fn_305( + inp: [G; IN_305], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_306], ExecError> { +) -> Result<[G; OUT_305], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -29124,8 +29078,8 @@ fn aiur_fn_306( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_306] = [__v_0]; - record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_305] = [__v_0]; + record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29135,8 +29089,8 @@ fn aiur_fn_306( let __v_7: G = __loaded[2]; match __v_5.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_306] = [__v_0]; - record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_305] = [__v_0]; + record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29154,21 +29108,21 @@ fn aiur_fn_306( match __v_12.as_canonical_u64() { 1u64 => { let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_305] = { let __args: [G; IN_305] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[305].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[305].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[305].bump_multiplicity(__i); } let __ret: [G; OUT_305] = unsafe { *(record.function_queries[305].output_at(__i).as_ptr() as *const [G; OUT_305]) }; __ret }, _ => aiur_fn_305(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = { let __values: [G; 3] = [__v_13, __v_3, __v_14]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_306] = [__v_15]; - record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_305] = [__v_15]; + record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_13: G = { let __a_val = __v_10.as_canonical_u64(); let __b_val = __v_8.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_13.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_305] = { let __args: [G; IN_305] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[305].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[305].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[305].bump_multiplicity(__i); } let __ret: [G; OUT_305] = unsafe { *(record.function_queries[305].output_at(__i).as_ptr() as *const [G; OUT_305]) }; __ret }, _ => aiur_fn_305(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_306] = [__v_14]; - record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_305] = [__v_14]; + record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29176,18 +29130,18 @@ fn aiur_fn_306( match __v_14.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_305] = { let __args: [G; IN_305] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[305].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[305].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[305].bump_multiplicity(__i); } let __ret: [G; OUT_305] = unsafe { *(record.function_queries[305].output_at(__i).as_ptr() as *const [G; OUT_305]) }; __ret }, _ => aiur_fn_305(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = { let __values: [G; 3] = [__v_15, __v_3, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_306] = [__v_17]; - record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_305] = [__v_17]; + record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_305] = { let __args: [G; IN_305] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[305].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[305].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[305].bump_multiplicity(__i); } let __ret: [G; OUT_305] = unsafe { *(record.function_queries[305].output_at(__i).as_ptr() as *const [G; OUT_305]) }; __ret }, _ => aiur_fn_305(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_306] = [__v_15]; - record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_305] = [__v_15]; + record.function_queries[305].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29221,23 +29175,23 @@ fn aiur_fn_306( }) } -const INPUT_SIZE_307: usize = 3; -const IN_307: usize = 3; -const OUT_307: usize = 1; -fn aiur_fn_307( - inp: [G; IN_307], +const INPUT_SIZE_306: usize = 3; +const IN_306: usize = 3; +const OUT_306: usize = 1; +fn aiur_fn_306( + inp: [G; IN_306], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_307], ExecError> { +) -> Result<[G; OUT_306], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_2.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_307] = [__v_0]; - record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_306] = [__v_0]; + record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -29247,15 +29201,15 @@ fn aiur_fn_307( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_307] = { let __args: [G; IN_307] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[307].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[307].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[307].bump_multiplicity(__i); } let __ret: [G; OUT_307] = unsafe { *(record.function_queries[307].output_at(__i).as_ptr() as *const [G; OUT_307]) }; __ret }, _ => aiur_fn_307(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_307] = [__v_6]; - record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_306] = [__v_6]; + record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_307] = [__v_0]; - record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_306] = [__v_0]; + record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29264,25 +29218,25 @@ fn aiur_fn_307( } }, _ => { - let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_307] = { let __args: [G; IN_307] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[307].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[307].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[307].bump_multiplicity(__i); } let __ret: [G; OUT_307] = unsafe { *(record.function_queries[307].output_at(__i).as_ptr() as *const [G; OUT_307]) }; __ret }, _ => aiur_fn_307(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __ret: [G; OUT_307] = [__v_3]; - record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_306] = [__v_3]; + record.function_queries[306].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_308: usize = 3; -const IN_308: usize = 3; -const OUT_308: usize = 1; -fn aiur_fn_308( - inp: [G; IN_308], +const INPUT_SIZE_307: usize = 3; +const IN_307: usize = 3; +const OUT_307: usize = 1; +fn aiur_fn_307( + inp: [G; IN_307], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_308], ExecError> { +) -> Result<[G; OUT_307], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -29302,8 +29256,8 @@ fn aiur_fn_308( let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = { let __values: [G; 3] = [__v_6, __v_10, __v_13]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_308] = [__v_14]; - record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_307] = [__v_14]; + record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29313,7 +29267,7 @@ fn aiur_fn_308( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 0u64 => { @@ -29323,13 +29277,13 @@ fn aiur_fn_308( let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 3] = [__v_6, __v_2, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_308] = [__v_13]; - record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_307] = [__v_13]; + record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_308] = [__v_0]; - record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_307] = [__v_0]; + record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29344,17 +29298,17 @@ fn aiur_fn_308( let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = { let __values: [G; 3] = [__v_1, __v_2, __v_13]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_15: G = { let __values: [G; 3] = [__v_10, __v_14, __v_0]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_308] = [__v_15]; - record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_307] = [__v_15]; + record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_307] = { let __args: [G; IN_307] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[307].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[307].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[307].bump_multiplicity(__i); } let __ret: [G; OUT_307] = unsafe { *(record.function_queries[307].output_at(__i).as_ptr() as *const [G; OUT_307]) }; __ret }, _ => aiur_fn_307(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = { let __values: [G; 3] = [__v_10, __v_4, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_308] = [__v_12]; - record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_307] = [__v_12]; + record.function_queries[307].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -29368,15 +29322,15 @@ fn aiur_fn_308( }) } -const INPUT_SIZE_309: usize = 4; -const IN_309: usize = 4; -const OUT_309: usize = 1; -fn aiur_fn_309( - inp: [G; IN_309], +const INPUT_SIZE_308: usize = 4; +const IN_308: usize = 4; +const OUT_308: usize = 1; +fn aiur_fn_308( + inp: [G; IN_308], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_309], ExecError> { +) -> Result<[G; OUT_308], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -29401,8 +29355,8 @@ fn aiur_fn_309( let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 3] = [__v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_19: G = { let __values: [G; 3] = [__v_7, __v_15, __v_18]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_309] = [__v_19]; - record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_308] = [__v_19]; + record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29412,17 +29366,17 @@ fn aiur_fn_309( let __v_9: G = __loaded[2]; match __v_7.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_1, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_1, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 0u64 => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_303] = { let __args: [G; IN_303] = [__v_9, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[303].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[303].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[303].bump_multiplicity(__i); } let __ret: [G; OUT_303] = unsafe { *(record.function_queries[303].output_at(__i).as_ptr() as *const [G; OUT_303]) }; __ret }, _ => aiur_fn_303(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_302] = { let __args: [G; IN_302] = [__v_9, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[302].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[302].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[302].bump_multiplicity(__i); } let __ret: [G; OUT_302] = unsafe { *(record.function_queries[302].output_at(__i).as_ptr() as *const [G; OUT_302]) }; __ret }, _ => aiur_fn_302(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = { let __values: [G; 3] = [__v_7, __v_8, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = { let __values: [G; 3] = [__v_11, __v_13, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_309] = [__v_14]; - record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_308] = [__v_14]; + record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -29436,17 +29390,17 @@ fn aiur_fn_309( let __v_18: G = { let __values: [G; 3] = [__v_13, __v_14, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_19: G = { let __values: [G; 3] = [__v_1, __v_12, __v_18]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_20: G = { let __values: [G; 3] = [__v_11, __v_19, __v_0]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_309] = [__v_20]; - record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_308] = [__v_20]; + record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = { let __values: [G; 3] = [__v_11, __v_5, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_309] = [__v_13]; - record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_308] = [__v_13]; + record.function_queries[308].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -29460,15 +29414,15 @@ fn aiur_fn_309( }) } -const INPUT_SIZE_310: usize = 4; -const IN_310: usize = 4; -const OUT_310: usize = 1; -fn aiur_fn_310( - inp: [G; IN_310], +const INPUT_SIZE_309: usize = 4; +const IN_309: usize = 4; +const OUT_309: usize = 1; +fn aiur_fn_309( + inp: [G; IN_309], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_310], ExecError> { +) -> Result<[G; OUT_309], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -29480,63 +29434,63 @@ fn aiur_fn_310( let __v_6: G = __loaded[2]; match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_307] = { let __args: [G; IN_307] = [__v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[307].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[307].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[307].bump_multiplicity(__i); } let __ret: [G; OUT_307] = unsafe { *(record.function_queries[307].output_at(__i).as_ptr() as *const [G; OUT_307]) }; __ret }, _ => aiur_fn_307(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_310] = [__v_7]; - record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_309] = [__v_7]; + record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_2 + __v_7); - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_5, __v_1, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_5, __v_1, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_310] = [__v_9]; - record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_309] = [__v_9]; + record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_5, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_5, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_6, __v_1, __v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_6, __v_1, __v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_310] = [__v_8]; - record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_309] = [__v_8]; + record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_311] = { let __args: [G; IN_311] = [__v_5, __v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[311].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[311].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[311].bump_multiplicity(__i); } let __ret: [G; OUT_311] = unsafe { *(record.function_queries[311].output_at(__i).as_ptr() as *const [G; OUT_311]) }; __ret }, _ => aiur_fn_311(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_5, __v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_310] = [__v_7]; - record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_309] = [__v_7]; + record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_302] = { let __args: [G; IN_302] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[302].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[302].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[302].bump_multiplicity(__i); } let __ret: [G; OUT_302] = unsafe { *(record.function_queries[302].output_at(__i).as_ptr() as *const [G; OUT_302]) }; __ret }, _ => aiur_fn_302(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_301] = { let __args: [G; IN_301] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[301].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[301].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[301].bump_multiplicity(__i); } let __ret: [G; OUT_301] = unsafe { *(record.function_queries[301].output_at(__i).as_ptr() as *const [G; OUT_301]) }; __ret }, _ => aiur_fn_301(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_307] = { let __args: [G; IN_307] = [__v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[307].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[307].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[307].bump_multiplicity(__i); } let __ret: [G; OUT_307] = unsafe { *(record.function_queries[307].output_at(__i).as_ptr() as *const [G; OUT_307]) }; __ret }, _ => aiur_fn_307(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_9, __v_8, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_9, __v_8, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_310] = [__v_10]; - record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_309] = [__v_10]; + record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_2.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_310] = [__v_3]; - record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_309] = [__v_3]; + record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_3, __v_1, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_3, __v_1, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_310] = [__v_9]; - record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_309] = [__v_9]; + record.function_queries[309].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -29553,15 +29507,15 @@ fn aiur_fn_310( }) } -const INPUT_SIZE_311: usize = 5; -const IN_311: usize = 5; -const OUT_311: usize = 1; -fn aiur_fn_311( - inp: [G; IN_311], +const INPUT_SIZE_310: usize = 5; +const IN_310: usize = 5; +const OUT_310: usize = 1; +fn aiur_fn_310( + inp: [G; IN_310], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_311], ExecError> { +) -> Result<[G; OUT_310], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -29574,55 +29528,55 @@ fn aiur_fn_311( let __v_7: G = __loaded[2]; match __v_5.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_307] = { let __args: [G; IN_307] = [__v_4, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[307].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[307].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[307].bump_multiplicity(__i); } let __ret: [G; OUT_307] = unsafe { *(record.function_queries[307].output_at(__i).as_ptr() as *const [G; OUT_307]) }; __ret }, _ => aiur_fn_307(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_4, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_311] = [__v_8]; - record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_310] = [__v_8]; + record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_8: G = G::from_u64(1); let __v_9: G = (__v_3 + __v_8); - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_0, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_0, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_6, __v_2, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_6, __v_2, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_311] = [__v_11]; - record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_310] = [__v_11]; + record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_311] = { let __args: [G; IN_311] = [__v_0, __v_6, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[311].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[311].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[311].bump_multiplicity(__i); } let __ret: [G; OUT_311] = unsafe { *(record.function_queries[311].output_at(__i).as_ptr() as *const [G; OUT_311]) }; __ret }, _ => aiur_fn_311(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_0, __v_6, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_311] = { let __args: [G; IN_311] = [__v_0, __v_7, __v_2, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[311].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[311].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[311].bump_multiplicity(__i); } let __ret: [G; OUT_311] = unsafe { *(record.function_queries[311].output_at(__i).as_ptr() as *const [G; OUT_311]) }; __ret }, _ => aiur_fn_311(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_0, __v_7, __v_2, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_311] = [__v_9]; - record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_310] = [__v_9]; + record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_311] = { let __args: [G; IN_311] = [__v_0, __v_7, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[311].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[311].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[311].bump_multiplicity(__i); } let __ret: [G; OUT_311] = unsafe { *(record.function_queries[311].output_at(__i).as_ptr() as *const [G; OUT_311]) }; __ret }, _ => aiur_fn_311(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_0, __v_7, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_311] = { let __args: [G; IN_311] = [__v_6, __v_7, __v_2, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[311].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[311].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[311].bump_multiplicity(__i); } let __ret: [G; OUT_311] = unsafe { *(record.function_queries[311].output_at(__i).as_ptr() as *const [G; OUT_311]) }; __ret }, _ => aiur_fn_311(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_6, __v_7, __v_2, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_311] = [__v_9]; - record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_310] = [__v_9]; + record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_302] = { let __args: [G; IN_302] = [__v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[302].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[302].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[302].bump_multiplicity(__i); } let __ret: [G; OUT_302] = unsafe { *(record.function_queries[302].output_at(__i).as_ptr() as *const [G; OUT_302]) }; __ret }, _ => aiur_fn_302(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_301] = { let __args: [G; IN_301] = [__v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[301].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[301].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[301].bump_multiplicity(__i); } let __ret: [G; OUT_301] = unsafe { *(record.function_queries[301].output_at(__i).as_ptr() as *const [G; OUT_301]) }; __ret }, _ => aiur_fn_301(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_307] = { let __args: [G; IN_307] = [__v_4, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[307].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[307].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[307].bump_multiplicity(__i); } let __ret: [G; OUT_307] = unsafe { *(record.function_queries[307].output_at(__i).as_ptr() as *const [G; OUT_307]) }; __ret }, _ => aiur_fn_307(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_4, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_10, __v_9, __v_6, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_10, __v_9, __v_6, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_0, __v_9, __v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_0, __v_9, __v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_311] = [__v_12]; - record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_310] = [__v_12]; + record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29631,17 +29585,17 @@ fn aiur_fn_311( break '__mc_0 [__v_4]; }, _ => { - let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_4, __v_2, __v_6, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_308] = { let __args: [G; IN_308] = [__v_4, __v_2, __v_6, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[308].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[308].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[308].bump_multiplicity(__i); } let __ret: [G; OUT_308] = unsafe { *(record.function_queries[308].output_at(__i).as_ptr() as *const [G; OUT_308]) }; __ret }, _ => aiur_fn_308(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; break '__mc_0 [__v_10]; }, } }; let __v_10: G = __mc_out___mc_0[0]; - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_0, __v_2, __v_3, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_0, __v_2, __v_3, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_311] = [__v_11]; - record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_310] = [__v_11]; + record.function_queries[310].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29656,15 +29610,15 @@ fn aiur_fn_311( }) } -const INPUT_SIZE_312: usize = 2; -const IN_312: usize = 2; -const OUT_312: usize = 1; -fn aiur_fn_312( - inp: [G; IN_312], +const INPUT_SIZE_311: usize = 2; +const IN_311: usize = 2; +const OUT_311: usize = 1; +fn aiur_fn_311( + inp: [G; IN_311], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_312], ExecError> { +) -> Result<[G; OUT_311], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -29674,19 +29628,19 @@ fn aiur_fn_312( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_312] = [__v_0]; - record.function_queries[312].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_311] = [__v_0]; + record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_313] = { let __args: [G; IN_313] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[313].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[313].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[313].bump_multiplicity(__i); } let __ret: [G; OUT_313] = unsafe { *(record.function_queries[313].output_at(__i).as_ptr() as *const [G; OUT_313]) }; __ret }, _ => aiur_fn_313(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_312] = { let __args: [G; IN_312] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[312].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[312].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[312].bump_multiplicity(__i); } let __ret: [G; OUT_312] = unsafe { *(record.function_queries[312].output_at(__i).as_ptr() as *const [G; OUT_312]) }; __ret }, _ => aiur_fn_312(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_312] = { let __args: [G; IN_312] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[312].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[312].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[312].bump_multiplicity(__i); } let __ret: [G; OUT_312] = unsafe { *(record.function_queries[312].output_at(__i).as_ptr() as *const [G; OUT_312]) }; __ret }, _ => aiur_fn_312(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_311] = { let __args: [G; IN_311] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[311].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[311].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[311].bump_multiplicity(__i); } let __ret: [G; OUT_311] = unsafe { *(record.function_queries[311].output_at(__i).as_ptr() as *const [G; OUT_311]) }; __ret }, _ => aiur_fn_311(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = { let __values: [G; 3] = [__v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_312] = [__v_8]; - record.function_queries[312].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_311] = [__v_8]; + record.function_queries[311].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29696,15 +29650,15 @@ fn aiur_fn_312( }) } -const INPUT_SIZE_313: usize = 2; -const IN_313: usize = 2; -const OUT_313: usize = 1; -fn aiur_fn_313( - inp: [G; IN_313], +const INPUT_SIZE_312: usize = 2; +const IN_312: usize = 2; +const OUT_312: usize = 1; +fn aiur_fn_312( + inp: [G; IN_312], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_313], ExecError> { +) -> Result<[G; OUT_312], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -29714,8 +29668,8 @@ fn aiur_fn_313( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_313] = [__v_0]; - record.function_queries[313].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_312] = [__v_0]; + record.function_queries[312].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29731,18 +29685,18 @@ fn aiur_fn_313( let __v_10: G = __loaded[2]; match __v_8.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_300] = { let __args: [G; IN_300] = [__v_8, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[300].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[300].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[300].bump_multiplicity(__i); } let __ret: [G; OUT_300] = unsafe { *(record.function_queries[300].output_at(__i).as_ptr() as *const [G; OUT_300]) }; __ret }, _ => aiur_fn_300(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_8, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_313] = { let __args: [G; IN_313] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[313].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[313].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[313].bump_multiplicity(__i); } let __ret: [G; OUT_313] = unsafe { *(record.function_queries[313].output_at(__i).as_ptr() as *const [G; OUT_313]) }; __ret }, _ => aiur_fn_313(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_312] = { let __args: [G; IN_312] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[312].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[312].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[312].bump_multiplicity(__i); } let __ret: [G; OUT_312] = unsafe { *(record.function_queries[312].output_at(__i).as_ptr() as *const [G; OUT_312]) }; __ret }, _ => aiur_fn_312(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_313] = [__v_12]; - record.function_queries[313].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_312] = [__v_12]; + record.function_queries[312].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_301] = { let __args: [G; IN_301] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[301].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[301].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[301].bump_multiplicity(__i); } let __ret: [G; OUT_301] = unsafe { *(record.function_queries[301].output_at(__i).as_ptr() as *const [G; OUT_301]) }; __ret }, _ => aiur_fn_301(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_300] = { let __args: [G; IN_300] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[300].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[300].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[300].bump_multiplicity(__i); } let __ret: [G; OUT_300] = unsafe { *(record.function_queries[300].output_at(__i).as_ptr() as *const [G; OUT_300]) }; __ret }, _ => aiur_fn_300(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_6.as_canonical_u64() { 0u64 => { @@ -29775,7 +29729,7 @@ fn aiur_fn_313( break '__mc_2 [__v_17]; }, 0u64 => { - let __r_arr: [G; OUT_305] = { let __args: [G; IN_305] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[305].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[305].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[305].bump_multiplicity(__i); } let __ret: [G; OUT_305] = unsafe { *(record.function_queries[305].output_at(__i).as_ptr() as *const [G; OUT_305]) }; __ret }, _ => aiur_fn_305(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_304] = { let __args: [G; IN_304] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[304].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[304].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[304].bump_multiplicity(__i); } let __ret: [G; OUT_304] = unsafe { *(record.function_queries[304].output_at(__i).as_ptr() as *const [G; OUT_304]) }; __ret }, _ => aiur_fn_304(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = G::from_u64(1); let __v_19: G = (__v_17 + __v_18); @@ -29816,7 +29770,7 @@ fn aiur_fn_313( break '__mc_3 [__v_7]; }, 0u64 => { - let __r_arr: [G; OUT_306] = { let __args: [G; IN_306] = [__v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[306].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[306].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[306].bump_multiplicity(__i); } let __ret: [G; OUT_306] = unsafe { *(record.function_queries[306].output_at(__i).as_ptr() as *const [G; OUT_306]) }; __ret }, _ => aiur_fn_306(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_305] = { let __args: [G; IN_305] = [__v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[305].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[305].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[305].bump_multiplicity(__i); } let __ret: [G; OUT_305] = unsafe { *(record.function_queries[305].output_at(__i).as_ptr() as *const [G; OUT_305]) }; __ret }, _ => aiur_fn_305(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; break '__mc_3 [__v_17]; }, @@ -29832,10 +29786,10 @@ fn aiur_fn_313( }; let __v_14: G = __mc_out___mc_3[0]; let __v_15: G = { let __values: [G; 3] = [__v_5, __v_13, __v_14]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_313] = { let __args: [G; IN_313] = [__v_15, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[313].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[313].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[313].bump_multiplicity(__i); } let __ret: [G; OUT_313] = unsafe { *(record.function_queries[313].output_at(__i).as_ptr() as *const [G; OUT_313]) }; __ret }, _ => aiur_fn_313(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_312] = { let __args: [G; IN_312] = [__v_15, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[312].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[312].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[312].bump_multiplicity(__i); } let __ret: [G; OUT_312] = unsafe { *(record.function_queries[312].output_at(__i).as_ptr() as *const [G; OUT_312]) }; __ret }, _ => aiur_fn_312(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_313] = [__v_16]; - record.function_queries[313].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_312] = [__v_16]; + record.function_queries[312].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -29851,15 +29805,15 @@ fn aiur_fn_313( }) } -const INPUT_SIZE_314: usize = 1; -const IN_314: usize = 1; -const OUT_314: usize = 1; -fn aiur_fn_314( - inp: [G; IN_314], +const INPUT_SIZE_313: usize = 1; +const IN_313: usize = 1; +const OUT_313: usize = 1; +fn aiur_fn_313( + inp: [G; IN_313], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_314], ExecError> { +) -> Result<[G; OUT_313], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -29868,8 +29822,8 @@ fn aiur_fn_314( let __v_3: G = __loaded[2]; match __v_1.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_314] = [__v_0]; - record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_313] = [__v_0]; + record.function_queries[313].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29887,15 +29841,15 @@ fn aiur_fn_314( let __v_9: G = __loaded[2]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_314] = { let __args: [G; IN_314] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[314].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[314].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[314].bump_multiplicity(__i); } let __ret: [G; OUT_314] = unsafe { *(record.function_queries[314].output_at(__i).as_ptr() as *const [G; OUT_314]) }; __ret }, _ => aiur_fn_314(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_313] = { let __args: [G; IN_313] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[313].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[313].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[313].bump_multiplicity(__i); } let __ret: [G; OUT_313] = unsafe { *(record.function_queries[313].output_at(__i).as_ptr() as *const [G; OUT_313]) }; __ret }, _ => aiur_fn_313(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_314] = [__v_10]; - record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_313] = [__v_10]; + record.function_queries[313].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_314] = [__v_0]; - record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_313] = [__v_0]; + record.function_queries[313].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29904,8 +29858,8 @@ fn aiur_fn_314( } }, _ => { - let __ret: [G; OUT_314] = [__v_0]; - record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_313] = [__v_0]; + record.function_queries[313].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -29919,21 +29873,21 @@ fn aiur_fn_314( }) } -const INPUT_SIZE_315: usize = 2; -const IN_315: usize = 2; -const OUT_315: usize = 1; -fn aiur_fn_315( - inp: [G; IN_315], +const INPUT_SIZE_314: usize = 2; +const IN_314: usize = 2; +const OUT_314: usize = 1; +fn aiur_fn_314( + inp: [G; IN_314], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_315], ExecError> { +) -> Result<[G; OUT_314], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_314] = { let __args: [G; IN_314] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[314].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[314].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[314].bump_multiplicity(__i); } let __ret: [G; OUT_314] = unsafe { *(record.function_queries[314].output_at(__i).as_ptr() as *const [G; OUT_314]) }; __ret }, _ => aiur_fn_314(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_313] = { let __args: [G; IN_313] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[313].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[313].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[313].bump_multiplicity(__i); } let __ret: [G; OUT_313] = unsafe { *(record.function_queries[313].output_at(__i).as_ptr() as *const [G; OUT_313]) }; __ret }, _ => aiur_fn_313(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_314] = { let __args: [G; IN_314] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[314].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[314].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[314].bump_multiplicity(__i); } let __ret: [G; OUT_314] = unsafe { *(record.function_queries[314].output_at(__i).as_ptr() as *const [G; OUT_314]) }; __ret }, _ => aiur_fn_314(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_313] = { let __args: [G; IN_313] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[313].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[313].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[313].bump_multiplicity(__i); } let __ret: [G; OUT_313] = unsafe { *(record.function_queries[313].output_at(__i).as_ptr() as *const [G; OUT_313]) }; __ret }, _ => aiur_fn_313(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_2.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -29948,14 +29902,14 @@ fn aiur_fn_315( match __v_7.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_315] = [__v_10]; - record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_314] = [__v_10]; + record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_315] = [__v_10]; - record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_314] = [__v_10]; + record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -29971,8 +29925,8 @@ fn aiur_fn_315( match __v_7.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_315] = [__v_10]; - record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_314] = [__v_10]; + record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -29988,27 +29942,27 @@ fn aiur_fn_315( let __v_15: G = __loaded[2]; match __v_13.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_10, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_10, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; match __v_16.as_canonical_u64() { 0u64 => { let __v_17: G = (__v_11 - __v_14); match __v_17.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_304] = { let __args: [G; IN_304] = [__v_12, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[304].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[304].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[304].bump_multiplicity(__i); } let __ret: [G; OUT_304] = unsafe { *(record.function_queries[304].output_at(__i).as_ptr() as *const [G; OUT_304]) }; __ret }, _ => aiur_fn_304(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_303] = { let __args: [G; IN_303] = [__v_12, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[303].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[303].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[303].bump_multiplicity(__i); } let __ret: [G; OUT_303] = unsafe { *(record.function_queries[303].output_at(__i).as_ptr() as *const [G; OUT_303]) }; __ret }, _ => aiur_fn_303(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; match __v_18.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_315] = { let __args: [G; IN_315] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[315].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[315].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[315].bump_multiplicity(__i); } let __ret: [G; OUT_315] = unsafe { *(record.function_queries[315].output_at(__i).as_ptr() as *const [G; OUT_315]) }; __ret }, _ => aiur_fn_315(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_314] = { let __args: [G; IN_314] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[314].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[314].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[314].bump_multiplicity(__i); } let __ret: [G; OUT_314] = unsafe { *(record.function_queries[314].output_at(__i).as_ptr() as *const [G; OUT_314]) }; __ret }, _ => aiur_fn_314(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __ret: [G; OUT_315] = [__v_19]; - record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_314] = [__v_19]; + record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_19: G = G::from_u64(0); - let __ret: [G; OUT_315] = [__v_19]; - record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_314] = [__v_19]; + record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30018,16 +29972,16 @@ fn aiur_fn_315( }, _ => { let __v_18: G = G::from_u64(0); - let __ret: [G; OUT_315] = [__v_18]; - record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_314] = [__v_18]; + record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_315] = [__v_17]; - record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_314] = [__v_17]; + record.function_queries[314].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30048,15 +30002,15 @@ fn aiur_fn_315( }) } -const INPUT_SIZE_316: usize = 3; -const IN_316: usize = 3; -const OUT_316: usize = 1; -fn aiur_fn_316( - inp: [G; IN_316], +const INPUT_SIZE_315: usize = 3; +const IN_315: usize = 3; +const OUT_315: usize = 1; +fn aiur_fn_315( + inp: [G; IN_315], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_316], ExecError> { +) -> Result<[G; OUT_315], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30068,8 +30022,8 @@ fn aiur_fn_316( match __v_3.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_316] = [__v_6]; - record.function_queries[316].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_315] = [__v_6]; + record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30079,14 +30033,14 @@ fn aiur_fn_316( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_300] = { let __args: [G; IN_300] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[300].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[300].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[300].bump_multiplicity(__i); } let __ret: [G; OUT_300] = unsafe { *(record.function_queries[300].output_at(__i).as_ptr() as *const [G; OUT_300]) }; __ret }, _ => aiur_fn_300(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_316] = { let __args: [G; IN_316] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[316].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[316].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[316].bump_multiplicity(__i); } let __ret: [G; OUT_316] = unsafe { *(record.function_queries[316].output_at(__i).as_ptr() as *const [G; OUT_316]) }; __ret }, _ => aiur_fn_316(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_315] = { let __args: [G; IN_315] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[315].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[315].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[315].bump_multiplicity(__i); } let __ret: [G; OUT_315] = unsafe { *(record.function_queries[315].output_at(__i).as_ptr() as *const [G; OUT_315]) }; __ret }, _ => aiur_fn_315(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_316] = [__v_10]; - record.function_queries[316].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_315] = [__v_10]; + record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30097,7 +30051,7 @@ fn aiur_fn_316( break '__mc_0 [__v_11]; }, 1u64 => { - let __r_arr: [G; OUT_317] = { let __args: [G; IN_317] = [__v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[317].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[317].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[317].bump_multiplicity(__i); } let __ret: [G; OUT_317] = unsafe { *(record.function_queries[317].output_at(__i).as_ptr() as *const [G; OUT_317]) }; __ret }, _ => aiur_fn_317(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_316] = { let __args: [G; IN_316] = [__v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[316].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[316].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[316].bump_multiplicity(__i); } let __ret: [G; OUT_316] = unsafe { *(record.function_queries[316].output_at(__i).as_ptr() as *const [G; OUT_316]) }; __ret }, _ => aiur_fn_316(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; break '__mc_0 [__v_11]; }, @@ -30110,15 +30064,15 @@ fn aiur_fn_316( match __v_11.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_316] = [__v_12]; - record.function_queries[316].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_315] = [__v_12]; + record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_316] = { let __args: [G; IN_316] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[316].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[316].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[316].bump_multiplicity(__i); } let __ret: [G; OUT_316] = unsafe { *(record.function_queries[316].output_at(__i).as_ptr() as *const [G; OUT_316]) }; __ret }, _ => aiur_fn_316(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_315] = { let __args: [G; IN_315] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[315].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[315].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[315].bump_multiplicity(__i); } let __ret: [G; OUT_315] = unsafe { *(record.function_queries[315].output_at(__i).as_ptr() as *const [G; OUT_315]) }; __ret }, _ => aiur_fn_315(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_316] = [__v_12]; - record.function_queries[316].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_315] = [__v_12]; + record.function_queries[315].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30137,15 +30091,15 @@ fn aiur_fn_316( }) } -const INPUT_SIZE_317: usize = 2; -const IN_317: usize = 2; -const OUT_317: usize = 1; -fn aiur_fn_317( - inp: [G; IN_317], +const INPUT_SIZE_316: usize = 2; +const IN_316: usize = 2; +const OUT_316: usize = 1; +fn aiur_fn_316( + inp: [G; IN_316], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_317], ExecError> { +) -> Result<[G; OUT_316], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30156,8 +30110,8 @@ fn aiur_fn_317( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_317] = [__v_5]; - record.function_queries[317].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_316] = [__v_5]; + record.function_queries[316].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30172,15 +30126,15 @@ fn aiur_fn_317( match __v_9.as_canonical_u64() { 0u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_317] = [__v_10]; - record.function_queries[317].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_316] = [__v_10]; + record.function_queries[316].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_317] = { let __args: [G; IN_317] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[317].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[317].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[317].bump_multiplicity(__i); } let __ret: [G; OUT_317] = unsafe { *(record.function_queries[317].output_at(__i).as_ptr() as *const [G; OUT_317]) }; __ret }, _ => aiur_fn_317(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_316] = { let __args: [G; IN_316] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[316].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[316].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[316].bump_multiplicity(__i); } let __ret: [G; OUT_316] = unsafe { *(record.function_queries[316].output_at(__i).as_ptr() as *const [G; OUT_316]) }; __ret }, _ => aiur_fn_316(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_317] = [__v_10]; - record.function_queries[317].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_316] = [__v_10]; + record.function_queries[316].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30197,15 +30151,15 @@ fn aiur_fn_317( }) } -const INPUT_SIZE_318: usize = 4; -const IN_318: usize = 4; -const OUT_318: usize = 1; -fn aiur_fn_318( - inp: [G; IN_318], +const INPUT_SIZE_317: usize = 4; +const IN_317: usize = 4; +const OUT_317: usize = 1; +fn aiur_fn_317( + inp: [G; IN_317], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_318], ExecError> { +) -> Result<[G; OUT_317], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30218,8 +30172,8 @@ fn aiur_fn_318( match __v_4.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_318] = [__v_7]; - record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_317] = [__v_7]; + record.function_queries[317].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30229,31 +30183,31 @@ fn aiur_fn_318( let __v_9: G = __loaded[2]; match __v_7.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_300] = { let __args: [G; IN_300] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[300].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[300].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[300].bump_multiplicity(__i); } let __ret: [G; OUT_300] = unsafe { *(record.function_queries[300].output_at(__i).as_ptr() as *const [G; OUT_300]) }; __ret }, _ => aiur_fn_300(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_299] = { let __args: [G; IN_299] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[299].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[299].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[299].bump_multiplicity(__i); } let __ret: [G; OUT_299] = unsafe { *(record.function_queries[299].output_at(__i).as_ptr() as *const [G; OUT_299]) }; __ret }, _ => aiur_fn_299(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_318] = { let __args: [G; IN_318] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[318].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[318].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[318].bump_multiplicity(__i); } let __ret: [G; OUT_318] = unsafe { *(record.function_queries[318].output_at(__i).as_ptr() as *const [G; OUT_318]) }; __ret }, _ => aiur_fn_318(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_317] = { let __args: [G; IN_317] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[317].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[317].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[317].bump_multiplicity(__i); } let __ret: [G; OUT_317] = unsafe { *(record.function_queries[317].output_at(__i).as_ptr() as *const [G; OUT_317]) }; __ret }, _ => aiur_fn_317(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_318] = [__v_11]; - record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_317] = [__v_11]; + record.function_queries[317].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_319] = { let __args: [G; IN_319] = [__v_9, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[319].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[319].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[319].bump_multiplicity(__i); } let __ret: [G; OUT_319] = unsafe { *(record.function_queries[319].output_at(__i).as_ptr() as *const [G; OUT_319]) }; __ret }, _ => aiur_fn_319(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_318] = { let __args: [G; IN_318] = [__v_9, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[318].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[318].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[318].bump_multiplicity(__i); } let __ret: [G; OUT_318] = unsafe { *(record.function_queries[318].output_at(__i).as_ptr() as *const [G; OUT_318]) }; __ret }, _ => aiur_fn_318(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_318] = [__v_12]; - record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_317] = [__v_12]; + record.function_queries[317].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_318] = { let __args: [G; IN_318] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[318].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[318].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[318].bump_multiplicity(__i); } let __ret: [G; OUT_318] = unsafe { *(record.function_queries[318].output_at(__i).as_ptr() as *const [G; OUT_318]) }; __ret }, _ => aiur_fn_318(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_317] = { let __args: [G; IN_317] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[317].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[317].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[317].bump_multiplicity(__i); } let __ret: [G; OUT_317] = unsafe { *(record.function_queries[317].output_at(__i).as_ptr() as *const [G; OUT_317]) }; __ret }, _ => aiur_fn_317(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_318] = [__v_12]; - record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_317] = [__v_12]; + record.function_queries[317].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30272,15 +30226,15 @@ fn aiur_fn_318( }) } -const INPUT_SIZE_319: usize = 3; -const IN_319: usize = 3; -const OUT_319: usize = 1; -fn aiur_fn_319( - inp: [G; IN_319], +const INPUT_SIZE_318: usize = 3; +const IN_318: usize = 3; +const OUT_318: usize = 1; +fn aiur_fn_318( + inp: [G; IN_318], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_319], ExecError> { +) -> Result<[G; OUT_318], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30292,8 +30246,8 @@ fn aiur_fn_319( match __v_3.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_319] = [__v_6]; - record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_318] = [__v_6]; + record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30309,15 +30263,15 @@ fn aiur_fn_319( match __v_9.as_canonical_u64() { 0u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_319] = [__v_10]; - record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_318] = [__v_10]; + record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_319] = { let __args: [G; IN_319] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[319].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[319].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[319].bump_multiplicity(__i); } let __ret: [G; OUT_319] = unsafe { *(record.function_queries[319].output_at(__i).as_ptr() as *const [G; OUT_319]) }; __ret }, _ => aiur_fn_319(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_318] = { let __args: [G; IN_318] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[318].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[318].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[318].bump_multiplicity(__i); } let __ret: [G; OUT_318] = unsafe { *(record.function_queries[318].output_at(__i).as_ptr() as *const [G; OUT_318]) }; __ret }, _ => aiur_fn_318(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_319] = [__v_10]; - record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_318] = [__v_10]; + record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30326,10 +30280,10 @@ fn aiur_fn_319( } }, _ => { - let __r_arr: [G; OUT_319] = { let __args: [G; IN_319] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[319].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[319].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[319].bump_multiplicity(__i); } let __ret: [G; OUT_319] = unsafe { *(record.function_queries[319].output_at(__i).as_ptr() as *const [G; OUT_319]) }; __ret }, _ => aiur_fn_319(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_318] = { let __args: [G; IN_318] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[318].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[318].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[318].bump_multiplicity(__i); } let __ret: [G; OUT_318] = unsafe { *(record.function_queries[318].output_at(__i).as_ptr() as *const [G; OUT_318]) }; __ret }, _ => aiur_fn_318(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_319] = [__v_9]; - record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_318] = [__v_9]; + record.function_queries[318].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30343,15 +30297,15 @@ fn aiur_fn_319( }) } -const INPUT_SIZE_320: usize = 2; -const IN_320: usize = 2; -const OUT_320: usize = 1; -fn aiur_fn_320( - inp: [G; IN_320], +const INPUT_SIZE_319: usize = 2; +const IN_319: usize = 2; +const OUT_319: usize = 1; +fn aiur_fn_319( + inp: [G; IN_319], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_320], ExecError> { +) -> Result<[G; OUT_319], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30362,8 +30316,8 @@ fn aiur_fn_320( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_320] = [__v_5]; - record.function_queries[320].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_319] = [__v_5]; + record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30379,7 +30333,7 @@ fn aiur_fn_320( break '__mc_0 [__v_8]; }, _ => { - let __r_arr: [G; OUT_316] = { let __args: [G; IN_316] = [__v_1, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[316].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[316].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[316].bump_multiplicity(__i); } let __ret: [G; OUT_316] = unsafe { *(record.function_queries[316].output_at(__i).as_ptr() as *const [G; OUT_316]) }; __ret }, _ => aiur_fn_316(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_315] = { let __args: [G; IN_315] = [__v_1, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[315].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[315].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[315].bump_multiplicity(__i); } let __ret: [G; OUT_315] = unsafe { *(record.function_queries[315].output_at(__i).as_ptr() as *const [G; OUT_315]) }; __ret }, _ => aiur_fn_315(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; break '__mc_0 [__v_8]; }, @@ -30389,25 +30343,25 @@ fn aiur_fn_320( match __v_8.as_canonical_u64() { 0u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_320] = [__v_9]; - record.function_queries[320].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_319] = [__v_9]; + record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_321] = { let __args: [G; IN_321] = [__v_7, __v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[321].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[321].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[321].bump_multiplicity(__i); } let __ret: [G; OUT_321] = unsafe { *(record.function_queries[321].output_at(__i).as_ptr() as *const [G; OUT_321]) }; __ret }, _ => aiur_fn_321(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_320] = { let __args: [G; IN_320] = [__v_7, __v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[320].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[320].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[320].bump_multiplicity(__i); } let __ret: [G; OUT_320] = unsafe { *(record.function_queries[320].output_at(__i).as_ptr() as *const [G; OUT_320]) }; __ret }, _ => aiur_fn_320(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 0u64 => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_320] = [__v_10]; - record.function_queries[320].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_319] = [__v_10]; + record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_320] = { let __args: [G; IN_320] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[320].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[320].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[320].bump_multiplicity(__i); } let __ret: [G; OUT_320] = unsafe { *(record.function_queries[320].output_at(__i).as_ptr() as *const [G; OUT_320]) }; __ret }, _ => aiur_fn_320(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_319] = { let __args: [G; IN_319] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[319].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[319].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[319].bump_multiplicity(__i); } let __ret: [G; OUT_319] = unsafe { *(record.function_queries[319].output_at(__i).as_ptr() as *const [G; OUT_319]) }; __ret }, _ => aiur_fn_319(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_320] = [__v_10]; - record.function_queries[320].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_319] = [__v_10]; + record.function_queries[319].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30429,15 +30383,15 @@ fn aiur_fn_320( }) } -const INPUT_SIZE_321: usize = 3; -const IN_321: usize = 3; -const OUT_321: usize = 1; -fn aiur_fn_321( - inp: [G; IN_321], +const INPUT_SIZE_320: usize = 3; +const IN_320: usize = 3; +const OUT_320: usize = 1; +fn aiur_fn_320( + inp: [G; IN_320], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_321], ExecError> { +) -> Result<[G; OUT_320], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30449,8 +30403,8 @@ fn aiur_fn_321( match __v_3.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_321] = [__v_6]; - record.function_queries[321].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_320] = [__v_6]; + record.function_queries[320].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30459,20 +30413,20 @@ fn aiur_fn_321( let __v_7: G = __loaded[1]; match __v_6.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_318] = { let __args: [G; IN_318] = [__v_1, __v_2, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[318].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[318].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[318].bump_multiplicity(__i); } let __ret: [G; OUT_318] = unsafe { *(record.function_queries[318].output_at(__i).as_ptr() as *const [G; OUT_318]) }; __ret }, _ => aiur_fn_318(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_317] = { let __args: [G; IN_317] = [__v_1, __v_2, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[317].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[317].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[317].bump_multiplicity(__i); } let __ret: [G; OUT_317] = unsafe { *(record.function_queries[317].output_at(__i).as_ptr() as *const [G; OUT_317]) }; __ret }, _ => aiur_fn_317(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 0u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_321] = [__v_9]; - record.function_queries[321].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_320] = [__v_9]; + record.function_queries[320].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_321] = { let __args: [G; IN_321] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[321].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[321].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[321].bump_multiplicity(__i); } let __ret: [G; OUT_321] = unsafe { *(record.function_queries[321].output_at(__i).as_ptr() as *const [G; OUT_321]) }; __ret }, _ => aiur_fn_321(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_320] = { let __args: [G; IN_320] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[320].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[320].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[320].bump_multiplicity(__i); } let __ret: [G; OUT_320] = unsafe { *(record.function_queries[320].output_at(__i).as_ptr() as *const [G; OUT_320]) }; __ret }, _ => aiur_fn_320(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_321] = [__v_9]; - record.function_queries[321].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_320] = [__v_9]; + record.function_queries[320].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30489,15 +30443,15 @@ fn aiur_fn_321( }) } -const INPUT_SIZE_322: usize = 1; -const IN_322: usize = 1; -const OUT_322: usize = 1; -fn aiur_fn_322( - inp: [G; IN_322], +const INPUT_SIZE_321: usize = 1; +const IN_321: usize = 1; +const OUT_321: usize = 1; +fn aiur_fn_321( + inp: [G; IN_321], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_322], ExecError> { +) -> Result<[G; OUT_321], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(0); @@ -30517,35 +30471,35 @@ fn aiur_fn_322( let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 3] = [__v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = G::from_u64(0); - let __r_arr: [G; OUT_310] = { let __args: [G; IN_310] = [__v_0, __v_16, __v_17, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[310].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[310].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[310].bump_multiplicity(__i); } let __ret: [G; OUT_310] = unsafe { *(record.function_queries[310].output_at(__i).as_ptr() as *const [G; OUT_310]) }; __ret }, _ => aiur_fn_310(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_309] = { let __args: [G; IN_309] = [__v_0, __v_16, __v_17, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[309].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[309].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[309].bump_multiplicity(__i); } let __ret: [G; OUT_309] = unsafe { *(record.function_queries[309].output_at(__i).as_ptr() as *const [G; OUT_309]) }; __ret }, _ => aiur_fn_309(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_312] = { let __args: [G; IN_312] = [__v_18, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[312].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[312].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[312].bump_multiplicity(__i); } let __ret: [G; OUT_312] = unsafe { *(record.function_queries[312].output_at(__i).as_ptr() as *const [G; OUT_312]) }; __ret }, _ => aiur_fn_312(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_311] = { let __args: [G; IN_311] = [__v_18, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[311].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[311].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[311].bump_multiplicity(__i); } let __ret: [G; OUT_311] = unsafe { *(record.function_queries[311].output_at(__i).as_ptr() as *const [G; OUT_311]) }; __ret }, _ => aiur_fn_311(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __ret: [G; OUT_322] = [__v_19]; - record.function_queries[322].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_321] = [__v_19]; + record.function_queries[321].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_323: usize = 2; -const IN_323: usize = 2; -const OUT_323: usize = 1; -fn aiur_fn_323( - inp: [G; IN_323], +const INPUT_SIZE_322: usize = 2; +const IN_322: usize = 2; +const OUT_322: usize = 1; +fn aiur_fn_322( + inp: [G; IN_322], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_323], ExecError> { +) -> Result<[G; OUT_322], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_323] = [__v_3]; - record.function_queries[323].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_322] = [__v_3]; + record.function_queries[322].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30556,19 +30510,19 @@ fn aiur_fn_323( match __v_3.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_323] = [__v_6]; - record.function_queries[323].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_322] = [__v_6]; + record.function_queries[322].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_322] = { let __args: [G; IN_322] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[322].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[322].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[322].bump_multiplicity(__i); } let __ret: [G; OUT_322] = unsafe { *(record.function_queries[322].output_at(__i).as_ptr() as *const [G; OUT_322]) }; __ret }, _ => aiur_fn_322(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_321] = { let __args: [G; IN_321] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[321].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[321].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[321].bump_multiplicity(__i); } let __ret: [G; OUT_321] = unsafe { *(record.function_queries[321].output_at(__i).as_ptr() as *const [G; OUT_321]) }; __ret }, _ => aiur_fn_321(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_322] = { let __args: [G; IN_322] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[322].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[322].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[322].bump_multiplicity(__i); } let __ret: [G; OUT_322] = unsafe { *(record.function_queries[322].output_at(__i).as_ptr() as *const [G; OUT_322]) }; __ret }, _ => aiur_fn_322(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_321] = { let __args: [G; IN_321] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[321].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[321].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[321].bump_multiplicity(__i); } let __ret: [G; OUT_321] = unsafe { *(record.function_queries[321].output_at(__i).as_ptr() as *const [G; OUT_321]) }; __ret }, _ => aiur_fn_321(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_320] = { let __args: [G; IN_320] = [__v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[320].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[320].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[320].bump_multiplicity(__i); } let __ret: [G; OUT_320] = unsafe { *(record.function_queries[320].output_at(__i).as_ptr() as *const [G; OUT_320]) }; __ret }, _ => aiur_fn_320(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_319] = { let __args: [G; IN_319] = [__v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[319].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[319].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[319].bump_multiplicity(__i); } let __ret: [G; OUT_319] = unsafe { *(record.function_queries[319].output_at(__i).as_ptr() as *const [G; OUT_319]) }; __ret }, _ => aiur_fn_319(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_323] = [__v_8]; - record.function_queries[323].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_322] = [__v_8]; + record.function_queries[322].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30580,36 +30534,36 @@ fn aiur_fn_323( }) } -const INPUT_SIZE_324: usize = 2; -const IN_324: usize = 2; -const OUT_324: usize = 1; -fn aiur_fn_324( - inp: [G; IN_324], +const INPUT_SIZE_323: usize = 2; +const IN_323: usize = 2; +const OUT_323: usize = 1; +fn aiur_fn_323( + inp: [G; IN_323], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_324], ExecError> { +) -> Result<[G; OUT_323], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_324] = [__v_3]; - record.function_queries[324].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_323] = [__v_3]; + record.function_queries[323].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_322] = { let __args: [G; IN_322] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[322].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[322].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[322].bump_multiplicity(__i); } let __ret: [G; OUT_322] = unsafe { *(record.function_queries[322].output_at(__i).as_ptr() as *const [G; OUT_322]) }; __ret }, _ => aiur_fn_322(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_321] = { let __args: [G; IN_321] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[321].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[321].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[321].bump_multiplicity(__i); } let __ret: [G; OUT_321] = unsafe { *(record.function_queries[321].output_at(__i).as_ptr() as *const [G; OUT_321]) }; __ret }, _ => aiur_fn_321(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_322] = { let __args: [G; IN_322] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[322].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[322].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[322].bump_multiplicity(__i); } let __ret: [G; OUT_322] = unsafe { *(record.function_queries[322].output_at(__i).as_ptr() as *const [G; OUT_322]) }; __ret }, _ => aiur_fn_322(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_321] = { let __args: [G; IN_321] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[321].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[321].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[321].bump_multiplicity(__i); } let __ret: [G; OUT_321] = unsafe { *(record.function_queries[321].output_at(__i).as_ptr() as *const [G; OUT_321]) }; __ret }, _ => aiur_fn_321(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_315] = { let __args: [G; IN_315] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[315].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[315].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[315].bump_multiplicity(__i); } let __ret: [G; OUT_315] = unsafe { *(record.function_queries[315].output_at(__i).as_ptr() as *const [G; OUT_315]) }; __ret }, _ => aiur_fn_315(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_314] = { let __args: [G; IN_314] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[314].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[314].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[314].bump_multiplicity(__i); } let __ret: [G; OUT_314] = unsafe { *(record.function_queries[314].output_at(__i).as_ptr() as *const [G; OUT_314]) }; __ret }, _ => aiur_fn_314(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_324] = [__v_5]; - record.function_queries[324].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_323] = [__v_5]; + record.function_queries[323].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30619,24 +30573,24 @@ fn aiur_fn_324( }) } -const INPUT_SIZE_325: usize = 2; -const IN_325: usize = 2; -const OUT_325: usize = 1; -fn aiur_fn_325( - inp: [G; IN_325], +const INPUT_SIZE_324: usize = 2; +const IN_324: usize = 2; +const OUT_324: usize = 1; +fn aiur_fn_324( + inp: [G; IN_324], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_325], ExecError> { +) -> Result<[G; OUT_324], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_330] = { let __args: [G; IN_330] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[330].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[330].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[330].bump_multiplicity(__i); } let __ret: [G; OUT_330] = unsafe { *(record.function_queries[330].output_at(__i).as_ptr() as *const [G; OUT_330]) }; __ret }, _ => aiur_fn_330(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_329] = { let __args: [G; IN_329] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[329].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[329].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[329].bump_multiplicity(__i); } let __ret: [G; OUT_329] = unsafe { *(record.function_queries[329].output_at(__i).as_ptr() as *const [G; OUT_329]) }; __ret }, _ => aiur_fn_329(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; match __v_2.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_330] = { let __args: [G; IN_330] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[330].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[330].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[330].bump_multiplicity(__i); } let __ret: [G; OUT_330] = unsafe { *(record.function_queries[330].output_at(__i).as_ptr() as *const [G; OUT_330]) }; __ret }, _ => aiur_fn_330(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_329] = { let __args: [G; IN_329] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[329].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[329].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[329].bump_multiplicity(__i); } let __ret: [G; OUT_329] = unsafe { *(record.function_queries[329].output_at(__i).as_ptr() as *const [G; OUT_329]) }; __ret }, _ => aiur_fn_329(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; match __v_4.as_canonical_u64() { @@ -30644,13 +30598,13 @@ fn aiur_fn_325( let __v_6: G = { let __a_val = __v_3.as_canonical_u64(); let __b_val = __v_5.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_6.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_325] = [__v_1]; - record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_324] = [__v_1]; + record.function_queries[324].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_325] = [__v_0]; - record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_324] = [__v_0]; + record.function_queries[324].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30659,43 +30613,43 @@ fn aiur_fn_325( } }, _ => { - let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_325] = { let __args: [G; IN_325] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[325].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[325].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[325].bump_multiplicity(__i); } let __ret: [G; OUT_325] = unsafe { *(record.function_queries[325].output_at(__i).as_ptr() as *const [G; OUT_325]) }; __ret }, _ => aiur_fn_325(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_325] = [__v_6]; - record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_324] = [__v_6]; + record.function_queries[324].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_325] = { let __args: [G; IN_325] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[325].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[325].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[325].bump_multiplicity(__i); } let __ret: [G; OUT_325] = unsafe { *(record.function_queries[325].output_at(__i).as_ptr() as *const [G; OUT_325]) }; __ret }, _ => aiur_fn_325(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_325] = [__v_4]; - record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_324] = [__v_4]; + record.function_queries[324].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_326: usize = 2; -const IN_326: usize = 2; -const OUT_326: usize = 1; -fn aiur_fn_326( - inp: [G; IN_326], +const INPUT_SIZE_325: usize = 2; +const IN_325: usize = 2; +const OUT_325: usize = 1; +fn aiur_fn_325( + inp: [G; IN_325], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_326], ExecError> { +) -> Result<[G; OUT_325], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_326] = [__v_0]; - record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_325] = [__v_0]; + record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -30705,8 +30659,8 @@ fn aiur_fn_326( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_326] = [__v_1]; - record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_325] = [__v_1]; + record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30716,33 +30670,33 @@ fn aiur_fn_326( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_326] = [__v_0]; - record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_325] = [__v_0]; + record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_328] = { let __args: [G; IN_328] = [__v_1, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[328].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[328].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[328].bump_multiplicity(__i); } let __ret: [G; OUT_328] = unsafe { *(record.function_queries[328].output_at(__i).as_ptr() as *const [G; OUT_328]) }; __ret }, _ => aiur_fn_328(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_1, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_326] = [__v_1]; - record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_325] = [__v_1]; + record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_328] = { let __args: [G; IN_328] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[328].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[328].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[328].bump_multiplicity(__i); } let __ret: [G; OUT_328] = unsafe { *(record.function_queries[328].output_at(__i).as_ptr() as *const [G; OUT_328]) }; __ret }, _ => aiur_fn_328(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_326] = [__v_0]; - record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_325] = [__v_0]; + record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_329] = { let __args: [G; IN_329] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[329].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[329].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[329].bump_multiplicity(__i); } let __ret: [G; OUT_329] = unsafe { *(record.function_queries[329].output_at(__i).as_ptr() as *const [G; OUT_329]) }; __ret }, _ => aiur_fn_329(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_328] = { let __args: [G; IN_328] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[328].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[328].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[328].bump_multiplicity(__i); } let __ret: [G; OUT_328] = unsafe { *(record.function_queries[328].output_at(__i).as_ptr() as *const [G; OUT_328]) }; __ret }, _ => aiur_fn_328(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_326] = [__v_11]; - record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_325] = [__v_11]; + record.function_queries[325].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30766,15 +30720,15 @@ fn aiur_fn_326( }) } -const INPUT_SIZE_327: usize = 2; -const IN_327: usize = 2; -const OUT_327: usize = 1; -fn aiur_fn_327( - inp: [G; IN_327], +const INPUT_SIZE_326: usize = 2; +const IN_326: usize = 2; +const OUT_326: usize = 1; +fn aiur_fn_326( + inp: [G; IN_326], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_327], ExecError> { +) -> Result<[G; OUT_326], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30782,8 +30736,8 @@ fn aiur_fn_327( match __v_2.as_canonical_u64() { 0u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_327] = [__v_3]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_3]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30800,14 +30754,14 @@ fn aiur_fn_327( match __v_6.as_canonical_u64() { 0u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_327] = [__v_9]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_9]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_327] = [__v_9]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_9]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30819,16 +30773,16 @@ fn aiur_fn_327( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_327] = [__v_9]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_9]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_327] = [__v_9]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_9]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30840,19 +30794,19 @@ fn aiur_fn_327( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = (__v_9 * __v_10); - let __ret: [G; OUT_327] = [__v_11]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_11]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_327] = [__v_9]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_9]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30864,19 +30818,19 @@ fn aiur_fn_327( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { 3u64 => { - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = (__v_9 * __v_10); - let __ret: [G; OUT_327] = [__v_11]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_11]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_327] = [__v_9]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_9]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30892,22 +30846,22 @@ fn aiur_fn_327( match __v_9.as_canonical_u64() { 0u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_327] = [__v_10]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_10]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_327] = [__v_10]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_10]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_327] = [__v_9]; - record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_326] = [__v_9]; + record.function_queries[326].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -30921,15 +30875,15 @@ fn aiur_fn_327( }) } -const INPUT_SIZE_328: usize = 2; -const IN_328: usize = 2; -const OUT_328: usize = 1; -fn aiur_fn_328( - inp: [G; IN_328], +const INPUT_SIZE_327: usize = 2; +const IN_327: usize = 2; +const OUT_327: usize = 1; +fn aiur_fn_327( + inp: [G; IN_327], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_328], ExecError> { +) -> Result<[G; OUT_327], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -30939,20 +30893,20 @@ fn aiur_fn_328( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_328] = [__v_6]; - record.function_queries[328].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_327] = [__v_6]; + record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_328] = [__v_6]; - record.function_queries[328].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_327] = [__v_6]; + record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -30962,48 +30916,48 @@ fn aiur_fn_328( }, _ => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_328] = [__v_5]; - record.function_queries[328].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_327] = [__v_5]; + record.function_queries[327].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_329: usize = 2; -const IN_329: usize = 2; -const OUT_329: usize = 1; -fn aiur_fn_329( - inp: [G; IN_329], +const INPUT_SIZE_328: usize = 2; +const IN_328: usize = 2; +const OUT_328: usize = 1; +fn aiur_fn_328( + inp: [G; IN_328], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_329], ExecError> { +) -> Result<[G; OUT_328], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = G::from_u64(0); - let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_330] = { let __args: [G; IN_330] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[330].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[330].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[330].bump_multiplicity(__i); } let __ret: [G; OUT_330] = unsafe { *(record.function_queries[330].output_at(__i).as_ptr() as *const [G; OUT_330]) }; __ret }, _ => aiur_fn_330(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_330] = { let __args: [G; IN_330] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[330].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[330].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[330].bump_multiplicity(__i); } let __ret: [G; OUT_330] = unsafe { *(record.function_queries[330].output_at(__i).as_ptr() as *const [G; OUT_330]) }; __ret }, _ => aiur_fn_330(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = { let __a_val = __v_4.as_canonical_u64(); let __b_val = __v_7.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_9.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_329] = [__v_1]; - record.function_queries[329].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_328] = [__v_1]; + record.function_queries[328].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_329] = [__v_0]; - record.function_queries[329].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_328] = [__v_0]; + record.function_queries[328].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31014,8 +30968,8 @@ fn aiur_fn_329( 0u64 => { let __v_9: G = G::from_u64(2); let __v_10: G = { let __values: [G; 3] = [__v_9, __v_0, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_329] = [__v_10]; - record.function_queries[329].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_328] = [__v_10]; + record.function_queries[328].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31025,15 +30979,15 @@ fn aiur_fn_329( }) } -const INPUT_SIZE_330: usize = 1; -const IN_330: usize = 1; -const OUT_330: usize = 2; -fn aiur_fn_330( - inp: [G; IN_330], +const INPUT_SIZE_329: usize = 1; +const IN_329: usize = 1; +const OUT_329: usize = 2; +fn aiur_fn_329( + inp: [G; IN_329], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_330], ExecError> { +) -> Result<[G; OUT_329], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -31044,12 +30998,12 @@ fn aiur_fn_330( 0u64 => { let __v_4: G = G::from_u64(1); let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_330] = [__v_4, __v_5]; - record.function_queries[330].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_329] = [__v_4, __v_5]; + record.function_queries[329].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_330] = { let __args: [G; IN_330] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[330].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[330].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[330].bump_multiplicity(__i); } let __ret: [G; OUT_330] = unsafe { *(record.function_queries[330].output_at(__i).as_ptr() as *const [G; OUT_330]) }; __ret }, _ => aiur_fn_330(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_329] = { let __args: [G; IN_329] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[329].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[329].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[329].bump_multiplicity(__i); } let __ret: [G; OUT_329] = unsafe { *(record.function_queries[329].output_at(__i).as_ptr() as *const [G; OUT_329]) }; __ret }, _ => aiur_fn_329(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; match __v_4.as_canonical_u64() { @@ -31057,15 +31011,15 @@ fn aiur_fn_330( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = (__v_5 + __v_7); - let __ret: [G; OUT_330] = [__v_6, __v_8]; - record.function_queries[330].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_329] = [__v_6, __v_8]; + record.function_queries[329].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_330] = [__v_6, __v_7]; - record.function_queries[330].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_329] = [__v_6, __v_7]; + record.function_queries[329].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -31073,23 +31027,23 @@ fn aiur_fn_330( _ => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_330] = [__v_4, __v_5]; - record.function_queries[330].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_329] = [__v_4, __v_5]; + record.function_queries[329].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_331: usize = 2; -const IN_331: usize = 2; -const OUT_331: usize = 2; -fn aiur_fn_331( - inp: [G; IN_331], +const INPUT_SIZE_330: usize = 2; +const IN_330: usize = 2; +const OUT_330: usize = 2; +fn aiur_fn_330( + inp: [G; IN_330], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_331], ExecError> { +) -> Result<[G; OUT_330], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31101,31 +31055,31 @@ fn aiur_fn_331( 1u64 => { let __v_5: G = G::from_u64(1); let __v_6: G = (__v_1 + __v_5); - let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_330] = { let __args: [G; IN_330] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[330].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[330].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[330].bump_multiplicity(__i); } let __ret: [G; OUT_330] = unsafe { *(record.function_queries[330].output_at(__i).as_ptr() as *const [G; OUT_330]) }; __ret }, _ => aiur_fn_330(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __ret: [G; OUT_331] = [__v_7, __v_8]; - record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_330] = [__v_7, __v_8]; + record.function_queries[330].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_331] = [__v_0, __v_1]; - record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_330] = [__v_0, __v_1]; + record.function_queries[330].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_332: usize = 2; -const IN_332: usize = 2; -const OUT_332: usize = 1; -fn aiur_fn_332( - inp: [G; IN_332], +const INPUT_SIZE_331: usize = 2; +const IN_331: usize = 2; +const OUT_331: usize = 1; +fn aiur_fn_331( + inp: [G; IN_331], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_332], ExecError> { +) -> Result<[G; OUT_331], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31138,26 +31092,26 @@ fn aiur_fn_332( let __v_5: G = G::from_u64(0); let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_332] = [__v_7]; - record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_331] = [__v_7]; + record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_325] = { let __args: [G; IN_325] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[325].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[325].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[325].bump_multiplicity(__i); } let __ret: [G; OUT_325] = unsafe { *(record.function_queries[325].output_at(__i).as_ptr() as *const [G; OUT_325]) }; __ret }, _ => aiur_fn_325(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_332] = [__v_5]; - record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_331] = [__v_5]; + record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_296] = { let __args: [G; IN_296] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[296].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[296].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[296].bump_multiplicity(__i); } let __ret: [G; OUT_296] = unsafe { *(record.function_queries[296].output_at(__i).as_ptr() as *const [G; OUT_296]) }; __ret }, _ => aiur_fn_296(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_325] = { let __args: [G; IN_325] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[325].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[325].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[325].bump_multiplicity(__i); } let __ret: [G; OUT_325] = unsafe { *(record.function_queries[325].output_at(__i).as_ptr() as *const [G; OUT_325]) }; __ret }, _ => aiur_fn_325(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_332] = [__v_6]; - record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_331] = [__v_6]; + record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -31167,24 +31121,24 @@ fn aiur_fn_332( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_332] = [__v_1]; - record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_331] = [__v_1]; + record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_298] = { let __args: [G; IN_298] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[298].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[298].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[298].bump_multiplicity(__i); } let __ret: [G; OUT_298] = unsafe { *(record.function_queries[298].output_at(__i).as_ptr() as *const [G; OUT_298]) }; __ret }, _ => aiur_fn_298(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_332] = [__v_0]; - record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_331] = [__v_0]; + record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_10: G = G::from_u64(3); let __v_11: G = { let __values: [G; 3] = [__v_10, __v_0, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_332] = [__v_11]; - record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_331] = [__v_11]; + record.function_queries[331].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31203,15 +31157,15 @@ fn aiur_fn_332( }) } -const INPUT_SIZE_333: usize = 1; -const IN_333: usize = 1; -const OUT_333: usize = 1; -fn aiur_fn_333( - inp: [G; IN_333], +const INPUT_SIZE_332: usize = 1; +const IN_332: usize = 1; +const OUT_332: usize = 1; +fn aiur_fn_332( + inp: [G; IN_332], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_333], ExecError> { +) -> Result<[G; OUT_332], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -31223,48 +31177,48 @@ fn aiur_fn_333( let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_333] = [__v_6]; - record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_332] = [__v_6]; + record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_4: G = G::from_u64(4); let __v_5: G = G::from_u64(0); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_2, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_333] = [__v_6]; - record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_332] = [__v_6]; + record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_4: G = G::from_u64(1); - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 3] = [__v_4, __v_5, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_333] = [__v_7]; - record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_332] = [__v_7]; + record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_325] = { let __args: [G; IN_325] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[325].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[325].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[325].bump_multiplicity(__i); } let __ret: [G; OUT_325] = unsafe { *(record.function_queries[325].output_at(__i).as_ptr() as *const [G; OUT_325]) }; __ret }, _ => aiur_fn_325(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_333] = [__v_6]; - record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_332] = [__v_6]; + record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_333] = [__v_6]; - record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_332] = [__v_6]; + record.function_queries[332].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31274,15 +31228,15 @@ fn aiur_fn_333( }) } -const INPUT_SIZE_334: usize = 2; -const IN_334: usize = 2; -const OUT_334: usize = 1; -fn aiur_fn_334( - inp: [G; IN_334], +const INPUT_SIZE_333: usize = 2; +const IN_333: usize = 2; +const OUT_333: usize = 1; +fn aiur_fn_333( + inp: [G; IN_333], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_334], ExecError> { +) -> Result<[G; OUT_333], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31295,47 +31249,47 @@ fn aiur_fn_334( let __v_5: G = G::from_u64(0); let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_334] = [__v_7]; - record.function_queries[334].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_333] = [__v_7]; + record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_5: G = G::from_u64(1); - let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 3] = [__v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_334] = [__v_8]; - record.function_queries[334].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_333] = [__v_8]; + record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_325] = { let __args: [G; IN_325] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[325].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[325].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[325].bump_multiplicity(__i); } let __ret: [G; OUT_325] = unsafe { *(record.function_queries[325].output_at(__i).as_ptr() as *const [G; OUT_325]) }; __ret }, _ => aiur_fn_325(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_334] = [__v_7]; - record.function_queries[334].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_333] = [__v_7]; + record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_334] = [__v_7]; - record.function_queries[334].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_333] = [__v_7]; + record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_334] = [__v_5]; - record.function_queries[334].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_333] = [__v_5]; + record.function_queries[333].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31345,15 +31299,15 @@ fn aiur_fn_334( }) } -const INPUT_SIZE_335: usize = 2; -const IN_335: usize = 2; -const OUT_335: usize = 1; -fn aiur_fn_335( - inp: [G; IN_335], +const INPUT_SIZE_334: usize = 2; +const IN_334: usize = 2; +const OUT_334: usize = 1; +fn aiur_fn_334( + inp: [G; IN_334], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_335], ExecError> { +) -> Result<[G; OUT_334], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31366,19 +31320,19 @@ fn aiur_fn_335( let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_335] = [__v_7]; - record.function_queries[335].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_334] = [__v_7]; + record.function_queries[334].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = { let __values: [G; 3] = [__v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_335] = [__v_8]; - record.function_queries[335].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_334] = [__v_8]; + record.function_queries[334].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31388,15 +31342,15 @@ fn aiur_fn_335( }) } -const INPUT_SIZE_336: usize = 2; -const IN_336: usize = 2; -const OUT_336: usize = 1; -fn aiur_fn_336( - inp: [G; IN_336], +const INPUT_SIZE_335: usize = 2; +const IN_335: usize = 2; +const OUT_335: usize = 1; +fn aiur_fn_335( + inp: [G; IN_335], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_336], ExecError> { +) -> Result<[G; OUT_335], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31406,30 +31360,30 @@ fn aiur_fn_336( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_336] = [__v_0]; - record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_335] = [__v_0]; + record.function_queries[335].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_337] = { let __args: [G; IN_337] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[337].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[337].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[337].bump_multiplicity(__i); } let __ret: [G; OUT_337] = unsafe { *(record.function_queries[337].output_at(__i).as_ptr() as *const [G; OUT_337]) }; __ret }, _ => aiur_fn_337(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_336] = [__v_5]; - record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_335] = [__v_5]; + record.function_queries[335].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_337: usize = 2; -const IN_337: usize = 2; -const OUT_337: usize = 1; -fn aiur_fn_337( - inp: [G; IN_337], +const INPUT_SIZE_336: usize = 2; +const IN_336: usize = 2; +const OUT_336: usize = 1; +fn aiur_fn_336( + inp: [G; IN_336], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_337], ExecError> { +) -> Result<[G; OUT_336], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31443,94 +31397,94 @@ fn aiur_fn_337( let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_6, __v_3, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_8]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_8]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_6: G = G::from_u64(1); - let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_9]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_9]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_6: G = G::from_u64(2); - let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_334] = { let __args: [G; IN_334] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[334].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[334].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[334].bump_multiplicity(__i); } let __ret: [G; OUT_334] = unsafe { *(record.function_queries[334].output_at(__i).as_ptr() as *const [G; OUT_334]) }; __ret }, _ => aiur_fn_334(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_6, __v_3, __v_7, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_9]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_9]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_6: G = G::from_u64(3); - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_10]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_10]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_6: G = G::from_u64(4); - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_10]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_10]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_6: G = G::from_u64(5); - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_10]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_10]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_6: G = G::from_u64(6); - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_10]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_10]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_6: G = G::from_u64(7); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_6, __v_3, __v_4, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_8]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_8]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { let __v_6: G = G::from_u64(8); - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = { let __values: [G; 4] = [__v_6, __v_3, __v_4, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_337] = [__v_8]; - record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_336] = [__v_8]; + record.function_queries[336].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31540,15 +31494,15 @@ fn aiur_fn_337( }) } -const INPUT_SIZE_338: usize = 2; -const IN_338: usize = 2; -const OUT_338: usize = 1; -fn aiur_fn_338( - inp: [G; IN_338], +const INPUT_SIZE_337: usize = 2; +const IN_337: usize = 2; +const OUT_337: usize = 1; +fn aiur_fn_337( + inp: [G; IN_337], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_338], ExecError> { +) -> Result<[G; OUT_337], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31579,14 +31533,14 @@ fn aiur_fn_338( match __v_12.as_canonical_u64() { 1u64 => { let __v_22: G = G::from_u64(1); - let __ret: [G; OUT_338] = [__v_22]; - record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_337] = [__v_22]; + record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_338] = [__v_22]; - record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_337] = [__v_22]; + record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -31606,8 +31560,8 @@ fn aiur_fn_338( match __v_12.as_canonical_u64() { 1u64 => { let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_338] = [__v_22]; - record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_337] = [__v_22]; + record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -31615,16 +31569,16 @@ fn aiur_fn_338( let __v_22: G = __r_arr[0]; match __v_22.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_337] = { let __args: [G; IN_337] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[337].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[337].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[337].bump_multiplicity(__i); } let __ret: [G; OUT_337] = unsafe { *(record.function_queries[337].output_at(__i).as_ptr() as *const [G; OUT_337]) }; __ret }, _ => aiur_fn_337(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_338] = [__v_23]; - record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_337] = [__v_23]; + record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_23: G = G::from_u64(0); - let __ret: [G; OUT_338] = [__v_23]; - record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_337] = [__v_23]; + record.function_queries[337].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31644,15 +31598,15 @@ fn aiur_fn_338( }) } -const INPUT_SIZE_339: usize = 2; -const IN_339: usize = 2; -const OUT_339: usize = 1; -fn aiur_fn_339( - inp: [G; IN_339], +const INPUT_SIZE_338: usize = 2; +const IN_338: usize = 2; +const OUT_338: usize = 1; +fn aiur_fn_338( + inp: [G; IN_338], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_339], ExecError> { +) -> Result<[G; OUT_338], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31669,14 +31623,14 @@ fn aiur_fn_339( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_339] = [__v_8]; - record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_338] = [__v_8]; + record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_339] = [__v_8]; - record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_338] = [__v_8]; + record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -31689,24 +31643,24 @@ fn aiur_fn_339( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_339] = [__v_8]; - record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_338] = [__v_8]; + record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_8: G = (__v_3 - __v_6); match __v_8.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_339] = [__v_9]; - record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_338] = [__v_9]; + record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_339] = [__v_9]; - record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_338] = [__v_9]; + record.function_queries[338].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -31723,15 +31677,15 @@ fn aiur_fn_339( }) } -const INPUT_SIZE_340: usize = 4; -const IN_340: usize = 4; -const OUT_340: usize = 1; -fn aiur_fn_340( - inp: [G; IN_340], +const INPUT_SIZE_339: usize = 4; +const IN_339: usize = 4; +const OUT_339: usize = 1; +fn aiur_fn_339( + inp: [G; IN_339], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_340], ExecError> { +) -> Result<[G; OUT_339], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -31741,16 +31695,16 @@ fn aiur_fn_340( 0u64 => { match __v_2.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_337] = { let __args: [G; IN_337] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[337].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[337].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[337].bump_multiplicity(__i); } let __ret: [G; OUT_337] = unsafe { *(record.function_queries[337].output_at(__i).as_ptr() as *const [G; OUT_337]) }; __ret }, _ => aiur_fn_337(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_340] = [__v_4]; - record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_339] = [__v_4]; + record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_340] = [__v_4]; - record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_339] = [__v_4]; + record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -31758,16 +31712,16 @@ fn aiur_fn_340( 1u64 => { match __v_2.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_340] = [__v_4]; - record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_339] = [__v_4]; + record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_340] = [__v_4]; - record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_339] = [__v_4]; + record.function_queries[339].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -31779,15 +31733,15 @@ fn aiur_fn_340( }) } -const INPUT_SIZE_341: usize = 1; -const IN_341: usize = 1; -const OUT_341: usize = 1; -fn aiur_fn_341( - inp: [G; IN_341], +const INPUT_SIZE_340: usize = 1; +const IN_340: usize = 1; +const OUT_340: usize = 1; +fn aiur_fn_340( + inp: [G; IN_340], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_341], ExecError> { +) -> Result<[G; OUT_340], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -31799,77 +31753,77 @@ fn aiur_fn_341( 0u64 => { let __v_5: G = G::from_u64(1); let __v_6: G = (__v_2 + __v_5); - let __ret: [G; OUT_341] = [__v_6]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_6]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_341] = [__v_5]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_5]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_341] = [__v_5]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_5]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_341] = [__v_5]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_5]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_342] = { let __args: [G; IN_342] = [__v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[342].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[342].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[342].bump_multiplicity(__i); } let __ret: [G; OUT_342] = unsafe { *(record.function_queries[342].output_at(__i).as_ptr() as *const [G; OUT_342]) }; __ret }, _ => aiur_fn_342(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_341] = [__v_7]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_7]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_342] = { let __args: [G; IN_342] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[342].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[342].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[342].bump_multiplicity(__i); } let __ret: [G; OUT_342] = unsafe { *(record.function_queries[342].output_at(__i).as_ptr() as *const [G; OUT_342]) }; __ret }, _ => aiur_fn_342(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_341] = [__v_8]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_8]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_342] = { let __args: [G; IN_342] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[342].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[342].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[342].bump_multiplicity(__i); } let __ret: [G; OUT_342] = unsafe { *(record.function_queries[342].output_at(__i).as_ptr() as *const [G; OUT_342]) }; __ret }, _ => aiur_fn_342(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_341] = [__v_8]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_8]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_342] = { let __args: [G; IN_342] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[342].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[342].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[342].bump_multiplicity(__i); } let __ret: [G; OUT_342] = unsafe { *(record.function_queries[342].output_at(__i).as_ptr() as *const [G; OUT_342]) }; __ret }, _ => aiur_fn_342(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_341] = [__v_5]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_5]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_341] = [__v_5]; - record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_340] = [__v_5]; + record.function_queries[340].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31879,59 +31833,59 @@ fn aiur_fn_341( }) } -const INPUT_SIZE_342: usize = 3; -const IN_342: usize = 3; -const OUT_342: usize = 1; -fn aiur_fn_342( - inp: [G; IN_342], +const INPUT_SIZE_341: usize = 3; +const IN_341: usize = 3; +const OUT_341: usize = 1; +fn aiur_fn_341( + inp: [G; IN_341], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_342], ExecError> { +) -> Result<[G; OUT_341], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_342] = { let __args: [G; IN_342] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[342].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[342].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[342].bump_multiplicity(__i); } let __ret: [G; OUT_342] = unsafe { *(record.function_queries[342].output_at(__i).as_ptr() as *const [G; OUT_342]) }; __ret }, _ => aiur_fn_342(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_342] = { let __args: [G; IN_342] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[342].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[342].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[342].bump_multiplicity(__i); } let __ret: [G; OUT_342] = unsafe { *(record.function_queries[342].output_at(__i).as_ptr() as *const [G; OUT_342]) }; __ret }, _ => aiur_fn_342(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_342] = [__v_8]; - record.function_queries[342].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_341] = [__v_8]; + record.function_queries[341].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_343: usize = 2; -const IN_343: usize = 2; -const OUT_343: usize = 1; -fn aiur_fn_343( - inp: [G; IN_343], +const INPUT_SIZE_342: usize = 2; +const IN_342: usize = 2; +const OUT_342: usize = 1; +fn aiur_fn_342( + inp: [G; IN_342], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_343], ExecError> { +) -> Result<[G; OUT_342], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_1.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_343] = [__v_1]; - record.function_queries[343].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_342] = [__v_1]; + record.function_queries[342].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_343] = [__v_0]; - record.function_queries[343].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_342] = [__v_0]; + record.function_queries[342].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -31941,57 +31895,57 @@ fn aiur_fn_343( }) } -const INPUT_SIZE_344: usize = 1; -const IN_344: usize = 1; -const OUT_344: usize = 1; -fn aiur_fn_344( - inp: [G; IN_344], +const INPUT_SIZE_343: usize = 1; +const IN_343: usize = 1; +const OUT_343: usize = 1; +fn aiur_fn_343( + inp: [G; IN_343], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_344], ExecError> { +) -> Result<[G; OUT_343], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; match __v_0.as_canonical_u64() { 0u64 => { let __v_1: G = G::from_u64(0); - let __ret: [G; OUT_344] = [__v_1]; - record.function_queries[344].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_343] = [__v_1]; + record.function_queries[343].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_1: G = G::from_u64(1); let __v_2: G = (__v_0 - __v_1); - let __ret: [G; OUT_344] = [__v_2]; - record.function_queries[344].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_343] = [__v_2]; + record.function_queries[343].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_345: usize = 2; -const IN_345: usize = 2; -const OUT_345: usize = 1; -fn aiur_fn_345( - inp: [G; IN_345], +const INPUT_SIZE_344: usize = 2; +const IN_344: usize = 2; +const OUT_344: usize = 1; +fn aiur_fn_344( + inp: [G; IN_344], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_345], ExecError> { +) -> Result<[G; OUT_344], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_1.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_345] = [__v_0]; - record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_344] = [__v_0]; + record.function_queries[344].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_345] = [__v_1]; - record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_344] = [__v_1]; + record.function_queries[344].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32001,15 +31955,15 @@ fn aiur_fn_345( }) } -const INPUT_SIZE_346: usize = 3; -const IN_346: usize = 3; -const OUT_346: usize = 1; -fn aiur_fn_346( - inp: [G; IN_346], +const INPUT_SIZE_345: usize = 3; +const IN_345: usize = 3; +const OUT_345: usize = 1; +fn aiur_fn_345( + inp: [G; IN_345], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_346], ExecError> { +) -> Result<[G; OUT_345], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -32025,14 +31979,14 @@ fn aiur_fn_346( match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_346] = [__v_8]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_8]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_8: G = { let __a_val = __v_4.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; - let __ret: [G; OUT_346] = [__v_8]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_8]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32042,37 +31996,37 @@ fn aiur_fn_346( }, 1u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_346] = [__v_7]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_7]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_346] = [__v_7]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_7]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_346] = [__v_7]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_7]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_346] = [__v_8]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_8]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_346] = [__v_8]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_8]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32081,31 +32035,31 @@ fn aiur_fn_346( } }, 4u64 => { - let __r_arr: [G; OUT_347] = { let __args: [G; IN_347] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[347].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[347].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[347].bump_multiplicity(__i); } let __ret: [G; OUT_347] = unsafe { *(record.function_queries[347].output_at(__i).as_ptr() as *const [G; OUT_347]) }; __ret }, _ => aiur_fn_347(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_346] = [__v_7]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_7]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_347] = { let __args: [G; IN_347] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[347].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[347].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[347].bump_multiplicity(__i); } let __ret: [G; OUT_347] = unsafe { *(record.function_queries[347].output_at(__i).as_ptr() as *const [G; OUT_347]) }; __ret }, _ => aiur_fn_347(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_346] = [__v_7]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_7]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_348] = { let __args: [G; IN_348] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[348].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[348].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[348].bump_multiplicity(__i); } let __ret: [G; OUT_348] = unsafe { *(record.function_queries[348].output_at(__i).as_ptr() as *const [G; OUT_348]) }; __ret }, _ => aiur_fn_348(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_347] = { let __args: [G; IN_347] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[347].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[347].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[347].bump_multiplicity(__i); } let __ret: [G; OUT_347] = unsafe { *(record.function_queries[347].output_at(__i).as_ptr() as *const [G; OUT_347]) }; __ret }, _ => aiur_fn_347(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_346] = [__v_7]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_7]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_346] = [__v_7]; - record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_345] = [__v_7]; + record.function_queries[345].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32115,27 +32069,27 @@ fn aiur_fn_346( }) } -const INPUT_SIZE_347: usize = 4; -const IN_347: usize = 4; -const OUT_347: usize = 1; -fn aiur_fn_347( - inp: [G; IN_347], +const INPUT_SIZE_346: usize = 4; +const IN_346: usize = 4; +const OUT_346: usize = 1; +fn aiur_fn_346( + inp: [G; IN_346], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_347], ExecError> { +) -> Result<[G; OUT_346], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_347] = [__v_5]; - record.function_queries[347].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_346] = [__v_5]; + record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -32143,10 +32097,10 @@ fn aiur_fn_347( let __v_6: G = (__v_2 + __v_5); let __v_7: G = G::from_u64(1); let __v_8: G = (__v_3 + __v_7); - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_1, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_1, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_347] = [__v_9]; - record.function_queries[347].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_346] = [__v_9]; + record.function_queries[346].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32156,38 +32110,38 @@ fn aiur_fn_347( }) } -const INPUT_SIZE_348: usize = 5; -const IN_348: usize = 5; -const OUT_348: usize = 1; -fn aiur_fn_348( - inp: [G; IN_348], +const INPUT_SIZE_347: usize = 5; +const IN_347: usize = 5; +const OUT_347: usize = 1; +fn aiur_fn_347( + inp: [G; IN_347], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_348], ExecError> { +) -> Result<[G; OUT_347], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_348] = [__v_6]; - record.function_queries[348].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_347] = [__v_6]; + record.function_queries[347].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_348] = [__v_7]; - record.function_queries[348].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_347] = [__v_7]; + record.function_queries[347].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -32195,10 +32149,10 @@ fn aiur_fn_348( let __v_8: G = (__v_3 + __v_7); let __v_9: G = G::from_u64(1); let __v_10: G = (__v_4 + __v_9); - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_2, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_2, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_348] = [__v_11]; - record.function_queries[348].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_347] = [__v_11]; + record.function_queries[347].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32213,60 +32167,60 @@ fn aiur_fn_348( }) } -const INPUT_SIZE_349: usize = 2; -const IN_349: usize = 2; -const OUT_349: usize = 1; -fn aiur_fn_349( - inp: [G; IN_349], +const INPUT_SIZE_348: usize = 2; +const IN_348: usize = 2; +const OUT_348: usize = 1; +fn aiur_fn_348( + inp: [G; IN_348], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_349], ExecError> { +) -> Result<[G; OUT_348], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_350] = { let __args: [G; IN_350] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[350].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[350].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[350].bump_multiplicity(__i); } let __ret: [G; OUT_350] = unsafe { *(record.function_queries[350].output_at(__i).as_ptr() as *const [G; OUT_350]) }; __ret }, _ => aiur_fn_350(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_349] = { let __args: [G; IN_349] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[349].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[349].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[349].bump_multiplicity(__i); } let __ret: [G; OUT_349] = unsafe { *(record.function_queries[349].output_at(__i).as_ptr() as *const [G; OUT_349]) }; __ret }, _ => aiur_fn_349(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_349] = [__v_4]; - record.function_queries[349].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_348] = [__v_4]; + record.function_queries[348].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_350: usize = 2; -const IN_350: usize = 2; -const OUT_350: usize = 1; -fn aiur_fn_350( - inp: [G; IN_350], +const INPUT_SIZE_349: usize = 2; +const IN_349: usize = 2; +const OUT_349: usize = 1; +fn aiur_fn_349( + inp: [G; IN_349], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_350], ExecError> { +) -> Result<[G; OUT_349], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_351] = { let __args: [G; IN_351] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[351].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[351].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[351].bump_multiplicity(__i); } let __ret: [G; OUT_351] = unsafe { *(record.function_queries[351].output_at(__i).as_ptr() as *const [G; OUT_351]) }; __ret }, _ => aiur_fn_351(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_350] = { let __args: [G; IN_350] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[350].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[350].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[350].bump_multiplicity(__i); } let __ret: [G; OUT_350] = unsafe { *(record.function_queries[350].output_at(__i).as_ptr() as *const [G; OUT_350]) }; __ret }, _ => aiur_fn_350(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = { let __a_val = __v_2.as_canonical_u64(); let __b_val = __v_1.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_350] = [__v_2]; - record.function_queries[350].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_349] = [__v_2]; + record.function_queries[349].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = (__v_1 - __v_2); - let __r_arr: [G; OUT_350] = { let __args: [G; IN_350] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[350].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[350].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[350].bump_multiplicity(__i); } let __ret: [G; OUT_350] = unsafe { *(record.function_queries[350].output_at(__i).as_ptr() as *const [G; OUT_350]) }; __ret }, _ => aiur_fn_350(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_349] = { let __args: [G; IN_349] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[349].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[349].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[349].bump_multiplicity(__i); } let __ret: [G; OUT_349] = unsafe { *(record.function_queries[349].output_at(__i).as_ptr() as *const [G; OUT_349]) }; __ret }, _ => aiur_fn_349(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_2 + __v_6); - let __ret: [G; OUT_350] = [__v_7]; - record.function_queries[350].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_349] = [__v_7]; + record.function_queries[349].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32276,15 +32230,15 @@ fn aiur_fn_350( }) } -const INPUT_SIZE_351: usize = 1; -const IN_351: usize = 1; -const OUT_351: usize = 1; -fn aiur_fn_351( - inp: [G; IN_351], +const INPUT_SIZE_350: usize = 1; +const IN_350: usize = 1; +const OUT_350: usize = 1; +fn aiur_fn_350( + inp: [G; IN_350], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_351], ExecError> { +) -> Result<[G; OUT_350], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -32294,13 +32248,13 @@ fn aiur_fn_351( match __v_1.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(1); - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_351] = { let __args: [G; IN_351] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[351].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[351].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[351].bump_multiplicity(__i); } let __ret: [G; OUT_351] = unsafe { *(record.function_queries[351].output_at(__i).as_ptr() as *const [G; OUT_351]) }; __ret }, _ => aiur_fn_351(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_4 + __v_6); - let __ret: [G; OUT_351] = [__v_7]; - record.function_queries[351].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_350] = [__v_7]; + record.function_queries[350].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32310,44 +32264,44 @@ fn aiur_fn_351( }) } -const INPUT_SIZE_352: usize = 2; -const IN_352: usize = 2; -const OUT_352: usize = 1; -fn aiur_fn_352( - inp: [G; IN_352], +const INPUT_SIZE_351: usize = 2; +const IN_351: usize = 2; +const OUT_351: usize = 1; +fn aiur_fn_351( + inp: [G; IN_351], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_352], ExecError> { +) -> Result<[G; OUT_351], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_1.as_canonical_u64() { 0u64 => { let __v_2: G = G::from_u64(0); - let __ret: [G; OUT_352] = [__v_2]; - record.function_queries[352].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_351] = [__v_2]; + record.function_queries[351].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_351] = { let __args: [G; IN_351] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[351].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[351].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[351].bump_multiplicity(__i); } let __ret: [G; OUT_351] = unsafe { *(record.function_queries[351].output_at(__i).as_ptr() as *const [G; OUT_351]) }; __ret }, _ => aiur_fn_351(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_350] = { let __args: [G; IN_350] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[350].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[350].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[350].bump_multiplicity(__i); } let __ret: [G; OUT_350] = unsafe { *(record.function_queries[350].output_at(__i).as_ptr() as *const [G; OUT_350]) }; __ret }, _ => aiur_fn_350(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = { let __a_val = __v_2.as_canonical_u64(); let __b_val = __v_1.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_352] = [__v_2]; - record.function_queries[352].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_351] = [__v_2]; + record.function_queries[351].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = (__v_1 - __v_2); - let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_351] = { let __args: [G; IN_351] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[351].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[351].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[351].bump_multiplicity(__i); } let __ret: [G; OUT_351] = unsafe { *(record.function_queries[351].output_at(__i).as_ptr() as *const [G; OUT_351]) }; __ret }, _ => aiur_fn_351(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_2 + __v_6); - let __ret: [G; OUT_352] = [__v_7]; - record.function_queries[352].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_351] = [__v_7]; + record.function_queries[351].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32359,15 +32313,15 @@ fn aiur_fn_352( }) } -const INPUT_SIZE_353: usize = 2; -const IN_353: usize = 2; -const OUT_353: usize = 1; -fn aiur_fn_353( - inp: [G; IN_353], +const INPUT_SIZE_352: usize = 2; +const IN_352: usize = 2; +const OUT_352: usize = 1; +fn aiur_fn_352( + inp: [G; IN_352], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_353], ExecError> { +) -> Result<[G; OUT_352], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -32376,31 +32330,31 @@ fn aiur_fn_353( let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); let __v_4: G = { let __values: [G; 3] = [__v_2, __v_3, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_353] = [__v_4]; - record.function_queries[353].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_352] = [__v_4]; + record.function_queries[352].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = { let __a_val = __v_1.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_353] = [__v_0]; - record.function_queries[353].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_352] = [__v_0]; + record.function_queries[352].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_350] = { let __args: [G; IN_350] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[350].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[350].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[350].bump_multiplicity(__i); } let __ret: [G; OUT_350] = unsafe { *(record.function_queries[350].output_at(__i).as_ptr() as *const [G; OUT_350]) }; __ret }, _ => aiur_fn_350(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_349] = { let __args: [G; IN_349] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[349].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[349].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[349].bump_multiplicity(__i); } let __ret: [G; OUT_349] = unsafe { *(record.function_queries[349].output_at(__i).as_ptr() as *const [G; OUT_349]) }; __ret }, _ => aiur_fn_349(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_353] = [__v_7]; - record.function_queries[353].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_352] = [__v_7]; + record.function_queries[352].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32412,19 +32366,19 @@ fn aiur_fn_353( }) } -const INPUT_SIZE_354: usize = 2; -const IN_354: usize = 2; -const OUT_354: usize = 1; -fn aiur_fn_354( - inp: [G; IN_354], +const INPUT_SIZE_353: usize = 2; +const IN_353: usize = 2; +const OUT_353: usize = 1; +fn aiur_fn_353( + inp: [G; IN_353], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_354], ExecError> { +) -> Result<[G; OUT_353], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(1); let __v_4: G = (__v_1 + __v_3); @@ -32433,30 +32387,30 @@ fn aiur_fn_354( match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(4294967295); - let __ret: [G; OUT_354] = [__v_6]; - record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_353] = [__v_6]; + record.function_queries[353].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_355] = { let __args: [G; IN_355] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[355].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[355].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[355].bump_multiplicity(__i); } let __ret: [G; OUT_355] = unsafe { *(record.function_queries[355].output_at(__i).as_ptr() as *const [G; OUT_355]) }; __ret }, _ => aiur_fn_355(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_354] = [__v_6]; - record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_353] = [__v_6]; + record.function_queries[353].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_355: usize = 2; -const IN_355: usize = 2; -const OUT_355: usize = 1; -fn aiur_fn_355( - inp: [G; IN_355], +const INPUT_SIZE_354: usize = 2; +const IN_354: usize = 2; +const OUT_354: usize = 1; +fn aiur_fn_354( + inp: [G; IN_354], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_355], ExecError> { +) -> Result<[G; OUT_354], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -32472,14 +32426,14 @@ fn aiur_fn_355( match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(4294967295); - let __ret: [G; OUT_355] = [__v_7]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_7]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_7: G = (__v_3 - __v_1); - let __ret: [G; OUT_355] = [__v_7]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_7]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32489,71 +32443,71 @@ fn aiur_fn_355( }, 1u64 => { let __v_6: G = G::from_u64(4294967295); - let __ret: [G; OUT_355] = [__v_6]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_6]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_6: G = G::from_u64(4294967295); - let __ret: [G; OUT_355] = [__v_6]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_6]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_6: G = G::from_u64(4294967295); - let __ret: [G; OUT_355] = [__v_6]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_6]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_355] = [__v_7]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_7]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_355] = [__v_9]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_9]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 4u64 => { - let __r_arr: [G; OUT_356] = { let __args: [G; IN_356] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[356].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[356].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[356].bump_multiplicity(__i); } let __ret: [G; OUT_356] = unsafe { *(record.function_queries[356].output_at(__i).as_ptr() as *const [G; OUT_356]) }; __ret }, _ => aiur_fn_356(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_355] = { let __args: [G; IN_355] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[355].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[355].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[355].bump_multiplicity(__i); } let __ret: [G; OUT_355] = unsafe { *(record.function_queries[355].output_at(__i).as_ptr() as *const [G; OUT_355]) }; __ret }, _ => aiur_fn_355(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_355] = [__v_6]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_6]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_356] = { let __args: [G; IN_356] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[356].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[356].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[356].bump_multiplicity(__i); } let __ret: [G; OUT_356] = unsafe { *(record.function_queries[356].output_at(__i).as_ptr() as *const [G; OUT_356]) }; __ret }, _ => aiur_fn_356(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_355] = { let __args: [G; IN_355] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[355].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[355].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[355].bump_multiplicity(__i); } let __ret: [G; OUT_355] = unsafe { *(record.function_queries[355].output_at(__i).as_ptr() as *const [G; OUT_355]) }; __ret }, _ => aiur_fn_355(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_355] = [__v_6]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_6]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_356] = { let __args: [G; IN_356] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[356].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[356].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[356].bump_multiplicity(__i); } let __ret: [G; OUT_356] = unsafe { *(record.function_queries[356].output_at(__i).as_ptr() as *const [G; OUT_356]) }; __ret }, _ => aiur_fn_356(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_355] = [__v_6]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_6]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_355] = [__v_6]; - record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_354] = [__v_6]; + record.function_queries[354].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32563,93 +32517,93 @@ fn aiur_fn_355( }) } -const INPUT_SIZE_356: usize = 3; -const IN_356: usize = 3; -const OUT_356: usize = 1; -fn aiur_fn_356( - inp: [G; IN_356], +const INPUT_SIZE_355: usize = 3; +const IN_355: usize = 3; +const OUT_355: usize = 1; +fn aiur_fn_355( + inp: [G; IN_355], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_356], ExecError> { +) -> Result<[G; OUT_355], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_356] = [__v_4]; - record.function_queries[356].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_355] = [__v_4]; + record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(1); let __v_6: G = (__v_2 + __v_5); - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_356] = [__v_8]; - record.function_queries[356].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_355] = [__v_8]; + record.function_queries[355].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_357: usize = 4; -const IN_357: usize = 4; -const OUT_357: usize = 1; -fn aiur_fn_357( - inp: [G; IN_357], +const INPUT_SIZE_356: usize = 4; +const IN_356: usize = 4; +const OUT_356: usize = 1; +fn aiur_fn_356( + inp: [G; IN_356], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_357], ExecError> { +) -> Result<[G; OUT_356], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_357] = [__v_5]; - record.function_queries[357].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_356] = [__v_5]; + record.function_queries[356].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_357] = [__v_7]; - record.function_queries[357].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_356] = [__v_7]; + record.function_queries[356].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_3 + __v_9); - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_357] = [__v_12]; - record.function_queries[357].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_356] = [__v_12]; + record.function_queries[356].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -32658,41 +32612,41 @@ fn aiur_fn_357( }) } -const INPUT_SIZE_358: usize = 3; -const IN_358: usize = 3; -const OUT_358: usize = 1; -fn aiur_fn_358( - inp: [G; IN_358], +const INPUT_SIZE_357: usize = 3; +const IN_357: usize = 3; +const OUT_357: usize = 1; +fn aiur_fn_357( + inp: [G; IN_357], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_358], ExecError> { +) -> Result<[G; OUT_357], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_358] = [__v_0]; - record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_357] = [__v_0]; + record.function_queries[357].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_358] = [__v_0]; - record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_357] = [__v_0]; + record.function_queries[357].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_359] = { let __args: [G; IN_359] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[359].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[359].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[359].bump_multiplicity(__i); } let __ret: [G; OUT_359] = unsafe { *(record.function_queries[359].output_at(__i).as_ptr() as *const [G; OUT_359]) }; __ret }, _ => aiur_fn_359(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_358] = [__v_5]; - record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_357] = [__v_5]; + record.function_queries[357].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32704,15 +32658,15 @@ fn aiur_fn_358( }) } -const INPUT_SIZE_359: usize = 3; -const IN_359: usize = 3; -const OUT_359: usize = 1; -fn aiur_fn_359( - inp: [G; IN_359], +const INPUT_SIZE_358: usize = 3; +const IN_358: usize = 3; +const OUT_358: usize = 1; +fn aiur_fn_358( + inp: [G; IN_358], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_359], ExecError> { +) -> Result<[G; OUT_358], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -32724,90 +32678,90 @@ fn aiur_fn_359( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_360] = { let __args: [G; IN_360] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[360].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[360].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[360].bump_multiplicity(__i); } let __ret: [G; OUT_360] = unsafe { *(record.function_queries[360].output_at(__i).as_ptr() as *const [G; OUT_360]) }; __ret }, _ => aiur_fn_360(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_359] = { let __args: [G; IN_359] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[359].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[359].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[359].bump_multiplicity(__i); } let __ret: [G; OUT_359] = unsafe { *(record.function_queries[359].output_at(__i).as_ptr() as *const [G; OUT_359]) }; __ret }, _ => aiur_fn_359(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_359] = [__v_7]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_7]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_359] = [__v_9]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_9]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_7: G = G::from_u64(2); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_359] = [__v_9]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_9]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_7: G = G::from_u64(3); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_359] = [__v_11]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_11]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_7: G = G::from_u64(4); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_359] = [__v_13]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_13]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_7: G = G::from_u64(5); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_359] = [__v_13]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_13]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_360] = { let __args: [G; IN_360] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[360].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[360].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[360].bump_multiplicity(__i); } let __ret: [G; OUT_360] = unsafe { *(record.function_queries[360].output_at(__i).as_ptr() as *const [G; OUT_360]) }; __ret }, _ => aiur_fn_360(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_359] = [__v_7]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_7]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_7: G = G::from_u64(7); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_359] = [__v_9]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_9]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { let __v_7: G = G::from_u64(8); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_359] = [__v_9]; - record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_358] = [__v_9]; + record.function_queries[358].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32817,15 +32771,15 @@ fn aiur_fn_359( }) } -const INPUT_SIZE_360: usize = 3; -const IN_360: usize = 3; -const OUT_360: usize = 1; -fn aiur_fn_360( - inp: [G; IN_360], +const INPUT_SIZE_359: usize = 3; +const IN_359: usize = 3; +const OUT_359: usize = 1; +fn aiur_fn_359( + inp: [G; IN_359], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_360], ExecError> { +) -> Result<[G; OUT_359], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -32836,8 +32790,8 @@ fn aiur_fn_360( let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); let __v_6: G = { let __values: [G; 4] = [__v_4, __v_0, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_360] = [__v_6]; - record.function_queries[360].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_359] = [__v_6]; + record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -32845,8 +32799,8 @@ fn aiur_fn_360( let __v_5: G = (__v_0 + __v_1); let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 4] = [__v_4, __v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_360] = [__v_7]; - record.function_queries[360].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_359] = [__v_7]; + record.function_queries[359].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32856,15 +32810,15 @@ fn aiur_fn_360( }) } -const INPUT_SIZE_361: usize = 5; -const IN_361: usize = 5; -const OUT_361: usize = 1; -fn aiur_fn_361( - inp: [G; IN_361], +const INPUT_SIZE_360: usize = 5; +const IN_360: usize = 5; +const OUT_360: usize = 1; +fn aiur_fn_360( + inp: [G; IN_360], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_361], ExecError> { +) -> Result<[G; OUT_360], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -32872,56 +32826,56 @@ fn aiur_fn_361( let __v_3: G = inp[3]; let __v_4: G = inp[4]; let __v_5: G = G::from_u64(6); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = (__v_4 + __v_8); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_2, __v_3, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_2, __v_3, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_361] = [__v_11]; - record.function_queries[361].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_360] = [__v_11]; + record.function_queries[360].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_362: usize = 3; -const IN_362: usize = 3; -const OUT_362: usize = 1; -fn aiur_fn_362( - inp: [G; IN_362], +const INPUT_SIZE_361: usize = 3; +const IN_361: usize = 3; +const OUT_361: usize = 1; +fn aiur_fn_361( + inp: [G; IN_361], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_362], ExecError> { +) -> Result<[G; OUT_361], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_362] = [__v_0]; - record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_361] = [__v_0]; + record.function_queries[361].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_362] = [__v_0]; - record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_361] = [__v_0]; + record.function_queries[361].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_362] = [__v_5]; - record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_361] = [__v_5]; + record.function_queries[361].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32933,15 +32887,15 @@ fn aiur_fn_362( }) } -const INPUT_SIZE_363: usize = 3; -const IN_363: usize = 3; -const OUT_363: usize = 1; -fn aiur_fn_363( - inp: [G; IN_363], +const INPUT_SIZE_362: usize = 3; +const IN_362: usize = 3; +const OUT_362: usize = 1; +fn aiur_fn_362( + inp: [G; IN_362], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_363], ExecError> { +) -> Result<[G; OUT_362], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -32956,8 +32910,8 @@ fn aiur_fn_363( let __v_7: G = { let __a_val = __v_4.as_canonical_u64(); let __b_val = __v_2.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_7.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_363] = [__v_0]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_0]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -32965,8 +32919,8 @@ fn aiur_fn_363( let __v_9: G = (__v_4 - __v_1); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_8, __v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_11]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_11]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -32978,88 +32932,88 @@ fn aiur_fn_363( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_9]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_9]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_7: G = G::from_u64(2); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_9]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_9]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_7: G = G::from_u64(3); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_11]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_11]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_7: G = G::from_u64(4); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_13]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_13]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_7: G = G::from_u64(5); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_13]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_13]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_7: G = G::from_u64(6); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(1); let __v_11: G = (__v_2 + __v_10); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_6, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_6, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_13]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_13]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_7: G = G::from_u64(7); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_9]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_9]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { let __v_7: G = G::from_u64(8); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_363] = [__v_9]; - record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_362] = [__v_9]; + record.function_queries[362].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -33069,15 +33023,15 @@ fn aiur_fn_363( }) } -const INPUT_SIZE_364: usize = 2; -const IN_364: usize = 2; -const OUT_364: usize = 1; -fn aiur_fn_364( - inp: [G; IN_364], +const INPUT_SIZE_363: usize = 2; +const IN_363: usize = 2; +const OUT_363: usize = 1; +fn aiur_fn_363( + inp: [G; IN_363], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_364], ExecError> { +) -> Result<[G; OUT_363], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33092,150 +33046,150 @@ fn aiur_fn_364( match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_364] = [__v_7]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_7]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_364] = [__v_7]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_7]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 3u64 => { - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_364] = [__v_7]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_7]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_364] = [__v_7]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_7]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 4u64 => { - let __r_arr: [G; OUT_365] = { let __args: [G; IN_365] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[365].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[365].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[365].bump_multiplicity(__i); } let __ret: [G; OUT_365] = unsafe { *(record.function_queries[365].output_at(__i).as_ptr() as *const [G; OUT_365]) }; __ret }, _ => aiur_fn_365(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_364] = [__v_6]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_6]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_365] = { let __args: [G; IN_365] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[365].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[365].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[365].bump_multiplicity(__i); } let __ret: [G; OUT_365] = unsafe { *(record.function_queries[365].output_at(__i).as_ptr() as *const [G; OUT_365]) }; __ret }, _ => aiur_fn_365(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_3, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_364] = [__v_6]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_6]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_365] = { let __args: [G; IN_365] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[365].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[365].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[365].bump_multiplicity(__i); } let __ret: [G; OUT_365] = unsafe { *(record.function_queries[365].output_at(__i).as_ptr() as *const [G; OUT_365]) }; __ret }, _ => aiur_fn_365(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_364] = [__v_6]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_6]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_364] = [__v_6]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_6]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_364] = [__v_6]; - record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_363] = [__v_6]; + record.function_queries[363].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_365: usize = 3; -const IN_365: usize = 3; -const OUT_365: usize = 1; -fn aiur_fn_365( - inp: [G; IN_365], +const INPUT_SIZE_364: usize = 3; +const IN_364: usize = 3; +const OUT_364: usize = 1; +fn aiur_fn_364( + inp: [G; IN_364], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_365], ExecError> { +) -> Result<[G; OUT_364], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_365] = [__v_4]; - record.function_queries[365].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_364] = [__v_4]; + record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(1); let __v_5: G = (__v_2 + __v_4); - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_365] = [__v_6]; - record.function_queries[365].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_364] = [__v_6]; + record.function_queries[364].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_366: usize = 4; -const IN_366: usize = 4; -const OUT_366: usize = 1; -fn aiur_fn_366( - inp: [G; IN_366], +const INPUT_SIZE_365: usize = 4; +const IN_365: usize = 4; +const OUT_365: usize = 1; +fn aiur_fn_365( + inp: [G; IN_365], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_366], ExecError> { +) -> Result<[G; OUT_365], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_366] = [__v_5]; - record.function_queries[366].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_365] = [__v_5]; + record.function_queries[365].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_366] = [__v_6]; - record.function_queries[366].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_365] = [__v_6]; + record.function_queries[365].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(1); let __v_7: G = (__v_3 + __v_6); - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_366] = [__v_8]; - record.function_queries[366].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_365] = [__v_8]; + record.function_queries[365].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -33244,48 +33198,48 @@ fn aiur_fn_366( }) } -const INPUT_SIZE_367: usize = 3; -const IN_367: usize = 3; -const OUT_367: usize = 1; -fn aiur_fn_367( - inp: [G; IN_367], +const INPUT_SIZE_366: usize = 3; +const IN_366: usize = 3; +const OUT_366: usize = 1; +fn aiur_fn_366( + inp: [G; IN_366], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_367], ExecError> { +) -> Result<[G; OUT_366], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_367] = [__v_0]; - record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_366] = [__v_0]; + record.function_queries[366].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_364] = { let __args: [G; IN_364] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[364].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[364].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[364].bump_multiplicity(__i); } let __ret: [G; OUT_364] = unsafe { *(record.function_queries[364].output_at(__i).as_ptr() as *const [G; OUT_364]) }; __ret }, _ => aiur_fn_364(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_363] = { let __args: [G; IN_363] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[363].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[363].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[363].bump_multiplicity(__i); } let __ret: [G; OUT_363] = unsafe { *(record.function_queries[363].output_at(__i).as_ptr() as *const [G; OUT_363]) }; __ret }, _ => aiur_fn_363(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_368] = { let __args: [G; IN_368] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[368].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[368].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[368].bump_multiplicity(__i); } let __ret: [G; OUT_368] = unsafe { *(record.function_queries[368].output_at(__i).as_ptr() as *const [G; OUT_368]) }; __ret }, _ => aiur_fn_368(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_367] = [__v_6]; - record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_366] = [__v_6]; + record.function_queries[366].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = (__v_2 + __v_7); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_0, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_0, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_367] = [__v_9]; - record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_366] = [__v_9]; + record.function_queries[366].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -33297,15 +33251,15 @@ fn aiur_fn_367( }) } -const INPUT_SIZE_368: usize = 3; -const IN_368: usize = 3; -const OUT_368: usize = 1; -fn aiur_fn_368( - inp: [G; IN_368], +const INPUT_SIZE_367: usize = 3; +const IN_367: usize = 3; +const OUT_367: usize = 1; +fn aiur_fn_367( + inp: [G; IN_367], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_368], ExecError> { +) -> Result<[G; OUT_367], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33317,90 +33271,90 @@ fn aiur_fn_368( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_369] = { let __args: [G; IN_369] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[369].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[369].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[369].bump_multiplicity(__i); } let __ret: [G; OUT_369] = unsafe { *(record.function_queries[369].output_at(__i).as_ptr() as *const [G; OUT_369]) }; __ret }, _ => aiur_fn_369(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_368] = { let __args: [G; IN_368] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[368].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[368].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[368].bump_multiplicity(__i); } let __ret: [G; OUT_368] = unsafe { *(record.function_queries[368].output_at(__i).as_ptr() as *const [G; OUT_368]) }; __ret }, _ => aiur_fn_368(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_368] = [__v_7]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_7]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_368] = [__v_9]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_9]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_7: G = G::from_u64(2); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_368] = [__v_9]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_9]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_7: G = G::from_u64(3); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_368] = [__v_11]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_11]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_7: G = G::from_u64(4); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_368] = [__v_13]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_13]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_7: G = G::from_u64(5); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_368] = [__v_13]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_13]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_369] = { let __args: [G; IN_369] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[369].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[369].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[369].bump_multiplicity(__i); } let __ret: [G; OUT_369] = unsafe { *(record.function_queries[369].output_at(__i).as_ptr() as *const [G; OUT_369]) }; __ret }, _ => aiur_fn_369(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_368] = [__v_7]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_7]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_7: G = G::from_u64(7); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_368] = [__v_9]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_9]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { let __v_7: G = G::from_u64(8); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_368] = [__v_9]; - record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_367] = [__v_9]; + record.function_queries[367].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -33410,15 +33364,15 @@ fn aiur_fn_368( }) } -const INPUT_SIZE_369: usize = 3; -const IN_369: usize = 3; -const OUT_369: usize = 1; -fn aiur_fn_369( - inp: [G; IN_369], +const INPUT_SIZE_368: usize = 3; +const IN_368: usize = 3; +const OUT_368: usize = 1; +fn aiur_fn_368( + inp: [G; IN_368], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_369], ExecError> { +) -> Result<[G; OUT_368], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33430,8 +33384,8 @@ fn aiur_fn_369( let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); let __v_6: G = { let __values: [G; 4] = [__v_4, __v_0, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_369] = [__v_6]; - record.function_queries[369].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_368] = [__v_6]; + record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -33439,10 +33393,10 @@ fn aiur_fn_369( match __v_4.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_1, __v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_1, __v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_369] = [__v_6]; - record.function_queries[369].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_368] = [__v_6]; + record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -33451,8 +33405,8 @@ fn aiur_fn_369( let __v_7: G = (__v_0 - __v_6); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_5, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_369] = [__v_9]; - record.function_queries[369].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_368] = [__v_9]; + record.function_queries[368].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -33464,15 +33418,15 @@ fn aiur_fn_369( }) } -const INPUT_SIZE_370: usize = 5; -const IN_370: usize = 5; -const OUT_370: usize = 1; -fn aiur_fn_370( - inp: [G; IN_370], +const INPUT_SIZE_369: usize = 5; +const IN_369: usize = 5; +const OUT_369: usize = 1; +fn aiur_fn_369( + inp: [G; IN_369], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_370], ExecError> { +) -> Result<[G; OUT_369], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33480,71 +33434,71 @@ fn aiur_fn_370( let __v_3: G = inp[3]; let __v_4: G = inp[4]; let __v_5: G = G::from_u64(6); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = (__v_4 + __v_8); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_2, __v_3, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_2, __v_3, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_370] = [__v_11]; - record.function_queries[370].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_369] = [__v_11]; + record.function_queries[369].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_371: usize = 3; -const IN_371: usize = 3; -const OUT_371: usize = 1; -fn aiur_fn_371( - inp: [G; IN_371], +const INPUT_SIZE_370: usize = 3; +const IN_370: usize = 3; +const OUT_370: usize = 1; +fn aiur_fn_370( + inp: [G; IN_370], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_371], ExecError> { +) -> Result<[G; OUT_370], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_371] = [__v_0]; - record.function_queries[371].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_370] = [__v_0]; + record.function_queries[370].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_371] = [__v_0]; - record.function_queries[371].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_370] = [__v_0]; + record.function_queries[370].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_6: G = (__v_2 + __v_3); - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_0, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_0, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_373] = { let __args: [G; IN_373] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[373].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[373].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[373].bump_multiplicity(__i); } let __ret: [G; OUT_373] = unsafe { *(record.function_queries[373].output_at(__i).as_ptr() as *const [G; OUT_373]) }; __ret }, _ => aiur_fn_373(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_372] = { let __args: [G; IN_372] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[372].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[372].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[372].bump_multiplicity(__i); } let __ret: [G; OUT_372] = unsafe { *(record.function_queries[372].output_at(__i).as_ptr() as *const [G; OUT_372]) }; __ret }, _ => aiur_fn_372(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_371] = [__v_8]; - record.function_queries[371].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_370] = [__v_8]; + record.function_queries[370].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = (__v_2 + __v_3); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_0, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_0, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_371] = [__v_9]; - record.function_queries[371].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_370] = [__v_9]; + record.function_queries[370].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -33558,33 +33512,33 @@ fn aiur_fn_371( }) } -const INPUT_SIZE_372: usize = 3; -const IN_372: usize = 3; -const OUT_372: usize = 1; -fn aiur_fn_372( - inp: [G; IN_372], +const INPUT_SIZE_371: usize = 3; +const IN_371: usize = 3; +const OUT_371: usize = 1; +fn aiur_fn_371( + inp: [G; IN_371], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_372], ExecError> { +) -> Result<[G; OUT_371], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = (__v_0 - __v_2); let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_4, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_6, __v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_6, __v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_372] = [__v_8]; - record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_371] = [__v_8]; + record.function_queries[371].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -33592,8 +33546,8 @@ fn aiur_fn_372( let __v_7: G = (__v_0 - __v_3); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_372] = [__v_9]; - record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_371] = [__v_9]; + record.function_queries[371].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -33603,15 +33557,15 @@ fn aiur_fn_372( }) } -const INPUT_SIZE_373: usize = 3; -const IN_373: usize = 3; -const OUT_373: usize = 1; -fn aiur_fn_373( - inp: [G; IN_373], +const INPUT_SIZE_372: usize = 3; +const IN_372: usize = 3; +const OUT_372: usize = 1; +fn aiur_fn_372( + inp: [G; IN_372], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_373], ExecError> { +) -> Result<[G; OUT_372], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33623,90 +33577,90 @@ fn aiur_fn_373( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_372] = { let __args: [G; IN_372] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[372].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[372].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[372].bump_multiplicity(__i); } let __ret: [G; OUT_372] = unsafe { *(record.function_queries[372].output_at(__i).as_ptr() as *const [G; OUT_372]) }; __ret }, _ => aiur_fn_372(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_373] = [__v_7]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_7]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_373] = [__v_9]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_9]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_7: G = G::from_u64(2); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_373] = [__v_9]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_9]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_7: G = G::from_u64(3); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_373] = [__v_11]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_11]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_7: G = G::from_u64(4); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_373] = [__v_13]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_13]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_7: G = G::from_u64(5); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_5, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_7, __v_8, __v_11, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_373] = [__v_13]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_13]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_374] = { let __args: [G; IN_374] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[374].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[374].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[374].bump_multiplicity(__i); } let __ret: [G; OUT_374] = unsafe { *(record.function_queries[374].output_at(__i).as_ptr() as *const [G; OUT_374]) }; __ret }, _ => aiur_fn_374(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_373] = { let __args: [G; IN_373] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[373].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[373].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[373].bump_multiplicity(__i); } let __ret: [G; OUT_373] = unsafe { *(record.function_queries[373].output_at(__i).as_ptr() as *const [G; OUT_373]) }; __ret }, _ => aiur_fn_373(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_373] = [__v_7]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_7]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_7: G = G::from_u64(7); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_373] = [__v_9]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_9]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { let __v_7: G = G::from_u64(8); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = { let __values: [G; 4] = [__v_7, __v_4, __v_5, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_373] = [__v_9]; - record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_372] = [__v_9]; + record.function_queries[372].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -33716,15 +33670,15 @@ fn aiur_fn_373( }) } -const INPUT_SIZE_374: usize = 5; -const IN_374: usize = 5; -const OUT_374: usize = 1; -fn aiur_fn_374( - inp: [G; IN_374], +const INPUT_SIZE_373: usize = 5; +const IN_373: usize = 5; +const OUT_373: usize = 1; +fn aiur_fn_373( + inp: [G; IN_373], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_374], ExecError> { +) -> Result<[G; OUT_373], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33732,30 +33686,30 @@ fn aiur_fn_374( let __v_3: G = inp[3]; let __v_4: G = inp[4]; let __v_5: G = G::from_u64(6); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = (__v_4 + __v_8); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_2, __v_3, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_2, __v_3, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = { let __values: [G; 4] = [__v_5, __v_6, __v_7, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_374] = [__v_11]; - record.function_queries[374].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_373] = [__v_11]; + record.function_queries[373].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_375: usize = 3; -const IN_375: usize = 3; -const OUT_375: usize = 3; -fn aiur_fn_375( - inp: [G; IN_375], +const INPUT_SIZE_374: usize = 3; +const IN_374: usize = 3; +const OUT_374: usize = 3; +fn aiur_fn_374( + inp: [G; IN_374], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_375], ExecError> { +) -> Result<[G; OUT_374], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33775,17 +33729,17 @@ fn aiur_fn_375( 0u64 => { let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 3] = [__v_10, __v_8, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_375] = { let __args: [G; IN_375] = [__v_5, __v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[375].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[375].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[375].bump_multiplicity(__i); } let __ret: [G; OUT_375] = unsafe { *(record.function_queries[375].output_at(__i).as_ptr() as *const [G; OUT_375]) }; __ret }, _ => aiur_fn_375(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_374] = { let __args: [G; IN_374] = [__v_5, __v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[374].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[374].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[374].bump_multiplicity(__i); } let __ret: [G; OUT_374] = unsafe { *(record.function_queries[374].output_at(__i).as_ptr() as *const [G; OUT_374]) }; __ret }, _ => aiur_fn_374(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; let __v_14: G = __r_arr[2]; - let __ret: [G; OUT_375] = [__v_12, __v_13, __v_14]; - record.function_queries[375].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_374] = [__v_12, __v_13, __v_14]; + record.function_queries[374].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __ret: [G; OUT_375] = [__v_0, __v_2, __v_1]; - record.function_queries[375].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_374] = [__v_0, __v_2, __v_1]; + record.function_queries[374].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -33794,23 +33748,23 @@ fn aiur_fn_375( } }, _ => { - let __ret: [G; OUT_375] = [__v_0, __v_2, __v_1]; - record.function_queries[375].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_374] = [__v_0, __v_2, __v_1]; + record.function_queries[374].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_376: usize = 3; -const IN_376: usize = 3; -const OUT_376: usize = 1; -fn aiur_fn_376( - inp: [G; IN_376], +const INPUT_SIZE_375: usize = 3; +const IN_375: usize = 3; +const OUT_375: usize = 1; +fn aiur_fn_375( + inp: [G; IN_375], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_376], ExecError> { +) -> Result<[G; OUT_375], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33818,56 +33772,56 @@ fn aiur_fn_376( let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_375] = { let __args: [G; IN_375] = [__v_1, __v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[375].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[375].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[375].bump_multiplicity(__i); } let __ret: [G; OUT_375] = unsafe { *(record.function_queries[375].output_at(__i).as_ptr() as *const [G; OUT_375]) }; __ret }, _ => aiur_fn_375(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_374] = { let __args: [G; IN_374] = [__v_1, __v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[374].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[374].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[374].bump_multiplicity(__i); } let __ret: [G; OUT_374] = unsafe { *(record.function_queries[374].output_at(__i).as_ptr() as *const [G; OUT_374]) }; __ret }, _ => aiur_fn_374(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; let __v_8: G = __r_arr[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_1, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_1, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_376] = [__v_10]; - record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_375] = [__v_10]; + record.function_queries[375].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_6, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_6, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_13, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_13, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_376] = [__v_14]; - record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_375] = [__v_14]; + record.function_queries[375].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_6, __v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_6, __v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_11, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_11, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_376] = [__v_12]; - record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_375] = [__v_12]; + record.function_queries[375].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_377: usize = 3; -const IN_377: usize = 3; -const OUT_377: usize = 1; -fn aiur_fn_377( - inp: [G; IN_377], +const INPUT_SIZE_376: usize = 3; +const IN_376: usize = 3; +const OUT_376: usize = 1; +fn aiur_fn_376( + inp: [G; IN_376], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_377], ExecError> { +) -> Result<[G; OUT_376], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -33882,87 +33836,87 @@ fn aiur_fn_377( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_7, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_7, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_377] = [__v_10]; - record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_376] = [__v_10]; + record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_375] = { let __args: [G; IN_375] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[375].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[375].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[375].bump_multiplicity(__i); } let __ret: [G; OUT_375] = unsafe { *(record.function_queries[375].output_at(__i).as_ptr() as *const [G; OUT_375]) }; __ret }, _ => aiur_fn_375(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_377] = [__v_7]; - record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_376] = [__v_7]; + record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_396] = { let __args: [G; IN_396] = [__v_4, __v_5, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[396].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[396].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[396].bump_multiplicity(__i); } let __ret: [G; OUT_396] = unsafe { *(record.function_queries[396].output_at(__i).as_ptr() as *const [G; OUT_396]) }; __ret }, _ => aiur_fn_396(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_395] = { let __args: [G; IN_395] = [__v_4, __v_5, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[395].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[395].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[395].bump_multiplicity(__i); } let __ret: [G; OUT_395] = unsafe { *(record.function_queries[395].output_at(__i).as_ptr() as *const [G; OUT_395]) }; __ret }, _ => aiur_fn_395(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_377] = [__v_7]; - record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_376] = [__v_7]; + record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_6, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_6, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_377] = [__v_9]; - record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_376] = [__v_9]; + record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_378] = { let __args: [G; IN_378] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[378].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[378].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[378].bump_multiplicity(__i); } let __ret: [G; OUT_378] = unsafe { *(record.function_queries[378].output_at(__i).as_ptr() as *const [G; OUT_378]) }; __ret }, _ => aiur_fn_378(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_377] = [__v_7]; - record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_376] = [__v_7]; + record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_377] = [__v_7]; - record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_376] = [__v_7]; + record.function_queries[376].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_378: usize = 5; -const IN_378: usize = 5; -const OUT_378: usize = 1; -fn aiur_fn_378( - inp: [G; IN_378], +const INPUT_SIZE_377: usize = 5; +const IN_377: usize = 5; +const OUT_377: usize = 1; +fn aiur_fn_377( + inp: [G; IN_377], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_378], ExecError> { +) -> Result<[G; OUT_377], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_231] = { let __args: [G; IN_231] = [__v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[231].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[231].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[231].bump_multiplicity(__i); } let __ret: [G; OUT_231] = unsafe { *(record.function_queries[231].output_at(__i).as_ptr() as *const [G; OUT_231]) }; __ret }, _ => aiur_fn_231(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_230] = { let __args: [G; IN_230] = [__v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[230].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[230].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[230].bump_multiplicity(__i); } let __ret: [G; OUT_230] = unsafe { *(record.function_queries[230].output_at(__i).as_ptr() as *const [G; OUT_230]) }; __ret }, _ => aiur_fn_230(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __r_arr: [G; OUT_385] = { let __args: [G; IN_385] = [__v_0, __v_1, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[385].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[385].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[385].bump_multiplicity(__i); } let __ret: [G; OUT_385] = unsafe { *(record.function_queries[385].output_at(__i).as_ptr() as *const [G; OUT_385]) }; __ret }, _ => aiur_fn_385(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_384] = { let __args: [G; IN_384] = [__v_0, __v_1, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[384].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[384].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[384].bump_multiplicity(__i); } let __ret: [G; OUT_384] = unsafe { *(record.function_queries[384].output_at(__i).as_ptr() as *const [G; OUT_384]) }; __ret }, _ => aiur_fn_384(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_10, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_10, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_378] = [__v_11]; - record.function_queries[378].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_377] = [__v_11]; + record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -33973,7 +33927,7 @@ fn aiur_fn_378( let __v_14: G = __loaded[3]; match __v_11.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_385] = { let __args: [G; IN_385] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[385].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[385].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[385].bump_multiplicity(__i); } let __ret: [G; OUT_385] = unsafe { *(record.function_queries[385].output_at(__i).as_ptr() as *const [G; OUT_385]) }; __ret }, _ => aiur_fn_385(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_15.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_16: G = __loaded[0]; @@ -33991,21 +33945,21 @@ fn aiur_fn_378( match __v_16.as_canonical_u64() { 6u64 => { let __v_28: G = (__v_22 + __v_1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_8, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_8, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_29, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_29, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __ret: [G; OUT_378] = [__v_30]; - record.function_queries[378].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_377] = [__v_30]; + record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_28: G = G::from_u64(8); let __v_29: G = { let __values: [G; 4] = [__v_28, __v_0, __v_1, __v_5]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_29, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_29, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __ret: [G; OUT_378] = [__v_30]; - record.function_queries[378].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_377] = [__v_30]; + record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34013,10 +33967,10 @@ fn aiur_fn_378( _ => { let __v_15: G = G::from_u64(8); let __v_16: G = { let __values: [G; 4] = [__v_15, __v_0, __v_1, __v_5]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_16, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_16, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_378] = [__v_17]; - record.function_queries[378].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_377] = [__v_17]; + record.function_queries[377].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34025,15 +33979,15 @@ fn aiur_fn_378( }) } -const INPUT_SIZE_379: usize = 0; -const IN_379: usize = 0; -const OUT_379: usize = 1; -fn aiur_fn_379( - inp: [G; IN_379], +const INPUT_SIZE_378: usize = 0; +const IN_378: usize = 0; +const OUT_378: usize = 1; +fn aiur_fn_378( + inp: [G; IN_378], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_379], ExecError> { +) -> Result<[G; OUT_378], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(167); let __v_1: G = G::from_u64(233); @@ -34068,21 +34022,21 @@ fn aiur_fn_379( let __v_30: G = G::from_u64(232); let __v_31: G = G::from_u64(96); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_379] = [__v_32]; - record.function_queries[379].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_378] = [__v_32]; + record.function_queries[378].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_380: usize = 0; -const IN_380: usize = 0; -const OUT_380: usize = 1; -fn aiur_fn_380( - inp: [G; IN_380], +const INPUT_SIZE_379: usize = 0; +const IN_379: usize = 0; +const OUT_379: usize = 1; +fn aiur_fn_379( + inp: [G; IN_379], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_380], ExecError> { +) -> Result<[G; OUT_379], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(106); let __v_1: G = G::from_u64(247); @@ -34117,21 +34071,21 @@ fn aiur_fn_380( let __v_30: G = G::from_u64(167); let __v_31: G = G::from_u64(19); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_380] = [__v_32]; - record.function_queries[380].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_379] = [__v_32]; + record.function_queries[379].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_381: usize = 0; -const IN_381: usize = 0; -const OUT_381: usize = 1; -fn aiur_fn_381( - inp: [G; IN_381], +const INPUT_SIZE_380: usize = 0; +const IN_380: usize = 0; +const OUT_380: usize = 1; +fn aiur_fn_380( + inp: [G; IN_380], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_381], ExecError> { +) -> Result<[G; OUT_380], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(29); let __v_1: G = G::from_u64(255); @@ -34166,21 +34120,21 @@ fn aiur_fn_381( let __v_30: G = G::from_u64(113); let __v_31: G = G::from_u64(77); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_381] = [__v_32]; - record.function_queries[381].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_380] = [__v_32]; + record.function_queries[380].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_382: usize = 0; -const IN_382: usize = 0; -const OUT_382: usize = 1; -fn aiur_fn_382( - inp: [G; IN_382], +const INPUT_SIZE_381: usize = 0; +const IN_381: usize = 0; +const OUT_381: usize = 1; +fn aiur_fn_381( + inp: [G; IN_381], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_382], ExecError> { +) -> Result<[G; OUT_381], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(10); let __v_1: G = G::from_u64(76); @@ -34215,21 +34169,21 @@ fn aiur_fn_382( let __v_30: G = G::from_u64(89); let __v_31: G = G::from_u64(164); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_382] = [__v_32]; - record.function_queries[382].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_381] = [__v_32]; + record.function_queries[381].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_383: usize = 0; -const IN_383: usize = 0; -const OUT_383: usize = 1; -fn aiur_fn_383( - inp: [G; IN_383], +const INPUT_SIZE_382: usize = 0; +const IN_382: usize = 0; +const OUT_382: usize = 1; +fn aiur_fn_382( + inp: [G; IN_382], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_383], ExecError> { +) -> Result<[G; OUT_382], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(86); let __v_1: G = G::from_u64(2); @@ -34264,21 +34218,21 @@ fn aiur_fn_383( let __v_30: G = G::from_u64(141); let __v_31: G = G::from_u64(48); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_383] = [__v_32]; - record.function_queries[383].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_382] = [__v_32]; + record.function_queries[382].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_384: usize = 0; -const IN_384: usize = 0; -const OUT_384: usize = 1; -fn aiur_fn_384( - inp: [G; IN_384], +const INPUT_SIZE_383: usize = 0; +const IN_383: usize = 0; +const OUT_383: usize = 1; +fn aiur_fn_383( + inp: [G; IN_383], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_384], ExecError> { +) -> Result<[G; OUT_383], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(2); let __v_1: G = G::from_u64(243); @@ -34313,27 +34267,27 @@ fn aiur_fn_384( let __v_30: G = G::from_u64(60); let __v_31: G = G::from_u64(93); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_384] = [__v_32]; - record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_383] = [__v_32]; + record.function_queries[383].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_385: usize = 4; -const IN_385: usize = 4; -const OUT_385: usize = 2; -fn aiur_fn_385( - inp: [G; IN_385], +const INPUT_SIZE_384: usize = 4; +const IN_384: usize = 4; +const OUT_384: usize = 2; +fn aiur_fn_384( + inp: [G; IN_384], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_385], ExecError> { +) -> Result<[G; OUT_384], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_379] = { let __args: [G; IN_379] = []; let __cu = unconstrained; let __hit = record.function_queries[379].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[379].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[379].bump_multiplicity(__i); } let __ret: [G; OUT_379] = unsafe { *(record.function_queries[379].output_at(__i).as_ptr() as *const [G; OUT_379]) }; __ret }, _ => aiur_fn_379(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_378] = { let __args: [G; IN_378] = []; let __cu = unconstrained; let __hit = record.function_queries[378].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[378].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[378].bump_multiplicity(__i); } let __ret: [G; OUT_378] = unsafe { *(record.function_queries[378].output_at(__i).as_ptr() as *const [G; OUT_378]) }; __ret }, _ => aiur_fn_378(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; @@ -34344,8 +34298,8 @@ fn aiur_fn_385( let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_6, __v_10]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_6, __v_10]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -34358,7 +34312,7 @@ fn aiur_fn_385( let __v_9: G = __loaded[3]; match __v_6.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_380] = { let __args: [G; IN_380] = []; let __cu = unconstrained; let __hit = record.function_queries[380].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[380].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[380].bump_multiplicity(__i); } let __ret: [G; OUT_380] = unsafe { *(record.function_queries[380].output_at(__i).as_ptr() as *const [G; OUT_380]) }; __ret }, _ => aiur_fn_380(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_379] = { let __args: [G; IN_379] = []; let __cu = unconstrained; let __hit = record.function_queries[379].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[379].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[379].bump_multiplicity(__i); } let __ret: [G; OUT_379] = unsafe { *(record.function_queries[379].output_at(__i).as_ptr() as *const [G; OUT_379]) }; __ret }, _ => aiur_fn_379(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; @@ -34369,12 +34323,12 @@ fn aiur_fn_385( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_12, __v_16]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_12, __v_16]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(5); let __v_14: G = { let __a_val = __v_12.as_canonical_u64(); let __b_val = __v_13.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -34385,25 +34339,25 @@ fn aiur_fn_385( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_16, __v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_15, __v_19]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_15, __v_19]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = G::from_u64(2); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = G::from_u64(3); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = G::from_u64(4); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_18.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_25: G = __loaded[0]; @@ -34437,7 +34391,7 @@ fn aiur_fn_385( let __v_45: G = G::from_u64(0); let __v_46: G = { let __values: [G; 4] = [__v_44, __v_39, __v_43, __v_45]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_47: G = G::from_u64(2); - let __r_arr: [G; OUT_381] = { let __args: [G; IN_381] = []; let __cu = unconstrained; let __hit = record.function_queries[381].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[381].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[381].bump_multiplicity(__i); } let __ret: [G; OUT_381] = unsafe { *(record.function_queries[381].output_at(__i).as_ptr() as *const [G; OUT_381]) }; __ret }, _ => aiur_fn_381(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_380] = { let __args: [G; IN_380] = []; let __cu = unconstrained; let __hit = record.function_queries[380].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[380].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[380].bump_multiplicity(__i); } let __ret: [G; OUT_380] = unsafe { *(record.function_queries[380].output_at(__i).as_ptr() as *const [G; OUT_380]) }; __ret }, _ => aiur_fn_380(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; let __v_49: G = G::from_u64(1); let __v_50: G = G::from_u64(1); @@ -34466,13 +34420,13 @@ fn aiur_fn_385( let __v_73: G = G::from_u64(0); let __v_74: G = { let __values: [G; 4] = [__v_72, __v_71, __v_24, __v_73]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_75: G = G::from_u64(5); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_3, __v_75]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_3, __v_75]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_76: G = __r_arr[0]; let __v_77: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_74, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_74, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_78: G = __r_arr[0]; - let __ret: [G; OUT_385] = [__v_77, __v_78]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_77, __v_78]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -34481,8 +34435,8 @@ fn aiur_fn_385( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(0); let __v_46: G = { let __values: [G; 4] = [__v_43, __v_44, __v_45, __v_45]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_42, __v_46]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_42, __v_46]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34493,8 +34447,8 @@ fn aiur_fn_385( let __v_35: G = G::from_u64(0); let __v_36: G = G::from_u64(0); let __v_37: G = { let __values: [G; 4] = [__v_34, __v_35, __v_36, __v_36]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_33, __v_37]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_33, __v_37]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34505,8 +34459,8 @@ fn aiur_fn_385( let __v_31: G = G::from_u64(0); let __v_32: G = G::from_u64(0); let __v_33: G = { let __values: [G; 4] = [__v_30, __v_31, __v_32, __v_32]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_29, __v_33]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_29, __v_33]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34521,8 +34475,8 @@ fn aiur_fn_385( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_10, __v_14]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_10, __v_14]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34533,8 +34487,8 @@ fn aiur_fn_385( let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_385] = [__v_6, __v_10]; - record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_384] = [__v_6, __v_10]; + record.function_queries[384].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34543,15 +34497,15 @@ fn aiur_fn_385( }) } -const INPUT_SIZE_386: usize = 1; -const IN_386: usize = 1; -const OUT_386: usize = 1; -fn aiur_fn_386( - inp: [G; IN_386], +const INPUT_SIZE_385: usize = 1; +const IN_385: usize = 1; +const OUT_385: usize = 1; +fn aiur_fn_385( + inp: [G; IN_385], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_386], ExecError> { +) -> Result<[G; OUT_385], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -34561,10 +34515,10 @@ fn aiur_fn_386( let __v_4: G = __loaded[3]; match __v_1.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_386] = [__v_5]; - record.function_queries[386].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_385] = [__v_5]; + record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -34579,23 +34533,23 @@ fn aiur_fn_386( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 12] = [__v_5, __v_6, __v_12, __v_13, __v_14, __v_14, __v_14, __v_14, __v_14, __v_14, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_386] = [__v_15]; - record.function_queries[386].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_385] = [__v_15]; + record.function_queries[385].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_387: usize = 2; -const IN_387: usize = 2; -const OUT_387: usize = 1; -fn aiur_fn_387( - inp: [G; IN_387], +const INPUT_SIZE_386: usize = 2; +const IN_386: usize = 2; +const OUT_386: usize = 1; +fn aiur_fn_386( + inp: [G; IN_386], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_387], ExecError> { +) -> Result<[G; OUT_386], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -34608,19 +34562,19 @@ fn aiur_fn_387( let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_387] = [__v_7]; - record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_386] = [__v_7]; + record.function_queries[386].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = { let __values: [G; 3] = [__v_6, __v_5, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_387] = [__v_8]; - record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_386] = [__v_8]; + record.function_queries[386].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -34630,28 +34584,28 @@ fn aiur_fn_387( }) } -const INPUT_SIZE_388: usize = 3; -const IN_388: usize = 3; -const OUT_388: usize = 2; -fn aiur_fn_388( - inp: [G; IN_388], +const INPUT_SIZE_387: usize = 3; +const IN_387: usize = 3; +const OUT_387: usize = 2; +fn aiur_fn_387( + inp: [G; IN_387], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_388], ExecError> { +) -> Result<[G; OUT_387], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; @@ -34666,31 +34620,31 @@ fn aiur_fn_388( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_388] = [__v_11, __v_15]; - record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_387] = [__v_11, __v_15]; + record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; match __v_13.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(1); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(1); let __r_arr: [G; OUT_116] = { let __args: [G; IN_116] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[116].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[116].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[116].bump_multiplicity(__i); } let __ret: [G; OUT_116] = unsafe { *(record.function_queries[116].output_at(__i).as_ptr() as *const [G; OUT_116]) }; __ret }, _ => aiur_fn_116(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_19, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_19, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_388] = [__v_17, __v_20]; - record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_387] = [__v_17, __v_20]; + record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -34699,8 +34653,8 @@ fn aiur_fn_388( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_16, __v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_388] = [__v_15, __v_19]; - record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_387] = [__v_15, __v_19]; + record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34719,33 +34673,33 @@ fn aiur_fn_388( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_388] = [__v_11, __v_15]; - record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_387] = [__v_11, __v_15]; + record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; match __v_13.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(1); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(1); let __r_arr: [G; OUT_125] = { let __args: [G; IN_125] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[125].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[125].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[125].bump_multiplicity(__i); } let __ret: [G; OUT_125] = unsafe { *(record.function_queries[125].output_at(__i).as_ptr() as *const [G; OUT_125]) }; __ret }, _ => aiur_fn_125(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_20, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_20, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_388] = [__v_17, __v_21]; - record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_387] = [__v_17, __v_21]; + record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -34754,8 +34708,8 @@ fn aiur_fn_388( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_16, __v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_388] = [__v_15, __v_19]; - record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_387] = [__v_15, __v_19]; + record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34763,11 +34717,11 @@ fn aiur_fn_388( } }, _ => { - let __r_arr: [G; OUT_264] = { let __args: [G; IN_264] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[264].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[264].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[264].bump_multiplicity(__i); } let __ret: [G; OUT_264] = unsafe { *(record.function_queries[264].output_at(__i).as_ptr() as *const [G; OUT_264]) }; __ret }, _ => aiur_fn_264(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_263] = { let __args: [G; IN_263] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[263].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[263].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[263].bump_multiplicity(__i); } let __ret: [G; OUT_263] = unsafe { *(record.function_queries[263].output_at(__i).as_ptr() as *const [G; OUT_263]) }; __ret }, _ => aiur_fn_263(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_388] = [__v_9, __v_10]; - record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_387] = [__v_9, __v_10]; + record.function_queries[387].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -34776,19 +34730,19 @@ fn aiur_fn_388( }) } -const INPUT_SIZE_389: usize = 2; -const IN_389: usize = 2; -const OUT_389: usize = 1; -fn aiur_fn_389( - inp: [G; IN_389], +const INPUT_SIZE_388: usize = 2; +const IN_388: usize = 2; +const OUT_388: usize = 1; +fn aiur_fn_388( + inp: [G; IN_388], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_389], ExecError> { +) -> Result<[G; OUT_388], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_2.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_3: G = __loaded[0]; @@ -34796,8 +34750,8 @@ fn aiur_fn_389( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_389] = [__v_2]; - record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_388] = [__v_2]; + record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -34807,26 +34761,26 @@ fn aiur_fn_389( let __v_8: G = __loaded[2]; match __v_6.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_389] = [__v_2]; - record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_388] = [__v_2]; + record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 3] = [__v_15, __v_12, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = { let __values: [G; 3] = [__v_14, __v_13, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_389] = [__v_17]; - record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_388] = [__v_17]; + record.function_queries[388].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -34841,18 +34795,18 @@ fn aiur_fn_389( }) } -const INPUT_SIZE_390: usize = 1; -const IN_390: usize = 1; -const OUT_390: usize = 1; -fn aiur_fn_390( - inp: [G; IN_390], +const INPUT_SIZE_389: usize = 1; +const IN_389: usize = 1; +const OUT_389: usize = 1; +fn aiur_fn_389( + inp: [G; IN_389], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_390], ExecError> { +) -> Result<[G; OUT_389], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; @@ -34862,7 +34816,7 @@ fn aiur_fn_390( break '__mc_0 [__v_3]; }, _ => { - let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; @@ -34872,7 +34826,7 @@ fn aiur_fn_390( break '__mc_0 [__v_5]; }, _ => { - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; @@ -34882,7 +34836,7 @@ fn aiur_fn_390( break '__mc_0 [__v_7]; }, _ => { - let __r_arr: [G; OUT_163] = { let __args: [G; IN_163] = []; let __cu = unconstrained; let __hit = record.function_queries[163].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[163].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[163].bump_multiplicity(__i); } let __ret: [G; OUT_163] = unsafe { *(record.function_queries[163].output_at(__i).as_ptr() as *const [G; OUT_163]) }; __ret }, _ => aiur_fn_163(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; @@ -34892,7 +34846,7 @@ fn aiur_fn_390( break '__mc_0 [__v_9]; }, _ => { - let __r_arr: [G; OUT_164] = { let __args: [G; IN_164] = []; let __cu = unconstrained; let __hit = record.function_queries[164].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[164].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[164].bump_multiplicity(__i); } let __ret: [G; OUT_164] = unsafe { *(record.function_queries[164].output_at(__i).as_ptr() as *const [G; OUT_164]) }; __ret }, _ => aiur_fn_164(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_163] = { let __args: [G; IN_163] = []; let __cu = unconstrained; let __hit = record.function_queries[163].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[163].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[163].bump_multiplicity(__i); } let __ret: [G; OUT_163] = unsafe { *(record.function_queries[163].output_at(__i).as_ptr() as *const [G; OUT_163]) }; __ret }, _ => aiur_fn_163(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; @@ -34902,7 +34856,7 @@ fn aiur_fn_390( break '__mc_0 [__v_11]; }, _ => { - let __r_arr: [G; OUT_168] = { let __args: [G; IN_168] = []; let __cu = unconstrained; let __hit = record.function_queries[168].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[168].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[168].bump_multiplicity(__i); } let __ret: [G; OUT_168] = unsafe { *(record.function_queries[168].output_at(__i).as_ptr() as *const [G; OUT_168]) }; __ret }, _ => aiur_fn_168(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; @@ -34912,7 +34866,7 @@ fn aiur_fn_390( break '__mc_0 [__v_13]; }, _ => { - let __r_arr: [G; OUT_167] = { let __args: [G; IN_167] = []; let __cu = unconstrained; let __hit = record.function_queries[167].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[167].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[167].bump_multiplicity(__i); } let __ret: [G; OUT_167] = unsafe { *(record.function_queries[167].output_at(__i).as_ptr() as *const [G; OUT_167]) }; __ret }, _ => aiur_fn_167(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_166] = { let __args: [G; IN_166] = []; let __cu = unconstrained; let __hit = record.function_queries[166].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[166].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[166].bump_multiplicity(__i); } let __ret: [G; OUT_166] = unsafe { *(record.function_queries[166].output_at(__i).as_ptr() as *const [G; OUT_166]) }; __ret }, _ => aiur_fn_166(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; @@ -34922,7 +34876,7 @@ fn aiur_fn_390( break '__mc_0 [__v_15]; }, _ => { - let __r_arr: [G; OUT_165] = { let __args: [G; IN_165] = []; let __cu = unconstrained; let __hit = record.function_queries[165].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[165].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[165].bump_multiplicity(__i); } let __ret: [G; OUT_165] = unsafe { *(record.function_queries[165].output_at(__i).as_ptr() as *const [G; OUT_165]) }; __ret }, _ => aiur_fn_165(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_164] = { let __args: [G; IN_164] = []; let __cu = unconstrained; let __hit = record.function_queries[164].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[164].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[164].bump_multiplicity(__i); } let __ret: [G; OUT_164] = unsafe { *(record.function_queries[164].output_at(__i).as_ptr() as *const [G; OUT_164]) }; __ret }, _ => aiur_fn_164(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; @@ -34932,7 +34886,7 @@ fn aiur_fn_390( break '__mc_0 [__v_17]; }, _ => { - let __r_arr: [G; OUT_166] = { let __args: [G; IN_166] = []; let __cu = unconstrained; let __hit = record.function_queries[166].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[166].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[166].bump_multiplicity(__i); } let __ret: [G; OUT_166] = unsafe { *(record.function_queries[166].output_at(__i).as_ptr() as *const [G; OUT_166]) }; __ret }, _ => aiur_fn_166(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_165] = { let __args: [G; IN_165] = []; let __cu = unconstrained; let __hit = record.function_queries[165].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[165].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[165].bump_multiplicity(__i); } let __ret: [G; OUT_165] = unsafe { *(record.function_queries[165].output_at(__i).as_ptr() as *const [G; OUT_165]) }; __ret }, _ => aiur_fn_165(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; @@ -34942,7 +34896,7 @@ fn aiur_fn_390( break '__mc_0 [__v_19]; }, _ => { - let __r_arr: [G; OUT_174] = { let __args: [G; IN_174] = []; let __cu = unconstrained; let __hit = record.function_queries[174].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[174].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[174].bump_multiplicity(__i); } let __ret: [G; OUT_174] = unsafe { *(record.function_queries[174].output_at(__i).as_ptr() as *const [G; OUT_174]) }; __ret }, _ => aiur_fn_174(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_173] = { let __args: [G; IN_173] = []; let __cu = unconstrained; let __hit = record.function_queries[173].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[173].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[173].bump_multiplicity(__i); } let __ret: [G; OUT_173] = unsafe { *(record.function_queries[173].output_at(__i).as_ptr() as *const [G; OUT_173]) }; __ret }, _ => aiur_fn_173(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; @@ -34952,7 +34906,7 @@ fn aiur_fn_390( break '__mc_0 [__v_21]; }, _ => { - let __r_arr: [G; OUT_175] = { let __args: [G; IN_175] = []; let __cu = unconstrained; let __hit = record.function_queries[175].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[175].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[175].bump_multiplicity(__i); } let __ret: [G; OUT_175] = unsafe { *(record.function_queries[175].output_at(__i).as_ptr() as *const [G; OUT_175]) }; __ret }, _ => aiur_fn_175(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_174] = { let __args: [G; IN_174] = []; let __cu = unconstrained; let __hit = record.function_queries[174].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[174].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[174].bump_multiplicity(__i); } let __ret: [G; OUT_174] = unsafe { *(record.function_queries[174].output_at(__i).as_ptr() as *const [G; OUT_174]) }; __ret }, _ => aiur_fn_174(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; @@ -34962,7 +34916,7 @@ fn aiur_fn_390( break '__mc_0 [__v_23]; }, _ => { - let __r_arr: [G; OUT_169] = { let __args: [G; IN_169] = []; let __cu = unconstrained; let __hit = record.function_queries[169].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[169].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[169].bump_multiplicity(__i); } let __ret: [G; OUT_169] = unsafe { *(record.function_queries[169].output_at(__i).as_ptr() as *const [G; OUT_169]) }; __ret }, _ => aiur_fn_169(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_168] = { let __args: [G; IN_168] = []; let __cu = unconstrained; let __hit = record.function_queries[168].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[168].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[168].bump_multiplicity(__i); } let __ret: [G; OUT_168] = unsafe { *(record.function_queries[168].output_at(__i).as_ptr() as *const [G; OUT_168]) }; __ret }, _ => aiur_fn_168(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; @@ -34972,7 +34926,7 @@ fn aiur_fn_390( break '__mc_0 [__v_25]; }, _ => { - let __r_arr: [G; OUT_170] = { let __args: [G; IN_170] = []; let __cu = unconstrained; let __hit = record.function_queries[170].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[170].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[170].bump_multiplicity(__i); } let __ret: [G; OUT_170] = unsafe { *(record.function_queries[170].output_at(__i).as_ptr() as *const [G; OUT_170]) }; __ret }, _ => aiur_fn_170(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_169] = { let __args: [G; IN_169] = []; let __cu = unconstrained; let __hit = record.function_queries[169].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[169].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[169].bump_multiplicity(__i); } let __ret: [G; OUT_169] = unsafe { *(record.function_queries[169].output_at(__i).as_ptr() as *const [G; OUT_169]) }; __ret }, _ => aiur_fn_169(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; @@ -34982,7 +34936,7 @@ fn aiur_fn_390( break '__mc_0 [__v_27]; }, _ => { - let __r_arr: [G; OUT_171] = { let __args: [G; IN_171] = []; let __cu = unconstrained; let __hit = record.function_queries[171].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[171].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[171].bump_multiplicity(__i); } let __ret: [G; OUT_171] = unsafe { *(record.function_queries[171].output_at(__i).as_ptr() as *const [G; OUT_171]) }; __ret }, _ => aiur_fn_171(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_170] = { let __args: [G; IN_170] = []; let __cu = unconstrained; let __hit = record.function_queries[170].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[170].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[170].bump_multiplicity(__i); } let __ret: [G; OUT_170] = unsafe { *(record.function_queries[170].output_at(__i).as_ptr() as *const [G; OUT_170]) }; __ret }, _ => aiur_fn_170(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; @@ -34992,7 +34946,7 @@ fn aiur_fn_390( break '__mc_0 [__v_29]; }, _ => { - let __r_arr: [G; OUT_172] = { let __args: [G; IN_172] = []; let __cu = unconstrained; let __hit = record.function_queries[172].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[172].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[172].bump_multiplicity(__i); } let __ret: [G; OUT_172] = unsafe { *(record.function_queries[172].output_at(__i).as_ptr() as *const [G; OUT_172]) }; __ret }, _ => aiur_fn_172(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_171] = { let __args: [G; IN_171] = []; let __cu = unconstrained; let __hit = record.function_queries[171].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[171].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[171].bump_multiplicity(__i); } let __ret: [G; OUT_171] = unsafe { *(record.function_queries[171].output_at(__i).as_ptr() as *const [G; OUT_171]) }; __ret }, _ => aiur_fn_171(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_29]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; @@ -35002,7 +34956,7 @@ fn aiur_fn_390( break '__mc_0 [__v_31]; }, _ => { - let __r_arr: [G; OUT_173] = { let __args: [G; IN_173] = []; let __cu = unconstrained; let __hit = record.function_queries[173].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[173].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[173].bump_multiplicity(__i); } let __ret: [G; OUT_173] = unsafe { *(record.function_queries[173].output_at(__i).as_ptr() as *const [G; OUT_173]) }; __ret }, _ => aiur_fn_173(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_172] = { let __args: [G; IN_172] = []; let __cu = unconstrained; let __hit = record.function_queries[172].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[172].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[172].bump_multiplicity(__i); } let __ret: [G; OUT_172] = unsafe { *(record.function_queries[172].output_at(__i).as_ptr() as *const [G; OUT_172]) }; __ret }, _ => aiur_fn_172(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; @@ -35051,64 +35005,64 @@ fn aiur_fn_390( match __v_3.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_390] = [__v_4]; - record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_389] = [__v_4]; + record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_219] = { let __args: [G; IN_219] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[219].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[219].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[219].bump_multiplicity(__i); } let __ret: [G; OUT_219] = unsafe { *(record.function_queries[219].output_at(__i).as_ptr() as *const [G; OUT_219]) }; __ret }, _ => aiur_fn_219(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_218] = { let __args: [G; IN_218] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[218].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[218].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[218].bump_multiplicity(__i); } let __ret: [G; OUT_218] = unsafe { *(record.function_queries[218].output_at(__i).as_ptr() as *const [G; OUT_218]) }; __ret }, _ => aiur_fn_218(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(2); - let __ret: [G; OUT_390] = [__v_5]; - record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_389] = [__v_5]; + record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_197] = { let __args: [G; IN_197] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[197].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[197].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[197].bump_multiplicity(__i); } let __ret: [G; OUT_197] = unsafe { *(record.function_queries[197].output_at(__i).as_ptr() as *const [G; OUT_197]) }; __ret }, _ => aiur_fn_197(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_196] = { let __args: [G; IN_196] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[196].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[196].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[196].bump_multiplicity(__i); } let __ret: [G; OUT_196] = unsafe { *(record.function_queries[196].output_at(__i).as_ptr() as *const [G; OUT_196]) }; __ret }, _ => aiur_fn_196(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(3); - let __ret: [G; OUT_390] = [__v_6]; - record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_389] = [__v_6]; + record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_184] = { let __args: [G; IN_184] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[184].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[184].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[184].bump_multiplicity(__i); } let __ret: [G; OUT_184] = unsafe { *(record.function_queries[184].output_at(__i).as_ptr() as *const [G; OUT_184]) }; __ret }, _ => aiur_fn_184(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_183] = { let __args: [G; IN_183] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[183].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[183].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[183].bump_multiplicity(__i); } let __ret: [G; OUT_183] = unsafe { *(record.function_queries[183].output_at(__i).as_ptr() as *const [G; OUT_183]) }; __ret }, _ => aiur_fn_183(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(4); - let __ret: [G; OUT_390] = [__v_7]; - record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_389] = [__v_7]; + record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_525] = { let __args: [G; IN_525] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[525].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[525].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[525].bump_multiplicity(__i); } let __ret: [G; OUT_525] = unsafe { *(record.function_queries[525].output_at(__i).as_ptr() as *const [G; OUT_525]) }; __ret }, _ => aiur_fn_525(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_524] = { let __args: [G; IN_524] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[524].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[524].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[524].bump_multiplicity(__i); } let __ret: [G; OUT_524] = unsafe { *(record.function_queries[524].output_at(__i).as_ptr() as *const [G; OUT_524]) }; __ret }, _ => aiur_fn_524(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(5); - let __ret: [G; OUT_390] = [__v_8]; - record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_389] = [__v_8]; + record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_241] = { let __args: [G; IN_241] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[241].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[241].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[241].bump_multiplicity(__i); } let __ret: [G; OUT_241] = unsafe { *(record.function_queries[241].output_at(__i).as_ptr() as *const [G; OUT_241]) }; __ret }, _ => aiur_fn_241(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(6); - let __ret: [G; OUT_390] = [__v_9]; - record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_389] = [__v_9]; + record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_390] = [__v_9]; - record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_389] = [__v_9]; + record.function_queries[389].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35125,71 +35079,71 @@ fn aiur_fn_390( }) } -const INPUT_SIZE_391: usize = 4; -const IN_391: usize = 4; -const OUT_391: usize = 2; -fn aiur_fn_391( - inp: [G; IN_391], +const INPUT_SIZE_390: usize = 4; +const IN_390: usize = 4; +const OUT_390: usize = 2; +fn aiur_fn_390( + inp: [G; IN_390], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_391], ExecError> { +) -> Result<[G; OUT_390], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_390] = { let __args: [G; IN_390] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[390].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[390].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[390].bump_multiplicity(__i); } let __ret: [G; OUT_390] = unsafe { *(record.function_queries[390].output_at(__i).as_ptr() as *const [G; OUT_390]) }; __ret }, _ => aiur_fn_390(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_389] = { let __args: [G; IN_389] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[389].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[389].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[389].bump_multiplicity(__i); } let __ret: [G; OUT_389] = unsafe { *(record.function_queries[389].output_at(__i).as_ptr() as *const [G; OUT_389]) }; __ret }, _ => aiur_fn_389(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_388] = { let __args: [G; IN_388] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[388].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[388].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[388].bump_multiplicity(__i); } let __ret: [G; OUT_388] = unsafe { *(record.function_queries[388].output_at(__i).as_ptr() as *const [G; OUT_388]) }; __ret }, _ => aiur_fn_388(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_391] = [__v_5, __v_6]; - record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_390] = [__v_5, __v_6]; + record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_387] = { let __args: [G; IN_387] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[387].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[387].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[387].bump_multiplicity(__i); } let __ret: [G; OUT_387] = unsafe { *(record.function_queries[387].output_at(__i).as_ptr() as *const [G; OUT_387]) }; __ret }, _ => aiur_fn_387(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_220] = { let __args: [G; IN_220] = [__v_0, __v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[220].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[220].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[220].bump_multiplicity(__i); } let __ret: [G; OUT_220] = unsafe { *(record.function_queries[220].output_at(__i).as_ptr() as *const [G; OUT_220]) }; __ret }, _ => aiur_fn_220(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_219] = { let __args: [G; IN_219] = [__v_0, __v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[219].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[219].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[219].bump_multiplicity(__i); } let __ret: [G; OUT_219] = unsafe { *(record.function_queries[219].output_at(__i).as_ptr() as *const [G; OUT_219]) }; __ret }, _ => aiur_fn_219(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; - let __ret: [G; OUT_391] = [__v_6, __v_7]; - record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_390] = [__v_6, __v_7]; + record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_203] = { let __args: [G; IN_203] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[203].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[203].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[203].bump_multiplicity(__i); } let __ret: [G; OUT_203] = unsafe { *(record.function_queries[203].output_at(__i).as_ptr() as *const [G; OUT_203]) }; __ret }, _ => aiur_fn_203(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_202] = { let __args: [G; IN_202] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[202].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[202].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[202].bump_multiplicity(__i); } let __ret: [G; OUT_202] = unsafe { *(record.function_queries[202].output_at(__i).as_ptr() as *const [G; OUT_202]) }; __ret }, _ => aiur_fn_202(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_391] = [__v_5, __v_6]; - record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_390] = [__v_5, __v_6]; + record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_187] = { let __args: [G; IN_187] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[187].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[187].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[187].bump_multiplicity(__i); } let __ret: [G; OUT_187] = unsafe { *(record.function_queries[187].output_at(__i).as_ptr() as *const [G; OUT_187]) }; __ret }, _ => aiur_fn_187(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_186] = { let __args: [G; IN_186] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[186].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[186].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[186].bump_multiplicity(__i); } let __ret: [G; OUT_186] = unsafe { *(record.function_queries[186].output_at(__i).as_ptr() as *const [G; OUT_186]) }; __ret }, _ => aiur_fn_186(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_391] = [__v_5, __v_6]; - record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_390] = [__v_5, __v_6]; + record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_531] = { let __args: [G; IN_531] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[531].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[531].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[531].bump_multiplicity(__i); } let __ret: [G; OUT_531] = unsafe { *(record.function_queries[531].output_at(__i).as_ptr() as *const [G; OUT_531]) }; __ret }, _ => aiur_fn_531(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_530] = { let __args: [G; IN_530] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[530].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[530].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[530].bump_multiplicity(__i); } let __ret: [G; OUT_530] = unsafe { *(record.function_queries[530].output_at(__i).as_ptr() as *const [G; OUT_530]) }; __ret }, _ => aiur_fn_530(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_391] = [__v_5, __v_6]; - record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_390] = [__v_5, __v_6]; + record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_253] = { let __args: [G; IN_253] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[253].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[253].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[253].bump_multiplicity(__i); } let __ret: [G; OUT_253] = unsafe { *(record.function_queries[253].output_at(__i).as_ptr() as *const [G; OUT_253]) }; __ret }, _ => aiur_fn_253(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_252] = { let __args: [G; IN_252] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[252].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[252].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[252].bump_multiplicity(__i); } let __ret: [G; OUT_252] = unsafe { *(record.function_queries[252].output_at(__i).as_ptr() as *const [G; OUT_252]) }; __ret }, _ => aiur_fn_252(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_391] = [__v_5, __v_6]; - record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_390] = [__v_5, __v_6]; + record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -35198,52 +35152,52 @@ fn aiur_fn_391( let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_391] = [__v_5, __v_9]; - record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_390] = [__v_5, __v_9]; + record.function_queries[390].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_392: usize = 3; -const IN_392: usize = 3; -const OUT_392: usize = 2; -fn aiur_fn_392( - inp: [G; IN_392], +const INPUT_SIZE_391: usize = 3; +const IN_391: usize = 3; +const OUT_391: usize = 2; +fn aiur_fn_391( + inp: [G; IN_391], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_392], ExecError> { +) -> Result<[G; OUT_391], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_383] = { let __args: [G; IN_383] = []; let __cu = unconstrained; let __hit = record.function_queries[383].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[383].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[383].bump_multiplicity(__i); } let __ret: [G; OUT_383] = unsafe { *(record.function_queries[383].output_at(__i).as_ptr() as *const [G; OUT_383]) }; __ret }, _ => aiur_fn_383(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_382] = { let __args: [G; IN_382] = []; let __cu = unconstrained; let __hit = record.function_queries[382].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[382].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[382].bump_multiplicity(__i); } let __ret: [G; OUT_382] = unsafe { *(record.function_queries[382].output_at(__i).as_ptr() as *const [G; OUT_382]) }; __ret }, _ => aiur_fn_382(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_393] = { let __args: [G; IN_393] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[393].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[393].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[393].bump_multiplicity(__i); } let __ret: [G; OUT_393] = unsafe { *(record.function_queries[393].output_at(__i).as_ptr() as *const [G; OUT_393]) }; __ret }, _ => aiur_fn_393(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_392] = { let __args: [G; IN_392] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[392].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[392].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[392].bump_multiplicity(__i); } let __ret: [G; OUT_392] = unsafe { *(record.function_queries[392].output_at(__i).as_ptr() as *const [G; OUT_392]) }; __ret }, _ => aiur_fn_392(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __ret: [G; OUT_392] = [__v_5, __v_6]; - record.function_queries[392].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_391] = [__v_5, __v_6]; + record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_384] = { let __args: [G; IN_384] = []; let __cu = unconstrained; let __hit = record.function_queries[384].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[384].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[384].bump_multiplicity(__i); } let __ret: [G; OUT_384] = unsafe { *(record.function_queries[384].output_at(__i).as_ptr() as *const [G; OUT_384]) }; __ret }, _ => aiur_fn_384(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_383] = { let __args: [G; IN_383] = []; let __cu = unconstrained; let __hit = record.function_queries[383].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[383].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[383].bump_multiplicity(__i); } let __ret: [G; OUT_383] = unsafe { *(record.function_queries[383].output_at(__i).as_ptr() as *const [G; OUT_383]) }; __ret }, _ => aiur_fn_383(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_394] = { let __args: [G; IN_394] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[394].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[394].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[394].bump_multiplicity(__i); } let __ret: [G; OUT_394] = unsafe { *(record.function_queries[394].output_at(__i).as_ptr() as *const [G; OUT_394]) }; __ret }, _ => aiur_fn_394(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_393] = { let __args: [G; IN_393] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[393].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[393].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[393].bump_multiplicity(__i); } let __ret: [G; OUT_393] = unsafe { *(record.function_queries[393].output_at(__i).as_ptr() as *const [G; OUT_393]) }; __ret }, _ => aiur_fn_393(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __ret: [G; OUT_392] = [__v_7, __v_8]; - record.function_queries[392].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_391] = [__v_7, __v_8]; + record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -35252,8 +35206,8 @@ fn aiur_fn_392( let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_8, __v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_392] = [__v_7, __v_11]; - record.function_queries[392].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_391] = [__v_7, __v_11]; + record.function_queries[391].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35262,19 +35216,19 @@ fn aiur_fn_392( }) } -const INPUT_SIZE_393: usize = 2; -const IN_393: usize = 2; -const OUT_393: usize = 2; -fn aiur_fn_393( - inp: [G; IN_393], +const INPUT_SIZE_392: usize = 2; +const IN_392: usize = 2; +const OUT_392: usize = 2; +fn aiur_fn_392( + inp: [G; IN_392], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_393], ExecError> { +) -> Result<[G; OUT_392], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(6); let __v_4: G = { let __a_val = __v_2.as_canonical_u64(); let __b_val = __v_3.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -35285,33 +35239,33 @@ fn aiur_fn_393( let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_393] = [__v_5, __v_9]; - record.function_queries[393].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_392] = [__v_5, __v_9]; + record.function_queries[392].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_5: G = G::from_u64(3); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(5); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_395] = { let __args: [G; IN_395] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[395].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[395].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[395].bump_multiplicity(__i); } let __ret: [G; OUT_395] = unsafe { *(record.function_queries[395].output_at(__i).as_ptr() as *const [G; OUT_395]) }; __ret }, _ => aiur_fn_395(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_394] = { let __args: [G; IN_394] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[394].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[394].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[394].bump_multiplicity(__i); } let __ret: [G; OUT_394] = unsafe { *(record.function_queries[394].output_at(__i).as_ptr() as *const [G; OUT_394]) }; __ret }, _ => aiur_fn_394(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_9.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(6); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(3); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_14, __v_6, __v_10, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_16, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_16, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_393] = [__v_13, __v_17]; - record.function_queries[393].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_392] = [__v_13, __v_17]; + record.function_queries[392].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -35320,8 +35274,8 @@ fn aiur_fn_393( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_393] = [__v_11, __v_15]; - record.function_queries[393].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_392] = [__v_11, __v_15]; + record.function_queries[392].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35330,19 +35284,19 @@ fn aiur_fn_393( }) } -const INPUT_SIZE_394: usize = 2; -const IN_394: usize = 2; -const OUT_394: usize = 2; -fn aiur_fn_394( - inp: [G; IN_394], +const INPUT_SIZE_393: usize = 2; +const IN_393: usize = 2; +const OUT_393: usize = 2; +fn aiur_fn_393( + inp: [G; IN_393], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_394], ExecError> { +) -> Result<[G; OUT_393], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(5); let __v_4: G = { let __a_val = __v_2.as_canonical_u64(); let __b_val = __v_3.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -35353,33 +35307,33 @@ fn aiur_fn_394( let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_394] = [__v_5, __v_9]; - record.function_queries[394].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_393] = [__v_5, __v_9]; + record.function_queries[393].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_5: G = G::from_u64(3); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(4); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_395] = { let __args: [G; IN_395] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[395].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[395].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[395].bump_multiplicity(__i); } let __ret: [G; OUT_395] = unsafe { *(record.function_queries[395].output_at(__i).as_ptr() as *const [G; OUT_395]) }; __ret }, _ => aiur_fn_395(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_394] = { let __args: [G; IN_394] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[394].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[394].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[394].bump_multiplicity(__i); } let __ret: [G; OUT_394] = unsafe { *(record.function_queries[394].output_at(__i).as_ptr() as *const [G; OUT_394]) }; __ret }, _ => aiur_fn_394(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_9.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(5); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(3); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_14, __v_6, __v_10, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_16, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_16, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_394] = [__v_13, __v_17]; - record.function_queries[394].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_393] = [__v_13, __v_17]; + record.function_queries[393].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -35388,8 +35342,8 @@ fn aiur_fn_394( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_394] = [__v_11, __v_15]; - record.function_queries[394].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_393] = [__v_11, __v_15]; + record.function_queries[393].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35398,19 +35352,19 @@ fn aiur_fn_394( }) } -const INPUT_SIZE_395: usize = 2; -const IN_395: usize = 2; -const OUT_395: usize = 2; -fn aiur_fn_395( - inp: [G; IN_395], +const INPUT_SIZE_394: usize = 2; +const IN_394: usize = 2; +const OUT_394: usize = 2; +fn aiur_fn_394( + inp: [G; IN_394], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_395], ExecError> { +) -> Result<[G; OUT_394], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; @@ -35422,13 +35376,13 @@ fn aiur_fn_395( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_382] = { let __args: [G; IN_382] = []; let __cu = unconstrained; let __hit = record.function_queries[382].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[382].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[382].bump_multiplicity(__i); } let __ret: [G; OUT_382] = unsafe { *(record.function_queries[382].output_at(__i).as_ptr() as *const [G; OUT_382]) }; __ret }, _ => aiur_fn_382(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_381] = { let __args: [G; IN_381] = []; let __cu = unconstrained; let __hit = record.function_queries[381].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[381].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[381].bump_multiplicity(__i); } let __ret: [G; OUT_381] = unsafe { *(record.function_queries[381].output_at(__i).as_ptr() as *const [G; OUT_381]) }; __ret }, _ => aiur_fn_381(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(3); let __v_13: G = (__v_11 - __v_12); @@ -35436,10 +35390,10 @@ fn aiur_fn_395( 0u64 => { let __v_14: G = G::from_u64(1); let __v_15: G = G::from_u64(2); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_395] = [__v_14, __v_16]; - record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_394] = [__v_14, __v_16]; + record.function_queries[394].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -35448,8 +35402,8 @@ fn aiur_fn_395( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_395] = [__v_14, __v_18]; - record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_394] = [__v_14, __v_18]; + record.function_queries[394].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35460,8 +35414,8 @@ fn aiur_fn_395( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_395] = [__v_11, __v_15]; - record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_394] = [__v_11, __v_15]; + record.function_queries[394].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35472,47 +35426,47 @@ fn aiur_fn_395( let __v_11: G = G::from_u64(0); let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_10, __v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_395] = [__v_9, __v_13]; - record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_394] = [__v_9, __v_13]; + record.function_queries[394].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_396: usize = 5; -const IN_396: usize = 5; -const OUT_396: usize = 1; -fn aiur_fn_396( - inp: [G; IN_396], +const INPUT_SIZE_395: usize = 5; +const IN_395: usize = 5; +const OUT_395: usize = 1; +fn aiur_fn_395( + inp: [G; IN_395], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_396], ExecError> { +) -> Result<[G; OUT_395], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_391] = { let __args: [G; IN_391] = [__v_0, __v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[391].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[391].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[391].bump_multiplicity(__i); } let __ret: [G; OUT_391] = unsafe { *(record.function_queries[391].output_at(__i).as_ptr() as *const [G; OUT_391]) }; __ret }, _ => aiur_fn_391(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_390] = { let __args: [G; IN_390] = [__v_0, __v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[390].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[390].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[390].bump_multiplicity(__i); } let __ret: [G; OUT_390] = unsafe { *(record.function_queries[390].output_at(__i).as_ptr() as *const [G; OUT_390]) }; __ret }, _ => aiur_fn_390(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_7]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_7]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __ret: [G; OUT_396] = [__v_6]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_6]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -35529,52 +35483,52 @@ fn aiur_fn_396( let __v_19: G = __loaded[11]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_397] = { let __args: [G; IN_397] = [__v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[397].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[397].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[397].bump_multiplicity(__i); } let __ret: [G; OUT_397] = unsafe { *(record.function_queries[397].output_at(__i).as_ptr() as *const [G; OUT_397]) }; __ret }, _ => aiur_fn_397(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_396] = { let __args: [G; IN_396] = [__v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[396].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[396].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[396].bump_multiplicity(__i); } let __ret: [G; OUT_396] = unsafe { *(record.function_queries[396].output_at(__i).as_ptr() as *const [G; OUT_396]) }; __ret }, _ => aiur_fn_396(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = __r_arr[1]; match __v_20.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_22]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_22]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_11, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_11, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_22, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_22, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_23]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_23]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 2u64 => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_20]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_20]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_392] = { let __args: [G; IN_392] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[392].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[392].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[392].bump_multiplicity(__i); } let __ret: [G; OUT_392] = unsafe { *(record.function_queries[392].output_at(__i).as_ptr() as *const [G; OUT_392]) }; __ret }, _ => aiur_fn_392(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_391] = { let __args: [G; IN_391] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[391].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[391].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[391].bump_multiplicity(__i); } let __ret: [G; OUT_391] = unsafe { *(record.function_queries[391].output_at(__i).as_ptr() as *const [G; OUT_391]) }; __ret }, _ => aiur_fn_391(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = __r_arr[1]; match __v_20.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_22]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_22]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_22]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_22]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35585,10 +35539,10 @@ fn aiur_fn_396( let __v_22: G = (__v_21 + __v_12); let __mc_out___mc_0: [G; 2] = '__mc_0: { match __v_16.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_408] = { let __args: [G; IN_408] = [__v_10, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[408].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[408].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[408].bump_multiplicity(__i); } let __ret: [G; OUT_408] = unsafe { *(record.function_queries[408].output_at(__i).as_ptr() as *const [G; OUT_408]) }; __ret }, _ => aiur_fn_408(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_407] = { let __args: [G; IN_407] = [__v_10, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[407].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[407].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[407].bump_multiplicity(__i); } let __ret: [G; OUT_407] = unsafe { *(record.function_queries[407].output_at(__i).as_ptr() as *const [G; OUT_407]) }; __ret }, _ => aiur_fn_407(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __v_24: G = __r_arr[1]; - let __r_arr: [G; OUT_400] = { let __args: [G; IN_400] = [__v_1, __v_3, __v_11, __v_13, __v_14, __v_12, __v_15, __v_24, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[400].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[400].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[400].bump_multiplicity(__i); } let __ret: [G; OUT_400] = unsafe { *(record.function_queries[400].output_at(__i).as_ptr() as *const [G; OUT_400]) }; __ret }, _ => aiur_fn_400(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_399] = { let __args: [G; IN_399] = [__v_1, __v_3, __v_11, __v_13, __v_14, __v_12, __v_15, __v_24, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[399].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[399].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[399].bump_multiplicity(__i); } let __ret: [G; OUT_399] = unsafe { *(record.function_queries[399].output_at(__i).as_ptr() as *const [G; OUT_399]) }; __ret }, _ => aiur_fn_399(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = __r_arr[1]; break '__mc_0 [__v_25, __v_26]; @@ -35603,46 +35557,46 @@ fn aiur_fn_396( let __v_24: G = __mc_out___mc_0[1]; match __v_23.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_396] = [__v_24]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_24]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_10, __v_11, __v_13, __v_14, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_10, __v_11, __v_13, __v_14, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_404] = { let __args: [G; IN_404] = [__v_1, __v_3, __v_11, __v_13, __v_14, __v_12, __v_15, __v_4, __v_2, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[404].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[404].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[404].bump_multiplicity(__i); } let __ret: [G; OUT_404] = unsafe { *(record.function_queries[404].output_at(__i).as_ptr() as *const [G; OUT_404]) }; __ret }, _ => aiur_fn_404(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_403] = { let __args: [G; IN_403] = [__v_1, __v_3, __v_11, __v_13, __v_14, __v_12, __v_15, __v_4, __v_2, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[403].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[403].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[403].bump_multiplicity(__i); } let __ret: [G; OUT_403] = unsafe { *(record.function_queries[403].output_at(__i).as_ptr() as *const [G; OUT_403]) }; __ret }, _ => aiur_fn_403(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = __r_arr[1]; match __v_26.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_27, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_27, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_28]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_28]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { match __v_16.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_396] = [__v_27]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_27]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_407] = { let __args: [G; IN_407] = [__v_10, __v_1, __v_3, __v_11, __v_13, __v_14, __v_12, __v_15, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[407].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[407].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[407].bump_multiplicity(__i); } let __ret: [G; OUT_407] = unsafe { *(record.function_queries[407].output_at(__i).as_ptr() as *const [G; OUT_407]) }; __ret }, _ => aiur_fn_407(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_406] = { let __args: [G; IN_406] = [__v_10, __v_1, __v_3, __v_11, __v_13, __v_14, __v_12, __v_15, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[406].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[406].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[406].bump_multiplicity(__i); } let __ret: [G; OUT_406] = unsafe { *(record.function_queries[406].output_at(__i).as_ptr() as *const [G; OUT_406]) }; __ret }, _ => aiur_fn_406(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; match __v_28.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_29, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_29, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_30]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_30]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_396] = [__v_27]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_27]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35650,10 +35604,10 @@ fn aiur_fn_396( } }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_28]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_28]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35661,10 +35615,10 @@ fn aiur_fn_396( } }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_396] = [__v_20]; - record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_395] = [__v_20]; + record.function_queries[395].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35673,20 +35627,20 @@ fn aiur_fn_396( }) } -const INPUT_SIZE_397: usize = 2; -const IN_397: usize = 2; -const OUT_397: usize = 2; -fn aiur_fn_397( - inp: [G; IN_397], +const INPUT_SIZE_396: usize = 2; +const IN_396: usize = 2; +const OUT_396: usize = 2; +fn aiur_fn_396( + inp: [G; IN_396], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_397], ExecError> { +) -> Result<[G; OUT_396], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = G::from_u64(0); - let __r_arr: [G; OUT_398] = { let __args: [G; IN_398] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[398].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[398].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[398].bump_multiplicity(__i); } let __ret: [G; OUT_398] = unsafe { *(record.function_queries[398].output_at(__i).as_ptr() as *const [G; OUT_398]) }; __ret }, _ => aiur_fn_398(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_397] = { let __args: [G; IN_397] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[397].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[397].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[397].bump_multiplicity(__i); } let __ret: [G; OUT_397] = unsafe { *(record.function_queries[397].output_at(__i).as_ptr() as *const [G; OUT_397]) }; __ret }, _ => aiur_fn_397(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = __r_arr[2]; @@ -35694,7 +35648,7 @@ fn aiur_fn_397( let __v_7: G = __r_arr[4]; match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = { let __a_val = __v_8.as_canonical_u64(); let __b_val = __v_4.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_9.as_canonical_u64() { @@ -35704,22 +35658,22 @@ fn aiur_fn_397( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_397] = [__v_10, __v_14]; - record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_396] = [__v_10, __v_14]; + record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(8); let __v_12: G = { let __values: [G; 4] = [__v_11, __v_5, __v_6, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_397] = [__v_14, __v_15]; - record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_396] = [__v_14, __v_15]; + record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35730,23 +35684,23 @@ fn aiur_fn_397( let __v_10: G = G::from_u64(0); let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_9, __v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_397] = [__v_8, __v_12]; - record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_396] = [__v_8, __v_12]; + record.function_queries[396].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_398: usize = 2; -const IN_398: usize = 2; -const OUT_398: usize = 5; -fn aiur_fn_398( - inp: [G; IN_398], +const INPUT_SIZE_397: usize = 2; +const IN_397: usize = 2; +const OUT_397: usize = 5; +fn aiur_fn_397( + inp: [G; IN_397], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_398], ExecError> { +) -> Result<[G; OUT_397], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -35759,14 +35713,14 @@ fn aiur_fn_398( 4u64 => { let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 + __v_6); - let __r_arr: [G; OUT_398] = { let __args: [G; IN_398] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[398].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[398].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[398].bump_multiplicity(__i); } let __ret: [G; OUT_398] = unsafe { *(record.function_queries[398].output_at(__i).as_ptr() as *const [G; OUT_398]) }; __ret }, _ => aiur_fn_398(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_397] = { let __args: [G; IN_397] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[397].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[397].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[397].bump_multiplicity(__i); } let __ret: [G; OUT_397] = unsafe { *(record.function_queries[397].output_at(__i).as_ptr() as *const [G; OUT_397]) }; __ret }, _ => aiur_fn_397(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = __r_arr[2]; let __v_11: G = __r_arr[3]; let __v_12: G = __r_arr[4]; - let __ret: [G; OUT_398] = [__v_8, __v_9, __v_10, __v_11, __v_12]; - record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_397] = [__v_8, __v_9, __v_10, __v_11, __v_12]; + record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { @@ -35784,8 +35738,8 @@ fn aiur_fn_398( let __v_12: G = G::from_u64(1); let __v_13: G = (__v_1 - __v_12); let __v_14: G = (__v_13 - __v_7); - let __ret: [G; OUT_398] = [__v_11, __v_1, __v_3, __v_4, __v_14]; - record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_397] = [__v_11, __v_1, __v_3, __v_4, __v_14]; + record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -35826,8 +35780,8 @@ fn aiur_fn_398( let __v_45: G = { let __values: [G; 32] = [__v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_46: G = G::from_u64(0); let __v_47: G = G::from_u64(0); - let __ret: [G; OUT_398] = [__v_11, __v_12, __v_45, __v_46, __v_47]; - record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_397] = [__v_11, __v_12, __v_45, __v_46, __v_47]; + record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35870,8 +35824,8 @@ fn aiur_fn_398( let __v_44: G = { let __values: [G; 32] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_45: G = G::from_u64(0); let __v_46: G = G::from_u64(0); - let __ret: [G; OUT_398] = [__v_10, __v_11, __v_44, __v_45, __v_46]; - record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_397] = [__v_10, __v_11, __v_44, __v_45, __v_46]; + record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -35914,23 +35868,23 @@ fn aiur_fn_398( let __v_40: G = { let __values: [G; 32] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = G::from_u64(0); let __v_42: G = G::from_u64(0); - let __ret: [G; OUT_398] = [__v_6, __v_7, __v_40, __v_41, __v_42]; - record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_397] = [__v_6, __v_7, __v_40, __v_41, __v_42]; + record.function_queries[397].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_399: usize = 1; -const IN_399: usize = 1; -const OUT_399: usize = 1; -fn aiur_fn_399( - inp: [G; IN_399], +const INPUT_SIZE_398: usize = 1; +const IN_398: usize = 1; +const OUT_398: usize = 1; +fn aiur_fn_398( + inp: [G; IN_398], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_399], ExecError> { +) -> Result<[G; OUT_398], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -35942,20 +35896,20 @@ fn aiur_fn_399( 7u64 => { match __v_2.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(2); - let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_146] = { let __args: [G; IN_146] = []; let __cu = unconstrained; let __hit = record.function_queries[146].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[146].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[146].bump_multiplicity(__i); } let __ret: [G; OUT_146] = unsafe { *(record.function_queries[146].output_at(__i).as_ptr() as *const [G; OUT_146]) }; __ret }, _ => aiur_fn_146(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_6, __v_7, __v_10, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_399] = [__v_12]; - record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_398] = [__v_12]; + record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -35968,7 +35922,7 @@ fn aiur_fn_399( let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_8, __v_9, __v_7, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_12: G = G::from_u64(2); - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(1); let __v_15: G = G::from_u64(1); @@ -35978,37 +35932,37 @@ fn aiur_fn_399( let __v_19: G = G::from_u64(3); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_19, __v_18, __v_11, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_399] = [__v_21]; - record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_398] = [__v_21]; + record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_399] = [__v_0]; - record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_398] = [__v_0]; + record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_399] = [__v_0]; - record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_398] = [__v_0]; + record.function_queries[398].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_400: usize = 9; -const IN_400: usize = 9; -const OUT_400: usize = 2; -fn aiur_fn_400( - inp: [G; IN_400], +const INPUT_SIZE_399: usize = 9; +const IN_399: usize = 9; +const OUT_399: usize = 2; +fn aiur_fn_399( + inp: [G; IN_399], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_400], ExecError> { +) -> Result<[G; OUT_399], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -36032,7 +35986,7 @@ fn aiur_fn_400( let __v_14: G = (__v_4 + __v_5); let __v_15: G = (__v_3 + __v_14); let __v_16: G = (__v_2 + __v_15); - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_16, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; @@ -36043,14 +35997,14 @@ fn aiur_fn_400( let __v_21: G = G::from_u64(0); let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 4] = [__v_20, __v_21, __v_22, __v_22]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_400] = [__v_19, __v_23]; - record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_399] = [__v_19, __v_23]; + record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_401] = { let __args: [G; IN_401] = [__v_19, __v_10, __v_2, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[401].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[401].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[401].bump_multiplicity(__i); } let __ret: [G; OUT_401] = unsafe { *(record.function_queries[401].output_at(__i).as_ptr() as *const [G; OUT_401]) }; __ret }, _ => aiur_fn_401(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_400] = { let __args: [G; IN_400] = [__v_19, __v_10, __v_2, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[400].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[400].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[400].bump_multiplicity(__i); } let __ret: [G; OUT_400] = unsafe { *(record.function_queries[400].output_at(__i).as_ptr() as *const [G; OUT_400]) }; __ret }, _ => aiur_fn_400(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; match __v_20.as_canonical_u64() { 0u64 => { @@ -36059,30 +36013,30 @@ fn aiur_fn_400( let __v_23: G = G::from_u64(0); let __v_24: G = G::from_u64(0); let __v_25: G = { let __values: [G; 4] = [__v_22, __v_23, __v_24, __v_24]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_400] = [__v_21, __v_25]; - record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_399] = [__v_21, __v_25]; + record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_12, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_12, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = (__v_3 + __v_4); let __v_23: G = (__v_2 + __v_22); - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_1, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = G::from_u64(1); let __v_26: G = (__v_16 + __v_25); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_21, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_21, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_28, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_28, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = G::from_u64(1); - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_29, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_29, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __ret: [G; OUT_400] = [__v_30, __v_31]; - record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_399] = [__v_30, __v_31]; + record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36097,32 +36051,32 @@ fn aiur_fn_400( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_400] = [__v_14, __v_18]; - record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_399] = [__v_14, __v_18]; + record.function_queries[399].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_401: usize = 5; -const IN_401: usize = 5; -const OUT_401: usize = 1; -fn aiur_fn_401( - inp: [G; IN_401], +const INPUT_SIZE_400: usize = 5; +const IN_400: usize = 5; +const OUT_400: usize = 1; +fn aiur_fn_400( + inp: [G; IN_400], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_401], ExecError> { +) -> Result<[G; OUT_400], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; @@ -36139,12 +36093,12 @@ fn aiur_fn_401( match __v_13.as_canonical_u64() { 0u64 => { let __v_14: G = G::from_u64(0); - let __ret: [G; OUT_401] = [__v_14]; - record.function_queries[401].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_400] = [__v_14]; + record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_14.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_15: G = __loaded[0]; @@ -36161,27 +36115,27 @@ fn aiur_fn_401( let __v_26: G = __loaded[11]; match __v_15.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_565] = { let __args: [G; IN_565] = [__v_22, __v_23, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[565].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[565].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[565].bump_multiplicity(__i); } let __ret: [G; OUT_565] = unsafe { *(record.function_queries[565].output_at(__i).as_ptr() as *const [G; OUT_565]) }; __ret }, _ => aiur_fn_565(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_564] = { let __args: [G; IN_564] = [__v_22, __v_23, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[564].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[564].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[564].bump_multiplicity(__i); } let __ret: [G; OUT_564] = unsafe { *(record.function_queries[564].output_at(__i).as_ptr() as *const [G; OUT_564]) }; __ret }, _ => aiur_fn_564(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = G::from_u64(2); let __v_29: G = G::from_u64(0); let __v_30: G = { let __values: [G; 4] = [__v_28, __v_27, __v_11, __v_29]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_32, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_32, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_6, __v_33, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_6, __v_33, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __ret: [G; OUT_401] = [__v_34]; - record.function_queries[401].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_400] = [__v_34]; + record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_27: G = G::from_u64(0); - let __ret: [G; OUT_401] = [__v_27]; - record.function_queries[401].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_400] = [__v_27]; + record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36190,61 +36144,61 @@ fn aiur_fn_401( }, _ => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_401] = [__v_13]; - record.function_queries[401].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_400] = [__v_13]; + record.function_queries[400].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_402: usize = 3; -const IN_402: usize = 3; -const OUT_402: usize = 1; -fn aiur_fn_402( - inp: [G; IN_402], +const INPUT_SIZE_401: usize = 3; +const IN_401: usize = 3; +const OUT_401: usize = 1; +fn aiur_fn_401( + inp: [G; IN_401], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_402], ExecError> { +) -> Result<[G; OUT_401], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = G::from_u64(1); let __v_5: G = (__v_1 + __v_4); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = { let __values: [G; 3] = [__v_7, __v_2, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_12, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_12, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_402] = [__v_13]; - record.function_queries[402].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_401] = [__v_13]; + record.function_queries[401].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_403: usize = 2; -const IN_403: usize = 2; -const OUT_403: usize = 1; -fn aiur_fn_403( - inp: [G; IN_403], +const INPUT_SIZE_402: usize = 2; +const IN_402: usize = 2; +const OUT_402: usize = 1; +fn aiur_fn_402( + inp: [G; IN_402], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_403], ExecError> { +) -> Result<[G; OUT_402], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; @@ -36256,7 +36210,7 @@ fn aiur_fn_403( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_9.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -36273,41 +36227,41 @@ fn aiur_fn_403( let __v_21: G = __loaded[11]; match __v_10.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_13, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_13, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_22, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_22, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_403] = { let __args: [G; IN_403] = [__v_23, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[403].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[403].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[403].bump_multiplicity(__i); } let __ret: [G; OUT_403] = unsafe { *(record.function_queries[403].output_at(__i).as_ptr() as *const [G; OUT_403]) }; __ret }, _ => aiur_fn_403(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_402] = { let __args: [G; IN_402] = [__v_23, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[402].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[402].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[402].bump_multiplicity(__i); } let __ret: [G; OUT_402] = unsafe { *(record.function_queries[402].output_at(__i).as_ptr() as *const [G; OUT_402]) }; __ret }, _ => aiur_fn_402(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __ret: [G; OUT_403] = [__v_24]; - record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_402] = [__v_24]; + record.function_queries[402].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_403] = [__v_2]; - record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_402] = [__v_2]; + record.function_queries[402].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_403] = [__v_2]; - record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_402] = [__v_2]; + record.function_queries[402].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_404: usize = 10; -const IN_404: usize = 10; -const OUT_404: usize = 2; -fn aiur_fn_404( - inp: [G; IN_404], +const INPUT_SIZE_403: usize = 10; +const IN_403: usize = 10; +const OUT_403: usize = 2; +fn aiur_fn_403( + inp: [G; IN_403], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_404], ExecError> { +) -> Result<[G; OUT_403], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -36322,7 +36276,7 @@ fn aiur_fn_404( let __v_10: G = (__v_4 + __v_5); let __v_11: G = (__v_3 + __v_10); let __v_12: G = (__v_2 + __v_11); - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = { let __a_val = __v_12.as_canonical_u64(); let __b_val = __v_13.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_14.as_canonical_u64() { @@ -36332,33 +36286,33 @@ fn aiur_fn_404( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 4] = [__v_16, __v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_404] = [__v_15, __v_19]; - record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_403] = [__v_15, __v_19]; + record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_262] = { let __args: [G; IN_262] = [__v_1, __v_2, __v_3, __v_4, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[262].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[262].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[262].bump_multiplicity(__i); } let __ret: [G; OUT_262] = unsafe { *(record.function_queries[262].output_at(__i).as_ptr() as *const [G; OUT_262]) }; __ret }, _ => aiur_fn_262(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_261] = { let __args: [G; IN_261] = [__v_1, __v_2, __v_3, __v_4, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[261].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[261].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[261].bump_multiplicity(__i); } let __ret: [G; OUT_261] = unsafe { *(record.function_queries[261].output_at(__i).as_ptr() as *const [G; OUT_261]) }; __ret }, _ => aiur_fn_261(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; match __v_15.as_canonical_u64() { 1u64 => { let __v_17: G = G::from_u64(1); - let __ret: [G; OUT_404] = [__v_17, __v_16]; - record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_403] = [__v_17, __v_16]; + record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_259] = { let __args: [G; IN_259] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[259].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[259].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[259].bump_multiplicity(__i); } let __ret: [G; OUT_259] = unsafe { *(record.function_queries[259].output_at(__i).as_ptr() as *const [G; OUT_259]) }; __ret }, _ => aiur_fn_259(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_258] = { let __args: [G; IN_258] = [__v_17]; let __cu = unconstrained; let __hit = record.function_queries[258].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[258].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[258].bump_multiplicity(__i); } let __ret: [G; OUT_258] = unsafe { *(record.function_queries[258].output_at(__i).as_ptr() as *const [G; OUT_258]) }; __ret }, _ => aiur_fn_258(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_403] = { let __args: [G; IN_403] = [__v_18, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[403].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[403].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[403].bump_multiplicity(__i); } let __ret: [G; OUT_403] = unsafe { *(record.function_queries[403].output_at(__i).as_ptr() as *const [G; OUT_403]) }; __ret }, _ => aiur_fn_403(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_402] = { let __args: [G; IN_402] = [__v_18, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[402].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[402].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[402].bump_multiplicity(__i); } let __ret: [G; OUT_402] = unsafe { *(record.function_queries[402].output_at(__i).as_ptr() as *const [G; OUT_402]) }; __ret }, _ => aiur_fn_402(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_259] = { let __args: [G; IN_259] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[259].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[259].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[259].bump_multiplicity(__i); } let __ret: [G; OUT_259] = unsafe { *(record.function_queries[259].output_at(__i).as_ptr() as *const [G; OUT_259]) }; __ret }, _ => aiur_fn_259(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_258] = { let __args: [G; IN_258] = [__v_19]; let __cu = unconstrained; let __hit = record.function_queries[258].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[258].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[258].bump_multiplicity(__i); } let __ret: [G; OUT_258] = unsafe { *(record.function_queries[258].output_at(__i).as_ptr() as *const [G; OUT_258]) }; __ret }, _ => aiur_fn_258(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_399] = { let __args: [G; IN_399] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[399].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[399].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[399].bump_multiplicity(__i); } let __ret: [G; OUT_399] = unsafe { *(record.function_queries[399].output_at(__i).as_ptr() as *const [G; OUT_399]) }; __ret }, _ => aiur_fn_399(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_398] = { let __args: [G; IN_398] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[398].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[398].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[398].bump_multiplicity(__i); } let __ret: [G; OUT_398] = unsafe { *(record.function_queries[398].output_at(__i).as_ptr() as *const [G; OUT_398]) }; __ret }, _ => aiur_fn_398(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_405] = { let __args: [G; IN_405] = [__v_21]; let __cu = unconstrained; let __hit = record.function_queries[405].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[405].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[405].bump_multiplicity(__i); } let __ret: [G; OUT_405] = unsafe { *(record.function_queries[405].output_at(__i).as_ptr() as *const [G; OUT_405]) }; __ret }, _ => aiur_fn_405(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_404] = { let __args: [G; IN_404] = [__v_21]; let __cu = unconstrained; let __hit = record.function_queries[404].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[404].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[404].bump_multiplicity(__i); } let __ret: [G; OUT_404] = unsafe { *(record.function_queries[404].output_at(__i).as_ptr() as *const [G; OUT_404]) }; __ret }, _ => aiur_fn_404(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = __r_arr[1]; let __v_24: G = __r_arr[2]; @@ -36371,46 +36325,46 @@ fn aiur_fn_404( if (__v_26 != __v_27) { return Err(ExecError::AssertEqMismatch { lhs: __v_26.as_canonical_u64(), rhs: __v_27.as_canonical_u64(), msg: Some("iota: major's constructor belongs to a different inductive".to_string()) }); } - let __r_arr: [G; OUT_406] = { let __args: [G; IN_406] = [__v_6, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[406].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[406].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[406].bump_multiplicity(__i); } let __ret: [G; OUT_406] = unsafe { *(record.function_queries[406].output_at(__i).as_ptr() as *const [G; OUT_406]) }; __ret }, _ => aiur_fn_406(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_405] = { let __args: [G; IN_405] = [__v_6, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[405].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[405].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[405].bump_multiplicity(__i); } let __ret: [G; OUT_405] = unsafe { *(record.function_queries[405].output_at(__i).as_ptr() as *const [G; OUT_405]) }; __ret }, _ => aiur_fn_405(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; match __v_28.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_402] = { let __args: [G; IN_402] = [__v_1, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[402].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[402].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[402].bump_multiplicity(__i); } let __ret: [G; OUT_402] = unsafe { *(record.function_queries[402].output_at(__i).as_ptr() as *const [G; OUT_402]) }; __ret }, _ => aiur_fn_402(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_401] = { let __args: [G; IN_401] = [__v_1, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[401].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[401].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[401].bump_multiplicity(__i); } let __ret: [G; OUT_401] = unsafe { *(record.function_queries[401].output_at(__i).as_ptr() as *const [G; OUT_401]) }; __ret }, _ => aiur_fn_401(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = G::from_u64(2); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_8, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_8, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; - let __ret: [G; OUT_404] = [__v_32, __v_33]; - record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_403] = [__v_32, __v_33]; + record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_30, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_30, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = (__v_3 + __v_4); let __v_33: G = (__v_2 + __v_32); - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_1, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = (__v_35 - __v_29); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_25, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_25, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = G::from_u64(1); let __v_39: G = (__v_12 + __v_38); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_31, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_31, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_41, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_41, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_42: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_42, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_42, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; let __v_44: G = G::from_u64(1); - let __ret: [G; OUT_404] = [__v_44, __v_43]; - record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_403] = [__v_44, __v_43]; + record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -36419,13 +36373,13 @@ fn aiur_fn_404( } }, _ => { - let __r_arr: [G; OUT_402] = { let __args: [G; IN_402] = [__v_1, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[402].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[402].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[402].bump_multiplicity(__i); } let __ret: [G; OUT_402] = unsafe { *(record.function_queries[402].output_at(__i).as_ptr() as *const [G; OUT_402]) }; __ret }, _ => aiur_fn_402(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_401] = { let __args: [G; IN_401] = [__v_1, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[401].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[401].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[401].bump_multiplicity(__i); } let __ret: [G; OUT_401] = unsafe { *(record.function_queries[401].output_at(__i).as_ptr() as *const [G; OUT_401]) }; __ret }, _ => aiur_fn_401(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = G::from_u64(2); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_8, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_8, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_404] = [__v_27, __v_28]; - record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_403] = [__v_27, __v_28]; + record.function_queries[403].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36436,15 +36390,15 @@ fn aiur_fn_404( }) } -const INPUT_SIZE_405: usize = 1; -const IN_405: usize = 1; -const OUT_405: usize = 4; -fn aiur_fn_405( - inp: [G; IN_405], +const INPUT_SIZE_404: usize = 1; +const IN_404: usize = 1; +const OUT_404: usize = 4; +fn aiur_fn_404( + inp: [G; IN_404], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_405], ExecError> { +) -> Result<[G; OUT_404], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; @@ -36457,7 +36411,7 @@ fn aiur_fn_405( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -36475,10 +36429,10 @@ fn aiur_fn_405( match __v_8.as_canonical_u64() { 6u64 => { let __v_20: G = G::from_u64(1); - let __r_arr: [G; OUT_463] = { let __args: [G; IN_463] = [__v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[463].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[463].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[463].bump_multiplicity(__i); } let __ret: [G; OUT_463] = unsafe { *(record.function_queries[463].output_at(__i).as_ptr() as *const [G; OUT_463]) }; __ret }, _ => aiur_fn_463(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_462] = { let __args: [G; IN_462] = [__v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[462].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[462].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[462].bump_multiplicity(__i); } let __ret: [G; OUT_462] = unsafe { *(record.function_queries[462].output_at(__i).as_ptr() as *const [G; OUT_462]) }; __ret }, _ => aiur_fn_462(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_405] = [__v_20, __v_13, __v_21, __v_2]; - record.function_queries[405].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_404] = [__v_20, __v_13, __v_21, __v_2]; + record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -36520,8 +36474,8 @@ fn aiur_fn_405( let __v_55: G = G::from_u64(1); let __v_56: G = G::from_u64(1); let __v_57: G = { let __values: [G; 3] = [__v_55, __v_56, __v_56]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_405] = [__v_20, __v_21, __v_54, __v_57]; - record.function_queries[405].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_404] = [__v_20, __v_21, __v_54, __v_57]; + record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36565,23 +36519,23 @@ fn aiur_fn_405( let __v_42: G = G::from_u64(1); let __v_43: G = G::from_u64(1); let __v_44: G = { let __values: [G; 3] = [__v_42, __v_43, __v_43]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_405] = [__v_7, __v_8, __v_41, __v_44]; - record.function_queries[405].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_404] = [__v_7, __v_8, __v_41, __v_44]; + record.function_queries[404].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_406: usize = 2; -const IN_406: usize = 2; -const OUT_406: usize = 3; -fn aiur_fn_406( - inp: [G; IN_406], +const INPUT_SIZE_405: usize = 2; +const IN_405: usize = 2; +const OUT_405: usize = 3; +fn aiur_fn_405( + inp: [G; IN_405], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_406], ExecError> { +) -> Result<[G; OUT_405], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -36599,8 +36553,8 @@ fn aiur_fn_406( let __v_10: G = G::from_u64(0); let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_9, __v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_406] = [__v_7, __v_8, __v_12]; - record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_405] = [__v_7, __v_8, __v_12]; + record.function_queries[405].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -36610,17 +36564,17 @@ fn aiur_fn_406( match __v_7.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_406] = [__v_8, __v_4, __v_5]; - record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_405] = [__v_8, __v_4, __v_5]; + record.function_queries[405].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_406] = { let __args: [G; IN_406] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[406].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[406].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[406].bump_multiplicity(__i); } let __ret: [G; OUT_406] = unsafe { *(record.function_queries[406].output_at(__i).as_ptr() as *const [G; OUT_406]) }; __ret }, _ => aiur_fn_406(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_405] = { let __args: [G; IN_405] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[405].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[405].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[405].bump_multiplicity(__i); } let __ret: [G; OUT_405] = unsafe { *(record.function_queries[405].output_at(__i).as_ptr() as *const [G; OUT_405]) }; __ret }, _ => aiur_fn_405(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = __r_arr[2]; - let __ret: [G; OUT_406] = [__v_8, __v_9, __v_10]; - record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_405] = [__v_8, __v_9, __v_10]; + record.function_queries[405].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36634,15 +36588,15 @@ fn aiur_fn_406( }) } -const INPUT_SIZE_407: usize = 9; -const IN_407: usize = 9; -const OUT_407: usize = 2; -fn aiur_fn_407( - inp: [G; IN_407], +const INPUT_SIZE_406: usize = 9; +const IN_406: usize = 9; +const OUT_406: usize = 2; +fn aiur_fn_406( + inp: [G; IN_406], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_407], ExecError> { +) -> Result<[G; OUT_406], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -36666,8 +36620,8 @@ fn aiur_fn_407( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_14, __v_18]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_14, __v_18]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -36684,8 +36638,8 @@ fn aiur_fn_407( let __v_21: G = G::from_u64(0); let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 4] = [__v_20, __v_21, __v_22, __v_22]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_19, __v_23]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_19, __v_23]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -36694,7 +36648,7 @@ fn aiur_fn_407( let __v_19: G = (__v_3 + __v_4); let __v_20: G = (__v_19 + __v_5); let __v_21: G = (__v_20 + __v_6); - let __r_arr: [G; OUT_408] = { let __args: [G; IN_408] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[408].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[408].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[408].bump_multiplicity(__i); } let __ret: [G; OUT_408] = unsafe { *(record.function_queries[408].output_at(__i).as_ptr() as *const [G; OUT_408]) }; __ret }, _ => aiur_fn_408(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_407] = { let __args: [G; IN_407] = [__v_0, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[407].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[407].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[407].bump_multiplicity(__i); } let __ret: [G; OUT_407] = unsafe { *(record.function_queries[407].output_at(__i).as_ptr() as *const [G; OUT_407]) }; __ret }, _ => aiur_fn_407(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = __r_arr[1]; match __v_22.as_canonical_u64() { @@ -36704,12 +36658,12 @@ fn aiur_fn_407( let __v_26: G = G::from_u64(0); let __v_27: G = G::from_u64(0); let __v_28: G = { let __values: [G; 4] = [__v_25, __v_26, __v_27, __v_27]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_24, __v_28]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_24, __v_28]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_23]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_23]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_24.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_25: G = __loaded[0]; @@ -36732,7 +36686,7 @@ fn aiur_fn_407( 0u64 => { match __v_29.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_410] = { let __args: [G; IN_410] = [__v_23]; let __cu = unconstrained; let __hit = record.function_queries[410].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[410].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[410].bump_multiplicity(__i); } let __ret: [G; OUT_410] = unsafe { *(record.function_queries[410].output_at(__i).as_ptr() as *const [G; OUT_410]) }; __ret }, _ => aiur_fn_410(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_409] = { let __args: [G; IN_409] = [__v_23]; let __cu = unconstrained; let __hit = record.function_queries[409].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[409].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[409].bump_multiplicity(__i); } let __ret: [G; OUT_409] = unsafe { *(record.function_queries[409].output_at(__i).as_ptr() as *const [G; OUT_409]) }; __ret }, _ => aiur_fn_409(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; match __v_39.as_canonical_u64() { 1u64 => { @@ -36741,16 +36695,16 @@ fn aiur_fn_407( let __v_42: G = G::from_u64(0); let __v_43: G = G::from_u64(0); let __v_44: G = { let __values: [G; 4] = [__v_41, __v_42, __v_43, __v_43]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_40, __v_44]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_40, __v_44]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_40]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_40]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_42: G = __r_arr[0]; let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_41, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; @@ -36761,14 +36715,14 @@ fn aiur_fn_407( let __v_46: G = G::from_u64(0); let __v_47: G = G::from_u64(0); let __v_48: G = { let __values: [G; 4] = [__v_45, __v_46, __v_47, __v_47]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_44, __v_48]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_44, __v_48]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_40, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_40, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; - let __r_arr: [G; OUT_469] = { let __args: [G; IN_469] = [__v_44, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[469].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[469].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[469].bump_multiplicity(__i); } let __ret: [G; OUT_469] = unsafe { *(record.function_queries[469].output_at(__i).as_ptr() as *const [G; OUT_469]) }; __ret }, _ => aiur_fn_469(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_468] = { let __args: [G; IN_468] = [__v_44, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[468].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[468].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[468].bump_multiplicity(__i); } let __ret: [G; OUT_468] = unsafe { *(record.function_queries[468].output_at(__i).as_ptr() as *const [G; OUT_468]) }; __ret }, _ => aiur_fn_468(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; match __v_45.as_canonical_u64() { 1u64 => { @@ -36777,31 +36731,31 @@ fn aiur_fn_407( let __v_48: G = G::from_u64(0); let __v_49: G = G::from_u64(0); let __v_50: G = { let __values: [G; 4] = [__v_47, __v_48, __v_49, __v_49]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_46, __v_50]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_46, __v_50]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_12, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_12, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_46: G = __r_arr[0]; let __v_47: G = (__v_3 + __v_4); let __v_48: G = (__v_47 + __v_5); - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_2, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_46, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_46, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __v_51: G = G::from_u64(0); - let __r_arr: [G; OUT_409] = { let __args: [G; IN_409] = [__v_50, __v_23, __v_40, __v_11, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[409].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[409].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[409].bump_multiplicity(__i); } let __ret: [G; OUT_409] = unsafe { *(record.function_queries[409].output_at(__i).as_ptr() as *const [G; OUT_409]) }; __ret }, _ => aiur_fn_409(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_408] = { let __args: [G; IN_408] = [__v_50, __v_23, __v_40, __v_11, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[408].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[408].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[408].bump_multiplicity(__i); } let __ret: [G; OUT_408] = unsafe { *(record.function_queries[408].output_at(__i).as_ptr() as *const [G; OUT_408]) }; __ret }, _ => aiur_fn_408(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = G::from_u64(1); let __v_54: G = (__v_21 + __v_53); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_2, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __v_56: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_52, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_52, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_57: G = __r_arr[0]; - let __ret: [G; OUT_407] = [__v_56, __v_57]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_56, __v_57]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36816,8 +36770,8 @@ fn aiur_fn_407( let __v_41: G = G::from_u64(0); let __v_42: G = G::from_u64(0); let __v_43: G = { let __values: [G; 4] = [__v_40, __v_41, __v_42, __v_42]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_39, __v_43]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_39, __v_43]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36828,8 +36782,8 @@ fn aiur_fn_407( let __v_41: G = G::from_u64(0); let __v_42: G = G::from_u64(0); let __v_43: G = { let __values: [G; 4] = [__v_40, __v_41, __v_42, __v_42]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_39, __v_43]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_39, __v_43]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36840,8 +36794,8 @@ fn aiur_fn_407( let __v_39: G = G::from_u64(0); let __v_40: G = G::from_u64(0); let __v_41: G = { let __values: [G; 4] = [__v_38, __v_39, __v_40, __v_40]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_407] = [__v_37, __v_41]; - record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_406] = [__v_37, __v_41]; + record.function_queries[406].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36862,15 +36816,15 @@ fn aiur_fn_407( }) } -const INPUT_SIZE_408: usize = 2; -const IN_408: usize = 2; -const OUT_408: usize = 2; -fn aiur_fn_408( - inp: [G; IN_408], +const INPUT_SIZE_407: usize = 2; +const IN_407: usize = 2; +const OUT_407: usize = 2; +fn aiur_fn_407( + inp: [G; IN_407], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_408], ExecError> { +) -> Result<[G; OUT_407], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -36894,8 +36848,8 @@ fn aiur_fn_408( match __v_8.as_canonical_u64() { 2u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_408] = [__v_12, __v_9]; - record.function_queries[408].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_407] = [__v_12, __v_9]; + record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -36933,8 +36887,8 @@ fn aiur_fn_408( let __v_43: G = G::from_u64(0); let __v_44: G = G::from_u64(0); let __v_45: G = { let __values: [G; 32] = [__v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_408] = [__v_12, __v_45]; - record.function_queries[408].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_407] = [__v_12, __v_45]; + record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36974,8 +36928,8 @@ fn aiur_fn_408( let __v_37: G = G::from_u64(0); let __v_38: G = G::from_u64(0); let __v_39: G = { let __values: [G; 32] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_408] = [__v_6, __v_39]; - record.function_queries[408].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_407] = [__v_6, __v_39]; + record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -36990,11 +36944,11 @@ fn aiur_fn_408( 5u64 => { let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 - __v_6); - let __r_arr: [G; OUT_408] = { let __args: [G; IN_408] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[408].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[408].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[408].bump_multiplicity(__i); } let __ret: [G; OUT_408] = unsafe { *(record.function_queries[408].output_at(__i).as_ptr() as *const [G; OUT_408]) }; __ret }, _ => aiur_fn_408(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_407] = { let __args: [G; IN_407] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[407].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[407].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[407].bump_multiplicity(__i); } let __ret: [G; OUT_407] = unsafe { *(record.function_queries[407].output_at(__i).as_ptr() as *const [G; OUT_407]) }; __ret }, _ => aiur_fn_407(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_408] = [__v_8, __v_9]; - record.function_queries[408].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_407] = [__v_8, __v_9]; + record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -37032,8 +36986,8 @@ fn aiur_fn_408( let __v_37: G = G::from_u64(0); let __v_38: G = G::from_u64(0); let __v_39: G = { let __values: [G; 32] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_408] = [__v_6, __v_39]; - record.function_queries[408].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_407] = [__v_6, __v_39]; + record.function_queries[407].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -37042,15 +36996,15 @@ fn aiur_fn_408( }) } -const INPUT_SIZE_409: usize = 5; -const IN_409: usize = 5; -const OUT_409: usize = 1; -fn aiur_fn_409( - inp: [G; IN_409], +const INPUT_SIZE_408: usize = 5; +const IN_408: usize = 5; +const OUT_408: usize = 1; +fn aiur_fn_408( + inp: [G; IN_408], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_409], ExecError> { +) -> Result<[G; OUT_408], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37060,8 +37014,8 @@ fn aiur_fn_409( let __v_5: G = (__v_3 - __v_4); match __v_5.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_409] = [__v_0]; - record.function_queries[409].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_408] = [__v_0]; + record.function_queries[408].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -37072,28 +37026,28 @@ fn aiur_fn_409( let __v_10: G = { let __values: [G; 4] = [__v_8, __v_0, __v_7, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = G::from_u64(1); let __v_12: G = (__v_4 + __v_11); - let __r_arr: [G; OUT_409] = { let __args: [G; IN_409] = [__v_10, __v_1, __v_2, __v_3, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[409].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[409].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[409].bump_multiplicity(__i); } let __ret: [G; OUT_409] = unsafe { *(record.function_queries[409].output_at(__i).as_ptr() as *const [G; OUT_409]) }; __ret }, _ => aiur_fn_409(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_408] = { let __args: [G; IN_408] = [__v_10, __v_1, __v_2, __v_3, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[408].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[408].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[408].bump_multiplicity(__i); } let __ret: [G; OUT_408] = unsafe { *(record.function_queries[408].output_at(__i).as_ptr() as *const [G; OUT_408]) }; __ret }, _ => aiur_fn_408(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_409] = [__v_13]; - record.function_queries[409].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_408] = [__v_13]; + record.function_queries[408].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_410: usize = 1; -const IN_410: usize = 1; -const OUT_410: usize = 1; -fn aiur_fn_410( - inp: [G; IN_410], +const INPUT_SIZE_409: usize = 1; +const IN_409: usize = 1; +const OUT_409: usize = 1; +fn aiur_fn_409( + inp: [G; IN_409], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_410], ExecError> { +) -> Result<[G; OUT_409], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_1.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_2: G = __loaded[0]; @@ -37110,38 +37064,38 @@ fn aiur_fn_410( let __v_13: G = __loaded[11]; match __v_2.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_411] = { let __args: [G; IN_411] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[411].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[411].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[411].bump_multiplicity(__i); } let __ret: [G; OUT_411] = unsafe { *(record.function_queries[411].output_at(__i).as_ptr() as *const [G; OUT_411]) }; __ret }, _ => aiur_fn_411(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_410] = { let __args: [G; IN_410] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[410].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[410].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[410].bump_multiplicity(__i); } let __ret: [G; OUT_410] = unsafe { *(record.function_queries[410].output_at(__i).as_ptr() as *const [G; OUT_410]) }; __ret }, _ => aiur_fn_410(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_412] = { let __args: [G; IN_412] = [__v_9, __v_10, __v_7, __v_5, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[412].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[412].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[412].bump_multiplicity(__i); } let __ret: [G; OUT_412] = unsafe { *(record.function_queries[412].output_at(__i).as_ptr() as *const [G; OUT_412]) }; __ret }, _ => aiur_fn_412(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_411] = { let __args: [G; IN_411] = [__v_9, __v_10, __v_7, __v_5, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[411].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[411].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[411].bump_multiplicity(__i); } let __ret: [G; OUT_411] = unsafe { *(record.function_queries[411].output_at(__i).as_ptr() as *const [G; OUT_411]) }; __ret }, _ => aiur_fn_411(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_410] = [__v_16]; - record.function_queries[410].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_409] = [__v_16]; + record.function_queries[409].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(1); - let __ret: [G; OUT_410] = [__v_14]; - record.function_queries[410].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_409] = [__v_14]; + record.function_queries[409].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_411: usize = 2; -const IN_411: usize = 2; -const OUT_411: usize = 1; -fn aiur_fn_411( - inp: [G; IN_411], +const INPUT_SIZE_410: usize = 2; +const IN_410: usize = 2; +const OUT_410: usize = 1; +fn aiur_fn_410( + inp: [G; IN_410], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_411], ExecError> { +) -> Result<[G; OUT_410], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -37194,10 +37148,10 @@ fn aiur_fn_411( _ => { match __v_2.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_411] = [__v_50]; - record.function_queries[411].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_410] = [__v_50]; + record.function_queries[410].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -37206,8 +37160,8 @@ fn aiur_fn_411( let __v_52: G = G::from_u64(1); let __v_53: G = { let __values: [G; 3] = [__v_51, __v_52, __v_52]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_54: G = { let __values: [G; 3] = [__v_50, __v_0, __v_53]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_411] = [__v_54]; - record.function_queries[411].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_410] = [__v_54]; + record.function_queries[410].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -37216,15 +37170,15 @@ fn aiur_fn_411( }) } -const INPUT_SIZE_412: usize = 6; -const IN_412: usize = 6; -const OUT_412: usize = 1; -fn aiur_fn_412( - inp: [G; IN_412], +const INPUT_SIZE_411: usize = 6; +const IN_411: usize = 6; +const OUT_411: usize = 1; +fn aiur_fn_411( + inp: [G; IN_411], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_412], ExecError> { +) -> Result<[G; OUT_411], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37236,12 +37190,12 @@ fn aiur_fn_412( match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_412] = [__v_7]; - record.function_queries[412].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_411] = [__v_7]; + record.function_queries[411].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_0, __v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_0, __v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -37258,32 +37212,32 @@ fn aiur_fn_412( let __v_19: G = __loaded[11]; match __v_8.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_413] = { let __args: [G; IN_413] = [__v_10, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[413].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[413].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[413].bump_multiplicity(__i); } let __ret: [G; OUT_413] = unsafe { *(record.function_queries[413].output_at(__i).as_ptr() as *const [G; OUT_413]) }; __ret }, _ => aiur_fn_413(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_412] = { let __args: [G; IN_412] = [__v_10, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[412].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[412].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[412].bump_multiplicity(__i); } let __ret: [G; OUT_412] = unsafe { *(record.function_queries[412].output_at(__i).as_ptr() as *const [G; OUT_412]) }; __ret }, _ => aiur_fn_412(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_20, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_413] = { let __args: [G; IN_413] = [__v_20, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[413].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[413].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[413].bump_multiplicity(__i); } let __ret: [G; OUT_413] = unsafe { *(record.function_queries[413].output_at(__i).as_ptr() as *const [G; OUT_413]) }; __ret }, _ => aiur_fn_413(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; match __v_21.as_canonical_u64() { 1u64 => { let __v_22: G = G::from_u64(1); - let __ret: [G; OUT_412] = [__v_22]; - record.function_queries[412].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_411] = [__v_22]; + record.function_queries[411].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_22: G = G::from_u64(1); let __v_23: G = (__v_5 + __v_22); - let __r_arr: [G; OUT_412] = { let __args: [G; IN_412] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[412].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[412].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[412].bump_multiplicity(__i); } let __ret: [G; OUT_412] = unsafe { *(record.function_queries[412].output_at(__i).as_ptr() as *const [G; OUT_412]) }; __ret }, _ => aiur_fn_412(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_411] = { let __args: [G; IN_411] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[411].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[411].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[411].bump_multiplicity(__i); } let __ret: [G; OUT_411] = unsafe { *(record.function_queries[411].output_at(__i).as_ptr() as *const [G; OUT_411]) }; __ret }, _ => aiur_fn_411(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __ret: [G; OUT_412] = [__v_24]; - record.function_queries[412].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_411] = [__v_24]; + record.function_queries[411].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_20: G = G::from_u64(1); - let __ret: [G; OUT_412] = [__v_20]; - record.function_queries[412].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_411] = [__v_20]; + record.function_queries[411].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -37292,22 +37246,22 @@ fn aiur_fn_412( }) } -const INPUT_SIZE_413: usize = 2; -const IN_413: usize = 2; -const OUT_413: usize = 1; -fn aiur_fn_413( - inp: [G; IN_413], +const INPUT_SIZE_412: usize = 2; +const IN_412: usize = 2; +const OUT_412: usize = 1; +fn aiur_fn_412( + inp: [G; IN_412], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_413], ExecError> { +) -> Result<[G; OUT_412], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_413] = [__v_0]; - record.function_queries[413].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_412] = [__v_0]; + record.function_queries[412].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -37320,15 +37274,15 @@ fn aiur_fn_413( 5u64 => { let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 - __v_6); - let __r_arr: [G; OUT_413] = { let __args: [G; IN_413] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[413].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[413].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[413].bump_multiplicity(__i); } let __ret: [G; OUT_413] = unsafe { *(record.function_queries[413].output_at(__i).as_ptr() as *const [G; OUT_413]) }; __ret }, _ => aiur_fn_413(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_412] = { let __args: [G; IN_412] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[412].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[412].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[412].bump_multiplicity(__i); } let __ret: [G; OUT_412] = unsafe { *(record.function_queries[412].output_at(__i).as_ptr() as *const [G; OUT_412]) }; __ret }, _ => aiur_fn_412(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_413] = [__v_8]; - record.function_queries[413].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_412] = [__v_8]; + record.function_queries[412].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_413] = [__v_0]; - record.function_queries[413].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_412] = [__v_0]; + record.function_queries[412].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -37337,15 +37291,15 @@ fn aiur_fn_413( }) } -const INPUT_SIZE_414: usize = 2; -const IN_414: usize = 2; -const OUT_414: usize = 1; -fn aiur_fn_414( - inp: [G; IN_414], +const INPUT_SIZE_413: usize = 2; +const IN_413: usize = 2; +const OUT_413: usize = 1; +fn aiur_fn_413( + inp: [G; IN_413], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_414], ExecError> { +) -> Result<[G; OUT_413], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37356,43 +37310,43 @@ fn aiur_fn_414( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_414] = [__v_7]; - record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_413] = [__v_7]; + record.function_queries[413].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_413] = { let __args: [G; IN_413] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[413].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[413].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[413].bump_multiplicity(__i); } let __ret: [G; OUT_413] = unsafe { *(record.function_queries[413].output_at(__i).as_ptr() as *const [G; OUT_413]) }; __ret }, _ => aiur_fn_413(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_414] = [__v_7]; - record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_413] = [__v_7]; + record.function_queries[413].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_414] = [__v_6]; - record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_413] = [__v_6]; + record.function_queries[413].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_415: usize = 2; -const IN_415: usize = 2; -const OUT_415: usize = 1; -fn aiur_fn_415( - inp: [G; IN_415], +const INPUT_SIZE_414: usize = 2; +const IN_414: usize = 2; +const OUT_414: usize = 1; +fn aiur_fn_414( + inp: [G; IN_414], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_415], ExecError> { +) -> Result<[G; OUT_414], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37403,94 +37357,94 @@ fn aiur_fn_415( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_415] = [__v_6]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_6]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_415] = [__v_7]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_7]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_415] = [__v_7]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_7]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 4u64 => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_415] = [__v_7]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_7]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_415] = [__v_7]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_7]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 5u64 => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_415] = [__v_7]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_7]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_415] = [__v_7]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_7]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 6u64 => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_415] = [__v_7]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_7]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_415] = [__v_8]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_8]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_415] = [__v_8]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_8]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -37498,31 +37452,31 @@ fn aiur_fn_415( } }, 8u64 => { - let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_414] = { let __args: [G; IN_414] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[414].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[414].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[414].bump_multiplicity(__i); } let __ret: [G; OUT_414] = unsafe { *(record.function_queries[414].output_at(__i).as_ptr() as *const [G; OUT_414]) }; __ret }, _ => aiur_fn_414(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_415] = [__v_6]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_6]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_415] = [__v_6]; - record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_414] = [__v_6]; + record.function_queries[414].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_416: usize = 2; -const IN_416: usize = 2; -const OUT_416: usize = 1; -fn aiur_fn_416( - inp: [G; IN_416], +const INPUT_SIZE_415: usize = 2; +const IN_415: usize = 2; +const OUT_415: usize = 1; +fn aiur_fn_415( + inp: [G; IN_415], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_416], ExecError> { +) -> Result<[G; OUT_415], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37533,8 +37487,8 @@ fn aiur_fn_416( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_416] = [__v_5]; - record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_415] = [__v_5]; + record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -37543,15 +37497,15 @@ fn aiur_fn_416( match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_416] = [__v_6]; - record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_415] = [__v_6]; + record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_416] = [__v_6]; - record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_415] = [__v_6]; + record.function_queries[415].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -37563,15 +37517,15 @@ fn aiur_fn_416( }) } -const INPUT_SIZE_417: usize = 2; -const IN_417: usize = 2; -const OUT_417: usize = 1; -fn aiur_fn_417( - inp: [G; IN_417], +const INPUT_SIZE_416: usize = 2; +const IN_416: usize = 2; +const OUT_416: usize = 1; +fn aiur_fn_416( + inp: [G; IN_416], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_417], ExecError> { +) -> Result<[G; OUT_416], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37582,80 +37536,80 @@ fn aiur_fn_417( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_417] = [__v_0]; - record.function_queries[417].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_416] = [__v_0]; + record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __ret: [G; OUT_417] = [__v_0]; - record.function_queries[417].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_416] = [__v_0]; + record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __ret: [G; OUT_417] = [__v_0]; - record.function_queries[417].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_416] = [__v_0]; + record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __ret: [G; OUT_417] = [__v_0]; - record.function_queries[417].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_416] = [__v_0]; + record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_417] = [__v_0]; - record.function_queries[417].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_416] = [__v_0]; + record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_0, __v_10, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_0, __v_10, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_417] = [__v_11]; - record.function_queries[417].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_416] = [__v_11]; + record.function_queries[416].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_418: usize = 2; -const IN_418: usize = 2; -const OUT_418: usize = 1; -fn aiur_fn_418( - inp: [G; IN_418], +const INPUT_SIZE_417: usize = 2; +const IN_417: usize = 2; +const OUT_417: usize = 1; +fn aiur_fn_417( + inp: [G; IN_417], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_418], ExecError> { +) -> Result<[G; OUT_417], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); let __v_4: G = { let __values: [G; 3] = [__v_2, __v_3, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_377] = { let __args: [G; IN_377] = [__v_0, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[377].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[377].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[377].bump_multiplicity(__i); } let __ret: [G; OUT_377] = unsafe { *(record.function_queries[377].output_at(__i).as_ptr() as *const [G; OUT_377]) }; __ret }, _ => aiur_fn_377(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_376] = { let __args: [G; IN_376] = [__v_0, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[376].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[376].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[376].bump_multiplicity(__i); } let __ret: [G; OUT_376] = unsafe { *(record.function_queries[376].output_at(__i).as_ptr() as *const [G; OUT_376]) }; __ret }, _ => aiur_fn_376(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_418] = [__v_5]; - record.function_queries[418].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_417] = [__v_5]; + record.function_queries[417].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_419: usize = 2; -const IN_419: usize = 2; -const OUT_419: usize = 1; -fn aiur_fn_419( - inp: [G; IN_419], +const INPUT_SIZE_418: usize = 2; +const IN_418: usize = 2; +const OUT_418: usize = 1; +fn aiur_fn_418( + inp: [G; IN_418], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_419], ExecError> { +) -> Result<[G; OUT_418], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37666,57 +37620,57 @@ fn aiur_fn_419( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_419] = [__v_0]; - record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_418] = [__v_0]; + record.function_queries[418].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __ret: [G; OUT_419] = [__v_0]; - record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_418] = [__v_0]; + record.function_queries[418].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __ret: [G; OUT_419] = [__v_0]; - record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_418] = [__v_0]; + record.function_queries[418].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __ret: [G; OUT_419] = [__v_0]; - record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_418] = [__v_0]; + record.function_queries[418].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_419] = [__v_0]; - record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_418] = [__v_0]; + record.function_queries[418].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_420] = { let __args: [G; IN_420] = [__v_0, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[420].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[420].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[420].bump_multiplicity(__i); } let __ret: [G; OUT_420] = unsafe { *(record.function_queries[420].output_at(__i).as_ptr() as *const [G; OUT_420]) }; __ret }, _ => aiur_fn_420(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_0, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_419] = [__v_11]; - record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_418] = [__v_11]; + record.function_queries[418].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_420: usize = 3; -const IN_420: usize = 3; -const OUT_420: usize = 1; -fn aiur_fn_420( - inp: [G; IN_420], +const INPUT_SIZE_419: usize = 3; +const IN_419: usize = 3; +const OUT_419: usize = 1; +fn aiur_fn_419( + inp: [G; IN_419], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_420], ExecError> { +) -> Result<[G; OUT_419], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37731,101 +37685,101 @@ fn aiur_fn_420( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_420] = { let __args: [G; IN_420] = [__v_7, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[420].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[420].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[420].bump_multiplicity(__i); } let __ret: [G; OUT_420] = unsafe { *(record.function_queries[420].output_at(__i).as_ptr() as *const [G; OUT_420]) }; __ret }, _ => aiur_fn_420(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_7, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_10]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_10]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_375] = { let __args: [G; IN_375] = [__v_0, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[375].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[375].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[375].bump_multiplicity(__i); } let __ret: [G; OUT_375] = unsafe { *(record.function_queries[375].output_at(__i).as_ptr() as *const [G; OUT_375]) }; __ret }, _ => aiur_fn_375(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_374] = { let __args: [G; IN_374] = [__v_0, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[374].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[374].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[374].bump_multiplicity(__i); } let __ret: [G; OUT_374] = unsafe { *(record.function_queries[374].output_at(__i).as_ptr() as *const [G; OUT_374]) }; __ret }, _ => aiur_fn_374(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_14]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_14]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_11, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_11, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_10, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_10, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_420] = { let __args: [G; IN_420] = [__v_17, __v_12, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[420].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[420].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[420].bump_multiplicity(__i); } let __ret: [G; OUT_420] = unsafe { *(record.function_queries[420].output_at(__i).as_ptr() as *const [G; OUT_420]) }; __ret }, _ => aiur_fn_420(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_17, __v_12, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_18]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_18]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_10, __v_11, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_10, __v_11, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __r_arr: [G; OUT_420] = { let __args: [G; IN_420] = [__v_15, __v_12, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[420].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[420].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[420].bump_multiplicity(__i); } let __ret: [G; OUT_420] = unsafe { *(record.function_queries[420].output_at(__i).as_ptr() as *const [G; OUT_420]) }; __ret }, _ => aiur_fn_420(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_15, __v_12, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_16]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_16]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 6u64 => { let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_6, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_6, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_420] = { let __args: [G; IN_420] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[420].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[420].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[420].bump_multiplicity(__i); } let __ret: [G; OUT_420] = unsafe { *(record.function_queries[420].output_at(__i).as_ptr() as *const [G; OUT_420]) }; __ret }, _ => aiur_fn_420(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_9]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_9]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_421] = { let __args: [G; IN_421] = [__v_4, __v_5, __v_6, __v_1, __v_2, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[421].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[421].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[421].bump_multiplicity(__i); } let __ret: [G; OUT_421] = unsafe { *(record.function_queries[421].output_at(__i).as_ptr() as *const [G; OUT_421]) }; __ret }, _ => aiur_fn_421(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_420] = { let __args: [G; IN_420] = [__v_4, __v_5, __v_6, __v_1, __v_2, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[420].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[420].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[420].bump_multiplicity(__i); } let __ret: [G; OUT_420] = unsafe { *(record.function_queries[420].output_at(__i).as_ptr() as *const [G; OUT_420]) }; __ret }, _ => aiur_fn_420(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_7]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_7]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_4, __v_5, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_421] = { let __args: [G; IN_421] = [__v_4, __v_5, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[421].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[421].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[421].bump_multiplicity(__i); } let __ret: [G; OUT_421] = unsafe { *(record.function_queries[421].output_at(__i).as_ptr() as *const [G; OUT_421]) }; __ret }, _ => aiur_fn_421(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_7]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_7]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_420] = [__v_7]; - record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_419] = [__v_7]; + record.function_queries[419].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_421: usize = 6; -const IN_421: usize = 6; -const OUT_421: usize = 1; -fn aiur_fn_421( - inp: [G; IN_421], +const INPUT_SIZE_420: usize = 6; +const IN_420: usize = 6; +const OUT_420: usize = 1; +fn aiur_fn_420( + inp: [G; IN_420], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_421], ExecError> { +) -> Result<[G; OUT_420], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37833,7 +37787,7 @@ fn aiur_fn_421( let __v_3: G = inp[3]; let __v_4: G = inp[4]; let __v_5: G = inp[5]; - let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_418] = { let __args: [G; IN_418] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[418].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[418].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[418].bump_multiplicity(__i); } let __ret: [G; OUT_418] = unsafe { *(record.function_queries[418].output_at(__i).as_ptr() as *const [G; OUT_418]) }; __ret }, _ => aiur_fn_418(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; @@ -37845,7 +37799,7 @@ fn aiur_fn_421( let __v_12: G = __loaded[3]; match __v_9.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_385] = { let __args: [G; IN_385] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[385].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[385].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[385].bump_multiplicity(__i); } let __ret: [G; OUT_385] = unsafe { *(record.function_queries[385].output_at(__i).as_ptr() as *const [G; OUT_385]) }; __ret }, _ => aiur_fn_385(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_13.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_14: G = __loaded[0]; @@ -37863,50 +37817,50 @@ fn aiur_fn_421( match __v_14.as_canonical_u64() { 6u64 => { let __v_26: G = (__v_20 + __v_1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_8, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_8, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_420] = { let __args: [G; IN_420] = [__v_27, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[420].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[420].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[420].bump_multiplicity(__i); } let __ret: [G; OUT_420] = unsafe { *(record.function_queries[420].output_at(__i).as_ptr() as *const [G; OUT_420]) }; __ret }, _ => aiur_fn_420(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_27, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_421] = [__v_28]; - record.function_queries[421].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_420] = [__v_28]; + record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __ret: [G; OUT_421] = [__v_26]; - record.function_queries[421].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_420] = [__v_26]; + record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_421] = [__v_13]; - record.function_queries[421].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_420] = [__v_13]; + record.function_queries[420].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_422: usize = 5; -const IN_422: usize = 5; -const OUT_422: usize = 1; -fn aiur_fn_422( - inp: [G; IN_422], +const INPUT_SIZE_421: usize = 5; +const IN_421: usize = 5; +const OUT_421: usize = 1; +fn aiur_fn_421( + inp: [G; IN_421], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_422], ExecError> { +) -> Result<[G; OUT_421], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -37923,48 +37877,48 @@ fn aiur_fn_422( let __v_17: G = __loaded[11]; match __v_6.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_8, __v_9, __v_11, __v_12, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_8, __v_9, __v_11, __v_12, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_404] = { let __args: [G; IN_404] = [__v_1, __v_3, __v_9, __v_11, __v_12, __v_10, __v_13, __v_4, __v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[404].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[404].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[404].bump_multiplicity(__i); } let __ret: [G; OUT_404] = unsafe { *(record.function_queries[404].output_at(__i).as_ptr() as *const [G; OUT_404]) }; __ret }, _ => aiur_fn_404(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_403] = { let __args: [G; IN_403] = [__v_1, __v_3, __v_9, __v_11, __v_12, __v_10, __v_13, __v_4, __v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[403].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[403].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[403].bump_multiplicity(__i); } let __ret: [G; OUT_403] = unsafe { *(record.function_queries[403].output_at(__i).as_ptr() as *const [G; OUT_403]) }; __ret }, _ => aiur_fn_403(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; match __v_19.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_20, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_418] = { let __args: [G; IN_418] = [__v_20, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[418].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[418].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[418].bump_multiplicity(__i); } let __ret: [G; OUT_418] = unsafe { *(record.function_queries[418].output_at(__i).as_ptr() as *const [G; OUT_418]) }; __ret }, _ => aiur_fn_418(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_422] = [__v_21]; - record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_421] = [__v_21]; + record.function_queries[421].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_422] = [__v_21]; - record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_421] = [__v_21]; + record.function_queries[421].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_422] = [__v_18]; - record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_421] = [__v_18]; + record.function_queries[421].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_423: usize = 2; -const IN_423: usize = 2; -const OUT_423: usize = 1; -fn aiur_fn_423( - inp: [G; IN_423], +const INPUT_SIZE_422: usize = 2; +const IN_422: usize = 2; +const OUT_422: usize = 1; +fn aiur_fn_422( + inp: [G; IN_422], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_423], ExecError> { +) -> Result<[G; OUT_422], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -37975,80 +37929,80 @@ fn aiur_fn_423( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_423] = [__v_0]; - record.function_queries[423].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_422] = [__v_0]; + record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __ret: [G; OUT_423] = [__v_0]; - record.function_queries[423].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_422] = [__v_0]; + record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __ret: [G; OUT_423] = [__v_0]; - record.function_queries[423].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_422] = [__v_0]; + record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __ret: [G; OUT_423] = [__v_0]; - record.function_queries[423].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_422] = [__v_0]; + record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_423] = [__v_0]; - record.function_queries[423].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_422] = [__v_0]; + record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_0, __v_10, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_0, __v_10, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_423] = [__v_11]; - record.function_queries[423].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_422] = [__v_11]; + record.function_queries[422].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_424: usize = 2; -const IN_424: usize = 2; -const OUT_424: usize = 1; -fn aiur_fn_424( - inp: [G; IN_424], +const INPUT_SIZE_423: usize = 2; +const IN_423: usize = 2; +const OUT_423: usize = 1; +fn aiur_fn_423( + inp: [G; IN_423], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_424], ExecError> { +) -> Result<[G; OUT_423], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); let __v_4: G = { let __values: [G; 3] = [__v_2, __v_3, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_0, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_0, __v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_424] = [__v_5]; - record.function_queries[424].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_423] = [__v_5]; + record.function_queries[423].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_425: usize = 3; -const IN_425: usize = 3; -const OUT_425: usize = 1; -fn aiur_fn_425( - inp: [G; IN_425], +const INPUT_SIZE_424: usize = 3; +const IN_424: usize = 3; +const OUT_424: usize = 1; +fn aiur_fn_424( + inp: [G; IN_424], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_425], ExecError> { +) -> Result<[G; OUT_424], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -38063,65 +38017,65 @@ fn aiur_fn_425( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_8, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_7, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_7, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_425] = [__v_10]; - record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_424] = [__v_10]; + record.function_queries[424].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_426] = { let __args: [G; IN_426] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[426].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[426].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[426].bump_multiplicity(__i); } let __ret: [G; OUT_426] = unsafe { *(record.function_queries[426].output_at(__i).as_ptr() as *const [G; OUT_426]) }; __ret }, _ => aiur_fn_426(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_425] = [__v_7]; - record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_424] = [__v_7]; + record.function_queries[424].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_428] = { let __args: [G; IN_428] = [__v_4, __v_5, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[428].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[428].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[428].bump_multiplicity(__i); } let __ret: [G; OUT_428] = unsafe { *(record.function_queries[428].output_at(__i).as_ptr() as *const [G; OUT_428]) }; __ret }, _ => aiur_fn_428(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_427] = { let __args: [G; IN_427] = [__v_4, __v_5, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[427].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[427].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[427].bump_multiplicity(__i); } let __ret: [G; OUT_427] = unsafe { *(record.function_queries[427].output_at(__i).as_ptr() as *const [G; OUT_427]) }; __ret }, _ => aiur_fn_427(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_425] = [__v_7]; - record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_424] = [__v_7]; + record.function_queries[424].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_6, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_6, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_425] = [__v_9]; - record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_424] = [__v_9]; + record.function_queries[424].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_427] = { let __args: [G; IN_427] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[427].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[427].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[427].bump_multiplicity(__i); } let __ret: [G; OUT_427] = unsafe { *(record.function_queries[427].output_at(__i).as_ptr() as *const [G; OUT_427]) }; __ret }, _ => aiur_fn_427(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_426] = { let __args: [G; IN_426] = [__v_4, __v_5, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[426].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[426].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[426].bump_multiplicity(__i); } let __ret: [G; OUT_426] = unsafe { *(record.function_queries[426].output_at(__i).as_ptr() as *const [G; OUT_426]) }; __ret }, _ => aiur_fn_426(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_425] = [__v_7]; - record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_424] = [__v_7]; + record.function_queries[424].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_425] = [__v_7]; - record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_424] = [__v_7]; + record.function_queries[424].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_426: usize = 3; -const IN_426: usize = 3; -const OUT_426: usize = 1; -fn aiur_fn_426( - inp: [G; IN_426], +const INPUT_SIZE_425: usize = 3; +const IN_425: usize = 3; +const OUT_425: usize = 1; +fn aiur_fn_425( + inp: [G; IN_425], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_426], ExecError> { +) -> Result<[G; OUT_425], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -38129,78 +38083,78 @@ fn aiur_fn_426( let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_375] = { let __args: [G; IN_375] = [__v_1, __v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[375].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[375].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[375].bump_multiplicity(__i); } let __ret: [G; OUT_375] = unsafe { *(record.function_queries[375].output_at(__i).as_ptr() as *const [G; OUT_375]) }; __ret }, _ => aiur_fn_375(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_374] = { let __args: [G; IN_374] = [__v_1, __v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[374].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[374].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[374].bump_multiplicity(__i); } let __ret: [G; OUT_374] = unsafe { *(record.function_queries[374].output_at(__i).as_ptr() as *const [G; OUT_374]) }; __ret }, _ => aiur_fn_374(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; let __v_8: G = __r_arr[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_1, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_1, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_426] = [__v_10]; - record.function_queries[426].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_425] = [__v_10]; + record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_6, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_6, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_13, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_13, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_426] = [__v_14]; - record.function_queries[426].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_425] = [__v_14]; + record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_6, __v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_6, __v_7, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_11, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_11, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_426] = [__v_12]; - record.function_queries[426].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_425] = [__v_12]; + record.function_queries[425].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_427: usize = 5; -const IN_427: usize = 5; -const OUT_427: usize = 1; -fn aiur_fn_427( - inp: [G; IN_427], +const INPUT_SIZE_426: usize = 5; +const IN_426: usize = 5; +const OUT_426: usize = 1; +fn aiur_fn_426( + inp: [G; IN_426], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_427], ExecError> { +) -> Result<[G; OUT_426], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_231] = { let __args: [G; IN_231] = [__v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[231].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[231].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[231].bump_multiplicity(__i); } let __ret: [G; OUT_231] = unsafe { *(record.function_queries[231].output_at(__i).as_ptr() as *const [G; OUT_231]) }; __ret }, _ => aiur_fn_231(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_230] = { let __args: [G; IN_230] = [__v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[230].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[230].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[230].bump_multiplicity(__i); } let __ret: [G; OUT_230] = unsafe { *(record.function_queries[230].output_at(__i).as_ptr() as *const [G; OUT_230]) }; __ret }, _ => aiur_fn_230(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __r_arr: [G; OUT_385] = { let __args: [G; IN_385] = [__v_0, __v_1, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[385].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[385].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[385].bump_multiplicity(__i); } let __ret: [G; OUT_385] = unsafe { *(record.function_queries[385].output_at(__i).as_ptr() as *const [G; OUT_385]) }; __ret }, _ => aiur_fn_385(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_384] = { let __args: [G; IN_384] = [__v_0, __v_1, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[384].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[384].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[384].bump_multiplicity(__i); } let __ret: [G; OUT_384] = unsafe { *(record.function_queries[384].output_at(__i).as_ptr() as *const [G; OUT_384]) }; __ret }, _ => aiur_fn_384(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_10, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_10, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_427] = [__v_11]; - record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_426] = [__v_11]; + record.function_queries[426].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -38211,7 +38165,7 @@ fn aiur_fn_427( let __v_14: G = __loaded[3]; match __v_11.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_386] = { let __args: [G; IN_386] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[386].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[386].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[386].bump_multiplicity(__i); } let __ret: [G; OUT_386] = unsafe { *(record.function_queries[386].output_at(__i).as_ptr() as *const [G; OUT_386]) }; __ret }, _ => aiur_fn_386(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_385] = { let __args: [G; IN_385] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[385].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[385].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[385].bump_multiplicity(__i); } let __ret: [G; OUT_385] = unsafe { *(record.function_queries[385].output_at(__i).as_ptr() as *const [G; OUT_385]) }; __ret }, _ => aiur_fn_385(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_15.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_16: G = __loaded[0]; @@ -38229,21 +38183,21 @@ fn aiur_fn_427( match __v_16.as_canonical_u64() { 6u64 => { let __v_28: G = (__v_22 + __v_1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_8, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_8, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __r_arr: [G; OUT_425] = { let __args: [G; IN_425] = [__v_29, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[425].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[425].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[425].bump_multiplicity(__i); } let __ret: [G; OUT_425] = unsafe { *(record.function_queries[425].output_at(__i).as_ptr() as *const [G; OUT_425]) }; __ret }, _ => aiur_fn_425(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_424] = { let __args: [G; IN_424] = [__v_29, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[424].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[424].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[424].bump_multiplicity(__i); } let __ret: [G; OUT_424] = unsafe { *(record.function_queries[424].output_at(__i).as_ptr() as *const [G; OUT_424]) }; __ret }, _ => aiur_fn_424(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __ret: [G; OUT_427] = [__v_30]; - record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_426] = [__v_30]; + record.function_queries[426].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_28: G = G::from_u64(8); let __v_29: G = { let __values: [G; 4] = [__v_28, __v_0, __v_1, __v_5]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_29, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_29, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __ret: [G; OUT_427] = [__v_30]; - record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_426] = [__v_30]; + record.function_queries[426].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -38251,10 +38205,10 @@ fn aiur_fn_427( _ => { let __v_15: G = G::from_u64(8); let __v_16: G = { let __values: [G; 4] = [__v_15, __v_0, __v_1, __v_5]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_16, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_16, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_427] = [__v_17]; - record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_426] = [__v_17]; + record.function_queries[426].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -38263,32 +38217,32 @@ fn aiur_fn_427( }) } -const INPUT_SIZE_428: usize = 5; -const IN_428: usize = 5; -const OUT_428: usize = 1; -fn aiur_fn_428( - inp: [G; IN_428], +const INPUT_SIZE_427: usize = 5; +const IN_427: usize = 5; +const OUT_427: usize = 1; +fn aiur_fn_427( + inp: [G; IN_427], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_428], ExecError> { +) -> Result<[G; OUT_427], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_390] = { let __args: [G; IN_390] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[390].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[390].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[390].bump_multiplicity(__i); } let __ret: [G; OUT_390] = unsafe { *(record.function_queries[390].output_at(__i).as_ptr() as *const [G; OUT_390]) }; __ret }, _ => aiur_fn_390(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_389] = { let __args: [G; IN_389] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[389].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[389].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[389].bump_multiplicity(__i); } let __ret: [G; OUT_389] = unsafe { *(record.function_queries[389].output_at(__i).as_ptr() as *const [G; OUT_389]) }; __ret }, _ => aiur_fn_389(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __mc_out___mc_0: [G; 2] = '__mc_0: { match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_391] = { let __args: [G; IN_391] = [__v_0, __v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[391].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[391].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[391].bump_multiplicity(__i); } let __ret: [G; OUT_391] = unsafe { *(record.function_queries[391].output_at(__i).as_ptr() as *const [G; OUT_391]) }; __ret }, _ => aiur_fn_391(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_390] = { let __args: [G; IN_390] = [__v_0, __v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[390].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[390].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[390].bump_multiplicity(__i); } let __ret: [G; OUT_390] = unsafe { *(record.function_queries[390].output_at(__i).as_ptr() as *const [G; OUT_390]) }; __ret }, _ => aiur_fn_390(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; break '__mc_0 [__v_8, __v_9]; @@ -38304,7 +38258,7 @@ fn aiur_fn_428( } }, _ => { - let __r_arr: [G; OUT_391] = { let __args: [G; IN_391] = [__v_0, __v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[391].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[391].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[391].bump_multiplicity(__i); } let __ret: [G; OUT_391] = unsafe { *(record.function_queries[391].output_at(__i).as_ptr() as *const [G; OUT_391]) }; __ret }, _ => aiur_fn_391(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_390] = { let __args: [G; IN_390] = [__v_0, __v_1, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[390].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[390].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[390].bump_multiplicity(__i); } let __ret: [G; OUT_390] = unsafe { *(record.function_queries[390].output_at(__i).as_ptr() as *const [G; OUT_390]) }; __ret }, _ => aiur_fn_390(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; break '__mc_0 [__v_6, __v_7]; @@ -38315,19 +38269,19 @@ fn aiur_fn_428( let __v_7: G = __mc_out___mc_0[1]; match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_7, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_7, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_8]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_8]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __ret: [G; OUT_428] = [__v_7]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_7]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_8.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_9: G = __loaded[0]; @@ -38344,43 +38298,43 @@ fn aiur_fn_428( let __v_20: G = __loaded[11]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_397] = { let __args: [G; IN_397] = [__v_12, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[397].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[397].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[397].bump_multiplicity(__i); } let __ret: [G; OUT_397] = unsafe { *(record.function_queries[397].output_at(__i).as_ptr() as *const [G; OUT_397]) }; __ret }, _ => aiur_fn_397(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_396] = { let __args: [G; IN_396] = [__v_12, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[396].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[396].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[396].bump_multiplicity(__i); } let __ret: [G; OUT_396] = unsafe { *(record.function_queries[396].output_at(__i).as_ptr() as *const [G; OUT_396]) }; __ret }, _ => aiur_fn_396(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = __r_arr[1]; match __v_21.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_22, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_22, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_23]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_23]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_23]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_23]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 4u64 => { - let __r_arr: [G; OUT_392] = { let __args: [G; IN_392] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[392].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[392].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[392].bump_multiplicity(__i); } let __ret: [G; OUT_392] = unsafe { *(record.function_queries[392].output_at(__i).as_ptr() as *const [G; OUT_392]) }; __ret }, _ => aiur_fn_392(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_391] = { let __args: [G; IN_391] = [__v_0, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[391].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[391].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[391].bump_multiplicity(__i); } let __ret: [G; OUT_391] = unsafe { *(record.function_queries[391].output_at(__i).as_ptr() as *const [G; OUT_391]) }; __ret }, _ => aiur_fn_391(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = __r_arr[1]; match __v_21.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_22, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_22, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_23]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_23]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_23]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_23]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -38391,10 +38345,10 @@ fn aiur_fn_428( let __v_23: G = (__v_22 + __v_13); let __mc_out___mc_1: [G; 2] = '__mc_1: { match __v_17.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_408] = { let __args: [G; IN_408] = [__v_11, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[408].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[408].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[408].bump_multiplicity(__i); } let __ret: [G; OUT_408] = unsafe { *(record.function_queries[408].output_at(__i).as_ptr() as *const [G; OUT_408]) }; __ret }, _ => aiur_fn_408(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_407] = { let __args: [G; IN_407] = [__v_11, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[407].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[407].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[407].bump_multiplicity(__i); } let __ret: [G; OUT_407] = unsafe { *(record.function_queries[407].output_at(__i).as_ptr() as *const [G; OUT_407]) }; __ret }, _ => aiur_fn_407(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = __r_arr[1]; - let __r_arr: [G; OUT_400] = { let __args: [G; IN_400] = [__v_1, __v_3, __v_12, __v_14, __v_15, __v_13, __v_16, __v_25, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[400].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[400].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[400].bump_multiplicity(__i); } let __ret: [G; OUT_400] = unsafe { *(record.function_queries[400].output_at(__i).as_ptr() as *const [G; OUT_400]) }; __ret }, _ => aiur_fn_400(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_399] = { let __args: [G; IN_399] = [__v_1, __v_3, __v_12, __v_14, __v_15, __v_13, __v_16, __v_25, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[399].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[399].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[399].bump_multiplicity(__i); } let __ret: [G; OUT_399] = unsafe { *(record.function_queries[399].output_at(__i).as_ptr() as *const [G; OUT_399]) }; __ret }, _ => aiur_fn_399(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = __r_arr[1]; break '__mc_1 [__v_26, __v_27]; @@ -38409,46 +38363,46 @@ fn aiur_fn_428( let __v_25: G = __mc_out___mc_1[1]; match __v_24.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_428] = [__v_25]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_25]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_11, __v_12, __v_14, __v_15, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_11, __v_12, __v_14, __v_15, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __r_arr: [G; OUT_404] = { let __args: [G; IN_404] = [__v_1, __v_3, __v_12, __v_14, __v_15, __v_13, __v_16, __v_4, __v_2, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[404].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[404].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[404].bump_multiplicity(__i); } let __ret: [G; OUT_404] = unsafe { *(record.function_queries[404].output_at(__i).as_ptr() as *const [G; OUT_404]) }; __ret }, _ => aiur_fn_404(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_403] = { let __args: [G; IN_403] = [__v_1, __v_3, __v_12, __v_14, __v_15, __v_13, __v_16, __v_4, __v_2, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[403].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[403].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[403].bump_multiplicity(__i); } let __ret: [G; OUT_403] = unsafe { *(record.function_queries[403].output_at(__i).as_ptr() as *const [G; OUT_403]) }; __ret }, _ => aiur_fn_403(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = __r_arr[1]; match __v_27.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_28, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_28, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_29]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_29]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { match __v_17.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_428] = [__v_28]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_28]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_407] = { let __args: [G; IN_407] = [__v_11, __v_1, __v_3, __v_12, __v_14, __v_15, __v_13, __v_16, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[407].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[407].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[407].bump_multiplicity(__i); } let __ret: [G; OUT_407] = unsafe { *(record.function_queries[407].output_at(__i).as_ptr() as *const [G; OUT_407]) }; __ret }, _ => aiur_fn_407(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_406] = { let __args: [G; IN_406] = [__v_11, __v_1, __v_3, __v_12, __v_14, __v_15, __v_13, __v_16, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[406].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[406].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[406].bump_multiplicity(__i); } let __ret: [G; OUT_406] = unsafe { *(record.function_queries[406].output_at(__i).as_ptr() as *const [G; OUT_406]) }; __ret }, _ => aiur_fn_406(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = __r_arr[1]; match __v_29.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_30, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_30, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_31]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_31]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_428] = [__v_28]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_28]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -38456,10 +38410,10 @@ fn aiur_fn_428( } }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_29]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_29]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -38467,10 +38421,10 @@ fn aiur_fn_428( } }, _ => { - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_428] = [__v_21]; - record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_427] = [__v_21]; + record.function_queries[427].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -38479,40 +38433,40 @@ fn aiur_fn_428( }) } -const INPUT_SIZE_429: usize = 2; -const IN_429: usize = 2; -const OUT_429: usize = 1; -fn aiur_fn_429( - inp: [G; IN_429], +const INPUT_SIZE_428: usize = 2; +const IN_428: usize = 2; +const OUT_428: usize = 1; +fn aiur_fn_428( + inp: [G; IN_428], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_429], ExecError> { +) -> Result<[G; OUT_428], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(1); let __v_4: G = (__v_1 + __v_3); let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_2, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_2, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_429] = [__v_6]; - record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_428] = [__v_6]; + record.function_queries[428].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_430: usize = 12; -const IN_430: usize = 12; -const OUT_430: usize = 1; -fn aiur_fn_430( - inp: [G; IN_430], +const INPUT_SIZE_429: usize = 12; +const IN_429: usize = 12; +const OUT_429: usize = 1; +fn aiur_fn_429( + inp: [G; IN_429], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_430], ExecError> { +) -> Result<[G; OUT_429], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -38528,43 +38482,43 @@ fn aiur_fn_430( let __v_11: G = inp[11]; match __v_0.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __ret: [G; OUT_430] = [__v_1]; - record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_429] = [__v_1]; + record.function_queries[429].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -38574,15 +38528,15 @@ fn aiur_fn_430( }) } -const INPUT_SIZE_431: usize = 12; -const IN_431: usize = 12; -const OUT_431: usize = 1; -fn aiur_fn_431( - inp: [G; IN_431], +const INPUT_SIZE_430: usize = 12; +const IN_430: usize = 12; +const OUT_430: usize = 1; +fn aiur_fn_430( + inp: [G; IN_430], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_431], ExecError> { +) -> Result<[G; OUT_430], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -38598,43 +38552,43 @@ fn aiur_fn_431( let __v_11: G = inp[11]; match __v_0.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __ret: [G; OUT_431] = [__v_2]; - record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_430] = [__v_2]; + record.function_queries[430].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -38644,21 +38598,21 @@ fn aiur_fn_431( }) } -const INPUT_SIZE_432: usize = 2; -const IN_432: usize = 2; -const OUT_432: usize = 1; -fn aiur_fn_432( - inp: [G; IN_432], +const INPUT_SIZE_431: usize = 2; +const IN_431: usize = 2; +const OUT_431: usize = 1; +fn aiur_fn_431( + inp: [G; IN_431], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_432], ExecError> { +) -> Result<[G; OUT_431], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -38667,15 +38621,15 @@ fn aiur_fn_432( let __v_7: G = __loaded[3]; match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_5 + __v_9); let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_432] = [__v_12]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_12]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -38683,16 +38637,16 @@ fn aiur_fn_432( let __v_9: G = G::from_u64(1); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 3] = [__v_9, __v_5, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_8, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_432] = [__v_14]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_14]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_8.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_9: G = __loaded[0]; @@ -38707,23 +38661,23 @@ fn aiur_fn_432( let __v_18: G = __loaded[9]; let __v_19: G = __loaded[10]; let __v_20: G = __loaded[11]; - let __r_arr: [G; OUT_430] = { let __args: [G; IN_430] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[430].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[430].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[430].bump_multiplicity(__i); } let __ret: [G; OUT_430] = unsafe { *(record.function_queries[430].output_at(__i).as_ptr() as *const [G; OUT_430]) }; __ret }, _ => aiur_fn_430(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_429] = { let __args: [G; IN_429] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[429].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[429].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[429].bump_multiplicity(__i); } let __ret: [G; OUT_429] = unsafe { *(record.function_queries[429].output_at(__i).as_ptr() as *const [G; OUT_429]) }; __ret }, _ => aiur_fn_429(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; if (__v_22 != __v_21) { return Err(ExecError::AssertEqMismatch { lhs: __v_22.as_canonical_u64(), rhs: __v_21.as_canonical_u64(), msg: Some("Const applied to wrong number of universe levels".to_string()) }); } - let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_430] = { let __args: [G; IN_430] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[430].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[430].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[430].bump_multiplicity(__i); } let __ret: [G; OUT_430] = unsafe { *(record.function_queries[430].output_at(__i).as_ptr() as *const [G; OUT_430]) }; __ret }, _ => aiur_fn_430(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_23, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_23, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __ret: [G; OUT_432] = [__v_24]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_24]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_8.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_9: G = __loaded[0]; @@ -38733,14 +38687,14 @@ fn aiur_fn_432( match __v_9.as_canonical_u64() { 5u64 => { let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_11, __v_6, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_11, __v_6, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_432] = [__v_14]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_14]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_13.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_14: G = __loaded[0]; @@ -38750,10 +38704,10 @@ fn aiur_fn_432( match __v_14.as_canonical_u64() { 5u64 => { let __v_18: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_16, __v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_16, __v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __ret: [G; OUT_432] = [__v_19]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_19]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -38766,67 +38720,67 @@ fn aiur_fn_432( 4u64 => { let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 3] = [__v_8, __v_5, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(5); let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_11, __v_5, __v_10, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_432] = [__v_13]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_13]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_433] = { let __args: [G; IN_433] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[433].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[433].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[433].bump_multiplicity(__i); } let __ret: [G; OUT_433] = unsafe { *(record.function_queries[433].output_at(__i).as_ptr() as *const [G; OUT_433]) }; __ret }, _ => aiur_fn_433(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 3] = [__v_9, __v_5, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_433] = { let __args: [G; IN_433] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[433].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[433].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[433].bump_multiplicity(__i); } let __ret: [G; OUT_433] = unsafe { *(record.function_queries[433].output_at(__i).as_ptr() as *const [G; OUT_433]) }; __ret }, _ => aiur_fn_433(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(1); - let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_432] = [__v_15]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_15]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_7, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_7, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_432] = [__v_10]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_10]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { match __v_5.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(2); - let __r_arr: [G; OUT_381] = { let __args: [G; IN_381] = []; let __cu = unconstrained; let __hit = record.function_queries[381].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[381].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[381].bump_multiplicity(__i); } let __ret: [G; OUT_381] = unsafe { *(record.function_queries[381].output_at(__i).as_ptr() as *const [G; OUT_381]) }; __ret }, _ => aiur_fn_381(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_380] = { let __args: [G; IN_380] = []; let __cu = unconstrained; let __hit = record.function_queries[380].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[380].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[380].bump_multiplicity(__i); } let __ret: [G; OUT_380] = unsafe { *(record.function_queries[380].output_at(__i).as_ptr() as *const [G; OUT_380]) }; __ret }, _ => aiur_fn_380(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 3] = [__v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_8, __v_9, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_432] = [__v_14]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_14]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_8: G = G::from_u64(2); - let __r_arr: [G; OUT_218] = { let __args: [G; IN_218] = []; let __cu = unconstrained; let __hit = record.function_queries[218].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[218].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[218].bump_multiplicity(__i); } let __ret: [G; OUT_218] = unsafe { *(record.function_queries[218].output_at(__i).as_ptr() as *const [G; OUT_218]) }; __ret }, _ => aiur_fn_218(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_217] = { let __args: [G; IN_217] = []; let __cu = unconstrained; let __hit = record.function_queries[217].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[217].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[217].bump_multiplicity(__i); } let __ret: [G; OUT_217] = unsafe { *(record.function_queries[217].output_at(__i).as_ptr() as *const [G; OUT_217]) }; __ret }, _ => aiur_fn_217(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 3] = [__v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_8, __v_9, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_432] = [__v_14]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_14]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -38835,9 +38789,9 @@ fn aiur_fn_432( } }, 8u64 => { - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; @@ -38852,7 +38806,7 @@ fn aiur_fn_432( if (__v_13 != __v_5) { return Err(ExecError::AssertEqMismatch { lhs: __v_13.as_canonical_u64(), rhs: __v_5.as_canonical_u64(), msg: Some("projection's structure type differs from the value's head".to_string()) }); } - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_16.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_17: G = __loaded[0]; @@ -38874,7 +38828,7 @@ fn aiur_fn_432( return Err(ExecError::AssertEqMismatch { lhs: __v_22.as_canonical_u64(), rhs: __v_29.as_canonical_u64(), msg: Some("projection on an inductive with more than one constructor".to_string()) }); } let __v_30: G = G::from_u64(0); - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_24, __v_25, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_24, __v_25, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_31.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_32: G = __loaded[0]; @@ -38891,15 +38845,15 @@ fn aiur_fn_432( let __v_43: G = __loaded[11]; match __v_32.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_34, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_34, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; - let __r_arr: [G; OUT_435] = { let __args: [G; IN_435] = [__v_44, __v_11, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[435].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[435].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[435].bump_multiplicity(__i); } let __ret: [G; OUT_435] = unsafe { *(record.function_queries[435].output_at(__i).as_ptr() as *const [G; OUT_435]) }; __ret }, _ => aiur_fn_435(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_44, __v_11, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; let __v_46: G = G::from_u64(0); - let __r_arr: [G; OUT_436] = { let __args: [G; IN_436] = [__v_45, __v_6, __v_46, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[436].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[436].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[436].bump_multiplicity(__i); } let __ret: [G; OUT_436] = unsafe { *(record.function_queries[436].output_at(__i).as_ptr() as *const [G; OUT_436]) }; __ret }, _ => aiur_fn_436(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_435] = { let __args: [G; IN_435] = [__v_45, __v_6, __v_46, __v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[435].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[435].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[435].bump_multiplicity(__i); } let __ret: [G; OUT_435] = unsafe { *(record.function_queries[435].output_at(__i).as_ptr() as *const [G; OUT_435]) }; __ret }, _ => aiur_fn_435(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; - let __ret: [G; OUT_432] = [__v_47]; - record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_431] = [__v_47]; + record.function_queries[431].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -38924,15 +38878,15 @@ fn aiur_fn_432( }) } -const INPUT_SIZE_433: usize = 2; -const IN_433: usize = 2; -const OUT_433: usize = 1; -fn aiur_fn_433( - inp: [G; IN_433], +const INPUT_SIZE_432: usize = 2; +const IN_432: usize = 2; +const OUT_432: usize = 1; +fn aiur_fn_432( + inp: [G; IN_432], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_433], ExecError> { +) -> Result<[G; OUT_432], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -38943,15 +38897,15 @@ fn aiur_fn_433( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_3 + __v_7); let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_6, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_6, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_433] = [__v_10]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_10]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -38959,16 +38913,16 @@ fn aiur_fn_433( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_3, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_6, __v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_433] = [__v_12]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_12]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_6.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_7: G = __loaded[0]; @@ -38983,23 +38937,23 @@ fn aiur_fn_433( let __v_16: G = __loaded[9]; let __v_17: G = __loaded[10]; let __v_18: G = __loaded[11]; - let __r_arr: [G; OUT_430] = { let __args: [G; IN_430] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[430].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[430].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[430].bump_multiplicity(__i); } let __ret: [G; OUT_430] = unsafe { *(record.function_queries[430].output_at(__i).as_ptr() as *const [G; OUT_430]) }; __ret }, _ => aiur_fn_430(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_429] = { let __args: [G; IN_429] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[429].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[429].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[429].bump_multiplicity(__i); } let __ret: [G; OUT_429] = unsafe { *(record.function_queries[429].output_at(__i).as_ptr() as *const [G; OUT_429]) }; __ret }, _ => aiur_fn_429(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; if (__v_20 != __v_19) { return Err(ExecError::AssertEqMismatch { lhs: __v_20.as_canonical_u64(), rhs: __v_19.as_canonical_u64(), msg: Some("Const applied to wrong number of universe levels".to_string()) }); } - let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_430] = { let __args: [G; IN_430] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[430].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[430].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[430].bump_multiplicity(__i); } let __ret: [G; OUT_430] = unsafe { *(record.function_queries[430].output_at(__i).as_ptr() as *const [G; OUT_430]) }; __ret }, _ => aiur_fn_430(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_433] = [__v_22]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_22]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_6.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_7: G = __loaded[0]; @@ -39009,14 +38963,14 @@ fn aiur_fn_433( match __v_7.as_canonical_u64() { 5u64 => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_9, __v_4, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_9, __v_4, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_433] = [__v_12]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_12]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_11.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_12: G = __loaded[0]; @@ -39026,10 +38980,10 @@ fn aiur_fn_433( match __v_12.as_canonical_u64() { 5u64 => { let __v_16: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_14, __v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_14, __v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_433] = [__v_17]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_17]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39042,67 +38996,67 @@ fn aiur_fn_433( 4u64 => { let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 3] = [__v_6, __v_3, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(5); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_9, __v_3, __v_8, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_433] = [__v_11]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_11]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_433] = { let __args: [G; IN_433] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[433].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[433].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[433].bump_multiplicity(__i); } let __ret: [G; OUT_433] = unsafe { *(record.function_queries[433].output_at(__i).as_ptr() as *const [G; OUT_433]) }; __ret }, _ => aiur_fn_433(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 3] = [__v_7, __v_3, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_433] = { let __args: [G; IN_433] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[433].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[433].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[433].bump_multiplicity(__i); } let __ret: [G; OUT_433] = unsafe { *(record.function_queries[433].output_at(__i).as_ptr() as *const [G; OUT_433]) }; __ret }, _ => aiur_fn_433(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(1); - let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_10, __v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_433] = [__v_13]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_13]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_5, __v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_5, __v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_433] = [__v_8]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_8]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { match __v_3.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(2); - let __r_arr: [G; OUT_381] = { let __args: [G; IN_381] = []; let __cu = unconstrained; let __hit = record.function_queries[381].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[381].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[381].bump_multiplicity(__i); } let __ret: [G; OUT_381] = unsafe { *(record.function_queries[381].output_at(__i).as_ptr() as *const [G; OUT_381]) }; __ret }, _ => aiur_fn_381(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_380] = { let __args: [G; IN_380] = []; let __cu = unconstrained; let __hit = record.function_queries[380].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[380].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[380].bump_multiplicity(__i); } let __ret: [G; OUT_380] = unsafe { *(record.function_queries[380].output_at(__i).as_ptr() as *const [G; OUT_380]) }; __ret }, _ => aiur_fn_380(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_6, __v_7, __v_10, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_433] = [__v_12]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_12]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_6: G = G::from_u64(2); - let __r_arr: [G; OUT_218] = { let __args: [G; IN_218] = []; let __cu = unconstrained; let __hit = record.function_queries[218].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[218].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[218].bump_multiplicity(__i); } let __ret: [G; OUT_218] = unsafe { *(record.function_queries[218].output_at(__i).as_ptr() as *const [G; OUT_218]) }; __ret }, _ => aiur_fn_218(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_217] = { let __args: [G; IN_217] = []; let __cu = unconstrained; let __hit = record.function_queries[217].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[217].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[217].bump_multiplicity(__i); } let __ret: [G; OUT_217] = unsafe { *(record.function_queries[217].output_at(__i).as_ptr() as *const [G; OUT_217]) }; __ret }, _ => aiur_fn_217(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_6, __v_7, __v_10, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_433] = [__v_12]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_12]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39111,9 +39065,9 @@ fn aiur_fn_433( } }, 8u64 => { - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; @@ -39128,7 +39082,7 @@ fn aiur_fn_433( if (__v_11 != __v_3) { return Err(ExecError::AssertEqMismatch { lhs: __v_11.as_canonical_u64(), rhs: __v_3.as_canonical_u64(), msg: Some("projection's structure type differs from the value's head".to_string()) }); } - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_14.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_15: G = __loaded[0]; @@ -39150,7 +39104,7 @@ fn aiur_fn_433( return Err(ExecError::AssertEqMismatch { lhs: __v_20.as_canonical_u64(), rhs: __v_27.as_canonical_u64(), msg: Some("projection on an inductive with more than one constructor".to_string()) }); } let __v_28: G = G::from_u64(0); - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_22, __v_23, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_22, __v_23, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_29.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_30: G = __loaded[0]; @@ -39167,15 +39121,15 @@ fn aiur_fn_433( let __v_41: G = __loaded[11]; match __v_30.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_32, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_32, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_42: G = __r_arr[0]; - let __r_arr: [G; OUT_435] = { let __args: [G; IN_435] = [__v_42, __v_9, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[435].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[435].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[435].bump_multiplicity(__i); } let __ret: [G; OUT_435] = unsafe { *(record.function_queries[435].output_at(__i).as_ptr() as *const [G; OUT_435]) }; __ret }, _ => aiur_fn_435(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_42, __v_9, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; let __v_44: G = G::from_u64(0); - let __r_arr: [G; OUT_436] = { let __args: [G; IN_436] = [__v_43, __v_4, __v_44, __v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[436].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[436].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[436].bump_multiplicity(__i); } let __ret: [G; OUT_436] = unsafe { *(record.function_queries[436].output_at(__i).as_ptr() as *const [G; OUT_436]) }; __ret }, _ => aiur_fn_436(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_435] = { let __args: [G; IN_435] = [__v_43, __v_4, __v_44, __v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[435].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[435].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[435].bump_multiplicity(__i); } let __ret: [G; OUT_435] = unsafe { *(record.function_queries[435].output_at(__i).as_ptr() as *const [G; OUT_435]) }; __ret }, _ => aiur_fn_435(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; - let __ret: [G; OUT_433] = [__v_45]; - record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_432] = [__v_45]; + record.function_queries[432].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39200,19 +39154,19 @@ fn aiur_fn_433( }) } -const INPUT_SIZE_434: usize = 2; -const IN_434: usize = 2; -const OUT_434: usize = 1; -fn aiur_fn_434( - inp: [G; IN_434], +const INPUT_SIZE_433: usize = 2; +const IN_433: usize = 2; +const OUT_433: usize = 1; +fn aiur_fn_433( + inp: [G; IN_433], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_434], ExecError> { +) -> Result<[G; OUT_433], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_2.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_3: G = __loaded[0]; @@ -39221,12 +39175,12 @@ fn aiur_fn_434( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_434] = [__v_4]; - record.function_queries[434].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_433] = [__v_4]; + record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_2, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_2, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -39235,8 +39189,8 @@ fn aiur_fn_434( let __v_11: G = __loaded[3]; match __v_8.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_434] = [__v_9]; - record.function_queries[434].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_433] = [__v_9]; + record.function_queries[433].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39248,23 +39202,23 @@ fn aiur_fn_434( }) } -const INPUT_SIZE_435: usize = 3; -const IN_435: usize = 3; -const OUT_435: usize = 1; -fn aiur_fn_435( - inp: [G; IN_435], +const INPUT_SIZE_434: usize = 3; +const IN_434: usize = 3; +const OUT_434: usize = 1; +fn aiur_fn_434( + inp: [G; IN_434], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_435], ExecError> { +) -> Result<[G; OUT_434], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_2.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_435] = [__v_0]; - record.function_queries[435].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_434] = [__v_0]; + record.function_queries[434].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39282,14 +39236,14 @@ fn aiur_fn_435( match __v_7.as_canonical_u64() { 0u64 => { let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_5, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_5, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(1); let __v_13: G = (__v_2 - __v_12); - let __r_arr: [G; OUT_435] = { let __args: [G; IN_435] = [__v_11, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[435].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[435].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[435].bump_multiplicity(__i); } let __ret: [G; OUT_435] = unsafe { *(record.function_queries[435].output_at(__i).as_ptr() as *const [G; OUT_435]) }; __ret }, _ => aiur_fn_435(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_11, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_435] = [__v_14]; - record.function_queries[435].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_434] = [__v_14]; + record.function_queries[434].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39306,15 +39260,15 @@ fn aiur_fn_435( }) } -const INPUT_SIZE_436: usize = 5; -const IN_436: usize = 5; -const OUT_436: usize = 1; -fn aiur_fn_436( - inp: [G; IN_436], +const INPUT_SIZE_435: usize = 5; +const IN_435: usize = 5; +const OUT_435: usize = 1; +fn aiur_fn_435( + inp: [G; IN_435], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_436], ExecError> { +) -> Result<[G; OUT_435], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -39331,22 +39285,22 @@ fn aiur_fn_436( let __v_9: G = (__v_1 - __v_2); match __v_9.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_436] = [__v_6]; - record.function_queries[436].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_435] = [__v_6]; + record.function_queries[435].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(8); let __v_11: G = { let __values: [G; 4] = [__v_10, __v_3, __v_2, __v_4]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_7, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_7, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(1); let __v_15: G = (__v_2 + __v_14); - let __r_arr: [G; OUT_436] = { let __args: [G; IN_436] = [__v_13, __v_1, __v_15, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[436].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[436].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[436].bump_multiplicity(__i); } let __ret: [G; OUT_436] = unsafe { *(record.function_queries[436].output_at(__i).as_ptr() as *const [G; OUT_436]) }; __ret }, _ => aiur_fn_436(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_435] = { let __args: [G; IN_435] = [__v_13, __v_1, __v_15, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[435].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[435].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[435].bump_multiplicity(__i); } let __ret: [G; OUT_435] = unsafe { *(record.function_queries[435].output_at(__i).as_ptr() as *const [G; OUT_435]) }; __ret }, _ => aiur_fn_435(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_436] = [__v_16]; - record.function_queries[436].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_435] = [__v_16]; + record.function_queries[435].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39358,15 +39312,15 @@ fn aiur_fn_436( }) } -const INPUT_SIZE_437: usize = 2; -const IN_437: usize = 2; -const OUT_437: usize = 1; -fn aiur_fn_437( - inp: [G; IN_437], +const INPUT_SIZE_436: usize = 2; +const IN_436: usize = 2; +const OUT_436: usize = 1; +fn aiur_fn_436( + inp: [G; IN_436], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_437], ExecError> { +) -> Result<[G; OUT_436], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -39383,14 +39337,14 @@ fn aiur_fn_437( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_437] = [__v_8]; - record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_436] = [__v_8]; + record.function_queries[436].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_437] = [__v_8]; - record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_436] = [__v_8]; + record.function_queries[436].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39403,25 +39357,25 @@ fn aiur_fn_437( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_437] = [__v_8]; - record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_436] = [__v_8]; + record.function_queries[436].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 0u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_437] = [__v_9]; - record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_436] = [__v_9]; + record.function_queries[436].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_436] = { let __args: [G; IN_436] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[436].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[436].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[436].bump_multiplicity(__i); } let __ret: [G; OUT_436] = unsafe { *(record.function_queries[436].output_at(__i).as_ptr() as *const [G; OUT_436]) }; __ret }, _ => aiur_fn_436(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_437] = [__v_9]; - record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_436] = [__v_9]; + record.function_queries[436].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39438,15 +39392,15 @@ fn aiur_fn_437( }) } -const INPUT_SIZE_438: usize = 3; -const IN_438: usize = 3; -const OUT_438: usize = 1; -fn aiur_fn_438( - inp: [G; IN_438], +const INPUT_SIZE_437: usize = 3; +const IN_437: usize = 3; +const OUT_437: usize = 1; +fn aiur_fn_437( + inp: [G; IN_437], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_438], ExecError> { +) -> Result<[G; OUT_437], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -39455,33 +39409,33 @@ fn aiur_fn_438( match __v_3.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_438] = [__v_4]; - record.function_queries[438].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_437] = [__v_4]; + record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_343] = { let __args: [G; IN_343] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[343].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[343].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[343].bump_multiplicity(__i); } let __ret: [G; OUT_343] = unsafe { *(record.function_queries[343].output_at(__i).as_ptr() as *const [G; OUT_343]) }; __ret }, _ => aiur_fn_343(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_342] = { let __args: [G; IN_342] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[342].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[342].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[342].bump_multiplicity(__i); } let __ret: [G; OUT_342] = unsafe { *(record.function_queries[342].output_at(__i).as_ptr() as *const [G; OUT_342]) }; __ret }, _ => aiur_fn_342(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_440] = { let __args: [G; IN_440] = [__v_0, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[440].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[440].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[440].bump_multiplicity(__i); } let __ret: [G; OUT_440] = unsafe { *(record.function_queries[440].output_at(__i).as_ptr() as *const [G; OUT_440]) }; __ret }, _ => aiur_fn_440(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_439] = { let __args: [G; IN_439] = [__v_0, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[439].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[439].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[439].bump_multiplicity(__i); } let __ret: [G; OUT_439] = unsafe { *(record.function_queries[439].output_at(__i).as_ptr() as *const [G; OUT_439]) }; __ret }, _ => aiur_fn_439(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_438] = [__v_10]; - record.function_queries[438].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_437] = [__v_10]; + record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_439] = { let __args: [G; IN_439] = [__v_0, __v_1, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[439].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[439].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[439].bump_multiplicity(__i); } let __ret: [G; OUT_439] = unsafe { *(record.function_queries[439].output_at(__i).as_ptr() as *const [G; OUT_439]) }; __ret }, _ => aiur_fn_439(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_0, __v_1, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_438] = [__v_7]; - record.function_queries[438].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_437] = [__v_7]; + record.function_queries[437].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39490,73 +39444,73 @@ fn aiur_fn_438( }) } -const INPUT_SIZE_439: usize = 4; -const IN_439: usize = 4; -const OUT_439: usize = 1; -fn aiur_fn_439( - inp: [G; IN_439], +const INPUT_SIZE_438: usize = 4; +const IN_438: usize = 4; +const OUT_438: usize = 1; +fn aiur_fn_438( + inp: [G; IN_438], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_439], ExecError> { +) -> Result<[G; OUT_438], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_5, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_440] = { let __args: [G; IN_440] = [__v_0, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[440].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[440].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[440].bump_multiplicity(__i); } let __ret: [G; OUT_440] = unsafe { *(record.function_queries[440].output_at(__i).as_ptr() as *const [G; OUT_440]) }; __ret }, _ => aiur_fn_440(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_439] = { let __args: [G; IN_439] = [__v_0, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[439].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[439].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[439].bump_multiplicity(__i); } let __ret: [G; OUT_439] = unsafe { *(record.function_queries[439].output_at(__i).as_ptr() as *const [G; OUT_439]) }; __ret }, _ => aiur_fn_439(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_439] = [__v_12]; - record.function_queries[439].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_438] = [__v_12]; + record.function_queries[438].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_0, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_0, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_1, __v_10, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_1, __v_10, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = (__v_3 - __v_10); - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_440] = { let __args: [G; IN_440] = [__v_12, __v_14, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[440].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[440].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[440].bump_multiplicity(__i); } let __ret: [G; OUT_440] = unsafe { *(record.function_queries[440].output_at(__i).as_ptr() as *const [G; OUT_440]) }; __ret }, _ => aiur_fn_440(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_439] = { let __args: [G; IN_439] = [__v_12, __v_14, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[439].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[439].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[439].bump_multiplicity(__i); } let __ret: [G; OUT_439] = unsafe { *(record.function_queries[439].output_at(__i).as_ptr() as *const [G; OUT_439]) }; __ret }, _ => aiur_fn_439(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_439] = [__v_18]; - record.function_queries[439].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_438] = [__v_18]; + record.function_queries[438].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_440: usize = 3; -const IN_440: usize = 3; -const OUT_440: usize = 1; -fn aiur_fn_440( - inp: [G; IN_440], +const INPUT_SIZE_439: usize = 3; +const IN_439: usize = 3; +const OUT_439: usize = 1; +fn aiur_fn_439( + inp: [G; IN_439], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_440], ExecError> { +) -> Result<[G; OUT_439], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -39564,65 +39518,65 @@ fn aiur_fn_440( let __v_3: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_1.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_441] = { let __args: [G; IN_441] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[441].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[441].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[441].bump_multiplicity(__i); } let __ret: [G; OUT_441] = unsafe { *(record.function_queries[441].output_at(__i).as_ptr() as *const [G; OUT_441]) }; __ret }, _ => aiur_fn_441(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_440] = { let __args: [G; IN_440] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[440].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[440].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[440].bump_multiplicity(__i); } let __ret: [G; OUT_440] = unsafe { *(record.function_queries[440].output_at(__i).as_ptr() as *const [G; OUT_440]) }; __ret }, _ => aiur_fn_440(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_440] = [__v_4]; - record.function_queries[440].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_439] = [__v_4]; + record.function_queries[439].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_441] = { let __args: [G; IN_441] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[441].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[441].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[441].bump_multiplicity(__i); } let __ret: [G; OUT_441] = unsafe { *(record.function_queries[441].output_at(__i).as_ptr() as *const [G; OUT_441]) }; __ret }, _ => aiur_fn_441(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_440] = { let __args: [G; IN_440] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[440].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[440].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[440].bump_multiplicity(__i); } let __ret: [G; OUT_440] = unsafe { *(record.function_queries[440].output_at(__i).as_ptr() as *const [G; OUT_440]) }; __ret }, _ => aiur_fn_440(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_440] = [__v_4]; - record.function_queries[440].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_439] = [__v_4]; + record.function_queries[439].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_441: usize = 3; -const IN_441: usize = 3; -const OUT_441: usize = 1; -fn aiur_fn_441( - inp: [G; IN_441], +const INPUT_SIZE_440: usize = 3; +const IN_440: usize = 3; +const OUT_440: usize = 1; +fn aiur_fn_440( + inp: [G; IN_440], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_441], ExecError> { +) -> Result<[G; OUT_440], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_442] = { let __args: [G; IN_442] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[442].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[442].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[442].bump_multiplicity(__i); } let __ret: [G; OUT_442] = unsafe { *(record.function_queries[442].output_at(__i).as_ptr() as *const [G; OUT_442]) }; __ret }, _ => aiur_fn_442(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_441] = { let __args: [G; IN_441] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[441].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[441].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[441].bump_multiplicity(__i); } let __ret: [G; OUT_441] = unsafe { *(record.function_queries[441].output_at(__i).as_ptr() as *const [G; OUT_441]) }; __ret }, _ => aiur_fn_441(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_441] = [__v_4]; - record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_440] = [__v_4]; + record.function_queries[440].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_449] = { let __args: [G; IN_449] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[449].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[449].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[449].bump_multiplicity(__i); } let __ret: [G; OUT_449] = unsafe { *(record.function_queries[449].output_at(__i).as_ptr() as *const [G; OUT_449]) }; __ret }, _ => aiur_fn_449(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_448] = { let __args: [G; IN_448] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[448].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[448].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[448].bump_multiplicity(__i); } let __ret: [G; OUT_448] = unsafe { *(record.function_queries[448].output_at(__i).as_ptr() as *const [G; OUT_448]) }; __ret }, _ => aiur_fn_448(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_441] = [__v_4]; - record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_440] = [__v_4]; + record.function_queries[440].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_442: usize = 3; -const IN_442: usize = 3; -const OUT_442: usize = 1; -fn aiur_fn_442( - inp: [G; IN_442], +const INPUT_SIZE_441: usize = 3; +const IN_441: usize = 3; +const OUT_441: usize = 1; +fn aiur_fn_441( + inp: [G; IN_441], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_442], ExecError> { +) -> Result<[G; OUT_441], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -39650,33 +39604,33 @@ fn aiur_fn_442( let __v_15: G = (__v_8 - __v_12); match __v_15.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_436] = { let __args: [G; IN_436] = [__v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[436].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[436].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[436].bump_multiplicity(__i); } let __ret: [G; OUT_436] = unsafe { *(record.function_queries[436].output_at(__i).as_ptr() as *const [G; OUT_436]) }; __ret }, _ => aiur_fn_436(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; match __v_16.as_canonical_u64() { 0u64 => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_442] = [__v_17]; - record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_441] = [__v_17]; + record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = (__v_17 - __v_18); match __v_19.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_443] = { let __args: [G; IN_443] = [__v_4, __v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[443].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[443].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[443].bump_multiplicity(__i); } let __ret: [G; OUT_443] = unsafe { *(record.function_queries[443].output_at(__i).as_ptr() as *const [G; OUT_443]) }; __ret }, _ => aiur_fn_443(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_442] = { let __args: [G; IN_442] = [__v_4, __v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[442].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[442].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[442].bump_multiplicity(__i); } let __ret: [G; OUT_442] = unsafe { *(record.function_queries[442].output_at(__i).as_ptr() as *const [G; OUT_442]) }; __ret }, _ => aiur_fn_442(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_442] = [__v_20]; - record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_441] = [__v_20]; + record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_20: G = G::from_u64(0); - let __ret: [G; OUT_442] = [__v_20]; - record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_441] = [__v_20]; + record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39685,39 +39639,39 @@ fn aiur_fn_442( }, _ => { let __v_16: G = G::from_u64(0); - let __ret: [G; OUT_442] = [__v_16]; - record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_441] = [__v_16]; + record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_442] = [__v_15]; - record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_441] = [__v_15]; + record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_442] = [__v_11]; - record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_441] = [__v_11]; + record.function_queries[441].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_443: usize = 3; -const IN_443: usize = 3; -const OUT_443: usize = 1; -fn aiur_fn_443( - inp: [G; IN_443], +const INPUT_SIZE_442: usize = 3; +const IN_442: usize = 3; +const OUT_442: usize = 1; +fn aiur_fn_442( + inp: [G; IN_442], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_443], ExecError> { +) -> Result<[G; OUT_442], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -39735,14 +39689,14 @@ fn aiur_fn_443( match __v_6.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_443] = [__v_9]; - record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_442] = [__v_9]; + record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_443] = [__v_9]; - record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_442] = [__v_9]; + record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39755,25 +39709,25 @@ fn aiur_fn_443( match __v_6.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_443] = [__v_9]; - record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_442] = [__v_9]; + record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_4, __v_7, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_4, __v_7, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 0u64 => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_443] = [__v_10]; - record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_442] = [__v_10]; + record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_443] = { let __args: [G; IN_443] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[443].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[443].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[443].bump_multiplicity(__i); } let __ret: [G; OUT_443] = unsafe { *(record.function_queries[443].output_at(__i).as_ptr() as *const [G; OUT_443]) }; __ret }, _ => aiur_fn_443(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_442] = { let __args: [G; IN_442] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[442].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[442].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[442].bump_multiplicity(__i); } let __ret: [G; OUT_442] = unsafe { *(record.function_queries[442].output_at(__i).as_ptr() as *const [G; OUT_442]) }; __ret }, _ => aiur_fn_442(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_443] = [__v_10]; - record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_442] = [__v_10]; + record.function_queries[442].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39790,15 +39744,15 @@ fn aiur_fn_443( }) } -const INPUT_SIZE_444: usize = 1; -const IN_444: usize = 1; -const OUT_444: usize = 1; -fn aiur_fn_444( - inp: [G; IN_444], +const INPUT_SIZE_443: usize = 1; +const IN_443: usize = 1; +const OUT_443: usize = 1; +fn aiur_fn_443( + inp: [G; IN_443], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_444], ExecError> { +) -> Result<[G; OUT_443], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -39810,48 +39764,48 @@ fn aiur_fn_444( 7u64 => { match __v_2.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_133] = { let __args: [G; IN_133] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[133].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[133].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[133].bump_multiplicity(__i); } let __ret: [G; OUT_133] = unsafe { *(record.function_queries[133].output_at(__i).as_ptr() as *const [G; OUT_133]) }; __ret }, _ => aiur_fn_133(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_132] = { let __args: [G; IN_132] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[132].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[132].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[132].bump_multiplicity(__i); } let __ret: [G; OUT_132] = unsafe { *(record.function_queries[132].output_at(__i).as_ptr() as *const [G; OUT_132]) }; __ret }, _ => aiur_fn_132(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_444] = [__v_5]; - record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_443] = [__v_5]; + record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_444] = [__v_5]; - record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_443] = [__v_5]; + record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 2u64 => { - let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_146] = { let __args: [G; IN_146] = []; let __cu = unconstrained; let __hit = record.function_queries[146].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[146].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[146].bump_multiplicity(__i); } let __ret: [G; OUT_146] = unsafe { *(record.function_queries[146].output_at(__i).as_ptr() as *const [G; OUT_146]) }; __ret }, _ => aiur_fn_146(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_444] = [__v_6]; - record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_443] = [__v_6]; + record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_444] = [__v_5]; - record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_443] = [__v_5]; + record.function_queries[443].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_445: usize = 1; -const IN_445: usize = 1; -const OUT_445: usize = 3; -fn aiur_fn_445( - inp: [G; IN_445], +const INPUT_SIZE_444: usize = 1; +const IN_444: usize = 1; +const OUT_444: usize = 3; +fn aiur_fn_444( + inp: [G; IN_444], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_445], ExecError> { +) -> Result<[G; OUT_444], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -39867,10 +39821,10 @@ fn aiur_fn_445( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 10] = [__v_6, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_445] = [__v_5, __v_9, __v_3]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_5, __v_9, __v_3]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39878,8 +39832,8 @@ fn aiur_fn_445( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 10] = [__v_6, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_5, __v_0, __v_8]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_5, __v_0, __v_8]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39892,21 +39846,21 @@ fn aiur_fn_445( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_148] = { let __args: [G; IN_148] = []; let __cu = unconstrained; let __hit = record.function_queries[148].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[148].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[148].bump_multiplicity(__i); } let __ret: [G; OUT_148] = unsafe { *(record.function_queries[148].output_at(__i).as_ptr() as *const [G; OUT_148]) }; __ret }, _ => aiur_fn_148(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_147] = { let __args: [G; IN_147] = []; let __cu = unconstrained; let __hit = record.function_queries[147].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[147].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[147].bump_multiplicity(__i); } let __ret: [G; OUT_147] = unsafe { *(record.function_queries[147].output_at(__i).as_ptr() as *const [G; OUT_147]) }; __ret }, _ => aiur_fn_147(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_444] = { let __args: [G; IN_444] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[444].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[444].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[444].bump_multiplicity(__i); } let __ret: [G; OUT_444] = unsafe { *(record.function_queries[444].output_at(__i).as_ptr() as *const [G; OUT_444]) }; __ret }, _ => aiur_fn_444(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; let __v_14: G = G::from_u64(1); let __r_arr: [G; OUT_116] = { let __args: [G; IN_116] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[116].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[116].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[116].bump_multiplicity(__i); } let __ret: [G; OUT_116] = unsafe { *(record.function_queries[116].output_at(__i).as_ptr() as *const [G; OUT_116]) }; __ret }, _ => aiur_fn_116(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_445] = [__v_14, __v_12, __v_15]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_14, __v_12, __v_15]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -39914,8 +39868,8 @@ fn aiur_fn_445( let __v_12: G = G::from_u64(1); let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 10] = [__v_12, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_11, __v_0, __v_14]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_11, __v_0, __v_14]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39928,7 +39882,7 @@ fn aiur_fn_445( let __v_12: G = __loaded[3]; match __v_9.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_162] = { let __args: [G; IN_162] = []; let __cu = unconstrained; let __hit = record.function_queries[162].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[162].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[162].bump_multiplicity(__i); } let __ret: [G; OUT_162] = unsafe { *(record.function_queries[162].output_at(__i).as_ptr() as *const [G; OUT_162]) }; __ret }, _ => aiur_fn_162(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_161] = { let __args: [G; IN_161] = []; let __cu = unconstrained; let __hit = record.function_queries[161].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[161].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[161].bump_multiplicity(__i); } let __ret: [G; OUT_161] = unsafe { *(record.function_queries[161].output_at(__i).as_ptr() as *const [G; OUT_161]) }; __ret }, _ => aiur_fn_161(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_10, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; @@ -39943,7 +39897,7 @@ fn aiur_fn_445( 7u64 => { match __v_16.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_444] = { let __args: [G; IN_444] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[444].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[444].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[444].bump_multiplicity(__i); } let __ret: [G; OUT_444] = unsafe { *(record.function_queries[444].output_at(__i).as_ptr() as *const [G; OUT_444]) }; __ret }, _ => aiur_fn_444(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; let __v_21: G = __r_arr[2]; @@ -39952,14 +39906,14 @@ fn aiur_fn_445( let __v_22: G = G::from_u64(1); let __r_arr: [G; OUT_118] = { let __args: [G; IN_118] = [__v_21, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[118].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[118].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[118].bump_multiplicity(__i); } let __ret: [G; OUT_118] = unsafe { *(record.function_queries[118].output_at(__i).as_ptr() as *const [G; OUT_118]) }; __ret }, _ => aiur_fn_118(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_445] = [__v_22, __v_20, __v_23]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_22, __v_20, __v_23]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_22: G = G::from_u64(1); - let __ret: [G; OUT_445] = [__v_22, __v_7, __v_17]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_22, __v_7, __v_17]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39969,8 +39923,8 @@ fn aiur_fn_445( let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 10] = [__v_20, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_19, __v_0, __v_22]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_19, __v_0, __v_22]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39980,8 +39934,8 @@ fn aiur_fn_445( let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 10] = [__v_20, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_19, __v_0, __v_22]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_19, __v_0, __v_22]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -39991,8 +39945,8 @@ fn aiur_fn_445( let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 10] = [__v_16, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_15, __v_0, __v_18]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_15, __v_0, __v_18]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40002,8 +39956,8 @@ fn aiur_fn_445( let __v_14: G = G::from_u64(1); let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 10] = [__v_14, __v_15, __v_15, __v_15, __v_15, __v_15, __v_15, __v_15, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_13, __v_0, __v_16]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_13, __v_0, __v_16]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40013,8 +39967,8 @@ fn aiur_fn_445( let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 10] = [__v_10, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_9, __v_0, __v_12]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_9, __v_0, __v_12]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40024,46 +39978,46 @@ fn aiur_fn_445( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 10] = [__v_6, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_445] = [__v_5, __v_0, __v_8]; - record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_444] = [__v_5, __v_0, __v_8]; + record.function_queries[444].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_446: usize = 3; -const IN_446: usize = 3; -const OUT_446: usize = 2; -fn aiur_fn_446( - inp: [G; IN_446], +const INPUT_SIZE_445: usize = 3; +const IN_445: usize = 3; +const OUT_445: usize = 2; +fn aiur_fn_445( + inp: [G; IN_445], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_446], ExecError> { +) -> Result<[G; OUT_445], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_444] = { let __args: [G; IN_444] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[444].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[444].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[444].bump_multiplicity(__i); } let __ret: [G; OUT_444] = unsafe { *(record.function_queries[444].output_at(__i).as_ptr() as *const [G; OUT_444]) }; __ret }, _ => aiur_fn_444(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_443] = { let __args: [G; IN_443] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[443].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[443].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[443].bump_multiplicity(__i); } let __ret: [G; OUT_443] = unsafe { *(record.function_queries[443].output_at(__i).as_ptr() as *const [G; OUT_443]) }; __ret }, _ => aiur_fn_443(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_444] = { let __args: [G; IN_444] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[444].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[444].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[444].bump_multiplicity(__i); } let __ret: [G; OUT_444] = unsafe { *(record.function_queries[444].output_at(__i).as_ptr() as *const [G; OUT_444]) }; __ret }, _ => aiur_fn_444(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_443] = { let __args: [G; IN_443] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[443].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[443].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[443].bump_multiplicity(__i); } let __ret: [G; OUT_443] = unsafe { *(record.function_queries[443].output_at(__i).as_ptr() as *const [G; OUT_443]) }; __ret }, _ => aiur_fn_443(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = (__v_3 * __v_4); match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_446] = [__v_6, __v_7]; - record.function_queries[446].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_445] = [__v_6, __v_7]; + record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_444] = { let __args: [G; IN_444] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[444].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[444].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[444].bump_multiplicity(__i); } let __ret: [G; OUT_444] = unsafe { *(record.function_queries[444].output_at(__i).as_ptr() as *const [G; OUT_444]) }; __ret }, _ => aiur_fn_444(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; let __v_8: G = __r_arr[2]; - let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_444] = { let __args: [G; IN_444] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[444].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[444].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[444].bump_multiplicity(__i); } let __ret: [G; OUT_444] = unsafe { *(record.function_queries[444].output_at(__i).as_ptr() as *const [G; OUT_444]) }; __ret }, _ => aiur_fn_444(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = __r_arr[2]; @@ -40072,27 +40026,27 @@ fn aiur_fn_446( 0u64 => { let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); - let __ret: [G; OUT_446] = [__v_13, __v_14]; - record.function_queries[446].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_445] = [__v_13, __v_14]; + record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_337] = { let __args: [G; IN_337] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[337].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[337].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[337].bump_multiplicity(__i); } let __ret: [G; OUT_337] = unsafe { *(record.function_queries[337].output_at(__i).as_ptr() as *const [G; OUT_337]) }; __ret }, _ => aiur_fn_337(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 0u64 => { let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_446] = [__v_14, __v_15]; - record.function_queries[446].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_445] = [__v_14, __v_15]; + record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(1); - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_7, __v_10, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_7, __v_10, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_446] = [__v_14, __v_15]; - record.function_queries[446].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_445] = [__v_14, __v_15]; + record.function_queries[445].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40103,48 +40057,48 @@ fn aiur_fn_446( }) } -const INPUT_SIZE_447: usize = 3; -const IN_447: usize = 3; -const OUT_447: usize = 1; -fn aiur_fn_447( - inp: [G; IN_447], +const INPUT_SIZE_446: usize = 3; +const IN_446: usize = 3; +const OUT_446: usize = 1; +fn aiur_fn_446( + inp: [G; IN_446], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_447], ExecError> { +) -> Result<[G; OUT_446], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_448] = { let __args: [G; IN_448] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[448].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[448].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[448].bump_multiplicity(__i); } let __ret: [G; OUT_448] = unsafe { *(record.function_queries[448].output_at(__i).as_ptr() as *const [G; OUT_448]) }; __ret }, _ => aiur_fn_448(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_447] = { let __args: [G; IN_447] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[447].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[447].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[447].bump_multiplicity(__i); } let __ret: [G; OUT_447] = unsafe { *(record.function_queries[447].output_at(__i).as_ptr() as *const [G; OUT_447]) }; __ret }, _ => aiur_fn_447(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_447] = [__v_4]; - record.function_queries[447].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_446] = [__v_4]; + record.function_queries[446].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_448] = { let __args: [G; IN_448] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[448].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[448].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[448].bump_multiplicity(__i); } let __ret: [G; OUT_448] = unsafe { *(record.function_queries[448].output_at(__i).as_ptr() as *const [G; OUT_448]) }; __ret }, _ => aiur_fn_448(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_447] = { let __args: [G; IN_447] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[447].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[447].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[447].bump_multiplicity(__i); } let __ret: [G; OUT_447] = unsafe { *(record.function_queries[447].output_at(__i).as_ptr() as *const [G; OUT_447]) }; __ret }, _ => aiur_fn_447(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_447] = [__v_4]; - record.function_queries[447].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_446] = [__v_4]; + record.function_queries[446].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_448: usize = 3; -const IN_448: usize = 3; -const OUT_448: usize = 1; -fn aiur_fn_448( - inp: [G; IN_448], +const INPUT_SIZE_447: usize = 3; +const IN_447: usize = 3; +const OUT_447: usize = 1; +fn aiur_fn_447( + inp: [G; IN_447], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_448], ExecError> { +) -> Result<[G; OUT_447], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -40158,48 +40112,48 @@ fn aiur_fn_448( 7u64 => { match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_228] = { let __args: [G; IN_228] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[228].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[228].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[228].bump_multiplicity(__i); } let __ret: [G; OUT_228] = unsafe { *(record.function_queries[228].output_at(__i).as_ptr() as *const [G; OUT_228]) }; __ret }, _ => aiur_fn_228(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_227] = { let __args: [G; IN_227] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[227].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[227].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[227].bump_multiplicity(__i); } let __ret: [G; OUT_227] = unsafe { *(record.function_queries[227].output_at(__i).as_ptr() as *const [G; OUT_227]) }; __ret }, _ => aiur_fn_227(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_230] = { let __args: [G; IN_230] = [__v_7, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[230].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[230].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[230].bump_multiplicity(__i); } let __ret: [G; OUT_230] = unsafe { *(record.function_queries[230].output_at(__i).as_ptr() as *const [G; OUT_230]) }; __ret }, _ => aiur_fn_230(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_229] = { let __args: [G; IN_229] = [__v_7, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[229].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[229].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[229].bump_multiplicity(__i); } let __ret: [G; OUT_229] = unsafe { *(record.function_queries[229].output_at(__i).as_ptr() as *const [G; OUT_229]) }; __ret }, _ => aiur_fn_229(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_448] = [__v_9]; - record.function_queries[448].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_447] = [__v_9]; + record.function_queries[447].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_448] = [__v_7]; - record.function_queries[448].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_447] = [__v_7]; + record.function_queries[447].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_448] = [__v_7]; - record.function_queries[448].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_447] = [__v_7]; + record.function_queries[447].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_449: usize = 3; -const IN_449: usize = 3; -const OUT_449: usize = 1; -fn aiur_fn_449( - inp: [G; IN_449], +const INPUT_SIZE_448: usize = 3; +const IN_448: usize = 3; +const OUT_448: usize = 1; +fn aiur_fn_448( + inp: [G; IN_448], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_449], ExecError> { +) -> Result<[G; OUT_448], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_448] = { let __args: [G; IN_448] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[448].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[448].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[448].bump_multiplicity(__i); } let __ret: [G; OUT_448] = unsafe { *(record.function_queries[448].output_at(__i).as_ptr() as *const [G; OUT_448]) }; __ret }, _ => aiur_fn_448(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_447] = { let __args: [G; IN_447] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[447].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[447].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[447].bump_multiplicity(__i); } let __ret: [G; OUT_447] = unsafe { *(record.function_queries[447].output_at(__i).as_ptr() as *const [G; OUT_447]) }; __ret }, _ => aiur_fn_447(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_3.as_canonical_u64() { 1u64 => { @@ -40207,7 +40161,7 @@ fn aiur_fn_449( break '__mc_0 [__v_4]; }, _ => { - let __r_arr: [G; OUT_448] = { let __args: [G; IN_448] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[448].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[448].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[448].bump_multiplicity(__i); } let __ret: [G; OUT_448] = unsafe { *(record.function_queries[448].output_at(__i).as_ptr() as *const [G; OUT_448]) }; __ret }, _ => aiur_fn_448(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_447] = { let __args: [G; IN_447] = [__v_1, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[447].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[447].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[447].bump_multiplicity(__i); } let __ret: [G; OUT_447] = unsafe { *(record.function_queries[447].output_at(__i).as_ptr() as *const [G; OUT_447]) }; __ret }, _ => aiur_fn_447(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; break '__mc_0 [__v_4]; }, @@ -40217,71 +40171,71 @@ fn aiur_fn_449( match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_449] = [__v_5]; - record.function_queries[449].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_448] = [__v_5]; + record.function_queries[448].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_450] = { let __args: [G; IN_450] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[450].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[450].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[450].bump_multiplicity(__i); } let __ret: [G; OUT_450] = unsafe { *(record.function_queries[450].output_at(__i).as_ptr() as *const [G; OUT_450]) }; __ret }, _ => aiur_fn_450(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_449] = { let __args: [G; IN_449] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[449].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[449].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[449].bump_multiplicity(__i); } let __ret: [G; OUT_449] = unsafe { *(record.function_queries[449].output_at(__i).as_ptr() as *const [G; OUT_449]) }; __ret }, _ => aiur_fn_449(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_449] = [__v_5]; - record.function_queries[449].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_448] = [__v_5]; + record.function_queries[448].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_450: usize = 3; -const IN_450: usize = 3; -const OUT_450: usize = 1; -fn aiur_fn_450( - inp: [G; IN_450], +const INPUT_SIZE_449: usize = 3; +const IN_449: usize = 3; +const OUT_449: usize = 1; +fn aiur_fn_449( + inp: [G; IN_449], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_450], ExecError> { +) -> Result<[G; OUT_449], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_418] = { let __args: [G; IN_418] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[418].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[418].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[418].bump_multiplicity(__i); } let __ret: [G; OUT_418] = unsafe { *(record.function_queries[418].output_at(__i).as_ptr() as *const [G; OUT_418]) }; __ret }, _ => aiur_fn_418(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_419] = { let __args: [G; IN_419] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[419].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[419].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[419].bump_multiplicity(__i); } let __ret: [G; OUT_419] = unsafe { *(record.function_queries[419].output_at(__i).as_ptr() as *const [G; OUT_419]) }; __ret }, _ => aiur_fn_419(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_418] = { let __args: [G; IN_418] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[418].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[418].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[418].bump_multiplicity(__i); } let __ret: [G; OUT_418] = unsafe { *(record.function_queries[418].output_at(__i).as_ptr() as *const [G; OUT_418]) }; __ret }, _ => aiur_fn_418(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = (__v_3 - __v_4); match __v_5.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_450] = [__v_6]; - record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_449] = [__v_6]; + record.function_queries[449].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_452] = { let __args: [G; IN_452] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[452].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[452].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[452].bump_multiplicity(__i); } let __ret: [G; OUT_452] = unsafe { *(record.function_queries[452].output_at(__i).as_ptr() as *const [G; OUT_452]) }; __ret }, _ => aiur_fn_452(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_451] = { let __args: [G; IN_451] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[451].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[451].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[451].bump_multiplicity(__i); } let __ret: [G; OUT_451] = unsafe { *(record.function_queries[451].output_at(__i).as_ptr() as *const [G; OUT_451]) }; __ret }, _ => aiur_fn_451(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_450] = [__v_7]; - record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_449] = [__v_7]; + record.function_queries[449].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_442] = { let __args: [G; IN_442] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[442].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[442].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[442].bump_multiplicity(__i); } let __ret: [G; OUT_442] = unsafe { *(record.function_queries[442].output_at(__i).as_ptr() as *const [G; OUT_442]) }; __ret }, _ => aiur_fn_442(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_441] = { let __args: [G; IN_441] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[441].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[441].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[441].bump_multiplicity(__i); } let __ret: [G; OUT_441] = unsafe { *(record.function_queries[441].output_at(__i).as_ptr() as *const [G; OUT_441]) }; __ret }, _ => aiur_fn_441(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_450] = [__v_8]; - record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_449] = [__v_8]; + record.function_queries[449].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_451] = { let __args: [G; IN_451] = [__v_0, __v_1, __v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[451].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[451].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[451].bump_multiplicity(__i); } let __ret: [G; OUT_451] = unsafe { *(record.function_queries[451].output_at(__i).as_ptr() as *const [G; OUT_451]) }; __ret }, _ => aiur_fn_451(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_450] = { let __args: [G; IN_450] = [__v_0, __v_1, __v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[450].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[450].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[450].bump_multiplicity(__i); } let __ret: [G; OUT_450] = unsafe { *(record.function_queries[450].output_at(__i).as_ptr() as *const [G; OUT_450]) }; __ret }, _ => aiur_fn_450(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_450] = [__v_8]; - record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_449] = [__v_8]; + record.function_queries[449].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40292,58 +40246,58 @@ fn aiur_fn_450( }) } -const INPUT_SIZE_451: usize = 5; -const IN_451: usize = 5; -const OUT_451: usize = 1; -fn aiur_fn_451( - inp: [G; IN_451], +const INPUT_SIZE_450: usize = 5; +const IN_450: usize = 5; +const OUT_450: usize = 1; +fn aiur_fn_450( + inp: [G; IN_450], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_451], ExecError> { +) -> Result<[G; OUT_450], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_5 - __v_6); match __v_7.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_451] = [__v_8]; - record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_450] = [__v_8]; + record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_452] = { let __args: [G; IN_452] = [__v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[452].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[452].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[452].bump_multiplicity(__i); } let __ret: [G; OUT_452] = unsafe { *(record.function_queries[452].output_at(__i).as_ptr() as *const [G; OUT_452]) }; __ret }, _ => aiur_fn_452(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_451] = { let __args: [G; IN_451] = [__v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[451].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[451].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[451].bump_multiplicity(__i); } let __ret: [G; OUT_451] = unsafe { *(record.function_queries[451].output_at(__i).as_ptr() as *const [G; OUT_451]) }; __ret }, _ => aiur_fn_451(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_451] = [__v_9]; - record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_450] = [__v_9]; + record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_442] = { let __args: [G; IN_442] = [__v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[442].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[442].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[442].bump_multiplicity(__i); } let __ret: [G; OUT_442] = unsafe { *(record.function_queries[442].output_at(__i).as_ptr() as *const [G; OUT_442]) }; __ret }, _ => aiur_fn_442(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_441] = { let __args: [G; IN_441] = [__v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[441].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[441].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[441].bump_multiplicity(__i); } let __ret: [G; OUT_441] = unsafe { *(record.function_queries[441].output_at(__i).as_ptr() as *const [G; OUT_441]) }; __ret }, _ => aiur_fn_441(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_451] = [__v_10]; - record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_450] = [__v_10]; + record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_453] = { let __args: [G; IN_453] = [__v_0, __v_1, __v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[453].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[453].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[453].bump_multiplicity(__i); } let __ret: [G; OUT_453] = unsafe { *(record.function_queries[453].output_at(__i).as_ptr() as *const [G; OUT_453]) }; __ret }, _ => aiur_fn_453(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_452] = { let __args: [G; IN_452] = [__v_0, __v_1, __v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[452].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[452].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[452].bump_multiplicity(__i); } let __ret: [G; OUT_452] = unsafe { *(record.function_queries[452].output_at(__i).as_ptr() as *const [G; OUT_452]) }; __ret }, _ => aiur_fn_452(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_451] = [__v_10]; - record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_450] = [__v_10]; + record.function_queries[450].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40354,15 +40308,15 @@ fn aiur_fn_451( }) } -const INPUT_SIZE_452: usize = 3; -const IN_452: usize = 3; -const OUT_452: usize = 1; -fn aiur_fn_452( - inp: [G; IN_452], +const INPUT_SIZE_451: usize = 3; +const IN_451: usize = 3; +const OUT_451: usize = 1; +fn aiur_fn_451( + inp: [G; IN_451], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_452], ExecError> { +) -> Result<[G; OUT_451], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -40381,16 +40335,16 @@ fn aiur_fn_452( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_452] = [__v_11]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_11]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_452] = [__v_11]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_11]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40403,30 +40357,30 @@ fn aiur_fn_452( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 4u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_12, __v_4, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_452] = [__v_14]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_14]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_452] = [__v_12]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_12]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_452] = [__v_11]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_11]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40439,53 +40393,53 @@ fn aiur_fn_452( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_12, __v_4, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_452] = [__v_14]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_14]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_452] = [__v_12]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_12]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_452] = [__v_11]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_11]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_452] = [__v_7]; - record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_451] = [__v_7]; + record.function_queries[451].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_453: usize = 5; -const IN_453: usize = 5; -const OUT_453: usize = 1; -fn aiur_fn_453( - inp: [G; IN_453], +const INPUT_SIZE_452: usize = 5; +const IN_452: usize = 5; +const OUT_452: usize = 1; +fn aiur_fn_452( + inp: [G; IN_452], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_453], ExecError> { +) -> Result<[G; OUT_452], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -40496,78 +40450,78 @@ fn aiur_fn_453( match __v_5.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_453] = [__v_6]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_6]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_467] = { let __args: [G; IN_467] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[467].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[467].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[467].bump_multiplicity(__i); } let __ret: [G; OUT_467] = unsafe { *(record.function_queries[467].output_at(__i).as_ptr() as *const [G; OUT_467]) }; __ret }, _ => aiur_fn_467(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_466] = { let __args: [G; IN_466] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[466].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[466].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[466].bump_multiplicity(__i); } let __ret: [G; OUT_466] = unsafe { *(record.function_queries[466].output_at(__i).as_ptr() as *const [G; OUT_466]) }; __ret }, _ => aiur_fn_466(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_453] = [__v_7]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_7]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_465] = { let __args: [G; IN_465] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[465].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[465].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[465].bump_multiplicity(__i); } let __ret: [G; OUT_465] = unsafe { *(record.function_queries[465].output_at(__i).as_ptr() as *const [G; OUT_465]) }; __ret }, _ => aiur_fn_465(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_464] = { let __args: [G; IN_464] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[464].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[464].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[464].bump_multiplicity(__i); } let __ret: [G; OUT_464] = unsafe { *(record.function_queries[464].output_at(__i).as_ptr() as *const [G; OUT_464]) }; __ret }, _ => aiur_fn_464(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_453] = [__v_8]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_8]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_461] = { let __args: [G; IN_461] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[461].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[461].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[461].bump_multiplicity(__i); } let __ret: [G; OUT_461] = unsafe { *(record.function_queries[461].output_at(__i).as_ptr() as *const [G; OUT_461]) }; __ret }, _ => aiur_fn_461(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_460] = { let __args: [G; IN_460] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[460].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[460].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[460].bump_multiplicity(__i); } let __ret: [G; OUT_460] = unsafe { *(record.function_queries[460].output_at(__i).as_ptr() as *const [G; OUT_460]) }; __ret }, _ => aiur_fn_460(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_453] = [__v_9]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_9]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_461] = { let __args: [G; IN_461] = [__v_3, __v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[461].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[461].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[461].bump_multiplicity(__i); } let __ret: [G; OUT_461] = unsafe { *(record.function_queries[461].output_at(__i).as_ptr() as *const [G; OUT_461]) }; __ret }, _ => aiur_fn_461(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_460] = { let __args: [G; IN_460] = [__v_3, __v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[460].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[460].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[460].bump_multiplicity(__i); } let __ret: [G; OUT_460] = unsafe { *(record.function_queries[460].output_at(__i).as_ptr() as *const [G; OUT_460]) }; __ret }, _ => aiur_fn_460(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_453] = [__v_10]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_10]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_446] = { let __args: [G; IN_446] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[446].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[446].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[446].bump_multiplicity(__i); } let __ret: [G; OUT_446] = unsafe { *(record.function_queries[446].output_at(__i).as_ptr() as *const [G; OUT_446]) }; __ret }, _ => aiur_fn_446(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; match __v_10.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_453] = [__v_11]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_11]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(16); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_2, __v_3, __v_12, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_2, __v_3, __v_12, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; let __v_15: G = __r_arr[2]; match __v_13.as_canonical_u64() { 1u64 => { let __v_16: G = G::from_u64(1); - let __ret: [G; OUT_453] = [__v_16]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_16]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_454] = { let __args: [G; IN_454] = [__v_0, __v_1, __v_14, __v_15, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[454].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[454].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[454].bump_multiplicity(__i); } let __ret: [G; OUT_454] = unsafe { *(record.function_queries[454].output_at(__i).as_ptr() as *const [G; OUT_454]) }; __ret }, _ => aiur_fn_454(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_453] = { let __args: [G; IN_453] = [__v_0, __v_1, __v_14, __v_15, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[453].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[453].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[453].bump_multiplicity(__i); } let __ret: [G; OUT_453] = unsafe { *(record.function_queries[453].output_at(__i).as_ptr() as *const [G; OUT_453]) }; __ret }, _ => aiur_fn_453(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_453] = [__v_16]; - record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_452] = [__v_16]; + record.function_queries[452].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40586,15 +40540,15 @@ fn aiur_fn_453( }) } -const INPUT_SIZE_454: usize = 5; -const IN_454: usize = 5; -const OUT_454: usize = 1; -fn aiur_fn_454( - inp: [G; IN_454], +const INPUT_SIZE_453: usize = 5; +const IN_453: usize = 5; +const OUT_453: usize = 1; +fn aiur_fn_453( + inp: [G; IN_453], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_454], ExecError> { +) -> Result<[G; OUT_453], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -40602,31 +40556,31 @@ fn aiur_fn_454( let __v_3: G = inp[3]; let __v_4: G = inp[4]; let __v_5: G = G::from_u64(8); - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_2, __v_3, __v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_2, __v_3, __v_5, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; match __v_6.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_454] = [__v_8]; - record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_453] = [__v_8]; + record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_456] = { let __args: [G; IN_456] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[456].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[456].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[456].bump_multiplicity(__i); } let __ret: [G; OUT_456] = unsafe { *(record.function_queries[456].output_at(__i).as_ptr() as *const [G; OUT_456]) }; __ret }, _ => aiur_fn_456(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_455] = { let __args: [G; IN_455] = [__v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[455].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[455].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[455].bump_multiplicity(__i); } let __ret: [G; OUT_455] = unsafe { *(record.function_queries[455].output_at(__i).as_ptr() as *const [G; OUT_455]) }; __ret }, _ => aiur_fn_455(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_454] = [__v_9]; - record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_453] = [__v_9]; + record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_460] = { let __args: [G; IN_460] = [__v_0, __v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[460].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[460].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[460].bump_multiplicity(__i); } let __ret: [G; OUT_460] = unsafe { *(record.function_queries[460].output_at(__i).as_ptr() as *const [G; OUT_460]) }; __ret }, _ => aiur_fn_460(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_454] = [__v_9]; - record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_453] = [__v_9]; + record.function_queries[453].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40635,15 +40589,15 @@ fn aiur_fn_454( }) } -const INPUT_SIZE_455: usize = 3; -const IN_455: usize = 3; -const OUT_455: usize = 1; -fn aiur_fn_455( - inp: [G; IN_455], +const INPUT_SIZE_454: usize = 3; +const IN_454: usize = 3; +const OUT_454: usize = 1; +fn aiur_fn_454( + inp: [G; IN_454], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_455], ExecError> { +) -> Result<[G; OUT_454], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -40654,19 +40608,19 @@ fn aiur_fn_455( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_455] = [__v_8]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_8]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = (__v_8 - __v_9); match __v_10.as_canonical_u64() { @@ -40692,60 +40646,60 @@ fn aiur_fn_455( let __v_20: G = (__v_13 - __v_17); match __v_20.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_14, __v_18, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_14, __v_18, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; match __v_21.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_443] = { let __args: [G; IN_443] = [__v_4, __v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[443].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[443].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[443].bump_multiplicity(__i); } let __ret: [G; OUT_443] = unsafe { *(record.function_queries[443].output_at(__i).as_ptr() as *const [G; OUT_443]) }; __ret }, _ => aiur_fn_443(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_442] = { let __args: [G; IN_442] = [__v_4, __v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[442].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[442].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[442].bump_multiplicity(__i); } let __ret: [G; OUT_442] = unsafe { *(record.function_queries[442].output_at(__i).as_ptr() as *const [G; OUT_442]) }; __ret }, _ => aiur_fn_442(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_455] = [__v_22]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_22]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_455] = [__v_22]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_22]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_21: G = G::from_u64(0); - let __ret: [G; OUT_455] = [__v_21]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_21]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_20: G = G::from_u64(0); - let __ret: [G; OUT_455] = [__v_20]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_20]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_19: G = G::from_u64(0); - let __ret: [G; OUT_455] = [__v_19]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_19]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_455] = [__v_15]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_15]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_455] = [__v_11]; - record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_454] = [__v_11]; + record.function_queries[454].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40754,45 +40708,45 @@ fn aiur_fn_455( }) } -const INPUT_SIZE_456: usize = 3; -const IN_456: usize = 3; -const OUT_456: usize = 1; -fn aiur_fn_456( - inp: [G; IN_456], +const INPUT_SIZE_455: usize = 3; +const IN_455: usize = 3; +const OUT_455: usize = 1; +fn aiur_fn_455( + inp: [G; IN_455], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_456], ExecError> { +) -> Result<[G; OUT_455], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = G::from_u64(8); - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_0, __v_1, __v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; match __v_4.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_456] = [__v_6]; - record.function_queries[456].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_455] = [__v_6]; + record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_455] = { let __args: [G; IN_455] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[455].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[455].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[455].bump_multiplicity(__i); } let __ret: [G; OUT_455] = unsafe { *(record.function_queries[455].output_at(__i).as_ptr() as *const [G; OUT_455]) }; __ret }, _ => aiur_fn_455(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_454] = { let __args: [G; IN_454] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[454].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[454].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[454].bump_multiplicity(__i); } let __ret: [G; OUT_454] = unsafe { *(record.function_queries[454].output_at(__i).as_ptr() as *const [G; OUT_454]) }; __ret }, _ => aiur_fn_454(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_456] = [__v_7]; - record.function_queries[456].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_455] = [__v_7]; + record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_456] = { let __args: [G; IN_456] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[456].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[456].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[456].bump_multiplicity(__i); } let __ret: [G; OUT_456] = unsafe { *(record.function_queries[456].output_at(__i).as_ptr() as *const [G; OUT_456]) }; __ret }, _ => aiur_fn_456(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_456] = [__v_7]; - record.function_queries[456].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_455] = [__v_7]; + record.function_queries[455].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40801,15 +40755,15 @@ fn aiur_fn_456( }) } -const INPUT_SIZE_457: usize = 3; -const IN_457: usize = 3; -const OUT_457: usize = 1; -fn aiur_fn_457( - inp: [G; IN_457], +const INPUT_SIZE_456: usize = 3; +const IN_456: usize = 3; +const OUT_456: usize = 1; +fn aiur_fn_456( + inp: [G; IN_456], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_457], ExecError> { +) -> Result<[G; OUT_456], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -40828,51 +40782,51 @@ fn aiur_fn_457( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 3u64 => { - let __r_arr: [G; OUT_456] = { let __args: [G; IN_456] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[456].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[456].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[456].bump_multiplicity(__i); } let __ret: [G; OUT_456] = unsafe { *(record.function_queries[456].output_at(__i).as_ptr() as *const [G; OUT_456]) }; __ret }, _ => aiur_fn_456(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_455] = { let __args: [G; IN_455] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[455].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[455].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[455].bump_multiplicity(__i); } let __ret: [G; OUT_455] = unsafe { *(record.function_queries[455].output_at(__i).as_ptr() as *const [G; OUT_455]) }; __ret }, _ => aiur_fn_455(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_456] = { let __args: [G; IN_456] = [__v_5, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[456].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[456].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[456].bump_multiplicity(__i); } let __ret: [G; OUT_456] = unsafe { *(record.function_queries[456].output_at(__i).as_ptr() as *const [G; OUT_456]) }; __ret }, _ => aiur_fn_456(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_455] = { let __args: [G; IN_455] = [__v_5, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[455].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[455].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[455].bump_multiplicity(__i); } let __ret: [G; OUT_455] = unsafe { *(record.function_queries[455].output_at(__i).as_ptr() as *const [G; OUT_455]) }; __ret }, _ => aiur_fn_455(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_457] = [__v_12]; - record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_456] = [__v_12]; + record.function_queries[456].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_457] = [__v_12]; - record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_456] = [__v_12]; + record.function_queries[456].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_457] = [__v_11]; - record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_456] = [__v_11]; + record.function_queries[456].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_457] = [__v_7]; - record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_456] = [__v_7]; + record.function_queries[456].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_458: usize = 4; -const IN_458: usize = 4; -const OUT_458: usize = 2; -fn aiur_fn_458( - inp: [G; IN_458], +const INPUT_SIZE_457: usize = 4; +const IN_457: usize = 4; +const OUT_457: usize = 2; +fn aiur_fn_457( + inp: [G; IN_457], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_458], ExecError> { +) -> Result<[G; OUT_457], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -40882,8 +40836,8 @@ fn aiur_fn_458( match __v_4.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_458] = [__v_5, __v_2]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_5, __v_2]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -40905,24 +40859,24 @@ fn aiur_fn_458( match __v_13.as_canonical_u64() { 0u64 => { let __v_14: G = G::from_u64(1); - let __ret: [G; OUT_458] = [__v_14, __v_2]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_14, __v_2]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(0); - let __ret: [G; OUT_458] = [__v_14, __v_2]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_14, __v_2]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40935,18 +40889,18 @@ fn aiur_fn_458( let __v_12: G = __loaded[3]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_458] = [__v_13, __v_2]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_2]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40963,28 +40917,28 @@ fn aiur_fn_458( let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_7, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_436] = { let __args: [G; IN_436] = [__v_7, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[436].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[436].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[436].bump_multiplicity(__i); } let __ret: [G; OUT_436] = unsafe { *(record.function_queries[436].output_at(__i).as_ptr() as *const [G; OUT_436]) }; __ret }, _ => aiur_fn_436(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_458] = [__v_14, __v_2]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_14, __v_2]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_14, __v_15]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_14, __v_15]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -40997,32 +40951,32 @@ fn aiur_fn_458( let __v_12: G = __loaded[3]; match __v_9.as_canonical_u64() { 3u64 => { - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_6, __v_10, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_6, __v_10, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; match __v_13.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_7, __v_11, __v_14, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_7, __v_11, __v_14, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_15, __v_16]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_15, __v_16]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_458] = [__v_15, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_15, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41035,34 +40989,34 @@ fn aiur_fn_458( let __v_12: G = __loaded[3]; match __v_9.as_canonical_u64() { 4u64 => { - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_6, __v_10, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_6, __v_10, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; match __v_13.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 3] = [__v_15, __v_6, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_7, __v_11, __v_14, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_7, __v_11, __v_14, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_17, __v_18]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_17, __v_18]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_458] = [__v_15, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_15, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41075,34 +41029,34 @@ fn aiur_fn_458( let __v_12: G = __loaded[3]; match __v_9.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_6, __v_10, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_6, __v_10, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; match __v_13.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 3] = [__v_15, __v_6, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_7, __v_11, __v_14, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_7, __v_11, __v_14, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_17, __v_18]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_17, __v_18]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_458] = [__v_15, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_15, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41115,18 +41069,18 @@ fn aiur_fn_458( let __v_12: G = __loaded[3]; match __v_9.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_6, __v_7, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_6, __v_7, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_458] = [__v_13, __v_2]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_2]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41146,47 +41100,47 @@ fn aiur_fn_458( let __v_14: G = (__v_7 - __v_11); match __v_14.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_8, __v_12, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_8, __v_12, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_15, __v_16]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_15, __v_16]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_458] = [__v_15, __v_2]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_15, __v_2]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_14, __v_15]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_14, __v_15]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_13, __v_14]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_13, __v_14]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_459] = { let __args: [G; IN_459] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[459].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[459].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[459].bump_multiplicity(__i); } let __ret: [G; OUT_459] = unsafe { *(record.function_queries[459].output_at(__i).as_ptr() as *const [G; OUT_459]) }; __ret }, _ => aiur_fn_459(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_458] = [__v_9, __v_10]; - record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_457] = [__v_9, __v_10]; + record.function_queries[457].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41195,15 +41149,15 @@ fn aiur_fn_458( }) } -const INPUT_SIZE_459: usize = 4; -const IN_459: usize = 4; -const OUT_459: usize = 2; -fn aiur_fn_459( - inp: [G; IN_459], +const INPUT_SIZE_458: usize = 4; +const IN_458: usize = 4; +const OUT_458: usize = 2; +fn aiur_fn_458( + inp: [G; IN_458], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_459], ExecError> { +) -> Result<[G; OUT_458], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -41213,54 +41167,54 @@ fn aiur_fn_459( 0u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_459] = [__v_4, __v_5]; - record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_458] = [__v_4, __v_5]; + record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(1); let __v_5: G = (__v_2 - __v_4); - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = (__v_6 - __v_7); match __v_8.as_canonical_u64() { 0u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_459] = [__v_9, __v_5]; - record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_458] = [__v_9, __v_5]; + record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_446] = { let __args: [G; IN_446] = [__v_6, __v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[446].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[446].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[446].bump_multiplicity(__i); } let __ret: [G; OUT_446] = unsafe { *(record.function_queries[446].output_at(__i).as_ptr() as *const [G; OUT_446]) }; __ret }, _ => aiur_fn_446(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_6, __v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_9.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_459] = [__v_10, __v_5]; - record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_458] = [__v_10, __v_5]; + record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(8); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_6, __v_7, __v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_6, __v_7, __v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; let __v_14: G = __r_arr[2]; match __v_12.as_canonical_u64() { 1u64 => { let __v_15: G = G::from_u64(1); - let __ret: [G; OUT_459] = [__v_15, __v_5]; - record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_458] = [__v_15, __v_5]; + record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_458] = { let __args: [G; IN_458] = [__v_13, __v_14, __v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[458].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[458].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[458].bump_multiplicity(__i); } let __ret: [G; OUT_458] = unsafe { *(record.function_queries[458].output_at(__i).as_ptr() as *const [G; OUT_458]) }; __ret }, _ => aiur_fn_458(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_457] = { let __args: [G; IN_457] = [__v_13, __v_14, __v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[457].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[457].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[457].bump_multiplicity(__i); } let __ret: [G; OUT_457] = unsafe { *(record.function_queries[457].output_at(__i).as_ptr() as *const [G; OUT_457]) }; __ret }, _ => aiur_fn_457(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __ret: [G; OUT_459] = [__v_15, __v_16]; - record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_458] = [__v_15, __v_16]; + record.function_queries[458].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41273,96 +41227,96 @@ fn aiur_fn_459( }) } -const INPUT_SIZE_460: usize = 3; -const IN_460: usize = 3; -const OUT_460: usize = 1; -fn aiur_fn_460( - inp: [G; IN_460], +const INPUT_SIZE_459: usize = 3; +const IN_459: usize = 3; +const OUT_459: usize = 1; +fn aiur_fn_459( + inp: [G; IN_459], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_460], ExecError> { +) -> Result<[G; OUT_459], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = (__v_3 - __v_4); match __v_5.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_460] = [__v_6]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_6]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_467] = { let __args: [G; IN_467] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[467].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[467].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[467].bump_multiplicity(__i); } let __ret: [G; OUT_467] = unsafe { *(record.function_queries[467].output_at(__i).as_ptr() as *const [G; OUT_467]) }; __ret }, _ => aiur_fn_467(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_466] = { let __args: [G; IN_466] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[466].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[466].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[466].bump_multiplicity(__i); } let __ret: [G; OUT_466] = unsafe { *(record.function_queries[466].output_at(__i).as_ptr() as *const [G; OUT_466]) }; __ret }, _ => aiur_fn_466(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_460] = [__v_7]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_7]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_465] = { let __args: [G; IN_465] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[465].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[465].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[465].bump_multiplicity(__i); } let __ret: [G; OUT_465] = unsafe { *(record.function_queries[465].output_at(__i).as_ptr() as *const [G; OUT_465]) }; __ret }, _ => aiur_fn_465(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_464] = { let __args: [G; IN_464] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[464].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[464].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[464].bump_multiplicity(__i); } let __ret: [G; OUT_464] = unsafe { *(record.function_queries[464].output_at(__i).as_ptr() as *const [G; OUT_464]) }; __ret }, _ => aiur_fn_464(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_460] = [__v_8]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_8]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_461] = { let __args: [G; IN_461] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[461].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[461].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[461].bump_multiplicity(__i); } let __ret: [G; OUT_461] = unsafe { *(record.function_queries[461].output_at(__i).as_ptr() as *const [G; OUT_461]) }; __ret }, _ => aiur_fn_461(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_460] = { let __args: [G; IN_460] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[460].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[460].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[460].bump_multiplicity(__i); } let __ret: [G; OUT_460] = unsafe { *(record.function_queries[460].output_at(__i).as_ptr() as *const [G; OUT_460]) }; __ret }, _ => aiur_fn_460(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_460] = [__v_9]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_9]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_461] = { let __args: [G; IN_461] = [__v_4, __v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[461].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[461].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[461].bump_multiplicity(__i); } let __ret: [G; OUT_461] = unsafe { *(record.function_queries[461].output_at(__i).as_ptr() as *const [G; OUT_461]) }; __ret }, _ => aiur_fn_461(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_460] = { let __args: [G; IN_460] = [__v_4, __v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[460].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[460].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[460].bump_multiplicity(__i); } let __ret: [G; OUT_460] = unsafe { *(record.function_queries[460].output_at(__i).as_ptr() as *const [G; OUT_460]) }; __ret }, _ => aiur_fn_460(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_460] = [__v_10]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_10]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_446] = { let __args: [G; IN_446] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[446].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[446].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[446].bump_multiplicity(__i); } let __ret: [G; OUT_446] = unsafe { *(record.function_queries[446].output_at(__i).as_ptr() as *const [G; OUT_446]) }; __ret }, _ => aiur_fn_446(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; match __v_10.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_460] = [__v_11]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_11]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_464] = { let __args: [G; IN_464] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[464].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[464].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[464].bump_multiplicity(__i); } let __ret: [G; OUT_464] = unsafe { *(record.function_queries[464].output_at(__i).as_ptr() as *const [G; OUT_464]) }; __ret }, _ => aiur_fn_464(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_463] = { let __args: [G; IN_463] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[463].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[463].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[463].bump_multiplicity(__i); } let __ret: [G; OUT_463] = unsafe { *(record.function_queries[463].output_at(__i).as_ptr() as *const [G; OUT_463]) }; __ret }, _ => aiur_fn_463(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { let __v_13: G = G::from_u64(1); - let __ret: [G; OUT_460] = [__v_13]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_13]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_470] = { let __args: [G; IN_470] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[470].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[470].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[470].bump_multiplicity(__i); } let __ret: [G; OUT_470] = unsafe { *(record.function_queries[470].output_at(__i).as_ptr() as *const [G; OUT_470]) }; __ret }, _ => aiur_fn_470(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_469] = { let __args: [G; IN_469] = [__v_3, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[469].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[469].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[469].bump_multiplicity(__i); } let __ret: [G; OUT_469] = unsafe { *(record.function_queries[469].output_at(__i).as_ptr() as *const [G; OUT_469]) }; __ret }, _ => aiur_fn_469(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_460] = [__v_13]; - record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_459] = [__v_13]; + record.function_queries[459].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41381,15 +41335,15 @@ fn aiur_fn_460( }) } -const INPUT_SIZE_461: usize = 3; -const IN_461: usize = 3; -const OUT_461: usize = 1; -fn aiur_fn_461( - inp: [G; IN_461], +const INPUT_SIZE_460: usize = 3; +const IN_460: usize = 3; +const OUT_460: usize = 1; +fn aiur_fn_460( + inp: [G; IN_460], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_461], ExecError> { +) -> Result<[G; OUT_460], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -41404,7 +41358,7 @@ fn aiur_fn_461( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_9.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -41421,13 +41375,13 @@ fn aiur_fn_461( let __v_21: G = __loaded[11]; match __v_10.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = (__v_16 + __v_17); let __v_24: G = (__v_22 - __v_23); match __v_24.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_288] = { let __args: [G; IN_288] = [__v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[288].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[288].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[288].bump_multiplicity(__i); } let __ret: [G; OUT_288] = unsafe { *(record.function_queries[288].output_at(__i).as_ptr() as *const [G; OUT_288]) }; __ret }, _ => aiur_fn_288(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_25.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_26: G = __loaded[0]; @@ -41452,42 +41406,42 @@ fn aiur_fn_461( match __v_42.as_canonical_u64() { 0u64 => { let __v_43: G = G::from_u64(0); - let __ret: [G; OUT_461] = [__v_43]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_43]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_463] = { let __args: [G; IN_463] = [__v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[463].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[463].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[463].bump_multiplicity(__i); } let __ret: [G; OUT_463] = unsafe { *(record.function_queries[463].output_at(__i).as_ptr() as *const [G; OUT_463]) }; __ret }, _ => aiur_fn_463(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_462] = { let __args: [G; IN_462] = [__v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[462].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[462].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[462].bump_multiplicity(__i); } let __ret: [G; OUT_462] = unsafe { *(record.function_queries[462].output_at(__i).as_ptr() as *const [G; OUT_462]) }; __ret }, _ => aiur_fn_462(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; - let __r_arr: [G; OUT_410] = { let __args: [G; IN_410] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[410].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[410].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[410].bump_multiplicity(__i); } let __ret: [G; OUT_410] = unsafe { *(record.function_queries[410].output_at(__i).as_ptr() as *const [G; OUT_410]) }; __ret }, _ => aiur_fn_410(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_409] = { let __args: [G; IN_409] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[409].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[409].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[409].bump_multiplicity(__i); } let __ret: [G; OUT_409] = unsafe { *(record.function_queries[409].output_at(__i).as_ptr() as *const [G; OUT_409]) }; __ret }, _ => aiur_fn_409(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; match __v_44.as_canonical_u64() { 1u64 => { let __v_45: G = G::from_u64(0); - let __ret: [G; OUT_461] = [__v_45]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_45]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_46: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_45, __v_46, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_45, __v_46, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; match __v_47.as_canonical_u64() { 0u64 => { let __v_48: G = G::from_u64(0); - let __ret: [G; OUT_461] = [__v_48]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_48]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_48: G = G::from_u64(0); - let __r_arr: [G; OUT_462] = { let __args: [G; IN_462] = [__v_43, __v_16, __v_17, __v_0, __v_4, __v_48, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[462].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[462].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[462].bump_multiplicity(__i); } let __ret: [G; OUT_462] = unsafe { *(record.function_queries[462].output_at(__i).as_ptr() as *const [G; OUT_462]) }; __ret }, _ => aiur_fn_462(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_461] = { let __args: [G; IN_461] = [__v_43, __v_16, __v_17, __v_0, __v_4, __v_48, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[461].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[461].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[461].bump_multiplicity(__i); } let __ret: [G; OUT_461] = unsafe { *(record.function_queries[461].output_at(__i).as_ptr() as *const [G; OUT_461]) }; __ret }, _ => aiur_fn_461(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __ret: [G; OUT_461] = [__v_49]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_49]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41498,47 +41452,47 @@ fn aiur_fn_461( }, _ => { let __v_38: G = G::from_u64(0); - let __ret: [G; OUT_461] = [__v_38]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_38]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_25: G = G::from_u64(0); - let __ret: [G; OUT_461] = [__v_25]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_25]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_461] = [__v_22]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_22]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_461] = [__v_9]; - record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_460] = [__v_9]; + record.function_queries[460].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_462: usize = 7; -const IN_462: usize = 7; -const OUT_462: usize = 1; -fn aiur_fn_462( - inp: [G; IN_462], +const INPUT_SIZE_461: usize = 7; +const IN_461: usize = 7; +const OUT_461: usize = 1; +fn aiur_fn_461( + inp: [G; IN_461], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_462], ExecError> { +) -> Result<[G; OUT_461], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -41551,32 +41505,32 @@ fn aiur_fn_462( match __v_7.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_462] = [__v_8]; - record.function_queries[462].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_461] = [__v_8]; + record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(8); let __v_9: G = { let __values: [G; 4] = [__v_8, __v_0, __v_5, __v_3]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_10: G = (__v_1 + __v_5); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_9, __v_11, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_9, __v_11, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 0u64 => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_462] = [__v_13]; - record.function_queries[462].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_461] = [__v_13]; + record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(1); let __v_14: G = (__v_5 + __v_13); - let __r_arr: [G; OUT_462] = { let __args: [G; IN_462] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_14, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[462].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[462].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[462].bump_multiplicity(__i); } let __ret: [G; OUT_462] = unsafe { *(record.function_queries[462].output_at(__i).as_ptr() as *const [G; OUT_462]) }; __ret }, _ => aiur_fn_462(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_461] = { let __args: [G; IN_461] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_14, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[461].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[461].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[461].bump_multiplicity(__i); } let __ret: [G; OUT_461] = unsafe { *(record.function_queries[461].output_at(__i).as_ptr() as *const [G; OUT_461]) }; __ret }, _ => aiur_fn_461(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_462] = [__v_15]; - record.function_queries[462].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_461] = [__v_15]; + record.function_queries[461].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41585,19 +41539,19 @@ fn aiur_fn_462( }) } -const INPUT_SIZE_463: usize = 2; -const IN_463: usize = 2; -const OUT_463: usize = 1; -fn aiur_fn_463( - inp: [G; IN_463], +const INPUT_SIZE_462: usize = 2; +const IN_462: usize = 2; +const OUT_462: usize = 1; +fn aiur_fn_462( + inp: [G; IN_462], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_463], ExecError> { +) -> Result<[G; OUT_462], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -41624,21 +41578,21 @@ fn aiur_fn_463( let __v_24: G = __r_arr[0]; let __r_arr: [G; OUT_22] = { let __args: [G; IN_22] = [__v_24]; let __cu = unconstrained; let __hit = record.function_queries[22].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[22].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[22].bump_multiplicity(__i); } let __ret: [G; OUT_22] = unsafe { *(record.function_queries[22].output_at(__i).as_ptr() as *const [G; OUT_22]) }; __ret }, _ => aiur_fn_22(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __ret: [G; OUT_463] = [__v_25]; - record.function_queries[463].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_462] = [__v_25]; + record.function_queries[462].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_464: usize = 3; -const IN_464: usize = 3; -const OUT_464: usize = 1; -fn aiur_fn_464( - inp: [G; IN_464], +const INPUT_SIZE_463: usize = 3; +const IN_463: usize = 3; +const OUT_463: usize = 1; +fn aiur_fn_463( + inp: [G; IN_463], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_464], ExecError> { +) -> Result<[G; OUT_463], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -41658,15 +41612,15 @@ fn aiur_fn_464( match __v_7.as_canonical_u64() { 4u64 => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_464] = [__v_11]; - record.function_queries[464].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_463] = [__v_11]; + record.function_queries[463].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_468] = { let __args: [G; IN_468] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[468].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[468].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[468].bump_multiplicity(__i); } let __ret: [G; OUT_468] = unsafe { *(record.function_queries[468].output_at(__i).as_ptr() as *const [G; OUT_468]) }; __ret }, _ => aiur_fn_468(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_467] = { let __args: [G; IN_467] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[467].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[467].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[467].bump_multiplicity(__i); } let __ret: [G; OUT_467] = unsafe { *(record.function_queries[467].output_at(__i).as_ptr() as *const [G; OUT_467]) }; __ret }, _ => aiur_fn_467(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_464] = [__v_11]; - record.function_queries[464].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_463] = [__v_11]; + record.function_queries[463].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41679,16 +41633,16 @@ fn aiur_fn_464( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 4u64 => { - let __r_arr: [G; OUT_468] = { let __args: [G; IN_468] = [__v_8, __v_9, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[468].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[468].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[468].bump_multiplicity(__i); } let __ret: [G; OUT_468] = unsafe { *(record.function_queries[468].output_at(__i).as_ptr() as *const [G; OUT_468]) }; __ret }, _ => aiur_fn_468(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_467] = { let __args: [G; IN_467] = [__v_8, __v_9, __v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[467].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[467].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[467].bump_multiplicity(__i); } let __ret: [G; OUT_467] = unsafe { *(record.function_queries[467].output_at(__i).as_ptr() as *const [G; OUT_467]) }; __ret }, _ => aiur_fn_467(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_464] = [__v_11]; - record.function_queries[464].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_463] = [__v_11]; + record.function_queries[463].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_464] = [__v_11]; - record.function_queries[464].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_463] = [__v_11]; + record.function_queries[463].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -41697,54 +41651,54 @@ fn aiur_fn_464( }) } -const INPUT_SIZE_465: usize = 3; -const IN_465: usize = 3; -const OUT_465: usize = 1; -fn aiur_fn_465( - inp: [G; IN_465], +const INPUT_SIZE_464: usize = 3; +const IN_464: usize = 3; +const OUT_464: usize = 1; +fn aiur_fn_464( + inp: [G; IN_464], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_465], ExecError> { +) -> Result<[G; OUT_464], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_466] = { let __args: [G; IN_466] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[466].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[466].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[466].bump_multiplicity(__i); } let __ret: [G; OUT_466] = unsafe { *(record.function_queries[466].output_at(__i).as_ptr() as *const [G; OUT_466]) }; __ret }, _ => aiur_fn_466(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_465] = { let __args: [G; IN_465] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[465].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[465].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[465].bump_multiplicity(__i); } let __ret: [G; OUT_465] = unsafe { *(record.function_queries[465].output_at(__i).as_ptr() as *const [G; OUT_465]) }; __ret }, _ => aiur_fn_465(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_465] = [__v_6]; - record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_464] = [__v_6]; + record.function_queries[464].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_3, __v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_3, __v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_465] = [__v_7]; - record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_464] = [__v_7]; + record.function_queries[464].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_466: usize = 1; -const IN_466: usize = 1; -const OUT_466: usize = 1; -fn aiur_fn_466( - inp: [G; IN_466], +const INPUT_SIZE_465: usize = 1; +const IN_465: usize = 1; +const OUT_465: usize = 1; +fn aiur_fn_465( + inp: [G; IN_465], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_466], ExecError> { +) -> Result<[G; OUT_465], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; @@ -41757,7 +41711,7 @@ fn aiur_fn_466( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -41781,7 +41735,7 @@ fn aiur_fn_466( match __v_21.as_canonical_u64() { 0u64 => { let __v_22: G = G::from_u64(0); - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_15, __v_16, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_15, __v_16, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_23.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_24: G = __loaded[0]; @@ -41801,114 +41755,114 @@ fn aiur_fn_466( match __v_31.as_canonical_u64() { 0u64 => { let __v_36: G = G::from_u64(1); - let __ret: [G; OUT_466] = [__v_36]; - record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_465] = [__v_36]; + record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_36: G = G::from_u64(0); - let __ret: [G; OUT_466] = [__v_36]; - record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_465] = [__v_36]; + record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_36: G = G::from_u64(0); - let __ret: [G; OUT_466] = [__v_36]; - record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_465] = [__v_36]; + record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_22: G = G::from_u64(0); - let __ret: [G; OUT_466] = [__v_22]; - record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_465] = [__v_22]; + record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_20: G = G::from_u64(0); - let __ret: [G; OUT_466] = [__v_20]; - record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_465] = [__v_20]; + record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_20: G = G::from_u64(0); - let __ret: [G; OUT_466] = [__v_20]; - record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_465] = [__v_20]; + record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_466] = [__v_7]; - record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_465] = [__v_7]; + record.function_queries[465].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_467: usize = 3; -const IN_467: usize = 3; -const OUT_467: usize = 1; -fn aiur_fn_467( - inp: [G; IN_467], +const INPUT_SIZE_466: usize = 3; +const IN_466: usize = 3; +const OUT_466: usize = 1; +fn aiur_fn_466( + inp: [G; IN_466], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_467], ExecError> { +) -> Result<[G; OUT_466], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_469] = { let __args: [G; IN_469] = [__v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[469].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[469].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[469].bump_multiplicity(__i); } let __ret: [G; OUT_469] = unsafe { *(record.function_queries[469].output_at(__i).as_ptr() as *const [G; OUT_469]) }; __ret }, _ => aiur_fn_469(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_468] = { let __args: [G; IN_468] = [__v_3, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[468].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[468].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[468].bump_multiplicity(__i); } let __ret: [G; OUT_468] = unsafe { *(record.function_queries[468].output_at(__i).as_ptr() as *const [G; OUT_468]) }; __ret }, _ => aiur_fn_468(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_467] = [__v_5]; - record.function_queries[467].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_466] = [__v_5]; + record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_3, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_3, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_467] = [__v_6]; - record.function_queries[467].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_466] = [__v_6]; + record.function_queries[466].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_468: usize = 4; -const IN_468: usize = 4; -const OUT_468: usize = 1; -fn aiur_fn_468( - inp: [G; IN_468], +const INPUT_SIZE_467: usize = 4; +const IN_467: usize = 4; +const OUT_467: usize = 1; +fn aiur_fn_467( + inp: [G; IN_467], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_468], ExecError> { +) -> Result<[G; OUT_467], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_4, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_4, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -41917,19 +41871,19 @@ fn aiur_fn_468( let __v_9: G = __loaded[3]; match __v_6.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_0, __v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_0, __v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 0u64 => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_468] = [__v_11]; - record.function_queries[468].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_467] = [__v_11]; + record.function_queries[467].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(1); let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_2, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_2, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); @@ -41940,39 +41894,39 @@ fn aiur_fn_468( let __v_20: G = { let __values: [G; 4] = [__v_18, __v_13, __v_17, __v_19]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_21: G = G::from_u64(0); let __v_22: G = { let __values: [G; 3] = [__v_21, __v_0, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_1, __v_20, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_1, __v_20, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_468] = [__v_23]; - record.function_queries[468].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_467] = [__v_23]; + record.function_queries[467].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_468] = [__v_10]; - record.function_queries[468].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_467] = [__v_10]; + record.function_queries[467].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_469: usize = 2; -const IN_469: usize = 2; -const OUT_469: usize = 1; -fn aiur_fn_469( - inp: [G; IN_469], +const INPUT_SIZE_468: usize = 2; +const IN_468: usize = 2; +const OUT_468: usize = 1; +fn aiur_fn_468( + inp: [G; IN_468], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_469], ExecError> { +) -> Result<[G; OUT_468], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_432] = { let __args: [G; IN_432] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[432].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[432].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[432].bump_multiplicity(__i); } let __ret: [G; OUT_432] = unsafe { *(record.function_queries[432].output_at(__i).as_ptr() as *const [G; OUT_432]) }; __ret }, _ => aiur_fn_432(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_2, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_2, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -41984,52 +41938,52 @@ fn aiur_fn_469( let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_5, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_5, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_469] = [__v_11]; - record.function_queries[469].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_468] = [__v_11]; + record.function_queries[468].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_469] = [__v_8]; - record.function_queries[469].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_468] = [__v_8]; + record.function_queries[468].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_470: usize = 3; -const IN_470: usize = 3; -const OUT_470: usize = 1; -fn aiur_fn_470( - inp: [G; IN_470], +const INPUT_SIZE_469: usize = 3; +const IN_469: usize = 3; +const OUT_469: usize = 1; +fn aiur_fn_469( + inp: [G; IN_469], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_470], ExecError> { +) -> Result<[G; OUT_469], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_470] = { let __args: [G; IN_470] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[470].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[470].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[470].bump_multiplicity(__i); } let __ret: [G; OUT_470] = unsafe { *(record.function_queries[470].output_at(__i).as_ptr() as *const [G; OUT_470]) }; __ret }, _ => aiur_fn_470(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __ret: [G; OUT_470] = [__v_3]; - record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_469] = [__v_3]; + record.function_queries[469].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_471: usize = 3; -const IN_471: usize = 3; -const OUT_471: usize = 1; -fn aiur_fn_471( - inp: [G; IN_471], +const INPUT_SIZE_470: usize = 3; +const IN_470: usize = 3; +const OUT_470: usize = 1; +fn aiur_fn_470( + inp: [G; IN_470], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_471], ExecError> { +) -> Result<[G; OUT_470], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -42052,22 +42006,22 @@ fn aiur_fn_471( match __v_11.as_canonical_u64() { 0u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42080,16 +42034,16 @@ fn aiur_fn_471( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42106,26 +42060,26 @@ fn aiur_fn_471( let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_436] = { let __args: [G; IN_436] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[436].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[436].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[436].bump_multiplicity(__i); } let __ret: [G; OUT_436] = unsafe { *(record.function_queries[436].output_at(__i).as_ptr() as *const [G; OUT_436]) }; __ret }, _ => aiur_fn_436(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42138,31 +42092,31 @@ fn aiur_fn_471( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 3u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_5, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_5, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_13]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_13]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(1); - let __ret: [G; OUT_471] = [__v_13]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_13]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42170,10 +42124,10 @@ fn aiur_fn_471( } }, _ => { - let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42186,31 +42140,31 @@ fn aiur_fn_471( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 4u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 0u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_12, __v_4, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_14]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_14]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_468] = { let __args: [G; IN_468] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[468].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[468].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[468].bump_multiplicity(__i); } let __ret: [G; OUT_468] = unsafe { *(record.function_queries[468].output_at(__i).as_ptr() as *const [G; OUT_468]) }; __ret }, _ => aiur_fn_468(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_467] = { let __args: [G; IN_467] = [__v_4, __v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[467].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[467].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[467].bump_multiplicity(__i); } let __ret: [G; OUT_467] = unsafe { *(record.function_queries[467].output_at(__i).as_ptr() as *const [G; OUT_467]) }; __ret }, _ => aiur_fn_467(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42223,38 +42177,38 @@ fn aiur_fn_471( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_4, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 0u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_12, __v_4, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_5, __v_9, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_14]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_14]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 6u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_7]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_7]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { @@ -42265,28 +42219,28 @@ fn aiur_fn_471( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_4, __v_5, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_4, __v_5, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_399] = { let __args: [G; IN_399] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[399].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[399].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[399].bump_multiplicity(__i); } let __ret: [G; OUT_399] = unsafe { *(record.function_queries[399].output_at(__i).as_ptr() as *const [G; OUT_399]) }; __ret }, _ => aiur_fn_399(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_398] = { let __args: [G; IN_398] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[398].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[398].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[398].bump_multiplicity(__i); } let __ret: [G; OUT_398] = unsafe { *(record.function_queries[398].output_at(__i).as_ptr() as *const [G; OUT_398]) }; __ret }, _ => aiur_fn_398(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = (__v_11 - __v_0); match __v_12.as_canonical_u64() { 0u64 => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_13]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_13]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_11, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_470] = { let __args: [G; IN_470] = [__v_11, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[470].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[470].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[470].bump_multiplicity(__i); } let __ret: [G; OUT_470] = unsafe { *(record.function_queries[470].output_at(__i).as_ptr() as *const [G; OUT_470]) }; __ret }, _ => aiur_fn_470(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_13]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_13]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42308,32 +42262,32 @@ fn aiur_fn_471( let __v_12: G = (__v_5 - __v_9); match __v_12.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_6, __v_10, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_6, __v_10, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_471] = [__v_13]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_13]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_13]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_13]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_12]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_12]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_471] = [__v_11]; - record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_470] = [__v_11]; + record.function_queries[470].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42345,15 +42299,15 @@ fn aiur_fn_471( }) } -const INPUT_SIZE_472: usize = 4; -const IN_472: usize = 4; -const OUT_472: usize = 3; -fn aiur_fn_472( - inp: [G; IN_472], +const INPUT_SIZE_471: usize = 4; +const IN_471: usize = 4; +const OUT_471: usize = 3; +fn aiur_fn_471( + inp: [G; IN_471], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_472], ExecError> { +) -> Result<[G; OUT_471], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -42362,8 +42316,8 @@ fn aiur_fn_472( match __v_2.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_472] = [__v_4, __v_0, __v_1]; - record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_471] = [__v_4, __v_0, __v_1]; + record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -42371,46 +42325,46 @@ fn aiur_fn_472( match __v_4.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_472] = [__v_5, __v_0, __v_1]; - record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_471] = [__v_5, __v_0, __v_1]; + record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_446] = { let __args: [G; IN_446] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[446].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[446].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[446].bump_multiplicity(__i); } let __ret: [G; OUT_446] = unsafe { *(record.function_queries[446].output_at(__i).as_ptr() as *const [G; OUT_446]) }; __ret }, _ => aiur_fn_446(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_445] = { let __args: [G; IN_445] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[445].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[445].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[445].bump_multiplicity(__i); } let __ret: [G; OUT_445] = unsafe { *(record.function_queries[445].output_at(__i).as_ptr() as *const [G; OUT_445]) }; __ret }, _ => aiur_fn_445(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; match __v_5.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_472] = [__v_6, __v_0, __v_1]; - record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_471] = [__v_6, __v_0, __v_1]; + record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; match __v_8.as_canonical_u64() { 1u64 => { match __v_10.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_474] = { let __args: [G; IN_474] = [__v_7, __v_9, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[474].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[474].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[474].bump_multiplicity(__i); } let __ret: [G; OUT_474] = unsafe { *(record.function_queries[474].output_at(__i).as_ptr() as *const [G; OUT_474]) }; __ret }, _ => aiur_fn_474(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_473] = { let __args: [G; IN_473] = [__v_7, __v_9, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[473].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[473].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[473].bump_multiplicity(__i); } let __ret: [G; OUT_473] = unsafe { *(record.function_queries[473].output_at(__i).as_ptr() as *const [G; OUT_473]) }; __ret }, _ => aiur_fn_473(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; - let __ret: [G; OUT_472] = [__v_11, __v_12, __v_13]; - record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_471] = [__v_11, __v_12, __v_13]; + record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_478] = { let __args: [G; IN_478] = [__v_7, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[478].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[478].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[478].bump_multiplicity(__i); } let __ret: [G; OUT_478] = unsafe { *(record.function_queries[478].output_at(__i).as_ptr() as *const [G; OUT_478]) }; __ret }, _ => aiur_fn_478(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_477] = { let __args: [G; IN_477] = [__v_7, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[477].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[477].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[477].bump_multiplicity(__i); } let __ret: [G; OUT_477] = unsafe { *(record.function_queries[477].output_at(__i).as_ptr() as *const [G; OUT_477]) }; __ret }, _ => aiur_fn_477(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; - let __ret: [G; OUT_472] = [__v_11, __v_12, __v_13]; - record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_471] = [__v_11, __v_12, __v_13]; + record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42418,21 +42372,21 @@ fn aiur_fn_472( _ => { match __v_10.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_479] = { let __args: [G; IN_479] = [__v_9, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[479].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[479].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[479].bump_multiplicity(__i); } let __ret: [G; OUT_479] = unsafe { *(record.function_queries[479].output_at(__i).as_ptr() as *const [G; OUT_479]) }; __ret }, _ => aiur_fn_479(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_478] = { let __args: [G; IN_478] = [__v_9, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[478].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[478].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[478].bump_multiplicity(__i); } let __ret: [G; OUT_478] = unsafe { *(record.function_queries[478].output_at(__i).as_ptr() as *const [G; OUT_478]) }; __ret }, _ => aiur_fn_478(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; - let __ret: [G; OUT_472] = [__v_11, __v_12, __v_13]; - record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_471] = [__v_11, __v_12, __v_13]; + record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_480] = { let __args: [G; IN_480] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[480].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[480].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[480].bump_multiplicity(__i); } let __ret: [G; OUT_480] = unsafe { *(record.function_queries[480].output_at(__i).as_ptr() as *const [G; OUT_480]) }; __ret }, _ => aiur_fn_480(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_479] = { let __args: [G; IN_479] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[479].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[479].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[479].bump_multiplicity(__i); } let __ret: [G; OUT_479] = unsafe { *(record.function_queries[479].output_at(__i).as_ptr() as *const [G; OUT_479]) }; __ret }, _ => aiur_fn_479(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; - let __ret: [G; OUT_472] = [__v_11, __v_12, __v_13]; - record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_471] = [__v_11, __v_12, __v_13]; + record.function_queries[471].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42447,15 +42401,15 @@ fn aiur_fn_472( }) } -const INPUT_SIZE_473: usize = 12; -const IN_473: usize = 12; -const OUT_473: usize = 1; -fn aiur_fn_473( - inp: [G; IN_473], +const INPUT_SIZE_472: usize = 12; +const IN_472: usize = 12; +const OUT_472: usize = 1; +fn aiur_fn_472( + inp: [G; IN_472], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_473], ExecError> { +) -> Result<[G; OUT_472], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -42471,29 +42425,29 @@ fn aiur_fn_473( let __v_11: G = inp[11]; match __v_0.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_473] = [__v_5]; - record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_472] = [__v_5]; + record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_473] = [__v_12]; - record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_472] = [__v_12]; + record.function_queries[472].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_474: usize = 6; -const IN_474: usize = 6; -const OUT_474: usize = 3; -fn aiur_fn_474( - inp: [G; IN_474], +const INPUT_SIZE_473: usize = 6; +const IN_473: usize = 6; +const OUT_473: usize = 3; +fn aiur_fn_473( + inp: [G; IN_473], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_474], ExecError> { +) -> Result<[G; OUT_473], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -42501,7 +42455,7 @@ fn aiur_fn_474( let __v_3: G = inp[3]; let __v_4: G = inp[4]; let __v_5: G = inp[5]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_6.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_7: G = __loaded[0]; @@ -42516,7 +42470,7 @@ fn aiur_fn_474( let __v_16: G = __loaded[9]; let __v_17: G = __loaded[10]; let __v_18: G = __loaded[11]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_19.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_20: G = __loaded[0]; @@ -42531,26 +42485,26 @@ fn aiur_fn_474( let __v_29: G = __loaded[9]; let __v_30: G = __loaded[10]; let __v_31: G = __loaded[11]; - let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_480] = { let __args: [G; IN_480] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[480].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[480].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[480].bump_multiplicity(__i); } let __ret: [G; OUT_480] = unsafe { *(record.function_queries[480].output_at(__i).as_ptr() as *const [G; OUT_480]) }; __ret }, _ => aiur_fn_480(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; - let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_480] = { let __args: [G; IN_480] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[480].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[480].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[480].bump_multiplicity(__i); } let __ret: [G; OUT_480] = unsafe { *(record.function_queries[480].output_at(__i).as_ptr() as *const [G; OUT_480]) }; __ret }, _ => aiur_fn_480(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; match __v_32.as_canonical_u64() { 0u64 => { match __v_33.as_canonical_u64() { 0u64 => { let __v_34: G = G::from_u64(0); - let __ret: [G; OUT_474] = [__v_34, __v_2, __v_3]; - record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_473] = [__v_34, __v_2, __v_3]; + record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_476] = { let __args: [G; IN_476] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[476].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[476].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[476].bump_multiplicity(__i); } let __ret: [G; OUT_476] = unsafe { *(record.function_queries[476].output_at(__i).as_ptr() as *const [G; OUT_476]) }; __ret }, _ => aiur_fn_476(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_475] = { let __args: [G; IN_475] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[475].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[475].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[475].bump_multiplicity(__i); } let __ret: [G; OUT_475] = unsafe { *(record.function_queries[475].output_at(__i).as_ptr() as *const [G; OUT_475]) }; __ret }, _ => aiur_fn_475(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = __r_arr[2]; - let __ret: [G; OUT_474] = [__v_34, __v_35, __v_36]; - record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_473] = [__v_34, __v_35, __v_36]; + record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42558,49 +42512,49 @@ fn aiur_fn_474( _ => { match __v_33.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_475] = { let __args: [G; IN_475] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[475].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[475].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[475].bump_multiplicity(__i); } let __ret: [G; OUT_475] = unsafe { *(record.function_queries[475].output_at(__i).as_ptr() as *const [G; OUT_475]) }; __ret }, _ => aiur_fn_475(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_474] = { let __args: [G; IN_474] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[474].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[474].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[474].bump_multiplicity(__i); } let __ret: [G; OUT_474] = unsafe { *(record.function_queries[474].output_at(__i).as_ptr() as *const [G; OUT_474]) }; __ret }, _ => aiur_fn_474(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = __r_arr[2]; - let __ret: [G; OUT_474] = [__v_34, __v_35, __v_36]; - record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_473] = [__v_34, __v_35, __v_36]; + record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_473] = { let __args: [G; IN_473] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[473].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[473].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[473].bump_multiplicity(__i); } let __ret: [G; OUT_473] = unsafe { *(record.function_queries[473].output_at(__i).as_ptr() as *const [G; OUT_473]) }; __ret }, _ => aiur_fn_473(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __r_arr: [G; OUT_473] = { let __args: [G; IN_473] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[473].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[473].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[473].bump_multiplicity(__i); } let __ret: [G; OUT_473] = unsafe { *(record.function_queries[473].output_at(__i).as_ptr() as *const [G; OUT_473]) }; __ret }, _ => aiur_fn_473(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = { let __a_val = __v_35.as_canonical_u64(); let __b_val = __v_34.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_36.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_475] = { let __args: [G; IN_475] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[475].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[475].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[475].bump_multiplicity(__i); } let __ret: [G; OUT_475] = unsafe { *(record.function_queries[475].output_at(__i).as_ptr() as *const [G; OUT_475]) }; __ret }, _ => aiur_fn_475(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_474] = { let __args: [G; IN_474] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[474].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[474].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[474].bump_multiplicity(__i); } let __ret: [G; OUT_474] = unsafe { *(record.function_queries[474].output_at(__i).as_ptr() as *const [G; OUT_474]) }; __ret }, _ => aiur_fn_474(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = __r_arr[1]; let __v_39: G = __r_arr[2]; - let __ret: [G; OUT_474] = [__v_37, __v_38, __v_39]; - record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_473] = [__v_37, __v_38, __v_39]; + record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_37: G = { let __a_val = __v_34.as_canonical_u64(); let __b_val = __v_35.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_37.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_476] = { let __args: [G; IN_476] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[476].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[476].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[476].bump_multiplicity(__i); } let __ret: [G; OUT_476] = unsafe { *(record.function_queries[476].output_at(__i).as_ptr() as *const [G; OUT_476]) }; __ret }, _ => aiur_fn_476(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_475] = { let __args: [G; IN_475] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[475].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[475].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[475].bump_multiplicity(__i); } let __ret: [G; OUT_475] = unsafe { *(record.function_queries[475].output_at(__i).as_ptr() as *const [G; OUT_475]) }; __ret }, _ => aiur_fn_475(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; let __v_40: G = __r_arr[2]; - let __ret: [G; OUT_474] = [__v_38, __v_39, __v_40]; - record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_473] = [__v_38, __v_39, __v_40]; + record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_477] = { let __args: [G; IN_477] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[477].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[477].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[477].bump_multiplicity(__i); } let __ret: [G; OUT_477] = unsafe { *(record.function_queries[477].output_at(__i).as_ptr() as *const [G; OUT_477]) }; __ret }, _ => aiur_fn_477(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_476] = { let __args: [G; IN_476] = [__v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[476].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[476].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[476].bump_multiplicity(__i); } let __ret: [G; OUT_476] = unsafe { *(record.function_queries[476].output_at(__i).as_ptr() as *const [G; OUT_476]) }; __ret }, _ => aiur_fn_476(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; let __v_40: G = __r_arr[2]; - let __ret: [G; OUT_474] = [__v_38, __v_39, __v_40]; - record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_473] = [__v_38, __v_39, __v_40]; + record.function_queries[473].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42613,176 +42567,176 @@ fn aiur_fn_474( }) } -const INPUT_SIZE_475: usize = 4; -const IN_475: usize = 4; -const OUT_475: usize = 3; -fn aiur_fn_475( - inp: [G; IN_475], +const INPUT_SIZE_474: usize = 4; +const IN_474: usize = 4; +const OUT_474: usize = 3; +fn aiur_fn_474( + inp: [G; IN_474], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_475], ExecError> { +) -> Result<[G; OUT_474], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_2 - __v_7); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_6, __v_1, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_6, __v_1, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = __r_arr[2]; - let __ret: [G; OUT_475] = [__v_9, __v_10, __v_11]; - record.function_queries[475].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_474] = [__v_9, __v_10, __v_11]; + record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_475] = [__v_6, __v_0, __v_1]; - record.function_queries[475].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_474] = [__v_6, __v_0, __v_1]; + record.function_queries[474].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_476: usize = 4; -const IN_476: usize = 4; -const OUT_476: usize = 3; -fn aiur_fn_476( - inp: [G; IN_476], +const INPUT_SIZE_475: usize = 4; +const IN_475: usize = 4; +const OUT_475: usize = 3; +fn aiur_fn_475( + inp: [G; IN_475], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_476], ExecError> { +) -> Result<[G; OUT_475], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_2 - __v_7); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_0, __v_6, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_0, __v_6, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = __r_arr[2]; - let __ret: [G; OUT_476] = [__v_9, __v_10, __v_11]; - record.function_queries[476].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_475] = [__v_9, __v_10, __v_11]; + record.function_queries[475].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_476] = [__v_6, __v_0, __v_1]; - record.function_queries[476].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_475] = [__v_6, __v_0, __v_1]; + record.function_queries[475].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_477: usize = 4; -const IN_477: usize = 4; -const OUT_477: usize = 3; -fn aiur_fn_477( - inp: [G; IN_477], +const INPUT_SIZE_476: usize = 4; +const IN_476: usize = 4; +const OUT_476: usize = 3; +fn aiur_fn_476( + inp: [G; IN_476], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_477], ExecError> { +) -> Result<[G; OUT_476], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(1); let __v_11: G = (__v_2 - __v_10); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_8, __v_9, __v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_8, __v_9, __v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; let __v_14: G = __r_arr[2]; - let __ret: [G; OUT_477] = [__v_12, __v_13, __v_14]; - record.function_queries[477].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_476] = [__v_12, __v_13, __v_14]; + record.function_queries[476].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_477] = [__v_8, __v_0, __v_1]; - record.function_queries[477].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_476] = [__v_8, __v_0, __v_1]; + record.function_queries[476].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_477] = [__v_6, __v_0, __v_1]; - record.function_queries[477].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_476] = [__v_6, __v_0, __v_1]; + record.function_queries[476].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_478: usize = 5; -const IN_478: usize = 5; -const OUT_478: usize = 3; -fn aiur_fn_478( - inp: [G; IN_478], +const INPUT_SIZE_477: usize = 5; +const IN_477: usize = 5; +const OUT_477: usize = 3; +fn aiur_fn_477( + inp: [G; IN_477], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_478], ExecError> { +) -> Result<[G; OUT_477], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; match __v_5.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_3 - __v_7); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_1, __v_6, __v_8, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_1, __v_6, __v_8, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = __r_arr[2]; - let __ret: [G; OUT_478] = [__v_9, __v_10, __v_11]; - record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_477] = [__v_9, __v_10, __v_11]; + record.function_queries[477].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -42797,35 +42751,35 @@ fn aiur_fn_478( let __v_17: G = __loaded[9]; let __v_18: G = __loaded[10]; let __v_19: G = __loaded[11]; - let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_480] = { let __args: [G; IN_480] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[480].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[480].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[480].bump_multiplicity(__i); } let __ret: [G; OUT_480] = unsafe { *(record.function_queries[480].output_at(__i).as_ptr() as *const [G; OUT_480]) }; __ret }, _ => aiur_fn_480(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; match __v_20.as_canonical_u64() { 0u64 => { let __v_21: G = G::from_u64(0); - let __ret: [G; OUT_478] = [__v_21, __v_1, __v_2]; - record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_477] = [__v_21, __v_1, __v_2]; + record.function_queries[477].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_1, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_1, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = __r_arr[1]; match __v_21.as_canonical_u64() { 1u64 => { let __v_23: G = G::from_u64(1); let __v_24: G = (__v_3 - __v_23); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_22, __v_2, __v_24, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_22, __v_2, __v_24, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = __r_arr[1]; let __v_27: G = __r_arr[2]; - let __ret: [G; OUT_478] = [__v_25, __v_26, __v_27]; - record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_477] = [__v_25, __v_26, __v_27]; + record.function_queries[477].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_23: G = G::from_u64(0); - let __ret: [G; OUT_478] = [__v_23, __v_1, __v_2]; - record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_477] = [__v_23, __v_1, __v_2]; + record.function_queries[477].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42836,38 +42790,38 @@ fn aiur_fn_478( }) } -const INPUT_SIZE_479: usize = 5; -const IN_479: usize = 5; -const OUT_479: usize = 3; -fn aiur_fn_479( - inp: [G; IN_479], +const INPUT_SIZE_478: usize = 5; +const IN_478: usize = 5; +const OUT_478: usize = 3; +fn aiur_fn_478( + inp: [G; IN_478], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_479], ExecError> { +) -> Result<[G; OUT_478], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; match __v_5.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_3 - __v_7); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_6, __v_2, __v_8, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_6, __v_2, __v_8, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = __r_arr[2]; - let __ret: [G; OUT_479] = [__v_9, __v_10, __v_11]; - record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_478] = [__v_9, __v_10, __v_11]; + record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -42882,35 +42836,35 @@ fn aiur_fn_479( let __v_17: G = __loaded[9]; let __v_18: G = __loaded[10]; let __v_19: G = __loaded[11]; - let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_480] = { let __args: [G; IN_480] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[480].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[480].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[480].bump_multiplicity(__i); } let __ret: [G; OUT_480] = unsafe { *(record.function_queries[480].output_at(__i).as_ptr() as *const [G; OUT_480]) }; __ret }, _ => aiur_fn_480(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; match __v_20.as_canonical_u64() { 0u64 => { let __v_21: G = G::from_u64(0); - let __ret: [G; OUT_479] = [__v_21, __v_1, __v_2]; - record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_478] = [__v_21, __v_1, __v_2]; + record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_2, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_2, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = __r_arr[1]; match __v_21.as_canonical_u64() { 1u64 => { let __v_23: G = G::from_u64(1); let __v_24: G = (__v_3 - __v_23); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_1, __v_22, __v_24, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_1, __v_22, __v_24, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = __r_arr[1]; let __v_27: G = __r_arr[2]; - let __ret: [G; OUT_479] = [__v_25, __v_26, __v_27]; - record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_478] = [__v_25, __v_26, __v_27]; + record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_23: G = G::from_u64(0); - let __ret: [G; OUT_479] = [__v_23, __v_1, __v_2]; - record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_478] = [__v_23, __v_1, __v_2]; + record.function_queries[478].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42921,24 +42875,24 @@ fn aiur_fn_479( }) } -const INPUT_SIZE_480: usize = 4; -const IN_480: usize = 4; -const OUT_480: usize = 3; -fn aiur_fn_480( - inp: [G; IN_480], +const INPUT_SIZE_479: usize = 4; +const IN_479: usize = 4; +const OUT_479: usize = 3; +fn aiur_fn_479( + inp: [G; IN_479], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_480], ExecError> { +) -> Result<[G; OUT_479], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; - let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_481] = { let __args: [G; IN_481] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[481].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[481].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[481].bump_multiplicity(__i); } let __ret: [G; OUT_481] = unsafe { *(record.function_queries[481].output_at(__i).as_ptr() as *const [G; OUT_481]) }; __ret }, _ => aiur_fn_481(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; match __v_4.as_canonical_u64() { @@ -42947,23 +42901,23 @@ fn aiur_fn_480( 1u64 => { let __v_8: G = G::from_u64(1); let __v_9: G = (__v_2 - __v_8); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_5, __v_7, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_5, __v_7, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; - let __ret: [G; OUT_480] = [__v_10, __v_11, __v_12]; - record.function_queries[480].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_479] = [__v_10, __v_11, __v_12]; + record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(1); let __v_9: G = (__v_2 - __v_8); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_5, __v_1, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_5, __v_1, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; - let __ret: [G; OUT_480] = [__v_10, __v_11, __v_12]; - record.function_queries[480].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_479] = [__v_10, __v_11, __v_12]; + record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42973,18 +42927,18 @@ fn aiur_fn_480( 1u64 => { let __v_8: G = G::from_u64(1); let __v_9: G = (__v_2 - __v_8); - let __r_arr: [G; OUT_472] = { let __args: [G; IN_472] = [__v_0, __v_7, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[472].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[472].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[472].bump_multiplicity(__i); } let __ret: [G; OUT_472] = unsafe { *(record.function_queries[472].output_at(__i).as_ptr() as *const [G; OUT_472]) }; __ret }, _ => aiur_fn_472(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_471] = { let __args: [G; IN_471] = [__v_0, __v_7, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[471].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[471].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[471].bump_multiplicity(__i); } let __ret: [G; OUT_471] = unsafe { *(record.function_queries[471].output_at(__i).as_ptr() as *const [G; OUT_471]) }; __ret }, _ => aiur_fn_471(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; - let __ret: [G; OUT_480] = [__v_10, __v_11, __v_12]; - record.function_queries[480].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_479] = [__v_10, __v_11, __v_12]; + record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_480] = [__v_8, __v_0, __v_1]; - record.function_queries[480].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_479] = [__v_8, __v_0, __v_1]; + record.function_queries[479].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -42993,15 +42947,15 @@ fn aiur_fn_480( }) } -const INPUT_SIZE_481: usize = 12; -const IN_481: usize = 12; -const OUT_481: usize = 1; -fn aiur_fn_481( - inp: [G; IN_481], +const INPUT_SIZE_480: usize = 12; +const IN_480: usize = 12; +const OUT_480: usize = 1; +fn aiur_fn_480( + inp: [G; IN_480], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_481], ExecError> { +) -> Result<[G; OUT_480], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -43018,35 +42972,35 @@ fn aiur_fn_481( match __v_0.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_481] = [__v_12]; - record.function_queries[481].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_480] = [__v_12]; + record.function_queries[480].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_481] = [__v_12]; - record.function_queries[481].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_480] = [__v_12]; + record.function_queries[480].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_481] = [__v_12]; - record.function_queries[481].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_480] = [__v_12]; + record.function_queries[480].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_482: usize = 2; -const IN_482: usize = 2; -const OUT_482: usize = 2; -fn aiur_fn_482( - inp: [G; IN_482], +const INPUT_SIZE_481: usize = 2; +const IN_481: usize = 2; +const OUT_481: usize = 2; +fn aiur_fn_481( + inp: [G; IN_481], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_482], ExecError> { +) -> Result<[G; OUT_481], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -43060,7 +43014,7 @@ fn aiur_fn_482( let __v_7: G = __loaded[3]; match __v_4.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; @@ -43072,7 +43026,7 @@ fn aiur_fn_482( let __v_14: G = __loaded[3]; match __v_11.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; match __v_15.as_canonical_u64() { @@ -43080,47 +43034,47 @@ fn aiur_fn_482( let __v_17: G = G::from_u64(8); let __v_18: G = { let __values: [G; 4] = [__v_17, __v_5, __v_6, __v_16]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_19: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_18, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_18, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_482] = [__v_19, __v_20]; - record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_481] = [__v_19, __v_20]; + record.function_queries[481].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_482] = [__v_17, __v_0]; - record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_481] = [__v_17, __v_0]; + record.function_queries[481].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_15: G = G::from_u64(1); - let __ret: [G; OUT_482] = [__v_15, __v_8]; - record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_481] = [__v_15, __v_8]; + record.function_queries[481].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_482] = [__v_8, __v_0]; - record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_481] = [__v_8, __v_0]; + record.function_queries[481].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_483: usize = 1; -const IN_483: usize = 1; -const OUT_483: usize = 2; -fn aiur_fn_483( - inp: [G; IN_483], +const INPUT_SIZE_482: usize = 1; +const IN_482: usize = 1; +const OUT_482: usize = 2; +fn aiur_fn_482( + inp: [G; IN_482], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_483], ExecError> { +) -> Result<[G; OUT_482], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; @@ -43133,7 +43087,7 @@ fn aiur_fn_483( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -43150,79 +43104,79 @@ fn aiur_fn_483( let __v_19: G = __loaded[11]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_11, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_11, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_20, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_20, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_483] = [__v_21, __v_22]; - record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_482] = [__v_21, __v_22]; + record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_11, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_11, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_20, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_20, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_483] = [__v_21, __v_22]; - record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_482] = [__v_21, __v_22]; + record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_20: G = G::from_u64(0); - let __ret: [G; OUT_483] = [__v_20, __v_0]; - record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_482] = [__v_20, __v_0]; + record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_483] = [__v_7, __v_0]; - record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_482] = [__v_7, __v_0]; + record.function_queries[482].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_484: usize = 3; -const IN_484: usize = 3; -const OUT_484: usize = 1; -fn aiur_fn_484( - inp: [G; IN_484], +const INPUT_SIZE_483: usize = 3; +const IN_483: usize = 3; +const OUT_483: usize = 1; +fn aiur_fn_483( + inp: [G; IN_483], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_484], ExecError> { +) -> Result<[G; OUT_483], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; - let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_484] = { let __args: [G; IN_484] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[484].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[484].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[484].bump_multiplicity(__i); } let __ret: [G; OUT_484] = unsafe { *(record.function_queries[484].output_at(__i).as_ptr() as *const [G; OUT_484]) }; __ret }, _ => aiur_fn_484(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; match __v_4.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_484] = [__v_7]; - record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_483] = [__v_7]; + record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_484] = [__v_7]; - record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_483] = [__v_7]; + record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -43237,7 +43191,7 @@ fn aiur_fn_484( let __v_17: G = __loaded[9]; let __v_18: G = __loaded[10]; let __v_19: G = __loaded[11]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_20.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_21: G = __loaded[0]; @@ -43252,27 +43206,27 @@ fn aiur_fn_484( let __v_30: G = __loaded[9]; let __v_31: G = __loaded[10]; let __v_32: G = __loaded[11]; - let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_0, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_0, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; let __v_34: G = __r_arr[1]; - let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_1, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_485] = { let __args: [G; IN_485] = [__v_1, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[485].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[485].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[485].bump_multiplicity(__i); } let __ret: [G; OUT_485] = unsafe { *(record.function_queries[485].output_at(__i).as_ptr() as *const [G; OUT_485]) }; __ret }, _ => aiur_fn_485(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = __r_arr[1]; match __v_33.as_canonical_u64() { 1u64 => { match __v_35.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_34, __v_36, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_34, __v_36, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; - let __ret: [G; OUT_484] = [__v_37]; - record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_483] = [__v_37]; + record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_34, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_34, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; - let __ret: [G; OUT_484] = [__v_37]; - record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_483] = [__v_37]; + record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -43280,16 +43234,16 @@ fn aiur_fn_484( 0u64 => { match __v_35.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_0, __v_36, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_0, __v_36, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; - let __ret: [G; OUT_484] = [__v_37]; - record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_483] = [__v_37]; + record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_37: G = G::from_u64(0); - let __ret: [G; OUT_484] = [__v_37]; - record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_483] = [__v_37]; + record.function_queries[483].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -43305,15 +43259,15 @@ fn aiur_fn_484( }) } -const INPUT_SIZE_485: usize = 1; -const IN_485: usize = 1; -const OUT_485: usize = 2; -fn aiur_fn_485( - inp: [G; IN_485], +const INPUT_SIZE_484: usize = 1; +const IN_484: usize = 1; +const OUT_484: usize = 2; +fn aiur_fn_484( + inp: [G; IN_484], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_485], ExecError> { +) -> Result<[G; OUT_484], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; @@ -43327,8 +43281,8 @@ fn aiur_fn_485( match __v_3.as_canonical_u64() { 2u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_485] = [__v_4, __v_7]; - record.function_queries[485].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_484] = [__v_4, __v_7]; + record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -43366,23 +43320,23 @@ fn aiur_fn_485( let __v_38: G = G::from_u64(0); let __v_39: G = { let __values: [G; 32] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_40: G = G::from_u64(0); - let __ret: [G; OUT_485] = [__v_39, __v_40]; - record.function_queries[485].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_484] = [__v_39, __v_40]; + record.function_queries[484].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_486: usize = 14; -const IN_486: usize = 14; -const OUT_486: usize = 2; -fn aiur_fn_486( - inp: [G; IN_486], +const INPUT_SIZE_485: usize = 14; +const IN_485: usize = 14; +const OUT_485: usize = 2; +fn aiur_fn_485( + inp: [G; IN_485], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_486], ExecError> { +) -> Result<[G; OUT_485], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -43400,154 +43354,154 @@ fn aiur_fn_486( let __v_13: G = inp[13]; match __v_1.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; match __v_14.as_canonical_u64() { 1u64 => { let __v_16: G = G::from_u64(1); - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_15, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_15, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_486] = [__v_16, __v_17]; - record.function_queries[486].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_485] = [__v_16, __v_17]; + record.function_queries[485].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_16: G = G::from_u64(0); - let __ret: [G; OUT_486] = [__v_16, __v_0]; - record.function_queries[486].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_485] = [__v_16, __v_0]; + record.function_queries[485].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 2u64 => { - let __r_arr: [G; OUT_483] = { let __args: [G; IN_483] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[483].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[483].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[483].bump_multiplicity(__i); } let __ret: [G; OUT_483] = unsafe { *(record.function_queries[483].output_at(__i).as_ptr() as *const [G; OUT_483]) }; __ret }, _ => aiur_fn_483(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_482] = { let __args: [G; IN_482] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[482].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[482].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[482].bump_multiplicity(__i); } let __ret: [G; OUT_482] = unsafe { *(record.function_queries[482].output_at(__i).as_ptr() as *const [G; OUT_482]) }; __ret }, _ => aiur_fn_482(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; match __v_14.as_canonical_u64() { 1u64 => { let __v_16: G = G::from_u64(1); - let __r_arr: [G; OUT_423] = { let __args: [G; IN_423] = [__v_15, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[423].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[423].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[423].bump_multiplicity(__i); } let __ret: [G; OUT_423] = unsafe { *(record.function_queries[423].output_at(__i).as_ptr() as *const [G; OUT_423]) }; __ret }, _ => aiur_fn_423(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_422] = { let __args: [G; IN_422] = [__v_15, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[422].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[422].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[422].bump_multiplicity(__i); } let __ret: [G; OUT_422] = unsafe { *(record.function_queries[422].output_at(__i).as_ptr() as *const [G; OUT_422]) }; __ret }, _ => aiur_fn_422(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_486] = [__v_16, __v_17]; - record.function_queries[486].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_485] = [__v_16, __v_17]; + record.function_queries[485].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_16: G = G::from_u64(0); - let __ret: [G; OUT_486] = [__v_16, __v_0]; - record.function_queries[486].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_485] = [__v_16, __v_0]; + record.function_queries[485].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_14: G = G::from_u64(0); - let __ret: [G; OUT_486] = [__v_14, __v_0]; - record.function_queries[486].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_485] = [__v_14, __v_0]; + record.function_queries[485].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_487: usize = 2; -const IN_487: usize = 2; -const OUT_487: usize = 1; -fn aiur_fn_487( - inp: [G; IN_487], +const INPUT_SIZE_486: usize = 2; +const IN_486: usize = 2; +const OUT_486: usize = 1; +fn aiur_fn_486( + inp: [G; IN_486], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_487], ExecError> { +) -> Result<[G; OUT_486], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 0u64 => { let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_489] = { let __args: [G; IN_489] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[489].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[489].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[489].bump_multiplicity(__i); } let __ret: [G; OUT_489] = unsafe { *(record.function_queries[489].output_at(__i).as_ptr() as *const [G; OUT_489]) }; __ret }, _ => aiur_fn_489(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_488] = { let __args: [G; IN_488] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[488].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[488].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[488].bump_multiplicity(__i); } let __ret: [G; OUT_488] = unsafe { *(record.function_queries[488].output_at(__i).as_ptr() as *const [G; OUT_488]) }; __ret }, _ => aiur_fn_488(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_487] = [__v_6]; - record.function_queries[487].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_486] = [__v_6]; + record.function_queries[486].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_488] = { let __args: [G; IN_488] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[488].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[488].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[488].bump_multiplicity(__i); } let __ret: [G; OUT_488] = unsafe { *(record.function_queries[488].output_at(__i).as_ptr() as *const [G; OUT_488]) }; __ret }, _ => aiur_fn_488(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __ret: [G; OUT_487] = [__v_3]; - record.function_queries[487].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_486] = [__v_3]; + record.function_queries[486].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_488: usize = 3; -const IN_488: usize = 3; -const OUT_488: usize = 1; -fn aiur_fn_488( - inp: [G; IN_488], +const INPUT_SIZE_487: usize = 3; +const IN_487: usize = 3; +const OUT_487: usize = 1; +fn aiur_fn_487( + inp: [G; IN_487], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_488], ExecError> { +) -> Result<[G; OUT_487], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = G::from_u64(0); - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_344] = { let __args: [G; IN_344] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[344].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[344].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[344].bump_multiplicity(__i); } let __ret: [G; OUT_344] = unsafe { *(record.function_queries[344].output_at(__i).as_ptr() as *const [G; OUT_344]) }; __ret }, _ => aiur_fn_344(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_489] = { let __args: [G; IN_489] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[489].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[489].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[489].bump_multiplicity(__i); } let __ret: [G; OUT_489] = unsafe { *(record.function_queries[489].output_at(__i).as_ptr() as *const [G; OUT_489]) }; __ret }, _ => aiur_fn_489(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_488] = { let __args: [G; IN_488] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[488].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[488].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[488].bump_multiplicity(__i); } let __ret: [G; OUT_488] = unsafe { *(record.function_queries[488].output_at(__i).as_ptr() as *const [G; OUT_488]) }; __ret }, _ => aiur_fn_488(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_488] = [__v_8]; - record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_487] = [__v_8]; + record.function_queries[487].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_0, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_0, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = (__v_2 - __v_6); - let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_352] = { let __args: [G; IN_352] = [__v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[352].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[352].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[352].bump_multiplicity(__i); } let __ret: [G; OUT_352] = unsafe { *(record.function_queries[352].output_at(__i).as_ptr() as *const [G; OUT_352]) }; __ret }, _ => aiur_fn_352(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_489] = { let __args: [G; IN_489] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[489].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[489].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[489].bump_multiplicity(__i); } let __ret: [G; OUT_489] = unsafe { *(record.function_queries[489].output_at(__i).as_ptr() as *const [G; OUT_489]) }; __ret }, _ => aiur_fn_489(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_488] = { let __args: [G; IN_488] = [__v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[488].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[488].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[488].bump_multiplicity(__i); } let __ret: [G; OUT_488] = unsafe { *(record.function_queries[488].output_at(__i).as_ptr() as *const [G; OUT_488]) }; __ret }, _ => aiur_fn_488(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_12, __v_6, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_12, __v_6, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_488] = [__v_14]; - record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_487] = [__v_14]; + record.function_queries[487].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_489: usize = 2; -const IN_489: usize = 2; -const OUT_489: usize = 1; -fn aiur_fn_489( - inp: [G; IN_489], +const INPUT_SIZE_488: usize = 2; +const IN_488: usize = 2; +const OUT_488: usize = 1; +fn aiur_fn_488( + inp: [G; IN_488], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_489], ExecError> { +) -> Result<[G; OUT_488], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -43558,15 +43512,15 @@ fn aiur_fn_489( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_3 + __v_7); let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_6, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_6, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_489] = [__v_10]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_10]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -43574,16 +43528,16 @@ fn aiur_fn_489( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_3, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_333] = { let __args: [G; IN_333] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[333].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[333].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[333].bump_multiplicity(__i); } let __ret: [G; OUT_333] = unsafe { *(record.function_queries[333].output_at(__i).as_ptr() as *const [G; OUT_333]) }; __ret }, _ => aiur_fn_333(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_6, __v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_489] = [__v_12]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_12]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_6.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_7: G = __loaded[0]; @@ -43598,85 +43552,85 @@ fn aiur_fn_489( let __v_16: G = __loaded[9]; let __v_17: G = __loaded[10]; let __v_18: G = __loaded[11]; - let __r_arr: [G; OUT_430] = { let __args: [G; IN_430] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[430].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[430].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[430].bump_multiplicity(__i); } let __ret: [G; OUT_430] = unsafe { *(record.function_queries[430].output_at(__i).as_ptr() as *const [G; OUT_430]) }; __ret }, _ => aiur_fn_430(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_429] = { let __args: [G; IN_429] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[429].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[429].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[429].bump_multiplicity(__i); } let __ret: [G; OUT_429] = unsafe { *(record.function_queries[429].output_at(__i).as_ptr() as *const [G; OUT_429]) }; __ret }, _ => aiur_fn_429(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; if (__v_20 != __v_19) { return Err(ExecError::AssertEqMismatch { lhs: __v_20.as_canonical_u64(), rhs: __v_19.as_canonical_u64(), msg: Some("Const applied to wrong number of universe levels".to_string()) }); } - let __r_arr: [G; OUT_431] = { let __args: [G; IN_431] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[431].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[431].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[431].bump_multiplicity(__i); } let __ret: [G; OUT_431] = unsafe { *(record.function_queries[431].output_at(__i).as_ptr() as *const [G; OUT_431]) }; __ret }, _ => aiur_fn_431(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_430] = { let __args: [G; IN_430] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[430].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[430].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[430].bump_multiplicity(__i); } let __ret: [G; OUT_430] = unsafe { *(record.function_queries[430].output_at(__i).as_ptr() as *const [G; OUT_430]) }; __ret }, _ => aiur_fn_430(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_21, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_489] = [__v_22]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_22]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); let __v_10: G = G::from_u64(1); let __v_11: G = { let __values: [G; 3] = [__v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_501] = { let __args: [G; IN_501] = [__v_8, __v_7, __v_11, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[501].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[501].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[501].bump_multiplicity(__i); } let __ret: [G; OUT_501] = unsafe { *(record.function_queries[501].output_at(__i).as_ptr() as *const [G; OUT_501]) }; __ret }, _ => aiur_fn_501(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_500] = { let __args: [G; IN_500] = [__v_8, __v_7, __v_11, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[500].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[500].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[500].bump_multiplicity(__i); } let __ret: [G; OUT_500] = unsafe { *(record.function_queries[500].output_at(__i).as_ptr() as *const [G; OUT_500]) }; __ret }, _ => aiur_fn_500(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_489] = [__v_12]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_12]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 3] = [__v_7, __v_3, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(5); let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_10, __v_3, __v_9, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_489] = [__v_12]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_12]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 3] = [__v_7, __v_3, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(1); - let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 4] = [__v_10, __v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_489] = [__v_13]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_13]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_490] = { let __args: [G; IN_490] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[490].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[490].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[490].bump_multiplicity(__i); } let __ret: [G; OUT_490] = unsafe { *(record.function_queries[490].output_at(__i).as_ptr() as *const [G; OUT_490]) }; __ret }, _ => aiur_fn_490(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_489] = { let __args: [G; IN_489] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[489].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[489].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[489].bump_multiplicity(__i); } let __ret: [G; OUT_489] = unsafe { *(record.function_queries[489].output_at(__i).as_ptr() as *const [G; OUT_489]) }; __ret }, _ => aiur_fn_489(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_489] = [__v_6]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_6]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __r_arr: [G; OUT_502] = { let __args: [G; IN_502] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[502].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[502].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[502].bump_multiplicity(__i); } let __ret: [G; OUT_502] = unsafe { *(record.function_queries[502].output_at(__i).as_ptr() as *const [G; OUT_502]) }; __ret }, _ => aiur_fn_502(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_501] = { let __args: [G; IN_501] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[501].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[501].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[501].bump_multiplicity(__i); } let __ret: [G; OUT_501] = unsafe { *(record.function_queries[501].output_at(__i).as_ptr() as *const [G; OUT_501]) }; __ret }, _ => aiur_fn_501(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_489] = [__v_6]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_6]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_507] = { let __args: [G; IN_507] = [__v_3, __v_4, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[507].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[507].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[507].bump_multiplicity(__i); } let __ret: [G; OUT_507] = unsafe { *(record.function_queries[507].output_at(__i).as_ptr() as *const [G; OUT_507]) }; __ret }, _ => aiur_fn_507(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_489] = [__v_6]; - record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_488] = [__v_6]; + record.function_queries[488].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -43686,74 +43640,74 @@ fn aiur_fn_489( }) } -const INPUT_SIZE_490: usize = 4; -const IN_490: usize = 4; -const OUT_490: usize = 1; -fn aiur_fn_490( - inp: [G; IN_490], +const INPUT_SIZE_489: usize = 4; +const IN_489: usize = 4; +const OUT_489: usize = 1; +fn aiur_fn_489( + inp: [G; IN_489], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_490], ExecError> { +) -> Result<[G; OUT_489], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = [__v_1, __v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_1, __v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 5] = [__v_6, __v_3, __v_5, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_9: G = G::from_u64(2); let __v_10: G = { let __values: [G; 5] = [__v_9, __v_0, __v_1, __v_8, __v_5]; let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_2, __v_10, __v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_2, __v_10, __v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_490] = [__v_11]; - record.function_queries[490].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_489] = [__v_11]; + record.function_queries[489].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_491: usize = 4; -const IN_491: usize = 4; -const OUT_491: usize = 1; -fn aiur_fn_491( - inp: [G; IN_491], +const INPUT_SIZE_490: usize = 4; +const IN_490: usize = 4; +const OUT_490: usize = 1; +fn aiur_fn_490( + inp: [G; IN_490], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_491], ExecError> { +) -> Result<[G; OUT_490], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_492] = { let __args: [G; IN_492] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[492].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[492].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[492].bump_multiplicity(__i); } let __ret: [G; OUT_492] = unsafe { *(record.function_queries[492].output_at(__i).as_ptr() as *const [G; OUT_492]) }; __ret }, _ => aiur_fn_492(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_491] = { let __args: [G; IN_491] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[491].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[491].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[491].bump_multiplicity(__i); } let __ret: [G; OUT_491] = unsafe { *(record.function_queries[491].output_at(__i).as_ptr() as *const [G; OUT_491]) }; __ret }, _ => aiur_fn_491(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; let __v_6: G = (__v_3 - __v_5); let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_491] = [__v_8]; - record.function_queries[491].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_490] = [__v_8]; + record.function_queries[490].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_492: usize = 2; -const IN_492: usize = 2; -const OUT_492: usize = 2; -fn aiur_fn_492( - inp: [G; IN_492], +const INPUT_SIZE_491: usize = 2; +const IN_491: usize = 2; +const OUT_491: usize = 2; +fn aiur_fn_491( + inp: [G; IN_491], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_492], ExecError> { +) -> Result<[G; OUT_491], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -43765,10 +43719,10 @@ fn aiur_fn_492( let __v_6: G = __loaded[4]; match __v_2.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_429] = { let __args: [G; IN_429] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[429].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[429].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[429].bump_multiplicity(__i); } let __ret: [G; OUT_429] = unsafe { *(record.function_queries[429].output_at(__i).as_ptr() as *const [G; OUT_429]) }; __ret }, _ => aiur_fn_429(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_428] = { let __args: [G; IN_428] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[428].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[428].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[428].bump_multiplicity(__i); } let __ret: [G; OUT_428] = unsafe { *(record.function_queries[428].output_at(__i).as_ptr() as *const [G; OUT_428]) }; __ret }, _ => aiur_fn_428(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_492] = [__v_7, __v_4]; - record.function_queries[492].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_491] = [__v_7, __v_4]; + record.function_queries[491].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -43776,18 +43730,18 @@ fn aiur_fn_492( 0u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_4 - __v_7); - let __ret: [G; OUT_492] = [__v_3, __v_8]; - record.function_queries[492].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_491] = [__v_3, __v_8]; + record.function_queries[491].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 - __v_7); - let __r_arr: [G; OUT_492] = { let __args: [G; IN_492] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[492].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[492].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[492].bump_multiplicity(__i); } let __ret: [G; OUT_492] = unsafe { *(record.function_queries[492].output_at(__i).as_ptr() as *const [G; OUT_492]) }; __ret }, _ => aiur_fn_492(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_491] = { let __args: [G; IN_491] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[491].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[491].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[491].bump_multiplicity(__i); } let __ret: [G; OUT_491] = unsafe { *(record.function_queries[491].output_at(__i).as_ptr() as *const [G; OUT_491]) }; __ret }, _ => aiur_fn_491(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_492] = [__v_9, __v_10]; - record.function_queries[492].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_491] = [__v_9, __v_10]; + record.function_queries[491].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -43795,18 +43749,18 @@ fn aiur_fn_492( 2u64 => { match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_492] = [__v_3, __v_6]; - record.function_queries[492].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_491] = [__v_3, __v_6]; + record.function_queries[491].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 - __v_7); - let __r_arr: [G; OUT_492] = { let __args: [G; IN_492] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[492].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[492].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[492].bump_multiplicity(__i); } let __ret: [G; OUT_492] = unsafe { *(record.function_queries[492].output_at(__i).as_ptr() as *const [G; OUT_492]) }; __ret }, _ => aiur_fn_492(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_491] = { let __args: [G; IN_491] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[491].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[491].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[491].bump_multiplicity(__i); } let __ret: [G; OUT_491] = unsafe { *(record.function_queries[491].output_at(__i).as_ptr() as *const [G; OUT_491]) }; __ret }, _ => aiur_fn_491(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_492] = [__v_9, __v_10]; - record.function_queries[492].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_491] = [__v_9, __v_10]; + record.function_queries[491].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -43818,41 +43772,41 @@ fn aiur_fn_492( }) } -const INPUT_SIZE_493: usize = 3; -const IN_493: usize = 3; -const OUT_493: usize = 1; -fn aiur_fn_493( - inp: [G; IN_493], +const INPUT_SIZE_492: usize = 3; +const IN_492: usize = 3; +const OUT_492: usize = 1; +fn aiur_fn_492( + inp: [G; IN_492], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_493], ExecError> { +) -> Result<[G; OUT_492], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_493] = { let __args: [G; IN_493] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[493].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[493].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[493].bump_multiplicity(__i); } let __ret: [G; OUT_493] = unsafe { *(record.function_queries[493].output_at(__i).as_ptr() as *const [G; OUT_493]) }; __ret }, _ => aiur_fn_493(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = (__v_2 - __v_4); let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_3, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_3, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_493] = [__v_7]; - record.function_queries[493].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_492] = [__v_7]; + record.function_queries[492].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_494: usize = 2; -const IN_494: usize = 2; -const OUT_494: usize = 2; -fn aiur_fn_494( - inp: [G; IN_494], +const INPUT_SIZE_493: usize = 2; +const IN_493: usize = 2; +const OUT_493: usize = 2; +fn aiur_fn_493( + inp: [G; IN_493], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_494], ExecError> { +) -> Result<[G; OUT_493], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -43867,8 +43821,8 @@ fn aiur_fn_494( let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_1, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_494] = [__v_9, __v_4]; - record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_493] = [__v_9, __v_4]; + record.function_queries[493].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -43878,18 +43832,18 @@ fn aiur_fn_494( let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_494] = [__v_10, __v_4]; - record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_493] = [__v_10, __v_4]; + record.function_queries[493].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 - __v_7); - let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_493] = { let __args: [G; IN_493] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[493].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[493].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[493].bump_multiplicity(__i); } let __ret: [G; OUT_493] = unsafe { *(record.function_queries[493].output_at(__i).as_ptr() as *const [G; OUT_493]) }; __ret }, _ => aiur_fn_493(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_494] = [__v_9, __v_10]; - record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_493] = [__v_9, __v_10]; + record.function_queries[493].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -43898,20 +43852,20 @@ fn aiur_fn_494( match __v_1.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_494] = [__v_8, __v_6]; - record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_493] = [__v_8, __v_6]; + record.function_queries[493].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 - __v_7); - let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_493] = { let __args: [G; IN_493] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[493].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[493].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[493].bump_multiplicity(__i); } let __ret: [G; OUT_493] = unsafe { *(record.function_queries[493].output_at(__i).as_ptr() as *const [G; OUT_493]) }; __ret }, _ => aiur_fn_493(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_494] = [__v_9, __v_10]; - record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_493] = [__v_9, __v_10]; + record.function_queries[493].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -43923,28 +43877,28 @@ fn aiur_fn_494( }) } -const INPUT_SIZE_495: usize = 4; -const IN_495: usize = 4; -const OUT_495: usize = 1; -fn aiur_fn_495( - inp: [G; IN_495], +const INPUT_SIZE_494: usize = 4; +const IN_494: usize = 4; +const OUT_494: usize = 1; +fn aiur_fn_494( + inp: [G; IN_494], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_495], ExecError> { +) -> Result<[G; OUT_494], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_0] = { let __args: [G; IN_0] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[0].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[0].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[0].bump_multiplicity(__i); } let __ret: [G; OUT_0] = unsafe { *(record.function_queries[0].output_at(__i).as_ptr() as *const [G; OUT_0]) }; __ret }, _ => aiur_fn_0(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_495] = [__v_0]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_0]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -43959,95 +43913,95 @@ fn aiur_fn_495( let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_495] = [__v_0]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_0]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = (__v_7 - __v_3); - let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_493] = { let __args: [G; IN_493] = [__v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[493].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[493].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[493].bump_multiplicity(__i); } let __ret: [G; OUT_493] = unsafe { *(record.function_queries[493].output_at(__i).as_ptr() as *const [G; OUT_493]) }; __ret }, _ => aiur_fn_493(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; let __v_14: G = (__v_2 - __v_13); let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_12, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_12, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_16, __v_3, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_16, __v_3, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_495] = [__v_18]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_18]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 3u64 => { let __v_10: G = G::from_u64(3); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_8, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_8, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_495] = [__v_14]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_14]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_10: G = G::from_u64(4); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(1); let __v_13: G = (__v_3 + __v_12); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_8, __v_1, __v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_8, __v_1, __v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_10, __v_11, __v_14, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_495] = [__v_16]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_16]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_10: G = G::from_u64(5); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(1); let __v_13: G = (__v_3 + __v_12); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_8, __v_1, __v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_8, __v_1, __v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_10, __v_11, __v_14, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_495] = [__v_16]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_16]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_10: G = G::from_u64(6); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_7, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_8, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_8, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(1); let __v_14: G = (__v_3 + __v_13); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_9, __v_1, __v_2, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_9, __v_1, __v_2, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = { let __values: [G; 4] = [__v_10, __v_11, __v_12, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_495] = [__v_16]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_16]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { let __v_10: G = G::from_u64(8); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_9, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_9, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = { let __values: [G; 4] = [__v_10, __v_7, __v_8, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_495] = [__v_12]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_12]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_495] = [__v_0]; - record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_494] = [__v_0]; + record.function_queries[494].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44056,31 +44010,31 @@ fn aiur_fn_495( }) } -const INPUT_SIZE_496: usize = 4; -const IN_496: usize = 4; -const OUT_496: usize = 1; -fn aiur_fn_496( - inp: [G; IN_496], +const INPUT_SIZE_495: usize = 4; +const IN_495: usize = 4; +const OUT_495: usize = 1; +fn aiur_fn_495( + inp: [G; IN_495], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_496], ExecError> { +) -> Result<[G; OUT_495], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_496] = [__v_8]; - record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_495] = [__v_8]; + record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44091,35 +44045,35 @@ fn aiur_fn_496( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 3u64 => { - let __r_arr: [G; OUT_497] = { let __args: [G; IN_497] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[497].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[497].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[497].bump_multiplicity(__i); } let __ret: [G; OUT_497] = unsafe { *(record.function_queries[497].output_at(__i).as_ptr() as *const [G; OUT_497]) }; __ret }, _ => aiur_fn_497(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_500] = { let __args: [G; IN_500] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[500].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[500].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[500].bump_multiplicity(__i); } let __ret: [G; OUT_500] = unsafe { *(record.function_queries[500].output_at(__i).as_ptr() as *const [G; OUT_500]) }; __ret }, _ => aiur_fn_500(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_499] = { let __args: [G; IN_499] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[499].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[499].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[499].bump_multiplicity(__i); } let __ret: [G; OUT_499] = unsafe { *(record.function_queries[499].output_at(__i).as_ptr() as *const [G; OUT_499]) }; __ret }, _ => aiur_fn_499(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_496] = [__v_10]; - record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_495] = [__v_10]; + record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_497] = { let __args: [G; IN_497] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[497].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[497].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[497].bump_multiplicity(__i); } let __ret: [G; OUT_497] = unsafe { *(record.function_queries[497].output_at(__i).as_ptr() as *const [G; OUT_497]) }; __ret }, _ => aiur_fn_497(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_0, __v_11, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_0, __v_11, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_500] = { let __args: [G; IN_500] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[500].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[500].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[500].bump_multiplicity(__i); } let __ret: [G; OUT_500] = unsafe { *(record.function_queries[500].output_at(__i).as_ptr() as *const [G; OUT_500]) }; __ret }, _ => aiur_fn_500(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_499] = { let __args: [G; IN_499] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[499].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[499].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[499].bump_multiplicity(__i); } let __ret: [G; OUT_499] = unsafe { *(record.function_queries[499].output_at(__i).as_ptr() as *const [G; OUT_499]) }; __ret }, _ => aiur_fn_499(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_496] = [__v_13]; - record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_495] = [__v_13]; + record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_498] = { let __args: [G; IN_498] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[498].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[498].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[498].bump_multiplicity(__i); } let __ret: [G; OUT_498] = unsafe { *(record.function_queries[498].output_at(__i).as_ptr() as *const [G; OUT_498]) }; __ret }, _ => aiur_fn_498(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_497] = { let __args: [G; IN_497] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[497].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[497].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[497].bump_multiplicity(__i); } let __ret: [G; OUT_497] = unsafe { *(record.function_queries[497].output_at(__i).as_ptr() as *const [G; OUT_497]) }; __ret }, _ => aiur_fn_497(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_496] = [__v_13]; - record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_495] = [__v_13]; + record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44130,10 +44084,10 @@ fn aiur_fn_496( } }, _ => { - let __r_arr: [G; OUT_500] = { let __args: [G; IN_500] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[500].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[500].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[500].bump_multiplicity(__i); } let __ret: [G; OUT_500] = unsafe { *(record.function_queries[500].output_at(__i).as_ptr() as *const [G; OUT_500]) }; __ret }, _ => aiur_fn_500(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_499] = { let __args: [G; IN_499] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[499].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[499].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[499].bump_multiplicity(__i); } let __ret: [G; OUT_499] = unsafe { *(record.function_queries[499].output_at(__i).as_ptr() as *const [G; OUT_499]) }; __ret }, _ => aiur_fn_499(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_496] = [__v_9]; - record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_495] = [__v_9]; + record.function_queries[495].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44142,15 +44096,15 @@ fn aiur_fn_496( }) } -const INPUT_SIZE_497: usize = 1; -const IN_497: usize = 1; -const OUT_497: usize = 1; -fn aiur_fn_497( - inp: [G; IN_497], +const INPUT_SIZE_496: usize = 1; +const IN_496: usize = 1; +const OUT_496: usize = 1; +fn aiur_fn_496( + inp: [G; IN_496], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_497], ExecError> { +) -> Result<[G; OUT_496], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 5] = { let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 5 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 5] = __args[..5].try_into().unwrap(); __arr }; @@ -44162,33 +44116,33 @@ fn aiur_fn_497( match __v_1.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_497] = [__v_6]; - record.function_queries[497].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_496] = [__v_6]; + record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_497] = [__v_6]; - record.function_queries[497].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_496] = [__v_6]; + record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_497] = { let __args: [G; IN_497] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[497].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[497].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[497].bump_multiplicity(__i); } let __ret: [G; OUT_497] = unsafe { *(record.function_queries[497].output_at(__i).as_ptr() as *const [G; OUT_497]) }; __ret }, _ => aiur_fn_497(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 0u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_497] = [__v_7]; - record.function_queries[497].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_496] = [__v_7]; + record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_497] = { let __args: [G; IN_497] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[497].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[497].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[497].bump_multiplicity(__i); } let __ret: [G; OUT_497] = unsafe { *(record.function_queries[497].output_at(__i).as_ptr() as *const [G; OUT_497]) }; __ret }, _ => aiur_fn_497(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = (__v_7 + __v_8); - let __ret: [G; OUT_497] = [__v_9]; - record.function_queries[497].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_496] = [__v_9]; + record.function_queries[496].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44200,53 +44154,53 @@ fn aiur_fn_497( }) } -const INPUT_SIZE_498: usize = 4; -const IN_498: usize = 4; -const OUT_498: usize = 1; -fn aiur_fn_498( - inp: [G; IN_498], +const INPUT_SIZE_497: usize = 4; +const IN_497: usize = 4; +const OUT_497: usize = 1; +fn aiur_fn_497( + inp: [G; IN_497], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_498], ExecError> { +) -> Result<[G; OUT_497], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_354] = { let __args: [G; IN_354] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[354].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[354].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[354].bump_multiplicity(__i); } let __ret: [G; OUT_354] = unsafe { *(record.function_queries[354].output_at(__i).as_ptr() as *const [G; OUT_354]) }; __ret }, _ => aiur_fn_354(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_353] = { let __args: [G; IN_353] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[353].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[353].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[353].bump_multiplicity(__i); } let __ret: [G; OUT_353] = unsafe { *(record.function_queries[353].output_at(__i).as_ptr() as *const [G; OUT_353]) }; __ret }, _ => aiur_fn_353(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_499] = { let __args: [G; IN_499] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[499].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[499].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[499].bump_multiplicity(__i); } let __ret: [G; OUT_499] = unsafe { *(record.function_queries[499].output_at(__i).as_ptr() as *const [G; OUT_499]) }; __ret }, _ => aiur_fn_499(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_498] = { let __args: [G; IN_498] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[498].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[498].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[498].bump_multiplicity(__i); } let __ret: [G; OUT_498] = unsafe { *(record.function_queries[498].output_at(__i).as_ptr() as *const [G; OUT_498]) }; __ret }, _ => aiur_fn_498(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; let __v_8: G = __r_arr[2]; let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_0, __v_7, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_0, __v_7, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = (__v_3 - __v_8); - let __r_arr: [G; OUT_500] = { let __args: [G; IN_500] = [__v_10, __v_6, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[500].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[500].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[500].bump_multiplicity(__i); } let __ret: [G; OUT_500] = unsafe { *(record.function_queries[500].output_at(__i).as_ptr() as *const [G; OUT_500]) }; __ret }, _ => aiur_fn_500(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_499] = { let __args: [G; IN_499] = [__v_10, __v_6, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[499].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[499].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[499].bump_multiplicity(__i); } let __ret: [G; OUT_499] = unsafe { *(record.function_queries[499].output_at(__i).as_ptr() as *const [G; OUT_499]) }; __ret }, _ => aiur_fn_499(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_13, __v_8, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_13, __v_8, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_498] = [__v_15]; - record.function_queries[498].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_497] = [__v_15]; + record.function_queries[497].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_499: usize = 2; -const IN_499: usize = 2; -const OUT_499: usize = 3; -fn aiur_fn_499( - inp: [G; IN_499], +const INPUT_SIZE_498: usize = 2; +const IN_498: usize = 2; +const OUT_498: usize = 3; +fn aiur_fn_498( + inp: [G; IN_498], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_499], ExecError> { +) -> Result<[G; OUT_498], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -44254,8 +44208,8 @@ fn aiur_fn_499( 0u64 => { let __v_2: G = G::from_u64(0); let __v_3: G = G::from_u64(0); - let __ret: [G; OUT_499] = [__v_0, __v_2, __v_3]; - record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_498] = [__v_0, __v_2, __v_3]; + record.function_queries[498].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44269,20 +44223,20 @@ fn aiur_fn_499( 2u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 - __v_7); - let __r_arr: [G; OUT_499] = { let __args: [G; IN_499] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[499].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[499].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[499].bump_multiplicity(__i); } let __ret: [G; OUT_499] = unsafe { *(record.function_queries[499].output_at(__i).as_ptr() as *const [G; OUT_499]) }; __ret }, _ => aiur_fn_499(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_498] = { let __args: [G; IN_498] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[498].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[498].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[498].bump_multiplicity(__i); } let __ret: [G; OUT_498] = unsafe { *(record.function_queries[498].output_at(__i).as_ptr() as *const [G; OUT_498]) }; __ret }, _ => aiur_fn_498(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = __r_arr[2]; let __v_12: G = G::from_u64(1); let __v_13: G = (__v_10 + __v_12); - let __ret: [G; OUT_499] = [__v_9, __v_13, __v_11]; - record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_498] = [__v_9, __v_13, __v_11]; + record.function_queries[498].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 - __v_7); - let __r_arr: [G; OUT_499] = { let __args: [G; IN_499] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[499].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[499].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[499].bump_multiplicity(__i); } let __ret: [G; OUT_499] = unsafe { *(record.function_queries[499].output_at(__i).as_ptr() as *const [G; OUT_499]) }; __ret }, _ => aiur_fn_499(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_498] = { let __args: [G; IN_498] = [__v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[498].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[498].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[498].bump_multiplicity(__i); } let __ret: [G; OUT_498] = unsafe { *(record.function_queries[498].output_at(__i).as_ptr() as *const [G; OUT_498]) }; __ret }, _ => aiur_fn_498(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = __r_arr[2]; @@ -44290,15 +44244,15 @@ fn aiur_fn_499( let __v_13: G = (__v_10 + __v_12); let __v_14: G = G::from_u64(1); let __v_15: G = (__v_11 + __v_14); - let __ret: [G; OUT_499] = [__v_9, __v_13, __v_15]; - record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_498] = [__v_9, __v_13, __v_15]; + record.function_queries[498].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(0); let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_499] = [__v_0, __v_7, __v_8]; - record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_498] = [__v_0, __v_7, __v_8]; + record.function_queries[498].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44307,15 +44261,15 @@ fn aiur_fn_499( }) } -const INPUT_SIZE_500: usize = 4; -const IN_500: usize = 4; -const OUT_500: usize = 1; -fn aiur_fn_500( - inp: [G; IN_500], +const INPUT_SIZE_499: usize = 4; +const IN_499: usize = 4; +const OUT_499: usize = 1; +fn aiur_fn_499( + inp: [G; IN_499], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_500], ExecError> { +) -> Result<[G; OUT_499], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -44328,22 +44282,22 @@ fn aiur_fn_500( let __v_7: G = __loaded[3]; match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_492] = { let __args: [G; IN_492] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[492].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[492].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[492].bump_multiplicity(__i); } let __ret: [G; OUT_492] = unsafe { *(record.function_queries[492].output_at(__i).as_ptr() as *const [G; OUT_492]) }; __ret }, _ => aiur_fn_492(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_491] = { let __args: [G; IN_491] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[491].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[491].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[491].bump_multiplicity(__i); } let __ret: [G; OUT_491] = unsafe { *(record.function_queries[491].output_at(__i).as_ptr() as *const [G; OUT_491]) }; __ret }, _ => aiur_fn_491(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = (__v_3 - __v_9); let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_500] = [__v_12]; - record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_499] = [__v_12]; + record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_5, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_5, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 3] = [__v_11, __v_9, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; @@ -44354,20 +44308,20 @@ fn aiur_fn_500( let __v_17: G = { let __values: [G; 5] = [__v_13, __v_9, __v_15, __v_1, __v_16]; let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_18: G = G::from_u64(1); let __v_19: G = (__v_3 + __v_18); - let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_6, __v_17, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_6, __v_17, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = G::from_u64(5); let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 4] = [__v_21, __v_9, __v_20, __v_22]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_500] = [__v_23]; - record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_499] = [__v_23]; + record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_5, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_5, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 3] = [__v_11, __v_9, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; @@ -44378,9 +44332,9 @@ fn aiur_fn_500( let __v_17: G = { let __values: [G; 5] = [__v_13, __v_9, __v_15, __v_1, __v_16]; let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_18: G = G::from_u64(1); let __v_19: G = (__v_3 + __v_18); - let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_6, __v_17, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_6, __v_17, __v_12, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_20, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_20, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_21.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_22: G = __loaded[0]; @@ -44390,12 +44344,12 @@ fn aiur_fn_500( match __v_22.as_canonical_u64() { 1u64 => { let __v_26: G = G::from_u64(1); - let __r_arr: [G; OUT_332] = { let __args: [G; IN_332] = [__v_10, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[332].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[332].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[332].bump_multiplicity(__i); } let __ret: [G; OUT_332] = unsafe { *(record.function_queries[332].output_at(__i).as_ptr() as *const [G; OUT_332]) }; __ret }, _ => aiur_fn_332(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_331] = { let __args: [G; IN_331] = [__v_10, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[331].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[331].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[331].bump_multiplicity(__i); } let __ret: [G; OUT_331] = unsafe { *(record.function_queries[331].output_at(__i).as_ptr() as *const [G; OUT_331]) }; __ret }, _ => aiur_fn_331(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = G::from_u64(0); let __v_29: G = { let __values: [G; 4] = [__v_26, __v_27, __v_28, __v_28]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_500] = [__v_29]; - record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_499] = [__v_29]; + record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44405,13 +44359,13 @@ fn aiur_fn_500( }, 6u64 => { let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_5, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_5, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_11, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_11, __v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(1); if (__v_12 != __v_13) { @@ -44419,16 +44373,16 @@ fn aiur_fn_500( } let __v_14: G = G::from_u64(2); let __v_15: G = { let __values: [G; 5] = [__v_14, __v_9, __v_6, __v_1, __v_3]; let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_7, __v_15, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_7, __v_15, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_500] = [__v_16]; - record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_499] = [__v_16]; + record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_5, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_5, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_9.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -44437,9 +44391,9 @@ fn aiur_fn_500( let __v_13: G = __loaded[3]; match __v_10.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_496] = { let __args: [G; IN_496] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[496].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[496].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[496].bump_multiplicity(__i); } let __ret: [G; OUT_496] = unsafe { *(record.function_queries[496].output_at(__i).as_ptr() as *const [G; OUT_496]) }; __ret }, _ => aiur_fn_496(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_6, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_14, __v_11, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_14, __v_11, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(1); if (__v_15 != __v_16) { @@ -44447,27 +44401,27 @@ fn aiur_fn_500( } let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(1); - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_12, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_12, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; match __v_19.as_canonical_u64() { 0u64 => { let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_12, __v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_12, __v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_500] = [__v_22]; - record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_499] = [__v_22]; + record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_20: G = G::from_u64(0); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_6, __v_1, __v_3, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_6, __v_1, __v_3, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_12, __v_21, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_12, __v_21, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_500] = [__v_23]; - record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_499] = [__v_23]; + record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44479,27 +44433,27 @@ fn aiur_fn_500( }, _ => { let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_495] = { let __args: [G; IN_495] = [__v_0, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[495].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[495].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[495].bump_multiplicity(__i); } let __ret: [G; OUT_495] = unsafe { *(record.function_queries[495].output_at(__i).as_ptr() as *const [G; OUT_495]) }; __ret }, _ => aiur_fn_495(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_494] = { let __args: [G; IN_494] = [__v_0, __v_1, __v_3, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[494].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[494].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[494].bump_multiplicity(__i); } let __ret: [G; OUT_494] = unsafe { *(record.function_queries[494].output_at(__i).as_ptr() as *const [G; OUT_494]) }; __ret }, _ => aiur_fn_494(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_9, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_500] = [__v_10]; - record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_499] = [__v_10]; + record.function_queries[499].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_501: usize = 4; -const IN_501: usize = 4; -const OUT_501: usize = 1; -fn aiur_fn_501( - inp: [G; IN_501], +const INPUT_SIZE_500: usize = 4; +const IN_500: usize = 4; +const OUT_500: usize = 1; +fn aiur_fn_500( + inp: [G; IN_500], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_501], ExecError> { +) -> Result<[G; OUT_500], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -44511,20 +44465,20 @@ fn aiur_fn_501( let __v_6: G = __loaded[2]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_501] = [__v_0]; - record.function_queries[501].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_500] = [__v_0]; + record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_0, __v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_0, __v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_501] = [__v_9]; - record.function_queries[501].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_500] = [__v_9]; + record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44537,7 +44491,7 @@ fn aiur_fn_501( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_11.as_canonical_u64() { 0u64 => { @@ -44545,24 +44499,24 @@ fn aiur_fn_501( }, _ => { let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_8, __v_2, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_8, __v_2, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; break '__mc_0 [__v_13]; }, } }; let __v_12: G = __mc_out___mc_0[0]; - let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = [__v_5, __v_12, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_5, __v_12, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 3] = [__v_13, __v_5, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_501] = { let __args: [G; IN_501] = [__v_9, __v_6, __v_14, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[501].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[501].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[501].bump_multiplicity(__i); } let __ret: [G; OUT_501] = unsafe { *(record.function_queries[501].output_at(__i).as_ptr() as *const [G; OUT_501]) }; __ret }, _ => aiur_fn_501(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_500] = { let __args: [G; IN_500] = [__v_9, __v_6, __v_14, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[500].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[500].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[500].bump_multiplicity(__i); } let __ret: [G; OUT_500] = unsafe { *(record.function_queries[500].output_at(__i).as_ptr() as *const [G; OUT_500]) }; __ret }, _ => aiur_fn_500(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_501] = [__v_15]; - record.function_queries[501].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_500] = [__v_15]; + record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __mc_out___mc_1: [G; 1] = '__mc_1: { match __v_11.as_canonical_u64() { 0u64 => { @@ -44570,14 +44524,14 @@ fn aiur_fn_501( }, _ => { let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_0, __v_2, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_0, __v_2, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; break '__mc_1 [__v_13]; }, } }; let __v_12: G = __mc_out___mc_1[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_12, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_12, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_13.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_14: G = __loaded[0]; @@ -44586,16 +44540,16 @@ fn aiur_fn_501( let __v_17: G = __loaded[3]; match __v_14.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = [__v_5, __v_15, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_5, __v_15, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; let __v_18: G = G::from_u64(0); let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(1); let __v_21: G = { let __values: [G; 3] = [__v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_22: G = { let __values: [G; 3] = [__v_18, __v_5, __v_21]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_501] = { let __args: [G; IN_501] = [__v_16, __v_6, __v_22, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[501].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[501].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[501].bump_multiplicity(__i); } let __ret: [G; OUT_501] = unsafe { *(record.function_queries[501].output_at(__i).as_ptr() as *const [G; OUT_501]) }; __ret }, _ => aiur_fn_501(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_500] = { let __args: [G; IN_500] = [__v_16, __v_6, __v_22, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[500].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[500].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[500].bump_multiplicity(__i); } let __ret: [G; OUT_500] = unsafe { *(record.function_queries[500].output_at(__i).as_ptr() as *const [G; OUT_500]) }; __ret }, _ => aiur_fn_500(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_501] = [__v_23]; - record.function_queries[501].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_500] = [__v_23]; + record.function_queries[500].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44612,43 +44566,43 @@ fn aiur_fn_501( }) } -const INPUT_SIZE_502: usize = 2; -const IN_502: usize = 2; -const OUT_502: usize = 1; -fn aiur_fn_502( - inp: [G; IN_502], +const INPUT_SIZE_501: usize = 2; +const IN_501: usize = 2; +const OUT_501: usize = 1; +fn aiur_fn_501( + inp: [G; IN_501], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_502], ExecError> { +) -> Result<[G; OUT_501], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_0.as_canonical_u64() { 0u64 => { let __v_2: G = G::from_u64(2); - let __r_arr: [G; OUT_381] = { let __args: [G; IN_381] = []; let __cu = unconstrained; let __hit = record.function_queries[381].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[381].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[381].bump_multiplicity(__i); } let __ret: [G; OUT_381] = unsafe { *(record.function_queries[381].output_at(__i).as_ptr() as *const [G; OUT_381]) }; __ret }, _ => aiur_fn_381(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_380] = { let __args: [G; IN_380] = []; let __cu = unconstrained; let __hit = record.function_queries[380].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[380].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[380].bump_multiplicity(__i); } let __ret: [G; OUT_380] = unsafe { *(record.function_queries[380].output_at(__i).as_ptr() as *const [G; OUT_380]) }; __ret }, _ => aiur_fn_380(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = G::from_u64(1); let __v_5: G = G::from_u64(1); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_2, __v_3, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_502] = [__v_8]; - record.function_queries[502].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_501] = [__v_8]; + record.function_queries[501].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_2: G = G::from_u64(2); - let __r_arr: [G; OUT_218] = { let __args: [G; IN_218] = []; let __cu = unconstrained; let __hit = record.function_queries[218].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[218].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[218].bump_multiplicity(__i); } let __ret: [G; OUT_218] = unsafe { *(record.function_queries[218].output_at(__i).as_ptr() as *const [G; OUT_218]) }; __ret }, _ => aiur_fn_218(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_217] = { let __args: [G; IN_217] = []; let __cu = unconstrained; let __hit = record.function_queries[217].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[217].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[217].bump_multiplicity(__i); } let __ret: [G; OUT_217] = unsafe { *(record.function_queries[217].output_at(__i).as_ptr() as *const [G; OUT_217]) }; __ret }, _ => aiur_fn_217(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = G::from_u64(1); let __v_5: G = G::from_u64(1); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_2, __v_3, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_502] = [__v_8]; - record.function_queries[502].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_501] = [__v_8]; + record.function_queries[501].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44658,23 +44612,23 @@ fn aiur_fn_502( }) } -const INPUT_SIZE_503: usize = 4; -const IN_503: usize = 4; -const OUT_503: usize = 1; -fn aiur_fn_503( - inp: [G; IN_503], +const INPUT_SIZE_502: usize = 4; +const IN_502: usize = 4; +const OUT_502: usize = 1; +fn aiur_fn_502( + inp: [G; IN_502], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_503], ExecError> { +) -> Result<[G; OUT_502], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_504] = { let __args: [G; IN_504] = [__v_4, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[504].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[504].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[504].bump_multiplicity(__i); } let __ret: [G; OUT_504] = unsafe { *(record.function_queries[504].output_at(__i).as_ptr() as *const [G; OUT_504]) }; __ret }, _ => aiur_fn_504(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_503] = { let __args: [G; IN_503] = [__v_4, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[503].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[503].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[503].bump_multiplicity(__i); } let __ret: [G; OUT_503] = unsafe { *(record.function_queries[503].output_at(__i).as_ptr() as *const [G; OUT_503]) }; __ret }, _ => aiur_fn_503(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -44686,10 +44640,10 @@ fn aiur_fn_503( let __v_10: G = G::from_u64(0); let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 3] = [__v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_7, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_7, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_503] = [__v_13]; - record.function_queries[503].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_502] = [__v_13]; + record.function_queries[502].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44699,29 +44653,29 @@ fn aiur_fn_503( }) } -const INPUT_SIZE_504: usize = 3; -const IN_504: usize = 3; -const OUT_504: usize = 1; -fn aiur_fn_504( - inp: [G; IN_504], +const INPUT_SIZE_503: usize = 3; +const IN_503: usize = 3; +const OUT_503: usize = 1; +fn aiur_fn_503( + inp: [G; IN_503], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_504], ExecError> { +) -> Result<[G; OUT_503], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __ret: [G; OUT_504] = [__v_3]; - record.function_queries[504].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_503] = [__v_3]; + record.function_queries[503].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -44734,15 +44688,15 @@ fn aiur_fn_504( let __v_9: G = { let __values: [G; 3] = [__v_8, __v_5, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_10: G = G::from_u64(1); let __v_11: G = (__v_1 - __v_10); - let __r_arr: [G; OUT_504] = { let __args: [G; IN_504] = [__v_6, __v_11, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[504].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[504].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[504].bump_multiplicity(__i); } let __ret: [G; OUT_504] = unsafe { *(record.function_queries[504].output_at(__i).as_ptr() as *const [G; OUT_504]) }; __ret }, _ => aiur_fn_504(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_503] = { let __args: [G; IN_503] = [__v_6, __v_11, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[503].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[503].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[503].bump_multiplicity(__i); } let __ret: [G; OUT_503] = unsafe { *(record.function_queries[503].output_at(__i).as_ptr() as *const [G; OUT_503]) }; __ret }, _ => aiur_fn_503(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_504] = [__v_12]; - record.function_queries[504].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_503] = [__v_12]; + record.function_queries[503].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_504] = [__v_3]; - record.function_queries[504].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_503] = [__v_3]; + record.function_queries[503].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44751,54 +44705,54 @@ fn aiur_fn_504( }) } -const INPUT_SIZE_505: usize = 3; -const IN_505: usize = 3; -const OUT_505: usize = 0; -fn aiur_fn_505( - inp: [G; IN_505], +const INPUT_SIZE_504: usize = 3; +const IN_504: usize = 3; +const OUT_504: usize = 0; +fn aiur_fn_504( + inp: [G; IN_504], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_505], ExecError> { +) -> Result<[G; OUT_504], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_0.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_505] = []; - record.function_queries[505].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_504] = []; + record.function_queries[504].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); if (__v_7 != __v_8) { return Err(ExecError::AssertEqMismatch { lhs: __v_7.as_canonical_u64(), rhs: __v_8.as_canonical_u64(), msg: Some("projection on a Prop structure: field is not a Prop".to_string()) }); } - let __ret: [G; OUT_505] = []; - record.function_queries[505].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_504] = []; + record.function_queries[504].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_506: usize = 4; -const IN_506: usize = 4; -const OUT_506: usize = 0; -fn aiur_fn_506( - inp: [G; IN_506], +const INPUT_SIZE_505: usize = 4; +const IN_505: usize = 4; +const OUT_505: usize = 0; +fn aiur_fn_505( + inp: [G; IN_505], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_506], ExecError> { +) -> Result<[G; OUT_505], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -44806,33 +44760,33 @@ fn aiur_fn_506( let __v_3: G = inp[3]; match __v_0.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_506] = []; - record.function_queries[506].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_505] = []; + record.function_queries[505].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(0); let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_506] = []; - record.function_queries[506].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_505] = []; + record.function_queries[505].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_341] = { let __args: [G; IN_341] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[341].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[341].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[341].bump_multiplicity(__i); } let __ret: [G; OUT_341] = unsafe { *(record.function_queries[341].output_at(__i).as_ptr() as *const [G; OUT_341]) }; __ret }, _ => aiur_fn_341(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(0); if (__v_9 != __v_10) { return Err(ExecError::AssertEqMismatch { lhs: __v_9.as_canonical_u64(), rhs: __v_10.as_canonical_u64(), msg: Some("projection on a Prop structure: later fields depend on a data field".to_string()) }); } - let __ret: [G; OUT_506] = []; - record.function_queries[506].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_505] = []; + record.function_queries[505].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44841,15 +44795,15 @@ fn aiur_fn_506( }) } -const INPUT_SIZE_507: usize = 7; -const IN_507: usize = 7; -const OUT_507: usize = 1; -fn aiur_fn_507( - inp: [G; IN_507], +const INPUT_SIZE_506: usize = 7; +const IN_506: usize = 7; +const OUT_506: usize = 1; +fn aiur_fn_506( + inp: [G; IN_506], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_507], ExecError> { +) -> Result<[G; OUT_506], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -44868,24 +44822,24 @@ fn aiur_fn_507( let __v_11: G = (__v_1 - __v_2); match __v_11.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_505] = { let __args: [G; IN_505] = [__v_5, __v_8, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[505].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[505].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[505].bump_multiplicity(__i); } let __ret: [G; OUT_505] = unsafe { *(record.function_queries[505].output_at(__i).as_ptr() as *const [G; OUT_505]) }; __ret }, _ => aiur_fn_505(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_507] = [__v_8]; - record.function_queries[507].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_504] = { let __args: [G; IN_504] = [__v_5, __v_8, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[504].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[504].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[504].bump_multiplicity(__i); } let __ret: [G; OUT_504] = unsafe { *(record.function_queries[504].output_at(__i).as_ptr() as *const [G; OUT_504]) }; __ret }, _ => aiur_fn_504(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_506] = [__v_8]; + record.function_queries[506].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_506] = { let __args: [G; IN_506] = [__v_5, __v_8, __v_9, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[506].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[506].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[506].bump_multiplicity(__i); } let __ret: [G; OUT_506] = unsafe { *(record.function_queries[506].output_at(__i).as_ptr() as *const [G; OUT_506]) }; __ret }, _ => aiur_fn_506(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_505] = { let __args: [G; IN_505] = [__v_5, __v_8, __v_9, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[505].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[505].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[505].bump_multiplicity(__i); } let __ret: [G; OUT_505] = unsafe { *(record.function_queries[505].output_at(__i).as_ptr() as *const [G; OUT_505]) }; __ret }, _ => aiur_fn_505(__args, record, io_buffer, __cu)? } }; let __v_12: G = G::from_u64(8); let __v_13: G = { let __values: [G; 4] = [__v_12, __v_3, __v_2, __v_4]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_9, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_9, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(1); let __v_17: G = (__v_2 + __v_16); - let __r_arr: [G; OUT_507] = { let __args: [G; IN_507] = [__v_15, __v_1, __v_17, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[507].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[507].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[507].bump_multiplicity(__i); } let __ret: [G; OUT_507] = unsafe { *(record.function_queries[507].output_at(__i).as_ptr() as *const [G; OUT_507]) }; __ret }, _ => aiur_fn_507(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_506] = { let __args: [G; IN_506] = [__v_15, __v_1, __v_17, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[506].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[506].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[506].bump_multiplicity(__i); } let __ret: [G; OUT_506] = unsafe { *(record.function_queries[506].output_at(__i).as_ptr() as *const [G; OUT_506]) }; __ret }, _ => aiur_fn_506(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_507] = [__v_18]; - record.function_queries[507].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_506] = [__v_18]; + record.function_queries[506].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -44897,23 +44851,23 @@ fn aiur_fn_507( }) } -const INPUT_SIZE_508: usize = 4; -const IN_508: usize = 4; -const OUT_508: usize = 1; -fn aiur_fn_508( - inp: [G; IN_508], +const INPUT_SIZE_507: usize = 4; +const IN_507: usize = 4; +const OUT_507: usize = 1; +fn aiur_fn_507( + inp: [G; IN_507], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_508], ExecError> { +) -> Result<[G; OUT_507], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_4, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_4, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; @@ -44928,7 +44882,7 @@ fn aiur_fn_508( if (__v_9 != __v_0) { return Err(ExecError::AssertEqMismatch { lhs: __v_9.as_canonical_u64(), rhs: __v_0.as_canonical_u64(), msg: Some("projection's structure type differs from the value's head".to_string()) }); } - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_12.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_13: G = __loaded[0]; @@ -44950,7 +44904,7 @@ fn aiur_fn_508( return Err(ExecError::AssertEqMismatch { lhs: __v_18.as_canonical_u64(), rhs: __v_25.as_canonical_u64(), msg: Some("projection on an inductive with more than one constructor".to_string()) }); } let __v_26: G = G::from_u64(0); - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_20, __v_21, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_20, __v_21, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_27.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_28: G = __loaded[0]; @@ -44967,18 +44921,18 @@ fn aiur_fn_508( let __v_39: G = __loaded[11]; match __v_28.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_30, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_30, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; - let __r_arr: [G; OUT_435] = { let __args: [G; IN_435] = [__v_40, __v_7, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[435].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[435].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[435].bump_multiplicity(__i); } let __ret: [G; OUT_435] = unsafe { *(record.function_queries[435].output_at(__i).as_ptr() as *const [G; OUT_435]) }; __ret }, _ => aiur_fn_435(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_434] = { let __args: [G; IN_434] = [__v_40, __v_7, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[434].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[434].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[434].bump_multiplicity(__i); } let __ret: [G; OUT_434] = unsafe { *(record.function_queries[434].output_at(__i).as_ptr() as *const [G; OUT_434]) }; __ret }, _ => aiur_fn_434(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = (__v_16 + __v_17); - let __r_arr: [G; OUT_503] = { let __args: [G; IN_503] = [__v_15, __v_10, __v_42, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[503].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[503].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[503].bump_multiplicity(__i); } let __ret: [G; OUT_503] = unsafe { *(record.function_queries[503].output_at(__i).as_ptr() as *const [G; OUT_503]) }; __ret }, _ => aiur_fn_503(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_502] = { let __args: [G; IN_502] = [__v_15, __v_10, __v_42, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[502].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[502].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[502].bump_multiplicity(__i); } let __ret: [G; OUT_502] = unsafe { *(record.function_queries[502].output_at(__i).as_ptr() as *const [G; OUT_502]) }; __ret }, _ => aiur_fn_502(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; let __v_44: G = G::from_u64(0); - let __r_arr: [G; OUT_507] = { let __args: [G; IN_507] = [__v_41, __v_1, __v_44, __v_0, __v_2, __v_43, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[507].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[507].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[507].bump_multiplicity(__i); } let __ret: [G; OUT_507] = unsafe { *(record.function_queries[507].output_at(__i).as_ptr() as *const [G; OUT_507]) }; __ret }, _ => aiur_fn_507(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_506] = { let __args: [G; IN_506] = [__v_41, __v_1, __v_44, __v_0, __v_2, __v_43, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[506].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[506].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[506].bump_multiplicity(__i); } let __ret: [G; OUT_506] = unsafe { *(record.function_queries[506].output_at(__i).as_ptr() as *const [G; OUT_506]) }; __ret }, _ => aiur_fn_506(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; - let __ret: [G; OUT_508] = [__v_45]; - record.function_queries[508].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_507] = [__v_45]; + record.function_queries[507].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -44998,21 +44952,21 @@ fn aiur_fn_508( }) } -const INPUT_SIZE_509: usize = 2; -const IN_509: usize = 2; -const OUT_509: usize = 1; -fn aiur_fn_509( - inp: [G; IN_509], +const INPUT_SIZE_508: usize = 2; +const IN_508: usize = 2; +const OUT_508: usize = 1; +fn aiur_fn_508( + inp: [G; IN_508], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_509], ExecError> { +) -> Result<[G; OUT_508], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_2, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_2, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -45021,8 +44975,8 @@ fn aiur_fn_509( let __v_7: G = __loaded[3]; match __v_4.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_509] = [__v_5]; - record.function_queries[509].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_508] = [__v_5]; + record.function_queries[508].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -45032,42 +44986,42 @@ fn aiur_fn_509( }) } -const INPUT_SIZE_510: usize = 3; -const IN_510: usize = 3; -const OUT_510: usize = 0; -fn aiur_fn_510( - inp: [G; IN_510], +const INPUT_SIZE_509: usize = 3; +const IN_509: usize = 3; +const OUT_509: usize = 0; +fn aiur_fn_509( + inp: [G; IN_509], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_510], ExecError> { +) -> Result<[G; OUT_509], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(1); if (__v_4 != __v_5) { return Err(ExecError::AssertEqMismatch { lhs: __v_4.as_canonical_u64(), rhs: __v_5.as_canonical_u64(), msg: Some("inferred type is not def-eq to the expected type".to_string()) }); } - let __ret: [G; OUT_510] = []; - record.function_queries[510].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_509] = []; + record.function_queries[509].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_511: usize = 0; -const IN_511: usize = 0; -const OUT_511: usize = 1; -fn aiur_fn_511( - inp: [G; IN_511], +const INPUT_SIZE_510: usize = 0; +const IN_510: usize = 0; +const OUT_510: usize = 1; +fn aiur_fn_510( + inp: [G; IN_510], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_511], ExecError> { +) -> Result<[G; OUT_510], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(41); let __v_1: G = G::from_u64(153); @@ -45102,21 +45056,21 @@ fn aiur_fn_511( let __v_30: G = G::from_u64(22); let __v_31: G = G::from_u64(236); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_511] = [__v_32]; - record.function_queries[511].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_510] = [__v_32]; + record.function_queries[510].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_512: usize = 0; -const IN_512: usize = 0; -const OUT_512: usize = 1; -fn aiur_fn_512( - inp: [G; IN_512], +const INPUT_SIZE_511: usize = 0; +const IN_511: usize = 0; +const OUT_511: usize = 1; +fn aiur_fn_511( + inp: [G; IN_511], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_512], ExecError> { +) -> Result<[G; OUT_511], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(27); let __v_1: G = G::from_u64(172); @@ -45151,21 +45105,21 @@ fn aiur_fn_512( let __v_30: G = G::from_u64(202); let __v_31: G = G::from_u64(42); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_512] = [__v_32]; - record.function_queries[512].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_511] = [__v_32]; + record.function_queries[511].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_513: usize = 0; -const IN_513: usize = 0; -const OUT_513: usize = 1; -fn aiur_fn_513( - inp: [G; IN_513], +const INPUT_SIZE_512: usize = 0; +const IN_512: usize = 0; +const OUT_512: usize = 1; +fn aiur_fn_512( + inp: [G; IN_512], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_513], ExecError> { +) -> Result<[G; OUT_512], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(18); let __v_1: G = G::from_u64(243); @@ -45200,21 +45154,21 @@ fn aiur_fn_513( let __v_30: G = G::from_u64(105); let __v_31: G = G::from_u64(103); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_513] = [__v_32]; - record.function_queries[513].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_512] = [__v_32]; + record.function_queries[512].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_514: usize = 0; -const IN_514: usize = 0; -const OUT_514: usize = 1; -fn aiur_fn_514( - inp: [G; IN_514], +const INPUT_SIZE_513: usize = 0; +const IN_513: usize = 0; +const OUT_513: usize = 1; +fn aiur_fn_513( + inp: [G; IN_513], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_514], ExecError> { +) -> Result<[G; OUT_513], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(123); let __v_1: G = G::from_u64(63); @@ -45249,21 +45203,21 @@ fn aiur_fn_514( let __v_30: G = G::from_u64(33); let __v_31: G = G::from_u64(76); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_514] = [__v_32]; - record.function_queries[514].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_513] = [__v_32]; + record.function_queries[513].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_515: usize = 0; -const IN_515: usize = 0; -const OUT_515: usize = 1; -fn aiur_fn_515( - inp: [G; IN_515], +const INPUT_SIZE_514: usize = 0; +const IN_514: usize = 0; +const OUT_514: usize = 1; +fn aiur_fn_514( + inp: [G; IN_514], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_515], ExecError> { +) -> Result<[G; OUT_514], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(171); let __v_1: G = G::from_u64(20); @@ -45298,21 +45252,21 @@ fn aiur_fn_515( let __v_30: G = G::from_u64(3); let __v_31: G = G::from_u64(208); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_515] = [__v_32]; - record.function_queries[515].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_514] = [__v_32]; + record.function_queries[514].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_516: usize = 0; -const IN_516: usize = 0; -const OUT_516: usize = 1; -fn aiur_fn_516( - inp: [G; IN_516], +const INPUT_SIZE_515: usize = 0; +const IN_515: usize = 0; +const OUT_515: usize = 1; +fn aiur_fn_515( + inp: [G; IN_515], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_516], ExecError> { +) -> Result<[G; OUT_515], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(35); let __v_1: G = G::from_u64(190); @@ -45347,21 +45301,21 @@ fn aiur_fn_516( let __v_30: G = G::from_u64(32); let __v_31: G = G::from_u64(77); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_516] = [__v_32]; - record.function_queries[516].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_515] = [__v_32]; + record.function_queries[515].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_517: usize = 0; -const IN_517: usize = 0; -const OUT_517: usize = 1; -fn aiur_fn_517( - inp: [G; IN_517], +const INPUT_SIZE_516: usize = 0; +const IN_516: usize = 0; +const OUT_516: usize = 1; +fn aiur_fn_516( + inp: [G; IN_516], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_517], ExecError> { +) -> Result<[G; OUT_516], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(190); let __v_1: G = G::from_u64(80); @@ -45396,21 +45350,21 @@ fn aiur_fn_517( let __v_30: G = G::from_u64(93); let __v_31: G = G::from_u64(232); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_517] = [__v_32]; - record.function_queries[517].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_516] = [__v_32]; + record.function_queries[516].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_518: usize = 0; -const IN_518: usize = 0; -const OUT_518: usize = 1; -fn aiur_fn_518( - inp: [G; IN_518], +const INPUT_SIZE_517: usize = 0; +const IN_517: usize = 0; +const OUT_517: usize = 1; +fn aiur_fn_517( + inp: [G; IN_517], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_518], ExecError> { +) -> Result<[G; OUT_517], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(196); let __v_1: G = G::from_u64(137); @@ -45445,21 +45399,21 @@ fn aiur_fn_518( let __v_30: G = G::from_u64(191); let __v_31: G = G::from_u64(34); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_518] = [__v_32]; - record.function_queries[518].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_517] = [__v_32]; + record.function_queries[517].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_519: usize = 0; -const IN_519: usize = 0; -const OUT_519: usize = 1; -fn aiur_fn_519( - inp: [G; IN_519], +const INPUT_SIZE_518: usize = 0; +const IN_518: usize = 0; +const OUT_518: usize = 1; +fn aiur_fn_518( + inp: [G; IN_518], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_519], ExecError> { +) -> Result<[G; OUT_518], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(14); let __v_1: G = G::from_u64(181); @@ -45494,21 +45448,21 @@ fn aiur_fn_519( let __v_30: G = G::from_u64(41); let __v_31: G = G::from_u64(156); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_519] = [__v_32]; - record.function_queries[519].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_518] = [__v_32]; + record.function_queries[518].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_520: usize = 0; -const IN_520: usize = 0; -const OUT_520: usize = 1; -fn aiur_fn_520( - inp: [G; IN_520], +const INPUT_SIZE_519: usize = 0; +const IN_519: usize = 0; +const OUT_519: usize = 1; +fn aiur_fn_519( + inp: [G; IN_519], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_520], ExecError> { +) -> Result<[G; OUT_519], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(230); let __v_1: G = G::from_u64(235); @@ -45543,21 +45497,21 @@ fn aiur_fn_520( let __v_30: G = G::from_u64(160); let __v_31: G = G::from_u64(164); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_520] = [__v_32]; - record.function_queries[520].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_519] = [__v_32]; + record.function_queries[519].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_521: usize = 0; -const IN_521: usize = 0; -const OUT_521: usize = 1; -fn aiur_fn_521( - inp: [G; IN_521], +const INPUT_SIZE_520: usize = 0; +const IN_520: usize = 0; +const OUT_520: usize = 1; +fn aiur_fn_520( + inp: [G; IN_520], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_521], ExecError> { +) -> Result<[G; OUT_520], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(227); let __v_1: G = G::from_u64(8); @@ -45592,21 +45546,21 @@ fn aiur_fn_521( let __v_30: G = G::from_u64(103); let __v_31: G = G::from_u64(230); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_521] = [__v_32]; - record.function_queries[521].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_520] = [__v_32]; + record.function_queries[520].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_522: usize = 0; -const IN_522: usize = 0; -const OUT_522: usize = 1; -fn aiur_fn_522( - inp: [G; IN_522], +const INPUT_SIZE_521: usize = 0; +const IN_521: usize = 0; +const OUT_521: usize = 1; +fn aiur_fn_521( + inp: [G; IN_521], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_522], ExecError> { +) -> Result<[G; OUT_521], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(122); let __v_1: G = G::from_u64(6); @@ -45641,21 +45595,21 @@ fn aiur_fn_522( let __v_30: G = G::from_u64(29); let __v_31: G = G::from_u64(23); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_522] = [__v_32]; - record.function_queries[522].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_521] = [__v_32]; + record.function_queries[521].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_523: usize = 0; -const IN_523: usize = 0; -const OUT_523: usize = 1; -fn aiur_fn_523( - inp: [G; IN_523], +const INPUT_SIZE_522: usize = 0; +const IN_522: usize = 0; +const OUT_522: usize = 1; +fn aiur_fn_522( + inp: [G; IN_522], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_523], ExecError> { +) -> Result<[G; OUT_522], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(20); let __v_1: G = G::from_u64(236); @@ -45690,21 +45644,21 @@ fn aiur_fn_523( let __v_30: G = G::from_u64(181); let __v_31: G = G::from_u64(180); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_523] = [__v_32]; - record.function_queries[523].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_522] = [__v_32]; + record.function_queries[522].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_524: usize = 0; -const IN_524: usize = 0; -const OUT_524: usize = 1; -fn aiur_fn_524( - inp: [G; IN_524], +const INPUT_SIZE_523: usize = 0; +const IN_523: usize = 0; +const OUT_523: usize = 1; +fn aiur_fn_523( + inp: [G; IN_523], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_524], ExecError> { +) -> Result<[G; OUT_523], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(173); let __v_1: G = G::from_u64(50); @@ -45739,98 +45693,98 @@ fn aiur_fn_524( let __v_30: G = G::from_u64(201); let __v_31: G = G::from_u64(250); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_524] = [__v_32]; - record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_523] = [__v_32]; + record.function_queries[523].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_525: usize = 1; -const IN_525: usize = 1; -const OUT_525: usize = 1; -fn aiur_fn_525( - inp: [G; IN_525], +const INPUT_SIZE_524: usize = 1; +const IN_524: usize = 1; +const OUT_524: usize = 1; +fn aiur_fn_524( + inp: [G; IN_524], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_525], ExecError> { +) -> Result<[G; OUT_524], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_511] = { let __args: [G; IN_511] = []; let __cu = unconstrained; let __hit = record.function_queries[511].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[511].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[511].bump_multiplicity(__i); } let __ret: [G; OUT_511] = unsafe { *(record.function_queries[511].output_at(__i).as_ptr() as *const [G; OUT_511]) }; __ret }, _ => aiur_fn_511(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = []; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_525] = [__v_3]; - record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_524] = [__v_3]; + record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_512] = { let __args: [G; IN_512] = []; let __cu = unconstrained; let __hit = record.function_queries[512].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[512].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[512].bump_multiplicity(__i); } let __ret: [G; OUT_512] = unsafe { *(record.function_queries[512].output_at(__i).as_ptr() as *const [G; OUT_512]) }; __ret }, _ => aiur_fn_512(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_511] = { let __args: [G; IN_511] = []; let __cu = unconstrained; let __hit = record.function_queries[511].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[511].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[511].bump_multiplicity(__i); } let __ret: [G; OUT_511] = unsafe { *(record.function_queries[511].output_at(__i).as_ptr() as *const [G; OUT_511]) }; __ret }, _ => aiur_fn_511(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_525] = [__v_5]; - record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_524] = [__v_5]; + record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_513] = { let __args: [G; IN_513] = []; let __cu = unconstrained; let __hit = record.function_queries[513].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[513].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[513].bump_multiplicity(__i); } let __ret: [G; OUT_513] = unsafe { *(record.function_queries[513].output_at(__i).as_ptr() as *const [G; OUT_513]) }; __ret }, _ => aiur_fn_513(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_512] = { let __args: [G; IN_512] = []; let __cu = unconstrained; let __hit = record.function_queries[512].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[512].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[512].bump_multiplicity(__i); } let __ret: [G; OUT_512] = unsafe { *(record.function_queries[512].output_at(__i).as_ptr() as *const [G; OUT_512]) }; __ret }, _ => aiur_fn_512(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_525] = [__v_7]; - record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_524] = [__v_7]; + record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_523] = { let __args: [G; IN_523] = []; let __cu = unconstrained; let __hit = record.function_queries[523].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[523].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[523].bump_multiplicity(__i); } let __ret: [G; OUT_523] = unsafe { *(record.function_queries[523].output_at(__i).as_ptr() as *const [G; OUT_523]) }; __ret }, _ => aiur_fn_523(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_522] = { let __args: [G; IN_522] = []; let __cu = unconstrained; let __hit = record.function_queries[522].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[522].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[522].bump_multiplicity(__i); } let __ret: [G; OUT_522] = unsafe { *(record.function_queries[522].output_at(__i).as_ptr() as *const [G; OUT_522]) }; __ret }, _ => aiur_fn_522(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(1); - let __ret: [G; OUT_525] = [__v_9]; - record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_524] = [__v_9]; + record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_522] = { let __args: [G; IN_522] = []; let __cu = unconstrained; let __hit = record.function_queries[522].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[522].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[522].bump_multiplicity(__i); } let __ret: [G; OUT_522] = unsafe { *(record.function_queries[522].output_at(__i).as_ptr() as *const [G; OUT_522]) }; __ret }, _ => aiur_fn_522(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_521] = { let __args: [G; IN_521] = []; let __cu = unconstrained; let __hit = record.function_queries[521].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[521].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[521].bump_multiplicity(__i); } let __ret: [G; OUT_521] = unsafe { *(record.function_queries[521].output_at(__i).as_ptr() as *const [G; OUT_521]) }; __ret }, _ => aiur_fn_521(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(1); - let __ret: [G; OUT_525] = [__v_11]; - record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_524] = [__v_11]; + record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_524] = { let __args: [G; IN_524] = []; let __cu = unconstrained; let __hit = record.function_queries[524].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[524].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[524].bump_multiplicity(__i); } let __ret: [G; OUT_524] = unsafe { *(record.function_queries[524].output_at(__i).as_ptr() as *const [G; OUT_524]) }; __ret }, _ => aiur_fn_524(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_523] = { let __args: [G; IN_523] = []; let __cu = unconstrained; let __hit = record.function_queries[523].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[523].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[523].bump_multiplicity(__i); } let __ret: [G; OUT_523] = unsafe { *(record.function_queries[523].output_at(__i).as_ptr() as *const [G; OUT_523]) }; __ret }, _ => aiur_fn_523(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { let __v_13: G = G::from_u64(1); - let __ret: [G; OUT_525] = [__v_13]; - record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_524] = [__v_13]; + record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_525] = [__v_13]; - record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_524] = [__v_13]; + record.function_queries[524].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -45847,56 +45801,56 @@ fn aiur_fn_525( }) } -const INPUT_SIZE_526: usize = 1; -const IN_526: usize = 1; -const OUT_526: usize = 1; -fn aiur_fn_526( - inp: [G; IN_526], +const INPUT_SIZE_525: usize = 1; +const IN_525: usize = 1; +const OUT_525: usize = 1; +fn aiur_fn_525( + inp: [G; IN_525], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_526], ExecError> { +) -> Result<[G; OUT_525], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_523] = { let __args: [G; IN_523] = []; let __cu = unconstrained; let __hit = record.function_queries[523].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[523].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[523].bump_multiplicity(__i); } let __ret: [G; OUT_523] = unsafe { *(record.function_queries[523].output_at(__i).as_ptr() as *const [G; OUT_523]) }; __ret }, _ => aiur_fn_523(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_522] = { let __args: [G; IN_522] = []; let __cu = unconstrained; let __hit = record.function_queries[522].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[522].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[522].bump_multiplicity(__i); } let __ret: [G; OUT_522] = unsafe { *(record.function_queries[522].output_at(__i).as_ptr() as *const [G; OUT_522]) }; __ret }, _ => aiur_fn_522(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_526] = [__v_3]; - record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_525] = [__v_3]; + record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_522] = { let __args: [G; IN_522] = []; let __cu = unconstrained; let __hit = record.function_queries[522].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[522].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[522].bump_multiplicity(__i); } let __ret: [G; OUT_522] = unsafe { *(record.function_queries[522].output_at(__i).as_ptr() as *const [G; OUT_522]) }; __ret }, _ => aiur_fn_522(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_521] = { let __args: [G; IN_521] = []; let __cu = unconstrained; let __hit = record.function_queries[521].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[521].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[521].bump_multiplicity(__i); } let __ret: [G; OUT_521] = unsafe { *(record.function_queries[521].output_at(__i).as_ptr() as *const [G; OUT_521]) }; __ret }, _ => aiur_fn_521(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_526] = [__v_5]; - record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_525] = [__v_5]; + record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_524] = { let __args: [G; IN_524] = []; let __cu = unconstrained; let __hit = record.function_queries[524].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[524].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[524].bump_multiplicity(__i); } let __ret: [G; OUT_524] = unsafe { *(record.function_queries[524].output_at(__i).as_ptr() as *const [G; OUT_524]) }; __ret }, _ => aiur_fn_524(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_523] = { let __args: [G; IN_523] = []; let __cu = unconstrained; let __hit = record.function_queries[523].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[523].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[523].bump_multiplicity(__i); } let __ret: [G; OUT_523] = unsafe { *(record.function_queries[523].output_at(__i).as_ptr() as *const [G; OUT_523]) }; __ret }, _ => aiur_fn_523(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_526] = [__v_7]; - record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_525] = [__v_7]; + record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_526] = [__v_7]; - record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_525] = [__v_7]; + record.function_queries[525].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -45907,15 +45861,15 @@ fn aiur_fn_526( }) } -const INPUT_SIZE_527: usize = 1; -const IN_527: usize = 1; -const OUT_527: usize = 3; -fn aiur_fn_527( - inp: [G; IN_527], +const INPUT_SIZE_526: usize = 1; +const IN_526: usize = 1; +const OUT_526: usize = 3; +fn aiur_fn_526( + inp: [G; IN_526], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_527], ExecError> { +) -> Result<[G; OUT_526], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -45932,11 +45886,11 @@ fn aiur_fn_527( let __v_8: G = __loaded[3]; match __v_5.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_151] = { let __args: [G; IN_151] = []; let __cu = unconstrained; let __hit = record.function_queries[151].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[151].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[151].bump_multiplicity(__i); } let __ret: [G; OUT_151] = unsafe { *(record.function_queries[151].output_at(__i).as_ptr() as *const [G; OUT_151]) }; __ret }, _ => aiur_fn_151(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_6, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; @@ -45948,8 +45902,8 @@ fn aiur_fn_527( let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 10] = [__v_16, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_527] = [__v_14, __v_15, __v_18]; - record.function_queries[527].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_526] = [__v_14, __v_15, __v_18]; + record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -45963,8 +45917,8 @@ fn aiur_fn_527( match __v_15.as_canonical_u64() { 0u64 => { let __v_18: G = G::from_u64(1); - let __ret: [G; OUT_527] = [__v_18, __v_12, __v_16]; - record.function_queries[527].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_526] = [__v_18, __v_12, __v_16]; + record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -45973,8 +45927,8 @@ fn aiur_fn_527( let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 10] = [__v_20, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_527] = [__v_18, __v_19, __v_22]; - record.function_queries[527].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_526] = [__v_18, __v_19, __v_22]; + record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -45985,8 +45939,8 @@ fn aiur_fn_527( let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 10] = [__v_20, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_527] = [__v_18, __v_19, __v_22]; - record.function_queries[527].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_526] = [__v_18, __v_19, __v_22]; + record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -45999,8 +45953,8 @@ fn aiur_fn_527( let __v_11: G = G::from_u64(1); let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 10] = [__v_11, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_527] = [__v_9, __v_10, __v_13]; - record.function_queries[527].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_526] = [__v_9, __v_10, __v_13]; + record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46011,34 +45965,34 @@ fn aiur_fn_527( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 10] = [__v_7, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_527] = [__v_5, __v_6, __v_9]; - record.function_queries[527].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_526] = [__v_5, __v_6, __v_9]; + record.function_queries[526].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_528: usize = 2; -const IN_528: usize = 2; -const OUT_528: usize = 1; -fn aiur_fn_528( - inp: [G; IN_528], +const INPUT_SIZE_527: usize = 2; +const IN_527: usize = 2; +const OUT_527: usize = 1; +fn aiur_fn_527( + inp: [G; IN_527], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_528], ExecError> { +) -> Result<[G; OUT_527], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_0.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_149] = { let __args: [G; IN_149] = []; let __cu = unconstrained; let __hit = record.function_queries[149].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[149].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[149].bump_multiplicity(__i); } let __ret: [G; OUT_149] = unsafe { *(record.function_queries[149].output_at(__i).as_ptr() as *const [G; OUT_149]) }; __ret }, _ => aiur_fn_149(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; break '__mc_0 [__v_2]; }, _ => { - let __r_arr: [G; OUT_151] = { let __args: [G; IN_151] = []; let __cu = unconstrained; let __hit = record.function_queries[151].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[151].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[151].bump_multiplicity(__i); } let __ret: [G; OUT_151] = unsafe { *(record.function_queries[151].output_at(__i).as_ptr() as *const [G; OUT_151]) }; __ret }, _ => aiur_fn_151(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_150] = { let __args: [G; IN_150] = []; let __cu = unconstrained; let __hit = record.function_queries[150].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[150].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[150].bump_multiplicity(__i); } let __ret: [G; OUT_150] = unsafe { *(record.function_queries[150].output_at(__i).as_ptr() as *const [G; OUT_150]) }; __ret }, _ => aiur_fn_150(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; break '__mc_0 [__v_2]; }, @@ -46058,27 +46012,27 @@ fn aiur_fn_528( let __v_13: G = G::from_u64(3); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_13, __v_8, __v_12, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_528] = [__v_15]; - record.function_queries[528].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_527] = [__v_15]; + record.function_queries[527].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_529: usize = 4; -const IN_529: usize = 4; -const OUT_529: usize = 2; -fn aiur_fn_529( - inp: [G; IN_529], +const INPUT_SIZE_528: usize = 4; +const IN_528: usize = 4; +const OUT_528: usize = 2; +fn aiur_fn_528( + inp: [G; IN_528], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_529], ExecError> { +) -> Result<[G; OUT_528], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(2); let __v_6: G = { let __a_val = __v_4.as_canonical_u64(); let __b_val = __v_5.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -46089,24 +46043,24 @@ fn aiur_fn_529( let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_8, __v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_529] = [__v_7, __v_11]; - record.function_queries[529].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_528] = [__v_7, __v_11]; + record.function_queries[528].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_527] = { let __args: [G; IN_527] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[527].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[527].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[527].bump_multiplicity(__i); } let __ret: [G; OUT_527] = unsafe { *(record.function_queries[527].output_at(__i).as_ptr() as *const [G; OUT_527]) }; __ret }, _ => aiur_fn_527(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_526] = { let __args: [G; IN_526] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[526].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[526].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[526].bump_multiplicity(__i); } let __ret: [G; OUT_526] = unsafe { *(record.function_queries[526].output_at(__i).as_ptr() as *const [G; OUT_526]) }; __ret }, _ => aiur_fn_526(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_527] = { let __args: [G; IN_527] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[527].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[527].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[527].bump_multiplicity(__i); } let __ret: [G; OUT_527] = unsafe { *(record.function_queries[527].output_at(__i).as_ptr() as *const [G; OUT_527]) }; __ret }, _ => aiur_fn_527(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_526] = { let __args: [G; IN_526] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[526].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[526].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[526].bump_multiplicity(__i); } let __ret: [G; OUT_526] = unsafe { *(record.function_queries[526].output_at(__i).as_ptr() as *const [G; OUT_526]) }; __ret }, _ => aiur_fn_526(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -46117,26 +46071,26 @@ fn aiur_fn_529( let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_18, __v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_529] = [__v_17, __v_21]; - record.function_queries[529].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_528] = [__v_17, __v_21]; + record.function_queries[528].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_530] = { let __args: [G; IN_530] = [__v_0, __v_1, __v_2, __v_8, __v_10, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[530].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[530].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[530].bump_multiplicity(__i); } let __ret: [G; OUT_530] = unsafe { *(record.function_queries[530].output_at(__i).as_ptr() as *const [G; OUT_530]) }; __ret }, _ => aiur_fn_530(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_529] = { let __args: [G; IN_529] = [__v_0, __v_1, __v_2, __v_8, __v_10, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[529].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[529].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[529].bump_multiplicity(__i); } let __ret: [G; OUT_529] = unsafe { *(record.function_queries[529].output_at(__i).as_ptr() as *const [G; OUT_529]) }; __ret }, _ => aiur_fn_529(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; - let __ret: [G; OUT_529] = [__v_17, __v_18]; - record.function_queries[529].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_528] = [__v_17, __v_18]; + record.function_queries[528].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_530] = { let __args: [G; IN_530] = [__v_0, __v_1, __v_2, __v_8, __v_10, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[530].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[530].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[530].bump_multiplicity(__i); } let __ret: [G; OUT_530] = unsafe { *(record.function_queries[530].output_at(__i).as_ptr() as *const [G; OUT_530]) }; __ret }, _ => aiur_fn_530(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_529] = { let __args: [G; IN_529] = [__v_0, __v_1, __v_2, __v_8, __v_10, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[529].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[529].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[529].bump_multiplicity(__i); } let __ret: [G; OUT_529] = unsafe { *(record.function_queries[529].output_at(__i).as_ptr() as *const [G; OUT_529]) }; __ret }, _ => aiur_fn_529(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __ret: [G; OUT_529] = [__v_14, __v_15]; - record.function_queries[529].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_528] = [__v_14, __v_15]; + record.function_queries[528].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46145,15 +46099,15 @@ fn aiur_fn_529( }) } -const INPUT_SIZE_530: usize = 6; -const IN_530: usize = 6; -const OUT_530: usize = 2; -fn aiur_fn_530( - inp: [G; IN_530], +const INPUT_SIZE_529: usize = 6; +const IN_529: usize = 6; +const OUT_529: usize = 2; +fn aiur_fn_529( + inp: [G; IN_529], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_530], ExecError> { +) -> Result<[G; OUT_529], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -46161,25 +46115,25 @@ fn aiur_fn_530( let __v_3: G = inp[3]; let __v_4: G = inp[4]; let __v_5: G = inp[5]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_527] = { let __args: [G; IN_527] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[527].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[527].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[527].bump_multiplicity(__i); } let __ret: [G; OUT_527] = unsafe { *(record.function_queries[527].output_at(__i).as_ptr() as *const [G; OUT_527]) }; __ret }, _ => aiur_fn_527(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_526] = { let __args: [G; IN_526] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[526].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[526].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[526].bump_multiplicity(__i); } let __ret: [G; OUT_526] = unsafe { *(record.function_queries[526].output_at(__i).as_ptr() as *const [G; OUT_526]) }; __ret }, _ => aiur_fn_526(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = __r_arr[2]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_527] = { let __args: [G; IN_527] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[527].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[527].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[527].bump_multiplicity(__i); } let __ret: [G; OUT_527] = unsafe { *(record.function_queries[527].output_at(__i).as_ptr() as *const [G; OUT_527]) }; __ret }, _ => aiur_fn_527(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_526] = { let __args: [G; IN_526] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[526].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[526].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[526].bump_multiplicity(__i); } let __ret: [G; OUT_526] = unsafe { *(record.function_queries[526].output_at(__i).as_ptr() as *const [G; OUT_526]) }; __ret }, _ => aiur_fn_526(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_528] = { let __args: [G; IN_528] = [__v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[528].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[528].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[528].bump_multiplicity(__i); } let __ret: [G; OUT_528] = unsafe { *(record.function_queries[528].output_at(__i).as_ptr() as *const [G; OUT_528]) }; __ret }, _ => aiur_fn_528(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_527] = { let __args: [G; IN_527] = [__v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[527].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[527].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[527].bump_multiplicity(__i); } let __ret: [G; OUT_527] = unsafe { *(record.function_queries[527].output_at(__i).as_ptr() as *const [G; OUT_527]) }; __ret }, _ => aiur_fn_527(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __r_arr: [G; OUT_528] = { let __args: [G; IN_528] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[528].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[528].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[528].bump_multiplicity(__i); } let __ret: [G; OUT_528] = unsafe { *(record.function_queries[528].output_at(__i).as_ptr() as *const [G; OUT_528]) }; __ret }, _ => aiur_fn_528(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_527] = { let __args: [G; IN_527] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[527].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[527].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[527].bump_multiplicity(__i); } let __ret: [G; OUT_527] = unsafe { *(record.function_queries[527].output_at(__i).as_ptr() as *const [G; OUT_527]) }; __ret }, _ => aiur_fn_527(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(2); let __v_17: G = G::from_u64(0); @@ -46191,13 +46145,13 @@ fn aiur_fn_530( let __v_23: G = G::from_u64(0); let __v_24: G = { let __values: [G; 4] = [__v_22, __v_21, __v_15, __v_23]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_25: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_2, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_24, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_24, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __ret: [G; OUT_530] = [__v_27, __v_28]; - record.function_queries[530].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_529] = [__v_27, __v_28]; + record.function_queries[529].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -46206,8 +46160,8 @@ fn aiur_fn_530( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_530] = [__v_14, __v_18]; - record.function_queries[530].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_529] = [__v_14, __v_18]; + record.function_queries[529].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46218,29 +46172,29 @@ fn aiur_fn_530( let __v_13: G = G::from_u64(0); let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_530] = [__v_11, __v_15]; - record.function_queries[530].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_529] = [__v_11, __v_15]; + record.function_queries[529].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_531: usize = 4; -const IN_531: usize = 4; -const OUT_531: usize = 2; -fn aiur_fn_531( - inp: [G; IN_531], +const INPUT_SIZE_530: usize = 4; +const IN_530: usize = 4; +const OUT_530: usize = 2; +fn aiur_fn_530( + inp: [G; IN_530], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_531], ExecError> { +) -> Result<[G; OUT_530], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(2); let __v_6: G = { let __a_val = __v_4.as_canonical_u64(); let __b_val = __v_5.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -46251,50 +46205,50 @@ fn aiur_fn_531( let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_8, __v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_531] = [__v_7, __v_11]; - record.function_queries[531].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_530] = [__v_7, __v_11]; + record.function_queries[530].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_526] = { let __args: [G; IN_526] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[526].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[526].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[526].bump_multiplicity(__i); } let __ret: [G; OUT_526] = unsafe { *(record.function_queries[526].output_at(__i).as_ptr() as *const [G; OUT_526]) }; __ret }, _ => aiur_fn_526(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_525] = { let __args: [G; IN_525] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[525].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[525].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[525].bump_multiplicity(__i); } let __ret: [G; OUT_525] = unsafe { *(record.function_queries[525].output_at(__i).as_ptr() as *const [G; OUT_525]) }; __ret }, _ => aiur_fn_525(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_529] = { let __args: [G; IN_529] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[529].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[529].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[529].bump_multiplicity(__i); } let __ret: [G; OUT_529] = unsafe { *(record.function_queries[529].output_at(__i).as_ptr() as *const [G; OUT_529]) }; __ret }, _ => aiur_fn_529(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_528] = { let __args: [G; IN_528] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[528].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[528].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[528].bump_multiplicity(__i); } let __ret: [G; OUT_528] = unsafe { *(record.function_queries[528].output_at(__i).as_ptr() as *const [G; OUT_528]) }; __ret }, _ => aiur_fn_528(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_531] = [__v_8, __v_9]; - record.function_queries[531].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_530] = [__v_8, __v_9]; + record.function_queries[530].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_511] = { let __args: [G; IN_511] = []; let __cu = unconstrained; let __hit = record.function_queries[511].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[511].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[511].bump_multiplicity(__i); } let __ret: [G; OUT_511] = unsafe { *(record.function_queries[511].output_at(__i).as_ptr() as *const [G; OUT_511]) }; __ret }, _ => aiur_fn_511(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = []; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_512] = { let __args: [G; IN_512] = []; let __cu = unconstrained; let __hit = record.function_queries[512].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[512].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[512].bump_multiplicity(__i); } let __ret: [G; OUT_512] = unsafe { *(record.function_queries[512].output_at(__i).as_ptr() as *const [G; OUT_512]) }; __ret }, _ => aiur_fn_512(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_511] = { let __args: [G; IN_511] = []; let __cu = unconstrained; let __hit = record.function_queries[511].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[511].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[511].bump_multiplicity(__i); } let __ret: [G; OUT_511] = unsafe { *(record.function_queries[511].output_at(__i).as_ptr() as *const [G; OUT_511]) }; __ret }, _ => aiur_fn_511(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_513] = { let __args: [G; IN_513] = []; let __cu = unconstrained; let __hit = record.function_queries[513].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[513].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[513].bump_multiplicity(__i); } let __ret: [G; OUT_513] = unsafe { *(record.function_queries[513].output_at(__i).as_ptr() as *const [G; OUT_513]) }; __ret }, _ => aiur_fn_513(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_512] = { let __args: [G; IN_512] = []; let __cu = unconstrained; let __hit = record.function_queries[512].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[512].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[512].bump_multiplicity(__i); } let __ret: [G; OUT_512] = unsafe { *(record.function_queries[512].output_at(__i).as_ptr() as *const [G; OUT_512]) }; __ret }, _ => aiur_fn_512(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_532] = { let __args: [G; IN_532] = [__v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[532].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[532].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[532].bump_multiplicity(__i); } let __ret: [G; OUT_532] = unsafe { *(record.function_queries[532].output_at(__i).as_ptr() as *const [G; OUT_532]) }; __ret }, _ => aiur_fn_532(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_531] = { let __args: [G; IN_531] = [__v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[531].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[531].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[531].bump_multiplicity(__i); } let __ret: [G; OUT_531] = unsafe { *(record.function_queries[531].output_at(__i).as_ptr() as *const [G; OUT_531]) }; __ret }, _ => aiur_fn_531(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __ret: [G; OUT_531] = [__v_14, __v_15]; - record.function_queries[531].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_530] = [__v_14, __v_15]; + record.function_queries[530].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_533] = { let __args: [G; IN_533] = [__v_9, __v_11, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[533].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[533].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[533].bump_multiplicity(__i); } let __ret: [G; OUT_533] = unsafe { *(record.function_queries[533].output_at(__i).as_ptr() as *const [G; OUT_533]) }; __ret }, _ => aiur_fn_533(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_532] = { let __args: [G; IN_532] = [__v_9, __v_11, __v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[532].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[532].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[532].bump_multiplicity(__i); } let __ret: [G; OUT_532] = unsafe { *(record.function_queries[532].output_at(__i).as_ptr() as *const [G; OUT_532]) }; __ret }, _ => aiur_fn_532(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __ret: [G; OUT_531] = [__v_14, __v_15]; - record.function_queries[531].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_530] = [__v_14, __v_15]; + record.function_queries[530].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46305,28 +46259,28 @@ fn aiur_fn_531( }) } -const INPUT_SIZE_532: usize = 3; -const IN_532: usize = 3; -const OUT_532: usize = 2; -fn aiur_fn_532( - inp: [G; IN_532], +const INPUT_SIZE_531: usize = 3; +const IN_531: usize = 3; +const OUT_531: usize = 2; +fn aiur_fn_531( + inp: [G; IN_531], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_532], ExecError> { +) -> Result<[G; OUT_531], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; match __v_8.as_canonical_u64() { @@ -46336,17 +46290,17 @@ fn aiur_fn_532( let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 4] = [__v_11, __v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_532] = [__v_10, __v_14]; - record.function_queries[532].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_531] = [__v_10, __v_14]; + record.function_queries[531].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __r_arr: [G; OUT_116] = { let __args: [G; IN_116] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[116].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[116].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[116].bump_multiplicity(__i); } let __ret: [G; OUT_116] = unsafe { *(record.function_queries[116].output_at(__i).as_ptr() as *const [G; OUT_116]) }; __ret }, _ => aiur_fn_116(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_245] = { let __args: [G; IN_245] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[245].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[245].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[245].bump_multiplicity(__i); } let __ret: [G; OUT_245] = unsafe { *(record.function_queries[245].output_at(__i).as_ptr() as *const [G; OUT_245]) }; __ret }, _ => aiur_fn_245(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_244] = { let __args: [G; IN_244] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[244].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[244].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[244].bump_multiplicity(__i); } let __ret: [G; OUT_244] = unsafe { *(record.function_queries[244].output_at(__i).as_ptr() as *const [G; OUT_244]) }; __ret }, _ => aiur_fn_244(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(2); - let __r_arr: [G; OUT_511] = { let __args: [G; IN_511] = []; let __cu = unconstrained; let __hit = record.function_queries[511].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[511].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[511].bump_multiplicity(__i); } let __ret: [G; OUT_511] = unsafe { *(record.function_queries[511].output_at(__i).as_ptr() as *const [G; OUT_511]) }; __ret }, _ => aiur_fn_511(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = []; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(0); let __v_15: G = { let __values: [G; 4] = [__v_12, __v_13, __v_0, __v_14]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; @@ -46357,13 +46311,13 @@ fn aiur_fn_532( let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 4] = [__v_19, __v_18, __v_6, __v_20]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_22: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_1, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_1, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __v_24: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_21, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_21, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __ret: [G; OUT_532] = [__v_24, __v_25]; - record.function_queries[532].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_531] = [__v_24, __v_25]; + record.function_queries[531].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -46373,15 +46327,15 @@ fn aiur_fn_532( }) } -const INPUT_SIZE_533: usize = 6; -const IN_533: usize = 6; -const OUT_533: usize = 2; -fn aiur_fn_533( - inp: [G; IN_533], +const INPUT_SIZE_532: usize = 6; +const IN_532: usize = 6; +const OUT_532: usize = 2; +fn aiur_fn_532( + inp: [G; IN_532], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_533], ExecError> { +) -> Result<[G; OUT_532], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -46390,16 +46344,16 @@ fn aiur_fn_533( let __v_4: G = inp[4]; let __v_5: G = inp[5]; let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_7, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_7, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_9, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_9, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; match __v_12.as_canonical_u64() { @@ -46409,12 +46363,12 @@ fn aiur_fn_533( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_533] = [__v_14, __v_18]; - record.function_queries[533].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_532] = [__v_14, __v_18]; + record.function_queries[532].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_243] = { let __args: [G; IN_243] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[243].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[243].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[243].bump_multiplicity(__i); } let __ret: [G; OUT_243] = unsafe { *(record.function_queries[243].output_at(__i).as_ptr() as *const [G; OUT_243]) }; __ret }, _ => aiur_fn_243(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_242] = { let __args: [G; IN_242] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[242].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[242].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[242].bump_multiplicity(__i); } let __ret: [G; OUT_242] = unsafe { *(record.function_queries[242].output_at(__i).as_ptr() as *const [G; OUT_242]) }; __ret }, _ => aiur_fn_242(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; match __v_14.as_canonical_u64() { @@ -46424,8 +46378,8 @@ fn aiur_fn_533( let __v_18: G = G::from_u64(0); let __v_19: G = G::from_u64(0); let __v_20: G = { let __values: [G; 4] = [__v_17, __v_18, __v_19, __v_19]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_533] = [__v_16, __v_20]; - record.function_queries[533].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_532] = [__v_16, __v_20]; + record.function_queries[532].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -46436,18 +46390,18 @@ fn aiur_fn_533( break '__mc_0 [__v_16]; }, _ => { - let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_13, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_337] = { let __args: [G; IN_337] = [__v_13, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[337].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[337].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[337].bump_multiplicity(__i); } let __ret: [G; OUT_337] = unsafe { *(record.function_queries[337].output_at(__i).as_ptr() as *const [G; OUT_337]) }; __ret }, _ => aiur_fn_337(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; break '__mc_0 [__v_16]; }, } }; let __v_16: G = __mc_out___mc_0[0]; - let __r_arr: [G; OUT_534] = { let __args: [G; IN_534] = [__v_0, __v_1, __v_16, __v_7, __v_9, __v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[534].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[534].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[534].bump_multiplicity(__i); } let __ret: [G; OUT_534] = unsafe { *(record.function_queries[534].output_at(__i).as_ptr() as *const [G; OUT_534]) }; __ret }, _ => aiur_fn_534(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_533] = { let __args: [G; IN_533] = [__v_0, __v_1, __v_16, __v_7, __v_9, __v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[533].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[533].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[533].bump_multiplicity(__i); } let __ret: [G; OUT_533] = unsafe { *(record.function_queries[533].output_at(__i).as_ptr() as *const [G; OUT_533]) }; __ret }, _ => aiur_fn_533(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; - let __ret: [G; OUT_533] = [__v_17, __v_18]; - record.function_queries[533].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_532] = [__v_17, __v_18]; + record.function_queries[532].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -46462,15 +46416,15 @@ fn aiur_fn_533( }) } -const INPUT_SIZE_534: usize = 9; -const IN_534: usize = 9; -const OUT_534: usize = 2; -fn aiur_fn_534( - inp: [G; IN_534], +const INPUT_SIZE_533: usize = 9; +const IN_533: usize = 9; +const OUT_533: usize = 2; +fn aiur_fn_533( + inp: [G; IN_533], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_534], ExecError> { +) -> Result<[G; OUT_533], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -46491,8 +46445,8 @@ fn aiur_fn_534( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_534] = [__v_12, __v_16]; - record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_533] = [__v_12, __v_16]; + record.function_queries[533].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -46508,12 +46462,12 @@ fn aiur_fn_534( let __v_21: G = { let __values: [G; 3] = [__v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_22: G = { let __values: [G; 3] = [__v_18, __v_17, __v_21]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_23: G = G::from_u64(2); - let __r_arr: [G; OUT_521] = { let __args: [G; IN_521] = []; let __cu = unconstrained; let __hit = record.function_queries[521].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[521].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[521].bump_multiplicity(__i); } let __ret: [G; OUT_521] = unsafe { *(record.function_queries[521].output_at(__i).as_ptr() as *const [G; OUT_521]) }; __ret }, _ => aiur_fn_521(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_520] = { let __args: [G; IN_520] = []; let __cu = unconstrained; let __hit = record.function_queries[520].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[520].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[520].bump_multiplicity(__i); } let __ret: [G; OUT_520] = unsafe { *(record.function_queries[520].output_at(__i).as_ptr() as *const [G; OUT_520]) }; __ret }, _ => aiur_fn_520(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = G::from_u64(0); let __v_26: G = { let __values: [G; 4] = [__v_23, __v_24, __v_22, __v_25]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_27: G = G::from_u64(2); - let __r_arr: [G; OUT_520] = { let __args: [G; IN_520] = []; let __cu = unconstrained; let __hit = record.function_queries[520].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[520].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[520].bump_multiplicity(__i); } let __ret: [G; OUT_520] = unsafe { *(record.function_queries[520].output_at(__i).as_ptr() as *const [G; OUT_520]) }; __ret }, _ => aiur_fn_520(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_519] = { let __args: [G; IN_519] = []; let __cu = unconstrained; let __hit = record.function_queries[519].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[519].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[519].bump_multiplicity(__i); } let __ret: [G; OUT_519] = unsafe { *(record.function_queries[519].output_at(__i).as_ptr() as *const [G; OUT_519]) }; __ret }, _ => aiur_fn_519(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = G::from_u64(1); let __v_30: G = G::from_u64(1); @@ -46522,12 +46476,12 @@ fn aiur_fn_534( let __v_33: G = { let __values: [G; 4] = [__v_27, __v_28, __v_31, __v_32]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_2.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_176] = { let __args: [G; IN_176] = []; let __cu = unconstrained; let __hit = record.function_queries[176].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[176].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[176].bump_multiplicity(__i); } let __ret: [G; OUT_176] = unsafe { *(record.function_queries[176].output_at(__i).as_ptr() as *const [G; OUT_176]) }; __ret }, _ => aiur_fn_176(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_175] = { let __args: [G; IN_175] = []; let __cu = unconstrained; let __hit = record.function_queries[175].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[175].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[175].bump_multiplicity(__i); } let __ret: [G; OUT_175] = unsafe { *(record.function_queries[175].output_at(__i).as_ptr() as *const [G; OUT_175]) }; __ret }, _ => aiur_fn_175(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; break '__mc_0 [__v_34]; }, _ => { - let __r_arr: [G; OUT_177] = { let __args: [G; IN_177] = []; let __cu = unconstrained; let __hit = record.function_queries[177].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[177].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[177].bump_multiplicity(__i); } let __ret: [G; OUT_177] = unsafe { *(record.function_queries[177].output_at(__i).as_ptr() as *const [G; OUT_177]) }; __ret }, _ => aiur_fn_177(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_176] = { let __args: [G; IN_176] = []; let __cu = unconstrained; let __hit = record.function_queries[176].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[176].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[176].bump_multiplicity(__i); } let __ret: [G; OUT_176] = unsafe { *(record.function_queries[176].output_at(__i).as_ptr() as *const [G; OUT_176]) }; __ret }, _ => aiur_fn_176(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; break '__mc_0 [__v_34]; }, @@ -46550,12 +46504,12 @@ fn aiur_fn_534( 1u64 => { match __v_2.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_516] = { let __args: [G; IN_516] = []; let __cu = unconstrained; let __hit = record.function_queries[516].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[516].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[516].bump_multiplicity(__i); } let __ret: [G; OUT_516] = unsafe { *(record.function_queries[516].output_at(__i).as_ptr() as *const [G; OUT_516]) }; __ret }, _ => aiur_fn_516(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_515] = { let __args: [G; IN_515] = []; let __cu = unconstrained; let __hit = record.function_queries[515].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[515].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[515].bump_multiplicity(__i); } let __ret: [G; OUT_515] = unsafe { *(record.function_queries[515].output_at(__i).as_ptr() as *const [G; OUT_515]) }; __ret }, _ => aiur_fn_515(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; break '__mc_1 [__v_47]; }, _ => { - let __r_arr: [G; OUT_517] = { let __args: [G; IN_517] = []; let __cu = unconstrained; let __hit = record.function_queries[517].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[517].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[517].bump_multiplicity(__i); } let __ret: [G; OUT_517] = unsafe { *(record.function_queries[517].output_at(__i).as_ptr() as *const [G; OUT_517]) }; __ret }, _ => aiur_fn_517(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_516] = { let __args: [G; IN_516] = []; let __cu = unconstrained; let __hit = record.function_queries[516].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[516].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[516].bump_multiplicity(__i); } let __ret: [G; OUT_516] = unsafe { *(record.function_queries[516].output_at(__i).as_ptr() as *const [G; OUT_516]) }; __ret }, _ => aiur_fn_516(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; break '__mc_1 [__v_47]; }, @@ -46564,12 +46518,12 @@ fn aiur_fn_534( _ => { match __v_2.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_518] = { let __args: [G; IN_518] = []; let __cu = unconstrained; let __hit = record.function_queries[518].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[518].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[518].bump_multiplicity(__i); } let __ret: [G; OUT_518] = unsafe { *(record.function_queries[518].output_at(__i).as_ptr() as *const [G; OUT_518]) }; __ret }, _ => aiur_fn_518(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_517] = { let __args: [G; IN_517] = []; let __cu = unconstrained; let __hit = record.function_queries[517].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[517].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[517].bump_multiplicity(__i); } let __ret: [G; OUT_517] = unsafe { *(record.function_queries[517].output_at(__i).as_ptr() as *const [G; OUT_517]) }; __ret }, _ => aiur_fn_517(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; break '__mc_1 [__v_47]; }, _ => { - let __r_arr: [G; OUT_519] = { let __args: [G; IN_519] = []; let __cu = unconstrained; let __hit = record.function_queries[519].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[519].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[519].bump_multiplicity(__i); } let __ret: [G; OUT_519] = unsafe { *(record.function_queries[519].output_at(__i).as_ptr() as *const [G; OUT_519]) }; __ret }, _ => aiur_fn_519(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_518] = { let __args: [G; IN_518] = []; let __cu = unconstrained; let __hit = record.function_queries[518].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[518].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[518].bump_multiplicity(__i); } let __ret: [G; OUT_518] = unsafe { *(record.function_queries[518].output_at(__i).as_ptr() as *const [G; OUT_518]) }; __ret }, _ => aiur_fn_518(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; break '__mc_1 [__v_47]; }, @@ -46593,31 +46547,31 @@ fn aiur_fn_534( let __v_60: G = G::from_u64(3); let __v_61: G = G::from_u64(0); let __v_62: G = { let __values: [G; 4] = [__v_60, __v_59, __v_46, __v_61]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_2, __v_62, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_536] = { let __args: [G; IN_536] = [__v_2, __v_62, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[536].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[536].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[536].bump_multiplicity(__i); } let __ret: [G; OUT_536] = unsafe { *(record.function_queries[536].output_at(__i).as_ptr() as *const [G; OUT_536]) }; __ret }, _ => aiur_fn_536(__args, record, io_buffer, __cu)? } }; let __v_63: G = __r_arr[0]; let __v_64: G = __r_arr[1]; - let __ret: [G; OUT_534] = [__v_63, __v_64]; - record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_533] = [__v_63, __v_64]; + record.function_queries[533].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_535: usize = 3; -const IN_535: usize = 3; -const OUT_535: usize = 2; -fn aiur_fn_535( - inp: [G; IN_535], +const INPUT_SIZE_534: usize = 3; +const IN_534: usize = 3; +const OUT_534: usize = 2; +fn aiur_fn_534( + inp: [G; IN_534], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_535], ExecError> { +) -> Result<[G; OUT_534], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = G::from_u64(2); let __v_5: G = { let __a_val = __v_3.as_canonical_u64(); let __b_val = __v_4.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -46628,16 +46582,16 @@ fn aiur_fn_535( let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_7, __v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_535] = [__v_6, __v_10]; - record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_534] = [__v_6, __v_10]; + record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -46657,7 +46611,7 @@ fn aiur_fn_535( 7u64 => { match __v_15.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_12, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_12, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; match __v_18.as_canonical_u64() { 0u64 => { @@ -46666,16 +46620,16 @@ fn aiur_fn_535( let __v_21: G = G::from_u64(0); let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 4] = [__v_20, __v_21, __v_22, __v_22]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_535] = [__v_19, __v_23]; - record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_534] = [__v_19, __v_23]; + record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_536] = { let __args: [G; IN_536] = [__v_12, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[536].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[536].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[536].bump_multiplicity(__i); } let __ret: [G; OUT_536] = unsafe { *(record.function_queries[536].output_at(__i).as_ptr() as *const [G; OUT_536]) }; __ret }, _ => aiur_fn_536(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_535] = { let __args: [G; IN_535] = [__v_12, __v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[535].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[535].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[535].bump_multiplicity(__i); } let __ret: [G; OUT_535] = unsafe { *(record.function_queries[535].output_at(__i).as_ptr() as *const [G; OUT_535]) }; __ret }, _ => aiur_fn_535(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; - let __ret: [G; OUT_535] = [__v_19, __v_20]; - record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_534] = [__v_19, __v_20]; + record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46686,8 +46640,8 @@ fn aiur_fn_535( let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(0); let __v_22: G = { let __values: [G; 4] = [__v_19, __v_20, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_535] = [__v_18, __v_22]; - record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_534] = [__v_18, __v_22]; + record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46698,8 +46652,8 @@ fn aiur_fn_535( let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(0); let __v_22: G = { let __values: [G; 4] = [__v_19, __v_20, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_535] = [__v_18, __v_22]; - record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_534] = [__v_18, __v_22]; + record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46710,8 +46664,8 @@ fn aiur_fn_535( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_535] = [__v_14, __v_18]; - record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_534] = [__v_14, __v_18]; + record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46722,8 +46676,8 @@ fn aiur_fn_535( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_535] = [__v_14, __v_18]; - record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_534] = [__v_14, __v_18]; + record.function_queries[534].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -46732,15 +46686,15 @@ fn aiur_fn_535( }) } -const INPUT_SIZE_536: usize = 4; -const IN_536: usize = 4; -const OUT_536: usize = 2; -fn aiur_fn_536( - inp: [G; IN_536], +const INPUT_SIZE_535: usize = 4; +const IN_535: usize = 4; +const OUT_535: usize = 2; +fn aiur_fn_535( + inp: [G; IN_535], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_536], ExecError> { +) -> Result<[G; OUT_535], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -46758,12 +46712,12 @@ fn aiur_fn_536( let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = { let __values: [G; 3] = [__v_10, __v_9, __v_13]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_15: G = G::from_u64(2); - let __r_arr: [G; OUT_521] = { let __args: [G; IN_521] = []; let __cu = unconstrained; let __hit = record.function_queries[521].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[521].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[521].bump_multiplicity(__i); } let __ret: [G; OUT_521] = unsafe { *(record.function_queries[521].output_at(__i).as_ptr() as *const [G; OUT_521]) }; __ret }, _ => aiur_fn_521(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_520] = { let __args: [G; IN_520] = []; let __cu = unconstrained; let __hit = record.function_queries[520].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[520].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[520].bump_multiplicity(__i); } let __ret: [G; OUT_520] = unsafe { *(record.function_queries[520].output_at(__i).as_ptr() as *const [G; OUT_520]) }; __ret }, _ => aiur_fn_520(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(0); let __v_18: G = { let __values: [G; 4] = [__v_15, __v_16, __v_14, __v_17]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_19: G = G::from_u64(2); - let __r_arr: [G; OUT_218] = { let __args: [G; IN_218] = []; let __cu = unconstrained; let __hit = record.function_queries[218].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[218].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[218].bump_multiplicity(__i); } let __ret: [G; OUT_218] = unsafe { *(record.function_queries[218].output_at(__i).as_ptr() as *const [G; OUT_218]) }; __ret }, _ => aiur_fn_218(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_217] = { let __args: [G; IN_217] = []; let __cu = unconstrained; let __hit = record.function_queries[217].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[217].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[217].bump_multiplicity(__i); } let __ret: [G; OUT_217] = unsafe { *(record.function_queries[217].output_at(__i).as_ptr() as *const [G; OUT_217]) }; __ret }, _ => aiur_fn_217(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = G::from_u64(1); let __v_22: G = G::from_u64(1); @@ -46787,18 +46741,18 @@ fn aiur_fn_536( let __v_40: G = G::from_u64(0); let __v_41: G = { let __values: [G; 4] = [__v_36, __v_1, __v_39, __v_40]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_42: G = G::from_u64(2); - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_2, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_41, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_41, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_44, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_44, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_45, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_45, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_46: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_46]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; let __v_48: G = __r_arr[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_48]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __v_50: G = G::from_u64(1); let __v_51: G = { let __a_val = __v_49.as_canonical_u64(); let __b_val = __v_50.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -46809,16 +46763,16 @@ fn aiur_fn_536( let __v_54: G = G::from_u64(0); let __v_55: G = G::from_u64(0); let __v_56: G = { let __values: [G; 4] = [__v_53, __v_54, __v_55, __v_55]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_536] = [__v_52, __v_56]; - record.function_queries[536].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_535] = [__v_52, __v_56]; + record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_52: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_48, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_48, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __v_54: G = G::from_u64(2); - let __r_arr: [G; OUT_514] = { let __args: [G; IN_514] = []; let __cu = unconstrained; let __hit = record.function_queries[514].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[514].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[514].bump_multiplicity(__i); } let __ret: [G; OUT_514] = unsafe { *(record.function_queries[514].output_at(__i).as_ptr() as *const [G; OUT_514]) }; __ret }, _ => aiur_fn_514(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_513] = { let __args: [G; IN_513] = []; let __cu = unconstrained; let __hit = record.function_queries[513].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[513].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[513].bump_multiplicity(__i); } let __ret: [G; OUT_513] = unsafe { *(record.function_queries[513].output_at(__i).as_ptr() as *const [G; OUT_513]) }; __ret }, _ => aiur_fn_513(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __v_56: G = G::from_u64(1); let __v_57: G = G::from_u64(1); @@ -46832,28 +46786,28 @@ fn aiur_fn_536( let __v_65: G = G::from_u64(0); let __v_66: G = { let __values: [G; 4] = [__v_64, __v_63, __v_35, __v_65]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_67: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_2, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_68: G = __r_arr[0]; let __v_69: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_66, __v_68]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_66, __v_68]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_70: G = __r_arr[0]; - let __ret: [G; OUT_536] = [__v_69, __v_70]; - record.function_queries[536].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_535] = [__v_69, __v_70]; + record.function_queries[535].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_537: usize = 6; -const IN_537: usize = 6; -const OUT_537: usize = 2; -fn aiur_fn_537( - inp: [G; IN_537], +const INPUT_SIZE_536: usize = 6; +const IN_536: usize = 6; +const OUT_536: usize = 2; +fn aiur_fn_536( + inp: [G; IN_536], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_537], ExecError> { +) -> Result<[G; OUT_536], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -46863,12 +46817,12 @@ fn aiur_fn_537( let __v_5: G = inp[5]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_0.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_514] = { let __args: [G; IN_514] = []; let __cu = unconstrained; let __hit = record.function_queries[514].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[514].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[514].bump_multiplicity(__i); } let __ret: [G; OUT_514] = unsafe { *(record.function_queries[514].output_at(__i).as_ptr() as *const [G; OUT_514]) }; __ret }, _ => aiur_fn_514(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_513] = { let __args: [G; IN_513] = []; let __cu = unconstrained; let __hit = record.function_queries[513].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[513].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[513].bump_multiplicity(__i); } let __ret: [G; OUT_513] = unsafe { *(record.function_queries[513].output_at(__i).as_ptr() as *const [G; OUT_513]) }; __ret }, _ => aiur_fn_513(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; break '__mc_0 [__v_6]; }, _ => { - let __r_arr: [G; OUT_515] = { let __args: [G; IN_515] = []; let __cu = unconstrained; let __hit = record.function_queries[515].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[515].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[515].bump_multiplicity(__i); } let __ret: [G; OUT_515] = unsafe { *(record.function_queries[515].output_at(__i).as_ptr() as *const [G; OUT_515]) }; __ret }, _ => aiur_fn_515(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_514] = { let __args: [G; IN_514] = []; let __cu = unconstrained; let __hit = record.function_queries[514].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[514].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[514].bump_multiplicity(__i); } let __ret: [G; OUT_514] = unsafe { *(record.function_queries[514].output_at(__i).as_ptr() as *const [G; OUT_514]) }; __ret }, _ => aiur_fn_514(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; break '__mc_0 [__v_6]; }, @@ -46879,18 +46833,18 @@ fn aiur_fn_537( let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_7, __v_2, __v_3, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_10: G = G::from_u64(2); - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_4, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_4, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_487] = { let __args: [G; IN_487] = [__v_12, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[487].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[487].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[487].bump_multiplicity(__i); } let __ret: [G; OUT_487] = unsafe { *(record.function_queries[487].output_at(__i).as_ptr() as *const [G; OUT_487]) }; __ret }, _ => aiur_fn_487(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_486] = { let __args: [G; IN_486] = [__v_12, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[486].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[486].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[486].bump_multiplicity(__i); } let __ret: [G; OUT_486] = unsafe { *(record.function_queries[486].output_at(__i).as_ptr() as *const [G; OUT_486]) }; __ret }, _ => aiur_fn_486(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_13, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_13, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_16]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = G::from_u64(1); let __v_19: G = { let __a_val = __v_17.as_canonical_u64(); let __b_val = __v_18.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; @@ -46901,13 +46855,13 @@ fn aiur_fn_537( let __v_22: G = G::from_u64(0); let __v_23: G = G::from_u64(0); let __v_24: G = { let __values: [G; 4] = [__v_21, __v_22, __v_23, __v_23]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_537] = [__v_20, __v_24]; - record.function_queries[537].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_536] = [__v_20, __v_24]; + record.function_queries[536].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_20: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_16, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_16, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = G::from_u64(2); let __v_23: G = G::from_u64(1); @@ -46922,28 +46876,28 @@ fn aiur_fn_537( let __v_32: G = G::from_u64(0); let __v_33: G = { let __values: [G; 4] = [__v_31, __v_30, __v_1, __v_32]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_34: G = G::from_u64(2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_4, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_4, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = G::from_u64(1); - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_33, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_33, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; - let __ret: [G; OUT_537] = [__v_36, __v_37]; - record.function_queries[537].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_536] = [__v_36, __v_37]; + record.function_queries[536].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_538: usize = 2; -const IN_538: usize = 2; -const OUT_538: usize = 1; -fn aiur_fn_538( - inp: [G; IN_538], +const INPUT_SIZE_537: usize = 2; +const IN_537: usize = 2; +const OUT_537: usize = 1; +fn aiur_fn_537( + inp: [G; IN_537], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_538], ExecError> { +) -> Result<[G; OUT_537], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -46951,8 +46905,8 @@ fn aiur_fn_538( match __v_2.as_canonical_u64() { 0u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_538] = [__v_3]; - record.function_queries[538].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_537] = [__v_3]; + record.function_queries[537].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -46960,14 +46914,14 @@ fn aiur_fn_538( match __v_3.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_538] = [__v_4]; - record.function_queries[538].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_537] = [__v_4]; + record.function_queries[537].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_4: G = G::from_u64(2); - let __ret: [G; OUT_538] = [__v_4]; - record.function_queries[538].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_537] = [__v_4]; + record.function_queries[537].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -46979,33 +46933,51 @@ fn aiur_fn_538( }) } -const INPUT_SIZE_539: usize = 2; -const IN_539: usize = 2; -const OUT_539: usize = 1; -fn aiur_fn_539( - inp: [G; IN_539], +const INPUT_SIZE_538: usize = 2; +const IN_538: usize = 2; +const OUT_538: usize = 1; +fn aiur_fn_538( + inp: [G; IN_538], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_539], ExecError> { +) -> Result<[G; OUT_538], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_0.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_539] = [__v_1]; - record.function_queries[539].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_538] = [__v_1]; + record.function_queries[538].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_539] = [__v_0]; - record.function_queries[539].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_538] = [__v_0]; + record.function_queries[538].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } +const INPUT_SIZE_539: usize = 0; +const IN_539: usize = 0; +const OUT_539: usize = 2; +fn aiur_fn_539( + inp: [G; IN_539], + record: &mut QueryRecord, + io_buffer: &mut IOBuffer, + unconstrained: bool, +) -> Result<[G; OUT_539], ExecError> { + stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { + let __v_0: G = G::from_u64(0); + let __v_1: G = G::from_u64(1); + let __ret: [G; OUT_539] = [__v_0, __v_1]; + record.function_queries[539].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }) +} + const INPUT_SIZE_540: usize = 0; const IN_540: usize = 0; const OUT_540: usize = 2; @@ -47016,7 +46988,7 @@ fn aiur_fn_540( unconstrained: bool, ) -> Result<[G; OUT_540], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = G::from_u64(0); + let __v_0: G = G::from_u64(1); let __v_1: G = G::from_u64(1); let __ret: [G; OUT_540] = [__v_0, __v_1]; record.function_queries[540].finish(&inp[..], &__ret[..], !unconstrained); @@ -47034,7 +47006,7 @@ fn aiur_fn_541( unconstrained: bool, ) -> Result<[G; OUT_541], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = G::from_u64(1); + let __v_0: G = G::from_u64(2); let __v_1: G = G::from_u64(1); let __ret: [G; OUT_541] = [__v_0, __v_1]; record.function_queries[541].finish(&inp[..], &__ret[..], !unconstrained); @@ -47042,8 +47014,8 @@ fn aiur_fn_541( }) } -const INPUT_SIZE_542: usize = 0; -const IN_542: usize = 0; +const INPUT_SIZE_542: usize = 4; +const IN_542: usize = 4; const OUT_542: usize = 2; fn aiur_fn_542( inp: [G; IN_542], @@ -47051,24 +47023,6 @@ fn aiur_fn_542( io_buffer: &mut IOBuffer, unconstrained: bool, ) -> Result<[G; OUT_542], ExecError> { - stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = G::from_u64(2); - let __v_1: G = G::from_u64(1); - let __ret: [G; OUT_542] = [__v_0, __v_1]; - record.function_queries[542].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }) -} - -const INPUT_SIZE_543: usize = 4; -const IN_543: usize = 4; -const OUT_543: usize = 2; -fn aiur_fn_543( - inp: [G; IN_543], - record: &mut QueryRecord, - io_buffer: &mut IOBuffer, - unconstrained: bool, -) -> Result<[G; OUT_543], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47077,46 +47031,46 @@ fn aiur_fn_543( match __v_0.as_canonical_u64() { 1u64 => { let __v_4: G = (__v_1 * __v_3); - let __ret: [G; OUT_543] = [__v_2, __v_4]; - record.function_queries[543].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_542] = [__v_2, __v_4]; + record.function_queries[542].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_543] = [__v_0, __v_1]; - record.function_queries[543].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_542] = [__v_0, __v_1]; + record.function_queries[542].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_544: usize = 1; -const IN_544: usize = 1; -const OUT_544: usize = 2; -fn aiur_fn_544( - inp: [G; IN_544], +const INPUT_SIZE_543: usize = 1; +const IN_543: usize = 1; +const OUT_543: usize = 2; +fn aiur_fn_543( + inp: [G; IN_543], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_544], ExecError> { +) -> Result<[G; OUT_543], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(1); - let __ret: [G; OUT_544] = [__v_0, __v_1]; - record.function_queries[544].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_543] = [__v_0, __v_1]; + record.function_queries[543].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_545: usize = 2; -const IN_545: usize = 2; -const OUT_545: usize = 1; -fn aiur_fn_545( - inp: [G; IN_545], +const INPUT_SIZE_544: usize = 2; +const IN_544: usize = 2; +const OUT_544: usize = 1; +fn aiur_fn_544( + inp: [G; IN_544], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_545], ExecError> { +) -> Result<[G; OUT_544], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47186,51 +47140,51 @@ fn aiur_fn_545( let __v_63: G = __loaded[29]; let __v_64: G = __loaded[30]; let __v_65: G = __loaded[31]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_2, __v_3, __v_4, __v_5, __v_34, __v_35, __v_36, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_2, __v_3, __v_4, __v_5, __v_34, __v_35, __v_36, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_66: G = __r_arr[0]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_6, __v_7, __v_8, __v_9, __v_38, __v_39, __v_40, __v_41]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_6, __v_7, __v_8, __v_9, __v_38, __v_39, __v_40, __v_41]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_67: G = __r_arr[0]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_10, __v_11, __v_12, __v_13, __v_42, __v_43, __v_44, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_10, __v_11, __v_12, __v_13, __v_42, __v_43, __v_44, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_68: G = __r_arr[0]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_14, __v_15, __v_16, __v_17, __v_46, __v_47, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_14, __v_15, __v_16, __v_17, __v_46, __v_47, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_69: G = __r_arr[0]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_18, __v_19, __v_20, __v_21, __v_50, __v_51, __v_52, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_18, __v_19, __v_20, __v_21, __v_50, __v_51, __v_52, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_70: G = __r_arr[0]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_22, __v_23, __v_24, __v_25, __v_54, __v_55, __v_56, __v_57]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_22, __v_23, __v_24, __v_25, __v_54, __v_55, __v_56, __v_57]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_71: G = __r_arr[0]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_26, __v_27, __v_28, __v_29, __v_58, __v_59, __v_60, __v_61]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_26, __v_27, __v_28, __v_29, __v_58, __v_59, __v_60, __v_61]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_72: G = __r_arr[0]; - let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_30, __v_31, __v_32, __v_33, __v_62, __v_63, __v_64, __v_65]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_30, __v_31, __v_32, __v_33, __v_62, __v_63, __v_64, __v_65]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; let __v_73: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_72, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_72, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_74: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_71, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_71, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_75: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_70, __v_75]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_70, __v_75]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_76: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_69, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_69, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_77: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_68, __v_77]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_68, __v_77]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_78: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_67, __v_78]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_67, __v_78]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_79: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_66, __v_79]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_66, __v_79]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_80: G = __r_arr[0]; - let __ret: [G; OUT_545] = [__v_80]; - record.function_queries[545].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_544] = [__v_80]; + record.function_queries[544].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_546: usize = 8; -const IN_546: usize = 8; -const OUT_546: usize = 1; -fn aiur_fn_546( - inp: [G; IN_546], +const INPUT_SIZE_545: usize = 8; +const IN_545: usize = 8; +const OUT_545: usize = 1; +fn aiur_fn_545( + inp: [G; IN_545], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_546], ExecError> { +) -> Result<[G; OUT_545], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47258,23 +47212,23 @@ fn aiur_fn_546( let __v_23: G = (__v_22 + __v_7); let __v_24: G = (__v_20 + __v_23); let __v_25: G = (__v_18 + __v_24); - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_16, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_16, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __ret: [G; OUT_546] = [__v_26]; - record.function_queries[546].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_545] = [__v_26]; + record.function_queries[545].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_547: usize = 2; -const IN_547: usize = 2; -const OUT_547: usize = 1; -fn aiur_fn_547( - inp: [G; IN_547], +const INPUT_SIZE_546: usize = 2; +const IN_546: usize = 2; +const OUT_546: usize = 1; +fn aiur_fn_546( + inp: [G; IN_546], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_547], ExecError> { +) -> Result<[G; OUT_546], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47286,8 +47240,8 @@ fn aiur_fn_547( match __v_2.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_547] = [__v_6]; - record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_546] = [__v_6]; + record.function_queries[546].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -47297,15 +47251,15 @@ fn aiur_fn_547( 1u64 => { let __v_7: G = G::from_u64(1); let __v_8: G = (__v_7 + __v_4); - let __ret: [G; OUT_547] = [__v_8]; - record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_546] = [__v_8]; + record.function_queries[546].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_547] = { let __args: [G; IN_547] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[547].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[547].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[547].bump_multiplicity(__i); } let __ret: [G; OUT_547] = unsafe { *(record.function_queries[547].output_at(__i).as_ptr() as *const [G; OUT_547]) }; __ret }, _ => aiur_fn_547(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_547] = [__v_7]; - record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_546] = [__v_7]; + record.function_queries[546].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47317,15 +47271,15 @@ fn aiur_fn_547( }) } -const INPUT_SIZE_548: usize = 3; -const IN_548: usize = 3; -const OUT_548: usize = 2; -fn aiur_fn_548( - inp: [G; IN_548], +const INPUT_SIZE_547: usize = 3; +const IN_547: usize = 3; +const OUT_547: usize = 2; +fn aiur_fn_547( + inp: [G; IN_547], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_548], ExecError> { +) -> Result<[G; OUT_547], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47334,37 +47288,37 @@ fn aiur_fn_548( let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; - let __ret: [G; OUT_548] = [__v_4, __v_5]; - record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_547] = [__v_4, __v_5]; + record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_547] = { let __args: [G; IN_547] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[547].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[547].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[547].bump_multiplicity(__i); } let __ret: [G; OUT_547] = unsafe { *(record.function_queries[547].output_at(__i).as_ptr() as *const [G; OUT_547]) }; __ret }, _ => aiur_fn_547(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_547] = { let __args: [G; IN_547] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[547].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[547].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[547].bump_multiplicity(__i); } let __ret: [G; OUT_547] = unsafe { *(record.function_queries[547].output_at(__i).as_ptr() as *const [G; OUT_547]) }; __ret }, _ => aiur_fn_547(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_546] = { let __args: [G; IN_546] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[546].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[546].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[546].bump_multiplicity(__i); } let __ret: [G; OUT_546] = unsafe { *(record.function_queries[546].output_at(__i).as_ptr() as *const [G; OUT_546]) }; __ret }, _ => aiur_fn_546(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { match __v_5.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_545] = { let __args: [G; IN_545] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[545].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[545].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[545].bump_multiplicity(__i); } let __ret: [G; OUT_545] = unsafe { *(record.function_queries[545].output_at(__i).as_ptr() as *const [G; OUT_545]) }; __ret }, _ => aiur_fn_545(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; - let __ret: [G; OUT_548] = [__v_7, __v_8]; - record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_547] = [__v_7, __v_8]; + record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; - let __ret: [G; OUT_548] = [__v_6, __v_7]; - record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_547] = [__v_6, __v_7]; + record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47372,19 +47326,19 @@ fn aiur_fn_548( _ => { match __v_5.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; - let __ret: [G; OUT_548] = [__v_6, __v_7]; - record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_547] = [__v_6, __v_7]; + record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_548] = [__v_6, __v_7]; - record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_547] = [__v_6, __v_7]; + record.function_queries[547].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47395,15 +47349,15 @@ fn aiur_fn_548( }) } -const INPUT_SIZE_549: usize = 2; -const IN_549: usize = 2; -const OUT_549: usize = 1; -fn aiur_fn_549( - inp: [G; IN_549], +const INPUT_SIZE_548: usize = 2; +const IN_548: usize = 2; +const OUT_548: usize = 1; +fn aiur_fn_548( + inp: [G; IN_548], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_549], ExecError> { +) -> Result<[G; OUT_548], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47420,14 +47374,14 @@ fn aiur_fn_549( match __v_5.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47440,21 +47394,21 @@ fn aiur_fn_549( match __v_5.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47467,31 +47421,31 @@ fn aiur_fn_549( match __v_5.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_549] = [__v_10]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_10]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47504,37 +47458,37 @@ fn aiur_fn_549( match __v_5.as_canonical_u64() { 0u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_549] = [__v_10]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_10]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -47549,16 +47503,16 @@ fn aiur_fn_549( let __v_7: G = __loaded[2]; match __v_5.as_canonical_u64() { 4u64 => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_549] = [__v_8]; - record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_548] = [__v_8]; + record.function_queries[548].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47570,15 +47524,15 @@ fn aiur_fn_549( }) } -const INPUT_SIZE_550: usize = 2; -const IN_550: usize = 2; -const OUT_550: usize = 1; -fn aiur_fn_550( - inp: [G; IN_550], +const INPUT_SIZE_549: usize = 2; +const IN_549: usize = 2; +const OUT_549: usize = 1; +fn aiur_fn_549( + inp: [G; IN_549], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_550], ExecError> { +) -> Result<[G; OUT_549], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47595,14 +47549,14 @@ fn aiur_fn_550( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_550] = [__v_8]; - record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_549] = [__v_8]; + record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_550] = [__v_8]; - record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_549] = [__v_8]; + record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47615,19 +47569,19 @@ fn aiur_fn_550( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_550] = [__v_8]; - record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_549] = [__v_8]; + record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_550] = { let __args: [G; IN_550] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[550].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[550].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[550].bump_multiplicity(__i); } let __ret: [G; OUT_550] = unsafe { *(record.function_queries[550].output_at(__i).as_ptr() as *const [G; OUT_550]) }; __ret }, _ => aiur_fn_550(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_550] = [__v_10]; - record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_549] = [__v_10]; + record.function_queries[549].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -47642,15 +47596,15 @@ fn aiur_fn_550( }) } -const INPUT_SIZE_551: usize = 4; -const IN_551: usize = 4; -const OUT_551: usize = 1; -fn aiur_fn_551( - inp: [G; IN_551], +const INPUT_SIZE_550: usize = 4; +const IN_550: usize = 4; +const OUT_550: usize = 1; +fn aiur_fn_550( + inp: [G; IN_550], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_551], ExecError> { +) -> Result<[G; OUT_550], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47660,16 +47614,16 @@ fn aiur_fn_551( 0u64 => { match __v_2.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_552] = { let __args: [G; IN_552] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[552].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[552].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[552].bump_multiplicity(__i); } let __ret: [G; OUT_552] = unsafe { *(record.function_queries[552].output_at(__i).as_ptr() as *const [G; OUT_552]) }; __ret }, _ => aiur_fn_552(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_551] = { let __args: [G; IN_551] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[551].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[551].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[551].bump_multiplicity(__i); } let __ret: [G; OUT_551] = unsafe { *(record.function_queries[551].output_at(__i).as_ptr() as *const [G; OUT_551]) }; __ret }, _ => aiur_fn_551(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_551] = [__v_4]; - record.function_queries[551].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_550] = [__v_4]; + record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_551] = [__v_4]; - record.function_queries[551].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_550] = [__v_4]; + record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -47681,15 +47635,15 @@ fn aiur_fn_551( match __v_2.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(2); - let __ret: [G; OUT_551] = [__v_4]; - record.function_queries[551].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_550] = [__v_4]; + record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_554] = { let __args: [G; IN_554] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[554].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[554].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[554].bump_multiplicity(__i); } let __ret: [G; OUT_554] = unsafe { *(record.function_queries[554].output_at(__i).as_ptr() as *const [G; OUT_554]) }; __ret }, _ => aiur_fn_554(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_551] = [__v_4]; - record.function_queries[551].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_550] = [__v_4]; + record.function_queries[550].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -47704,15 +47658,15 @@ fn aiur_fn_551( }) } -const INPUT_SIZE_552: usize = 2; -const IN_552: usize = 2; -const OUT_552: usize = 1; -fn aiur_fn_552( - inp: [G; IN_552], +const INPUT_SIZE_551: usize = 2; +const IN_551: usize = 2; +const OUT_551: usize = 1; +fn aiur_fn_551( + inp: [G; IN_551], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_552], ExecError> { +) -> Result<[G; OUT_551], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47720,38 +47674,38 @@ fn aiur_fn_552( let __v_2: G = __r_arr[0]; let __r_arr: [G; OUT_122] = { let __args: [G; IN_122] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[122].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[122].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[122].bump_multiplicity(__i); } let __ret: [G; OUT_122] = unsafe { *(record.function_queries[122].output_at(__i).as_ptr() as *const [G; OUT_122]) }; __ret }, _ => aiur_fn_122(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_778] = { let __args: [G; IN_778] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[778].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[778].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[778].bump_multiplicity(__i); } let __ret: [G; OUT_778] = unsafe { *(record.function_queries[778].output_at(__i).as_ptr() as *const [G; OUT_778]) }; __ret }, _ => aiur_fn_778(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_778] = { let __args: [G; IN_778] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[778].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[778].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[778].bump_multiplicity(__i); } let __ret: [G; OUT_778] = unsafe { *(record.function_queries[778].output_at(__i).as_ptr() as *const [G; OUT_778]) }; __ret }, _ => aiur_fn_778(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_553] = { let __args: [G; IN_553] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[553].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[553].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[553].bump_multiplicity(__i); } let __ret: [G; OUT_553] = unsafe { *(record.function_queries[553].output_at(__i).as_ptr() as *const [G; OUT_553]) }; __ret }, _ => aiur_fn_553(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_552] = { let __args: [G; IN_552] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[552].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[552].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[552].bump_multiplicity(__i); } let __ret: [G; OUT_552] = unsafe { *(record.function_queries[552].output_at(__i).as_ptr() as *const [G; OUT_552]) }; __ret }, _ => aiur_fn_552(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_552] = [__v_7]; - record.function_queries[552].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_551] = [__v_7]; + record.function_queries[551].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_552] = [__v_6]; - record.function_queries[552].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_551] = [__v_6]; + record.function_queries[551].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_553: usize = 2; -const IN_553: usize = 2; -const OUT_553: usize = 1; -fn aiur_fn_553( - inp: [G; IN_553], +const INPUT_SIZE_552: usize = 2; +const IN_552: usize = 2; +const OUT_552: usize = 1; +fn aiur_fn_552( + inp: [G; IN_552], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_553], ExecError> { +) -> Result<[G; OUT_552], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47769,8 +47723,8 @@ fn aiur_fn_553( match __v_2.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_553] = [__v_12]; - record.function_queries[553].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_552] = [__v_12]; + record.function_queries[552].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -47787,14 +47741,14 @@ fn aiur_fn_553( let __v_21: G = __loaded[9]; match __v_12.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_553] = { let __args: [G; IN_553] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[553].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[553].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[553].bump_multiplicity(__i); } let __ret: [G; OUT_553] = unsafe { *(record.function_queries[553].output_at(__i).as_ptr() as *const [G; OUT_553]) }; __ret }, _ => aiur_fn_553(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_552] = { let __args: [G; IN_552] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[552].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[552].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[552].bump_multiplicity(__i); } let __ret: [G; OUT_552] = unsafe { *(record.function_queries[552].output_at(__i).as_ptr() as *const [G; OUT_552]) }; __ret }, _ => aiur_fn_552(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_554] = { let __args: [G; IN_554] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[554].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[554].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[554].bump_multiplicity(__i); } let __ret: [G; OUT_554] = unsafe { *(record.function_queries[554].output_at(__i).as_ptr() as *const [G; OUT_554]) }; __ret }, _ => aiur_fn_554(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_553] = { let __args: [G; IN_553] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[553].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[553].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[553].bump_multiplicity(__i); } let __ret: [G; OUT_553] = unsafe { *(record.function_queries[553].output_at(__i).as_ptr() as *const [G; OUT_553]) }; __ret }, _ => aiur_fn_553(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __ret: [G; OUT_553] = [__v_24]; - record.function_queries[553].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_552] = [__v_24]; + record.function_queries[552].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -47809,15 +47763,15 @@ fn aiur_fn_553( }) } -const INPUT_SIZE_554: usize = 16; -const IN_554: usize = 16; -const OUT_554: usize = 1; -fn aiur_fn_554( - inp: [G; IN_554], +const INPUT_SIZE_553: usize = 16; +const IN_553: usize = 16; +const OUT_553: usize = 1; +fn aiur_fn_553( + inp: [G; IN_553], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_554], ExecError> { +) -> Result<[G; OUT_553], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47835,51 +47789,51 @@ fn aiur_fn_554( let __v_13: G = inp[13]; let __v_14: G = inp[14]; let __v_15: G = inp[15]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_7, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_7, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_6, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_6, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_5, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_5, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_4, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_4, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_3, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_21, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_21, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_20, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_20, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_19, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_19, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_18, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_18, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_17, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_17, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_16, __v_29]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_16, __v_29]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __ret: [G; OUT_554] = [__v_30]; - record.function_queries[554].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_553] = [__v_30]; + record.function_queries[553].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_555: usize = 2; -const IN_555: usize = 2; -const OUT_555: usize = 1; -fn aiur_fn_555( - inp: [G; IN_555], +const INPUT_SIZE_554: usize = 2; +const IN_554: usize = 2; +const OUT_554: usize = 1; +fn aiur_fn_554( + inp: [G; IN_554], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_555], ExecError> { +) -> Result<[G; OUT_554], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47896,14 +47850,14 @@ fn aiur_fn_555( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_555] = [__v_8]; - record.function_queries[555].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_554] = [__v_8]; + record.function_queries[554].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_555] = [__v_8]; - record.function_queries[555].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_554] = [__v_8]; + record.function_queries[554].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -47916,19 +47870,19 @@ fn aiur_fn_555( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(2); - let __ret: [G; OUT_555] = [__v_8]; - record.function_queries[555].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_554] = [__v_8]; + record.function_queries[554].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_554] = { let __args: [G; IN_554] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[554].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[554].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[554].bump_multiplicity(__i); } let __ret: [G; OUT_554] = unsafe { *(record.function_queries[554].output_at(__i).as_ptr() as *const [G; OUT_554]) }; __ret }, _ => aiur_fn_554(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_555] = [__v_10]; - record.function_queries[555].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_554] = [__v_10]; + record.function_queries[554].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -47943,15 +47897,15 @@ fn aiur_fn_555( }) } -const INPUT_SIZE_556: usize = 3; -const IN_556: usize = 3; -const OUT_556: usize = 2; -fn aiur_fn_556( - inp: [G; IN_556], +const INPUT_SIZE_555: usize = 3; +const IN_555: usize = 3; +const OUT_555: usize = 2; +fn aiur_fn_555( + inp: [G; IN_555], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_556], ExecError> { +) -> Result<[G; OUT_555], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -47959,11 +47913,11 @@ fn aiur_fn_556( let __v_3: G = (__v_0 - __v_1); match __v_3.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; - let __ret: [G; OUT_556] = [__v_4, __v_5]; - record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_555] = [__v_4, __v_5]; + record.function_queries[555].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -47977,26 +47931,26 @@ fn aiur_fn_556( let __v_9: G = __loaded[1]; let __v_10: G = __loaded[2]; let __v_11: G = __loaded[3]; - let __r_arr: [G; OUT_557] = { let __args: [G; IN_557] = [__v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[557].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[557].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[557].bump_multiplicity(__i); } let __ret: [G; OUT_557] = unsafe { *(record.function_queries[557].output_at(__i).as_ptr() as *const [G; OUT_557]) }; __ret }, _ => aiur_fn_557(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; - let __ret: [G; OUT_556] = [__v_12, __v_13]; - record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_555] = [__v_12, __v_13]; + record.function_queries[555].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_557: usize = 9; -const IN_557: usize = 9; -const OUT_557: usize = 2; -fn aiur_fn_557( - inp: [G; IN_557], +const INPUT_SIZE_556: usize = 9; +const IN_556: usize = 9; +const OUT_556: usize = 2; +fn aiur_fn_556( + inp: [G; IN_556], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_557], ExecError> { +) -> Result<[G; OUT_556], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -48011,21 +47965,21 @@ fn aiur_fn_557( 0u64 => { match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_10, __v_11]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_10, __v_11]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48033,29 +47987,29 @@ fn aiur_fn_557( 1u64 => { match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_10, __v_11]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_10, __v_11]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48063,43 +48017,43 @@ fn aiur_fn_557( 2u64 => { match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_550] = { let __args: [G; IN_550] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[550].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[550].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[550].bump_multiplicity(__i); } let __ret: [G; OUT_550] = unsafe { *(record.function_queries[550].output_at(__i).as_ptr() as *const [G; OUT_550]) }; __ret }, _ => aiur_fn_550(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_549] = { let __args: [G; IN_549] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[549].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[549].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[549].bump_multiplicity(__i); } let __ret: [G; OUT_549] = unsafe { *(record.function_queries[549].output_at(__i).as_ptr() as *const [G; OUT_549]) }; __ret }, _ => aiur_fn_549(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; - let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_547] = { let __args: [G; IN_547] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[547].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[547].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[547].bump_multiplicity(__i); } let __ret: [G; OUT_547] = unsafe { *(record.function_queries[547].output_at(__i).as_ptr() as *const [G; OUT_547]) }; __ret }, _ => aiur_fn_547(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_14, __v_15]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_14, __v_15]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48107,49 +48061,49 @@ fn aiur_fn_557( 3u64 => { match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_13, __v_14]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_13, __v_14]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48157,57 +48111,57 @@ fn aiur_fn_557( 4u64 => { match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_13, __v_14]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_13, __v_14]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48215,65 +48169,65 @@ fn aiur_fn_557( 5u64 => { match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_13, __v_14]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_13, __v_14]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48281,79 +48235,79 @@ fn aiur_fn_557( 6u64 => { match __v_4.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_6, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_3, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_3, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9, __v_10, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_9, __v_10, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_17, __v_18]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_17, __v_18]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48361,29 +48315,29 @@ fn aiur_fn_557( 7u64 => { match __v_4.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __r_arr: [G; OUT_551] = { let __args: [G; IN_551] = [__v_1, __v_2, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[551].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[551].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[551].bump_multiplicity(__i); } let __ret: [G; OUT_551] = unsafe { *(record.function_queries[551].output_at(__i).as_ptr() as *const [G; OUT_551]) }; __ret }, _ => aiur_fn_551(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_550] = { let __args: [G; IN_550] = [__v_1, __v_2, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[550].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[550].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[550].bump_multiplicity(__i); } let __ret: [G; OUT_550] = unsafe { *(record.function_queries[550].output_at(__i).as_ptr() as *const [G; OUT_550]) }; __ret }, _ => aiur_fn_550(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_10, __v_11]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_10, __v_11]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48391,33 +48345,33 @@ fn aiur_fn_557( 8u64 => { match __v_4.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_548] = { let __args: [G; IN_548] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[548].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[548].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[548].bump_multiplicity(__i); } let __ret: [G; OUT_548] = unsafe { *(record.function_queries[548].output_at(__i).as_ptr() as *const [G; OUT_548]) }; __ret }, _ => aiur_fn_548(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_547] = { let __args: [G; IN_547] = [__v_1, __v_5, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[547].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[547].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[547].bump_multiplicity(__i); } let __ret: [G; OUT_547] = unsafe { *(record.function_queries[547].output_at(__i).as_ptr() as *const [G; OUT_547]) }; __ret }, _ => aiur_fn_547(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_3, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_3, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_9, __v_10, __v_16, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_9, __v_10, __v_16, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_18, __v_19]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_18, __v_19]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; - let __ret: [G; OUT_557] = [__v_9, __v_10]; - record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_556] = [__v_9, __v_10]; + record.function_queries[556].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48429,15 +48383,15 @@ fn aiur_fn_557( }) } -const INPUT_SIZE_558: usize = 7; -const IN_558: usize = 7; -const OUT_558: usize = 2; -fn aiur_fn_558( - inp: [G; IN_558], +const INPUT_SIZE_557: usize = 7; +const IN_557: usize = 7; +const OUT_557: usize = 2; +fn aiur_fn_557( + inp: [G; IN_557], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_558], ExecError> { +) -> Result<[G; OUT_557], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -48450,19 +48404,19 @@ fn aiur_fn_558( _ => { match __v_3.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; - let __ret: [G; OUT_558] = [__v_12, __v_13]; - record.function_queries[558].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_557] = [__v_12, __v_13]; + record.function_queries[557].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48471,15 +48425,15 @@ fn aiur_fn_558( }) } -const INPUT_SIZE_559: usize = 3; -const IN_559: usize = 3; -const OUT_559: usize = 2; -fn aiur_fn_559( - inp: [G; IN_559], +const INPUT_SIZE_558: usize = 3; +const IN_558: usize = 3; +const OUT_558: usize = 2; +fn aiur_fn_558( + inp: [G; IN_558], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_559], ExecError> { +) -> Result<[G; OUT_558], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -48500,19 +48454,19 @@ fn aiur_fn_559( let __v_12: G = __loaded[4]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_559] = [__v_13, __v_14]; - record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_558] = [__v_13, __v_14]; + record.function_queries[558].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_539] = { let __args: [G; IN_539] = []; let __cu = unconstrained; let __hit = record.function_queries[539].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[539].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[539].bump_multiplicity(__i); } let __ret: [G; OUT_539] = unsafe { *(record.function_queries[539].output_at(__i).as_ptr() as *const [G; OUT_539]) }; __ret }, _ => aiur_fn_539(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_559] = [__v_13, __v_14]; - record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_558] = [__v_13, __v_14]; + record.function_queries[558].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48526,25 +48480,25 @@ fn aiur_fn_559( let __v_12: G = __loaded[4]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = []; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __ret: [G; OUT_559] = [__v_13, __v_14]; - record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_558] = [__v_13, __v_14]; + record.function_queries[558].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_558] = { let __args: [G; IN_558] = [__v_4, __v_5, __v_6, __v_9, __v_10, __v_11, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[558].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[558].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[558].bump_multiplicity(__i); } let __ret: [G; OUT_558] = unsafe { *(record.function_queries[558].output_at(__i).as_ptr() as *const [G; OUT_558]) }; __ret }, _ => aiur_fn_558(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_557] = { let __args: [G; IN_557] = [__v_4, __v_5, __v_6, __v_9, __v_10, __v_11, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[557].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[557].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[557].bump_multiplicity(__i); } let __ret: [G; OUT_557] = unsafe { *(record.function_queries[557].output_at(__i).as_ptr() as *const [G; OUT_557]) }; __ret }, _ => aiur_fn_557(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = __r_arr[1]; - let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_7, __v_12, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_558] = { let __args: [G; IN_558] = [__v_7, __v_12, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[558].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[558].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[558].bump_multiplicity(__i); } let __ret: [G; OUT_558] = unsafe { *(record.function_queries[558].output_at(__i).as_ptr() as *const [G; OUT_558]) }; __ret }, _ => aiur_fn_558(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_13, __v_14, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_13, __v_14, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; - let __ret: [G; OUT_559] = [__v_17, __v_18]; - record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_558] = [__v_17, __v_18]; + record.function_queries[558].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -48559,15 +48513,15 @@ fn aiur_fn_559( }) } -const INPUT_SIZE_560: usize = 12; -const IN_560: usize = 12; -const OUT_560: usize = 1; -fn aiur_fn_560( - inp: [G; IN_560], +const INPUT_SIZE_559: usize = 12; +const IN_559: usize = 12; +const OUT_559: usize = 1; +fn aiur_fn_559( + inp: [G; IN_559], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_560], ExecError> { +) -> Result<[G; OUT_559], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -48584,50 +48538,50 @@ fn aiur_fn_560( match __v_0.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_12: G = G::from_u64(2); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_12: G = G::from_u64(3); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_12: G = G::from_u64(4); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_12: G = G::from_u64(5); - let __ret: [G; OUT_560] = [__v_12]; - record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_559] = [__v_12]; + record.function_queries[559].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -48637,15 +48591,15 @@ fn aiur_fn_560( }) } -const INPUT_SIZE_561: usize = 25; -const IN_561: usize = 25; -const OUT_561: usize = 2; -fn aiur_fn_561( - inp: [G; IN_561], +const INPUT_SIZE_560: usize = 25; +const IN_560: usize = 25; +const OUT_560: usize = 2; +fn aiur_fn_560( + inp: [G; IN_560], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_561], ExecError> { +) -> Result<[G; OUT_560], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -48672,42 +48626,42 @@ fn aiur_fn_561( let __v_22: G = inp[22]; let __v_23: G = inp[23]; let __v_24: G = inp[24]; - let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; match __v_27.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_562] = { let __args: [G; IN_562] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[562].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[562].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[562].bump_multiplicity(__i); } let __ret: [G; OUT_562] = unsafe { *(record.function_queries[562].output_at(__i).as_ptr() as *const [G; OUT_562]) }; __ret }, _ => aiur_fn_562(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_561] = { let __args: [G; IN_561] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[561].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[561].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[561].bump_multiplicity(__i); } let __ret: [G; OUT_561] = unsafe { *(record.function_queries[561].output_at(__i).as_ptr() as *const [G; OUT_561]) }; __ret }, _ => aiur_fn_561(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; - let __ret: [G; OUT_561] = [__v_28, __v_29]; - record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_560] = [__v_28, __v_29]; + record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; - let __ret: [G; OUT_561] = [__v_28, __v_29]; - record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_560] = [__v_28, __v_29]; + record.function_queries[560].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_562: usize = 25; -const IN_562: usize = 25; -const OUT_562: usize = 2; -fn aiur_fn_562( - inp: [G; IN_562], +const INPUT_SIZE_561: usize = 25; +const IN_561: usize = 25; +const OUT_561: usize = 2; +fn aiur_fn_561( + inp: [G; IN_561], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_562], ExecError> { +) -> Result<[G; OUT_561], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -48738,33 +48692,33 @@ fn aiur_fn_562( 1u64 => { match __v_12.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_3, __v_15, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_3, __v_15, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; let __v_31: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_28, __v_29, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_28, __v_29, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_26, __v_27, __v_32, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_26, __v_27, __v_32, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_34, __v_35]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_34, __v_35]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_25, __v_26]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_25, __v_26]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48772,75 +48726,75 @@ fn aiur_fn_562( 5u64 => { match __v_12.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_31]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_31]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_32, __v_33, __v_35, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_32, __v_33, __v_35, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_29, __v_30, __v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_29, __v_30, __v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; let __v_40: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_26, __v_27, __v_39, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_26, __v_27, __v_39, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; match __v_43.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = __r_arr[1]; let __v_46: G = G::from_u64(0); - let __r_arr: [G; OUT_563] = { let __args: [G; IN_563] = [__v_7, __v_8, __v_19, __v_20, __v_5, __v_24, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[563].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[563].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[563].bump_multiplicity(__i); } let __ret: [G; OUT_563] = unsafe { *(record.function_queries[563].output_at(__i).as_ptr() as *const [G; OUT_563]) }; __ret }, _ => aiur_fn_563(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_562] = { let __args: [G; IN_562] = [__v_7, __v_8, __v_19, __v_20, __v_5, __v_24, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[562].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[562].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[562].bump_multiplicity(__i); } let __ret: [G; OUT_562] = unsafe { *(record.function_queries[562].output_at(__i).as_ptr() as *const [G; OUT_562]) }; __ret }, _ => aiur_fn_562(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; let __v_48: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_44, __v_45, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_44, __v_45, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __v_50: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_41, __v_42, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_41, __v_42, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; let __v_52: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_51, __v_52]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_51, __v_52]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_41, __v_42, __v_44, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_41, __v_42, __v_44, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_46: G = __r_arr[0]; let __v_47: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_46, __v_47]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_46, __v_47]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_25, __v_26]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_25, __v_26]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -48848,98 +48802,98 @@ fn aiur_fn_562( 7u64 => { match __v_12.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_31]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_31]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_37]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_37]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_8, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_8, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_40]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_40]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; let __v_44: G = __r_arr[1]; - let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_7, __v_19, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_558] = { let __args: [G; IN_558] = [__v_7, __v_19, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[558].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[558].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[558].bump_multiplicity(__i); } let __ret: [G; OUT_558] = unsafe { *(record.function_queries[558].output_at(__i).as_ptr() as *const [G; OUT_558]) }; __ret }, _ => aiur_fn_558(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; let __v_46: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_43, __v_44, __v_45, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_43, __v_44, __v_45, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; let __v_48: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_41, __v_42, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_41, __v_42, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __v_50: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_38, __v_39, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_38, __v_39, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; let __v_52: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_35, __v_36, __v_51, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_35, __v_36, __v_51, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __v_54: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_32, __v_33, __v_53, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_32, __v_33, __v_53, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __v_56: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_29, __v_30, __v_55, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_29, __v_30, __v_55, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_57: G = __r_arr[0]; let __v_58: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_26, __v_27, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_26, __v_27, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_59: G = __r_arr[0]; let __v_60: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_59, __v_60]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_59, __v_60]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_25, __v_26]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_25, __v_26]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = __r_arr[1]; - let __ret: [G; OUT_562] = [__v_25, __v_26]; - record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_561] = [__v_25, __v_26]; + record.function_queries[561].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_563: usize = 7; -const IN_563: usize = 7; -const OUT_563: usize = 2; -fn aiur_fn_563( - inp: [G; IN_563], +const INPUT_SIZE_562: usize = 7; +const IN_562: usize = 7; +const OUT_562: usize = 2; +fn aiur_fn_562( + inp: [G; IN_562], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_563], ExecError> { +) -> Result<[G; OUT_562], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -48951,15 +48905,15 @@ fn aiur_fn_563( let __v_7: G = (__v_4 - __v_6); match __v_7.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_541] = { let __args: [G; IN_541] = []; let __cu = unconstrained; let __hit = record.function_queries[541].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[541].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[541].bump_multiplicity(__i); } let __ret: [G; OUT_541] = unsafe { *(record.function_queries[541].output_at(__i).as_ptr() as *const [G; OUT_541]) }; __ret }, _ => aiur_fn_541(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_540] = { let __args: [G; IN_540] = []; let __cu = unconstrained; let __hit = record.function_queries[540].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[540].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[540].bump_multiplicity(__i); } let __ret: [G; OUT_540] = unsafe { *(record.function_queries[540].output_at(__i).as_ptr() as *const [G; OUT_540]) }; __ret }, _ => aiur_fn_540(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_563] = [__v_8, __v_9]; - record.function_queries[563].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_562] = [__v_8, __v_9]; + record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_0, __v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_0, __v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_8.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_9: G = __loaded[0]; @@ -48974,7 +48928,7 @@ fn aiur_fn_563( let __v_18: G = __loaded[9]; let __v_19: G = __loaded[10]; let __v_20: G = __loaded[11]; - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_2, __v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_2, __v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_21.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_22: G = __loaded[0]; @@ -48989,34 +48943,34 @@ fn aiur_fn_563( let __v_31: G = __loaded[9]; let __v_32: G = __loaded[10]; let __v_33: G = __loaded[11]; - let __r_arr: [G; OUT_564] = { let __args: [G; IN_564] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[564].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[564].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[564].bump_multiplicity(__i); } let __ret: [G; OUT_564] = unsafe { *(record.function_queries[564].output_at(__i).as_ptr() as *const [G; OUT_564]) }; __ret }, _ => aiur_fn_564(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_563] = { let __args: [G; IN_563] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[563].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[563].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[563].bump_multiplicity(__i); } let __ret: [G; OUT_563] = unsafe { *(record.function_queries[563].output_at(__i).as_ptr() as *const [G; OUT_563]) }; __ret }, _ => aiur_fn_563(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = G::from_u64(1); let __v_37: G = (__v_6 + __v_36); - let __r_arr: [G; OUT_563] = { let __args: [G; IN_563] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[563].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[563].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[563].bump_multiplicity(__i); } let __ret: [G; OUT_563] = unsafe { *(record.function_queries[563].output_at(__i).as_ptr() as *const [G; OUT_563]) }; __ret }, _ => aiur_fn_563(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_562] = { let __args: [G; IN_562] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[562].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[562].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[562].bump_multiplicity(__i); } let __ret: [G; OUT_562] = unsafe { *(record.function_queries[562].output_at(__i).as_ptr() as *const [G; OUT_562]) }; __ret }, _ => aiur_fn_562(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_34, __v_35, __v_38, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_34, __v_35, __v_38, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; let __v_41: G = __r_arr[1]; - let __ret: [G; OUT_563] = [__v_40, __v_41]; - record.function_queries[563].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_562] = [__v_40, __v_41]; + record.function_queries[562].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_564: usize = 25; -const IN_564: usize = 25; -const OUT_564: usize = 2; -fn aiur_fn_564( - inp: [G; IN_564], +const INPUT_SIZE_563: usize = 25; +const IN_563: usize = 25; +const OUT_563: usize = 2; +fn aiur_fn_563( + inp: [G; IN_563], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_564], ExecError> { +) -> Result<[G; OUT_563], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49047,94 +49001,94 @@ fn aiur_fn_564( 6u64 => { match __v_12.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_1, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_25]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_6, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_31]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_31]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = __r_arr[1]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_7, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_7, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_34]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; let __v_36: G = __r_arr[1]; - let __r_arr: [G; OUT_556] = { let __args: [G; IN_556] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[556].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[556].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[556].bump_multiplicity(__i); } let __ret: [G; OUT_556] = unsafe { *(record.function_queries[556].output_at(__i).as_ptr() as *const [G; OUT_556]) }; __ret }, _ => aiur_fn_556(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_555] = { let __args: [G; IN_555] = [__v_2, __v_14, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[555].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[555].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[555].bump_multiplicity(__i); } let __ret: [G; OUT_555] = unsafe { *(record.function_queries[555].output_at(__i).as_ptr() as *const [G; OUT_555]) }; __ret }, _ => aiur_fn_555(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_35, __v_36, __v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_35, __v_36, __v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; let __v_40: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_32, __v_33, __v_39, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_32, __v_33, __v_39, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_29, __v_30, __v_41, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_29, __v_30, __v_41, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; let __v_44: G = __r_arr[1]; - let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_26, __v_27, __v_43, __v_44]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_542] = { let __args: [G; IN_542] = [__v_26, __v_27, __v_43, __v_44]; let __cu = unconstrained; let __hit = record.function_queries[542].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[542].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[542].bump_multiplicity(__i); } let __ret: [G; OUT_542] = unsafe { *(record.function_queries[542].output_at(__i).as_ptr() as *const [G; OUT_542]) }; __ret }, _ => aiur_fn_542(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; let __v_46: G = __r_arr[1]; - let __ret: [G; OUT_564] = [__v_45, __v_46]; - record.function_queries[564].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_563] = [__v_45, __v_46]; + record.function_queries[563].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; - let __ret: [G; OUT_564] = [__v_28, __v_29]; - record.function_queries[564].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_563] = [__v_28, __v_29]; + record.function_queries[563].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_559] = { let __args: [G; IN_559] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[559].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[559].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[559].bump_multiplicity(__i); } let __ret: [G; OUT_559] = unsafe { *(record.function_queries[559].output_at(__i).as_ptr() as *const [G; OUT_559]) }; __ret }, _ => aiur_fn_559(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __r_arr: [G; OUT_538] = { let __args: [G; IN_538] = [__v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[538].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[538].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[538].bump_multiplicity(__i); } let __ret: [G; OUT_538] = unsafe { *(record.function_queries[538].output_at(__i).as_ptr() as *const [G; OUT_538]) }; __ret }, _ => aiur_fn_538(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_537] = { let __args: [G; IN_537] = [__v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[537].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[537].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[537].bump_multiplicity(__i); } let __ret: [G; OUT_537] = unsafe { *(record.function_queries[537].output_at(__i).as_ptr() as *const [G; OUT_537]) }; __ret }, _ => aiur_fn_537(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_544] = { let __args: [G; IN_544] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[544].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[544].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[544].bump_multiplicity(__i); } let __ret: [G; OUT_544] = unsafe { *(record.function_queries[544].output_at(__i).as_ptr() as *const [G; OUT_544]) }; __ret }, _ => aiur_fn_544(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_543] = { let __args: [G; IN_543] = [__v_27]; let __cu = unconstrained; let __hit = record.function_queries[543].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[543].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[543].bump_multiplicity(__i); } let __ret: [G; OUT_543] = unsafe { *(record.function_queries[543].output_at(__i).as_ptr() as *const [G; OUT_543]) }; __ret }, _ => aiur_fn_543(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; - let __ret: [G; OUT_564] = [__v_28, __v_29]; - record.function_queries[564].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_563] = [__v_28, __v_29]; + record.function_queries[563].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_565: usize = 3; -const IN_565: usize = 3; -const OUT_565: usize = 1; -fn aiur_fn_565( - inp: [G; IN_565], +const INPUT_SIZE_564: usize = 3; +const IN_564: usize = 3; +const OUT_564: usize = 1; +fn aiur_fn_564( + inp: [G; IN_564], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_565], ExecError> { +) -> Result<[G; OUT_564], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = G::from_u64(4); - let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; let __v_6: G = __r_arr[2]; @@ -49143,7 +49097,7 @@ fn aiur_fn_565( let __v_9: G = __r_arr[5]; let __v_10: G = __r_arr[6]; let __v_11: G = __r_arr[7]; - let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; let __v_14: G = __r_arr[2]; @@ -49169,27 +49123,27 @@ fn aiur_fn_565( let __v_33: G = __r_arr[0]; let __r_arr: [G; OUT_22] = { let __args: [G; IN_22] = [__v_33]; let __cu = unconstrained; let __hit = record.function_queries[22].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[22].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[22].bump_multiplicity(__i); } let __ret: [G; OUT_22] = unsafe { *(record.function_queries[22].output_at(__i).as_ptr() as *const [G; OUT_22]) }; __ret }, _ => aiur_fn_22(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __ret: [G; OUT_565] = [__v_34]; - record.function_queries[565].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_564] = [__v_34]; + record.function_queries[564].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_566: usize = 2; -const IN_566: usize = 2; -const OUT_566: usize = 12; -fn aiur_fn_566( - inp: [G; IN_566], +const INPUT_SIZE_565: usize = 2; +const IN_565: usize = 2; +const OUT_565: usize = 12; +fn aiur_fn_565( + inp: [G; IN_565], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_566], ExecError> { +) -> Result<[G; OUT_565], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -49204,25 +49158,25 @@ fn aiur_fn_566( let __v_13: G = __loaded[9]; let __v_14: G = __loaded[10]; let __v_15: G = __loaded[11]; - let __ret: [G; OUT_566] = [__v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15]; - record.function_queries[566].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_565] = [__v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15]; + record.function_queries[565].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_567: usize = 2; -const IN_567: usize = 2; -const OUT_567: usize = 1; -fn aiur_fn_567( - inp: [G; IN_567], +const INPUT_SIZE_566: usize = 2; +const IN_566: usize = 2; +const OUT_566: usize = 1; +fn aiur_fn_566( + inp: [G; IN_566], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_567], ExecError> { +) -> Result<[G; OUT_566], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_566] = { let __args: [G; IN_566] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[566].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[566].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[566].bump_multiplicity(__i); } let __ret: [G; OUT_566] = unsafe { *(record.function_queries[566].output_at(__i).as_ptr() as *const [G; OUT_566]) }; __ret }, _ => aiur_fn_566(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_565] = { let __args: [G; IN_565] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[565].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[565].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[565].bump_multiplicity(__i); } let __ret: [G; OUT_565] = unsafe { *(record.function_queries[565].output_at(__i).as_ptr() as *const [G; OUT_565]) }; __ret }, _ => aiur_fn_565(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -49237,53 +49191,53 @@ fn aiur_fn_567( let __v_13: G = __r_arr[11]; match __v_2.as_canonical_u64() { 5u64 => { - let __ret: [G; OUT_567] = [__v_7]; - record.function_queries[567].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_566] = [__v_7]; + record.function_queries[566].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(0); - let __ret: [G; OUT_567] = [__v_14]; - record.function_queries[567].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_566] = [__v_14]; + record.function_queries[566].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_568: usize = 3; -const IN_568: usize = 3; -const OUT_568: usize = 1; -fn aiur_fn_568( - inp: [G; IN_568], +const INPUT_SIZE_567: usize = 3; +const IN_567: usize = 3; +const OUT_567: usize = 1; +fn aiur_fn_567( + inp: [G; IN_567], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_568], ExecError> { +) -> Result<[G; OUT_567], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = G::from_u64(0); - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_569] = { let __args: [G; IN_569] = [__v_0, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[569].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[569].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[569].bump_multiplicity(__i); } let __ret: [G; OUT_569] = unsafe { *(record.function_queries[569].output_at(__i).as_ptr() as *const [G; OUT_569]) }; __ret }, _ => aiur_fn_569(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_568] = { let __args: [G; IN_568] = [__v_0, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[568].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[568].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[568].bump_multiplicity(__i); } let __ret: [G; OUT_568] = unsafe { *(record.function_queries[568].output_at(__i).as_ptr() as *const [G; OUT_568]) }; __ret }, _ => aiur_fn_568(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_568] = [__v_5]; - record.function_queries[568].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_567] = [__v_5]; + record.function_queries[567].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_569: usize = 5; -const IN_569: usize = 5; -const OUT_569: usize = 1; -fn aiur_fn_569( - inp: [G; IN_569], +const INPUT_SIZE_568: usize = 5; +const IN_568: usize = 5; +const OUT_568: usize = 1; +fn aiur_fn_568( + inp: [G; IN_568], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_569], ExecError> { +) -> Result<[G; OUT_568], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49299,23 +49253,23 @@ fn aiur_fn_569( let __v_8: G = G::from_u64(1); let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 4] = [__v_8, __v_9, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_569] = [__v_10]; - record.function_queries[569].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_568] = [__v_10]; + record.function_queries[568].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_570] = { let __args: [G; IN_570] = [__v_6, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[570].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[570].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[570].bump_multiplicity(__i); } let __ret: [G; OUT_570] = unsafe { *(record.function_queries[570].output_at(__i).as_ptr() as *const [G; OUT_570]) }; __ret }, _ => aiur_fn_570(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_569] = { let __args: [G; IN_569] = [__v_6, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[569].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[569].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[569].bump_multiplicity(__i); } let __ret: [G; OUT_569] = unsafe { *(record.function_queries[569].output_at(__i).as_ptr() as *const [G; OUT_569]) }; __ret }, _ => aiur_fn_569(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = G::from_u64(1); let __v_11: G = (__v_3 + __v_10); let __v_12: G = (__v_4 + __v_9); - let __r_arr: [G; OUT_569] = { let __args: [G; IN_569] = [__v_7, __v_1, __v_2, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[569].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[569].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[569].bump_multiplicity(__i); } let __ret: [G; OUT_569] = unsafe { *(record.function_queries[569].output_at(__i).as_ptr() as *const [G; OUT_569]) }; __ret }, _ => aiur_fn_569(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_568] = { let __args: [G; IN_568] = [__v_7, __v_1, __v_2, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[568].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[568].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[568].bump_multiplicity(__i); } let __ret: [G; OUT_568] = unsafe { *(record.function_queries[568].output_at(__i).as_ptr() as *const [G; OUT_568]) }; __ret }, _ => aiur_fn_568(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_770] = { let __args: [G; IN_770] = [__v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[770].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[770].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[770].bump_multiplicity(__i); } let __ret: [G; OUT_770] = unsafe { *(record.function_queries[770].output_at(__i).as_ptr() as *const [G; OUT_770]) }; __ret }, _ => aiur_fn_770(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_769] = { let __args: [G; IN_769] = [__v_8, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[769].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[769].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[769].bump_multiplicity(__i); } let __ret: [G; OUT_769] = unsafe { *(record.function_queries[769].output_at(__i).as_ptr() as *const [G; OUT_769]) }; __ret }, _ => aiur_fn_769(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_569] = [__v_14]; - record.function_queries[569].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_568] = [__v_14]; + record.function_queries[568].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -49325,15 +49279,15 @@ fn aiur_fn_569( }) } -const INPUT_SIZE_570: usize = 5; -const IN_570: usize = 5; -const OUT_570: usize = 2; -fn aiur_fn_570( - inp: [G; IN_570], +const INPUT_SIZE_569: usize = 5; +const IN_569: usize = 5; +const OUT_569: usize = 2; +fn aiur_fn_569( + inp: [G; IN_569], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_570], ExecError> { +) -> Result<[G; OUT_569], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49350,35 +49304,35 @@ fn aiur_fn_570( let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 4] = [__v_8, __v_9, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_570] = [__v_10, __v_11]; - record.function_queries[570].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_569] = [__v_10, __v_11]; + record.function_queries[569].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_570] = { let __args: [G; IN_570] = [__v_7, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[570].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[570].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[570].bump_multiplicity(__i); } let __ret: [G; OUT_570] = unsafe { *(record.function_queries[570].output_at(__i).as_ptr() as *const [G; OUT_570]) }; __ret }, _ => aiur_fn_570(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_569] = { let __args: [G; IN_569] = [__v_7, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[569].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[569].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[569].bump_multiplicity(__i); } let __ret: [G; OUT_569] = unsafe { *(record.function_queries[569].output_at(__i).as_ptr() as *const [G; OUT_569]) }; __ret }, _ => aiur_fn_569(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __r_arr: [G; OUT_567] = { let __args: [G; IN_567] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[567].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[567].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[567].bump_multiplicity(__i); } let __ret: [G; OUT_567] = unsafe { *(record.function_queries[567].output_at(__i).as_ptr() as *const [G; OUT_567]) }; __ret }, _ => aiur_fn_567(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_566] = { let __args: [G; IN_566] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[566].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[566].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[566].bump_multiplicity(__i); } let __ret: [G; OUT_566] = unsafe { *(record.function_queries[566].output_at(__i).as_ptr() as *const [G; OUT_566]) }; __ret }, _ => aiur_fn_566(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_571] = { let __args: [G; IN_571] = [__v_2, __v_6, __v_10, __v_4, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[571].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[571].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[571].bump_multiplicity(__i); } let __ret: [G; OUT_571] = unsafe { *(record.function_queries[571].output_at(__i).as_ptr() as *const [G; OUT_571]) }; __ret }, _ => aiur_fn_571(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_570] = { let __args: [G; IN_570] = [__v_2, __v_6, __v_10, __v_4, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[570].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[570].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[570].bump_multiplicity(__i); } let __ret: [G; OUT_570] = unsafe { *(record.function_queries[570].output_at(__i).as_ptr() as *const [G; OUT_570]) }; __ret }, _ => aiur_fn_570(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_1, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __r_arr: [G; OUT_770] = { let __args: [G; IN_770] = [__v_12, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[770].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[770].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[770].bump_multiplicity(__i); } let __ret: [G; OUT_770] = unsafe { *(record.function_queries[770].output_at(__i).as_ptr() as *const [G; OUT_770]) }; __ret }, _ => aiur_fn_770(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_769] = { let __args: [G; IN_769] = [__v_12, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[769].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[769].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[769].bump_multiplicity(__i); } let __ret: [G; OUT_769] = unsafe { *(record.function_queries[769].output_at(__i).as_ptr() as *const [G; OUT_769]) }; __ret }, _ => aiur_fn_769(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = { let __values: [G; 4] = [__v_13, __v_14, __v_3, __v_15]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = { let __a_val = __v_9.as_canonical_u64(); let __b_val = __v_10.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_17.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_570] = [__v_16, __v_10]; - record.function_queries[570].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_569] = [__v_16, __v_10]; + record.function_queries[569].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_570] = [__v_16, __v_9]; - record.function_queries[570].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_569] = [__v_16, __v_9]; + record.function_queries[569].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -49390,15 +49344,15 @@ fn aiur_fn_570( }) } -const INPUT_SIZE_571: usize = 5; -const IN_571: usize = 5; -const OUT_571: usize = 1; -fn aiur_fn_571( - inp: [G; IN_571], +const INPUT_SIZE_570: usize = 5; +const IN_570: usize = 5; +const OUT_570: usize = 1; +fn aiur_fn_570( + inp: [G; IN_570], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_571], ExecError> { +) -> Result<[G; OUT_570], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49411,37 +49365,37 @@ fn aiur_fn_571( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 4] = [__v_6, __v_7, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_571] = [__v_8]; - record.function_queries[571].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_570] = [__v_8]; + record.function_queries[570].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_565] = { let __args: [G; IN_565] = [__v_0, __v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[565].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[565].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[565].bump_multiplicity(__i); } let __ret: [G; OUT_565] = unsafe { *(record.function_queries[565].output_at(__i).as_ptr() as *const [G; OUT_565]) }; __ret }, _ => aiur_fn_565(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_564] = { let __args: [G; IN_564] = [__v_0, __v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[564].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[564].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[564].bump_multiplicity(__i); } let __ret: [G; OUT_564] = unsafe { *(record.function_queries[564].output_at(__i).as_ptr() as *const [G; OUT_564]) }; __ret }, _ => aiur_fn_564(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = (__v_3 + __v_4); let __v_9: G = G::from_u64(1); let __v_10: G = (__v_4 + __v_9); - let __r_arr: [G; OUT_571] = { let __args: [G; IN_571] = [__v_0, __v_1, __v_2, __v_3, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[571].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[571].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[571].bump_multiplicity(__i); } let __ret: [G; OUT_571] = unsafe { *(record.function_queries[571].output_at(__i).as_ptr() as *const [G; OUT_571]) }; __ret }, _ => aiur_fn_571(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_570] = { let __args: [G; IN_570] = [__v_0, __v_1, __v_2, __v_3, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[570].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[570].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[570].bump_multiplicity(__i); } let __ret: [G; OUT_570] = unsafe { *(record.function_queries[570].output_at(__i).as_ptr() as *const [G; OUT_570]) }; __ret }, _ => aiur_fn_570(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = { let __values: [G; 4] = [__v_6, __v_7, __v_8, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_571] = [__v_12]; - record.function_queries[571].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_570] = [__v_12]; + record.function_queries[570].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_572: usize = 3; -const IN_572: usize = 3; -const OUT_572: usize = 1; -fn aiur_fn_572( - inp: [G; IN_572], +const INPUT_SIZE_571: usize = 3; +const IN_571: usize = 3; +const OUT_571: usize = 1; +fn aiur_fn_571( + inp: [G; IN_571], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_572], ExecError> { +) -> Result<[G; OUT_571], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49452,26 +49406,26 @@ fn aiur_fn_572( let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_7: G = { let __values: [G; 3] = [__v_3, __v_0, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_8: G = G::from_u64(1); - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = (__v_8 + __v_9); - let __r_arr: [G; OUT_573] = { let __args: [G; IN_573] = [__v_7, __v_1, __v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[573].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[573].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[573].bump_multiplicity(__i); } let __ret: [G; OUT_573] = unsafe { *(record.function_queries[573].output_at(__i).as_ptr() as *const [G; OUT_573]) }; __ret }, _ => aiur_fn_573(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_572] = { let __args: [G; IN_572] = [__v_7, __v_1, __v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[572].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[572].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[572].bump_multiplicity(__i); } let __ret: [G; OUT_572] = unsafe { *(record.function_queries[572].output_at(__i).as_ptr() as *const [G; OUT_572]) }; __ret }, _ => aiur_fn_572(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_572] = [__v_11]; - record.function_queries[572].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_571] = [__v_11]; + record.function_queries[571].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_573: usize = 4; -const IN_573: usize = 4; -const OUT_573: usize = 1; -fn aiur_fn_573( - inp: [G; IN_573], +const INPUT_SIZE_572: usize = 4; +const IN_572: usize = 4; +const OUT_572: usize = 1; +fn aiur_fn_572( + inp: [G; IN_572], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_573], ExecError> { +) -> Result<[G; OUT_572], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49479,33 +49433,33 @@ fn aiur_fn_573( let __v_3: G = inp[3]; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_573] = [__v_0]; - record.function_queries[573].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_572] = [__v_0]; + record.function_queries[572].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_4: G = G::from_u64(0); - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_569] = { let __args: [G; IN_569] = [__v_0, __v_1, __v_2, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[569].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[569].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[569].bump_multiplicity(__i); } let __ret: [G; OUT_569] = unsafe { *(record.function_queries[569].output_at(__i).as_ptr() as *const [G; OUT_569]) }; __ret }, _ => aiur_fn_569(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_568] = { let __args: [G; IN_568] = [__v_0, __v_1, __v_2, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[568].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[568].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[568].bump_multiplicity(__i); } let __ret: [G; OUT_568] = unsafe { *(record.function_queries[568].output_at(__i).as_ptr() as *const [G; OUT_568]) }; __ret }, _ => aiur_fn_568(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_574] = { let __args: [G; IN_574] = [__v_0, __v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[574].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[574].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[574].bump_multiplicity(__i); } let __ret: [G; OUT_574] = unsafe { *(record.function_queries[574].output_at(__i).as_ptr() as *const [G; OUT_574]) }; __ret }, _ => aiur_fn_574(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_573] = { let __args: [G; IN_573] = [__v_0, __v_6, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[573].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[573].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[573].bump_multiplicity(__i); } let __ret: [G; OUT_573] = unsafe { *(record.function_queries[573].output_at(__i).as_ptr() as *const [G; OUT_573]) }; __ret }, _ => aiur_fn_573(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_580] = { let __args: [G; IN_580] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[580].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[580].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[580].bump_multiplicity(__i); } let __ret: [G; OUT_580] = unsafe { *(record.function_queries[580].output_at(__i).as_ptr() as *const [G; OUT_580]) }; __ret }, _ => aiur_fn_580(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_579] = { let __args: [G; IN_579] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[579].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[579].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[579].bump_multiplicity(__i); } let __ret: [G; OUT_579] = unsafe { *(record.function_queries[579].output_at(__i).as_ptr() as *const [G; OUT_579]) }; __ret }, _ => aiur_fn_579(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_573] = [__v_0]; - record.function_queries[573].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_572] = [__v_0]; + record.function_queries[572].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(1); let __v_10: G = (__v_3 - __v_9); - let __r_arr: [G; OUT_573] = { let __args: [G; IN_573] = [__v_7, __v_1, __v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[573].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[573].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[573].bump_multiplicity(__i); } let __ret: [G; OUT_573] = unsafe { *(record.function_queries[573].output_at(__i).as_ptr() as *const [G; OUT_573]) }; __ret }, _ => aiur_fn_573(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_572] = { let __args: [G; IN_572] = [__v_7, __v_1, __v_2, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[572].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[572].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[572].bump_multiplicity(__i); } let __ret: [G; OUT_572] = unsafe { *(record.function_queries[572].output_at(__i).as_ptr() as *const [G; OUT_572]) }; __ret }, _ => aiur_fn_572(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_573] = [__v_11]; - record.function_queries[573].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_572] = [__v_11]; + record.function_queries[572].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -49514,15 +49468,15 @@ fn aiur_fn_573( }) } -const INPUT_SIZE_574: usize = 3; -const IN_574: usize = 3; -const OUT_574: usize = 1; -fn aiur_fn_574( - inp: [G; IN_574], +const INPUT_SIZE_573: usize = 3; +const IN_573: usize = 3; +const OUT_573: usize = 1; +fn aiur_fn_573( + inp: [G; IN_573], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_574], ExecError> { +) -> Result<[G; OUT_573], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49536,19 +49490,19 @@ fn aiur_fn_574( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_574] = [__v_8]; - record.function_queries[574].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_573] = [__v_8]; + record.function_queries[573].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_575] = { let __args: [G; IN_575] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[575].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[575].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[575].bump_multiplicity(__i); } let __ret: [G; OUT_575] = unsafe { *(record.function_queries[575].output_at(__i).as_ptr() as *const [G; OUT_575]) }; __ret }, _ => aiur_fn_575(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_574] = { let __args: [G; IN_574] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[574].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[574].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[574].bump_multiplicity(__i); } let __ret: [G; OUT_574] = unsafe { *(record.function_queries[574].output_at(__i).as_ptr() as *const [G; OUT_574]) }; __ret }, _ => aiur_fn_574(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_574] = { let __args: [G; IN_574] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[574].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[574].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[574].bump_multiplicity(__i); } let __ret: [G; OUT_574] = unsafe { *(record.function_queries[574].output_at(__i).as_ptr() as *const [G; OUT_574]) }; __ret }, _ => aiur_fn_574(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_573] = { let __args: [G; IN_573] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[573].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[573].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[573].bump_multiplicity(__i); } let __ret: [G; OUT_573] = unsafe { *(record.function_queries[573].output_at(__i).as_ptr() as *const [G; OUT_573]) }; __ret }, _ => aiur_fn_573(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_574] = [__v_8]; - record.function_queries[574].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_573] = [__v_8]; + record.function_queries[573].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -49558,28 +49512,28 @@ fn aiur_fn_574( }) } -const INPUT_SIZE_575: usize = 3; -const IN_575: usize = 3; -const OUT_575: usize = 1; -fn aiur_fn_575( - inp: [G; IN_575], +const INPUT_SIZE_574: usize = 3; +const IN_574: usize = 3; +const OUT_574: usize = 1; +fn aiur_fn_574( + inp: [G; IN_574], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_575], ExecError> { +) -> Result<[G; OUT_574], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_3.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(1); let __v_5: G = G::from_u64(1); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_575] = [__v_6]; - record.function_queries[575].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_574] = [__v_6]; + record.function_queries[574].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -49588,32 +49542,32 @@ fn aiur_fn_575( let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_8: G = { let __values: [G; 3] = [__v_4, __v_0, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_575] = [__v_8]; - record.function_queries[575].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_574] = [__v_8]; + record.function_queries[574].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_576] = { let __args: [G; IN_576] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[576].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[576].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[576].bump_multiplicity(__i); } let __ret: [G; OUT_576] = unsafe { *(record.function_queries[576].output_at(__i).as_ptr() as *const [G; OUT_576]) }; __ret }, _ => aiur_fn_576(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_575] = { let __args: [G; IN_575] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[575].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[575].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[575].bump_multiplicity(__i); } let __ret: [G; OUT_575] = unsafe { *(record.function_queries[575].output_at(__i).as_ptr() as *const [G; OUT_575]) }; __ret }, _ => aiur_fn_575(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_578] = { let __args: [G; IN_578] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[578].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[578].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[578].bump_multiplicity(__i); } let __ret: [G; OUT_578] = unsafe { *(record.function_queries[578].output_at(__i).as_ptr() as *const [G; OUT_578]) }; __ret }, _ => aiur_fn_578(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_577] = { let __args: [G; IN_577] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[577].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[577].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[577].bump_multiplicity(__i); } let __ret: [G; OUT_577] = unsafe { *(record.function_queries[577].output_at(__i).as_ptr() as *const [G; OUT_577]) }; __ret }, _ => aiur_fn_577(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_575] = [__v_5]; - record.function_queries[575].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_574] = [__v_5]; + record.function_queries[574].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_576: usize = 3; -const IN_576: usize = 3; -const OUT_576: usize = 1; -fn aiur_fn_576( - inp: [G; IN_576], +const INPUT_SIZE_575: usize = 3; +const IN_575: usize = 3; +const OUT_575: usize = 1; +fn aiur_fn_575( + inp: [G; IN_575], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_576], ExecError> { +) -> Result<[G; OUT_575], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49627,17 +49581,17 @@ fn aiur_fn_576( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_576] = [__v_8]; - record.function_queries[576].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_575] = [__v_8]; + record.function_queries[575].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_576] = { let __args: [G; IN_576] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[576].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[576].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[576].bump_multiplicity(__i); } let __ret: [G; OUT_576] = unsafe { *(record.function_queries[576].output_at(__i).as_ptr() as *const [G; OUT_576]) }; __ret }, _ => aiur_fn_576(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_575] = { let __args: [G; IN_575] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[575].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[575].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[575].bump_multiplicity(__i); } let __ret: [G; OUT_575] = unsafe { *(record.function_queries[575].output_at(__i).as_ptr() as *const [G; OUT_575]) }; __ret }, _ => aiur_fn_575(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_577] = { let __args: [G; IN_577] = [__v_4, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[577].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[577].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[577].bump_multiplicity(__i); } let __ret: [G; OUT_577] = unsafe { *(record.function_queries[577].output_at(__i).as_ptr() as *const [G; OUT_577]) }; __ret }, _ => aiur_fn_577(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_576] = { let __args: [G; IN_576] = [__v_4, __v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[576].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[576].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[576].bump_multiplicity(__i); } let __ret: [G; OUT_576] = unsafe { *(record.function_queries[576].output_at(__i).as_ptr() as *const [G; OUT_576]) }; __ret }, _ => aiur_fn_576(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_576] = [__v_7]; - record.function_queries[576].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_575] = [__v_7]; + record.function_queries[575].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -49647,15 +49601,15 @@ fn aiur_fn_576( }) } -const INPUT_SIZE_577: usize = 4; -const IN_577: usize = 4; -const OUT_577: usize = 1; -fn aiur_fn_577( - inp: [G; IN_577], +const INPUT_SIZE_576: usize = 4; +const IN_576: usize = 4; +const OUT_576: usize = 1; +fn aiur_fn_576( + inp: [G; IN_576], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_577], ExecError> { +) -> Result<[G; OUT_576], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49672,12 +49626,12 @@ fn aiur_fn_577( let __v_9: G = G::from_u64(1); let __v_10: G = { let __values: [G; 3] = [__v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = { let __values: [G; 3] = [__v_7, __v_0, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_577] = [__v_11]; - record.function_queries[577].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_576] = [__v_11]; + record.function_queries[576].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_566] = { let __args: [G; IN_566] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[566].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[566].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[566].bump_multiplicity(__i); } let __ret: [G; OUT_566] = unsafe { *(record.function_queries[566].output_at(__i).as_ptr() as *const [G; OUT_566]) }; __ret }, _ => aiur_fn_566(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_565] = { let __args: [G; IN_565] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[565].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[565].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[565].bump_multiplicity(__i); } let __ret: [G; OUT_565] = unsafe { *(record.function_queries[565].output_at(__i).as_ptr() as *const [G; OUT_565]) }; __ret }, _ => aiur_fn_565(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; let __v_9: G = __r_arr[2]; @@ -49690,7 +49644,7 @@ fn aiur_fn_577( let __v_16: G = __r_arr[9]; let __v_17: G = __r_arr[10]; let __v_18: G = __r_arr[11]; - let __r_arr: [G; OUT_566] = { let __args: [G; IN_566] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[566].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[566].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[566].bump_multiplicity(__i); } let __ret: [G; OUT_566] = unsafe { *(record.function_queries[566].output_at(__i).as_ptr() as *const [G; OUT_566]) }; __ret }, _ => aiur_fn_566(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_565] = { let __args: [G; IN_565] = [__v_3, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[565].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[565].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[565].bump_multiplicity(__i); } let __ret: [G; OUT_565] = unsafe { *(record.function_queries[565].output_at(__i).as_ptr() as *const [G; OUT_565]) }; __ret }, _ => aiur_fn_565(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; let __v_21: G = __r_arr[2]; @@ -49703,24 +49657,24 @@ fn aiur_fn_577( let __v_28: G = __r_arr[9]; let __v_29: G = __r_arr[10]; let __v_30: G = __r_arr[11]; - let __r_arr: [G; OUT_561] = { let __args: [G; IN_561] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[561].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[561].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[561].bump_multiplicity(__i); } let __ret: [G; OUT_561] = unsafe { *(record.function_queries[561].output_at(__i).as_ptr() as *const [G; OUT_561]) }; __ret }, _ => aiur_fn_561(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; match __v_31.as_canonical_u64() { 0u64 => { let __v_33: G = G::from_u64(0); let __v_34: G = { let __values: [G; 3] = [__v_33, __v_0, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_577] = [__v_34]; - record.function_queries[577].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_576] = [__v_34]; + record.function_queries[576].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_33: G = G::from_u64(0); - let __r_arr: [G; OUT_577] = { let __args: [G; IN_577] = [__v_0, __v_6, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[577].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[577].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[577].bump_multiplicity(__i); } let __ret: [G; OUT_577] = unsafe { *(record.function_queries[577].output_at(__i).as_ptr() as *const [G; OUT_577]) }; __ret }, _ => aiur_fn_577(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_576] = { let __args: [G; IN_576] = [__v_0, __v_6, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[576].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[576].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[576].bump_multiplicity(__i); } let __ret: [G; OUT_576] = unsafe { *(record.function_queries[576].output_at(__i).as_ptr() as *const [G; OUT_576]) }; __ret }, _ => aiur_fn_576(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = { let __values: [G; 3] = [__v_33, __v_5, __v_34]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_577] = [__v_35]; - record.function_queries[577].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_576] = [__v_35]; + record.function_queries[576].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -49732,15 +49686,15 @@ fn aiur_fn_577( }) } -const INPUT_SIZE_578: usize = 3; -const IN_578: usize = 3; -const OUT_578: usize = 1; -fn aiur_fn_578( - inp: [G; IN_578], +const INPUT_SIZE_577: usize = 3; +const IN_577: usize = 3; +const OUT_577: usize = 1; +fn aiur_fn_577( + inp: [G; IN_577], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_578], ExecError> { +) -> Result<[G; OUT_577], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49754,8 +49708,8 @@ fn aiur_fn_578( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_578] = [__v_8]; - record.function_queries[578].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_577] = [__v_8]; + record.function_queries[577].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -49764,10 +49718,10 @@ fn aiur_fn_578( let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_10: G = { let __values: [G; 3] = [__v_6, __v_4, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_579] = { let __args: [G; IN_579] = [__v_5, __v_1, __v_2, __v_4, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[579].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[579].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[579].bump_multiplicity(__i); } let __ret: [G; OUT_579] = unsafe { *(record.function_queries[579].output_at(__i).as_ptr() as *const [G; OUT_579]) }; __ret }, _ => aiur_fn_579(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_578] = { let __args: [G; IN_578] = [__v_5, __v_1, __v_2, __v_4, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[578].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[578].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[578].bump_multiplicity(__i); } let __ret: [G; OUT_578] = unsafe { *(record.function_queries[578].output_at(__i).as_ptr() as *const [G; OUT_578]) }; __ret }, _ => aiur_fn_578(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_578] = [__v_11]; - record.function_queries[578].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_577] = [__v_11]; + record.function_queries[577].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -49777,15 +49731,15 @@ fn aiur_fn_578( }) } -const INPUT_SIZE_579: usize = 5; -const IN_579: usize = 5; -const OUT_579: usize = 1; -fn aiur_fn_579( - inp: [G; IN_579], +const INPUT_SIZE_578: usize = 5; +const IN_578: usize = 5; +const OUT_578: usize = 1; +fn aiur_fn_578( + inp: [G; IN_578], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_579], ExecError> { +) -> Result<[G; OUT_578], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49803,12 +49757,12 @@ fn aiur_fn_579( let __v_10: G = G::from_u64(1); let __v_11: G = { let __values: [G; 3] = [__v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_12: G = { let __values: [G; 3] = [__v_8, __v_4, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_579] = [__v_12]; - record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_578] = [__v_12]; + record.function_queries[578].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_566] = { let __args: [G; IN_566] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[566].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[566].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[566].bump_multiplicity(__i); } let __ret: [G; OUT_566] = unsafe { *(record.function_queries[566].output_at(__i).as_ptr() as *const [G; OUT_566]) }; __ret }, _ => aiur_fn_566(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_565] = { let __args: [G; IN_565] = [__v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[565].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[565].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[565].bump_multiplicity(__i); } let __ret: [G; OUT_565] = unsafe { *(record.function_queries[565].output_at(__i).as_ptr() as *const [G; OUT_565]) }; __ret }, _ => aiur_fn_565(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = __r_arr[2]; @@ -49821,7 +49775,7 @@ fn aiur_fn_579( let __v_17: G = __r_arr[9]; let __v_18: G = __r_arr[10]; let __v_19: G = __r_arr[11]; - let __r_arr: [G; OUT_566] = { let __args: [G; IN_566] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[566].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[566].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[566].bump_multiplicity(__i); } let __ret: [G; OUT_566] = unsafe { *(record.function_queries[566].output_at(__i).as_ptr() as *const [G; OUT_566]) }; __ret }, _ => aiur_fn_566(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_565] = { let __args: [G; IN_565] = [__v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[565].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[565].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[565].bump_multiplicity(__i); } let __ret: [G; OUT_565] = unsafe { *(record.function_queries[565].output_at(__i).as_ptr() as *const [G; OUT_565]) }; __ret }, _ => aiur_fn_565(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = __r_arr[1]; let __v_22: G = __r_arr[2]; @@ -49834,17 +49788,17 @@ fn aiur_fn_579( let __v_29: G = __r_arr[9]; let __v_30: G = __r_arr[10]; let __v_31: G = __r_arr[11]; - let __r_arr: [G; OUT_561] = { let __args: [G; IN_561] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[561].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[561].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[561].bump_multiplicity(__i); } let __ret: [G; OUT_561] = unsafe { *(record.function_queries[561].output_at(__i).as_ptr() as *const [G; OUT_561]) }; __ret }, _ => aiur_fn_561(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_560] = { let __args: [G; IN_560] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[560].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[560].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[560].bump_multiplicity(__i); } let __ret: [G; OUT_560] = unsafe { *(record.function_queries[560].output_at(__i).as_ptr() as *const [G; OUT_560]) }; __ret }, _ => aiur_fn_560(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = __r_arr[1]; match __v_32.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_768] = { let __args: [G; IN_768] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[768].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[768].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[768].bump_multiplicity(__i); } let __ret: [G; OUT_768] = unsafe { *(record.function_queries[768].output_at(__i).as_ptr() as *const [G; OUT_768]) }; __ret }, _ => aiur_fn_768(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __r_arr: [G; OUT_579] = { let __args: [G; IN_579] = [__v_7, __v_1, __v_2, __v_6, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[579].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[579].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[579].bump_multiplicity(__i); } let __ret: [G; OUT_579] = unsafe { *(record.function_queries[579].output_at(__i).as_ptr() as *const [G; OUT_579]) }; __ret }, _ => aiur_fn_579(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_578] = { let __args: [G; IN_578] = [__v_7, __v_1, __v_2, __v_6, __v_34]; let __cu = unconstrained; let __hit = record.function_queries[578].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[578].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[578].bump_multiplicity(__i); } let __ret: [G; OUT_578] = unsafe { *(record.function_queries[578].output_at(__i).as_ptr() as *const [G; OUT_578]) }; __ret }, _ => aiur_fn_578(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; - let __ret: [G; OUT_579] = [__v_35]; - record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_578] = [__v_35]; + record.function_queries[578].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -49854,11 +49808,11 @@ fn aiur_fn_579( let __v_37: G = G::from_u64(1); let __v_38: G = { let __values: [G; 3] = [__v_36, __v_37, __v_37]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_39: G = { let __values: [G; 3] = [__v_35, __v_6, __v_38]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_579] = { let __args: [G; IN_579] = [__v_7, __v_1, __v_2, __v_6, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[579].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[579].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[579].bump_multiplicity(__i); } let __ret: [G; OUT_579] = unsafe { *(record.function_queries[579].output_at(__i).as_ptr() as *const [G; OUT_579]) }; __ret }, _ => aiur_fn_579(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_578] = { let __args: [G; IN_578] = [__v_7, __v_1, __v_2, __v_6, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[578].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[578].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[578].bump_multiplicity(__i); } let __ret: [G; OUT_578] = unsafe { *(record.function_queries[578].output_at(__i).as_ptr() as *const [G; OUT_578]) }; __ret }, _ => aiur_fn_578(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; let __v_41: G = { let __values: [G; 3] = [__v_34, __v_4, __v_40]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_579] = [__v_41]; - record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_578] = [__v_41]; + record.function_queries[578].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -49870,15 +49824,15 @@ fn aiur_fn_579( }) } -const INPUT_SIZE_580: usize = 2; -const IN_580: usize = 2; -const OUT_580: usize = 1; -fn aiur_fn_580( - inp: [G; IN_580], +const INPUT_SIZE_579: usize = 2; +const IN_579: usize = 2; +const OUT_579: usize = 1; +fn aiur_fn_579( + inp: [G; IN_579], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_580], ExecError> { +) -> Result<[G; OUT_579], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -49895,14 +49849,14 @@ fn aiur_fn_580( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_580] = [__v_8]; - record.function_queries[580].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_579] = [__v_8]; + record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_580] = [__v_8]; - record.function_queries[580].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_579] = [__v_8]; + record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -49915,25 +49869,25 @@ fn aiur_fn_580( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_580] = [__v_8]; - record.function_queries[580].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_579] = [__v_8]; + record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 0u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_580] = [__v_9]; - record.function_queries[580].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_579] = [__v_9]; + record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_580] = { let __args: [G; IN_580] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[580].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[580].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[580].bump_multiplicity(__i); } let __ret: [G; OUT_580] = unsafe { *(record.function_queries[580].output_at(__i).as_ptr() as *const [G; OUT_580]) }; __ret }, _ => aiur_fn_580(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_579] = { let __args: [G; IN_579] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[579].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[579].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[579].bump_multiplicity(__i); } let __ret: [G; OUT_579] = unsafe { *(record.function_queries[579].output_at(__i).as_ptr() as *const [G; OUT_579]) }; __ret }, _ => aiur_fn_579(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_580] = [__v_9]; - record.function_queries[580].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_579] = [__v_9]; + record.function_queries[579].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -49950,15 +49904,15 @@ fn aiur_fn_580( }) } -const INPUT_SIZE_581: usize = 1; -const IN_581: usize = 1; -const OUT_581: usize = 1; -fn aiur_fn_581( - inp: [G; IN_581], +const INPUT_SIZE_580: usize = 1; +const IN_580: usize = 1; +const OUT_580: usize = 1; +fn aiur_fn_580( + inp: [G; IN_580], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_581], ExecError> { +) -> Result<[G; OUT_580], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -49970,17 +49924,17 @@ fn aiur_fn_581( let __v_4: G = G::from_u64(1); let __v_5: G = G::from_u64(1); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_581] = [__v_6]; - record.function_queries[581].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_580] = [__v_6]; + record.function_queries[580].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_581] = { let __args: [G; IN_581] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[581].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[581].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[581].bump_multiplicity(__i); } let __ret: [G; OUT_581] = unsafe { *(record.function_queries[581].output_at(__i).as_ptr() as *const [G; OUT_581]) }; __ret }, _ => aiur_fn_581(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_580] = { let __args: [G; IN_580] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[580].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[580].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[580].bump_multiplicity(__i); } let __ret: [G; OUT_580] = unsafe { *(record.function_queries[580].output_at(__i).as_ptr() as *const [G; OUT_580]) }; __ret }, _ => aiur_fn_580(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_581] = [__v_5]; - record.function_queries[581].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_580] = [__v_5]; + record.function_queries[580].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -49990,15 +49944,15 @@ fn aiur_fn_581( }) } -const INPUT_SIZE_582: usize = 1; -const IN_582: usize = 1; -const OUT_582: usize = 1; -fn aiur_fn_582( - inp: [G; IN_582], +const INPUT_SIZE_581: usize = 1; +const IN_581: usize = 1; +const OUT_581: usize = 1; +fn aiur_fn_581( + inp: [G; IN_581], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_582], ExecError> { +) -> Result<[G; OUT_581], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -50008,25 +49962,25 @@ fn aiur_fn_582( match __v_1.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_582] = [__v_4]; - record.function_queries[582].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_581] = [__v_4]; + record.function_queries[581].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_582] = { let __args: [G; IN_582] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[582].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[582].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[582].bump_multiplicity(__i); } let __ret: [G; OUT_582] = unsafe { *(record.function_queries[582].output_at(__i).as_ptr() as *const [G; OUT_582]) }; __ret }, _ => aiur_fn_582(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_581] = { let __args: [G; IN_581] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[581].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[581].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[581].bump_multiplicity(__i); } let __ret: [G; OUT_581] = unsafe { *(record.function_queries[581].output_at(__i).as_ptr() as *const [G; OUT_581]) }; __ret }, _ => aiur_fn_581(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_582] = [__v_5]; - record.function_queries[582].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_581] = [__v_5]; + record.function_queries[581].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_582] = [__v_5]; - record.function_queries[582].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_581] = [__v_5]; + record.function_queries[581].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -50038,15 +49992,15 @@ fn aiur_fn_582( }) } -const INPUT_SIZE_583: usize = 2; -const IN_583: usize = 2; -const OUT_583: usize = 1; -fn aiur_fn_583( - inp: [G; IN_583], +const INPUT_SIZE_582: usize = 2; +const IN_582: usize = 2; +const OUT_582: usize = 1; +fn aiur_fn_582( + inp: [G; IN_582], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_583], ExecError> { +) -> Result<[G; OUT_582], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -50103,26 +50057,26 @@ fn aiur_fn_583( let __v_49: G = G::from_u64(1); let __v_50: G = G::from_u64(1); let __v_51: G = { let __values: [G; 3] = [__v_49, __v_50, __v_50]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_583] = [__v_51]; - record.function_queries[583].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_582] = [__v_51]; + record.function_queries[582].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_49: G = G::from_u64(1); let __v_50: G = (__v_1 + __v_49); - let __r_arr: [G; OUT_583] = { let __args: [G; IN_583] = [__v_48, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[583].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[583].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[583].bump_multiplicity(__i); } let __ret: [G; OUT_583] = unsafe { *(record.function_queries[583].output_at(__i).as_ptr() as *const [G; OUT_583]) }; __ret }, _ => aiur_fn_583(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_582] = { let __args: [G; IN_582] = [__v_48, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[582].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[582].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[582].bump_multiplicity(__i); } let __ret: [G; OUT_582] = unsafe { *(record.function_queries[582].output_at(__i).as_ptr() as *const [G; OUT_582]) }; __ret }, _ => aiur_fn_582(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; match __v_3.as_canonical_u64() { 1u64 => { let __v_52: G = G::from_u64(0); let __v_53: G = { let __values: [G; 3] = [__v_52, __v_1, __v_51]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_583] = [__v_53]; - record.function_queries[583].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_582] = [__v_53]; + record.function_queries[582].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_583] = [__v_51]; - record.function_queries[583].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_582] = [__v_51]; + record.function_queries[582].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -50134,15 +50088,15 @@ fn aiur_fn_583( }) } -const INPUT_SIZE_584: usize = 2; -const IN_584: usize = 2; -const OUT_584: usize = 1; -fn aiur_fn_584( - inp: [G; IN_584], +const INPUT_SIZE_583: usize = 2; +const IN_583: usize = 2; +const OUT_583: usize = 1; +fn aiur_fn_583( + inp: [G; IN_583], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_584], ExecError> { +) -> Result<[G; OUT_583], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -50197,8 +50151,8 @@ fn aiur_fn_584( match __v_2.as_canonical_u64() { 1u64 => { let __v_49: G = G::from_u64(0); - let __ret: [G; OUT_584] = [__v_49]; - record.function_queries[584].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_583] = [__v_49]; + record.function_queries[583].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -50224,15 +50178,15 @@ fn aiur_fn_584( match __v_49.as_canonical_u64() { 1u64 => { let __v_50: G = G::from_u64(1); - let __ret: [G; OUT_584] = [__v_50]; - record.function_queries[584].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_583] = [__v_50]; + record.function_queries[583].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_584] = { let __args: [G; IN_584] = [__v_48, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[584].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[584].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[584].bump_multiplicity(__i); } let __ret: [G; OUT_584] = unsafe { *(record.function_queries[584].output_at(__i).as_ptr() as *const [G; OUT_584]) }; __ret }, _ => aiur_fn_584(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_583] = { let __args: [G; IN_583] = [__v_48, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[583].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[583].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[583].bump_multiplicity(__i); } let __ret: [G; OUT_583] = unsafe { *(record.function_queries[583].output_at(__i).as_ptr() as *const [G; OUT_583]) }; __ret }, _ => aiur_fn_583(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_584] = [__v_50]; - record.function_queries[584].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_583] = [__v_50]; + record.function_queries[583].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -50244,18 +50198,18 @@ fn aiur_fn_584( }) } -const INPUT_SIZE_585: usize = 1; -const IN_585: usize = 1; -const OUT_585: usize = 0; -fn aiur_fn_585( - inp: [G; IN_585], +const INPUT_SIZE_584: usize = 1; +const IN_584: usize = 1; +const OUT_584: usize = 0; +fn aiur_fn_584( + inp: [G; IN_584], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_585], ExecError> { +) -> Result<[G; OUT_584], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = __r_arr[1]; let __v_3: G = __r_arr[2]; @@ -50309,10 +50263,10 @@ fn aiur_fn_585( match __v_1.as_canonical_u64() { 8u64 => { let __v_49: G = G::from_u64(1); - let __r_arr: [G; OUT_584] = { let __args: [G; IN_584] = [__v_2, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[584].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[584].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[584].bump_multiplicity(__i); } let __ret: [G; OUT_584] = unsafe { *(record.function_queries[584].output_at(__i).as_ptr() as *const [G; OUT_584]) }; __ret }, _ => aiur_fn_584(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_583] = { let __args: [G; IN_583] = [__v_2, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[583].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[583].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[583].bump_multiplicity(__i); } let __ret: [G; OUT_583] = unsafe { *(record.function_queries[583].output_at(__i).as_ptr() as *const [G; OUT_583]) }; __ret }, _ => aiur_fn_583(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __v_51: G = G::from_u64(0); - let __r_arr: [G; OUT_584] = { let __args: [G; IN_584] = [__v_2, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[584].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[584].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[584].bump_multiplicity(__i); } let __ret: [G; OUT_584] = unsafe { *(record.function_queries[584].output_at(__i).as_ptr() as *const [G; OUT_584]) }; __ret }, _ => aiur_fn_584(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_583] = { let __args: [G; IN_583] = [__v_2, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[583].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[583].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[583].bump_multiplicity(__i); } let __ret: [G; OUT_583] = unsafe { *(record.function_queries[583].output_at(__i).as_ptr() as *const [G; OUT_583]) }; __ret }, _ => aiur_fn_583(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = (__v_50 * __v_52); let __v_54: G = G::from_u64(0); @@ -50320,20 +50274,20 @@ fn aiur_fn_585( return Err(ExecError::AssertEqMismatch { lhs: __v_53.as_canonical_u64(), rhs: __v_54.as_canonical_u64(), msg: Some("mutual block mixes a definition member with inductives".to_string()) }); } let __v_55: G = G::from_u64(0); - let __r_arr: [G; OUT_583] = { let __args: [G; IN_583] = [__v_2, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[583].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[583].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[583].bump_multiplicity(__i); } let __ret: [G; OUT_583] = unsafe { *(record.function_queries[583].output_at(__i).as_ptr() as *const [G; OUT_583]) }; __ret }, _ => aiur_fn_583(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_582] = { let __args: [G; IN_582] = [__v_2, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[582].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[582].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[582].bump_multiplicity(__i); } let __ret: [G; OUT_582] = unsafe { *(record.function_queries[582].output_at(__i).as_ptr() as *const [G; OUT_582]) }; __ret }, _ => aiur_fn_582(__args, record, io_buffer, __cu)? } }; let __v_56: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_56]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_56]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_57: G = __r_arr[0]; let __v_58: G = G::from_u64(2); let __v_59: G = { let __a_val = __v_57.as_canonical_u64(); let __b_val = __v_58.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_59.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_585] = []; - record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_584] = []; + record.function_queries[584].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_295] = { let __args: [G; IN_295] = [__v_2, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[295].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[295].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[295].bump_multiplicity(__i); } let __ret: [G; OUT_295] = unsafe { *(record.function_queries[295].output_at(__i).as_ptr() as *const [G; OUT_295]) }; __ret }, _ => aiur_fn_295(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_2, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; let __v_60: G = __r_arr[0]; let __v_61: G = G::from_u64(0); let __v_62: G = G::from_u64(1); @@ -50341,34 +50295,34 @@ fn aiur_fn_585( let __v_64: G = { let __values: [G; 3] = [__v_62, __v_63, __v_63]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_65: G = { let __values: [G; 3] = [__v_61, __v_56, __v_64]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_66: G = G::from_u64(1); - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_56]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_56]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_67: G = __r_arr[0]; let __v_68: G = (__v_66 + __v_67); - let __r_arr: [G; OUT_573] = { let __args: [G; IN_573] = [__v_65, __v_60, __v_0, __v_68]; let __cu = unconstrained; let __hit = record.function_queries[573].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[573].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[573].bump_multiplicity(__i); } let __ret: [G; OUT_573] = unsafe { *(record.function_queries[573].output_at(__i).as_ptr() as *const [G; OUT_573]) }; __ret }, _ => aiur_fn_573(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_572] = { let __args: [G; IN_572] = [__v_65, __v_60, __v_0, __v_68]; let __cu = unconstrained; let __hit = record.function_queries[572].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[572].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[572].bump_multiplicity(__i); } let __ret: [G; OUT_572] = unsafe { *(record.function_queries[572].output_at(__i).as_ptr() as *const [G; OUT_572]) }; __ret }, _ => aiur_fn_572(__args, record, io_buffer, __cu)? } }; let __v_69: G = __r_arr[0]; - let __r_arr: [G; OUT_582] = { let __args: [G; IN_582] = [__v_69]; let __cu = unconstrained; let __hit = record.function_queries[582].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[582].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[582].bump_multiplicity(__i); } let __ret: [G; OUT_582] = unsafe { *(record.function_queries[582].output_at(__i).as_ptr() as *const [G; OUT_582]) }; __ret }, _ => aiur_fn_582(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_581] = { let __args: [G; IN_581] = [__v_69]; let __cu = unconstrained; let __hit = record.function_queries[581].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[581].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[581].bump_multiplicity(__i); } let __ret: [G; OUT_581] = unsafe { *(record.function_queries[581].output_at(__i).as_ptr() as *const [G; OUT_581]) }; __ret }, _ => aiur_fn_581(__args, record, io_buffer, __cu)? } }; let __v_70: G = __r_arr[0]; let __v_71: G = G::from_u64(1); if (__v_70 != __v_71) { return Err(ExecError::AssertEqMismatch { lhs: __v_70.as_canonical_u64(), rhs: __v_71.as_canonical_u64(), msg: Some("canonical block: refinement left members tied, order ambiguous".to_string()) }); } - let __r_arr: [G; OUT_581] = { let __args: [G; IN_581] = [__v_69]; let __cu = unconstrained; let __hit = record.function_queries[581].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[581].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[581].bump_multiplicity(__i); } let __ret: [G; OUT_581] = unsafe { *(record.function_queries[581].output_at(__i).as_ptr() as *const [G; OUT_581]) }; __ret }, _ => aiur_fn_581(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_580] = { let __args: [G; IN_580] = [__v_69]; let __cu = unconstrained; let __hit = record.function_queries[580].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[580].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[580].bump_multiplicity(__i); } let __ret: [G; OUT_580] = unsafe { *(record.function_queries[580].output_at(__i).as_ptr() as *const [G; OUT_580]) }; __ret }, _ => aiur_fn_580(__args, record, io_buffer, __cu)? } }; let __v_72: G = __r_arr[0]; - let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_72, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_338] = { let __args: [G; IN_338] = [__v_72, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[338].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[338].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[338].bump_multiplicity(__i); } let __ret: [G; OUT_338] = unsafe { *(record.function_queries[338].output_at(__i).as_ptr() as *const [G; OUT_338]) }; __ret }, _ => aiur_fn_338(__args, record, io_buffer, __cu)? } }; let __v_73: G = __r_arr[0]; let __v_74: G = G::from_u64(1); if (__v_73 != __v_74) { return Err(ExecError::AssertEqMismatch { lhs: __v_73.as_canonical_u64(), rhs: __v_74.as_canonical_u64(), msg: Some("canonical block: members are not in canonical order".to_string()) }); } - let __ret: [G; OUT_585] = []; - record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_584] = []; + record.function_queries[584].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_585] = []; - record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_584] = []; + record.function_queries[584].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -50377,15 +50331,15 @@ fn aiur_fn_585( }) } -const INPUT_SIZE_586: usize = 12; -const IN_586: usize = 12; -const OUT_586: usize = 1; -fn aiur_fn_586( - inp: [G; IN_586], +const INPUT_SIZE_585: usize = 12; +const IN_585: usize = 12; +const OUT_585: usize = 1; +fn aiur_fn_585( + inp: [G; IN_585], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_586], ExecError> { +) -> Result<[G; OUT_585], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -50401,56 +50355,56 @@ fn aiur_fn_586( let __v_11: G = inp[11]; match __v_0.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_586] = [__v_3]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_3]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { match __v_4.as_canonical_u64() { 1u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_586] = [__v_12]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_12]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_586] = [__v_12]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_12]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 2u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_586] = [__v_12]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_12]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __ret: [G; OUT_586] = [__v_4]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_4]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_586] = [__v_12]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_12]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __ret: [G; OUT_586] = [__v_6]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_6]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __ret: [G; OUT_586] = [__v_8]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_8]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __ret: [G; OUT_586] = [__v_9]; - record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_585] = [__v_9]; + record.function_queries[585].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -50460,15 +50414,15 @@ fn aiur_fn_586( }) } -const INPUT_SIZE_587: usize = 1; -const IN_587: usize = 1; -const OUT_587: usize = 1; -fn aiur_fn_587( - inp: [G; IN_587], +const INPUT_SIZE_586: usize = 1; +const IN_586: usize = 1; +const OUT_586: usize = 1; +fn aiur_fn_586( + inp: [G; IN_586], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_587], ExecError> { +) -> Result<[G; OUT_586], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; @@ -50479,18 +50433,18 @@ fn aiur_fn_587( match __v_1.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_587] = [__v_5]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_5]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_587] = [__v_5]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_5]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -50506,67 +50460,67 @@ fn aiur_fn_587( let __v_16: G = __loaded[10]; let __v_17: G = __loaded[11]; let __v_18: G = G::from_u64(1); - let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_585] = { let __args: [G; IN_585] = [__v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[585].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[585].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[585].bump_multiplicity(__i); } let __ret: [G; OUT_585] = unsafe { *(record.function_queries[585].output_at(__i).as_ptr() as *const [G; OUT_585]) }; __ret }, _ => aiur_fn_585(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = (__v_18 - __v_19); - let __ret: [G; OUT_587] = [__v_20]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_20]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_5 * __v_6); - let __ret: [G; OUT_587] = [__v_7]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_7]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_5 * __v_6); - let __ret: [G; OUT_587] = [__v_7]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_7]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = (__v_5 * __v_6); - let __ret: [G; OUT_587] = [__v_7]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_7]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = (__v_6 * __v_7); let __v_9: G = (__v_5 * __v_8); - let __ret: [G; OUT_587] = [__v_9]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_9]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_587] = [__v_5]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_5]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_587] = [__v_5]; - record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_586] = [__v_5]; + record.function_queries[586].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -50576,48 +50530,48 @@ fn aiur_fn_587( }) } -const INPUT_SIZE_588: usize = 2; -const IN_588: usize = 2; -const OUT_588: usize = 0; -fn aiur_fn_588( - inp: [G; IN_588], +const INPUT_SIZE_587: usize = 2; +const IN_587: usize = 2; +const OUT_587: usize = 0; +fn aiur_fn_587( + inp: [G; IN_587], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_588], ExecError> { +) -> Result<[G; OUT_587], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_0.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_588] = []; - record.function_queries[588].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_587] = []; + record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = G::from_u64(1); if (__v_2 != __v_3) { return Err(ExecError::AssertEqMismatch { lhs: __v_2.as_canonical_u64(), rhs: __v_3.as_canonical_u64(), msg: Some("safe constant references an unsafe constant".to_string()) }); } - let __ret: [G; OUT_588] = []; - record.function_queries[588].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_587] = []; + record.function_queries[587].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_589: usize = 2; -const IN_589: usize = 2; -const OUT_589: usize = 0; -fn aiur_fn_589( - inp: [G; IN_589], +const INPUT_SIZE_588: usize = 2; +const IN_588: usize = 2; +const OUT_588: usize = 0; +fn aiur_fn_588( + inp: [G; IN_588], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_589], ExecError> { +) -> Result<[G; OUT_588], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -50627,28 +50581,28 @@ fn aiur_fn_589( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_589] = []; - record.function_queries[589].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_588] = []; + record.function_queries[588].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_589] = []; - record.function_queries[589].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_588] = []; + record.function_queries[588].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_589] = []; - record.function_queries[589].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_588] = []; + record.function_queries[588].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_589] = []; - record.function_queries[589].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_588] = []; + record.function_queries[588].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { @@ -50657,8 +50611,8 @@ fn aiur_fn_589( if (__v_5 != __v_6) { return Err(ExecError::AssertEqMismatch { lhs: __v_5.as_canonical_u64(), rhs: __v_6.as_canonical_u64(), msg: Some("universe param index out of range".to_string()) }); } - let __ret: [G; OUT_589] = []; - record.function_queries[589].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_588] = []; + record.function_queries[588].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -50668,15 +50622,15 @@ fn aiur_fn_589( }) } -const INPUT_SIZE_590: usize = 2; -const IN_590: usize = 2; -const OUT_590: usize = 0; -fn aiur_fn_590( - inp: [G; IN_590], +const INPUT_SIZE_589: usize = 2; +const IN_589: usize = 2; +const OUT_589: usize = 0; +fn aiur_fn_589( + inp: [G; IN_589], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_590], ExecError> { +) -> Result<[G; OUT_589], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -50686,15 +50640,15 @@ fn aiur_fn_590( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_590] = []; - record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_589] = []; + record.function_queries[589].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_590] = []; - record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_589] = []; + record.function_queries[589].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -50704,15 +50658,15 @@ fn aiur_fn_590( }) } -const INPUT_SIZE_591: usize = 3; -const IN_591: usize = 3; -const OUT_591: usize = 0; -fn aiur_fn_591( - inp: [G; IN_591], +const INPUT_SIZE_590: usize = 3; +const IN_590: usize = 3; +const OUT_590: usize = 0; +fn aiur_fn_590( + inp: [G; IN_590], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_591], ExecError> { +) -> Result<[G; OUT_590], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -50729,18 +50683,18 @@ fn aiur_fn_591( if (__v_7 != __v_8) { return Err(ExecError::AssertEqMismatch { lhs: __v_7.as_canonical_u64(), rhs: __v_8.as_canonical_u64(), msg: Some("loose bound variable: BVar index exceeds binder depth".to_string()) }); } - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -50755,62 +50709,62 @@ fn aiur_fn_591( let __v_17: G = __loaded[9]; let __v_18: G = __loaded[10]; let __v_19: G = __loaded[11]; - let __r_arr: [G; OUT_430] = { let __args: [G; IN_430] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[430].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[430].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[430].bump_multiplicity(__i); } let __ret: [G; OUT_430] = unsafe { *(record.function_queries[430].output_at(__i).as_ptr() as *const [G; OUT_430]) }; __ret }, _ => aiur_fn_430(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_429] = { let __args: [G; IN_429] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[429].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[429].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[429].bump_multiplicity(__i); } let __ret: [G; OUT_429] = unsafe { *(record.function_queries[429].output_at(__i).as_ptr() as *const [G; OUT_429]) }; __ret }, _ => aiur_fn_429(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; if (__v_21 != __v_20) { return Err(ExecError::AssertEqMismatch { lhs: __v_21.as_canonical_u64(), rhs: __v_20.as_canonical_u64(), msg: Some("Const applied to wrong number of universe levels".to_string()) }); } - let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_589] = { let __args: [G; IN_589] = [__v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[589].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[589].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[589].bump_multiplicity(__i); } let __ret: [G; OUT_589] = unsafe { *(record.function_queries[589].output_at(__i).as_ptr() as *const [G; OUT_589]) }; __ret }, _ => aiur_fn_589(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 + __v_7); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 + __v_7); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 + __v_7); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_6, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_6, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_591] = []; - record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_6, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_590] = []; + record.function_queries[590].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -50820,15 +50774,15 @@ fn aiur_fn_591( }) } -const INPUT_SIZE_592: usize = 0; -const IN_592: usize = 0; -const OUT_592: usize = 1; -fn aiur_fn_592( - inp: [G; IN_592], +const INPUT_SIZE_591: usize = 0; +const IN_591: usize = 0; +const OUT_591: usize = 1; +fn aiur_fn_591( + inp: [G; IN_591], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_592], ExecError> { +) -> Result<[G; OUT_591], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(231); let __v_1: G = G::from_u64(117); @@ -50863,21 +50817,21 @@ fn aiur_fn_592( let __v_30: G = G::from_u64(27); let __v_31: G = G::from_u64(75); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_592] = [__v_32]; - record.function_queries[592].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_591] = [__v_32]; + record.function_queries[591].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_593: usize = 0; -const IN_593: usize = 0; -const OUT_593: usize = 1; -fn aiur_fn_593( - inp: [G; IN_593], +const INPUT_SIZE_592: usize = 0; +const IN_592: usize = 0; +const OUT_592: usize = 1; +fn aiur_fn_592( + inp: [G; IN_592], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_593], ExecError> { +) -> Result<[G; OUT_592], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = G::from_u64(178); let __v_1: G = G::from_u64(14); @@ -50912,21 +50866,21 @@ fn aiur_fn_593( let __v_30: G = G::from_u64(149); let __v_31: G = G::from_u64(149); let __v_32: G = { let __values: [G; 32] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_593] = [__v_32]; - record.function_queries[593].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_592] = [__v_32]; + record.function_queries[592].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_594: usize = 3; -const IN_594: usize = 3; -const OUT_594: usize = 1; -fn aiur_fn_594( - inp: [G; IN_594], +const INPUT_SIZE_593: usize = 3; +const IN_593: usize = 3; +const OUT_593: usize = 1; +fn aiur_fn_593( + inp: [G; IN_593], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_594], ExecError> { +) -> Result<[G; OUT_593], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -50935,8 +50889,8 @@ fn aiur_fn_594( match __v_3.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_594] = [__v_4]; - record.function_queries[594].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_593] = [__v_4]; + record.function_queries[593].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -50949,16 +50903,16 @@ fn aiur_fn_594( 5u64 => { let __v_8: G = G::from_u64(1); let __v_9: G = (__v_2 + __v_8); - let __r_arr: [G; OUT_594] = { let __args: [G; IN_594] = [__v_6, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[594].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[594].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[594].bump_multiplicity(__i); } let __ret: [G; OUT_594] = unsafe { *(record.function_queries[594].output_at(__i).as_ptr() as *const [G; OUT_594]) }; __ret }, _ => aiur_fn_594(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_593] = { let __args: [G; IN_593] = [__v_6, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[593].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[593].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[593].bump_multiplicity(__i); } let __ret: [G; OUT_593] = unsafe { *(record.function_queries[593].output_at(__i).as_ptr() as *const [G; OUT_593]) }; __ret }, _ => aiur_fn_593(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_594] = [__v_10]; - record.function_queries[594].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_593] = [__v_10]; + record.function_queries[593].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_594] = [__v_8]; - record.function_queries[594].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_593] = [__v_8]; + record.function_queries[593].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -50967,19 +50921,19 @@ fn aiur_fn_594( }) } -const INPUT_SIZE_595: usize = 0; -const IN_595: usize = 0; -const OUT_595: usize = 0; -fn aiur_fn_595( - inp: [G; IN_595], +const INPUT_SIZE_594: usize = 0; +const IN_594: usize = 0; +const OUT_594: usize = 0; +fn aiur_fn_594( + inp: [G; IN_594], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_595], ExecError> { +) -> Result<[G; OUT_594], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __r_arr: [G; OUT_593] = { let __args: [G; IN_593] = []; let __cu = unconstrained; let __hit = record.function_queries[593].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[593].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[593].bump_multiplicity(__i); } let __ret: [G; OUT_593] = unsafe { *(record.function_queries[593].output_at(__i).as_ptr() as *const [G; OUT_593]) }; __ret }, _ => aiur_fn_593(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_592] = { let __args: [G; IN_592] = []; let __cu = unconstrained; let __hit = record.function_queries[592].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[592].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[592].bump_multiplicity(__i); } let __ret: [G; OUT_592] = unsafe { *(record.function_queries[592].output_at(__i).as_ptr() as *const [G; OUT_592]) }; __ret }, _ => aiur_fn_592(__args, record, io_buffer, __cu)? } }; let __v_0: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_1.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_2: G = __loaded[0]; @@ -51008,8 +50962,8 @@ fn aiur_fn_595( if (__v_7 != __v_16) { return Err(ExecError::AssertEqMismatch { lhs: __v_7.as_canonical_u64(), rhs: __v_16.as_canonical_u64(), msg: Some("Eq inductive: wrong constructor count".to_string()) }); } - let __ret: [G; OUT_595] = []; - record.function_queries[595].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_594] = []; + record.function_queries[594].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51019,15 +50973,15 @@ fn aiur_fn_595( }) } -const INPUT_SIZE_596: usize = 4; -const IN_596: usize = 4; -const OUT_596: usize = 0; -fn aiur_fn_596( - inp: [G; IN_596], +const INPUT_SIZE_595: usize = 4; +const IN_595: usize = 4; +const OUT_595: usize = 0; +fn aiur_fn_595( + inp: [G; IN_595], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_596], ExecError> { +) -> Result<[G; OUT_595], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51035,7 +50989,7 @@ fn aiur_fn_596( let __v_3: G = inp[3]; let __mc_out___mc_0: [G; 2] = '__mc_0: { match __v_1.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_592] = { let __args: [G; IN_592] = []; let __cu = unconstrained; let __hit = record.function_queries[592].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[592].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[592].bump_multiplicity(__i); } let __ret: [G; OUT_592] = unsafe { *(record.function_queries[592].output_at(__i).as_ptr() as *const [G; OUT_592]) }; __ret }, _ => aiur_fn_592(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = []; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; @@ -51048,7 +51002,7 @@ fn aiur_fn_596( break '__mc_0 [__v_7, __v_8]; }, 1u64 => { - let __r_arr: [G; OUT_382] = { let __args: [G; IN_382] = []; let __cu = unconstrained; let __hit = record.function_queries[382].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[382].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[382].bump_multiplicity(__i); } let __ret: [G; OUT_382] = unsafe { *(record.function_queries[382].output_at(__i).as_ptr() as *const [G; OUT_382]) }; __ret }, _ => aiur_fn_382(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_381] = { let __args: [G; IN_381] = []; let __cu = unconstrained; let __hit = record.function_queries[381].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[381].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[381].bump_multiplicity(__i); } let __ret: [G; OUT_381] = unsafe { *(record.function_queries[381].output_at(__i).as_ptr() as *const [G; OUT_381]) }; __ret }, _ => aiur_fn_381(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; @@ -51061,7 +51015,7 @@ fn aiur_fn_596( break '__mc_0 [__v_7, __v_8]; }, 2u64 => { - let __r_arr: [G; OUT_383] = { let __args: [G; IN_383] = []; let __cu = unconstrained; let __hit = record.function_queries[383].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[383].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[383].bump_multiplicity(__i); } let __ret: [G; OUT_383] = unsafe { *(record.function_queries[383].output_at(__i).as_ptr() as *const [G; OUT_383]) }; __ret }, _ => aiur_fn_383(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_382] = { let __args: [G; IN_382] = []; let __cu = unconstrained; let __hit = record.function_queries[382].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[382].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[382].bump_multiplicity(__i); } let __ret: [G; OUT_382] = unsafe { *(record.function_queries[382].output_at(__i).as_ptr() as *const [G; OUT_382]) }; __ret }, _ => aiur_fn_382(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; @@ -51069,13 +51023,13 @@ fn aiur_fn_596( if (__v_5 != __v_6) { return Err(ExecError::AssertEqMismatch { lhs: __v_5.as_canonical_u64(), rhs: __v_6.as_canonical_u64(), msg: Some("Quot.lift declared at a non-canonical address".to_string()) }); } - let __r_arr: [G; OUT_595] = { let __args: [G; IN_595] = []; let __cu = unconstrained; let __hit = record.function_queries[595].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[595].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[595].bump_multiplicity(__i); } let __ret: [G; OUT_595] = unsafe { *(record.function_queries[595].output_at(__i).as_ptr() as *const [G; OUT_595]) }; __ret }, _ => aiur_fn_595(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_594] = { let __args: [G; IN_594] = []; let __cu = unconstrained; let __hit = record.function_queries[594].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[594].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[594].bump_multiplicity(__i); } let __ret: [G; OUT_594] = unsafe { *(record.function_queries[594].output_at(__i).as_ptr() as *const [G; OUT_594]) }; __ret }, _ => aiur_fn_594(__args, record, io_buffer, __cu)? } }; let __v_7: G = G::from_u64(2); let __v_8: G = G::from_u64(6); break '__mc_0 [__v_7, __v_8]; }, 3u64 => { - let __r_arr: [G; OUT_384] = { let __args: [G; IN_384] = []; let __cu = unconstrained; let __hit = record.function_queries[384].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[384].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[384].bump_multiplicity(__i); } let __ret: [G; OUT_384] = unsafe { *(record.function_queries[384].output_at(__i).as_ptr() as *const [G; OUT_384]) }; __ret }, _ => aiur_fn_384(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_383] = { let __args: [G; IN_383] = []; let __cu = unconstrained; let __hit = record.function_queries[383].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[383].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[383].bump_multiplicity(__i); } let __ret: [G; OUT_383] = unsafe { *(record.function_queries[383].output_at(__i).as_ptr() as *const [G; OUT_383]) }; __ret }, _ => aiur_fn_383(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; @@ -51098,34 +51052,34 @@ fn aiur_fn_596( return Err(ExecError::AssertEqMismatch { lhs: __v_2.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Quot constant: wrong universe param count for its kind".to_string()) }); } let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_594] = { let __args: [G; IN_594] = [__v_3, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[594].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[594].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[594].bump_multiplicity(__i); } let __ret: [G; OUT_594] = unsafe { *(record.function_queries[594].output_at(__i).as_ptr() as *const [G; OUT_594]) }; __ret }, _ => aiur_fn_594(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_593] = { let __args: [G; IN_593] = [__v_3, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[593].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[593].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[593].bump_multiplicity(__i); } let __ret: [G; OUT_593] = unsafe { *(record.function_queries[593].output_at(__i).as_ptr() as *const [G; OUT_593]) }; __ret }, _ => aiur_fn_593(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); if (__v_7 != __v_8) { return Err(ExecError::AssertEqMismatch { lhs: __v_7.as_canonical_u64(), rhs: __v_8.as_canonical_u64(), msg: Some("Quot constant: type has too few foralls for its kind".to_string()) }); } - let __ret: [G; OUT_596] = []; - record.function_queries[596].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_595] = []; + record.function_queries[595].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_597: usize = 2; -const IN_597: usize = 2; -const OUT_597: usize = 1; -fn aiur_fn_597( - inp: [G; IN_597], +const INPUT_SIZE_596: usize = 2; +const IN_596: usize = 2; +const OUT_596: usize = 1; +fn aiur_fn_596( + inp: [G; IN_596], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_597], ExecError> { +) -> Result<[G; OUT_596], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_597] = [__v_0]; - record.function_queries[597].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_596] = [__v_0]; + record.function_queries[596].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51138,10 +51092,10 @@ fn aiur_fn_597( 5u64 => { let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 - __v_6); - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_597] = [__v_8]; - record.function_queries[597].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_596] = [__v_8]; + record.function_queries[596].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51153,29 +51107,29 @@ fn aiur_fn_597( }) } -const INPUT_SIZE_598: usize = 3; -const IN_598: usize = 3; -const OUT_598: usize = 0; -fn aiur_fn_598( - inp: [G; IN_598], +const INPUT_SIZE_597: usize = 3; +const IN_597: usize = 3; +const OUT_597: usize = 0; +fn aiur_fn_597( + inp: [G; IN_597], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_598], ExecError> { +) -> Result<[G; OUT_597], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = G::from_u64(0); if (__v_3 != __v_4) { return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("more universe levels than the inductive declares".to_string()) }); } - let __ret: [G; OUT_598] = []; - record.function_queries[598].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_597] = []; + record.function_queries[597].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51198,9 +51152,9 @@ fn aiur_fn_598( let __v_10: G = (__v_1 - __v_9); let __v_11: G = G::from_u64(1); let __v_12: G = (__v_2 + __v_11); - let __r_arr: [G; OUT_598] = { let __args: [G; IN_598] = [__v_5, __v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[598].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[598].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[598].bump_multiplicity(__i); } let __ret: [G; OUT_598] = unsafe { *(record.function_queries[598].output_at(__i).as_ptr() as *const [G; OUT_598]) }; __ret }, _ => aiur_fn_598(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_598] = []; - record.function_queries[598].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_5, __v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_597] = []; + record.function_queries[597].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51217,15 +51171,15 @@ fn aiur_fn_598( }) } -const INPUT_SIZE_599: usize = 4; -const IN_599: usize = 4; -const OUT_599: usize = 0; -fn aiur_fn_599( - inp: [G; IN_599], +const INPUT_SIZE_598: usize = 4; +const IN_598: usize = 4; +const OUT_598: usize = 0; +fn aiur_fn_598( + inp: [G; IN_598], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_599], ExecError> { +) -> Result<[G; OUT_598], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51234,8 +51188,8 @@ fn aiur_fn_599( let __v_4: G = (__v_1 - __v_3); match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_599] = []; - record.function_queries[599].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_598] = []; + record.function_queries[598].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51261,9 +51215,9 @@ fn aiur_fn_599( } let __v_16: G = G::from_u64(1); let __v_17: G = (__v_3 + __v_16); - let __r_arr: [G; OUT_599] = { let __args: [G; IN_599] = [__v_7, __v_1, __v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[599].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[599].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[599].bump_multiplicity(__i); } let __ret: [G; OUT_599] = unsafe { *(record.function_queries[599].output_at(__i).as_ptr() as *const [G; OUT_599]) }; __ret }, _ => aiur_fn_599(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_599] = []; - record.function_queries[599].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_598] = { let __args: [G; IN_598] = [__v_7, __v_1, __v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[598].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[598].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[598].bump_multiplicity(__i); } let __ret: [G; OUT_598] = unsafe { *(record.function_queries[598].output_at(__i).as_ptr() as *const [G; OUT_598]) }; __ret }, _ => aiur_fn_598(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_598] = []; + record.function_queries[598].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51280,20 +51234,20 @@ fn aiur_fn_599( }) } -const INPUT_SIZE_600: usize = 3; -const IN_600: usize = 3; -const OUT_600: usize = 0; -fn aiur_fn_600( - inp: [G; IN_600], +const INPUT_SIZE_599: usize = 3; +const IN_599: usize = 3; +const OUT_599: usize = 0; +fn aiur_fn_599( + inp: [G; IN_599], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_600], ExecError> { +) -> Result<[G; OUT_599], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -51319,8 +51273,8 @@ fn aiur_fn_600( if (__v_12 != __v_2) { return Err(ExecError::AssertEqMismatch { lhs: __v_12.as_canonical_u64(), rhs: __v_2.as_canonical_u64(), msg: Some("ctor return head is a different member of the block".to_string()) }); } - let __ret: [G; OUT_600] = []; - record.function_queries[600].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_599] = []; + record.function_queries[599].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51330,15 +51284,15 @@ fn aiur_fn_600( }) } -const INPUT_SIZE_601: usize = 7; -const IN_601: usize = 7; -const OUT_601: usize = 0; -fn aiur_fn_601( - inp: [G; IN_601], +const INPUT_SIZE_600: usize = 7; +const IN_600: usize = 7; +const OUT_600: usize = 0; +fn aiur_fn_600( + inp: [G; IN_600], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_601], ExecError> { +) -> Result<[G; OUT_600], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51348,7 +51302,7 @@ fn aiur_fn_601( let __v_5: G = inp[5]; let __v_6: G = inp[6]; let __v_7: G = (__v_1 + __v_3); - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; @@ -51360,32 +51314,32 @@ fn aiur_fn_601( let __v_14: G = __loaded[3]; match __v_11.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_600] = { let __args: [G; IN_600] = [__v_12, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[600].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[600].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[600].bump_multiplicity(__i); } let __ret: [G; OUT_600] = unsafe { *(record.function_queries[600].output_at(__i).as_ptr() as *const [G; OUT_600]) }; __ret }, _ => aiur_fn_600(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_599] = { let __args: [G; IN_599] = [__v_12, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[599].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[599].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[599].bump_multiplicity(__i); } let __ret: [G; OUT_599] = unsafe { *(record.function_queries[599].output_at(__i).as_ptr() as *const [G; OUT_599]) }; __ret }, _ => aiur_fn_599(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_598] = { let __args: [G; IN_598] = [__v_13, __v_4, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[598].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[598].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[598].bump_multiplicity(__i); } let __ret: [G; OUT_598] = unsafe { *(record.function_queries[598].output_at(__i).as_ptr() as *const [G; OUT_598]) }; __ret }, _ => aiur_fn_598(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_13, __v_4, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = (__v_1 + __v_2); if (__v_16 != __v_17) { return Err(ExecError::AssertEqMismatch { lhs: __v_16.as_canonical_u64(), rhs: __v_17.as_canonical_u64(), msg: Some("ctor return type: wrong number of spine arguments".to_string()) }); } let __v_18: G = G::from_u64(0); - let __r_arr: [G; OUT_599] = { let __args: [G; IN_599] = [__v_10, __v_1, __v_3, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[599].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[599].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[599].bump_multiplicity(__i); } let __ret: [G; OUT_599] = unsafe { *(record.function_queries[599].output_at(__i).as_ptr() as *const [G; OUT_599]) }; __ret }, _ => aiur_fn_599(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_598] = { let __args: [G; IN_598] = [__v_10, __v_1, __v_3, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[598].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[598].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[598].bump_multiplicity(__i); } let __ret: [G; OUT_598] = unsafe { *(record.function_queries[598].output_at(__i).as_ptr() as *const [G; OUT_598]) }; __ret }, _ => aiur_fn_598(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(1); let __v_22: G = G::from_u64(1); let __v_23: G = { let __values: [G; 3] = [__v_21, __v_22, __v_22]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_24: G = { let __values: [G; 3] = [__v_20, __v_5, __v_23]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_612] = { let __args: [G; IN_612] = [__v_19, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[612].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[612].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[612].bump_multiplicity(__i); } let __ret: [G; OUT_612] = unsafe { *(record.function_queries[612].output_at(__i).as_ptr() as *const [G; OUT_612]) }; __ret }, _ => aiur_fn_612(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_19, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(0); if (__v_25 != __v_26) { return Err(ExecError::AssertEqMismatch { lhs: __v_25.as_canonical_u64(), rhs: __v_26.as_canonical_u64(), msg: Some("ctor return type: reflexive occurrence in an index argument".to_string()) }); } - let __ret: [G; OUT_601] = []; - record.function_queries[601].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_600] = []; + record.function_queries[600].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51395,15 +51349,15 @@ fn aiur_fn_601( }) } -const INPUT_SIZE_602: usize = 4; -const IN_602: usize = 4; -const OUT_602: usize = 0; -fn aiur_fn_602( - inp: [G; IN_602], +const INPUT_SIZE_601: usize = 4; +const IN_601: usize = 4; +const OUT_601: usize = 0; +fn aiur_fn_601( + inp: [G; IN_601], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_602], ExecError> { +) -> Result<[G; OUT_601], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51411,8 +51365,8 @@ fn aiur_fn_602( let __v_3: G = inp[3]; match __v_2.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_602] = []; - record.function_queries[602].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_601] = []; + record.function_queries[601].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51430,7 +51384,7 @@ fn aiur_fn_602( let __v_11: G = __loaded[3]; match __v_8.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_5, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_5, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(1); if (__v_12 != __v_13) { @@ -51440,9 +51394,9 @@ fn aiur_fn_602( let __v_15: G = { let __values: [G; 3] = [__v_14, __v_5, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_16: G = G::from_u64(1); let __v_17: G = (__v_2 - __v_16); - let __r_arr: [G; OUT_602] = { let __args: [G; IN_602] = [__v_6, __v_10, __v_17, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[602].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[602].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[602].bump_multiplicity(__i); } let __ret: [G; OUT_602] = unsafe { *(record.function_queries[602].output_at(__i).as_ptr() as *const [G; OUT_602]) }; __ret }, _ => aiur_fn_602(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_602] = []; - record.function_queries[602].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_601] = { let __args: [G; IN_601] = [__v_6, __v_10, __v_17, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[601].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[601].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[601].bump_multiplicity(__i); } let __ret: [G; OUT_601] = unsafe { *(record.function_queries[601].output_at(__i).as_ptr() as *const [G; OUT_601]) }; __ret }, _ => aiur_fn_601(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_601] = []; + record.function_queries[601].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51459,15 +51413,15 @@ fn aiur_fn_602( }) } -const INPUT_SIZE_603: usize = 3; -const IN_603: usize = 3; -const OUT_603: usize = 0; -fn aiur_fn_603( - inp: [G; IN_603], +const INPUT_SIZE_602: usize = 3; +const IN_602: usize = 3; +const OUT_602: usize = 0; +fn aiur_fn_602( + inp: [G; IN_602], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_603], ExecError> { +) -> Result<[G; OUT_602], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51475,27 +51429,27 @@ fn aiur_fn_603( let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_602] = { let __args: [G; IN_602] = [__v_0, __v_1, __v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[602].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[602].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[602].bump_multiplicity(__i); } let __ret: [G; OUT_602] = unsafe { *(record.function_queries[602].output_at(__i).as_ptr() as *const [G; OUT_602]) }; __ret }, _ => aiur_fn_602(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_603] = []; - record.function_queries[603].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_601] = { let __args: [G; IN_601] = [__v_0, __v_1, __v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[601].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[601].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[601].bump_multiplicity(__i); } let __ret: [G; OUT_601] = unsafe { *(record.function_queries[601].output_at(__i).as_ptr() as *const [G; OUT_601]) }; __ret }, _ => aiur_fn_601(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_602] = []; + record.function_queries[602].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_604: usize = 3; -const IN_604: usize = 3; -const OUT_604: usize = 1; -fn aiur_fn_604( - inp: [G; IN_604], +const INPUT_SIZE_603: usize = 3; +const IN_603: usize = 3; +const OUT_603: usize = 1; +fn aiur_fn_603( + inp: [G; IN_603], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_604], ExecError> { +) -> Result<[G; OUT_603], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; match __v_1.as_canonical_u64() { 0u64 => { @@ -51506,8 +51460,8 @@ fn aiur_fn_604( let __v_7: G = __loaded[3]; match __v_4.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_604] = [__v_5]; - record.function_queries[604].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_603] = [__v_5]; + record.function_queries[603].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51527,10 +51481,10 @@ fn aiur_fn_604( let __v_9: G = (__v_1 - __v_8); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 3] = [__v_10, __v_5, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_6, __v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_6, __v_9, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_604] = [__v_12]; - record.function_queries[604].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_603] = [__v_12]; + record.function_queries[603].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51542,15 +51496,15 @@ fn aiur_fn_604( }) } -const INPUT_SIZE_605: usize = 3; -const IN_605: usize = 3; -const OUT_605: usize = 0; -fn aiur_fn_605( - inp: [G; IN_605], +const INPUT_SIZE_604: usize = 3; +const IN_604: usize = 3; +const OUT_604: usize = 0; +fn aiur_fn_604( + inp: [G; IN_604], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_605], ExecError> { +) -> Result<[G; OUT_604], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51562,9 +51516,9 @@ fn aiur_fn_605( let __v_6: G = __loaded[3]; match __v_3.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_322] = { let __args: [G; IN_322] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[322].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[322].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[322].bump_multiplicity(__i); } let __ret: [G; OUT_322] = unsafe { *(record.function_queries[322].output_at(__i).as_ptr() as *const [G; OUT_322]) }; __ret }, _ => aiur_fn_322(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = G::from_u64(1); if (__v_8 != __v_9) { @@ -51572,29 +51526,29 @@ fn aiur_fn_605( } let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 3] = [__v_10, __v_4, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_605] = { let __args: [G; IN_605] = [__v_5, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[605].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[605].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[605].bump_multiplicity(__i); } let __ret: [G; OUT_605] = unsafe { *(record.function_queries[605].output_at(__i).as_ptr() as *const [G; OUT_605]) }; __ret }, _ => aiur_fn_605(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_605] = []; - record.function_queries[605].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_5, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_604] = []; + record.function_queries[604].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_605] = []; - record.function_queries[605].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_604] = []; + record.function_queries[604].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_606: usize = 4; -const IN_606: usize = 4; -const OUT_606: usize = 0; -fn aiur_fn_606( - inp: [G; IN_606], +const INPUT_SIZE_605: usize = 4; +const IN_605: usize = 4; +const OUT_605: usize = 0; +fn aiur_fn_605( + inp: [G; IN_605], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_606], ExecError> { +) -> Result<[G; OUT_605], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51602,9 +51556,9 @@ fn aiur_fn_606( let __v_3: G = inp[3]; match __v_1.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_605] = { let __args: [G; IN_605] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[605].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[605].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[605].bump_multiplicity(__i); } let __ret: [G; OUT_605] = unsafe { *(record.function_queries[605].output_at(__i).as_ptr() as *const [G; OUT_605]) }; __ret }, _ => aiur_fn_605(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_606] = []; - record.function_queries[606].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_605] = []; + record.function_queries[605].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51619,9 +51573,9 @@ fn aiur_fn_606( let __v_9: G = (__v_1 - __v_8); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 3] = [__v_10, __v_5, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_606] = { let __args: [G; IN_606] = [__v_6, __v_9, __v_2, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[606].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[606].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[606].bump_multiplicity(__i); } let __ret: [G; OUT_606] = unsafe { *(record.function_queries[606].output_at(__i).as_ptr() as *const [G; OUT_606]) }; __ret }, _ => aiur_fn_606(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_606] = []; - record.function_queries[606].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_605] = { let __args: [G; IN_605] = [__v_6, __v_9, __v_2, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[605].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[605].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[605].bump_multiplicity(__i); } let __ret: [G; OUT_605] = unsafe { *(record.function_queries[605].output_at(__i).as_ptr() as *const [G; OUT_605]) }; __ret }, _ => aiur_fn_605(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_605] = []; + record.function_queries[605].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51633,15 +51587,15 @@ fn aiur_fn_606( }) } -const INPUT_SIZE_607: usize = 3; -const IN_607: usize = 3; -const OUT_607: usize = 0; -fn aiur_fn_607( - inp: [G; IN_607], +const INPUT_SIZE_606: usize = 3; +const IN_606: usize = 3; +const OUT_606: usize = 0; +fn aiur_fn_606( + inp: [G; IN_606], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_607], ExecError> { +) -> Result<[G; OUT_606], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51652,52 +51606,52 @@ fn aiur_fn_607( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_607] = []; - record.function_queries[607].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_606] = []; + record.function_queries[606].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_606] = { let __args: [G; IN_606] = [__v_0, __v_1, __v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[606].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[606].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[606].bump_multiplicity(__i); } let __ret: [G; OUT_606] = unsafe { *(record.function_queries[606].output_at(__i).as_ptr() as *const [G; OUT_606]) }; __ret }, _ => aiur_fn_606(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_607] = []; - record.function_queries[607].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_605] = { let __args: [G; IN_605] = [__v_0, __v_1, __v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[605].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[605].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[605].bump_multiplicity(__i); } let __ret: [G; OUT_605] = unsafe { *(record.function_queries[605].output_at(__i).as_ptr() as *const [G; OUT_605]) }; __ret }, _ => aiur_fn_605(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_606] = []; + record.function_queries[606].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_608: usize = 2; -const IN_608: usize = 2; -const OUT_608: usize = 1; -fn aiur_fn_608( - inp: [G; IN_608], +const INPUT_SIZE_607: usize = 2; +const IN_607: usize = 2; +const OUT_607: usize = 1; +fn aiur_fn_607( + inp: [G; IN_607], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_608], ExecError> { +) -> Result<[G; OUT_607], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_288] = { let __args: [G; IN_288] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[288].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[288].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[288].bump_multiplicity(__i); } let __ret: [G; OUT_288] = unsafe { *(record.function_queries[288].output_at(__i).as_ptr() as *const [G; OUT_288]) }; __ret }, _ => aiur_fn_288(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __ret: [G; OUT_608] = [__v_2]; - record.function_queries[608].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_607] = [__v_2]; + record.function_queries[607].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_609: usize = 2; -const IN_609: usize = 2; -const OUT_609: usize = 1; -fn aiur_fn_609( - inp: [G; IN_609], +const INPUT_SIZE_608: usize = 2; +const IN_608: usize = 2; +const OUT_608: usize = 1; +fn aiur_fn_608( + inp: [G; IN_608], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_609], ExecError> { +) -> Result<[G; OUT_608], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51708,8 +51662,8 @@ fn aiur_fn_609( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_609] = [__v_5]; - record.function_queries[609].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_608] = [__v_5]; + record.function_queries[608].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -51718,15 +51672,15 @@ fn aiur_fn_609( match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_609] = [__v_6]; - record.function_queries[609].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_608] = [__v_6]; + record.function_queries[608].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_609] = { let __args: [G; IN_609] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[609].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[609].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[609].bump_multiplicity(__i); } let __ret: [G; OUT_609] = unsafe { *(record.function_queries[609].output_at(__i).as_ptr() as *const [G; OUT_609]) }; __ret }, _ => aiur_fn_609(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_608] = { let __args: [G; IN_608] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[608].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[608].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[608].bump_multiplicity(__i); } let __ret: [G; OUT_608] = unsafe { *(record.function_queries[608].output_at(__i).as_ptr() as *const [G; OUT_608]) }; __ret }, _ => aiur_fn_608(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_609] = [__v_6]; - record.function_queries[609].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_608] = [__v_6]; + record.function_queries[608].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -51738,19 +51692,19 @@ fn aiur_fn_609( }) } -const INPUT_SIZE_610: usize = 2; -const IN_610: usize = 2; -const OUT_610: usize = 1; -fn aiur_fn_610( - inp: [G; IN_610], +const INPUT_SIZE_609: usize = 2; +const IN_609: usize = 2; +const OUT_609: usize = 1; +fn aiur_fn_609( + inp: [G; IN_609], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_610], ExecError> { +) -> Result<[G; OUT_609], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_2.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_3: G = __loaded[0]; @@ -51767,31 +51721,31 @@ fn aiur_fn_610( let __v_14: G = __loaded[11]; match __v_3.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_609] = { let __args: [G; IN_609] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[609].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[609].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[609].bump_multiplicity(__i); } let __ret: [G; OUT_609] = unsafe { *(record.function_queries[609].output_at(__i).as_ptr() as *const [G; OUT_609]) }; __ret }, _ => aiur_fn_609(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_608] = { let __args: [G; IN_608] = [__v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[608].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[608].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[608].bump_multiplicity(__i); } let __ret: [G; OUT_608] = unsafe { *(record.function_queries[608].output_at(__i).as_ptr() as *const [G; OUT_608]) }; __ret }, _ => aiur_fn_608(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_610] = [__v_15]; - record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_609] = [__v_15]; + record.function_queries[609].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); - let __ret: [G; OUT_610] = [__v_15]; - record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_609] = [__v_15]; + record.function_queries[609].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_611: usize = 2; -const IN_611: usize = 2; -const OUT_611: usize = 1; -fn aiur_fn_611( - inp: [G; IN_611], +const INPUT_SIZE_610: usize = 2; +const IN_610: usize = 2; +const OUT_610: usize = 1; +fn aiur_fn_610( + inp: [G; IN_610], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_611], ExecError> { +) -> Result<[G; OUT_610], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51803,105 +51757,105 @@ fn aiur_fn_611( match __v_2.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_611] = [__v_6]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_6]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_611] = [__v_6]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_6]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_609] = { let __args: [G; IN_609] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[609].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[609].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[609].bump_multiplicity(__i); } let __ret: [G; OUT_609] = unsafe { *(record.function_queries[609].output_at(__i).as_ptr() as *const [G; OUT_609]) }; __ret }, _ => aiur_fn_609(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_611] = [__v_6]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_6]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_611] = [__v_7]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_7]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_611] = [__v_7]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_7]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 4u64 => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_611] = [__v_7]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_7]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_611] = [__v_7]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_7]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 5u64 => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_611] = [__v_7]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_7]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_611] = [__v_7]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_7]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 6u64 => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; match __v_6.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(1); - let __ret: [G; OUT_611] = [__v_7]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_7]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; match __v_7.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_611] = [__v_8]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_8]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_611] = [__v_8]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_8]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -51910,15 +51864,15 @@ fn aiur_fn_611( }, 7u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_611] = [__v_6]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_6]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_611] = [__v_6]; - record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_610] = [__v_6]; + record.function_queries[610].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -51928,15 +51882,15 @@ fn aiur_fn_611( }) } -const INPUT_SIZE_612: usize = 2; -const IN_612: usize = 2; -const OUT_612: usize = 1; -fn aiur_fn_612( - inp: [G; IN_612], +const INPUT_SIZE_611: usize = 2; +const IN_611: usize = 2; +const OUT_611: usize = 1; +fn aiur_fn_611( + inp: [G; IN_611], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_612], ExecError> { +) -> Result<[G; OUT_611], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -51947,25 +51901,25 @@ fn aiur_fn_612( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_612] = [__v_5]; - record.function_queries[612].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_611] = [__v_5]; + record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_3, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_612] = [__v_6]; - record.function_queries[612].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_611] = [__v_6]; + record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_612] = { let __args: [G; IN_612] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[612].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[612].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[612].bump_multiplicity(__i); } let __ret: [G; OUT_612] = unsafe { *(record.function_queries[612].output_at(__i).as_ptr() as *const [G; OUT_612]) }; __ret }, _ => aiur_fn_612(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_612] = [__v_6]; - record.function_queries[612].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_611] = [__v_6]; + record.function_queries[611].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -51977,23 +51931,23 @@ fn aiur_fn_612( }) } -const INPUT_SIZE_613: usize = 3; -const IN_613: usize = 3; -const OUT_613: usize = 2; -fn aiur_fn_613( - inp: [G; IN_613], +const INPUT_SIZE_612: usize = 3; +const IN_612: usize = 3; +const OUT_612: usize = 2; +fn aiur_fn_612( + inp: [G; IN_612], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_613], ExecError> { +) -> Result<[G; OUT_612], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_613] = [__v_0, __v_2]; - record.function_queries[613].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_612] = [__v_0, __v_2]; + record.function_queries[612].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52008,16 +51962,16 @@ fn aiur_fn_613( let __v_8: G = { let __values: [G; 3] = [__v_7, __v_4, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_1 - __v_9); - let __r_arr: [G; OUT_613] = { let __args: [G; IN_613] = [__v_5, __v_10, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[613].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[613].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[613].bump_multiplicity(__i); } let __ret: [G; OUT_613] = unsafe { *(record.function_queries[613].output_at(__i).as_ptr() as *const [G; OUT_613]) }; __ret }, _ => aiur_fn_613(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_612] = { let __args: [G; IN_612] = [__v_5, __v_10, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[612].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[612].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[612].bump_multiplicity(__i); } let __ret: [G; OUT_612] = unsafe { *(record.function_queries[612].output_at(__i).as_ptr() as *const [G; OUT_612]) }; __ret }, _ => aiur_fn_612(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; - let __ret: [G; OUT_613] = [__v_11, __v_12]; - record.function_queries[613].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_612] = [__v_11, __v_12]; + record.function_queries[612].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_613] = [__v_0, __v_2]; - record.function_queries[613].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_612] = [__v_0, __v_2]; + record.function_queries[612].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -52026,15 +51980,15 @@ fn aiur_fn_613( }) } -const INPUT_SIZE_614: usize = 4; -const IN_614: usize = 4; -const OUT_614: usize = 0; -fn aiur_fn_614( - inp: [G; IN_614], +const INPUT_SIZE_613: usize = 4; +const IN_613: usize = 4; +const OUT_613: usize = 0; +fn aiur_fn_613( + inp: [G; IN_613], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_614], ExecError> { +) -> Result<[G; OUT_613], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52043,8 +51997,8 @@ fn aiur_fn_614( let __v_4: G = (__v_1 - __v_3); match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_614] = []; - record.function_queries[614].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_613] = []; + record.function_queries[613].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52069,9 +52023,9 @@ fn aiur_fn_614( } let __v_15: G = G::from_u64(1); let __v_16: G = (__v_3 + __v_15); - let __r_arr: [G; OUT_614] = { let __args: [G; IN_614] = [__v_7, __v_1, __v_2, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[614].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[614].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[614].bump_multiplicity(__i); } let __ret: [G; OUT_614] = unsafe { *(record.function_queries[614].output_at(__i).as_ptr() as *const [G; OUT_614]) }; __ret }, _ => aiur_fn_614(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_614] = []; - record.function_queries[614].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_613] = { let __args: [G; IN_613] = [__v_7, __v_1, __v_2, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[613].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[613].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[613].bump_multiplicity(__i); } let __ret: [G; OUT_613] = unsafe { *(record.function_queries[613].output_at(__i).as_ptr() as *const [G; OUT_613]) }; __ret }, _ => aiur_fn_613(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_613] = []; + record.function_queries[613].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52088,22 +52042,22 @@ fn aiur_fn_614( }) } -const INPUT_SIZE_615: usize = 5; -const IN_615: usize = 5; -const OUT_615: usize = 0; -fn aiur_fn_615( - inp: [G; IN_615], +const INPUT_SIZE_614: usize = 5; +const IN_614: usize = 5; +const OUT_614: usize = 0; +fn aiur_fn_614( + inp: [G; IN_614], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_615], ExecError> { +) -> Result<[G; OUT_614], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -52121,25 +52075,25 @@ fn aiur_fn_615( match __v_6.as_canonical_u64() { 5u64 => { let __v_18: G = G::from_u64(0); - let __r_arr: [G; OUT_598] = { let __args: [G; IN_598] = [__v_1, __v_7, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[598].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[598].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[598].bump_multiplicity(__i); } let __ret: [G; OUT_598] = unsafe { *(record.function_queries[598].output_at(__i).as_ptr() as *const [G; OUT_598]) }; __ret }, _ => aiur_fn_598(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_1, __v_7, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = (__v_9 + __v_10); if (__v_19 != __v_20) { return Err(ExecError::AssertEqMismatch { lhs: __v_19.as_canonical_u64(), rhs: __v_20.as_canonical_u64(), msg: Some("recursive occurrence is not fully applied".to_string()) }); } let __v_21: G = G::from_u64(0); - let __r_arr: [G; OUT_614] = { let __args: [G; IN_614] = [__v_2, __v_9, __v_4, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[614].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[614].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[614].bump_multiplicity(__i); } let __ret: [G; OUT_614] = unsafe { *(record.function_queries[614].output_at(__i).as_ptr() as *const [G; OUT_614]) }; __ret }, _ => aiur_fn_614(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_613] = { let __args: [G; IN_613] = [__v_2, __v_9, __v_4, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[613].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[613].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[613].bump_multiplicity(__i); } let __ret: [G; OUT_613] = unsafe { *(record.function_queries[613].output_at(__i).as_ptr() as *const [G; OUT_613]) }; __ret }, _ => aiur_fn_613(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_612] = { let __args: [G; IN_612] = [__v_22, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[612].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[612].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[612].bump_multiplicity(__i); } let __ret: [G; OUT_612] = unsafe { *(record.function_queries[612].output_at(__i).as_ptr() as *const [G; OUT_612]) }; __ret }, _ => aiur_fn_612(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_22, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __v_24: G = G::from_u64(0); if (__v_23 != __v_24) { return Err(ExecError::AssertEqMismatch { lhs: __v_23.as_canonical_u64(), rhs: __v_24.as_canonical_u64(), msg: Some("recursive occurrence: index argument mentions the block".to_string()) }); } - let __ret: [G; OUT_615] = []; - record.function_queries[615].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_614] = []; + record.function_queries[614].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52149,30 +52103,30 @@ fn aiur_fn_615( }) } -const INPUT_SIZE_616: usize = 4; -const IN_616: usize = 4; -const OUT_616: usize = 0; -fn aiur_fn_616( - inp: [G; IN_616], +const INPUT_SIZE_615: usize = 4; +const IN_615: usize = 4; +const OUT_615: usize = 0; +fn aiur_fn_615( + inp: [G; IN_615], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_616], ExecError> { +) -> Result<[G; OUT_615], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_616] = []; - record.function_queries[616].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_615] = []; + record.function_queries[615].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_5.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_6: G = __loaded[0]; @@ -52181,7 +52135,7 @@ fn aiur_fn_616( let __v_9: G = __loaded[3]; match __v_6.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_7, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); if (__v_10 != __v_11) { @@ -52189,9 +52143,9 @@ fn aiur_fn_616( } let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_12, __v_7, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_616] = { let __args: [G; IN_616] = [__v_8, __v_1, __v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[616].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[616].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[616].bump_multiplicity(__i); } let __ret: [G; OUT_616] = unsafe { *(record.function_queries[616].output_at(__i).as_ptr() as *const [G; OUT_616]) }; __ret }, _ => aiur_fn_616(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_616] = []; - record.function_queries[616].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_615] = { let __args: [G; IN_615] = [__v_8, __v_1, __v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[615].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[615].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[615].bump_multiplicity(__i); } let __ret: [G; OUT_615] = unsafe { *(record.function_queries[615].output_at(__i).as_ptr() as *const [G; OUT_615]) }; __ret }, _ => aiur_fn_615(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_615] = []; + record.function_queries[615].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52205,28 +52159,28 @@ fn aiur_fn_616( let __v_15: G = __loaded[3]; match __v_12.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_610] = { let __args: [G; IN_610] = [__v_13, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[610].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[610].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[610].bump_multiplicity(__i); } let __ret: [G; OUT_610] = unsafe { *(record.function_queries[610].output_at(__i).as_ptr() as *const [G; OUT_610]) }; __ret }, _ => aiur_fn_610(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_609] = { let __args: [G; IN_609] = [__v_13, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[609].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[609].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[609].bump_multiplicity(__i); } let __ret: [G; OUT_609] = unsafe { *(record.function_queries[609].output_at(__i).as_ptr() as *const [G; OUT_609]) }; __ret }, _ => aiur_fn_609(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; match __v_16.as_canonical_u64() { 1u64 => { match __v_3.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_615] = { let __args: [G; IN_615] = [__v_13, __v_14, __v_11, __v_1, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[615].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[615].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[615].bump_multiplicity(__i); } let __ret: [G; OUT_615] = unsafe { *(record.function_queries[615].output_at(__i).as_ptr() as *const [G; OUT_615]) }; __ret }, _ => aiur_fn_615(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_616] = []; - record.function_queries[616].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_614] = { let __args: [G; IN_614] = [__v_13, __v_14, __v_11, __v_1, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[614].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[614].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[614].bump_multiplicity(__i); } let __ret: [G; OUT_614] = unsafe { *(record.function_queries[614].output_at(__i).as_ptr() as *const [G; OUT_614]) }; __ret }, _ => aiur_fn_614(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_615] = []; + record.function_queries[615].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_616] = []; - record.function_queries[616].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_615] = []; + record.function_queries[615].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_17.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_18: G = __loaded[0]; @@ -52243,9 +52197,9 @@ fn aiur_fn_616( let __v_29: G = __loaded[11]; match __v_18.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; - let __r_arr: [G; OUT_612] = { let __args: [G; IN_612] = [__v_30, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[612].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[612].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[612].bump_multiplicity(__i); } let __ret: [G; OUT_612] = unsafe { *(record.function_queries[612].output_at(__i).as_ptr() as *const [G; OUT_612]) }; __ret }, _ => aiur_fn_612(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_611] = { let __args: [G; IN_611] = [__v_30, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[611].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[611].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[611].bump_multiplicity(__i); } let __ret: [G; OUT_611] = unsafe { *(record.function_queries[611].output_at(__i).as_ptr() as *const [G; OUT_611]) }; __ret }, _ => aiur_fn_611(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = G::from_u64(0); if (__v_31 != __v_32) { @@ -52253,14 +52207,14 @@ fn aiur_fn_616( } let __v_33: G = G::from_u64(0); let __v_34: G = { let __values: [G; 3] = [__v_33, __v_25, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_11, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_35: G = __r_arr[0]; - let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_35]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_35]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; let __v_36: G = __r_arr[0]; let __v_37: G = G::from_u64(0); - let __r_arr: [G; OUT_617] = { let __args: [G; IN_617] = [__v_25, __v_26, __v_23, __v_34, __v_37, __v_21, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[617].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[617].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[617].bump_multiplicity(__i); } let __ret: [G; OUT_617] = unsafe { *(record.function_queries[617].output_at(__i).as_ptr() as *const [G; OUT_617]) }; __ret }, _ => aiur_fn_617(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_616] = []; - record.function_queries[616].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_616] = { let __args: [G; IN_616] = [__v_25, __v_26, __v_23, __v_34, __v_37, __v_21, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[616].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[616].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[616].bump_multiplicity(__i); } let __ret: [G; OUT_616] = unsafe { *(record.function_queries[616].output_at(__i).as_ptr() as *const [G; OUT_616]) }; __ret }, _ => aiur_fn_616(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_615] = []; + record.function_queries[615].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52281,15 +52235,15 @@ fn aiur_fn_616( }) } -const INPUT_SIZE_617: usize = 7; -const IN_617: usize = 7; -const OUT_617: usize = 0; -fn aiur_fn_617( - inp: [G; IN_617], +const INPUT_SIZE_616: usize = 7; +const IN_616: usize = 7; +const OUT_616: usize = 0; +fn aiur_fn_616( + inp: [G; IN_616], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_617], ExecError> { +) -> Result<[G; OUT_616], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52301,12 +52255,12 @@ fn aiur_fn_617( let __v_7: G = (__v_2 - __v_4); match __v_7.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_617] = []; - record.function_queries[617].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_616] = []; + record.function_queries[616].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_0, __v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_0, __v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_8.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_9: G = __loaded[0]; @@ -52326,22 +52280,22 @@ fn aiur_fn_617( let __v_21: G = G::from_u64(1); let __v_22: G = G::from_u64(1); let __v_23: G = { let __values: [G; 3] = [__v_21, __v_22, __v_22]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_613] = { let __args: [G; IN_613] = [__v_11, __v_5, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[613].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[613].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[613].bump_multiplicity(__i); } let __ret: [G; OUT_613] = unsafe { *(record.function_queries[613].output_at(__i).as_ptr() as *const [G; OUT_613]) }; __ret }, _ => aiur_fn_613(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_612] = { let __args: [G; IN_612] = [__v_11, __v_5, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[612].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[612].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[612].bump_multiplicity(__i); } let __ret: [G; OUT_612] = unsafe { *(record.function_queries[612].output_at(__i).as_ptr() as *const [G; OUT_612]) }; __ret }, _ => aiur_fn_612(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = __r_arr[1]; let __v_26: G = G::from_u64(0); - let __r_arr: [G; OUT_371] = { let __args: [G; IN_371] = [__v_24, __v_6, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[371].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[371].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[371].bump_multiplicity(__i); } let __ret: [G; OUT_371] = unsafe { *(record.function_queries[371].output_at(__i).as_ptr() as *const [G; OUT_371]) }; __ret }, _ => aiur_fn_371(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_370] = { let __args: [G; IN_370] = [__v_24, __v_6, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[370].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[370].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[370].bump_multiplicity(__i); } let __ret: [G; OUT_370] = unsafe { *(record.function_queries[370].output_at(__i).as_ptr() as *const [G; OUT_370]) }; __ret }, _ => aiur_fn_370(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = G::from_u64(1); let __v_29: G = G::from_u64(1); let __v_30: G = { let __values: [G; 3] = [__v_28, __v_29, __v_29]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_31: G = G::from_u64(0); - let __r_arr: [G; OUT_618] = { let __args: [G; IN_618] = [__v_27, __v_3, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[618].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[618].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[618].bump_multiplicity(__i); } let __ret: [G; OUT_618] = unsafe { *(record.function_queries[618].output_at(__i).as_ptr() as *const [G; OUT_618]) }; __ret }, _ => aiur_fn_618(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_617] = { let __args: [G; IN_617] = [__v_27, __v_3, __v_30, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[617].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[617].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[617].bump_multiplicity(__i); } let __ret: [G; OUT_617] = unsafe { *(record.function_queries[617].output_at(__i).as_ptr() as *const [G; OUT_617]) }; __ret }, _ => aiur_fn_617(__args, record, io_buffer, __cu)? } }; let __v_32: G = G::from_u64(1); let __v_33: G = (__v_4 + __v_32); - let __r_arr: [G; OUT_617] = { let __args: [G; IN_617] = [__v_0, __v_1, __v_2, __v_3, __v_33, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[617].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[617].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[617].bump_multiplicity(__i); } let __ret: [G; OUT_617] = unsafe { *(record.function_queries[617].output_at(__i).as_ptr() as *const [G; OUT_617]) }; __ret }, _ => aiur_fn_617(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_617] = []; - record.function_queries[617].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_616] = { let __args: [G; IN_616] = [__v_0, __v_1, __v_2, __v_3, __v_33, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[616].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[616].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[616].bump_multiplicity(__i); } let __ret: [G; OUT_616] = unsafe { *(record.function_queries[616].output_at(__i).as_ptr() as *const [G; OUT_616]) }; __ret }, _ => aiur_fn_616(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_616] = []; + record.function_queries[616].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52353,15 +52307,15 @@ fn aiur_fn_617( }) } -const INPUT_SIZE_618: usize = 4; -const IN_618: usize = 4; -const OUT_618: usize = 0; -fn aiur_fn_618( - inp: [G; IN_618], +const INPUT_SIZE_617: usize = 4; +const IN_617: usize = 4; +const OUT_617: usize = 0; +fn aiur_fn_617( + inp: [G; IN_617], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_618], ExecError> { +) -> Result<[G; OUT_617], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52374,32 +52328,32 @@ fn aiur_fn_618( let __v_7: G = __loaded[3]; match __v_4.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_616] = { let __args: [G; IN_616] = [__v_5, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[616].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[616].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[616].bump_multiplicity(__i); } let __ret: [G; OUT_616] = unsafe { *(record.function_queries[616].output_at(__i).as_ptr() as *const [G; OUT_616]) }; __ret }, _ => aiur_fn_616(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_615] = { let __args: [G; IN_615] = [__v_5, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[615].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[615].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[615].bump_multiplicity(__i); } let __ret: [G; OUT_615] = unsafe { *(record.function_queries[615].output_at(__i).as_ptr() as *const [G; OUT_615]) }; __ret }, _ => aiur_fn_615(__args, record, io_buffer, __cu)? } }; let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 3] = [__v_8, __v_5, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_618] = { let __args: [G; IN_618] = [__v_6, __v_1, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[618].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[618].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[618].bump_multiplicity(__i); } let __ret: [G; OUT_618] = unsafe { *(record.function_queries[618].output_at(__i).as_ptr() as *const [G; OUT_618]) }; __ret }, _ => aiur_fn_618(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_618] = []; - record.function_queries[618].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_617] = { let __args: [G; IN_617] = [__v_6, __v_1, __v_9, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[617].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[617].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[617].bump_multiplicity(__i); } let __ret: [G; OUT_617] = unsafe { *(record.function_queries[617].output_at(__i).as_ptr() as *const [G; OUT_617]) }; __ret }, _ => aiur_fn_617(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_617] = []; + record.function_queries[617].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_618] = []; - record.function_queries[618].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_617] = []; + record.function_queries[617].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_619: usize = 4; -const IN_619: usize = 4; -const OUT_619: usize = 0; -fn aiur_fn_619( - inp: [G; IN_619], +const INPUT_SIZE_618: usize = 4; +const IN_618: usize = 4; +const OUT_618: usize = 0; +fn aiur_fn_618( + inp: [G; IN_618], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_619], ExecError> { +) -> Result<[G; OUT_618], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52410,26 +52364,26 @@ fn aiur_fn_619( let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_8: G = { let __values: [G; 3] = [__v_4, __v_2, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_613] = { let __args: [G; IN_613] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[613].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[613].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[613].bump_multiplicity(__i); } let __ret: [G; OUT_613] = unsafe { *(record.function_queries[613].output_at(__i).as_ptr() as *const [G; OUT_613]) }; __ret }, _ => aiur_fn_613(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_612] = { let __args: [G; IN_612] = [__v_0, __v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[612].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[612].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[612].bump_multiplicity(__i); } let __ret: [G; OUT_612] = unsafe { *(record.function_queries[612].output_at(__i).as_ptr() as *const [G; OUT_612]) }; __ret }, _ => aiur_fn_612(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = __r_arr[1]; let __v_11: G = G::from_u64(1); - let __r_arr: [G; OUT_618] = { let __args: [G; IN_618] = [__v_9, __v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[618].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[618].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[618].bump_multiplicity(__i); } let __ret: [G; OUT_618] = unsafe { *(record.function_queries[618].output_at(__i).as_ptr() as *const [G; OUT_618]) }; __ret }, _ => aiur_fn_618(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_619] = []; - record.function_queries[619].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_617] = { let __args: [G; IN_617] = [__v_9, __v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[617].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[617].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[617].bump_multiplicity(__i); } let __ret: [G; OUT_617] = unsafe { *(record.function_queries[617].output_at(__i).as_ptr() as *const [G; OUT_617]) }; __ret }, _ => aiur_fn_617(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_618] = []; + record.function_queries[618].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_620: usize = 8; -const IN_620: usize = 8; -const OUT_620: usize = 0; -fn aiur_fn_620( - inp: [G; IN_620], +const INPUT_SIZE_619: usize = 8; +const IN_619: usize = 8; +const OUT_619: usize = 0; +fn aiur_fn_619( + inp: [G; IN_619], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_620], ExecError> { +) -> Result<[G; OUT_619], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52443,25 +52397,25 @@ fn aiur_fn_620( let __v_9: G = G::from_u64(1); let __v_10: G = G::from_u64(1); let __v_11: G = { let __values: [G; 3] = [__v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_0, __v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_0, __v_8, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_621] = { let __args: [G; IN_621] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_12, __v_7, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[621].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[621].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[621].bump_multiplicity(__i); } let __ret: [G; OUT_621] = unsafe { *(record.function_queries[621].output_at(__i).as_ptr() as *const [G; OUT_621]) }; __ret }, _ => aiur_fn_621(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_620] = []; - record.function_queries[620].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_620] = { let __args: [G; IN_620] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_12, __v_7, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[620].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[620].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[620].bump_multiplicity(__i); } let __ret: [G; OUT_620] = unsafe { *(record.function_queries[620].output_at(__i).as_ptr() as *const [G; OUT_620]) }; __ret }, _ => aiur_fn_620(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_619] = []; + record.function_queries[619].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_621: usize = 10; -const IN_621: usize = 10; -const OUT_621: usize = 0; -fn aiur_fn_621( - inp: [G; IN_621], +const INPUT_SIZE_620: usize = 10; +const IN_620: usize = 10; +const OUT_620: usize = 0; +fn aiur_fn_620( + inp: [G; IN_620], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_621], ExecError> { +) -> Result<[G; OUT_620], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52476,12 +52430,12 @@ fn aiur_fn_621( let __v_10: G = (__v_3 - __v_9); match __v_10.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_621] = []; - record.function_queries[621].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_620] = []; + record.function_queries[620].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_5, __v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_5, __v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_11.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_12: G = __loaded[0]; @@ -52513,15 +52467,15 @@ fn aiur_fn_621( if (__v_18 != __v_1) { return Err(ExecError::AssertEqMismatch { lhs: __v_18.as_canonical_u64(), rhs: __v_1.as_canonical_u64(), msg: Some("ctor parameter count differs from the inductive's".to_string()) }); } - let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_0, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_601] = { let __args: [G; IN_601] = [__v_14, __v_18, __v_2, __v_19, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[601].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[601].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[601].bump_multiplicity(__i); } let __ret: [G; OUT_601] = unsafe { *(record.function_queries[601].output_at(__i).as_ptr() as *const [G; OUT_601]) }; __ret }, _ => aiur_fn_601(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_607] = { let __args: [G; IN_607] = [__v_14, __v_18, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[607].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[607].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[607].bump_multiplicity(__i); } let __ret: [G; OUT_607] = unsafe { *(record.function_queries[607].output_at(__i).as_ptr() as *const [G; OUT_607]) }; __ret }, _ => aiur_fn_607(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_602] = { let __args: [G; IN_602] = [__v_0, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[602].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[602].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[602].bump_multiplicity(__i); } let __ret: [G; OUT_602] = unsafe { *(record.function_queries[602].output_at(__i).as_ptr() as *const [G; OUT_602]) }; __ret }, _ => aiur_fn_602(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_600] = { let __args: [G; IN_600] = [__v_14, __v_18, __v_2, __v_19, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[600].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[600].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[600].bump_multiplicity(__i); } let __ret: [G; OUT_600] = unsafe { *(record.function_queries[600].output_at(__i).as_ptr() as *const [G; OUT_600]) }; __ret }, _ => aiur_fn_600(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_606] = { let __args: [G; IN_606] = [__v_14, __v_18, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[606].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[606].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[606].bump_multiplicity(__i); } let __ret: [G; OUT_606] = unsafe { *(record.function_queries[606].output_at(__i).as_ptr() as *const [G; OUT_606]) }; __ret }, _ => aiur_fn_606(__args, record, io_buffer, __cu)? } }; let __mc_out___mc_0: [G; 0] = '__mc_0: { match __v_8.as_canonical_u64() { 0u64 => { let __v_26: G = G::from_u64(1); let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 3] = [__v_26, __v_27, __v_27]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_619] = { let __args: [G; IN_619] = [__v_14, __v_18, __v_5, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[619].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[619].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[619].bump_multiplicity(__i); } let __ret: [G; OUT_619] = unsafe { *(record.function_queries[619].output_at(__i).as_ptr() as *const [G; OUT_619]) }; __ret }, _ => aiur_fn_619(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_618] = { let __args: [G; IN_618] = [__v_14, __v_18, __v_5, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[618].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[618].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[618].bump_multiplicity(__i); } let __ret: [G; OUT_618] = unsafe { *(record.function_queries[618].output_at(__i).as_ptr() as *const [G; OUT_618]) }; __ret }, _ => aiur_fn_618(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, _ => { @@ -52531,9 +52485,9 @@ fn aiur_fn_621( }; let __v_26: G = G::from_u64(1); let __v_27: G = (__v_9 + __v_26); - let __r_arr: [G; OUT_621] = { let __args: [G; IN_621] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[621].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[621].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[621].bump_multiplicity(__i); } let __ret: [G; OUT_621] = unsafe { *(record.function_queries[621].output_at(__i).as_ptr() as *const [G; OUT_621]) }; __ret }, _ => aiur_fn_621(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_621] = []; - record.function_queries[621].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_620] = { let __args: [G; IN_620] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[620].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[620].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[620].bump_multiplicity(__i); } let __ret: [G; OUT_620] = unsafe { *(record.function_queries[620].output_at(__i).as_ptr() as *const [G; OUT_620]) }; __ret }, _ => aiur_fn_620(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_620] = []; + record.function_queries[620].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52545,15 +52499,15 @@ fn aiur_fn_621( }) } -const INPUT_SIZE_622: usize = 12; -const IN_622: usize = 12; -const OUT_622: usize = 0; -fn aiur_fn_622( - inp: [G; IN_622], +const INPUT_SIZE_621: usize = 12; +const IN_621: usize = 12; +const OUT_621: usize = 0; +fn aiur_fn_621( + inp: [G; IN_621], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_622], ExecError> { +) -> Result<[G; OUT_621], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52569,29 +52523,29 @@ fn aiur_fn_622( let __v_11: G = inp[11]; match __v_0.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_620] = { let __args: [G; IN_620] = [__v_2, __v_3, __v_4, __v_5, __v_1, __v_7, __v_8, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[620].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[620].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[620].bump_multiplicity(__i); } let __ret: [G; OUT_620] = unsafe { *(record.function_queries[620].output_at(__i).as_ptr() as *const [G; OUT_620]) }; __ret }, _ => aiur_fn_620(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_622] = []; - record.function_queries[622].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_619] = { let __args: [G; IN_619] = [__v_2, __v_3, __v_4, __v_5, __v_1, __v_7, __v_8, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[619].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[619].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[619].bump_multiplicity(__i); } let __ret: [G; OUT_619] = unsafe { *(record.function_queries[619].output_at(__i).as_ptr() as *const [G; OUT_619]) }; __ret }, _ => aiur_fn_619(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_621] = []; + record.function_queries[621].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_622] = []; - record.function_queries[622].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_621] = []; + record.function_queries[621].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_623: usize = 13; -const IN_623: usize = 13; -const OUT_623: usize = 0; -fn aiur_fn_623( - inp: [G; IN_623], +const INPUT_SIZE_622: usize = 13; +const IN_622: usize = 13; +const OUT_622: usize = 0; +fn aiur_fn_622( + inp: [G; IN_622], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_623], ExecError> { +) -> Result<[G; OUT_622], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52612,12 +52566,12 @@ fn aiur_fn_623( let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_623] = []; - record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_622] = []; + record.function_queries[622].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; @@ -52671,14 +52625,14 @@ fn aiur_fn_623( match __v_14.as_canonical_u64() { 8u64 => { let __v_62: G = G::from_u64(0); - let __r_arr: [G; OUT_624] = { let __args: [G; IN_624] = [__v_15, __v_2, __v_3, __v_4, __v_8, __v_62, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[624].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[624].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[624].bump_multiplicity(__i); } let __ret: [G; OUT_624] = unsafe { *(record.function_queries[624].output_at(__i).as_ptr() as *const [G; OUT_624]) }; __ret }, _ => aiur_fn_624(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_623] = []; - record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_623] = { let __args: [G; IN_623] = [__v_15, __v_2, __v_3, __v_4, __v_8, __v_62, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[623].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[623].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[623].bump_multiplicity(__i); } let __ret: [G; OUT_623] = unsafe { *(record.function_queries[623].output_at(__i).as_ptr() as *const [G; OUT_623]) }; __ret }, _ => aiur_fn_623(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_622] = []; + record.function_queries[622].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_623] = []; - record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_622] = []; + record.function_queries[622].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -52688,23 +52642,23 @@ fn aiur_fn_623( } }, _ => { - let __ret: [G; OUT_623] = []; - record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_622] = []; + record.function_queries[622].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_624: usize = 7; -const IN_624: usize = 7; -const OUT_624: usize = 0; -fn aiur_fn_624( - inp: [G; IN_624], +const INPUT_SIZE_623: usize = 7; +const IN_623: usize = 7; +const OUT_623: usize = 0; +fn aiur_fn_623( + inp: [G; IN_623], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_624], ExecError> { +) -> Result<[G; OUT_623], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52763,8 +52717,8 @@ fn aiur_fn_624( let __v_53: G = __loaded[46]; match __v_7.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_624] = []; - record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_623] = []; + record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -52776,13 +52730,13 @@ fn aiur_fn_624( 1u64 => { let __v_56: G = G::from_u64(1); let __v_57: G = (__v_5 + __v_56); - let __r_arr: [G; OUT_624] = { let __args: [G; IN_624] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_57, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[624].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[624].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[624].bump_multiplicity(__i); } let __ret: [G; OUT_624] = unsafe { *(record.function_queries[624].output_at(__i).as_ptr() as *const [G; OUT_624]) }; __ret }, _ => aiur_fn_624(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_624] = []; - record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_623] = { let __args: [G; IN_623] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_57, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[623].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[623].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[623].bump_multiplicity(__i); } let __ret: [G; OUT_623] = unsafe { *(record.function_queries[623].output_at(__i).as_ptr() as *const [G; OUT_623]) }; __ret }, _ => aiur_fn_623(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_623] = []; + record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_6, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_288] = { let __args: [G; IN_288] = [__v_6, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[288].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[288].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[288].bump_multiplicity(__i); } let __ret: [G; OUT_288] = unsafe { *(record.function_queries[288].output_at(__i).as_ptr() as *const [G; OUT_288]) }; __ret }, _ => aiur_fn_288(__args, record, io_buffer, __cu)? } }; let __v_56: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_56.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_57: G = __loaded[0]; @@ -52802,20 +52756,20 @@ fn aiur_fn_624( if (__v_60 != __v_2) { return Err(ExecError::AssertEqMismatch { lhs: __v_60.as_canonical_u64(), rhs: __v_2.as_canonical_u64(), msg: Some("mutual block peers disagree on parameter count".to_string()) }); } - let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_1, __v_59, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_602] = { let __args: [G; IN_602] = [__v_1, __v_59, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[602].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[602].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[602].bump_multiplicity(__i); } let __ret: [G; OUT_602] = unsafe { *(record.function_queries[602].output_at(__i).as_ptr() as *const [G; OUT_602]) }; __ret }, _ => aiur_fn_602(__args, record, io_buffer, __cu)? } }; let __v_69: G = (__v_2 + __v_3); let __v_70: G = G::from_u64(1); let __v_71: G = G::from_u64(1); let __v_72: G = { let __values: [G; 3] = [__v_70, __v_71, __v_71]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_1, __v_69, __v_72]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_1, __v_69, __v_72]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; let __v_73: G = __r_arr[0]; let __v_74: G = (__v_60 + __v_61); let __v_75: G = G::from_u64(1); let __v_76: G = G::from_u64(1); let __v_77: G = { let __values: [G; 3] = [__v_75, __v_76, __v_76]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_59, __v_74, __v_77]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_59, __v_74, __v_77]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; let __v_78: G = __r_arr[0]; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_73, __v_78]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_73, __v_78]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_79: G = __r_arr[0]; let __v_80: G = G::from_u64(1); if (__v_79 != __v_80) { @@ -52823,17 +52777,17 @@ fn aiur_fn_624( } let __v_81: G = G::from_u64(1); let __v_82: G = (__v_5 + __v_81); - let __r_arr: [G; OUT_624] = { let __args: [G; IN_624] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_82, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[624].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[624].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[624].bump_multiplicity(__i); } let __ret: [G; OUT_624] = unsafe { *(record.function_queries[624].output_at(__i).as_ptr() as *const [G; OUT_624]) }; __ret }, _ => aiur_fn_624(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_624] = []; - record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_623] = { let __args: [G; IN_623] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_82, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[623].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[623].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[623].bump_multiplicity(__i); } let __ret: [G; OUT_623] = unsafe { *(record.function_queries[623].output_at(__i).as_ptr() as *const [G; OUT_623]) }; __ret }, _ => aiur_fn_623(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_623] = []; + record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_69: G = G::from_u64(1); let __v_70: G = (__v_5 + __v_69); - let __r_arr: [G; OUT_624] = { let __args: [G; IN_624] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_70, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[624].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[624].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[624].bump_multiplicity(__i); } let __ret: [G; OUT_624] = unsafe { *(record.function_queries[624].output_at(__i).as_ptr() as *const [G; OUT_624]) }; __ret }, _ => aiur_fn_624(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_624] = []; - record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_623] = { let __args: [G; IN_623] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_70, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[623].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[623].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[623].bump_multiplicity(__i); } let __ret: [G; OUT_623] = unsafe { *(record.function_queries[623].output_at(__i).as_ptr() as *const [G; OUT_623]) }; __ret }, _ => aiur_fn_623(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_623] = []; + record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -52843,9 +52797,9 @@ fn aiur_fn_624( _ => { let __v_54: G = G::from_u64(1); let __v_55: G = (__v_5 + __v_54); - let __r_arr: [G; OUT_624] = { let __args: [G; IN_624] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_55, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[624].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[624].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[624].bump_multiplicity(__i); } let __ret: [G; OUT_624] = unsafe { *(record.function_queries[624].output_at(__i).as_ptr() as *const [G; OUT_624]) }; __ret }, _ => aiur_fn_624(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_624] = []; - record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_623] = { let __args: [G; IN_623] = [__v_53, __v_1, __v_2, __v_3, __v_4, __v_55, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[623].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[623].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[623].bump_multiplicity(__i); } let __ret: [G; OUT_623] = unsafe { *(record.function_queries[623].output_at(__i).as_ptr() as *const [G; OUT_623]) }; __ret }, _ => aiur_fn_623(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_623] = []; + record.function_queries[623].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -52857,15 +52811,15 @@ fn aiur_fn_624( }) } -const INPUT_SIZE_625: usize = 16; -const IN_625: usize = 16; -const OUT_625: usize = 1; -fn aiur_fn_625( - inp: [G; IN_625], +const INPUT_SIZE_624: usize = 16; +const IN_624: usize = 16; +const OUT_624: usize = 1; +fn aiur_fn_624( + inp: [G; IN_624], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_625], ExecError> { +) -> Result<[G; OUT_624], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52883,37 +52837,37 @@ fn aiur_fn_625( let __v_13: G = inp[13]; let __v_14: G = inp[14]; let __v_15: G = inp[15]; - let __r_arr: [G; OUT_297] = { let __args: [G; IN_297] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[297].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[297].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[297].bump_multiplicity(__i); } let __ret: [G; OUT_297] = unsafe { *(record.function_queries[297].output_at(__i).as_ptr() as *const [G; OUT_297]) }; __ret }, _ => aiur_fn_297(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_296] = { let __args: [G; IN_296] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[296].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[296].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[296].bump_multiplicity(__i); } let __ret: [G; OUT_296] = unsafe { *(record.function_queries[296].output_at(__i).as_ptr() as *const [G; OUT_296]) }; __ret }, _ => aiur_fn_296(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; match __v_16.as_canonical_u64() { 1u64 => { let __v_17: G = G::from_u64(1); - let __ret: [G; OUT_625] = [__v_17]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_17]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { match __v_15.as_canonical_u64() { 0u64 => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_625] = [__v_17]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_17]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { match __v_1.as_canonical_u64() { 0u64 => { let __v_17: G = G::from_u64(1); - let __ret: [G; OUT_625] = [__v_17]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_17]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { match __v_2.as_canonical_u64() { 0u64 => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_625] = [__v_17]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_17]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -52922,26 +52876,26 @@ fn aiur_fn_625( match __v_10.as_canonical_u64() { 0u64 => { let __v_17: G = G::from_u64(1); - let __ret: [G; OUT_625] = [__v_17]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_17]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_17: G = G::from_u64(1); let __v_18: G = G::from_u64(1); let __v_19: G = { let __values: [G; 3] = [__v_17, __v_18, __v_18]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_626] = { let __args: [G; IN_626] = [__v_5, __v_9, __v_10, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[626].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[626].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[626].bump_multiplicity(__i); } let __ret: [G; OUT_626] = unsafe { *(record.function_queries[626].output_at(__i).as_ptr() as *const [G; OUT_626]) }; __ret }, _ => aiur_fn_626(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_625] = { let __args: [G; IN_625] = [__v_5, __v_9, __v_10, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[625].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[625].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[625].bump_multiplicity(__i); } let __ret: [G; OUT_625] = unsafe { *(record.function_queries[625].output_at(__i).as_ptr() as *const [G; OUT_625]) }; __ret }, _ => aiur_fn_625(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __ret: [G; OUT_625] = [__v_20]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_20]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_625] = [__v_17]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_17]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -52950,8 +52904,8 @@ fn aiur_fn_625( }, _ => { let __v_17: G = G::from_u64(0); - let __ret: [G; OUT_625] = [__v_17]; - record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_624] = [__v_17]; + record.function_queries[624].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -52962,15 +52916,15 @@ fn aiur_fn_625( }) } -const INPUT_SIZE_626: usize = 4; -const IN_626: usize = 4; -const OUT_626: usize = 1; -fn aiur_fn_626( - inp: [G; IN_626], +const INPUT_SIZE_625: usize = 4; +const IN_625: usize = 4; +const OUT_625: usize = 1; +fn aiur_fn_625( + inp: [G; IN_625], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_626], ExecError> { +) -> Result<[G; OUT_625], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -52982,10 +52936,10 @@ fn aiur_fn_626( let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_627] = { let __args: [G; IN_627] = [__v_0, __v_2, __v_4, __v_3, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[627].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[627].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[627].bump_multiplicity(__i); } let __ret: [G; OUT_627] = unsafe { *(record.function_queries[627].output_at(__i).as_ptr() as *const [G; OUT_627]) }; __ret }, _ => aiur_fn_627(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_626] = { let __args: [G; IN_626] = [__v_0, __v_2, __v_4, __v_3, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[626].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[626].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[626].bump_multiplicity(__i); } let __ret: [G; OUT_626] = unsafe { *(record.function_queries[626].output_at(__i).as_ptr() as *const [G; OUT_626]) }; __ret }, _ => aiur_fn_626(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_626] = [__v_8]; - record.function_queries[626].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_625] = [__v_8]; + record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -53000,16 +52954,16 @@ fn aiur_fn_626( let __v_9: G = { let __values: [G; 3] = [__v_8, __v_5, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_10: G = G::from_u64(1); let __v_11: G = (__v_1 - __v_10); - let __r_arr: [G; OUT_626] = { let __args: [G; IN_626] = [__v_6, __v_11, __v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[626].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[626].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[626].bump_multiplicity(__i); } let __ret: [G; OUT_626] = unsafe { *(record.function_queries[626].output_at(__i).as_ptr() as *const [G; OUT_626]) }; __ret }, _ => aiur_fn_626(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_625] = { let __args: [G; IN_625] = [__v_6, __v_11, __v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[625].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[625].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[625].bump_multiplicity(__i); } let __ret: [G; OUT_625] = unsafe { *(record.function_queries[625].output_at(__i).as_ptr() as *const [G; OUT_625]) }; __ret }, _ => aiur_fn_625(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_626] = [__v_12]; - record.function_queries[626].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_625] = [__v_12]; + record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_626] = [__v_8]; - record.function_queries[626].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_625] = [__v_8]; + record.function_queries[625].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53018,15 +52972,15 @@ fn aiur_fn_626( }) } -const INPUT_SIZE_627: usize = 5; -const IN_627: usize = 5; -const OUT_627: usize = 1; -fn aiur_fn_627( - inp: [G; IN_627], +const INPUT_SIZE_626: usize = 5; +const IN_626: usize = 5; +const OUT_626: usize = 1; +fn aiur_fn_626( + inp: [G; IN_626], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_627], ExecError> { +) -> Result<[G; OUT_626], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53039,10 +52993,10 @@ fn aiur_fn_627( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; - let __r_arr: [G; OUT_628] = { let __args: [G; IN_628] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[628].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[628].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[628].bump_multiplicity(__i); } let __ret: [G; OUT_628] = unsafe { *(record.function_queries[628].output_at(__i).as_ptr() as *const [G; OUT_628]) }; __ret }, _ => aiur_fn_628(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_627] = { let __args: [G; IN_627] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[627].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[627].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[627].bump_multiplicity(__i); } let __ret: [G; OUT_627] = unsafe { *(record.function_queries[627].output_at(__i).as_ptr() as *const [G; OUT_627]) }; __ret }, _ => aiur_fn_627(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_627] = [__v_8]; - record.function_queries[627].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_626] = [__v_8]; + record.function_queries[626].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -53053,13 +53007,13 @@ fn aiur_fn_627( let __v_9: G = __loaded[3]; match __v_6.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_7, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(1); let __v_12: G = G::from_u64(0); let __v_13: G = G::from_u64(0); let __v_14: G = { let __values: [G; 3] = [__v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_10, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_10, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = (__v_11 - __v_15); let __v_17: G = G::from_u64(1); @@ -53081,16 +53035,16 @@ fn aiur_fn_627( let __v_22: G = { let __values: [G; 3] = [__v_21, __v_7, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_23: G = G::from_u64(1); let __v_24: G = (__v_2 + __v_23); - let __r_arr: [G; OUT_627] = { let __args: [G; IN_627] = [__v_8, __v_1, __v_24, __v_22, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[627].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[627].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[627].bump_multiplicity(__i); } let __ret: [G; OUT_627] = unsafe { *(record.function_queries[627].output_at(__i).as_ptr() as *const [G; OUT_627]) }; __ret }, _ => aiur_fn_627(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_626] = { let __args: [G; IN_626] = [__v_8, __v_1, __v_24, __v_22, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[626].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[626].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[626].bump_multiplicity(__i); } let __ret: [G; OUT_626] = unsafe { *(record.function_queries[626].output_at(__i).as_ptr() as *const [G; OUT_626]) }; __ret }, _ => aiur_fn_626(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __ret: [G; OUT_627] = [__v_25]; - record.function_queries[627].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_626] = [__v_25]; + record.function_queries[626].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_627] = [__v_10]; - record.function_queries[627].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_626] = [__v_10]; + record.function_queries[626].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53099,15 +53053,15 @@ fn aiur_fn_627( }) } -const INPUT_SIZE_628: usize = 2; -const IN_628: usize = 2; -const OUT_628: usize = 1; -fn aiur_fn_628( - inp: [G; IN_628], +const INPUT_SIZE_627: usize = 2; +const IN_627: usize = 2; +const OUT_627: usize = 1; +fn aiur_fn_627( + inp: [G; IN_627], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_628], ExecError> { +) -> Result<[G; OUT_627], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53118,25 +53072,25 @@ fn aiur_fn_628( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_628] = [__v_5]; - record.function_queries[628].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_627] = [__v_5]; + record.function_queries[627].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_629] = { let __args: [G; IN_629] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[629].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[629].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[629].bump_multiplicity(__i); } let __ret: [G; OUT_629] = unsafe { *(record.function_queries[629].output_at(__i).as_ptr() as *const [G; OUT_629]) }; __ret }, _ => aiur_fn_629(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_628] = { let __args: [G; IN_628] = [__v_1, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[628].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[628].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[628].bump_multiplicity(__i); } let __ret: [G; OUT_628] = unsafe { *(record.function_queries[628].output_at(__i).as_ptr() as *const [G; OUT_628]) }; __ret }, _ => aiur_fn_628(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; match __v_5.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_628] = [__v_6]; - record.function_queries[628].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_627] = [__v_6]; + record.function_queries[627].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_628] = { let __args: [G; IN_628] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[628].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[628].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[628].bump_multiplicity(__i); } let __ret: [G; OUT_628] = unsafe { *(record.function_queries[628].output_at(__i).as_ptr() as *const [G; OUT_628]) }; __ret }, _ => aiur_fn_628(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_627] = { let __args: [G; IN_627] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[627].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[627].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[627].bump_multiplicity(__i); } let __ret: [G; OUT_627] = unsafe { *(record.function_queries[627].output_at(__i).as_ptr() as *const [G; OUT_627]) }; __ret }, _ => aiur_fn_627(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_628] = [__v_6]; - record.function_queries[628].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_627] = [__v_6]; + record.function_queries[627].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53148,15 +53102,15 @@ fn aiur_fn_628( }) } -const INPUT_SIZE_629: usize = 2; -const IN_629: usize = 2; -const OUT_629: usize = 1; -fn aiur_fn_629( - inp: [G; IN_629], +const INPUT_SIZE_628: usize = 2; +const IN_628: usize = 2; +const OUT_628: usize = 1; +fn aiur_fn_628( + inp: [G; IN_628], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_629], ExecError> { +) -> Result<[G; OUT_628], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53167,8 +53121,8 @@ fn aiur_fn_629( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_629] = [__v_5]; - record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_628] = [__v_5]; + record.function_queries[628].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -53183,24 +53137,24 @@ fn aiur_fn_629( match __v_9.as_canonical_u64() { 0u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_629] = [__v_10]; - record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_628] = [__v_10]; + record.function_queries[628].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_629] = { let __args: [G; IN_629] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[629].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[629].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[629].bump_multiplicity(__i); } let __ret: [G; OUT_629] = unsafe { *(record.function_queries[629].output_at(__i).as_ptr() as *const [G; OUT_629]) }; __ret }, _ => aiur_fn_629(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_628] = { let __args: [G; IN_628] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[628].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[628].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[628].bump_multiplicity(__i); } let __ret: [G; OUT_628] = unsafe { *(record.function_queries[628].output_at(__i).as_ptr() as *const [G; OUT_628]) }; __ret }, _ => aiur_fn_628(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_629] = [__v_10]; - record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_628] = [__v_10]; + record.function_queries[628].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_629] = { let __args: [G; IN_629] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[629].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[629].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[629].bump_multiplicity(__i); } let __ret: [G; OUT_629] = unsafe { *(record.function_queries[629].output_at(__i).as_ptr() as *const [G; OUT_629]) }; __ret }, _ => aiur_fn_629(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_628] = { let __args: [G; IN_628] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[628].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[628].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[628].bump_multiplicity(__i); } let __ret: [G; OUT_628] = unsafe { *(record.function_queries[628].output_at(__i).as_ptr() as *const [G; OUT_628]) }; __ret }, _ => aiur_fn_628(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_629] = [__v_9]; - record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_628] = [__v_9]; + record.function_queries[628].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53212,15 +53166,15 @@ fn aiur_fn_629( }) } -const INPUT_SIZE_630: usize = 13; -const IN_630: usize = 13; -const OUT_630: usize = 1; -fn aiur_fn_630( - inp: [G; IN_630], +const INPUT_SIZE_629: usize = 13; +const IN_629: usize = 13; +const OUT_629: usize = 1; +fn aiur_fn_629( + inp: [G; IN_629], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_630], ExecError> { +) -> Result<[G; OUT_629], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53237,13 +53191,13 @@ fn aiur_fn_630( let __v_12: G = inp[12]; match __v_0.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_631] = { let __args: [G; IN_631] = [__v_7, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[631].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[631].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[631].bump_multiplicity(__i); } let __ret: [G; OUT_631] = unsafe { *(record.function_queries[631].output_at(__i).as_ptr() as *const [G; OUT_631]) }; __ret }, _ => aiur_fn_631(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_630] = { let __args: [G; IN_630] = [__v_7, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[630].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[630].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[630].bump_multiplicity(__i); } let __ret: [G; OUT_630] = unsafe { *(record.function_queries[630].output_at(__i).as_ptr() as *const [G; OUT_630]) }; __ret }, _ => aiur_fn_630(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_13.as_canonical_u64() { 0u64 => { let __v_14: G = G::from_u64(0); - let __ret: [G; OUT_630] = [__v_14]; - record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_629] = [__v_14]; + record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -53251,25 +53205,25 @@ fn aiur_fn_630( let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_2, __v_14, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_2, __v_14, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = G::from_u64(0); let __v_20: G = G::from_u64(0); let __v_21: G = { let __values: [G; 3] = [__v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_18, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_18, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; match __v_22.as_canonical_u64() { 0u64 => { let __v_23: G = G::from_u64(0); - let __ret: [G; OUT_630] = [__v_23]; - record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_629] = [__v_23]; + record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { match __v_5.as_canonical_u64() { 1u64 => { let __v_23: G = G::from_u64(0); - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_7, __v_8, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_7, __v_8, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_24.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_25: G = __loaded[0]; @@ -53287,22 +53241,22 @@ fn aiur_fn_630( match __v_25.as_canonical_u64() { 6u64 => { let __v_37: G = G::from_bool((__v_32 == G::ZERO)); - let __ret: [G; OUT_630] = [__v_37]; - record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_629] = [__v_37]; + record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_37: G = G::from_u64(0); - let __ret: [G; OUT_630] = [__v_37]; - record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_629] = [__v_37]; + record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_23: G = G::from_u64(0); - let __ret: [G; OUT_630] = [__v_23]; - record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_629] = [__v_23]; + record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53313,23 +53267,23 @@ fn aiur_fn_630( }, _ => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_630] = [__v_13]; - record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_629] = [__v_13]; + record.function_queries[629].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_631: usize = 2; -const IN_631: usize = 2; -const OUT_631: usize = 1; -fn aiur_fn_631( - inp: [G; IN_631], +const INPUT_SIZE_630: usize = 2; +const IN_630: usize = 2; +const OUT_630: usize = 1; +fn aiur_fn_630( + inp: [G; IN_630], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_631], ExecError> { +) -> Result<[G; OUT_630], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53338,12 +53292,12 @@ fn aiur_fn_631( match __v_2.as_canonical_u64() { 1u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_631] = [__v_3]; - record.function_queries[631].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_630] = [__v_3]; + record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = __r_arr[2]; @@ -53397,16 +53351,16 @@ fn aiur_fn_631( match __v_3.as_canonical_u64() { 8u64 => { let __v_51: G = G::from_u64(0); - let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_4, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_4, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __ret: [G; OUT_631] = [__v_52]; - record.function_queries[631].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_630] = [__v_52]; + record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_51: G = G::from_u64(0); - let __ret: [G; OUT_631] = [__v_51]; - record.function_queries[631].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_630] = [__v_51]; + record.function_queries[630].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53417,18 +53371,18 @@ fn aiur_fn_631( }) } -const INPUT_SIZE_632: usize = 1; -const IN_632: usize = 1; -const OUT_632: usize = 1; -fn aiur_fn_632( - inp: [G; IN_632], +const INPUT_SIZE_631: usize = 1; +const IN_631: usize = 1; +const OUT_631: usize = 1; +fn aiur_fn_631( + inp: [G; IN_631], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_632], ExecError> { +) -> Result<[G; OUT_631], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = __r_arr[1]; let __v_3: G = __r_arr[2]; @@ -53482,14 +53436,14 @@ fn aiur_fn_632( match __v_1.as_canonical_u64() { 8u64 => { let __v_49: G = G::from_u64(1); - let __ret: [G; OUT_632] = [__v_49]; - record.function_queries[632].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_631] = [__v_49]; + record.function_queries[631].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_49: G = G::from_u64(0); - let __ret: [G; OUT_632] = [__v_49]; - record.function_queries[632].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_631] = [__v_49]; + record.function_queries[631].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53498,15 +53452,15 @@ fn aiur_fn_632( }) } -const INPUT_SIZE_633: usize = 2; -const IN_633: usize = 2; -const OUT_633: usize = 1; -fn aiur_fn_633( - inp: [G; IN_633], +const INPUT_SIZE_632: usize = 2; +const IN_632: usize = 2; +const OUT_632: usize = 1; +fn aiur_fn_632( + inp: [G; IN_632], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_633], ExecError> { +) -> Result<[G; OUT_632], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53563,14 +53517,14 @@ fn aiur_fn_633( match __v_1.as_canonical_u64() { 1u64 => { let __v_49: G = G::from_u64(1); - let __ret: [G; OUT_633] = [__v_49]; - record.function_queries[633].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_632] = [__v_49]; + record.function_queries[632].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_49: G = G::from_u64(0); - let __ret: [G; OUT_633] = [__v_49]; - record.function_queries[633].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_632] = [__v_49]; + record.function_queries[632].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53580,17 +53534,17 @@ fn aiur_fn_633( 1u64 => { let __v_49: G = G::from_u64(1); let __v_50: G = (__v_1 + __v_49); - let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_48, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_48, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __ret: [G; OUT_633] = [__v_51]; - record.function_queries[633].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_632] = [__v_51]; + record.function_queries[632].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_48, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_48, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __ret: [G; OUT_633] = [__v_49]; - record.function_queries[633].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_632] = [__v_49]; + record.function_queries[632].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53602,15 +53556,15 @@ fn aiur_fn_633( }) } -const INPUT_SIZE_634: usize = 5; -const IN_634: usize = 5; -const OUT_634: usize = 1; -fn aiur_fn_634( - inp: [G; IN_634], +const INPUT_SIZE_633: usize = 5; +const IN_633: usize = 5; +const OUT_633: usize = 1; +fn aiur_fn_633( + inp: [G; IN_633], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_634], ExecError> { +) -> Result<[G; OUT_633], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53620,7 +53574,7 @@ fn aiur_fn_634( let __v_5: G = (__v_3 + __v_4); let __v_6: G = (__v_2 + __v_5); let __v_7: G = (__v_1 + __v_6); - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_0, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_8.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_9: G = __loaded[0]; @@ -53639,8 +53593,8 @@ fn aiur_fn_634( let __v_18: G = __loaded[3]; match __v_15.as_canonical_u64() { 2u64 => { - let __ret: [G; OUT_634] = [__v_16]; - record.function_queries[634].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_633] = [__v_16]; + record.function_queries[633].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -53655,15 +53609,15 @@ fn aiur_fn_634( }) } -const INPUT_SIZE_635: usize = 12; -const IN_635: usize = 12; -const OUT_635: usize = 1; -fn aiur_fn_635( - inp: [G; IN_635], +const INPUT_SIZE_634: usize = 12; +const IN_634: usize = 12; +const OUT_634: usize = 1; +fn aiur_fn_634( + inp: [G; IN_634], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_635], ExecError> { +) -> Result<[G; OUT_634], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53682,7 +53636,7 @@ fn aiur_fn_635( let __v_12: G = (__v_3 + __v_5); let __v_13: G = (__v_12 + __v_6); let __v_14: G = (__v_13 + __v_4); - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_2, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_2, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_15.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_16: G = __loaded[0]; @@ -53701,16 +53655,16 @@ fn aiur_fn_635( let __v_25: G = __loaded[3]; match __v_22.as_canonical_u64() { 2u64 => { - let __ret: [G; OUT_635] = [__v_24]; - record.function_queries[635].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_634] = [__v_24]; + record.function_queries[634].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_26: G = G::from_u64(1); let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 3] = [__v_26, __v_27, __v_27]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_635] = [__v_28]; - record.function_queries[635].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_634] = [__v_28]; + record.function_queries[634].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53719,8 +53673,8 @@ fn aiur_fn_635( let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 3] = [__v_20, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_635] = [__v_22]; - record.function_queries[635].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_634] = [__v_22]; + record.function_queries[634].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -53729,23 +53683,23 @@ fn aiur_fn_635( let __v_12: G = G::from_u64(1); let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 3] = [__v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_635] = [__v_14]; - record.function_queries[635].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_634] = [__v_14]; + record.function_queries[634].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_636: usize = 6; -const IN_636: usize = 6; -const OUT_636: usize = 1; -fn aiur_fn_636( - inp: [G; IN_636], +const INPUT_SIZE_635: usize = 6; +const IN_635: usize = 6; +const OUT_635: usize = 1; +fn aiur_fn_635( + inp: [G; IN_635], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_636], ExecError> { +) -> Result<[G; OUT_635], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53756,7 +53710,7 @@ fn aiur_fn_636( let __v_6: G = (__v_3 + __v_4); let __v_7: G = (__v_2 + __v_6); let __v_8: G = (__v_1 + __v_7); - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_9.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -53768,14 +53722,14 @@ fn aiur_fn_636( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_15, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_15, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = (__v_2 + __v_3); let __v_18: G = (__v_17 + __v_4); - let __r_arr: [G; OUT_637] = { let __args: [G; IN_637] = [__v_16, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[637].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[637].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[637].bump_multiplicity(__i); } let __ret: [G; OUT_637] = unsafe { *(record.function_queries[637].output_at(__i).as_ptr() as *const [G; OUT_637]) }; __ret }, _ => aiur_fn_637(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_636] = { let __args: [G; IN_636] = [__v_16, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[636].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[636].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[636].bump_multiplicity(__i); } let __ret: [G; OUT_636] = unsafe { *(record.function_queries[636].output_at(__i).as_ptr() as *const [G; OUT_636]) }; __ret }, _ => aiur_fn_636(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __ret: [G; OUT_636] = [__v_19]; - record.function_queries[636].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_635] = [__v_19]; + record.function_queries[635].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -53785,15 +53739,15 @@ fn aiur_fn_636( }) } -const INPUT_SIZE_637: usize = 2; -const IN_637: usize = 2; -const OUT_637: usize = 1; -fn aiur_fn_637( - inp: [G; IN_637], +const INPUT_SIZE_636: usize = 2; +const IN_636: usize = 2; +const OUT_636: usize = 1; +fn aiur_fn_636( + inp: [G; IN_636], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_637], ExecError> { +) -> Result<[G; OUT_636], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53806,13 +53760,13 @@ fn aiur_fn_637( let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_637] = [__v_7]; - record.function_queries[637].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_636] = [__v_7]; + record.function_queries[636].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_346] = { let __args: [G; IN_346] = [__v_3, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[346].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[346].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[346].bump_multiplicity(__i); } let __ret: [G; OUT_346] = unsafe { *(record.function_queries[346].output_at(__i).as_ptr() as *const [G; OUT_346]) }; __ret }, _ => aiur_fn_346(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_345] = { let __args: [G; IN_345] = [__v_3, __v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[345].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[345].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[345].bump_multiplicity(__i); } let __ret: [G; OUT_345] = unsafe { *(record.function_queries[345].output_at(__i).as_ptr() as *const [G; OUT_345]) }; __ret }, _ => aiur_fn_345(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); if (__v_6 != __v_7) { @@ -53820,13 +53774,13 @@ fn aiur_fn_637( } let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_362] = { let __args: [G; IN_362] = [__v_3, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[362].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[362].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[362].bump_multiplicity(__i); } let __ret: [G; OUT_362] = unsafe { *(record.function_queries[362].output_at(__i).as_ptr() as *const [G; OUT_362]) }; __ret }, _ => aiur_fn_362(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_361] = { let __args: [G; IN_361] = [__v_3, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[361].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[361].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[361].bump_multiplicity(__i); } let __ret: [G; OUT_361] = unsafe { *(record.function_queries[361].output_at(__i).as_ptr() as *const [G; OUT_361]) }; __ret }, _ => aiur_fn_361(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_637] = { let __args: [G; IN_637] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[637].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[637].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[637].bump_multiplicity(__i); } let __ret: [G; OUT_637] = unsafe { *(record.function_queries[637].output_at(__i).as_ptr() as *const [G; OUT_637]) }; __ret }, _ => aiur_fn_637(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_636] = { let __args: [G; IN_636] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[636].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[636].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[636].bump_multiplicity(__i); } let __ret: [G; OUT_636] = unsafe { *(record.function_queries[636].output_at(__i).as_ptr() as *const [G; OUT_636]) }; __ret }, _ => aiur_fn_636(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = { let __values: [G; 3] = [__v_8, __v_10, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_637] = [__v_12]; - record.function_queries[637].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_636] = [__v_12]; + record.function_queries[636].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -53836,15 +53790,15 @@ fn aiur_fn_637( }) } -const INPUT_SIZE_638: usize = 3; -const IN_638: usize = 3; -const OUT_638: usize = 1; -fn aiur_fn_638( - inp: [G; IN_638], +const INPUT_SIZE_637: usize = 3; +const IN_637: usize = 3; +const OUT_637: usize = 1; +fn aiur_fn_637( + inp: [G; IN_637], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_638], ExecError> { +) -> Result<[G; OUT_637], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -53855,8 +53809,8 @@ fn aiur_fn_638( let __v_4: G = G::from_u64(1); let __v_5: G = G::from_u64(1); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_638] = [__v_6]; - record.function_queries[638].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_637] = [__v_6]; + record.function_queries[637].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -53867,30 +53821,30 @@ fn aiur_fn_638( let __v_8: G = { let __values: [G; 3] = [__v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_9: G = G::from_u64(1); let __v_10: G = (__v_2 + __v_9); - let __r_arr: [G; OUT_638] = { let __args: [G; IN_638] = [__v_0, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[638].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[638].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[638].bump_multiplicity(__i); } let __ret: [G; OUT_638] = unsafe { *(record.function_queries[638].output_at(__i).as_ptr() as *const [G; OUT_638]) }; __ret }, _ => aiur_fn_638(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_637] = { let __args: [G; IN_637] = [__v_0, __v_1, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[637].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[637].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[637].bump_multiplicity(__i); } let __ret: [G; OUT_637] = unsafe { *(record.function_queries[637].output_at(__i).as_ptr() as *const [G; OUT_637]) }; __ret }, _ => aiur_fn_637(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = { let __values: [G; 3] = [__v_4, __v_8, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_638] = [__v_12]; - record.function_queries[638].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_637] = [__v_12]; + record.function_queries[637].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_639: usize = 2; -const IN_639: usize = 2; -const OUT_639: usize = 1; -fn aiur_fn_639( - inp: [G; IN_639], +const INPUT_SIZE_638: usize = 2; +const IN_638: usize = 2; +const OUT_638: usize = 1; +fn aiur_fn_638( + inp: [G; IN_638], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_639], ExecError> { +) -> Result<[G; OUT_638], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -53944,14 +53898,14 @@ fn aiur_fn_639( match __v_2.as_canonical_u64() { 8u64 => { let __v_50: G = G::from_u64(0); - let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_3, __v_3, __v_0, __v_1, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_639] = { let __args: [G; IN_639] = [__v_3, __v_3, __v_0, __v_1, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[639].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[639].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[639].bump_multiplicity(__i); } let __ret: [G; OUT_639] = unsafe { *(record.function_queries[639].output_at(__i).as_ptr() as *const [G; OUT_639]) }; __ret }, _ => aiur_fn_639(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __ret: [G; OUT_639] = [__v_51]; - record.function_queries[639].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_638] = [__v_51]; + record.function_queries[638].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_50.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_51: G = __loaded[0]; @@ -53969,7 +53923,7 @@ fn aiur_fn_639( match __v_51.as_canonical_u64() { 5u64 => { let __v_63: G = G::from_u64(0); - let __r_arr: [G; OUT_638] = { let __args: [G; IN_638] = [__v_1, __v_52, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[638].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[638].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[638].bump_multiplicity(__i); } let __ret: [G; OUT_638] = unsafe { *(record.function_queries[638].output_at(__i).as_ptr() as *const [G; OUT_638]) }; __ret }, _ => aiur_fn_638(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_637] = { let __args: [G; IN_637] = [__v_1, __v_52, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[637].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[637].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[637].bump_multiplicity(__i); } let __ret: [G; OUT_637] = unsafe { *(record.function_queries[637].output_at(__i).as_ptr() as *const [G; OUT_637]) }; __ret }, _ => aiur_fn_637(__args, record, io_buffer, __cu)? } }; let __v_64: G = __r_arr[0]; let __v_65: G = G::from_u64(0); let __v_66: G = G::from_u64(0); @@ -53980,16 +53934,16 @@ fn aiur_fn_639( let __v_71: G = G::from_u64(1); let __v_72: G = { let __values: [G; 6] = [__v_70, __v_71, __v_71, __v_71, __v_71, __v_71]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_73: G = { let __values: [G; 6] = [__v_65, __v_0, __v_66, __v_69, __v_64, __v_72]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_639] = [__v_73]; - record.function_queries[639].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_638] = [__v_73]; + record.function_queries[638].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_63: G = G::from_u64(1); let __v_64: G = G::from_u64(1); let __v_65: G = { let __values: [G; 6] = [__v_63, __v_64, __v_64, __v_64, __v_64, __v_64]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_639] = [__v_65]; - record.function_queries[639].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_638] = [__v_65]; + record.function_queries[638].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54000,15 +53954,15 @@ fn aiur_fn_639( }) } -const INPUT_SIZE_640: usize = 5; -const IN_640: usize = 5; -const OUT_640: usize = 1; -fn aiur_fn_640( - inp: [G; IN_640], +const INPUT_SIZE_639: usize = 5; +const IN_639: usize = 5; +const OUT_639: usize = 1; +fn aiur_fn_639( + inp: [G; IN_639], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_640], ExecError> { +) -> Result<[G; OUT_639], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -54068,16 +54022,16 @@ fn aiur_fn_640( let __v_52: G = G::from_u64(1); let __v_53: G = G::from_u64(1); let __v_54: G = { let __values: [G; 6] = [__v_52, __v_53, __v_53, __v_53, __v_53, __v_53]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_640] = [__v_54]; - record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_639] = [__v_54]; + record.function_queries[639].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_0, __v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_0, __v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_288] = { let __args: [G; IN_288] = [__v_2, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[288].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[288].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[288].bump_multiplicity(__i); } let __ret: [G; OUT_288] = unsafe { *(record.function_queries[288].output_at(__i).as_ptr() as *const [G; OUT_288]) }; __ret }, _ => aiur_fn_288(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_53.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_54: G = __loaded[0]; @@ -54104,7 +54058,7 @@ fn aiur_fn_640( }; let __v_66: G = __mc_out___mc_0[0]; let __v_67: G = G::from_u64(0); - let __r_arr: [G; OUT_638] = { let __args: [G; IN_638] = [__v_3, __v_66, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[638].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[638].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[638].bump_multiplicity(__i); } let __ret: [G; OUT_638] = unsafe { *(record.function_queries[638].output_at(__i).as_ptr() as *const [G; OUT_638]) }; __ret }, _ => aiur_fn_638(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_637] = { let __args: [G; IN_637] = [__v_3, __v_66, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[637].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[637].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[637].bump_multiplicity(__i); } let __ret: [G; OUT_637] = unsafe { *(record.function_queries[637].output_at(__i).as_ptr() as *const [G; OUT_637]) }; __ret }, _ => aiur_fn_637(__args, record, io_buffer, __cu)? } }; let __v_68: G = __r_arr[0]; let __v_69: G = G::from_u64(0); let __v_70: G = G::from_u64(0); @@ -54113,20 +54067,20 @@ fn aiur_fn_640( let __v_73: G = { let __values: [G; 3] = [__v_71, __v_72, __v_72]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_74: G = G::from_u64(1); let __v_75: G = (__v_4 + __v_74); - let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_0, __v_51, __v_2, __v_3, __v_75]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_639] = { let __args: [G; IN_639] = [__v_0, __v_51, __v_2, __v_3, __v_75]; let __cu = unconstrained; let __hit = record.function_queries[639].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[639].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[639].bump_multiplicity(__i); } let __ret: [G; OUT_639] = unsafe { *(record.function_queries[639].output_at(__i).as_ptr() as *const [G; OUT_639]) }; __ret }, _ => aiur_fn_639(__args, record, io_buffer, __cu)? } }; let __v_76: G = __r_arr[0]; let __v_77: G = { let __values: [G; 6] = [__v_69, __v_52, __v_70, __v_73, __v_68, __v_76]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_640] = [__v_77]; - record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_639] = [__v_77]; + record.function_queries[639].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_52: G = G::from_u64(1); let __v_53: G = (__v_4 + __v_52); - let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_0, __v_51, __v_2, __v_3, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_639] = { let __args: [G; IN_639] = [__v_0, __v_51, __v_2, __v_3, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[639].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[639].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[639].bump_multiplicity(__i); } let __ret: [G; OUT_639] = unsafe { *(record.function_queries[639].output_at(__i).as_ptr() as *const [G; OUT_639]) }; __ret }, _ => aiur_fn_639(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; - let __ret: [G; OUT_640] = [__v_54]; - record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_639] = [__v_54]; + record.function_queries[639].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54138,15 +54092,15 @@ fn aiur_fn_640( }) } -const INPUT_SIZE_641: usize = 3; -const IN_641: usize = 3; -const OUT_641: usize = 1; -fn aiur_fn_641( - inp: [G; IN_641], +const INPUT_SIZE_640: usize = 3; +const IN_640: usize = 3; +const OUT_640: usize = 1; +fn aiur_fn_640( + inp: [G; IN_640], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_641], ExecError> { +) -> Result<[G; OUT_640], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -54161,8 +54115,8 @@ fn aiur_fn_641( match __v_3.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_641] = [__v_9]; - record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_640] = [__v_9]; + record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -54172,38 +54126,38 @@ fn aiur_fn_641( let __v_9: G = __r_arr[0]; match __v_9.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_644] = { let __args: [G; IN_644] = [__v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[644].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[644].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[644].bump_multiplicity(__i); } let __ret: [G; OUT_644] = unsafe { *(record.function_queries[644].output_at(__i).as_ptr() as *const [G; OUT_644]) }; __ret }, _ => aiur_fn_644(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_643] = { let __args: [G; IN_643] = [__v_6, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[643].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[643].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[643].bump_multiplicity(__i); } let __ret: [G; OUT_643] = unsafe { *(record.function_queries[643].output_at(__i).as_ptr() as *const [G; OUT_643]) }; __ret }, _ => aiur_fn_643(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; match __v_10.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(1); - let __ret: [G; OUT_641] = [__v_11]; - record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_640] = [__v_11]; + record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_641] = [__v_11]; - record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_640] = [__v_11]; + record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_641] = [__v_10]; - record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_640] = [__v_10]; + record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_641] = [__v_9]; - record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_640] = [__v_9]; + record.function_queries[640].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54215,15 +54169,15 @@ fn aiur_fn_641( }) } -const INPUT_SIZE_642: usize = 2; -const IN_642: usize = 2; -const OUT_642: usize = 1; -fn aiur_fn_642( - inp: [G; IN_642], +const INPUT_SIZE_641: usize = 2; +const IN_641: usize = 2; +const OUT_641: usize = 1; +fn aiur_fn_641( + inp: [G; IN_641], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_642], ExecError> { +) -> Result<[G; OUT_641], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -54231,8 +54185,8 @@ fn aiur_fn_642( match __v_2.as_canonical_u64() { 0u64 => { let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_642] = [__v_3]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_3]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -54254,22 +54208,22 @@ fn aiur_fn_642( match __v_11.as_canonical_u64() { 0u64 => { let __v_12: G = G::from_u64(1); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54282,16 +54236,16 @@ fn aiur_fn_642( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54308,24 +54262,24 @@ fn aiur_fn_642( let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_643] = { let __args: [G; IN_643] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[643].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[643].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[643].bump_multiplicity(__i); } let __ret: [G; OUT_643] = unsafe { *(record.function_queries[643].output_at(__i).as_ptr() as *const [G; OUT_643]) }; __ret }, _ => aiur_fn_643(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54338,28 +54292,28 @@ fn aiur_fn_642( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 3u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54372,28 +54326,28 @@ fn aiur_fn_642( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 4u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54406,28 +54360,28 @@ fn aiur_fn_642( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54440,40 +54394,40 @@ fn aiur_fn_642( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_5, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; match __v_12.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_13]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_13]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_13]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_13]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54486,16 +54440,16 @@ fn aiur_fn_642( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_340] = { let __args: [G; IN_340] = [__v_4, __v_5, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[340].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[340].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[340].bump_multiplicity(__i); } let __ret: [G; OUT_340] = unsafe { *(record.function_queries[340].output_at(__i).as_ptr() as *const [G; OUT_340]) }; __ret }, _ => aiur_fn_340(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_339] = { let __args: [G; IN_339] = [__v_4, __v_5, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[339].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[339].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[339].bump_multiplicity(__i); } let __ret: [G; OUT_339] = unsafe { *(record.function_queries[339].output_at(__i).as_ptr() as *const [G; OUT_339]) }; __ret }, _ => aiur_fn_339(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54515,32 +54469,32 @@ fn aiur_fn_642( let __v_12: G = (__v_5 - __v_9); match __v_12.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_642] = [__v_13]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_13]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_13]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_13]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_12]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_12]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_642] = [__v_11]; - record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_641] = [__v_11]; + record.function_queries[641].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54554,15 +54508,15 @@ fn aiur_fn_642( }) } -const INPUT_SIZE_643: usize = 2; -const IN_643: usize = 2; -const OUT_643: usize = 1; -fn aiur_fn_643( - inp: [G; IN_643], +const INPUT_SIZE_642: usize = 2; +const IN_642: usize = 2; +const OUT_642: usize = 1; +fn aiur_fn_642( + inp: [G; IN_642], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_643], ExecError> { +) -> Result<[G; OUT_642], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -54579,14 +54533,14 @@ fn aiur_fn_643( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_643] = [__v_8]; - record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_642] = [__v_8]; + record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_643] = [__v_8]; - record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_642] = [__v_8]; + record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54599,25 +54553,25 @@ fn aiur_fn_643( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_643] = [__v_8]; - record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_642] = [__v_8]; + record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_327] = { let __args: [G; IN_327] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[327].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[327].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[327].bump_multiplicity(__i); } let __ret: [G; OUT_327] = unsafe { *(record.function_queries[327].output_at(__i).as_ptr() as *const [G; OUT_327]) }; __ret }, _ => aiur_fn_327(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_326] = { let __args: [G; IN_326] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[326].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[326].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[326].bump_multiplicity(__i); } let __ret: [G; OUT_326] = unsafe { *(record.function_queries[326].output_at(__i).as_ptr() as *const [G; OUT_326]) }; __ret }, _ => aiur_fn_326(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_643] = { let __args: [G; IN_643] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[643].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[643].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[643].bump_multiplicity(__i); } let __ret: [G; OUT_643] = unsafe { *(record.function_queries[643].output_at(__i).as_ptr() as *const [G; OUT_643]) }; __ret }, _ => aiur_fn_643(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_643] = [__v_9]; - record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_642] = [__v_9]; + record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_643] = [__v_9]; - record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_642] = [__v_9]; + record.function_queries[642].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54634,15 +54588,15 @@ fn aiur_fn_643( }) } -const INPUT_SIZE_644: usize = 2; -const IN_644: usize = 2; -const OUT_644: usize = 1; -fn aiur_fn_644( - inp: [G; IN_644], +const INPUT_SIZE_643: usize = 2; +const IN_643: usize = 2; +const OUT_643: usize = 1; +fn aiur_fn_643( + inp: [G; IN_643], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_644], ExecError> { +) -> Result<[G; OUT_643], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -54659,14 +54613,14 @@ fn aiur_fn_644( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(1); - let __ret: [G; OUT_644] = [__v_8]; - record.function_queries[644].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_643] = [__v_8]; + record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_644] = [__v_8]; - record.function_queries[644].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_643] = [__v_8]; + record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54679,25 +54633,25 @@ fn aiur_fn_644( match __v_5.as_canonical_u64() { 1u64 => { let __v_8: G = G::from_u64(0); - let __ret: [G; OUT_644] = [__v_8]; - record.function_queries[644].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_643] = [__v_8]; + record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; match __v_8.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_644] = { let __args: [G; IN_644] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[644].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[644].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[644].bump_multiplicity(__i); } let __ret: [G; OUT_644] = unsafe { *(record.function_queries[644].output_at(__i).as_ptr() as *const [G; OUT_644]) }; __ret }, _ => aiur_fn_644(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_643] = { let __args: [G; IN_643] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[643].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[643].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[643].bump_multiplicity(__i); } let __ret: [G; OUT_643] = unsafe { *(record.function_queries[643].output_at(__i).as_ptr() as *const [G; OUT_643]) }; __ret }, _ => aiur_fn_643(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_644] = [__v_9]; - record.function_queries[644].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_643] = [__v_9]; + record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_644] = [__v_9]; - record.function_queries[644].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_643] = [__v_9]; + record.function_queries[643].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54714,15 +54668,15 @@ fn aiur_fn_644( }) } -const INPUT_SIZE_645: usize = 13; -const IN_645: usize = 13; -const OUT_645: usize = 1; -fn aiur_fn_645( - inp: [G; IN_645], +const INPUT_SIZE_644: usize = 13; +const IN_644: usize = 13; +const OUT_644: usize = 1; +fn aiur_fn_644( + inp: [G; IN_644], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_645], ExecError> { +) -> Result<[G; OUT_644], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -54739,37 +54693,37 @@ fn aiur_fn_645( let __v_12: G = inp[12]; match __v_0.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_636] = { let __args: [G; IN_636] = [__v_2, __v_3, __v_5, __v_6, __v_4, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[636].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[636].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[636].bump_multiplicity(__i); } let __ret: [G; OUT_636] = unsafe { *(record.function_queries[636].output_at(__i).as_ptr() as *const [G; OUT_636]) }; __ret }, _ => aiur_fn_636(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_635] = { let __args: [G; IN_635] = [__v_2, __v_3, __v_5, __v_6, __v_4, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[635].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[635].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[635].bump_multiplicity(__i); } let __ret: [G; OUT_635] = unsafe { *(record.function_queries[635].output_at(__i).as_ptr() as *const [G; OUT_635]) }; __ret }, _ => aiur_fn_635(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_645] = [__v_13]; - record.function_queries[645].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_644] = [__v_13]; + record.function_queries[644].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(1); let __v_15: G = { let __values: [G; 3] = [__v_13, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_645] = [__v_15]; - record.function_queries[645].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_644] = [__v_15]; + record.function_queries[644].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_646: usize = 2; -const IN_646: usize = 2; -const OUT_646: usize = 1; -fn aiur_fn_646( - inp: [G; IN_646], +const INPUT_SIZE_645: usize = 2; +const IN_645: usize = 2; +const OUT_645: usize = 1; +fn aiur_fn_645( + inp: [G; IN_645], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_646], ExecError> { +) -> Result<[G; OUT_645], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = __r_arr[2]; @@ -54823,15 +54777,15 @@ fn aiur_fn_646( match __v_2.as_canonical_u64() { 8u64 => { let __v_50: G = G::from_u64(0); - let __r_arr: [G; OUT_647] = { let __args: [G; IN_647] = [__v_3, __v_3, __v_0, __v_50, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[647].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[647].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[647].bump_multiplicity(__i); } let __ret: [G; OUT_647] = unsafe { *(record.function_queries[647].output_at(__i).as_ptr() as *const [G; OUT_647]) }; __ret }, _ => aiur_fn_647(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_646] = { let __args: [G; IN_646] = [__v_3, __v_3, __v_0, __v_50, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[646].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[646].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[646].bump_multiplicity(__i); } let __ret: [G; OUT_646] = unsafe { *(record.function_queries[646].output_at(__i).as_ptr() as *const [G; OUT_646]) }; __ret }, _ => aiur_fn_646(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __ret: [G; OUT_646] = [__v_51]; - record.function_queries[646].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_645] = [__v_51]; + record.function_queries[645].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_646] = [__v_1]; - record.function_queries[646].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_645] = [__v_1]; + record.function_queries[645].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54840,15 +54794,15 @@ fn aiur_fn_646( }) } -const INPUT_SIZE_647: usize = 5; -const IN_647: usize = 5; -const OUT_647: usize = 1; -fn aiur_fn_647( - inp: [G; IN_647], +const INPUT_SIZE_646: usize = 5; +const IN_646: usize = 5; +const OUT_646: usize = 1; +fn aiur_fn_646( + inp: [G; IN_646], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_647], ExecError> { +) -> Result<[G; OUT_646], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -54905,16 +54859,16 @@ fn aiur_fn_647( let __v_51: G = __loaded[46]; match __v_5.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_647] = [__v_4]; - record.function_queries[647].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_646] = [__v_4]; + record.function_queries[646].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_6.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_0, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_52]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_52]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_53.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_54: G = __loaded[0]; @@ -54931,9 +54885,9 @@ fn aiur_fn_647( let __v_65: G = __loaded[11]; match __v_54.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_56, __v_57, __v_59, __v_60, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_56, __v_57, __v_59, __v_60, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; let __v_66: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_66]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_66]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_67: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_67.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_68: G = __loaded[0]; @@ -54950,20 +54904,20 @@ fn aiur_fn_647( let __v_79: G = __loaded[11]; match __v_68.as_canonical_u64() { 5u64 => { - let __ret: [G; OUT_647] = [__v_75]; - record.function_queries[647].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_646] = [__v_75]; + record.function_queries[646].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_647] = [__v_4]; - record.function_queries[647].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_646] = [__v_4]; + record.function_queries[646].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __ret: [G; OUT_647] = [__v_4]; - record.function_queries[647].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_646] = [__v_4]; + record.function_queries[646].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54971,10 +54925,10 @@ fn aiur_fn_647( _ => { let __v_52: G = G::from_u64(1); let __v_53: G = (__v_3 + __v_52); - let __r_arr: [G; OUT_647] = { let __args: [G; IN_647] = [__v_0, __v_51, __v_2, __v_53, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[647].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[647].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[647].bump_multiplicity(__i); } let __ret: [G; OUT_647] = unsafe { *(record.function_queries[647].output_at(__i).as_ptr() as *const [G; OUT_647]) }; __ret }, _ => aiur_fn_647(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_646] = { let __args: [G; IN_646] = [__v_0, __v_51, __v_2, __v_53, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[646].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[646].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[646].bump_multiplicity(__i); } let __ret: [G; OUT_646] = unsafe { *(record.function_queries[646].output_at(__i).as_ptr() as *const [G; OUT_646]) }; __ret }, _ => aiur_fn_646(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; - let __ret: [G; OUT_647] = [__v_54]; - record.function_queries[647].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_646] = [__v_54]; + record.function_queries[646].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -54986,20 +54940,20 @@ fn aiur_fn_647( }) } -const INPUT_SIZE_648: usize = 3; -const IN_648: usize = 3; -const OUT_648: usize = 1; -fn aiur_fn_648( - inp: [G; IN_648], +const INPUT_SIZE_647: usize = 3; +const IN_647: usize = 3; +const OUT_647: usize = 1; +fn aiur_fn_647( + inp: [G; IN_647], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_648], ExecError> { +) -> Result<[G; OUT_647], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = __r_arr[2]; @@ -55053,7 +55007,7 @@ fn aiur_fn_648( match __v_3.as_canonical_u64() { 8u64 => { let __v_51: G = G::from_u64(0); - let __r_arr: [G; OUT_647] = { let __args: [G; IN_647] = [__v_4, __v_4, __v_0, __v_51, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[647].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[647].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[647].bump_multiplicity(__i); } let __ret: [G; OUT_647] = unsafe { *(record.function_queries[647].output_at(__i).as_ptr() as *const [G; OUT_647]) }; __ret }, _ => aiur_fn_647(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_646] = { let __args: [G; IN_646] = [__v_4, __v_4, __v_0, __v_51, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[646].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[646].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[646].bump_multiplicity(__i); } let __ret: [G; OUT_646] = unsafe { *(record.function_queries[646].output_at(__i).as_ptr() as *const [G; OUT_646]) }; __ret }, _ => aiur_fn_646(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; break '__mc_0 [__v_52]; }, @@ -55065,7 +55019,7 @@ fn aiur_fn_648( } }; let __v_51: G = __mc_out___mc_0[0]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_51]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_51]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = __r_arr[1]; let __v_54: G = __r_arr[2]; @@ -55119,12 +55073,12 @@ fn aiur_fn_648( match __v_52.as_canonical_u64() { 8u64 => { let __v_100: G = G::from_u64(0); - let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_53, __v_53, __v_51, __v_2, __v_100]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_639] = { let __args: [G; IN_639] = [__v_53, __v_53, __v_51, __v_2, __v_100]; let __cu = unconstrained; let __hit = record.function_queries[639].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[639].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[639].bump_multiplicity(__i); } let __ret: [G; OUT_639] = unsafe { *(record.function_queries[639].output_at(__i).as_ptr() as *const [G; OUT_639]) }; __ret }, _ => aiur_fn_639(__args, record, io_buffer, __cu)? } }; let __v_101: G = __r_arr[0]; break '__mc_1 [__v_101]; }, _ => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_51]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_51]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_100: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_100.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_101: G = __loaded[0]; @@ -55142,7 +55096,7 @@ fn aiur_fn_648( match __v_101.as_canonical_u64() { 5u64 => { let __v_113: G = G::from_u64(0); - let __r_arr: [G; OUT_638] = { let __args: [G; IN_638] = [__v_2, __v_102, __v_113]; let __cu = unconstrained; let __hit = record.function_queries[638].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[638].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[638].bump_multiplicity(__i); } let __ret: [G; OUT_638] = unsafe { *(record.function_queries[638].output_at(__i).as_ptr() as *const [G; OUT_638]) }; __ret }, _ => aiur_fn_638(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_637] = { let __args: [G; IN_637] = [__v_2, __v_102, __v_113]; let __cu = unconstrained; let __hit = record.function_queries[637].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[637].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[637].bump_multiplicity(__i); } let __ret: [G; OUT_637] = unsafe { *(record.function_queries[637].output_at(__i).as_ptr() as *const [G; OUT_637]) }; __ret }, _ => aiur_fn_637(__args, record, io_buffer, __cu)? } }; let __v_114: G = __r_arr[0]; let __v_115: G = G::from_u64(0); let __v_116: G = G::from_u64(0); @@ -55168,40 +55122,40 @@ fn aiur_fn_648( } }; let __v_100: G = __mc_out___mc_1[0]; - let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_631] = { let __args: [G; IN_631] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[631].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[631].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[631].bump_multiplicity(__i); } let __ret: [G; OUT_631] = unsafe { *(record.function_queries[631].output_at(__i).as_ptr() as *const [G; OUT_631]) }; __ret }, _ => aiur_fn_631(__args, record, io_buffer, __cu)? } }; let __v_101: G = __r_arr[0]; match __v_101.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_648] = [__v_100]; - record.function_queries[648].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_647] = [__v_100]; + record.function_queries[647].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_649] = { let __args: [G; IN_649] = [__v_0, __v_51, __v_2, __v_100]; let __cu = unconstrained; let __hit = record.function_queries[649].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[649].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[649].bump_multiplicity(__i); } let __ret: [G; OUT_649] = unsafe { *(record.function_queries[649].output_at(__i).as_ptr() as *const [G; OUT_649]) }; __ret }, _ => aiur_fn_649(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_648] = { let __args: [G; IN_648] = [__v_0, __v_51, __v_2, __v_100]; let __cu = unconstrained; let __hit = record.function_queries[648].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[648].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[648].bump_multiplicity(__i); } let __ret: [G; OUT_648] = unsafe { *(record.function_queries[648].output_at(__i).as_ptr() as *const [G; OUT_648]) }; __ret }, _ => aiur_fn_648(__args, record, io_buffer, __cu)? } }; let __v_102: G = __r_arr[0]; - let __ret: [G; OUT_648] = [__v_102]; - record.function_queries[648].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_647] = [__v_102]; + record.function_queries[647].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_649: usize = 4; -const IN_649: usize = 4; -const OUT_649: usize = 1; -fn aiur_fn_649( - inp: [G; IN_649], +const INPUT_SIZE_648: usize = 4; +const IN_648: usize = 4; +const OUT_648: usize = 1; +fn aiur_fn_648( + inp: [G; IN_648], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_649], ExecError> { +) -> Result<[G; OUT_648], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; let __v_6: G = __r_arr[2]; @@ -55255,15 +55209,15 @@ fn aiur_fn_649( match __v_4.as_canonical_u64() { 8u64 => { let __v_52: G = G::from_u64(0); - let __r_arr: [G; OUT_650] = { let __args: [G; IN_650] = [__v_5, __v_5, __v_0, __v_1, __v_2, __v_3, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[650].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[650].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[650].bump_multiplicity(__i); } let __ret: [G; OUT_650] = unsafe { *(record.function_queries[650].output_at(__i).as_ptr() as *const [G; OUT_650]) }; __ret }, _ => aiur_fn_650(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_649] = { let __args: [G; IN_649] = [__v_5, __v_5, __v_0, __v_1, __v_2, __v_3, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[649].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[649].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[649].bump_multiplicity(__i); } let __ret: [G; OUT_649] = unsafe { *(record.function_queries[649].output_at(__i).as_ptr() as *const [G; OUT_649]) }; __ret }, _ => aiur_fn_649(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; - let __ret: [G; OUT_649] = [__v_53]; - record.function_queries[649].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_648] = [__v_53]; + record.function_queries[648].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_649] = [__v_3]; - record.function_queries[649].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_648] = [__v_3]; + record.function_queries[648].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55272,15 +55226,15 @@ fn aiur_fn_649( }) } -const INPUT_SIZE_650: usize = 7; -const IN_650: usize = 7; -const OUT_650: usize = 1; -fn aiur_fn_650( - inp: [G; IN_650], +const INPUT_SIZE_649: usize = 7; +const IN_649: usize = 7; +const OUT_649: usize = 1; +fn aiur_fn_649( + inp: [G; IN_649], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_650], ExecError> { +) -> Result<[G; OUT_649], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55339,16 +55293,16 @@ fn aiur_fn_650( let __v_53: G = __loaded[46]; match __v_7.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_650] = [__v_5]; - record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_649] = [__v_5]; + record.function_queries[649].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_8.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_0, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_0, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_54]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_54]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_55.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_56: G = __loaded[0]; @@ -55365,9 +55319,9 @@ fn aiur_fn_650( let __v_67: G = __loaded[11]; let __mc_out___mc_0: [G; 5] = '__mc_0: { match __v_56.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_58, __v_59, __v_61, __v_62, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_58, __v_59, __v_61, __v_62, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; let __v_68: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_68]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_68]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_69: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_69.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_70: G = __loaded[0]; @@ -55426,39 +55380,39 @@ fn aiur_fn_650( 0u64 => { let __v_73: G = G::from_u64(1); let __v_74: G = (__v_6 + __v_73); - let __r_arr: [G; OUT_650] = { let __args: [G; IN_650] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_5, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[650].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[650].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[650].bump_multiplicity(__i); } let __ret: [G; OUT_650] = unsafe { *(record.function_queries[650].output_at(__i).as_ptr() as *const [G; OUT_650]) }; __ret }, _ => aiur_fn_650(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_649] = { let __args: [G; IN_649] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_5, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[649].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[649].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[649].bump_multiplicity(__i); } let __ret: [G; OUT_649] = unsafe { *(record.function_queries[649].output_at(__i).as_ptr() as *const [G; OUT_649]) }; __ret }, _ => aiur_fn_649(__args, record, io_buffer, __cu)? } }; let __v_75: G = __r_arr[0]; - let __ret: [G; OUT_650] = [__v_75]; - record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_649] = [__v_75]; + record.function_queries[649].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_645] = { let __args: [G; IN_645] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_71]; let __cu = unconstrained; let __hit = record.function_queries[645].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[645].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[645].bump_multiplicity(__i); } let __ret: [G; OUT_645] = unsafe { *(record.function_queries[645].output_at(__i).as_ptr() as *const [G; OUT_645]) }; __ret }, _ => aiur_fn_645(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_644] = { let __args: [G; IN_644] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_71]; let __cu = unconstrained; let __hit = record.function_queries[644].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[644].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[644].bump_multiplicity(__i); } let __ret: [G; OUT_644] = unsafe { *(record.function_queries[644].output_at(__i).as_ptr() as *const [G; OUT_644]) }; __ret }, _ => aiur_fn_644(__args, record, io_buffer, __cu)? } }; let __v_73: G = __r_arr[0]; - let __r_arr: [G; OUT_635] = { let __args: [G; IN_635] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[635].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[635].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[635].bump_multiplicity(__i); } let __ret: [G; OUT_635] = unsafe { *(record.function_queries[635].output_at(__i).as_ptr() as *const [G; OUT_635]) }; __ret }, _ => aiur_fn_635(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; let __v_74: G = __r_arr[0]; - let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_5, __v_69, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_640] = { let __args: [G; IN_640] = [__v_5, __v_69, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[640].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[640].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[640].bump_multiplicity(__i); } let __ret: [G; OUT_640] = unsafe { *(record.function_queries[640].output_at(__i).as_ptr() as *const [G; OUT_640]) }; __ret }, _ => aiur_fn_640(__args, record, io_buffer, __cu)? } }; let __v_75: G = __r_arr[0]; match __v_75.as_canonical_u64() { 1u64 => { let __v_76: G = G::from_u64(1); let __v_77: G = (__v_6 + __v_76); - let __r_arr: [G; OUT_650] = { let __args: [G; IN_650] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_5, __v_77]; let __cu = unconstrained; let __hit = record.function_queries[650].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[650].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[650].bump_multiplicity(__i); } let __ret: [G; OUT_650] = unsafe { *(record.function_queries[650].output_at(__i).as_ptr() as *const [G; OUT_650]) }; __ret }, _ => aiur_fn_650(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_649] = { let __args: [G; IN_649] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_5, __v_77]; let __cu = unconstrained; let __hit = record.function_queries[649].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[649].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[649].bump_multiplicity(__i); } let __ret: [G; OUT_649] = unsafe { *(record.function_queries[649].output_at(__i).as_ptr() as *const [G; OUT_649]) }; __ret }, _ => aiur_fn_649(__args, record, io_buffer, __cu)? } }; let __v_78: G = __r_arr[0]; - let __ret: [G; OUT_650] = [__v_78]; - record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_649] = [__v_78]; + record.function_queries[649].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_76: G = G::from_u64(1); - let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_5, __v_69, __v_76, __v_73, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_783] = { let __args: [G; IN_783] = [__v_5, __v_69, __v_76, __v_73, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[783].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[783].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[783].bump_multiplicity(__i); } let __ret: [G; OUT_783] = unsafe { *(record.function_queries[783].output_at(__i).as_ptr() as *const [G; OUT_783]) }; __ret }, _ => aiur_fn_783(__args, record, io_buffer, __cu)? } }; let __v_77: G = __r_arr[0]; let __v_78: G = G::from_u64(1); let __v_79: G = (__v_6 + __v_78); - let __r_arr: [G; OUT_650] = { let __args: [G; IN_650] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_77, __v_79]; let __cu = unconstrained; let __hit = record.function_queries[650].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[650].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[650].bump_multiplicity(__i); } let __ret: [G; OUT_650] = unsafe { *(record.function_queries[650].output_at(__i).as_ptr() as *const [G; OUT_650]) }; __ret }, _ => aiur_fn_650(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_649] = { let __args: [G; IN_649] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_77, __v_79]; let __cu = unconstrained; let __hit = record.function_queries[649].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[649].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[649].bump_multiplicity(__i); } let __ret: [G; OUT_649] = unsafe { *(record.function_queries[649].output_at(__i).as_ptr() as *const [G; OUT_649]) }; __ret }, _ => aiur_fn_649(__args, record, io_buffer, __cu)? } }; let __v_80: G = __r_arr[0]; - let __ret: [G; OUT_650] = [__v_80]; - record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_649] = [__v_80]; + record.function_queries[649].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55468,10 +55422,10 @@ fn aiur_fn_650( _ => { let __v_54: G = G::from_u64(1); let __v_55: G = (__v_6 + __v_54); - let __r_arr: [G; OUT_650] = { let __args: [G; IN_650] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_5, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[650].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[650].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[650].bump_multiplicity(__i); } let __ret: [G; OUT_650] = unsafe { *(record.function_queries[650].output_at(__i).as_ptr() as *const [G; OUT_650]) }; __ret }, _ => aiur_fn_650(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_649] = { let __args: [G; IN_649] = [__v_0, __v_53, __v_2, __v_3, __v_4, __v_5, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[649].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[649].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[649].bump_multiplicity(__i); } let __ret: [G; OUT_649] = unsafe { *(record.function_queries[649].output_at(__i).as_ptr() as *const [G; OUT_649]) }; __ret }, _ => aiur_fn_649(__args, record, io_buffer, __cu)? } }; let __v_56: G = __r_arr[0]; - let __ret: [G; OUT_650] = [__v_56]; - record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_649] = [__v_56]; + record.function_queries[649].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55483,15 +55437,15 @@ fn aiur_fn_650( }) } -const INPUT_SIZE_651: usize = 3; -const IN_651: usize = 3; -const OUT_651: usize = 2; -fn aiur_fn_651( - inp: [G; IN_651], +const INPUT_SIZE_650: usize = 3; +const IN_650: usize = 3; +const OUT_650: usize = 2; +fn aiur_fn_650( + inp: [G; IN_650], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_651], ExecError> { +) -> Result<[G; OUT_650], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55507,8 +55461,8 @@ fn aiur_fn_651( 1u64 => { let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_651] = [__v_9, __v_10]; - record.function_queries[651].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_650] = [__v_9, __v_10]; + record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -55517,18 +55471,18 @@ fn aiur_fn_651( match __v_9.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(1); - let __ret: [G; OUT_651] = [__v_10, __v_2]; - record.function_queries[651].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_650] = [__v_10, __v_2]; + record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_10: G = G::from_u64(1); let __v_11: G = (__v_2 + __v_10); - let __r_arr: [G; OUT_651] = { let __args: [G; IN_651] = [__v_8, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[651].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[651].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[651].bump_multiplicity(__i); } let __ret: [G; OUT_651] = unsafe { *(record.function_queries[651].output_at(__i).as_ptr() as *const [G; OUT_651]) }; __ret }, _ => aiur_fn_651(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_650] = { let __args: [G; IN_650] = [__v_8, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[650].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[650].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[650].bump_multiplicity(__i); } let __ret: [G; OUT_650] = unsafe { *(record.function_queries[650].output_at(__i).as_ptr() as *const [G; OUT_650]) }; __ret }, _ => aiur_fn_650(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; - let __ret: [G; OUT_651] = [__v_12, __v_13]; - record.function_queries[651].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_650] = [__v_12, __v_13]; + record.function_queries[650].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55540,15 +55494,15 @@ fn aiur_fn_651( }) } -const INPUT_SIZE_652: usize = 5; -const IN_652: usize = 5; -const OUT_652: usize = 2; -fn aiur_fn_652( - inp: [G; IN_652], +const INPUT_SIZE_651: usize = 5; +const IN_651: usize = 5; +const OUT_651: usize = 2; +fn aiur_fn_651( + inp: [G; IN_651], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_652], ExecError> { +) -> Result<[G; OUT_651], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55566,8 +55520,8 @@ fn aiur_fn_652( 1u64 => { let __v_11: G = G::from_u64(0); let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_652] = [__v_11, __v_12]; - record.function_queries[652].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_651] = [__v_11, __v_12]; + record.function_queries[651].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -55588,7 +55542,7 @@ fn aiur_fn_652( let __v_13: G = __mc_out___mc_0[0]; let __mc_out___mc_1: [G; 1] = '__mc_1: { match __v_2.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_644] = { let __args: [G; IN_644] = [__v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[644].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[644].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[644].bump_multiplicity(__i); } let __ret: [G; OUT_644] = unsafe { *(record.function_queries[644].output_at(__i).as_ptr() as *const [G; OUT_644]) }; __ret }, _ => aiur_fn_644(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_643] = { let __args: [G; IN_643] = [__v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[643].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[643].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[643].bump_multiplicity(__i); } let __ret: [G; OUT_643] = unsafe { *(record.function_queries[643].output_at(__i).as_ptr() as *const [G; OUT_643]) }; __ret }, _ => aiur_fn_643(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; break '__mc_1 [__v_14]; }, @@ -55604,18 +55558,18 @@ fn aiur_fn_652( match __v_16.as_canonical_u64() { 1u64 => { let __v_17: G = G::from_u64(1); - let __ret: [G; OUT_652] = [__v_17, __v_4]; - record.function_queries[652].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_651] = [__v_17, __v_4]; + record.function_queries[651].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_17: G = G::from_u64(1); let __v_18: G = (__v_4 + __v_17); - let __r_arr: [G; OUT_652] = { let __args: [G; IN_652] = [__v_10, __v_1, __v_2, __v_3, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[652].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[652].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[652].bump_multiplicity(__i); } let __ret: [G; OUT_652] = unsafe { *(record.function_queries[652].output_at(__i).as_ptr() as *const [G; OUT_652]) }; __ret }, _ => aiur_fn_652(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_651] = { let __args: [G; IN_651] = [__v_10, __v_1, __v_2, __v_3, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[651].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[651].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[651].bump_multiplicity(__i); } let __ret: [G; OUT_651] = unsafe { *(record.function_queries[651].output_at(__i).as_ptr() as *const [G; OUT_651]) }; __ret }, _ => aiur_fn_651(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = __r_arr[1]; - let __ret: [G; OUT_652] = [__v_19, __v_20]; - record.function_queries[652].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_651] = [__v_19, __v_20]; + record.function_queries[651].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55627,15 +55581,15 @@ fn aiur_fn_652( }) } -const INPUT_SIZE_653: usize = 2; -const IN_653: usize = 2; -const OUT_653: usize = 4; -fn aiur_fn_653( - inp: [G; IN_653], +const INPUT_SIZE_652: usize = 2; +const IN_652: usize = 2; +const OUT_652: usize = 4; +fn aiur_fn_652( + inp: [G; IN_652], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_653], ExecError> { +) -> Result<[G; OUT_652], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55688,27 +55642,27 @@ fn aiur_fn_653( let __v_45: G = G::from_u64(1); let __v_46: G = G::from_u64(1); let __v_47: G = { let __values: [G; 3] = [__v_45, __v_46, __v_46]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_653] = [__v_40, __v_41, __v_44, __v_47]; - record.function_queries[653].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_652] = [__v_40, __v_41, __v_44, __v_47]; + record.function_queries[652].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_653] = [__v_3, __v_4, __v_5, __v_6]; - record.function_queries[653].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_652] = [__v_3, __v_4, __v_5, __v_6]; + record.function_queries[652].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_8: G = G::from_u64(1); let __v_9: G = (__v_1 - __v_8); - let __r_arr: [G; OUT_653] = { let __args: [G; IN_653] = [__v_7, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[653].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[653].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[653].bump_multiplicity(__i); } let __ret: [G; OUT_653] = unsafe { *(record.function_queries[653].output_at(__i).as_ptr() as *const [G; OUT_653]) }; __ret }, _ => aiur_fn_653(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_652] = { let __args: [G; IN_652] = [__v_7, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[652].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[652].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[652].bump_multiplicity(__i); } let __ret: [G; OUT_652] = unsafe { *(record.function_queries[652].output_at(__i).as_ptr() as *const [G; OUT_652]) }; __ret }, _ => aiur_fn_652(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; let __v_13: G = __r_arr[3]; - let __ret: [G; OUT_653] = [__v_10, __v_11, __v_12, __v_13]; - record.function_queries[653].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_652] = [__v_10, __v_11, __v_12, __v_13]; + record.function_queries[652].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55720,15 +55674,15 @@ fn aiur_fn_653( }) } -const INPUT_SIZE_654: usize = 4; -const IN_654: usize = 4; -const OUT_654: usize = 1; -fn aiur_fn_654( - inp: [G; IN_654], +const INPUT_SIZE_653: usize = 4; +const IN_653: usize = 4; +const OUT_653: usize = 1; +fn aiur_fn_653( + inp: [G; IN_653], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_654], ExecError> { +) -> Result<[G; OUT_653], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55742,20 +55696,20 @@ fn aiur_fn_654( let __v_7: G = (__v_6 - __v_0); let __v_8: G = G::from_u64(0); let __v_9: G = { let __values: [G; 4] = [__v_4, __v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_654] = [__v_9]; - record.function_queries[654].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_653] = [__v_9]; + record.function_queries[653].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_4.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_5.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_654] = [__v_6]; - record.function_queries[654].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_653] = [__v_6]; + record.function_queries[653].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -55765,8 +55719,8 @@ fn aiur_fn_654( let __v_9: G = (__v_8 - __v_0); let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 4] = [__v_6, __v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_654] = [__v_11]; - record.function_queries[654].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_653] = [__v_11]; + record.function_queries[653].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55775,15 +55729,15 @@ fn aiur_fn_654( }) } -const INPUT_SIZE_655: usize = 6; -const IN_655: usize = 6; -const OUT_655: usize = 1; -fn aiur_fn_655( - inp: [G; IN_655], +const INPUT_SIZE_654: usize = 6; +const IN_654: usize = 6; +const OUT_654: usize = 1; +fn aiur_fn_654( + inp: [G; IN_654], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_655], ExecError> { +) -> Result<[G; OUT_654], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55793,8 +55747,8 @@ fn aiur_fn_655( let __v_5: G = inp[5]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_655] = [__v_0]; - record.function_queries[655].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_654] = [__v_0]; + record.function_queries[654].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -55805,19 +55759,19 @@ fn aiur_fn_655( let __v_9: G = __loaded[3]; match __v_6.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_654] = { let __args: [G; IN_654] = [__v_5, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[654].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[654].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[654].bump_multiplicity(__i); } let __ret: [G; OUT_654] = unsafe { *(record.function_queries[654].output_at(__i).as_ptr() as *const [G; OUT_654]) }; __ret }, _ => aiur_fn_654(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_653] = { let __args: [G; IN_653] = [__v_5, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[653].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[653].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[653].bump_multiplicity(__i); } let __ret: [G; OUT_653] = unsafe { *(record.function_queries[653].output_at(__i).as_ptr() as *const [G; OUT_653]) }; __ret }, _ => aiur_fn_653(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_8, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(1); let __v_14: G = (__v_1 - __v_13); let __v_15: G = G::from_u64(1); let __v_16: G = (__v_5 + __v_15); - let __r_arr: [G; OUT_655] = { let __args: [G; IN_655] = [__v_12, __v_14, __v_2, __v_3, __v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[655].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[655].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[655].bump_multiplicity(__i); } let __ret: [G; OUT_655] = unsafe { *(record.function_queries[655].output_at(__i).as_ptr() as *const [G; OUT_655]) }; __ret }, _ => aiur_fn_655(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_654] = { let __args: [G; IN_654] = [__v_12, __v_14, __v_2, __v_3, __v_4, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[654].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[654].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[654].bump_multiplicity(__i); } let __ret: [G; OUT_654] = unsafe { *(record.function_queries[654].output_at(__i).as_ptr() as *const [G; OUT_654]) }; __ret }, _ => aiur_fn_654(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_655] = [__v_17]; - record.function_queries[655].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_654] = [__v_17]; + record.function_queries[654].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -55829,15 +55783,15 @@ fn aiur_fn_655( }) } -const INPUT_SIZE_656: usize = 2; -const IN_656: usize = 2; -const OUT_656: usize = 1; -fn aiur_fn_656( - inp: [G; IN_656], +const INPUT_SIZE_655: usize = 2; +const IN_655: usize = 2; +const OUT_655: usize = 1; +fn aiur_fn_655( + inp: [G; IN_655], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_656], ExecError> { +) -> Result<[G; OUT_655], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55846,8 +55800,8 @@ fn aiur_fn_656( let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); let __v_4: G = { let __values: [G; 3] = [__v_2, __v_3, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_656] = [__v_4]; - record.function_queries[656].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_655] = [__v_4]; + record.function_queries[655].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -55861,18 +55815,18 @@ fn aiur_fn_656( let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 - __v_7); - let __r_arr: [G; OUT_656] = { let __args: [G; IN_656] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[656].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[656].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[656].bump_multiplicity(__i); } let __ret: [G; OUT_656] = unsafe { *(record.function_queries[656].output_at(__i).as_ptr() as *const [G; OUT_656]) }; __ret }, _ => aiur_fn_656(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_655] = { let __args: [G; IN_655] = [__v_4, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[655].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[655].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[655].bump_multiplicity(__i); } let __ret: [G; OUT_655] = unsafe { *(record.function_queries[655].output_at(__i).as_ptr() as *const [G; OUT_655]) }; __ret }, _ => aiur_fn_655(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = { let __values: [G; 3] = [__v_6, __v_3, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_656] = [__v_10]; - record.function_queries[656].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_655] = [__v_10]; + record.function_queries[655].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_9.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -55884,19 +55838,19 @@ fn aiur_fn_656( let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(1); let __v_16: G = (__v_1 - __v_15); - let __r_arr: [G; OUT_656] = { let __args: [G; IN_656] = [__v_12, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[656].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[656].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[656].bump_multiplicity(__i); } let __ret: [G; OUT_656] = unsafe { *(record.function_queries[656].output_at(__i).as_ptr() as *const [G; OUT_656]) }; __ret }, _ => aiur_fn_656(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_655] = { let __args: [G; IN_655] = [__v_12, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[655].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[655].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[655].bump_multiplicity(__i); } let __ret: [G; OUT_655] = unsafe { *(record.function_queries[655].output_at(__i).as_ptr() as *const [G; OUT_655]) }; __ret }, _ => aiur_fn_655(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = { let __values: [G; 3] = [__v_14, __v_11, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_656] = [__v_18]; - record.function_queries[656].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_655] = [__v_18]; + record.function_queries[655].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(1); let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 3] = [__v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_656] = [__v_16]; - record.function_queries[656].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_655] = [__v_16]; + record.function_queries[655].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -55907,15 +55861,15 @@ fn aiur_fn_656( }) } -const INPUT_SIZE_657: usize = 4; -const IN_657: usize = 4; -const OUT_657: usize = 1; -fn aiur_fn_657( - inp: [G; IN_657], +const INPUT_SIZE_656: usize = 4; +const IN_656: usize = 4; +const OUT_656: usize = 1; +fn aiur_fn_656( + inp: [G; IN_656], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_657], ExecError> { +) -> Result<[G; OUT_656], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55924,8 +55878,8 @@ fn aiur_fn_657( let __v_4: G = (__v_1 - __v_3); match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_657] = [__v_0]; - record.function_queries[657].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_656] = [__v_0]; + record.function_queries[656].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -55941,25 +55895,25 @@ fn aiur_fn_657( let __v_14: G = { let __values: [G; 4] = [__v_12, __v_0, __v_11, __v_13]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_15: G = G::from_u64(1); let __v_16: G = (__v_3 + __v_15); - let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_14, __v_1, __v_2, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_656] = { let __args: [G; IN_656] = [__v_14, __v_1, __v_2, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[656].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[656].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[656].bump_multiplicity(__i); } let __ret: [G; OUT_656] = unsafe { *(record.function_queries[656].output_at(__i).as_ptr() as *const [G; OUT_656]) }; __ret }, _ => aiur_fn_656(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __ret: [G; OUT_657] = [__v_17]; - record.function_queries[657].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_656] = [__v_17]; + record.function_queries[656].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_658: usize = 3; -const IN_658: usize = 3; -const OUT_658: usize = 1; -fn aiur_fn_658( - inp: [G; IN_658], +const INPUT_SIZE_657: usize = 3; +const IN_657: usize = 3; +const OUT_657: usize = 1; +fn aiur_fn_657( + inp: [G; IN_657], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_658], ExecError> { +) -> Result<[G; OUT_657], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -55970,21 +55924,21 @@ fn aiur_fn_658( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_658] = [__v_0]; - record.function_queries[658].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_657] = [__v_0]; + record.function_queries[657].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(3); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_8, __v_0, __v_7, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_658] = { let __args: [G; IN_658] = [__v_10, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[658].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[658].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[658].bump_multiplicity(__i); } let __ret: [G; OUT_658] = unsafe { *(record.function_queries[658].output_at(__i).as_ptr() as *const [G; OUT_658]) }; __ret }, _ => aiur_fn_658(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_10, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __ret: [G; OUT_658] = [__v_11]; - record.function_queries[658].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_657] = [__v_11]; + record.function_queries[657].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -55994,15 +55948,15 @@ fn aiur_fn_658( }) } -const INPUT_SIZE_659: usize = 5; -const IN_659: usize = 5; -const OUT_659: usize = 1; -fn aiur_fn_659( - inp: [G; IN_659], +const INPUT_SIZE_658: usize = 5; +const IN_658: usize = 5; +const OUT_658: usize = 1; +fn aiur_fn_658( + inp: [G; IN_658], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_659], ExecError> { +) -> Result<[G; OUT_658], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56012,32 +55966,32 @@ fn aiur_fn_659( match __v_3.as_canonical_u64() { 0u64 => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_0, __v_1, __v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_656] = { let __args: [G; IN_656] = [__v_0, __v_1, __v_2, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[656].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[656].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[656].bump_multiplicity(__i); } let __ret: [G; OUT_656] = unsafe { *(record.function_queries[656].output_at(__i).as_ptr() as *const [G; OUT_656]) }; __ret }, _ => aiur_fn_656(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_659] = [__v_6]; - record.function_queries[659].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_658] = [__v_6]; + record.function_queries[658].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_658] = { let __args: [G; IN_658] = [__v_0, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[658].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[658].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[658].bump_multiplicity(__i); } let __ret: [G; OUT_658] = unsafe { *(record.function_queries[658].output_at(__i).as_ptr() as *const [G; OUT_658]) }; __ret }, _ => aiur_fn_658(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_0, __v_4, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __ret: [G; OUT_659] = [__v_5]; - record.function_queries[659].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_658] = [__v_5]; + record.function_queries[658].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_660: usize = 3; -const IN_660: usize = 3; -const OUT_660: usize = 1; -fn aiur_fn_660( - inp: [G; IN_660], +const INPUT_SIZE_659: usize = 3; +const IN_659: usize = 3; +const OUT_659: usize = 1; +fn aiur_fn_659( + inp: [G; IN_659], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_660], ExecError> { +) -> Result<[G; OUT_659], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56045,8 +55999,8 @@ fn aiur_fn_660( let __v_3: G = (__v_1 - __v_2); match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_660] = [__v_0]; - record.function_queries[660].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_659] = [__v_0]; + record.function_queries[659].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56061,25 +56015,25 @@ fn aiur_fn_660( let __v_12: G = { let __values: [G; 4] = [__v_10, __v_0, __v_9, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_13: G = G::from_u64(1); let __v_14: G = (__v_2 + __v_13); - let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_12, __v_1, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_659] = { let __args: [G; IN_659] = [__v_12, __v_1, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[659].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[659].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[659].bump_multiplicity(__i); } let __ret: [G; OUT_659] = unsafe { *(record.function_queries[659].output_at(__i).as_ptr() as *const [G; OUT_659]) }; __ret }, _ => aiur_fn_659(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; - let __ret: [G; OUT_660] = [__v_15]; - record.function_queries[660].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_659] = [__v_15]; + record.function_queries[659].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_661: usize = 2; -const IN_661: usize = 2; -const OUT_661: usize = 1; -fn aiur_fn_661( - inp: [G; IN_661], +const INPUT_SIZE_660: usize = 2; +const IN_660: usize = 2; +const OUT_660: usize = 1; +fn aiur_fn_660( + inp: [G; IN_660], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_661], ExecError> { +) -> Result<[G; OUT_660], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56089,18 +56043,18 @@ fn aiur_fn_661( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_661] = [__v_0]; - record.function_queries[661].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_660] = [__v_0]; + record.function_queries[660].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(5); - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_5, __v_3, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_661] = [__v_8]; - record.function_queries[661].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_660] = [__v_8]; + record.function_queries[660].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56110,15 +56064,15 @@ fn aiur_fn_661( }) } -const INPUT_SIZE_662: usize = 2; -const IN_662: usize = 2; -const OUT_662: usize = 2; -fn aiur_fn_662( - inp: [G; IN_662], +const INPUT_SIZE_661: usize = 2; +const IN_661: usize = 2; +const OUT_661: usize = 2; +fn aiur_fn_661( + inp: [G; IN_661], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_662], ExecError> { +) -> Result<[G; OUT_661], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56127,8 +56081,8 @@ fn aiur_fn_662( let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); let __v_4: G = { let __values: [G; 3] = [__v_2, __v_3, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_662] = [__v_4, __v_0]; - record.function_queries[662].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_661] = [__v_4, __v_0]; + record.function_queries[661].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56141,20 +56095,20 @@ fn aiur_fn_662( 5u64 => { let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 - __v_6); - let __r_arr: [G; OUT_662] = { let __args: [G; IN_662] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[662].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[662].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[662].bump_multiplicity(__i); } let __ret: [G; OUT_662] = unsafe { *(record.function_queries[662].output_at(__i).as_ptr() as *const [G; OUT_662]) }; __ret }, _ => aiur_fn_662(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = G::from_u64(0); let __v_11: G = { let __values: [G; 3] = [__v_10, __v_3, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_662] = [__v_11, __v_9]; - record.function_queries[662].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_661] = [__v_11, __v_9]; + record.function_queries[661].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_9.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -56165,21 +56119,21 @@ fn aiur_fn_662( 5u64 => { let __v_14: G = G::from_u64(1); let __v_15: G = (__v_1 - __v_14); - let __r_arr: [G; OUT_662] = { let __args: [G; IN_662] = [__v_12, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[662].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[662].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[662].bump_multiplicity(__i); } let __ret: [G; OUT_662] = unsafe { *(record.function_queries[662].output_at(__i).as_ptr() as *const [G; OUT_662]) }; __ret }, _ => aiur_fn_662(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_12, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = __r_arr[1]; let __v_18: G = G::from_u64(0); let __v_19: G = { let __values: [G; 3] = [__v_18, __v_11, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_662] = [__v_19, __v_17]; - record.function_queries[662].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_661] = [__v_19, __v_17]; + record.function_queries[661].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(1); let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 3] = [__v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_662] = [__v_16, __v_0]; - record.function_queries[662].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_661] = [__v_16, __v_0]; + record.function_queries[661].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -56190,15 +56144,15 @@ fn aiur_fn_662( }) } -const INPUT_SIZE_663: usize = 3; -const IN_663: usize = 3; -const OUT_663: usize = 1; -fn aiur_fn_663( - inp: [G; IN_663], +const INPUT_SIZE_662: usize = 3; +const IN_662: usize = 3; +const OUT_662: usize = 1; +fn aiur_fn_662( + inp: [G; IN_662], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_663], ExecError> { +) -> Result<[G; OUT_662], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56212,21 +56166,21 @@ fn aiur_fn_663( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_663] = [__v_8]; - record.function_queries[663].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_662] = [__v_8]; + record.function_queries[662].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = (__v_2 + __v_8); - let __r_arr: [G; OUT_663] = { let __args: [G; IN_663] = [__v_5, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[663].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[663].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[663].bump_multiplicity(__i); } let __ret: [G; OUT_663] = unsafe { *(record.function_queries[663].output_at(__i).as_ptr() as *const [G; OUT_663]) }; __ret }, _ => aiur_fn_663(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_662] = { let __args: [G; IN_662] = [__v_5, __v_1, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[662].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[662].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[662].bump_multiplicity(__i); } let __ret: [G; OUT_662] = unsafe { *(record.function_queries[662].output_at(__i).as_ptr() as *const [G; OUT_662]) }; __ret }, _ => aiur_fn_662(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = { let __values: [G; 3] = [__v_6, __v_7, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_663] = [__v_11]; - record.function_queries[663].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_662] = [__v_11]; + record.function_queries[662].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56236,15 +56190,15 @@ fn aiur_fn_663( }) } -const INPUT_SIZE_664: usize = 6; -const IN_664: usize = 6; -const OUT_664: usize = 1; -fn aiur_fn_664( - inp: [G; IN_664], +const INPUT_SIZE_663: usize = 6; +const IN_663: usize = 6; +const OUT_663: usize = 1; +fn aiur_fn_663( + inp: [G; IN_663], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_664], ExecError> { +) -> Result<[G; OUT_663], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56254,33 +56208,33 @@ fn aiur_fn_664( let __v_5: G = inp[5]; match __v_4.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_658] = { let __args: [G; IN_658] = [__v_0, __v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[658].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[658].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[658].bump_multiplicity(__i); } let __ret: [G; OUT_658] = unsafe { *(record.function_queries[658].output_at(__i).as_ptr() as *const [G; OUT_658]) }; __ret }, _ => aiur_fn_658(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_0, __v_5, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_664] = [__v_6]; - record.function_queries[664].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_663] = [__v_6]; + record.function_queries[663].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_0, __v_1, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_0, __v_1, __v_2, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_664] = [__v_7]; - record.function_queries[664].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_663] = [__v_7]; + record.function_queries[663].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_665: usize = 3; -const IN_665: usize = 3; -const OUT_665: usize = 1; -fn aiur_fn_665( - inp: [G; IN_665], +const INPUT_SIZE_664: usize = 3; +const IN_664: usize = 3; +const OUT_664: usize = 1; +fn aiur_fn_664( + inp: [G; IN_664], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_665], ExecError> { +) -> Result<[G; OUT_664], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56288,8 +56242,8 @@ fn aiur_fn_665( let __v_3: G = (__v_1 - __v_2); match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_665] = [__v_0]; - record.function_queries[665].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_664] = [__v_0]; + record.function_queries[664].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56302,25 +56256,25 @@ fn aiur_fn_665( let __v_10: G = { let __values: [G; 4] = [__v_8, __v_0, __v_7, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_11: G = G::from_u64(1); let __v_12: G = (__v_2 + __v_11); - let __r_arr: [G; OUT_665] = { let __args: [G; IN_665] = [__v_10, __v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[665].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[665].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[665].bump_multiplicity(__i); } let __ret: [G; OUT_665] = unsafe { *(record.function_queries[665].output_at(__i).as_ptr() as *const [G; OUT_665]) }; __ret }, _ => aiur_fn_665(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_664] = { let __args: [G; IN_664] = [__v_10, __v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[664].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[664].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[664].bump_multiplicity(__i); } let __ret: [G; OUT_664] = unsafe { *(record.function_queries[664].output_at(__i).as_ptr() as *const [G; OUT_664]) }; __ret }, _ => aiur_fn_664(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_665] = [__v_13]; - record.function_queries[665].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_664] = [__v_13]; + record.function_queries[664].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_666: usize = 9; -const IN_666: usize = 9; -const OUT_666: usize = 1; -fn aiur_fn_666( - inp: [G; IN_666], +const INPUT_SIZE_665: usize = 9; +const IN_665: usize = 9; +const OUT_665: usize = 1; +fn aiur_fn_665( + inp: [G; IN_665], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_666], ExecError> { +) -> Result<[G; OUT_665], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56331,12 +56285,12 @@ fn aiur_fn_666( let __v_6: G = inp[6]; let __v_7: G = inp[7]; let __v_8: G = inp[8]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_1, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_655] = { let __args: [G; IN_655] = [__v_9, __v_2, __v_6, __v_7, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[655].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[655].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[655].bump_multiplicity(__i); } let __ret: [G; OUT_655] = unsafe { *(record.function_queries[655].output_at(__i).as_ptr() as *const [G; OUT_655]) }; __ret }, _ => aiur_fn_655(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_654] = { let __args: [G; IN_654] = [__v_9, __v_2, __v_6, __v_7, __v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[654].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[654].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[654].bump_multiplicity(__i); } let __ret: [G; OUT_654] = unsafe { *(record.function_queries[654].output_at(__i).as_ptr() as *const [G; OUT_654]) }; __ret }, _ => aiur_fn_654(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_656] = { let __args: [G; IN_656] = [__v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[656].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[656].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[656].bump_multiplicity(__i); } let __ret: [G; OUT_656] = unsafe { *(record.function_queries[656].output_at(__i).as_ptr() as *const [G; OUT_656]) }; __ret }, _ => aiur_fn_656(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_655] = { let __args: [G; IN_655] = [__v_11, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[655].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[655].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[655].bump_multiplicity(__i); } let __ret: [G; OUT_655] = unsafe { *(record.function_queries[655].output_at(__i).as_ptr() as *const [G; OUT_655]) }; __ret }, _ => aiur_fn_655(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(2); let __v_14: G = G::from_u64(0); @@ -56344,12 +56298,12 @@ fn aiur_fn_666( let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_7.as_canonical_u64() { 0u64 => { let __v_16: G = G::from_u64(0); - let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_15, __v_6, __v_3, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_656] = { let __args: [G; IN_656] = [__v_15, __v_6, __v_3, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[656].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[656].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[656].bump_multiplicity(__i); } let __ret: [G; OUT_656] = unsafe { *(record.function_queries[656].output_at(__i).as_ptr() as *const [G; OUT_656]) }; __ret }, _ => aiur_fn_656(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; break '__mc_0 [__v_17]; }, _ => { - let __r_arr: [G; OUT_658] = { let __args: [G; IN_658] = [__v_15, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[658].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[658].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[658].bump_multiplicity(__i); } let __ret: [G; OUT_658] = unsafe { *(record.function_queries[658].output_at(__i).as_ptr() as *const [G; OUT_658]) }; __ret }, _ => aiur_fn_658(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_15, __v_8, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; break '__mc_0 [__v_16]; }, @@ -56357,7 +56311,7 @@ fn aiur_fn_666( }; let __v_16: G = __mc_out___mc_0[0]; let __v_17: G = G::from_u64(0); - let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_16, __v_3, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_659] = { let __args: [G; IN_659] = [__v_16, __v_3, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[659].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[659].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[659].bump_multiplicity(__i); } let __ret: [G; OUT_659] = unsafe { *(record.function_queries[659].output_at(__i).as_ptr() as *const [G; OUT_659]) }; __ret }, _ => aiur_fn_659(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(0); @@ -56365,45 +56319,45 @@ fn aiur_fn_666( let __v_22: G = G::from_u64(5); let __v_23: G = G::from_u64(0); let __v_24: G = { let __values: [G; 4] = [__v_22, __v_18, __v_21, __v_23]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_24, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_24, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; - let __ret: [G; OUT_666] = [__v_25]; - record.function_queries[666].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_665] = [__v_25]; + record.function_queries[665].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_667: usize = 3; -const IN_667: usize = 3; -const OUT_667: usize = 1; -fn aiur_fn_667( - inp: [G; IN_667], +const INPUT_SIZE_666: usize = 3; +const IN_666: usize = 3; +const OUT_666: usize = 1; +fn aiur_fn_666( + inp: [G; IN_666], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_667], ExecError> { +) -> Result<[G; OUT_666], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = G::from_u64(0); - let __r_arr: [G; OUT_702] = { let __args: [G; IN_702] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[702].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[702].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[702].bump_multiplicity(__i); } let __ret: [G; OUT_702] = unsafe { *(record.function_queries[702].output_at(__i).as_ptr() as *const [G; OUT_702]) }; __ret }, _ => aiur_fn_702(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_701] = { let __args: [G; IN_701] = [__v_0, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[701].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[701].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[701].bump_multiplicity(__i); } let __ret: [G; OUT_701] = unsafe { *(record.function_queries[701].output_at(__i).as_ptr() as *const [G; OUT_701]) }; __ret }, _ => aiur_fn_701(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_667] = [__v_4]; - record.function_queries[667].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_666] = [__v_4]; + record.function_queries[666].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_668: usize = 4; -const IN_668: usize = 4; -const OUT_668: usize = 1; -fn aiur_fn_668( - inp: [G; IN_668], +const INPUT_SIZE_667: usize = 4; +const IN_667: usize = 4; +const OUT_667: usize = 1; +fn aiur_fn_667( + inp: [G; IN_667], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_668], ExecError> { +) -> Result<[G; OUT_667], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56412,8 +56366,8 @@ fn aiur_fn_668( let __v_4: G = (__v_1 - __v_3); match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_668] = [__v_0]; - record.function_queries[668].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_667] = [__v_0]; + record.function_queries[667].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56426,25 +56380,25 @@ fn aiur_fn_668( let __v_11: G = { let __values: [G; 4] = [__v_9, __v_0, __v_8, __v_10]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_12: G = G::from_u64(1); let __v_13: G = (__v_3 + __v_12); - let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_11, __v_1, __v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_11, __v_1, __v_2, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_668] = [__v_14]; - record.function_queries[668].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_667] = [__v_14]; + record.function_queries[667].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_669: usize = 2; -const IN_669: usize = 2; -const OUT_669: usize = 1; -fn aiur_fn_669( - inp: [G; IN_669], +const INPUT_SIZE_668: usize = 2; +const IN_668: usize = 2; +const OUT_668: usize = 1; +fn aiur_fn_668( + inp: [G; IN_668], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_669], ExecError> { +) -> Result<[G; OUT_668], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56454,18 +56408,18 @@ fn aiur_fn_669( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_669] = [__v_0]; - record.function_queries[669].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_668] = [__v_0]; + record.function_queries[668].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(4); - let __r_arr: [G; OUT_669] = { let __args: [G; IN_669] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[669].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[669].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[669].bump_multiplicity(__i); } let __ret: [G; OUT_669] = unsafe { *(record.function_queries[669].output_at(__i).as_ptr() as *const [G; OUT_669]) }; __ret }, _ => aiur_fn_669(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_0, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(0); let __v_8: G = { let __values: [G; 4] = [__v_5, __v_3, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_669] = [__v_8]; - record.function_queries[669].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_668] = [__v_8]; + record.function_queries[668].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56475,15 +56429,15 @@ fn aiur_fn_669( }) } -const INPUT_SIZE_670: usize = 9; -const IN_670: usize = 9; -const OUT_670: usize = 1; -fn aiur_fn_670( - inp: [G; IN_670], +const INPUT_SIZE_669: usize = 9; +const IN_669: usize = 9; +const OUT_669: usize = 1; +fn aiur_fn_669( + inp: [G; IN_669], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_670], ExecError> { +) -> Result<[G; OUT_669], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56495,12 +56449,12 @@ fn aiur_fn_670( let __v_7: G = inp[7]; let __v_8: G = inp[8]; let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_653] = { let __args: [G; IN_653] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[653].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[653].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[653].bump_multiplicity(__i); } let __ret: [G; OUT_653] = unsafe { *(record.function_queries[653].output_at(__i).as_ptr() as *const [G; OUT_653]) }; __ret }, _ => aiur_fn_653(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_652] = { let __args: [G; IN_652] = [__v_6, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[652].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[652].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[652].bump_multiplicity(__i); } let __ret: [G; OUT_652] = unsafe { *(record.function_queries[652].output_at(__i).as_ptr() as *const [G; OUT_652]) }; __ret }, _ => aiur_fn_652(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; let __v_13: G = __r_arr[3]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_14.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_15: G = __loaded[0]; @@ -56517,32 +56471,32 @@ fn aiur_fn_670( let __v_26: G = __loaded[11]; match __v_15.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_671] = { let __args: [G; IN_671] = [__v_17, __v_16, __v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[671].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[671].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[671].bump_multiplicity(__i); } let __ret: [G; OUT_671] = unsafe { *(record.function_queries[671].output_at(__i).as_ptr() as *const [G; OUT_671]) }; __ret }, _ => aiur_fn_671(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_670] = { let __args: [G; IN_670] = [__v_17, __v_16, __v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[670].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[670].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[670].bump_multiplicity(__i); } let __ret: [G; OUT_670] = unsafe { *(record.function_queries[670].output_at(__i).as_ptr() as *const [G; OUT_670]) }; __ret }, _ => aiur_fn_670(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __ret: [G; OUT_670] = [__v_27]; - record.function_queries[670].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_669] = [__v_27]; + record.function_queries[669].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_671] = { let __args: [G; IN_671] = [__v_0, __v_1, __v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[671].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[671].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[671].bump_multiplicity(__i); } let __ret: [G; OUT_671] = unsafe { *(record.function_queries[671].output_at(__i).as_ptr() as *const [G; OUT_671]) }; __ret }, _ => aiur_fn_671(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_670] = { let __args: [G; IN_670] = [__v_0, __v_1, __v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[670].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[670].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[670].bump_multiplicity(__i); } let __ret: [G; OUT_670] = unsafe { *(record.function_queries[670].output_at(__i).as_ptr() as *const [G; OUT_670]) }; __ret }, _ => aiur_fn_670(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __ret: [G; OUT_670] = [__v_27]; - record.function_queries[670].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_669] = [__v_27]; + record.function_queries[669].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_671: usize = 11; -const IN_671: usize = 11; -const OUT_671: usize = 1; -fn aiur_fn_671( - inp: [G; IN_671], +const INPUT_SIZE_670: usize = 11; +const IN_670: usize = 11; +const OUT_670: usize = 1; +fn aiur_fn_670( + inp: [G; IN_670], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_671], ExecError> { +) -> Result<[G; OUT_670], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56555,28 +56509,28 @@ fn aiur_fn_671( let __v_8: G = inp[8]; let __v_9: G = inp[9]; let __v_10: G = inp[10]; - let __r_arr: [G; OUT_789] = { let __args: [G; IN_789] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[789].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[789].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[789].bump_multiplicity(__i); } let __ret: [G; OUT_789] = unsafe { *(record.function_queries[789].output_at(__i).as_ptr() as *const [G; OUT_789]) }; __ret }, _ => aiur_fn_789(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_788] = { let __args: [G; IN_788] = [__v_8]; let __cu = unconstrained; let __hit = record.function_queries[788].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[788].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[788].bump_multiplicity(__i); } let __ret: [G; OUT_788] = unsafe { *(record.function_queries[788].output_at(__i).as_ptr() as *const [G; OUT_788]) }; __ret }, _ => aiur_fn_788(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_638] = { let __args: [G; IN_638] = [__v_7, __v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[638].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[638].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[638].bump_multiplicity(__i); } let __ret: [G; OUT_638] = unsafe { *(record.function_queries[638].output_at(__i).as_ptr() as *const [G; OUT_638]) }; __ret }, _ => aiur_fn_638(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_637] = { let __args: [G; IN_637] = [__v_7, __v_1, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[637].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[637].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[637].bump_multiplicity(__i); } let __ret: [G; OUT_637] = unsafe { *(record.function_queries[637].output_at(__i).as_ptr() as *const [G; OUT_637]) }; __ret }, _ => aiur_fn_637(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __r_arr: [G; OUT_662] = { let __args: [G; IN_662] = [__v_14, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[662].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[662].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[662].bump_multiplicity(__i); } let __ret: [G; OUT_662] = unsafe { *(record.function_queries[662].output_at(__i).as_ptr() as *const [G; OUT_662]) }; __ret }, _ => aiur_fn_662(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_14, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; - let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_8, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_666] = { let __args: [G; IN_666] = [__v_8, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[666].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[666].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[666].bump_multiplicity(__i); } let __ret: [G; OUT_666] = unsafe { *(record.function_queries[666].output_at(__i).as_ptr() as *const [G; OUT_666]) }; __ret }, _ => aiur_fn_666(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; - let __r_arr: [G; OUT_685] = { let __args: [G; IN_685] = [__v_8, __v_9, __v_4, __v_11, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[685].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[685].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[685].bump_multiplicity(__i); } let __ret: [G; OUT_685] = unsafe { *(record.function_queries[685].output_at(__i).as_ptr() as *const [G; OUT_685]) }; __ret }, _ => aiur_fn_685(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_684] = { let __args: [G; IN_684] = [__v_8, __v_9, __v_4, __v_11, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[684].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[684].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[684].bump_multiplicity(__i); } let __ret: [G; OUT_684] = unsafe { *(record.function_queries[684].output_at(__i).as_ptr() as *const [G; OUT_684]) }; __ret }, _ => aiur_fn_684(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_653] = { let __args: [G; IN_653] = [__v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[653].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[653].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[653].bump_multiplicity(__i); } let __ret: [G; OUT_653] = unsafe { *(record.function_queries[653].output_at(__i).as_ptr() as *const [G; OUT_653]) }; __ret }, _ => aiur_fn_653(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_652] = { let __args: [G; IN_652] = [__v_8, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[652].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[652].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[652].bump_multiplicity(__i); } let __ret: [G; OUT_652] = unsafe { *(record.function_queries[652].output_at(__i).as_ptr() as *const [G; OUT_652]) }; __ret }, _ => aiur_fn_652(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; let __v_21: G = __r_arr[1]; let __v_22: G = __r_arr[2]; let __v_23: G = __r_arr[3]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_24.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_25: G = __loaded[0]; @@ -56593,16 +56547,16 @@ fn aiur_fn_671( let __v_36: G = __loaded[11]; match __v_25.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_27, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_27, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = G::from_u64(0); - let __r_arr: [G; OUT_655] = { let __args: [G; IN_655] = [__v_37, __v_28, __v_4, __v_21, __v_22, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[655].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[655].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[655].bump_multiplicity(__i); } let __ret: [G; OUT_655] = unsafe { *(record.function_queries[655].output_at(__i).as_ptr() as *const [G; OUT_655]) }; __ret }, _ => aiur_fn_655(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_654] = { let __args: [G; IN_654] = [__v_37, __v_28, __v_4, __v_21, __v_22, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[654].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[654].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[654].bump_multiplicity(__i); } let __ret: [G; OUT_654] = unsafe { *(record.function_queries[654].output_at(__i).as_ptr() as *const [G; OUT_654]) }; __ret }, _ => aiur_fn_654(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; - let __r_arr: [G; OUT_656] = { let __args: [G; IN_656] = [__v_39, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[656].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[656].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[656].bump_multiplicity(__i); } let __ret: [G; OUT_656] = unsafe { *(record.function_queries[656].output_at(__i).as_ptr() as *const [G; OUT_656]) }; __ret }, _ => aiur_fn_656(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_655] = { let __args: [G; IN_655] = [__v_39, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[655].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[655].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[655].bump_multiplicity(__i); } let __ret: [G; OUT_655] = unsafe { *(record.function_queries[655].output_at(__i).as_ptr() as *const [G; OUT_655]) }; __ret }, _ => aiur_fn_655(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; let __v_41: G = (__v_11 + __v_19); let __v_42: G = G::from_u64(0); - let __r_arr: [G; OUT_663] = { let __args: [G; IN_663] = [__v_40, __v_41, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[663].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[663].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[663].bump_multiplicity(__i); } let __ret: [G; OUT_663] = unsafe { *(record.function_queries[663].output_at(__i).as_ptr() as *const [G; OUT_663]) }; __ret }, _ => aiur_fn_663(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_662] = { let __args: [G; IN_662] = [__v_40, __v_41, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[662].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[662].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[662].bump_multiplicity(__i); } let __ret: [G; OUT_662] = unsafe { *(record.function_queries[662].output_at(__i).as_ptr() as *const [G; OUT_662]) }; __ret }, _ => aiur_fn_662(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; let __v_44: G = G::from_u64(2); let __v_45: G = G::from_u64(0); @@ -56616,13 +56570,13 @@ fn aiur_fn_671( let __v_53: G = (__v_52 + __v_5); let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_21.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_658] = { let __args: [G; IN_658] = [__v_46, __v_22, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[658].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[658].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[658].bump_multiplicity(__i); } let __ret: [G; OUT_658] = unsafe { *(record.function_queries[658].output_at(__i).as_ptr() as *const [G; OUT_658]) }; __ret }, _ => aiur_fn_658(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_46, __v_22, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; break '__mc_0 [__v_54]; }, _ => { let __v_54: G = G::from_u64(0); - let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_46, __v_4, __v_51, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_46, __v_4, __v_51, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; break '__mc_0 [__v_55]; }, @@ -56630,7 +56584,7 @@ fn aiur_fn_671( }; let __v_54: G = __mc_out___mc_0[0]; let __v_55: G = G::from_u64(0); - let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_54, __v_5, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_659] = { let __args: [G; IN_659] = [__v_54, __v_5, __v_55]; let __cu = unconstrained; let __hit = record.function_queries[659].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[659].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[659].bump_multiplicity(__i); } let __ret: [G; OUT_659] = unsafe { *(record.function_queries[659].output_at(__i).as_ptr() as *const [G; OUT_659]) }; __ret }, _ => aiur_fn_659(__args, record, io_buffer, __cu)? } }; let __v_56: G = __r_arr[0]; let __v_57: G = G::from_u64(1); let __v_58: G = (__v_49 + __v_57); @@ -56642,7 +56596,7 @@ fn aiur_fn_671( let __v_64: G = G::from_u64(0); let __v_65: G = { let __values: [G; 4] = [__v_63, __v_62, __v_64, __v_64]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_66: G = G::from_u64(0); - let __r_arr: [G; OUT_665] = { let __args: [G; IN_665] = [__v_65, __v_5, __v_66]; let __cu = unconstrained; let __hit = record.function_queries[665].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[665].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[665].bump_multiplicity(__i); } let __ret: [G; OUT_665] = unsafe { *(record.function_queries[665].output_at(__i).as_ptr() as *const [G; OUT_665]) }; __ret }, _ => aiur_fn_665(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_664] = { let __args: [G; IN_664] = [__v_65, __v_5, __v_66]; let __cu = unconstrained; let __hit = record.function_queries[664].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[664].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[664].bump_multiplicity(__i); } let __ret: [G; OUT_664] = unsafe { *(record.function_queries[664].output_at(__i).as_ptr() as *const [G; OUT_664]) }; __ret }, _ => aiur_fn_664(__args, record, io_buffer, __cu)? } }; let __v_67: G = __r_arr[0]; let __v_68: G = G::from_u64(3); let __v_69: G = G::from_u64(0); @@ -56654,16 +56608,16 @@ fn aiur_fn_671( let __v_75: G = G::from_u64(5); let __v_76: G = G::from_u64(0); let __v_77: G = { let __values: [G; 4] = [__v_75, __v_56, __v_74, __v_76]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_77, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_77, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_78: G = __r_arr[0]; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_78, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_78, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_79: G = __r_arr[0]; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_79, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_79, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_80: G = __r_arr[0]; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_80, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_80, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_81: G = __r_arr[0]; - let __ret: [G; OUT_671] = [__v_81]; - record.function_queries[671].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_670] = [__v_81]; + record.function_queries[670].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56673,15 +56627,15 @@ fn aiur_fn_671( }) } -const INPUT_SIZE_672: usize = 26; -const IN_672: usize = 26; -const OUT_672: usize = 0; -fn aiur_fn_672( - inp: [G; IN_672], +const INPUT_SIZE_671: usize = 26; +const IN_671: usize = 26; +const OUT_671: usize = 0; +fn aiur_fn_671( + inp: [G; IN_671], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_672], ExecError> { +) -> Result<[G; OUT_671], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56716,7 +56670,7 @@ fn aiur_fn_672( let __mc_out___mc_0: [G; 13] = '__mc_0: { match __v_18.as_canonical_u64() { 1u64 => { let __v_26: G = G::from_u64(0); - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_20, __v_21, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_20, __v_21, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_27.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_28: G = __loaded[0]; @@ -56767,11 +56721,11 @@ fn aiur_fn_672( let __v_40: G = G::from_u64(1); let __v_41: G = G::from_u64(1); let __v_42: G = { let __values: [G; 3] = [__v_40, __v_41, __v_41]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_15, __v_39, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_15, __v_39, __v_42]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; - let __r_arr: [G; OUT_631] = { let __args: [G; IN_631] = [__v_20, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[631].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[631].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[631].bump_multiplicity(__i); } let __ret: [G; OUT_631] = unsafe { *(record.function_queries[631].output_at(__i).as_ptr() as *const [G; OUT_631]) }; __ret }, _ => aiur_fn_631(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_630] = { let __args: [G; IN_630] = [__v_20, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[630].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[630].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[630].bump_multiplicity(__i); } let __ret: [G; OUT_630] = unsafe { *(record.function_queries[630].output_at(__i).as_ptr() as *const [G; OUT_630]) }; __ret }, _ => aiur_fn_630(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; - let __r_arr: [G; OUT_625] = { let __args: [G; IN_625] = [__v_43, __v_18, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_44]; let __cu = unconstrained; let __hit = record.function_queries[625].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[625].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[625].bump_multiplicity(__i); } let __ret: [G; OUT_625] = unsafe { *(record.function_queries[625].output_at(__i).as_ptr() as *const [G; OUT_625]) }; __ret }, _ => aiur_fn_625(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_624] = { let __args: [G; IN_624] = [__v_43, __v_18, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_44]; let __cu = unconstrained; let __hit = record.function_queries[624].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[624].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[624].bump_multiplicity(__i); } let __ret: [G; OUT_624] = unsafe { *(record.function_queries[624].output_at(__i).as_ptr() as *const [G; OUT_624]) }; __ret }, _ => aiur_fn_624(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; let __mc_out___mc_1: [G; 1] = '__mc_1: { match __v_45.as_canonical_u64() { 1u64 => { @@ -56791,17 +56745,17 @@ fn aiur_fn_672( }; let __v_46: G = __mc_out___mc_1[0]; let __v_47: G = G::from_u64(0); - let __r_arr: [G; OUT_705] = { let __args: [G; IN_705] = [__v_1, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[705].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[705].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[705].bump_multiplicity(__i); } let __ret: [G; OUT_705] = unsafe { *(record.function_queries[705].output_at(__i).as_ptr() as *const [G; OUT_705]) }; __ret }, _ => aiur_fn_705(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_704] = { let __args: [G; IN_704] = [__v_1, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[704].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[704].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[704].bump_multiplicity(__i); } let __ret: [G; OUT_704] = unsafe { *(record.function_queries[704].output_at(__i).as_ptr() as *const [G; OUT_704]) }; __ret }, _ => aiur_fn_704(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; - let __r_arr: [G; OUT_648] = { let __args: [G; IN_648] = [__v_10, __v_20, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[648].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[648].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[648].bump_multiplicity(__i); } let __ret: [G; OUT_648] = unsafe { *(record.function_queries[648].output_at(__i).as_ptr() as *const [G; OUT_648]) }; __ret }, _ => aiur_fn_648(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_647] = { let __args: [G; IN_647] = [__v_10, __v_20, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[647].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[647].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[647].bump_multiplicity(__i); } let __ret: [G; OUT_647] = unsafe { *(record.function_queries[647].output_at(__i).as_ptr() as *const [G; OUT_647]) }; __ret }, _ => aiur_fn_647(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_679] = { let __args: [G; IN_679] = [__v_49, __v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[679].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[679].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[679].bump_multiplicity(__i); } let __ret: [G; OUT_679] = unsafe { *(record.function_queries[679].output_at(__i).as_ptr() as *const [G; OUT_679]) }; __ret }, _ => aiur_fn_679(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_678] = { let __args: [G; IN_678] = [__v_49, __v_10, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[678].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[678].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[678].bump_multiplicity(__i); } let __ret: [G; OUT_678] = unsafe { *(record.function_queries[678].output_at(__i).as_ptr() as *const [G; OUT_678]) }; __ret }, _ => aiur_fn_678(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __r_arr: [G; OUT_682] = { let __args: [G; IN_682] = [__v_49]; let __cu = unconstrained; let __hit = record.function_queries[682].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[682].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[682].bump_multiplicity(__i); } let __ret: [G; OUT_682] = unsafe { *(record.function_queries[682].output_at(__i).as_ptr() as *const [G; OUT_682]) }; __ret }, _ => aiur_fn_682(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_681] = { let __args: [G; IN_681] = [__v_49]; let __cu = unconstrained; let __hit = record.function_queries[681].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[681].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[681].bump_multiplicity(__i); } let __ret: [G; OUT_681] = unsafe { *(record.function_queries[681].output_at(__i).as_ptr() as *const [G; OUT_681]) }; __ret }, _ => aiur_fn_681(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_631] = { let __args: [G; IN_631] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[631].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[631].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[631].bump_multiplicity(__i); } let __ret: [G; OUT_631] = unsafe { *(record.function_queries[631].output_at(__i).as_ptr() as *const [G; OUT_631]) }; __ret }, _ => aiur_fn_631(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_631] = { let __args: [G; IN_631] = [__v_20]; let __cu = unconstrained; let __hit = record.function_queries[631].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[631].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[631].bump_multiplicity(__i); } let __ret: [G; OUT_631] = unsafe { *(record.function_queries[631].output_at(__i).as_ptr() as *const [G; OUT_631]) }; __ret }, _ => aiur_fn_631(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __v_54: G = G::from_u64(1); let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_10, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; @@ -56811,7 +56765,7 @@ fn aiur_fn_672( let __v_58: G = (__v_52 * __v_57); let __mc_out___mc_2: [G; 1] = '__mc_2: { match __v_58.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_645] = { let __args: [G; IN_645] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[645].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[645].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[645].bump_multiplicity(__i); } let __ret: [G; OUT_645] = unsafe { *(record.function_queries[645].output_at(__i).as_ptr() as *const [G; OUT_645]) }; __ret }, _ => aiur_fn_645(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_644] = { let __args: [G; IN_644] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[644].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[644].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[644].bump_multiplicity(__i); } let __ret: [G; OUT_644] = unsafe { *(record.function_queries[644].output_at(__i).as_ptr() as *const [G; OUT_644]) }; __ret }, _ => aiur_fn_644(__args, record, io_buffer, __cu)? } }; let __v_59: G = __r_arr[0]; break '__mc_2 [__v_59]; }, @@ -56825,26 +56779,26 @@ fn aiur_fn_672( }; let __v_59: G = __mc_out___mc_2[0]; let __v_60: G = G::from_u64(0); - let __r_arr: [G; OUT_652] = { let __args: [G; IN_652] = [__v_49, __v_25, __v_58, __v_59, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[652].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[652].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[652].bump_multiplicity(__i); } let __ret: [G; OUT_652] = unsafe { *(record.function_queries[652].output_at(__i).as_ptr() as *const [G; OUT_652]) }; __ret }, _ => aiur_fn_652(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_651] = { let __args: [G; IN_651] = [__v_49, __v_25, __v_58, __v_59, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[651].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[651].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[651].bump_multiplicity(__i); } let __ret: [G; OUT_651] = unsafe { *(record.function_queries[651].output_at(__i).as_ptr() as *const [G; OUT_651]) }; __ret }, _ => aiur_fn_651(__args, record, io_buffer, __cu)? } }; let __v_61: G = __r_arr[0]; let __v_62: G = __r_arr[1]; match __v_61.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_673] = { let __args: [G; IN_673] = [__v_49, __v_62, __v_18, __v_20, __v_21, __v_3, __v_5, __v_6, __v_48, __v_50, __v_51, __v_7, __v_2, __v_15, __v_14, __v_17, __v_46, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[673].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[673].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[673].bump_multiplicity(__i); } let __ret: [G; OUT_673] = unsafe { *(record.function_queries[673].output_at(__i).as_ptr() as *const [G; OUT_673]) }; __ret }, _ => aiur_fn_673(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_672] = []; - record.function_queries[672].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_672] = { let __args: [G; IN_672] = [__v_49, __v_62, __v_18, __v_20, __v_21, __v_3, __v_5, __v_6, __v_48, __v_50, __v_51, __v_7, __v_2, __v_15, __v_14, __v_17, __v_46, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[672].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[672].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[672].bump_multiplicity(__i); } let __ret: [G; OUT_672] = unsafe { *(record.function_queries[672].output_at(__i).as_ptr() as *const [G; OUT_672]) }; __ret }, _ => aiur_fn_672(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_671] = []; + record.function_queries[671].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_63: G = G::from_u64(0); - let __r_arr: [G; OUT_651] = { let __args: [G; IN_651] = [__v_49, __v_25, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[651].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[651].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[651].bump_multiplicity(__i); } let __ret: [G; OUT_651] = unsafe { *(record.function_queries[651].output_at(__i).as_ptr() as *const [G; OUT_651]) }; __ret }, _ => aiur_fn_651(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_650] = { let __args: [G; IN_650] = [__v_49, __v_25, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[650].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[650].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[650].bump_multiplicity(__i); } let __ret: [G; OUT_650] = unsafe { *(record.function_queries[650].output_at(__i).as_ptr() as *const [G; OUT_650]) }; __ret }, _ => aiur_fn_650(__args, record, io_buffer, __cu)? } }; let __v_64: G = __r_arr[0]; let __v_65: G = __r_arr[1]; match __v_64.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_673] = { let __args: [G; IN_673] = [__v_49, __v_65, __v_18, __v_20, __v_21, __v_3, __v_5, __v_6, __v_48, __v_50, __v_51, __v_7, __v_2, __v_15, __v_14, __v_17, __v_46, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[673].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[673].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[673].bump_multiplicity(__i); } let __ret: [G; OUT_673] = unsafe { *(record.function_queries[673].output_at(__i).as_ptr() as *const [G; OUT_673]) }; __ret }, _ => aiur_fn_673(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_672] = []; - record.function_queries[672].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_672] = { let __args: [G; IN_672] = [__v_49, __v_65, __v_18, __v_20, __v_21, __v_3, __v_5, __v_6, __v_48, __v_50, __v_51, __v_7, __v_2, __v_15, __v_14, __v_17, __v_46, __v_45]; let __cu = unconstrained; let __hit = record.function_queries[672].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[672].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[672].bump_multiplicity(__i); } let __ret: [G; OUT_672] = unsafe { *(record.function_queries[672].output_at(__i).as_ptr() as *const [G; OUT_672]) }; __ret }, _ => aiur_fn_672(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_671] = []; + record.function_queries[671].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56855,8 +56809,8 @@ fn aiur_fn_672( } }, _ => { - let __ret: [G; OUT_672] = []; - record.function_queries[672].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_671] = []; + record.function_queries[671].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -56868,15 +56822,15 @@ fn aiur_fn_672( }) } -const INPUT_SIZE_673: usize = 18; -const IN_673: usize = 18; -const OUT_673: usize = 0; -fn aiur_fn_673( - inp: [G; IN_673], +const INPUT_SIZE_672: usize = 18; +const IN_672: usize = 18; +const OUT_672: usize = 0; +fn aiur_fn_672( + inp: [G; IN_672], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_673], ExecError> { +) -> Result<[G; OUT_672], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56896,27 +56850,27 @@ fn aiur_fn_673( let __v_15: G = inp[15]; let __v_16: G = inp[16]; let __v_17: G = inp[17]; - let __r_arr: [G; OUT_653] = { let __args: [G; IN_653] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[653].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[653].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[653].bump_multiplicity(__i); } let __ret: [G; OUT_653] = unsafe { *(record.function_queries[653].output_at(__i).as_ptr() as *const [G; OUT_653]) }; __ret }, _ => aiur_fn_653(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_652] = { let __args: [G; IN_652] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[652].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[652].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[652].bump_multiplicity(__i); } let __ret: [G; OUT_652] = unsafe { *(record.function_queries[652].output_at(__i).as_ptr() as *const [G; OUT_652]) }; __ret }, _ => aiur_fn_652(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = __r_arr[1]; let __v_20: G = __r_arr[2]; let __v_21: G = __r_arr[3]; - let __r_arr: [G; OUT_670] = { let __args: [G; IN_670] = [__v_13, __v_14, __v_5, __v_15, __v_16, __v_17, __v_0, __v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[670].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[670].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[670].bump_multiplicity(__i); } let __ret: [G; OUT_670] = unsafe { *(record.function_queries[670].output_at(__i).as_ptr() as *const [G; OUT_670]) }; __ret }, _ => aiur_fn_670(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_669] = { let __args: [G; IN_669] = [__v_13, __v_14, __v_5, __v_15, __v_16, __v_17, __v_0, __v_10, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[669].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[669].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[669].bump_multiplicity(__i); } let __ret: [G; OUT_669] = unsafe { *(record.function_queries[669].output_at(__i).as_ptr() as *const [G; OUT_669]) }; __ret }, _ => aiur_fn_669(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = G::from_u64(1); let __v_24: G = G::from_u64(1); let __v_25: G = { let __values: [G; 3] = [__v_23, __v_24, __v_24]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_12, __v_22, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_12, __v_22, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = G::from_u64(1); if (__v_26 != __v_27) { return Err(ExecError::AssertEqMismatch { lhs: __v_26.as_canonical_u64(), rhs: __v_27.as_canonical_u64(), msg: Some("recursor's declared type is not def-eq to the canonical reconstruction".to_string()) }); } - let __r_arr: [G; OUT_789] = { let __args: [G; IN_789] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[789].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[789].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[789].bump_multiplicity(__i); } let __ret: [G; OUT_789] = unsafe { *(record.function_queries[789].output_at(__i).as_ptr() as *const [G; OUT_789]) }; __ret }, _ => aiur_fn_789(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_788] = { let __args: [G; IN_788] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[788].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[788].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[788].bump_multiplicity(__i); } let __ret: [G; OUT_788] = unsafe { *(record.function_queries[788].output_at(__i).as_ptr() as *const [G; OUT_788]) }; __ret }, _ => aiur_fn_788(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __r_arr: [G; OUT_685] = { let __args: [G; IN_685] = [__v_0, __v_10, __v_5, __v_28, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[685].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[685].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[685].bump_multiplicity(__i); } let __ret: [G; OUT_685] = unsafe { *(record.function_queries[685].output_at(__i).as_ptr() as *const [G; OUT_685]) }; __ret }, _ => aiur_fn_685(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_684] = { let __args: [G; IN_684] = [__v_0, __v_10, __v_5, __v_28, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[684].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[684].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[684].bump_multiplicity(__i); } let __ret: [G; OUT_684] = unsafe { *(record.function_queries[684].output_at(__i).as_ptr() as *const [G; OUT_684]) }; __ret }, _ => aiur_fn_684(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; if (__v_6 != __v_28) { return Err(ExecError::AssertEqMismatch { lhs: __v_6.as_canonical_u64(), rhs: __v_28.as_canonical_u64(), msg: Some("recursor motive count disagrees with the canonical reconstruction".to_string()) }); @@ -56925,28 +56879,28 @@ fn aiur_fn_673( return Err(ExecError::AssertEqMismatch { lhs: __v_7.as_canonical_u64(), rhs: __v_30.as_canonical_u64(), msg: Some("recursor minor count disagrees with the canonical reconstruction".to_string()) }); } let __v_31: G = G::from_u64(0); - let __r_arr: [G; OUT_674] = { let __args: [G; IN_674] = [__v_0, __v_1, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[674].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[674].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[674].bump_multiplicity(__i); } let __ret: [G; OUT_674] = unsafe { *(record.function_queries[674].output_at(__i).as_ptr() as *const [G; OUT_674]) }; __ret }, _ => aiur_fn_674(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_673] = { let __args: [G; IN_673] = [__v_0, __v_1, __v_31]; let __cu = unconstrained; let __hit = record.function_queries[673].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[673].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[673].bump_multiplicity(__i); } let __ret: [G; OUT_673] = unsafe { *(record.function_queries[673].output_at(__i).as_ptr() as *const [G; OUT_673]) }; __ret }, _ => aiur_fn_673(__args, record, io_buffer, __cu)? } }; let __v_32: G = __r_arr[0]; let __v_33: G = G::from_u64(0); - let __r_arr: [G; OUT_675] = { let __args: [G; IN_675] = [__v_2, __v_32, __v_3, __v_4, __v_5, __v_6, __v_7, __v_21, __v_8, __v_0, __v_9, __v_10, __v_19, __v_20, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[675].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[675].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[675].bump_multiplicity(__i); } let __ret: [G; OUT_675] = unsafe { *(record.function_queries[675].output_at(__i).as_ptr() as *const [G; OUT_675]) }; __ret }, _ => aiur_fn_675(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_674] = { let __args: [G; IN_674] = [__v_2, __v_32, __v_3, __v_4, __v_5, __v_6, __v_7, __v_21, __v_8, __v_0, __v_9, __v_10, __v_19, __v_20, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[674].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[674].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[674].bump_multiplicity(__i); } let __ret: [G; OUT_674] = unsafe { *(record.function_queries[674].output_at(__i).as_ptr() as *const [G; OUT_674]) }; __ret }, _ => aiur_fn_674(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = G::from_u64(0); - let __r_arr: [G; OUT_676] = { let __args: [G; IN_676] = [__v_11, __v_34, __v_5, __v_6, __v_7, __v_3, __v_4, __v_2, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[676].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[676].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[676].bump_multiplicity(__i); } let __ret: [G; OUT_676] = unsafe { *(record.function_queries[676].output_at(__i).as_ptr() as *const [G; OUT_676]) }; __ret }, _ => aiur_fn_676(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_673] = []; - record.function_queries[673].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_675] = { let __args: [G; IN_675] = [__v_11, __v_34, __v_5, __v_6, __v_7, __v_3, __v_4, __v_2, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[675].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[675].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[675].bump_multiplicity(__i); } let __ret: [G; OUT_675] = unsafe { *(record.function_queries[675].output_at(__i).as_ptr() as *const [G; OUT_675]) }; __ret }, _ => aiur_fn_675(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_672] = []; + record.function_queries[672].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_674: usize = 3; -const IN_674: usize = 3; -const OUT_674: usize = 1; -fn aiur_fn_674( - inp: [G; IN_674], +const INPUT_SIZE_673: usize = 3; +const IN_673: usize = 3; +const OUT_673: usize = 1; +fn aiur_fn_673( + inp: [G; IN_673], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_674], ExecError> { +) -> Result<[G; OUT_673], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -56955,8 +56909,8 @@ fn aiur_fn_674( match __v_3.as_canonical_u64() { 0u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_674] = [__v_4]; - record.function_queries[674].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_673] = [__v_4]; + record.function_queries[673].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -56970,12 +56924,12 @@ fn aiur_fn_674( match __v_4.as_canonical_u64() { 1u64 => { let __v_10: G = G::from_u64(0); - let __ret: [G; OUT_674] = [__v_10]; - record.function_queries[674].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_673] = [__v_10]; + record.function_queries[673].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_10.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_11: G = __loaded[0]; @@ -57003,11 +56957,11 @@ fn aiur_fn_674( let __v_23: G = __mc_out___mc_0[0]; let __v_24: G = G::from_u64(1); let __v_25: G = (__v_2 + __v_24); - let __r_arr: [G; OUT_674] = { let __args: [G; IN_674] = [__v_9, __v_1, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[674].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[674].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[674].bump_multiplicity(__i); } let __ret: [G; OUT_674] = unsafe { *(record.function_queries[674].output_at(__i).as_ptr() as *const [G; OUT_674]) }; __ret }, _ => aiur_fn_674(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_673] = { let __args: [G; IN_673] = [__v_9, __v_1, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[673].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[673].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[673].bump_multiplicity(__i); } let __ret: [G; OUT_673] = unsafe { *(record.function_queries[673].output_at(__i).as_ptr() as *const [G; OUT_673]) }; __ret }, _ => aiur_fn_673(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; let __v_27: G = (__v_23 + __v_26); - let __ret: [G; OUT_674] = [__v_27]; - record.function_queries[674].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_673] = [__v_27]; + record.function_queries[673].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -57019,15 +56973,15 @@ fn aiur_fn_674( }) } -const INPUT_SIZE_675: usize = 15; -const IN_675: usize = 15; -const OUT_675: usize = 1; -fn aiur_fn_675( - inp: [G; IN_675], +const INPUT_SIZE_674: usize = 15; +const IN_674: usize = 15; +const OUT_674: usize = 1; +fn aiur_fn_674( + inp: [G; IN_674], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_675], ExecError> { +) -> Result<[G; OUT_674], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57050,12 +57004,12 @@ fn aiur_fn_675( let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 3] = [__v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_675] = [__v_18]; - record.function_queries[675].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_674] = [__v_18]; + record.function_queries[674].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_2, __v_3, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_2, __v_3, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_16.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_17: G = __loaded[0]; @@ -57073,24 +57027,24 @@ fn aiur_fn_675( match __v_17.as_canonical_u64() { 6u64 => { let __v_29: G = (__v_1 + __v_14); - let __r_arr: [G; OUT_678] = { let __args: [G; IN_678] = [__v_19, __v_29, __v_4, __v_5, __v_6, __v_23, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[678].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[678].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[678].bump_multiplicity(__i); } let __ret: [G; OUT_678] = unsafe { *(record.function_queries[678].output_at(__i).as_ptr() as *const [G; OUT_678]) }; __ret }, _ => aiur_fn_678(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_677] = { let __args: [G; IN_677] = [__v_19, __v_29, __v_4, __v_5, __v_6, __v_23, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[677].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[677].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[677].bump_multiplicity(__i); } let __ret: [G; OUT_677] = unsafe { *(record.function_queries[677].output_at(__i).as_ptr() as *const [G; OUT_677]) }; __ret }, _ => aiur_fn_677(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; let __v_31: G = G::from_u64(0); let __v_32: G = G::from_u64(1); let __v_33: G = (__v_14 + __v_32); - let __r_arr: [G; OUT_675] = { let __args: [G; IN_675] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[675].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[675].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[675].bump_multiplicity(__i); } let __ret: [G; OUT_675] = unsafe { *(record.function_queries[675].output_at(__i).as_ptr() as *const [G; OUT_675]) }; __ret }, _ => aiur_fn_675(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_674] = { let __args: [G; IN_674] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[674].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[674].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[674].bump_multiplicity(__i); } let __ret: [G; OUT_674] = unsafe { *(record.function_queries[674].output_at(__i).as_ptr() as *const [G; OUT_674]) }; __ret }, _ => aiur_fn_674(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = { let __values: [G; 3] = [__v_31, __v_30, __v_34]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_675] = [__v_35]; - record.function_queries[675].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_674] = [__v_35]; + record.function_queries[674].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_29: G = G::from_u64(1); let __v_30: G = G::from_u64(1); let __v_31: G = { let __values: [G; 3] = [__v_29, __v_30, __v_30]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_675] = [__v_31]; - record.function_queries[675].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_674] = [__v_31]; + record.function_queries[674].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -57099,15 +57053,15 @@ fn aiur_fn_675( }) } -const INPUT_SIZE_676: usize = 9; -const IN_676: usize = 9; -const OUT_676: usize = 0; -fn aiur_fn_676( - inp: [G; IN_676], +const INPUT_SIZE_675: usize = 9; +const IN_675: usize = 9; +const OUT_675: usize = 0; +fn aiur_fn_675( + inp: [G; IN_675], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_676], ExecError> { +) -> Result<[G; OUT_675], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57126,8 +57080,8 @@ fn aiur_fn_676( let __v_13: G = __loaded[4]; match __v_9.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_676] = []; - record.function_queries[676].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_675] = []; + record.function_queries[675].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -57141,7 +57095,7 @@ fn aiur_fn_676( if (__v_14 != __v_15) { return Err(ExecError::AssertEqMismatch { lhs: __v_14.as_canonical_u64(), rhs: __v_15.as_canonical_u64(), msg: Some("recursor rule names a ctor index out of range".to_string()) }); } - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_5, __v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_5, __v_6, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_16.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_17: G = __loaded[0]; @@ -57174,8 +57128,8 @@ fn aiur_fn_676( let __v_31: G = __loaded[2]; match __v_29.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_676] = []; - record.function_queries[676].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_675] = []; + record.function_queries[675].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -57186,7 +57140,7 @@ fn aiur_fn_676( let __v_36: G = G::from_u64(1); let __v_37: G = G::from_u64(1); let __v_38: G = { let __values: [G; 3] = [__v_36, __v_37, __v_37]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_707] = { let __args: [G; IN_707] = [__v_12, __v_34, __v_35, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[707].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[707].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[707].bump_multiplicity(__i); } let __ret: [G; OUT_707] = unsafe { *(record.function_queries[707].output_at(__i).as_ptr() as *const [G; OUT_707]) }; __ret }, _ => aiur_fn_707(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_706] = { let __args: [G; IN_706] = [__v_12, __v_34, __v_35, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[706].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[706].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[706].bump_multiplicity(__i); } let __ret: [G; OUT_706] = unsafe { *(record.function_queries[706].output_at(__i).as_ptr() as *const [G; OUT_706]) }; __ret }, _ => aiur_fn_706(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; let __v_40: G = __r_arr[1]; let __v_41: G = __r_arr[2]; @@ -57196,7 +57150,7 @@ fn aiur_fn_676( let __v_42: G = G::from_u64(1); let __v_43: G = G::from_u64(1); let __v_44: G = { let __values: [G; 3] = [__v_42, __v_43, __v_43]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_438] = { let __args: [G; IN_438] = [__v_39, __v_30, __v_44]; let __cu = unconstrained; let __hit = record.function_queries[438].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[438].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[438].bump_multiplicity(__i); } let __ret: [G; OUT_438] = unsafe { *(record.function_queries[438].output_at(__i).as_ptr() as *const [G; OUT_438]) }; __ret }, _ => aiur_fn_438(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_437] = { let __args: [G; IN_437] = [__v_39, __v_30, __v_44]; let __cu = unconstrained; let __hit = record.function_queries[437].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[437].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[437].bump_multiplicity(__i); } let __ret: [G; OUT_437] = unsafe { *(record.function_queries[437].output_at(__i).as_ptr() as *const [G; OUT_437]) }; __ret }, _ => aiur_fn_437(__args, record, io_buffer, __cu)? } }; let __v_45: G = __r_arr[0]; let __v_46: G = G::from_u64(1); if (__v_45 != __v_46) { @@ -57204,9 +57158,9 @@ fn aiur_fn_676( } let __v_47: G = G::from_u64(1); let __v_48: G = (__v_8 + __v_47); - let __r_arr: [G; OUT_676] = { let __args: [G; IN_676] = [__v_13, __v_31, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[676].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[676].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[676].bump_multiplicity(__i); } let __ret: [G; OUT_676] = unsafe { *(record.function_queries[676].output_at(__i).as_ptr() as *const [G; OUT_676]) }; __ret }, _ => aiur_fn_676(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_676] = []; - record.function_queries[676].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_675] = { let __args: [G; IN_675] = [__v_13, __v_31, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[675].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[675].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[675].bump_multiplicity(__i); } let __ret: [G; OUT_675] = unsafe { *(record.function_queries[675].output_at(__i).as_ptr() as *const [G; OUT_675]) }; __ret }, _ => aiur_fn_675(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_675] = []; + record.function_queries[675].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -57223,15 +57177,15 @@ fn aiur_fn_676( }) } -const INPUT_SIZE_677: usize = 12; -const IN_677: usize = 12; -const OUT_677: usize = 1; -fn aiur_fn_677( - inp: [G; IN_677], +const INPUT_SIZE_676: usize = 12; +const IN_676: usize = 12; +const OUT_676: usize = 1; +fn aiur_fn_676( + inp: [G; IN_676], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_677], ExecError> { +) -> Result<[G; OUT_676], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57251,13 +57205,13 @@ fn aiur_fn_677( let __v_14: G = __loaded[2]; match __v_12.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_677] = [__v_0]; - record.function_queries[677].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_676] = [__v_0]; + record.function_queries[676].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_2, __v_11, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_766] = { let __args: [G; IN_766] = [__v_2, __v_11, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[766].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[766].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[766].bump_multiplicity(__i); } let __ret: [G; OUT_766] = unsafe { *(record.function_queries[766].output_at(__i).as_ptr() as *const [G; OUT_766]) }; __ret }, _ => aiur_fn_766(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); @@ -57292,27 +57246,27 @@ fn aiur_fn_677( let __v_47: G = G::from_u64(0); let __v_48: G = G::from_u64(0); let __v_49: G = { let __values: [G; 32] = [__v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48]; let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_4, __v_16, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_766] = { let __args: [G; IN_766] = [__v_4, __v_16, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[766].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[766].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[766].bump_multiplicity(__i); } let __ret: [G; OUT_766] = unsafe { *(record.function_queries[766].output_at(__i).as_ptr() as *const [G; OUT_766]) }; __ret }, _ => aiur_fn_766(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __v_51: G = G::from_u64(0); - let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_5, __v_16, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_766] = { let __args: [G; IN_766] = [__v_5, __v_16, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[766].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[766].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[766].bump_multiplicity(__i); } let __ret: [G; OUT_766] = unsafe { *(record.function_queries[766].output_at(__i).as_ptr() as *const [G; OUT_766]) }; __ret }, _ => aiur_fn_766(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; let __v_53: G = (__v_6 + __v_7); let __v_54: G = (__v_53 + __v_8); let __v_55: G = (__v_54 + __v_9); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_3, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_3, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_56: G = __r_arr[0]; let __v_57: G = (__v_9 - __v_13); let __v_58: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_56, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_56, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_59: G = __r_arr[0]; let __v_60: G = (__v_7 + __v_8); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_59, __v_60, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_59, __v_60, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_61: G = __r_arr[0]; - let __r_arr: [G; OUT_691] = { let __args: [G; IN_691] = [__v_61]; let __cu = unconstrained; let __hit = record.function_queries[691].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[691].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[691].bump_multiplicity(__i); } let __ret: [G; OUT_691] = unsafe { *(record.function_queries[691].output_at(__i).as_ptr() as *const [G; OUT_691]) }; __ret }, _ => aiur_fn_691(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_690] = { let __args: [G; IN_690] = [__v_61]; let __cu = unconstrained; let __hit = record.function_queries[690].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[690].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[690].bump_multiplicity(__i); } let __ret: [G; OUT_690] = unsafe { *(record.function_queries[690].output_at(__i).as_ptr() as *const [G; OUT_690]) }; __ret }, _ => aiur_fn_690(__args, record, io_buffer, __cu)? } }; let __v_62: G = __r_arr[0]; let __v_63: G = __r_arr[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_62]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_62]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_64: G = __r_arr[0]; let __v_65: G = (__v_55 + __v_64); let __v_66: G = G::from_u64(2); @@ -57321,32 +57275,32 @@ fn aiur_fn_677( let __v_69: G = G::from_u64(1); let __v_70: G = (__v_65 - __v_69); let __v_71: G = G::from_u64(0); - let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_68, __v_6, __v_70, __v_71]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_68, __v_6, __v_70, __v_71]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; let __v_72: G = __r_arr[0]; let __v_73: G = G::from_u64(1); let __v_74: G = (__v_65 - __v_73); let __v_75: G = (__v_74 - __v_6); let __v_76: G = G::from_u64(0); - let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_72, __v_7, __v_75, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_72, __v_7, __v_75, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; let __v_77: G = __r_arr[0]; let __v_78: G = G::from_u64(1); let __v_79: G = (__v_65 - __v_78); let __v_80: G = (__v_79 - __v_6); let __v_81: G = (__v_80 - __v_7); let __v_82: G = G::from_u64(0); - let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_77, __v_8, __v_81, __v_82]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_77, __v_8, __v_81, __v_82]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; let __v_83: G = __r_arr[0]; let __v_84: G = G::from_u64(1); let __v_85: G = G::from_u64(1); let __v_86: G = { let __values: [G; 3] = [__v_84, __v_85, __v_85]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_63, __v_86]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_63, __v_86]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_87: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_87]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_88: G = __r_arr[0]; let __v_89: G = __r_arr[1]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_89, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_89, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_90: G = __r_arr[0]; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_83, __v_90]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_83, __v_90]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_91: G = __r_arr[0]; let __v_92: G = G::from_u64(1); let __v_93: G = (__v_9 - __v_92); @@ -57356,22 +57310,22 @@ fn aiur_fn_677( let __v_97: G = G::from_u64(0); let __v_98: G = { let __values: [G; 4] = [__v_96, __v_95, __v_97, __v_97]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_99: G = G::from_u64(0); - let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_98, __v_64, __v_99]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_659] = { let __args: [G; IN_659] = [__v_98, __v_64, __v_99]; let __cu = unconstrained; let __hit = record.function_queries[659].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[659].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[659].bump_multiplicity(__i); } let __ret: [G; OUT_659] = unsafe { *(record.function_queries[659].output_at(__i).as_ptr() as *const [G; OUT_659]) }; __ret }, _ => aiur_fn_659(__args, record, io_buffer, __cu)? } }; let __v_100: G = __r_arr[0]; let __v_101: G = G::from_u64(3); let __v_102: G = G::from_u64(0); let __v_103: G = { let __values: [G; 4] = [__v_101, __v_91, __v_100, __v_102]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_669] = { let __args: [G; IN_669] = [__v_103, __v_62]; let __cu = unconstrained; let __hit = record.function_queries[669].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[669].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[669].bump_multiplicity(__i); } let __ret: [G; OUT_669] = unsafe { *(record.function_queries[669].output_at(__i).as_ptr() as *const [G; OUT_669]) }; __ret }, _ => aiur_fn_669(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_103, __v_62]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; let __v_104: G = __r_arr[0]; let __v_105: G = G::from_u64(3); let __v_106: G = G::from_u64(0); let __v_107: G = { let __values: [G; 4] = [__v_105, __v_0, __v_104, __v_106]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_108: G = G::from_u64(1); let __v_109: G = (__v_11 + __v_108); - let __r_arr: [G; OUT_677] = { let __args: [G; IN_677] = [__v_107, __v_14, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_109]; let __cu = unconstrained; let __hit = record.function_queries[677].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[677].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[677].bump_multiplicity(__i); } let __ret: [G; OUT_677] = unsafe { *(record.function_queries[677].output_at(__i).as_ptr() as *const [G; OUT_677]) }; __ret }, _ => aiur_fn_677(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_676] = { let __args: [G; IN_676] = [__v_107, __v_14, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_109]; let __cu = unconstrained; let __hit = record.function_queries[676].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[676].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[676].bump_multiplicity(__i); } let __ret: [G; OUT_676] = unsafe { *(record.function_queries[676].output_at(__i).as_ptr() as *const [G; OUT_676]) }; __ret }, _ => aiur_fn_676(__args, record, io_buffer, __cu)? } }; let __v_110: G = __r_arr[0]; - let __ret: [G; OUT_677] = [__v_110]; - record.function_queries[677].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_676] = [__v_110]; + record.function_queries[676].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -57381,15 +57335,15 @@ fn aiur_fn_677( }) } -const INPUT_SIZE_678: usize = 13; -const IN_678: usize = 13; -const OUT_678: usize = 1; -fn aiur_fn_678( - inp: [G; IN_678], +const INPUT_SIZE_677: usize = 13; +const IN_677: usize = 13; +const OUT_677: usize = 1; +fn aiur_fn_677( + inp: [G; IN_677], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_678], ExecError> { +) -> Result<[G; OUT_677], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57404,19 +57358,19 @@ fn aiur_fn_678( let __v_10: G = inp[10]; let __v_11: G = inp[11]; let __v_12: G = inp[12]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_0, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_13, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_13, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_688] = { let __args: [G; IN_688] = [__v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[688].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[688].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[688].bump_multiplicity(__i); } let __ret: [G; OUT_688] = unsafe { *(record.function_queries[688].output_at(__i).as_ptr() as *const [G; OUT_688]) }; __ret }, _ => aiur_fn_688(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_687] = { let __args: [G; IN_687] = [__v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[687].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[687].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[687].bump_multiplicity(__i); } let __ret: [G; OUT_687] = unsafe { *(record.function_queries[687].output_at(__i).as_ptr() as *const [G; OUT_687]) }; __ret }, _ => aiur_fn_687(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = (__v_2 + __v_3); let __v_18: G = (__v_17 + __v_4); let __v_19: G = (__v_18 + __v_16); let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(0); - let __r_arr: [G; OUT_689] = { let __args: [G; IN_689] = [__v_13, __v_5, __v_5, __v_20, __v_11, __v_12, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[689].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[689].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[689].bump_multiplicity(__i); } let __ret: [G; OUT_689] = unsafe { *(record.function_queries[689].output_at(__i).as_ptr() as *const [G; OUT_689]) }; __ret }, _ => aiur_fn_689(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_688] = { let __args: [G; IN_688] = [__v_13, __v_5, __v_5, __v_20, __v_11, __v_12, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[688].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[688].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[688].bump_multiplicity(__i); } let __ret: [G; OUT_688] = unsafe { *(record.function_queries[688].output_at(__i).as_ptr() as *const [G; OUT_688]) }; __ret }, _ => aiur_fn_688(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = G::from_u64(1); let __v_24: G = G::from_u64(1); @@ -57429,7 +57383,7 @@ fn aiur_fn_678( let __v_31: G = { let __values: [G; 3] = [__v_29, __v_30, __v_30]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_32: G = G::from_u64(0); let __v_33: G = G::from_u64(0); - let __r_arr: [G; OUT_701] = { let __args: [G; IN_701] = [__v_22, __v_8, __v_25, __v_28, __v_31, __v_32, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[701].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[701].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[701].bump_multiplicity(__i); } let __ret: [G; OUT_701] = unsafe { *(record.function_queries[701].output_at(__i).as_ptr() as *const [G; OUT_701]) }; __ret }, _ => aiur_fn_701(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_700] = { let __args: [G; IN_700] = [__v_22, __v_8, __v_25, __v_28, __v_31, __v_32, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[700].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[700].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[700].bump_multiplicity(__i); } let __ret: [G; OUT_700] = unsafe { *(record.function_queries[700].output_at(__i).as_ptr() as *const [G; OUT_700]) }; __ret }, _ => aiur_fn_700(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = __r_arr[2]; @@ -57443,26 +57397,26 @@ fn aiur_fn_678( let __v_44: G = G::from_u64(0); let __v_45: G = { let __values: [G; 4] = [__v_43, __v_42, __v_44, __v_44]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_46: G = G::from_u64(0); - let __r_arr: [G; OUT_695] = { let __args: [G; IN_695] = [__v_45, __v_16, __v_16, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[695].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[695].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[695].bump_multiplicity(__i); } let __ret: [G; OUT_695] = unsafe { *(record.function_queries[695].output_at(__i).as_ptr() as *const [G; OUT_695]) }; __ret }, _ => aiur_fn_695(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_694] = { let __args: [G; IN_694] = [__v_45, __v_16, __v_16, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[694].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[694].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[694].bump_multiplicity(__i); } let __ret: [G; OUT_694] = unsafe { *(record.function_queries[694].output_at(__i).as_ptr() as *const [G; OUT_694]) }; __ret }, _ => aiur_fn_694(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; let __v_48: G = G::from_u64(0); - let __r_arr: [G; OUT_677] = { let __args: [G; IN_677] = [__v_47, __v_35, __v_36, __v_34, __v_9, __v_10, __v_2, __v_3, __v_4, __v_16, __v_7, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[677].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[677].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[677].bump_multiplicity(__i); } let __ret: [G; OUT_677] = unsafe { *(record.function_queries[677].output_at(__i).as_ptr() as *const [G; OUT_677]) }; __ret }, _ => aiur_fn_677(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_676] = { let __args: [G; IN_676] = [__v_47, __v_35, __v_36, __v_34, __v_9, __v_10, __v_2, __v_3, __v_4, __v_16, __v_7, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[676].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[676].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[676].bump_multiplicity(__i); } let __ret: [G; OUT_676] = unsafe { *(record.function_queries[676].output_at(__i).as_ptr() as *const [G; OUT_676]) }; __ret }, _ => aiur_fn_676(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __ret: [G; OUT_678] = [__v_49]; - record.function_queries[678].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_677] = [__v_49]; + record.function_queries[677].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_679: usize = 3; -const IN_679: usize = 3; -const OUT_679: usize = 1; -fn aiur_fn_679( - inp: [G; IN_679], +const INPUT_SIZE_678: usize = 3; +const IN_678: usize = 3; +const OUT_678: usize = 1; +fn aiur_fn_678( + inp: [G; IN_678], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_679], ExecError> { +) -> Result<[G; OUT_678], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57479,19 +57433,19 @@ fn aiur_fn_679( let __v_9: G = G::from_u64(1); let __v_10: G = G::from_u64(1); let __v_11: G = { let __values: [G; 3] = [__v_9, __v_10, __v_10]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_679] = [__v_11]; - record.function_queries[679].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_678] = [__v_11]; + record.function_queries[678].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_680] = { let __args: [G; IN_680] = [__v_1, __v_4, __v_6, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[680].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[680].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[680].bump_multiplicity(__i); } let __ret: [G; OUT_680] = unsafe { *(record.function_queries[680].output_at(__i).as_ptr() as *const [G; OUT_680]) }; __ret }, _ => aiur_fn_680(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_679] = { let __args: [G; IN_679] = [__v_1, __v_4, __v_6, __v_5, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[679].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[679].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[679].bump_multiplicity(__i); } let __ret: [G; OUT_679] = unsafe { *(record.function_queries[679].output_at(__i).as_ptr() as *const [G; OUT_679]) }; __ret }, _ => aiur_fn_679(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_679] = { let __args: [G; IN_679] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[679].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[679].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[679].bump_multiplicity(__i); } let __ret: [G; OUT_679] = unsafe { *(record.function_queries[679].output_at(__i).as_ptr() as *const [G; OUT_679]) }; __ret }, _ => aiur_fn_679(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_678] = { let __args: [G; IN_678] = [__v_8, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[678].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[678].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[678].bump_multiplicity(__i); } let __ret: [G; OUT_678] = unsafe { *(record.function_queries[678].output_at(__i).as_ptr() as *const [G; OUT_678]) }; __ret }, _ => aiur_fn_678(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = { let __values: [G; 3] = [__v_10, __v_9, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_679] = [__v_12]; - record.function_queries[679].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_678] = [__v_12]; + record.function_queries[678].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -57501,22 +57455,22 @@ fn aiur_fn_679( }) } -const INPUT_SIZE_680: usize = 5; -const IN_680: usize = 5; -const OUT_680: usize = 1; -fn aiur_fn_680( - inp: [G; IN_680], +const INPUT_SIZE_679: usize = 5; +const IN_679: usize = 5; +const OUT_679: usize = 1; +fn aiur_fn_679( + inp: [G; IN_679], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_680], ExecError> { +) -> Result<[G; OUT_679], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; let __v_3: G = inp[3]; let __v_4: G = inp[4]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = __r_arr[1]; let __v_7: G = __r_arr[2]; @@ -57570,15 +57524,15 @@ fn aiur_fn_680( match __v_5.as_canonical_u64() { 8u64 => { let __v_53: G = G::from_u64(0); - let __r_arr: [G; OUT_681] = { let __args: [G; IN_681] = [__v_6, __v_6, __v_0, __v_1, __v_2, __v_3, __v_4, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[681].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[681].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[681].bump_multiplicity(__i); } let __ret: [G; OUT_681] = unsafe { *(record.function_queries[681].output_at(__i).as_ptr() as *const [G; OUT_681]) }; __ret }, _ => aiur_fn_681(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_680] = { let __args: [G; IN_680] = [__v_6, __v_6, __v_0, __v_1, __v_2, __v_3, __v_4, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[680].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[680].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[680].bump_multiplicity(__i); } let __ret: [G; OUT_680] = unsafe { *(record.function_queries[680].output_at(__i).as_ptr() as *const [G; OUT_680]) }; __ret }, _ => aiur_fn_680(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; - let __ret: [G; OUT_680] = [__v_54]; - record.function_queries[680].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_679] = [__v_54]; + record.function_queries[679].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_680] = [__v_4]; - record.function_queries[680].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_679] = [__v_4]; + record.function_queries[679].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -57587,15 +57541,15 @@ fn aiur_fn_680( }) } -const INPUT_SIZE_681: usize = 8; -const IN_681: usize = 8; -const OUT_681: usize = 1; -fn aiur_fn_681( - inp: [G; IN_681], +const INPUT_SIZE_680: usize = 8; +const IN_680: usize = 8; +const OUT_680: usize = 1; +fn aiur_fn_680( + inp: [G; IN_680], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_681], ExecError> { +) -> Result<[G; OUT_680], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57655,16 +57609,16 @@ fn aiur_fn_681( let __v_54: G = __loaded[46]; match __v_8.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_681] = [__v_6]; - record.function_queries[681].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_680] = [__v_6]; + record.function_queries[680].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_9.as_canonical_u64() { 2u64 => { - let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_0, __v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_0, __v_2, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_55]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_55]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_56: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_56.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_57: G = __loaded[0]; @@ -57681,9 +57635,9 @@ fn aiur_fn_681( let __v_68: G = __loaded[11]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_57.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_59, __v_60, __v_62, __v_63, __v_61]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_59, __v_60, __v_62, __v_63, __v_61]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; let __v_69: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_69]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_69]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_70: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_70.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_71: G = __loaded[0]; @@ -57719,9 +57673,9 @@ fn aiur_fn_681( break '__mc_0 [__v_85]; }, _ => { - let __r_arr: [G; OUT_636] = { let __args: [G; IN_636] = [__v_59, __v_60, __v_62, __v_63, __v_61, __v_83]; let __cu = unconstrained; let __hit = record.function_queries[636].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[636].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[636].bump_multiplicity(__i); } let __ret: [G; OUT_636] = unsafe { *(record.function_queries[636].output_at(__i).as_ptr() as *const [G; OUT_636]) }; __ret }, _ => aiur_fn_636(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_635] = { let __args: [G; IN_635] = [__v_59, __v_60, __v_62, __v_63, __v_61, __v_83]; let __cu = unconstrained; let __hit = record.function_queries[635].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[635].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[635].bump_multiplicity(__i); } let __ret: [G; OUT_635] = unsafe { *(record.function_queries[635].output_at(__i).as_ptr() as *const [G; OUT_635]) }; __ret }, _ => aiur_fn_635(__args, record, io_buffer, __cu)? } }; let __v_85: G = __r_arr[0]; - let __r_arr: [G; OUT_644] = { let __args: [G; IN_644] = [__v_85, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[644].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[644].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[644].bump_multiplicity(__i); } let __ret: [G; OUT_644] = unsafe { *(record.function_queries[644].output_at(__i).as_ptr() as *const [G; OUT_644]) }; __ret }, _ => aiur_fn_644(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_643] = { let __args: [G; IN_643] = [__v_85, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[643].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[643].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[643].bump_multiplicity(__i); } let __ret: [G; OUT_643] = unsafe { *(record.function_queries[643].output_at(__i).as_ptr() as *const [G; OUT_643]) }; __ret }, _ => aiur_fn_643(__args, record, io_buffer, __cu)? } }; let __v_86: G = __r_arr[0]; break '__mc_0 [__v_86]; }, @@ -57742,17 +57696,17 @@ fn aiur_fn_681( let __v_69: G = __mc_out___mc_0[0]; match __v_69.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_681] = [__v_55]; - record.function_queries[681].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_680] = [__v_55]; + record.function_queries[680].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_70: G = G::from_u64(1); let __v_71: G = (__v_7 + __v_70); - let __r_arr: [G; OUT_681] = { let __args: [G; IN_681] = [__v_0, __v_54, __v_2, __v_3, __v_4, __v_5, __v_6, __v_71]; let __cu = unconstrained; let __hit = record.function_queries[681].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[681].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[681].bump_multiplicity(__i); } let __ret: [G; OUT_681] = unsafe { *(record.function_queries[681].output_at(__i).as_ptr() as *const [G; OUT_681]) }; __ret }, _ => aiur_fn_681(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_680] = { let __args: [G; IN_680] = [__v_0, __v_54, __v_2, __v_3, __v_4, __v_5, __v_6, __v_71]; let __cu = unconstrained; let __hit = record.function_queries[680].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[680].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[680].bump_multiplicity(__i); } let __ret: [G; OUT_680] = unsafe { *(record.function_queries[680].output_at(__i).as_ptr() as *const [G; OUT_680]) }; __ret }, _ => aiur_fn_680(__args, record, io_buffer, __cu)? } }; let __v_72: G = __r_arr[0]; - let __ret: [G; OUT_681] = [__v_72]; - record.function_queries[681].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_680] = [__v_72]; + record.function_queries[680].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -57760,10 +57714,10 @@ fn aiur_fn_681( _ => { let __v_55: G = G::from_u64(1); let __v_56: G = (__v_7 + __v_55); - let __r_arr: [G; OUT_681] = { let __args: [G; IN_681] = [__v_0, __v_54, __v_2, __v_3, __v_4, __v_5, __v_6, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[681].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[681].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[681].bump_multiplicity(__i); } let __ret: [G; OUT_681] = unsafe { *(record.function_queries[681].output_at(__i).as_ptr() as *const [G; OUT_681]) }; __ret }, _ => aiur_fn_681(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_680] = { let __args: [G; IN_680] = [__v_0, __v_54, __v_2, __v_3, __v_4, __v_5, __v_6, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[680].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[680].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[680].bump_multiplicity(__i); } let __ret: [G; OUT_680] = unsafe { *(record.function_queries[680].output_at(__i).as_ptr() as *const [G; OUT_680]) }; __ret }, _ => aiur_fn_680(__args, record, io_buffer, __cu)? } }; let __v_57: G = __r_arr[0]; - let __ret: [G; OUT_681] = [__v_57]; - record.function_queries[681].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_680] = [__v_57]; + record.function_queries[680].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -57775,15 +57729,15 @@ fn aiur_fn_681( }) } -const INPUT_SIZE_682: usize = 1; -const IN_682: usize = 1; -const OUT_682: usize = 1; -fn aiur_fn_682( - inp: [G; IN_682], +const INPUT_SIZE_681: usize = 1; +const IN_681: usize = 1; +const OUT_681: usize = 1; +fn aiur_fn_681( + inp: [G; IN_681], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_682], ExecError> { +) -> Result<[G; OUT_681], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 6] = { let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 6 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 6] = __args[..6].try_into().unwrap(); __arr }; @@ -57798,12 +57752,12 @@ fn aiur_fn_682( let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_682] = [__v_9]; - record.function_queries[682].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_681] = [__v_9]; + record.function_queries[681].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_7.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_8: G = __loaded[0]; @@ -57830,11 +57784,11 @@ fn aiur_fn_682( }; let __v_20: G = __mc_out___mc_0[0]; let __v_21: G = G::from_u64(0); - let __r_arr: [G; OUT_682] = { let __args: [G; IN_682] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[682].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[682].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[682].bump_multiplicity(__i); } let __ret: [G; OUT_682] = unsafe { *(record.function_queries[682].output_at(__i).as_ptr() as *const [G; OUT_682]) }; __ret }, _ => aiur_fn_682(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_681] = { let __args: [G; IN_681] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[681].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[681].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[681].bump_multiplicity(__i); } let __ret: [G; OUT_681] = unsafe { *(record.function_queries[681].output_at(__i).as_ptr() as *const [G; OUT_681]) }; __ret }, _ => aiur_fn_681(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = { let __values: [G; 3] = [__v_21, __v_20, __v_22]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_682] = [__v_23]; - record.function_queries[682].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_681] = [__v_23]; + record.function_queries[681].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -57844,20 +57798,20 @@ fn aiur_fn_682( }) } -const INPUT_SIZE_683: usize = 3; -const IN_683: usize = 3; -const OUT_683: usize = 1; -fn aiur_fn_683( - inp: [G; IN_683], +const INPUT_SIZE_682: usize = 3; +const IN_682: usize = 3; +const OUT_682: usize = 1; +fn aiur_fn_682( + inp: [G; IN_682], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_683], ExecError> { +) -> Result<[G; OUT_682], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = __r_arr[2]; @@ -57866,7 +57820,7 @@ fn aiur_fn_683( let __v_8: G = __r_arr[5]; let __v_9: G = __r_arr[6]; let __v_10: G = __r_arr[7]; - let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_292] = { let __args: [G; IN_292] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[292].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[292].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[292].bump_multiplicity(__i); } let __ret: [G; OUT_292] = unsafe { *(record.function_queries[292].output_at(__i).as_ptr() as *const [G; OUT_292]) }; __ret }, _ => aiur_fn_292(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; @@ -57893,21 +57847,21 @@ fn aiur_fn_683( let __v_33: G = __r_arr[0]; let __r_arr: [G; OUT_22] = { let __args: [G; IN_22] = [__v_33]; let __cu = unconstrained; let __hit = record.function_queries[22].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[22].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[22].bump_multiplicity(__i); } let __ret: [G; OUT_22] = unsafe { *(record.function_queries[22].output_at(__i).as_ptr() as *const [G; OUT_22]) }; __ret }, _ => aiur_fn_22(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __ret: [G; OUT_683] = [__v_34]; - record.function_queries[683].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_682] = [__v_34]; + record.function_queries[682].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_684: usize = 15; -const IN_684: usize = 15; -const OUT_684: usize = 1; -fn aiur_fn_684( - inp: [G; IN_684], +const INPUT_SIZE_683: usize = 15; +const IN_683: usize = 15; +const OUT_683: usize = 1; +fn aiur_fn_683( + inp: [G; IN_683], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_684], ExecError> { +) -> Result<[G; OUT_683], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57930,12 +57884,12 @@ fn aiur_fn_684( let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 3] = [__v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_684] = [__v_18]; - record.function_queries[684].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_683] = [__v_18]; + record.function_queries[683].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_290] = { let __args: [G; IN_290] = [__v_10, __v_11, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[290].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[290].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[290].bump_multiplicity(__i); } let __ret: [G; OUT_290] = unsafe { *(record.function_queries[290].output_at(__i).as_ptr() as *const [G; OUT_290]) }; __ret }, _ => aiur_fn_290(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_10, __v_11, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_16.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_17: G = __loaded[0]; @@ -57952,20 +57906,20 @@ fn aiur_fn_684( let __v_28: G = __loaded[11]; match __v_17.as_canonical_u64() { 6u64 => { - let __r_arr: [G; OUT_683] = { let __args: [G; IN_683] = [__v_11, __v_14, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[683].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[683].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[683].bump_multiplicity(__i); } let __ret: [G; OUT_683] = unsafe { *(record.function_queries[683].output_at(__i).as_ptr() as *const [G; OUT_683]) }; __ret }, _ => aiur_fn_683(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_682] = { let __args: [G; IN_682] = [__v_11, __v_14, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[682].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[682].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[682].bump_multiplicity(__i); } let __ret: [G; OUT_682] = unsafe { *(record.function_queries[682].output_at(__i).as_ptr() as *const [G; OUT_682]) }; __ret }, _ => aiur_fn_682(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __r_arr: [G; OUT_690] = { let __args: [G; IN_690] = [__v_29, __v_19, __v_23, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_13, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[690].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[690].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[690].bump_multiplicity(__i); } let __ret: [G; OUT_690] = unsafe { *(record.function_queries[690].output_at(__i).as_ptr() as *const [G; OUT_690]) }; __ret }, _ => aiur_fn_690(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_689] = { let __args: [G; IN_689] = [__v_29, __v_19, __v_23, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_13, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[689].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[689].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[689].bump_multiplicity(__i); } let __ret: [G; OUT_689] = unsafe { *(record.function_queries[689].output_at(__i).as_ptr() as *const [G; OUT_689]) }; __ret }, _ => aiur_fn_689(__args, record, io_buffer, __cu)? } }; let __v_30: G = __r_arr[0]; let __v_31: G = G::from_u64(0); let __v_32: G = G::from_u64(1); let __v_33: G = (__v_13 + __v_32); let __v_34: G = G::from_u64(1); let __v_35: G = (__v_14 + __v_34); - let __r_arr: [G; OUT_684] = { let __args: [G; IN_684] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_33, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[684].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[684].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[684].bump_multiplicity(__i); } let __ret: [G; OUT_684] = unsafe { *(record.function_queries[684].output_at(__i).as_ptr() as *const [G; OUT_684]) }; __ret }, _ => aiur_fn_684(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_683] = { let __args: [G; IN_683] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_33, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[683].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[683].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[683].bump_multiplicity(__i); } let __ret: [G; OUT_683] = unsafe { *(record.function_queries[683].output_at(__i).as_ptr() as *const [G; OUT_683]) }; __ret }, _ => aiur_fn_683(__args, record, io_buffer, __cu)? } }; let __v_36: G = __r_arr[0]; let __v_37: G = { let __values: [G; 3] = [__v_31, __v_30, __v_36]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_684] = [__v_37]; - record.function_queries[684].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_683] = [__v_37]; + record.function_queries[683].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -57977,15 +57931,15 @@ fn aiur_fn_684( }) } -const INPUT_SIZE_685: usize = 5; -const IN_685: usize = 5; -const OUT_685: usize = 1; -fn aiur_fn_685( - inp: [G; IN_685], +const INPUT_SIZE_684: usize = 5; +const IN_684: usize = 5; +const OUT_684: usize = 1; +fn aiur_fn_684( + inp: [G; IN_684], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_685], ExecError> { +) -> Result<[G; OUT_684], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -57994,23 +57948,23 @@ fn aiur_fn_685( let __v_4: G = inp[4]; let __v_5: G = G::from_u64(0); let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_686] = { let __args: [G; IN_686] = [__v_0, __v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[686].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[686].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[686].bump_multiplicity(__i); } let __ret: [G; OUT_686] = unsafe { *(record.function_queries[686].output_at(__i).as_ptr() as *const [G; OUT_686]) }; __ret }, _ => aiur_fn_686(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_685] = { let __args: [G; IN_685] = [__v_0, __v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[685].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[685].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[685].bump_multiplicity(__i); } let __ret: [G; OUT_685] = unsafe { *(record.function_queries[685].output_at(__i).as_ptr() as *const [G; OUT_685]) }; __ret }, _ => aiur_fn_685(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_685] = [__v_7]; - record.function_queries[685].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_684] = [__v_7]; + record.function_queries[684].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_686: usize = 8; -const IN_686: usize = 8; -const OUT_686: usize = 1; -fn aiur_fn_686( - inp: [G; IN_686], +const INPUT_SIZE_685: usize = 8; +const IN_685: usize = 8; +const OUT_685: usize = 1; +fn aiur_fn_685( + inp: [G; IN_685], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_686], ExecError> { +) -> Result<[G; OUT_685], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58032,12 +57986,12 @@ fn aiur_fn_686( let __v_14: G = G::from_u64(1); let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 3] = [__v_14, __v_15, __v_15]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_686] = [__v_16]; - record.function_queries[686].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_685] = [__v_16]; + record.function_queries[685].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_14.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_15: G = __loaded[0]; @@ -58055,28 +58009,28 @@ fn aiur_fn_686( match __v_15.as_canonical_u64() { 5u64 => { let __v_27: G = G::from_u64(0); - let __r_arr: [G; OUT_684] = { let __args: [G; IN_684] = [__v_9, __v_10, __v_11, __v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_7, __v_22, __v_23, __v_20, __v_6, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[684].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[684].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[684].bump_multiplicity(__i); } let __ret: [G; OUT_684] = unsafe { *(record.function_queries[684].output_at(__i).as_ptr() as *const [G; OUT_684]) }; __ret }, _ => aiur_fn_684(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_683] = { let __args: [G; IN_683] = [__v_9, __v_10, __v_11, __v_12, __v_1, __v_2, __v_3, __v_4, __v_5, __v_7, __v_22, __v_23, __v_20, __v_6, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[683].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[683].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[683].bump_multiplicity(__i); } let __ret: [G; OUT_683] = unsafe { *(record.function_queries[683].output_at(__i).as_ptr() as *const [G; OUT_683]) }; __ret }, _ => aiur_fn_683(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = (__v_6 + __v_29); let __v_31: G = G::from_u64(1); let __v_32: G = (__v_7 + __v_31); - let __r_arr: [G; OUT_686] = { let __args: [G; IN_686] = [__v_13, __v_1, __v_2, __v_3, __v_4, __v_5, __v_30, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[686].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[686].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[686].bump_multiplicity(__i); } let __ret: [G; OUT_686] = unsafe { *(record.function_queries[686].output_at(__i).as_ptr() as *const [G; OUT_686]) }; __ret }, _ => aiur_fn_686(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_685] = { let __args: [G; IN_685] = [__v_13, __v_1, __v_2, __v_3, __v_4, __v_5, __v_30, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[685].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[685].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[685].bump_multiplicity(__i); } let __ret: [G; OUT_685] = unsafe { *(record.function_queries[685].output_at(__i).as_ptr() as *const [G; OUT_685]) }; __ret }, _ => aiur_fn_685(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_28, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_28, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; - let __ret: [G; OUT_686] = [__v_34]; - record.function_queries[686].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_685] = [__v_34]; + record.function_queries[685].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_27: G = G::from_u64(1); let __v_28: G = (__v_7 + __v_27); - let __r_arr: [G; OUT_686] = { let __args: [G; IN_686] = [__v_13, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[686].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[686].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[686].bump_multiplicity(__i); } let __ret: [G; OUT_686] = unsafe { *(record.function_queries[686].output_at(__i).as_ptr() as *const [G; OUT_686]) }; __ret }, _ => aiur_fn_686(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_685] = { let __args: [G; IN_685] = [__v_13, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[685].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[685].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[685].bump_multiplicity(__i); } let __ret: [G; OUT_685] = unsafe { *(record.function_queries[685].output_at(__i).as_ptr() as *const [G; OUT_685]) }; __ret }, _ => aiur_fn_685(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; - let __ret: [G; OUT_686] = [__v_29]; - record.function_queries[686].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_685] = [__v_29]; + record.function_queries[685].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -58088,15 +58042,15 @@ fn aiur_fn_686( }) } -const INPUT_SIZE_687: usize = 5; -const IN_687: usize = 5; -const OUT_687: usize = 1; -fn aiur_fn_687( - inp: [G; IN_687], +const INPUT_SIZE_686: usize = 5; +const IN_686: usize = 5; +const OUT_686: usize = 1; +fn aiur_fn_686( + inp: [G; IN_686], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_687], ExecError> { +) -> Result<[G; OUT_686], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58111,23 +58065,23 @@ fn aiur_fn_687( let __v_8: G = (__v_7 - __v_0); let __v_9: G = G::from_u64(0); let __v_10: G = { let __values: [G; 4] = [__v_5, __v_8, __v_9, __v_9]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_687] = [__v_10]; - record.function_queries[687].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_686] = [__v_10]; + record.function_queries[686].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_5.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_4, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_4, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_7, __v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_7, __v_2, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_687] = [__v_9]; - record.function_queries[687].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_686] = [__v_9]; + record.function_queries[686].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -58137,8 +58091,8 @@ fn aiur_fn_687( let __v_10: G = (__v_9 - __v_0); let __v_11: G = G::from_u64(0); let __v_12: G = { let __values: [G; 4] = [__v_7, __v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_687] = [__v_12]; - record.function_queries[687].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_686] = [__v_12]; + record.function_queries[686].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -58147,15 +58101,15 @@ fn aiur_fn_687( }) } -const INPUT_SIZE_688: usize = 2; -const IN_688: usize = 2; -const OUT_688: usize = 1; -fn aiur_fn_688( - inp: [G; IN_688], +const INPUT_SIZE_687: usize = 2; +const IN_687: usize = 2; +const OUT_687: usize = 1; +fn aiur_fn_687( + inp: [G; IN_687], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_688], ExecError> { +) -> Result<[G; OUT_687], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58168,30 +58122,30 @@ fn aiur_fn_688( 5u64 => { let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 + __v_6); - let __r_arr: [G; OUT_688] = { let __args: [G; IN_688] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[688].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[688].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[688].bump_multiplicity(__i); } let __ret: [G; OUT_688] = unsafe { *(record.function_queries[688].output_at(__i).as_ptr() as *const [G; OUT_688]) }; __ret }, _ => aiur_fn_688(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_687] = { let __args: [G; IN_687] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[687].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[687].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[687].bump_multiplicity(__i); } let __ret: [G; OUT_687] = unsafe { *(record.function_queries[687].output_at(__i).as_ptr() as *const [G; OUT_687]) }; __ret }, _ => aiur_fn_687(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_688] = [__v_8]; - record.function_queries[688].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_687] = [__v_8]; + record.function_queries[687].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_688] = [__v_1]; - record.function_queries[688].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_687] = [__v_1]; + record.function_queries[687].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_689: usize = 7; -const IN_689: usize = 7; -const OUT_689: usize = 1; -fn aiur_fn_689( - inp: [G; IN_689], +const INPUT_SIZE_688: usize = 7; +const IN_688: usize = 7; +const OUT_688: usize = 1; +fn aiur_fn_688( + inp: [G; IN_688], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_689], ExecError> { +) -> Result<[G; OUT_688], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58202,8 +58156,8 @@ fn aiur_fn_689( let __v_6: G = inp[6]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_689] = [__v_0]; - record.function_queries[689].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_688] = [__v_0]; + record.function_queries[688].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -58214,26 +58168,26 @@ fn aiur_fn_689( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_687] = { let __args: [G; IN_687] = [__v_6, __v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[687].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[687].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[687].bump_multiplicity(__i); } let __ret: [G; OUT_687] = unsafe { *(record.function_queries[687].output_at(__i).as_ptr() as *const [G; OUT_687]) }; __ret }, _ => aiur_fn_687(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_686] = { let __args: [G; IN_686] = [__v_6, __v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[686].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[686].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[686].bump_multiplicity(__i); } let __ret: [G; OUT_686] = unsafe { *(record.function_queries[686].output_at(__i).as_ptr() as *const [G; OUT_686]) }; __ret }, _ => aiur_fn_686(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_9, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_9, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = G::from_u64(1); let __v_15: G = (__v_1 - __v_14); let __v_16: G = G::from_u64(1); let __v_17: G = (__v_6 + __v_16); - let __r_arr: [G; OUT_689] = { let __args: [G; IN_689] = [__v_13, __v_15, __v_2, __v_3, __v_4, __v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[689].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[689].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[689].bump_multiplicity(__i); } let __ret: [G; OUT_689] = unsafe { *(record.function_queries[689].output_at(__i).as_ptr() as *const [G; OUT_689]) }; __ret }, _ => aiur_fn_689(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_688] = { let __args: [G; IN_688] = [__v_13, __v_15, __v_2, __v_3, __v_4, __v_5, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[688].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[688].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[688].bump_multiplicity(__i); } let __ret: [G; OUT_688] = unsafe { *(record.function_queries[688].output_at(__i).as_ptr() as *const [G; OUT_688]) }; __ret }, _ => aiur_fn_688(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __ret: [G; OUT_689] = [__v_18]; - record.function_queries[689].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_688] = [__v_18]; + record.function_queries[688].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_11: G = G::from_u64(1); let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_14.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_15: G = __loaded[0]; @@ -58242,19 +58196,19 @@ fn aiur_fn_689( let __v_18: G = __loaded[3]; match __v_15.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_687] = { let __args: [G; IN_687] = [__v_6, __v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[687].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[687].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[687].bump_multiplicity(__i); } let __ret: [G; OUT_687] = unsafe { *(record.function_queries[687].output_at(__i).as_ptr() as *const [G; OUT_687]) }; __ret }, _ => aiur_fn_687(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_686] = { let __args: [G; IN_686] = [__v_6, __v_2, __v_3, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[686].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[686].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[686].bump_multiplicity(__i); } let __ret: [G; OUT_686] = unsafe { *(record.function_queries[686].output_at(__i).as_ptr() as *const [G; OUT_686]) }; __ret }, _ => aiur_fn_686(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = G::from_u64(0); - let __r_arr: [G; OUT_367] = { let __args: [G; IN_367] = [__v_17, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[367].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[367].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[367].bump_multiplicity(__i); } let __ret: [G; OUT_367] = unsafe { *(record.function_queries[367].output_at(__i).as_ptr() as *const [G; OUT_367]) }; __ret }, _ => aiur_fn_367(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_366] = { let __args: [G; IN_366] = [__v_17, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[366].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[366].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[366].bump_multiplicity(__i); } let __ret: [G; OUT_366] = unsafe { *(record.function_queries[366].output_at(__i).as_ptr() as *const [G; OUT_366]) }; __ret }, _ => aiur_fn_366(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = G::from_u64(1); let __v_23: G = (__v_1 - __v_22); let __v_24: G = G::from_u64(1); let __v_25: G = (__v_6 + __v_24); - let __r_arr: [G; OUT_689] = { let __args: [G; IN_689] = [__v_21, __v_23, __v_2, __v_3, __v_4, __v_5, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[689].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[689].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[689].bump_multiplicity(__i); } let __ret: [G; OUT_689] = unsafe { *(record.function_queries[689].output_at(__i).as_ptr() as *const [G; OUT_689]) }; __ret }, _ => aiur_fn_689(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_688] = { let __args: [G; IN_688] = [__v_21, __v_23, __v_2, __v_3, __v_4, __v_5, __v_25]; let __cu = unconstrained; let __hit = record.function_queries[688].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[688].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[688].bump_multiplicity(__i); } let __ret: [G; OUT_688] = unsafe { *(record.function_queries[688].output_at(__i).as_ptr() as *const [G; OUT_688]) }; __ret }, _ => aiur_fn_688(__args, record, io_buffer, __cu)? } }; let __v_26: G = __r_arr[0]; - let __ret: [G; OUT_689] = [__v_26]; - record.function_queries[689].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_688] = [__v_26]; + record.function_queries[688].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -58268,15 +58222,15 @@ fn aiur_fn_689( }) } -const INPUT_SIZE_690: usize = 13; -const IN_690: usize = 13; -const OUT_690: usize = 1; -fn aiur_fn_690( - inp: [G; IN_690], +const INPUT_SIZE_689: usize = 13; +const IN_689: usize = 13; +const OUT_689: usize = 1; +fn aiur_fn_689( + inp: [G; IN_689], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_690], ExecError> { +) -> Result<[G; OUT_689], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58291,13 +58245,13 @@ fn aiur_fn_690( let __v_10: G = inp[10]; let __v_11: G = inp[11]; let __v_12: G = inp[12]; - let __r_arr: [G; OUT_336] = { let __args: [G; IN_336] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[336].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[336].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[336].bump_multiplicity(__i); } let __ret: [G; OUT_336] = unsafe { *(record.function_queries[336].output_at(__i).as_ptr() as *const [G; OUT_336]) }; __ret }, _ => aiur_fn_336(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_335] = { let __args: [G; IN_335] = [__v_1, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[335].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[335].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[335].bump_multiplicity(__i); } let __ret: [G; OUT_335] = unsafe { *(record.function_queries[335].output_at(__i).as_ptr() as *const [G; OUT_335]) }; __ret }, _ => aiur_fn_335(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; let __v_14: G = (__v_9 + __v_10); let __v_15: G = (__v_8 + __v_14); let __v_16: G = (__v_9 + __v_10); let __v_17: G = G::from_u64(0); - let __r_arr: [G; OUT_689] = { let __args: [G; IN_689] = [__v_13, __v_2, __v_15, __v_16, __v_3, __v_4, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[689].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[689].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[689].bump_multiplicity(__i); } let __ret: [G; OUT_689] = unsafe { *(record.function_queries[689].output_at(__i).as_ptr() as *const [G; OUT_689]) }; __ret }, _ => aiur_fn_689(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_688] = { let __args: [G; IN_688] = [__v_13, __v_2, __v_15, __v_16, __v_3, __v_4, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[688].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[688].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[688].bump_multiplicity(__i); } let __ret: [G; OUT_688] = unsafe { *(record.function_queries[688].output_at(__i).as_ptr() as *const [G; OUT_688]) }; __ret }, _ => aiur_fn_688(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(1); @@ -58309,24 +58263,24 @@ fn aiur_fn_690( let __v_26: G = G::from_u64(1); let __v_27: G = { let __values: [G; 3] = [__v_25, __v_26, __v_26]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_28: G = G::from_u64(0); - let __r_arr: [G; OUT_701] = { let __args: [G; IN_701] = [__v_18, __v_6, __v_21, __v_24, __v_27, __v_28, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[701].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[701].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[701].bump_multiplicity(__i); } let __ret: [G; OUT_701] = unsafe { *(record.function_queries[701].output_at(__i).as_ptr() as *const [G; OUT_701]) }; __ret }, _ => aiur_fn_701(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_700] = { let __args: [G; IN_700] = [__v_18, __v_6, __v_21, __v_24, __v_27, __v_28, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[700].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[700].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[700].bump_multiplicity(__i); } let __ret: [G; OUT_700] = unsafe { *(record.function_queries[700].output_at(__i).as_ptr() as *const [G; OUT_700]) }; __ret }, _ => aiur_fn_700(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = __r_arr[1]; let __v_31: G = __r_arr[2]; let __v_32: G = __r_arr[3]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_33: G = __r_arr[0]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_30]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_30]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = (__v_33 + __v_34); let __v_36: G = (__v_15 + __v_35); let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_32]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = __r_arr[1]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_38, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_38, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; let __v_40: G = G::from_u64(0); - let __r_arr: [G; OUT_694] = { let __args: [G; IN_694] = [__v_39, __v_34, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[694].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[694].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[694].bump_multiplicity(__i); } let __ret: [G; OUT_694] = unsafe { *(record.function_queries[694].output_at(__i).as_ptr() as *const [G; OUT_694]) }; __ret }, _ => aiur_fn_694(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_693] = { let __args: [G; IN_693] = [__v_39, __v_34, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[693].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[693].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[693].bump_multiplicity(__i); } let __ret: [G; OUT_693] = unsafe { *(record.function_queries[693].output_at(__i).as_ptr() as *const [G; OUT_693]) }; __ret }, _ => aiur_fn_693(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = G::from_u64(1); let __v_43: G = (__v_36 - __v_42); @@ -58335,66 +58289,66 @@ fn aiur_fn_690( let __v_46: G = G::from_u64(0); let __v_47: G = G::from_u64(0); let __v_48: G = { let __values: [G; 4] = [__v_46, __v_45, __v_47, __v_47]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_48, __v_41]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_48, __v_41]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __v_50: G = G::from_u64(2); let __v_51: G = G::from_u64(0); let __v_52: G = { let __values: [G; 4] = [__v_50, __v_0, __v_5, __v_51]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_696] = { let __args: [G; IN_696] = [__v_52, __v_2, __v_8, __v_36, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[696].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[696].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[696].bump_multiplicity(__i); } let __ret: [G; OUT_696] = unsafe { *(record.function_queries[696].output_at(__i).as_ptr() as *const [G; OUT_696]) }; __ret }, _ => aiur_fn_696(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_695] = { let __args: [G; IN_695] = [__v_52, __v_2, __v_8, __v_36, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[695].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[695].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[695].bump_multiplicity(__i); } let __ret: [G; OUT_695] = unsafe { *(record.function_queries[695].output_at(__i).as_ptr() as *const [G; OUT_695]) }; __ret }, _ => aiur_fn_695(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __v_54: G = G::from_u64(0); - let __r_arr: [G; OUT_695] = { let __args: [G; IN_695] = [__v_53, __v_33, __v_35, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[695].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[695].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[695].bump_multiplicity(__i); } let __ret: [G; OUT_695] = unsafe { *(record.function_queries[695].output_at(__i).as_ptr() as *const [G; OUT_695]) }; __ret }, _ => aiur_fn_695(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_694] = { let __args: [G; IN_694] = [__v_53, __v_33, __v_35, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[694].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[694].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[694].bump_multiplicity(__i); } let __ret: [G; OUT_694] = unsafe { *(record.function_queries[694].output_at(__i).as_ptr() as *const [G; OUT_694]) }; __ret }, _ => aiur_fn_694(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __v_56: G = G::from_u64(3); let __v_57: G = G::from_u64(0); let __v_58: G = { let __values: [G; 4] = [__v_56, __v_49, __v_55, __v_57]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_59: G = G::from_u64(0); - let __r_arr: [G; OUT_693] = { let __args: [G; IN_693] = [__v_30, __v_31, __v_29, __v_7, __v_11, __v_33, __v_15, __v_59]; let __cu = unconstrained; let __hit = record.function_queries[693].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[693].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[693].bump_multiplicity(__i); } let __ret: [G; OUT_693] = unsafe { *(record.function_queries[693].output_at(__i).as_ptr() as *const [G; OUT_693]) }; __ret }, _ => aiur_fn_693(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_692] = { let __args: [G; IN_692] = [__v_30, __v_31, __v_29, __v_7, __v_11, __v_33, __v_15, __v_59]; let __cu = unconstrained; let __hit = record.function_queries[692].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[692].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[692].bump_multiplicity(__i); } let __ret: [G; OUT_692] = unsafe { *(record.function_queries[692].output_at(__i).as_ptr() as *const [G; OUT_692]) }; __ret }, _ => aiur_fn_692(__args, record, io_buffer, __cu)? } }; let __v_60: G = __r_arr[0]; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_58, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_58, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_61: G = __r_arr[0]; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_61, __v_29]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_61, __v_29]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_62: G = __r_arr[0]; - let __ret: [G; OUT_690] = [__v_62]; - record.function_queries[690].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_689] = [__v_62]; + record.function_queries[689].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_691: usize = 1; -const IN_691: usize = 1; -const OUT_691: usize = 2; -fn aiur_fn_691( - inp: [G; IN_691], +const INPUT_SIZE_690: usize = 1; +const IN_690: usize = 1; +const OUT_690: usize = 2; +fn aiur_fn_690( + inp: [G; IN_690], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_691], ExecError> { +) -> Result<[G; OUT_690], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(1); let __v_2: G = G::from_u64(1); let __v_3: G = { let __values: [G; 3] = [__v_1, __v_2, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_692] = { let __args: [G; IN_692] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[692].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[692].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[692].bump_multiplicity(__i); } let __ret: [G; OUT_692] = unsafe { *(record.function_queries[692].output_at(__i).as_ptr() as *const [G; OUT_692]) }; __ret }, _ => aiur_fn_692(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_691] = { let __args: [G; IN_691] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[691].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[691].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[691].bump_multiplicity(__i); } let __ret: [G; OUT_691] = unsafe { *(record.function_queries[691].output_at(__i).as_ptr() as *const [G; OUT_691]) }; __ret }, _ => aiur_fn_691(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; - let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_691] = [__v_6, __v_5]; - record.function_queries[691].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_690] = [__v_6, __v_5]; + record.function_queries[690].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_692: usize = 2; -const IN_692: usize = 2; -const OUT_692: usize = 2; -fn aiur_fn_692( - inp: [G; IN_692], +const INPUT_SIZE_691: usize = 2; +const IN_691: usize = 2; +const OUT_691: usize = 2; +fn aiur_fn_691( + inp: [G; IN_691], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_692], ExecError> { +) -> Result<[G; OUT_691], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58407,31 +58361,31 @@ fn aiur_fn_692( 5u64 => { let __v_6: G = G::from_u64(0); let __v_7: G = { let __values: [G; 3] = [__v_6, __v_3, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_692] = { let __args: [G; IN_692] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[692].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[692].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[692].bump_multiplicity(__i); } let __ret: [G; OUT_692] = unsafe { *(record.function_queries[692].output_at(__i).as_ptr() as *const [G; OUT_692]) }; __ret }, _ => aiur_fn_692(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_691] = { let __args: [G; IN_691] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[691].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[691].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[691].bump_multiplicity(__i); } let __ret: [G; OUT_691] = unsafe { *(record.function_queries[691].output_at(__i).as_ptr() as *const [G; OUT_691]) }; __ret }, _ => aiur_fn_691(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; - let __ret: [G; OUT_692] = [__v_8, __v_9]; - record.function_queries[692].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_691] = [__v_8, __v_9]; + record.function_queries[691].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_692] = [__v_1, __v_0]; - record.function_queries[692].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_691] = [__v_1, __v_0]; + record.function_queries[691].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_693: usize = 8; -const IN_693: usize = 8; -const OUT_693: usize = 1; -fn aiur_fn_693( - inp: [G; IN_693], +const INPUT_SIZE_692: usize = 8; +const IN_692: usize = 8; +const OUT_692: usize = 1; +fn aiur_fn_692( + inp: [G; IN_692], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_693], ExecError> { +) -> Result<[G; OUT_692], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58450,30 +58404,30 @@ fn aiur_fn_693( let __v_11: G = G::from_u64(1); let __v_12: G = G::from_u64(1); let __v_13: G = { let __values: [G; 3] = [__v_11, __v_12, __v_12]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_693] = [__v_13]; - record.function_queries[693].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_692] = [__v_13]; + record.function_queries[692].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_1, __v_7, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_766] = { let __args: [G; IN_766] = [__v_1, __v_7, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[766].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[766].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[766].bump_multiplicity(__i); } let __ret: [G; OUT_766] = unsafe { *(record.function_queries[766].output_at(__i).as_ptr() as *const [G; OUT_766]) }; __ret }, _ => aiur_fn_766(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = G::from_u64(0); - let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_3, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_766] = { let __args: [G; IN_766] = [__v_3, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[766].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[766].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[766].bump_multiplicity(__i); } let __ret: [G; OUT_766] = unsafe { *(record.function_queries[766].output_at(__i).as_ptr() as *const [G; OUT_766]) }; __ret }, _ => aiur_fn_766(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = (__v_5 + __v_7); let __v_16: G = (__v_6 + __v_15); - let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = (__v_5 - __v_9); let __v_19: G = (__v_18 + __v_7); let __v_20: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_17, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_17, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_691] = { let __args: [G; IN_691] = [__v_21]; let __cu = unconstrained; let __hit = record.function_queries[691].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[691].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[691].bump_multiplicity(__i); } let __ret: [G; OUT_691] = unsafe { *(record.function_queries[691].output_at(__i).as_ptr() as *const [G; OUT_691]) }; __ret }, _ => aiur_fn_691(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_690] = { let __args: [G; IN_690] = [__v_21]; let __cu = unconstrained; let __hit = record.function_queries[690].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[690].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[690].bump_multiplicity(__i); } let __ret: [G; OUT_690] = unsafe { *(record.function_queries[690].output_at(__i).as_ptr() as *const [G; OUT_690]) }; __ret }, _ => aiur_fn_690(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = __r_arr[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_24: G = __r_arr[0]; let __v_25: G = (__v_16 + __v_24); let __v_26: G = G::from_u64(1); @@ -58487,37 +58441,37 @@ fn aiur_fn_693( let __v_34: G = G::from_u64(1); let __v_35: G = G::from_u64(1); let __v_36: G = { let __values: [G; 3] = [__v_34, __v_35, __v_35]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_23, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_23, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_37]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_39, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_39, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; let __v_41: G = G::from_u64(0); let __v_42: G = G::from_u64(0); let __v_43: G = { let __values: [G; 4] = [__v_41, __v_29, __v_42, __v_42]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_255] = { let __args: [G; IN_255] = [__v_43, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[255].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[255].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[255].bump_multiplicity(__i); } let __ret: [G; OUT_255] = unsafe { *(record.function_queries[255].output_at(__i).as_ptr() as *const [G; OUT_255]) }; __ret }, _ => aiur_fn_255(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_254] = { let __args: [G; IN_254] = [__v_43, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[254].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[254].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[254].bump_multiplicity(__i); } let __ret: [G; OUT_254] = unsafe { *(record.function_queries[254].output_at(__i).as_ptr() as *const [G; OUT_254]) }; __ret }, _ => aiur_fn_254(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = G::from_u64(0); let __v_46: G = G::from_u64(0); let __v_47: G = { let __values: [G; 4] = [__v_45, __v_33, __v_46, __v_46]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_48: G = G::from_u64(0); - let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_47, __v_24, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_659] = { let __args: [G; IN_659] = [__v_47, __v_24, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[659].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[659].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[659].bump_multiplicity(__i); } let __ret: [G; OUT_659] = unsafe { *(record.function_queries[659].output_at(__i).as_ptr() as *const [G; OUT_659]) }; __ret }, _ => aiur_fn_659(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __v_50: G = G::from_u64(3); let __v_51: G = G::from_u64(0); let __v_52: G = { let __values: [G; 4] = [__v_50, __v_44, __v_49, __v_51]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_661] = { let __args: [G; IN_661] = [__v_52, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[661].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[661].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[661].bump_multiplicity(__i); } let __ret: [G; OUT_661] = unsafe { *(record.function_queries[661].output_at(__i).as_ptr() as *const [G; OUT_661]) }; __ret }, _ => aiur_fn_661(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_660] = { let __args: [G; IN_660] = [__v_52, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[660].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[660].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[660].bump_multiplicity(__i); } let __ret: [G; OUT_660] = unsafe { *(record.function_queries[660].output_at(__i).as_ptr() as *const [G; OUT_660]) }; __ret }, _ => aiur_fn_660(__args, record, io_buffer, __cu)? } }; let __v_53: G = __r_arr[0]; let __v_54: G = G::from_u64(0); let __v_55: G = G::from_u64(1); let __v_56: G = (__v_7 + __v_55); - let __r_arr: [G; OUT_693] = { let __args: [G; IN_693] = [__v_10, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[693].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[693].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[693].bump_multiplicity(__i); } let __ret: [G; OUT_693] = unsafe { *(record.function_queries[693].output_at(__i).as_ptr() as *const [G; OUT_693]) }; __ret }, _ => aiur_fn_693(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_692] = { let __args: [G; IN_692] = [__v_10, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[692].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[692].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[692].bump_multiplicity(__i); } let __ret: [G; OUT_692] = unsafe { *(record.function_queries[692].output_at(__i).as_ptr() as *const [G; OUT_692]) }; __ret }, _ => aiur_fn_692(__args, record, io_buffer, __cu)? } }; let __v_57: G = __r_arr[0]; let __v_58: G = { let __values: [G; 3] = [__v_54, __v_53, __v_57]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_693] = [__v_58]; - record.function_queries[693].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_692] = [__v_58]; + record.function_queries[692].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -58527,15 +58481,15 @@ fn aiur_fn_693( }) } -const INPUT_SIZE_694: usize = 3; -const IN_694: usize = 3; -const OUT_694: usize = 1; -fn aiur_fn_694( - inp: [G; IN_694], +const INPUT_SIZE_693: usize = 3; +const IN_693: usize = 3; +const OUT_693: usize = 1; +fn aiur_fn_693( + inp: [G; IN_693], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_694], ExecError> { +) -> Result<[G; OUT_693], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58549,19 +58503,19 @@ fn aiur_fn_694( let __v_6: G = G::from_u64(1); let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_694] = [__v_8]; - record.function_queries[694].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_693] = [__v_8]; + record.function_queries[693].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __r_arr: [G; OUT_694] = { let __args: [G; IN_694] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[694].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[694].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[694].bump_multiplicity(__i); } let __ret: [G; OUT_694] = unsafe { *(record.function_queries[694].output_at(__i).as_ptr() as *const [G; OUT_694]) }; __ret }, _ => aiur_fn_694(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_693] = { let __args: [G; IN_693] = [__v_5, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[693].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[693].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[693].bump_multiplicity(__i); } let __ret: [G; OUT_693] = unsafe { *(record.function_queries[693].output_at(__i).as_ptr() as *const [G; OUT_693]) }; __ret }, _ => aiur_fn_693(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = { let __values: [G; 3] = [__v_6, __v_7, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_694] = [__v_9]; - record.function_queries[694].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_693] = [__v_9]; + record.function_queries[693].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -58571,15 +58525,15 @@ fn aiur_fn_694( }) } -const INPUT_SIZE_695: usize = 4; -const IN_695: usize = 4; -const OUT_695: usize = 1; -fn aiur_fn_695( - inp: [G; IN_695], +const INPUT_SIZE_694: usize = 4; +const IN_694: usize = 4; +const OUT_694: usize = 1; +fn aiur_fn_694( + inp: [G; IN_694], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_695], ExecError> { +) -> Result<[G; OUT_694], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58588,8 +58542,8 @@ fn aiur_fn_695( let __v_4: G = (__v_1 - __v_3); match __v_4.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_695] = [__v_0]; - record.function_queries[695].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_694] = [__v_0]; + record.function_queries[694].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -58604,25 +58558,25 @@ fn aiur_fn_695( let __v_13: G = { let __values: [G; 4] = [__v_11, __v_0, __v_10, __v_12]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_14: G = G::from_u64(1); let __v_15: G = (__v_3 + __v_14); - let __r_arr: [G; OUT_695] = { let __args: [G; IN_695] = [__v_13, __v_1, __v_2, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[695].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[695].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[695].bump_multiplicity(__i); } let __ret: [G; OUT_695] = unsafe { *(record.function_queries[695].output_at(__i).as_ptr() as *const [G; OUT_695]) }; __ret }, _ => aiur_fn_695(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_694] = { let __args: [G; IN_694] = [__v_13, __v_1, __v_2, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[694].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[694].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[694].bump_multiplicity(__i); } let __ret: [G; OUT_694] = unsafe { *(record.function_queries[694].output_at(__i).as_ptr() as *const [G; OUT_694]) }; __ret }, _ => aiur_fn_694(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; - let __ret: [G; OUT_695] = [__v_16]; - record.function_queries[695].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_694] = [__v_16]; + record.function_queries[694].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_696: usize = 6; -const IN_696: usize = 6; -const OUT_696: usize = 1; -fn aiur_fn_696( - inp: [G; IN_696], +const INPUT_SIZE_695: usize = 6; +const IN_695: usize = 6; +const OUT_695: usize = 1; +fn aiur_fn_695( + inp: [G; IN_695], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_696], ExecError> { +) -> Result<[G; OUT_695], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58635,55 +58589,55 @@ fn aiur_fn_696( let __v_6: G = G::from_u64(1); let __v_7: G = (__v_3 - __v_6); let __v_8: G = G::from_u64(0); - let __r_arr: [G; OUT_668] = { let __args: [G; IN_668] = [__v_0, __v_2, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[668].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[668].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[668].bump_multiplicity(__i); } let __ret: [G; OUT_668] = unsafe { *(record.function_queries[668].output_at(__i).as_ptr() as *const [G; OUT_668]) }; __ret }, _ => aiur_fn_668(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_667] = { let __args: [G; IN_667] = [__v_0, __v_2, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[667].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[667].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[667].bump_multiplicity(__i); } let __ret: [G; OUT_667] = unsafe { *(record.function_queries[667].output_at(__i).as_ptr() as *const [G; OUT_667]) }; __ret }, _ => aiur_fn_667(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __ret: [G; OUT_696] = [__v_9]; - record.function_queries[696].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_695] = [__v_9]; + record.function_queries[695].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_6: G = (__v_3 - __v_2); - let __r_arr: [G; OUT_658] = { let __args: [G; IN_658] = [__v_0, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[658].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[658].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[658].bump_multiplicity(__i); } let __ret: [G; OUT_658] = unsafe { *(record.function_queries[658].output_at(__i).as_ptr() as *const [G; OUT_658]) }; __ret }, _ => aiur_fn_658(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_657] = { let __args: [G; IN_657] = [__v_0, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[657].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[657].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[657].bump_multiplicity(__i); } let __ret: [G; OUT_657] = unsafe { *(record.function_queries[657].output_at(__i).as_ptr() as *const [G; OUT_657]) }; __ret }, _ => aiur_fn_657(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_696] = [__v_7]; - record.function_queries[696].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_695] = [__v_7]; + record.function_queries[695].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_697: usize = 3; -const IN_697: usize = 3; -const OUT_697: usize = 2; -fn aiur_fn_697( - inp: [G; IN_697], +const INPUT_SIZE_696: usize = 3; +const IN_696: usize = 3; +const OUT_696: usize = 2; +fn aiur_fn_696( + inp: [G; IN_696], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_697], ExecError> { +) -> Result<[G; OUT_696], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_698] = { let __args: [G; IN_698] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[698].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[698].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[698].bump_multiplicity(__i); } let __ret: [G; OUT_698] = unsafe { *(record.function_queries[698].output_at(__i).as_ptr() as *const [G; OUT_698]) }; __ret }, _ => aiur_fn_698(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_697] = { let __args: [G; IN_697] = [__v_0, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[697].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[697].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[697].bump_multiplicity(__i); } let __ret: [G; OUT_697] = unsafe { *(record.function_queries[697].output_at(__i).as_ptr() as *const [G; OUT_697]) }; __ret }, _ => aiur_fn_697(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; - let __ret: [G; OUT_697] = [__v_3, __v_4]; - record.function_queries[697].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_696] = [__v_3, __v_4]; + record.function_queries[696].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_698: usize = 3; -const IN_698: usize = 3; -const OUT_698: usize = 2; -fn aiur_fn_698( - inp: [G; IN_698], +const INPUT_SIZE_697: usize = 3; +const IN_697: usize = 3; +const OUT_697: usize = 2; +fn aiur_fn_697( + inp: [G; IN_697], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_698], ExecError> { +) -> Result<[G; OUT_697], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58691,7 +58645,7 @@ fn aiur_fn_698( let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_417] = { let __args: [G; IN_417] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[417].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[417].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[417].bump_multiplicity(__i); } let __ret: [G; OUT_417] = unsafe { *(record.function_queries[417].output_at(__i).as_ptr() as *const [G; OUT_417]) }; __ret }, _ => aiur_fn_417(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_0, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_6.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_7: G = __loaded[0]; @@ -58700,11 +58654,11 @@ fn aiur_fn_698( let __v_10: G = __loaded[3]; match __v_7.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_698] = { let __args: [G; IN_698] = [__v_9, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[698].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[698].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[698].bump_multiplicity(__i); } let __ret: [G; OUT_698] = unsafe { *(record.function_queries[698].output_at(__i).as_ptr() as *const [G; OUT_698]) }; __ret }, _ => aiur_fn_698(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_697] = { let __args: [G; IN_697] = [__v_9, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[697].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[697].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[697].bump_multiplicity(__i); } let __ret: [G; OUT_697] = unsafe { *(record.function_queries[697].output_at(__i).as_ptr() as *const [G; OUT_697]) }; __ret }, _ => aiur_fn_697(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; - let __ret: [G; OUT_698] = [__v_11, __v_12]; - record.function_queries[698].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_697] = [__v_11, __v_12]; + record.function_queries[697].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -58719,18 +58673,18 @@ fn aiur_fn_698( match __v_13.as_canonical_u64() { 2u64 => { let __v_17: G = G::from_u64(0); - let __r_arr: [G; OUT_699] = { let __args: [G; IN_699] = [__v_1, __v_14, __v_12, __v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[699].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[699].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[699].bump_multiplicity(__i); } let __ret: [G; OUT_699] = unsafe { *(record.function_queries[699].output_at(__i).as_ptr() as *const [G; OUT_699]) }; __ret }, _ => aiur_fn_699(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_698] = { let __args: [G; IN_698] = [__v_1, __v_14, __v_12, __v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[698].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[698].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[698].bump_multiplicity(__i); } let __ret: [G; OUT_698] = unsafe { *(record.function_queries[698].output_at(__i).as_ptr() as *const [G; OUT_698]) }; __ret }, _ => aiur_fn_698(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = __r_arr[1]; - let __ret: [G; OUT_698] = [__v_18, __v_19]; - record.function_queries[698].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_697] = [__v_18, __v_19]; + record.function_queries[697].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); - let __ret: [G; OUT_698] = [__v_17, __v_18]; - record.function_queries[698].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_697] = [__v_17, __v_18]; + record.function_queries[697].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -58739,15 +58693,15 @@ fn aiur_fn_698( }) } -const INPUT_SIZE_699: usize = 5; -const IN_699: usize = 5; -const OUT_699: usize = 2; -fn aiur_fn_699( - inp: [G; IN_699], +const INPUT_SIZE_698: usize = 5; +const IN_698: usize = 5; +const OUT_698: usize = 2; +fn aiur_fn_698( + inp: [G; IN_698], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_699], ExecError> { +) -> Result<[G; OUT_698], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58765,8 +58719,8 @@ fn aiur_fn_699( 1u64 => { let __v_11: G = G::from_u64(0); let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_699] = [__v_11, __v_12]; - record.function_queries[699].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_698] = [__v_11, __v_12]; + record.function_queries[698].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -58778,7 +58732,7 @@ fn aiur_fn_699( break '__mc_0 [__v_12]; }, _ => { - let __r_arr: [G; OUT_700] = { let __args: [G; IN_700] = [__v_8, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[700].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[700].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[700].bump_multiplicity(__i); } let __ret: [G; OUT_700] = unsafe { *(record.function_queries[700].output_at(__i).as_ptr() as *const [G; OUT_700]) }; __ret }, _ => aiur_fn_700(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_699] = { let __args: [G; IN_699] = [__v_8, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[699].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[699].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[699].bump_multiplicity(__i); } let __ret: [G; OUT_699] = unsafe { *(record.function_queries[699].output_at(__i).as_ptr() as *const [G; OUT_699]) }; __ret }, _ => aiur_fn_699(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; break '__mc_0 [__v_12]; }, @@ -58789,18 +58743,18 @@ fn aiur_fn_699( match __v_13.as_canonical_u64() { 1u64 => { let __v_14: G = G::from_u64(1); - let __ret: [G; OUT_699] = [__v_14, __v_4]; - record.function_queries[699].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_698] = [__v_14, __v_4]; + record.function_queries[698].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_14: G = G::from_u64(1); let __v_15: G = (__v_4 + __v_14); - let __r_arr: [G; OUT_699] = { let __args: [G; IN_699] = [__v_10, __v_1, __v_2, __v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[699].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[699].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[699].bump_multiplicity(__i); } let __ret: [G; OUT_699] = unsafe { *(record.function_queries[699].output_at(__i).as_ptr() as *const [G; OUT_699]) }; __ret }, _ => aiur_fn_699(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_698] = { let __args: [G; IN_698] = [__v_10, __v_1, __v_2, __v_3, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[698].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[698].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[698].bump_multiplicity(__i); } let __ret: [G; OUT_698] = unsafe { *(record.function_queries[698].output_at(__i).as_ptr() as *const [G; OUT_698]) }; __ret }, _ => aiur_fn_698(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; let __v_17: G = __r_arr[1]; - let __ret: [G; OUT_699] = [__v_16, __v_17]; - record.function_queries[699].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_698] = [__v_16, __v_17]; + record.function_queries[698].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -58812,15 +58766,15 @@ fn aiur_fn_699( }) } -const INPUT_SIZE_700: usize = 3; -const IN_700: usize = 3; -const OUT_700: usize = 1; -fn aiur_fn_700( - inp: [G; IN_700], +const INPUT_SIZE_699: usize = 3; +const IN_699: usize = 3; +const OUT_699: usize = 1; +fn aiur_fn_699( + inp: [G; IN_699], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_700], ExecError> { +) -> Result<[G; OUT_699], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58832,8 +58786,8 @@ fn aiur_fn_700( match __v_3.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_700] = [__v_6]; - record.function_queries[700].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_699] = [__v_6]; + record.function_queries[699].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -58844,28 +58798,28 @@ fn aiur_fn_700( match __v_6.as_canonical_u64() { 1u64 => { let __v_9: G = G::from_u64(0); - let __ret: [G; OUT_700] = [__v_9]; - record.function_queries[700].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_699] = [__v_9]; + record.function_queries[699].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_9: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_4, __v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_4, __v_2, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __r_arr: [G; OUT_642] = { let __args: [G; IN_642] = [__v_10, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[642].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[642].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[642].bump_multiplicity(__i); } let __ret: [G; OUT_642] = unsafe { *(record.function_queries[642].output_at(__i).as_ptr() as *const [G; OUT_642]) }; __ret }, _ => aiur_fn_642(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_641] = { let __args: [G; IN_641] = [__v_10, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[641].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[641].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[641].bump_multiplicity(__i); } let __ret: [G; OUT_641] = unsafe { *(record.function_queries[641].output_at(__i).as_ptr() as *const [G; OUT_641]) }; __ret }, _ => aiur_fn_641(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; match __v_11.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_700] = { let __args: [G; IN_700] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[700].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[700].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[700].bump_multiplicity(__i); } let __ret: [G; OUT_700] = unsafe { *(record.function_queries[700].output_at(__i).as_ptr() as *const [G; OUT_700]) }; __ret }, _ => aiur_fn_700(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_699] = { let __args: [G; IN_699] = [__v_5, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[699].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[699].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[699].bump_multiplicity(__i); } let __ret: [G; OUT_699] = unsafe { *(record.function_queries[699].output_at(__i).as_ptr() as *const [G; OUT_699]) }; __ret }, _ => aiur_fn_699(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __ret: [G; OUT_700] = [__v_12]; - record.function_queries[700].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_699] = [__v_12]; + record.function_queries[699].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_12: G = G::from_u64(0); - let __ret: [G; OUT_700] = [__v_12]; - record.function_queries[700].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_699] = [__v_12]; + record.function_queries[699].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -58882,15 +58836,15 @@ fn aiur_fn_700( }) } -const INPUT_SIZE_701: usize = 7; -const IN_701: usize = 7; -const OUT_701: usize = 4; -fn aiur_fn_701( - inp: [G; IN_701], +const INPUT_SIZE_700: usize = 7; +const IN_700: usize = 7; +const OUT_700: usize = 4; +fn aiur_fn_700( + inp: [G; IN_700], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_701], ExecError> { +) -> Result<[G; OUT_700], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58907,7 +58861,7 @@ fn aiur_fn_701( match __v_7.as_canonical_u64() { 5u64 => { let __v_11: G = (__v_6 + __v_5); - let __r_arr: [G; OUT_697] = { let __args: [G; IN_697] = [__v_8, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[697].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[697].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[697].bump_multiplicity(__i); } let __ret: [G; OUT_697] = unsafe { *(record.function_queries[697].output_at(__i).as_ptr() as *const [G; OUT_697]) }; __ret }, _ => aiur_fn_697(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_696] = { let __args: [G; IN_696] = [__v_8, __v_1, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[696].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[696].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[696].bump_multiplicity(__i); } let __ret: [G; OUT_696] = unsafe { *(record.function_queries[696].output_at(__i).as_ptr() as *const [G; OUT_696]) }; __ret }, _ => aiur_fn_696(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; let __v_14: G = G::from_u64(0); @@ -58920,53 +58874,53 @@ fn aiur_fn_701( let __v_19: G = { let __values: [G; 3] = [__v_18, __v_13, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_20: G = G::from_u64(1); let __v_21: G = (__v_5 + __v_20); - let __r_arr: [G; OUT_701] = { let __args: [G; IN_701] = [__v_9, __v_1, __v_15, __v_17, __v_19, __v_21, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[701].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[701].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[701].bump_multiplicity(__i); } let __ret: [G; OUT_701] = unsafe { *(record.function_queries[701].output_at(__i).as_ptr() as *const [G; OUT_701]) }; __ret }, _ => aiur_fn_701(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_700] = { let __args: [G; IN_700] = [__v_9, __v_1, __v_15, __v_17, __v_19, __v_21, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[700].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[700].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[700].bump_multiplicity(__i); } let __ret: [G; OUT_700] = unsafe { *(record.function_queries[700].output_at(__i).as_ptr() as *const [G; OUT_700]) }; __ret }, _ => aiur_fn_700(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = __r_arr[1]; let __v_24: G = __r_arr[2]; let __v_25: G = __r_arr[3]; - let __ret: [G; OUT_701] = [__v_22, __v_23, __v_24, __v_25]; - record.function_queries[701].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_700] = [__v_22, __v_23, __v_24, __v_25]; + record.function_queries[700].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_16: G = G::from_u64(1); let __v_17: G = (__v_5 + __v_16); - let __r_arr: [G; OUT_701] = { let __args: [G; IN_701] = [__v_9, __v_1, __v_15, __v_3, __v_4, __v_17, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[701].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[701].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[701].bump_multiplicity(__i); } let __ret: [G; OUT_701] = unsafe { *(record.function_queries[701].output_at(__i).as_ptr() as *const [G; OUT_701]) }; __ret }, _ => aiur_fn_701(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_700] = { let __args: [G; IN_700] = [__v_9, __v_1, __v_15, __v_3, __v_4, __v_17, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[700].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[700].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[700].bump_multiplicity(__i); } let __ret: [G; OUT_700] = unsafe { *(record.function_queries[700].output_at(__i).as_ptr() as *const [G; OUT_700]) }; __ret }, _ => aiur_fn_700(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = __r_arr[1]; let __v_20: G = __r_arr[2]; let __v_21: G = __r_arr[3]; - let __ret: [G; OUT_701] = [__v_18, __v_19, __v_20, __v_21]; - record.function_queries[701].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_700] = [__v_18, __v_19, __v_20, __v_21]; + record.function_queries[700].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, _ => { - let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; - let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __ret: [G; OUT_701] = [__v_11, __v_12, __v_13, __v_0]; - record.function_queries[701].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_700] = [__v_11, __v_12, __v_13, __v_0]; + record.function_queries[700].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_702: usize = 4; -const IN_702: usize = 4; -const OUT_702: usize = 1; -fn aiur_fn_702( - inp: [G; IN_702], +const INPUT_SIZE_701: usize = 4; +const IN_701: usize = 4; +const OUT_701: usize = 1; +fn aiur_fn_701( + inp: [G; IN_701], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_702], ExecError> { +) -> Result<[G; OUT_701], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -58984,12 +58938,12 @@ fn aiur_fn_702( let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 3] = [__v_10, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_702] = [__v_12]; - record.function_queries[702].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_701] = [__v_12]; + record.function_queries[701].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_10.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_11: G = __loaded[0]; @@ -59006,26 +58960,26 @@ fn aiur_fn_702( let __v_22: G = __loaded[11]; match __v_11.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_666] = { let __args: [G; IN_666] = [__v_5, __v_13, __v_14, __v_15, __v_8, __v_1, __v_2, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[666].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[666].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[666].bump_multiplicity(__i); } let __ret: [G; OUT_666] = unsafe { *(record.function_queries[666].output_at(__i).as_ptr() as *const [G; OUT_666]) }; __ret }, _ => aiur_fn_666(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_665] = { let __args: [G; IN_665] = [__v_5, __v_13, __v_14, __v_15, __v_8, __v_1, __v_2, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[665].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[665].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[665].bump_multiplicity(__i); } let __ret: [G; OUT_665] = unsafe { *(record.function_queries[665].output_at(__i).as_ptr() as *const [G; OUT_665]) }; __ret }, _ => aiur_fn_665(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __v_24: G = G::from_u64(0); - let __r_arr: [G; OUT_358] = { let __args: [G; IN_358] = [__v_23, __v_3, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[358].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[358].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[358].bump_multiplicity(__i); } let __ret: [G; OUT_358] = unsafe { *(record.function_queries[358].output_at(__i).as_ptr() as *const [G; OUT_358]) }; __ret }, _ => aiur_fn_358(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_357] = { let __args: [G; IN_357] = [__v_23, __v_3, __v_24]; let __cu = unconstrained; let __hit = record.function_queries[357].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[357].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[357].bump_multiplicity(__i); } let __ret: [G; OUT_357] = unsafe { *(record.function_queries[357].output_at(__i).as_ptr() as *const [G; OUT_357]) }; __ret }, _ => aiur_fn_357(__args, record, io_buffer, __cu)? } }; let __v_25: G = __r_arr[0]; let __v_26: G = G::from_u64(0); let __v_27: G = G::from_u64(1); let __v_28: G = (__v_3 + __v_27); - let __r_arr: [G; OUT_702] = { let __args: [G; IN_702] = [__v_9, __v_1, __v_2, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[702].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[702].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[702].bump_multiplicity(__i); } let __ret: [G; OUT_702] = unsafe { *(record.function_queries[702].output_at(__i).as_ptr() as *const [G; OUT_702]) }; __ret }, _ => aiur_fn_702(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_701] = { let __args: [G; IN_701] = [__v_9, __v_1, __v_2, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[701].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[701].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[701].bump_multiplicity(__i); } let __ret: [G; OUT_701] = unsafe { *(record.function_queries[701].output_at(__i).as_ptr() as *const [G; OUT_701]) }; __ret }, _ => aiur_fn_701(__args, record, io_buffer, __cu)? } }; let __v_29: G = __r_arr[0]; let __v_30: G = { let __values: [G; 3] = [__v_26, __v_25, __v_29]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_702] = [__v_30]; - record.function_queries[702].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_701] = [__v_30]; + record.function_queries[701].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_702] = { let __args: [G; IN_702] = [__v_9, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[702].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[702].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[702].bump_multiplicity(__i); } let __ret: [G; OUT_702] = unsafe { *(record.function_queries[702].output_at(__i).as_ptr() as *const [G; OUT_702]) }; __ret }, _ => aiur_fn_702(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_701] = { let __args: [G; IN_701] = [__v_9, __v_1, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[701].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[701].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[701].bump_multiplicity(__i); } let __ret: [G; OUT_701] = unsafe { *(record.function_queries[701].output_at(__i).as_ptr() as *const [G; OUT_701]) }; __ret }, _ => aiur_fn_701(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_702] = [__v_23]; - record.function_queries[702].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_701] = [__v_23]; + record.function_queries[701].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59037,15 +58991,15 @@ fn aiur_fn_702( }) } -const INPUT_SIZE_703: usize = 13; -const IN_703: usize = 13; -const OUT_703: usize = 0; -fn aiur_fn_703( - inp: [G; IN_703], +const INPUT_SIZE_702: usize = 13; +const IN_702: usize = 13; +const OUT_702: usize = 0; +fn aiur_fn_702( + inp: [G; IN_702], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_703], ExecError> { +) -> Result<[G; OUT_702], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -59062,9 +59016,9 @@ fn aiur_fn_703( let __v_12: G = inp[12]; match __v_0.as_canonical_u64() { 7u64 => { - let __r_arr: [G; OUT_634] = { let __args: [G; IN_634] = [__v_2, __v_3, __v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[634].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[634].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[634].bump_multiplicity(__i); } let __ret: [G; OUT_634] = unsafe { *(record.function_queries[634].output_at(__i).as_ptr() as *const [G; OUT_634]) }; __ret }, _ => aiur_fn_634(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_633] = { let __args: [G; IN_633] = [__v_2, __v_3, __v_5, __v_6, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[633].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[633].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[633].bump_multiplicity(__i); } let __ret: [G; OUT_633] = unsafe { *(record.function_queries[633].output_at(__i).as_ptr() as *const [G; OUT_633]) }; __ret }, _ => aiur_fn_633(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_14.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_15: G = __loaded[0]; @@ -59081,9 +59035,9 @@ fn aiur_fn_703( let __v_26: G = __loaded[11]; match __v_15.as_canonical_u64() { 5u64 => { - let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_631] = { let __args: [G; IN_631] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[631].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[631].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[631].bump_multiplicity(__i); } let __ret: [G; OUT_631] = unsafe { *(record.function_queries[631].output_at(__i).as_ptr() as *const [G; OUT_631]) }; __ret }, _ => aiur_fn_631(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; - let __r_arr: [G; OUT_632] = { let __args: [G; IN_632] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[632].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[632].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[632].bump_multiplicity(__i); } let __ret: [G; OUT_632] = unsafe { *(record.function_queries[632].output_at(__i).as_ptr() as *const [G; OUT_632]) }; __ret }, _ => aiur_fn_632(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_631] = { let __args: [G; IN_631] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[631].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[631].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[631].bump_multiplicity(__i); } let __ret: [G; OUT_631] = unsafe { *(record.function_queries[631].output_at(__i).as_ptr() as *const [G; OUT_631]) }; __ret }, _ => aiur_fn_631(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = G::from_u64(1); let __r_arr: [G; OUT_2] = { let __args: [G; IN_2] = [__v_10, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[2].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[2].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[2].bump_multiplicity(__i); } let __ret: [G; OUT_2] = unsafe { *(record.function_queries[2].output_at(__i).as_ptr() as *const [G; OUT_2]) }; __ret }, _ => aiur_fn_2(__args, record, io_buffer, __cu)? } }; @@ -59091,7 +59045,7 @@ fn aiur_fn_703( let __v_31: G = (__v_29 - __v_30); let __v_32: G = (__v_28 * __v_31); let __v_33: G = (__v_27 * __v_32); - let __r_arr: [G; OUT_787] = { let __args: [G; IN_787] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[787].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[787].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[787].bump_multiplicity(__i); } let __ret: [G; OUT_787] = unsafe { *(record.function_queries[787].output_at(__i).as_ptr() as *const [G; OUT_787]) }; __ret }, _ => aiur_fn_787(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; if (__v_34 != __v_20) { return Err(ExecError::AssertEqMismatch { lhs: __v_34.as_canonical_u64(), rhs: __v_20.as_canonical_u64(), msg: Some("recursor rule count differs from the inductive's ctor count".to_string()) }); @@ -59101,11 +59055,11 @@ fn aiur_fn_703( let __v_37: G = (__v_35 + __v_36); let __v_38: G = G::from_u64(1); let __v_39: G = (__v_37 + __v_38); - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_2, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_2, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_40: G = __r_arr[0]; let __v_41: G = (__v_5 + __v_6); let __v_42: G = (__v_3 + __v_41); - let __r_arr: [G; OUT_706] = { let __args: [G; IN_706] = [__v_7, __v_42, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[706].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[706].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[706].bump_multiplicity(__i); } let __ret: [G; OUT_706] = unsafe { *(record.function_queries[706].output_at(__i).as_ptr() as *const [G; OUT_706]) }; __ret }, _ => aiur_fn_706(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_705] = { let __args: [G; IN_705] = [__v_7, __v_42, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[705].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[705].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[705].bump_multiplicity(__i); } let __ret: [G; OUT_705] = unsafe { *(record.function_queries[705].output_at(__i).as_ptr() as *const [G; OUT_705]) }; __ret }, _ => aiur_fn_705(__args, record, io_buffer, __cu)? } }; let __mc_out___mc_0: [G; 0] = '__mc_0: { match __v_33.as_canonical_u64() { 1u64 => { break '__mc_0 []; @@ -59118,20 +59072,20 @@ fn aiur_fn_703( return Err(ExecError::AssertEqMismatch { lhs: __v_4.as_canonical_u64(), rhs: __v_19.as_canonical_u64(), msg: Some("recursor index count differs from its inductive's".to_string()) }); } let __v_43: G = (__v_18 + __v_19); - let __r_arr: [G; OUT_704] = { let __args: [G; IN_704] = [__v_2, __v_3, __v_5, __v_6, __v_4, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[704].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[704].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[704].bump_multiplicity(__i); } let __ret: [G; OUT_704] = unsafe { *(record.function_queries[704].output_at(__i).as_ptr() as *const [G; OUT_704]) }; __ret }, _ => aiur_fn_704(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_703] = { let __args: [G; IN_703] = [__v_2, __v_3, __v_5, __v_6, __v_4, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[703].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[703].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[703].bump_multiplicity(__i); } let __ret: [G; OUT_703] = unsafe { *(record.function_queries[703].output_at(__i).as_ptr() as *const [G; OUT_703]) }; __ret }, _ => aiur_fn_703(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, } }; - let __r_arr: [G; OUT_630] = { let __args: [G; IN_630] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[630].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[630].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[630].bump_multiplicity(__i); } let __ret: [G; OUT_630] = unsafe { *(record.function_queries[630].output_at(__i).as_ptr() as *const [G; OUT_630]) }; __ret }, _ => aiur_fn_630(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_629] = { let __args: [G; IN_629] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[629].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[629].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[629].bump_multiplicity(__i); } let __ret: [G; OUT_629] = unsafe { *(record.function_queries[629].output_at(__i).as_ptr() as *const [G; OUT_629]) }; __ret }, _ => aiur_fn_629(__args, record, io_buffer, __cu)? } }; let __v_43: G = __r_arr[0]; if (__v_8 != __v_43) { return Err(ExecError::AssertEqMismatch { lhs: __v_8.as_canonical_u64(), rhs: __v_43.as_canonical_u64(), msg: Some("recursor k_flag disagrees with its inductive's K eligibility".to_string()) }); } - let __r_arr: [G; OUT_622] = { let __args: [G; IN_622] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[622].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[622].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[622].bump_multiplicity(__i); } let __ret: [G; OUT_622] = unsafe { *(record.function_queries[622].output_at(__i).as_ptr() as *const [G; OUT_622]) }; __ret }, _ => aiur_fn_622(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_672] = { let __args: [G; IN_672] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[672].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[672].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[672].bump_multiplicity(__i); } let __ret: [G; OUT_672] = unsafe { *(record.function_queries[672].output_at(__i).as_ptr() as *const [G; OUT_672]) }; __ret }, _ => aiur_fn_672(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_703] = []; - record.function_queries[703].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_621] = { let __args: [G; IN_621] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26]; let __cu = unconstrained; let __hit = record.function_queries[621].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[621].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[621].bump_multiplicity(__i); } let __ret: [G; OUT_621] = unsafe { *(record.function_queries[621].output_at(__i).as_ptr() as *const [G; OUT_621]) }; __ret }, _ => aiur_fn_621(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_671] = { let __args: [G; IN_671] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[671].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[671].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[671].bump_multiplicity(__i); } let __ret: [G; OUT_671] = unsafe { *(record.function_queries[671].output_at(__i).as_ptr() as *const [G; OUT_671]) }; __ret }, _ => aiur_fn_671(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_702] = []; + record.function_queries[702].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -59146,15 +59100,15 @@ fn aiur_fn_703( }) } -const INPUT_SIZE_704: usize = 6; -const IN_704: usize = 6; -const OUT_704: usize = 0; -fn aiur_fn_704( - inp: [G; IN_704], +const INPUT_SIZE_703: usize = 6; +const IN_703: usize = 6; +const OUT_703: usize = 0; +fn aiur_fn_703( + inp: [G; IN_703], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_704], ExecError> { +) -> Result<[G; OUT_703], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -59165,7 +59119,7 @@ fn aiur_fn_704( let __v_6: G = (__v_3 + __v_4); let __v_7: G = (__v_2 + __v_6); let __v_8: G = (__v_1 + __v_7); - let __r_arr: [G; OUT_597] = { let __args: [G; IN_597] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[597].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[597].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[597].bump_multiplicity(__i); } let __ret: [G; OUT_597] = unsafe { *(record.function_queries[597].output_at(__i).as_ptr() as *const [G; OUT_597]) }; __ret }, _ => aiur_fn_597(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __loaded: [G; 4] = { let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; let __ptr_u64 = __v_9.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 4 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 4] = __args[..4].try_into().unwrap(); __arr }; let __v_10: G = __loaded[0]; @@ -59177,13 +59131,13 @@ fn aiur_fn_704( let __r_arr: [G; OUT_115] = { let __args: [G; IN_115] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[115].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[115].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[115].bump_multiplicity(__i); } let __ret: [G; OUT_115] = unsafe { *(record.function_queries[115].output_at(__i).as_ptr() as *const [G; OUT_115]) }; __ret }, _ => aiur_fn_115(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_15]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_16: G = __r_arr[0]; if (__v_16 != __v_5) { return Err(ExecError::AssertEqMismatch { lhs: __v_16.as_canonical_u64(), rhs: __v_5.as_canonical_u64(), msg: Some("recursor major premise has the wrong number of spine args".to_string()) }); } - let __ret: [G; OUT_704] = []; - record.function_queries[704].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_703] = []; + record.function_queries[703].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -59193,15 +59147,15 @@ fn aiur_fn_704( }) } -const INPUT_SIZE_705: usize = 2; -const IN_705: usize = 2; -const OUT_705: usize = 1; -fn aiur_fn_705( - inp: [G; IN_705], +const INPUT_SIZE_704: usize = 2; +const IN_704: usize = 2; +const OUT_704: usize = 1; +fn aiur_fn_704( + inp: [G; IN_704], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_705], ExecError> { +) -> Result<[G; OUT_704], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -59211,8 +59165,8 @@ fn aiur_fn_705( let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); let __v_5: G = { let __values: [G; 3] = [__v_3, __v_4, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_705] = [__v_5]; - record.function_queries[705].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_704] = [__v_5]; + record.function_queries[704].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -59222,26 +59176,26 @@ fn aiur_fn_705( let __v_6: G = { let __values: [G; 3] = [__v_4, __v_1, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_1 + __v_7); - let __r_arr: [G; OUT_705] = { let __args: [G; IN_705] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[705].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[705].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[705].bump_multiplicity(__i); } let __ret: [G; OUT_705] = unsafe { *(record.function_queries[705].output_at(__i).as_ptr() as *const [G; OUT_705]) }; __ret }, _ => aiur_fn_705(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_704] = { let __args: [G; IN_704] = [__v_0, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[704].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[704].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[704].bump_multiplicity(__i); } let __ret: [G; OUT_704] = unsafe { *(record.function_queries[704].output_at(__i).as_ptr() as *const [G; OUT_704]) }; __ret }, _ => aiur_fn_704(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; let __v_10: G = { let __values: [G; 3] = [__v_3, __v_6, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_705] = [__v_10]; - record.function_queries[705].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_704] = [__v_10]; + record.function_queries[704].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_706: usize = 3; -const IN_706: usize = 3; -const OUT_706: usize = 0; -fn aiur_fn_706( - inp: [G; IN_706], +const INPUT_SIZE_705: usize = 3; +const IN_705: usize = 3; +const OUT_705: usize = 0; +fn aiur_fn_705( + inp: [G; IN_705], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_706], ExecError> { +) -> Result<[G; OUT_705], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -59254,18 +59208,18 @@ fn aiur_fn_706( let __v_7: G = __loaded[4]; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_706] = []; - record.function_queries[706].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_705] = []; + record.function_queries[705].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_4.as_canonical_u64() { _ => { let __v_8: G = (__v_1 + __v_5); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_6, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_706] = { let __args: [G; IN_706] = [__v_7, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[706].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[706].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[706].bump_multiplicity(__i); } let __ret: [G; OUT_706] = unsafe { *(record.function_queries[706].output_at(__i).as_ptr() as *const [G; OUT_706]) }; __ret }, _ => aiur_fn_706(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_706] = []; - record.function_queries[706].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_6, __v_8, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_705] = { let __args: [G; IN_705] = [__v_7, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[705].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[705].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[705].bump_multiplicity(__i); } let __ret: [G; OUT_705] = unsafe { *(record.function_queries[705].output_at(__i).as_ptr() as *const [G; OUT_705]) }; __ret }, _ => aiur_fn_705(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_705] = []; + record.function_queries[705].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59277,15 +59231,15 @@ fn aiur_fn_706( }) } -const INPUT_SIZE_707: usize = 4; -const IN_707: usize = 4; -const OUT_707: usize = 3; -fn aiur_fn_707( - inp: [G; IN_707], +const INPUT_SIZE_706: usize = 4; +const IN_706: usize = 4; +const OUT_706: usize = 3; +fn aiur_fn_706( + inp: [G; IN_706], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_707], ExecError> { +) -> Result<[G; OUT_706], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -59293,8 +59247,8 @@ fn aiur_fn_707( let __v_3: G = inp[3]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_707] = [__v_0, __v_2, __v_3]; - record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_706] = [__v_0, __v_2, __v_3]; + record.function_queries[706].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -59311,17 +59265,17 @@ fn aiur_fn_707( let __v_11: G = (__v_2 + __v_10); let __v_12: G = G::from_u64(0); let __v_13: G = { let __values: [G; 3] = [__v_12, __v_5, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_707] = { let __args: [G; IN_707] = [__v_6, __v_9, __v_11, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[707].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[707].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[707].bump_multiplicity(__i); } let __ret: [G; OUT_707] = unsafe { *(record.function_queries[707].output_at(__i).as_ptr() as *const [G; OUT_707]) }; __ret }, _ => aiur_fn_707(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_706] = { let __args: [G; IN_706] = [__v_6, __v_9, __v_11, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[706].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[706].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[706].bump_multiplicity(__i); } let __ret: [G; OUT_706] = unsafe { *(record.function_queries[706].output_at(__i).as_ptr() as *const [G; OUT_706]) }; __ret }, _ => aiur_fn_706(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; let __v_15: G = __r_arr[1]; let __v_16: G = __r_arr[2]; - let __ret: [G; OUT_707] = [__v_14, __v_15, __v_16]; - record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_706] = [__v_14, __v_15, __v_16]; + record.function_queries[706].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_707] = [__v_0, __v_2, __v_3]; - record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_706] = [__v_0, __v_2, __v_3]; + record.function_queries[706].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59330,15 +59284,15 @@ fn aiur_fn_707( }) } -const INPUT_SIZE_708: usize = 13; -const IN_708: usize = 13; -const OUT_708: usize = 0; -fn aiur_fn_708( - inp: [G; IN_708], +const INPUT_SIZE_707: usize = 13; +const IN_707: usize = 13; +const OUT_707: usize = 0; +fn aiur_fn_707( + inp: [G; IN_707], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_708], ExecError> { +) -> Result<[G; OUT_707], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -59353,131 +59307,131 @@ fn aiur_fn_708( let __v_10: G = inp[10]; let __v_11: G = inp[11]; let __v_12: G = inp[12]; - let __r_arr: [G; OUT_586] = { let __args: [G; IN_586] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[586].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[586].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[586].bump_multiplicity(__i); } let __ret: [G; OUT_586] = unsafe { *(record.function_queries[586].output_at(__i).as_ptr() as *const [G; OUT_586]) }; __ret }, _ => aiur_fn_586(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_585] = { let __args: [G; IN_585] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[585].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[585].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[585].bump_multiplicity(__i); } let __ret: [G; OUT_585] = unsafe { *(record.function_queries[585].output_at(__i).as_ptr() as *const [G; OUT_585]) }; __ret }, _ => aiur_fn_585(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; match __v_0.as_canonical_u64() { 0u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_3, __v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_3, __v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 3] = [__v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 3] = [__v_20, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = [__v_3, __v_2, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_3, __v_2, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_3, __v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_3, __v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 3] = [__v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __v_20: G = G::from_u64(0); let __v_21: G = G::from_u64(0); let __v_22: G = { let __values: [G; 3] = [__v_20, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_324] = { let __args: [G; IN_324] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[324].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[324].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[324].bump_multiplicity(__i); } let __ret: [G; OUT_324] = unsafe { *(record.function_queries[324].output_at(__i).as_ptr() as *const [G; OUT_324]) }; __ret }, _ => aiur_fn_324(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_323] = { let __args: [G; IN_323] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[323].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[323].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[323].bump_multiplicity(__i); } let __ret: [G; OUT_323] = unsafe { *(record.function_queries[323].output_at(__i).as_ptr() as *const [G; OUT_323]) }; __ret }, _ => aiur_fn_323(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; let __v_24: G = G::from_u64(1); if (__v_23 != __v_24) { return Err(ExecError::AssertEqMismatch { lhs: __v_23.as_canonical_u64(), rhs: __v_24.as_canonical_u64(), msg: Some("theorem's type is not a Prop".to_string()) }); } - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; let __v_25: G = G::from_u64(1); let __v_26: G = G::from_u64(1); let __v_27: G = { let __values: [G; 3] = [__v_25, __v_26, __v_26]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = [__v_3, __v_2, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_3, __v_2, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_3, __v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_3, __v_15, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_16: G = G::from_u64(1); let __v_17: G = G::from_u64(1); let __v_18: G = { let __values: [G; 3] = [__v_16, __v_17, __v_17]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; let __v_20: G = G::from_u64(1); let __v_21: G = G::from_u64(1); let __v_22: G = { let __values: [G; 3] = [__v_20, __v_21, __v_21]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_510] = { let __args: [G; IN_510] = [__v_3, __v_2, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[510].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[510].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[510].bump_multiplicity(__i); } let __ret: [G; OUT_510] = unsafe { *(record.function_queries[510].output_at(__i).as_ptr() as *const [G; OUT_510]) }; __ret }, _ => aiur_fn_510(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_3, __v_2, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_596] = { let __args: [G; IN_596] = [__v_12, __v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[596].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[596].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[596].bump_multiplicity(__i); } let __ret: [G; OUT_596] = unsafe { *(record.function_queries[596].output_at(__i).as_ptr() as *const [G; OUT_596]) }; __ret }, _ => aiur_fn_596(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_595] = { let __args: [G; IN_595] = [__v_12, __v_3, __v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[595].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[595].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[595].bump_multiplicity(__i); } let __ret: [G; OUT_595] = unsafe { *(record.function_queries[595].output_at(__i).as_ptr() as *const [G; OUT_595]) }; __ret }, _ => aiur_fn_595(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_585] = { let __args: [G; IN_585] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[585].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[585].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[585].bump_multiplicity(__i); } let __ret: [G; OUT_585] = unsafe { *(record.function_queries[585].output_at(__i).as_ptr() as *const [G; OUT_585]) }; __ret }, _ => aiur_fn_585(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_620] = { let __args: [G; IN_620] = [__v_2, __v_3, __v_4, __v_5, __v_1, __v_7, __v_8, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[620].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[620].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[620].bump_multiplicity(__i); } let __ret: [G; OUT_620] = unsafe { *(record.function_queries[620].output_at(__i).as_ptr() as *const [G; OUT_620]) }; __ret }, _ => aiur_fn_620(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_623] = { let __args: [G; IN_623] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[623].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[623].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[623].bump_multiplicity(__i); } let __ret: [G; OUT_623] = unsafe { *(record.function_queries[623].output_at(__i).as_ptr() as *const [G; OUT_623]) }; __ret }, _ => aiur_fn_623(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_584] = { let __args: [G; IN_584] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[584].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[584].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[584].bump_multiplicity(__i); } let __ret: [G; OUT_584] = unsafe { *(record.function_queries[584].output_at(__i).as_ptr() as *const [G; OUT_584]) }; __ret }, _ => aiur_fn_584(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_619] = { let __args: [G; IN_619] = [__v_2, __v_3, __v_4, __v_5, __v_1, __v_7, __v_8, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[619].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[619].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[619].bump_multiplicity(__i); } let __ret: [G; OUT_619] = unsafe { *(record.function_queries[619].output_at(__i).as_ptr() as *const [G; OUT_619]) }; __ret }, _ => aiur_fn_619(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_622] = { let __args: [G; IN_622] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[622].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[622].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[622].bump_multiplicity(__i); } let __ret: [G; OUT_622] = unsafe { *(record.function_queries[622].output_at(__i).as_ptr() as *const [G; OUT_622]) }; __ret }, _ => aiur_fn_622(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_289] = { let __args: [G; IN_289] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[289].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[289].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[289].bump_multiplicity(__i); } let __ret: [G; OUT_289] = unsafe { *(record.function_queries[289].output_at(__i).as_ptr() as *const [G; OUT_289]) }; __ret }, _ => aiur_fn_289(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_288] = { let __args: [G; IN_288] = [__v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[288].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[288].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[288].bump_multiplicity(__i); } let __ret: [G; OUT_288] = unsafe { *(record.function_queries[288].output_at(__i).as_ptr() as *const [G; OUT_288]) }; __ret }, _ => aiur_fn_288(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_19.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_20: G = __loaded[0]; @@ -59497,28 +59451,28 @@ fn aiur_fn_708( if (__v_6 != __v_23) { return Err(ExecError::AssertEqMismatch { lhs: __v_6.as_canonical_u64(), rhs: __v_23.as_canonical_u64(), msg: Some("ctor parameter count differs from its inductive's".to_string()) }); } - let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_22, __v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_601] = { let __args: [G; IN_601] = [__v_2, __v_6, __v_24, __v_7, __v_21, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[601].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[601].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[601].bump_multiplicity(__i); } let __ret: [G; OUT_601] = unsafe { *(record.function_queries[601].output_at(__i).as_ptr() as *const [G; OUT_601]) }; __ret }, _ => aiur_fn_601(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_602] = { let __args: [G; IN_602] = [__v_22, __v_2, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[602].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[602].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[602].bump_multiplicity(__i); } let __ret: [G; OUT_602] = unsafe { *(record.function_queries[602].output_at(__i).as_ptr() as *const [G; OUT_602]) }; __ret }, _ => aiur_fn_602(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_600] = { let __args: [G; IN_600] = [__v_2, __v_6, __v_24, __v_7, __v_21, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[600].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[600].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[600].bump_multiplicity(__i); } let __ret: [G; OUT_600] = unsafe { *(record.function_queries[600].output_at(__i).as_ptr() as *const [G; OUT_600]) }; __ret }, _ => aiur_fn_600(__args, record, io_buffer, __cu)? } }; let __v_32: G = (__v_23 + __v_24); let __v_33: G = G::from_u64(1); let __v_34: G = G::from_u64(1); let __v_35: G = { let __values: [G; 3] = [__v_33, __v_34, __v_34]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_604] = { let __args: [G; IN_604] = [__v_22, __v_32, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[604].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[604].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[604].bump_multiplicity(__i); } let __ret: [G; OUT_604] = unsafe { *(record.function_queries[604].output_at(__i).as_ptr() as *const [G; OUT_604]) }; __ret }, _ => aiur_fn_604(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_603] = { let __args: [G; IN_603] = [__v_22, __v_32, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[603].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[603].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[603].bump_multiplicity(__i); } let __ret: [G; OUT_603] = unsafe { *(record.function_queries[603].output_at(__i).as_ptr() as *const [G; OUT_603]) }; __ret }, _ => aiur_fn_603(__args, record, io_buffer, __cu)? } }; let __v_36: G = __r_arr[0]; - let __r_arr: [G; OUT_607] = { let __args: [G; IN_607] = [__v_2, __v_6, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[607].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[607].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[607].bump_multiplicity(__i); } let __ret: [G; OUT_607] = unsafe { *(record.function_queries[607].output_at(__i).as_ptr() as *const [G; OUT_607]) }; __ret }, _ => aiur_fn_607(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_606] = { let __args: [G; IN_606] = [__v_2, __v_6, __v_36]; let __cu = unconstrained; let __hit = record.function_queries[606].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[606].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[606].bump_multiplicity(__i); } let __ret: [G; OUT_606] = unsafe { *(record.function_queries[606].output_at(__i).as_ptr() as *const [G; OUT_606]) }; __ret }, _ => aiur_fn_606(__args, record, io_buffer, __cu)? } }; match __v_26.as_canonical_u64() { 0u64 => { let __v_37: G = G::from_u64(1); let __v_38: G = G::from_u64(1); let __v_39: G = { let __values: [G; 3] = [__v_37, __v_38, __v_38]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_619] = { let __args: [G; IN_619] = [__v_2, __v_6, __v_3, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[619].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[619].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[619].bump_multiplicity(__i); } let __ret: [G; OUT_619] = unsafe { *(record.function_queries[619].output_at(__i).as_ptr() as *const [G; OUT_619]) }; __ret }, _ => aiur_fn_619(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_618] = { let __args: [G; IN_618] = [__v_2, __v_6, __v_3, __v_39]; let __cu = unconstrained; let __hit = record.function_queries[618].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[618].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[618].bump_multiplicity(__i); } let __ret: [G; OUT_618] = unsafe { *(record.function_queries[618].output_at(__i).as_ptr() as *const [G; OUT_618]) }; __ret }, _ => aiur_fn_618(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59530,17 +59484,17 @@ fn aiur_fn_708( }, 7u64 => { let __v_14: G = G::from_u64(0); - let __r_arr: [G; OUT_591] = { let __args: [G; IN_591] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[591].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[591].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[591].bump_multiplicity(__i); } let __ret: [G; OUT_591] = unsafe { *(record.function_queries[591].output_at(__i).as_ptr() as *const [G; OUT_591]) }; __ret }, _ => aiur_fn_591(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_590] = { let __args: [G; IN_590] = [__v_2, __v_14, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[590].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[590].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[590].bump_multiplicity(__i); } let __ret: [G; OUT_590] = unsafe { *(record.function_queries[590].output_at(__i).as_ptr() as *const [G; OUT_590]) }; __ret }, _ => aiur_fn_590(__args, record, io_buffer, __cu)? } }; let __v_15: G = G::from_u64(1); let __v_16: G = G::from_u64(1); let __v_17: G = { let __values: [G; 3] = [__v_15, __v_16, __v_16]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_509] = { let __args: [G; IN_509] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[509].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[509].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[509].bump_multiplicity(__i); } let __ret: [G; OUT_509] = unsafe { *(record.function_queries[509].output_at(__i).as_ptr() as *const [G; OUT_509]) }; __ret }, _ => aiur_fn_509(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_508] = { let __args: [G; IN_508] = [__v_2, __v_17]; let __cu = unconstrained; let __hit = record.function_queries[508].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[508].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[508].bump_multiplicity(__i); } let __ret: [G; OUT_508] = unsafe { *(record.function_queries[508].output_at(__i).as_ptr() as *const [G; OUT_508]) }; __ret }, _ => aiur_fn_508(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; - let __r_arr: [G; OUT_588] = { let __args: [G; IN_588] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[588].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[588].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[588].bump_multiplicity(__i); } let __ret: [G; OUT_588] = unsafe { *(record.function_queries[588].output_at(__i).as_ptr() as *const [G; OUT_588]) }; __ret }, _ => aiur_fn_588(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_585] = { let __args: [G; IN_585] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[585].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[585].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[585].bump_multiplicity(__i); } let __ret: [G; OUT_585] = unsafe { *(record.function_queries[585].output_at(__i).as_ptr() as *const [G; OUT_585]) }; __ret }, _ => aiur_fn_585(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_703] = { let __args: [G; IN_703] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[703].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[703].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[703].bump_multiplicity(__i); } let __ret: [G; OUT_703] = unsafe { *(record.function_queries[703].output_at(__i).as_ptr() as *const [G; OUT_703]) }; __ret }, _ => aiur_fn_703(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_708] = []; - record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_587] = { let __args: [G; IN_587] = [__v_13, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[587].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[587].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[587].bump_multiplicity(__i); } let __ret: [G; OUT_587] = unsafe { *(record.function_queries[587].output_at(__i).as_ptr() as *const [G; OUT_587]) }; __ret }, _ => aiur_fn_587(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_584] = { let __args: [G; IN_584] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[584].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[584].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[584].bump_multiplicity(__i); } let __ret: [G; OUT_584] = unsafe { *(record.function_queries[584].output_at(__i).as_ptr() as *const [G; OUT_584]) }; __ret }, _ => aiur_fn_584(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_702] = { let __args: [G; IN_702] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[702].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[702].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[702].bump_multiplicity(__i); } let __ret: [G; OUT_702] = unsafe { *(record.function_queries[702].output_at(__i).as_ptr() as *const [G; OUT_702]) }; __ret }, _ => aiur_fn_702(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_707] = []; + record.function_queries[707].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -59550,18 +59504,18 @@ fn aiur_fn_708( }) } -const INPUT_SIZE_709: usize = 1; -const IN_709: usize = 1; -const OUT_709: usize = 0; -fn aiur_fn_709( - inp: [G; IN_709], +const INPUT_SIZE_708: usize = 1; +const IN_708: usize = 1; +const OUT_708: usize = 0; +fn aiur_fn_708( + inp: [G; IN_708], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_709], ExecError> { +) -> Result<[G; OUT_708], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_1.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_2: G = __loaded[0]; @@ -59576,22 +59530,22 @@ fn aiur_fn_709( let __v_11: G = __loaded[9]; let __v_12: G = __loaded[10]; let __v_13: G = __loaded[11]; - let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_709] = []; - record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_707] = { let __args: [G; IN_707] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_0]; let __cu = unconstrained; let __hit = record.function_queries[707].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[707].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[707].bump_multiplicity(__i); } let __ret: [G; OUT_707] = unsafe { *(record.function_queries[707].output_at(__i).as_ptr() as *const [G; OUT_707]) }; __ret }, _ => aiur_fn_707(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_708] = []; + record.function_queries[708].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_710: usize = 1; -const IN_710: usize = 1; -const OUT_710: usize = 1; -fn aiur_fn_710( - inp: [G; IN_710], +const INPUT_SIZE_709: usize = 1; +const IN_709: usize = 1; +const OUT_709: usize = 1; +fn aiur_fn_709( + inp: [G; IN_709], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_710], ExecError> { +) -> Result<[G; OUT_709], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 18] = { let __mq = record.memory_queries.get_mut(&18).ok_or(ExecError::InvalidMemorySize(18))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 18 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 18] = __args[..18].try_into().unwrap(); __arr }; @@ -59622,90 +59576,90 @@ fn aiur_fn_710( let __v_22: G = G::from_u64(1); let __v_23: G = { let __values: [G; 3] = [__v_21, __v_22, __v_22]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_24: G = { let __values: [G; 3] = [__v_19, __v_20, __v_23]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_710] = [__v_24]; - record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_709] = [__v_24]; + record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { let __v_19: G = G::from_u64(0); let __r_arr: [G; OUT_17] = { let __args: [G; IN_17] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[17].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[17].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[17].bump_multiplicity(__i); } let __ret: [G; OUT_17] = unsafe { *(record.function_queries[17].output_at(__i).as_ptr() as *const [G; OUT_17]) }; __ret }, _ => aiur_fn_17(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = { let __values: [G; 3] = [__v_19, __v_20, __v_21]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_710] = [__v_22]; - record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_709] = [__v_22]; + record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_710] = [__v_21]; - record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_709] = [__v_21]; + record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_710] = [__v_21]; - record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_709] = [__v_21]; + record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 9u64 => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_710] = [__v_21]; - record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_709] = [__v_21]; + record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 10u64 => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_19: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_20: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_19, __v_22]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_710] = [__v_23]; - record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_709] = [__v_23]; + record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_19: G = G::from_u64(1); let __v_20: G = G::from_u64(1); let __v_21: G = { let __values: [G; 3] = [__v_19, __v_20, __v_20]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_710] = [__v_21]; - record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_709] = [__v_21]; + record.function_queries[709].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_711: usize = 1; -const IN_711: usize = 1; -const OUT_711: usize = 1; -fn aiur_fn_711( - inp: [G; IN_711], +const INPUT_SIZE_710: usize = 1; +const IN_710: usize = 1; +const OUT_710: usize = 1; +fn aiur_fn_710( + inp: [G; IN_710], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_711], ExecError> { +) -> Result<[G; OUT_710], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -59717,19 +59671,19 @@ fn aiur_fn_711( let __v_4: G = G::from_u64(1); let __v_5: G = G::from_u64(1); let __v_6: G = { let __values: [G; 3] = [__v_4, __v_5, __v_5]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_711] = [__v_6]; - record.function_queries[711].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_710] = [__v_6]; + record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __r_arr: [G; OUT_711] = { let __args: [G; IN_711] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[711].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[711].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[711].bump_multiplicity(__i); } let __ret: [G; OUT_711] = unsafe { *(record.function_queries[711].output_at(__i).as_ptr() as *const [G; OUT_711]) }; __ret }, _ => aiur_fn_711(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_711] = [__v_6]; - record.function_queries[711].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_710] = [__v_6]; + record.function_queries[710].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -59739,15 +59693,15 @@ fn aiur_fn_711( }) } -const INPUT_SIZE_712: usize = 1; -const IN_712: usize = 1; -const OUT_712: usize = 1; -fn aiur_fn_712( - inp: [G; IN_712], +const INPUT_SIZE_711: usize = 1; +const IN_711: usize = 1; +const OUT_711: usize = 1; +fn aiur_fn_711( + inp: [G; IN_711], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_712], ExecError> { +) -> Result<[G; OUT_711], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 11] = { let __mq = record.memory_queries.get_mut(&11).ok_or(ExecError::InvalidMemorySize(11))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 11 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 11] = __args[..11].try_into().unwrap(); __arr }; @@ -59767,21 +59721,21 @@ fn aiur_fn_712( let __v_12: G = G::from_u64(1); let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 3] = [__v_12, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_712] = [__v_14]; - record.function_queries[712].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_711] = [__v_14]; + record.function_queries[711].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; - let __r_arr: [G; OUT_712] = { let __args: [G; IN_712] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[712].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[712].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[712].bump_multiplicity(__i); } let __ret: [G; OUT_712] = unsafe { *(record.function_queries[712].output_at(__i).as_ptr() as *const [G; OUT_712]) }; __ret }, _ => aiur_fn_712(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_711] = { let __args: [G; IN_711] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[711].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[711].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[711].bump_multiplicity(__i); } let __ret: [G; OUT_711] = unsafe { *(record.function_queries[711].output_at(__i).as_ptr() as *const [G; OUT_711]) }; __ret }, _ => aiur_fn_711(__args, record, io_buffer, __cu)? } }; let __v_13: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; - let __ret: [G; OUT_712] = [__v_14]; - record.function_queries[712].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_711] = [__v_14]; + record.function_queries[711].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59793,15 +59747,15 @@ fn aiur_fn_712( }) } -const INPUT_SIZE_713: usize = 1; -const IN_713: usize = 1; -const OUT_713: usize = 1; -fn aiur_fn_713( - inp: [G; IN_713], +const INPUT_SIZE_712: usize = 1; +const IN_712: usize = 1; +const OUT_712: usize = 1; +fn aiur_fn_712( + inp: [G; IN_712], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_713], ExecError> { +) -> Result<[G; OUT_712], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 36] = { let __mq = record.memory_queries.get_mut(&36).ok_or(ExecError::InvalidMemorySize(36))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 36 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 36] = __args[..36].try_into().unwrap(); __arr }; @@ -59846,21 +59800,21 @@ fn aiur_fn_713( let __v_37: G = G::from_u64(1); let __v_38: G = G::from_u64(1); let __v_39: G = { let __values: [G; 3] = [__v_37, __v_38, __v_38]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_713] = [__v_39]; - record.function_queries[713].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_712] = [__v_39]; + record.function_queries[712].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_35]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_35]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; - let __r_arr: [G; OUT_713] = { let __args: [G; IN_713] = [__v_36]; let __cu = unconstrained; let __hit = record.function_queries[713].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[713].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[713].bump_multiplicity(__i); } let __ret: [G; OUT_713] = unsafe { *(record.function_queries[713].output_at(__i).as_ptr() as *const [G; OUT_713]) }; __ret }, _ => aiur_fn_713(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_712] = { let __args: [G; IN_712] = [__v_36]; let __cu = unconstrained; let __hit = record.function_queries[712].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[712].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[712].bump_multiplicity(__i); } let __ret: [G; OUT_712] = unsafe { *(record.function_queries[712].output_at(__i).as_ptr() as *const [G; OUT_712]) }; __ret }, _ => aiur_fn_712(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_37, __v_38]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_39: G = __r_arr[0]; - let __ret: [G; OUT_713] = [__v_39]; - record.function_queries[713].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_712] = [__v_39]; + record.function_queries[712].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59872,15 +59826,15 @@ fn aiur_fn_713( }) } -const INPUT_SIZE_714: usize = 1; -const IN_714: usize = 1; -const OUT_714: usize = 1; -fn aiur_fn_714( - inp: [G; IN_714], +const INPUT_SIZE_713: usize = 1; +const IN_713: usize = 1; +const OUT_713: usize = 1; +fn aiur_fn_713( + inp: [G; IN_713], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_714], ExecError> { +) -> Result<[G; OUT_713], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 47] = { let __mq = record.memory_queries.get_mut(&47).ok_or(ExecError::InvalidMemorySize(47))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 47 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 47] = __args[..47].try_into().unwrap(); __arr }; @@ -59936,8 +59890,8 @@ fn aiur_fn_714( let __v_48: G = G::from_u64(1); let __v_49: G = G::from_u64(1); let __v_50: G = { let __values: [G; 3] = [__v_48, __v_49, __v_49]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_714] = [__v_50]; - record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_713] = [__v_50]; + record.function_queries[713].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -59945,18 +59899,18 @@ fn aiur_fn_714( 0u64 => { match __v_3.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_13]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_14]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __r_arr: [G; OUT_714] = { let __args: [G; IN_714] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[714].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[714].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[714].bump_multiplicity(__i); } let __ret: [G; OUT_714] = unsafe { *(record.function_queries[714].output_at(__i).as_ptr() as *const [G; OUT_714]) }; __ret }, _ => aiur_fn_714(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_713] = { let __args: [G; IN_713] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[713].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[713].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[713].bump_multiplicity(__i); } let __ret: [G; OUT_713] = unsafe { *(record.function_queries[713].output_at(__i).as_ptr() as *const [G; OUT_713]) }; __ret }, _ => aiur_fn_713(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_50, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_50, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __ret: [G; OUT_714] = [__v_52]; - record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_713] = [__v_52]; + record.function_queries[713].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59964,18 +59918,18 @@ fn aiur_fn_714( 1u64 => { match __v_3.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_28]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; - let __r_arr: [G; OUT_713] = { let __args: [G; IN_713] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[713].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[713].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[713].bump_multiplicity(__i); } let __ret: [G; OUT_713] = unsafe { *(record.function_queries[713].output_at(__i).as_ptr() as *const [G; OUT_713]) }; __ret }, _ => aiur_fn_713(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_712] = { let __args: [G; IN_712] = [__v_29]; let __cu = unconstrained; let __hit = record.function_queries[712].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[712].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[712].bump_multiplicity(__i); } let __ret: [G; OUT_712] = unsafe { *(record.function_queries[712].output_at(__i).as_ptr() as *const [G; OUT_712]) }; __ret }, _ => aiur_fn_712(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __r_arr: [G; OUT_714] = { let __args: [G; IN_714] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[714].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[714].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[714].bump_multiplicity(__i); } let __ret: [G; OUT_714] = unsafe { *(record.function_queries[714].output_at(__i).as_ptr() as *const [G; OUT_714]) }; __ret }, _ => aiur_fn_714(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_713] = { let __args: [G; IN_713] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[713].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[713].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[713].bump_multiplicity(__i); } let __ret: [G; OUT_713] = unsafe { *(record.function_queries[713].output_at(__i).as_ptr() as *const [G; OUT_713]) }; __ret }, _ => aiur_fn_713(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_50, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_50, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __ret: [G; OUT_714] = [__v_52]; - record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_713] = [__v_52]; + record.function_queries[713].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -59983,18 +59937,18 @@ fn aiur_fn_714( 2u64 => { match __v_3.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_45]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_45]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; - let __r_arr: [G; OUT_712] = { let __args: [G; IN_712] = [__v_46]; let __cu = unconstrained; let __hit = record.function_queries[712].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[712].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[712].bump_multiplicity(__i); } let __ret: [G; OUT_712] = unsafe { *(record.function_queries[712].output_at(__i).as_ptr() as *const [G; OUT_712]) }; __ret }, _ => aiur_fn_712(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_711] = { let __args: [G; IN_711] = [__v_46]; let __cu = unconstrained; let __hit = record.function_queries[711].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[711].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[711].bump_multiplicity(__i); } let __ret: [G; OUT_711] = unsafe { *(record.function_queries[711].output_at(__i).as_ptr() as *const [G; OUT_711]) }; __ret }, _ => aiur_fn_711(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __r_arr: [G; OUT_714] = { let __args: [G; IN_714] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[714].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[714].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[714].bump_multiplicity(__i); } let __ret: [G; OUT_714] = unsafe { *(record.function_queries[714].output_at(__i).as_ptr() as *const [G; OUT_714]) }; __ret }, _ => aiur_fn_714(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_713] = { let __args: [G; IN_713] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[713].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[713].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[713].bump_multiplicity(__i); } let __ret: [G; OUT_713] = unsafe { *(record.function_queries[713].output_at(__i).as_ptr() as *const [G; OUT_713]) }; __ret }, _ => aiur_fn_713(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_50, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_50, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __ret: [G; OUT_714] = [__v_52]; - record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_713] = [__v_52]; + record.function_queries[713].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -60011,15 +59965,15 @@ fn aiur_fn_714( }) } -const INPUT_SIZE_715: usize = 48; -const IN_715: usize = 48; -const OUT_715: usize = 1; -fn aiur_fn_715( - inp: [G; IN_715], +const INPUT_SIZE_714: usize = 48; +const IN_714: usize = 48; +const OUT_714: usize = 1; +fn aiur_fn_714( + inp: [G; IN_714], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_715], ExecError> { +) -> Result<[G; OUT_714], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60071,22 +60025,22 @@ fn aiur_fn_715( let __v_47: G = inp[47]; match __v_0.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_711] = { let __args: [G; IN_711] = [__v_45]; let __cu = unconstrained; let __hit = record.function_queries[711].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[711].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[711].bump_multiplicity(__i); } let __ret: [G; OUT_711] = unsafe { *(record.function_queries[711].output_at(__i).as_ptr() as *const [G; OUT_711]) }; __ret }, _ => aiur_fn_711(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_45]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; match __v_0.as_canonical_u64() { 0u64 => { match __v_1.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_12]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __ret: [G; OUT_715] = [__v_52]; - record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_714] = [__v_52]; + record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -60094,16 +60048,16 @@ fn aiur_fn_715( 1u64 => { match __v_1.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_43]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_712] = { let __args: [G; IN_712] = [__v_44]; let __cu = unconstrained; let __hit = record.function_queries[712].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[712].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[712].bump_multiplicity(__i); } let __ret: [G; OUT_712] = unsafe { *(record.function_queries[712].output_at(__i).as_ptr() as *const [G; OUT_712]) }; __ret }, _ => aiur_fn_712(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_711] = { let __args: [G; IN_711] = [__v_44]; let __cu = unconstrained; let __hit = record.function_queries[711].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[711].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[711].bump_multiplicity(__i); } let __ret: [G; OUT_711] = unsafe { *(record.function_queries[711].output_at(__i).as_ptr() as *const [G; OUT_711]) }; __ret }, _ => aiur_fn_711(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_52: G = __r_arr[0]; - let __ret: [G; OUT_715] = [__v_52]; - record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_714] = [__v_52]; + record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -60111,12 +60065,12 @@ fn aiur_fn_715( 2u64 => { match __v_1.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_715] = [__v_50]; - record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_714] = [__v_50]; + record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -60124,28 +60078,28 @@ fn aiur_fn_715( 3u64 => { match __v_1.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_710] = { let __args: [G; IN_710] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[710].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[710].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[710].bump_multiplicity(__i); } let __ret: [G; OUT_710] = unsafe { *(record.function_queries[710].output_at(__i).as_ptr() as *const [G; OUT_710]) }; __ret }, _ => aiur_fn_710(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_715] = [__v_50]; - record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_714] = [__v_50]; + record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }, 8u64 => { - let __r_arr: [G; OUT_714] = { let __args: [G; IN_714] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[714].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[714].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[714].bump_multiplicity(__i); } let __ret: [G; OUT_714] = unsafe { *(record.function_queries[714].output_at(__i).as_ptr() as *const [G; OUT_714]) }; __ret }, _ => aiur_fn_714(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_713] = { let __args: [G; IN_713] = [__v_1]; let __cu = unconstrained; let __hit = record.function_queries[713].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[713].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[713].bump_multiplicity(__i); } let __ret: [G; OUT_713] = unsafe { *(record.function_queries[713].output_at(__i).as_ptr() as *const [G; OUT_713]) }; __ret }, _ => aiur_fn_713(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; - let __ret: [G; OUT_715] = [__v_50]; - record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_714] = [__v_50]; + record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __ret: [G; OUT_715] = [__v_48]; - record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_714] = [__v_48]; + record.function_queries[714].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -60154,15 +60108,15 @@ fn aiur_fn_715( }) } -const INPUT_SIZE_716: usize = 2; -const IN_716: usize = 2; -const OUT_716: usize = 1; -fn aiur_fn_716( - inp: [G; IN_716], +const INPUT_SIZE_715: usize = 2; +const IN_715: usize = 2; +const OUT_715: usize = 1; +fn aiur_fn_715( + inp: [G; IN_715], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_716], ExecError> { +) -> Result<[G; OUT_715], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60173,8 +60127,8 @@ fn aiur_fn_716( match __v_2.as_canonical_u64() { 1u64 => { let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_716] = [__v_5]; - record.function_queries[716].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_715] = [__v_5]; + record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -60182,15 +60136,15 @@ fn aiur_fn_716( match __v_5.as_canonical_u64() { 0u64 => { let __v_6: G = G::from_u64(1); - let __ret: [G; OUT_716] = [__v_6]; - record.function_queries[716].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_715] = [__v_6]; + record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_715] = { let __args: [G; IN_715] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[715].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[715].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[715].bump_multiplicity(__i); } let __ret: [G; OUT_715] = unsafe { *(record.function_queries[715].output_at(__i).as_ptr() as *const [G; OUT_715]) }; __ret }, _ => aiur_fn_715(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; - let __ret: [G; OUT_716] = [__v_6]; - record.function_queries[716].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_715] = [__v_6]; + record.function_queries[715].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -60202,18 +60156,18 @@ fn aiur_fn_716( }) } -const INPUT_SIZE_717: usize = 1; -const IN_717: usize = 1; -const OUT_717: usize = 0; -fn aiur_fn_717( - inp: [G; IN_717], +const INPUT_SIZE_716: usize = 1; +const IN_716: usize = 1; +const OUT_716: usize = 0; +fn aiur_fn_716( + inp: [G; IN_716], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_717], ExecError> { +) -> Result<[G; OUT_716], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_1: G = __r_arr[0]; let __v_2: G = __r_arr[1]; let __v_3: G = __r_arr[2]; @@ -60267,14 +60221,14 @@ fn aiur_fn_717( let __mc_out___mc_0: [G; 0] = '__mc_0: { match __v_1.as_canonical_u64() { 8u64 => { let __v_49: G = G::from_u64(0); - let __r_arr: [G; OUT_719] = { let __args: [G; IN_719] = [__v_0, __v_2, __v_2, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[719].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[719].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[719].bump_multiplicity(__i); } let __ret: [G; OUT_719] = unsafe { *(record.function_queries[719].output_at(__i).as_ptr() as *const [G; OUT_719]) }; __ret }, _ => aiur_fn_719(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_718] = { let __args: [G; IN_718] = [__v_0, __v_2, __v_2, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[718].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[718].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[718].bump_multiplicity(__i); } let __ret: [G; OUT_718] = unsafe { *(record.function_queries[718].output_at(__i).as_ptr() as *const [G; OUT_718]) }; __ret }, _ => aiur_fn_718(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, 7u64 => { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, } @@ -60282,8 +60236,8 @@ fn aiur_fn_717( 6u64 => { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, } @@ -60291,8 +60245,8 @@ fn aiur_fn_717( 4u64 => { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_18]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, } @@ -60300,39 +60254,39 @@ fn aiur_fn_717( 5u64 => { match __v_2.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, } }, _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, } }; - let __r_arr: [G; OUT_715] = { let __args: [G; IN_715] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[715].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[715].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[715].bump_multiplicity(__i); } let __ret: [G; OUT_715] = unsafe { *(record.function_queries[715].output_at(__i).as_ptr() as *const [G; OUT_715]) }; __ret }, _ => aiur_fn_715(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_714] = { let __args: [G; IN_714] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[714].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[714].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[714].bump_multiplicity(__i); } let __ret: [G; OUT_714] = unsafe { *(record.function_queries[714].output_at(__i).as_ptr() as *const [G; OUT_714]) }; __ret }, _ => aiur_fn_714(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __v_50: G = G::from_u64(0); - let __r_arr: [G; OUT_718] = { let __args: [G; IN_718] = [__v_47, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[718].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[718].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[718].bump_multiplicity(__i); } let __ret: [G; OUT_718] = unsafe { *(record.function_queries[718].output_at(__i).as_ptr() as *const [G; OUT_718]) }; __ret }, _ => aiur_fn_718(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_717] = []; - record.function_queries[717].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_47, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_716] = []; + record.function_queries[716].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_718: usize = 3; -const IN_718: usize = 3; -const OUT_718: usize = 0; -fn aiur_fn_718( - inp: [G; IN_718], +const INPUT_SIZE_717: usize = 3; +const IN_717: usize = 3; +const OUT_717: usize = 0; +fn aiur_fn_717( + inp: [G; IN_717], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_718], ExecError> { +) -> Result<[G; OUT_717], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60343,16 +60297,16 @@ fn aiur_fn_718( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_718] = []; - record.function_queries[718].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_717] = []; + record.function_queries[717].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_715] = { let __args: [G; IN_715] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[715].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[715].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[715].bump_multiplicity(__i); } let __ret: [G; OUT_715] = unsafe { *(record.function_queries[715].output_at(__i).as_ptr() as *const [G; OUT_715]) }; __ret }, _ => aiur_fn_715(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __mc_out___mc_0: [G; 0] = '__mc_0: { match __v_6.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_4]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; break '__mc_0 []; }, _ => { @@ -60362,9 +60316,9 @@ fn aiur_fn_718( }; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_2 + __v_7); - let __r_arr: [G; OUT_718] = { let __args: [G; IN_718] = [__v_5, __v_1, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[718].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[718].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[718].bump_multiplicity(__i); } let __ret: [G; OUT_718] = unsafe { *(record.function_queries[718].output_at(__i).as_ptr() as *const [G; OUT_718]) }; __ret }, _ => aiur_fn_718(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_718] = []; - record.function_queries[718].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_5, __v_1, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_717] = []; + record.function_queries[717].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -60374,15 +60328,15 @@ fn aiur_fn_718( }) } -const INPUT_SIZE_719: usize = 4; -const IN_719: usize = 4; -const OUT_719: usize = 0; -fn aiur_fn_719( - inp: [G; IN_719], +const INPUT_SIZE_718: usize = 4; +const IN_718: usize = 4; +const OUT_718: usize = 0; +fn aiur_fn_718( + inp: [G; IN_718], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_719], ExecError> { +) -> Result<[G; OUT_718], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60438,17 +60392,17 @@ fn aiur_fn_719( let __v_50: G = __loaded[46]; match __v_4.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_719] = []; - record.function_queries[719].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_718] = []; + record.function_queries[718].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_720] = { let __args: [G; IN_720] = [__v_0, __v_1, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[720].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[720].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[720].bump_multiplicity(__i); } let __ret: [G; OUT_720] = unsafe { *(record.function_queries[720].output_at(__i).as_ptr() as *const [G; OUT_720]) }; __ret }, _ => aiur_fn_720(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_719] = { let __args: [G; IN_719] = [__v_0, __v_1, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[719].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[719].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[719].bump_multiplicity(__i); } let __ret: [G; OUT_719] = unsafe { *(record.function_queries[719].output_at(__i).as_ptr() as *const [G; OUT_719]) }; __ret }, _ => aiur_fn_719(__args, record, io_buffer, __cu)? } }; let __v_51: G = G::from_u64(1); let __v_52: G = (__v_3 + __v_51); - let __r_arr: [G; OUT_719] = { let __args: [G; IN_719] = [__v_0, __v_1, __v_50, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[719].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[719].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[719].bump_multiplicity(__i); } let __ret: [G; OUT_719] = unsafe { *(record.function_queries[719].output_at(__i).as_ptr() as *const [G; OUT_719]) }; __ret }, _ => aiur_fn_719(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_719] = []; - record.function_queries[719].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_718] = { let __args: [G; IN_718] = [__v_0, __v_1, __v_50, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[718].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[718].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[718].bump_multiplicity(__i); } let __ret: [G; OUT_718] = unsafe { *(record.function_queries[718].output_at(__i).as_ptr() as *const [G; OUT_718]) }; __ret }, _ => aiur_fn_718(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_718] = []; + record.function_queries[718].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -60458,15 +60412,15 @@ fn aiur_fn_719( }) } -const INPUT_SIZE_720: usize = 48; -const IN_720: usize = 48; -const OUT_720: usize = 0; -fn aiur_fn_720( - inp: [G; IN_720], +const INPUT_SIZE_719: usize = 48; +const IN_719: usize = 48; +const OUT_719: usize = 0; +fn aiur_fn_719( + inp: [G; IN_719], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_720], ExecError> { +) -> Result<[G; OUT_719], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60516,9 +60470,9 @@ fn aiur_fn_720( let __v_45: G = inp[45]; let __v_46: G = inp[46]; let __v_47: G = inp[47]; - let __r_arr: [G; OUT_294] = { let __args: [G; IN_294] = [__v_1, __v_0, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[294].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[294].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[294].bump_multiplicity(__i); } let __ret: [G; OUT_294] = unsafe { *(record.function_queries[294].output_at(__i).as_ptr() as *const [G; OUT_294]) }; __ret }, _ => aiur_fn_294(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_293] = { let __args: [G; IN_293] = [__v_1, __v_0, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[293].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[293].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[293].bump_multiplicity(__i); } let __ret: [G; OUT_293] = unsafe { *(record.function_queries[293].output_at(__i).as_ptr() as *const [G; OUT_293]) }; __ret }, _ => aiur_fn_293(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; - let __r_arr: [G; OUT_287] = { let __args: [G; IN_287] = [__v_48]; let __cu = unconstrained; let __hit = record.function_queries[287].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[287].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[287].bump_multiplicity(__i); } let __ret: [G; OUT_287] = unsafe { *(record.function_queries[287].output_at(__i).as_ptr() as *const [G; OUT_287]) }; __ret }, _ => aiur_fn_287(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_286] = { let __args: [G; IN_286] = [__v_48]; let __cu = unconstrained; let __hit = record.function_queries[286].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[286].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[286].bump_multiplicity(__i); } let __ret: [G; OUT_286] = unsafe { *(record.function_queries[286].output_at(__i).as_ptr() as *const [G; OUT_286]) }; __ret }, _ => aiur_fn_286(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __loaded: [G; 12] = { let __mq = record.memory_queries.get_mut(&12).ok_or(ExecError::InvalidMemorySize(12))?; let __ptr_u64 = __v_49.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 12 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 12] = __args[..12].try_into().unwrap(); __arr }; let __v_50: G = __loaded[0]; @@ -60533,22 +60487,22 @@ fn aiur_fn_720( let __v_59: G = __loaded[9]; let __v_60: G = __loaded[10]; let __v_61: G = __loaded[11]; - let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_720] = []; - record.function_queries[720].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_707] = { let __args: [G; IN_707] = [__v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[707].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[707].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[707].bump_multiplicity(__i); } let __ret: [G; OUT_707] = unsafe { *(record.function_queries[707].output_at(__i).as_ptr() as *const [G; OUT_707]) }; __ret }, _ => aiur_fn_707(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_719] = []; + record.function_queries[719].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_721: usize = 1; -const IN_721: usize = 1; -const OUT_721: usize = 1; -fn aiur_fn_721( - inp: [G; IN_721], +const INPUT_SIZE_720: usize = 1; +const IN_720: usize = 1; +const OUT_720: usize = 1; +fn aiur_fn_720( + inp: [G; IN_720], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_721], ExecError> { +) -> Result<[G; OUT_720], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(1); @@ -60561,21 +60515,21 @@ fn aiur_fn_721( let __v_7: G = { let __values: [G; 3] = [__v_5, __v_6, __v_4]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __r_arr: [G; OUT_22] = { let __args: [G; IN_22] = [__v_7]; let __cu = unconstrained; let __hit = record.function_queries[22].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[22].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[22].bump_multiplicity(__i); } let __ret: [G; OUT_22] = unsafe { *(record.function_queries[22].output_at(__i).as_ptr() as *const [G; OUT_22]) }; __ret }, _ => aiur_fn_22(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_721] = [__v_8]; - record.function_queries[721].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_720] = [__v_8]; + record.function_queries[720].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_722: usize = 2; -const IN_722: usize = 2; -const OUT_722: usize = 1; -fn aiur_fn_722( - inp: [G; IN_722], +const INPUT_SIZE_721: usize = 2; +const IN_721: usize = 2; +const OUT_721: usize = 1; +fn aiur_fn_721( + inp: [G; IN_721], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_722], ExecError> { +) -> Result<[G; OUT_721], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60591,21 +60545,21 @@ fn aiur_fn_722( let __v_9: G = { let __values: [G; 3] = [__v_7, __v_8, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __r_arr: [G; OUT_22] = { let __args: [G; IN_22] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[22].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[22].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[22].bump_multiplicity(__i); } let __ret: [G; OUT_22] = unsafe { *(record.function_queries[22].output_at(__i).as_ptr() as *const [G; OUT_22]) }; __ret }, _ => aiur_fn_22(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_722] = [__v_10]; - record.function_queries[722].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_721] = [__v_10]; + record.function_queries[721].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_723: usize = 1; -const IN_723: usize = 1; -const OUT_723: usize = 3; -fn aiur_fn_723( - inp: [G; IN_723], +const INPUT_SIZE_722: usize = 1; +const IN_722: usize = 1; +const OUT_722: usize = 3; +fn aiur_fn_722( + inp: [G; IN_722], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_723], ExecError> { +) -> Result<[G; OUT_722], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_74] = { let __args: [G; IN_74] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[74].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[74].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[74].bump_multiplicity(__i); } let __ret: [G; OUT_74] = unsafe { *(record.function_queries[74].output_at(__i).as_ptr() as *const [G; OUT_74]) }; __ret }, _ => aiur_fn_74(__args, record, io_buffer, __cu)? } }; @@ -60616,15 +60570,15 @@ fn aiur_fn_723( let __r_arr: [G; OUT_89] = { let __args: [G; IN_89] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[89].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[89].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[89].bump_multiplicity(__i); } let __ret: [G; OUT_89] = unsafe { *(record.function_queries[89].output_at(__i).as_ptr() as *const [G; OUT_89]) }; __ret }, _ => aiur_fn_89(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; - let __r_arr: [G; OUT_721] = { let __args: [G; IN_721] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[721].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[721].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[721].bump_multiplicity(__i); } let __ret: [G; OUT_721] = unsafe { *(record.function_queries[721].output_at(__i).as_ptr() as *const [G; OUT_721]) }; __ret }, _ => aiur_fn_721(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_720] = { let __args: [G; IN_720] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[720].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[720].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[720].bump_multiplicity(__i); } let __ret: [G; OUT_720] = unsafe { *(record.function_queries[720].output_at(__i).as_ptr() as *const [G; OUT_720]) }; __ret }, _ => aiur_fn_720(__args, record, io_buffer, __cu)? } }; let __v_5: G = __r_arr[0]; let __v_6: G = G::from_u64(0); let __v_7: G = G::from_u64(1); let __v_8: G = G::from_u64(1); let __v_9: G = { let __values: [G; 3] = [__v_7, __v_8, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_10: G = { let __values: [G; 3] = [__v_6, __v_3, __v_9]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_723] = [__v_5, __v_10, __v_4]; - record.function_queries[723].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_722] = [__v_5, __v_10, __v_4]; + record.function_queries[722].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -60664,25 +60618,25 @@ fn aiur_fn_723( let __v_36: G = G::from_u64(1); let __v_37: G = G::from_u64(1); let __v_38: G = { let __values: [G; 3] = [__v_36, __v_37, __v_37]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_723] = [__v_35, __v_38, __v_2]; - record.function_queries[723].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_722] = [__v_35, __v_38, __v_2]; + record.function_queries[722].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_723] = { let __args: [G; IN_723] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[723].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[723].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[723].bump_multiplicity(__i); } let __ret: [G; OUT_723] = unsafe { *(record.function_queries[723].output_at(__i).as_ptr() as *const [G; OUT_723]) }; __ret }, _ => aiur_fn_723(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_722] = { let __args: [G; IN_722] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[722].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[722].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[722].bump_multiplicity(__i); } let __ret: [G; OUT_722] = unsafe { *(record.function_queries[722].output_at(__i).as_ptr() as *const [G; OUT_722]) }; __ret }, _ => aiur_fn_722(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = __r_arr[2]; - let __r_arr: [G; OUT_723] = { let __args: [G; IN_723] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[723].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[723].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[723].bump_multiplicity(__i); } let __ret: [G; OUT_723] = unsafe { *(record.function_queries[723].output_at(__i).as_ptr() as *const [G; OUT_723]) }; __ret }, _ => aiur_fn_723(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_722] = { let __args: [G; IN_722] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[722].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[722].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[722].bump_multiplicity(__i); } let __ret: [G; OUT_722] = unsafe { *(record.function_queries[722].output_at(__i).as_ptr() as *const [G; OUT_722]) }; __ret }, _ => aiur_fn_722(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = __r_arr[1]; let __v_8: G = __r_arr[2]; - let __r_arr: [G; OUT_722] = { let __args: [G; IN_722] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[722].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[722].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[722].bump_multiplicity(__i); } let __ret: [G; OUT_722] = unsafe { *(record.function_queries[722].output_at(__i).as_ptr() as *const [G; OUT_722]) }; __ret }, _ => aiur_fn_722(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_721] = { let __args: [G; IN_721] = [__v_3, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[721].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[721].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[721].bump_multiplicity(__i); } let __ret: [G; OUT_721] = unsafe { *(record.function_queries[721].output_at(__i).as_ptr() as *const [G; OUT_721]) }; __ret }, _ => aiur_fn_721(__args, record, io_buffer, __cu)? } }; let __v_9: G = __r_arr[0]; - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; - let __ret: [G; OUT_723] = [__v_9, __v_10, __v_8]; - record.function_queries[723].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_722] = [__v_9, __v_10, __v_8]; + record.function_queries[722].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -60692,15 +60646,15 @@ fn aiur_fn_723( }) } -const INPUT_SIZE_724: usize = 1; -const IN_724: usize = 1; -const OUT_724: usize = 1; -fn aiur_fn_724( - inp: [G; IN_724], +const INPUT_SIZE_723: usize = 1; +const IN_723: usize = 1; +const OUT_723: usize = 1; +fn aiur_fn_723( + inp: [G; IN_723], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_724], ExecError> { +) -> Result<[G; OUT_723], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 32] = { let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 32 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 32] = __args[..32].try_into().unwrap(); __arr }; @@ -60762,7 +60716,7 @@ fn aiur_fn_724( if (__v_39 != __v_49) { return Err(ExecError::AssertEqMismatch { lhs: __v_39.as_canonical_u64(), rhs: __v_49.as_canonical_u64(), msg: Some("assumption tree: wrong tag4 variant".to_string()) }); } - let __r_arr: [G; OUT_723] = { let __args: [G; IN_723] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[723].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[723].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[723].bump_multiplicity(__i); } let __ret: [G; OUT_723] = unsafe { *(record.function_queries[723].output_at(__i).as_ptr() as *const [G; OUT_723]) }; __ret }, _ => aiur_fn_723(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_722] = { let __args: [G; IN_722] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[722].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[722].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[722].bump_multiplicity(__i); } let __ret: [G; OUT_722] = unsafe { *(record.function_queries[722].output_at(__i).as_ptr() as *const [G; OUT_722]) }; __ret }, _ => aiur_fn_722(__args, record, io_buffer, __cu)? } }; let __v_50: G = __r_arr[0]; let __v_51: G = __r_arr[1]; let __v_52: G = __r_arr[2]; @@ -60910,21 +60864,21 @@ fn aiur_fn_724( if (__v_89 != __v_32) { return Err(ExecError::AssertEqMismatch { lhs: __v_89.as_canonical_u64(), rhs: __v_32.as_canonical_u64(), msg: Some("assumption tree: recomputed merkle root != requested root".to_string()) }); } - let __ret: [G; OUT_724] = [__v_51]; - record.function_queries[724].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_723] = [__v_51]; + record.function_queries[723].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_725: usize = 7; -const IN_725: usize = 7; -const OUT_725: usize = 6; -fn aiur_fn_725( - inp: [G; IN_725], +const INPUT_SIZE_724: usize = 7; +const IN_724: usize = 7; +const OUT_724: usize = 6; +fn aiur_fn_724( + inp: [G; IN_724], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_725], ExecError> { +) -> Result<[G; OUT_724], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60939,28 +60893,28 @@ fn aiur_fn_725( let __v_9: G = __loaded[2]; match __v_7.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_725] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; - record.function_queries[725].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_724] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; + record.function_queries[724].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_10: G = G::from_u64(1); - let __r_arr: [G; OUT_788] = { let __args: [G; IN_788] = [__v_8, __v_10, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[788].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[788].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[788].bump_multiplicity(__i); } let __ret: [G; OUT_788] = unsafe { *(record.function_queries[788].output_at(__i).as_ptr() as *const [G; OUT_788]) }; __ret }, _ => aiur_fn_788(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_787] = { let __args: [G; IN_787] = [__v_8, __v_10, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[787].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[787].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[787].bump_multiplicity(__i); } let __ret: [G; OUT_787] = unsafe { *(record.function_queries[787].output_at(__i).as_ptr() as *const [G; OUT_787]) }; __ret }, _ => aiur_fn_787(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; let __v_14: G = __r_arr[3]; let __v_15: G = __r_arr[4]; let __v_16: G = __r_arr[5]; - let __r_arr: [G; OUT_725] = { let __args: [G; IN_725] = [__v_9, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[725].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[725].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[725].bump_multiplicity(__i); } let __ret: [G; OUT_725] = unsafe { *(record.function_queries[725].output_at(__i).as_ptr() as *const [G; OUT_725]) }; __ret }, _ => aiur_fn_725(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_9, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; let __v_17: G = __r_arr[0]; let __v_18: G = __r_arr[1]; let __v_19: G = __r_arr[2]; let __v_20: G = __r_arr[3]; let __v_21: G = __r_arr[4]; let __v_22: G = __r_arr[5]; - let __ret: [G; OUT_725] = [__v_17, __v_18, __v_19, __v_20, __v_21, __v_22]; - record.function_queries[725].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_724] = [__v_17, __v_18, __v_19, __v_20, __v_21, __v_22]; + record.function_queries[724].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -60970,15 +60924,15 @@ fn aiur_fn_725( }) } -const INPUT_SIZE_726: usize = 7; -const IN_726: usize = 7; -const OUT_726: usize = 1; -fn aiur_fn_726( - inp: [G; IN_726], +const INPUT_SIZE_725: usize = 7; +const IN_725: usize = 7; +const OUT_725: usize = 1; +fn aiur_fn_725( + inp: [G; IN_725], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_726], ExecError> { +) -> Result<[G; OUT_725], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -60988,23 +60942,23 @@ fn aiur_fn_726( let __v_5: G = inp[5]; let __v_6: G = inp[6]; let __v_7: G = G::from_u64(0); - let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_771] = { let __args: [G; IN_771] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[771].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[771].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[771].bump_multiplicity(__i); } let __ret: [G; OUT_771] = unsafe { *(record.function_queries[771].output_at(__i).as_ptr() as *const [G; OUT_771]) }; __ret }, _ => aiur_fn_771(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; - let __ret: [G; OUT_726] = [__v_8]; - record.function_queries[726].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_725] = [__v_8]; + record.function_queries[725].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_727: usize = 14; -const IN_727: usize = 14; -const OUT_727: usize = 0; -fn aiur_fn_727( - inp: [G; IN_727], +const INPUT_SIZE_726: usize = 14; +const IN_726: usize = 14; +const OUT_726: usize = 0; +fn aiur_fn_726( + inp: [G; IN_726], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_727], ExecError> { +) -> Result<[G; OUT_726], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61020,18 +60974,18 @@ fn aiur_fn_727( let __v_11: G = inp[11]; let __v_12: G = inp[12]; let __v_13: G = inp[13]; - let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_0, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_725] = { let __args: [G; IN_725] = [__v_0, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[725].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[725].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[725].bump_multiplicity(__i); } let __ret: [G; OUT_725] = unsafe { *(record.function_queries[725].output_at(__i).as_ptr() as *const [G; OUT_725]) }; __ret }, _ => aiur_fn_725(__args, record, io_buffer, __cu)? } }; let __v_14: G = __r_arr[0]; match __v_14.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_727] = []; - record.function_queries[727].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_726] = []; + record.function_queries[726].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __mc_out___mc_0: [G; 0] = '__mc_0: { match __v_13.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_725] = { let __args: [G; IN_725] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[725].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[725].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[725].bump_multiplicity(__i); } let __ret: [G; OUT_725] = unsafe { *(record.function_queries[725].output_at(__i).as_ptr() as *const [G; OUT_725]) }; __ret }, _ => aiur_fn_725(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = G::from_u64(1); if (__v_15 != __v_16) { @@ -61044,7 +60998,7 @@ fn aiur_fn_727( }, } }; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; let __v_17: G = __r_arr[2]; @@ -61098,14 +61052,14 @@ fn aiur_fn_727( let __mc_out___mc_1: [G; 0] = '__mc_1: { match __v_15.as_canonical_u64() { 8u64 => { let __v_63: G = G::from_u64(0); - let __r_arr: [G; OUT_719] = { let __args: [G; IN_719] = [__v_0, __v_16, __v_16, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[719].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[719].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[719].bump_multiplicity(__i); } let __ret: [G; OUT_719] = unsafe { *(record.function_queries[719].output_at(__i).as_ptr() as *const [G; OUT_719]) }; __ret }, _ => aiur_fn_719(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_718] = { let __args: [G; IN_718] = [__v_0, __v_16, __v_16, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[718].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[718].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[718].bump_multiplicity(__i); } let __ret: [G; OUT_718] = unsafe { *(record.function_queries[718].output_at(__i).as_ptr() as *const [G; OUT_718]) }; __ret }, _ => aiur_fn_718(__args, record, io_buffer, __cu)? } }; break '__mc_1 []; }, 7u64 => { match __v_16.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_24, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_24, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; break '__mc_1 []; }, } @@ -61113,8 +61067,8 @@ fn aiur_fn_727( 6u64 => { match __v_16.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_24, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_24, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; break '__mc_1 []; }, } @@ -61122,8 +61076,8 @@ fn aiur_fn_727( 4u64 => { match __v_16.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_32, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_32, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; break '__mc_1 []; }, } @@ -61131,24 +61085,24 @@ fn aiur_fn_727( 5u64 => { match __v_16.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_24, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_24, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; break '__mc_1 []; }, } }, _ => { - let __r_arr: [G; OUT_709] = { let __args: [G; IN_709] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[709].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[709].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[709].bump_multiplicity(__i); } let __ret: [G; OUT_709] = unsafe { *(record.function_queries[709].output_at(__i).as_ptr() as *const [G; OUT_709]) }; __ret }, _ => aiur_fn_709(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_708] = { let __args: [G; IN_708] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[708].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[708].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[708].bump_multiplicity(__i); } let __ret: [G; OUT_708] = unsafe { *(record.function_queries[708].output_at(__i).as_ptr() as *const [G; OUT_708]) }; __ret }, _ => aiur_fn_708(__args, record, io_buffer, __cu)? } }; break '__mc_1 []; }, } }; - let __r_arr: [G; OUT_715] = { let __args: [G; IN_715] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62]; let __cu = unconstrained; let __hit = record.function_queries[715].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[715].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[715].bump_multiplicity(__i); } let __ret: [G; OUT_715] = unsafe { *(record.function_queries[715].output_at(__i).as_ptr() as *const [G; OUT_715]) }; __ret }, _ => aiur_fn_715(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_714] = { let __args: [G; IN_714] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62]; let __cu = unconstrained; let __hit = record.function_queries[714].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[714].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[714].bump_multiplicity(__i); } let __ret: [G; OUT_714] = unsafe { *(record.function_queries[714].output_at(__i).as_ptr() as *const [G; OUT_714]) }; __ret }, _ => aiur_fn_714(__args, record, io_buffer, __cu)? } }; let __v_63: G = __r_arr[0]; let __v_64: G = G::from_u64(0); - let __r_arr: [G; OUT_728] = { let __args: [G; IN_728] = [__v_61, __v_63, __v_64, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[728].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[728].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[728].bump_multiplicity(__i); } let __ret: [G; OUT_728] = unsafe { *(record.function_queries[728].output_at(__i).as_ptr() as *const [G; OUT_728]) }; __ret }, _ => aiur_fn_728(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_727] = []; - record.function_queries[727].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_61, __v_63, __v_64, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_726] = []; + record.function_queries[726].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -61157,8 +61111,71 @@ fn aiur_fn_727( }) } -const INPUT_SIZE_728: usize = 16; -const IN_728: usize = 16; +const INPUT_SIZE_727: usize = 16; +const IN_727: usize = 16; +const OUT_727: usize = 0; +fn aiur_fn_727( + inp: [G; IN_727], + record: &mut QueryRecord, + io_buffer: &mut IOBuffer, + unconstrained: bool, +) -> Result<[G; OUT_727], ExecError> { + stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { + let __v_0: G = inp[0]; + let __v_1: G = inp[1]; + let __v_2: G = inp[2]; + let __v_3: G = inp[3]; + let __v_4: G = inp[4]; + let __v_5: G = inp[5]; + let __v_6: G = inp[6]; + let __v_7: G = inp[7]; + let __v_8: G = inp[8]; + let __v_9: G = inp[9]; + let __v_10: G = inp[10]; + let __v_11: G = inp[11]; + let __v_12: G = inp[12]; + let __v_13: G = inp[13]; + let __v_14: G = inp[14]; + let __v_15: G = inp[15]; + let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; + let __v_16: G = __loaded[0]; + let __v_17: G = __loaded[1]; + let __v_18: G = __loaded[2]; + match __v_16.as_canonical_u64() { + 1u64 => { + let __ret: [G; OUT_727] = []; + record.function_queries[727].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + 0u64 => { + let __r_arr: [G; OUT_715] = { let __args: [G; IN_715] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[715].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[715].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[715].bump_multiplicity(__i); } let __ret: [G; OUT_715] = unsafe { *(record.function_queries[715].output_at(__i).as_ptr() as *const [G; OUT_715]) }; __ret }, _ => aiur_fn_715(__args, record, io_buffer, __cu)? } }; + let __v_19: G = __r_arr[0]; + let __mc_out___mc_0: [G; 0] = '__mc_0: { match __v_19.as_canonical_u64() { + 1u64 => { + let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_17, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; + break '__mc_0 []; + }, + _ => { + break '__mc_0 []; + }, +} + }; + let __v_20: G = G::from_u64(1); + let __v_21: G = (__v_2 + __v_20); + let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_18, __v_1, __v_21, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_727] = []; + record.function_queries[727].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + _ => { + return Err(ExecError::MatchNoCase(__v_16.as_canonical_u64())); + }, + } + }) +} + +const INPUT_SIZE_728: usize = 13; +const IN_728: usize = 13; const OUT_728: usize = 0; fn aiur_fn_728( inp: [G; IN_728], @@ -61180,48 +61197,33 @@ fn aiur_fn_728( let __v_10: G = inp[10]; let __v_11: G = inp[11]; let __v_12: G = inp[12]; - let __v_13: G = inp[13]; - let __v_14: G = inp[14]; - let __v_15: G = inp[15]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; - let __v_16: G = __loaded[0]; - let __v_17: G = __loaded[1]; - let __v_18: G = __loaded[2]; - match __v_16.as_canonical_u64() { + let __v_13: G = __loaded[0]; + let __v_14: G = __loaded[1]; + let __v_15: G = __loaded[2]; + match __v_13.as_canonical_u64() { 1u64 => { let __ret: [G; OUT_728] = []; record.function_queries[728].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; - let __v_19: G = __r_arr[0]; - let __mc_out___mc_0: [G; 0] = '__mc_0: { match __v_19.as_canonical_u64() { - 1u64 => { - let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_17, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; - break '__mc_0 []; - }, - _ => { - break '__mc_0 []; - }, -} - }; - let __v_20: G = G::from_u64(1); - let __v_21: G = (__v_2 + __v_20); - let __r_arr: [G; OUT_728] = { let __args: [G; IN_728] = [__v_18, __v_1, __v_21, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15]; let __cu = unconstrained; let __hit = record.function_queries[728].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[728].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[728].bump_multiplicity(__i); } let __ret: [G; OUT_728] = unsafe { *(record.function_queries[728].output_at(__i).as_ptr() as *const [G; OUT_728]) }; __ret }, _ => aiur_fn_728(__args, record, io_buffer, __cu)? } }; + let __v_16: G = G::from_u64(1); + let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_14, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_728] = { let __args: [G; IN_728] = [__v_15, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[728].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[728].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[728].bump_multiplicity(__i); } let __ret: [G; OUT_728] = unsafe { *(record.function_queries[728].output_at(__i).as_ptr() as *const [G; OUT_728]) }; __ret }, _ => aiur_fn_728(__args, record, io_buffer, __cu)? } }; let __ret: [G; OUT_728] = []; record.function_queries[728].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - return Err(ExecError::MatchNoCase(__v_16.as_canonical_u64())); + return Err(ExecError::MatchNoCase(__v_13.as_canonical_u64())); }, } }) } -const INPUT_SIZE_729: usize = 13; -const IN_729: usize = 13; +const INPUT_SIZE_729: usize = 3; +const IN_729: usize = 3; const OUT_729: usize = 0; fn aiur_fn_729( inp: [G; IN_729], @@ -61233,55 +61235,7 @@ fn aiur_fn_729( let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __v_3: G = inp[3]; - let __v_4: G = inp[4]; - let __v_5: G = inp[5]; - let __v_6: G = inp[6]; - let __v_7: G = inp[7]; - let __v_8: G = inp[8]; - let __v_9: G = inp[9]; - let __v_10: G = inp[10]; - let __v_11: G = inp[11]; - let __v_12: G = inp[12]; - let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; - let __v_13: G = __loaded[0]; - let __v_14: G = __loaded[1]; - let __v_15: G = __loaded[2]; - match __v_13.as_canonical_u64() { - 1u64 => { - let __ret: [G; OUT_729] = []; - record.function_queries[729].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - 0u64 => { - let __v_16: G = G::from_u64(1); - let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_14, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_729] = { let __args: [G; IN_729] = [__v_15, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[729].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[729].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[729].bump_multiplicity(__i); } let __ret: [G; OUT_729] = unsafe { *(record.function_queries[729].output_at(__i).as_ptr() as *const [G; OUT_729]) }; __ret }, _ => aiur_fn_729(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_729] = []; - record.function_queries[729].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - _ => { - return Err(ExecError::MatchNoCase(__v_13.as_canonical_u64())); - }, - } - }) -} - -const INPUT_SIZE_730: usize = 3; -const IN_730: usize = 3; -const OUT_730: usize = 0; -fn aiur_fn_730( - inp: [G; IN_730], - record: &mut QueryRecord, - io_buffer: &mut IOBuffer, - unconstrained: bool, -) -> Result<[G; OUT_730], ExecError> { - stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = inp[0]; - let __v_1: G = inp[1]; - let __v_2: G = inp[2]; - let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_723] = { let __args: [G; IN_723] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[723].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[723].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[723].bump_multiplicity(__i); } let __ret: [G; OUT_723] = unsafe { *(record.function_queries[723].output_at(__i).as_ptr() as *const [G; OUT_723]) }; __ret }, _ => aiur_fn_723(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __mc_out___mc_0: [G; 1] = '__mc_0: { match __v_1.as_canonical_u64() { 1u64 => { @@ -61291,7 +61245,7 @@ fn aiur_fn_730( break '__mc_0 [__v_6]; }, 0u64 => { - let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_723] = { let __args: [G; IN_723] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[723].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[723].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[723].bump_multiplicity(__i); } let __ret: [G; OUT_723] = unsafe { *(record.function_queries[723].output_at(__i).as_ptr() as *const [G; OUT_723]) }; __ret }, _ => aiur_fn_723(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; break '__mc_0 [__v_4]; }, @@ -61303,7 +61257,7 @@ fn aiur_fn_730( let __v_4: G = __mc_out___mc_0[0]; let __v_5: G = G::from_u64(1); let __v_6: G = G::from_u64(1); - let __r_arr: [G; OUT_725] = { let __args: [G; IN_725] = [__v_3, __v_5, __v_6, __v_6, __v_6, __v_6, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[725].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[725].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[725].bump_multiplicity(__i); } let __ret: [G; OUT_725] = unsafe { *(record.function_queries[725].output_at(__i).as_ptr() as *const [G; OUT_725]) }; __ret }, _ => aiur_fn_725(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_3, __v_5, __v_6, __v_6, __v_6, __v_6, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = __r_arr[1]; let __v_9: G = __r_arr[2]; @@ -61312,29 +61266,29 @@ fn aiur_fn_730( let __v_12: G = __r_arr[5]; let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(1); - let __r_arr: [G; OUT_725] = { let __args: [G; IN_725] = [__v_4, __v_13, __v_14, __v_14, __v_14, __v_14, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[725].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[725].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[725].bump_multiplicity(__i); } let __ret: [G; OUT_725] = unsafe { *(record.function_queries[725].output_at(__i).as_ptr() as *const [G; OUT_725]) }; __ret }, _ => aiur_fn_725(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_4, __v_13, __v_14, __v_14, __v_14, __v_14, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; let __v_17: G = __r_arr[2]; let __v_18: G = __r_arr[3]; let __v_19: G = __r_arr[4]; let __v_20: G = __r_arr[5]; - let __r_arr: [G; OUT_729] = { let __args: [G; IN_729] = [__v_3, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[729].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[729].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[729].bump_multiplicity(__i); } let __ret: [G; OUT_729] = unsafe { *(record.function_queries[729].output_at(__i).as_ptr() as *const [G; OUT_729]) }; __ret }, _ => aiur_fn_729(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_730] = []; - record.function_queries[730].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_728] = { let __args: [G; IN_728] = [__v_3, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[728].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[728].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[728].bump_multiplicity(__i); } let __ret: [G; OUT_728] = unsafe { *(record.function_queries[728].output_at(__i).as_ptr() as *const [G; OUT_728]) }; __ret }, _ => aiur_fn_728(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_729] = []; + record.function_queries[729].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_731: usize = 1; -const IN_731: usize = 1; -const OUT_731: usize = 3; -fn aiur_fn_731( - inp: [G; IN_731], +const INPUT_SIZE_730: usize = 1; +const IN_730: usize = 1; +const OUT_730: usize = 3; +fn aiur_fn_730( + inp: [G; IN_730], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_731], ExecError> { +) -> Result<[G; OUT_730], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_74] = { let __args: [G; IN_74] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[74].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[74].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[74].bump_multiplicity(__i); } let __ret: [G; OUT_74] = unsafe { *(record.function_queries[74].output_at(__i).as_ptr() as *const [G; OUT_74]) }; __ret }, _ => aiur_fn_74(__args, record, io_buffer, __cu)? } }; @@ -61344,8 +61298,8 @@ fn aiur_fn_731( 0u64 => { let __v_3: G = G::from_u64(1); let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_731] = [__v_3, __v_4, __v_2]; - record.function_queries[731].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_730] = [__v_3, __v_4, __v_2]; + record.function_queries[730].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { @@ -61353,8 +61307,8 @@ fn aiur_fn_731( let __v_3: G = __r_arr[0]; let __v_4: G = __r_arr[1]; let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_731] = [__v_5, __v_3, __v_4]; - record.function_queries[731].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_730] = [__v_5, __v_3, __v_4]; + record.function_queries[730].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61364,15 +61318,15 @@ fn aiur_fn_731( }) } -const INPUT_SIZE_732: usize = 2; -const IN_732: usize = 2; -const OUT_732: usize = 10; -fn aiur_fn_732( - inp: [G; IN_732], +const INPUT_SIZE_731: usize = 2; +const IN_731: usize = 2; +const OUT_731: usize = 10; +fn aiur_fn_731( + inp: [G; IN_731], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_732], ExecError> { +) -> Result<[G; OUT_731], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61380,8 +61334,8 @@ fn aiur_fn_732( 0u64 => { let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_732] = [__v_2, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_1]; - record.function_queries[732].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_731] = [__v_2, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_3, __v_1]; + record.function_queries[731].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61396,23 +61350,23 @@ fn aiur_fn_732( let __v_9: G = __r_arr[7]; let __v_10: G = __r_arr[8]; let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_732] = [__v_11, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; - record.function_queries[732].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_731] = [__v_11, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; + record.function_queries[731].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_733: usize = 2; -const IN_733: usize = 2; -const OUT_733: usize = 3; -fn aiur_fn_733( - inp: [G; IN_733], +const INPUT_SIZE_732: usize = 2; +const IN_732: usize = 2; +const OUT_732: usize = 3; +fn aiur_fn_732( + inp: [G; IN_732], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_733], ExecError> { +) -> Result<[G; OUT_732], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61420,8 +61374,8 @@ fn aiur_fn_733( 0u64 => { let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_733] = [__v_2, __v_3, __v_1]; - record.function_queries[733].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_732] = [__v_2, __v_3, __v_1]; + record.function_queries[732].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61429,23 +61383,23 @@ fn aiur_fn_733( let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_733] = [__v_4, __v_2, __v_3]; - record.function_queries[733].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_732] = [__v_4, __v_2, __v_3]; + record.function_queries[732].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_734: usize = 2; -const IN_734: usize = 2; -const OUT_734: usize = 3; -fn aiur_fn_734( - inp: [G; IN_734], +const INPUT_SIZE_733: usize = 2; +const IN_733: usize = 2; +const OUT_733: usize = 3; +fn aiur_fn_733( + inp: [G; IN_733], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_734], ExecError> { +) -> Result<[G; OUT_733], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61453,8 +61407,8 @@ fn aiur_fn_734( 0u64 => { let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_734] = [__v_2, __v_3, __v_1]; - record.function_queries[734].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_733] = [__v_2, __v_3, __v_1]; + record.function_queries[733].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61462,23 +61416,23 @@ fn aiur_fn_734( let __v_2: G = __r_arr[0]; let __v_3: G = __r_arr[1]; let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_734] = [__v_4, __v_2, __v_3]; - record.function_queries[734].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_733] = [__v_4, __v_2, __v_3]; + record.function_queries[733].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_735: usize = 2; -const IN_735: usize = 2; -const OUT_735: usize = 3; -fn aiur_fn_735( - inp: [G; IN_735], +const INPUT_SIZE_734: usize = 2; +const IN_734: usize = 2; +const OUT_734: usize = 3; +fn aiur_fn_734( + inp: [G; IN_734], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_735], ExecError> { +) -> Result<[G; OUT_734], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61486,8 +61440,8 @@ fn aiur_fn_735( 0u64 => { let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_735] = [__v_2, __v_3, __v_1]; - record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_734] = [__v_2, __v_3, __v_1]; + record.function_queries[734].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61498,22 +61452,22 @@ fn aiur_fn_735( 0u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_735] = [__v_4, __v_5, __v_3]; - record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_734] = [__v_4, __v_5, __v_3]; + record.function_queries[734].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_735] = [__v_4, __v_5, __v_3]; - record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_734] = [__v_4, __v_5, __v_3]; + record.function_queries[734].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(2); - let __ret: [G; OUT_735] = [__v_4, __v_5, __v_3]; - record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_734] = [__v_4, __v_5, __v_3]; + record.function_queries[734].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61525,15 +61479,15 @@ fn aiur_fn_735( }) } -const INPUT_SIZE_736: usize = 2; -const IN_736: usize = 2; -const OUT_736: usize = 3; -fn aiur_fn_736( - inp: [G; IN_736], +const INPUT_SIZE_735: usize = 2; +const IN_735: usize = 2; +const OUT_735: usize = 3; +fn aiur_fn_735( + inp: [G; IN_735], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_736], ExecError> { +) -> Result<[G; OUT_735], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61541,8 +61495,8 @@ fn aiur_fn_736( 0u64 => { let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_736] = [__v_2, __v_3, __v_1]; - record.function_queries[736].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_735] = [__v_2, __v_3, __v_1]; + record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61553,29 +61507,29 @@ fn aiur_fn_736( 0u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(0); - let __ret: [G; OUT_736] = [__v_4, __v_5, __v_3]; - record.function_queries[736].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_735] = [__v_4, __v_5, __v_3]; + record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(1); - let __ret: [G; OUT_736] = [__v_4, __v_5, __v_3]; - record.function_queries[736].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_735] = [__v_4, __v_5, __v_3]; + record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(2); - let __ret: [G; OUT_736] = [__v_4, __v_5, __v_3]; - record.function_queries[736].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_735] = [__v_4, __v_5, __v_3]; + record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { let __v_4: G = G::from_u64(0); let __v_5: G = G::from_u64(3); - let __ret: [G; OUT_736] = [__v_4, __v_5, __v_3]; - record.function_queries[736].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_735] = [__v_4, __v_5, __v_3]; + record.function_queries[735].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61587,15 +61541,15 @@ fn aiur_fn_736( }) } -const INPUT_SIZE_737: usize = 9; -const IN_737: usize = 9; -const OUT_737: usize = 2; -fn aiur_fn_737( - inp: [G; IN_737], +const INPUT_SIZE_736: usize = 9; +const IN_736: usize = 9; +const OUT_736: usize = 2; +fn aiur_fn_736( + inp: [G; IN_736], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_737], ExecError> { +) -> Result<[G; OUT_736], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61613,8 +61567,8 @@ fn aiur_fn_737( let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 19] = [__v_10, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&19).ok_or(ExecError::InvalidMemorySize(19))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_737] = [__v_12, __v_0]; - record.function_queries[737].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_736] = [__v_12, __v_0]; + record.function_queries[736].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61646,28 +61600,28 @@ fn aiur_fn_737( let __v_33: G = __r_arr[5]; let __v_34: G = __r_arr[6]; let __v_35: G = __r_arr[7]; - let __r_arr: [G; OUT_737] = { let __args: [G; IN_737] = [__v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[737].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[737].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[737].bump_multiplicity(__i); } let __ret: [G; OUT_737] = unsafe { *(record.function_queries[737].output_at(__i).as_ptr() as *const [G; OUT_737]) }; __ret }, _ => aiur_fn_737(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_736] = { let __args: [G; IN_736] = [__v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[736].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[736].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[736].bump_multiplicity(__i); } let __ret: [G; OUT_736] = unsafe { *(record.function_queries[736].output_at(__i).as_ptr() as *const [G; OUT_736]) }; __ret }, _ => aiur_fn_736(__args, record, io_buffer, __cu)? } }; let __v_36: G = __r_arr[0]; let __v_37: G = __r_arr[1]; let __v_38: G = G::from_u64(0); let __v_39: G = { let __values: [G; 19] = [__v_38, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_36]; let __mq = record.memory_queries.get_mut(&19).ok_or(ExecError::InvalidMemorySize(19))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_737] = [__v_39, __v_37]; - record.function_queries[737].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_736] = [__v_39, __v_37]; + record.function_queries[736].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_738: usize = 2; -const IN_738: usize = 2; -const OUT_738: usize = 3; -fn aiur_fn_738( - inp: [G; IN_738], +const INPUT_SIZE_737: usize = 2; +const IN_737: usize = 2; +const OUT_737: usize = 3; +fn aiur_fn_737( + inp: [G; IN_737], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_738], ExecError> { +) -> Result<[G; OUT_737], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61675,8 +61629,8 @@ fn aiur_fn_738( 0u64 => { let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_738] = [__v_2, __v_3, __v_1]; - record.function_queries[738].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_737] = [__v_2, __v_3, __v_1]; + record.function_queries[737].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61690,27 +61644,27 @@ fn aiur_fn_738( let __v_8: G = __r_arr[6]; let __v_9: G = __r_arr[7]; let __v_10: G = __r_arr[8]; - let __r_arr: [G; OUT_737] = { let __args: [G; IN_737] = [__v_10, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[737].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[737].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[737].bump_multiplicity(__i); } let __ret: [G; OUT_737] = unsafe { *(record.function_queries[737].output_at(__i).as_ptr() as *const [G; OUT_737]) }; __ret }, _ => aiur_fn_737(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_736] = { let __args: [G; IN_736] = [__v_10, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[736].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[736].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[736].bump_multiplicity(__i); } let __ret: [G; OUT_736] = unsafe { *(record.function_queries[736].output_at(__i).as_ptr() as *const [G; OUT_736]) }; __ret }, _ => aiur_fn_736(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_738] = [__v_13, __v_11, __v_12]; - record.function_queries[738].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_737] = [__v_13, __v_11, __v_12]; + record.function_queries[737].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_739: usize = 1; -const IN_739: usize = 1; -const OUT_739: usize = 41; -fn aiur_fn_739( - inp: [G; IN_739], +const INPUT_SIZE_738: usize = 1; +const IN_738: usize = 1; +const OUT_738: usize = 41; +fn aiur_fn_738( + inp: [G; IN_738], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_739], ExecError> { +) -> Result<[G; OUT_738], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_76] = { let __args: [G; IN_76] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[76].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[76].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[76].bump_multiplicity(__i); } let __ret: [G; OUT_76] = unsafe { *(record.function_queries[76].output_at(__i).as_ptr() as *const [G; OUT_76]) }; __ret }, _ => aiur_fn_76(__args, record, io_buffer, __cu)? } }; @@ -61732,11 +61686,11 @@ fn aiur_fn_739( let __v_15: G = __b1_out[5]; let __v_16: G = __b1_out[6]; let __v_17: G = __b1_out[7]; - let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_10, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_10, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; let __v_18: G = __r_arr[0]; let __v_19: G = __r_arr[1]; let __v_20: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_11, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_11, __v_20]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = __r_arr[1]; let __v_23: G = __r_arr[2]; @@ -61747,7 +61701,7 @@ fn aiur_fn_739( let __v_28: G = __r_arr[7]; let __v_29: G = __r_arr[8]; let __v_30: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_12, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_12, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; @@ -61758,7 +61712,7 @@ fn aiur_fn_739( let __v_38: G = __r_arr[7]; let __v_39: G = __r_arr[8]; let __v_40: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_13, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; let __v_43: G = __r_arr[2]; @@ -61769,7 +61723,7 @@ fn aiur_fn_739( let __v_48: G = __r_arr[7]; let __v_49: G = __r_arr[8]; let __v_50: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_14, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; let __v_52: G = __r_arr[1]; let __v_53: G = __r_arr[2]; @@ -61780,25 +61734,25 @@ fn aiur_fn_739( let __v_58: G = __r_arr[7]; let __v_59: G = __r_arr[8]; let __v_60: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_15, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_15, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_61: G = __r_arr[0]; let __v_62: G = __r_arr[1]; let __v_63: G = __r_arr[2]; - let __ret: [G; OUT_739] = [__v_18, __v_19, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_61, __v_62, __v_63]; - record.function_queries[739].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_738] = [__v_18, __v_19, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_61, __v_62, __v_63]; + record.function_queries[738].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_740: usize = 1; -const IN_740: usize = 1; -const OUT_740: usize = 49; -fn aiur_fn_740( - inp: [G; IN_740], +const INPUT_SIZE_739: usize = 1; +const IN_739: usize = 1; +const OUT_739: usize = 49; +fn aiur_fn_739( + inp: [G; IN_739], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_740], ExecError> { +) -> Result<[G; OUT_739], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_76] = { let __args: [G; IN_76] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[76].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[76].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[76].bump_multiplicity(__i); } let __ret: [G; OUT_76] = unsafe { *(record.function_queries[76].output_at(__i).as_ptr() as *const [G; OUT_76]) }; __ret }, _ => aiur_fn_76(__args, record, io_buffer, __cu)? } }; @@ -61811,7 +61765,7 @@ fn aiur_fn_740( let __v_7: G = __r_arr[6]; let __v_8: G = __r_arr[7]; let __v_9: G = __r_arr[8]; - let __r_arr: [G; OUT_739] = { let __args: [G; IN_739] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[739].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[739].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[739].bump_multiplicity(__i); } let __ret: [G; OUT_739] = unsafe { *(record.function_queries[739].output_at(__i).as_ptr() as *const [G; OUT_739]) }; __ret }, _ => aiur_fn_739(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_738] = { let __args: [G; IN_738] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[738].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[738].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[738].bump_multiplicity(__i); } let __ret: [G; OUT_738] = unsafe { *(record.function_queries[738].output_at(__i).as_ptr() as *const [G; OUT_738]) }; __ret }, _ => aiur_fn_738(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; @@ -61853,21 +61807,21 @@ fn aiur_fn_740( let __v_48: G = __r_arr[38]; let __v_49: G = __r_arr[39]; let __v_50: G = __r_arr[40]; - let __ret: [G; OUT_740] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50]; - record.function_queries[740].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_739] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50]; + record.function_queries[739].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_741: usize = 9; -const IN_741: usize = 9; -const OUT_741: usize = 2; -fn aiur_fn_741( - inp: [G; IN_741], +const INPUT_SIZE_740: usize = 9; +const IN_740: usize = 9; +const OUT_740: usize = 2; +fn aiur_fn_740( + inp: [G; IN_740], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_741], ExecError> { +) -> Result<[G; OUT_740], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61885,12 +61839,12 @@ fn aiur_fn_741( let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 50] = [__v_10, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&50).ok_or(ExecError::InvalidMemorySize(50))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_741] = [__v_12, __v_0]; - record.function_queries[741].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_740] = [__v_12, __v_0]; + record.function_queries[740].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_740] = { let __args: [G; IN_740] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[740].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[740].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[740].bump_multiplicity(__i); } let __ret: [G; OUT_740] = unsafe { *(record.function_queries[740].output_at(__i).as_ptr() as *const [G; OUT_740]) }; __ret }, _ => aiur_fn_740(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_739] = { let __args: [G; IN_739] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[739].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[739].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[739].bump_multiplicity(__i); } let __ret: [G; OUT_739] = unsafe { *(record.function_queries[739].output_at(__i).as_ptr() as *const [G; OUT_739]) }; __ret }, _ => aiur_fn_739(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; @@ -61949,28 +61903,28 @@ fn aiur_fn_741( let __v_64: G = __r_arr[5]; let __v_65: G = __r_arr[6]; let __v_66: G = __r_arr[7]; - let __r_arr: [G; OUT_741] = { let __args: [G; IN_741] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66]; let __cu = unconstrained; let __hit = record.function_queries[741].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[741].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[741].bump_multiplicity(__i); } let __ret: [G; OUT_741] = unsafe { *(record.function_queries[741].output_at(__i).as_ptr() as *const [G; OUT_741]) }; __ret }, _ => aiur_fn_741(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_740] = { let __args: [G; IN_740] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66]; let __cu = unconstrained; let __hit = record.function_queries[740].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[740].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[740].bump_multiplicity(__i); } let __ret: [G; OUT_740] = unsafe { *(record.function_queries[740].output_at(__i).as_ptr() as *const [G; OUT_740]) }; __ret }, _ => aiur_fn_740(__args, record, io_buffer, __cu)? } }; let __v_67: G = __r_arr[0]; let __v_68: G = __r_arr[1]; let __v_69: G = G::from_u64(0); let __v_70: G = { let __values: [G; 50] = [__v_69, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_67]; let __mq = record.memory_queries.get_mut(&50).ok_or(ExecError::InvalidMemorySize(50))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_741] = [__v_70, __v_68]; - record.function_queries[741].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_740] = [__v_70, __v_68]; + record.function_queries[740].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_742: usize = 2; -const IN_742: usize = 2; -const OUT_742: usize = 3; -fn aiur_fn_742( - inp: [G; IN_742], +const INPUT_SIZE_741: usize = 2; +const IN_741: usize = 2; +const OUT_741: usize = 3; +fn aiur_fn_741( + inp: [G; IN_741], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_742], ExecError> { +) -> Result<[G; OUT_741], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -61978,8 +61932,8 @@ fn aiur_fn_742( 0u64 => { let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); - let __ret: [G; OUT_742] = [__v_2, __v_3, __v_1]; - record.function_queries[742].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_741] = [__v_2, __v_3, __v_1]; + record.function_queries[741].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -61993,27 +61947,27 @@ fn aiur_fn_742( let __v_8: G = __r_arr[6]; let __v_9: G = __r_arr[7]; let __v_10: G = __r_arr[8]; - let __r_arr: [G; OUT_741] = { let __args: [G; IN_741] = [__v_10, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[741].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[741].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[741].bump_multiplicity(__i); } let __ret: [G; OUT_741] = unsafe { *(record.function_queries[741].output_at(__i).as_ptr() as *const [G; OUT_741]) }; __ret }, _ => aiur_fn_741(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_740] = { let __args: [G; IN_740] = [__v_10, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[740].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[740].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[740].bump_multiplicity(__i); } let __ret: [G; OUT_740] = unsafe { *(record.function_queries[740].output_at(__i).as_ptr() as *const [G; OUT_740]) }; __ret }, _ => aiur_fn_740(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = G::from_u64(0); - let __ret: [G; OUT_742] = [__v_13, __v_11, __v_12]; - record.function_queries[742].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_741] = [__v_13, __v_11, __v_12]; + record.function_queries[741].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_743: usize = 1; -const IN_743: usize = 1; -const OUT_743: usize = 55; -fn aiur_fn_743( - inp: [G; IN_743], +const INPUT_SIZE_742: usize = 1; +const IN_742: usize = 1; +const OUT_742: usize = 55; +fn aiur_fn_742( + inp: [G; IN_742], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_743], ExecError> { +) -> Result<[G; OUT_742], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_74] = { let __args: [G; IN_74] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[74].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[74].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[74].bump_multiplicity(__i); } let __ret: [G; OUT_74] = unsafe { *(record.function_queries[74].output_at(__i).as_ptr() as *const [G; OUT_74]) }; __ret }, _ => aiur_fn_74(__args, record, io_buffer, __cu)? } }; @@ -62049,15 +62003,15 @@ fn aiur_fn_743( let __v_27: G = __b1_out[7]; match __v_1.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_735] = { let __args: [G; IN_735] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[735].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[735].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[735].bump_multiplicity(__i); } let __ret: [G; OUT_735] = unsafe { *(record.function_queries[735].output_at(__i).as_ptr() as *const [G; OUT_735]) }; __ret }, _ => aiur_fn_735(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; - let __r_arr: [G; OUT_735] = { let __args: [G; IN_735] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[735].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[735].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[735].bump_multiplicity(__i); } let __ret: [G; OUT_735] = unsafe { *(record.function_queries[735].output_at(__i).as_ptr() as *const [G; OUT_735]) }; __ret }, _ => aiur_fn_735(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = __r_arr[2]; @@ -62068,26 +62022,26 @@ fn aiur_fn_743( let __v_41: G = __r_arr[7]; let __v_42: G = __r_arr[8]; let __v_43: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = __r_arr[1]; let __v_46: G = __r_arr[2]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_16, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_16, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; let __v_48: G = __r_arr[1]; let __v_49: G = __r_arr[2]; let __v_50: G = G::from_u64(0); let __v_51: G = G::from_u64(0); - let __ret: [G; OUT_743] = [__v_50, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_47, __v_48, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_49]; - record.function_queries[743].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_742] = [__v_50, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_47, __v_48, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_49]; + record.function_queries[742].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; @@ -62098,7 +62052,7 @@ fn aiur_fn_743( let __v_38: G = __r_arr[7]; let __v_39: G = __r_arr[8]; let __v_40: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_14, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; let __v_43: G = __r_arr[2]; @@ -62109,7 +62063,7 @@ fn aiur_fn_743( let __v_48: G = __r_arr[7]; let __v_49: G = __r_arr[8]; let __v_50: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_15, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_15, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_51: G = __r_arr[0]; let __v_52: G = __r_arr[1]; let __v_53: G = __r_arr[2]; @@ -62120,30 +62074,30 @@ fn aiur_fn_743( let __v_58: G = __r_arr[7]; let __v_59: G = __r_arr[8]; let __v_60: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_16, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_16, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_61: G = __r_arr[0]; let __v_62: G = __r_arr[1]; let __v_63: G = __r_arr[2]; - let __r_arr: [G; OUT_742] = { let __args: [G; IN_742] = [__v_17, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[742].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[742].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[742].bump_multiplicity(__i); } let __ret: [G; OUT_742] = unsafe { *(record.function_queries[742].output_at(__i).as_ptr() as *const [G; OUT_742]) }; __ret }, _ => aiur_fn_742(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_741] = { let __args: [G; IN_741] = [__v_17, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[741].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[741].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[741].bump_multiplicity(__i); } let __ret: [G; OUT_741] = unsafe { *(record.function_queries[741].output_at(__i).as_ptr() as *const [G; OUT_741]) }; __ret }, _ => aiur_fn_741(__args, record, io_buffer, __cu)? } }; let __v_64: G = __r_arr[0]; let __v_65: G = __r_arr[1]; let __v_66: G = __r_arr[2]; let __v_67: G = G::from_u64(1); let __v_68: G = G::from_u64(0); - let __ret: [G; OUT_743] = [__v_67, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_61, __v_62, __v_64, __v_65, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_66]; - record.function_queries[743].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_742] = [__v_67, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_61, __v_62, __v_64, __v_65, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_68, __v_66]; + record.function_queries[742].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; - let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = __r_arr[2]; @@ -62154,7 +62108,7 @@ fn aiur_fn_743( let __v_41: G = __r_arr[7]; let __v_42: G = __r_arr[8]; let __v_43: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = __r_arr[1]; let __v_46: G = __r_arr[2]; @@ -62165,7 +62119,7 @@ fn aiur_fn_743( let __v_51: G = __r_arr[7]; let __v_52: G = __r_arr[8]; let __v_53: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_16, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_16, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; let __v_55: G = __r_arr[1]; let __v_56: G = __r_arr[2]; @@ -62176,7 +62130,7 @@ fn aiur_fn_743( let __v_61: G = __r_arr[7]; let __v_62: G = __r_arr[8]; let __v_63: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_17, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_17, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_64: G = __r_arr[0]; let __v_65: G = __r_arr[1]; let __v_66: G = __r_arr[2]; @@ -62187,7 +62141,7 @@ fn aiur_fn_743( let __v_71: G = __r_arr[7]; let __v_72: G = __r_arr[8]; let __v_73: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_18, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_18, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_74: G = __r_arr[0]; let __v_75: G = __r_arr[1]; let __v_76: G = __r_arr[2]; @@ -62198,17 +62152,17 @@ fn aiur_fn_743( let __v_81: G = __r_arr[7]; let __v_82: G = __r_arr[8]; let __v_83: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_19, __v_83]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_19, __v_83]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_84: G = __r_arr[0]; let __v_85: G = __r_arr[1]; let __v_86: G = __r_arr[2]; - let __r_arr: [G; OUT_738] = { let __args: [G; IN_738] = [__v_20, __v_86]; let __cu = unconstrained; let __hit = record.function_queries[738].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[738].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[738].bump_multiplicity(__i); } let __ret: [G; OUT_738] = unsafe { *(record.function_queries[738].output_at(__i).as_ptr() as *const [G; OUT_738]) }; __ret }, _ => aiur_fn_738(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_737] = { let __args: [G; IN_737] = [__v_20, __v_86]; let __cu = unconstrained; let __hit = record.function_queries[737].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[737].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[737].bump_multiplicity(__i); } let __ret: [G; OUT_737] = unsafe { *(record.function_queries[737].output_at(__i).as_ptr() as *const [G; OUT_737]) }; __ret }, _ => aiur_fn_737(__args, record, io_buffer, __cu)? } }; let __v_87: G = __r_arr[0]; let __v_88: G = __r_arr[1]; let __v_89: G = __r_arr[2]; let __v_90: G = G::from_u64(2); - let __ret: [G; OUT_743] = [__v_90, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_84, __v_85, __v_87, __v_88, __v_89]; - record.function_queries[743].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_742] = [__v_90, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_84, __v_85, __v_87, __v_88, __v_89]; + record.function_queries[742].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -62218,15 +62172,15 @@ fn aiur_fn_743( }) } -const INPUT_SIZE_744: usize = 1; -const IN_744: usize = 1; -const OUT_744: usize = 63; -fn aiur_fn_744( - inp: [G; IN_744], +const INPUT_SIZE_743: usize = 1; +const IN_743: usize = 1; +const OUT_743: usize = 63; +fn aiur_fn_743( + inp: [G; IN_743], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_744], ExecError> { +) -> Result<[G; OUT_743], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_76] = { let __args: [G; IN_76] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[76].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[76].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[76].bump_multiplicity(__i); } let __ret: [G; OUT_76] = unsafe { *(record.function_queries[76].output_at(__i).as_ptr() as *const [G; OUT_76]) }; __ret }, _ => aiur_fn_76(__args, record, io_buffer, __cu)? } }; @@ -62239,7 +62193,7 @@ fn aiur_fn_744( let __v_7: G = __r_arr[6]; let __v_8: G = __r_arr[7]; let __v_9: G = __r_arr[8]; - let __r_arr: [G; OUT_743] = { let __args: [G; IN_743] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[743].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[743].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[743].bump_multiplicity(__i); } let __ret: [G; OUT_743] = unsafe { *(record.function_queries[743].output_at(__i).as_ptr() as *const [G; OUT_743]) }; __ret }, _ => aiur_fn_743(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_742] = { let __args: [G; IN_742] = [__v_9]; let __cu = unconstrained; let __hit = record.function_queries[742].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[742].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[742].bump_multiplicity(__i); } let __ret: [G; OUT_742] = unsafe { *(record.function_queries[742].output_at(__i).as_ptr() as *const [G; OUT_742]) }; __ret }, _ => aiur_fn_742(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; @@ -62295,21 +62249,21 @@ fn aiur_fn_744( let __v_62: G = __r_arr[52]; let __v_63: G = __r_arr[53]; let __v_64: G = __r_arr[54]; - let __ret: [G; OUT_744] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64]; - record.function_queries[744].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_743] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64]; + record.function_queries[743].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_745: usize = 9; -const IN_745: usize = 9; -const OUT_745: usize = 2; -fn aiur_fn_745( - inp: [G; IN_745], +const INPUT_SIZE_744: usize = 9; +const IN_744: usize = 9; +const OUT_744: usize = 2; +fn aiur_fn_744( + inp: [G; IN_744], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_745], ExecError> { +) -> Result<[G; OUT_744], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -62327,12 +62281,12 @@ fn aiur_fn_745( let __v_10: G = G::from_u64(1); let __v_11: G = G::from_u64(1); let __v_12: G = { let __values: [G; 64] = [__v_10, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11, __v_11]; let __mq = record.memory_queries.get_mut(&64).ok_or(ExecError::InvalidMemorySize(64))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_745] = [__v_12, __v_0]; - record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_744] = [__v_12, __v_0]; + record.function_queries[744].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_744] = { let __args: [G; IN_744] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[744].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[744].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[744].bump_multiplicity(__i); } let __ret: [G; OUT_744] = unsafe { *(record.function_queries[744].output_at(__i).as_ptr() as *const [G; OUT_744]) }; __ret }, _ => aiur_fn_744(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_743] = { let __args: [G; IN_743] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[743].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[743].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[743].bump_multiplicity(__i); } let __ret: [G; OUT_743] = unsafe { *(record.function_queries[743].output_at(__i).as_ptr() as *const [G; OUT_743]) }; __ret }, _ => aiur_fn_743(__args, record, io_buffer, __cu)? } }; let __v_10: G = __r_arr[0]; let __v_11: G = __r_arr[1]; let __v_12: G = __r_arr[2]; @@ -62405,28 +62359,28 @@ fn aiur_fn_745( let __v_78: G = __r_arr[5]; let __v_79: G = __r_arr[6]; let __v_80: G = __r_arr[7]; - let __r_arr: [G; OUT_745] = { let __args: [G; IN_745] = [__v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80]; let __cu = unconstrained; let __hit = record.function_queries[745].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[745].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[745].bump_multiplicity(__i); } let __ret: [G; OUT_745] = unsafe { *(record.function_queries[745].output_at(__i).as_ptr() as *const [G; OUT_745]) }; __ret }, _ => aiur_fn_745(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_744] = { let __args: [G; IN_744] = [__v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80]; let __cu = unconstrained; let __hit = record.function_queries[744].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[744].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[744].bump_multiplicity(__i); } let __ret: [G; OUT_744] = unsafe { *(record.function_queries[744].output_at(__i).as_ptr() as *const [G; OUT_744]) }; __ret }, _ => aiur_fn_744(__args, record, io_buffer, __cu)? } }; let __v_81: G = __r_arr[0]; let __v_82: G = __r_arr[1]; let __v_83: G = G::from_u64(0); let __v_84: G = { let __values: [G; 64] = [__v_83, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_81]; let __mq = record.memory_queries.get_mut(&64).ok_or(ExecError::InvalidMemorySize(64))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_745] = [__v_84, __v_82]; - record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_744] = [__v_84, __v_82]; + record.function_queries[744].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_746: usize = 1; -const IN_746: usize = 1; -const OUT_746: usize = 55; -fn aiur_fn_746( - inp: [G; IN_746], +const INPUT_SIZE_745: usize = 1; +const IN_745: usize = 1; +const OUT_745: usize = 55; +fn aiur_fn_745( + inp: [G; IN_745], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_746], ExecError> { +) -> Result<[G; OUT_745], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __r_arr: [G; OUT_74] = { let __args: [G; IN_74] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[74].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[74].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[74].bump_multiplicity(__i); } let __ret: [G; OUT_74] = unsafe { *(record.function_queries[74].output_at(__i).as_ptr() as *const [G; OUT_74]) }; __ret }, _ => aiur_fn_74(__args, record, io_buffer, __cu)? } }; @@ -62462,15 +62416,15 @@ fn aiur_fn_746( let __v_27: G = __b1_out[7]; match __v_1.as_canonical_u64() { 0u64 => { - let __r_arr: [G; OUT_735] = { let __args: [G; IN_735] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[735].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[735].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[735].bump_multiplicity(__i); } let __ret: [G; OUT_735] = unsafe { *(record.function_queries[735].output_at(__i).as_ptr() as *const [G; OUT_735]) }; __ret }, _ => aiur_fn_735(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; - let __r_arr: [G; OUT_735] = { let __args: [G; IN_735] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[735].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[735].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[735].bump_multiplicity(__i); } let __ret: [G; OUT_735] = unsafe { *(record.function_queries[735].output_at(__i).as_ptr() as *const [G; OUT_735]) }; __ret }, _ => aiur_fn_735(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = __r_arr[2]; @@ -62481,30 +62435,30 @@ fn aiur_fn_746( let __v_41: G = __r_arr[7]; let __v_42: G = __r_arr[8]; let __v_43: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = __r_arr[1]; let __v_46: G = __r_arr[2]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_16, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_16, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_47: G = __r_arr[0]; let __v_48: G = __r_arr[1]; let __v_49: G = __r_arr[2]; let __v_50: G = G::from_u64(0); let __v_51: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_50, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_47, __v_48, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_49]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_50, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_47, __v_48, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_51, __v_49]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { - let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; - let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_14, __v_33]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_34: G = __r_arr[0]; let __v_35: G = __r_arr[1]; let __v_36: G = __r_arr[2]; @@ -62515,7 +62469,7 @@ fn aiur_fn_746( let __v_41: G = __r_arr[7]; let __v_42: G = __r_arr[8]; let __v_43: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_15, __v_43]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_44: G = __r_arr[0]; let __v_45: G = __r_arr[1]; let __v_46: G = __r_arr[2]; @@ -62526,7 +62480,7 @@ fn aiur_fn_746( let __v_51: G = __r_arr[7]; let __v_52: G = __r_arr[8]; let __v_53: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_16, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_16, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; let __v_55: G = __r_arr[1]; let __v_56: G = __r_arr[2]; @@ -62537,7 +62491,7 @@ fn aiur_fn_746( let __v_61: G = __r_arr[7]; let __v_62: G = __r_arr[8]; let __v_63: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_17, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_17, __v_63]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_64: G = __r_arr[0]; let __v_65: G = __r_arr[1]; let __v_66: G = __r_arr[2]; @@ -62548,7 +62502,7 @@ fn aiur_fn_746( let __v_71: G = __r_arr[7]; let __v_72: G = __r_arr[8]; let __v_73: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_18, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_18, __v_73]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_74: G = __r_arr[0]; let __v_75: G = __r_arr[1]; let __v_76: G = __r_arr[2]; @@ -62559,25 +62513,25 @@ fn aiur_fn_746( let __v_81: G = __r_arr[7]; let __v_82: G = __r_arr[8]; let __v_83: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_19, __v_83]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_19, __v_83]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_84: G = __r_arr[0]; let __v_85: G = __r_arr[1]; let __v_86: G = __r_arr[2]; - let __r_arr: [G; OUT_738] = { let __args: [G; IN_738] = [__v_20, __v_86]; let __cu = unconstrained; let __hit = record.function_queries[738].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[738].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[738].bump_multiplicity(__i); } let __ret: [G; OUT_738] = unsafe { *(record.function_queries[738].output_at(__i).as_ptr() as *const [G; OUT_738]) }; __ret }, _ => aiur_fn_738(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_737] = { let __args: [G; IN_737] = [__v_20, __v_86]; let __cu = unconstrained; let __hit = record.function_queries[737].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[737].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[737].bump_multiplicity(__i); } let __ret: [G; OUT_737] = unsafe { *(record.function_queries[737].output_at(__i).as_ptr() as *const [G; OUT_737]) }; __ret }, _ => aiur_fn_737(__args, record, io_buffer, __cu)? } }; let __v_87: G = __r_arr[0]; let __v_88: G = __r_arr[1]; let __v_89: G = __r_arr[2]; let __v_90: G = G::from_u64(1); - let __ret: [G; OUT_746] = [__v_90, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_84, __v_85, __v_87, __v_88, __v_89]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_90, __v_28, __v_29, __v_31, __v_32, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_84, __v_85, __v_87, __v_88, __v_89]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { - let __r_arr: [G; OUT_734] = { let __args: [G; IN_734] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[734].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[734].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[734].bump_multiplicity(__i); } let __ret: [G; OUT_734] = unsafe { *(record.function_queries[734].output_at(__i).as_ptr() as *const [G; OUT_734]) }; __ret }, _ => aiur_fn_734(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; @@ -62588,22 +62542,22 @@ fn aiur_fn_746( let __v_38: G = __r_arr[7]; let __v_39: G = __r_arr[8]; let __v_40: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_14, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; let __v_43: G = __r_arr[2]; let __v_44: G = G::from_u64(2); let __v_45: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_44, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_43]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_44, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_43]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 3u64 => { - let __r_arr: [G; OUT_736] = { let __args: [G; IN_736] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[736].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[736].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[736].bump_multiplicity(__i); } let __ret: [G; OUT_736] = unsafe { *(record.function_queries[736].output_at(__i).as_ptr() as *const [G; OUT_736]) }; __ret }, _ => aiur_fn_736(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_735] = { let __args: [G; IN_735] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[735].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[735].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[735].bump_multiplicity(__i); } let __ret: [G; OUT_735] = unsafe { *(record.function_queries[735].output_at(__i).as_ptr() as *const [G; OUT_735]) }; __ret }, _ => aiur_fn_735(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_13, __v_30]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_31: G = __r_arr[0]; let __v_32: G = __r_arr[1]; let __v_33: G = __r_arr[2]; @@ -62614,18 +62568,18 @@ fn aiur_fn_746( let __v_38: G = __r_arr[7]; let __v_39: G = __r_arr[8]; let __v_40: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_14, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_40]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; let __v_43: G = __r_arr[2]; let __v_44: G = G::from_u64(3); let __v_45: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_44, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_43]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_44, __v_28, __v_29, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_41, __v_42, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_45, __v_43]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 4u64 => { - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; @@ -62636,7 +62590,7 @@ fn aiur_fn_746( let __v_35: G = __r_arr[7]; let __v_36: G = __r_arr[8]; let __v_37: G = __r_arr[9]; - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; let __v_40: G = __r_arr[2]; @@ -62647,18 +62601,18 @@ fn aiur_fn_746( let __v_45: G = __r_arr[7]; let __v_46: G = __r_arr[8]; let __v_47: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_14, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_14, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; let __v_49: G = __r_arr[1]; let __v_50: G = __r_arr[2]; let __v_51: G = G::from_u64(4); let __v_52: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_51, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_48, __v_49, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_50]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_51, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_48, __v_49, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_52, __v_50]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 5u64 => { - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; @@ -62669,18 +62623,18 @@ fn aiur_fn_746( let __v_35: G = __r_arr[7]; let __v_36: G = __r_arr[8]; let __v_37: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; let __v_40: G = __r_arr[2]; let __v_41: G = G::from_u64(5); let __v_42: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_41, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_40]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_41, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_40]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; @@ -62691,18 +62645,18 @@ fn aiur_fn_746( let __v_35: G = __r_arr[7]; let __v_36: G = __r_arr[8]; let __v_37: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; let __v_40: G = __r_arr[2]; let __v_41: G = G::from_u64(6); let __v_42: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_41, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_40]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_41, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_40]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { - let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_12, __v_11]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; @@ -62713,14 +62667,14 @@ fn aiur_fn_746( let __v_35: G = __r_arr[7]; let __v_36: G = __r_arr[8]; let __v_37: G = __r_arr[9]; - let __r_arr: [G; OUT_733] = { let __args: [G; IN_733] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[733].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[733].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[733].bump_multiplicity(__i); } let __ret: [G; OUT_733] = unsafe { *(record.function_queries[733].output_at(__i).as_ptr() as *const [G; OUT_733]) }; __ret }, _ => aiur_fn_733(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_732] = { let __args: [G; IN_732] = [__v_13, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[732].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[732].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[732].bump_multiplicity(__i); } let __ret: [G; OUT_732] = unsafe { *(record.function_queries[732].output_at(__i).as_ptr() as *const [G; OUT_732]) }; __ret }, _ => aiur_fn_732(__args, record, io_buffer, __cu)? } }; let __v_38: G = __r_arr[0]; let __v_39: G = __r_arr[1]; let __v_40: G = __r_arr[2]; let __v_41: G = G::from_u64(7); let __v_42: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_41, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_40]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_41, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_38, __v_39, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_42, __v_40]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 8u64 => { @@ -62742,7 +62696,7 @@ fn aiur_fn_746( let __v_34: G = __r_arr[6]; let __v_35: G = __r_arr[7]; let __v_36: G = __r_arr[8]; - let __r_arr: [G; OUT_745] = { let __args: [G; IN_745] = [__v_36, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[745].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[745].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[745].bump_multiplicity(__i); } let __ret: [G; OUT_745] = unsafe { *(record.function_queries[745].output_at(__i).as_ptr() as *const [G; OUT_745]) }; __ret }, _ => aiur_fn_745(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_744] = { let __args: [G; IN_744] = [__v_36, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35]; let __cu = unconstrained; let __hit = record.function_queries[744].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[744].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[744].bump_multiplicity(__i); } let __ret: [G; OUT_744] = unsafe { *(record.function_queries[744].output_at(__i).as_ptr() as *const [G; OUT_744]) }; __ret }, _ => aiur_fn_744(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = __r_arr[1]; break '__mc_0 [__v_37, __v_38]; @@ -62756,8 +62710,8 @@ fn aiur_fn_746( let __v_29: G = __mc_out___mc_0[1]; let __v_30: G = G::from_u64(8); let __v_31: G = G::from_u64(0); - let __ret: [G; OUT_746] = [__v_30, __v_28, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_29]; - record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_745] = [__v_30, __v_28, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_31, __v_29]; + record.function_queries[745].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -62767,15 +62721,15 @@ fn aiur_fn_746( }) } -const INPUT_SIZE_747: usize = 1; -const IN_747: usize = 1; -const OUT_747: usize = 1; -fn aiur_fn_747( - inp: [G; IN_747], +const INPUT_SIZE_746: usize = 1; +const IN_746: usize = 1; +const OUT_746: usize = 1; +fn aiur_fn_746( + inp: [G; IN_746], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_747], ExecError> { +) -> Result<[G; OUT_746], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 18] = { let __mq = record.memory_queries.get_mut(&18).ok_or(ExecError::InvalidMemorySize(18))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 18 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 18] = __args[..18].try_into().unwrap(); __arr }; @@ -62804,40 +62758,40 @@ fn aiur_fn_747( let __v_22: G = __r_arr[0]; let __r_arr: [G; OUT_22] = { let __args: [G; IN_22] = [__v_22]; let __cu = unconstrained; let __hit = record.function_queries[22].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[22].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[22].bump_multiplicity(__i); } let __ret: [G; OUT_22] = unsafe { *(record.function_queries[22].output_at(__i).as_ptr() as *const [G; OUT_22]) }; __ret }, _ => aiur_fn_22(__args, record, io_buffer, __cu)? } }; let __v_23: G = __r_arr[0]; - let __ret: [G; OUT_747] = [__v_23]; - record.function_queries[747].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_746] = [__v_23]; + record.function_queries[746].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_748: usize = 1; -const IN_748: usize = 1; -const OUT_748: usize = 1; -fn aiur_fn_748( - inp: [G; IN_748], +const INPUT_SIZE_747: usize = 1; +const IN_747: usize = 1; +const OUT_747: usize = 1; +fn aiur_fn_747( + inp: [G; IN_747], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_748], ExecError> { +) -> Result<[G; OUT_747], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; match __v_0.as_canonical_u64() { 0u64 => { let __v_1: G = G::from_u64(0); - let __ret: [G; OUT_748] = [__v_1]; - record.function_queries[748].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_747] = [__v_1]; + record.function_queries[747].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 1u64 => { let __v_1: G = G::from_u64(1); - let __ret: [G; OUT_748] = [__v_1]; - record.function_queries[748].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_747] = [__v_1]; + record.function_queries[747].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 2u64 => { let __v_1: G = G::from_u64(2); - let __ret: [G; OUT_748] = [__v_1]; - record.function_queries[748].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_747] = [__v_1]; + record.function_queries[747].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -62847,6 +62801,44 @@ fn aiur_fn_748( }) } +const INPUT_SIZE_748: usize = 3; +const IN_748: usize = 3; +const OUT_748: usize = 0; +fn aiur_fn_748( + inp: [G; IN_748], + record: &mut QueryRecord, + io_buffer: &mut IOBuffer, + unconstrained: bool, +) -> Result<[G; OUT_748], ExecError> { + stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { + let __v_0: G = inp[0]; + let __v_1: G = inp[1]; + let __v_2: G = inp[2]; + match __v_1.as_canonical_u64() { + 1u64 => { + let __ret: [G; OUT_748] = []; + record.function_queries[748].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + 0u64 => { + let __r_arr: [G; OUT_747] = { let __args: [G; IN_747] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[747].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[747].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[747].bump_multiplicity(__i); } let __ret: [G; OUT_747] = unsafe { *(record.function_queries[747].output_at(__i).as_ptr() as *const [G; OUT_747]) }; __ret }, _ => aiur_fn_747(__args, record, io_buffer, __cu)? } }; + let __v_3: G = __r_arr[0]; + let __r_arr: [G; OUT_747] = { let __args: [G; IN_747] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[747].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[747].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[747].bump_multiplicity(__i); } let __ret: [G; OUT_747] = unsafe { *(record.function_queries[747].output_at(__i).as_ptr() as *const [G; OUT_747]) }; __ret }, _ => aiur_fn_747(__args, record, io_buffer, __cu)? } }; + let __v_4: G = __r_arr[0]; + if (__v_3 != __v_4) { + return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Reveal: claimed definition kind != real".to_string()) }); + } + let __ret: [G; OUT_748] = []; + record.function_queries[748].finish(&inp[..], &__ret[..], !unconstrained); + return Ok(__ret); + }, + _ => { + return Err(ExecError::MatchNoCase(__v_1.as_canonical_u64())); + }, + } + }) +} + const INPUT_SIZE_749: usize = 3; const IN_749: usize = 3; const OUT_749: usize = 0; @@ -62867,12 +62859,12 @@ fn aiur_fn_749( return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_748] = { let __args: [G; IN_748] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[748].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[748].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[748].bump_multiplicity(__i); } let __ret: [G; OUT_748] = unsafe { *(record.function_queries[748].output_at(__i).as_ptr() as *const [G; OUT_748]) }; __ret }, _ => aiur_fn_748(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_747] = { let __args: [G; IN_747] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[747].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[747].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[747].bump_multiplicity(__i); } let __ret: [G; OUT_747] = unsafe { *(record.function_queries[747].output_at(__i).as_ptr() as *const [G; OUT_747]) }; __ret }, _ => aiur_fn_747(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_748] = { let __args: [G; IN_748] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[748].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[748].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[748].bump_multiplicity(__i); } let __ret: [G; OUT_748] = unsafe { *(record.function_queries[748].output_at(__i).as_ptr() as *const [G; OUT_748]) }; __ret }, _ => aiur_fn_748(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_747] = { let __args: [G; IN_747] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[747].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[747].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[747].bump_multiplicity(__i); } let __ret: [G; OUT_747] = unsafe { *(record.function_queries[747].output_at(__i).as_ptr() as *const [G; OUT_747]) }; __ret }, _ => aiur_fn_747(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; if (__v_3 != __v_4) { - return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Reveal: claimed definition kind != real".to_string()) }); + return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Reveal: claimed definition safety != real".to_string()) }); } let __ret: [G; OUT_749] = []; record.function_queries[749].finish(&inp[..], &__ret[..], !unconstrained); @@ -62905,12 +62897,12 @@ fn aiur_fn_750( return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_748] = { let __args: [G; IN_748] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[748].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[748].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[748].bump_multiplicity(__i); } let __ret: [G; OUT_748] = unsafe { *(record.function_queries[748].output_at(__i).as_ptr() as *const [G; OUT_748]) }; __ret }, _ => aiur_fn_748(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_103] = { let __args: [G; IN_103] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[103].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[103].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[103].bump_multiplicity(__i); } let __ret: [G; OUT_103] = unsafe { *(record.function_queries[103].output_at(__i).as_ptr() as *const [G; OUT_103]) }; __ret }, _ => aiur_fn_103(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_748] = { let __args: [G; IN_748] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[748].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[748].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[748].bump_multiplicity(__i); } let __ret: [G; OUT_748] = unsafe { *(record.function_queries[748].output_at(__i).as_ptr() as *const [G; OUT_748]) }; __ret }, _ => aiur_fn_748(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_103] = { let __args: [G; IN_103] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[103].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[103].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[103].bump_multiplicity(__i); } let __ret: [G; OUT_103] = unsafe { *(record.function_queries[103].output_at(__i).as_ptr() as *const [G; OUT_103]) }; __ret }, _ => aiur_fn_103(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; if (__v_3 != __v_4) { - return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Reveal: claimed definition safety != real".to_string()) }); + return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Reveal: claimed quotient kind != real".to_string()) }); } let __ret: [G; OUT_750] = []; record.function_queries[750].finish(&inp[..], &__ret[..], !unconstrained); @@ -62943,12 +62935,8 @@ fn aiur_fn_751( return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_103] = { let __args: [G; IN_103] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[103].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[103].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[103].bump_multiplicity(__i); } let __ret: [G; OUT_103] = unsafe { *(record.function_queries[103].output_at(__i).as_ptr() as *const [G; OUT_103]) }; __ret }, _ => aiur_fn_103(__args, record, io_buffer, __cu)? } }; - let __v_3: G = __r_arr[0]; - let __r_arr: [G; OUT_103] = { let __args: [G; IN_103] = [__v_2]; let __cu = unconstrained; let __hit = record.function_queries[103].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[103].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[103].bump_multiplicity(__i); } let __ret: [G; OUT_103] = unsafe { *(record.function_queries[103].output_at(__i).as_ptr() as *const [G; OUT_103]) }; __ret }, _ => aiur_fn_103(__args, record, io_buffer, __cu)? } }; - let __v_4: G = __r_arr[0]; - if (__v_3 != __v_4) { - return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Reveal: claimed quotient kind != real".to_string()) }); + if (__v_0 != __v_2) { + return Err(ExecError::AssertEqMismatch { lhs: __v_0.as_canonical_u64(), rhs: __v_2.as_canonical_u64(), msg: Some("Reveal: claimed flag != real".to_string()) }); } let __ret: [G; OUT_751] = []; record.function_queries[751].finish(&inp[..], &__ret[..], !unconstrained); @@ -62961,8 +62949,8 @@ fn aiur_fn_751( }) } -const INPUT_SIZE_752: usize = 3; -const IN_752: usize = 3; +const INPUT_SIZE_752: usize = 17; +const IN_752: usize = 17; const OUT_752: usize = 0; fn aiur_fn_752( inp: [G; IN_752], @@ -62970,40 +62958,6 @@ fn aiur_fn_752( io_buffer: &mut IOBuffer, unconstrained: bool, ) -> Result<[G; OUT_752], ExecError> { - stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { - let __v_0: G = inp[0]; - let __v_1: G = inp[1]; - let __v_2: G = inp[2]; - match __v_1.as_canonical_u64() { - 1u64 => { - let __ret: [G; OUT_752] = []; - record.function_queries[752].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - 0u64 => { - if (__v_0 != __v_2) { - return Err(ExecError::AssertEqMismatch { lhs: __v_0.as_canonical_u64(), rhs: __v_2.as_canonical_u64(), msg: Some("Reveal: claimed flag != real".to_string()) }); - } - let __ret: [G; OUT_752] = []; - record.function_queries[752].finish(&inp[..], &__ret[..], !unconstrained); - return Ok(__ret); - }, - _ => { - return Err(ExecError::MatchNoCase(__v_1.as_canonical_u64())); - }, - } - }) -} - -const INPUT_SIZE_753: usize = 17; -const IN_753: usize = 17; -const OUT_753: usize = 0; -fn aiur_fn_753( - inp: [G; IN_753], - record: &mut QueryRecord, - io_buffer: &mut IOBuffer, - unconstrained: bool, -) -> Result<[G; OUT_753], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -63024,8 +62978,8 @@ fn aiur_fn_753( let __v_16: G = inp[16]; match __v_8.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_753] = []; - record.function_queries[753].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_752] = []; + record.function_queries[752].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -63053,8 +63007,8 @@ fn aiur_fn_753( if (__v_7 != __v_16) { return Err(ExecError::AssertEqMismatch { lhs: __v_7.as_canonical_u64(), rhs: __v_16.as_canonical_u64(), msg: Some("Reveal: claimed numeric field != real".to_string()) }); } - let __ret: [G; OUT_753] = []; - record.function_queries[753].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_752] = []; + record.function_queries[752].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -63064,23 +63018,23 @@ fn aiur_fn_753( }) } -const INPUT_SIZE_754: usize = 3; -const IN_754: usize = 3; -const OUT_754: usize = 0; -fn aiur_fn_754( - inp: [G; IN_754], +const INPUT_SIZE_753: usize = 3; +const IN_753: usize = 3; +const OUT_753: usize = 0; +fn aiur_fn_753( + inp: [G; IN_753], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_754], ExecError> { +) -> Result<[G; OUT_753], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_754] = []; - record.function_queries[754].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_753] = []; + record.function_queries[753].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -63246,8 +63200,8 @@ fn aiur_fn_754( if (__v_34 != __v_66) { return Err(ExecError::AssertEqMismatch { lhs: __v_34.as_canonical_u64(), rhs: __v_66.as_canonical_u64(), msg: Some("Reveal: claimed address field != real".to_string()) }); } - let __ret: [G; OUT_754] = []; - record.function_queries[754].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_753] = []; + record.function_queries[753].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -63257,27 +63211,27 @@ fn aiur_fn_754( }) } -const INPUT_SIZE_755: usize = 3; -const IN_755: usize = 3; -const OUT_755: usize = 0; -fn aiur_fn_755( - inp: [G; IN_755], +const INPUT_SIZE_754: usize = 3; +const IN_754: usize = 3; +const OUT_754: usize = 0; +fn aiur_fn_754( + inp: [G; IN_754], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_755], ExecError> { +) -> Result<[G; OUT_754], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_755] = []; - record.function_queries[755].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_754] = []; + record.function_queries[754].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_747] = { let __args: [G; IN_747] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[747].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[747].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[747].bump_multiplicity(__i); } let __ret: [G; OUT_747] = unsafe { *(record.function_queries[747].output_at(__i).as_ptr() as *const [G; OUT_747]) }; __ret }, _ => aiur_fn_747(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_746] = { let __args: [G; IN_746] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[746].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[746].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[746].bump_multiplicity(__i); } let __ret: [G; OUT_746] = unsafe { *(record.function_queries[746].output_at(__i).as_ptr() as *const [G; OUT_746]) }; __ret }, _ => aiur_fn_746(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 32] = { let __mq = record.memory_queries.get_mut(&32).ok_or(ExecError::InvalidMemorySize(32))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 32 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 32] = __args[..32].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -63441,8 +63395,8 @@ fn aiur_fn_755( if (__v_35 != __v_67) { return Err(ExecError::AssertEqMismatch { lhs: __v_35.as_canonical_u64(), rhs: __v_67.as_canonical_u64(), msg: Some("Reveal: claimed expr hash != hash of the real expr".to_string()) }); } - let __ret: [G; OUT_755] = []; - record.function_queries[755].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_754] = []; + record.function_queries[754].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -63452,15 +63406,15 @@ fn aiur_fn_755( }) } -const INPUT_SIZE_756: usize = 10; -const IN_756: usize = 10; -const OUT_756: usize = 0; -fn aiur_fn_756( - inp: [G; IN_756], +const INPUT_SIZE_755: usize = 10; +const IN_755: usize = 10; +const OUT_755: usize = 0; +fn aiur_fn_755( + inp: [G; IN_755], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_756], ExecError> { +) -> Result<[G; OUT_755], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -63508,8 +63462,8 @@ fn aiur_fn_756( let __v_39: G = __loaded[10]; match __v_29.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_756] = []; - record.function_queries[756].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_755] = []; + record.function_queries[755].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -63585,7 +63539,7 @@ fn aiur_fn_756( return Err(ExecError::AssertEqMismatch { lhs: __v_37.as_canonical_u64(), rhs: __v_26.as_canonical_u64(), msg: Some("Reveal: claimed recursor rule field count != real".to_string()) }); } let __v_40: G = G::from_u64(0); - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_38, __v_40, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_38, __v_40, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; let __r_arr: [G; OUT_15] = { let __args: [G; IN_15] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9]; let __cu = unconstrained; let __hit = record.function_queries[15].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[15].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[15].bump_multiplicity(__i); } let __ret: [G; OUT_15] = unsafe { *(record.function_queries[15].output_at(__i).as_ptr() as *const [G; OUT_15]) }; __ret }, _ => aiur_fn_15(__args, record, io_buffer, __cu)? } }; let __v_41: G = __r_arr[0]; let __v_42: G = __r_arr[1]; @@ -63595,9 +63549,9 @@ fn aiur_fn_756( let __v_46: G = __r_arr[5]; let __v_47: G = __r_arr[6]; let __v_48: G = __r_arr[7]; - let __r_arr: [G; OUT_756] = { let __args: [G; IN_756] = [__v_39, __v_28, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[756].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[756].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[756].bump_multiplicity(__i); } let __ret: [G; OUT_756] = unsafe { *(record.function_queries[756].output_at(__i).as_ptr() as *const [G; OUT_756]) }; __ret }, _ => aiur_fn_756(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_756] = []; - record.function_queries[756].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_39, __v_28, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_755] = []; + record.function_queries[755].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -63616,23 +63570,23 @@ fn aiur_fn_756( }) } -const INPUT_SIZE_757: usize = 3; -const IN_757: usize = 3; -const OUT_757: usize = 0; -fn aiur_fn_757( - inp: [G; IN_757], +const INPUT_SIZE_756: usize = 3; +const IN_756: usize = 3; +const OUT_756: usize = 0; +fn aiur_fn_756( + inp: [G; IN_756], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_757], ExecError> { +) -> Result<[G; OUT_756], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_757] = []; - record.function_queries[757].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_756] = []; + record.function_queries[756].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -63644,9 +63598,9 @@ fn aiur_fn_757( let __v_8: G = G::from_u64(0); let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); - let __r_arr: [G; OUT_756] = { let __args: [G; IN_756] = [__v_0, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[756].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[756].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[756].bump_multiplicity(__i); } let __ret: [G; OUT_756] = unsafe { *(record.function_queries[756].output_at(__i).as_ptr() as *const [G; OUT_756]) }; __ret }, _ => aiur_fn_756(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_757] = []; - record.function_queries[757].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_0, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_756] = []; + record.function_queries[756].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -63656,15 +63610,15 @@ fn aiur_fn_757( }) } -const INPUT_SIZE_758: usize = 49; -const IN_758: usize = 49; -const OUT_758: usize = 0; -fn aiur_fn_758( - inp: [G; IN_758], +const INPUT_SIZE_757: usize = 49; +const IN_757: usize = 49; +const OUT_757: usize = 0; +fn aiur_fn_757( + inp: [G; IN_757], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_758], ExecError> { +) -> Result<[G; OUT_757], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -63715,7 +63669,7 @@ fn aiur_fn_758( let __v_46: G = inp[46]; let __v_47: G = inp[47]; let __v_48: G = inp[48]; - let __r_arr: [G; OUT_782] = { let __args: [G; IN_782] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[782].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[782].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[782].bump_multiplicity(__i); } let __ret: [G; OUT_782] = unsafe { *(record.function_queries[782].output_at(__i).as_ptr() as *const [G; OUT_782]) }; __ret }, _ => aiur_fn_782(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_781] = { let __args: [G; IN_781] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __cu = unconstrained; let __hit = record.function_queries[781].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[781].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[781].bump_multiplicity(__i); } let __ret: [G; OUT_781] = unsafe { *(record.function_queries[781].output_at(__i).as_ptr() as *const [G; OUT_781]) }; __ret }, _ => aiur_fn_781(__args, record, io_buffer, __cu)? } }; let __v_49: G = __r_arr[0]; let __v_50: G = __r_arr[1]; let __v_51: G = __r_arr[2]; @@ -63754,14 +63708,14 @@ fn aiur_fn_758( _ => { match __v_49.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_49, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_82, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_758] = []; - record.function_queries[758].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_49, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_82, __v_47, __v_48]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_757] = []; + record.function_queries[757].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -63770,15 +63724,15 @@ fn aiur_fn_758( }) } -const INPUT_SIZE_759: usize = 2; -const IN_759: usize = 2; -const OUT_759: usize = 0; -fn aiur_fn_759( - inp: [G; IN_759], +const INPUT_SIZE_758: usize = 2; +const IN_758: usize = 2; +const OUT_758: usize = 0; +fn aiur_fn_758( + inp: [G; IN_758], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_759], ExecError> { +) -> Result<[G; OUT_758], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -63835,15 +63789,15 @@ fn aiur_fn_759( let __v_51: G = __loaded[49]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_759] = []; - record.function_queries[759].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_758] = []; + record.function_queries[758].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_758] = { let __args: [G; IN_758] = [__v_0, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[758].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[758].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[758].bump_multiplicity(__i); } let __ret: [G; OUT_758] = unsafe { *(record.function_queries[758].output_at(__i).as_ptr() as *const [G; OUT_758]) }; __ret }, _ => aiur_fn_758(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_759] = { let __args: [G; IN_759] = [__v_0, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[759].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[759].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[759].bump_multiplicity(__i); } let __ret: [G; OUT_759] = unsafe { *(record.function_queries[759].output_at(__i).as_ptr() as *const [G; OUT_759]) }; __ret }, _ => aiur_fn_759(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_759] = []; - record.function_queries[759].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_757] = { let __args: [G; IN_757] = [__v_0, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[757].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[757].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[757].bump_multiplicity(__i); } let __ret: [G; OUT_757] = unsafe { *(record.function_queries[757].output_at(__i).as_ptr() as *const [G; OUT_757]) }; __ret }, _ => aiur_fn_757(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_758] = { let __args: [G; IN_758] = [__v_0, __v_51]; let __cu = unconstrained; let __hit = record.function_queries[758].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[758].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[758].bump_multiplicity(__i); } let __ret: [G; OUT_758] = unsafe { *(record.function_queries[758].output_at(__i).as_ptr() as *const [G; OUT_758]) }; __ret }, _ => aiur_fn_758(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_758] = []; + record.function_queries[758].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -63853,29 +63807,29 @@ fn aiur_fn_759( }) } -const INPUT_SIZE_760: usize = 3; -const IN_760: usize = 3; -const OUT_760: usize = 0; -fn aiur_fn_760( - inp: [G; IN_760], +const INPUT_SIZE_759: usize = 3; +const IN_759: usize = 3; +const OUT_759: usize = 0; +fn aiur_fn_759( + inp: [G; IN_759], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_760], ExecError> { +) -> Result<[G; OUT_759], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; match __v_1.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_760] = []; - record.function_queries[760].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_759] = []; + record.function_queries[759].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_759] = { let __args: [G; IN_759] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[759].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[759].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[759].bump_multiplicity(__i); } let __ret: [G; OUT_759] = unsafe { *(record.function_queries[759].output_at(__i).as_ptr() as *const [G; OUT_759]) }; __ret }, _ => aiur_fn_759(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_760] = []; - record.function_queries[760].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_758] = { let __args: [G; IN_758] = [__v_0, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[758].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[758].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[758].bump_multiplicity(__i); } let __ret: [G; OUT_758] = unsafe { *(record.function_queries[758].output_at(__i).as_ptr() as *const [G; OUT_758]) }; __ret }, _ => aiur_fn_758(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_759] = []; + record.function_queries[759].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -63885,15 +63839,15 @@ fn aiur_fn_760( }) } -const INPUT_SIZE_761: usize = 99; -const IN_761: usize = 99; -const OUT_761: usize = 0; -fn aiur_fn_761( - inp: [G; IN_761], +const INPUT_SIZE_760: usize = 99; +const IN_760: usize = 99; +const OUT_760: usize = 0; +fn aiur_fn_760( + inp: [G; IN_760], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_761], ExecError> { +) -> Result<[G; OUT_760], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -64000,13 +63954,13 @@ fn aiur_fn_761( 0u64 => { match __v_1.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_749] = { let __args: [G; IN_749] = [__v_1, __v_46, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[749].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[749].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[749].bump_multiplicity(__i); } let __ret: [G; OUT_749] = unsafe { *(record.function_queries[749].output_at(__i).as_ptr() as *const [G; OUT_749]) }; __ret }, _ => aiur_fn_749(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_750] = { let __args: [G; IN_750] = [__v_2, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[750].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[750].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[750].bump_multiplicity(__i); } let __ret: [G; OUT_750] = unsafe { *(record.function_queries[750].output_at(__i).as_ptr() as *const [G; OUT_750]) }; __ret }, _ => aiur_fn_750(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_11, __v_59, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_12, __v_61, __v_62]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_761] = []; - record.function_queries[761].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_748] = { let __args: [G; IN_748] = [__v_1, __v_46, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[748].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[748].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[748].bump_multiplicity(__i); } let __ret: [G; OUT_748] = unsafe { *(record.function_queries[748].output_at(__i).as_ptr() as *const [G; OUT_748]) }; __ret }, _ => aiur_fn_748(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_749] = { let __args: [G; IN_749] = [__v_2, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[749].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[749].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[749].bump_multiplicity(__i); } let __ret: [G; OUT_749] = unsafe { *(record.function_queries[749].output_at(__i).as_ptr() as *const [G; OUT_749]) }; __ret }, _ => aiur_fn_749(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_11, __v_59, __v_60]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_12, __v_61, __v_62]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_760] = []; + record.function_queries[760].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64021,14 +63975,14 @@ fn aiur_fn_761( 1u64 => { match __v_1.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_1, __v_46, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_26, __v_75, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_760] = { let __args: [G; IN_760] = [__v_27, __v_77, __v_78]; let __cu = unconstrained; let __hit = record.function_queries[760].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[760].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[760].bump_multiplicity(__i); } let __ret: [G; OUT_760] = unsafe { *(record.function_queries[760].output_at(__i).as_ptr() as *const [G; OUT_760]) }; __ret }, _ => aiur_fn_760(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_761] = []; - record.function_queries[761].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_1, __v_46, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_26, __v_75, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_759] = { let __args: [G; IN_759] = [__v_27, __v_77, __v_78]; let __cu = unconstrained; let __hit = record.function_queries[759].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[759].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[759].bump_multiplicity(__i); } let __ret: [G; OUT_759] = unsafe { *(record.function_queries[759].output_at(__i).as_ptr() as *const [G; OUT_759]) }; __ret }, _ => aiur_fn_759(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_760] = []; + record.function_queries[760].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64043,17 +63997,17 @@ fn aiur_fn_761( 2u64 => { match __v_1.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_1, __v_46, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_2, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_43, __v_95, __v_96]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_757] = { let __args: [G; IN_757] = [__v_44, __v_97, __v_98]; let __cu = unconstrained; let __hit = record.function_queries[757].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[757].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[757].bump_multiplicity(__i); } let __ret: [G; OUT_757] = unsafe { *(record.function_queries[757].output_at(__i).as_ptr() as *const [G; OUT_757]) }; __ret }, _ => aiur_fn_757(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_761] = []; - record.function_queries[761].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_1, __v_46, __v_47]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_2, __v_48, __v_49]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_43, __v_95, __v_96]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_756] = { let __args: [G; IN_756] = [__v_44, __v_97, __v_98]; let __cu = unconstrained; let __hit = record.function_queries[756].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[756].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[756].bump_multiplicity(__i); } let __ret: [G; OUT_756] = unsafe { *(record.function_queries[756].output_at(__i).as_ptr() as *const [G; OUT_756]) }; __ret }, _ => aiur_fn_756(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_760] = []; + record.function_queries[760].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64070,15 +64024,15 @@ fn aiur_fn_761( }) } -const INPUT_SIZE_762: usize = 2; -const IN_762: usize = 2; -const OUT_762: usize = 0; -fn aiur_fn_762( - inp: [G; IN_762], +const INPUT_SIZE_761: usize = 2; +const IN_761: usize = 2; +const OUT_761: usize = 0; +fn aiur_fn_761( + inp: [G; IN_761], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_762], ExecError> { +) -> Result<[G; OUT_761], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -64149,12 +64103,12 @@ fn aiur_fn_762( let __v_65: G = __loaded[63]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_762] = []; - record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_761] = []; + record.function_queries[761].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_779] = { let __args: [G; IN_779] = [__v_0, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[779].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[779].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[779].bump_multiplicity(__i); } let __ret: [G; OUT_779] = unsafe { *(record.function_queries[779].output_at(__i).as_ptr() as *const [G; OUT_779]) }; __ret }, _ => aiur_fn_779(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_778] = { let __args: [G; IN_778] = [__v_0, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[778].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[778].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[778].bump_multiplicity(__i); } let __ret: [G; OUT_778] = unsafe { *(record.function_queries[778].output_at(__i).as_ptr() as *const [G; OUT_778]) }; __ret }, _ => aiur_fn_778(__args, record, io_buffer, __cu)? } }; let __v_66: G = __r_arr[0]; let __v_67: G = __r_arr[1]; let __v_68: G = __r_arr[2]; @@ -64200,10 +64154,10 @@ fn aiur_fn_762( let __v_108: G = __r_arr[42]; let __v_109: G = __r_arr[43]; let __v_110: G = __r_arr[44]; - let __r_arr: [G; OUT_761] = { let __args: [G; IN_761] = [__v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_95, __v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107, __v_108, __v_109, __v_110, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64]; let __cu = unconstrained; let __hit = record.function_queries[761].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[761].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[761].bump_multiplicity(__i); } let __ret: [G; OUT_761] = unsafe { *(record.function_queries[761].output_at(__i).as_ptr() as *const [G; OUT_761]) }; __ret }, _ => aiur_fn_761(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_762] = { let __args: [G; IN_762] = [__v_0, __v_65]; let __cu = unconstrained; let __hit = record.function_queries[762].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[762].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[762].bump_multiplicity(__i); } let __ret: [G; OUT_762] = unsafe { *(record.function_queries[762].output_at(__i).as_ptr() as *const [G; OUT_762]) }; __ret }, _ => aiur_fn_762(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_762] = []; - record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_760] = { let __args: [G; IN_760] = [__v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_95, __v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107, __v_108, __v_109, __v_110, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64]; let __cu = unconstrained; let __hit = record.function_queries[760].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[760].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[760].bump_multiplicity(__i); } let __ret: [G; OUT_760] = unsafe { *(record.function_queries[760].output_at(__i).as_ptr() as *const [G; OUT_760]) }; __ret }, _ => aiur_fn_760(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_761] = { let __args: [G; IN_761] = [__v_0, __v_65]; let __cu = unconstrained; let __hit = record.function_queries[761].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[761].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[761].bump_multiplicity(__i); } let __ret: [G; OUT_761] = unsafe { *(record.function_queries[761].output_at(__i).as_ptr() as *const [G; OUT_761]) }; __ret }, _ => aiur_fn_761(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_761] = []; + record.function_queries[761].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -64213,15 +64167,15 @@ fn aiur_fn_762( }) } -const INPUT_SIZE_763: usize = 55; -const IN_763: usize = 55; -const OUT_763: usize = 0; -fn aiur_fn_763( - inp: [G; IN_763], +const INPUT_SIZE_762: usize = 55; +const IN_762: usize = 55; +const OUT_762: usize = 0; +fn aiur_fn_762( + inp: [G; IN_762], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_763], ExecError> { +) -> Result<[G; OUT_762], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -64278,7 +64232,7 @@ fn aiur_fn_763( let __v_52: G = inp[52]; let __v_53: G = inp[53]; let __v_54: G = inp[54]; - let __r_arr: [G; OUT_282] = { let __args: [G; IN_282] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[282].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[282].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[282].bump_multiplicity(__i); } let __ret: [G; OUT_282] = unsafe { *(record.function_queries[282].output_at(__i).as_ptr() as *const [G; OUT_282]) }; __ret }, _ => aiur_fn_282(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_281] = { let __args: [G; IN_281] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[281].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[281].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[281].bump_multiplicity(__i); } let __ret: [G; OUT_281] = unsafe { *(record.function_queries[281].output_at(__i).as_ptr() as *const [G; OUT_281]) }; __ret }, _ => aiur_fn_281(__args, record, io_buffer, __cu)? } }; let __v_55: G = __r_arr[0]; let __v_56: G = __r_arr[1]; let __v_57: G = __r_arr[2]; @@ -64335,13 +64289,13 @@ fn aiur_fn_763( 0u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_749] = { let __args: [G; IN_749] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[749].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[749].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[749].bump_multiplicity(__i); } let __ret: [G; OUT_749] = unsafe { *(record.function_queries[749].output_at(__i).as_ptr() as *const [G; OUT_749]) }; __ret }, _ => aiur_fn_749(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_750] = { let __args: [G; IN_750] = [__v_57, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[750].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[750].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[750].bump_multiplicity(__i); } let __ret: [G; OUT_750] = unsafe { *(record.function_queries[750].output_at(__i).as_ptr() as *const [G; OUT_750]) }; __ret }, _ => aiur_fn_750(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_66, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_67, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_748] = { let __args: [G; IN_748] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[748].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[748].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[748].bump_multiplicity(__i); } let __ret: [G; OUT_748] = unsafe { *(record.function_queries[748].output_at(__i).as_ptr() as *const [G; OUT_748]) }; __ret }, _ => aiur_fn_748(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_749] = { let __args: [G; IN_749] = [__v_57, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[749].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[749].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[749].bump_multiplicity(__i); } let __ret: [G; OUT_749] = unsafe { *(record.function_queries[749].output_at(__i).as_ptr() as *const [G; OUT_749]) }; __ret }, _ => aiur_fn_749(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_66, __v_15, __v_16]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_67, __v_17, __v_18]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64356,17 +64310,17 @@ fn aiur_fn_763( 1u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_57, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_90, __v_91, __v_92, __v_93, __v_94, __v_95, __v_96, __v_97, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_98, __v_51, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_757] = { let __args: [G; IN_757] = [__v_99, __v_53, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[757].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[757].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[757].bump_multiplicity(__i); } let __ret: [G; OUT_757] = unsafe { *(record.function_queries[757].output_at(__i).as_ptr() as *const [G; OUT_757]) }; __ret }, _ => aiur_fn_757(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_57, __v_4, __v_5]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_90, __v_91, __v_92, __v_93, __v_94, __v_95, __v_96, __v_97, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_98, __v_51, __v_52]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_756] = { let __args: [G; IN_756] = [__v_99, __v_53, __v_54]; let __cu = unconstrained; let __hit = record.function_queries[756].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[756].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[756].bump_multiplicity(__i); } let __ret: [G; OUT_756] = unsafe { *(record.function_queries[756].output_at(__i).as_ptr() as *const [G; OUT_756]) }; __ret }, _ => aiur_fn_756(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64381,11 +64335,11 @@ fn aiur_fn_763( 2u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_65, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_65, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64400,11 +64354,11 @@ fn aiur_fn_763( 3u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_751] = { let __args: [G; IN_751] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[751].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[751].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[751].bump_multiplicity(__i); } let __ret: [G; OUT_751] = unsafe { *(record.function_queries[751].output_at(__i).as_ptr() as *const [G; OUT_751]) }; __ret }, _ => aiur_fn_751(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_755] = { let __args: [G; IN_755] = [__v_65, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[755].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[755].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[755].bump_multiplicity(__i); } let __ret: [G; OUT_755] = unsafe { *(record.function_queries[755].output_at(__i).as_ptr() as *const [G; OUT_755]) }; __ret }, _ => aiur_fn_755(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_750] = { let __args: [G; IN_750] = [__v_56, __v_2, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[750].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[750].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[750].bump_multiplicity(__i); } let __ret: [G; OUT_750] = unsafe { *(record.function_queries[750].output_at(__i).as_ptr() as *const [G; OUT_750]) }; __ret }, _ => aiur_fn_750(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_65, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64419,11 +64373,11 @@ fn aiur_fn_763( 4u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_72, __v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_72, __v_20, __v_21]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64438,10 +64392,10 @@ fn aiur_fn_763( 5u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_64, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_64, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64456,10 +64410,10 @@ fn aiur_fn_763( 6u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_64, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_64, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64474,10 +64428,10 @@ fn aiur_fn_763( 7u64 => { match __v_56.as_canonical_u64() { _ => { - let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; - let __r_arr: [G; OUT_754] = { let __args: [G; IN_754] = [__v_64, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[754].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[754].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[754].bump_multiplicity(__i); } let __ret: [G; OUT_754] = unsafe { *(record.function_queries[754].output_at(__i).as_ptr() as *const [G; OUT_754]) }; __ret }, _ => aiur_fn_754(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_752] = { let __args: [G; IN_752] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10]; let __cu = unconstrained; let __hit = record.function_queries[752].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[752].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[752].bump_multiplicity(__i); } let __ret: [G; OUT_752] = unsafe { *(record.function_queries[752].output_at(__i).as_ptr() as *const [G; OUT_752]) }; __ret }, _ => aiur_fn_752(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_753] = { let __args: [G; IN_753] = [__v_64, __v_11, __v_12]; let __cu = unconstrained; let __hit = record.function_queries[753].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[753].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[753].bump_multiplicity(__i); } let __ret: [G; OUT_753] = unsafe { *(record.function_queries[753].output_at(__i).as_ptr() as *const [G; OUT_753]) }; __ret }, _ => aiur_fn_753(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -64490,9 +64444,9 @@ fn aiur_fn_763( 8u64 => { match __v_1.as_canonical_u64() { 8u64 => { - let __r_arr: [G; OUT_762] = { let __args: [G; IN_762] = [__v_56, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[762].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[762].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[762].bump_multiplicity(__i); } let __ret: [G; OUT_762] = unsafe { *(record.function_queries[762].output_at(__i).as_ptr() as *const [G; OUT_762]) }; __ret }, _ => aiur_fn_762(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_763] = []; - record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_761] = { let __args: [G; IN_761] = [__v_56, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[761].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[761].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[761].bump_multiplicity(__i); } let __ret: [G; OUT_761] = unsafe { *(record.function_queries[761].output_at(__i).as_ptr() as *const [G; OUT_761]) }; __ret }, _ => aiur_fn_761(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_762] = []; + record.function_queries[762].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -64509,41 +64463,41 @@ fn aiur_fn_763( }) } -const INPUT_SIZE_764: usize = 2; -const IN_764: usize = 2; -const OUT_764: usize = 0; -fn aiur_fn_764( - inp: [G; IN_764], +const INPUT_SIZE_763: usize = 2; +const IN_763: usize = 2; +const OUT_763: usize = 0; +fn aiur_fn_763( + inp: [G; IN_763], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_764], ExecError> { +) -> Result<[G; OUT_763], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_723] = { let __args: [G; IN_723] = [__v_0]; let __cu = unconstrained; let __hit = record.function_queries[723].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[723].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[723].bump_multiplicity(__i); } let __ret: [G; OUT_723] = unsafe { *(record.function_queries[723].output_at(__i).as_ptr() as *const [G; OUT_723]) }; __ret }, _ => aiur_fn_723(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; - let __r_arr: [G; OUT_416] = { let __args: [G; IN_416] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[416].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[416].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[416].bump_multiplicity(__i); } let __ret: [G; OUT_416] = unsafe { *(record.function_queries[416].output_at(__i).as_ptr() as *const [G; OUT_416]) }; __ret }, _ => aiur_fn_416(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_415] = { let __args: [G; IN_415] = [__v_1, __v_2]; let __cu = unconstrained; let __hit = record.function_queries[415].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[415].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[415].bump_multiplicity(__i); } let __ret: [G; OUT_415] = unsafe { *(record.function_queries[415].output_at(__i).as_ptr() as *const [G; OUT_415]) }; __ret }, _ => aiur_fn_415(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __v_4: G = G::from_u64(1); if (__v_3 != __v_4) { return Err(ExecError::AssertEqMismatch { lhs: __v_3.as_canonical_u64(), rhs: __v_4.as_canonical_u64(), msg: Some("Contains: target is not a leaf of the claimed tree".to_string()) }); } - let __ret: [G; OUT_764] = []; - record.function_queries[764].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_763] = []; + record.function_queries[763].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_765: usize = 8; -const IN_765: usize = 8; -const OUT_765: usize = 0; -fn aiur_fn_765( - inp: [G; IN_765], +const INPUT_SIZE_764: usize = 8; +const IN_764: usize = 8; +const OUT_764: usize = 0; +fn aiur_fn_764( + inp: [G; IN_764], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_765], ExecError> { +) -> Result<[G; OUT_764], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -64771,23 +64725,23 @@ fn aiur_fn_765( let __r_arr: [G; OUT_89] = { let __args: [G; IN_89] = [__v_177]; let __cu = unconstrained; let __hit = record.function_queries[89].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[89].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[89].bump_multiplicity(__i); } let __ret: [G; OUT_89] = unsafe { *(record.function_queries[89].output_at(__i).as_ptr() as *const [G; OUT_89]) }; __ret }, _ => aiur_fn_89(__args, record, io_buffer, __cu)? } }; let __v_186: G = __r_arr[0]; let __v_187: G = __r_arr[1]; - let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_187]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_730] = { let __args: [G; IN_730] = [__v_187]; let __cu = unconstrained; let __hit = record.function_queries[730].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[730].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[730].bump_multiplicity(__i); } let __ret: [G; OUT_730] = unsafe { *(record.function_queries[730].output_at(__i).as_ptr() as *const [G; OUT_730]) }; __ret }, _ => aiur_fn_730(__args, record, io_buffer, __cu)? } }; let __v_188: G = __r_arr[0]; let __v_189: G = __r_arr[1]; let __v_190: G = __r_arr[2]; match __v_188.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_717] = { let __args: [G; IN_717] = [__v_186]; let __cu = unconstrained; let __hit = record.function_queries[717].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[717].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[717].bump_multiplicity(__i); } let __ret: [G; OUT_717] = unsafe { *(record.function_queries[717].output_at(__i).as_ptr() as *const [G; OUT_717]) }; __ret }, _ => aiur_fn_717(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_765] = []; - record.function_queries[765].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_716] = { let __args: [G; IN_716] = [__v_186]; let __cu = unconstrained; let __hit = record.function_queries[716].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[716].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[716].bump_multiplicity(__i); } let __ret: [G; OUT_716] = unsafe { *(record.function_queries[716].output_at(__i).as_ptr() as *const [G; OUT_716]) }; __ret }, _ => aiur_fn_716(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_764] = []; + record.function_queries[764].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_189]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_723] = { let __args: [G; IN_723] = [__v_189]; let __cu = unconstrained; let __hit = record.function_queries[723].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[723].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[723].bump_multiplicity(__i); } let __ret: [G; OUT_723] = unsafe { *(record.function_queries[723].output_at(__i).as_ptr() as *const [G; OUT_723]) }; __ret }, _ => aiur_fn_723(__args, record, io_buffer, __cu)? } }; let __v_191: G = __r_arr[0]; let __v_192: G = G::from_u64(1); let __v_193: G = G::from_u64(1); - let __r_arr: [G; OUT_725] = { let __args: [G; IN_725] = [__v_191, __v_192, __v_193, __v_193, __v_193, __v_193, __v_193]; let __cu = unconstrained; let __hit = record.function_queries[725].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[725].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[725].bump_multiplicity(__i); } let __ret: [G; OUT_725] = unsafe { *(record.function_queries[725].output_at(__i).as_ptr() as *const [G; OUT_725]) }; __ret }, _ => aiur_fn_725(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_724] = { let __args: [G; IN_724] = [__v_191, __v_192, __v_193, __v_193, __v_193, __v_193, __v_193]; let __cu = unconstrained; let __hit = record.function_queries[724].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[724].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[724].bump_multiplicity(__i); } let __ret: [G; OUT_724] = unsafe { *(record.function_queries[724].output_at(__i).as_ptr() as *const [G; OUT_724]) }; __ret }, _ => aiur_fn_724(__args, record, io_buffer, __cu)? } }; let __v_194: G = __r_arr[0]; let __v_195: G = __r_arr[1]; let __v_196: G = __r_arr[2]; @@ -64797,9 +64751,9 @@ fn aiur_fn_765( let __v_200: G = G::from_u64(1); let __v_201: G = G::from_u64(1); let __v_202: G = G::from_u64(0); - let __r_arr: [G; OUT_727] = { let __args: [G; IN_727] = [__v_186, __v_200, __v_201, __v_201, __v_201, __v_201, __v_201, __v_194, __v_195, __v_196, __v_197, __v_198, __v_199, __v_202]; let __cu = unconstrained; let __hit = record.function_queries[727].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[727].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[727].bump_multiplicity(__i); } let __ret: [G; OUT_727] = unsafe { *(record.function_queries[727].output_at(__i).as_ptr() as *const [G; OUT_727]) }; __ret }, _ => aiur_fn_727(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_765] = []; - record.function_queries[765].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_726] = { let __args: [G; IN_726] = [__v_186, __v_200, __v_201, __v_201, __v_201, __v_201, __v_201, __v_194, __v_195, __v_196, __v_197, __v_198, __v_199, __v_202]; let __cu = unconstrained; let __hit = record.function_queries[726].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[726].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[726].bump_multiplicity(__i); } let __ret: [G; OUT_726] = unsafe { *(record.function_queries[726].output_at(__i).as_ptr() as *const [G; OUT_726]) }; __ret }, _ => aiur_fn_726(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_764] = []; + record.function_queries[764].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -64811,20 +64765,20 @@ fn aiur_fn_765( let __r_arr: [G; OUT_89] = { let __args: [G; IN_89] = [__v_177]; let __cu = unconstrained; let __hit = record.function_queries[89].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[89].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[89].bump_multiplicity(__i); } let __ret: [G; OUT_89] = unsafe { *(record.function_queries[89].output_at(__i).as_ptr() as *const [G; OUT_89]) }; __ret }, _ => aiur_fn_89(__args, record, io_buffer, __cu)? } }; let __v_186: G = __r_arr[0]; let __v_187: G = __r_arr[1]; - let __r_arr: [G; OUT_731] = { let __args: [G; IN_731] = [__v_187]; let __cu = unconstrained; let __hit = record.function_queries[731].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[731].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[731].bump_multiplicity(__i); } let __ret: [G; OUT_731] = unsafe { *(record.function_queries[731].output_at(__i).as_ptr() as *const [G; OUT_731]) }; __ret }, _ => aiur_fn_731(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_730] = { let __args: [G; IN_730] = [__v_187]; let __cu = unconstrained; let __hit = record.function_queries[730].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[730].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[730].bump_multiplicity(__i); } let __ret: [G; OUT_730] = unsafe { *(record.function_queries[730].output_at(__i).as_ptr() as *const [G; OUT_730]) }; __ret }, _ => aiur_fn_730(__args, record, io_buffer, __cu)? } }; let __v_188: G = __r_arr[0]; let __v_189: G = __r_arr[1]; let __v_190: G = __r_arr[2]; - let __r_arr: [G; OUT_730] = { let __args: [G; IN_730] = [__v_186, __v_188, __v_189]; let __cu = unconstrained; let __hit = record.function_queries[730].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[730].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[730].bump_multiplicity(__i); } let __ret: [G; OUT_730] = unsafe { *(record.function_queries[730].output_at(__i).as_ptr() as *const [G; OUT_730]) }; __ret }, _ => aiur_fn_730(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_765] = []; - record.function_queries[765].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_729] = { let __args: [G; IN_729] = [__v_186, __v_188, __v_189]; let __cu = unconstrained; let __hit = record.function_queries[729].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[729].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[729].bump_multiplicity(__i); } let __ret: [G; OUT_729] = unsafe { *(record.function_queries[729].output_at(__i).as_ptr() as *const [G; OUT_729]) }; __ret }, _ => aiur_fn_729(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_764] = []; + record.function_queries[764].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 6u64 => { let __r_arr: [G; OUT_89] = { let __args: [G; IN_89] = [__v_177]; let __cu = unconstrained; let __hit = record.function_queries[89].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[89].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[89].bump_multiplicity(__i); } let __ret: [G; OUT_89] = unsafe { *(record.function_queries[89].output_at(__i).as_ptr() as *const [G; OUT_89]) }; __ret }, _ => aiur_fn_89(__args, record, io_buffer, __cu)? } }; let __v_186: G = __r_arr[0]; let __v_187: G = __r_arr[1]; - let __r_arr: [G; OUT_746] = { let __args: [G; IN_746] = [__v_187]; let __cu = unconstrained; let __hit = record.function_queries[746].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[746].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[746].bump_multiplicity(__i); } let __ret: [G; OUT_746] = unsafe { *(record.function_queries[746].output_at(__i).as_ptr() as *const [G; OUT_746]) }; __ret }, _ => aiur_fn_746(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_745] = { let __args: [G; IN_745] = [__v_187]; let __cu = unconstrained; let __hit = record.function_queries[745].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[745].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[745].bump_multiplicity(__i); } let __ret: [G; OUT_745] = unsafe { *(record.function_queries[745].output_at(__i).as_ptr() as *const [G; OUT_745]) }; __ret }, _ => aiur_fn_745(__args, record, io_buffer, __cu)? } }; let __v_188: G = __r_arr[0]; let __v_189: G = __r_arr[1]; let __v_190: G = __r_arr[2]; @@ -64880,9 +64834,9 @@ fn aiur_fn_765( let __v_240: G = __r_arr[52]; let __v_241: G = __r_arr[53]; let __v_242: G = __r_arr[54]; - let __r_arr: [G; OUT_763] = { let __args: [G; IN_763] = [__v_186, __v_188, __v_189, __v_190, __v_191, __v_192, __v_193, __v_194, __v_195, __v_196, __v_197, __v_198, __v_199, __v_200, __v_201, __v_202, __v_203, __v_204, __v_205, __v_206, __v_207, __v_208, __v_209, __v_210, __v_211, __v_212, __v_213, __v_214, __v_215, __v_216, __v_217, __v_218, __v_219, __v_220, __v_221, __v_222, __v_223, __v_224, __v_225, __v_226, __v_227, __v_228, __v_229, __v_230, __v_231, __v_232, __v_233, __v_234, __v_235, __v_236, __v_237, __v_238, __v_239, __v_240, __v_241]; let __cu = unconstrained; let __hit = record.function_queries[763].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[763].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[763].bump_multiplicity(__i); } let __ret: [G; OUT_763] = unsafe { *(record.function_queries[763].output_at(__i).as_ptr() as *const [G; OUT_763]) }; __ret }, _ => aiur_fn_763(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_765] = []; - record.function_queries[765].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_762] = { let __args: [G; IN_762] = [__v_186, __v_188, __v_189, __v_190, __v_191, __v_192, __v_193, __v_194, __v_195, __v_196, __v_197, __v_198, __v_199, __v_200, __v_201, __v_202, __v_203, __v_204, __v_205, __v_206, __v_207, __v_208, __v_209, __v_210, __v_211, __v_212, __v_213, __v_214, __v_215, __v_216, __v_217, __v_218, __v_219, __v_220, __v_221, __v_222, __v_223, __v_224, __v_225, __v_226, __v_227, __v_228, __v_229, __v_230, __v_231, __v_232, __v_233, __v_234, __v_235, __v_236, __v_237, __v_238, __v_239, __v_240, __v_241]; let __cu = unconstrained; let __hit = record.function_queries[762].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[762].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[762].bump_multiplicity(__i); } let __ret: [G; OUT_762] = unsafe { *(record.function_queries[762].output_at(__i).as_ptr() as *const [G; OUT_762]) }; __ret }, _ => aiur_fn_762(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_764] = []; + record.function_queries[764].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 7u64 => { @@ -64892,9 +64846,9 @@ fn aiur_fn_765( let __r_arr: [G; OUT_89] = { let __args: [G; IN_89] = [__v_187]; let __cu = unconstrained; let __hit = record.function_queries[89].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[89].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[89].bump_multiplicity(__i); } let __ret: [G; OUT_89] = unsafe { *(record.function_queries[89].output_at(__i).as_ptr() as *const [G; OUT_89]) }; __ret }, _ => aiur_fn_89(__args, record, io_buffer, __cu)? } }; let __v_188: G = __r_arr[0]; let __v_189: G = __r_arr[1]; - let __r_arr: [G; OUT_764] = { let __args: [G; IN_764] = [__v_186, __v_188]; let __cu = unconstrained; let __hit = record.function_queries[764].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[764].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[764].bump_multiplicity(__i); } let __ret: [G; OUT_764] = unsafe { *(record.function_queries[764].output_at(__i).as_ptr() as *const [G; OUT_764]) }; __ret }, _ => aiur_fn_764(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_765] = []; - record.function_queries[765].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_763] = { let __args: [G; IN_763] = [__v_186, __v_188]; let __cu = unconstrained; let __hit = record.function_queries[763].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[763].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[763].bump_multiplicity(__i); } let __ret: [G; OUT_763] = unsafe { *(record.function_queries[763].output_at(__i).as_ptr() as *const [G; OUT_763]) }; __ret }, _ => aiur_fn_763(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_764] = []; + record.function_queries[764].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -64904,15 +64858,15 @@ fn aiur_fn_765( }) } -const INPUT_SIZE_766: usize = 8; -const IN_766: usize = 8; -const OUT_766: usize = 0; -fn aiur_fn_766( - inp: [G; IN_766], +const INPUT_SIZE_765: usize = 8; +const IN_765: usize = 8; +const OUT_765: usize = 0; +fn aiur_fn_765( + inp: [G; IN_765], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_766], ExecError> { +) -> Result<[G; OUT_765], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -64922,27 +64876,27 @@ fn aiur_fn_766( let __v_5: G = inp[5]; let __v_6: G = inp[6]; let __v_7: G = inp[7]; - let __r_arr: [G; OUT_765] = { let __args: [G; IN_765] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[765].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[765].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[765].bump_multiplicity(__i); } let __ret: [G; OUT_765] = unsafe { *(record.function_queries[765].output_at(__i).as_ptr() as *const [G; OUT_765]) }; __ret }, _ => aiur_fn_765(__args, record, io_buffer, __cu)? } }; - let __ret: [G; OUT_766] = []; - record.function_queries[766].finish(&inp[..], &__ret[..], !unconstrained); + let __r_arr: [G; OUT_764] = { let __args: [G; IN_764] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[764].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[764].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[764].bump_multiplicity(__i); } let __ret: [G; OUT_764] = unsafe { *(record.function_queries[764].output_at(__i).as_ptr() as *const [G; OUT_764]) }; __ret }, _ => aiur_fn_764(__args, record, io_buffer, __cu)? } }; + let __ret: [G; OUT_765] = []; + record.function_queries[765].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_767: usize = 3; -const IN_767: usize = 3; -const OUT_767: usize = 1; -fn aiur_fn_767( - inp: [G; IN_767], +const INPUT_SIZE_766: usize = 3; +const IN_766: usize = 3; +const OUT_766: usize = 1; +fn aiur_fn_766( + inp: [G; IN_766], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_767], ExecError> { +) -> Result<[G; OUT_766], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; let __v_2: G = inp[2]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_3: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_3.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_4: G = __loaded[0]; @@ -64950,13 +64904,13 @@ fn aiur_fn_767( let __v_6: G = __loaded[2]; match __v_4.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_767] = [__v_2]; - record.function_queries[767].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_766] = [__v_2]; + record.function_queries[766].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __ret: [G; OUT_767] = [__v_5]; - record.function_queries[767].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_766] = [__v_5]; + record.function_queries[766].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -64966,15 +64920,15 @@ fn aiur_fn_767( }) } -const INPUT_SIZE_768: usize = 2; -const IN_768: usize = 2; -const OUT_768: usize = 1; -fn aiur_fn_768( - inp: [G; IN_768], +const INPUT_SIZE_767: usize = 2; +const IN_767: usize = 2; +const OUT_767: usize = 1; +fn aiur_fn_767( + inp: [G; IN_767], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_768], ExecError> { +) -> Result<[G; OUT_767], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -64989,17 +64943,17 @@ fn aiur_fn_768( let __v_7: G = G::from_u64(1); let __v_8: G = { let __values: [G; 3] = [__v_6, __v_7, __v_7]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_9: G = { let __values: [G; 3] = [__v_5, __v_1, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_768] = [__v_9]; - record.function_queries[768].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_767] = [__v_9]; + record.function_queries[767].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_768] = { let __args: [G; IN_768] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[768].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[768].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[768].bump_multiplicity(__i); } let __ret: [G; OUT_768] = unsafe { *(record.function_queries[768].output_at(__i).as_ptr() as *const [G; OUT_768]) }; __ret }, _ => aiur_fn_768(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_767] = { let __args: [G; IN_767] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[767].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[767].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[767].bump_multiplicity(__i); } let __ret: [G; OUT_767] = unsafe { *(record.function_queries[767].output_at(__i).as_ptr() as *const [G; OUT_767]) }; __ret }, _ => aiur_fn_767(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = { let __values: [G; 3] = [__v_5, __v_3, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_768] = [__v_7]; - record.function_queries[768].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_767] = [__v_7]; + record.function_queries[767].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65009,15 +64963,15 @@ fn aiur_fn_768( }) } -const INPUT_SIZE_769: usize = 1; -const IN_769: usize = 1; -const OUT_769: usize = 8; -fn aiur_fn_769( - inp: [G; IN_769], +const INPUT_SIZE_768: usize = 1; +const IN_768: usize = 1; +const OUT_768: usize = 8; +fn aiur_fn_768( + inp: [G; IN_768], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_769], ExecError> { +) -> Result<[G; OUT_768], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 10] = { let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 10 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 10] = __args[..10].try_into().unwrap(); __arr }; @@ -65041,12 +64995,12 @@ fn aiur_fn_769( let __v_16: G = G::from_u64(0); let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); - let __ret: [G; OUT_769] = [__v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; - record.function_queries[769].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_768] = [__v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18]; + record.function_queries[768].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_769] = { let __args: [G; IN_769] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[769].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[769].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[769].bump_multiplicity(__i); } let __ret: [G; OUT_769] = unsafe { *(record.function_queries[769].output_at(__i).as_ptr() as *const [G; OUT_769]) }; __ret }, _ => aiur_fn_769(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_768] = { let __args: [G; IN_768] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[768].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[768].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[768].bump_multiplicity(__i); } let __ret: [G; OUT_768] = unsafe { *(record.function_queries[768].output_at(__i).as_ptr() as *const [G; OUT_768]) }; __ret }, _ => aiur_fn_768(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = __r_arr[1]; let __v_13: G = __r_arr[2]; @@ -65064,8 +65018,8 @@ fn aiur_fn_769( let __v_24: G = __r_arr[5]; let __v_25: G = __r_arr[6]; let __v_26: G = __r_arr[7]; - let __ret: [G; OUT_769] = [__v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26]; - record.function_queries[769].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_768] = [__v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26]; + record.function_queries[768].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65075,15 +65029,15 @@ fn aiur_fn_769( }) } -const INPUT_SIZE_770: usize = 2; -const IN_770: usize = 2; -const OUT_770: usize = 1; -fn aiur_fn_770( - inp: [G; IN_770], +const INPUT_SIZE_769: usize = 2; +const IN_769: usize = 2; +const OUT_769: usize = 1; +fn aiur_fn_769( + inp: [G; IN_769], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_770], ExecError> { +) -> Result<[G; OUT_769], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -65094,17 +65048,17 @@ fn aiur_fn_770( let __v_5: G = __loaded[3]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_770] = [__v_1]; - record.function_queries[770].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_769] = [__v_1]; + record.function_queries[769].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_6: G = G::from_u64(0); - let __r_arr: [G; OUT_770] = { let __args: [G; IN_770] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[770].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[770].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[770].bump_multiplicity(__i); } let __ret: [G; OUT_770] = unsafe { *(record.function_queries[770].output_at(__i).as_ptr() as *const [G; OUT_770]) }; __ret }, _ => aiur_fn_770(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_769] = { let __args: [G; IN_769] = [__v_5, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[769].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[769].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[769].bump_multiplicity(__i); } let __ret: [G; OUT_769] = unsafe { *(record.function_queries[769].output_at(__i).as_ptr() as *const [G; OUT_769]) }; __ret }, _ => aiur_fn_769(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = { let __values: [G; 4] = [__v_6, __v_3, __v_4, __v_7]; let __mq = record.memory_queries.get_mut(&4).ok_or(ExecError::InvalidMemorySize(4))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_770] = [__v_8]; - record.function_queries[770].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_769] = [__v_8]; + record.function_queries[769].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65114,15 +65068,15 @@ fn aiur_fn_770( }) } -const INPUT_SIZE_771: usize = 1; -const IN_771: usize = 1; -const OUT_771: usize = 8; -fn aiur_fn_771( - inp: [G; IN_771], +const INPUT_SIZE_770: usize = 1; +const IN_770: usize = 1; +const OUT_770: usize = 8; +fn aiur_fn_770( + inp: [G; IN_770], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_771], ExecError> { +) -> Result<[G; OUT_770], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -65139,12 +65093,12 @@ fn aiur_fn_771( let __v_9: G = G::from_u64(0); let __v_10: G = G::from_u64(0); let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_771] = [__v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; - record.function_queries[771].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_770] = [__v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11]; + record.function_queries[770].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_771] = { let __args: [G; IN_771] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[771].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[771].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[771].bump_multiplicity(__i); } let __ret: [G; OUT_771] = unsafe { *(record.function_queries[771].output_at(__i).as_ptr() as *const [G; OUT_771]) }; __ret }, _ => aiur_fn_771(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_770] = { let __args: [G; IN_770] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[770].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[770].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[770].bump_multiplicity(__i); } let __ret: [G; OUT_770] = unsafe { *(record.function_queries[770].output_at(__i).as_ptr() as *const [G; OUT_770]) }; __ret }, _ => aiur_fn_770(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = __r_arr[1]; let __v_6: G = __r_arr[2]; @@ -65162,8 +65116,8 @@ fn aiur_fn_771( let __v_17: G = __r_arr[5]; let __v_18: G = __r_arr[6]; let __v_19: G = __r_arr[7]; - let __ret: [G; OUT_771] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; - record.function_queries[771].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_770] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; + record.function_queries[770].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65173,15 +65127,15 @@ fn aiur_fn_771( }) } -const INPUT_SIZE_772: usize = 8; -const IN_772: usize = 8; -const OUT_772: usize = 1; -fn aiur_fn_772( - inp: [G; IN_772], +const INPUT_SIZE_771: usize = 8; +const IN_771: usize = 8; +const OUT_771: usize = 1; +fn aiur_fn_771( + inp: [G; IN_771], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_772], ExecError> { +) -> Result<[G; OUT_771], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -65193,8 +65147,8 @@ fn aiur_fn_772( let __v_7: G = inp[7]; match __v_1.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_772] = [__v_7]; - record.function_queries[772].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_771] = [__v_7]; + record.function_queries[771].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -65215,25 +65169,25 @@ fn aiur_fn_772( let __v_20: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_3.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_20.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_0, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_771] = { let __args: [G; IN_771] = [__v_0, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[771].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[771].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[771].bump_multiplicity(__i); } let __ret: [G; OUT_771] = unsafe { *(record.function_queries[771].output_at(__i).as_ptr() as *const [G; OUT_771]) }; __ret }, _ => aiur_fn_771(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; - let __ret: [G; OUT_772] = [__v_21]; - record.function_queries[772].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_771] = [__v_21]; + record.function_queries[771].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_21: G = (__v_0 - __v_3); match __v_21.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_772] = [__v_4]; - record.function_queries[772].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_771] = [__v_4]; + record.function_queries[771].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_772] = { let __args: [G; IN_772] = [__v_0, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[772].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[772].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[772].bump_multiplicity(__i); } let __ret: [G; OUT_772] = unsafe { *(record.function_queries[772].output_at(__i).as_ptr() as *const [G; OUT_772]) }; __ret }, _ => aiur_fn_772(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_771] = { let __args: [G; IN_771] = [__v_0, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[771].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[771].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[771].bump_multiplicity(__i); } let __ret: [G; OUT_771] = unsafe { *(record.function_queries[771].output_at(__i).as_ptr() as *const [G; OUT_771]) }; __ret }, _ => aiur_fn_771(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; - let __ret: [G; OUT_772] = [__v_22]; - record.function_queries[772].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_771] = [__v_22]; + record.function_queries[771].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -65247,37 +65201,37 @@ fn aiur_fn_772( }) } -const INPUT_SIZE_773: usize = 1; -const IN_773: usize = 1; -const OUT_773: usize = 1; -fn aiur_fn_773( - inp: [G; IN_773], +const INPUT_SIZE_772: usize = 1; +const IN_772: usize = 1; +const OUT_772: usize = 1; +fn aiur_fn_772( + inp: [G; IN_772], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_773], ExecError> { +) -> Result<[G; OUT_772], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = G::from_u64(1); let __v_2: G = G::from_u64(1); let __v_3: G = { let __values: [G; 3] = [__v_1, __v_2, __v_2]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_790] = { let __args: [G; IN_790] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[790].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[790].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[790].bump_multiplicity(__i); } let __ret: [G; OUT_790] = unsafe { *(record.function_queries[790].output_at(__i).as_ptr() as *const [G; OUT_790]) }; __ret }, _ => aiur_fn_790(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_789] = { let __args: [G; IN_789] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[789].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[789].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[789].bump_multiplicity(__i); } let __ret: [G; OUT_789] = unsafe { *(record.function_queries[789].output_at(__i).as_ptr() as *const [G; OUT_789]) }; __ret }, _ => aiur_fn_789(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; - let __ret: [G; OUT_773] = [__v_4]; - record.function_queries[773].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_772] = [__v_4]; + record.function_queries[772].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }) } -const INPUT_SIZE_774: usize = 2; -const IN_774: usize = 2; -const OUT_774: usize = 1; -fn aiur_fn_774( - inp: [G; IN_774], +const INPUT_SIZE_773: usize = 2; +const IN_773: usize = 2; +const OUT_773: usize = 1; +fn aiur_fn_773( + inp: [G; IN_773], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_774], ExecError> { +) -> Result<[G; OUT_773], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -65287,17 +65241,17 @@ fn aiur_fn_774( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_774] = [__v_1]; - record.function_queries[774].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_773] = [__v_1]; + record.function_queries[773].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(0); - let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_773] = { let __args: [G; IN_773] = [__v_4, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[773].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[773].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[773].bump_multiplicity(__i); } let __ret: [G; OUT_773] = unsafe { *(record.function_queries[773].output_at(__i).as_ptr() as *const [G; OUT_773]) }; __ret }, _ => aiur_fn_773(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = { let __values: [G; 3] = [__v_5, __v_3, __v_6]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_774] = [__v_7]; - record.function_queries[774].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_773] = [__v_7]; + record.function_queries[773].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65307,15 +65261,15 @@ fn aiur_fn_774( }) } -const INPUT_SIZE_775: usize = 1; -const IN_775: usize = 1; -const OUT_775: usize = 1; -fn aiur_fn_775( - inp: [G; IN_775], +const INPUT_SIZE_774: usize = 1; +const IN_774: usize = 1; +const OUT_774: usize = 1; +fn aiur_fn_774( + inp: [G; IN_774], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_775], ExecError> { +) -> Result<[G; OUT_774], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -65325,17 +65279,17 @@ fn aiur_fn_775( match __v_1.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_775] = [__v_4]; - record.function_queries[775].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_774] = [__v_4]; + record.function_queries[774].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_774] = { let __args: [G; IN_774] = [__v_3]; let __cu = unconstrained; let __hit = record.function_queries[774].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[774].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[774].bump_multiplicity(__i); } let __ret: [G; OUT_774] = unsafe { *(record.function_queries[774].output_at(__i).as_ptr() as *const [G; OUT_774]) }; __ret }, _ => aiur_fn_774(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __v_5: G = G::from_u64(1); let __v_6: G = (__v_4 + __v_5); - let __ret: [G; OUT_775] = [__v_6]; - record.function_queries[775].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_774] = [__v_6]; + record.function_queries[774].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65345,15 +65299,15 @@ fn aiur_fn_775( }) } -const INPUT_SIZE_776: usize = 1; -const IN_776: usize = 1; -const OUT_776: usize = 8; -fn aiur_fn_776( - inp: [G; IN_776], +const INPUT_SIZE_775: usize = 1; +const IN_775: usize = 1; +const OUT_775: usize = 8; +fn aiur_fn_775( + inp: [G; IN_775], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_776], ExecError> { +) -> Result<[G; OUT_775], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 36] = { let __mq = record.memory_queries.get_mut(&36).ok_or(ExecError::InvalidMemorySize(36))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 36 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 36] = __args[..36].try_into().unwrap(); __arr }; @@ -65403,12 +65357,12 @@ fn aiur_fn_776( let __v_42: G = G::from_u64(0); let __v_43: G = G::from_u64(0); let __v_44: G = G::from_u64(0); - let __ret: [G; OUT_776] = [__v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44]; - record.function_queries[776].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_775] = [__v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44]; + record.function_queries[775].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_776] = { let __args: [G; IN_776] = [__v_36]; let __cu = unconstrained; let __hit = record.function_queries[776].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[776].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[776].bump_multiplicity(__i); } let __ret: [G; OUT_776] = unsafe { *(record.function_queries[776].output_at(__i).as_ptr() as *const [G; OUT_776]) }; __ret }, _ => aiur_fn_776(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_775] = { let __args: [G; IN_775] = [__v_36]; let __cu = unconstrained; let __hit = record.function_queries[775].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[775].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[775].bump_multiplicity(__i); } let __ret: [G; OUT_775] = unsafe { *(record.function_queries[775].output_at(__i).as_ptr() as *const [G; OUT_775]) }; __ret }, _ => aiur_fn_775(__args, record, io_buffer, __cu)? } }; let __v_37: G = __r_arr[0]; let __v_38: G = __r_arr[1]; let __v_39: G = __r_arr[2]; @@ -65426,8 +65380,8 @@ fn aiur_fn_776( let __v_50: G = __r_arr[5]; let __v_51: G = __r_arr[6]; let __v_52: G = __r_arr[7]; - let __ret: [G; OUT_776] = [__v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52]; - record.function_queries[776].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_775] = [__v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52]; + record.function_queries[775].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65437,19 +65391,19 @@ fn aiur_fn_776( }) } -const INPUT_SIZE_777: usize = 2; -const IN_777: usize = 2; -const OUT_777: usize = 1; -fn aiur_fn_777( - inp: [G; IN_777], +const INPUT_SIZE_776: usize = 2; +const IN_776: usize = 2; +const OUT_776: usize = 1; +fn aiur_fn_776( + inp: [G; IN_776], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_777], ExecError> { +) -> Result<[G; OUT_776], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_1]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_2: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_2.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_3: G = __loaded[0]; @@ -65457,8 +65411,8 @@ fn aiur_fn_777( let __v_5: G = __loaded[2]; match __v_3.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_777] = [__v_4]; - record.function_queries[777].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_776] = [__v_4]; + record.function_queries[776].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65468,15 +65422,15 @@ fn aiur_fn_777( }) } -const INPUT_SIZE_778: usize = 1; -const IN_778: usize = 1; -const OUT_778: usize = 1; -fn aiur_fn_778( - inp: [G; IN_778], +const INPUT_SIZE_777: usize = 1; +const IN_777: usize = 1; +const OUT_777: usize = 1; +fn aiur_fn_777( + inp: [G; IN_777], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_778], ExecError> { +) -> Result<[G; OUT_777], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 10] = { let __mq = record.memory_queries.get_mut(&10).ok_or(ExecError::InvalidMemorySize(10))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 10 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 10] = __args[..10].try_into().unwrap(); __arr }; @@ -65493,17 +65447,17 @@ fn aiur_fn_778( match __v_1.as_canonical_u64() { 1u64 => { let __v_11: G = G::from_u64(0); - let __ret: [G; OUT_778] = [__v_11]; - record.function_queries[778].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_777] = [__v_11]; + record.function_queries[777].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_778] = { let __args: [G; IN_778] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[778].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[778].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[778].bump_multiplicity(__i); } let __ret: [G; OUT_778] = unsafe { *(record.function_queries[778].output_at(__i).as_ptr() as *const [G; OUT_778]) }; __ret }, _ => aiur_fn_778(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_777] = { let __args: [G; IN_777] = [__v_10]; let __cu = unconstrained; let __hit = record.function_queries[777].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[777].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[777].bump_multiplicity(__i); } let __ret: [G; OUT_777] = unsafe { *(record.function_queries[777].output_at(__i).as_ptr() as *const [G; OUT_777]) }; __ret }, _ => aiur_fn_777(__args, record, io_buffer, __cu)? } }; let __v_11: G = __r_arr[0]; let __v_12: G = G::from_u64(1); let __v_13: G = (__v_11 + __v_12); - let __ret: [G; OUT_778] = [__v_13]; - record.function_queries[778].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_777] = [__v_13]; + record.function_queries[777].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65513,15 +65467,15 @@ fn aiur_fn_778( }) } -const INPUT_SIZE_779: usize = 9; -const IN_779: usize = 9; -const OUT_779: usize = 45; -fn aiur_fn_779( - inp: [G; IN_779], +const INPUT_SIZE_778: usize = 9; +const IN_778: usize = 9; +const OUT_778: usize = 45; +fn aiur_fn_778( + inp: [G; IN_778], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_779], ExecError> { +) -> Result<[G; OUT_778], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -65586,8 +65540,8 @@ fn aiur_fn_779( let __v_56: G = __r_arr[0]; match __v_56.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_779] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54]; - record.function_queries[779].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_778] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43, __v_44, __v_45, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54]; + record.function_queries[778].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -65600,7 +65554,7 @@ fn aiur_fn_779( let __v_62: G = __r_arr[5]; let __v_63: G = __r_arr[6]; let __v_64: G = __r_arr[7]; - let __r_arr: [G; OUT_779] = { let __args: [G; IN_779] = [__v_55, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64]; let __cu = unconstrained; let __hit = record.function_queries[779].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[779].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[779].bump_multiplicity(__i); } let __ret: [G; OUT_779] = unsafe { *(record.function_queries[779].output_at(__i).as_ptr() as *const [G; OUT_779]) }; __ret }, _ => aiur_fn_779(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_778] = { let __args: [G; IN_778] = [__v_55, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64]; let __cu = unconstrained; let __hit = record.function_queries[778].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[778].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[778].bump_multiplicity(__i); } let __ret: [G; OUT_778] = unsafe { *(record.function_queries[778].output_at(__i).as_ptr() as *const [G; OUT_778]) }; __ret }, _ => aiur_fn_778(__args, record, io_buffer, __cu)? } }; let __v_65: G = __r_arr[0]; let __v_66: G = __r_arr[1]; let __v_67: G = __r_arr[2]; @@ -65646,8 +65600,8 @@ fn aiur_fn_779( let __v_107: G = __r_arr[42]; let __v_108: G = __r_arr[43]; let __v_109: G = __r_arr[44]; - let __ret: [G; OUT_779] = [__v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_95, __v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107, __v_108, __v_109]; - record.function_queries[779].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_778] = [__v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87, __v_88, __v_89, __v_90, __v_91, __v_92, __v_93, __v_94, __v_95, __v_96, __v_97, __v_98, __v_99, __v_100, __v_101, __v_102, __v_103, __v_104, __v_105, __v_106, __v_107, __v_108, __v_109]; + record.function_queries[778].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65662,15 +65616,15 @@ fn aiur_fn_779( }) } -const INPUT_SIZE_780: usize = 1; -const IN_780: usize = 1; -const OUT_780: usize = 8; -fn aiur_fn_780( - inp: [G; IN_780], +const INPUT_SIZE_779: usize = 1; +const IN_779: usize = 1; +const OUT_779: usize = 8; +fn aiur_fn_779( + inp: [G; IN_779], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_780], ExecError> { +) -> Result<[G; OUT_779], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 47] = { let __mq = record.memory_queries.get_mut(&47).ok_or(ExecError::InvalidMemorySize(47))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 47 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 47] = __args[..47].try_into().unwrap(); __arr }; @@ -65731,12 +65685,12 @@ fn aiur_fn_780( let __v_53: G = G::from_u64(0); let __v_54: G = G::from_u64(0); let __v_55: G = G::from_u64(0); - let __ret: [G; OUT_780] = [__v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55]; - record.function_queries[780].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_779] = [__v_48, __v_49, __v_50, __v_51, __v_52, __v_53, __v_54, __v_55]; + record.function_queries[779].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_780] = { let __args: [G; IN_780] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[780].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[780].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[780].bump_multiplicity(__i); } let __ret: [G; OUT_780] = unsafe { *(record.function_queries[780].output_at(__i).as_ptr() as *const [G; OUT_780]) }; __ret }, _ => aiur_fn_780(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_779] = { let __args: [G; IN_779] = [__v_47]; let __cu = unconstrained; let __hit = record.function_queries[779].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[779].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[779].bump_multiplicity(__i); } let __ret: [G; OUT_779] = unsafe { *(record.function_queries[779].output_at(__i).as_ptr() as *const [G; OUT_779]) }; __ret }, _ => aiur_fn_779(__args, record, io_buffer, __cu)? } }; let __v_48: G = __r_arr[0]; let __v_49: G = __r_arr[1]; let __v_50: G = __r_arr[2]; @@ -65754,8 +65708,8 @@ fn aiur_fn_780( let __v_61: G = __r_arr[5]; let __v_62: G = __r_arr[6]; let __v_63: G = __r_arr[7]; - let __ret: [G; OUT_780] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63]; - record.function_queries[780].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_779] = [__v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63]; + record.function_queries[779].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65765,15 +65719,15 @@ fn aiur_fn_780( }) } -const INPUT_SIZE_781: usize = 1; -const IN_781: usize = 1; -const OUT_781: usize = 8; -fn aiur_fn_781( - inp: [G; IN_781], +const INPUT_SIZE_780: usize = 1; +const IN_780: usize = 1; +const OUT_780: usize = 8; +fn aiur_fn_780( + inp: [G; IN_780], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_781], ExecError> { +) -> Result<[G; OUT_780], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 11] = { let __mq = record.memory_queries.get_mut(&11).ok_or(ExecError::InvalidMemorySize(11))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 11 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 11] = __args[..11].try_into().unwrap(); __arr }; @@ -65798,12 +65752,12 @@ fn aiur_fn_781( let __v_17: G = G::from_u64(0); let __v_18: G = G::from_u64(0); let __v_19: G = G::from_u64(0); - let __ret: [G; OUT_781] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; - record.function_queries[781].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_780] = [__v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; + record.function_queries[780].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_781] = { let __args: [G; IN_781] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[781].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[781].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[781].bump_multiplicity(__i); } let __ret: [G; OUT_781] = unsafe { *(record.function_queries[781].output_at(__i).as_ptr() as *const [G; OUT_781]) }; __ret }, _ => aiur_fn_781(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_780] = { let __args: [G; IN_780] = [__v_11]; let __cu = unconstrained; let __hit = record.function_queries[780].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[780].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[780].bump_multiplicity(__i); } let __ret: [G; OUT_780] = unsafe { *(record.function_queries[780].output_at(__i).as_ptr() as *const [G; OUT_780]) }; __ret }, _ => aiur_fn_780(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = __r_arr[1]; let __v_14: G = __r_arr[2]; @@ -65821,8 +65775,8 @@ fn aiur_fn_781( let __v_25: G = __r_arr[5]; let __v_26: G = __r_arr[6]; let __v_27: G = __r_arr[7]; - let __ret: [G; OUT_781] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27]; - record.function_queries[781].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_780] = [__v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27]; + record.function_queries[780].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65832,15 +65786,15 @@ fn aiur_fn_781( }) } -const INPUT_SIZE_782: usize = 9; -const IN_782: usize = 9; -const OUT_782: usize = 34; -fn aiur_fn_782( - inp: [G; IN_782], +const INPUT_SIZE_781: usize = 9; +const IN_781: usize = 9; +const OUT_781: usize = 34; +fn aiur_fn_781( + inp: [G; IN_781], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_782], ExecError> { +) -> Result<[G; OUT_781], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -65894,8 +65848,8 @@ fn aiur_fn_782( let __v_45: G = __r_arr[0]; match __v_45.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_782] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43]; - record.function_queries[782].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_781] = [__v_10, __v_11, __v_12, __v_13, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19, __v_20, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27, __v_28, __v_29, __v_30, __v_31, __v_32, __v_33, __v_34, __v_35, __v_36, __v_37, __v_38, __v_39, __v_40, __v_41, __v_42, __v_43]; + record.function_queries[781].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -65908,7 +65862,7 @@ fn aiur_fn_782( let __v_51: G = __r_arr[5]; let __v_52: G = __r_arr[6]; let __v_53: G = __r_arr[7]; - let __r_arr: [G; OUT_782] = { let __args: [G; IN_782] = [__v_44, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[782].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[782].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[782].bump_multiplicity(__i); } let __ret: [G; OUT_782] = unsafe { *(record.function_queries[782].output_at(__i).as_ptr() as *const [G; OUT_782]) }; __ret }, _ => aiur_fn_782(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_781] = { let __args: [G; IN_781] = [__v_44, __v_46, __v_47, __v_48, __v_49, __v_50, __v_51, __v_52, __v_53]; let __cu = unconstrained; let __hit = record.function_queries[781].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[781].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[781].bump_multiplicity(__i); } let __ret: [G; OUT_781] = unsafe { *(record.function_queries[781].output_at(__i).as_ptr() as *const [G; OUT_781]) }; __ret }, _ => aiur_fn_781(__args, record, io_buffer, __cu)? } }; let __v_54: G = __r_arr[0]; let __v_55: G = __r_arr[1]; let __v_56: G = __r_arr[2]; @@ -65943,8 +65897,8 @@ fn aiur_fn_782( let __v_85: G = __r_arr[31]; let __v_86: G = __r_arr[32]; let __v_87: G = __r_arr[33]; - let __ret: [G; OUT_782] = [__v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87]; - record.function_queries[782].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_781] = [__v_54, __v_55, __v_56, __v_57, __v_58, __v_59, __v_60, __v_61, __v_62, __v_63, __v_64, __v_65, __v_66, __v_67, __v_68, __v_69, __v_70, __v_71, __v_72, __v_73, __v_74, __v_75, __v_76, __v_77, __v_78, __v_79, __v_80, __v_81, __v_82, __v_83, __v_84, __v_85, __v_86, __v_87]; + record.function_queries[781].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65959,15 +65913,15 @@ fn aiur_fn_782( }) } -const INPUT_SIZE_783: usize = 1; -const IN_783: usize = 1; -const OUT_783: usize = 1; -fn aiur_fn_783( - inp: [G; IN_783], +const INPUT_SIZE_782: usize = 1; +const IN_782: usize = 1; +const OUT_782: usize = 1; +fn aiur_fn_782( + inp: [G; IN_782], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_783], ExecError> { +) -> Result<[G; OUT_782], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; @@ -65977,14 +65931,14 @@ fn aiur_fn_783( match __v_1.as_canonical_u64() { 1u64 => { let __v_4: G = G::from_u64(1); - let __ret: [G; OUT_783] = [__v_4]; - record.function_queries[783].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_782] = [__v_4]; + record.function_queries[782].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_4: G = G::from_u64(0); - let __ret: [G; OUT_783] = [__v_4]; - record.function_queries[783].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_782] = [__v_4]; + record.function_queries[782].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -65994,15 +65948,15 @@ fn aiur_fn_783( }) } -const INPUT_SIZE_784: usize = 5; -const IN_784: usize = 5; -const OUT_784: usize = 1; -fn aiur_fn_784( - inp: [G; IN_784], +const INPUT_SIZE_783: usize = 5; +const IN_783: usize = 5; +const OUT_783: usize = 1; +fn aiur_fn_783( + inp: [G; IN_783], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_784], ExecError> { +) -> Result<[G; OUT_783], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -66023,17 +65977,17 @@ fn aiur_fn_784( let __v_13: G = G::from_u64(1); let __v_14: G = { let __values: [G; 6] = [__v_12, __v_13, __v_13, __v_13, __v_13, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_15: G = { let __values: [G; 6] = [__v_11, __v_1, __v_2, __v_3, __v_4, __v_14]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_784] = [__v_15]; - record.function_queries[784].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_783] = [__v_15]; + record.function_queries[783].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_11: G = G::from_u64(0); - let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_10, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_783] = { let __args: [G; IN_783] = [__v_10, __v_1, __v_2, __v_3, __v_4]; let __cu = unconstrained; let __hit = record.function_queries[783].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[783].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[783].bump_multiplicity(__i); } let __ret: [G; OUT_783] = unsafe { *(record.function_queries[783].output_at(__i).as_ptr() as *const [G; OUT_783]) }; __ret }, _ => aiur_fn_783(__args, record, io_buffer, __cu)? } }; let __v_12: G = __r_arr[0]; let __v_13: G = { let __values: [G; 6] = [__v_11, __v_6, __v_7, __v_8, __v_9, __v_12]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_784] = [__v_13]; - record.function_queries[784].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_783] = [__v_13]; + record.function_queries[783].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66043,15 +65997,15 @@ fn aiur_fn_784( }) } -const INPUT_SIZE_785: usize = 2; -const IN_785: usize = 2; -const OUT_785: usize = 1; -fn aiur_fn_785( - inp: [G; IN_785], +const INPUT_SIZE_784: usize = 2; +const IN_784: usize = 2; +const OUT_784: usize = 1; +fn aiur_fn_784( + inp: [G; IN_784], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_785], ExecError> { +) -> Result<[G; OUT_784], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -66060,8 +66014,8 @@ fn aiur_fn_785( let __v_2: G = G::from_u64(1); let __v_3: G = G::from_u64(1); let __v_4: G = { let __values: [G; 3] = [__v_2, __v_3, __v_3]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_785] = [__v_4]; - record.function_queries[785].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_784] = [__v_4]; + record.function_queries[784].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66074,11 +66028,11 @@ fn aiur_fn_785( let __v_5: G = G::from_u64(0); let __v_6: G = G::from_u64(1); let __v_7: G = (__v_1 - __v_6); - let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_784] = { let __args: [G; IN_784] = [__v_4, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[784].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[784].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[784].bump_multiplicity(__i); } let __ret: [G; OUT_784] = unsafe { *(record.function_queries[784].output_at(__i).as_ptr() as *const [G; OUT_784]) }; __ret }, _ => aiur_fn_784(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = { let __values: [G; 3] = [__v_5, __v_3, __v_8]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_785] = [__v_9]; - record.function_queries[785].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_784] = [__v_9]; + record.function_queries[784].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66090,28 +66044,28 @@ fn aiur_fn_785( }) } -const INPUT_SIZE_786: usize = 2; -const IN_786: usize = 2; -const OUT_786: usize = 1; -fn aiur_fn_786( - inp: [G; IN_786], +const INPUT_SIZE_785: usize = 2; +const IN_785: usize = 2; +const OUT_785: usize = 1; +fn aiur_fn_785( + inp: [G; IN_785], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_786], ExecError> { +) -> Result<[G; OUT_785], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; match __v_1.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_786] = [__v_0]; - record.function_queries[786].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_785] = [__v_0]; + record.function_queries[785].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_2: G = G::from_u64(1); let __v_3: G = (__v_1 - __v_2); - let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_785] = { let __args: [G; IN_785] = [__v_0, __v_3]; let __cu = unconstrained; let __hit = record.function_queries[785].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[785].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[785].bump_multiplicity(__i); } let __ret: [G; OUT_785] = unsafe { *(record.function_queries[785].output_at(__i).as_ptr() as *const [G; OUT_785]) }; __ret }, _ => aiur_fn_785(__args, record, io_buffer, __cu)? } }; let __v_4: G = __r_arr[0]; let __loaded: [G; 3] = { let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; let __ptr_u64 = __v_4.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 3 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 3] = __args[..3].try_into().unwrap(); __arr }; let __v_5: G = __loaded[0]; @@ -66119,8 +66073,8 @@ fn aiur_fn_786( let __v_7: G = __loaded[2]; match __v_5.as_canonical_u64() { 0u64 => { - let __ret: [G; OUT_786] = [__v_7]; - record.function_queries[786].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_785] = [__v_7]; + record.function_queries[785].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66132,15 +66086,15 @@ fn aiur_fn_786( }) } -const INPUT_SIZE_787: usize = 1; -const IN_787: usize = 1; -const OUT_787: usize = 1; -fn aiur_fn_787( - inp: [G; IN_787], +const INPUT_SIZE_786: usize = 1; +const IN_786: usize = 1; +const OUT_786: usize = 1; +fn aiur_fn_786( + inp: [G; IN_786], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_787], ExecError> { +) -> Result<[G; OUT_786], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 5] = { let __mq = record.memory_queries.get_mut(&5).ok_or(ExecError::InvalidMemorySize(5))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 5 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 5] = __args[..5].try_into().unwrap(); __arr }; @@ -66152,17 +66106,17 @@ fn aiur_fn_787( match __v_1.as_canonical_u64() { 1u64 => { let __v_6: G = G::from_u64(0); - let __ret: [G; OUT_787] = [__v_6]; - record.function_queries[787].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_786] = [__v_6]; + record.function_queries[786].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_787] = { let __args: [G; IN_787] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[787].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[787].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[787].bump_multiplicity(__i); } let __ret: [G; OUT_787] = unsafe { *(record.function_queries[787].output_at(__i).as_ptr() as *const [G; OUT_787]) }; __ret }, _ => aiur_fn_787(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_786] = { let __args: [G; IN_786] = [__v_5]; let __cu = unconstrained; let __hit = record.function_queries[786].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[786].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[786].bump_multiplicity(__i); } let __ret: [G; OUT_786] = unsafe { *(record.function_queries[786].output_at(__i).as_ptr() as *const [G; OUT_786]) }; __ret }, _ => aiur_fn_786(__args, record, io_buffer, __cu)? } }; let __v_6: G = __r_arr[0]; let __v_7: G = G::from_u64(1); let __v_8: G = (__v_6 + __v_7); - let __ret: [G; OUT_787] = [__v_8]; - record.function_queries[787].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_786] = [__v_8]; + record.function_queries[786].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66172,15 +66126,15 @@ fn aiur_fn_787( }) } -const INPUT_SIZE_788: usize = 8; -const IN_788: usize = 8; -const OUT_788: usize = 6; -fn aiur_fn_788( - inp: [G; IN_788], +const INPUT_SIZE_787: usize = 8; +const IN_787: usize = 8; +const OUT_787: usize = 6; +fn aiur_fn_787( + inp: [G; IN_787], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_788], ExecError> { +) -> Result<[G; OUT_787], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -66190,7 +66144,7 @@ fn aiur_fn_788( let __v_5: G = inp[5]; let __v_6: G = inp[6]; let __v_7: G = inp[7]; - let __r_arr: [G; OUT_791] = { let __args: [G; IN_791] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[791].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[791].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[791].bump_multiplicity(__i); } let __ret: [G; OUT_791] = unsafe { *(record.function_queries[791].output_at(__i).as_ptr() as *const [G; OUT_791]) }; __ret }, _ => aiur_fn_791(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_790] = { let __args: [G; IN_790] = [__v_0, __v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __cu = unconstrained; let __hit = record.function_queries[790].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[790].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[790].bump_multiplicity(__i); } let __ret: [G; OUT_790] = unsafe { *(record.function_queries[790].output_at(__i).as_ptr() as *const [G; OUT_790]) }; __ret }, _ => aiur_fn_790(__args, record, io_buffer, __cu)? } }; let __v_8: G = __r_arr[0]; let __v_9: G = __r_arr[1]; let __v_10: G = __r_arr[2]; @@ -66201,8 +66155,8 @@ fn aiur_fn_788( 0u64 => { let __v_14: G = G::from_u64(0); let __v_15: G = G::from_u64(1); - let __ret: [G; OUT_788] = [__v_14, __v_15, __v_10, __v_11, __v_12, __v_13]; - record.function_queries[788].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_787] = [__v_14, __v_15, __v_10, __v_11, __v_12, __v_13]; + record.function_queries[787].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66212,15 +66166,15 @@ fn aiur_fn_788( }) } -const INPUT_SIZE_789: usize = 1; -const IN_789: usize = 1; -const OUT_789: usize = 1; -fn aiur_fn_789( - inp: [G; IN_789], +const INPUT_SIZE_788: usize = 1; +const IN_788: usize = 1; +const OUT_788: usize = 1; +fn aiur_fn_788( + inp: [G; IN_788], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_789], ExecError> { +) -> Result<[G; OUT_788], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __loaded: [G; 6] = { let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; let __ptr_u64 = __v_0.as_canonical_u64(); let __ptr_usize = usize::try_from(__ptr_u64).ok().ok_or(ExecError::PointerTooLarge(__ptr_u64))?; if __ptr_usize >= __mq.len() { return Err(ExecError::UnboundPointer { ptr: __ptr_u64, size: 6 }); } if !unconstrained { __mq.bump_multiplicity(__ptr_usize); } let (__args, _) = __mq.get_index(__ptr_usize).expect("bounds checked above"); let __arr: [G; 6] = __args[..6].try_into().unwrap(); __arr }; @@ -66233,17 +66187,17 @@ fn aiur_fn_789( match __v_1.as_canonical_u64() { 1u64 => { let __v_7: G = G::from_u64(0); - let __ret: [G; OUT_789] = [__v_7]; - record.function_queries[789].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_788] = [__v_7]; + record.function_queries[788].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { - let __r_arr: [G; OUT_789] = { let __args: [G; IN_789] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[789].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[789].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[789].bump_multiplicity(__i); } let __ret: [G; OUT_789] = unsafe { *(record.function_queries[789].output_at(__i).as_ptr() as *const [G; OUT_789]) }; __ret }, _ => aiur_fn_789(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_788] = { let __args: [G; IN_788] = [__v_6]; let __cu = unconstrained; let __hit = record.function_queries[788].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[788].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[788].bump_multiplicity(__i); } let __ret: [G; OUT_788] = unsafe { *(record.function_queries[788].output_at(__i).as_ptr() as *const [G; OUT_788]) }; __ret }, _ => aiur_fn_788(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; let __v_8: G = G::from_u64(1); let __v_9: G = (__v_7 + __v_8); - let __ret: [G; OUT_789] = [__v_9]; - record.function_queries[789].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_788] = [__v_9]; + record.function_queries[788].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66253,15 +66207,15 @@ fn aiur_fn_789( }) } -const INPUT_SIZE_790: usize = 2; -const IN_790: usize = 2; -const OUT_790: usize = 1; -fn aiur_fn_790( - inp: [G; IN_790], +const INPUT_SIZE_789: usize = 2; +const IN_789: usize = 2; +const OUT_789: usize = 1; +fn aiur_fn_789( + inp: [G; IN_789], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_790], ExecError> { +) -> Result<[G; OUT_789], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -66271,17 +66225,17 @@ fn aiur_fn_790( let __v_4: G = __loaded[2]; match __v_2.as_canonical_u64() { 1u64 => { - let __ret: [G; OUT_790] = [__v_1]; - record.function_queries[790].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_789] = [__v_1]; + record.function_queries[789].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { let __v_5: G = G::from_u64(0); let __v_6: G = { let __values: [G; 3] = [__v_5, __v_3, __v_1]; let __mq = record.memory_queries.get_mut(&3).ok_or(ExecError::InvalidMemorySize(3))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __r_arr: [G; OUT_790] = { let __args: [G; IN_790] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[790].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[790].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[790].bump_multiplicity(__i); } let __ret: [G; OUT_790] = unsafe { *(record.function_queries[790].output_at(__i).as_ptr() as *const [G; OUT_790]) }; __ret }, _ => aiur_fn_790(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_789] = { let __args: [G; IN_789] = [__v_4, __v_6]; let __cu = unconstrained; let __hit = record.function_queries[789].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[789].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[789].bump_multiplicity(__i); } let __ret: [G; OUT_789] = unsafe { *(record.function_queries[789].output_at(__i).as_ptr() as *const [G; OUT_789]) }; __ret }, _ => aiur_fn_789(__args, record, io_buffer, __cu)? } }; let __v_7: G = __r_arr[0]; - let __ret: [G; OUT_790] = [__v_7]; - record.function_queries[790].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_789] = [__v_7]; + record.function_queries[789].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66291,15 +66245,15 @@ fn aiur_fn_790( }) } -const INPUT_SIZE_791: usize = 8; -const IN_791: usize = 8; -const OUT_791: usize = 6; -fn aiur_fn_791( - inp: [G; IN_791], +const INPUT_SIZE_790: usize = 8; +const IN_790: usize = 8; +const OUT_790: usize = 6; +fn aiur_fn_790( + inp: [G; IN_790], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_791], ExecError> { +) -> Result<[G; OUT_790], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -66319,8 +66273,8 @@ fn aiur_fn_791( let __v_13: G = G::from_u64(1); let __v_14: G = G::from_u64(1); let __v_15: G = { let __values: [G; 6] = [__v_13, __v_14, __v_14, __v_14, __v_14, __v_14]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_791] = [__v_8, __v_9, __v_0, __v_1, __v_12, __v_15]; - record.function_queries[791].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_790] = [__v_8, __v_9, __v_0, __v_1, __v_12, __v_15]; + record.function_queries[790].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, 0u64 => { @@ -66341,22 +66295,22 @@ fn aiur_fn_791( let __v_20: G = { let __a_val = __v_0.as_canonical_u64(); let __b_val = __v_4.as_canonical_u64(); let __a_u32 = u32::try_from(__a_val).ok().ok_or(ExecError::U32OutOfRange(__a_val))?; let __b_u32 = u32::try_from(__b_val).ok().ok_or(ExecError::U32OutOfRange(__b_val))?; let __result = G::from_bool(__a_u32 < __b_u32); if !unconstrained { let __x_bytes = __a_u32.to_le_bytes(); let __z_bytes = __b_u32.to_le_bytes(); let __c_u32 = __b_u32.wrapping_sub(__a_u32).wrapping_sub(1); let __y_bytes = __c_u32.to_le_bytes(); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[0]), &G::from_u8(__x_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__x_bytes[2]), &G::from_u8(__x_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[0]), &G::from_u8(__y_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__y_bytes[2]), &G::from_u8(__y_bytes[3])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[0]), &G::from_u8(__z_bytes[1])); record.bytes2_queries.bump_range_check(&G::from_u8(__z_bytes[2]), &G::from_u8(__z_bytes[3])); } __result }; match __v_20.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_791] = { let __args: [G; IN_791] = [__v_0, __v_1, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[791].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[791].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[791].bump_multiplicity(__i); } let __ret: [G; OUT_791] = unsafe { *(record.function_queries[791].output_at(__i).as_ptr() as *const [G; OUT_791]) }; __ret }, _ => aiur_fn_791(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_790] = { let __args: [G; IN_790] = [__v_0, __v_1, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __cu = unconstrained; let __hit = record.function_queries[790].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[790].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[790].bump_multiplicity(__i); } let __ret: [G; OUT_790] = unsafe { *(record.function_queries[790].output_at(__i).as_ptr() as *const [G; OUT_790]) }; __ret }, _ => aiur_fn_790(__args, record, io_buffer, __cu)? } }; let __v_21: G = __r_arr[0]; let __v_22: G = __r_arr[1]; let __v_23: G = __r_arr[2]; let __v_24: G = __r_arr[3]; let __v_25: G = __r_arr[4]; let __v_26: G = __r_arr[5]; - let __r_arr: [G; OUT_792] = { let __args: [G; IN_792] = [__v_3, __v_4, __v_5, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[792].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[792].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[792].bump_multiplicity(__i); } let __ret: [G; OUT_792] = unsafe { *(record.function_queries[792].output_at(__i).as_ptr() as *const [G; OUT_792]) }; __ret }, _ => aiur_fn_792(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_791] = { let __args: [G; IN_791] = [__v_3, __v_4, __v_5, __v_21, __v_22, __v_23, __v_24, __v_25, __v_26, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[791].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[791].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[791].bump_multiplicity(__i); } let __ret: [G; OUT_791] = unsafe { *(record.function_queries[791].output_at(__i).as_ptr() as *const [G; OUT_791]) }; __ret }, _ => aiur_fn_791(__args, record, io_buffer, __cu)? } }; let __v_27: G = __r_arr[0]; let __v_28: G = __r_arr[1]; let __v_29: G = __r_arr[2]; let __v_30: G = __r_arr[3]; let __v_31: G = __r_arr[4]; let __v_32: G = __r_arr[5]; - let __ret: [G; OUT_791] = [__v_27, __v_28, __v_29, __v_30, __v_31, __v_32]; - record.function_queries[791].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_790] = [__v_27, __v_28, __v_29, __v_30, __v_31, __v_32]; + record.function_queries[790].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66366,27 +66320,27 @@ fn aiur_fn_791( let __v_22: G = G::from_u64(0); let __v_23: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_24: G = { let __values: [G; 6] = [__v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_791] = [__v_22, __v_3, __v_0, __v_1, __v_23, __v_24]; - record.function_queries[791].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_790] = [__v_22, __v_3, __v_0, __v_1, __v_23, __v_24]; + record.function_queries[790].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { - let __r_arr: [G; OUT_791] = { let __args: [G; IN_791] = [__v_0, __v_1, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[791].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[791].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[791].bump_multiplicity(__i); } let __ret: [G; OUT_791] = unsafe { *(record.function_queries[791].output_at(__i).as_ptr() as *const [G; OUT_791]) }; __ret }, _ => aiur_fn_791(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_790] = { let __args: [G; IN_790] = [__v_0, __v_1, __v_14, __v_15, __v_16, __v_17, __v_18, __v_19]; let __cu = unconstrained; let __hit = record.function_queries[790].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[790].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[790].bump_multiplicity(__i); } let __ret: [G; OUT_790] = unsafe { *(record.function_queries[790].output_at(__i).as_ptr() as *const [G; OUT_790]) }; __ret }, _ => aiur_fn_790(__args, record, io_buffer, __cu)? } }; let __v_22: G = __r_arr[0]; let __v_23: G = __r_arr[1]; let __v_24: G = __r_arr[2]; let __v_25: G = __r_arr[3]; let __v_26: G = __r_arr[4]; let __v_27: G = __r_arr[5]; - let __r_arr: [G; OUT_792] = { let __args: [G; IN_792] = [__v_3, __v_4, __v_5, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[792].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[792].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[792].bump_multiplicity(__i); } let __ret: [G; OUT_792] = unsafe { *(record.function_queries[792].output_at(__i).as_ptr() as *const [G; OUT_792]) }; __ret }, _ => aiur_fn_792(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_791] = { let __args: [G; IN_791] = [__v_3, __v_4, __v_5, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_22, __v_23, __v_24, __v_25, __v_26, __v_27]; let __cu = unconstrained; let __hit = record.function_queries[791].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[791].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[791].bump_multiplicity(__i); } let __ret: [G; OUT_791] = unsafe { *(record.function_queries[791].output_at(__i).as_ptr() as *const [G; OUT_791]) }; __ret }, _ => aiur_fn_791(__args, record, io_buffer, __cu)? } }; let __v_28: G = __r_arr[0]; let __v_29: G = __r_arr[1]; let __v_30: G = __r_arr[2]; let __v_31: G = __r_arr[3]; let __v_32: G = __r_arr[4]; let __v_33: G = __r_arr[5]; - let __ret: [G; OUT_791] = [__v_28, __v_29, __v_30, __v_31, __v_32, __v_33]; - record.function_queries[791].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_790] = [__v_28, __v_29, __v_30, __v_31, __v_32, __v_33]; + record.function_queries[790].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66400,15 +66354,15 @@ fn aiur_fn_791( }) } -const INPUT_SIZE_792: usize = 15; -const IN_792: usize = 15; -const OUT_792: usize = 6; -fn aiur_fn_792( - inp: [G; IN_792], +const INPUT_SIZE_791: usize = 15; +const IN_791: usize = 15; +const OUT_791: usize = 6; +fn aiur_fn_791( + inp: [G; IN_791], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_792], ExecError> { +) -> Result<[G; OUT_791], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -66427,38 +66381,38 @@ fn aiur_fn_792( let __v_14: G = inp[14]; match __v_0.as_canonical_u64() { 1u64 => { - let __r_arr: [G; OUT_793] = { let __args: [G; IN_793] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[793].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[793].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[793].bump_multiplicity(__i); } let __ret: [G; OUT_793] = unsafe { *(record.function_queries[793].output_at(__i).as_ptr() as *const [G; OUT_793]) }; __ret }, _ => aiur_fn_793(__args, record, io_buffer, __cu)? } }; + let __r_arr: [G; OUT_792] = { let __args: [G; IN_792] = [__v_1, __v_2, __v_3, __v_4, __v_5, __v_6, __v_7, __v_8, __v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __cu = unconstrained; let __hit = record.function_queries[792].get_index_of(&__args[..]); match __hit { Some(__i) if __cu || record.function_queries[792].mult_at(__i) != G::ZERO => { if !unconstrained { record.function_queries[792].bump_multiplicity(__i); } let __ret: [G; OUT_792] = unsafe { *(record.function_queries[792].output_at(__i).as_ptr() as *const [G; OUT_792]) }; __ret }, _ => aiur_fn_792(__args, record, io_buffer, __cu)? } }; let __v_15: G = __r_arr[0]; let __v_16: G = __r_arr[1]; let __v_17: G = __r_arr[2]; let __v_18: G = __r_arr[3]; let __v_19: G = __r_arr[4]; let __v_20: G = __r_arr[5]; - let __ret: [G; OUT_792] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; - record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_791] = [__v_15, __v_16, __v_17, __v_18, __v_19, __v_20]; + record.function_queries[791].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { let __v_15: G = G::from_u64(0); let __v_16: G = { let __values: [G; 6] = [__v_3, __v_4, __v_5, __v_6, __v_7, __v_8]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = { let __values: [G; 6] = [__v_9, __v_10, __v_11, __v_12, __v_13, __v_14]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_792] = [__v_15, __v_0, __v_1, __v_2, __v_16, __v_17]; - record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_791] = [__v_15, __v_0, __v_1, __v_2, __v_16, __v_17]; + record.function_queries[791].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } }) } -const INPUT_SIZE_793: usize = 14; -const IN_793: usize = 14; -const OUT_793: usize = 6; -fn aiur_fn_793( - inp: [G; IN_793], +const INPUT_SIZE_792: usize = 14; +const IN_792: usize = 14; +const OUT_792: usize = 6; +fn aiur_fn_792( + inp: [G; IN_792], record: &mut QueryRecord, io_buffer: &mut IOBuffer, unconstrained: bool, -) -> Result<[G; OUT_793], ExecError> { +) -> Result<[G; OUT_792], ExecError> { stacker::maybe_grow(64 * 1024, 4 * 1024 * 1024, || { let __v_0: G = inp[0]; let __v_1: G = inp[1]; @@ -66498,8 +66452,8 @@ fn aiur_fn_793( let __v_26: G = G::from_u64(1); let __v_27: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_28: G = { let __values: [G; 6] = [__v_25, __v_26, __v_0, __v_1, __v_7, __v_27]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_20, __v_21, __v_4, __v_5, __v_24, __v_28]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_20, __v_21, __v_4, __v_5, __v_24, __v_28]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66523,8 +66477,8 @@ fn aiur_fn_793( let __v_32: G = G::from_u64(1); let __v_33: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_34: G = { let __values: [G; 6] = [__v_31, __v_32, __v_0, __v_1, __v_25, __v_33]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_22, __v_23, __v_30, __v_34]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_22, __v_23, __v_30, __v_34]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66552,8 +66506,8 @@ fn aiur_fn_793( let __v_38: G = G::from_u64(0); let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_38, __v_39, __v_10, __v_11, __v_31, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66577,8 +66531,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66586,8 +66540,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66597,8 +66551,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66626,8 +66580,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66635,8 +66589,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66646,8 +66600,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66659,8 +66613,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66670,8 +66624,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66703,8 +66657,8 @@ fn aiur_fn_793( let __v_38: G = G::from_u64(0); let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_38, __v_39, __v_10, __v_11, __v_31, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66728,8 +66682,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66737,8 +66691,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66748,8 +66702,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66777,8 +66731,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66786,8 +66740,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66797,8 +66751,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66810,8 +66764,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66821,8 +66775,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66852,8 +66806,8 @@ fn aiur_fn_793( let __v_32: G = G::from_u64(1); let __v_33: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_34: G = { let __values: [G; 6] = [__v_31, __v_32, __v_0, __v_1, __v_25, __v_33]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_22, __v_23, __v_30, __v_34]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_22, __v_23, __v_30, __v_34]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66881,8 +66835,8 @@ fn aiur_fn_793( let __v_38: G = G::from_u64(0); let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_38, __v_39, __v_10, __v_11, __v_31, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66906,8 +66860,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66915,8 +66869,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66926,8 +66880,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66955,8 +66909,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -66964,8 +66918,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66975,8 +66929,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66988,8 +66942,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -66999,8 +66953,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67032,8 +66986,8 @@ fn aiur_fn_793( let __v_38: G = G::from_u64(0); let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_38, __v_39, __v_10, __v_11, __v_31, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_32, __v_33, __v_28, __v_29, __v_37, __v_40]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67057,8 +67011,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67066,8 +67020,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67077,8 +67031,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67106,8 +67060,8 @@ fn aiur_fn_793( let __v_44: G = G::from_u64(0); let __v_45: G = G::from_u64(1); let __v_46: G = { let __values: [G; 6] = [__v_44, __v_45, __v_34, __v_35, __v_36, __v_37]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_10, __v_11, __v_43, __v_46]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67115,8 +67069,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67126,8 +67080,8 @@ fn aiur_fn_793( let __v_39: G = G::from_u64(1); let __v_40: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_41: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_38, __v_39, __v_0, __v_1, __v_40, __v_41]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67139,8 +67093,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67150,8 +67104,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67185,8 +67139,8 @@ fn aiur_fn_793( let __v_26: G = G::from_u64(0); let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_26, __v_27, __v_10, __v_11, __v_19, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_20, __v_21, __v_16, __v_17, __v_25, __v_28]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_20, __v_21, __v_16, __v_17, __v_25, __v_28]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67210,8 +67164,8 @@ fn aiur_fn_793( let __v_32: G = G::from_u64(0); let __v_33: G = G::from_u64(1); let __v_34: G = { let __values: [G; 6] = [__v_32, __v_33, __v_22, __v_23, __v_24, __v_25]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67219,8 +67173,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67230,8 +67184,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67259,8 +67213,8 @@ fn aiur_fn_793( let __v_32: G = G::from_u64(0); let __v_33: G = G::from_u64(1); let __v_34: G = { let __values: [G; 6] = [__v_32, __v_33, __v_22, __v_23, __v_24, __v_25]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67268,8 +67222,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67279,8 +67233,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67292,8 +67246,8 @@ fn aiur_fn_793( let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67303,8 +67257,8 @@ fn aiur_fn_793( let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67336,8 +67290,8 @@ fn aiur_fn_793( let __v_26: G = G::from_u64(0); let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_26, __v_27, __v_10, __v_11, __v_19, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_20, __v_21, __v_16, __v_17, __v_25, __v_28]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_20, __v_21, __v_16, __v_17, __v_25, __v_28]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67361,8 +67315,8 @@ fn aiur_fn_793( let __v_32: G = G::from_u64(0); let __v_33: G = G::from_u64(1); let __v_34: G = { let __values: [G; 6] = [__v_32, __v_33, __v_22, __v_23, __v_24, __v_25]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67370,8 +67324,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67381,8 +67335,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67410,8 +67364,8 @@ fn aiur_fn_793( let __v_32: G = G::from_u64(0); let __v_33: G = G::from_u64(1); let __v_34: G = { let __values: [G; 6] = [__v_32, __v_33, __v_22, __v_23, __v_24, __v_25]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_10, __v_11, __v_31, __v_34]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, _ => { @@ -67419,8 +67373,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67430,8 +67384,8 @@ fn aiur_fn_793( let __v_27: G = G::from_u64(1); let __v_28: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_29: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_26, __v_27, __v_0, __v_1, __v_28, __v_29]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67443,8 +67397,8 @@ fn aiur_fn_793( let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -67454,8 +67408,8 @@ fn aiur_fn_793( let __v_15: G = G::from_u64(1); let __v_16: G = { let __values: [G; 6] = [__v_2, __v_3, __v_4, __v_5, __v_6, __v_7]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; let __v_17: G = { let __values: [G; 6] = [__v_8, __v_9, __v_10, __v_11, __v_12, __v_13]; let __mq = record.memory_queries.get_mut(&6).ok_or(ExecError::InvalidMemorySize(6))?; if let Some(__i) = __mq.get_index_of(&__values[..]) { if !unconstrained { __mq.bump_multiplicity(__i); } __mq.output_at(__i)[0] } else { let __ptr = G::from_usize(__mq.len()); __mq.insert(&__values[..], &[__ptr], G::from_bool(!unconstrained)); __ptr } }; - let __ret: [G; OUT_793] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; - record.function_queries[793].finish(&inp[..], &__ret[..], !unconstrained); + let __ret: [G; OUT_792] = [__v_14, __v_15, __v_0, __v_1, __v_16, __v_17]; + record.function_queries[792].finish(&inp[..], &__ret[..], !unconstrained); return Ok(__ret); }, } @@ -71436,11 +71390,6 @@ pub(crate) fn execute_generated( let __out = aiur_fn_792(__inp, record, io_buffer, false)?; return Ok(__out.to_vec()); }, - 793u64 => { - let __inp: [G; IN_793] = args.try_into().expect("input size mismatch"); - let __out = aiur_fn_793(__inp, record, io_buffer, false)?; - return Ok(__out.to_vec()); - }, _ => { return Err(ExecError::InvalidFunIdx(fun_idx)); }, diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index 04ec15457..fb81e90f5 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -148,6 +148,34 @@ without scanning degrees. Larger caps require a linear metadata check. No AIR, trace width, FFT cost or proof encoding changes. Unsafe configurations are rejected; the recursive verifier already requires cap height zero. +## Host memory and byte advice + +`split_u32` obtains its four low bytes from the native field-to-bytes hint. +The production caller still range-checks every byte and reconstructs the +original field element. Both the reconstruction and its maximum value are +below the field modulus, so inputs at least `2^32` fail instead of truncating. +Zero still normalizes to an empty limb list. Removing repeated subtraction +avoids retaining a growing tree of unconstrained queries; the byte checks +and constrained arithmetic are unchanged. [Byte-hint regressions](../Tests/Ix/IxVM/ByteHints.lean) +cover boundary values, incorrect advice and native prove/verify cases. + +Function witness construction stores a member index and query index per +active row, sharing function metadata across the member's rows. On a 64-bit +host this reduces per-row metadata from 72 to 16 bytes. Counting active +multiplicities before allocation also avoids geometric vector growth and +metadata for advice-only entries. Row order, selector offsets, multiplicities +and completion ranks are preserved, including advice promotion. + +The prover RAM model sums all member-function queries before splitting a +grouped circuit's height. It uses the configured extension-field dimension +for lookup messages and quotient storage, independent of accumulator grouping, +and includes lookup row writers at padded heights plus function metadata. +The [RAM and witness regressions](../crates/aiur/src/synthesis/tests/peak.rs) +cover reordered groups, advice-only entries, shard sizing and extension storage. +The historical RSS calibration remains an estimate requiring recalibration +against the current prover; these corrections do not establish an absolute +process-memory bound. + ## Compatibility and validation The activity, call-order and branch-gating repairs change affected AIR @@ -158,6 +186,8 @@ specialization also changes the IxVM AIR and key, and extends the internal Lean/Rust bytecode representation; rebuild both sides of the FFI together. Lookup retuning changes affected stage-2 layouts, quotient degrees and keys, so it also requires rebuilding systems and regenerating proofs. +The removed byte-advice helper changes compiled function indices; regenerate +the IxVM executor and rebuild its systems together with the Lean sources. The native regressions cover supplied false witnesses as well as honest execution, finite recursion, shared callees, advice promotion and grouped @@ -170,7 +200,7 @@ Aiur proving corpus with specialized layouts. Run them with: cargo test --locked --release -p aiur --features parallel cargo clippy --locked --release -p aiur --all-targets --features parallel -- -D warnings lake exe ix codegen --check -lake test -- aiur-cross aiur-cost aiur-prove aiur-components recursive-verifier ix-aggr +lake test -- aiur-cross aiur-cost aiur-prove aiur-components ixvm-byte-hints recursive-verifier ix-aggr lake test -- --ignored ixvm ``` From df3ceb0f569e34b372f8dde1b8a2a1e3dd6e8b3e Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 18:20:39 -0400 Subject: [PATCH 20/30] Check Aiur emission inputs and conservative folded degrees Port emission validation from b8cf284a and the EqZero allocation repair from f83498cd on top of the optimized component-rank and lookup-group implementation. Retain the native regressions from monorepo 12600064 and check rejection with an acyclic component layout as well. Validation: 60 release Aiur tests passed (two existing performance tests ignored); release Clippy with all targets and parallel features passed with warnings denied; cargo fmt check passed. --- crates/aiur/src/constraints.rs | 8 +- crates/aiur/src/emission_checks.rs | 375 ++++++++++++++++++ crates/aiur/src/lib.rs | 1 + crates/aiur/src/synthesis.rs | 2 + .../src/synthesis/tests/constant_degree.rs | 37 ++ docs/aiur-soundness.md | 16 + 6 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 crates/aiur/src/emission_checks.rs create mode 100644 crates/aiur/src/synthesis/tests/constant_degree.rs diff --git a/crates/aiur/src/constraints.rs b/crates/aiur/src/constraints.rs index a737f918f..7f635c985 100644 --- a/crates/aiur/src/constraints.rs +++ b/crates/aiur/src/constraints.rs @@ -475,10 +475,12 @@ impl Op { }, Op::EqZero(a) => { let (a, deg) = state.map[*a].clone(); - if let Expr::Const(a) = a { - assert_eq!(deg, 0); - state.map.push((konst(G::from_bool(a == G::ZERO)), 0)); + if let (Expr::Const(value), 0) = (&a, deg) { + state.map.push((konst(G::from_bool(*value == G::ZERO)), 0)); } else { + // Folding (for example 0*x) can produce a constant while its + // tracked degree remains positive. Keep the compiler/witness + // allocation and constrain the result through the normal path. // We have two constraints: // 1. ax = 0 // 2. ad + x = 1 diff --git a/crates/aiur/src/emission_checks.rs b/crates/aiur/src/emission_checks.rs new file mode 100644 index 000000000..283158bd3 --- /dev/null +++ b/crates/aiur/src/emission_checks.rs @@ -0,0 +1,375 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Logical scopes and selector reads required by circuit construction. + +use crate::bytecode::{Block, Ctrl, Op, Toplevel}; + +fn indices_in_scope(available: usize, indices: &[usize]) -> bool { + indices.iter().all(|&index| index < available) +} + +fn word_in_scope(available: usize, indices: &[usize]) -> bool { + indices.len() == 4 && indices_in_scope(available, indices) +} + +impl Op { + /// Includes virtual outputs such as carries, which use no fresh column. + pub(crate) fn output_size(&self) -> usize { + match self { + Self::Const(..) + | Self::Add(..) + | Self::Sub(..) + | Self::Mul(..) + | Self::EqZero(..) + | Self::Store(..) + | Self::U8ShiftLeft(..) + | Self::U8ShiftRight(..) + | Self::U8Xor(..) + | Self::U8And(..) + | Self::U8Or(..) + | Self::U8LessThan(..) + | Self::U32LessThan(..) + | Self::UnconstrainedGInverse(..) + | Self::U32ToField(..) => 1, + Self::Call(_, _, size, _) + | Self::Load(size, _) + | Self::IORead(_, _, size) => *size, + Self::AssertEq(..) + | Self::IOSetInfo(..) + | Self::IOWrite(..) + | Self::Debug(..) + | Self::U8RangeCheck(..) => 0, + Self::IOGetInfo(..) + | Self::U8Add(..) + | Self::U8Mul(..) + | Self::U8Sub(..) + | Self::U8XorSplit7(..) + | Self::U8XorSplit4(..) + | Self::UnconstrainedBigUintDivMod(..) => 2, + Self::U8BitDecomposition(..) | Self::UnconstrainedGToBytes(..) => 8, + Self::UnconstrainedU32Add(..) | Self::UnconstrainedU32Add3(..) => 5, + } + } + + /// Check reads in the incoming scope, before allocating any outputs. + /// Advice and I/O operands are not consumed while building constraints. + pub(crate) fn emission_inputs(&self, available: usize) -> bool { + match self { + Self::Add(a, b) + | Self::Sub(a, b) + | Self::Mul(a, b) + | Self::U8Xor(a, b) + | Self::U8Add(a, b) + | Self::U8Mul(a, b) + | Self::U8Sub(a, b) + | Self::U8And(a, b) + | Self::U8Or(a, b) + | Self::U8LessThan(a, b) + | Self::U32LessThan(a, b) + | Self::U8XorSplit7(a, b) + | Self::U8XorSplit4(a, b) + | Self::U8RangeCheck(a, b) => *a < available && *b < available, + Self::EqZero(index) + | Self::Load(_, index) + | Self::U8BitDecomposition(index) + | Self::U8ShiftLeft(index) + | Self::U8ShiftRight(index) => *index < available, + Self::Call(_, indices, _, false) | Self::Store(indices) => { + indices_in_scope(available, indices) + }, + Self::AssertEq(left, right, _) => { + left.len() == right.len() + && indices_in_scope(available, left) + && indices_in_scope(available, right) + }, + Self::UnconstrainedU32Add(left, right) => { + word_in_scope(available, left) && word_in_scope(available, right) + }, + Self::UnconstrainedU32Add3(left, middle, right) => { + word_in_scope(available, left) + && word_in_scope(available, middle) + && word_in_scope(available, right) + }, + Self::U32ToField(indices) => word_in_scope(available, indices), + _ => true, + } + } +} + +pub(crate) fn check_emission_ops( + ops: &[Op], + mut available: usize, +) -> Result { + for op in ops { + if !op.emission_inputs(available) { + return Err("operation reads outside its incoming scope or width"); + } + available = available + .checked_add(op.output_size()) + .ok_or("logical value count overflows")?; + } + Ok(available) +} + +impl Block { + pub(crate) fn check_emission( + &self, + available: usize, + selectors: usize, + yield_size: Option, + ) -> Result<(), &'static str> { + let available = check_emission_ops(&self.ops, available)?; + match &self.ctrl { + Ctrl::Return(index, outputs) | Ctrl::Yield(index, outputs) => { + if *index >= selectors { + return Err("terminal reads outside its function's selector region"); + } + if !indices_in_scope(available, outputs) { + return Err("terminal reads outside its logical scope"); + } + if matches!(self.ctrl, Ctrl::Yield(..)) + && yield_size != Some(outputs.len()) + { + return Err("yield width differs from its enclosing continuation"); + } + }, + Ctrl::Match(index, branches, fallback) => { + if *index >= available { + return Err("match reads outside its logical scope"); + } + for block in branches.values().chain(fallback.as_deref()) { + block.check_emission(available, selectors, yield_size)?; + } + }, + Ctrl::MatchContinue(index, branches, fallback, size, _, _, cont) => { + if *index >= available { + return Err("match reads outside its logical scope"); + } + for block in branches.values().chain(fallback.as_deref()) { + block.check_emission(available, selectors, Some(*size))?; + } + let available = available + .checked_add(*size) + .ok_or("continuation merge count overflows")?; + cont.check_emission(available, selectors, yield_size)?; + }, + } + Ok(()) + } +} + +impl Toplevel { + /// Validate every constrained function before native circuit construction. + /// This does not typecheck source programs or constrain advice operands. + pub fn validate_emission(&self) -> Result<(), &'static str> { + for function in &self.functions { + if function.constrained { + function.body.check_emission( + function.layout.input_size, + function.layout.selectors, + None, + )?; + } + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use multi_stark::p3_field::PrimeCharacteristicRing; + use multi_stark::types::{CommitmentParameters, FriParameters}; + + use super::check_emission_ops; + use crate::{ + G, + bytecode::{ + Block, CallComponent, Circuit, Ctrl, Function, FunctionLayout, Op, + Toplevel, + }, + synthesis::AiurSystem, + }; + + fn malformed_operand() -> Toplevel { + let layout = FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 7, + lookups: 4, + }; + Toplevel { + functions: vec![Function { + body: Block { + ops: vec![Op::Add(0, 1)], + ctrl: Ctrl::Return(0, vec![1]), + }, + layout, + entry: true, + constrained: true, + }], + memory_sizes: vec![], + circuits: vec![Circuit { members: vec![0], layout }], + call_components: vec![], + } + } + + #[test] + #[should_panic(expected = "invalid Aiur emission inputs")] + fn system_construction_rejects_invalid_operand() { + let top = malformed_operand(); + top.validate_lookup_shapes().unwrap(); + top.validate_row_counts().unwrap(); + AiurSystem::build( + top, + CommitmentParameters { log_blowup: 1, cap_height: 0 }, + FriParameters { + log_final_poly_len: 0, + max_log_arity: 1, + num_queries: 64, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + }, + ); + } + + #[test] + #[should_panic(expected = "invalid Aiur emission inputs")] + fn component_layout_still_rejects_invalid_operand() { + let mut top = malformed_operand(); + top.call_components = vec![CallComponent { order: 0, ranked: false }]; + top.functions[0].layout.auxiliaries = 1; + top.functions[0].layout.lookups = 1; + top.circuits[0].layout = top.functions[0].layout; + top.validate_lookup_shapes().unwrap(); + top.validate_call_components().unwrap(); + top.validate_row_counts().unwrap(); + AiurSystem::build( + top, + CommitmentParameters { log_blowup: 1, cap_height: 0 }, + FriParameters { + log_final_poly_len: 0, + max_log_arity: 1, + num_queries: 64, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + }, + ); + } + + #[test] + fn incoming_scopes_exclude_store_pointers_and_include_virtual_carries() { + assert!(check_emission_ops(&[Op::Store(vec![1])], 1).is_err()); + assert_eq!(check_emission_ops(&[Op::Store(vec![0])], 1), Ok(2)); + let ops = [ + Op::UnconstrainedU32Add(vec![0, 1, 2, 3], vec![0, 1, 2, 3]), + Op::U8RangeCheck(4, 7), + Op::Add(8, 0), + ]; + assert_eq!(check_emission_ops(&ops, 4), Ok(10)); + assert!( + check_emission_ops(&[Op::U8RangeCheck(0, 0), Op::Add(1, 0)], 1).is_err() + ); + assert!(check_emission_ops(&[Op::U32ToField(vec![0; 3])], 1).is_err()); + assert!(check_emission_ops(&[Op::U32ToField(vec![0; 5])], 1).is_err()); + assert!( + check_emission_ops(&[Op::AssertEq(vec![0], vec![], None)], 1).is_err() + ); + } + + fn continuation_body(output: usize, yield_width: usize) -> Block { + Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + [( + G::ZERO, + Block { + ops: vec![Op::Const(G::ONE), Op::Const(G::TWO)], + ctrl: Ctrl::Yield(0, vec![2; yield_width]), + }, + )] + .into_iter() + .collect(), + Some(Box::new(Block { ops: vec![], ctrl: Ctrl::Return(1, vec![0]) })), + 1, + 0, + 0, + Box::new(Block { ops: vec![], ctrl: Ctrl::Return(2, vec![output]) }), + ), + } + } + + #[test] + fn continuations_expose_only_merged_values_and_check_every_selector() { + assert!(continuation_body(1, 1).check_emission(1, 3, None).is_ok()); + assert!(continuation_body(2, 1).check_emission(1, 3, None).is_err()); + assert!(continuation_body(1, 0).check_emission(1, 3, None).is_err()); + assert!(continuation_body(1, 2).check_emission(1, 3, None).is_err()); + assert!(continuation_body(1, 1).check_emission(1, 2, None).is_err()); + assert!( + Block { ops: vec![], ctrl: Ctrl::Return(1, vec![]) } + .check_emission(0, 1, None) + .is_err() + ); + assert!( + Block { ops: vec![], ctrl: Ctrl::Yield(0, vec![]) } + .check_emission(0, 1, None) + .is_err() + ); + } + + #[test] + fn siblings_restore_scope_and_native_scope_addition_is_checked() { + let block = Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + [ + ( + G::ZERO, + Block { + ops: vec![Op::Const(G::ONE)], + ctrl: Ctrl::Return(0, vec![1]), + }, + ), + (G::ONE, Block { ops: vec![], ctrl: Ctrl::Return(1, vec![1]) }), + ] + .into_iter() + .collect(), + None, + ), + }; + assert!(block.check_emission(1, 2, None).is_err()); + assert!(block.check_emission(2, 2, None).is_ok()); + assert!(check_emission_ops(&[Op::Const(G::ZERO)], usize::MAX).is_err()); + let block = Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + Default::default(), + None, + 1, + 0, + 0, + Box::new(Block { ops: vec![], ctrl: Ctrl::Return(0, vec![]) }), + ), + }; + assert!(block.check_emission(usize::MAX, 1, None).is_err()); + } + + #[test] + fn unused_advice_operands_do_not_become_constraint_requirements() { + let ignored = [ + Op::Call(usize::MAX, vec![usize::MAX], 2, true), + Op::UnconstrainedGInverse(usize::MAX), + Op::IOWrite(usize::MAX, vec![usize::MAX]), + ]; + assert_eq!(check_emission_ops(&ignored, 0), Ok(3)); + let mut top = malformed_operand(); + assert!(top.validate_emission().is_err()); + top.functions[0].constrained = false; + top.circuits.clear(); + assert!(top.validate_emission().is_ok()); + } +} diff --git a/crates/aiur/src/lib.rs b/crates/aiur/src/lib.rs index f14416cce..b1364c12a 100644 --- a/crates/aiur/src/lib.rs +++ b/crates/aiur/src/lib.rs @@ -1,6 +1,7 @@ pub mod bytecode; mod call_order; pub mod constraints; +mod emission_checks; pub mod execute; pub mod gadgets; mod lookup_budget; diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index d5b5fc6fb..29602a76d 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -151,6 +151,7 @@ impl AiurSystem { toplevel.checked_claim_shapes().expect("invalid Aiur lookup shapes"); toplevel.validate_call_components().expect("invalid Aiur call components"); toplevel.validate_row_counts().expect("invalid Aiur control counts"); + toplevel.validate_emission().expect("invalid Aiur emission inputs"); let mut circuit_inputs: Vec> = Vec::new(); let mut slot_widths: Vec> = Vec::new(); @@ -677,6 +678,7 @@ mod tests { mod branchless; mod byte_shapes; mod call_order; + mod constant_degree; mod host_timings; mod lookup_budget; mod lookup_groups; diff --git a/crates/aiur/src/synthesis/tests/constant_degree.rs b/crates/aiur/src/synthesis/tests/constant_degree.rs new file mode 100644 index 000000000..346d12aa6 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/constant_degree.rs @@ -0,0 +1,37 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; + +fn folded_zero_toplevel() -> Toplevel { + with_singleton_circuits( + vec![Function { + body: Block { + ops: vec![Op::Const(G::ZERO), Op::Mul(1, 0), Op::EqZero(2)], + ctrl: Ctrl::Return(0, vec![3]), + }, + // The compiler and witness builder retain the conservative product + // degree 1, so EqZero reserves two auxiliary columns. + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 9, + lookups: 4, + }, + entry: true, + constrained: true, + }], + vec![], + ) +} + +#[test] +fn folded_zero_product_can_be_tested_for_zero() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(folded_zero_toplevel(), cp, fp); + for input in [G::ZERO, G::ONE, G::from_u64(17), -G::ONE] { + let (claim, proof) = system.prove(0, &[input], &mut empty_io_buffer()); + assert_eq!(claim, vec![function_channel(), G::ZERO, input, G::ONE]); + system.verify(&claim, &proof).unwrap(); + } +} diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index fb81e90f5..6f3a2c32d 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -129,6 +129,22 @@ the fixed-table and global-count regressions do not claim another demonstrated false-result acceptance. See [metadata bounds](../crates/aiur/src/synthesis/tests/lookup_budget.rs) and [fixed tables](../crates/aiur/src/synthesis/tests/byte_shapes.rs). +## Constraint construction checks + +Before constructing a circuit, synthesis checks every constrained function's +logical operands, selector indices, word widths, and continuation merge +scopes. Sibling branches retain their incoming scope; a continuation sees +only the values yielded to it. Virtual carry outputs count as logical values +even when they allocate no column. These checks also apply to functions whose +component certificate removes all dynamic rank columns. Advice and I/O +operands unused by the constraint builder remain outside this scope check. + +Expression folding can produce a constant while conservative degree tracking +still assigns a positive degree, for example after multiplying an input by +zero. `EqZero` uses its constant shortcut only when the tracked degree is +also zero. Otherwise it retains the witness columns and constraints selected +by the compiler, so construction and execution agree on the allocation. + ## Native Merkle cap coverage The native binary MMCS injects shorter matrices while walking from the From 11be019508abe48573cdb11063c3db8b40f1c607 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 18:20:40 -0400 Subject: [PATCH 21/30] Port and audit Aiur proofs on optimized layouts Import the scoped Aiur proof and native-binding components onto the newer kernel base without the independent compiler library. Adapt generic calls to six gap columns and derived child ranks, prove component relayout preserves complete evaluation and arity, and model all three allocation modes. Generic physical extraction explicitly retains its layout premise pending the full component-mode extension. Bind compiled keys after production lookup retuning. Preserve the destination fresh-name implementation while fixing demonstrated array-update effect order and explicit-return inlining errors. Review and freeze 1,574 root statements, 988 premise sections and 197 runtime workers, with the source migration review beside the manifest. Validation: check-aiur; check-kernel --with-model; 112 parallel native release tests; all-target parallel Clippy with warnings denied; format; three generated executor checks; Lean proving/components/byte hints/recursive-verifier/aggregate suites; full ignored IxVM corpus and unchanged shard FFT cost. --- Cargo.lock | 27 + Ix/Aiur/Blake3.lean | 155 + Ix/Aiur/BoundVerifier.lean | 143 + Ix/Aiur/Branchless.lean | 27 + Ix/Aiur/Challenger.lean | 91 + Ix/Aiur/CompiledKey.lean | 93 + Ix/Aiur/CompiledVerifier.lean | 48 + Ix/Aiur/Compiler.lean | 19 +- Ix/Aiur/Compiler/Dedup.lean | 45 +- Ix/Aiur/Compiler/Layout.lean | 9 +- Ix/Aiur/Compiler/Lower.lean | 2 +- Ix/Aiur/Domain.lean | 66 + Ix/Aiur/EmissionChecks.lean | 119 + Ix/Aiur/Extension.lean | 47 + Ix/Aiur/ExtensionMmcs.lean | 62 + Ix/Aiur/Folding.lean | 40 + Ix/Aiur/FriDomain.lean | 31 + Ix/Aiur/FriQuery.lean | 92 + Ix/Aiur/Interpolation.lean | 59 + Ix/Aiur/KeyCodec.lean | 239 + Ix/Aiur/LogUp.lean | 81 + Ix/Aiur/LookupCoordinates.lean | 50 + Ix/Aiur/LookupGroups.lean | 108 + Ix/Aiur/LookupShapes.lean | 114 + Ix/Aiur/Merkle.lean | 113 + Ix/Aiur/MerkleCap.lean | 24 + Ix/Aiur/Polynomial.lean | 52 + Ix/Aiur/ProofCodec.lean | 168 + Ix/Aiur/ProofShape.lean | 108 + Ix/Aiur/Proofs.lean | 70 + Ix/Aiur/Proofs/Activity.lean | 60 + Ix/Aiur/Proofs/Audit.lean | 4033 +++ Ix/Aiur/Proofs/Blake3.lean | 402 + Ix/Aiur/Proofs/BlockAllocation.lean | 210 + Ix/Aiur/Proofs/BlockCompletion.lean | 175 + Ix/Aiur/Proofs/BlockDegrees.lean | 101 + Ix/Aiur/Proofs/BlockExpressions.lean | 734 + Ix/Aiur/Proofs/BlockLookups.lean | 69 + Ix/Aiur/Proofs/BlockQueryPool.lean | 71 + Ix/Aiur/Proofs/BlockQuerySlots.lean | 303 + Ix/Aiur/Proofs/BlockReflection.lean | 412 + Ix/Aiur/Proofs/BlockRowCalls.lean | 273 + Ix/Aiur/Proofs/BlockRowExecution.lean | 666 + Ix/Aiur/Proofs/BlockRowInputs.lean | 312 + Ix/Aiur/Proofs/BlockRowProjection.lean | 436 + Ix/Aiur/Proofs/BlockRows.lean | 159 + Ix/Aiur/Proofs/BlockSelectors.lean | 180 + Ix/Aiur/Proofs/BranchSelection.lean | 117 + Ix/Aiur/Proofs/BranchlessSlots.lean | 178 + Ix/Aiur/Proofs/ByteArithmetic.lean | 185 + Ix/Aiur/Proofs/ByteColumns.lean | 374 + Ix/Aiur/Proofs/ByteLookups.lean | 284 + Ix/Aiur/Proofs/CallInventory.lean | 108 + Ix/Aiur/Proofs/CallOrder.lean | 161 + Ix/Aiur/Proofs/Challenger.lean | 375 + Ix/Aiur/Proofs/CheckedCircuit.lean | 89 + Ix/Aiur/Proofs/CircuitAllocation.lean | 216 + Ix/Aiur/Proofs/CircuitCompletion.lean | 114 + Ix/Aiur/Proofs/CircuitExpressions.lean | 272 + Ix/Aiur/Proofs/CircuitLayout.lean | 286 + Ix/Aiur/Proofs/CircuitMembership.lean | 234 + Ix/Aiur/Proofs/CircuitPoolExecution.lean | 114 + Ix/Aiur/Proofs/CircuitReflection.lean | 171 + Ix/Aiur/Proofs/CircuitRowCounts.lean | 133 + Ix/Aiur/Proofs/CircuitRowExecution.lean | 54 + Ix/Aiur/Proofs/CircuitRowMembers.lean | 203 + Ix/Aiur/Proofs/CircuitRowQueries.lean | 170 + Ix/Aiur/Proofs/CircuitRowReturns.lean | 117 + Ix/Aiur/Proofs/CircuitRows.lean | 103 + Ix/Aiur/Proofs/CircuitTableData.lean | 130 + Ix/Aiur/Proofs/CircuitTableExecution.lean | 152 + Ix/Aiur/Proofs/CircuitTraces.lean | 217 + Ix/Aiur/Proofs/Compilation.lean | 126 + Ix/Aiur/Proofs/CompiledCircuitRows.lean | 68 + Ix/Aiur/Proofs/CompiledKey.lean | 315 + Ix/Aiur/Proofs/CompilerAllocation.lean | 45 + Ix/Aiur/Proofs/CompilerBranches.lean | 149 + Ix/Aiur/Proofs/CompilerLayout.lean | 387 + Ix/Aiur/Proofs/Dedup.lean | 67 + Ix/Aiur/Proofs/Domain.lean | 179 + Ix/Aiur/Proofs/DomainAccumulator.lean | 142 + Ix/Aiur/Proofs/EmissionAllocation.lean | 314 + Ix/Aiur/Proofs/EmissionControls.lean | 130 + Ix/Aiur/Proofs/EmissionInputs.lean | 172 + Ix/Aiur/Proofs/EncodedCircuitExecution.lean | 159 + Ix/Aiur/Proofs/Execution.lean | 182 + Ix/Aiur/Proofs/ExpressionGraph.lean | 561 + Ix/Aiur/Proofs/Extension.lean | 220 + Ix/Aiur/Proofs/ExtensionField.lean | 108 + Ix/Aiur/Proofs/ExtensionMmcs.lean | 255 + Ix/Aiur/Proofs/Field.lean | 268 + Ix/Aiur/Proofs/Folding.lean | 202 + Ix/Aiur/Proofs/FriDomain.lean | 286 + Ix/Aiur/Proofs/FriQuery.lean | 355 + Ix/Aiur/Proofs/FrontendExpressions.lean | 647 + Ix/Aiur/Proofs/FunctionLayout.lean | 198 + Ix/Aiur/Proofs/FunctionRows.lean | 168 + Ix/Aiur/Proofs/GlobalLookups.lean | 536 + Ix/Aiur/Proofs/GoldilocksAlgebra.lean | 157 + Ix/Aiur/Proofs/GoldilocksInverse.lean | 137 + Ix/Aiur/Proofs/GraphCompilation.lean | 757 + Ix/Aiur/Proofs/GraphCompletion.lean | 162 + Ix/Aiur/Proofs/GraphWidths.lean | 163 + Ix/Aiur/Proofs/Grouping.lean | 134 + Ix/Aiur/Proofs/InactiveRows.lean | 378 + Ix/Aiur/Proofs/Interpolation.lean | 408 + Ix/Aiur/Proofs/KeyArtifact.lean | 63 + Ix/Aiur/Proofs/KeyCodec.lean | 462 + Ix/Aiur/Proofs/LayoutProjection.lean | 165 + Ix/Aiur/Proofs/LayoutState.lean | 109 + Ix/Aiur/Proofs/LocalConstraints.lean | 190 + Ix/Aiur/Proofs/LogUp.lean | 248 + Ix/Aiur/Proofs/LogUpAccumulator.lean | 109 + Ix/Aiur/Proofs/LogUpAlgebra.lean | 195 + Ix/Aiur/Proofs/LogUpFractions.lean | 151 + Ix/Aiur/Proofs/Lookup.lean | 168 + Ix/Aiur/Proofs/LookupBudget.lean | 268 + Ix/Aiur/Proofs/LookupCoordinates.lean | 199 + Ix/Aiur/Proofs/LookupExpressions.lean | 248 + Ix/Aiur/Proofs/LookupLayout.lean | 1079 + Ix/Aiur/Proofs/LookupMessages.lean | 371 + Ix/Aiur/Proofs/LookupShapes.lean | 264 + Ix/Aiur/Proofs/Memory.lean | 236 + Ix/Aiur/Proofs/MemoryColumns.lean | 463 + Ix/Aiur/Proofs/Merkle.lean | 467 + Ix/Aiur/Proofs/MerkleCap.lean | 168 + Ix/Aiur/Proofs/Metadata.lean | 185 + Ix/Aiur/Proofs/NormalizationFrames.lean | 162 + Ix/Aiur/Proofs/OpeningShape.lean | 144 + Ix/Aiur/Proofs/OperationAllocation.lean | 75 + Ix/Aiur/Proofs/OperationDegrees.lean | 343 + Ix/Aiur/Proofs/OperationExpressions.lean | 1098 + Ix/Aiur/Proofs/OperationReflection.lean | 495 + Ix/Aiur/Proofs/OperationRows.lean | 662 + Ix/Aiur/Proofs/OperationSequences.lean | 207 + Ix/Aiur/Proofs/Polynomial.lean | 463 + Ix/Aiur/Proofs/ProofCodec.lean | 315 + Ix/Aiur/Proofs/ProofShape.lean | 173 + Ix/Aiur/Proofs/ProviderEquivalence.lean | 103 + Ix/Aiur/Proofs/PrunedMerkle.lean | 743 + Ix/Aiur/Proofs/PublicCircuitExecution.lean | 78 + Ix/Aiur/Proofs/QuerySlotMessages.lean | 216 + Ix/Aiur/Proofs/QuerySlots.lean | 203 + Ix/Aiur/Proofs/Quotient.lean | 114 + Ix/Aiur/Proofs/QuotientAlgebra.lean | 93 + Ix/Aiur/Proofs/Relayout.lean | 346 + Ix/Aiur/Proofs/Renaming.lean | 284 + Ix/Aiur/Proofs/ReturnGates.lean | 214 + Ix/Aiur/Proofs/RowCounts.lean | 236 + Ix/Aiur/Proofs/SelectorAlgebra.lean | 78 + Ix/Aiur/Proofs/SelectorControl.lean | 377 + Ix/Aiur/Proofs/SelectorMessages.lean | 217 + Ix/Aiur/Proofs/Selectors.lean | 130 + Ix/Aiur/Proofs/ShapedVerifier.lean | 61 + Ix/Aiur/Proofs/TableExpressions.lean | 115 + Ix/Aiur/Proofs/TailMatches.lean | 85 + Ix/Aiur/Proofs/Transcript.lean | 179 + Ix/Aiur/Proofs/VerifierAccumulator.lean | 232 + Ix/Aiur/Proofs/VerifierArithmetic.lean | 173 + Ix/Aiur/PrunedMerkle.lean | 155 + Ix/Aiur/Quotient.lean | 37 + Ix/Aiur/RowCounts.lean | 105 + Ix/Aiur/Semantics/AIR.lean | 214 + Ix/Aiur/Semantics/BytecodeEval.lean | 11 +- Ix/Aiur/Semantics/Flatten.lean | 29 +- Ix/Aiur/Semantics/SourceEval.lean | 17 +- Ix/Aiur/ShapedVerifier.lean | 57 + Ix/Aiur/Stages/Bytecode.lean | 207 +- Ix/Aiur/Stages/Source.lean | 72 +- Ix/Aiur/Transcript.lean | 73 + Ix/Aiur/VerifierArithmetic.lean | 105 + Ix/MultiStark/SystemDeserialize.lean | 10 +- Tests/Aiur/AIRSemantics.lean | 189 + Tests/Aiur/Backend.lean | 108 + Tests/Aiur/Blake3.lean | 95 + Tests/Aiur/BlockExpressions.lean | 119 + Tests/Aiur/BlockRows.lean | 127 + Tests/Aiur/ByteGadgets.lean | 71 + Tests/Aiur/BytecodeCompare.lean | 70 + Tests/Aiur/CircuitExpressions.lean | 121 + Tests/Aiur/CircuitRows.lean | 169 + Tests/Aiur/CompiledKey.lean | 155 + Tests/Aiur/ConstantDegree.lean | 65 + Tests/Aiur/Dedup.lean | 111 + Tests/Aiur/DedupFixtures.lean | 59 + Tests/Aiur/Domain.lean | 135 + Tests/Aiur/EmissionChecks.lean | 89 + Tests/Aiur/EmissionReader.lean | 155 + Tests/Aiur/ExpressionGraph.lean | 156 + Tests/Aiur/Extension.lean | 122 + Tests/Aiur/ExtensionMmcs.lean | 130 + Tests/Aiur/Folding.lean | 152 + Tests/Aiur/FriDomain.lean | 113 + Tests/Aiur/FriQuery.lean | 212 + Tests/Aiur/FrontendExpressions.lean | 181 + Tests/Aiur/GraphCompilation.lean | 189 + Tests/Aiur/Hoisting.lean | 97 + Tests/Aiur/Interpolation.lean | 123 + Tests/Aiur/KeyCodec.lean | 74 + Tests/Aiur/LogUp.lean | 150 + Tests/Aiur/LookupBudget.lean | 61 + Tests/Aiur/LookupShapes.lean | 95 + Tests/Aiur/MemoryRows.lean | 72 + Tests/Aiur/Merkle.lean | 82 + Tests/Aiur/MerkleCap.lean | 38 + Tests/Aiur/OperationExpressions.lean | 138 + Tests/Aiur/OperationRows.lean | 144 + Tests/Aiur/Polynomial.lean | 125 + Tests/Aiur/ProofCodec.lean | 92 + Tests/Aiur/ProofShape.lean | 63 + Tests/Aiur/PrunedMerkle.lean | 97 + Tests/Aiur/SelectorControl.lean | 110 + Tests/Aiur/SourceValues.lean | 43 + Tests/Aiur/TailMatches.lean | 81 + Tests/Aiur/TraceHeights.lean | 49 + Tests/Aiur/Transcript.lean | 212 + Tests/Aiur/VerifierArithmetic.lean | 172 + Tests/Aiur/backend-foundation-review.md | 52 + Tests/Aiur/backend-foundation.txt | 27004 ++++++++++++++++ Tests/Aiur/bytecode-compatibility.txt | 396 + Tests/Aiur/dedup-compatibility.txt | 1333 + Tests/Aiur/source-value-compatibility.txt | 100 + Tests/Aiur/tail-match-compatibility.txt | 282 + crates/aiur/Cargo.toml | 15 +- crates/aiur/src/constraints.rs | 2 + crates/aiur/src/constraints/tests.rs | 290 + .../constraints/tests/block_expressions.rs | 194 + .../aiur/src/constraints/tests/block_rows.rs | 168 + .../constraints/tests/circuit_expressions.rs | 138 + .../src/constraints/tests/circuit_rows.rs | 219 + .../src/constraints/tests/compiled_keys.rs | 217 + .../src/constraints/tests/emission_checks.rs | 192 + .../constraints/tests/frontend_expressions.rs | 238 + .../aiur/src/constraints/tests/memory_rows.rs | 101 + .../tests/operation_expressions.rs | 301 + .../src/constraints/tests/operation_rows.rs | 246 + crates/aiur/src/graph_shape.rs | 184 + crates/aiur/src/lib.rs | 1 + crates/aiur/src/synthesis.rs | 16 + crates/aiur/src/synthesis/tests/advice.rs | 156 + crates/aiur/src/synthesis/tests/blake3.rs | 101 + .../aiur/src/synthesis/tests/byte_gadgets.rs | 243 + .../aiur/src/synthesis/tests/byte_shapes.rs | 49 + .../src/synthesis/tests/extension_mmcs.rs | 363 + crates/aiur/src/synthesis/tests/folding.rs | 230 + crates/aiur/src/synthesis/tests/fri_domain.rs | 180 + crates/aiur/src/synthesis/tests/fri_query.rs | 439 + .../aiur/src/synthesis/tests/interpolation.rs | 174 + .../aiur/src/synthesis/tests/lookup_budget.rs | 71 + .../aiur/src/synthesis/tests/lookup_shapes.rs | 163 + crates/aiur/src/synthesis/tests/memory.rs | 112 + crates/aiur/src/synthesis/tests/merkle.rs | 286 + crates/aiur/src/synthesis/tests/mmcs.rs | 10 +- crates/aiur/src/synthesis/tests/polynomial.rs | 214 + .../aiur/src/synthesis/tests/proof_codec.rs | 258 + .../aiur/src/synthesis/tests/proof_shapes.rs | 206 + .../aiur/src/synthesis/tests/pruned_merkle.rs | 278 + crates/aiur/src/synthesis/tests/scalar.rs | 125 + crates/aiur/src/synthesis/tests/transcript.rs | 379 + crates/aiur/src/vk_codec.rs | 240 +- crates/aiur/src/vk_codec/tests/codec.rs | 297 + crates/aiur/src/vk_codec/tests/compilation.rs | 490 + crates/aiur/src/vk_codec/tests/domain.rs | 249 + .../vk_codec/tests/extension_arithmetic.rs | 256 + crates/aiur/src/vk_codec/tests/graphs.rs | 286 + crates/aiur/src/vk_codec/tests/logup.rs | 355 + .../src/vk_codec/tests/verifier_arithmetic.rs | 432 + docs/aiur-soundness.md | 40 + lakefile.lean | 318 + 269 files changed, 83119 insertions(+), 85 deletions(-) create mode 100644 Ix/Aiur/Blake3.lean create mode 100644 Ix/Aiur/BoundVerifier.lean create mode 100644 Ix/Aiur/Branchless.lean create mode 100644 Ix/Aiur/Challenger.lean create mode 100644 Ix/Aiur/CompiledKey.lean create mode 100644 Ix/Aiur/CompiledVerifier.lean create mode 100644 Ix/Aiur/Domain.lean create mode 100644 Ix/Aiur/EmissionChecks.lean create mode 100644 Ix/Aiur/Extension.lean create mode 100644 Ix/Aiur/ExtensionMmcs.lean create mode 100644 Ix/Aiur/Folding.lean create mode 100644 Ix/Aiur/FriDomain.lean create mode 100644 Ix/Aiur/FriQuery.lean create mode 100644 Ix/Aiur/Interpolation.lean create mode 100644 Ix/Aiur/KeyCodec.lean create mode 100644 Ix/Aiur/LogUp.lean create mode 100644 Ix/Aiur/LookupCoordinates.lean create mode 100644 Ix/Aiur/LookupGroups.lean create mode 100644 Ix/Aiur/LookupShapes.lean create mode 100644 Ix/Aiur/Merkle.lean create mode 100644 Ix/Aiur/MerkleCap.lean create mode 100644 Ix/Aiur/Polynomial.lean create mode 100644 Ix/Aiur/ProofCodec.lean create mode 100644 Ix/Aiur/ProofShape.lean create mode 100644 Ix/Aiur/Proofs.lean create mode 100644 Ix/Aiur/Proofs/Activity.lean create mode 100644 Ix/Aiur/Proofs/Audit.lean create mode 100644 Ix/Aiur/Proofs/Blake3.lean create mode 100644 Ix/Aiur/Proofs/BlockAllocation.lean create mode 100644 Ix/Aiur/Proofs/BlockCompletion.lean create mode 100644 Ix/Aiur/Proofs/BlockDegrees.lean create mode 100644 Ix/Aiur/Proofs/BlockExpressions.lean create mode 100644 Ix/Aiur/Proofs/BlockLookups.lean create mode 100644 Ix/Aiur/Proofs/BlockQueryPool.lean create mode 100644 Ix/Aiur/Proofs/BlockQuerySlots.lean create mode 100644 Ix/Aiur/Proofs/BlockReflection.lean create mode 100644 Ix/Aiur/Proofs/BlockRowCalls.lean create mode 100644 Ix/Aiur/Proofs/BlockRowExecution.lean create mode 100644 Ix/Aiur/Proofs/BlockRowInputs.lean create mode 100644 Ix/Aiur/Proofs/BlockRowProjection.lean create mode 100644 Ix/Aiur/Proofs/BlockRows.lean create mode 100644 Ix/Aiur/Proofs/BlockSelectors.lean create mode 100644 Ix/Aiur/Proofs/BranchSelection.lean create mode 100644 Ix/Aiur/Proofs/BranchlessSlots.lean create mode 100644 Ix/Aiur/Proofs/ByteArithmetic.lean create mode 100644 Ix/Aiur/Proofs/ByteColumns.lean create mode 100644 Ix/Aiur/Proofs/ByteLookups.lean create mode 100644 Ix/Aiur/Proofs/CallInventory.lean create mode 100644 Ix/Aiur/Proofs/CallOrder.lean create mode 100644 Ix/Aiur/Proofs/Challenger.lean create mode 100644 Ix/Aiur/Proofs/CheckedCircuit.lean create mode 100644 Ix/Aiur/Proofs/CircuitAllocation.lean create mode 100644 Ix/Aiur/Proofs/CircuitCompletion.lean create mode 100644 Ix/Aiur/Proofs/CircuitExpressions.lean create mode 100644 Ix/Aiur/Proofs/CircuitLayout.lean create mode 100644 Ix/Aiur/Proofs/CircuitMembership.lean create mode 100644 Ix/Aiur/Proofs/CircuitPoolExecution.lean create mode 100644 Ix/Aiur/Proofs/CircuitReflection.lean create mode 100644 Ix/Aiur/Proofs/CircuitRowCounts.lean create mode 100644 Ix/Aiur/Proofs/CircuitRowExecution.lean create mode 100644 Ix/Aiur/Proofs/CircuitRowMembers.lean create mode 100644 Ix/Aiur/Proofs/CircuitRowQueries.lean create mode 100644 Ix/Aiur/Proofs/CircuitRowReturns.lean create mode 100644 Ix/Aiur/Proofs/CircuitRows.lean create mode 100644 Ix/Aiur/Proofs/CircuitTableData.lean create mode 100644 Ix/Aiur/Proofs/CircuitTableExecution.lean create mode 100644 Ix/Aiur/Proofs/CircuitTraces.lean create mode 100644 Ix/Aiur/Proofs/Compilation.lean create mode 100644 Ix/Aiur/Proofs/CompiledCircuitRows.lean create mode 100644 Ix/Aiur/Proofs/CompiledKey.lean create mode 100644 Ix/Aiur/Proofs/CompilerAllocation.lean create mode 100644 Ix/Aiur/Proofs/CompilerBranches.lean create mode 100644 Ix/Aiur/Proofs/CompilerLayout.lean create mode 100644 Ix/Aiur/Proofs/Dedup.lean create mode 100644 Ix/Aiur/Proofs/Domain.lean create mode 100644 Ix/Aiur/Proofs/DomainAccumulator.lean create mode 100644 Ix/Aiur/Proofs/EmissionAllocation.lean create mode 100644 Ix/Aiur/Proofs/EmissionControls.lean create mode 100644 Ix/Aiur/Proofs/EmissionInputs.lean create mode 100644 Ix/Aiur/Proofs/EncodedCircuitExecution.lean create mode 100644 Ix/Aiur/Proofs/Execution.lean create mode 100644 Ix/Aiur/Proofs/ExpressionGraph.lean create mode 100644 Ix/Aiur/Proofs/Extension.lean create mode 100644 Ix/Aiur/Proofs/ExtensionField.lean create mode 100644 Ix/Aiur/Proofs/ExtensionMmcs.lean create mode 100644 Ix/Aiur/Proofs/Field.lean create mode 100644 Ix/Aiur/Proofs/Folding.lean create mode 100644 Ix/Aiur/Proofs/FriDomain.lean create mode 100644 Ix/Aiur/Proofs/FriQuery.lean create mode 100644 Ix/Aiur/Proofs/FrontendExpressions.lean create mode 100644 Ix/Aiur/Proofs/FunctionLayout.lean create mode 100644 Ix/Aiur/Proofs/FunctionRows.lean create mode 100644 Ix/Aiur/Proofs/GlobalLookups.lean create mode 100644 Ix/Aiur/Proofs/GoldilocksAlgebra.lean create mode 100644 Ix/Aiur/Proofs/GoldilocksInverse.lean create mode 100644 Ix/Aiur/Proofs/GraphCompilation.lean create mode 100644 Ix/Aiur/Proofs/GraphCompletion.lean create mode 100644 Ix/Aiur/Proofs/GraphWidths.lean create mode 100644 Ix/Aiur/Proofs/Grouping.lean create mode 100644 Ix/Aiur/Proofs/InactiveRows.lean create mode 100644 Ix/Aiur/Proofs/Interpolation.lean create mode 100644 Ix/Aiur/Proofs/KeyArtifact.lean create mode 100644 Ix/Aiur/Proofs/KeyCodec.lean create mode 100644 Ix/Aiur/Proofs/LayoutProjection.lean create mode 100644 Ix/Aiur/Proofs/LayoutState.lean create mode 100644 Ix/Aiur/Proofs/LocalConstraints.lean create mode 100644 Ix/Aiur/Proofs/LogUp.lean create mode 100644 Ix/Aiur/Proofs/LogUpAccumulator.lean create mode 100644 Ix/Aiur/Proofs/LogUpAlgebra.lean create mode 100644 Ix/Aiur/Proofs/LogUpFractions.lean create mode 100644 Ix/Aiur/Proofs/Lookup.lean create mode 100644 Ix/Aiur/Proofs/LookupBudget.lean create mode 100644 Ix/Aiur/Proofs/LookupCoordinates.lean create mode 100644 Ix/Aiur/Proofs/LookupExpressions.lean create mode 100644 Ix/Aiur/Proofs/LookupLayout.lean create mode 100644 Ix/Aiur/Proofs/LookupMessages.lean create mode 100644 Ix/Aiur/Proofs/LookupShapes.lean create mode 100644 Ix/Aiur/Proofs/Memory.lean create mode 100644 Ix/Aiur/Proofs/MemoryColumns.lean create mode 100644 Ix/Aiur/Proofs/Merkle.lean create mode 100644 Ix/Aiur/Proofs/MerkleCap.lean create mode 100644 Ix/Aiur/Proofs/Metadata.lean create mode 100644 Ix/Aiur/Proofs/NormalizationFrames.lean create mode 100644 Ix/Aiur/Proofs/OpeningShape.lean create mode 100644 Ix/Aiur/Proofs/OperationAllocation.lean create mode 100644 Ix/Aiur/Proofs/OperationDegrees.lean create mode 100644 Ix/Aiur/Proofs/OperationExpressions.lean create mode 100644 Ix/Aiur/Proofs/OperationReflection.lean create mode 100644 Ix/Aiur/Proofs/OperationRows.lean create mode 100644 Ix/Aiur/Proofs/OperationSequences.lean create mode 100644 Ix/Aiur/Proofs/Polynomial.lean create mode 100644 Ix/Aiur/Proofs/ProofCodec.lean create mode 100644 Ix/Aiur/Proofs/ProofShape.lean create mode 100644 Ix/Aiur/Proofs/ProviderEquivalence.lean create mode 100644 Ix/Aiur/Proofs/PrunedMerkle.lean create mode 100644 Ix/Aiur/Proofs/PublicCircuitExecution.lean create mode 100644 Ix/Aiur/Proofs/QuerySlotMessages.lean create mode 100644 Ix/Aiur/Proofs/QuerySlots.lean create mode 100644 Ix/Aiur/Proofs/Quotient.lean create mode 100644 Ix/Aiur/Proofs/QuotientAlgebra.lean create mode 100644 Ix/Aiur/Proofs/Relayout.lean create mode 100644 Ix/Aiur/Proofs/Renaming.lean create mode 100644 Ix/Aiur/Proofs/ReturnGates.lean create mode 100644 Ix/Aiur/Proofs/RowCounts.lean create mode 100644 Ix/Aiur/Proofs/SelectorAlgebra.lean create mode 100644 Ix/Aiur/Proofs/SelectorControl.lean create mode 100644 Ix/Aiur/Proofs/SelectorMessages.lean create mode 100644 Ix/Aiur/Proofs/Selectors.lean create mode 100644 Ix/Aiur/Proofs/ShapedVerifier.lean create mode 100644 Ix/Aiur/Proofs/TableExpressions.lean create mode 100644 Ix/Aiur/Proofs/TailMatches.lean create mode 100644 Ix/Aiur/Proofs/Transcript.lean create mode 100644 Ix/Aiur/Proofs/VerifierAccumulator.lean create mode 100644 Ix/Aiur/Proofs/VerifierArithmetic.lean create mode 100644 Ix/Aiur/PrunedMerkle.lean create mode 100644 Ix/Aiur/Quotient.lean create mode 100644 Ix/Aiur/RowCounts.lean create mode 100644 Ix/Aiur/Semantics/AIR.lean create mode 100644 Ix/Aiur/ShapedVerifier.lean create mode 100644 Ix/Aiur/Transcript.lean create mode 100644 Ix/Aiur/VerifierArithmetic.lean create mode 100644 Tests/Aiur/AIRSemantics.lean create mode 100644 Tests/Aiur/Backend.lean create mode 100644 Tests/Aiur/Blake3.lean create mode 100644 Tests/Aiur/BlockExpressions.lean create mode 100644 Tests/Aiur/BlockRows.lean create mode 100644 Tests/Aiur/ByteGadgets.lean create mode 100644 Tests/Aiur/BytecodeCompare.lean create mode 100644 Tests/Aiur/CircuitExpressions.lean create mode 100644 Tests/Aiur/CircuitRows.lean create mode 100644 Tests/Aiur/CompiledKey.lean create mode 100644 Tests/Aiur/ConstantDegree.lean create mode 100644 Tests/Aiur/Dedup.lean create mode 100644 Tests/Aiur/DedupFixtures.lean create mode 100644 Tests/Aiur/Domain.lean create mode 100644 Tests/Aiur/EmissionChecks.lean create mode 100644 Tests/Aiur/EmissionReader.lean create mode 100644 Tests/Aiur/ExpressionGraph.lean create mode 100644 Tests/Aiur/Extension.lean create mode 100644 Tests/Aiur/ExtensionMmcs.lean create mode 100644 Tests/Aiur/Folding.lean create mode 100644 Tests/Aiur/FriDomain.lean create mode 100644 Tests/Aiur/FriQuery.lean create mode 100644 Tests/Aiur/FrontendExpressions.lean create mode 100644 Tests/Aiur/GraphCompilation.lean create mode 100644 Tests/Aiur/Hoisting.lean create mode 100644 Tests/Aiur/Interpolation.lean create mode 100644 Tests/Aiur/KeyCodec.lean create mode 100644 Tests/Aiur/LogUp.lean create mode 100644 Tests/Aiur/LookupBudget.lean create mode 100644 Tests/Aiur/LookupShapes.lean create mode 100644 Tests/Aiur/MemoryRows.lean create mode 100644 Tests/Aiur/Merkle.lean create mode 100644 Tests/Aiur/MerkleCap.lean create mode 100644 Tests/Aiur/OperationExpressions.lean create mode 100644 Tests/Aiur/OperationRows.lean create mode 100644 Tests/Aiur/Polynomial.lean create mode 100644 Tests/Aiur/ProofCodec.lean create mode 100644 Tests/Aiur/ProofShape.lean create mode 100644 Tests/Aiur/PrunedMerkle.lean create mode 100644 Tests/Aiur/SelectorControl.lean create mode 100644 Tests/Aiur/SourceValues.lean create mode 100644 Tests/Aiur/TailMatches.lean create mode 100644 Tests/Aiur/TraceHeights.lean create mode 100644 Tests/Aiur/Transcript.lean create mode 100644 Tests/Aiur/VerifierArithmetic.lean create mode 100644 Tests/Aiur/backend-foundation-review.md create mode 100644 Tests/Aiur/backend-foundation.txt create mode 100644 Tests/Aiur/bytecode-compatibility.txt create mode 100644 Tests/Aiur/dedup-compatibility.txt create mode 100644 Tests/Aiur/source-value-compatibility.txt create mode 100644 Tests/Aiur/tail-match-compatibility.txt create mode 100644 crates/aiur/src/constraints/tests.rs create mode 100644 crates/aiur/src/constraints/tests/block_expressions.rs create mode 100644 crates/aiur/src/constraints/tests/block_rows.rs create mode 100644 crates/aiur/src/constraints/tests/circuit_expressions.rs create mode 100644 crates/aiur/src/constraints/tests/circuit_rows.rs create mode 100644 crates/aiur/src/constraints/tests/compiled_keys.rs create mode 100644 crates/aiur/src/constraints/tests/emission_checks.rs create mode 100644 crates/aiur/src/constraints/tests/frontend_expressions.rs create mode 100644 crates/aiur/src/constraints/tests/memory_rows.rs create mode 100644 crates/aiur/src/constraints/tests/operation_expressions.rs create mode 100644 crates/aiur/src/constraints/tests/operation_rows.rs create mode 100644 crates/aiur/src/graph_shape.rs create mode 100644 crates/aiur/src/synthesis/tests/advice.rs create mode 100644 crates/aiur/src/synthesis/tests/blake3.rs create mode 100644 crates/aiur/src/synthesis/tests/byte_gadgets.rs create mode 100644 crates/aiur/src/synthesis/tests/extension_mmcs.rs create mode 100644 crates/aiur/src/synthesis/tests/folding.rs create mode 100644 crates/aiur/src/synthesis/tests/fri_domain.rs create mode 100644 crates/aiur/src/synthesis/tests/fri_query.rs create mode 100644 crates/aiur/src/synthesis/tests/interpolation.rs create mode 100644 crates/aiur/src/synthesis/tests/memory.rs create mode 100644 crates/aiur/src/synthesis/tests/merkle.rs create mode 100644 crates/aiur/src/synthesis/tests/polynomial.rs create mode 100644 crates/aiur/src/synthesis/tests/proof_codec.rs create mode 100644 crates/aiur/src/synthesis/tests/proof_shapes.rs create mode 100644 crates/aiur/src/synthesis/tests/pruned_merkle.rs create mode 100644 crates/aiur/src/synthesis/tests/scalar.rs create mode 100644 crates/aiur/src/synthesis/tests/transcript.rs create mode 100644 crates/aiur/src/vk_codec/tests/codec.rs create mode 100644 crates/aiur/src/vk_codec/tests/compilation.rs create mode 100644 crates/aiur/src/vk_codec/tests/domain.rs create mode 100644 crates/aiur/src/vk_codec/tests/extension_arithmetic.rs create mode 100644 crates/aiur/src/vk_codec/tests/graphs.rs create mode 100644 crates/aiur/src/vk_codec/tests/logup.rs create mode 100644 crates/aiur/src/vk_codec/tests/verifier_arithmetic.rs diff --git a/Cargo.lock b/Cargo.lock index ee41938d4..447526296 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,14 +50,20 @@ dependencies = [ name = "aiur" version = "0.1.0" dependencies = [ + "blake3", "hashbrown 0.15.5", "indexmap", "libc", "multi-stark", "num-bigint 0.4.6", "p3-blake3", + "p3-challenger", "p3-commit", + "p3-fri", + "p3-merkle-tree", + "p3-stir", "p3-symmetric", + "p3-util", "rayon", "rustc-hash", "tracing", @@ -2765,6 +2771,27 @@ dependencies = [ "serde", ] +[[package]] +name = "p3-stir" +version = "0.6.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=3152b14a89067c83775a8076cc262ffc48a1fd7c#3152b14a89067c83775a8076cc262ffc48a1fd7c" +dependencies = [ + "itertools 0.15.0", + "libm", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-security", + "p3-util", + "serde", + "spin 0.12.3", + "thiserror", + "tracing", +] + [[package]] name = "p3-symmetric" version = "0.6.0" diff --git a/Ix/Aiur/Blake3.lean b/Ix/Aiur/Blake3.lean new file mode 100644 index 000000000..ec56f77d5 --- /dev/null +++ b/Ix/Aiur/Blake3.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Transcript + +/-! Total, unkeyed, 32-byte BLAKE3 for the native transcript and PCS. +Words and compression blocks have checked dimensions. The canonical tree +splits at the largest power of two strictly below the input byte length. +The native input bound is separate from the total mathematical function. +-/ + +namespace Aiur.NativeAIR.Blake3 + +abbrev CV := Vector UInt32 8 +abbrev Block := Vector UInt32 16 +abbrev Digest := Vector UInt8 32 + +def iv : CV := #v[ + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19] + +def schedules : Vector (Vector (Fin 16) 16) 7 := #v[ + #v[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + #v[2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8], + #v[3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1], + #v[10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6], + #v[12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4], + #v[9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7], + #v[11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13]] + +def rotateRight (word count : UInt32) : UInt32 := + (word >>> count) ||| (word <<< (32 - count)) + +def mix (a b c d x y : UInt32) : Vector UInt32 4 := + let a := a + b + x + let d := rotateRight (d ^^^ a) 16 + let c := c + d + let b := rotateRight (b ^^^ c) 12 + let a := a + b + y + let d := rotateRight (d ^^^ a) 8 + let c := c + d + let b := rotateRight (b ^^^ c) 7 + #v[a, b, c, d] + +def g (state : Block) (a b c d : Fin 16) (x y : UInt32) : Block := + let words := mix state[a] state[b] state[c] state[d] x y + (((state.set a words[0]).set b words[1]).set c words[2]).set d words[3] + +def round (state message : Block) (schedule : Vector (Fin 16) 16) : Block := + let state := g state 0 4 8 12 message[schedule[0]] message[schedule[1]] + let state := g state 1 5 9 13 message[schedule[2]] message[schedule[3]] + let state := g state 2 6 10 14 message[schedule[4]] message[schedule[5]] + let state := g state 3 7 11 15 message[schedule[6]] message[schedule[7]] + let state := g state 0 5 10 15 message[schedule[8]] message[schedule[9]] + let state := g state 1 6 11 12 message[schedule[10]] message[schedule[11]] + let state := g state 2 7 8 13 message[schedule[12]] message[schedule[13]] + g state 3 4 9 14 message[schedule[14]] message[schedule[15]] + +def initialWords (cv : CV) (counter : UInt64) (blockLen flags : UInt32) : Block := + #v[cv[0], cv[1], cv[2], cv[3], cv[4], cv[5], cv[6], cv[7], + iv[0], iv[1], iv[2], iv[3], counter.toUInt32, (counter >>> 32).toUInt32, blockLen, flags] + +def compress (cv : CV) (message : Block) (counter : UInt64) (blockLen flags : UInt32) : CV := + let state := schedules.foldl (fun state schedule => round state message schedule) + (initialWords cv counter blockLen flags) + Vector.ofFn fun index => state[index.val] ^^^ state[index.val + 8] + +def wordBytes (word : UInt32) : Vector UInt8 4 := + Vector.ofFn fun index => (word.toNat / 256^index.val).toUInt8 + +def bytesWord (bytes : Vector UInt8 4) : UInt32 := + UInt32.ofNat (Challenger.littleEndian bytes.toList) + +/-- Zero padding is part of block framing, including the empty input block. -/ +def blockWords (bytes : List UInt8) : Block := + let input := bytes.toArray + Vector.ofFn fun word => bytesWord (Vector.ofFn fun byte => input[word.val * 4 + byte.val]?.getD 0) + +def cvBytes (cv : CV) : Digest := + Vector.ofFn fun index => (wordBytes cv[index.val / 4])[index.val % 4] + +structure Output where + cv : CV + block : Block + blockLen : UInt32 + counter : UInt64 + flags : UInt32 + deriving DecidableEq, Repr + +def Output.chainingValue (output : Output) : CV := + compress output.cv output.block output.counter output.blockLen output.flags + +def Output.rootHash (output : Output) : Digest := + cvBytes (compress output.cv output.block 0 output.blockLen (output.flags ||| 8)) + +/-- A full last block receives CHUNK_END; it is never followed by an empty block. -/ +def chunkLoop (counter : UInt64) (cv : CV) (start : Bool) (input : List UInt8) : Output := + if h : input.length ≤ 64 then + ⟨cv, blockWords input, input.length.toUInt32, counter, (if start then 1 else 0) ||| 2⟩ + else + let next := compress cv (blockWords (input.take 64)) counter 64 (if start then 1 else 0) + chunkLoop counter next false (input.drop 64) +termination_by input.length +decreasing_by simp only [List.length_drop]; omega + +def chunkOutput (counter : UInt64) (input : List UInt8) : Output := + chunkLoop counter iv true input + +/-- This internal BLAKE3 parent is distinct from hashing a PCS Merkle pair. -/ +def parentOutput (left right : CV) : Output := + ⟨iv, left ++ right, 64, 0, 4⟩ + +def leftLen (size : Nat) : Nat := 2 ^ (size - 1).log2 + +theorem leftLen_positive (size : Nat) : 0 < leftLen size := Nat.two_pow_pos _ + +theorem leftLen_lt {size : Nat} (large : 1024 < size) : leftLen size < size := by + have := Nat.log2_self_le (n := size - 1) (by omega) + unfold leftLen + omega + +def subtree (counter : Nat) (input : List UInt8) : Output := + if _h : input.length ≤ 1024 then chunkOutput counter.toUInt64 input + else + let split := leftLen input.length + let left := subtree counter (input.take split) + let right := subtree (counter + split / 1024) (input.drop split) + parentOutput left.chainingValue right.chainingValue +termination_by input.length +decreasing_by + · have := leftLen_lt (size := input.length) (by omega) + simp only [List.length_take]; omega + · have := leftLen_positive input.length + simp only [List.length_drop]; omega + +def digest (input : List UInt8) : Digest := (subtree 0 input).rootHash + +def hash : Challenger.Hash32 := + fun input => + let bytes := digest input + fun index => bytes[index] + +/-- Native BLAKE3 supports at most 2^64 - 1 input bytes. -/ +def NativeInput (input : List UInt8) : Prop := input.length < 2^64 + +def replay (fuel : Nat) (key : KeyCodec.Key) (proof : ProofCodec.Data) + (claims : List (List G)) : Option Transcript.Replay := Transcript.replay hash fuel key proof claims + +def verifyArithmetic (fuel : Nat) (key : KeyCodec.Key) (proof : ProofCodec.Data) + (claims : List (List G)) (rows : List ProofShape.Row) : Option Transcript.Replay := + Transcript.verifyArithmetic hash fuel key proof claims rows + +end Aiur.NativeAIR.Blake3 diff --git a/Ix/Aiur/BoundVerifier.lean b/Ix/Aiur/BoundVerifier.lean new file mode 100644 index 000000000..3ed75608f --- /dev/null +++ b/Ix/Aiur/BoundVerifier.lean @@ -0,0 +1,143 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Compilation +import Ix.Aiur.LookupShapes +import Ix.Aiur.RowCounts +import Ix.Aiur.EmissionChecks +import Ix.Aiur.KeyCodec +import Ix.Aiur.Protocol + +/-! A verifier whose caller selects the source, entrypoint, parameters and +complete allowed key bytes. Untrusted proof bytes cannot select any of them. + +This is a program/statement/key binding component. It does not assert that +the selected source implements the certified checker, that compilation or +AIR constraints reflect source execution, or that the proof-system FFI is +sound. Those are distinct C8 obligations. In particular, no certified release +is instantiated here for the legacy `verify_claim` or the C2 pilot. +-/ + +namespace Aiur.BoundVerifier + +/-- Trusted deployment selection, independent of the proof being verified. +Circuit grouping is explicit; environment-variable overrides are not used. -/ +structure Selection where + source : Source.Toplevel + groups : Array (String × Array String) := #[] + entrypoint : Lean.Name + function : Bytecode.FunIdx + inputSize : Nat + success : Array G + commitment : CommitmentParameters + fri : FriParameters + key : ByteArray + +def Selection.compile (selection : Selection) : Except String CompiledToplevel := do + let compiled ← selection.source.compile + if selection.groups.isEmpty then return compiled + compiled.groupFunctions selection.groups + +/-- The system is built from exactly the selected compilation and parameters. +It is derived, rather than accepted as a second independent caller argument. -/ +def Selection.system (selection : Selection) (compiled : CompiledToplevel) : AiurSystem := + AiurSystem.build compiled.bytecode selection.commitment selection.fri + +def Selection.keyParameters (selection : Selection) : NativeAIR.KeyCodec.Parameters := + ⟨selection.commitment.logBlowup, selection.commitment.capHeight, + selection.fri.logFinalPolyLen, selection.fri.maxLogArity, selection.fri.numQueries, + selection.fri.commitProofOfWorkBits, selection.fri.queryProofOfWorkBits⟩ + +structure Backend (selection : Selection) where + compiled : CompiledToplevel + compilation : selection.compile = .ok compiled + system : AiurSystem + systemBuilt : system = selection.system compiled + selected : compiled.getFuncIdx selection.entrypoint = some selection.function + functionRange : selection.function < gSize.toNat + entry : Bytecode.Function + present : compiled.bytecode.functions[selection.function]? = some entry + publicEntry : entry.entry = true + constrained : entry.constrained = true + arity : entry.layout.inputSize = selection.inputSize + returnArity : entry.body.returnsHaveSize selection.success.size = true + lookupShapes : compiled.bytecode.validateLookupShapes = true + rowCounts : compiled.bytecode.validateRowCounts = true + emissionChecks : compiled.bytecode.validateEmission = true + keyBound : system.vkBytes = selection.key + keyData : NativeAIR.KeyCodec.Key + keyDecoded : NativeAIR.KeyCodec.decodeCanonical selection.key = some keyData + keyParameters : keyData.parameters = selection.keyParameters + +def build (selection : Selection) : Except String (Backend selection) := + match hc : selection.compile with + | .error e => .error e + | .ok compiled => + if hs : compiled.getFuncIdx selection.entrypoint = some selection.function then + if hr : selection.function < gSize.toNat then + match hp : compiled.bytecode.functions[selection.function]? with + | none => .error "selected function is absent" + | some entry => + if he : entry.entry = true ∧ entry.constrained = true ∧ + entry.layout.inputSize = selection.inputSize then + if ho : entry.body.returnsHaveSize selection.success.size = true then + if hl : compiled.bytecode.validateLookupShapes = true then + if hn : compiled.bytecode.validateRowCounts = true then + if hi : compiled.bytecode.validateEmission = true then + let system := selection.system compiled + if hk : system.vkBytes = selection.key then + match hd : NativeAIR.KeyCodec.decodeCanonical selection.key with + | none => .error "verification key is not a checked canonical v5 artifact" + | some keyData => + if hm : keyData.parameters = selection.keyParameters then + .ok ⟨compiled, hc, system, rfl, hs, hr, entry, hp, he.1, he.2.1, he.2.2, ho, hl, hn, hi, hk, + keyData, hd, hm⟩ + else .error "verification key parameters differ from the selected parameters" + else .error "verification key differs from the selected key" + else .error "compiled circuit reads an invalid logical value or selector" + else .error "compiled circuit control counts exceed their bounds" + else .error "compiled lookup message arities differ" + else .error "selected success result has the wrong output arity" + else .error "selected function is not a constrained public entry of the expected arity" + else .error "function index is not a canonical field element" + else .error "entrypoint differs from the selected function" + +/-- `input` is the statement the caller expects. A serialized proof supplies +neither a different statement nor an alternative key or success result. -/ +def verify {selection : Selection} (backend : Backend selection) (input : Array G) + (bytes : ByteArray) : Except String Unit := do + if input.size != selection.inputSize then throw "public input arity differs" + let proof ← Proof.ofBytesChecked bytes + backend.system.verify + (buildClaim selection.function input selection.success) proof + +theorem verify_success {selection : Selection} {backend : Backend selection} + {input : Array G} {bytes : ByteArray} (h : verify backend input bytes = .ok ()) : + input.size = selection.inputSize ∧ + ∃ proof, Proof.ofBytesChecked bytes = .ok proof ∧ + backend.system.verify + (buildClaim selection.function input selection.success) proof = .ok () := by + unfold verify at h + split at h + · cases h + · rename_i ha + refine ⟨by simpa using ha, ?_⟩ + cases hp : Proof.ofBytesChecked bytes with + | error e => simp [hp, bind, Except.bind] at h + | ok proof => exact ⟨proof, rfl, by simpa [hp, bind, Except.bind] using h⟩ + +/-- Every produced backend retains the actual compiler artifact, including +the grouping result. No compiler-semantic claim is packed into this result. -/ +theorem Backend.compilation_stages {selection : Selection} (backend : Backend selection) : + ∃ initial, selection.source.compile = .ok initial ∧ + (if selection.groups.isEmpty then .ok initial + else initial.groupFunctions selection.groups) = .ok backend.compiled := by + have h := backend.compilation + unfold Selection.compile at h + cases hc : selection.source.compile with + | error e => simp [hc, bind, Except.bind] at h + | ok initial => exact ⟨initial, rfl, by simpa [hc, bind, Except.bind, pure, Except.pure] using h⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Branchless.lean b/Ix/Aiur/Branchless.lean new file mode 100644 index 000000000..a5c0ab9a4 --- /dev/null +++ b/Ix/Aiur/Branchless.lean @@ -0,0 +1,27 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +module +public import Ix.Aiur.Stages.Bytecode + +/-! Ungated lookup messages require one writer per physical slot. A single +selector does not ensure that: a branch with no terminal can still emit +lookups. Restrict the optimization to one function with terminal control. -/ + +public section +@[expose] section +namespace Aiur.Bytecode + +def Function.hasTerminalControl (function : Function) : Bool := + match function.body.ctrl with + | .«return» .. | .yield .. => true + | _ => false + +def circuitBranchless (selectors : Nat) (functions : List Function) : Bool := + selectors == 1 && match functions with + | [function] => function.hasTerminalControl + | _ => false + +end Aiur.Bytecode diff --git a/Ix/Aiur/Challenger.lean b/Ix/Aiur/Challenger.lean new file mode 100644 index 000000000..5df23f431 --- /dev/null +++ b/Ix/Aiur/Challenger.lean @@ -0,0 +1,91 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ProofCodec + +/-! Total replay of the pinned byte-hash / serializing Goldilocks challenger. +The hash is an explicit 32-byte function. The pending buffer is stored in +sampling order, the reverse of the native vector. Rejection sampling uses +explicit fuel; exhaustion rejects without returning a fabricated sample. +-/ + +namespace Aiur.NativeAIR.Challenger + +abbrev Hash32 := List UInt8 → Fin 32 → UInt8 + +structure State where + input : List UInt8 + pending : List UInt8 + deriving DecidableEq, Repr + +def initial (seed : List UInt8) : State := ⟨seed, []⟩ + +def observeByte (state : State) (byte : UInt8) : State := + ⟨state.input ++ [byte], []⟩ + +/-- Empty slices perform no byte observations and preserve pending output. -/ +def observeBytes (state : State) (bytes : List UInt8) : State := + if bytes.isEmpty then state else ⟨state.input ++ bytes, []⟩ + +def observeField (state : State) (value : G) : State := + observeBytes state (ProofCodec.encodeField value) + +def observeExtension (state : State) (value : ProofCodec.Extension) : State := + observeField (observeField state value.c0) value.c1 + +/-- Caps are observed as digest bytes, without a vector length prefix. -/ +def observeCap (state : State) (cap : KeyCodec.MerkleCap) : State := + observeBytes state cap.flatten + +def sampleByte (hash : Hash32) (state : State) : UInt8 × State := + match state.pending with + | byte :: rest => (byte, ⟨state.input, rest⟩) + | [] => + let digest := hash state.input + (digest 31, ⟨List.ofFn digest, (List.ofFn digest).reverse.drop 1⟩) + +def sampleBytes (hash : Hash32) : Nat → State → List UInt8 × State + | 0, state => ([], state) + | count + 1, state => + let (byte, next) := sampleByte hash state + let (rest, final) := sampleBytes hash count next + (byte :: rest, final) + +def littleEndian (bytes : List UInt8) : Nat := + bytes.foldr (fun byte rest => byte.toNat + 256 * rest) 0 + +def sampleWord (hash : Hash32) (state : State) : Nat × State := + let (bytes, next) := sampleBytes hash 8 state + (littleEndian bytes, next) + +def sampleField (hash : Hash32) : Nat → State → Option (G × State) + | 0, _ => none + | fuel + 1, state => + let (word, next) := sampleWord hash state + if word < gSize.toNat then some (G.ofNat word, next) + else sampleField hash fuel next + +/-- Each basis coordinate has its own rejection-sampling budget. -/ +def sampleExtension (hash : Hash32) (fuel : Nat) (state : State) : + Option (ProofCodec.Extension × State) := do + let (c0, next) ← sampleField hash fuel state + let (c1, final) ← sampleField hash fuel next + return (⟨c0, c1⟩, final) + +def sampleBits (hash : Hash32) (bits : Nat) (state : State) : Option (Nat × State) := + if bits < 64 ∧ 2^bits < gSize.toNat then + let (word, next) := sampleWord hash state + some (word % 2^bits, next) + else none + +/-- Unlike zero-bit sampling, a zero-bit witness check consumes nothing. -/ +def checkWitness (hash : Hash32) (bits : Nat) (witness : G) (state : State) : + Option (Bool × State) := do + if bits = 0 then return (true, state) + else + let (value, next) ← sampleBits hash bits (observeField state witness) + return (value == 0, next) + +end Aiur.NativeAIR.Challenger diff --git a/Ix/Aiur/CompiledKey.lean b/Ix/Aiur/CompiledKey.lean new file mode 100644 index 000000000..310c7df77 --- /dev/null +++ b/Ix/Aiur/CompiledKey.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CompiledCircuitRows +import Ix.Aiur.Proofs.CircuitCompletion +import Ix.Aiur.Proofs.ByteColumns +import Ix.Aiur.LookupGroups + +/-! Reconstruct the complete native circuit list from the selected bytecode. +The comparison includes ordered graph nodes, constraints, lookups, dimensions, +degrees, grouping and preprocessed indices. Commitment contents and proof +verification are separate from this executable graph-binding check. -/ + +namespace Aiur.NativeAIR.CompiledKey +open Compiler CircuitEmitter + +def main (index : Nat) : Expr := .var ⟨.main, .current, index⟩ +def next (index : Nat) : Expr := .var ⟨.main, .next, index⟩ +def preprocessed (index : Nat) : Expr := .var ⟨.preprocessed, .current, index⟩ + +def memoryEquations : List Expr := + let selector := main 1 + let transition := (next 1).frontMul .isTransition + [selector.frontMul (selector.frontSub (.konst 1)), + (main 0).frontMul ((Expr.konst 1).frontSub selector), + transition.frontMul (selector.frontSub (.konst 1)), + transition.frontMul (((main 2).frontAdd (.konst 1)).frontSub (next 2))] + +def memoryLookup (width : Nat) : ExprLookup := + ⟨(main 0).frontNeg, + [Expr.konst 1, .konst (G.ofNat width), main 2].map ((main 1).frontMul) ++ + (List.ofFn fun i : Fin width => (main 1).frontMul (main (3 + i.val)))⟩ + +def byte1Lookup (kind : AIR.Byte1Kind) : ExprLookup := + ⟨(main kind.column.val).frontNeg, match kind with + | .bits => [.konst 2, preprocessed 0] ++ List.ofFn (fun i : Fin 8 => preprocessed (1 + i.val)) + | .shiftLeft => [.konst 3, preprocessed 0, preprocessed 9] + | .shiftRight => [.konst 4, preprocessed 0, preprocessed 10]⟩ + +def byte2Lookup (kind : AIR.Byte2Kind) : ExprLookup := + ⟨(main kind.column.val).frontNeg, [.konst kind.channel, preprocessed 0, preprocessed 1] ++ match kind with + | .xor => [preprocessed 2] + | .add => [preprocessed 3] + | .sub => [preprocessed 4] + | .and => [preprocessed 5] + | .or => [preprocessed 6] + | .lessThan => [preprocessed 7] + | .range => [] + | .mul => [preprocessed 8, preprocessed 9] + | .split7 => [preprocessed 10, preprocessed 11] + | .split4 => [preprocessed 12, preprocessed 13]⟩ + +def circuit (logBlowup mainWidth preprocessedWidth preprocessedHeight groupSize : Nat) + (base : BaseCompilation) : Option KeyCodec.Circuit := do + let raw : KeyCodec.Circuit := ⟨mainWidth, preprocessedWidth, preprocessedHeight, 0, groupSize, base.graph⟩ + let degree ← raw.computedDegree + let result := LookupGroups.retune { raw with maxConstraintDegree := degree } (2^logBlowup) + if result.valid then some result else none + +def functionCircuit (logBlowup : Nat) (program : Bytecode.Toplevel) (source : Bytecode.Circuit) : Option KeyCodec.Circuit := do + let compiled ← compileCircuit (circuitWidths source) program source + let groupSize := if compiled.emission.branchless && 2 ≤ compiled.emission.lookups.length then 2 else 1 + circuit logBlowup source.layout.width 0 0 groupSize compiled.base + +def memoryCircuit (logBlowup width : Nat) : Option KeyCodec.Circuit := do + let base ← compileBase ⟨0, 3 + width, 0, 0⟩ [memoryLookup width] memoryEquations + circuit logBlowup (3 + width) 0 0 1 base + +def byte1Circuit (logBlowup : Nat) : Option KeyCodec.Circuit := do + let base ← compileBase ⟨11, 3, 0, 0⟩ (AIR.Byte1Kind.all.map byte1Lookup) [] + circuit logBlowup 3 11 256 2 base + +def byte2Circuit (logBlowup : Nat) : Option KeyCodec.Circuit := do + let base ← compileBase ⟨14, 10, 0, 0⟩ (AIR.Byte2Kind.all.map byte2Lookup) [] + circuit logBlowup 10 14 65536 2 base + +def circuits (logBlowup : Nat) (program : Bytecode.Toplevel) : Option (List KeyCodec.Circuit) := do + let functions ← program.circuits.toList.mapM (functionCircuit logBlowup program) + let memories ← program.memorySizes.toList.mapM (memoryCircuit logBlowup) + let byte1 ← byte1Circuit logBlowup + let byte2 ← byte2Circuit logBlowup + return functions ++ memories ++ [byte1, byte2] + +def preprocessedIndices (program : Bytecode.Toplevel) : List (Option Nat) := + List.replicate (program.circuits.size + program.memorySizes.size) none ++ [some 0, some 1] + +def check (program : Bytecode.Toplevel) (key : KeyCodec.Key) : Bool := + circuits key.parameters.logBlowup program == some key.circuits && + key.preprocessedIndices == preprocessedIndices program + +end Aiur.NativeAIR.CompiledKey diff --git a/Ix/Aiur/CompiledVerifier.lean b/Ix/Aiur/CompiledVerifier.lean new file mode 100644 index 000000000..1b31df6b0 --- /dev/null +++ b/Ix/Aiur/CompiledVerifier.lean @@ -0,0 +1,48 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.BoundVerifier +import Ix.Aiur.CompiledKey + +/-! Enforce equality between the selected native key and the complete checked +circuit model. This strengthens program/key binding; native acceptance, +preprocessed commitment meaning and certified source soundness remain open. -/ + +namespace Aiur.BoundVerifier + +structure CompiledBackend (selection : Selection) extends Backend selection where + graphsChecked : NativeAIR.CompiledKey.check compiled.bytecode keyData = true + +def buildCompiled (selection : Selection) : Except String (CompiledBackend selection) := do + let backend ← build selection + if checked : NativeAIR.CompiledKey.check backend.compiled.bytecode backend.keyData = true then + return ⟨backend, checked⟩ + else throw "verification key circuits differ from the checked compilation" + +def verifyCompiled {selection : Selection} (backend : CompiledBackend selection) (input : Array G) + (bytes : ByteArray) : Except String Unit := + verify backend.toBackend input bytes + +theorem CompiledBackend.circuits_bound {selection : Selection} (backend : CompiledBackend selection) : + NativeAIR.CompiledKey.circuits backend.keyData.parameters.logBlowup backend.compiled.bytecode = + some backend.keyData.circuits := by + have checked := backend.graphsChecked + simp only [NativeAIR.CompiledKey.check, Bool.and_eq_true, beq_iff_eq] at checked + exact checked.1 + +theorem CompiledBackend.preprocessed_indices {selection : Selection} (backend : CompiledBackend selection) : + backend.keyData.preprocessedIndices = NativeAIR.CompiledKey.preprocessedIndices backend.compiled.bytecode := by + have checked := backend.graphsChecked + simp only [NativeAIR.CompiledKey.check, Bool.and_eq_true, beq_iff_eq] at checked + exact checked.2 + +theorem verifyCompiled_success {selection : Selection} {backend : CompiledBackend selection} + {input : Array G} {bytes : ByteArray} (accepted : verifyCompiled backend input bytes = .ok ()) : + input.size = selection.inputSize ∧ + ∃ proof, Proof.ofBytesChecked bytes = .ok proof ∧ + backend.system.verify (buildClaim selection.function input selection.success) proof = .ok () := + verify_success accepted + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Compiler.lean b/Ix/Aiur/Compiler.lean index 9350ada61..0d7505848 100644 --- a/Ix/Aiur/Compiler.lean +++ b/Ix/Aiur/Compiler.lean @@ -141,12 +141,11 @@ def Bytecode.Toplevel.needsCircuit (t : Bytecode.Toplevel) : Array Bool := Id.ru stack := stack.push callee needs -/-- Full compilation pipeline. -/ -def Source.Toplevel.compile (t : Source.Toplevel) : Except String CompiledToplevel := do - let t ← t.inlineCalls - let typedDecls ← t.checkAndSimplify.mapError toString - let concDecls ← typedDecls.concretize.mapError toString - let (bytecodeRaw, preNameMap) ← concDecls.toBytecode +/-- The exact artifact produced by the total final compilation passes. +Keeping this operation separate lets the compilation success theorem bind +the returned bytecode and function map to the successful stage outputs. -/ +def finishCompilation (t : Source.Toplevel) (bytecodeRaw : Bytecode.Toplevel) + (preNameMap : Std.HashMap Global Bytecode.FunIdx) : CompiledToplevel := Id.run do let (bytecodeDedup, remap) := bytecodeRaw.deduplicate let needs := bytecodeDedup.needsCircuit let bytecode : Bytecode.Toplevel := { bytecodeDedup with @@ -162,6 +161,14 @@ def Source.Toplevel.compile (t : Source.Toplevel) : Except String CompiledToplev circuits := bytecode.singletonCircuits fun i => reverseMap[i]?.getD s!"" } pure (CompiledToplevel.mk t bytecode nameMap) +/-- Full compilation pipeline. -/ +def Source.Toplevel.compile (t : Source.Toplevel) : Except String CompiledToplevel := do + let t ← t.inlineCalls + let typedDecls ← t.checkAndSimplify.mapError toString + let concDecls ← typedDecls.concretize.mapError toString + let (bytecodeRaw, preNameMap) ← concDecls.toBytecode + return finishCompilation t bytecodeRaw preNameMap + /-- Name of the environment variable that switches function grouping OFF process-wide: when it is set to anything but `0` or the empty string, `compileWithGroups` ignores its grouping and compiles the singleton diff --git a/Ix/Aiur/Compiler/Dedup.lean b/Ix/Aiur/Compiler/Dedup.lean index 8a9d70bfa..521738be4 100644 --- a/Ix/Aiur/Compiler/Dedup.lean +++ b/Ix/Aiur/Compiler/Dedup.lean @@ -138,14 +138,14 @@ def assignClasses [BEq α] [Hashable α] (values : Array α) : Array Nat × Nat | none => (classes.push nextId, map.insert v nextId, nextId + 1) (classes, nextId) -/-- Bounded refinement step. The `bound` caps iterations — `classes.size + 1` -is always enough since the number of distinct equivalence classes can only -increase (or stay the same) per step, and is bounded above by `classes.size`. -/ +/-- Bounded refinement step. The bound caps optimization work. The public +pass validates the final candidate, so execution preservation does not +depend on proving that this iteration has reached a fixed point. -/ def partitionRefineBound : Nat → Array Nat → Array (Array FunIdx) → Array Nat | 0, classes, _ => classes | bound+1, classes, callees => let signatures := classes.mapIdx fun i cls => - (cls, callees[i]!.map (classes[·]!)) + (cls, (callees[i]?.getD #[]).map fun callee => classes[callee]?.getD 0) let (newClasses, _) := assignClasses signatures if newClasses == classes then classes else partitionRefineBound bound newClasses callees @@ -200,9 +200,9 @@ def deduplicate_newFunctions (functions : Array Function) (classes : Array Nat) else acc) #[] -/-- Deduplicate bytecode functions via partition refinement. -Returns the deduplicated toplevel and a mapping from old index to new index. -/ -def Toplevel.deduplicate (t : Toplevel) : Toplevel × (FunIdx → FunIdx) := +/-- Propose a deduplication by partition refinement. The public pass validates +this candidate before returning it. -/ +def Toplevel.deduplicateCandidate (t : Toplevel) : Toplevel × (FunIdx → FunIdx) := let functions := t.functions let n := functions.size if n == 0 then (t, id) @@ -219,6 +219,37 @@ def Toplevel.deduplicate (t : Toplevel) : Toplevel × (FunIdx → FunIdx) := let newFunctions := deduplicate_newFunctions functions classes canonical remapFn ({ t with functions := newFunctions }, remapFn) +/-- Keep invalid source function indices outside the target's domain. -/ +def boundedRenaming (source : Toplevel) (rename : FunIdx → FunIdx) (i : FunIdx) : FunIdx := + if i < source.functions.size then rename i else i + +/-- Every old function must map to a valid target with the same layout and +the exact body obtained by rewriting calls. Target size and bounded renaming +also prevent invalid source calls from becoming valid target calls. -/ +def validatesRenaming (source target : Toplevel) (rename : FunIdx → FunIdx) : Bool := + target.functions.size ≤ source.functions.size && + (Array.range source.functions.size).all fun i => + if hi : i < source.functions.size then + if hj : rename i < target.functions.size then + source.functions[i].layout == target.functions[rename i].layout && + rewriteBlock rename source.functions[i].body == target.functions[rename i].body + else false + else false + +/-- Use a proposed function renaming only after checking its complete code +relation. An invalid candidate leaves the original program and indices intact. -/ +def checkedRenaming (source candidate : Toplevel) (rename : FunIdx → FunIdx) : + Toplevel × (FunIdx → FunIdx) := + let bounded := boundedRenaming source rename + if validatesRenaming source candidate bounded then (candidate, bounded) + else (source, id) + +/-- Deduplicate bytecode functions via validated partition refinement. +Returns the selected program and a mapping from old index to new index. -/ +def Toplevel.deduplicate (source : Toplevel) : Toplevel × (FunIdx → FunIdx) := + let candidate := source.deduplicateCandidate + checkedRenaming source candidate.1 candidate.2 + end Bytecode end Aiur diff --git a/Ix/Aiur/Compiler/Layout.lean b/Ix/Aiur/Compiler/Layout.lean index 7e51539ea..185b317e8 100644 --- a/Ix/Aiur/Compiler/Layout.lean +++ b/Ix/Aiur/Compiler/Layout.lean @@ -324,8 +324,13 @@ decreasing_by end -def blockLayout (block : Bytecode.Block) : LayoutM Unit := - discard (relayoutBlock block) +/-- State projection of continuation relayout. -/ +def ctrlLayout (ctrl : Bytecode.Ctrl) : LayoutM Unit := + discard (relayoutCtrl ctrl) + +def blockLayout (block : Bytecode.Block) : LayoutM Unit := do + block.ops.forM opLayout + ctrlLayout block.ctrl end Bytecode diff --git a/Ix/Aiur/Compiler/Lower.lean b/Ix/Aiur/Compiler/Lower.lean index 115fc3872..3788e93f1 100644 --- a/Ix/Aiur/Compiler/Lower.lean +++ b/Ix/Aiur/Compiler/Lower.lean @@ -250,9 +250,9 @@ def toIndex let eltSize ← match typSize layoutMap eltTyp with | .error e => throw e | .ok len => pure len + let val ← toIndex layoutMap bindings val let arr ← toIndex layoutMap bindings arr let left := arr.extract 0 (i * eltSize) - let val ← toIndex layoutMap bindings val let right := arr.extract ((i + 1) * eltSize) pure $ left ++ val ++ right | .store _ _ arg => do diff --git a/Ix/Aiur/Domain.lean b/Ix/Aiur/Domain.lean new file mode 100644 index 000000000..c56172cc3 --- /dev/null +++ b/Ix/Aiur/Domain.lean @@ -0,0 +1,66 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Extension + +/-! Natural trace domains and the pinned Goldilocks two-adic generators. +The checked out-of-domain selector evaluator rejects every division pole. +-/ + +namespace Aiur.NativeAIR.Domain + +def generators : Array G := #[ + 0x0000000000000001, 0xffffffff00000000, 0x0001000000000000, + 0xfffffffeff000001, 0xefffffff00000001, 0x00003fffffffc000, + 0x0000008000000000, 0xf80007ff08000001, 0xbf79143ce60ca966, + 0x1905d02a5c411f4e, 0x9d8f2ad78bfed972, 0x0653b4801da1c8cf, + 0xf2c35199959dfcb6, 0x1544ef2335d17997, 0xe0ee099310bba1e2, + 0xf6b2cffe2306baac, 0x54df9630bf79450e, 0xabd0a6e8aa3d8a0e, + 0x81281a7b05f9beac, 0xfbd41c6b8caa3302, 0x30ba2ecd5e93e76d, + 0xf502aef532322654, 0x4b2a18ade67246b5, 0xea9d5a1336fbc98b, + 0x86cdcc31c307e171, 0x4bbaf5976ecfefd8, 0xed41d05b78d6e286, + 0x10d78dd8915a171d, 0x59049500004a4485, 0xdfa8c93ba46d2666, + 0x7e9bd009b86a0845, 0x400a7f755588e659, 0x185629dcda58878c] + +theorem generators_size : generators.size = 33 := rfl + +abbrev Subgroup := Fin 33 + +def ofLogSize (bits : Nat) : Option Subgroup := + if bounded : bits < 33 then some ⟨bits, bounded⟩ else none + +def size (domain : Subgroup) : Nat := 2 ^ domain.val + +def generator (domain : Subgroup) : G := + generators[domain.val]'(by simpa only [generators_size] using domain.isLt) + +def point (domain : Subgroup) (index : Fin (size domain)) : G := + (generator domain).pow index.val + +def lastPoint (domain : Subgroup) : G := (generator domain).inverse + +def normalizer (domain : Subgroup) : G := G.ofNat (size domain) * generator domain + +structure Selectors (W : Type) where + isFirst : W + isLast : W + isTransition : W + invVanishing : W + deriving DecidableEq, Repr + +open ProofCodec (Extension) + +def vanishing (domain : Subgroup) (value : Extension) : Extension := + value.power (size domain) - 1 + +def selectors (domain : Subgroup) (value : Extension) : Option (Selectors Extension) := do + let z := vanishing domain value + let lastDenominator := value - Extension.ofBase (lastPoint domain) + let firstInverse ← (value - 1).tryInverse + let lastInverse ← lastDenominator.tryInverse + let vanishingInverse ← z.tryInverse + return ⟨z * firstInverse, z * lastInverse, lastDenominator, vanishingInverse⟩ + +end Aiur.NativeAIR.Domain diff --git a/Ix/Aiur/EmissionChecks.lean b/Ix/Aiur/EmissionChecks.lean new file mode 100644 index 000000000..99be67636 --- /dev/null +++ b/Ix/Aiur/EmissionChecks.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +module +public import Ix.Aiur.Stages.Bytecode + +/-! +Structural checks for circuit emission. Each operation reads the incoming +logical scope and then appends its outputs. Branches restore that scope; +continuations append only their merge values. Unconstrained advice and I/O +operations do not read their runtime operands while building constraints. + +The checked addition matches the supported 64-bit native index domain. These +checks establish neither source typing nor the meaning of unchecked advice. +-/ + +public section +@[expose] section + +namespace Aiur.Bytecode + +def indicesInScope (available : Nat) (indices : Array ValIdx) : Bool := + indices.all fun index => decide (index < available) + +def wordInScope (available : Nat) (indices : Array ValIdx) : Bool := + indices.size == 4 && indicesInScope available indices + +/-- Logical outputs include virtual carries, which occupy no fresh column. -/ +def Op.outputSize : Op → Nat + | .const .. | .add .. | .sub .. | .mul .. | .eqZero .. | .store .. + | .u8ShiftLeft .. | .u8ShiftRight .. | .u8Xor .. | .u8And .. | .u8Or .. + | .u8LessThan .. | .u32LessThan .. | .unconstrainedGInverse .. | .u32ToField .. => 1 + | .call _ _ size _ | .load size _ | .ioRead _ _ size => size + | .assertEq .. | .ioSetInfo .. | .ioWrite .. | .debug .. | .u8RangeCheck .. => 0 + | .ioGetInfo .. | .u8Add .. | .u8Mul .. | .u8Sub .. | .u8XorSplit7 .. + | .u8XorSplit4 .. | .unconstrainedBigUintDivMod .. => 2 + | .u8BitDecomposition .. | .unconstrainedGToBytes .. => 8 + | .unconstrainedU32Add .. | .unconstrainedU32Add3 .. => 5 + +/-- Check precisely the operands consumed by the constraint builder. In +particular, a store cannot read its own newly allocated pointer. -/ +def Op.emissionInputs (available : Nat) : Op → Bool + | .add a b | .sub a b | .mul a b | .u8Xor a b | .u8Add a b | .u8Mul a b + | .u8Sub a b | .u8And a b | .u8Or a b | .u8LessThan a b | .u32LessThan a b + | .u8XorSplit7 a b | .u8XorSplit4 a b | .u8RangeCheck a b => + decide (a < available) && decide (b < available) + | .eqZero index | .load _ index | .u8BitDecomposition index + | .u8ShiftLeft index | .u8ShiftRight index => decide (index < available) + | .call _ indices _ false | .store indices => indicesInScope available indices + | .assertEq left right _ => left.size == right.size && + (indicesInScope available left && indicesInScope available right) + | .unconstrainedU32Add left right => wordInScope available left && wordInScope available right + | .unconstrainedU32Add3 left middle right => + wordInScope available left && (wordInScope available middle && wordInScope available right) + | .u32ToField indices => wordInScope available indices + | _ => true + +def addScope (available count : Nat) : Option Nat := + let next := available + count + if next < 2^64 then some next else none + +def checkEmissionOps : List Op → Nat → Option Nat + | [], available => some available + | op :: ops, available => do + if !op.emissionInputs available then none else do + let next ← addScope available op.outputSize + checkEmissionOps ops next + +private theorem block_ctrl_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def Ctrl.emissionChecks (available selectors : Nat) (yieldSize : Option Nat) : Ctrl → Bool + | .return index outputs => decide (index < selectors) && indicesInScope available outputs + | .yield index outputs => decide (index < selectors) && + (indicesInScope available outputs && yieldSize == some outputs.size) + | .match index branches fallback => + decide (index < available) && + (branches.attach.all (fun ⟨(_, block), _⟩ => block.emissionChecks available selectors yieldSize) && + (match fallback with | none => true | some block => block.emissionChecks available selectors yieldSize)) + | .matchContinue index branches fallback size _ _ continuation => + decide (index < available) && + (branches.attach.all (fun ⟨(_, block), _⟩ => block.emissionChecks available selectors (some size)) && + ((match fallback with | none => true | some block => block.emissionChecks available selectors (some size)) && + (match addScope available size with + | none => false + | some next => continuation.emissionChecks next selectors yieldSize))) +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.emissionChecks (available selectors : Nat) (yieldSize : Option Nat) (block : Block) : Bool := + match checkEmissionOps block.ops.toList available with + | none => false + | some next => block.ctrl.emissionChecks next selectors yieldSize +termination_by sizeOf block +decreasing_by exact block_ctrl_smaller block + +end + +def Function.emissionChecks (function : Function) : Bool := + decide (function.layout.inputSize < 2^64) && + function.body.emissionChecks function.layout.inputSize function.layout.selectors none + +/-- Check every constrained body before invoking the native circuit builder. -/ +def Toplevel.validateEmission (program : Toplevel) : Bool := + program.functions.all fun function => !function.constrained || function.emissionChecks + +end Aiur.Bytecode + +end +end diff --git a/Ix/Aiur/Extension.lean b/Ix/Aiur/Extension.lean new file mode 100644 index 000000000..b23459aef --- /dev/null +++ b/Ix/Aiur/Extension.lean @@ -0,0 +1,47 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ProofCodec + +/-! Arithmetic on the two canonical coordinates carried by native proofs. +The pinned Goldilocks extension uses the basis `1, u` with `u² = 7`. +These definitions do not authenticate polynomial openings or a transcript. +-/ + +namespace Aiur.NativeAIR.ProofCodec.Extension + +def ofBase (value : G) : Extension := ⟨value, 0⟩ + +instance ofNat : OfNat Extension n := ⟨ofBase (G.ofNat n)⟩ +instance add : Add Extension := ⟨fun a b => ⟨a.c0 + b.c0, a.c1 + b.c1⟩⟩ +instance sub : Sub Extension := ⟨fun a b => ⟨a.c0 - b.c0, a.c1 - b.c1⟩⟩ +instance neg : Neg Extension := ⟨fun a => ⟨0 - a.c0, 0 - a.c1⟩⟩ +instance mul : Mul Extension := ⟨fun a b => + ⟨a.c0 * b.c0 + a.c1 * (b.c1 * 7), a.c0 * b.c1 + a.c1 * b.c0⟩⟩ + +def basis : Extension := ⟨0, 1⟩ +def conjugate (value : Extension) : Extension := ⟨value.c0, 0 - value.c1⟩ +def norm (value : Extension) : G := value.c0 * value.c0 - 7 * (value.c1 * value.c1) +def scale (value : Extension) (scalar : G) : Extension := + ⟨value.c0 * scalar, value.c1 * scalar⟩ + +def powBits (value : Extension) (exponent : Nat) : Nat → Extension + | 0 => 1 + | fuel + 1 => + if exponent == 0 then 1 + else + let half := powBits value (exponent / 2) fuel + let square := half * half + if exponent % 2 == 0 then square else square * value + +def power (value : Extension) (exponent : Nat) : Extension := + powBits value exponent (exponent.log2 + 1) + +def tryInverse (value : Extension) : Option Extension := + if value == 0 then none else some (value.conjugate.scale value.norm.inverse) + +def evalOps : EvalOps Extension := ⟨ofBase, (· + ·), (· - ·), (· * ·), (-·)⟩ + +end Aiur.NativeAIR.ProofCodec.Extension diff --git a/Ix/Aiur/ExtensionMmcs.lean b/Ix/Aiur/ExtensionMmcs.lean new file mode 100644 index 000000000..2d4a8f4b1 --- /dev/null +++ b/Ix/Aiur/ExtensionMmcs.lean @@ -0,0 +1,62 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.PrunedMerkle +import Ix.Aiur.ProofCodec + +/-! The native quadratic-extension MMCS adapter. Coordinates are flattened +in basis order, and dimensions retain their heights. Width multiplication +models release-mode machine arithmetic; `WidthsFit` states when it agrees +with mathematical doubling and the original extension-row shape. +-/ + +namespace Aiur.NativeAIR.ExtensionMmcs + +open Merkle (Digest Hash Dimensions) +open ProofCodec (Extension) + +def baseRow (values : List Extension) : List G := + values.flatMap fun value => [value.c0, value.c1] + +def baseRows (rows : List (List Extension)) : List (List G) := rows.map baseRow + +def baseDimensions (wordBits : Nat) (dimensions : List Dimensions) : List Dimensions := + dimensions.map fun dimension => + { dimension with width := (dimension.width * 2) % 2^wordBits } + +def WidthsFit (wordBits : Nat) (dimensions : List Dimensions) : Prop := + ∀ dimension ∈ dimensions, dimension.width * 2 < 2^wordBits + +def shape : List Dimensions → List (List Extension) → Bool + | [], [] => true + | dimension :: dimensions, row :: rows => row.length == dimension.width && shape dimensions rows + | _, _ => false + +def replay (hash : Hash) (wordBits : Nat) (dimensions : List Dimensions) (capHeight index : Nat) + (rows : List (List Extension)) (proof : List Digest) : Option Merkle.Replay := + Merkle.replay hash (baseDimensions wordBits dimensions) capHeight index (baseRows rows) proof + +def verify (hash : Hash) (wordBits : Nat) (dimensions : List Dimensions) (capHeight index : Nat) + (cap : List Digest) (rows : List (List Extension)) (proof : List Digest) : Bool := + Merkle.verify hash (baseDimensions wordBits dimensions) capHeight index cap (baseRows rows) proof + +def verifyCovered (hash : Hash) (wordBits : Nat) (dimensions : List Dimensions) (capHeight index : Nat) + (cap : List Digest) (rows : List (List Extension)) (proof : List Digest) : Bool := + Merkle.covered dimensions capHeight && verify hash wordBits dimensions capHeight index cap rows proof + +def replayMulti (hash : Hash) (wordBits : Nat) (dimensions : List Dimensions) (capHeight : Nat) + (indices : List Nat) (rows : List (List (List Extension))) (proof : List Digest) : + PrunedMerkle.Logged (List PrunedMerkle.Node) := + PrunedMerkle.replay hash (baseDimensions wordBits dimensions) capHeight indices (rows.map baseRows) proof + +def verifyMulti (hash : Hash) (wordBits : Nat) (dimensions : List Dimensions) (capHeight : Nat) + (indices : List Nat) (cap : List Digest) (rows : List (List (List Extension))) (proof : List Digest) : Bool := + PrunedMerkle.verify hash (baseDimensions wordBits dimensions) capHeight indices cap (rows.map baseRows) proof + +def verifyMultiCovered (hash : Hash) (wordBits : Nat) (dimensions : List Dimensions) (capHeight : Nat) + (indices : List Nat) (cap : List Digest) (rows : List (List (List Extension))) (proof : List Digest) : Bool := + Merkle.covered dimensions capHeight && verifyMulti hash wordBits dimensions capHeight indices cap rows proof + +end Aiur.NativeAIR.ExtensionMmcs diff --git a/Ix/Aiur/Folding.lean b/Ix/Aiur/Folding.lean new file mode 100644 index 000000000..f558cec8a --- /dev/null +++ b/Ix/Aiur/Folding.lean @@ -0,0 +1,40 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Interpolation + +/-! Global coefficient folding and restriction to a folding coset. +Coefficients use the ascending-power convention, with trailing zeros allowed. +-/ + +namespace Aiur.NativeAIR.Folding + +open _root_.Aiur.NativeAIR.Quotient (horner) + +def foldCoefficients [OfNat R 0] [Add R] [Mul R] (arity : Domain.Subgroup) (challenge : R) + (coefficients : List R) : List R := + if _empty : coefficients = [] then [] + else horner challenge (coefficients.take (Domain.size arity)) :: + foldCoefficients arity challenge (coefficients.drop (Domain.size arity)) +termination_by coefficients.length +decreasing_by + have positive := (show 0 < Domain.size arity from Nat.two_pow_pos arity.val) + have nonempty := List.length_pos_iff.mpr _empty + simp only [List.length_drop] + omega + +def rowCoefficients [OfNat R 0] [Add R] [Mul R] (arity : Domain.Subgroup) (point : R) + (coefficients : List R) : List R := + if _empty : coefficients = [] then [] + else Polynomial.add (coefficients.take (Domain.size arity)) + (Polynomial.scale point (rowCoefficients arity point (coefficients.drop (Domain.size arity)))) +termination_by coefficients.length +decreasing_by + have positive := (show 0 < Domain.size arity from Nat.two_pow_pos arity.val) + have nonempty := List.length_pos_iff.mpr _empty + simp only [List.length_drop] + omega + +end Aiur.NativeAIR.Folding diff --git a/Ix/Aiur/FriDomain.lean b/Ix/Aiur/FriDomain.lean new file mode 100644 index 000000000..19a15e8ae --- /dev/null +++ b/Ix/Aiur/FriDomain.lean @@ -0,0 +1,31 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Domain + +/-! Query locations for the pinned two-adic FRI strategy. Indices use +bit-reversed order. `wordReverse` spells out the native word reversal and +overflowing right shift; correspondence requires a supported bit count and +an admitted domain index. +-/ + +namespace Aiur.NativeAIR.FriDomain + +def reverseBits (bits index : Nat) : Nat := (BitVec.ofNat bits index).reverse.toNat + +def wordReverse (wordBits bits index : Nat) : Nat := + ((BitVec.ofNat wordBits index).reverse >>> ((wordBits - bits) % wordBits)).toNat + +def queryPoint (domain : Domain.Subgroup) (index : Nat) : G := + (Domain.generator domain).pow (reverseBits domain.val index) + +def inputPoint (domain : Domain.Subgroup) (index : Nat) : G := 7 * queryPoint domain index + +/-- The interpolation node at `slot` of the native folding row `index`. -/ +def foldNode (parent arity : Domain.Subgroup) (index slot : Nat) : G := + (Domain.generator parent).pow (reverseBits (parent.val - arity.val) index) * + (Domain.generator arity).pow (reverseBits arity.val slot) + +end Aiur.NativeAIR.FriDomain diff --git a/Ix/Aiur/FriQuery.lean b/Ix/Aiur/FriQuery.lean new file mode 100644 index 000000000..d1e14f560 --- /dev/null +++ b/Ix/Aiur/FriQuery.lean @@ -0,0 +1,92 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Interpolation + +/-! The native FRI query pass: reconstruct a row, fold it, then add at most +one reduced opening at the new height. Captured rows precede this addition. +The guards make the private native routine's caller preconditions explicit. +-/ + +namespace Aiur.NativeAIR.FriQuery + +open ProofCodec (Extension) +open _root_.Aiur.NativeAIR.Quotient (horner) + +def reconstruct (arity : Domain.Subgroup) (index : Nat) (value : R) (siblings : List R) : Option (List R) := + if siblings.length + 1 == Domain.size arity then + some (siblings.insertIdx (index % Domain.size arity) value) + else none + +structure State where + domain : Domain.Subgroup + index : Nat + value : Extension + deriving DecidableEq, Repr + +structure Round where + arity : Domain.Subgroup + challenge : Extension + siblings : List Extension + deriving DecidableEq, Repr + +structure Row where + domain : Domain.Subgroup + index : Nat + values : List Extension + deriving DecidableEq, Repr + +def roll (height : Nat) (factor value : Extension) : List (Nat × Extension) → + Extension × List (Nat × Extension) + | [] => (value, []) + | (nextHeight, next) :: rest => + if nextHeight == height then (value + factor * next, rest) + else (value, (nextHeight, next) :: rest) + +structure StepResult where + state : State + remaining : List (Nat × Extension) + row : Row + deriving DecidableEq, Repr + +def step (state : State) (round : Round) (openings : List (Nat × Extension)) : Option StepResult := do + if round.arity.val == 0 || round.arity.val > state.domain.val then none + else + let child ← Domain.ofLogSize (state.domain.val - round.arity.val) + let values ← reconstruct round.arity state.index state.value round.siblings + let index := state.index / Domain.size round.arity + let folded ← Interpolation.foldRow state.domain round.arity index values round.challenge + let (value, remaining) := roll child.val (round.challenge.power (Domain.size round.arity)) folded openings + return ⟨⟨child, index, value⟩, remaining, ⟨child, index, values⟩⟩ + +structure Result where + state : State + rows : List Row + deriving DecidableEq, Repr + +def walk (final : Domain.Subgroup) (state : State) (openings : List (Nat × Extension)) : + List Round → Option Result + | [] => if state.domain == final && openings.isEmpty then some ⟨state, []⟩ else none + | round :: rest => do + let result ← step state round openings + let tail ← walk final result.state result.remaining rest + return ⟨tail.state, result.row :: tail.rows⟩ + +def run (initial final : Domain.Subgroup) (index : Nat) (openings : List (Nat × Extension)) + (rounds : List Round) : Option Result := do + if index ≥ Domain.size initial then none + else match openings with + | [] => none + | (height, value) :: rest => + if height == initial.val then walk final ⟨initial, index, value⟩ rest rounds else none + +def check (initial final : Domain.Subgroup) (index : Nat) (openings : List (Nat × Extension)) + (rounds : List Round) (finalPolynomial : List Extension) : Option Result := do + let result ← run initial final index openings rounds + if horner (Extension.ofBase (FriDomain.queryPoint initial result.state.index)) finalPolynomial == result.state.value then + some result + else none + +end Aiur.NativeAIR.FriQuery diff --git a/Ix/Aiur/Interpolation.lean b/Ix/Aiur/Interpolation.lean new file mode 100644 index 000000000..6a09a3e8c --- /dev/null +++ b/Ix/Aiur/Interpolation.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Polynomial +import Ix.Aiur.LogUp + +/-! Coefficients and evaluation of the native FRI row interpolant. +The evaluator preserves the native early return at a node. Elsewhere it +checks every inverse; the domain proofs establish that these checks succeed. +-/ + +namespace Aiur.NativeAIR.Interpolation + +def derivativeValue [OfNat R 0] [Add R] [Mul R] (point : R) : List R → R + | [] => 0 + | _ :: rest => Quotient.horner point rest + point * derivativeValue point rest + +def combine [OfNat R 0] [Add R] [Mul R] (vanishing : List R) (scale : R) : + List (R × R) → List R + | [] => [] + | (root, value) :: rest => + Polynomial.add (Polynomial.scale (value * (root * scale)) (Polynomial.divide root vanishing)) + (combine vanishing scale rest) + +def coefficients [OfNat R 0] [OfNat R 1] [Add R] [Sub R] [Mul R] + (samples : List (R × R)) (scale : R) : List R := + combine (Polynomial.fromRoots (samples.map Prod.fst)) scale samples + +open ProofCodec (Extension) + +def weightedSum (scale point : Extension) : List (Extension × Extension) → Option Extension + | [] => some 0 + | (root, value) :: rest => do + let inverse ← (point - root).tryInverse + let tail ← weightedSum scale point rest + return value * (root * scale) * inverse + tail + +def evaluate (scale point : Extension) (samples : List (Extension × Extension)) : Option Extension := + match samples.find? (fun sample => point == sample.1) with + | some sample => some sample.2 + | none => do + let sum ← weightedSum scale point samples + return sum * LogUp.product (samples.map (fun sample => point - sample.1)) + +def foldSamples (parent arity : Domain.Subgroup) (index : Nat) (values : List Extension) : + List (Extension × Extension) := + ((Polynomial.foldingNodes parent arity index).map Extension.ofBase).zip values + +def foldScale (parent arity : Domain.Subgroup) (index : Nat) : G := + (G.ofNat (Domain.size arity) * (FriDomain.foldNode parent arity index 0).pow (Domain.size arity)).inverse + +def foldRow (parent arity : Domain.Subgroup) (index : Nat) (values : List Extension) + (point : Extension) : Option Extension := + if arity.val > parent.val || index ≥ 2^(parent.val - arity.val) || values.length != Domain.size arity then none + else evaluate (Extension.ofBase (foldScale parent arity index)) point (foldSamples parent arity index values) + +end Aiur.NativeAIR.Interpolation diff --git a/Ix/Aiur/KeyCodec.lean b/Ix/Aiur/KeyCodec.lean new file mode 100644 index 000000000..335fede0d --- /dev/null +++ b/Ix/Aiur/KeyCodec.lean @@ -0,0 +1,239 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ExpressionGraph + +/-! Total host codec for the dense v5 verifying-key format in `vk_codec.rs`. +The decoded graph retains every serialized field. Derived widths, degrees, +lookup prefixes and constraint counts use the native Goldilocks extension +degree two. This module does not implement the PCS or instantiate a native +verifier refinement assumption. -/ + +namespace Aiur.NativeAIR.KeyCodec + +abbrev Reader := StateT (List UInt8) Option + +def readByte : Reader UInt8 + | [] => none + | byte :: rest => some (byte, rest) + +def readNat : Nat → Reader Nat + | 0 => pure 0 + | count + 1 => do + let byte ← readByte + let rest ← readNat count + return byte.toNat + 256 * rest + +def readMany (read : Reader α) : Nat → Reader (List α) + | 0 => pure [] + | count + 1 => do + let first ← read + let rest ← readMany read count + return first :: rest + +def readVector (read : Reader α) : Reader (List α) := do + readMany read (← readNat 2) + +def encodeNat : Nat → Nat → List UInt8 + | 0, _ => [] + | count + 1, value => value.toUInt8 :: encodeNat count (value / 256) + +def encodeVector (encode : α → List UInt8) (values : List α) : List UInt8 := + encodeNat 2 values.length ++ values.flatMap encode + +def readNode : Reader Node := do + match (← readByte).toNat with + | 0 => return .konst (G.ofNat (← readNat 2)) + | 1 => return .konst (G.ofNat (← readNat 8)) + | 2 => return .publicInput (← readNat 1) + | 3 => return .isFirstRow + | 4 => return .isLastRow + | 5 => return .isTransition + | 6 => return .add (← readNat 2) (← readNat 2) + | 7 => return .sub (← readNat 2) (← readNat 2) + | 8 => return .mul (← readNat 2) (← readNat 2) + | 9 => return .neg (← readNat 2) + | 10 => return .var ⟨.preprocessed, .current, ← readNat 2⟩ + | 11 => return .var ⟨.preprocessed, .next, ← readNat 2⟩ + | 12 => return .var ⟨.main, .current, ← readNat 2⟩ + | 13 => return .var ⟨.main, .next, ← readNat 2⟩ + | 14 => return .var ⟨.stage2, .current, ← readNat 2⟩ + | 15 => return .var ⟨.stage2, .next, ← readNat 2⟩ + | _ => failure + +def encodeNode : Node → List UInt8 + | .konst value => if value.n < 65536 then 0 :: encodeNat 2 value.n else 1 :: encodeNat 8 value.n + | .publicInput index => 2 :: encodeNat 1 index + | .isFirstRow => [3] + | .isLastRow => [4] + | .isTransition => [5] + | .add a b => 6 :: (encodeNat 2 a ++ encodeNat 2 b) + | .sub a b => 7 :: (encodeNat 2 a ++ encodeNat 2 b) + | .mul a b => 8 :: (encodeNat 2 a ++ encodeNat 2 b) + | .neg child => 9 :: encodeNat 2 child + | .var column => + let tag : UInt8 := match column.source, column.offset with + | .preprocessed, .current => 10 | .preprocessed, .next => 11 + | .main, .current => 12 | .main, .next => 13 + | .stage2, .current => 14 | .stage2, .next => 15 + tag :: encodeNat 2 column.index + +def readLookup : Reader Lookup := do + let multiplicity ← readNat 2 + let args ← readVector (readNat 2) + return ⟨multiplicity, args⟩ + +def encodeLookup (lookup : Lookup) : List UInt8 := + encodeNat 2 lookup.multiplicity ++ encodeVector (encodeNat 2) lookup.args + +structure Circuit where + mainWidth : Nat + preprocessedWidth : Nat + preprocessedHeight : Nat + maxConstraintDegree : Nat + lookupGroupSize : Nat + graph : Graph + deriving DecidableEq, Repr + +def Circuit.groups (circuit : Circuit) : Nat := + max 1 ((circuit.graph.lookups.length + circuit.lookupGroupSize - 1) / circuit.lookupGroupSize) + +def Circuit.widths (circuit : Circuit) : GraphWidths := + ⟨circuit.preprocessedWidth, circuit.mainWidth, circuit.groups * 2, 8⟩ + +def Circuit.constraintCount (circuit : Circuit) : Nat := + circuit.graph.zeros.length + circuit.groups * 2 + +def nodeDegree (degrees : Array Nat) : Node → Option Nat + | .konst _ | .publicInput _ | .isTransition => some 0 + | .var _ | .isFirstRow | .isLastRow => some 1 + | .add a b | .sub a b => return max (← degrees[a]?) (← degrees[b]?) + | .mul a b => do + let sum := (← degrees[a]?) + (← degrees[b]?) + if sum < 2^32 then some sum else none + | .neg child => degrees[child]? + +def nodeDegreesFrom : List Node → Array Nat → Option (Array Nat) + | [], degrees => some degrees + | node :: nodes, degrees => do + nodeDegreesFrom nodes (degrees.push (← nodeDegree degrees node)) + +def lookupDegrees (degrees : Array Nat) (lookup : Lookup) : Option (Nat × Nat) := do + let multiplicity ← degrees[lookup.multiplicity]? + let args ← lookup.args.mapM (fun index => degrees[index]?) + return (multiplicity, args.foldr max 0) + +/-- The at-most-eight-term native analytic logUp degree calculation. `Nat` +arithmetic agrees with its u64 intermediates when all node degrees fit u32. -/ +def groupDegree (degrees : List (Nat × Nat)) : Nat := + let sum := (degrees.map Prod.snd).sum + (degrees.map (fun (multiplicity, message) => multiplicity + sum - message)).foldr max (sum + 1) + +def Circuit.computedDegree (circuit : Circuit) : Option Nat := do + let degrees ← nodeDegreesFrom circuit.graph.nodes #[] + let zeros ← circuit.graph.zeros.mapM (fun index => degrees[index]?) + let lookups ← circuit.graph.lookups.mapM (lookupDegrees degrees) + let groups := (List.range circuit.groups).map fun index => + groupDegree ((lookups.drop (index * circuit.lookupGroupSize)).take circuit.lookupGroupSize) + return groups.foldr max (max 1 (zeros.foldr max 0)) + +def Circuit.valid (circuit : Circuit) : Bool := + 1 ≤ circuit.lookupGroupSize && circuit.lookupGroupSize ≤ 8 && + (checkedGraphPrefix circuit.widths circuit.graph).isSome && + circuit.computedDegree == some circuit.maxConstraintDegree + +def readCircuitData : Reader Circuit := do + let main ← readNat 2 + let preprocessed ← readNat 2 + let height ← readNat 4 + let degree ← readNat 2 + let group ← readNat 1 + let nodes ← readVector readNode + let zeros ← readVector (readNat 2) + let lookups ← readVector readLookup + return ⟨main, preprocessed, height, degree, group, ⟨nodes, zeros, lookups⟩⟩ + +def readCircuit : Reader Circuit := do + let circuit ← readCircuitData + if circuit.valid then return circuit else failure + +def encodeCircuit (circuit : Circuit) : List UInt8 := + encodeNat 2 circuit.mainWidth ++ encodeNat 2 circuit.preprocessedWidth ++ + encodeNat 4 circuit.preprocessedHeight ++ encodeNat 2 circuit.maxConstraintDegree ++ + encodeNat 1 circuit.lookupGroupSize ++ encodeVector encodeNode circuit.graph.nodes ++ + encodeVector (encodeNat 2) circuit.graph.zeros ++ encodeVector encodeLookup circuit.graph.lookups + +structure Parameters where + logBlowup : Nat + capHeight : Nat + logFinalPolyLen : Nat + maxLogArity : Nat + numQueries : Nat + commitProofOfWorkBits : Nat + queryProofOfWorkBits : Nat + deriving DecidableEq, Repr + +def readParameters : Reader Parameters := do + return ⟨← readNat 2, ← readNat 2, ← readNat 2, ← readNat 2, + ← readNat 2, ← readNat 2, ← readNat 2⟩ + +def encodeParameters (parameters : Parameters) : List UInt8 := + [parameters.logBlowup, parameters.capHeight, parameters.logFinalPolyLen, + parameters.maxLogArity, parameters.numQueries, parameters.commitProofOfWorkBits, + parameters.queryProofOfWorkBits].flatMap (encodeNat 2) + +abbrev MerkleCap := List (List UInt8) + +def readCommitment : Reader (Option MerkleCap) := do + match (← readByte).toNat with + | 0 => return none + | 1 => + let cap ← readVector (readMany readByte 32) + if cap.length.isPowerOfTwo then return some cap else failure + | _ => failure + +def encodeCommitment : Option MerkleCap → List UInt8 + | none => [0] + | some cap => 1 :: encodeVector id cap + +def readIndex : Reader (Option Nat) := do + let index ← readNat 2 + return if index = 65535 then none else some index + +def encodeIndex (index : Option Nat) : List UInt8 := + encodeNat 2 (index.getD 65535) + +structure Key where + parameters : Parameters + circuits : List Circuit + preprocessedCommitment : Option MerkleCap + preprocessedIndices : List (Option Nat) + deriving DecidableEq, Repr + +def readKey : Reader Key := do + let parameters ← readParameters + let circuits ← readVector readCircuit + let commitment ← readCommitment + let indices ← readMany readIndex circuits.length + return ⟨parameters, circuits, commitment, indices⟩ + +def encodeKey (key : Key) : List UInt8 := + encodeParameters key.parameters ++ encodeVector encodeCircuit key.circuits ++ + encodeCommitment key.preprocessedCommitment ++ key.preprocessedIndices.flatMap encodeIndex + +/-- Complete consumption is mandatory; an extra suffix is not another key. -/ +def decode (bytes : ByteArray) : Option Key := do + let (key, rest) ← readKey bytes.data.toList + if rest.isEmpty then some key else none + +def encode (key : Key) : ByteArray := (encodeKey key).toByteArray + +/-- Optional canonical-byte gate. The native decoder also accepts big-tag +small constants and reduces u64 field constants; canonical encoding does not. -/ +def decodeCanonical (bytes : ByteArray) : Option Key := do + let key ← decode bytes + if encode key = bytes then some key else none + +end Aiur.NativeAIR.KeyCodec diff --git a/Ix/Aiur/LogUp.lean b/Ix/Aiur/LogUp.lean new file mode 100644 index 000000000..17eb25d09 --- /dev/null +++ b/Ix/Aiur/LogUp.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.LookupCoordinates + +/-! Checked degree-two logUp evaluation. Every external node and coordinate +read is optional. Group zero has the native normalization to one; groups above +eight are rejected. The returned list retains both coordinates in native order. +Prefix and suffix scans include multiplication by one at their endpoints; +ring reflection relates these to the native seeded scans. -/ + +namespace Aiur.NativeAIR.LogUp + +def product [OfNat R 1] [Mul R] (values : List R) : R := values.foldr (· * ·) 1 +def sum [OfNat R 0] [Add R] (values : List R) : R := values.foldr (· + ·) 0 + +/-- Denominator-cleared weighted numerator, defined without division. -/ +def numerator [OfNat R 0] [OfNat R 1] [Add R] [Mul R] : List (R × R) → R + | [] => 0 + | (weight, message) :: rest => + weight * product (rest.map Prod.snd) + message * numerator rest + +def prefixSuffixTerms [OfNat R 1] [Mul R] (initial : R) (entries : List (R × R)) : List R := + let messages := entries.map Prod.snd + let prefixes := messages.scanl (· * ·) initial + let suffixes := (messages.scanr (· * ·) 1).tail + (entries.zip (prefixes.zip suffixes)).map fun (entry, before, after) => before * after * entry.1 + +def groupEquation [OfNat R 0] [OfNat R 1] [Add R] [Sub R] [Mul R] + (entries : List (R × R)) (difference : R) : R := + match entries with + | [] => difference + | [(weight, message)] => message * difference - weight + | _ => (entries.map Prod.snd).foldl (· * ·) 1 * difference - + (prefixSuffixTerms 1 entries).foldl (· + ·) 0 + +section Evaluation + +variable {W : Type u} [OfNat W 0] [OfNat W 1] [OfNat W 7] [Add W] [Sub W] [Mul W] + +def fingerprint (gamma : Coordinates W) (args : List W) : Coordinates W := + args.foldr (fun arg acc => acc * gamma + Coordinates.ofBase arg) 0 + +def compress (beta gamma : Coordinates W) (lookups : List (W × List W)) : + List (Coordinates W × Coordinates W) := + lookups.map fun (multiplicity, args) => + (Coordinates.ofBase multiplicity, fingerprint gamma args + beta) + +def groupCount (groupSize lookupCount : Nat) : Nat := + max 1 ((lookupCount + max groupSize 1 - 1) / max groupSize 1) + +def chunk (groupSize index : Nat) (lookups : List α) : List α := + (lookups.drop (index * max groupSize 1)).take (max groupSize 1) + +def step (beta gamma injection next : Coordinates W) (stageCurrent : Array W) + (lookups : List (W × List W)) (groupSize index : Nat) : Option (Coordinates W) := do + let source ← Coordinates.read stageCurrent index + let target ← if index + 1 < groupCount groupSize lookups.length then Coordinates.read stageCurrent (index + 1) + else some (next + injection) + return groupEquation (compress beta gamma (chunk groupSize index lookups)) (target - source) + +def equations (lookups : List (W × List W)) (stageCurrent stageNext publics deltaScaled : Array W) + (isLast : W) (groupSize : Nat) : Option (List (Coordinates W)) := do + if 8 < groupSize then none else do + let beta ← Coordinates.read publics 0 + let gamma ← Coordinates.read publics 1 + let delta ← Coordinates.read deltaScaled 0 + let injection := delta.scale isLast + let next ← Coordinates.read stageNext 0 + let groups := groupCount groupSize lookups.length + (List.range groups).mapM (step beta gamma injection next stageCurrent lookups groupSize) + +def constraintValues (lookups : List Lookup) (nodeValues stageCurrent stageNext publics deltaScaled : Array W) + (isLast : W) (groupSize : Nat) : Option (List W) := do + let values ← lookups.mapM (readLookup nodeValues) + return Coordinates.flatten (← equations values stageCurrent stageNext publics deltaScaled isLast groupSize) + +end Evaluation +end Aiur.NativeAIR.LogUp diff --git a/Ix/Aiur/LookupCoordinates.lean b/Ix/Aiur/LookupCoordinates.lean new file mode 100644 index 000000000..125702e54 --- /dev/null +++ b/Ix/Aiur/LookupCoordinates.lean @@ -0,0 +1,50 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Extension + +/-! The two coordinates checked by native degree-two logUp. At an opening +point each coordinate is itself a challenge-field value. The two coordinates +must remain separate there; this quadratic algebra need not be a field. -/ + +namespace Aiur.NativeAIR.LogUp + +structure Coordinates (W : Type u) where + c0 : W + c1 : W + deriving DecidableEq, Repr + +namespace Coordinates + +def ofBase [OfNat W 0] (value : W) : Coordinates W := ⟨value, 0⟩ + +instance ofNat [OfNat W n] [OfNat W 0] : OfNat (Coordinates W) n := + ⟨ofBase (OfNat.ofNat n)⟩ +instance add [Add W] : Add (Coordinates W) := ⟨fun a b => ⟨a.c0 + b.c0, a.c1 + b.c1⟩⟩ +instance sub [Sub W] : Sub (Coordinates W) := ⟨fun a b => ⟨a.c0 - b.c0, a.c1 - b.c1⟩⟩ +instance neg [Neg W] : Neg (Coordinates W) := ⟨fun a => ⟨-a.c0, -a.c1⟩⟩ + +/-- The native `mul2` Karatsuba formula, with the pinned nonresidue 7. -/ +instance mul [OfNat W 7] [Add W] [Sub W] [Mul W] : Mul (Coordinates W) := ⟨fun a b => + let v0 := a.c0 * b.c0 + let v1 := a.c1 * b.c1 + ⟨v0 + v1 * 7, (a.c0 + a.c1) * (b.c0 + b.c1) - v0 - v1⟩⟩ + +def scale [Mul W] (value : Coordinates W) (scalar : W) : Coordinates W := + ⟨value.c0 * scalar, value.c1 * scalar⟩ + +def map (f : W → V) (value : Coordinates W) : Coordinates V := ⟨f value.c0, f value.c1⟩ + +def read (values : Array W) (slot : Nat) : Option (Coordinates W) := do + return ⟨← values[2 * slot]?, ← values[2 * slot + 1]?⟩ + +def flatten (values : List (Coordinates W)) : List W := values.flatMap fun value => [value.c0, value.c1] + +/-- Only base-field coordinates have this identification with the native field. -/ +def toExtension (value : Coordinates G) : ProofCodec.Extension := ⟨value.c0, value.c1⟩ +def fromExtension (value : ProofCodec.Extension) : Coordinates G := ⟨value.c0, value.c1⟩ + +end Coordinates +end Aiur.NativeAIR.LogUp diff --git a/Ix/Aiur/LookupGroups.lean b/Ix/Aiur/LookupGroups.lean new file mode 100644 index 000000000..ed929163e --- /dev/null +++ b/Ix/Aiur/LookupGroups.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.KeyCodec + +/-! Total lookup-group selection for the production FFT cost comparison. +Machine-size and u128 intermediate checks match the native selector. The +authored graph remains fixed; grouping determines the direct LogUp evaluator's +degree, accumulator width and constraint count. -/ + +namespace Aiur.NativeAIR.LookupGroups + +structure FftCost where + one : Nat + two : Nat + slope : Nat + intercept : Nat + deriving DecidableEq, Repr + +def checked128 (value : Nat) : Option Nat := + if value < 2^128 then some value else none + +def FftCost.make (stage2 quotient blowup degree : Nat) : Option FftCost := do + if stage2 ≥ 2^64 || quotient ≥ 2^64 || blowup ≥ 2^64 || degree ≥ 2^64 then none else do + if quotient = 0 || quotient.nextPowerOfTwo != quotient || + blowup = 0 || blowup.nextPowerOfTwo != blowup then none else do + let logQ := quotient.log2 + let logB := blowup.log2 + let qd ← checked128 (quotient * degree) + let trace ← checked128 ((blowup + 1) * stage2) + let combined ← checked128 (stage2 + qd) + let slope ← checked128 ((blowup + 1) * combined) + let scaledLog ← checked128 (blowup * logB) + let logs ← checked128 (logQ + scaledLog) + let intercept ← checked128 (qd * logs) + let scaledOneLog ← checked128 (blowup * max logB 1) + let oneLogs ← checked128 (max logQ 1 + scaledOneLog) + let quotientOne ← checked128 (qd * oneLogs) + let one ← checked128 (trace + quotientOne) + let two ← checked128 (slope + intercept) + return ⟨one, two, slope, intercept⟩ + +def FftCost.noWorse (candidate baseline : FftCost) : Bool := + candidate.one ≤ baseline.one && candidate.two ≤ baseline.two && candidate.slope ≤ baseline.slope + +def FftCost.scoreLess (candidate current : FftCost) : Bool := + candidate.slope < current.slope || + (candidate.slope == current.slope && + (candidate.intercept < current.intercept || + (candidate.intercept == current.intercept && candidate.one < current.one))) + +def quotientDegree (circuit : KeyCodec.Circuit) : Nat := + (max circuit.maxConstraintDegree 2 - 1).nextPowerOfTwo + +def withGroup (circuit : KeyCodec.Circuit) (group : Nat) : Option KeyCodec.Circuit := do + let candidate := { circuit with lookupGroupSize := group } + let degree ← candidate.computedDegree + return { candidate with maxConstraintDegree := degree } + +def selectGroup (circuit : KeyCodec.Circuit) (blowup : Nat) : Option Nat := do + if circuit.graph.nodes.any (fun node => match node with + | .var column => column.source == .stage2 | _ => false) then none else do + let baseline ← FftCost.make circuit.widths.stage2 (quotientDegree circuit) blowup 2 + let best := (List.range (min 8 (max 1 circuit.graph.lookups.length))).foldl + (fun best offset => + let group := offset + 1 + match withGroup circuit group with + | none => best + | some candidate => + let quotient := quotientDegree candidate + if quotient ≥ 2^64 || quotient > blowup then best else + match FftCost.make candidate.widths.stage2 quotient blowup 2 with + | none => best + | some cost => + if cost.noWorse baseline && cost.scoreLess best.2 then (group, cost) else best) + (circuit.lookupGroupSize, baseline) + return best.1 + +def retune (circuit : KeyCodec.Circuit) (blowup : Nat) : KeyCodec.Circuit := + match selectGroup circuit blowup with + | none => circuit + | some group => (withGroup circuit group).getD circuit + +/-- Fields consumed by the authored AIR and the preprocessed commitment. -/ +def AuthoredFields (circuit : KeyCodec.Circuit) := + (circuit.graph, circuit.mainWidth, circuit.preprocessedWidth, circuit.preprocessedHeight) + +theorem withGroup_authored {circuit result : KeyCodec.Circuit} {group : Nat} + (selected : withGroup circuit group = some result) : AuthoredFields result = AuthoredFields circuit := by + simp only [withGroup, bind, Option.bind] at selected + split at selected + · cases selected + · cases selected + rfl + +theorem retune_authored (circuit : KeyCodec.Circuit) (blowup : Nat) : + AuthoredFields (retune circuit blowup) = AuthoredFields circuit := by + unfold retune + split + · rfl + · rename_i group _ + cases selected : withGroup circuit group with + | none => rfl + | some result => exact withGroup_authored selected + +end Aiur.NativeAIR.LookupGroups diff --git a/Ix/Aiur/LookupShapes.lean b/Ix/Aiur/LookupShapes.lean new file mode 100644 index 000000000..68bc15db1 --- /dev/null +++ b/Ix/Aiur/LookupShapes.lean @@ -0,0 +1,114 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +module +public import Ix.Aiur.Stages.Bytecode + +/-! +Total structural checks for the boundaries of zero-padded lookup messages. + +Function messages contain the function index, inputs, outputs and rank, +without length separators. Calls must use their callee's input and return +arities. Public result arity is checked separately against the entry body. +These checks do not establish value-index or circuit-layout correctness. +-/ + +public section +@[expose] section + +namespace Aiur.Bytecode + +private theorem block_ctrl_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +/-- Check every function return, including early returns from continuation +arms. A yield returns to its enclosing continuation, not the function. -/ +def Ctrl.returnsHaveSize (size : Nat) : Ctrl → Bool + | .return _ values => values.size == size + | .yield .. => true + | .match _ branches fallback => + branches.attach.all (fun ⟨(_, block), _⟩ => block.returnsHaveSize size) && + (match fallback with | none => true | some block => block.returnsHaveSize size) + | .matchContinue _ branches fallback _ _ _ continuation => + branches.attach.all (fun ⟨(_, block), _⟩ => block.returnsHaveSize size) && + ((match fallback with | none => true | some block => block.returnsHaveSize size) && + continuation.returnsHaveSize size) +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.returnsHaveSize (size : Nat) (block : Block) : Bool := + block.ctrl.returnsHaveSize size +termination_by sizeOf block +decreasing_by exact block_ctrl_smaller block + +end + +def Op.lookupShape (program : Toplevel) : Op → Bool + | .call index inputs outputs false => + match program.functions[index]? with + | none => false + | some callee => callee.constrained && + (callee.layout.inputSize == inputs.size && callee.body.returnsHaveSize outputs) + | .store values => decide (values.size < gSize.toNat) + | .load size _ => decide (size < gSize.toNat) + | _ => true + +mutual + +def Ctrl.lookupShapes (program : Toplevel) (yieldSize : Option Nat) : Ctrl → Bool + | .return .. => true + | .yield _ values => yieldSize == some values.size + | .match _ branches fallback => + branches.attach.all (fun ⟨(_, block), _⟩ => block.lookupShapes program yieldSize) && + (match fallback with | none => true | some block => block.lookupShapes program yieldSize) + | .matchContinue _ branches fallback size _ _ continuation => + branches.attach.all (fun ⟨(_, block), _⟩ => block.lookupShapes program (some size)) && + ((match fallback with | none => true | some block => block.lookupShapes program (some size)) && + continuation.lookupShapes program yieldSize) +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.lookupShapes (program : Toplevel) (yieldSize : Option Nat) (block : Block) : Bool := + block.ops.all (Op.lookupShape program) && block.ctrl.lookupShapes program yieldSize +termination_by sizeOf block +decreasing_by exact block_ctrl_smaller block + +end + +/-- Mirror the native construction guard, including canonical function +indices, canonical memory widths and continuation-yield arities. -/ +def Toplevel.validateLookupShapes (program : Toplevel) : Bool := + decide (program.functions.size < gSize.toNat) && + (program.memorySizes.all (fun size => decide (size < gSize.toNat)) && + program.functions.all (fun function => + !function.constrained || function.body.lookupShapes program none)) + +/-- A public claim names a constrained public function and has exactly its +input and return widths. The final zero rank is omitted from this encoding. -/ +def Toplevel.validClaimShape (program : Toplevel) (claim : Array G) : Bool := + match claim.toList with + | channel :: index :: arguments => + channel == 0 && + (match program.functions[index.n]? with + | none => false + | some function => function.entry && function.constrained && + (decide (function.layout.inputSize ≤ arguments.length) && + function.body.returnsHaveSize (arguments.length - function.layout.inputSize))) + | _ => false + +end Aiur.Bytecode + +end +end diff --git a/Ix/Aiur/Merkle.lean b/Ix/Aiur/Merkle.lean new file mode 100644 index 000000000..5509d7269 --- /dev/null +++ b/Ix/Aiur/Merkle.lean @@ -0,0 +1,113 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Blake3 +import Ix.Aiur.MerkleCap + +/-! Binary MMCS paths for verifier-selected power-of-two matrix heights. +Rows at the same height retain their original matrix order. Every ordinary +BLAKE3 input is retained, including both hashes around a shorter-row +injection. Shared, pruned openings are a separate verification algorithm. +-/ + +namespace Aiur.NativeAIR.Merkle + +abbrev Digest := Blake3.Digest +abbrev Hash := List UInt8 → Digest + +structure Dimensions where + width : Nat + logHeight : Nat + deriving DecidableEq, Repr + +def maxHeight (dimensions : List Dimensions) : Nat := + MerkleCap.maxDegree (dimensions.map Dimensions.logHeight) + +def shape : List Dimensions → List (List G) → Bool + | [], [] => true + | dimension :: dimensions, row :: rows => row.length == dimension.width && shape dimensions rows + | _, _ => false + +def hasHeight (dimensions : List Dimensions) (height : Nat) : Bool := + dimensions.any fun dimension => dimension.logHeight == height + +def rowsAt : List Dimensions → List (List G) → Nat → List (List G) + | dimension :: dimensions, row :: rows, height => + if dimension.logHeight = height then row :: rowsAt dimensions rows height + else rowsAt dimensions rows height + | _, _, _ => [] + +def rowBytes (dimensions : List Dimensions) (rows : List (List G)) (height : Nat) : List UInt8 := + Transcript.fieldsBytes (rowsAt dimensions rows height).flatten + +def pairBytes (left right : Digest) : List UInt8 := left.toList ++ right.toList + +def branchBytes (index : Nat) (current sibling : Digest) : List UInt8 := + if index % 2 = 0 then pairBytes current sibling else pairBytes sibling current + +structure Hashing where + digest : Digest + inputs : List (List UInt8) + deriving DecidableEq, Repr + +/-- `height` is the next layer, after pairing the current node and sibling. -/ +def step (hash : Hash) (dimensions : List Dimensions) (rows : List (List G)) + (height index : Nat) (current sibling : Digest) : Hashing := + let input := branchBytes index current sibling + let parent := hash input + if hasHeight dimensions height then + let leaf := rowBytes dimensions rows height + let inject := pairBytes parent (hash leaf) + ⟨hash inject, [input, leaf, inject]⟩ + else ⟨parent, [input]⟩ + +def walk (hash : Hash) (dimensions : List Dimensions) (rows : List (List G)) + (height index : Nat) (current : Digest) : List Digest → Hashing + | [] => ⟨current, []⟩ + | sibling :: proof => + let first := step hash dimensions rows (height - 1) index current sibling + let rest := walk hash dimensions rows (height - 1) (index / 2) first.digest proof + ⟨rest.digest, first.inputs ++ rest.inputs⟩ + +structure Replay where + logHeight : Nat + index : Nat + hashing : Hashing + deriving DecidableEq, Repr + +/-- Structural failure precedes hashing, as in native individual verification. +The raw replay preserves the native omission of rows below the cap. -/ +def replay (hash : Hash) (dimensions : List Dimensions) (capHeight index : Nat) + (rows : List (List G)) (proof : List Digest) : Option Replay := + let height := maxHeight dimensions + if dimensions.isEmpty || !shape dimensions rows || + proof.length != height - capHeight || !(index < 2^height) then none + else + let leaf := rowBytes dimensions rows height + let result := walk hash dimensions rows height index (hash leaf) proof + some ⟨height - proof.length, index / 2^proof.length, ⟨result.digest, leaf :: result.inputs⟩⟩ + +def accepts (cap : List Digest) (result : Replay) : Bool := + cap[result.index]? == some result.hashing.digest + +def verify (hash : Hash) (dimensions : List Dimensions) (capHeight index : Nat) + (cap : List Digest) (rows : List (List G)) (proof : List Digest) : Bool := + match replay hash dimensions capHeight index rows proof with + | none => false + | some result => accepts cap result + +def covered (dimensions : List Dimensions) (capHeight : Nat) : Bool := + MerkleCap.coverage 0 capHeight (dimensions.map Dimensions.logHeight) + +def verifyCovered (hash : Hash) (dimensions : List Dimensions) (capHeight index : Nat) + (cap : List Digest) (rows : List (List G)) (proof : List Digest) : Bool := + covered dimensions capHeight && verify hash dimensions capHeight index cap rows proof + +/-- A collision among the inputs actually queried by these replays. This is +finite and gives an explicit witness; it does not assert global injectivity. -/ +def CollisionOn (hash : Hash) (inputs : List (List UInt8)) : Prop := + ∃ left ∈ inputs, ∃ right ∈ inputs, left ≠ right ∧ hash left = hash right + +end Aiur.NativeAIR.Merkle diff --git a/Ix/Aiur/MerkleCap.lean b/Ix/Aiur/MerkleCap.lean new file mode 100644 index 000000000..51040dca4 --- /dev/null +++ b/Ix/Aiur/MerkleCap.lean @@ -0,0 +1,24 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ProofShape + +/-! A binary MMCS cap must retain every matrix injection. Heights here are +logarithms of power-of-two row counts. Subtracting the common LDE blowup +before comparing avoids machine addition overflow in the native guard. +-/ + +namespace Aiur.NativeAIR.MerkleCap + +def maxDegree (degrees : List Nat) : Nat := degrees.foldr max 0 + +def coverage (logBlowup capHeight : Nat) (degrees : List Nat) : Bool := + let effective := min (capHeight - logBlowup) (maxDegree degrees) + degrees.all fun degree => effective ≤ degree + +def check (key : KeyCodec.Key) (proof : ProofCodec.Data) : Bool := + coverage key.parameters.logBlowup key.parameters.capHeight (proof.logDegrees.map UInt8.toNat) + +end Aiur.NativeAIR.MerkleCap diff --git a/Ix/Aiur/Polynomial.lean b/Ix/Aiur/Polynomial.lean new file mode 100644 index 000000000..a93f9d83c --- /dev/null +++ b/Ix/Aiur/Polynomial.lean @@ -0,0 +1,52 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Quotient +import Ix.Aiur.FriDomain + +/-! Coefficients in the native verifier's ascending-power convention. +Trailing zeros are permitted. Synthetic division lowers the coefficient +length without assuming an evaluation point is a root. +-/ + +namespace Aiur.NativeAIR.Polynomial + +def IsZero [OfNat R 0] (coefficients : List R) : Prop := + ∀ coefficient ∈ coefficients, coefficient = 0 + +def Monic [OfNat R 1] (coefficients : List R) : Prop := + ∃ initial, coefficients = initial ++ [1] + +def add [Add R] : List R → List R → List R + | [], right => right + | left, [] => left + | first :: left, second :: right => (first + second) :: add left right + +def sub [OfNat R 0] [Sub R] : List R → List R → List R + | [], right => right.map (0 - ·) + | left, [] => left + | first :: left, second :: right => (first - second) :: sub left right + +def scale [Mul R] (scalar : R) (coefficients : List R) : List R := + coefficients.map (scalar * ·) + +def mulLinear [OfNat R 0] [Sub R] [Mul R] (root : R) (coefficients : List R) : List R := + sub (0 :: coefficients) (scale root coefficients) + +def fromRoots [OfNat R 0] [OfNat R 1] [Sub R] [Mul R] (roots : List R) : List R := + roots.foldr mulLinear [1] + +def powerMinus [OfNat R 0] [OfNat R 1] [Sub R] (degree : Nat) (constant : R) : List R := + sub (List.replicate degree 0 ++ [1]) [constant] + +def divide [OfNat R 0] [Add R] [Mul R] (point : R) : List R → List R + | [] => [] + | [_] => [] + | _ :: next :: rest => Quotient.horner point (next :: rest) :: divide point (next :: rest) + +def foldingNodes (parent arity : Domain.Subgroup) (index : Nat) : List G := + (List.range (Domain.size arity)).map (FriDomain.foldNode parent arity index) + +end Aiur.NativeAIR.Polynomial diff --git a/Ix/Aiur/ProofCodec.lean b/Ix/Aiur/ProofCodec.lean new file mode 100644 index 000000000..8c4b6673e --- /dev/null +++ b/Ix/Aiur/ProofCodec.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.KeyCodec + +/-! Total codec for the pinned CPU Goldilocks/Blake3 multi-STARK proof. +The native bincode configuration uses little-endian fixed-width integers, +u64 vector lengths, one-byte booleans/options, and fixed arrays without a +length prefix. Extension elements have two canonical Goldilocks coordinates. + +Every opening and authentication digest is retained. Parsing establishes +byte framing only; proof shape, transcript checks and cryptographic meaning +are separate obligations. Native `from_bytes` permits a trailing suffix; +`decode` deliberately requires complete consumption. +-/ + +namespace Aiur.NativeAIR.ProofCodec + +open KeyCodec (Reader readByte readNat readMany encodeNat) + +structure Extension where + c0 : G + c1 : G + deriving DecidableEq, Repr + +abbrev Digest := List UInt8 +abbrev Cap := List Digest +abbrev Openings (α : Type) := List (List (List α)) + +def readVector (read : Reader α) : Reader (List α) := do + readMany read (← readNat 8) + +def encodeVector (encode : α → List UInt8) (values : List α) : List UInt8 := + encodeNat 8 values.length ++ values.flatMap encode + +def readOption (read : Reader α) : Reader (Option α) := do + match (← readByte).toNat with + | 0 => return none + | 1 => return some (← read) + | _ => failure + +def encodeOption (encode : α → List UInt8) : Option α → List UInt8 + | none => [0] + | some value => 1 :: encode value + +def readBool : Reader Bool := do + match (← readByte).toNat with + | 0 => return false + | 1 => return true + | _ => failure + +def encodeBool (value : Bool) : List UInt8 := [if value then 1 else 0] + +def readField : Reader G := do + let value ← readNat 8 + if value < gSize.toNat then return G.ofNat value else failure + +def encodeField (value : G) : List UInt8 := encodeNat 8 value.n + +def readExtension : Reader Extension := do + return ⟨← readField, ← readField⟩ + +def encodeExtension (value : Extension) : List UInt8 := + encodeField value.c0 ++ encodeField value.c1 + +def readCap : Reader Cap := readVector (readMany readByte 32) + +def encodeCap (cap : Cap) : List UInt8 := encodeVector id cap + +def readOpenings (read : Reader α) : Reader (Openings α) := + readVector (readVector (readVector read)) + +def encodeOpenings (encode : α → List UInt8) (values : Openings α) : List UInt8 := + encodeVector (encodeVector (encodeVector encode)) values + +structure Commitments where + stage1 : Cap + stage2 : Cap + quotient : Cap + deriving DecidableEq, Repr + +def readCommitments : Reader Commitments := do + return ⟨← readCap, ← readCap, ← readCap⟩ + +def encodeCommitments (value : Commitments) : List UInt8 := + encodeCap value.stage1 ++ encodeCap value.stage2 ++ encodeCap value.quotient + +structure BatchOpening where + values : Openings G + siblingHashes : List Digest + deriving DecidableEq, Repr + +def readBatchOpening : Reader BatchOpening := do + return ⟨← readOpenings readField, ← readCap⟩ + +def encodeBatchOpening (value : BatchOpening) : List UInt8 := + encodeOpenings encodeField value.values ++ encodeCap value.siblingHashes + +structure CommitStep where + logArity : UInt8 + siblingValues : List (List Extension) + siblingHashes : List Digest + deriving DecidableEq, Repr + +def readCommitStep : Reader CommitStep := do + return ⟨← readByte, ← readVector (readVector readExtension), ← readCap⟩ + +def encodeCommitStep (value : CommitStep) : List UInt8 := + value.logArity :: (encodeVector (encodeVector encodeExtension) value.siblingValues ++ + encodeCap value.siblingHashes) + +structure Fri where + commits : List Cap + commitPowWitnesses : List G + inputOpenings : List BatchOpening + commitOpenings : List CommitStep + finalPoly : List Extension + queryPowWitness : G + deriving DecidableEq, Repr + +def readFri : Reader Fri := do + return ⟨← readVector readCap, ← readVector readField, + ← readVector readBatchOpening, ← readVector readCommitStep, + ← readVector readExtension, ← readField⟩ + +def encodeFri (value : Fri) : List UInt8 := + encodeVector encodeCap value.commits ++ encodeVector encodeField value.commitPowWitnesses ++ + encodeVector encodeBatchOpening value.inputOpenings ++ encodeVector encodeCommitStep value.commitOpenings ++ + encodeVector encodeExtension value.finalPoly ++ encodeField value.queryPowWitness + +structure Data where + active : List Bool + commitments : Commitments + accumulators : List Extension + logDegrees : List UInt8 + fri : Fri + quotient : Openings Extension + preprocessed : Option (Openings Extension) + stage1 : Openings Extension + stage2 : Openings Extension + deriving DecidableEq, Repr + +def readData : Reader Data := do + return ⟨← readVector readBool, ← readCommitments, ← readVector readExtension, + ← readVector readByte, ← readFri, ← readOpenings readExtension, + ← readOption (readOpenings readExtension), ← readOpenings readExtension, + ← readOpenings readExtension⟩ + +def encodeData (value : Data) : List UInt8 := + encodeVector encodeBool value.active ++ encodeCommitments value.commitments ++ + encodeVector encodeExtension value.accumulators ++ encodeVector (fun b => [b]) value.logDegrees ++ + encodeFri value.fri ++ encodeOpenings encodeExtension value.quotient ++ + encodeOption (encodeOpenings encodeExtension) value.preprocessed ++ + encodeOpenings encodeExtension value.stage1 ++ encodeOpenings encodeExtension value.stage2 + +def decode (bytes : ByteArray) : Option Data := do + let (value, rest) ← readData bytes.data.toList + if rest.isEmpty then some value else none + +def encode (value : Data) : ByteArray := (encodeData value).toByteArray + +def decodeCanonical (bytes : ByteArray) : Option Data := do + let value ← decode bytes + if encode value = bytes then some value else none + +end Aiur.NativeAIR.ProofCodec diff --git a/Ix/Aiur/ProofShape.lean b/Ix/Aiur/ProofShape.lean new file mode 100644 index 000000000..31f72b70f --- /dev/null +++ b/Ix/Aiur/ProofShape.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ProofCodec +import Ix.Aiur.Proofs.ByteColumns + +/-! Checked extraction of the native verifier's per-active-circuit opening +records. This mirrors `System::verify_shape` using checked indexed reads. +The Aiur guards additionally bind fixed trace heights and the lookup budget. +Opened values are claims about polynomials; shape checks alone do not prove +that they arise from a satisfying execution trace. +-/ + +namespace Aiur.NativeAIR.ProofShape + +open ProofCodec (Extension Data) + +structure Pair where + current : List Extension + next : List Extension + deriving DecidableEq, Repr + +def pair : List (List Extension) → Option Pair + | [current, next] => some ⟨current, next⟩ + | _ => none + +def single : List α → Option α + | [value] => some value + | _ => none + +def activeIndices (proof : Data) : List Nat := + proof.active.zipIdx.filterMap fun (active, index) => if active then some index else none + +def quotientDegree (circuit : KeyCodec.Circuit) : Nat := + (max circuit.maxConstraintDegree 2 - 1).nextPowerOfTwo + +structure Row where + circuitIndex : Nat + circuit : KeyCodec.Circuit + logDegree : UInt8 + stage1 : Pair + stage2 : Pair + preprocessed : Option Pair + quotient : List Extension + accumulator : Extension + deriving DecidableEq, Repr + +def readPreprocessed (proof : Data) : Option Nat → Option (Option Pair) + | none => some none + | some slot => (proof.preprocessed >>= fun opened => opened[slot]? >>= pair).map some + +def readRow (key : KeyCodec.Key) (proof : Data) (index position : Nat) : Option Row := do + let circuit ← key.circuits[index]? + let preprocessedIndex ← key.preprocessedIndices[index]? + let degree ← proof.logDegrees[position]? + let stage1 ← pair (← proof.stage1[position]?) + let stage2 ← pair (← proof.stage2[position]?) + let quotient ← single (← proof.quotient[position]?) + let accumulator ← proof.accumulators[position]? + let preprocessed ← readPreprocessed proof preprocessedIndex + return ⟨index, circuit, degree, stage1, stage2, preprocessed, quotient, accumulator⟩ + +def Pair.hasWidth (values : Pair) (width : Nat) : Bool := + values.current.length == width && values.next.length == width + +def Row.fits (parameters : KeyCodec.Parameters) (row : Row) : Bool := + row.stage1.hasWidth row.circuit.mainWidth && row.stage2.hasWidth row.circuit.widths.stage2 && + (match row.preprocessed with | none => true | some values => values.hasWidth row.circuit.preprocessedWidth) && + row.quotient.length == quotientDegree row.circuit * 2 && + row.logDegree.toNat + (quotientDegree row.circuit).log2 ≤ 32 - parameters.logBlowup + +def header (key : KeyCodec.Key) (proof : Data) : Bool := + let active := (activeIndices proof).length + let preprocessed := (key.preprocessedIndices.filter Option.isSome).length + !key.circuits.isEmpty && proof.active.length == key.circuits.length && active > 0 && + key.preprocessedIndices.length == key.circuits.length && + proof.logDegrees.length == active && + key.preprocessedCommitment.isNone == (preprocessed == 0) && + (proof.preprocessed.getD []).length == preprocessed && + proof.stage1.length == active && proof.stage2.length == active && + proof.quotient.length == active && proof.accumulators.length == active + +def inactivePreprocessed (key : KeyCodec.Key) (proof : Data) : Bool := + (key.preprocessedIndices.zip proof.active).all fun (slot, active) => + match slot, active with + | some index, false => (proof.preprocessed.getD [])[index]? == some [] + | _, _ => true + +def rows (key : KeyCodec.Key) (proof : Data) : Option (List Row) := + (activeIndices proof).zipIdx.mapM fun (index, position) => readRow key proof index position + +def check (key : KeyCodec.Key) (proof : Data) : Option (List Row) := do + if header key proof && inactivePreprocessed key proof then + let result ← rows key proof + if result.all (Row.fits key.parameters) then some result else none + else none + +def fixedHeights (key : KeyCodec.Key) (proof : Data) : Bool := + fixedTraceHeights (key.circuits.map (·.preprocessedHeight)) proof.active + (proof.logDegrees.map UInt8.toNat) + +def queryBound (key : KeyCodec.Key) (proof : Data) : Option Nat := + lookupQueryBound (key.circuits.map (·.graph.lookups.length)) proof.active + (proof.logDegrees.map UInt8.toNat) + +end Aiur.NativeAIR.ProofShape diff --git a/Ix/Aiur/Proofs.lean b/Ix/Aiur/Proofs.lean new file mode 100644 index 000000000..34c3ffa44 --- /dev/null +++ b/Ix/Aiur/Proofs.lean @@ -0,0 +1,70 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Activity +import Ix.Aiur.Proofs.CallOrder +import Ix.Aiur.Proofs.Lookup +import Ix.Aiur.Proofs.Execution +import Ix.Aiur.Proofs.Memory +import Ix.Aiur.Proofs.Field +import Ix.Aiur.Proofs.LocalConstraints +import Ix.Aiur.Proofs.ByteArithmetic +import Ix.Aiur.Proofs.ByteLookups +import Ix.Aiur.Proofs.LookupMessages +import Ix.Aiur.Proofs.LookupShapes +import Ix.Aiur.Proofs.GlobalLookups +import Ix.Aiur.Proofs.LookupBudget +import Ix.Aiur.Proofs.SelectorMessages +import Ix.Aiur.Proofs.SelectorControl +import Ix.Aiur.Proofs.ReturnGates +import Ix.Aiur.Proofs.BranchSelection +import Ix.Aiur.Proofs.OperationRows +import Ix.Aiur.Proofs.CallInventory +import Ix.Aiur.Proofs.BlockRows +import Ix.Aiur.Proofs.BlockRowProjection +import Ix.Aiur.Proofs.BlockRowExecution +import Ix.Aiur.Proofs.BlockRowCalls +import Ix.Aiur.Proofs.BlockRowInputs +import Ix.Aiur.Proofs.FunctionRows +import Ix.Aiur.Proofs.QuerySlots +import Ix.Aiur.Proofs.BlockQuerySlots +import Ix.Aiur.Proofs.QuerySlotMessages +import Ix.Aiur.Proofs.BlockQueryPool +import Ix.Aiur.Proofs.CircuitRows +import Ix.Aiur.Proofs.CircuitRowMembers +import Ix.Aiur.Proofs.CircuitRowQueries +import Ix.Aiur.Proofs.CircuitRowReturns +import Ix.Aiur.Proofs.CircuitRowExecution +import Ix.Aiur.Proofs.RowCounts +import Ix.Aiur.Proofs.CircuitRowCounts +import Ix.Aiur.Proofs.ProviderEquivalence +import Ix.Aiur.Proofs.CircuitTableData +import Ix.Aiur.Proofs.CircuitTableExecution +import Ix.Aiur.Proofs.PublicCircuitExecution +import Ix.Aiur.Proofs.BranchlessSlots +import Ix.Aiur.Proofs.EncodedCircuitExecution +import Ix.Aiur.Proofs.CircuitTraces +import Ix.Aiur.Proofs.CircuitMembership +import Ix.Aiur.Proofs.LookupLayout +import Ix.Aiur.Proofs.MemoryColumns +import Ix.Aiur.Proofs.ByteColumns +import Ix.Aiur.Proofs.ExpressionGraph +import Ix.Aiur.Proofs.FrontendExpressions +import Ix.Aiur.Proofs.GraphCompilation +import Ix.Aiur.Proofs.OperationExpressions +import Ix.Aiur.Proofs.OperationReflection +import Ix.Aiur.Proofs.OperationSequences +import Ix.Aiur.Proofs.LookupExpressions +import Ix.Aiur.Proofs.Metadata +import Ix.Aiur.Proofs.Renaming +import Ix.Aiur.Proofs.Dedup +import Ix.Aiur.Proofs.TailMatches +import Ix.Aiur.Proofs.NormalizationFrames +import Ix.Aiur.Proofs.Compilation +import Ix.Aiur.Proofs.Grouping +import Ix.Aiur.Proofs.Audit + +/-! Audited compiler, grouping and verifier-binding components for Aiur. +These roots do not yet establish full public acceptance-to-model soundness. -/ diff --git a/Ix/Aiur/Proofs/Activity.lean b/Ix/Aiur/Proofs/Activity.lean new file mode 100644 index 000000000..a1d5abdaf --- /dev/null +++ b/Ix/Aiur/Proofs/Activity.lean @@ -0,0 +1,60 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Goldilocks + +/-! Local arithmetic for the function and memory AIR's activity constraint. +The Rust constraint emitter uses `multiplicity * (1 - selector)` on every +function and memory circuit. This theorem rules out a nonzero return/pull +multiplicity on an inactive row. It is not the full AIR/execution reflection +theorem, nor a proof of the Rust field implementation or constraint emitter. +-/ + +namespace Aiur + +theorem G.ofNat_n (a : G) : G.ofNat a.n = a := by + have h : a.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp a.property + simp only [G.ofNat, Nat.mod_eq_of_lt h, Nat.toUInt64, UInt64.ofNat_toNat] + split + · rfl + · contradiction + +theorem G.mul_one (a : G) : a * 1 = a := by + change G.ofNat (a.n * (1 : G).n) = a + have h : (1 : G).n = 1 := rfl + rw [h, Nat.mul_one] + exact G.ofNat_n a + +theorem G.mul_zero (a : G) : a * 0 = 0 := by + change G.ofNat (a.n * (0 : G).n) = 0 + have h : (0 : G).n = 0 := rfl + rw [h, Nat.mul_zero] + rfl + +namespace AIR + +/-- Exact polynomial appended by both the function and memory emitters. -/ +def activityConstraint (multiplicity selector : G) : G := + multiplicity * (1 - selector) + +theorem inactive_multiplicity_zero {multiplicity selector : G} + (inactive : selector = 0) (satisfied : activityConstraint multiplicity selector = 0) : + multiplicity = 0 := by + subst selector + have h : (1 : G) - 0 = 1 := by decide + simpa only [activityConstraint, h, G.mul_one] using satisfied + +theorem nonzero_multiplicity_active {multiplicity selector : G} + (satisfied : activityConstraint multiplicity selector = 0) + (nonzero : multiplicity ≠ 0) : selector ≠ 0 := by + intro inactive + exact nonzero (inactive_multiplicity_zero inactive satisfied) + +theorem active_satisfies (multiplicity : G) : activityConstraint multiplicity 1 = 0 := by + have h : (1 : G) - 1 = 0 := by decide + simp only [activityConstraint, h, G.mul_zero] + +end AIR +end Aiur diff --git a/Ix/Aiur/Proofs/Audit.lean b/Ix/Aiur/Proofs/Audit.lean new file mode 100644 index 000000000..d7c9ebe54 --- /dev/null +++ b/Ix/Aiur/Proofs/Audit.lean @@ -0,0 +1,4033 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean +import Ix.Aiur.BoundVerifier +import Ix.Aiur.Proofs.Activity +import Ix.Aiur.Proofs.CallOrder +import Ix.Aiur.Proofs.Lookup +import Ix.Aiur.Proofs.Execution +import Ix.Aiur.Proofs.Memory +import Ix.Aiur.Proofs.LocalConstraints +import Ix.Aiur.Proofs.ByteLookups +import Ix.Aiur.Proofs.LookupMessages +import Ix.Aiur.Proofs.LookupShapes +import Ix.Aiur.Proofs.GlobalLookups +import Ix.Aiur.Proofs.LookupBudget +import Ix.Aiur.Proofs.ReturnGates +import Ix.Aiur.Proofs.BranchSelection +import Ix.Aiur.Proofs.CallInventory +import Ix.Aiur.Proofs.FunctionRows +import Ix.Aiur.Proofs.BlockQueryPool +import Ix.Aiur.Proofs.CircuitRowExecution +import Ix.Aiur.Proofs.CircuitRowCounts +import Ix.Aiur.Proofs.PublicCircuitExecution +import Ix.Aiur.Proofs.EncodedCircuitExecution +import Ix.Aiur.Proofs.CircuitTraces +import Ix.Aiur.Proofs.CircuitMembership +import Ix.Aiur.Proofs.LookupLayout +import Ix.Aiur.Proofs.MemoryColumns +import Ix.Aiur.Proofs.ByteColumns +import Ix.Aiur.Proofs.ExpressionGraph +import Ix.Aiur.Proofs.FrontendExpressions +import Ix.Aiur.Proofs.GraphCompilation +import Ix.Aiur.Proofs.LookupExpressions +import Ix.Aiur.Proofs.CompiledCircuitRows +import Ix.Aiur.Proofs.BlockAllocation +import Ix.Aiur.Proofs.CircuitAllocation +import Ix.Aiur.Proofs.CircuitCompletion +import Ix.Aiur.Proofs.CheckedCircuit +import Ix.Aiur.Proofs.KeyArtifact +import Ix.Aiur.Proofs.CompiledKey +import Ix.Aiur.Proofs.ShapedVerifier +import Ix.Aiur.Proofs.ExtensionField +import Ix.Aiur.Proofs.LogUpAccumulator +import Ix.Aiur.Proofs.DomainAccumulator +import Ix.Aiur.Proofs.Quotient +import Ix.Aiur.Proofs.VerifierAccumulator +import Ix.Aiur.Proofs.Blake3 +import Ix.Aiur.Proofs.MerkleCap +import Ix.Aiur.Proofs.Merkle +import Ix.Aiur.Proofs.PrunedMerkle +import Ix.Aiur.Proofs.ExtensionMmcs +import Ix.Aiur.Proofs.FriDomain +import Ix.Aiur.Proofs.Polynomial +import Ix.Aiur.Proofs.Interpolation +import Ix.Aiur.Proofs.Folding +import Ix.Aiur.Proofs.FriQuery +import Ix.Aiur.Proofs.Transcript +import Ix.Aiur.Proofs.Grouping +import Ix.Aiur.Proofs.TailMatches +import Ix.Aiur.Proofs.NormalizationFrames + +/-! Exact proof and execution inventory for the implemented C8 components. +The compiler and proof-system runtime are inventoried here; their presence +is not a proof of runtime refinement or public certified semantic soundness. +-/ + +open Lean Lean.Elab Command + +namespace Aiur.Proofs.Audit + +def callOrderRoots : Array Lean.Name := #[ + `Aiur.G.n_ofNat, `Aiur.G.sub_eq_zero_iff, `Aiur.G.n_add, `Aiur.G.n_mul, + `Aiur.AIR.packRank_lt, `Aiur.AIR.call_order_strict, `Aiur.AIR.call_order_irrefl, + `Aiur.AIR.active_call_order_strict, `Aiur.AIR.packed_call_order_strict, + `Aiur.AIR.call_relation_wellFounded] + +def lookupRoots : Array Lean.Name := #[ + `Aiur.G.zero_add, `Aiur.G.ofNat_ne_zero_of_lt, + `Aiur.AIR.characteristic_queries_balance, `Aiur.AIR.suppliedWeight_nonzero_provider, + `Aiur.AIR.exactLookupBalance_provider, `Aiur.AIR.byteRangeMessage_bounded, + `Aiur.AIR.exactLookupBalance_byteRange, `Aiur.AIR.exactLookupBalance_rankBytes, + `Aiur.AIR.exactLookupBalance_call_order] + +def executionRoots : Array Lean.Name := #[ + `Aiur.AIR.FunctionRow.Valid.active_of_nonzero, + `Aiur.AIR.functionQueries_provider, + `Aiur.AIR.balancedRows_execute, + `Aiur.AIR.balancedRoots_execute] + +def memoryRoots : Array Lean.Name := #[ + `Aiur.AIR.MemoryRowsValid.pointer_injective, + `Aiur.AIR.memoryFacts_functional, + `Aiur.AIR.memoryQueries_provider, + `Aiur.AIR.memoryQueries_width, + `Aiur.AIR.memoryQueries_consistent, + `Aiur.AIR.memoryQueries_fact] + +def fieldRoots : Array Lean.Name := #[ + `Aiur.gSize_prime, + `Aiur.G.mul_eq_zero_iff, + `Aiur.G.boolean_of_constraint, + `Aiur.G.boolean_of_one_sub_constraint, + `Aiur.G.eqZero_of_constraints] + +def localConstraintRoots : Array Lean.Name := #[ + `Aiur.AIR.selectorSum_count_le_one, + `Aiur.AIR.selectorSum_inactive, + `Aiur.AIR.selectorSum_active_split, + `Aiur.AIR.selectorSum_characteristic_cancel, + `Aiur.AIR.nonzero_multiplicity_selector_one, + `Aiur.AIR.active_eqZero, + `Aiur.AIR.active_case, + `Aiur.AIR.active_default, + `Aiur.AIR.MemoryRowsPolynomials.valid, + `Aiur.AIR.MemoryRowsPolynomials.functional] + +def byteArithmeticRoots : Array Lean.Name := #[ + `Aiur.AIR.inverse256_correct, + `Aiur.AIR.byte_add_carry, + `Aiur.AIR.byte_sub_borrow, + `Aiur.AIR.byte_carry_relation, + `Aiur.AIR.pack4_n, + `Aiur.AIR.u32Carry_relation, + `Aiur.AIR.u32_less_than, + `Aiur.AIR.active_u32_less_than] + +def byteLookupRoots : Array Lean.Name := #[ + `Aiur.AIR.exactLookupBalance_byte1, + `Aiur.AIR.exactLookupBalance_byte2, + `Aiur.AIR.exactLookupBalance_byte1_step, + `Aiur.AIR.exactLookupBalance_byte2_step, + `Aiur.AIR.active_u32_less_than_step] + +def lookupMessageRoots : Array Lean.Name := #[ + `Aiur.AIR.padMessage_injective_of_shape, + `Aiur.AIR.exactLookupBalance_of_injective_on, + `Aiur.AIR.ExactLookupBalance.filter, + `Aiur.AIR.paddedLookupBalance_provider, + `Aiur.AIR.paddedLookupBalance_exact, + `Aiur.AIR.functionMessage_shape, + `Aiur.AIR.memoryMessage_shape, + `Aiur.AIR.byte1Request_shape, + `Aiur.AIR.byte2Request_shape, + `Aiur.AIR.functionMessage_injective, + `Aiur.AIR.exactLookupBalance_functionMessages, + `Aiur.AIR.memoryMessage_injective, + `Aiur.AIR.exactLookupBalance_memoryMessages, + `Aiur.AIR.padMessage_append_zero, + `Aiur.AIR.functionMessage_rank_alias] + +def lookupShapeRoots : Array Lean.Name := #[ + `Aiur.Bytecode.AIR.RunBlock.return_size, + `Aiur.Bytecode.AIR.RunFunction.return_size, + `Aiur.Bytecode.AIR.Step.calls_lookupShape, + `Aiur.Bytecode.AIR.RunOps.calls_lookupShape, + `Aiur.Bytecode.AIR.RunBlock.calls_lookupShape, + `Aiur.Bytecode.AIR.RunFunction.calls_lookupShape, + `Aiur.BoundVerifier.Backend.air_return_size, + `Aiur.BoundVerifier.Backend.claim_shape] + +def globalLookupRoots : Array Lean.Name := #[ + `Aiur.AIR.padded_functionMessage_reflects, + `Aiur.AIR.GlobalLookups.function_provider, + `Aiur.AIR.GlobalLookups.byte1, + `Aiur.AIR.GlobalLookups.byte2, + `Aiur.AIR.GlobalLookups.memory_fact, + `Aiur.AIR.GlobalLookups.memory_consistent, + `Aiur.AIR.GlobalLookups.byte1_step, + `Aiur.AIR.GlobalLookups.byte2_step, + `Aiur.AIR.GlobalLookups.rank_bytes, + `Aiur.AIR.GlobalLookups.rows_execute, + `Aiur.AIR.GlobalLookups.roots_execute, + `Aiur.BoundVerifier.Backend.root_lookupShape, + `Aiur.BoundVerifier.claim_padding, + `Aiur.BoundVerifier.Backend.global_execution] + +def lookupBudgetRoots : Array Lean.Name := #[ + `Aiur.lookupQueryBound_sound, + `Aiur.lookupQueryBound_consumer_count, + `Aiur.lookupQueryBound_shape, + `Aiur.lookupQueryBound_step_no_overflow, + `Aiur.lookupQueryBound_complete, + `Aiur.lookupSlotSum_bounded, + `Aiur.lookupQueryBound_encodedKey, + `Aiur.AIR.GlobalLookups.of_budget] + +def selectorControlRoots : Array Lean.Name := #[ + `Aiur.AIR.weightedMessage_active, + `Aiur.AIR.weightedMessage_inactive, + `Aiur.AIR.slotMessage_active, + `Aiur.AIR.continuation_merge, + `Aiur.Bytecode.Block.selectorFlow_sound, + `Aiur.Bytecode.Block.selectorFlow_yields_empty, + `Aiur.Bytecode.Block.selectorFlow_active_return, + `Aiur.Bytecode.Block.selectorFlow_provider_return, + `Aiur.AIR.SelectorFlow.Sound.inactive_terminal, + `Aiur.AIR.SelectorFlow.Sound.return_stops_continuation, + `Aiur.AIR.SelectorFlow.Sound.yield_starts_continuation, + `Aiur.Bytecode.Block.returnGates_reflects, + `Aiur.Bytecode.Block.return_message] + +def operationRowRoots : Array Lean.Name := #[ + `Aiur.AIR.emitOp_step, + `Aiur.AIR.emitOps_run, + `Aiur.AIR.emitOp_calls, + `Aiur.AIR.emitOps_calls, + `Aiur.AIR.CallsEmitted.ordered, + `Aiur.AIR.active_array_equality, + `Aiur.Bytecode.Block.selectorFlow_boolean, + `Aiur.Bytecode.MatchPolynomials.active_branch, + `Aiur.Bytecode.MatchPolynomials.active_match, + `Aiur.Bytecode.MatchPolynomials.active_matchContinue] + +def blockRowRoots : Array Lean.Name := #[ + `Aiur.Bytecode.Block.emitRow_projection, + `Aiur.Bytecode.Block.emitRow_selectors, + `Aiur.AIR.mergeEquations_chosen, + `Aiur.Bytecode.branchRows_selected, + `Aiur.Bytecode.Block.emitRow_run, + `Aiur.Bytecode.Block.emitRow_tracks_calls, + `Aiur.Bytecode.Block.emitRow_inputs, + `Aiur.Bytecode.Function.emitRow_run, + `Aiur.Bytecode.Function.emitRow_valid, + `Aiur.AIR.slotMessage_chosen, + `Aiur.Bytecode.Function.emitRow_message] + +def querySlotRoots : Array Lean.Name := #[ + `Aiur.Bytecode.Block.emitRow_equation_querySlots, + `Aiur.AIR.QuerySlots.slot_multiplicity, + `Aiur.AIR.QuerySlots.multiplicity_boolean, + `Aiur.AIR.QuerySlots.active_singleton, + `Aiur.AIR.QuerySlots.slot_message, + `Aiur.AIR.QuerySlots.queries_reflect, + `Aiur.AIR.QuerySlots.padded_balance, + `Aiur.AIR.decodedQueries_length, + `Aiur.Bytecode.Block.emitRow_queried_pool, + `Aiur.Bytecode.Function.emitRow_pool_valid] + +def circuitRowRoots : Array Lean.Name := #[ + `Aiur.AIR.emitMembers_spec, + `Aiur.Bytecode.Circuit.emitRow_spec, + `Aiur.Bytecode.Circuit.emitRow_boolean, + `Aiur.Bytecode.Circuit.emitRow_active_member, + `Aiur.Bytecode.Circuit.emitRow_querySlots, + `Aiur.AIR.circuitEmission_rank_queried, + `Aiur.AIR.MemberEmission.FromProgram.return_count, + `Aiur.AIR.circuitEmission_return_count, + `Aiur.AIR.circuitEmission_return_message, + `Aiur.Bytecode.Circuit.emitRow_valid] + +def rowCountRoots : Array Lean.Name := #[ + `Aiur.Bytecode.Ctrl.controlCounts_spec, + `Aiur.Bytecode.Block.controlCounts_spec, + `Aiur.Bytecode.Block.rowBounds_of_controlCounts, + `Aiur.Bytecode.Block.return_bound_of_controlCounts, + `Aiur.Bytecode.Block.returns_le_selectors, + `Aiur.Bytecode.Toplevel.validateRowCounts_circuit, + `Aiur.Bytecode.Circuit.validateRowCounts_spec, + `Aiur.Bytecode.Circuit.emitRow_count_bounds, + `Aiur.Bytecode.Circuit.emitRow_valid_checked, + `Aiur.BoundVerifier.Backend.circuit_row_counts] + +def circuitTableRoots : Array Lean.Name := #[ + `Aiur.Bytecode.Circuit.emitRow_valid_in_pool, + `Aiur.AIR.suppliedWeight_padded_congr, + `Aiur.AIR.PaddedLookupBalance.congr_providers, + `Aiur.Bytecode.Circuit.emitRow_provider, + `Aiur.AIR.AuxiliaryTables.global_of_circuit_balance, + `Aiur.AIR.FunctionRow.inactive_valid, + `Aiur.AIR.CircuitWitness.provider_row, + `Aiur.AIR.CircuitWitness.interpreted_row, + `Aiur.AIR.circuitWitnesses_interpret, + `Aiur.AIR.circuitWitnesses_execute, + `Aiur.AIR.PaddedLookupBalance.congr_queries, + `Aiur.BoundVerifier.Backend.public_circuit_execution] + +def branchlessRoots : Array Lean.Name := #[ + `Aiur.AIR.QueryWriters.single, + `Aiur.Bytecode.Function.emitRow_terminal_writers, + `Aiur.AIR.circuitEmission_queryWriters, + `Aiur.Bytecode.Circuit.emitRow_queryWriters, + `Aiur.Bytecode.Circuit.emitRow_queries_reflect, + `Aiur.AIR.slotMessage_member_length, + `Aiur.AIR.QuerySlots.decoded_widths, + `Aiur.AIR.circuitWitnesses_queries_reflect, + `Aiur.AIR.circuitWitnesses_decoded_widths, + `Aiur.BoundVerifier.Backend.encoded_circuit_execution] + +def circuitTraceRoots : Array Lean.Name := #[ + `Aiur.AIR.CircuitTraces.slot_sum_append, + `Aiur.AIR.CircuitTraces.capacity_bounded, + `Aiur.AIR.emitCircuitWitness_spec, + `Aiur.AIR.encodedQueries_length, + `Aiur.AIR.encodedCircuitQueryPool_uniform_bound, + `Aiur.AIR.emitCircuitWitnesses_spec, + `Aiur.AIR.CircuitTraces.emitWitnesses_spec, + `Aiur.BoundVerifier.Backend.trace_circuit_execution] + +def circuitMembershipRoots : Array Lean.Name := #[ + `Aiur.Bytecode.singletonCircuits_constrained, + `Aiur.CompiledToplevel.groupFunctions_constrained, + `Aiur.finishCompilation_circuits_constrained, + `Aiur.Source.Toplevel.compile_circuits_constrained, + `Aiur.BoundVerifier.Backend.circuits_constrained, + `Aiur.Bytecode.Toplevel.validateLookupShapes_function, + `Aiur.AIR.CircuitWitness.shapes_of_compiled, + `Aiur.BoundVerifier.Backend.witness_shapes, + `Aiur.BoundVerifier.Backend.compiled_trace_execution] + +def lookupLayoutRoots : Array Lean.Name := #[ + `Aiur.Concrete.Bytecode.opLayout_lookupUsage, + `Aiur.Concrete.Bytecode.opsLayout_lookupUsage, + `Aiur.AIR.emitOp_lookupUsage, + `Aiur.AIR.emitOps_lookupUsage, + `Aiur.Bytecode.branchRows_lookupUsage, + `Aiur.Bytecode.Ctrl.emitRow_lookupUsage, + `Aiur.Bytecode.Block.emitRow_lookupUsage, + `Aiur.Concrete.Bytecode.ctrlLayout_lookupUsage, + `Aiur.Concrete.Bytecode.blockLayout_lookupUsage, + `Aiur.Concrete.Function.compile_lookupLayout, + `Aiur.Concrete.Decls.toBytecode_lookupLayout, + `Aiur.Bytecode.rewriteCtrl_lookupUsage, + `Aiur.Bytecode.rewriteBlock_lookupUsage, + `Aiur.Bytecode.Toplevel.deduplicate_lookupLayout, + `Aiur.finishCompilation_lookupLayout, + `Aiur.Source.Toplevel.compile_lookupLayout, + `Aiur.BoundVerifier.Backend.functions_lookupLayout, + `Aiur.Bytecode.singletonCircuits_lookupBound, + `Aiur.Bytecode.merged_lookupBound, + `Aiur.CompiledToplevel.groupFunctions_lookupBound, + `Aiur.finishCompilation_lookupBound, + `Aiur.Source.Toplevel.compile_lookupBound, + `Aiur.BoundVerifier.Backend.circuits_lookupBound, + `Aiur.AIR.CircuitWitness.lookupBounds_of_compiled, + `Aiur.BoundVerifier.Backend.witness_lookupBounds, + `Aiur.BoundVerifier.Backend.bounded_trace_execution] + +def memoryColumnRoots : Array Lean.Name := #[ + `Aiur.AIR.decodeMemoryRow_width, + `Aiur.AIR.decodeMemoryRows_size, + `Aiur.AIR.memoryColumnProvider_reflect, + `Aiur.AIR.decodeMemoryRows_polynomials, + `Aiur.AIR.decodeMemoryRows_valid, + `Aiur.AIR.decodeMemoryRows_providers, + `Aiur.AIR.memoryMatrixProviders_reflect, + `Aiur.Concrete.Decls.toBytecode_memorySizes_distinct, + `Aiur.Bytecode.Toplevel.deduplicate_memorySizes, + `Aiur.finishCompilation_memorySizes, + `Aiur.Source.Toplevel.compile_memorySizes_distinct, + `Aiur.BoundVerifier.Backend.memorySizes_distinct, + `Aiur.BoundVerifier.Backend.memorySizes_canonical, + `Aiur.AIR.MemoryTraces.slot_sum_append, + `Aiur.AIR.MemoryTraces.rows_valid, + `Aiur.AIR.MemoryTraces.rows_size_le, + `Aiur.AIR.MemoryTraces.providers_reflect, + `Aiur.AIR.MemoryTraces.capacity_bounded, + `Aiur.AIR.MemoryTraces.functional, + `Aiur.AIR.MemoryTraces.functional_of_budget, + `Aiur.AIR.MemoryTraces.circuitProviders_reflect, + `Aiur.BoundVerifier.Backend.memory_trace_execution] + +def byteColumnRoots : Array Lean.Name := #[ + `Aiur.fixedTraceHeights_sound, + `Aiur.fixedTraceHeights_complete, + `Aiur.FixedTraceHeights.alignment, + `Aiur.fixedTraceHeights_bytes, + `Aiur.AIR.byte1ColumnProvider_reflect, + `Aiur.AIR.byte2ColumnProvider_reflect, + `Aiur.AIR.CircuitTraces.fixed_heights_append, + `Aiur.AIR.MemoryTraces.fixed_heights_append, + `Aiur.AIR.canonical_byte_metadata, + `Aiur.AIR.suppliedWeight_perm, + `Aiur.AIR.PaddedLookupBalance.perm_providers, + `Aiur.AIR.flatMap_map_swap, + `Aiur.AIR.byte1MatrixProviders_reflect, + `Aiur.AIR.byte2MatrixProviders_reflect, + `Aiur.AIR.ByteTraces.providers_reflect, + `Aiur.AIR.SystemTraces.fixed_heights, + `Aiur.AIR.SystemTraces.memory_functional, + `Aiur.BoundVerifier.Backend.column_trace_execution] + +def expressionGraphRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Node.check_iff, + `Aiur.NativeAIR.checkNodes_iff, + `Aiur.NativeAIR.checkedGraphPrefix_iff, + `Aiur.NativeAIR.roots_below_prefix, + `Aiur.NativeAIR.prefix_bounded, + `Aiur.NativeAIR.Graph.Valid.prefix_bounded, + `Aiur.NativeAIR.Node.eval_defined, + `Aiur.NativeAIR.sweepFrom_defined, + `Aiur.NativeAIR.Graph.Valid.sweep_defined, + `Aiur.NativeAIR.ValidNodes.take, + `Aiur.NativeAIR.Node.eval_withoutStage2, + `Aiur.NativeAIR.sweepFrom_withoutStage2, + `Aiur.NativeAIR.sweepFrom_append, + `Aiur.NativeAIR.sweepFrom_preserves, + `Aiur.NativeAIR.Graph.Valid.lookup_sweep_defined, + `Aiur.NativeAIR.Graph.Valid.lookup_sweep_agrees, + `Aiur.NativeAIR.Node.unfold_eval, + `Aiur.NativeAIR.Reflects.push, + `Aiur.NativeAIR.Node.unfold_defined, + `Aiur.NativeAIR.unfoldFrom_defined, + `Aiur.NativeAIR.unfoldFrom_reflects, + `Aiur.NativeAIR.Graph.Valid.unfold_defined, + `Aiur.NativeAIR.Graph.sweep_reflects, + `Aiur.NativeAIR.Reflects.readNodes, + `Aiur.NativeAIR.Reflects.readLookup, + `Aiur.NativeAIR.readNodes_congr, + `Aiur.NativeAIR.readNodes_defined, + `Aiur.NativeAIR.readLookup_defined, + `Aiur.NativeAIR.Graph.Valid.lookup_values_agree, + `Aiur.NativeAIR.Graph.Valid.lookup_values_reflect] + +def graphAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.ValidNodes.take, + `Aiur.NativeAIR.sweepFrom_append] + +def graphPropextRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Node.check_iff, + `Aiur.NativeAIR.checkNodes_iff, + `Aiur.NativeAIR.roots_below_prefix, + `Aiur.NativeAIR.prefix_bounded, + `Aiur.NativeAIR.Graph.Valid.prefix_bounded, + `Aiur.NativeAIR.Node.eval_withoutStage2] + +def graphClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Reflects.push, + `Aiur.NativeAIR.unfoldFrom_reflects, + `Aiur.NativeAIR.Graph.sweep_reflects, + `Aiur.NativeAIR.Graph.Valid.lookup_values_reflect] + +def frontendExpressionRoots : Array Lean.Name := #[ + `Aiur.G.sub_zero, + `Aiur.G.neg_neg, + `Aiur.NativeAIR.Expr.isConstant_eq, + `Aiur.NativeAIR.Expr.frontNeg_noConstantNegs, + `Aiur.NativeAIR.Expr.frontNeg_isConstant, + `Aiur.NativeAIR.Expr.frontAdd_isConstant, + `Aiur.NativeAIR.Expr.frontSub_isConstant, + `Aiur.NativeAIR.Expr.frontAdd_noConstantNegs, + `Aiur.NativeAIR.Expr.frontSub_noConstantNegs, + `Aiur.NativeAIR.Expr.frontMul_noConstantNegs, + `Aiur.NativeAIR.Expr.frontNeg_eval, + `Aiur.NativeAIR.Expr.eval_constantValue, + `Aiur.NativeAIR.Expr.frontAdd_eval, + `Aiur.NativeAIR.Expr.frontSub_eval, + `Aiur.NativeAIR.Expr.frontMul_eval, + `Aiur.NativeAIR.goldilocks_add_zero, + `Aiur.NativeAIR.goldilocks_zero_add, + `Aiur.NativeAIR.goldilocks_sub_zero, + `Aiur.NativeAIR.goldilocks_zero_sub, + `Aiur.NativeAIR.goldilocks_mul_zero, + `Aiur.NativeAIR.goldilocks_zero_mul, + `Aiur.NativeAIR.goldilocks_mul_one, + `Aiur.NativeAIR.goldilocks_one_mul, + `Aiur.NativeAIR.goldilocks_neg_neg, + `Aiur.NativeAIR.goldilocks_konst_add, + `Aiur.NativeAIR.goldilocks_konst, + `Aiur.NativeAIR.goldilocks_add, + `Aiur.NativeAIR.goldilocks_sub, + `Aiur.NativeAIR.goldilocks_mul, + `Aiur.NativeAIR.goldilocks_konst_sub, + `Aiur.NativeAIR.goldilocks_konst_mul, + `Aiur.NativeAIR.goldilocks_konst_neg, + `Aiur.NativeAIR.goldilocksLaws, + `Aiur.NativeAIR.Expr.constantValue_eq_of_eval, + `Aiur.NativeAIR.Expr.frontMul_isConstant, + `Aiur.NativeAIR.RowExpr.reflects_iff_eval, + `Aiur.NativeAIR.RowExpr.konst_reflects, + `Aiur.NativeAIR.RowExpr.variable_reflects, + `Aiur.NativeAIR.RowExpr.add_reflects, + `Aiur.NativeAIR.RowExpr.sub_reflects, + `Aiur.NativeAIR.RowExpr.mul_reflects, + `Aiur.NativeAIR.ScalarEmission.eval_of, + `Aiur.NativeAIR.eqZeroRegular_reflects, + `Aiur.NativeAIR.emitEqZero_reflects, + `Aiur.NativeAIR.mulRegular_reflects, + `Aiur.NativeAIR.emitMul_reflects, + `Aiur.NativeAIR.emitEqZero_noConstantNegs, + `Aiur.NativeAIR.emitMul_noConstantNegs, + `Aiur.NativeAIR.emitAdd_reflects, + `Aiur.NativeAIR.emitSub_reflects] + +def frontendQuotRoots : Array Lean.Name := #[ + `Aiur.G.neg_neg, + `Aiur.NativeAIR.goldilocks_neg_neg, + `Aiur.NativeAIR.goldilocksLaws, + `Aiur.NativeAIR.RowExpr.add_reflects, + `Aiur.NativeAIR.RowExpr.sub_reflects, + `Aiur.NativeAIR.ScalarEmission.eval_of, + `Aiur.NativeAIR.eqZeroRegular_reflects, + `Aiur.NativeAIR.mulRegular_reflects, + `Aiur.NativeAIR.emitAdd_reflects, + `Aiur.NativeAIR.emitSub_reflects] + +def frontendClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Expr.frontMul_isConstant, + `Aiur.NativeAIR.RowExpr.mul_reflects, + `Aiur.NativeAIR.emitEqZero_reflects, + `Aiur.NativeAIR.emitMul_reflects] + +def frontendExpressionPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.Expr.isConstant, + `Aiur.NativeAIR.Expr.constantValue, + `Aiur.NativeAIR.Expr.frontNeg, + `Aiur.NativeAIR.Expr.frontAdd, + `Aiur.NativeAIR.Expr.frontSub, + `Aiur.NativeAIR.Expr.frontMul, + `Aiur.NativeAIR.EvalLaws.mk, + `Aiur.NativeAIR.Expr.noConstantNegs, + `Aiur.NativeAIR.RowExpr.mk, + `Aiur.NativeAIR.RowExpr.konst, + `Aiur.NativeAIR.RowExpr.variable, + `Aiur.NativeAIR.RowExpr.add, + `Aiur.NativeAIR.RowExpr.sub, + `Aiur.NativeAIR.RowExpr.mul, + `Aiur.NativeAIR.RowExpr.eval, + `Aiur.NativeAIR.RowExpr.Reflects, + `Aiur.NativeAIR.ScalarEmission.mk, + `Aiur.NativeAIR.ScalarEmission.eval, + `Aiur.NativeAIR.mainCurrent, + `Aiur.NativeAIR.eqZeroRegular, + `Aiur.NativeAIR.emitEqZero, + `Aiur.NativeAIR.mulRegular, + `Aiur.NativeAIR.emitMul] + +def graphCompilationRoots : Array Lean.Name := #[ + `Aiur.G.sub_self, + `Aiur.NativeAIR.goldilocksGraphLaws, + `Aiur.NativeAIR.Compiler.Extends.refl, + `Aiur.NativeAIR.Compiler.Extends.trans, + `Aiur.NativeAIR.Compiler.Extends.push, + `Aiur.NativeAIR.Compiler.eval_extends, + `Aiur.NativeAIR.Compiler.Evaluation.empty, + `Aiur.NativeAIR.Compiler.Evaluation.push, + `Aiur.NativeAIR.Compiler.result_same, + `Aiur.NativeAIR.Compiler.intern_reflects, + `Aiur.NativeAIR.Compiler.asConst_reflects, + `Aiur.NativeAIR.Compiler.asConst_value, + `Aiur.NativeAIR.Compiler.konst_reflects, + `Aiur.NativeAIR.Compiler.neg_reflects, + `Aiur.NativeAIR.Compiler.sortedAdd_reflects, + `Aiur.NativeAIR.Compiler.sortedMul_reflects, + `Aiur.NativeAIR.Compiler.add_reflects, + `Aiur.NativeAIR.Compiler.sub_reflects, + `Aiur.NativeAIR.Compiler.mul_reflects, + `Aiur.NativeAIR.Compiler.result_prepend, + `Aiur.NativeAIR.Compiler.compileExpr_reflects, + `Aiur.NativeAIR.Compiler.compileExpr_sweep, + `Aiur.NativeAIR.Compiler.RootsReflect.grow, + `Aiur.NativeAIR.Compiler.compileExprs_reflects, + `Aiur.NativeAIR.Compiler.RootsReflect.read, + `Aiur.NativeAIR.Compiler.compileLookup_reflects, + `Aiur.NativeAIR.Compiler.RootsReflect.readLookup, + `Aiur.NativeAIR.Compiler.LookupsReflect.grow, + `Aiur.NativeAIR.Compiler.compileLookups_reflects, + `Aiur.NativeAIR.Compiler.recordZero_reflects, + `Aiur.NativeAIR.Compiler.Vanishes.append, + `Aiur.NativeAIR.Compiler.ExprsVanish.cons, + `Aiur.NativeAIR.Compiler.compileZeros_reflects, + `Aiur.NativeAIR.Compiler.canonicalZeros_vanish, + `Aiur.NativeAIR.Compiler.compileBase_reflects, + `Aiur.NativeAIR.Compiler.LookupsReflect.read, + `Aiur.NativeAIR.Compiler.compileBase_satisfaction] + +def graphCompilationAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Compiler.Extends.refl, + `Aiur.NativeAIR.Compiler.Extends.trans, + `Aiur.NativeAIR.Compiler.RootsReflect.grow, + `Aiur.NativeAIR.Compiler.LookupsReflect.grow] + +def graphCompilationQuotRoots : Array Lean.Name := #[ + `Aiur.G.sub_self, + `Aiur.NativeAIR.goldilocksGraphLaws, + `Aiur.NativeAIR.Compiler.eval_extends, + `Aiur.NativeAIR.Compiler.Evaluation.push, + `Aiur.NativeAIR.Compiler.RootsReflect.read, + `Aiur.NativeAIR.Compiler.RootsReflect.readLookup, + `Aiur.NativeAIR.Compiler.recordZero_reflects, + `Aiur.NativeAIR.Compiler.Vanishes.append, + `Aiur.NativeAIR.Compiler.canonicalZeros_vanish, + `Aiur.NativeAIR.Compiler.LookupsReflect.read] + +def graphCompilationClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Compiler.intern_reflects, + `Aiur.NativeAIR.Compiler.konst_reflects, + `Aiur.NativeAIR.Compiler.neg_reflects, + `Aiur.NativeAIR.Compiler.sortedAdd_reflects, + `Aiur.NativeAIR.Compiler.sortedMul_reflects, + `Aiur.NativeAIR.Compiler.add_reflects, + `Aiur.NativeAIR.Compiler.sub_reflects, + `Aiur.NativeAIR.Compiler.mul_reflects, + `Aiur.NativeAIR.Compiler.compileExpr_reflects, + `Aiur.NativeAIR.Compiler.compileExpr_sweep, + `Aiur.NativeAIR.Compiler.compileExprs_reflects, + `Aiur.NativeAIR.Compiler.compileLookup_reflects, + `Aiur.NativeAIR.Compiler.compileLookups_reflects, + `Aiur.NativeAIR.Compiler.compileZeros_reflects, + `Aiur.NativeAIR.Compiler.compileBase_reflects, + `Aiur.NativeAIR.Compiler.compileBase_satisfaction] + +def graphCompilationPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.GraphEvalLaws.mk, + `Aiur.NativeAIR.Compiler.Extends, + `Aiur.NativeAIR.Compiler.Evaluation.mk, + `Aiur.NativeAIR.Compiler.intern, + `Aiur.NativeAIR.Compiler.asConst, + `Aiur.NativeAIR.Compiler.Result, + `Aiur.NativeAIR.Compiler.neg, + `Aiur.NativeAIR.Compiler.sortedAdd, + `Aiur.NativeAIR.Compiler.sortedMul, + `Aiur.NativeAIR.Compiler.add, + `Aiur.NativeAIR.Compiler.sub, + `Aiur.NativeAIR.Compiler.mul, + `Aiur.NativeAIR.Compiler.compileExpr, + `Aiur.NativeAIR.Compiler.compileExprs, + `Aiur.NativeAIR.Compiler.RootsReflect.nil, + `Aiur.NativeAIR.Compiler.RootsReflect.cons, + `Aiur.NativeAIR.Compiler.evalExprs, + `Aiur.NativeAIR.Compiler.ExprLookup.mk, + `Aiur.NativeAIR.Compiler.ExprLookup.exprs, + `Aiur.NativeAIR.Compiler.ExprLookup.eval, + `Aiur.NativeAIR.Compiler.compileLookup, + `Aiur.NativeAIR.Compiler.compileLookups, + `Aiur.NativeAIR.Compiler.LookupsReflect.nil, + `Aiur.NativeAIR.Compiler.LookupsReflect.cons, + `Aiur.NativeAIR.Compiler.recordZero, + `Aiur.NativeAIR.Compiler.Vanishes, + `Aiur.NativeAIR.Compiler.ExprsVanish, + `Aiur.NativeAIR.Compiler.compileZeros, + `Aiur.NativeAIR.Compiler.canonicalZeros, + `Aiur.NativeAIR.Compiler.BaseCompilation.mk, + `Aiur.NativeAIR.Compiler.compileBase] + +def operationExpressionRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.OpEmitter.list_mapM_read, + `Aiur.NativeAIR.OpEmitter.array_mapM_read, + `Aiur.NativeAIR.OpEmitter.array_mapM_size, + `Aiur.NativeAIR.OpEmitter.array_mapM_push, + `Aiur.NativeAIR.OpEmitter.list_mapM_of_map, + `Aiur.NativeAIR.OpEmitter.array_mapM_ofFn, + `Aiur.NativeAIR.OpEmitter.list_mapM_ofFn, + `Aiur.NativeAIR.OpEmitter.list_mapM_transform, + `Aiur.NativeAIR.OpEmitter.array_mapM_transform, + `Aiur.NativeAIR.OpEmitter.list_mapM_refine, + `Aiur.NativeAIR.OpEmitter.array_mapM_refine, + `Aiur.NativeAIR.OpEmitter.evalRows_empty, + `Aiur.NativeAIR.OpEmitter.evalRows_singleton, + `Aiur.NativeAIR.OpEmitter.evalRows_values, + `Aiur.NativeAIR.OpEmitter.evalRows_read, + `Aiur.NativeAIR.OpEmitter.select_reflects, + `Aiur.NativeAIR.OpEmitter.select_values, + `Aiur.NativeAIR.OpEmitter.select_normal, + `Aiur.NativeAIR.OpEmitter.array_ofFn_getD, + `Aiur.NativeAIR.OpEmitter.array_map_getD_of_mapM, + `Aiur.NativeAIR.OpEmitter.evalRows_getD, + `Aiur.NativeAIR.OpEmitter.advice_eval, + `Aiur.NativeAIR.OpEmitter.advice_normal, + `Aiur.NativeAIR.OpEmitter.CallExpr.eval_of, + `Aiur.NativeAIR.OpEmitter.emitAdvice_reflects, + `Aiur.NativeAIR.OpEmitter.Emission.eval_of, + `Aiur.NativeAIR.OpEmitter.emitByte1_reflects, + `Aiur.NativeAIR.OpEmitter.scale_isConstant, + `Aiur.NativeAIR.OpEmitter.byteCarry_reflects, + `Aiur.NativeAIR.OpEmitter.byteCarry_normal, + `Aiur.NativeAIR.OpEmitter.emitByte2_reflects, + `Aiur.NativeAIR.OpEmitter.emitByte2_normal, + `Aiur.NativeAIR.OpEmitter.scale_reflects, + `Aiur.NativeAIR.OpEmitter.list_ofFn_four, + `Aiur.NativeAIR.OpEmitter.list_foldl_zip_four, + `Aiur.NativeAIR.OpEmitter.packFour_reflects, + `Aiur.NativeAIR.OpEmitter.packFour_normal, + `Aiur.NativeAIR.OpEmitter.readWord_reflects, + `Aiur.NativeAIR.OpEmitter.readWord_normal, + `Aiur.NativeAIR.OpEmitter.packedAdvice_reflects, + `Aiur.NativeAIR.OpEmitter.packedAdvice_normal, + `Aiur.NativeAIR.OpEmitter.packed_advice_not_constant, + `Aiur.NativeAIR.OpEmitter.emitWordSum_reflects, + `Aiur.NativeAIR.OpEmitter.emitWordSum_normal, + `Aiur.NativeAIR.OpEmitter.packed_advice_value, + `Aiur.NativeAIR.OpEmitter.carryStep_eval, + `Aiur.NativeAIR.OpEmitter.carryStep_normal, + `Aiur.NativeAIR.OpEmitter.carryStep_not_constant, + `Aiur.NativeAIR.OpEmitter.carries_eval, + `Aiur.NativeAIR.OpEmitter.carries_normal, + `Aiur.NativeAIR.OpEmitter.packSix_eval, + `Aiur.NativeAIR.OpEmitter.rangePair_eval, + `Aiur.NativeAIR.OpEmitter.rangeSix_eval, + `Aiur.NativeAIR.OpEmitter.emitCall_reflects, + `Aiur.NativeAIR.OpEmitter.emitStore_reflects, + `Aiur.NativeAIR.OpEmitter.emitLoad_reflects, + `Aiur.NativeAIR.OpEmitter.rangeFour_eval, + `Aiur.NativeAIR.OpEmitter.booleanExpr_eval, + `Aiur.NativeAIR.OpEmitter.emitU32LessThan_reflects, + `Aiur.NativeAIR.OpEmitter.emitU32LessThan_normal, + `Aiur.NativeAIR.OpEmitter.rowValues_getD, + `Aiur.NativeAIR.OpEmitter.emitAssert_reflects, + `Aiur.NativeAIR.OpEmitter.fromScalar_eval, + `Aiur.NativeAIR.OpEmitter.empty_eval, + `Aiur.NativeAIR.OpEmitter.normal_empty, + `Aiur.NativeAIR.OpEmitter.normal_singleton, + `Aiur.NativeAIR.OpEmitter.Normal.read, + `Aiur.NativeAIR.OpEmitter.emitOp_byte1, + `Aiur.NativeAIR.OpEmitter.emitOp_byte2, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch, + `Aiur.NativeAIR.OpEmitter.list_ofFn_getD_pair, + `Aiur.NativeAIR.OpEmitter.emitOp_reflects, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_normal, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_normal, + `Aiur.NativeAIR.OpEmitter.emitOp_normal, + `Aiur.NativeAIR.OpEmitter.evalRows_append, + `Aiur.NativeAIR.OpEmitter.Normal.append, + `Aiur.NativeAIR.OpEmitter.Emission.eval_components, + `Aiur.NativeAIR.OpEmitter.OpsEmission.eval_of, + `Aiur.NativeAIR.OpEmitter.OpsEmission.eval_components, + `Aiur.NativeAIR.OpEmitter.emitOps_column, + `Aiur.NativeAIR.OpEmitter.emitOps_normal, + `Aiur.NativeAIR.OpEmitter.emitOps_reflects, + `Aiur.NativeAIR.LookupEmitter.addArgs_eval, + `Aiur.NativeAIR.LookupEmitter.gateArgs_eval, + `Aiur.NativeAIR.LookupEmitter.QueryExpr.eval_components, + `Aiur.NativeAIR.LookupEmitter.queryParts_cons, + `Aiur.NativeAIR.LookupEmitter.queryParts_eval, + `Aiur.NativeAIR.LookupEmitter.accumulate_eval, + `Aiur.NativeAIR.LookupEmitter.fold_eval, + `Aiur.NativeAIR.LookupEmitter.filter_eval, + `Aiur.NativeAIR.LookupEmitter.valuedFold_eq, + `Aiur.NativeAIR.LookupEmitter.slot_eval, + `Aiur.NativeAIR.LookupEmitter.slots_eval] + +def operationExpressionQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.OpEmitter.list_mapM_read, + `Aiur.NativeAIR.OpEmitter.array_mapM_read, + `Aiur.NativeAIR.OpEmitter.array_mapM_size, + `Aiur.NativeAIR.OpEmitter.array_mapM_push, + `Aiur.NativeAIR.OpEmitter.list_mapM_of_map, + `Aiur.NativeAIR.OpEmitter.list_mapM_ofFn, + `Aiur.NativeAIR.OpEmitter.list_mapM_transform, + `Aiur.NativeAIR.OpEmitter.array_mapM_transform, + `Aiur.NativeAIR.OpEmitter.list_mapM_refine, + `Aiur.NativeAIR.OpEmitter.array_mapM_refine, + `Aiur.NativeAIR.OpEmitter.evalRows_empty, + `Aiur.NativeAIR.OpEmitter.evalRows_singleton, + `Aiur.NativeAIR.OpEmitter.evalRows_values, + `Aiur.NativeAIR.OpEmitter.select_values, + `Aiur.NativeAIR.OpEmitter.select_normal, + `Aiur.NativeAIR.OpEmitter.array_map_getD_of_mapM, + `Aiur.NativeAIR.OpEmitter.Emission.eval_of, + `Aiur.NativeAIR.OpEmitter.byteCarry_reflects, + `Aiur.NativeAIR.OpEmitter.scale_reflects, + `Aiur.NativeAIR.OpEmitter.list_ofFn_four, + `Aiur.NativeAIR.OpEmitter.list_foldl_zip_four, + `Aiur.NativeAIR.OpEmitter.carryStep_eval, + `Aiur.NativeAIR.OpEmitter.carries_eval, + `Aiur.NativeAIR.OpEmitter.carries_normal, + `Aiur.NativeAIR.OpEmitter.packSix_eval, + `Aiur.NativeAIR.OpEmitter.rangePair_eval, + `Aiur.NativeAIR.OpEmitter.rangeSix_eval, + `Aiur.NativeAIR.OpEmitter.rangeFour_eval, + `Aiur.NativeAIR.OpEmitter.booleanExpr_eval, + `Aiur.NativeAIR.OpEmitter.emitU32LessThan_normal, + `Aiur.NativeAIR.OpEmitter.rowValues_getD, + `Aiur.NativeAIR.OpEmitter.fromScalar_eval, + `Aiur.NativeAIR.OpEmitter.empty_eval, + `Aiur.NativeAIR.OpEmitter.list_ofFn_getD_pair, + `Aiur.NativeAIR.OpEmitter.evalRows_append, + `Aiur.NativeAIR.OpEmitter.Normal.append, + `Aiur.NativeAIR.OpEmitter.OpsEmission.eval_of, + `Aiur.NativeAIR.LookupEmitter.addArgs_eval, + `Aiur.NativeAIR.LookupEmitter.gateArgs_eval, + `Aiur.NativeAIR.LookupEmitter.accumulate_eval, + `Aiur.NativeAIR.LookupEmitter.fold_eval, + `Aiur.NativeAIR.LookupEmitter.filter_eval, + `Aiur.NativeAIR.LookupEmitter.slot_eval, + `Aiur.NativeAIR.LookupEmitter.slots_eval] + +def operationExpressionClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.OpEmitter.array_mapM_ofFn, + `Aiur.NativeAIR.OpEmitter.evalRows_read, + `Aiur.NativeAIR.OpEmitter.select_reflects, + `Aiur.NativeAIR.OpEmitter.array_ofFn_getD, + `Aiur.NativeAIR.OpEmitter.evalRows_getD, + `Aiur.NativeAIR.OpEmitter.advice_eval, + `Aiur.NativeAIR.OpEmitter.advice_normal, + `Aiur.NativeAIR.OpEmitter.CallExpr.eval_of, + `Aiur.NativeAIR.OpEmitter.emitAdvice_reflects, + `Aiur.NativeAIR.OpEmitter.emitByte1_reflects, + `Aiur.NativeAIR.OpEmitter.emitByte2_reflects, + `Aiur.NativeAIR.OpEmitter.emitByte2_normal, + `Aiur.NativeAIR.OpEmitter.packFour_reflects, + `Aiur.NativeAIR.OpEmitter.readWord_reflects, + `Aiur.NativeAIR.OpEmitter.readWord_normal, + `Aiur.NativeAIR.OpEmitter.packedAdvice_reflects, + `Aiur.NativeAIR.OpEmitter.packed_advice_not_constant, + `Aiur.NativeAIR.OpEmitter.emitWordSum_reflects, + `Aiur.NativeAIR.OpEmitter.emitWordSum_normal, + `Aiur.NativeAIR.OpEmitter.packed_advice_value, + `Aiur.NativeAIR.OpEmitter.emitCall_reflects, + `Aiur.NativeAIR.OpEmitter.emitStore_reflects, + `Aiur.NativeAIR.OpEmitter.emitLoad_reflects, + `Aiur.NativeAIR.OpEmitter.emitU32LessThan_reflects, + `Aiur.NativeAIR.OpEmitter.emitAssert_reflects, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch, + `Aiur.NativeAIR.OpEmitter.emitOp_reflects, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_normal, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_normal, + `Aiur.NativeAIR.OpEmitter.emitOp_normal, + `Aiur.NativeAIR.OpEmitter.emitOps_normal, + `Aiur.NativeAIR.OpEmitter.emitOps_reflects, + `Aiur.NativeAIR.LookupEmitter.queryParts_cons, + `Aiur.NativeAIR.LookupEmitter.queryParts_eval] + +def operationExpressionPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.OpEmitter.evalExpr, + `Aiur.NativeAIR.OpEmitter.evalRows, + `Aiur.NativeAIR.OpEmitter.rowExprs, + `Aiur.NativeAIR.OpEmitter.Normal, + `Aiur.NativeAIR.OpEmitter.select, + `Aiur.NativeAIR.OpEmitter.advice, + `Aiur.NativeAIR.OpEmitter.CallExpr.mk, + `Aiur.NativeAIR.OpEmitter.CallExpr.eval, + `Aiur.NativeAIR.OpEmitter.Emission.mk, + `Aiur.NativeAIR.OpEmitter.Emission.eval, + `Aiur.NativeAIR.OpEmitter.fromScalar, + `Aiur.NativeAIR.OpEmitter.emitAdvice, + `Aiur.NativeAIR.OpEmitter.emitByte1, + `Aiur.NativeAIR.OpEmitter.byteCarry, + `Aiur.NativeAIR.OpEmitter.emitByte2, + `Aiur.NativeAIR.OpEmitter.packFour, + `Aiur.NativeAIR.OpEmitter.readWord, + `Aiur.NativeAIR.OpEmitter.packedAdvice, + `Aiur.NativeAIR.OpEmitter.emitWordSum, + `Aiur.NativeAIR.OpEmitter.carryStep, + `Aiur.NativeAIR.OpEmitter.carries, + `Aiur.NativeAIR.OpEmitter.packSix, + `Aiur.NativeAIR.OpEmitter.rangePair, + `Aiur.NativeAIR.OpEmitter.rangeSix, + `Aiur.NativeAIR.OpEmitter.emitCall, + `Aiur.NativeAIR.OpEmitter.emitStore, + `Aiur.NativeAIR.OpEmitter.emitLoad, + `Aiur.NativeAIR.OpEmitter.rangeFour, + `Aiur.NativeAIR.OpEmitter.booleanExpr, + `Aiur.NativeAIR.OpEmitter.emitU32LessThan, + `Aiur.NativeAIR.OpEmitter.emitAssert, + `Aiur.NativeAIR.OpEmitter.emitOp, + `Aiur.NativeAIR.OpEmitter.OpsEmission.mk, + `Aiur.NativeAIR.OpEmitter.OpsEmission.eval, + `Aiur.NativeAIR.OpEmitter.emitOps, + `Aiur.NativeAIR.LookupEmitter.addArgs, + `Aiur.NativeAIR.LookupEmitter.gateArgs, + `Aiur.NativeAIR.LookupEmitter.QueryExpr.mk, + `Aiur.NativeAIR.LookupEmitter.QueryExpr.eval, + `Aiur.NativeAIR.LookupEmitter.queryParts, + `Aiur.NativeAIR.LookupEmitter.accumulate, + `Aiur.NativeAIR.LookupEmitter.valuedAccumulate, + `Aiur.NativeAIR.LookupEmitter.slot, + `Aiur.NativeAIR.LookupEmitter.slots] + +def blockCircuitRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.BlockEmitter.evaluated_read, + `Aiur.NativeAIR.BlockEmitter.list_mapM_evaluate, + `Aiur.NativeAIR.BlockEmitter.sum_fold_eval, + `Aiur.NativeAIR.BlockEmitter.sum_eval, + `Aiur.NativeAIR.BlockEmitter.selectors_array_eval, + `Aiur.NativeAIR.BlockEmitter.ctrlSelector_reads, + `Aiur.NativeAIR.BlockEmitter.blockSelector_reads, + `Aiur.NativeAIR.BlockEmitter.ctrlSelector_eval, + `Aiur.NativeAIR.BlockEmitter.blockSelector_eval, + `Aiur.NativeAIR.BlockEmitter.list_mapM_flatMap, + `Aiur.NativeAIR.BlockEmitter.list_mapM_foldl, + `Aiur.NativeAIR.BlockEmitter.Emission.eval_of, + `Aiur.NativeAIR.BlockEmitter.Emission.eval_components, + `Aiur.NativeAIR.BlockEmitter.Emission.prefix_eval, + `Aiur.NativeAIR.BlockEmitter.Emission.afterOps_eval, + `Aiur.NativeAIR.BlockEmitter.join_eval, + `Aiur.NativeAIR.BlockEmitter.Emission.continued_eval, + `Aiur.NativeAIR.BlockEmitter.YieldExpr.eval_of, + `Aiur.NativeAIR.BlockEmitter.YieldExpr.eval_components, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval_of, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval_components, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.message_eval, + `Aiur.NativeAIR.BlockEmitter.returned_eval, + `Aiur.NativeAIR.BlockEmitter.yielded_eval, + `Aiur.NativeAIR.BlockEmitter.evalRows_getD_any, + `Aiur.NativeAIR.BlockEmitter.yieldValue_eval, + `Aiur.NativeAIR.BlockEmitter.yieldGate_eval, + `Aiur.NativeAIR.BlockEmitter.mergeEquations_eval, + `Aiur.NativeAIR.BlockEmitter.yields_size, + `Aiur.NativeAIR.BlockEmitter.caseEquation_eval, + `Aiur.NativeAIR.BlockEmitter.defaultEquations_eval, + `Aiur.NativeAIR.BlockEmitter.fold_max_start, + `Aiur.NativeAIR.BlockEmitter.fold_max_member, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_match, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_matchContinue, + `Aiur.NativeAIR.BlockEmitter.branchRows_invariants, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_invariants, + `Aiur.NativeAIR.BlockEmitter.emitBlock_invariants, + `Aiur.NativeAIR.BlockEmitter.list_mapM_refine_mem, + `Aiur.NativeAIR.BlockEmitter.caseRows_reflects, + `Aiur.NativeAIR.BlockEmitter.defaultRow_reflects, + `Aiur.NativeAIR.BlockEmitter.branchRows_reflects, + `Aiur.NativeAIR.BlockEmitter.continueRow_column, + `Aiur.NativeAIR.BlockEmitter.advice_absolute_eval, + `Aiur.NativeAIR.BlockEmitter.continueRow_reflects, + `Aiur.NativeAIR.BlockEmitter.ctrl_reflects, + `Aiur.NativeAIR.BlockEmitter.block_reflects, + `Aiur.NativeAIR.BlockEmitter.returnArgs_fold_eval, + `Aiur.NativeAIR.BlockEmitter.returnArgs_eval, + `Aiur.NativeAIR.BlockEmitter.lookup_eval, + `Aiur.NativeAIR.CircuitEmitter.selectorExprs_reads, + `Aiur.NativeAIR.CircuitEmitter.Member.eval_of, + `Aiur.NativeAIR.CircuitEmitter.Member.eval_components, + `Aiur.NativeAIR.CircuitEmitter.selectorEquations_eval, + `Aiur.NativeAIR.CircuitEmitter.evalFin_of, + `Aiur.NativeAIR.CircuitEmitter.evalFin_components, + `Aiur.NativeAIR.CircuitEmitter.Emission.eval_of, + `Aiur.NativeAIR.CircuitEmitter.Emission.eval_components, + `Aiur.NativeAIR.CircuitEmitter.Emission.lookup_eval, + `Aiur.NativeAIR.CircuitEmitter.Emission.lookups_eval, + `Aiur.NativeAIR.CircuitEmitter.emitMember_reflects, + `Aiur.NativeAIR.CircuitEmitter.emitMembers_reflects, + `Aiur.NativeAIR.CircuitEmitter.circuitEmission_eval, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_reflects, + `Aiur.NativeAIR.CircuitEmitter.equations_vanish, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_reflects] + +def blockCircuitQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.BlockEmitter.list_mapM_evaluate, + `Aiur.NativeAIR.BlockEmitter.sum_fold_eval, + `Aiur.NativeAIR.BlockEmitter.sum_eval, + `Aiur.NativeAIR.BlockEmitter.list_mapM_flatMap, + `Aiur.NativeAIR.BlockEmitter.list_mapM_foldl, + `Aiur.NativeAIR.BlockEmitter.Emission.eval_of, + `Aiur.NativeAIR.BlockEmitter.Emission.prefix_eval, + `Aiur.NativeAIR.BlockEmitter.join_eval, + `Aiur.NativeAIR.BlockEmitter.Emission.continued_eval, + `Aiur.NativeAIR.BlockEmitter.YieldExpr.eval_of, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval_of, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.message_eval, + `Aiur.NativeAIR.BlockEmitter.returned_eval, + `Aiur.NativeAIR.BlockEmitter.yielded_eval, + `Aiur.NativeAIR.BlockEmitter.yieldGate_eval, + `Aiur.NativeAIR.BlockEmitter.yields_size, + `Aiur.NativeAIR.BlockEmitter.caseEquation_eval, + `Aiur.NativeAIR.BlockEmitter.list_mapM_refine_mem, + `Aiur.NativeAIR.BlockEmitter.returnArgs_fold_eval, + `Aiur.NativeAIR.BlockEmitter.returnArgs_eval, + `Aiur.NativeAIR.BlockEmitter.lookup_eval, + `Aiur.NativeAIR.CircuitEmitter.selectorEquations_eval, + `Aiur.NativeAIR.CircuitEmitter.equations_vanish] + +def blockCircuitClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.BlockEmitter.evaluated_read, + `Aiur.NativeAIR.BlockEmitter.selectors_array_eval, + `Aiur.NativeAIR.BlockEmitter.ctrlSelector_reads, + `Aiur.NativeAIR.BlockEmitter.blockSelector_reads, + `Aiur.NativeAIR.BlockEmitter.ctrlSelector_eval, + `Aiur.NativeAIR.BlockEmitter.blockSelector_eval, + `Aiur.NativeAIR.BlockEmitter.Emission.afterOps_eval, + `Aiur.NativeAIR.BlockEmitter.evalRows_getD_any, + `Aiur.NativeAIR.BlockEmitter.yieldValue_eval, + `Aiur.NativeAIR.BlockEmitter.mergeEquations_eval, + `Aiur.NativeAIR.BlockEmitter.defaultEquations_eval, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_match, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_matchContinue, + `Aiur.NativeAIR.BlockEmitter.branchRows_invariants, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_invariants, + `Aiur.NativeAIR.BlockEmitter.emitBlock_invariants, + `Aiur.NativeAIR.BlockEmitter.caseRows_reflects, + `Aiur.NativeAIR.BlockEmitter.defaultRow_reflects, + `Aiur.NativeAIR.BlockEmitter.branchRows_reflects, + `Aiur.NativeAIR.BlockEmitter.continueRow_column, + `Aiur.NativeAIR.BlockEmitter.advice_absolute_eval, + `Aiur.NativeAIR.BlockEmitter.continueRow_reflects, + `Aiur.NativeAIR.BlockEmitter.ctrl_reflects, + `Aiur.NativeAIR.BlockEmitter.block_reflects, + `Aiur.NativeAIR.CircuitEmitter.selectorExprs_reads, + `Aiur.NativeAIR.CircuitEmitter.evalFin_of, + `Aiur.NativeAIR.CircuitEmitter.evalFin_components, + `Aiur.NativeAIR.CircuitEmitter.Emission.eval_of, + `Aiur.NativeAIR.CircuitEmitter.Emission.eval_components, + `Aiur.NativeAIR.CircuitEmitter.Emission.lookup_eval, + `Aiur.NativeAIR.CircuitEmitter.Emission.lookups_eval, + `Aiur.NativeAIR.CircuitEmitter.emitMember_reflects, + `Aiur.NativeAIR.CircuitEmitter.emitMembers_reflects, + `Aiur.NativeAIR.CircuitEmitter.circuitEmission_eval, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_reflects, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_reflects] + +def blockCircuitPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.BlockEmitter.sum, + `Aiur.NativeAIR.BlockEmitter.SelectorReads, + `Aiur.NativeAIR.BlockEmitter.ctrlSelector, + `Aiur.NativeAIR.BlockEmitter.blockSelector, + `Aiur.NativeAIR.BlockEmitter.Context.mk, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.mk, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval, + `Aiur.NativeAIR.BlockEmitter.ReturnExpr.message, + `Aiur.NativeAIR.BlockEmitter.YieldExpr.mk, + `Aiur.NativeAIR.BlockEmitter.YieldExpr.eval, + `Aiur.NativeAIR.BlockEmitter.evalGatedCall, + `Aiur.NativeAIR.BlockEmitter.Emission.mk, + `Aiur.NativeAIR.BlockEmitter.Emission.eval, + `Aiur.NativeAIR.BlockEmitter.Emission.prefix, + `Aiur.NativeAIR.BlockEmitter.Emission.afterOps, + `Aiur.NativeAIR.BlockEmitter.join, + `Aiur.NativeAIR.BlockEmitter.Emission.continued, + `Aiur.NativeAIR.BlockEmitter.returned, + `Aiur.NativeAIR.BlockEmitter.yielded, + `Aiur.NativeAIR.BlockEmitter.yieldValue, + `Aiur.NativeAIR.BlockEmitter.yieldGate, + `Aiur.NativeAIR.BlockEmitter.mergeEquations, + `Aiur.NativeAIR.BlockEmitter.caseEquation, + `Aiur.NativeAIR.BlockEmitter.defaultEquations, + `Aiur.NativeAIR.BlockEmitter.emitCtrl, + `Aiur.NativeAIR.BlockEmitter.emitBlock, + `Aiur.NativeAIR.BlockEmitter.caseRow, + `Aiur.NativeAIR.BlockEmitter.defaultRow, + `Aiur.NativeAIR.BlockEmitter.branchRows, + `Aiur.NativeAIR.BlockEmitter.continueRow, + `Aiur.NativeAIR.BlockEmitter.selectorAt, + `Aiur.NativeAIR.BlockEmitter.Context.valued, + `Aiur.NativeAIR.BlockEmitter.BlockReflects, + `Aiur.NativeAIR.BlockEmitter.CtrlReflects, + `Aiur.NativeAIR.BlockEmitter.returnArgs, + `Aiur.NativeAIR.BlockEmitter.lookup, + `Aiur.NativeAIR.CircuitEmitter.selectorExprs, + `Aiur.NativeAIR.CircuitEmitter.Member.mk, + `Aiur.NativeAIR.CircuitEmitter.Member.readBound, + `Aiur.NativeAIR.CircuitEmitter.Member.eval, + `Aiur.NativeAIR.CircuitEmitter.emitMember, + `Aiur.NativeAIR.CircuitEmitter.emitMembers, + `Aiur.NativeAIR.CircuitEmitter.rankBytes, + `Aiur.NativeAIR.CircuitEmitter.selectorEquations, + `Aiur.NativeAIR.CircuitEmitter.Emission.mk, + `Aiur.NativeAIR.CircuitEmitter.Emission.readBound, + `Aiur.NativeAIR.CircuitEmitter.circuitEmission, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit, + `Aiur.NativeAIR.CircuitEmitter.Emission.lookup, + `Aiur.NativeAIR.CircuitEmitter.Emission.lookups, + `Aiur.NativeAIR.CircuitEmitter.evalFin, + `Aiur.NativeAIR.CircuitEmitter.Emission.eval, + `Aiur.NativeAIR.CircuitEmitter.Compiled.mk, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit] + +def allocationRoots : Array Lean.Name := #[ + `Aiur.Bytecode.selectedDegree_initial, + `Aiur.Bytecode.selectedDegree_append, + `Aiur.Concrete.Bytecode.getDegree_list, + `Aiur.Concrete.Bytecode.getDegree_array, + `Aiur.Concrete.Bytecode.opLayout_allocation, + `Aiur.NativeAIR.RowExpr.ZeroConstant.konst, + `Aiur.NativeAIR.RowExpr.ZeroConstant.variable, + `Aiur.NativeAIR.RowExpr.ZeroConstant.add, + `Aiur.NativeAIR.RowExpr.ZeroConstant.sub, + `Aiur.NativeAIR.RowExpr.ZeroConstant.mul, + `Aiur.NativeAIR.OpEmitter.DegreeValid.empty, + `Aiur.NativeAIR.OpEmitter.DegreeValid.singleton, + `Aiur.NativeAIR.OpEmitter.DegreeValid.append, + `Aiur.NativeAIR.OpEmitter.DegreeValid.push, + `Aiur.NativeAIR.OpEmitter.DegreeValid.read, + `Aiur.NativeAIR.OpEmitter.DegreeValid.getD, + `Aiur.NativeAIR.OpEmitter.DegreeValid.select, + `Aiur.NativeAIR.OpEmitter.advice_degreeValid, + `Aiur.NativeAIR.OpEmitter.packFour_degreeValid, + `Aiur.NativeAIR.OpEmitter.readWord_degreeValid, + `Aiur.NativeAIR.OpEmitter.fromScalar_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitMul_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitEqZero_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitByte2_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitWordSum_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitU32LessThan_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitOp_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitOps_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitEqZero_allocation, + `Aiur.NativeAIR.OpEmitter.rowDegrees_empty, + `Aiur.NativeAIR.OpEmitter.rowDegrees_append, + `Aiur.NativeAIR.OpEmitter.rowDegrees_push, + `Aiur.NativeAIR.OpEmitter.rowDegrees_singleton, + `Aiur.NativeAIR.OpEmitter.rowDegrees_getD, + `Aiur.NativeAIR.OpEmitter.rowDegrees_read, + `Aiur.NativeAIR.OpEmitter.select_degrees, + `Aiur.NativeAIR.OpEmitter.advice_degrees, + `Aiur.NativeAIR.OpEmitter.packFour_degree, + `Aiur.NativeAIR.OpEmitter.readWord_degree, + `Aiur.NativeAIR.OpEmitter.emitAdvice_allocation, + `Aiur.NativeAIR.OpEmitter.emitWordSum_allocation, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_allocation, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_allocation, + `Aiur.NativeAIR.OpEmitter.emitOp_allocation, + `Aiur.NativeAIR.OpEmitter.emitOp_layout, + `Aiur.NativeAIR.OpEmitter.emitOps_fold_layout, + `Aiur.NativeAIR.OpEmitter.emitOps_layout, + `Aiur.Concrete.Bytecode.allocationBranchStep_degrees, + `Aiur.Concrete.Bytecode.allocationBranchStep_column, + `Aiur.Concrete.Bytecode.allocationBranchFold, + `Aiur.Concrete.Bytecode.allocationBranchLoop, + `Aiur.Concrete.Bytecode.matchLayout_allocation, + `Aiur.Concrete.Bytecode.ctrlLayout_continue, + `Aiur.NativeAIR.BlockEmitter.branchRows_values, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_degreeValid, + `Aiur.NativeAIR.BlockEmitter.emitBlock_degreeValid, + `Aiur.NativeAIR.BlockEmitter.branchRows_layout, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_layout, + `Aiur.NativeAIR.BlockEmitter.emitBlock_layout] + +def allocationAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.RowExpr.ZeroConstant.konst, + `Aiur.NativeAIR.RowExpr.ZeroConstant.variable] + +def allocationQuotRoots : Array Lean.Name := #[ + `Aiur.Bytecode.selectedDegree_initial, + `Aiur.NativeAIR.RowExpr.ZeroConstant.add, + `Aiur.NativeAIR.RowExpr.ZeroConstant.sub, + `Aiur.NativeAIR.RowExpr.ZeroConstant.mul, + `Aiur.NativeAIR.OpEmitter.DegreeValid.append, + `Aiur.NativeAIR.OpEmitter.DegreeValid.select, + `Aiur.NativeAIR.OpEmitter.packFour_degreeValid, + `Aiur.NativeAIR.OpEmitter.readWord_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitMul_degreeValid, + `Aiur.NativeAIR.OpEmitter.rowDegrees_empty, + `Aiur.NativeAIR.OpEmitter.rowDegrees_append, + `Aiur.NativeAIR.OpEmitter.rowDegrees_push, + `Aiur.NativeAIR.OpEmitter.rowDegrees_singleton, + `Aiur.NativeAIR.OpEmitter.rowDegrees_getD, + `Aiur.NativeAIR.OpEmitter.rowDegrees_read, + `Aiur.NativeAIR.OpEmitter.select_degrees] + +def allocationClassicalRoots : Array Lean.Name := #[ + `Aiur.Bytecode.selectedDegree_append, + `Aiur.Concrete.Bytecode.getDegree_list, + `Aiur.Concrete.Bytecode.getDegree_array, + `Aiur.Concrete.Bytecode.opLayout_allocation, + `Aiur.NativeAIR.OpEmitter.advice_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitByte2_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitWordSum_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitOp_degreeValid, + `Aiur.NativeAIR.OpEmitter.emitOps_degreeValid, + `Aiur.NativeAIR.OpEmitter.advice_degrees, + `Aiur.NativeAIR.OpEmitter.packFour_degree, + `Aiur.NativeAIR.OpEmitter.readWord_degree, + `Aiur.NativeAIR.OpEmitter.emitAdvice_allocation, + `Aiur.NativeAIR.OpEmitter.emitWordSum_allocation, + `Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_allocation, + `Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_allocation, + `Aiur.NativeAIR.OpEmitter.emitOp_allocation, + `Aiur.NativeAIR.OpEmitter.emitOp_layout, + `Aiur.NativeAIR.OpEmitter.emitOps_fold_layout, + `Aiur.NativeAIR.OpEmitter.emitOps_layout, + `Aiur.Concrete.Bytecode.allocationBranchStep_degrees, + `Aiur.Concrete.Bytecode.allocationBranchStep_column, + `Aiur.Concrete.Bytecode.allocationBranchFold, + `Aiur.Concrete.Bytecode.allocationBranchLoop, + `Aiur.Concrete.Bytecode.matchLayout_allocation, + `Aiur.Concrete.Bytecode.ctrlLayout_continue, + `Aiur.NativeAIR.BlockEmitter.branchRows_values, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_degreeValid, + `Aiur.NativeAIR.BlockEmitter.emitBlock_degreeValid, + `Aiur.NativeAIR.BlockEmitter.branchRows_layout, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_layout, + `Aiur.NativeAIR.BlockEmitter.emitBlock_layout] + +def allocationPremises : Array Lean.Name := #[ + `Aiur.Bytecode.OpAllocation.mk, + `Aiur.Bytecode.OpAllocation.advice, + `Aiur.Bytecode.selectedDegree, + `Aiur.Bytecode.Op.allocation, + `Aiur.NativeAIR.RowExpr.ZeroConstant, + `Aiur.NativeAIR.OpEmitter.DegreeValid, + `Aiur.NativeAIR.OpEmitter.rowDegrees, + `Aiur.NativeAIR.OpEmitter.Emission.allocation, + `Aiur.Concrete.Bytecode.allocationBranchStep] + +def circuitAllocationRoots : Array Lean.Name := #[ + `Aiur.Concrete.Bytecode.opLayout_fixed, + `Aiur.Concrete.Bytecode.opsLayout_fields, + `Aiur.Concrete.Bytecode.allocationBranchStep_fields, + `Aiur.Concrete.Bytecode.allocationBranchFold_fields, + `Aiur.Concrete.Bytecode.matchLayout_fields, + `Aiur.Concrete.Bytecode.ctrlLayout_fields, + `Aiur.Concrete.Bytecode.blockLayout_fields, + `Aiur.Concrete.Bytecode.ctrlLayout_match_list, + `Aiur.Concrete.Bytecode.rewriteOp_layout, + `Aiur.Concrete.Bytecode.matchLayout_rewrite, + `Aiur.Concrete.Bytecode.rewriteCtrl_layout, + `Aiur.Concrete.Bytecode.rewriteBlock_layout, + `Aiur.Bytecode.functionsComputedLayout_empty, + `Aiur.Bytecode.functionsComputedLayout_push, + `Aiur.Bytecode.Function.ComputedLayout.auxiliaries, + `Aiur.Bytecode.Function.ComputedLayout.reserved, + `Aiur.Bytecode.Function.ComputedLayout.selectors, + `Aiur.Concrete.Function.compile_computedLayout, + `Aiur.Concrete.Decls.toBytecode_computedLayout, + `Aiur.Bytecode.Function.ComputedLayout.rewrite, + `Aiur.Bytecode.deduplicate_newFunctions_computedLayout, + `Aiur.Bytecode.Toplevel.deduplicateCandidate_computedLayout, + `Aiur.Bytecode.Toplevel.deduplicate_computedLayout, + `Aiur.finishCompilation_computedLayout, + `Aiur.Source.Toplevel.compile_computedLayout, + `Aiur.BoundVerifier.Backend.functions_computedLayout, + `Aiur.Bytecode.merged_columnBound, + `Aiur.Bytecode.singletonCircuits_columnBound, + `Aiur.CompiledToplevel.groupFunctions_columnBound, + `Aiur.finishCompilation_columnBound, + `Aiur.Source.Toplevel.compile_columnBound, + `Aiur.BoundVerifier.Backend.circuits_columnBound, + `Aiur.NativeAIR.CircuitEmitter.emitMember_layout, + `Aiur.NativeAIR.CircuitEmitter.emitMembers_layout, + `Aiur.NativeAIR.CircuitEmitter.emitMembers_selectors, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_readBound, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_readBound, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_physical_reflects, + `Aiur.BoundVerifier.Backend.circuit_readBound, + `Aiur.BoundVerifier.Backend.compileCircuit_reflects] + +def circuitAllocationPremises : Array Lean.Name := #[ + `Aiur.Bytecode.Function.ComputedLayout, + `Aiur.Bytecode.FunctionsComputedLayout, + `Aiur.Bytecode.MembersColumnBound, + `Aiur.Bytecode.CircuitsColumnBound] + +def circuitCompletionRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Compiler.compileExpr_defined, + `Aiur.NativeAIR.Compiler.compileExprs_defined, + `Aiur.NativeAIR.Compiler.compileLookup_defined, + `Aiur.NativeAIR.Compiler.compileLookups_defined, + `Aiur.NativeAIR.Compiler.recordZero_defined, + `Aiur.NativeAIR.Compiler.compileZeros_defined, + `Aiur.NativeAIR.Compiler.compileBase_defined, + `Aiur.AIR.selectorSum_zero, + `Aiur.AIR.emitOp_inactive, + `Aiur.AIR.emitOps_inactive, + `Aiur.AIR.BlockEmission.Inactive.prefix, + `Aiur.AIR.BlockEmission.Inactive.afterOps, + `Aiur.AIR.joinBlockEmissions_inactive, + `Aiur.AIR.BlockEmission.Inactive.continued, + `Aiur.Bytecode.branchSelectorFlows_entry_zero, + `Aiur.Bytecode.Ctrl.selectorFlow_entry_zero, + `Aiur.Bytecode.Block.selectorFlow_entry_zero, + `Aiur.Bytecode.branchRows_inactive, + `Aiur.Bytecode.Ctrl.emitRow_inactive, + `Aiur.Bytecode.Block.emitRow_inactive, + `Aiur.AIR.MemberEmission.entry_zero, + `Aiur.AIR.emitMember_zero, + `Aiur.AIR.emitMembers_zero, + `Aiur.AIR.circuitEmission_zero, + `Aiur.Bytecode.Circuit.emitRow_zero, + `Aiur.NativeAIR.CircuitEmitter.zeroValues_fits, + `Aiur.NativeAIR.CircuitEmitter.zeroValues_read, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_zero_eval, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_compiles, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_defined_iff, + `Aiur.BoundVerifier.Backend.emitCircuit_compiles, + `Aiur.BoundVerifier.Backend.emittedCircuit_reflects] + +def circuitCompletionQuotRoots : Array Lean.Name := #[ + `Aiur.AIR.emitOp_inactive, + `Aiur.AIR.emitOps_inactive, + `Aiur.AIR.joinBlockEmissions_inactive] + +def circuitCompletionClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Compiler.compileExpr_defined, + `Aiur.NativeAIR.Compiler.compileExprs_defined, + `Aiur.NativeAIR.Compiler.compileLookup_defined, + `Aiur.NativeAIR.Compiler.compileLookups_defined, + `Aiur.NativeAIR.Compiler.recordZero_defined, + `Aiur.NativeAIR.Compiler.compileZeros_defined, + `Aiur.NativeAIR.Compiler.compileBase_defined, + `Aiur.Bytecode.branchSelectorFlows_entry_zero, + `Aiur.Bytecode.Ctrl.selectorFlow_entry_zero, + `Aiur.Bytecode.Block.selectorFlow_entry_zero, + `Aiur.Bytecode.branchRows_inactive, + `Aiur.Bytecode.Ctrl.emitRow_inactive, + `Aiur.Bytecode.Block.emitRow_inactive, + `Aiur.AIR.MemberEmission.entry_zero, + `Aiur.AIR.emitMember_zero, + `Aiur.AIR.emitMembers_zero, + `Aiur.AIR.circuitEmission_zero, + `Aiur.Bytecode.Circuit.emitRow_zero, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_zero_eval, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_compiles, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_defined_iff, + `Aiur.BoundVerifier.Backend.emitCircuit_compiles, + `Aiur.BoundVerifier.Backend.emittedCircuit_reflects] + +def circuitCompletionPremises : Array Lean.Name := #[ + `Aiur.AIR.BlockEmission.Inactive, + `Aiur.NativeAIR.CircuitEmitter.circuitWidths, + `Aiur.NativeAIR.CircuitEmitter.zeroValues] + +def checkedCircuitRoots : Array Lean.Name := #[ + `Aiur.Bytecode.indicesInScope_spec, + `Aiur.Bytecode.wordInScope_spec, + `Aiur.Bytecode.addScope_eq, + `Aiur.Bytecode.checkEmissionOps_cons, + `Aiur.Bytecode.checkEmissionOps_le, + `Aiur.Bytecode.Op.allocation_outputSize, + `Aiur.NativeAIR.OpEmitter.list_mapM_defined, + `Aiur.NativeAIR.OpEmitter.array_mapM_defined, + `Aiur.NativeAIR.OpEmitter.select_defined, + `Aiur.NativeAIR.OpEmitter.readWord_defined, + `Aiur.NativeAIR.OpEmitter.emitOp_defined, + `Aiur.NativeAIR.OpEmitter.emitOp_outputSize, + `Aiur.NativeAIR.OpEmitter.emitOps_defined, + `Aiur.Bytecode.emissionChecks_match, + `Aiur.Bytecode.emissionChecks_matchContinue, + `Aiur.Bytecode.Block.emissionChecks_parts, + `Aiur.Bytecode.Toplevel.validateEmission_function, + `Aiur.NativeAIR.BlockEmitter.ctrlSelector_defined, + `Aiur.NativeAIR.BlockEmitter.blockSelector_defined, + `Aiur.NativeAIR.BlockEmitter.Emission.YieldShape.prefix, + `Aiur.NativeAIR.BlockEmitter.join_yieldShape, + `Aiur.NativeAIR.BlockEmitter.branchRows_defined, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_defined, + `Aiur.NativeAIR.BlockEmitter.emitBlock_defined, + `Aiur.NativeAIR.CircuitEmitter.emitMember_defined, + `Aiur.NativeAIR.CircuitEmitter.emitMembers_defined, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_defined, + `Aiur.BoundVerifier.Backend.circuit_emits, + `Aiur.BoundVerifier.Backend.circuit_compiles, + `Aiur.BoundVerifier.Backend.circuit_graph_reflects] + +def checkedCircuitAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.Bytecode.addScope_eq, + `Aiur.NativeAIR.BlockEmitter.Emission.YieldShape.prefix] + +def checkedCircuitQuotRoots : Array Lean.Name := #[ + `Aiur.Bytecode.indicesInScope_spec, + `Aiur.Bytecode.wordInScope_spec, + `Aiur.Bytecode.checkEmissionOps_le, + `Aiur.NativeAIR.OpEmitter.list_mapM_defined, + `Aiur.NativeAIR.OpEmitter.array_mapM_defined, + `Aiur.NativeAIR.OpEmitter.select_defined, + `Aiur.NativeAIR.OpEmitter.readWord_defined, + `Aiur.NativeAIR.OpEmitter.emitOp_defined, + `Aiur.NativeAIR.BlockEmitter.join_yieldShape] + +def checkedCircuitClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.OpEmitter.emitOp_outputSize, + `Aiur.NativeAIR.OpEmitter.emitOps_defined, + `Aiur.Bytecode.emissionChecks_match, + `Aiur.Bytecode.emissionChecks_matchContinue, + `Aiur.Bytecode.Block.emissionChecks_parts, + `Aiur.Bytecode.Toplevel.validateEmission_function, + `Aiur.NativeAIR.BlockEmitter.ctrlSelector_defined, + `Aiur.NativeAIR.BlockEmitter.blockSelector_defined, + `Aiur.NativeAIR.BlockEmitter.branchRows_defined, + `Aiur.NativeAIR.BlockEmitter.emitCtrl_defined, + `Aiur.NativeAIR.BlockEmitter.emitBlock_defined, + `Aiur.NativeAIR.CircuitEmitter.emitMember_defined, + `Aiur.NativeAIR.CircuitEmitter.emitMembers_defined, + `Aiur.NativeAIR.CircuitEmitter.emitCircuit_defined, + `Aiur.BoundVerifier.Backend.circuit_emits, + `Aiur.BoundVerifier.Backend.circuit_compiles, + `Aiur.BoundVerifier.Backend.circuit_graph_reflects] + +def checkedCircuitPremises : Array Lean.Name := #[ + `Aiur.Bytecode.indicesInScope, + `Aiur.Bytecode.wordInScope, + `Aiur.Bytecode.Op.outputSize, + `Aiur.Bytecode.Op.emissionInputs, + `Aiur.Bytecode.addScope, + `Aiur.Bytecode.checkEmissionOps, + `Aiur.Bytecode.Ctrl.emissionChecks, + `Aiur.Bytecode.Block.emissionChecks, + `Aiur.Bytecode.Function.emissionChecks, + `Aiur.Bytecode.Toplevel.validateEmission, + `Aiur.NativeAIR.BlockEmitter.Emission.YieldShape] + +def keyCodecRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.KeyCodec.Reads.pure, + `Aiur.NativeAIR.KeyCodec.Reads.bind, + `Aiur.NativeAIR.KeyCodec.Reads.map, + `Aiur.NativeAIR.KeyCodec.Reads.result, + `Aiur.NativeAIR.KeyCodec.readByte_reads, + `Aiur.NativeAIR.KeyCodec.Reads.byte, + `Aiur.NativeAIR.KeyCodec.encodeNat_length, + `Aiur.NativeAIR.KeyCodec.readNat_reads, + `Aiur.NativeAIR.KeyCodec.readMany_reads, + `Aiur.NativeAIR.KeyCodec.readVector_reads, + `Aiur.NativeAIR.KeyCodec.readNode_reads, + `Aiur.NativeAIR.KeyCodec.readLookup_reads, + `Aiur.NativeAIR.KeyCodec.readCircuitData_reads, + `Aiur.NativeAIR.KeyCodec.readCircuit_reads, + `Aiur.NativeAIR.KeyCodec.readParameters_reads, + `Aiur.NativeAIR.KeyCodec.readCommitment_reads, + `Aiur.NativeAIR.KeyCodec.readIndex_reads, + `Aiur.NativeAIR.KeyCodec.readKey_reads, + `Aiur.NativeAIR.KeyCodec.decode_encode, + `Aiur.NativeAIR.KeyCodec.decodeCanonical_success, + `Aiur.NativeAIR.KeyCodec.decodeCanonical_encode, + `Aiur.NativeAIR.KeyCodec.canonical_bytes_unique, + `Aiur.NativeAIR.KeyCodec.encode_injective, + `Aiur.NativeAIR.KeyCodec.Returns.pure, + `Aiur.NativeAIR.KeyCodec.Returns.failure, + `Aiur.NativeAIR.KeyCodec.Returns.bind, + `Aiur.NativeAIR.KeyCodec.Returns.bind_any, + `Aiur.NativeAIR.KeyCodec.Returns.weaken, + `Aiur.NativeAIR.KeyCodec.Returns.result, + `Aiur.NativeAIR.KeyCodec.readMany_returns, + `Aiur.NativeAIR.KeyCodec.readVector_returns, + `Aiur.NativeAIR.KeyCodec.readCircuit_returns, + `Aiur.NativeAIR.KeyCodec.readCommitment_returns, + `Aiur.NativeAIR.KeyCodec.readKey_returns, + `Aiur.NativeAIR.KeyCodec.decode_success, + `Aiur.NativeAIR.KeyCodec.decode_valid, + `Aiur.NativeAIR.KeyCodec.readKey_commitment, + `Aiur.NativeAIR.KeyCodec.decode_commitment, + `Aiur.NativeAIR.KeyCodec.Circuit.valid_graph, + `Aiur.NativeAIR.KeyCodec.decoded_graph_sweeps, + `Aiur.NativeAIR.KeyCodec.decode_encoded_suffix, + `Aiur.BoundVerifier.Backend.key_decodes, + `Aiur.BoundVerifier.Backend.native_key_decodes, + `Aiur.BoundVerifier.Backend.native_key_encoding, + `Aiur.BoundVerifier.Backend.key_commitment, + `Aiur.BoundVerifier.Backend.key_graph_valid, + `Aiur.BoundVerifier.Backend.key_graph_reflects] + +def keyCodecAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.KeyCodec.Reads.pure, + `Aiur.NativeAIR.KeyCodec.Reads.map, + `Aiur.NativeAIR.KeyCodec.Reads.result, + `Aiur.NativeAIR.KeyCodec.readByte_reads, + `Aiur.NativeAIR.KeyCodec.Returns.pure, + `Aiur.NativeAIR.KeyCodec.Returns.failure, + `Aiur.NativeAIR.KeyCodec.Returns.weaken] + +def keyCodecQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.KeyCodec.readCircuit_reads, + `Aiur.NativeAIR.KeyCodec.readParameters_reads, + `Aiur.NativeAIR.KeyCodec.readIndex_reads, + `Aiur.NativeAIR.KeyCodec.readMany_returns, + `Aiur.NativeAIR.KeyCodec.readVector_returns, + `Aiur.NativeAIR.KeyCodec.Circuit.valid_graph] + +def keyCodecClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.KeyCodec.readCommitment_reads, + `Aiur.NativeAIR.KeyCodec.readKey_reads, + `Aiur.NativeAIR.KeyCodec.decode_encode, + `Aiur.NativeAIR.KeyCodec.decodeCanonical_success, + `Aiur.NativeAIR.KeyCodec.decodeCanonical_encode, + `Aiur.NativeAIR.KeyCodec.canonical_bytes_unique, + `Aiur.NativeAIR.KeyCodec.encode_injective, + `Aiur.NativeAIR.KeyCodec.readCommitment_returns, + `Aiur.NativeAIR.KeyCodec.readKey_returns, + `Aiur.NativeAIR.KeyCodec.decode_success, + `Aiur.NativeAIR.KeyCodec.decode_valid, + `Aiur.NativeAIR.KeyCodec.readKey_commitment, + `Aiur.NativeAIR.KeyCodec.decode_commitment, + `Aiur.NativeAIR.KeyCodec.decoded_graph_sweeps, + `Aiur.NativeAIR.KeyCodec.decode_encoded_suffix, + `Aiur.BoundVerifier.Backend.key_decodes, + `Aiur.BoundVerifier.Backend.native_key_decodes, + `Aiur.BoundVerifier.Backend.native_key_encoding, + `Aiur.BoundVerifier.Backend.key_commitment, + `Aiur.BoundVerifier.Backend.key_graph_valid, + `Aiur.BoundVerifier.Backend.key_graph_reflects] + +def keyCodecPremises : Array Lean.Name := #[ + `Aiur.BoundVerifier.Selection.keyParameters, + `Aiur.NativeAIR.KeyCodec.Reader, + `Aiur.NativeAIR.KeyCodec.readByte, + `Aiur.NativeAIR.KeyCodec.readNat, + `Aiur.NativeAIR.KeyCodec.readMany, + `Aiur.NativeAIR.KeyCodec.readVector, + `Aiur.NativeAIR.KeyCodec.encodeNat, + `Aiur.NativeAIR.KeyCodec.encodeVector, + `Aiur.NativeAIR.KeyCodec.readNode, + `Aiur.NativeAIR.KeyCodec.encodeNode, + `Aiur.NativeAIR.KeyCodec.readLookup, + `Aiur.NativeAIR.KeyCodec.encodeLookup, + `Aiur.NativeAIR.KeyCodec.Circuit.mk, + `Aiur.NativeAIR.KeyCodec.Circuit.groups, + `Aiur.NativeAIR.KeyCodec.Circuit.widths, + `Aiur.NativeAIR.KeyCodec.Circuit.constraintCount, + `Aiur.NativeAIR.KeyCodec.nodeDegree, + `Aiur.NativeAIR.KeyCodec.nodeDegreesFrom, + `Aiur.NativeAIR.KeyCodec.lookupDegrees, + `Aiur.NativeAIR.KeyCodec.groupDegree, + `Aiur.NativeAIR.KeyCodec.Circuit.computedDegree, + `Aiur.NativeAIR.KeyCodec.Circuit.valid, + `Aiur.NativeAIR.KeyCodec.readCircuitData, + `Aiur.NativeAIR.KeyCodec.readCircuit, + `Aiur.NativeAIR.KeyCodec.encodeCircuit, + `Aiur.NativeAIR.KeyCodec.Parameters.mk, + `Aiur.NativeAIR.KeyCodec.readParameters, + `Aiur.NativeAIR.KeyCodec.encodeParameters, + `Aiur.NativeAIR.KeyCodec.MerkleCap, + `Aiur.NativeAIR.KeyCodec.readCommitment, + `Aiur.NativeAIR.KeyCodec.encodeCommitment, + `Aiur.NativeAIR.KeyCodec.readIndex, + `Aiur.NativeAIR.KeyCodec.encodeIndex, + `Aiur.NativeAIR.KeyCodec.Key.mk, + `Aiur.NativeAIR.KeyCodec.readKey, + `Aiur.NativeAIR.KeyCodec.encodeKey, + `Aiur.NativeAIR.KeyCodec.decode, + `Aiur.NativeAIR.KeyCodec.encode, + `Aiur.NativeAIR.KeyCodec.decodeCanonical, + `Aiur.NativeAIR.KeyCodec.Reads, + `Aiur.NativeAIR.KeyCodec.NodeWireFits, + `Aiur.NativeAIR.KeyCodec.LookupWireFits.mk, + `Aiur.NativeAIR.KeyCodec.CircuitWireFits.mk, + `Aiur.NativeAIR.KeyCodec.ParametersWireFits, + `Aiur.NativeAIR.KeyCodec.CommitmentWireFits, + `Aiur.NativeAIR.KeyCodec.IndexWireFits, + `Aiur.NativeAIR.KeyCodec.KeyWireFits.mk, + `Aiur.NativeAIR.KeyCodec.Returns, + `Aiur.NativeAIR.KeyCodec.CommitmentValid] + +def compiledKeyRoots : Array Lean.Name := #[ + `Aiur.BoundVerifier.CompiledBackend.circuits_bound, + `Aiur.BoundVerifier.CompiledBackend.preprocessed_indices, + `Aiur.BoundVerifier.verifyCompiled_success, + `Aiur.NativeAIR.Compiler.compileExpr_widen, + `Aiur.NativeAIR.Compiler.compileExprs_widen, + `Aiur.NativeAIR.Compiler.compileLookup_widen, + `Aiur.NativeAIR.Compiler.compileLookups_widen, + `Aiur.NativeAIR.Compiler.compileZeros_widen, + `Aiur.NativeAIR.Compiler.compileBase_widen, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_widen, + `Aiur.NativeAIR.CircuitEmitter.circuitWidths_le, + `Aiur.NativeAIR.CompiledKey.column_eval, + `Aiur.NativeAIR.CompiledKey.memoryEquations_eval, + `Aiur.NativeAIR.CompiledKey.memoryLookup_eval, + `Aiur.NativeAIR.CompiledKey.byte1Lookup_eval, + `Aiur.NativeAIR.CompiledKey.byte2Lookup_eval, + `Aiur.NativeAIR.CompiledKey.circuit_success, + `Aiur.NativeAIR.CompiledKey.functionCircuit_success, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_success, + `Aiur.NativeAIR.CompiledKey.byte1Circuit_success, + `Aiur.NativeAIR.CompiledKey.byte2Circuit_success, + `Aiur.NativeAIR.CompiledKey.circuits_parts, + `Aiur.NativeAIR.CompiledKey.circuits_length, + `Aiur.NativeAIR.CompiledKey.circuits_function, + `Aiur.NativeAIR.CompiledKey.circuits_memory, + `Aiur.NativeAIR.CompiledKey.circuits_bytes, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_reflects, + `Aiur.NativeAIR.CompiledKey.byte1Circuit_reflects, + `Aiur.NativeAIR.CompiledKey.byte2Circuit_reflects, + `Aiur.BoundVerifier.CompiledBackend.circuit_count, + `Aiur.BoundVerifier.CompiledBackend.function_graph_reflects, + `Aiur.BoundVerifier.CompiledBackend.memory_graph_reflects, + `Aiur.BoundVerifier.CompiledBackend.byte_graphs, + `Aiur.BoundVerifier.CompiledBackend.byte1_graph_reflects, + `Aiur.BoundVerifier.CompiledBackend.byte2_graph_reflects] + +def compiledKeyQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.CompiledKey.circuit_success, + `Aiur.NativeAIR.Compiler.compileZeros_widen, + `Aiur.NativeAIR.Compiler.compileBase_widen, + `Aiur.NativeAIR.CompiledKey.memoryEquations_eval, + `Aiur.NativeAIR.CompiledKey.byte1Lookup_eval, + `Aiur.NativeAIR.CompiledKey.byte2Lookup_eval, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_success, + `Aiur.NativeAIR.CompiledKey.byte1Circuit_success, + `Aiur.NativeAIR.CompiledKey.byte2Circuit_success] + +def compiledKeyClassicalRoots : Array Lean.Name := #[ + `Aiur.BoundVerifier.CompiledBackend.circuits_bound, + `Aiur.BoundVerifier.CompiledBackend.preprocessed_indices, + `Aiur.BoundVerifier.verifyCompiled_success, + `Aiur.NativeAIR.CircuitEmitter.compileCircuit_widen, + `Aiur.NativeAIR.CompiledKey.memoryLookup_eval, + `Aiur.NativeAIR.CompiledKey.functionCircuit_success, + `Aiur.NativeAIR.CompiledKey.circuits_parts, + `Aiur.NativeAIR.CompiledKey.circuits_length, + `Aiur.NativeAIR.CompiledKey.circuits_function, + `Aiur.NativeAIR.CompiledKey.circuits_memory, + `Aiur.NativeAIR.CompiledKey.circuits_bytes, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_reflects, + `Aiur.NativeAIR.CompiledKey.byte1Circuit_reflects, + `Aiur.NativeAIR.CompiledKey.byte2Circuit_reflects, + `Aiur.BoundVerifier.CompiledBackend.circuit_count, + `Aiur.BoundVerifier.CompiledBackend.function_graph_reflects, + `Aiur.BoundVerifier.CompiledBackend.memory_graph_reflects, + `Aiur.BoundVerifier.CompiledBackend.byte_graphs, + `Aiur.BoundVerifier.CompiledBackend.byte1_graph_reflects, + `Aiur.BoundVerifier.CompiledBackend.byte2_graph_reflects] + +def compiledKeyPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.CompiledKey.main, + `Aiur.NativeAIR.CompiledKey.next, + `Aiur.NativeAIR.CompiledKey.preprocessed, + `Aiur.NativeAIR.CompiledKey.memoryEquations, + `Aiur.NativeAIR.CompiledKey.memoryLookup, + `Aiur.NativeAIR.CompiledKey.byte1Lookup, + `Aiur.NativeAIR.CompiledKey.byte2Lookup, + `Aiur.NativeAIR.CompiledKey.circuit, + `Aiur.NativeAIR.CompiledKey.functionCircuit, + `Aiur.NativeAIR.CompiledKey.memoryCircuit, + `Aiur.NativeAIR.CompiledKey.byte1Circuit, + `Aiur.NativeAIR.CompiledKey.byte2Circuit, + `Aiur.NativeAIR.CompiledKey.circuits, + `Aiur.NativeAIR.CompiledKey.preprocessedIndices, + `Aiur.NativeAIR.CompiledKey.check, + `Aiur.BoundVerifier.CompiledBackend.mk, + `Aiur.BoundVerifier.buildCompiled, + `Aiur.BoundVerifier.verifyCompiled, + `Aiur.NativeAIR.GraphWidths.Le, + `Aiur.NativeAIR.CompiledKey.columns] + +def proofAcceptanceRoots : Array Lean.Name := #[ + `Aiur.BoundVerifier.verifyShaped_success, + `Aiur.NativeAIR.ProofCodec.readVector_reads, + `Aiur.NativeAIR.ProofCodec.readOption_reads, + `Aiur.NativeAIR.ProofCodec.readBool_reads, + `Aiur.NativeAIR.ProofCodec.readField_reads, + `Aiur.NativeAIR.ProofCodec.readExtension_reads, + `Aiur.NativeAIR.ProofCodec.readCap_reads, + `Aiur.NativeAIR.ProofCodec.readOpenings_reads, + `Aiur.NativeAIR.ProofCodec.readCommitments_reads, + `Aiur.NativeAIR.ProofCodec.readBatchOpening_reads, + `Aiur.NativeAIR.ProofCodec.readCommitStep_reads, + `Aiur.NativeAIR.ProofCodec.readFri_reads, + `Aiur.NativeAIR.ProofCodec.readData_reads, + `Aiur.NativeAIR.ProofCodec.decode_encode, + `Aiur.NativeAIR.ProofCodec.decode_success, + `Aiur.NativeAIR.ProofCodec.decodeCanonical_success, + `Aiur.NativeAIR.ProofCodec.decodeCanonical_encode, + `Aiur.NativeAIR.ProofCodec.canonical_bytes_unique, + `Aiur.NativeAIR.ProofCodec.encode_injective, + `Aiur.NativeAIR.ProofCodec.decode_append_rejected, + `Aiur.NativeAIR.ProofCodec.readNat_returns, + `Aiur.NativeAIR.ProofCodec.readVector_returns, + `Aiur.NativeAIR.ProofCodec.readOption_returns, + `Aiur.NativeAIR.ProofCodec.readCap_returns, + `Aiur.NativeAIR.ProofCodec.readOpenings_returns, + `Aiur.NativeAIR.ProofCodec.readCommitments_returns, + `Aiur.NativeAIR.ProofCodec.readBatchOpening_returns, + `Aiur.NativeAIR.ProofCodec.readCommitStep_returns, + `Aiur.NativeAIR.ProofCodec.readFri_returns, + `Aiur.NativeAIR.ProofCodec.readData_returns, + `Aiur.NativeAIR.ProofCodec.decode_fits, + `Aiur.NativeAIR.ProofShape.pair_success, + `Aiur.NativeAIR.ProofShape.single_success, + `Aiur.NativeAIR.ProofShape.readPreprocessed_none, + `Aiur.NativeAIR.ProofShape.readPreprocessed_some, + `Aiur.NativeAIR.ProofShape.readRow_success, + `Aiur.NativeAIR.ProofShape.Pair.hasWidth_success, + `Aiur.NativeAIR.ProofShape.Row.fits_success, + `Aiur.NativeAIR.ProofShape.check_success, + `Aiur.NativeAIR.ProofShape.check_length, + `Aiur.NativeAIR.ProofShape.activeIndices_mem, + `Aiur.NativeAIR.ProofShape.check_row, + `Aiur.NativeAIR.ProofShape.check_row_active, + `Aiur.NativeAIR.ProofShape.check_nonempty, + `Aiur.NativeAIR.ProofShape.fixedHeights_sound, + `Aiur.NativeAIR.ProofShape.queryBound_sound, + `Aiur.BoundVerifier.CheckedProof.framing, + `Aiur.BoundVerifier.CheckedProof.wire_bounds, + `Aiur.BoundVerifier.CheckedProof.row, + `Aiur.BoundVerifier.CheckedProof.nonempty, + `Aiur.BoundVerifier.CheckedProof.fixed_heights, + `Aiur.BoundVerifier.CheckedProof.lookup_budget, + `Aiur.BoundVerifier.verifyShaped_acceptance] + +def proofAcceptanceAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.ProofCodec.readBool_reads] + +def proofAcceptanceQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.ProofCodec.decode_success, + `Aiur.NativeAIR.ProofCodec.decodeCanonical_success, + `Aiur.NativeAIR.ProofCodec.decodeCanonical_encode, + `Aiur.NativeAIR.ProofCodec.canonical_bytes_unique, + `Aiur.NativeAIR.ProofCodec.readNat_returns, + `Aiur.NativeAIR.ProofCodec.readVector_returns, + `Aiur.NativeAIR.ProofCodec.readCap_returns, + `Aiur.NativeAIR.ProofCodec.readOpenings_returns, + `Aiur.NativeAIR.ProofCodec.readCommitments_returns, + `Aiur.NativeAIR.ProofCodec.readBatchOpening_returns, + `Aiur.NativeAIR.ProofCodec.readCommitStep_returns, + `Aiur.NativeAIR.ProofCodec.readFri_returns, + `Aiur.NativeAIR.ProofCodec.readData_returns, + `Aiur.NativeAIR.ProofCodec.decode_fits, + `Aiur.NativeAIR.ProofShape.readPreprocessed_some, + `Aiur.NativeAIR.ProofShape.readRow_success, + `Aiur.NativeAIR.ProofShape.Pair.hasWidth_success, + `Aiur.NativeAIR.ProofShape.Row.fits_success, + `Aiur.NativeAIR.ProofShape.check_success, + `Aiur.NativeAIR.ProofShape.check_length, + `Aiur.NativeAIR.ProofShape.activeIndices_mem, + `Aiur.NativeAIR.ProofShape.check_row, + `Aiur.NativeAIR.ProofShape.check_row_active, + `Aiur.NativeAIR.ProofShape.check_nonempty, + `Aiur.NativeAIR.ProofShape.fixedHeights_sound, + `Aiur.NativeAIR.ProofShape.queryBound_sound, + `Aiur.BoundVerifier.CheckedProof.framing, + `Aiur.BoundVerifier.CheckedProof.wire_bounds, + `Aiur.BoundVerifier.CheckedProof.row, + `Aiur.BoundVerifier.CheckedProof.nonempty, + `Aiur.BoundVerifier.CheckedProof.fixed_heights, + `Aiur.BoundVerifier.CheckedProof.lookup_budget] + +def proofAcceptanceClassicalRoots : Array Lean.Name := #[ + `Aiur.BoundVerifier.verifyShaped_success, + `Aiur.BoundVerifier.verifyShaped_acceptance] + +def proofAcceptancePremises : Array Lean.Name := #[ + `Aiur.NativeAIR.ProofCodec.Extension.mk, + `Aiur.NativeAIR.ProofCodec.Digest, + `Aiur.NativeAIR.ProofCodec.Cap, + `Aiur.NativeAIR.ProofCodec.Openings, + `Aiur.NativeAIR.ProofCodec.readVector, + `Aiur.NativeAIR.ProofCodec.encodeVector, + `Aiur.NativeAIR.ProofCodec.readOption, + `Aiur.NativeAIR.ProofCodec.encodeOption, + `Aiur.NativeAIR.ProofCodec.readBool, + `Aiur.NativeAIR.ProofCodec.encodeBool, + `Aiur.NativeAIR.ProofCodec.readField, + `Aiur.NativeAIR.ProofCodec.encodeField, + `Aiur.NativeAIR.ProofCodec.readExtension, + `Aiur.NativeAIR.ProofCodec.encodeExtension, + `Aiur.NativeAIR.ProofCodec.readCap, + `Aiur.NativeAIR.ProofCodec.encodeCap, + `Aiur.NativeAIR.ProofCodec.readOpenings, + `Aiur.NativeAIR.ProofCodec.encodeOpenings, + `Aiur.NativeAIR.ProofCodec.Commitments.mk, + `Aiur.NativeAIR.ProofCodec.readCommitments, + `Aiur.NativeAIR.ProofCodec.encodeCommitments, + `Aiur.NativeAIR.ProofCodec.BatchOpening.mk, + `Aiur.NativeAIR.ProofCodec.readBatchOpening, + `Aiur.NativeAIR.ProofCodec.encodeBatchOpening, + `Aiur.NativeAIR.ProofCodec.CommitStep.mk, + `Aiur.NativeAIR.ProofCodec.readCommitStep, + `Aiur.NativeAIR.ProofCodec.encodeCommitStep, + `Aiur.NativeAIR.ProofCodec.Fri.mk, + `Aiur.NativeAIR.ProofCodec.readFri, + `Aiur.NativeAIR.ProofCodec.encodeFri, + `Aiur.NativeAIR.ProofCodec.Data.mk, + `Aiur.NativeAIR.ProofCodec.readData, + `Aiur.NativeAIR.ProofCodec.encodeData, + `Aiur.NativeAIR.ProofCodec.decode, + `Aiur.NativeAIR.ProofCodec.encode, + `Aiur.NativeAIR.ProofCodec.decodeCanonical, + `Aiur.NativeAIR.ProofShape.Pair.mk, + `Aiur.NativeAIR.ProofShape.pair, + `Aiur.NativeAIR.ProofShape.single, + `Aiur.NativeAIR.ProofShape.activeIndices, + `Aiur.NativeAIR.ProofShape.quotientDegree, + `Aiur.NativeAIR.ProofShape.Row.mk, + `Aiur.NativeAIR.ProofShape.readPreprocessed, + `Aiur.NativeAIR.ProofShape.readRow, + `Aiur.NativeAIR.ProofShape.Pair.hasWidth, + `Aiur.NativeAIR.ProofShape.Row.fits, + `Aiur.NativeAIR.ProofShape.header, + `Aiur.NativeAIR.ProofShape.inactivePreprocessed, + `Aiur.NativeAIR.ProofShape.rows, + `Aiur.NativeAIR.ProofShape.check, + `Aiur.NativeAIR.ProofShape.fixedHeights, + `Aiur.NativeAIR.ProofShape.queryBound, + `Aiur.BoundVerifier.CheckedProof.mk, + `Aiur.BoundVerifier.readProof, + `Aiur.BoundVerifier.verifyShaped, + `Aiur.NativeAIR.ProofCodec.VectorFits, + `Aiur.NativeAIR.ProofCodec.CapFits, + `Aiur.NativeAIR.ProofCodec.OpeningsFits, + `Aiur.NativeAIR.ProofCodec.CommitmentsFits.mk, + `Aiur.NativeAIR.ProofCodec.BatchOpeningFits.mk, + `Aiur.NativeAIR.ProofCodec.CommitStepFits.mk, + `Aiur.NativeAIR.ProofCodec.FriFits.mk, + `Aiur.NativeAIR.ProofCodec.DataFits.mk, + `Aiur.NativeAIR.ProofShape.Row.Sourced.mk, + `Aiur.NativeAIR.ProofShape.Row.Fits.mk] + +def extensionRoots : Array Lean.Name := #[ + `Aiur.G.residue_injective, + `Aiur.G.residue_ofNat, + `Aiur.G.residue_add, + `Aiur.G.residue_mul, + `Aiur.G.residue_sub, + `Aiur.G.residue_numeral, + `Aiur.G.residue_zero, + `Aiur.G.residue_one, + `Aiur.G.residue_neg, + `Aiur.G.residue_ofInt, + `Aiur.G.left_distrib, + `Aiur.G.neg_add_cancel, + `Aiur.G.sub_eq_add_neg, + `Aiur.G.ofInt_neg, + `Aiur.G.neg_mul, + `Aiur.G.pow_go_eq, + `Aiur.G.pow_eq, + `Aiur.G.inverse_eq_power, + `Aiur.G.n_power, + `Aiur.G.mul_right_cancel, + `Aiur.G.nonzeroResidues_length, + `Aiur.G.mem_nonzeroResidues, + `Aiur.G.nonzeroResidues_nodup, + `Aiur.G.map_perm_of_injective, + `Aiur.G.multiplication_perm, + `Aiur.G.product_nonzero, + `Aiur.G.product_perm, + `Aiur.G.product_map_mul, + `Aiur.G.power_eq_one_of_perm, + `Aiur.G.fermat, + `Aiur.G.inverse_zero, + `Aiur.G.mul_inverse_cancel, + `Aiur.NativeAIR.ProofCodec.Extension.ext, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_injective, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_add, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_sub, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_neg, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_mul, + `Aiur.NativeAIR.ProofCodec.Extension.add_zero, + `Aiur.NativeAIR.ProofCodec.Extension.add_comm, + `Aiur.NativeAIR.ProofCodec.Extension.add_assoc, + `Aiur.NativeAIR.ProofCodec.Extension.mul_one, + `Aiur.NativeAIR.ProofCodec.Extension.zero_mul, + `Aiur.NativeAIR.ProofCodec.Extension.mul_comm, + `Aiur.NativeAIR.ProofCodec.Extension.mul_assoc, + `Aiur.NativeAIR.ProofCodec.Extension.left_distrib, + `Aiur.NativeAIR.ProofCodec.Extension.neg_add_cancel, + `Aiur.NativeAIR.ProofCodec.Extension.sub_eq_add_neg, + `Aiur.NativeAIR.ProofCodec.Extension.neg_mul, + `Aiur.NativeAIR.ProofCodec.Extension.basis_square, + `Aiur.NativeAIR.ProofCodec.Extension.coordinates, + `Aiur.NativeAIR.ProofCodec.Extension.scale_eq_mul, + `Aiur.NativeAIR.ProofCodec.Extension.conjugate_conjugate, + `Aiur.NativeAIR.ProofCodec.Extension.mul_conjugate, + `Aiur.NativeAIR.ProofCodec.Extension.conjugate_mul, + `Aiur.NativeAIR.ProofCodec.Extension.norm_mul, + `Aiur.NativeAIR.ProofCodec.Extension.evalLaws, + `Aiur.NativeAIR.ProofCodec.Extension.powBits_eq, + `Aiur.NativeAIR.ProofCodec.Extension.power_eq, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_power, + `Aiur.NativeAIR.ProofCodec.Extension.inverse_formula, + `Aiur.G.seven_euler_certificate, + `Aiur.G.seven_not_square, + `Aiur.G.square_ratio, + `Aiur.NativeAIR.ProofCodec.Extension.norm_zero_iff, + `Aiur.NativeAIR.ProofCodec.Extension.mul_eq_zero_iff, + `Aiur.NativeAIR.ProofCodec.Extension.one_ne_zero, + `Aiur.NativeAIR.ProofCodec.Extension.mul_left_cancel, + `Aiur.NativeAIR.ProofCodec.Extension.inverse_correct, + `Aiur.NativeAIR.ProofCodec.Extension.tryInverse_none_iff, + `Aiur.NativeAIR.ProofCodec.Extension.tryInverse_some_iff] + +def extensionAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.G.residue_injective, + `Aiur.NativeAIR.ProofCodec.Extension.ext] + +def extensionQuotRoots : Array Lean.Name := #[ + `Aiur.G.mem_nonzeroResidues, + `Aiur.G.nonzeroResidues_nodup, + `Aiur.NativeAIR.ProofCodec.Extension.add_comm, + `Aiur.NativeAIR.ProofCodec.Extension.conjugate_conjugate] + +def extensionClassicalRoots : Array Lean.Name := #[ + `Aiur.G.residue_neg, + `Aiur.G.residue_ofInt, + `Aiur.G.left_distrib, + `Aiur.G.neg_add_cancel, + `Aiur.G.sub_eq_add_neg, + `Aiur.G.ofInt_neg, + `Aiur.G.neg_mul, + `Aiur.G.pow_go_eq, + `Aiur.G.pow_eq, + `Aiur.G.inverse_eq_power, + `Aiur.G.n_power, + `Aiur.G.mul_right_cancel, + `Aiur.G.map_perm_of_injective, + `Aiur.G.multiplication_perm, + `Aiur.G.product_nonzero, + `Aiur.G.product_perm, + `Aiur.G.product_map_mul, + `Aiur.G.power_eq_one_of_perm, + `Aiur.G.fermat, + `Aiur.G.mul_inverse_cancel, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_add, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_sub, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_neg, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_mul, + `Aiur.NativeAIR.ProofCodec.Extension.mul_one, + `Aiur.NativeAIR.ProofCodec.Extension.zero_mul, + `Aiur.NativeAIR.ProofCodec.Extension.mul_comm, + `Aiur.NativeAIR.ProofCodec.Extension.mul_assoc, + `Aiur.NativeAIR.ProofCodec.Extension.left_distrib, + `Aiur.NativeAIR.ProofCodec.Extension.neg_add_cancel, + `Aiur.NativeAIR.ProofCodec.Extension.sub_eq_add_neg, + `Aiur.NativeAIR.ProofCodec.Extension.neg_mul, + `Aiur.NativeAIR.ProofCodec.Extension.coordinates, + `Aiur.NativeAIR.ProofCodec.Extension.scale_eq_mul, + `Aiur.NativeAIR.ProofCodec.Extension.mul_conjugate, + `Aiur.NativeAIR.ProofCodec.Extension.conjugate_mul, + `Aiur.NativeAIR.ProofCodec.Extension.norm_mul, + `Aiur.NativeAIR.ProofCodec.Extension.evalLaws, + `Aiur.NativeAIR.ProofCodec.Extension.powBits_eq, + `Aiur.NativeAIR.ProofCodec.Extension.power_eq, + `Aiur.NativeAIR.ProofCodec.Extension.ofBase_power, + `Aiur.NativeAIR.ProofCodec.Extension.inverse_formula, + `Aiur.G.seven_not_square, + `Aiur.G.square_ratio, + `Aiur.NativeAIR.ProofCodec.Extension.norm_zero_iff, + `Aiur.NativeAIR.ProofCodec.Extension.mul_eq_zero_iff, + `Aiur.NativeAIR.ProofCodec.Extension.mul_left_cancel, + `Aiur.NativeAIR.ProofCodec.Extension.inverse_correct, + `Aiur.NativeAIR.ProofCodec.Extension.tryInverse_some_iff] + +def extensionPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.ProofCodec.Extension.ofBase, + `Aiur.NativeAIR.ProofCodec.Extension.ofNat, + `Aiur.NativeAIR.ProofCodec.Extension.add, + `Aiur.NativeAIR.ProofCodec.Extension.sub, + `Aiur.NativeAIR.ProofCodec.Extension.neg, + `Aiur.NativeAIR.ProofCodec.Extension.mul, + `Aiur.NativeAIR.ProofCodec.Extension.basis, + `Aiur.NativeAIR.ProofCodec.Extension.conjugate, + `Aiur.NativeAIR.ProofCodec.Extension.norm, + `Aiur.NativeAIR.ProofCodec.Extension.scale, + `Aiur.NativeAIR.ProofCodec.Extension.powBits, + `Aiur.NativeAIR.ProofCodec.Extension.power, + `Aiur.NativeAIR.ProofCodec.Extension.tryInverse, + `Aiur.NativeAIR.ProofCodec.Extension.evalOps, + `Aiur.G.characteristicNeZero, + `Aiur.G.residue, + `Aiur.G.neg, + `Aiur.G.natCast, + `Aiur.G.ofInt, + `Aiur.G.intCast, + `Aiur.G.nsmul, + `Aiur.G.zsmul, + `Aiur.G.npow, + `Aiur.G.commRing, + `Aiur.G.nonzeroResidues, + `Aiur.G.product, + `Aiur.NativeAIR.ProofCodec.Extension.natCast, + `Aiur.NativeAIR.ProofCodec.Extension.intCast, + `Aiur.NativeAIR.ProofCodec.Extension.nsmul, + `Aiur.NativeAIR.ProofCodec.Extension.zsmul, + `Aiur.NativeAIR.ProofCodec.Extension.npow, + `Aiur.NativeAIR.ProofCodec.Extension.commRing] + +def logUpRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.LogUp.Coordinates.ext, + `Aiur.NativeAIR.LogUp.Coordinates.zero_iff, + `Aiur.NativeAIR.LogUp.Coordinates.flatten_length, + `Aiur.NativeAIR.LogUp.Coordinates.flatten_zero_iff, + `Aiur.NativeAIR.LogUp.Coordinates.mul_schoolbook, + `Aiur.NativeAIR.LogUp.Coordinates.add_zero, + `Aiur.NativeAIR.LogUp.Coordinates.add_comm, + `Aiur.NativeAIR.LogUp.Coordinates.add_assoc, + `Aiur.NativeAIR.LogUp.Coordinates.mul_one, + `Aiur.NativeAIR.LogUp.Coordinates.mul_zero, + `Aiur.NativeAIR.LogUp.Coordinates.mul_comm, + `Aiur.NativeAIR.LogUp.Coordinates.mul_assoc, + `Aiur.NativeAIR.LogUp.Coordinates.left_distrib, + `Aiur.NativeAIR.LogUp.Coordinates.neg_add_cancel, + `Aiur.NativeAIR.LogUp.Coordinates.sub_eq_add_neg, + `Aiur.NativeAIR.LogUp.Coordinates.ofBase_add, + `Aiur.NativeAIR.LogUp.Coordinates.ofBase_neg, + `Aiur.NativeAIR.LogUp.Coordinates.ofBase_mul, + `Aiur.NativeAIR.LogUp.Coordinates.neg_mul, + `Aiur.NativeAIR.LogUp.Coordinates.scale_eq_mul, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_injective, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_fromExtension, + `Aiur.NativeAIR.LogUp.Coordinates.fromExtension_toExtension, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_zero_iff, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_ofBase, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_add, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_sub, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_mul, + `Aiur.NativeAIR.LogUp.Coordinates.collapse_loses_constraint, + `Aiur.NativeAIR.LogUp.sub_zero_iff, + `Aiur.NativeAIR.LogUp.clears_cons, + `Aiur.NativeAIR.LogUp.product_cons, + `Aiur.NativeAIR.LogUp.product_append, + `Aiur.NativeAIR.LogUp.product_foldl, + `Aiur.NativeAIR.LogUp.sum_foldl, + `Aiur.NativeAIR.LogUp.sum_append, + `Aiur.NativeAIR.LogUp.telescope, + `Aiur.NativeAIR.LogUp.cyclic_accumulator, + `Aiur.NativeAIR.LogUp.final_accumulator, + `Aiur.NativeAIR.LogUp.prefix_products, + `Aiur.NativeAIR.LogUp.prefix_seeded, + `Aiur.NativeAIR.LogUp.suffix_seeded, + `Aiur.NativeAIR.LogUp.suffix_products, + `Aiur.NativeAIR.LogUp.prefixSuffixTerms_cons, + `Aiur.NativeAIR.LogUp.prefixSuffixTerms_sum, + `Aiur.NativeAIR.LogUp.groupEquation_polynomial, + `Aiur.NativeAIR.LogUp.numerator_append, + `Aiur.NativeAIR.LogUp.fingerprint_reverse_horner, + `Aiur.NativeAIR.LogUp.fingerprint_nil, + `Aiur.NativeAIR.LogUp.fingerprint_cons, + `Aiur.NativeAIR.LogUp.fingerprint_trailing_zero, + `Aiur.NativeAIR.LogUp.fingerprint_padding, + `Aiur.NativeAIR.LogUp.groupCount_positive, + `Aiur.NativeAIR.LogUp.groupCount_covers, + `Aiur.NativeAIR.LogUp.groupCount_zero, + `Aiur.NativeAIR.LogUp.groupCount_empty, + `Aiur.NativeAIR.LogUp.groupCount_key, + `Aiur.NativeAIR.LogUp.chunk_length, + `Aiur.NativeAIR.LogUp.chunks_take, + `Aiur.NativeAIR.LogUp.chunks_cover, + `Aiur.NativeAIR.LogUp.chunk_mem, + `Aiur.NativeAIR.LogUp.chunk_map, + `Aiur.NativeAIR.LogUp.mapM_some_reads, + `Aiur.NativeAIR.LogUp.mapM_defined, + `Aiur.NativeAIR.LogUp.read_coordinates_defined, + `Aiur.NativeAIR.LogUp.read_coordinates_success, + `Aiur.NativeAIR.LogUp.step_polynomial, + `Aiur.NativeAIR.LogUp.step_defined, + `Aiur.NativeAIR.LogUp.equations_success, + `Aiur.NativeAIR.LogUp.equations_defined, + `Aiur.NativeAIR.LogUp.equations_zero, + `Aiur.NativeAIR.LogUp.constraintValues_success, + `Aiur.NativeAIR.LogUp.constraintValues_length, + `Aiur.NativeAIR.LogUp.constraintValues_defined, + `Aiur.NativeAIR.LogUp.constraintValues_reflect, + `Aiur.NativeAIR.LogUp.inverseValue_correct, + `Aiur.NativeAIR.LogUp.product_nonzero, + `Aiur.NativeAIR.LogUp.poleFree_product, + `Aiur.NativeAIR.LogUp.fractionSum_cons, + `Aiur.NativeAIR.LogUp.fractionSum_append, + `Aiur.NativeAIR.LogUp.fractionSum_clears, + `Aiur.NativeAIR.LogUp.groupEquation_zero_iff, + `Aiur.NativeAIR.LogUp.product_toExtension, + `Aiur.NativeAIR.LogUp.fieldEntries_messages, + `Aiur.NativeAIR.LogUp.numerator_toExtension, + `Aiur.NativeAIR.LogUp.groupEquation_toExtension, + `Aiur.NativeAIR.LogUp.coordinate_group_zero_iff, + `Aiur.NativeAIR.LogUp.coordinate_polynomial_zero_iff, + `Aiur.NativeAIR.LogUp.fingerprint_toExtension, + `Aiur.NativeAIR.LogUp.pole_can_hide_step, + `Aiur.NativeAIR.LogUp.fractionSum_flatMap, + `Aiur.NativeAIR.LogUp.fieldEntries_compress_chunk, + `Aiur.NativeAIR.LogUp.lookupFractions_chunks, + `Aiur.NativeAIR.LogUp.equations_accumulator, + `Aiur.NativeAIR.LogUp.constraintValues_accumulator] + +def logUpAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.LogUp.Coordinates.ext, + `Aiur.NativeAIR.LogUp.Coordinates.zero_iff, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_injective, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_fromExtension, + `Aiur.NativeAIR.LogUp.Coordinates.fromExtension_toExtension, + `Aiur.NativeAIR.LogUp.product_cons, + `Aiur.NativeAIR.LogUp.fingerprint_nil, + `Aiur.NativeAIR.LogUp.fingerprint_cons, + `Aiur.NativeAIR.LogUp.groupCount_zero] + +def logUpQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.LogUp.Coordinates.flatten_length, + `Aiur.NativeAIR.LogUp.Coordinates.flatten_zero_iff, + `Aiur.NativeAIR.LogUp.prefix_seeded, + `Aiur.NativeAIR.LogUp.suffix_seeded, + `Aiur.NativeAIR.LogUp.suffix_products, + `Aiur.NativeAIR.LogUp.prefixSuffixTerms_cons, + `Aiur.NativeAIR.LogUp.fingerprint_reverse_horner, + `Aiur.NativeAIR.LogUp.groupCount_positive, + `Aiur.NativeAIR.LogUp.groupCount_empty, + `Aiur.NativeAIR.LogUp.mapM_some_reads, + `Aiur.NativeAIR.LogUp.mapM_defined, + `Aiur.NativeAIR.LogUp.read_coordinates_defined, + `Aiur.NativeAIR.LogUp.read_coordinates_success, + `Aiur.NativeAIR.LogUp.step_defined, + `Aiur.NativeAIR.LogUp.equations_success, + `Aiur.NativeAIR.LogUp.equations_defined, + `Aiur.NativeAIR.LogUp.constraintValues_success, + `Aiur.NativeAIR.LogUp.constraintValues_length, + `Aiur.NativeAIR.LogUp.constraintValues_defined, + `Aiur.NativeAIR.LogUp.constraintValues_reflect] + +def logUpClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.LogUp.Coordinates.mul_schoolbook, + `Aiur.NativeAIR.LogUp.Coordinates.add_zero, + `Aiur.NativeAIR.LogUp.Coordinates.add_comm, + `Aiur.NativeAIR.LogUp.Coordinates.add_assoc, + `Aiur.NativeAIR.LogUp.Coordinates.mul_one, + `Aiur.NativeAIR.LogUp.Coordinates.mul_zero, + `Aiur.NativeAIR.LogUp.Coordinates.mul_comm, + `Aiur.NativeAIR.LogUp.Coordinates.mul_assoc, + `Aiur.NativeAIR.LogUp.Coordinates.left_distrib, + `Aiur.NativeAIR.LogUp.Coordinates.neg_add_cancel, + `Aiur.NativeAIR.LogUp.Coordinates.sub_eq_add_neg, + `Aiur.NativeAIR.LogUp.Coordinates.ofBase_add, + `Aiur.NativeAIR.LogUp.Coordinates.ofBase_neg, + `Aiur.NativeAIR.LogUp.Coordinates.ofBase_mul, + `Aiur.NativeAIR.LogUp.Coordinates.neg_mul, + `Aiur.NativeAIR.LogUp.Coordinates.scale_eq_mul, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension_mul, + `Aiur.NativeAIR.LogUp.Coordinates.collapse_loses_constraint, + `Aiur.NativeAIR.LogUp.sub_zero_iff, + `Aiur.NativeAIR.LogUp.clears_cons, + `Aiur.NativeAIR.LogUp.product_append, + `Aiur.NativeAIR.LogUp.product_foldl, + `Aiur.NativeAIR.LogUp.sum_foldl, + `Aiur.NativeAIR.LogUp.sum_append, + `Aiur.NativeAIR.LogUp.telescope, + `Aiur.NativeAIR.LogUp.cyclic_accumulator, + `Aiur.NativeAIR.LogUp.final_accumulator, + `Aiur.NativeAIR.LogUp.prefix_products, + `Aiur.NativeAIR.LogUp.prefixSuffixTerms_sum, + `Aiur.NativeAIR.LogUp.groupEquation_polynomial, + `Aiur.NativeAIR.LogUp.numerator_append, + `Aiur.NativeAIR.LogUp.fingerprint_trailing_zero, + `Aiur.NativeAIR.LogUp.fingerprint_padding, + `Aiur.NativeAIR.LogUp.groupCount_covers, + `Aiur.NativeAIR.LogUp.chunks_take, + `Aiur.NativeAIR.LogUp.chunks_cover, + `Aiur.NativeAIR.LogUp.step_polynomial, + `Aiur.NativeAIR.LogUp.equations_zero, + `Aiur.NativeAIR.LogUp.inverseValue_correct, + `Aiur.NativeAIR.LogUp.product_nonzero, + `Aiur.NativeAIR.LogUp.poleFree_product, + `Aiur.NativeAIR.LogUp.fractionSum_append, + `Aiur.NativeAIR.LogUp.fractionSum_clears, + `Aiur.NativeAIR.LogUp.groupEquation_zero_iff, + `Aiur.NativeAIR.LogUp.product_toExtension, + `Aiur.NativeAIR.LogUp.numerator_toExtension, + `Aiur.NativeAIR.LogUp.groupEquation_toExtension, + `Aiur.NativeAIR.LogUp.coordinate_group_zero_iff, + `Aiur.NativeAIR.LogUp.coordinate_polynomial_zero_iff, + `Aiur.NativeAIR.LogUp.fingerprint_toExtension, + `Aiur.NativeAIR.LogUp.pole_can_hide_step, + `Aiur.NativeAIR.LogUp.fractionSum_flatMap, + `Aiur.NativeAIR.LogUp.lookupFractions_chunks, + `Aiur.NativeAIR.LogUp.equations_accumulator, + `Aiur.NativeAIR.LogUp.constraintValues_accumulator] + +def logUpPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.LogUp.Coordinates.mk, + `Aiur.NativeAIR.LogUp.Coordinates.ofBase, + `Aiur.NativeAIR.LogUp.Coordinates.ofNat, + `Aiur.NativeAIR.LogUp.Coordinates.add, + `Aiur.NativeAIR.LogUp.Coordinates.sub, + `Aiur.NativeAIR.LogUp.Coordinates.neg, + `Aiur.NativeAIR.LogUp.Coordinates.mul, + `Aiur.NativeAIR.LogUp.Coordinates.scale, + `Aiur.NativeAIR.LogUp.Coordinates.map, + `Aiur.NativeAIR.LogUp.Coordinates.read, + `Aiur.NativeAIR.LogUp.Coordinates.flatten, + `Aiur.NativeAIR.LogUp.Coordinates.toExtension, + `Aiur.NativeAIR.LogUp.Coordinates.fromExtension, + `Aiur.NativeAIR.LogUp.product, + `Aiur.NativeAIR.LogUp.sum, + `Aiur.NativeAIR.LogUp.numerator, + `Aiur.NativeAIR.LogUp.prefixSuffixTerms, + `Aiur.NativeAIR.LogUp.groupEquation, + `Aiur.NativeAIR.LogUp.fingerprint, + `Aiur.NativeAIR.LogUp.compress, + `Aiur.NativeAIR.LogUp.groupCount, + `Aiur.NativeAIR.LogUp.chunk, + `Aiur.NativeAIR.LogUp.step, + `Aiur.NativeAIR.LogUp.equations, + `Aiur.NativeAIR.LogUp.constraintValues, + `Aiur.NativeAIR.LogUp.Coordinates.natCast, + `Aiur.NativeAIR.LogUp.Coordinates.intCast, + `Aiur.NativeAIR.LogUp.Coordinates.nsmul, + `Aiur.NativeAIR.LogUp.Coordinates.zsmul, + `Aiur.NativeAIR.LogUp.Coordinates.npow, + `Aiur.NativeAIR.LogUp.Coordinates.commRing, + `Aiur.NativeAIR.LogUp.inverseValue, + `Aiur.NativeAIR.LogUp.fractionSum, + `Aiur.NativeAIR.LogUp.PoleFree, + `Aiur.NativeAIR.LogUp.fieldEntries, + `Aiur.NativeAIR.LogUp.lookupFractions] + +def domainRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Domain.generators_size, + `Aiur.NativeAIR.Domain.Algebra.power_zero, + `Aiur.NativeAIR.Domain.Algebra.power_mul, + `Aiur.NativeAIR.Domain.Algebra.power_period, + `Aiur.NativeAIR.Domain.Algebra.power_inverse, + `Aiur.NativeAIR.Domain.Algebra.predecessor_inverse, + `Aiur.NativeAIR.Domain.Algebra.dividedPowers_factor, + `Aiur.NativeAIR.Domain.Algebra.dividedPowers_diagonal, + `Aiur.NativeAIR.Domain.Algebra.root_dividedPowers, + `Aiur.NativeAIR.Domain.Algebra.dividedPowers_off_root, + `Aiur.NativeAIR.Domain.ofLogSize_some, + `Aiur.NativeAIR.Domain.ofLogSize_defined, + `Aiur.NativeAIR.Domain.size_positive, + `Aiur.NativeAIR.Domain.size_bound, + `Aiur.NativeAIR.Domain.size_lt_characteristic, + `Aiur.NativeAIR.Domain.size_lt_u64, + `Aiur.NativeAIR.Domain.generator_zero, + `Aiur.NativeAIR.Domain.generator_square_certificate, + `Aiur.NativeAIR.Domain.generator_full_certificate, + `Aiur.NativeAIR.Domain.generator_half_certificate, + `Aiur.NativeAIR.Domain.generator_power, + `Aiur.NativeAIR.Domain.generator_half, + `Aiur.NativeAIR.Domain.generator_nonzero, + `Aiur.NativeAIR.Domain.point_eq, + `Aiur.NativeAIR.Domain.point_injective, + `Aiur.NativeAIR.Domain.generator_order, + `Aiur.NativeAIR.Domain.point_zero, + `Aiur.NativeAIR.Domain.point_power, + `Aiur.NativeAIR.Domain.point_nonzero, + `Aiur.NativeAIR.Domain.point_next, + `Aiur.NativeAIR.Domain.point_first_iff, + `Aiur.NativeAIR.Domain.lastPoint_eq_power, + `Aiur.NativeAIR.Domain.point_last, + `Aiur.NativeAIR.Domain.lastPoint_power, + `Aiur.NativeAIR.Domain.point_last_iff, + `Aiur.NativeAIR.Domain.lastPoint_nonzero, + `Aiur.NativeAIR.Domain.lastPoint_inverse, + `Aiur.NativeAIR.Domain.lastPoint_predecessor, + `Aiur.NativeAIR.Domain.normalizer_nonzero, + `Aiur.NativeAIR.Domain.first_at_row, + `Aiur.NativeAIR.Domain.last_at_row, + `Aiur.NativeAIR.Domain.transition_at_row, + `Aiur.NativeAIR.Domain.ofBase_dividedPowers, + `Aiur.NativeAIR.Domain.vanishing_eq, + `Aiur.NativeAIR.Domain.vanishing_at_row, + `Aiur.NativeAIR.Domain.lastPoint_extension_power, + `Aiur.NativeAIR.Domain.root_difference_nonzero, + `Aiur.NativeAIR.Domain.selectors_success, + `Aiur.NativeAIR.Domain.selectors_defined, + `Aiur.NativeAIR.Domain.selectors_defined_iff, + `Aiur.NativeAIR.Domain.selectors_none_at_row, + `Aiur.NativeAIR.LogUp.normalized_injection, + `Aiur.NativeAIR.LogUp.equations_domain_row, + `Aiur.NativeAIR.LogUp.equations_domain_sum, + `Aiur.NativeAIR.LogUp.constraintValues_domain_sum, + `Aiur.NativeAIR.Quotient.horner_nil, + `Aiur.NativeAIR.Quotient.horner_cons, + `Aiur.NativeAIR.Quotient.horner_append, + `Aiur.NativeAIR.Quotient.horner_powers, + `Aiur.NativeAIR.Quotient.composition_from, + `Aiur.NativeAIR.Quotient.composition_horner, + `Aiur.NativeAIR.Quotient.composition_order, + `Aiur.NativeAIR.Quotient.composition_append, + `Aiur.NativeAIR.Quotient.composition_zero, + `Aiur.NativeAIR.Quotient.inverse_check, + `Aiur.NativeAIR.Quotient.coefficients_flatten, + `Aiur.NativeAIR.Quotient.coefficients_success, + `Aiur.NativeAIR.Quotient.coefficients_length, + `Aiur.NativeAIR.Quotient.coefficients_defined, + `Aiur.NativeAIR.Quotient.coefficients_defined_iff, + `Aiur.NativeAIR.Quotient.evaluate_success, + `Aiur.NativeAIR.Quotient.evaluate_powers, + `Aiur.NativeAIR.Quotient.check_true_iff] + +def domainAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Domain.ofLogSize_some, + `Aiur.NativeAIR.Domain.size_positive, + `Aiur.NativeAIR.Quotient.horner_nil, + `Aiur.NativeAIR.Quotient.horner_cons] + +def domainQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Domain.Algebra.power_zero, + `Aiur.NativeAIR.Domain.size_bound, + `Aiur.NativeAIR.Domain.size_lt_characteristic, + `Aiur.NativeAIR.Domain.size_lt_u64, + `Aiur.NativeAIR.Domain.generator_square_certificate, + `Aiur.NativeAIR.Domain.generator_half_certificate, + `Aiur.NativeAIR.Quotient.coefficients_success, + `Aiur.NativeAIR.Quotient.coefficients_length] + +def domainClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Domain.Algebra.predecessor_inverse, + `Aiur.NativeAIR.Domain.Algebra.dividedPowers_factor, + `Aiur.NativeAIR.Domain.Algebra.dividedPowers_diagonal, + `Aiur.NativeAIR.Domain.Algebra.root_dividedPowers, + `Aiur.NativeAIR.Domain.Algebra.dividedPowers_off_root, + `Aiur.NativeAIR.Domain.generator_power, + `Aiur.NativeAIR.Domain.generator_half, + `Aiur.NativeAIR.Domain.generator_nonzero, + `Aiur.NativeAIR.Domain.point_eq, + `Aiur.NativeAIR.Domain.point_injective, + `Aiur.NativeAIR.Domain.generator_order, + `Aiur.NativeAIR.Domain.point_zero, + `Aiur.NativeAIR.Domain.point_power, + `Aiur.NativeAIR.Domain.point_nonzero, + `Aiur.NativeAIR.Domain.point_next, + `Aiur.NativeAIR.Domain.point_first_iff, + `Aiur.NativeAIR.Domain.lastPoint_eq_power, + `Aiur.NativeAIR.Domain.point_last, + `Aiur.NativeAIR.Domain.lastPoint_power, + `Aiur.NativeAIR.Domain.point_last_iff, + `Aiur.NativeAIR.Domain.lastPoint_nonzero, + `Aiur.NativeAIR.Domain.lastPoint_inverse, + `Aiur.NativeAIR.Domain.lastPoint_predecessor, + `Aiur.NativeAIR.Domain.normalizer_nonzero, + `Aiur.NativeAIR.Domain.first_at_row, + `Aiur.NativeAIR.Domain.last_at_row, + `Aiur.NativeAIR.Domain.transition_at_row, + `Aiur.NativeAIR.Domain.ofBase_dividedPowers, + `Aiur.NativeAIR.Domain.vanishing_eq, + `Aiur.NativeAIR.Domain.vanishing_at_row, + `Aiur.NativeAIR.Domain.lastPoint_extension_power, + `Aiur.NativeAIR.Domain.root_difference_nonzero, + `Aiur.NativeAIR.Domain.selectors_success, + `Aiur.NativeAIR.Domain.selectors_defined, + `Aiur.NativeAIR.Domain.selectors_defined_iff, + `Aiur.NativeAIR.Domain.selectors_none_at_row, + `Aiur.NativeAIR.LogUp.normalized_injection, + `Aiur.NativeAIR.LogUp.equations_domain_row, + `Aiur.NativeAIR.LogUp.equations_domain_sum, + `Aiur.NativeAIR.LogUp.constraintValues_domain_sum, + `Aiur.NativeAIR.Quotient.horner_append, + `Aiur.NativeAIR.Quotient.horner_powers, + `Aiur.NativeAIR.Quotient.composition_from, + `Aiur.NativeAIR.Quotient.composition_horner, + `Aiur.NativeAIR.Quotient.composition_order, + `Aiur.NativeAIR.Quotient.composition_append, + `Aiur.NativeAIR.Quotient.composition_zero, + `Aiur.NativeAIR.Quotient.inverse_check, + `Aiur.NativeAIR.Quotient.coefficients_defined, + `Aiur.NativeAIR.Quotient.coefficients_defined_iff, + `Aiur.NativeAIR.Quotient.evaluate_success, + `Aiur.NativeAIR.Quotient.evaluate_powers, + `Aiur.NativeAIR.Quotient.check_true_iff] + +def domainPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.Domain.generators, + `Aiur.NativeAIR.Domain.Subgroup, + `Aiur.NativeAIR.Domain.ofLogSize, + `Aiur.NativeAIR.Domain.size, + `Aiur.NativeAIR.Domain.generator, + `Aiur.NativeAIR.Domain.point, + `Aiur.NativeAIR.Domain.lastPoint, + `Aiur.NativeAIR.Domain.normalizer, + `Aiur.NativeAIR.Domain.Selectors.mk, + `Aiur.NativeAIR.Domain.vanishing, + `Aiur.NativeAIR.Domain.selectors, + `Aiur.NativeAIR.Quotient.horner, + `Aiur.NativeAIR.Quotient.composition, + `Aiur.NativeAIR.Quotient.coefficients, + `Aiur.NativeAIR.Quotient.evaluate, + `Aiur.NativeAIR.Quotient.check, + `Aiur.NativeAIR.Domain.Algebra.dividedPowers] + +def verifierArithmeticRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.CompiledKey.preprocessedIndices_none, + `Aiur.NativeAIR.CompiledKey.circuits_preprocessed_absent, + `Aiur.BoundVerifier.CompiledBackend.row_preprocessed_absent, + `Aiur.NativeAIR.VerifierArithmetic.publics_size, + `Aiur.NativeAIR.VerifierArithmetic.publics_beta, + `Aiur.NativeAIR.VerifierArithmetic.publics_gamma, + `Aiur.NativeAIR.VerifierArithmetic.publics_entering, + `Aiur.NativeAIR.VerifierArithmetic.publics_leaving, + `Aiur.NativeAIR.VerifierArithmetic.deltaScaled_size, + `Aiur.NativeAIR.VerifierArithmetic.deltaScaled_coordinates, + `Aiur.NativeAIR.VerifierArithmetic.view_fits, + `Aiur.NativeAIR.VerifierArithmetic.domain_defined, + `Aiur.NativeAIR.VerifierArithmetic.stage2_width, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_success, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.evaluate, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_defined, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_defined_iff, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_constraint_count, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_reflects, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.identity, + `Aiur.NativeAIR.VerifierArithmetic.check_true_iff, + `Aiur.NativeAIR.VerifierArithmetic.check_quotient, + `Aiur.BoundVerifier.CompiledBackend.checked_row_arithmetic, + `Aiur.NativeAIR.VerifierArithmetic.claimMessage_native, + `Aiur.NativeAIR.VerifierArithmetic.publicEntries_compress, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_nil, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_cons, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_success, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_defined, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_defined_iff, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_lookupFractions, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_cons, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_final, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_row, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_sum, + `Aiur.NativeAIR.VerifierArithmetic.verify_true_iff, + `Aiur.NativeAIR.VerifierArithmetic.verify_lookup_balance, + `Aiur.NativeAIR.VerifierArithmetic.verify_row, + `Aiur.BoundVerifier.CompiledBackend.checked_row_values] + +def verifierArithmeticAxiomFreeRoots : Array Lean.Name := #[] + +def verifierArithmeticQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.VerifierArithmetic.view_fits, + `Aiur.NativeAIR.VerifierArithmetic.domain_defined, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_success, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.evaluate, + `Aiur.NativeAIR.VerifierArithmetic.check_quotient, + `Aiur.NativeAIR.VerifierArithmetic.publicEntries_compress, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_cons, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_cons, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_final, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_row, + `Aiur.NativeAIR.VerifierArithmetic.verify_true_iff] + +def verifierArithmeticClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.CompiledKey.circuits_preprocessed_absent, + `Aiur.BoundVerifier.CompiledBackend.row_preprocessed_absent, + `Aiur.NativeAIR.VerifierArithmetic.deltaScaled_coordinates, + `Aiur.NativeAIR.VerifierArithmetic.stage2_width, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_defined, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_defined_iff, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_constraint_count, + `Aiur.NativeAIR.VerifierArithmetic.evaluate_reflects, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.identity, + `Aiur.NativeAIR.VerifierArithmetic.check_true_iff, + `Aiur.BoundVerifier.CompiledBackend.checked_row_arithmetic, + `Aiur.NativeAIR.VerifierArithmetic.claimMessage_native, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_success, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_defined, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_defined_iff, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_lookupFractions, + `Aiur.NativeAIR.VerifierArithmetic.checkRows_sum, + `Aiur.NativeAIR.VerifierArithmetic.verify_lookup_balance, + `Aiur.NativeAIR.VerifierArithmetic.verify_row, + `Aiur.BoundVerifier.CompiledBackend.checked_row_values] + +def verifierArithmeticPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.VerifierArithmetic.Challenges.mk, + `Aiur.NativeAIR.VerifierArithmetic.pairColumns, + `Aiur.NativeAIR.VerifierArithmetic.rowColumns, + `Aiur.NativeAIR.VerifierArithmetic.publics, + `Aiur.NativeAIR.VerifierArithmetic.deltaScaled, + `Aiur.NativeAIR.VerifierArithmetic.view, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.mk, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.constraints, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.accepts, + `Aiur.NativeAIR.VerifierArithmetic.evaluate, + `Aiur.NativeAIR.VerifierArithmetic.check, + `Aiur.NativeAIR.VerifierArithmetic.checkRows, + `Aiur.NativeAIR.VerifierArithmetic.claimMessage, + `Aiur.NativeAIR.VerifierArithmetic.initialAccumulator, + `Aiur.NativeAIR.VerifierArithmetic.verify, + `Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.mk, + `Aiur.NativeAIR.VerifierArithmetic.publicEntries] + +def transcriptRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Challenger.initial_valid, + `Aiur.NativeAIR.Challenger.State.Valid.bound, + `Aiur.NativeAIR.Challenger.observeBytes_nil, + `Aiur.NativeAIR.Challenger.observeBytes_append, + `Aiur.NativeAIR.Challenger.observeBytes_value, + `Aiur.NativeAIR.Challenger.observeBytes_fold, + `Aiur.NativeAIR.Challenger.observeBytes_valid, + `Aiur.NativeAIR.Challenger.observeField_value, + `Aiur.NativeAIR.Challenger.observeField_valid, + `Aiur.NativeAIR.Challenger.observeExtension_bytes, + `Aiur.NativeAIR.Challenger.observeExtension_valid, + `Aiur.NativeAIR.Challenger.observeExtensions_valid, + `Aiur.NativeAIR.Challenger.observeCap_empty, + `Aiur.NativeAIR.Challenger.observeCap_valid, + `Aiur.NativeAIR.Challenger.sampleByte_buffered, + `Aiur.NativeAIR.Challenger.sampleByte_refill, + `Aiur.NativeAIR.Challenger.sampleByte_valid, + `Aiur.NativeAIR.Challenger.digest_reverse, + `Aiur.NativeAIR.Challenger.sampleByte_pending_bound, + `Aiur.NativeAIR.Challenger.sampleBytes_length, + `Aiur.NativeAIR.Challenger.sampleBytes_pending_bound, + `Aiur.NativeAIR.Challenger.sampleBytes_valid, + `Aiur.NativeAIR.Challenger.sampleBytes_buffered, + `Aiur.NativeAIR.Challenger.sampleBytes_refill, + `Aiur.NativeAIR.Challenger.littleEndian_bound, + `Aiur.NativeAIR.Challenger.littleEndian_encode, + `Aiur.NativeAIR.Challenger.littleEndian_reads, + `Aiur.NativeAIR.Challenger.sampleWord_bound, + `Aiur.NativeAIR.Challenger.sampleWord_full_mask, + `Aiur.NativeAIR.Challenger.sampleWord_reads, + `Aiur.NativeAIR.Challenger.FieldSample.positive, + `Aiur.NativeAIR.Challenger.sampleField_success, + `Aiur.NativeAIR.Challenger.FieldSample.complete, + `Aiur.NativeAIR.Challenger.sampleField_iff, + `Aiur.NativeAIR.Challenger.sampleField_mono, + `Aiur.NativeAIR.Challenger.sampleField_unique, + `Aiur.NativeAIR.Challenger.FieldSample.valid, + `Aiur.NativeAIR.Challenger.sampleField_valid, + `Aiur.NativeAIR.Challenger.sampleField_canonical, + `Aiur.NativeAIR.Challenger.sampleExtension_success, + `Aiur.NativeAIR.Challenger.sampleExtension_mono, + `Aiur.NativeAIR.Challenger.sampleExtension_valid, + `Aiur.NativeAIR.Challenger.sampleBits_success, + `Aiur.NativeAIR.Challenger.sampleBits_zero, + `Aiur.NativeAIR.Challenger.sampleBits_mask, + `Aiur.NativeAIR.Challenger.sampleBits_valid, + `Aiur.NativeAIR.Challenger.checkWitness_zero, + `Aiur.NativeAIR.Challenger.checkWitness_positive, + `Aiur.NativeAIR.Challenger.checkWitness_true_iff, + `Aiur.NativeAIR.Challenger.checkWitness_valid, + `Aiur.NativeAIR.Transcript.seed_length, + `Aiur.NativeAIR.Transcript.circuitShape_length, + `Aiur.NativeAIR.Transcript.shape_length, + `Aiur.NativeAIR.Transcript.fieldsBytes_length, + `Aiur.NativeAIR.Transcript.observeFields_bytes, + `Aiur.NativeAIR.Transcript.claimsFields_framing, + `Aiur.NativeAIR.Transcript.lookupState_schedule, + `Aiur.NativeAIR.Transcript.lookupState_valid, + `Aiur.NativeAIR.Transcript.accumulatorState_valid, + `Aiur.NativeAIR.Transcript.replay_success, + `Aiur.NativeAIR.Transcript.Replay.Reads.complete, + `Aiur.NativeAIR.Transcript.replay_iff, + `Aiur.NativeAIR.Transcript.replay_mono, + `Aiur.NativeAIR.Transcript.replay_unique, + `Aiur.NativeAIR.Transcript.replay_valid, + `Aiur.NativeAIR.Transcript.verifyArithmetic_success, + `Aiur.NativeAIR.Transcript.verifyArithmetic_iff, + `Aiur.NativeAIR.Transcript.verifyArithmetic_mono, + `Aiur.BoundVerifier.CompiledBackend.transcript_row] + +def transcriptAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Challenger.initial_valid, + `Aiur.NativeAIR.Challenger.observeBytes_nil, + `Aiur.NativeAIR.Challenger.observeBytes_value, + `Aiur.NativeAIR.Challenger.observeBytes_valid, + `Aiur.NativeAIR.Challenger.observeField_value, + `Aiur.NativeAIR.Challenger.observeField_valid, + `Aiur.NativeAIR.Challenger.observeExtension_valid, + `Aiur.NativeAIR.Challenger.observeExtensions_valid, + `Aiur.NativeAIR.Challenger.observeCap_empty, + `Aiur.NativeAIR.Challenger.observeCap_valid, + `Aiur.NativeAIR.Transcript.accumulatorState_valid] + +def transcriptQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Challenger.State.Valid.bound, + `Aiur.NativeAIR.Challenger.digest_reverse, + `Aiur.NativeAIR.Challenger.sampleByte_pending_bound, + `Aiur.NativeAIR.Challenger.sampleBytes_pending_bound, + `Aiur.NativeAIR.Challenger.sampleBytes_refill, + `Aiur.NativeAIR.Challenger.littleEndian_bound, + `Aiur.NativeAIR.Challenger.sampleWord_bound, + `Aiur.NativeAIR.Challenger.FieldSample.positive, + `Aiur.NativeAIR.Challenger.sampleField_success, + `Aiur.NativeAIR.Challenger.FieldSample.complete, + `Aiur.NativeAIR.Challenger.sampleField_iff, + `Aiur.NativeAIR.Challenger.sampleField_mono, + `Aiur.NativeAIR.Challenger.sampleField_unique, + `Aiur.NativeAIR.Challenger.sampleField_valid, + `Aiur.NativeAIR.Challenger.sampleField_canonical, + `Aiur.NativeAIR.Challenger.sampleExtension_success, + `Aiur.NativeAIR.Challenger.sampleExtension_mono, + `Aiur.NativeAIR.Challenger.sampleExtension_valid, + `Aiur.NativeAIR.Challenger.checkWitness_true_iff, + `Aiur.NativeAIR.Challenger.checkWitness_valid, + `Aiur.NativeAIR.Transcript.shape_length, + `Aiur.NativeAIR.Transcript.fieldsBytes_length, + `Aiur.NativeAIR.Transcript.replay_success, + `Aiur.NativeAIR.Transcript.replay_iff, + `Aiur.NativeAIR.Transcript.replay_mono, + `Aiur.NativeAIR.Transcript.replay_unique, + `Aiur.NativeAIR.Transcript.replay_valid, + `Aiur.NativeAIR.Transcript.verifyArithmetic_success, + `Aiur.NativeAIR.Transcript.verifyArithmetic_iff, + `Aiur.NativeAIR.Transcript.verifyArithmetic_mono] + +def transcriptClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Challenger.sampleWord_full_mask, + `Aiur.NativeAIR.Challenger.sampleBits_mask, + `Aiur.BoundVerifier.CompiledBackend.transcript_row] + +def transcriptPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.Challenger.Hash32, + `Aiur.NativeAIR.Challenger.State.mk, + `Aiur.NativeAIR.Challenger.initial, + `Aiur.NativeAIR.Challenger.observeByte, + `Aiur.NativeAIR.Challenger.observeBytes, + `Aiur.NativeAIR.Challenger.observeField, + `Aiur.NativeAIR.Challenger.observeExtension, + `Aiur.NativeAIR.Challenger.observeCap, + `Aiur.NativeAIR.Challenger.sampleByte, + `Aiur.NativeAIR.Challenger.sampleBytes, + `Aiur.NativeAIR.Challenger.littleEndian, + `Aiur.NativeAIR.Challenger.sampleWord, + `Aiur.NativeAIR.Challenger.sampleField, + `Aiur.NativeAIR.Challenger.sampleExtension, + `Aiur.NativeAIR.Challenger.sampleBits, + `Aiur.NativeAIR.Challenger.checkWitness, + `Aiur.NativeAIR.Transcript.parameterWords, + `Aiur.NativeAIR.Transcript.seed, + `Aiur.NativeAIR.Transcript.circuitShape, + `Aiur.NativeAIR.Transcript.shape, + `Aiur.NativeAIR.Transcript.claimsFields, + `Aiur.NativeAIR.Transcript.fieldsBytes, + `Aiur.NativeAIR.Transcript.prefixBytes, + `Aiur.NativeAIR.Transcript.lookupState, + `Aiur.NativeAIR.Transcript.accumulatorState, + `Aiur.NativeAIR.Transcript.Replay.mk, + `Aiur.NativeAIR.Transcript.replay, + `Aiur.NativeAIR.Transcript.verifyArithmetic, + `Aiur.NativeAIR.Challenger.State.Valid, + `Aiur.NativeAIR.Challenger.FieldSample.accept, + `Aiur.NativeAIR.Challenger.FieldSample.reject, + `Aiur.NativeAIR.Transcript.Replay.Reads.mk] + +def blake3Roots : Array Lean.Name := #[ + `Aiur.NativeAIR.Blake3.leftLen_positive, + `Aiur.NativeAIR.Blake3.leftLen_lt, + `Aiur.NativeAIR.Blake3.schedules_permute, + `Aiur.NativeAIR.Blake3.schedules_next, + `Aiur.NativeAIR.Blake3.rotateRight_bits, + `Aiur.NativeAIR.Blake3.bytesWord_value, + `Aiur.NativeAIR.Blake3.wordBytes_encoding, + `Aiur.NativeAIR.Blake3.bytesWord_wordBytes, + `Aiur.NativeAIR.Blake3.bytesWord_pack, + `Aiur.NativeAIR.Blake3.wordBytes_pack, + `Aiur.NativeAIR.Blake3.wordBytes_bytesWord, + `Aiur.NativeAIR.Blake3.bytesWord_injective, + `Aiur.NativeAIR.Blake3.blockWords_byte, + `Aiur.NativeAIR.Blake3.blockWords_value, + `Aiur.NativeAIR.Blake3.cvBytes_value, + `Aiur.NativeAIR.Blake3.g_unchanged, + `Aiur.NativeAIR.Blake3.g_values, + `Aiur.NativeAIR.Blake3.initialWords_counter, + `Aiur.NativeAIR.Blake3.parentOutput_values, + `Aiur.NativeAIR.Blake3.leftLen_bounds, + `Aiur.NativeAIR.Blake3.leftLen_chunks, + `Aiur.NativeAIR.Blake3.leftLen_chunk_multiple, + `Aiur.NativeAIR.Blake3.leftLen_unique, + `Aiur.NativeAIR.Blake3.chunkLoop_small, + `Aiur.NativeAIR.Blake3.chunkLoop_step, + `Aiur.NativeAIR.Blake3.chunkLoop_counter, + `Aiur.NativeAIR.Blake3.chunkOutput_counter, + `Aiur.NativeAIR.Blake3.chunkLoop_reads, + `Aiur.NativeAIR.Blake3.ChunkReads.complete, + `Aiur.NativeAIR.Blake3.chunkLoop_iff, + `Aiur.NativeAIR.Blake3.ChunkReads.framing, + `Aiur.NativeAIR.Blake3.chunkOutput_framing, + `Aiur.NativeAIR.Blake3.subtree_small, + `Aiur.NativeAIR.Blake3.subtree_step, + `Aiur.NativeAIR.Blake3.subtree_root_counter, + `Aiur.NativeAIR.Blake3.subtree_tree, + `Aiur.NativeAIR.Blake3.TreeHash.complete, + `Aiur.NativeAIR.Blake3.subtree_iff, + `Aiur.NativeAIR.Blake3.TreeHash.unique, + `Aiur.NativeAIR.Blake3.native_counter, + `Aiur.NativeAIR.Blake3.native_child_spans, + `Aiur.NativeAIR.Blake3.ChunkAt.native, + `Aiur.NativeAIR.Blake3.digest_native_counters, + `Aiur.NativeAIR.Blake3.digest_tree, + `Aiur.NativeAIR.Blake3.replay_iff, + `Aiur.NativeAIR.Blake3.replay_unique, + `Aiur.NativeAIR.Blake3.verifyArithmetic_iff, + `Aiur.NativeAIR.Blake3.hash_bytes, + `Aiur.BoundVerifier.CompiledBackend.blake3_transcript_row] + +def blake3AxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Blake3.leftLen_positive] + +def blake3QuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Blake3.leftLen_lt, + `Aiur.NativeAIR.Blake3.schedules_next, + `Aiur.NativeAIR.Blake3.rotateRight_bits, + `Aiur.NativeAIR.Blake3.bytesWord_value, + `Aiur.NativeAIR.Blake3.bytesWord_pack, + `Aiur.NativeAIR.Blake3.g_unchanged, + `Aiur.NativeAIR.Blake3.g_values, + `Aiur.NativeAIR.Blake3.initialWords_counter, + `Aiur.NativeAIR.Blake3.parentOutput_values, + `Aiur.NativeAIR.Blake3.leftLen_bounds, + `Aiur.NativeAIR.Blake3.leftLen_chunks, + `Aiur.NativeAIR.Blake3.leftLen_chunk_multiple, + `Aiur.NativeAIR.Blake3.leftLen_unique, + `Aiur.NativeAIR.Blake3.chunkLoop_small, + `Aiur.NativeAIR.Blake3.chunkLoop_step, + `Aiur.NativeAIR.Blake3.chunkLoop_counter, + `Aiur.NativeAIR.Blake3.chunkOutput_counter, + `Aiur.NativeAIR.Blake3.chunkLoop_reads, + `Aiur.NativeAIR.Blake3.ChunkReads.complete, + `Aiur.NativeAIR.Blake3.chunkLoop_iff, + `Aiur.NativeAIR.Blake3.ChunkReads.framing, + `Aiur.NativeAIR.Blake3.subtree_small, + `Aiur.NativeAIR.Blake3.subtree_step, + `Aiur.NativeAIR.Blake3.subtree_root_counter, + `Aiur.NativeAIR.Blake3.subtree_tree, + `Aiur.NativeAIR.Blake3.TreeHash.complete, + `Aiur.NativeAIR.Blake3.subtree_iff, + `Aiur.NativeAIR.Blake3.TreeHash.unique, + `Aiur.NativeAIR.Blake3.native_counter, + `Aiur.NativeAIR.Blake3.digest_tree, + `Aiur.NativeAIR.Blake3.replay_iff, + `Aiur.NativeAIR.Blake3.replay_unique, + `Aiur.NativeAIR.Blake3.verifyArithmetic_iff] + +def blake3ClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Blake3.schedules_permute, + `Aiur.NativeAIR.Blake3.wordBytes_encoding, + `Aiur.NativeAIR.Blake3.bytesWord_wordBytes, + `Aiur.NativeAIR.Blake3.wordBytes_pack, + `Aiur.NativeAIR.Blake3.wordBytes_bytesWord, + `Aiur.NativeAIR.Blake3.bytesWord_injective, + `Aiur.NativeAIR.Blake3.blockWords_byte, + `Aiur.NativeAIR.Blake3.blockWords_value, + `Aiur.NativeAIR.Blake3.cvBytes_value, + `Aiur.NativeAIR.Blake3.chunkOutput_framing, + `Aiur.NativeAIR.Blake3.native_child_spans, + `Aiur.NativeAIR.Blake3.ChunkAt.native, + `Aiur.NativeAIR.Blake3.digest_native_counters, + `Aiur.NativeAIR.Blake3.hash_bytes, + `Aiur.BoundVerifier.CompiledBackend.blake3_transcript_row] + +def blake3Premises : Array Lean.Name := #[ + `Aiur.NativeAIR.Blake3.CV, + `Aiur.NativeAIR.Blake3.Block, + `Aiur.NativeAIR.Blake3.Digest, + `Aiur.NativeAIR.Blake3.iv, + `Aiur.NativeAIR.Blake3.schedules, + `Aiur.NativeAIR.Blake3.rotateRight, + `Aiur.NativeAIR.Blake3.mix, + `Aiur.NativeAIR.Blake3.g, + `Aiur.NativeAIR.Blake3.round, + `Aiur.NativeAIR.Blake3.initialWords, + `Aiur.NativeAIR.Blake3.compress, + `Aiur.NativeAIR.Blake3.wordBytes, + `Aiur.NativeAIR.Blake3.bytesWord, + `Aiur.NativeAIR.Blake3.blockWords, + `Aiur.NativeAIR.Blake3.cvBytes, + `Aiur.NativeAIR.Blake3.Output.mk, + `Aiur.NativeAIR.Blake3.Output.chainingValue, + `Aiur.NativeAIR.Blake3.Output.rootHash, + `Aiur.NativeAIR.Blake3.chunkLoop, + `Aiur.NativeAIR.Blake3.chunkOutput, + `Aiur.NativeAIR.Blake3.parentOutput, + `Aiur.NativeAIR.Blake3.leftLen, + `Aiur.NativeAIR.Blake3.subtree, + `Aiur.NativeAIR.Blake3.digest, + `Aiur.NativeAIR.Blake3.hash, + `Aiur.NativeAIR.Blake3.NativeInput, + `Aiur.NativeAIR.Blake3.replay, + `Aiur.NativeAIR.Blake3.verifyArithmetic, + `Aiur.NativeAIR.Blake3.ChunkReads.last, + `Aiur.NativeAIR.Blake3.ChunkReads.step, + `Aiur.NativeAIR.Blake3.TreeHash.chunk, + `Aiur.NativeAIR.Blake3.TreeHash.parent, + `Aiur.NativeAIR.Blake3.ChunkAt.leaf, + `Aiur.NativeAIR.Blake3.ChunkAt.left, + `Aiur.NativeAIR.Blake3.ChunkAt.right] + +def merkleCapRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.MerkleCap.maxDegree_nil, + `Aiur.NativeAIR.MerkleCap.maxDegree_cons, + `Aiur.NativeAIR.MerkleCap.degree_le_max, + `Aiur.NativeAIR.MerkleCap.maxDegree_le, + `Aiur.NativeAIR.MerkleCap.maxDegree_mono, + `Aiur.NativeAIR.MerkleCap.coverage_iff, + `Aiur.NativeAIR.MerkleCap.coverage_height_iff, + `Aiur.NativeAIR.MerkleCap.coverage_empty, + `Aiur.NativeAIR.MerkleCap.coverage_low_cap, + `Aiur.NativeAIR.MerkleCap.coverage_uniform, + `Aiur.NativeAIR.MerkleCap.coverage_subset, + `Aiur.NativeAIR.MerkleCap.coverage_injection, + `Aiur.NativeAIR.MerkleCap.coverage_cap_size, + `Aiur.NativeAIR.MerkleCap.omitted_rejected, + `Aiur.NativeAIR.MerkleCap.shorter_matrix_rejected, + `Aiur.NativeAIR.MerkleCap.exact_injection_accepted, + `Aiur.NativeAIR.MerkleCap.check_iff, + `Aiur.NativeAIR.MerkleCap.check_degree, + `Aiur.BoundVerifier.CheckedProof.cap_coverage, + `Aiur.BoundVerifier.CheckedProof.row_cap, + `Aiur.BoundVerifier.CheckedProof.row_injection, + `Aiur.BoundVerifier.verifyShaped_cap] + +def merkleCapAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.MerkleCap.maxDegree_nil, + `Aiur.NativeAIR.MerkleCap.maxDegree_cons, + `Aiur.NativeAIR.MerkleCap.coverage_empty, + `Aiur.NativeAIR.MerkleCap.shorter_matrix_rejected, + `Aiur.NativeAIR.MerkleCap.exact_injection_accepted] + +def merkleCapClassicalRoots : Array Lean.Name := #[ + `Aiur.BoundVerifier.verifyShaped_cap] + +def merkleCapPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.MerkleCap.maxDegree, + `Aiur.NativeAIR.MerkleCap.coverage, + `Aiur.NativeAIR.MerkleCap.check] + +def merkleRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Merkle.fieldsBytes_injective, + `Aiur.NativeAIR.Merkle.pairBytes_length, + `Aiur.NativeAIR.Merkle.pairBytes_injective, + `Aiur.NativeAIR.Merkle.branchBytes_injective, + `Aiur.NativeAIR.Merkle.shape_length, + `Aiur.NativeAIR.Merkle.rowsAt_absent, + `Aiur.NativeAIR.Merkle.rowsAt_injective, + `Aiur.NativeAIR.Merkle.rowBytes_injective, + `Aiur.NativeAIR.Merkle.CollisionOn.mono, + `Aiur.NativeAIR.Merkle.equal_of_no_collision, + `Aiur.NativeAIR.Merkle.step_calls, + `Aiur.NativeAIR.Merkle.walk_calls, + `Aiur.NativeAIR.Merkle.step_binding, + `Aiur.NativeAIR.Merkle.walk_binding, + `Aiur.NativeAIR.Merkle.replay_success, + `Aiur.NativeAIR.Merkle.replay_complete, + `Aiur.NativeAIR.Merkle.replay_calls, + `Aiur.NativeAIR.Merkle.replay_position, + `Aiur.NativeAIR.Merkle.replay_index_bound, + `Aiur.NativeAIR.Merkle.hasHeight_iff, + `Aiur.NativeAIR.Merkle.height_le_max, + `Aiur.NativeAIR.Merkle.covered_iff, + `Aiur.NativeAIR.Merkle.replay_binding, + `Aiur.NativeAIR.Merkle.verify_success, + `Aiur.NativeAIR.Merkle.verify_collision, + `Aiur.NativeAIR.Merkle.verifyCovered_collision, + `Aiur.NativeAIR.Merkle.blake3_collision, + `Aiur.NativeAIR.Merkle.branchBytes_length, + `Aiur.NativeAIR.Merkle.rowsAt_fields_le, + `Aiur.NativeAIR.Merkle.rowBytes_length_le, + `Aiur.NativeAIR.Merkle.step_input_length, + `Aiur.NativeAIR.Merkle.walk_input_length, + `Aiur.NativeAIR.Merkle.replay_input_length, + `Aiur.NativeAIR.Merkle.replay_native_input] + +def merkleAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Merkle.CollisionOn.mono, + `Aiur.NativeAIR.Merkle.equal_of_no_collision] + +def merkleQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Merkle.fieldsBytes_injective, + `Aiur.NativeAIR.Merkle.shape_length, + `Aiur.NativeAIR.Merkle.rowsAt_absent, + `Aiur.NativeAIR.Merkle.rowsAt_injective, + `Aiur.NativeAIR.Merkle.rowBytes_injective, + `Aiur.NativeAIR.Merkle.step_calls, + `Aiur.NativeAIR.Merkle.walk_calls, + `Aiur.NativeAIR.Merkle.walk_binding, + `Aiur.NativeAIR.Merkle.replay_success, + `Aiur.NativeAIR.Merkle.replay_complete, + `Aiur.NativeAIR.Merkle.replay_calls, + `Aiur.NativeAIR.Merkle.replay_position, + `Aiur.NativeAIR.Merkle.replay_index_bound, + `Aiur.NativeAIR.Merkle.hasHeight_iff, + `Aiur.NativeAIR.Merkle.height_le_max, + `Aiur.NativeAIR.Merkle.covered_iff, + `Aiur.NativeAIR.Merkle.replay_binding, + `Aiur.NativeAIR.Merkle.rowsAt_fields_le, + `Aiur.NativeAIR.Merkle.rowBytes_length_le, + `Aiur.NativeAIR.Merkle.step_input_length, + `Aiur.NativeAIR.Merkle.walk_input_length, + `Aiur.NativeAIR.Merkle.replay_input_length, + `Aiur.NativeAIR.Merkle.replay_native_input] + +def merkleClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Merkle.verify_success, + `Aiur.NativeAIR.Merkle.verify_collision, + `Aiur.NativeAIR.Merkle.verifyCovered_collision, + `Aiur.NativeAIR.Merkle.blake3_collision] + +def merklePremises : Array Lean.Name := #[ + `Aiur.NativeAIR.Merkle.Digest, + `Aiur.NativeAIR.Merkle.Hash, + `Aiur.NativeAIR.Merkle.Dimensions.mk, + `Aiur.NativeAIR.Merkle.maxHeight, + `Aiur.NativeAIR.Merkle.shape, + `Aiur.NativeAIR.Merkle.hasHeight, + `Aiur.NativeAIR.Merkle.rowsAt, + `Aiur.NativeAIR.Merkle.rowBytes, + `Aiur.NativeAIR.Merkle.pairBytes, + `Aiur.NativeAIR.Merkle.branchBytes, + `Aiur.NativeAIR.Merkle.Hashing.mk, + `Aiur.NativeAIR.Merkle.step, + `Aiur.NativeAIR.Merkle.walk, + `Aiur.NativeAIR.Merkle.Replay.mk, + `Aiur.NativeAIR.Merkle.replay, + `Aiur.NativeAIR.Merkle.accepts, + `Aiur.NativeAIR.Merkle.verify, + `Aiur.NativeAIR.Merkle.covered, + `Aiur.NativeAIR.Merkle.verifyCovered, + `Aiur.NativeAIR.Merkle.CollisionOn] + +def prunedMerkleRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Merkle.walk_append, + `Aiur.NativeAIR.PrunedMerkle.Logged.bind_success, + `Aiur.NativeAIR.PrunedMerkle.Logged.bind_input_left, + `Aiur.NativeAIR.PrunedMerkle.Logged.bind_input_right, + `Aiur.NativeAIR.PrunedMerkle.Logged.bind_if, + `Aiur.NativeAIR.PrunedMerkle.hashInput_value, + `Aiur.NativeAIR.PrunedMerkle.hashInput_inputs, + `Aiur.NativeAIR.PrunedMerkle.TicketAt.mono, + `Aiur.NativeAIR.PrunedMerkle.NodeAt.mono, + `Aiur.NativeAIR.PrunedMerkle.PendingAt.mono, + `Aiur.NativeAIR.PrunedMerkle.PendingNode.mono, + `Aiur.NativeAIR.PrunedMerkle.TicketAt.extend, + `Aiur.NativeAIR.PrunedMerkle.TicketAt.finish, + `Aiur.NativeAIR.PrunedMerkle.PendingAt.finish_absent, + `Aiur.NativeAIR.PrunedMerkle.PendingAt.finish_injected, + `Aiur.NativeAIR.PrunedMerkle.NodeAt.singleton, + `Aiur.NativeAIR.PrunedMerkle.NodeAt.pair, + `Aiur.NativeAIR.PrunedMerkle.origins_cons, + `Aiur.NativeAIR.PrunedMerkle.origins_extend, + `Aiur.NativeAIR.PrunedMerkle.combine_refines, + `Aiur.NativeAIR.PrunedMerkle.inject_refines, + `Aiur.NativeAIR.PrunedMerkle.initial_refines, + `Aiur.NativeAIR.PrunedMerkle.walk_refines, + `Aiur.NativeAIR.PrunedMerkle.mapM_members, + `Aiur.NativeAIR.PrunedMerkle.representatives_refines, + `Aiur.NativeAIR.PrunedMerkle.replay_refines, + `Aiur.NativeAIR.PrunedMerkle.replay_individual, + `Aiur.NativeAIR.PrunedMerkle.verify_individual, + `Aiur.NativeAIR.PrunedMerkle.verifyCovered_individual, + `Aiur.NativeAIR.PrunedMerkle.verify_collision, + `Aiur.NativeAIR.PrunedMerkle.verifyCovered_collision, + `Aiur.NativeAIR.PrunedMerkle.blake3_collision, + `Aiur.NativeAIR.PrunedMerkle.blake3_native_collision] + +def prunedMerkleAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.PrunedMerkle.hashInput_value, + `Aiur.NativeAIR.PrunedMerkle.hashInput_inputs, + `Aiur.NativeAIR.PrunedMerkle.origins_cons] + +def prunedMerkleQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Merkle.walk_append, + `Aiur.NativeAIR.PrunedMerkle.TicketAt.finish, + `Aiur.NativeAIR.PrunedMerkle.PendingAt.finish_absent, + `Aiur.NativeAIR.PrunedMerkle.PendingAt.finish_injected, + `Aiur.NativeAIR.PrunedMerkle.NodeAt.singleton, + `Aiur.NativeAIR.PrunedMerkle.NodeAt.pair, + `Aiur.NativeAIR.PrunedMerkle.combine_refines, + `Aiur.NativeAIR.PrunedMerkle.inject_refines, + `Aiur.NativeAIR.PrunedMerkle.initial_refines, + `Aiur.NativeAIR.PrunedMerkle.walk_refines, + `Aiur.NativeAIR.PrunedMerkle.mapM_members, + `Aiur.NativeAIR.PrunedMerkle.representatives_refines, + `Aiur.NativeAIR.PrunedMerkle.replay_refines, + `Aiur.NativeAIR.PrunedMerkle.replay_individual] + +def prunedMerkleClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.PrunedMerkle.verify_individual, + `Aiur.NativeAIR.PrunedMerkle.verifyCovered_individual, + `Aiur.NativeAIR.PrunedMerkle.verify_collision, + `Aiur.NativeAIR.PrunedMerkle.verifyCovered_collision, + `Aiur.NativeAIR.PrunedMerkle.blake3_collision, + `Aiur.NativeAIR.PrunedMerkle.blake3_native_collision] + +def prunedMerklePremises : Array Lean.Name := #[ + `Aiur.NativeAIR.PrunedMerkle.Logged.mk, + `Aiur.NativeAIR.PrunedMerkle.Logged.pure, + `Aiur.NativeAIR.PrunedMerkle.Logged.bind, + `Aiur.NativeAIR.PrunedMerkle.reject, + `Aiur.NativeAIR.PrunedMerkle.ofOption, + `Aiur.NativeAIR.PrunedMerkle.hashInput, + `Aiur.NativeAIR.PrunedMerkle.Ticket.mk, + `Aiur.NativeAIR.PrunedMerkle.Ticket.extend, + `Aiur.NativeAIR.PrunedMerkle.Node.mk, + `Aiur.NativeAIR.PrunedMerkle.uniqueIndices, + `Aiur.NativeAIR.PrunedMerkle.parentIndices, + `Aiur.NativeAIR.PrunedMerkle.boundaryCount, + `Aiur.NativeAIR.PrunedMerkle.representatives, + `Aiur.NativeAIR.PrunedMerkle.initial, + `Aiur.NativeAIR.PrunedMerkle.combine, + `Aiur.NativeAIR.PrunedMerkle.inject, + `Aiur.NativeAIR.PrunedMerkle.walk, + `Aiur.NativeAIR.PrunedMerkle.replay, + `Aiur.NativeAIR.PrunedMerkle.accepts, + `Aiur.NativeAIR.PrunedMerkle.verify, + `Aiur.NativeAIR.PrunedMerkle.verifyCovered, + `Aiur.NativeAIR.PrunedMerkle.TicketAt.mk, + `Aiur.NativeAIR.PrunedMerkle.NodeAt, + `Aiur.NativeAIR.PrunedMerkle.PendingAt, + `Aiur.NativeAIR.PrunedMerkle.PendingNode, + `Aiur.NativeAIR.PrunedMerkle.origins, + `Aiur.NativeAIR.PrunedMerkle.instMonadLogged] + +def extensionMmcsRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.ExtensionMmcs.baseRow_length, + `Aiur.NativeAIR.ExtensionMmcs.baseRow_injective, + `Aiur.NativeAIR.ExtensionMmcs.baseRows_length, + `Aiur.NativeAIR.ExtensionMmcs.baseRows_injective, + `Aiur.NativeAIR.ExtensionMmcs.baseRows_fields, + `Aiur.NativeAIR.ExtensionMmcs.baseDimensions_length, + `Aiur.NativeAIR.ExtensionMmcs.baseDimensions_heights, + `Aiur.NativeAIR.ExtensionMmcs.baseDimensions_maxHeight, + `Aiur.NativeAIR.ExtensionMmcs.baseDimensions_covered, + `Aiur.NativeAIR.ExtensionMmcs.baseDimensions_exact, + `Aiur.NativeAIR.ExtensionMmcs.shape_base, + `Aiur.NativeAIR.ExtensionMmcs.fri_width_fits, + `Aiur.NativeAIR.ExtensionMmcs.baseRows_query, + `Aiur.NativeAIR.ExtensionMmcs.replay_shape, + `Aiur.NativeAIR.ExtensionMmcs.verifyMulti_individual, + `Aiur.NativeAIR.ExtensionMmcs.verifyMulti_shape, + `Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered_individual, + `Aiur.NativeAIR.ExtensionMmcs.replay_native_input, + `Aiur.NativeAIR.ExtensionMmcs.verifyCovered_collision, + `Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered_collision, + `Aiur.NativeAIR.ExtensionMmcs.blake3_native_collision, + `Aiur.NativeAIR.ExtensionMmcs.blake3_multi_native_collision] + +def extensionMmcsAxiomFreeRoots : Array Lean.Name := #[] + +def extensionMmcsQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.ExtensionMmcs.baseRow_length, + `Aiur.NativeAIR.ExtensionMmcs.baseRow_injective, + `Aiur.NativeAIR.ExtensionMmcs.baseRows_injective, + `Aiur.NativeAIR.ExtensionMmcs.baseRows_fields, + `Aiur.NativeAIR.ExtensionMmcs.baseDimensions_exact, + `Aiur.NativeAIR.ExtensionMmcs.baseRows_query, + `Aiur.NativeAIR.ExtensionMmcs.replay_native_input] + +def extensionMmcsClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.ExtensionMmcs.shape_base, + `Aiur.NativeAIR.ExtensionMmcs.fri_width_fits, + `Aiur.NativeAIR.ExtensionMmcs.replay_shape, + `Aiur.NativeAIR.ExtensionMmcs.verifyMulti_individual, + `Aiur.NativeAIR.ExtensionMmcs.verifyMulti_shape, + `Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered_individual, + `Aiur.NativeAIR.ExtensionMmcs.verifyCovered_collision, + `Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered_collision, + `Aiur.NativeAIR.ExtensionMmcs.blake3_native_collision, + `Aiur.NativeAIR.ExtensionMmcs.blake3_multi_native_collision] + +def extensionMmcsPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.ExtensionMmcs.baseRow, + `Aiur.NativeAIR.ExtensionMmcs.baseRows, + `Aiur.NativeAIR.ExtensionMmcs.baseDimensions, + `Aiur.NativeAIR.ExtensionMmcs.WidthsFit, + `Aiur.NativeAIR.ExtensionMmcs.shape, + `Aiur.NativeAIR.ExtensionMmcs.replay, + `Aiur.NativeAIR.ExtensionMmcs.verify, + `Aiur.NativeAIR.ExtensionMmcs.verifyCovered, + `Aiur.NativeAIR.ExtensionMmcs.replayMulti, + `Aiur.NativeAIR.ExtensionMmcs.verifyMulti, + `Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered] + +def friDomainRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.FriDomain.reverseBits_bound, + `Aiur.NativeAIR.FriDomain.reverseBits_zero, + `Aiur.NativeAIR.FriDomain.reverseBits_zero_width, + `Aiur.NativeAIR.FriDomain.reverseBits_mod, + `Aiur.NativeAIR.FriDomain.reverseBits_involution, + `Aiur.NativeAIR.FriDomain.reverseBits_injective, + `Aiur.NativeAIR.FriDomain.reverseBits_surjective, + `Aiur.NativeAIR.FriDomain.index_split_bound, + `Aiur.NativeAIR.FriDomain.reverseBits_split, + `Aiur.NativeAIR.FriDomain.reverseBits_padding, + `Aiur.NativeAIR.FriDomain.wordReverse_eq, + `Aiur.NativeAIR.FriDomain.generator_nested, + `Aiur.NativeAIR.FriDomain.queryPoint_eq, + `Aiur.NativeAIR.FriDomain.queryPoint_domain, + `Aiur.NativeAIR.FriDomain.queryPoint_injective, + `Aiur.NativeAIR.FriDomain.queryPoint_surjective, + `Aiur.NativeAIR.FriDomain.queryPoint_nonzero, + `Aiur.NativeAIR.FriDomain.queryPoint_power, + `Aiur.NativeAIR.FriDomain.queryPoint_zero, + `Aiur.NativeAIR.FriDomain.queryPoint_padding, + `Aiur.NativeAIR.FriDomain.index_join_bound, + `Aiur.NativeAIR.FriDomain.reverseBits_join, + `Aiur.NativeAIR.FriDomain.foldNode_eq, + `Aiur.NativeAIR.FriDomain.foldNode_injective, + `Aiur.NativeAIR.FriDomain.foldNode_nonzero, + `Aiur.NativeAIR.FriDomain.foldNode_power, + `Aiur.NativeAIR.FriDomain.queryPoint_reduce, + `Aiur.NativeAIR.FriDomain.inputPoint_nonzero, + `Aiur.NativeAIR.FriDomain.inputPoint_injective, + `Aiur.NativeAIR.FriDomain.inputPoint_power, + `Aiur.NativeAIR.FriDomain.coset_shift_certificate, + `Aiur.NativeAIR.FriDomain.coset_shift_not_root, + `Aiur.NativeAIR.FriDomain.inputPoint_not_root, + `Aiur.NativeAIR.FriDomain.inputPoint_trace_disjoint] + +def friDomainQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.FriDomain.reverseBits_bound, + `Aiur.NativeAIR.FriDomain.reverseBits_zero, + `Aiur.NativeAIR.FriDomain.reverseBits_zero_width, + `Aiur.NativeAIR.FriDomain.reverseBits_mod, + `Aiur.NativeAIR.FriDomain.reverseBits_involution, + `Aiur.NativeAIR.FriDomain.reverseBits_injective, + `Aiur.NativeAIR.FriDomain.reverseBits_surjective, + `Aiur.NativeAIR.FriDomain.reverseBits_split, + `Aiur.NativeAIR.FriDomain.reverseBits_padding, + `Aiur.NativeAIR.FriDomain.wordReverse_eq, + `Aiur.NativeAIR.FriDomain.queryPoint_domain, + `Aiur.NativeAIR.FriDomain.queryPoint_surjective, + `Aiur.NativeAIR.FriDomain.index_join_bound, + `Aiur.NativeAIR.FriDomain.reverseBits_join] + +def friDomainClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.FriDomain.generator_nested, + `Aiur.NativeAIR.FriDomain.queryPoint_eq, + `Aiur.NativeAIR.FriDomain.queryPoint_injective, + `Aiur.NativeAIR.FriDomain.queryPoint_nonzero, + `Aiur.NativeAIR.FriDomain.queryPoint_power, + `Aiur.NativeAIR.FriDomain.queryPoint_zero, + `Aiur.NativeAIR.FriDomain.queryPoint_padding, + `Aiur.NativeAIR.FriDomain.foldNode_eq, + `Aiur.NativeAIR.FriDomain.foldNode_injective, + `Aiur.NativeAIR.FriDomain.foldNode_nonzero, + `Aiur.NativeAIR.FriDomain.foldNode_power, + `Aiur.NativeAIR.FriDomain.queryPoint_reduce, + `Aiur.NativeAIR.FriDomain.inputPoint_nonzero, + `Aiur.NativeAIR.FriDomain.inputPoint_injective, + `Aiur.NativeAIR.FriDomain.inputPoint_power, + `Aiur.NativeAIR.FriDomain.coset_shift_not_root, + `Aiur.NativeAIR.FriDomain.inputPoint_not_root, + `Aiur.NativeAIR.FriDomain.inputPoint_trace_disjoint] + +def friDomainPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.FriDomain.reverseBits, + `Aiur.NativeAIR.FriDomain.wordReverse, + `Aiur.NativeAIR.FriDomain.queryPoint, + `Aiur.NativeAIR.FriDomain.inputPoint, + `Aiur.NativeAIR.FriDomain.foldNode] + +def polynomialRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Polynomial.isZero_nil, + `Aiur.NativeAIR.Polynomial.isZero_iff_all, + `Aiur.NativeAIR.Polynomial.isZero_cons, + `Aiur.NativeAIR.Polynomial.isZero_append, + `Aiur.NativeAIR.Polynomial.monic_nonzero, + `Aiur.NativeAIR.Polynomial.sub_nil, + `Aiur.NativeAIR.Polynomial.horner_zero, + `Aiur.NativeAIR.Polynomial.add_length, + `Aiur.NativeAIR.Polynomial.sub_length, + `Aiur.NativeAIR.Polynomial.scale_length, + `Aiur.NativeAIR.Polynomial.sub_append, + `Aiur.NativeAIR.Polynomial.sub_append_left, + `Aiur.NativeAIR.Polynomial.horner_add, + `Aiur.NativeAIR.Polynomial.horner_neg, + `Aiur.NativeAIR.Polynomial.horner_sub, + `Aiur.NativeAIR.Polynomial.horner_scale, + `Aiur.NativeAIR.Polynomial.mulLinear_length, + `Aiur.NativeAIR.Polynomial.horner_mulLinear, + `Aiur.NativeAIR.Polynomial.fromRoots_length, + `Aiur.NativeAIR.Polynomial.horner_fromRoots, + `Aiur.NativeAIR.Polynomial.mulLinear_monic, + `Aiur.NativeAIR.Polynomial.fromRoots_monic, + `Aiur.NativeAIR.Polynomial.fromRoots_nonzero, + `Aiur.NativeAIR.Polynomial.fromRoots_vanishes, + `Aiur.NativeAIR.Polynomial.powerMinus_length, + `Aiur.NativeAIR.Polynomial.powerMinus_monic, + `Aiur.NativeAIR.Polynomial.horner_replicate_zero, + `Aiur.NativeAIR.Polynomial.horner_powerMinus, + `Aiur.NativeAIR.Polynomial.divide_length, + `Aiur.NativeAIR.Polynomial.divide_factor, + `Aiur.NativeAIR.Polynomial.zero_of_divide_zero, + `Aiur.NativeAIR.Polynomial.divide_nonzero, + `Aiur.NativeAIR.Polynomial.divide_root, + `Aiur.NativeAIR.Polynomial.roots_lt_length, + `Aiur.NativeAIR.Polynomial.roots_le_degree, + `Aiur.NativeAIR.Polynomial.zero_of_roots, + `Aiur.NativeAIR.Polynomial.zero_sub_of_samples, + `Aiur.NativeAIR.Polynomial.equal_of_samples, + `Aiur.NativeAIR.Polynomial.monic_zero_sub_of_samples, + `Aiur.NativeAIR.Polynomial.monic_equal_of_samples, + `Aiur.NativeAIR.Polynomial.root_product_identity, + `Aiur.NativeAIR.Polynomial.root_count_le, + `Aiur.NativeAIR.Polynomial.equal_count_le, + `Aiur.NativeAIR.Polynomial.base_roots_lt_length, + `Aiur.NativeAIR.Polynomial.extension_roots_lt_length, + `Aiur.NativeAIR.Polynomial.base_root_count_le, + `Aiur.NativeAIR.Polynomial.extension_root_count_le, + `Aiur.NativeAIR.Polynomial.foldingNodes_length, + `Aiur.NativeAIR.Polynomial.foldingNodes_nodup, + `Aiur.NativeAIR.Polynomial.foldingNodes_powers, + `Aiur.NativeAIR.Polynomial.folding_product_identity] + +def polynomialAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Polynomial.isZero_nil, + `Aiur.NativeAIR.Polynomial.sub_nil] + +def polynomialQuotRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Polynomial.isZero_iff_all, + `Aiur.NativeAIR.Polynomial.isZero_cons, + `Aiur.NativeAIR.Polynomial.horner_zero, + `Aiur.NativeAIR.Polynomial.sub_append_left, + `Aiur.NativeAIR.Polynomial.mulLinear_length, + `Aiur.NativeAIR.Polynomial.fromRoots_length, + `Aiur.NativeAIR.Polynomial.mulLinear_monic, + `Aiur.NativeAIR.Polynomial.fromRoots_monic, + `Aiur.NativeAIR.Polynomial.fromRoots_nonzero, + `Aiur.NativeAIR.Polynomial.powerMinus_length, + `Aiur.NativeAIR.Polynomial.powerMinus_monic, + `Aiur.NativeAIR.Polynomial.horner_replicate_zero, + `Aiur.NativeAIR.Polynomial.divide_length, + `Aiur.NativeAIR.Polynomial.zero_of_divide_zero, + `Aiur.NativeAIR.Polynomial.divide_nonzero, + `Aiur.NativeAIR.Polynomial.foldingNodes_length] + +def polynomialClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Polynomial.sub_append, + `Aiur.NativeAIR.Polynomial.horner_add, + `Aiur.NativeAIR.Polynomial.horner_neg, + `Aiur.NativeAIR.Polynomial.horner_sub, + `Aiur.NativeAIR.Polynomial.horner_scale, + `Aiur.NativeAIR.Polynomial.horner_mulLinear, + `Aiur.NativeAIR.Polynomial.horner_fromRoots, + `Aiur.NativeAIR.Polynomial.fromRoots_vanishes, + `Aiur.NativeAIR.Polynomial.horner_powerMinus, + `Aiur.NativeAIR.Polynomial.divide_factor, + `Aiur.NativeAIR.Polynomial.divide_root, + `Aiur.NativeAIR.Polynomial.roots_lt_length, + `Aiur.NativeAIR.Polynomial.roots_le_degree, + `Aiur.NativeAIR.Polynomial.zero_of_roots, + `Aiur.NativeAIR.Polynomial.zero_sub_of_samples, + `Aiur.NativeAIR.Polynomial.equal_of_samples, + `Aiur.NativeAIR.Polynomial.monic_zero_sub_of_samples, + `Aiur.NativeAIR.Polynomial.monic_equal_of_samples, + `Aiur.NativeAIR.Polynomial.root_product_identity, + `Aiur.NativeAIR.Polynomial.root_count_le, + `Aiur.NativeAIR.Polynomial.equal_count_le, + `Aiur.NativeAIR.Polynomial.base_roots_lt_length, + `Aiur.NativeAIR.Polynomial.extension_roots_lt_length, + `Aiur.NativeAIR.Polynomial.base_root_count_le, + `Aiur.NativeAIR.Polynomial.extension_root_count_le, + `Aiur.NativeAIR.Polynomial.foldingNodes_nodup, + `Aiur.NativeAIR.Polynomial.foldingNodes_powers, + `Aiur.NativeAIR.Polynomial.folding_product_identity] + +def polynomialPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.Polynomial.IsZero, + `Aiur.NativeAIR.Polynomial.Monic, + `Aiur.NativeAIR.Polynomial.add, + `Aiur.NativeAIR.Polynomial.sub, + `Aiur.NativeAIR.Polynomial.scale, + `Aiur.NativeAIR.Polynomial.mulLinear, + `Aiur.NativeAIR.Polynomial.fromRoots, + `Aiur.NativeAIR.Polynomial.powerMinus, + `Aiur.NativeAIR.Polynomial.divide, + `Aiur.NativeAIR.Polynomial.foldingNodes] + +def interpolationRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Interpolation.derivative_zero, + `Aiur.NativeAIR.Interpolation.derivative_neg, + `Aiur.NativeAIR.Interpolation.derivative_sub, + `Aiur.NativeAIR.Interpolation.divide_diagonal, + `Aiur.NativeAIR.Interpolation.monomial_value, + `Aiur.NativeAIR.Interpolation.monomial_derivative, + `Aiur.NativeAIR.Interpolation.powerMinus_derivative, + `Aiur.NativeAIR.Interpolation.root_product_derivative, + `Aiur.NativeAIR.Interpolation.root_quotient_diagonal, + `Aiur.NativeAIR.Interpolation.closed_weight_diagonal, + `Aiur.NativeAIR.Interpolation.combine_length, + `Aiur.NativeAIR.Interpolation.coefficients_length, + `Aiur.NativeAIR.Interpolation.combine_zero, + `Aiur.NativeAIR.Interpolation.combine_at_node, + `Aiur.NativeAIR.Interpolation.coefficients_at_node, + `Aiur.NativeAIR.Interpolation.coefficients_unique, + `Aiur.NativeAIR.Interpolation.coefficients_evaluate, + `Aiur.NativeAIR.Interpolation.divide_inverse_value, + `Aiur.NativeAIR.Interpolation.weightedSum_polynomial, + `Aiur.NativeAIR.Interpolation.evaluate_polynomial, + `Aiur.NativeAIR.Interpolation.foldSamples_roots, + `Aiur.NativeAIR.Interpolation.foldSamples_length, + `Aiur.NativeAIR.Interpolation.foldSamples_nodup, + `Aiur.NativeAIR.Interpolation.foldSamples_powers, + `Aiur.NativeAIR.Interpolation.foldScale_inverse, + `Aiur.NativeAIR.Interpolation.foldRow_polynomial, + `Aiur.NativeAIR.Interpolation.foldRow_reject_shape, + `Aiur.NativeAIR.Interpolation.foldRow_at_node, + `Aiur.NativeAIR.Interpolation.foldRow_evaluate, + `Aiur.NativeAIR.Interpolation.foldRow_success] + +def interpolationClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Interpolation.derivative_zero, + `Aiur.NativeAIR.Interpolation.derivative_neg, + `Aiur.NativeAIR.Interpolation.derivative_sub, + `Aiur.NativeAIR.Interpolation.divide_diagonal, + `Aiur.NativeAIR.Interpolation.monomial_value, + `Aiur.NativeAIR.Interpolation.monomial_derivative, + `Aiur.NativeAIR.Interpolation.powerMinus_derivative, + `Aiur.NativeAIR.Interpolation.root_product_derivative, + `Aiur.NativeAIR.Interpolation.root_quotient_diagonal, + `Aiur.NativeAIR.Interpolation.closed_weight_diagonal, + `Aiur.NativeAIR.Interpolation.combine_zero, + `Aiur.NativeAIR.Interpolation.combine_at_node, + `Aiur.NativeAIR.Interpolation.coefficients_at_node, + `Aiur.NativeAIR.Interpolation.coefficients_unique, + `Aiur.NativeAIR.Interpolation.coefficients_evaluate, + `Aiur.NativeAIR.Interpolation.divide_inverse_value, + `Aiur.NativeAIR.Interpolation.weightedSum_polynomial, + `Aiur.NativeAIR.Interpolation.evaluate_polynomial, + `Aiur.NativeAIR.Interpolation.foldSamples_nodup, + `Aiur.NativeAIR.Interpolation.foldSamples_powers, + `Aiur.NativeAIR.Interpolation.foldScale_inverse, + `Aiur.NativeAIR.Interpolation.foldRow_polynomial, + `Aiur.NativeAIR.Interpolation.foldRow_at_node, + `Aiur.NativeAIR.Interpolation.foldRow_evaluate, + `Aiur.NativeAIR.Interpolation.foldRow_success] + +def interpolationPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.Interpolation.derivativeValue, + `Aiur.NativeAIR.Interpolation.combine, + `Aiur.NativeAIR.Interpolation.coefficients, + `Aiur.NativeAIR.Interpolation.weightedSum, + `Aiur.NativeAIR.Interpolation.evaluate, + `Aiur.NativeAIR.Interpolation.foldSamples, + `Aiur.NativeAIR.Interpolation.foldScale, + `Aiur.NativeAIR.Interpolation.foldRow] + +def foldingRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Folding.horner_split, + `Aiur.NativeAIR.Folding.rowCoefficients_length, + `Aiur.NativeAIR.Folding.rowCoefficients_value, + `Aiur.NativeAIR.Folding.rowCoefficients_fold, + `Aiur.NativeAIR.Folding.foldCoefficients_degree, + `Aiur.NativeAIR.Folding.foldRow_global, + `Aiur.NativeAIR.Folding.foldRow_codeword, + `Aiur.NativeAIR.Folding.foldRow_codeword_degree, + `Aiur.NativeAIR.Folding.values_of_agreement, + `Aiur.NativeAIR.Folding.interpolant_values, + `Aiur.NativeAIR.Folding.interpolants_different, + `Aiur.NativeAIR.Folding.foldRow_equal_count_le] + +def foldingClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.Folding.horner_split, + `Aiur.NativeAIR.Folding.rowCoefficients_value, + `Aiur.NativeAIR.Folding.rowCoefficients_fold, + `Aiur.NativeAIR.Folding.foldRow_global, + `Aiur.NativeAIR.Folding.foldRow_codeword, + `Aiur.NativeAIR.Folding.foldRow_codeword_degree, + `Aiur.NativeAIR.Folding.interpolant_values, + `Aiur.NativeAIR.Folding.interpolants_different, + `Aiur.NativeAIR.Folding.foldRow_equal_count_le] + +def foldingPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.Folding.foldCoefficients, + `Aiur.NativeAIR.Folding.rowCoefficients] + +def friQueryRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.FriQuery.reconstruct_eq, + `Aiur.NativeAIR.FriQuery.reconstruct_success, + `Aiur.NativeAIR.FriQuery.reconstruct_length, + `Aiur.NativeAIR.FriQuery.reconstruct_self, + `Aiur.NativeAIR.FriQuery.reconstruct_siblings, + `Aiur.NativeAIR.FriQuery.step_success, + `Aiur.NativeAIR.FriQuery.step_dimensions, + `Aiur.NativeAIR.FriQuery.step_row, + `Aiur.NativeAIR.FriQuery.step_index_bound, + `Aiur.NativeAIR.FriQuery.step_self_sample, + `Aiur.NativeAIR.FriQuery.step_polynomial, + `Aiur.NativeAIR.FriQuery.step_global, + `Aiur.NativeAIR.FriQuery.roll_length, + `Aiur.NativeAIR.FriQuery.roll_empty, + `Aiur.NativeAIR.FriQuery.roll_matching, + `Aiur.NativeAIR.FriQuery.roll_other, + `Aiur.NativeAIR.FriQuery.roll_count, + `Aiur.NativeAIR.FriQuery.roll_order, + `Aiur.NativeAIR.FriQuery.walk_nil_success, + `Aiur.NativeAIR.FriQuery.walk_cons_success, + `Aiur.NativeAIR.FriQuery.walk_summary, + `Aiur.NativeAIR.FriQuery.walk_openings, + `Aiur.NativeAIR.FriQuery.run_success, + `Aiur.NativeAIR.FriQuery.run_summary, + `Aiur.NativeAIR.FriQuery.check_success, + `Aiur.NativeAIR.FriQuery.check_final_polynomial] + +def friQueryPropextRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.FriQuery.roll_empty] + +def friQueryClassicalRoots : Array Lean.Name := #[ + `Aiur.NativeAIR.FriQuery.reconstruct_eq, + `Aiur.NativeAIR.FriQuery.reconstruct_self, + `Aiur.NativeAIR.FriQuery.step_dimensions, + `Aiur.NativeAIR.FriQuery.step_row, + `Aiur.NativeAIR.FriQuery.step_index_bound, + `Aiur.NativeAIR.FriQuery.step_self_sample, + `Aiur.NativeAIR.FriQuery.step_polynomial, + `Aiur.NativeAIR.FriQuery.step_global, + `Aiur.NativeAIR.FriQuery.roll_matching, + `Aiur.NativeAIR.FriQuery.roll_count, + `Aiur.NativeAIR.FriQuery.roll_order, + `Aiur.NativeAIR.FriQuery.walk_summary, + `Aiur.NativeAIR.FriQuery.walk_openings, + `Aiur.NativeAIR.FriQuery.run_summary, + `Aiur.NativeAIR.FriQuery.check_final_polynomial] + +def friQueryPremises : Array Lean.Name := #[ + `Aiur.NativeAIR.FriQuery.reconstruct, + `Aiur.NativeAIR.FriQuery.State.mk, + `Aiur.NativeAIR.FriQuery.Round.mk, + `Aiur.NativeAIR.FriQuery.Row.mk, + `Aiur.NativeAIR.FriQuery.roll, + `Aiur.NativeAIR.FriQuery.StepResult.mk, + `Aiur.NativeAIR.FriQuery.step, + `Aiur.NativeAIR.FriQuery.Result.mk, + `Aiur.NativeAIR.FriQuery.walk, + `Aiur.NativeAIR.FriQuery.run, + `Aiur.NativeAIR.FriQuery.check] + +/-! The migration retains generic dynamic-rank extraction and makes that +layout premise explicit. Component relayout preserves evaluator behavior; +physical extraction for every component rank mode is a separate obligation. +Lookup retuning preserves authored fields and is included in key equality. -/ +def optimizedLayoutRoots : Array Lean.Name := #[ + `Aiur.AIR.callOrderConstraint_derived, + `Aiur.AIR.EquationAvailable.mono, + `Aiur.AIR.EquationAvailable.satisfied, + `Aiur.Bytecode.Op.allocationFor_empty, + `Aiur.Bytecode.Eval.SameCode.refl, + `Aiur.Bytecode.Eval.SameCode.ofFunctionsEq, + `Aiur.Bytecode.Eval.SameCode.trans, + `Aiur.Source.Toplevel.inlineCalls_componentRanks, + `Aiur.Concrete.Bytecode.opLayout_callRanks, + `Aiur.Concrete.Bytecode.opLayout_context, + `Aiur.Concrete.Bytecode.opsLayout_context, + `Aiur.Concrete.Bytecode.opsLayout_inputSize, + `Aiur.Concrete.Bytecode.blockLayout_eq_discard_relayout, + `Aiur.Concrete.Bytecode.ctrlLayout_eq_def, + `Aiur.Concrete.Bytecode.relayoutBlock_preserves_execution, + `Aiur.Concrete.Bytecode.relayoutCtrl_context, + `Aiur.Concrete.Bytecode.relayoutBlock_context, + `Aiur.Concrete.Bytecode.relayoutCtrl_inputSize, + `Aiur.Concrete.Bytecode.relayoutBlock_inputSize, + `Aiur.Concrete.Bytecode.relayoutCtrl_callRanks, + `Aiur.Concrete.Bytecode.relayoutBlock_callRanks, + `Aiur.Concrete.Bytecode.blockLayout_callRanks, + `Aiur.Concrete.Bytecode.ctrlLayout_callRanks, + `Aiur.Bytecode.Toplevel.withCallComponents_sameCode, + `Aiur.Concrete.Bytecode.opLayout_genericAllocation, + `Aiur.Concrete.Bytecode.allocationBranchStep_callRanks, + `Aiur.Concrete.Bytecode.allocationBranchFold_callRanks, + `Aiur.Concrete.Bytecode.layoutRenaming_empty, + `Aiur.NativeAIR.LookupGroups.withGroup_authored, + `Aiur.NativeAIR.LookupGroups.retune_authored] + +def optimizedLayoutPropextRoots : Array Lean.Name := #[ + `Aiur.AIR.EquationAvailable.mono, + `Aiur.AIR.EquationAvailable.satisfied, + `Aiur.Bytecode.Op.allocationFor_empty, + `Aiur.Concrete.Bytecode.layoutRenaming_empty] + +def optimizedLayoutQuotRoots : Array Lean.Name := #[ + `Aiur.AIR.callOrderConstraint_derived, + `Aiur.NativeAIR.LookupGroups.retune_authored] + +def optimizedLayoutPremises : Array Lean.Name := #[ + `Aiur.Bytecode.CallRank.zero, + `Aiur.Bytecode.CallRank.bound, + `Aiur.Bytecode.CallRank.ordered, + `Aiur.Bytecode.CallComponent.mk, + `Aiur.Bytecode.CallComponent.permits, + `Aiur.Bytecode.Toplevel.mk, + `Aiur.Bytecode.Toplevel.validCallComponents, + `Aiur.Bytecode.Toplevel.findCallComponents, + `Aiur.Bytecode.Toplevel.callRanksFor, + `Aiur.Bytecode.Toplevel.withCallComponents, + `Aiur.Bytecode.Op.allocationFor, + `Aiur.Concrete.Bytecode.LayoutMState.withCallRanks, + `Aiur.Concrete.Bytecode.LayoutMState.context, + `Aiur.Concrete.Bytecode.LayoutRenaming, + `Aiur.Concrete.Bytecode.relayoutCtrl, + `Aiur.Concrete.Bytecode.relayoutBlock, + `Aiur.AIR.EquationAvailable, + `Aiur.NativeAIR.LookupGroups.FftCost.mk, + `Aiur.NativeAIR.LookupGroups.checked128, + `Aiur.NativeAIR.LookupGroups.FftCost.make, + `Aiur.NativeAIR.LookupGroups.FftCost.noWorse, + `Aiur.NativeAIR.LookupGroups.FftCost.scoreLess, + `Aiur.NativeAIR.LookupGroups.quotientDegree, + `Aiur.NativeAIR.LookupGroups.withGroup, + `Aiur.NativeAIR.LookupGroups.selectGroup, + `Aiur.NativeAIR.LookupGroups.retune, + `Aiur.NativeAIR.LookupGroups.AuthoredFields] + +def roots : Array Lean.Name := optimizedLayoutRoots ++ #[ + `Aiur.G.ofNat_n, `Aiur.G.mul_one, `Aiur.G.mul_zero, + `Aiur.AIR.inactive_multiplicity_zero, + `Aiur.AIR.nonzero_multiplicity_active, `Aiur.AIR.active_satisfies, + `Aiur.Bytecode.Eval.runFunction_sameCode, + `Aiur.finishCompilation_sameCode, `Aiur.finishCompilation_reflects, + `Aiur.Source.Toplevel.compile_artifact_of_ok, + `Aiur.BoundVerifier.build, `Aiur.BoundVerifier.verify_success, + `Aiur.BoundVerifier.Backend.compilation_stages, + `Aiur.CompiledToplevel.groupFunctions_preserves_code, + `Aiur.CompiledToplevel.groupFunctions_sameCode, + `Aiur.CompiledToplevel.groupFunctions_preserves_execution, + `Aiur.BoundVerifier.Backend.reference_execution, + `Aiur.BoundVerifier.Backend.execution_reflects, + `Aiur.Bytecode.Ctrl.beq_eq_true_iff, + `Aiur.Bytecode.Block.beq_eq_true_iff, + `Aiur.Bytecode.Eval.runFunction_renamed_iff, + `Aiur.Bytecode.Eval.deduplicate_preserves_execution, + `Aiur.finishCompilation_preserves_execution, + `Aiur.finishCompilation_nameMap_image, + `Aiur.BoundVerifier.Backend.execution_reflects_raw, + `Aiur.Source.Eval.interp_restoreTailMatches, + `Aiur.Source.Eval.interp_wrapLets, + `Aiur.Source.Eval.evalFrames_append, + `Aiur.Source.Eval.interp_peelLets, + `Aiur.Source.Eval.interp_ret_wrapLets, + `Aiur.Source.Eval.interp_ioWrite_sequence, + `Aiur.Source.Eval.interp_debug_sequence, + `Aiur.Source.Eval.interp_assertEq_sequence, + `Aiur.Source.Eval.interp_ioSetInfo_sequence, + `Aiur.Source.Eval.interp_app_mode, + `Aiur.AIR.memoryPointerCycle_valid, + `Aiur.AIR.memoryPointerCycle_inconsistent] ++ callOrderRoots ++ lookupRoots ++ executionRoots ++ memoryRoots ++ + fieldRoots ++ localConstraintRoots ++ byteArithmeticRoots ++ byteLookupRoots ++ + lookupMessageRoots ++ lookupShapeRoots ++ globalLookupRoots ++ lookupBudgetRoots ++ + selectorControlRoots ++ operationRowRoots ++ blockRowRoots ++ querySlotRoots ++ circuitRowRoots ++ + rowCountRoots ++ circuitTableRoots ++ branchlessRoots ++ circuitTraceRoots ++ circuitMembershipRoots ++ lookupLayoutRoots ++ memoryColumnRoots ++ byteColumnRoots ++ expressionGraphRoots ++ frontendExpressionRoots ++ graphCompilationRoots ++ operationExpressionRoots ++ blockCircuitRoots ++ allocationRoots ++ circuitAllocationRoots ++ circuitCompletionRoots ++ checkedCircuitRoots ++ keyCodecRoots ++ compiledKeyRoots ++ proofAcceptanceRoots ++ extensionRoots ++ logUpRoots ++ domainRoots ++ verifierArithmeticRoots ++ transcriptRoots ++ blake3Roots ++ merkleCapRoots ++ merkleRoots ++ prunedMerkleRoots ++ extensionMmcsRoots ++ friDomainRoots ++ polynomialRoots ++ interpolationRoots ++ foldingRoots ++ friQueryRoots + +def premises : Array Lean.Name := optimizedLayoutPremises ++ #[ + `Aiur.AIR.activityConstraint, + `Aiur.Bytecode.Eval.SameCode.mk, + `Aiur.finishCompilation, + `Aiur.BoundVerifier.Selection.mk, + `Aiur.BoundVerifier.Selection.compile, + `Aiur.BoundVerifier.Selection.system, + `Aiur.BoundVerifier.Backend.mk, + `Aiur.BoundVerifier.verify, + `Aiur.CompiledToplevel.groupFunctions, + `Aiur.AIR.callRankBound, `Aiur.AIR.packRank, `Aiur.AIR.callOrderConstraint, + `Aiur.Concrete.Bytecode.LayoutMState.new, `Aiur.Concrete.Bytecode.opLayout, + `Aiur.AIR.suppliedWeight, `Aiur.AIR.ExactLookupBalance, + `Aiur.AIR.byteRangeMessage, `Aiur.AIR.byteRangeProviders, `Aiur.AIR.rankByteQueries, + `Aiur.Bytecode.instBEqCtrl, `Aiur.Bytecode.instBEqBlock, + `Aiur.Bytecode.instHashableCtrl, `Aiur.Bytecode.instHashableBlock, + `Aiur.Bytecode.Eval.RenamedCode.mk, + `Aiur.Bytecode.boundedRenaming, `Aiur.Bytecode.validatesRenaming, + `Aiur.Bytecode.checkedRenaming, `Aiur.Bytecode.Toplevel.deduplicate, + `Aiur.Bytecode.Toplevel.deduplicateCandidate, + `Aiur.Source.Term.restoreTailMatches, `Aiur.instHashableValue, + `Aiur.Source.Term.hoistLets, `Aiur.Source.Term.hoistLetsAux, + `Aiur.Source.Term.hoistBinaryLets, `Aiur.Source.Term.peelListLets, + `Aiur.Source.Term.freshen, `Aiur.Source.Term.freshBound, + `Aiur.Source.Term.hasExplicitReturn, `Aiur.Source.Term.expandOnce, + `Aiur.Source.Toplevel.inlineCalls, + `Aiur.Bytecode.AIR.Memory, `Aiur.Bytecode.AIR.Call.mk, `Aiur.Bytecode.AIR.primitive, + `Aiur.Bytecode.AIR.readValues, `Aiur.Bytecode.AIR.packWord, `Aiur.Bytecode.AIR.adviceOfSize, + `Aiur.Bytecode.AIR.unaryByte, `Aiur.Bytecode.AIR.binaryByte, + `Aiur.Bytecode.AIR.pairValues, `Aiur.Bytecode.AIR.readWord, + `Aiur.Bytecode.AIR.Step.primitive, `Aiur.Bytecode.AIR.Step.call, + `Aiur.Bytecode.AIR.Step.store, `Aiur.Bytecode.AIR.Step.load, + `Aiur.Bytecode.AIR.RunOps.nil, `Aiur.Bytecode.AIR.RunOps.cons, + `Aiur.Bytecode.AIR.SelectArm.case, `Aiur.Bytecode.AIR.SelectArm.fallback, + `Aiur.Bytecode.AIR.RunBlock.block, + `Aiur.Bytecode.AIR.RunCtrl.returned, `Aiur.Bytecode.AIR.RunCtrl.yielded, + `Aiur.Bytecode.AIR.RunCtrl.match, `Aiur.Bytecode.AIR.RunCtrl.matchContinueReturn, + `Aiur.Bytecode.AIR.RunCtrl.matchContinueYield, + `Aiur.Bytecode.AIR.RunFunction.function, `Aiur.Bytecode.AIR.Execution.function, + `Aiur.AIR.FunctionRow.mk, `Aiur.AIR.FunctionRow.Valid.mk, + `Aiur.AIR.FunctionRow.requests, `Aiur.AIR.FunctionRow.byteQueries, + `Aiur.AIR.functionProviders, `Aiur.AIR.functionQueries, `Aiur.AIR.functionByteQueries, + `Aiur.AIR.MemoryRow.mk, `Aiur.AIR.memoryActivityTransition, + `Aiur.AIR.memoryPointerTransition, `Aiur.AIR.MemoryRowsValid.mk, + `Aiur.AIR.memoryFacts, `Aiur.AIR.memoryProviders, `Aiur.AIR.memoryPointerCycle, + `Aiur.GoldilocksProof.squareMod, `Aiur.AIR.booleanConstraint, + `Aiur.AIR.oneSubBooleanConstraint, `Aiur.AIR.selectorSum, + `Aiur.AIR.MemoryRowsPolynomials.mk, + `Aiur.AIR.inverse256, `Aiur.AIR.pack4, `Aiur.AIR.pack4Nat, + `Aiur.AIR.carryStep, `Aiur.AIR.u32Carries, + `Aiur.AIR.Byte1Kind.all, `Aiur.AIR.Byte1Kind.channel, `Aiur.AIR.Byte1Kind.result, + `Aiur.AIR.byte1Outputs, `Aiur.AIR.byte1Request, `Aiur.AIR.byte1Providers, + `Aiur.AIR.Byte1Kind.op, + `Aiur.AIR.Byte2Kind.all, `Aiur.AIR.Byte2Kind.channel, `Aiur.AIR.Byte2Kind.result, + `Aiur.AIR.byte2Outputs, `Aiur.AIR.byte2Request, `Aiur.AIR.byte2Providers, + `Aiur.AIR.Byte2Kind.op, `Aiur.AIR.Byte2Kind.extendOutputs, + `Aiur.AIR.byte1Preprocessed, `Aiur.AIR.byte2Preprocessed, + `Aiur.AIR.padMessage, `Aiur.AIR.HasMessageShape, `Aiur.AIR.mapProviders, + `Aiur.AIR.PaddedLookupBalance, `Aiur.AIR.functionMessage, `Aiur.AIR.memoryMessage, + `Aiur.AIR.Byte1Kind.outputSize, `Aiur.AIR.Byte2Kind.outputSize, + `Aiur.AIR.lookupMessageWidth, `Aiur.AIR.FunctionMessageValid, + `Aiur.Bytecode.Ctrl.returnsHaveSize, `Aiur.Bytecode.Block.returnsHaveSize, + `Aiur.Bytecode.Op.lookupShape, `Aiur.Bytecode.Ctrl.lookupShapes, + `Aiur.Bytecode.Block.lookupShapes, `Aiur.Bytecode.Toplevel.validateLookupShapes, + `Aiur.Bytecode.Toplevel.validClaimShape, `Aiur.Bytecode.AIR.Call.LookupShape, + `Aiur.Bytecode.AIR.Outcome.ReturnSize, + `Aiur.AIR.LookupTables.mk, `Aiur.AIR.LookupTables.providers, + `Aiur.AIR.GlobalLookups.mk, `Aiur.AIR.rangeMessage, + `Aiur.lookupSlotSum, `Aiur.lookupQueryBoundAux, `Aiur.lookupQueryBound, + `Aiur.AIR.addMessages, `Aiur.AIR.scaleMessage, `Aiur.AIR.weightedMessage, + `Aiur.AIR.gateMessage, `Aiur.AIR.slotMessage, + `Aiur.AIR.SelectorFlow.mk, `Aiur.AIR.SelectorFlow.guard, + `Aiur.AIR.SelectorFlow.join, `Aiur.AIR.SelectorFlow.continue, + `Aiur.AIR.SelectorFlow.Satisfied, `Aiur.AIR.SelectorFlow.Sound.mk, + `Aiur.Bytecode.Ctrl.selectorFlow, `Aiur.Bytecode.Block.selectorFlow, + `Aiur.Bytecode.branchSelectorFlows, `Aiur.Bytecode.Ctrl.returnGates, + `Aiur.Bytecode.Block.returnGates, `Aiur.Bytecode.branchReturnGates, + `Aiur.AIR.RowValue.mk, `Aiur.AIR.RowValue.variable, `Aiur.AIR.RowValue.konst, + `Aiur.AIR.rowValues, `Aiur.AIR.RowValue.add, `Aiur.AIR.RowValue.sub, + `Aiur.AIR.RowValue.mul, `Aiur.AIR.rowAdvice, `Aiur.AIR.RowValue.pack, + `Aiur.AIR.readRowWord, `Aiur.AIR.OpEmission.mk, `Aiur.AIR.emitAdvice, + `Aiur.AIR.emitByte1, `Aiur.AIR.Byte2Kind.extendRowOutputs, `Aiur.AIR.emitByte2, + `Aiur.AIR.range4Queries, `Aiur.AIR.emitU32LessThan, `Aiur.AIR.emitU32Add, + `Aiur.AIR.emitOp, `Aiur.AIR.OpsEmission.mk, `Aiur.AIR.emitOps, + `Aiur.AIR.CallsEmitted, `Aiur.Bytecode.MatchPolynomials.mk, + `Aiur.AIR.RowContext.mk, `Aiur.AIR.QueryPart.mk, `Aiur.AIR.queryParts, + `Aiur.AIR.BlockEmission.mk, `Aiur.AIR.BlockEmission.prefix, + `Aiur.AIR.BlockEmission.afterOps, `Aiur.AIR.joinBlockEmissions, + `Aiur.AIR.mergeEquations, `Aiur.AIR.BlockEmission.continued, + `Aiur.Bytecode.Ctrl.emitRow, `Aiur.Bytecode.Block.emitRow, + `Aiur.AIR.SelectorFlow.unguard, `Aiur.AIR.EmissionProjection.mk, + `Aiur.Bytecode.caseRow, `Aiur.Bytecode.defaultRow, `Aiur.Bytecode.branchRows, + `Aiur.Bytecode.continueRow, `Aiur.AIR.BlockEmission.QueriesIn, + `Aiur.AIR.BlockEmission.CallsAt, `Aiur.AIR.BlockEmission.TerminalAt, + `Aiur.AIR.EmissionIncluded.mk, `Aiur.Bytecode.Ctrl.rowBounds, + `Aiur.Bytecode.Block.rowBounds, `Aiur.AIR.BlockEmission.HasQuery, + `Aiur.AIR.BlockEmission.TracksCalls, `Aiur.AIR.RowInputs, + `Aiur.AIR.InputPreservation.mk, `Aiur.Bytecode.Function.emitRow, + `Aiur.AIR.gateCount, `Aiur.AIR.queryCount, `Aiur.AIR.QuerySlots.mk, + `Aiur.AIR.activeQuerySlot, `Aiur.AIR.querySlotParts, `Aiur.AIR.querySlotMultiplicity, + `Aiur.AIR.decodedQuery, `Aiur.AIR.encodedQuery, `Aiur.AIR.decodedQueries, + `Aiur.AIR.encodedQueries, `Aiur.AIR.blockQueryPool, + `Aiur.AIR.MemberEmission.mk, `Aiur.AIR.MemberEmission.selector, `Aiur.AIR.MemberEmission.entry, + `Aiur.AIR.emitMember, `Aiur.AIR.emitMembers, `Aiur.AIR.CircuitEmission.mk, + `Aiur.AIR.circuitRankBytes, `Aiur.AIR.circuitEmission, `Aiur.AIR.CircuitEmission.lookup, + `Aiur.Bytecode.Circuit.emitRow, `Aiur.AIR.MemberEmission.FromProgram.mk, + `Aiur.AIR.CircuitEmission.QueriesIn, `Aiur.AIR.circuitQueryPool, + `Aiur.Bytecode.FunctionLayout.width, + `Aiur.Bytecode.ControlCounts.mk, `Aiur.Bytecode.ControlCounts.sum, + `Aiur.Bytecode.ControlCounts.branch, `Aiur.Bytecode.ControlCounts.continue, + `Aiur.Bytecode.Ctrl.controlCounts, `Aiur.Bytecode.Block.controlCounts, + `Aiur.Bytecode.branchControlCounts, `Aiur.Bytecode.Circuit.validateRowCounts, + `Aiur.Bytecode.Toplevel.validateRowCounts, `Aiur.Bytecode.ControlCounts.Describes.mk, + `Aiur.BoundVerifier.build, + `Aiur.AIR.Provider.PaddedEq, `Aiur.AIR.CircuitEmission.provider, + `Aiur.AIR.AuxiliaryTables.mk, `Aiur.AIR.AuxiliaryTables.withFunctions, + `Aiur.AIR.AuxiliaryTables.providers, `Aiur.AIR.AuxiliaryTables.circuitProviders, + `Aiur.AIR.circuitProviders, `Aiur.AIR.FunctionRow.Provides, + `Aiur.AIR.FunctionRow.inactive, `Aiur.AIR.FunctionRow.QueriesIn, + `Aiur.AIR.CircuitWitness.mk, `Aiur.AIR.CircuitWitness.Emitted, + `Aiur.AIR.CircuitWitness.Satisfied, `Aiur.AIR.CircuitWitness.Shapes, + `Aiur.AIR.CircuitWitness.LookupBounds, + `Aiur.Bytecode.Function.hasTerminalControl, `Aiur.Bytecode.circuitBranchless, + `Aiur.AIR.unitQuerySelectors, `Aiur.AIR.QueryWriters, + `Aiur.AIR.encodedCircuitQueryPool, + `Aiur.AIR.CircuitTraces.nil, `Aiur.AIR.CircuitTraces.inactive, `Aiur.AIR.CircuitTraces.active, + `Aiur.AIR.CircuitTraces.bitmap, `Aiur.AIR.CircuitTraces.degrees, `Aiur.AIR.CircuitTraces.capacity, + `Aiur.AIR.emitCircuitWitness, `Aiur.AIR.CircuitTraces.emitWitnesses, + `Aiur.Bytecode.Toplevel.singletonCircuits, + `Aiur.Bytecode.MembersConstrained, `Aiur.Bytecode.CircuitsConstrained, + `Aiur.Bytecode.Op.lookupUsage, + `Aiur.Bytecode.Ctrl.lookupUsage, + `Aiur.Bytecode.Block.lookupUsage, + `Aiur.Bytecode.branchLookupUsage, + `Aiur.Bytecode.Function.LookupLayout, + `Aiur.Bytecode.FunctionsLookupLayout, + `Aiur.Bytecode.MembersLookupBound, + `Aiur.Bytecode.CircuitsLookupBound, + `Aiur.AIR.MemoryColumns, + `Aiur.AIR.decodeMemoryRow, + `Aiur.AIR.memoryColumnEquations, + `Aiur.AIR.memoryColumnLookup, + `Aiur.AIR.memoryColumnProvider, + `Aiur.AIR.memoryNextIndex, + `Aiur.AIR.memoryMatrixEquations, + `Aiur.AIR.MemoryMatrixSatisfied, + `Aiur.AIR.decodeMemoryRows, + `Aiur.AIR.memoryMatrixProviders, + `Aiur.AIR.MemoryTraces.nil, `Aiur.AIR.MemoryTraces.inactive, `Aiur.AIR.MemoryTraces.active, + `Aiur.AIR.MemoryTraces.bitmap, + `Aiur.AIR.MemoryTraces.degrees, + `Aiur.AIR.MemoryTraces.capacity, + `Aiur.AIR.MemoryTraces.rows, + `Aiur.AIR.MemoryTraces.providers, + `Aiur.AIR.MemoryTraces.Satisfied, + `Aiur.AIR.memoryTableProviders, + `Aiur.AIR.MemoryTraces.auxiliary, + `Aiur.fixedTraceHeights, + `Aiur.FixedTraceHeights.nil, + `Aiur.FixedTraceHeights.inactive, + `Aiur.FixedTraceHeights.active, + `Aiur.AIR.Byte1Columns, + `Aiur.AIR.Byte2Columns, + `Aiur.AIR.Byte1Kind.column, + `Aiur.AIR.Byte2Kind.column, + `Aiur.AIR.byte1PreprocessedColumns, + `Aiur.AIR.byte2PreprocessedColumns, + `Aiur.AIR.byte1ColumnLookup, + `Aiur.AIR.byte2ColumnLookup, + `Aiur.AIR.byte1ColumnProvider, + `Aiur.AIR.byte2ColumnProvider, + `Aiur.AIR.byte1MatrixProviders, + `Aiur.AIR.byte2MatrixProviders, + `Aiur.AIR.ByteTraces.mk, + `Aiur.AIR.ByteTraces.providers, + `Aiur.AIR.ByteTraces.byte1Weights, + `Aiur.AIR.ByteTraces.byte2Weights, + `Aiur.AIR.SystemTraces.mk, + `Aiur.AIR.SystemTraces.bitmap, + `Aiur.AIR.SystemTraces.degrees, + `Aiur.AIR.SystemTraces.queryBound, + `Aiur.AIR.SystemTraces.providers, + `Aiur.AIR.systemFixedHeights, + `Aiur.AIR.systemLookupSlots, + `Aiur.NativeAIR.Source.preprocessed, + `Aiur.NativeAIR.Source.main, + `Aiur.NativeAIR.Source.stage2, + `Aiur.NativeAIR.RowOffset.current, + `Aiur.NativeAIR.RowOffset.next, + `Aiur.NativeAIR.ColRef.mk, + `Aiur.NativeAIR.Node.konst, + `Aiur.NativeAIR.Node.var, + `Aiur.NativeAIR.Node.publicInput, + `Aiur.NativeAIR.Node.isFirstRow, + `Aiur.NativeAIR.Node.isLastRow, + `Aiur.NativeAIR.Node.isTransition, + `Aiur.NativeAIR.Node.add, + `Aiur.NativeAIR.Node.sub, + `Aiur.NativeAIR.Node.mul, + `Aiur.NativeAIR.Node.neg, + `Aiur.NativeAIR.GraphWidths.mk, + `Aiur.NativeAIR.GraphWidths.width, + `Aiur.NativeAIR.Lookup.mk, + `Aiur.NativeAIR.Graph.mk, + `Aiur.NativeAIR.Lookup.roots, + `Aiur.NativeAIR.Graph.lookupRoots, + `Aiur.NativeAIR.Graph.lookupPrefix, + `Aiur.NativeAIR.Node.Valid, + `Aiur.NativeAIR.Node.check, + `Aiur.NativeAIR.checkNodes, + `Aiur.NativeAIR.ValidNodes.nil, + `Aiur.NativeAIR.ValidNodes.cons, + `Aiur.NativeAIR.checkedGraphPrefix, + `Aiur.NativeAIR.Graph.Valid.mk, + `Aiur.NativeAIR.EvalOps.mk, + `Aiur.NativeAIR.Values.mk, + `Aiur.NativeAIR.Values.Fits, + `Aiur.NativeAIR.Node.eval, + `Aiur.NativeAIR.sweepFrom, + `Aiur.NativeAIR.Graph.sweep, + `Aiur.NativeAIR.Values.withoutStage2, + `Aiur.NativeAIR.Graph.sweepLookupPrefix, + `Aiur.NativeAIR.Expr.konst, + `Aiur.NativeAIR.Expr.var, + `Aiur.NativeAIR.Expr.publicInput, + `Aiur.NativeAIR.Expr.isFirstRow, + `Aiur.NativeAIR.Expr.isLastRow, + `Aiur.NativeAIR.Expr.isTransition, + `Aiur.NativeAIR.Expr.add, + `Aiur.NativeAIR.Expr.sub, + `Aiur.NativeAIR.Expr.mul, + `Aiur.NativeAIR.Expr.neg, + `Aiur.NativeAIR.Expr.eval, + `Aiur.NativeAIR.Node.unfold, + `Aiur.NativeAIR.Reflects, + `Aiur.NativeAIR.unfoldFrom, + `Aiur.NativeAIR.Graph.unfold, + `Aiur.NativeAIR.readNodes, + `Aiur.NativeAIR.evalRoots, + `Aiur.NativeAIR.readLookup, + `Aiur.NativeAIR.evalLookup, + `Aiur.NativeAIR.goldilocksOps] ++ frontendExpressionPremises ++ graphCompilationPremises ++ operationExpressionPremises ++ blockCircuitPremises ++ allocationPremises ++ circuitAllocationPremises ++ circuitCompletionPremises ++ checkedCircuitPremises ++ keyCodecPremises ++ compiledKeyPremises ++ proofAcceptancePremises ++ extensionPremises ++ logUpPremises ++ domainPremises ++ verifierArithmeticPremises ++ transcriptPremises ++ blake3Premises ++ merkleCapPremises ++ merklePremises ++ prunedMerklePremises ++ extensionMmcsPremises ++ friDomainPremises ++ polynomialPremises ++ interpolationPremises ++ foldingPremises ++ friQueryPremises + +private def constants (info : Lean.ConstantInfo) : Array Lean.Name := + info.type.getUsedConstants ++ match info with + | .thmInfo value => value.value.getUsedConstants + | .defnInfo value => value.value.getUsedConstants + | .opaqueInfo value => value.value.getUsedConstants + | .inductInfo value => value.ctors.toArray + | _ => #[] + +private partial def closure (env : Lean.Environment) (runtime : Bool) (pending : List Lean.Name) + (seen : NameSet := {}) : NameSet := + match pending with + | [] => seen + | name :: rest => + if seen.contains name then closure env runtime rest seen + else match env.checked.get.find? name with + | none => closure env runtime rest (seen.insert name) + | some info => + let extras := if runtime then Id.run do + let mut names := #[] + let worker := Lean.Compiler.mkUnsafeRecName name + if (env.checked.get.find? worker).isSome then names := names.push worker + if let some other := Lean.Compiler.getImplementedBy? env name then + names := names.push other + if let some other := (Lean.Compiler.CSimp.ext.getState env).map.find? name then + names := names.push other.toDeclName + return names + else #[] + closure env runtime ((constants info ++ extras).toList ++ rest) (seen.insert name) + +private def projectConstant (env : Lean.Environment) (name : Lean.Name) : Bool := + match env.getModuleIdxFor? name with + | none => false + | some idx => (`Ix).isPrefixOf env.allImportedModuleNames[idx.toNat]! + +private def sortedNames (names : Array Name) : Array Name := names.qsort Name.lt + +/-- Read checked types, bodies and constructors; imported cached axiom +summaries can omit constructor dependencies. -/ +private def checkAxioms (env : Environment) (root : Name) (expected : Array Name) : + CommandElabM (Array Name) := do + let reachable := closure env false [root] + let mut actual := #[] + for name in reachable do + let some info := env.checked.get.find? name + | throwError "C8 component has an unavailable checked dependency: {name}" + if info.isAxiom then actual := actual.push name + let sorted := sortedNames actual + unless sorted == sortedNames expected do + throwError "C8 axiom boundary changed for {root}: expected {sortedNames expected}, actual {sorted}" + return sorted + +-- Constructor closure and exact-set failure paths are part of the audit. +private inductive ConstructorAuditFixture where + | plain + | withProof (proof : propext (Iff.refl True) = rfl) + +run_cmd do + let _ ← checkAxioms (← getEnv) ``ConstructorAuditFixture.plain #[``propext] + let _ ← checkAxioms (← getEnv) ``Eq.refl #[] + +/-- error: C8 axiom boundary changed for Eq.refl: expected [propext], actual [] -/ +#guard_msgs in +run_cmd do + let _ ← checkAxioms (← getEnv) ``Eq.refl #[``propext] + +/-- error: C8 axiom boundary changed for propext: expected [], actual [propext] -/ +#guard_msgs in +run_cmd do + let _ ← checkAxioms (← getEnv) ``propext #[] + +end Aiur.Proofs.Audit + +open Aiur.Proofs.Audit in +run_cmd do + let env ← getEnv + if env.allImportedModuleNames.any (fun name => (`Ix.Compiler).isPrefixOf name) then + throwError "Aiur consistency components depend on the excluded compiler library" + for root in roots do + let some info := env.checked.get.find? root | throwError "C8 component audit: missing root {root}" + let expected := if optimizedLayoutRoots.contains root then + if root == `Aiur.NativeAIR.LookupGroups.withGroup_authored then #[] + else if optimizedLayoutPropextRoots.contains root then #[``propext] + else if optimizedLayoutQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext, ``Classical.choice, ``Quot.sound] + else if friQueryRoots.contains root then + if friQueryPropextRoots.contains root then #[``propext] + else if friQueryClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else #[``propext, ``Quot.sound] + else if foldingRoots.contains root then + if foldingClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else #[``propext, ``Quot.sound] + else if interpolationRoots.contains root then + if interpolationClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else #[``propext, ``Quot.sound] + else if polynomialRoots.contains root then + if polynomialAxiomFreeRoots.contains root then #[] + else if polynomialClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if polynomialQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if friDomainRoots.contains root then + if friDomainClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if friDomainQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if extensionMmcsRoots.contains root then + if extensionMmcsAxiomFreeRoots.contains root then #[] + else if extensionMmcsClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if extensionMmcsQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if prunedMerkleRoots.contains root then + if prunedMerkleAxiomFreeRoots.contains root then #[] + else if prunedMerkleClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if prunedMerkleQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if merkleRoots.contains root then + if merkleAxiomFreeRoots.contains root then #[] + else if merkleClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if merkleQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if merkleCapRoots.contains root then + if merkleCapAxiomFreeRoots.contains root then #[] + else if merkleCapClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else #[``propext, ``Quot.sound] + else if blake3Roots.contains root then + if blake3AxiomFreeRoots.contains root then #[] + else if blake3ClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if blake3QuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if transcriptRoots.contains root then + if transcriptAxiomFreeRoots.contains root then #[] + else if transcriptClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if transcriptQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if verifierArithmeticRoots.contains root then + if verifierArithmeticAxiomFreeRoots.contains root then #[] + else if verifierArithmeticClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if verifierArithmeticQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if domainRoots.contains root then + if domainAxiomFreeRoots.contains root then #[] + else if domainClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if domainQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if logUpRoots.contains root then + if logUpAxiomFreeRoots.contains root then #[] + else if logUpClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if logUpQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if extensionRoots.contains root then + if extensionAxiomFreeRoots.contains root then #[] + else if extensionClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if extensionQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if proofAcceptanceRoots.contains root then + if proofAcceptanceAxiomFreeRoots.contains root then #[] + else if proofAcceptanceClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if proofAcceptanceQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if compiledKeyRoots.contains root then + if compiledKeyClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if compiledKeyQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if keyCodecRoots.contains root then + if keyCodecAxiomFreeRoots.contains root then #[] + else if keyCodecClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if keyCodecQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if checkedCircuitRoots.contains root then + if checkedCircuitAxiomFreeRoots.contains root then #[] + else if checkedCircuitClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if checkedCircuitQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if circuitCompletionRoots.contains root then + if circuitCompletionClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if circuitCompletionQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if circuitAllocationRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if allocationRoots.contains root then + if allocationAxiomFreeRoots.contains root then #[] + else if allocationClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if allocationQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if blockCircuitRoots.contains root then + if blockCircuitClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if blockCircuitQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if operationExpressionRoots.contains root then + if operationExpressionClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if operationExpressionQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if graphCompilationRoots.contains root then + if graphCompilationAxiomFreeRoots.contains root then #[] + else if graphCompilationClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if graphCompilationQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if frontendExpressionRoots.contains root then + if frontendClassicalRoots.contains root then #[``propext, ``Classical.choice, ``Quot.sound] + else if frontendQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext] + else if graphAxiomFreeRoots.contains root then #[] + else if graphPropextRoots.contains root || #[ + `Aiur.G.ofNat_n, `Aiur.G.mul_one, `Aiur.G.mul_zero, + `Aiur.AIR.inactive_multiplicity_zero, + `Aiur.AIR.nonzero_multiplicity_active, `Aiur.AIR.active_satisfies].contains root || + #[`Aiur.G.n_ofNat, `Aiur.G.n_add, `Aiur.G.n_mul, `Aiur.G.zero_add, + `Aiur.AIR.suppliedWeight_nonzero_provider, `Aiur.AIR.inverse256_correct, + `Aiur.AIR.byte1Request_shape, `Aiur.AIR.byte2Request_shape, + `Aiur.AIR.functionMessage_injective, `Aiur.AIR.memoryMessage_injective, + `Aiur.AIR.decodedQueries_length, + `Aiur.AIR.encodedQueries_length, + `Aiur.AIR.slotMessage_member_length, + `Aiur.AIR.suppliedWeight_padded_congr, + `Aiur.AIR.PaddedLookupBalance.congr_providers, + `Aiur.FixedTraceHeights.alignment, + `Aiur.AIR.PaddedLookupBalance.congr_queries].contains root + then #[``propext] + else if (expressionGraphRoots.contains root && !graphClassicalRoots.contains root) || + callOrderRoots.contains root || lookupRoots.contains root || + executionRoots.contains root || memoryRoots.contains root || + #[`Aiur.AIR.selectorSum_characteristic_cancel, `Aiur.AIR.active_case, + `Aiur.AIR.active_default, `Aiur.AIR.byte_add_carry, `Aiur.AIR.byte_sub_borrow, + `Aiur.AIR.byte_carry_relation, `Aiur.AIR.pack4_n, + `Aiur.AIR.exactLookupBalance_byte1, `Aiur.AIR.exactLookupBalance_byte2, + `Aiur.AIR.exactLookupBalance_byte1_step, `Aiur.AIR.exactLookupBalance_byte2_step, + `Aiur.AIR.padMessage_injective_of_shape, `Aiur.AIR.ExactLookupBalance.filter, + `Aiur.AIR.paddedLookupBalance_provider, `Aiur.AIR.padMessage_append_zero, + `Aiur.AIR.functionMessage_rank_alias, + `Aiur.AIR.GlobalLookups.byte1, `Aiur.AIR.GlobalLookups.byte2, + `Aiur.AIR.GlobalLookups.byte1_step, `Aiur.AIR.GlobalLookups.byte2_step, + `Aiur.AIR.GlobalLookups.rank_bytes, `Aiur.BoundVerifier.claim_padding, + `Aiur.lookupQueryBound_sound, `Aiur.lookupQueryBound_consumer_count, + `Aiur.AIR.CircuitTraces.slot_sum_append, `Aiur.AIR.CircuitTraces.capacity_bounded, + `Aiur.AIR.decodeMemoryRow_width, `Aiur.AIR.decodeMemoryRows_size, + `Aiur.AIR.MemoryTraces.slot_sum_append, `Aiur.AIR.MemoryTraces.rows_size_le, + `Aiur.AIR.MemoryTraces.capacity_bounded, + `Aiur.fixedTraceHeights_sound, `Aiur.fixedTraceHeights_complete, + `Aiur.AIR.byte2ColumnProvider_reflect, `Aiur.AIR.suppliedWeight_perm, + `Aiur.AIR.PaddedLookupBalance.perm_providers, `Aiur.AIR.flatMap_map_swap, + `Aiur.AIR.byte2MatrixProviders_reflect, + `Aiur.AIR.encodedCircuitQueryPool_uniform_bound, + `Aiur.lookupQueryBound_shape, `Aiur.lookupQueryBound_complete, + `Aiur.lookupSlotSum_bounded, `Aiur.lookupQueryBound_encodedKey, + `Aiur.AIR.GlobalLookups.of_budget, + `Aiur.AIR.emitOp_calls, `Aiur.AIR.emitOps_calls, + `Aiur.AIR.emitOp_lookupUsage, `Aiur.AIR.emitOps_lookupUsage, + `Aiur.AIR.AuxiliaryTables.global_of_circuit_balance, + `Aiur.AIR.FunctionRow.inactive_valid, + `Aiur.AIR.CallsEmitted.ordered, `Aiur.AIR.active_array_equality, + `Aiur.AIR.QuerySlots.active_singleton].contains root + then #[``propext, ``Quot.sound] + else #[``propext, ``Classical.choice, ``Quot.sound] + let axioms ← checkAxioms env root expected + liftTermElabM do logInfo m!"ROOT {root}\n{← Meta.ppExpr info.type}\nAXIOMS {axioms}" + for name in premises do + let some info := env.checked.get.find? name | throwError "C8 component audit: missing premise {name}" + liftTermElabM do + logInfo m!"PREMISE {name}\n{← Meta.ppExpr info.type}" + if let .defnInfo value := info then logInfo m!"DEFINITION\n{← Meta.ppExpr value.value}" + let logical := closure env false roots.toList + -- Also follow compiler workers and replacements transitively. They need + -- not occur in the logical body, especially for partial opaque functions. + let reachable := (closure env true roots.toList).toList.mergeSort (fun a b => a.toString < b.toString) + let mut workers : Array Lean.Name := #[] + let mut partials : Array Lean.Name := #[] + let mut externs : Array Lean.Name := #[] + let mut replacements : Array (Lean.Name × Lean.Name) := #[] + let mut runtime : Array Lean.Name := #[] + for name in reachable do + unless (env.checked.get.find? name).isSome do + throwError "C8 component has an unavailable checked runtime dependency: {name}" + if projectConstant env name then + if let some parent := Lean.Compiler.isUnsafeRecName? name then + match env.checked.get.find? parent with + | some (.defnInfo original) => + unless original.safety == .safe do + throwError "C8 recursion worker source is not safe: {name}" + | some (.opaqueInfo original) => + if original.isUnsafe then throwError "C8 recursion worker source is unsafe: {name}" + partials := partials.push parent + | _ => throwError "C8 recursion worker has no source definition: {name}" + workers := workers.push name + if Lean.isExtern env name then externs := externs.push name + if let some other := Lean.Compiler.getImplementedBy? env name then + replacements := replacements.push (name, other) + if let some other := (Lean.Compiler.CSimp.ext.getState env).map.find? name then + replacements := replacements.push (name, other.toDeclName) + if let some (.defnInfo definition) := env.checked.get.find? name then + unless definition.safety == .safe || (Lean.Compiler.isUnsafeRecName? name).isSome do + runtime := runtime.push name + if let some (.opaqueInfo definition) := env.checked.get.find? name then + if definition.isUnsafe then runtime := runtime.push name + if Lean.Elab.ComputedFields.computedFieldAttr.hasTag env name then + throwError "C8 component has an unreviewed computed field: {name}" + unless externs == #[`Aiur.AiurSystem.build, `Aiur.AiurSystem.verify, + `Aiur.AiurSystem.vkBytes, `Aiur.Proof.ofBytesChecked] do + throwError "C8 component runtime extern inventory changed: {externs}" + unless replacements.isEmpty do throwError "C8 component runtime replacements changed: {replacements}" + unless runtime.isEmpty do throwError "C8 component has an unreviewed unsafe runtime: {runtime}" + unless partials == #[`Aiur.instHashableTyp.hash, + `Aiur.instReprPattern.repr, `Aiur.instReprTyp.repr] do + throwError "C8 component partial opaque inventory changed: {partials}" + if reachable.contains `Aiur.functionGroupsDisabledImpl then + throwError "C8 selected program must not depend on the environment grouping override" + for name in workers.qsort Name.lt do + let some (.defnInfo value) := env.checked.get.find? name + | throwError "C8 recursion worker is missing: {name}" + liftTermElabM do + logInfo m!"RECURSION WORKER {name}\n{← Meta.ppExpr value.type}\nIMPLEMENTATION\n{← Meta.ppExpr value.value}" + logInfo m!"C8 component ROOTS {roots.size}; LOGICAL DECLARATIONS {logical.size}; WITH RUNTIME {reachable.length}" + logInfo m!"IX RUNTIME EXTERNS {externs}\nPARTIAL OPAQUE SOURCES {partials}\nOTHER UNSAFE RUNTIME {runtime}\nRECURSION WORKERS {workers.size}" + logInfo "Runtime diagnostics cover Ix modules, including private constants. Lean/Std runtime primitives remain an external execution boundary. Partial opaque implementations are inventoried, not proved to refine their logical defaults." + logInfo "The runtime inventory and theorem premises are frozen separately. These roots do not establish full compiler/AIR reflection or public certified claim semantics." diff --git a/Ix/Aiur/Proofs/Blake3.lean b/Ix/Aiur/Proofs/Blake3.lean new file mode 100644 index 000000000..7d7892a0f --- /dev/null +++ b/Ix/Aiur/Proofs/Blake3.lean @@ -0,0 +1,402 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Blake3 +import Ix.Aiur.Proofs.Challenger +import Ix.Aiur.Proofs.Transcript + +namespace Aiur.NativeAIR.Blake3 + +theorem schedules_permute : ∀ index : Fin 7, + schedules[index].toList.Perm (List.finRange 16) := by decide + +theorem schedules_next : ∀ index : Fin 6, + schedules[index.val + 1] = Vector.ofFn (fun position : Fin 16 => + schedules[index.val][schedules[1][position]]) := by decide + +theorem rotateRight_bits (word : UInt32) (count : UInt32) + (positive : 0 < count.toNat) (bounded : count.toNat < 32) : + (rotateRight word count).toBitVec = word.toBitVec.rotateRight count.toNat := by + simp [rotateRight, UInt32.toBitVec_shiftRight, UInt32.toBitVec_shiftLeft, + BitVec.rotateRight_def, Nat.mod_eq_of_lt bounded] + congr 2 + omega + +theorem bytesWord_value (bytes : Vector UInt8 4) : + (bytesWord bytes).toNat = Challenger.littleEndian bytes.toList := by + have bound := Challenger.littleEndian_bound bytes.toList + simp only [Vector.length_toList] at bound + exact Nat.mod_eq_of_lt (by simpa using bound) + +theorem wordBytes_encoding (word : UInt32) : (wordBytes word).toList = KeyCodec.encodeNat 4 word.toNat := by + simp [wordBytes, Vector.toList_ofFn, List.ofFn_succ, KeyCodec.encodeNat, Nat.div_div_eq_div_mul] + +theorem bytesWord_wordBytes (word : UInt32) : bytesWord (wordBytes word) = word := by + apply UInt32.toNat_inj.mp + rw [bytesWord_value, wordBytes_encoding] + exact Challenger.littleEndian_encode 4 word.toNat (by exact word.toNat_lt) + +theorem bytesWord_pack (a b c d : UInt8) : (bytesWord #v[a, b, c, d]).toNat = + a.toNat + 256 * (b.toNat + 256 * (c.toNat + 256 * d.toNat)) := by + rw [bytesWord_value] + simp [Challenger.littleEndian] + +theorem wordBytes_pack (a b c d : UInt8) : wordBytes (bytesWord #v[a, b, c, d]) = #v[a, b, c, d] := by + have ha := a.toNat_lt + have hb := b.toNat_lt + have hc := c.toNat_lt + have hd := d.toNat_lt + apply Vector.ext + intro index bounded + have cases : index = 0 ∨ index = 1 ∨ index = 2 ∨ index = 3 := by omega + rcases cases with rfl | rfl | rfl | rfl <;> + apply UInt8.toNat_inj.mp <;> simp [wordBytes, bytesWord_pack] <;> omega + +theorem wordBytes_bytesWord (bytes : Vector UInt8 4) : wordBytes (bytesWord bytes) = bytes := by + have value : bytes = #v[bytes[0], bytes[1], bytes[2], bytes[3]] := by + apply Vector.ext + intro index bounded + have cases : index = 0 ∨ index = 1 ∨ index = 2 ∨ index = 3 := by omega + rcases cases with rfl | rfl | rfl | rfl <;> rfl + conv => lhs; rw [value] + rw [wordBytes_pack, ← value] + +theorem bytesWord_injective {first second : Vector UInt8 4} (equal : bytesWord first = bytesWord second) : + first = second := by rw [← wordBytes_bytesWord first, equal, wordBytes_bytesWord] + +theorem blockWords_byte (input : List UInt8) (word : Fin 16) (byte : Fin 4) : + ((Vector.ofFn fun byte : Fin 4 => input.toArray[word.val * 4 + byte.val]?.getD 0) : Vector UInt8 4)[byte] + = input[word.val * 4 + byte.val]?.getD 0 := by simp + +theorem blockWords_value (input : List UInt8) (word : Fin 16) : + (blockWords input)[word].toNat = + Challenger.littleEndian (List.ofFn fun byte : Fin 4 => input[word.val * 4 + byte.val]?.getD 0) := by + simpa [blockWords, Vector.toList_ofFn] using bytesWord_value + (Vector.ofFn fun byte : Fin 4 => input.toArray[word.val * 4 + byte.val]?.getD 0) + +theorem cvBytes_value (cv : CV) (index : Fin 32) : + (cvBytes cv)[index] = (cv[index.val / 4].toNat / 256^(index.val % 4)).toUInt8 := by + simp [cvBytes, wordBytes] + +theorem g_unchanged (state : Block) (a b c d index : Fin 16) (x y : UInt32) + (ha : a ≠ index) (hb : b ≠ index) (hc : c ≠ index) (hd : d ≠ index) : + (g state a b c d x y)[index] = state[index] := by + simp [g, Fin.getElem_fin, Fin.val_inj, ha, hb, hc, hd] + +theorem g_values (state : Block) (a b c d : Fin 16) (x y : UInt32) + (ab : a ≠ b) (ac : a ≠ c) (ad : a ≠ d) (bc : b ≠ c) (bd : b ≠ d) (cd : c ≠ d) : + let words := mix state[a] state[b] state[c] state[d] x y + (g state a b c d x y)[a] = words[0] ∧ (g state a b c d x y)[b] = words[1] ∧ + (g state a b c d x y)[c] = words[2] ∧ (g state a b c d x y)[d] = words[3] := by + simp [g, Fin.getElem_fin, Fin.val_inj, + Ne.symm ab, Ne.symm ac, Ne.symm ad, Ne.symm bc, Ne.symm bd, Ne.symm cd] + +theorem initialWords_counter (cv : CV) (counter : UInt64) (blockLen flags : UInt32) : + (initialWords cv counter blockLen flags)[12].toNat + + 2^32 * (initialWords cv counter blockLen flags)[13].toNat = counter.toNat := by + have bounded := counter.toNat_lt + simp [initialWords, Nat.shiftRight_eq_div_pow] + omega + +theorem parentOutput_values (left right : CV) : + (parentOutput left right).cv = iv ∧ (parentOutput left right).block = left ++ right ∧ + (parentOutput left right).blockLen = 64 ∧ (parentOutput left right).counter = 0 ∧ + (parentOutput left right).flags = 4 := ⟨rfl, rfl, rfl, rfl, rfl⟩ + +theorem leftLen_bounds {size : Nat} (large : 1024 < size) : + leftLen size < size ∧ size ≤ 2 * leftLen size := by + have upper := Nat.lt_log2_self (n := size - 1) + rw [Nat.pow_succ] at upper + exact ⟨leftLen_lt large, by unfold leftLen; omega⟩ + +theorem leftLen_chunks {size : Nat} (large : 1024 < size) : + ∃ exponent, leftLen size = 1024 * 2^exponent := by + have exponent : 10 ≤ (size - 1).log2 := (Nat.le_log2 (by omega)).mpr (by omega) + refine ⟨(size - 1).log2 - 10, ?_⟩ + unfold leftLen + conv => lhs; rw [show (size - 1).log2 = 10 + ((size - 1).log2 - 10) by omega] + rw [Nat.pow_add] + +theorem leftLen_chunk_multiple {size : Nat} (large : 1024 < size) : + leftLen size / 1024 * 1024 = leftLen size := by + obtain ⟨exponent, value⟩ := leftLen_chunks large + rw [value] + omega + +theorem leftLen_unique {left right exponent : Nat} + (power : left = 1024 * 2^exponent) (positive : 0 < right) (bounded : right ≤ left) : + leftLen (left + right) = left := by + have pow : left = 2^(10 + exponent) := by rw [Nat.pow_add]; exact power + have nonzero : left + right - 1 ≠ 0 := by + have := Nat.two_pow_pos (10 + exponent) + omega + have log : (left + right - 1).log2 = 10 + exponent := + (Nat.log2_eq_iff nonzero).mpr ⟨by omega, by rw [Nat.pow_succ, ← pow]; omega⟩ + rw [leftLen, log, ← pow] + +theorem chunkLoop_small (counter : UInt64) (cv : CV) (start : Bool) (input : List UInt8) + (small : input.length ≤ 64) : + chunkLoop counter cv start input = + ⟨cv, blockWords input, input.length.toUInt32, counter, (if start then 1 else 0) ||| 2⟩ := by + rw [chunkLoop, dif_pos small] + +theorem chunkLoop_step (counter : UInt64) (cv : CV) (start : Bool) (input : List UInt8) + (large : 64 < input.length) : + chunkLoop counter cv start input = + chunkLoop counter (compress cv (blockWords (input.take 64)) counter 64 (if start then 1 else 0)) + false (input.drop 64) := by + rw [chunkLoop, dif_neg (by omega)] + +theorem chunkLoop_counter (counter : UInt64) (cv : CV) (start : Bool) (input : List UInt8) : + (chunkLoop counter cv start input).counter = counter := by + rw [chunkLoop] + split + · rfl + · exact chunkLoop_counter _ _ _ _ +termination_by input.length +decreasing_by simp only [List.length_drop]; omega + +theorem chunkOutput_counter (counter : UInt64) (input : List UInt8) : + (chunkOutput counter input).counter = counter := chunkLoop_counter _ _ _ _ + +/-- Every non-final block has exactly 64 bytes. The final block may be full; +only the empty input has an empty final block. -/ +inductive ChunkReads (counter : UInt64) : CV → Bool → List UInt8 → Output → Prop where + | last (cv : CV) (start : Bool) (input : List UInt8) (small : input.length ≤ 64) : + ChunkReads counter cv start input + ⟨cv, blockWords input, input.length.toUInt32, counter, (if start then 1 else 0) ||| 2⟩ + | step (cv : CV) (start : Bool) (input : List UInt8) (output : Output) + (large : 64 < input.length) + (rest : ChunkReads counter + (compress cv (blockWords (input.take 64)) counter 64 (if start then 1 else 0)) + false (input.drop 64) output) : ChunkReads counter cv start input output + +theorem chunkLoop_reads (counter : UInt64) (cv : CV) (start : Bool) (input : List UInt8) : + ChunkReads counter cv start input (chunkLoop counter cv start input) := by + by_cases small : input.length ≤ 64 + · rw [chunkLoop_small _ _ _ _ small] + exact .last _ _ _ small + · rw [chunkLoop_step _ _ _ _ (by omega)] + exact .step _ _ _ _ (by omega) (chunkLoop_reads _ _ _ _) +termination_by input.length +decreasing_by simp only [List.length_drop]; omega + +theorem ChunkReads.complete {counter : UInt64} {cv : CV} {start : Bool} {input : List UInt8} {output : Output} + (reads : ChunkReads counter cv start input output) : chunkLoop counter cv start input = output := by + induction reads with + | last cv start input small => exact chunkLoop_small _ _ _ _ small + | step cv start input output large rest ih => rw [chunkLoop_step _ _ _ _ large, ih] + +theorem chunkLoop_iff (counter : UInt64) (cv : CV) (start : Bool) (input : List UInt8) (output : Output) : + chunkLoop counter cv start input = output ↔ ChunkReads counter cv start input output := + ⟨fun equal => equal ▸ chunkLoop_reads _ _ _ _, ChunkReads.complete⟩ + +theorem ChunkReads.framing {counter : UInt64} {cv : CV} {start : Bool} {input : List UInt8} {output : Output} + (reads : ChunkReads counter cv start input output) : + ∃ count, let remaining := input.drop (64 * count) + remaining.length ≤ 64 ∧ (input ≠ [] → 0 < remaining.length) ∧ + output.block = blockWords remaining ∧ output.blockLen.toNat = remaining.length ∧ + output.counter = counter ∧ output.flags = (if start && count == 0 then 1 else 0) ||| 2 := by + induction reads with + | last cv start input small => + refine ⟨0, ?_⟩ + simp only [Nat.mul_zero, List.drop_zero, Nat.reduceBEq, Bool.and_true] + refine ⟨small, ?_, by trivial, ?_, by trivial, by trivial⟩ + · intro nonempty; exact List.length_pos_iff.mpr nonempty + · exact Nat.mod_eq_of_lt (by omega) + | step cv start input output large rest ih => + obtain ⟨count, bound, positive, block, length, counterEq, flags⟩ := ih + refine ⟨count + 1, ?_⟩ + simp only [List.drop_drop] at bound positive block length + have advance : 64 * (count + 1) = 64 + 64 * count := by omega + rw [advance] + refine ⟨bound, fun _ => positive (by simp only [← List.length_pos_iff, List.length_drop]; omega), + block, length, counterEq, ?_⟩ + simpa using flags + +theorem chunkOutput_framing (counter : UInt64) (input : List UInt8) (bounded : input.length ≤ 1024) : + ∃ count, count < 16 ∧ + let remaining := input.drop (64 * count) + remaining.length ≤ 64 ∧ (input ≠ [] → 0 < remaining.length) ∧ + (chunkOutput counter input).block = blockWords remaining ∧ + (chunkOutput counter input).blockLen.toNat = remaining.length ∧ + (chunkOutput counter input).counter = counter ∧ + (chunkOutput counter input).flags = (if count = 0 then 3 else 2) := by + obtain ⟨count, bound, positive, block, length, counterEq, flags⟩ := (chunkLoop_reads counter iv true input).framing + have countBound : count < 16 := by + by_cases nonempty : input = [] + · subst input + have : count = 0 := by + have flagEmpty : (chunkLoop counter iv true []).flags = 3 := by rw [chunkLoop_small _ _ _ _ (by decide)]; rfl + rw [flagEmpty] at flags + by_cases zero : count = 0 + · exact zero + · simp [zero] at flags + omega + · have := positive nonempty + simp only [List.length_drop] at this + omega + refine ⟨count, countBound, bound, positive, block, length, counterEq, ?_⟩ + change (chunkLoop counter iv true input).flags = _ + rw [flags] + by_cases zero : count = 0 <;> simp [zero] <;> decide + +theorem subtree_small (counter : Nat) (input : List UInt8) (small : input.length ≤ 1024) : + subtree counter input = chunkOutput counter.toUInt64 input := by + rw [subtree, dif_pos small] + +theorem subtree_step (counter : Nat) (input : List UInt8) (large : 1024 < input.length) : + subtree counter input = parentOutput + (subtree counter (input.take (leftLen input.length))).chainingValue + (subtree (counter + leftLen input.length / 1024) (input.drop (leftLen input.length))).chainingValue := by + rw [subtree, dif_neg (by omega)] + +theorem subtree_root_counter (input : List UInt8) : (subtree 0 input).counter = 0 := by + by_cases small : input.length ≤ 1024 + · rw [subtree_small _ _ small, chunkOutput_counter]; rfl + · rw [subtree_step _ _ (by omega)]; rfl + +/-- Canonical BLAKE3 trees, specified by full power-of-two left subtrees +and nonempty right subtrees no larger than their siblings. -/ +inductive TreeHash : Nat → List UInt8 → Output → Prop where + | chunk (counter : Nat) (input : List UInt8) (output : Output) (small : input.length ≤ 1024) + (blocks : ChunkReads counter.toUInt64 iv true input output) : TreeHash counter input output + | parent (counter exponent : Nat) (left right : List UInt8) (leftOutput rightOutput : Output) + (full : left.length = 1024 * 2^exponent) (nonempty : 0 < right.length) (bounded : right.length ≤ left.length) + (leftHash : TreeHash counter left leftOutput) + (rightHash : TreeHash (counter + left.length / 1024) right rightOutput) : + TreeHash counter (left ++ right) (parentOutput leftOutput.chainingValue rightOutput.chainingValue) + +theorem subtree_tree (counter : Nat) (input : List UInt8) : TreeHash counter input (subtree counter input) := by + by_cases small : input.length ≤ 1024 + · rw [subtree_small _ _ small] + exact .chunk _ _ _ small (chunkLoop_reads _ _ _ _) + · have large : 1024 < input.length := by omega + have splitBound := leftLen_bounds large + obtain ⟨exponent, full⟩ := leftLen_chunks large + have takeLength : (input.take (leftLen input.length)).length = leftLen input.length := by + simp only [List.length_take]; omega + have result := TreeHash.parent counter exponent (input.take (leftLen input.length)) + (input.drop (leftLen input.length)) _ _ (by rw [takeLength]; exact full) + (by simp only [List.length_drop]; omega) + (by simp only [List.length_drop, takeLength]; omega) + (subtree_tree _ _) (subtree_tree _ _) + rw [List.take_append_drop, takeLength] at result + rw [subtree_step _ _ large] + exact result +termination_by input.length +decreasing_by + · have := leftLen_lt (size := input.length) (by omega) + simp only [List.length_take]; omega + · have := leftLen_positive input.length + simp only [List.length_drop]; omega + +theorem TreeHash.complete {counter : Nat} {input : List UInt8} {output : Output} + (tree : TreeHash counter input output) : subtree counter input = output := by + induction tree with + | chunk counter input output small blocks => rw [subtree_small _ _ small]; exact blocks.complete + | parent counter exponent left right leftOutput rightOutput full nonempty bounded leftHash rightHash ihLeft ihRight => + have positive := Nat.two_pow_pos exponent + have large : 1024 < (left ++ right).length := by simp only [List.length_append]; omega + have split := leftLen_unique full nonempty bounded + rw [subtree_step _ _ large, List.length_append, split, + List.take_left, List.drop_left, ihLeft, ihRight] + +theorem subtree_iff (counter : Nat) (input : List UInt8) (output : Output) : + subtree counter input = output ↔ TreeHash counter input output := + ⟨fun equal => equal ▸ subtree_tree _ _, TreeHash.complete⟩ + +theorem TreeHash.unique {counter : Nat} {input : List UInt8} {first second : Output} + (one : TreeHash counter input first) (two : TreeHash counter input second) : first = second := + one.complete.symm.trans two.complete + +theorem native_counter {counter : Nat} {input : List UInt8} + (span : counter * 1024 + input.length < 2^64) : + counter < 2^54 ∧ counter.toUInt64.toNat = counter := by + constructor + · omega + · exact Nat.mod_eq_of_lt (by omega) + +theorem native_child_spans {counter : Nat} {input : List UInt8} + (span : counter * 1024 + input.length < 2^64) (large : 1024 < input.length) : + counter * 1024 + (input.take (leftLen input.length)).length < 2^64 ∧ + (counter + leftLen input.length / 1024) * 1024 + (input.drop (leftLen input.length)).length < 2^64 := by + have splitBound := leftLen_lt large + have multiple := leftLen_chunk_multiple large + simp only [List.length_take, List.length_drop, Nat.add_mul] + omega + +/-- A particular leaf reached by the actual canonical subtree recursion. -/ +inductive ChunkAt : Nat → List UInt8 → Nat → List UInt8 → Prop where + | leaf (counter : Nat) (input : List UInt8) (small : input.length ≤ 1024) : + ChunkAt counter input counter input + | left {counter leaf : Nat} {input bytes : List UInt8} (large : 1024 < input.length) + (path : ChunkAt counter (input.take (leftLen input.length)) leaf bytes) : + ChunkAt counter input leaf bytes + | right {counter leaf : Nat} {input bytes : List UInt8} (large : 1024 < input.length) + (path : ChunkAt (counter + leftLen input.length / 1024) (input.drop (leftLen input.length)) leaf bytes) : + ChunkAt counter input leaf bytes + +theorem ChunkAt.native {counter leaf : Nat} {input bytes : List UInt8} + (path : ChunkAt counter input leaf bytes) (span : counter * 1024 + input.length < 2^64) : + bytes.length ≤ 1024 ∧ leaf < 2^54 ∧ leaf.toUInt64.toNat = leaf := by + induction path with + | leaf counter input small => exact ⟨small, native_counter span⟩ + | left large path ih => exact ih (native_child_spans span large).1 + | right large path ih => exact ih (native_child_spans span large).2 + +theorem digest_native_counters {input bytes : List UInt8} (native : NativeInput input) {leaf : Nat} + (path : ChunkAt 0 input leaf bytes) : bytes.length ≤ 1024 ∧ leaf < 2^54 ∧ leaf.toUInt64.toNat = leaf := + path.native (by simpa only [NativeInput, Nat.zero_mul, Nat.zero_add] using native) + +theorem digest_tree (input : List UInt8) : + ∃ output, TreeHash 0 input output ∧ output.counter = 0 ∧ digest input = output.rootHash := + ⟨subtree 0 input, subtree_tree _ _, subtree_root_counter _, rfl⟩ + +theorem replay_iff (fuel : Nat) (key : KeyCodec.Key) (proof : ProofCodec.Data) + (claims : List (List G)) (result : Transcript.Replay) : + replay fuel key proof claims = some result ↔ result.Reads hash fuel key proof claims := + Transcript.replay_iff _ _ _ _ _ _ + +theorem replay_unique {fuel more : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {first second : Transcript.Replay} + (one : replay fuel key proof claims = some first) (two : replay more key proof claims = some second) : + first = second := Transcript.replay_unique one two + +theorem verifyArithmetic_iff (fuel : Nat) (key : KeyCodec.Key) (proof : ProofCodec.Data) + (claims : List (List G)) (rows : List ProofShape.Row) (result : Transcript.Replay) : + verifyArithmetic fuel key proof claims rows = some result ↔ + replay fuel key proof claims = some result ∧ + VerifierArithmetic.verify result.challenges claims rows = some true := + Transcript.verifyArithmetic_iff _ _ _ _ _ _ _ + +theorem hash_bytes (input : List UInt8) : List.ofFn (hash input) = (digest input).toList := by + change List.ofFn (fun index : Fin 32 => (digest input)[index]) = _ + exact Vector.toList_ofFn.symm.trans + (congrArg Vector.toList (Vector.ofFn_getElem (xs := digest input))) + +end Aiur.NativeAIR.Blake3 + +namespace Aiur.BoundVerifier +open NativeAIR + +/-- Concrete Blake3 supplies all transcript challenges and the continuing +PCS state. Authentication and cryptographic soundness remain separate. -/ +theorem CompiledBackend.blake3_transcript_row {selection : Selection} (backend : CompiledBackend selection) + {bytes : ByteArray} (checked : CheckedProof backend.keyData bytes) + {fuel : Nat} {claims : List (List G)} {result : Transcript.Replay} + (accepted : Blake3.verifyArithmetic fuel backend.keyData checked.data claims checked.rows = some result) + {position : Nat} {row : ProofShape.Row} (present : checked.rows[position]? = some row) : + result.Reads Blake3.hash fuel backend.keyData checked.data claims ∧ + row.Sourced backend.keyData checked.data row.circuitIndex position ∧ row.Fits backend.keyData.parameters ∧ + ∃ initial before evaluation, + VerifierArithmetic.initialAccumulator result.challenges claims = some initial ∧ + (initial :: checked.rows.map (·.accumulator))[position]? = some before ∧ + VerifierArithmetic.evaluate result.challenges row before = some evaluation ∧ + Quotient.composition result.challenges.alpha evaluation.constraints = + Domain.vanishing evaluation.domain result.challenges.zeta * evaluation.quotientValue := + backend.transcript_row checked accepted present + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/BlockAllocation.lean b/Ix/Aiur/Proofs/BlockAllocation.lean new file mode 100644 index 000000000..b3d303920 --- /dev/null +++ b/Ix/Aiur/Proofs/BlockAllocation.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockDegrees +import Ix.Aiur.Proofs.EmissionAllocation +import Ix.Aiur.Proofs.CompilerBranches + +/-! Recursive block emission has the logical degree map and physical column +cursor calculated by the actual compiler layout pass. -/ + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter Aiur.Bytecode Concrete.Bytecode + +theorem branchRows_layout {selectors : Array Expr} {context : Context} {matched : RowExpr} + {rows : Array RowExpr} {column lookup : Nat} {branches : Array (G × Block)} + {fallback : Option Block} {emission : Emission} (index : Nat) (initial : LayoutMState) (base : Nat) + (generic : initial.callRanks = #[]) + (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) + (emitted : branchRows selectors context matched rows column lookup branches fallback = some emission) + (caseSound : ∀ pair ∈ branches.toList, ∀ entry result state, + state.callRanks = #[] → rowDegrees rows = state.degrees → column = base + state.functionLayout.auxiliaries → + emitBlock selectors context entry rows column lookup pair.2 = some result → + result.column = base + ((blockLayout pair.2).run state).2.functionLayout.auxiliaries) + (defaultSound : ∀ block, fallback = some block → ∀ entry result state, + state.callRanks = #[] → rowDegrees rows = state.degrees → column + branches.size = base + state.functionLayout.auxiliaries → + emitBlock selectors context entry rows (column + branches.size) lookup block = some result → + result.column = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) : + ((ctrlLayout (.match index branches fallback)).run initial).2.degrees = rowDegrees emission.values ∧ + emission.column = base + ((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout.auxiliaries := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i defaults defaultsEmitted + cases emitted + have caseEffects : List.Forall₂ (fun pair result => ∀ state : LayoutMState, + state.callRanks = #[] → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → + result.column = base + ((blockLayout pair.2).run state).2.functionLayout.auxiliaries) + branches.toList cases := by + apply AIR.mapM_forall₂ casesEmitted + intro pair member result resultEmitted + simp only [caseRow, bind, Option.bind] at resultEmitted + split at resultEmitted + · cases resultEmitted + rename_i entry entryRead + dsimp only at resultEmitted + split at resultEmitted + · cases resultEmitted + rename_i body bodyEmitted + cases resultEmitted + intro state stateGeneric degrees auxiliaries + exact caseSound pair member entry body state stateGeneric (aligned.trans degrees.symm) + (by rw [auxiliaries]; exact cursor) bodyEmitted + have defaultEffects : List.Forall₂ (fun block result => ∀ state : LayoutMState, + state.callRanks = #[] → state.degrees = initial.degrees → + state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + branches.size → + result.column = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) + fallback.toList defaults := by + cases present : fallback with + | none => + simp only [defaultRow, present, Option.some.injEq] at defaultsEmitted + subst defaults + exact .nil + | some block => + simp only [defaultRow, present, bind, Option.bind] at defaultsEmitted + split at defaultsEmitted + · cases defaultsEmitted + rename_i entry entryRead + dsimp only at defaultsEmitted + split at defaultsEmitted + · cases defaultsEmitted + rename_i body bodyEmitted + cases defaultsEmitted + refine .cons ?_ .nil + intro state stateGeneric degrees auxiliaries + exact defaultSound block present entry body state stateGeneric (aligned.trans degrees.symm) + (by rw [cursor, auxiliaries, Nat.add_assoc]) bodyEmitted + have layout := matchLayout_allocation index branches fallback initial base Emission.column generic caseEffects defaultEffects + rw [← cursor] at layout + exact ⟨layout.1.trans aligned.symm, layout.2.symm⟩ + +private theorem case_allocation_smaller {branches : Array (G × Block)} {pair : G × Block} + (member : pair ∈ branches.toList) : sizeOf pair.2 < sizeOf branches := by + have bound := Array.sizeOf_lt_of_mem (Array.mem_toList_iff.mp member) + cases pair + simp at bound ⊢ + omega + +private theorem default_allocation_smaller {fallback : Option Block} {block : Block} + (present : fallback = some block) : sizeOf block < sizeOf fallback := by + rw [present] + simp + +mutual + +theorem emitCtrl_layout {selectors : Array Expr} {context : Context} {incoming : Expr} + {rows : Array RowExpr} {column lookup : Nat} (ctrl : Ctrl) {emission : Emission} + (initial : LayoutMState) (base : Nat) (valid : DegreeValid rows) + (generic : initial.callRanks = #[]) + (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) + (emitted : emitCtrl selectors context incoming rows column lookup ctrl = some emission) : + ((ctrlLayout ctrl).run initial).2.degrees = rowDegrees emission.values ∧ + emission.column = base + ((ctrlLayout ctrl).run initial).2.functionLayout.auxiliaries := by + cases ctrl with + | «return» index indices | yield index indices => + simp only [emitCtrl, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + rw [ctrlLayout_eq_def] + exact ⟨aligned.symm, cursor⟩ + | «match» index branches fallback => + rw [emitCtrl_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + apply branchRows_layout index initial base generic aligned cursor emitted + · intro pair member entry result state stateGeneric degrees column emitted + exact (emitBlock_layout pair.2 state base valid stateGeneric degrees column emitted).2 + · intro block present entry result state stateGeneric degrees column emitted + exact (emitBlock_layout block state base valid stateGeneric degrees column emitted).2 + | matchContinue index branches fallback size aux slots continuation => + rw [emitCtrl_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i joined joinedEmitted + have joinedLayout := branchRows_layout index initial base generic aligned cursor joinedEmitted + (fun pair member entry result state stateGeneric degrees column emitted => + (emitBlock_layout pair.2 state base valid stateGeneric degrees column emitted).2) + (fun block present entry result state stateGeneric degrees column emitted => + (emitBlock_layout block state base valid stateGeneric degrees column emitted).2) + rw [branchRows_values joinedEmitted] at joinedLayout + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i continued continuedEmitted + cases emitted + let before := ((pushDegrees (.replicate size 1)).run + ((bumpAuxiliaries size).run ((ctrlLayout (.match index branches fallback)).run initial).2).2).2 + have beforeDegrees : rowDegrees (rows ++ advice joined.column size) = before.degrees := by + change _ = ((ctrlLayout (.match index branches fallback)).run initial).2.degrees ++ .replicate size 1 + rw [rowDegrees_append, advice_degrees, joinedLayout.1] + have beforeColumn : joined.column + size = base + before.functionLayout.auxiliaries := by + change _ = base + (((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout.auxiliaries + size) + rw [joinedLayout.2, Nat.add_assoc] + have result := emitBlock_layout continuation before base (valid.append (advice_degreeValid _ _)) + ((ctrlLayout_callRanks (.match index branches fallback) initial).trans generic) + beforeDegrees beforeColumn continuedEmitted + rw [ctrlLayout_continue] + exact result + · cases emitted +termination_by sizeOf ctrl +decreasing_by + all_goals subst ctrl + all_goals first + | (have bound := case_allocation_smaller ‹_ ∈ _›; simp; omega) + | (have bound := default_allocation_smaller ‹_ = some _›; simp; omega) + | decreasing_tactic + +theorem emitBlock_layout {selectors : Array Expr} {context : Context} {incoming : Expr} + {rows : Array RowExpr} {column lookup : Nat} (block : Block) {emission : Emission} + (initial : LayoutMState) (base : Nat) (valid : DegreeValid rows) + (generic : initial.callRanks = #[]) + (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) + (emitted : emitBlock selectors context incoming rows column lookup block = some emission) : + ((blockLayout block).run initial).2.degrees = rowDegrees emission.values ∧ + emission.column = base + ((blockLayout block).run initial).2.functionLayout.auxiliaries := by + simp only [emitBlock, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i operations operationsEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i control controlEmitted + cases emitted + have operationsLayout := emitOps_layout initial base generic valid aligned cursor operationsEmitted + have result := emitCtrl_layout block.ctrl ((block.ops.forM opLayout).run initial).2 base + (emitOps_degreeValid valid operationsEmitted) + ((congrArg Prod.snd (opsLayout_context block.ops initial)).trans generic) + operationsLayout.1.symm operationsLayout.2 controlEmitted + rw [blockLayout] + exact result +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/BlockCompletion.lean b/Ix/Aiur/Proofs/BlockCompletion.lean new file mode 100644 index 000000000..17bb5bb60 --- /dev/null +++ b/Ix/Aiur/Proofs/BlockCompletion.lean @@ -0,0 +1,175 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.EmissionControls + +/-! Every checked block emits, with yields scoped to their own continuation. -/ + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter Bytecode + +def Emission.YieldShape (size : Option Nat) (emission : Emission) : Prop := + ∀ part ∈ emission.yields, size = some part.values.size + +theorem Emission.YieldShape.prefix {emission : Emission} {size : Option Nat} + (valid : emission.YieldShape size) (equations : List Expr) : + (emission.prefix equations).YieldShape size := valid + +theorem join_yieldShape (rows : Array RowExpr) (column lookup : Nat) (emissions : List Emission) + {size : Option Nat} (valid : ∀ emission ∈ emissions, emission.YieldShape size) : + (join rows column lookup emissions).YieldShape size := by + intro part member + obtain ⟨emission, present, yielded⟩ := List.mem_flatMap.mp member + exact valid emission present part yielded + +private theorem list_mapM_defined_property {read : α → Option β} (inputs : List α) (property : β → Prop) + (defined : ∀ input ∈ inputs, ∃ output, read input = some output ∧ property output) : + ∃ outputs, inputs.mapM read = some outputs ∧ ∀ output ∈ outputs, property output := by + induction inputs with + | nil => exact ⟨[], rfl, by simp⟩ + | cons input inputs ih => + obtain ⟨output, head, valid⟩ := defined input List.mem_cons_self + obtain ⟨outputs, tail, rest⟩ := ih (fun value member => defined value (List.mem_cons_of_mem _ member)) + exact ⟨output :: outputs, + by simp only [List.mapM_cons, head, tail, bind, Option.bind_some, pure], + by simpa only [List.forall_mem_cons] using And.intro valid rest⟩ + +theorem branchRows_defined (selectors : Array Expr) (context : Context) (matched : RowExpr) + (rows : Array RowExpr) (column lookup : Nat) (branches : Array (G × Block)) + (fallback : Option Block) (size : Option Nat) + (casesDefined : ∀ pair ∈ branches.toList, ∃ entry emission, + blockSelector selectors pair.2 = some entry ∧ + emitBlock selectors context entry rows column lookup pair.2 = some emission ∧ emission.YieldShape size) + (defaultDefined : ∀ block, fallback = some block → ∃ entry emission, + blockSelector selectors block = some entry ∧ + emitBlock selectors context entry rows (column + branches.size) lookup block = some emission ∧ + emission.YieldShape size) : + ∃ emission, branchRows selectors context matched rows column lookup branches fallback = some emission ∧ + emission.YieldShape size := by + obtain ⟨cases, casesEmitted, casesValid⟩ := list_mapM_defined_property branches.toList + (fun emission : Emission => emission.YieldShape size) (read := caseRow selectors context matched rows column lookup) (by + intro pair member + obtain ⟨entry, emission, selected, emitted, valid⟩ := casesDefined pair member + exact ⟨emission.prefix [caseEquation entry matched pair.1], + by simp only [caseRow, selected, emitted, bind, Option.bind_some, pure], valid.prefix _⟩) + have defaults : ∃ defaults, + defaultRow selectors context matched rows column lookup branches fallback = some defaults ∧ + ∀ emission ∈ defaults, emission.YieldShape size := by + cases fallback with + | none => exact ⟨[], rfl, by simp⟩ + | some block => + obtain ⟨entry, emission, selected, emitted, valid⟩ := defaultDefined block rfl + exact ⟨[emission.prefix (defaultEquations entry matched column branches)], + by simp only [defaultRow, selected, emitted, bind, Option.bind_some, pure], + by simpa only [List.forall_mem_singleton] using valid.prefix (defaultEquations entry matched column branches)⟩ + obtain ⟨defaults, defaultsEmitted, defaultsValid⟩ := defaults + refine ⟨join rows column lookup (cases ++ defaults), ?_, ?_⟩ + · simp only [branchRows, casesEmitted, defaultsEmitted, bind, Option.bind_some, pure] + · exact join_yieldShape rows column lookup _ (by simpa only [List.forall_mem_append] using And.intro casesValid defaultsValid) + +mutual + +theorem emitCtrl_defined (selectors : Array Expr) (context : Context) (incoming : Expr) + (rows : Array RowExpr) (column lookup : Nat) (ctrl : Ctrl) {size : Option Nat} + (valid : DegreeValid rows) (inputs : context.inputSize ≤ rows.size) + (checked : ctrl.emissionChecks rows.size selectors.size size = true) : + ∃ emission, emitCtrl selectors context incoming rows column lookup ctrl = some emission ∧ emission.YieldShape size := by + cases ctrl with + | «return» index outputs => + obtain ⟨_, outputChecks⟩ : index < selectors.size ∧ indicesInScope rows.size outputs = true := by + simpa only [Ctrl.emissionChecks, Bool.and_eq_true, decide_eq_true_eq] using checked + have inputChecks : indicesInScope rows.size (Array.range context.inputSize) = true := by + rw [indicesInScope_spec] + intro index member + exact Nat.lt_of_lt_of_le (by simpa using member) inputs + obtain ⟨inputValues, inputsRead⟩ := select_defined inputChecks + obtain ⟨outputValues, outputsRead⟩ := select_defined outputChecks + refine ⟨returned context incoming rows inputValues outputValues column lookup, ?_, ?_⟩ + · rw [emitCtrl.eq_def] + simp only [inputsRead, outputsRead, bind, Option.bind_some, pure] + · simp [Emission.YieldShape, returned] + | yield index outputs => + obtain ⟨bound, outputChecks, width⟩ : index < selectors.size ∧ + indicesInScope rows.size outputs = true ∧ size = some outputs.size := by + simpa only [Ctrl.emissionChecks, Bool.and_eq_true, decide_eq_true_eq, beq_iff_eq] using checked + obtain ⟨outputValues, outputsRead⟩ := select_defined outputChecks + refine ⟨yielded selectors[index] rows outputValues column lookup, ?_, ?_⟩ + · rw [emitCtrl.eq_def] + simp only [getElem?_pos selectors index bound, outputsRead, bind, Option.bind_some, pure] + · simpa only [Emission.YieldShape, yielded, List.forall_mem_singleton, array_mapM_size outputsRead] using width + | «match» index branches fallback => + obtain ⟨bound, casesValid, defaultValid⟩ := (emissionChecks_match _ _ _ _ _ _).mp checked + obtain ⟨emission, emitted, shape⟩ := branchRows_defined selectors context rows[index] rows column lookup branches fallback size + (by + intro pair member + obtain ⟨entry, selected⟩ := blockSelector_defined selectors pair.2 (casesValid pair member) + obtain ⟨emission, emitted, shape⟩ := emitBlock_defined selectors context entry rows column lookup pair.2 + valid inputs (casesValid pair member) + exact ⟨entry, emission, selected, emitted, shape⟩) + (by + intro block present + obtain ⟨entry, selected⟩ := blockSelector_defined selectors block (defaultValid block present) + obtain ⟨emission, emitted, shape⟩ := emitBlock_defined selectors context entry rows (column + branches.size) lookup block + valid inputs (defaultValid block present) + exact ⟨entry, emission, selected, emitted, shape⟩) + exact ⟨emission, by rw [emitCtrl_match, getElem?_pos rows index bound]; exact emitted, shape⟩ + | matchContinue index branches fallback outputs aux lookups continuation => + obtain ⟨bound, casesValid, defaultValid, next, added, continuationValid⟩ := + (emissionChecks_matchContinue _ _ _ _ _ _ _ _ _ _).mp checked + obtain ⟨joined, joinedEmitted, shape⟩ := branchRows_defined selectors context rows[index] rows column lookup branches fallback (some outputs) + (by + intro pair member + obtain ⟨entry, selected⟩ := blockSelector_defined selectors pair.2 (casesValid pair member) + obtain ⟨emission, emitted, shape⟩ := emitBlock_defined selectors context entry rows column lookup pair.2 + valid inputs (casesValid pair member) + exact ⟨entry, emission, selected, emitted, shape⟩) + (by + intro block present + obtain ⟨entry, selected⟩ := blockSelector_defined selectors block (defaultValid block present) + obtain ⟨emission, emitted, shape⟩ := emitBlock_defined selectors context entry rows (column + branches.size) lookup block + valid inputs (defaultValid block present) + exact ⟨entry, emission, selected, emitted, shape⟩) + have yieldsValid : joined.yields.all (fun part => part.values.size == outputs) = true := by + rw [List.all_eq_true] + intro part member + exact beq_iff_eq.mpr (Option.some.inj (shape part member)).symm + have nextSize : (rows ++ advice joined.column outputs).size = next := by + simp only [Array.size_append, advice, Array.size_ofFn, (addScope_eq added).1] + have continuationChecks : continuation.emissionChecks (rows ++ advice joined.column outputs).size selectors.size size = true := + nextSize ▸ continuationValid + obtain ⟨entry, selected⟩ := blockSelector_defined selectors continuation continuationChecks + obtain ⟨continued, continuedEmitted, continuedShape⟩ := emitBlock_defined selectors context (yieldGate joined.yields) + (rows ++ advice joined.column outputs) (joined.column + outputs) joined.lookup continuation + (valid.append (advice_degreeValid _ _)) (by simp only [Array.size_append]; omega) continuationChecks + refine ⟨joined.continued (mergeEquations incoming joined.column outputs joined.yields ++ [entry.frontSub (yieldGate joined.yields)]) continued, ?_, continuedShape⟩ + rw [emitCtrl_matchContinue, getElem?_pos rows index bound] + simp only [joinedEmitted, continueRow, yieldsValid, if_true, selected, continuedEmitted, + bind, Option.bind_some, pure] +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (show pair ∈ branches from by simpa using member); grind) + +theorem emitBlock_defined (selectors : Array Expr) (context : Context) (incoming : Expr) + (rows : Array RowExpr) (column lookup : Nat) (block : Block) {size : Option Nat} + (valid : DegreeValid rows) (inputs : context.inputSize ≤ rows.size) + (checked : block.emissionChecks rows.size selectors.size size = true) : + ∃ emission, emitBlock selectors context incoming rows column lookup block = some emission ∧ emission.YieldShape size := by + obtain ⟨next, checkedOps, checkedCtrl⟩ := Block.emissionChecks_parts checked + obtain ⟨entry, selected⟩ := blockSelector_defined selectors block checked + obtain ⟨operations, operationsEmitted, valuesSize⟩ := emitOps_defined incoming context.rank block.ops.toList rows column valid checkedOps + obtain ⟨control, controlEmitted, shape⟩ := emitCtrl_defined selectors context incoming operations.values operations.column + (lookup + operations.queries.length) block.ctrl (emitOps_degreeValid valid operationsEmitted) + (by have mono := checkEmissionOps_le checkedOps; omega) (valuesSize ▸ checkedCtrl) + refine ⟨(control.afterOps incoming lookup operations).prefix [entry.frontMul ((Expr.konst 1).frontSub entry)], ?_, shape⟩ + rw [emitBlock.eq_def] + simp only [selected, operationsEmitted, controlEmitted, bind, Option.bind_some, pure] +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/BlockDegrees.lean b/Ix/Aiur/Proofs/BlockDegrees.lean new file mode 100644 index 000000000..ed25fe732 --- /dev/null +++ b/Ix/Aiur/Proofs/BlockDegrees.lean @@ -0,0 +1,101 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationDegrees +import Ix.Aiur.Proofs.BlockExpressions + +/-! The degree-zero constant invariant survives branches and continuations. -/ + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter + +theorem branchRows_values {selectors : Array Expr} {context : Context} {matched : RowExpr} + {rows : Array RowExpr} {column lookup : Nat} {branches : Array (G × Bytecode.Block)} + {fallback : Option Bytecode.Block} {emission : Emission} + (emitted : branchRows selectors context matched rows column lookup branches fallback = some emission) : + emission.values = rows := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + rfl + +mutual + +theorem emitCtrl_degreeValid {selectors : Array Expr} {context : Context} {incoming : Expr} + {rows : Array RowExpr} {column lookup : Nat} (ctrl : Bytecode.Ctrl) {emission : Emission} + (valid : DegreeValid rows) + (emitted : emitCtrl selectors context incoming rows column lookup ctrl = some emission) : + DegreeValid emission.values := by + cases ctrl with + | «return» index indices | yield index indices => + simp only [emitCtrl, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact valid + | «match» index branches fallback => + rw [emitCtrl_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + rw [branchRows_values emitted] + exact valid + | matchContinue index branches fallback size aux lookups continuation => + rw [emitCtrl_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i continued continuedEmitted + cases emitted + change DegreeValid continued.values + exact emitBlock_degreeValid continuation (valid.append (advice_degreeValid _ _)) continuedEmitted + · cases emitted +termination_by sizeOf ctrl +decreasing_by all_goals decreasing_tactic + +theorem emitBlock_degreeValid {selectors : Array Expr} {context : Context} {incoming : Expr} + {rows : Array RowExpr} {column lookup : Nat} (block : Bytecode.Block) {emission : Emission} + (valid : DegreeValid rows) + (emitted : emitBlock selectors context incoming rows column lookup block = some emission) : + DegreeValid emission.values := by + simp only [emitBlock, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i operations operationsEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i control controlEmitted + cases emitted + change DegreeValid control.values + exact emitCtrl_degreeValid block.ctrl (emitOps_degreeValid valid operationsEmitted) controlEmitted +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/BlockExpressions.lean b/Ix/Aiur/Proofs/BlockExpressions.lean new file mode 100644 index 000000000..cc08fb25f --- /dev/null +++ b/Ix/Aiur/Proofs/BlockExpressions.lean @@ -0,0 +1,734 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockSelectors + +/-! +Symbolic block emission retains returns, escaping yields, and gated call +records alongside the native expressions. Branch joins restore the incoming +logical map; continuations consume their local yields and append merge columns. +-/ + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter LookupEmitter + +theorem list_mapM_flatMap {α β γ δ : Type} {read : α → Option β} + {inputs : List α} {outputs : List β} (evaluated : inputs.mapM read = some outputs) + (first : α → List γ) (second : β → List δ) (evaluate : γ → Option δ) + (related : ∀ input output, read input = some output → + (first input).mapM evaluate = some (second output)) : + (inputs.flatMap first).mapM evaluate = some (outputs.flatMap second) := by + induction inputs generalizing outputs with + | nil => + cases evaluated + rfl + | cons input rest ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i output outputEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i tail tailEval + cases evaluated + simp only [List.flatMap_cons, List.mapM_append, related input output outputEval, + ih tailEval, bind, Option.bind_some, pure] + +theorem list_mapM_foldl {α β γ : Type} {read : α → Option β} + {inputs : List α} {outputs : List β} (evaluated : inputs.mapM read = some outputs) + (first : γ → α → γ) (second : γ → β → γ) + (related : ∀ input output, read input = some output → ∀ start, first start input = second start output) + (start : γ) : inputs.foldl first start = outputs.foldl second start := by + induction inputs generalizing outputs start with + | nil => + cases evaluated + rfl + | cons input rest ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i output outputEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i tail tailEval + cases evaluated + simp only [List.foldl_cons, related input output outputEval, ih tailEval] + +structure Context where + function : Nat + inputSize : Nat + rank : Expr + +structure ReturnExpr where + selector : Expr + function : Nat + inputs : Array Expr + outputs : Array Expr + rank : Expr + +def ReturnExpr.eval (values : Values G) (returned : ReturnExpr) : Option (G × Bytecode.AIR.Call) := do + let selector ← evalExpr values returned.selector + let inputs ← returned.inputs.mapM (evalExpr values) + let outputs ← returned.outputs.mapM (evalExpr values) + let rank ← evalExpr values returned.rank + return (selector, ⟨returned.function, inputs, outputs, rank⟩) + +def ReturnExpr.message (returned : ReturnExpr) : List Expr := + [.konst 0, .konst (G.ofNat returned.function)] ++ returned.inputs.toList ++ + returned.outputs.toList ++ [returned.rank] + +structure YieldExpr where + selector : Expr + values : Array RowExpr + +def YieldExpr.eval (values : Values G) (yielded : YieldExpr) : Option (G × Array AIR.RowValue) := do + let selector ← evalExpr values yielded.selector + let outputs ← evalRows values yielded.values + return (selector, outputs) + +def evalGatedCall (values : Values G) (called : Expr × CallExpr) : + Option (G × (Bytecode.AIR.Call × (Fin 6 → G))) := do + let selector ← evalExpr values called.1 + let call ← called.2.eval values + return (selector, call) + +structure Emission where + values : Array RowExpr + column : Nat + lookup : Nat + equations : List Expr := [] + queries : List QueryExpr := [] + returns : List ReturnExpr := [] + yields : List YieldExpr := [] + calls : List (Expr × CallExpr) := [] + +def Emission.eval (values : Values G) (emission : Emission) : Option AIR.BlockEmission := do + let outputs ← evalRows values emission.values + let equations ← emission.equations.mapM (evalExpr values) + let queries ← emission.queries.mapM (QueryExpr.eval values) + let returns ← emission.returns.mapM (ReturnExpr.eval values) + let yields ← emission.yields.mapM (YieldExpr.eval values) + let calls ← emission.calls.mapM (evalGatedCall values) + return ⟨outputs, emission.column, emission.lookup, equations, queries, returns, yields, calls⟩ + +theorem Emission.eval_of {values : Values G} {emission : Emission} {result : AIR.BlockEmission} + (outputs : evalRows values emission.values = some result.values) + (column : emission.column = result.column) (lookup : emission.lookup = result.lookup) + (equations : emission.equations.mapM (evalExpr values) = some result.equations) + (queries : emission.queries.mapM (QueryExpr.eval values) = some result.queries) + (returns : emission.returns.mapM (ReturnExpr.eval values) = some result.returns) + (yields : emission.yields.mapM (YieldExpr.eval values) = some result.yields) + (calls : emission.calls.mapM (evalGatedCall values) = some result.calls) : + emission.eval values = some result := by + simp only [Emission.eval, outputs, equations, queries, returns, yields, calls, + column, lookup, bind, Option.bind_some, pure] + +theorem Emission.eval_components {values : Values G} {emission : Emission} {result : AIR.BlockEmission} + (evaluated : emission.eval values = some result) : + evalRows values emission.values = some result.values ∧ + emission.column = result.column ∧ emission.lookup = result.lookup ∧ + emission.equations.mapM (evalExpr values) = some result.equations ∧ + emission.queries.mapM (QueryExpr.eval values) = some result.queries ∧ + emission.returns.mapM (ReturnExpr.eval values) = some result.returns ∧ + emission.yields.mapM (YieldExpr.eval values) = some result.yields ∧ + emission.calls.mapM (evalGatedCall values) = some result.calls := by + simp only [Emission.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i outputs outputsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i equations equationsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i queries queriesEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i returns returnsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i yields yieldsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i calls callsEval + cases evaluated + exact ⟨outputsEval, rfl, rfl, equationsEval, queriesEval, returnsEval, yieldsEval, callsEval⟩ + +def Emission.prefix (equations : List Expr) (emission : Emission) : Emission := + { emission with equations := equations ++ emission.equations } + +theorem Emission.prefix_eval {values : Values G} {emission : Emission} {result : AIR.BlockEmission} + {equations : List Expr} {results : List G} (evaluated : emission.eval values = some result) + (equationsEval : equations.mapM (evalExpr values) = some results) : + (emission.prefix equations).eval values = some (result.prefix results) := by + obtain ⟨outputs, column, lookup, oldEquations, queries, returns, yields, calls⟩ := + Emission.eval_components evaluated + apply Emission.eval_of + · exact outputs + · exact column + · exact lookup + · simp only [Emission.prefix, List.mapM_append, equationsEval, oldEquations, + bind, Option.bind_some, pure, AIR.BlockEmission.prefix] + · exact queries + · exact returns + · exact yields + · exact calls + +def Emission.afterOps (incoming : Expr) (lookup : Nat) (ops : OpsEmission) (control : Emission) : Emission := + { control with + equations := ops.equations ++ control.equations + queries := LookupEmitter.queryParts lookup incoming ops.queries ++ control.queries + calls := ops.calls.map (incoming, ·) ++ control.calls } + +theorem Emission.afterOps_eval {values : Values G} {incoming : Expr} {s : G} (lookup : Nat) + {ops : OpsEmission} {operations : AIR.OpsEmission} {control : Emission} {result : AIR.BlockEmission} + (incomingEval : evalExpr values incoming = some s) + (opsEval : ops.eval values = some operations) (controlEval : control.eval values = some result) : + (control.afterOps incoming lookup ops).eval values = some (result.afterOps s lookup operations) := by + obtain ⟨_, _, opEquations, opQueries, opCalls⟩ := OpsEmission.eval_components opsEval + obtain ⟨outputs, column, lookupEq, equations, queries, returns, yields, calls⟩ := + Emission.eval_components controlEval + have gatedCalls : (ops.calls.map (incoming, ·)).mapM (evalGatedCall values) = + some (operations.calls.map (s, ·)) := by + apply list_mapM_transform opCalls (incoming, ·) (s, ·) (evalGatedCall values) + intro call result reflected + simp only [evalGatedCall, incomingEval, reflected, bind, Option.bind_some, pure] + apply Emission.eval_of + · exact outputs + · exact column + · exact lookupEq + · simp only [Emission.afterOps, List.mapM_append, opEquations, equations, + bind, Option.bind_some, pure, AIR.BlockEmission.afterOps] + · simp only [Emission.afterOps, List.mapM_append, LookupEmitter.queryParts_eval incomingEval opQueries, + queries, bind, Option.bind_some, pure, AIR.BlockEmission.afterOps] + · exact returns + · exact yields + · simp only [Emission.afterOps, List.mapM_append, gatedCalls, calls, + bind, Option.bind_some, pure, AIR.BlockEmission.afterOps] + +def join (values : Array RowExpr) (column lookup : Nat) (emissions : List Emission) : Emission := + { values + column := emissions.foldl (fun column emission => max column emission.column) column + lookup := emissions.foldl (fun lookup emission => max lookup emission.lookup) lookup + equations := emissions.flatMap (·.equations) + queries := emissions.flatMap (·.queries) + returns := emissions.flatMap (·.returns) + yields := emissions.flatMap (·.yields) + calls := emissions.flatMap (·.calls) } + +theorem join_eval {values : Values G} {rows : Array RowExpr} {inputs : Array AIR.RowValue} + (inputEval : evalRows values rows = some inputs) (column lookup : Nat) + {emissions : List Emission} {results : List AIR.BlockEmission} + (evaluated : emissions.mapM (Emission.eval values) = some results) : + (join rows column lookup emissions).eval values = some (AIR.joinBlockEmissions inputs column lookup results) := by + apply Emission.eval_of + · exact inputEval + · apply list_mapM_foldl evaluated + intro emission result reflected start + rw [(Emission.eval_components reflected).2.1] + · apply list_mapM_foldl evaluated + intro emission result reflected start + rw [(Emission.eval_components reflected).2.2.1] + · exact list_mapM_flatMap evaluated Emission.equations AIR.BlockEmission.equations + (evalExpr values) (fun _ _ reflected => (Emission.eval_components reflected).2.2.2.1) + · exact list_mapM_flatMap evaluated Emission.queries AIR.BlockEmission.queries + (QueryExpr.eval values) (fun _ _ reflected => (Emission.eval_components reflected).2.2.2.2.1) + · exact list_mapM_flatMap evaluated Emission.returns AIR.BlockEmission.returns + (ReturnExpr.eval values) (fun _ _ reflected => (Emission.eval_components reflected).2.2.2.2.2.1) + · exact list_mapM_flatMap evaluated Emission.yields AIR.BlockEmission.yields + (YieldExpr.eval values) (fun _ _ reflected => (Emission.eval_components reflected).2.2.2.2.2.2.1) + · exact list_mapM_flatMap evaluated Emission.calls AIR.BlockEmission.calls + (evalGatedCall values) (fun _ _ reflected => (Emission.eval_components reflected).2.2.2.2.2.2.2) + +def Emission.continued (branches : Emission) (equations : List Expr) (continuation : Emission) : Emission := + { continuation with + equations := branches.equations ++ equations ++ continuation.equations + queries := branches.queries ++ continuation.queries + returns := branches.returns ++ continuation.returns + calls := branches.calls ++ continuation.calls } + +theorem Emission.continued_eval {values : Values G} + {branches continuation : Emission} {first last : AIR.BlockEmission} + {equations : List Expr} {results : List G} + (branchesEval : branches.eval values = some first) + (continuationEval : continuation.eval values = some last) + (equationsEval : equations.mapM (evalExpr values) = some results) : + (branches.continued equations continuation).eval values = some (first.continued results last) := by + obtain ⟨_, _, _, firstEquations, firstQueries, firstReturns, _, firstCalls⟩ := + Emission.eval_components branchesEval + obtain ⟨outputs, column, lookup, lastEquations, lastQueries, lastReturns, yields, lastCalls⟩ := + Emission.eval_components continuationEval + apply Emission.eval_of + · exact outputs + · exact column + · exact lookup + · simp only [Emission.continued, AIR.BlockEmission.continued, List.mapM_append, + firstEquations, equationsEval, lastEquations, bind, Option.bind_some, pure] + · simp only [Emission.continued, AIR.BlockEmission.continued, List.mapM_append, + firstQueries, lastQueries, bind, Option.bind_some, pure] + · simp only [Emission.continued, AIR.BlockEmission.continued, List.mapM_append, + firstReturns, lastReturns, bind, Option.bind_some, pure] + · exact yields + · simp only [Emission.continued, AIR.BlockEmission.continued, List.mapM_append, + firstCalls, lastCalls, bind, Option.bind_some, pure] + +theorem YieldExpr.eval_of {values : Values G} {yielded : YieldExpr} {s : G} {outputs : Array AIR.RowValue} + (selectorEval : evalExpr values yielded.selector = some s) + (outputsEval : evalRows values yielded.values = some outputs) : + yielded.eval values = some (s, outputs) := by + simp only [YieldExpr.eval, selectorEval, outputsEval, bind, Option.bind_some, pure] + +theorem YieldExpr.eval_components {values : Values G} {yielded : YieldExpr} {result : G × Array AIR.RowValue} + (evaluated : yielded.eval values = some result) : + evalExpr values yielded.selector = some result.1 ∧ evalRows values yielded.values = some result.2 := by + simp only [YieldExpr.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i selector selectorEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i outputs outputsEval + cases evaluated + exact ⟨selectorEval, outputsEval⟩ + +theorem ReturnExpr.eval_of {values : Values G} {returned : ReturnExpr} {s r : G} + {inputs outputs : Array G} (selectorEval : evalExpr values returned.selector = some s) + (inputsEval : returned.inputs.mapM (evalExpr values) = some inputs) + (outputsEval : returned.outputs.mapM (evalExpr values) = some outputs) + (rankEval : evalExpr values returned.rank = some r) : + returned.eval values = some (s, ⟨returned.function, inputs, outputs, r⟩) := by + simp only [ReturnExpr.eval, selectorEval, inputsEval, outputsEval, rankEval, bind, Option.bind_some, pure] + +theorem ReturnExpr.eval_components {values : Values G} {returned : ReturnExpr} {result : G × Bytecode.AIR.Call} + (evaluated : returned.eval values = some result) : + returned.function = result.2.function ∧ evalExpr values returned.selector = some result.1 ∧ + returned.inputs.mapM (evalExpr values) = some result.2.inputs ∧ + returned.outputs.mapM (evalExpr values) = some result.2.outputs ∧ + evalExpr values returned.rank = some result.2.rank := by + simp only [ReturnExpr.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i selector selectorEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i inputs inputsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i outputs outputsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i rank rankEval + cases evaluated + exact ⟨rfl, selectorEval, inputsEval, outputsEval, rankEval⟩ + +theorem ReturnExpr.message_eval {values : Values G} {returned : ReturnExpr} {result : G × Bytecode.AIR.Call} + (evaluated : returned.eval values = some result) : + returned.message.mapM (evalExpr values) = some (AIR.functionMessage result.2) := by + obtain ⟨function, _, inputsEval, outputsEval, rankEval⟩ := ReturnExpr.eval_components evaluated + have inputs := congrArg (Functor.map Array.toList) inputsEval + have outputs := congrArg (Functor.map Array.toList) outputsEval + rw [Array.toList_mapM] at inputs outputs + simp only [Functor.map, Option.map_some] at inputs outputs + simp only [ReturnExpr.message, List.mapM_append, List.mapM_cons, List.mapM_nil, + inputs, outputs, rankEval, + show evalExpr values (.konst 0) = some 0 from rfl, + show evalExpr values (.konst (G.ofNat result.2.function)) = some (G.ofNat result.2.function) from rfl, + bind, Option.bind_some, pure, AIR.functionMessage, function, + List.cons_append, List.nil_append, List.append_assoc] + +def returned (context : Context) (incoming : Expr) (rows inputs outputs : Array RowExpr) + (column lookup : Nat) : Emission := + { values := rows, column, lookup, + returns := [⟨incoming, context.function, rowExprs inputs, rowExprs outputs, context.rank⟩] } + +theorem returned_eval {values : Values G} {context : Context} {incoming : Expr} {s r : G} + {rows inputs outputs : Array RowExpr} {a b c : Array AIR.RowValue} (column lookup : Nat) + (incomingEval : evalExpr values incoming = some s) (rankEval : evalExpr values context.rank = some r) + (rowsEval : evalRows values rows = some a) (inputsEval : evalRows values inputs = some b) + (outputsEval : evalRows values outputs = some c) : + (returned context incoming rows inputs outputs column lookup).eval values = + some { values := a, column, lookup, + returns := [(s, ⟨context.function, AIR.rowValues b, AIR.rowValues c, r⟩)] } := by + have result := ReturnExpr.eval_of (returned := + ⟨incoming, context.function, rowExprs inputs, rowExprs outputs, context.rank⟩) + incomingEval (evalRows_values inputsEval) (evalRows_values outputsEval) rankEval + apply Emission.eval_of rowsEval rfl rfl rfl rfl ?_ rfl rfl + simp only [returned, List.mapM_cons, List.mapM_nil, result, bind, Option.bind_some, pure] + +def yielded (selector : Expr) (rows outputs : Array RowExpr) (column lookup : Nat) : Emission := + { values := rows, column, lookup, yields := [⟨selector, outputs⟩] } + +theorem yielded_eval {values : Values G} {selector : Expr} {s : G} + {rows outputs : Array RowExpr} {a b : Array AIR.RowValue} (column lookup : Nat) + (selectorEval : evalExpr values selector = some s) + (rowsEval : evalRows values rows = some a) (outputsEval : evalRows values outputs = some b) : + (yielded selector rows outputs column lookup).eval values = + some { values := a, column, lookup, yields := [(s, b)] } := by + have result := YieldExpr.eval_of (yielded := ⟨selector, outputs⟩) selectorEval outputsEval + apply Emission.eval_of rowsEval rfl rfl rfl rfl rfl ?_ rfl + simp only [yielded, List.mapM_cons, List.mapM_nil, result, bind, Option.bind_some, pure] + +theorem evalRows_getD_any {values : Values G} {rows : Array RowExpr} {results : Array AIR.RowValue} + (evaluated : evalRows values rows = some results) (index : Nat) : + (rows[index]?.getD (.konst 0)).Reflects values (results[index]?.getD (.konst 0)) := by + by_cases bound : index < rows.size + · exact evalRows_getD evaluated bound + · have size := array_mapM_size evaluated + have absent : rows[index]? = none := Array.getElem?_eq_none_iff.mpr (by omega) + have resultAbsent : results[index]? = none := Array.getElem?_eq_none_iff.mpr (by omega) + simp only [absent, resultAbsent, Option.getD_none] + exact RowExpr.konst_reflects _ _ + +def yieldValue (yielded : YieldExpr) (index : Nat) : Expr := + yielded.selector.frontMul (yielded.values[index]?.getD (.konst 0)).expr + +theorem yieldValue_eval {values : Values G} {yielded : YieldExpr} {result : G × Array AIR.RowValue} + (evaluated : yielded.eval values = some result) (index : Nat) : + evalExpr values (yieldValue yielded index) = + some (result.1 * (AIR.rowValues result.2)[index]?.getD 0) := by + obtain ⟨selectorEval, outputsEval⟩ := YieldExpr.eval_components evaluated + rw [rowValues_getD] + exact Expr.frontMul_eval goldilocksLaws values selectorEval (evalRows_getD_any outputsEval index).1 + +def yieldGate (yields : List YieldExpr) : Expr := sum (yields.map (·.selector)) + +theorem yieldGate_eval {values : Values G} {yields : List YieldExpr} {results : List (G × Array AIR.RowValue)} + (evaluated : yields.mapM (YieldExpr.eval values) = some results) : + evalExpr values (yieldGate yields) = some (AIR.selectorSum (results.map Prod.fst)) := by + apply sum_eval + exact list_mapM_transform evaluated YieldExpr.selector Prod.fst (evalExpr values) + (fun _ _ reflected => (YieldExpr.eval_components reflected).1) + +def mergeEquations (incoming : Expr) (column size : Nat) (yields : List YieldExpr) : List Expr := + (List.range size).map fun index => incoming.frontMul + ((mainCurrent (column + index)).expr.frontSub (sum (yields.map (yieldValue · index)))) + +theorem mergeEquations_eval {values : Values G} (row : Nat → G) {incoming : Expr} {s : G} + (column size : Nat) {yields : List YieldExpr} {results : List (G × Array AIR.RowValue)} + (incomingEval : evalExpr values incoming = some s) + (evaluated : yields.mapM (YieldExpr.eval values) = some results) + (reads : ∀ index < size, (values.columns .main .current)[column + index]? = some (row (column + index))) : + (mergeEquations incoming column size yields).mapM (evalExpr values) = + some (AIR.mergeEquations row s column size results) := by + apply list_mapM_of_map + intro index member + have sumValues := list_mapM_transform evaluated (yieldValue · index) + (fun result => result.1 * (AIR.rowValues result.2)[index]?.getD 0) (evalExpr values) + (fun _ _ reflected => yieldValue_eval reflected index) + have merged : evalExpr values (mainCurrent (column + index)).expr = some (row (column + index)) := + reads index (List.mem_range.mp member) + exact Expr.frontMul_eval goldilocksLaws values incomingEval + (Expr.frontSub_eval goldilocksLaws values merged (sum_eval sumValues)) + +theorem yields_size {values : Values G} {yields : List YieldExpr} {results : List (G × Array AIR.RowValue)} + (evaluated : yields.mapM (YieldExpr.eval values) = some results) (size : Nat) : + yields.all (fun part => part.values.size == size) = results.all (fun part => part.2.size == size) := by + have related := AIR.mapM_forall₂ evaluated (fun _ _ _ reflected => + (array_mapM_size (YieldExpr.eval_components reflected).2).symm) + clear evaluated + induction related with + | nil => rfl + | cons head _ ih => simp only [List.all_cons, head, ih] + +def caseEquation (entry : Expr) (matched : RowExpr) (value : G) : Expr := + entry.frontMul (matched.expr.frontSub (.konst value)) + +theorem caseEquation_eval {values : Values G} {entry : Expr} {s : G} {matched : RowExpr} {value : AIR.RowValue} + (entryEval : evalExpr values entry = some s) (matchedRef : matched.Reflects values value) (branch : G) : + evalExpr values (caseEquation entry matched branch) = some (s * (value.value - branch)) := + Expr.frontMul_eval goldilocksLaws values entryEval + (Expr.frontSub_eval goldilocksLaws values matchedRef.1 rfl) + +def defaultEquations (entry : Expr) (matched : RowExpr) (column : Nat) + (branches : Array (G × Bytecode.Block)) : List Expr := + branches.toList.mapIdx fun index pair => entry.frontMul + (((matched.expr.frontSub (.konst pair.1)).frontMul (mainCurrent (column + index)).expr).frontSub (.konst 1)) + +theorem defaultEquations_eval {values : Values G} (row : Nat → G) + {entry : Expr} {s : G} {matched : RowExpr} {value : AIR.RowValue} + (column : Nat) (branches : Array (G × Bytecode.Block)) + (entryEval : evalExpr values entry = some s) (matchedRef : matched.Reflects values value) + (reads : ∀ index < branches.size, + (values.columns .main .current)[column + index]? = some (row (column + index))) : + (defaultEquations entry matched column branches).mapM (evalExpr values) = + some (branches.toList.mapIdx fun index pair => s * ((value.value - pair.1) * row (column + index) - 1)) := by + simp only [defaultEquations, List.mapIdx_eq_zipIdx_map] + apply list_mapM_of_map + intro pair member + have present := List.mk_mem_zipIdx_iff_getElem?.mp member + have bound : pair.2 < branches.size := by + have original := (List.getElem?_eq_some_iff.mp present).choose + simpa only [Array.length_toList] using original + have inverse : evalExpr values (mainCurrent (column + pair.2)).expr = some (row (column + pair.2)) := + reads pair.2 bound + exact Expr.frontMul_eval goldilocksLaws values entryEval + (Expr.frontSub_eval goldilocksLaws values + (Expr.frontMul_eval goldilocksLaws values + (Expr.frontSub_eval goldilocksLaws values matchedRef.1 rfl) inverse) rfl) + +private theorem block_smaller (block : Bytecode.Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def emitCtrl (selectors : Array Expr) (context : Context) (incoming : Expr) + (rows : Array RowExpr) (column lookup : Nat) : Bytecode.Ctrl → Option Emission + | .return _ indices => do + let inputs ← select rows (Array.range context.inputSize) + let outputs ← select rows indices + return returned context incoming rows inputs outputs column lookup + | .yield index indices => do + let selector ← selectors[index]? + let outputs ← select rows indices + return yielded selector rows outputs column lookup + | .match index branches fallback => do + let matched ← rows[index]? + let cases ← branches.attach.toList.mapM fun ⟨pair, _⟩ => do + let entry ← blockSelector selectors pair.2 + let emission ← emitBlock selectors context entry rows column lookup pair.2 + return emission.prefix [caseEquation entry matched pair.1] + let default : List Emission ← match fallback with + | none => some [] + | some block => do + let entry ← blockSelector selectors block + let emission ← emitBlock selectors context entry rows (column + branches.size) lookup block + pure [emission.prefix (defaultEquations entry matched column branches)] + return join rows column lookup (cases ++ default) + | .matchContinue index branches fallback size _ _ continuation => do + let matched ← rows[index]? + let cases ← branches.attach.toList.mapM fun ⟨pair, _⟩ => do + let entry ← blockSelector selectors pair.2 + let emission ← emitBlock selectors context entry rows column lookup pair.2 + return emission.prefix [caseEquation entry matched pair.1] + let default : List Emission ← match fallback with + | none => some [] + | some block => do + let entry ← blockSelector selectors block + let emission ← emitBlock selectors context entry rows (column + branches.size) lookup block + pure [emission.prefix (defaultEquations entry matched column branches)] + let joined := join rows column lookup (cases ++ default) + if joined.yields.all (fun part => part.values.size == size) then do + let gate := yieldGate joined.yields + let entry ← blockSelector selectors continuation + let equations := mergeEquations incoming joined.column size joined.yields ++ [entry.frontSub gate] + let continued ← emitBlock selectors context gate (rows ++ advice joined.column size) + (joined.column + size) joined.lookup continuation + return joined.continued equations continued + else none +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def emitBlock (selectors : Array Expr) (context : Context) (incoming : Expr) + (rows : Array RowExpr) (column lookup : Nat) (block : Bytecode.Block) : Option Emission := do + let entry ← blockSelector selectors block + let operations ← OpEmitter.emitOps incoming context.rank block.ops.toList rows column + let control ← emitCtrl selectors context incoming operations.values operations.column + (lookup + operations.queries.length) block.ctrl + return (control.afterOps incoming lookup operations).prefix + [entry.frontMul ((Expr.konst 1).frontSub entry)] +termination_by sizeOf block +decreasing_by exact block_smaller block + +end + +theorem fold_max_start (measure : α → Nat) (items : List α) (start : Nat) : + start ≤ items.foldl (fun current item => max current (measure item)) start := by + induction items generalizing start with + | nil => exact Nat.le_refl _ + | cons item items ih => exact Nat.le_trans (Nat.le_max_left _ _) (ih _) + +theorem fold_max_member (measure : α → Nat) {items : List α} {item : α} + (member : item ∈ items) (start : Nat) : + measure item ≤ items.foldl (fun current item => max current (measure item)) start := by + induction items generalizing start with + | nil => cases member + | cons head rest ih => + rcases List.mem_cons.mp member with equal | tail + · subst item + exact Nat.le_trans (Nat.le_max_right _ _) (fold_max_start measure rest _) + · exact ih tail _ + +def caseRow (selectors : Array Expr) (context : Context) (matched : RowExpr) + (rows : Array RowExpr) (column lookup : Nat) (pair : G × Bytecode.Block) : Option Emission := do + let entry ← blockSelector selectors pair.2 + let emission ← emitBlock selectors context entry rows column lookup pair.2 + return emission.prefix [caseEquation entry matched pair.1] + +def defaultRow (selectors : Array Expr) (context : Context) (matched : RowExpr) + (rows : Array RowExpr) (column lookup : Nat) (branches : Array (G × Bytecode.Block)) + (fallback : Option Bytecode.Block) : Option (List Emission) := + match fallback with + | none => some [] + | some block => do + let entry ← blockSelector selectors block + let emission ← emitBlock selectors context entry rows (column + branches.size) lookup block + return [emission.prefix (defaultEquations entry matched column branches)] + +def branchRows (selectors : Array Expr) (context : Context) (matched : RowExpr) + (rows : Array RowExpr) (column lookup : Nat) (branches : Array (G × Bytecode.Block)) + (fallback : Option Bytecode.Block) : Option Emission := do + let cases ← branches.toList.mapM (caseRow selectors context matched rows column lookup) + let default ← defaultRow selectors context matched rows column lookup branches fallback + return join rows column lookup (cases ++ default) + +def continueRow (selectors : Array Expr) (context : Context) (incoming : Expr) + (rows : Array RowExpr) (size : Nat) (continuation : Bytecode.Block) (joined : Emission) : Option Emission := + if joined.yields.all (fun part => part.values.size == size) then do + let gate := yieldGate joined.yields + let entry ← blockSelector selectors continuation + let equations := mergeEquations incoming joined.column size joined.yields ++ [entry.frontSub gate] + let continued ← emitBlock selectors context gate (rows ++ advice joined.column size) + (joined.column + size) joined.lookup continuation + return joined.continued equations continued + else none + +theorem emitCtrl_match (selectors : Array Expr) (context : Context) (incoming : Expr) + (rows : Array RowExpr) (column lookup index : Nat) (branches : Array (G × Bytecode.Block)) + (fallback : Option Bytecode.Block) : + emitCtrl selectors context incoming rows column lookup (.match index branches fallback) = (do + let matched ← rows[index]? + branchRows selectors context matched rows column lookup branches fallback) := by + rw [emitCtrl.eq_def] + simp only [branchRows, Array.toList_attach] + cases rows[index]? with + | none => simp only [bind, Option.bind_none] + | some matched => + simp only [bind, Option.bind_some] + rw [AIR.attachWith_mapM_val _ _ _ (fun pair : G × Bytecode.Block => + (blockSelector selectors pair.2).bind fun entry => + (emitBlock selectors context entry rows column lookup pair.2).bind fun emission => + pure (emission.prefix [caseEquation entry matched pair.1]))] + change (branches.toList.mapM (caseRow selectors context matched rows column lookup)).bind _ = _ + congr 1 + funext cases + cases fallback <;> simp only [defaultRow, bind, Option.bind_assoc, Option.bind_some] + +theorem emitCtrl_matchContinue (selectors : Array Expr) (context : Context) (incoming : Expr) + (rows : Array RowExpr) (column lookup index : Nat) (branches : Array (G × Bytecode.Block)) + (fallback : Option Bytecode.Block) (size aux slots : Nat) (continuation : Bytecode.Block) : + emitCtrl selectors context incoming rows column lookup (.matchContinue index branches fallback size aux slots continuation) = (do + let matched ← rows[index]? + let joined ← branchRows selectors context matched rows column lookup branches fallback + continueRow selectors context incoming rows size continuation joined) := by + rw [emitCtrl.eq_def] + simp only [branchRows, Array.toList_attach] + cases rows[index]? with + | none => simp only [bind, Option.bind_none] + | some matched => + simp only [bind, Option.bind_some] + rw [AIR.attachWith_mapM_val _ _ _ (fun pair : G × Bytecode.Block => + (blockSelector selectors pair.2).bind fun entry => + (emitBlock selectors context entry rows column lookup pair.2).bind fun emission => + pure (emission.prefix [caseEquation entry matched pair.1]))] + simp only [Option.bind_assoc] + change (branches.toList.mapM (caseRow selectors context matched rows column lookup)).bind _ = _ + congr 1 + funext cases + cases fallback <;> simp only [defaultRow, continueRow, bind, pure, Option.bind_assoc, Option.bind_some] + +theorem branchRows_invariants {selectors : Array Expr} {context : Context} {matched : RowExpr} + {rows : Array RowExpr} {column lookup : Nat} {branches : Array (G × Bytecode.Block)} + {fallback : Option Bytecode.Block} {emission : Emission} (normal : Normal rows) + (emitted : branchRows selectors context matched rows column lookup branches fallback = some emission) : + Normal emission.values ∧ column ≤ emission.column := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact ⟨normal, fold_max_start Emission.column _ column⟩ + +mutual + +theorem emitCtrl_invariants {selectors : Array Expr} {context : Context} {incoming : Expr} + {rows : Array RowExpr} {column lookup : Nat} (ctrl : Bytecode.Ctrl) {emission : Emission} + (normal : Normal rows) (emitted : emitCtrl selectors context incoming rows column lookup ctrl = some emission) : + Normal emission.values ∧ column ≤ emission.column := by + cases ctrl with + | «return» index indices | yield index indices => + simp only [emitCtrl, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact ⟨normal, Nat.le_refl _⟩ + | «match» index branches fallback => + rw [emitCtrl_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + exact branchRows_invariants normal emitted + | matchContinue index branches fallback size aux lookups continuation => + rw [emitCtrl_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i joined joinedEmitted + have joinedBounds := branchRows_invariants normal joinedEmitted + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i continued continuedEmitted + cases emitted + have result := emitBlock_invariants continuation + (normal.append (advice_normal _ _)) continuedEmitted + exact ⟨result.1, Nat.le_trans joinedBounds.2 (Nat.le_trans (Nat.le_add_right _ _) result.2)⟩ + · cases emitted +termination_by sizeOf ctrl +decreasing_by all_goals decreasing_tactic + +theorem emitBlock_invariants {selectors : Array Expr} {context : Context} {incoming : Expr} + {rows : Array RowExpr} {column lookup : Nat} (block : Bytecode.Block) {emission : Emission} + (normal : Normal rows) (emitted : emitBlock selectors context incoming rows column lookup block = some emission) : + Normal emission.values ∧ column ≤ emission.column := by + simp only [emitBlock, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i operations operationsEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i control controlEmitted + cases emitted + have result := emitCtrl_invariants block.ctrl (emitOps_normal normal operationsEmitted) controlEmitted + exact ⟨result.1, Nat.le_trans (emitOps_column operationsEmitted) result.2⟩ +termination_by sizeOf block +decreasing_by exact block_smaller block + +end + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/BlockLookups.lean b/Ix/Aiur/Proofs/BlockLookups.lean new file mode 100644 index 000000000..a9b59d6fa --- /dev/null +++ b/Ix/Aiur/Proofs/BlockLookups.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockReflection + +/-! Returns contribute arguments to the provider slot without adding weight. +Consumer slots retain both multiplicities and gated argument accumulation. -/ + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter LookupEmitter Compiler + +def returnArgs (branchless : Bool) (returns : List ReturnExpr) : List Expr := + returns.foldl (fun args returned => addArgs args (gateArgs branchless returned.selector returned.message)) [] + +theorem returnArgs_fold_eval (branchless : Bool) {values : Values G} + {returns : List ReturnExpr} {results : List (G × Bytecode.AIR.Call)} + (evaluated : returns.mapM (ReturnExpr.eval values) = some results) + {initial : List Expr} {start : List G} + (initialEval : initial.mapM (evalExpr values) = some start) : + (returns.foldl (fun args returned => addArgs args (gateArgs branchless returned.selector returned.message)) initial).mapM + (evalExpr values) = some (results.foldl (fun args part => + AIR.addMessages args (AIR.gateMessage branchless part.1 (AIR.functionMessage part.2))) start) := by + induction returns generalizing results initial start with + | nil => + cases evaluated + exact initialEval + | cons returned rest ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i result resultEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i tail tailEval + cases evaluated + exact ih tailEval (addArgs_eval initialEval (gateArgs_eval branchless + (ReturnExpr.eval_components resultEval).2.1 (ReturnExpr.message_eval resultEval))) + +theorem returnArgs_eval (branchless : Bool) {values : Values G} + {returns : List ReturnExpr} {results : List (G × Bytecode.AIR.Call)} + (evaluated : returns.mapM (ReturnExpr.eval values) = some results) : + (returnArgs branchless returns).mapM (evalExpr values) = some + (AIR.slotMessage branchless (results.map fun part => (part.1, AIR.functionMessage part.2))) := by + simpa only [returnArgs, AIR.slotMessage, List.foldl_map] using + returnArgs_fold_eval branchless evaluated (show [].mapM (evalExpr values) = some [] from rfl) + +def lookup (branchless : Bool) (emission : Emission) (slot : Nat) : ExprLookup := + if slot = 0 then ⟨.konst 0, returnArgs branchless emission.returns⟩ + else LookupEmitter.slot branchless emission.queries slot + +theorem lookup_eval (branchless : Bool) {values : Values G} {emission : Emission} {result : AIR.BlockEmission} + (evaluated : emission.eval values = some result) (slot : Nat) : + (lookup branchless emission slot).eval goldilocksOps values = some + (if slot = 0 then (0, AIR.slotMessage branchless (result.returns.map fun part => (part.1, AIR.functionMessage part.2))) + else (AIR.querySlotMultiplicity result.queries slot, + AIR.slotMessage branchless (AIR.querySlotParts result.queries slot))) := by + obtain ⟨_, _, _, _, queries, returns, _, _⟩ := Emission.eval_components evaluated + by_cases zero : slot = 0 + · simp only [lookup, zero, if_true] + change ((returnArgs branchless emission.returns).mapM (evalExpr values)).bind + (fun args => some (0, args)) = _ + rw [returnArgs_eval branchless returns] + rfl + · simpa only [lookup, zero, if_false] using LookupEmitter.slot_eval branchless queries slot + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/BlockQueryPool.lean b/Ix/Aiur/Proofs/BlockQueryPool.lean new file mode 100644 index 000000000..6d7e3a8eb --- /dev/null +++ b/Ix/Aiur/Proofs/BlockQueryPool.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.QuerySlotMessages + +/-! +Function-row validity using the query pool computed from valued block +emissions. Slot exclusivity supplies active raw-query membership, removing +that separate premise from the function-row theorem. Exact global lookup +balance, count/layout validity and native verifier reflection remain open. +-/ + +namespace Aiur.AIR + +def blockQueryPool (emissions : List BlockEmission) : List (List G) := + emissions.flatMap fun emission => decodedQueries emission.queries emission.lookup + +theorem QuerySlots.queried_pool {gate : G} {start : Nat} {emission : BlockEmission} + (slots : QuerySlots gate start emission.lookup emission.queries) + {emissions : List BlockEmission} (member : emission ∈ emissions) : + emission.QueriesIn (blockQueryPool emissions) := by + intro query present active + exact List.mem_flatMap.mpr ⟨emission, member, slots.decoded_member present active⟩ + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Block.emitRow_queried_pool (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + (bounds : block.rowBounds selector) {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) + (linked : incoming = (block.selectorFlow selector).entry) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + {emissions : List BlockEmission} (member : emission ∈ emissions) : + emission.QueriesIn (blockQueryPool emissions) := + (block.emitRow_equation_querySlots row selector context incoming values column lookup + bounds emitted linked satisfied).queried_pool member + +theorem Function.emitRow_pool_valid {tables : LookupTables} {width : Nat} + {emissions : List BlockEmission} (global : GlobalLookups tables width (blockQueryPool emissions)) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (program : Toplevel) (row : Nat → G) (selector : SelIdx → G) + (functionIndex : FunIdx) (rankBytes : Fin 6 → G) (values : Array RowValue) (column lookup : Nat) + (function : Function) (present : program.functions[functionIndex]? = some function) + (arity : values.size = function.layout.inputSize) + (shape : function.body.lookupShapes program none = true) (bounds : function.body.rowBounds selector) + {emission : BlockEmission} + (emitted : function.emitRow row selector functionIndex (packRank rankBytes) values column lookup = some emission) + (member : emission ∈ emissions) + (multiplicity : G) (nonzero : multiplicity ≠ 0) + (activity : activityConstraint multiplicity (function.body.selectorFlow selector).entry = 0) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + ∃ interpreted : FunctionRow, interpreted.Valid program (memoryFacts tables.memory) ∧ + (1, interpreted.request) ∈ emission.returns ∧ + interpreted.request.function = functionIndex ∧ interpreted.request.inputs = rowValues values ∧ + interpreted.request.rank = packRank rankBytes ∧ interpreted.rankBytes = rankBytes ∧ + interpreted.selector = (function.body.selectorFlow selector).entry ∧ + interpreted.multiplicity = multiplicity ∧ emission.CallsAt interpreted.calls ∧ + CallsEmitted (packRank rankBytes) 1 emission.equations (blockQueryPool emissions) interpreted.calls := by + have bodyEmitted := emitted + rw [Function.emitRow] at bodyEmitted + have queried := function.body.emitRow_queried_pool row selector _ _ _ _ _ bounds bodyEmitted rfl satisfied member + exact function.emitRow_valid global memoryValid canonical program row selector functionIndex rankBytes + values column lookup present arity shape bounds emitted multiplicity nonzero activity satisfied queried + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BlockQuerySlots.lean b/Ix/Aiur/Proofs/BlockQuerySlots.lean new file mode 100644 index 000000000..4d564bc11 --- /dev/null +++ b/Ix/Aiur/Proofs/BlockQuerySlots.lean @@ -0,0 +1,303 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.QuerySlots + +/-! +The valued block emitter respects lookup-slot intervals and has at most +one active query in each slot. Branch exclusivity follows from the emitted +selector equations; continuations resume after the maximum branch cursor. +An inactive parent also disables its continuation under the terminal bound. + +Only the selector equations and explicit syntax count bounds are needed. +Native expression/layout reflection remains separate. +-/ + +namespace Aiur.AIR + +theorem selectorSum_all_zero {gates : List G} (zero : ∀ gate ∈ gates, gate = 0) : + selectorSum gates = 0 := by + induction gates with + | nil => rfl + | cons gate gates ih => + rw [selectorSum_cons, zero gate List.mem_cons_self, G.zero_add] + exact ih (fun gate member => zero gate (List.mem_cons_of_mem _ member)) + +theorem SelectorFlow.Sound.yield_gateCount {flow : SelectorFlow} (sound : flow.Sound) + (bounded : flow.returns.length + flow.yields.length < gSize.toNat) + (boolean : booleanConstraint flow.entry = 0) : + gateCount (selectorSum flow.yields) ≤ gateCount flow.entry := by + rcases G.boolean_of_constraint boolean with inactive | active + · have zero := sound.inactive_terminal bounded inactive + have yieldsZero := selectorSum_all_zero (fun gate member => zero gate (List.mem_append_right _ member)) + rw [inactive, yieldsZero] + exact Nat.le_refl _ + · rw [active] + exact gateCount_le_one _ + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem branchSelectorFlows_case_satisfied {selector : SelIdx → G} + {branches : Array (G × Block)} {fallback : Option Block} + (valid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied) + {pair : G × Block} (member : pair ∈ branches.toList) : + (pair.2.selectorFlow selector).Satisfied := + SelectorFlow.join_satisfied valid _ (List.mem_append_left _ (List.mem_map.mpr ⟨pair, member, rfl⟩)) + +theorem branchSelectorFlows_default_satisfied {selector : SelIdx → G} + {branches : Array (G × Block)} {fallback : Option Block} + (valid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied) + {block : Block} (present : fallback = some block) : (block.selectorFlow selector).Satisfied := by + apply SelectorFlow.join_satisfied valid _ + apply List.mem_append_right + rw [present] + exact List.mem_cons_self + +theorem branchRows_querySlots (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + (valid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied) + (bounded : branches.size + fallback.toList.length < gSize.toNat) + (boolean : booleanConstraint (SelectorFlow.join (branchSelectorFlows selector branches fallback)).entry = 0) + (caseSound : ∀ pair ∈ branches.toList, ∀ emission, + pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → + QuerySlots (pair.2.selectorFlow selector).entry lookup emission.lookup emission.queries) + (defaultSound : ∀ block, fallback = some block → ∀ emission, + block.emitRow row selector context (block.selectorFlow selector).entry values + (column + branches.size) lookup = some emission → + QuerySlots (block.selectorFlow selector).entry lookup emission.lookup emission.queries) : + QuerySlots (SelectorFlow.join (branchSelectorFlows selector branches fallback)).entry + lookup emission.lookup emission.queries := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i default defaultEmitted + have equal := Option.some.inj emitted + subst emission + have casesRelated : List.Forall₂ (fun block emission => + QuerySlots (block.selectorFlow selector).entry lookup emission.lookup emission.queries) + (branches.toList.map Prod.snd) cases := by + apply forall₂_map_left + apply mapM_forall₂ casesEmitted + intro pair member emission emitted + simp only [caseRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i body bodyEmitted + have equal := Option.some.inj emitted + subst emission + exact caseSound pair member body bodyEmitted + have defaultRelated : List.Forall₂ (fun block emission => + QuerySlots (block.selectorFlow selector).entry lookup emission.lookup emission.queries) + fallback.toList default := by + cases fallback with + | none => + have equal := Option.some.inj defaultEmitted + subst default + exact .nil + | some block => + simp only [defaultRow, bind, Option.bind] at defaultEmitted + split at defaultEmitted + · cases defaultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj defaultEmitted + subst default + exact .cons (defaultSound block rfl body bodyEmitted) .nil + have individual := branchSelectorFlows_boolean selector branches fallback valid + have count := selector_gateCount + (gates := (branchSelectorFlows selector branches fallback).map SelectorFlow.entry) + (fun gate member => by + obtain ⟨flow, flowMember, equal⟩ := List.mem_map.mp member + subst gate + exact individual flow flowMember) + (by simpa only [branchSelectorFlows, List.length_map, List.length_append, Array.length_toList] using bounded) + boolean + apply QuerySlots.join (fun block : Block => (block.selectorFlow selector).entry) + _ values column lookup (forall₂_append casesRelated defaultRelated) + apply Nat.le_of_eq + simpa only [SelectorFlow.join, branchSelectorFlows, List.map_append, List.map_map, Function.comp_def] using count + +private theorem block_query_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +private theorem block_query_pair_smaller (pair : G × Block) : sizeOf pair.2 < sizeOf pair := by + cases pair + simp + omega + +private theorem block_query_option_smaller {block : Block} {fallback : Option Block} + (present : fallback = some block) : sizeOf block < sizeOf fallback := by + rw [present] + simp + +mutual + +theorem Ctrl.emitRow_querySlots (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) + (bounds : ctrl.rowBounds selector) {emission : BlockEmission} + (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) + (linked : incoming = (ctrl.selectorFlow selector).entry) + (valid : (ctrl.selectorFlow selector).Satisfied) : + QuerySlots incoming lookup emission.lookup emission.queries := by + cases ctrlEq : ctrl with + | «return» index indices => + rw [ctrlEq] at bounds emitted linked valid + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · dsimp only at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + exact QuerySlots.empty incoming lookup + | yield index indices => + rw [ctrlEq] at bounds emitted linked valid + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + exact QuerySlots.empty incoming lookup + | «match» index branches fallback => + rw [ctrlEq] at bounds emitted linked valid + have boolean := (Ctrl.match index branches fallback).selectorFlow_boolean selector valid + rw [Ctrl.emitRow_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + rw [Ctrl.rowBounds.eq_def] at bounds + obtain ⟨branchBound, casesBounded, fallbackBounded⟩ := bounds + rw [Ctrl.selectorFlow_match] at valid boolean linked + have joinedValid := SelectorFlow.guard_satisfied valid + rw [linked] + apply branchRows_querySlots row selector context matched.value values column lookup branches fallback + emitted joinedValid branchBound boolean + · intro pair member body bodyEmitted + exact Block.emitRow_querySlots row selector context _ values column lookup pair.2 + (casesBounded pair member) bodyEmitted rfl (branchSelectorFlows_case_satisfied joinedValid member) + · intro block present body bodyEmitted + have bounded : block.rowBounds selector := by rw [present] at fallbackBounded; exact fallbackBounded + exact Block.emitRow_querySlots row selector context _ values _ lookup block bounded bodyEmitted rfl + (branchSelectorFlows_default_satisfied joinedValid present) + | matchContinue index branches fallback size aux slots continuation => + rw [ctrlEq] at bounds emitted linked valid + have boolean := (Ctrl.matchContinue index branches fallback size aux slots continuation).selectorFlow_boolean selector valid + rw [Ctrl.emitRow_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + dsimp only at emitted + split at emitted + · cases emitted + · rename_i joined branchesEmitted + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i continued contEmitted + have equal := Option.some.inj emitted + subst emission + rw [Ctrl.rowBounds.eq_def] at bounds + obtain ⟨branchBound, terminalBound, casesBounded, fallbackBounded, contBounded⟩ := bounds + rw [Ctrl.selectorFlow_matchContinue] at valid boolean linked + obtain ⟨joinedValid, contValid, link⟩ := + SelectorFlow.continue_satisfied (SelectorFlow.guard_satisfied valid) + have joinedSlots := branchRows_querySlots row selector context matched.value values column lookup + branches fallback branchesEmitted joinedValid branchBound boolean + (fun pair member body bodyEmitted => + Block.emitRow_querySlots row selector context _ values column lookup pair.2 + (casesBounded pair member) bodyEmitted rfl (branchSelectorFlows_case_satisfied joinedValid member)) + (fun block present body bodyEmitted => + Block.emitRow_querySlots row selector context _ values _ lookup block + (by rw [present] at fallbackBounded; exact fallbackBounded) bodyEmitted rfl + (branchSelectorFlows_default_satisfied joinedValid present)) + have projected := branchRows_selector_projection row selector context matched.value values column lookup + branches fallback branchesEmitted + have contLinked : selectorSum (joined.yields.map Prod.fst) = + (continuation.selectorFlow selector).entry := by + rw [projected.yielded] + exact link.symm + have continuedSlots := Block.emitRow_querySlots row selector context _ _ _ _ continuation + contBounded contEmitted contLinked contValid + have joinedSound := branchSelectorFlows_sound selector branches fallback joinedValid + (fun pair _ valid => pair.2.selectorFlow_sound selector valid) + (fun block _ valid => block.selectorFlow_sound selector valid) + have countBound := joinedSound.yield_gateCount terminalBound boolean + rw [← projected.yielded] at countBound + rw [linked] + exact joinedSlots.append (continuedSlots.weaken countBound) + · cases emitted +termination_by sizeOf ctrl +decreasing_by + all_goals + try rw [ctrlEq] + first + | (have bound := Array.sizeOf_lt_of_mem (Array.mem_def.mpr member) + have pairBound := block_query_pair_smaller pair + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (have optionBound := block_query_option_smaller present + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (simp only [Ctrl.matchContinue.sizeOf_spec]; omega) + +theorem Block.emitRow_querySlots (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + (bounds : block.rowBounds selector) {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) + (linked : incoming = (block.selectorFlow selector).entry) + (valid : (block.selectorFlow selector).Satisfied) : + QuerySlots incoming lookup emission.lookup emission.queries := by + rw [Block.rowBounds] at bounds + have boolean : booleanConstraint incoming = 0 := by + rw [linked] + exact block.selectorFlow_boolean selector valid + rw [Block.selectorFlow] at linked valid + rw [Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i operations opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i control ctrlEmitted + have controlSlots := Ctrl.emitRow_querySlots row selector context incoming _ _ _ block.ctrl + bounds ctrlEmitted linked valid + have equal := Option.some.inj emitted + subst emission + exact (QuerySlots.indexed incoming lookup operations.queries boolean).append controlSlots +termination_by sizeOf block +decreasing_by exact block_query_smaller block + +end + +theorem Block.emitRow_equation_querySlots (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + (bounds : block.rowBounds selector) {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) + (linked : incoming = (block.selectorFlow selector).entry) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + QuerySlots incoming lookup emission.lookup emission.queries := + block.emitRow_querySlots row selector context incoming values column lookup bounds emitted linked + (block.emitRow_selectors row selector context incoming values column lookup emitted satisfied) + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BlockReflection.lean b/Ix/Aiur/Proofs/BlockReflection.lean new file mode 100644 index 000000000..06ed6dd4f --- /dev/null +++ b/Ix/Aiur/Proofs/BlockReflection.lean @@ -0,0 +1,412 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockExpressions + +/-! +Reflection of symbolic block and control emission into the valued model. +Branch callbacks below are discharged by structural recursion over bytecode; +fresh reads are restricted to the columns consumed by the complete emission. +-/ + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter LookupEmitter + +def selectorAt (selectors : Array G) (index : Nat) : G := selectors[index]?.getD 0 + +def Context.valued (context : Context) (rank : G) : AIR.RowContext := + ⟨context.function, context.inputSize, rank⟩ + +def BlockReflects (values : Values G) (row : Nat → G) (selectors : Array Expr) (selected : Nat → G) + (context : Context) (rank : G) (block : Bytecode.Block) : Prop := + ∀ {incoming : Expr} {s : G} {rows : Array RowExpr} {inputs : Array AIR.RowValue} + {column lookup : Nat} {emission : Emission}, + evalExpr values incoming = some s → evalRows values rows = some inputs → Normal rows → + emitBlock selectors context incoming rows column lookup block = some emission → + (∀ index, column ≤ index → index < emission.column → + (values.columns .main .current)[index]? = some (row index)) → + ∃ result, block.emitRow row selected (context.valued rank) s inputs column lookup = some result ∧ + emission.eval values = some result + +def CtrlReflects (values : Values G) (row : Nat → G) (selectors : Array Expr) (selected : Nat → G) + (context : Context) (rank : G) (ctrl : Bytecode.Ctrl) : Prop := + ∀ {incoming : Expr} {s : G} {rows : Array RowExpr} {inputs : Array AIR.RowValue} + {column lookup : Nat} {emission : Emission}, + evalExpr values incoming = some s → evalRows values rows = some inputs → Normal rows → + emitCtrl selectors context incoming rows column lookup ctrl = some emission → + (∀ index, column ≤ index → index < emission.column → + (values.columns .main .current)[index]? = some (row index)) → + ∃ result, ctrl.emitRow row selected (context.valued rank) s inputs column lookup = some result ∧ + emission.eval values = some result + +theorem list_mapM_refine_mem {α β γ : Type} {first : α → Option β} {second : α → Option γ} + {evaluate : β → Option γ} {inputs : List α} {outputs : List β} + (selected : inputs.mapM first = some outputs) + (related : ∀ input ∈ inputs, ∀ output ∈ outputs, first input = some output → + ∃ value, second input = some value ∧ evaluate output = some value) : + ∃ values, inputs.mapM second = some values ∧ outputs.mapM evaluate = some values := by + induction inputs generalizing outputs with + | nil => + cases selected + exact ⟨[], rfl, rfl⟩ + | cons input rest ih => + simp only [List.mapM_cons, bind, Option.bind] at selected + split at selected + · cases selected + rename_i output outputSelected + dsimp only at selected + split at selected + · cases selected + rename_i tail tailSelected + cases selected + obtain ⟨value, read, evaluated⟩ := related input List.mem_cons_self output List.mem_cons_self outputSelected + obtain ⟨values, reads, evaluations⟩ := ih tailSelected (fun input member output present selected => + related input (List.mem_cons_of_mem _ member) output (List.mem_cons_of_mem _ present) selected) + refine ⟨value :: values, ?_, ?_⟩ <;> + simp only [List.mapM_cons, read, evaluated, reads, evaluations, bind, Option.bind_some, pure] + +theorem caseRows_reflects {values : Values G} (row : Nat → G) + {selectors : Array Expr} {selected : Nat → G} {context : Context} (rank : G) + {matched : RowExpr} {value : AIR.RowValue} {rows : Array RowExpr} {inputs : Array AIR.RowValue} + (column lookup limit : Nat) {branches : Array (G × Bytecode.Block)} {emissions : List Emission} + (selectorEval : SelectorReads values selectors selected) + (matchedRef : matched.Reflects values value) + (inputEval : evalRows values rows = some inputs) (normal : Normal rows) + (emitted : branches.toList.mapM (caseRow selectors context matched rows column lookup) = some emissions) + (bounds : ∀ emission ∈ emissions, emission.column ≤ limit) + (reads : ∀ index, column ≤ index → index < limit → + (values.columns .main .current)[index]? = some (row index)) + (reflection : ∀ pair ∈ branches.toList, BlockReflects values row selectors selected context rank pair.2) : + ∃ results, branches.toList.mapM (Bytecode.caseRow row selected (context.valued rank) + value.value inputs column lookup) = some results ∧ emissions.mapM (Emission.eval values) = some results := by + apply list_mapM_refine_mem emitted + intro pair member emission present emitted + simp only [caseRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i entry entrySelected + dsimp only at emitted + split at emitted + · cases emitted + rename_i child childEmitted + cases emitted + have upper := bounds _ present + have entryEval : evalExpr values entry = some (pair.2.selectorFlow selected).entry := + blockSelector_reads selectorEval pair.2 entrySelected + obtain ⟨result, resultEmitted, resultEval⟩ := reflection pair member entryEval inputEval normal childEmitted + (fun index lower bound => reads index lower (Nat.lt_of_lt_of_le bound upper)) + have equation : [caseEquation entry matched pair.1].mapM (evalExpr values) = + some [(pair.2.selectorFlow selected).entry * (value.value - pair.1)] := by + simp only [List.mapM_cons, List.mapM_nil, caseEquation_eval entryEval matchedRef, + bind, Option.bind_some, pure] + refine ⟨_, ?_, Emission.prefix_eval resultEval equation⟩ + simp only [Bytecode.caseRow, resultEmitted, bind, Option.bind_some, pure] + +theorem defaultRow_reflects {values : Values G} (row : Nat → G) + {selectors : Array Expr} {selected : Nat → G} {context : Context} (rank : G) + {matched : RowExpr} {value : AIR.RowValue} {rows : Array RowExpr} {inputs : Array AIR.RowValue} + (column lookup limit : Nat) (branches : Array (G × Bytecode.Block)) {fallback : Option Bytecode.Block} + {emissions : List Emission} (selectorEval : SelectorReads values selectors selected) + (matchedRef : matched.Reflects values value) + (inputEval : evalRows values rows = some inputs) (normal : Normal rows) + (emitted : defaultRow selectors context matched rows column lookup branches fallback = some emissions) + (bounds : ∀ emission ∈ emissions, emission.column ≤ limit) + (reads : ∀ index, column ≤ index → index < limit → + (values.columns .main .current)[index]? = some (row index)) + (reflection : ∀ block ∈ fallback.toList, BlockReflects values row selectors selected context rank block) : + ∃ results, Bytecode.defaultRow row selected (context.valued rank) value.value + inputs column lookup branches fallback = some results ∧ emissions.mapM (Emission.eval values) = some results := by + cases fallback with + | none => + cases emitted + exact ⟨[], rfl, rfl⟩ + | some block => + simp only [defaultRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i entry entrySelected + dsimp only at emitted + split at emitted + · cases emitted + rename_i child childEmitted + cases emitted + have upper := bounds _ List.mem_cons_self + have allocated := (emitBlock_invariants block normal childEmitted).2 + have entryEval : evalExpr values entry = some (block.selectorFlow selected).entry := + blockSelector_reads selectorEval block entrySelected + obtain ⟨result, resultEmitted, resultEval⟩ := reflection block List.mem_cons_self entryEval inputEval normal childEmitted + (fun index lower upperBound => reads index (by omega) (Nat.lt_of_lt_of_le upperBound upper)) + have equations := defaultEquations_eval row column branches entryEval matchedRef + (fun index bound => reads (column + index) (by omega) (by dsimp only [Emission.prefix] at upper; omega)) + have prefixed := Emission.prefix_eval resultEval equations + refine ⟨[result.prefix (branches.toList.mapIdx fun index pair => + (block.selectorFlow selected).entry * ((value.value - pair.1) * row (column + index) - 1))], ?_, ?_⟩ + · simp only [Bytecode.defaultRow, resultEmitted, bind, Option.bind_some, pure] + · simp only [List.mapM_cons, List.mapM_nil, prefixed, bind, Option.bind_some, pure] + +theorem branchRows_reflects {values : Values G} (row : Nat → G) + {selectors : Array Expr} {selected : Nat → G} {context : Context} (rank : G) + {matched : RowExpr} {value : AIR.RowValue} {rows : Array RowExpr} {inputs : Array AIR.RowValue} + {column lookup : Nat} {branches : Array (G × Bytecode.Block)} {fallback : Option Bytecode.Block} + {emission : Emission} (selectorEval : SelectorReads values selectors selected) + (matchedRef : matched.Reflects values value) + (inputEval : evalRows values rows = some inputs) (normal : Normal rows) + (emitted : branchRows selectors context matched rows column lookup branches fallback = some emission) + (reads : ∀ index, column ≤ index → index < emission.column → + (values.columns .main .current)[index]? = some (row index)) + (casesReflect : ∀ pair ∈ branches.toList, BlockReflects values row selectors selected context rank pair.2) + (defaultReflect : ∀ block ∈ fallback.toList, BlockReflects values row selectors selected context rank block) : + ∃ result, Bytecode.branchRows row selected (context.valued rank) value.value + inputs column lookup branches fallback = some result ∧ emission.eval values = some result := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i default defaultEmitted + cases emitted + obtain ⟨caseValues, casesRead, casesEval⟩ := caseRows_reflects row rank column lookup + (join rows column lookup (cases ++ default)).column selectorEval matchedRef inputEval normal casesEmitted + (fun emission member => fold_max_member Emission.column (List.mem_append_left default member) column) reads casesReflect + obtain ⟨defaultValues, defaultRead, defaultEval⟩ := defaultRow_reflects row rank column lookup + (join rows column lookup (cases ++ default)).column branches selectorEval matchedRef inputEval normal defaultEmitted + (fun emission member => fold_max_member Emission.column (List.mem_append_right cases member) column) reads defaultReflect + have combined : (cases ++ default).mapM (Emission.eval values) = some (caseValues ++ defaultValues) := by + simp only [List.mapM_append, casesEval, defaultEval, bind, Option.bind_some, pure] + refine ⟨_, ?_, join_eval inputEval column lookup combined⟩ + simp only [Bytecode.branchRows, casesRead, defaultRead, bind, Option.bind_some, pure] + +theorem continueRow_column {selectors : Array Expr} {context : Context} {incoming : Expr} + {rows : Array RowExpr} {size : Nat} {continuation : Bytecode.Block} {joined emission : Emission} + (normal : Normal rows) + (emitted : continueRow selectors context incoming rows size continuation joined = some emission) : + joined.column ≤ emission.column := by + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i continued continuedEmitted + cases emitted + exact Nat.le_trans (Nat.le_add_right _ _) + (emitBlock_invariants continuation (normal.append (advice_normal _ _)) continuedEmitted).2 + · cases emitted + +theorem advice_absolute_eval {values : Values G} (row : Nat → G) (column size : Nat) + (reads : ∀ index < size, (values.columns .main .current)[column + index]? = some (row (column + index))) : + evalRows values (advice column size) = some (AIR.rowAdvice row column size) := by + simpa only [AIR.rowAdvice, Nat.zero_add] using advice_eval values (fun index => row (column + index)) column size reads + +theorem continueRow_reflects {values : Values G} (row : Nat → G) + {selectors : Array Expr} {selected : Nat → G} {context : Context} (rank : G) + {incoming : Expr} {s : G} {rows : Array RowExpr} {inputs : Array AIR.RowValue} + (size : Nat) (continuation : Bytecode.Block) {joined emission : Emission} {branches : AIR.BlockEmission} + (selectorEval : SelectorReads values selectors selected) + (incomingEval : evalExpr values incoming = some s) + (inputEval : evalRows values rows = some inputs) (normal : Normal rows) + (joinedEval : joined.eval values = some branches) + (emitted : continueRow selectors context incoming rows size continuation joined = some emission) + (reads : ∀ index, joined.column ≤ index → index < emission.column → + (values.columns .main .current)[index]? = some (row index)) + (reflection : BlockReflects values row selectors selected context rank continuation) : + ∃ result, Bytecode.continueRow row selected (context.valued rank) s inputs size continuation branches = + some result ∧ emission.eval values = some result := by + simp only [continueRow] at emitted + split at emitted + · rename_i widths + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i entry entrySelected + dsimp only at emitted + split at emitted + · cases emitted + rename_i continued continuedEmitted + cases emitted + have allocated := (emitBlock_invariants continuation (normal.append (advice_normal _ _)) continuedEmitted).2 + obtain ⟨_, column, lookup, _, _, _, yieldsEval, _⟩ := Emission.eval_components joinedEval + have validWidths : branches.yields.all (fun part => part.2.size == size) = true := + (yields_size yieldsEval size).symm.trans widths + have fresh : ∀ index < size, + (values.columns .main .current)[joined.column + index]? = some (row (joined.column + index)) := + fun index bound => reads (joined.column + index) (by omega) + (by change joined.column + index < continued.column; omega) + have outputs := advice_absolute_eval row joined.column size fresh + have gateEval := yieldGate_eval yieldsEval + have entryEval : evalExpr values entry = some (continuation.selectorFlow selected).entry := + blockSelector_reads selectorEval continuation entrySelected + obtain ⟨result, resultEmitted, resultEval⟩ := reflection gateEval (evalRows_append inputEval outputs) + (normal.append (advice_normal _ _)) continuedEmitted (fun index lower upper => reads index (by omega) upper) + have mergeEval := mergeEquations_eval row joined.column size incomingEval yieldsEval fresh + have linkEval := Expr.frontSub_eval goldilocksLaws values entryEval gateEval + have equations : (mergeEquations incoming joined.column size joined.yields ++ [entry.frontSub (yieldGate joined.yields)]).mapM + (evalExpr values) = some (AIR.mergeEquations row s joined.column size branches.yields ++ + [(continuation.selectorFlow selected).entry - AIR.selectorSum (branches.yields.map Prod.fst)]) := by + simp only [List.mapM_append, List.mapM_cons, List.mapM_nil, mergeEval, linkEval, + bind, Option.bind_some, pure, goldilocks_sub] + refine ⟨_, ?_, Emission.continued_eval joinedEval resultEval equations⟩ + simp only [Bytecode.continueRow, validWidths, if_true, ← column, ← lookup, + resultEmitted, bind, Option.bind_some, pure] + · cases emitted + +private theorem case_block_smaller {branches : Array (G × Bytecode.Block)} {pair : G × Bytecode.Block} + (member : pair ∈ branches.toList) : sizeOf pair.2 < sizeOf branches := by + have present : pair ∈ branches := Array.mem_toList_iff.mp member + have bound := Array.sizeOf_lt_of_mem present + cases pair + simp at bound ⊢ + omega + +private theorem fallback_block_smaller {fallback : Option Bytecode.Block} {block : Bytecode.Block} + (member : block ∈ fallback.toList) : sizeOf block < sizeOf fallback := by + cases fallback with + | none => cases member + | some value => + have equal := List.mem_singleton.mp member + subst block + simp + +private theorem block_smaller (block : Bytecode.Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +theorem ctrl_reflects (values : Values G) (row : Nat → G) + {selectors : Array Expr} {selected : Nat → G} {context : Context} {rank : G} + (selectorEval : SelectorReads values selectors selected) + (rankEval : evalExpr values context.rank = some rank) (ctrl : Bytecode.Ctrl) : + CtrlReflects values row selectors selected context rank ctrl := by + intro incoming s rows inputs column lookup emission incomingEval inputEval normal emitted reads + cases ctrl with + | «return» index indices => + simp only [emitCtrl, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i arguments argsSelected + dsimp only at emitted + split at emitted + · cases emitted + rename_i outputs outputsSelected + cases emitted + obtain ⟨args, argsRead, argsEval⟩ := select_reflects inputEval argsSelected + obtain ⟨out, outRead, outEval⟩ := select_reflects inputEval outputsSelected + refine ⟨_, ?_, returned_eval column lookup incomingEval rankEval inputEval argsEval outEval⟩ + simp only [Bytecode.Ctrl.emitRow, Context.valued, select_values argsRead, select_values outRead, + bind, Option.bind_some, pure] + | yield index indices => + simp only [emitCtrl, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i selector selectorRead + dsimp only at emitted + split at emitted + · cases emitted + rename_i outputs outputsSelected + cases emitted + obtain ⟨out, outRead, outEval⟩ := select_reflects inputEval outputsSelected + have selectedEval : evalExpr values selector = some (selected index) := selectorEval selectorRead + have selectedList := congrArg (Functor.map Array.toList) outRead + rw [Array.toList_mapM] at selectedList + simp only [Functor.map, Option.map_some] at selectedList + refine ⟨_, ?_, yielded_eval column lookup selectedEval inputEval outEval⟩ + simp only [Bytecode.Ctrl.emitRow, selectedList, bind, Option.bind_some, pure, Array.toArray_toList] + | «match» index branches fallback => + rw [emitCtrl_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i matched matchedRead + dsimp only at emitted + obtain ⟨value, valueRead, valueRef⟩ := evalRows_read inputEval matchedRead + obtain ⟨result, resultEmitted, resultEval⟩ := branchRows_reflects row rank selectorEval valueRef inputEval normal emitted reads + (fun pair member => block_reflects values row selectorEval rankEval pair.2) + (fun block member => block_reflects values row selectorEval rankEval block) + refine ⟨result, ?_, resultEval⟩ + simp only [Bytecode.Ctrl.emitRow_match, valueRead, resultEmitted, bind, Option.bind_some] + | matchContinue index branches fallback size aux slots continuation => + rw [emitCtrl_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i matched matchedRead + dsimp only at emitted + split at emitted + · cases emitted + rename_i joined joinedEmitted + dsimp only at emitted + have finish := continueRow_column normal emitted + have start := (branchRows_invariants normal joinedEmitted).2 + obtain ⟨value, valueRead, valueRef⟩ := evalRows_read inputEval matchedRead + obtain ⟨branchValue, branchEmitted, branchEval⟩ := branchRows_reflects row rank selectorEval valueRef inputEval normal + joinedEmitted (fun index lower upper => reads index lower (Nat.lt_of_lt_of_le upper finish)) + (fun pair member => block_reflects values row selectorEval rankEval pair.2) + (fun block member => block_reflects values row selectorEval rankEval block) + obtain ⟨result, resultEmitted, resultEval⟩ := continueRow_reflects row rank size continuation + selectorEval incomingEval inputEval normal branchEval emitted + (fun index lower upper => reads index (Nat.le_trans start lower) upper) + (block_reflects values row selectorEval rankEval continuation) + refine ⟨result, ?_, resultEval⟩ + simp only [Bytecode.Ctrl.emitRow_matchContinue, valueRead, branchEmitted, resultEmitted, bind, Option.bind_some] +termination_by sizeOf ctrl +decreasing_by + all_goals subst ctrl + all_goals first + | (have bound := case_block_smaller ‹_ ∈ _›; simp; omega) + | (have bound := fallback_block_smaller ‹_ ∈ _›; simp; omega) + | decreasing_tactic + +theorem block_reflects (values : Values G) (row : Nat → G) + {selectors : Array Expr} {selected : Nat → G} {context : Context} {rank : G} + (selectorEval : SelectorReads values selectors selected) + (rankEval : evalExpr values context.rank = some rank) (block : Bytecode.Block) : + BlockReflects values row selectors selected context rank block := by + intro incoming s rows inputs column lookup emission incomingEval inputEval normal emitted reads + simp only [emitBlock, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i entry entrySelected + dsimp only at emitted + split at emitted + · cases emitted + rename_i operations operationsEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i control controlEmitted + cases emitted + have operationsNormal := emitOps_normal normal operationsEmitted + have endBound := (emitCtrl_invariants block.ctrl operationsNormal controlEmitted).2 + have startBound := emitOps_column operationsEmitted + obtain ⟨opValue, opEmitted, opEval⟩ := emitOps_reflects values row incomingEval rankEval inputEval normal operationsEmitted + (fun index lower upper => reads index lower (by change index < control.column; omega)) + obtain ⟨opValues, columnEq, _, queriesEval, _⟩ := OpsEmission.eval_components opEval + have queryCount := Bytecode.AIR.list_mapM_some_length _ _ _ queriesEval + obtain ⟨result, resultEmitted, resultEval⟩ := ctrl_reflects values row selectorEval rankEval block.ctrl + incomingEval opValues operationsNormal controlEmitted + (fun index lower upper => reads index (Nat.le_trans startBound lower) upper) + have entryEval : evalExpr values entry = some (block.selectorFlow selected).entry := + blockSelector_reads selectorEval block entrySelected + have guard := Expr.frontMul_eval goldilocksLaws values entryEval + (Expr.frontSub_eval goldilocksLaws values (show evalExpr values (.konst 1) = some 1 from rfl) entryEval) + have guarded : [entry.frontMul ((Expr.konst 1).frontSub entry)].mapM (evalExpr values) = + some [AIR.oneSubBooleanConstraint (block.selectorFlow selected).entry] := by + simp only [List.mapM_cons, List.mapM_nil, guard, bind, Option.bind_some, pure, goldilocks_mul, goldilocks_sub] + rfl + refine ⟨_, ?_, Emission.prefix_eval (Emission.afterOps_eval lookup incomingEval opEval resultEval) guarded⟩ + simp only [Bytecode.Block.emitRow, show (context.valued rank).rank = rank from rfl, opEmitted, + bind, Option.bind_some, ← columnEq, queryCount, resultEmitted, pure] +termination_by sizeOf block +decreasing_by exact block_smaller block + +end + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/BlockRowCalls.lean b/Ix/Aiur/Proofs/BlockRowCalls.lean new file mode 100644 index 000000000..3374c311d --- /dev/null +++ b/Ix/Aiur/Proofs/BlockRowCalls.lean @@ -0,0 +1,273 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockRowExecution + +/-! +Every call recorded by the valued block emitter retains its own gate, +function query, rank-byte queries and call-order equation through branching +and continuations. Tracking holds for arbitrary assignments; an active +execution then inherits the inventory required by the rank argument. +-/ + +namespace Aiur.AIR +open Bytecode + +def BlockEmission.HasQuery (emission : BlockEmission) (selector : G) (message : List G) : Prop := + ∃ part ∈ emission.queries, part.selector = selector ∧ part.message = message + +def BlockEmission.TracksCalls (rank : G) (emission : BlockEmission) : Prop := + ∀ part ∈ emission.calls, + emission.HasQuery part.1 (functionMessage part.2.1) ∧ + (∀ message ∈ (rankByteQueries part.2.2).map rangeMessage, emission.HasQuery part.1 message) ∧ + EquationAvailable emission.equations + (part.1 * callOrderConstraint rank part.2.1.rank (packRank part.2.2)) + +theorem BlockEmission.HasQuery.mono {first last : BlockEmission} + (included : first.queries ⊆ last.queries) {selector : G} {message : List G} + (queried : first.HasQuery selector message) : last.HasQuery selector message := by + obtain ⟨part, member, gate, equal⟩ := queried + exact ⟨part, included member, gate, equal⟩ + +theorem BlockEmission.HasQuery.active {emission : BlockEmission} {queries : List (List G)} + (queried : emission.QueriesIn queries) {message : List G} (present : emission.HasQuery 1 message) : + message ∈ queries := by + obtain ⟨part, member, gate, equal⟩ := present + rw [← equal] + exact queried part member gate + +theorem BlockEmission.TracksCalls.prefix {rank : G} {emission : BlockEmission} + (tracked : emission.TracksCalls rank) (equations : List G) : + (emission.prefix equations).TracksCalls rank := by + intro part member + obtain ⟨query, bytes, equation⟩ := tracked part member + exact ⟨query, bytes, equation.mono (fun _ member => List.mem_append_right _ member)⟩ + +theorem BlockEmission.TracksCalls.afterOps {rank incoming : G} {lookup : Nat} + {operations : OpsEmission} {control : BlockEmission} + (opsTracked : CallsEmitted rank incoming operations.equations operations.queries operations.calls) + (ctrlTracked : control.TracksCalls rank) : + (control.afterOps incoming lookup operations).TracksCalls rank := by + intro part member + rcases List.mem_append.mp member with first | last + · obtain ⟨edge, edgeMember, equal⟩ := List.mem_map.mp first + subst part + obtain ⟨query, bytes, equation⟩ := opsTracked edge edgeMember + have memberQuery : ∀ message ∈ operations.queries, + (control.afterOps incoming lookup operations).HasQuery incoming message := by + intro message member + obtain ⟨query, queryMember, gate, equal⟩ := queryParts_member lookup incoming member + exact ⟨query, List.mem_append_left _ queryMember, gate, equal⟩ + exact ⟨memberQuery _ query, fun message member => memberQuery message (bytes member), + equation.mono (fun _ member => List.mem_append_left _ member)⟩ + · obtain ⟨query, bytes, equation⟩ := ctrlTracked part last + exact ⟨query.mono (fun _ member => List.mem_append_right _ member), + fun message member => (bytes message member).mono (fun _ member => List.mem_append_right _ member), + equation.mono (fun _ member => List.mem_append_right _ member)⟩ + +theorem BlockEmission.TracksCalls.join (rank : G) (values : Array RowValue) (column lookup : Nat) + (emissions : List BlockEmission) (tracked : ∀ emission ∈ emissions, emission.TracksCalls rank) : + (joinBlockEmissions values column lookup emissions).TracksCalls rank := by + intro part member + obtain ⟨emission, emissionMember, partMember⟩ := List.mem_flatMap.mp member + obtain ⟨query, bytes, equation⟩ := tracked emission emissionMember part partMember + have included := EmissionIncluded.join values column lookup emissionMember + exact ⟨query.mono included.queries, fun message member => (bytes message member).mono included.queries, + equation.mono included.equations⟩ + +theorem BlockEmission.TracksCalls.continued {rank : G} {branches continuation : BlockEmission} + (first : branches.TracksCalls rank) (last : continuation.TracksCalls rank) (equations : List G) : + (branches.continued equations continuation).TracksCalls rank := by + intro part member + rcases List.mem_append.mp member with left | right + · obtain ⟨query, bytes, equation⟩ := first part left + exact ⟨query.mono (fun _ member => List.mem_append_left _ member), + fun message member => (bytes message member).mono (fun _ member => List.mem_append_left _ member), + equation.mono (fun _ member => List.mem_append_left _ (List.mem_append_left _ member))⟩ + · obtain ⟨query, bytes, equation⟩ := last part right + exact ⟨query.mono (fun _ member => List.mem_append_right _ member), + fun message member => (bytes message member).mono (fun _ member => List.mem_append_right _ member), + equation.mono (fun _ member => List.mem_append_right _ member)⟩ + +theorem BlockEmission.TracksCalls.active {rank : G} {emission : BlockEmission} + (tracked : emission.TracksCalls rank) + {queries : List (List G)} (queried : emission.QueriesIn queries) + {calls : List (Bytecode.AIR.Call × (Fin 6 → G))} (called : emission.CallsAt calls) : + CallsEmitted rank 1 emission.equations queries calls := by + intro edge member + obtain ⟨query, bytes, equation⟩ := tracked (1, edge) (called edge member) + exact ⟨query.active queried, fun _ member => (bytes _ member).active queried, equation⟩ + +theorem forall₂_right_property {α β : Type} {source : List α} {emissions : List β} {property : β → Prop} + (related : List.Forall₂ (fun _ emission => property emission) source emissions) : + ∀ emission ∈ emissions, property emission := by + induction related with + | nil => simp + | cons first _ ih => + intro emission member + rcases List.mem_cons.mp member with equal | tail + · subst emission; exact first + · exact ih emission tail + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem branchRows_tracks_calls (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + (caseSound : ∀ pair ∈ branches.toList, ∀ emission, + pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → + emission.TracksCalls context.rank) + (defaultSound : ∀ block, fallback = some block → ∀ emission, + block.emitRow row selector context (block.selectorFlow selector).entry values + (column + branches.size) lookup = some emission → emission.TracksCalls context.rank) : + emission.TracksCalls context.rank := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i default defaultEmitted + have equal := Option.some.inj emitted + subst emission + have casesTracked : ∀ emission ∈ cases, emission.TracksCalls context.rank := by + apply forall₂_right_property + apply mapM_forall₂ casesEmitted + intro pair member result resultEmitted + simp only [caseRow, bind, Option.bind] at resultEmitted + split at resultEmitted + · cases resultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj resultEmitted + subst result + exact (caseSound pair member body bodyEmitted).prefix _ + have defaultTracked : ∀ emission ∈ default, emission.TracksCalls context.rank := by + cases fallback with + | none => + simp only [defaultRow, Option.some.injEq] at defaultEmitted + subst default + simp + | some block => + simp only [defaultRow, bind, Option.bind] at defaultEmitted + split at defaultEmitted + · cases defaultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj defaultEmitted + subst default + intro emission member + have equal := List.mem_singleton.mp member + subst emission + exact (defaultSound block rfl body bodyEmitted).prefix _ + apply BlockEmission.TracksCalls.join + intro emission member + rcases List.mem_append.mp member with left | right + · exact casesTracked emission left + · exact defaultTracked emission right + +private theorem block_call_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +theorem Ctrl.emitRow_tracks_calls (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) + {emission : BlockEmission} + (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) : + emission.TracksCalls context.rank := by + cases ctrl with + | «return» index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · dsimp only at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + simp [BlockEmission.TracksCalls] + | yield index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + simp [BlockEmission.TracksCalls] + | «match» index branches fallback => + rw [Ctrl.emitRow_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + apply branchRows_tracks_calls row selector context matched.value values column lookup branches fallback emitted + · intro pair member body bodyEmitted + exact Block.emitRow_tracks_calls row selector context _ values column lookup pair.2 bodyEmitted + · intro block present body bodyEmitted + exact Block.emitRow_tracks_calls row selector context _ values _ lookup block bodyEmitted + | matchContinue index branches fallback size aux slots continuation => + rw [Ctrl.emitRow_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + dsimp only at emitted + split at emitted + · cases emitted + · rename_i joined branchesEmitted + have branchesTracked := branchRows_tracks_calls row selector context matched.value values column lookup + branches fallback branchesEmitted + (fun pair member body bodyEmitted => + Block.emitRow_tracks_calls row selector context _ values column lookup pair.2 bodyEmitted) + (fun block present body bodyEmitted => + Block.emitRow_tracks_calls row selector context _ values _ lookup block bodyEmitted) + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i continued contEmitted + have contTracked := Block.emitRow_tracks_calls row selector context _ _ _ _ continuation contEmitted + have equal := Option.some.inj emitted + subst emission + exact branchesTracked.continued contTracked _ + · cases emitted +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr ‹_ ∈ _›); grind) + +theorem Block.emitRow_tracks_calls (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) : + emission.TracksCalls context.rank := by + rw [Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i operations opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i control ctrlEmitted + have tracked := Ctrl.emitRow_tracks_calls row selector context incoming _ _ _ block.ctrl ctrlEmitted + have equal := Option.some.inj emitted + subst emission + exact (BlockEmission.TracksCalls.afterOps (emitOps_calls opsEmitted) tracked).prefix _ +termination_by sizeOf block +decreasing_by exact block_call_smaller block + +end + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BlockRowExecution.lean b/Ix/Aiur/Proofs/BlockRowExecution.lean new file mode 100644 index 000000000..9cd3c81ab --- /dev/null +++ b/Ix/Aiur/Proofs/BlockRowExecution.lean @@ -0,0 +1,666 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockRowProjection + +/-! +Execution extraction from the valued block emitter, covering operations, +case and default selection, early returns, and continuation merges. The +proof follows the actual emitted equations and logical value map. + +Active raw queries must belong to the global lookup pool, and the explicit +branch and terminal counts must fit the field characteristic. Deriving +these premises from shared slots and validated native layouts is separate. +-/ + +namespace Aiur.AIR +open Bytecode + +theorem selector_pair_split {α : Type} {parts : List (G × α)} + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) : + ∃ before chosen after, parts = before ++ chosen :: after ∧ chosen.1 = 1 ∧ + ∀ part ∈ before ++ after, part.1 = 0 := by + obtain ⟨before, after, split, zero⟩ := selectorSum_active_split + (fun value member => by + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst value + exact individual part partMember) + (by simpa only [List.length_map] using bounded) active + obtain ⟨first, rest, partsEq, firstEq, restEq⟩ := List.map_eq_append_iff.mp split + obtain ⟨chosen, last, tailEq, activeChosen, lastEq⟩ := List.map_eq_cons_iff.mp restEq + refine ⟨first, chosen, last, by rw [partsEq, tailEq], activeChosen, ?_⟩ + intro part member + apply zero part.1 + rcases List.mem_append.mp member with firstMember | lastMember + · apply List.mem_append_left + rw [← firstEq] + exact List.mem_map.mpr ⟨part, firstMember, rfl⟩ + · apply List.mem_append_right + rw [← lastEq] + exact List.mem_map.mpr ⟨part, lastMember, rfl⟩ + +theorem selector_pair_chosen {α : Type} {parts : List (G × α)} + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) + {chosen : G × α} (member : chosen ∈ parts) (selected : chosen.1 = 1) : + ∃ before after, parts = before ++ chosen :: after ∧ + ∀ part ∈ before ++ after, part.1 = 0 := by + obtain ⟨before, other, after, equal, _, zero⟩ := selector_pair_split individual bounded active + rw [equal] at member + rcases List.mem_append.mp member with left | tail + · have inactive := zero chosen (List.mem_append_left _ left) + exact False.elim (G.one_ne_zero (selected.symm.trans inactive)) + · rcases List.mem_cons.mp tail with same | right + · subst chosen + exact ⟨before, after, equal, zero⟩ + · have inactive := zero chosen (List.mem_append_right _ right) + exact False.elim (G.one_ne_zero (selected.symm.trans inactive)) + +theorem selector_weighted_zero {α : Type} (read : α → G) {parts : List (G × α)} + (zero : ∀ part ∈ parts, part.1 = 0) : + selectorSum (parts.map fun part => part.1 * read part.2) = 0 := by + induction parts with + | nil => rfl + | cons part parts ih => + rw [List.map_cons, selectorSum_cons, zero part List.mem_cons_self, + G.mul_comm 0, G.mul_zero, G.zero_add] + exact ih (fun part member => zero part (List.mem_cons_of_mem _ member)) + +theorem selector_weighted_chosen {α : Type} (read : α → G) {parts : List (G × α)} + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) + {chosen : G × α} (member : chosen ∈ parts) (selected : chosen.1 = 1) : + selectorSum (parts.map fun part => part.1 * read part.2) = read chosen.2 := by + obtain ⟨before, after, equal, zero⟩ := selector_pair_chosen individual bounded active member selected + rw [equal, List.map_append, selectorSum_append, + selector_weighted_zero read (fun part member => zero part (List.mem_append_left _ member)), + G.zero_add, List.map_cons, selectorSum_cons, + selector_weighted_zero read (fun part member => zero part (List.mem_append_right _ member)), + G.add_zero, selected, G.mul_comm, G.mul_one] + +theorem mergeEquations_chosen (row : Nat → G) {parent : G} {column size : Nat} + {parts : List (G × Array RowValue)} (parentActive : parent = 1) + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) + {chosen : Array RowValue} (member : (1, chosen) ∈ parts) (width : chosen.size = size) + (equations : ∀ equation ∈ mergeEquations row parent column size parts, equation = 0) : + rowValues (rowAdvice row column size) = rowValues chosen := by + apply Array.ext (by + rw [rowValues_advice_size] + simpa only [rowValues, Array.size_map] using width.symm) + intro index leftBound rightBound + have bound : index < size := by simpa only [rowValues_advice_size] using leftBound + have polynomial := equations _ (List.mem_map.mpr ⟨index, List.mem_range.mpr bound, rfl⟩) + change parent * (row (column + index) - selectorSum + (parts.map fun part => part.1 * (rowValues part.2)[index]?.getD 0)) = 0 at polynomial + rw [selector_weighted_chosen (fun values => (rowValues values)[index]?.getD 0) + individual bounded active member rfl] at polynomial + have equal := active_case parentActive polynomial + rw [Array.getElem?_eq_getElem rightBound, Option.getD_some] at equal + simpa only [rowValues, rowAdvice, Array.getElem_map, Array.getElem_ofFn, + RowValue.variable, Fin.getElem_fin] using equal + +def BlockEmission.QueriesIn (emission : BlockEmission) (queries : List (List G)) : Prop := + ∀ part ∈ emission.queries, part.selector = 1 → part.message ∈ queries + +def BlockEmission.CallsAt (emission : BlockEmission) + (calls : List (Bytecode.AIR.Call × (Fin 6 → G))) : Prop := + ∀ edge ∈ calls, (1, edge) ∈ emission.calls + +def BlockEmission.TerminalAt (emission : BlockEmission) : Bytecode.AIR.Outcome → Prop + | .returned outputs => ∃ request, (1, request) ∈ emission.returns ∧ request.outputs = outputs + | .yielded outputs => ∃ yielded, (1, yielded) ∈ emission.yields ∧ rowValues yielded = outputs + +structure EmissionIncluded (part whole : BlockEmission) : Prop where + equations : part.equations ⊆ whole.equations + queries : part.queries ⊆ whole.queries + returns : part.returns ⊆ whole.returns + yields : part.yields ⊆ whole.yields + calls : part.calls ⊆ whole.calls + +theorem EmissionIncluded.refl (emission : BlockEmission) : EmissionIncluded emission emission := + ⟨List.Subset.refl _, List.Subset.refl _, List.Subset.refl _, List.Subset.refl _, List.Subset.refl _⟩ + +theorem EmissionIncluded.trans {first middle last : BlockEmission} + (left : EmissionIncluded first middle) (right : EmissionIncluded middle last) : + EmissionIncluded first last := + ⟨left.equations.trans right.equations, left.queries.trans right.queries, + left.returns.trans right.returns, left.yields.trans right.yields, left.calls.trans right.calls⟩ + +theorem EmissionIncluded.prefix (emission : BlockEmission) (equations : List G) : + EmissionIncluded emission (emission.prefix equations) := + ⟨fun _ member => List.mem_append_right _ member, List.Subset.refl _, + List.Subset.refl _, List.Subset.refl _, List.Subset.refl _⟩ + +theorem EmissionIncluded.join (values : Array RowValue) (column lookup : Nat) + {emissions : List BlockEmission} {emission : BlockEmission} (member : emission ∈ emissions) : + EmissionIncluded emission (joinBlockEmissions values column lookup emissions) := by + constructor <;> exact fun _ present => List.mem_flatMap.mpr ⟨emission, member, present⟩ + +theorem EmissionIncluded.satisfied {part whole : BlockEmission} (included : EmissionIncluded part whole) + (satisfied : ∀ equation ∈ whole.equations, equation = 0) : + ∀ equation ∈ part.equations, equation = 0 := + fun equation member => satisfied equation (included.equations member) + +theorem EmissionIncluded.queried {part whole : BlockEmission} (included : EmissionIncluded part whole) + {queries : List (List G)} (queried : whole.QueriesIn queries) : part.QueriesIn queries := + fun query member active => queried query (included.queries member) active + +theorem EmissionIncluded.terminal {part whole : BlockEmission} (included : EmissionIncluded part whole) + {outcome : Bytecode.AIR.Outcome} (terminal : part.TerminalAt outcome) : whole.TerminalAt outcome := by + cases outcome with + | returned outputs => + obtain ⟨request, member, equal⟩ := terminal + exact ⟨request, included.returns member, equal⟩ + | yielded outputs => + obtain ⟨values, member, equal⟩ := terminal + exact ⟨values, included.yields member, equal⟩ + +theorem EmissionIncluded.called {part whole : BlockEmission} (included : EmissionIncluded part whole) + {calls : List (Bytecode.AIR.Call × (Fin 6 → G))} (called : part.CallsAt calls) : whole.CallsAt calls := + fun edge member => included.calls (called edge member) + +theorem forall₂_left_member {α β : Type} {relation : α → β → Prop} {source : List α} + {emissions : List β} (related : List.Forall₂ relation source emissions) {item : α} + (member : item ∈ source) : ∃ emission ∈ emissions, relation item emission := by + induction related with + | nil => cases member + | @cons head emission heads emissions first rest ih => + rcases List.mem_cons.mp member with equal | tail + · subst item + exact ⟨emission, List.mem_cons_self, first⟩ + · obtain ⟨body, bodyMember, correct⟩ := ih tail + exact ⟨body, List.mem_cons_of_mem _ bodyMember, correct⟩ + +theorem mapM_member {α β : Type} {source : List α} {emissions : List β} {emit : α → Option β} + (emitted : source.mapM emit = some emissions) {item : α} (member : item ∈ source) : + ∃ emission ∈ emissions, emit item = some emission := + forall₂_left_member (mapM_forall₂ emitted (fun _ _ _ equal => equal)) member + +theorem mapM_of_forall₂ {α β : Type} {source : List α} {emissions : List β} {emit : α → Option β} + (related : List.Forall₂ (fun item emission => emit item = some emission) source emissions) : + source.mapM emit = some emissions := by + induction related with + | nil => rfl + | cons first _ ih => rw [List.mapM_cons, first, ih]; rfl + +theorem readRowValues (values : Array RowValue) (indices : Array ValIdx) (outputs : List RowValue) + (read : indices.toList.mapM (fun index => values[index]?) = some outputs) : + Bytecode.AIR.readValues (rowValues values) indices = some (rowValues outputs.toArray) := by + have related := mapM_forall₂ read (fun _ _ _ equal => equal) + have mapped : List.Forall₂ (fun index value => (rowValues values)[index]? = some value) + indices.toList (outputs.map RowValue.value) := by + generalize sourceEq : indices.toList = source at related ⊢ + clear read sourceEq + induction related with + | nil => exact .nil + | cons first _ ih => exact .cons (rowValues_read first) ih + have result := mapM_of_forall₂ mapped + have listResult : (Array.toList <$> Bytecode.AIR.readValues (rowValues values) indices) = + some (rowValues outputs.toArray).toList := by + rw [Bytecode.AIR.readValues, Array.toList_mapM] + simpa only [rowValues, Array.toList_map, List.toList_toArray] using result + cases emitted : Bytecode.AIR.readValues (rowValues values) indices with + | none => rw [emitted] at listResult; cases listResult + | some array => + rw [emitted] at listResult + have equal := Array.toList_inj.mp (Option.some.inj listResult) + exact congrArg some equal + +theorem queryParts_member (slot : Nat) (selector : G) {queries : List (List G)} {message : List G} + (member : message ∈ queries) : + ∃ part ∈ queryParts slot selector queries, part.selector = selector ∧ part.message = message := by + obtain ⟨index, bound, equal⟩ := List.mem_iff_getElem.mp member + refine ⟨⟨slot + index, selector, message⟩, ?_, rfl, rfl⟩ + exact List.mem_mapIdx.mpr ⟨index, bound, by rw [equal]⟩ + +theorem EmissionIncluded.afterOps (incoming : G) (lookup : Nat) (operations : OpsEmission) + (control : BlockEmission) : EmissionIncluded control (control.afterOps incoming lookup operations) := + ⟨fun _ member => List.mem_append_right _ member, + fun _ member => List.mem_append_right _ member, List.Subset.refl _, List.Subset.refl _, + fun _ member => List.mem_append_right _ member⟩ + +theorem BlockEmission.afterOps_queried {incoming : G} {lookup : Nat} {operations : OpsEmission} + {control : BlockEmission} {queries : List (List G)} (active : incoming = 1) + (queried : (control.afterOps incoming lookup operations).QueriesIn queries) : + operations.queries ⊆ queries := by + intro message member + obtain ⟨part, partMember, gate, equal⟩ := queryParts_member lookup incoming member + rw [← equal] + exact queried part (List.mem_append_left _ partMember) (gate.trans active) + +theorem BlockEmission.afterOps_called {incoming : G} {lookup : Nat} {operations : OpsEmission} + {control : BlockEmission} {calls : List (Bytecode.AIR.Call × (Fin 6 → G))} + (active : incoming = 1) (called : control.CallsAt calls) : + (control.afterOps incoming lookup operations).CallsAt (operations.calls ++ calls) := by + intro edge member + rcases List.mem_append.mp member with first | rest + · exact List.mem_append_left _ (List.mem_map.mpr ⟨edge, first, by rw [active]⟩) + · exact List.mem_append_right _ (called edge rest) + +theorem EmissionIncluded.continued (branches : BlockEmission) (equations : List G) + (continuation : BlockEmission) : EmissionIncluded continuation (branches.continued equations continuation) := + ⟨fun _ member => List.mem_append_right _ member, + fun _ member => List.mem_append_right _ member, + fun _ member => List.mem_append_right _ member, List.Subset.refl _, + fun _ member => List.mem_append_right _ member⟩ + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +private theorem row_bounds_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def Ctrl.rowBounds (selector : SelIdx → G) : Ctrl → Prop + | .return .. | .yield .. => True + | .match _ branches fallback => + branches.size + fallback.toList.length < gSize.toNat ∧ + (∀ pair ∈ branches.toList, pair.2.rowBounds selector) ∧ + (match fallback with | none => True | some block => block.rowBounds selector) + | .matchContinue _ branches fallback _ _ _ continuation => + let flow := SelectorFlow.join (branchSelectorFlows selector branches fallback) + branches.size + fallback.toList.length < gSize.toNat ∧ + flow.returns.length + flow.yields.length < gSize.toNat ∧ + (∀ pair ∈ branches.toList, pair.2.rowBounds selector) ∧ + (match fallback with | none => True | some block => block.rowBounds selector) ∧ + continuation.rowBounds selector +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr ‹_ ∈ _›); grind) + +def Block.rowBounds (selector : SelIdx → G) (block : Block) : Prop := + block.ctrl.rowBounds selector +termination_by sizeOf block +decreasing_by exact row_bounds_smaller block + +end + +theorem AIR.SelectArm.rowBounds {selector : SelIdx → G} {matched : G} + {branches : Array (G × Block)} {fallback : Option Block} {block : Block} + (selected : SelectArm matched branches fallback block) + (casesBounded : ∀ pair ∈ branches.toList, pair.2.rowBounds selector) + (fallbackBounded : ∀ block, fallback = some block → block.rowBounds selector) : + block.rowBounds selector := by + cases selected with + | case member => exact casesBounded _ member + | fallback present unmatched => exact fallbackBounded block present + +theorem AIR.SelectArm.smaller_match {matched : G} {branches : Array (G × Block)} + {fallback : Option Block} {block : Block} (selected : SelectArm matched branches fallback block) + (index : ValIdx) : sizeOf block < sizeOf (Ctrl.match index branches fallback) := by + cases selected with + | case member => + have bound := Array.sizeOf_lt_of_mem (Array.mem_def.mpr member) + simp only [Prod.mk.sizeOf_spec, Ctrl.match.sizeOf_spec] at * + omega + | fallback present unmatched => rw [present]; simp; omega + +theorem AIR.SelectArm.smaller_matchContinue {matched : G} {branches : Array (G × Block)} + {fallback : Option Block} {block : Block} (selected : SelectArm matched branches fallback block) + (index : ValIdx) (size aux slots : Nat) (continuation : Block) : + sizeOf block < sizeOf (Ctrl.matchContinue index branches fallback size aux slots continuation) := by + cases selected with + | case member => + have bound := Array.sizeOf_lt_of_mem (Array.mem_def.mpr member) + simp only [Prod.mk.sizeOf_spec, Ctrl.matchContinue.sizeOf_spec] at * + omega + | fallback present unmatched => rw [present]; simp; omega + +theorem branchRows_polynomials (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + MatchPolynomials selector matched branches fallback := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i default defaultEmitted + have equal := Option.some.inj emitted + subst emission + constructor + · intro pair member + obtain ⟨result, resultMember, resultEmitted⟩ := mapM_member casesEmitted member + simp only [caseRow, bind, Option.bind] at resultEmitted + split at resultEmitted + · cases resultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj resultEmitted + subst result + exact satisfied _ ((EmissionIncluded.join values column lookup + (List.mem_append_left _ resultMember)).equations List.mem_cons_self) + · intro block present pair member + rw [present] at defaultEmitted + simp only [defaultRow, bind, Option.bind] at defaultEmitted + split at defaultEmitted + · cases defaultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj defaultEmitted + subst default + obtain ⟨index, bound, selected⟩ := List.mem_iff_getElem.mp member + refine ⟨row (column + index), ?_⟩ + apply satisfied + apply (EmissionIncluded.join values column lookup + (List.mem_append_right cases List.mem_cons_self)).equations + apply List.mem_append_left + exact List.mem_mapIdx.mpr ⟨index, bound, by rw [selected]⟩ + +theorem branchRows_body (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + {block : Block} (selected : AIR.SelectArm matched branches fallback block) : + ∃ bodyColumn body, + block.emitRow row selector context (block.selectorFlow selector).entry values bodyColumn lookup = some body ∧ + EmissionIncluded body emission := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i default defaultEmitted + have equal := Option.some.inj emitted + subst emission + cases selected with + | case member => + obtain ⟨result, resultMember, resultEmitted⟩ := mapM_member casesEmitted member + simp only [caseRow, bind, Option.bind] at resultEmitted + split at resultEmitted + · cases resultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj resultEmitted + subst result + exact ⟨column, body, bodyEmitted, + (EmissionIncluded.prefix body _).trans + (EmissionIncluded.join values column lookup (List.mem_append_left _ resultMember))⟩ + | fallback present unmatched => + rw [present] at defaultEmitted + simp only [defaultRow, bind, Option.bind] at defaultEmitted + split at defaultEmitted + · cases defaultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj defaultEmitted + subst default + exact ⟨column + branches.size, body, bodyEmitted, + (EmissionIncluded.prefix body _).trans + (EmissionIncluded.join values column lookup + (List.mem_append_right _ List.mem_cons_self))⟩ + +theorem branchRows_selector_projection (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) : + EmissionProjection (SelectorFlow.join (branchSelectorFlows selector branches fallback)) + (branchReturnGates selector branches fallback) emission := + branchRows_projection row selector context matched values column lookup branches fallback emitted + (fun pair _ _ bodyEmitted => pair.2.emitRow_projection row selector context _ _ _ _ bodyEmitted) + (fun block _ _ bodyEmitted => block.emitRow_projection row selector context _ _ _ _ bodyEmitted) + +theorem branchRows_selected (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (bounded : branches.size + fallback.toList.length < gSize.toNat) + (active : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).entry = 1) : + ∃ block bodyColumn body, AIR.SelectArm matched branches fallback block ∧ + (block.selectorFlow selector).entry = 1 ∧ + block.emitRow row selector context (block.selectorFlow selector).entry values bodyColumn lookup = some body ∧ + EmissionIncluded body emission := by + have projected := branchRows_selector_projection row selector context matched values column lookup + branches fallback emitted + have polynomials := branchRows_polynomials row selector context matched values column lookup + branches fallback emitted satisfied + obtain ⟨block, selected, _, blockActive⟩ := polynomials.active_branch + (fun equation member => satisfied equation (projected.equations member)) bounded active + obtain ⟨bodyColumn, body, bodyEmitted, included⟩ := branchRows_body row selector context matched values + column lookup branches fallback emitted selected + exact ⟨block, bodyColumn, body, selected, blockActive, bodyEmitted, included⟩ + +mutual + +theorem Ctrl.emitRow_run {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (program : Toplevel) (yieldSize : Option Nat) + (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) + (shape : ctrl.lookupShapes program yieldSize = true) (bounds : ctrl.rowBounds selector) + {emission : BlockEmission} + (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) + (active : incoming = 1) (linked : incoming = (ctrl.selectorFlow selector).entry) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.QueriesIn queries) : + ∃ outcome calls, + AIR.RunCtrl (memoryFacts tables.memory) ctrl (rowValues values) outcome (calls.map Prod.fst) ∧ + emission.TerminalAt outcome ∧ emission.CallsAt calls := by + cases ctrl with + | «return» index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i inputs readInputs + dsimp only at emitted + split at emitted + · cases emitted + · rename_i outputs readOutputs + have equal := Option.some.inj emitted + subst emission + refine ⟨.returned outputs, [], AIR.RunCtrl.returned readOutputs, ?_, by simp [BlockEmission.CallsAt]⟩ + refine ⟨⟨context.function, inputs, outputs, context.rank⟩, ?_, rfl⟩ + change (1, _) ∈ [(incoming, _)] + rw [active] + exact List.mem_cons_self + | yield index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i outputs readOutputs + have equal := Option.some.inj emitted + subst emission + rw [Ctrl.selectorFlow.eq_def] at linked + have selected : selector index = 1 := linked.symm.trans active + refine ⟨.yielded (rowValues outputs.toArray), [], + AIR.RunCtrl.yielded (readRowValues values indices outputs readOutputs), ?_, + by simp [BlockEmission.CallsAt]⟩ + exact ⟨outputs.toArray, by change (1, _) ∈ [(selector index, _)]; rw [selected]; exact List.mem_cons_self, rfl⟩ + | «match» index branches fallback => + rw [Ctrl.emitRow_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + rw [Ctrl.rowBounds.eq_def] at bounds + obtain ⟨branchBound, casesBounded, fallbackBounded⟩ := bounds + obtain ⟨casesShape, fallbackShape⟩ := (lookupShapes_match _ _ _ _ _).mp shape + rw [Ctrl.selectorFlow_match] at linked + obtain ⟨arm, bodyColumn, body, selected, armActive, bodyEmitted, included⟩ := + branchRows_selected row selector context matched.value values column lookup branches fallback + emitted satisfied branchBound (linked.symm.trans active) + have smaller := selected.smaller_match index + obtain ⟨outcome, calls, execution, terminal, called⟩ := Block.emitRow_run global memoryValid canonical + program yieldSize row selector context _ values bodyColumn lookup arm + (selected.lookupShapes program yieldSize casesShape fallbackShape) + (selected.rowBounds casesBounded (fun block present => by + rw [present] at fallbackBounded; exact fallbackBounded)) bodyEmitted armActive rfl + (included.satisfied satisfied) (included.queried queried) + exact ⟨outcome, calls, AIR.RunCtrl.match (rowValues_read read) selected execution, + included.terminal terminal, included.called called⟩ + | matchContinue index branches fallback size aux slots continuation => + rw [Ctrl.emitRow_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + dsimp only at emitted + split at emitted + · cases emitted + · rename_i joined branchesEmitted + simp only [continueRow] at emitted + split at emitted + · rename_i sizes + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i continued contEmitted + have equal := Option.some.inj emitted + subst emission + rw [Ctrl.rowBounds.eq_def] at bounds + obtain ⟨branchBound, terminalBound, casesBounded, fallbackBounded, contBounded⟩ := bounds + obtain ⟨casesShape, fallbackShape, contShape⟩ := + (lookupShapes_matchContinue _ _ _ _ _ _ _ _ _).mp shape + rw [Ctrl.selectorFlow_matchContinue] at linked + have joinedActive : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).entry = 1 := + linked.symm.trans active + have joinedSatisfied : ∀ equation ∈ joined.equations, equation = 0 := + fun equation member => satisfied equation + (List.mem_append_left _ (List.mem_append_left _ member)) + have joinedQueried : joined.QueriesIn queries := + fun part member gate => queried part (List.mem_append_left _ member) gate + obtain ⟨arm, bodyColumn, body, selected, armActive, bodyEmitted, included⟩ := + branchRows_selected row selector context matched.value values column lookup branches fallback + branchesEmitted joinedSatisfied branchBound joinedActive + have smaller := selected.smaller_matchContinue index size aux slots continuation + obtain ⟨outcome, calls, execution, terminal, called⟩ := Block.emitRow_run global memoryValid canonical + program (some size) row selector context _ values bodyColumn lookup arm + (selected.lookupShapes program (some size) casesShape fallbackShape) + (selected.rowBounds casesBounded (fun block present => by + rw [present] at fallbackBounded; exact fallbackBounded)) bodyEmitted armActive rfl + (included.satisfied joinedSatisfied) (included.queried joinedQueried) + have joinedTerminal := included.terminal terminal + have joinedCalls := included.called called + cases outcome with + | returned outputs => + refine ⟨.returned outputs, calls, + AIR.RunCtrl.matchContinueReturn (rowValues_read read) selected execution, ?_, ?_⟩ + · obtain ⟨request, member, equal⟩ := joinedTerminal + exact ⟨request, List.mem_append_left _ member, equal⟩ + · exact fun edge member => List.mem_append_left _ (joinedCalls edge member) + | yielded outputs => + obtain ⟨yielded, yieldMember, yieldEqual⟩ := joinedTerminal + have projected := branchRows_selector_projection row selector context matched.value values column lookup + branches fallback branchesEmitted + have flowValid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied := + fun equation member => joinedSatisfied equation (projected.equations member) + have flowSound := branchSelectorFlows_sound selector branches fallback flowValid + (fun pair _ valid => pair.2.selectorFlow_sound selector valid) + (fun block _ valid => block.selectorFlow_sound selector valid) + have oneYield : (1 : G) ∈ (SelectorFlow.join (branchSelectorFlows selector branches fallback)).yields := by + rw [← projected.yielded] + exact List.mem_map.mpr ⟨(1, yielded), yieldMember, rfl⟩ + have gateOne : selectorSum (joined.yields.map Prod.fst) = 1 := by + rw [projected.yielded] + exact flowSound.yield_starts_continuation terminalBound joinedActive oneYield + have link : (continuation.selectorFlow selector).entry = selectorSum (joined.yields.map Prod.fst) := by + apply (G.sub_eq_zero_iff _ _).mp + apply satisfied + exact List.mem_append_left _ (List.mem_append_right _ + (List.mem_append_right _ List.mem_cons_self)) + have yieldWidth : yielded.size = size := + beq_iff_eq.mp ((List.all_eq_true.mp sizes) _ yieldMember) + have yieldBound : joined.yields.length < gSize.toNat := by + have lengths := congrArg List.length projected.yielded + simp only [List.length_map] at lengths + omega + have yieldBoolean : ∀ part ∈ joined.yields, booleanConstraint part.1 = 0 := by + intro part member + apply flowSound.yielded + rw [← projected.yielded] + exact List.mem_map.mpr ⟨part, member, rfl⟩ + have mergeValues := mergeEquations_chosen row active yieldBoolean yieldBound gateOne + yieldMember yieldWidth (fun equation member => satisfied equation + (List.mem_append_left _ (List.mem_append_right _ (List.mem_append_left _ member)))) + have contIncluded := EmissionIncluded.continued joined + (mergeEquations row incoming joined.column size joined.yields ++ + [(continuation.selectorFlow selector).entry - selectorSum (joined.yields.map Prod.fst)]) continued + obtain ⟨result, contCalls, contRun, contTerminal, contCallsAt⟩ := + Block.emitRow_run global memoryValid canonical program yieldSize row selector context _ _ _ _ + continuation contShape contBounded contEmitted gateOne link.symm + (contIncluded.satisfied satisfied) (contIncluded.queried queried) + rw [rowValues_append, mergeValues, yieldEqual] at contRun + have outputSize : outputs.size = size := by + rw [← yieldEqual] + simpa only [rowValues, Array.size_map] using yieldWidth + refine ⟨result, calls ++ contCalls, ?_, contIncluded.terminal contTerminal, ?_⟩ + · simpa only [List.map_append] using + AIR.RunCtrl.matchContinueYield (rowValues_read read) selected execution outputSize contRun + · intro edge member + rcases List.mem_append.mp member with first | last + · exact List.mem_append_left _ (joinedCalls edge first) + · exact List.mem_append_right _ (contCallsAt edge last) + · cases emitted +termination_by sizeOf ctrl +decreasing_by all_goals first | decreasing_tactic | omega + +theorem Block.emitRow_run {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (program : Toplevel) (yieldSize : Option Nat) + (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + (shape : block.lookupShapes program yieldSize = true) (bounds : block.rowBounds selector) + {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) + (active : incoming = 1) (linked : incoming = (block.selectorFlow selector).entry) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.QueriesIn queries) : + ∃ outcome calls, + AIR.RunBlock (memoryFacts tables.memory) block (rowValues values) outcome (calls.map Prod.fst) ∧ + emission.TerminalAt outcome ∧ emission.CallsAt calls := by + rw [Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i operations opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i control ctrlEmitted + have equal := Option.some.inj emitted + subst emission + have tailIncluded := EmissionIncluded.prefix (control.afterOps incoming lookup operations) + [oneSubBooleanConstraint (block.selectorFlow selector).entry] + have controlIncluded := (EmissionIncluded.afterOps incoming lookup operations control).trans tailIncluded + rw [Block.lookupShapes, Bool.and_eq_true] at shape + have opsRun := emitOps_run global memoryValid canonical + (fun op member => (Array.all_eq_true'.mp shape.1) op (Array.mem_def.mpr member)) + opsEmitted active + (fun equation member => (tailIncluded.satisfied satisfied) equation (List.mem_append_left _ member)) + (BlockEmission.afterOps_queried active (tailIncluded.queried queried)) + obtain ⟨outcome, calls, ctrlRun, terminal, called⟩ := Ctrl.emitRow_run global memoryValid canonical + program yieldSize row selector context incoming _ _ _ block.ctrl shape.2 + (by rwa [Block.rowBounds] at bounds) ctrlEmitted active + (by simpa only [Block.selectorFlow] using linked) + (controlIncluded.satisfied satisfied) (controlIncluded.queried queried) + refine ⟨outcome, operations.calls ++ calls, ?_, controlIncluded.terminal terminal, ?_⟩ + · simpa only [List.map_append] using AIR.RunBlock.block opsRun ctrlRun + · exact tailIncluded.called (BlockEmission.afterOps_called active called) +termination_by sizeOf block +decreasing_by exact row_bounds_smaller block + +end + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BlockRowInputs.lean b/Ix/Aiur/Proofs/BlockRowInputs.lean new file mode 100644 index 000000000..22870e7e6 --- /dev/null +++ b/Ix/Aiur/Proofs/BlockRowInputs.lean @@ -0,0 +1,312 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockRowCalls + +/-! +Input-prefix preservation through the valued block emitter. Operation +outputs and continuation merges append logical values, while branch joins +restore their incoming scope. Every emitted return therefore identifies +the original function, inputs and rank, including on inactive branches. +-/ + +namespace Aiur.AIR +open Bytecode + +theorem option_array_eq_of_toList {α : Type} {result : Option (Array α)} {expected : Array α} + (equal : (Array.toList <$> result) = some expected.toList) : result = some expected := by + cases result with + | none => cases equal + | some array => exact congrArg some (Array.toList_inj.mp (Option.some.inj equal)) + +theorem forall₂_imp {α β : Type} {source : List α} {target : List β} + {first last : α → β → Prop} (related : List.Forall₂ first source target) + (implies : ∀ left right, first left right → last left right) : + List.Forall₂ last source target := by + induction related with + | nil => exact .nil + | cons head _ ih => exact .cons (implies _ _ head) ih + +theorem forall₂_of_get {α β : Type} {source : List α} {target : List β} {relation : α → β → Prop} + (sizes : source.length = target.length) + (related : ∀ index (leftBound : index < source.length) (rightBound : index < target.length), + relation source[index] target[index]) : List.Forall₂ relation source target := by + induction source generalizing target with + | nil => + have empty : target = [] := List.eq_nil_of_length_eq_zero sizes.symm + subst target + exact .nil + | cons head tail ih => + cases target with + | nil => simp at sizes + | cons first rest => + refine .cons (related 0 (by simp) (by simp)) ?_ + apply ih (Nat.succ.inj sizes) + intro index leftBound rightBound + exact related (index + 1) (by simpa using leftBound) (by simpa using rightBound) + +theorem readValues_append {values extra : Array G} {indices : Array ValIdx} {outputs : Array G} + (read : Bytecode.AIR.readValues values indices = some outputs) : + Bytecode.AIR.readValues (values ++ extra) indices = some outputs := by + have listRead := congrArg (Functor.map Array.toList) read + rw [Bytecode.AIR.readValues, Array.toList_mapM] at listRead + have related := mapM_forall₂ listRead (fun _ _ _ equal => equal) + have lifted := forall₂_imp related (last := fun index value => (values ++ extra)[index]? = some value) + (fun index value present => by + have bound := (Array.getElem?_eq_some_iff.mp present).choose + rw [Array.getElem?_append_left bound] + exact present) + apply option_array_eq_of_toList + rw [Bytecode.AIR.readValues, Array.toList_mapM] + exact mapM_of_forall₂ lifted + +theorem readValues_range (values : Array G) : + Bytecode.AIR.readValues values (Array.range values.size) = some values := by + apply option_array_eq_of_toList + rw [Bytecode.AIR.readValues, Array.toList_mapM] + apply mapM_of_forall₂ + apply forall₂_of_get (by simp) + intro index leftBound rightBound + have bound : index < values.size := by simpa only [Array.length_toList] using rightBound + simpa only [Array.getElem_toList, Array.getElem_range] using Array.getElem?_eq_getElem bound + +def RowInputs (size : Nat) (inputs : Array G) (values : Array RowValue) : Prop := + Bytecode.AIR.readValues (rowValues values) (Array.range size) = some inputs + +theorem RowInputs.append {size : Nat} {inputs : Array G} {values extra : Array RowValue} + (preserved : RowInputs size inputs values) : RowInputs size inputs (values ++ extra) := by + unfold RowInputs at * + rw [rowValues_append] + exact readValues_append preserved + +theorem RowInputs.full (values : Array RowValue) : RowInputs values.size (rowValues values) values := by + have read := readValues_range (rowValues values) + simpa only [RowInputs, rowValues, Array.size_map] using read + +theorem emitOps_inputs {row : Nat → G} {selector rank : G} {ops : List Op} + {values : Array RowValue} {column : Nat} {emission : OpsEmission} + (emitted : emitOps row selector rank ops values column = some emission) + {size : Nat} {inputs : Array G} (preserved : RowInputs size inputs values) : + RowInputs size inputs emission.values := by + induction ops generalizing values column emission with + | nil => + simp only [emitOps, Option.some.injEq] at emitted + subst emission + exact preserved + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i rest restEmitted + have equal := Option.some.inj emitted + subst emission + change RowInputs size inputs rest.values + exact ih restEmitted preserved.append + +structure InputPreservation (context : RowContext) (inputs : Array G) (emission : BlockEmission) : Prop where + values : RowInputs context.inputSize inputs emission.values + returned : ∀ part ∈ emission.returns, + part.2.function = context.function ∧ part.2.inputs = inputs ∧ part.2.rank = context.rank + +theorem InputPreservation.prefix {context : RowContext} {inputs : Array G} {emission : BlockEmission} + (preserved : InputPreservation context inputs emission) (equations : List G) : + InputPreservation context inputs (emission.prefix equations) := + ⟨preserved.values, preserved.returned⟩ + +theorem InputPreservation.afterOps {context : RowContext} {inputs : Array G} {control : BlockEmission} + (preserved : InputPreservation context inputs control) (incoming : G) (lookup : Nat) + (operations : OpsEmission) : InputPreservation context inputs (control.afterOps incoming lookup operations) := + ⟨preserved.values, preserved.returned⟩ + +theorem InputPreservation.join {context : RowContext} {inputs : Array G} {values : Array RowValue} + (initial : RowInputs context.inputSize inputs values) (column lookup : Nat) (emissions : List BlockEmission) + (preserved : ∀ emission ∈ emissions, InputPreservation context inputs emission) : + InputPreservation context inputs (joinBlockEmissions values column lookup emissions) := by + refine ⟨initial, ?_⟩ + intro part member + obtain ⟨emission, emissionMember, partMember⟩ := List.mem_flatMap.mp member + exact (preserved emission emissionMember).returned part partMember + +theorem InputPreservation.continued {context : RowContext} {inputs : Array G} + {branches continuation : BlockEmission} + (first : InputPreservation context inputs branches) (last : InputPreservation context inputs continuation) + (equations : List G) : InputPreservation context inputs (branches.continued equations continuation) := by + refine ⟨last.values, ?_⟩ + intro part member + rcases List.mem_append.mp member with left | right + · exact first.returned part left + · exact last.returned part right + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem branchRows_inputs (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + {inputs : Array G} (initial : RowInputs context.inputSize inputs values) + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + (caseSound : ∀ pair ∈ branches.toList, ∀ emission, + pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → + InputPreservation context inputs emission) + (defaultSound : ∀ block, fallback = some block → ∀ emission, + block.emitRow row selector context (block.selectorFlow selector).entry values + (column + branches.size) lookup = some emission → InputPreservation context inputs emission) : + InputPreservation context inputs emission := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i default defaultEmitted + have equal := Option.some.inj emitted + subst emission + have casesPreserved : ∀ emission ∈ cases, InputPreservation context inputs emission := by + apply forall₂_right_property + apply mapM_forall₂ casesEmitted + intro pair member result resultEmitted + simp only [caseRow, bind, Option.bind] at resultEmitted + split at resultEmitted + · cases resultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj resultEmitted + subst result + exact (caseSound pair member body bodyEmitted).prefix _ + have defaultPreserved : ∀ emission ∈ default, InputPreservation context inputs emission := by + cases fallback with + | none => + simp only [defaultRow, Option.some.injEq] at defaultEmitted + subst default + simp + | some block => + simp only [defaultRow, bind, Option.bind] at defaultEmitted + split at defaultEmitted + · cases defaultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj defaultEmitted + subst default + intro emission member + have equal := List.mem_singleton.mp member + subst emission + exact (defaultSound block rfl body bodyEmitted).prefix _ + apply InputPreservation.join initial + intro emission member + rcases List.mem_append.mp member with left | right + · exact casesPreserved emission left + · exact defaultPreserved emission right + +private theorem block_input_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +theorem Ctrl.emitRow_inputs (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) + {emission : BlockEmission} {inputs : Array G} (initial : RowInputs context.inputSize inputs values) + (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) : + InputPreservation context inputs emission := by + cases ctrl with + | «return» index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i provided readInputs + dsimp only at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + refine ⟨initial, ?_⟩ + intro part member + have equal := List.mem_singleton.mp member + subst part + exact ⟨rfl, Option.some.inj (readInputs.symm.trans initial), rfl⟩ + | yield index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + exact ⟨initial, by simp⟩ + | «match» index branches fallback => + rw [Ctrl.emitRow_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + apply branchRows_inputs row selector context matched.value values column lookup branches fallback initial emitted + · intro pair member body bodyEmitted + exact Block.emitRow_inputs row selector context _ values column lookup pair.2 initial bodyEmitted + · intro block present body bodyEmitted + exact Block.emitRow_inputs row selector context _ values _ lookup block initial bodyEmitted + | matchContinue index branches fallback size aux slots continuation => + rw [Ctrl.emitRow_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + dsimp only at emitted + split at emitted + · cases emitted + · rename_i joined branchesEmitted + have branchesPreserved := branchRows_inputs row selector context matched.value values column lookup + branches fallback initial branchesEmitted + (fun pair member body bodyEmitted => + Block.emitRow_inputs row selector context _ values column lookup pair.2 initial bodyEmitted) + (fun block present body bodyEmitted => + Block.emitRow_inputs row selector context _ values _ lookup block initial bodyEmitted) + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i continued contEmitted + have contPreserved := Block.emitRow_inputs row selector context _ _ _ _ continuation initial.append contEmitted + have equal := Option.some.inj emitted + subst emission + exact branchesPreserved.continued contPreserved _ + · cases emitted +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr ‹_ ∈ _›); grind) + +theorem Block.emitRow_inputs (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + {emission : BlockEmission} {inputs : Array G} (initial : RowInputs context.inputSize inputs values) + (emitted : block.emitRow row selector context incoming values column lookup = some emission) : + InputPreservation context inputs emission := by + rw [Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i operations opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i control ctrlEmitted + have preserved := Ctrl.emitRow_inputs row selector context incoming _ _ _ block.ctrl + (emitOps_inputs opsEmitted initial) ctrlEmitted + have equal := Option.some.inj emitted + subst emission + exact (preserved.afterOps incoming lookup operations).prefix _ +termination_by sizeOf block +decreasing_by exact block_input_smaller block + +end + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BlockRowProjection.lean b/Ix/Aiur/Proofs/BlockRowProjection.lean new file mode 100644 index 000000000..696405cee --- /dev/null +++ b/Ix/Aiur/Proofs/BlockRowProjection.lean @@ -0,0 +1,436 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockRows +import Batteries.Data.List.Basic + +/-! +The selector and return-gate projections of the valued block emitter. +Successful emission suffices for the projection equalities; no satisfying +assignment is assumed. Its equations therefore imply the previously checked +selector-flow equations. +-/ + +namespace Aiur.AIR +open Bytecode + +theorem mapM_forall₂ {α β : Type} {relation : α → β → Prop} {source : List α} + {emissions : List β} {emit : α → Option β} + (emitted : source.mapM emit = some emissions) + (each : ∀ item ∈ source, ∀ emission, emit item = some emission → relation item emission) : + List.Forall₂ relation source emissions := by + induction source generalizing emissions with + | nil => + simp only [List.mapM_nil, pure, Option.some.injEq] at emitted + subst emissions + exact .nil + | cons item items ih => + simp only [List.mapM_cons, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i rest restEmitted + have equal := Option.some.inj emitted + subst emissions + exact .cons (each item List.mem_cons_self first firstEmitted) + (ih restEmitted (fun item member => each item (List.mem_cons_of_mem _ member))) + +theorem attachWith_mapM_val {α β : Type} (items : List α) (predicate : α → Prop) + (holds : ∀ item ∈ items, predicate item) (emit : α → Option β) : + (items.attachWith predicate holds).mapM (fun item => emit item.val) = items.mapM emit := by + have result := List.mapM_map (m := Option) (l := items.attachWith predicate holds) + (f := Subtype.val) (g := emit) + rw [List.attachWith_map_subtype_val] at result + exact result.symm + +theorem forall₂_map_left {α β γ : Type} {relation : β → γ → Prop} {map : α → β} + {left : List α} {right : List γ} + (related : List.Forall₂ (fun item result => relation (map item) result) left right) : + List.Forall₂ relation (left.map map) right := by + induction related with + | nil => exact .nil + | cons first _ ih => exact .cons first ih + +theorem forall₂_append {α β : Type} {relation : α → β → Prop} + {firstLeft restLeft : List α} {firstRight restRight : List β} + (first : List.Forall₂ relation firstLeft firstRight) + (rest : List.Forall₂ relation restLeft restRight) : + List.Forall₂ relation (firstLeft ++ restLeft) (firstRight ++ restRight) := by + induction first with + | nil => exact rest + | cons head _ ih => exact .cons head ih + +def SelectorFlow.unguard (flow : SelectorFlow) : SelectorFlow := + { flow with equations := flow.equations.tail } + +structure EmissionProjection (flow : SelectorFlow) (gates : List G) + (emission : BlockEmission) : Prop where + returned : emission.returns.map Prod.fst = gates + yielded : emission.yields.map Prod.fst = flow.yields + equations : flow.equations ⊆ emission.equations + +theorem EmissionProjection.prefix {flow : SelectorFlow} {gates : List G} + {emission : BlockEmission} (projection : EmissionProjection flow gates emission) + (equations : List G) : EmissionProjection flow gates (emission.prefix equations) := + ⟨projection.returned, projection.yielded, + fun _ member => List.mem_append_right _ (projection.equations member)⟩ + +theorem EmissionProjection.join {α : Type} {source : List α} {emissions : List BlockEmission} + (flow : α → SelectorFlow) (gates : α → List G) + (projections : List.Forall₂ (fun item emission => EmissionProjection (flow item) (gates item) emission) + source emissions) (values : Array RowValue) (column lookup : Nat) : + EmissionProjection (SelectorFlow.join (source.map flow)) (source.flatMap gates) + (joinBlockEmissions values column lookup emissions) := by + induction projections with + | nil => exact ⟨rfl, rfl, by simp [SelectorFlow.join]⟩ + | @cons item emission items emissions first rest ih => + refine ⟨?_, ?_, ?_⟩ + · change (emission.returns ++ emissions.flatMap (·.returns)).map Prod.fst = + gates item ++ items.flatMap gates + rw [List.map_append, first.returned] + exact congrArg (gates item ++ ·) ih.returned + · change (emission.yields ++ emissions.flatMap (·.yields)).map Prod.fst = + (flow item).yields ++ (items.map flow).flatMap (·.yields) + rw [List.map_append, first.yielded] + exact congrArg ((flow item).yields ++ ·) ih.yielded + · intro equation member + change equation ∈ (flow item).equations ++ (items.map flow).flatMap (·.equations) at member + change equation ∈ emission.equations ++ emissions.flatMap (·.equations) + rcases List.mem_append.mp member with left | right + · exact List.mem_append_left _ (first.equations left) + · exact List.mem_append_right _ (ih.equations right) + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Ctrl.selectorFlow_equations (selector : SelIdx → G) (ctrl : Ctrl) : + (ctrl.selectorFlow selector).equations = + oneSubBooleanConstraint (ctrl.selectorFlow selector).entry :: + (ctrl.selectorFlow selector).equations.tail := by + cases ctrl <;> rw [Ctrl.selectorFlow.eq_def] + all_goals rfl + +def caseRow (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) (pair : G × Block) : + Option BlockEmission := do + let entry := (pair.2.selectorFlow selector).entry + let emission ← pair.2.emitRow row selector context entry values column lookup + return emission.prefix [entry * (matched - pair.1)] + +def defaultRow (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) : Option (List BlockEmission) := + match fallback with + | none => some [] + | some block => do + let entry := (block.selectorFlow selector).entry + let emission ← block.emitRow row selector context entry values (column + branches.size) lookup + return [emission.prefix (branches.toList.mapIdx fun i pair => + entry * ((matched - pair.1) * row (column + i) - 1))] + +def branchRows (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) : Option BlockEmission := do + let cases ← branches.toList.mapM (caseRow row selector context matched values column lookup) + let default ← defaultRow row selector context matched values column lookup branches fallback + return joinBlockEmissions values column lookup (cases ++ default) + +theorem Ctrl.emitRow_match (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) + (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).emitRow row selector context incoming values column lookup = (do + let matched ← values[index]? + branchRows row selector context matched.value values column lookup branches fallback) := by + rw [Ctrl.emitRow.eq_def] + simp only [branchRows, Array.toList_attach] + cases read : values[index]? with + | none => simp only [bind, Option.bind_none] + | some matched => + simp only [bind, Option.bind_some] + rw [attachWith_mapM_val _ _ _ (fun pair : G × Block => + (pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup).bind + fun emission => pure (emission.prefix + [(pair.2.selectorFlow selector).entry * (matched.value - pair.1)]))] + change (branches.toList.mapM (caseRow row selector context matched.value values column lookup)).bind _ = _ + congr 1 + funext cases + cases fallback with + | none => rfl + | some block => simp only [defaultRow, bind, Option.bind_assoc] + +def continueRow (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (size : Nat) (continuation : Block) + (joined : BlockEmission) : Option BlockEmission := + if joined.yields.all (fun part => part.2.size == size) then do + let gate := selectorSum (joined.yields.map Prod.fst) + let merged := rowAdvice row joined.column size + let equations := mergeEquations row incoming joined.column size joined.yields ++ + [(continuation.selectorFlow selector).entry - gate] + let continued ← continuation.emitRow row selector context gate (values ++ merged) + (joined.column + size) joined.lookup + return joined.continued equations continued + else none + +theorem Ctrl.emitRow_matchContinue (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) + (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) + (size aux slots : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback size aux slots continuation).emitRow + row selector context incoming values column lookup = (do + let matched ← values[index]? + let joined ← branchRows row selector context matched.value values column lookup branches fallback + continueRow row selector context incoming values size continuation joined) := by + rw [Ctrl.emitRow.eq_def] + simp only [branchRows, Array.toList_attach] + cases read : values[index]? with + | none => simp only [bind, Option.bind_none] + | some matched => + simp only [bind, Option.bind_some] + rw [attachWith_mapM_val _ _ _ (fun pair : G × Block => + (pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup).bind + fun emission => pure (emission.prefix + [(pair.2.selectorFlow selector).entry * (matched.value - pair.1)]))] + simp only [Option.bind_assoc] + change (branches.toList.mapM (caseRow row selector context matched.value values column lookup)).bind _ = _ + congr 1 + funext cases + cases fallback <;> simp only [defaultRow, continueRow, bind, pure, + Option.bind_assoc, Option.bind_some] + +theorem caseRows_projection (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) {emissions : List BlockEmission} + (emitted : branches.toList.mapM (caseRow row selector context matched values column lookup) = some emissions) + (sound : ∀ pair ∈ branches.toList, ∀ emission, + pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → + EmissionProjection (pair.2.selectorFlow selector) + (pair.2.returnGates selector (pair.2.selectorFlow selector).entry) emission) : + List.Forall₂ (fun block emission => EmissionProjection (block.selectorFlow selector) + (block.returnGates selector (block.selectorFlow selector).entry) emission) + (branches.toList.map Prod.snd) emissions := by + apply forall₂_map_left + apply mapM_forall₂ emitted + intro pair member emission emitted + simp only [caseRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i body bodyEmitted + have equal := Option.some.inj emitted + subst emission + exact (sound pair member body bodyEmitted).prefix _ + +theorem defaultRow_projection (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emissions : List BlockEmission} + (emitted : defaultRow row selector context matched values column lookup branches fallback = some emissions) + (sound : ∀ block, fallback = some block → ∀ emission, + block.emitRow row selector context (block.selectorFlow selector).entry values + (column + branches.size) lookup = some emission → + EmissionProjection (block.selectorFlow selector) + (block.returnGates selector (block.selectorFlow selector).entry) emission) : + List.Forall₂ (fun block emission => EmissionProjection (block.selectorFlow selector) + (block.returnGates selector (block.selectorFlow selector).entry) emission) + fallback.toList emissions := by + cases fallback with + | none => + simp only [defaultRow, Option.some.injEq] at emitted + subst emissions + exact .nil + | some block => + simp only [defaultRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i body bodyEmitted + have equal := Option.some.inj emitted + subst emissions + exact .cons ((sound block rfl body bodyEmitted).prefix _) .nil + +theorem branchRows_projection (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + (caseSound : ∀ pair ∈ branches.toList, ∀ emission, + pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → + EmissionProjection (pair.2.selectorFlow selector) + (pair.2.returnGates selector (pair.2.selectorFlow selector).entry) emission) + (defaultSound : ∀ block, fallback = some block → ∀ emission, + block.emitRow row selector context (block.selectorFlow selector).entry values + (column + branches.size) lookup = some emission → + EmissionProjection (block.selectorFlow selector) + (block.returnGates selector (block.selectorFlow selector).entry) emission) : + EmissionProjection (SelectorFlow.join (branchSelectorFlows selector branches fallback)) + (branchReturnGates selector branches fallback) emission := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i default defaultEmitted + have equal := Option.some.inj emitted + subst emission + have casesProjection := caseRows_projection row selector context matched values column lookup branches + casesEmitted caseSound + have defaultProjection := defaultRow_projection row selector context matched values column lookup + branches fallback defaultEmitted defaultSound + have result := EmissionProjection.join + (fun block : Block => block.selectorFlow selector) + (fun block : Block => block.returnGates selector (block.selectorFlow selector).entry) + (forall₂_append casesProjection defaultProjection) values column lookup + simpa only [branchSelectorFlows, branchReturnGates, List.map_append, List.map_map, + List.flatMap_append, List.flatMap_map, Function.comp_def] using result + +private theorem block_projection_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +theorem Ctrl.emitRow_projection (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) + {emission : BlockEmission} + (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) : + EmissionProjection (ctrl.selectorFlow selector).unguard + (ctrl.returnGates selector incoming) emission := by + cases ctrl with + | «return» index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · dsimp only at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + rw [Ctrl.selectorFlow.eq_def, Ctrl.returnGates.eq_def] + exact ⟨rfl, rfl, by simp [SelectorFlow.unguard, SelectorFlow.guard]⟩ + | yield index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + rw [Ctrl.selectorFlow.eq_def, Ctrl.returnGates.eq_def] + exact ⟨rfl, rfl, by simp [SelectorFlow.unguard, SelectorFlow.guard]⟩ + | «match» index branches fallback => + rw [Ctrl.emitRow_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + rw [Ctrl.selectorFlow_match, Ctrl.returnGates_match] + apply branchRows_projection row selector context matched.value values column lookup branches fallback emitted + · intro pair member body bodyEmitted + exact Block.emitRow_projection row selector context _ values column lookup pair.2 bodyEmitted + · intro block present body bodyEmitted + exact Block.emitRow_projection row selector context _ values _ lookup block bodyEmitted + | matchContinue index branches fallback size aux slots continuation => + rw [Ctrl.emitRow_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + dsimp only at emitted + split at emitted + · cases emitted + · rename_i joined branchesEmitted + have branchesProjection := branchRows_projection row selector context matched.value values column lookup + branches fallback branchesEmitted + (fun pair member body bodyEmitted => + Block.emitRow_projection row selector context _ values column lookup pair.2 bodyEmitted) + (fun block present body bodyEmitted => + Block.emitRow_projection row selector context _ values _ lookup block bodyEmitted) + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i continued contEmitted + have contProjection := Block.emitRow_projection row selector context _ _ _ _ continuation contEmitted + have gate := congrArg selectorSum branchesProjection.yielded + have equal := Option.some.inj emitted + subst emission + rw [Ctrl.selectorFlow_matchContinue, Ctrl.returnGates_matchContinue] + refine ⟨?_, contProjection.yielded, ?_⟩ + · change (joined.returns ++ continued.returns).map Prod.fst = _ + rw [List.map_append, branchesProjection.returned, contProjection.returned, gate] + · intro equation member + change equation ∈ + (SelectorFlow.join (branchSelectorFlows selector branches fallback)).equations ++ + ((continuation.selectorFlow selector).entry - + selectorSum (SelectorFlow.join (branchSelectorFlows selector branches fallback)).yields) :: + (continuation.selectorFlow selector).equations at member + change equation ∈ (joined.equations ++ + (mergeEquations row incoming joined.column size joined.yields ++ + [(continuation.selectorFlow selector).entry - selectorSum (joined.yields.map Prod.fst)])) ++ + continued.equations + rcases List.mem_append.mp member with branchEquation | contEquation + · exact List.mem_append_left _ (List.mem_append_left _ + (branchesProjection.equations branchEquation)) + · rcases List.mem_cons.mp contEquation with link | contEquation + · rw [link, ← gate] + exact List.mem_append_left _ (List.mem_append_right _ + (List.mem_append_right _ List.mem_cons_self)) + · exact List.mem_append_right _ (contProjection.equations contEquation) + · cases emitted +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr ‹_ ∈ _›); grind) + +theorem Block.emitRow_projection (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) : + EmissionProjection (block.selectorFlow selector) + (block.returnGates selector incoming) emission := by + rw [Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i operations opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i control ctrlEmitted + have projected := Ctrl.emitRow_projection row selector context incoming _ _ _ block.ctrl ctrlEmitted + have equal := Option.some.inj emitted + subst emission + rw [Block.returnGates, Block.selectorFlow] + refine ⟨projected.returned, projected.yielded, ?_⟩ + intro equation member + change equation ∈ oneSubBooleanConstraint (block.ctrl.selectorFlow selector).entry :: + (operations.equations ++ control.equations) + change equation ∈ (block.ctrl.selectorFlow selector).equations at member + rw [Ctrl.selectorFlow_equations] at member + rcases List.mem_cons.mp member with guard | tail + · rw [guard] + exact List.mem_cons_self + · exact List.mem_cons_of_mem _ (List.mem_append_right _ (projected.equations tail)) +termination_by sizeOf block +decreasing_by exact block_projection_smaller block + +end + +theorem Block.emitRow_selectors (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + (block.selectorFlow selector).Satisfied := + fun equation member => satisfied equation + ((block.emitRow_projection row selector context incoming values column lookup emitted).equations member) + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BlockRows.lean b/Ix/Aiur/Proofs/BlockRows.lean new file mode 100644 index 000000000..2d392f8c7 --- /dev/null +++ b/Ix/Aiur/Proofs/BlockRows.lean @@ -0,0 +1,159 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CallInventory +import Ix.Aiur.Proofs.BranchSelection + +/-! +A total valued model of native block constraint emission. Branches share +columns and lookup slots, default arms allocate inverse witnesses, and +continuations consume local yields while preserving early returns. Selector +gates match native emission even on assignments that violate its equations. + +Native expression reflection and successful emission from validated layouts +remain separate obligations. +-/ + +namespace Aiur.AIR +open Bytecode + +structure RowContext where + function : FunIdx + inputSize : Nat + rank : G + +structure QueryPart where + slot : Nat + selector : G + message : List G + deriving Repr + +def queryParts (slot : Nat) (selector : G) (queries : List (List G)) : List QueryPart := + queries.mapIdx fun index message => ⟨slot + index, selector, message⟩ + +structure BlockEmission where + values : Array RowValue + column : Nat + lookup : Nat + equations : List G := [] + queries : List QueryPart := [] + returns : List (G × Bytecode.AIR.Call) := [] + yields : List (G × Array RowValue) := [] + calls : List (G × (Bytecode.AIR.Call × (Fin 6 → G))) := [] + +def BlockEmission.prefix (equations : List G) (emission : BlockEmission) : BlockEmission := + { emission with equations := equations ++ emission.equations } + +def BlockEmission.afterOps (incoming : G) (lookup : Nat) (ops : OpsEmission) + (control : BlockEmission) : BlockEmission := + { control with + equations := ops.equations ++ control.equations + queries := queryParts lookup incoming ops.queries ++ control.queries + calls := ops.calls.map (incoming, ·) ++ control.calls } + +def joinBlockEmissions (values : Array RowValue) (column lookup : Nat) + (emissions : List BlockEmission) : BlockEmission := + { values + column := emissions.foldl (fun column emission => max column emission.column) column + lookup := emissions.foldl (fun lookup emission => max lookup emission.lookup) lookup + equations := emissions.flatMap (·.equations) + queries := emissions.flatMap (·.queries) + returns := emissions.flatMap (·.returns) + yields := emissions.flatMap (·.yields) + calls := emissions.flatMap (·.calls) } + +def mergeEquations (row : Nat → G) (parent : G) (column size : Nat) + (yields : List (G × Array RowValue)) : List G := + (List.range size).map fun index => parent * (row (column + index) - + selectorSum (yields.map fun part => part.1 * (rowValues part.2)[index]?.getD 0)) + +def BlockEmission.continued (branches : BlockEmission) (equations : List G) + (continuation : BlockEmission) : BlockEmission := + { continuation with + equations := branches.equations ++ equations ++ continuation.equations + queries := branches.queries ++ continuation.queries + returns := branches.returns ++ continuation.returns + calls := branches.calls ++ continuation.calls } + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +private theorem block_row_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def Ctrl.emitRow (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) : Ctrl → Option BlockEmission + | .return _ indices => do + let inputs ← AIR.readValues (rowValues values) (Array.range context.inputSize) + let outputs ← AIR.readValues (rowValues values) indices + return { + values, column, lookup + returns := [(incoming, ⟨context.function, inputs, outputs, context.rank⟩)] } + | .yield index indices => do + let outputs ← indices.toList.mapM fun index => values[index]? + return { values, column, lookup, yields := [(selector index, outputs.toArray)] } + | .match index branches fallback => do + let matched ← values[index]? + let cases ← branches.attach.toList.mapM fun ⟨pair, _⟩ => do + let entry := (pair.2.selectorFlow selector).entry + let emission ← pair.2.emitRow row selector context entry values column lookup + return emission.prefix [entry * (matched.value - pair.1)] + let default : List BlockEmission ← match fallback with + | none => some [] + | some block => do + let entry := (block.selectorFlow selector).entry + let emission ← block.emitRow row selector context entry values (column + branches.size) lookup + pure [emission.prefix (branches.toList.mapIdx fun i pair => + entry * ((matched.value - pair.1) * row (column + i) - 1))] + return joinBlockEmissions values column lookup (cases ++ default) + | .matchContinue index branches fallback size _ _ continuation => do + let matched ← values[index]? + let cases ← branches.attach.toList.mapM fun ⟨pair, _⟩ => do + let entry := (pair.2.selectorFlow selector).entry + let emission ← pair.2.emitRow row selector context entry values column lookup + return emission.prefix [entry * (matched.value - pair.1)] + let default : List BlockEmission ← match fallback with + | none => some [] + | some block => do + let entry := (block.selectorFlow selector).entry + let emission ← block.emitRow row selector context entry values (column + branches.size) lookup + pure [emission.prefix (branches.toList.mapIdx fun i pair => + entry * ((matched.value - pair.1) * row (column + i) - 1))] + let joined := joinBlockEmissions values column lookup (cases ++ default) + if joined.yields.all (fun part => part.2.size == size) then do + let gate := selectorSum (joined.yields.map Prod.fst) + let merged := rowAdvice row joined.column size + let equations := mergeEquations row incoming joined.column size joined.yields ++ + [(continuation.selectorFlow selector).entry - gate] + let continued ← continuation.emitRow row selector context gate (values ++ merged) + (joined.column + size) joined.lookup + return joined.continued equations continued + else none +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.emitRow (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) + (block : Block) : Option BlockEmission := do + let operations ← emitOps row incoming context.rank block.ops.toList values column + let control ← block.ctrl.emitRow row selector context incoming operations.values + operations.column (lookup + operations.queries.length) + return (control.afterOps incoming lookup operations).prefix + [oneSubBooleanConstraint (block.selectorFlow selector).entry] +termination_by sizeOf block +decreasing_by exact block_row_smaller block + +end + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BlockSelectors.lean b/Ix/Aiur/Proofs/BlockSelectors.lean new file mode 100644 index 000000000..eaccf5ef3 --- /dev/null +++ b/Ix/Aiur/Proofs/BlockSelectors.lean @@ -0,0 +1,180 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LookupExpressions + +/-! +The native block selector is a left-associated sum of its immediate branch +selectors. A continuation's selector is excluded. Selector reads use a finite +table so successful reflection requires no readings of unallocated columns. +-/ + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter + +theorem evaluated_read {values : Values G} {expressions : Array Expr} {results : Array G} + (evaluated : expressions.mapM (evalExpr values) = some results) + {index : Nat} {expr : Expr} (present : expressions[index]? = some expr) : + evalExpr values expr = some (results[index]?.getD 0) := by + have size := array_mapM_size evaluated + have inputBound := (Array.getElem?_eq_some_iff.mp present).choose + have bound : index < results.size := by omega + have read := array_mapM_read evaluated index + simpa only [present, bind, Option.bind_some, getElem?_pos results index bound, + Option.getD_some] using read + +theorem list_mapM_evaluate {α β γ : Type} {first : α → Option β} {evaluate : β → Option γ} + {inputs : List α} {outputs : List β} (selected : inputs.mapM first = some outputs) + (value : α → γ) + (related : ∀ input output, first input = some output → evaluate output = some (value input)) : + outputs.mapM evaluate = some (inputs.map value) := by + obtain ⟨results, selected, evaluated⟩ := list_mapM_refine selected + (second := fun input => some (value input)) + (fun input output read => ⟨value input, rfl, related input output read⟩) + have equal : inputs.mapM (fun input => some (value input)) = some (inputs.map value) := by + simpa only [List.map_id] using list_mapM_of_map inputs id value + (fun input => some (value input)) (fun _ _ => rfl) + rw [equal] at selected + cases selected + exact evaluated + +def sum (expressions : List Expr) : Expr := expressions.foldl Expr.frontAdd (.konst 0) + +theorem sum_fold_eval {values : Values G} {expressions : List Expr} {results : List G} + (evaluated : expressions.mapM (evalExpr values) = some results) + {initial : Expr} {start : G} (initialEval : evalExpr values initial = some start) : + evalExpr values (expressions.foldl Expr.frontAdd initial) = some (results.foldl (· + ·) start) := by + induction expressions generalizing results initial start with + | nil => + cases evaluated + exact initialEval + | cons expr rest ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i value valueEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i tail tailEval + cases evaluated + exact ih tailEval (Expr.frontAdd_eval goldilocksLaws values initialEval valueEval) + +theorem sum_eval {values : Values G} {expressions : List Expr} {results : List G} + (evaluated : expressions.mapM (evalExpr values) = some results) : + evalExpr values (sum expressions) = some (AIR.selectorSum results) := sum_fold_eval evaluated rfl + +def SelectorReads (values : Values G) (selectors : Array Expr) (selector : Nat → G) : Prop := + ∀ {index : Nat} {expr : Expr}, selectors[index]? = some expr → evalExpr values expr = some (selector index) + +theorem selectors_array_eval {values : Values G} {selectors : Array Expr} {results : Array G} + (evaluated : selectors.mapM (evalExpr values) = some results) : + SelectorReads values selectors (fun index => results[index]?.getD 0) := + fun read => evaluated_read evaluated read + +private theorem block_smaller (block : Bytecode.Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def ctrlSelector (selectors : Array Expr) : Bytecode.Ctrl → Option Expr + | .return index _ | .yield index _ => selectors[index]? + | .match _ branches fallback | .matchContinue _ branches fallback .. => do + let entries ← branches.attach.toList.mapM fun ⟨pair, _⟩ => blockSelector selectors pair.2 + let last : List Expr ← match fallback with + | none => some [] + | some block => (blockSelector selectors block).map (fun expr => [expr]) + return sum (entries ++ last) +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def blockSelector (selectors : Array Expr) (block : Bytecode.Block) : Option Expr := + ctrlSelector selectors block.ctrl +termination_by sizeOf block +decreasing_by exact block_smaller block + +end + +mutual + +theorem ctrlSelector_reads {values : Values G} {selectors : Array Expr} {selector : Nat → G} + (evaluated : SelectorReads values selectors selector) + (ctrl : Bytecode.Ctrl) {expr : Expr} (selected : ctrlSelector selectors ctrl = some expr) : + evalExpr values expr = some (ctrl.selectorFlow selector).entry := by + cases ctrl with + | «return» index indices | yield index indices => + simp only [ctrlSelector] at selected + simpa only [Bytecode.Ctrl.selectorFlow, AIR.SelectorFlow.guard] using evaluated selected + | «match» index branches fallback | matchContinue index branches fallback size aux lookups continuation => + simp only [ctrlSelector, bind, Option.bind] at selected + split at selected + · cases selected + rename_i entries entriesSelected + dsimp only at selected + have entriesEval := list_mapM_evaluate entriesSelected + (fun pair => (pair.val.2.selectorFlow selector).entry) + (fun ⟨pair, _⟩ output read => blockSelector_reads evaluated pair.2 read) + cases fallback with + | none => + cases selected + have summed := sum_eval entriesEval + simpa only [Bytecode.Ctrl.selectorFlow, AIR.SelectorFlow.guard, + AIR.SelectorFlow.join, AIR.SelectorFlow.continue, + List.append_nil, List.map_map, Function.comp_def] using summed + | some block => + cases entrySelected : blockSelector selectors block with + | none => simp only [entrySelected, Option.map_none] at selected; cases selected + | some entry => + simp only [entrySelected, Option.map_some] at selected + cases selected + have entryEval := blockSelector_reads evaluated block entrySelected + have singleton : [entry].mapM (evalExpr values) = + some [(block.selectorFlow selector).entry] := by + simp only [List.mapM_cons, List.mapM_nil, entryEval, bind, Option.bind_some, pure] + have combined : (entries ++ [entry]).mapM (evalExpr values) = + some ((branches.attach.toList.map fun pair => + (pair.val.2.selectorFlow selector).entry) ++ + [(block.selectorFlow selector).entry]) := by + simp only [List.mapM_append, entriesEval, singleton, bind, Option.bind_some, pure] + have summed := sum_eval combined + simpa only [Bytecode.Ctrl.selectorFlow, AIR.SelectorFlow.guard, + AIR.SelectorFlow.join, AIR.SelectorFlow.continue, List.map_append, + List.map_cons, List.map_nil, List.map_map, Function.comp_def] using summed +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +theorem blockSelector_reads {values : Values G} {selectors : Array Expr} {selector : Nat → G} + (evaluated : SelectorReads values selectors selector) + (block : Bytecode.Block) {expr : Expr} (selected : blockSelector selectors block = some expr) : + evalExpr values expr = some (block.selectorFlow selector).entry := by + simp only [blockSelector] at selected + simpa only [Bytecode.Block.selectorFlow] using ctrlSelector_reads evaluated block.ctrl selected +termination_by sizeOf block +decreasing_by exact block_smaller block + +end + + +theorem ctrlSelector_eval {values : Values G} {selectors : Array Expr} {results : Array G} + (evaluated : selectors.mapM (evalExpr values) = some results) + (ctrl : Bytecode.Ctrl) {expr : Expr} (selected : ctrlSelector selectors ctrl = some expr) : + evalExpr values expr = some (ctrl.selectorFlow (fun index => results[index]?.getD 0)).entry := + ctrlSelector_reads (selectors_array_eval evaluated) ctrl selected + +theorem blockSelector_eval {values : Values G} {selectors : Array Expr} {results : Array G} + (evaluated : selectors.mapM (evalExpr values) = some results) + (block : Bytecode.Block) {expr : Expr} (selected : blockSelector selectors block = some expr) : + evalExpr values expr = some (block.selectorFlow (fun index => results[index]?.getD 0)).entry := + blockSelector_reads (selectors_array_eval evaluated) block selected + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/BranchSelection.lean b/Ix/Aiur/Proofs/BranchSelection.lean new file mode 100644 index 000000000..c19363738 --- /dev/null +++ b/Ix/Aiur/Proofs/BranchSelection.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ReturnGates + +/-! Active case/default polynomial equations recover a branch of the actual +bytecode and its selector constraints. The branch-count bound and decoding +of the matched expression and default inverse columns remain explicit. -/ + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Ctrl.selectorFlow_boolean (selector : SelIdx → G) (ctrl : Ctrl) + (valid : (ctrl.selectorFlow selector).Satisfied) : + booleanConstraint (ctrl.selectorFlow selector).entry = 0 := by + cases ctrl <;> rw [Ctrl.selectorFlow.eq_def] at valid ⊢ + all_goals + have boolean := SelectorFlow.guard_boolean valid + exact boolean + +theorem Block.selectorFlow_boolean (selector : SelIdx → G) (block : Block) + (valid : (block.selectorFlow selector).Satisfied) : + booleanConstraint (block.selectorFlow selector).entry = 0 := by + rw [Block.selectorFlow] at valid ⊢ + exact Ctrl.selectorFlow_boolean selector block.ctrl valid + +/-- Case and default polynomial forms after reading the matched expression. +Default inverse advice is arbitrary; its equation establishes disequality. -/ +structure MatchPolynomials (selector : SelIdx → G) (scrutinee : G) + (branches : Array (G × Block)) (fallback : Option Block) : Prop where + cases : ∀ pair ∈ branches.toList, + (pair.2.selectorFlow selector).entry * (scrutinee - pair.1) = 0 + default : ∀ block, fallback = some block → ∀ pair ∈ branches.toList, + ∃ inverse : G, + (block.selectorFlow selector).entry * ((scrutinee - pair.1) * inverse - 1) = 0 + +theorem branchSelectorFlows_boolean (selector : SelIdx → G) (branches : Array (G × Block)) + (fallback : Option Block) + (valid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied) : + ∀ flow ∈ branchSelectorFlows selector branches fallback, booleanConstraint flow.entry = 0 := by + intro flow member + have satisfied := SelectorFlow.join_satisfied valid flow member + rcases List.mem_append.mp member with caseMember | defaultMember + · obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp caseMember + subst flow + exact pair.2.selectorFlow_boolean selector satisfied + · obtain ⟨block, blockMember, equal⟩ := List.mem_map.mp defaultMember + subst flow + exact block.selectorFlow_boolean selector satisfied + +/-- An active sum selects a branch that matches the scrutinee, with its own +selector equations available for recursive local execution extraction. -/ +theorem MatchPolynomials.active_branch {selector : SelIdx → G} {scrutinee : G} + {branches : Array (G × Block)} {fallback : Option Block} + (polynomials : MatchPolynomials selector scrutinee branches fallback) + (valid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied) + (bounded : branches.size + fallback.toList.length < gSize.toNat) + (active : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).entry = 1) : + ∃ block, AIR.SelectArm scrutinee branches fallback block ∧ + (block.selectorFlow selector).Satisfied ∧ (block.selectorFlow selector).entry = 1 := by + have individual := branchSelectorFlows_boolean selector branches fallback valid + change selectorSum ((branchSelectorFlows selector branches fallback).map SelectorFlow.entry) = 1 at active + have count := selectorSum_active_count + (selectors := (branchSelectorFlows selector branches fallback).map SelectorFlow.entry) + (fun value member => by + obtain ⟨flow, flowMember, equal⟩ := List.mem_map.mp member + subst value + exact individual flow flowMember) + (by simpa only [List.length_map, branchSelectorFlows, List.length_append, + Array.length_toList] using bounded) active + have oneMember : (1 : G) ∈ (branchSelectorFlows selector branches fallback).map SelectorFlow.entry := + List.count_pos_iff.mp (Nat.lt_of_lt_of_eq (by decide : 0 < 1) count.symm) + obtain ⟨flow, flowMember, selected⟩ := List.mem_map.mp oneMember + have satisfied := SelectorFlow.join_satisfied valid flow flowMember + rcases List.mem_append.mp flowMember with caseMember | defaultMember + · obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp caseMember + subst flow + refine ⟨pair.2, ?_, satisfied, selected⟩ + apply AIR.SelectArm.case + have matchesEq := active_case selected (polynomials.cases pair pairMember) + rw [matchesEq] + exact pairMember + · obtain ⟨block, blockMember, equal⟩ := List.mem_map.mp defaultMember + subst flow + have present : fallback = some block := by simpa using blockMember + refine ⟨block, AIR.SelectArm.fallback present ?_, satisfied, selected⟩ + intro pair pairMember + obtain ⟨inverse, equation⟩ := polynomials.default block present pair pairMember + exact (active_default selected equation).symm + +theorem MatchPolynomials.active_match {selector : SelIdx → G} {scrutinee : G} + {index : ValIdx} {branches : Array (G × Block)} {fallback : Option Block} + (polynomials : MatchPolynomials selector scrutinee branches fallback) + (valid : ((Ctrl.match index branches fallback).selectorFlow selector).Satisfied) + (bounded : branches.size + fallback.toList.length < gSize.toNat) + (active : ((Ctrl.match index branches fallback).selectorFlow selector).entry = 1) : + ∃ block, AIR.SelectArm scrutinee branches fallback block ∧ + (block.selectorFlow selector).Satisfied ∧ (block.selectorFlow selector).entry = 1 := by + rw [Ctrl.selectorFlow_match] at valid active + exact polynomials.active_branch (SelectorFlow.guard_satisfied valid) bounded active + +theorem MatchPolynomials.active_matchContinue {selector : SelIdx → G} {scrutinee : G} + {index : ValIdx} {branches : Array (G × Block)} {fallback : Option Block} + {outputs aux lookups : Nat} {continuation : Block} + (polynomials : MatchPolynomials selector scrutinee branches fallback) + (valid : ((Ctrl.matchContinue index branches fallback outputs aux lookups continuation).selectorFlow selector).Satisfied) + (bounded : branches.size + fallback.toList.length < gSize.toNat) + (active : ((Ctrl.matchContinue index branches fallback outputs aux lookups continuation).selectorFlow selector).entry = 1) : + ∃ block, AIR.SelectArm scrutinee branches fallback block ∧ + (block.selectorFlow selector).Satisfied ∧ (block.selectorFlow selector).entry = 1 := by + rw [Ctrl.selectorFlow_matchContinue] at valid active + exact polynomials.active_branch + (SelectorFlow.continue_satisfied (SelectorFlow.guard_satisfied valid)).1 bounded active + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/BranchlessSlots.lean b/Ix/Aiur/Proofs/BranchlessSlots.lean new file mode 100644 index 000000000..9bc477be6 --- /dev/null +++ b/Ix/Aiur/Proofs/BranchlessSlots.lean @@ -0,0 +1,178 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRowCounts + +/-! Every circuit eligible for ungated messages has a single function +with terminal control. Its queries occupy disjoint slots, independent of +witness selectors. This closes the single-writer premise and reflects all +encoded consumer slots after padding; native expression reflection remains +a separate obligation. -/ + +namespace Aiur.AIR +open Bytecode + +def unitQuerySelectors (queries : List QueryPart) : List QueryPart := + queries.map fun query => { query with selector := 1 } + +def QueryWriters (start finish : Nat) (queries : List QueryPart) : Prop := + QuerySlots 1 start finish (unitQuerySelectors queries) + +theorem unitQuerySelectors_parts (slot : Nat) (selector : G) (queries : List (List G)) : + unitQuerySelectors (queryParts slot selector queries) = queryParts slot 1 queries := by + induction queries generalizing slot with + | nil => rfl + | cons message queries ih => + rw [queryParts_cons, queryParts_cons] + change _ :: unitQuerySelectors (queryParts (slot + 1) selector queries) = _ + rw [ih] + +theorem QueryWriters.indexed (slot : Nat) (selector : G) (queries : List (List G)) : + QueryWriters slot (slot + queries.length) (queryParts slot selector queries) := by + rw [QueryWriters, unitQuerySelectors_parts] + exact QuerySlots.indexed 1 slot queries (by decide +kernel) + +theorem QueryWriters.append {start middle finish : Nat} {first rest : List QueryPart} + (left : QueryWriters start middle first) (right : QueryWriters middle finish rest) : + QueryWriters start finish (first ++ rest) := by + unfold QueryWriters unitQuerySelectors + rw [List.map_append] + exact QuerySlots.append left right + +theorem QueryWriters.extend {start finish limit : Nat} {queries : List QueryPart} + (writers : QueryWriters start finish queries) (bound : finish ≤ limit) : + QueryWriters start limit queries := QuerySlots.extend writers bound + +theorem QueryWriters.permuted {start finish : Nat} {queries other : List QueryPart} + (writers : QueryWriters start finish queries) (permutation : queries.Perm other) : + QueryWriters start finish other := QuerySlots.permuted writers (permutation.map _) + +theorem unitQuerySelectors_count (queries : List QueryPart) (slot : Nat) : + queryCount (unitQuerySelectors queries) slot = (querySlotParts queries slot).length := by + simp only [queryCount, unitQuerySelectors, List.filter_map, List.length_map, + querySlotParts, Function.comp_def, beq_self_eq_true, Bool.and_true] + +theorem QueryWriters.single {start finish : Nat} {queries : List QueryPart} + (writers : QueryWriters start finish queries) (slot : Nat) : + (querySlotParts queries slot).length ≤ 1 := by + rw [← unitQuerySelectors_count] + exact writers.count slot + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Function.emitRow_terminal_writers (row : Nat → G) (selector : SelIdx → G) + (function : Function) (functionIndex : FunIdx) (rank : G) + (inputs : Array RowValue) (column lookup : Nat) {emission : BlockEmission} + (terminal : function.hasTerminalControl = true) + (emitted : function.emitRow row selector functionIndex rank inputs column lookup = some emission) : + QueryWriters lookup emission.lookup emission.queries := by + rw [Function.emitRow, Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i ops opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i control controlEmitted + have equal := Option.some.inj emitted + subst emission + cases ctrlEq : function.body.ctrl with + | «match» index branches fallback => + simp only [Function.hasTerminalControl, ctrlEq, Bool.false_eq_true] at terminal + | matchContinue index branches fallback size aux slots continuation => + simp only [Function.hasTerminalControl, ctrlEq, Bool.false_eq_true] at terminal + | «return» index indices => + rw [ctrlEq, Ctrl.emitRow.eq_def] at controlEmitted + simp only [bind, Option.bind] at controlEmitted + split at controlEmitted + · cases controlEmitted + · dsimp only at controlEmitted + split at controlEmitted + · cases controlEmitted + · have equal := Option.some.inj controlEmitted + subst control + simpa only [BlockEmission.prefix, BlockEmission.afterOps, List.append_nil] using + QueryWriters.indexed lookup (function.body.selectorFlow selector).entry ops.queries + | yield index indices => + rw [ctrlEq, Ctrl.emitRow.eq_def] at controlEmitted + simp only [bind, Option.bind] at controlEmitted + split at controlEmitted + · cases controlEmitted + · have equal := Option.some.inj controlEmitted + subst control + simpa only [BlockEmission.prefix, BlockEmission.afterOps, List.append_nil] using + QueryWriters.indexed lookup (function.body.selectorFlow selector).entry ops.queries + +end Aiur.Bytecode + +namespace Aiur.AIR +open Bytecode + +theorem circuitBranchless_member {selectors : Nat} {members : List MemberEmission} + (enabled : circuitBranchless selectors (members.map (·.function)) = true) : + ∃ member, members = [member] ∧ member.function.hasTerminalControl = true := by + cases members with + | nil => simp only [List.map_nil, circuitBranchless, Bool.and_false, Bool.false_eq_true] at enabled + | cons member rest => + cases rest with + | nil => + refine ⟨member, rfl, ?_⟩ + simp only [List.map_cons, List.map_nil, circuitBranchless, Bool.and_eq_true] at enabled + exact enabled.2 + | cons next rest => + simp only [List.map_cons, circuitBranchless, Bool.and_false, Bool.false_eq_true] at enabled + +theorem circuitEmission_queryWriters {row : Nat → G} {rank : G} {column : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromProgram row rank column 4 program) + (enabled : (circuitEmission row circuit members).branchless = true) + (limits : ∀ member ∈ members, member.body.lookup ≤ circuit.layout.lookups) : + QueryWriters 1 circuit.layout.lookups (circuitEmission row circuit members).queries := by + obtain ⟨member, membersEq, terminal⟩ := circuitBranchless_member enabled + subst members + have body := member.function.emitRow_terminal_writers row (member.selector row) + member.functionIndex rank (rowAdvice row 0 member.function.layout.inputSize) column 4 + terminal (source member List.mem_cons_self).emitted + have headers := QueryWriters.indexed 1 (circuitEmission row circuit [member]).selector + ((rankByteQueries (circuitRankBytes row circuit.layout)).map rangeMessage) + have combined := (headers.append (body.extend (limits member List.mem_cons_self))).permuted List.perm_append_comm + simpa only [circuitEmission, List.flatMap_cons, List.flatMap_nil, List.append_nil, + List.isEmpty_cons, Bool.false_eq_true, if_false] using combined + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitRow_queryWriters (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (enabled : emission.branchless = true) + (limits : ∀ member ∈ emission.members, member.body.lookup ≤ circuit.layout.lookups) : + QueryWriters 1 emission.lookupCount emission.queries := by + obtain ⟨description, _, source⟩ := circuit.emitRow_spec row program emitted + have writers := circuitEmission_queryWriters source (by rw [← description]; exact enabled) limits + have lookupEq := congrArg CircuitEmission.lookupCount description + change emission.lookupCount = circuit.layout.lookups at lookupEq + rw [← lookupEq, ← description] at writers + exact writers + +theorem Circuit.emitRow_queries_reflect (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (validated : circuit.validateRowCounts program = true) + (reserved : 4 ≤ circuit.layout.lookups) + (limits : ∀ member ∈ emission.members, member.body.lookup ≤ circuit.layout.lookups) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (width : Nat) : + (encodedQueries emission.branchless emission.queries emission.lookupCount).map (padMessage width) = + (decodedQueries emission.queries emission.lookupCount).map (padMessage width) := by + obtain ⟨bounded, bounds, _, _⟩ := circuit.emitRow_count_bounds row program emitted validated satisfied + have slots := circuit.emitRow_querySlots row program emitted bounded bounds reserved limits satisfied + apply slots.queries_reflect + exact fun enabled slot => (circuit.emitRow_queryWriters row program emitted enabled limits).single slot + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ByteArithmetic.lean b/Ix/Aiur/Proofs/ByteArithmetic.lean new file mode 100644 index 000000000..fe7190a2b --- /dev/null +++ b/Ix/Aiur/Proofs/ByteArithmetic.lean @@ -0,0 +1,185 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LocalConstraints + +/-! +Virtual byte carries and the four-byte strict-comparison gadget. + +The native byte-add/subtract lookups supply only their low byte. Multiplying +the residual by the inverse of 256 gives the carry or borrow in the semantic +operation. For `u32_less_than`, twelve range-checked bytes and four boolean +carry equations give the integer identity `a + witness + 1 = b + carry*2^32`. +The range bounds make its final carry exactly the complement of `a < b`. + +All arithmetic is over the actual Goldilocks representation. Lookup-derived +byte bounds and decoding the native expressions remain separate inputs. +-/ + +namespace Aiur + +theorem G.mul_assoc (a b c : G) : (a * b) * c = a * (b * c) := by + apply G.ext_n + simp only [G.n_mul, Nat.mod_mul_mod, Nat.mul_mod_mod, Nat.mul_assoc] + +theorem G.n_sub (a b : G) : (a - b).n = (a.n + gSize.toNat - b.n) % gSize.toNat := + G.n_ofNat _ + +namespace AIR + +def inverse256 : G := 18374686475393433601 + +theorem inverse256_correct : inverse256 * 256 = 1 := by decide +kernel + +theorem byte_division_eq (value : G) : (value * inverse256) * 256 = value := by + rw [G.mul_assoc, inverse256_correct, G.mul_one] + +theorem byte_add_carry {x y low : G} (hx : x.n < 256) (hy : y.n < 256) + (hlow : low = G.ofNat ((x.n + y.n) % 256)) : + (x + y - low) * inverse256 = G.ofNat ((x.n + y.n) / 256) := by + apply G.ext_n + rw [hlow] + simp only [G.n_mul, G.n_sub, G.n_add, G.n_ofNat] + have p : gSize.toNat = 18446744069414584321 := by decide + have inv : inverse256.n = 18374686475393433601 := rfl + rw [p, inv] + omega + +theorem byte_sub_borrow {x y low : G} (hx : x.n < 256) (hy : y.n < 256) + (hlow : low = G.ofNat ((x.n + 256 - y.n) % 256)) : + (low + y - x) * inverse256 = if x.n < y.n then 1 else 0 := by + have diff : low + y - x = if x.n < y.n then 256 else 0 := by + apply G.ext_n + rw [hlow] + split + all_goals + simp only [G.n_sub, G.n_add, G.n_ofNat] + have full : (256 : G).n = 256 := rfl + have zero : (0 : G).n = 0 := rfl + simp only [full, zero] + have p : gSize.toNat = 18446744069414584321 := by decide + rw [p] + omega + rw [diff] + split <;> decide +kernel + +theorem byte_carry_relation {x y z previous carry : G} + (hx : x.n < 256) (hy : y.n < 256) (hz : z.n < 256) + (hp : previous = 0 ∨ previous = 1) (hc : carry = 0 ∨ carry = 1) + (computed : carry = (x + y + previous - z) * inverse256) : + x.n + y.n + previous.n = z.n + 256 * carry.n := by + have hp' : previous.n ≤ 1 := by rcases hp with rfl | rfl <;> decide + have hc' : carry.n ≤ 1 := by rcases hc with rfl | rfl <;> decide + have fieldEqual : carry * 256 = x + y + previous - z := by + rw [computed, byte_division_eq] + have numeric := congrArg G.n fieldEqual + simp only [G.n_mul, G.n_sub, G.n_add] at numeric + have scale : (256 : G).n = 256 := rfl + have p : gSize.toNat = 18446744069414584321 := by decide + rw [scale, p] at numeric + omega + +def pack4 (bytes : Fin 4 → G) : G := + bytes 0 + 256 * bytes 1 + 65536 * bytes 2 + 16777216 * bytes 3 + +def pack4Nat (bytes : Fin 4 → G) : Nat := + (bytes 0).n + 256 * (bytes 1).n + 65536 * (bytes 2).n + 16777216 * (bytes 3).n + +theorem pack4_n (bytes : Fin 4 → G) (bounded : ∀ i, (bytes i).n < 256) : + (pack4 bytes).n = pack4Nat bytes ∧ (pack4 bytes).n < 2 ^ 32 := by + have h0 := bounded 0 + have h1 := bounded 1 + have h2 := bounded 2 + have h3 := bounded 3 + have totalBound : (bytes 0).n + 256 * (bytes 1).n + 65536 * (bytes 2).n + + 16777216 * (bytes 3).n < 2 ^ 32 := by omega + have fieldBound : (bytes 0).n + 256 * (bytes 1).n + 65536 * (bytes 2).n + + 16777216 * (bytes 3).n < 18446744069414584321 := + Nat.lt_trans totalBound (by decide) + have s1 : (256 : G).n = 256 := rfl + have s2 : (65536 : G).n = 65536 := rfl + have s3 : (16777216 : G).n = 16777216 := rfl + simp only [pack4, pack4Nat, G.n_add, G.n_mul, s1, s2, s3] + have p : gSize.toNat = 18446744069414584321 := by decide + rw [p] + simp only [Nat.add_mod_mod, Nat.mod_add_mod] + rw [Nat.mod_eq_of_lt fieldBound] + exact ⟨rfl, totalBound⟩ + +def carryStep (x y z previous : G) : G := (x + y + previous - z) * inverse256 + +def u32Carries (x y z : Fin 4 → G) : Fin 5 → G := + let c1 := carryStep (x 0) (y 0) (z 0) 1 + let c2 := carryStep (x 1) (y 1) (z 1) c1 + let c3 := carryStep (x 2) (y 2) (z 2) c2 + let c4 := carryStep (x 3) (y 3) (z 3) c3 + fun i => match i with + | 0 => 1 + | 1 => c1 + | 2 => c2 + | 3 => c3 + | 4 => c4 + +theorem u32Carry_relation (x y z : Fin 4 → G) + (hx : ∀ i, (x i).n < 256) (hy : ∀ i, (y i).n < 256) (hz : ∀ i, (z i).n < 256) + (boolean : ∀ i : Fin 4, booleanConstraint (u32Carries x y z i.succ) = 0) : + pack4Nat x + pack4Nat y + 1 = pack4Nat z + 2 ^ 32 * (u32Carries x y z 4).n := by + have hc0 : u32Carries x y z 0 = 0 ∨ u32Carries x y z 0 = 1 := Or.inr rfl + have hc1 := G.boolean_of_constraint (boolean 0) + have hc2 := G.boolean_of_constraint (boolean 1) + have hc3 := G.boolean_of_constraint (boolean 2) + have hc4 := G.boolean_of_constraint (boolean 3) + have r0 := byte_carry_relation (hx 0) (hy 0) (hz 0) hc0 hc1 rfl + have r1 := byte_carry_relation (hx 1) (hy 1) (hz 1) hc1 hc2 rfl + have r2 := byte_carry_relation (hx 2) (hy 2) (hz 2) hc2 hc3 rfl + have r3 := byte_carry_relation (hx 3) (hy 3) (hz 3) hc3 hc4 rfl + simp only [show (0 : Fin 4).succ = (1 : Fin 5) from rfl, + show (1 : Fin 4).succ = (2 : Fin 5) from rfl, + show (2 : Fin 4).succ = (3 : Fin 5) from rfl, + show (3 : Fin 4).succ = (4 : Fin 5) from rfl] at r0 r1 r2 r3 + have initial : (u32Carries x y z 0).n = 1 := rfl + rw [initial] at r0 + unfold pack4Nat + omega + +theorem u32_less_than (x y z : Fin 4 → G) + (hx : ∀ i, (x i).n < 256) (hy : ∀ i, (y i).n < 256) (hz : ∀ i, (z i).n < 256) + (boolean : ∀ i : Fin 4, booleanConstraint (u32Carries x y z i.succ) = 0) : + 1 - u32Carries x y z 4 = G.u32LessThan (pack4 x) (pack4 z) := by + have relation := u32Carry_relation x y z hx hy hz boolean + obtain ⟨nx, bx⟩ := pack4_n x hx + obtain ⟨ny, by'⟩ := pack4_n y hy + obtain ⟨nz, bz⟩ := pack4_n z hz + have last := G.boolean_of_constraint (boolean 3) + change u32Carries x y z 4 = 0 ∨ u32Carries x y z 4 = 1 at last + rcases last with zero | one + · have value : (u32Carries x y z 4).n = 0 := congrArg G.n zero + have less : (pack4 x).n < (pack4 z).n := by omega + rw [zero, G.u32LessThan, if_pos less] + decide +kernel + · have value : (u32Carries x y z 4).n = 1 := congrArg G.n one + have notLess : ¬(pack4 x).n < (pack4 z).n := by omega + rw [one, G.u32LessThan, if_neg notLess] + decide +kernel + +theorem active_u32_less_than {selector a b : G} (active : selector = 1) + (x y z : Fin 4 → G) + (hx : ∀ i, (x i).n < 256) (hy : ∀ i, (y i).n < 256) (hz : ∀ i, (z i).n < 256) + (decomposeA : selector * (a - pack4 x) = 0) + (decomposeB : selector * (b - pack4 z) = 0) + (carries : ∀ i : Fin 4, selector * booleanConstraint (u32Carries x y z i.succ) = 0) : + a.n < 2 ^ 32 ∧ b.n < 2 ^ 32 ∧ + 1 - u32Carries x y z 4 = G.u32LessThan a b := by + have ha := active_case active decomposeA + have hb := active_case active decomposeB + subst a b + refine ⟨(pack4_n x hx).2, (pack4_n z hz).2, u32_less_than x y z hx hy hz ?_⟩ + intro i + have satisfied := carries i + rw [active, G.mul_comm, G.mul_one] at satisfied + exact satisfied + +end AIR +end Aiur diff --git a/Ix/Aiur/Proofs/ByteColumns.lean b/Ix/Aiur/Proofs/ByteColumns.lean new file mode 100644 index 000000000..85eeead7b --- /dev/null +++ b/Ix/Aiur/Proofs/ByteColumns.lean @@ -0,0 +1,374 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.MemoryColumns + +/-! +The native fixed-height guard requires active byte tables at degrees 8 and 16. +Physical byte columns and fixed preprocessed columns supply exactly the +logical byte providers, up to enumeration order. A system trace combines +canonical function, memory and byte assignments and their lookup budget. +Its balanced, satisfying columns imply execution of the selected success +call and functional memory. Native expression/codec/verifier refinement, +compiler refinement and the certified semantic/cryptographic endpoint remain +separate obligations. +-/ + +namespace Aiur + +def fixedTraceHeights : List Nat → List Bool → List Nat → Bool + | [], [], [] => true + | height :: heights, false :: active, degrees => height == 0 && fixedTraceHeights heights active degrees + | height :: heights, true :: active, degree :: degrees => + (height == 0 || (degree < 64 && height == 2^degree)) && fixedTraceHeights heights active degrees + | _, _, _ => false + +inductive FixedTraceHeights : List Nat → List Bool → List Nat → Prop where + | nil : FixedTraceHeights [] [] [] + | inactive {heights : List Nat} {active : List Bool} {degrees : List Nat} + (rest : FixedTraceHeights heights active degrees) : + FixedTraceHeights (0 :: heights) (false :: active) degrees + | active (height degree : Nat) {heights : List Nat} {active : List Bool} {degrees : List Nat} + (matched : height = 0 ∨ degree < 64 ∧ height = 2^degree) + (rest : FixedTraceHeights heights active degrees) : + FixedTraceHeights (height :: heights) (true :: active) (degree :: degrees) + +theorem fixedTraceHeights_sound {heights : List Nat} {active : List Bool} {degrees : List Nat} + (accepted : fixedTraceHeights heights active degrees = true) : FixedTraceHeights heights active degrees := by + induction heights generalizing active degrees with + | nil => + cases active <;> cases degrees <;> simp only [fixedTraceHeights, Bool.false_eq_true] at accepted + exact .nil + | cons height heights ih => + cases active with + | nil => simp only [fixedTraceHeights, Bool.false_eq_true] at accepted + | cons enabled active => + cases enabled with + | false => + simp only [fixedTraceHeights, Bool.and_eq_true, beq_iff_eq] at accepted + obtain ⟨rfl, accepted⟩ := accepted + exact .inactive (ih accepted) + | true => + cases degrees with + | nil => simp only [fixedTraceHeights, Bool.false_eq_true] at accepted + | cons degree degrees => + simp only [fixedTraceHeights, Bool.and_eq_true, Bool.or_eq_true, beq_iff_eq, + decide_eq_true_eq] at accepted + exact .active height degree accepted.1 (ih accepted.2) + +theorem fixedTraceHeights_complete {heights : List Nat} {active : List Bool} {degrees : List Nat} + (valid : FixedTraceHeights heights active degrees) : fixedTraceHeights heights active degrees = true := by + induction valid with + | nil => rfl + | inactive rest ih => exact ih + | active height degree matched rest ih => + simp only [fixedTraceHeights, Bool.and_eq_true, Bool.or_eq_true, beq_iff_eq, + decide_eq_true_eq] + exact ⟨matched, ih⟩ + +theorem FixedTraceHeights.alignment {heights : List Nat} {active : List Bool} {degrees : List Nat} + (valid : FixedTraceHeights heights active degrees) : + heights.length = active.length ∧ degrees.length = (active.filter id).length := by + induction valid with + | nil => exact ⟨rfl, rfl⟩ + | inactive rest ih => simpa only [List.length_cons, List.filter_cons, id_eq, + Bool.false_eq_true, ↓reduceIte, Nat.add_right_cancel_iff] using ih + | active height degree matched rest ih => simpa only [List.length_cons, List.filter_cons, id_eq, + ↓reduceIte, Nat.add_right_cancel_iff] using ih + +end Aiur + +namespace Aiur.AIR + +abbrev Byte1Columns := Fin 3 → G +abbrev Byte2Columns := Fin 10 → G + +def Byte1Kind.column : Byte1Kind → Fin 3 + | .bits => 0 + | .shiftLeft => 1 + | .shiftRight => 2 + +def Byte2Kind.column : Byte2Kind → Fin 10 + | .xor => 0 + | .add => 1 + | .sub => 2 + | .and => 3 + | .or => 4 + | .lessThan => 5 + | .range => 6 + | .mul => 7 + | .split7 => 8 + | .split4 => 9 + +def byte1PreprocessedColumns (row : Fin 256) : Fin 11 → G := + fun column => (byte1Preprocessed row)[column.val]?.getD 0 + +def byte2PreprocessedColumns (row : Fin 65536) : Fin 14 → G := + fun column => (byte2Preprocessed row)[column.val]?.getD 0 + +def byte1ColumnLookup (kind : Byte1Kind) (preprocessed : Fin 11 → G) (columns : Byte1Columns) : + G × List G := + (0 - columns kind.column, match kind with + | .bits => [2, preprocessed 0] ++ List.ofFn (fun bit : Fin 8 => preprocessed ⟨1 + bit.val, by omega⟩) + | .shiftLeft => [3, preprocessed 0, preprocessed 9] + | .shiftRight => [4, preprocessed 0, preprocessed 10]) + +def byte2ColumnLookup (kind : Byte2Kind) (preprocessed : Fin 14 → G) (columns : Byte2Columns) : + G × List G := + (0 - columns kind.column, [kind.channel, preprocessed 0, preprocessed 1] ++ match kind with + | .xor => [preprocessed 2] + | .add => [preprocessed 3] + | .sub => [preprocessed 4] + | .and => [preprocessed 5] + | .or => [preprocessed 6] + | .lessThan => [preprocessed 7] + | .range => [] + | .mul => [preprocessed 8, preprocessed 9] + | .split7 => [preprocessed 10, preprocessed 11] + | .split4 => [preprocessed 12, preprocessed 13]) + +def byte1ColumnProvider (kind : Byte1Kind) (row : Fin 256) (columns : Byte1Columns) : + Provider (List G) := ((byte1ColumnLookup kind (byte1PreprocessedColumns row) columns).2, columns kind.column) + +def byte2ColumnProvider (kind : Byte2Kind) (row : Fin 65536) (columns : Byte2Columns) : + Provider (List G) := ((byte2ColumnLookup kind (byte2PreprocessedColumns row) columns).2, columns kind.column) + +theorem byte1ColumnProvider_reflect (kind : Byte1Kind) (row : Fin 256) (columns : Byte1Columns) : + byte1ColumnProvider kind row columns = + (byte1Request kind (G.ofNat row.val) (byte1Outputs kind row), columns kind.column) := by + cases kind <;> + simp [byte1ColumnProvider, byte1ColumnLookup, byte1PreprocessedColumns, byte1Preprocessed, + byte1Request, byte1Outputs, Byte1Kind.channel, Byte1Kind.column, List.ofFn_succ] + all_goals simp [Array.getElem_push, + show (9 : Fin 11).val = 9 from rfl, show (10 : Fin 11).val = 10 from rfl] + +theorem byte2ColumnProvider_reflect (kind : Byte2Kind) (row : Fin 65536) (columns : Byte2Columns) : + byte2ColumnProvider kind row columns = + (byte2Request kind (byteRangeMessage row).1 (byteRangeMessage row).2 (byte2Outputs kind row), + columns kind.column) := by + cases kind <;> + simp [byte2ColumnProvider, byte2ColumnLookup, byte2PreprocessedColumns, byte2Preprocessed, + byte2Request, byte2Outputs, Byte2Kind.channel, Byte2Kind.column] + all_goals repeat constructor + all_goals rfl + +end Aiur.AIR + +namespace Aiur + +theorem fixedTraceHeights_bytes {active : List Bool} {degrees : List Nat} + (accepted : fixedTraceHeights [256, 65536] active degrees = true) : + active = [true, true] ∧ degrees = [8, 16] := by + have valid := fixedTraceHeights_sound accepted + cases valid with + | active _ degree first rest => + have firstPower : 2^degree = 2^8 := by + rcases first with impossible | ⟨_, power⟩ + · contradiction + · exact power.symm + have firstDegree := (Nat.pow_right_inj (by decide : 1 < 2)).mp firstPower + cases rest with + | active _ next second rest => + have secondPower : 2^next = 2^16 := by + rcases second with impossible | ⟨_, power⟩ + · contradiction + · exact power.symm + have secondDegree := (Nat.pow_right_inj (by decide : 1 < 2)).mp secondPower + cases rest + exact ⟨rfl, by rw [firstDegree, secondDegree]⟩ + +end Aiur + +namespace Aiur.AIR + +theorem CircuitTraces.fixed_heights_append {circuits : List Bytecode.Circuit} (traces : CircuitTraces circuits) + (heights : List Nat) (active : List Bool) (degrees : List Nat) : + fixedTraceHeights (List.replicate circuits.length 0 ++ heights) + (traces.bitmap ++ active) (traces.degrees ++ degrees) = fixedTraceHeights heights active degrees := by + induction traces with + | nil => rfl + | inactive circuit rest ih => + simpa only [List.length_cons, List.replicate_succ, List.cons_append, bitmap, CircuitTraces.degrees, + fixedTraceHeights, beq_self_eq_true, Bool.true_and] using ih + | active circuit degree values rest ih => + simpa only [List.length_cons, List.replicate_succ, List.cons_append, bitmap, CircuitTraces.degrees, + fixedTraceHeights, beq_self_eq_true, Bool.true_or, Bool.true_and] using ih + +theorem MemoryTraces.fixed_heights_append {widths : List Nat} (traces : MemoryTraces widths) + (heights : List Nat) (active : List Bool) (degrees : List Nat) : + fixedTraceHeights (List.replicate widths.length 0 ++ heights) + (traces.bitmap ++ active) (traces.degrees ++ degrees) = fixedTraceHeights heights active degrees := by + induction traces with + | nil => rfl + | inactive width rest ih => + simpa only [List.length_cons, List.replicate_succ, List.cons_append, bitmap, MemoryTraces.degrees, + fixedTraceHeights, beq_self_eq_true, Bool.true_and] using ih + | active width degree matrix rest ih => + simpa only [List.length_cons, List.replicate_succ, List.cons_append, bitmap, MemoryTraces.degrees, + fixedTraceHeights, beq_self_eq_true, Bool.true_or, Bool.true_and] using ih + +theorem canonical_byte_metadata {circuits : List Bytecode.Circuit} (functions : CircuitTraces circuits) + {widths : List Nat} (memories : MemoryTraces widths) + {active : List Bool} {degrees : List Nat} + (accepted : fixedTraceHeights + (List.replicate circuits.length 0 ++ (List.replicate widths.length 0 ++ [256, 65536])) + (functions.bitmap ++ (memories.bitmap ++ active)) + (functions.degrees ++ (memories.degrees ++ degrees)) = true) : + active = [true, true] ∧ degrees = [8, 16] := by + rw [functions.fixed_heights_append, memories.fixed_heights_append] at accepted + exact fixedTraceHeights_bytes accepted + +end Aiur.AIR + +namespace Aiur.AIR + +theorem suppliedWeight_perm {α : Type} [DecidableEq α] {left right : List (Provider α)} + (permutation : left.Perm right) (message : α) : suppliedWeight message left = suppliedWeight message right := by + induction permutation with + | nil => rfl + | cons provider permutation ih => + change (if provider.1 = message then provider.2 + suppliedWeight message _ else suppliedWeight message _) = + (if provider.1 = message then provider.2 + suppliedWeight message _ else suppliedWeight message _) + rw [ih] + | swap a b rest => + by_cases left : a.1 = message <;> by_cases right : b.1 = message <;> + simp only [suppliedWeight, List.foldr_cons, left, right, ↓reduceIte] + rw [← G.add_assoc, G.add_comm b.2 a.2, G.add_assoc] + | trans first last ih ih' => exact ih.trans ih' + +theorem PaddedLookupBalance.perm_providers {width : Nat} {queries : List (List G)} + {left right : List (Provider (List G))} (balanced : PaddedLookupBalance width queries left) + (permutation : left.Perm right) : PaddedLookupBalance width queries right := by + intro message + exact (balanced message).trans (suppliedWeight_perm (permutation.map _) message) + +private theorem flatMap_append_perm {α β : Type} (items : List α) (left right : α → List β) : + (items.flatMap fun item => left item ++ right item).Perm (items.flatMap left ++ items.flatMap right) := by + induction items with + | nil => exact .nil + | cons item items ih => + simp only [List.flatMap_cons] + have first := (List.Perm.refl (left item ++ right item)).append ih + apply first.trans + simpa only [List.append_assoc] using + ((show (right item ++ items.flatMap left).Perm (items.flatMap left ++ right item) from + List.perm_append_comm).append_right + (items.flatMap right)).append_left (left item) + +theorem flatMap_map_swap {α β γ : Type} (left : List α) (right : List β) (value : α → β → γ) : + (left.flatMap fun a => right.map (value a)).Perm (right.flatMap fun b => left.map (fun a => value a b)) := by + induction right with + | nil => simp + | cons b right ih => + simp only [List.map_cons, List.flatMap_cons] + have split := flatMap_append_perm left (fun a => [value a b]) (fun a => right.map (value a)) + simp only [← List.map_eq_flatMap] at split + exact split.trans ((List.Perm.refl _).append ih) + +def byte1MatrixProviders (matrix : Fin 256 → Byte1Columns) : List (Provider (List G)) := + (List.finRange 256).flatMap fun row => Byte1Kind.all.map fun kind => byte1ColumnProvider kind row (matrix row) + +def byte2MatrixProviders (matrix : Fin 65536 → Byte2Columns) : List (Provider (List G)) := + (List.finRange 65536).flatMap fun row => Byte2Kind.all.map fun kind => byte2ColumnProvider kind row (matrix row) + +theorem byte1MatrixProviders_reflect (matrix : Fin 256 → Byte1Columns) : + (byte1MatrixProviders matrix).Perm (byte1Providers fun kind row => matrix row kind.column) := by + have swapped := flatMap_map_swap (List.finRange 256) Byte1Kind.all + (fun row kind => byte1ColumnProvider kind row (matrix row)) + simpa only [byte1MatrixProviders, byte1ColumnProvider_reflect, byte1Providers, + List.finRange, List.map_ofFn, Function.comp_def] using swapped + +theorem byte2MatrixProviders_reflect (matrix : Fin 65536 → Byte2Columns) : + (byte2MatrixProviders matrix).Perm (byte2Providers fun kind row => matrix row kind.column) := by + have swapped := flatMap_map_swap (List.finRange 65536) Byte2Kind.all + (fun row kind => byte2ColumnProvider kind row (matrix row)) + simpa only [byte2MatrixProviders, byte2ColumnProvider_reflect, byte2Providers, + List.finRange, List.map_ofFn, Function.comp_def] using swapped + +structure ByteTraces where + unary : Fin 256 → Byte1Columns + binary : Fin 65536 → Byte2Columns + +def ByteTraces.providers (traces : ByteTraces) : List (Provider (List G)) := + byte1MatrixProviders traces.unary ++ byte2MatrixProviders traces.binary + +def ByteTraces.byte1Weights (traces : ByteTraces) : Byte1Kind → Fin 256 → G := + fun kind row => traces.unary row kind.column + +def ByteTraces.byte2Weights (traces : ByteTraces) : Byte2Kind → Fin 65536 → G := + fun kind row => traces.binary row kind.column + +theorem ByteTraces.providers_reflect (traces : ByteTraces) : + traces.providers.Perm (byte1Providers traces.byte1Weights ++ byte2Providers traces.byte2Weights) := + (byte1MatrixProviders_reflect traces.unary).append (byte2MatrixProviders_reflect traces.binary) + +structure SystemTraces (program : Bytecode.Toplevel) where + functions : CircuitTraces program.circuits.toList + memories : MemoryTraces program.memorySizes.toList + bytes : ByteTraces + +def SystemTraces.bitmap {program : Bytecode.Toplevel} (traces : SystemTraces program) : List Bool := + traces.functions.bitmap ++ (traces.memories.bitmap ++ [true, true]) + +def SystemTraces.degrees {program : Bytecode.Toplevel} (traces : SystemTraces program) : List Nat := + traces.functions.degrees ++ (traces.memories.degrees ++ [8, 16]) + +def systemFixedHeights (program : Bytecode.Toplevel) : List Nat := + List.replicate program.circuits.size 0 ++ (List.replicate program.memorySizes.size 0 ++ [256, 65536]) + +def systemLookupSlots (program : Bytecode.Toplevel) : List Nat := + program.circuits.toList.map (·.layout.lookups) ++ (List.replicate program.memorySizes.size 1 ++ [3, 10]) + +def SystemTraces.queryBound {program : Bytecode.Toplevel} (traces : SystemTraces program) : Option Nat := + lookupQueryBound (systemLookupSlots program) traces.bitmap traces.degrees + +def SystemTraces.providers {program : Bytecode.Toplevel} (traces : SystemTraces program) + (circuits : List CircuitEmission) : List (Provider (List G)) := + circuitProviders circuits ++ (traces.memories.providers ++ traces.bytes.providers) + +theorem SystemTraces.fixed_heights {program : Bytecode.Toplevel} (traces : SystemTraces program) : + fixedTraceHeights (systemFixedHeights program) traces.bitmap traces.degrees = true := by + unfold systemFixedHeights bitmap degrees + rw [← Array.length_toList, traces.functions.fixed_heights_append] + rw [← Array.length_toList, traces.memories.fixed_heights_append] + rfl + +theorem SystemTraces.memory_functional {program : Bytecode.Toplevel} (traces : SystemTraces program) + {result : Nat} (budget : traces.queryBound = some result) (satisfied : traces.memories.Satisfied) + {width : Nat} {pointer : G} {left right : Array G} + (loadedLeft : memoryFacts traces.memories.rows width pointer left) + (loadedRight : memoryFacts traces.memories.rows width pointer right) : left = right := + traces.memories.functional_of_budget traces.functions budget satisfied loadedLeft loadedRight + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem Backend.column_trace_execution {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + (traces : SystemTraces backend.compiled.bytecode) {witnesses : List CircuitWitness} + (emitted : traces.functions.emitWitnesses backend.compiled.bytecode = some witnesses) + {result : Nat} (budget : traces.queryBound = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: + encodedCircuitQueryPool (witnesses.map (·.emission))) + (traces.providers (witnesses.map (·.emission)))) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) (memorySatisfied : traces.memories.Satisfied) : + Execution backend.compiled.bytecode (memoryFacts traces.memories.rows) + ⟨selection.function, input, selection.success, 0⟩ := by + unfold SystemTraces.providers at balanced + have replaced := balanced.perm_providers + ((traces.bytes.providers_reflect.append_left traces.memories.providers).append_left + (circuitProviders (witnesses.map CircuitWitness.emission))) + rw [← List.append_assoc traces.memories.providers] at replaced + exact backend.memory_trace_execution generic traces.functions traces.memories + traces.bytes.byte1Weights traces.bytes.byte2Weights emitted budget width input arity + replaced publicWidth queryWidths satisfied memorySatisfied + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/ByteLookups.lean b/Ix/Aiur/Proofs/ByteLookups.lean new file mode 100644 index 000000000..73e644c1f --- /dev/null +++ b/Ix/Aiur/Proofs/ByteLookups.lean @@ -0,0 +1,284 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ByteArithmetic + +/-! +Extraction of byte operations from fixed byte-table lookup messages. + +The three unary and ten binary channels, row order, output columns and +arities match the native byte chips. Providers range over the complete +fixed tables with arbitrary field multiplicities. Exact balance and a +query-count bound force each requested input and output to match one row. +The step theorems include virtual carry/borrow outputs omitted by lookups. + +Native preprocessed rows and lookup expressions are compared exhaustively +against these definitions by the component gate. That executable comparison +does not prove native refinement. Extracting balance for these exact tuples +from the global padded/compressed lookup argument remains a separate task. +-/ + +namespace Aiur.AIR + +inductive Byte1Kind where + | bits | shiftLeft | shiftRight + deriving DecidableEq + +def Byte1Kind.all : List Byte1Kind := [.bits, .shiftLeft, .shiftRight] + +def Byte1Kind.channel : Byte1Kind → G + | .bits => 2 + | .shiftLeft => 3 + | .shiftRight => 4 + +theorem Byte1Kind.channel_injective {left right : Byte1Kind} + (same : left.channel = right.channel) : left = right := by + revert same + cases left <;> cases right <;> decide +kernel + +def Byte1Kind.result : Byte1Kind → G → Array G + | .bits, input => Array.ofFn (G.u8BitDecomposition input) + | .shiftLeft, input => #[G.u8ShiftLeft input] + | .shiftRight, input => #[G.u8ShiftRight input] + +def byte1Outputs (kind : Byte1Kind) (row : Fin 256) : Array G := + match kind with + | .bits => Array.ofFn fun bit : Fin 8 => G.ofNat ((row.val >>> bit.val) &&& 1) + | .shiftLeft => #[G.ofNat ((row.val * 2) % 256)] + | .shiftRight => #[G.ofNat (row.val / 2)] + +def byte1Request (kind : Byte1Kind) (input : G) (outputs : Array G) : List G := + kind.channel :: input :: outputs.toList + +def byte1Providers (weights : Byte1Kind → Fin 256 → G) : List (Provider (List G)) := + Byte1Kind.all.flatMap fun kind => List.ofFn fun row => + (byte1Request kind (G.ofNat row.val) (byte1Outputs kind row), weights kind row) + +theorem byte1Outputs_correct (kind : Byte1Kind) (row : Fin 256) : + byte1Outputs kind row = kind.result (G.ofNat row.val) := by + have below : row.val < gSize.toNat := Nat.lt_trans row.isLt (by decide) + cases kind <;> + simp only [byte1Outputs, Byte1Kind.result, G.u8ShiftLeft, + G.u8ShiftRight, G.n_ofNat, Nat.mod_eq_of_lt below] + apply congrArg Array.ofFn + funext bit + simp only [G.u8BitDecomposition, G.n_ofNat, Nat.mod_eq_of_lt below] + +theorem exactLookupBalance_byte1 {queries : List (List G)} + (weights : Byte1Kind → Fin 256 → G) + (balanced : ExactLookupBalance queries (byte1Providers weights)) + (bounded : queries.length < gSize.toNat) + {kind : Byte1Kind} {input : G} {outputs : Array G} + (queried : byte1Request kind input outputs ∈ queries) : + input.n < 256 ∧ outputs = kind.result input := by + obtain ⟨provider, member, same, _⟩ := exactLookupBalance_provider balanced bounded queried + obtain ⟨providerKind, _, rowMember⟩ := List.mem_flatMap.mp member + obtain ⟨row, equal⟩ := List.mem_ofFn.mp rowMember + subst provider + change byte1Request providerKind (G.ofNat row.val) (byte1Outputs providerKind row) = + byte1Request kind input outputs at same + obtain ⟨sameChannel, sameTail⟩ := List.cons.inj same + have equalKind := Byte1Kind.channel_injective sameChannel + subst providerKind + obtain ⟨sameInput, sameOutputs⟩ := List.cons.inj sameTail + have below : row.val < gSize.toNat := Nat.lt_trans row.isLt (by decide) + constructor + · rw [← sameInput, G.n_ofNat, Nat.mod_eq_of_lt below] + exact row.isLt + · rw [← sameInput] + exact (Array.toList_inj.mp sameOutputs).symm.trans (byte1Outputs_correct kind row) + +inductive Byte2Kind where + | xor | add | sub | and | or | lessThan | range | mul | split7 | split4 + deriving DecidableEq + +def Byte2Kind.all : List Byte2Kind := + [.xor, .add, .sub, .and, .or, .lessThan, .range, .mul, .split7, .split4] + +def Byte2Kind.channel : Byte2Kind → G + | .xor => 5 + | .add => 6 + | .sub => 7 + | .and => 8 + | .or => 9 + | .lessThan => 10 + | .range => 11 + | .mul => 12 + | .split7 => 13 + | .split4 => 14 + +theorem Byte2Kind.channel_injective {left right : Byte2Kind} + (same : left.channel = right.channel) : left = right := by + revert same + cases left <;> cases right <;> decide +kernel + +def Byte2Kind.result : Byte2Kind → G → G → Array G + | .xor, x, y => #[G.u8Xor x y] + | .add, x, y => #[(G.u8Add x y).1] + | .sub, x, y => #[(G.u8Sub x y).1] + | .and, x, y => #[G.u8And x y] + | .or, x, y => #[G.u8Or x y] + | .lessThan, x, y => #[G.u8LessThan x y] + | .range, _, _ => #[] + | .mul, x, y => Bytecode.AIR.pairValues (G.u8Mul x y) + | .split7, x, y => #[G.ofNat ((x.n ^^^ y.n) / 128), G.ofNat (((x.n ^^^ y.n) * 2) % 256)] + | .split4, x, y => #[G.ofNat ((x.n ^^^ y.n) / 16), G.ofNat (((x.n ^^^ y.n) * 16) % 256)] + +def byte2Outputs (kind : Byte2Kind) (row : Fin 65536) : Array G := + let x := row.val / 256 + let y := row.val % 256 + match kind with + | .xor => #[G.ofNat (x ^^^ y)] + | .add => #[G.ofNat ((x + y) % 256)] + | .sub => #[G.ofNat ((x + 256 - y) % 256)] + | .and => #[G.ofNat (x &&& y)] + | .or => #[G.ofNat (x ||| y)] + | .lessThan => #[if x < y then 1 else 0] + | .range => #[] + | .mul => #[G.ofNat ((x * y) % 256), G.ofNat ((x * y) / 256)] + | .split7 => #[G.ofNat ((x ^^^ y) / 128), G.ofNat (((x ^^^ y) * 2) % 256)] + | .split4 => #[G.ofNat ((x ^^^ y) / 16), G.ofNat (((x ^^^ y) * 16) % 256)] + +def byte2Request (kind : Byte2Kind) (x y : G) (outputs : Array G) : List G := + kind.channel :: x :: y :: outputs.toList + +def byte2Providers (weights : Byte2Kind → Fin 65536 → G) : List (Provider (List G)) := + Byte2Kind.all.flatMap fun kind => List.ofFn fun row => + let inputs := byteRangeMessage row + (byte2Request kind inputs.1 inputs.2 (byte2Outputs kind row), weights kind row) + +theorem byte2Outputs_correct (kind : Byte2Kind) (row : Fin 65536) : + byte2Outputs kind row = kind.result (byteRangeMessage row).1 (byteRangeMessage row).2 := by + have left : row.val / 256 < gSize.toNat := + Nat.lt_trans (show row.val / 256 < 256 by omega) (by decide) + have right : row.val % 256 < gSize.toNat := Nat.lt_trans (Nat.mod_lt _ (by decide)) (by decide) + cases kind <;> + simp only [byte2Outputs, Byte2Kind.result, byteRangeMessage, G.u8Xor, G.u8Add, + G.u8Sub, G.u8And, G.u8Or, G.u8LessThan, G.u8Mul, Bytecode.AIR.pairValues, + G.n_ofNat, Nat.mod_eq_of_lt left, Nat.mod_eq_of_lt right] + +theorem exactLookupBalance_byte2 {queries : List (List G)} + (weights : Byte2Kind → Fin 65536 → G) + (balanced : ExactLookupBalance queries (byte2Providers weights)) + (bounded : queries.length < gSize.toNat) + {kind : Byte2Kind} {x y : G} {outputs : Array G} + (queried : byte2Request kind x y outputs ∈ queries) : + x.n < 256 ∧ y.n < 256 ∧ outputs = kind.result x y := by + obtain ⟨provider, member, same, _⟩ := exactLookupBalance_provider balanced bounded queried + obtain ⟨providerKind, _, rowMember⟩ := List.mem_flatMap.mp member + obtain ⟨row, equal⟩ := List.mem_ofFn.mp rowMember + subst provider + change byte2Request providerKind (byteRangeMessage row).1 (byteRangeMessage row).2 + (byte2Outputs providerKind row) = byte2Request kind x y outputs at same + obtain ⟨sameChannel, sameTail⟩ := List.cons.inj same + have equalKind := Byte2Kind.channel_injective sameChannel + subst providerKind + obtain ⟨sameX, sameTail⟩ := List.cons.inj sameTail + obtain ⟨sameY, sameOutputs⟩ := List.cons.inj sameTail + rw [← sameX, ← sameY] + refine ⟨(byteRangeMessage_bounded row).1, (byteRangeMessage_bounded row).2, ?_⟩ + exact (Array.toList_inj.mp sameOutputs).symm.trans (byte2Outputs_correct kind row) + +def Byte1Kind.op : Byte1Kind → Bytecode.ValIdx → Bytecode.Op + | .bits => .u8BitDecomposition + | .shiftLeft => .u8ShiftLeft + | .shiftRight => .u8ShiftRight + +theorem byte1_primitive {kind : Byte1Kind} {values : Array G} {index : Bytecode.ValIdx} + {input : G} (read : values[index]? = some input) (bounded : input.n < 256) : + Bytecode.AIR.primitive (kind.op index) values #[] = some (kind.result input) := by + cases kind <;> + simp only [Byte1Kind.op, Byte1Kind.result, Bytecode.AIR.primitive, + Bytecode.AIR.unaryByte, read, bind, Option.bind, if_pos bounded, Function.comp_apply] + +theorem exactLookupBalance_byte1_step {queries : List (List G)} + (weights : Byte1Kind → Fin 256 → G) + (balanced : ExactLookupBalance queries (byte1Providers weights)) + (bounded : queries.length < gSize.toNat) + (memory : Bytecode.AIR.Memory) {kind : Byte1Kind} {values : Array G} + {index : Bytecode.ValIdx} {input : G} {outputs : Array G} + (read : values[index]? = some input) + (queried : byte1Request kind input outputs ∈ queries) : + Bytecode.AIR.Step memory (kind.op index) values (values ++ outputs) [] := by + obtain ⟨range, correct⟩ := exactLookupBalance_byte1 weights balanced bounded queried + apply Bytecode.AIR.Step.primitive (advice := #[]) + rw [correct] + exact byte1_primitive read range + +def Byte2Kind.op : Byte2Kind → Bytecode.ValIdx → Bytecode.ValIdx → Bytecode.Op + | .xor => .u8Xor + | .add => .u8Add + | .sub => .u8Sub + | .and => .u8And + | .or => .u8Or + | .lessThan => .u8LessThan + | .range => .u8RangeCheck + | .mul => .u8Mul + | .split7 => .u8XorSplit7 + | .split4 => .u8XorSplit4 + +def Byte2Kind.extendOutputs (kind : Byte2Kind) (x y : G) (outputs : Array G) : Array G := + match kind with + | .add => outputs.push ((x + y - outputs[0]?.getD 0) * inverse256) + | .sub => outputs.push ((outputs[0]?.getD 0 + y - x) * inverse256) + | _ => outputs + +theorem byte2_primitive {kind : Byte2Kind} {values : Array G} {left right : Bytecode.ValIdx} + {x y : G} (readX : values[left]? = some x) (readY : values[right]? = some y) + (hx : x.n < 256) (hy : y.n < 256) : + Bytecode.AIR.primitive (kind.op left right) values #[] = + some (kind.extendOutputs x y (kind.result x y)) := by + cases kind <;> + simp only [Byte2Kind.op, Byte2Kind.result, Byte2Kind.extendOutputs, + Bytecode.AIR.primitive, Bytecode.AIR.binaryByte, readX, readY, + bind, Option.bind, if_pos (And.intro hx hy)] + · simp only [G.u8Add, Bytecode.AIR.pairValues, Array.getElem?_singleton, ite_true, Option.getD_some] + rw [byte_add_carry hx hy rfl] + rfl + · simp only [G.u8Sub, Bytecode.AIR.pairValues, Array.getElem?_singleton, ite_true, Option.getD_some] + rw [byte_sub_borrow hx hy rfl] + rfl + +theorem exactLookupBalance_byte2_step {queries : List (List G)} + (weights : Byte2Kind → Fin 65536 → G) + (balanced : ExactLookupBalance queries (byte2Providers weights)) + (bounded : queries.length < gSize.toNat) + (memory : Bytecode.AIR.Memory) {kind : Byte2Kind} {values : Array G} + {left right : Bytecode.ValIdx} {x y : G} {outputs : Array G} + (readX : values[left]? = some x) (readY : values[right]? = some y) + (queried : byte2Request kind x y outputs ∈ queries) : + Bytecode.AIR.Step memory (kind.op left right) values + (values ++ kind.extendOutputs x y outputs) [] := by + obtain ⟨rangeX, rangeY, correct⟩ := exactLookupBalance_byte2 weights balanced bounded queried + apply Bytecode.AIR.Step.primitive (advice := #[]) + rw [correct] + exact byte2_primitive readX readY rangeX rangeY + +theorem active_u32_less_than_step (memory : Bytecode.AIR.Memory) + {selector a b : G} {values : Array G} {left right : Bytecode.ValIdx} + (active : selector = 1) (readA : values[left]? = some a) (readB : values[right]? = some b) + (x y z : Fin 4 → G) + (hx : ∀ i, (x i).n < 256) (hy : ∀ i, (y i).n < 256) (hz : ∀ i, (z i).n < 256) + (decomposeA : selector * (a - pack4 x) = 0) + (decomposeB : selector * (b - pack4 z) = 0) + (carries : ∀ i : Fin 4, selector * booleanConstraint (u32Carries x y z i.succ) = 0) : + Bytecode.AIR.Step memory (.u32LessThan left right) values + (values ++ #[1 - u32Carries x y z 4]) [] := by + obtain ⟨rangeA, rangeB, correct⟩ := active_u32_less_than active x y z hx hy hz decomposeA decomposeB carries + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, readA, readB, bind, Option.bind, if_pos (And.intro rangeA rangeB), correct] + +def byte1Preprocessed (row : Fin 256) : Array G := + #[G.ofNat row.val] ++ byte1Outputs .bits row ++ + byte1Outputs .shiftLeft row ++ byte1Outputs .shiftRight row + +def byte2Preprocessed (row : Fin 65536) : Array G := + let inputs := byteRangeMessage row + #[inputs.1, inputs.2] ++ byte2Outputs .xor row ++ byte2Outputs .add row ++ + byte2Outputs .sub row ++ byte2Outputs .and row ++ byte2Outputs .or row ++ + byte2Outputs .lessThan row ++ byte2Outputs .mul row ++ byte2Outputs .split7 row ++ + byte2Outputs .split4 row + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/CallInventory.lean b/Ix/Aiur/Proofs/CallInventory.lean new file mode 100644 index 000000000..b33f2f268 --- /dev/null +++ b/Ix/Aiur/Proofs/CallInventory.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationRows + +/-! +Call inventories retain the exact function and gap queries and rank-order +polynomials emitted alongside each operation. Sequence composition preserves +this inventory. Active satisfying calls have strictly increasing bounded ranks +when their byte queries belong to the shared global lookup pool. +-/ + +namespace Aiur.AIR +open Bytecode + +/-- A valued relation is either identically zero at this emission or checked +by one of its equations. Derived call ranks use the first case. -/ +def EquationAvailable (equations : List G) (value : G) : Prop := + value = 0 ∨ value ∈ equations + +theorem EquationAvailable.mono {first last : List G} {value : G} + (equation : EquationAvailable first value) (included : first ⊆ last) : + EquationAvailable last value := equation.imp_right (fun member => included member) + +theorem EquationAvailable.satisfied {equations : List G} {value : G} + (equation : EquationAvailable equations value) + (zero : ∀ value ∈ equations, value = 0) : value = 0 := + equation.elim id (zero value) + +/-- Every recorded call has its function query, all gap range queries and +an established selector-gated order relation. -/ +def CallsEmitted (rank selector : G) (equations : List G) (queries : List (List G)) + (calls : List (Bytecode.AIR.Call × (Fin 6 → G))) : Prop := + ∀ edge ∈ calls, functionMessage edge.1 ∈ queries ∧ + (rankByteQueries edge.2).map rangeMessage ⊆ queries ∧ + EquationAvailable equations (selector * callOrderConstraint rank edge.1.rank (packRank edge.2)) + +theorem emitOp_calls {row : Nat → G} {selector rank : G} {op : Op} + {values : Array RowValue} {emission : OpEmission} + (emitted : emitOp row selector rank op values = some emission) : + CallsEmitted rank selector emission.equations emission.queries emission.calls := by + cases op <;> simp only [emitOp, emitByte1, emitByte2, emitU32LessThan, emitU32Add, + emitAdvice, bind, Option.bind, Option.map, pure] at emitted + all_goals + repeat' first + | split at emitted + | (dsimp only at emitted; split at emitted) + all_goals cases emitted + all_goals simp [CallsEmitted, EquationAvailable, callOrderConstraint_derived, G.mul_zero] + +theorem CallsEmitted.append {rank selector : G} {firstEquations restEquations : List G} + {firstQueries restQueries : List (List G)} + {firstCalls restCalls : List (Bytecode.AIR.Call × (Fin 6 → G))} + (first : CallsEmitted rank selector firstEquations firstQueries firstCalls) + (rest : CallsEmitted rank selector restEquations restQueries restCalls) : + CallsEmitted rank selector (firstEquations ++ restEquations) + (firstQueries ++ restQueries) (firstCalls ++ restCalls) := by + intro edge member + rcases List.mem_append.mp member with left | right + · obtain ⟨query, bytes, equation⟩ := first edge left + exact ⟨List.mem_append_left _ query, + fun _ member => List.mem_append_left _ (bytes member), + equation.mono (fun _ member => List.mem_append_left _ member)⟩ + · obtain ⟨query, bytes, equation⟩ := rest edge right + exact ⟨List.mem_append_right _ query, + fun _ member => List.mem_append_right _ (bytes member), + equation.mono (fun _ member => List.mem_append_right _ member)⟩ + +theorem emitOps_calls {row : Nat → G} {selector rank : G} {ops : List Op} + {values : Array RowValue} {column : Nat} {emission : OpsEmission} + (emitted : emitOps row selector rank ops values column = some emission) : + CallsEmitted rank selector emission.equations emission.queries emission.calls := by + induction ops generalizing values column emission with + | nil => + simp only [emitOps, Option.some.injEq] at emitted + subst emission + simp [CallsEmitted] + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i rest restEmitted + have equal := Option.some.inj emitted + subst emission + exact (emitOp_calls firstEmitted).append (ih restEmitted) + +theorem CallsEmitted.ordered {tables : LookupTables} {width : Nat} {pool : List (List G)} + (global : GlobalLookups tables width pool) + {rank selector : G} {equations : List G} {queries : List (List G)} + {calls : List (Bytecode.AIR.Call × (Fin 6 → G))} + (tracked : CallsEmitted rank selector equations queries calls) + (active : selector = 1) (satisfied : ∀ equation ∈ equations, equation = 0) + (queried : queries ⊆ pool) (rankBound : rank.n < callRankBound) + {edge : Bytecode.AIR.Call × (Fin 6 → G)} (called : edge ∈ calls) + (childBound : edge.1.rank.n < callRankBound) : + functionMessage edge.1 ∈ pool ∧ rank.n < edge.1.rank.n := by + obtain ⟨query, bytes, equation⟩ := tracked edge called + refine ⟨queried query, + active_call_order_strict active rankBound childBound ?_ (equation.satisfied satisfied)⟩ + exact packRank_lt edge.2 (global.rank_bytes edge.2 (fun _ member => queried (bytes member))) + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/CallOrder.lean b/Ix/Aiur/Proofs/CallOrder.lean new file mode 100644 index 000000000..31f8087b0 --- /dev/null +++ b/Ix/Aiur/Proofs/CallOrder.lean @@ -0,0 +1,161 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Activity + +/-! Arithmetic for the call-order AIR. Each active function row carries a +48-bit rank. A constrained call binds the callee's rank in its function +lookup and supplies a 48-bit gap satisfying `child - parent - 1 - gap = 0`. +The bounds prevent field wraparound and force strict increase. Connecting +the byte-table lookups and native constraint emitter to these premises is +part of the remaining AIR extraction proof. +-/ + +namespace Aiur + +theorem G.n_ofNat (n : Nat) : (G.ofNat n).n = n % gSize.toNat := by + have hm : n % gSize.toNat < gSize.toNat := Nat.mod_lt _ (by decide) + have hw : n % gSize.toNat < UInt64.size := Nat.lt_trans hm (by decide) + have hv : (n % gSize.toNat).toUInt64.toNat = n % gSize.toNat := by + simp [Nat.toUInt64, Nat.mod_eq_of_lt hw] + have h : (n % gSize.toNat).toUInt64 < gSize := by + simpa only [UInt64.lt_iff_toNat_lt, hv] using hm + simp only [G.ofNat, dif_pos h, G.n, hv] + +theorem G.sub_eq_zero_iff (a b : G) : a - b = 0 ↔ a = b := by + have ha : a.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp a.property + have hb : b.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp b.property + have hp : gSize.toNat = 18446744069414584321 := by decide + constructor + · intro h + have hn := congrArg G.n h + change (G.ofNat (a.n + gSize.toNat - b.n)).n = 0 at hn + rw [G.n_ofNat, hp] at hn + rw [hp] at ha hb + have he : a.n = b.n := by omega + apply Subtype.ext + exact UInt64.toNat_inj.mp he + · intro h + subst b + change G.ofNat (a.n + gSize.toNat - a.n) = 0 + simp only [Nat.add_sub_cancel_left] + rfl + +theorem G.n_add (a b : G) : (a + b).n = (a.n + b.n) % gSize.toNat := + G.n_ofNat _ + +theorem G.n_mul (a b : G) : (a * b).n = (a.n * b.n) % gSize.toNat := + G.n_ofNat _ + +namespace AIR + +def callRankBound : Nat := 2 ^ 48 + +/-- The six little-endian byte expressions used by the Rust emitter. -/ +def packRank (bytes : Fin 6 → G) : G := + bytes 0 + 256 * bytes 1 + 65536 * bytes 2 + 16777216 * bytes 3 + + 4294967296 * bytes 4 + 1099511627776 * bytes 5 + +theorem packRank_lt (bytes : Fin 6 → G) (bounded : ∀ i, (bytes i).n < 256) : + (packRank bytes).n < callRankBound := by + have h0 := bounded 0 + have h1 := bounded 1 + have h2 := bounded 2 + have h3 := bounded 3 + have h4 := bounded 4 + have h5 := bounded 5 + have c1 : (256 : G).n = 256 := rfl + have c2 : (65536 : G).n = 65536 := rfl + have c3 : (16777216 : G).n = 16777216 := rfl + have c4 : (4294967296 : G).n = 4294967296 := rfl + have c5 : (1099511627776 : G).n = 1099511627776 := rfl + simp only [packRank, G.n_add, G.n_mul, c1, c2, c3, c4, c5] + have modulus : gSize.toNat = 18446744069414584321 := by decide + rw [modulus] + simp only [Nat.add_mod_mod, Nat.mod_add_mod] + apply Nat.lt_of_le_of_lt (Nat.mod_le _ _) + unfold callRankBound + omega + +/-- Exact active-call polynomial, before selector gating. -/ +def callOrderConstraint (parent child gap : G) : G := + child - parent - 1 - gap + +/-- The optimized emitter derives the child rank from its six gap bytes. +The order relation is then an identity rather than an additional equation. -/ +theorem callOrderConstraint_derived (parent gap : G) : + callOrderConstraint parent (parent + 1 + gap) gap = 0 := by + apply (G.sub_eq_zero_iff _ _).2 + apply Subtype.ext + apply UInt64.toNat_inj.mp + change (G.ofNat ((G.ofNat ((parent + 1 + gap).n + gSize.toNat - parent.n)).n + + gSize.toNat - 1)).n = gap.n + simp only [G.n_ofNat, G.n_add] + have one : (1 : G).n = 1 := rfl + rw [one] + have hp : parent.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp parent.property + have hg : gap.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp gap.property + have modulus : gSize.toNat = 18446744069414584321 := by decide + simp only [modulus] at hp hg ⊢ + omega + +theorem call_order_strict {parent child gap : G} + (hp : parent.n < callRankBound) (hc : child.n < callRankBound) + (hg : gap.n < callRankBound) + (satisfied : callOrderConstraint parent child gap = 0) : + parent.n < child.n := by + have h1 : child - parent - 1 = gap := + (G.sub_eq_zero_iff _ _).mp satisfied + have h := congrArg G.n h1 + change (G.ofNat ((G.ofNat (child.n + gSize.toNat - parent.n)).n + + gSize.toNat - 1)).n = gap.n at h + simp only [G.n_ofNat] at h + have modulus : gSize.toNat = 18446744069414584321 := by decide + rw [modulus] at h + unfold callRankBound at hp hc hg + omega + +theorem call_order_irrefl (rank gap : G) (hr : rank.n < callRankBound) + (hg : gap.n < callRankBound) : callOrderConstraint rank rank gap ≠ 0 := by + intro h + exact Nat.lt_irrefl _ (call_order_strict hr hr hg h) + +theorem active_call_order_strict {selector parent child gap : G} + (active : selector = 1) + (hp : parent.n < callRankBound) (hc : child.n < callRankBound) + (hg : gap.n < callRankBound) + (satisfied : selector * callOrderConstraint parent child gap = 0) : + parent.n < child.n := by + rw [active, G.mul_comm, G.mul_one] at satisfied + exact call_order_strict hp hc hg satisfied + +/-- Range-checked bytes suffice for the rank bounds in an active call. -/ +theorem packed_call_order_strict (parent child gap : Fin 6 → G) + (hp : ∀ i, (parent i).n < 256) (hc : ∀ i, (child i).n < 256) + (hg : ∀ i, (gap i).n < 256) + (satisfied : callOrderConstraint (packRank parent) (packRank child) (packRank gap) = 0) : + (packRank parent).n < (packRank child).n := + call_order_strict (packRank_lt parent hp) (packRank_lt child hc) + (packRank_lt gap hg) satisfied + +/-- Any call relation satisfying the bounded-rank constraints is well founded. +The relation is oriented `calls child parent`, as required by recursion. -/ +theorem call_relation_wellFounded {α : Sort u} (rank : α → G) + (bounded : ∀ node, (rank node).n < callRankBound) (calls : α → α → Prop) + (ordered : ∀ child parent, calls child parent → + ∃ gap : G, gap.n < callRankBound ∧ + callOrderConstraint (rank parent) (rank child) gap = 0) : + WellFounded calls := by + apply Subrelation.wf (r := fun child parent => + callRankBound - (rank child).n < callRankBound - (rank parent).n) + (fun {child parent} h => ?_) + (InvImage.wf (fun node => callRankBound - (rank node).n) Nat.lt_wfRel.wf) + obtain ⟨gap, hg, hs⟩ := ordered child parent h + have strict := call_order_strict (bounded parent) (bounded child) hg hs + have limit := bounded child + omega + +end AIR +end Aiur diff --git a/Ix/Aiur/Proofs/Challenger.lean b/Ix/Aiur/Proofs/Challenger.lean new file mode 100644 index 000000000..35a05bbbc --- /dev/null +++ b/Ix/Aiur/Proofs/Challenger.lean @@ -0,0 +1,375 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Challenger +import Ix.Aiur.Proofs.KeyCodec + +namespace Aiur.NativeAIR.Challenger + +/-- Pending bytes are a suffix of the reversed digest still held in the +input buffer. Observations may leave any input and no pending output. -/ +def State.Valid (state : State) : Prop := + state.pending = [] ∨ ∃ consumed, state.input.length = 32 ∧ state.pending = state.input.reverse.drop consumed + +theorem initial_valid (seed : List UInt8) : (initial seed).Valid := Or.inl rfl + +theorem State.Valid.bound {state : State} (valid : state.Valid) : state.pending.length ≤ 32 := by + rcases valid with empty | ⟨consumed, length, pending⟩ + · simp only [empty, List.length_nil]; omega + · simp only [pending, List.length_drop, List.length_reverse, length]; omega + +theorem observeBytes_nil (state : State) : observeBytes state [] = state := rfl + +theorem observeBytes_append (state : State) (left right : List UInt8) : + observeBytes state (left ++ right) = observeBytes (observeBytes state left) right := by + cases left <;> cases right <;> simp [observeBytes, List.append_assoc] + +theorem observeBytes_value (state : State) (bytes : List UInt8) : + observeBytes state bytes = if bytes.isEmpty then state else ⟨state.input ++ bytes, []⟩ := rfl + +theorem observeBytes_fold (state : State) (bytes : List UInt8) : + observeBytes state bytes = bytes.foldl observeByte state := by + induction bytes generalizing state with + | nil => rfl + | cons byte bytes ih => + rw [List.foldl_cons, ← ih] + cases bytes <;> simp [observeBytes, observeByte, List.append_assoc] + +theorem observeBytes_valid {state : State} (valid : state.Valid) (bytes : List UInt8) : + (observeBytes state bytes).Valid := by + rw [observeBytes_value] + split + · exact valid + · exact Or.inl rfl + +theorem observeField_value (state : State) (value : G) : + observeField state value = ⟨state.input ++ ProofCodec.encodeField value, []⟩ := by + rw [observeField, observeBytes_value] + rfl + +theorem observeField_valid {state : State} (valid : state.Valid) (value : G) : + (observeField state value).Valid := observeBytes_valid valid _ + +theorem observeExtension_bytes (state : State) (value : ProofCodec.Extension) : + observeExtension state value = observeBytes state (ProofCodec.encodeExtension value) := by + rw [observeExtension, ProofCodec.encodeExtension, observeBytes_append] + rfl + +theorem observeExtension_valid {state : State} (valid : state.Valid) (value : ProofCodec.Extension) : + (observeExtension state value).Valid := observeField_valid (observeField_valid valid value.c0) value.c1 + +theorem observeExtensions_valid {state : State} (valid : state.Valid) (values : List ProofCodec.Extension) : + (values.foldl observeExtension state).Valid := by + induction values generalizing state with + | nil => exact valid + | cons value values ih => exact ih (observeExtension_valid valid value) + +theorem observeCap_empty (state : State) : observeCap state [] = state := rfl + +theorem observeCap_valid {state : State} (valid : state.Valid) (cap : KeyCodec.MerkleCap) : + (observeCap state cap).Valid := observeBytes_valid valid _ + +theorem sampleByte_buffered (hash : Hash32) (input : List UInt8) (byte : UInt8) (rest : List UInt8) : + sampleByte hash ⟨input, byte :: rest⟩ = (byte, ⟨input, rest⟩) := rfl + +theorem sampleByte_refill (hash : Hash32) (input : List UInt8) : + sampleByte hash ⟨input, []⟩ = + (hash input 31, ⟨List.ofFn (hash input), (List.ofFn (hash input)).reverse.drop 1⟩) := rfl + +theorem sampleByte_valid (hash : Hash32) {state : State} (valid : state.Valid) : + (sampleByte hash state).2.Valid := by + cases pending : state.pending with + | nil => + simp only [sampleByte, pending] + exact Or.inr ⟨1, List.length_ofFn, rfl⟩ + | cons byte rest => + rcases valid with empty | ⟨consumed, length, remaining⟩ + · rw [empty] at pending; cases pending + · change (sampleByte hash state).2.pending = [] ∨ _ + right + refine ⟨consumed + 1, ?_, ?_⟩ + · simpa only [sampleByte, pending] using length + · simp only [sampleByte, pending] + rw [← List.tail_drop, ← remaining, pending] + rfl + +theorem digest_reverse (digest : Fin 32 → UInt8) : + (List.ofFn digest).reverse = digest 31 :: (List.ofFn digest).reverse.drop 1 := by + conv => lhs; rw [List.ofFn_succ_last] + simp only [List.reverse_append, List.reverse_cons, List.reverse_nil, List.nil_append, + List.singleton_append] + rw [List.ofFn_succ_last] + simp + +theorem sampleByte_pending_bound (hash : Hash32) (state : State) (bounded : state.pending.length ≤ 32) : + (sampleByte hash state).2.pending.length ≤ 32 := by + cases pending : state.pending with + | nil => simp [sampleByte, pending] + | cons byte rest => simp only [sampleByte, pending]; simp_all; omega + +theorem sampleBytes_length (hash : Hash32) (count : Nat) (state : State) : + (sampleBytes hash count state).1.length = count := by + induction count generalizing state with + | zero => rfl + | succ count ih => simp only [sampleBytes, List.length_cons, ih] + +theorem sampleBytes_pending_bound (hash : Hash32) (count : Nat) (state : State) + (bounded : state.pending.length ≤ 32) : (sampleBytes hash count state).2.pending.length ≤ 32 := by + induction count generalizing state with + | zero => exact bounded + | succ count ih => exact ih _ (sampleByte_pending_bound hash state bounded) + +theorem sampleBytes_valid (hash : Hash32) (count : Nat) {state : State} (valid : state.Valid) : + (sampleBytes hash count state).2.Valid := by + induction count generalizing state with + | zero => exact valid + | succ count ih => exact ih (sampleByte_valid hash valid) + +theorem sampleBytes_buffered (hash : Hash32) (input bytes rest : List UInt8) : + sampleBytes hash bytes.length ⟨input, bytes ++ rest⟩ = (bytes, ⟨input, rest⟩) := by + induction bytes with + | nil => rfl + | cons byte bytes ih => simp only [List.length_cons, List.cons_append, sampleBytes, sampleByte, ih] + +theorem sampleBytes_refill (hash : Hash32) (input : List UInt8) : + sampleBytes hash 32 ⟨input, []⟩ = + ((List.ofFn (hash input)).reverse, ⟨List.ofFn (hash input), []⟩) := by + have tail := sampleBytes_buffered hash (List.ofFn (hash input)) + ((List.ofFn (hash input)).reverse.drop 1) [] + simp only [List.length_drop, List.length_reverse, List.length_ofFn, List.append_nil] at tail + rw [sampleBytes] + simp only [sampleByte] + rw [tail, ← digest_reverse] + +theorem littleEndian_bound (bytes : List UInt8) : littleEndian bytes < 256^bytes.length := by + induction bytes with + | nil => decide + | cons byte bytes ih => + have bounded := byte.toNat_lt + simp only [littleEndian, List.foldr_cons, List.length_cons, Nat.pow_succ] at * + omega + +theorem littleEndian_encode (count value : Nat) (bounded : value < 256^count) : + littleEndian (KeyCodec.encodeNat count value) = value := by + induction count generalizing value with + | zero => + have zero : value = 0 := by simpa using bounded + subst value + rfl + | succ count ih => + have small : value / 256 < 256^count := by + apply (Nat.div_lt_iff_lt_mul (by decide : 0 < 256)).mpr + simpa only [Nat.pow_succ] using bounded + simp only [KeyCodec.encodeNat, littleEndian, List.foldr_cons] + change value.toUInt8.toNat + 256 * littleEndian (KeyCodec.encodeNat count (value / 256)) = value + rw [ih _ small] + exact Nat.mod_add_div _ _ + +theorem littleEndian_reads (bytes : List UInt8) : + KeyCodec.Reads (KeyCodec.readNat bytes.length) bytes (littleEndian bytes) := by + induction bytes with + | nil => exact KeyCodec.Reads.pure 0 + | cons byte bytes ih => + exact KeyCodec.Reads.byte (ih.result (fun value => byte.toNat + 256 * value)) + +theorem sampleWord_bound (hash : Hash32) (state : State) : (sampleWord hash state).1 < 2^64 := by + have bound := littleEndian_bound (sampleBytes hash 8 state).1 + rw [sampleBytes_length] at bound + exact bound + +theorem sampleWord_full_mask (hash : Hash32) (state : State) : + (sampleWord hash state).1 &&& (2^64 - 1) = (sampleWord hash state).1 := + Nat.and_two_pow_sub_one_of_lt_two_pow (sampleWord_bound hash state) + +theorem sampleWord_reads (hash : Hash32) (state : State) : + KeyCodec.Reads (KeyCodec.readNat 8) (sampleBytes hash 8 state).1 (sampleWord hash state).1 := by + have read := littleEndian_reads (sampleBytes hash 8 state).1 + rw [sampleBytes_length] at read + exact read + +/-- A finite native execution: each rejected word advances to its returned +state, and the first canonical word is the returned field representative. -/ +inductive FieldSample (hash : Hash32) : State → Nat → G → State → Prop where + | accept {state : State} (canonical : (sampleWord hash state).1 < gSize.toNat) : + FieldSample hash state 1 (G.ofNat (sampleWord hash state).1) (sampleWord hash state).2 + | reject {state final : State} {count : Nat} {value : G} + (noncanonical : ¬(sampleWord hash state).1 < gSize.toNat) + (rest : FieldSample hash (sampleWord hash state).2 count value final) : + FieldSample hash state (count + 1) value final + +theorem FieldSample.positive {hash : Hash32} {state final : State} {count : Nat} {value : G} + (trace : FieldSample hash state count value final) : 0 < count := by + cases trace <;> omega + +theorem sampleField_success {hash : Hash32} {fuel : Nat} {state final : State} {value : G} + (accepted : sampleField hash fuel state = some (value, final)) : + ∃ count, count ≤ fuel ∧ FieldSample hash state count value final := by + induction fuel generalizing state with + | zero => cases accepted + | succ fuel ih => + change (if (sampleWord hash state).1 < gSize.toNat then + some (G.ofNat (sampleWord hash state).1, (sampleWord hash state).2) + else sampleField hash fuel (sampleWord hash state).2) = some (value, final) at accepted + split at accepted + · obtain ⟨sameValue, sameState⟩ := Prod.mk.inj (Option.some.inj accepted) + rw [← sameValue, ← sameState] + exact ⟨1, by omega, .accept (by assumption)⟩ + · obtain ⟨count, bound, trace⟩ := ih accepted + exact ⟨count + 1, by omega, .reject (by assumption) trace⟩ + +theorem FieldSample.complete {hash : Hash32} {state final : State} {count : Nat} {value : G} + (trace : FieldSample hash state count value final) (fuel : Nat) (bound : count ≤ fuel) : + sampleField hash fuel state = some (value, final) := by + induction trace generalizing fuel with + | accept canonical => + cases fuel with + | zero => omega + | succ fuel => simp only [sampleField, canonical, ↓reduceIte] + | reject noncanonical trace ih => + cases fuel with + | zero => omega + | succ fuel => + simp only [sampleField, noncanonical, ↓reduceIte] + exact ih fuel (by omega) + +theorem sampleField_iff (hash : Hash32) (fuel : Nat) (state final : State) (value : G) : + sampleField hash fuel state = some (value, final) ↔ + ∃ count, count ≤ fuel ∧ FieldSample hash state count value final := + ⟨sampleField_success, fun ⟨_, bound, trace⟩ => trace.complete fuel bound⟩ + +theorem sampleField_mono {hash : Hash32} {fuel more : Nat} {state final : State} {value : G} + (accepted : sampleField hash fuel state = some (value, final)) (bound : fuel ≤ more) : + sampleField hash more state = some (value, final) := by + obtain ⟨count, small, trace⟩ := sampleField_success accepted + exact trace.complete more (Nat.le_trans small bound) + +theorem sampleField_unique {hash : Hash32} {fuel other : Nat} {state left right : State} {a b : G} + (first : sampleField hash fuel state = some (a, left)) + (second : sampleField hash other state = some (b, right)) : a = b ∧ left = right := by + have one := sampleField_mono first (Nat.le_max_left fuel other) + have two := sampleField_mono second (Nat.le_max_right fuel other) + exact Prod.mk.inj (Option.some.inj (one.symm.trans two)) + +theorem FieldSample.valid {hash : Hash32} {state final : State} {count : Nat} {value : G} + (trace : FieldSample hash state count value final) (valid : state.Valid) : final.Valid := by + induction trace with + | accept _ => exact sampleBytes_valid hash 8 valid + | @reject before _ _ _ _ _ ih => + apply ih + change (sampleBytes hash 8 before).2.Valid + exact sampleBytes_valid hash 8 valid + +theorem sampleField_valid {hash : Hash32} {fuel : Nat} {state final : State} {value : G} + (accepted : sampleField hash fuel state = some (value, final)) (valid : state.Valid) : final.Valid := by + obtain ⟨_, _, trace⟩ := sampleField_success accepted + exact trace.valid valid + +theorem sampleField_canonical {hash : Hash32} {fuel : Nat} {state final : State} {value : G} + (accepted : sampleField hash fuel state = some (value, final)) : + ∃ before, sampleWord hash before = (value.n, final) ∧ value.n < gSize.toNat := by + obtain ⟨_, _, trace⟩ := sampleField_success accepted + clear accepted + rename_i count bound + clear bound + induction trace with + | @accept before canonical => + refine ⟨before, ?_, ?_⟩ + · simp only [G.n_ofNat, Nat.mod_eq_of_lt canonical] + · simpa only [G.n_ofNat, Nat.mod_eq_of_lt canonical] using canonical + | reject _ _ ih => exact ih + +theorem sampleExtension_success {hash : Hash32} {fuel : Nat} {state final : State} + {value : ProofCodec.Extension} (accepted : sampleExtension hash fuel state = some (value, final)) : + ∃ next, sampleField hash fuel state = some (value.c0, next) ∧ + sampleField hash fuel next = some (value.c1, final) := by + simp only [sampleExtension, bind, pure, Option.bind_eq_some_iff, Option.some.injEq, + Prod.exists, Prod.mk.injEq] at accepted + obtain ⟨c0, next, first, c1, final', second, ⟨rfl, rfl⟩, rfl⟩ := accepted + exact ⟨next, first, second⟩ + +theorem sampleExtension_mono {hash : Hash32} {fuel more : Nat} {state final : State} + {value : ProofCodec.Extension} (accepted : sampleExtension hash fuel state = some (value, final)) + (bound : fuel ≤ more) : sampleExtension hash more state = some (value, final) := by + obtain ⟨next, first, second⟩ := sampleExtension_success accepted + simp only [sampleExtension, sampleField_mono first bound, sampleField_mono second bound, + bind, pure, Option.bind_some] + +theorem sampleExtension_valid {hash : Hash32} {fuel : Nat} {state final : State} + {value : ProofCodec.Extension} (accepted : sampleExtension hash fuel state = some (value, final)) + (valid : state.Valid) : final.Valid := by + obtain ⟨next, first, second⟩ := sampleExtension_success accepted + exact sampleField_valid second (sampleField_valid first valid) + +theorem sampleBits_success {hash : Hash32} {bits value : Nat} {state final : State} + (accepted : sampleBits hash bits state = some (value, final)) : + bits < 64 ∧ 2^bits < gSize.toNat ∧ value = (sampleWord hash state).1 % 2^bits ∧ + final = (sampleWord hash state).2 ∧ value < 2^bits := by + change (if bits < 64 ∧ 2^bits < gSize.toNat then + some ((sampleWord hash state).1 % 2^bits, (sampleWord hash state).2) + else none) = some (value, final) at accepted + split at accepted + · rename_i valid + obtain ⟨sameValue, sameState⟩ := Prod.mk.inj (Option.some.inj accepted) + refine ⟨valid.1, valid.2, sameValue.symm, sameState.symm, ?_⟩ + rw [← sameValue] + exact Nat.mod_lt _ (Nat.two_pow_pos _) + · cases accepted + +theorem sampleBits_zero (hash : Hash32) (state : State) : + sampleBits hash 0 state = some (0, (sampleWord hash state).2) := by + have bound : 1 < gSize.toNat := by decide + change (if 0 < 64 ∧ 2^0 < gSize.toNat then + some ((sampleWord hash state).1 % 2^0, (sampleWord hash state).2) else none) = _ + simp only [Nat.pow_zero, bound, Nat.mod_one, Nat.zero_lt_succ, and_self, ↓reduceIte] + +theorem sampleBits_mask {hash : Hash32} {bits value : Nat} {state final : State} + (accepted : sampleBits hash bits state = some (value, final)) : + value = (sampleWord hash state).1 &&& (2^bits - 1) := by + rw [Nat.and_two_pow_sub_one_eq_mod] + exact (sampleBits_success accepted).2.2.1 + +theorem sampleBits_valid {hash : Hash32} {bits value : Nat} {state final : State} + (accepted : sampleBits hash bits state = some (value, final)) (valid : state.Valid) : final.Valid := by + rw [(sampleBits_success accepted).2.2.2.1] + exact sampleBytes_valid hash 8 valid + +theorem checkWitness_zero (hash : Hash32) (witness : G) (state : State) : + checkWitness hash 0 witness state = some (true, state) := rfl + +theorem checkWitness_positive (hash : Hash32) {bits : Nat} (positive : bits ≠ 0) + (witness : G) (state : State) : checkWitness hash bits witness state = do + let (value, next) ← sampleBits hash bits (observeField state witness) + return (value == 0, next) := by + simp only [checkWitness, positive, ↓reduceIte] + +theorem checkWitness_true_iff (hash : Hash32) (bits : Nat) (witness : G) (state final : State) : + checkWitness hash bits witness state = some (true, final) ↔ + (bits = 0 ∧ final = state) ∨ + (bits ≠ 0 ∧ sampleBits hash bits (observeField state witness) = some (0, final)) := by + by_cases zero : bits = 0 + · subst bits + simp only [checkWitness_zero, Option.some.injEq, Prod.mk.injEq, true_and, + ne_eq, not_true_eq_false, false_and, or_false] + exact eq_comm + · rw [checkWitness_positive hash zero witness state] + simp only [bind, pure, Option.bind_eq_some_iff, Prod.exists, Option.some.injEq, Prod.mk.injEq, + beq_iff_eq, ne_eq, zero, false_and, not_false_eq_true, true_and, false_or] + constructor + · rintro ⟨value, next, read, rfl, rfl⟩; exact read + · intro read; exact ⟨0, final, read, rfl, rfl⟩ + +theorem checkWitness_valid {hash : Hash32} {bits : Nat} {witness : G} {state final : State} + {accepted : Bool} (read : checkWitness hash bits witness state = some (accepted, final)) + (valid : state.Valid) : final.Valid := by + by_cases zero : bits = 0 + · subst bits + obtain ⟨_, same⟩ := Prod.mk.inj (Option.some.inj read) + exact same ▸ valid + · rw [checkWitness_positive hash zero witness state] at read + simp only [bind, pure, Option.bind_eq_some_iff, Prod.exists, Option.some.injEq, Prod.mk.injEq] at read + obtain ⟨value, next, sampled, _, rfl⟩ := read + exact sampleBits_valid sampled (observeField_valid valid witness) + +end Aiur.NativeAIR.Challenger diff --git a/Ix/Aiur/Proofs/CheckedCircuit.lean b/Ix/Aiur/Proofs/CheckedCircuit.lean new file mode 100644 index 000000000..52014c675 --- /dev/null +++ b/Ix/Aiur/Proofs/CheckedCircuit.lean @@ -0,0 +1,89 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockCompletion +import Ix.Aiur.Proofs.CircuitCompletion + +/-! Checked backend construction supplies circuit emission and a physical graph. -/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter BlockEmitter Bytecode + +theorem emitMember_defined (rank : Expr) (column lookup selectorBase : Nat) + (program : Toplevel) (index : Nat) {function : Function} + (present : program.functions[index]? = some function) (checked : function.emissionChecks = true) : + ∃ member, emitMember rank column lookup selectorBase program index = some member := by + rw [Function.emissionChecks, Bool.and_eq_true] at checked + have bodyChecks : function.body.emissionChecks (advice 0 function.layout.inputSize).size + (selectorExprs selectorBase function.layout.selectors).size none = true := by + simpa only [advice, selectorExprs, Array.size_ofFn] using checked.2 + obtain ⟨entry, selected⟩ := blockSelector_defined (selectorExprs selectorBase function.layout.selectors) function.body bodyChecks + obtain ⟨body, emitted, _⟩ := emitBlock_defined (selectorExprs selectorBase function.layout.selectors) + ⟨index, function.layout.inputSize, rank⟩ entry (advice 0 function.layout.inputSize) column lookup function.body + (advice_degreeValid _ _) (by simp only [advice, Array.size_ofFn, Nat.le_refl]) bodyChecks + refine ⟨⟨index, function, selectorBase, entry, body⟩, ?_⟩ + simp only [emitMember, present, selected, emitted, bind, Option.bind_some, pure] + +theorem emitMembers_defined (rank : Expr) (column lookup selectorBase : Nat) (program : Toplevel) (indices : List Nat) + (checked : ∀ index ∈ indices, ∃ function, program.functions[index]? = some function ∧ function.emissionChecks = true) : + ∃ members, emitMembers rank column lookup selectorBase program indices = some members := by + induction indices generalizing selectorBase with + | nil => exact ⟨[], rfl⟩ + | cons index indices ih => + obtain ⟨function, present, valid⟩ := checked index List.mem_cons_self + obtain ⟨member, memberEmitted⟩ := emitMember_defined rank column lookup selectorBase program index present valid + obtain ⟨members, membersEmitted⟩ := ih (selectorBase + member.function.layout.selectors) + (fun index present => checked index (List.mem_cons_of_mem _ present)) + exact ⟨member :: members, by simp only [emitMembers, memberEmitted, membersEmitted, bind, Option.bind_some, pure]⟩ + +theorem emitCircuit_defined (program : Toplevel) (circuit : Circuit) + (checked : program.validateEmission = true) (members : MembersConstrained program.functions circuit.members) : + ∃ emission, emitCircuit program circuit = some emission := by + have valid : ∀ index ∈ circuit.members.toList, + ∃ function, program.functions[index]? = some function ∧ function.emissionChecks = true := by + intro index member + obtain ⟨function, present, constrained⟩ := members index (by simpa using member) + exact ⟨function, present, Toplevel.validateEmission_function checked (Array.mem_of_getElem? present) constrained⟩ + obtain ⟨emissions, emitted⟩ := emitMembers_defined (packSix (rankBytes circuit.layout)) + (circuit.layout.inputSize + circuit.layout.selectors + 1 + 6) 4 circuit.layout.inputSize + program circuit.members.toList valid + refine ⟨circuitEmission circuit emissions, ?_⟩ + simp only [emitCircuit, emitted, bind, Option.bind_some, pure] + +end Aiur.NativeAIR.CircuitEmitter + +namespace Aiur.BoundVerifier +open NativeAIR NativeAIR.CircuitEmitter + +theorem Backend.circuit_emits {selection : Selection} (backend : Backend selection) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) : + ∃ emission, emitCircuit backend.compiled.bytecode circuit = some emission := + emitCircuit_defined backend.compiled.bytecode circuit backend.emissionChecks (backend.circuits_constrained circuit member) + +theorem Backend.circuit_compiles {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) : + ∃ compiled, compileCircuit (circuitWidths circuit) backend.compiled.bytecode circuit = some compiled := by + obtain ⟨emission, emitted⟩ := backend.circuit_emits member + obtain ⟨compiled, built, _⟩ := backend.emitCircuit_compiles generic member emitted + exact ⟨compiled, built⟩ + +theorem Backend.circuit_graph_reflects {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) + {values : Values G} (fits : values.Fits (circuitWidths circuit)) : + ∃ compiled result buffer, + compileCircuit (circuitWidths circuit) backend.compiled.bytecode circuit = some compiled ∧ + circuit.emitRow (fun index => (values.columns .main .current)[index]?.getD 0) backend.compiled.bytecode = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Compiler.Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := by + obtain ⟨emission, emitted⟩ := backend.circuit_emits member + obtain ⟨compiled, result, buffer, built, _, resultEmitted, swept, satisfied, lookups⟩ := + backend.emittedCircuit_reflects generic member fits emitted + exact ⟨compiled, result, buffer, built, resultEmitted, swept, satisfied, lookups⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/CircuitAllocation.lean b/Ix/Aiur/Proofs/CircuitAllocation.lean new file mode 100644 index 000000000..95bcf5bc9 --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitAllocation.lean @@ -0,0 +1,216 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitLayout +import Ix.Aiur.Proofs.BlockAllocation +import Ix.Aiur.Proofs.CompiledCircuitRows + +/-! Compiled layouts and checked row counts bound every symbolic circuit +read by the actual main-trace width, including grouped selector regions. -/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter BlockEmitter Compiler Aiur.Bytecode + +theorem emitMember_layout {rank : Expr} {column lookup selectorBase base : Nat} + {program : Toplevel} {functionIndex : Nat} {member : Member} + (functions : FunctionsComputedLayout program.functions) (cursor : column = base + 7) + (emitted : emitMember rank column lookup selectorBase program functionIndex = some member) : + member.functionIndex = functionIndex ∧ program.functions[functionIndex]? = some member.function ∧ + member.selectorBase = selectorBase ∧ member.body.column = base + member.function.layout.auxiliaries := by + simp only [emitMember, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i function functionRead + dsimp only at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i body bodyEmitted + cases emitted + have layout := BlockEmitter.emitBlock_layout function.body (.new function.layout.inputSize) base + (advice_degreeValid _ _) rfl (advice_degrees _ _) cursor bodyEmitted + have valid := functions function (Array.mem_of_getElem? functionRead) + exact ⟨rfl, functionRead, rfl, layout.2.trans (congrArg (base + ·) valid.auxiliaries.symm)⟩ + +theorem emitMembers_layout {rank : Expr} (column lookup selectorBase base : Nat) + (program : Toplevel) (indices : List Nat) {members : List Member} + (functions : FunctionsComputedLayout program.functions) (cursor : column = base + 7) + (emitted : emitMembers rank column lookup selectorBase program indices = some members) : + members.map Member.functionIndex = indices ∧ + (∀ member ∈ members, program.functions[member.functionIndex]? = some member.function ∧ + member.body.column = base + member.function.layout.auxiliaries ∧ + member.selectorBase + member.function.layout.selectors ≤ + selectorBase + (members.map (fun part => part.function.layout.selectors)).sum) := by + induction indices generalizing selectorBase members with + | nil => + cases emitted + exact ⟨rfl, by simp⟩ + | cons index indices ih => + simp only [emitMembers, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i member memberEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + obtain ⟨indexEq, present, selectorEq, columnEq⟩ := emitMember_layout functions cursor memberEmitted + obtain ⟨indicesEq, tail⟩ := ih _ restEmitted + refine ⟨by simp only [List.map_cons, indexEq, indicesEq], ?_⟩ + intro chosen memberOf + rcases List.mem_cons.mp memberOf with equal | later + · subst chosen + refine ⟨by rw [indexEq]; exact present, columnEq, ?_⟩ + simp only [List.map_cons, List.sum_cons, selectorEq] + omega + · obtain ⟨present, columnEq, bounded⟩ := tail chosen later + refine ⟨present, columnEq, ?_⟩ + simpa only [List.map_cons, List.sum_cons, Nat.add_assoc] using bounded + +private theorem member_functions_read (program : Toplevel) (members : List Member) + (present : ∀ member ∈ members, program.functions[member.functionIndex]? = some member.function) : + (members.map Member.functionIndex).mapM (fun index => program.functions[index]?) = + some (members.map Member.function) := by + induction members with + | nil => rfl + | cons member members ih => + simp only [List.map_cons, List.mapM_cons, present member List.mem_cons_self, + ih (fun member present' => present member (List.mem_cons_of_mem _ present'))] + rfl + +theorem emitMembers_selectors {rank : Expr} (column lookup selectorBase base : Nat) + (program : Toplevel) (circuit : Circuit) {members : List Member} + (functions : FunctionsComputedLayout program.functions) (cursor : column = base + 7) + (validated : circuit.validateRowCounts program = true) + (emitted : emitMembers rank column lookup selectorBase program circuit.members.toList = some members) : + (members.map (fun member => member.function.layout.selectors)).sum ≤ circuit.layout.selectors := by + obtain ⟨indices, layout⟩ := emitMembers_layout column lookup selectorBase base program circuit.members.toList + functions cursor emitted + have present := member_functions_read program members (fun member memberOf => (layout member memberOf).1) + rw [indices] at present + rw [Circuit.validateRowCounts, present] at validated + simp only [Bool.and_eq_true, decide_eq_true_eq] at validated + have leaves : members.map (fun member => member.function.layout.selectors) = + (members.map Member.function).map (fun function => function.body.controlCounts.leaves) := by + rw [List.map_map] + apply List.map_congr_left + intro member memberOf + exact (functions member.function (Array.mem_of_getElem? (layout member memberOf).1)).selectors + rw [leaves] + exact validated.2.2 + +private theorem fold_max_le {α : Type} (measure : α → Nat) (items : List α) (initial bound : Nat) + (before : initial ≤ bound) (members : ∀ item ∈ items, measure item ≤ bound) : + items.foldl (fun acc item => max acc (measure item)) initial ≤ bound := by + induction items generalizing initial with + | nil => exact before + | cons item items ih => + exact ih (max initial (measure item)) (Nat.max_le.mpr ⟨before, members item List.mem_cons_self⟩) + (fun item member => members item (List.mem_cons_of_mem _ member)) + +theorem emitCircuit_readBound (program : Toplevel) (circuit : Circuit) {emission : Emission} + (functions : FunctionsComputedLayout program.functions) + (columns : MembersColumnBound program.functions circuit.members circuit.layout) + (validated : circuit.validateRowCounts program = true) + (emitted : emitCircuit program circuit = some emission) : + emission.readBound ≤ circuit.layout.width := by + simp only [emitCircuit, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i members membersEmitted + cases emitted + let base := circuit.layout.inputSize + circuit.layout.selectors + have cursor : circuit.layout.inputSize + circuit.layout.selectors + 1 + 6 = base + 7 := by omega + obtain ⟨indices, layout⟩ := emitMembers_layout _ _ _ base program circuit.members.toList functions cursor membersEmitted + have selectors := emitMembers_selectors _ _ _ base program circuit functions cursor validated membersEmitted + apply fold_max_le Member.readBound + · change circuit.layout.inputSize + circuit.layout.selectors + 1 + 6 ≤ + circuit.layout.inputSize + circuit.layout.selectors + circuit.layout.auxiliaries + have reserved := columns.1 + omega + · intro member memberOf + obtain ⟨present, bodyColumn, selectorBound⟩ := layout member memberOf + have memberIndex : member.functionIndex ∈ circuit.members := by + apply Array.mem_toList_iff.mp + rw [← indices] + exact List.mem_map.mpr ⟨member, memberOf, rfl⟩ + have bound := columns.2 member.functionIndex memberIndex + rw [Array.getElem!_eq_getD, Array.getD_eq_getD_getElem?, present] at bound + change member.function.layout.inputSize ≤ circuit.layout.inputSize ∧ + member.function.layout.auxiliaries ≤ circuit.layout.auxiliaries at bound + change max member.function.layout.inputSize + (max (member.selectorBase + member.function.layout.selectors) member.body.column) ≤ + circuit.layout.inputSize + circuit.layout.selectors + circuit.layout.auxiliaries + dsimp only [base] at bodyColumn + omega + +theorem compileCircuit_readBound {widths : GraphWidths} (program : Toplevel) (circuit : Circuit) + {compiled : Compiled} (functions : FunctionsComputedLayout program.functions) + (columns : MembersColumnBound program.functions circuit.members circuit.layout) + (validated : circuit.validateRowCounts program = true) + (built : compileCircuit widths program circuit = some compiled) : + compiled.emission.readBound ≤ circuit.layout.width := by + simp only [compileCircuit, bind, Option.bind] at built + split at built + · cases built + rename_i emission emitted + dsimp only at built + split at built + · cases built + cases built + exact emitCircuit_readBound program circuit functions columns validated emitted + +theorem compileCircuit_physical_reflects {values : Values G} {widths : GraphWidths} + (fits : values.Fits widths) (program : Toplevel) (circuit : Circuit) {compiled : Compiled} + (functions : FunctionsComputedLayout program.functions) + (columns : MembersColumnBound program.functions circuit.members circuit.layout) + (validated : circuit.validateRowCounts program = true) (physical : widths.main = circuit.layout.width) + (built : compileCircuit widths program circuit = some compiled) : + ∃ result buffer, + circuit.emitRow (fun index => (values.columns .main .current)[index]?.getD 0) program = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := by + have bound := compileCircuit_readBound program circuit functions columns validated built + apply compileCircuit_reflects _ fits program circuit built + intro index indexBound + have size : index < (values.columns .main .current).size := by + rw [fits.1, GraphWidths.width, physical] + exact Nat.lt_of_lt_of_le indexBound bound + simp only [Array.getElem?_eq_getElem size, Option.getD_some] + +end Aiur.NativeAIR.CircuitEmitter + +namespace Aiur.BoundVerifier +open NativeAIR NativeAIR.CircuitEmitter + +theorem Backend.circuit_readBound {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) {emission : Emission} + (emitted : emitCircuit backend.compiled.bytecode circuit = some emission) : + emission.readBound ≤ circuit.layout.width := + emitCircuit_readBound backend.compiled.bytecode circuit (backend.functions_computedLayout generic) + (backend.circuits_columnBound generic circuit member) (backend.circuit_row_counts member) emitted + +theorem Backend.compileCircuit_reflects {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + {values : Values G} {widths : GraphWidths} (fits : values.Fits widths) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) {compiled : Compiled} + (physical : widths.main = circuit.layout.width) + (built : compileCircuit widths backend.compiled.bytecode circuit = some compiled) : + ∃ result buffer, + circuit.emitRow (fun index => (values.columns .main .current)[index]?.getD 0) backend.compiled.bytecode = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Compiler.Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := + compileCircuit_physical_reflects fits backend.compiled.bytecode circuit (backend.functions_computedLayout generic) + (backend.circuits_columnBound generic circuit member) (backend.circuit_row_counts member) physical built + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/CircuitCompletion.lean b/Ix/Aiur/Proofs/CircuitCompletion.lean new file mode 100644 index 000000000..dd883c03e --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitCompletion.lean @@ -0,0 +1,114 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitAllocation +import Ix.Aiur.Proofs.GraphCompletion +import Ix.Aiur.Proofs.InactiveRows + +/-! A successfully emitted compiled circuit always has a base graph at its +physical width. Its zero row satisfies the equations, excluding rejection of +nonzero constant constraints without assuming an active execution. -/ + +namespace Aiur.NativeAIR.CircuitEmitter +open Compiler Aiur.Bytecode + +def circuitWidths (circuit : Circuit) : GraphWidths := ⟨0, circuit.layout.width, 0, 0⟩ + +def zeroValues (width : Nat) : Values G where + columns := fun source _ => match source with + | .main => Array.replicate width 0 + | _ => #[] + publics := #[] + isFirstRow := 0 + isLastRow := 0 + isTransition := 0 + +theorem zeroValues_fits (circuit : Circuit) : (zeroValues circuit.layout.width).Fits (circuitWidths circuit) := by + refine ⟨?_, rfl⟩ + intro source offset + cases source <;> simp only [zeroValues, circuitWidths, GraphWidths.width, Array.size_replicate, Array.size_empty] + +theorem zeroValues_read (width index : Nat) (bound : index < width) : + ((zeroValues width).columns .main .current)[index]? = some 0 := by + simp only [zeroValues, Array.getElem?_replicate, bound, if_true] + +theorem emitCircuit_zero_eval (program : Toplevel) (circuit : Circuit) {emission : Emission} + (functions : FunctionsComputedLayout program.functions) + (columns : MembersColumnBound program.functions circuit.members circuit.layout) + (validated : circuit.validateRowCounts program = true) + (emitted : emitCircuit program circuit = some emission) : + ∃ result, emission.eval (zeroValues circuit.layout.width) = some result ∧ + (∀ equation ∈ result.equations, equation = 0) := by + have bound := emitCircuit_readBound program circuit functions columns validated emitted + obtain ⟨result, resultEmitted, evaluated⟩ := emitCircuit_reflects (fun _ => 0) program circuit emitted + (fun index indexBound => zeroValues_read _ _ (Nat.lt_of_lt_of_le indexBound bound)) + exact ⟨result, evaluated, circuit.emitRow_zero program resultEmitted⟩ + +theorem emitCircuit_compiles (program : Toplevel) (circuit : Circuit) {emission : Emission} + (functions : FunctionsComputedLayout program.functions) + (columns : MembersColumnBound program.functions circuit.members circuit.layout) + (validated : circuit.validateRowCounts program = true) + (emitted : emitCircuit program circuit = some emission) : + ∃ compiled, compileCircuit (circuitWidths circuit) program circuit = some compiled ∧ + compiled.emission = emission := by + obtain ⟨result, evaluated, satisfied⟩ := emitCircuit_zero_eval program circuit functions columns validated emitted + have equations := (Emission.eval_components evaluated).2.2.2.2.2.2.2.2.2.1 + have zeros := (equations_vanish equations).mpr satisfied + obtain ⟨base, baseCompiled⟩ := compileBase_defined goldilocksGraphLaws + (show Function.Injective goldilocksOps.konst from fun _ _ equal => equal) + (zeroValues_fits circuit) rfl emission.lookups emission.equations (Emission.lookups_eval evaluated) zeros + refine ⟨⟨emission, base⟩, ?_, rfl⟩ + simp only [compileCircuit, emitted, baseCompiled, bind, Option.bind_some, pure] + +theorem compileCircuit_defined_iff (program : Toplevel) (circuit : Circuit) + (functions : FunctionsComputedLayout program.functions) + (columns : MembersColumnBound program.functions circuit.members circuit.layout) + (validated : circuit.validateRowCounts program = true) : + (compileCircuit (circuitWidths circuit) program circuit).isSome = true ↔ + (emitCircuit program circuit).isSome = true := by + constructor + · intro compiled + cases emitted : emitCircuit program circuit with + | none => simp only [compileCircuit, emitted, bind, Option.bind_none, Option.isSome_none, Bool.false_eq_true] at compiled + | some emission => rfl + · intro emitted + obtain ⟨emission, emitted⟩ := Option.isSome_iff_exists.mp emitted + obtain ⟨compiled, built, _⟩ := emitCircuit_compiles program circuit functions columns validated emitted + rw [built] + rfl + +end Aiur.NativeAIR.CircuitEmitter + +namespace Aiur.BoundVerifier +open NativeAIR NativeAIR.CircuitEmitter + +theorem Backend.emitCircuit_compiles {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) {emission : Emission} + (emitted : emitCircuit backend.compiled.bytecode circuit = some emission) : + ∃ compiled, compileCircuit (circuitWidths circuit) backend.compiled.bytecode circuit = some compiled ∧ + compiled.emission = emission := + CircuitEmitter.emitCircuit_compiles backend.compiled.bytecode circuit (backend.functions_computedLayout generic) + (backend.circuits_columnBound generic circuit member) (backend.circuit_row_counts member) emitted + +theorem Backend.emittedCircuit_reflects {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) + {values : Values G} (fits : values.Fits (circuitWidths circuit)) {emission : Emission} + (emitted : emitCircuit backend.compiled.bytecode circuit = some emission) : + ∃ compiled result buffer, + compileCircuit (circuitWidths circuit) backend.compiled.bytecode circuit = some compiled ∧ + compiled.emission = emission ∧ + circuit.emitRow (fun index => (values.columns .main .current)[index]?.getD 0) backend.compiled.bytecode = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Compiler.Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := by + obtain ⟨compiled, built, same⟩ := backend.emitCircuit_compiles generic member emitted + obtain ⟨result, buffer, resultEmitted, swept, satisfied, lookups⟩ := + backend.compileCircuit_reflects generic fits member rfl built + exact ⟨compiled, result, buffer, built, same, resultEmitted, swept, satisfied, lookups⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/CircuitExpressions.lean b/Ix/Aiur/Proofs/CircuitExpressions.lean new file mode 100644 index 000000000..2ead63209 --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitExpressions.lean @@ -0,0 +1,272 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockLookups +import Ix.Aiur.Proofs.CircuitRows + +/-! +Symbolic function-circuit emission, preserving the native ordering of member +constraints and shared lookup contributions. Members restart auxiliary and +lookup cursors while their selector tables occupy consecutive regions. +-/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter LookupEmitter BlockEmitter Compiler + +def selectorExprs (base count : Nat) : Array Expr := + Array.ofFn fun index : Fin count => (mainCurrent (base + index.val)).expr + +theorem selectorExprs_reads {values : Values G} (row : Nat → G) (base count : Nat) + (reads : ∀ index < count, + (values.columns .main .current)[base + index]? = some (row (base + index))) : + SelectorReads values (selectorExprs base count) (fun index => row (base + index)) := by + intro index expr present + have bound : index < count := by + have bound := (Array.getElem?_eq_some_iff.mp present).choose + simpa only [selectorExprs, Array.size_ofFn] using bound + have equal : (selectorExprs base count)[index]? = some (mainCurrent (base + index)).expr := by + simp only [selectorExprs, Array.getElem?_ofFn, bound, dif_pos] + rw [equal] at present + cases present + exact reads index bound + +structure Member where + functionIndex : Nat + function : Bytecode.Function + selectorBase : Nat + entry : Expr + body : BlockEmitter.Emission + +def Member.readBound (member : Member) : Nat := + max member.function.layout.inputSize + (max (member.selectorBase + member.function.layout.selectors) member.body.column) + +def Member.eval (values : Values G) (member : Member) : Option AIR.MemberEmission := do + let body ← member.body.eval values + return ⟨member.functionIndex, member.function, member.selectorBase, body⟩ + +theorem Member.eval_of {values : Values G} {member : Member} {body : AIR.BlockEmission} + (evaluated : member.body.eval values = some body) : + member.eval values = some ⟨member.functionIndex, member.function, member.selectorBase, body⟩ := by + simp only [Member.eval, evaluated, bind, Option.bind_some, pure] + +theorem Member.eval_components {values : Values G} {member : Member} {result : AIR.MemberEmission} + (evaluated : member.eval values = some result) : + member.functionIndex = result.functionIndex ∧ member.function = result.function ∧ + member.selectorBase = result.selectorBase ∧ member.body.eval values = some result.body := by + simp only [Member.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i body bodyEval + cases evaluated + exact ⟨rfl, rfl, rfl, bodyEval⟩ + +def emitMember (rank : Expr) (column lookup selectorBase : Nat) + (program : Bytecode.Toplevel) (functionIndex : Nat) : Option Member := do + let function ← program.functions[functionIndex]? + let selectors := selectorExprs selectorBase function.layout.selectors + let entry ← blockSelector selectors function.body + let body ← emitBlock selectors ⟨functionIndex, function.layout.inputSize, rank⟩ entry + (advice 0 function.layout.inputSize) column lookup function.body + return ⟨functionIndex, function, selectorBase, entry, body⟩ + +def emitMembers (rank : Expr) (column lookup selectorBase : Nat) + (program : Bytecode.Toplevel) : List Nat → Option (List Member) + | [] => some [] + | index :: indices => do + let member ← emitMember rank column lookup selectorBase program index + let rest ← emitMembers rank column lookup (selectorBase + member.function.layout.selectors) program indices + return member :: rest + +def rankBytes (layout : Bytecode.FunctionLayout) : Fin 6 → Expr := + fun index => (mainCurrent (layout.inputSize + layout.selectors + 1 + index.val)).expr + +def selectorEquations (layout : Bytecode.FunctionLayout) : List Expr := + (List.range layout.selectors).map fun index => + let selector := (mainCurrent (layout.inputSize + index)).expr + selector.frontMul (selector.frontSub (.konst 1)) + +theorem selectorEquations_eval {values : Values G} (row : Nat → G) (layout : Bytecode.FunctionLayout) + (reads : ∀ index < layout.selectors, + (values.columns .main .current)[layout.inputSize + index]? = some (row (layout.inputSize + index))) : + (selectorEquations layout).mapM (evalExpr values) = some + ((List.range layout.selectors).map fun index => AIR.booleanConstraint (row (layout.inputSize + index))) := by + apply list_mapM_of_map + intro index member + have evaluated : evalExpr values (mainCurrent (layout.inputSize + index)).expr = + some (row (layout.inputSize + index)) := reads index (List.mem_range.mp member) + exact Expr.frontMul_eval goldilocksLaws values evaluated + (Expr.frontSub_eval goldilocksLaws values evaluated rfl) + +structure Emission where + members : List Member + selector : Expr + multiplicity : Expr + rankBytes : Fin 6 → Expr + width : Nat + selectorStart : Nat + selectorCount : Nat + lookupCount : Nat + branchless : Bool + equations : List Expr + queries : List QueryExpr + returns : List ReturnExpr + +def Emission.readBound (emission : Emission) : Nat := + emission.members.foldl (fun bound member => max bound member.readBound) + (emission.selectorStart + emission.selectorCount + 1 + 6) + +def circuitEmission (circuit : Bytecode.Circuit) (members : List Member) : Emission := + let selector := sum (members.map (·.entry)) + let multiplicity := (mainCurrent (circuit.layout.inputSize + circuit.layout.selectors)).expr + let bytes := rankBytes circuit.layout + { members, selector, multiplicity, rankBytes := bytes + width := circuit.layout.width + selectorStart := circuit.layout.inputSize + selectorCount := circuit.layout.selectors + lookupCount := circuit.layout.lookups + branchless := Bytecode.circuitBranchless circuit.layout.selectors (members.map (·.function)) + equations := members.flatMap (·.body.equations) ++ selectorEquations circuit.layout ++ + (if 1 < circuit.members.size then [selector.frontMul ((Expr.konst 1).frontSub selector)] else []) ++ + [multiplicity.frontMul ((Expr.konst 1).frontSub selector)] + queries := members.flatMap (·.body.queries) ++ + (if members.isEmpty then [] else queryParts 1 selector (rangeSix bytes)) + returns := members.flatMap (·.body.returns) } + +def emitCircuit (program : Bytecode.Toplevel) (circuit : Bytecode.Circuit) : Option Emission := do + let rank := packSix (rankBytes circuit.layout) + let column := circuit.layout.inputSize + circuit.layout.selectors + 1 + 6 + let members ← emitMembers rank column 4 circuit.layout.inputSize program circuit.members.toList + return circuitEmission circuit members + +def Emission.lookup (emission : Emission) (slot : Nat) : ExprLookup := + if slot = 0 then ⟨emission.multiplicity.frontNeg, returnArgs emission.branchless emission.returns⟩ + else LookupEmitter.slot emission.branchless emission.queries slot + +def Emission.lookups (emission : Emission) : List ExprLookup := + List.ofFn fun slot : Fin emission.lookupCount => emission.lookup slot.val + +def evalFin (values : Values G) (expressions : Fin size → Expr) : Option (Fin size → G) := do + let results ← (Array.ofFn expressions).mapM (evalExpr values) + return fun index => results[index.val]?.getD 0 + +theorem evalFin_of {values : Values G} {expressions : Fin size → Expr} {results : Fin size → G} + (evaluated : ∀ index, evalExpr values (expressions index) = some (results index)) : + evalFin values expressions = some results := by + have arrayEval := array_mapM_ofFn expressions results (evalExpr values) evaluated + simp only [evalFin, arrayEval, bind, Option.bind_some, pure] + congr 1 + funext index + simp only [Array.getElem?_ofFn, index.isLt, dif_pos, Option.getD_some] + +theorem evalFin_components {values : Values G} {expressions : Fin size → Expr} {results : Fin size → G} + (evaluated : evalFin values expressions = some results) : + ∀ index, evalExpr values (expressions index) = some (results index) := by + simp only [evalFin, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i array arrayEval + cases evaluated + intro index + apply evaluated_read arrayEval + simp only [Array.getElem?_ofFn, index.isLt, dif_pos] + +def Emission.eval (values : Values G) (emission : Emission) : Option AIR.CircuitEmission := do + let members ← emission.members.mapM (Member.eval values) + let selector ← evalExpr values emission.selector + let multiplicity ← evalExpr values emission.multiplicity + let rankBytes ← evalFin values emission.rankBytes + let equations ← emission.equations.mapM (evalExpr values) + let queries ← emission.queries.mapM (QueryExpr.eval values) + let returns ← emission.returns.mapM (ReturnExpr.eval values) + return ⟨members, selector, multiplicity, rankBytes, emission.width, emission.selectorStart, + emission.selectorCount, emission.lookupCount, emission.branchless, equations, queries, returns⟩ + +theorem Emission.eval_of {values : Values G} {emission : Emission} {result : AIR.CircuitEmission} + (members : emission.members.mapM (Member.eval values) = some result.members) + (selector : evalExpr values emission.selector = some result.selector) + (multiplicity : evalExpr values emission.multiplicity = some result.multiplicity) + (rankBytes : ∀ index, evalExpr values (emission.rankBytes index) = some (result.rankBytes index)) + (width : emission.width = result.width) (start : emission.selectorStart = result.selectorStart) + (count : emission.selectorCount = result.selectorCount) (lookups : emission.lookupCount = result.lookupCount) + (branchless : emission.branchless = result.branchless) + (equations : emission.equations.mapM (evalExpr values) = some result.equations) + (queries : emission.queries.mapM (QueryExpr.eval values) = some result.queries) + (returns : emission.returns.mapM (ReturnExpr.eval values) = some result.returns) : + emission.eval values = some result := by + simp only [Emission.eval, members, selector, multiplicity, evalFin_of rankBytes, equations, queries, returns, + width, start, count, lookups, branchless, bind, Option.bind_some, pure] + +theorem Emission.eval_components {values : Values G} {emission : Emission} {result : AIR.CircuitEmission} + (evaluated : emission.eval values = some result) : + emission.members.mapM (Member.eval values) = some result.members ∧ + evalExpr values emission.selector = some result.selector ∧ + evalExpr values emission.multiplicity = some result.multiplicity ∧ + (∀ index, evalExpr values (emission.rankBytes index) = some (result.rankBytes index)) ∧ + emission.width = result.width ∧ emission.selectorStart = result.selectorStart ∧ + emission.selectorCount = result.selectorCount ∧ emission.lookupCount = result.lookupCount ∧ + emission.branchless = result.branchless ∧ + emission.equations.mapM (evalExpr values) = some result.equations ∧ + emission.queries.mapM (QueryExpr.eval values) = some result.queries ∧ + emission.returns.mapM (ReturnExpr.eval values) = some result.returns := by + simp only [Emission.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i members membersEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i selector selectorEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i multiplicity multiplicityEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i bytes bytesEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i equations equationsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i queries queriesEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i returns returnsEval + cases evaluated + exact ⟨membersEval, selectorEval, multiplicityEval, evalFin_components bytesEval, + rfl, rfl, rfl, rfl, rfl, equationsEval, queriesEval, returnsEval⟩ + +theorem Emission.lookup_eval {values : Values G} {emission : Emission} {result : AIR.CircuitEmission} + (evaluated : emission.eval values = some result) (slot : Nat) : + (emission.lookup slot).eval goldilocksOps values = some (result.lookup slot) := by + obtain ⟨_, _, multiplicity, _, _, _, _, _, branchless, _, queries, returns⟩ := Emission.eval_components evaluated + by_cases zero : slot = 0 + · simp only [Emission.lookup, AIR.CircuitEmission.lookup, zero, if_true, ExprLookup.eval] + have weight := Expr.frontNeg_eval goldilocksLaws values multiplicity + change evalExpr values emission.multiplicity.frontNeg = some (0 - result.multiplicity) at weight + change ((evalExpr values emission.multiplicity.frontNeg).bind fun weight => + ((returnArgs emission.branchless emission.returns).mapM (evalExpr values)).bind fun args => some (weight, args)) = _ + rw [weight, returnArgs_eval emission.branchless returns, branchless] + rfl + · simpa only [Emission.lookup, AIR.CircuitEmission.lookup, zero, if_false, branchless] using + LookupEmitter.slot_eval emission.branchless queries slot + +theorem Emission.lookups_eval {values : Values G} {emission : Emission} {result : AIR.CircuitEmission} + (evaluated : emission.eval values = some result) : + emission.lookups.mapM (ExprLookup.eval goldilocksOps values) = some + (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := by + have lookups := (Emission.eval_components evaluated).2.2.2.2.2.2.2.1 + have reflected := list_mapM_ofFn (fun slot : Fin emission.lookupCount => emission.lookup slot.val) + (fun slot => result.lookup slot.val) (ExprLookup.eval goldilocksOps values) + (fun slot => Emission.lookup_eval evaluated slot.val) + rw [← lookups] + exact reflected + +end Aiur.NativeAIR.CircuitEmitter diff --git a/Ix/Aiur/Proofs/CircuitLayout.lean b/Ix/Aiur/Proofs/CircuitLayout.lean new file mode 100644 index 000000000..259b4c779 --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitLayout.lean @@ -0,0 +1,286 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FunctionLayout + +/-! Compiled circuit layouts contain every member's input and auxiliary +columns. Selector extents are supplied separately by the checked row counts. -/ + +namespace Aiur.Bytecode + +def MembersColumnBound (functions : Array Function) (members : Array FunIdx) (layout : FunctionLayout) : Prop := + 7 ≤ layout.auxiliaries ∧ ∀ index ∈ members, + functions[index]!.layout.inputSize ≤ layout.inputSize ∧ + functions[index]!.layout.auxiliaries ≤ layout.auxiliaries + +def CircuitsColumnBound (functions : Array Function) (circuits : Array Circuit) : Prop := + ∀ circuit ∈ circuits, MembersColumnBound functions circuit.members circuit.layout + +private theorem column_circuits_empty (functions : Array Function) : CircuitsColumnBound functions #[] := by + simp [CircuitsColumnBound] + +private theorem column_circuits_push {functions : Array Function} {circuits : Array Circuit} {circuit : Circuit} + (before : CircuitsColumnBound functions circuits) + (member : MembersColumnBound functions circuit.members circuit.layout) : + CircuitsColumnBound functions (circuits.push circuit) := by + intro c present + rcases Array.mem_push.mp present with prior | equal + · exact before c prior + · subst c; exact member + +private theorem column_bang_of_present {functions : Array Function} {index : Nat} {function : Function} + (present : functions[index]? = some function) : functions[index]! = function := by + rw [Array.getElem!_eq_getD, Array.getD_eq_getD_getElem?, present] + rfl + +private theorem column_member_singleton {functions : Array Function} {index : FunIdx} {function : Function} + (present : functions[index]? = some function) (valid : function.ComputedLayout) : + MembersColumnBound functions #[index] function.layout := by + refine ⟨valid.reserved, ?_⟩ + intro i member + have equal : i = index := by simpa using member + subst i + rw [column_bang_of_present present] + exact ⟨Nat.le_refl _, Nat.le_refl _⟩ + +private theorem column_array_bang {α : Type} [Inhabited α] (property : α → Prop) + {array : Array α} (valid : ∀ value ∈ array, property value) (fallback : property default) (index : Nat) : + property array[index]! := by + by_cases bound : index < array.size + · rw [getElem!_pos array index bound] + exact valid _ (Array.getElem_mem bound) + · rw [getElem!_neg array index bound] + exact fallback + +private theorem column_first_reserved {functions : Array Function} {members : Array FunIdx} + (valid : FunctionsComputedLayout functions) (nonempty : 0 < functions.size) + (constrained : MembersConstrained functions members) : + 7 ≤ functions[members[0]!]!.layout.auxiliaries := by + refine column_array_bang (fun index : FunIdx => 7 ≤ functions[index]!.layout.auxiliaries) + (array := members) ?_ ?_ 0 + · intro index member + obtain ⟨function, present, _⟩ := constrained index member + rw [column_bang_of_present present] + exact (valid function (Array.mem_of_getElem? present)).reserved + · change 7 ≤ functions[0]!.layout.auxiliaries + rw [getElem!_pos functions 0 nonempty] + exact (valid _ (Array.getElem_mem nonempty)).reserved + +private theorem column_merge_fold (functions : Array Function) (first : FunIdx) (members : List FunIdx) + (initial : FunctionLayout) + (firstInput : functions[first]!.layout.inputSize ≤ initial.inputSize) + (firstAux : functions[first]!.layout.auxiliaries ≤ initial.auxiliaries) : + let final := members.foldl (fun acc index => if index == first then acc else acc.merge functions[index]!.layout) initial + initial.inputSize ≤ final.inputSize ∧ initial.auxiliaries ≤ final.auxiliaries ∧ + ∀ index ∈ members, functions[index]!.layout.inputSize ≤ final.inputSize ∧ + functions[index]!.layout.auxiliaries ≤ final.auxiliaries := by + induction members generalizing initial with + | nil => exact ⟨Nat.le_refl _, Nat.le_refl _, by simp⟩ + | cons index members ih => + let next := if index == first then initial else initial.merge functions[index]!.layout + have before : initial.inputSize ≤ next.inputSize ∧ initial.auxiliaries ≤ next.auxiliaries := by + dsimp only [next] + split + · exact ⟨Nat.le_refl _, Nat.le_refl _⟩ + · exact ⟨Nat.le_max_left _ _, Nat.le_max_left _ _⟩ + have here : functions[index]!.layout.inputSize ≤ next.inputSize ∧ + functions[index]!.layout.auxiliaries ≤ next.auxiliaries := by + dsimp only [next] + split + · rename_i equal + have eq : index = first := beq_iff_eq.mp equal + subst index + exact ⟨firstInput, firstAux⟩ + · exact ⟨Nat.le_max_right _ _, Nat.le_max_right _ _⟩ + have rest := ih next (Nat.le_trans firstInput before.1) (Nat.le_trans firstAux before.2) + refine ⟨Nat.le_trans before.1 rest.1, Nat.le_trans before.2 rest.2.1, ?_⟩ + intro chosen member + rcases List.mem_cons.mp member with equal | later + · subst chosen + exact ⟨Nat.le_trans here.1 rest.1, Nat.le_trans here.2 rest.2.1⟩ + · exact rest.2.2 chosen later + +theorem merged_columnBound (functions : Array Function) (members : Array FunIdx) + (valid : FunctionsComputedLayout functions) (nonempty : 0 < functions.size) + (constrained : MembersConstrained functions members) : + MembersColumnBound functions members + (members.foldl (init := functions[members[0]!]!.layout) + fun acc index => if index == members[0]! then acc else acc.merge functions[index]!.layout) := by + rw [← Array.foldl_toList] + have folded := column_merge_fold functions members[0]! members.toList functions[members[0]!]!.layout + (Nat.le_refl _) (Nat.le_refl _) + exact ⟨Nat.le_trans (column_first_reserved valid nonempty constrained) folded.2.1, + fun index member => folded.2.2 index (Array.mem_def.mp member)⟩ + +private theorem list_forIn'_id_invariant {α β : Type} (items : List α) + (step : (item : α) → item ∈ items → β → Id (ForInStep β)) (property : β → Prop) + (initial : β) (before : property initial) + (preserved : ∀ item member acc, property acc → property (step item member acc).run.value) : + property (forIn' items initial step).run := by + induction items generalizing initial with + | nil => exact before + | cons item items ih => + rw [List.forIn'_cons] + have first := preserved item List.mem_cons_self initial before + cases computed : step item List.mem_cons_self initial with + | done next => + simp only [computed, Id.run, ForInStep.value] at first + exact first + | yield next => + simp only [computed, Id.run, ForInStep.value] at first + exact ih (fun item member => step item (List.mem_cons_of_mem _ member)) next first + (fun item member acc => preserved item (List.mem_cons_of_mem _ member) acc) + +theorem singletonCircuits_columnBound (program : Toplevel) (nameOf : FunIdx → String) + (valid : FunctionsComputedLayout program.functions) : + CircuitsColumnBound program.functions (program.singletonCircuits nameOf) := by + unfold Toplevel.singletonCircuits + simp only [Id.run] + rw [Std.Legacy.Range.forIn'_eq_forIn'_range'] + apply list_forIn'_id_invariant _ _ (CircuitsColumnBound program.functions) _ (column_circuits_empty _) + intro index member circuits before + split + · exact column_circuits_push before + (column_member_singleton (Array.getElem?_eq_getElem _) (valid _ (Array.getElem_mem _))) + · exact before + +end Aiur.Bytecode + +namespace Aiur +open Bytecode + +private theorem list_forIn_except_invariant {ε α β : Type} (items : List α) + (step : α → β → Except ε (ForInStep β)) (property : β → Prop) (initial : β) + (before : property initial) + (preserved : ∀ item ∈ items, ∀ acc result, property acc → step item acc = .ok result → property result.value) + {result : β} (computed : forIn items initial step = .ok result) : property result := by + induction items generalizing initial with + | nil => cases computed; exact before + | cons item items ih => + simp only [List.forIn_cons, bind, Except.bind] at computed + split at computed + · cases computed + · rename_i next nextComputed + have first := preserved item List.mem_cons_self initial next before nextComputed + cases next with + | done next => cases computed; exact first + | yield next => + exact ih next first (fun item member => preserved item (List.mem_cons_of_mem _ member)) computed + +private theorem array_forIn_except_invariant {ε α β : Type} (items : Array α) + (step : α → β → Except ε (ForInStep β)) (property : β → Prop) (initial : β) + (before : property initial) + (preserved : ∀ item ∈ items, ∀ acc result, property acc → step item acc = .ok result → property result.value) + {result : β} (computed : forIn items initial step = .ok result) : property result := by + rw [← Array.forIn_toList] at computed + exact list_forIn_except_invariant items.toList step property initial before + (fun item member => preserved item (Array.mem_toList_iff.mp member)) computed + +private theorem column_members_empty (functions : Array Function) : MembersConstrained functions #[] := by + simp [MembersConstrained] + +private theorem column_members_push {functions : Array Function} {members : Array FunIdx} {index : FunIdx} + (before : MembersConstrained functions members) (constrained : functions[index]!.constrained = true) : + MembersConstrained functions (members.push index) := by + intro i member + rcases Array.mem_push.mp member with prior | equal + · exact before i prior + · subst i + by_cases bound : index < functions.size + · exact ⟨functions[index], Array.getElem?_eq_getElem bound, + by simpa only [getElem!_pos functions index bound] using constrained⟩ + · rw [getElem!_neg functions index bound] at constrained + contradiction + +theorem CompiledToplevel.groupFunctions_columnBound {before after : CompiledToplevel} + {groups : Array (String × Array String)} + (functions : FunctionsComputedLayout before.bytecode.functions) + (nonempty : 0 < before.bytecode.functions.size) + (valid : CircuitsColumnBound before.bytecode.functions before.bytecode.circuits) + (accepted : before.groupFunctions groups = .ok after) : + CircuitsColumnBound after.bytecode.functions after.bytecode.circuits := by + unfold CompiledToplevel.groupFunctions at accepted + simp only [bind, Except.bind, pure, Except.pure, throw, throwThe, MonadExceptOf.throw] at accepted + split at accepted + · cases accepted + · rename_i resolved resolvedComputed + have resolvedValid : ∀ pair ∈ resolved.2, MembersConstrained before.bytecode.functions pair.2 := by + apply array_forIn_except_invariant _ _ + (fun acc => ∀ pair ∈ acc.2, MembersConstrained before.bytecode.functions pair.2) _ ?_ ?_ resolvedComputed + · simp + · intro item member acc result accumulated step + rcases item with ⟨groupName, names⟩ + dsimp only at step + split at step + · cases step + · split at step + · cases step + · rename_i named namedComputed + have namedValid : MembersConstrained before.bytecode.functions named.2 := by + apply array_forIn_except_invariant _ _ + (fun acc => MembersConstrained before.bytecode.functions acc.2) _ (column_members_empty _) ?_ namedComputed + intro name nameMember acc result accumulated step + repeat' first | split at step | (dsimp only at step; split at step) + all_goals cases step + all_goals exact column_members_push accumulated (by assumption) + cases step + intro pair member + rcases Array.mem_push.mp member with prior | equal + · exact accumulated pair prior + · subst pair; exact namedValid + split at accepted + · cases accepted + · rename_i circuits circuitsComputed + cases accepted + apply array_forIn_except_invariant _ _ + (fun acc => CircuitsColumnBound before.bytecode.functions acc.1) _ (column_circuits_empty _) ?_ circuitsComputed + intro circuit member acc result accumulated step + split at step + · split at step + · cases step + exact column_circuits_push accumulated (valid circuit member) + · split at step + · cases step + exact accumulated + · cases step + apply column_circuits_push accumulated + apply merged_columnBound _ _ functions nonempty + exact column_array_bang (fun pair : String × Array FunIdx => + MembersConstrained before.bytecode.functions pair.2) resolvedValid (column_members_empty _) _ + · cases step + +theorem finishCompilation_columnBound (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) (valid : FunctionsComputedLayout raw.functions) + (generic : source.componentRanks = false) : + CircuitsColumnBound (finishCompilation source raw names).bytecode.functions + (finishCompilation source raw names).bytecode.circuits := by + unfold finishCompilation + apply singletonCircuits_columnBound + exact finishCompilation_computedLayout source raw names valid generic + +theorem Source.Toplevel.compile_columnBound {source : Source.Toplevel} {compiled : CompiledToplevel} + (accepted : source.compile = .ok compiled) (generic : source.componentRanks = false) : + CircuitsColumnBound compiled.bytecode.functions compiled.bytecode.circuits := by + obtain ⟨inlined, typed, concrete, raw, names, inlinedOk, _, _, lowered, artifact⟩ := + source.compile_artifact_of_ok accepted + rw [artifact] + exact finishCompilation_columnBound inlined raw names (Concrete.Decls.toBytecode_computedLayout lowered) + ((Source.Toplevel.inlineCalls_componentRanks inlinedOk).trans generic) + +theorem BoundVerifier.Backend.circuits_columnBound {selection : BoundVerifier.Selection} + (backend : BoundVerifier.Backend selection) (generic : selection.source.componentRanks = false) : + CircuitsColumnBound backend.compiled.bytecode.functions backend.compiled.bytecode.circuits := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + have valid := Source.Toplevel.compile_columnBound compiled generic + split at grouped + · cases grouped + exact valid + · have same := (CompiledToplevel.groupFunctions_preserves_code grouped).2.2.1 + have bound := (Array.getElem?_eq_some_iff.mp backend.present).choose + rw [same] at bound + exact CompiledToplevel.groupFunctions_columnBound + (Source.Toplevel.compile_computedLayout compiled generic) (by omega) valid grouped + +end Aiur diff --git a/Ix/Aiur/Proofs/CircuitMembership.lean b/Ix/Aiur/Proofs/CircuitMembership.lean new file mode 100644 index 000000000..78fea71fc --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitMembership.lean @@ -0,0 +1,234 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitTraces +import Ix.Aiur.Proofs.Grouping +import Std.Tactic.Do + +/-! The actual compiler and successful grouping produce only constrained +circuit members. The selected backend's program shape check therefore +discharges the shape condition for every successfully emitted trace row. +Physical lookup bounds, native extraction and the cryptographic and +source-semantic endpoint remain separate proof obligations. -/ + +open Std.Do +namespace Aiur.Bytecode + +def MembersConstrained (functions : Array Function) (members : Array FunIdx) : Prop := + ∀ index ∈ members, ∃ function, functions[index]? = some function ∧ function.constrained = true + +def CircuitsConstrained (functions : Array Function) (circuits : Array Circuit) : Prop := + ∀ circuit ∈ circuits, MembersConstrained functions circuit.members + +private theorem circuits_empty (functions : Array Function) : CircuitsConstrained functions #[] := by + simp [CircuitsConstrained] + +private theorem circuits_push {functions : Array Function} {circuits : Array Circuit} {circuit : Circuit} + (before : CircuitsConstrained functions circuits) (member : MembersConstrained functions circuit.members) : + CircuitsConstrained functions (circuits.push circuit) := by + intro c present + rcases Array.mem_push.mp present with prior | equal + · exact before c prior + · subst c; exact member + +private theorem member_singleton {functions : Array Function} {index : FunIdx} {function : Function} + (present : functions[index]? = some function) (constrained : function.constrained = true) : + MembersConstrained functions #[index] := by + intro i member + have equal : i = index := by simpa using member + subst i + exact ⟨function, present, constrained⟩ + +private theorem members_empty (functions : Array Function) : MembersConstrained functions #[] := by + simp [MembersConstrained] + +private theorem members_push {functions : Array Function} {members : Array FunIdx} {index : FunIdx} + (before : MembersConstrained functions members) (constrained : functions[index]!.constrained = true) : + MembersConstrained functions (members.push index) := by + intro i member + rcases Array.mem_push.mp member with prior | equal + · exact before i prior + · subst i + by_cases bound : index < functions.size + · exact ⟨functions[index], Array.getElem?_eq_getElem bound, + by simpa only [getElem!_pos functions index bound] using constrained⟩ + · rw [getElem!_neg functions index bound] at constrained + contradiction + +private theorem array_bang_valid {α : Type} [Inhabited α] (property : α → Prop) + {array : Array α} (valid : ∀ value ∈ array, property value) (fallback : property default) (index : Nat) : + property array[index]! := by + by_cases bound : index < array.size + · rw [getElem!_pos array index bound] + exact valid _ (Array.getElem_mem bound) + · rw [getElem!_neg array index bound] + exact fallback + +private theorem array_split_member {α : Type} {array : Array α} {pref suff : List α} {value : α} + (split : array.toList = pref ++ value :: suff) : value ∈ array := by + apply Array.mem_toList_iff.mp + rw [split] + simp + +set_option mvcgen.warning false in +theorem singletonCircuits_constrained (program : Toplevel) (nameOf : FunIdx → String) : + CircuitsConstrained program.functions (program.singletonCircuits nameOf) := by + have spec : Triple (m := Id) (program.singletonCircuits nameOf) ⌜True⌝ + (⇓ circuits => ⌜CircuitsConstrained program.functions circuits⌝) := by + mvcgen [Toplevel.singletonCircuits, Id.run] invariants + · ⇓⟨_, circuits⟩ => ⌜CircuitsConstrained program.functions circuits⌝ + case vc1.step.isTrue => + apply circuits_push (by assumption) + apply member_singleton (Array.getElem?_eq_getElem _) + assumption + case vc3.pre => exact circuits_empty _ + exact Id.of_wp_run_eq rfl _ spec + +end Aiur.Bytecode + +namespace Aiur +open Bytecode + +-- The library's corresponding specification has unused monad parameters. +-- This specialization keeps loop verification conditions fully determined. +private theorem throw_except {ε α : Type} {error : ε} {post : PostCond α (.except ε .pure)} : + Triple (ps := .except ε .pure) (throw error : Except ε α) (spred(post.2.1 error)) post := by + simp [Triple.iff] + +set_option mvcgen.warning false in +theorem CompiledToplevel.groupFunctions_constrained {before after : CompiledToplevel} + {groups : Array (String × Array String)} + (valid : CircuitsConstrained before.bytecode.functions before.bytecode.circuits) + (accepted : before.groupFunctions groups = .ok after) : + CircuitsConstrained after.bytecode.functions after.bytecode.circuits := by + have spec : ⦃⌜True⌝⦄ before.groupFunctions groups + ⦃post⟨fun compiled => ⌜CircuitsConstrained compiled.bytecode.functions compiled.bytecode.circuits⌝, + fun _ => ⌜True⌝⟩⦄ := by + mvcgen [CompiledToplevel.groupFunctions, -Spec.throw_Except, throw_except] invariants + · post⟨fun ⟨_, _, resolved⟩ => ⌜∀ pair ∈ resolved, + MembersConstrained before.bytecode.functions pair.2⌝, fun _ => ⌜True⌝⟩ + · post⟨fun ⟨_, _, members⟩ => ⌜MembersConstrained before.bytecode.functions members⌝, + fun _ => ⌜True⌝⟩ + · post⟨fun ⟨_, circuits, _⟩ => ⌜CircuitsConstrained before.bytecode.functions circuits⌝, + fun _ => ⌜True⌝⟩ + case vc4.step.h_1.isTrue.isFalse.isFalse => exact members_push (by assumption) (by assumption) + case vc7.step.isFalse.pre => exact members_empty _ + case vc8.step.isFalse.post.success => + intro pair member + rcases Array.mem_push.mp member with prior | equal + · apply_assumption; exact prior + · subst pair; assumption + case vc10.pre => + change ∀ pair ∈ (#[] : Array (String × Array FunIdx)), _ + simp + case vc11.step.isTrue.h_1 => + apply circuits_push (by assumption) + apply valid + exact array_split_member (by assumption) + case vc13.step.isTrue.h_2.isFalse => + apply circuits_push (by assumption) + exact array_bang_valid (fun pair : String × Array FunIdx => + MembersConstrained before.bytecode.functions pair.2) (by assumption) (members_empty _) _ + case vc15.post.success.pre => exact circuits_empty _ + exact Except.of_wp_eq accepted (fun result => match result with + | .error _ => True + | .ok compiled => CircuitsConstrained compiled.bytecode.functions compiled.bytecode.circuits) spec + +theorem finishCompilation_circuits_constrained (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) : + CircuitsConstrained (finishCompilation source raw names).bytecode.functions + (finishCompilation source raw names).bytecode.circuits := by + unfold finishCompilation + exact singletonCircuits_constrained _ _ + +theorem Source.Toplevel.compile_circuits_constrained {source : Source.Toplevel} {compiled : CompiledToplevel} + (accepted : source.compile = .ok compiled) : + CircuitsConstrained compiled.bytecode.functions compiled.bytecode.circuits := by + obtain ⟨inlined, typed, concrete, raw, names, _, _, _, _, artifact⟩ := + source.compile_artifact_of_ok accepted + rw [artifact] + exact finishCompilation_circuits_constrained inlined raw names + +theorem BoundVerifier.Backend.circuits_constrained {selection : BoundVerifier.Selection} + (backend : BoundVerifier.Backend selection) : + CircuitsConstrained backend.compiled.bytecode.functions backend.compiled.bytecode.circuits := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + have valid := Source.Toplevel.compile_circuits_constrained compiled + split at grouped + · cases grouped + exact valid + · exact CompiledToplevel.groupFunctions_constrained valid grouped + +end Aiur + +namespace Aiur.Bytecode + +theorem Toplevel.validateLookupShapes_function {program : Toplevel} + (valid : program.validateLookupShapes = true) {function : Function} {index : FunIdx} + (present : program.functions[index]? = some function) (constrained : function.constrained = true) : + function.body.lookupShapes program none = true := by + simp only [Toplevel.validateLookupShapes, Bool.and_eq_true] at valid + have checked := Array.all_eq_true'.mp valid.2.2 function (Array.mem_of_getElem? present) + simpa only [constrained, Bool.not_true, Bool.false_or] using checked + +end Aiur.Bytecode + +namespace Aiur.AIR +open Bytecode + +theorem CircuitWitness.shapes_of_compiled {program : Toplevel} + (shapes : program.validateLookupShapes = true) + (constrained : CircuitsConstrained program.functions program.circuits) + (witness : CircuitWitness) (circuit : witness.circuit ∈ program.circuits) + (emitted : witness.Emitted program) : witness.Shapes program := by + obtain ⟨_, indices, source⟩ := witness.circuit.emitRow_spec witness.values program emitted + intro part member + have index : part.functionIndex ∈ witness.circuit.members := by + apply Array.mem_toList_iff.mp + rw [← indices] + exact List.mem_map.mpr ⟨part, member, rfl⟩ + obtain ⟨function, present, isConstrained⟩ := constrained witness.circuit circuit part.functionIndex index + have equal := Option.some.inj (present.symm.trans (source part member).present) + subst function + exact Toplevel.validateLookupShapes_function shapes present isConstrained + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem Backend.witness_shapes {selection : Selection} (backend : Backend selection) + (witness : CircuitWitness) (circuit : witness.circuit ∈ backend.compiled.bytecode.circuits) + (emitted : witness.Emitted backend.compiled.bytecode) : witness.Shapes backend.compiled.bytecode := + witness.shapes_of_compiled backend.lookupShapes backend.circuits_constrained circuit emitted + +theorem Backend.compiled_trace_execution {selection : Selection} (backend : Backend selection) + (tables : AuxiliaryTables) (traces : CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List CircuitWitness} + (emitted : traces.emitWitnesses backend.compiled.bytecode = some witnesses) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (budget : lookupQueryBound + (backend.compiled.bytecode.circuits.toList.map (·.layout.lookups) ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: + encodedCircuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) + ⟨selection.function, input, selection.success, 0⟩ := by + have valid := (traces.emitWitnesses_spec emitted).1 + apply backend.trace_circuit_execution tables traces emitted budget width input arity balanced + publicWidth queryWidths memoryValid canonical satisfied _ limits + intro witness member + exact backend.witness_shapes witness (by simpa using (valid witness member).1) (valid witness member).2 + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/CircuitPoolExecution.lean b/Ix/Aiur/Proofs/CircuitPoolExecution.lean new file mode 100644 index 000000000..a27a2537c --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitPoolExecution.lean @@ -0,0 +1,114 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRowReturns + +/-! +A nonzero provider row of the valued circuit model yields a valid +function row from the same bytecode program. The interpreted inputs, rank +bytes and multiplicity agree with the circuit, and its padded provider +message names that same semantic call. All selected call and rank-byte +queries belong to any ambient pool containing the computed circuit pool. + +Exact global lookup balance, memory validity, shape and count/layout bounds +remain explicit. This is not yet extraction from native public verification. +-/ + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitRow_valid_in_pool {tables : LookupTables} {width : Nat} {emissions : List CircuitEmission} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (member : emission ∈ emissions) + (pooled : circuitQueryPool emissions ⊆ queries) + (bounded : circuit.members.size < gSize.toNat) + (bounds : ∀ part ∈ emission.members, part.function.body.rowBounds (part.selector row)) + (shape : ∀ part ∈ emission.members, part.function.body.lookupShapes program none = true) + (returnBound : ∀ part ∈ emission.members, + (part.function.body.selectorFlow (part.selector row)).returns.length < gSize.toNat) + (reserved : 4 ≤ circuit.layout.lookups) + (limits : ∀ part ∈ emission.members, part.body.lookup ≤ circuit.layout.lookups) + (single : emission.branchless = true → emission.returns.length ≤ 1) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (nonzero : emission.multiplicity ≠ 0) : + ∃ selected ∈ emission.members, ∃ interpreted : FunctionRow, + interpreted.Valid program (memoryFacts tables.memory) ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = rowValues (rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = packRank emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + padMessage width (emission.lookup 0).2 = padMessage width (functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + (interpreted.requests.map functionMessage) ⊆ queries ∧ + (interpreted.byteQueries.map rangeMessage) ⊆ queries := by + obtain ⟨description, indices, source⟩ := circuit.emitRow_spec row program emitted + have count := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at count + have valid : ∀ equation ∈ (circuitEmission row circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have slots := circuit.emitRow_querySlots row program emitted bounded bounds reserved limits satisfied + have inCircuit := slots.circuit_pool member + have queried : emission.QueriesIn queries := fun query present active => + pooled (inCircuit query present active) + have wholeQueried : (circuitEmission row circuit emission.members).QueriesIn queries := by + rw [← description] + exact queried + have activity := circuitEmission_activity valid + rw [← description] at activity + have active := nonzero_multiplicity_selector_one activity nonzero + obtain ⟨selected, selectedMember, selectedActive, selectedSource⟩ := + circuit.emitRow_active_member row program emitted satisfied bounded nonzero + have bodySatisfied := circuitEmission_member_satisfied valid selectedMember + have bodyQueried := circuitEmission_member_queried wholeQueried selectedMember + have selectedActivity : activityConstraint emission.multiplicity + (selected.function.body.selectorFlow (selected.selector row)).entry = 0 := by + change activityConstraint emission.multiplicity (selected.entry row) = 0 + rw [selectedActive] + rw [active] at activity + exact activity + obtain ⟨interpreted, interpretedValid, returned, functionEq, inputsEq, rankEq, + rankBytesEq, selectorEq, multiplicityEq, called, inventory⟩ := + selected.function.emitRow_valid global memoryValid canonical program row (selected.selector row) + selected.functionIndex emission.rankBytes (rowAdvice row 0 selected.function.layout.inputSize) + _ 4 selectedSource.present (by simp only [rowAdvice, Array.size_ofFn]) + (shape selected selectedMember) (bounds selected selectedMember) selectedSource.emitted + emission.multiplicity nonzero selectedActivity bodySatisfied bodyQueried + have returnMember : (1, interpreted.request) ∈ emission.returns := by + have returnsEq := congrArg CircuitEmission.returns description + rw [returnsEq] + exact List.mem_flatMap.mpr ⟨selected, selectedMember, returned⟩ + have message := circuitEmission_return_message source shape (by omega) returnBound valid + (by rw [← description]; exact active) width + (by rw [← description]; exact single) + (by rw [← description]; exact returnMember) + rw [← description] at message + have headers := circuitEmission_rank_queried wholeQueried (by rw [← description]; exact active) + rw [← description] at headers + refine ⟨selected, selectedMember, interpreted, interpretedValid, functionEq, inputsEq, + rankEq, rankBytesEq, ?_, multiplicityEq, returnMember, message, called, ?_, ?_⟩ + · exact selectorEq.trans (selectedActive.trans active.symm) + · intro message member + simp only [FunctionRow.requests, List.map_map, List.mem_map, Function.comp_def] at member + obtain ⟨edge, edgeMember, equal⟩ := member + rw [← equal] + exact (inventory edge edgeMember).1 + · intro message member + rw [FunctionRow.byteQueries, List.map_append] at member + rcases List.mem_append.mp member with header | gap + · rw [rankBytesEq] at header + exact headers header + · obtain ⟨pair, pairMember, messageEq⟩ := List.mem_map.mp gap + obtain ⟨edge, edgeMember, pairMember⟩ := List.mem_flatMap.mp pairMember + rw [← messageEq] + exact (inventory edge edgeMember).2.1 (List.mem_map.mpr ⟨pair, pairMember, rfl⟩) + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/CircuitReflection.lean b/Ix/Aiur/Proofs/CircuitReflection.lean new file mode 100644 index 000000000..b049164f7 --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitReflection.lean @@ -0,0 +1,171 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitExpressions + +/-! +Reflection of complete symbolic function circuits into the valued circuit +model. The row premise covers the finite header and member allocations; +no equation values, query messages, or selected executions are assumed. +-/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter LookupEmitter BlockEmitter Compiler + +theorem emitMember_reflects {values : Values G} (row : Nat → G) {rank : Expr} {r : G} + {column lookup selectorBase : Nat} {program : Bytecode.Toplevel} {functionIndex : Nat} {member : Member} + (rankEval : evalExpr values rank = some r) + (emitted : emitMember rank column lookup selectorBase program functionIndex = some member) + (reads : ∀ index < member.readBound, (values.columns .main .current)[index]? = some (row index)) : + ∃ result, AIR.emitMember row r column lookup selectorBase program functionIndex = some result ∧ + member.eval values = some result ∧ evalExpr values member.entry = some (result.entry row) := by + simp only [emitMember, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i function functionRead + dsimp only at emitted + split at emitted + · cases emitted + rename_i entry entryRead + dsimp only at emitted + split at emitted + · cases emitted + rename_i body bodyEmitted + cases emitted + dsimp only [Member.readBound] at reads + have selectors : SelectorReads values (selectorExprs selectorBase function.layout.selectors) + (fun index => row (selectorBase + index)) := selectorExprs_reads row selectorBase function.layout.selectors + (fun index bound => reads (selectorBase + index) (by omega)) + have entryEval := blockSelector_reads selectors function.body entryRead + have inputs := advice_absolute_eval row 0 function.layout.inputSize + (fun index bound => by simpa only [Nat.zero_add] using reads index (by omega)) + obtain ⟨result, bodyRead, bodyEval⟩ := block_reflects values row selectors rankEval function.body + entryEval inputs (advice_normal _ _) bodyEmitted (fun index _ bound => reads index (by omega)) + dsimp only [Context.valued] at bodyRead + refine ⟨⟨functionIndex, function, selectorBase, result⟩, ?_, Member.eval_of bodyEval, entryEval⟩ + simp only [AIR.emitMember, functionRead, Bytecode.Function.emitRow, bodyRead, bind, Option.bind_some, pure] + +theorem emitMembers_reflects {values : Values G} (row : Nat → G) {rank : Expr} {r : G} + (column lookup selectorBase : Nat) (program : Bytecode.Toplevel) (indices : List Nat) + {members : List Member} (rankEval : evalExpr values rank = some r) + (emitted : emitMembers rank column lookup selectorBase program indices = some members) + (reads : ∀ member ∈ members, ∀ index < member.readBound, + (values.columns .main .current)[index]? = some (row index)) : + ∃ results, AIR.emitMembers row r column lookup selectorBase program indices = some results ∧ + members.mapM (Member.eval values) = some results ∧ + (members.map Member.entry).mapM (evalExpr values) = some (results.map (·.entry row)) := by + induction indices generalizing selectorBase members with + | nil => + cases emitted + exact ⟨[], rfl, rfl, rfl⟩ + | cons index indices ih => + simp only [emitMembers, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i member memberEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i tail tailEmitted + cases emitted + obtain ⟨result, memberRead, memberEval, entryEval⟩ := emitMember_reflects row rankEval memberEmitted + (reads member List.mem_cons_self) + obtain ⟨results, resultsRead, resultsEval, entriesEval⟩ := ih _ tailEmitted + (fun member present => reads member (List.mem_cons_of_mem _ present)) + have function := (Member.eval_components memberEval).2.1 + refine ⟨result :: results, ?_, ?_, ?_⟩ + · simp only [AIR.emitMembers, memberRead, bind, Option.bind_some, ← function, resultsRead, pure] + · simp only [List.mapM_cons, memberEval, resultsEval, bind, Option.bind_some, pure] + · simp only [List.map_cons, List.mapM_cons, entryEval, entriesEval, bind, Option.bind_some, pure] + +theorem circuitEmission_eval {values : Values G} (row : Nat → G) (circuit : Bytecode.Circuit) + {members : List Member} {results : List AIR.MemberEmission} + (membersEval : members.mapM (Member.eval values) = some results) + (entriesEval : (members.map Member.entry).mapM (evalExpr values) = some (results.map (·.entry row))) + (reads : ∀ index < circuit.layout.inputSize + circuit.layout.selectors + 1 + 6, + (values.columns .main .current)[index]? = some (row index)) : + (circuitEmission circuit members).eval values = some (AIR.circuitEmission row circuit results) := by + have selectorEval := sum_eval entriesEval + have rankEval (index : Fin 6) : evalExpr values (rankBytes circuit.layout index) = + some (AIR.circuitRankBytes row circuit.layout index) := + reads (circuit.layout.inputSize + circuit.layout.selectors + 1 + index.val) (by omega) + have multiplicityEval : evalExpr values (mainCurrent (circuit.layout.inputSize + circuit.layout.selectors)).expr = + some (row (circuit.layout.inputSize + circuit.layout.selectors)) := + reads (circuit.layout.inputSize + circuit.layout.selectors) (by omega) + have functions : members.map Member.function = results.map AIR.MemberEmission.function := by + have relation := AIR.mapM_forall₂ membersEval (fun _ _ _ reflected => (Member.eval_components reflected).2.1) + clear membersEval entriesEval selectorEval + induction relation with + | nil => rfl + | cons equal _ ih => simp only [List.map_cons, equal, ih] + have equations : (members.flatMap (·.body.equations)).mapM (evalExpr values) = + some (results.flatMap (·.body.equations)) := + list_mapM_flatMap membersEval (fun member => member.body.equations) (fun result => result.body.equations) + (evalExpr values) (fun _ _ reflected => + (BlockEmitter.Emission.eval_components (Member.eval_components reflected).2.2.2).2.2.2.1) + have queries : (members.flatMap (·.body.queries)).mapM (QueryExpr.eval values) = + some (results.flatMap (·.body.queries)) := + list_mapM_flatMap membersEval (fun member => member.body.queries) (fun result => result.body.queries) + (QueryExpr.eval values) (fun _ _ reflected => + (BlockEmitter.Emission.eval_components (Member.eval_components reflected).2.2.2).2.2.2.2.1) + have returns : (members.flatMap (·.body.returns)).mapM (ReturnExpr.eval values) = + some (results.flatMap (·.body.returns)) := + list_mapM_flatMap membersEval (fun member => member.body.returns) (fun result => result.body.returns) + (ReturnExpr.eval values) (fun _ _ reflected => + (BlockEmitter.Emission.eval_components (Member.eval_components reflected).2.2.2).2.2.2.2.2.1) + have oneMinus := Expr.frontSub_eval goldilocksLaws values + (show evalExpr values (.konst 1) = some 1 from rfl) selectorEval + have exclusive := Expr.frontMul_eval goldilocksLaws values selectorEval oneMinus + have activity := Expr.frontMul_eval goldilocksLaws values multiplicityEval oneMinus + have selectors := selectorEquations_eval row circuit.layout + (fun index bound => reads (circuit.layout.inputSize + index) (by omega)) + have rankQueries := queryParts_eval selectorEval (rangeSix_eval (rankBytes circuit.layout) + (AIR.circuitRankBytes row circuit.layout) rankEval) 1 + have empty : members.isEmpty = results.isEmpty := by + cases members <;> cases results <;> simp_all + apply Emission.eval_of + · exact membersEval + · exact selectorEval + · exact multiplicityEval + · exact rankEval + · rfl + · rfl + · rfl + · rfl + · simp only [circuitEmission, AIR.circuitEmission, functions] + · simp only [circuitEmission, AIR.circuitEmission, List.mapM_append] + split <;> simp only [List.mapM_cons, List.mapM_nil, equations, selectors, exclusive, activity, + bind, Option.bind_some, pure, goldilocks_mul, goldilocks_sub, + AIR.oneSubBooleanConstraint, AIR.activityConstraint] + · simp only [circuitEmission, AIR.circuitEmission, empty] + split <;> simp only [List.mapM_append, List.mapM_nil, queries, rankQueries, + bind, Option.bind_some, pure] + · exact returns + +theorem emitCircuit_reflects {values : Values G} (row : Nat → G) (program : Bytecode.Toplevel) + (circuit : Bytecode.Circuit) {emission : Emission} + (emitted : emitCircuit program circuit = some emission) + (reads : ∀ index < emission.readBound, (values.columns .main .current)[index]? = some (row index)) : + ∃ result, circuit.emitRow row program = some result ∧ emission.eval values = some result := by + simp only [emitCircuit, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i members membersEmitted + cases emitted + have header := fold_max_start Member.readBound members + (circuit.layout.inputSize + circuit.layout.selectors + 1 + 6) + have headerReads : ∀ index < circuit.layout.inputSize + circuit.layout.selectors + 1 + 6, + (values.columns .main .current)[index]? = some (row index) := + fun index bound => reads index (Nat.lt_of_lt_of_le bound header) + have rankEval := packSix_eval values (rankBytes circuit.layout) (AIR.circuitRankBytes row circuit.layout) + (fun index => headerReads (circuit.layout.inputSize + circuit.layout.selectors + 1 + index.val) (by omega)) + obtain ⟨results, resultsRead, resultsEval, entriesEval⟩ := emitMembers_reflects row + (circuit.layout.inputSize + circuit.layout.selectors + 1 + 6) 4 circuit.layout.inputSize program circuit.members.toList + rankEval membersEmitted (fun member present index bound => reads index + (Nat.lt_of_lt_of_le bound (fold_max_member Member.readBound present _))) + refine ⟨_, ?_, circuitEmission_eval row circuit resultsEval entriesEval headerReads⟩ + simp only [Bytecode.Circuit.emitRow, resultsRead, bind, Option.bind_some, pure] + +end Aiur.NativeAIR.CircuitEmitter diff --git a/Ix/Aiur/Proofs/CircuitRowCounts.lean b/Ix/Aiur/Proofs/CircuitRowCounts.lean new file mode 100644 index 000000000..6304c6e6e --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitRowCounts.lean @@ -0,0 +1,133 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.RowCounts + +/-! A successful circuit count check discharges all branch and terminal +count premises and the branchless single-return condition in row extraction. +Native expression reflection and the remaining layout obligations are separate. -/ + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Toplevel.validateRowCounts_circuit {program : Toplevel} + (validated : program.validateRowCounts = true) {circuit : Circuit} + (member : circuit ∈ program.circuits) : circuit.validateRowCounts program = true := by + rw [Toplevel.validateRowCounts, Array.all_eq_true'] at validated + exact validated circuit member + +private theorem mapM_of_members {α β γ : Type} (items : List α) (index : α → β) (value : α → γ) + (read : β → Option γ) (present : ∀ item ∈ items, read (index item) = some (value item)) : + (items.map index).mapM read = some (items.map value) := by + induction items with + | nil => rfl + | cons item rest ih => + simp only [List.map_cons, List.mapM_cons, present item List.mem_cons_self, + ih (fun item member => present item (List.mem_cons_of_mem _ member))] + rfl + +theorem Circuit.validateRowCounts_spec (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (validated : circuit.validateRowCounts program = true) : + circuit.members.size < gSize.toNat ∧ + (∀ part ∈ emission.members, part.function.body.controlCounts.nodes < gSize.toNat) ∧ + (emission.members.map (fun part => part.function.body.controlCounts.leaves)).sum ≤ circuit.layout.selectors := by + obtain ⟨_, indices, source⟩ := circuit.emitRow_spec row program emitted + have present := mapM_of_members emission.members (·.functionIndex) (·.function) + (fun index => program.functions[index]?) (fun part member => (source part member).present) + rw [indices] at present + rw [Circuit.validateRowCounts, present] at validated + simpa only [Bool.and_eq_true, decide_eq_true_eq, List.all_map, List.all_eq_true, + List.map_map, Function.comp_def] using validated + +private theorem flatMap_length_le_sum {α β : Type} (items : List α) (parts : α → List β) + (bound : α → Nat) (bounded : ∀ item ∈ items, (parts item).length ≤ bound item) : + (items.flatMap parts).length ≤ (items.map bound).sum := by + induction items with + | nil => exact Nat.le_refl _ + | cons first rest ih => + have head := bounded first List.mem_cons_self + have tail := ih (fun item member => bounded item (List.mem_cons_of_mem _ member)) + simp only [List.flatMap_cons, List.length_append, List.map_cons, List.sum_cons] + omega + +theorem Circuit.emitRow_count_bounds (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (validated : circuit.validateRowCounts program = true) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + circuit.members.size < gSize.toNat ∧ + (∀ part ∈ emission.members, part.function.body.rowBounds (part.selector row)) ∧ + (∀ part ∈ emission.members, + (part.function.body.selectorFlow (part.selector row)).returns.length < gSize.toNat) ∧ + (emission.branchless = true → emission.returns.length ≤ 1) := by + obtain ⟨bounded, nodes, leaves⟩ := circuit.validateRowCounts_spec row program emitted validated + refine ⟨bounded, ?_, ?_, ?_⟩ + · intro part member + exact part.function.body.rowBounds_of_controlCounts (part.selector row) (nodes part member) + · intro part member + exact part.function.body.return_bound_of_controlCounts (part.selector row) (nodes part member) + · intro branchless + obtain ⟨description, _, source⟩ := circuit.emitRow_spec row program emitted + have valid : ∀ equation ∈ (circuitEmission row circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have each : ∀ part ∈ emission.members, part.body.returns.length ≤ part.function.body.controlCounts.leaves := by + intro part member + have gates := congrArg List.length ((source part member).return_gates + (circuitEmission_member_satisfied valid member)) + simp only [List.length_map] at gates + rw [gates] + exact part.function.body.returns_le_selectors (part.selector row) + have combined := flatMap_length_le_sum emission.members (·.body.returns) + (fun part => part.function.body.controlCounts.leaves) each + have returnsEq := congrArg CircuitEmission.returns description + rw [returnsEq] + rw [description] at branchless + change circuitBranchless circuit.layout.selectors (emission.members.map (·.function)) = true at branchless + unfold circuitBranchless at branchless + rw [Bool.and_eq_true] at branchless + have one := beq_iff_eq.mp branchless.1 + change (emission.members.flatMap (·.body.returns)).length ≤ 1 + omega + +theorem Circuit.emitRow_valid_checked {tables : LookupTables} {width : Nat} {emissions : List CircuitEmission} + (global : GlobalLookups tables width (circuitQueryPool emissions)) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (member : emission ∈ emissions) + (validated : circuit.validateRowCounts program = true) + (shape : ∀ part ∈ emission.members, part.function.body.lookupShapes program none = true) + (reserved : 4 ≤ circuit.layout.lookups) + (limits : ∀ part ∈ emission.members, part.body.lookup ≤ circuit.layout.lookups) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (nonzero : emission.multiplicity ≠ 0) : + ∃ selected ∈ emission.members, ∃ interpreted : FunctionRow, + interpreted.Valid program (memoryFacts tables.memory) ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = rowValues (rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = packRank emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + padMessage width (emission.lookup 0).2 = padMessage width (functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + (interpreted.requests.map functionMessage) ⊆ circuitQueryPool emissions ∧ + (interpreted.byteQueries.map rangeMessage) ⊆ circuitQueryPool emissions := by + obtain ⟨bounded, bounds, returnBound, single⟩ := circuit.emitRow_count_bounds row program emitted validated satisfied + exact circuit.emitRow_valid global memoryValid canonical row program emitted member bounded bounds shape + returnBound reserved limits single satisfied nonzero + +end Aiur.Bytecode + +namespace Aiur.BoundVerifier + +theorem Backend.circuit_row_counts {selection : Selection} (backend : Backend selection) + {circuit : Bytecode.Circuit} (member : circuit ∈ backend.compiled.bytecode.circuits) : + circuit.validateRowCounts backend.compiled.bytecode = true := + Bytecode.Toplevel.validateRowCounts_circuit backend.rowCounts member + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/CircuitRowExecution.lean b/Ix/Aiur/Proofs/CircuitRowExecution.lean new file mode 100644 index 000000000..8bb78947b --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitRowExecution.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitPoolExecution + +/-! +A nonzero provider row of the valued circuit model yields a valid +function row from the same bytecode program. The interpreted inputs, rank +bytes and multiplicity agree with the circuit, and its padded provider +message names that same semantic call. All selected call and rank-byte +queries belong to the computed circuit pool. + +Exact global lookup balance, memory validity, shape and count/layout bounds +remain explicit. This is not yet extraction from native public verification. +-/ + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitRow_valid {tables : LookupTables} {width : Nat} {emissions : List CircuitEmission} + (global : GlobalLookups tables width (circuitQueryPool emissions)) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (member : emission ∈ emissions) + (bounded : circuit.members.size < gSize.toNat) + (bounds : ∀ part ∈ emission.members, part.function.body.rowBounds (part.selector row)) + (shape : ∀ part ∈ emission.members, part.function.body.lookupShapes program none = true) + (returnBound : ∀ part ∈ emission.members, + (part.function.body.selectorFlow (part.selector row)).returns.length < gSize.toNat) + (reserved : 4 ≤ circuit.layout.lookups) + (limits : ∀ part ∈ emission.members, part.body.lookup ≤ circuit.layout.lookups) + (single : emission.branchless = true → emission.returns.length ≤ 1) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (nonzero : emission.multiplicity ≠ 0) : + ∃ selected ∈ emission.members, ∃ interpreted : FunctionRow, + interpreted.Valid program (memoryFacts tables.memory) ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = rowValues (rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = packRank emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + padMessage width (emission.lookup 0).2 = padMessage width (functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + (interpreted.requests.map functionMessage) ⊆ circuitQueryPool emissions ∧ + (interpreted.byteQueries.map rangeMessage) ⊆ circuitQueryPool emissions := by + exact circuit.emitRow_valid_in_pool global memoryValid canonical row program emitted member + (List.Subset.refl _) bounded bounds shape returnBound reserved limits single satisfied nonzero + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/CircuitRowMembers.lean b/Ix/Aiur/Proofs/CircuitRowMembers.lean new file mode 100644 index 000000000..57f34166b --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitRowMembers.lean @@ -0,0 +1,203 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRows + +/-! +Successful circuit emission retains the actual program functions and +member selector offsets. Satisfying header and body equations make the +circuit selector boolean. Nonzero provider multiplicity selects an active +member under the explicit member-count bound. +-/ + +namespace Aiur.AIR +open Bytecode + +structure MemberEmission.FromProgram (row : Nat → G) (rank : G) (column lookup : Nat) + (program : Toplevel) (member : MemberEmission) : Prop where + present : program.functions[member.functionIndex]? = some member.function + emitted : member.function.emitRow row (member.selector row) member.functionIndex rank + (rowAdvice row 0 member.function.layout.inputSize) column lookup = some member.body + +theorem emitMember_spec (row : Nat → G) (rank : G) (column lookup selectorBase : Nat) + (program : Toplevel) (functionIndex : FunIdx) {member : MemberEmission} + (emitted : emitMember row rank column lookup selectorBase program functionIndex = some member) : + member.functionIndex = functionIndex ∧ member.selectorBase = selectorBase ∧ + member.FromProgram row rank column lookup program := by + simp only [emitMember, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i function present + dsimp only at emitted + split at emitted + · cases emitted + · rename_i body bodyEmitted + have equal := Option.some.inj emitted + subst member + exact ⟨rfl, rfl, present, bodyEmitted⟩ + +theorem emitMembers_spec (row : Nat → G) (rank : G) (column lookup selectorBase : Nat) + (program : Toplevel) (indices : List FunIdx) {members : List MemberEmission} + (emitted : emitMembers row rank column lookup selectorBase program indices = some members) : + members.map MemberEmission.functionIndex = indices ∧ + ∀ member ∈ members, member.FromProgram row rank column lookup program := by + induction indices generalizing selectorBase members with + | nil => + have equal := Option.some.inj emitted + subst members + exact ⟨rfl, by simp⟩ + | cons index indices ih => + simp only [emitMembers, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i member memberEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i rest restEmitted + have equal := Option.some.inj emitted + subst members + obtain ⟨indexEq, _, first⟩ := emitMember_spec row rank column lookup selectorBase program index memberEmitted + obtain ⟨indicesEq, remaining⟩ := ih _ restEmitted + refine ⟨by rw [List.map_cons, indexEq, indicesEq], ?_⟩ + intro item present + rcases List.mem_cons.mp present with equal | tail + · subst item + exact first + · exact remaining item tail + +theorem MemberEmission.FromProgram.selector_satisfied {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : + (member.function.body.selectorFlow (member.selector row)).Satisfied := by + have emitted := source.emitted + rw [Bytecode.Function.emitRow] at emitted + exact member.function.body.emitRow_selectors row (member.selector row) _ _ _ _ _ emitted satisfied + +theorem circuitEmission_member_satisfied {row : Nat → G} {circuit : Circuit} {members : List MemberEmission} + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) + {member : MemberEmission} (present : member ∈ members) : + ∀ equation ∈ member.body.equations, equation = 0 := by + intro equation member + apply satisfied equation + exact List.mem_append_left _ (List.mem_append_left _ (List.mem_append_left _ + (List.mem_flatMap.mpr ⟨_, present, member⟩))) + +theorem circuitEmission_activity {row : Nat → G} {circuit : Circuit} {members : List MemberEmission} + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) : + activityConstraint (circuitEmission row circuit members).multiplicity + (circuitEmission row circuit members).selector = 0 := + satisfied _ (List.mem_append_right _ List.mem_cons_self) + +theorem circuitEmission_member_boolean {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromProgram row rank column lookup program) + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) : + ∀ member ∈ members, booleanConstraint (member.entry row) = 0 := by + intro member present + exact member.function.body.selectorFlow_boolean (member.selector row) + ((source member present).selector_satisfied (circuitEmission_member_satisfied satisfied present)) + +theorem circuitEmission_boolean {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromProgram row rank column lookup program) + (count : members.length = circuit.members.size) + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) : + booleanConstraint (circuitEmission row circuit members).selector = 0 := by + by_cases grouped : 1 < circuit.members.size + · have constraint : oneSubBooleanConstraint (circuitEmission row circuit members).selector = 0 := by + apply satisfied _ + apply List.mem_append_left + apply List.mem_append_right + simp only [if_pos grouped] + exact List.mem_cons_self + rcases G.boolean_of_one_sub_constraint constraint with inactive | active + · rw [inactive]; rfl + · rw [active]; rfl + · have bounded : members.length ≤ 1 := by omega + cases members with + | nil => + change booleanConstraint 0 = 0 + rw [booleanConstraint, G.mul_comm, G.mul_zero] + | cons member rest => + have empty : rest = [] := List.length_eq_zero_iff.mp (by simp only [List.length_cons] at bounded; omega) + subst rest + have boolean := circuitEmission_member_boolean source satisfied member List.mem_cons_self + change booleanConstraint (selectorSum [member.entry row]) = 0 + rw [selectorSum_cons] + change booleanConstraint (member.entry row + 0) = 0 + rw [G.add_zero] + exact boolean + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitRow_spec (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) : + emission = circuitEmission row circuit emission.members ∧ + emission.members.map MemberEmission.functionIndex = circuit.members.toList ∧ + ∀ member ∈ emission.members, + member.FromProgram row (packRank (circuitRankBytes row circuit.layout)) + (circuit.layout.inputSize + circuit.layout.selectors + 1 + 6) 4 program := by + simp only [Circuit.emitRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i members membersEmitted + have equal := Option.some.inj emitted + subst emission + obtain ⟨indices, source⟩ := emitMembers_spec row _ _ _ _ program _ membersEmitted + exact ⟨rfl, indices, source⟩ + +theorem Circuit.emitRow_boolean (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + booleanConstraint emission.selector = 0 := by + obtain ⟨description, indices, source⟩ := circuit.emitRow_spec row program emitted + have count := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at count + have valid : ∀ equation ∈ (circuitEmission row circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have boolean := circuitEmission_boolean source count valid + rw [← description] at boolean + exact boolean + +theorem Circuit.emitRow_active_member (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (bounded : circuit.members.size < gSize.toNat) (nonzero : emission.multiplicity ≠ 0) : + ∃ member ∈ emission.members, member.entry row = 1 ∧ + member.FromProgram row (packRank emission.rankBytes) + (circuit.layout.inputSize + circuit.layout.selectors + 1 + 6) 4 program := by + obtain ⟨description, indices, source⟩ := circuit.emitRow_spec row program emitted + have length := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at length + have valid : ∀ equation ∈ (circuitEmission row circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have activity := circuitEmission_activity valid + rw [← description] at activity + have active := nonzero_multiplicity_selector_one activity nonzero + have individual := circuitEmission_member_boolean source valid + have selectorEq := congrArg CircuitEmission.selector description + have count := selectorSum_active_count + (selectors := emission.members.map (fun member : MemberEmission => member.entry row)) + (fun gate member => by + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst gate + exact individual part partMember) + (by simpa only [List.length_map, length] using bounded) + (show selectorSum (emission.members.map (fun member => member.entry row)) = 1 from selectorEq.symm.trans active) + have existsOne : (1 : G) ∈ emission.members.map (·.entry row) := + List.count_pos_iff.mp (Nat.lt_of_lt_of_eq (by decide : 0 < 1) count.symm) + obtain ⟨member, present, selected⟩ := List.mem_map.mp existsOne + refine ⟨member, present, selected, ?_⟩ + have rankEq := congrArg CircuitEmission.rankBytes description + rw [rankEq] + exact source member present + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/CircuitRowQueries.lean b/Ix/Aiur/Proofs/CircuitRowQueries.lean new file mode 100644 index 000000000..7cd70664e --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitRowQueries.lean @@ -0,0 +1,170 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRowMembers + +/-! +Shared-slot extraction across circuit members and the three reserved +rank-byte lookup slots. Validated body bounds and lookup cursor limits give +one active query per physical slot and a computed circuit query pool. +Native layout enforcement and verifier-to-valued-model reflection remain +separate. +-/ + +namespace Aiur.AIR +open Bytecode + +theorem QuerySlots.extend {gate : G} {start finish limit : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (bound : finish ≤ limit) : + QuerySlots gate start limit queries := + ⟨Nat.le_trans slots.extent bound, + fun query member => ⟨(slots.range query member).1, Nat.lt_of_lt_of_le (slots.range query member).2 bound⟩, + slots.boolean, slots.count⟩ + +theorem QuerySlots.permuted {gate : G} {start finish : Nat} {queries other : List QueryPart} + (slots : QuerySlots gate start finish queries) (permutation : queries.Perm other) : + QuerySlots gate start finish other := by + refine ⟨slots.extent, ?_, ?_, ?_⟩ + · exact fun query member => slots.range query (permutation.mem_iff.mpr member) + · exact fun query member => slots.boolean query (permutation.mem_iff.mpr member) + · intro slot + have counts : queryCount queries slot = queryCount other slot := (permutation.filter _).length_eq + rw [← counts] + exact slots.count slot + +theorem fold_lookup_upper (emissions : List BlockEmission) (start limit : Nat) + (initial : start ≤ limit) (bounded : ∀ emission ∈ emissions, emission.lookup ≤ limit) : + emissions.foldl (fun current emission => max current emission.lookup) start ≤ limit := by + induction emissions generalizing start with + | nil => exact initial + | cons emission rest ih => + apply ih + · exact Nat.max_le.mpr ⟨initial, bounded emission List.mem_cons_self⟩ + · exact fun item member => bounded item (List.mem_cons_of_mem _ member) + +theorem forall₂_self_map {α β : Type} (items : List α) (map : α → β) (relation : α → β → Prop) + (related : ∀ item ∈ items, relation item (map item)) : List.Forall₂ relation items (items.map map) := by + induction items with + | nil => exact .nil + | cons item rest ih => + exact .cons (related item List.mem_cons_self) (ih (fun item member => related item (List.mem_cons_of_mem _ member))) + +theorem MemberEmission.FromProgram.querySlots {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + (bounds : member.function.body.rowBounds (member.selector row)) + (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : + QuerySlots (member.entry row) lookup member.body.lookup member.body.queries := by + have emitted := source.emitted + rw [Bytecode.Function.emitRow] at emitted + exact member.function.body.emitRow_equation_querySlots row (member.selector row) _ _ _ _ _ bounds emitted rfl satisfied + +theorem circuitEmission_querySlots {row : Nat → G} {rank : G} {column : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromProgram row rank column 4 program) + (count : members.length = circuit.members.size) + (bounded : circuit.members.size < gSize.toNat) + (bounds : ∀ member ∈ members, member.function.body.rowBounds (member.selector row)) + (reserved : 4 ≤ circuit.layout.lookups) + (limits : ∀ member ∈ members, member.body.lookup ≤ circuit.layout.lookups) + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) : + QuerySlots (circuitEmission row circuit members).selector 1 circuit.layout.lookups + (circuitEmission row circuit members).queries := by + by_cases empty : members = [] + · subst members + exact (QuerySlots.empty 0 1).extend (by omega) + have nonempty : members.isEmpty = false := by cases members <;> simp_all + have boolean := circuitEmission_boolean source count satisfied + have individual := circuitEmission_member_boolean source satisfied + have slots : ∀ member ∈ members, QuerySlots (member.entry row) 4 member.body.lookup member.body.queries := + fun member present => (source member present).querySlots (bounds member present) + (circuitEmission_member_satisfied satisfied present) + have related := forall₂_self_map members MemberEmission.body + (fun member body => QuerySlots (member.entry row) 4 body.lookup body.queries) slots + have selectorCount := selector_gateCount + (gates := members.map (fun member : MemberEmission => member.entry row)) + (fun gate member => by + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst gate + exact individual part partMember) + (by simpa only [List.length_map, count] using bounded) boolean + have joined := QuerySlots.join (fun member : MemberEmission => member.entry row) + (circuitEmission row circuit members).selector #[] 0 4 related (Nat.le_of_eq selectorCount) + have upper : (joinBlockEmissions #[] 0 4 (members.map MemberEmission.body)).lookup ≤ circuit.layout.lookups := by + apply fold_lookup_upper _ _ _ reserved + intro body member + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst body + exact limits part partMember + have bodies := joined.extend upper + have rankSlots : QuerySlots (circuitEmission row circuit members).selector 1 4 + (queryParts 1 (circuitEmission row circuit members).selector + ((rankByteQueries (circuitRankBytes row circuit.layout)).map rangeMessage)) := + QuerySlots.indexed _ 1 ((rankByteQueries (circuitRankBytes row circuit.layout)).map rangeMessage) boolean + have combined := (rankSlots.append bodies).permuted List.perm_append_comm + simpa only [joinBlockEmissions, List.flatMap_map, Function.comp_def, circuitEmission, + nonempty, Bool.false_eq_true, if_false] using combined + +def CircuitEmission.QueriesIn (emission : CircuitEmission) (queries : List (List G)) : Prop := + ∀ part ∈ emission.queries, part.selector = 1 → part.message ∈ queries + +def circuitQueryPool (emissions : List CircuitEmission) : List (List G) := + emissions.flatMap fun emission => decodedQueries emission.queries emission.lookupCount + +theorem QuerySlots.circuit_pool {emission : CircuitEmission} + (slots : QuerySlots emission.selector 1 emission.lookupCount emission.queries) + {emissions : List CircuitEmission} (member : emission ∈ emissions) : + emission.QueriesIn (circuitQueryPool emissions) := by + intro query present active + exact List.mem_flatMap.mpr ⟨emission, member, slots.decoded_member present active⟩ + +theorem circuitEmission_member_queried {row : Nat → G} {circuit : Circuit} {members : List MemberEmission} + {queries : List (List G)} (queried : (circuitEmission row circuit members).QueriesIn queries) + {member : MemberEmission} (present : member ∈ members) : member.body.QueriesIn queries := by + intro query member active + exact queried query (List.mem_append_left _ (List.mem_flatMap.mpr ⟨_, present, member⟩)) active + +theorem circuitEmission_rank_queried {row : Nat → G} {circuit : Circuit} {members : List MemberEmission} + {queries : List (List G)} (queried : (circuitEmission row circuit members).QueriesIn queries) + (active : (circuitEmission row circuit members).selector = 1) : + (rankByteQueries (circuitEmission row circuit members).rankBytes).map rangeMessage ⊆ queries := by + have nonempty : members.isEmpty = false := by + cases members with + | nil => exact False.elim (G.one_ne_zero active.symm) + | cons => rfl + simp only [CircuitEmission.QueriesIn, circuitEmission, nonempty, Bool.false_eq_true, if_false] at queried + intro message member + obtain ⟨part, partMember, selectorEq, messageEq⟩ := + queryParts_member 1 (circuitEmission row circuit members).selector member + have result := queried part (List.mem_append_right _ partMember) (selectorEq.trans active) + rw [messageEq] at result + exact result + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitRow_querySlots (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (bounded : circuit.members.size < gSize.toNat) + (bounds : ∀ member ∈ emission.members, member.function.body.rowBounds (member.selector row)) + (reserved : 4 ≤ circuit.layout.lookups) + (limits : ∀ member ∈ emission.members, member.body.lookup ≤ circuit.layout.lookups) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + QuerySlots emission.selector 1 emission.lookupCount emission.queries := by + obtain ⟨description, indices, source⟩ := circuit.emitRow_spec row program emitted + have count := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at count + have valid : ∀ equation ∈ (circuitEmission row circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have slots := circuitEmission_querySlots source count bounded bounds reserved limits valid + have lookupEq := congrArg CircuitEmission.lookupCount description + change emission.lookupCount = circuit.layout.lookups at lookupEq + rw [← lookupEq] at slots + rw [← description] at slots + exact slots + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/CircuitRowReturns.lean b/Ix/Aiur/Proofs/CircuitRowReturns.lean new file mode 100644 index 000000000..77ed1e5df --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitRowReturns.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRowQueries + +/-! +The combined circuit return slot encodes the selected semantic return. +Per-function selector conservation and return-count bounds compose across +grouped members without an extra bound on the total inactive return count. +The single-writer premise for the ungated branchless optimization is explicit. +-/ + +namespace Aiur.AIR +open Bytecode + +theorem MemberEmission.FromProgram.return_gates {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : + member.body.returns.map Prod.fst = (member.function.body.selectorFlow (member.selector row)).returns := by + have emitted := source.emitted + rw [Bytecode.Function.emitRow] at emitted + have projected := member.function.body.emitRow_projection row (member.selector row) _ _ _ _ _ emitted + exact projected.returned.trans (member.function.body.returnGates_reflects (member.selector row) _ + (source.selector_satisfied satisfied) rfl) + +theorem MemberEmission.FromProgram.return_boolean {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : + ∀ part ∈ member.body.returns, booleanConstraint part.1 = 0 := by + intro part present + have sound := member.function.body.selectorFlow_sound (member.selector row) (source.selector_satisfied satisfied) + apply sound.returned part.1 + rw [← source.return_gates satisfied] + exact List.mem_map.mpr ⟨part, present, rfl⟩ + +theorem MemberEmission.FromProgram.return_count {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + (shape : member.function.body.lookupShapes program none = true) + (bounded : (member.function.body.selectorFlow (member.selector row)).returns.length < gSize.toNat) + (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : + (member.body.returns.map Prod.fst).count 1 = gateCount (member.entry row) := by + have valid := source.selector_satisfied satisfied + have sound := member.function.body.selectorFlow_sound (member.selector row) valid + have empty := member.function.body.selectorFlow_yields_empty (member.selector row) program shape + have conservation := sound.conservation + rw [empty] at conservation + change _ = selectorSum (member.function.body.selectorFlow (member.selector row)).returns + 0 at conservation + rw [G.add_zero] at conservation + rw [source.return_gates satisfied, MemberEmission.entry, conservation] + apply selector_gateCount sound.returned bounded + rw [← conservation] + exact member.function.body.selectorFlow_boolean (member.selector row) valid + +theorem flatMap_return_count {α β : Type} (items : List α) (gate : α → G) (parts : α → List (G × β)) + (count : ∀ item ∈ items, ((parts item).map Prod.fst).count 1 = gateCount (gate item)) : + ((items.flatMap parts).map Prod.fst).count 1 = (items.map gate).count 1 := by + have summed : ((items.flatMap parts).map Prod.fst).count 1 = ((items.map gate).map gateCount).sum := by + induction items with + | nil => rfl + | cons item rest ih => + rw [List.flatMap_cons, List.map_append, List.count_append, count item List.mem_cons_self, + ih (fun item member => count item (List.mem_cons_of_mem _ member))] + rfl + exact summed.trans (gateCount_list _) + +theorem circuitEmission_return_count {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromProgram row rank column lookup program) + (shape : ∀ member ∈ members, member.function.body.lookupShapes program none = true) + (bounded : members.length < gSize.toNat) + (returnBound : ∀ member ∈ members, + (member.function.body.selectorFlow (member.selector row)).returns.length < gSize.toNat) + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) + (active : (circuitEmission row circuit members).selector = 1) : + ((circuitEmission row circuit members).returns.map Prod.fst).count 1 = 1 := by + have each := fun member present => (source member present).return_count (shape member present) + (returnBound member present) (circuitEmission_member_satisfied satisfied present) + change ((members.flatMap (·.body.returns)).map Prod.fst).count 1 = 1 + rw [flatMap_return_count members (fun member => member.entry row) (fun member => member.body.returns) each] + have individual := circuitEmission_member_boolean source satisfied + apply selectorSum_active_count + · intro gate member + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst gate + exact individual part partMember + · simpa only [List.length_map] using bounded + · exact active + +theorem circuitEmission_return_message {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromProgram row rank column lookup program) + (shape : ∀ member ∈ members, member.function.body.lookupShapes program none = true) + (bounded : members.length < gSize.toNat) + (returnBound : ∀ member ∈ members, + (member.function.body.selectorFlow (member.selector row)).returns.length < gSize.toNat) + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) + (active : (circuitEmission row circuit members).selector = 1) + (width : Nat) + (single : (circuitEmission row circuit members).branchless = true → + (circuitEmission row circuit members).returns.length ≤ 1) + {request : Bytecode.AIR.Call} (present : (1, request) ∈ (circuitEmission row circuit members).returns) : + padMessage width ((circuitEmission row circuit members).lookup 0).2 = padMessage width (functionMessage request) := by + have count := circuitEmission_return_count source shape bounded returnBound satisfied active + apply slotMessage_chosen_count width (circuitEmission row circuit members).branchless + (by simpa only [List.length_map] using single) + (fun part member => ?_) + (by simpa only [List.map_map, Function.comp_def] using count) + (List.mem_map.mpr ⟨(1, request), present, rfl⟩) rfl + obtain ⟨returned, returnMember, equal⟩ := List.mem_map.mp member + subst part + obtain ⟨body, bodyMember, returnedMember⟩ := List.mem_flatMap.mp returnMember + exact (source body bodyMember).return_boolean (circuitEmission_member_satisfied satisfied bodyMember) + returned returnedMember + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/CircuitRows.lean b/Ix/Aiur/Proofs/CircuitRows.lean new file mode 100644 index 000000000..1e5d1dd20 --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitRows.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockQueryPool +import Ix.Aiur.Branchless + +/-! +A valued model of the complete native function-circuit builder. Grouped +members share auxiliary columns, rank bytes, multiplicity and lookup slots, +while their selector columns occupy consecutive regions. The model retains +the native header equations and provider-message combination on arbitrary +assignments. Native expression/codec reflection and layout validity remain +separate obligations. +-/ + +namespace Aiur.AIR +open Bytecode + +structure MemberEmission where + functionIndex : FunIdx + function : Function + selectorBase : Nat + body : BlockEmission + +def MemberEmission.selector (row : Nat → G) (member : MemberEmission) : SelIdx → G := + fun index => row (member.selectorBase + index) + +def MemberEmission.entry (row : Nat → G) (member : MemberEmission) : G := + (member.function.body.selectorFlow (member.selector row)).entry + +def emitMember (row : Nat → G) (rank : G) (column lookup selectorBase : Nat) + (program : Toplevel) (functionIndex : FunIdx) : Option MemberEmission := do + let function ← program.functions[functionIndex]? + let body ← function.emitRow row (fun index => row (selectorBase + index)) functionIndex rank + (rowAdvice row 0 function.layout.inputSize) column lookup + return ⟨functionIndex, function, selectorBase, body⟩ + +def emitMembers (row : Nat → G) (rank : G) (column lookup selectorBase : Nat) + (program : Toplevel) : List FunIdx → Option (List MemberEmission) + | [] => some [] + | index :: indices => do + let member ← emitMember row rank column lookup selectorBase program index + let rest ← emitMembers row rank column lookup (selectorBase + member.function.layout.selectors) program indices + return member :: rest + +structure CircuitEmission where + members : List MemberEmission + selector : G + multiplicity : G + rankBytes : Fin 6 → G + width : Nat + selectorStart : Nat + selectorCount : Nat + lookupCount : Nat + branchless : Bool + equations : List G + queries : List QueryPart + returns : List (G × Bytecode.AIR.Call) + +def circuitRankBytes (row : Nat → G) (layout : Bytecode.FunctionLayout) : Fin 6 → G := + fun index => row (layout.inputSize + layout.selectors + 1 + index.val) + +def circuitEmission (row : Nat → G) (circuit : Circuit) (members : List MemberEmission) : CircuitEmission := + let selector := selectorSum (members.map (·.entry row)) + let multiplicity := row (circuit.layout.inputSize + circuit.layout.selectors) + let rankBytes := circuitRankBytes row circuit.layout + { members, selector, multiplicity, rankBytes + width := circuit.layout.width + selectorStart := circuit.layout.inputSize + selectorCount := circuit.layout.selectors + lookupCount := circuit.layout.lookups + branchless := circuitBranchless circuit.layout.selectors (members.map (·.function)) + equations := members.flatMap (·.body.equations) ++ + (List.range circuit.layout.selectors).map (fun index => booleanConstraint (row (circuit.layout.inputSize + index))) ++ + (if 1 < circuit.members.size then [oneSubBooleanConstraint selector] else []) ++ + [activityConstraint multiplicity selector] + queries := members.flatMap (·.body.queries) ++ + (if members.isEmpty then [] else + queryParts 1 selector ((rankByteQueries rankBytes).map rangeMessage)) + returns := members.flatMap (·.body.returns) } + +def CircuitEmission.lookup (emission : CircuitEmission) (slot : Nat) : G × List G := + if slot = 0 then + (0 - emission.multiplicity, + slotMessage emission.branchless (emission.returns.map fun part => (part.1, functionMessage part.2))) + else + (querySlotMultiplicity emission.queries slot, + slotMessage emission.branchless (querySlotParts emission.queries slot)) + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +def Circuit.emitRow (row : Nat → G) (program : Toplevel) (circuit : Circuit) : Option CircuitEmission := do + let rank := packRank (circuitRankBytes row circuit.layout) + let column := circuit.layout.inputSize + circuit.layout.selectors + 1 + 6 + let members ← emitMembers row rank column 4 circuit.layout.inputSize program circuit.members.toList + return circuitEmission row circuit members + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/CircuitTableData.lean b/Ix/Aiur/Proofs/CircuitTableData.lean new file mode 100644 index 000000000..6fd625f9c --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitTableData.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ProviderEquivalence + +/-! Physical circuit providers, auxiliary tables and witness assignments. +Provider-only function rows initialize lookup extraction; their local validity +is not assumed. Zero-weight rows can be represented by a valid inactive row. -/ + +namespace Aiur.AIR +open Bytecode + +/-- Memory and fixed byte tables before any function-row interpretation. -/ +structure AuxiliaryTables where + memoryWidths : List Nat + memory : Nat → Array MemoryRow + byte1 : Byte1Kind → Fin 256 → G + byte2 : Byte2Kind → Fin 65536 → G + +def AuxiliaryTables.withFunctions (tables : AuxiliaryTables) (functions : List FunctionRow) : LookupTables := + ⟨functions, tables.memoryWidths, tables.memory, tables.byte1, tables.byte2⟩ + +def AuxiliaryTables.providers (tables : AuxiliaryTables) : List (Provider (List G)) := + tables.memoryWidths.flatMap (fun width => + mapProviders (fun request => memoryMessage width request.1 request.2) + (memoryProviders (tables.memory width))) ++ + byte1Providers tables.byte1 ++ byte2Providers tables.byte2 + +def circuitProviders (emissions : List CircuitEmission) : List (Provider (List G)) := + emissions.map CircuitEmission.provider + +def AuxiliaryTables.circuitProviders (tables : AuxiliaryTables) (emissions : List CircuitEmission) : + List (Provider (List G)) := Aiur.AIR.circuitProviders emissions ++ tables.providers + +theorem AuxiliaryTables.withFunctions_providers (tables : AuxiliaryTables) (functions : List FunctionRow) : + (tables.withFunctions functions).providers = + mapProviders functionMessage (functionProviders functions) ++ tables.providers := by + simp only [withFunctions, LookupTables.providers, providers, List.append_assoc] + +def FunctionRow.Provides (width : Nat) (emission : CircuitEmission) (row : FunctionRow) : Prop := + Provider.PaddedEq width emission.provider (functionMessage row.request, row.multiplicity) + +theorem AuxiliaryTables.providers_related (tables : AuxiliaryTables) {width : Nat} + {emissions : List CircuitEmission} {functions : List FunctionRow} + (related : List.Forall₂ (FunctionRow.Provides width) emissions functions) : + List.Forall₂ (Provider.PaddedEq width) (tables.circuitProviders emissions) + (tables.withFunctions functions).providers := by + rw [tables.withFunctions_providers] + apply forall₂_append + · induction related with + | nil => exact .nil + | cons first rest ih => exact .cons first ih + · exact paddedProviders_refl width tables.providers + +theorem AuxiliaryTables.global_of_circuit_balance (tables : AuxiliaryTables) + {width : Nat} {queries : List (List G)} {emissions : List CircuitEmission} + {functions : List FunctionRow} + (balanced : PaddedLookupBalance width queries (tables.circuitProviders emissions)) + (bounded : queries.length < gSize.toNat) + (widths : ∀ query ∈ queries, query.length ≤ width) + (related : List.Forall₂ (FunctionRow.Provides width) emissions functions) : + GlobalLookups (tables.withFunctions functions) width queries := + ⟨balanced.congr_providers (tables.providers_related related), bounded, widths⟩ + +def FunctionRow.inactive : FunctionRow := + ⟨⟨0, #[], #[], 0⟩, [], fun _ => 0, 0, 0⟩ + +theorem FunctionRow.inactive_valid (program : Toplevel) (memory : Bytecode.AIR.Memory) : + inactive.Valid program memory := by + have notActive : inactive.selector ≠ 1 := by + intro equal + have bad := congrArg G.n equal + change 0 = 1 at bad + omega + refine ⟨Or.inl rfl, ?_, fun active => False.elim (notActive active), + fun active => False.elim (notActive active), ?_⟩ + · change (0 : G) * (1 - 0) = 0 + rw [G.mul_comm, G.mul_zero] + · intro edge member + cases member + +theorem FunctionRow.inactive_provides (width : Nat) {emission : CircuitEmission} + (zero : emission.multiplicity = 0) : Provides width emission inactive := + ⟨zero, fun nonzero => False.elim (nonzero zero)⟩ + +theorem forall₂_exists_right {α β : Type} (source : List α) (relation : α → β → Prop) + (available : ∀ item ∈ source, ∃ value, relation item value) : + ∃ target, List.Forall₂ relation source target := by + induction source with + | nil => exact ⟨[], .nil⟩ + | cons first rest ih => + obtain ⟨value, firstRelated⟩ := available first List.mem_cons_self + obtain ⟨values, restRelated⟩ := ih (fun item member => available item (List.mem_cons_of_mem _ member)) + exact ⟨value :: values, .cons firstRelated restRelated⟩ + +/-- One valued row, retaining the selected circuit and the assignment used +by its emitter. Membership, successful emission and satisfaction are proved +separately when extracting a trace. -/ +structure CircuitWitness where + circuit : Circuit + values : Nat → G + emission : CircuitEmission + +def CircuitWitness.Emitted (program : Toplevel) (witness : CircuitWitness) : Prop := + witness.circuit.emitRow witness.values program = some witness.emission + +def CircuitWitness.Satisfied (witness : CircuitWitness) : Prop := + ∀ equation ∈ witness.emission.equations, equation = 0 + +def CircuitWitness.Shapes (program : Toplevel) (witness : CircuitWitness) : Prop := + ∀ part ∈ witness.emission.members, part.function.body.lookupShapes program none = true + +def CircuitWitness.LookupBounds (witness : CircuitWitness) : Prop := + 4 ≤ witness.circuit.layout.lookups ∧ + ∀ part ∈ witness.emission.members, part.body.lookup ≤ witness.circuit.layout.lookups + +theorem CircuitWitness.provider_row {program : Toplevel} (witness : CircuitWitness) + (emitted : witness.Emitted program) (satisfied : witness.Satisfied) + (validated : witness.circuit.validateRowCounts program = true) (shape : witness.Shapes program) + (width : Nat) : ∃ row : FunctionRow, row.Provides width witness.emission := by + by_cases zero : witness.emission.multiplicity = 0 + · exact ⟨FunctionRow.inactive, FunctionRow.inactive_provides width zero⟩ + · obtain ⟨request, _, message⟩ := witness.circuit.emitRow_provider witness.values program + emitted validated shape satisfied zero width + exact ⟨⟨request, [], witness.emission.rankBytes, 0, witness.emission.multiplicity⟩, + rfl, fun _ => message⟩ + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/CircuitTableExecution.lean b/Ix/Aiur/Proofs/CircuitTableExecution.lean new file mode 100644 index 000000000..f4a1e2e85 --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitTableExecution.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitTableData + +/-! Construct locally valid function rows from valued circuit witnesses and +physical provider balance, then derive finite call executions. The two-stage +construction avoids assuming the validity of the table being extracted. +Native extraction and the explicit layout/shape conditions remain separate. -/ + +namespace Aiur.AIR +open Bytecode + +private theorem forall₂_weaken {α β : Type} {left : List α} {right : List β} + {first second : α → β → Prop} (related : List.Forall₂ first left right) + (weaken : ∀ a b, first a b → second a b) : List.Forall₂ second left right := by + induction related with + | nil => exact .nil + | cons head tail ih => exact .cons (weaken _ _ head) ih + +def FunctionRow.QueriesIn (queries : List (List G)) (row : FunctionRow) : Prop := + row.selector = 1 → row.requests.map functionMessage ⊆ queries ∧ row.byteQueries.map rangeMessage ⊆ queries + +theorem FunctionRow.inactive_queried (queries : List (List G)) : inactive.QueriesIn queries := by + intro active + have bad := congrArg G.n active + change 0 = 1 at bad + omega + +theorem CircuitWitness.interpreted_row {tables : LookupTables} {width : Nat} + {queries : List (List G)} {emissions : List CircuitEmission} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + {program : Toplevel} (witness : CircuitWitness) + (emitted : witness.Emitted program) (satisfied : witness.Satisfied) + (validated : witness.circuit.validateRowCounts program = true) (shape : witness.Shapes program) + (limits : witness.LookupBounds) (member : witness.emission ∈ emissions) + (pooled : circuitQueryPool emissions ⊆ queries) : + ∃ row : FunctionRow, row.Valid program (memoryFacts tables.memory) ∧ + row.Provides width witness.emission ∧ row.QueriesIn queries := by + by_cases zero : witness.emission.multiplicity = 0 + · exact ⟨FunctionRow.inactive, FunctionRow.inactive_valid _ _, + FunctionRow.inactive_provides width zero, FunctionRow.inactive_queried queries⟩ + · obtain ⟨bounded, bounds, returnBound, single⟩ := witness.circuit.emitRow_count_bounds + witness.values program emitted validated satisfied + obtain ⟨_, _, row, valid, _, _, _, _, _, multiplicity, _, message, _, called, bytes⟩ := + witness.circuit.emitRow_valid_in_pool global memoryValid canonical witness.values program + emitted member pooled bounded bounds shape returnBound limits.1 limits.2 single satisfied zero + exact ⟨row, valid, ⟨multiplicity.symm, fun _ => message⟩, fun _ => ⟨called, bytes⟩⟩ + +theorem functionQueries_in_pool {queries : List (List G)} {roots : List Bytecode.AIR.Call} + {rows : List FunctionRow} (rootQueries : roots.map functionMessage ⊆ queries) + (queried : ∀ row ∈ rows, row.QueriesIn queries) : + (functionQueries roots rows).map functionMessage ⊆ queries := by + intro message member + obtain ⟨request, requestMember, equal⟩ := List.mem_map.mp member + subst message + rcases List.mem_append.mp requestMember with root | called + · exact rootQueries (List.mem_map.mpr ⟨request, root, rfl⟩) + · obtain ⟨row, rowMember, callMember⟩ := List.mem_flatMap.mp called + by_cases active : row.selector = 1 + · rw [if_pos active] at callMember + exact (queried row rowMember active).1 (List.mem_map.mpr ⟨request, callMember, rfl⟩) + · rw [if_neg active] at callMember + cases callMember + +theorem functionByteQueries_in_pool {queries : List (List G)} {rows : List FunctionRow} + (queried : ∀ row ∈ rows, row.QueriesIn queries) : + (functionByteQueries rows).map rangeMessage ⊆ queries := by + intro message member + obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp member + subst message + obtain ⟨row, rowMember, queryMember⟩ := List.mem_flatMap.mp pairMember + by_cases active : row.selector = 1 + · rw [if_pos active] at queryMember + exact (queried row rowMember active).2 (List.mem_map.mpr ⟨pair, queryMember, rfl⟩) + · rw [if_neg active] at queryMember + cases queryMember + +/-- Construct locally valid function rows from the complete circuit witness +list. The input balance names only physical circuit providers and auxiliary +tables. Function-row validity is a conclusion, not an input. -/ +theorem circuitWitnesses_interpret (tables : AuxiliaryTables) {program : Toplevel} + (witnesses : List CircuitWitness) {width : Nat} {queries : List (List G)} + (balanced : PaddedLookupBalance width queries (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : queries.length < gSize.toNat) (widths : ∀ query ∈ queries, query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (counted : program.validateRowCounts = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.Emitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes program) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) + (pooled : circuitQueryPool (witnesses.map (·.emission)) ⊆ queries) : + ∃ functions : List FunctionRow, + List.Forall₂ (FunctionRow.Provides width) (witnesses.map (·.emission)) functions ∧ + GlobalLookups (tables.withFunctions functions) width queries ∧ + (∀ row ∈ functions, row.Valid program (memoryFacts tables.memory)) ∧ + (∀ row ∈ functions, row.QueriesIn queries) := by + have counts := fun witness member => Toplevel.validateRowCounts_circuit counted (circuits witness member) + obtain ⟨provisional, providers⟩ := forall₂_exists_right witnesses + (fun witness (row : FunctionRow) => row.Provides width witness.emission) + (fun witness member => witness.provider_row (emitted witness member) (satisfied witness member) + (counts witness member) (shapes witness member) width) + have providerRows := forall₂_map_left providers + have global := tables.global_of_circuit_balance balanced bounded widths providerRows + obtain ⟨functions, interpreted⟩ := forall₂_exists_right witnesses + (fun witness (row : FunctionRow) => row.Valid program (memoryFacts tables.memory) ∧ + row.Provides width witness.emission ∧ row.QueriesIn queries) + (fun witness member => witness.interpreted_row global memoryValid canonical + (emitted witness member) (satisfied witness member) (counts witness member) (shapes witness member) + (limits witness member) (List.mem_map.mpr ⟨witness, member, rfl⟩) pooled) + have provided : List.Forall₂ (FunctionRow.Provides width) (witnesses.map (·.emission)) functions := by + apply forall₂_map_left + exact forall₂_weaken interpreted (fun _ _ evidence => evidence.2.1) + refine ⟨functions, provided, tables.global_of_circuit_balance balanced bounded widths provided, ?_, ?_⟩ + · intro row member + obtain ⟨witness, _, evidence⟩ := forall₂_right_member interpreted member + exact evidence.1 + · intro row member + obtain ⟨witness, _, evidence⟩ := forall₂_right_member interpreted member + exact evidence.2.2 + +theorem circuitWitnesses_execute (tables : AuxiliaryTables) {program : Toplevel} + (witnesses : List CircuitWitness) {width : Nat} {queries : List (List G)} + (balanced : PaddedLookupBalance width queries (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : queries.length < gSize.toNat) (widths : ∀ query ∈ queries, query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (counted : program.validateRowCounts = true) (programShapes : program.validateLookupShapes = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.Emitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes program) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) + (pooled : circuitQueryPool (witnesses.map (·.emission)) ⊆ queries) + {request : Bytecode.AIR.Call} (shape : request.LookupShape program) + (root : functionMessage request ∈ queries) : + Bytecode.AIR.Execution program (memoryFacts tables.memory) request := by + obtain ⟨functions, _, global, valid, queried⟩ := circuitWitnesses_interpret tables witnesses + balanced bounded widths memoryValid canonical counted circuits emitted satisfied shapes limits pooled + apply global.roots_execute (roots := [request]) programShapes valid + (functionQueries_in_pool ?_ queried) (functionByteQueries_in_pool queried) shape List.mem_cons_self + intro message member + have equal : message = functionMessage request := List.mem_singleton.mp member + rwa [equal] + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/CircuitTraces.lean b/Ix/Aiur/Proofs/CircuitTraces.lean new file mode 100644 index 000000000..d11a5f147 --- /dev/null +++ b/Ix/Aiur/Proofs/CircuitTraces.lean @@ -0,0 +1,217 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.EncodedCircuitExecution +import Ix.Aiur.Proofs.LookupBudget + +/-! Canonical circuit traces encode the activation bitmap and active-order +degrees directly. Successful emission supplies every row's circuit and +lookup extent. Unit consumers fit the trace capacity, which the checked +global budget bounds below the field characteristic. Native extraction +from the accepted commitments and proof metadata remains separate. -/ + +namespace Aiur.AIR +open Bytecode + +/-- Trace assignments indexed by the canonical circuit order. An active +circuit has exactly the height specified by its active-position degree. -/ +inductive CircuitTraces : List Circuit → Type where + | nil : CircuitTraces [] + | inactive (circuit : Circuit) {circuits : List Circuit} (rest : CircuitTraces circuits) : + CircuitTraces (circuit :: circuits) + | active (circuit : Circuit) (degree : Nat) (values : Fin (2 ^ degree) → Nat → G) + {circuits : List Circuit} (rest : CircuitTraces circuits) : CircuitTraces (circuit :: circuits) + +def CircuitTraces.bitmap {circuits : List Circuit} : CircuitTraces circuits → List Bool + | .nil => [] + | .inactive _ rest => false :: rest.bitmap + | .active _ _ _ rest => true :: rest.bitmap + +def CircuitTraces.degrees {circuits : List Circuit} : CircuitTraces circuits → List Nat + | .nil => [] + | .inactive _ rest => rest.degrees + | .active _ degree _ rest => degree :: rest.degrees + +def CircuitTraces.capacity {circuits : List Circuit} : CircuitTraces circuits → Nat + | .nil => 0 + | .inactive _ rest => rest.capacity + | .active circuit degree _ rest => 2 ^ degree * circuit.layout.lookups + rest.capacity + +def emitCircuitWitness (program : Toplevel) (circuit : Circuit) (values : Nat → G) : Option CircuitWitness := do + let emission ← circuit.emitRow values program + return ⟨circuit, values, emission⟩ + +def CircuitTraces.emitWitnesses {circuits : List Circuit} (program : Toplevel) : + CircuitTraces circuits → Option (List CircuitWitness) + | .nil => some [] + | .inactive _ rest => rest.emitWitnesses program + | .active circuit _ values rest => do + let first ← (List.ofFn values).mapM (emitCircuitWitness program circuit) + let later ← rest.emitWitnesses program + return first ++ later + +theorem CircuitTraces.slot_sum_append {circuits : List Circuit} (traces : CircuitTraces circuits) + (otherSlots : List Nat) (otherActive : List Bool) (otherDegrees : List Nat) : + lookupSlotSum (circuits.map (·.layout.lookups) ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = + (lookupSlotSum otherSlots otherActive otherDegrees).map (traces.capacity + ·) := by + induction traces with + | nil => + simp only [List.map_nil, List.nil_append, bitmap, degrees, capacity, Nat.zero_add] + cases lookupSlotSum otherSlots otherActive otherDegrees <;> rfl + | inactive circuit rest ih => + simp only [List.map_cons, List.cons_append, bitmap, degrees, capacity, lookupSlotSum] + exact ih + | active circuit degree values rest ih => + simp only [List.map_cons, List.cons_append, bitmap, degrees, capacity, lookupSlotSum, ih, + bind, Option.bind] + cases lookupSlotSum otherSlots otherActive otherDegrees <;> + simp only [Option.map_none, Option.map_some, pure, Nat.add_assoc] + +theorem CircuitTraces.capacity_bounded {circuits : List Circuit} (traces : CircuitTraces circuits) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (accepted : lookupQueryBound (circuits.map (·.layout.lookups) ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = some result) : + traces.capacity + 1 < gSize.toNat := by + obtain ⟨_, total, shape, count, bounded⟩ := lookupQueryBound_sound accepted + rw [traces.slot_sum_append] at shape + cases other : lookupSlotSum otherSlots otherActive otherDegrees with + | none => simp only [other, Option.map_none, reduceCtorEq] at shape + | some extra => + simp only [other, Option.map_some, Option.some.injEq] at shape + omega + +theorem emitCircuitWitness_spec {program : Toplevel} {circuit : Circuit} {values : Nat → G} + {witness : CircuitWitness} (emitted : emitCircuitWitness program circuit values = some witness) : + witness.circuit = circuit ∧ witness.values = values ∧ witness.Emitted program ∧ + witness.emission.lookupCount = circuit.layout.lookups := by + simp only [emitCircuitWitness, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i emission emissionEq + have equal := Option.some.inj emitted + subst witness + have description := (circuit.emitRow_spec values program emissionEq).1 + refine ⟨rfl, rfl, emissionEq, ?_⟩ + exact congrArg CircuitEmission.lookupCount description + +theorem encodedQueries_length (branchless : Bool) (queries : List QueryPart) (limit : Nat) : + (encodedQueries branchless queries limit).length ≤ limit := by + simpa only [encodedQueries, List.length_range] using + List.length_filterMap_le (encodedQuery branchless queries) (List.range limit) + +theorem encodedCircuitQueryPool_uniform_bound (witnesses : List CircuitWitness) (slots : Nat) + (bounded : ∀ witness ∈ witnesses, witness.emission.lookupCount ≤ slots) : + (encodedCircuitQueryPool (witnesses.map (·.emission))).length ≤ witnesses.length * slots := by + induction witnesses with + | nil => simp only [List.map_nil, encodedCircuitQueryPool, List.flatMap_nil, List.length_nil, Nat.zero_mul, Nat.le_refl] + | cons witness rest ih => + have first := Nat.le_trans (encodedQueries_length witness.emission.branchless + witness.emission.queries witness.emission.lookupCount) (bounded witness List.mem_cons_self) + have later := ih (fun item member => bounded item (List.mem_cons_of_mem _ member)) + simp only [encodedCircuitQueryPool, List.map_cons, List.flatMap_cons, + List.length_append, List.length_cons, Nat.add_mul, Nat.one_mul] at * + omega + +theorem emitCircuitWitnesses_spec {program : Toplevel} {circuit : Circuit} + {values : List (Nat → G)} {witnesses : List CircuitWitness} + (emitted : values.mapM (emitCircuitWitness program circuit) = some witnesses) : + witnesses.length = values.length ∧ + (∀ witness ∈ witnesses, witness.circuit = circuit ∧ witness.Emitted program ∧ + witness.emission.lookupCount = circuit.layout.lookups) := by + have related : List.Forall₂ (fun _ witness => witness.circuit = circuit ∧ witness.Emitted program ∧ + witness.emission.lookupCount = circuit.layout.lookups) values witnesses := by + apply mapM_forall₂ emitted + intro value member witness produced + obtain ⟨same, _, emitted, count⟩ := emitCircuitWitness_spec produced + exact ⟨same, emitted, count⟩ + have length : witnesses.length = values.length := by + clear emitted + induction related with + | nil => rfl + | cons first rest ih => simpa only [List.length_cons] using congrArg (· + 1) ih + refine ⟨length, ?_⟩ + intro witness member + obtain ⟨_, _, evidence⟩ := forall₂_right_member related member + exact evidence + +theorem CircuitTraces.emitWitnesses_spec {circuits : List Circuit} (traces : CircuitTraces circuits) + {program : Toplevel} {witnesses : List CircuitWitness} + (emitted : traces.emitWitnesses program = some witnesses) : + (∀ witness ∈ witnesses, witness.circuit ∈ circuits ∧ witness.Emitted program) ∧ + (encodedCircuitQueryPool (witnesses.map (·.emission))).length ≤ traces.capacity := by + induction traces generalizing witnesses with + | nil => + have equal := Option.some.inj emitted + subst witnesses + exact ⟨by simp only [List.not_mem_nil, false_implies, implies_true], Nat.le_refl 0⟩ + | inactive circuit rest ih => + obtain ⟨valid, bounded⟩ := ih emitted + exact ⟨fun witness member => ⟨List.mem_cons_of_mem _ (valid witness member).1, + (valid witness member).2⟩, bounded⟩ + | active circuit degree values rest ih => + simp only [emitWitnesses, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i later laterEmitted + have equal := Option.some.inj emitted + subst witnesses + obtain ⟨valid, bounded⟩ := ih laterEmitted + obtain ⟨length, firstValid⟩ := emitCircuitWitnesses_spec firstEmitted + have firstBound := encodedCircuitQueryPool_uniform_bound first circuit.layout.lookups + (fun witness member => Nat.le_of_eq (firstValid witness member).2.2) + simp only [List.length_ofFn] at length + rw [length] at firstBound + refine ⟨?_, ?_⟩ + · intro witness member + rcases List.mem_append.mp member with before | after + · have evidence := firstValid witness before + exact ⟨List.mem_cons.mpr (Or.inl evidence.1), evidence.2.1⟩ + · exact ⟨List.mem_cons_of_mem _ (valid witness after).1, (valid witness after).2⟩ + · simp only [encodedCircuitQueryPool, List.map_append, List.flatMap_append, + List.length_append, capacity] at * + omega + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +/-- Trace rows and the checked native-style budget replace the separate +query-count premise. Native commitment/trace extraction remains separate. -/ +theorem Backend.trace_circuit_execution {selection : Selection} (backend : Backend selection) + (tables : AuxiliaryTables) (traces : CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List CircuitWitness} + (emitted : traces.emitWitnesses backend.compiled.bytecode = some witnesses) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (budget : lookupQueryBound + (backend.compiled.bytecode.circuits.toList.map (·.layout.lookups) ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: + encodedCircuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes backend.compiled.bytecode) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) + ⟨selection.function, input, selection.success, 0⟩ := by + obtain ⟨valid, bound⟩ := traces.emitWitnesses_spec emitted + have totalBound := traces.capacity_bounded budget + apply backend.encoded_circuit_execution tables witnesses width input arity balanced (by omega) + publicWidth queryWidths memoryValid canonical + (fun witness member => by simpa using (valid witness member).1) + (fun witness member => (valid witness member).2) satisfied shapes limits + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/Compilation.lean b/Ix/Aiur/Proofs/Compilation.lean new file mode 100644 index 000000000..b6e3b1f58 --- /dev/null +++ b/Ix/Aiur/Proofs/Compilation.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Compiler +import Ix.Aiur.Proofs.Metadata +import Ix.Aiur.Proofs.Relayout +import Ix.Aiur.Proofs.Dedup +import Std.Data.HashMap.Lemmas + +/-! Artifact binding for the actual compilation pipeline. This strengthens +stage existence with equality to the returned artifact. Semantic success +reflection through these stages remains a separate obligation. -/ + +namespace Aiur + +/-- Inlining changes function bodies and retains the selected rank policy. -/ +theorem Source.Toplevel.inlineCalls_componentRanks {source inlined : Source.Toplevel} + (accepted : source.inlineCalls = .ok inlined) : + inlined.componentRanks = source.componentRanks := by + unfold Source.Toplevel.inlineCalls at accepted + simp only [bind, Except.bind, pure, Except.pure] at accepted + repeat' first + | split at accepted + | (dsimp only at accepted; split at accepted) + all_goals cases accepted + all_goals rfl + +theorem Source.Toplevel.compile_artifact_of_ok + {source : Source.Toplevel} {compiled : CompiledToplevel} + (h : source.compile = .ok compiled) : + ∃ inlined typed concrete raw names, + source.inlineCalls = .ok inlined ∧ + inlined.checkAndSimplify = .ok typed ∧ + typed.concretize = .ok concrete ∧ + concrete.toBytecode = .ok (raw, names) ∧ + compiled = finishCompilation inlined raw names := by + obtain ⟨inlined, typed, concrete, raw, names, hi, ht, hc, hb⟩ := + source.compile_stages_of_ok h + refine ⟨inlined, typed, concrete, raw, names, hi, ht, hc, hb, ?_⟩ + simpa only [Source.Toplevel.compile, hi, ht, hc, hb, Except.mapError, + bind, Except.bind, pure, Except.pure, Except.ok.injEq] using h.symm + +/-- Reachability, checked component layouts and partition construction retain +the executable behavior and input arity of the deduplicated program. -/ +theorem finishCompilation_sameCode (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) : + Bytecode.Eval.SameCode (finishCompilation source raw names).bytecode raw.deduplicate.1 := by + let dedup := raw.deduplicate.1 + let reachable : Bytecode.Toplevel := { dedup with + functions := dedup.functions.mapIdx fun i f => + { f with constrained := dedup.needsCircuit[i]! } } + let ranked := if source.componentRanks then reachable.withCallComponents else reachable + have reach : Bytecode.Eval.SameCode reachable dedup := by + constructor + · simp only [reachable, Array.size_mapIdx] + · intro i ha hb t fuel st + simp only [reachable, Array.getElem_mapIdx] + · intro i ha hb + simp only [reachable, Array.getElem_mapIdx] + have rank : Bytecode.Eval.SameCode ranked reachable := by + dsimp only [ranked] + split + · exact reachable.withCallComponents_sameCode + · exact Bytecode.Eval.SameCode.refl reachable + have partition : Bytecode.Eval.SameCode + (finishCompilation source raw names).bytecode ranked := + Bytecode.Eval.SameCode.ofFunctionsEq rfl + exact partition.trans (rank.trans reach) + +/-- Backward success reflection for the final reachability/partition passes. +The preceding deduplication and source-to-bytecode passes remain separate. -/ +theorem finishCompilation_reflects {source : Source.Toplevel} {raw : Bytecode.Toplevel} + {names : Std.HashMap Global Bytecode.FunIdx} {function : Bytecode.FunIdx} + {args : Array G} {io : IOBuffer} {fuel : Nat} {result : Array G × IOBuffer} + (h : Bytecode.Eval.runFunction (finishCompilation source raw names).bytecode + function args io fuel = .ok result) : + Bytecode.Eval.runFunction raw.deduplicate.1 function args io fuel = .ok result := + (Bytecode.Eval.runFunction_sameCode (finishCompilation_sameCode source raw names) + function args io fuel).symm.trans h + +/-- Checked deduplication, reachability metadata and circuit construction +preserve and reflect success at the actual remapping of each original index. -/ +theorem finishCompilation_preserves_execution (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) (function : Bytecode.FunIdx) + (args : Array G) (io : IOBuffer) (fuel : Nat) (result : Array G × IOBuffer) : + Bytecode.Eval.runFunction raw function args io fuel = .ok result ↔ + Bytecode.Eval.runFunction (finishCompilation source raw names).bytecode + (raw.deduplicate.2 function) args io fuel = .ok result := by + rw [Bytecode.Eval.runFunction_sameCode (finishCompilation_sameCode source raw names)] + exact Bytecode.Eval.deduplicate_preserves_execution raw function args io fuel result + +private theorem fold_renamed_name_image {α : Type} [BEq α] [Hashable α] [LawfulBEq α] + (items : List (α × Nat)) (initial : Std.HashMap α Nat) (rename : Nat → Nat) + {name : α} {value : Nat} + (present : (items.foldl (fun acc item => acc.insert item.1 (rename item.2)) initial)[name]? = + some value) : + initial[name]? = some value ∨ ∃ before, (name, before) ∈ items ∧ rename before = value := by + induction items generalizing initial with + | nil => exact Or.inl present + | cons item items ih => + simp only [List.foldl_cons] at present + rcases ih _ present with prior | ⟨before, member, eq⟩ + · rw [Std.HashMap.getElem?_insert] at prior + split at prior + next same => + have hname : item.1 = name := eq_of_beq same + have hvalue : rename item.2 = value := Option.some.inj prior + exact Or.inr ⟨item.2, List.mem_cons.mpr (Or.inl (Prod.ext hname.symm rfl)), hvalue⟩ + next different => exact Or.inl prior + · exact Or.inr ⟨before, by simp [member], eq⟩ + +/-- A compiled entrypoint comes from the same name before deduplication, +with its index transformed by the actual selected renaming. -/ +theorem finishCompilation_nameMap_image {source : Source.Toplevel} {raw : Bytecode.Toplevel} + {names : Std.HashMap Global Bytecode.FunIdx} {name : Lean.Name} {function : Bytecode.FunIdx} + (present : (finishCompilation source raw names).getFuncIdx name = some function) : + ∃ original, names[Global.mk name]? = some original ∧ raw.deduplicate.2 original = function := by + simp only [finishCompilation, CompiledToplevel.getFuncIdx, Id.run, pure] at present + rw [Std.HashMap.fold_eq_foldl_toList] at present + rcases fold_renamed_name_image names.toList ∅ raw.deduplicate.2 present with impossible | ⟨original, member, eq⟩ + · simp at impossible + · exact ⟨original, by simpa using member, eq⟩ + +end Aiur diff --git a/Ix/Aiur/Proofs/CompiledCircuitRows.lean b/Ix/Aiur/Proofs/CompiledCircuitRows.lean new file mode 100644 index 000000000..a531e963e --- /dev/null +++ b/Ix/Aiur/Proofs/CompiledCircuitRows.lean @@ -0,0 +1,68 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitReflection + +/-! +Compose native-style circuit emission and base-graph compilation. Swept graph +constraints and every physical lookup slot have the valued circuit meaning, +including constant-zero elimination, root deduplication, and shared providers. +-/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter Compiler + +theorem equations_vanish {values : Values G} {expressions : List Expr} {results : List G} + (evaluated : expressions.mapM (evalExpr values) = some results) : + ExprsVanish goldilocksOps values expressions ↔ ∀ result ∈ results, result = 0 := by + have related := AIR.mapM_forall₂ evaluated (fun _ _ _ reflected => reflected) + clear evaluated + induction related with + | nil => constructor <;> intro _ _ member <;> cases member + | cons reflected _ ih => + rw [ExprsVanish.cons, List.forall_mem_cons] + constructor + · intro ⟨zero, zeros⟩ + exact ⟨Option.some.inj (reflected.symm.trans zero), ih.mp zeros⟩ + · intro ⟨zero, zeros⟩ + exact ⟨zero ▸ reflected, ih.mpr zeros⟩ + +structure Compiled where + emission : Emission + base : BaseCompilation + +def compileCircuit (widths : GraphWidths) (program : Bytecode.Toplevel) (circuit : Bytecode.Circuit) : Option Compiled := do + let emission ← emitCircuit program circuit + let base ← compileBase widths emission.lookups emission.equations + return ⟨emission, base⟩ + +theorem compileCircuit_reflects {values : Values G} (row : Nat → G) {widths : GraphWidths} + (fits : values.Fits widths) (program : Bytecode.Toplevel) (circuit : Bytecode.Circuit) {compiled : Compiled} + (built : compileCircuit widths program circuit = some compiled) + (reads : ∀ index < compiled.emission.readBound, + (values.columns .main .current)[index]? = some (row index)) : + ∃ result buffer, circuit.emitRow row program = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := by + simp only [compileCircuit, bind, Option.bind] at built + split at built + · cases built + rename_i emission emitted + dsimp only at built + split at built + · cases built + rename_i base baseCompiled + cases built + obtain ⟨result, resultEmitted, evaluated⟩ := emitCircuit_reflects row program circuit emitted reads + obtain ⟨buffer, swept, lookups, zeros⟩ := compileBase_reflects goldilocksGraphLaws fits + emission.lookups emission.equations baseCompiled + have equations := (Emission.eval_components evaluated).2.2.2.2.2.2.2.2.2.1 + obtain ⟨messages, exprReads, graphReads⟩ := lookups.read + exact ⟨result, buffer, resultEmitted, swept, zeros.trans (equations_vanish equations), + graphReads.trans (exprReads.symm.trans (Emission.lookups_eval evaluated))⟩ + +end Aiur.NativeAIR.CircuitEmitter diff --git a/Ix/Aiur/Proofs/CompiledKey.lean b/Ix/Aiur/Proofs/CompiledKey.lean new file mode 100644 index 000000000..f3f2f1e30 --- /dev/null +++ b/Ix/Aiur/Proofs/CompiledKey.lean @@ -0,0 +1,315 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.CompiledVerifier +import Ix.Aiur.Proofs.GraphWidths +import Ix.Aiur.Proofs.TableExpressions +import Ix.Aiur.Proofs.KeyArtifact + +/-! The enforced compiled-key comparison supplies graph equality and native +dimensions. Every function, memory and byte circuit in the selected key has +the corresponding physical row meaning, without a graph-equality premise. -/ + +namespace Aiur.NativeAIR.CompiledKey +open Compiler CircuitEmitter OpEmitter + +theorem circuit_success {logBlowup mainWidth preprocessedWidth preprocessedHeight groupSize : Nat} + {base : BaseCompilation} {result : KeyCodec.Circuit} + (built : circuit logBlowup mainWidth preprocessedWidth preprocessedHeight groupSize base = some result) : + result.graph = base.graph ∧ result.mainWidth = mainWidth ∧ + result.preprocessedWidth = preprocessedWidth ∧ result.preprocessedHeight = preprocessedHeight ∧ + result.valid = true := by + simp only [circuit, bind, Option.bind] at built + split at built + · cases built + · dsimp only at built + rename_i degree _ + split at built + · cases built + have authored := LookupGroups.retune_authored + ⟨mainWidth, preprocessedWidth, preprocessedHeight, degree, groupSize, base.graph⟩ (2^logBlowup) + exact ⟨congrArg (fun fields => fields.1) authored, + congrArg (fun fields => fields.2.1) authored, + congrArg (fun fields => fields.2.2.1) authored, + congrArg (fun fields => fields.2.2.2) authored, ‹_›⟩ + · cases built + +theorem functionCircuit_success {logBlowup : Nat} {program : Bytecode.Toplevel} {source : Bytecode.Circuit} + {result : KeyCodec.Circuit} (built : functionCircuit logBlowup program source = some result) : + ∃ compiled, compileCircuit (circuitWidths source) program source = some compiled ∧ + result.graph = compiled.base.graph ∧ result.mainWidth = source.layout.width ∧ + result.preprocessedWidth = 0 ∧ result.preprocessedHeight = 0 ∧ + result.valid = true := by + cases compiled : compileCircuit (circuitWidths source) program source with + | none => simp only [functionCircuit, compiled, bind, Option.bind_none, reduceCtorEq] at built + | some output => + simp only [functionCircuit, compiled, bind, Option.bind_some] at built + have fields := circuit_success built + exact ⟨output, rfl, fields.1, fields.2.1, fields.2.2.1, fields.2.2.2.1, fields.2.2.2.2⟩ + +theorem memoryCircuit_success {logBlowup width : Nat} {result : KeyCodec.Circuit} + (built : memoryCircuit logBlowup width = some result) : + ∃ base, compileBase ⟨0, 3 + width, 0, 0⟩ [memoryLookup width] memoryEquations = some base ∧ + result.graph = base.graph ∧ result.mainWidth = 3 + width ∧ + result.preprocessedWidth = 0 ∧ result.preprocessedHeight = 0 ∧ result.valid = true := by + cases compiled : compileBase ⟨0, 3 + width, 0, 0⟩ [memoryLookup width] memoryEquations with + | none => simp only [memoryCircuit, compiled, bind, Option.bind_none, reduceCtorEq] at built + | some base => + simp only [memoryCircuit, compiled, bind, Option.bind_some] at built + have fields := circuit_success built + exact ⟨base, rfl, fields.1, fields.2.1, fields.2.2.1, fields.2.2.2.1, fields.2.2.2.2⟩ + +theorem byte1Circuit_success {logBlowup : Nat} {result : KeyCodec.Circuit} (built : byte1Circuit logBlowup = some result) : + ∃ base, compileBase ⟨11, 3, 0, 0⟩ (AIR.Byte1Kind.all.map byte1Lookup) [] = some base ∧ + result.graph = base.graph ∧ result.mainWidth = 3 ∧ result.preprocessedWidth = 11 ∧ + result.preprocessedHeight = 256 ∧ result.valid = true := by + cases compiled : compileBase ⟨11, 3, 0, 0⟩ (AIR.Byte1Kind.all.map byte1Lookup) [] with + | none => simp only [byte1Circuit, compiled, bind, Option.bind_none, reduceCtorEq] at built + | some base => + simp only [byte1Circuit, compiled, bind, Option.bind_some] at built + have fields := circuit_success built + exact ⟨base, rfl, fields.1, fields.2.1, fields.2.2.1, fields.2.2.2.1, fields.2.2.2.2⟩ + +theorem byte2Circuit_success {logBlowup : Nat} {result : KeyCodec.Circuit} (built : byte2Circuit logBlowup = some result) : + ∃ base, compileBase ⟨14, 10, 0, 0⟩ (AIR.Byte2Kind.all.map byte2Lookup) [] = some base ∧ + result.graph = base.graph ∧ result.mainWidth = 10 ∧ result.preprocessedWidth = 14 ∧ + result.preprocessedHeight = 65536 ∧ result.valid = true := by + cases compiled : compileBase ⟨14, 10, 0, 0⟩ (AIR.Byte2Kind.all.map byte2Lookup) [] with + | none => simp only [byte2Circuit, compiled, bind, Option.bind_none, reduceCtorEq] at built + | some base => + simp only [byte2Circuit, compiled, bind, Option.bind_some] at built + have fields := circuit_success built + exact ⟨base, rfl, fields.1, fields.2.1, fields.2.2.1, fields.2.2.2.1, fields.2.2.2.2⟩ + +theorem circuits_parts {logBlowup : Nat} {program : Bytecode.Toplevel} {result : List KeyCodec.Circuit} + (built : circuits logBlowup program = some result) : + ∃ functions memories byte1 byte2, + program.circuits.toList.mapM (functionCircuit logBlowup program) = some functions ∧ + program.memorySizes.toList.mapM (memoryCircuit logBlowup) = some memories ∧ + byte1Circuit logBlowup = some byte1 ∧ byte2Circuit logBlowup = some byte2 ∧ + result = functions ++ memories ++ [byte1, byte2] := by + cases functionsBuilt : program.circuits.toList.mapM (functionCircuit logBlowup program) with + | none => simp only [circuits, functionsBuilt, bind, Option.bind_none, reduceCtorEq] at built + | some functions => + cases memoriesBuilt : program.memorySizes.toList.mapM (memoryCircuit logBlowup) with + | none => simp only [circuits, functionsBuilt, memoriesBuilt, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at built + | some memories => + cases first : byte1Circuit logBlowup with + | none => simp only [circuits, functionsBuilt, memoriesBuilt, first, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at built + | some byte1 => + cases second : byte2Circuit logBlowup with + | none => simp only [circuits, functionsBuilt, memoriesBuilt, first, second, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at built + | some byte2 => + simp only [circuits, functionsBuilt, memoriesBuilt, first, second, bind, Option.bind_some, pure, Option.some.injEq] at built + exact ⟨functions, memories, byte1, byte2, rfl, rfl, rfl, rfl, built.symm⟩ + +theorem circuits_length {logBlowup : Nat} {program : Bytecode.Toplevel} {result : List KeyCodec.Circuit} + (built : circuits logBlowup program = some result) : + result.length = program.circuits.size + program.memorySizes.size + 2 := by + obtain ⟨functions, memories, _, _, functionsBuilt, memoriesBuilt, _, _, equal⟩ := circuits_parts built + have fl := Bytecode.AIR.list_mapM_some_length _ _ _ functionsBuilt + have ml := Bytecode.AIR.list_mapM_some_length _ _ _ memoriesBuilt + simp only [equal, List.length_append, fl, ml, Array.length_toList, List.length_cons, List.length_nil] + +theorem circuits_function {logBlowup : Nat} {program : Bytecode.Toplevel} {result : List KeyCodec.Circuit} + (built : circuits logBlowup program = some result) {index : Nat} {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (present : program.circuits[index]? = some source) (selected : result[index]? = some artifact) : + functionCircuit logBlowup program source = some artifact := by + obtain ⟨functions, memories, byte1, byte2, functionsBuilt, _, _, _, equal⟩ := circuits_parts built + have length := Bytecode.AIR.list_mapM_some_length _ _ _ functionsBuilt + have bound : index < functions.length := by + rw [length, Array.length_toList] + exact (Array.getElem?_eq_some_iff.mp present).1 + rw [equal, List.append_assoc, List.getElem?_append_left bound] at selected + have read := list_mapM_read functionsBuilt index + simpa only [Array.getElem?_toList, present, Option.bind_some, selected, bind] using read + +theorem circuits_memory {logBlowup : Nat} {program : Bytecode.Toplevel} {result : List KeyCodec.Circuit} + (built : circuits logBlowup program = some result) {index width : Nat} {artifact : KeyCodec.Circuit} + (present : program.memorySizes[index]? = some width) + (selected : result[program.circuits.size + index]? = some artifact) : + memoryCircuit logBlowup width = some artifact := by + obtain ⟨functions, memories, byte1, byte2, functionsBuilt, memoriesBuilt, _, _, equal⟩ := circuits_parts built + have fl := Bytecode.AIR.list_mapM_some_length _ _ _ functionsBuilt + have ml := Bytecode.AIR.list_mapM_some_length _ _ _ memoriesBuilt + have first : functions.length ≤ program.circuits.size + index := by simp only [fl, Array.length_toList]; omega + have inside : index < memories.length := by + rw [ml, Array.length_toList] + exact (Array.getElem?_eq_some_iff.mp present).1 + rw [equal, List.append_assoc, List.getElem?_append_right first] at selected + simp only [fl, Array.length_toList, Nat.add_sub_cancel_left, List.getElem?_append_left inside] at selected + have read := list_mapM_read memoriesBuilt index + simpa only [Array.getElem?_toList, present, Option.bind_some, selected, bind] using read + +theorem circuits_bytes {logBlowup : Nat} {program : Bytecode.Toplevel} {result : List KeyCodec.Circuit} + (built : circuits logBlowup program = some result) : + ∃ byte1 byte2, byte1Circuit logBlowup = some byte1 ∧ byte2Circuit logBlowup = some byte2 ∧ + result[program.circuits.size + program.memorySizes.size]? = some byte1 ∧ + result[program.circuits.size + program.memorySizes.size + 1]? = some byte2 := by + obtain ⟨functions, memories, byte1, byte2, functionsBuilt, memoriesBuilt, first, second, equal⟩ := circuits_parts built + have fl := Bytecode.AIR.list_mapM_some_length _ _ _ functionsBuilt + have ml := Bytecode.AIR.list_mapM_some_length _ _ _ memoriesBuilt + have length : (functions ++ memories).length = program.circuits.size + program.memorySizes.size := by + simp only [List.length_append, fl, ml, Array.length_toList] + refine ⟨byte1, byte2, first, second, ?_, ?_⟩ + · rw [equal, List.getElem?_append_right (by omega), length, Nat.sub_self] + rfl + · rw [equal, List.getElem?_append_right (by omega), length] + simp only [Nat.add_sub_cancel_left, List.getElem?_cons_succ, List.getElem?_cons_zero] + +theorem memoryCircuit_reflects {logBlowup width : Nat} {artifact : KeyCodec.Circuit} + (built : memoryCircuit logBlowup width = some artifact) {values : Values G} (fits : values.Fits artifact.widths) : + ∃ buffer, artifact.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ + ∀ equation ∈ AIR.memoryColumnEquations width (columns values .main .current (3 + width)) + (columns values .main .next (3 + width)) values.isTransition, equation = 0) ∧ + artifact.graph.lookups.mapM (readLookup buffer) = + some [AIR.memoryColumnLookup width (columns values .main .current (3 + width))] := by + obtain ⟨base, compiled, graph, mainWidth, _, _, _⟩ := memoryCircuit_success built + have widths : (GraphWidths.mk 0 (3 + width) 0 0).Le artifact.widths := by + refine ⟨?_, Nat.zero_le _⟩ + intro source + cases source <;> simp only [GraphWidths.width, KeyCodec.Circuit.widths, mainWidth, Nat.le_refl, Nat.zero_le] + have wide := compileBase_widen widths _ _ compiled + obtain ⟨buffer, swept, lookups, equations⟩ := compileBase_reflects goldilocksGraphLaws fits _ _ wide + have mainBound : 3 + width ≤ artifact.widths.main := by simp only [KeyCodec.Circuit.widths, mainWidth, Nat.le_refl] + have eqs := memoryEquations_eval fits width mainBound + have lookup := memoryLookup_eval fits width mainBound + obtain ⟨results, exprReads, graphReads⟩ := lookups.read + refine ⟨buffer, graph ▸ swept, ?_, ?_⟩ + · rw [graph] + exact equations.trans (equations_vanish eqs) + · rw [graph] + exact graphReads.trans (exprReads.symm.trans (by + simp only [List.mapM_cons, List.mapM_nil, lookup, bind, Option.bind_some, pure])) + +theorem byte1Circuit_reflects {logBlowup : Nat} {artifact : KeyCodec.Circuit} (built : byte1Circuit logBlowup = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ buffer, artifact.graph.sweep goldilocksOps values = some buffer ∧ + Vanishes goldilocksOps buffer artifact.graph.zeros ∧ + artifact.graph.lookups.mapM (readLookup buffer) = some + (AIR.Byte1Kind.all.map fun kind => AIR.byte1ColumnLookup kind + (columns values .preprocessed .current 11) (columns values .main .current 3)) := by + obtain ⟨base, compiled, graph, mainWidth, preWidth, _, _⟩ := byte1Circuit_success built + have widths : (GraphWidths.mk 11 3 0 0).Le artifact.widths := by + refine ⟨?_, Nat.zero_le _⟩ + intro source + cases source <;> simp only [GraphWidths.width, KeyCodec.Circuit.widths, mainWidth, preWidth, Nat.le_refl, Nat.zero_le] + have wide := compileBase_widen widths _ _ compiled + obtain ⟨buffer, swept, lookups, equations⟩ := compileBase_reflects goldilocksGraphLaws fits _ _ wide + have mainBound : 3 ≤ artifact.widths.main := by simp only [KeyCodec.Circuit.widths, mainWidth, Nat.le_refl] + have preBound : 11 ≤ artifact.widths.preprocessed := by simp only [KeyCodec.Circuit.widths, preWidth, Nat.le_refl] + have evaluated := list_mapM_of_map AIR.Byte1Kind.all byte1Lookup _ (ExprLookup.eval goldilocksOps values) + (fun kind _ => byte1Lookup_eval fits mainBound preBound kind) + obtain ⟨results, exprReads, graphReads⟩ := lookups.read + refine ⟨buffer, graph ▸ swept, ?_, ?_⟩ + · rw [graph] + exact equations.mpr (fun _ member => nomatch member) + · rw [graph] + exact graphReads.trans (exprReads.symm.trans evaluated) + +theorem byte2Circuit_reflects {logBlowup : Nat} {artifact : KeyCodec.Circuit} (built : byte2Circuit logBlowup = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ buffer, artifact.graph.sweep goldilocksOps values = some buffer ∧ + Vanishes goldilocksOps buffer artifact.graph.zeros ∧ + artifact.graph.lookups.mapM (readLookup buffer) = some + (AIR.Byte2Kind.all.map fun kind => AIR.byte2ColumnLookup kind + (columns values .preprocessed .current 14) (columns values .main .current 10)) := by + obtain ⟨base, compiled, graph, mainWidth, preWidth, _, _⟩ := byte2Circuit_success built + have widths : (GraphWidths.mk 14 10 0 0).Le artifact.widths := by + refine ⟨?_, Nat.zero_le _⟩ + intro source + cases source <;> simp only [GraphWidths.width, KeyCodec.Circuit.widths, mainWidth, preWidth, Nat.le_refl, Nat.zero_le] + have wide := compileBase_widen widths _ _ compiled + obtain ⟨buffer, swept, lookups, equations⟩ := compileBase_reflects goldilocksGraphLaws fits _ _ wide + have mainBound : 10 ≤ artifact.widths.main := by simp only [KeyCodec.Circuit.widths, mainWidth, Nat.le_refl] + have preBound : 14 ≤ artifact.widths.preprocessed := by simp only [KeyCodec.Circuit.widths, preWidth, Nat.le_refl] + have evaluated := list_mapM_of_map AIR.Byte2Kind.all byte2Lookup _ (ExprLookup.eval goldilocksOps values) + (fun kind _ => byte2Lookup_eval fits mainBound preBound kind) + obtain ⟨results, exprReads, graphReads⟩ := lookups.read + refine ⟨buffer, graph ▸ swept, ?_, ?_⟩ + · rw [graph] + exact equations.mpr (fun _ member => nomatch member) + · rw [graph] + exact graphReads.trans (exprReads.symm.trans evaluated) + +end Aiur.NativeAIR.CompiledKey + +namespace Aiur.BoundVerifier +open NativeAIR NativeAIR.CircuitEmitter NativeAIR.Compiler + +theorem CompiledBackend.circuit_count {selection : Selection} (backend : CompiledBackend selection) : + backend.keyData.circuits.length = + backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size + 2 := + CompiledKey.circuits_length backend.circuits_bound + +theorem CompiledBackend.function_graph_reflects {selection : Selection} (backend : CompiledBackend selection) + (generic : selection.source.componentRanks = false) + {index : Nat} {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (present : backend.compiled.bytecode.circuits[index]? = some source) + (selected : backend.keyData.circuits[index]? = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ result buffer, + source.emitRow (fun index => (values.columns .main .current)[index]?.getD 0) backend.compiled.bytecode = some result ∧ + artifact.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + artifact.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := by + have bound := CompiledKey.circuits_function backend.circuits_bound present selected + obtain ⟨compiled, built, graph, mainWidth, _, _, _⟩ := CompiledKey.functionCircuit_success bound + have physical : artifact.widths.main = source.layout.width := mainWidth + have wide := compileCircuit_widen (circuitWidths_le (Nat.le_of_eq physical.symm)) _ _ built + obtain ⟨result, buffer, emitted, swept, satisfied, lookups⟩ := backend.toBackend.compileCircuit_reflects + generic fits (Array.mem_of_getElem? present) physical wide + exact ⟨result, buffer, emitted, graph ▸ swept, graph ▸ satisfied, graph ▸ lookups⟩ + +theorem CompiledBackend.memory_graph_reflects {selection : Selection} (backend : CompiledBackend selection) + {index width : Nat} {artifact : KeyCodec.Circuit} + (present : backend.compiled.bytecode.memorySizes[index]? = some width) + (selected : backend.keyData.circuits[backend.compiled.bytecode.circuits.size + index]? = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ buffer, artifact.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ + ∀ equation ∈ AIR.memoryColumnEquations width (CompiledKey.columns values .main .current (3 + width)) + (CompiledKey.columns values .main .next (3 + width)) values.isTransition, equation = 0) ∧ + artifact.graph.lookups.mapM (readLookup buffer) = + some [AIR.memoryColumnLookup width (CompiledKey.columns values .main .current (3 + width))] := + CompiledKey.memoryCircuit_reflects (CompiledKey.circuits_memory backend.circuits_bound present selected) fits + +theorem CompiledBackend.byte_graphs {selection : Selection} (backend : CompiledBackend selection) : + ∃ byte1 byte2, CompiledKey.byte1Circuit backend.keyData.parameters.logBlowup = some byte1 ∧ CompiledKey.byte2Circuit backend.keyData.parameters.logBlowup = some byte2 ∧ + backend.keyData.circuits[backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size]? = some byte1 ∧ + backend.keyData.circuits[backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size + 1]? = some byte2 := + CompiledKey.circuits_bytes backend.circuits_bound + +theorem CompiledBackend.byte1_graph_reflects {selection : Selection} (backend : CompiledBackend selection) + {artifact : KeyCodec.Circuit} + (selected : backend.keyData.circuits[backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size]? = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ buffer, artifact.graph.sweep goldilocksOps values = some buffer ∧ + Vanishes goldilocksOps buffer artifact.graph.zeros ∧ + artifact.graph.lookups.mapM (readLookup buffer) = some + (AIR.Byte1Kind.all.map fun kind => AIR.byte1ColumnLookup kind + (CompiledKey.columns values .preprocessed .current 11) (CompiledKey.columns values .main .current 3)) := by + obtain ⟨byte1, _, built, _, present, _⟩ := backend.byte_graphs + have equal := Option.some.inj (present.symm.trans selected) + subst artifact + exact CompiledKey.byte1Circuit_reflects built fits + +theorem CompiledBackend.byte2_graph_reflects {selection : Selection} (backend : CompiledBackend selection) + {artifact : KeyCodec.Circuit} + (selected : backend.keyData.circuits[backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size + 1]? = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ buffer, artifact.graph.sweep goldilocksOps values = some buffer ∧ + Vanishes goldilocksOps buffer artifact.graph.zeros ∧ + artifact.graph.lookups.mapM (readLookup buffer) = some + (AIR.Byte2Kind.all.map fun kind => AIR.byte2ColumnLookup kind + (CompiledKey.columns values .preprocessed .current 14) (CompiledKey.columns values .main .current 10)) := by + obtain ⟨_, byte2, _, built, _, present⟩ := backend.byte_graphs + have equal := Option.some.inj (present.symm.trans selected) + subst artifact + exact CompiledKey.byte2Circuit_reflects built fits + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/CompilerAllocation.lean b/Ix/Aiur/Proofs/CompilerAllocation.lean new file mode 100644 index 000000000..50d296a4c --- /dev/null +++ b/Ix/Aiur/Proofs/CompilerAllocation.lean @@ -0,0 +1,45 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationAllocation +import Ix.Aiur.Proofs.LookupLayout +import Ix.Aiur.Proofs.LayoutState + +/-! The allocation projection describes the actual compiler layout step. -/ + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode + +theorem opLayout_allocation (op : Op) (initial : LayoutMState) : + ((opLayout op).run initial).2.degrees = initial.degrees ++ (op.allocationFor initial.callRanks initial.degrees).degrees ∧ + ((opLayout op).run initial).2.functionLayout.auxiliaries = + initial.functionLayout.auxiliaries + (op.allocationFor initial.callRanks initial.degrees).auxiliaries := by + cases op + case call function args outputSize unconstrained => + cases unconstrained <;> cases rank : initial.callRanks[function]?.getD .ordered <;> + simp [opLayout, Op.allocationFor, bumpLookups, bumpAuxiliaries, pushDegrees, + StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + bind, pure, rank, Nat.add_assoc] + all_goals + simp only [opLayout, getDegree_array, bumpLookups, bumpAuxiliaries, getDegree, + pushDegree, pushDegrees, addMemSize, Op.allocationFor, Op.allocation, OpAllocation.advice] + all_goals dsimp [StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + instMonadStateOfMonadStateOf, instMonadStateOfStateTOfMonad, + bind, pure] + all_goals try simp [selectedDegree] + all_goals try split + all_goals try simp_all + all_goals first | rfl | exact ⟨rfl, rfl⟩ + +theorem opLayout_genericAllocation (op : Op) (initial : LayoutMState) + (generic : initial.callRanks = #[]) : + ((opLayout op).run initial).2.degrees = initial.degrees ++ (op.allocation initial.degrees).degrees ∧ + ((opLayout op).run initial).2.functionLayout.auxiliaries = + initial.functionLayout.auxiliaries + (op.allocation initial.degrees).auxiliaries := by + simpa only [generic, Op.allocationFor_empty] using opLayout_allocation op initial + +end Aiur.Concrete.Bytecode diff --git a/Ix/Aiur/Proofs/CompilerBranches.lean b/Ix/Aiur/Proofs/CompilerBranches.lean new file mode 100644 index 000000000..d69b39f1f --- /dev/null +++ b/Ix/Aiur/Proofs/CompilerBranches.lean @@ -0,0 +1,149 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CompilerAllocation +import Ix.Aiur.Proofs.Relayout + +/-! Branch layout restores the incoming logical degrees and retains the maximum +physical allocation, including the inverse columns of a default branch. -/ + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode + +def allocationBranchStep (shared : SharedData) (degrees : Array Nat) (acc : SharedData) + (block : Block) : LayoutM SharedData := do + setSharedData shared + blockLayout block + let used ← getSharedData + setDegrees degrees + return acc.maximals used + +theorem allocationBranchStep_degrees (shared : SharedData) (degrees : Array Nat) (acc : SharedData) + (block : Block) (initial : LayoutMState) : + ((allocationBranchStep shared degrees acc block).run initial).2.degrees = degrees := rfl + +theorem allocationBranchStep_callRanks (shared : SharedData) (degrees : Array Nat) + (acc : SharedData) (block : Block) (initial : LayoutMState) : + ((allocationBranchStep shared degrees acc block).run initial).2.callRanks = initial.callRanks := + blockLayout_callRanks block ((setSharedData shared).run initial).2 + +theorem allocationBranchFold_callRanks {α : Type} (items : List α) (blockOf : α → Block) + (shared : SharedData) (degrees : Array Nat) (acc : SharedData) (initial : LayoutMState) : + ((items.foldlM (fun acc item => allocationBranchStep shared degrees acc (blockOf item)) acc).run initial).2.callRanks = + initial.callRanks := by + induction items generalizing acc initial with + | nil => rfl + | cons item items ih => + rw [List.foldlM_cons] + exact (ih ((allocationBranchStep shared degrees acc (blockOf item)).run initial).1 + ((allocationBranchStep shared degrees acc (blockOf item)).run initial).2).trans + (allocationBranchStep_callRanks shared degrees acc (blockOf item) initial) + +theorem allocationBranchStep_column (shared : SharedData) (degrees : Array Nat) (acc : SharedData) + (block : Block) (initial : LayoutMState) (base column : Nat) (aligned : initial.degrees = degrees) + (generic : initial.callRanks = #[]) + (effect : ∀ state : LayoutMState, state.callRanks = #[] → state.degrees = degrees → + state.functionLayout.auxiliaries = shared.auxiliaries → + column = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) : + base + ((allocationBranchStep shared degrees acc block).run initial).1.auxiliaries = + max (base + acc.auxiliaries) column := by + have body := effect ((setSharedData shared).run initial).2 generic aligned rfl + change base + max acc.auxiliaries + ((blockLayout block).run ((setSharedData shared).run initial).2).2.functionLayout.auxiliaries = _ + rw [← Nat.add_max_add_left, ← body] + +theorem allocationBranchFold {α β : Type} {items : List α} {emissions : List β} + (blockOf : α → Block) (measure : β → Nat) (shared : SharedData) (degrees : Array Nat) (base : Nat) + (related : List.Forall₂ (fun item emission => ∀ state : LayoutMState, + state.callRanks = #[] → state.degrees = degrees → state.functionLayout.auxiliaries = shared.auxiliaries → + measure emission = base + ((blockLayout (blockOf item)).run state).2.functionLayout.auxiliaries) + items emissions) + (acc : SharedData) (initial : LayoutMState) (aligned : initial.degrees = degrees) + (generic : initial.callRanks = #[]) : + ((items.foldlM (fun acc item => allocationBranchStep shared degrees acc (blockOf item)) acc).run initial).2.degrees = + degrees ∧ + base + ((items.foldlM (fun acc item => allocationBranchStep shared degrees acc (blockOf item)) acc).run initial).1.auxiliaries = + emissions.foldl (fun current emission => max current (measure emission)) (base + acc.auxiliaries) := by + induction related generalizing acc initial with + | nil => exact ⟨aligned, rfl⟩ + | @cons item emission items emissions effect related ih => + rw [List.foldlM_cons] + have next := ih ((allocationBranchStep shared degrees acc (blockOf item)).run initial).1 + ((allocationBranchStep shared degrees acc (blockOf item)).run initial).2 + (allocationBranchStep_degrees ..) + ((allocationBranchStep_callRanks shared degrees acc (blockOf item) initial).trans generic) + rw [allocationBranchStep_column shared degrees acc (blockOf item) initial base + (measure emission) aligned generic effect] at next + exact next + +theorem allocationBranchLoop (branches : Array (G × Block)) (shared : SharedData) (degrees : Array Nat) : + branches.attach.foldlM (fun acc pair => allocationBranchStep shared degrees acc pair.val.2) shared = + branches.toList.foldlM (fun acc pair => allocationBranchStep shared degrees acc pair.2) shared := by + rw [← Array.foldlM_toList, Array.toList_attach, ← List.foldlM_map, + List.attachWith_map_val, List.foldlM_map] + +theorem matchLayout_allocation {β : Type} (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) (initial : LayoutMState) (base : Nat) (measure : β → Nat) + {cases defaults : List β} + (generic : initial.callRanks = #[]) + (caseEffects : List.Forall₂ (fun pair emission => ∀ state : LayoutMState, + state.callRanks = #[] → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → + measure emission = base + ((blockLayout pair.2).run state).2.functionLayout.auxiliaries) + branches.toList cases) + (defaultEffects : List.Forall₂ (fun block emission => ∀ state : LayoutMState, + state.callRanks = #[] → state.degrees = initial.degrees → + state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + branches.size → + measure emission = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) + fallback.toList defaults) : + ((ctrlLayout (.match index branches fallback)).run initial).2.degrees = initial.degrees ∧ + base + ((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout.auxiliaries = + (cases ++ defaults).foldl (fun current emission => max current (measure emission)) + (base + initial.functionLayout.auxiliaries) := by + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop : LayoutM SharedData := branches.attach.foldlM + (fun acc pair => allocationBranchStep shared initial.degrees acc pair.val.2) shared + have loopResult : (loop.run initial).2.degrees = initial.degrees ∧ + base + (loop.run initial).1.auxiliaries = + cases.foldl (fun current emission => max current (measure emission)) + (base + initial.functionLayout.auxiliaries) := by + dsimp only [loop] + rw [allocationBranchLoop] + exact allocationBranchFold Prod.snd measure shared initial.degrees base caseEffects shared initial rfl generic + have loopRanks : (loop.run initial).2.callRanks = #[] := by + dsimp only [loop] + rw [allocationBranchLoop] + exact (allocationBranchFold_callRanks branches.toList Prod.snd shared initial.degrees shared initial).trans generic + rw [ctrlLayout_eq_def] + cases fallback with + | none => + cases defaultEffects + change (loop.run initial).2.degrees = initial.degrees ∧ + base + (loop.run initial).1.auxiliaries = _ + simpa only [List.append_nil] using loopResult + | some block => + cases defaultEffects with + | cons effect tail => + cases tail + let before := ((bumpAuxiliaries branches.size).run + ((setSharedData shared).run (loop.run initial).2).2).2 + have body := effect before loopRanks loopResult.1 rfl + change initial.degrees = initial.degrees ∧ + base + max (loop.run initial).1.auxiliaries + ((blockLayout block).run before).2.functionLayout.auxiliaries = _ + constructor + · rfl + · rw [← Nat.add_max_add_left, ← body, loopResult.2] + simp only [List.foldl_append, List.foldl_cons, List.foldl_nil] + +theorem ctrlLayout_continue (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) (size aux slots : Nat) (continuation : Block) : + ctrlLayout (.matchContinue index branches fallback size aux slots continuation) = (do + ctrlLayout (.match index branches fallback) + bumpAuxiliaries size + pushDegrees (.replicate size 1) + blockLayout continuation) := by + exact ctrlLayout_eq_def _ + +end Aiur.Concrete.Bytecode diff --git a/Ix/Aiur/Proofs/CompilerLayout.lean b/Ix/Aiur/Proofs/CompilerLayout.lean new file mode 100644 index 000000000..c491d4a2e --- /dev/null +++ b/Ix/Aiur/Proofs/CompilerLayout.lean @@ -0,0 +1,387 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CompilerBranches + +/-! The compiler preserves input width, counts every leaf selector, and +retains the reserved auxiliary columns through branches and continuations. -/ + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode + +private theorem ops_fold_fields (ops : List Op) (initial : LayoutMState) : + let final := ((ops.foldlM (fun _ op => opLayout op) ()).run initial).2.functionLayout + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries := by + induction ops generalizing initial with + | nil => exact ⟨rfl, rfl, Nat.le_refl _⟩ + | cons op ops ih => + rw [List.foldlM_cons] + have fixed := opLayout_fixed op initial + have allocated := (opLayout_allocation op initial).2 + have rest := ih ((opLayout op).run initial).2 + exact ⟨rest.1.trans fixed.1, rest.2.1.trans fixed.2, + Nat.le_trans (by rw [allocated]; exact Nat.le_add_right _ _) rest.2.2⟩ + +theorem opsLayout_fields (ops : Array Op) (initial : LayoutMState) : + let final := ((ops.forM opLayout).run initial).2.functionLayout + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries := by + unfold Array.forM + rw [← Array.foldlM_toList] + exact ops_fold_fields ops.toList initial + +theorem allocationBranchStep_fields (shared : SharedData) (degrees : Array Nat) (acc : SharedData) + (block : Block) (initial : LayoutMState) + (effect : ∀ state : LayoutMState, + ((blockLayout block).run state).2.functionLayout.inputSize = state.functionLayout.inputSize ∧ + ((blockLayout block).run state).2.functionLayout.selectors = + state.functionLayout.selectors + block.controlCounts.leaves) : + let final := (allocationBranchStep shared degrees acc block).run initial + final.2.functionLayout.inputSize = initial.functionLayout.inputSize ∧ + final.2.functionLayout.selectors = initial.functionLayout.selectors + block.controlCounts.leaves ∧ + acc.auxiliaries ≤ final.1.auxiliaries := by + have body := effect ((setSharedData shared).run initial).2 + exact ⟨body.1, body.2, Nat.le_max_left _ _⟩ + +theorem allocationBranchFold_fields {α : Type} (items : List α) (blockOf : α → Block) + (shared : SharedData) (degrees : Array Nat) (acc : SharedData) (initial : LayoutMState) + (effect : ∀ item ∈ items, ∀ state : LayoutMState, + ((blockLayout (blockOf item)).run state).2.functionLayout.inputSize = state.functionLayout.inputSize ∧ + ((blockLayout (blockOf item)).run state).2.functionLayout.selectors = + state.functionLayout.selectors + (blockOf item).controlCounts.leaves) : + let final := (items.foldlM (fun acc item => allocationBranchStep shared degrees acc (blockOf item)) acc).run initial + final.2.functionLayout.inputSize = initial.functionLayout.inputSize ∧ + final.2.functionLayout.selectors = initial.functionLayout.selectors + + (items.map (fun item => (blockOf item).controlCounts.leaves)).sum ∧ + acc.auxiliaries ≤ final.1.auxiliaries := by + induction items generalizing acc initial with + | nil => exact ⟨rfl, (Nat.add_zero _).symm, Nat.le_refl _⟩ + | cons item items ih => + rw [List.foldlM_cons] + have first := allocationBranchStep_fields shared degrees acc (blockOf item) initial + (effect item List.mem_cons_self) + have rest := ih ((allocationBranchStep shared degrees acc (blockOf item)).run initial).1 + ((allocationBranchStep shared degrees acc (blockOf item)).run initial).2 + (fun item member => effect item (List.mem_cons_of_mem _ member)) + refine ⟨rest.1.trans first.1, ?_, Nat.le_trans first.2.2 rest.2.2⟩ + exact rest.2.1.trans (by rw [first.2.1]; simp only [List.map_cons, List.sum_cons, Nat.add_assoc]) + +theorem matchLayout_fields (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) (initial : LayoutMState) + (caseEffect : ∀ pair ∈ branches.toList, ∀ state : LayoutMState, + ((blockLayout pair.2).run state).2.functionLayout.inputSize = state.functionLayout.inputSize ∧ + ((blockLayout pair.2).run state).2.functionLayout.selectors = + state.functionLayout.selectors + pair.2.controlCounts.leaves) + (defaultEffect : ∀ block, fallback = some block → ∀ state : LayoutMState, + ((blockLayout block).run state).2.functionLayout.inputSize = state.functionLayout.inputSize ∧ + ((blockLayout block).run state).2.functionLayout.selectors = + state.functionLayout.selectors + block.controlCounts.leaves) : + let final := ((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors + + (ControlCounts.sum (branchControlCounts branches fallback)).leaves ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries := by + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop : LayoutM SharedData := branches.attach.foldlM + (fun acc pair => allocationBranchStep shared initial.degrees acc pair.val.2) shared + have loopResult : (loop.run initial).2.functionLayout.inputSize = initial.functionLayout.inputSize ∧ + (loop.run initial).2.functionLayout.selectors = initial.functionLayout.selectors + + (branches.toList.map (fun pair => pair.2.controlCounts.leaves)).sum ∧ + initial.functionLayout.auxiliaries ≤ (loop.run initial).1.auxiliaries := by + dsimp only [loop] + rw [allocationBranchLoop] + exact allocationBranchFold_fields branches.toList Prod.snd shared initial.degrees shared initial caseEffect + rw [ctrlLayout_eq_def] + cases present : fallback with + | none => + change (loop.run initial).2.functionLayout.inputSize = _ ∧ + (loop.run initial).2.functionLayout.selectors = _ ∧ + initial.functionLayout.auxiliaries ≤ (loop.run initial).1.auxiliaries + simpa only [branchControlCounts, ControlCounts.sum, Option.toList_none, List.map_nil, + List.append_nil, List.map_map, Function.comp_def] using loopResult + | some block => + let before := ((bumpAuxiliaries branches.size).run ((setSharedData shared).run (loop.run initial).2).2).2 + have body := defaultEffect block present before + change ((blockLayout block).run before).2.functionLayout.inputSize = _ ∧ + ((blockLayout block).run before).2.functionLayout.selectors = _ ∧ + initial.functionLayout.auxiliaries ≤ max (loop.run initial).1.auxiliaries _ + refine ⟨body.1.trans loopResult.1, ?_, Nat.le_trans loopResult.2.2 (Nat.le_max_left _ _)⟩ + rw [body.2] + change (loop.run initial).2.functionLayout.selectors + block.controlCounts.leaves = _ + rw [loopResult.2.1] + simp only [branchControlCounts, ControlCounts.sum, Option.toList_some, List.map_cons, + List.map_nil, List.map_append, List.map_map, Function.comp_def, List.sum_append, + List.sum_cons, List.sum_nil, Nat.add_zero, Nat.add_assoc] + +private theorem layout_case_smaller {branches : Array (G × Block)} {pair : G × Block} + (member : pair ∈ branches.toList) : sizeOf pair.2 < sizeOf branches := by + have bound := Array.sizeOf_lt_of_mem (Array.mem_toList_iff.mp member) + cases pair + simp at bound ⊢ + omega + +private theorem layout_default_smaller {fallback : Option Block} {block : Block} + (present : fallback = some block) : sizeOf block < sizeOf fallback := by + rw [present] + simp + +mutual + +theorem ctrlLayout_fields (ctrl : Ctrl) (initial : LayoutMState) : + let final := ((ctrlLayout ctrl).run initial).2.functionLayout + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors + ctrl.controlCounts.leaves ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries := by + cases ctrl with + | «return» index indices | yield index indices => + rw [ctrlLayout_eq_def, Ctrl.controlCounts.eq_def] + exact ⟨rfl, rfl, Nat.le_refl _⟩ + | «match» index branches fallback => + rw [Ctrl.controlCounts_match] + exact matchLayout_fields index branches fallback initial + (fun pair member state => ⟨(blockLayout_fields pair.2 state).1, (blockLayout_fields pair.2 state).2.1⟩) + (fun block present state => ⟨(blockLayout_fields block state).1, (blockLayout_fields block state).2.1⟩) + | matchContinue index branches fallback size aux slots continuation => + have first := matchLayout_fields index branches fallback initial + (fun pair member state => ⟨(blockLayout_fields pair.2 state).1, (blockLayout_fields pair.2 state).2.1⟩) + (fun block present state => ⟨(blockLayout_fields block state).1, (blockLayout_fields block state).2.1⟩) + let before := ((pushDegrees (.replicate size 1)).run ((bumpAuxiliaries size).run + ((ctrlLayout (.match index branches fallback)).run initial).2).2).2 + have rest := blockLayout_fields continuation before + rw [ctrlLayout_continue, Ctrl.controlCounts_matchContinue] + refine ⟨rest.1.trans first.1, ?_, ?_⟩ + · change ((blockLayout continuation).run before).2.functionLayout.selectors = _ + rw [rest.2.1] + change ((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout.selectors + _ = _ + rw [first.2.1, Nat.add_assoc] + rfl + · have monotone := rest.2.2 + change ((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout.auxiliaries + size ≤ _ at monotone + exact Nat.le_trans first.2.2 (Nat.le_trans (Nat.le_add_right _ _) monotone) +termination_by sizeOf ctrl +decreasing_by + all_goals subst ctrl + all_goals first + | (have bound := layout_case_smaller ‹_ ∈ _›; simp; omega) + | (have bound := layout_default_smaller ‹_ = some _›; simp; omega) + | decreasing_tactic + +theorem blockLayout_fields (block : Block) (initial : LayoutMState) : + let final := ((blockLayout block).run initial).2.functionLayout + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors + block.controlCounts.leaves ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries := by + rw [blockLayout, Block.controlCounts] + have first := opsLayout_fields block.ops initial + have rest := ctrlLayout_fields block.ctrl ((block.ops.forM opLayout).run initial).2 + exact ⟨rest.1.trans first.1, rest.2.1.trans (congrArg (· + block.ctrl.controlCounts.leaves) first.2.1), + Nat.le_trans first.2.2 rest.2.2⟩ +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +theorem ctrlLayout_match_list (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : + ctrlLayout (.match index branches fallback) = (do + let shared ← getSharedData + let degrees ← getDegrees + let acc ← branches.toList.foldlM (fun acc pair => allocationBranchStep shared degrees acc pair.2) shared + let final ← match fallback with + | none => pure acc + | some block => do + setSharedData shared + bumpAuxiliaries branches.size + blockLayout block + let used ← getSharedData + setDegrees degrees + pure (acc.maximals used) + setSharedData final) := by + rw [ctrlLayout_eq_def] + change (do + let shared ← getSharedData + let degrees ← getDegrees + let acc ← branches.attach.foldlM + (fun acc (pair : {pair // pair ∈ branches}) => allocationBranchStep shared degrees acc pair.val.2) shared + let final ← match fallback with + | none => pure acc + | some block => do + setSharedData shared + bumpAuxiliaries branches.size + blockLayout block + let used ← getSharedData + setDegrees degrees + pure (acc.maximals used) + setSharedData final) = _ + simp only [allocationBranchLoop] + +/-- Renaming preserves physical layout when it preserves the selected call +mode. The empty table used before component analysis satisfies this property. -/ +def LayoutRenaming (rename : FunIdx → FunIdx) (ranks : Array CallRank) : Prop := + ∀ function, ranks[rename function]?.getD .ordered = ranks[function]?.getD .ordered + +theorem layoutRenaming_empty (rename : FunIdx → FunIdx) : LayoutRenaming rename #[] := by + intro function + simp + +theorem rewriteOp_layout (rename : FunIdx → FunIdx) (op : Op) (initial : LayoutMState) + (compatible : LayoutRenaming rename initial.callRanks) : + (opLayout (rewriteOp rename op)).run initial = (opLayout op).run initial := by + cases op + case call function args outputSize unconstrained => + cases unconstrained <;> + simp [rewriteOp, opLayout, bumpLookups, bumpAuxiliaries, pushDegrees, + StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + bind, pure, compatible function] + all_goals rfl + +private theorem rewrite_branches_list (rename : FunIdx → FunIdx) (branches : Array (G × Block)) : + (branches.attach.map fun ⟨(tag, block), _⟩ => (tag, rewriteBlock rename block)).toList = + branches.toList.map (fun pair => (pair.1, rewriteBlock rename pair.2)) := by + simp only [Array.toList_map, Array.toList_attach] + exact List.attachWith_map_val (f := fun pair : G × Block => (pair.1, rewriteBlock rename pair.2)) _ + +private theorem foldlM_layout_equal {α β : Type} (items : List α) + (first second : β → α → LayoutM β) (ranks : Array CallRank) + (equal : ∀ item ∈ items, ∀ acc state, state.callRanks = ranks → + (first acc item).run state = (second acc item).run state) + (preserved : ∀ item ∈ items, ∀ acc state, + ((second acc item).run state).2.callRanks = state.callRanks) + (acc : β) (initial : LayoutMState) (aligned : initial.callRanks = ranks) : + (items.foldlM first acc).run initial = (items.foldlM second acc).run initial := by + induction items generalizing acc initial with + | nil => rfl + | cons item items ih => + rw [List.foldlM_cons, List.foldlM_cons] + change (let next := (first acc item).run initial; + (items.foldlM first next.1).run next.2) = + (let next := (second acc item).run initial; + (items.foldlM second next.1).run next.2) + rw [equal item List.mem_cons_self acc initial aligned] + exact ih (fun item member => equal item (List.mem_cons_of_mem _ member)) + (fun item member => preserved item (List.mem_cons_of_mem _ member)) + ((second acc item).run initial).1 ((second acc item).run initial).2 + ((preserved item List.mem_cons_self acc initial).trans aligned) + +theorem matchLayout_rewrite (rename : FunIdx → FunIdx) (index : ValIdx) + (branches : Array (G × Block)) (fallback : Option Block) + (ranks : Array CallRank) (initial : LayoutMState) (aligned : initial.callRanks = ranks) + (caseEqual : ∀ pair ∈ branches.toList, ∀ state, state.callRanks = ranks → + (blockLayout (rewriteBlock rename pair.2)).run state = (blockLayout pair.2).run state) + (defaultEqual : ∀ block, fallback = some block → ∀ state, state.callRanks = ranks → + (blockLayout (rewriteBlock rename block)).run state = (blockLayout block).run state) : + (ctrlLayout (.match index + (branches.attach.map fun ⟨(tag, block), _⟩ => (tag, rewriteBlock rename block)) + (fallback.map (rewriteBlock rename)))).run initial = (ctrlLayout (.match index branches fallback)).run initial := by + rw [ctrlLayout_match_list, ctrlLayout_match_list, rewrite_branches_list] + simp only [List.foldlM_map] + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop := branches.toList.foldlM + (fun acc pair => allocationBranchStep shared initial.degrees acc pair.2) shared + have loops : + (branches.toList.foldlM + (fun acc pair => allocationBranchStep shared initial.degrees acc (rewriteBlock rename pair.2)) shared).run initial = + loop.run initial := by + apply foldlM_layout_equal _ _ _ ranks ?_ ?_ shared initial aligned + · intro pair member acc state stateRanks + change (let result := (blockLayout (rewriteBlock rename pair.2)).run ((setSharedData shared).run state).2; + (acc.maximals ⟨result.2.functionLayout.auxiliaries, result.2.functionLayout.lookups⟩, + ((setDegrees initial.degrees).run result.2).2)) = _ + rw [caseEqual pair member ((setSharedData shared).run state).2 stateRanks] + rfl + · intro pair _ acc state + exact allocationBranchStep_callRanks shared initial.degrees acc pair.2 state + simp only [Array.size_map, Array.size_attach] + cases present : fallback with + | none => + change (let result := (branches.toList.foldlM + (fun acc pair => allocationBranchStep shared initial.degrees acc (rewriteBlock rename pair.2)) shared).run initial; + (setSharedData result.1).run result.2) = _ + rw [loops] + rfl + | some block => + let before := ((bumpAuxiliaries branches.size).run + ((setSharedData shared).run (loop.run initial).2).2).2 + have beforeRanks : before.callRanks = ranks := + (allocationBranchFold_callRanks branches.toList Prod.snd shared initial.degrees shared initial).trans aligned + change (let branchResult := (branches.toList.foldlM + (fun acc pair => allocationBranchStep shared initial.degrees acc (rewriteBlock rename pair.2)) shared).run initial; + let result := (blockLayout (rewriteBlock rename block)).run + ((bumpAuxiliaries branches.size).run ((setSharedData shared).run branchResult.2).2).2; + (setSharedData (branchResult.1.maximals + ⟨result.2.functionLayout.auxiliaries, result.2.functionLayout.lookups⟩)).run + ((setDegrees initial.degrees).run result.2).2) = _ + rw [loops] + dsimp only + rw [defaultEqual block present before beforeRanks] + rfl + +mutual + +theorem rewriteCtrl_layout (rename : FunIdx → FunIdx) (ctrl : Ctrl) (initial : LayoutMState) + (compatible : LayoutRenaming rename initial.callRanks) : + (ctrlLayout (rewriteCtrl rename ctrl)).run initial = (ctrlLayout ctrl).run initial := by + cases ctrl with + | «return» index indices | yield index indices => rw [rewriteCtrl.eq_def] + | «match» index branches fallback => + rw [rewriteCtrl.eq_def] + have equal := matchLayout_rewrite rename index branches fallback + initial.callRanks initial rfl + (fun pair member state aligned => rewriteBlock_layout rename pair.2 state (aligned ▸ compatible)) + (fun block present state aligned => rewriteBlock_layout rename block state (aligned ▸ compatible)) + cases fallback <;> exact equal + | matchContinue index branches fallback size aux slots continuation => + rw [rewriteCtrl.eq_def, ctrlLayout_continue, ctrlLayout_continue] + have equal := matchLayout_rewrite rename index branches fallback + initial.callRanks initial rfl + (fun pair member state aligned => rewriteBlock_layout rename pair.2 state (aligned ▸ compatible)) + (fun block present state aligned => rewriteBlock_layout rename block state (aligned ▸ compatible)) + cases fallback <;> simp only [Option.map_none, Option.map_some] at equal ⊢ + all_goals + change (blockLayout (rewriteBlock rename continuation)).run + ((pushDegrees (.replicate size 1)).run ((bumpAuxiliaries size).run + ((ctrlLayout _).run initial).2).2).2 = _ + rw [equal] + apply rewriteBlock_layout + change LayoutRenaming rename ((ctrlLayout _).run initial).2.callRanks + rw [ctrlLayout_callRanks] + exact compatible +termination_by sizeOf ctrl +decreasing_by + all_goals subst ctrl + all_goals first + | (have bound := layout_case_smaller ‹_ ∈ _›; simp; omega) + | (have bound := layout_default_smaller ‹_ = some _›; simp; omega) + | decreasing_tactic + +theorem rewriteBlock_layout (rename : FunIdx → FunIdx) (block : Block) (initial : LayoutMState) + (compatible : LayoutRenaming rename initial.callRanks) : + (blockLayout (rewriteBlock rename block)).run initial = (blockLayout block).run initial := by + have operations : ((block.ops.map (rewriteOp rename)).forM opLayout).run initial = + (block.ops.forM opLayout).run initial := by + simp only [Array.forM, ← Array.foldlM_toList, Array.toList_map, List.foldlM_map] + apply foldlM_layout_equal _ _ _ initial.callRanks ?_ ?_ () initial rfl + · intro op _ _ state aligned + exact rewriteOp_layout rename op state (aligned ▸ compatible) + · intro op _ _ state + exact opLayout_callRanks op state + rw [rewriteBlock, blockLayout, blockLayout] + change (ctrlLayout (rewriteCtrl rename block.ctrl)).run + (((block.ops.map (rewriteOp rename)).forM opLayout).run initial).2 = _ + rw [operations] + exact rewriteCtrl_layout rename block.ctrl ((block.ops.forM opLayout).run initial).2 + (by + change LayoutRenaming rename ((block.ops.forM opLayout).run initial).2.context.2 + rw [opsLayout_context] + exact compatible) +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +end Aiur.Concrete.Bytecode diff --git a/Ix/Aiur/Proofs/Dedup.lean b/Ix/Aiur/Proofs/Dedup.lean new file mode 100644 index 000000000..96d754b3a --- /dev/null +++ b/Ix/Aiur/Proofs/Dedup.lean @@ -0,0 +1,67 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Renaming + +/-! The actual deduplication pass validates its proposed transformation. +These proofs require no correctness assumption about partition refinement. -/ + +namespace Aiur.Bytecode.Eval + +theorem validatesRenaming_sound {a b : Toplevel} {rename : FunIdx → FunIdx} + (valid : validatesRenaming a b (boundedRenaming a rename) = true) : + RenamedCode a b (boundedRenaming a rename) := by + simp only [validatesRenaming, Bool.and_eq_true, decide_eq_true_eq] at valid + have all := Array.all_eq_true.mp valid.2 + simp only [Array.size_range, Array.getElem_range] at all + have checked (i : Nat) (hi : i < a.functions.size) : + ∃ hj : boundedRenaming a rename i < b.functions.size, + a.functions[i].layout = b.functions[boundedRenaming a rename i].layout ∧ + rewriteBlock (boundedRenaming a rename) a.functions[i].body = + b.functions[boundedRenaming a rename i].body := by + have h := all i hi + simp only [dif_pos hi] at h + split at h + next hj => exact ⟨hj, by simpa only [Bool.and_eq_true, beq_iff_eq] using h⟩ + next hj => contradiction + constructor + · intro i + constructor + · intro hi + obtain ⟨hj, _⟩ := checked i hi + exact hj + · intro hj + by_cases hi : i < a.functions.size + · exact hi + · simp only [boundedRenaming, if_neg hi] at hj + exact Nat.lt_of_lt_of_le hj valid.1 + · intro i hi hj + obtain ⟨_, _, body⟩ := checked i hi + exact body + · intro i hi hj + obtain ⟨_, layout, _⟩ := checked i hi + exact congrArg FunctionLayout.inputSize layout + +theorem checkedRenaming_preserves_execution (source candidate : Toplevel) (rename : FunIdx → FunIdx) + (function : FunIdx) (args : Array G) (io : IOBuffer) (fuel : Nat) (result : Array G × IOBuffer) : + runFunction source function args io fuel = .ok result ↔ + runFunction (checkedRenaming source candidate rename).1 + ((checkedRenaming source candidate rename).2 function) + args io fuel = .ok result := by + unfold checkedRenaming + dsimp only + split + next valid => exact runFunction_renamed_iff (validatesRenaming_sound valid) function args io fuel result + next invalid => rfl + +theorem deduplicate_preserves_execution (source : Toplevel) + (function : FunIdx) (args : Array G) (io : IOBuffer) (fuel : Nat) (result : Array G × IOBuffer) : + runFunction source function args io fuel = .ok result ↔ + runFunction source.deduplicate.1 (source.deduplicate.2 function) + args io fuel = .ok result := + checkedRenaming_preserves_execution source source.deduplicateCandidate.1 source.deduplicateCandidate.2 + function args io fuel result + +end Aiur.Bytecode.Eval diff --git a/Ix/Aiur/Proofs/Domain.lean b/Ix/Aiur/Proofs/Domain.lean new file mode 100644 index 000000000..2321e26d8 --- /dev/null +++ b/Ix/Aiur/Proofs/Domain.lean @@ -0,0 +1,179 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Domain +import Ix.Aiur.Proofs.SelectorAlgebra + +/-! Exact orders and row locations for all 33 native trace-domain generators. +The finite certificates evaluate bounded repeated squaring in the kernel; +the domain itself is represented by an index function, without enumeration. +-/ + +namespace Aiur.NativeAIR.Domain + +open Lean.Grind + +theorem ofLogSize_some {bits : Nat} {domain : Subgroup} + (accepted : ofLogSize bits = some domain) : domain.val = bits := by + simp only [ofLogSize] at accepted + split at accepted + · exact congrArg Fin.val (Option.some.inj accepted).symm + · cases accepted + +theorem ofLogSize_defined (bits : Nat) : (ofLogSize bits).isSome = (bits < 33) := by + simp only [ofLogSize] + split <;> simp_all + +theorem size_positive (domain : Subgroup) : 0 < size domain := Nat.two_pow_pos _ + +theorem size_bound (domain : Subgroup) : size domain ≤ 2 ^ 32 := by + apply Nat.pow_le_pow_right (by decide) + have := domain.isLt + omega + +theorem size_lt_characteristic (domain : Subgroup) : size domain < gSize.toNat := + Nat.lt_of_le_of_lt (size_bound domain) (by decide) + +theorem size_lt_u64 (domain : Subgroup) : size domain < 2 ^ 64 := + Nat.lt_of_le_of_lt (size_bound domain) (by decide) + +theorem generator_zero : generator 0 = 1 := by decide +kernel + +theorem generator_square_certificate : ∀ index : Fin 32, + generator ⟨index.val + 1, by omega⟩ * generator ⟨index.val + 1, by omega⟩ = + generator ⟨index.val, by omega⟩ := by + decide +kernel + +theorem generator_full_certificate : ∀ domain : Subgroup, + G.pow (generator domain) (size domain) = 1 := by + decide +kernel + +theorem generator_half_certificate : ∀ index : Fin 32, + G.pow (generator ⟨index.val + 1, by omega⟩) (2 ^ index.val) = 0 - 1 := by + decide +kernel + +theorem generator_power (domain : Subgroup) : generator domain ^ size domain = 1 := by + rw [← G.pow_eq _ _ (size_lt_u64 domain)] + exact generator_full_certificate domain + +theorem generator_half (index : Fin 32) : + generator ⟨index.val + 1, by omega⟩ ^ (2 ^ index.val) = 0 - 1 := by + rw [← G.pow_eq _ _ (by + apply Nat.lt_of_le_of_lt (Nat.pow_le_pow_right (by decide) (Nat.le_of_lt index.isLt)) + decide)] + exact generator_half_certificate index + +theorem generator_nonzero (domain : Subgroup) : generator domain ≠ 0 := by + intro zero + have power := generator_power domain + have positive := size_positive domain + have successor : size domain = (size domain - 1) + 1 := by omega + rw [zero, successor, Semiring.pow_succ, G.mul_zero] at power + exact G.one_ne_zero power.symm + +theorem point_eq (domain : Subgroup) (index : Fin (size domain)) : + point domain index = generator domain ^ index.val := + G.pow_eq _ _ (Nat.lt_trans index.isLt (size_lt_u64 domain)) + +theorem point_injective (domain : Subgroup) {i j : Fin (size domain)} + (equal : point domain i = point domain j) : i = j := by + apply Fin.ext + cases domain with + | mk bits bounded => + cases bits with + | zero => have := i.isLt; have := j.isLt; simp only [size, Nat.pow_zero] at *; omega + | succ bits => + have full := congrArg G.n (generator_power ⟨bits + 1, bounded⟩) + have half := congrArg G.n (generator_half ⟨bits, by omega⟩) + have same := congrArg G.n equal + simp only [point_eq, G.n_power] at same + simp only [G.n_power, size] at full half + apply GoldilocksProof.pow_mod_injective (by decide) full + (fun h => (by decide : G.n (0 - 1) ≠ 1) (half.symm.trans h)) i.isLt j.isLt same + +theorem generator_order (domain : Subgroup) (n : Nat) : + generator domain ^ n = 1 ↔ size domain ∣ n := by + have period := Algebra.power_period (generator domain) (generator_power domain) n + constructor + · intro equal + have same : point domain ⟨n % size domain, Nat.mod_lt _ (size_positive domain)⟩ = + point domain ⟨0, size_positive domain⟩ := by + simp only [point_eq, Semiring.pow_zero] + exact period.symm.trans equal + have zero := congrArg Fin.val (point_injective domain same) + exact Nat.dvd_of_mod_eq_zero zero + · intro divides + rw [period, Nat.mod_eq_zero_of_dvd divides, Semiring.pow_zero] + +theorem point_zero (domain : Subgroup) : point domain ⟨0, size_positive domain⟩ = 1 := by + rw [point_eq, Semiring.pow_zero] + +theorem point_power (domain : Subgroup) (index : Fin (size domain)) : + point domain index ^ size domain = 1 := by + rw [point_eq, ← Algebra.power_mul, Nat.mul_comm, Algebra.power_mul, + generator_power, Semiring.one_pow] + +theorem point_nonzero (domain : Subgroup) (index : Fin (size domain)) : + point domain index ≠ 0 := by + intro zero + have power := point_power domain index + rw [zero, Algebra.power_zero _ (size_positive domain)] at power + exact G.one_ne_zero power.symm + +theorem point_next (domain : Subgroup) (index : Fin (size domain)) : + point domain ⟨(index.val + 1) % size domain, Nat.mod_lt _ (size_positive domain)⟩ = + point domain index * generator domain := by + rw [point_eq, point_eq, ← Algebra.power_period _ (generator_power domain), Semiring.pow_succ] + +theorem point_first_iff (domain : Subgroup) (index : Fin (size domain)) : + point domain index = 1 ↔ index.val = 0 := by + constructor + · intro equal + exact congrArg Fin.val (point_injective domain (equal.trans (point_zero domain).symm)) + · intro zero + rw [point_eq, zero, Semiring.pow_zero] + +theorem lastPoint_eq_power (domain : Subgroup) : + lastPoint domain = generator domain ^ (size domain - 1) := by + exact (Algebra.predecessor_inverse _ _ (size_positive domain) (generator_power domain) + (G.mul_inverse_cancel _ (generator_nonzero domain))).symm + +theorem point_last (domain : Subgroup) : + point domain ⟨size domain - 1, by have := size_positive domain; omega⟩ = lastPoint domain := by + rw [point_eq, lastPoint_eq_power] + +theorem lastPoint_power (domain : Subgroup) : lastPoint domain ^ size domain = 1 := by + rw [← point_last domain] + exact point_power _ _ + +theorem point_last_iff (domain : Subgroup) (index : Fin (size domain)) : + point domain index = lastPoint domain ↔ index.val = size domain - 1 := by + constructor + · intro equal + exact congrArg Fin.val (point_injective domain (equal.trans (point_last domain).symm)) + · intro equal + rw [point_eq, equal, lastPoint_eq_power] + +theorem lastPoint_nonzero (domain : Subgroup) : lastPoint domain ≠ 0 := by + rw [← point_last domain] + exact point_nonzero _ _ + +theorem lastPoint_inverse (domain : Subgroup) : lastPoint domain * generator domain = 1 := by + rw [G.mul_comm] + exact G.mul_inverse_cancel _ (generator_nonzero domain) + +theorem lastPoint_predecessor (domain : Subgroup) : + lastPoint domain ^ (size domain - 1) = generator domain := + Algebra.predecessor_inverse _ _ (size_positive domain) (lastPoint_power domain) + (lastPoint_inverse domain) + +theorem normalizer_nonzero (domain : Subgroup) : normalizer domain ≠ 0 := by + intro zero + have factors := (G.mul_eq_zero_iff _ _).mp zero + exact factors.elim + (G.ofNat_ne_zero_of_lt (size_positive domain) (size_lt_characteristic domain)) + (generator_nonzero domain) + +end Aiur.NativeAIR.Domain diff --git a/Ix/Aiur/Proofs/DomainAccumulator.lean b/Ix/Aiur/Proofs/DomainAccumulator.lean new file mode 100644 index 000000000..b6ed1fa3f --- /dev/null +++ b/Ix/Aiur/Proofs/DomainAccumulator.lean @@ -0,0 +1,142 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Selectors +import Ix.Aiur.Proofs.LogUpAccumulator + +/-! Actual domain normalization discharges the scaled boundary injection. +Every checked group in every cyclic trace row contributes to the circuit's +lookup fraction sum, provided the compressed base-field messages avoid poles. +-/ + +namespace Aiur.NativeAIR.LogUp + +open ProofCodec (Extension) + +theorem normalized_injection (domain : Domain.Subgroup) (index : Fin (Domain.size domain)) + (delta : Coordinates G) : + (delta.scale (Domain.normalizer domain).inverse).scale + (Domain.Algebra.dividedPowers (Domain.point domain index) (Domain.lastPoint domain) (Domain.size domain)) = + if index.val = Domain.size domain - 1 then delta else 0 := by + rw [Domain.last_at_row] + have cancel : (Domain.normalizer domain).inverse * Domain.normalizer domain = 1 := by + rw [G.mul_comm] + exact G.mul_inverse_cancel _ (Domain.normalizer_nonzero domain) + by_cases last : index.val = Domain.size domain - 1 + · simp only [if_pos last] + apply Coordinates.ext <;> simp only [Coordinates.scale] <;> rw [G.mul_assoc, cancel, G.mul_one] + · simp only [if_neg last] + apply Coordinates.ext <;> simp only [Coordinates.scale, G.mul_zero] <;> rfl + +theorem equations_domain_row (domain : Domain.Subgroup) (index : Fin (Domain.size domain)) + {lookups : List (G × List G)} {stageCurrent stageNext publics deltaScaled : Array G} + {groupSize : Nat} {result : List (Coordinates G)} {beta gamma delta : Coordinates G} + (betaRead : Coordinates.read publics 0 = some beta) (gammaRead : Coordinates.read publics 1 = some gamma) + (deltaRead : Coordinates.read deltaScaled 0 = some (delta.scale (Domain.normalizer domain).inverse)) + (accepted : equations lookups stageCurrent stageNext publics deltaScaled + (Domain.Algebra.dividedPowers (Domain.point domain index) (Domain.lastPoint domain) (Domain.size domain)) + groupSize = some result) + (zero : ∀ value ∈ result, value = 0) + (free : PoleFree (fieldEntries (compress beta gamma lookups))) : + ∃ first next, Coordinates.read stageCurrent 0 = some first ∧ + Coordinates.read stageNext 0 = some next ∧ + next.toExtension - first.toExtension + + (if index.val = Domain.size domain - 1 then delta.toExtension else 0) = + lookupFractions beta gamma lookups := by + obtain ⟨first, next, scaled, hf, hn, hd, equation⟩ := equations_accumulator betaRead gammaRead accepted zero free + have same := Option.some.inj (hd.symm.trans deltaRead) + subst scaled + rw [normalized_injection] at equation + refine ⟨first, next, hf, hn, ?_⟩ + by_cases last : index.val = Domain.size domain - 1 + · simpa only [if_pos last] using equation + · have zeroEmbed : (0 : Coordinates G).toExtension = 0 := (Coordinates.toExtension_zero_iff _).mpr rfl + simpa only [if_neg last, zeroEmbed] using equation + +theorem equations_domain_sum (domain : Domain.Subgroup) + (lookups : Fin (Domain.size domain) → List (G × List G)) + (stageRows : Fin (Domain.size domain) → Array G) (publics deltaScaled : Array G) + (groupSize : Nat) (beta gamma delta : Coordinates G) + (betaRead : Coordinates.read publics 0 = some beta) (gammaRead : Coordinates.read publics 1 = some gamma) + (deltaRead : Coordinates.read deltaScaled 0 = some (delta.scale (Domain.normalizer domain).inverse)) + (rows : ∀ index : Fin (Domain.size domain), ∃ result, + equations (lookups index) (stageRows index) + (stageRows ⟨(index.val + 1) % Domain.size domain, Nat.mod_lt _ (Domain.size_positive domain)⟩) + publics deltaScaled + (Domain.Algebra.dividedPowers (Domain.point domain index) (Domain.lastPoint domain) (Domain.size domain)) + groupSize = some result ∧ (∀ value ∈ result, value = 0)) + (free : ∀ index, PoleFree (fieldEntries (compress beta gamma (lookups index)))) : + sum (List.ofFn fun index => lookupFractions beta gamma (lookups index)) = delta.toExtension := by + let rowIndex := fun index => (⟨index % Domain.size domain, Nat.mod_lt _ (Domain.size_positive domain)⟩ : + Fin (Domain.size domain)) + let states := fun index => ((Coordinates.read (stageRows (rowIndex index)) 0).getD 0).toExtension + let fractions := fun index => lookupFractions beta gamma (lookups (rowIndex index)) + have wrap : states (Domain.size domain) = states 0 := by + simp only [states, rowIndex, Nat.mod_self, Nat.zero_mod] + have steps : ∀ index, index < Domain.size domain → + states (index + 1) - states index + + (if index + 1 = Domain.size domain then delta.toExtension else 0) = fractions index := by + intro index bound + let i : Fin (Domain.size domain) := ⟨index, bound⟩ + obtain ⟨result, accepted, zero⟩ := rows i + obtain ⟨first, next, hf, hn, equation⟩ := + equations_domain_row domain i betaRead gammaRead deltaRead accepted zero (free i) + dsimp only [i] at hf hn + have source : states index = first.toExtension := by + simp only [states, rowIndex, Nat.mod_eq_of_lt bound, hf, Option.getD_some] + have target : states (index + 1) = next.toExtension := by + simp only [states, rowIndex, hn, Option.getD_some] + have fraction : fractions index = lookupFractions beta gamma (lookups i) := by + simp only [fractions, rowIndex, Nat.mod_eq_of_lt bound, i] + rw [source, target, fraction] + have condition : (i.val = Domain.size domain - 1) ↔ (index + 1 = Domain.size domain) := by + have := Domain.size_positive domain + simp only [i] + omega + simpa only [condition] using equation + have total := cyclic_accumulator states fractions (Domain.size domain) delta.toExtension + (Domain.size_positive domain) wrap steps + have enumeration : (List.range (Domain.size domain)).map fractions = + List.ofFn (fun index => lookupFractions beta gamma (lookups index)) := by + apply List.ext_getElem + · simp only [List.length_map, List.length_range, List.length_ofFn] + · intro index left right + have bound : index < Domain.size domain := by simpa only [List.length_ofFn] using right + simp only [List.getElem_map, List.getElem_range, List.getElem_ofFn, + fractions, rowIndex, Nat.mod_eq_of_lt bound] + rwa [enumeration] at total + +theorem constraintValues_domain_sum (domain : Domain.Subgroup) (lookups : List Lookup) + (nodeRows stageRows : Fin (Domain.size domain) → Array G) (publics deltaScaled : Array G) + (groupSize : Nat) (beta gamma delta : Coordinates G) + (betaRead : Coordinates.read publics 0 = some beta) (gammaRead : Coordinates.read publics 1 = some gamma) + (deltaRead : Coordinates.read deltaScaled 0 = some (delta.scale (Domain.normalizer domain).inverse)) + (rows : ∀ index : Fin (Domain.size domain), ∃ result, + constraintValues lookups (nodeRows index) (stageRows index) + (stageRows ⟨(index.val + 1) % Domain.size domain, Nat.mod_lt _ (Domain.size_positive domain)⟩) + publics deltaScaled + (Domain.Algebra.dividedPowers (Domain.point domain index) (Domain.lastPoint domain) (Domain.size domain)) + groupSize = some result ∧ (∀ value ∈ result, value = 0)) + (free : ∀ index values, lookups.mapM (readLookup (nodeRows index)) = some values → + PoleFree (fieldEntries (compress beta gamma values))) : + ∃ values : Fin (Domain.size domain) → List (G × List G), + (∀ index, lookups.mapM (readLookup (nodeRows index)) = some (values index)) ∧ + sum (List.ofFn fun index => lookupFractions beta gamma (values index)) = delta.toExtension := by + let values := fun index => (lookups.mapM (readLookup (nodeRows index))).getD [] + have reads : ∀ index, lookups.mapM (readLookup (nodeRows index)) = some (values index) := by + intro index + obtain ⟨result, accepted, _⟩ := rows index + obtain ⟨readValues, _, read, _, _⟩ := constraintValues_success accepted + simp only [values, read, Option.getD_some] + refine ⟨values, reads, equations_domain_sum domain values stageRows publics deltaScaled groupSize + beta gamma delta betaRead gammaRead deltaRead ?_ (fun index => free index (values index) (reads index))⟩ + intro index + obtain ⟨result, accepted, zero⟩ := rows index + obtain ⟨readValues, coordinates, read, equations, rfl⟩ := constraintValues_success accepted + have same := Option.some.inj (read.symm.trans (reads index)) + subst readValues + exact ⟨coordinates, equations, (Coordinates.flatten_zero_iff coordinates).mp zero⟩ + +end Aiur.NativeAIR.LogUp diff --git a/Ix/Aiur/Proofs/EmissionAllocation.lean b/Ix/Aiur/Proofs/EmissionAllocation.lean new file mode 100644 index 000000000..d72e5d8d0 --- /dev/null +++ b/Ix/Aiur/Proofs/EmissionAllocation.lean @@ -0,0 +1,314 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationDegrees +import Ix.Aiur.Proofs.CompilerAllocation + +/-! Symbolic emission agrees with the compiler's logical degrees and physical +auxiliary allocation. Degree-zero constant folding is justified by the invariant +preserved from the initial advice map. -/ + +namespace Aiur.NativeAIR.OpEmitter +open Aiur.Bytecode + +def rowDegrees (rows : Array RowExpr) : Array Nat := rows.map RowExpr.degree + +theorem rowDegrees_empty : rowDegrees #[] = #[] := Array.map_empty + +theorem rowDegrees_append (left right : Array RowExpr) : + rowDegrees (left ++ right) = rowDegrees left ++ rowDegrees right := Array.map_append + +theorem rowDegrees_push (rows : Array RowExpr) (row : RowExpr) : + rowDegrees (rows.push row) = (rowDegrees rows).push row.degree := Array.map_push + +theorem rowDegrees_singleton (row : RowExpr) : rowDegrees #[row] = #[row.degree] := + Array.map_singleton + +theorem rowDegrees_getD (rows : Array RowExpr) (index : Nat) : + (rowDegrees rows)[index]?.getD 0 = (rows[index]?.getD (.konst 0)).degree := by + simp only [rowDegrees, Array.getElem?_map] + cases rows[index]? <;> rfl + +theorem rowDegrees_read {rows : Array RowExpr} {index : Nat} {row : RowExpr} + (read : rows[index]? = some row) : (rowDegrees rows)[index]?.getD 0 = row.degree := by + rw [rowDegrees_getD, read] + rfl + +theorem select_degrees {rows : Array RowExpr} {indices : Array Nat} {selected : Array RowExpr} + (read : select rows indices = some selected) : + indices.map (fun index => (rowDegrees rows)[index]?.getD 0) = rowDegrees selected := by + have selectedMap := congrArg rowDegrees (array_map_getD_of_mapM (.konst 0) read) + simpa only [rowDegrees, Array.map_map, Function.comp_def, ← rowDegrees_getD] using selectedMap + +theorem advice_degrees (first count : Nat) : + rowDegrees (advice first count) = Array.replicate count 1 := by + apply Array.ext (by simp only [rowDegrees, Array.size_map, advice, Array.size_ofFn, Array.size_replicate]) + intro index _ _ + simp only [rowDegrees, advice, Array.getElem_map, Array.getElem_ofFn, + Array.getElem_replicate, mainCurrent, RowExpr.variable] + +theorem packFour_degree (bytes : Fin 4 → RowExpr) : + (packFour bytes).degree = (rowDegrees (Array.ofFn bytes)).foldl Nat.max 0 := by + simp only [rowDegrees, Array.map_ofFn, ← Array.foldl_toList, Array.toList_ofFn, + list_ofFn_four, List.foldl_cons, List.foldl_nil, Function.comp_def, + packFour, RowExpr.add, RowExpr.mul, RowExpr.konst, Nat.add_zero] + +theorem readWord_degree {rows : Array RowExpr} {indices : Array Nat} {word : RowExpr} + (read : readWord rows indices = some word) : + word.degree = selectedDegree (rowDegrees rows) indices 0 := by + simp only [readWord, bind, Option.bind] at read + split at read + · cases read + next size => + cases selected : select rows indices <;> simp only [selected] at read + · cases read + next bytes => + cases read + have width : indices.size = 4 := by omega + rw [packFour_degree, array_ofFn_getD bytes (.konst 0) ((array_mapM_size selected).trans width)] + simp only [selectedDegree, select_degrees selected] + +def Emission.allocation (emission : Emission) : OpAllocation := + ⟨rowDegrees emission.outputs, emission.used⟩ + +theorem emitAdvice_allocation (first count : Nat) : + (emitAdvice first count).allocation = .advice count := by + simp only [Emission.allocation, emitAdvice, advice_degrees, OpAllocation.advice] + +theorem emitWordSum_allocation (first : Nat) (sum : RowExpr) : + (emitWordSum first sum).allocation = ⟨(Array.replicate 4 1).push (max sum.degree 1), 4⟩ := by + simp only [Emission.allocation, emitWordSum, rowDegrees_push, advice_degrees, + RowExpr.mul, RowExpr.sub, RowExpr.konst, packedAdvice, packFour, RowExpr.add, + mainCurrent, RowExpr.variable, Nat.add_zero] + rfl + +theorem emitByte1_dispatch_allocation (selector rank : Expr) (first : Nat) (kind : AIR.Byte1Kind) + (index : Nat) {rows : Array RowExpr} {emission : Emission} + (emitted : emitOp selector rank first (kind.op index) rows = some emission) : + emission.allocation = (kind.op index).allocation (rowDegrees rows) := by + rw [emitOp_byte1] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + cases kind <;> simp only [Emission.allocation, emitByte1, advice_degrees, + AIR.Byte1Kind.op, AIR.Byte1Kind.outputSize, Op.allocation, OpAllocation.advice] + +theorem emitByte2_dispatch_allocation (selector rank : Expr) (first : Nat) (kind : AIR.Byte2Kind) + (a b : Nat) {rows : Array RowExpr} {emission : Emission} + (emitted : emitOp selector rank first (kind.op a b) rows = some emission) : + emission.allocation = (kind.op a b).allocation (rowDegrees rows) := by + rw [emitOp_byte2] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + have degreeA := rowDegrees_read readA + have degreeB := rowDegrees_read readB + cases kind <;> simp only [Emission.allocation, emitByte2, advice_degrees, rowDegrees_push, + AIR.Byte2Kind.op, AIR.Byte2Kind.outputSize, Op.allocation, OpAllocation.advice, + byteCarry, degreeA, degreeB] <;> rfl + +theorem emitOp_allocation {selector rank : Expr} {first : Nat} {op : Op} + {rows : Array RowExpr} {emission : Emission} (valid : DegreeValid rows) + (emitted : emitOp selector rank first op rows = some emission) : + emission.allocation = op.allocation (rowDegrees rows) := by + cases op with + | const value => + cases emitted + simp only [Emission.allocation, fromScalar, rowDegrees_singleton, RowExpr.konst, Op.allocation] + | add a b | sub a b | mul a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + have degreeA := rowDegrees_read readA + have degreeB := rowDegrees_read readB + simp only [Emission.allocation, fromScalar, rowDegrees_singleton, Op.allocation, degreeA, degreeB] + first + | rfl + | (simp only [emitMul, RowExpr.mul]; split <;> + simp_all only [if_pos, mulRegular, mainCurrent, RowExpr.variable, OpAllocation.advice] <;> rfl) + | eqZero index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i input read + cases emitted + have allocated := emitEqZero_allocation selector first (valid.read read) + simp only [Emission.allocation, fromScalar, rowDegrees_singleton, Op.allocation, rowDegrees_read read] + split at allocated <;> + simp_all only [Prod.mk.injEq, if_true, if_false] + | call function indices size unconstrained => + cases unconstrained with + | true => + cases emitted + simp only [emitAdvice_allocation, Op.allocation, if_true, Nat.add_zero, OpAllocation.advice] + | false => + simp only [emitOp, Bool.false_eq_true, if_false, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + simp only [Emission.allocation, emitCall, advice_degrees, Op.allocation, + Bool.false_eq_true, if_false] + | store indices | load size index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + simp only [Emission.allocation, emitStore, emitLoad, advice_degrees, Op.allocation, OpAllocation.advice] + | assertEq xs ys message => + simp only [emitOp] at emitted + split at emitted + · cases emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + simp only [Emission.allocation, emitAssert, rowDegrees_empty, Op.allocation] + | ioGetInfo | ioRead | unconstrainedBigUintDivMod | unconstrainedGToBytes | unconstrainedGInverse => + cases emitted + exact emitAdvice_allocation _ _ + | ioSetInfo | ioWrite | debug => + cases emitted + simp only [Emission.allocation, rowDegrees_empty, Op.allocation] + | u8BitDecomposition index => exact emitByte1_dispatch_allocation selector rank first .bits index emitted + | u8ShiftLeft index => exact emitByte1_dispatch_allocation selector rank first .shiftLeft index emitted + | u8ShiftRight index => exact emitByte1_dispatch_allocation selector rank first .shiftRight index emitted + | u8Xor a b => exact emitByte2_dispatch_allocation selector rank first .xor a b emitted + | u8Add a b => exact emitByte2_dispatch_allocation selector rank first .add a b emitted + | u8Sub a b => exact emitByte2_dispatch_allocation selector rank first .sub a b emitted + | u8And a b => exact emitByte2_dispatch_allocation selector rank first .and a b emitted + | u8Or a b => exact emitByte2_dispatch_allocation selector rank first .or a b emitted + | u8LessThan a b => exact emitByte2_dispatch_allocation selector rank first .lessThan a b emitted + | u8RangeCheck a b => exact emitByte2_dispatch_allocation selector rank first .range a b emitted + | u8Mul a b => exact emitByte2_dispatch_allocation selector rank first .mul a b emitted + | u8XorSplit7 a b => exact emitByte2_dispatch_allocation selector rank first .split7 a b emitted + | u8XorSplit4 a b => exact emitByte2_dispatch_allocation selector rank first .split4 a b emitted + | u32LessThan a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + simp only [Emission.allocation, emitU32LessThan, rowDegrees_singleton, Op.allocation] + | unconstrainedU32Add a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + simp only [emitWordSum_allocation, Op.allocation, RowExpr.add, + readWord_degree readA, readWord_degree readB, selectedDegree_append, + selectedDegree_initial (rowDegrees rows) a 1] + simp only [Nat.max_assoc, Nat.max_comm] + | unconstrainedU32Add3 a b c => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + dsimp only at emitted + split at emitted + · cases emitted + rename_i third readC + cases emitted + simp only [emitWordSum_allocation, Op.allocation, RowExpr.add, + readWord_degree readA, readWord_degree readB, readWord_degree readC, + selectedDegree_append, selectedDegree_initial (rowDegrees rows) a 1] + simp only [Nat.max_assoc, Nat.max_comm] + | u32ToField indices => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i word read + cases emitted + simp only [Emission.allocation, fromScalar, rowDegrees_singleton, Op.allocation, readWord_degree read] + +theorem emitOp_layout {selector rank : Expr} {first : Nat} {op : Op} + {rows : Array RowExpr} {emission : Emission} (initial : Concrete.Bytecode.LayoutMState) + (generic : initial.callRanks = #[]) + (valid : DegreeValid rows) (aligned : rowDegrees rows = initial.degrees) + (emitted : emitOp selector rank first op rows = some emission) : + ((Concrete.Bytecode.opLayout op).run initial).2.degrees = rowDegrees (rows ++ emission.outputs) ∧ + ((Concrete.Bytecode.opLayout op).run initial).2.functionLayout.auxiliaries = + initial.functionLayout.auxiliaries + emission.used := by + have allocated := emitOp_allocation valid emitted + rw [aligned] at allocated + have degrees := congrArg OpAllocation.degrees allocated + have auxiliaries := congrArg OpAllocation.auxiliaries allocated + obtain ⟨layoutDegrees, layoutAux⟩ := Concrete.Bytecode.opLayout_genericAllocation op initial generic + simp only [Emission.allocation] at degrees auxiliaries + rw [← degrees] at layoutDegrees + rw [← auxiliaries] at layoutAux + exact ⟨by simpa only [rowDegrees_append, aligned] using layoutDegrees, layoutAux⟩ + +theorem emitOps_fold_layout {selector rank : Expr} {ops : List Op} {rows : Array RowExpr} + {column : Nat} {emission : OpsEmission} (initial : Concrete.Bytecode.LayoutMState) (base : Nat) + (generic : initial.callRanks = #[]) + (valid : DegreeValid rows) (aligned : rowDegrees rows = initial.degrees) + (cursor : column = base + initial.functionLayout.auxiliaries) + (emitted : emitOps selector rank ops rows column = some emission) : + ((ops.foldlM (fun _ op => Concrete.Bytecode.opLayout op) ()).run initial).2.degrees = + rowDegrees emission.values ∧ + emission.column = base + + ((ops.foldlM (fun _ op => Concrete.Bytecode.opLayout op) ()).run initial).2.functionLayout.auxiliaries := by + induction ops generalizing rows column emission initial with + | nil => + cases emitted + exact ⟨aligned.symm, cursor⟩ + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + obtain ⟨nextDegrees, nextAux⟩ := emitOp_layout initial generic valid aligned firstEmitted + have reflected := ih ((Concrete.Bytecode.opLayout op).run initial).2 + ((Concrete.Bytecode.opLayout_callRanks op initial).trans generic) + (valid.append (emitOp_degreeValid valid firstEmitted)) nextDegrees.symm + (by rw [cursor, nextAux, Nat.add_assoc]) restEmitted + rw [List.foldlM_cons] + exact reflected + +theorem emitOps_layout {selector rank : Expr} {ops : Array Op} {rows : Array RowExpr} + {column : Nat} {emission : OpsEmission} (initial : Concrete.Bytecode.LayoutMState) (base : Nat) + (generic : initial.callRanks = #[]) + (valid : DegreeValid rows) (aligned : rowDegrees rows = initial.degrees) + (cursor : column = base + initial.functionLayout.auxiliaries) + (emitted : emitOps selector rank ops.toList rows column = some emission) : + ((ops.forM Concrete.Bytecode.opLayout).run initial).2.degrees = rowDegrees emission.values ∧ + emission.column = base + ((ops.forM Concrete.Bytecode.opLayout).run initial).2.functionLayout.auxiliaries := by + unfold Array.forM + rw [← Array.foldlM_toList] + exact emitOps_fold_layout initial base generic valid aligned cursor emitted + +end Aiur.NativeAIR.OpEmitter diff --git a/Ix/Aiur/Proofs/EmissionControls.lean b/Ix/Aiur/Proofs/EmissionControls.lean new file mode 100644 index 000000000..432859bc1 --- /dev/null +++ b/Ix/Aiur/Proofs/EmissionControls.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.EmissionInputs +import Ix.Aiur.Proofs.BlockDegrees + +/-! Checked control scopes provide every selector used by circuit emission. -/ + +namespace Aiur.Bytecode + +theorem emissionChecks_match (available selectors : Nat) (yieldSize : Option Nat) + (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).emissionChecks available selectors yieldSize = true ↔ + index < available ∧ + (∀ pair ∈ branches.toList, pair.2.emissionChecks available selectors yieldSize = true) ∧ + (∀ block, fallback = some block → block.emissionChecks available selectors yieldSize = true) := by + rw [Ctrl.emissionChecks.eq_def] + simp only [Bool.and_eq_true, decide_eq_true_eq, Array.all_eq_true', + Array.mem_attach, forall_const, Subtype.forall] + cases fallback <;> simp + +theorem emissionChecks_matchContinue (available selectors : Nat) (yieldSize : Option Nat) + (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) + (size aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback size aux lookups continuation).emissionChecks + available selectors yieldSize = true ↔ + index < available ∧ + (∀ pair ∈ branches.toList, pair.2.emissionChecks available selectors (some size) = true) ∧ + (∀ block, fallback = some block → block.emissionChecks available selectors (some size) = true) ∧ + ∃ next, addScope available size = some next ∧ continuation.emissionChecks next selectors yieldSize = true := by + rw [Ctrl.emissionChecks.eq_def] + simp only [Bool.and_eq_true, decide_eq_true_eq, Array.all_eq_true', + Array.mem_attach, forall_const, Subtype.forall] + cases fallback <;> cases added : addScope available size <;> simp + +theorem Block.emissionChecks_parts {block : Block} {available selectors : Nat} {yieldSize : Option Nat} + (checked : block.emissionChecks available selectors yieldSize = true) : + ∃ next, checkEmissionOps block.ops.toList available = some next ∧ + block.ctrl.emissionChecks next selectors yieldSize = true := by + unfold Block.emissionChecks at checked + split at checked + · cases checked + next next checkedOps => exact ⟨next, checkedOps, checked⟩ + +theorem Toplevel.validateEmission_function {program : Toplevel} (checked : program.validateEmission = true) + {function : Function} (member : function ∈ program.functions) (constrained : function.constrained = true) : + function.emissionChecks = true := by + rw [Toplevel.validateEmission, Array.all_eq_true'] at checked + simpa only [constrained, Bool.not_true, Bool.false_or] using checked function member + +end Aiur.Bytecode + +namespace Aiur.NativeAIR.BlockEmitter +open OpEmitter Bytecode + +private theorem branchSelectors_defined (selectors : Array Expr) (branches : Array (G × Block)) + (fallback : Option Block) + (casesDefined : ∀ pair ∈ branches.toList, ∃ entry, blockSelector selectors pair.2 = some entry) + (defaultDefined : ∀ block, fallback = some block → ∃ entry, blockSelector selectors block = some entry) : + ∃ entries last, + (branches.attach.toList.mapM fun pair => blockSelector selectors pair.val.2) = some entries ∧ + (match fallback with + | none => some [] + | some block => (blockSelector selectors block).map (fun entry => [entry])) = some last := by + obtain ⟨entries, casesRead⟩ := list_mapM_defined branches.attach.toList (fun pair _ => + casesDefined pair.val (by simpa using pair.property)) + cases fallback with + | none => exact ⟨entries, [], casesRead, rfl⟩ + | some block => + obtain ⟨entry, defaultRead⟩ := defaultDefined block rfl + exact ⟨entries, [entry], casesRead, by simp only [defaultRead, Option.map_some]⟩ + +mutual + +theorem ctrlSelector_defined (selectors : Array Expr) (ctrl : Ctrl) {available : Nat} {yieldSize : Option Nat} + (checked : ctrl.emissionChecks available selectors.size yieldSize = true) : + ∃ entry, ctrlSelector selectors ctrl = some entry := by + cases ctrl with + | «return» index outputs | yield index outputs => + have bound : index < selectors.size := by + simp only [Ctrl.emissionChecks, Bool.and_eq_true, decide_eq_true_eq] at checked + exact checked.1 + exact ⟨selectors[index], by simpa only [ctrlSelector] using getElem?_pos selectors index bound⟩ + | «match» index branches fallback => + obtain ⟨_, casesValid, defaultValid⟩ := (emissionChecks_match _ _ _ _ _ _).mp checked + obtain ⟨entries, last, casesRead, defaultRead⟩ := branchSelectors_defined selectors branches fallback + (fun pair member => blockSelector_defined selectors pair.2 (casesValid pair member)) + (fun block present => blockSelector_defined selectors block (defaultValid block present)) + refine ⟨sum (entries ++ last), ?_⟩ + rw [ctrlSelector.eq_def] + cases fallback with + | none => cases defaultRead; simp only [casesRead, bind, Option.bind_some, pure] + | some block => + simp only at defaultRead + simp only [casesRead, bind, Option.bind_some, pure] + rw [defaultRead] + rfl + | matchContinue index branches fallback size aux lookups continuation => + obtain ⟨_, casesValid, defaultValid, _⟩ := (emissionChecks_matchContinue _ _ _ _ _ _ _ _ _ _).mp checked + obtain ⟨entries, last, casesRead, defaultRead⟩ := branchSelectors_defined selectors branches fallback + (fun pair member => blockSelector_defined selectors pair.2 (casesValid pair member)) + (fun block present => blockSelector_defined selectors block (defaultValid block present)) + refine ⟨sum (entries ++ last), ?_⟩ + rw [ctrlSelector.eq_def] + cases fallback with + | none => cases defaultRead; simp only [casesRead, bind, Option.bind_some, pure] + | some block => + simp only at defaultRead + simp only [casesRead, bind, Option.bind_some, pure] + rw [defaultRead] + rfl +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (show pair ∈ branches from by simpa using member); grind) + +theorem blockSelector_defined (selectors : Array Expr) (block : Block) {available : Nat} {yieldSize : Option Nat} + (checked : block.emissionChecks available selectors.size yieldSize = true) : + ∃ entry, blockSelector selectors block = some entry := by + obtain ⟨_, _, control⟩ := Block.emissionChecks_parts checked + simpa only [blockSelector] using ctrlSelector_defined selectors block.ctrl control +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +end Aiur.NativeAIR.BlockEmitter diff --git a/Ix/Aiur/Proofs/EmissionInputs.lean b/Ix/Aiur/Proofs/EmissionInputs.lean new file mode 100644 index 000000000..a1f0ed67d --- /dev/null +++ b/Ix/Aiur/Proofs/EmissionInputs.lean @@ -0,0 +1,172 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.EmissionChecks +import Ix.Aiur.Proofs.EmissionAllocation + +/-! Checked operand scopes supply operation emission and its exact output size. -/ + +namespace Aiur.Bytecode + +theorem indicesInScope_spec (available : Nat) (indices : Array ValIdx) : + indicesInScope available indices = true ↔ ∀ index ∈ indices, index < available := by + simp only [indicesInScope, Array.all_eq_true', decide_eq_true_eq] + +theorem wordInScope_spec (available : Nat) (indices : Array ValIdx) : + wordInScope available indices = true ↔ indices.size = 4 ∧ indicesInScope available indices = true := by + simp only [wordInScope, Bool.and_eq_true, beq_iff_eq] + +theorem addScope_eq {available count next : Nat} (checked : addScope available count = some next) : + next = available + count ∧ next < 2^64 := by + unfold addScope at checked + dsimp only at checked + split at checked + · cases checked + exact ⟨rfl, ‹_›⟩ + · cases checked + +theorem checkEmissionOps_cons {op : Op} {ops : List Op} {available next : Nat} + (checked : checkEmissionOps (op :: ops) available = some next) : + op.emissionInputs available = true ∧ + ∃ after, addScope available op.outputSize = some after ∧ checkEmissionOps ops after = some next := by + simp only [checkEmissionOps] at checked + split at checked + · cases checked + next valid => + refine ⟨by simpa using valid, ?_⟩ + simp only [bind, Option.bind] at checked + split at checked + · cases checked + next after added => exact ⟨after, added, checked⟩ + +theorem checkEmissionOps_le {ops : List Op} {available next : Nat} + (checked : checkEmissionOps ops available = some next) : available ≤ next := by + induction ops generalizing available with + | nil => cases checked; exact Nat.le_refl _ + | cons op ops ih => + obtain ⟨_, after, added, rest⟩ := checkEmissionOps_cons checked + have size := (addScope_eq added).1 + have mono := ih rest + omega + +theorem Op.allocation_outputSize (op : Op) (degrees : Array Nat) : + (op.allocation degrees).degrees.size = op.outputSize := by + cases op <;> simp only [Op.allocation, Op.outputSize, OpAllocation.advice] + all_goals first + | rfl + | simp only [Array.size_replicate] + | (split <;> rfl) + +end Aiur.Bytecode + +namespace Aiur.NativeAIR.OpEmitter +open Bytecode + +theorem list_mapM_defined {read : α → Option β} (inputs : List α) + (defined : ∀ input ∈ inputs, ∃ output, read input = some output) : + ∃ outputs, inputs.mapM read = some outputs := by + induction inputs with + | nil => exact ⟨[], rfl⟩ + | cons input inputs ih => + obtain ⟨output, head⟩ := defined input List.mem_cons_self + obtain ⟨outputs, tail⟩ := ih (fun value member => defined value (List.mem_cons_of_mem _ member)) + exact ⟨output :: outputs, by simp only [List.mapM_cons, head, tail, bind, Option.bind_some, pure]⟩ + +theorem array_mapM_defined {read : α → Option β} (inputs : Array α) + (defined : ∀ input ∈ inputs, ∃ output, read input = some output) : + ∃ outputs, inputs.mapM read = some outputs := by + obtain ⟨outputs, evaluated⟩ := list_mapM_defined inputs.toList (by simpa using defined) + exact ⟨outputs.toArray, by simp only [Array.mapM_eq_mapM_toList, evaluated, Functor.map, Option.map_some]⟩ + +theorem select_defined {rows : Array RowExpr} {indices : Array Nat} + (checked : indicesInScope rows.size indices = true) : ∃ outputs, select rows indices = some outputs := by + apply array_mapM_defined + intro index member + have bound := (indicesInScope_spec _ _).mp checked index member + exact ⟨rows[index], getElem?_pos rows index bound⟩ + +theorem readWord_defined {rows : Array RowExpr} {indices : Array Nat} + (checked : wordInScope rows.size indices = true) : ∃ output, readWord rows indices = some output := by + obtain ⟨size, valid⟩ := (wordInScope_spec _ _).mp checked + obtain ⟨outputs, selected⟩ := select_defined valid + exact ⟨_, by simp only [readWord, size, ne_eq, not_true_eq_false, if_false, selected, + bind, Option.bind_some, pure]; rfl⟩ + +theorem emitOp_defined (selector rank : Expr) (first : Nat) (op : Op) (rows : Array RowExpr) + (checked : op.emissionInputs rows.size = true) : ∃ emission, emitOp selector rank first op rows = some emission := by + cases op with + | const | ioGetInfo | ioRead | ioSetInfo | ioWrite | debug | unconstrainedBigUintDivMod + | unconstrainedGToBytes | unconstrainedGInverse => exact ⟨_, rfl⟩ + | add a b | sub a b | mul a b | u8Xor a b | u8Add a b | u8Mul a b | u8Sub a b + | u8And a b | u8Or a b | u8LessThan a b | u32LessThan a b | u8XorSplit7 a b + | u8XorSplit4 a b | u8RangeCheck a b => + obtain ⟨left, right⟩ : a < rows.size ∧ b < rows.size := by + simpa only [Op.emissionInputs, Bool.and_eq_true, decide_eq_true_eq] using checked + exact ⟨_, by simp only [emitOp, getElem?_pos rows a left, getElem?_pos rows b right, + bind, Option.bind_some, pure]; rfl⟩ + | eqZero index | load size index | u8BitDecomposition index | u8ShiftLeft index | u8ShiftRight index => + have bound : index < rows.size := by simpa only [Op.emissionInputs, decide_eq_true_eq] using checked + exact ⟨_, by simp only [emitOp, getElem?_pos rows index bound, bind, Option.bind_some, pure]; rfl⟩ + | call function indices size unconstrained => + cases unconstrained with + | true => exact ⟨_, rfl⟩ + | false => + obtain ⟨outputs, selected⟩ := select_defined checked + exact ⟨_, by simp only [emitOp, Bool.false_eq_true, if_false, selected, bind, Option.bind_some, pure]; rfl⟩ + | store indices => + obtain ⟨outputs, selected⟩ := select_defined checked + exact ⟨_, by simp only [emitOp, selected, bind, Option.bind_some, pure]; rfl⟩ + | assertEq left right message => + obtain ⟨size, leftValid, rightValid⟩ : left.size = right.size ∧ + indicesInScope rows.size left = true ∧ indicesInScope rows.size right = true := by + simpa only [Op.emissionInputs, Bool.and_eq_true, beq_iff_eq] using checked + obtain ⟨xs, leftRead⟩ := select_defined leftValid + obtain ⟨ys, rightRead⟩ := select_defined rightValid + exact ⟨_, by simp only [emitOp, size, ne_eq, not_true_eq_false, if_false, leftRead, rightRead, + bind, Option.bind_some, pure]; rfl⟩ + | unconstrainedU32Add left right => + obtain ⟨leftValid, rightValid⟩ : wordInScope rows.size left = true ∧ wordInScope rows.size right = true := by + simpa only [Op.emissionInputs, Bool.and_eq_true] using checked + obtain ⟨a, leftRead⟩ := readWord_defined leftValid + obtain ⟨b, rightRead⟩ := readWord_defined rightValid + exact ⟨_, by simp only [emitOp, leftRead, rightRead, bind, Option.bind_some, pure]; rfl⟩ + | unconstrainedU32Add3 left middle right => + obtain ⟨leftValid, middleValid, rightValid⟩ : wordInScope rows.size left = true ∧ + wordInScope rows.size middle = true ∧ wordInScope rows.size right = true := by + simpa only [Op.emissionInputs, Bool.and_eq_true] using checked + obtain ⟨a, leftRead⟩ := readWord_defined leftValid + obtain ⟨b, middleRead⟩ := readWord_defined middleValid + obtain ⟨c, rightRead⟩ := readWord_defined rightValid + exact ⟨_, by simp only [emitOp, leftRead, middleRead, rightRead, bind, Option.bind_some, pure]; rfl⟩ + | u32ToField indices => + obtain ⟨output, selected⟩ := readWord_defined checked + exact ⟨_, by simp only [emitOp, selected, bind, Option.bind_some, pure]; rfl⟩ + +theorem emitOp_outputSize {selector rank : Expr} {first : Nat} {op : Op} + {rows : Array RowExpr} {emission : Emission} (valid : DegreeValid rows) + (emitted : emitOp selector rank first op rows = some emission) : + emission.outputs.size = op.outputSize := by + have allocated := congrArg (fun allocation => allocation.degrees.size) (emitOp_allocation valid emitted) + simpa only [Emission.allocation, rowDegrees, Array.size_map, Op.allocation_outputSize] using allocated + +theorem emitOps_defined (selector rank : Expr) (ops : List Op) (rows : Array RowExpr) (column : Nat) + {next : Nat} (valid : DegreeValid rows) (checked : checkEmissionOps ops rows.size = some next) : + ∃ emission, emitOps selector rank ops rows column = some emission ∧ emission.values.size = next := by + induction ops generalizing rows column with + | nil => cases checked; exact ⟨_, rfl, rfl⟩ + | cons op ops ih => + obtain ⟨inputs, after, added, rest⟩ := checkEmissionOps_cons checked + obtain ⟨first, firstEmitted⟩ := emitOp_defined selector rank column op rows inputs + have size := emitOp_outputSize valid firstEmitted + have nextSize : (rows ++ first.outputs).size = after := by + simp only [Array.size_append, size, (addScope_eq added).1] + obtain ⟨last, lastEmitted, lastSize⟩ := ih (rows ++ first.outputs) (column + first.used) + (valid.append (emitOp_degreeValid valid firstEmitted)) (nextSize ▸ rest) + refine ⟨{ last with + equations := first.equations ++ last.equations, + queries := first.queries ++ last.queries, calls := first.calls ++ last.calls }, ?_, lastSize⟩ + simp only [emitOps, firstEmitted, lastEmitted, bind, Option.bind_some, pure] + +end Aiur.NativeAIR.OpEmitter diff --git a/Ix/Aiur/Proofs/EncodedCircuitExecution.lean b/Ix/Aiur/Proofs/EncodedCircuitExecution.lean new file mode 100644 index 000000000..288662132 --- /dev/null +++ b/Ix/Aiur/Proofs/EncodedCircuitExecution.lean @@ -0,0 +1,159 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BranchlessSlots +import Ix.Aiur.Proofs.PublicCircuitExecution + +/-! Encoded circuit consumer messages give the same padded query pool +and query count as decoded active operations. Their physical message widths +bound the decoded widths. This connects valued slot balance to execution +of the selected public success call without a single-writer assumption. +Native trace extraction and the cryptographic reduction remain separate. -/ + +namespace Aiur.AIR +open Bytecode + +theorem gateMessage_length (branchless : Bool) (gate : G) (message : List G) : + (gateMessage branchless gate message).length = message.length := by + cases branchless <;> simp only [gateMessage, Bool.false_eq_true, if_false, + scaleMessage, List.length_map, if_true] + +private theorem slotMessage_fold_start (branchless : Bool) (parts : List (G × List G)) (start : List G) : + start.length ≤ (parts.foldl (fun combined part => addMessages combined + (gateMessage branchless part.1 part.2)) start).length := by + induction parts generalizing start with + | nil => exact Nat.le_refl _ + | cons part rest ih => + have step := ih (addMessages start (gateMessage branchless part.1 part.2)) + simp only [List.foldl_cons] + apply Nat.le_trans _ step + rw [addMessages_length] + exact Nat.le_max_left _ _ + +private theorem slotMessage_fold_member (branchless : Bool) {parts : List (G × List G)} + {part : G × List G} (member : part ∈ parts) (start : List G) : + part.2.length ≤ (parts.foldl (fun combined part => addMessages combined + (gateMessage branchless part.1 part.2)) start).length := by + induction parts generalizing start with + | nil => cases member + | cons first rest ih => + rcases List.mem_cons.mp member with equal | later + · subst part + apply Nat.le_trans _ (slotMessage_fold_start branchless rest _) + rw [addMessages_length, gateMessage_length] + exact Nat.le_max_right _ _ + · exact ih later _ + +theorem slotMessage_member_length (branchless : Bool) {parts : List (G × List G)} + {part : G × List G} (member : part ∈ parts) : part.2.length ≤ (slotMessage branchless parts).length := + slotMessage_fold_member branchless member [] + +theorem QuerySlots.encoded_member {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (branchless : Bool) + {query : QueryPart} (member : query ∈ queries) (active : query.selector = 1) : + slotMessage branchless (querySlotParts queries query.slot) ∈ encodedQueries branchless queries finish := by + have count : queryCount queries query.slot = 1 := congrArg List.length (slots.active_singleton member active) + have multiplicity : querySlotMultiplicity queries query.slot = 1 := by + rw [slots.slot_multiplicity, count] + rfl + apply List.mem_filterMap.mpr + refine ⟨query.slot, List.mem_range.mpr (slots.range query member).2, ?_⟩ + simp only [encodedQuery, multiplicity, if_true] + +theorem QuerySlots.decoded_widths {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (branchless : Bool) (width : Nat) + (widths : ∀ message ∈ encodedQueries branchless queries finish, message.length ≤ width) : + ∀ message ∈ decodedQueries queries finish, message.length ≤ width := by + intro message present + obtain ⟨slot, _, decoded⟩ := List.mem_filterMap.mp present + cases found : activeQuerySlot queries slot with + | nil => simp only [decodedQuery, found, List.head?_nil, Option.map_none, reduceCtorEq] at decoded + | cons query rest => + have member : query ∈ activeQuerySlot queries slot := by rw [found]; exact List.mem_cons_self + obtain ⟨original, _, active⟩ := by + simpa only [activeQuerySlot, List.mem_filter, Bool.and_eq_true, beq_iff_eq] using member + simp only [decodedQuery, found, List.head?_cons, Option.map_some, Option.some.injEq] at decoded + rw [← decoded] + exact Nat.le_trans (slotMessage_member_length branchless (querySlotParts_member original)) + (widths _ (slots.encoded_member branchless original active)) + +/-- Unit consumers encoded by the valued circuit's physical lookup slots. +The return provider is kept separately in `circuitProviders`. -/ +def encodedCircuitQueryPool (emissions : List CircuitEmission) : List (List G) := + emissions.flatMap fun emission => encodedQueries emission.branchless emission.queries emission.lookupCount + +theorem circuitWitnesses_queries_reflect {program : Toplevel} (witnesses : List CircuitWitness) + (counted : program.validateRowCounts = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.Emitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) (width : Nat) : + (encodedCircuitQueryPool (witnesses.map (·.emission))).map (padMessage width) = + (circuitQueryPool (witnesses.map (·.emission))).map (padMessage width) := by + simp only [encodedCircuitQueryPool, circuitQueryPool, List.map_flatMap] + rw [List.flatMap, List.flatMap] + apply congrArg List.flatten + apply List.map_congr_left + intro emission member + obtain ⟨witness, witnessMember, equal⟩ := List.mem_map.mp member + subst emission + exact witness.circuit.emitRow_queries_reflect witness.values program (emitted witness witnessMember) + (Toplevel.validateRowCounts_circuit counted (circuits witness witnessMember)) + (limits witness witnessMember).1 (limits witness witnessMember).2 (satisfied witness witnessMember) width + +theorem circuitWitnesses_decoded_widths {program : Toplevel} (witnesses : List CircuitWitness) + (counted : program.validateRowCounts = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.Emitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) (width : Nat) + (widths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) : + ∀ query ∈ circuitQueryPool (witnesses.map (·.emission)), query.length ≤ width := by + intro query member + obtain ⟨emission, emissionMember, queryMember⟩ := List.mem_flatMap.mp member + obtain ⟨witness, witnessMember, equal⟩ := List.mem_map.mp emissionMember + subst emission + obtain ⟨bounded, bounds, _, _⟩ := witness.circuit.emitRow_count_bounds witness.values program + (emitted witness witnessMember) (Toplevel.validateRowCounts_circuit counted (circuits witness witnessMember)) + (satisfied witness witnessMember) + have slots := witness.circuit.emitRow_querySlots witness.values program (emitted witness witnessMember) + bounded bounds (limits witness witnessMember).1 (limits witness witnessMember).2 (satisfied witness witnessMember) + exact slots.decoded_widths witness.emission.branchless width + (fun message present => widths message (List.mem_flatMap.mpr + ⟨witness.emission, List.mem_map.mpr ⟨witness, witnessMember, rfl⟩, present⟩)) query queryMember + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem Backend.encoded_circuit_execution {selection : Selection} (backend : Backend selection) + (tables : AuxiliaryTables) (witnesses : List CircuitWitness) (width : Nat) + (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: + encodedCircuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : (encodedCircuitQueryPool (witnesses.map (·.emission))).length + 1 < gSize.toNat) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ backend.compiled.bytecode.circuits) + (emitted : ∀ witness ∈ witnesses, witness.Emitted backend.compiled.bytecode) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes backend.compiled.bytecode) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) + ⟨selection.function, input, selection.success, 0⟩ := by + have messages := circuitWitnesses_queries_reflect witnesses backend.rowCounts circuits emitted satisfied limits width + have lengths := congrArg List.length messages + simp only [List.length_map] at lengths + apply backend.public_circuit_execution tables witnesses width input arity + (balanced.congr_queries (by simp only [List.map_cons, messages])) (by rwa [← lengths]) publicWidth + (circuitWitnesses_decoded_widths witnesses backend.rowCounts circuits emitted satisfied limits width queryWidths) + memoryValid canonical circuits emitted satisfied shapes limits + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/Execution.lean b/Ix/Aiur/Proofs/Execution.lean new file mode 100644 index 000000000..f34e5688a --- /dev/null +++ b/Ix/Aiur/Proofs/Execution.lean @@ -0,0 +1,182 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Semantics.AIR +import Ix.Aiur.Proofs.Lookup + +/-! +Finite execution from locally interpreted rows and exact lookup balance. + +The interface keeps function requests, provider multiplicities, active-row +rank bytes and call-gap bytes explicit. Local row interpretation is still an +extraction obligation for the native constraint emitter. This theorem closes +the global call-table obligation once those local interpretations, exact +balance and the query-count bounds have been established. In particular, it +does not assume that a matching provider already has a finite execution. +-/ + +namespace Aiur.AIR + +open Bytecode.AIR + +/-- One interpreted function row; each call carries its six gap bytes. -/ +structure FunctionRow where + request : Call + calls : List (Call × (Fin 6 → G)) + rankBytes : Fin 6 → G + selector : G + multiplicity : G + +def FunctionRow.requests (row : FunctionRow) : List Call := row.calls.map Prod.fst + +def FunctionRow.byteQueries (row : FunctionRow) : List (G × G) := + rankByteQueries row.rankBytes ++ row.calls.flatMap fun edge => rankByteQueries edge.2 + +/-- The concrete local obligations of an interpreted row. The execution +field resolves operations and control flow but leaves calls as requests. -/ +structure FunctionRow.Valid (program : Bytecode.Toplevel) (memory : Memory) + (row : FunctionRow) : Prop where + selector : row.selector = 0 ∨ row.selector = 1 + activity : activityConstraint row.multiplicity row.selector = 0 + rank : row.selector = 1 → row.request.rank = packRank row.rankBytes + execution : row.selector = 1 → RunFunction program memory row.request row.requests + order : ∀ edge ∈ row.calls, + row.selector * callOrderConstraint row.request.rank edge.1.rank (packRank edge.2) = 0 + +def functionProviders (rows : List FunctionRow) : List (Provider Call) := + rows.map fun row => (row.request, row.multiplicity) + +def functionQueries (roots : List Call) (rows : List FunctionRow) : List Call := + roots ++ rows.flatMap fun row => if row.selector = 1 then row.requests else [] + +def functionByteQueries (rows : List FunctionRow) : List (G × G) := + rows.flatMap fun row => if row.selector = 1 then row.byteQueries else [] + +theorem FunctionRow.Valid.active_of_nonzero {program : Bytecode.Toplevel} + {memory : Memory} {row : FunctionRow} (valid : row.Valid program memory) + (nonzero : row.multiplicity ≠ 0) : row.selector = 1 := by + rcases valid.selector with inactive | active + · exact False.elim (nonzero (inactive_multiplicity_zero inactive valid.activity)) + · exact active + +theorem functionByteQueries_member {rows : List FunctionRow} {row : FunctionRow} + (member : row ∈ rows) (active : row.selector = 1) : + row.byteQueries ⊆ functionByteQueries rows := by + intro query queried + apply List.mem_flatMap.mpr + exact ⟨row, member, by simpa only [if_pos active] using queried⟩ + +theorem functionQueries_member {roots : List Call} {rows : List FunctionRow} + {row : FunctionRow} (member : row ∈ rows) (active : row.selector = 1) : + row.requests ⊆ functionQueries roots rows := by + intro query queried + apply List.mem_append_right + apply List.mem_flatMap.mpr + exact ⟨row, member, by simpa only [if_pos active] using queried⟩ + +/-- Every requested call has an active row supplying exactly that call, +including its rank. Provider multiplicities need not be natural counts. -/ +theorem functionQueries_provider {program : Bytecode.Toplevel} {memory : Memory} + {roots : List Call} {rows : List FunctionRow} + (valid : ∀ row ∈ rows, row.Valid program memory) + (balanced : ExactLookupBalance (functionQueries roots rows) (functionProviders rows)) + (bounded : (functionQueries roots rows).length < gSize.toNat) + {request : Call} (queried : request ∈ functionQueries roots rows) : + ∃ row ∈ rows, row.request = request ∧ row.selector = 1 := by + obtain ⟨provider, member, same, nonzero⟩ := + exactLookupBalance_provider balanced bounded queried + obtain ⟨row, rowMember, providerEq⟩ := List.mem_map.mp member + subst provider + exact ⟨row, rowMember, same, (valid row rowMember).active_of_nonzero nonzero⟩ + +theorem FunctionRow.Valid.rank_bounded {program : Bytecode.Toplevel} + {memory : Memory} {rows : List FunctionRow} {row : FunctionRow} + (valid : row.Valid program memory) (member : row ∈ rows) (active : row.selector = 1) + (weights : Fin 65536 → G) + (balanced : ExactLookupBalance (functionByteQueries rows) (byteRangeProviders weights)) + (bounded : (functionByteQueries rows).length < gSize.toNat) : + row.request.rank.n < callRankBound := by + rw [valid.rank active] + apply packRank_lt + apply exactLookupBalance_rankBytes weights balanced bounded + intro pair queried + apply functionByteQueries_member member active + exact List.mem_append_left _ queried + +theorem FunctionRow.Valid.call_order {program : Bytecode.Toplevel} {memory : Memory} + {rows : List FunctionRow} {row : FunctionRow} (valid : row.Valid program memory) + (member : row ∈ rows) (active : row.selector = 1) + (weights : Fin 65536 → G) + (balanced : ExactLookupBalance (functionByteQueries rows) (byteRangeProviders weights)) + (bounded : (functionByteQueries rows).length < gSize.toNat) + {edge : Call × (Fin 6 → G)} (called : edge ∈ row.calls) + (childBound : edge.1.rank.n < callRankBound) : + row.request.rank.n < edge.1.rank.n := by + have gapBound : (packRank edge.2).n < callRankBound := by + apply packRank_lt + apply exactLookupBalance_rankBytes weights balanced bounded + intro pair queried + apply functionByteQueries_member member active + apply List.mem_append_right + exact List.mem_flatMap.mpr ⟨edge, called, queried⟩ + exact active_call_order_strict active + (valid.rank_bounded member active weights balanced bounded) + childBound gapBound (valid.order edge called) + +/-- Active locally valid rows give finite call derivations. The proof uses +the actual 48-bit rank/gap equations and balanced byte-table queries, not a +postulated acyclic call graph or an execution assumption on callees. -/ +theorem balancedRows_execute {program : Bytecode.Toplevel} {memory : Memory} + {roots : List Call} {rows : List FunctionRow} + (valid : ∀ row ∈ rows, row.Valid program memory) + (balanced : ExactLookupBalance (functionQueries roots rows) (functionProviders rows)) + (bounded : (functionQueries roots rows).length < gSize.toNat) + (weights : Fin 65536 → G) + (bytesBalanced : ExactLookupBalance (functionByteQueries rows) (byteRangeProviders weights)) + (bytesBounded : (functionByteQueries rows).length < gSize.toNat) + {row : FunctionRow} (member : row ∈ rows) (active : row.selector = 1) : + Execution program memory row.request := by + have all : ∀ n : Nat, ∀ row : FunctionRow, + callRankBound - row.request.rank.n = n → row ∈ rows → row.selector = 1 → + Execution program memory row.request := by + intro n + induction n using Nat.strongRecOn with + | ind n ih => + intro parent measure member active + apply Execution.function ((valid parent member).execution active) + intro child called + obtain ⟨edge, edgeMember, edgeEq⟩ := List.mem_map.mp called + obtain ⟨provider, providerMember, same, providerActive⟩ := + functionQueries_provider valid balanced bounded + (functionQueries_member member active called) + have childBound := (valid provider providerMember).rank_bounded + providerMember providerActive weights bytesBalanced bytesBounded + have order := (valid parent member).call_order member active weights + bytesBalanced bytesBounded edgeMember + (by simpa only [edgeEq, ← same] using childBound) + rw [edgeEq, ← same] at order + have smaller : callRankBound - provider.request.rank.n < n := by omega + rw [← same] + exact ih _ smaller provider rfl providerMember providerActive + exact all _ row rfl member active + +/-- Every public/root request has a finite derivation under the same local, +balance and count obligations. Root rank zero may be imposed by the public +message encoding without changing this statement. -/ +theorem balancedRoots_execute {program : Bytecode.Toplevel} {memory : Memory} + {roots : List Call} {rows : List FunctionRow} + (valid : ∀ row ∈ rows, row.Valid program memory) + (balanced : ExactLookupBalance (functionQueries roots rows) (functionProviders rows)) + (bounded : (functionQueries roots rows).length < gSize.toNat) + (weights : Fin 65536 → G) + (bytesBalanced : ExactLookupBalance (functionByteQueries rows) (byteRangeProviders weights)) + (bytesBounded : (functionByteQueries rows).length < gSize.toNat) + {request : Call} (root : request ∈ roots) : Execution program memory request := by + obtain ⟨row, member, same, active⟩ := functionQueries_provider valid balanced bounded + (List.mem_append_left _ root) + rw [← same] + exact balancedRows_execute valid balanced bounded weights bytesBalanced bytesBounded member active + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/ExpressionGraph.lean b/Ix/Aiur/Proofs/ExpressionGraph.lean new file mode 100644 index 000000000..eeddcf2f4 --- /dev/null +++ b/Ix/Aiur/Proofs/ExpressionGraph.lean @@ -0,0 +1,561 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Field + +/-! +The native base-node graph, its checked read layout, and forward evaluation. +The layout checker requires children before parents, bounded roots and leaf +indices, and no stage-two columns in the lookup prefix. Valid inputs admit +both sweeps. Their results agree with unfolded expressions for arbitrary +working operations, and their lookup values agree on the shared prefix. + +These are total Lean definitions. The native comparison evaluates actual +Rust graphs and the guard on malformed layouts. Refinement of Rust execution, +frontend compilation, key decoding and cryptographic acceptance remains open. +-/ + +namespace Aiur.NativeAIR + +inductive Source where + | preprocessed | main | stage2 + deriving DecidableEq, Repr + +inductive RowOffset where + | current | next + deriving DecidableEq, Repr + +structure ColRef where + source : Source + offset : RowOffset + index : Nat + deriving DecidableEq, Repr + +inductive Node where + | konst (value : G) + | var (column : ColRef) + | publicInput (index : Nat) + | isFirstRow | isLastRow | isTransition + | add (left right : Nat) + | sub (left right : Nat) + | mul (left right : Nat) + | neg (child : Nat) + deriving DecidableEq, Repr + +structure GraphWidths where + preprocessed : Nat + main : Nat + stage2 : Nat + publics : Nat + deriving DecidableEq, Repr + +def GraphWidths.width (widths : GraphWidths) : Source → Nat + | .preprocessed => widths.preprocessed + | .main => widths.main + | .stage2 => widths.stage2 + +structure Lookup where + multiplicity : Nat + args : List Nat + deriving DecidableEq, Repr + +structure Graph where + nodes : List Node + zeros : List Nat + lookups : List Lookup + deriving DecidableEq, Repr + +def Lookup.roots (lookup : Lookup) : List Nat := lookup.multiplicity :: lookup.args +def Graph.lookupRoots (graph : Graph) : List Nat := graph.lookups.flatMap Lookup.roots +/-- The dense prefix reconstructed by the native codec. Compilation can +intern extra nodes before folding its last lookup, so its stored prefix can +be longer. Children before parents make this root-derived prefix sufficient. -/ +def Graph.lookupPrefix (graph : Graph) : Nat := + graph.lookupRoots.foldr (fun index rest => max (index + 1) rest) 0 + +def Node.Valid (widths : GraphWidths) (lookupEnd index : Nat) : Node → Prop + | .konst _ | .isFirstRow | .isLastRow | .isTransition => True + | .var column => column.index < widths.width column.source ∧ + (column.source = .stage2 → lookupEnd ≤ index) + | .publicInput input => input < widths.publics + | .add a b | .sub a b | .mul a b => a < index ∧ b < index + | .neg a => a < index + +def Node.check (widths : GraphWidths) (lookupEnd index : Nat) : Node → Bool + | .konst _ | .isFirstRow | .isLastRow | .isTransition => true + | .var column => column.index < widths.width column.source && + (column.source != .stage2 || lookupEnd ≤ index) + | .publicInput input => input < widths.publics + | .add a b | .sub a b | .mul a b => a < index && b < index + | .neg a => a < index + +theorem Node.check_iff (widths : GraphWidths) (lookupEnd index : Nat) (node : Node) : + node.check widths lookupEnd index = true ↔ node.Valid widths lookupEnd index := by + cases node <;> simp only [Node.check, Node.Valid, Bool.and_eq_true, + Bool.or_eq_true, bne_iff_ne, decide_eq_true_eq, iff_self] + case var column => + cases column.source <;> simp + +def checkNodes (widths : GraphWidths) (lookupEnd : Nat) : Nat → List Node → Bool + | _, [] => true + | index, node :: nodes => node.check widths lookupEnd index && checkNodes widths lookupEnd (index + 1) nodes + +inductive ValidNodes (widths : GraphWidths) (lookupEnd : Nat) : Nat → List Node → Prop where + | nil (index : Nat) : ValidNodes widths lookupEnd index [] + | cons {index : Nat} {node : Node} {nodes : List Node} + (valid : node.Valid widths lookupEnd index) + (rest : ValidNodes widths lookupEnd (index + 1) nodes) : + ValidNodes widths lookupEnd index (node :: nodes) + +theorem checkNodes_iff (widths : GraphWidths) (lookupEnd index : Nat) (nodes : List Node) : + checkNodes widths lookupEnd index nodes = true ↔ ValidNodes widths lookupEnd index nodes := by + induction nodes generalizing index with + | nil => exact ⟨fun _ => .nil _, fun _ => rfl⟩ + | cons node nodes ih => + simp only [checkNodes, Bool.and_eq_true, Node.check_iff, ih] + exact ⟨fun ⟨valid, rest⟩ => .cons valid rest, fun valid => by cases valid; exact ⟨‹_›, ‹_›⟩⟩ + +def checkedGraphPrefix (widths : GraphWidths) (graph : Graph) : Option Nat := + if graph.zeros.all (· < graph.nodes.length) && graph.lookupRoots.all (· < graph.nodes.length) && + checkNodes widths graph.lookupPrefix 0 graph.nodes then + some graph.lookupPrefix + else none + +structure Graph.Valid (widths : GraphWidths) (graph : Graph) : Prop where + nodes : ValidNodes widths graph.lookupPrefix 0 graph.nodes + zeros : ∀ index ∈ graph.zeros, index < graph.nodes.length + lookups : ∀ index ∈ graph.lookupRoots, index < graph.nodes.length + +theorem checkedGraphPrefix_iff (widths : GraphWidths) (graph : Graph) (lookupEnd : Nat) : + checkedGraphPrefix widths graph = some lookupEnd ↔ graph.Valid widths ∧ lookupEnd = graph.lookupPrefix := by + simp only [checkedGraphPrefix] + split + next accepted => + simp only [Bool.and_eq_true, List.all_eq_true, decide_eq_true_eq, checkNodes_iff] at accepted + obtain ⟨⟨zeros, lookups⟩, nodes⟩ := accepted + exact ⟨fun equal => ⟨⟨nodes, zeros, lookups⟩, (Option.some.inj equal).symm⟩, + fun ⟨_, equal⟩ => congrArg some equal.symm⟩ + next rejected => + constructor + · intro equal; cases equal + · rintro ⟨valid, _⟩ + apply False.elim + apply rejected + simp only [Bool.and_eq_true, List.all_eq_true, decide_eq_true_eq, checkNodes_iff] + exact ⟨⟨valid.zeros, valid.lookups⟩, valid.nodes⟩ + +theorem roots_below_prefix (roots : List Nat) (index : Nat) (member : index ∈ roots) : + index < roots.foldr (fun root rest => max (root + 1) rest) 0 := by + induction roots with + | nil => simp only [List.not_mem_nil] at member + | cons root roots ih => + simp only [List.mem_cons] at member + simp only [List.foldr_cons] + rcases member with rfl | member + · exact Nat.lt_of_lt_of_le (Nat.lt_succ_self _) (Nat.le_max_left _ _) + · exact Nat.lt_of_lt_of_le (ih member) (Nat.le_max_right _ _) + +theorem prefix_bounded (roots : List Nat) (bound : Nat) (bounded : ∀ index ∈ roots, index < bound) : + roots.foldr (fun root rest => max (root + 1) rest) 0 ≤ bound := by + induction roots with + | nil => exact Nat.zero_le _ + | cons root roots ih => + simp only [List.foldr_cons, Nat.max_le] + exact ⟨bounded root (by simp), ih (fun index member => bounded index (by simp [member]))⟩ + +theorem Graph.Valid.prefix_bounded {widths : GraphWidths} {graph : Graph} (valid : graph.Valid widths) : + graph.lookupPrefix ≤ graph.nodes.length := Aiur.NativeAIR.prefix_bounded _ _ valid.lookups + +structure EvalOps (W : Type u) where + konst : G → W + add : W → W → W + sub : W → W → W + mul : W → W → W + neg : W → W + +structure Values (W : Type u) where + columns : Source → RowOffset → Array W + publics : Array W + isFirstRow : W + isLastRow : W + isTransition : W + +def Values.Fits (values : Values W) (widths : GraphWidths) : Prop := + (∀ source offset, (values.columns source offset).size = widths.width source) ∧ + values.publics.size = widths.publics + +def Node.eval (ops : EvalOps W) (values : Values W) (buffer : Array W) : Node → Option W + | .konst value => some (ops.konst value) + | .var column => (values.columns column.source column.offset)[column.index]? + | .publicInput index => values.publics[index]? + | .isFirstRow => some values.isFirstRow + | .isLastRow => some values.isLastRow + | .isTransition => some values.isTransition + | .add a b => return ops.add (← buffer[a]?) (← buffer[b]?) + | .sub a b => return ops.sub (← buffer[a]?) (← buffer[b]?) + | .mul a b => return ops.mul (← buffer[a]?) (← buffer[b]?) + | .neg a => return ops.neg (← buffer[a]?) + +theorem Node.eval_defined (ops : EvalOps W) (values : Values W) (buffer : Array W) + {widths : GraphWidths} {lookupEnd : Nat} {node : Node} + (fits : values.Fits widths) (valid : node.Valid widths lookupEnd buffer.size) : + ∃ value, node.eval ops values buffer = some value := by + cases node <;> simp only [Node.Valid] at valid + all_goals try exact ⟨_, rfl⟩ + case var column => + have bounded : column.index < (values.columns column.source column.offset).size := by + rw [fits.1]; exact valid.1 + exact ⟨_, Array.getElem?_eq_getElem bounded⟩ + case publicInput input => + have bounded : input < values.publics.size := by rw [fits.2]; exact valid + exact ⟨_, Array.getElem?_eq_getElem bounded⟩ + case add a b => simp [Node.eval, Array.getElem?_eq_getElem valid.1, Array.getElem?_eq_getElem valid.2] + case sub a b => simp [Node.eval, Array.getElem?_eq_getElem valid.1, Array.getElem?_eq_getElem valid.2] + case mul a b => simp [Node.eval, Array.getElem?_eq_getElem valid.1, Array.getElem?_eq_getElem valid.2] + case neg a => simp [Node.eval, Array.getElem?_eq_getElem valid] + +def sweepFrom (ops : EvalOps W) (values : Values W) : List Node → Array W → Option (Array W) + | [], buffer => some buffer + | node :: nodes, buffer => do + let value ← node.eval ops values buffer + sweepFrom ops values nodes (buffer.push value) + +def Graph.sweep (graph : Graph) (ops : EvalOps W) (values : Values W) : Option (Array W) := + sweepFrom ops values graph.nodes #[] + +theorem sweepFrom_defined (ops : EvalOps W) (values : Values W) (nodes : List Node) (buffer : Array W) + {widths : GraphWidths} {lookupEnd : Nat} (fits : values.Fits widths) + (valid : ValidNodes widths lookupEnd buffer.size nodes) : + ∃ result, sweepFrom ops values nodes buffer = some result ∧ result.size = buffer.size + nodes.length := by + induction nodes generalizing buffer with + | nil => exact ⟨buffer, rfl, by simp⟩ + | cons node nodes ih => + cases valid with + | cons valid rest => + obtain ⟨value, evaluated⟩ := Node.eval_defined ops values buffer fits valid + obtain ⟨result, swept, length⟩ := ih (buffer.push value) (by simpa only [Array.size_push] using rest) + refine ⟨result, ?_, ?_⟩ + · simp only [sweepFrom, evaluated, bind, Option.bind, swept] + · simp only [Array.size_push, List.length_cons] at length ⊢; omega + +theorem Graph.Valid.sweep_defined {widths : GraphWidths} {graph : Graph} (valid : graph.Valid widths) + (ops : EvalOps W) (values : Values W) (fits : values.Fits widths) : + ∃ result, graph.sweep ops values = some result ∧ result.size = graph.nodes.length := by + simpa only [Graph.sweep, Array.size_empty, Nat.zero_add] using + sweepFrom_defined ops values graph.nodes #[] fits valid.nodes + +theorem ValidNodes.take {widths : GraphWidths} {lookupEnd index : Nat} {nodes : List Node} + (valid : ValidNodes widths lookupEnd index nodes) (count : Nat) : + ValidNodes widths lookupEnd index (nodes.take count) := by + induction valid generalizing count with + | nil index => simpa using ValidNodes.nil (widths := widths) (lookupEnd := lookupEnd) index + | cons valid rest ih => + cases count with + | zero => exact .nil _ + | succ count => exact .cons valid (ih count) + +def Values.withoutStage2 (values : Values W) : Values W := + { values with columns := fun source offset => + match source with + | .stage2 => #[] + | _ => values.columns source offset } + +theorem Node.eval_withoutStage2 (ops : EvalOps W) (values : Values W) (buffer : Array W) + {widths : GraphWidths} {lookupEnd : Nat} {node : Node} + (valid : node.Valid widths lookupEnd buffer.size) (inside : buffer.size < lookupEnd) : + node.eval ops values.withoutStage2 buffer = node.eval ops values buffer := by + cases node <;> try rfl + case var column => + cases source : column.source <;> simp only [Node.eval, Values.withoutStage2, source] + exact False.elim (Nat.not_lt_of_ge (valid.2 source) inside) + +theorem sweepFrom_withoutStage2 (ops : EvalOps W) (values : Values W) (nodes : List Node) (buffer : Array W) + {widths : GraphWidths} {lookupEnd : Nat} (valid : ValidNodes widths lookupEnd buffer.size nodes) + (inside : buffer.size + nodes.length ≤ lookupEnd) : + sweepFrom ops values.withoutStage2 nodes buffer = sweepFrom ops values nodes buffer := by + induction nodes generalizing buffer with + | nil => rfl + | cons node nodes ih => + cases valid with + | cons valid rest => + have lt : buffer.size < lookupEnd := by simp only [List.length_cons] at inside; omega + simp only [sweepFrom, Node.eval_withoutStage2 ops values buffer valid lt] + cases evaluated : node.eval ops values buffer with + | none => rfl + | some value => + simp only [bind, Option.bind] + exact ih (buffer.push value) (by simpa only [Array.size_push] using rest) + (by simp only [Array.size_push, List.length_cons] at inside ⊢; omega) + +theorem sweepFrom_append (ops : EvalOps W) (values : Values W) (left right : List Node) (buffer : Array W) : + sweepFrom ops values (left ++ right) buffer = + (sweepFrom ops values left buffer).bind (sweepFrom ops values right) := by + induction left generalizing buffer with + | nil => rfl + | cons node nodes ih => + simp only [List.cons_append, sweepFrom] + cases node.eval ops values buffer with + | none => rfl + | some value => exact ih (buffer.push value) + +theorem sweepFrom_preserves (ops : EvalOps W) (values : Values W) (nodes : List Node) + {buffer result : Array W} (swept : sweepFrom ops values nodes buffer = some result) + (index : Nat) (bound : index < buffer.size) : result[index]? = buffer[index]? := by + induction nodes generalizing buffer with + | nil => cases swept; rfl + | cons node nodes ih => + simp only [sweepFrom] at swept + cases evaluated : node.eval ops values buffer with + | none => simp only [evaluated, bind, Option.bind, reduceCtorEq] at swept + | some value => + simp only [evaluated, bind, Option.bind] at swept + exact (ih swept (by simp only [Array.size_push]; omega)).trans + ((Array.getElem?_push_lt bound).trans (Array.getElem?_eq_getElem bound).symm) + +def Graph.sweepLookupPrefix (graph : Graph) (ops : EvalOps W) (values : Values W) : Option (Array W) := + sweepFrom ops values.withoutStage2 (graph.nodes.take graph.lookupPrefix) #[] + +theorem Graph.Valid.lookup_sweep_defined {widths : GraphWidths} {graph : Graph} (valid : graph.Valid widths) + (ops : EvalOps W) (values : Values W) (fits : values.Fits widths) : + ∃ result, graph.sweepLookupPrefix ops values = some result ∧ result.size = graph.lookupPrefix := by + have nodes := valid.nodes.take graph.lookupPrefix + have length : (graph.nodes.take graph.lookupPrefix).length = graph.lookupPrefix := + List.length_take_of_le valid.prefix_bounded + unfold Graph.sweepLookupPrefix + rw [sweepFrom_withoutStage2 ops values _ #[] nodes (by simp only [Array.size_empty, Nat.zero_add, length, Nat.le_refl])] + simpa only [Array.size_empty, Nat.zero_add, length] using sweepFrom_defined ops values _ #[] fits nodes + +theorem Graph.Valid.lookup_sweep_agrees {widths : GraphWidths} {graph : Graph} (valid : graph.Valid widths) + (ops : EvalOps W) (values : Values W) {full prefixValues : Array W} + (fullSweep : graph.sweep ops values = some full) + (partialSweep : graph.sweepLookupPrefix ops values = some prefixValues) + (index : Nat) (bound : index < prefixValues.size) : full[index]? = prefixValues[index]? := by + have nodes := valid.nodes.take graph.lookupPrefix + have length : (graph.nodes.take graph.lookupPrefix).length = graph.lookupPrefix := + List.length_take_of_le valid.prefix_bounded + unfold Graph.sweepLookupPrefix at partialSweep + rw [sweepFrom_withoutStage2 ops values _ #[] nodes (by simp only [Array.size_empty, Nat.zero_add, length, Nat.le_refl])] + at partialSweep + unfold Graph.sweep at fullSweep + rw [← List.take_append_drop graph.lookupPrefix graph.nodes, sweepFrom_append, partialSweep] at fullSweep + exact sweepFrom_preserves ops values _ fullSweep index bound + +inductive Expr where + | konst (value : G) + | var (column : ColRef) + | publicInput (index : Nat) + | isFirstRow | isLastRow | isTransition + | add (left right : Expr) + | sub (left right : Expr) + | mul (left right : Expr) + | neg (child : Expr) + deriving DecidableEq, Repr + +def Expr.eval (ops : EvalOps W) (values : Values W) : Expr → Option W + | .konst value => some (ops.konst value) + | .var column => (values.columns column.source column.offset)[column.index]? + | .publicInput index => values.publics[index]? + | .isFirstRow => some values.isFirstRow + | .isLastRow => some values.isLastRow + | .isTransition => some values.isTransition + | .add a b => return ops.add (← a.eval ops values) (← b.eval ops values) + | .sub a b => return ops.sub (← a.eval ops values) (← b.eval ops values) + | .mul a b => return ops.mul (← a.eval ops values) (← b.eval ops values) + | .neg a => return ops.neg (← a.eval ops values) + +def Node.unfold (trees : Array Expr) : Node → Option Expr + | .konst value => some (.konst value) + | .var column => some (.var column) + | .publicInput index => some (.publicInput index) + | .isFirstRow => some .isFirstRow + | .isLastRow => some .isLastRow + | .isTransition => some .isTransition + | .add a b => return .add (← trees[a]?) (← trees[b]?) + | .sub a b => return .sub (← trees[a]?) (← trees[b]?) + | .mul a b => return .mul (← trees[a]?) (← trees[b]?) + | .neg a => return .neg (← trees[a]?) + +def Reflects (ops : EvalOps W) (values : Values W) (trees : Array Expr) (buffer : Array W) : Prop := + buffer.size = trees.size ∧ ∀ index : Nat, buffer[index]? = (trees[index]?).bind (Expr.eval ops values) + +theorem Node.unfold_eval (ops : EvalOps W) (values : Values W) {trees : Array Expr} {buffer : Array W} + (reflects : Reflects ops values trees buffer) (node : Node) {expr : Expr} + (unfolded : node.unfold trees = some expr) : node.eval ops values buffer = expr.eval ops values := by + cases node <;> simp only [Node.unfold] at unfolded + all_goals first + | (cases unfolded; rfl) + | skip + all_goals simp only [Node.eval, reflects.2] + all_goals + repeat first + | (split at unfolded) + | (rename_i a b; cases ha : trees[a]? <;> cases hb : trees[b]? <;> + simp only [ha, hb, bind, Option.bind, pure, reduceCtorEq] at unfolded ⊢) + | (rename_i a; cases ha : trees[a]? <;> + simp only [ha, bind, Option.bind, pure, reduceCtorEq] at unfolded ⊢) + all_goals cases unfolded; rfl + +theorem Reflects.push {ops : EvalOps W} {values : Values W} {trees : Array Expr} {buffer : Array W} + (reflects : Reflects ops values trees buffer) (expr : Expr) (value : W) + (evaluated : expr.eval ops values = some value) : + Reflects ops values (trees.push expr) (buffer.push value) := by + refine ⟨by simpa only [Array.size_push] using congrArg (· + 1) reflects.1, ?_⟩ + intro index + simp only [Array.getElem?_push, reflects.1] + split + · simpa only [Option.bind_some] using evaluated.symm + · exact reflects.2 index + +def unfoldFrom : List Node → Array Expr → Option (Array Expr) + | [], trees => some trees + | node :: nodes, trees => do + let expr ← node.unfold trees + unfoldFrom nodes (trees.push expr) + +def Graph.unfold (graph : Graph) : Option (Array Expr) := unfoldFrom graph.nodes #[] + +theorem Node.unfold_defined {trees : Array Expr} {widths : GraphWidths} {lookupEnd : Nat} {node : Node} + (valid : node.Valid widths lookupEnd trees.size) : ∃ expr, node.unfold trees = some expr := by + cases node <;> simp only [Node.Valid] at valid + all_goals try exact ⟨_, rfl⟩ + case add a b => simp [Node.unfold, Array.getElem?_eq_getElem valid.1, Array.getElem?_eq_getElem valid.2] + case sub a b => simp [Node.unfold, Array.getElem?_eq_getElem valid.1, Array.getElem?_eq_getElem valid.2] + case mul a b => simp [Node.unfold, Array.getElem?_eq_getElem valid.1, Array.getElem?_eq_getElem valid.2] + case neg a => simp [Node.unfold, Array.getElem?_eq_getElem valid] + +theorem unfoldFrom_defined {nodes : List Node} {trees : Array Expr} {widths : GraphWidths} {lookupEnd : Nat} + (valid : ValidNodes widths lookupEnd trees.size nodes) : + ∃ result, unfoldFrom nodes trees = some result ∧ result.size = trees.size + nodes.length := by + induction nodes generalizing trees with + | nil => exact ⟨trees, rfl, by simp⟩ + | cons node nodes ih => + cases valid with + | cons valid rest => + obtain ⟨expr, unfolded⟩ := Node.unfold_defined valid + obtain ⟨result, extended, length⟩ := ih (trees := trees.push expr) (by simpa only [Array.size_push] using rest) + refine ⟨result, ?_, ?_⟩ + · simp only [unfoldFrom, unfolded, bind, Option.bind, extended] + · simp only [Array.size_push, List.length_cons] at length ⊢; omega + +theorem unfoldFrom_reflects (ops : EvalOps W) (values : Values W) (nodes : List Node) + {trees resultTrees : Array Expr} {buffer resultBuffer : Array W} + (reflects : Reflects ops values trees buffer) + (unfolded : unfoldFrom nodes trees = some resultTrees) + (swept : sweepFrom ops values nodes buffer = some resultBuffer) : + Reflects ops values resultTrees resultBuffer := by + induction nodes generalizing trees buffer with + | nil => cases unfolded; cases swept; exact reflects + | cons node nodes ih => + simp only [unfoldFrom] at unfolded + cases tree : node.unfold trees with + | none => simp only [tree, bind, Option.bind, reduceCtorEq] at unfolded + | some expr => + simp only [tree, bind, Option.bind] at unfolded + simp only [sweepFrom] at swept + cases evaluated : node.eval ops values buffer with + | none => simp only [evaluated, bind, Option.bind, reduceCtorEq] at swept + | some value => + simp only [evaluated, bind, Option.bind] at swept + have exprEval : expr.eval ops values = some value := + (Node.unfold_eval ops values reflects node tree).symm.trans evaluated + exact ih (reflects.push expr value exprEval) unfolded swept + +theorem Graph.Valid.unfold_defined {widths : GraphWidths} {graph : Graph} (valid : graph.Valid widths) : + ∃ trees, graph.unfold = some trees ∧ trees.size = graph.nodes.length := by + simpa only [Graph.unfold, Array.size_empty, Nat.zero_add] using unfoldFrom_defined (trees := #[]) valid.nodes + +theorem Graph.sweep_reflects (graph : Graph) (ops : EvalOps W) (values : Values W) + {trees : Array Expr} {buffer : Array W} + (unfolded : graph.unfold = some trees) (swept : graph.sweep ops values = some buffer) : + Reflects ops values trees buffer := + unfoldFrom_reflects ops values graph.nodes ⟨rfl, fun _ => rfl⟩ unfolded swept + +def readNodes (buffer : Array W) (roots : List Nat) : Option (List W) := + roots.mapM fun index => buffer[index]? + +def evalRoots (ops : EvalOps W) (values : Values W) (trees : Array Expr) (roots : List Nat) : Option (List W) := + roots.mapM fun index => (trees[index]?).bind (Expr.eval ops values) + +def readLookup (buffer : Array W) (lookup : Lookup) : Option (W × List W) := do + let multiplicity ← buffer[lookup.multiplicity]? + let args ← readNodes buffer lookup.args + return (multiplicity, args) + +def evalLookup (ops : EvalOps W) (values : Values W) (trees : Array Expr) + (lookup : Lookup) : Option (W × List W) := do + let multiplicity ← (trees[lookup.multiplicity]?).bind (Expr.eval ops values) + let args ← evalRoots ops values trees lookup.args + return (multiplicity, args) + +theorem Reflects.readNodes {ops : EvalOps W} {values : Values W} {trees : Array Expr} {buffer : Array W} + (reflects : Reflects ops values trees buffer) (roots : List Nat) : + readNodes buffer roots = evalRoots ops values trees roots := by + simp only [Aiur.NativeAIR.readNodes, evalRoots, reflects.2] + +theorem Reflects.readLookup {ops : EvalOps W} {values : Values W} {trees : Array Expr} {buffer : Array W} + (reflects : Reflects ops values trees buffer) (lookup : Lookup) : + readLookup buffer lookup = evalLookup ops values trees lookup := by + simp only [Aiur.NativeAIR.readLookup, evalLookup, reflects.2, reflects.readNodes] + +theorem readNodes_congr (left right : Array W) (roots : List Nat) + (agree : ∀ index ∈ roots, left[index]? = right[index]?) : readNodes left roots = readNodes right roots := by + induction roots with + | nil => rfl + | cons root roots ih => + simp only [readNodes, List.mapM_cons, agree root (by simp)] + rw [show roots.mapM (fun index => left[index]?) = roots.mapM (fun index => right[index]?) from + ih (fun index member => agree index (by simp [member]))] + +theorem readNodes_defined (buffer : Array W) (roots : List Nat) + (bound : ∀ index ∈ roots, index < buffer.size) : + ∃ values, readNodes buffer roots = some values ∧ values.length = roots.length := by + induction roots with + | nil => exact ⟨[], rfl, rfl⟩ + | cons root roots ih => + obtain ⟨values, read, size⟩ := ih (fun index member => bound index (by simp [member])) + have rootBound := bound root (by simp) + refine ⟨buffer[root] :: values, ?_, congrArg (· + 1) size⟩ + simp only [readNodes, List.mapM_cons, Array.getElem?_eq_getElem rootBound, bind, Option.bind] + change (readNodes buffer roots).bind (fun values => some (buffer[root] :: values)) = _ + rw [read]; rfl + +theorem readLookup_defined (buffer : Array W) (lookup : Lookup) + (bound : ∀ index ∈ lookup.roots, index < buffer.size) : + ∃ value, readLookup buffer lookup = some value ∧ value.2.length = lookup.args.length := by + have rootBound := bound lookup.multiplicity (by simp [Lookup.roots]) + obtain ⟨args, read, length⟩ := readNodes_defined buffer lookup.args + (fun index member => bound index (by simp [Lookup.roots, member])) + exact ⟨(buffer[lookup.multiplicity], args), by + simp only [readLookup, Array.getElem?_eq_getElem rootBound, read, bind, Option.bind, pure], length⟩ + +theorem Graph.Valid.lookup_values_agree {widths : GraphWidths} {graph : Graph} (valid : graph.Valid widths) + (ops : EvalOps W) (values : Values W) {full prefixValues : Array W} + (fullSweep : graph.sweep ops values = some full) + (partialSweep : graph.sweepLookupPrefix ops values = some prefixValues) + (size : prefixValues.size = graph.lookupPrefix) (lookup : Lookup) (member : lookup ∈ graph.lookups) : + readLookup full lookup = readLookup prefixValues lookup := by + have bound : ∀ index ∈ lookup.roots, index < prefixValues.size := by + intro index root + rw [size] + exact roots_below_prefix graph.lookupRoots index (List.mem_flatMap.mpr ⟨lookup, member, root⟩) + have agree : ∀ index ∈ lookup.roots, full[index]? = prefixValues[index]? := + fun index root => valid.lookup_sweep_agrees ops values fullSweep partialSweep index (bound index root) + simp only [readLookup, agree lookup.multiplicity (by simp [Lookup.roots])] + rw [readNodes_congr full prefixValues lookup.args + (fun index root => agree index (by simp [Lookup.roots, root]))] + +theorem Graph.Valid.lookup_values_reflect {widths : GraphWidths} {graph : Graph} (valid : graph.Valid widths) + (ops : EvalOps W) (values : Values W) {trees : Array Expr} {full prefixValues : Array W} + (unfolded : graph.unfold = some trees) + (fullSweep : graph.sweep ops values = some full) + (partialSweep : graph.sweepLookupPrefix ops values = some prefixValues) + (size : prefixValues.size = graph.lookupPrefix) (lookup : Lookup) (member : lookup ∈ graph.lookups) : + readLookup prefixValues lookup = evalLookup ops values trees lookup := + (valid.lookup_values_agree ops values fullSweep partialSweep size lookup member).symm.trans + ((graph.sweep_reflects ops values unfolded fullSweep).readLookup lookup) + +def goldilocksOps : EvalOps G := ⟨id, (· + ·), (· - ·), (· * ·), (0 - ·)⟩ + +end Aiur.NativeAIR diff --git a/Ix/Aiur/Proofs/Extension.lean b/Ix/Aiur/Proofs/Extension.lean new file mode 100644 index 000000000..c2daaf43f --- /dev/null +++ b/Ix/Aiur/Proofs/Extension.lean @@ -0,0 +1,220 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Extension +import Ix.Aiur.Proofs.GoldilocksAlgebra + +/-! Algebra of the native quadratic coordinates, with base embedding, +conjugation, norm and the working operations used by expression reflection. +Ring laws alone do not establish that the quadratic algebra is a field. +-/ + +namespace Aiur.NativeAIR.ProofCodec.Extension + +theorem ext {a b : Extension} (c0 : a.c0 = b.c0) (c1 : a.c1 = b.c1) : a = b := by + cases a; cases b; cases c0; cases c1; rfl + +theorem ofBase_injective {a b : G} (equal : ofBase a = ofBase b) : a = b := + congrArg Extension.c0 equal + +theorem ofBase_add (a b : G) : ofBase (a + b) = ofBase a + ofBase b := by + apply ext + · rfl + · change (0 : G) = 0 + 0; grind + +theorem ofBase_sub (a b : G) : ofBase (a - b) = ofBase a - ofBase b := by + apply ext + · rfl + · change (0 : G) = 0 - 0; grind + +theorem ofBase_neg (a : G) : ofBase (-a) = -ofBase a := by + apply ext + · rfl + · change (0 : G) = 0 - 0; grind + +theorem ofBase_mul (a b : G) : ofBase (a * b) = ofBase a * ofBase b := by + apply ext + · change a * b = a * b + 0 * (0 * 7); grind + · change (0 : G) = a * 0 + 0 * b; grind + +theorem add_zero (a : Extension) : a + 0 = a := by + apply ext + · exact G.add_zero a.c0 + · exact G.add_zero a.c1 + +theorem add_comm (a b : Extension) : a + b = b + a := + ext (G.add_comm _ _) (G.add_comm _ _) + +theorem add_assoc (a b c : Extension) : a + b + c = a + (b + c) := + ext (G.add_assoc _ _ _) (G.add_assoc _ _ _) + +theorem mul_one (a : Extension) : a * 1 = a := by + apply ext + · change a.c0 * 1 + a.c1 * (0 * 7) = a.c0; grind + · change a.c0 * 0 + a.c1 * 1 = a.c1; grind + +theorem zero_mul (a : Extension) : 0 * a = 0 := by + apply ext + · change 0 * a.c0 + 0 * (a.c1 * 7) = (0 : G); grind + · change 0 * a.c1 + 0 * a.c0 = (0 : G); grind + +theorem mul_comm (a b : Extension) : a * b = b * a := by + apply ext + · change a.c0 * b.c0 + a.c1 * (b.c1 * 7) = b.c0 * a.c0 + b.c1 * (a.c1 * 7); grind + · change a.c0 * b.c1 + a.c1 * b.c0 = b.c0 * a.c1 + b.c1 * a.c0; grind + +theorem mul_assoc (a b c : Extension) : a * b * c = a * (b * c) := by + apply ext + · change (a.c0 * b.c0 + a.c1 * (b.c1 * 7)) * c.c0 + + (a.c0 * b.c1 + a.c1 * b.c0) * (c.c1 * 7) = + a.c0 * (b.c0 * c.c0 + b.c1 * (c.c1 * 7)) + a.c1 * ((b.c0 * c.c1 + b.c1 * c.c0) * 7) + grind + · change (a.c0 * b.c0 + a.c1 * (b.c1 * 7)) * c.c1 + + (a.c0 * b.c1 + a.c1 * b.c0) * c.c0 = + a.c0 * (b.c0 * c.c1 + b.c1 * c.c0) + a.c1 * (b.c0 * c.c0 + b.c1 * (c.c1 * 7)) + grind + +theorem left_distrib (a b c : Extension) : a * (b + c) = a * b + a * c := by + apply ext + · change a.c0 * (b.c0 + c.c0) + a.c1 * ((b.c1 + c.c1) * 7) = + (a.c0 * b.c0 + a.c1 * (b.c1 * 7)) + (a.c0 * c.c0 + a.c1 * (c.c1 * 7)) + grind + · change a.c0 * (b.c1 + c.c1) + a.c1 * (b.c0 + c.c0) = + (a.c0 * b.c1 + a.c1 * b.c0) + (a.c0 * c.c1 + a.c1 * c.c0) + grind + +theorem neg_add_cancel (a : Extension) : -a + a = 0 := by + apply ext + · exact G.neg_add_cancel a.c0 + · exact G.neg_add_cancel a.c1 + +theorem sub_eq_add_neg (a b : Extension) : a - b = a + -b := + ext (G.sub_eq_add_neg _ _) (G.sub_eq_add_neg _ _) + +instance natCast : NatCast Extension := ⟨fun n => ofBase (G.ofNat n)⟩ +instance intCast : IntCast Extension := ⟨fun n => ofBase (G.ofInt n)⟩ +instance nsmul : SMul Nat Extension := ⟨fun n a => ofBase (G.ofNat n) * a⟩ +instance zsmul : SMul Int Extension := ⟨fun n a => ofBase (G.ofInt n) * a⟩ +instance npow : HPow Extension Nat Extension := ⟨fun a n => npowRec n a⟩ + +theorem neg_mul (a b : Extension) : -a * b = -(a * b) := by + apply ext + · change (0 - a.c0) * b.c0 + (0 - a.c1) * (b.c1 * 7) = + 0 - (a.c0 * b.c0 + a.c1 * (b.c1 * 7)) + grind + · change (0 - a.c0) * b.c1 + (0 - a.c1) * b.c0 = + 0 - (a.c0 * b.c1 + a.c1 * b.c0) + grind + +instance commRing : Lean.Grind.CommRing Extension where + add_zero := add_zero + add_comm := add_comm + add_assoc := add_assoc + mul_assoc := mul_assoc + mul_comm := mul_comm + mul_one := mul_one + left_distrib := left_distrib + zero_mul := zero_mul + mul_zero a := by rw [mul_comm, zero_mul] + pow_zero _ := rfl + pow_succ _ _ := rfl + ofNat_succ n := by + change ofBase (G.ofNat (n + 1)) = ofBase (G.ofNat n) + ofBase 1 + rw [G.ofNat_add, ofBase_add] + rfl + neg_add_cancel := neg_add_cancel + sub_eq_add_neg := sub_eq_add_neg + intCast_neg n := by + change ofBase (G.ofInt (-n)) = -ofBase (G.ofInt n) + rw [G.ofInt_neg, ofBase_neg] + neg_zsmul n a := by + change ofBase (G.ofInt (-n)) * a = -(ofBase (G.ofInt n) * a) + rw [G.ofInt_neg, ofBase_neg, neg_mul] + +theorem basis_square : basis * basis = ofBase 7 := by decide +kernel + +theorem coordinates (a : Extension) : a = ofBase a.c0 + ofBase a.c1 * basis := by + apply ext + · change a.c0 = a.c0 + (a.c1 * 0 + 0 * (1 * 7)); grind + · change a.c1 = 0 + (a.c1 * 1 + 0 * 0); grind + +theorem scale_eq_mul (a : Extension) (b : G) : a.scale b = a * ofBase b := by + apply ext + · change a.c0 * b = a.c0 * b + a.c1 * (0 * 7); grind + · change a.c1 * b = a.c0 * 0 + a.c1 * b; grind + +theorem conjugate_conjugate (a : Extension) : a.conjugate.conjugate = a := by + apply ext + · rfl + · exact G.neg_neg a.c1 + +theorem mul_conjugate (a : Extension) : a * a.conjugate = ofBase a.norm := by + apply ext + · change a.c0 * a.c0 + a.c1 * ((0 - a.c1) * 7) = a.c0 * a.c0 - 7 * (a.c1 * a.c1) + grind + · change a.c0 * (0 - a.c1) + a.c1 * a.c0 = (0 : G); grind + +theorem conjugate_mul (a b : Extension) : (a * b).conjugate = a.conjugate * b.conjugate := by + apply ext + · change a.c0 * b.c0 + a.c1 * (b.c1 * 7) = a.c0 * b.c0 + (0 - a.c1) * ((0 - b.c1) * 7) + grind + · change 0 - (a.c0 * b.c1 + a.c1 * b.c0) = a.c0 * (0 - b.c1) + (0 - a.c1) * b.c0 + grind + +theorem norm_mul (a b : Extension) : (a * b).norm = a.norm * b.norm := by + apply ofBase_injective + rw [ofBase_mul, ← mul_conjugate, ← mul_conjugate, ← mul_conjugate, conjugate_mul] + grind + +theorem evalLaws : EvalLaws evalOps where + konst_add := ofBase_add + konst_sub := ofBase_sub + konst_mul := ofBase_mul + konst_neg := ofBase_neg + add_zero := add_zero + zero_add a := by change 0 + a = a; grind + sub_zero a := by change a - 0 = a; grind + zero_sub a := by change 0 - a = -a; grind + mul_zero a := by change a * 0 = 0; grind + zero_mul := zero_mul + mul_one := mul_one + one_mul a := by change 1 * a = a; grind + neg_neg a := by change - - a = a; grind + +theorem powBits_eq (a : Extension) (n fuel : Nat) (bounded : n < 2 ^ fuel) : + powBits a n fuel = a ^ n := by + induction fuel generalizing n with + | zero => + have zero : n = 0 := by simpa using bounded + subst n + rfl + | succ fuel ih => + by_cases zero : n = 0 + · subst n + rfl + · have half : n / 2 < 2 ^ fuel := + (Nat.div_lt_iff_lt_mul (by decide)).mpr (by simpa only [Nat.pow_succ] using bounded) + simp only [powBits, beq_iff_eq, if_neg zero, ih _ half] + by_cases even : n % 2 = 0 + · rw [if_pos even, ← Lean.Grind.Semiring.pow_add] + congr 1 + omega + · rw [if_neg even, ← Lean.Grind.Semiring.pow_add, ← Lean.Grind.Semiring.pow_succ] + congr 1 + omega + +theorem power_eq (a : Extension) (n : Nat) : power a n = a ^ n := + powBits_eq a n _ Nat.lt_log2_self + +theorem ofBase_power (a : G) (n : Nat) : ofBase (a ^ n) = ofBase a ^ n := by + induction n with + | zero => rfl + | succ n ih => rw [Lean.Grind.Semiring.pow_succ, Lean.Grind.Semiring.pow_succ, ofBase_mul, ih] + +theorem inverse_formula (a : Extension) : + a.tryInverse = if a = 0 then none else some (a.conjugate * ofBase (a.norm ^ (gSize.toNat - 2))) := by + simp only [tryInverse, beq_iff_eq, scale_eq_mul, G.inverse_eq_power] + +end Aiur.NativeAIR.ProofCodec.Extension diff --git a/Ix/Aiur/Proofs/ExtensionField.lean b/Ix/Aiur/Proofs/ExtensionField.lean new file mode 100644 index 000000000..8220bdc3a --- /dev/null +++ b/Ix/Aiur/Proofs/ExtensionField.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Extension +import Ix.Aiur.Proofs.GoldilocksInverse + +/-! The native relation `u² = 7` gives a field. A kernel-evaluated Euler +certificate and the proved Goldilocks Fermat theorem exclude square roots +of seven. The norm is therefore nonzero on every nonzero extension value, +which validates the concrete inverse formula used by the native backend. +-/ + +namespace Aiur.G + +theorem seven_euler_certificate : G.pow 7 ((gSize.toNat - 1) / 2) = 0 - 1 := by + decide +kernel + +theorem seven_not_square (a : G) : a * a ≠ 7 := by + intro square + have nonzero : a ≠ 0 := by + intro zero + rw [zero, G.mul_zero] at square + exact (by decide : (0 : G) ≠ 7) square + have raised := congrArg (fun value : G => value ^ ((gSize.toNat - 1) / 2)) square + rw [Lean.Grind.CommSemiring.mul_pow, ← Lean.Grind.Semiring.pow_add] at raised + have twice : (gSize.toNat - 1) / 2 + (gSize.toNat - 1) / 2 = gSize.toNat - 1 := by decide + rw [twice, fermat a nonzero, ← G.pow_eq _ _ (by decide), seven_euler_certificate] at raised + exact (by decide : (1 : G) ≠ 0 - 1) raised + +theorem square_ratio (x y inverse : G) (square : x * x = 7 * (y * y)) + (cancel : y * inverse = 1) : (x * inverse) * (x * inverse) = 7 := by + grind + +end Aiur.G + +namespace Aiur.NativeAIR.ProofCodec.Extension + +theorem norm_zero_iff (a : Extension) : a.norm = 0 ↔ a = 0 := by + constructor + · intro zero + have square : a.c0 * a.c0 = 7 * (a.c1 * a.c1) := by + change a.c0 * a.c0 - 7 * (a.c1 * a.c1) = 0 at zero + exact (G.sub_eq_zero_iff _ _).mp zero + by_cases last : a.c1 = 0 + · rw [last, G.mul_zero, G.mul_zero] at square + have first := (G.mul_eq_zero_iff _ _).mp square + apply ext + · exact first.elim id id + · exact last + · have inverse := G.mul_inverse_cancel a.c1 last + exact False.elim (G.seven_not_square (a.c0 * a.c1.inverse) (G.square_ratio _ _ _ square inverse)) + · intro zero + rw [zero] + rfl + +theorem mul_eq_zero_iff (a b : Extension) : a * b = 0 ↔ a = 0 ∨ b = 0 := by + constructor + · intro zero + have norms := congrArg norm zero + rw [norm_mul] at norms + change a.norm * b.norm = 0 at norms + rcases (G.mul_eq_zero_iff _ _).mp norms with left | right + · exact Or.inl ((norm_zero_iff a).mp left) + · exact Or.inr ((norm_zero_iff b).mp right) + · rintro (rfl | rfl) <;> grind + +theorem one_ne_zero : (1 : Extension) ≠ 0 := by decide + +theorem mul_left_cancel {a b c : Extension} (nonzero : a ≠ 0) (equal : a * b = a * c) : b = c := by + have zero : a * (b - c) = 0 := by grind + have equal := (mul_eq_zero_iff _ _).mp zero |>.resolve_left nonzero + grind + +theorem inverse_correct (a : Extension) (nonzero : a ≠ 0) : + a.tryInverse = some (a.conjugate.scale a.norm.inverse) ∧ + a * (a.conjugate.scale a.norm.inverse) = 1 := by + constructor + · simp only [tryInverse, beq_iff_eq, if_neg nonzero] + · have normNonzero : a.norm ≠ 0 := fun zero => nonzero ((norm_zero_iff a).mp zero) + rw [scale_eq_mul, ← mul_assoc, mul_conjugate, ← ofBase_mul, G.mul_inverse_cancel _ normNonzero] + rfl + +theorem tryInverse_none_iff (a : Extension) : a.tryInverse = none ↔ a = 0 := by + simp only [tryInverse, beq_iff_eq] + split <;> simp_all + +theorem tryInverse_some_iff (a b : Extension) : a.tryInverse = some b ↔ a * b = 1 := by + constructor + · intro accepted + have nonzero : a ≠ 0 := by + intro zero + rw [zero, tryInverse] at accepted + cases accepted + obtain ⟨returned, correct⟩ := inverse_correct a nonzero + have same := Option.some.inj (accepted.symm.trans returned) + exact same ▸ correct + · intro inverse + have nonzero : a ≠ 0 := by + intro zero + rw [zero, zero_mul] at inverse + exact one_ne_zero inverse.symm + obtain ⟨returned, correct⟩ := inverse_correct a nonzero + have result := mul_left_cancel nonzero (inverse.trans correct.symm) + exact result.symm ▸ returned + +end Aiur.NativeAIR.ProofCodec.Extension diff --git a/Ix/Aiur/Proofs/ExtensionMmcs.lean b/Ix/Aiur/Proofs/ExtensionMmcs.lean new file mode 100644 index 000000000..14474cc1f --- /dev/null +++ b/Ix/Aiur/Proofs/ExtensionMmcs.lean @@ -0,0 +1,255 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ExtensionMmcs +import Ix.Aiur.Proofs.PrunedMerkle + +/-! Extension-coordinate packing and its authenticated row correspondence. -/ + +namespace Aiur.NativeAIR.ExtensionMmcs + +open Merkle (Digest Hash Dimensions) +open ProofCodec (Extension) + +theorem baseRow_length (values : List Extension) : (baseRow values).length = values.length * 2 := by + induction values with + | nil => rfl + | cons value values ih => + simp only [baseRow, List.flatMap_cons, List.cons_append, List.nil_append, List.length_cons] at ih ⊢ + omega + +theorem baseRow_injective {left right : List Extension} (same : baseRow left = baseRow right) : left = right := by + induction left generalizing right with + | nil => + have count := congrArg List.length same + rw [baseRow_length, baseRow_length] at count + have empty : right.length = 0 := by simp only [List.length_nil] at count; omega + exact (List.eq_nil_of_length_eq_zero empty).symm + | cons value values ih => + cases right with + | nil => + have count := congrArg List.length same + rw [baseRow_length, baseRow_length] at count + simp only [List.length_cons, List.length_nil] at count + omega + | cons other others => + simp only [baseRow, List.flatMap_cons, List.cons_append, List.nil_append, List.cons.injEq] at same + have rowEq : value = other := by + cases value + cases other + simp only [Extension.mk.injEq] + exact ⟨same.1, same.2.1⟩ + rw [rowEq, ih same.2.2] + +theorem baseRows_length (rows : List (List Extension)) : (baseRows rows).length = rows.length := + List.length_map _ + +theorem baseRows_injective {left right : List (List Extension)} (same : baseRows left = baseRows right) : left = right := by + induction left generalizing right with + | nil => + have count := congrArg List.length same + rw [baseRows_length, baseRows_length] at count + exact (List.eq_nil_of_length_eq_zero count.symm).symm + | cons row rows ih => + cases right with + | nil => simp only [baseRows, List.map_cons, List.map_nil, List.cons_ne_nil] at same + | cons other others => + simp only [baseRows, List.map_cons, List.cons.injEq] at same + rw [baseRow_injective same.1, ih same.2] + +theorem baseRows_fields (rows : List (List Extension)) : + (baseRows rows).flatten.length = rows.flatten.length * 2 := by + induction rows with + | nil => rfl + | cons row rows ih => + simp only [baseRows, List.map_cons, List.flatten_cons, List.length_append, baseRow_length] at ih ⊢ + omega + +theorem baseDimensions_length (wordBits : Nat) (dimensions : List Dimensions) : + (baseDimensions wordBits dimensions).length = dimensions.length := List.length_map _ + +theorem baseDimensions_heights (wordBits : Nat) (dimensions : List Dimensions) : + (baseDimensions wordBits dimensions).map Dimensions.logHeight = dimensions.map Dimensions.logHeight := by + simp only [baseDimensions, List.map_map, Function.comp_def] + +theorem baseDimensions_maxHeight (wordBits : Nat) (dimensions : List Dimensions) : + Merkle.maxHeight (baseDimensions wordBits dimensions) = Merkle.maxHeight dimensions := by + simp only [Merkle.maxHeight, baseDimensions_heights] + +theorem baseDimensions_covered (wordBits : Nat) (dimensions : List Dimensions) (capHeight : Nat) : + Merkle.covered (baseDimensions wordBits dimensions) capHeight = Merkle.covered dimensions capHeight := by + simp only [Merkle.covered, baseDimensions_heights] + +theorem baseDimensions_exact {wordBits : Nat} {dimensions : List Dimensions} (bounded : WidthsFit wordBits dimensions) : + baseDimensions wordBits dimensions = dimensions.map (fun dimension => { dimension with width := dimension.width * 2 }) := by + apply List.map_congr_left + intro dimension member + simp only [Nat.mod_eq_of_lt (bounded dimension member)] + +theorem shape_base {wordBits : Nat} {dimensions : List Dimensions} {rows : List (List Extension)} + (bounded : WidthsFit wordBits dimensions) : + Merkle.shape (baseDimensions wordBits dimensions) (baseRows rows) = shape dimensions rows := by + rw [baseDimensions_exact bounded] + induction dimensions generalizing rows with + | nil => cases rows <;> rfl + | cons dimension dimensions ih => + have tailBound : WidthsFit wordBits dimensions := + fun child member => bounded child (List.mem_cons.mpr (Or.inr member)) + cases rows with + | nil => rfl + | cons row rows => + have count : ((baseRow row).length == dimension.width * 2) = (row.length == dimension.width) := by + rw [baseRow_length] + have equality : (row.length * 2 = dimension.width * 2) ↔ row.length = dimension.width := by omega + apply Bool.eq_iff_iff.mpr + simpa only [beq_iff_eq] using equality + change (((baseRow row).length == dimension.width * 2) && + Merkle.shape (dimensions.map (fun dimension => { dimension with width := dimension.width * 2 })) + (baseRows rows)) = ((row.length == dimension.width) && shape dimensions rows) + rw [count, ih tailBound] + +theorem fri_width_fits {logArity height : Nat} (bounded : logArity ≤ 32) : + WidthsFit 64 [⟨2^logArity, height⟩] := by + intro dimension member + obtain rfl := List.mem_singleton.mp member + change 2^logArity * 2 < 2^64 + rw [← Nat.pow_succ] + exact Nat.pow_lt_pow_right (by decide) (by omega) + +theorem baseRows_query {indices : List Nat} {rows : List (List (List Extension))} + {index : Nat} {query : List (List Extension)} (member : (index, query) ∈ indices.zip rows) : + (index, baseRows query) ∈ indices.zip (rows.map baseRows) := by + rw [List.zip_map_right] + exact List.mem_map.mpr ⟨(index, query), member, rfl⟩ + +theorem replay_shape {hash : Hash} {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {rows : List (List Extension)} {proof : List Digest} {result : Merkle.Replay} + (bounded : WidthsFit wordBits dimensions) + (success : replay hash wordBits dimensions capHeight index rows proof = some result) : + shape dimensions rows = true := by + have fits := (Merkle.replay_success success).2.1 + rwa [shape_base bounded] at fits + +theorem verifyMulti_individual {hash : Hash} {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {indices : List Nat} {cap : List Digest} {rows : List (List (List Extension))} {query : List (List Extension)} + {proof : List Digest} + (accepted : verifyMulti hash wordBits dimensions capHeight indices cap rows proof = true) + (member : (index, query) ∈ indices.zip rows) : + ∃ path result, replay hash wordBits dimensions capHeight index query path = some result ∧ + verify hash wordBits dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ (replayMulti hash wordBits dimensions capHeight indices rows proof).inputs := + PrunedMerkle.verify_individual accepted (baseRows_query member) + +theorem verifyMulti_shape {hash : Hash} {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {indices : List Nat} {cap : List Digest} {rows : List (List (List Extension))} {query : List (List Extension)} + {proof : List Digest} + (bounded : WidthsFit wordBits dimensions) + (accepted : verifyMulti hash wordBits dimensions capHeight indices cap rows proof = true) + (member : (index, query) ∈ indices.zip rows) : shape dimensions query = true := by + obtain ⟨_, _, result, _, _⟩ := verifyMulti_individual accepted member + exact replay_shape bounded result + +theorem verifyMultiCovered_individual {hash : Hash} {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {indices : List Nat} {cap : List Digest} {rows : List (List (List Extension))} {query : List (List Extension)} + {proof : List Digest} + (accepted : verifyMultiCovered hash wordBits dimensions capHeight indices cap rows proof = true) + (member : (index, query) ∈ indices.zip rows) : + ∃ path result, replay hash wordBits dimensions capHeight index query path = some result ∧ + verifyCovered hash wordBits dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ (replayMulti hash wordBits dimensions capHeight indices rows proof).inputs := by + simp only [verifyMultiCovered, Bool.and_eq_true] at accepted + obtain ⟨path, result, evaluated, verified, subset⟩ := verifyMulti_individual accepted.2 member + exact ⟨path, result, evaluated, by simp only [verifyCovered, accepted.1, verified, Bool.and_self], subset⟩ + +theorem replay_native_input {hash : Hash} {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {rows : List (List Extension)} {proof : List Digest} {result : Merkle.Replay} + (success : replay hash wordBits dimensions capHeight index rows proof = some result) + (bounded : rows.flatten.length < 2^60) {input : List UInt8} (member : input ∈ result.hashing.inputs) : + Blake3.NativeInput input := by + have baseBound : (baseRows rows).flatten.length < 2^61 := by rw [baseRows_fields]; omega + exact Merkle.replay_native_input success baseBound member + +theorem verifyCovered_collision {hash : Hash} {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {cap : List Digest} {leftRows rightRows : List (List Extension)} {leftProof rightProof : List Digest} + (left : verifyCovered hash wordBits dimensions capHeight index cap leftRows leftProof = true) + (right : verifyCovered hash wordBits dimensions capHeight index cap rightRows rightProof = true) + (different : leftRows ≠ rightRows) : + ∃ left right, replay hash wordBits dimensions capHeight index leftRows leftProof = some left ∧ + replay hash wordBits dimensions capHeight index rightRows rightProof = some right ∧ + Merkle.CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) := by + simp only [verifyCovered, Bool.and_eq_true] at left right + have coverage : Merkle.covered (baseDimensions wordBits dimensions) capHeight = true := by + simpa only [baseDimensions_covered] using left.1 + have distinct : baseRows leftRows ≠ baseRows rightRows := fun same => different (baseRows_injective same) + simpa only [replay, baseDimensions_maxHeight] using Merkle.verify_collision coverage left.2 right.2 distinct + +theorem verifyMultiCovered_collision {hash : Hash} {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {leftIndices rightIndices : List Nat} {cap : List Digest} + {leftRows rightRows : List (List (List Extension))} {leftQuery rightQuery : List (List Extension)} + {leftProof rightProof : List Digest} + (left : verifyMultiCovered hash wordBits dimensions capHeight leftIndices cap leftRows leftProof = true) + (right : verifyMultiCovered hash wordBits dimensions capHeight rightIndices cap rightRows rightProof = true) + (leftMember : (index, leftQuery) ∈ leftIndices.zip leftRows) + (rightMember : (index, rightQuery) ∈ rightIndices.zip rightRows) + (different : leftQuery ≠ rightQuery) : + ∃ inputs, + inputs ⊆ (replayMulti hash wordBits dimensions capHeight leftIndices leftRows leftProof).inputs ++ + (replayMulti hash wordBits dimensions capHeight rightIndices rightRows rightProof).inputs ∧ + Merkle.CollisionOn hash inputs ∧ inputs.length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) ∧ + ∀ input ∈ inputs, input.length ≤ max 64 (16 * max leftQuery.flatten.length rightQuery.flatten.length) := by + simp only [verifyMultiCovered, Bool.and_eq_true] at left right + have coverage : Merkle.covered (baseDimensions wordBits dimensions) capHeight = true := by + simpa only [baseDimensions_covered] using left.1 + have distinct : baseRows leftQuery ≠ baseRows rightQuery := fun same => different (baseRows_injective same) + obtain ⟨inputs, subset, collision, count, bytes⟩ := PrunedMerkle.verify_collision coverage left.2 right.2 + (baseRows_query leftMember) (baseRows_query rightMember) distinct + refine ⟨inputs, subset, collision, ?_, ?_⟩ + · simpa only [baseDimensions_maxHeight] using count + · intro input member + have bounded := bytes input member + rw [baseRows_fields, baseRows_fields] at bounded + omega + +theorem blake3_native_collision {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {cap : List Digest} {leftRows rightRows : List (List Extension)} {leftProof rightProof : List Digest} + (left : verifyCovered Blake3.digest wordBits dimensions capHeight index cap leftRows leftProof = true) + (right : verifyCovered Blake3.digest wordBits dimensions capHeight index cap rightRows rightProof = true) + (different : leftRows ≠ rightRows) + (leftBound : leftRows.flatten.length < 2^60) (rightBound : rightRows.flatten.length < 2^60) : + ∃ left right, replay Blake3.digest wordBits dimensions capHeight index leftRows leftProof = some left ∧ + replay Blake3.digest wordBits dimensions capHeight index rightRows rightProof = some right ∧ + Merkle.CollisionOn Blake3.digest (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) ∧ + ∀ input ∈ left.hashing.inputs ++ right.hashing.inputs, Blake3.NativeInput input := by + obtain ⟨left, right, leftReplay, rightReplay, collision, count⟩ := verifyCovered_collision left right different + refine ⟨left, right, leftReplay, rightReplay, collision, count, ?_⟩ + intro input member + exact (List.mem_append.mp member).elim (replay_native_input leftReplay leftBound) + (replay_native_input rightReplay rightBound) + +theorem blake3_multi_native_collision {wordBits capHeight index : Nat} {dimensions : List Dimensions} + {leftIndices rightIndices : List Nat} {cap : List Digest} + {leftRows rightRows : List (List (List Extension))} {leftQuery rightQuery : List (List Extension)} + {leftProof rightProof : List Digest} + (left : verifyMultiCovered Blake3.digest wordBits dimensions capHeight leftIndices cap leftRows leftProof = true) + (right : verifyMultiCovered Blake3.digest wordBits dimensions capHeight rightIndices cap rightRows rightProof = true) + (leftMember : (index, leftQuery) ∈ leftIndices.zip leftRows) + (rightMember : (index, rightQuery) ∈ rightIndices.zip rightRows) + (different : leftQuery ≠ rightQuery) + (leftBound : leftQuery.flatten.length < 2^60) (rightBound : rightQuery.flatten.length < 2^60) : + ∃ inputs, + inputs ⊆ (replayMulti Blake3.digest wordBits dimensions capHeight leftIndices leftRows leftProof).inputs ++ + (replayMulti Blake3.digest wordBits dimensions capHeight rightIndices rightRows rightProof).inputs ∧ + Merkle.CollisionOn Blake3.digest inputs ∧ inputs.length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) ∧ + ∀ input ∈ inputs, Blake3.NativeInput input := by + obtain ⟨inputs, subset, collision, count, bytes⟩ := verifyMultiCovered_collision left right leftMember rightMember different + refine ⟨inputs, subset, collision, count, ?_⟩ + intro input member + have := bytes input member + unfold Blake3.NativeInput + omega + +end Aiur.NativeAIR.ExtensionMmcs diff --git a/Ix/Aiur/Proofs/Field.lean b/Ix/Aiur/Proofs/Field.lean new file mode 100644 index 000000000..07da05f5e --- /dev/null +++ b/Ix/Aiur/Proofs/Field.lean @@ -0,0 +1,268 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Lookup +import Init.Data.Nat.Coprime +import Init.Data.List.Nat.Range +import Init.Data.List.Perm + +/-! +Primality and local field consequences for the actual Goldilocks model. + +A kernel-checked certificate gives a unit of order `2^32` modulo every +nontrivial divisor of `2^64 - 2^32 + 1`. Its first `2^32` powers are distinct, +so each such divisor is at least `2^32`. Two nontrivial factors would have +product at least `2^64`, proving primality. Only 32 modular squarings are +evaluated; the proof neither enumerates the field nor evaluates enormous +unreduced powers. It uses no native-evaluation axiom or external field oracle. + +The resulting no-zero-divisors theorem discharges boolean-selector and +equality-test polynomial implications. These are arithmetic facts about +Lean's `G`; extraction from native constraint expressions remains separate. +-/ + +namespace Aiur.GoldilocksProof + +/-- Repeated modular squaring, with an explicit modulus and base. -/ +def squareMod (modulus base : Nat) : Nat → Nat + | 0 => base % modulus + | n + 1 => let previous := squareMod modulus base n; previous * previous % modulus + +theorem squareMod_eq (modulus base n : Nat) : + squareMod modulus base n = base ^ (2 ^ n) % modulus := by + induction n with + | zero => simp [squareMod] + | succ n ih => + rw [squareMod, ih, Nat.pow_succ, Nat.pow_mul] + simp only [Nat.pow_two, Nat.mul_mod_mod, Nat.mod_mul_mod] + +theorem squareMod_half : squareMod gSize.toNat 1753635133440165772 31 = gSize.toNat - 1 := by + decide +kernel + +theorem squareMod_full : squareMod gSize.toNat 1753635133440165772 32 = 1 := by + decide +kernel + +theorem pow_mod_period {modulus base period : Nat} (hmod : 1 < modulus) + (hperiod : base ^ period % modulus = 1) (exponent : Nat) : + base ^ exponent % modulus = base ^ (exponent % period) % modulus := by + conv => lhs; rw [← Nat.mod_add_div exponent period] + rw [Nat.pow_add, Nat.pow_mul, Nat.mul_mod, Nat.pow_mod (base ^ period), hperiod] + simp only [Nat.one_pow, Nat.mod_eq_of_lt hmod, Nat.mul_one, Nat.mod_mod] + +theorem pow_mod_gcd {modulus base : Nat} (hmod : 1 < modulus) (a b : Nat) + (ha : base ^ a % modulus = 1) (hb : base ^ b % modulus = 1) : + base ^ (Nat.gcd a b) % modulus = 1 := by + induction a using Nat.strongRecOn generalizing b with + | ind a ih => + by_cases hz : a = 0 + · subst a; simpa only [Nat.gcd_zero_left] using hb + · rw [Nat.gcd_rec] + apply ih (b % a) (Nat.mod_lt _ (Nat.pos_of_ne_zero hz)) a + · exact (pow_mod_period hmod ha b).symm.trans hb + · exact ha + +theorem divisor_two_pow {d n : Nat} (divides : d ∣ 2 ^ n) : + ∃ k, k ≤ n ∧ d = 2 ^ k := by + induction n generalizing d with + | zero => exact ⟨0, Nat.le_refl _, Nat.eq_one_of_dvd_one divides⟩ + | succ n ih => + rw [Nat.pow_succ, Nat.dvd_mul] at divides + obtain ⟨a, b, ha, hb, equal⟩ := divides + obtain ⟨k, hk, rfl⟩ := ih ha + have bound : b ≤ 2 := Nat.le_of_dvd (by decide) hb + have positive : 0 < b := Nat.pos_of_dvd_of_pos hb (by decide) + have cases : b = 1 ∨ b = 2 := by omega + rcases cases with rfl | rfl + · exact ⟨k, by omega, by simpa only [Nat.mul_one] using equal.symm⟩ + · exact ⟨k + 1, by omega, by simpa only [Nat.pow_succ] using equal.symm⟩ + +theorem proper_divisor_two_pow {d n : Nat} (divides : d ∣ 2 ^ (n + 1)) + (proper : d < 2 ^ (n + 1)) : d ∣ 2 ^ n := by + obtain ⟨k, hk, rfl⟩ := divisor_two_pow divides + apply Nat.pow_dvd_pow + have ne : k ≠ n + 1 := by intro equal; subst k; exact Nat.lt_irrefl _ proper + omega + +theorem pow_mod_ne_one {modulus base n : Nat} (hmod : 1 < modulus) + (full : base ^ (2 ^ (n + 1)) % modulus = 1) + (half : base ^ (2 ^ n) % modulus ≠ 1) + {k : Nat} (positive : 0 < k) (small : k < 2 ^ (n + 1)) : + base ^ k % modulus ≠ 1 := by + intro equal + have hg := pow_mod_gcd hmod k (2 ^ (n + 1)) equal full + have gd : Nat.gcd k (2 ^ (n + 1)) ∣ 2 ^ n := by + apply proper_divisor_two_pow (Nat.gcd_dvd_right _ _) + exact Nat.lt_of_le_of_lt (Nat.gcd_le_left _ positive) small + apply half + rw [pow_mod_period hmod hg, Nat.mod_eq_zero_of_dvd gd] + exact Nat.mod_eq_of_lt hmod + +theorem pow_mod_injective {modulus base n : Nat} (hmod : 1 < modulus) + (full : base ^ (2 ^ (n + 1)) % modulus = 1) + (half : base ^ (2 ^ n) % modulus ≠ 1) + {i j : Nat} (hi : i < 2 ^ (n + 1)) (hj : j < 2 ^ (n + 1)) + (equal : base ^ i % modulus = base ^ j % modulus) : i = j := by + suffices step : ∀ i j, i < j → j < 2 ^ (n + 1) → + base ^ i % modulus = base ^ j % modulus → False by + by_cases h : i < j + · exact False.elim (step i j h hj equal) + · by_cases h' : j < i + · exact False.elim (step j i h' hi equal.symm) + · omega + intro i j lt bound same + have translated : base ^ (i + (2 ^ (n + 1) - i)) % modulus = + base ^ (j + (2 ^ (n + 1) - i)) % modulus := by + rw [Nat.pow_add base i, Nat.pow_add base j, + Nat.mul_mod (base ^ i), Nat.mul_mod (base ^ j), same] + have left : i + (2 ^ (n + 1) - i) = 2 ^ (n + 1) := by omega + have right : j + (2 ^ (n + 1) - i) = (j - i) + 2 ^ (n + 1) := by omega + rw [left, full, right, Nat.pow_add, Nat.mul_mod, full, Nat.mul_one, Nat.mod_mod] at translated + exact pow_mod_ne_one hmod full half (by omega) (by omega) translated.symm + +theorem two_pow_le_modulus {modulus base n : Nat} (hmod : 1 < modulus) + (full : base ^ (2 ^ (n + 1)) % modulus = 1) + (half : base ^ (2 ^ n) % modulus ≠ 1) : 2 ^ (n + 1) ≤ modulus := by + let residues := List.ofFn fun i : Fin (2 ^ (n + 1)) => base ^ i.val % modulus + have distinct : residues.Nodup := by + apply List.pairwise_iff_getElem.mpr + intro i j hi hj lt same + simp only [residues, List.getElem_ofFn] at same + have hi' : i < 2 ^ (n + 1) := by simpa only [residues, List.length_ofFn] using hi + have hj' : j < 2 ^ (n + 1) := by simpa only [residues, List.length_ofFn] using hj + have equal := pow_mod_injective hmod full half hi' hj' same + omega + have subset : residues ⊆ List.range modulus := by + intro value member + obtain ⟨i, rfl⟩ := List.mem_ofFn.mp member + exact List.mem_range.mpr (Nat.mod_lt _ (by omega)) + have bound := distinct.length_le_of_subset subset + simpa only [residues, List.length_ofFn, List.length_range] using bound + +/-- A power-of-two order certificate forces every nontrivial divisor to +contain at least that many distinct residues. -/ +theorem two_power_divisor_bound {modulus base n : Nat} + (certificateFull : squareMod modulus base (n + 1) = 1) + (certificateHalf : Nat.gcd modulus (squareMod modulus base n - 1) = 1) + {d : Nat} (divides : d ∣ modulus) (nontrivial : 1 < d) : 2 ^ (n + 1) ≤ d := by + have full : base ^ (2 ^ (n + 1)) % d = 1 := by + have h := congrArg (· % d) certificateFull + rw [squareMod_eq, Nat.mod_mod_of_dvd _ divides, Nat.mod_eq_of_lt nontrivial] at h + exact h + have half : base ^ (2 ^ n) % d ≠ 1 := by + intro equal + have h : squareMod modulus base n % d = 1 := by + rw [squareMod_eq, Nat.mod_mod_of_dvd _ divides, equal] + have hd : d ∣ squareMod modulus base n - 1 := + Nat.dvd_of_mod_eq_zero (Nat.sub_mod_eq_zero_of_mod_eq + (h.trans (Nat.mod_eq_of_lt nontrivial).symm)) + have one := Nat.dvd_gcd divides hd + rw [certificateHalf] at one + have := Nat.eq_one_of_dvd_one one + omega + exact two_pow_le_modulus nontrivial full half + +theorem nontrivial_divisor_large {d : Nat} (divides : d ∣ gSize.toNat) + (nontrivial : 1 < d) : 2 ^ 32 ≤ d := by + apply two_power_divisor_bound (modulus := gSize.toNat) (base := 1753635133440165772) + (n := 31) squareMod_full ?_ divides nontrivial + rw [squareMod_half] + decide +kernel + +theorem goldilocks_divisors {d : Nat} (divides : d ∣ gSize.toNat) : + d = 1 ∨ d = gSize.toNat := by + obtain ⟨e, product⟩ := divides + by_cases hd : d = 1 + · exact Or.inl hd + · by_cases he : e = 1 + · exact Or.inr (by simpa only [he, Nat.mul_one] using product.symm) + · have positiveD : 0 < d := Nat.pos_of_dvd_of_pos ⟨e, product⟩ (by decide) + have dividesE : e ∣ gSize.toNat := ⟨d, product.trans (Nat.mul_comm _ _)⟩ + have positiveE : 0 < e := Nat.pos_of_dvd_of_pos dividesE (by decide) + have boundD := nontrivial_divisor_large ⟨e, product⟩ (by omega) + have boundE := nontrivial_divisor_large dividesE (by omega) + have impossible := Nat.mul_le_mul boundD boundE + rw [← product] at impossible + have bad : ¬(2 ^ 32 * 2 ^ 32 ≤ gSize.toNat) := by decide +kernel + exact False.elim (bad impossible) + +end Aiur.GoldilocksProof + +namespace Aiur + +/-- Primality stated explicitly as the nontriviality and divisor criterion. -/ +theorem gSize_prime : 1 < gSize.toNat ∧ + ∀ d : Nat, d ∣ gSize.toNat → d = 1 ∨ d = gSize.toNat := + ⟨by decide, fun _ => GoldilocksProof.goldilocks_divisors⟩ + +theorem G.n_eq_zero_iff (a : G) : a.n = 0 ↔ a = 0 := by + constructor + · intro equal + rw [← G.ofNat_n a, equal] + rfl + · intro equal; subst a; rfl + +theorem G.coprime_characteristic_of_ne_zero {a : G} (nonzero : a ≠ 0) : + Nat.Coprime gSize.toNat a.n := by + have positive : 0 < a.n := Nat.pos_of_ne_zero fun equal => nonzero ((G.n_eq_zero_iff a).mp equal) + have bounded : a.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp a.property + rcases GoldilocksProof.goldilocks_divisors (Nat.gcd_dvd_left gSize.toNat a.n) with one | whole + · exact one + · have small := Nat.gcd_le_right gSize.toNat positive + rw [whole] at small + omega + +theorem G.mul_eq_zero_iff (a b : G) : a * b = 0 ↔ a = 0 ∨ b = 0 := by + constructor + · intro equal + by_cases zero : a = 0 + · exact Or.inl zero + · apply Or.inr + have numeric := congrArg G.n equal + rw [G.n_mul] at numeric + have divides : gSize.toNat ∣ b.n := + (G.coprime_characteristic_of_ne_zero zero).dvd_of_dvd_mul_left + (Nat.dvd_of_mod_eq_zero numeric) + have bound : b.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp b.property + apply (G.n_eq_zero_iff b).mp + by_cases z : b.n = 0 + · exact z + · have large := Nat.le_of_dvd (Nat.pos_of_ne_zero z) divides + omega + · rintro (rfl | rfl) + · rw [G.mul_comm, G.mul_zero] + · exact G.mul_zero a + +theorem G.mul_eq_zero_of_left_ne_zero {a b : G} (nonzero : a ≠ 0) (zero : a * b = 0) : + b = 0 := (G.mul_eq_zero_iff a b).mp zero |>.resolve_left nonzero + +theorem G.boolean_of_constraint {value : G} (satisfied : value * (value - 1) = 0) : + value = 0 ∨ value = 1 := by + rcases (G.mul_eq_zero_iff _ _).mp satisfied with zero | one + · exact Or.inl zero + · exact Or.inr ((G.sub_eq_zero_iff value 1).mp one) + +theorem G.boolean_of_one_sub_constraint {value : G} (satisfied : value * (1 - value) = 0) : + value = 0 ∨ value = 1 := by + rcases (G.mul_eq_zero_iff _ _).mp satisfied with zero | one + · exact Or.inl zero + · exact Or.inr (((G.sub_eq_zero_iff 1 value).mp one).symm) + +theorem G.eqZero_of_constraints {input inverse output : G} + (annihilate : input * output = 0) + (complement : input * inverse + output - 1 = 0) : output = G.eqZero input := by + by_cases zero : input = 0 + · rw [zero, G.mul_comm (0 : G), G.mul_zero, G.zero_add] at complement + rw [G.eqZero, if_pos zero] + exact (G.sub_eq_zero_iff output 1).mp complement + · rw [G.eqZero, if_neg zero] + exact G.mul_eq_zero_of_left_ne_zero zero annihilate + +theorem G.ne_zero_of_inverse_constraint {input inverse : G} + (satisfied : input * inverse - 1 = 0) : input ≠ 0 := by + intro zero + rw [zero, G.mul_comm (0 : G), G.mul_zero] at satisfied + exact G.one_ne_zero ((G.sub_eq_zero_iff (0 : G) 1).mp satisfied).symm + +end Aiur diff --git a/Ix/Aiur/Proofs/Folding.lean b/Ix/Aiur/Proofs/Folding.lean new file mode 100644 index 000000000..569a907fe --- /dev/null +++ b/Ix/Aiur/Proofs/Folding.lean @@ -0,0 +1,202 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Folding +import Ix.Aiur.Proofs.Interpolation + +/-! A native row fold evaluates one global polynomial of reduced degree. +The same global coefficients apply at every child-domain query point. +-/ + +namespace Aiur.NativeAIR.Folding + +open Lean.Grind +open _root_.Aiur.NativeAIR.Quotient (horner horner_nil horner_cons) + +variable {R : Type} [CommRing R] + +theorem horner_split (point : R) (width : Nat) (coefficients : List R) : + horner point coefficients = horner point (coefficients.take width) + + point ^ width * horner point (coefficients.drop width) := by + have split := Quotient.horner_append point (coefficients.take width) (coefficients.drop width) + rw [List.take_append_drop, List.length_take] at split + by_cases enough : width ≤ coefficients.length + · simpa only [Nat.min_eq_left enough] using split + · have empty : coefficients.drop width = [] := List.drop_eq_nil_iff.mpr (by omega) + rw [empty, horner_nil, Semiring.mul_zero, Semiring.add_zero] at split ⊢ + exact split + +theorem rowCoefficients_length (arity : Domain.Subgroup) (point : R) (coefficients : List R) : + (rowCoefficients arity point coefficients).length ≤ Domain.size arity := by + induction coefficients using rowCoefficients.induct arity with + | case1 => rw [rowCoefficients, dif_pos rfl]; exact Nat.zero_le _ + | case2 coefficients nonempty ih => + rw [rowCoefficients, dif_neg nonempty, Polynomial.add_length, Polynomial.scale_length] + apply Nat.max_le.mpr + exact ⟨by simp only [List.length_take]; omega, ih⟩ + +theorem rowCoefficients_value (arity : Domain.Subgroup) (point root : R) (coefficients : List R) + (power : root ^ Domain.size arity = point) : + horner root (rowCoefficients arity point coefficients) = horner root coefficients := by + induction coefficients using rowCoefficients.induct arity with + | case1 => rw [rowCoefficients, dif_pos rfl] + | case2 coefficients nonempty ih => + rw [rowCoefficients, dif_neg nonempty, Polynomial.horner_add, Polynomial.horner_scale, ih] + exact (horner_split root (Domain.size arity) coefficients |>.trans (by rw [power])).symm + +theorem rowCoefficients_fold (arity : Domain.Subgroup) (point challenge : R) (coefficients : List R) : + horner challenge (rowCoefficients arity point coefficients) = + horner point (foldCoefficients arity challenge coefficients) := by + induction coefficients using rowCoefficients.induct arity with + | case1 => rw [rowCoefficients, dif_pos rfl, foldCoefficients, dif_pos rfl]; rfl + | case2 coefficients nonempty ih => + rw [rowCoefficients, dif_neg nonempty, foldCoefficients, dif_neg nonempty, + Polynomial.horner_add, Polynomial.horner_scale, horner_cons, ih] + +theorem foldCoefficients_degree (arity : Domain.Subgroup) (challenge : R) (degree : Nat) + (coefficients : List R) (bounded : coefficients.length ≤ Domain.size arity * degree) : + (foldCoefficients arity challenge coefficients).length ≤ degree := by + induction degree generalizing coefficients with + | zero => + have empty : coefficients = [] := by simpa only [Nat.mul_zero, Nat.le_zero, List.length_eq_zero_iff] using bounded + subst coefficients + rw [foldCoefficients, dif_pos rfl] + exact Nat.le_refl _ + | succ degree ih => + by_cases empty : coefficients = [] + · subst coefficients; rw [foldCoefficients, dif_pos rfl]; exact Nat.zero_le _ + · rw [foldCoefficients, dif_neg empty, List.length_cons] + apply Nat.succ_le_succ + apply ih + simp only [List.length_drop] + rw [Nat.mul_succ] at bounded + omega + +open ProofCodec (Extension) + +theorem foldRow_global (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (values coefficients : List Extension) + (shape : values.length = Domain.size arity) + (agrees : ∀ sample ∈ Interpolation.foldSamples parent arity index values, + horner sample.1 coefficients = sample.2) (challenge : Extension) : + Interpolation.foldRow parent arity index values challenge = + some (horner (Extension.ofBase (FriDomain.queryPoint child index)) + (foldCoefficients arity challenge coefficients)) := by + rw [← rowCoefficients_fold] + apply Interpolation.foldRow_evaluate parent child arity dimensions bounded values + (rowCoefficients arity (Extension.ofBase (FriDomain.queryPoint child index)) coefficients) + shape (rowCoefficients_length arity _ coefficients) + intro sample member + rw [rowCoefficients_value arity _ sample.1 coefficients, agrees sample member] + have power := Interpolation.foldSamples_powers parent child arity dimensions index values shape sample member + rwa [Interpolation.foldSamples_length parent arity index values shape] at power + +theorem foldRow_codeword (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (coefficients : List Extension) + (challenge : Extension) : + Interpolation.foldRow parent arity index + ((Polynomial.foldingNodes parent arity index).map (fun root => horner (Extension.ofBase root) coefficients)) + challenge = some (horner (Extension.ofBase (FriDomain.queryPoint child index)) + (foldCoefficients arity challenge coefficients)) := by + apply foldRow_global parent child arity dimensions bounded _ coefficients + · simp only [List.length_map, Polynomial.foldingNodes_length] + · intro sample member + unfold Interpolation.foldSamples at member + have mapped : + (Polynomial.foldingNodes parent arity index).map (fun root => horner (Extension.ofBase root) coefficients) = + ((Polynomial.foldingNodes parent arity index).map Extension.ofBase).map (fun root => horner root coefficients) := by + rw [List.map_map] + rfl + rw [mapped, ← List.map_prod_left_eq_zip] at member + obtain ⟨root, _, rfl⟩ := List.mem_map.mp member + rfl + +theorem foldRow_codeword_degree (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) (degree : Nat) + (coefficients : List Extension) (length : coefficients.length ≤ Domain.size arity * degree) + (challenge : Extension) : + ∃ folded : List Extension, folded.length ≤ degree ∧ + ∀ index, index < 2^(parent.val - arity.val) → + Interpolation.foldRow parent arity index + ((Polynomial.foldingNodes parent arity index).map (fun root => horner (Extension.ofBase root) coefficients)) + challenge = some (horner (Extension.ofBase (FriDomain.queryPoint child index)) folded) := by + exact ⟨foldCoefficients arity challenge coefficients, + foldCoefficients_degree arity challenge degree coefficients length, + fun _ bounded => foldRow_codeword parent child arity dimensions bounded coefficients challenge⟩ + +theorem values_of_agreement (parent arity : Domain.Subgroup) (index : Nat) + (values coefficients : List Extension) (shape : values.length = Domain.size arity) + (agrees : ∀ sample ∈ Interpolation.foldSamples parent arity index values, + horner sample.1 coefficients = sample.2) : + values = (Polynomial.foldingNodes parent arity index).map (fun root => horner (Extension.ofBase root) coefficients) := by + calc + values = (Interpolation.foldSamples parent arity index values).map Prod.snd := by + apply Eq.symm + apply List.map_snd_zip + simp only [List.length_map, Polynomial.foldingNodes_length, shape, Nat.le_refl] + _ = (Interpolation.foldSamples parent arity index values).map (fun sample => horner sample.1 coefficients) := + List.map_congr_left (fun sample member => (agrees sample member).symm) + _ = _ := by + simpa only [List.map_map, Function.comp_def] using + congrArg (List.map (fun root => horner root coefficients)) + (Interpolation.foldSamples_roots parent arity index values shape) + +theorem interpolant_values (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (values : List Extension) + (shape : values.length = Domain.size arity) : + values = (Polynomial.foldingNodes parent arity index).map (fun root => horner (Extension.ofBase root) + (Interpolation.coefficients (Interpolation.foldSamples parent arity index values) + (Extension.ofBase (Interpolation.foldScale parent arity index)))) := by + apply values_of_agreement parent arity index values _ shape + intro sample member + have atNode := Interpolation.foldRow_at_node parent child arity dimensions bounded values shape sample.1 sample.2 member + rw [Interpolation.foldRow_polynomial parent child arity dimensions bounded values shape] at atNode + exact Option.some.inj atNode + +theorem interpolants_different (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (left right : List Extension) + (leftShape : left.length = Domain.size arity) (rightShape : right.length = Domain.size arity) + (different : left ≠ right) : + ¬ Polynomial.IsZero (Polynomial.sub + (Interpolation.coefficients (Interpolation.foldSamples parent arity index left) + (Extension.ofBase (Interpolation.foldScale parent arity index))) + (Interpolation.coefficients (Interpolation.foldSamples parent arity index right) + (Extension.ofBase (Interpolation.foldScale parent arity index)))) := by + intro zero + apply different + conv => lhs; rw [interpolant_values parent child arity dimensions bounded left leftShape] + conv => rhs; rw [interpolant_values parent child arity dimensions bounded right rightShape] + apply List.map_congr_left + intro root _ + have equal := Polynomial.horner_zero (Extension.ofBase root) zero + rw [Polynomial.horner_sub] at equal + exact (LogUp.sub_zero_iff _ _).mp equal + +/-- A deterministic bound for two fixed distinct rows and distinct challenges. -/ +theorem foldRow_equal_count_le (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (left right challenges : List Extension) + (leftShape : left.length = Domain.size arity) (rightShape : right.length = Domain.size arity) + (different : left ≠ right) (unique : challenges.Nodup) : + (challenges.filter (fun challenge => Interpolation.foldRow parent arity index left challenge == + Interpolation.foldRow parent arity index right challenge)).length ≤ Domain.size arity - 1 := by + have bound := Polynomial.equal_count_le (fun a b => (Extension.mul_eq_zero_iff a b).mp) _ _ challenges + (interpolants_different parent child arity dimensions bounded left right leftShape rightShape different) unique + have leftBound := Interpolation.coefficients_length (Interpolation.foldSamples parent arity index left) + (Extension.ofBase (Interpolation.foldScale parent arity index)) + have rightBound := Interpolation.coefficients_length (Interpolation.foldSamples parent arity index right) + (Extension.ofBase (Interpolation.foldScale parent arity index)) + rw [Interpolation.foldSamples_length parent arity index left leftShape] at leftBound + rw [Interpolation.foldSamples_length parent arity index right rightShape] at rightBound + simp only [Interpolation.foldRow_polynomial parent child arity dimensions bounded left leftShape, + Interpolation.foldRow_polynomial parent child arity dimensions bounded right rightShape, + Option.some_beq_some] + omega + +end Aiur.NativeAIR.Folding diff --git a/Ix/Aiur/Proofs/FriDomain.lean b/Ix/Aiur/Proofs/FriDomain.lean new file mode 100644 index 000000000..049883c3f --- /dev/null +++ b/Ix/Aiur/Proofs/FriDomain.lean @@ -0,0 +1,286 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.FriDomain +import Ix.Aiur.Proofs.Domain + +/-! The bit-reversal permutation, nested two-adic generators, and the +field points used by FRI input openings, row folding and final evaluation. +-/ + +namespace Aiur.NativeAIR.FriDomain + +open Lean.Grind + +theorem reverseBits_bound (bits index : Nat) : reverseBits bits index < 2^bits := + (BitVec.ofNat bits index).reverse.isLt + +theorem reverseBits_zero (bits : Nat) : reverseBits bits 0 = 0 := by + unfold reverseBits + rw [show BitVec.ofNat bits 0 = 0#bits from rfl, + (BitVec.reverse_eq_zero_iff).mpr rfl] + rfl + +theorem reverseBits_zero_width (index : Nat) : reverseBits 0 index = 0 := by + have := reverseBits_bound 0 index + simp only [Nat.pow_zero] at this + omega + +theorem reverseBits_mod (bits index : Nat) : + reverseBits bits (index % 2^bits) = reverseBits bits index := by + unfold reverseBits + congr 2 + apply BitVec.eq_of_toNat_eq + simp + +theorem reverseBits_involution (bits index : Nat) : + reverseBits bits (reverseBits bits index) = index % 2^bits := by + simp only [reverseBits, BitVec.ofNat_toNat, BitVec.setWidth_eq, + BitVec.reverse_reverse_eq, BitVec.toNat_ofNat] + +theorem reverseBits_injective {bits left right : Nat} + (leftBound : left < 2^bits) (rightBound : right < 2^bits) + (equal : reverseBits bits left = reverseBits bits right) : left = right := by + have same := congrArg (reverseBits bits) equal + simpa only [reverseBits_involution, Nat.mod_eq_of_lt leftBound, + Nat.mod_eq_of_lt rightBound] using same + +theorem reverseBits_surjective {bits index : Nat} (bounded : index < 2^bits) : + ∃ original < 2^bits, reverseBits bits original = index := + ⟨reverseBits bits index, reverseBits_bound _ _, + (reverseBits_involution _ _).trans (Nat.mod_eq_of_lt bounded)⟩ + +theorem index_split_bound {low high index : Nat} (bounded : index < 2^(high + low)) : + index / 2^low < 2^high := by + rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] + simpa only [Nat.pow_add] using bounded + +theorem reverseBits_split {high low index : Nat} (bounded : index < 2^(high + low)) : + reverseBits (high + low) index = + reverseBits low (index % 2^low) * 2^high + reverseBits high (index / 2^low) := by + have decomposition : BitVec.ofNat (high + low) index = + BitVec.ofNat high (index / 2^low) ++ BitVec.ofNat low index := by + apply BitVec.eq_of_toNat_eq + simp only [BitVec.toNat_ofNat, Nat.mod_eq_of_lt bounded, BitVec.toNat_append, + Nat.mod_eq_of_lt (index_split_bound bounded)] + rw [← Nat.shiftLeft_add_eq_or_of_lt (Nat.mod_lt _ (Nat.two_pow_pos _)), Nat.shiftLeft_eq] + have := Nat.mod_add_div index (2^low) + rw [Nat.mul_comm] at this + omega + unfold reverseBits + rw [decomposition, BitVec.reverse_append, BitVec.toNat_cast, BitVec.toNat_append] + rw [show BitVec.ofNat low (index % 2^low) = BitVec.ofNat low index by + apply BitVec.eq_of_toNat_eq; simp] + rw [← Nat.shiftLeft_add_eq_or_of_lt (BitVec.isLt _), Nat.shiftLeft_eq] + +theorem reverseBits_padding {bits index : Nat} (bounded : index < 2^bits) (extra : Nat) : + reverseBits (extra + bits) index = reverseBits bits index * 2^extra := by + have bound : index < 2^(extra + bits) := Nat.lt_of_lt_of_le bounded + (Nat.pow_le_pow_right (by decide) (by omega)) + rw [reverseBits_split bound, Nat.mod_eq_of_lt bounded, Nat.div_eq_of_lt bounded, + reverseBits_zero, Nat.add_zero] + +theorem wordReverse_eq {wordBits bits index : Nat} + (supported : bits ≤ wordBits) (bounded : index < 2^bits) : + wordReverse wordBits bits index = reverseBits bits index := by + by_cases empty : bits = 0 + · subst bits + have zero : index = 0 := by simpa using bounded + subst index + simp only [wordReverse, Nat.sub_zero, Nat.mod_self, + reverseBits_zero, BitVec.toNat_ushiftRight, Nat.shiftRight_zero] + exact reverseBits_zero wordBits + · have shiftBound : wordBits - bits < wordBits := by omega + unfold wordReverse + rw [Nat.mod_eq_of_lt shiftBound, BitVec.toNat_ushiftRight, Nat.shiftRight_eq_div_pow] + change reverseBits wordBits index / 2^(wordBits - bits) = reverseBits bits index + conv => lhs; arg 1; rw [← Nat.sub_add_cancel supported] + rw [reverseBits_padding bounded, Nat.mul_div_cancel _ (Nat.two_pow_pos _)] + +theorem generator_nested (parent child : Domain.Subgroup) (nested : child.val ≤ parent.val) : + Domain.generator parent ^ (2^(parent.val - child.val)) = Domain.generator child := by + have step : ∀ (extra bits : Nat) (bounded : bits + extra < 33), + Domain.generator ⟨bits + extra, bounded⟩ ^ (2^extra) = + Domain.generator ⟨bits, by omega⟩ := by + intro extra + induction extra with + | zero => intro bits bounded; simp only [Nat.add_zero, Nat.pow_zero, Semiring.pow_one] + | succ extra ih => + intro bits bounded + have square := Domain.generator_square_certificate ⟨bits + extra, by omega⟩ + have powerSquare : Domain.generator ⟨bits + (extra + 1), bounded⟩ ^ 2 = + Domain.generator ⟨bits + extra, by omega⟩ := by + simpa only [Semiring.pow_succ, Semiring.pow_zero, Semiring.one_mul, Nat.add_assoc] using square + rw [Nat.pow_succ, Nat.mul_comm, Domain.Algebra.power_mul, powerSquare] + exact ih bits (by omega) + have result := step (parent.val - child.val) child.val (by have := parent.isLt; omega) + simpa only [Nat.add_sub_of_le nested] using result + +theorem queryPoint_eq (domain : Domain.Subgroup) (index : Nat) : + queryPoint domain index = Domain.generator domain ^ reverseBits domain.val index := by + exact G.pow_eq _ _ (Nat.lt_trans (reverseBits_bound _ _) (Domain.size_lt_u64 domain)) + +theorem queryPoint_domain (domain : Domain.Subgroup) (index : Nat) : + queryPoint domain index = Domain.point domain ⟨reverseBits domain.val index, reverseBits_bound _ _⟩ := rfl + +theorem queryPoint_injective (domain : Domain.Subgroup) {left right : Nat} + (leftBound : left < Domain.size domain) (rightBound : right < Domain.size domain) + (equal : queryPoint domain left = queryPoint domain right) : left = right := by + have same := congrArg Fin.val (Domain.point_injective domain equal) + exact reverseBits_injective leftBound rightBound same + +theorem queryPoint_surjective (domain : Domain.Subgroup) (index : Fin (Domain.size domain)) : + ∃ query < Domain.size domain, queryPoint domain query = Domain.point domain index := by + obtain ⟨query, bound, reversed⟩ := reverseBits_surjective index.isLt + refine ⟨query, bound, ?_⟩ + rw [queryPoint_domain] + congr 1 + exact Fin.ext reversed + +theorem queryPoint_nonzero (domain : Domain.Subgroup) (index : Nat) : + queryPoint domain index ≠ 0 := Domain.point_nonzero _ _ + +theorem queryPoint_power (domain : Domain.Subgroup) (index : Nat) : + queryPoint domain index ^ Domain.size domain = 1 := Domain.point_power _ _ + +theorem queryPoint_zero (domain : Domain.Subgroup) : queryPoint domain 0 = 1 := by + rw [queryPoint_eq, reverseBits_zero, Semiring.pow_zero] + +theorem queryPoint_padding (parent child : Domain.Subgroup) (nested : child.val ≤ parent.val) + {index : Nat} (bounded : index < Domain.size child) : + queryPoint parent index = queryPoint child index := by + rw [queryPoint_eq, queryPoint_eq] + conv => lhs; arg 2; arg 1; rw [← Nat.sub_add_cancel nested] + rw [reverseBits_padding bounded, Nat.mul_comm, Domain.Algebra.power_mul, generator_nested _ _ nested] + +theorem index_join_bound {high low index slot : Nat} + (indexBound : index < 2^high) (slotBound : slot < 2^low) : + index * 2^low + slot < 2^(high + low) := by + have bound := Nat.mul_le_mul_right (2^low) (Nat.succ_le_of_lt indexBound) + rw [Nat.succ_mul, ← Nat.pow_add] at bound + omega + +theorem reverseBits_join {high low index slot : Nat} + (indexBound : index < 2^high) (slotBound : slot < 2^low) : + reverseBits (high + low) (index * 2^low + slot) = + reverseBits low slot * 2^high + reverseBits high index := by + rw [reverseBits_split (index_join_bound indexBound slotBound), Nat.mul_comm index, + Nat.mul_add_mod, Nat.mod_eq_of_lt slotBound, + Nat.mul_add_div (Nat.two_pow_pos _), + Nat.div_eq_of_lt slotBound, Nat.add_zero] + +theorem foldNode_eq (parent arity : Domain.Subgroup) (nested : arity.val ≤ parent.val) + {index slot : Nat} (indexBound : index < 2^(parent.val - arity.val)) + (slotBound : slot < Domain.size arity) : + foldNode parent arity index slot = queryPoint parent (index * Domain.size arity + slot) := by + have firstBound : reverseBits (parent.val - arity.val) index < 2^64 := + Nat.lt_of_lt_of_le (reverseBits_bound _ _) + (Nat.pow_le_pow_right (by decide) (by have := parent.isLt; omega)) + rw [foldNode, G.pow_eq _ _ firstBound, + G.pow_eq _ _ (Nat.lt_trans (reverseBits_bound _ _) (Domain.size_lt_u64 arity)), queryPoint_eq] + change _ = Domain.generator parent ^ + reverseBits parent.val (index * 2^arity.val + slot) + conv => rhs; arg 2; arg 1; rw [← Nat.sub_add_cancel nested] + rw [reverseBits_join indexBound slotBound, Semiring.pow_add, + Nat.mul_comm, Domain.Algebra.power_mul, generator_nested _ _ nested] + exact G.mul_comm _ _ + +theorem foldNode_injective (parent arity : Domain.Subgroup) (nested : arity.val ≤ parent.val) + {index left right : Nat} (indexBound : index < 2^(parent.val - arity.val)) + (leftBound : left < Domain.size arity) (rightBound : right < Domain.size arity) + (equal : foldNode parent arity index left = foldNode parent arity index right) : left = right := by + rw [foldNode_eq _ _ nested indexBound leftBound, + foldNode_eq _ _ nested indexBound rightBound] at equal + have boundLeft := index_join_bound indexBound leftBound + have boundRight := index_join_bound indexBound rightBound + rw [Nat.sub_add_cancel nested] at boundLeft boundRight + have same := queryPoint_injective parent boundLeft boundRight equal + omega + +theorem foldNode_nonzero (parent arity : Domain.Subgroup) (nested : arity.val ≤ parent.val) + {index slot : Nat} (indexBound : index < 2^(parent.val - arity.val)) + (slotBound : slot < Domain.size arity) : foldNode parent arity index slot ≠ 0 := by + rw [foldNode_eq _ _ nested indexBound slotBound] + exact queryPoint_nonzero _ _ + +theorem foldNode_power (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) (index slot : Nat) : + foldNode parent arity index slot ^ Domain.size arity = queryPoint child index := by + have nested : child.val ≤ parent.val := by omega + have height : parent.val - arity.val = child.val := by omega + have power : 2^(parent.val - child.val) = Domain.size arity := by + unfold Domain.size + congr 1 + omega + unfold foldNode + rw [height, G.pow_eq _ _ (Nat.lt_trans (reverseBits_bound _ _) (Domain.size_lt_u64 child)), + G.pow_eq _ _ (Nat.lt_trans (reverseBits_bound _ _) (Domain.size_lt_u64 arity)), + CommSemiring.mul_pow] + have right : (Domain.generator arity ^ reverseBits arity.val slot) ^ Domain.size arity = 1 := by + rw [← Domain.Algebra.power_mul, Nat.mul_comm, Domain.Algebra.power_mul, + Domain.generator_power, Semiring.one_pow] + rw [right, Semiring.mul_one, ← Domain.Algebra.power_mul, Nat.mul_comm, + Domain.Algebra.power_mul, ← power, generator_nested _ _ nested, queryPoint_eq] + +theorem queryPoint_reduce (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < Domain.size parent) : + queryPoint parent index ^ Domain.size arity = + queryPoint child (index / Domain.size arity) := by + have nested : arity.val ≤ parent.val := by omega + have bound : index / Domain.size arity < 2^(parent.val - arity.val) := by + apply index_split_bound + simpa only [Nat.sub_add_cancel nested, Domain.size] using bounded + have reconstruct : index / Domain.size arity * Domain.size arity + index % Domain.size arity = index := by + have := Nat.mod_add_div index (Domain.size arity) + rw [Nat.mul_comm] at this + omega + have row := foldNode_eq parent arity nested bound (Nat.mod_lt index (Domain.size_positive arity)) + rw [reconstruct] at row + rw [← row, foldNode_power _ _ _ dimensions] + +theorem inputPoint_nonzero (domain : Domain.Subgroup) (index : Nat) : + inputPoint domain index ≠ 0 := by + intro zero + exact ((G.mul_eq_zero_iff _ _).mp zero).elim (by decide) (queryPoint_nonzero _ _) + +theorem inputPoint_injective (domain : Domain.Subgroup) {left right : Nat} + (leftBound : left < Domain.size domain) (rightBound : right < Domain.size domain) + (equal : inputPoint domain left = inputPoint domain right) : left = right := by + apply queryPoint_injective domain leftBound rightBound + unfold inputPoint at equal + have zero : (7 : G) * (queryPoint domain left - queryPoint domain right) = 0 := by grind + exact (G.sub_eq_zero_iff _ _).mp (((G.mul_eq_zero_iff _ _).mp zero).resolve_left (by decide)) + +theorem inputPoint_power (domain : Domain.Subgroup) (index : Nat) : + inputPoint domain index ^ Domain.size domain = (7 : G) ^ Domain.size domain := by + rw [inputPoint, CommSemiring.mul_pow, queryPoint_power, Semiring.mul_one] + +theorem coset_shift_certificate : G.pow 7 (2^32) ≠ 1 := by decide +kernel + +theorem coset_shift_not_root (domain : Domain.Subgroup) : (7 : G) ^ Domain.size domain ≠ 1 := by + intro root + have power := congrArg (fun value : G => value ^ (2^(32 - domain.val))) root + rw [← Domain.Algebra.power_mul, Domain.size, ← Nat.pow_add, + Nat.add_sub_of_le (by have := domain.isLt; omega), Semiring.one_pow, + ← G.pow_eq _ _ (by decide)] at power + exact coset_shift_certificate power + +theorem inputPoint_not_root (domain : Domain.Subgroup) (index : Nat) : + inputPoint domain index ^ Domain.size domain ≠ 1 := by + rw [inputPoint_power] + exact coset_shift_not_root domain + +theorem inputPoint_trace_disjoint (query trace : Domain.Subgroup) + (nested : trace.val ≤ query.val) (index : Nat) (row : Fin (Domain.size trace)) : + inputPoint query index ≠ Domain.point trace row := by + intro equal + apply inputPoint_not_root query index + rw [equal] + have sizes : Domain.size query = Domain.size trace * 2^(query.val - trace.val) := by + simp only [Domain.size, ← Nat.pow_add, Nat.add_sub_of_le nested] + rw [sizes, Domain.Algebra.power_mul, Domain.point_power, Semiring.one_pow] + +end Aiur.NativeAIR.FriDomain diff --git a/Ix/Aiur/Proofs/FriQuery.lean b/Ix/Aiur/Proofs/FriQuery.lean new file mode 100644 index 000000000..da8c59393 --- /dev/null +++ b/Ix/Aiur/Proofs/FriQuery.lean @@ -0,0 +1,355 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.FriQuery +import Ix.Aiur.Proofs.Folding + +/-! Accepted query steps preserve sibling order and the carried value, +evaluate the row interpolant and implement global polynomial folding. +Complete chains consume descending input heights and reach the exact final +index and polynomial value. The captured rows still require authentication. +-/ + +namespace Aiur.NativeAIR.FriQuery + +open ProofCodec (Extension) +open _root_.Aiur.NativeAIR.Quotient (horner) + +theorem reconstruct_eq (arity : Domain.Subgroup) (index : Nat) (value : R) (siblings : List R) + (shape : siblings.length + 1 = Domain.size arity) : + reconstruct arity index value siblings = some (siblings.insertIdx (index % Domain.size arity) value) := by + simp only [reconstruct, shape, beq_self_eq_true, if_true] + +theorem reconstruct_success {arity : Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R} + (accepted : reconstruct arity index value siblings = some row) : + siblings.length + 1 = Domain.size arity ∧ row = siblings.insertIdx (index % Domain.size arity) value := by + unfold reconstruct at accepted + split at accepted + next shape => exact ⟨beq_iff_eq.mp shape, (Option.some.inj accepted).symm⟩ + next _ => cases accepted + +theorem reconstruct_length {arity : Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R} + (accepted : reconstruct arity index value siblings = some row) : row.length = Domain.size arity := by + obtain ⟨shape, rfl⟩ := reconstruct_success accepted + rw [List.length_insertIdx_of_le_length _ value, shape] + have bounded := Nat.mod_lt index (Domain.size_positive arity) + omega + +theorem reconstruct_self {arity : Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R} + (accepted : reconstruct arity index value siblings = some row) : + row[index % Domain.size arity]? = some value := by + obtain ⟨shape, rfl⟩ := reconstruct_success accepted + rw [List.getElem?_insertIdx_self, if_pos] + have bounded := Nat.mod_lt index (Domain.size_positive arity) + omega + +theorem reconstruct_siblings {arity : Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R} + (accepted : reconstruct arity index value siblings = some row) : + row.eraseIdx (index % Domain.size arity) = siblings := by + obtain ⟨_, rfl⟩ := reconstruct_success accepted + exact List.eraseIdx_insertIdx_self value + +theorem step_success {state : State} {round : Round} {openings : List (Nat × Extension)} {result : StepResult} + (accepted : step state round openings = some result) : + 0 < round.arity.val ∧ round.arity.val ≤ state.domain.val ∧ + ∃ child values folded, + Domain.ofLogSize (state.domain.val - round.arity.val) = some child ∧ + reconstruct round.arity state.index state.value round.siblings = some values ∧ + Interpolation.foldRow state.domain round.arity (state.index / Domain.size round.arity) values round.challenge = some folded ∧ + result = ⟨⟨child, state.index / Domain.size round.arity, + (roll child.val (round.challenge.power (Domain.size round.arity)) folded openings).1⟩, + (roll child.val (round.challenge.power (Domain.size round.arity)) folded openings).2, + ⟨child, state.index / Domain.size round.arity, values⟩⟩ := by + unfold step at accepted + split at accepted + next _ => cases accepted + next admitted => + simp only [Bool.or_eq_true, beq_iff_eq, decide_eq_true_eq] at admitted + cases childRead : Domain.ofLogSize (state.domain.val - round.arity.val) with + | none => simp only [childRead, bind, Option.bind_none] at accepted; cases accepted + | some child => + simp only [childRead, bind, Option.bind_some] at accepted + cases rowRead : reconstruct round.arity state.index state.value round.siblings with + | none => simp only [rowRead, Option.bind_none] at accepted; cases accepted + | some values => + simp only [rowRead, Option.bind_some] at accepted + cases foldRead : Interpolation.foldRow state.domain round.arity + (state.index / Domain.size round.arity) values round.challenge with + | none => simp only [foldRead, Option.bind_none] at accepted; cases accepted + | some folded => + simp only [foldRead, Option.bind_some, pure] at accepted + exact ⟨by omega, by omega, child, values, folded, rfl, rfl, foldRead, + (Option.some.inj accepted).symm⟩ + +theorem step_dimensions {state : State} {round : Round} {openings : List (Nat × Extension)} {result : StepResult} + (accepted : step state round openings = some result) : + 0 < round.arity.val ∧ state.domain.val = result.state.domain.val + round.arity.val ∧ + result.state.index = state.index / Domain.size round.arity ∧ + result.state.index < Domain.size result.state.domain ∧ + result.row.domain = result.state.domain ∧ result.row.index = result.state.index := by + obtain ⟨positive, nested, child, values, folded, childRead, _, foldRead, rfl⟩ := step_success accepted + have childValue := Domain.ofLogSize_some childRead + have bounded := (Interpolation.foldRow_success foldRead).2.1 + refine ⟨positive, by simp only; omega, rfl, ?_, rfl, rfl⟩ + simpa only [Domain.size, childValue] using bounded + +theorem step_row {state : State} {round : Round} {openings : List (Nat × Extension)} {result : StepResult} + (accepted : step state round openings = some result) : + result.row.values.length = Domain.size round.arity ∧ + result.row.values[state.index % Domain.size round.arity]? = some state.value ∧ + result.row.values.eraseIdx (state.index % Domain.size round.arity) = round.siblings := by + obtain ⟨_, _, _, _, _, _, rowRead, _, rfl⟩ := step_success accepted + exact ⟨reconstruct_length rowRead, reconstruct_self rowRead, reconstruct_siblings rowRead⟩ + +theorem step_index_bound {state : State} {round : Round} {openings : List (Nat × Extension)} {result : StepResult} + (accepted : step state round openings = some result) : state.index < Domain.size state.domain := by + obtain ⟨_, dimensions, index, bounded, _, _⟩ := step_dimensions accepted + rw [index, Nat.div_lt_iff_lt_mul (Domain.size_positive round.arity)] at bounded + simpa only [Domain.size, dimensions, Nat.pow_add] using bounded + +theorem step_self_sample {state : State} {round : Round} {openings : List (Nat × Extension)} {result : StepResult} + (accepted : step state round openings = some result) : + (Extension.ofBase (FriDomain.queryPoint state.domain state.index), state.value) ∈ + Interpolation.foldSamples state.domain round.arity result.state.index result.row.values := by + obtain ⟨_, dimensions, index, bounded, _, _⟩ := step_dimensions accepted + have nested : round.arity.val ≤ state.domain.val := by omega + have groupBound : result.state.index < 2^(state.domain.val - round.arity.val) := by + simpa only [Domain.size, dimensions, Nat.add_sub_cancel] using bounded + have slotBound := Nat.mod_lt state.index (Domain.size_positive round.arity) + have node := FriDomain.foldNode_eq state.domain round.arity nested groupBound slotBound + have joined : result.state.index * Domain.size round.arity + state.index % Domain.size round.arity = state.index := by + rw [index, Nat.mul_comm, Nat.div_add_mod] + rw [joined] at node + apply List.mem_of_getElem? (i := state.index % Domain.size round.arity) + apply List.getElem?_zip_eq_some.mpr + constructor + · simp only [Polynomial.foldingNodes, List.getElem?_map, List.getElem?_range slotBound, Option.map_some, node] + · exact (step_row accepted).2.1 + +theorem step_polynomial {state : State} {round : Round} {openings : List (Nat × Extension)} {result : StepResult} + (accepted : step state round openings = some result) : + ∃ candidate : List Extension, candidate.length ≤ Domain.size round.arity ∧ + horner (Extension.ofBase (FriDomain.queryPoint state.domain state.index)) candidate = state.value ∧ + (∀ sample ∈ Interpolation.foldSamples state.domain round.arity result.state.index result.row.values, + horner sample.1 candidate = sample.2) ∧ + (result.state.value, result.remaining) = roll result.state.domain.val + (round.challenge.power (Domain.size round.arity)) (horner round.challenge candidate) openings := by + have self := step_self_sample accepted + obtain ⟨_, _, child, values, folded, _, _, foldRead, output⟩ := step_success accepted + obtain ⟨_, _, _, candidate, degree, agrees, value⟩ := Interpolation.foldRow_success foldRead + refine ⟨candidate, degree, ?_, ?_, ?_⟩ + · exact agrees (Extension.ofBase (FriDomain.queryPoint state.domain state.index), state.value) + (by simpa only [output] using self) + · simpa only [output] using agrees + · simp only [output] + rw [← value] + +theorem step_global {state : State} {round : Round} {openings : List (Nat × Extension)} {result : StepResult} + (accepted : step state round openings = some result) (coefficients : List Extension) + (agrees : ∀ sample ∈ Interpolation.foldSamples state.domain round.arity result.state.index result.row.values, + horner sample.1 coefficients = sample.2) : + (result.state.value, result.remaining) = roll result.state.domain.val + (round.challenge.power (Domain.size round.arity)) + (horner (Extension.ofBase (FriDomain.queryPoint result.state.domain result.state.index)) + (Folding.foldCoefficients round.arity round.challenge coefficients)) openings := by + obtain ⟨_, nested, child, values, folded, childRead, rowRead, foldRead, rfl⟩ := step_success accepted + have dimensions : state.domain.val = child.val + round.arity.val := by + have := Domain.ofLogSize_some childRead + omega + have bounded := (Interpolation.foldRow_success foldRead).2.1 + rw [Folding.foldRow_global state.domain child round.arity dimensions bounded values coefficients + (reconstruct_length rowRead) agrees] at foldRead + rw [Option.some.inj foldRead] + +theorem roll_length (height : Nat) (factor value : Extension) (openings : List (Nat × Extension)) : + (roll height factor value openings).2.length ≤ openings.length := by + cases openings with + | nil => exact Nat.le_refl _ + | cons entry rest => + rcases entry with ⟨nextHeight, next⟩ + change (if nextHeight == height then (value + factor * next, rest) + else (value, (nextHeight, next) :: rest)).2.length ≤ rest.length + 1 + split <;> simp only [List.length_cons] <;> omega + +theorem roll_empty (height : Nat) (factor value : Extension) : roll height factor value [] = (value, []) := rfl + +theorem roll_matching (height : Nat) (factor value next : Extension) (rest : List (Nat × Extension)) : + roll height factor value ((height, next) :: rest) = (value + factor * next, rest) := by + simp only [roll, beq_self_eq_true, if_true] + +theorem roll_other (height nextHeight : Nat) (factor value next : Extension) (rest : List (Nat × Extension)) + (different : nextHeight ≠ height) : + roll height factor value ((nextHeight, next) :: rest) = (value, (nextHeight, next) :: rest) := by + simp only [roll, beq_iff_eq, if_neg different] + +theorem roll_count (height : Nat) (factor value : Extension) (openings : List (Nat × Extension)) : + openings.length ≤ (roll height factor value openings).2.length + 1 := by + cases openings with + | nil => exact Nat.zero_le _ + | cons entry rest => + rcases entry with ⟨nextHeight, next⟩ + by_cases same : nextHeight = height + · subst nextHeight + rw [roll_matching] + exact Nat.le_refl _ + · rw [roll_other height nextHeight factor value next rest same] + exact Nat.le_succ _ + +theorem roll_order (height : Nat) (factor value : Extension) (openings : List (Nat × Extension)) + (unique : (roll height factor value openings).2.Pairwise (fun left right => right.1 < left.1)) + (bounded : ∀ entry ∈ (roll height factor value openings).2, entry.1 < height) : + openings.Pairwise (fun left right => right.1 < left.1) ∧ + ∀ entry ∈ openings, entry.1 ≤ height := by + cases openings with + | nil => exact ⟨List.Pairwise.nil, fun _ member => by cases member⟩ + | cons entry rest => + rcases entry with ⟨nextHeight, next⟩ + by_cases same : nextHeight = height + · subst nextHeight + rw [roll_matching] at unique bounded + refine ⟨List.pairwise_cons.mpr ⟨bounded, unique⟩, ?_⟩ + intro entry member + rcases List.mem_cons.mp member with rfl | later + · exact Nat.le_refl _ + · exact Nat.le_of_lt (bounded entry later) + · rw [roll_other height nextHeight factor value next rest same] at unique bounded + exact ⟨unique, fun entry member => Nat.le_of_lt (bounded entry member)⟩ + +theorem walk_nil_success {final : Domain.Subgroup} {state : State} + {openings : List (Nat × Extension)} {result : Result} + (accepted : walk final state openings [] = some result) : + state.domain = final ∧ openings = [] ∧ result = ⟨state, []⟩ := by + unfold walk at accepted + split at accepted + next shape => + obtain ⟨height, empty⟩ := (by simpa only [Bool.and_eq_true, beq_iff_eq, List.isEmpty_iff] using shape : + state.domain = final ∧ openings = []) + exact ⟨height, empty, (Option.some.inj accepted).symm⟩ + next _ => cases accepted + +theorem walk_cons_success {final : Domain.Subgroup} {state : State} + {openings : List (Nat × Extension)} {round : Round} {rest : List Round} {result : Result} + (accepted : walk final state openings (round :: rest) = some result) : + ∃ head tail, step state round openings = some head ∧ + walk final head.state head.remaining rest = some tail ∧ result = ⟨tail.state, head.row :: tail.rows⟩ := by + rw [walk] at accepted + cases headRead : step state round openings with + | none => simp only [headRead, bind, Option.bind_none] at accepted; cases accepted + | some head => + simp only [headRead, bind, Option.bind_some] at accepted + cases tailRead : walk final head.state head.remaining rest with + | none => simp only [tailRead, Option.bind_none] at accepted; cases accepted + | some tail => + simp only [tailRead, Option.bind_some, pure] at accepted + exact ⟨head, tail, rfl, tailRead, (Option.some.inj accepted).symm⟩ + +theorem walk_summary {final : Domain.Subgroup} {state : State} + {openings : List (Nat × Extension)} {rounds : List Round} {result : Result} + (accepted : walk final state openings rounds = some result) : + result.state.domain = final ∧ result.rows.length = rounds.length ∧ + state.domain.val = final.val + (rounds.map (fun round => round.arity.val)).sum ∧ + result.state.index = state.index / 2^((rounds.map (fun round => round.arity.val)).sum) := by + induction rounds generalizing state openings result with + | nil => + obtain ⟨height, _, rfl⟩ := walk_nil_success accepted + refine ⟨height, rfl, ?_, ?_⟩ + · simpa only [List.map_nil, List.sum_nil, Nat.add_zero] using congrArg Fin.val height + · simp only [List.map_nil, List.sum_nil, Nat.pow_zero, Nat.div_one] + | cons round rest ih => + obtain ⟨head, tail, stepRead, tailRead, rfl⟩ := walk_cons_success accepted + obtain ⟨height, length, dimensions, index⟩ := ih tailRead + obtain ⟨_, headDimensions, headIndex, _, _, _⟩ := step_dimensions stepRead + simp only [List.map_cons, List.sum_cons, List.length_cons] + refine ⟨height, by simp only [length], by omega, ?_⟩ + rw [index, headIndex, Nat.div_div_eq_div_mul, Domain.size, ← Nat.pow_add] + +theorem walk_openings {final : Domain.Subgroup} {state : State} + {openings : List (Nat × Extension)} {rounds : List Round} {result : Result} + (accepted : walk final state openings rounds = some result) : + openings.Pairwise (fun left right => right.1 < left.1) ∧ + (∀ entry ∈ openings, entry.1 < state.domain.val) ∧ openings.length ≤ rounds.length := by + induction rounds generalizing state openings result with + | nil => + obtain ⟨_, rfl, _⟩ := walk_nil_success accepted + exact ⟨List.Pairwise.nil, (fun _ member => by cases member), Nat.le_refl _⟩ + | cons round rest ih => + obtain ⟨head, tail, stepRead, tailRead, _⟩ := walk_cons_success accepted + obtain ⟨positive, nested, child, values, folded, childRead, _, _, rfl⟩ := step_success stepRead + obtain ⟨unique, bounded, count⟩ := ih tailRead + change (roll child.val (round.challenge.power (Domain.size round.arity)) folded openings).2.length ≤ rest.length at count + obtain ⟨oldUnique, oldBounded⟩ := roll_order child.val + (round.challenge.power (Domain.size round.arity)) folded openings unique bounded + have childValue := Domain.ofLogSize_some childRead + have childLess : child.val < state.domain.val := by omega + have removed := roll_count child.val (round.challenge.power (Domain.size round.arity)) folded openings + exact ⟨oldUnique, fun entry member => Nat.lt_of_le_of_lt (oldBounded entry member) childLess, + by simp only [List.length_cons]; omega⟩ + +theorem run_success {initial final : Domain.Subgroup} {index : Nat} + {openings : List (Nat × Extension)} {rounds : List Round} {result : Result} + (accepted : run initial final index openings rounds = some result) : + index < Domain.size initial ∧ ∃ value rest, openings = (initial.val, value) :: rest ∧ + walk final ⟨initial, index, value⟩ rest rounds = some result := by + unfold run at accepted + split at accepted + next _ => cases accepted + next admitted => + refine ⟨by omega, ?_⟩ + cases openings with + | nil => cases accepted + | cons entry rest => + rcases entry with ⟨height, value⟩ + change (if height == initial.val then walk final ⟨initial, index, value⟩ rest rounds else none) = some result at accepted + split at accepted + next matching => + have same : height = initial.val := beq_iff_eq.mp matching + subst height + exact ⟨value, rest, rfl, accepted⟩ + next _ => cases accepted + +theorem run_summary {initial final : Domain.Subgroup} {index : Nat} + {openings : List (Nat × Extension)} {rounds : List Round} {result : Result} + (accepted : run initial final index openings rounds = some result) : + index < Domain.size initial ∧ result.state.domain = final ∧ + result.rows.length = rounds.length ∧ + initial.val = final.val + (rounds.map (fun round => round.arity.val)).sum ∧ + result.state.index = index / 2^((rounds.map (fun round => round.arity.val)).sum) ∧ + result.state.index < Domain.size final ∧ + openings.Pairwise (fun left right => right.1 < left.1) ∧ openings.length ≤ rounds.length + 1 := by + obtain ⟨indexBound, value, rest, rfl, walked⟩ := run_success accepted + obtain ⟨height, length, dimensions, finalIndex⟩ := walk_summary walked + change initial.val = final.val + (rounds.map (fun round => round.arity.val)).sum at dimensions + obtain ⟨unique, bounded, count⟩ := walk_openings walked + refine ⟨indexBound, height, length, dimensions, finalIndex, ?_, + List.pairwise_cons.mpr ⟨bounded, unique⟩, by simp only [List.length_cons]; omega⟩ + rw [finalIndex, Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] + simpa only [Domain.size, dimensions, Nat.pow_add] using indexBound + +theorem check_success {initial final : Domain.Subgroup} {index : Nat} + {openings : List (Nat × Extension)} {rounds : List Round} {finalPolynomial : List Extension} {result : Result} + (accepted : check initial final index openings rounds finalPolynomial = some result) : + run initial final index openings rounds = some result ∧ + horner (Extension.ofBase (FriDomain.queryPoint initial result.state.index)) finalPolynomial = result.state.value := by + unfold check at accepted + cases runRead : run initial final index openings rounds with + | none => simp only [runRead, bind, Option.bind_none] at accepted; cases accepted + | some output => + simp only [runRead, bind, Option.bind_some] at accepted + split at accepted + next matching => + cases accepted + exact ⟨rfl, beq_iff_eq.mp matching⟩ + next _ => cases accepted + +theorem check_final_polynomial {initial final : Domain.Subgroup} {index : Nat} + {openings : List (Nat × Extension)} {rounds : List Round} {finalPolynomial : List Extension} {result : Result} + (accepted : check initial final index openings rounds finalPolynomial = some result) : + horner (Extension.ofBase (FriDomain.queryPoint final result.state.index)) finalPolynomial = result.state.value := by + obtain ⟨runRead, equal⟩ := check_success accepted + obtain ⟨_, _, _, dimensions, _, bounded, _, _⟩ := run_summary runRead + rw [FriDomain.queryPoint_padding initial final (by omega) bounded] at equal + exact equal + +end Aiur.NativeAIR.FriQuery diff --git a/Ix/Aiur/Proofs/FrontendExpressions.lean b/Ix/Aiur/Proofs/FrontendExpressions.lean new file mode 100644 index 000000000..f51e7fe00 --- /dev/null +++ b/Ix/Aiur/Proofs/FrontendExpressions.lean @@ -0,0 +1,647 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ExpressionGraph +import Ix.Aiur.Proofs.OperationRows + +/-! +Smart expression construction, evaluated metadata and scalar operation emission. +The operators mirror the pinned native frontend's folds. Evaluation is preserved +for working operations satisfying the stated algebra laws, which are proved for +Goldilocks. A preserved check excluding negated constant nodes makes syntactic +constant flags precise, independently of conservative degree bookkeeping. + +The addition, subtraction, multiplication and equality-test emitters reflect +the valued operation model, including allocated columns and every equation. Native comparison +checks actual expression trees and operation emission. Rust execution refinement, +remaining operation forms, graph compilation and cryptographic acceptance +are separate obligations. +-/ + +namespace Aiur + +theorem G.sub_zero (value : G) : value - 0 = value := by + apply G.ext_n + simp only [G.n_sub, show (0 : G).n = 0 from rfl, Nat.sub_zero, Nat.add_mod_right] + exact Nat.mod_eq_of_lt (UInt64.lt_iff_toNat_lt.mp value.property) + +theorem G.neg_neg (value : G) : 0 - (0 - value) = value := by + have bound := UInt64.lt_iff_toNat_lt.mp value.property + apply G.ext_n + simp only [G.n_sub, show (0 : G).n = 0 from rfl, Nat.zero_add] + change value.n < gSize.toNat at bound + by_cases zero : value.n = 0 + · simp only [zero, Nat.sub_zero, Nat.mod_self] + · have inside : gSize.toNat - value.n < gSize.toNat := by omega + rw [Nat.mod_eq_of_lt inside] + have cancel : gSize.toNat - (gSize.toNat - value.n) = value.n := by omega + rw [cancel, Nat.mod_eq_of_lt bound] + +namespace NativeAIR + +def Expr.isConstant : Expr → Bool + | .konst _ => true + | _ => false + +def Expr.constantValue : Expr → Option G + | .konst value => some value + | _ => none + +def Expr.frontNeg : Expr → Expr + | .konst value => .konst (0 - value) + | .neg value => value + | value => .neg value + +def Expr.frontAdd (left right : Expr) : Expr := + match left.constantValue, right.constantValue with + | some a, some b => .konst (a + b) + | some a, none => if a == 0 then right else .add left right + | none, some b => if b == 0 then left else .add left right + | none, none => .add left right + +def Expr.frontSub (left right : Expr) : Expr := + match left.constantValue, right.constantValue with + | some a, some b => .konst (a - b) + | none, some b => if b == 0 then left else .sub left right + | some a, none => if a == 0 then right.frontNeg else .sub left right + | none, none => .sub left right + +def Expr.frontMul (left right : Expr) : Expr := + match left.constantValue, right.constantValue with + | some a, some b => .konst (a * b) + | some a, none => if a == 0 then .konst 0 else if a == 1 then right else .mul left right + | none, some b => if b == 0 then .konst 0 else if b == 1 then left else .mul left right + | none, none => .mul left right + +structure EvalLaws (ops : EvalOps W) : Prop where + konst_add : ∀ a b, ops.konst (a + b) = ops.add (ops.konst a) (ops.konst b) + konst_sub : ∀ a b, ops.konst (a - b) = ops.sub (ops.konst a) (ops.konst b) + konst_mul : ∀ a b, ops.konst (a * b) = ops.mul (ops.konst a) (ops.konst b) + konst_neg : ∀ a, ops.konst (0 - a) = ops.neg (ops.konst a) + add_zero : ∀ a, ops.add a (ops.konst 0) = a + zero_add : ∀ a, ops.add (ops.konst 0) a = a + sub_zero : ∀ a, ops.sub a (ops.konst 0) = a + zero_sub : ∀ a, ops.sub (ops.konst 0) a = ops.neg a + mul_zero : ∀ a, ops.mul a (ops.konst 0) = ops.konst 0 + zero_mul : ∀ a, ops.mul (ops.konst 0) a = ops.konst 0 + mul_one : ∀ a, ops.mul a (ops.konst 1) = a + one_mul : ∀ a, ops.mul (ops.konst 1) a = a + neg_neg : ∀ a, ops.neg (ops.neg a) = a + +def Expr.noConstantNegs : Expr → Bool + | .neg child => !child.isConstant && child.noConstantNegs + | .add a b | .sub a b | .mul a b => a.noConstantNegs && b.noConstantNegs + | _ => true + +theorem Expr.isConstant_eq (expr : Expr) : expr.isConstant = expr.constantValue.isSome := by + cases expr <;> rfl + +theorem Expr.frontNeg_noConstantNegs {expr : Expr} (valid : expr.noConstantNegs = true) : + expr.frontNeg.noConstantNegs = true := by + cases expr <;> simp_all only [Expr.noConstantNegs, Expr.frontNeg, Expr.isConstant, + Bool.not_false, Bool.true_and, Bool.and_eq_true] + +theorem Expr.frontNeg_isConstant {expr : Expr} (valid : expr.noConstantNegs = true) : + expr.frontNeg.isConstant = expr.isConstant := by + cases expr <;> try rfl + case neg child => + simp only [Expr.noConstantNegs, Bool.and_eq_true, Bool.not_eq_true'] at valid + exact valid.1 + +theorem Expr.frontAdd_isConstant (left right : Expr) : + (left.frontAdd right).isConstant = (left.isConstant && right.isConstant) := by + have leftC := left.isConstant_eq + have rightC := right.isConstant_eq + cases hl : left.constantValue <;> cases hr : right.constantValue + all_goals simp only [hl, hr, Option.isSome_none, Option.isSome_some] at leftC rightC + · rw [leftC, rightC]; simp only [Expr.frontAdd, hl, hr]; rfl + · rename_i c + by_cases zero : c = 0 + · simp only [Expr.frontAdd, hl, hr, beq_iff_eq, if_pos zero, leftC, rightC, Bool.false_and] + · rw [leftC, rightC]; simp only [Expr.frontAdd, hl, hr, beq_iff_eq, if_neg zero]; rfl + · rename_i c + by_cases zero : c = 0 + · simp only [Expr.frontAdd, hl, hr, beq_iff_eq, if_pos zero, leftC, rightC, Bool.true_and] + · rw [leftC, rightC]; simp only [Expr.frontAdd, hl, hr, beq_iff_eq, if_neg zero]; rfl + · rw [leftC, rightC]; simp only [Expr.frontAdd, hl, hr]; rfl + +theorem Expr.frontSub_isConstant (left right : Expr) (valid : right.noConstantNegs = true) : + (left.frontSub right).isConstant = (left.isConstant && right.isConstant) := by + have leftC := left.isConstant_eq + have rightC := right.isConstant_eq + cases hl : left.constantValue <;> cases hr : right.constantValue + all_goals simp only [hl, hr, Option.isSome_none, Option.isSome_some] at leftC rightC + · rw [leftC, rightC]; simp only [Expr.frontSub, hl, hr]; rfl + + · rename_i c + by_cases zero : c = 0 + · simp only [Expr.frontSub, hl, hr, beq_iff_eq, if_pos zero, leftC, rightC, Bool.false_and] + · rw [leftC, rightC]; simp only [Expr.frontSub, hl, hr, beq_iff_eq, if_neg zero]; rfl + · rename_i c + by_cases zero : c = 0 + · simp only [Expr.frontSub, hl, hr, beq_iff_eq, if_pos zero, Expr.frontNeg_isConstant valid, + leftC, rightC, Bool.true_and] + · rw [leftC, rightC]; simp only [Expr.frontSub, hl, hr, beq_iff_eq, if_neg zero]; rfl + · rw [leftC, rightC]; simp only [Expr.frontSub, hl, hr]; rfl + +theorem Expr.frontAdd_noConstantNegs {left right : Expr} + (leftValid : left.noConstantNegs = true) (rightValid : right.noConstantNegs = true) : + (left.frontAdd right).noConstantNegs = true := by + have raw : (Expr.add left right).noConstantNegs = true := by + simp only [Expr.noConstantNegs, leftValid, rightValid, Bool.true_and] + unfold Expr.frontAdd + cases hl : left.constantValue <;> cases hr : right.constantValue + · exact raw + · rename_i c + by_cases zero : c = 0 + · simp only [beq_iff_eq, if_pos zero]; exact leftValid + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rename_i c + by_cases zero : c = 0 + · simp only [beq_iff_eq, if_pos zero]; exact rightValid + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rfl + +theorem Expr.frontSub_noConstantNegs {left right : Expr} + (leftValid : left.noConstantNegs = true) (rightValid : right.noConstantNegs = true) : + (left.frontSub right).noConstantNegs = true := by + have raw : (Expr.sub left right).noConstantNegs = true := by + simp only [Expr.noConstantNegs, leftValid, rightValid, Bool.true_and] + unfold Expr.frontSub + cases hl : left.constantValue <;> cases hr : right.constantValue + · exact raw + · rename_i c + by_cases zero : c = 0 + · simp only [beq_iff_eq, if_pos zero]; exact leftValid + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rename_i c + by_cases zero : c = 0 + · simp only [beq_iff_eq, if_pos zero]; exact Expr.frontNeg_noConstantNegs rightValid + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rfl + +theorem Expr.frontMul_noConstantNegs {left right : Expr} + (leftValid : left.noConstantNegs = true) (rightValid : right.noConstantNegs = true) : + (left.frontMul right).noConstantNegs = true := by + have raw : (Expr.mul left right).noConstantNegs = true := by + simp only [Expr.noConstantNegs, leftValid, rightValid, Bool.true_and] + unfold Expr.frontMul + cases hl : left.constantValue <;> cases hr : right.constantValue + · exact raw + · rename_i c + by_cases zero : c = 0 + · simp only [beq_iff_eq, if_pos zero]; rfl + · by_cases one : c = 1 + · simp only [beq_iff_eq, if_neg zero, if_pos one]; exact leftValid + · simp only [beq_iff_eq, if_neg zero, if_neg one]; exact raw + · rename_i c + by_cases zero : c = 0 + · simp only [beq_iff_eq, if_pos zero]; rfl + · by_cases one : c = 1 + · simp only [beq_iff_eq, if_neg zero, if_pos one]; exact rightValid + · simp only [beq_iff_eq, if_neg zero, if_neg one]; exact raw + · rfl + +theorem Expr.frontNeg_eval {ops : EvalOps W} (laws : EvalLaws ops) (values : Values W) {expr : Expr} {value : W} + (evaluated : expr.eval ops values = some value) : + expr.frontNeg.eval ops values = some (ops.neg value) := by + have raw : (Expr.neg expr).eval ops values = some (ops.neg value) := by + change (expr.eval ops values).bind (fun c => some (ops.neg c)) = _ + rw [evaluated]; rfl + cases expr <;> try exact raw + case konst c => + change some (ops.konst c) = some value at evaluated + cases evaluated + exact congrArg some (laws.konst_neg c) + case neg expr => + change (expr.eval ops values).bind (fun c => some (ops.neg c)) = some value at evaluated + cases inner : expr.eval ops values with + | none => simp only [inner, Option.bind_none, reduceCtorEq] at evaluated + | some result => + simp only [inner, Option.bind_some, Option.some.injEq] at evaluated + subst value + simpa only [Expr.frontNeg, laws.neg_neg] using inner + +theorem Expr.eval_constantValue (ops : EvalOps W) (values : Values W) {expr : Expr} {value : W} {constant : G} + (evaluated : expr.eval ops values = some value) + (known : expr.constantValue = some constant) : ops.konst constant = value := by + cases expr <;> simp only [Expr.constantValue, reduceCtorEq] at known + case konst c => cases known; exact Option.some.inj evaluated + +theorem Expr.frontAdd_eval {ops : EvalOps W} (laws : EvalLaws ops) (values : Values W) {left right : Expr} {a b : W} + (leftEval : left.eval ops values = some a) + (rightEval : right.eval ops values = some b) : + (left.frontAdd right).eval ops values = some (ops.add a b) := by + have raw : (Expr.add left right).eval ops values = some (ops.add a b) := by + change (left.eval ops values).bind (fun x => + (right.eval ops values).bind (fun y => some (ops.add x y))) = _ + rw [leftEval, Option.bind_some, rightEval]; rfl + unfold Expr.frontAdd + cases hl : left.constantValue <;> cases hr : right.constantValue + · exact raw + · rename_i c + have equal := Expr.eval_constantValue ops values rightEval hr + subst b + by_cases zero : c = 0 + · simp only [beq_iff_eq, zero, laws.add_zero]; exact leftEval + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rename_i c + have equal := Expr.eval_constantValue ops values leftEval hl + subst a + by_cases zero : c = 0 + · simp only [beq_iff_eq, zero, laws.zero_add]; exact rightEval + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rename_i c d + have leftEq := Expr.eval_constantValue ops values leftEval hl + have rightEq := Expr.eval_constantValue ops values rightEval hr + subst a; subst b + exact congrArg some (laws.konst_add c d) + +theorem Expr.frontSub_eval {ops : EvalOps W} (laws : EvalLaws ops) (values : Values W) {left right : Expr} {a b : W} + (leftEval : left.eval ops values = some a) + (rightEval : right.eval ops values = some b) : + (left.frontSub right).eval ops values = some (ops.sub a b) := by + have raw : (Expr.sub left right).eval ops values = some (ops.sub a b) := by + change (left.eval ops values).bind (fun x => + (right.eval ops values).bind (fun y => some (ops.sub x y))) = _ + rw [leftEval, Option.bind_some, rightEval]; rfl + unfold Expr.frontSub + cases hl : left.constantValue <;> cases hr : right.constantValue + · exact raw + · rename_i c + have equal := Expr.eval_constantValue ops values rightEval hr + subst b + by_cases zero : c = 0 + · simp only [beq_iff_eq, zero, laws.sub_zero]; exact leftEval + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rename_i c + have equal := Expr.eval_constantValue ops values leftEval hl + subst a + by_cases zero : c = 0 + · simp only [beq_iff_eq, zero, laws.zero_sub]; exact Expr.frontNeg_eval laws values rightEval + · simp only [beq_iff_eq, if_neg zero]; exact raw + · rename_i c d + have leftEq := Expr.eval_constantValue ops values leftEval hl + have rightEq := Expr.eval_constantValue ops values rightEval hr + subst a; subst b + exact congrArg some (laws.konst_sub c d) + +theorem Expr.frontMul_eval {ops : EvalOps W} (laws : EvalLaws ops) (values : Values W) {left right : Expr} {a b : W} + (leftEval : left.eval ops values = some a) + (rightEval : right.eval ops values = some b) : + (left.frontMul right).eval ops values = some (ops.mul a b) := by + have raw : (Expr.mul left right).eval ops values = some (ops.mul a b) := by + change (left.eval ops values).bind (fun x => + (right.eval ops values).bind (fun y => some (ops.mul x y))) = _ + rw [leftEval, Option.bind_some, rightEval]; rfl + unfold Expr.frontMul + cases hl : left.constantValue <;> cases hr : right.constantValue + · exact raw + · rename_i c + have equal := Expr.eval_constantValue ops values rightEval hr + subst b + by_cases zero : c = 0 + · simp only [beq_iff_eq, zero, laws.mul_zero]; rfl + · by_cases one : c = 1 + · simp only [beq_iff_eq, one, laws.mul_one]; exact leftEval + · simp only [beq_iff_eq, if_neg zero, if_neg one]; exact raw + · rename_i c + have equal := Expr.eval_constantValue ops values leftEval hl + subst a + by_cases zero : c = 0 + · simp only [beq_iff_eq, zero, laws.zero_mul]; rfl + · by_cases one : c = 1 + · simp only [beq_iff_eq, one, laws.one_mul]; exact rightEval + · simp only [beq_iff_eq, if_neg zero, if_neg one]; exact raw + · rename_i c d + have leftEq := Expr.eval_constantValue ops values leftEval hl + have rightEq := Expr.eval_constantValue ops values rightEval hr + subst a; subst b + exact congrArg some (laws.konst_mul c d) + +theorem goldilocks_add_zero (a : G) : goldilocksOps.add a (goldilocksOps.konst 0) = a := G.add_zero a +theorem goldilocks_zero_add (a : G) : goldilocksOps.add (goldilocksOps.konst 0) a = a := G.zero_add a +theorem goldilocks_sub_zero (a : G) : goldilocksOps.sub a (goldilocksOps.konst 0) = a := G.sub_zero a +theorem goldilocks_zero_sub (a : G) : goldilocksOps.sub (goldilocksOps.konst 0) a = goldilocksOps.neg a := rfl +theorem goldilocks_mul_zero (a : G) : goldilocksOps.mul a (goldilocksOps.konst 0) = goldilocksOps.konst 0 := G.mul_zero a +theorem goldilocks_zero_mul (a : G) : goldilocksOps.mul (goldilocksOps.konst 0) a = goldilocksOps.konst 0 := + (G.mul_comm 0 a).trans (G.mul_zero a) +theorem goldilocks_mul_one (a : G) : goldilocksOps.mul a (goldilocksOps.konst 1) = a := G.mul_one a +theorem goldilocks_one_mul (a : G) : goldilocksOps.mul (goldilocksOps.konst 1) a = a := + (G.mul_comm 1 a).trans (G.mul_one a) +theorem goldilocks_neg_neg (a : G) : goldilocksOps.neg (goldilocksOps.neg a) = a := G.neg_neg a + +theorem goldilocks_konst_add (a b : G) : goldilocksOps.konst (a + b) = goldilocksOps.add (goldilocksOps.konst a) (goldilocksOps.konst b) := rfl +theorem goldilocks_konst (a : G) : goldilocksOps.konst a = a := rfl +theorem goldilocks_add (a b : G) : goldilocksOps.add a b = a + b := rfl +theorem goldilocks_sub (a b : G) : goldilocksOps.sub a b = a - b := rfl +theorem goldilocks_mul (a b : G) : goldilocksOps.mul a b = a * b := rfl +theorem goldilocks_konst_sub (a b : G) : goldilocksOps.konst (a - b) = goldilocksOps.sub (goldilocksOps.konst a) (goldilocksOps.konst b) := calc + _ = a - b := goldilocks_konst _ + _ = goldilocksOps.konst a - goldilocksOps.konst b := + (congrArg (fun x : G => x - b) (goldilocks_konst a).symm).trans + (congrArg (fun y : G => goldilocksOps.konst a - y) (goldilocks_konst b).symm) + _ = _ := (goldilocks_sub _ _).symm +theorem goldilocks_konst_mul (a b : G) : goldilocksOps.konst (a * b) = goldilocksOps.mul (goldilocksOps.konst a) (goldilocksOps.konst b) := rfl +theorem goldilocks_konst_neg (a : G) : goldilocksOps.konst (0 - a) = goldilocksOps.neg (goldilocksOps.konst a) := rfl + +theorem goldilocksLaws : EvalLaws goldilocksOps where + konst_add := goldilocks_konst_add + konst_sub := goldilocks_konst_sub + konst_mul := goldilocks_konst_mul + konst_neg := goldilocks_konst_neg + add_zero := goldilocks_add_zero + zero_add := goldilocks_zero_add + sub_zero := goldilocks_sub_zero + zero_sub := goldilocks_zero_sub + mul_zero := goldilocks_mul_zero + zero_mul := goldilocks_zero_mul + mul_one := goldilocks_mul_one + one_mul := goldilocks_one_mul + neg_neg := goldilocks_neg_neg + +theorem Expr.constantValue_eq_of_eval (values : Values G) {expr : Expr} {value constant : G} + (evaluated : expr.eval goldilocksOps values = some value) + (known : expr.constantValue = some constant) : constant = value := + (goldilocks_konst constant).symm.trans (Expr.eval_constantValue goldilocksOps values evaluated known) + +theorem Expr.frontMul_isConstant (values : Values G) {left right : Expr} {a b : G} + (leftEval : left.eval goldilocksOps values = some a) + (rightEval : right.eval goldilocksOps values = some b) : + (left.frontMul right).isConstant = + ((left.isConstant && right.isConstant) || (left.isConstant && a == 0) || + (right.isConstant && b == 0)) := by + have leftC := left.isConstant_eq + have rightC := right.isConstant_eq + cases hl : left.constantValue <;> cases hr : right.constantValue + all_goals simp only [hl, hr, Option.isSome_none, Option.isSome_some] at leftC rightC + all_goals rw [leftC, rightC] + · simp only [Expr.frontMul, hl, hr]; rfl + · rename_i c + have equal := Expr.constantValue_eq_of_eval values rightEval hr + subst b + by_cases zero : c = 0 + · simp [Expr.frontMul, hl, hr, zero, Expr.isConstant] + · have eqZero : (c == 0) = false := by simpa only [beq_eq_false_iff_ne] using zero + by_cases one : c = 1 + · simp only [Expr.frontMul, hl, hr, eqZero, Bool.false_eq_true, if_false, beq_iff_eq, + if_pos one, leftC, Bool.false_and, Bool.true_and, Bool.false_or] + · simp only [Expr.frontMul, hl, hr, eqZero, Bool.false_eq_true, if_false, beq_iff_eq, + if_neg one, Bool.false_and, Bool.true_and, Bool.false_or]; rfl + · rename_i c + have equal := Expr.constantValue_eq_of_eval values leftEval hl + subst a + by_cases zero : c = 0 + · simp [Expr.frontMul, hl, hr, zero, Expr.isConstant] + · have eqZero : (c == 0) = false := by simpa only [beq_eq_false_iff_ne] using zero + by_cases one : c = 1 + · simp only [Expr.frontMul, hl, hr, eqZero, Bool.false_eq_true, if_false, beq_iff_eq, + if_pos one, rightC, Bool.false_and, Bool.true_and, Bool.false_or] + · simp only [Expr.frontMul, hl, hr, eqZero, Bool.false_eq_true, if_false, beq_iff_eq, + if_neg one, Bool.false_and, Bool.true_and, Bool.false_or]; rfl + · simp [Expr.frontMul, hl, hr, Expr.isConstant] + +structure RowExpr where + expr : Expr + degree : Nat + deriving Repr, DecidableEq + +def RowExpr.konst (value : G) : RowExpr := ⟨.konst value, 0⟩ +def RowExpr.variable (column : ColRef) : RowExpr := ⟨.var column, 1⟩ +def RowExpr.add (left right : RowExpr) : RowExpr := + ⟨left.expr.frontAdd right.expr, max left.degree right.degree⟩ +def RowExpr.sub (left right : RowExpr) : RowExpr := + ⟨left.expr.frontSub right.expr, max left.degree right.degree⟩ +def RowExpr.mul (left right : RowExpr) : RowExpr := + ⟨left.expr.frontMul right.expr, left.degree + right.degree⟩ + +def RowExpr.eval (values : Values G) (expr : RowExpr) : Option AIR.RowValue := do + let value ← expr.expr.eval goldilocksOps values + return ⟨value, expr.degree, expr.expr.isConstant⟩ + +def RowExpr.Reflects (values : Values G) (expr : RowExpr) (value : AIR.RowValue) : Prop := + expr.expr.eval goldilocksOps values = some value.value ∧ + expr.degree = value.degree ∧ expr.expr.isConstant = value.constant + +theorem RowExpr.reflects_iff_eval (values : Values G) (expr : RowExpr) (value : AIR.RowValue) : + expr.Reflects values value ↔ expr.eval values = some value := by + unfold RowExpr.Reflects RowExpr.eval + cases h : expr.expr.eval goldilocksOps values with + | none => simp only [bind, Option.bind_none, reduceCtorEq, false_and] + | some output => + cases value + simp only [Option.some.injEq, bind, Option.bind_some, pure, AIR.RowValue.mk.injEq] + +theorem RowExpr.konst_reflects (values : Values G) (value : G) : + (RowExpr.konst value).Reflects values (AIR.RowValue.konst value) := ⟨rfl, rfl, rfl⟩ + +theorem RowExpr.variable_reflects (values : Values G) {column : ColRef} {value : G} + (read : (values.columns column.source column.offset)[column.index]? = some value) : + (RowExpr.variable column).Reflects values (AIR.RowValue.variable value) := ⟨read, rfl, rfl⟩ + +theorem RowExpr.add_reflects (values : Values G) {left right : RowExpr} {a b : AIR.RowValue} + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) : + (left.add right).Reflects values (a.add b) := by + refine ⟨Expr.frontAdd_eval goldilocksLaws values leftRef.1 rightRef.1, ?_, ?_⟩ + · change max left.degree right.degree = max a.degree b.degree + rw [leftRef.2.1, rightRef.2.1] + · change (left.expr.frontAdd right.expr).isConstant = (a.constant && b.constant) + rw [Expr.frontAdd_isConstant, leftRef.2.2, rightRef.2.2] + +theorem RowExpr.sub_reflects (values : Values G) {left right : RowExpr} {a b : AIR.RowValue} + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) + (rightValid : right.expr.noConstantNegs = true) : + (left.sub right).Reflects values (a.sub b) := by + refine ⟨Expr.frontSub_eval goldilocksLaws values leftRef.1 rightRef.1, ?_, ?_⟩ + · change max left.degree right.degree = max a.degree b.degree + rw [leftRef.2.1, rightRef.2.1] + · change (left.expr.frontSub right.expr).isConstant = (a.constant && b.constant) + rw [Expr.frontSub_isConstant _ _ rightValid, leftRef.2.2, rightRef.2.2] + +theorem RowExpr.mul_reflects (values : Values G) {left right : RowExpr} {a b : AIR.RowValue} + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) : + (left.mul right).Reflects values (a.mul b) := by + refine ⟨Expr.frontMul_eval goldilocksLaws values leftRef.1 rightRef.1, ?_, ?_⟩ + · change left.degree + right.degree = a.degree + b.degree + rw [leftRef.2.1, rightRef.2.1] + · change (left.expr.frontMul right.expr).isConstant = + ((a.constant && b.constant) || (a.constant && a.value == 0) || (b.constant && b.value == 0)) + rw [Expr.frontMul_isConstant values leftRef.1 rightRef.1, leftRef.2.2, rightRef.2.2] + +structure ScalarEmission where + output : RowExpr + used : Nat := 0 + equations : List Expr := [] + +def ScalarEmission.eval (values : Values G) (emission : ScalarEmission) : Option AIR.OpEmission := do + let output ← emission.output.eval values + let equations ← emission.equations.mapM (Expr.eval goldilocksOps values) + return { outputs := #[output], used := emission.used, equations } + +theorem ScalarEmission.eval_of (values : Values G) {output : RowExpr} {value : AIR.RowValue} + {used : Nat} {equations : List Expr} {results : List G} + (reflected : output.Reflects values value) + (evaluated : equations.mapM (Expr.eval goldilocksOps values) = some results) : + (ScalarEmission.mk output used equations).eval values = + some { outputs := #[value], used, equations := results } := by + have outputEval := (RowExpr.reflects_iff_eval values output value).mp reflected + simp only [ScalarEmission.eval, outputEval, evaluated, bind, Option.bind, pure] + +def mainCurrent (index : Nat) : RowExpr := .variable ⟨.main, .current, index⟩ + +def eqZeroRegular (selector : Expr) (first : Nat) (input : RowExpr) : ScalarEmission := + let d := mainCurrent first + let x := mainCurrent (first + 1) + ⟨x, 2, [(selector.frontMul input.expr).frontMul x.expr, + selector.frontMul (((input.expr.frontMul d.expr).frontAdd x.expr).frontSub (.konst 1))]⟩ + +def emitEqZero (selector : Expr) (first : Nat) (input : RowExpr) : ScalarEmission := + match input.expr.constantValue, input.degree with + | some value, 0 => ⟨.konst (G.eqZero value), 0, []⟩ + | _, _ => eqZeroRegular selector first input + +theorem eqZeroRegular_reflects (values : Values G) (row : Nat → G) {selector : Expr} {s : G} + {first : Nat} {input : RowExpr} {value : AIR.RowValue} + (selectorEval : selector.eval goldilocksOps values = some s) + (inputRef : input.Reflects values value) + (firstRead : (values.columns .main .current)[first]? = some (row 0)) + (secondRead : (values.columns .main .current)[first + 1]? = some (row 1)) : + (eqZeroRegular selector first input).eval values = + some { outputs := #[AIR.RowValue.variable (row 1)], used := 2, equations := + [s * value.value * row 1, s * (value.value * row 0 + row 1 - 1)] } := by + have dRef := RowExpr.variable_reflects values (column := ⟨.main, .current, first⟩) firstRead + have xRef := RowExpr.variable_reflects values (column := ⟨.main, .current, first + 1⟩) secondRead + have oneEval : (Expr.konst 1).eval goldilocksOps values = some 1 := rfl + have firstEval := Expr.frontMul_eval goldilocksLaws values + (Expr.frontMul_eval goldilocksLaws values selectorEval inputRef.1) xRef.1 + have secondEval := Expr.frontMul_eval goldilocksLaws values selectorEval + (Expr.frontSub_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values + (Expr.frontMul_eval goldilocksLaws values inputRef.1 dRef.1) xRef.1) oneEval) + apply ScalarEmission.eval_of values xRef + simp only [mainCurrent, List.mapM_cons, List.mapM_nil, firstEval, secondEval, bind, Option.bind, pure] + simp only [goldilocks_add, goldilocks_sub, goldilocks_mul, AIR.RowValue.variable] + +theorem emitEqZero_reflects (values : Values G) (row : Nat → G) {selector : Expr} {s : G} + {first : Nat} {input : RowExpr} {value : AIR.RowValue} + (selectorEval : selector.eval goldilocksOps values = some s) + (inputRef : input.Reflects values value) + (reads : ∀ index < (emitEqZero selector first input).used, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitEqZero selector first input).eval values = AIR.emitOp row s 0 (.eqZero 0) #[value] := by + have known := input.expr.isConstant_eq + have constant := inputRef.2.2 + have degree := inputRef.2.1 + cases hc : input.expr.constantValue with + | none => + have notConstant : value.constant = false := by + rw [hc] at known + exact constant.symm.trans known + simp only [emitEqZero, hc] + simp only [AIR.emitOp, Array.getElem?_singleton, if_true, bind, Option.bind_some, notConstant, + Bool.false_and, Bool.false_eq_true, if_false] + apply eqZeroRegular_reflects values row selectorEval inputRef + · simpa only [Nat.add_zero] using reads 0 (by simp only [emitEqZero, hc, eqZeroRegular]; decide) + · exact reads 1 (by simp only [emitEqZero, hc, eqZeroRegular]; decide) + | some c => + have isConstant : value.constant = true := by + rw [hc] at known + exact constant.symm.trans known + have valueEq := Expr.constantValue_eq_of_eval values inputRef.1 hc + cases hd : input.degree with + | zero => + have zeroDegree : value.degree = 0 := degree.symm.trans hd + simp only [emitEqZero, hc, hd] + simp only [AIR.emitOp, Array.getElem?_singleton, if_true, bind, Option.bind_some, isConstant, + zeroDegree, beq_self_eq_true, Bool.true_and, if_true] + rw [valueEq] + exact ScalarEmission.eval_of values (RowExpr.konst_reflects values _) rfl + | succ n => + have positiveDegree : value.degree = n + 1 := degree.symm.trans hd + simp only [emitEqZero, hc, hd] + simp only [AIR.emitOp, Array.getElem?_singleton, if_true, bind, Option.bind_some, isConstant, + positiveDegree, Nat.succ_ne_zero, beq_iff_eq, Bool.true_and, if_false] + apply eqZeroRegular_reflects values row selectorEval inputRef + · simpa only [Nat.add_zero] using reads 0 (by simp only [emitEqZero, hc, hd, eqZeroRegular]; decide) + · exact reads 1 (by simp only [emitEqZero, hc, hd, eqZeroRegular]; decide) + +def mulRegular (selector : Expr) (first : Nat) (product : RowExpr) : ScalarEmission := + let output := mainCurrent first + ⟨output, 1, [selector.frontMul (output.expr.frontSub product.expr)]⟩ + +def emitMul (selector : Expr) (first : Nat) (left right : RowExpr) : ScalarEmission := + let product := left.mul right + if product.degree < 2 then ⟨product, 0, []⟩ else mulRegular selector first product + +theorem mulRegular_reflects (values : Values G) (row : Nat → G) {selector : Expr} {s : G} + {first : Nat} {product : RowExpr} {value : AIR.RowValue} + (selectorEval : selector.eval goldilocksOps values = some s) + (productRef : product.Reflects values value) + (read : (values.columns .main .current)[first]? = some (row 0)) : + (mulRegular selector first product).eval values = + some { outputs := #[AIR.RowValue.variable (row 0)], used := 1, equations := [s * (row 0 - value.value)] } := by + have outputRef := RowExpr.variable_reflects values (column := ⟨.main, .current, first⟩) read + have equationEval := Expr.frontMul_eval goldilocksLaws values selectorEval + (Expr.frontSub_eval goldilocksLaws values outputRef.1 productRef.1) + apply ScalarEmission.eval_of values outputRef + simp only [mainCurrent, List.mapM_cons, List.mapM_nil, equationEval, bind, Option.bind, pure] + simp only [goldilocks_mul, goldilocks_sub, AIR.RowValue.variable] + +theorem emitMul_reflects (values : Values G) (row : Nat → G) {selector : Expr} {s : G} + {first : Nat} {left right : RowExpr} {a b : AIR.RowValue} + (selectorEval : selector.eval goldilocksOps values = some s) + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) + (reads : ∀ index < (emitMul selector first left right).used, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitMul selector first left right).eval values = AIR.emitOp row s 0 (.mul 0 1) #[a, b] := by + have productRef := RowExpr.mul_reflects values leftRef rightRef + simp only [AIR.emitOp, show (#[a, b][0]?) = some a from rfl, + show (#[a, b][1]?) = some b from rfl, bind, Option.bind_some] + rw [← productRef.2.1] + unfold emitMul + split + next small => + rw [if_pos small] + exact ScalarEmission.eval_of values productRef rfl + next large => + rw [if_neg large] + apply mulRegular_reflects values row selectorEval productRef + simpa only [Nat.add_zero] using reads 0 (by simp only [emitMul, if_neg large, mulRegular]; decide) + +theorem emitEqZero_noConstantNegs (selector : Expr) (first : Nat) (input : RowExpr) : + (emitEqZero selector first input).output.expr.noConstantNegs = true := by + unfold emitEqZero + cases input.expr.constantValue <;> cases input.degree <;> rfl + +theorem emitMul_noConstantNegs (selector : Expr) (first : Nat) {left right : RowExpr} + (leftValid : left.expr.noConstantNegs = true) (rightValid : right.expr.noConstantNegs = true) : + (emitMul selector first left right).output.expr.noConstantNegs = true := by + unfold emitMul + dsimp only + split + · exact Expr.frontMul_noConstantNegs leftValid rightValid + · rfl + +theorem emitAdd_reflects (values : Values G) (row : Nat → G) (selector rank : G) + {left right : RowExpr} {a b : AIR.RowValue} + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) : + (ScalarEmission.mk (left.add right) 0 []).eval values = + AIR.emitOp row selector rank (.add 0 1) #[a, b] := by + simp only [AIR.emitOp, show (#[a, b][0]?) = some a from rfl, + show (#[a, b][1]?) = some b from rfl, bind, Option.bind_some] + exact ScalarEmission.eval_of values (RowExpr.add_reflects values leftRef rightRef) rfl + +theorem emitSub_reflects (values : Values G) (row : Nat → G) (selector rank : G) + {left right : RowExpr} {a b : AIR.RowValue} + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) + (rightValid : right.expr.noConstantNegs = true) : + (ScalarEmission.mk (left.sub right) 0 []).eval values = + AIR.emitOp row selector rank (.sub 0 1) #[a, b] := by + simp only [AIR.emitOp, show (#[a, b][0]?) = some a from rfl, + show (#[a, b][1]?) = some b from rfl, bind, Option.bind_some] + exact ScalarEmission.eval_of values (RowExpr.sub_reflects values leftRef rightRef rightValid) rfl + +end NativeAIR +end Aiur diff --git a/Ix/Aiur/Proofs/FunctionLayout.lean b/Ix/Aiur/Proofs/FunctionLayout.lean new file mode 100644 index 000000000..894912ad2 --- /dev/null +++ b/Ix/Aiur/Proofs/FunctionLayout.lean @@ -0,0 +1,198 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CompilerLayout + +/-! Successful compilation supplies the exact computed layout for every +function. The property survives deduplication and circuit grouping. -/ + +namespace Aiur.Bytecode + +def Function.ComputedLayout (function : Function) : Prop := + let computed := ((Concrete.Bytecode.blockLayout function.body).run + (.new function.layout.inputSize)).2.functionLayout + function.layout = { computed with lookups := computed.lookups + 1 } + +def FunctionsComputedLayout (functions : Array Function) : Prop := + ∀ function ∈ functions, function.ComputedLayout + +theorem functionsComputedLayout_empty : FunctionsComputedLayout #[] := by + simp [FunctionsComputedLayout] + +theorem functionsComputedLayout_push {functions : Array Function} {function : Function} + (before : FunctionsComputedLayout functions) (valid : function.ComputedLayout) : + FunctionsComputedLayout (functions.push function) := by + intro chosen member + rcases Array.mem_push.mp member with prior | equal + · exact before chosen prior + · subst chosen; exact valid + +theorem Function.ComputedLayout.auxiliaries {function : Function} (valid : function.ComputedLayout) : + function.layout.auxiliaries = ((Concrete.Bytecode.blockLayout function.body).run + (.new function.layout.inputSize)).2.functionLayout.auxiliaries := by + have field := congrArg FunctionLayout.auxiliaries valid + exact field + +theorem Function.ComputedLayout.reserved {function : Function} (valid : function.ComputedLayout) : + 7 ≤ function.layout.auxiliaries := by + rw [valid.auxiliaries] + exact (Concrete.Bytecode.blockLayout_fields function.body (.new function.layout.inputSize)).2.2 + +theorem Function.ComputedLayout.selectors {function : Function} (valid : function.ComputedLayout) : + function.layout.selectors = function.body.controlCounts.leaves := by + have field := congrArg FunctionLayout.selectors valid + have count := (Concrete.Bytecode.blockLayout_fields function.body (.new function.layout.inputSize)).2.1 + exact field.trans (by simpa only [Concrete.Bytecode.LayoutMState.new, Nat.zero_add] using count) + +end Aiur.Bytecode + +namespace Aiur.Concrete +open Aiur.Bytecode + +private theorem layout_result_computed {body : Block} {size : Nat} {state : Bytecode.LayoutMState} + {resultUnit : Unit} (computed : (Bytecode.blockLayout body).run (.new size) = (resultUnit, state)) : + let final := { state.functionLayout with lookups := state.functionLayout.lookups + 1 } + let calculated := ((Bytecode.blockLayout body).run (.new final.inputSize)).2.functionLayout + final = { calculated with lookups := calculated.lookups + 1 } := by + have input := (Bytecode.blockLayout_fields body (.new size)).1 + rw [computed] at input + change state.functionLayout.inputSize = size at input + dsimp only + rw [input, computed] + simp only [input] + +theorem Function.compile_computedLayout {layoutMap : LayoutMap} {function : Function} + {body : Block} {state : Bytecode.LayoutMState} + (compiled : function.compile layoutMap = .ok (body, state)) (entry constrained : Bool) : + (Aiur.Bytecode.Function.mk body state.functionLayout entry constrained).ComputedLayout := by + unfold Function.compile at compiled + simp only [bind, Except.bind, pure, Except.pure] at compiled + repeat' first + | split at compiled + | (dsimp only at compiled; split at compiled) + all_goals cases compiled + all_goals exact layout_result_computed (by assumption) + +private theorem except_foldlM_invariant {ε α β : Type} (items : List α) (step : β → α → Except ε β) + (property : β → Prop) (initial : β) (before : property initial) + (preserved : ∀ acc item result, property acc → step acc item = .ok result → property result) + {result : β} (computed : items.foldlM step initial = .ok result) : property result := by + induction items generalizing initial with + | nil => cases computed; exact before + | cons item items ih => + simp only [List.foldlM_cons, bind, Except.bind] at computed + split at computed + · cases computed + · rename_i next nextComputed + exact ih next (preserved initial item next before nextComputed) computed + +theorem Decls.toBytecode_computedLayout {decls : Decls} {program : Toplevel} + {names : Std.HashMap Global FunIdx} (compiled : decls.toBytecode = .ok (program, names)) : + FunctionsComputedLayout program.functions := by + unfold Decls.toBytecode at compiled + simp only [bind, Except.bind, pure, Except.pure] at compiled + split at compiled + · cases compiled + · split at compiled + · cases compiled + · rename_i result folded + cases compiled + unfold IndexMap.foldlM at folded + rw [← Array.foldlM_toList] at folded + apply except_foldlM_invariant _ _ (fun result => FunctionsComputedLayout result.1) _ + functionsComputedLayout_empty ?_ folded + intro acc item result before step + rcases item with ⟨name, declaration⟩ + cases declaration <;> dsimp only at step + all_goals first + | (cases step; exact before) + | (split at step + · cases step + · rename_i result compiled + cases step + exact functionsComputedLayout_push before (Function.compile_computedLayout compiled _ _)) + +end Aiur.Concrete + +namespace Aiur.Bytecode + +theorem Function.ComputedLayout.rewrite {function : Function} (valid : function.ComputedLayout) + (rename : FunIdx → FunIdx) : { function with body := rewriteBlock rename function.body }.ComputedLayout := by + unfold Function.ComputedLayout at * + rw [Concrete.Bytecode.rewriteBlock_layout rename function.body + (.new function.layout.inputSize) (Concrete.Bytecode.layoutRenaming_empty rename)] + exact valid + +theorem deduplicate_newFunctions_computedLayout (functions : Array Function) + (classes : Array Nat) (canonical : Array Bool) (rename : FunIdx → FunIdx) + (valid : FunctionsComputedLayout functions) : + FunctionsComputedLayout (deduplicate_newFunctions functions classes canonical rename) := by + unfold deduplicate_newFunctions + apply Array.foldl_induction (fun _ result => FunctionsComputedLayout result) functionsComputedLayout_empty + intro index accumulated before + dsimp only + split + · apply functionsComputedLayout_push before + apply Function.ComputedLayout.rewrite + apply valid + exact (Array.of_mem_zip (Array.getElem_mem index.isLt)).2 + · exact before + +theorem Toplevel.deduplicateCandidate_computedLayout (program : Toplevel) + (valid : FunctionsComputedLayout program.functions) : + FunctionsComputedLayout program.deduplicateCandidate.1.functions := by + unfold Toplevel.deduplicateCandidate + dsimp only + split + · exact valid + · exact deduplicate_newFunctions_computedLayout _ _ _ _ valid + +theorem Toplevel.deduplicate_computedLayout (program : Toplevel) + (valid : FunctionsComputedLayout program.functions) : + FunctionsComputedLayout program.deduplicate.1.functions := by + unfold Toplevel.deduplicate checkedRenaming + dsimp only + split + · exact program.deduplicateCandidate_computedLayout valid + · exact valid + +end Aiur.Bytecode + +namespace Aiur +open Bytecode + +theorem finishCompilation_computedLayout (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) (valid : FunctionsComputedLayout raw.functions) + (generic : source.componentRanks = false) : + FunctionsComputedLayout (finishCompilation source raw names).bytecode.functions := by + unfold finishCompilation + simp only [generic, Bool.false_eq_true, if_false] + intro function member + obtain ⟨index, bound, equal⟩ := Array.exists_of_mem_mapIdx member + subst function + change raw.deduplicate.1.functions[index].ComputedLayout + exact raw.deduplicate_computedLayout valid _ (Array.getElem_mem bound) + +theorem Source.Toplevel.compile_computedLayout {source : Source.Toplevel} {compiled : CompiledToplevel} + (accepted : source.compile = .ok compiled) (generic : source.componentRanks = false) : + FunctionsComputedLayout compiled.bytecode.functions := by + obtain ⟨inlined, typed, concrete, raw, names, inlinedOk, _, _, lowered, artifact⟩ := + source.compile_artifact_of_ok accepted + rw [artifact] + exact finishCompilation_computedLayout inlined raw names (Concrete.Decls.toBytecode_computedLayout lowered) + ((Source.Toplevel.inlineCalls_componentRanks inlinedOk).trans generic) + +theorem BoundVerifier.Backend.functions_computedLayout {selection : BoundVerifier.Selection} + (backend : BoundVerifier.Backend selection) (generic : selection.source.componentRanks = false) : + FunctionsComputedLayout backend.compiled.bytecode.functions := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + have valid := Source.Toplevel.compile_computedLayout compiled generic + split at grouped + · cases grouped + exact valid + · rw [(CompiledToplevel.groupFunctions_preserves_code grouped).2.2.1] + exact valid + +end Aiur diff --git a/Ix/Aiur/Proofs/FunctionRows.lean b/Ix/Aiur/Proofs/FunctionRows.lean new file mode 100644 index 000000000..1cd904cb4 --- /dev/null +++ b/Ix/Aiur/Proofs/FunctionRows.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockRowInputs + +/-! +Whole-function execution and local function-row validity derived from the +valued emitter. The same semantic return determines the combined provider +message, including shared slots with differing raw message lengths. + +Lookup membership, count bounds, function layout and activity premises are +explicit. These theorems do not yet extract rows from the Rust verifier or +establish public acceptance-to-certified-claim soundness. +-/ + +namespace Aiur.AIR + +theorem slotMessage_chosen (width : Nat) (branchless : Bool) {parts : List (G × List G)} + (single : branchless = true → parts.length = 1) + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) + {chosen : G × List G} (member : chosen ∈ parts) (selected : chosen.1 = 1) : + padMessage width (slotMessage branchless parts) = padMessage width chosen.2 := by + cases branchless with + | false => + obtain ⟨before, after, equal, zero⟩ := selector_pair_chosen individual bounded active member selected + rw [equal] + exact weightedMessage_split width before after chosen selected zero + | true => + obtain ⟨part, equal⟩ := List.length_eq_one_iff.mp (single rfl) + subst parts + have same := List.mem_singleton.mp member + subst chosen + rfl + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +def Function.emitRow (row : Nat → G) (selector : SelIdx → G) (functionIndex : FunIdx) (rank : G) + (values : Array RowValue) (column lookup : Nat) (function : Function) : Option BlockEmission := + function.body.emitRow row selector ⟨functionIndex, function.layout.inputSize, rank⟩ + (function.body.selectorFlow selector).entry values column lookup + +theorem Function.emitRow_run {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (program : Toplevel) (row : Nat → G) (selector : SelIdx → G) + (functionIndex : FunIdx) (rank : G) (values : Array RowValue) (column lookup : Nat) + (function : Function) (present : program.functions[functionIndex]? = some function) + (arity : values.size = function.layout.inputSize) + (shape : function.body.lookupShapes program none = true) (bounds : function.body.rowBounds selector) + {emission : BlockEmission} + (emitted : function.emitRow row selector functionIndex rank values column lookup = some emission) + (active : (function.body.selectorFlow selector).entry = 1) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.QueriesIn queries) : + ∃ request calls, (1, request) ∈ emission.returns ∧ + request.function = functionIndex ∧ request.inputs = rowValues values ∧ request.rank = rank ∧ + AIR.RunFunction program (memoryFacts tables.memory) request (calls.map Prod.fst) ∧ + emission.CallsAt calls ∧ CallsEmitted rank 1 emission.equations queries calls := by + have bodyEmitted := emitted + rw [Function.emitRow] at bodyEmitted + have initial : RowInputs function.layout.inputSize (rowValues values) values := by + rw [← arity] + exact RowInputs.full values + have preserved := function.body.emitRow_inputs row selector _ _ _ _ _ initial bodyEmitted + have tracked := function.body.emitRow_tracks_calls row selector _ _ _ _ _ bodyEmitted + obtain ⟨outcome, calls, execution, terminal, called⟩ := function.body.emitRow_run global memoryValid canonical + program none row selector _ _ _ _ _ shape bounds bodyEmitted active rfl satisfied queried + cases outcome with + | returned outputs => + obtain ⟨request, member, outputsEq⟩ := terminal + obtain ⟨functionEq, inputsEq, rankEq⟩ := preserved.returned (1, request) member + refine ⟨request, calls, member, functionEq, inputsEq, rankEq, ?_, called, tracked.active queried called⟩ + apply AIR.RunFunction.function + · rw [functionEq] + exact present + · rw [inputsEq] + simpa only [rowValues, Array.size_map] using arity.symm + · rw [inputsEq, outputsEq] + exact execution + | yielded outputs => + obtain ⟨yielded, member, _⟩ := terminal + have empty := function.body.selectorFlow_yields_empty selector program shape + have projected := function.body.emitRow_projection row selector _ _ _ _ _ bodyEmitted + have one : (1 : G) ∈ emission.yields.map Prod.fst := + List.mem_map.mpr ⟨(1, yielded), member, rfl⟩ + rw [projected.yielded, empty] at one + cases one + +theorem Function.emitRow_valid {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (program : Toplevel) (row : Nat → G) (selector : SelIdx → G) + (functionIndex : FunIdx) (rankBytes : Fin 6 → G) (values : Array RowValue) (column lookup : Nat) + (function : Function) (present : program.functions[functionIndex]? = some function) + (arity : values.size = function.layout.inputSize) + (shape : function.body.lookupShapes program none = true) (bounds : function.body.rowBounds selector) + {emission : BlockEmission} + (emitted : function.emitRow row selector functionIndex (packRank rankBytes) values column lookup = some emission) + (multiplicity : G) (nonzero : multiplicity ≠ 0) + (activity : activityConstraint multiplicity (function.body.selectorFlow selector).entry = 0) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.QueriesIn queries) : + ∃ interpreted : FunctionRow, interpreted.Valid program (memoryFacts tables.memory) ∧ + (1, interpreted.request) ∈ emission.returns ∧ + interpreted.request.function = functionIndex ∧ interpreted.request.inputs = rowValues values ∧ + interpreted.request.rank = packRank rankBytes ∧ interpreted.rankBytes = rankBytes ∧ + interpreted.selector = (function.body.selectorFlow selector).entry ∧ + interpreted.multiplicity = multiplicity ∧ emission.CallsAt interpreted.calls ∧ + CallsEmitted (packRank rankBytes) 1 emission.equations queries interpreted.calls := by + have active := nonzero_multiplicity_selector_one activity nonzero + obtain ⟨request, calls, member, functionEq, inputsEq, rankEq, execution, called, inventory⟩ := + function.emitRow_run global memoryValid canonical program row selector functionIndex (packRank rankBytes) + values column lookup present arity shape bounds emitted active satisfied queried + let interpreted : FunctionRow := ⟨request, calls, rankBytes, 1, multiplicity⟩ + refine ⟨interpreted, ?_, member, functionEq, inputsEq, rankEq, rfl, active.symm, rfl, called, inventory⟩ + refine ⟨Or.inr rfl, ?_, fun _ => rankEq, fun _ => execution, ?_⟩ + · rw [active] at activity + exact activity + · intro edge edgeMember + change 1 * callOrderConstraint request.rank edge.1.rank (packRank edge.2) = 0 + rw [rankEq] + exact (inventory edge edgeMember).2.2.satisfied satisfied + +theorem Function.emitRow_message (row : Nat → G) (selector : SelIdx → G) + (functionIndex : FunIdx) (rank : G) (values : Array RowValue) (column lookup : Nat) + (function : Function) (program : Toplevel) + (shape : function.body.lookupShapes program none = true) + {emission : BlockEmission} + (emitted : function.emitRow row selector functionIndex rank values column lookup = some emission) + (active : (function.body.selectorFlow selector).entry = 1) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (bounded : emission.returns.length < gSize.toNat) + (width : Nat) (branchless : Bool) (single : branchless = true → emission.returns.length = 1) + {request : AIR.Call} (member : (1, request) ∈ emission.returns) : + padMessage width (slotMessage branchless + (emission.returns.map fun part => (part.1, functionMessage part.2))) = + padMessage width (functionMessage request) := by + have bodyEmitted := emitted + rw [Function.emitRow] at bodyEmitted + have projection := function.body.emitRow_projection row selector _ _ _ _ _ bodyEmitted + have valid := function.body.emitRow_selectors row selector _ _ _ _ _ bodyEmitted satisfied + have gates := projection.returned.trans (function.body.returnGates_reflects selector _ valid rfl) + have empty := function.body.selectorFlow_yields_empty selector program shape + have sound := function.body.selectorFlow_sound selector valid + have conservation := sound.conservation + rw [empty] at conservation + change _ = selectorSum (function.body.selectorFlow selector).returns + 0 at conservation + rw [G.add_zero, active] at conservation + apply slotMessage_chosen width branchless + (by simpa only [List.length_map] using single) + (fun part present => ?_) + (by simpa only [List.length_map] using bounded) + (by simpa only [List.map_map, Function.comp_def, gates] using conservation.symm) + (List.mem_map.mpr ⟨(1, request), member, rfl⟩) rfl + obtain ⟨returned, returnMember, equal⟩ := List.mem_map.mp present + subst part + apply sound.returned returned.1 + rw [← gates] + exact List.mem_map.mpr ⟨returned, returnMember, rfl⟩ + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/GlobalLookups.lean b/Ix/Aiur/Proofs/GlobalLookups.lean new file mode 100644 index 000000000..c381a1b73 --- /dev/null +++ b/Ix/Aiur/Proofs/GlobalLookups.lean @@ -0,0 +1,536 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LookupMessages +import Ix.Aiur.Proofs.LookupShapes +import Ix.Aiur.Proofs.Execution +import Ix.Aiur.Proofs.Memory + +/-! +Function execution, immutable memory facts and byte operations from one +mixed pool of zero-padded lookup messages. + +The native function, memory and thirteen byte channels determine the +provider family. Query widths and the actual structural call checks prevent +padding aliases. Only reachable calls need a checked shape; an active row's +local execution determines its return width and propagates the callee checks. +Byte lookups from the same pool bound all call ranks and gaps, giving finite +execution by strict rank increase. + +The pool retains arbitrary field provider multiplicities, inactive rows and +all consumer kinds. It assumes local row interpretation, exact padded +balance, and explicit query-count and width bounds. Extraction of these +obligations from native AIR and cryptographic verification is still required. +-/ + +namespace Aiur.AIR + +open Bytecode.AIR + +structure LookupTables where + functions : List FunctionRow + memoryWidths : List Nat + memory : Nat → Array MemoryRow + byte1 : Byte1Kind → Fin 256 → G + byte2 : Byte2Kind → Fin 65536 → G + +def LookupTables.providers (tables : LookupTables) : List (Provider (List G)) := + mapProviders functionMessage (functionProviders tables.functions) ++ + tables.memoryWidths.flatMap (fun width => + mapProviders (fun request => memoryMessage width request.1 request.2) + (memoryProviders (tables.memory width))) ++ + byte1Providers tables.byte1 ++ byte2Providers tables.byte2 + +theorem LookupTables.provider_cases {tables : LookupTables} {provider : Provider (List G)} + (member : provider ∈ tables.providers) : + (∃ row ∈ tables.functions, provider = (functionMessage row.request, row.multiplicity)) ∨ + (∃ width ∈ tables.memoryWidths, ∃ i : Fin (tables.memory width).size, + provider = (memoryMessage width (tables.memory width)[i].pointer + (tables.memory width)[i].contents, (tables.memory width)[i].multiplicity)) ∨ + (∃ kind : Byte1Kind, ∃ row : Fin 256, + provider = (byte1Request kind (G.ofNat row.val) (byte1Outputs kind row), tables.byte1 kind row)) ∨ + (∃ kind : Byte2Kind, ∃ row : Fin 65536, + provider = (byte2Request kind (byteRangeMessage row).1 (byteRangeMessage row).2 + (byte2Outputs kind row), tables.byte2 kind row)) := by + simp only [LookupTables.providers, List.mem_append] at member + rcases member with ((function | memory) | byte1) | byte2 + · obtain ⟨original, originalMember, equal⟩ := List.mem_map.mp function + obtain ⟨row, rowMember, rowEq⟩ := List.mem_map.mp originalMember + subst original + exact Or.inl ⟨row, rowMember, equal.symm⟩ + · obtain ⟨width, widthMember, originalMember⟩ := List.mem_flatMap.mp memory + obtain ⟨original, rowMember, equal⟩ := List.mem_map.mp originalMember + obtain ⟨row, rowEq⟩ := List.mem_ofFn.mp rowMember + subst original + exact Or.inr (Or.inl ⟨width, widthMember, row, equal.symm⟩) + · obtain ⟨kind, _, rowMember⟩ := List.mem_flatMap.mp byte1 + obtain ⟨row, equal⟩ := List.mem_ofFn.mp rowMember + exact Or.inr (Or.inr (Or.inl ⟨kind, row, equal.symm⟩)) + · obtain ⟨kind, _, rowMember⟩ := List.mem_flatMap.mp byte2 + obtain ⟨row, equal⟩ := List.mem_ofFn.mp rowMember + exact Or.inr (Or.inr (Or.inr ⟨kind, row, equal.symm⟩)) + +theorem Byte1Kind.channel_range (kind : Byte1Kind) : + 2 ≤ kind.channel.n ∧ kind.channel.n ≤ 4 := by + cases kind <;> decide +kernel + +theorem Byte2Kind.channel_range (kind : Byte2Kind) : + 5 ≤ kind.channel.n ∧ kind.channel.n ≤ 14 := by + cases kind <;> decide +kernel + +theorem padMessage_channel {width : Nat} {left right : List G} + (positive : 0 < width) (same : padMessage width left = padMessage width right) : + left[0]?.getD 0 = right[0]?.getD 0 := by + have first := congrArg (fun message => message[0]?.getD 0) same + simpa only [padMessage_read left 0 positive, padMessage_read right 0 positive] using first + +theorem LookupTables.function_provider {tables : LookupTables} {provider : Provider (List G)} + (member : provider ∈ tables.providers) (channel : provider.1[0]?.getD 0 = 0) : + ∃ row ∈ tables.functions, provider = (functionMessage row.request, row.multiplicity) := by + rcases tables.provider_cases member with function | ⟨width, _, i, equal⟩ | + ⟨kind, row, equal⟩ | ⟨kind, row, equal⟩ + · exact function + · subst provider + have bad := congrArg G.n channel + change 1 = 0 at bad + omega + · subst provider + have bad := congrArg G.n channel + change kind.channel.n = 0 at bad + have range := kind.channel_range + omega + · subst provider + have bad := congrArg G.n channel + change kind.channel.n = 0 at bad + have range := kind.channel_range + omega + +theorem LookupTables.memory_provider {tables : LookupTables} {provider : Provider (List G)} + (member : provider ∈ tables.providers) (channel : provider.1[0]?.getD 0 = 1) : + ∃ width ∈ tables.memoryWidths, ∃ i : Fin (tables.memory width).size, + provider = (memoryMessage width (tables.memory width)[i].pointer + (tables.memory width)[i].contents, (tables.memory width)[i].multiplicity) := by + rcases tables.provider_cases member with ⟨row, _, equal⟩ | memory | + ⟨kind, row, equal⟩ | ⟨kind, row, equal⟩ + · subst provider + have bad := congrArg G.n channel + change 0 = 1 at bad + omega + · exact memory + · subst provider + have bad := congrArg G.n channel + change kind.channel.n = 1 at bad + have range := kind.channel_range + omega + · subst provider + have bad := congrArg G.n channel + change kind.channel.n = 1 at bad + have range := kind.channel_range + omega + +theorem LookupTables.byte1_provider {tables : LookupTables} {provider : Provider (List G)} + {kind : Byte1Kind} (member : provider ∈ tables.providers) + (channel : provider.1[0]?.getD 0 = kind.channel) : + ∃ row : Fin 256, + provider = (byte1Request kind (G.ofNat row.val) (byte1Outputs kind row), tables.byte1 kind row) := by + have range := kind.channel_range + rcases tables.provider_cases member with ⟨row, _, equal⟩ | ⟨width, _, i, equal⟩ | + ⟨providedKind, row, equal⟩ | ⟨providedKind, row, equal⟩ + · subst provider + have bad := congrArg G.n channel + change 0 = kind.channel.n at bad + omega + · subst provider + have bad := congrArg G.n channel + change 1 = kind.channel.n at bad + omega + · subst provider + have same := Byte1Kind.channel_injective channel + subst providedKind + exact ⟨row, rfl⟩ + · subst provider + have bad := congrArg G.n channel + change providedKind.channel.n = kind.channel.n at bad + have providedRange := providedKind.channel_range + omega + +theorem LookupTables.byte2_provider {tables : LookupTables} {provider : Provider (List G)} + {kind : Byte2Kind} (member : provider ∈ tables.providers) + (channel : provider.1[0]?.getD 0 = kind.channel) : + ∃ row : Fin 65536, + provider = (byte2Request kind (byteRangeMessage row).1 (byteRangeMessage row).2 + (byte2Outputs kind row), tables.byte2 kind row) := by + have range := kind.channel_range + rcases tables.provider_cases member with ⟨row, _, equal⟩ | ⟨width, _, i, equal⟩ | + ⟨providedKind, row, equal⟩ | ⟨providedKind, row, equal⟩ + · subst provider + have bad := congrArg G.n channel + change 0 = kind.channel.n at bad + omega + · subst provider + have bad := congrArg G.n channel + change 1 = kind.channel.n at bad + omega + · subst provider + have bad := congrArg G.n channel + change providedKind.channel.n = kind.channel.n at bad + have providedRange := providedKind.channel_range + omega + · subst provider + have same := Byte2Kind.channel_injective channel + subst providedKind + exact ⟨row, rfl⟩ + +theorem functionMessage_minimum (request : Call) : 3 ≤ (functionMessage request).length := by + simp only [functionMessage, List.length_cons, List.length_append, List.length_nil] + omega + +theorem padded_functionMessage_index {width : Nat} {left right : Call} + (leftBound : left.function < gSize.toNat) (rightBound : right.function < gSize.toNat) + (widthBound : (functionMessage left).length ≤ width) + (same : padMessage width (functionMessage left) = padMessage width (functionMessage right)) : + left.function = right.function := by + have minimum := functionMessage_minimum left + have key := congrArg (fun message => message[1]?.getD 0) same + rw [padMessage_read (functionMessage left) 1 (by omega), + padMessage_read (functionMessage right) 1 (by omega)] at key + exact G.ofNat_injective_below leftBound rightBound key + +/-- The query's structural return check and the provider's local execution +determine the same message width, even when some callees never return. -/ +theorem padded_functionMessage_reflects {width : Nat} {program : Bytecode.Toplevel} + {memory : Memory} {request provided : Call} {calls : List Call} + (programBound : program.functions.size < gSize.toNat) + (shape : request.LookupShape program) + (execution : RunFunction program memory provided calls) + (widthBound : (functionMessage request).length ≤ width) + (same : padMessage width (functionMessage request) = padMessage width (functionMessage provided)) : + request = provided := by + obtain ⟨callee, present, constrained, inputSize, returnSize⟩ := shape + have requestBound : request.function < gSize.toNat := + Nat.lt_trans (Array.getElem?_eq_some_iff.mp present).choose programBound + cases execution with + | function supplied arity body => + have providedBound : provided.function < gSize.toNat := + Nat.lt_trans (Array.getElem?_eq_some_iff.mp supplied).choose programBound + have index := padded_functionMessage_index requestBound providedBound widthBound same + have calleeEq := Option.some.inj ((index ▸ present).symm.trans supplied) + subst callee + have inputEq : request.inputs.size = provided.inputs.size := inputSize.symm.trans arity + have outputEq : request.outputs.size = provided.outputs.size := + (body.return_size request.outputs.size returnSize).symm + have lengths : (functionMessage request).length = (functionMessage provided).length := by + simp only [functionMessage, List.length_cons, List.length_append, Array.length_toList, + inputEq, outputEq] + have raw := padMessage_injective_of_length widthBound lengths same + exact functionMessage_injective (arities := fun _ => (request.inputs.size, request.outputs.size)) + ⟨requestBound, rfl, rfl⟩ ⟨providedBound, inputEq.symm, outputEq.symm⟩ raw + +/-- One mixed padded pool. Only consumer counts are bounded; provider +multiplicities are arbitrary field elements. Message widths are checked on +queries, without imposing a global output-arity table on function rows. -/ +structure GlobalLookups (tables : LookupTables) (width : Nat) (queries : List (List G)) : Prop where + balance : PaddedLookupBalance width queries tables.providers + count : queries.length < gSize.toNat + widths : ∀ query ∈ queries, query.length ≤ width + +theorem GlobalLookups.function_provider {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} + (valid : ∀ row ∈ tables.functions, row.Valid program memory) + (programBound : program.functions.size < gSize.toNat) + {request : Call} (shape : request.LookupShape program) + (queried : functionMessage request ∈ queries) : + ∃ row ∈ tables.functions, row.request = request ∧ row.selector = 1 := by + obtain ⟨provider, member, same, nonzero⟩ := + paddedLookupBalance_provider global.balance global.count queried + have widthBound := global.widths _ queried + have minimum := functionMessage_minimum request + have channel := padMessage_channel (by omega : 0 < width) same + obtain ⟨row, rowMember, equal⟩ := tables.function_provider member channel + subst provider + have active := (valid row rowMember).active_of_nonzero nonzero + have exactCall := padded_functionMessage_reflects programBound shape + ((valid row rowMember).execution active) widthBound same.symm + exact ⟨row, rowMember, exactCall.symm, active⟩ + +theorem GlobalLookups.byte1 {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {kind : Byte1Kind} {input : G} {outputs : Array G} + (sized : outputs.size = kind.outputSize) + (queried : byte1Request kind input outputs ∈ queries) : + input.n < 256 ∧ outputs = kind.result input := by + obtain ⟨provider, member, same, _⟩ := + paddedLookupBalance_provider global.balance global.count queried + have shape := byte1Request_shape (fun _ => (0, 0)) kind input outputs sized + have widthBound := global.widths _ queried + have minimum := shape.1 + have channel := padMessage_channel (by omega : 0 < width) same + obtain ⟨row, equal⟩ := tables.byte1_provider member channel + subst provider + have raw := (padMessage_injective_of_shape shape + (byte1Request_shape _ kind _ _ (byte1Outputs_size kind row)) widthBound same.symm).symm + obtain ⟨_, tail⟩ := List.cons.inj raw + obtain ⟨sameInput, sameOutputs⟩ := List.cons.inj tail + have below : row.val < gSize.toNat := Nat.lt_trans row.isLt (by decide) + constructor + · rw [← sameInput, G.n_ofNat, Nat.mod_eq_of_lt below] + exact row.isLt + · rw [← sameInput] + exact (Array.toList_inj.mp sameOutputs).symm.trans (byte1Outputs_correct kind row) + +theorem GlobalLookups.byte2 {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {kind : Byte2Kind} {x y : G} {outputs : Array G} + (sized : outputs.size = kind.outputSize) + (queried : byte2Request kind x y outputs ∈ queries) : + x.n < 256 ∧ y.n < 256 ∧ outputs = kind.result x y := by + obtain ⟨provider, member, same, _⟩ := + paddedLookupBalance_provider global.balance global.count queried + have shape := byte2Request_shape (fun _ => (0, 0)) kind x y outputs sized + have widthBound := global.widths _ queried + have minimum := shape.1 + have channel := padMessage_channel (by omega : 0 < width) same + obtain ⟨row, equal⟩ := tables.byte2_provider member channel + subst provider + have raw := (padMessage_injective_of_shape shape + (byte2Request_shape _ kind _ _ _ (byte2Outputs_size kind row)) widthBound same.symm).symm + obtain ⟨_, tail⟩ := List.cons.inj raw + obtain ⟨sameX, tail⟩ := List.cons.inj tail + obtain ⟨sameY, sameOutputs⟩ := List.cons.inj tail + rw [← sameX, ← sameY] + refine ⟨(byteRangeMessage_bounded row).1, (byteRangeMessage_bounded row).2, ?_⟩ + exact (Array.toList_inj.mp sameOutputs).symm.trans (byte2Outputs_correct kind row) + +theorem GlobalLookups.memory_fact {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + (valid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + {size : Nat} {pointer : G} {contents : Array G} + (sizeBound : size < gSize.toNat) (sized : contents.size = size) + (queried : memoryMessage size pointer contents ∈ queries) : + memoryFacts tables.memory size pointer contents := by + obtain ⟨provider, member, same, nonzero⟩ := + paddedLookupBalance_provider global.balance global.count queried + have shape := memoryMessage_shape (fun _ => (0, 0)) size pointer contents sizeBound sized + have widthBound := global.widths _ queried + have minimum := shape.1 + have channel := padMessage_channel (by omega : 0 < width) same + obtain ⟨providedSize, sizeMember, row, equal⟩ := tables.memory_provider member channel + subst provider + have raw := (padMessage_injective_of_shape shape + (memoryMessage_shape _ providedSize _ _ (canonical _ sizeMember) + ((valid providedSize).widths row row.isLt)) widthBound same.symm).symm + obtain ⟨sameSize, tail⟩ := List.cons.inj (List.cons.inj raw).2 + have sizeEq := G.ofNat_injective_below (canonical _ sizeMember) sizeBound sameSize + subst providedSize + obtain ⟨samePointer, sameContents⟩ := List.cons.inj tail + have active : (tables.memory size)[row].selector = 1 := by + rcases (valid size).selectors row row.isLt with inactive | active + · exact False.elim (nonzero (inactive_multiplicity_zero inactive + ((valid size).activity row row.isLt))) + · exact active + exact ⟨row, row.isLt, active, samePointer, Array.toList_inj.mp sameContents⟩ + +theorem GlobalLookups.memory_consistent {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + (valid : ∀ size, MemoryRowsValid size (tables.memory size)) + (heights : ∀ size, (tables.memory size).size < gSize.toNat) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + {size : Nat} {pointer : G} {left right : Array G} + (sizeBound : size < gSize.toNat) (leftSize : left.size = size) (rightSize : right.size = size) + (queriedLeft : memoryMessage size pointer left ∈ queries) + (queriedRight : memoryMessage size pointer right ∈ queries) : left = right := + memoryFacts_functional tables.memory valid heights + (global.memory_fact valid canonical sizeBound leftSize queriedLeft) + (global.memory_fact valid canonical sizeBound rightSize queriedRight) + +theorem GlobalLookups.byte1_step {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + (memory : Memory) {kind : Byte1Kind} {values : Array G} + {index : Bytecode.ValIdx} {input : G} {outputs : Array G} + (read : values[index]? = some input) (sized : outputs.size = kind.outputSize) + (queried : byte1Request kind input outputs ∈ queries) : + Step memory (kind.op index) values (values ++ outputs) [] := by + obtain ⟨range, correct⟩ := global.byte1 sized queried + apply Step.primitive (advice := #[]) + rw [correct] + exact byte1_primitive read range + +theorem GlobalLookups.byte2_step {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + (memory : Memory) {kind : Byte2Kind} {values : Array G} + {left right : Bytecode.ValIdx} {x y : G} {outputs : Array G} + (readX : values[left]? = some x) (readY : values[right]? = some y) + (sized : outputs.size = kind.outputSize) + (queried : byte2Request kind x y outputs ∈ queries) : + Step memory (kind.op left right) values + (values ++ kind.extendOutputs x y outputs) [] := by + obtain ⟨rangeX, rangeY, correct⟩ := global.byte2 sized queried + apply Step.primitive (advice := #[]) + rw [correct] + exact byte2_primitive readX readY rangeX rangeY + +def rangeMessage (pair : G × G) : List G := byte2Request .range pair.1 pair.2 #[] + +theorem GlobalLookups.rank_bytes {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + (bytes : Fin 6 → G) (queried : (rankByteQueries bytes).map rangeMessage ⊆ queries) : + ∀ i, (bytes i).n < 256 := by + have pairRange : ∀ pair ∈ rankByteQueries bytes, pair.1.n < 256 ∧ pair.2.n < 256 := by + intro pair member + have result := global.byte2 (kind := .range) (outputs := #[]) rfl + (queried (List.mem_map.mpr ⟨pair, member, rfl⟩)) + exact ⟨result.1, result.2.1⟩ + have p0 := pairRange _ (by simp [rankByteQueries] : (bytes 0, bytes 1) ∈ rankByteQueries bytes) + have p1 := pairRange _ (by simp [rankByteQueries] : (bytes 2, bytes 3) ∈ rankByteQueries bytes) + have p2 := pairRange _ (by simp [rankByteQueries] : (bytes 4, bytes 5) ∈ rankByteQueries bytes) + intro i + have cases : i = 0 ∨ i = 1 ∨ i = 2 ∨ i = 3 ∨ i = 4 ∨ i = 5 := by omega + rcases cases with rfl | rfl | rfl | rfl | rfl | rfl + · exact p0.1 + · exact p0.2 + · exact p1.1 + · exact p1.2 + · exact p2.1 + · exact p2.2 + +theorem FunctionRow.Valid.global_rank_bounded {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {row : FunctionRow} + (valid : row.Valid program memory) (member : row ∈ tables.functions) (active : row.selector = 1) + (queried : (functionByteQueries tables.functions).map rangeMessage ⊆ queries) : + row.request.rank.n < callRankBound := by + rw [valid.rank active] + apply packRank_lt + apply global.rank_bytes + intro message messageMember + obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp messageMember + apply queried + exact List.mem_map.mpr ⟨pair, functionByteQueries_member member active + (List.mem_append_left _ pairMember), equal⟩ + +theorem FunctionRow.Valid.global_call_order {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {row : FunctionRow} + (valid : row.Valid program memory) (member : row ∈ tables.functions) (active : row.selector = 1) + (queried : (functionByteQueries tables.functions).map rangeMessage ⊆ queries) + {edge : Call × (Fin 6 → G)} (called : edge ∈ row.calls) + (childBound : edge.1.rank.n < callRankBound) : + row.request.rank.n < edge.1.rank.n := by + have gapBound : (packRank edge.2).n < callRankBound := by + apply packRank_lt + apply global.rank_bytes + intro message messageMember + obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp messageMember + apply queried + exact List.mem_map.mpr ⟨pair, functionByteQueries_member member active + (List.mem_append_right _ (List.mem_flatMap.mpr ⟨edge, called, pairMember⟩)), equal⟩ + exact active_call_order_strict active + (valid.global_rank_bounded global member active queried) + childBound gapBound (valid.order edge called) + +/-- Reachable rows execute finitely using one global padded lookup balance. +Only the current request is assumed to have a checked call shape; structural +program validation propagates that fact to its children. -/ +theorem GlobalLookups.rows_execute {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {roots : List Call} + (programValid : program.validateLookupShapes = true) + (valid : ∀ row ∈ tables.functions, row.Valid program memory) + (functionsQueried : (functionQueries roots tables.functions).map functionMessage ⊆ queries) + (bytesQueried : (functionByteQueries tables.functions).map rangeMessage ⊆ queries) + {row : FunctionRow} (member : row ∈ tables.functions) (active : row.selector = 1) + (shape : row.request.LookupShape program) : Execution program memory row.request := by + have programBound : program.functions.size < gSize.toNat := by + have checked := programValid + simp only [Bytecode.Toplevel.validateLookupShapes, Bool.and_eq_true, decide_eq_true_eq] at checked + exact checked.1 + have all : ∀ n : Nat, ∀ row : FunctionRow, + callRankBound - row.request.rank.n = n → row ∈ tables.functions → row.selector = 1 → + row.request.LookupShape program → Execution program memory row.request := by + intro n + induction n using Nat.strongRecOn with + | ind n ih => + intro parent measure member active shape + have body := (valid parent member).execution active + have children : ∀ child ∈ parent.requests, child.LookupShape program := by + obtain ⟨callee, present, constrained, _, _⟩ := shape + exact body.calls_lookupShape programValid present constrained + apply Execution.function body + intro child called + obtain ⟨edge, edgeMember, edgeEq⟩ := List.mem_map.mp called + obtain ⟨provider, providerMember, same, providerActive⟩ := + global.function_provider valid programBound (children child called) + (functionsQueried (List.mem_map.mpr + ⟨child, functionQueries_member member active called, rfl⟩)) + have childBound := (valid provider providerMember).global_rank_bounded + global providerMember providerActive bytesQueried + have order := (valid parent member).global_call_order global member active bytesQueried + edgeMember (by simpa only [edgeEq, ← same] using childBound) + rw [edgeEq, ← same] at order + have smaller : callRankBound - provider.request.rank.n < n := by omega + rw [← same] + exact ih _ smaller provider rfl providerMember providerActive (same ▸ children child called) + exact all _ row rfl member active shape + +theorem GlobalLookups.roots_execute {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {roots : List Call} + (programValid : program.validateLookupShapes = true) + (valid : ∀ row ∈ tables.functions, row.Valid program memory) + (functionsQueried : (functionQueries roots tables.functions).map functionMessage ⊆ queries) + (bytesQueried : (functionByteQueries tables.functions).map rangeMessage ⊆ queries) + {request : Call} (shape : request.LookupShape program) (root : request ∈ roots) : + Execution program memory request := by + have programBound : program.functions.size < gSize.toNat := by + have checked := programValid + simp only [Bytecode.Toplevel.validateLookupShapes, Bool.and_eq_true, decide_eq_true_eq] at checked + exact checked.1 + obtain ⟨row, member, same, active⟩ := global.function_provider valid programBound shape + (functionsQueried (List.mem_map.mpr ⟨request, List.mem_append_left _ root, rfl⟩)) + rw [← same] + exact global.rows_execute programValid valid functionsQueried bytesQueried member active (same ▸ shape) + +end Aiur.AIR + +namespace Aiur.BoundVerifier + +open AIR Bytecode.AIR + +theorem Backend.root_lookupShape {selection : Selection} (backend : Backend selection) + (input : Array G) (arity : input.size = selection.inputSize) : + Call.LookupShape backend.compiled.bytecode ⟨selection.function, input, selection.success, 0⟩ := + ⟨backend.entry, backend.present, backend.constrained, backend.arity.trans arity.symm, + backend.returnArity⟩ + +theorem claim_padding (selection : Selection) + (width : Nat) (input : Array G) : + padMessage width (functionMessage ⟨selection.function, input, selection.success, 0⟩) = + padMessage width (buildClaim selection.function input selection.success).toList := by + have encoding : functionMessage ⟨selection.function, input, selection.success, 0⟩ = + (buildClaim selection.function input selection.success).toList ++ [0] := by + simp only [functionMessage, buildClaim, Array.toList_append, List.cons_append, + List.nil_append, functionChannel] + rfl + rw [encoding] + exact padMessage_append_zero _ + +/-- The selected success request has a finite AIR execution once its local +row and mixed lookup obligations are discharged. This is still conditional +on those obligations, not a theorem about public verifier acceptance. -/ +theorem Backend.global_execution {selection : Selection} (backend : Backend selection) + {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) {memory : Memory} + (input : Array G) (arity : input.size = selection.inputSize) + (valid : ∀ row ∈ tables.functions, row.Valid backend.compiled.bytecode memory) + (functionsQueried : (functionQueries [⟨selection.function, input, selection.success, 0⟩] + tables.functions).map functionMessage ⊆ queries) + (bytesQueried : (functionByteQueries tables.functions).map rangeMessage ⊆ queries) : + Execution backend.compiled.bytecode memory ⟨selection.function, input, selection.success, 0⟩ := + global.roots_execute backend.lookupShapes valid functionsQueried bytesQueried + (backend.root_lookupShape input arity) List.mem_cons_self + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/GoldilocksAlgebra.lean b/Ix/Aiur/Proofs/GoldilocksAlgebra.lean new file mode 100644 index 000000000..3e488d9f0 --- /dev/null +++ b/Ix/Aiur/Proofs/GoldilocksAlgebra.lean @@ -0,0 +1,157 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FrontendExpressions +import Init.GrindInstances.Ring.Fin +import Batteries.Tactic.OpenPrivate + +/-! Ring operations for the actual canonical Goldilocks representation. +The residue map proves the laws without changing the runtime operations. +Natural powers in the ring instance are the mathematical recursive powers; +the existing bounded repeated-squaring routine has a separate specification. +-/ + +namespace Aiur.G + +open Fin.NatCast Fin.IntCast +open private Aiur.G.pow.go from Ix.Aiur.Goldilocks + +instance characteristicNeZero : NeZero gSize.toNat := ⟨by decide⟩ + +def residue (value : G) : Fin gSize.toNat := + ⟨value.n, UInt64.lt_iff_toNat_lt.mp value.property⟩ + +theorem residue_injective {a b : G} (equal : residue a = residue b) : a = b := by + have numeric := congrArg (fun x : Fin gSize.toNat => x.val) equal + exact G.ext_n numeric + +theorem residue_ofNat (n : Nat) : residue (G.ofNat n) = Fin.ofNat _ n := by + apply Fin.ext + exact G.n_ofNat n + +theorem residue_add (a b : G) : residue (a + b) = residue a + residue b := by + apply Fin.ext + exact G.n_add a b + +theorem residue_mul (a b : G) : residue (a * b) = residue a * residue b := by + apply Fin.ext + exact G.n_mul a b + +theorem residue_sub (a b : G) : residue (a - b) = residue a - residue b := by + apply Fin.ext + simp only [Fin.sub_def, residue] + rw [G.n_sub, Nat.add_sub_assoc (Nat.le_of_lt (UInt64.lt_iff_toNat_lt.mp b.property)), Nat.add_comm] + +instance neg : Neg G := ⟨(0 - ·)⟩ +instance natCast : NatCast G := ⟨G.ofNat⟩ + +def ofInt : Int → G + | .ofNat n => G.ofNat n + | .negSucc n => -G.ofNat (n + 1) + +instance intCast : IntCast G := ⟨ofInt⟩ +instance nsmul : SMul Nat G := ⟨fun n a => G.ofNat n * a⟩ +instance zsmul : SMul Int G := ⟨fun n a => ofInt n * a⟩ +instance npow : HPow G Nat G := ⟨fun a n => npowRec n a⟩ + +theorem residue_numeral (n : Nat) : residue (OfNat.ofNat n : G) = OfNat.ofNat n := + residue_ofNat n + +theorem residue_zero : residue 0 = 0 := rfl +theorem residue_one : residue 1 = 1 := rfl + +theorem residue_neg (a : G) : residue (-a) = -residue a := by + change residue (0 - a) = -residue a + rw [residue_sub, residue_numeral] + grind + +theorem residue_ofInt (n : Int) : residue (ofInt n) = Int.cast n := by + cases n with + | ofNat n => exact residue_ofNat n + | negSucc n => + change residue (-G.ofNat (n + 1)) = Int.cast (Int.negSucc n) + rw [residue_neg, residue_ofNat] + rfl + +theorem left_distrib (a b c : G) : a * (b + c) = a * b + a * c := by + apply residue_injective + simp only [residue_add, residue_mul] + grind + +theorem neg_add_cancel (a : G) : -a + a = 0 := by + apply residue_injective + simp only [residue_add, residue_neg, residue_zero] + grind + +theorem sub_eq_add_neg (a b : G) : a - b = a + -b := by + apply residue_injective + simp only [residue_sub, residue_add, residue_neg] + grind + +theorem ofInt_neg (n : Int) : ofInt (-n) = -ofInt n := by + apply residue_injective + simp only [residue_ofInt, residue_neg] + exact Lean.Grind.Ring.intCast_neg n + +theorem neg_mul (a b : G) : -a * b = -(a * b) := by + apply residue_injective + simp only [residue_mul, residue_neg] + grind + +instance commRing : Lean.Grind.CommRing G where + add_zero := G.add_zero + add_comm := G.add_comm + add_assoc := G.add_assoc + mul_assoc := G.mul_assoc + mul_comm := G.mul_comm + mul_one := G.mul_one + left_distrib := left_distrib + zero_mul a := by rw [G.mul_comm, G.mul_zero] + mul_zero := G.mul_zero + pow_zero _ := rfl + pow_succ _ _ := rfl + ofNat_succ n := G.ofNat_add n 1 + neg_add_cancel := neg_add_cancel + sub_eq_add_neg := sub_eq_add_neg + intCast_neg := ofInt_neg + neg_zsmul n a := by + change ofInt (-n) * a = -(ofInt n * a) + rw [ofInt_neg, neg_mul] + +theorem pow_go_eq (a : G) (n fuel : Nat) (bounded : n < 2 ^ fuel) : + Aiur.G.pow.go a n fuel = a ^ n := by + induction fuel generalizing n with + | zero => + have zero : n = 0 := by simpa using bounded + subst n + rfl + | succ fuel ih => + by_cases zero : n = 0 + · subst n + rfl + · have half : n / 2 < 2 ^ fuel := + (Nat.div_lt_iff_lt_mul (by decide)).mpr (by simpa only [Nat.pow_succ] using bounded) + simp only [Aiur.G.pow.go, beq_iff_eq, if_neg zero, ih _ half] + by_cases even : n % 2 = 0 + · rw [if_pos even, ← Lean.Grind.Semiring.pow_add] + congr 1 + omega + · rw [if_neg even, ← Lean.Grind.Semiring.pow_add, ← Lean.Grind.Semiring.pow_succ] + congr 1 + omega + +theorem pow_eq (a : G) (n : Nat) (bounded : n < 2 ^ 64) : G.pow a n = a ^ n := + pow_go_eq a n 64 bounded + +theorem inverse_eq_power (a : G) : G.inverse a = a ^ (gSize.toNat - 2) := + pow_eq a _ (by decide) + +theorem n_power (a : G) (n : Nat) : (a ^ n).n = a.n ^ n % gSize.toNat := by + induction n with + | zero => rfl + | succ n ih => + rw [Lean.Grind.Semiring.pow_succ, G.n_mul, ih, Nat.mod_mul_mod, Nat.pow_succ] + +end Aiur.G diff --git a/Ix/Aiur/Proofs/GoldilocksInverse.lean b/Ix/Aiur/Proofs/GoldilocksInverse.lean new file mode 100644 index 000000000..4bca3ea94 --- /dev/null +++ b/Ix/Aiur/Proofs/GoldilocksInverse.lean @@ -0,0 +1,137 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.GoldilocksAlgebra +import Ix.Aiur.Proofs.Field + +/-! Fermat's theorem for the actual Goldilocks representation. Multiplication +by a nonzero element permutes the finite list of nonzero residues. Cancelling +its nonzero product proves the exponent identity and the runtime inverse law. +The argument is symbolic; the list of field elements is never evaluated. +-/ + +namespace Aiur.G + +theorem mul_right_cancel {a b c : G} (nonzero : c ≠ 0) (equal : a * c = b * c) : a = b := by + have zero : (a - b) * c = 0 := by grind + have same := (G.mul_eq_zero_iff _ _).mp zero |>.resolve_right nonzero + exact (G.sub_eq_zero_iff a b).mp same + +/-- A mathematical enumeration, excluded from runtime initialization. -/ +noncomputable def nonzeroResidues : List G := + List.ofFn fun index : Fin (gSize.toNat - 1) => G.ofNat (index.val + 1) + +theorem nonzeroResidues_length : nonzeroResidues.length = gSize.toNat - 1 := List.length_ofFn + +theorem mem_nonzeroResidues (a : G) : a ∈ nonzeroResidues ↔ a ≠ 0 := by + constructor + · intro member + obtain ⟨index, rfl⟩ := List.mem_ofFn.mp member + apply G.ofNat_ne_zero_of_lt (by omega) + have bound := index.isLt + omega + · intro nonzero + have positive : 0 < a.n := Nat.pos_of_ne_zero fun equal => nonzero ((G.n_eq_zero_iff a).mp equal) + have bounded := UInt64.lt_iff_toNat_lt.mp a.property + change a.n < gSize.toNat at bounded + apply List.mem_ofFn.mpr + refine ⟨⟨a.n - 1, by omega⟩, ?_⟩ + change G.ofNat (a.n - 1 + 1) = a + rw [Nat.sub_add_cancel positive, G.ofNat_n] + +theorem nonzeroResidues_nodup : nonzeroResidues.Nodup := by + apply List.pairwise_iff_getElem.mpr + intro i j hi hj lt same + simp only [nonzeroResidues, List.getElem_ofFn] at same + have bi : i < gSize.toNat - 1 := by simpa only [nonzeroResidues_length] using hi + have bj : j < gSize.toNat - 1 := by simpa only [nonzeroResidues_length] using hj + have equal := G.ofNat_injective_below (by omega : i + 1 < gSize.toNat) + (by omega : j + 1 < gSize.toNat) same + omega + +theorem map_perm_of_injective (values : List G) (f : G → G) (nodup : values.Nodup) + (injective : ∀ {x y}, f x = f y → x = y) (subset : values.map f ⊆ values) : + (values.map f).Perm values := by + have distinct : (values.map f).Nodup := + List.Pairwise.map f (fun _ _ different equal => different (injective equal)) nodup + apply (List.perm_ext_iff_of_nodup distinct nodup).mpr + intro value + constructor + · exact fun member => subset member + · intro member + by_cases included : value ∈ values.map f + · exact included + · have enlarged : (value :: values.map f).Nodup := + List.nodup_cons.mpr ⟨included, distinct⟩ + have bound := enlarged.length_le_of_subset (l₂ := values) (by + intro x present + rcases List.mem_cons.mp present with equal | tail + · exact equal ▸ member + · exact subset tail) + simp only [List.length_cons, List.length_map] at bound + omega + +theorem multiplication_perm (a : G) (nonzero : a ≠ 0) : + (nonzeroResidues.map (a * ·)).Perm nonzeroResidues := by + apply map_perm_of_injective nonzeroResidues (a * ·) nonzeroResidues_nodup + · intro x y equal + apply mul_right_cancel nonzero + simpa only [G.mul_comm _ a] using equal + · intro value member + obtain ⟨x, present, rfl⟩ := List.mem_map.mp member + apply (mem_nonzeroResidues _).mpr + intro zero + exact ((G.mul_eq_zero_iff _ _).mp zero).elim nonzero ((mem_nonzeroResidues x).mp present) + +def product : List G → G + | [] => 1 + | value :: values => value * product values + +theorem product_nonzero (values : List G) (nonzero : ∀ x ∈ values, x ≠ 0) : product values ≠ 0 := by + induction values with + | nil => exact G.one_ne_zero + | cons x xs ih => + intro zero + exact ((G.mul_eq_zero_iff _ _).mp zero).elim + (nonzero x List.mem_cons_self) + (ih (fun x member => nonzero x (List.mem_cons_of_mem _ member))) + +theorem product_perm {left right : List G} (permuted : left.Perm right) : product left = product right := by + induction permuted with + | nil => rfl + | cons x _ ih => simp only [product, ih] + | swap a b rest => simp only [product]; grind + | trans _ _ first second => exact first.trans second + +theorem product_map_mul (a : G) (values : List G) : + product (values.map (a * ·)) = a ^ values.length * product values := by + induction values with + | nil => rfl + | cons x xs ih => + simp only [List.map_cons, List.length_cons, product, ih, Lean.Grind.Semiring.pow_succ] + grind + +theorem power_eq_one_of_perm (a : G) (values : List G) + (nonzero : ∀ x ∈ values, x ≠ 0) (permuted : (values.map (a * ·)).Perm values) : + a ^ values.length = 1 := by + have same := product_perm permuted + rw [product_map_mul] at same + apply mul_right_cancel (product_nonzero values nonzero) + simpa only [Lean.Grind.Semiring.one_mul] using same + +theorem fermat (a : G) (nonzero : a ≠ 0) : a ^ (gSize.toNat - 1) = 1 := by + have same := power_eq_one_of_perm a nonzeroResidues + (fun x member => (mem_nonzeroResidues x).mp member) (multiplication_perm a nonzero) + simpa only [nonzeroResidues_length] using same + +theorem inverse_zero : G.inverse 0 = 0 := by decide +kernel + +theorem mul_inverse_cancel (a : G) (nonzero : a ≠ 0) : a * a.inverse = 1 := by + rw [G.inverse_eq_power, G.mul_comm, ← Lean.Grind.Semiring.pow_succ] + have successor : gSize.toNat - 2 + 1 = gSize.toNat - 1 := by decide + rw [successor] + exact fermat a nonzero + +end Aiur.G diff --git a/Ix/Aiur/Proofs/GraphCompilation.lean b/Ix/Aiur/Proofs/GraphCompilation.lean new file mode 100644 index 000000000..540580245 --- /dev/null +++ b/Ix/Aiur/Proofs/GraphCompilation.lean @@ -0,0 +1,757 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FrontendExpressions + +/-! +Value preservation for base expression graph compilation. A linear structural +interner models the native hash table's insertion order. Smart graph operators +fold constants, share nodes, sort commutative operands and cancel equal ids. +Successful compilation preserves earlier node values, constraint satisfaction, +and ordered lookup multiplicities and arguments. The required working algebra +laws are proved for Goldilocks. + +The model uses natural-number node indices. Native comparison checks actual +base graphs and compilation rejections. Rust execution and hash-table refinement, +machine bounds, extension-coordinate expansion, and cryptographic acceptance +remain separate obligations. +-/ + +namespace Aiur + +theorem G.sub_self (value : G) : value - value = 0 := by + apply G.ext_n + simp only [G.n_sub, show (0 : G).n = 0 from rfl] + rw [show value.n + gSize.toNat - value.n = gSize.toNat from by omega] + exact Nat.mod_self _ + +namespace NativeAIR + +structure GraphEvalLaws (ops : EvalOps W) : Prop extends EvalLaws ops where + add_comm : ∀ a b, ops.add a b = ops.add b a + mul_comm : ∀ a b, ops.mul a b = ops.mul b a + sub_self : ∀ a, ops.sub a a = ops.konst 0 + +theorem goldilocksGraphLaws : GraphEvalLaws goldilocksOps where + toEvalLaws := goldilocksLaws + add_comm := G.add_comm + mul_comm := G.mul_comm + sub_self := G.sub_self + +namespace Compiler + +def Extends (before after : Array W) : Prop := + ∀ (index : Nat) (value : W), before[index]? = some value → after[index]? = some value + +theorem Extends.refl (buffer : Array W) : Extends buffer buffer := fun _ _ read => read + +theorem Extends.trans {first second third : Array W} + (left : Extends first second) (right : Extends second third) : Extends first third := + fun index value read => right index value (left index value read) + +theorem Extends.push (buffer : Array W) (value : W) : Extends buffer (buffer.push value) := by + intro index old read + have bound := (Array.getElem?_eq_some_iff.mp read).1 + rw [Array.getElem?_push_lt bound, (Array.getElem?_eq_some_iff.mp read).2] + +theorem eval_extends (ops : EvalOps W) (values : Values W) {before after : Array W} + (growth : Extends before after) (node : Node) {value : W} + (evaluated : node.eval ops values before = some value) : + node.eval ops values after = some value := by + cases node <;> simp only [Node.eval] at evaluated ⊢ + all_goals try exact evaluated + case add a b | sub a b | mul a b => + cases ha : before[a]? <;> cases hb : before[b]? <;> + simp only [ha, hb, bind, Option.bind, pure, reduceCtorEq] at evaluated + all_goals + rename_i va vb + simpa only [growth a va ha, growth b vb hb, bind, Option.bind, pure] using evaluated + case neg a => + cases ha : before[a]? <;> + simp only [ha, bind, Option.bind, pure, reduceCtorEq] at evaluated + rename_i va + simpa only [growth a va ha, bind, Option.bind, pure] using evaluated + +structure Evaluation (ops : EvalOps W) (values : Values W) (nodes : List Node) + (buffer : Array W) : Prop where + size : buffer.size = nodes.length + sweep : sweepFrom ops values nodes #[] = some buffer + cached : ∀ (index : Nat) (node : Node), nodes[index]? = some node → node.eval ops values buffer = buffer[index]? + +theorem Evaluation.empty (ops : EvalOps W) (values : Values W) : + Evaluation ops values [] #[] := ⟨rfl, rfl, fun _ _ read => by cases read⟩ + +theorem Evaluation.push {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) (node : Node) (value : W) + (evaluated : node.eval ops values buffer = some value) : + Evaluation ops values (nodes ++ [node]) (buffer.push value) := by + refine ⟨by simp only [Array.size_push, List.length_append, List.length_singleton, valid.size], ?_, ?_⟩ + · simp only [sweepFrom_append, valid.sweep, sweepFrom, evaluated, bind, Option.bind] + · intro index old found + by_cases bound : index < nodes.length + · rw [List.getElem?_append_left bound] at found + have bnd : index < buffer.size := by rw [valid.size]; exact bound + have read := Array.getElem?_eq_getElem bnd + have oldEval := (valid.cached index old found).trans read + exact (eval_extends ops values (Extends.push buffer value) old oldEval).trans + (Array.getElem?_push_lt bnd).symm + · rw [List.getElem?_append_right (by omega)] at found + have pos : index = nodes.length := by + have bnd := (List.getElem?_eq_some_iff.mp found).1 + simp only [List.length_singleton] at bnd + omega + subst index + simp only [Nat.sub_self, List.getElem?_cons_zero, Option.some.injEq] at found + subst old + simpa only [← valid.size, Array.getElem?_push_size] using + eval_extends ops values (Extends.push buffer value) node evaluated + +def intern (nodes : List Node) (node : Node) : List Node × Nat := + match nodes.findIdx? (fun old => decide (old = node)) with + | some index => (nodes, index) + | none => (nodes ++ [node], nodes.length) + +def asConst (nodes : List Node) (index : Nat) : Option G := + match nodes[index]? with + | some (.konst value) => some value + | _ => none + +def Result (ops : EvalOps W) (values : Values W) (before : Array W) + (result : List Node × Nat) (value : W) : Prop := + ∃ after, Evaluation ops values result.1 after ∧ Extends before after ∧ after[result.2]? = some value + +theorem result_same {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {index : Nat} {value : W} + (read : buffer[index]? = some value) : Result ops values buffer (nodes, index) value := + ⟨buffer, valid, Extends.refl buffer, read⟩ + +theorem intern_reflects {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) (node : Node) {value : W} + (evaluated : node.eval ops values buffer = some value) : + Result ops values buffer (intern nodes node) value := by + unfold intern + split + next index found => + obtain ⟨bound, equal, _⟩ := List.findIdx?_eq_some_iff_getElem.mp found + simp only [decide_eq_true_eq] at equal + have nodeRead : nodes[index]? = some node := by rw [List.getElem?_eq_getElem bound, equal] + exact result_same valid ((valid.cached index node nodeRead).symm.trans evaluated) + next => + exact ⟨buffer.push value, valid.push node value evaluated, Extends.push buffer value, + by simp only [← valid.size, Array.getElem?_push_size]⟩ + +theorem asConst_reflects {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {index : Nat} {constant : G} + (found : asConst nodes index = some constant) : buffer[index]? = some (ops.konst constant) := by + unfold asConst at found + split at found + next value nodeRead => + cases found + exact (valid.cached index (.konst constant) nodeRead).symm + next => cases found + +theorem asConst_value {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {index : Nat} {constant : G} {value : W} + (found : asConst nodes index = some constant) (read : buffer[index]? = some value) : + value = ops.konst constant := Option.some.inj (read.symm.trans (asConst_reflects valid found)) + +def neg (nodes : List Node) (a : Nat) : List Node × Nat := + match asConst nodes a with + | some value => intern nodes (.konst (0 - value)) + | none => match nodes[a]? with + | some (.neg inner) => (nodes, inner) + | _ => intern nodes (.neg a) + +def sortedAdd (nodes : List Node) (a b : Nat) : List Node × Nat := + intern nodes (if a ≤ b then .add a b else .add b a) + +def sortedMul (nodes : List Node) (a b : Nat) : List Node × Nat := + intern nodes (if a ≤ b then .mul a b else .mul b a) + +def add (nodes : List Node) (a b : Nat) : List Node × Nat := + match asConst nodes a, asConst nodes b with + | some x, some y => intern nodes (.konst (x + y)) + | some x, none => if x == 0 then (nodes, b) else sortedAdd nodes a b + | none, some y => if y == 0 then (nodes, a) else sortedAdd nodes a b + | none, none => sortedAdd nodes a b + +def sub (nodes : List Node) (a b : Nat) : List Node × Nat := + if a = b then intern nodes (.konst 0) else + match asConst nodes a, asConst nodes b with + | some x, some y => intern nodes (.konst (x - y)) + | none, some y => if y == 0 then (nodes, a) else intern nodes (.sub a b) + | some x, none => if x == 0 then neg nodes b else intern nodes (.sub a b) + | none, none => intern nodes (.sub a b) + +def mul (nodes : List Node) (a b : Nat) : List Node × Nat := + match asConst nodes a, asConst nodes b with + | some x, some y => intern nodes (.konst (x * y)) + | some x, none => if x == 0 then (nodes, a) else if x == 1 then (nodes, b) else sortedMul nodes a b + | none, some y => if y == 0 then (nodes, b) else if y == 1 then (nodes, a) else sortedMul nodes a b + | none, none => sortedMul nodes a b + +theorem konst_reflects {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) (value : G) : + Result ops values buffer (intern nodes (.konst value)) (ops.konst value) := + intern_reflects valid (.konst value) rfl + +theorem neg_reflects {ops : EvalOps W} (laws : EvalLaws ops) + {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {a : Nat} {value : W} + (read : buffer[a]? = some value) : Result ops values buffer (neg nodes a) (ops.neg value) := by + unfold neg + split + next constant found => + rw [asConst_value valid found read, ← laws.konst_neg] + exact konst_reflects valid _ + next => + split + next inner found => + have evaluated := (valid.cached a (.neg inner) found).trans read + cases innerRead : buffer[inner]? with + | none => simp only [Node.eval, innerRead, bind, Option.bind, reduceCtorEq] at evaluated + | some child => + simp only [Node.eval, innerRead, bind, Option.bind, pure, Option.some.injEq] at evaluated + rw [← evaluated, laws.neg_neg] + exact result_same valid innerRead + next => + exact intern_reflects valid (.neg a) (by simp only [Node.eval, read, bind, Option.bind, pure]) + +theorem sortedAdd_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {a b : Nat} {left right : W} + (leftRead : buffer[a]? = some left) (rightRead : buffer[b]? = some right) : + Result ops values buffer (sortedAdd nodes a b) (ops.add left right) := by + unfold sortedAdd + split <;> apply intern_reflects valid <;> + simp only [Node.eval, leftRead, rightRead, bind, Option.bind, pure] + exact congrArg some (laws.add_comm right left) + +theorem sortedMul_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {a b : Nat} {left right : W} + (leftRead : buffer[a]? = some left) (rightRead : buffer[b]? = some right) : + Result ops values buffer (sortedMul nodes a b) (ops.mul left right) := by + unfold sortedMul + split <;> apply intern_reflects valid <;> + simp only [Node.eval, leftRead, rightRead, bind, Option.bind, pure] + exact congrArg some (laws.mul_comm right left) + +theorem add_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {a b : Nat} {left right : W} + (leftRead : buffer[a]? = some left) (rightRead : buffer[b]? = some right) : + Result ops values buffer (add nodes a b) (ops.add left right) := by + cases ha : asConst nodes a <;> cases hb : asConst nodes b + all_goals simp only [add, ha, hb] + · exact sortedAdd_reflects laws valid leftRead rightRead + · rename_i y + split + next zero => + have zero : y = 0 := beq_iff_eq.mp zero + rw [asConst_value valid hb rightRead, zero, laws.add_zero] + exact result_same valid leftRead + next => exact sortedAdd_reflects laws valid leftRead rightRead + · rename_i x + split + next zero => + have zero : x = 0 := beq_iff_eq.mp zero + rw [asConst_value valid ha leftRead, zero, laws.zero_add] + exact result_same valid rightRead + next => exact sortedAdd_reflects laws valid leftRead rightRead + · rw [asConst_value valid ha leftRead, asConst_value valid hb rightRead, ← laws.konst_add] + exact konst_reflects valid _ + +theorem sub_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {a b : Nat} {left right : W} + (leftRead : buffer[a]? = some left) (rightRead : buffer[b]? = some right) : + Result ops values buffer (sub nodes a b) (ops.sub left right) := by + have raw : Result ops values buffer (intern nodes (.sub a b)) (ops.sub left right) := + intern_reflects valid (.sub a b) (by simp only [Node.eval, leftRead, rightRead, bind, Option.bind, pure]) + unfold sub + split + next equal => + subst b + have equal := Option.some.inj (leftRead.symm.trans rightRead) + rw [equal, laws.sub_self] + exact konst_reflects valid _ + next => + cases ha : asConst nodes a <;> cases hb : asConst nodes b + all_goals dsimp only + · exact raw + · rename_i y + split + next zero => + have zero : y = 0 := beq_iff_eq.mp zero + rw [asConst_value valid hb rightRead, zero, laws.sub_zero] + exact result_same valid leftRead + next => exact raw + · rename_i x + split + next zero => + have zero : x = 0 := beq_iff_eq.mp zero + rw [asConst_value valid ha leftRead, zero, laws.zero_sub] + exact neg_reflects laws.toEvalLaws valid rightRead + next => exact raw + · rw [asConst_value valid ha leftRead, asConst_value valid hb rightRead, ← laws.konst_sub] + exact konst_reflects valid _ + +theorem mul_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {a b : Nat} {left right : W} + (leftRead : buffer[a]? = some left) (rightRead : buffer[b]? = some right) : + Result ops values buffer (mul nodes a b) (ops.mul left right) := by + cases ha : asConst nodes a <;> cases hb : asConst nodes b + all_goals simp only [mul, ha, hb] + · exact sortedMul_reflects laws valid leftRead rightRead + · rename_i y + split + next zero => + have zero : y = 0 := beq_iff_eq.mp zero + rw [asConst_value valid hb rightRead, zero, laws.mul_zero] + exact result_same valid (by simpa only [zero] using asConst_reflects valid hb) + next => + split + next one => + have one : y = 1 := beq_iff_eq.mp one + rw [asConst_value valid hb rightRead, one, laws.mul_one] + exact result_same valid leftRead + next => exact sortedMul_reflects laws valid leftRead rightRead + · rename_i x + split + next zero => + have zero : x = 0 := beq_iff_eq.mp zero + rw [asConst_value valid ha leftRead, zero, laws.zero_mul] + exact result_same valid (by simpa only [zero] using asConst_reflects valid ha) + next => + split + next one => + have one : x = 1 := beq_iff_eq.mp one + rw [asConst_value valid ha leftRead, one, laws.one_mul] + exact result_same valid rightRead + next => exact sortedMul_reflects laws valid leftRead rightRead + · rw [asConst_value valid ha leftRead, asConst_value valid hb rightRead, ← laws.konst_mul] + exact konst_reflects valid _ + +def compileExpr (widths : GraphWidths) (allowStage2 : Bool) : Expr → List Node → Option (List Node × Nat) + | .konst value, nodes => some (intern nodes (.konst value)) + | .var column, nodes => + if (column.source != .stage2 || allowStage2) && column.index < widths.width column.source then + some (intern nodes (.var column)) + else none + | .publicInput index, nodes => + if index < widths.publics then some (intern nodes (.publicInput index)) else none + | .isFirstRow, nodes => some (intern nodes .isFirstRow) + | .isLastRow, nodes => some (intern nodes .isLastRow) + | .isTransition, nodes => some (intern nodes .isTransition) + | .add left right, nodes => do + let (nodes, a) ← compileExpr widths allowStage2 left nodes + let (nodes, b) ← compileExpr widths allowStage2 right nodes + return add nodes a b + | .sub left right, nodes => do + let (nodes, a) ← compileExpr widths allowStage2 left nodes + let (nodes, b) ← compileExpr widths allowStage2 right nodes + return sub nodes a b + | .mul left right, nodes => do + let (nodes, a) ← compileExpr widths allowStage2 left nodes + let (nodes, b) ← compileExpr widths allowStage2 right nodes + return mul nodes a b + | .neg child, nodes => do + let (nodes, a) ← compileExpr widths allowStage2 child nodes + return neg nodes a + +theorem result_prepend {ops : EvalOps W} {values : Values W} {before middle : Array W} + (growth : Extends before middle) {result : List Node × Nat} {value : W} + (reflected : Result ops values middle result value) : Result ops values before result value := by + obtain ⟨after, valid, rest, read⟩ := reflected + exact ⟨after, valid, growth.trans rest, read⟩ + +theorem compileExpr_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (allowStage2 : Bool) (expr : Expr) {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {result : List Node × Nat} + (compiled : compileExpr widths allowStage2 expr nodes = some result) : + ∃ value, expr.eval ops values = some value ∧ Result ops values buffer result value := by + induction expr generalizing nodes buffer result with + | konst value => + cases compiled + exact ⟨_, rfl, konst_reflects valid value⟩ + | var column => + simp only [compileExpr] at compiled + split at compiled + next accepted => + cases compiled + have bound : column.index < (values.columns column.source column.offset).size := by + rw [fits.1] + simp only [Bool.and_eq_true, decide_eq_true_eq] at accepted + exact accepted.2 + have read := Array.getElem?_eq_getElem bound + exact ⟨_, read, intern_reflects valid (.var column) read⟩ + next => cases compiled + | publicInput index => + simp only [compileExpr] at compiled + split at compiled + next bound => + cases compiled + have bound : index < values.publics.size := by rw [fits.2]; exact bound + have read := Array.getElem?_eq_getElem bound + exact ⟨_, read, intern_reflects valid (.publicInput index) read⟩ + next => cases compiled + | isFirstRow | isLastRow | isTransition => + cases compiled + exact ⟨_, rfl, intern_reflects valid _ rfl⟩ + | add left right ihLeft ihRight | sub left right ihLeft ihRight | mul left right ihLeft ihRight => + simp only [compileExpr] at compiled + cases leftCompiled : compileExpr widths allowStage2 left nodes with + | none => simp only [leftCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some leftResult => + cases rightCompiled : compileExpr widths allowStage2 right leftResult.1 with + | none => simp only [leftCompiled, rightCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some rightResult => + simp only [leftCompiled, rightCompiled, bind, Option.bind, pure, Option.some.injEq] at compiled + subst result + obtain ⟨leftValue, leftEval, leftBuffer, leftValid, leftGrowth, leftRead⟩ := ihLeft valid leftCompiled + obtain ⟨rightValue, rightEval, rightBuffer, rightValid, rightGrowth, rightRead⟩ := ihRight leftValid rightCompiled + simp only [Expr.eval, leftEval, rightEval, bind, Option.bind, pure, Option.some.injEq] + refine ⟨_, rfl, result_prepend (leftGrowth.trans rightGrowth) ?_⟩ + first + | exact add_reflects laws rightValid (rightGrowth _ _ leftRead) rightRead + | exact sub_reflects laws rightValid (rightGrowth _ _ leftRead) rightRead + | exact mul_reflects laws rightValid (rightGrowth _ _ leftRead) rightRead + | neg child ih => + simp only [compileExpr] at compiled + cases childCompiled : compileExpr widths allowStage2 child nodes with + | none => simp only [childCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some childResult => + simp only [childCompiled, bind, Option.bind, pure, Option.some.injEq] at compiled + subst result + obtain ⟨value, evaluated, childBuffer, childValid, growth, read⟩ := ih valid childCompiled + exact ⟨ops.neg value, by simp only [Expr.eval, evaluated, bind, Option.bind, pure], + result_prepend growth (neg_reflects laws.toEvalLaws childValid read)⟩ + +theorem compileExpr_sweep {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (allowStage2 : Bool) (expr : Expr) {result : List Node × Nat} + (compiled : compileExpr widths allowStage2 expr [] = some result) : + ∃ buffer, sweepFrom ops values result.1 #[] = some buffer ∧ + buffer[result.2]? = expr.eval ops values := by + obtain ⟨value, evaluated, buffer, valid, _, read⟩ := + compileExpr_reflects laws fits allowStage2 expr (Evaluation.empty ops values) compiled + exact ⟨buffer, valid.sweep, read.trans evaluated.symm⟩ + +def compileExprs (widths : GraphWidths) (allowStage2 : Bool) : + List Expr → List Node → Option (List Node × List Nat) + | [], nodes => some (nodes, []) + | expr :: exprs, nodes => do + let (nodes, root) ← compileExpr widths allowStage2 expr nodes + let (nodes, roots) ← compileExprs widths allowStage2 exprs nodes + return (nodes, root :: roots) + +inductive RootsReflect (ops : EvalOps W) (values : Values W) (buffer : Array W) : + List Nat → List Expr → Prop where + | nil : RootsReflect ops values buffer [] [] + | cons {root : Nat} {expr : Expr} {roots : List Nat} {exprs : List Expr} + (head : ∃ value, expr.eval ops values = some value ∧ buffer[root]? = some value) + (tail : RootsReflect ops values buffer roots exprs) : + RootsReflect ops values buffer (root :: roots) (expr :: exprs) + +theorem RootsReflect.grow {ops : EvalOps W} {values : Values W} {before after : Array W} + (growth : Extends before after) {roots : List Nat} {exprs : List Expr} + (reflected : RootsReflect ops values before roots exprs) : RootsReflect ops values after roots exprs := by + induction reflected with + | nil => exact .nil + | cons head _ ih => + obtain ⟨value, evaluated, read⟩ := head + exact .cons ⟨value, evaluated, growth _ _ read⟩ ih + +theorem compileExprs_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (allowStage2 : Bool) (exprs : List Expr) {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {result : List Node × List Nat} + (compiled : compileExprs widths allowStage2 exprs nodes = some result) : + ∃ after, Evaluation ops values result.1 after ∧ Extends buffer after ∧ + RootsReflect ops values after result.2 exprs := by + induction exprs generalizing nodes buffer result with + | nil => cases compiled; exact ⟨buffer, valid, Extends.refl buffer, .nil⟩ + | cons expr exprs ih => + simp only [compileExprs] at compiled + cases headCompiled : compileExpr widths allowStage2 expr nodes with + | none => simp only [headCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some headResult => + cases restCompiled : compileExprs widths allowStage2 exprs headResult.1 with + | none => simp only [headCompiled, restCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some restResult => + simp only [headCompiled, restCompiled, bind, Option.bind, pure, Option.some.injEq] at compiled + subst result + obtain ⟨value, evaluated, middle, middleValid, growth, read⟩ := + compileExpr_reflects laws fits allowStage2 expr valid headCompiled + obtain ⟨after, afterValid, restGrowth, reflected⟩ := ih middleValid restCompiled + exact ⟨after, afterValid, growth.trans restGrowth, .cons ⟨value, evaluated, restGrowth _ _ read⟩ reflected⟩ + +def evalExprs (ops : EvalOps W) (values : Values W) (exprs : List Expr) : Option (List W) := + exprs.mapM (Expr.eval ops values) + +theorem RootsReflect.read {ops : EvalOps W} {values : Values W} {buffer : Array W} + {roots : List Nat} {exprs : List Expr} (reflected : RootsReflect ops values buffer roots exprs) : + ∃ result, evalExprs ops values exprs = some result ∧ readNodes buffer roots = some result := by + induction reflected with + | nil => exact ⟨[], rfl, rfl⟩ + | cons head _ ih => + obtain ⟨value, evaluated, read⟩ := head + obtain ⟨rest, restEval, restRead⟩ := ih + refine ⟨value :: rest, ?_, ?_⟩ + · simp only [evalExprs, List.mapM_cons, evaluated, bind, Option.bind] + change (evalExprs ops values _).bind _ = _ + rw [restEval]; rfl + · simp only [readNodes, List.mapM_cons, read, bind, Option.bind] + change (readNodes buffer _).bind _ = _ + rw [restRead]; rfl + +structure ExprLookup where + multiplicity : Expr + args : List Expr + deriving DecidableEq, Repr + +def ExprLookup.exprs (lookup : ExprLookup) : List Expr := lookup.multiplicity :: lookup.args + +def ExprLookup.eval (ops : EvalOps W) (values : Values W) (lookup : ExprLookup) : Option (W × List W) := do + let multiplicity ← lookup.multiplicity.eval ops values + let args ← evalExprs ops values lookup.args + return (multiplicity, args) + +def compileLookup (widths : GraphWidths) (lookup : ExprLookup) (nodes : List Node) : + Option (List Node × Lookup) := do + let (nodes, roots) ← compileExprs widths false lookup.exprs nodes + match roots with + | [] => none + | root :: roots => return (nodes, ⟨root, roots⟩) + +theorem compileLookup_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (lookup : ExprLookup) {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {result : List Node × Lookup} + (compiled : compileLookup widths lookup nodes = some result) : + ∃ after, Evaluation ops values result.1 after ∧ Extends buffer after ∧ + RootsReflect ops values after result.2.roots lookup.exprs := by + simp only [compileLookup] at compiled + cases exprsCompiled : compileExprs widths false lookup.exprs nodes with + | none => simp only [exprsCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some rootsResult => + obtain ⟨after, afterValid, growth, reflected⟩ := compileExprs_reflects laws fits false lookup.exprs valid exprsCompiled + cases rootsResult with + | mk nodes roots => + cases roots with + | nil => simp only [exprsCompiled, bind, Option.bind, reduceCtorEq] at compiled + | cons root roots => + simp only [exprsCompiled, bind, Option.bind, pure, Option.some.injEq] at compiled + subst result + exact ⟨after, afterValid, growth, reflected⟩ + +theorem RootsReflect.readLookup {ops : EvalOps W} {values : Values W} {buffer : Array W} + {lookup : Lookup} {exprs : ExprLookup} + (reflected : RootsReflect ops values buffer lookup.roots exprs.exprs) : + ∃ read, exprs.eval ops values = some read ∧ readLookup buffer lookup = some read := by + cases reflected with + | cons head tail => + obtain ⟨multiplicity, multiplicityEval, multiplicityRead⟩ := head + obtain ⟨args, argsEval, argsRead⟩ := RootsReflect.read tail + exact ⟨(multiplicity, args), + by simp only [ExprLookup.eval, multiplicityEval, argsEval, bind, Option.bind, pure], + by simp only [Aiur.NativeAIR.readLookup, multiplicityRead, argsRead, bind, Option.bind, pure]⟩ + +def compileLookups (widths : GraphWidths) : List ExprLookup → List Node → Option (List Node × List Lookup) + | [], nodes => some (nodes, []) + | lookup :: lookups, nodes => do + let (nodes, root) ← compileLookup widths lookup nodes + let (nodes, roots) ← compileLookups widths lookups nodes + return (nodes, root :: roots) + +inductive LookupsReflect (ops : EvalOps W) (values : Values W) (buffer : Array W) : + List Lookup → List ExprLookup → Prop where + | nil : LookupsReflect ops values buffer [] [] + | cons {lookup : Lookup} {expr : ExprLookup} {lookups : List Lookup} {exprs : List ExprLookup} + (head : RootsReflect ops values buffer lookup.roots expr.exprs) + (tail : LookupsReflect ops values buffer lookups exprs) : + LookupsReflect ops values buffer (lookup :: lookups) (expr :: exprs) + +theorem LookupsReflect.grow {ops : EvalOps W} {values : Values W} {before after : Array W} + (growth : Extends before after) {lookups : List Lookup} {exprs : List ExprLookup} + (reflected : LookupsReflect ops values before lookups exprs) : LookupsReflect ops values after lookups exprs := by + induction reflected with + | nil => exact .nil + | cons head _ ih => exact .cons (head.grow growth) ih + +theorem compileLookups_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (lookups : List ExprLookup) {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {result : List Node × List Lookup} + (compiled : compileLookups widths lookups nodes = some result) : + ∃ after, Evaluation ops values result.1 after ∧ Extends buffer after ∧ + LookupsReflect ops values after result.2 lookups := by + induction lookups generalizing nodes buffer result with + | nil => cases compiled; exact ⟨buffer, valid, Extends.refl buffer, .nil⟩ + | cons lookup lookups ih => + simp only [compileLookups] at compiled + cases headCompiled : compileLookup widths lookup nodes with + | none => simp only [headCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some headResult => + cases restCompiled : compileLookups widths lookups headResult.1 with + | none => simp only [headCompiled, restCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some restResult => + simp only [headCompiled, restCompiled, bind, Option.bind, pure, Option.some.injEq] at compiled + subst result + obtain ⟨middle, middleValid, growth, reflected⟩ := compileLookup_reflects laws fits lookup valid headCompiled + obtain ⟨after, afterValid, restGrowth, restReflected⟩ := ih middleValid restCompiled + exact ⟨after, afterValid, growth.trans restGrowth, .cons (reflected.grow restGrowth) restReflected⟩ + +def recordZero (nodes : List Node) (root : Nat) : Option (List Nat) := + match asConst nodes root with + | none => some [root] + | some value => if value == 0 then some [] else none + +def Vanishes (ops : EvalOps W) (buffer : Array W) (roots : List Nat) : Prop := + ∀ root ∈ roots, buffer[root]? = some (ops.konst 0) + +def ExprsVanish (ops : EvalOps W) (values : Values W) (exprs : List Expr) : Prop := + ∀ expr ∈ exprs, expr.eval ops values = some (ops.konst 0) + +theorem recordZero_reflects {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer after : Array W} + (valid : Evaluation ops values nodes buffer) (growth : Extends buffer after) {root : Nat} {value : W} + (read : buffer[root]? = some value) {roots : List Nat} (recorded : recordZero nodes root = some roots) : + Vanishes ops after roots ↔ value = ops.konst 0 := by + unfold recordZero at recorded + cases found : asConst nodes root with + | none => + simp only [found, Option.some.injEq] at recorded + subst roots + simp only [Vanishes, List.mem_singleton, forall_eq, growth root value read, Option.some.injEq] + | some constant => + simp only [found] at recorded + split at recorded + next zero => + have zero : constant = 0 := beq_iff_eq.mp zero + cases recorded + rw [asConst_value valid found read, zero] + simp only [Vanishes, List.not_mem_nil, false_implies, forall_const, iff_self] + next => cases recorded + +theorem Vanishes.append (ops : EvalOps W) (buffer : Array W) (left right : List Nat) : + Vanishes ops buffer (left ++ right) ↔ Vanishes ops buffer left ∧ Vanishes ops buffer right := by + simp only [Vanishes, List.mem_append, or_imp, forall_and] + +theorem ExprsVanish.cons (ops : EvalOps W) (values : Values W) (head : Expr) (tail : List Expr) : + ExprsVanish ops values (head :: tail) ↔ head.eval ops values = some (ops.konst 0) ∧ ExprsVanish ops values tail := by + simp only [ExprsVanish, List.forall_mem_cons] + +def compileZeros (widths : GraphWidths) : List Expr → List Node → Option (List Node × List Nat) + | [], nodes => some (nodes, []) + | expr :: exprs, nodes => do + let (nodes, root) ← compileExpr widths false expr nodes + let head ← recordZero nodes root + let (nodes, roots) ← compileZeros widths exprs nodes + return (nodes, head ++ roots) + +theorem compileZeros_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (exprs : List Expr) {nodes : List Node} {buffer : Array W} + (valid : Evaluation ops values nodes buffer) {result : List Node × List Nat} + (compiled : compileZeros widths exprs nodes = some result) : + ∃ after, Evaluation ops values result.1 after ∧ Extends buffer after ∧ + (Vanishes ops after result.2 ↔ ExprsVanish ops values exprs) := by + induction exprs generalizing nodes buffer result with + | nil => + cases compiled + exact ⟨buffer, valid, Extends.refl buffer, by constructor <;> intro _ _ member <;> cases member⟩ + | cons expr exprs ih => + simp only [compileZeros] at compiled + cases headCompiled : compileExpr widths false expr nodes with + | none => simp only [headCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some headResult => + cases recorded : recordZero headResult.1 headResult.2 with + | none => simp only [headCompiled, recorded, bind, Option.bind, reduceCtorEq] at compiled + | some headRoots => + cases restCompiled : compileZeros widths exprs headResult.1 with + | none => simp only [headCompiled, recorded, restCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some restResult => + simp only [headCompiled, recorded, restCompiled, bind, Option.bind, pure, Option.some.injEq] at compiled + subst result + obtain ⟨value, evaluated, middle, middleValid, growth, read⟩ := compileExpr_reflects laws fits false expr valid headCompiled + obtain ⟨after, afterValid, restGrowth, reflected⟩ := ih middleValid restCompiled + refine ⟨after, afterValid, growth.trans restGrowth, ?_⟩ + rw [Vanishes.append, recordZero_reflects middleValid restGrowth read recorded, reflected, + ExprsVanish.cons, evaluated, Option.some.injEq] + +def canonicalZeros (roots : List Nat) : List Nat := + (roots.mergeSort (· ≤ ·)).eraseDups + +theorem canonicalZeros_vanish (ops : EvalOps W) (buffer : Array W) (roots : List Nat) : + Vanishes ops buffer (canonicalZeros roots) ↔ Vanishes ops buffer roots := by + simp only [Vanishes, canonicalZeros, List.mem_eraseDups, List.mem_mergeSort] + +structure BaseCompilation where + graph : Graph + lookupEnd : Nat + deriving DecidableEq, Repr + +def compileBase (widths : GraphWidths) (lookups : List ExprLookup) (constraints : List Expr) : + Option BaseCompilation := do + let (lookupNodes, lookups) ← compileLookups widths lookups [] + let (nodes, zeros) ← compileZeros widths constraints lookupNodes + return ⟨⟨nodes, canonicalZeros zeros, lookups⟩, lookupNodes.length⟩ + +theorem compileBase_reflects {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (lookups : List ExprLookup) (constraints : List Expr) {result : BaseCompilation} + (compiled : compileBase widths lookups constraints = some result) : + ∃ buffer, result.graph.sweep ops values = some buffer ∧ + LookupsReflect ops values buffer result.graph.lookups lookups ∧ + (Vanishes ops buffer result.graph.zeros ↔ ExprsVanish ops values constraints) := by + simp only [compileBase] at compiled + cases lookupsCompiled : compileLookups widths lookups [] with + | none => simp only [lookupsCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some lookupResult => + cases zerosCompiled : compileZeros widths constraints lookupResult.1 with + | none => simp only [lookupsCompiled, zerosCompiled, bind, Option.bind, reduceCtorEq] at compiled + | some zeroResult => + simp only [lookupsCompiled, zerosCompiled, bind, Option.bind, pure, Option.some.injEq] at compiled + subst result + obtain ⟨middle, middleValid, _, lookupsReflected⟩ := + compileLookups_reflects laws fits lookups (Evaluation.empty ops values) lookupsCompiled + obtain ⟨buffer, bufferValid, growth, zerosReflected⟩ := + compileZeros_reflects laws fits constraints middleValid zerosCompiled + exact ⟨buffer, bufferValid.sweep, lookupsReflected.grow growth, + (canonicalZeros_vanish ops buffer zeroResult.2).trans zerosReflected⟩ + +theorem LookupsReflect.read {ops : EvalOps W} {values : Values W} {buffer : Array W} + {lookups : List Lookup} {exprs : List ExprLookup} + (reflected : LookupsReflect ops values buffer lookups exprs) : + ∃ result, exprs.mapM (ExprLookup.eval ops values) = some result ∧ + lookups.mapM (readLookup buffer) = some result := by + induction reflected with + | nil => exact ⟨[], rfl, rfl⟩ + | cons head _ ih => + obtain ⟨value, evaluated, read⟩ := head.readLookup + obtain ⟨rest, restEval, restRead⟩ := ih + exact ⟨value :: rest, + by simp only [List.mapM_cons, evaluated, restEval, bind, Option.bind, pure], + by simp only [List.mapM_cons, read, restRead, bind, Option.bind, pure]⟩ + +theorem compileBase_satisfaction {ops : EvalOps W} (laws : GraphEvalLaws ops) + {values : Values W} {widths : GraphWidths} (fits : values.Fits widths) + (lookups : List ExprLookup) (constraints : List Expr) {result : BaseCompilation} + (compiled : compileBase widths lookups constraints = some result) {buffer : Array W} + (swept : result.graph.sweep ops values = some buffer) : + (Vanishes ops buffer result.graph.zeros ↔ ExprsVanish ops values constraints) ∧ + result.graph.lookups.mapM (readLookup buffer) = lookups.mapM (ExprLookup.eval ops values) := by + obtain ⟨actual, actualSweep, lookupsReflected, zerosReflected⟩ := compileBase_reflects laws fits lookups constraints compiled + have equal := Option.some.inj (actualSweep.symm.trans swept) + subst actual + obtain ⟨reads, exprReads, graphReads⟩ := lookupsReflected.read + exact ⟨zerosReflected, graphReads.trans exprReads.symm⟩ + +end Compiler +end NativeAIR +end Aiur diff --git a/Ix/Aiur/Proofs/GraphCompletion.lean b/Ix/Aiur/Proofs/GraphCompletion.lean new file mode 100644 index 000000000..6a6aa3ce4 --- /dev/null +++ b/Ix/Aiur/Proofs/GraphCompletion.lean @@ -0,0 +1,162 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.GraphCompilation + +/-! Defined reads make expression and lookup compilation total. A satisfying +assignment also excludes the compiler's rejection of a nonzero constant +constraint. The latter requires an injective interpretation of constants. -/ + +namespace Aiur.NativeAIR.Compiler + +theorem compileExpr_defined {ops : EvalOps W} {values : Values W} {widths : GraphWidths} + (fits : values.Fits widths) (allowStage2 : Bool) (stage : widths.stage2 = 0 ∨ allowStage2 = true) + (expr : Expr) (nodes : List Node) {value : W} (evaluated : expr.eval ops values = some value) : + ∃ result, compileExpr widths allowStage2 expr nodes = some result := by + induction expr generalizing nodes value with + | konst constant => exact ⟨_, rfl⟩ + | var column => + have bound := (Array.getElem?_eq_some_iff.mp evaluated).choose + rw [fits.1] at bound + have enabled : (column.source != .stage2 || allowStage2) = true := by + rcases stage with empty | allowed + · cases source : column.source + · rfl + · rfl + · rw [source, GraphWidths.width, empty] at bound + omega + · simp only [allowed, Bool.or_true] + simp only [compileExpr, enabled, decide_eq_true bound, Bool.and_self, ite_true] + exact ⟨_, rfl⟩ + | publicInput index => + have bound := (Array.getElem?_eq_some_iff.mp evaluated).choose + rw [fits.2] at bound + simp only [compileExpr, bound, if_true] + exact ⟨_, rfl⟩ + | isFirstRow | isLastRow | isTransition => exact ⟨_, rfl⟩ + | add left right leftIH rightIH | sub left right leftIH rightIH | mul left right leftIH rightIH => + simp only [Expr.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i leftValue leftRead + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i rightValue rightRead + obtain ⟨middle, first⟩ := leftIH nodes leftRead + obtain ⟨result, last⟩ := rightIH middle.1 rightRead + simp only [compileExpr, first, last, bind, Option.bind_some, pure] + exact ⟨_, rfl⟩ + | neg child ih => + simp only [Expr.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i childValue childRead + obtain ⟨result, compiled⟩ := ih nodes childRead + simp only [compileExpr, compiled, bind, Option.bind_some, pure] + exact ⟨_, rfl⟩ + +theorem compileExprs_defined {ops : EvalOps W} {values : Values W} {widths : GraphWidths} + (fits : values.Fits widths) (allowStage2 : Bool) (stage : widths.stage2 = 0 ∨ allowStage2 = true) + (exprs : List Expr) (nodes : List Node) {results : List W} + (evaluated : evalExprs ops values exprs = some results) : + ∃ result, compileExprs widths allowStage2 exprs nodes = some result := by + induction exprs generalizing nodes results with + | nil => exact ⟨_, rfl⟩ + | cons expr exprs ih => + simp only [evalExprs, List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i value valueRead + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i rest restRead + obtain ⟨middle, first⟩ := compileExpr_defined fits allowStage2 stage expr nodes valueRead + obtain ⟨result, last⟩ := ih middle.1 restRead + simp only [compileExprs, first, last, bind, Option.bind_some, pure] + exact ⟨_, rfl⟩ + +theorem compileLookup_defined {ops : EvalOps W} {values : Values W} {widths : GraphWidths} + (fits : values.Fits widths) (stage : widths.stage2 = 0) (lookup : ExprLookup) (nodes : List Node) + {value : W × List W} (evaluated : lookup.eval ops values = some value) : + ∃ result, compileLookup widths lookup nodes = some result := by + simp only [ExprLookup.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i multiplicity weightRead + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i args argsRead + obtain ⟨middle, first⟩ := compileExpr_defined fits false (.inl stage) lookup.multiplicity nodes weightRead + obtain ⟨result, last⟩ := compileExprs_defined fits false (.inl stage) lookup.args middle.1 argsRead + simp only [compileLookup, ExprLookup.exprs, compileExprs, first, last, bind, Option.bind_some, pure] + exact ⟨_, rfl⟩ + +theorem compileLookups_defined {ops : EvalOps W} {values : Values W} {widths : GraphWidths} + (fits : values.Fits widths) (stage : widths.stage2 = 0) (lookups : List ExprLookup) (nodes : List Node) + {valuesRead : List (W × List W)} (evaluated : lookups.mapM (ExprLookup.eval ops values) = some valuesRead) : + ∃ result, compileLookups widths lookups nodes = some result := by + induction lookups generalizing nodes valuesRead with + | nil => exact ⟨_, rfl⟩ + | cons lookup lookups ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i value valueRead + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i rest restRead + obtain ⟨middle, first⟩ := compileLookup_defined fits stage lookup nodes valueRead + obtain ⟨result, last⟩ := ih middle.1 restRead + simp only [compileLookups, first, last, bind, Option.bind_some, pure] + exact ⟨_, rfl⟩ + +theorem recordZero_defined {ops : EvalOps W} {values : Values W} {nodes : List Node} {buffer : Array W} + (injective : Function.Injective ops.konst) (valid : Evaluation ops values nodes buffer) {root : Nat} + (read : buffer[root]? = some (ops.konst 0)) : ∃ roots, recordZero nodes root = some roots := by + unfold recordZero + cases found : asConst nodes root with + | none => exact ⟨_, rfl⟩ + | some constant => + have zero : constant = 0 := (injective (asConst_value valid found read)).symm + simp only [zero, beq_self_eq_true, if_true] + exact ⟨_, rfl⟩ + +theorem compileZeros_defined {ops : EvalOps W} (laws : GraphEvalLaws ops) + (injective : Function.Injective ops.konst) {values : Values W} {widths : GraphWidths} + (fits : values.Fits widths) (stage : widths.stage2 = 0) (exprs : List Expr) + {nodes : List Node} {buffer : Array W} (valid : Evaluation ops values nodes buffer) + (satisfied : ExprsVanish ops values exprs) : + ∃ result, compileZeros widths exprs nodes = some result := by + induction exprs generalizing nodes buffer with + | nil => exact ⟨_, rfl⟩ + | cons expr exprs ih => + have valueRead := satisfied expr List.mem_cons_self + obtain ⟨middle, compiled⟩ := compileExpr_defined fits false (.inl stage) expr nodes valueRead + obtain ⟨value, evaluated, after, afterValid, _, read⟩ := + compileExpr_reflects laws fits false expr valid compiled + have equal := Option.some.inj (evaluated.symm.trans valueRead) + rw [equal] at read + obtain ⟨roots, recorded⟩ := recordZero_defined injective afterValid read + obtain ⟨result, rest⟩ := ih afterValid (fun expr member => satisfied expr (List.mem_cons_of_mem _ member)) + simp only [compileZeros, compiled, recorded, rest, bind, Option.bind_some, pure] + exact ⟨_, rfl⟩ + +theorem compileBase_defined {ops : EvalOps W} (laws : GraphEvalLaws ops) + (injective : Function.Injective ops.konst) {values : Values W} {widths : GraphWidths} + (fits : values.Fits widths) (stage : widths.stage2 = 0) (lookups : List ExprLookup) (constraints : List Expr) + {valuesRead : List (W × List W)} (lookupsRead : lookups.mapM (ExprLookup.eval ops values) = some valuesRead) + (satisfied : ExprsVanish ops values constraints) : + ∃ result, compileBase widths lookups constraints = some result := by + obtain ⟨middle, compiled⟩ := compileLookups_defined fits stage lookups [] lookupsRead + obtain ⟨buffer, valid, _, _⟩ := compileLookups_reflects laws fits lookups (Evaluation.empty ops values) compiled + obtain ⟨result, zeros⟩ := compileZeros_defined laws injective fits stage constraints valid satisfied + simp only [compileBase, compiled, zeros, bind, Option.bind_some, pure] + exact ⟨_, rfl⟩ + +end Aiur.NativeAIR.Compiler diff --git a/Ix/Aiur/Proofs/GraphWidths.lean b/Ix/Aiur/Proofs/GraphWidths.lean new file mode 100644 index 000000000..76cfc8bc3 --- /dev/null +++ b/Ix/Aiur/Proofs/GraphWidths.lean @@ -0,0 +1,163 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CheckedCircuit + +/-! Additional columns do not change successful graph compilation. Widths +only guard variable reads; interning, folding and root order are preserved. +This lets physical function circuits use the complete native key widths. -/ + +namespace Aiur.NativeAIR + +def GraphWidths.Le (small large : GraphWidths) : Prop := + (∀ source, small.width source ≤ large.width source) ∧ small.publics ≤ large.publics + +namespace Compiler + +theorem compileExpr_widen {small large : GraphWidths} (widths : small.Le large) + (allowStage2 : Bool) (expr : Expr) {nodes : List Node} {result : List Node × Nat} + (compiled : compileExpr small allowStage2 expr nodes = some result) : + compileExpr large allowStage2 expr nodes = some result := by + induction expr generalizing nodes result with + | konst | isFirstRow | isLastRow | isTransition => exact compiled + | var column => + simp only [compileExpr] at compiled ⊢ + split at compiled + · rename_i valid + simp only [Bool.and_eq_true, decide_eq_true_eq] at valid + have bound := Nat.lt_of_lt_of_le valid.2 (widths.1 column.source) + simpa only [valid.1, bound, decide_true, Bool.true_and, if_true] using compiled + · cases compiled + | publicInput index => + simp only [compileExpr] at compiled ⊢ + split at compiled + · rename_i bound + simpa only [Nat.lt_of_lt_of_le bound widths.2, if_true] using compiled + · cases compiled + | add left right ihLeft ihRight | sub left right ihLeft ihRight | mul left right ihLeft ihRight => + cases leftBuilt : compileExpr small allowStage2 left nodes with + | none => simp only [compileExpr, leftBuilt, bind, Option.bind_none, reduceCtorEq] at compiled + | some leftResult => + cases rightBuilt : compileExpr small allowStage2 right leftResult.1 with + | none => simp only [compileExpr, leftBuilt, rightBuilt, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at compiled + | some rightResult => + simp only [compileExpr, leftBuilt, rightBuilt, bind, Option.bind_some] at compiled + simpa only [compileExpr, ihLeft leftBuilt, ihRight rightBuilt, bind, Option.bind_some] using compiled + | neg child ih => + cases childBuilt : compileExpr small allowStage2 child nodes with + | none => simp only [compileExpr, childBuilt, bind, Option.bind_none, reduceCtorEq] at compiled + | some childResult => + simp only [compileExpr, childBuilt, bind, Option.bind_some] at compiled + simpa only [compileExpr, ih childBuilt, bind, Option.bind_some] using compiled + +theorem compileExprs_widen {small large : GraphWidths} (widths : small.Le large) + (allowStage2 : Bool) (exprs : List Expr) {nodes : List Node} {result : List Node × List Nat} + (compiled : compileExprs small allowStage2 exprs nodes = some result) : + compileExprs large allowStage2 exprs nodes = some result := by + induction exprs generalizing nodes result with + | nil => exact compiled + | cons expr exprs ih => + cases headBuilt : compileExpr small allowStage2 expr nodes with + | none => simp only [compileExprs, headBuilt, bind, Option.bind_none, reduceCtorEq] at compiled + | some headResult => + cases tailBuilt : compileExprs small allowStage2 exprs headResult.1 with + | none => simp only [compileExprs, headBuilt, tailBuilt, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at compiled + | some tailResult => + have headWide := compileExpr_widen widths allowStage2 expr headBuilt + have tailWide := ih tailBuilt + simp only [compileExprs, headBuilt, tailBuilt, bind, Option.bind_some] at compiled + simpa only [compileExprs, headWide, tailWide, bind, Option.bind_some] using compiled + +theorem compileLookup_widen {small large : GraphWidths} (widths : small.Le large) + (lookup : ExprLookup) {nodes : List Node} {result : List Node × Lookup} + (compiled : compileLookup small lookup nodes = some result) : + compileLookup large lookup nodes = some result := by + cases built : compileExprs small false lookup.exprs nodes with + | none => simp only [compileLookup, built, bind, Option.bind_none, reduceCtorEq] at compiled + | some exprs => + have wide := compileExprs_widen widths false lookup.exprs built + simp only [compileLookup, built, bind, Option.bind_some] at compiled + simpa only [compileLookup, wide, bind, Option.bind_some] using compiled + +theorem compileLookups_widen {small large : GraphWidths} (widths : small.Le large) + (lookups : List ExprLookup) {nodes : List Node} {result : List Node × List Lookup} + (compiled : compileLookups small lookups nodes = some result) : + compileLookups large lookups nodes = some result := by + induction lookups generalizing nodes result with + | nil => exact compiled + | cons lookup lookups ih => + cases headBuilt : compileLookup small lookup nodes with + | none => simp only [compileLookups, headBuilt, bind, Option.bind_none, reduceCtorEq] at compiled + | some headResult => + cases tailBuilt : compileLookups small lookups headResult.1 with + | none => simp only [compileLookups, headBuilt, tailBuilt, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at compiled + | some tailResult => + have headWide := compileLookup_widen widths lookup headBuilt + have tailWide := ih tailBuilt + simp only [compileLookups, headBuilt, tailBuilt, bind, Option.bind_some] at compiled + simpa only [compileLookups, headWide, tailWide, bind, Option.bind_some] using compiled + +theorem compileZeros_widen {small large : GraphWidths} (widths : small.Le large) + (exprs : List Expr) {nodes : List Node} {result : List Node × List Nat} + (compiled : compileZeros small exprs nodes = some result) : + compileZeros large exprs nodes = some result := by + induction exprs generalizing nodes result with + | nil => exact compiled + | cons expr exprs ih => + cases headBuilt : compileExpr small false expr nodes with + | none => simp only [compileZeros, headBuilt, bind, Option.bind_none, reduceCtorEq] at compiled + | some headResult => + cases recorded : recordZero headResult.1 headResult.2 with + | none => simp only [compileZeros, headBuilt, recorded, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at compiled + | some roots => + cases tailBuilt : compileZeros small exprs headResult.1 with + | none => simp only [compileZeros, headBuilt, recorded, tailBuilt, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at compiled + | some tailResult => + have headWide := compileExpr_widen widths false expr headBuilt + have tailWide := ih tailBuilt + simp only [compileZeros, headBuilt, recorded, tailBuilt, bind, Option.bind_some] at compiled + simpa only [compileZeros, headWide, recorded, tailWide, bind, Option.bind_some] using compiled + +theorem compileBase_widen {small large : GraphWidths} (widths : small.Le large) + (lookups : List ExprLookup) (constraints : List Expr) {result : BaseCompilation} + (compiled : compileBase small lookups constraints = some result) : + compileBase large lookups constraints = some result := by + cases lookupsBuilt : compileLookups small lookups [] with + | none => simp only [compileBase, lookupsBuilt, bind, Option.bind_none, reduceCtorEq] at compiled + | some lookupResult => + cases zerosBuilt : compileZeros small constraints lookupResult.1 with + | none => simp only [compileBase, lookupsBuilt, zerosBuilt, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at compiled + | some zeroResult => + have lookupsWide := compileLookups_widen widths lookups lookupsBuilt + have zerosWide := compileZeros_widen widths constraints zerosBuilt + simp only [compileBase, lookupsBuilt, zerosBuilt, bind, Option.bind_some] at compiled + simpa only [compileBase, lookupsWide, zerosWide, bind, Option.bind_some] using compiled + +end Compiler + +namespace CircuitEmitter + +theorem compileCircuit_widen {small large : GraphWidths} (widths : small.Le large) + (program : Bytecode.Toplevel) (circuit : Bytecode.Circuit) {compiled : Compiled} + (built : compileCircuit small program circuit = some compiled) : + compileCircuit large program circuit = some compiled := by + cases emitted : emitCircuit program circuit with + | none => simp only [compileCircuit, emitted, bind, Option.bind_none, reduceCtorEq] at built + | some emission => + cases baseBuilt : Compiler.compileBase small emission.lookups emission.equations with + | none => simp only [compileCircuit, emitted, baseBuilt, bind, Option.bind_some, Option.bind_none, reduceCtorEq] at built + | some base => + have baseWide := Compiler.compileBase_widen widths emission.lookups emission.equations baseBuilt + simp only [compileCircuit, emitted, baseBuilt, bind, Option.bind_some] at built + simpa only [compileCircuit, emitted, baseWide, bind, Option.bind_some] using built + +theorem circuitWidths_le {circuit : Bytecode.Circuit} {widths : GraphWidths} + (main : circuit.layout.width ≤ widths.main) : (circuitWidths circuit).Le widths := by + refine ⟨?_, Nat.zero_le _⟩ + intro source + cases source <;> simp only [circuitWidths, GraphWidths.width, Nat.zero_le, main] + +end CircuitEmitter +end Aiur.NativeAIR diff --git a/Ix/Aiur/Proofs/Grouping.lean b/Ix/Aiur/Proofs/Grouping.lean new file mode 100644 index 000000000..8d110a97f --- /dev/null +++ b/Ix/Aiur/Proofs/Grouping.lean @@ -0,0 +1,134 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.BoundVerifier + +/-! +# Reference execution through the selected circuit grouping + +Successful grouping preserves the source, function map, complete function +array and memory widths. Its partition change therefore preserves reference +execution, including errors and final I/O state. The selected backend can +reflect that execution back through final compilation metadata and checked +deduplication to the same named function in the actual lowering output. This +does not yet extract execution from AIR witnesses or reflect earlier passes. +-/ + +namespace Aiur + +theorem CompiledToplevel.groupFunctions_preserves_code + {before after : CompiledToplevel} {groups : Array (String × Array String)} + (accepted : before.groupFunctions groups = .ok after) : + after.source = before.source ∧ after.nameMap = before.nameMap ∧ + after.bytecode.functions = before.bytecode.functions ∧ + after.bytecode.memorySizes = before.bytecode.memorySizes := by + unfold CompiledToplevel.groupFunctions at accepted + simp only [bind, Except.bind, pure, Except.pure] at accepted + split at accepted + · cases accepted + · split at accepted + · cases accepted + · cases accepted + exact ⟨rfl, rfl, rfl, rfl⟩ + +theorem CompiledToplevel.groupFunctions_sameCode + {before after : CompiledToplevel} {groups : Array (String × Array String)} + (accepted : before.groupFunctions groups = .ok after) : + Bytecode.Eval.SameCode after.bytecode before.bytecode := by + have same := (groupFunctions_preserves_code accepted).2.2.1 + exact Bytecode.Eval.SameCode.ofFunctionsEq same + +/-- Equality includes error results and final I/O state at every fuel value. -/ +theorem CompiledToplevel.groupFunctions_preserves_execution + {before after : CompiledToplevel} {groups : Array (String × Array String)} + (accepted : before.groupFunctions groups = .ok after) + (function : Bytecode.FunIdx) (args : Array G) (io : IOBuffer) (fuel : Nat) : + Bytecode.Eval.runFunction after.bytecode function args io fuel = + Bytecode.Eval.runFunction before.bytecode function args io fuel := + Bytecode.Eval.runFunction_sameCode (groupFunctions_sameCode accepted) + function args io fuel + +/-- The actual selected compilation preserves the ungrouped reference run. -/ +theorem BoundVerifier.Backend.reference_execution + {selection : BoundVerifier.Selection} (backend : BoundVerifier.Backend selection) + (function : Bytecode.FunIdx) (args : Array G) (io : IOBuffer) (fuel : Nat) : + ∃ initial, selection.source.compile = .ok initial ∧ + Bytecode.Eval.runFunction backend.compiled.bytecode function args io fuel = + Bytecode.Eval.runFunction initial.bytecode function args io fuel := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + refine ⟨initial, compiled, ?_⟩ + split at grouped + · cases grouped + rfl + · exact CompiledToplevel.groupFunctions_preserves_execution grouped function args io fuel + +/-- Reference success at the selected entrypoint reflects to the exact +deduplicated output of the successful source compiler stages. No AIR or +cryptographic acceptance premise is substituted for reference execution. -/ +theorem BoundVerifier.Backend.execution_reflects + {selection : BoundVerifier.Selection} (backend : BoundVerifier.Backend selection) + {args : Array G} {io : IOBuffer} {fuel : Nat} {result : Array G × IOBuffer} + (accepted : Bytecode.Eval.runFunction backend.compiled.bytecode + selection.function args io fuel = .ok result) : + ∃ inlined typed concrete raw names, + selection.source.inlineCalls = .ok inlined ∧ + inlined.checkAndSimplify = .ok typed ∧ + typed.concretize = .ok concrete ∧ + concrete.toBytecode = .ok (raw, names) ∧ + Bytecode.Eval.runFunction raw.deduplicate.1 + selection.function args io fuel = .ok result := by + obtain ⟨initial, compiled, execution⟩ := + backend.reference_execution selection.function args io fuel + obtain ⟨inlined, typed, concrete, raw, names, hi, ht, hc, hb, artifact⟩ := + Source.Toplevel.compile_artifact_of_ok compiled + refine ⟨inlined, typed, concrete, raw, names, hi, ht, hc, hb, ?_⟩ + apply finishCompilation_reflects (source := inlined) (names := names) + rw [← artifact] + exact execution.symm.trans accepted + +/-- Grouping retains the selected entrypoint as well as its reference run. -/ +theorem BoundVerifier.Backend.reference_entrypoint + {selection : BoundVerifier.Selection} (backend : BoundVerifier.Backend selection) + (args : Array G) (io : IOBuffer) (fuel : Nat) : + ∃ initial, selection.source.compile = .ok initial ∧ + initial.getFuncIdx selection.entrypoint = some selection.function ∧ + Bytecode.Eval.runFunction backend.compiled.bytecode selection.function args io fuel = + Bytecode.Eval.runFunction initial.bytecode selection.function args io fuel := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + refine ⟨initial, compiled, ?_⟩ + split at grouped + · cases grouped + exact ⟨backend.selected, rfl⟩ + · have sameNames := (CompiledToplevel.groupFunctions_preserves_code grouped).2.1 + exact ⟨by simpa only [CompiledToplevel.getFuncIdx, sameNames] using backend.selected, + CompiledToplevel.groupFunctions_preserves_execution grouped selection.function args io fuel⟩ + +/-- Successful execution of the selected backend reflects through grouping, +metadata and checked deduplication to the same named function in the actual +lowering output. The earlier source passes and AIR extraction are separate. -/ +theorem BoundVerifier.Backend.execution_reflects_raw + {selection : BoundVerifier.Selection} (backend : BoundVerifier.Backend selection) + {args : Array G} {io : IOBuffer} {fuel : Nat} {result : Array G × IOBuffer} + (accepted : Bytecode.Eval.runFunction backend.compiled.bytecode + selection.function args io fuel = .ok result) : + ∃ inlined typed concrete raw names original, + selection.source.inlineCalls = .ok inlined ∧ + inlined.checkAndSimplify = .ok typed ∧ + typed.concretize = .ok concrete ∧ + concrete.toBytecode = .ok (raw, names) ∧ + names[Global.mk selection.entrypoint]? = some original ∧ + raw.deduplicate.2 original = selection.function ∧ + Bytecode.Eval.runFunction raw original args io fuel = .ok result := by + obtain ⟨initial, compiled, selected, execution⟩ := backend.reference_entrypoint args io fuel + obtain ⟨inlined, typed, concrete, raw, names, hi, ht, hc, hb, artifact⟩ := + Source.Toplevel.compile_artifact_of_ok compiled + rw [artifact] at selected + obtain ⟨original, named, remapped⟩ := finishCompilation_nameMap_image selected + refine ⟨inlined, typed, concrete, raw, names, original, hi, ht, hc, hb, named, remapped, ?_⟩ + apply (finishCompilation_preserves_execution inlined raw names original args io fuel result).mpr + rw [remapped, ← artifact] + exact execution.symm.trans accepted + +end Aiur diff --git a/Ix/Aiur/Proofs/InactiveRows.lean b/Ix/Aiur/Proofs/InactiveRows.lean new file mode 100644 index 000000000..7fa115fd7 --- /dev/null +++ b/Ix/Aiur/Proofs/InactiveRows.lean @@ -0,0 +1,378 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRows + +/-! Zero selectors satisfy every successfully emitted block, for arbitrary +logical values and advice. The all-zero circuit row therefore witnesses that +symbolic circuit constraints contain no contradictory constant equation. -/ + +namespace Aiur.AIR +open Bytecode + +theorem selectorSum_zero (values : List G) (zero : ∀ value ∈ values, value = 0) : + selectorSum values = 0 := by + induction values with + | nil => rfl + | cons value values ih => + rw [selectorSum_cons, zero value List.mem_cons_self, + ih (fun value member => zero value (List.mem_cons_of_mem _ member)), G.zero_add] + +theorem emitOp_inactive {row : Nat → G} {rank : G} (op : Op) {values : Array RowValue} + {emission : OpEmission} (emitted : emitOp row 0 rank op values = some emission) : + ∀ equation ∈ emission.equations, equation = 0 := by + cases op <;> simp only [emitOp, emitAdvice, emitByte1, emitByte2, emitU32LessThan, + emitU32Add, bind, Option.bind] at emitted + all_goals repeat' first | split at emitted | (dsimp only at emitted; split at emitted) + all_goals cases emitted + all_goals simp [G.mul_comm (0 : G), G.mul_zero] + +theorem emitOps_inactive {row : Nat → G} {rank : G} (ops : List Op) {values : Array RowValue} + {column : Nat} {emission : OpsEmission} (emitted : emitOps row 0 rank ops values column = some emission) : + ∀ equation ∈ emission.equations, equation = 0 := by + induction ops generalizing values column emission with + | nil => cases emitted; simp + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + intro equation member + rcases List.mem_append.mp member with firstMember | restMember + · exact emitOp_inactive op firstEmitted equation firstMember + · exact ih restEmitted equation restMember + +def BlockEmission.Inactive (emission : BlockEmission) : Prop := + (∀ equation ∈ emission.equations, equation = 0) ∧ ∀ part ∈ emission.yields, part.1 = 0 + +theorem BlockEmission.Inactive.prefix {emission : BlockEmission} (inactive : emission.Inactive) + (equations : List G) (zero : ∀ equation ∈ equations, equation = 0) : + (emission.prefix equations).Inactive := by + refine ⟨?_, inactive.2⟩ + intro equation member + rcases List.mem_append.mp member with first | last + · exact zero equation first + · exact inactive.1 equation last + +theorem BlockEmission.Inactive.afterOps {emission : BlockEmission} (inactive : emission.Inactive) + (incoming : G) (lookup : Nat) (ops : OpsEmission) (zero : ∀ equation ∈ ops.equations, equation = 0) : + (emission.afterOps incoming lookup ops).Inactive := inactive.prefix _ zero + +theorem joinBlockEmissions_inactive (values : Array RowValue) (column lookup : Nat) + (emissions : List BlockEmission) (inactive : ∀ emission ∈ emissions, emission.Inactive) : + (joinBlockEmissions values column lookup emissions).Inactive := by + constructor + · intro equation member + obtain ⟨emission, member, present⟩ := List.mem_flatMap.mp member + exact (inactive emission member).1 equation present + · intro part member + obtain ⟨emission, member, present⟩ := List.mem_flatMap.mp member + exact (inactive emission member).2 part present + +theorem BlockEmission.Inactive.continued {branches continuation : BlockEmission} + (first : branches.Inactive) (last : continuation.Inactive) + (equations : List G) (zero : ∀ equation ∈ equations, equation = 0) : + (branches.continued equations continuation).Inactive := by + refine ⟨?_, last.2⟩ + intro equation member + rcases List.mem_append.mp member with before | after + · rcases List.mem_append.mp before with branch | link + · exact first.1 equation branch + · exact zero equation link + · exact last.1 equation after + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +private theorem inactive_case_smaller {branches : Array (G × Block)} {pair : G × Block} + (member : pair ∈ branches.toList) : sizeOf pair.2 < sizeOf branches := by + have bound := Array.sizeOf_lt_of_mem (Array.mem_toList_iff.mp member) + cases pair + simp at bound ⊢ + omega + +private theorem inactive_default_smaller {fallback : Option Block} {block : Block} + (present : fallback = some block) : sizeOf block < sizeOf fallback := by + rw [present] + simp + +theorem branchSelectorFlows_entry_zero (branches : Array (G × Block)) (fallback : Option Block) + (caseZero : ∀ pair ∈ branches.toList, (pair.2.selectorFlow (fun _ => 0)).entry = 0) + (defaultZero : ∀ block, fallback = some block → (block.selectorFlow (fun _ => 0)).entry = 0) : + (SelectorFlow.join (branchSelectorFlows (fun _ => 0) branches fallback)).entry = 0 := by + apply selectorSum_zero + intro value member + obtain ⟨flow, flowMember, equal⟩ := List.mem_map.mp member + subst value + rcases List.mem_append.mp flowMember with first | last + · obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp first + subst flow + exact caseZero pair pairMember + · obtain ⟨block, blockMember, equal⟩ := List.mem_map.mp last + subst flow + exact defaultZero block (by simpa only [Option.mem_toList] using blockMember) + +mutual + +theorem Ctrl.selectorFlow_entry_zero (ctrl : Ctrl) : (ctrl.selectorFlow (fun _ => 0)).entry = 0 := by + cases ctrl with + | «return» index values | yield index values => rw [Ctrl.selectorFlow.eq_def]; rfl + | «match» index branches fallback => + rw [Ctrl.selectorFlow_match] + exact branchSelectorFlows_entry_zero branches fallback + (fun pair member => Block.selectorFlow_entry_zero pair.2) + (fun block present => Block.selectorFlow_entry_zero block) + | matchContinue index branches fallback size aux slots continuation => + rw [Ctrl.selectorFlow_matchContinue] + exact branchSelectorFlows_entry_zero branches fallback + (fun pair member => Block.selectorFlow_entry_zero pair.2) + (fun block present => Block.selectorFlow_entry_zero block) +termination_by sizeOf ctrl +decreasing_by + all_goals subst ctrl + all_goals first + | (have bound := inactive_case_smaller ‹_ ∈ _›; simp; omega) + | (have bound := inactive_default_smaller ‹_ = some _›; simp; omega) + +theorem Block.selectorFlow_entry_zero (block : Block) : (block.selectorFlow (fun _ => 0)).entry = 0 := by + rw [Block.selectorFlow] + exact Ctrl.selectorFlow_entry_zero block.ctrl +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +theorem branchRows_inactive (row : Nat → G) (context : RowContext) (matched : G) + (values : Array RowValue) (column lookup : Nat) (branches : Array (G × Block)) (fallback : Option Block) + {emission : BlockEmission} + (caseSound : ∀ pair ∈ branches.toList, ∀ result, + pair.2.emitRow row (fun _ => 0) context 0 values column lookup = some result → result.Inactive) + (defaultSound : ∀ block, fallback = some block → ∀ result, + block.emitRow row (fun _ => 0) context 0 values (column + branches.size) lookup = some result → result.Inactive) + (emitted : branchRows row (fun _ => 0) context matched values column lookup branches fallback = some emission) : + emission.Inactive := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i defaults defaultsEmitted + cases emitted + have casesValid : ∀ result ∈ cases, result.Inactive := by + have related : List.Forall₂ (fun _ result => result.Inactive) branches.toList cases := by + apply mapM_forall₂ casesEmitted + intro pair member result resultEmitted + simp only [caseRow, Block.selectorFlow_entry_zero, bind, Option.bind] at resultEmitted + split at resultEmitted + · cases resultEmitted + rename_i body bodyEmitted + cases resultEmitted + exact (caseSound pair member body bodyEmitted).prefix _ (by simp [G.mul_comm (0 : G), G.mul_zero]) + intro result member + obtain ⟨_, _, valid⟩ := forall₂_right_member related member + exact valid + have defaultsValid : ∀ result ∈ defaults, result.Inactive := by + cases present : fallback with + | none => + simp only [defaultRow, present, Option.some.injEq] at defaultsEmitted + subst defaults + simp + | some block => + simp only [defaultRow, present, Block.selectorFlow_entry_zero, bind, Option.bind] at defaultsEmitted + split at defaultsEmitted + · cases defaultsEmitted + rename_i body bodyEmitted + cases defaultsEmitted + intro result member + have equal := List.mem_singleton.mp member + subst result + apply (defaultSound block present body bodyEmitted).prefix + simp [G.mul_comm (0 : G), G.mul_zero] + apply joinBlockEmissions_inactive + intro result member + rcases List.mem_append.mp member with first | last + · exact casesValid result first + · exact defaultsValid result last + +mutual + +theorem Ctrl.emitRow_inactive (row : Nat → G) (context : RowContext) (ctrl : Ctrl) + (values : Array RowValue) (column lookup : Nat) {emission : BlockEmission} + (emitted : ctrl.emitRow row (fun _ => 0) context 0 values column lookup = some emission) : + emission.Inactive := by + cases ctrl with + | «return» index indices | yield index indices => + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + repeat' first | split at emitted | (dsimp only at emitted; split at emitted) + all_goals cases emitted + all_goals simp [BlockEmission.Inactive] + | «match» index branches fallback => + rw [Ctrl.emitRow_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + exact branchRows_inactive row context _ values column lookup branches fallback + (fun pair member result emitted => Block.emitRow_inactive row context pair.2 values column lookup emitted) + (fun block present result emitted => Block.emitRow_inactive row context block values _ lookup emitted) emitted + | matchContinue index branches fallback size aux slots continuation => + rw [Ctrl.emitRow_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i joined joinedEmitted + have joinedValid := branchRows_inactive row context _ values column lookup branches fallback + (fun pair member result emitted => Block.emitRow_inactive row context pair.2 values column lookup emitted) + (fun block present result emitted => Block.emitRow_inactive row context block values _ lookup emitted) joinedEmitted + have gate : selectorSum (joined.yields.map Prod.fst) = 0 := by + apply selectorSum_zero + intro value member + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst value + exact joinedValid.2 part partMember + simp only [continueRow, gate, Block.selectorFlow_entry_zero] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i continued continuedEmitted + cases emitted + apply joinedValid.continued (Block.emitRow_inactive row context continuation _ _ _ continuedEmitted) + intro equation member + rcases List.mem_append.mp member with merged | linked + · obtain ⟨index, _, equal⟩ := List.mem_map.mp merged + rw [← equal] + exact (G.mul_comm 0 _).trans (G.mul_zero _) + · have equal := List.mem_singleton.mp linked + exact equal.trans (show (0 : G) - 0 = 0 from rfl) + · cases emitted +termination_by sizeOf ctrl +decreasing_by + all_goals subst ctrl + all_goals first + | (have bound := inactive_case_smaller ‹_ ∈ _›; simp; omega) + | (have bound := inactive_default_smaller ‹_ = some _›; simp; omega) + | decreasing_tactic + +theorem Block.emitRow_inactive (row : Nat → G) (context : RowContext) (block : Block) + (values : Array RowValue) (column lookup : Nat) {emission : BlockEmission} + (emitted : block.emitRow row (fun _ => 0) context 0 values column lookup = some emission) : + emission.Inactive := by + rw [Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i operations opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i control ctrlEmitted + cases emitted + have controlValid := Ctrl.emitRow_inactive row context block.ctrl _ _ _ ctrlEmitted + apply (controlValid.afterOps _ _ _ (emitOps_inactive block.ops.toList opsEmitted)).prefix + simp [Block.selectorFlow_entry_zero, oneSubBooleanConstraint, G.mul_comm (0 : G), G.mul_zero] +termination_by sizeOf block +decreasing_by cases block; simp; omega + +end + +end Aiur.Bytecode + +namespace Aiur.AIR +open Bytecode + +theorem MemberEmission.entry_zero (member : MemberEmission) : member.entry (fun _ => 0) = 0 := + Block.selectorFlow_entry_zero member.function.body + +theorem emitMember_zero {rank : G} {column lookup selectorBase : Nat} {program : Toplevel} + {functionIndex : FunIdx} {member : MemberEmission} + (emitted : emitMember (fun _ => 0) rank column lookup selectorBase program functionIndex = some member) : + member.body.Inactive := by + simp only [emitMember, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i function functionRead + dsimp only at emitted + split at emitted + · cases emitted + rename_i body bodyEmitted + cases emitted + simp only [Function.emitRow, Block.selectorFlow_entry_zero] at bodyEmitted + exact Block.emitRow_inactive _ _ _ _ _ _ bodyEmitted + +theorem emitMembers_zero {rank : G} (column lookup selectorBase : Nat) (program : Toplevel) + (indices : List FunIdx) {members : List MemberEmission} + (emitted : emitMembers (fun _ => 0) rank column lookup selectorBase program indices = some members) : + ∀ member ∈ members, member.body.Inactive := by + induction indices generalizing selectorBase members with + | nil => cases emitted; simp + | cons index indices ih => + simp only [emitMembers, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i member memberEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + intro chosen memberOf + rcases List.mem_cons.mp memberOf with equal | later + · subst chosen; exact emitMember_zero memberEmitted + · exact ih _ restEmitted chosen later + +theorem circuitEmission_zero (circuit : Circuit) (members : List MemberEmission) + (inactive : ∀ member ∈ members, member.body.Inactive) : + ∀ equation ∈ (circuitEmission (fun _ => 0) circuit members).equations, equation = 0 := by + have selected : selectorSum (members.map (·.entry (fun _ => 0))) = 0 := by + apply selectorSum_zero + intro value member + obtain ⟨part, _, equal⟩ := List.mem_map.mp member + subst value + exact part.entry_zero + intro equation member + dsimp only [circuitEmission] at member + rw [selected] at member + rcases List.mem_append.mp member with prior | activity + · rcases List.mem_append.mp prior with prior | group + · rcases List.mem_append.mp prior with body | boolean + · obtain ⟨part, partMember, present⟩ := List.mem_flatMap.mp body + exact (inactive part partMember).1 equation present + · obtain ⟨_, _, equal⟩ := List.mem_map.mp boolean + exact equal.symm.trans (show booleanConstraint 0 = 0 from rfl) + · split at group + · exact (List.mem_singleton.mp group).trans (show oneSubBooleanConstraint 0 = 0 from rfl) + · cases group + · exact (List.mem_singleton.mp activity).trans (show activityConstraint 0 0 = 0 from rfl) + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitRow_zero (program : Toplevel) (circuit : Circuit) {emission : CircuitEmission} + (emitted : circuit.emitRow (fun _ => 0) program = some emission) : + ∀ equation ∈ emission.equations, equation = 0 := by + simp only [Circuit.emitRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i members membersEmitted + cases emitted + exact circuitEmission_zero circuit members (emitMembers_zero _ _ _ program circuit.members.toList membersEmitted) + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/Interpolation.lean b/Ix/Aiur/Proofs/Interpolation.lean new file mode 100644 index 000000000..96b1faf6f --- /dev/null +++ b/Ix/Aiur/Proofs/Interpolation.lean @@ -0,0 +1,408 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Interpolation +import Ix.Aiur.Proofs.Polynomial + +/-! Lagrange interpolation on the native folding cosets. Synthetic division +and the checked polynomial root bound establish the diagonal weights, exact +node values, degree bound and uniqueness. The runtime formula is then proved +to evaluate those coefficients, with its node branch preceding inversion. +-/ + +namespace Aiur.NativeAIR.Interpolation + +open Lean.Grind +open _root_.Aiur.NativeAIR.Quotient (horner horner_nil horner_cons) +attribute [local instance] Semiring.natCast Ring.intCast + +variable {R : Type} [CommRing R] + +theorem derivative_zero (point : R) {coefficients : List R} (zero : Polynomial.IsZero coefficients) : + derivativeValue point coefficients = 0 := by + induction coefficients with + | nil => rfl + | cons coefficient rest ih => + obtain ⟨_, tailZero⟩ := (Polynomial.isZero_cons _ _).mp zero + rw [derivativeValue, Polynomial.horner_zero point tailZero, ih tailZero] + grind + +theorem derivative_neg (point : R) (coefficients : List R) : + derivativeValue point (coefficients.map (0 - ·)) = 0 - derivativeValue point coefficients := by + induction coefficients with + | nil => change (0 : R) = 0 - 0; grind + | cons first rest ih => + simp only [List.map_cons, derivativeValue, Polynomial.horner_neg, ih] + grind + +theorem derivative_sub (point : R) (left right : List R) : + derivativeValue point (Polynomial.sub left right) = derivativeValue point left - derivativeValue point right := by + induction left generalizing right with + | nil => rw [Polynomial.sub, derivative_neg, derivativeValue] + | cons first left ih => + cases right with + | nil => rw [Polynomial.sub_nil, derivativeValue]; grind + | cons second right => + rw [Polynomial.sub, derivativeValue, Polynomial.horner_sub, ih, derivativeValue, derivativeValue] + grind + +theorem divide_diagonal (point : R) (coefficients : List R) : + horner point (Polynomial.divide point coefficients) = derivativeValue point coefficients := by + induction coefficients using Polynomial.divide.induct with + | case1 => rfl + | case2 first => simp only [Polynomial.divide, horner_nil, derivativeValue]; grind + | case3 first next rest ih => + change horner point (next :: rest) + point * horner point (Polynomial.divide point (next :: rest)) = + horner point (next :: rest) + point * derivativeValue point (next :: rest) + rw [ih] + +theorem monomial_value (point : R) (degree : Nat) : + horner point (List.replicate degree 0 ++ [1]) = point ^ degree := by + rw [Quotient.horner_append, Polynomial.horner_replicate_zero, List.length_replicate] + simp only [horner_cons, horner_nil] + grind + +theorem monomial_derivative (point : R) (degree : Nat) : + derivativeValue point (List.replicate degree 0 ++ [1]) = (degree : R) * point ^ (degree - 1) := by + induction degree with + | zero => + simp only [List.replicate_zero, List.nil_append, derivativeValue, horner_nil, Semiring.natCast_zero] + grind + | succ degree ih => + rw [List.replicate_succ, List.cons_append, derivativeValue, monomial_value, ih, Semiring.natCast_succ] + cases degree with + | zero => simp only [Nat.zero_sub, Nat.add_sub_cancel, Semiring.pow_zero, Semiring.natCast_zero]; grind + | succ degree => simp only [Nat.add_sub_cancel, Semiring.pow_succ]; grind + +theorem powerMinus_derivative (point constant : R) (degree : Nat) : + derivativeValue point (Polynomial.powerMinus degree constant) = (degree : R) * point ^ (degree - 1) := by + rw [Polynomial.powerMinus, derivative_sub, monomial_derivative] + simp only [derivativeValue, horner_nil] + grind + +theorem root_product_derivative (noZeroDivisors : ∀ a b : R, a * b = 0 → a = 0 ∨ b = 0) + (roots : List R) (constant : R) (unique : roots.Nodup) (positive : 0 < roots.length) + (powers : ∀ root ∈ roots, root ^ roots.length = constant) (point : R) : + derivativeValue point (Polynomial.fromRoots roots) = (roots.length : R) * point ^ (roots.length - 1) := by + have zero : Polynomial.IsZero (Polynomial.sub (Polynomial.fromRoots roots) (Polynomial.powerMinus roots.length constant)) := by + apply Polynomial.monic_zero_sub_of_samples noZeroDivisors _ _ roots + (Polynomial.fromRoots_monic roots) (Polynomial.powerMinus_monic positive constant) unique + · rw [Polynomial.fromRoots_length, Polynomial.powerMinus_length] + · rw [Polynomial.fromRoots_length] + omega + · intro root member + rw [Polynomial.fromRoots_vanishes roots root member, Polynomial.horner_powerMinus, powers root member] + grind + have difference := derivative_zero point zero + rw [derivative_sub, powerMinus_derivative] at difference + exact (LogUp.sub_zero_iff _ _).mp difference + +theorem root_quotient_diagonal (noZeroDivisors : ∀ a b : R, a * b = 0 → a = 0 ∨ b = 0) + (roots : List R) (constant : R) (unique : roots.Nodup) (positive : 0 < roots.length) + (powers : ∀ root ∈ roots, root ^ roots.length = constant) (point : R) : + horner point (Polynomial.divide point (Polynomial.fromRoots roots)) = + (roots.length : R) * point ^ (roots.length - 1) := by + rw [divide_diagonal, root_product_derivative noZeroDivisors roots constant unique positive powers] + +theorem closed_weight_diagonal (noZeroDivisors : ∀ a b : R, a * b = 0 → a = 0 ∨ b = 0) + (roots : List R) (constant scale root : R) (unique : roots.Nodup) (positive : 0 < roots.length) + (powers : ∀ root ∈ roots, root ^ roots.length = constant) (member : root ∈ roots) + (inverts : (roots.length : R) * constant * scale = 1) : + (root * scale) * horner root (Polynomial.divide root (Polynomial.fromRoots roots)) = 1 := by + rw [root_quotient_diagonal noZeroDivisors roots constant unique positive powers] + have power : root ^ (roots.length - 1) * root = constant := by + rw [← Semiring.pow_succ, Nat.sub_add_cancel (by omega)] + exact powers root member + grind + +theorem combine_length (vanishing : List R) (scale : R) (samples : List (R × R)) : + (combine vanishing scale samples).length ≤ vanishing.length - 1 := by + induction samples with + | nil => exact Nat.zero_le _ + | cons sample samples ih => + rw [combine, Polynomial.add_length, Polynomial.scale_length, Polynomial.divide_length] + exact Nat.max_le.mpr ⟨Nat.le_refl _, ih⟩ + +theorem coefficients_length (samples : List (R × R)) (scale : R) : + (coefficients samples scale).length ≤ samples.length := by + have bounded := combine_length (Polynomial.fromRoots (samples.map Prod.fst)) scale samples + simpa only [coefficients, Polynomial.fromRoots_length, Nat.add_sub_cancel, List.length_map] using bounded + +theorem combine_zero (vanishing : List R) (scale point : R) (samples : List (R × R)) + (zero : ∀ sample ∈ samples, horner point (Polynomial.divide sample.1 vanishing) = 0) : + horner point (combine vanishing scale samples) = 0 := by + induction samples with + | nil => rfl + | cons sample samples ih => + rw [combine, Polynomial.horner_add, Polynomial.horner_scale, + zero sample List.mem_cons_self, ih (fun value member => zero value (List.mem_cons_of_mem _ member))] + grind + +theorem combine_at_node (vanishing : List R) (scale root value : R) (samples : List (R × R)) + (unique : (samples.map Prod.fst).Nodup) (member : (root, value) ∈ samples) + (diagonal : (root * scale) * horner root (Polynomial.divide root vanishing) = 1) + (offDiagonal : ∀ sample ∈ samples, sample.1 ≠ root → horner root (Polynomial.divide sample.1 vanishing) = 0) : + horner root (combine vanishing scale samples) = value := by + induction samples with + | nil => cases member + | cons sample samples ih => + obtain ⟨absent, tailUnique⟩ := List.nodup_cons.mp unique + rw [combine, Polynomial.horner_add, Polynomial.horner_scale] + rcases List.mem_cons.mp member with same | later + · subst sample + have tailZero : horner root (combine vanishing scale samples) = 0 := by + apply combine_zero + intro sample member + apply offDiagonal sample (List.mem_cons_of_mem _ member) + intro equal + exact absent (List.mem_map.mpr ⟨sample, member, equal⟩) + rw [tailZero] + grind + · have different : sample.1 ≠ root := by + intro same + exact absent (List.mem_map.mpr ⟨(root, value), later, same.symm⟩) + rw [offDiagonal sample List.mem_cons_self different, + ih tailUnique later (fun item member => offDiagonal item (List.mem_cons_of_mem _ member))] + grind + +theorem coefficients_at_node (noZeroDivisors : ∀ a b : R, a * b = 0 → a = 0 ∨ b = 0) + (samples : List (R × R)) (constant scale root value : R) + (unique : (samples.map Prod.fst).Nodup) (positive : 0 < samples.length) + (powers : ∀ sample ∈ samples, sample.1 ^ samples.length = constant) + (inverts : (samples.length : R) * constant * scale = 1) (member : (root, value) ∈ samples) : + horner root (coefficients samples scale) = value := by + have rootMember : root ∈ samples.map Prod.fst := List.mem_map.mpr ⟨(root, value), member, rfl⟩ + apply combine_at_node _ scale root value samples unique member + · apply closed_weight_diagonal noZeroDivisors (samples.map Prod.fst) constant scale root unique + (by simpa only [List.length_map] using positive) _ rootMember + (by simpa only [List.length_map] using inverts) + intro node nodeMember + obtain ⟨sample, sampleMember, rfl⟩ := List.mem_map.mp nodeMember + simpa only [List.length_map] using powers sample sampleMember + · intro sample sampleMember different + apply Polynomial.divide_root noZeroDivisors sample.1 root _ + (Polynomial.fromRoots_vanishes _ _ (List.mem_map.mpr ⟨sample, sampleMember, rfl⟩)) + (Polynomial.fromRoots_vanishes _ _ rootMember) + exact Ne.symm different + +theorem coefficients_unique (noZeroDivisors : ∀ a b : R, a * b = 0 → a = 0 ∨ b = 0) + (samples : List (R × R)) (constant scale : R) (candidate : List R) + (unique : (samples.map Prod.fst).Nodup) (positive : 0 < samples.length) + (powers : ∀ sample ∈ samples, sample.1 ^ samples.length = constant) + (inverts : (samples.length : R) * constant * scale = 1) + (bounded : candidate.length ≤ samples.length) + (agrees : ∀ sample ∈ samples, horner sample.1 candidate = sample.2) : + Polynomial.IsZero (Polynomial.sub candidate (coefficients samples scale)) := by + apply Polynomial.zero_sub_of_samples noZeroDivisors candidate (coefficients samples scale) + (samples.map Prod.fst) unique + · simpa only [List.length_map] using bounded + · simpa only [List.length_map] using coefficients_length samples scale + · intro root member + obtain ⟨sample, sampleMember, rfl⟩ := List.mem_map.mp member + rw [agrees sample sampleMember] + exact (coefficients_at_node noZeroDivisors samples constant scale sample.1 sample.2 + unique positive powers inverts sampleMember).symm + +theorem coefficients_evaluate (noZeroDivisors : ∀ a b : R, a * b = 0 → a = 0 ∨ b = 0) + (samples : List (R × R)) (constant scale : R) (candidate : List R) + (unique : (samples.map Prod.fst).Nodup) (positive : 0 < samples.length) + (powers : ∀ sample ∈ samples, sample.1 ^ samples.length = constant) + (inverts : (samples.length : R) * constant * scale = 1) + (bounded : candidate.length ≤ samples.length) + (agrees : ∀ sample ∈ samples, horner sample.1 candidate = sample.2) (point : R) : + horner point (coefficients samples scale) = horner point candidate := by + have zero := Polynomial.horner_zero point (coefficients_unique noZeroDivisors samples constant scale candidate + unique positive powers inverts bounded agrees) + rw [Polynomial.horner_sub] at zero + exact ((LogUp.sub_zero_iff _ _).mp zero).symm + +theorem divide_inverse_value (vanishing : List R) (point root inverse : R) + (vanishes : horner root vanishing = 0) (inverts : (point - root) * inverse = 1) : + inverse * horner point vanishing = horner point (Polynomial.divide root vanishing) := by + have factor := Polynomial.divide_factor point root vanishing + rw [vanishes] at factor + calc + inverse * horner point vanishing = inverse * ((point - root) * horner point (Polynomial.divide root vanishing)) := by + rw [factor] + grind + _ = horner point (Polynomial.divide root vanishing) := by grind + +open ProofCodec (Extension) + +theorem weightedSum_polynomial (vanishing : List Extension) (scale point : Extension) + (samples : List (Extension × Extension)) + (roots : ∀ sample ∈ samples, horner sample.1 vanishing = 0) + (away : ∀ sample ∈ samples, point ≠ sample.1) : + ∃ result, weightedSum scale point samples = some result ∧ + result * horner point vanishing = horner point (combine vanishing scale samples) := by + induction samples with + | nil => exact ⟨0, rfl, by change 0 * horner point vanishing = 0; grind⟩ + | cons sample samples ih => + have nonzero : point - sample.1 ≠ 0 := fun zero => + away sample List.mem_cons_self ((LogUp.sub_zero_iff _ _).mp zero) + obtain ⟨returned, inverse⟩ := Extension.inverse_correct (point - sample.1) nonzero + obtain ⟨tail, tailRead, tailValue⟩ := ih + (fun entry member => roots entry (List.mem_cons_of_mem _ member)) + (fun entry member => away entry (List.mem_cons_of_mem _ member)) + refine ⟨sample.2 * (sample.1 * scale) * (point - sample.1).conjugate.scale (point - sample.1).norm.inverse + tail, ?_, ?_⟩ + · simp only [weightedSum, returned, tailRead, bind, Option.bind_some, pure] + · have head := divide_inverse_value vanishing point sample.1 _ (roots sample List.mem_cons_self) inverse + rw [combine, Polynomial.horner_add, Polynomial.horner_scale] + rw [Semiring.right_distrib, Semiring.mul_assoc, head, tailValue] + +theorem evaluate_polynomial (samples : List (Extension × Extension)) (constant scale point : Extension) + (unique : (samples.map Prod.fst).Nodup) (positive : 0 < samples.length) + (powers : ∀ sample ∈ samples, sample.1 ^ samples.length = constant) + (inverts : (samples.length : Extension) * constant * scale = 1) : + evaluate scale point samples = some (horner point (coefficients samples scale)) := by + unfold evaluate + split + next sample found => + have member := List.mem_of_find?_eq_some found + have test : (point == sample.1) = true := + List.find?_some (p := fun entry : Extension × Extension => point == entry.1) found + have same : point = sample.1 := beq_iff_eq.mp test + rw [same, coefficients_at_node (fun a b => (Extension.mul_eq_zero_iff a b).mp) + samples constant scale sample.1 sample.2 unique positive powers inverts member] + next missing => + have away : ∀ sample ∈ samples, point ≠ sample.1 := by + intro sample member same + have absent := List.find?_eq_none.mp missing sample member + simp only [same, beq_self_eq_true] at absent + contradiction + obtain ⟨result, returned, correct⟩ := weightedSum_polynomial + (Polynomial.fromRoots (samples.map Prod.fst)) scale point samples + (fun sample member => Polynomial.fromRoots_vanishes _ _ (List.mem_map.mpr ⟨sample, member, rfl⟩)) away + simp only [returned, bind, Option.bind_some, pure] + rw [Polynomial.horner_fromRoots] at correct + simpa only [coefficients, List.map_map, Function.comp_def] using congrArg some correct + +theorem foldSamples_roots (parent arity : Domain.Subgroup) (index : Nat) (values : List Extension) + (shape : values.length = Domain.size arity) : + (foldSamples parent arity index values).map Prod.fst = + (Polynomial.foldingNodes parent arity index).map Extension.ofBase := by + apply List.map_fst_zip + simp only [List.length_map, Polynomial.foldingNodes_length, shape, Nat.le_refl] + +theorem foldSamples_length (parent arity : Domain.Subgroup) (index : Nat) (values : List Extension) + (shape : values.length = Domain.size arity) : + (foldSamples parent arity index values).length = Domain.size arity := by + have length := congrArg List.length (foldSamples_roots parent arity index values shape) + simpa only [List.length_map, Polynomial.foldingNodes_length] using length + +theorem foldSamples_nodup (parent arity : Domain.Subgroup) (nested : arity.val ≤ parent.val) + {index : Nat} (bounded : index < 2^(parent.val - arity.val)) (values : List Extension) + (shape : values.length = Domain.size arity) : (foldSamples parent arity index values |>.map Prod.fst).Nodup := by + rw [foldSamples_roots parent arity index values shape, List.nodup_iff_pairwise_ne, List.pairwise_map] + exact (Polynomial.foldingNodes_nodup parent arity nested bounded).imp + (fun different equal => different (Extension.ofBase_injective equal)) + +theorem foldSamples_powers (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) (index : Nat) (values : List Extension) + (shape : values.length = Domain.size arity) : ∀ sample ∈ foldSamples parent arity index values, + sample.1 ^ (foldSamples parent arity index values).length = Extension.ofBase (FriDomain.queryPoint child index) := by + intro sample member + have rootMember : sample.1 ∈ (foldSamples parent arity index values).map Prod.fst := + List.mem_map.mpr ⟨sample, member, rfl⟩ + rw [foldSamples_roots parent arity index values shape] at rootMember + obtain ⟨node, nodeMember, same⟩ := List.mem_map.mp rootMember + rw [foldSamples_length parent arity index values shape, ← same, ← Extension.ofBase_power, + Polynomial.foldingNodes_powers parent child arity dimensions index node nodeMember] + +theorem foldScale_inverse (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) (index : Nat) : + (Domain.size arity : Extension) * Extension.ofBase (FriDomain.queryPoint child index) * + Extension.ofBase (foldScale parent arity index) = 1 := by + have nonzero : G.ofNat (Domain.size arity) * FriDomain.queryPoint child index ≠ 0 := by + intro zero + exact ((G.mul_eq_zero_iff _ _).mp zero).elim + (G.ofNat_ne_zero_of_lt (Domain.size_positive arity) (Domain.size_lt_characteristic arity)) + (FriDomain.queryPoint_nonzero child index) + unfold foldScale + rw [G.pow_eq _ _ (Domain.size_lt_u64 arity), FriDomain.foldNode_power parent child arity dimensions] + change Extension.ofBase (G.ofNat (Domain.size arity)) * Extension.ofBase (FriDomain.queryPoint child index) * + Extension.ofBase (G.ofNat (Domain.size arity) * FriDomain.queryPoint child index).inverse = Extension.ofBase 1 + rw [← Extension.ofBase_mul, ← Extension.ofBase_mul, G.mul_inverse_cancel _ nonzero] + +theorem foldRow_polynomial (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (values : List Extension) + (shape : values.length = Domain.size arity) (point : Extension) : + foldRow parent arity index values point = some (horner point + (coefficients (foldSamples parent arity index values) (Extension.ofBase (foldScale parent arity index)))) := by + have nested : arity.val ≤ parent.val := by omega + have length := foldSamples_length parent arity index values shape + simp only [foldRow, gt_iff_lt, decide_eq_true_eq, Bool.or_eq_true, bne_iff_ne, _root_.or_assoc, + if_neg (by omega : ¬(parent.val < arity.val ∨ 2^(parent.val - arity.val) ≤ index ∨ values.length ≠ Domain.size arity))] + apply evaluate_polynomial _ (Extension.ofBase (FriDomain.queryPoint child index)) + · exact foldSamples_nodup parent arity nested bounded values shape + · rw [length]; exact Domain.size_positive arity + · exact foldSamples_powers parent child arity dimensions index values shape + · rw [length]; exact foldScale_inverse parent child arity dimensions index + +theorem foldRow_reject_shape (parent arity : Domain.Subgroup) (index : Nat) (values : List Extension) + (point : Extension) (malformed : arity.val > parent.val ∨ index ≥ 2^(parent.val - arity.val) ∨ values.length ≠ Domain.size arity) : + foldRow parent arity index values point = none := by + simp only [foldRow, decide_eq_true_eq, Bool.or_eq_true, bne_iff_ne, _root_.or_assoc, if_pos malformed] + +theorem foldRow_at_node (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (values : List Extension) + (shape : values.length = Domain.size arity) (root value : Extension) + (member : (root, value) ∈ foldSamples parent arity index values) : + foldRow parent arity index values root = some value := by + rw [foldRow_polynomial parent child arity dimensions bounded values shape] + congr 1 + apply coefficients_at_node (fun a b => (Extension.mul_eq_zero_iff a b).mp) + _ (Extension.ofBase (FriDomain.queryPoint child index)) _ root value _ _ _ _ member + · exact foldSamples_nodup parent arity (by omega) bounded values shape + · rw [foldSamples_length parent arity index values shape]; exact Domain.size_positive arity + · exact foldSamples_powers parent child arity dimensions index values shape + · rw [foldSamples_length parent arity index values shape]; exact foldScale_inverse parent child arity dimensions index + +theorem foldRow_evaluate (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (values candidate : List Extension) + (shape : values.length = Domain.size arity) (degree : candidate.length ≤ Domain.size arity) + (agrees : ∀ sample ∈ foldSamples parent arity index values, horner sample.1 candidate = sample.2) + (point : Extension) : foldRow parent arity index values point = some (horner point candidate) := by + rw [foldRow_polynomial parent child arity dimensions bounded values shape] + congr 1 + apply coefficients_evaluate (fun a b => (Extension.mul_eq_zero_iff a b).mp) + _ (Extension.ofBase (FriDomain.queryPoint child index)) _ candidate + · exact foldSamples_nodup parent arity (by omega) bounded values shape + · rw [foldSamples_length parent arity index values shape]; exact Domain.size_positive arity + · exact foldSamples_powers parent child arity dimensions index values shape + · rw [foldSamples_length parent arity index values shape]; exact foldScale_inverse parent child arity dimensions index + · rwa [foldSamples_length parent arity index values shape] + · exact agrees + +theorem foldRow_success {parent arity : Domain.Subgroup} {index : Nat} {values : List Extension} + {point result : Extension} (accepted : foldRow parent arity index values point = some result) : + arity.val ≤ parent.val ∧ index < 2^(parent.val - arity.val) ∧ values.length = Domain.size arity ∧ + ∃ candidate : List Extension, candidate.length ≤ Domain.size arity ∧ + (∀ sample ∈ foldSamples parent arity index values, horner sample.1 candidate = sample.2) ∧ + result = horner point candidate := by + have wellFormed : ¬(arity.val > parent.val ∨ index ≥ 2^(parent.val - arity.val) ∨ values.length ≠ Domain.size arity) := by + intro malformed + rw [foldRow_reject_shape parent arity index values point malformed] at accepted + cases accepted + have nested : arity.val ≤ parent.val := by omega + have bounded : index < 2^(parent.val - arity.val) := by omega + have shape : values.length = Domain.size arity := by omega + let child : Domain.Subgroup := ⟨parent.val - arity.val, by have := parent.isLt; omega⟩ + have dimensions : parent.val = child.val + arity.val := by change parent.val = parent.val - arity.val + arity.val; omega + refine ⟨nested, bounded, shape, + coefficients (foldSamples parent arity index values) (Extension.ofBase (foldScale parent arity index)), ?_, ?_, ?_⟩ + · have length := coefficients_length (foldSamples parent arity index values) (Extension.ofBase (foldScale parent arity index)) + rwa [foldSamples_length parent arity index values shape] at length + · intro sample member + have atNode := foldRow_at_node parent child arity dimensions bounded values shape sample.1 sample.2 member + rw [foldRow_polynomial parent child arity dimensions bounded values shape] at atNode + exact Option.some.inj atNode + · rw [foldRow_polynomial parent child arity dimensions bounded values shape] at accepted + exact (Option.some.inj accepted).symm + +end Aiur.NativeAIR.Interpolation diff --git a/Ix/Aiur/Proofs/KeyArtifact.lean b/Ix/Aiur/Proofs/KeyArtifact.lean new file mode 100644 index 000000000..5c1404af7 --- /dev/null +++ b/Ix/Aiur/Proofs/KeyArtifact.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.BoundVerifier +import Ix.Aiur.Proofs.KeyCodec + +/-! The backend's selected native key has a checked canonical v5 meaning. +This establishes byte interpretation and decoded graph evaluation. Equality +with the compiler's graph, native verifier execution and cryptographic +acceptance-to-satisfaction are separate obligations. -/ + +namespace Aiur.BoundVerifier +open NativeAIR + +theorem Backend.key_decodes {selection : Selection} (backend : Backend selection) : + KeyCodec.decode selection.key = some backend.keyData := + (KeyCodec.decodeCanonical_success backend.keyDecoded).1 + +theorem Backend.native_key_decodes {selection : Selection} (backend : Backend selection) : + KeyCodec.decodeCanonical backend.system.vkBytes = some backend.keyData := by + rw [backend.keyBound] + exact backend.keyDecoded + +theorem Backend.native_key_encoding {selection : Selection} (backend : Backend selection) : + KeyCodec.encode backend.keyData = backend.system.vkBytes := by + rw [backend.keyBound] + exact (KeyCodec.decodeCanonical_success backend.keyDecoded).2 + +theorem Backend.key_commitment {selection : Selection} (backend : Backend selection) : + KeyCodec.CommitmentValid backend.keyData.preprocessedCommitment := + KeyCodec.decode_commitment backend.key_decodes + +theorem Backend.key_graph_valid {selection : Selection} (backend : Backend selection) + {circuit : KeyCodec.Circuit} (member : circuit ∈ backend.keyData.circuits) : + circuit.graph.Valid circuit.widths := + (KeyCodec.Circuit.valid_graph ((KeyCodec.decode_valid backend.key_decodes).1 circuit member)).2.2.1 + +theorem Backend.key_graph_reflects {selection : Selection} (backend : Backend selection) + {circuit : KeyCodec.Circuit} (member : circuit ∈ backend.keyData.circuits) + (ops : EvalOps W) (values : Values W) (fits : values.Fits circuit.widths) : + ∃ trees full lookupValues, + circuit.graph.unfold = some trees ∧ circuit.graph.sweep ops values = some full ∧ + circuit.graph.sweepLookupPrefix ops values = some lookupValues ∧ + trees.size = circuit.graph.nodes.length ∧ full.size = circuit.graph.nodes.length ∧ + lookupValues.size = circuit.graph.lookupPrefix ∧ Reflects ops values trees full ∧ + readNodes full circuit.graph.zeros = evalRoots ops values trees circuit.graph.zeros ∧ + ∀ lookup ∈ circuit.graph.lookups, + readLookup lookupValues lookup = readLookup full lookup ∧ + readLookup lookupValues lookup = evalLookup ops values trees lookup := by + have valid := backend.key_graph_valid member + obtain ⟨trees, unfolded, treesSize⟩ := valid.unfold_defined + obtain ⟨full, swept, fullSize⟩ := valid.sweep_defined ops values fits + obtain ⟨lookupValues, lookupSwept, lookupSize⟩ := valid.lookup_sweep_defined ops values fits + have reflected := circuit.graph.sweep_reflects ops values unfolded swept + refine ⟨trees, full, lookupValues, unfolded, swept, lookupSwept, treesSize, fullSize, + lookupSize, reflected, reflected.readNodes _, ?_⟩ + intro lookup present + exact ⟨(valid.lookup_values_agree ops values swept lookupSwept lookupSize lookup present).symm, + valid.lookup_values_reflect ops values unfolded swept lookupSwept lookupSize lookup present⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/KeyCodec.lean b/Ix/Aiur/Proofs/KeyCodec.lean new file mode 100644 index 000000000..249b0a137 --- /dev/null +++ b/Ix/Aiur/Proofs/KeyCodec.lean @@ -0,0 +1,462 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.KeyCodec + +/-! Exact v5 byte framing, canonical round trips and checked graph meaning. -/ + +namespace Aiur.NativeAIR.KeyCodec + +def Reads (read : Reader α) (bytes : List UInt8) (value : α) : Prop := + ∀ rest, read (bytes ++ rest) = some (value, rest) + +theorem Reads.pure (value : α) : Reads (pure value) [] value := by + intro rest + rfl + +theorem Reads.bind {read : Reader α} {next : α → Reader β} + {left right : List UInt8} {middle : α} {value : β} + (first : Reads read left middle) (second : Reads (next middle) right value) : + Reads (read >>= next) (left ++ right) value := by + intro rest + change (StateT.bind read next) _ = _ + rw [List.append_assoc, StateT.bind, first (right ++ rest)] + exact second rest + +theorem Reads.map {read : Reader α} {bytes : List UInt8} {value : α} + (readValue : Reads read bytes value) (f : α → β) : + Reads (f <$> read) bytes (f value) := by + intro rest + change (StateT.map f read) _ = _ + rw [StateT.map, readValue rest] + rfl + +theorem Reads.result {read : Reader α} {bytes : List UInt8} {value : α} + (readValue : Reads read bytes value) (f : α → β) : + Reads (do let value ← read; Pure.pure (f value)) bytes (f value) := by + intro rest + change (StateT.bind read _) _ = _ + rw [StateT.bind, readValue rest] + rfl + +theorem readByte_reads (byte : UInt8) : Reads readByte [byte] byte := fun _ => rfl + +theorem Reads.byte {next : UInt8 → Reader α} {byte : UInt8} {bytes : List UInt8} {value : α} + (body : Reads (next byte) bytes value) : Reads (readByte >>= next) (byte :: bytes) value := + (readByte_reads byte).bind body + +theorem encodeNat_length (count value : Nat) : (encodeNat count value).length = count := by + induction count generalizing value with + | zero => rfl + | succ count ih => simp only [encodeNat, List.length_cons, ih] + +theorem readNat_reads (count value : Nat) (bounded : value < 256^count) : + Reads (readNat count) (encodeNat count value) value := by + induction count generalizing value with + | zero => + have zero : value = 0 := by simpa using bounded + subst value + exact Reads.pure 0 + | succ count ih => + have small : value / 256 < 256^count := by + apply (Nat.div_lt_iff_lt_mul (by decide : 0 < 256)).mpr + simpa only [Nat.pow_succ] using bounded + have rest := ih (value / 256) small + have number : value.toUInt8.toNat + 256 * (value / 256) = value := by + simp only [Nat.toUInt8_eq] + exact Nat.mod_add_div _ _ + rw [readNat, encodeNat] + apply Reads.byte + simpa only [number] using rest.result (fun n => value.toUInt8.toNat + 256 * n) + +theorem readMany_reads {read : Reader α} (encode : α → List UInt8) (values : List α) + (elements : ∀ value ∈ values, Reads read (encode value) value) : + Reads (readMany read values.length) (values.flatMap encode) values := by + induction values with + | nil => exact Reads.pure [] + | cons value values ih => + have first := elements value List.mem_cons_self + have rest := ih (fun value member => elements value (List.mem_cons_of_mem _ member)) + exact first.bind (rest.result (value :: ·)) + +theorem readVector_reads {read : Reader α} (encode : α → List UInt8) (values : List α) + (bounded : values.length < 65536) + (elements : ∀ value ∈ values, Reads read (encode value) value) : + Reads (readVector read) (encodeVector encode values) values := + (readNat_reads 2 values.length bounded).bind (readMany_reads encode values elements) + +def NodeWireFits : Node → Prop + | .konst _ | .isFirstRow | .isLastRow | .isTransition => True + | .var column => column.index < 65536 + | .publicInput index => index < 256 + | .add a b | .sub a b | .mul a b => a < 65536 ∧ b < 65536 + | .neg child => child < 65536 + +theorem readNode_reads (node : Node) (fits : NodeWireFits node) : + Reads readNode (encodeNode node) node := by + cases node with + | konst value => + simp only [encodeNode] + split + next small => + unfold readNode + apply Reads.byte + change Reads (do let n ← readNat 2; pure (Node.konst (G.ofNat n))) _ _ + simpa only [Function.comp_apply, G.ofNat_n] using + (readNat_reads 2 value.n small).result (Node.konst ∘ G.ofNat) + next _ => + have bounded : value.n < 256^8 := UInt64.toNat_lt value.val + unfold readNode + apply Reads.byte + change Reads (do let n ← readNat 8; pure (Node.konst (G.ofNat n))) _ _ + simpa only [Function.comp_apply, G.ofNat_n] using + (readNat_reads 8 value.n bounded).result (Node.konst ∘ G.ofNat) + | publicInput index => + unfold readNode encodeNode + apply Reads.byte + exact (readNat_reads 1 index fits).result Node.publicInput + | isFirstRow => intro rest; rfl + | isLastRow => intro rest; rfl + | isTransition => intro rest; rfl + | add a b | sub a b | mul a b => + unfold readNode encodeNode + apply Reads.byte + apply Reads.bind (readNat_reads 2 a fits.1) + exact (readNat_reads 2 b fits.2).result _ + | neg child => + unfold readNode encodeNode + apply Reads.byte + exact (readNat_reads 2 child fits).result Node.neg + | var column => + obtain ⟨source, offset, index⟩ := column + cases source <;> cases offset <;> unfold readNode encodeNode <;> + apply Reads.byte <;> exact (readNat_reads 2 index fits).result _ + +structure LookupWireFits (lookup : Lookup) : Prop where + multiplicity : lookup.multiplicity < 65536 + count : lookup.args.length < 65536 + args : ∀ arg ∈ lookup.args, arg < 65536 + +theorem readLookup_reads (lookup : Lookup) (fits : LookupWireFits lookup) : + Reads readLookup (encodeLookup lookup) lookup := by + unfold readLookup encodeLookup + apply Reads.bind (readNat_reads 2 lookup.multiplicity fits.multiplicity) + exact (readVector_reads (encodeNat 2) lookup.args fits.count + (fun arg member => readNat_reads 2 arg (fits.args arg member))).result _ + +structure CircuitWireFits (circuit : Circuit) : Prop where + mainWidth : circuit.mainWidth < 65536 + preprocessedWidth : circuit.preprocessedWidth < 65536 + preprocessedHeight : circuit.preprocessedHeight < 2^32 + maxConstraintDegree : circuit.maxConstraintDegree < 65536 + lookupGroupSize : circuit.lookupGroupSize < 256 + nodesCount : circuit.graph.nodes.length < 65536 + nodes : ∀ node ∈ circuit.graph.nodes, NodeWireFits node + zerosCount : circuit.graph.zeros.length < 65536 + zeros : ∀ index ∈ circuit.graph.zeros, index < 65536 + lookupsCount : circuit.graph.lookups.length < 65536 + lookups : ∀ lookup ∈ circuit.graph.lookups, LookupWireFits lookup + +theorem readCircuitData_reads (circuit : Circuit) (fits : CircuitWireFits circuit) : + Reads readCircuitData (encodeCircuit circuit) circuit := by + unfold readCircuitData encodeCircuit + simp only [List.append_assoc] + apply Reads.bind (readNat_reads 2 circuit.mainWidth fits.mainWidth) + apply Reads.bind (readNat_reads 2 circuit.preprocessedWidth fits.preprocessedWidth) + apply Reads.bind (readNat_reads 4 circuit.preprocessedHeight fits.preprocessedHeight) + apply Reads.bind (readNat_reads 2 circuit.maxConstraintDegree fits.maxConstraintDegree) + apply Reads.bind (readNat_reads 1 circuit.lookupGroupSize fits.lookupGroupSize) + apply Reads.bind (readVector_reads encodeNode circuit.graph.nodes fits.nodesCount + (fun node member => readNode_reads node (fits.nodes node member))) + apply Reads.bind (readVector_reads (encodeNat 2) circuit.graph.zeros fits.zerosCount + (fun index member => readNat_reads 2 index (fits.zeros index member))) + exact (readVector_reads encodeLookup circuit.graph.lookups fits.lookupsCount + (fun lookup member => readLookup_reads lookup (fits.lookups lookup member))).result _ + +theorem readCircuit_reads (circuit : Circuit) (fits : CircuitWireFits circuit) + (valid : circuit.valid = true) : Reads readCircuit (encodeCircuit circuit) circuit := by + intro rest + simp only [readCircuit, bind, StateT.bind, readCircuitData_reads circuit fits rest, + Option.bind_some, valid, ite_true, pure, StateT.pure] + +def ParametersWireFits (parameters : Parameters) : Prop := + ∀ value ∈ [parameters.logBlowup, parameters.capHeight, parameters.logFinalPolyLen, + parameters.maxLogArity, parameters.numQueries, parameters.commitProofOfWorkBits, + parameters.queryProofOfWorkBits], value < 65536 + +theorem readParameters_reads (parameters : Parameters) (fits : ParametersWireFits parameters) : + Reads readParameters (encodeParameters parameters) parameters := by + unfold ParametersWireFits at fits + simp only [List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, forall_eq] at fits + unfold readParameters encodeParameters + simp only [List.flatMap_cons, List.flatMap_nil, List.append_nil] + apply Reads.bind (readNat_reads 2 parameters.logBlowup fits.1) + apply Reads.bind (readNat_reads 2 parameters.capHeight fits.2.1) + apply Reads.bind (readNat_reads 2 parameters.logFinalPolyLen fits.2.2.1) + apply Reads.bind (readNat_reads 2 parameters.maxLogArity fits.2.2.2.1) + apply Reads.bind (readNat_reads 2 parameters.numQueries fits.2.2.2.2.1) + apply Reads.bind (readNat_reads 2 parameters.commitProofOfWorkBits fits.2.2.2.2.2.1) + exact (readNat_reads 2 parameters.queryProofOfWorkBits fits.2.2.2.2.2.2).result _ + +def CommitmentWireFits : Option MerkleCap → Prop + | none => True + | some cap => cap.length < 65536 ∧ cap.length.isPowerOfTwo ∧ ∀ digest ∈ cap, digest.length = 32 + +theorem readCommitment_reads (commitment : Option MerkleCap) (fits : CommitmentWireFits commitment) : + Reads readCommitment (encodeCommitment commitment) commitment := by + cases commitment with + | none => intro rest; rfl + | some cap => + unfold readCommitment encodeCommitment + apply Reads.byte + have body : Reads (readVector (readMany readByte 32)) (encodeVector id cap) cap := by + apply readVector_reads id cap fits.1 + intro digest member + have bytes := readMany_reads (fun byte => [byte]) digest (fun byte _ => readByte_reads byte) + simpa only [fits.2.2 digest member, List.flatMap_singleton', id_eq] using bytes + intro rest + change (StateT.bind (readVector (readMany readByte 32)) _) _ = _ + rw [StateT.bind, body rest] + simp only [bind, Option.bind_some, fits.2.1, ite_true, pure, StateT.pure] + +def IndexWireFits : Option Nat → Prop + | none => True + | some index => index < 65535 + +theorem readIndex_reads (index : Option Nat) (fits : IndexWireFits index) : + Reads readIndex (encodeIndex index) index := by + unfold readIndex encodeIndex + have bounded : index.getD 65535 < 65536 := by + cases index <;> simp only [IndexWireFits, Option.getD] at fits ⊢ <;> omega + have equal : (if index.getD 65535 = 65535 then none else some (index.getD 65535)) = index := by + cases index <;> simp only [IndexWireFits, Option.getD] at fits ⊢ + · rfl + · rw [if_neg (by omega)] + simpa only [equal] using + (readNat_reads 2 (index.getD 65535) bounded).result (fun n => if n = 65535 then none else some n) + +structure KeyWireFits (key : Key) : Prop where + parameters : ParametersWireFits key.parameters + circuitCount : key.circuits.length < 65536 + circuits : ∀ circuit ∈ key.circuits, CircuitWireFits circuit + commitment : CommitmentWireFits key.preprocessedCommitment + indexCount : key.preprocessedIndices.length = key.circuits.length + indices : ∀ index ∈ key.preprocessedIndices, IndexWireFits index + +theorem readKey_reads (key : Key) (fits : KeyWireFits key) + (valid : ∀ circuit ∈ key.circuits, circuit.valid = true) : + Reads readKey (encodeKey key) key := by + unfold readKey encodeKey + simp only [List.append_assoc] + apply Reads.bind (readParameters_reads key.parameters fits.parameters) + apply Reads.bind (readVector_reads encodeCircuit key.circuits fits.circuitCount + (fun circuit member => readCircuit_reads circuit (fits.circuits circuit member) (valid circuit member))) + apply Reads.bind (readCommitment_reads key.preprocessedCommitment fits.commitment) + rw [← fits.indexCount] + exact (readMany_reads encodeIndex key.preprocessedIndices + (fun index member => readIndex_reads index (fits.indices index member))).result _ + +theorem decode_encode (key : Key) (fits : KeyWireFits key) + (valid : ∀ circuit ∈ key.circuits, circuit.valid = true) : decode (encode key) = some key := by + have read := readKey_reads key fits valid [] + simp only [List.append_nil] at read + simp only [decode, encode, List.toList_data_toByteArray, read, + bind, Option.bind_some, List.isEmpty_nil, ite_true] + +theorem decodeCanonical_success {bytes : ByteArray} {key : Key} + (accepted : decodeCanonical bytes = some key) : decode bytes = some key ∧ encode key = bytes := by + unfold decodeCanonical at accepted + cases parsed : decode bytes with + | none => simp [parsed, bind, Option.bind] at accepted + | some result => + simp only [parsed, bind, Option.bind_some] at accepted + split at accepted + next encoded => cases accepted; exact ⟨rfl, encoded⟩ + next => cases accepted + +theorem decodeCanonical_encode (key : Key) (fits : KeyWireFits key) + (valid : ∀ circuit ∈ key.circuits, circuit.valid = true) : + decodeCanonical (encode key) = some key := by + simp only [decodeCanonical, decode_encode key fits valid, bind, Option.bind_some, ite_true] + +theorem canonical_bytes_unique {first second : ByteArray} {key : Key} + (left : decodeCanonical first = some key) (right : decodeCanonical second = some key) : first = second := + (decodeCanonical_success left).2.symm.trans (decodeCanonical_success right).2 + +theorem encode_injective {first second : Key} (leftFits : KeyWireFits first) (rightFits : KeyWireFits second) + (leftValid : ∀ circuit ∈ first.circuits, circuit.valid = true) + (rightValid : ∀ circuit ∈ second.circuits, circuit.valid = true) + (equal : encode first = encode second) : first = second := by + have decoded := congrArg decode equal + rw [decode_encode first leftFits leftValid, decode_encode second rightFits rightValid] at decoded + exact Option.some.inj decoded + +def Returns (read : Reader α) (property : α → Prop) : Prop := + ∀ bytes value rest, read bytes = some (value, rest) → property value + +theorem Returns.pure {value : α} {property : α → Prop} (valid : property value) : + Returns (Pure.pure value) property := by + intro bytes result rest parsed + cases parsed + exact valid + +theorem Returns.failure (property : α → Prop) : Returns failure property := by + intro bytes value rest parsed + cases parsed + +theorem Returns.bind {read : Reader α} {next : α → Reader β} {left : α → Prop} {right : β → Prop} + (first : Returns read left) (second : ∀ value, left value → Returns (next value) right) : + Returns (read >>= next) right := by + intro bytes value rest parsed + change (StateT.bind read next) bytes = _ at parsed + cases readFirst : read bytes with + | none => simp [StateT.bind, readFirst] at parsed + | some pair => + obtain ⟨middle, unread⟩ := pair + rw [StateT.bind, readFirst] at parsed + change next middle unread = some (value, rest) at parsed + exact second middle (first bytes middle unread readFirst) unread value rest parsed + +theorem Returns.bind_any {read : Reader α} {next : α → Reader β} {property : β → Prop} + (body : ∀ value, Returns (next value) property) : Returns (read >>= next) property := + Returns.bind (fun _ _ _ _ => True.intro) (fun value _ => body value) + +theorem Returns.weaken {read : Reader α} {left right : α → Prop} + (valid : Returns read left) (weaken : ∀ value, left value → right value) : Returns read right := + fun bytes value rest parsed => weaken value (valid bytes value rest parsed) + +theorem Returns.result {read : Reader α} {left : α → Prop} {right : β → Prop} + (valid : Returns read left) (f : α → β) (preserves : ∀ value, left value → right (f value)) : + Returns (do let value ← read; Pure.pure (f value)) right := + Returns.bind valid (fun value known => Returns.pure (preserves value known)) + +theorem readMany_returns {read : Reader α} {property : α → Prop} (valid : Returns read property) (count : Nat) : + Returns (readMany read count) (fun values => values.length = count ∧ ∀ value ∈ values, property value) := by + induction count with + | zero => exact Returns.pure ⟨rfl, by simp⟩ + | succ count ih => + refine Returns.bind (right := fun values : List α => + values.length = count + 1 ∧ ∀ value ∈ values, property value) valid ?_ + intro value first + refine Returns.result (right := fun values : List α => + values.length = count + 1 ∧ ∀ value ∈ values, property value) ih (value :: ·) ?_ + intro values rest + exact ⟨by simp only [List.length_cons, rest.1], fun entry member => by + rcases List.mem_cons.mp member with rfl | member + · exact first + · exact rest.2 entry member⟩ + +theorem readVector_returns {read : Reader α} {property : α → Prop} (valid : Returns read property) : + Returns (readVector read) (fun values => ∀ value ∈ values, property value) := + Returns.bind_any (fun count => (readMany_returns valid count).weaken (fun _ known => known.2)) + +theorem readCircuit_returns : Returns readCircuit (fun circuit => circuit.valid = true) := by + unfold readCircuit + apply Returns.bind_any + intro circuit + split + next valid => exact Returns.pure valid + next => exact Returns.failure _ + +def CommitmentValid : Option MerkleCap → Prop + | none => True + | some cap => cap.length.isPowerOfTwo ∧ ∀ digest ∈ cap, digest.length = 32 + +theorem readCommitment_returns : Returns readCommitment CommitmentValid := by + unfold readCommitment + refine Returns.bind_any (property := CommitmentValid) ?_ + intro byte + split + · exact Returns.pure True.intro + · refine Returns.bind (right := CommitmentValid) + (readVector_returns ((readMany_returns (read := readByte) (property := fun _ => True) + (fun _ _ _ _ => True.intro) 32).weaken (fun _ known => known.1))) ?_ + intro cap digests + split + next power => exact Returns.pure ⟨power, digests⟩ + next => exact Returns.failure _ + · exact Returns.failure _ + +theorem readKey_returns : Returns readKey (fun key => + (∀ circuit ∈ key.circuits, circuit.valid = true) ∧ key.preprocessedIndices.length = key.circuits.length) := by + unfold readKey + refine Returns.bind_any (read := readParameters) (property := fun key : Key => + (∀ circuit ∈ key.circuits, circuit.valid = true) ∧ key.preprocessedIndices.length = key.circuits.length) ?_ + intro parameters + refine Returns.bind (right := fun key : Key => + (∀ circuit ∈ key.circuits, circuit.valid = true) ∧ key.preprocessedIndices.length = key.circuits.length) + (readVector_returns readCircuit_returns) ?_ + intro circuits valid + refine Returns.bind_any (read := readCommitment) (property := fun key : Key => + (∀ circuit ∈ key.circuits, circuit.valid = true) ∧ key.preprocessedIndices.length = key.circuits.length) ?_ + intro commitment + apply Returns.result (right := fun key : Key => + (∀ circuit ∈ key.circuits, circuit.valid = true) ∧ key.preprocessedIndices.length = key.circuits.length) + (readMany_returns (read := readIndex) (property := fun _ => True) + (fun _ _ _ _ => True.intro) circuits.length) + (fun indices => Key.mk parameters circuits commitment indices) + intro indices known + exact ⟨valid, known.1⟩ + +theorem decode_success {bytes : ByteArray} {key : Key} (parsed : decode bytes = some key) : + readKey bytes.data.toList = some (key, []) := by + unfold decode at parsed + cases read : readKey bytes.data.toList with + | none => simp [read, bind, Option.bind] at parsed + | some pair => + obtain ⟨result, rest⟩ := pair + simp only [read, bind, Option.bind_some] at parsed + split at parsed + next empty => + have empty : rest = [] := List.isEmpty_iff.mp empty + cases parsed + simp only [empty] + next => cases parsed + +theorem decode_valid {bytes : ByteArray} {key : Key} (parsed : decode bytes = some key) : + (∀ circuit ∈ key.circuits, circuit.valid = true) ∧ key.preprocessedIndices.length = key.circuits.length := + readKey_returns _ _ _ (decode_success parsed) + +theorem readKey_commitment : Returns readKey (fun key => CommitmentValid key.preprocessedCommitment) := by + unfold readKey + refine Returns.bind_any (read := readParameters) + (property := fun key : Key => CommitmentValid key.preprocessedCommitment) ?_ + intro parameters + refine Returns.bind_any (read := readVector readCircuit) + (property := fun key : Key => CommitmentValid key.preprocessedCommitment) ?_ + intro circuits + refine Returns.bind (right := fun key : Key => CommitmentValid key.preprocessedCommitment) + readCommitment_returns ?_ + intro commitment valid + refine Returns.bind_any (read := readMany readIndex circuits.length) + (property := fun key : Key => CommitmentValid key.preprocessedCommitment) ?_ + intro indices + exact Returns.pure valid + +theorem decode_commitment {bytes : ByteArray} {key : Key} (parsed : decode bytes = some key) : + CommitmentValid key.preprocessedCommitment := readKey_commitment _ _ _ (decode_success parsed) + +theorem Circuit.valid_graph {circuit : Circuit} (valid : circuit.valid = true) : + 1 ≤ circuit.lookupGroupSize ∧ circuit.lookupGroupSize ≤ 8 ∧ + circuit.graph.Valid circuit.widths ∧ circuit.computedDegree = some circuit.maxConstraintDegree := by + simp only [Circuit.valid, Bool.and_eq_true, decide_eq_true_eq, beq_iff_eq] at valid + obtain ⟨⟨⟨positive, bounded⟩, prefixRead⟩, degrees⟩ := valid + cases read : checkedGraphPrefix circuit.widths circuit.graph with + | none => simp only [read, Option.isSome_none, Bool.false_eq_true] at prefixRead + | some index => exact ⟨positive, bounded, (checkedGraphPrefix_iff _ _ _).mp read |>.1, degrees⟩ + +theorem decoded_graph_sweeps {bytes : ByteArray} {key : Key} (parsed : decode bytes = some key) + {circuit : Circuit} (member : circuit ∈ key.circuits) (ops : EvalOps W) (values : Values W) + (fits : values.Fits circuit.widths) : + ∃ buffer, circuit.graph.sweep ops values = some buffer ∧ buffer.size = circuit.graph.nodes.length := + ((Circuit.valid_graph ((decode_valid parsed).1 circuit member)).2.2.1).sweep_defined ops values fits + +theorem decode_encoded_suffix (key : Key) (fits : KeyWireFits key) + (valid : ∀ circuit ∈ key.circuits, circuit.valid = true) (rest : List UInt8) : + decode ((encodeKey key ++ rest).toByteArray) = if rest = [] then some key else none := by + simp only [decode, List.toList_data_toByteArray, readKey_reads key fits valid rest, bind, Option.bind_some] + cases rest <;> rfl + +end Aiur.NativeAIR.KeyCodec diff --git a/Ix/Aiur/Proofs/LayoutProjection.lean b/Ix/Aiur/Proofs/LayoutProjection.lean new file mode 100644 index 000000000..3ceb34d5f --- /dev/null +++ b/Ix/Aiur/Proofs/LayoutProjection.lean @@ -0,0 +1,165 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LayoutState + +/-! The state projection of the actual layout pass. Constructing revised +continuations preserves the same degree, column, selector and lookup state +as folding just those state effects. -/ + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode + +theorem blockLayout_eq_discard_relayout (block : Block) : + blockLayout block = discard (relayoutBlock block) := by + funext initial + rw [relayoutBlock.eq_def] + rfl + +private theorem fold_project {α β γ σ : Type} (items : List α) + (step : β → α → StateM σ β) (summary : γ → α → StateM σ γ) + (project : β → γ) + (effect : ∀ acc item state, + (project ((step acc item).run state).1, ((step acc item).run state).2) = + (summary (project acc) item).run state) + (acc : β) (initial : σ) : + (project ((items.foldlM step acc).run initial).1, ((items.foldlM step acc).run initial).2) = + (items.foldlM summary (project acc)).run initial := by + induction items generalizing acc initial with + | nil => rfl + | cons item items ih => + simp only [List.foldlM_cons] + change (project ((items.foldlM step ((step acc item).run initial).1).run + ((step acc item).run initial).2).1, + ((items.foldlM step ((step acc item).run initial).1).run + ((step acc item).run initial).2).2) = + (items.foldlM summary ((summary (project acc) item).run initial).1).run + ((summary (project acc) item).run initial).2 + rw [← effect acc item initial] + exact ih _ _ + +private def fullStep (shared : SharedData) (degrees : Array Nat) + (acc : Array (G × Block) × SharedData) (pair : G × Block) : + LayoutM (Array (G × Block) × SharedData) := do + setSharedData shared + let body ← relayoutBlock pair.2 + let used ← getSharedData + setDegrees degrees + return (acc.1.push (pair.1, body), acc.2.maximals used) + +private def summaryStep (shared : SharedData) (degrees : Array Nat) + (acc : SharedData) (pair : G × Block) : LayoutM SharedData := do + setSharedData shared + blockLayout pair.2 + let used ← getSharedData + setDegrees degrees + return acc.maximals used + +private theorem branch_projection (branches : Array (G × Block)) + (shared : SharedData) (degrees : Array Nat) (initial : LayoutMState) : + let full := (branches.attach.foldlM + (fun acc pair => fullStep shared degrees acc pair.val) (#[], shared)).run initial + (full.1.2, full.2) = (branches.attach.foldlM + (fun acc pair => summaryStep shared degrees acc pair.val) shared).run initial := by + simp only + rw [← Array.foldlM_toList, ← Array.foldlM_toList] + apply fold_project (project := Prod.snd) + intro acc pair state + simp only [summaryStep, fullStep, blockLayout_eq_discard_relayout] + rfl + +private theorem fullFold_size {α : Type} (items : List α) (pairOf : α → G × Block) + (shared : SharedData) (degrees : Array Nat) + (acc : Array (G × Block) × SharedData) (initial : LayoutMState) : + ((items.foldlM (fun acc item => fullStep shared degrees acc (pairOf item)) acc).run initial).1.1.size = + acc.1.size + items.length := by + induction items generalizing acc initial with + | nil => simp only [List.foldlM_nil, List.length_nil, Nat.add_zero]; rfl + | cons item items ih => + rw [List.foldlM_cons] + have rest := ih ((fullStep shared degrees acc (pairOf item)).run initial).1 + ((fullStep shared degrees acc (pairOf item)).run initial).2 + change ((items.foldlM (fun acc item => fullStep shared degrees acc (pairOf item)) + ((fullStep shared degrees acc (pairOf item)).run initial).1).run + ((fullStep shared degrees acc (pairOf item)).run initial).2).1.1.size = _ + rw [rest] + change (acc.1.push _).size + items.length = _ + simp only [Array.size_push, List.length_cons] + omega + +private theorem branch_size (branches : Array (G × Block)) + (shared : SharedData) (degrees : Array Nat) (initial : LayoutMState) : + ((branches.attach.foldlM (fun acc pair => fullStep shared degrees acc pair.val) + (#[], shared)).run initial).1.1.size = branches.size := by + rw [← Array.foldlM_toList] + simpa only [Array.size_empty, Nat.zero_add, Array.length_toList, Array.size_attach] using + fullFold_size branches.attach.toList Subtype.val shared degrees (#[], shared) initial + +theorem ctrlLayout_eq_def (ctrl : Ctrl) : ctrlLayout ctrl = (match ctrl with + | .match _ branches fallback => do + let shared ← getSharedData + let degrees ← getDegrees + let maximal ← branches.attach.foldlM + (fun acc pair => summaryStep shared degrees acc pair.val) shared + let final ← match fallback with + | none => pure maximal + | some block => do + setSharedData shared + bumpAuxiliaries branches.size + blockLayout block + let used ← getSharedData + setDegrees degrees + pure (maximal.maximals used) + setSharedData final + | .return .. | .yield .. => bumpSelectors + | .matchContinue index branches fallback outputs _ _ cont => do + ctrlLayout (.match index branches fallback) + bumpAuxiliaries outputs + pushDegrees (.replicate outputs 1) + blockLayout cont) := by + cases ctrl with + | «return» sel outs => funext initial; rw [ctrlLayout, relayoutCtrl.eq_def]; rfl + | «yield» sel outs => funext initial; rw [ctrlLayout, relayoutCtrl.eq_def]; rfl + | «match» index branches fallback => + funext initial + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let full := branches.attach.foldlM + (fun acc pair => fullStep shared initial.degrees acc pair.val) (#[], shared) + let summary := branches.attach.foldlM + (fun acc pair => summaryStep shared initial.degrees acc pair.val) shared + have projected := branch_projection branches shared initial.degrees initial + have sized := branch_size branches shared initial.degrees initial + have valueEq : (full.run initial).1.2 = (summary.run initial).1 := congrArg Prod.fst projected + have stateEq : (full.run initial).2 = (summary.run initial).2 := congrArg Prod.snd projected + rw [ctrlLayout, relayoutCtrl.eq_def] + cases fallback with + | none => + change (setSharedData (full.run initial).1.2).run (full.run initial).2 = + (setSharedData (summary.run initial).1).run (summary.run initial).2 + rw [valueEq, stateEq] + | some block => + simp only [blockLayout_eq_discard_relayout] + change (do + setSharedData shared + bumpAuxiliaries (full.run initial).1.1.size + discard (relayoutBlock block) + let used ← getSharedData + setDegrees initial.degrees + setSharedData ((full.run initial).1.2.maximals used)).run (full.run initial).2 = + (do + setSharedData shared + bumpAuxiliaries branches.size + discard (relayoutBlock block) + let used ← getSharedData + setDegrees initial.degrees + setSharedData ((summary.run initial).1.maximals used)).run (summary.run initial).2 + rw [valueEq, stateEq, sized] + | matchContinue index branches fallback outputs aux slots cont => + funext initial + rw [ctrlLayout, relayoutCtrl.eq_def] + simp only [ctrlLayout, relayoutCtrl.eq_def, blockLayout_eq_discard_relayout] + cases fallback <;> rfl + +end Aiur.Concrete.Bytecode diff --git a/Ix/Aiur/Proofs/LayoutState.lean b/Ix/Aiur/Proofs/LayoutState.lean new file mode 100644 index 000000000..f0e966b67 --- /dev/null +++ b/Ix/Aiur/Proofs/LayoutState.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Compiler.Layout + +/-! State fields that every operation layout preserves, for all three +component rank modes and the generic ordered fallback. -/ + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode + +theorem getDegree_list (indices : List ValIdx) (initial : LayoutMState) : + (indices.mapM getDegree).run initial = (indices.map (fun i => initial.degrees[i]?.getD 0), initial) := by + induction indices with + | nil => rfl + | cons index indices ih => + rw [List.mapM_cons] + change (let (values, final) := (indices.mapM getDegree).run initial; + (initial.degrees[index]?.getD 0 :: values, final)) = + (initial.degrees[index]?.getD 0 :: indices.map (fun i => initial.degrees[i]?.getD 0), initial) + rw [ih] + +theorem getDegree_array (indices : Array ValIdx) : + indices.mapM getDegree = (fun initial => pure (indices.map (fun i => initial.degrees[i]?.getD 0), initial)) := by + rw [Array.mapM_eq_mapM_toList] + funext initial + change (let (values, final) := (indices.toList.mapM getDegree).run initial; + (values.toArray, final)) = (indices.map (fun i => initial.degrees[i]?.getD 0), initial) + rw [getDegree_list] + simp only [← List.map_toArray, Array.toArray_toList] + +theorem opLayout_fixed (op : Op) (initial : LayoutMState) : + ((opLayout op).run initial).2.functionLayout.inputSize = initial.functionLayout.inputSize ∧ + ((opLayout op).run initial).2.functionLayout.selectors = initial.functionLayout.selectors := by + cases op + case call function args outputSize unconstrained => + cases unconstrained <;> cases rank : initial.callRanks[function]?.getD .ordered <;> + simp [opLayout, bumpLookups, bumpAuxiliaries, pushDegrees, + StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + bind, pure, rank] + all_goals + simp only [opLayout, getDegree_array, bumpLookups, bumpAuxiliaries, getDegree, + pushDegree, pushDegrees, addMemSize] + all_goals dsimp [StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + instMonadStateOfMonadStateOf, instMonadStateOfStateTOfMonad, bind, pure] + all_goals try split + all_goals exact ⟨rfl, rfl⟩ + +theorem opLayout_callRanks (op : Op) (initial : LayoutMState) : + ((opLayout op).run initial).2.callRanks = initial.callRanks := by + cases op + case call function args outputSize unconstrained => + cases unconstrained <;> cases rank : initial.callRanks[function]?.getD .ordered <;> + simp [opLayout, bumpLookups, bumpAuxiliaries, pushDegrees, + StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + bind, pure, rank] + all_goals + simp only [opLayout, getDegree_array, bumpLookups, bumpAuxiliaries, getDegree, + pushDegree, pushDegrees, addMemSize] + all_goals dsimp [StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + instMonadStateOfMonadStateOf, instMonadStateOfStateTOfMonad, bind, pure] + all_goals try split + all_goals rfl + +private theorem ops_fold_inputSize (ops : List Op) (initial : LayoutMState) : + ((ops.foldlM (fun _ op => opLayout op) ()).run initial).2.functionLayout.inputSize = + initial.functionLayout.inputSize := by + induction ops generalizing initial with + | nil => rfl + | cons op ops ih => + rw [List.foldlM_cons] + exact (ih ((opLayout op).run initial).2).trans (opLayout_fixed op initial).1 + +theorem opsLayout_inputSize (ops : Array Op) (initial : LayoutMState) : + ((ops.forM opLayout).run initial).2.functionLayout.inputSize = + initial.functionLayout.inputSize := by + unfold Array.forM + rw [← Array.foldlM_toList] + exact ops_fold_inputSize ops.toList initial + +/-- The input arity and the selected call modes stay fixed throughout layout. -/ +def LayoutMState.context (state : LayoutMState) : Nat × Array CallRank := + (state.functionLayout.inputSize, state.callRanks) + +theorem opLayout_context (op : Op) (initial : LayoutMState) : + ((opLayout op).run initial).2.context = initial.context := + Prod.ext (opLayout_fixed op initial).1 (opLayout_callRanks op initial) + +private theorem ops_fold_context (ops : List Op) (initial : LayoutMState) : + ((ops.foldlM (fun _ op => opLayout op) ()).run initial).2.context = initial.context := by + induction ops generalizing initial with + | nil => rfl + | cons op ops ih => + rw [List.foldlM_cons] + exact (ih ((opLayout op).run initial).2).trans (opLayout_context op initial) + +theorem opsLayout_context (ops : Array Op) (initial : LayoutMState) : + ((ops.forM opLayout).run initial).2.context = initial.context := by + unfold Array.forM + rw [← Array.foldlM_toList] + exact ops_fold_context ops.toList initial + +end Aiur.Concrete.Bytecode diff --git a/Ix/Aiur/Proofs/LocalConstraints.lean b/Ix/Aiur/Proofs/LocalConstraints.lean new file mode 100644 index 000000000..add26a239 --- /dev/null +++ b/Ix/Aiur/Proofs/LocalConstraints.lean @@ -0,0 +1,190 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Field +import Ix.Aiur.Proofs.Memory + +/-! +Arithmetic extraction from the native AIR's local polynomial forms. + +Boolean selector equations, the two `eq_zero` equations, case equality and +default disequality imply their semantic properties over `G`. Boolean sums +select at most one branch when the number of summands is below the field +characteristic. The bound is explicit and a cancellation counterexample +shows its necessity. These sums use the native emitter's left-fold order. + +Memory-table functionality now follows from its polynomial equations and +trace-height bound without separately assuming boolean selectors. Decoding +the Rust expressions, trace widths and transition selectors, and extracting +exact lookup balance from proof verification, remain separate obligations. +-/ + +namespace Aiur.AIR + +/-- Selector-column equation used in function and memory circuits. -/ +def booleanConstraint (value : G) : G := value * (value - 1) + +/-- Block and grouped-circuit selector equation, with the opposite sign. -/ +def oneSubBooleanConstraint (value : G) : G := value * (1 - value) + +def selectorSum (selectors : List G) : G := selectors.foldl (· + ·) 0 + +theorem foldl_add_eq (selectors : List G) (initial : G) : + selectors.foldl (· + ·) initial = initial + selectorSum selectors := by + induction selectors generalizing initial with + | nil => exact (G.add_zero initial).symm + | cons head tail ih => + simp only [List.foldl_cons, selectorSum] + rw [ih, ih] + simp only [G.zero_add, G.add_assoc] + +theorem selectorSum_cons (head : G) (tail : List G) : + selectorSum (head :: tail) = head + selectorSum tail := by + simpa only [selectorSum, List.foldl_cons, G.zero_add] using foldl_add_eq tail head + +theorem selectorSum_eq_count (selectors : List G) + (boolean : ∀ value ∈ selectors, value = 0 ∨ value = 1) : + selectorSum selectors = G.ofNat (selectors.count 1) := by + induction selectors with + | nil => rfl + | cons head tail ih => + have rest : ∀ value ∈ tail, value = 0 ∨ value = 1 := + fun value member => boolean value (List.mem_cons_of_mem _ member) + rcases boolean head List.mem_cons_self with rfl | rfl + · rw [selectorSum_cons, G.zero_add, List.count_cons_of_ne (Ne.symm G.one_ne_zero), ih rest] + · rw [selectorSum_cons, List.count_cons_self, ih rest, G.ofNat_add, G.add_comm] + rfl + +theorem selectorSum_n_eq_count {selectors : List G} + (boolean : ∀ value ∈ selectors, value = 0 ∨ value = 1) + (bounded : selectors.length < gSize.toNat) : + (selectorSum selectors).n = selectors.count 1 := by + rw [selectorSum_eq_count selectors boolean, G.n_ofNat] + exact Nat.mod_eq_of_lt (Nat.lt_of_le_of_lt List.count_le_length bounded) + +theorem selectorSum_count_le_one {selectors : List G} + (individual : ∀ value ∈ selectors, booleanConstraint value = 0) + (combined : oneSubBooleanConstraint (selectorSum selectors) = 0) + (bounded : selectors.length < gSize.toNat) : selectors.count 1 ≤ 1 := by + have boolean : ∀ value ∈ selectors, value = 0 ∨ value = 1 := + fun value member => G.boolean_of_constraint (individual value member) + have count := selectorSum_n_eq_count boolean bounded + rcases G.boolean_of_one_sub_constraint combined with zero | one + · rw [zero] at count + change 0 = selectors.count 1 at count + omega + · rw [one] at count + change 1 = selectors.count 1 at count + omega + +theorem selectorSum_inactive {selectors : List G} + (individual : ∀ value ∈ selectors, booleanConstraint value = 0) + (bounded : selectors.length < gSize.toNat) + (inactive : selectorSum selectors = 0) : ∀ value ∈ selectors, value = 0 := by + have boolean : ∀ value ∈ selectors, value = 0 ∨ value = 1 := + fun value member => G.boolean_of_constraint (individual value member) + have count := selectorSum_n_eq_count boolean bounded + rw [inactive] at count + have absent : (1 : G) ∉ selectors := List.count_eq_zero.mp count.symm + intro value member + rcases boolean value member with zero | one + · exact zero + · subst value; exact False.elim (absent member) + +theorem selectorSum_active_count {selectors : List G} + (individual : ∀ value ∈ selectors, booleanConstraint value = 0) + (bounded : selectors.length < gSize.toNat) + (active : selectorSum selectors = 1) : selectors.count 1 = 1 := by + have boolean : ∀ value ∈ selectors, value = 0 ∨ value = 1 := + fun value member => G.boolean_of_constraint (individual value member) + have count := selectorSum_n_eq_count boolean bounded + rw [active] at count + exact count.symm + +/-- An active bounded sum has exactly one active occurrence; all other +occurrences are zero, even when list values repeat. -/ +theorem selectorSum_active_split {selectors : List G} + (individual : ∀ value ∈ selectors, booleanConstraint value = 0) + (bounded : selectors.length < gSize.toNat) (active : selectorSum selectors = 1) : + ∃ before after : List G, selectors = before ++ 1 :: after ∧ + ∀ value ∈ before ++ after, value = 0 := by + have count := selectorSum_active_count individual bounded active + have member : (1 : G) ∈ selectors := List.count_pos_iff.mp (by omega) + obtain ⟨before, after, equal, _⟩ := List.eq_append_cons_of_mem member + refine ⟨before, after, equal, ?_⟩ + rw [equal, List.count_append, List.count_cons_self] at count + have absent : (1 : G) ∉ before ++ after := by + apply List.count_eq_zero.mp + rw [List.count_append] + omega + intro value member + have member' : value ∈ selectors := by + rw [equal] + rcases List.mem_append.mp member with left | right + · exact List.mem_append_left _ left + · exact List.mem_append_right _ (List.mem_cons_of_mem _ right) + rcases G.boolean_of_constraint (individual value member') with zero | one + · exact zero + · subst value; exact False.elim (absent member) + +/-- Boolean summands alone do not prevent a full characteristic of active +branches from being represented by an inactive field sum. -/ +theorem selectorSum_characteristic_cancel : + selectorSum (List.replicate gSize.toNat (1 : G)) = 0 := by + rw [selectorSum_eq_count _ (fun value member => + Or.inr (List.eq_of_mem_replicate member)), List.count_replicate_self] + rfl + +theorem nonzero_multiplicity_selector_one {multiplicity selector : G} + (satisfied : activityConstraint multiplicity selector = 0) + (nonzero : multiplicity ≠ 0) : selector = 1 := by + have zero := G.mul_eq_zero_of_left_ne_zero nonzero satisfied + exact ((G.sub_eq_zero_iff 1 selector).mp zero).symm + +theorem active_eqZero {selector input inverse output : G} (active : selector = 1) + (annihilate : selector * input * output = 0) + (complement : selector * (input * inverse + output - 1) = 0) : + output = G.eqZero input := by + rw [active, G.mul_comm (1 : G) input, G.mul_one] at annihilate + rw [active, G.mul_comm, G.mul_one] at complement + exact G.eqZero_of_constraints annihilate complement + +theorem active_case {selector matched key : G} (active : selector = 1) + (satisfied : selector * (matched - key) = 0) : matched = key := by + rw [active, G.mul_comm, G.mul_one] at satisfied + exact (G.sub_eq_zero_iff matched key).mp satisfied + +theorem active_default {selector matched key inverse : G} (active : selector = 1) + (satisfied : selector * ((matched - key) * inverse - 1) = 0) : matched ≠ key := by + rw [active, G.mul_comm, G.mul_one] at satisfied + intro equal + have nonzero := G.ne_zero_of_inverse_constraint satisfied + exact nonzero ((G.sub_eq_zero_iff matched key).mpr equal) + +/-- The four memory polynomial forms, with interior transition gating +resolved and column widths decoded. No boolean-selector premise. -/ +structure MemoryRowsPolynomials (width : Nat) (rows : Array MemoryRow) : Prop where + selectors : ∀ i (hi : i < rows.size), booleanConstraint rows[i].selector = 0 + activity : ∀ i (hi : i < rows.size), activityConstraint rows[i].multiplicity rows[i].selector = 0 + widths : ∀ i (hi : i < rows.size), rows[i].contents.size = width + activityTransition : ∀ i (hi : i + 1 < rows.size), + memoryActivityTransition (rows[i]'(by omega)) rows[i + 1] = 0 + pointerTransition : ∀ i (hi : i + 1 < rows.size), + memoryPointerTransition (rows[i]'(by omega)) rows[i + 1] = 0 + +theorem MemoryRowsPolynomials.valid {width : Nat} {rows : Array MemoryRow} + (polynomials : MemoryRowsPolynomials width rows) : MemoryRowsValid width rows := + ⟨fun i hi => G.boolean_of_constraint (polynomials.selectors i hi), + polynomials.activity, polynomials.widths, polynomials.activityTransition, polynomials.pointerTransition⟩ + +theorem MemoryRowsPolynomials.functional (tables : Nat → Array MemoryRow) + (polynomials : ∀ width, MemoryRowsPolynomials width (tables width)) + (bounded : ∀ width, (tables width).size < gSize.toNat) + {width : Nat} {pointer : G} {left right : Array G} + (loadedLeft : memoryFacts tables width pointer left) + (loadedRight : memoryFacts tables width pointer right) : left = right := + memoryFacts_functional tables (fun width => (polynomials width).valid) bounded loadedLeft loadedRight + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/LogUp.lean b/Ix/Aiur/Proofs/LogUp.lean new file mode 100644 index 000000000..8d03b68fa --- /dev/null +++ b/Ix/Aiur/Proofs/LogUp.lean @@ -0,0 +1,248 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LogUpAlgebra +import Ix.Aiur.KeyCodec + +/-! Checked reads, complete grouping, and the polynomial equations extracted +from the executable logUp evaluator. These results preserve both coordinates +and their order, including the last-row boundary injection. -/ + +namespace Aiur.NativeAIR.LogUp + +theorem groupCount_positive (groupSize lookupCount : Nat) : 0 < groupCount groupSize lookupCount := by + simp only [groupCount]; omega + +theorem groupCount_covers (groupSize lookupCount : Nat) : + lookupCount ≤ groupCount groupSize lookupCount * max groupSize 1 := by + apply (Nat.le_mul_iff_le_left (by omega : 0 < max groupSize 1)).mpr + exact Nat.le_max_right _ _ + +theorem groupCount_zero (lookupCount : Nat) : groupCount 0 lookupCount = groupCount 1 lookupCount := rfl + +theorem groupCount_empty (groupSize : Nat) : groupCount groupSize 0 = 1 := by + have positive : 0 < max groupSize 1 := by omega + simp only [groupCount, Nat.zero_add, Nat.div_eq_of_lt (by omega : max groupSize 1 - 1 < max groupSize 1)] + rfl + +theorem groupCount_key (circuit : KeyCodec.Circuit) (positive : 0 < circuit.lookupGroupSize) : + groupCount circuit.lookupGroupSize circuit.graph.lookups.length = circuit.groups := by + simp only [groupCount, KeyCodec.Circuit.groups, Nat.max_eq_left positive] + +theorem chunk_length (groupSize index : Nat) (values : List α) : + (chunk groupSize index values).length = min (max groupSize 1) (values.length - index * max groupSize 1) := by + simp only [chunk, List.length_take, List.length_drop] + +theorem chunks_take (groupSize count : Nat) (values : List α) : + (List.range count).flatMap (fun index => chunk groupSize index values) = values.take (count * max groupSize 1) := by + induction count with + | zero => simp only [List.range_zero, List.flatMap_nil, Nat.zero_mul, List.take_zero] + | succ count ih => + rw [List.range_succ, List.flatMap_append, ih] + simp only [List.flatMap_cons, List.flatMap_nil, List.append_nil, chunk, Nat.add_mul, + Nat.one_mul, List.take_add] + +theorem chunks_cover (groupSize : Nat) (values : List α) : + (List.range (groupCount groupSize values.length)).flatMap (fun index => chunk groupSize index values) = values := by + rw [chunks_take, List.take_of_length_le (groupCount_covers groupSize values.length)] + +theorem chunk_mem {groupSize index : Nat} {values : List α} {value : α} + (member : value ∈ chunk groupSize index values) : value ∈ values := + List.mem_of_mem_drop (List.mem_of_mem_take member) + +theorem chunk_map (groupSize index : Nat) (values : List α) (f : α → β) : + chunk groupSize index (values.map f) = (chunk groupSize index values).map f := by + simp only [chunk, List.map_take, List.map_drop] + +theorem mapM_some_reads {read : α → Option β} {inputs : List α} {outputs : List β} + (accepted : inputs.mapM read = some outputs) : outputs.length = inputs.length ∧ + ∀ (index : Nat) input, inputs[index]? = some input → ∃ output, outputs[index]? = some output ∧ read input = some output := by + induction inputs generalizing outputs with + | nil => + cases accepted + exact ⟨rfl, fun _ _ impossible => by simp at impossible⟩ + | cons input inputs ih => + simp only [List.mapM_cons, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at accepted + obtain ⟨output, head, rest, tail, rfl⟩ := accepted + obtain ⟨length, reads⟩ := ih tail + refine ⟨congrArg (· + 1) length, ?_⟩ + intro index value valueRead + cases index with + | zero => + have same := Option.some.inj valueRead + subst value + exact ⟨output, rfl, head⟩ + | succ index => exact reads index value valueRead + +theorem mapM_defined (inputs : List α) (read : α → Option β) + (defined : ∀ input ∈ inputs, ∃ output, read input = some output) : + ∃ outputs, inputs.mapM read = some outputs := by + induction inputs with + | nil => exact ⟨[], rfl⟩ + | cons input inputs ih => + obtain ⟨output, head⟩ := defined input List.mem_cons_self + obtain ⟨outputs, tail⟩ := ih (fun value member => defined value (List.mem_cons_of_mem _ member)) + exact ⟨output :: outputs, by simp only [List.mapM_cons, head, tail, bind, Option.bind_some, pure]⟩ + +theorem read_coordinates_defined (values : Array W) (slot : Nat) (bounded : 2 * slot + 1 < values.size) : + ∃ value, Coordinates.read values slot = some value := by + have first : 2 * slot < values.size := by omega + exact ⟨⟨values[2 * slot], values[2 * slot + 1]⟩, by + simp only [Coordinates.read, Array.getElem?_eq_getElem first, Array.getElem?_eq_getElem bounded, + bind, Option.bind_some, pure]⟩ + +theorem read_coordinates_success {values : Array W} {slot : Nat} {value : Coordinates W} + (accepted : Coordinates.read values slot = some value) : + values[2 * slot]? = some value.c0 ∧ values[2 * slot + 1]? = some value.c1 := by + simp only [Coordinates.read, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at accepted + obtain ⟨first, hf, second, hs, rfl⟩ := accepted + exact ⟨hf, hs⟩ + +section Evaluation + +variable {W : Type u} [Lean.Grind.CommRing W] + +theorem step_polynomial {beta gamma injection next : Coordinates W} {stageCurrent : Array W} + {lookups : List (W × List W)} {groupSize index : Nat} {result : Coordinates W} + (accepted : step beta gamma injection next stageCurrent lookups groupSize index = some result) : + ∃ source target, Coordinates.read stageCurrent index = some source ∧ + (if index + 1 < groupCount groupSize lookups.length then Coordinates.read stageCurrent (index + 1) + else some (next + injection)) = some target ∧ + result = product ((compress beta gamma (chunk groupSize index lookups)).map Prod.snd) * + (target - source) - numerator (compress beta gamma (chunk groupSize index lookups)) := by + simp only [step, bind, Option.bind_eq_some_iff, pure] at accepted + obtain ⟨source, hs, accepted⟩ := accepted + split at accepted + next interior => + simp only [Option.bind_eq_some_iff] at accepted + obtain ⟨target, ht, accepted⟩ := accepted + cases accepted + exact ⟨source, target, hs, by rw [if_pos interior]; exact ht, groupEquation_polynomial _ _⟩ + next final => + cases accepted + exact ⟨source, next + injection, hs, by rw [if_neg final], groupEquation_polynomial _ _⟩ + +theorem step_defined (beta gamma injection next : Coordinates W) (stageCurrent : Array W) + (lookups : List (W × List W)) (groupSize index : Nat) + (width : groupCount groupSize lookups.length * 2 ≤ stageCurrent.size) + (bounded : index < groupCount groupSize lookups.length) : + ∃ result, step beta gamma injection next stageCurrent lookups groupSize index = some result := by + obtain ⟨source, hs⟩ := read_coordinates_defined stageCurrent index (by omega) + have target : ∃ target, (if index + 1 < groupCount groupSize lookups.length then + Coordinates.read stageCurrent (index + 1) else some (next + injection)) = some target := by + split + next bound => exact read_coordinates_defined stageCurrent (index + 1) (by omega) + next => exact ⟨_, rfl⟩ + obtain ⟨target, ht⟩ := target + refine ⟨groupEquation (compress beta gamma (chunk groupSize index lookups)) (target - source), ?_⟩ + by_cases interior : index + 1 < groupCount groupSize lookups.length + · rw [if_pos interior] at ht + simp only [step, hs, if_pos interior, ht, bind, Option.bind_some, pure] + · rw [if_neg interior] at ht + have same := Option.some.inj ht + simp only [step, hs, if_neg interior, same, bind, Option.bind_some, pure] + +theorem equations_success {lookups : List (W × List W)} {stageCurrent stageNext publics deltaScaled : Array W} + {isLast : W} {groupSize : Nat} {result : List (Coordinates W)} + (accepted : equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = some result) : + groupSize ≤ 8 ∧ ∃ beta gamma delta next, + Coordinates.read publics 0 = some beta ∧ Coordinates.read publics 1 = some gamma ∧ + Coordinates.read deltaScaled 0 = some delta ∧ Coordinates.read stageNext 0 = some next ∧ + result.length = groupCount groupSize lookups.length ∧ + ∀ index, index < groupCount groupSize lookups.length → ∃ value, + result[index]? = some value ∧ + step beta gamma (delta.scale isLast) next stageCurrent lookups groupSize index = some value := by + unfold equations at accepted + split at accepted + next => cases accepted + next bounded => + simp only [bind, Option.bind_eq_some_iff] at accepted + obtain ⟨beta, hb, gamma, hg, delta, hd, next, hn, steps⟩ := accepted + obtain ⟨length, reads⟩ := mapM_some_reads steps + refine ⟨by omega, beta, gamma, delta, next, hb, hg, hd, hn, ?_, ?_⟩ + · simpa only [List.length_range] using length + · intro index bound + exact reads index index (List.getElem?_range bound) + +theorem equations_defined (lookups : List (W × List W)) (stageCurrent stageNext publics deltaScaled : Array W) + (isLast : W) (groupSize : Nat) (bounded : groupSize ≤ 8) + (currentWidth : groupCount groupSize lookups.length * 2 ≤ stageCurrent.size) + (nextWidth : 2 ≤ stageNext.size) (publicWidth : 4 ≤ publics.size) (deltaWidth : 2 ≤ deltaScaled.size) : + ∃ result, equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = some result := by + obtain ⟨beta, hb⟩ := read_coordinates_defined publics 0 (by omega) + obtain ⟨gamma, hg⟩ := read_coordinates_defined publics 1 (by omega) + obtain ⟨delta, hd⟩ := read_coordinates_defined deltaScaled 0 (by omega) + obtain ⟨next, hn⟩ := read_coordinates_defined stageNext 0 (by omega) + obtain ⟨result, steps⟩ := mapM_defined (List.range (groupCount groupSize lookups.length)) + (step beta gamma (delta.scale isLast) next stageCurrent lookups groupSize) + (fun index member => step_defined _ _ _ _ _ _ _ _ currentWidth (List.mem_range.mp member)) + exact ⟨result, by simp only [equations, if_neg (by omega : ¬8 < groupSize), hb, hg, hd, hn, + bind, Option.bind_some, steps]⟩ + +theorem equations_zero {lookups : List (W × List W)} {stageCurrent stageNext publics deltaScaled : Array W} + {isLast : W} {groupSize : Nat} {result : List (Coordinates W)} + (accepted : equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = some result) + (zero : ∀ value ∈ result, value = 0) : + ∃ beta gamma delta next, + Coordinates.read publics 0 = some beta ∧ Coordinates.read publics 1 = some gamma ∧ + Coordinates.read deltaScaled 0 = some delta ∧ Coordinates.read stageNext 0 = some next ∧ + ∀ index, index < groupCount groupSize lookups.length → ∃ source target, + Coordinates.read stageCurrent index = some source ∧ + (if index + 1 < groupCount groupSize lookups.length then Coordinates.read stageCurrent (index + 1) + else some (next + delta.scale isLast)) = some target ∧ + product ((compress beta gamma (chunk groupSize index lookups)).map Prod.snd) * + (target - source) = numerator (compress beta gamma (chunk groupSize index lookups)) := by + obtain ⟨_, beta, gamma, delta, next, hb, hg, hd, hn, _, steps⟩ := equations_success accepted + refine ⟨beta, gamma, delta, next, hb, hg, hd, hn, ?_⟩ + intro index bound + obtain ⟨value, valueRead, stepRead⟩ := steps index bound + obtain ⟨source, target, hs, ht, equation⟩ := step_polynomial stepRead + have vanishes := zero value (List.mem_of_getElem? valueRead) + exact ⟨source, target, hs, ht, by rw [vanishes] at equation; grind⟩ + +theorem constraintValues_success {lookups : List Lookup} {nodeValues stageCurrent stageNext publics deltaScaled : Array W} + {isLast : W} {groupSize : Nat} {result : List W} + (accepted : constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled isLast groupSize = some result) : + ∃ values coordinates, lookups.mapM (readLookup nodeValues) = some values ∧ + equations values stageCurrent stageNext publics deltaScaled isLast groupSize = some coordinates ∧ + result = Coordinates.flatten coordinates := by + simp only [constraintValues, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at accepted + obtain ⟨values, hv, coordinates, hc, rfl⟩ := accepted + exact ⟨values, coordinates, hv, hc, rfl⟩ + +theorem constraintValues_length {lookups : List Lookup} {nodeValues stageCurrent stageNext publics deltaScaled : Array W} + {isLast : W} {groupSize : Nat} {result : List W} + (accepted : constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled isLast groupSize = some result) : + result.length = 2 * groupCount groupSize lookups.length := by + obtain ⟨values, coordinates, hv, hc, rfl⟩ := constraintValues_success accepted + obtain ⟨_, _, _, _, _, _, _, _, _, length, _⟩ := equations_success hc + rw [Coordinates.flatten_length, length, (mapM_some_reads hv).1] + +theorem constraintValues_defined (lookups : List Lookup) (nodeValues stageCurrent stageNext publics deltaScaled : Array W) + (isLast : W) (groupSize : Nat) (bounded : groupSize ≤ 8) + (roots : ∀ lookup ∈ lookups, ∀ index ∈ lookup.roots, index < nodeValues.size) + (currentWidth : groupCount groupSize lookups.length * 2 ≤ stageCurrent.size) + (nextWidth : 2 ≤ stageNext.size) (publicWidth : 4 ≤ publics.size) (deltaWidth : 2 ≤ deltaScaled.size) : + ∃ result, constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled isLast groupSize = some result := by + obtain ⟨values, hv⟩ := mapM_defined lookups (readLookup nodeValues) (by + intro lookup member + obtain ⟨value, read, _⟩ := readLookup_defined nodeValues lookup (roots lookup member) + exact ⟨value, read⟩) + have lengths := (mapM_some_reads hv).1 + obtain ⟨coordinates, hc⟩ := equations_defined values stageCurrent stageNext publics deltaScaled isLast groupSize + bounded (by simpa only [lengths] using currentWidth) nextWidth publicWidth deltaWidth + exact ⟨Coordinates.flatten coordinates, by simp only [constraintValues, hv, hc, bind, Option.bind_some, pure]⟩ + +theorem constraintValues_reflect {ops : EvalOps W} {values : Values W} {trees : Array Expr} {buffer : Array W} + (reflects : Reflects ops values trees buffer) (lookups : List Lookup) + (stageCurrent stageNext publics deltaScaled : Array W) (isLast : W) (groupSize : Nat) : + constraintValues lookups buffer stageCurrent stageNext publics deltaScaled isLast groupSize = + (do let lookupValues ← lookups.mapM (evalLookup ops values trees) + return Coordinates.flatten (← equations lookupValues stageCurrent stageNext publics deltaScaled isLast groupSize)) := by + have same : readLookup buffer = evalLookup ops values trees := funext reflects.readLookup + simp only [constraintValues, same] + +end Evaluation +end Aiur.NativeAIR.LogUp diff --git a/Ix/Aiur/Proofs/LogUpAccumulator.lean b/Ix/Aiur/Proofs/LogUpAccumulator.lean new file mode 100644 index 000000000..59fbbe251 --- /dev/null +++ b/Ix/Aiur/Proofs/LogUpAccumulator.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LogUpFractions + +/-! A complete row's checked grouped equations imply the sum-of-fractions +accumulator identity when its base-field messages avoid poles. The proof +telescopes every group, including the empty pass-through case, and retains +the caller's scaled last-row injection. -/ + +namespace Aiur.NativeAIR.LogUp + +open ProofCodec (Extension) + +def lookupFractions (beta gamma : Coordinates G) (lookups : List (G × List G)) : Extension := + fractionSum (fieldEntries (compress beta gamma lookups)) + +theorem fractionSum_flatMap (inputs : List α) (entries : α → List (Extension × Extension)) : + fractionSum (inputs.flatMap entries) = sum (inputs.map fun input => fractionSum (entries input)) := by + induction inputs with + | nil => rfl + | cons input inputs ih => + simp only [List.flatMap_cons, fractionSum_append, List.map_cons, sum, List.foldr_cons] at * + rw [ih] + +theorem fieldEntries_compress_chunk (beta gamma : Coordinates G) (lookups : List (G × List G)) + (groupSize index : Nat) : + fieldEntries (compress beta gamma (chunk groupSize index lookups)) = + chunk groupSize index (fieldEntries (compress beta gamma lookups)) := by + simp only [fieldEntries, compress, chunk_map] + +theorem lookupFractions_chunks (beta gamma : Coordinates G) (lookups : List (G × List G)) (groupSize : Nat) : + sum ((List.range (groupCount groupSize lookups.length)).map + (fun index => lookupFractions beta gamma (chunk groupSize index lookups))) = lookupFractions beta gamma lookups := by + simp only [lookupFractions, fieldEntries_compress_chunk] + rw [← fractionSum_flatMap] + have length : (fieldEntries (compress beta gamma lookups)).length = lookups.length := by + simp only [fieldEntries, compress, List.length_map] + rw [← length, chunks_cover] + +theorem equations_accumulator {lookups : List (G × List G)} {stageCurrent stageNext publics deltaScaled : Array G} + {isLast : G} {groupSize : Nat} {result : List (Coordinates G)} + {beta gamma : Coordinates G} + (betaRead : Coordinates.read publics 0 = some beta) (gammaRead : Coordinates.read publics 1 = some gamma) + (accepted : equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = some result) + (zero : ∀ value ∈ result, value = 0) + (free : PoleFree (fieldEntries (compress beta gamma lookups))) : + ∃ first next delta, Coordinates.read stageCurrent 0 = some first ∧ + Coordinates.read stageNext 0 = some next ∧ Coordinates.read deltaScaled 0 = some delta ∧ + next.toExtension - first.toExtension + (delta.scale isLast).toExtension = lookupFractions beta gamma lookups := by + obtain ⟨readBeta, readGamma, delta, next, hb, hg, hd, hn, groups⟩ := equations_zero accepted zero + have sameBeta := Option.some.inj (hb.symm.trans betaRead) + have sameGamma := Option.some.inj (hg.symm.trans gammaRead) + subst readBeta + subst readGamma + let count := groupCount groupSize lookups.length + let injection := delta.scale isLast + let states := fun index => if index < count then + ((Coordinates.read stageCurrent index).getD 0).toExtension else (next + injection).toExtension + let increments := fun index => lookupFractions beta gamma (chunk groupSize index lookups) + have steps : ∀ index, index < count → states (index + 1) - states index = increments index := by + intro index bound + obtain ⟨source, target, hs, ht, equation⟩ := groups index bound + have localFree : PoleFree (fieldEntries (compress beta gamma (chunk groupSize index lookups))) := by + rw [fieldEntries_compress_chunk] + exact fun entry member => free entry (chunk_mem member) + have fraction := (coordinate_polynomial_zero_iff _ _ localFree).mp equation + rw [Coordinates.toExtension_sub] at fraction + have sourceRead : states index = source.toExtension := by + simp only [states, if_pos bound, hs, Option.getD_some] + have targetRead : states (index + 1) = target.toExtension := by + by_cases interior : index + 1 < count + · rw [if_pos interior] at ht + simp only [states, if_pos interior, ht, Option.getD_some] + · rw [if_neg interior] at ht + have same := Option.some.inj ht + simp only [states, if_neg interior, injection, same] + rw [sourceRead, targetRead] + exact fraction + have telescoped := telescope states increments count steps + rw [lookupFractions_chunks] at telescoped + obtain ⟨first, _, hf, _, _⟩ := groups 0 (groupCount_positive _ _) + have positive : 0 < count := groupCount_positive _ _ + have firstState : states 0 = first.toExtension := by + simp only [states, if_pos positive, hf, Option.getD_some] + have finalState : states count = next.toExtension + injection.toExtension := by + simp only [states, Nat.lt_irrefl, ↓reduceIte, Coordinates.toExtension_add] + rw [firstState, finalState] at telescoped + exact ⟨first, next, delta, hf, hn, hd, by change _ + injection.toExtension = _; grind⟩ + +theorem constraintValues_accumulator {lookups : List Lookup} {nodeValues stageCurrent stageNext publics deltaScaled : Array G} + {isLast : G} {groupSize : Nat} {result : List G} {beta gamma : Coordinates G} + (betaRead : Coordinates.read publics 0 = some beta) (gammaRead : Coordinates.read publics 1 = some gamma) + (accepted : constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled isLast groupSize = some result) + (zero : ∀ value ∈ result, value = 0) + (free : ∀ values, lookups.mapM (readLookup nodeValues) = some values → + PoleFree (fieldEntries (compress beta gamma values))) : + ∃ values first next delta, lookups.mapM (readLookup nodeValues) = some values ∧ + Coordinates.read stageCurrent 0 = some first ∧ Coordinates.read stageNext 0 = some next ∧ + Coordinates.read deltaScaled 0 = some delta ∧ + next.toExtension - first.toExtension + (delta.scale isLast).toExtension = lookupFractions beta gamma values := by + obtain ⟨values, coordinates, hv, hc, rfl⟩ := constraintValues_success accepted + have vanishes := (Coordinates.flatten_zero_iff coordinates).mp zero + obtain ⟨first, next, delta, hf, hn, hd, equation⟩ := equations_accumulator betaRead gammaRead hc vanishes (free values hv) + exact ⟨values, first, next, delta, hv, hf, hn, hd, equation⟩ + +end Aiur.NativeAIR.LogUp diff --git a/Ix/Aiur/Proofs/LogUpAlgebra.lean b/Ix/Aiur/Proofs/LogUpAlgebra.lean new file mode 100644 index 000000000..a5ecd89af --- /dev/null +++ b/Ix/Aiur/Proofs/LogUpAlgebra.lean @@ -0,0 +1,195 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.LogUp +import Ix.Aiur.Proofs.LookupCoordinates + +/-! Product reflection for grouped logUp, valid in a commutative ring even +when the coordinate algebra has zero divisors. Denominator cancellation is +deliberately a separate result requiring nonzero native field messages. -/ + +namespace Aiur.NativeAIR.LogUp + +section Algebra + +variable {R : Type u} [Lean.Grind.CommRing R] + +theorem sub_zero_iff (left right : R) : left - right = 0 ↔ left = right := by + constructor <;> intro equal <;> grind + +theorem clears_cons (weight message inverse denominator fractions cleared : R) + (inverts : message * inverse = 1) (tail : denominator * fractions = cleared) : + message * denominator * (weight * inverse + fractions) = weight * denominator + message * cleared := by + grind + +theorem product_cons (value : R) (values : List R) : product (value :: values) = value * product values := rfl + +theorem product_append (left right : List R) : product (left ++ right) = product left * product right := by + induction left with + | nil => simp only [List.nil_append, product, List.foldr_nil]; grind + | cons x xs ih => + simp only [List.cons_append, product, List.foldr_cons] at * + rw [ih] + grind + +theorem product_foldl (values : List R) (initial : R) : + values.foldl (· * ·) initial = initial * product values := by + induction values generalizing initial with + | nil => simp only [List.foldl_nil, product, List.foldr_nil]; grind + | cons x xs ih => simp only [List.foldl_cons, ih, product, List.foldr_cons]; grind + +theorem sum_foldl (values : List R) (initial : R) : + values.foldl (· + ·) initial = initial + sum values := by + induction values generalizing initial with + | nil => simp only [List.foldl_nil, sum, List.foldr_nil]; grind + | cons x xs ih => simp only [List.foldl_cons, ih, sum, List.foldr_cons]; grind + +theorem sum_append (left right : List R) : sum (left ++ right) = sum left + sum right := by + induction left with + | nil => change sum right = 0 + sum right; grind + | cons x xs ih => + change x + sum (xs ++ right) = (x + sum xs) + sum right + rw [ih] + grind + +theorem telescope (states increments : Nat → R) (count : Nat) + (steps : ∀ index, index < count → states (index + 1) - states index = increments index) : + states count - states 0 = sum ((List.range count).map increments) := by + induction count with + | zero => change states 0 - states 0 = 0; grind + | succ count ih => + have earlier := ih (fun index bound => steps index (by omega)) + have last := steps count (by omega) + rw [List.range_succ, List.map_append, sum_append] + change states (count + 1) - states 0 = sum ((List.range count).map increments) + (increments count + 0) + grind + +theorem cyclic_accumulator (states fractions : Nat → R) (count : Nat) (delta : R) + (positive : 0 < count) (wrap : states count = states 0) + (rows : ∀ index, index < count → + states (index + 1) - states index + (if index + 1 = count then delta else 0) = fractions index) : + sum ((List.range count).map fractions) = delta := by + cases count with + | zero => omega + | succ count => + have earlier := telescope states fractions count (by + intro index bound + have row := rows index (by omega) + rw [if_neg (by omega : index + 1 ≠ count + 1), Lean.Grind.Semiring.add_zero] at row + exact row) + have last := rows count (by omega) + rw [if_pos rfl, wrap] at last + rw [List.range_succ, List.map_append, sum_append] + change sum ((List.range count).map fractions) + (fractions count + 0) = delta + grind + +theorem final_accumulator (accumulators contributions : Nat → R) (count : Nat) + (finalZero : accumulators count = 0) + (circuits : ∀ index, index < count → accumulators (index + 1) - accumulators index = contributions index) : + accumulators 0 + sum ((List.range count).map contributions) = 0 := by + have total := telescope accumulators contributions count circuits + rw [finalZero] at total + grind + +theorem prefix_products (values : List R) (initial : R) (index : Nat) : + (values.scanl (· * ·) initial)[index]? = + if index ≤ values.length then some (initial * product (values.take index)) else none := by + rw [List.getElem?_scanl, product_foldl] + +theorem prefix_seeded (first : R) (rest : List R) : + (first :: rest).scanl (· * ·) 1 = 1 :: rest.scanl (· * ·) first := by + rw [List.scanl_cons, Lean.Grind.Semiring.one_mul] + +theorem suffix_seeded (rest : List R) (last : R) : + (rest ++ [last]).scanr (· * ·) 1 = rest.scanr (· * ·) last ++ [1] := by + simp only [List.scanr_append, List.foldr_cons, List.foldr_nil, Lean.Grind.Semiring.mul_one, + List.scanr_cons, List.scanr_nil, List.tail_cons] + +theorem suffix_products (values : List R) (index : Nat) : + (values.scanr (· * ·) 1)[index]? = + if index ≤ values.length then some (product (values.drop index)) else none := by + induction values generalizing index with + | nil => cases index <;> simp [product] + | cons x xs ih => + cases index with + | zero => simp only [List.scanr_cons, List.getElem?_cons_zero, Nat.zero_le, + ↓reduceIte, List.drop_zero, product] + | succ index => + simp only [List.scanr_cons, List.getElem?_cons_succ, List.length_cons, + Nat.succ_le_succ_iff, List.drop_succ_cons, ih] + +theorem prefixSuffixTerms_cons (weight message initial : R) (entries : List (R × R)) : + prefixSuffixTerms initial ((weight, message) :: entries) = + initial * product (entries.map Prod.snd) * weight :: prefixSuffixTerms (initial * message) entries := by + cases entries <;> + simp [prefixSuffixTerms, List.scanl_cons, List.scanr_cons, product] + +theorem prefixSuffixTerms_sum (entries : List (R × R)) (initial : R) : + sum (prefixSuffixTerms initial entries) = initial * numerator entries := by + induction entries generalizing initial with + | nil => simp only [prefixSuffixTerms, List.map_nil, List.zip_nil_left, sum, List.foldr_nil, + numerator]; grind + | cons entry entries ih => + obtain ⟨weight, message⟩ := entry + rw [prefixSuffixTerms_cons] + change initial * product (entries.map Prod.snd) * weight + + sum (prefixSuffixTerms (initial * message) entries) = _ + rw [ih] + simp only [numerator] + grind + +theorem groupEquation_polynomial (entries : List (R × R)) (difference : R) : + groupEquation entries difference = product (entries.map Prod.snd) * difference - numerator entries := by + cases entries with + | nil => simp only [groupEquation, List.map_nil, product, List.foldr_nil, numerator]; grind + | cons entry entries => + obtain ⟨weight, message⟩ := entry + cases entries with + | nil => simp only [groupEquation, List.map_cons, List.map_nil, product, List.foldr_cons, + List.foldr_nil, numerator]; grind + | cons entry entries => + rw [groupEquation, product_foldl, sum_foldl, prefixSuffixTerms_sum] <;> grind + +theorem numerator_append (left right : List (R × R)) : + numerator (left ++ right) = numerator left * product (right.map Prod.snd) + + product (left.map Prod.snd) * numerator right := by + induction left with + | nil => simp only [List.nil_append, numerator, List.map_nil, product, List.foldr_nil]; grind + | cons entry entries ih => + obtain ⟨weight, message⟩ := entry + simp only [List.cons_append, numerator, List.map_append, product_append, ih, + List.map_cons, product_cons] + grind + +end Algebra + +section Fingerprint + +variable {W : Type u} [Lean.Grind.CommRing W] + +theorem fingerprint_reverse_horner (gamma : Coordinates W) (args : List W) : + fingerprint gamma args = args.reverse.foldl (fun acc arg => acc * gamma + Coordinates.ofBase arg) 0 := by + simp only [fingerprint, List.foldl_reverse] + +theorem fingerprint_nil (gamma : Coordinates W) : fingerprint gamma [] = 0 := rfl + +theorem fingerprint_cons (gamma : Coordinates W) (arg : W) (args : List W) : + fingerprint gamma (arg :: args) = fingerprint gamma args * gamma + Coordinates.ofBase arg := rfl + +theorem fingerprint_trailing_zero (gamma : Coordinates W) (args : List W) : + fingerprint gamma (args ++ [0]) = fingerprint gamma args := by + induction args with + | nil => change 0 * gamma + (0 : Coordinates W) = 0; grind + | cons arg args ih => simp only [List.cons_append, fingerprint_cons, ih] + +theorem fingerprint_padding (gamma : Coordinates W) (args : List W) (count : Nat) : + fingerprint gamma (args ++ List.replicate count 0) = fingerprint gamma args := by + induction count with + | zero => simp only [List.replicate_zero, List.append_nil] + | succ count ih => + rw [List.replicate_succ', ← List.append_assoc, fingerprint_trailing_zero, ih] + +end Fingerprint +end Aiur.NativeAIR.LogUp diff --git a/Ix/Aiur/Proofs/LogUpFractions.lean b/Ix/Aiur/Proofs/LogUpFractions.lean new file mode 100644 index 000000000..e49bca854 --- /dev/null +++ b/Ix/Aiur/Proofs/LogUpFractions.lean @@ -0,0 +1,151 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LogUp + +/-! Denominator cancellation on base-field trace rows. The coordinate pairs +then identify with the proved native extension field. This identification +and cancellation are not applied to arbitrary challenge-field coordinates. +The pole-free premise remains a cryptographic obligation. -/ + +namespace Aiur.NativeAIR.LogUp + +open ProofCodec (Extension) + +/-- The total inverse convention is used only under `PoleFree` below. -/ +def inverseValue (value : Extension) : Extension := value.tryInverse.getD 0 + +def fractionSum (entries : List (Extension × Extension)) : Extension := + sum (entries.map fun (weight, message) => weight * inverseValue message) + +def PoleFree (entries : List (Extension × Extension)) : Prop := + ∀ entry ∈ entries, entry.2 ≠ 0 + +def fieldEntries (entries : List (Coordinates G × Coordinates G)) : List (Extension × Extension) := + entries.map fun (weight, message) => (weight.toExtension, message.toExtension) + +theorem inverseValue_correct (value : Extension) (nonzero : value ≠ 0) : + value * inverseValue value = 1 := by + obtain ⟨read, correct⟩ := Extension.inverse_correct value nonzero + simpa only [inverseValue, read, Option.getD_some] using correct + +theorem product_nonzero (values : List Extension) (nonzero : ∀ value ∈ values, value ≠ 0) : + product values ≠ 0 := by + induction values with + | nil => exact Extension.one_ne_zero + | cons value values ih => + rw [product_cons] + intro zero + exact ((Extension.mul_eq_zero_iff _ _).mp zero).elim + (nonzero value List.mem_cons_self) + (ih (fun value member => nonzero value (List.mem_cons_of_mem _ member))) + +theorem poleFree_product (entries : List (Extension × Extension)) (free : PoleFree entries) : + product (entries.map Prod.snd) ≠ 0 := by + apply product_nonzero + intro value member + obtain ⟨entry, present, rfl⟩ := List.mem_map.mp member + exact free entry present + +theorem fractionSum_cons (weight message : Extension) (entries : List (Extension × Extension)) : + fractionSum ((weight, message) :: entries) = weight * inverseValue message + fractionSum entries := rfl + +theorem fractionSum_append (left right : List (Extension × Extension)) : + fractionSum (left ++ right) = fractionSum left + fractionSum right := by + induction left with + | nil => change fractionSum right = 0 + fractionSum right; grind + | cons entry entries ih => + obtain ⟨weight, message⟩ := entry + simp only [List.cons_append, fractionSum_cons, ih] + grind + +theorem fractionSum_clears (entries : List (Extension × Extension)) (free : PoleFree entries) : + product (entries.map Prod.snd) * fractionSum entries = numerator entries := by + induction entries with + | nil => change (1 : Extension) * 0 = 0; grind + | cons entry entries ih => + obtain ⟨weight, message⟩ := entry + have inverse := inverseValue_correct message (free _ List.mem_cons_self) + have tail := ih (fun entry member => free entry (List.mem_cons_of_mem _ member)) + simp only [List.map_cons, product_cons, fractionSum_cons, numerator] + exact clears_cons _ _ _ _ _ _ inverse tail + +theorem groupEquation_zero_iff (entries : List (Extension × Extension)) (difference : Extension) + (free : PoleFree entries) : groupEquation entries difference = 0 ↔ difference = fractionSum entries := by + rw [groupEquation_polynomial, sub_zero_iff] + constructor + · intro zero + apply Extension.mul_left_cancel (poleFree_product entries free) + rw [fractionSum_clears entries free] + exact zero + · intro same + rw [same, fractionSum_clears entries free] + +theorem product_toExtension (values : List (Coordinates G)) : + (product values).toExtension = product (values.map Coordinates.toExtension) := by + induction values with + | nil => rfl + | cons value values ih => + simp only [product_cons, Coordinates.toExtension_mul, List.map_cons, ih] + +theorem fieldEntries_messages (entries : List (Coordinates G × Coordinates G)) : + (fieldEntries entries).map Prod.snd = (entries.map Prod.snd).map Coordinates.toExtension := by + simp only [fieldEntries, List.map_map] + rfl + +theorem numerator_toExtension (entries : List (Coordinates G × Coordinates G)) : + (numerator entries).toExtension = numerator (fieldEntries entries) := by + induction entries with + | nil => rfl + | cons entry entries ih => + obtain ⟨weight, message⟩ := entry + change (weight * product (entries.map Prod.snd) + message * numerator entries).toExtension = + weight.toExtension * product ((fieldEntries entries).map Prod.snd) + + message.toExtension * numerator (fieldEntries entries) + rw [Coordinates.toExtension_add, Coordinates.toExtension_mul, Coordinates.toExtension_mul, + product_toExtension, fieldEntries_messages, ih] + +theorem groupEquation_toExtension (entries : List (Coordinates G × Coordinates G)) (difference : Coordinates G) : + (groupEquation entries difference).toExtension = groupEquation (fieldEntries entries) difference.toExtension := by + rw [groupEquation_polynomial, groupEquation_polynomial, Coordinates.toExtension_sub, + Coordinates.toExtension_mul, product_toExtension, numerator_toExtension, fieldEntries_messages] + +theorem coordinate_group_zero_iff (entries : List (Coordinates G × Coordinates G)) (difference : Coordinates G) + (free : PoleFree (fieldEntries entries)) : + groupEquation entries difference = 0 ↔ difference.toExtension = fractionSum (fieldEntries entries) := by + rw [← Coordinates.toExtension_zero_iff, groupEquation_toExtension, groupEquation_zero_iff _ _ free] + +theorem coordinate_polynomial_zero_iff (entries : List (Coordinates G × Coordinates G)) (difference : Coordinates G) + (free : PoleFree (fieldEntries entries)) : + product (entries.map Prod.snd) * difference = numerator entries ↔ + difference.toExtension = fractionSum (fieldEntries entries) := by + have reflected := coordinate_group_zero_iff entries difference free + rw [groupEquation_polynomial] at reflected + have subtract : product (entries.map Prod.snd) * difference - numerator entries = 0 ↔ + product (entries.map Prod.snd) * difference = numerator entries := by + constructor <;> intro equal <;> grind + exact subtract.symm.trans reflected + +theorem fingerprint_toExtension (gamma : Coordinates G) (args : List G) : + (fingerprint gamma args).toExtension = + args.foldr (fun arg acc => acc * gamma.toExtension + Extension.ofBase arg) 0 := by + induction args with + | nil => rfl + | cons arg args ih => + rw [fingerprint_cons, Coordinates.toExtension_add, Coordinates.toExtension_mul, ih] + rfl + +/-- A zero denominator can make an accumulator step unconstrained. -/ +theorem pole_can_hide_step : + groupEquation ([(0, 0)] : List (Extension × Extension)) 1 = 0 ∧ + (1 : Extension) ≠ fractionSum [(0, 0)] := by + constructor + · change (0 : Extension) * 1 - 0 = 0; grind + · have zero : fractionSum ([(0, 0)] : List (Extension × Extension)) = 0 := by + change (0 : Extension) * inverseValue 0 + 0 = 0; grind + rw [zero] + exact Extension.one_ne_zero + +end Aiur.NativeAIR.LogUp diff --git a/Ix/Aiur/Proofs/Lookup.lean b/Ix/Aiur/Proofs/Lookup.lean new file mode 100644 index 000000000..01f4a4989 --- /dev/null +++ b/Ix/Aiur/Proofs/Lookup.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CallOrder + +/-! Exact lookup balance over the actual Goldilocks representation. + +Consumer queries have unit weight; providers may have arbitrary field +multiplicities. A query count below the characteristic cannot disappear by +modular cancellation, so every queried message has a nonzero provider. +Instantiating this result with the fixed 256-by-256 byte table recovers byte +bounds, including the six bytes used by the call-order constraint. + +These theorems assume exact message balance. They do not extract that +balance from a cryptographic transcript or identify the Rust emitter with +this mathematical interface. +-/ + +namespace Aiur + +theorem G.zero_add (a : G) : 0 + a = a := by + change G.ofNat (0 + a.n) = a + simpa only [Nat.zero_add] using G.ofNat_n a + +theorem G.ofNat_ne_zero_of_lt {n : Nat} (positive : 0 < n) + (bounded : n < gSize.toNat) : G.ofNat n ≠ 0 := by + intro h + have hn := congrArg G.n h + rw [G.n_ofNat, Nat.mod_eq_of_lt bounded] at hn + change n = 0 at hn + omega + +namespace AIR + +/-- A supplied message and its return/pull multiplicity. -/ +abbrev Provider (α : Type u) := α × G + +/-- Total supplied weight for one exact message. -/ +def suppliedWeight [DecidableEq α] (message : α) (providers : List (Provider α)) : G := + providers.foldr (fun provider rest => + if provider.1 = message then provider.2 + rest else rest) 0 + +/-- Exact tuple balance, before randomized message compression. Each +consumer contributes one; arbitrary provider weights are field elements. -/ +def ExactLookupBalance [DecidableEq α] (queries : List α) + (providers : List (Provider α)) : Prop := + ∀ message, G.ofNat (queries.count message) = suppliedWeight message providers + +/-- The count bound is necessary: exactly one characteristic's worth of +identical queries has zero field weight, even with no providers. -/ +theorem characteristic_queries_balance [DecidableEq α] (message : α) : + ExactLookupBalance (List.replicate gSize.toNat message) [] := by + intro query + simp only [List.count_replicate, suppliedWeight] + split <;> rfl + +theorem suppliedWeight_nonzero_provider [DecidableEq α] (message : α) + (providers : List (Provider α)) + (nonzero : suppliedWeight message providers ≠ 0) : + ∃ provider ∈ providers, provider.1 = message ∧ provider.2 ≠ 0 := by + induction providers with + | nil => exact False.elim (nonzero rfl) + | cons provider rest ih => + obtain ⟨provided, multiplicity⟩ := provider + by_cases same : provided = message + · by_cases zero : multiplicity = 0 + · have hn : suppliedWeight message rest ≠ 0 := by + simpa only [suppliedWeight, List.foldr_cons, if_pos same, zero, G.zero_add] using nonzero + obtain ⟨provider, member, hm, hw⟩ := ih hn + exact ⟨provider, List.mem_cons_of_mem _ member, hm, hw⟩ + · exact ⟨(provided, multiplicity), List.mem_cons_self, same, zero⟩ + · have hn : suppliedWeight message rest ≠ 0 := by + simpa only [suppliedWeight, List.foldr_cons, if_neg same] using nonzero + obtain ⟨provider, member, hm, hw⟩ := ih hn + exact ⟨provider, List.mem_cons_of_mem _ member, hm, hw⟩ + +/-- A bounded positive request cannot be supplied solely by zero weights, +even when other providers use negative field multiplicities. -/ +theorem exactLookupBalance_provider [DecidableEq α] + {queries : List α} {providers : List (Provider α)} + (balanced : ExactLookupBalance queries providers) + (bounded : queries.length < gSize.toNat) {message : α} + (queried : message ∈ queries) : + ∃ provider ∈ providers, provider.1 = message ∧ provider.2 ≠ 0 := by + have positive : 0 < queries.count message := List.count_pos_iff.mpr queried + have countBound : queries.count message < gSize.toNat := + Nat.lt_of_le_of_lt List.count_le_length bounded + have nonzero := G.ofNat_ne_zero_of_lt positive countBound + rw [balanced message] at nonzero + exact suppliedWeight_nonzero_provider message providers nonzero + +/-- Row order of the two-byte preprocessed table: outer first byte, inner +second byte, each ranging from 0 through 255. -/ +def byteRangeMessage (row : Fin 65536) : G × G := + (G.ofNat (row.val / 256), G.ofNat (row.val % 256)) + +def byteRangeProviders (weights : Fin 65536 → G) : List (Provider (G × G)) := + List.ofFn fun row => (byteRangeMessage row, weights row) + +theorem byteRangeMessage_bounded (row : Fin 65536) : + (byteRangeMessage row).1.n < 256 ∧ (byteRangeMessage row).2.n < 256 := by + have first : row.val / 256 < 256 := by omega + have second : row.val % 256 < 256 := Nat.mod_lt _ (by decide) + have firstField : row.val / 256 < gSize.toNat := by + exact Nat.lt_trans first (by decide) + have secondField : row.val % 256 < gSize.toNat := by + exact Nat.lt_trans second (by decide) + simpa only [byteRangeMessage, G.n_ofNat, Nat.mod_eq_of_lt firstField, + Nat.mod_eq_of_lt secondField] using And.intro first second + +/-- Exact balance against the fixed byte table establishes both byte +bounds. The table's multiplicity column remains arbitrary. -/ +theorem exactLookupBalance_byteRange {queries : List (G × G)} + (weights : Fin 65536 → G) + (balanced : ExactLookupBalance queries (byteRangeProviders weights)) + (bounded : queries.length < gSize.toNat) {a b : G} + (queried : (a, b) ∈ queries) : a.n < 256 ∧ b.n < 256 := by + obtain ⟨provider, member, message, _⟩ := + exactLookupBalance_provider balanced bounded queried + obtain ⟨row, hrow⟩ := List.mem_ofFn.mp member + have same : byteRangeMessage row = (a, b) := by + exact (congrArg Prod.fst hrow).trans message + simpa only [same] using byteRangeMessage_bounded row + +/-- The three pair queries emitted for one six-byte rank or gap. -/ +def rankByteQueries (bytes : Fin 6 → G) : List (G × G) := + [(bytes 0, bytes 1), (bytes 2, bytes 3), (bytes 4, bytes 5)] + +theorem exactLookupBalance_rankBytes {queries : List (G × G)} + (weights : Fin 65536 → G) + (balanced : ExactLookupBalance queries (byteRangeProviders weights)) + (bounded : queries.length < gSize.toNat) (bytes : Fin 6 → G) + (queried : rankByteQueries bytes ⊆ queries) : + ∀ i, (bytes i).n < 256 := by + have p0 := exactLookupBalance_byteRange weights balanced bounded + (queried (by simp [rankByteQueries] : (bytes 0, bytes 1) ∈ rankByteQueries bytes)) + have p1 := exactLookupBalance_byteRange weights balanced bounded + (queried (by simp [rankByteQueries] : (bytes 2, bytes 3) ∈ rankByteQueries bytes)) + have p2 := exactLookupBalance_byteRange weights balanced bounded + (queried (by simp [rankByteQueries] : (bytes 4, bytes 5) ∈ rankByteQueries bytes)) + intro i + have cases : i = 0 ∨ i = 1 ∨ i = 2 ∨ i = 3 ∨ i = 4 ∨ i = 5 := by omega + rcases cases with rfl | rfl | rfl | rfl | rfl | rfl + · exact p0.1 + · exact p0.2 + · exact p1.1 + · exact p1.2 + · exact p2.1 + · exact p2.2 + +theorem exactLookupBalance_call_order {queries : List (G × G)} + (weights : Fin 65536 → G) + (balanced : ExactLookupBalance queries (byteRangeProviders weights)) + (bounded : queries.length < gSize.toNat) (parent child gap : Fin 6 → G) + (hp : rankByteQueries parent ⊆ queries) + (hc : rankByteQueries child ⊆ queries) + (hg : rankByteQueries gap ⊆ queries) + (satisfied : callOrderConstraint (packRank parent) (packRank child) (packRank gap) = 0) : + (packRank parent).n < (packRank child).n := + packed_call_order_strict parent child gap + (exactLookupBalance_rankBytes weights balanced bounded parent hp) + (exactLookupBalance_rankBytes weights balanced bounded child hc) + (exactLookupBalance_rankBytes weights balanced bounded gap hg) satisfied + +end AIR +end Aiur diff --git a/Ix/Aiur/Proofs/LookupBudget.lean b/Ix/Aiur/Proofs/LookupBudget.lean new file mode 100644 index 000000000..7a3ff6c9f --- /dev/null +++ b/Ix/Aiur/Proofs/LookupBudget.lean @@ -0,0 +1,268 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.GlobalLookups + +/-! +The native verifier's conservative lookup-consumer budget. + +Canonical slot counts and active-order trace heights determine the bound: +one public claim plus every lookup slot in every active trace row. The total +natural-number model below checks sequence alignment, shift bounds and the +strict field-characteristic bound. Its accepted arithmetic fits the native +checked u64 operations. The component gate compares both implementations. + +Interpreting actual consumer multiplicities as zero or one and counting them +within these slots still belongs to native AIR extraction. These definitions +and comparisons are not a proof of Rust execution refinement. +-/ + +namespace Aiur + +/-- Canonical circuit slot counts and the activation bitmap consume trace +degrees in active order. Missing, extra and misaligned entries fail. -/ +def lookupSlotSum : List Nat → List Bool → List Nat → Option Nat + | [], [], [] => some 0 + | _ :: slots, false :: active, degrees => lookupSlotSum slots active degrees + | slots :: rest, true :: active, degree :: degrees => do + let tail ← lookupSlotSum rest active degrees + pure (2 ^ degree * slots + tail) + | _, _, _ => none + +def lookupQueryBoundAux : List Nat → List Bool → List Nat → Nat → Option Nat + | [], [], [], used => some used + | _ :: slots, false :: active, degrees, used => lookupQueryBoundAux slots active degrees used + | slots :: rest, true :: active, degree :: degrees, used => + if degree < 64 then + let next := used + 2 ^ degree * slots + if next < gSize.toNat then lookupQueryBoundAux rest active degrees next else none + else none + | _, _, _, _ => none + +/-- Total natural-number mirror of the native checked-u64 budget guard. +Counting every slot includes providers and bounds unit consumers from above. +The initial one is the single public claim. -/ +def lookupQueryBound (slots : List Nat) (active : List Bool) (degrees : List Nat) : Option Nat := + if active.any id then lookupQueryBoundAux slots active degrees 1 else none + +theorem lookupQueryBoundAux_sound {slots : List Nat} {active : List Bool} {degrees : List Nat} + {used result : Nat} (below : used < gSize.toNat) + (accepted : lookupQueryBoundAux slots active degrees used = some result) : + ∃ total, lookupSlotSum slots active degrees = some total ∧ result = used + total ∧ + result < gSize.toNat := by + induction slots generalizing active degrees used with + | nil => + cases active <;> cases degrees <;> simp only [lookupQueryBoundAux, reduceCtorEq] at accepted + cases accepted + exact ⟨0, rfl, by omega, below⟩ + | cons count slots ih => + cases active with + | nil => simp only [lookupQueryBoundAux, reduceCtorEq] at accepted + | cons enabled active => + cases enabled with + | false => exact ih below accepted + | true => + cases degrees with + | nil => simp only [lookupQueryBoundAux, reduceCtorEq] at accepted + | cons degree degrees => + simp only [lookupQueryBoundAux] at accepted + split at accepted + next degreeBound => + split at accepted + next nextBound => + obtain ⟨total, shape, sum, bounded⟩ := ih nextBound accepted + refine ⟨2 ^ degree * count + total, ?_, by omega, bounded⟩ + simp only [lookupSlotSum, shape, bind, Option.bind, pure] + next => contradiction + next => contradiction + +theorem lookupQueryBound_sound {slots : List Nat} {active : List Bool} {degrees : List Nat} + {result : Nat} (accepted : lookupQueryBound slots active degrees = some result) : + active.any id = true ∧ ∃ total, lookupSlotSum slots active degrees = some total ∧ + result = 1 + total ∧ result < gSize.toNat := by + simp only [lookupQueryBound] at accepted + split at accepted + next enabled => exact ⟨enabled, lookupQueryBoundAux_sound (by decide) accepted⟩ + next => contradiction + +theorem lookupQueryBound_consumer_count {slots : List Nat} {active : List Bool} {degrees : List Nat} + {result total : Nat} (accepted : lookupQueryBound slots active degrees = some result) + (shape : lookupSlotSum slots active degrees = some total) + {α : Type u} (queries : List α) (perSlot : queries.length ≤ total) : + (queries.length + 1) < gSize.toNat := by + obtain ⟨_, sum, sameShape, sameResult, below⟩ := lookupQueryBound_sound accepted + have equal := Option.some.inj (sameShape.symm.trans shape) + omega + +theorem lookupQueryBoundAux_shape {slots : List Nat} {active : List Bool} {degrees : List Nat} + {used result : Nat} (accepted : lookupQueryBoundAux slots active degrees used = some result) : + slots.length = active.length ∧ degrees.length = active.count true ∧ + ∀ degree ∈ degrees, degree < 64 := by + induction slots generalizing active degrees used with + | nil => + cases active <;> cases degrees <;> simp only [lookupQueryBoundAux, reduceCtorEq] at accepted + exact ⟨rfl, rfl, by simp only [List.not_mem_nil, false_implies, implies_true]⟩ + | cons count slots ih => + cases active with + | nil => simp only [lookupQueryBoundAux, reduceCtorEq] at accepted + | cons enabled active => + cases enabled with + | false => + obtain ⟨aligned, degreesCount, bounded⟩ := ih accepted + refine ⟨by simpa only [List.length_cons] using congrArg Nat.succ aligned, ?_, bounded⟩ + simpa only [List.count_cons, beq_iff_eq, Bool.false_eq_true, ↓reduceIte, Nat.add_zero] + using degreesCount + | true => + cases degrees with + | nil => simp only [lookupQueryBoundAux, reduceCtorEq] at accepted + | cons degree degrees => + simp only [lookupQueryBoundAux] at accepted + split at accepted + next degreeBound => + split at accepted + next => + obtain ⟨aligned, degreesCount, bounded⟩ := ih accepted + refine ⟨by simpa only [List.length_cons] using congrArg Nat.succ aligned, ?_, ?_⟩ + · simpa only [List.length_cons, List.count_cons, beq_iff_eq, ↓reduceIte, Nat.succ_eq_add_one] + using congrArg Nat.succ degreesCount + · intro d member + rcases List.mem_cons.mp member with same | later + · exact same ▸ degreeBound + · exact bounded d later + next => contradiction + next => contradiction + +theorem lookupQueryBound_shape {slots : List Nat} {active : List Bool} {degrees : List Nat} + {result : Nat} (accepted : lookupQueryBound slots active degrees = some result) : + active.any id = true ∧ slots.length = active.length ∧ + degrees.length = active.count true ∧ ∀ degree ∈ degrees, degree < 64 := by + simp only [lookupQueryBound] at accepted + split at accepted + next enabled => exact ⟨enabled, lookupQueryBoundAux_shape accepted⟩ + next => contradiction + +/-- A step admitted by the natural-number guard fits both native checked +u64 operations. Arithmetic overflow can never turn a rejected sum into an +accepted smaller count. -/ +theorem lookupQueryBound_step_no_overflow {used height slots : Nat} + (accepted : used + height * slots < gSize.toNat) : + height * slots < 2 ^ 64 ∧ used + height * slots < 2 ^ 64 := by + have modulus : gSize.toNat < 2 ^ 64 := by decide +kernel + omega + +theorem lookupQueryBoundAux_complete {slots : List Nat} {active : List Bool} {degrees : List Nat} + {used total : Nat} (shape : lookupSlotSum slots active degrees = some total) + (degreesBound : ∀ degree ∈ degrees, degree < 64) + (bounded : used + total < gSize.toNat) : + lookupQueryBoundAux slots active degrees used = some (used + total) := by + induction slots generalizing active degrees used total with + | nil => + cases active <;> cases degrees <;> simp only [lookupSlotSum, reduceCtorEq] at shape + cases shape + rfl + | cons count slots ih => + cases active with + | nil => simp only [lookupSlotSum, reduceCtorEq] at shape + | cons enabled active => + cases enabled with + | false => exact ih shape degreesBound bounded + | true => + cases degrees with + | nil => simp only [lookupSlotSum, reduceCtorEq] at shape + | cons degree degrees => + cases tail : lookupSlotSum slots active degrees with + | none => simp only [lookupSlotSum, tail, bind, Option.bind, reduceCtorEq] at shape + | some rest => + have totalEq : 2 ^ degree * count + rest = total := by + simpa only [lookupSlotSum, tail, bind, Option.bind, pure, Option.some.injEq] using shape + have nextBound : used + 2 ^ degree * count < gSize.toNat := by omega + have continued := ih tail + (fun d member => degreesBound d (List.mem_cons_of_mem degree member)) + (used := used + 2 ^ degree * count) (by omega) + simp only [lookupQueryBoundAux, if_pos (degreesBound degree List.mem_cons_self), + if_pos nextBound, continued] + congr 1 + omega + +theorem lookupQueryBound_complete {slots : List Nat} {active : List Bool} {degrees : List Nat} + {total : Nat} (enabled : active.any id = true) + (shape : lookupSlotSum slots active degrees = some total) + (degreesBound : ∀ degree ∈ degrees, degree < 64) + (bounded : 1 + total < gSize.toNat) : + lookupQueryBound slots active degrees = some (1 + total) := by + simp only [lookupQueryBound, enabled, ↓reduceIte] + exact lookupQueryBoundAux_complete shape degreesBound bounded + +theorem lookupSlotSum_bounded {slots : List Nat} {active : List Bool} {degrees : List Nat} + {total maxSlots maxDegree : Nat} (shape : lookupSlotSum slots active degrees = some total) + (slotsBound : ∀ count ∈ slots, count ≤ maxSlots) + (degreesBound : ∀ degree ∈ degrees, degree ≤ maxDegree) : + total ≤ slots.length * (2 ^ maxDegree * maxSlots) := by + induction slots generalizing active degrees total with + | nil => + cases active <;> cases degrees <;> simp only [lookupSlotSum, reduceCtorEq] at shape + cases shape + exact Nat.zero_le _ + | cons count slots ih => + have tailSlots : ∀ n ∈ slots, n ≤ maxSlots := + fun n member => slotsBound n (List.mem_cons_of_mem count member) + cases active with + | nil => simp only [lookupSlotSum, reduceCtorEq] at shape + | cons enabled active => + cases enabled with + | false => + have bound := ih shape tailSlots degreesBound + simp only [List.length_cons, Nat.add_mul] + omega + | true => + cases degrees with + | nil => simp only [lookupSlotSum, reduceCtorEq] at shape + | cons degree degrees => + cases tail : lookupSlotSum slots active degrees with + | none => simp only [lookupSlotSum, tail, bind, Option.bind, reduceCtorEq] at shape + | some rest => + have totalEq : 2 ^ degree * count + rest = total := by + simpa only [lookupSlotSum, tail, bind, Option.bind, pure, Option.some.injEq] using shape + have tailBound := ih tail tailSlots + (fun d member => degreesBound d (List.mem_cons_of_mem degree member)) + have powerBound : 2 ^ degree ≤ 2 ^ maxDegree := + Nat.pow_le_pow_right (by decide) (degreesBound degree List.mem_cons_self) + have headBound := Nat.mul_le_mul powerBound (slotsBound count List.mem_cons_self) + simp only [List.length_cons, Nat.add_mul] + omega + +/-- Version-five keys encode circuit and slot counts as u16. Together with +Goldilocks' maximum 2^32 trace height, those format limits already leave a +strict margin below the characteristic. The explicit budget guard preserves +every such well-shaped proof, independently of its chosen activation subset. -/ +theorem lookupQueryBound_encodedKey {slots : List Nat} {active : List Bool} {degrees : List Nat} + {total : Nat} (enabled : active.any id = true) + (shape : lookupSlotSum slots active degrees = some total) + (circuitCount : slots.length < 65536) + (slotsBound : ∀ count ∈ slots, count < 65536) + (degreesBound : ∀ degree ∈ degrees, degree ≤ 32) : + lookupQueryBound slots active degrees = some (1 + total) := by + apply lookupQueryBound_complete enabled shape + (fun degree member => Nat.lt_of_le_of_lt (degreesBound degree member) (by decide)) + have totalBound := lookupSlotSum_bounded shape (maxSlots := 65535) + (fun count member => Nat.le_sub_one_of_lt (slotsBound count member)) degreesBound + have countBound : slots.length ≤ 65535 := by omega + have outerBound := Nat.mul_le_mul_right (2 ^ 32 * 65535) countBound + have margin : 1 + 65535 * (2 ^ 32 * 65535) < gSize.toNat := by decide +kernel + omega + +/-- The checked native budget supplies the global count premise once local +AIR extraction bounds internal unit consumers by the trace's slot total. -/ +theorem AIR.GlobalLookups.of_budget {tables : AIR.LookupTables} {width : Nat} + {slots : List Nat} {active : List Bool} {degrees : List Nat} {result total : Nat} + (accepted : lookupQueryBound slots active degrees = some result) + (shape : lookupSlotSum slots active degrees = some total) + (root : List G) (queries : List (List G)) (perSlot : queries.length ≤ total) + (balance : AIR.PaddedLookupBalance width (root :: queries) tables.providers) + (widths : ∀ query ∈ root :: queries, query.length ≤ width) : + AIR.GlobalLookups tables width (root :: queries) := + ⟨balance, lookupQueryBound_consumer_count accepted shape queries perSlot, widths⟩ + +end Aiur diff --git a/Ix/Aiur/Proofs/LookupCoordinates.lean b/Ix/Aiur/Proofs/LookupCoordinates.lean new file mode 100644 index 000000000..512859400 --- /dev/null +++ b/Ix/Aiur/Proofs/LookupCoordinates.lean @@ -0,0 +1,199 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.LookupCoordinates +import Ix.Aiur.Proofs.ExtensionField + +/-! Ring laws for the separate logUp coordinates, and the field identification +available on base-field trace rows. No field instance is assigned to coordinates +over the challenge field. -/ + +namespace Aiur.NativeAIR.LogUp.Coordinates + +theorem ext {a b : Coordinates W} (first : a.c0 = b.c0) (second : a.c1 = b.c1) : a = b := by + cases a; cases b; cases first; cases second; rfl + +theorem zero_iff [OfNat W 0] (a : Coordinates W) : a = 0 ↔ a.c0 = 0 ∧ a.c1 = 0 := by + constructor + · intro same; cases same; exact ⟨rfl, rfl⟩ + · exact fun same => ext same.1 same.2 + +theorem flatten_length (values : List (Coordinates W)) : (flatten values).length = 2 * values.length := by + induction values with + | nil => rfl + | cons value values ih => simp only [flatten, List.flatMap_cons, List.length_append, + List.length_cons, List.length_nil] at *; omega + +theorem flatten_zero_iff [OfNat W 0] (values : List (Coordinates W)) : + (∀ x ∈ flatten values, x = 0) ↔ ∀ value ∈ values, value = 0 := by + constructor + · intro zero value member + apply (zero_iff value).mpr + exact ⟨zero _ (List.mem_flatMap.mpr ⟨value, member, by simp⟩), + zero _ (List.mem_flatMap.mpr ⟨value, member, by simp⟩)⟩ + · intro zero x member + obtain ⟨value, present, coordinate⟩ := List.mem_flatMap.mp member + cases zero value present + change x ∈ [(0 : W), 0] at coordinate + simpa only [List.mem_cons, List.not_mem_nil, or_false, or_self] using coordinate + +section Algebra + +variable {W : Type u} [Lean.Grind.CommRing W] + +attribute [local instance] Lean.Grind.Semiring.natCast Lean.Grind.Ring.intCast + +theorem mul_schoolbook (a b : Coordinates W) : + a * b = ⟨a.c0 * b.c0 + 7 * a.c1 * b.c1, a.c0 * b.c1 + a.c1 * b.c0⟩ := by + apply ext + · change a.c0 * b.c0 + (a.c1 * b.c1) * 7 = _; grind + · change (a.c0 + a.c1) * (b.c0 + b.c1) - a.c0 * b.c0 - a.c1 * b.c1 = _; grind + +theorem add_zero (a : Coordinates W) : a + 0 = a := by + apply ext <;> change _ + (0 : W) = _ <;> grind + +theorem add_comm (a b : Coordinates W) : a + b = b + a := by + apply ext <;> change (_ : W) + _ = _ + _ <;> grind + +theorem add_assoc (a b c : Coordinates W) : a + b + c = a + (b + c) := by + apply ext <;> change (_ : W) + _ + _ = _ + (_ + _) <;> grind + +theorem mul_one (a : Coordinates W) : a * 1 = a := by + rw [mul_schoolbook] + apply ext + · change a.c0 * 1 + 7 * a.c1 * 0 = a.c0; grind + · change a.c0 * 0 + a.c1 * 1 = a.c1; grind + +theorem mul_zero (a : Coordinates W) : a * 0 = 0 := by + rw [mul_schoolbook] + apply ext + · change a.c0 * 0 + 7 * a.c1 * 0 = (0 : W); grind + · change a.c0 * 0 + a.c1 * 0 = (0 : W); grind + +theorem mul_comm (a b : Coordinates W) : a * b = b * a := by + rw [mul_schoolbook, mul_schoolbook] + apply ext <;> dsimp only <;> grind + +theorem mul_assoc (a b c : Coordinates W) : a * b * c = a * (b * c) := by + simp only [mul_schoolbook] + apply ext <;> dsimp only <;> grind + +theorem left_distrib (a b c : Coordinates W) : a * (b + c) = a * b + a * c := by + simp only [mul_schoolbook] + apply ext + · change a.c0 * (b.c0 + c.c0) + 7 * a.c1 * (b.c1 + c.c1) = + (a.c0 * b.c0 + 7 * a.c1 * b.c1) + (a.c0 * c.c0 + 7 * a.c1 * c.c1) + grind + · change a.c0 * (b.c1 + c.c1) + a.c1 * (b.c0 + c.c0) = + (a.c0 * b.c1 + a.c1 * b.c0) + (a.c0 * c.c1 + a.c1 * c.c0) + grind + +theorem neg_add_cancel (a : Coordinates W) : -a + a = 0 := by + apply ext <;> change -(_ : W) + _ = 0 <;> grind + +theorem sub_eq_add_neg (a b : Coordinates W) : a - b = a + -b := by + apply ext <;> change (_ : W) - _ = _ + -_ <;> grind + +theorem ofBase_add (a b : W) : ofBase (a + b) = ofBase a + ofBase b := by + apply ext + · rfl + · change (0 : W) = 0 + 0; grind + +theorem ofBase_neg (a : W) : ofBase (-a) = -ofBase a := by + apply ext + · rfl + · change (0 : W) = -0; grind + +theorem ofBase_mul (a b : W) : ofBase (a * b) = ofBase a * ofBase b := by + rw [mul_schoolbook] + apply ext + · change a * b = a * b + 7 * 0 * 0; grind + · change (0 : W) = a * 0 + 0 * b; grind + +instance natCast : NatCast (Coordinates W) := ⟨fun n => ofBase (Nat.cast n)⟩ +instance intCast : IntCast (Coordinates W) := ⟨fun n => ofBase (Int.cast n)⟩ +instance nsmul : SMul Nat (Coordinates W) := ⟨fun n a => ofBase (Nat.cast n) * a⟩ +instance zsmul : SMul Int (Coordinates W) := ⟨fun n a => ofBase (Int.cast n) * a⟩ +instance npow : HPow (Coordinates W) Nat (Coordinates W) := ⟨fun a n => npowRec n a⟩ + +theorem neg_mul (a b : Coordinates W) : -a * b = -(a * b) := by + simp only [mul_schoolbook] + apply ext + · change -a.c0 * b.c0 + 7 * -a.c1 * b.c1 = -(a.c0 * b.c0 + 7 * a.c1 * b.c1); grind + · change -a.c0 * b.c1 + -a.c1 * b.c0 = -(a.c0 * b.c1 + a.c1 * b.c0); grind + +instance commRing : Lean.Grind.CommRing (Coordinates W) where + add_zero := add_zero + add_comm := add_comm + add_assoc := add_assoc + mul_assoc := mul_assoc + mul_comm := mul_comm + mul_one := mul_one + left_distrib := left_distrib + zero_mul a := by rw [mul_comm, mul_zero] + mul_zero := mul_zero + pow_zero _ := rfl + pow_succ _ _ := rfl + ofNat_succ n := by + change ofBase (OfNat.ofNat (n + 1) : W) = ofBase (OfNat.ofNat n : W) + ofBase (1 : W) + rw [Lean.Grind.Semiring.ofNat_succ, ofBase_add] + ofNat_eq_natCast n := by + change ofBase (OfNat.ofNat n : W) = ofBase (Nat.cast n : W) + rw [Lean.Grind.Semiring.ofNat_eq_natCast] + neg_add_cancel := neg_add_cancel + sub_eq_add_neg := sub_eq_add_neg + intCast_neg n := by + change ofBase (Int.cast (-n) : W) = -ofBase (Int.cast n : W) + rw [Lean.Grind.Ring.intCast_neg, ofBase_neg] + intCast_ofNat n := by + change ofBase (Int.cast (OfNat.ofNat n) : W) = ofBase (OfNat.ofNat n : W) + rw [Lean.Grind.Ring.intCast_ofNat] + zsmul_natCast_eq_nsmul n a := by + change ofBase (Int.cast (Nat.cast n) : W) * a = ofBase (Nat.cast n : W) * a + rw [Lean.Grind.Ring.intCast_natCast] + neg_zsmul n a := by + change ofBase (Int.cast (-n) : W) * a = -(ofBase (Int.cast n : W) * a) + rw [Lean.Grind.Ring.intCast_neg, ofBase_neg, neg_mul] + +theorem scale_eq_mul (a : Coordinates W) (b : W) : a.scale b = a * ofBase b := by + rw [mul_schoolbook] + apply ext + · change a.c0 * b = a.c0 * b + 7 * a.c1 * 0; grind + · change a.c1 * b = a.c0 * 0 + a.c1 * b; grind + +end Algebra + +theorem toExtension_injective {a b : Coordinates G} (same : a.toExtension = b.toExtension) : a = b := + ext (congrArg ProofCodec.Extension.c0 same) (congrArg ProofCodec.Extension.c1 same) + +theorem toExtension_fromExtension (a : ProofCodec.Extension) : (fromExtension a).toExtension = a := rfl + +theorem fromExtension_toExtension (a : Coordinates G) : fromExtension a.toExtension = a := rfl + +theorem toExtension_zero_iff (a : Coordinates G) : a.toExtension = 0 ↔ a = 0 := + ⟨fun same => toExtension_injective (b := 0) same, fun same => same ▸ rfl⟩ + +theorem toExtension_ofBase (a : G) : (ofBase a).toExtension = ProofCodec.Extension.ofBase a := rfl +theorem toExtension_add (a b : Coordinates G) : (a + b).toExtension = a.toExtension + b.toExtension := rfl +theorem toExtension_sub (a b : Coordinates G) : (a - b).toExtension = a.toExtension - b.toExtension := rfl + +theorem toExtension_mul (a b : Coordinates G) : (a * b).toExtension = a.toExtension * b.toExtension := by + rw [mul_schoolbook] + apply ProofCodec.Extension.ext + · change a.c0 * b.c0 + 7 * a.c1 * b.c1 = a.c0 * b.c0 + a.c1 * (b.c1 * 7); grind + · rfl + +/-- Over challenge-field coordinates, combining them with the basis loses a +constraint: this nonzero pair combines to zero. -/ +theorem collapse_loses_constraint : + let a : Coordinates ProofCodec.Extension := ⟨-ProofCodec.Extension.basis, 1⟩ + a ≠ 0 ∧ a.c0 + a.c1 * ProofCodec.Extension.basis = 0 := by + constructor + · intro same + exact ProofCodec.Extension.one_ne_zero (congrArg Coordinates.c1 same) + · change -ProofCodec.Extension.basis + 1 * ProofCodec.Extension.basis = 0 + grind + +end Aiur.NativeAIR.LogUp.Coordinates diff --git a/Ix/Aiur/Proofs/LookupExpressions.lean b/Ix/Aiur/Proofs/LookupExpressions.lean new file mode 100644 index 000000000..b914a9738 --- /dev/null +++ b/Ix/Aiur/Proofs/LookupExpressions.lean @@ -0,0 +1,248 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationSequences +import Ix.Aiur.Proofs.GraphCompilation +import Ix.Aiur.Proofs.QuerySlotMessages + +/-! +Native lookup argument gating and accumulation, retaining exact frontend +expression trees. A slot's evaluation is the existing valued multiplicity +and combined message, including unequal message widths and repeated writers. +The resulting expression lookups feed the checked base-graph compiler. +-/ + +namespace Aiur.NativeAIR +namespace LookupEmitter +open OpEmitter Compiler + +def addArgs : List Expr → List Expr → List Expr + | [], right => right + | left, [] => left + | x :: left, y :: right => x.frontAdd y :: addArgs left right + +def gateArgs (branchless : Bool) (selector : Expr) (args : List Expr) : List Expr := + if branchless then args else args.map selector.frontMul + +theorem addArgs_eval {values : Values G} {left right : List Expr} {a b : List G} + (leftEval : left.mapM (evalExpr values) = some a) + (rightEval : right.mapM (evalExpr values) = some b) : + (addArgs left right).mapM (evalExpr values) = some (AIR.addMessages a b) := by + induction left generalizing right a b with + | nil => + cases leftEval + exact rightEval + | cons x left ih => + cases right with + | nil => + cases rightEval + have empty : AIR.addMessages a [] = a := by cases a <;> rfl + simpa only [addArgs, List.reverse_nil, empty] using leftEval + | cons y right => + simp only [List.mapM_cons, bind, Option.bind] at leftEval rightEval + split at leftEval + · cases leftEval + rename_i xValue xEval + dsimp only at leftEval + split at leftEval + · cases leftEval + rename_i leftValues leftValuesEval + cases leftEval + split at rightEval + · cases rightEval + rename_i yValue yEval + dsimp only at rightEval + split at rightEval + · cases rightEval + rename_i rightValues rightValuesEval + cases rightEval + simp only [addArgs, AIR.addMessages, List.mapM_cons, + Expr.frontAdd_eval goldilocksLaws values xEval yEval, + ih leftValuesEval rightValuesEval, bind, Option.bind_some, pure, goldilocks_add] + +theorem gateArgs_eval (branchless : Bool) {values : Values G} {selector : Expr} {s : G} + {args : List Expr} {results : List G} (selectorEval : evalExpr values selector = some s) + (argsEval : args.mapM (evalExpr values) = some results) : + (gateArgs branchless selector args).mapM (evalExpr values) = + some (AIR.gateMessage branchless s results) := by + cases branchless with + | true => exact argsEval + | false => + exact list_mapM_transform argsEval selector.frontMul (s * ·) (evalExpr values) + (fun _ _ evaluated => Expr.frontMul_eval goldilocksLaws values selectorEval evaluated) + +structure QueryExpr where + slot : Nat + selector : Expr + message : List Expr + +def QueryExpr.eval (values : Values G) (query : QueryExpr) : Option AIR.QueryPart := do + let selector ← evalExpr values query.selector + let message ← query.message.mapM (evalExpr values) + return ⟨query.slot, selector, message⟩ + +theorem QueryExpr.eval_components {values : Values G} {query : QueryExpr} {result : AIR.QueryPart} + (evaluated : query.eval values = some result) : + query.slot = result.slot ∧ evalExpr values query.selector = some result.selector ∧ + query.message.mapM (evalExpr values) = some result.message := by + simp only [QueryExpr.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i selector selectorEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i message messageEval + cases evaluated + exact ⟨rfl, selectorEval, messageEval⟩ + +def queryParts (slot : Nat) (selector : Expr) (queries : List (List Expr)) : List QueryExpr := + queries.mapIdx fun index message => ⟨slot + index, selector, message⟩ + +theorem queryParts_cons (slot : Nat) (selector : Expr) (message : List Expr) (queries : List (List Expr)) : + queryParts slot selector (message :: queries) = + ⟨slot, selector, message⟩ :: queryParts (slot + 1) selector queries := by + simp [queryParts, List.mapIdx_cons, Nat.add_comm, Nat.add_left_comm] + +theorem queryParts_eval {values : Values G} {selector : Expr} {s : G} + {queries : List (List Expr)} {messages : List (List G)} + (selectorEval : evalExpr values selector = some s) + (evaluated : queries.mapM (List.mapM (evalExpr values)) = some messages) (slot : Nat) : + (queryParts slot selector queries).mapM (QueryExpr.eval values) = + some (AIR.queryParts slot s messages) := by + induction queries generalizing messages slot with + | nil => + cases evaluated + rfl + | cons query queries ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i message messageEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i rest restEval + cases evaluated + rw [queryParts_cons, AIR.queryParts_cons] + have head : (QueryExpr.mk slot selector query).eval values = some ⟨slot, s, message⟩ := by + simp only [QueryExpr.eval, selectorEval, messageEval, bind, Option.bind_some, pure] + simp only [List.mapM_cons, head, ih restEval, bind, Option.bind_some, pure] + +def accumulate (branchless : Bool) (lookup : ExprLookup) (query : QueryExpr) : ExprLookup := + ⟨lookup.multiplicity.frontAdd query.selector, + addArgs lookup.args (gateArgs branchless query.selector query.message)⟩ + +theorem accumulate_eval (branchless : Bool) {values : Values G} + {lookup : ExprLookup} {query : QueryExpr} {initial : G × List G} {part : AIR.QueryPart} + (initialEval : lookup.eval goldilocksOps values = some initial) + (queryEval : query.eval values = some part) : + (accumulate branchless lookup query).eval goldilocksOps values = + some (initial.1 + part.selector, + AIR.addMessages initial.2 (AIR.gateMessage branchless part.selector part.message)) := by + obtain ⟨_, selectorEval, messageEval⟩ := QueryExpr.eval_components queryEval + simp only [ExprLookup.eval, bind, Option.bind] at initialEval + split at initialEval + · cases initialEval + rename_i multiplicity multiplicityEval + dsimp only at initialEval + split at initialEval + · cases initialEval + rename_i args argsEval + cases initialEval + have weight := Expr.frontAdd_eval goldilocksLaws values multiplicityEval selectorEval + have message := addArgs_eval argsEval (gateArgs_eval branchless selectorEval messageEval) + simp only [accumulate, ExprLookup.eval, weight, show evalExprs goldilocksOps values + (addArgs lookup.args (gateArgs branchless query.selector query.message)) = + some (AIR.addMessages args (AIR.gateMessage branchless part.selector part.message)) from message, + bind, Option.bind_some, pure, goldilocks_add] + +def valuedAccumulate (branchless : Bool) (lookup : G × List G) (query : AIR.QueryPart) : G × List G := + (lookup.1 + query.selector, AIR.addMessages lookup.2 (AIR.gateMessage branchless query.selector query.message)) + +theorem fold_eval (branchless : Bool) {values : Values G} + {queries : List QueryExpr} {parts : List AIR.QueryPart} + (evaluated : queries.mapM (QueryExpr.eval values) = some parts) + {initial : ExprLookup} {start : G × List G} (initialEval : initial.eval goldilocksOps values = some start) : + (queries.foldl (accumulate branchless) initial).eval goldilocksOps values = + some (parts.foldl (valuedAccumulate branchless) start) := by + induction queries generalizing parts initial start with + | nil => + cases evaluated + exact initialEval + | cons query queries ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i part partEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i rest restEval + cases evaluated + exact ih restEval (accumulate_eval branchless initialEval partEval) + +theorem filter_eval {values : Values G} {queries : List QueryExpr} {parts : List AIR.QueryPart} + (evaluated : queries.mapM (QueryExpr.eval values) = some parts) (slot : Nat) : + (queries.filter (fun query => query.slot == slot)).mapM (QueryExpr.eval values) = + some (parts.filter fun query => query.slot == slot) := by + induction queries generalizing parts with + | nil => + cases evaluated + rfl + | cons query queries ih => + simp only [List.mapM_cons, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i part partEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i rest restEval + cases evaluated + have same := (QueryExpr.eval_components partEval).1 + simp only [List.filter_cons, same] + split + · simp only [List.mapM_cons, partEval, ih restEval, bind, Option.bind_some, pure] + · exact ih restEval + +theorem valuedFold_eq (branchless : Bool) (parts : List AIR.QueryPart) (start : G × List G) : + parts.foldl (valuedAccumulate branchless) start = + ((parts.map AIR.QueryPart.selector).foldl (· + ·) start.1, + (parts.map fun part => (part.selector, part.message)).foldl + (fun args part => AIR.addMessages args (AIR.gateMessage branchless part.1 part.2)) start.2) := by + induction parts generalizing start with + | nil => rfl + | cons part parts ih => exact ih _ + +def slot (branchless : Bool) (queries : List QueryExpr) (index : Nat) : ExprLookup := + (queries.filter fun query => query.slot == index).foldl (accumulate branchless) ⟨.konst 0, []⟩ + +theorem slot_eval (branchless : Bool) {values : Values G} + {queries : List QueryExpr} {parts : List AIR.QueryPart} + (evaluated : queries.mapM (QueryExpr.eval values) = some parts) (index : Nat) : + (slot branchless queries index).eval goldilocksOps values = + some (AIR.querySlotMultiplicity parts index, + AIR.slotMessage branchless (AIR.querySlotParts parts index)) := by + have result := fold_eval branchless (filter_eval evaluated index) + (show (ExprLookup.mk (.konst 0) []).eval goldilocksOps values = some (0, []) from rfl) + rw [valuedFold_eq] at result + simpa only [slot, AIR.querySlotMultiplicity, AIR.querySlotParts, AIR.selectorSum, + AIR.slotMessage, List.map_map, Function.comp_def] using result + +def slots (branchless : Bool) (queries : List QueryExpr) (count : Nat) : List ExprLookup := + List.ofFn fun index : Fin count => slot branchless queries index.val + +theorem slots_eval (branchless : Bool) {values : Values G} + {queries : List QueryExpr} {parts : List AIR.QueryPart} + (evaluated : queries.mapM (QueryExpr.eval values) = some parts) (count : Nat) : + (slots branchless queries count).mapM (ExprLookup.eval goldilocksOps values) = + some (List.ofFn fun index : Fin count => + (AIR.querySlotMultiplicity parts index.val, + AIR.slotMessage branchless (AIR.querySlotParts parts index.val))) := by + exact list_mapM_ofFn _ _ _ (fun index => slot_eval branchless evaluated index.val) + +end LookupEmitter +end Aiur.NativeAIR diff --git a/Ix/Aiur/Proofs/LookupLayout.lean b/Ix/Aiur/Proofs/LookupLayout.lean new file mode 100644 index 000000000..6076e9909 --- /dev/null +++ b/Ix/Aiur/Proofs/LookupLayout.lean @@ -0,0 +1,1079 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitMembership +import Ix.Aiur.Proofs.Relayout + +/-! +For the generic rank layout, the compiler's lookup allocation equals the valued emitter's physical extent. +The equality is preserved by function renaming and deduplication; final +compilation and grouping bound every member by its selected circuit layout. +Canonical trace execution therefore needs no independent per-witness lookup +limit or shape hypothesis. Native extraction, memory validity and the complete +compiler and certified semantic/cryptographic endpoint remain obligations. +-/ + +namespace Aiur.Bytecode + +def Op.lookupUsage : Op → Nat + | .call _ _ _ unconstrained => if unconstrained then 0 else 4 + | .store _ | .load _ _ | .u8BitDecomposition _ | .u8ShiftLeft _ | .u8ShiftRight _ + | .u8Xor .. | .u8And .. | .u8Or .. | .u8Add .. | .u8Sub .. | .u8Mul .. + | .u8XorSplit7 .. | .u8XorSplit4 .. | .u8LessThan .. | .u8RangeCheck .. => 1 + | .u32LessThan .. => 6 + | _ => 0 + +private theorem lookup_block_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def Ctrl.lookupUsage : Ctrl → Nat + | .return .. | .yield .. => 0 + | .match _ branches fallback => ( + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.lookupUsage) ++ + (match fallback with | none => [] | some block => [block.lookupUsage])).foldl Nat.max 0 + | .matchContinue _ branches fallback _ _ _ continuation => ( + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.lookupUsage) ++ + (match fallback with | none => [] | some block => [block.lookupUsage])).foldl Nat.max 0 + + continuation.lookupUsage +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.lookupUsage (block : Block) : Nat := + (block.ops.toList.map Op.lookupUsage).sum + block.ctrl.lookupUsage +termination_by sizeOf block +decreasing_by exact lookup_block_smaller block + +end + +def branchLookupUsage (branches : Array (G × Block)) (fallback : Option Block) : Nat := + (branches.toList.map (fun pair => pair.2.lookupUsage) ++ + fallback.toList.map (fun block => block.lookupUsage)).foldl Nat.max 0 + +theorem Ctrl.lookupUsage_match (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).lookupUsage = branchLookupUsage branches fallback := by + rw [Ctrl.lookupUsage.eq_def] + simp only [branchLookupUsage, Array.toList_attach] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.lookupUsage)] + cases fallback <;> rfl + +theorem Ctrl.lookupUsage_matchContinue (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) (outputs aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).lookupUsage = + branchLookupUsage branches fallback + continuation.lookupUsage := by + rw [Ctrl.lookupUsage.eq_def] + simp only [branchLookupUsage, Array.toList_attach] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.lookupUsage)] + cases fallback <;> rfl + +end Aiur.Bytecode + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode Std.Do + +private theorem list_getDegree (indices : List ValIdx) (initial : LayoutMState) : + (indices.mapM getDegree).run initial = (indices.map (fun i => initial.degrees[i]?.getD 0), initial) := by + induction indices with + | nil => rfl + | cons index indices ih => + rw [List.mapM_cons] + change (let (values, final) := (indices.mapM getDegree).run initial; + (initial.degrees[index]?.getD 0 :: values, final)) = + (initial.degrees[index]?.getD 0 :: indices.map (fun i => initial.degrees[i]?.getD 0), initial) + rw [ih] + +private theorem array_getDegree (indices : Array ValIdx) : + indices.mapM getDegree = (fun initial => pure (indices.map (fun i => initial.degrees[i]?.getD 0), initial)) := by + rw [Array.mapM_eq_mapM_toList] + funext initial + change (let (values, final) := (indices.toList.mapM getDegree).run initial; + (values.toArray, final)) = (indices.map (fun i => initial.degrees[i]?.getD 0), initial) + rw [list_getDegree] + simp only [← List.map_toArray, Array.toArray_toList] + +set_option mvcgen.warning false in +theorem opLayout_lookupUsage (op : Op) (initial : LayoutMState) + (generic : initial.callRanks = #[]) : + ((opLayout op).run initial).2.functionLayout.lookups = initial.functionLayout.lookups + op.lookupUsage := by + cases op + case call function args outputSize unconstrained => + cases unconstrained <;> + simp [opLayout, Op.lookupUsage, bumpLookups, bumpAuxiliaries, pushDegrees, + StateT.run, StateT.bind, StateT.pure, StateT.get, StateT.modifyGet, + get, getThe, MonadStateOf.get, modify, modifyGet, MonadStateOf.modifyGet, + bind, pure, generic, Nat.add_assoc] + all_goals + simp only [opLayout, array_getDegree] <;> + apply StateM.of_wp_run_eq rfl (fun result : Unit × LayoutMState => + result.2.functionLayout.lookups = _) + all_goals + mvcgen [opLayout, array_getDegree, bumpLookups, bumpAuxiliaries, getDegree, getDegrees, + pushDegree, pushDegrees, addMemSize] + all_goals simp_all [Op.lookupUsage] + all_goals try rfl + +private theorem ops_fold_lookupUsage (ops : List Op) (initial : LayoutMState) + (generic : initial.callRanks = #[]) : + ((ops.foldlM (fun _ op => opLayout op) ()).run initial).2.functionLayout.lookups = + initial.functionLayout.lookups + (ops.map Op.lookupUsage).sum := by + induction ops generalizing initial with + | nil => rfl + | cons op ops ih => + rw [List.foldlM_cons] + change ((ops.foldlM (fun _ op => opLayout op) ()).run ((opLayout op).run initial).2).2.functionLayout.lookups = _ + rw [ih _ ((opLayout_callRanks op initial).trans generic), opLayout_lookupUsage op initial generic, + List.map_cons, List.sum_cons, Nat.add_assoc] + +theorem opsLayout_lookupUsage (ops : Array Op) (initial : LayoutMState) + (generic : initial.callRanks = #[]) : + ((ops.forM opLayout).run initial).2.functionLayout.lookups = + initial.functionLayout.lookups + (ops.toList.map Op.lookupUsage).sum := by + unfold Array.forM + rw [← Array.foldlM_toList] + exact ops_fold_lookupUsage ops.toList initial generic + +private def branchLayoutStep (shared : SharedData) (degrees : Array Nat) (acc : SharedData) + (block : Block) : LayoutM SharedData := do + setSharedData shared + blockLayout block + let used ← getSharedData + setDegrees degrees + return acc.maximals used + +private theorem branchLayoutStep_callRanks (shared : SharedData) (degrees : Array Nat) + (acc : SharedData) (block : Block) (initial : LayoutMState) : + ((branchLayoutStep shared degrees acc block).run initial).2.callRanks = initial.callRanks := + blockLayout_callRanks block ((setSharedData shared).run initial).2 + +private theorem branchFold_callRanks {α : Type} (items : List α) (blockOf : α → Block) + (shared : SharedData) (degrees : Array Nat) (acc : SharedData) (initial : LayoutMState) : + ((items.foldlM (fun acc item => branchLayoutStep shared degrees acc (blockOf item)) acc).run initial).2.callRanks = + initial.callRanks := by + induction items generalizing acc initial with + | nil => rfl + | cons item items ih => + rw [List.foldlM_cons] + exact (ih ((branchLayoutStep shared degrees acc (blockOf item)).run initial).1 + ((branchLayoutStep shared degrees acc (blockOf item)).run initial).2).trans + (branchLayoutStep_callRanks shared degrees acc (blockOf item) initial) + +private theorem branchLayoutStep_lookupUsage (shared : SharedData) (degrees : Array Nat) (acc : SharedData) + (block : Block) (initial : LayoutMState) + (generic : initial.callRanks = #[]) + (effect : ∀ state, state.callRanks = #[] → ((blockLayout block).run state).2.functionLayout.lookups = + state.functionLayout.lookups + block.lookupUsage) : + ((branchLayoutStep shared degrees acc block).run initial).1.lookups = + max acc.lookups (shared.lookups + block.lookupUsage) := by + change max acc.lookups ((blockLayout block).run ((setSharedData shared).run initial).2).2.functionLayout.lookups = _ + rw [effect ((setSharedData shared).run initial).2 generic] + rfl + +private theorem branchFold_lookupUsage {α : Type} (items : List α) (blockOf : α → Block) + (shared : SharedData) (degrees : Array Nat) (acc : SharedData) (initial : LayoutMState) + (start : Nat) (aligned : acc.lookups = shared.lookups + start) + (generic : initial.callRanks = #[]) + (effect : ∀ item ∈ items, ∀ state, state.callRanks = #[] → + ((blockLayout (blockOf item)).run state).2.functionLayout.lookups = + state.functionLayout.lookups + (blockOf item).lookupUsage) : + ((items.foldlM (fun acc item => branchLayoutStep shared degrees acc (blockOf item)) acc).run initial).1.lookups = + shared.lookups + (items.map (fun item => (blockOf item).lookupUsage)).foldl Nat.max start := by + induction items generalizing acc initial start with + | nil => exact aligned + | cons item items ih => + rw [List.foldlM_cons] + change ((items.foldlM (fun acc item => branchLayoutStep shared degrees acc (blockOf item)) + ((branchLayoutStep shared degrees acc (blockOf item)).run initial).1).run + ((branchLayoutStep shared degrees acc (blockOf item)).run initial).2).1.lookups = _ + simp only [List.map_cons, List.foldl_cons] + apply ih _ _ _ _ + ((branchLayoutStep_callRanks shared degrees acc (blockOf item) initial).trans generic) + (fun item member => effect item (List.mem_cons_of_mem _ member)) + rw [branchLayoutStep_lookupUsage shared degrees acc (blockOf item) initial generic + (effect item List.mem_cons_self), aligned, Nat.add_max_add_left] + +private theorem matchLayout_lookupUsage (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) (initial : LayoutMState) + (generic : initial.callRanks = #[]) + (caseEffect : ∀ pair ∈ branches.toList, ∀ state, state.callRanks = #[] → + ((blockLayout pair.2).run state).2.functionLayout.lookups = + state.functionLayout.lookups + pair.2.lookupUsage) + (defaultEffect : ∀ block, fallback = some block → ∀ state, state.callRanks = #[] → + ((blockLayout block).run state).2.functionLayout.lookups = + state.functionLayout.lookups + block.lookupUsage) : + ((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout.lookups = + initial.functionLayout.lookups + branchLookupUsage branches fallback := by + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop : LayoutM SharedData := branches.attach.foldlM (init := shared) + fun acc pair => branchLayoutStep shared initial.degrees acc pair.val.2 + have loopCount : (loop.run initial).1.lookups = initial.functionLayout.lookups + + (branches.toList.map (fun pair => pair.2.lookupUsage)).foldl Nat.max 0 := by + dsimp only [loop] + rw [← Array.foldlM_toList] + have count := branchFold_lookupUsage branches.attach.toList (fun pair => pair.val.2) + shared initial.degrees shared initial 0 (Nat.add_zero _).symm + generic + (fun pair _ => caseEffect pair.val (Array.mem_def.mp pair.property)) + simp only [Array.toList_attach] at count ⊢ + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.lookupUsage)] at count + exact count + have loopGeneric : (loop.run initial).2.callRanks = #[] := by + dsimp only [loop] + rw [← Array.foldlM_toList] + exact (branchFold_callRanks branches.attach.toList (fun pair => pair.val.2) + shared initial.degrees shared initial).trans generic + rw [ctrlLayout_eq_def] + cases fallbackEq : fallback with + | none => + change (loop.run initial).1.lookups = _ + simpa only [branchLookupUsage, fallbackEq, Option.toList_none, List.map_nil, List.append_nil] using loopCount + | some block => + change max (loop.run initial).1.lookups + ((blockLayout block).run ((bumpAuxiliaries branches.size).run + ((setSharedData shared).run (loop.run initial).2).2).2).2.functionLayout.lookups = _ + rw [defaultEffect block fallbackEq ((bumpAuxiliaries branches.size).run + ((setSharedData shared).run (loop.run initial).2).2).2 loopGeneric] + change max (loop.run initial).1.lookups (initial.functionLayout.lookups + block.lookupUsage) = _ + rw [loopCount, Nat.add_max_add_left] + simp only [branchLookupUsage, Option.toList_some, List.map_cons, List.map_nil, + List.foldl_append, List.foldl_cons, List.foldl_nil] + +end Aiur.Concrete.Bytecode + +namespace Aiur.Bytecode + +def Function.LookupLayout (function : Function) : Prop := + function.layout.lookups = 4 + function.body.lookupUsage + +def FunctionsLookupLayout (functions : Array Function) : Prop := + ∀ function ∈ functions, function.LookupLayout + +private theorem functionsLookupLayout_empty : FunctionsLookupLayout #[] := by + simp [FunctionsLookupLayout] + +private theorem functionsLookupLayout_push {functions : Array Function} {function : Function} + (before : FunctionsLookupLayout functions) (valid : function.LookupLayout) : + FunctionsLookupLayout (functions.push function) := by + intro fn member + rcases Array.mem_push.mp member with prior | equal + · exact before fn prior + · subst fn; exact valid + +end Aiur.Bytecode + +namespace Aiur.AIR +open Bytecode + +theorem emitOp_lookupUsage {row : Nat → G} {selector rank : G} {op : Op} + {values : Array RowValue} {emission : OpEmission} + (emitted : emitOp row selector rank op values = some emission) : + emission.queries.length = op.lookupUsage := by + cases op <;> simp only [emitOp, emitByte1, emitByte2, emitU32LessThan, emitU32Add, + emitAdvice, bind, Option.bind, Option.map, pure] at emitted + all_goals + repeat' first + | split at emitted + | (dsimp only at emitted; split at emitted) + all_goals cases emitted + all_goals simp_all [Op.lookupUsage, rankByteQueries, range4Queries] + +theorem emitOps_lookupUsage {row : Nat → G} {selector rank : G} {ops : List Op} + {values : Array RowValue} {column : Nat} {emission : OpsEmission} + (emitted : emitOps row selector rank ops values column = some emission) : + emission.queries.length = (ops.map Op.lookupUsage).sum := by + induction ops generalizing values column emission with + | nil => + have equal := Option.some.inj emitted + subst emission + rfl + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i rest restEmitted + have equal := Option.some.inj emitted + subst emission + simp only [List.length_append, List.map_cons, List.sum_cons, + emitOp_lookupUsage firstEmitted, ih restEmitted] + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +private theorem lookup_fold_related {blocks : List Block} {emissions : List BlockEmission} {lookup : Nat} + (related : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage) blocks emissions) + (acc : Nat) : + emissions.foldl (fun value emission => max value emission.lookup) (lookup + acc) = + lookup + (blocks.map Block.lookupUsage).foldl Nat.max acc := by + induction related generalizing acc with + | nil => rfl + | cons first rest ih => + simp only [List.foldl_cons, List.map_cons, first, Nat.add_max_add_left] + exact ih _ + +theorem branchRows_lookupUsage (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (matched : G) (values : Array RowValue) (column lookup : Nat) + (branches : Array (G × Block)) (fallback : Option Block) {emission : BlockEmission} + (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) + (caseSound : ∀ pair ∈ branches.toList, ∀ emission, + pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → + emission.lookup = lookup + pair.2.lookupUsage) + (defaultSound : ∀ block, fallback = some block → ∀ emission, + block.emitRow row selector context (block.selectorFlow selector).entry values + (column + branches.size) lookup = some emission → + emission.lookup = lookup + block.lookupUsage) : + emission.lookup = lookup + branchLookupUsage branches fallback := by + simp only [branchRows, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i cases casesEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i default defaultEmitted + have equal := Option.some.inj emitted + subst emission + have casesRelated : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage) + (branches.toList.map Prod.snd) cases := by + apply forall₂_map_left + apply mapM_forall₂ casesEmitted + intro pair member emission emitted + simp only [caseRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i body bodyEmitted + have equal := Option.some.inj emitted + subst emission + exact caseSound pair member body bodyEmitted + have defaultRelated : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage) + fallback.toList default := by + cases fallbackEq : fallback with + | none => + simp only [defaultRow, fallbackEq, Option.some.injEq] at defaultEmitted + subst default + exact .nil + | some block => + simp only [defaultRow, fallbackEq, bind, Option.bind] at defaultEmitted + split at defaultEmitted + · cases defaultEmitted + · rename_i body bodyEmitted + have equal := Option.some.inj defaultEmitted + subst default + exact .cons (defaultSound block fallbackEq body bodyEmitted) .nil + have joined := lookup_fold_related (forall₂_append casesRelated defaultRelated) 0 + simpa only [Nat.add_zero, joinBlockEmissions, branchLookupUsage, List.map_append, + List.map_map, Function.comp_def] using joined + +private theorem lookup_pair_smaller (pair : G × Block) : sizeOf pair.2 < sizeOf pair := by + cases pair + simp + omega + +private theorem lookup_option_smaller {fallback : Option Block} {block : Block} + (present : fallback = some block) : sizeOf block < sizeOf fallback := by + rw [present] + simp + +mutual + +theorem Ctrl.emitRow_lookupUsage (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) + {emission : BlockEmission} + (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) : + emission.lookup = lookup + ctrl.lookupUsage := by + cases ctrlEq : ctrl with + | «return» index indices => + rw [ctrlEq] at emitted + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · dsimp only at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + simp only [Ctrl.lookupUsage, Nat.add_zero] + | yield index indices => + rw [ctrlEq] at emitted + rw [Ctrl.emitRow.eq_def] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · have equal := Option.some.inj emitted + subst emission + simp only [Ctrl.lookupUsage, Nat.add_zero] + | «match» index branches fallback => + rw [ctrlEq] at emitted + rw [Ctrl.lookupUsage_match] + rw [Ctrl.emitRow_match] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + apply branchRows_lookupUsage row selector context matched.value values column lookup branches fallback emitted + · intro pair member body bodyEmitted + exact Block.emitRow_lookupUsage row selector context _ values column lookup pair.2 bodyEmitted + · intro block present body bodyEmitted + exact Block.emitRow_lookupUsage row selector context _ values _ lookup block bodyEmitted + | matchContinue index branches fallback size aux slots continuation => + rw [ctrlEq] at emitted + rw [Ctrl.lookupUsage_matchContinue] + rw [Ctrl.emitRow_matchContinue] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i matched read + dsimp only at emitted + split at emitted + · cases emitted + · rename_i joined branchesEmitted + simp only [continueRow] at emitted + split at emitted + · simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i continued contEmitted + have equal := Option.some.inj emitted + subst emission + have joinedLookup := branchRows_lookupUsage row selector context matched.value values column lookup + branches fallback branchesEmitted + (fun pair member body bodyEmitted => + Block.emitRow_lookupUsage row selector context _ values column lookup pair.2 bodyEmitted) + (fun block present body bodyEmitted => + Block.emitRow_lookupUsage row selector context _ values _ lookup block bodyEmitted) + have contLookup := Block.emitRow_lookupUsage row selector context _ _ _ _ continuation contEmitted + simpa only [BlockEmission.continued, joinedLookup, Nat.add_assoc] using contLookup + · cases emitted +termination_by sizeOf ctrl +decreasing_by + all_goals + try rw [ctrlEq] + first + | (have bound := Array.sizeOf_lt_of_mem (Array.mem_def.mpr member) + have pairBound := lookup_pair_smaller pair + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (have optionBound := lookup_option_smaller present + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (simp only [Ctrl.matchContinue.sizeOf_spec]; omega) + +theorem Block.emitRow_lookupUsage (row : Nat → G) (selector : SelIdx → G) (context : RowContext) + (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) + {emission : BlockEmission} + (emitted : block.emitRow row selector context incoming values column lookup = some emission) : + emission.lookup = lookup + block.lookupUsage := by + rw [Block.emitRow] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i operations opsEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i control ctrlEmitted + have controlLookup := Ctrl.emitRow_lookupUsage row selector context incoming _ _ _ block.ctrl ctrlEmitted + have equal := Option.some.inj emitted + subst emission + simpa only [BlockEmission.prefix, BlockEmission.afterOps, Block.lookupUsage, + emitOps_lookupUsage opsEmitted, Nat.add_assoc] using controlLookup +termination_by sizeOf block +decreasing_by exact lookup_block_smaller block + +end + +end Aiur.Bytecode + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode + +private theorem ctrlLayout_matchContinue (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) (size aux slots : Nat) (continuation : Block) : + ctrlLayout (.matchContinue index branches fallback size aux slots continuation) = (do + ctrlLayout (.match index branches fallback) + bumpAuxiliaries size + pushDegrees (.replicate size 1) + blockLayout continuation) := by + exact ctrlLayout_eq_def _ + +mutual + +theorem ctrlLayout_lookupUsage (ctrl : Ctrl) (initial : LayoutMState) + (generic : initial.callRanks = #[]) : + ((ctrlLayout ctrl).run initial).2.functionLayout.lookups = + initial.functionLayout.lookups + ctrl.lookupUsage := by + cases ctrlEq : ctrl with + | «return» index indices => + rw [ctrlLayout_eq_def, Ctrl.lookupUsage.eq_def] + rfl + | yield index indices => + rw [ctrlLayout_eq_def, Ctrl.lookupUsage.eq_def] + rfl + | «match» index branches fallback => + rw [Ctrl.lookupUsage_match] + apply matchLayout_lookupUsage index branches fallback initial generic + · intro pair member state stateGeneric + exact blockLayout_lookupUsage pair.2 state stateGeneric + · intro block present state stateGeneric + exact blockLayout_lookupUsage block state stateGeneric + | matchContinue index branches fallback size aux slots continuation => + rw [ctrlLayout_matchContinue, Ctrl.lookupUsage_matchContinue] + change ((blockLayout continuation).run ((pushDegrees (.replicate size 1)).run + ((bumpAuxiliaries size).run ((ctrlLayout (.match index branches fallback)).run initial).2).2).2).2.functionLayout.lookups = _ + rw [blockLayout_lookupUsage continuation ((pushDegrees (.replicate size 1)).run + ((bumpAuxiliaries size).run ((ctrlLayout (.match index branches fallback)).run initial).2).2).2 + ((ctrlLayout_callRanks _ initial).trans generic)] + change ((ctrlLayout (.match index branches fallback)).run initial).2.functionLayout.lookups + + continuation.lookupUsage = _ + have first := matchLayout_lookupUsage index branches fallback initial generic + (fun pair member state stateGeneric => blockLayout_lookupUsage pair.2 state stateGeneric) + (fun block present state stateGeneric => blockLayout_lookupUsage block state stateGeneric) + rw [first, Nat.add_assoc] +termination_by sizeOf ctrl +decreasing_by + all_goals + try rw [ctrlEq] + first + | (have bound := Array.sizeOf_lt_of_mem (Array.mem_def.mpr member) + have pairBound := lookup_pair_smaller pair + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (have optionBound := lookup_option_smaller present + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (simp only [Ctrl.matchContinue.sizeOf_spec]; omega) + +theorem blockLayout_lookupUsage (block : Block) (initial : LayoutMState) + (generic : initial.callRanks = #[]) : + ((blockLayout block).run initial).2.functionLayout.lookups = + initial.functionLayout.lookups + block.lookupUsage := by + rw [blockLayout] + change ((ctrlLayout block.ctrl).run ((block.ops.forM opLayout).run initial).2).2.functionLayout.lookups = _ + rw [ctrlLayout_lookupUsage _ _ ((congrArg Prod.snd (opsLayout_context block.ops initial)).trans generic), + opsLayout_lookupUsage _ initial generic, Block.lookupUsage, Nat.add_assoc] +termination_by sizeOf block +decreasing_by exact lookup_block_smaller block + +end + +end Aiur.Concrete.Bytecode + +namespace Aiur.Concrete +open Aiur.Bytecode + +private theorem layout_result_lookupUsage {body : Block} {size : Nat} {state : Bytecode.LayoutMState} + {resultUnit : Unit} (computed : (Bytecode.blockLayout body).run (.new size) = (resultUnit, state)) : + state.functionLayout.lookups + 1 = 4 + body.lookupUsage := by + have count := Bytecode.blockLayout_lookupUsage body (.new size) rfl + rw [computed] at count + simp only [Bytecode.LayoutMState.new] at count + omega + +theorem Function.compile_lookupLayout {layoutMap : LayoutMap} {function : Function} + {body : Block} {state : Bytecode.LayoutMState} + (compiled : function.compile layoutMap = .ok (body, state)) : + state.functionLayout.lookups = 4 + body.lookupUsage := by + unfold Function.compile at compiled + simp only [bind, Except.bind, pure, Except.pure] at compiled + repeat' first + | split at compiled + | (dsimp only at compiled; split at compiled) + all_goals cases compiled + all_goals + change _ + 1 = 4 + _ + exact layout_result_lookupUsage (by assumption) + +open Std.Do + +private theorem except_post {ε α : Type} (action : Except ε α) (property : α → Prop) + (valid : ∀ value, action = .ok value → property value) : + ⦃⌜True⌝⦄ action ⦃post⟨fun value => ⌜property value⌝, fun _ => ⌜True⌝⟩⦄ := by + cases computed : action with + | error error => + change ⦃⌜True⌝⦄ (throw error : Except ε α) ⦃post⟨fun value => ⌜property value⌝, fun _ => ⌜True⌝⟩⦄ + simp [Triple.iff] + | ok value => + change ⦃⌜True⌝⦄ (pure value : Except ε α) ⦃post⟨fun value => ⌜property value⌝, fun _ => ⌜True⌝⟩⦄ + simpa [Triple.iff] using valid value computed + +private theorem lookup_throw {ε α : Type} {error : ε} {post : PostCond α (.except ε .pure)} : + Triple (ps := .except ε .pure) (throw error : Except ε α) (spred(post.2.1 error)) post := by + simp [Triple.iff] + +private theorem layoutMap_spec (decls : Decls) : + ⦃⌜True⌝⦄ decls.layoutMap ⦃post⟨fun _ => ⌜True⌝, fun _ => ⌜True⌝⟩⦄ := + except_post decls.layoutMap (fun _ => True) (fun _ _ => trivial) + +set_option mvcgen.warning false in +theorem Decls.toBytecode_lookupLayout {decls : Decls} {program : Toplevel} + {names : Std.HashMap Global FunIdx} (compiled : decls.toBytecode = .ok (program, names)) : + FunctionsLookupLayout program.functions := by + have spec : ⦃⌜True⌝⦄ decls.toBytecode + ⦃post⟨fun result => ⌜FunctionsLookupLayout result.1.functions⌝, fun _ => ⌜True⌝⟩⦄ := by + mvcgen [Decls.toBytecode, IndexMap.foldlM, ← Array.foldlM_toList, + layoutMap_spec, -Spec.throw_Except, lookup_throw] invariants + · post⟨fun ⟨_, functions, _⟩ => ⌜FunctionsLookupLayout functions⌝, fun _ => ⌜True⌝⟩ + case vc2.step.h_1.h_2 => + apply functionsLookupLayout_push (by assumption) + exact Function.compile_lookupLayout (by assumption) + case vc4.success.pre => exact functionsLookupLayout_empty + exact Except.of_wp_eq compiled (fun result => match result with + | .error _ => True + | .ok result => FunctionsLookupLayout result.1.functions) spec + +end Aiur.Concrete + +namespace Aiur.Bytecode + +theorem rewriteOp_lookupUsage (rename : FunIdx → FunIdx) (op : Op) : + (rewriteOp rename op).lookupUsage = op.lookupUsage := by + cases op <;> rfl + +private theorem branchLookupUsage_rewrite (rename : FunIdx → FunIdx) + (branches : Array (G × Block)) (fallback : Option Block) + (caseEqual : ∀ pair ∈ branches.toList, (rewriteBlock rename pair.2).lookupUsage = pair.2.lookupUsage) + (defaultEqual : ∀ block, fallback = some block → (rewriteBlock rename block).lookupUsage = block.lookupUsage) : + branchLookupUsage (branches.attach.map fun ⟨(tag, block), _⟩ => (tag, rewriteBlock rename block)) + (fallback.map (rewriteBlock rename)) = + branchLookupUsage branches fallback := by + unfold branchLookupUsage + apply congrArg (fun values : List Nat => values.foldl Nat.max 0) + congr 1 + · simp only [Array.toList_map, Array.toList_attach, List.map_map, Function.comp_def] + rw [← List.attachWith_map_val (p := fun pair => pair ∈ branches) + (f := fun pair : G × Block => pair.2.lookupUsage) (fun _ member => Array.mem_def.mpr member)] + apply List.map_congr_left + intro pair member + rcases pair with ⟨⟨tag, block⟩, present⟩ + exact caseEqual (tag, block) (Array.mem_def.mp present) + · cases fallbackEq : fallback with + | none => rfl + | some block => + simp only [Option.map_some, Option.toList_some, List.map_cons, List.map_nil] + rw [defaultEqual block fallbackEq] + +mutual + +theorem rewriteCtrl_lookupUsage (rename : FunIdx → FunIdx) (ctrl : Ctrl) : + (rewriteCtrl rename ctrl).lookupUsage = ctrl.lookupUsage := by + cases ctrlEq : ctrl with + | «return» index indices => rw [rewriteCtrl.eq_def] + | yield index indices => rw [rewriteCtrl.eq_def] + | «match» index branches fallback => + rw [rewriteCtrl.eq_def, Ctrl.lookupUsage_match, Ctrl.lookupUsage_match] + have equal := branchLookupUsage_rewrite rename branches fallback + (fun pair member => rewriteBlock_lookupUsage rename pair.2) + (fun block present => rewriteBlock_lookupUsage rename block) + cases fallback <;> exact equal + | matchContinue index branches fallback size aux slots continuation => + rw [rewriteCtrl.eq_def, Ctrl.lookupUsage_matchContinue, Ctrl.lookupUsage_matchContinue, + rewriteBlock_lookupUsage rename continuation] + congr 1 + have equal := branchLookupUsage_rewrite rename branches fallback + (fun pair member => rewriteBlock_lookupUsage rename pair.2) + (fun block present => rewriteBlock_lookupUsage rename block) + cases fallback <;> exact equal +termination_by sizeOf ctrl +decreasing_by + all_goals + try rw [ctrlEq] + first + | (have bound := Array.sizeOf_lt_of_mem (Array.mem_def.mpr member) + have pairBound := lookup_pair_smaller pair + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (have optionBound := lookup_option_smaller present + first | simp only [Ctrl.match.sizeOf_spec] | simp only [Ctrl.matchContinue.sizeOf_spec] + omega) + | (simp only [Ctrl.matchContinue.sizeOf_spec]; omega) + +theorem rewriteBlock_lookupUsage (rename : FunIdx → FunIdx) (block : Block) : + (rewriteBlock rename block).lookupUsage = block.lookupUsage := by + rw [rewriteBlock, Block.lookupUsage, Block.lookupUsage, rewriteCtrl_lookupUsage] + simp only [Array.toList_map, List.map_map, Function.comp_def, rewriteOp_lookupUsage] +termination_by sizeOf block +decreasing_by exact lookup_block_smaller block + +end + +theorem deduplicate_newFunctions_lookupLayout (functions : Array Function) + (classes : Array Nat) (canonical : Array Bool) (rename : FunIdx → FunIdx) + (valid : FunctionsLookupLayout functions) : + FunctionsLookupLayout (deduplicate_newFunctions functions classes canonical rename) := by + unfold deduplicate_newFunctions + apply Array.foldl_induction (fun _ result => FunctionsLookupLayout result) functionsLookupLayout_empty + intro index accumulated before + dsimp only + split + · apply functionsLookupLayout_push before + change (((classes.zip canonical).zip functions)[index]).2.layout.lookups = + 4 + (rewriteBlock rename (((classes.zip canonical).zip functions)[index]).2.body).lookupUsage + rw [rewriteBlock_lookupUsage] + apply valid + exact (Array.of_mem_zip (Array.getElem_mem index.isLt)).2 + · exact before + +theorem Toplevel.deduplicateCandidate_lookupLayout (program : Toplevel) + (valid : FunctionsLookupLayout program.functions) : + FunctionsLookupLayout program.deduplicateCandidate.1.functions := by + unfold Toplevel.deduplicateCandidate + dsimp only + split + · exact valid + · exact deduplicate_newFunctions_lookupLayout _ _ _ _ valid + +theorem Toplevel.deduplicate_lookupLayout (program : Toplevel) + (valid : FunctionsLookupLayout program.functions) : + FunctionsLookupLayout program.deduplicate.1.functions := by + unfold Toplevel.deduplicate checkedRenaming + dsimp only + split + · exact program.deduplicateCandidate_lookupLayout valid + · exact valid + +end Aiur.Bytecode + +namespace Aiur +open Bytecode + +theorem finishCompilation_lookupLayout (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) (valid : FunctionsLookupLayout raw.functions) + (generic : source.componentRanks = false) : + FunctionsLookupLayout (finishCompilation source raw names).bytecode.functions := by + unfold finishCompilation + simp only [generic, Bool.false_eq_true, if_false] + intro function member + obtain ⟨index, bound, equal⟩ := Array.exists_of_mem_mapIdx member + subst function + change raw.deduplicate.1.functions[index].LookupLayout + exact raw.deduplicate_lookupLayout valid _ (Array.getElem_mem bound) + +theorem Source.Toplevel.compile_lookupLayout {source : Source.Toplevel} {compiled : CompiledToplevel} + (accepted : source.compile = .ok compiled) (generic : source.componentRanks = false) : + FunctionsLookupLayout compiled.bytecode.functions := by + obtain ⟨inlined, typed, concrete, raw, names, inlinedOk, _, _, lowered, artifact⟩ := + source.compile_artifact_of_ok accepted + rw [artifact] + exact finishCompilation_lookupLayout inlined raw names (Concrete.Decls.toBytecode_lookupLayout lowered) + ((Source.Toplevel.inlineCalls_componentRanks inlinedOk).trans generic) + +theorem BoundVerifier.Backend.functions_lookupLayout {selection : BoundVerifier.Selection} + (backend : BoundVerifier.Backend selection) (generic : selection.source.componentRanks = false) : + FunctionsLookupLayout backend.compiled.bytecode.functions := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + have valid := Source.Toplevel.compile_lookupLayout compiled generic + split at grouped + · cases grouped + exact valid + · rw [(CompiledToplevel.groupFunctions_preserves_code grouped).2.2.1] + exact valid + +end Aiur + +namespace Aiur.Bytecode + +def MembersLookupBound (functions : Array Function) (members : Array FunIdx) (slots : Nat) : Prop := + 4 ≤ slots ∧ ∀ index ∈ members, functions[index]!.layout.lookups ≤ slots + +def CircuitsLookupBound (functions : Array Function) (circuits : Array Circuit) : Prop := + ∀ circuit ∈ circuits, MembersLookupBound functions circuit.members circuit.layout.lookups + +private theorem lookup_circuits_empty (functions : Array Function) : CircuitsLookupBound functions #[] := by + simp [CircuitsLookupBound] + +private theorem lookup_circuits_push {functions : Array Function} {circuits : Array Circuit} {circuit : Circuit} + (before : CircuitsLookupBound functions circuits) + (member : MembersLookupBound functions circuit.members circuit.layout.lookups) : + CircuitsLookupBound functions (circuits.push circuit) := by + intro c present + rcases Array.mem_push.mp present with prior | equal + · exact before c prior + · subst c; exact member + +private theorem lookup_member_singleton {functions : Array Function} {index : FunIdx} {function : Function} + (present : functions[index]? = some function) (valid : function.LookupLayout) : + MembersLookupBound functions #[index] function.layout.lookups := by + constructor + · change function.layout.lookups = 4 + function.body.lookupUsage at valid + omega + · intro i member + have equal : i = index := by simpa using member + subst i + rw [Array.getElem!_eq_getD, Array.getD_eq_getD_getElem?, present] + exact Nat.le_refl _ + +open Std.Do + +set_option mvcgen.warning false in +theorem singletonCircuits_lookupBound (program : Toplevel) (nameOf : FunIdx → String) + (valid : FunctionsLookupLayout program.functions) : + CircuitsLookupBound program.functions (program.singletonCircuits nameOf) := by + have spec : Triple (m := Id) (program.singletonCircuits nameOf) ⌜True⌝ + (⇓ circuits => ⌜CircuitsLookupBound program.functions circuits⌝) := by + mvcgen [Toplevel.singletonCircuits, Id.run] invariants + · ⇓⟨_, circuits⟩ => ⌜CircuitsLookupBound program.functions circuits⌝ + case vc1.step.isTrue => + apply lookup_circuits_push (by assumption) + exact lookup_member_singleton (Array.getElem?_eq_getElem _) (valid _ (Array.getElem_mem _)) + case vc3.pre => exact lookup_circuits_empty _ + exact Id.of_wp_run_eq rfl _ spec + +private theorem lookup_bang_of_present {functions : Array Function} {index : Nat} {function : Function} + (present : functions[index]? = some function) : functions[index]! = function := by + rw [Array.getElem!_eq_getD, Array.getD_eq_getD_getElem?, present] + rfl + +private theorem lookup_array_bang {α : Type} [Inhabited α] (property : α → Prop) + {array : Array α} (valid : ∀ value ∈ array, property value) (fallback : property default) (index : Nat) : + property array[index]! := by + by_cases bound : index < array.size + · rw [getElem!_pos array index bound] + exact valid _ (Array.getElem_mem bound) + · rw [getElem!_neg array index bound] + exact fallback + +private theorem lookup_first_reserved {functions : Array Function} {members : Array FunIdx} + (valid : FunctionsLookupLayout functions) (nonempty : 0 < functions.size) + (constrained : MembersConstrained functions members) : + 4 ≤ functions[members[0]!]!.layout.lookups := by + refine lookup_array_bang (fun index : FunIdx => 4 ≤ functions[index]!.layout.lookups) + (array := members) ?_ ?_ 0 + · intro index member + obtain ⟨function, present, _⟩ := constrained index member + rw [lookup_bang_of_present present] + have bound := valid function (Array.mem_of_getElem? present) + change function.layout.lookups = 4 + function.body.lookupUsage at bound + omega + · change 4 ≤ functions[0]!.layout.lookups + rw [getElem!_pos functions 0 nonempty] + have bound := valid _ (Array.getElem_mem nonempty) + change functions[0].layout.lookups = 4 + functions[0].body.lookupUsage at bound + omega + +private theorem lookup_merge_fold (functions : Array Function) (first : FunIdx) (members : List FunIdx) + (initial : FunctionLayout) (firstBound : functions[first]!.layout.lookups ≤ initial.lookups) : + let final := members.foldl (fun acc index => if index == first then acc else acc.merge functions[index]!.layout) initial + initial.lookups ≤ final.lookups ∧ ∀ index ∈ members, functions[index]!.layout.lookups ≤ final.lookups := by + induction members generalizing initial with + | nil => exact ⟨Nat.le_refl _, by simp⟩ + | cons index members ih => + let next := if index == first then initial else initial.merge functions[index]!.layout + have before : initial.lookups ≤ next.lookups := by + dsimp only [next] + split + · exact Nat.le_refl _ + · exact Nat.le_max_left _ _ + have here : functions[index]!.layout.lookups ≤ next.lookups := by + dsimp only [next] + split + · rename_i equal + have eq : index = first := beq_iff_eq.mp equal + subst index + exact firstBound + · exact Nat.le_max_right _ _ + have rest := ih next (Nat.le_trans firstBound before) + refine ⟨Nat.le_trans before rest.1, ?_⟩ + intro chosen member + rcases List.mem_cons.mp member with equal | later + · subst chosen; exact Nat.le_trans here rest.1 + · exact rest.2 chosen later + +theorem merged_lookupBound (functions : Array Function) (members : Array FunIdx) + (valid : FunctionsLookupLayout functions) (nonempty : 0 < functions.size) + (constrained : MembersConstrained functions members) : + MembersLookupBound functions members + (members.foldl (init := functions[members[0]!]!.layout) + fun acc index => if index == members[0]! then acc else acc.merge functions[index]!.layout).lookups := by + rw [← Array.foldl_toList] + have folded := lookup_merge_fold functions members[0]! members.toList functions[members[0]!]!.layout + (Nat.le_refl _) + exact ⟨Nat.le_trans (lookup_first_reserved valid nonempty constrained) folded.1, + fun index member => folded.2 index (Array.mem_def.mp member)⟩ + +end Aiur.Bytecode + +namespace Aiur +open Bytecode Std.Do + +private theorem lookup_throw_except {ε α : Type} {error : ε} {post : PostCond α (.except ε .pure)} : + Triple (ps := .except ε .pure) (throw error : Except ε α) (spred(post.2.1 error)) post := by + simp [Triple.iff] + +private theorem lookup_members_empty (functions : Array Function) : MembersConstrained functions #[] := by + simp [MembersConstrained] + +private theorem lookup_members_push {functions : Array Function} {members : Array FunIdx} {index : FunIdx} + (before : MembersConstrained functions members) (constrained : functions[index]!.constrained = true) : + MembersConstrained functions (members.push index) := by + intro i member + rcases Array.mem_push.mp member with prior | equal + · exact before i prior + · subst i + by_cases bound : index < functions.size + · exact ⟨functions[index], Array.getElem?_eq_getElem bound, + by simpa only [getElem!_pos functions index bound] using constrained⟩ + · rw [getElem!_neg functions index bound] at constrained + contradiction + +private theorem lookup_split_member {α : Type} {array : Array α} {pref suff : List α} {value : α} + (split : array.toList = pref ++ value :: suff) : value ∈ array := by + apply Array.mem_toList_iff.mp + rw [split] + simp + +set_option mvcgen.warning false in +theorem CompiledToplevel.groupFunctions_lookupBound {before after : CompiledToplevel} + {groups : Array (String × Array String)} + (functions : FunctionsLookupLayout before.bytecode.functions) + (nonempty : 0 < before.bytecode.functions.size) + (valid : CircuitsLookupBound before.bytecode.functions before.bytecode.circuits) + (accepted : before.groupFunctions groups = .ok after) : + CircuitsLookupBound after.bytecode.functions after.bytecode.circuits := by + have spec : ⦃⌜True⌝⦄ before.groupFunctions groups + ⦃post⟨fun compiled => ⌜CircuitsLookupBound compiled.bytecode.functions compiled.bytecode.circuits⌝, + fun _ => ⌜True⌝⟩⦄ := by + mvcgen [CompiledToplevel.groupFunctions, -Spec.throw_Except, lookup_throw_except] invariants + · post⟨fun ⟨_, _, resolved⟩ => ⌜∀ pair ∈ resolved, + MembersConstrained before.bytecode.functions pair.2⌝, fun _ => ⌜True⌝⟩ + · post⟨fun ⟨_, _, members⟩ => ⌜MembersConstrained before.bytecode.functions members⌝, + fun _ => ⌜True⌝⟩ + · post⟨fun ⟨_, circuits, _⟩ => ⌜CircuitsLookupBound before.bytecode.functions circuits⌝, + fun _ => ⌜True⌝⟩ + case vc4.step.h_1.isTrue.isFalse.isFalse => exact lookup_members_push (by assumption) (by assumption) + case vc7.step.isFalse.pre => exact lookup_members_empty _ + case vc8.step.isFalse.post.success => + intro pair member + rcases Array.mem_push.mp member with prior | equal + · apply_assumption; exact prior + · subst pair; assumption + case vc10.pre => + change ∀ pair ∈ (#[] : Array (String × Array FunIdx)), _ + simp + case vc11.step.isTrue.h_1 => + apply lookup_circuits_push (by assumption) + apply valid + exact lookup_split_member (by assumption) + case vc13.step.isTrue.h_2.isFalse => + apply lookup_circuits_push (by assumption) + apply merged_lookupBound _ _ functions nonempty + exact lookup_array_bang (fun pair : String × Array FunIdx => + MembersConstrained before.bytecode.functions pair.2) (by assumption) (lookup_members_empty _) _ + case vc15.post.success.pre => exact lookup_circuits_empty _ + exact Except.of_wp_eq accepted (fun result => match result with + | .error _ => True + | .ok compiled => CircuitsLookupBound compiled.bytecode.functions compiled.bytecode.circuits) spec + +theorem finishCompilation_lookupBound (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) (valid : FunctionsLookupLayout raw.functions) + (generic : source.componentRanks = false) : + CircuitsLookupBound (finishCompilation source raw names).bytecode.functions + (finishCompilation source raw names).bytecode.circuits := by + unfold finishCompilation + apply singletonCircuits_lookupBound + exact finishCompilation_lookupLayout source raw names valid generic + +theorem Source.Toplevel.compile_lookupBound {source : Source.Toplevel} {compiled : CompiledToplevel} + (accepted : source.compile = .ok compiled) (generic : source.componentRanks = false) : + CircuitsLookupBound compiled.bytecode.functions compiled.bytecode.circuits := by + obtain ⟨inlined, typed, concrete, raw, names, inlinedOk, _, _, lowered, artifact⟩ := + source.compile_artifact_of_ok accepted + rw [artifact] + exact finishCompilation_lookupBound inlined raw names (Concrete.Decls.toBytecode_lookupLayout lowered) + ((Source.Toplevel.inlineCalls_componentRanks inlinedOk).trans generic) + +theorem BoundVerifier.Backend.circuits_lookupBound {selection : BoundVerifier.Selection} + (backend : BoundVerifier.Backend selection) (generic : selection.source.componentRanks = false) : + CircuitsLookupBound backend.compiled.bytecode.functions backend.compiled.bytecode.circuits := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + have valid := Source.Toplevel.compile_lookupBound compiled generic + split at grouped + · cases grouped + exact valid + · have same := (CompiledToplevel.groupFunctions_preserves_code grouped).2.2.1 + have bound := (Array.getElem?_eq_some_iff.mp backend.present).choose + rw [same] at bound + exact CompiledToplevel.groupFunctions_lookupBound + (Source.Toplevel.compile_lookupLayout compiled generic) (by omega) valid grouped + +end Aiur + +namespace Aiur.AIR +open Bytecode + +theorem CircuitWitness.lookupBounds_of_compiled {program : Toplevel} + (functions : FunctionsLookupLayout program.functions) + (layouts : CircuitsLookupBound program.functions program.circuits) + (witness : CircuitWitness) (circuit : witness.circuit ∈ program.circuits) + (emitted : witness.Emitted program) : witness.LookupBounds := by + obtain ⟨_, indices, source⟩ := witness.circuit.emitRow_spec witness.values program emitted + have bounds := layouts witness.circuit circuit + refine ⟨bounds.1, ?_⟩ + intro part member + have index : part.functionIndex ∈ witness.circuit.members := by + apply Array.mem_toList_iff.mp + rw [← indices] + exact List.mem_map.mpr ⟨part, member, rfl⟩ + have present := (source part member).present + have count := Block.emitRow_lookupUsage witness.values (part.selector witness.values) _ _ _ _ _ + part.function.body (source part member).emitted + have layout := functions part.function (Array.mem_of_getElem? present) + change part.function.layout.lookups = 4 + part.function.body.lookupUsage at layout + have limit := bounds.2 part.functionIndex index + rw [lookup_bang_of_present present] at limit + rw [count, ← layout] + exact limit + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem Backend.witness_lookupBounds {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + (witness : CircuitWitness) (circuit : witness.circuit ∈ backend.compiled.bytecode.circuits) + (emitted : witness.Emitted backend.compiled.bytecode) : witness.LookupBounds := + witness.lookupBounds_of_compiled (backend.functions_lookupLayout generic) + (backend.circuits_lookupBound generic) circuit emitted + +theorem Backend.bounded_trace_execution {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + (tables : AuxiliaryTables) (traces : CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List CircuitWitness} + (emitted : traces.emitWitnesses backend.compiled.bytecode = some witnesses) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (budget : lookupQueryBound + (backend.compiled.bytecode.circuits.toList.map (·.layout.lookups) ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: + encodedCircuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) + ⟨selection.function, input, selection.success, 0⟩ := by + have valid := (traces.emitWitnesses_spec emitted).1 + apply backend.compiled_trace_execution tables traces emitted budget width input arity balanced + publicWidth queryWidths memoryValid canonical satisfied + intro witness member + exact backend.witness_lookupBounds generic witness + (by simpa using (valid witness member).1) (valid witness member).2 + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/LookupMessages.lean b/Ix/Aiur/Proofs/LookupMessages.lean new file mode 100644 index 000000000..482a07d1f --- /dev/null +++ b/Ix/Aiur/Proofs/LookupMessages.lean @@ -0,0 +1,371 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ByteLookups + +/-! +Exact lookup messages from their zero-padded representations. + +The first two fields determine message length through the native channel +and function-arity schema. Padding is then injective, and exact balance +passes through padding and channel filtering. Zero-weight providers may +contain arbitrary data. Function and memory encodings recover the typed +messages used by execution and memory-table proofs. + +These results do not extract padded balance from the cryptographic verifier. +Connecting all native active rows to the function-arity schema is also an +obligation; an arbitrary bytecode program need not have uniform returns. +-/ + +namespace Aiur.AIR + +def padMessage (width : Nat) (message : List G) : List G := + List.ofFn fun i : Fin width => message[i.val]?.getD 0 + +theorem padMessage_length (width : Nat) (message : List G) : + (padMessage width message).length = width := List.length_ofFn + +theorem padMessage_read {width : Nat} (message : List G) (i : Nat) (hi : i < width) : + (padMessage width message)[i]?.getD 0 = message[i]?.getD 0 := by + simp only [padMessage, List.getElem?_ofFn, dif_pos hi, Option.getD_some] + +theorem padMessage_injective_of_length {width : Nat} {left right : List G} + (bounded : left.length ≤ width) (lengths : left.length = right.length) + (same : padMessage width left = padMessage width right) : left = right := by + apply List.ext_getElem lengths + intro i hi hj + have equal := congrArg (fun message => message[i]?.getD 0) same + rw [padMessage_read left i (by omega), padMessage_read right i (by omega)] at equal + simpa only [List.getElem?_eq_getElem hi, List.getElem?_eq_getElem hj, + Option.getD_some] using equal + +/-- The message length is determined by its first two entries. -/ +def HasMessageShape (widths : G → G → Nat) (message : List G) : Prop := + 2 ≤ message.length ∧ message.length = widths (message[0]?.getD 0) (message[1]?.getD 0) + +theorem padMessage_injective_of_shape {width : Nat} {widths : G → G → Nat} + {left right : List G} (leftShape : HasMessageShape widths left) + (rightShape : HasMessageShape widths right) (bounded : left.length ≤ width) + (same : padMessage width left = padMessage width right) : left = right := by + have minimum := leftShape.1 + have first := congrArg (fun message => message[0]?.getD 0) same + have second := congrArg (fun message => message[1]?.getD 0) same + rw [padMessage_read left 0 (by omega), padMessage_read right 0 (by omega)] at first + rw [padMessage_read left 1 (by omega), padMessage_read right 1 (by omega)] at second + apply padMessage_injective_of_length bounded _ same + rw [leftShape.2, rightShape.2, first, second] + +def mapProviders (encode : α → β) (providers : List (Provider α)) : List (Provider β) := + providers.map fun provider => (encode provider.1, provider.2) + +theorem count_map_of_matching [DecidableEq α] [DecidableEq β] + (encode : α → β) (message : α) (queries : List α) + (matching : ∀ query ∈ queries, encode query = encode message ↔ query = message) : + (queries.map encode).count (encode message) = queries.count message := by + induction queries with + | nil => rfl + | cons query queries ih => + have head := matching query List.mem_cons_self + have tail := ih (fun value member => matching value (List.mem_cons_of_mem query member)) + simp only [List.map_cons, List.count_cons, beq_iff_eq, head, tail] + +theorem suppliedWeight_map_of_matching [DecidableEq α] [DecidableEq β] + (encode : α → β) (message : α) (providers : List (Provider α)) + (matching : ∀ provider ∈ providers, + provider.2 ≠ 0 → (encode provider.1 = encode message ↔ provider.1 = message)) : + suppliedWeight (encode message) (mapProviders encode providers) = + suppliedWeight message providers := by + induction providers with + | nil => rfl + | cons provider providers ih => + have tail := ih (fun value member => matching value (List.mem_cons_of_mem provider member)) + change (if encode provider.1 = encode message then + provider.2 + suppliedWeight (encode message) (mapProviders encode providers) + else suppliedWeight (encode message) (mapProviders encode providers)) = + (if provider.1 = message then provider.2 + suppliedWeight message providers + else suppliedWeight message providers) + by_cases zero : provider.2 = 0 + · simp only [zero, G.zero_add, ite_self, tail] + · have head := matching provider List.mem_cons_self zero + simp only [head, tail] + +theorem suppliedWeight_eq_zero_of_absent [DecidableEq α] (message : α) + (providers : List (Provider α)) + (absent : ∀ provider ∈ providers, provider.2 ≠ 0 → provider.1 ≠ message) : + suppliedWeight message providers = 0 := by + induction providers with + | nil => rfl + | cons provider providers ih => + have tail := ih (fun value member => absent value (List.mem_cons_of_mem provider member)) + change (if provider.1 = message then provider.2 + suppliedWeight message providers + else suppliedWeight message providers) = 0 + by_cases zero : provider.2 = 0 + · simpa only [zero, G.zero_add, ite_self] using tail + · have head := absent provider List.mem_cons_self zero + simpa only [if_neg head] using tail + +theorem exactLookupBalance_of_injective_on [DecidableEq α] [DecidableEq β] + (encode : α → β) (admissible : α → Prop) + (injective : ∀ {left right}, admissible left → admissible right → + encode left = encode right → left = right) + {queries : List α} {providers : List (Provider α)} + (queriesAdmissible : ∀ query ∈ queries, admissible query) + (providersAdmissible : ∀ provider ∈ providers, provider.2 ≠ 0 → admissible provider.1) + (balanced : ExactLookupBalance (queries.map encode) (mapProviders encode providers)) : + ExactLookupBalance queries providers := by + intro message + by_cases valid : admissible message + · have queryMatching : ∀ query ∈ queries, + encode query = encode message ↔ query = message := by + intro query member + exact ⟨injective (queriesAdmissible query member) valid, congrArg encode⟩ + have providerMatching : ∀ provider ∈ providers, + provider.2 ≠ 0 → (encode provider.1 = encode message ↔ provider.1 = message) := by + intro provider member nonzero + exact ⟨injective (providersAdmissible provider member nonzero) valid, congrArg encode⟩ + have result := balanced (encode message) + rw [count_map_of_matching encode message queries queryMatching, + suppliedWeight_map_of_matching encode message providers providerMatching] at result + exact result + · have absent : message ∉ queries := fun member => valid (queriesAdmissible message member) + rw [List.count_eq_zero.mpr absent, suppliedWeight_eq_zero_of_absent message providers] + · rfl + · intro provider member nonzero equal + exact valid (equal ▸ providersAdmissible provider member nonzero) + +theorem suppliedWeight_filter [DecidableEq α] (keep : α → Bool) (message : α) + (providers : List (Provider α)) : + suppliedWeight message (providers.filter fun provider => keep provider.1) = + if keep message then suppliedWeight message providers else 0 := by + induction providers with + | nil => simp only [suppliedWeight, List.filter_nil, List.foldr_nil, ite_self] + | cons provider providers ih => + by_cases same : provider.1 = message + · by_cases retained : keep message = true + · simp only [List.filter_cons, same, retained, ↓reduceIte, suppliedWeight, List.foldr_cons] at * + rw [ih] + · have dropped : keep message = false := Bool.eq_false_iff.mpr retained + simp only [List.filter_cons, same, dropped, Bool.false_eq_true, ↓reduceIte] + simpa only [dropped, Bool.false_eq_true, ↓reduceIte] using ih + · by_cases retained : keep provider.1 = true + · simp only [List.filter_cons, retained, ↓reduceIte, suppliedWeight, + List.foldr_cons, if_neg same] at * + exact ih + · have dropped : keep provider.1 = false := Bool.eq_false_iff.mpr retained + simp only [List.filter_cons, dropped, Bool.false_eq_true, ↓reduceIte] + simpa only [suppliedWeight, List.foldr_cons, if_neg same] using ih + +/-- Restrict global exact balance to any collection of message channels. -/ +theorem ExactLookupBalance.filter [DecidableEq α] {queries : List α} + {providers : List (Provider α)} (balanced : ExactLookupBalance queries providers) + (keep : α → Bool) : + ExactLookupBalance (queries.filter keep) (providers.filter fun provider => keep provider.1) := by + intro message + rw [suppliedWeight_filter] + by_cases retained : keep message = true + · rw [if_pos retained, List.count_filter retained, balanced] + · rw [if_neg retained] + have absent : message ∉ queries.filter keep := fun member => + retained (List.mem_filter.mp member).2 + rw [List.count_eq_zero.mpr absent] + rfl + +def PaddedLookupBalance (width : Nat) (queries : List (List G)) + (providers : List (Provider (List G))) : Prop := + ExactLookupBalance (queries.map (padMessage width)) (mapProviders (padMessage width) providers) + +/-- A bounded query has a nonzero provider with the same padded message. +No message-shape hypothesis is needed for this first extraction step. -/ +theorem paddedLookupBalance_provider {width : Nat} {queries : List (List G)} + {providers : List (Provider (List G))} (balanced : PaddedLookupBalance width queries providers) + (bounded : queries.length < gSize.toNat) {message : List G} (queried : message ∈ queries) : + ∃ provider ∈ providers, padMessage width provider.1 = padMessage width message ∧ provider.2 ≠ 0 := by + obtain ⟨provider, member, same, nonzero⟩ := exactLookupBalance_provider balanced + (by simpa only [List.length_map] using bounded) (List.mem_map.mpr ⟨message, queried, rfl⟩) + obtain ⟨original, originalMember, equal⟩ := List.mem_map.mp member + subst provider + exact ⟨original, originalMember, same, nonzero⟩ + +theorem paddedLookupBalance_exact {width : Nat} (widths : G → G → Nat) + {queries : List (List G)} {providers : List (Provider (List G))} + (queryShapes : ∀ query ∈ queries, HasMessageShape widths query ∧ query.length ≤ width) + (providerShapes : ∀ provider ∈ providers, provider.2 ≠ 0 → + HasMessageShape widths provider.1 ∧ provider.1.length ≤ width) + (balanced : PaddedLookupBalance width queries providers) : + ExactLookupBalance queries providers := by + apply exactLookupBalance_of_injective_on (padMessage width) + (fun message => HasMessageShape widths message ∧ message.length ≤ width) _ + queryShapes providerShapes balanced + intro left right hl hr same + exact padMessage_injective_of_shape hl.1 hr.1 hl.2 same + +/-- Input and output widths for each function index. -/ +abbrev FunctionArities := Nat → Nat × Nat + +def functionMessage (request : Bytecode.AIR.Call) : List G := + 0 :: G.ofNat request.function :: + (request.inputs.toList ++ request.outputs.toList ++ [request.rank]) + +def memoryMessage (width : Nat) (pointer : G) (contents : Array G) : List G := + 1 :: G.ofNat width :: pointer :: contents.toList + +def Byte1Kind.outputSize : Byte1Kind → Nat + | .bits => 8 + | .shiftLeft | .shiftRight => 1 + +def Byte2Kind.outputSize : Byte2Kind → Nat + | .range => 0 + | .mul | .split7 | .split4 => 2 + | _ => 1 + +/-- Length of a native message, determined by its channel and second field. +Function messages include the final call-order rank. -/ +def lookupMessageWidth (arities : FunctionArities) (channel key : G) : Nat := + match channel.n with + | 0 => 3 + (arities key.n).1 + (arities key.n).2 + | 1 => 3 + key.n + | 2 => 10 + | 3 | 4 => 3 + | 5 | 6 | 7 | 8 | 9 | 10 => 4 + | 11 => 3 + | 12 | 13 | 14 => 5 + | _ => 0 + +def FunctionMessageValid (arities : FunctionArities) (request : Bytecode.AIR.Call) : Prop := + request.function < gSize.toNat ∧ + request.inputs.size = (arities request.function).1 ∧ + request.outputs.size = (arities request.function).2 + +theorem functionMessage_shape (arities : FunctionArities) (request : Bytecode.AIR.Call) + (valid : FunctionMessageValid arities request) : + HasMessageShape (lookupMessageWidth arities) (functionMessage request) := by + obtain ⟨indexBound, inputs, outputs⟩ := valid + simp only [HasMessageShape, functionMessage, List.length_cons, List.length_append, + List.length_nil, Array.length_toList, List.getElem?_cons_zero, + List.getElem?_cons_succ, Option.getD_some, lookupMessageWidth, G.n_ofNat, + Nat.mod_eq_of_lt indexBound] + change _ ∧ _ = 3 + (arities request.function).1 + (arities request.function).2 + omega + +theorem memoryMessage_shape (arities : FunctionArities) (width : Nat) + (pointer : G) (contents : Array G) (bounded : width < gSize.toNat) + (sized : contents.size = width) : + HasMessageShape (lookupMessageWidth arities) (memoryMessage width pointer contents) := by + simp only [HasMessageShape, memoryMessage, List.length_cons, Array.length_toList, + List.getElem?_cons_zero, List.getElem?_cons_succ, Option.getD_some, + lookupMessageWidth, G.n_ofNat, Nat.mod_eq_of_lt bounded] + change _ ∧ _ = 3 + width + omega + +theorem byte1Request_shape (arities : FunctionArities) (kind : Byte1Kind) (input : G) + (outputs : Array G) (sized : outputs.size = kind.outputSize) : + HasMessageShape (lookupMessageWidth arities) (byte1Request kind input outputs) := by + cases kind <;> + simp only [Byte1Kind.outputSize] at sized <;> + simp only [HasMessageShape, byte1Request, List.length_cons, Array.length_toList, + List.getElem?_cons_zero, List.getElem?_cons_succ, Option.getD_some, + lookupMessageWidth, Byte1Kind.channel, sized] <;> exact ⟨by decide +kernel, rfl⟩ + +theorem byte2Request_shape (arities : FunctionArities) (kind : Byte2Kind) (x y : G) + (outputs : Array G) (sized : outputs.size = kind.outputSize) : + HasMessageShape (lookupMessageWidth arities) (byte2Request kind x y outputs) := by + cases kind <;> + simp only [Byte2Kind.outputSize] at sized <;> + simp only [HasMessageShape, byte2Request, List.length_cons, Array.length_toList, + List.getElem?_cons_zero, List.getElem?_cons_succ, Option.getD_some, + lookupMessageWidth, Byte2Kind.channel, sized] <;> exact ⟨by decide +kernel, rfl⟩ + +theorem byte1Outputs_size (kind : Byte1Kind) (row : Fin 256) : + (byte1Outputs kind row).size = kind.outputSize := by + cases kind <;> simp only [byte1Outputs, Byte1Kind.outputSize, Array.size_ofFn, + List.size_toArray, List.length_cons, List.length_nil] + +theorem byte2Outputs_size (kind : Byte2Kind) (row : Fin 65536) : + (byte2Outputs kind row).size = kind.outputSize := by + cases kind <;> simp only [byte2Outputs, Byte2Kind.outputSize, + List.size_toArray, List.length_cons, List.length_nil] + +theorem functionMessage_injective {arities : FunctionArities} + {left right : Bytecode.AIR.Call} + (validLeft : FunctionMessageValid arities left) + (validRight : FunctionMessageValid arities right) + (same : functionMessage left = functionMessage right) : left = right := by + obtain ⟨lf, li, lo, lr⟩ := left + obtain ⟨rf, ri, ro, rr⟩ := right + obtain ⟨lb, lis, los⟩ := validLeft + obtain ⟨rb, ris, ros⟩ := validRight + obtain ⟨index, values⟩ := List.cons.inj (List.cons.inj same).2 + have index := G.ofNat_injective_below lb rb index + change lf = rf at index + subst rf + have inputSize : li.toList.length = ri.toList.length := by + simp only [Array.length_toList] + exact lis.trans ris.symm + change (li.toList ++ lo.toList) ++ [lr] = (ri.toList ++ ro.toList) ++ [rr] at values + obtain ⟨data, rank⟩ := List.append_inj' values rfl + obtain ⟨input, output⟩ := List.append_inj data inputSize + have input := Array.toList_inj.mp input + have output := Array.toList_inj.mp output + have rank := (List.cons.inj rank).1 + subst ri + subst ro + subst rr + rfl + +theorem exactLookupBalance_functionMessages (arities : FunctionArities) + {queries : List Bytecode.AIR.Call} {providers : List (Provider Bytecode.AIR.Call)} + (queryShapes : ∀ query ∈ queries, FunctionMessageValid arities query) + (providerShapes : ∀ provider ∈ providers, provider.2 ≠ 0 → + FunctionMessageValid arities provider.1) + (balanced : ExactLookupBalance (queries.map functionMessage) (mapProviders functionMessage providers)) : + ExactLookupBalance queries providers := + exactLookupBalance_of_injective_on functionMessage (FunctionMessageValid arities) + (fun left right same => functionMessage_injective left right same) + queryShapes providerShapes balanced + +theorem memoryMessage_injective {width : Nat} {left right : G × Array G} + (same : memoryMessage width left.1 left.2 = memoryMessage width right.1 right.2) : + left = right := by + obtain ⟨pointer, contents⟩ := List.cons.inj (List.cons.inj (List.cons.inj same).2).2 + exact Prod.ext pointer (Array.toList_inj.mp contents) + +theorem exactLookupBalance_memoryMessages (width : Nat) + {queries : List (G × Array G)} {providers : List (Provider (G × Array G))} + (balanced : ExactLookupBalance (queries.map fun request => memoryMessage width request.1 request.2) + (mapProviders (fun request => memoryMessage width request.1 request.2) providers)) : + ExactLookupBalance queries providers := + exactLookupBalance_of_injective_on (fun request => memoryMessage width request.1 request.2) + (fun _ => True) (fun _ _ same => memoryMessage_injective same) + (fun _ _ => True.intro) (fun _ _ _ => True.intro) balanced + +/-- Root messages omit the final rank field; appending its fixed zero does +not change any padded lookup message. -/ +theorem padMessage_append_zero {width : Nat} (message : List G) : + padMessage width (message ++ [0]) = padMessage width message := by + apply congrArg List.ofFn + funext i + by_cases inside : i.val < message.length + · simp only [List.getElem?_append_left inside] + · rw [List.getElem?_append_right (by omega)] + have outside : message[i.val]? = none := List.getElem?_eq_none (by omega) + rw [outside, Option.getD_none] + by_cases last : i.val = message.length + · simp only [last, Nat.sub_self, List.getElem?_cons_zero, Option.getD_some] + · rw [List.getElem?_eq_none (by simp only [List.length_cons, List.length_nil]; omega)] + rfl + +/-- Without an output-arity check, the last output of one request can be +the rank of a shorter return. This holds at every padding width. -/ +theorem functionMessage_rank_alias (width : Nat) : + let output : Bytecode.AIR.Call := ⟨0, #[], #[7], 0⟩ + let rank : Bytecode.AIR.Call := ⟨0, #[], #[], 7⟩ + output ≠ rank ∧ padMessage width (functionMessage output) = + padMessage width (functionMessage rank) := by + constructor + · decide +kernel + · change padMessage width ([0, 0, 7] ++ [0]) = padMessage width [0, 0, 7] + exact padMessage_append_zero _ + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/LookupShapes.lean b/Ix/Aiur/Proofs/LookupShapes.lean new file mode 100644 index 000000000..c54900191 --- /dev/null +++ b/Ix/Aiur/Proofs/LookupShapes.lean @@ -0,0 +1,264 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.LookupShapes +import Ix.Aiur.Semantics.AIR +import Ix.Aiur.BoundVerifier +import Ix.Aiur.Proofs.CallOrder + +/-! A checked return-arity validator implies the output size of every AIR +execution, including early returns and match continuations. -/ + +namespace Aiur.Bytecode + +theorem returnsHaveSize_match (size : Nat) (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) : + (Ctrl.match index branches fallback).returnsHaveSize size = true ↔ + (∀ pair ∈ branches.toList, pair.2.returnsHaveSize size = true) ∧ + (∀ block, fallback = some block → block.returnsHaveSize size = true) := by + rw [Ctrl.returnsHaveSize.eq_def] + simp only [Bool.and_eq_true, Array.all_eq_true', + Array.mem_attach, forall_const, Subtype.forall] + cases fallback <;> simp + +theorem returnsHaveSize_matchContinue (size : Nat) (index : ValIdx) + (branches : Array (G × Block)) (fallback : Option Block) + (outputs aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).returnsHaveSize size = true ↔ + (∀ pair ∈ branches.toList, pair.2.returnsHaveSize size = true) ∧ + (∀ block, fallback = some block → block.returnsHaveSize size = true) ∧ + continuation.returnsHaveSize size = true := by + rw [Ctrl.returnsHaveSize.eq_def] + simp only [Bool.and_eq_true, Array.all_eq_true', + Array.mem_attach, forall_const, Subtype.forall] + cases fallback <;> simp + +namespace AIR + +/-- A function query uses the input and return boundaries of its selected +callee. Returnless functions satisfy the last check vacuously; they still +need a finite execution before they can provide a return. -/ +def Call.LookupShape (program : Toplevel) (request : Call) : Prop := + ∃ callee, program.functions[request.function]? = some callee ∧ + callee.constrained = true ∧ callee.layout.inputSize = request.inputs.size ∧ + callee.body.returnsHaveSize request.outputs.size = true + +theorem list_mapM_some_length (f : α → Option β) (inputs : List α) (outputs : List β) + (result : inputs.mapM f = some outputs) : outputs.length = inputs.length := by + induction inputs generalizing outputs with + | nil => simp only [List.mapM_nil, pure, Option.some.injEq] at result + subst outputs; rfl + | cons input inputs ih => + simp only [List.mapM_cons, bind, Option.bind, pure] at result + cases head : f input with + | none => simp only [head, reduceCtorEq] at result + | some output => + cases tail : inputs.mapM f with + | none => simp only [head, tail, reduceCtorEq] at result + | some rest => + simp only [head, tail, Option.some.injEq] at result + subst outputs + simp only [List.length_cons, ih rest tail] + +theorem readValues_size {values : Array G} {indices : Array ValIdx} {outputs : Array G} + (read : readValues values indices = some outputs) : outputs.size = indices.size := by + have listResult := congrArg (Functor.map Array.toList) read + rw [readValues, Array.toList_mapM] at listResult + have sizes := list_mapM_some_length (fun index => values[index]?) indices.toList outputs.toList listResult + simpa only [Array.length_toList] using sizes + +theorem SelectArm.returnsHaveSize {scrutinee : G} {branches : Array (G × Block)} + {fallback : Option Block} {arm : Block} (selected : SelectArm scrutinee branches fallback arm) + (size : Nat) (casesValid : ∀ pair ∈ branches.toList, pair.2.returnsHaveSize size = true) + (fallbackValid : ∀ block, fallback = some block → block.returnsHaveSize size = true) : + arm.returnsHaveSize size = true := by + cases selected with + | case member => exact casesValid _ member + | fallback present unmatched => exact fallbackValid _ present + +def Outcome.ReturnSize (outcome : Outcome) (size : Nat) : Prop := + match outcome with + | .returned outputs => outputs.size = size + | .yielded _ => True + +theorem RunBlock.return_size {memory : Memory} {block : Block} {values : Array G} + {outcome : Outcome} {calls : List Call} (execution : RunBlock memory block values outcome calls) + (size : Nat) (valid : block.returnsHaveSize size = true) : outcome.ReturnSize size := by + revert valid + induction execution using RunBlock.rec + (motive_2 := fun ctrl _ outcome _ _ => ctrl.returnsHaveSize size = true → outcome.ReturnSize size) with + | block operations control ih => + intro valid + apply ih + simpa only [Block.returnsHaveSize] using valid + | returned result valid => + rw [Ctrl.returnsHaveSize] at valid + have sized : _ = size := beq_iff_eq.mp valid + exact (readValues_size result).trans sized + | yielded result valid => exact True.intro + | «match» value selected branch ih valid => + obtain ⟨casesValid, fallbackValid⟩ := (returnsHaveSize_match _ _ _ _).mp valid + exact ih (selected.returnsHaveSize size casesValid fallbackValid) + | matchContinueReturn value selected branch ih valid => + obtain ⟨casesValid, fallbackValid, _⟩ := (returnsHaveSize_matchContinue _ _ _ _ _ _ _ _).mp valid + exact ih (selected.returnsHaveSize size casesValid fallbackValid) + | matchContinueYield value selected branch outputSize continued ihBranch ihCont valid => + obtain ⟨_, _, contValid⟩ := (returnsHaveSize_matchContinue _ _ _ _ _ _ _ _).mp valid + exact ihCont contValid + +theorem RunFunction.return_size {program : Toplevel} {memory : Memory} + {request : Call} {calls : List Call} (execution : RunFunction program memory request calls) + {callee : Function} (present : program.functions[request.function]? = some callee) + (size : Nat) (valid : callee.body.returnsHaveSize size = true) : request.outputs.size = size := by + cases execution with + | function selected arity body => + have same := Option.some.inj (selected.symm.trans present) + subst callee + exact body.return_size size valid + +theorem Step.calls_lookupShape {program : Toplevel} {memory : Memory} {op : Op} + {values outputs : Array G} {calls : List Call} (execution : Step memory op values outputs calls) + (valid : op.lookupShape program = true) : ∀ request ∈ calls, request.LookupShape program := by + intro request member + cases execution with + | primitive evaluated => cases member + | call arguments outputSize => + have same := List.mem_singleton.mp member + subst request + simp only [Op.lookupShape] at valid + split at valid + · cases valid + · rename_i callee present + obtain ⟨constrained, inputSize, returnSize⟩ := + (show _ ∧ _ ∧ _ from by simpa only [Bool.and_eq_true, beq_iff_eq] using valid) + refine ⟨callee, present, constrained, ?_, ?_⟩ + · exact inputSize.trans (readValues_size arguments).symm + · simpa only [outputSize] using returnSize + | store arguments stored => cases member + | load address width loaded => cases member + +theorem RunOps.calls_lookupShape {program : Toplevel} {memory : Memory} {ops : List Op} + {values outputs : Array G} {calls : List Call} (execution : RunOps memory ops values outputs calls) + (valid : ∀ op ∈ ops, op.lookupShape program = true) : + ∀ request ∈ calls, request.LookupShape program := by + induction execution with + | nil => intro request member; cases member + | @cons op ops values intermediate firstCalls finalValues restCalls first rest ih => + intro request member + rcases List.mem_append.mp member with firstMember | restMember + · exact first.calls_lookupShape (valid op List.mem_cons_self) request firstMember + · exact ih (fun op member => valid op (List.mem_cons_of_mem _ member)) request restMember + +end AIR + +theorem lookupShapes_match (program : Toplevel) (yieldSize : Option Nat) + (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).lookupShapes program yieldSize = true ↔ + (∀ pair ∈ branches.toList, pair.2.lookupShapes program yieldSize = true) ∧ + (∀ block, fallback = some block → block.lookupShapes program yieldSize = true) := by + rw [Ctrl.lookupShapes.eq_def] + simp only [Bool.and_eq_true, Array.all_eq_true', + Array.mem_attach, forall_const, Subtype.forall] + cases fallback <;> simp + +theorem lookupShapes_matchContinue (program : Toplevel) (yieldSize : Option Nat) + (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) + (outputs aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).lookupShapes program yieldSize = true ↔ + (∀ pair ∈ branches.toList, pair.2.lookupShapes program (some outputs) = true) ∧ + (∀ block, fallback = some block → block.lookupShapes program (some outputs) = true) ∧ + continuation.lookupShapes program yieldSize = true := by + rw [Ctrl.lookupShapes.eq_def] + simp only [Bool.and_eq_true, Array.all_eq_true', + Array.mem_attach, forall_const, Subtype.forall] + cases fallback <;> simp + +namespace AIR + +theorem SelectArm.lookupShapes {scrutinee : G} {branches : Array (G × Block)} + {fallback : Option Block} {arm : Block} (selected : SelectArm scrutinee branches fallback arm) + (program : Toplevel) (yieldSize : Option Nat) + (casesValid : ∀ pair ∈ branches.toList, pair.2.lookupShapes program yieldSize = true) + (fallbackValid : ∀ block, fallback = some block → block.lookupShapes program yieldSize = true) : + arm.lookupShapes program yieldSize = true := by + cases selected with + | case member => exact casesValid _ member + | fallback present unmatched => exact fallbackValid _ present + +theorem RunBlock.calls_lookupShape {program : Toplevel} {memory : Memory} {block : Block} + {values : Array G} {outcome : Outcome} {calls : List Call} + (execution : RunBlock memory block values outcome calls) + (yieldSize : Option Nat) (valid : block.lookupShapes program yieldSize = true) : + ∀ request ∈ calls, request.LookupShape program := by + revert yieldSize valid + induction execution using RunBlock.rec + (motive_2 := fun ctrl _ _ calls _ => ∀ yieldSize, + ctrl.lookupShapes program yieldSize = true → + ∀ request ∈ calls, request.LookupShape program) with + | block operations control ih => + intro yieldSize valid request member + obtain ⟨opsValid, ctrlValid⟩ := (show _ ∧ _ from by + simpa only [Block.lookupShapes, Bool.and_eq_true] using valid) + rcases List.mem_append.mp member with first | last + · apply operations.calls_lookupShape _ request first + simpa only [Array.all_eq_true', Array.mem_def] using opsValid + · exact ih yieldSize ctrlValid request last + | returned result yieldSize valid request member => cases member + | yielded result yieldSize valid request member => cases member + | «match» value selected branch ih yieldSize valid request member => + obtain ⟨casesValid, fallbackValid⟩ := (lookupShapes_match _ _ _ _ _).mp valid + exact ih yieldSize (selected.lookupShapes program yieldSize casesValid fallbackValid) request member + | matchContinueReturn value selected branch ih yieldSize valid request member => + obtain ⟨casesValid, fallbackValid, _⟩ := (lookupShapes_matchContinue _ _ _ _ _ _ _ _ _).mp valid + exact ih _ (selected.lookupShapes program _ casesValid fallbackValid) request member + | matchContinueYield value selected branch outputSize continued ihBranch ihCont yieldSize valid request member => + obtain ⟨casesValid, fallbackValid, contValid⟩ := (lookupShapes_matchContinue _ _ _ _ _ _ _ _ _).mp valid + rcases List.mem_append.mp member with first | last + · exact ihBranch _ (selected.lookupShapes program _ casesValid fallbackValid) request first + · exact ihCont yieldSize contValid request last + +theorem RunFunction.calls_lookupShape {program : Toplevel} {memory : Memory} + {request : Call} {calls : List Call} (execution : RunFunction program memory request calls) + (valid : program.validateLookupShapes = true) + {callee : Function} (present : program.functions[request.function]? = some callee) + (constrained : callee.constrained = true) : + ∀ child ∈ calls, child.LookupShape program := by + simp only [Toplevel.validateLookupShapes, Bool.and_eq_true] at valid + have functionsValid := valid.2.2 + have member : callee ∈ program.functions := Array.mem_of_getElem? present + have bodyValid := Array.all_eq_true'.mp functionsValid callee member + simp only [constrained, Bool.not_true, Bool.false_or] at bodyValid + cases execution with + | function selected arity body => + have same := Option.some.inj (selected.symm.trans present) + subst callee + exact body.calls_lookupShape none bodyValid + +end AIR +end Aiur.Bytecode + +namespace Aiur.BoundVerifier + +theorem Backend.air_return_size {selection : Selection} (backend : Backend selection) + {memory : Bytecode.AIR.Memory} {request : Bytecode.AIR.Call} + {calls : List Bytecode.AIR.Call} + (execution : Bytecode.AIR.RunFunction backend.compiled.bytecode memory request calls) + (selected : request.function = selection.function) : + request.outputs.size = selection.success.size := by + apply execution.return_size (callee := backend.entry) _ _ backend.returnArity + simpa only [selected] using backend.present + +theorem Backend.claim_shape {selection : Selection} (backend : Backend selection) + (input : Array G) (arity : input.size = selection.inputSize) : + backend.compiled.bytecode.validClaimShape + (buildClaim selection.function input selection.success) = true := by + simp only [Bytecode.Toplevel.validClaimShape, buildClaim, Array.toList_append, + List.cons_append, List.nil_append, G.n_ofNat, + Nat.mod_eq_of_lt backend.functionRange, backend.present, backend.publicEntry, + backend.constrained, functionChannel, Bool.true_and, Bool.and_true, List.length_append, + Array.length_toList, backend.arity, arity, Nat.add_sub_cancel_left, backend.returnArity] + exact decide_eq_true (by omega) + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/Memory.lean b/Ix/Aiur/Proofs/Memory.lean new file mode 100644 index 000000000..369fdc836 --- /dev/null +++ b/Ix/Aiur/Proofs/Memory.lean @@ -0,0 +1,236 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Semantics.AIR +import Ix.Aiur.Proofs.Lookup + +/-! +Immutable memory facts from incrementing memory tables and exact balance. + +The native memory AIR has no first-pointer-zero constraint. Active rows form +a prefix and their pointers increment in the field; an arbitrary initial +pointer and wraparound are permitted. A trace-height bound below the field +characteristic suffices to make these pointers distinct. A separate bound +on query counts prevents modular cancellation in the lookup argument. + +The local polynomial and exact-message interfaces below still require +extraction from the native proof system. Contents need not be injectively +stored, acyclic, or created by earlier runtime operations. These theorems +establish functionality at a fixed width and pointer, not refinement to the +reference evaluator's insertion-order memory. +-/ + +namespace Aiur + +theorem G.ext_n {a b : G} (equal : a.n = b.n) : a = b := + Subtype.ext (UInt64.toNat_inj.mp equal) + +theorem G.add_zero (a : G) : a + 0 = a := by + change G.ofNat (a.n + 0) = a + simpa only [Nat.add_zero] using G.ofNat_n a + +theorem G.ofNat_add (a b : Nat) : G.ofNat (a + b) = G.ofNat a + G.ofNat b := by + apply G.ext_n + simp only [G.n_ofNat, G.n_add, Nat.add_mod, Nat.mod_mod] + +theorem G.add_assoc (a b c : G) : (a + b) + c = a + (b + c) := by + apply G.ext_n + simp only [G.n_add, Nat.mod_add_mod, Nat.add_mod_mod, Nat.add_assoc] + +theorem G.add_left_cancel (a : G) {b c : G} (equal : a + b = a + c) : b = c := by + have ha : a.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp a.property + have hb : b.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp b.property + have hc : c.n < gSize.toNat := UInt64.lt_iff_toNat_lt.mp c.property + have equal := congrArg G.n equal + simp only [G.n_add] at equal + apply G.ext_n + have modulus : gSize.toNat = 18446744069414584321 := by decide + rw [modulus] at ha hb hc equal + omega + +theorem G.ofNat_injective_below {a b : Nat} (ha : a < gSize.toNat) + (hb : b < gSize.toNat) (equal : G.ofNat a = G.ofNat b) : a = b := by + have equal := congrArg G.n equal + simpa only [G.n_ofNat, Nat.mod_eq_of_lt ha, Nat.mod_eq_of_lt hb] using equal + +namespace AIR + +/-- Columns of a memory row; the table fixes the contents width. -/ +structure MemoryRow where + selector : G + multiplicity : G + pointer : G + contents : Array G + +/-- Interior transition polynomial: an active successor requires an active row. -/ +def memoryActivityTransition (row next : MemoryRow) : G := + next.selector * (row.selector - 1) + +/-- Interior transition polynomial for the incrementing pointer column. -/ +def memoryPointerTransition (row next : MemoryRow) : G := + next.selector * (row.pointer + 1 - next.pointer) + +/-- Local memory constraints after decoding boolean selectors. The last row +has no successor constraint, matching the native transition selector. -/ +structure MemoryRowsValid (width : Nat) (rows : Array MemoryRow) : Prop where + selectors : ∀ i (hi : i < rows.size), rows[i].selector = 0 ∨ rows[i].selector = 1 + activity : ∀ i (hi : i < rows.size), activityConstraint rows[i].multiplicity rows[i].selector = 0 + widths : ∀ i (hi : i < rows.size), rows[i].contents.size = width + activityTransition : ∀ i (hi : i + 1 < rows.size), + memoryActivityTransition (rows[i]'(by omega)) rows[i + 1] = 0 + pointerTransition : ∀ i (hi : i + 1 < rows.size), + memoryPointerTransition (rows[i]'(by omega)) rows[i + 1] = 0 + +theorem MemoryRowsValid.previous_active {width : Nat} {rows : Array MemoryRow} + (valid : MemoryRowsValid width rows) (i : Nat) (hi : i + 1 < rows.size) + (active : rows[i + 1].selector = 1) : (rows[i]'(by omega)).selector = 1 := by + have satisfied := valid.activityTransition i hi + unfold memoryActivityTransition at satisfied + rw [active, G.mul_comm, G.mul_one] at satisfied + exact (G.sub_eq_zero_iff (rows[i]'(by omega)).selector 1).mp satisfied + +theorem MemoryRowsValid.next_pointer {width : Nat} {rows : Array MemoryRow} + (valid : MemoryRowsValid width rows) (i : Nat) (hi : i + 1 < rows.size) + (active : rows[i + 1].selector = 1) : + rows[i + 1].pointer = (rows[i]'(by omega)).pointer + 1 := by + have satisfied := valid.pointerTransition i hi + unfold memoryPointerTransition at satisfied + rw [active, G.mul_comm, G.mul_one] at satisfied + exact ((G.sub_eq_zero_iff ((rows[i]'(by omega)).pointer + 1) rows[i + 1].pointer).mp satisfied).symm + +theorem MemoryRowsValid.pointer_eq_first_add {width : Nat} {rows : Array MemoryRow} + (valid : MemoryRowsValid width rows) (i : Nat) (hi : i < rows.size) + (active : rows[i].selector = 1) : + rows[i].pointer = (rows[0]'(by omega)).pointer + G.ofNat i := by + induction i with + | zero => simp only [show G.ofNat 0 = (0 : G) from rfl, G.add_zero] + | succ i ih => + rw [valid.next_pointer i hi active] + rw [ih (by omega) (valid.previous_active i hi active), G.ofNat_add, G.add_assoc] + rfl + +theorem MemoryRowsValid.pointer_injective {width : Nat} {rows : Array MemoryRow} + (valid : MemoryRowsValid width rows) (bounded : rows.size < gSize.toNat) + (i j : Nat) (hi : i < rows.size) (hj : j < rows.size) + (activeI : rows[i].selector = 1) (activeJ : rows[j].selector = 1) + (same : rows[i].pointer = rows[j].pointer) : i = j := by + rw [valid.pointer_eq_first_add i hi activeI, valid.pointer_eq_first_add j hj activeJ] at same + exact G.ofNat_injective_below (by omega) (by omega) (G.add_left_cancel _ same) + +def memoryFacts (tables : Nat → Array MemoryRow) : Bytecode.AIR.Memory := + fun width pointer contents => ∃ i : Nat, ∃ hi : i < (tables width).size, + (tables width)[i].selector = 1 ∧ (tables width)[i].pointer = pointer ∧ + (tables width)[i].contents = contents + +theorem memoryFacts_functional (tables : Nat → Array MemoryRow) + (valid : ∀ width, MemoryRowsValid width (tables width)) + (bounded : ∀ width, (tables width).size < gSize.toNat) + {width : Nat} {pointer : G} {left right : Array G} + (loadedLeft : memoryFacts tables width pointer left) + (loadedRight : memoryFacts tables width pointer right) : left = right := by + obtain ⟨i, hi, ai, pi, vi⟩ := loadedLeft + obtain ⟨j, hj, aj, pj, vj⟩ := loadedRight + have same := (valid width).pointer_injective (bounded width) i j hi hj ai aj (pi.trans pj.symm) + subst j + exact vi.symm.trans vj + +/-- Providers for one fixed-width memory table, in native row order. -/ +def memoryProviders (rows : Array MemoryRow) : List (Provider (G × Array G)) := + List.ofFn fun i : Fin rows.size => + ((rows[i].pointer, rows[i].contents), rows[i].multiplicity) + +theorem memoryQueries_provider {width : Nat} {rows : Array MemoryRow} + (valid : MemoryRowsValid width rows) {queries : List (G × Array G)} + (balanced : ExactLookupBalance queries (memoryProviders rows)) + (bounded : queries.length < gSize.toNat) + {pointer : G} {contents : Array G} (queried : (pointer, contents) ∈ queries) : + ∃ i : Nat, ∃ hi : i < rows.size, + rows[i].selector = 1 ∧ rows[i].pointer = pointer ∧ rows[i].contents = contents := by + obtain ⟨provider, member, same, nonzero⟩ := exactLookupBalance_provider balanced bounded queried + obtain ⟨i, provided⟩ := List.mem_ofFn.mp member + subst provider + have active : rows[i].selector = 1 := by + rcases valid.selectors i i.isLt with inactive | active + · exact False.elim (nonzero (inactive_multiplicity_zero inactive (valid.activity i i.isLt))) + · exact active + exact ⟨i, i.isLt, active, congrArg Prod.fst same, congrArg Prod.snd same⟩ + +theorem memoryQueries_width {width : Nat} {rows : Array MemoryRow} + (valid : MemoryRowsValid width rows) {queries : List (G × Array G)} + (balanced : ExactLookupBalance queries (memoryProviders rows)) + (bounded : queries.length < gSize.toNat) + {pointer : G} {contents : Array G} (queried : (pointer, contents) ∈ queries) : + contents.size = width := by + obtain ⟨i, hi, _, _, same⟩ := memoryQueries_provider valid balanced bounded queried + rw [← same] + exact valid.widths i hi + +/-- Two balanced requests for the same width and pointer have equal data. +The trace-height bound prevents a pointer from recurring after a full field +cycle; the query-count bound separately prevents requests cancelling out. -/ +theorem memoryQueries_consistent {width : Nat} {rows : Array MemoryRow} + (valid : MemoryRowsValid width rows) (heightBound : rows.size < gSize.toNat) + {queries : List (G × Array G)} + (balanced : ExactLookupBalance queries (memoryProviders rows)) + (queryBound : queries.length < gSize.toNat) + {pointer : G} {left right : Array G} + (queriedLeft : (pointer, left) ∈ queries) + (queriedRight : (pointer, right) ∈ queries) : left = right := by + obtain ⟨i, hi, ai, pi, vi⟩ := memoryQueries_provider valid balanced queryBound queriedLeft + obtain ⟨j, hj, aj, pj, vj⟩ := memoryQueries_provider valid balanced queryBound queriedRight + have same := valid.pointer_injective heightBound i j hi hj ai aj (pi.trans pj.symm) + subst j + exact vi.symm.trans vj + +theorem memoryQueries_fact (tables : Nat → Array MemoryRow) + (valid : ∀ width, MemoryRowsValid width (tables width)) + (queries : Nat → List (G × Array G)) + (balanced : ∀ width, ExactLookupBalance (queries width) (memoryProviders (tables width))) + (bounded : ∀ width, (queries width).length < gSize.toNat) + {width : Nat} {pointer : G} {contents : Array G} + (queried : (pointer, contents) ∈ queries width) : + memoryFacts tables width pointer contents := + memoryQueries_provider (valid width) (balanced width) (bounded width) queried + +/-- A size-parameterized table used symbolically at `period = p`. Keeping +the size as an argument avoids a native initializer allocating `p + 1` rows +when this proof module is imported. -/ +def memoryPointerCycle (period : Nat) : Array MemoryRow := + Array.ofFn fun i : Fin (period + 1) => + ⟨1, 0, G.ofNat i.val, #[G.ofNat (i.val / period)]⟩ + +theorem memoryPointerCycle_valid : MemoryRowsValid 1 (memoryPointerCycle gSize.toNat) := by + constructor + · intro i hi + right + simp only [memoryPointerCycle, Array.getElem_ofFn] + · intro i hi + simp only [memoryPointerCycle, Array.getElem_ofFn] + exact active_satisfies 0 + · intro i hi + simp only [memoryPointerCycle, Array.getElem_ofFn, List.size_toArray, List.length_cons, + List.length_nil] + · intro i hi + simp only [memoryActivityTransition, memoryPointerCycle, Array.getElem_ofFn] + have same : (1 : G) - 1 = 0 := (G.sub_eq_zero_iff _ _).mpr rfl + rw [same, G.mul_zero] + · intro i hi + simp only [memoryPointerTransition, memoryPointerCycle, Array.getElem_ofFn] + have same : G.ofNat i + 1 = G.ofNat (i + 1) := (G.ofNat_add i 1).symm + rw [same, (G.sub_eq_zero_iff _ _).mpr rfl, G.mul_zero] + +theorem memoryPointerCycle_inconsistent : + ∃ i j : Fin (memoryPointerCycle gSize.toNat).size, + (memoryPointerCycle gSize.toNat)[i].selector = 1 ∧ (memoryPointerCycle gSize.toNat)[j].selector = 1 ∧ + (memoryPointerCycle gSize.toNat)[i].pointer = (memoryPointerCycle gSize.toNat)[j].pointer ∧ + (memoryPointerCycle gSize.toNat)[i].contents ≠ (memoryPointerCycle gSize.toNat)[j].contents := by + have size : (memoryPointerCycle gSize.toNat).size = gSize.toNat + 1 := by + simp only [memoryPointerCycle, Array.size_ofFn] + refine ⟨⟨0, by rw [size]; omega⟩, ⟨gSize.toNat, by rw [size]; omega⟩, ?_⟩ + simp only [Fin.getElem_fin, memoryPointerCycle, Array.getElem_ofFn] + decide + +end AIR +end Aiur diff --git a/Ix/Aiur/Proofs/MemoryColumns.lean b/Ix/Aiur/Proofs/MemoryColumns.lean new file mode 100644 index 000000000..977007a85 --- /dev/null +++ b/Ix/Aiur/Proofs/MemoryColumns.lean @@ -0,0 +1,463 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LookupLayout + +/-! +Decode the native memory column layout and its four valued equations. +Satisfied canonical traces supply valid memory rows and the same weighted +lookup providers; the checked global trace budget gives functional memory. +Compilation supplies distinct canonical memory widths. This removes separate +memory-validity and width hypotheses from backend trace execution. Extraction +from the native verifier, compiler refinement and certified semantic and +cryptographic soundness remain separate obligations. +-/ + +namespace Aiur.AIR + +abbrev MemoryColumns (width : Nat) := Fin (3 + width) → G + +def decodeMemoryRow (width : Nat) (columns : MemoryColumns width) : MemoryRow := + ⟨columns ⟨1, by omega⟩, columns ⟨0, by omega⟩, columns ⟨2, by omega⟩, + Array.ofFn fun i : Fin width => columns ⟨3 + i.val, by omega⟩⟩ + +def memoryColumnEquations (width : Nat) (current next : MemoryColumns width) (transition : G) : List G := + let selector := current ⟨1, by omega⟩ + let nextSelector := next ⟨1, by omega⟩ + [selector * (selector - 1), + current ⟨0, by omega⟩ * (1 - selector), + (nextSelector * transition) * (selector - 1), + (nextSelector * transition) * (current ⟨2, by omega⟩ + 1 - next ⟨2, by omega⟩)] + +def memoryColumnLookup (width : Nat) (columns : MemoryColumns width) : G × List G := + (0 - columns ⟨0, by omega⟩, + (memoryMessage width (columns ⟨2, by omega⟩) (decodeMemoryRow width columns).contents).map + fun value => columns ⟨1, by omega⟩ * value) + +def memoryColumnProvider (width : Nat) (columns : MemoryColumns width) : Provider (List G) := + ((memoryColumnLookup width columns).2, columns ⟨0, by omega⟩) + +def memoryNextIndex {height : Nat} (index : Fin height) : Fin height := + if next : index.val + 1 < height then ⟨index.val + 1, next⟩ else ⟨0, by omega⟩ + +def memoryMatrixEquations (width height : Nat) (matrix : Fin height → MemoryColumns width) + (index : Fin height) : List G := + memoryColumnEquations width (matrix index) (matrix (memoryNextIndex index)) + (if index.val + 1 < height then 1 else 0) + +def MemoryMatrixSatisfied (width height : Nat) (matrix : Fin height → MemoryColumns width) : Prop := + ∀ index, ∀ equation ∈ memoryMatrixEquations width height matrix index, equation = 0 + +def decodeMemoryRows (width height : Nat) (matrix : Fin height → MemoryColumns width) : Array MemoryRow := + Array.ofFn fun index => decodeMemoryRow width (matrix index) + +def memoryMatrixProviders (width height : Nat) (matrix : Fin height → MemoryColumns width) : + List (Provider (List G)) := + List.ofFn fun index => memoryColumnProvider width (matrix index) + +theorem decodeMemoryRow_width (width : Nat) (columns : MemoryColumns width) : + (decodeMemoryRow width columns).contents.size = width := by + simp only [decodeMemoryRow, Array.size_ofFn] + +theorem decodeMemoryRows_size (width height : Nat) (matrix : Fin height → MemoryColumns width) : + (decodeMemoryRows width height matrix).size = height := by + simp only [decodeMemoryRows, Array.size_ofFn] + +theorem memoryColumnProvider_reflect (width : Nat) (current next : MemoryColumns width) (transition : G) + (satisfied : ∀ equation ∈ memoryColumnEquations width current next transition, equation = 0) + (messageWidth : Nat) : + Provider.PaddedEq messageWidth (memoryColumnProvider width current) + (memoryMessage width (decodeMemoryRow width current).pointer + (decodeMemoryRow width current).contents, (decodeMemoryRow width current).multiplicity) := by + refine ⟨rfl, ?_⟩ + intro nonzero + have activity : activityConstraint (current ⟨0, by omega⟩) (current ⟨1, by omega⟩) = 0 := + satisfied _ (by simp only [memoryColumnEquations, List.mem_cons]; exact Or.inr (Or.inl rfl)) + have active := nonzero_multiplicity_selector_one activity nonzero + change padMessage messageWidth + ((memoryMessage width (current ⟨2, by omega⟩) (decodeMemoryRow width current).contents).map + fun value => current ⟨1, by omega⟩ * value) = _ + rw [active] + simp only [G.mul_comm (1 : G), G.mul_one] + rw [List.map_id'] + rfl + +theorem decodeMemoryRows_polynomials (width height : Nat) (matrix : Fin height → MemoryColumns width) + (satisfied : MemoryMatrixSatisfied width height matrix) : + MemoryRowsPolynomials width (decodeMemoryRows width height matrix) := by + constructor + · intro i bound + have rowBound : i < height := by simpa only [decodeMemoryRows_size] using bound + have checked := satisfied ⟨i, rowBound⟩ + simp only [decodeMemoryRows, Array.getElem_ofFn, decodeMemoryRow, booleanConstraint] + exact checked _ (by simp [memoryMatrixEquations, memoryColumnEquations]) + · intro i bound + have rowBound : i < height := by simpa only [decodeMemoryRows_size] using bound + have checked := satisfied ⟨i, rowBound⟩ + simp only [decodeMemoryRows, Array.getElem_ofFn, decodeMemoryRow, activityConstraint] + exact checked _ (by simp [memoryMatrixEquations, memoryColumnEquations]) + · intro i bound + simp only [decodeMemoryRows, Array.getElem_ofFn, decodeMemoryRow_width] + · intro i bound + have rowBound : i + 1 < height := by simpa only [decodeMemoryRows_size] using bound + have checked := satisfied ⟨i, by omega⟩ + have equation := checked _ (show ((matrix (memoryNextIndex ⟨i, by omega⟩)) ⟨1, by omega⟩ * + (if i + 1 < height then (1 : G) else 0)) * (matrix ⟨i, by omega⟩ ⟨1, by omega⟩ - 1) ∈ + memoryMatrixEquations width height matrix ⟨i, by omega⟩ from by + simp [memoryMatrixEquations, memoryColumnEquations]) + simpa only [memoryNextIndex, rowBound, if_pos, dif_pos, G.mul_one, + memoryActivityTransition, decodeMemoryRows, Array.getElem_ofFn, decodeMemoryRow] using equation + · intro i bound + have rowBound : i + 1 < height := by simpa only [decodeMemoryRows_size] using bound + have checked := satisfied ⟨i, by omega⟩ + have equation := checked _ (show ((matrix (memoryNextIndex ⟨i, by omega⟩)) ⟨1, by omega⟩ * + (if i + 1 < height then (1 : G) else 0)) * + (matrix ⟨i, by omega⟩ ⟨2, by omega⟩ + 1 - matrix (memoryNextIndex ⟨i, by omega⟩) ⟨2, by omega⟩) ∈ + memoryMatrixEquations width height matrix ⟨i, by omega⟩ from by + simp [memoryMatrixEquations, memoryColumnEquations]) + simpa only [memoryNextIndex, rowBound, if_pos, dif_pos, G.mul_one, + memoryPointerTransition, decodeMemoryRows, Array.getElem_ofFn, decodeMemoryRow] using equation + +theorem decodeMemoryRows_valid (width height : Nat) (matrix : Fin height → MemoryColumns width) + (satisfied : MemoryMatrixSatisfied width height matrix) : + MemoryRowsValid width (decodeMemoryRows width height matrix) := + (decodeMemoryRows_polynomials width height matrix satisfied).valid + +private theorem memory_forall₂_ofFn {α β : Type} {relation : α → β → Prop} + {height : Nat} (left : Fin height → α) (right : Fin height → β) + (related : ∀ index, relation (left index) (right index)) : + List.Forall₂ relation (List.ofFn left) (List.ofFn right) := by + induction height with + | zero => simp only [List.ofFn_zero]; exact .nil + | succ height ih => + rw [List.ofFn_succ, List.ofFn_succ] + exact .cons (related 0) (ih (fun i => left i.succ) (fun i => right i.succ) (fun i => related i.succ)) + +private theorem memoryProviders_toList (rows : Array MemoryRow) : + memoryProviders rows = rows.toList.map (fun row => ((row.pointer, row.contents), row.multiplicity)) := by + have list := congrArg (List.map fun row : MemoryRow => ((row.pointer, row.contents), row.multiplicity)) + (List.ofFn_getElem (xs := rows.toList)) + simpa only [memoryProviders, List.map_ofFn, Function.comp_def, Array.length_toList, + Fin.getElem_fin, Array.getElem_toList] using list + +theorem decodeMemoryRows_providers (width height : Nat) (matrix : Fin height → MemoryColumns width) : + mapProviders (fun request => memoryMessage width request.1 request.2) + (memoryProviders (decodeMemoryRows width height matrix)) = + List.ofFn (fun index => + (memoryMessage width (decodeMemoryRow width (matrix index)).pointer + (decodeMemoryRow width (matrix index)).contents, (decodeMemoryRow width (matrix index)).multiplicity)) := by + rw [memoryProviders_toList] + simp only [mapProviders, decodeMemoryRows, Array.toList_ofFn, + List.map_ofFn, Function.comp_def] + +theorem memoryMatrixProviders_reflect (width height : Nat) (matrix : Fin height → MemoryColumns width) + (satisfied : MemoryMatrixSatisfied width height matrix) (messageWidth : Nat) : + List.Forall₂ (Provider.PaddedEq messageWidth) (memoryMatrixProviders width height matrix) + (mapProviders (fun request => memoryMessage width request.1 request.2) + (memoryProviders (decodeMemoryRows width height matrix))) := by + rw [decodeMemoryRows_providers] + apply memory_forall₂_ofFn + intro index + exact memoryColumnProvider_reflect width (matrix index) (matrix (memoryNextIndex index)) + (if index.val + 1 < height then 1 else 0) (satisfied index) messageWidth + +end Aiur.AIR + +namespace Aiur + +private theorem memorySizes_distinct (sizes : Concrete.Bytecode.MemSizes) : sizes.toArray.toList.Nodup := by + change sizes.toArray.toList.Pairwise (fun a b => a ≠ b) + simpa only [Std.TreeSet.toList_toArray, Std.compare_eq_iff_eq] using sizes.distinct_toList + +theorem Concrete.Decls.toBytecode_memorySizes_distinct {decls : Concrete.Decls} + {program : Bytecode.Toplevel} {names : Std.HashMap Global Bytecode.FunIdx} + (compiled : decls.toBytecode = .ok (program, names)) : program.memorySizes.toList.Nodup := by + unfold Concrete.Decls.toBytecode at compiled + simp only [bind, Except.bind, pure, Except.pure] at compiled + split at compiled + · cases compiled + · split at compiled + · cases compiled + · cases compiled + exact memorySizes_distinct _ + +theorem Bytecode.Toplevel.deduplicate_memorySizes (program : Bytecode.Toplevel) : + program.deduplicate.1.memorySizes = program.memorySizes := by + unfold Bytecode.Toplevel.deduplicate Bytecode.checkedRenaming + dsimp only + split + · unfold Bytecode.Toplevel.deduplicateCandidate + dsimp only + split <;> rfl + · rfl + +theorem finishCompilation_memorySizes (source : Source.Toplevel) (raw : Bytecode.Toplevel) + (names : Std.HashMap Global Bytecode.FunIdx) : + (finishCompilation source raw names).bytecode.memorySizes = raw.memorySizes := by + have preserved (program : Bytecode.Toplevel) : + program.withCallComponents.memorySizes = program.memorySizes := by + unfold Bytecode.Toplevel.withCallComponents + dsimp only + split <;> rfl + cases flag : source.componentRanks <;> + simp [finishCompilation, flag, preserved, raw.deduplicate_memorySizes] + +theorem Source.Toplevel.compile_memorySizes_distinct {source : Source.Toplevel} {compiled : CompiledToplevel} + (accepted : source.compile = .ok compiled) : compiled.bytecode.memorySizes.toList.Nodup := by + obtain ⟨inlined, typed, concrete, raw, names, _, _, _, lowered, artifact⟩ := + source.compile_artifact_of_ok accepted + rw [artifact, finishCompilation_memorySizes] + exact Concrete.Decls.toBytecode_memorySizes_distinct lowered + +theorem BoundVerifier.Backend.memorySizes_distinct {selection : BoundVerifier.Selection} + (backend : BoundVerifier.Backend selection) : backend.compiled.bytecode.memorySizes.toList.Nodup := by + obtain ⟨initial, compiled, grouped⟩ := backend.compilation_stages + have distinct := Source.Toplevel.compile_memorySizes_distinct compiled + split at grouped + · cases grouped; exact distinct + · rw [(CompiledToplevel.groupFunctions_preserves_code grouped).2.2.2] + exact distinct + +theorem BoundVerifier.Backend.memorySizes_canonical {selection : BoundVerifier.Selection} + (backend : BoundVerifier.Backend selection) : + ∀ width ∈ backend.compiled.bytecode.memorySizes.toList, width < gSize.toNat := by + have checked := backend.lookupShapes + simp only [Bytecode.Toplevel.validateLookupShapes, Bool.and_eq_true] at checked + intro width member + have valid := Array.all_eq_true'.mp checked.2.1 width (Array.mem_toList_iff.mp member) + exact of_decide_eq_true valid + +end Aiur + +namespace Aiur.AIR + +inductive MemoryTraces : List Nat → Type where + | nil : MemoryTraces [] + | inactive (width : Nat) {widths : List Nat} (rest : MemoryTraces widths) : MemoryTraces (width :: widths) + | active (width degree : Nat) (matrix : Fin (2^degree) → MemoryColumns width) + {widths : List Nat} (rest : MemoryTraces widths) : MemoryTraces (width :: widths) + +def MemoryTraces.bitmap {widths : List Nat} : MemoryTraces widths → List Bool + | .nil => [] + | .inactive _ rest => false :: rest.bitmap + | .active _ _ _ rest => true :: rest.bitmap + +def MemoryTraces.degrees {widths : List Nat} : MemoryTraces widths → List Nat + | .nil => [] + | .inactive _ rest => rest.degrees + | .active _ degree _ rest => degree :: rest.degrees + +def MemoryTraces.capacity {widths : List Nat} : MemoryTraces widths → Nat + | .nil => 0 + | .inactive _ rest => rest.capacity + | .active _ degree _ rest => 2^degree + rest.capacity + +def MemoryTraces.rows {widths : List Nat} : MemoryTraces widths → Nat → Array MemoryRow + | .nil, _ => #[] + | .inactive width rest, size => if size = width then #[] else rest.rows size + | .active width degree matrix rest, size => + if size = width then decodeMemoryRows width (2^degree) matrix else rest.rows size + +def MemoryTraces.providers {widths : List Nat} : MemoryTraces widths → List (Provider (List G)) + | .nil => [] + | .inactive _ rest => rest.providers + | .active width degree matrix rest => memoryMatrixProviders width (2^degree) matrix ++ rest.providers + +def MemoryTraces.Satisfied {widths : List Nat} : MemoryTraces widths → Prop + | .nil => True + | .inactive _ rest => rest.Satisfied + | .active width degree matrix rest => MemoryMatrixSatisfied width (2^degree) matrix ∧ rest.Satisfied + +theorem MemoryTraces.slot_sum_append {widths : List Nat} (traces : MemoryTraces widths) + (otherSlots : List Nat) (otherActive : List Bool) (otherDegrees : List Nat) : + lookupSlotSum (List.replicate widths.length 1 ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = + (lookupSlotSum otherSlots otherActive otherDegrees).map (traces.capacity + ·) := by + induction traces with + | nil => + simp only [List.length_nil, List.replicate_zero, List.nil_append, bitmap, degrees, capacity, Nat.zero_add] + cases lookupSlotSum otherSlots otherActive otherDegrees <;> rfl + | inactive width rest ih => + simp only [List.length_cons, List.replicate_succ, List.cons_append, bitmap, degrees, capacity, lookupSlotSum] + exact ih + | active width degree matrix rest ih => + simp only [List.length_cons, List.replicate_succ, List.cons_append, bitmap, degrees, capacity, + lookupSlotSum, ih, bind, Option.bind, Nat.mul_one] + cases lookupSlotSum otherSlots otherActive otherDegrees <;> + simp only [Option.map_none, Option.map_some, pure, Nat.add_assoc] + +private theorem memoryRows_empty_valid (width : Nat) : MemoryRowsValid width #[] := by + constructor <;> intro i bound <;> simp at bound + +theorem MemoryTraces.rows_valid {widths : List Nat} (traces : MemoryTraces widths) + (satisfied : traces.Satisfied) (width : Nat) : MemoryRowsValid width (traces.rows width) := by + induction traces with + | nil => exact memoryRows_empty_valid _ + | inactive size rest ih => + simp only [MemoryTraces.rows] + split + · exact memoryRows_empty_valid _ + · exact ih satisfied + | active size degree matrix rest ih => + simp only [MemoryTraces.rows] + split + · rename_i equal + subst width + exact decodeMemoryRows_valid _ _ _ satisfied.1 + · exact ih satisfied.2 + +theorem MemoryTraces.rows_size_le {widths : List Nat} (traces : MemoryTraces widths) (width : Nat) : + (traces.rows width).size ≤ traces.capacity := by + induction traces with + | nil => exact Nat.le_refl _ + | inactive size rest ih => + simp only [MemoryTraces.rows, MemoryTraces.capacity] + split + · exact Nat.zero_le _ + · exact ih + | active size degree matrix rest ih => + simp only [MemoryTraces.rows, MemoryTraces.capacity] + split + · rw [decodeMemoryRows_size]; omega + · exact Nat.le_trans ih (Nat.le_add_left _ _) + +def memoryTableProviders (widths : List Nat) (rows : Nat → Array MemoryRow) : List (Provider (List G)) := + widths.flatMap fun width => mapProviders (fun request => memoryMessage width request.1 request.2) + (memoryProviders (rows width)) + +private theorem memoryTableProviders_cons (width : Nat) (widths : List Nat) (rows : Nat → Array MemoryRow) : + memoryTableProviders (width :: widths) rows = + mapProviders (fun request => memoryMessage width request.1 request.2) (memoryProviders (rows width)) ++ + memoryTableProviders widths rows := rfl + +private theorem memoryTableProviders_congr (widths : List Nat) (left right : Nat → Array MemoryRow) + (equal : ∀ width ∈ widths, left width = right width) : + memoryTableProviders widths left = memoryTableProviders widths right := by + induction widths with + | nil => rfl + | cons width widths ih => + rw [memoryTableProviders_cons, memoryTableProviders_cons, equal width List.mem_cons_self] + rw [ih (fun size member => equal size (List.mem_cons_of_mem _ member))] + +theorem MemoryTraces.providers_reflect {widths : List Nat} (traces : MemoryTraces widths) + (distinct : widths.Nodup) (satisfied : traces.Satisfied) (messageWidth : Nat) : + List.Forall₂ (Provider.PaddedEq messageWidth) traces.providers (memoryTableProviders widths traces.rows) := by + induction traces with + | nil => exact .nil + | @inactive width widths rest ih => + have unique := List.nodup_cons.mp distinct + have tail : memoryTableProviders widths (MemoryTraces.rows (.inactive width rest)) = + memoryTableProviders widths rest.rows := by + apply memoryTableProviders_congr + intro size member + have different : size ≠ width := fun equal => unique.1 (equal ▸ member) + simp only [MemoryTraces.rows, if_neg different] + rw [memoryTableProviders_cons, tail] + have empty : MemoryTraces.rows (.inactive width rest) width = #[] := by simp [MemoryTraces.rows] + rw [empty] + simpa only [memoryProviders, Array.size_empty, List.ofFn_zero, mapProviders, List.map_nil, + List.nil_append, MemoryTraces.providers] using ih unique.2 satisfied + | @active width degree matrix widths rest ih => + have unique := List.nodup_cons.mp distinct + have tail : memoryTableProviders widths (MemoryTraces.rows (.active width degree matrix rest)) = + memoryTableProviders widths rest.rows := by + apply memoryTableProviders_congr + intro size member + have different : size ≠ width := fun equal => unique.1 (equal ▸ member) + simp only [MemoryTraces.rows, if_neg different] + rw [memoryTableProviders_cons, tail] + have first : MemoryTraces.rows (.active width degree matrix rest) width = + decodeMemoryRows width (2^degree) matrix := by simp [MemoryTraces.rows] + rw [first] + exact forall₂_append (memoryMatrixProviders_reflect _ _ _ satisfied.1 messageWidth) + (ih unique.2 satisfied.2) + +theorem MemoryTraces.capacity_bounded {widths : List Nat} (traces : MemoryTraces widths) + {circuits : List Bytecode.Circuit} (functions : CircuitTraces circuits) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (accepted : lookupQueryBound + (circuits.map (·.layout.lookups) ++ (List.replicate widths.length 1 ++ otherSlots)) + (functions.bitmap ++ (traces.bitmap ++ otherActive)) + (functions.degrees ++ (traces.degrees ++ otherDegrees)) = some result) : + traces.capacity + 1 < gSize.toNat := by + obtain ⟨_, total, shape, count, bounded⟩ := lookupQueryBound_sound accepted + rw [functions.slot_sum_append, traces.slot_sum_append] at shape + cases other : lookupSlotSum otherSlots otherActive otherDegrees with + | none => simp only [other, Option.map_none, reduceCtorEq] at shape + | some extra => + simp only [other, Option.map_some, Option.some.injEq] at shape + omega + +theorem MemoryTraces.functional {widths : List Nat} (traces : MemoryTraces widths) + (satisfied : traces.Satisfied) (bounded : traces.capacity < gSize.toNat) + {width : Nat} {pointer : G} {left right : Array G} + (loadedLeft : memoryFacts traces.rows width pointer left) + (loadedRight : memoryFacts traces.rows width pointer right) : left = right := + memoryFacts_functional traces.rows (traces.rows_valid satisfied) + (fun size => Nat.lt_of_le_of_lt (traces.rows_size_le size) bounded) loadedLeft loadedRight + +theorem MemoryTraces.functional_of_budget {widths : List Nat} (traces : MemoryTraces widths) + {circuits : List Bytecode.Circuit} (functions : CircuitTraces circuits) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (accepted : lookupQueryBound + (circuits.map (·.layout.lookups) ++ (List.replicate widths.length 1 ++ otherSlots)) + (functions.bitmap ++ (traces.bitmap ++ otherActive)) + (functions.degrees ++ (traces.degrees ++ otherDegrees)) = some result) + (satisfied : traces.Satisfied) {width : Nat} {pointer : G} {left right : Array G} + (loadedLeft : memoryFacts traces.rows width pointer left) + (loadedRight : memoryFacts traces.rows width pointer right) : left = right := by + have bounded := traces.capacity_bounded functions accepted + exact traces.functional satisfied (by omega) loadedLeft loadedRight + +def MemoryTraces.auxiliary {widths : List Nat} (traces : MemoryTraces widths) + (byte1 : Byte1Kind → Fin 256 → G) (byte2 : Byte2Kind → Fin 65536 → G) : AuxiliaryTables := + ⟨widths, traces.rows, byte1, byte2⟩ + +theorem MemoryTraces.circuitProviders_reflect {widths : List Nat} (traces : MemoryTraces widths) + (distinct : widths.Nodup) (satisfied : traces.Satisfied) (messageWidth : Nat) + (byte1 : Byte1Kind → Fin 256 → G) (byte2 : Byte2Kind → Fin 65536 → G) + (circuits : List CircuitEmission) : + List.Forall₂ (Provider.PaddedEq messageWidth) + (circuitProviders circuits ++ (traces.providers ++ byte1Providers byte1 ++ byte2Providers byte2)) + ((traces.auxiliary byte1 byte2).circuitProviders circuits) := + forall₂_append (paddedProviders_refl _ _) (forall₂_append + (forall₂_append (traces.providers_reflect distinct satisfied messageWidth) (paddedProviders_refl _ _)) + (paddedProviders_refl _ _)) + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem Backend.memory_trace_execution {selection : Selection} (backend : Backend selection) + (generic : selection.source.componentRanks = false) + (functions : CircuitTraces backend.compiled.bytecode.circuits.toList) + (memories : MemoryTraces backend.compiled.bytecode.memorySizes.toList) + (byte1 : Byte1Kind → Fin 256 → G) (byte2 : Byte2Kind → Fin 65536 → G) + {witnesses : List CircuitWitness} + (emitted : functions.emitWitnesses backend.compiled.bytecode = some witnesses) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (budget : lookupQueryBound + (backend.compiled.bytecode.circuits.toList.map (·.layout.lookups) ++ + (List.replicate backend.compiled.bytecode.memorySizes.size 1 ++ otherSlots)) + (functions.bitmap ++ (memories.bitmap ++ otherActive)) + (functions.degrees ++ (memories.degrees ++ otherDegrees)) = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: + encodedCircuitQueryPool (witnesses.map (·.emission))) + (circuitProviders (witnesses.map (·.emission)) ++ + (memories.providers ++ byte1Providers byte1 ++ byte2Providers byte2))) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) (memorySatisfied : memories.Satisfied) : + Execution backend.compiled.bytecode (memoryFacts memories.rows) + ⟨selection.function, input, selection.success, 0⟩ := by + have decoded := balanced.congr_providers + (memories.circuitProviders_reflect backend.memorySizes_distinct memorySatisfied width byte1 byte2 _) + exact backend.bounded_trace_execution generic (memories.auxiliary byte1 byte2) functions emitted budget width input arity + decoded publicWidth queryWidths (memories.rows_valid memorySatisfied) backend.memorySizes_canonical satisfied + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/Merkle.lean b/Ix/Aiur/Proofs/Merkle.lean new file mode 100644 index 000000000..b85fea51e --- /dev/null +++ b/Ix/Aiur/Proofs/Merkle.lean @@ -0,0 +1,467 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Merkle +import Ix.Aiur.Proofs.Blake3 +import Ix.Aiur.Proofs.MerkleCap + +/-! Fixed-width row packing and binary path authentication. Hash security +is reduced to a collision among the explicitly retained query inputs. -/ + +namespace Aiur.NativeAIR.Merkle + +theorem fieldsBytes_injective {left right : List G} + (same : Transcript.fieldsBytes left = Transcript.fieldsBytes right) : left = right := by + have lengths := congrArg List.length same + rw [Transcript.fieldsBytes_length, Transcript.fieldsBytes_length] at lengths + have count : left.length = right.length := by omega + have l := KeyCodec.readMany_reads ProofCodec.encodeField left + (fun value _ => ProofCodec.readField_reads value) [] + have r := KeyCodec.readMany_reads ProofCodec.encodeField right + (fun value _ => ProofCodec.readField_reads value) [] + change KeyCodec.readMany ProofCodec.readField left.length + (Transcript.fieldsBytes left ++ []) = some (left, []) at l + change KeyCodec.readMany ProofCodec.readField right.length + (Transcript.fieldsBytes right ++ []) = some (right, []) at r + rw [same, count, r] at l + exact (congrArg Prod.fst (Option.some.inj l)).symm + +theorem pairBytes_length (left right : Digest) : (pairBytes left right).length = 64 := by + simp [pairBytes] + +theorem pairBytes_injective {left right otherLeft otherRight : Digest} + (same : pairBytes left right = pairBytes otherLeft otherRight) : + left = otherLeft ∧ right = otherRight := by + have heads := congrArg (List.take 32) same + have tails := congrArg (List.drop 32) same + simp [pairBytes] at heads tails + exact ⟨Vector.toList_inj.mp heads, Vector.toList_inj.mp tails⟩ + +theorem branchBytes_injective {index : Nat} {left right leftSibling rightSibling : Digest} + (same : branchBytes index left leftSibling = branchBytes index right rightSibling) : + left = right ∧ leftSibling = rightSibling := by + unfold branchBytes at same + split at same + · exact pairBytes_injective same + · exact (pairBytes_injective same).symm + +theorem shape_length {dimensions : List Dimensions} {rows : List (List G)} + (fits : shape dimensions rows = true) : rows.length = dimensions.length := by + induction dimensions generalizing rows with + | nil => cases rows <;> simp_all [shape] + | cons dimension dimensions ih => + cases rows with + | nil => simp [shape] at fits + | cons row rows => + simp only [shape, Bool.and_eq_true, beq_iff_eq] at fits + simp only [List.length_cons, ih fits.2] + +theorem rowsAt_absent {dimensions : List Dimensions} {rows : List (List G)} {height : Nat} + (absent : hasHeight dimensions height = false) : rowsAt dimensions rows height = [] := by + induction dimensions generalizing rows with + | nil => rfl + | cons dimension dimensions ih => + simp only [hasHeight, List.any_cons, Bool.or_eq_false_iff, beq_eq_false_iff_ne] at absent + cases rows with + | nil => rfl + | cons row rows => simp only [rowsAt, if_neg absent.1, ih absent.2] + +theorem rowsAt_injective {dimensions : List Dimensions} {left right : List (List G)} + (lf : shape dimensions left = true) (rf : shape dimensions right = true) + (same : ∀ height, (rowsAt dimensions left height).flatten = (rowsAt dimensions right height).flatten) : + left = right := by + induction dimensions generalizing left right with + | nil => cases left <;> cases right <;> simp_all [shape] + | cons dimension dimensions ih => + cases left with + | nil => simp [shape] at lf + | cons l left => + cases right with + | nil => simp [shape] at rf + | cons r right => + simp only [shape, Bool.and_eq_true, beq_iff_eq] at lf rf + have first := same dimension.logHeight + simp only [rowsAt] at first + have pieces := List.append_inj first (lf.1.trans rf.1.symm) + obtain rfl := pieces.1 + congr 1 + apply ih lf.2 rf.2 + intro height + have next := same height + by_cases equal : dimension.logHeight = height + · simp only [rowsAt, if_pos equal, List.flatten_cons] at next + exact List.append_cancel_left next + · simpa only [rowsAt, if_neg equal] using next + +theorem rowBytes_injective {dimensions : List Dimensions} {left right : List (List G)} + (lf : shape dimensions left = true) (rf : shape dimensions right = true) + (same : ∀ height, rowBytes dimensions left height = rowBytes dimensions right height) : + left = right := + rowsAt_injective lf rf fun height => fieldsBytes_injective (same height) + +theorem CollisionOn.mono {hash : Hash} {smaller larger : List (List UInt8)} + (subset : ∀ input ∈ smaller, input ∈ larger) (collision : CollisionOn hash smaller) : + CollisionOn hash larger := by + obtain ⟨left, hl, right, hr, different, same⟩ := collision + exact ⟨left, subset left hl, right, subset right hr, different, same⟩ + +theorem equal_of_no_collision {hash : Hash} {inputs : List (List UInt8)} + (free : ¬CollisionOn hash inputs) {left right : List UInt8} + (hl : left ∈ inputs) (hr : right ∈ inputs) (same : hash left = hash right) : left = right := by + by_cases equal : left = right + · exact equal + · exact False.elim (free ⟨left, hl, right, hr, equal, same⟩) + +theorem step_calls (hash : Hash) (dimensions : List Dimensions) (rows : List (List G)) + (height index : Nat) (current sibling : Digest) : + (step hash dimensions rows height index current sibling).inputs.length ≤ 3 := by + unfold step + split <;> simp only [List.length_cons, List.length_nil] <;> omega + +theorem walk_calls (hash : Hash) (dimensions : List Dimensions) (rows : List (List G)) + (height index : Nat) (current : Digest) (proof : List Digest) : + (walk hash dimensions rows height index current proof).inputs.length ≤ 3 * proof.length := by + induction proof generalizing height index current with + | nil => simp [walk] + | cons sibling proof ih => + simp only [walk, List.length_append, List.length_cons] + have := step_calls hash dimensions rows (height - 1) index current sibling + have := ih (height - 1) (index / 2) (step hash dimensions rows (height - 1) index current sibling).digest + omega + +theorem step_binding {hash : Hash} {dimensions : List Dimensions} {leftRows rightRows : List (List G)} + {height index : Nat} {left right leftSibling rightSibling : Digest} + (free : ¬CollisionOn hash + ((step hash dimensions leftRows height index left leftSibling).inputs ++ + (step hash dimensions rightRows height index right rightSibling).inputs)) + (same : (step hash dimensions leftRows height index left leftSibling).digest = + (step hash dimensions rightRows height index right rightSibling).digest) : + left = right ∧ (hasHeight dimensions height = true → + rowBytes dimensions leftRows height = rowBytes dimensions rightRows height) := by + by_cases inject : hasHeight dimensions height = true + · simp only [step, inject, ↓reduceIte] at same + have outer := equal_of_no_collision free (same := same) + (by simp [step, inject]) (by simp [step, inject]) + have parts := pairBytes_injective outer + have branch := equal_of_no_collision free + (by simp [step, inject]) (by simp [step, inject]) parts.1 + have leaf := equal_of_no_collision free + (by simp [step, inject]) (by simp [step, inject]) parts.2 + exact ⟨(branchBytes_injective branch).1, fun _ => leaf⟩ + · simp only [step, if_neg inject] at same + have branch := equal_of_no_collision free (same := same) + (by simp [step, inject]) (by simp [step, inject]) + exact ⟨(branchBytes_injective branch).1, fun impossible => False.elim (inject impossible)⟩ + +/-- Equal final nodes bind the starting digest and every injected height, +unless the two walks have queried a concrete hash collision. -/ +theorem walk_binding {hash : Hash} {dimensions : List Dimensions} {leftRows rightRows : List (List G)} + {height index : Nat} {left right : Digest} {leftProof rightProof : List Digest} + (count : leftProof.length = rightProof.length) + (free : ¬CollisionOn hash + ((walk hash dimensions leftRows height index left leftProof).inputs ++ + (walk hash dimensions rightRows height index right rightProof).inputs)) + (same : (walk hash dimensions leftRows height index left leftProof).digest = + (walk hash dimensions rightRows height index right rightProof).digest) : + left = right ∧ ∀ depth < leftProof.length, + hasHeight dimensions (height - (depth + 1)) = true → + rowBytes dimensions leftRows (height - (depth + 1)) = + rowBytes dimensions rightRows (height - (depth + 1)) := by + induction leftProof generalizing rightProof height index left right with + | nil => + have empty : rightProof = [] := List.eq_nil_of_length_eq_zero count.symm + subst rightProof + exact ⟨same, fun depth bound => by simp at bound⟩ + | cons leftSibling leftProof ih => + cases rightProof with + | nil => simp at count + | cons rightSibling rightProof => + have tailCount : leftProof.length = rightProof.length := Nat.succ.inj count + have freeTail : ¬CollisionOn hash + ((walk hash dimensions leftRows (height - 1) (index / 2) + (step hash dimensions leftRows (height - 1) index left leftSibling).digest leftProof).inputs ++ + (walk hash dimensions rightRows (height - 1) (index / 2) + (step hash dimensions rightRows (height - 1) index right rightSibling).digest rightProof).inputs) := by + intro collision + apply free (collision.mono ?_) + intro input member + simp only [List.mem_append] at member + simp only [walk, List.mem_append] + exact member.elim (fun h => Or.inl (Or.inr h)) (fun h => Or.inr (Or.inr h)) + have tail := ih tailCount freeTail same + have freeStep : ¬CollisionOn hash + ((step hash dimensions leftRows (height - 1) index left leftSibling).inputs ++ + (step hash dimensions rightRows (height - 1) index right rightSibling).inputs) := by + intro collision + apply free (collision.mono ?_) + intro input member + simp only [List.mem_append] at member + simp only [walk, List.mem_append] + exact member.elim (fun h => Or.inl (Or.inl h)) (fun h => Or.inr (Or.inl h)) + have first := step_binding freeStep tail.1 + refine ⟨first.1, ?_⟩ + intro depth bound inject + cases depth with + | zero => exact first.2 inject + | succ depth => + have shorter : depth < leftProof.length := by simpa using bound + have heightEq : height - (depth + 1 + 1) = (height - 1) - (depth + 1) := by omega + rw [heightEq] at inject ⊢ + exact tail.2 depth shorter inject + +theorem replay_success {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {rows : List (List G)} {proof : List Digest} {result : Replay} + (success : replay hash dimensions capHeight index rows proof = some result) : + dimensions ≠ [] ∧ shape dimensions rows = true ∧ proof.length = maxHeight dimensions - capHeight ∧ + index < 2^maxHeight dimensions ∧ + result = ⟨maxHeight dimensions - proof.length, index / 2^proof.length, + ⟨(walk hash dimensions rows (maxHeight dimensions) index + (hash (rowBytes dimensions rows (maxHeight dimensions))) proof).digest, + rowBytes dimensions rows (maxHeight dimensions) :: + (walk hash dimensions rows (maxHeight dimensions) index + (hash (rowBytes dimensions rows (maxHeight dimensions))) proof).inputs⟩⟩ := by + unfold replay at success + dsimp only at success + split at success + · cases success + next valid => + simp only [Bool.or_eq_true, List.isEmpty_iff, Bool.not_eq_true', + bne_iff_ne, Bool.not_eq_false, decide_eq_true_eq, not_or] at valid + exact ⟨valid.1.1.1, by simpa using valid.1.1.2, + Decidable.not_not.mp valid.1.2, valid.2, (Option.some.inj success).symm⟩ + +theorem replay_complete {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {rows : List (List G)} {proof : List Digest} + (nonempty : dimensions ≠ []) (fits : shape dimensions rows = true) + (count : proof.length = maxHeight dimensions - capHeight) (bounded : index < 2^maxHeight dimensions) : + replay hash dimensions capHeight index rows proof = + some ⟨maxHeight dimensions - proof.length, index / 2^proof.length, + ⟨(walk hash dimensions rows (maxHeight dimensions) index + (hash (rowBytes dimensions rows (maxHeight dimensions))) proof).digest, + rowBytes dimensions rows (maxHeight dimensions) :: + (walk hash dimensions rows (maxHeight dimensions) index + (hash (rowBytes dimensions rows (maxHeight dimensions))) proof).inputs⟩⟩ := by + simp only [replay, List.isEmpty_eq_false_iff.mpr nonempty, fits, Bool.not_true, Bool.or_self, + count, bne_self_eq_false, bounded, decide_true, Bool.false_eq_true, ↓reduceIte] + +theorem replay_calls {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {rows : List (List G)} {proof : List Digest} {result : Replay} + (success : replay hash dimensions capHeight index rows proof = some result) : + result.hashing.inputs.length ≤ 1 + 3 * proof.length := by + obtain ⟨_, _, _, _, rfl⟩ := replay_success success + have := walk_calls hash dimensions rows (maxHeight dimensions) index + (hash (rowBytes dimensions rows (maxHeight dimensions))) proof + simp only [List.length_cons] + omega + +theorem replay_position {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {rows : List (List G)} {proof : List Digest} {result : Replay} + (success : replay hash dimensions capHeight index rows proof = some result) : + result.logHeight = min capHeight (maxHeight dimensions) ∧ + result.index = index / 2^(maxHeight dimensions - capHeight) := by + obtain ⟨_, _, count, _, rfl⟩ := replay_success success + simp only [count] + constructor + · omega + · trivial + +theorem replay_index_bound {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {rows : List (List G)} {proof : List Digest} {result : Replay} + (success : replay hash dimensions capHeight index rows proof = some result) : + result.index < 2^result.logHeight := by + obtain ⟨_, _, count, bounded, rfl⟩ := replay_success success + apply (Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)).mpr + have lengthBound : proof.length ≤ maxHeight dimensions := by omega + simpa only [← Nat.pow_add, Nat.sub_add_cancel lengthBound] using bounded + +theorem hasHeight_iff {dimensions : List Dimensions} {height : Nat} : + hasHeight dimensions height = true ↔ ∃ dimension ∈ dimensions, dimension.logHeight = height := by + simp only [hasHeight, List.any_eq_true, beq_iff_eq] + +theorem height_le_max {dimensions : List Dimensions} {dimension : Dimensions} + (member : dimension ∈ dimensions) : dimension.logHeight ≤ maxHeight dimensions := + MerkleCap.degree_le_max (List.mem_map.mpr ⟨dimension, member, rfl⟩) + +theorem covered_iff {dimensions : List Dimensions} {capHeight : Nat} : + covered dimensions capHeight = true ↔ + ∀ dimension ∈ dimensions, min capHeight (maxHeight dimensions) ≤ dimension.logHeight := by + simp only [covered, MerkleCap.coverage_iff, Nat.sub_zero, List.forall_mem_map, maxHeight] + +/-- Coverage makes every matrix row recoverable from the authenticated +height groups. Both paths may supply different sibling digests. -/ +theorem replay_binding {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {leftRows rightRows : List (List G)} {leftProof rightProof : List Digest} {left right : Replay} + (coverage : covered dimensions capHeight = true) + (ls : replay hash dimensions capHeight index leftRows leftProof = some left) + (rs : replay hash dimensions capHeight index rightRows rightProof = some right) + (free : ¬CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs)) + (same : left.hashing.digest = right.hashing.digest) : leftRows = rightRows := by + obtain ⟨_, lf, lc, _, rfl⟩ := replay_success ls + obtain ⟨_, rf, rc, _, rfl⟩ := replay_success rs + have freeWalk : ¬CollisionOn hash + ((walk hash dimensions leftRows (maxHeight dimensions) index + (hash (rowBytes dimensions leftRows (maxHeight dimensions))) leftProof).inputs ++ + (walk hash dimensions rightRows (maxHeight dimensions) index + (hash (rowBytes dimensions rightRows (maxHeight dimensions))) rightProof).inputs) := by + intro collision + apply free (collision.mono ?_) + intro input member + simp only [List.mem_append] at member + simp only [List.mem_append, List.mem_cons] + exact member.elim (fun h => Or.inl (Or.inr h)) (fun h => Or.inr (Or.inr h)) + have path := walk_binding (lc.trans rc.symm) freeWalk same + have leaf := equal_of_no_collision free + (by simp) (by simp) path.1 + apply rowBytes_injective lf rf + intro height + by_cases present : hasHeight dimensions height = true + · obtain ⟨dimension, member, atHeight⟩ := hasHeight_iff.mp present + have upper := height_le_max member + have lower := covered_iff.mp coverage dimension member + rw [atHeight] at upper lower + by_cases atTop : height = maxHeight dimensions + · simpa only [atTop] using leaf + · have depthBound : maxHeight dimensions - height - 1 < leftProof.length := by omega + have heightEq : maxHeight dimensions - (maxHeight dimensions - height - 1 + 1) = height := by omega + have inject : hasHeight dimensions (maxHeight dimensions - (maxHeight dimensions - height - 1 + 1)) = true := by + simpa only [heightEq] using present + simpa only [heightEq] using path.2 _ depthBound inject + · have absent : hasHeight dimensions height = false := by simpa using present + simp only [rowBytes, rowsAt_absent absent] + +theorem verify_success {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {cap : List Digest} {rows : List (List G)} {proof : List Digest} + (accepted : verify hash dimensions capHeight index cap rows proof = true) : + ∃ result, replay hash dimensions capHeight index rows proof = some result ∧ + cap[result.index]? = some result.hashing.digest := by + cases running : replay hash dimensions capHeight index rows proof with + | none => simp [verify, running] at accepted + | some result => + exact ⟨result, rfl, by simpa only [verify, running, accepts, beq_iff_eq] using accepted⟩ + +/-- Two different accepted rows at the same public dimensions, cap and +index exhibit a collision within at most two path transcripts. -/ +theorem verify_collision {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {cap : List Digest} {leftRows rightRows : List (List G)} {leftProof rightProof : List Digest} + (coverage : covered dimensions capHeight = true) + (la : verify hash dimensions capHeight index cap leftRows leftProof = true) + (ra : verify hash dimensions capHeight index cap rightRows rightProof = true) + (different : leftRows ≠ rightRows) : + ∃ left right, replay hash dimensions capHeight index leftRows leftProof = some left ∧ + replay hash dimensions capHeight index rightRows rightProof = some right ∧ + CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ 2 + 6 * (maxHeight dimensions - capHeight) := by + classical + obtain ⟨left, ls, lc⟩ := verify_success la + obtain ⟨right, rs, rc⟩ := verify_success ra + have li := (replay_position ls).2 + have ri := (replay_position rs).2 + have sameIndex := li.trans ri.symm + rw [sameIndex, rc] at lc + have same := (Option.some.inj lc).symm + have collision : CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) := by + by_cases collides : CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) + · exact collides + · exact False.elim (different (replay_binding coverage ls rs collides same)) + refine ⟨left, right, ls, rs, collision, ?_⟩ + have leftBound := replay_calls ls + have rightBound := replay_calls rs + have leftCount := (replay_success ls).2.2.1 + have rightCount := (replay_success rs).2.2.1 + simp only [List.length_append] + omega + +theorem verifyCovered_collision {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {cap : List Digest} {leftRows rightRows : List (List G)} {leftProof rightProof : List Digest} + (la : verifyCovered hash dimensions capHeight index cap leftRows leftProof = true) + (ra : verifyCovered hash dimensions capHeight index cap rightRows rightProof = true) + (different : leftRows ≠ rightRows) : + ∃ left right, replay hash dimensions capHeight index leftRows leftProof = some left ∧ + replay hash dimensions capHeight index rightRows rightProof = some right ∧ + CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ 2 + 6 * (maxHeight dimensions - capHeight) := by + simp only [verifyCovered, Bool.and_eq_true] at la ra + exact verify_collision la.1 la.2 ra.2 different + +theorem blake3_collision {dimensions : List Dimensions} {capHeight index : Nat} + {cap : List Digest} {leftRows rightRows : List (List G)} {leftProof rightProof : List Digest} + (la : verifyCovered Blake3.digest dimensions capHeight index cap leftRows leftProof = true) + (ra : verifyCovered Blake3.digest dimensions capHeight index cap rightRows rightProof = true) + (different : leftRows ≠ rightRows) : + ∃ left right, replay Blake3.digest dimensions capHeight index leftRows leftProof = some left ∧ + replay Blake3.digest dimensions capHeight index rightRows rightProof = some right ∧ + CollisionOn Blake3.digest (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ 2 + 6 * (maxHeight dimensions - capHeight) := + verifyCovered_collision la ra different + +theorem branchBytes_length (index : Nat) (current sibling : Digest) : + (branchBytes index current sibling).length = 64 := by + unfold branchBytes + split <;> exact pairBytes_length _ _ + +theorem rowsAt_fields_le (dimensions : List Dimensions) (rows : List (List G)) (height : Nat) : + (rowsAt dimensions rows height).flatten.length ≤ rows.flatten.length := by + induction dimensions generalizing rows with + | nil => simp [rowsAt] + | cons dimension dimensions ih => + cases rows with + | nil => simp [rowsAt] + | cons row rows => + have rest := ih rows + unfold rowsAt + split <;> simp only [List.flatten_cons, List.length_append] <;> omega + +theorem rowBytes_length_le (dimensions : List Dimensions) (rows : List (List G)) (height : Nat) : + (rowBytes dimensions rows height).length ≤ 8 * rows.flatten.length := by + rw [rowBytes, Transcript.fieldsBytes_length] + exact Nat.mul_le_mul_left 8 (rowsAt_fields_le dimensions rows height) + +theorem step_input_length {hash : Hash} {dimensions : List Dimensions} {rows : List (List G)} + {height index : Nat} {current sibling : Digest} {input : List UInt8} + (member : input ∈ (step hash dimensions rows height index current sibling).inputs) : + input.length ≤ max 64 (8 * rows.flatten.length) := by + unfold step at member + split at member + · simp only [List.mem_cons, List.not_mem_nil, or_false] at member + rcases member with rfl | rfl | rfl + · rw [branchBytes_length]; exact Nat.le_max_left _ _ + · exact Nat.le_trans (rowBytes_length_le dimensions rows height) (Nat.le_max_right _ _) + · rw [pairBytes_length]; exact Nat.le_max_left _ _ + · simp only [List.mem_singleton] at member + subst input + rw [branchBytes_length] + exact Nat.le_max_left _ _ + +theorem walk_input_length {hash : Hash} {dimensions : List Dimensions} {rows : List (List G)} + {height index : Nat} {current : Digest} {proof : List Digest} {input : List UInt8} + (member : input ∈ (walk hash dimensions rows height index current proof).inputs) : + input.length ≤ max 64 (8 * rows.flatten.length) := by + induction proof generalizing height index current with + | nil => cases member + | cons sibling proof ih => + simp only [walk, List.mem_append] at member + exact member.elim step_input_length ih + +theorem replay_input_length {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {rows : List (List G)} {proof : List Digest} {result : Replay} + (success : replay hash dimensions capHeight index rows proof = some result) + {input : List UInt8} (member : input ∈ result.hashing.inputs) : + input.length ≤ max 64 (8 * rows.flatten.length) := by + obtain ⟨_, _, _, _, rfl⟩ := replay_success success + simp only [List.mem_cons] at member + rcases member with rfl | member + · exact Nat.le_trans (rowBytes_length_le dimensions rows (maxHeight dimensions)) (Nat.le_max_right _ _) + · exact walk_input_length member + +theorem replay_native_input {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {rows : List (List G)} {proof : List Digest} {result : Replay} + (success : replay hash dimensions capHeight index rows proof = some result) + (bounded : rows.flatten.length < 2^61) {input : List UInt8} (member : input ∈ result.hashing.inputs) : + Blake3.NativeInput input := by + have bound := replay_input_length success member + unfold Blake3.NativeInput + omega + +end Aiur.NativeAIR.Merkle diff --git a/Ix/Aiur/Proofs/MerkleCap.lean b/Ix/Aiur/Proofs/MerkleCap.lean new file mode 100644 index 000000000..4d58acb0e --- /dev/null +++ b/Ix/Aiur/Proofs/MerkleCap.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.MerkleCap +import Ix.Aiur.Proofs.ShapedVerifier + +/-! Cap coverage puts every selected power-of-two matrix injection on the +authenticated path. Hash binding and native path replay remain separate. +-/ + +namespace Aiur.NativeAIR.MerkleCap + +theorem maxDegree_nil : maxDegree [] = 0 := rfl + +theorem maxDegree_cons (degree : Nat) (degrees : List Nat) : + maxDegree (degree :: degrees) = max degree (maxDegree degrees) := rfl + +theorem degree_le_max {degree : Nat} {degrees : List Nat} (member : degree ∈ degrees) : + degree ≤ maxDegree degrees := by + induction degrees with + | nil => cases member + | cons first rest ih => + simp only [List.mem_cons] at member + rw [maxDegree_cons] + rcases member with rfl | member + · omega + · have := ih member; omega + +theorem maxDegree_le {degrees : List Nat} {bound : Nat} + (bounded : ∀ degree ∈ degrees, degree ≤ bound) : maxDegree degrees ≤ bound := by + induction degrees with + | nil => exact Nat.zero_le _ + | cons degree rest ih => + have first := bounded degree (by simp) + have tail := ih (fun d member => bounded d (by simp [member])) + rw [maxDegree_cons] + omega + +theorem maxDegree_mono {selected degrees : List Nat} + (subset : ∀ degree ∈ selected, degree ∈ degrees) : maxDegree selected ≤ maxDegree degrees := + maxDegree_le fun degree member => degree_le_max (subset degree member) + +theorem coverage_iff {logBlowup capHeight : Nat} {degrees : List Nat} : + coverage logBlowup capHeight degrees = true ↔ + ∀ degree ∈ degrees, min (capHeight - logBlowup) (maxDegree degrees) ≤ degree := by + simp only [coverage, List.all_eq_true, decide_eq_true_eq] + +theorem coverage_height_iff {logBlowup capHeight : Nat} {degrees : List Nat} : + coverage logBlowup capHeight degrees = true ↔ + ∀ degree ∈ degrees, + min capHeight (logBlowup + maxDegree degrees) ≤ logBlowup + degree := by + rw [coverage_iff] + constructor <;> intro covered degree member + · have := covered degree member; omega + · have := covered degree member; omega + +theorem coverage_empty (logBlowup capHeight : Nat) : coverage logBlowup capHeight [] = true := rfl + +theorem coverage_low_cap {logBlowup capHeight : Nat} (low : capHeight ≤ logBlowup) + (degrees : List Nat) : coverage logBlowup capHeight degrees = true := by + apply coverage_iff.mpr + intro degree member + omega + +theorem coverage_uniform {logBlowup capHeight degree : Nat} {degrees : List Nat} + (uniform : ∀ d ∈ degrees, d = degree) : coverage logBlowup capHeight degrees = true := by + have bound : maxDegree degrees ≤ degree := maxDegree_le fun d member => by + rw [uniform d member] + exact Nat.le_refl _ + apply coverage_iff.mpr + intro d member + rw [uniform d member] + omega + +theorem coverage_subset {logBlowup capHeight : Nat} {degrees selected : List Nat} + (covered : coverage logBlowup capHeight degrees = true) + (subset : ∀ degree ∈ selected, degree ∈ degrees) : + coverage logBlowup capHeight selected = true := by + have bound := maxDegree_mono subset + apply coverage_iff.mpr + intro degree member + have := coverage_iff.mp covered degree (subset degree member) + omega + +/-- The matrix is injected no later than the final authenticated path step. +Clamping the cap to the tree's depth is included in the right-hand side. -/ +theorem coverage_injection {logBlowup capHeight : Nat} {degrees : List Nat} + (covered : coverage logBlowup capHeight degrees = true) {degree : Nat} + (member : degree ∈ degrees) : + (logBlowup + maxDegree degrees) - (logBlowup + degree) ≤ + (logBlowup + maxDegree degrees) - min capHeight (logBlowup + maxDegree degrees) := by + have := coverage_height_iff.mp covered degree member + omega + +theorem coverage_cap_size {logBlowup capHeight : Nat} {degrees : List Nat} + (covered : coverage logBlowup capHeight degrees = true) {degree : Nat} + (member : degree ∈ degrees) : + 2 ^ min capHeight (logBlowup + maxDegree degrees) ≤ 2 ^ (logBlowup + degree) := + Nat.pow_le_pow_right (by decide) (coverage_height_iff.mp covered degree member) + +/-- A matrix omitted by the truncated walk must fail the coverage guard. -/ +theorem omitted_rejected {logBlowup capHeight degree : Nat} {degrees : List Nat} + (member : degree ∈ degrees) + (omitted : (logBlowup + maxDegree degrees) - min capHeight (logBlowup + maxDegree degrees) < + (logBlowup + maxDegree degrees) - (logBlowup + degree)) : + coverage logBlowup capHeight degrees = false := by + cases accepted : coverage logBlowup capHeight degrees with + | false => rfl + | true => have := coverage_injection accepted member; omega + +theorem shorter_matrix_rejected : coverage 0 2 [3, 1] = false := by decide + +theorem exact_injection_accepted : coverage 0 1 [3, 1] = true := by decide + +theorem check_iff {key : KeyCodec.Key} {proof : ProofCodec.Data} : + check key proof = true ↔ + ∀ degree ∈ proof.logDegrees, + min key.parameters.capHeight + (key.parameters.logBlowup + maxDegree (proof.logDegrees.map UInt8.toNat)) ≤ + key.parameters.logBlowup + degree.toNat := by + simp only [check, coverage_height_iff, List.forall_mem_map] + +theorem check_degree {key : KeyCodec.Key} {proof : ProofCodec.Data} + (accepted : check key proof = true) {position : Nat} {degree : UInt8} + (present : proof.logDegrees[position]? = some degree) : + min key.parameters.capHeight + (key.parameters.logBlowup + maxDegree (proof.logDegrees.map UInt8.toNat)) ≤ + key.parameters.logBlowup + degree.toNat := + check_iff.mp accepted degree (List.mem_of_getElem? present) + +end Aiur.NativeAIR.MerkleCap + +namespace Aiur.BoundVerifier + +theorem CheckedProof.cap_coverage {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) : + NativeAIR.MerkleCap.coverage key.parameters.logBlowup key.parameters.capHeight + (checked.data.logDegrees.map UInt8.toNat) = true := checked.cap + +theorem CheckedProof.row_cap {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) {position : Nat} {row : NativeAIR.ProofShape.Row} + (present : checked.rows[position]? = some row) : + min key.parameters.capHeight + (key.parameters.logBlowup + NativeAIR.MerkleCap.maxDegree (checked.data.logDegrees.map UInt8.toNat)) ≤ + key.parameters.logBlowup + row.logDegree.toNat := + NativeAIR.MerkleCap.check_degree checked.cap (checked.row present).2.1.degree + +theorem CheckedProof.row_injection {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) {position : Nat} {row : NativeAIR.ProofShape.Row} + (present : checked.rows[position]? = some row) : + (key.parameters.logBlowup + NativeAIR.MerkleCap.maxDegree (checked.data.logDegrees.map UInt8.toNat)) - + (key.parameters.logBlowup + row.logDegree.toNat) ≤ + (key.parameters.logBlowup + NativeAIR.MerkleCap.maxDegree (checked.data.logDegrees.map UInt8.toNat)) - + key.parameters.capHeight := by + have := checked.row_cap present + omega + +theorem verifyShaped_cap {selection : Selection} {backend : CompiledBackend selection} + {input : Array G} {bytes : ByteArray} (accepted : verifyShaped backend input bytes = .ok ()) : + ∃ checked : CheckedProof backend.keyData bytes, + readProof backend.keyData bytes = .ok checked ∧ + NativeAIR.MerkleCap.check backend.keyData checked.data = true := by + obtain ⟨checked, parsed, _⟩ := verifyShaped_success accepted + exact ⟨checked, parsed, checked.cap⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/Metadata.lean b/Ix/Aiur/Proofs/Metadata.lean new file mode 100644 index 000000000..0296ba973 --- /dev/null +++ b/Ix/Aiur/Proofs/Metadata.lean @@ -0,0 +1,185 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Semantics.BytecodeEval + +/-! Circuit metadata does not change reference bytecode execution. The +theorem preserves errors and state as well as successful outputs, and works +in both directions. It does not interpret satisfying AIR witnesses as +executions of the reference evaluator. -/ + +namespace Aiur.Bytecode.Eval + +structure SameCode (a b : Toplevel) : Prop where + size : a.functions.size = b.functions.size + /-- Bodies may differ in layout metadata. Their executable behavior must + agree in every ambient program, at every fuel and complete input state. -/ + body : ∀ i (ha : i < a.functions.size) (hb : i < b.functions.size), + ∀ t fuel st, evalBlock t fuel a.functions[i].body st = + evalBlock t fuel b.functions[i].body st + inputSize : ∀ i (ha : i < a.functions.size) (hb : i < b.functions.size), + a.functions[i].layout.inputSize = b.functions[i].layout.inputSize + +theorem SameCode.refl (t : Toplevel) : SameCode t t := + ⟨rfl, fun _ _ _ _ _ _ => rfl, fun _ _ _ => rfl⟩ + +theorem SameCode.ofFunctionsEq {a b : Toplevel} (same : a.functions = b.functions) : + SameCode a b := by + constructor + · exact congrArg Array.size same + · intro i ha hb t fuel st + simp only [same] + · intro i ha hb + simp only [same] + +theorem SameCode.trans {a b c : Toplevel} (ab : SameCode a b) (bc : SameCode b c) : + SameCode a c := by + constructor + · exact ab.size.trans bc.size + · intro i ha hc t fuel st + have hb : i < b.functions.size := by rwa [← ab.size] + exact (ab.body i ha hb t fuel st).trans (bc.body i hb hc t fuel st) + · intro i ha hc + have hb : i < b.functions.size := by rwa [← ab.size] + exact (ab.inputSize i ha hb).trans (bc.inputSize i hb hc) + +private theorem ops_lt (b : Block) : sizeOf b.ops < sizeOf b := by + cases b; simp; omega + +private theorem ctrl_lt (b : Block) : sizeOf b.ctrl < sizeOf b := by + cases b; simp; omega + +private theorem case_lt (cases : Array (G × Block)) (defaultBlock : Option Block) + (i : Nat) (h : i < cases.size) : + sizeOf cases[i].2 < sizeOf cases + sizeOf defaultBlock := by + have h1 := Array.sizeOf_get cases i h + have h2 : sizeOf cases[i].2 < sizeOf cases[i] := by + cases cases[i]; simp; omega + omega + +mutual + +theorem evalOp_sameCode {a b : Toplevel} (code : SameCode a b) + (fuel : Nat) (op : Op) (st : EvalState) : + evalOp a fuel op st = evalOp b fuel op st := by + cases op <;> simp only [evalOp] + case call fi args outputSize unconstrained => + cases hg : readIdxs st args with + | error e => rfl + | ok gs => + simp only [bind, Except.bind] + by_cases ha : fi < a.functions.size + · have hb : fi < b.functions.size := by rwa [← code.size] + simp only [dif_pos ha, dif_pos hb, code.inputSize fi ha hb] + split + · rfl + · cases fuel with + | zero => rfl + | succ fuel => + simp only + rw [code.body fi ha hb, evalBlock_sameCode code] + · have hb : ¬ fi < b.functions.size := by rwa [← code.size] + simp only [dif_neg ha, dif_neg hb] +termination_by (fuel, sizeOf op, 0) +decreasing_by all_goals first | decreasing_tactic | omega + +theorem runOps_sameCode {a b : Toplevel} (code : SameCode a b) + (fuel : Nat) (ops : Array Op) (st : EvalState) (i : Nat) : + runOps a fuel ops st i = runOps b fuel ops st i := by + rw [runOps.eq_1 a, runOps.eq_1 b] + by_cases h : i < ops.size + · simp only [dif_pos h, evalOp_sameCode code fuel ops[i] st] + cases evalOp b fuel ops[i] st with + | error e => rfl + | ok st' => exact runOps_sameCode code fuel ops st' (i + 1) + · simp only [dif_neg h] +termination_by (fuel, sizeOf ops, 1 + (ops.size - i)) +decreasing_by all_goals first | decreasing_tactic | omega + +theorem evalBlock_sameCode {a b : Toplevel} (code : SameCode a b) + (fuel : Nat) (block : Block) (st : EvalState) : + evalBlock a fuel block st = evalBlock b fuel block st := by + rw [evalBlock.eq_1 a, evalBlock.eq_1 b, runOps_sameCode code] + cases runOps b fuel block.ops st 0 with + | error e => rfl + | ok st' => exact evalCtrl_sameCode code fuel block.ctrl st' +termination_by (fuel, sizeOf block, 4) +decreasing_by + all_goals first + | decreasing_tactic + | (apply Prod.Lex.right; apply Prod.Lex.left; exact ops_lt _) + | (apply Prod.Lex.right; apply Prod.Lex.left; exact ctrl_lt _) + | omega + +theorem evalCtrl_sameCode {a b : Toplevel} (code : SameCode a b) + (fuel : Nat) (ctrl : Ctrl) (st : EvalState) : + evalCtrl a fuel ctrl st = evalCtrl b fuel ctrl st := by + cases ctrl with + | «return» sel outs => simp only [evalCtrl] + | «yield» sel outs => simp only [evalCtrl] + | «match» idx cases fallback => + simp only [evalCtrl] + cases readIdx st idx with + | error e => rfl + | ok scrut => exact evalMatchArm_sameCode code fuel cases fallback scrut st 0 + | matchContinue idx cases fallback out aux lookups cont => + simp only [evalCtrl] + cases readIdx st idx with + | error e => rfl + | ok scrut => + simp only + rw [evalMatchArm_sameCode code] + cases evalMatchArm b fuel cases fallback scrut st with + | error e => rfl + | ok result => exact evalBlock_sameCode code fuel cont _ +termination_by (fuel, sizeOf ctrl, 3) +decreasing_by all_goals first | decreasing_tactic | omega + +theorem evalMatchArm_sameCode {a b : Toplevel} (code : SameCode a b) + (fuel : Nat) (cases : Array (G × Block)) (fallback : Option Block) + (scrut : G) (st : EvalState) (i : Nat) : + evalMatchArm a fuel cases fallback scrut st i = evalMatchArm b fuel cases fallback scrut st i := by + rw [evalMatchArm.eq_1 a, evalMatchArm.eq_1 b] + by_cases h : i < cases.size + · simp only [dif_pos h] + split + · exact evalBlock_sameCode code fuel cases[i].2 st + · exact evalMatchArm_sameCode code fuel cases fallback scrut st (i + 1) + · simp only [dif_neg h] + exact evalDefaultBlock_sameCode code fuel fallback st +termination_by (fuel, sizeOf cases + sizeOf fallback, 2 + (cases.size - i)) +decreasing_by + all_goals + clean_wf + first + | decreasing_tactic + | (apply Prod.Lex.right; apply Prod.Lex.left; exact case_lt cases fallback i ‹_›) + | (apply Prod.Lex.right; apply Prod.Lex.left + cases cases; simp; omega) + | omega + +theorem evalDefaultBlock_sameCode {a b : Toplevel} (code : SameCode a b) + (fuel : Nat) (fallback : Option Block) (st : EvalState) : + evalDefaultBlock a fuel fallback st = evalDefaultBlock b fuel fallback st := by + cases fallback with + | none => simp only [evalDefaultBlock] + | some block => simpa only [evalDefaultBlock] using evalBlock_sameCode code fuel block st +termination_by (fuel, sizeOf fallback, 1) +decreasing_by all_goals first | decreasing_tactic | (simp_wf; omega) + +end + +theorem runFunction_sameCode {a b : Toplevel} (code : SameCode a b) + (function : FunIdx) (args : Array G) (io : IOBuffer) (fuel : Nat) : + runFunction a function args io fuel = runFunction b function args io fuel := by + rw [runFunction.eq_1 a, runFunction.eq_1 b] + by_cases ha : function < a.functions.size + · have hb : function < b.functions.size := by rwa [← code.size] + simp only [dif_pos ha, dif_pos hb, code.inputSize function ha hb, + code.body function ha hb, evalBlock_sameCode code] + · have hb : ¬ function < b.functions.size := by rwa [← code.size] + simp only [dif_neg ha, dif_neg hb] + +end Aiur.Bytecode.Eval diff --git a/Ix/Aiur/Proofs/NormalizationFrames.lean b/Ix/Aiur/Proofs/NormalizationFrames.lean new file mode 100644 index 000000000..fca517727 --- /dev/null +++ b/Ix/Aiur/Proofs/NormalizationFrames.lean @@ -0,0 +1,162 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Semantics.SourceEval + +/-! Semantic identities for let frames, continuation sequencing and call +modes. They preserve complete results at unchanged call fuel. These are +components of normalization; fresh naming and complete argument hoisting +require separate proofs. -/ + +namespace Aiur.Source.Eval + +theorem wrapLets_peelLets (term : Term) : + Term.wrapLets term.peelLets.1 term.peelLets.2 = term := by + induction term using Term.peelLets.induct with + | case1 pattern value body frames core peeled ih => + simpa only [Term.peelLets, peeled, Term.wrapLets] using congrArg (Term.let pattern value) ih + | case2 term notLet => + rw [Term.peelLets.eq_def] + split + · exact False.elim (notLet _ _ _ rfl) + · rfl + +def evalFrames (decls : Decls) (fuel : Nat) : + List (Pattern × Term) → Bindings → EvalState → Except SourceError (Bindings × EvalState) + | [], bindings, st => .ok (bindings, st) + | (pattern, value) :: frames, bindings, st => do + let (value, st) ← interp decls fuel bindings value st + let some added := matchPattern st.store pattern value | .error .patternFail + evalFrames decls fuel frames (added ++ bindings) st + +theorem interp_wrapLets (decls : Decls) (fuel : Nat) (frames : List (Pattern × Term)) + (body : Term) (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings (Term.wrapLets frames body) st = + (do let (bindings, st) ← evalFrames decls fuel frames bindings st + interp decls fuel bindings body st) := by + induction frames generalizing bindings st with + | nil => rfl + | cons frame frames ih => + rcases frame with ⟨pattern, value⟩ + simp only [Term.wrapLets, interp, evalFrames] + cases interp decls fuel bindings value st with + | error error => rfl + | ok result => + rcases result with ⟨value, st'⟩ + dsimp only [bind, Except.bind] + cases matchPattern st'.store pattern value with + | none => rfl + | some added => exact ih (added ++ bindings) st' + +theorem evalFrames_append (decls : Decls) (fuel : Nat) + (first rest : List (Pattern × Term)) (bindings : Bindings) (st : EvalState) : + evalFrames decls fuel (first ++ rest) bindings st = + (do let (bindings, st) ← evalFrames decls fuel first bindings st + evalFrames decls fuel rest bindings st) := by + induction first generalizing bindings st with + | nil => rfl + | cons frame frames ih => + rcases frame with ⟨pattern, value⟩ + simp only [List.cons_append, evalFrames] + cases interp decls fuel bindings value st with + | error error => rfl + | ok result => + rcases result with ⟨value, st'⟩ + dsimp only [bind, Except.bind] + cases matchPattern st'.store pattern value with + | none => rfl + | some added => exact ih (added ++ bindings) st' + +theorem interp_peelLets (decls : Decls) (fuel : Nat) (term : Term) + (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings term st = + (do let (bindings, st) ← evalFrames decls fuel term.peelLets.1 bindings st + interp decls fuel bindings term.peelLets.2 st) := by + rw [← interp_wrapLets, wrapLets_peelLets] + +theorem interp_ret_wrapLets (decls : Decls) (fuel : Nat) + (frames : List (Pattern × Term)) (body : Term) (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings (.ret (Term.wrapLets frames body)) st = + interp decls fuel bindings (Term.wrapLets frames (.ret body)) st := by + rw [interp_wrapLets] + simp only [interp, interp_wrapLets] + cases evalFrames decls fuel frames bindings st with + | error error => rfl + | ok result => cases result; rfl + +theorem interp_ioWrite_sequence (decls : Decls) (fuel : Nat) + (channel data continuation : Term) (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings (.ioWrite channel data continuation) st = + interp decls fuel bindings (.let .wildcard (.ioWrite channel data .unit) continuation) st := by + simp only [interp] + cases interp decls fuel bindings channel st <;> simp only + next result => + rcases result with ⟨channel, st⟩ + cases interp decls fuel bindings data st <;> simp only + next result => + rcases result with ⟨data, st⟩ + cases channel <;> cases data <;> simp only + split <;> simp only [matchPattern, List.nil_append] + +theorem interp_debug_sequence (decls : Decls) (fuel : Nat) + (label : String) (value : Option Term) (continuation : Term) + (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings (.debug label value continuation) st = + interp decls fuel bindings (.let .wildcard (.debug label value .unit) continuation) st := by + cases value with + | none => simp only [interp, matchPattern, List.nil_append] + | some value => + simp only [interp] + cases interp decls fuel bindings value st with + | error error => rfl + | ok result => + rcases result with ⟨value, st'⟩ + simp only [matchPattern, List.nil_append] + +theorem interp_assertEq_sequence (decls : Decls) (fuel : Nat) + (first second : Term) (message : Option String) (continuation : Term) + (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings (.assertEq first second message continuation) st = + interp decls fuel bindings + (.let .wildcard (.assertEq first second message .unit) continuation) st := by + cases message <;> ( + simp only [interp] + cases interp decls fuel bindings first st <;> simp only + next result => + rcases result with ⟨first, st⟩ + cases interp decls fuel bindings second st <;> simp only + next result => + rcases result with ⟨second, st⟩ + split <;> simp only [matchPattern, List.nil_append]) + +theorem interp_ioSetInfo_sequence (decls : Decls) (fuel : Nat) + (channel key index length continuation : Term) (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings (.ioSetInfo channel key index length continuation) st = + interp decls fuel bindings + (.let .wildcard (.ioSetInfo channel key index length .unit) continuation) st := by + simp only [interp] + cases interp decls fuel bindings channel st <;> simp only + next result => + rcases result with ⟨channel, st⟩ + cases interp decls fuel bindings key st <;> simp only + next result => + rcases result with ⟨key, st⟩ + cases interp decls fuel bindings index st <;> simp only + next result => + rcases result with ⟨index, st⟩ + cases interp decls fuel bindings length st <;> simp only + next result => + rcases result with ⟨length, st⟩ + cases channel <;> cases key <;> cases index <;> cases length <;> simp only + split <;> try simp only + split <;> simp only [matchPattern, List.nil_append] + +theorem interp_app_mode (decls : Decls) (fuel : Nat) (bindings : Bindings) + (global : Global) (args : List Term) (before after : CallMode) (st : EvalState) : + interp decls fuel bindings (.app global args before) st = + interp decls fuel bindings (.app global args after) st := by + simp only [interp] + +end Aiur.Source.Eval diff --git a/Ix/Aiur/Proofs/OpeningShape.lean b/Ix/Aiur/Proofs/OpeningShape.lean new file mode 100644 index 000000000..e3554d940 --- /dev/null +++ b/Ix/Aiur/Proofs/OpeningShape.lean @@ -0,0 +1,144 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.VerifierArithmetic +import Ix.Aiur.Proofs.ShapedVerifier +import Ix.Aiur.Proofs.Selectors +import Ix.Aiur.Proofs.LogUp + +/-! The selected compiled key supplies the missing preprocessed-slot +invariant. Together with checked proof shape it gives the complete graph +view, lookup widths and valid logarithmic trace domain. +-/ + +namespace Aiur.NativeAIR.CompiledKey + +theorem preprocessedIndices_none (program : Bytecode.Toplevel) (index : Nat) : + (preprocessedIndices program)[index]? = some none ↔ + index < program.circuits.size + program.memorySizes.size := by + unfold preprocessedIndices + by_cases inside : index < program.circuits.size + program.memorySizes.size + · rw [List.getElem?_append_left (by simpa only [List.length_replicate] using inside)] + simp only [List.getElem?_replicate, inside, if_true] + · rw [List.getElem?_append_right (by simpa using Nat.le_of_not_lt inside)] + simp only [List.length_replicate] + constructor + · intro present + have member := List.mem_of_getElem? present + simp only [List.mem_cons, List.not_mem_nil, reduceCtorEq, false_or] at member + · intro bound; exact False.elim (inside bound) + +theorem circuits_preprocessed_absent {logBlowup : Nat} {program : Bytecode.Toplevel} {result : List KeyCodec.Circuit} + (built : circuits logBlowup program = some result) {index : Nat} {artifact : KeyCodec.Circuit} + (selected : result[index]? = some artifact) + (absent : (preprocessedIndices program)[index]? = some none) : artifact.preprocessedWidth = 0 := by + have bound := (preprocessedIndices_none program index).mp absent + by_cases first : index < program.circuits.size + · have source := Array.getElem?_eq_getElem first + obtain ⟨_, _, _, _, width, _, _⟩ := functionCircuit_success (circuits_function built source selected) + exact width + · have memory : index - program.circuits.size < program.memorySizes.size := by omega + have source := Array.getElem?_eq_getElem memory + have equal : program.circuits.size + (index - program.circuits.size) = index := by omega + have compiled := circuits_memory built source (equal ▸ selected) + obtain ⟨_, _, _, _, width, _, _⟩ := memoryCircuit_success compiled + exact width + +end Aiur.NativeAIR.CompiledKey + +namespace Aiur.BoundVerifier +open NativeAIR + +theorem CompiledBackend.row_preprocessed_absent {selection : Selection} + (backend : CompiledBackend selection) {proof : ProofCodec.Data} {index position : Nat} + {row : ProofShape.Row} (sourced : row.Sourced backend.keyData proof index position) + (absent : row.preprocessed = none) : row.circuit.preprocessedWidth = 0 := by + obtain ⟨slot, present, read⟩ := sourced.preprocessed + cases slot with + | none => + rw [backend.preprocessed_indices] at present + exact CompiledKey.circuits_preprocessed_absent backend.circuits_bound sourced.circuit present + | some slot => + obtain ⟨_, _, _, _, someRow⟩ := ProofShape.readPreprocessed_some read + rw [absent] at someRow + cases someRow + +end Aiur.BoundVerifier + +namespace Aiur.NativeAIR.VerifierArithmetic +open ProofCodec (Extension) +open LogUp (Coordinates) + +theorem publics_size (challenges : Challenges) (entering leaving : Extension) : + (publics challenges entering leaving).size = 8 := rfl + +theorem publics_beta (challenges : Challenges) (entering leaving : Extension) : + Coordinates.read (publics challenges entering leaving) 0 = + some ((Coordinates.fromExtension challenges.beta).map Extension.ofBase) := rfl + +theorem publics_gamma (challenges : Challenges) (entering leaving : Extension) : + Coordinates.read (publics challenges entering leaving) 1 = + some ((Coordinates.fromExtension challenges.gamma).map Extension.ofBase) := rfl + +theorem publics_entering (challenges : Challenges) (entering leaving : Extension) : + Coordinates.read (publics challenges entering leaving) 2 = + some ((Coordinates.fromExtension entering).map Extension.ofBase) := rfl + +theorem publics_leaving (challenges : Challenges) (entering leaving : Extension) : + Coordinates.read (publics challenges entering leaving) 3 = + some ((Coordinates.fromExtension leaving).map Extension.ofBase) := rfl + +theorem deltaScaled_size (domain : Domain.Subgroup) (entering leaving : Extension) : + (deltaScaled domain entering leaving).size = 2 := rfl + +theorem deltaScaled_coordinates (domain : Domain.Subgroup) (entering leaving : Extension) : + Coordinates.read (deltaScaled domain entering leaving) 0 = + some (((Coordinates.fromExtension (leaving - entering)).scale (Domain.normalizer domain).inverse).map + Extension.ofBase) := by + change some (⟨(Extension.ofBase leaving.c0 - Extension.ofBase entering.c0) * + Extension.ofBase (Domain.normalizer domain).inverse, + (Extension.ofBase leaving.c1 - Extension.ofBase entering.c1) * + Extension.ofBase (Domain.normalizer domain).inverse⟩ : Coordinates Extension) = + some ⟨Extension.ofBase ((leaving.c0 - entering.c0) * (Domain.normalizer domain).inverse), + Extension.ofBase ((leaving.c1 - entering.c1) * (Domain.normalizer domain).inverse)⟩ + rw [Extension.ofBase_mul, Extension.ofBase_mul, Extension.ofBase_sub, Extension.ofBase_sub] + +theorem view_fits {parameters : KeyCodec.Parameters} {row : ProofShape.Row} + (fits : row.Fits parameters) (absent : row.preprocessed = none → row.circuit.preprocessedWidth = 0) + (challenges : Challenges) (entering : Extension) (selectors : Domain.Selectors Extension) : + (view challenges row entering selectors).Fits row.circuit.widths := by + refine ⟨?_, rfl⟩ + intro source offset + cases source with + | main => cases offset <;> simp only [view, rowColumns, pairColumns, List.size_toArray, + KeyCodec.Circuit.widths, GraphWidths.width, fits.stage1] + | stage2 => + cases offset with + | current => exact fits.stage2.1 + | next => exact fits.stage2.2 + | preprocessed => + cases selected : row.preprocessed with + | none => simp only [view, rowColumns, selected, Array.size_empty, KeyCodec.Circuit.widths, + GraphWidths.width, absent selected] + | some pair => + have dimensions := fits.preprocessed pair selected + cases offset <;> simp only [view, rowColumns, selected, pairColumns, List.size_toArray, + KeyCodec.Circuit.widths, GraphWidths.width, dimensions] + +theorem domain_defined {parameters : KeyCodec.Parameters} {row : ProofShape.Row} (fits : row.Fits parameters) : + ∃ domain, Domain.ofLogSize row.logDegree.toNat = some domain := by + have bounded : row.logDegree.toNat < 33 := by have := fits.degree; omega + exact ⟨⟨row.logDegree.toNat, bounded⟩, by simp only [Domain.ofLogSize, dif_pos bounded]⟩ + +theorem stage2_width {parameters : KeyCodec.Parameters} {row : ProofShape.Row} (fits : row.Fits parameters) + (positive : 0 < row.circuit.lookupGroupSize) : + LogUp.groupCount row.circuit.lookupGroupSize row.circuit.graph.lookups.length * 2 ≤ + (rowColumns row .stage2 .current).size ∧ 2 ≤ (rowColumns row .stage2 .next).size := by + simp only [rowColumns, pairColumns, List.size_toArray, fits.stage2, KeyCodec.Circuit.widths, + ← LogUp.groupCount_key row.circuit positive] + have := LogUp.groupCount_positive row.circuit.lookupGroupSize row.circuit.graph.lookups.length + omega + +end Aiur.NativeAIR.VerifierArithmetic diff --git a/Ix/Aiur/Proofs/OperationAllocation.lean b/Ix/Aiur/Proofs/OperationAllocation.lean new file mode 100644 index 000000000..3ea32cffa --- /dev/null +++ b/Ix/Aiur/Proofs/OperationAllocation.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Stages.Bytecode + +/-! Logical output degrees and physical auxiliary allocation of one operation. +This projection retains the compiler's independent degree bookkeeping. -/ + +namespace Aiur.Bytecode + +structure OpAllocation where + degrees : Array Nat + auxiliaries : Nat + deriving DecidableEq, Repr + +def OpAllocation.advice (size : Nat) : OpAllocation := ⟨Array.replicate size 1, size⟩ + +def selectedDegree (degrees : Array Nat) (indices : Array Nat) (initial : Nat) : Nat := + (indices.map fun index => degrees[index]?.getD 0).foldl Nat.max initial + +theorem selectedDegree_initial (degrees : Array Nat) (indices : Array Nat) (initial : Nat) : + selectedDegree degrees indices initial = max initial (selectedDegree degrees indices 0) := by + simpa only [selectedDegree, Nat.max_zero] using + (Array.foldl_assoc (op := Nat.max) (xs := indices.map fun index => degrees[index]?.getD 0) + (a₁ := initial) (a₂ := 0)) + +theorem selectedDegree_append (degrees : Array Nat) (left right : Array Nat) (initial : Nat) : + selectedDegree degrees (left ++ right) initial = + max (selectedDegree degrees left initial) (selectedDegree degrees right 0) := by + simp only [selectedDegree, Array.map_append, Array.foldl_append] + exact selectedDegree_initial degrees right _ + +def Op.allocation (degrees : Array Nat) : Op → OpAllocation + | .const _ => ⟨#[0], 0⟩ + | .add a b | .sub a b => ⟨#[max (degrees[a]?.getD 0) (degrees[b]?.getD 0)], 0⟩ + | .mul a b => + let degree := degrees[a]?.getD 0 + degrees[b]?.getD 0 + if degree < 2 then ⟨#[degree], 0⟩ else .advice 1 + | .eqZero a => if degrees[a]?.getD 0 = 0 then ⟨#[0], 0⟩ else ⟨#[1], 2⟩ + | .call _ _ size unconstrained => + ⟨Array.replicate size 1, size + (if unconstrained then 0 else 6)⟩ + | .store _ => .advice 1 + | .load size _ | .ioRead _ _ size => .advice size + | .assertEq .. | .ioSetInfo .. | .ioWrite .. | .debug .. | .u8RangeCheck .. => ⟨#[], 0⟩ + | .ioGetInfo .. | .unconstrainedBigUintDivMod .. => .advice 2 + | .u8BitDecomposition .. | .unconstrainedGToBytes .. => .advice 8 + | .u8ShiftLeft .. | .u8ShiftRight .. | .u8Xor .. | .u8And .. | .u8Or .. | .u8LessThan .. + | .unconstrainedGInverse .. => .advice 1 + | .u8Add a b | .u8Sub a b => + ⟨#[1, max (max (degrees[a]?.getD 0) (degrees[b]?.getD 0)) 1], 1⟩ + | .u8Mul .. | .u8XorSplit7 .. | .u8XorSplit4 .. => .advice 2 + | .u32LessThan .. => ⟨#[1], 12⟩ + | .unconstrainedU32Add a b => ⟨(Array.replicate 4 1).push (selectedDegree degrees (a ++ b) 1), 4⟩ + | .unconstrainedU32Add3 a b c => ⟨(Array.replicate 4 1).push (selectedDegree degrees (a ++ b ++ c) 1), 4⟩ + | .u32ToField indices => ⟨#[selectedDegree degrees indices 0], 0⟩ + +/-- Allocation for a selected component layout. The empty mode table retains +the generic ordered call allocation described by `Op.allocation`. -/ +def Op.allocationFor (callRanks : Array CallRank) (degrees : Array Nat) : Op → OpAllocation + | .call function _ size unconstrained => + let extra := if unconstrained then 0 else + match callRanks[function]?.getD .ordered with + | .zero => 0 + | .bound => 1 + | .ordered => 6 + ⟨Array.replicate size 1, size + extra⟩ + | op => op.allocation degrees + +theorem Op.allocationFor_empty (op : Op) (degrees : Array Nat) : + op.allocationFor #[] degrees = op.allocation degrees := by + cases op <;> rfl + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/OperationDegrees.lean b/Ix/Aiur/Proofs/OperationDegrees.lean new file mode 100644 index 000000000..5c262d43b --- /dev/null +++ b/Ix/Aiur/Proofs/OperationDegrees.lean @@ -0,0 +1,343 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationSequences + +/-! +Tracked degree zero implies a constant frontend expression. Positive tracked +degrees may still accompany folded constants; no converse is imposed. This +invariant is needed to identify equality-test allocation with compiler layout. +-/ + +namespace Aiur.NativeAIR + +def RowExpr.ZeroConstant (row : RowExpr) : Prop := + row.degree = 0 → ∃ value, row.expr = .konst value + +theorem RowExpr.ZeroConstant.konst (value : G) : (RowExpr.konst value).ZeroConstant := + fun _ => ⟨value, rfl⟩ + +theorem RowExpr.ZeroConstant.variable (column : ColRef) : (RowExpr.variable column).ZeroConstant := by + intro zero + cases zero + +theorem RowExpr.ZeroConstant.add {left right : RowExpr} (a : left.ZeroConstant) (b : right.ZeroConstant) : + (left.add right).ZeroConstant := by + intro zero + change max left.degree right.degree = 0 at zero + obtain ⟨x, hx⟩ := a (by omega) + obtain ⟨y, hy⟩ := b (by omega) + exact ⟨x + y, by simp only [RowExpr.add, hx, hy, Expr.frontAdd, Expr.constantValue]⟩ + +theorem RowExpr.ZeroConstant.sub {left right : RowExpr} (a : left.ZeroConstant) (b : right.ZeroConstant) : + (left.sub right).ZeroConstant := by + intro zero + change max left.degree right.degree = 0 at zero + obtain ⟨x, hx⟩ := a (by omega) + obtain ⟨y, hy⟩ := b (by omega) + exact ⟨x - y, by simp only [RowExpr.sub, hx, hy, Expr.frontSub, Expr.constantValue]⟩ + +theorem RowExpr.ZeroConstant.mul {left right : RowExpr} (a : left.ZeroConstant) (b : right.ZeroConstant) : + (left.mul right).ZeroConstant := by + intro zero + change left.degree + right.degree = 0 at zero + obtain ⟨x, hx⟩ := a (by omega) + obtain ⟨y, hy⟩ := b (by omega) + exact ⟨x * y, by simp only [RowExpr.mul, hx, hy, Expr.frontMul, Expr.constantValue]⟩ + +namespace OpEmitter + +def DegreeValid (rows : Array RowExpr) : Prop := ∀ row ∈ rows, row.ZeroConstant + +theorem DegreeValid.empty : DegreeValid #[] := by + intro row member + exact False.elim (Array.not_mem_empty row member) + +theorem DegreeValid.singleton {row : RowExpr} (valid : row.ZeroConstant) : DegreeValid #[row] := by + intro expr member + have equal := Array.mem_singleton.mp member + subst expr + exact valid + +theorem DegreeValid.append {left right : Array RowExpr} (a : DegreeValid left) (b : DegreeValid right) : + DegreeValid (left ++ right) := by + intro row member + rcases Array.mem_append.mp member with member | member + · exact a row member + · exact b row member + +theorem DegreeValid.push {rows : Array RowExpr} {row : RowExpr} (valid : DegreeValid rows) + (added : row.ZeroConstant) : DegreeValid (rows.push row) := by + intro expr member + rcases Array.mem_push.mp member with member | rfl + · exact valid expr member + · exact added + +theorem DegreeValid.read {rows : Array RowExpr} (valid : DegreeValid rows) {index : Nat} {row : RowExpr} + (present : rows[index]? = some row) : row.ZeroConstant := valid row (Array.mem_of_getElem? present) + +theorem DegreeValid.getD {rows : Array RowExpr} (valid : DegreeValid rows) (index : Nat) : + (rows[index]?.getD (.konst 0)).ZeroConstant := by + cases present : rows[index]? with + | none => exact RowExpr.ZeroConstant.konst 0 + | some row => exact valid.read present + +theorem DegreeValid.select {rows : Array RowExpr} (valid : DegreeValid rows) + {indices : Array Nat} {selected : Array RowExpr} (read : select rows indices = some selected) : + DegreeValid selected := by + intro row member + obtain ⟨index, bound, equal⟩ := Array.mem_iff_getElem.mp member + have selectedRead : selected[index]? = some row := Array.getElem?_eq_some_iff.mpr ⟨bound, equal⟩ + have input := array_mapM_read read index + rw [selectedRead] at input + cases indexRead : indices[index]? with + | none => rw [indexRead] at input; cases input + | some actual => + simp only [indexRead, bind, Option.bind_some] at input + exact valid.read input + +theorem advice_degreeValid (first count : Nat) : DegreeValid (advice first count) := by + intro row member + obtain ⟨index, rfl⟩ := Array.mem_ofFn.mp member + exact RowExpr.ZeroConstant.variable _ + +theorem packFour_degreeValid (bytes : Fin 4 → RowExpr) (valid : ∀ index, (bytes index).ZeroConstant) : + (packFour bytes).ZeroConstant := by + exact ((((RowExpr.ZeroConstant.konst 0).add ((valid 0).mul (RowExpr.ZeroConstant.konst _))).add + ((valid 1).mul (RowExpr.ZeroConstant.konst _))).add + ((valid 2).mul (RowExpr.ZeroConstant.konst _))).add + ((valid 3).mul (RowExpr.ZeroConstant.konst _)) + +theorem readWord_degreeValid {rows : Array RowExpr} (valid : DegreeValid rows) + {indices : Array Nat} {word : RowExpr} (read : readWord rows indices = some word) : word.ZeroConstant := by + simp only [readWord] at read + split at read + · cases read + · simp only [bind, Option.bind] at read + split at read + · cases read + rename_i selected selectedRead + cases read + exact packFour_degreeValid _ (fun index => (valid.select selectedRead).getD index.val) + +theorem fromScalar_degreeValid {scalar : ScalarEmission} (valid : scalar.output.ZeroConstant) : + DegreeValid (fromScalar scalar).outputs := DegreeValid.singleton valid + +theorem emitMul_degreeValid (selector : Expr) (first : Nat) {left right : RowExpr} + (a : left.ZeroConstant) (b : right.ZeroConstant) : (emitMul selector first left right).output.ZeroConstant := by + dsimp only [emitMul] + split + · exact a.mul b + · exact RowExpr.ZeroConstant.variable _ + +theorem emitEqZero_degreeValid (selector : Expr) (first : Nat) (input : RowExpr) : + (emitEqZero selector first input).output.ZeroConstant := by + unfold emitEqZero + split + · exact RowExpr.ZeroConstant.konst _ + · exact RowExpr.ZeroConstant.variable _ + +theorem emitByte2_degreeValid (first : Nat) (kind : AIR.Byte2Kind) (left right : RowExpr) : + DegreeValid (emitByte2 first kind left right).outputs := by + have carry (subtract : Bool) : (byteCarry first subtract left right).ZeroConstant := by + intro zero + change max (max left.degree right.degree) 1 = 0 at zero + omega + cases kind <;> first + | exact advice_degreeValid _ _ + | exact (advice_degreeValid _ _).push (carry _) + +theorem emitWordSum_degreeValid (first : Nat) {sum : RowExpr} (valid : sum.ZeroConstant) : + DegreeValid (emitWordSum first sum).outputs := + (advice_degreeValid _ _).push ((valid.sub + (packFour_degreeValid _ (fun _ => RowExpr.ZeroConstant.variable _))).mul (RowExpr.ZeroConstant.konst _)) + +theorem emitU32LessThan_degreeValid (selector : Expr) (first : Nat) (left right : RowExpr) : + DegreeValid (emitU32LessThan selector first left right).outputs := by + apply DegreeValid.singleton + intro zero + cases zero + +theorem emitByte1_dispatch_degreeValid (selector rank : Expr) (first : Nat) (kind : AIR.Byte1Kind) (index : Nat) + {rows : Array RowExpr} {emission : Emission} + (emitted : emitOp selector rank first (kind.op index) rows = some emission) : DegreeValid emission.outputs := by + rw [emitOp_byte1] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact advice_degreeValid _ _ + +theorem emitByte2_dispatch_degreeValid (selector rank : Expr) (first : Nat) (kind : AIR.Byte2Kind) (a b : Nat) + {rows : Array RowExpr} {emission : Emission} + (emitted : emitOp selector rank first (kind.op a b) rows = some emission) : DegreeValid emission.outputs := by + rw [emitOp_byte2] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact emitByte2_degreeValid _ _ _ _ + +theorem emitOp_degreeValid {selector rank : Expr} {first : Nat} {op : Bytecode.Op} + {rows : Array RowExpr} {emission : Emission} (valid : DegreeValid rows) + (emitted : emitOp selector rank first op rows = some emission) : + DegreeValid emission.outputs := by + cases op with + | const value => + cases emitted + exact DegreeValid.singleton (RowExpr.ZeroConstant.konst _) + | add a b | sub a b | mul a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + apply DegreeValid.singleton + first + | exact RowExpr.ZeroConstant.add (valid.read readA) (valid.read readB) + | exact RowExpr.ZeroConstant.sub (valid.read readA) (valid.read readB) + | exact emitMul_degreeValid selector first (valid.read readA) (valid.read readB) + | eqZero index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact DegreeValid.singleton (emitEqZero_degreeValid _ _ _) + | call function indices size unconstrained => + cases unconstrained with + | true => + cases emitted + exact advice_degreeValid _ _ + | false => + simp only [emitOp, Bool.false_eq_true, if_false, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact advice_degreeValid _ _ + | store indices | load size index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact advice_degreeValid _ _ + | assertEq xs ys message => + simp only [emitOp] at emitted + split at emitted + · cases emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact DegreeValid.empty + | ioGetInfo | ioRead | unconstrainedBigUintDivMod | unconstrainedGToBytes | unconstrainedGInverse => + cases emitted + exact advice_degreeValid _ _ + | ioSetInfo | ioWrite | debug => + cases emitted + exact DegreeValid.empty + | u8BitDecomposition index => exact emitByte1_dispatch_degreeValid selector rank first .bits index emitted + | u8ShiftLeft index => exact emitByte1_dispatch_degreeValid selector rank first .shiftLeft index emitted + | u8ShiftRight index => exact emitByte1_dispatch_degreeValid selector rank first .shiftRight index emitted + | u8Xor a b => exact emitByte2_dispatch_degreeValid selector rank first .xor a b emitted + | u8Add a b => exact emitByte2_dispatch_degreeValid selector rank first .add a b emitted + | u8Sub a b => exact emitByte2_dispatch_degreeValid selector rank first .sub a b emitted + | u8And a b => exact emitByte2_dispatch_degreeValid selector rank first .and a b emitted + | u8Or a b => exact emitByte2_dispatch_degreeValid selector rank first .or a b emitted + | u8LessThan a b => exact emitByte2_dispatch_degreeValid selector rank first .lessThan a b emitted + | u8RangeCheck a b => exact emitByte2_dispatch_degreeValid selector rank first .range a b emitted + | u8Mul a b => exact emitByte2_dispatch_degreeValid selector rank first .mul a b emitted + | u8XorSplit7 a b => exact emitByte2_dispatch_degreeValid selector rank first .split7 a b emitted + | u8XorSplit4 a b => exact emitByte2_dispatch_degreeValid selector rank first .split4 a b emitted + | u32LessThan a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact emitU32LessThan_degreeValid _ _ _ _ + | unconstrainedU32Add a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + exact emitWordSum_degreeValid _ (RowExpr.ZeroConstant.add + (readWord_degreeValid valid readA) (readWord_degreeValid valid readB)) + | unconstrainedU32Add3 a b c => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + dsimp only at emitted + split at emitted + · cases emitted + rename_i third readC + cases emitted + exact emitWordSum_degreeValid _ (RowExpr.ZeroConstant.add + (RowExpr.ZeroConstant.add (readWord_degreeValid valid readA) (readWord_degreeValid valid readB)) + (readWord_degreeValid valid readC)) + | u32ToField indices => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i word read + cases emitted + exact DegreeValid.singleton (readWord_degreeValid valid read) + +theorem emitOps_degreeValid {selector rank : Expr} {ops : List Bytecode.Op} {rows : Array RowExpr} + {column : Nat} {emission : OpsEmission} (valid : DegreeValid rows) + (emitted : emitOps selector rank ops rows column = some emission) : DegreeValid emission.values := by + induction ops generalizing rows column emission with + | nil => + cases emitted + exact valid + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + exact ih (emission := rest) (valid.append (emitOp_degreeValid valid firstEmitted)) restEmitted + +theorem emitEqZero_allocation (selector : Expr) (first : Nat) {input : RowExpr} + (valid : input.ZeroConstant) : + ((emitEqZero selector first input).used, (emitEqZero selector first input).output.degree) = + if input.degree = 0 then (0, 0) else (2, 1) := by + by_cases zero : input.degree = 0 + · obtain ⟨value, constant⟩ := valid zero + simp only [emitEqZero, constant, Expr.constantValue, zero, if_true, RowExpr.konst] + · cases constant : input.expr.constantValue <;> + simp only [emitEqZero, constant, zero, if_false, eqZeroRegular, mainCurrent, RowExpr.variable] + split + · rename_i impossible + exact False.elim (zero impossible) + · rfl + +end OpEmitter +end Aiur.NativeAIR diff --git a/Ix/Aiur/Proofs/OperationExpressions.lean b/Ix/Aiur/Proofs/OperationExpressions.lean new file mode 100644 index 000000000..bdef0f6f7 --- /dev/null +++ b/Ix/Aiur/Proofs/OperationExpressions.lean @@ -0,0 +1,1098 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FrontendExpressions + +/-! +Symbolic operation emission and its evaluation in the valued AIR model. +The symbolic outputs retain the frontend expression trees and independently +tracked degrees. Queries are the ungated contributions later assembled into +physical lookup slots. The call records retain the same expressions as those +queries and the six allocated rank-gap bytes. +-/ + +namespace Aiur.NativeAIR +namespace OpEmitter + +theorem list_mapM_read {read : α → Option β} {inputs : List α} {outputs : List β} + (evaluated : inputs.mapM read = some outputs) (index : Nat) : + (inputs[index]? >>= read) = outputs[index]? := by + induction inputs generalizing outputs index with + | nil => + simp only [List.mapM_nil, pure, Option.some.injEq] at evaluated + subst outputs + rfl + | cons input rest ih => + simp only [List.mapM_cons, bind, Option.bind, pure] at evaluated + cases head : read input <;> simp only [head] at evaluated + · cases evaluated + cases tail : rest.mapM read <;> simp only [tail] at evaluated + · cases evaluated + cases evaluated + cases index with + | zero => exact head + | succ index => exact ih tail index + +theorem array_mapM_read {read : α → Option β} {inputs : Array α} {outputs : Array β} + (evaluated : inputs.mapM read = some outputs) (index : Nat) : + (inputs[index]? >>= read) = outputs[index]? := by + have lists := congrArg (Functor.map Array.toList) evaluated + rw [Array.toList_mapM] at lists + simpa only [Array.getElem?_toList] using list_mapM_read lists index + +theorem array_mapM_size {read : α → Option β} {inputs : Array α} {outputs : Array β} + (evaluated : inputs.mapM read = some outputs) : outputs.size = inputs.size := by + have lists := congrArg (Functor.map Array.toList) evaluated + rw [Array.toList_mapM] at lists + exact Bytecode.AIR.list_mapM_some_length read inputs.toList outputs.toList lists + +theorem array_mapM_push (read : α → Option β) (inputs : Array α) (input : α) : + (inputs.push input).mapM read = (do + let outputs ← inputs.mapM read + let output ← read input + return outputs.push output) := by + simp only [Array.mapM_eq_mapM_toList, Array.toList_push, List.mapM_append, + List.mapM_cons, List.mapM_nil] + cases inputs.toList.mapM read <;> cases read input <;> + simp only [bind, Option.bind, pure, Functor.map, Option.map] + congr 1 + apply Array.toList_inj.mp + simp only [Array.toList_push] + +theorem list_mapM_of_map (items : List α) (input : α → β) (output : α → γ) + (read : β → Option γ) (evaluated : ∀ item ∈ items, read (input item) = some (output item)) : + (items.map input).mapM read = some (items.map output) := by + induction items with + | nil => rfl + | cons item rest ih => + simp only [List.map_cons, List.mapM_cons, evaluated item List.mem_cons_self, + ih (fun value member => evaluated value (List.mem_cons_of_mem _ member))] + rfl + +theorem array_mapM_ofFn {n : Nat} (input : Fin n → α) (output : Fin n → β) + (read : α → Option β) (evaluated : ∀ index, read (input index) = some (output index)) : + (Array.ofFn input).mapM read = some (Array.ofFn output) := by + rw [Array.mapM_eq_mapM_toList, Array.toList_ofFn] + have listEval : (List.ofFn input).mapM read = some (List.ofFn output) := by + simpa only [List.map_ofFn, Function.comp_id] using + list_mapM_of_map (List.ofFn id) input output read (fun index _ => evaluated index) + rw [listEval] + simp only [Functor.map, Option.map_some, List.toArray_ofFn] + +theorem list_mapM_ofFn {n : Nat} (input : Fin n → α) (output : Fin n → β) + (read : α → Option β) (evaluated : ∀ index, read (input index) = some (output index)) : + (List.ofFn input).mapM read = some (List.ofFn output) := by + simpa only [List.map_ofFn, Function.comp_id] using + list_mapM_of_map (List.ofFn id) input output read (fun index _ => evaluated index) + +theorem list_mapM_transform {read : α → Option β} {inputs : List α} {outputs : List β} + (evaluated : inputs.mapM read = some outputs) (input : α → γ) (output : β → δ) + (next : γ → Option δ) + (related : ∀ a b, read a = some b → next (input a) = some (output b)) : + (inputs.map input).mapM next = some (outputs.map output) := by + induction inputs generalizing outputs with + | nil => + simp only [List.mapM_nil, pure, Option.some.injEq] at evaluated + subst outputs + rfl + | cons a rest ih => + simp only [List.mapM_cons, bind, Option.bind, pure] at evaluated + cases head : read a <;> simp only [head] at evaluated + · cases evaluated + cases tail : rest.mapM read <;> simp only [tail] at evaluated + · cases evaluated + cases evaluated + simp only [List.map_cons, List.mapM_cons, related _ _ head, ih tail] + rfl + +theorem array_mapM_transform {read : α → Option β} {inputs : Array α} {outputs : Array β} + (evaluated : inputs.mapM read = some outputs) (input : α → γ) (output : β → δ) + (next : γ → Option δ) + (related : ∀ a b, read a = some b → next (input a) = some (output b)) : + (inputs.map input).mapM next = some (outputs.map output) := by + have lists := congrArg (Functor.map Array.toList) evaluated + rw [Array.toList_mapM] at lists + rw [Array.mapM_eq_mapM_toList, Array.toList_map, + list_mapM_transform lists input output next related] + simp only [Functor.map, Option.map_some, ← Array.toList_map, Array.toArray_toList] + +theorem list_mapM_refine {first : α → Option β} {second : α → Option γ} {evaluate : β → Option γ} + {inputs : List α} {outputs : List β} (selected : inputs.mapM first = some outputs) + (related : ∀ input output, first input = some output → + ∃ value, second input = some value ∧ evaluate output = some value) : + ∃ values, inputs.mapM second = some values ∧ outputs.mapM evaluate = some values := by + induction inputs generalizing outputs with + | nil => + simp only [List.mapM_nil, pure, Option.some.injEq] at selected + subst outputs + exact ⟨[], rfl, rfl⟩ + | cons input rest ih => + simp only [List.mapM_cons, bind, Option.bind, pure] at selected + cases head : first input <;> simp only [head] at selected + · cases selected + cases tail : rest.mapM first <;> simp only [tail] at selected + · cases selected + cases selected + obtain ⟨value, read, evaluated⟩ := related _ _ head + obtain ⟨values, reads, evaluations⟩ := ih tail + refine ⟨value :: values, ?_, ?_⟩ <;> + simp only [List.mapM_cons, read, evaluated, reads, evaluations, bind, Option.bind_some, pure] + +theorem array_mapM_refine {first : α → Option β} {second : α → Option γ} {evaluate : β → Option γ} + {inputs : Array α} {outputs : Array β} (selected : inputs.mapM first = some outputs) + (related : ∀ input output, first input = some output → + ∃ value, second input = some value ∧ evaluate output = some value) : + ∃ values, inputs.mapM second = some values ∧ outputs.mapM evaluate = some values := by + have lists := congrArg (Functor.map Array.toList) selected + rw [Array.toList_mapM] at lists + obtain ⟨values, reads, evaluations⟩ := list_mapM_refine lists related + refine ⟨values.toArray, ?_, ?_⟩ <;> + simp only [Array.mapM_eq_mapM_toList, reads, evaluations, Functor.map, Option.map_some] + +abbrev evalExpr (values : Values G) := Expr.eval goldilocksOps values + +def evalRows (values : Values G) (rows : Array RowExpr) : Option (Array AIR.RowValue) := + rows.mapM (RowExpr.eval values) + +theorem evalRows_empty (values : Values G) : evalRows values #[] = some #[] := + Array.mapM_empty _ + +theorem evalRows_singleton {values : Values G} {expr : RowExpr} {value : AIR.RowValue} + (reflected : expr.Reflects values value) : evalRows values #[expr] = some #[value] := by + change ((#[] : Array RowExpr).push expr).mapM (RowExpr.eval values) = some #[value] + rw [array_mapM_push, Array.mapM_empty, (RowExpr.reflects_iff_eval _ _ _).mp reflected] + rfl + +def rowExprs (rows : Array RowExpr) : Array Expr := rows.map RowExpr.expr + +def Normal (rows : Array RowExpr) : Prop := + ∀ row ∈ rows, row.expr.noConstantNegs = true + +theorem evalRows_values {values : Values G} {rows : Array RowExpr} {outputs : Array AIR.RowValue} + (evaluated : evalRows values rows = some outputs) : + (rowExprs rows).mapM (evalExpr values) = some (AIR.rowValues outputs) := by + apply array_mapM_transform evaluated RowExpr.expr AIR.RowValue.value + intro expr value result + exact ((RowExpr.reflects_iff_eval _ _ _).mpr result).1 + +theorem evalRows_read {values : Values G} {rows : Array RowExpr} {outputs : Array AIR.RowValue} + (evaluated : evalRows values rows = some outputs) {index : Nat} {row : RowExpr} + (present : rows[index]? = some row) : + ∃ output, outputs[index]? = some output ∧ row.Reflects values output := by + have read := array_mapM_read evaluated index + rw [present] at read + dsimp only [bind, Option.bind_some] at read + cases result : row.eval values with + | none => + have sizes := array_mapM_size evaluated + obtain ⟨bound, _⟩ := Array.getElem?_eq_some_iff.mp present + have absent := Array.getElem?_eq_none_iff.mp (read.symm.trans result) + omega + | some output => + exact ⟨output, read.symm.trans result, (RowExpr.reflects_iff_eval _ _ _).mpr result⟩ + +def select (rows : Array RowExpr) (indices : Array Nat) : Option (Array RowExpr) := + indices.mapM fun index => rows[index]? + +theorem select_reflects {values : Values G} {rows : Array RowExpr} {outputs : Array AIR.RowValue} + (evaluated : evalRows values rows = some outputs) {indices : Array Nat} {selected : Array RowExpr} + (read : select rows indices = some selected) : + ∃ results, indices.mapM (fun index => outputs[index]?) = some results ∧ + evalRows values selected = some results := by + apply array_mapM_refine read + intro index expr present + obtain ⟨value, present, reflected⟩ := evalRows_read evaluated present + exact ⟨value, present, (RowExpr.reflects_iff_eval _ _ _).mp reflected⟩ + +theorem select_values {rows : Array AIR.RowValue} {indices : Array Nat} {outputs : Array AIR.RowValue} + (read : indices.mapM (fun index => rows[index]?) = some outputs) : + Bytecode.AIR.readValues (AIR.rowValues rows) indices = some (AIR.rowValues outputs) := by + have result := array_mapM_transform read id AIR.RowValue.value + (fun index => (AIR.rowValues rows)[index]?) (fun _ _ present => AIR.rowValues_read present) + simpa only [Array.map_id, Bytecode.AIR.readValues, AIR.rowValues] using result + +theorem select_normal {rows : Array RowExpr} (normal : Normal rows) + {indices : Array Nat} {selected : Array RowExpr} (read : select rows indices = some selected) : + Normal selected := by + intro expr member + obtain ⟨index, bound, equal⟩ := Array.mem_iff_getElem.mp member + have selectedRead : selected[index]? = some expr := Array.getElem?_eq_some_iff.mpr ⟨bound, equal⟩ + have input := array_mapM_read read index + rw [selectedRead] at input + cases indexRead : indices[index]? with + | none => simp only [indexRead, bind, Option.bind_none, reduceCtorEq] at input + | some inputIndex => + simp only [indexRead, bind, Option.bind_some] at input + exact normal expr (Array.mem_of_getElem? input) + +theorem array_ofFn_getD (items : Array α) (fallback : α) {count : Nat} (size : items.size = count) : + Array.ofFn (fun index : Fin count => items[index.val]?.getD fallback) = items := by + apply Array.ext (by simp only [Array.size_ofFn, size]) + intro index _ bound + simp only [Array.getElem_ofFn, getElem?_pos items index bound, Option.getD_some] + +theorem array_map_getD_of_mapM {α : Type} {items : Array α} {indices : Array Nat} {selected : Array α} + (fallback : α) (read : indices.mapM (fun index => items[index]?) = some selected) : + indices.map (fun index => items[index]?.getD fallback) = selected := by + have size := array_mapM_size read + apply Array.ext (by simp only [Array.size_map, size]) + intro index inputBound outputBound + have bound : index < indices.size := by simpa only [Array.size_map] using inputBound + have result := array_mapM_read read index + simp only [getElem?_pos indices index bound, getElem?_pos selected index outputBound, + bind, Option.bind_some] at result + simp only [Array.getElem_map, result, Option.getD_some] + +theorem evalRows_getD {values : Values G} {rows : Array RowExpr} {outputs : Array AIR.RowValue} + (evaluated : evalRows values rows = some outputs) {index : Nat} (bound : index < rows.size) : + (rows[index]?.getD (.konst 0)).Reflects values (outputs[index]?.getD (.konst 0)) := by + have present : rows[index]? = some rows[index] := getElem?_pos rows index bound + obtain ⟨value, output, reflected⟩ := evalRows_read evaluated present + simpa only [present, output, Option.getD_some] using reflected + +def advice (first count : Nat) : Array RowExpr := + Array.ofFn fun index : Fin count => mainCurrent (first + index.val) + +theorem advice_eval (values : Values G) (row : Nat → G) (first count : Nat) + (reads : ∀ index < count, + (values.columns .main .current)[first + index]? = some (row index)) : + evalRows values (advice first count) = some (AIR.rowAdvice row 0 count) := by + apply array_mapM_ofFn + intro index + exact (RowExpr.reflects_iff_eval _ _ _).mp + (RowExpr.variable_reflects values (by simpa only [Nat.zero_add] using reads index.val index.isLt)) + +theorem advice_normal (first count : Nat) : Normal (advice first count) := by + intro expr member + obtain ⟨index, rfl⟩ := Array.mem_ofFn.mp member + rfl + +structure CallExpr where + function : Nat + inputs : Array Expr + outputs : Array Expr + rank : Expr + gap : Fin 6 → Expr + +def CallExpr.eval (values : Values G) (call : CallExpr) : + Option (Bytecode.AIR.Call × (Fin 6 → G)) := do + let inputs ← call.inputs.mapM (evalExpr values) + let outputs ← call.outputs.mapM (evalExpr values) + let rank ← call.rank.eval goldilocksOps values + let gap ← (Array.ofFn call.gap).mapM (evalExpr values) + return (⟨call.function, inputs, outputs, rank⟩, fun index => gap[index.val]?.getD 0) + +theorem CallExpr.eval_of {values : Values G} {call : CallExpr} {inputs outputs : Array G} + {rank : G} {gap : Fin 6 → G} + (inputEval : call.inputs.mapM (evalExpr values) = some inputs) + (outputEval : call.outputs.mapM (evalExpr values) = some outputs) + (rankEval : evalExpr values call.rank = some rank) + (gapEval : ∀ index, evalExpr values (call.gap index) = some (gap index)) : + call.eval values = some (⟨call.function, inputs, outputs, rank⟩, gap) := by + have bytes := array_mapM_ofFn call.gap gap (evalExpr values) gapEval + simp only [CallExpr.eval, inputEval, outputEval, rankEval, bytes, bind, Option.bind_some, pure] + congr 2 + funext index + simp only [Array.getElem?_ofFn, index.isLt, dif_pos, Option.getD_some] + +structure Emission where + outputs : Array RowExpr := #[] + used : Nat := 0 + equations : List Expr := [] + queries : List (List Expr) := [] + calls : List CallExpr := [] + +def Emission.eval (values : Values G) (emission : Emission) : Option AIR.OpEmission := do + let outputs ← evalRows values emission.outputs + let equations ← emission.equations.mapM (evalExpr values) + let queries ← emission.queries.mapM (List.mapM (evalExpr values)) + let calls ← emission.calls.mapM (CallExpr.eval values) + return ⟨outputs, emission.used, equations, queries, calls⟩ + +def fromScalar (emission : ScalarEmission) : Emission := + { outputs := #[emission.output], used := emission.used, equations := emission.equations } + +def emitAdvice (first count : Nat) : Emission := + { outputs := advice first count, used := count } + +theorem emitAdvice_reflects (values : Values G) (row : Nat → G) (first count : Nat) + (reads : ∀ index < count, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitAdvice first count).eval values = some (AIR.emitAdvice row count) := by + simp only [Emission.eval, emitAdvice, advice_eval values row first count reads, + List.mapM_nil, bind, Option.bind_some, pure, AIR.emitAdvice] + +theorem Emission.eval_of {values : Values G} {emission : Emission} {result : AIR.OpEmission} + (outputs : evalRows values emission.outputs = some result.outputs) + (used : emission.used = result.used) + (equations : emission.equations.mapM (evalExpr values) = some result.equations) + (queries : emission.queries.mapM (List.mapM (evalExpr values)) = some result.queries) + (calls : emission.calls.mapM (CallExpr.eval values) = some result.calls) : + emission.eval values = some result := by + simp only [Emission.eval, outputs, equations, queries, calls, used, bind, Option.bind_some, pure] + +def emitByte1 (first : Nat) (kind : AIR.Byte1Kind) (input : RowExpr) : Emission := + let outputs := advice first kind.outputSize + { outputs, used := kind.outputSize, + queries := [[.konst kind.channel, input.expr] ++ (rowExprs outputs).toList] } + +theorem emitByte1_reflects (values : Values G) (row : Nat → G) (first : Nat) (kind : AIR.Byte1Kind) + {input : RowExpr} {value : AIR.RowValue} (inputRef : input.Reflects values value) + (reads : ∀ index < kind.outputSize, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitByte1 first kind input).eval values = + some { outputs := AIR.rowAdvice row 0 kind.outputSize, used := kind.outputSize, + queries := [AIR.byte1Request kind value.value + (AIR.rowValues (AIR.rowAdvice row 0 kind.outputSize))] } := by + have outputs := advice_eval values row first kind.outputSize reads + have raw := congrArg (Functor.map Array.toList) (evalRows_values outputs) + rw [Array.toList_mapM] at raw + simp only [Functor.map, Option.map_some] at raw + apply Emission.eval_of outputs rfl rfl ?_ rfl + simp only [emitByte1, List.mapM_cons, List.mapM_nil, List.cons_append, List.nil_append, + inputRef.1, show evalExpr values (.konst kind.channel) = some kind.channel from rfl, + raw, bind, Option.bind_some, pure, AIR.byte1Request] + +def byteCarry (first : Nat) (subtract : Bool) (left right : RowExpr) : RowExpr := + let low := (mainCurrent first).expr + let numerator := if subtract then (low.frontAdd right.expr).frontSub left.expr + else (left.expr.frontAdd right.expr).frontSub low + ⟨numerator.frontMul (.konst AIR.inverse256), max (max left.degree right.degree) 1⟩ + +theorem scale_isConstant (expr : Expr) {coefficient : G} (nonzero : coefficient ≠ 0) : + (expr.frontMul (.konst coefficient)).isConstant = expr.isConstant := by + have known := expr.isConstant_eq + have notZero : (coefficient == 0) = false := by simpa only [beq_eq_false_iff_ne] using nonzero + cases constant : expr.constantValue with + | none => + simp only [constant, Option.isSome_none] at known + simp only [Expr.frontMul, constant, + show (Expr.konst coefficient).constantValue = some coefficient from rfl, + notZero, Bool.false_eq_true, if_false] + split + · rfl + · exact known.symm + | some value => + simp only [constant, Option.isSome_some] at known + simp only [Expr.frontMul, constant, + show (Expr.konst coefficient).constantValue = some coefficient from rfl] + exact known.symm + +theorem byteCarry_reflects (values : Values G) (row : Nat → G) (first : Nat) (subtract : Bool) + {left right : RowExpr} {a b : AIR.RowValue} + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) + (leftNormal : left.expr.noConstantNegs = true) + (read : (values.columns .main .current)[first]? = some (row 0)) : + (byteCarry first subtract left right).Reflects values + ⟨(if subtract then row 0 + b.value - a.value else a.value + b.value - row 0) * AIR.inverse256, + max (max a.degree b.degree) 1, false⟩ := by + have low : evalExpr values (mainCurrent first).expr = some (row 0) := read + have coeff : evalExpr values (.konst AIR.inverse256) = some AIR.inverse256 := rfl + have invNonzero : AIR.inverse256 ≠ 0 := by decide +kernel + unfold RowExpr.Reflects + cases subtract <;> simp only [byteCarry, Bool.false_eq_true, if_false, if_true] + all_goals refine ⟨?_, ?_, ?_⟩ + · exact Expr.frontMul_eval goldilocksLaws values + (Expr.frontSub_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values leftRef.1 rightRef.1) low) coeff + · rw [leftRef.2.1, rightRef.2.1] + · rw [scale_isConstant _ invNonzero, Expr.frontSub_isConstant _ _ (by rfl)] + exact Bool.and_false _ + · exact Expr.frontMul_eval goldilocksLaws values + (Expr.frontSub_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values low rightRef.1) leftRef.1) coeff + · rw [leftRef.2.1, rightRef.2.1] + · rw [scale_isConstant _ invNonzero, Expr.frontSub_isConstant _ _ leftNormal, + Expr.frontAdd_isConstant] + rfl + +theorem byteCarry_normal (first : Nat) (subtract : Bool) {left right : RowExpr} + (leftNormal : left.expr.noConstantNegs = true) + (rightNormal : right.expr.noConstantNegs = true) : + (byteCarry first subtract left right).expr.noConstantNegs = true := by + cases subtract + · exact Expr.frontMul_noConstantNegs + (Expr.frontSub_noConstantNegs (Expr.frontAdd_noConstantNegs leftNormal rightNormal) rfl) rfl + · exact Expr.frontMul_noConstantNegs + (Expr.frontSub_noConstantNegs (Expr.frontAdd_noConstantNegs rfl rightNormal) leftNormal) rfl + +def emitByte2 (first : Nat) (kind : AIR.Byte2Kind) (left right : RowExpr) : Emission := + let allocated := advice first kind.outputSize + let outputs := match kind with + | .add => allocated.push (byteCarry first false left right) + | .sub => allocated.push (byteCarry first true left right) + | _ => allocated + { outputs, used := kind.outputSize, + queries := [[.konst kind.channel, left.expr, right.expr] ++ (rowExprs allocated).toList] } + +theorem emitByte2_reflects (values : Values G) (row : Nat → G) (first : Nat) (kind : AIR.Byte2Kind) + {left right : RowExpr} {a b : AIR.RowValue} + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) + (leftNormal : left.expr.noConstantNegs = true) + (reads : ∀ index < kind.outputSize, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitByte2 first kind left right).eval values = + some { outputs := kind.extendRowOutputs a b (AIR.rowAdvice row 0 kind.outputSize), + used := kind.outputSize, + queries := [AIR.byte2Request kind a.value b.value + (AIR.rowValues (AIR.rowAdvice row 0 kind.outputSize))] } := by + have allocated := advice_eval values row first kind.outputSize reads + have raw := congrArg (Functor.map Array.toList) (evalRows_values allocated) + rw [Array.toList_mapM] at raw + simp only [Functor.map, Option.map_some] at raw + apply Emission.eval_of ?_ rfl rfl ?_ rfl + · cases kind <;> try exact allocated + all_goals + have firstRead : (values.columns .main .current)[first]? = some (row 0) := by + simpa only [Nat.add_zero] using reads 0 (by decide) + have carry (subtract : Bool) := (RowExpr.reflects_iff_eval _ _ _).mp + (byteCarry_reflects values row first subtract leftRef rightRef leftNormal firstRead) + simp only [emitByte2, AIR.Byte2Kind.extendRowOutputs, AIR.Byte2Kind.outputSize, evalRows, array_mapM_push, + show (advice first 1).mapM (RowExpr.eval values) = some (AIR.rowAdvice row 0 1) from allocated, + carry, bind, Option.bind_some, pure, AIR.rowValues, AIR.rowAdvice, + Array.map_ofFn, Array.getElem?_ofFn, Nat.zero_lt_succ, dif_pos, Option.getD_some, + AIR.RowValue.variable, Nat.zero_add, Function.comp_def, Bool.false_eq_true, if_false, if_true] + · simp only [emitByte2, List.mapM_cons, List.mapM_nil, List.cons_append, List.nil_append, + leftRef.1, rightRef.1, show evalExpr values (.konst kind.channel) = some kind.channel from rfl, + raw, bind, Option.bind_some, pure, AIR.byte2Request] + +theorem emitByte2_normal (first : Nat) (kind : AIR.Byte2Kind) {left right : RowExpr} + (leftNormal : left.expr.noConstantNegs = true) + (rightNormal : right.expr.noConstantNegs = true) : + Normal (emitByte2 first kind left right).outputs := by + cases kind <;> try exact advice_normal _ _ + all_goals + intro expr member + rcases Array.mem_push.mp member with member | rfl + · exact advice_normal _ _ expr member + · exact byteCarry_normal _ _ leftNormal rightNormal + +/-- The native four-term, little-endian left fold, including its initial +zero and unit coefficient. Metadata follows the same maximum fold. -/ +def packFour (bytes : Fin 4 → RowExpr) : RowExpr := + ((((RowExpr.konst 0).add ((bytes 0).mul (.konst (G.ofNat (256^0))))).add + ((bytes 1).mul (.konst (G.ofNat (256^1))))).add + ((bytes 2).mul (.konst (G.ofNat (256^2))))).add + ((bytes 3).mul (.konst (G.ofNat (256^3)))) + +theorem scale_reflects (values : Values G) {expr : RowExpr} {value : AIR.RowValue} + (reflected : expr.Reflects values value) (coefficient : G) (nonzero : coefficient ≠ 0) : + (expr.mul (.konst coefficient)).Reflects values + ⟨value.value * coefficient, value.degree, value.constant⟩ := by + refine ⟨Expr.frontMul_eval goldilocksLaws values reflected.1 rfl, ?_, ?_⟩ + · exact reflected.2.1 + · exact (scale_isConstant expr.expr nonzero).trans reflected.2.2 + +private def packFourValue (results : Fin 4 → AIR.RowValue) : AIR.RowValue := + ((((AIR.RowValue.konst 0).add + ⟨(results 0).value * G.ofNat (256^0), (results 0).degree, (results 0).constant⟩).add + ⟨(results 1).value * G.ofNat (256^1), (results 1).degree, (results 1).constant⟩).add + ⟨(results 2).value * G.ofNat (256^2), (results 2).degree, (results 2).constant⟩).add + ⟨(results 3).value * G.ofNat (256^3), (results 3).degree, (results 3).constant⟩ + +theorem list_ofFn_four (values : Fin 4 → α) : + List.ofFn values = [values 0, values 1, values 2, values 3] := by + simp only [List.ofFn_succ, List.ofFn_zero, Fin.succ_zero_eq_one, + show (1 : Fin 2).succ = (2 : Fin 3) from rfl, + show (1 : Fin 3).succ = (2 : Fin 4) from rfl, + show (2 : Fin 3).succ = (3 : Fin 4) from rfl] + +theorem list_foldl_zip_four (values : Fin 4 → α) (step : β → α × Nat → β) (initial : β) : + (List.ofFn values).zipIdx.foldl step initial = + step (step (step (step initial (values 0, 0)) (values 1, 1)) (values 2, 2)) (values 3, 3) := by + rw [list_ofFn_four] + rfl + +private theorem rowValue_ext {left right : AIR.RowValue} + (value : left.value = right.value) (degree : left.degree = right.degree) + (constant : left.constant = right.constant) : left = right := by + cases left + cases right + cases value + cases degree + cases constant + rfl + +private theorem packFourValue_eq (results : Fin 4 → AIR.RowValue) : + packFourValue results = AIR.RowValue.pack (Array.ofFn results) := by + apply rowValue_ext + · change (0 + (results 0).value * G.ofNat (256^0) + (results 1).value * G.ofNat (256^1) + + (results 2).value * G.ofNat (256^2) + (results 3).value * G.ofNat (256^3)) = + ((Array.ofFn results).map AIR.RowValue.value).toList.zipIdx.foldl + (fun value (byte, index) => value + byte * G.ofNat (256^index)) 0 + rw [Array.map_ofFn, Array.toList_ofFn] + exact (list_foldl_zip_four (fun index => (results index).value) + (fun value (byte, index) => value + byte * G.ofNat (256^index)) 0).symm + · change max (max (max (max 0 (results 0).degree) (results 1).degree) (results 2).degree) + (results 3).degree = (Array.ofFn results).toList.foldl (fun d v => max d v.degree) 0 + simp only [Array.toList_ofFn, list_ofFn_four, List.foldl_cons, List.foldl_nil] + · change ((((true && (results 0).constant) && (results 1).constant) && (results 2).constant) && + (results 3).constant) = (Array.ofFn results).all AIR.RowValue.constant + simp only [← Array.all_toList, Array.toList_ofFn, list_ofFn_four, List.all_cons, + List.all_nil, Bool.true_and, Bool.and_true, Bool.and_assoc] + +theorem packFour_reflects (values : Values G) (bytes : Fin 4 → RowExpr) + (results : Fin 4 → AIR.RowValue) + (reflected : ∀ index, (bytes index).Reflects values (results index)) : + (packFour bytes).Reflects values (AIR.RowValue.pack (Array.ofFn results)) := by + have r0 := scale_reflects values (reflected 0) (G.ofNat (256^0)) (by decide +kernel) + have r1 := scale_reflects values (reflected 1) (G.ofNat (256^1)) (by decide +kernel) + have r2 := scale_reflects values (reflected 2) (G.ofNat (256^2)) (by decide +kernel) + have r3 := scale_reflects values (reflected 3) (G.ofNat (256^3)) (by decide +kernel) + have result := RowExpr.add_reflects values + (RowExpr.add_reflects values + (RowExpr.add_reflects values + (RowExpr.add_reflects values (RowExpr.konst_reflects values 0) r0) r1) r2) r3 + change (packFour bytes).Reflects values (packFourValue results) at result + rw [packFourValue_eq] at result + exact result + +theorem packFour_normal (bytes : Fin 4 → RowExpr) + (normal : ∀ index, (bytes index).expr.noConstantNegs = true) : + (packFour bytes).expr.noConstantNegs = true := by + exact Expr.frontAdd_noConstantNegs + (Expr.frontAdd_noConstantNegs + (Expr.frontAdd_noConstantNegs + (Expr.frontAdd_noConstantNegs rfl + (Expr.frontMul_noConstantNegs (normal 0) rfl)) + (Expr.frontMul_noConstantNegs (normal 1) rfl)) + (Expr.frontMul_noConstantNegs (normal 2) rfl)) + (Expr.frontMul_noConstantNegs (normal 3) rfl) + +def readWord (rows : Array RowExpr) (indices : Array Nat) : Option RowExpr := do + if indices.size ≠ 4 then none else do + let bytes ← select rows indices + return packFour fun index => bytes[index.val]?.getD (.konst 0) + +theorem readWord_reflects {values : Values G} {rows : Array RowExpr} {outputs : Array AIR.RowValue} + (evaluated : evalRows values rows = some outputs) {indices : Array Nat} {word : RowExpr} + (read : readWord rows indices = some word) : + ∃ value, AIR.readRowWord outputs indices = some value ∧ word.Reflects values value := by + simp only [readWord, bind, Option.bind] at read + split at read + · cases read + next size => + have width : indices.size = 4 := by omega + cases selected : select rows indices <;> simp only [selected] at read + · cases read + next bytes => + cases read + have byteSize := (array_mapM_size selected).trans width + obtain ⟨results, resultRead, resultEval⟩ := select_reflects evaluated selected + have resultSize := (array_mapM_size resultRead).trans width + have reflected := packFour_reflects values + (fun index => bytes[index.val]?.getD (.konst 0)) + (fun index => results[index.val]?.getD (.konst 0)) + (fun index => evalRows_getD resultEval (by omega)) + rw [array_ofFn_getD results (.konst 0) resultSize] at reflected + refine ⟨AIR.RowValue.pack results, ?_, reflected⟩ + simp only [AIR.readRowWord, Bytecode.AIR.readWord, if_neg size, + select_values resultRead, bind, Option.bind_some] + rw [array_map_getD_of_mapM (.konst 0) resultRead] + rfl + +theorem readWord_normal {rows : Array RowExpr} (normal : Normal rows) + {indices : Array Nat} {word : RowExpr} (read : readWord rows indices = some word) : + word.expr.noConstantNegs = true := by + simp only [readWord, bind, Option.bind] at read + split at read + · cases read + next size => + cases selected : select rows indices <;> simp only [selected] at read + · cases read + next bytes => + cases read + apply packFour_normal + intro index + have byteSize := array_mapM_size selected + have bound : index.val < bytes.size := by omega + simp only [getElem?_pos bytes index.val bound, Option.getD_some] + exact select_normal normal selected _ (Array.getElem_mem ..) + +def packedAdvice (first : Nat) : RowExpr := + packFour fun index => mainCurrent (first + index.val) + +theorem packedAdvice_reflects (values : Values G) (row : Nat → G) (first : Nat) + (reads : ∀ index < 4, + (values.columns .main .current)[first + index]? = some (row index)) : + (packedAdvice first).Reflects values (AIR.RowValue.pack (AIR.rowAdvice row 0 4)) := by + apply packFour_reflects + intro index + apply RowExpr.variable_reflects values + simpa only [Nat.zero_add] using reads index.val index.isLt + +theorem packedAdvice_normal (first : Nat) : (packedAdvice first).expr.noConstantNegs = true := + packFour_normal _ (fun _ => rfl) + +theorem packed_advice_not_constant (row : Nat → G) : + (AIR.RowValue.pack (AIR.rowAdvice row 0 4)).constant = false := by + change (Array.ofFn (fun index : Fin 4 => AIR.RowValue.variable (row (0 + index.val)))).all + AIR.RowValue.constant = false + simp only [← Array.all_toList, Array.toList_ofFn, list_ofFn_four, + List.all_cons, List.all_nil, AIR.RowValue.variable, Bool.false_and] + +def emitWordSum (first : Nat) (sum : RowExpr) : Emission := + let packed := packedAdvice first + { outputs := (advice first 4).push ((sum.sub packed).mul (.konst 0xfffffffe00000002)), used := 4 } + +theorem emitWordSum_reflects (values : Values G) (row : Nat → G) (first : Nat) + {sum : RowExpr} {value : AIR.RowValue} (sumRef : sum.Reflects values value) + (reads : ∀ index < 4, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitWordSum first sum).eval values = + some { outputs := (AIR.rowAdvice row 0 4).push + ⟨(value.value - (AIR.RowValue.pack (AIR.rowAdvice row 0 4)).value) * 0xfffffffe00000002, + max value.degree (AIR.RowValue.pack (AIR.rowAdvice row 0 4)).degree, false⟩, + used := 4 } := by + have allocated := advice_eval values row first 4 reads + have packed := packedAdvice_reflects values row first reads + have difference := RowExpr.sub_reflects values sumRef packed (packedAdvice_normal first) + have carry := scale_reflects values difference 0xfffffffe00000002 (by decide +kernel) + have absent := packed_advice_not_constant row + have carryEval := (RowExpr.reflects_iff_eval _ _ _).mp carry + have constant : (value.sub (AIR.RowValue.pack (AIR.rowAdvice row 0 4))).constant = false := by + change (value.constant && (AIR.RowValue.pack (AIR.rowAdvice row 0 4)).constant) = false + rw [absent, Bool.and_false] + rw [constant] at carryEval + apply Emission.eval_of ?_ rfl rfl rfl rfl + simp only [emitWordSum, evalRows, array_mapM_push, + show (advice first 4).mapM (RowExpr.eval values) = some (AIR.rowAdvice row 0 4) from allocated, + carryEval, bind, Option.bind_some, pure] + rfl + +theorem emitWordSum_normal (first : Nat) {sum : RowExpr} + (normal : sum.expr.noConstantNegs = true) : Normal (emitWordSum first sum).outputs := by + intro expr member + rcases Array.mem_push.mp member with member | rfl + · exact advice_normal _ _ expr member + · exact Expr.frontMul_noConstantNegs + (Expr.frontSub_noConstantNegs normal (packedAdvice_normal first)) rfl + +theorem packed_advice_value (row : Nat → G) : + (AIR.RowValue.pack (AIR.rowAdvice row 0 4)).value = AIR.pack4 (fun index => row index.val) := by + change ((Array.ofFn (fun index : Fin 4 => AIR.RowValue.variable (row (0 + index.val)))).map + AIR.RowValue.value).toList.zipIdx.foldl (fun acc (byte, index) => acc + byte * G.ofNat (256^index)) 0 = _ + rw [Array.map_ofFn, Array.toList_ofFn, list_foldl_zip_four] + change 0 + row 0 * G.ofNat (256^0) + row 1 * G.ofNat (256^1) + row 2 * G.ofNat (256^2) + + row 3 * G.ofNat (256^3) = AIR.pack4 (fun index => row index.val) + rw [show G.ofNat (256^0) = (1 : G) from by decide +kernel, + show G.ofNat (256^1) = (256 : G) from by decide +kernel, + show G.ofNat (256^2) = (65536 : G) from by decide +kernel, + show G.ofNat (256^3) = (16777216 : G) from by decide +kernel, + G.mul_one, G.zero_add, G.mul_comm (row 1) 256, G.mul_comm (row 2) 65536, + G.mul_comm (row 3) 16777216] + rfl + +def carryStep (x y z previous : Expr) : Expr := + (((x.frontAdd y).frontAdd previous).frontSub z).frontMul (.konst AIR.inverse256) + +theorem carryStep_eval {values : Values G} {x y z previous : Expr} {a b c d : G} + (xe : evalExpr values x = some a) (ye : evalExpr values y = some b) + (ze : evalExpr values z = some c) (pe : evalExpr values previous = some d) : + evalExpr values (carryStep x y z previous) = some (AIR.carryStep a b c d) := + Expr.frontMul_eval goldilocksLaws values + (Expr.frontSub_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values xe ye) pe) ze) rfl + +theorem carryStep_normal {x y z previous : Expr} + (xn : x.noConstantNegs = true) (yn : y.noConstantNegs = true) + (zn : z.noConstantNegs = true) (pn : previous.noConstantNegs = true) : + (carryStep x y z previous).noConstantNegs = true := + Expr.frontMul_noConstantNegs + (Expr.frontSub_noConstantNegs + (Expr.frontAdd_noConstantNegs (Expr.frontAdd_noConstantNegs xn yn) pn) zn) rfl + +theorem carryStep_not_constant {x y z previous : Expr} + (zn : z.noConstantNegs = true) (zc : z.isConstant = false) : + (carryStep x y z previous).isConstant = false := by + rw [carryStep, scale_isConstant _ (show AIR.inverse256 ≠ 0 from by decide +kernel), + Expr.frontSub_isConstant _ _ zn, zc, Bool.and_false] + +def carries (x y z : Fin 4 → Expr) : Fin 5 → Expr := + let c1 := carryStep (x 0) (y 0) (z 0) (.konst 1) + let c2 := carryStep (x 1) (y 1) (z 1) c1 + let c3 := carryStep (x 2) (y 2) (z 2) c2 + let c4 := carryStep (x 3) (y 3) (z 3) c3 + fun index => match index with + | 0 => .konst 1 + | 1 => c1 + | 2 => c2 + | 3 => c3 + | 4 => c4 + +theorem carries_eval {values : Values G} {x y z : Fin 4 → Expr} {a b c : Fin 4 → G} + (xe : ∀ index, evalExpr values (x index) = some (a index)) + (ye : ∀ index, evalExpr values (y index) = some (b index)) + (ze : ∀ index, evalExpr values (z index) = some (c index)) : + ∀ index, evalExpr values (carries x y z index) = some (AIR.u32Carries a b c index) := by + have c1 := carryStep_eval (xe 0) (ye 0) (ze 0) + (show evalExpr values (.konst 1) = some 1 from rfl) + have c2 := carryStep_eval (xe 1) (ye 1) (ze 1) c1 + have c3 := carryStep_eval (xe 2) (ye 2) (ze 2) c2 + have c4 := carryStep_eval (xe 3) (ye 3) (ze 3) c3 + intro ⟨index, bound⟩ + have options : index = 0 ∨ index = 1 ∨ index = 2 ∨ index = 3 ∨ index = 4 := by omega + rcases options with rfl | rfl | rfl | rfl | rfl + · rfl + · exact c1 + · exact c2 + · exact c3 + · exact c4 + +theorem carries_normal {x y z : Fin 4 → Expr} + (xn : ∀ index, (x index).noConstantNegs = true) + (yn : ∀ index, (y index).noConstantNegs = true) + (zn : ∀ index, (z index).noConstantNegs = true) : + ∀ index, (carries x y z index).noConstantNegs = true := by + have first := carryStep_normal (xn 0) (yn 0) (zn 0) (show (Expr.konst 1).noConstantNegs = true from rfl) + have second := carryStep_normal (xn 1) (yn 1) (zn 1) first + have third := carryStep_normal (xn 2) (yn 2) (zn 2) second + have fourth := carryStep_normal (xn 3) (yn 3) (zn 3) third + intro ⟨index, bound⟩ + have options : index = 0 ∨ index = 1 ∨ index = 2 ∨ index = 3 ∨ index = 4 := by omega + rcases options with rfl | rfl | rfl | rfl | rfl + · rfl + · exact first + · exact second + · exact third + · exact fourth + +def packSix (bytes : Fin 6 → Expr) : Expr := + ((((((Expr.konst 0).frontAdd ((bytes 0).frontMul (.konst 1))).frontAdd + ((bytes 1).frontMul (.konst 256))).frontAdd ((bytes 2).frontMul (.konst 65536))).frontAdd + ((bytes 3).frontMul (.konst 16777216))).frontAdd + ((bytes 4).frontMul (.konst 4294967296))).frontAdd + ((bytes 5).frontMul (.konst 1099511627776)) + +private def packSixValue (bytes : Fin 6 → G) : G := + 0 + bytes 0 * 1 + bytes 1 * 256 + bytes 2 * 65536 + bytes 3 * 16777216 + + bytes 4 * 4294967296 + bytes 5 * 1099511627776 + +private theorem packSixValue_eq (bytes : Fin 6 → G) : packSixValue bytes = AIR.packRank bytes := by + unfold packSixValue AIR.packRank + rw [G.mul_one, G.zero_add, G.mul_comm (bytes 1) 256, G.mul_comm (bytes 2) 65536, + G.mul_comm (bytes 3) 16777216, G.mul_comm (bytes 4) 4294967296, + G.mul_comm (bytes 5) 1099511627776] + +theorem packSix_eval (values : Values G) (bytes : Fin 6 → Expr) (results : Fin 6 → G) + (evaluated : ∀ index, evalExpr values (bytes index) = some (results index)) : + evalExpr values (packSix bytes) = some (AIR.packRank results) := by + have term (index : Fin 6) (coefficient : G) := Expr.frontMul_eval goldilocksLaws values + (evaluated index) (show evalExpr values (.konst coefficient) = some coefficient from rfl) + have packed := Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values + (show evalExpr values (.konst 0) = some 0 from rfl) (term 0 1)) + (term 1 256)) (term 2 65536)) (term 3 16777216)) (term 4 4294967296)) + (term 5 1099511627776) + change evalExpr values (packSix bytes) = some (packSixValue results) at packed + rw [packSixValue_eq] at packed + exact packed + +def rangePair (left right : Expr) : List Expr := [.konst 11, left, right] + +def rangeSix (bytes : Fin 6 → Expr) : List (List Expr) := + [rangePair (bytes 0) (bytes 1), rangePair (bytes 2) (bytes 3), rangePair (bytes 4) (bytes 5)] + +theorem rangePair_eval {values : Values G} {left right : Expr} {a b : G} + (leftEval : evalExpr values left = some a) (rightEval : evalExpr values right = some b) : + (rangePair left right).mapM (evalExpr values) = some (AIR.rangeMessage (a, b)) := by + simp only [rangePair, List.mapM_cons, List.mapM_nil, leftEval, rightEval, + show evalExpr values (.konst 11) = some 11 from rfl, bind, Option.bind_some, pure] + rfl + +theorem rangeSix_eval {values : Values G} (bytes : Fin 6 → Expr) (results : Fin 6 → G) + (evaluated : ∀ index, evalExpr values (bytes index) = some (results index)) : + (rangeSix bytes).mapM (List.mapM (evalExpr values)) = + some ((AIR.rankByteQueries results).map AIR.rangeMessage) := by + simp only [rangeSix, List.mapM_cons, List.mapM_nil, + rangePair_eval (evaluated 0) (evaluated 1), rangePair_eval (evaluated 2) (evaluated 3), + rangePair_eval (evaluated 4) (evaluated 5), bind, Option.bind_some, pure] + rfl + +def emitCall (_selector rank : Expr) (first function : Nat) (inputs : Array RowExpr) + (size : Nat) : Emission := + let outputs := advice first size + let gap : Fin 6 → Expr := fun index => (mainCurrent (first + size + index.val)).expr + let child := (rank.frontAdd (.konst 1)).frontAdd (packSix gap) + { outputs, used := size + 6, + queries := ([.konst 0, .konst (G.ofNat function)] ++ + (rowExprs inputs).toList ++ (rowExprs outputs).toList ++ [child]) :: rangeSix gap, + calls := [⟨function, rowExprs inputs, rowExprs outputs, child, gap⟩] } + +theorem emitCall_reflects (values : Values G) (row : Nat → G) (first function size : Nat) + {selector rank : Expr} {s r : G} {inputs : Array RowExpr} {arguments : Array AIR.RowValue} + (_selectorEval : evalExpr values selector = some s) (rankEval : evalExpr values rank = some r) + (inputEval : evalRows values inputs = some arguments) + (reads : ∀ index < size + 6, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitCall selector rank first function inputs size).eval values = + some { outputs := AIR.rowAdvice row 0 size, used := size + 6, + queries := AIR.functionMessage + ⟨function, AIR.rowValues arguments, AIR.rowValues (AIR.rowAdvice row 0 size), + r + 1 + AIR.packRank (fun index => row (size + index.val))⟩ :: + (AIR.rankByteQueries (fun index => row (size + index.val))).map AIR.rangeMessage, + calls := [(⟨function, AIR.rowValues arguments, AIR.rowValues (AIR.rowAdvice row 0 size), + r + 1 + AIR.packRank (fun index => row (size + index.val))⟩, + fun index => row (size + index.val))] } := by + have outputs := advice_eval values row first size (fun index bound => reads index (by omega)) + have gap (index : Fin 6) : + evalExpr values (mainCurrent (first + size + index.val)).expr = + some (row (size + index.val)) := by + change (values.columns .main .current)[first + size + index.val]? = _ + simpa only [Nat.add_assoc] using reads (size + index.val) (by omega) + have child := Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values rankEval + (show evalExpr values (.konst 1) = some 1 from rfl)) + (packSix_eval values _ _ gap) + have args := congrArg (Functor.map Array.toList) (evalRows_values inputEval) + have outs := congrArg (Functor.map Array.toList) (evalRows_values outputs) + rw [Array.toList_mapM] at args outs + simp only [Functor.map, Option.map_some] at args outs + apply Emission.eval_of outputs rfl rfl ?_ ?_ + · simp only [emitCall, List.mapM_cons, List.mapM_append, List.mapM_nil, + show evalExpr values (.konst 0) = some 0 from rfl, + show evalExpr values (.konst (G.ofNat function)) = some (G.ofNat function) from rfl, + args, outs, child, rangeSix_eval _ _ gap, bind, Option.bind_some, pure] + rfl + · have call := CallExpr.eval_of + (call := ⟨function, rowExprs inputs, rowExprs (advice first size), + (rank.frontAdd (.konst 1)).frontAdd (packSix + (fun index => (mainCurrent (first + size + index.val)).expr)), + fun index => (mainCurrent (first + size + index.val)).expr⟩) + (evalRows_values inputEval) (evalRows_values outputs) child gap + simp only [emitCall, List.mapM_cons, List.mapM_nil, call, bind, Option.bind_some, pure] + rfl + +def emitStore (first : Nat) (contents : Array RowExpr) : Emission := + { outputs := advice first 1, used := 1, + queries := [[.konst 1, .konst (G.ofNat contents.size), (mainCurrent first).expr] ++ + (rowExprs contents).toList] } + +theorem emitStore_reflects (values : Values G) (row : Nat → G) (first : Nat) + {contents : Array RowExpr} {stored : Array AIR.RowValue} + (contentsEval : evalRows values contents = some stored) + (read : (values.columns .main .current)[first]? = some (row 0)) : + (emitStore first contents).eval values = + some { outputs := AIR.rowAdvice row 0 1, used := 1, + queries := [AIR.memoryMessage contents.size (row 0) (AIR.rowValues stored)] } := by + have outputs := advice_eval values row first 1 (by + intro index bound + have equal : index = 0 := by omega + subst index + simpa only [Nat.add_zero] using read) + have storedEval := congrArg (Functor.map Array.toList) (evalRows_values contentsEval) + rw [Array.toList_mapM] at storedEval + simp only [Functor.map, Option.map_some] at storedEval + apply Emission.eval_of outputs rfl rfl ?_ rfl + simp only [emitStore, List.cons_append, List.nil_append, List.mapM_cons, List.mapM_nil, + show evalExpr values (.konst 1) = some 1 from rfl, + show evalExpr values (.konst (G.ofNat contents.size)) = some (G.ofNat contents.size) from rfl, + show evalExpr values (mainCurrent first).expr = some (row 0) from read, + storedEval, bind, Option.bind_some, pure, AIR.memoryMessage] + +def emitLoad (first size : Nat) (pointer : RowExpr) : Emission := + let outputs := advice first size + { outputs, used := size, + queries := [[.konst 1, .konst (G.ofNat size), pointer.expr] ++ (rowExprs outputs).toList] } + +theorem emitLoad_reflects (values : Values G) (row : Nat → G) (first size : Nat) + {pointer : RowExpr} {address : AIR.RowValue} (pointerRef : pointer.Reflects values address) + (reads : ∀ index < size, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitLoad first size pointer).eval values = + some { outputs := AIR.rowAdvice row 0 size, used := size, + queries := [AIR.memoryMessage size address.value (AIR.rowValues (AIR.rowAdvice row 0 size))] } := by + have outputs := advice_eval values row first size reads + have raw := congrArg (Functor.map Array.toList) (evalRows_values outputs) + rw [Array.toList_mapM] at raw + simp only [Functor.map, Option.map_some] at raw + apply Emission.eval_of outputs rfl rfl ?_ rfl + simp only [emitLoad, List.cons_append, List.nil_append, List.mapM_cons, List.mapM_nil, + show evalExpr values (.konst 1) = some 1 from rfl, + show evalExpr values (.konst (G.ofNat size)) = some (G.ofNat size) from rfl, + pointerRef.1, raw, bind, Option.bind_some, pure, AIR.memoryMessage] + +def rangeFour (bytes : Fin 4 → Expr) : List (List Expr) := + [rangePair (bytes 0) (bytes 1), rangePair (bytes 2) (bytes 3)] + +theorem rangeFour_eval {values : Values G} (bytes : Fin 4 → Expr) (results : Fin 4 → G) + (evaluated : ∀ index, evalExpr values (bytes index) = some (results index)) : + (rangeFour bytes).mapM (List.mapM (evalExpr values)) = some (AIR.range4Queries results) := by + simp only [rangeFour, List.mapM_cons, List.mapM_nil, + rangePair_eval (evaluated 0) (evaluated 1), rangePair_eval (evaluated 2) (evaluated 3), + bind, Option.bind_some, pure] + rfl + +def booleanExpr (expr : Expr) : Expr := expr.frontMul (expr.frontSub (.konst 1)) + +theorem booleanExpr_eval {values : Values G} {expr : Expr} {value : G} + (evaluated : evalExpr values expr = some value) : + evalExpr values (booleanExpr expr) = some (AIR.booleanConstraint value) := + Expr.frontMul_eval goldilocksLaws values evaluated + (Expr.frontSub_eval goldilocksLaws values evaluated rfl) + +def emitU32LessThan (selector : Expr) (first : Nat) (left right : RowExpr) : Emission := + let x : Fin 4 → Expr := fun index => (mainCurrent (first + index.val)).expr + let y : Fin 4 → Expr := fun index => (mainCurrent (first + 4 + index.val)).expr + let z : Fin 4 → Expr := fun index => (mainCurrent (first + 8 + index.val)).expr + let chain := carries x y z + { outputs := #[⟨(Expr.konst 1).frontSub (chain 4), 1⟩], used := 12, + equations := selector.frontMul (left.expr.frontSub (packedAdvice first).expr) :: + selector.frontMul (right.expr.frontSub (packedAdvice (first + 8)).expr) :: + List.ofFn (fun index : Fin 4 => selector.frontMul (booleanExpr (chain index.succ))), + queries := rangeFour x ++ rangeFour y ++ rangeFour z } + +theorem emitU32LessThan_reflects (values : Values G) (row : Nat → G) (first : Nat) + {selector : Expr} {s : G} {left right : RowExpr} {a b : AIR.RowValue} + (selectorEval : evalExpr values selector = some s) + (leftRef : left.Reflects values a) (rightRef : right.Reflects values b) + (reads : ∀ index < 12, + (values.columns .main .current)[first + index]? = some (row index)) : + (emitU32LessThan selector first left right).eval values = + some { outputs := #[⟨1 - AIR.u32Carries (fun i => row i.val) + (fun i => row (4 + i.val)) (fun i => row (8 + i.val)) 4, 1, false⟩], + used := 12, + equations := s * (a.value - AIR.pack4 (fun i => row i.val)) :: + s * (b.value - AIR.pack4 (fun i => row (8 + i.val))) :: + List.ofFn (fun i : Fin 4 => s * AIR.booleanConstraint + (AIR.u32Carries (fun i => row i.val) (fun i => row (4 + i.val)) + (fun i => row (8 + i.val)) i.succ)), + queries := AIR.range4Queries (fun i => row i.val) ++ + AIR.range4Queries (fun i => row (4 + i.val)) ++ AIR.range4Queries (fun i => row (8 + i.val)) } := by + let x : Fin 4 → Expr := fun index => (mainCurrent (first + index.val)).expr + let y : Fin 4 → Expr := fun index => (mainCurrent (first + 4 + index.val)).expr + let z : Fin 4 → Expr := fun index => (mainCurrent (first + 8 + index.val)).expr + have xe (index : Fin 4) : evalExpr values (x index) = some (row index.val) := + reads index.val (by omega) + have ye (index : Fin 4) : evalExpr values (y index) = some (row (4 + index.val)) := by + change (values.columns .main .current)[first + 4 + index.val]? = _ + simpa only [Nat.add_assoc] using reads (4 + index.val) (by omega) + have ze (index : Fin 4) : evalExpr values (z index) = some (row (8 + index.val)) := by + change (values.columns .main .current)[first + 8 + index.val]? = _ + simpa only [Nat.add_assoc] using reads (8 + index.val) (by omega) + have chain := carries_eval xe ye ze + have px := (packedAdvice_reflects values row first (fun index bound => reads index (by omega))).1 + have pz := (packedAdvice_reflects values (fun index => row (8 + index)) (first + 8) (by + intro index bound + simpa only [Nat.add_assoc] using reads (8 + index) (by omega))).1 + rw [packed_advice_value] at px pz + have firstEq := Expr.frontMul_eval goldilocksLaws values selectorEval + (Expr.frontSub_eval goldilocksLaws values leftRef.1 px) + have secondEq := Expr.frontMul_eval goldilocksLaws values selectorEval + (Expr.frontSub_eval goldilocksLaws values rightRef.1 pz) + have restEq (index : Fin 4) := Expr.frontMul_eval goldilocksLaws values selectorEval + (booleanExpr_eval (chain index.succ)) + have chainNormal : (carries x y z 4).noConstantNegs = true := + carries_normal (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) 4 + have chainNonconstant : (carries x y z 4).isConstant = false := carryStep_not_constant rfl rfl + have output : (⟨(Expr.konst 1).frontSub (carries x y z 4), 1⟩ : RowExpr).Reflects values + ⟨1 - AIR.u32Carries (fun i => row i.val) (fun i => row (4 + i.val)) + (fun i => row (8 + i.val)) 4, 1, false⟩ := by + refine ⟨Expr.frontSub_eval goldilocksLaws values + (show evalExpr values (.konst 1) = some 1 from rfl) (chain 4), rfl, ?_⟩ + change ((Expr.konst 1).frontSub (carries x y z 4)).isConstant = false + rw [Expr.frontSub_isConstant _ _ chainNormal, chainNonconstant, Bool.and_false] + apply Emission.eval_of (evalRows_singleton output) rfl ?_ ?_ rfl + · have remaining := list_mapM_ofFn _ _ (evalExpr values) restEq + dsimp only [x, y, z] at remaining + simp only [emitU32LessThan, List.mapM_cons, firstEq, secondEq, remaining, + bind, Option.bind_some, pure, goldilocks_mul, goldilocks_sub] + · have rx := rangeFour_eval x _ xe + have ry := rangeFour_eval y _ ye + have rz := rangeFour_eval z _ ze + dsimp only [x, y, z] at rx ry rz + simp only [emitU32LessThan, List.mapM_append, rx, ry, rz, bind, Option.bind_some, pure] + +theorem emitU32LessThan_normal (selector : Expr) (first : Nat) (left right : RowExpr) : + Normal (emitU32LessThan selector first left right).outputs := by + intro expr member + have equal := Array.mem_singleton.mp member + subst expr + let x : Fin 4 → Expr := fun index => (mainCurrent (first + index.val)).expr + let y : Fin 4 → Expr := fun index => (mainCurrent (first + 4 + index.val)).expr + let z : Fin 4 → Expr := fun index => (mainCurrent (first + 8 + index.val)).expr + have normal : (carries x y z 4).noConstantNegs = true := + carries_normal (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) 4 + exact Expr.frontSub_noConstantNegs (left := Expr.konst 1) (right := carries x y z 4) rfl normal + +def emitAssert (selector : Expr) (left right : Array RowExpr) : Emission := + { equations := List.ofFn fun index : Fin left.size => selector.frontMul + ((left[index.val]?.getD (.konst 0)).expr.frontSub (right[index.val]?.getD (.konst 0)).expr) } + +theorem rowValues_getD (rows : Array AIR.RowValue) (index : Nat) : + (AIR.rowValues rows)[index]?.getD 0 = (rows[index]?.getD (.konst 0)).value := by + simp only [AIR.rowValues, Array.getElem?_map] + cases rows[index]? <;> rfl + +theorem emitAssert_reflects {values : Values G} {selector : Expr} {s : G} + {left right : Array RowExpr} {a b : Array AIR.RowValue} + (selectorEval : evalExpr values selector = some s) + (leftEval : evalRows values left = some a) (rightEval : evalRows values right = some b) + (size : left.size = right.size) : + (emitAssert selector left right).eval values = + some { equations := List.ofFn fun index : Fin left.size => + s * ((AIR.rowValues a)[index.val]?.getD 0 - (AIR.rowValues b)[index.val]?.getD 0) } := by + apply Emission.eval_of (evalRows_empty values) rfl ?_ rfl rfl + apply list_mapM_ofFn + intro index + have leftRef := evalRows_getD leftEval index.isLt + have rightRef := evalRows_getD rightEval (index := index.val) (by omega) + rw [rowValues_getD, rowValues_getD] + exact Expr.frontMul_eval goldilocksLaws values selectorEval + (Expr.frontSub_eval goldilocksLaws values leftRef.1 rightRef.1) + +/-- The operation dispatcher mirrors the native emitter's fresh-column order. +Operand reads here are checked in the incoming logical scope. The native store +reads after pushing its pointer, so that correspondence also uses the checked +program's incoming-scope index validity. -/ +def emitOp (selector rank : Expr) (first : Nat) (op : Bytecode.Op) + (rows : Array RowExpr) : Option Emission := + match op with + | .const value => some (fromScalar ⟨.konst value, 0, []⟩) + | .add a b => do return fromScalar ⟨(← rows[a]?).add (← rows[b]?), 0, []⟩ + | .sub a b => do return fromScalar ⟨(← rows[a]?).sub (← rows[b]?), 0, []⟩ + | .mul a b => do return fromScalar (NativeAIR.emitMul selector first (← rows[a]?) (← rows[b]?)) + | .eqZero a => do return fromScalar (NativeAIR.emitEqZero selector first (← rows[a]?)) + | .call function indices size unconstrained => + if unconstrained then some (emitAdvice first size) + else do return emitCall selector rank first function (← select rows indices) size + | .store indices => do return emitStore first (← select rows indices) + | .load size index => do return emitLoad first size (← rows[index]?) + | .assertEq xs ys _ => + if xs.size ≠ ys.size then none + else do return emitAssert selector (← select rows xs) (← select rows ys) + | .ioGetInfo .. => some (emitAdvice first 2) + | .ioRead _ _ size => some (emitAdvice first size) + | .ioSetInfo .. | .ioWrite .. | .debug .. => some {} + | .u8BitDecomposition index => do return emitByte1 first .bits (← rows[index]?) + | .u8ShiftLeft index => do return emitByte1 first .shiftLeft (← rows[index]?) + | .u8ShiftRight index => do return emitByte1 first .shiftRight (← rows[index]?) + | .u8Xor a b => do return emitByte2 first .xor (← rows[a]?) (← rows[b]?) + | .u8Add a b => do return emitByte2 first .add (← rows[a]?) (← rows[b]?) + | .u8Sub a b => do return emitByte2 first .sub (← rows[a]?) (← rows[b]?) + | .u8And a b => do return emitByte2 first .and (← rows[a]?) (← rows[b]?) + | .u8Or a b => do return emitByte2 first .or (← rows[a]?) (← rows[b]?) + | .u8LessThan a b => do return emitByte2 first .lessThan (← rows[a]?) (← rows[b]?) + | .u8RangeCheck a b => do return emitByte2 first .range (← rows[a]?) (← rows[b]?) + | .u8Mul a b => do return emitByte2 first .mul (← rows[a]?) (← rows[b]?) + | .u8XorSplit7 a b => do return emitByte2 first .split7 (← rows[a]?) (← rows[b]?) + | .u8XorSplit4 a b => do return emitByte2 first .split4 (← rows[a]?) (← rows[b]?) + | .u32LessThan a b => do return emitU32LessThan selector first (← rows[a]?) (← rows[b]?) + | .unconstrainedBigUintDivMod .. => some (emitAdvice first 2) + | .unconstrainedGToBytes .. => some (emitAdvice first 8) + | .unconstrainedGInverse .. => some (emitAdvice first 1) + | .unconstrainedU32Add a b => do + return emitWordSum first ((← readWord rows a).add (← readWord rows b)) + | .unconstrainedU32Add3 a b c => do + return emitWordSum first (((← readWord rows a).add (← readWord rows b)).add (← readWord rows c)) + | .u32ToField indices => do return fromScalar ⟨← readWord rows indices, 0, []⟩ + +end OpEmitter +end Aiur.NativeAIR diff --git a/Ix/Aiur/Proofs/OperationReflection.lean b/Ix/Aiur/Proofs/OperationReflection.lean new file mode 100644 index 000000000..1896f63fc --- /dev/null +++ b/Ix/Aiur/Proofs/OperationReflection.lean @@ -0,0 +1,495 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationExpressions + +/-! +Reflection of complete symbolic operation emission into the valued AIR. +Successful incoming evaluations and reads of the allocated fresh columns +derive all output values, metadata, equations, raw queries and call records. +-/ + +namespace Aiur.NativeAIR.OpEmitter + +theorem fromScalar_eval (values : Values G) (emission : ScalarEmission) : + (fromScalar emission).eval values = emission.eval values := by + have singleton : evalRows values #[emission.output] = do + let output ← emission.output.eval values + return #[output] := by + change ((#[] : Array RowExpr).push emission.output).mapM _ = _ + rw [array_mapM_push, Array.mapM_empty] + rfl + simp only [fromScalar, Emission.eval, singleton, ScalarEmission.eval, List.mapM_nil, + bind, Option.bind, pure] + cases emission.output.eval values <;> simp only + +theorem empty_eval (values : Values G) : ({} : Emission).eval values = some {} := by + exact Emission.eval_of (evalRows_empty values) rfl rfl rfl rfl + +theorem normal_empty : Normal #[] := by + intro row member + exact False.elim (Array.not_mem_empty row member) + +theorem normal_singleton {row : RowExpr} (normal : row.expr.noConstantNegs = true) : + Normal #[row] := by + intro item member + have equal := Array.mem_singleton.mp member + subst item + exact normal + +theorem Normal.read {rows : Array RowExpr} (normal : Normal rows) + {index : Nat} {row : RowExpr} (read : rows[index]? = some row) : + row.expr.noConstantNegs = true := normal row (Array.mem_of_getElem? read) + +theorem emitOp_byte1 (selector rank : Expr) (first : Nat) (kind : AIR.Byte1Kind) + (index : Nat) (rows : Array RowExpr) : + emitOp selector rank first (kind.op index) rows = do + return emitByte1 first kind (← rows[index]?) := by + cases kind <;> rfl + +theorem emitOp_byte2 (selector rank : Expr) (first : Nat) (kind : AIR.Byte2Kind) + (left right : Nat) (rows : Array RowExpr) : + emitOp selector rank first (kind.op left right) rows = do + return emitByte2 first kind (← rows[left]?) (← rows[right]?) := by + cases kind <;> rfl + +theorem emitByte1_dispatch (values : Values G) (row : Nat → G) (selector rank : Expr) + (s r : G) (first : Nat) (kind : AIR.Byte1Kind) (index : Nat) + {rows : Array RowExpr} {inputs : Array AIR.RowValue} {emission : Emission} + (inputEval : evalRows values rows = some inputs) + (emitted : emitOp selector rank first (kind.op index) rows = some emission) + (reads : ∀ index < emission.used, + (values.columns .main .current)[first + index]? = some (row index)) : + ∃ result, AIR.emitOp row s r (kind.op index) inputs = some result ∧ + emission.eval values = some result := by + rw [emitOp_byte1] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i input read + cases emitted + obtain ⟨value, readValue, reflected⟩ := evalRows_read inputEval read + refine ⟨_, ?_, emitByte1_reflects values row first kind reflected reads⟩ + cases kind <;> simp only [AIR.Byte1Kind.op, AIR.emitOp, AIR.emitByte1, + readValue, bind, Option.bind_some, pure] + +theorem emitByte2_dispatch (values : Values G) (row : Nat → G) (selector rank : Expr) + (s r : G) (first : Nat) (kind : AIR.Byte2Kind) (left right : Nat) + {rows : Array RowExpr} {inputs : Array AIR.RowValue} {emission : Emission} + (inputEval : evalRows values rows = some inputs) (normal : Normal rows) + (emitted : emitOp selector rank first (kind.op left right) rows = some emission) + (reads : ∀ index < emission.used, + (values.columns .main .current)[first + index]? = some (row index)) : + ∃ result, AIR.emitOp row s r (kind.op left right) inputs = some result ∧ + emission.eval values = some result := by + rw [emitOp_byte2] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i a readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i b readB + cases emitted + obtain ⟨x, readX, refX⟩ := evalRows_read inputEval readA + obtain ⟨y, readY, refY⟩ := evalRows_read inputEval readB + refine ⟨_, ?_, emitByte2_reflects values row first kind refX refY (normal.read readA) reads⟩ + cases kind <;> simp only [AIR.Byte2Kind.op, AIR.emitOp, AIR.emitByte2, + readX, readY, bind, Option.bind_some, pure] + +theorem list_ofFn_getD_pair {α β γ : Type} (left : Array α) (right : Array β) + (leftDefault : α) (rightDefault : β) (f : α → β → γ) {count : Nat} + (size : left.size = count) : + (List.ofFn fun index : Fin count => + f (left[index.val]?.getD leftDefault) (right[index.val]?.getD rightDefault)) = + List.ofFn fun index : Fin left.size => f left[index] (right[index.val]?.getD rightDefault) := by + subst count + congr 1 + funext index + rw [getElem?_pos left index.val index.isLt, Option.getD_some] + rfl + +theorem emitOp_reflects (values : Values G) (row : Nat → G) + {selector rank : Expr} {s r : G} {first : Nat} {op : Bytecode.Op} + {rows : Array RowExpr} {inputs : Array AIR.RowValue} {emission : Emission} + (selectorEval : evalExpr values selector = some s) (rankEval : evalExpr values rank = some r) + (inputEval : evalRows values rows = some inputs) (normal : Normal rows) + (emitted : emitOp selector rank first op rows = some emission) + (reads : ∀ index < emission.used, + (values.columns .main .current)[first + index]? = some (row index)) : + ∃ result, AIR.emitOp row s r op inputs = some result ∧ emission.eval values = some result := by + cases op with + | const value => + cases emitted + refine ⟨_, rfl, ?_⟩ + rw [fromScalar_eval] + exact ScalarEmission.eval_of values (RowExpr.konst_reflects values value) rfl + | add a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + obtain ⟨x, readX, refX⟩ := evalRows_read inputEval readA + obtain ⟨y, readY, refY⟩ := evalRows_read inputEval readB + refine ⟨{ outputs := #[x.add y] }, ?_, ?_⟩ + · simp only [AIR.emitOp, readX, readY, bind, Option.bind_some, pure] + · rw [fromScalar_eval] + exact ScalarEmission.eval_of values (RowExpr.add_reflects values refX refY) rfl + | sub a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + obtain ⟨x, readX, refX⟩ := evalRows_read inputEval readA + obtain ⟨y, readY, refY⟩ := evalRows_read inputEval readB + refine ⟨{ outputs := #[x.sub y] }, ?_, ?_⟩ + · simp only [AIR.emitOp, readX, readY, bind, Option.bind_some, pure] + · rw [fromScalar_eval] + exact ScalarEmission.eval_of values + (RowExpr.sub_reflects values refX refY (normal.read readB)) rfl + | mul a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + obtain ⟨x, readX, refX⟩ := evalRows_read inputEval readA + obtain ⟨y, readY, refY⟩ := evalRows_read inputEval readB + have reflected := NativeAIR.emitMul_reflects values row selectorEval refX refY reads + have indexed : AIR.emitOp row s r (.mul a b) inputs = AIR.emitOp row s 0 (.mul 0 1) #[x, y] := by + simp only [AIR.emitOp, readX, readY, show #[x, y][0]? = some x from rfl, + show #[x, y][1]? = some y from rfl, bind, Option.bind_some] + rw [indexed] + have total : ∃ result, AIR.emitOp row s 0 (.mul 0 1) #[x, y] = some result := by + simp only [AIR.emitOp, show #[x, y][0]? = some x from rfl, + show #[x, y][1]? = some y from rfl, bind, Option.bind_some] + split <;> exact ⟨_, rfl⟩ + obtain ⟨result, resultEq⟩ := total + exact ⟨result, resultEq, (fromScalar_eval _ _).trans (reflected.trans resultEq)⟩ + | eqZero index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i input read + cases emitted + obtain ⟨value, readValue, refValue⟩ := evalRows_read inputEval read + have reflected := NativeAIR.emitEqZero_reflects values row selectorEval refValue reads + have indexed : AIR.emitOp row s r (.eqZero index) inputs = AIR.emitOp row s 0 (.eqZero 0) #[value] := by + simp only [AIR.emitOp, readValue, show #[value][0]? = some value from rfl, bind, Option.bind_some] + rw [indexed] + have total : ∃ result, AIR.emitOp row s 0 (.eqZero 0) #[value] = some result := by + simp only [AIR.emitOp, show #[value][0]? = some value from rfl, bind, Option.bind_some] + split <;> exact ⟨_, rfl⟩ + obtain ⟨result, resultEq⟩ := total + exact ⟨result, resultEq, (fromScalar_eval _ _).trans (reflected.trans resultEq)⟩ + | call function indices size unconstrained => + cases unconstrained with + | true => + cases emitted + exact ⟨_, rfl, emitAdvice_reflects values row first size reads⟩ + | false => + simp only [emitOp, Bool.false_eq_true, if_false, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i arguments selected + cases emitted + obtain ⟨args, argsRead, argsEval⟩ := select_reflects inputEval selected + refine ⟨_, ?_, emitCall_reflects values row first function size selectorEval rankEval argsEval reads⟩ + simp only [AIR.emitOp, Bool.false_eq_true, if_false, select_values argsRead, + bind, Option.bind_some, pure] + | store indices => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i contents selected + cases emitted + obtain ⟨stored, storedRead, storedEval⟩ := select_reflects inputEval selected + have size : contents.size = indices.size := array_mapM_size selected + have read : (values.columns .main .current)[first]? = some (row 0) := by + simpa only [Nat.add_zero] using reads 0 (by change 0 < 1; decide) + refine ⟨_, ?_, emitStore_reflects values row first storedEval read⟩ + simp only [AIR.emitOp, select_values storedRead, bind, Option.bind_some, pure, size] + rfl + | load size index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i pointer read + cases emitted + obtain ⟨address, addressRead, addressRef⟩ := evalRows_read inputEval read + refine ⟨_, ?_, emitLoad_reflects values row first size addressRef reads⟩ + simp only [AIR.emitOp, addressRead, bind, Option.bind_some, pure] + | assertEq xs ys message => + simp only [emitOp] at emitted + split at emitted + · cases emitted + rename_i size + have same : xs.size = ys.size := Classical.not_not.mp size + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left selectedLeft + dsimp only at emitted + split at emitted + · cases emitted + rename_i right selectedRight + cases emitted + obtain ⟨a, readA, evalA⟩ := select_reflects inputEval selectedLeft + obtain ⟨b, readB, evalB⟩ := select_reflects inputEval selectedRight + have leftSize := array_mapM_size selectedLeft + have rightSize := array_mapM_size selectedRight + have resultSize : (AIR.rowValues a).size = left.size := by + simpa only [AIR.rowValues, Array.size_map] using array_mapM_size evalA + refine ⟨_, ?_, emitAssert_reflects selectorEval evalA evalB (by omega)⟩ + simp only [AIR.emitOp, same, ne_eq, not_true_eq_false, if_false, + select_values readA, select_values readB, bind, Option.bind_some, pure] + rw [list_ofFn_getD_pair (AIR.rowValues a) (AIR.rowValues b) 0 0 (fun x y => s * (x - y)) resultSize] + | ioGetInfo | ioRead | unconstrainedBigUintDivMod | unconstrainedGToBytes | unconstrainedGInverse => + cases emitted + exact ⟨_, rfl, emitAdvice_reflects values row first _ reads⟩ + | ioSetInfo | ioWrite | debug => + cases emitted + exact ⟨_, rfl, empty_eval values⟩ + | u8BitDecomposition index => exact emitByte1_dispatch values row selector rank s r first .bits index inputEval emitted reads + | u8ShiftLeft index => exact emitByte1_dispatch values row selector rank s r first .shiftLeft index inputEval emitted reads + | u8ShiftRight index => exact emitByte1_dispatch values row selector rank s r first .shiftRight index inputEval emitted reads + | u8Xor a b => exact emitByte2_dispatch values row selector rank s r first .xor a b inputEval normal emitted reads + | u8Add a b => exact emitByte2_dispatch values row selector rank s r first .add a b inputEval normal emitted reads + | u8Sub a b => exact emitByte2_dispatch values row selector rank s r first .sub a b inputEval normal emitted reads + | u8And a b => exact emitByte2_dispatch values row selector rank s r first .and a b inputEval normal emitted reads + | u8Or a b => exact emitByte2_dispatch values row selector rank s r first .or a b inputEval normal emitted reads + | u8LessThan a b => exact emitByte2_dispatch values row selector rank s r first .lessThan a b inputEval normal emitted reads + | u8RangeCheck a b => exact emitByte2_dispatch values row selector rank s r first .range a b inputEval normal emitted reads + | u8Mul a b => exact emitByte2_dispatch values row selector rank s r first .mul a b inputEval normal emitted reads + | u8XorSplit7 a b => exact emitByte2_dispatch values row selector rank s r first .split7 a b inputEval normal emitted reads + | u8XorSplit4 a b => exact emitByte2_dispatch values row selector rank s r first .split4 a b inputEval normal emitted reads + | u32LessThan a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + obtain ⟨x, readX, refX⟩ := evalRows_read inputEval readA + obtain ⟨y, readY, refY⟩ := evalRows_read inputEval readB + refine ⟨_, ?_, emitU32LessThan_reflects values row first selectorEval refX refY reads⟩ + simp only [AIR.emitOp, AIR.emitU32LessThan, readX, readY, bind, Option.bind_some, pure] + | unconstrainedU32Add a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + obtain ⟨x, readX, refX⟩ := readWord_reflects inputEval readA + obtain ⟨y, readY, refY⟩ := readWord_reflects inputEval readB + refine ⟨_, ?_, emitWordSum_reflects values row first (RowExpr.add_reflects values refX refY) reads⟩ + simp only [AIR.emitOp, AIR.emitU32Add, readX, readY, bind, Option.bind_some, pure] + | unconstrainedU32Add3 a b c => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + dsimp only at emitted + split at emitted + · cases emitted + rename_i third readC + cases emitted + obtain ⟨x, readX, refX⟩ := readWord_reflects inputEval readA + obtain ⟨y, readY, refY⟩ := readWord_reflects inputEval readB + obtain ⟨z, readZ, refZ⟩ := readWord_reflects inputEval readC + refine ⟨_, ?_, emitWordSum_reflects values row first + (RowExpr.add_reflects values (RowExpr.add_reflects values refX refY) refZ) reads⟩ + simp only [AIR.emitOp, AIR.emitU32Add, readX, readY, readZ, + Option.map_some, bind, Option.bind_some, pure] + | u32ToField indices => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i word read + cases emitted + obtain ⟨value, readValue, refValue⟩ := readWord_reflects inputEval read + refine ⟨{ outputs := #[value] }, ?_, ?_⟩ + · simp only [AIR.emitOp, readValue, bind, Option.bind_some, pure] + · rw [fromScalar_eval] + exact ScalarEmission.eval_of values refValue rfl + +theorem emitByte1_dispatch_normal (selector rank : Expr) (first : Nat) + (kind : AIR.Byte1Kind) (index : Nat) {rows : Array RowExpr} {emission : Emission} + (emitted : emitOp selector rank first (kind.op index) rows = some emission) : + Normal emission.outputs := by + rw [emitOp_byte1] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact advice_normal _ _ + +theorem emitByte2_dispatch_normal (selector rank : Expr) (first : Nat) + (kind : AIR.Byte2Kind) (a b : Nat) {rows : Array RowExpr} {emission : Emission} + (normal : Normal rows) + (emitted : emitOp selector rank first (kind.op a b) rows = some emission) : + Normal emission.outputs := by + rw [emitOp_byte2] at emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + exact emitByte2_normal _ _ (normal.read readA) (normal.read readB) + +theorem emitOp_normal {selector rank : Expr} {first : Nat} {op : Bytecode.Op} + {rows : Array RowExpr} {emission : Emission} (normal : Normal rows) + (emitted : emitOp selector rank first op rows = some emission) : + Normal emission.outputs := by + cases op with + | const value => + cases emitted + exact normal_singleton rfl + | add a b | sub a b | mul a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + apply normal_singleton + first + | exact Expr.frontAdd_noConstantNegs (normal.read readA) (normal.read readB) + | exact Expr.frontSub_noConstantNegs (normal.read readA) (normal.read readB) + | exact NativeAIR.emitMul_noConstantNegs selector first (normal.read readA) (normal.read readB) + | eqZero index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact normal_singleton (NativeAIR.emitEqZero_noConstantNegs _ _ _) + | call function indices size unconstrained => + cases unconstrained with + | true => + cases emitted + exact advice_normal _ _ + | false => + simp only [emitOp, Bool.false_eq_true, if_false, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact advice_normal _ _ + | store indices | load size index => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + cases emitted + exact advice_normal _ _ + | assertEq xs ys message => + simp only [emitOp] at emitted + split at emitted + · cases emitted + simp only [bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact normal_empty + | ioGetInfo | ioRead | unconstrainedBigUintDivMod | unconstrainedGToBytes | unconstrainedGInverse => + cases emitted + exact advice_normal _ _ + | ioSetInfo | ioWrite | debug => + cases emitted + exact normal_empty + | u8BitDecomposition index => exact emitByte1_dispatch_normal selector rank first .bits index emitted + | u8ShiftLeft index => exact emitByte1_dispatch_normal selector rank first .shiftLeft index emitted + | u8ShiftRight index => exact emitByte1_dispatch_normal selector rank first .shiftRight index emitted + | u8Xor a b => exact emitByte2_dispatch_normal selector rank first .xor a b normal emitted + | u8Add a b => exact emitByte2_dispatch_normal selector rank first .add a b normal emitted + | u8Sub a b => exact emitByte2_dispatch_normal selector rank first .sub a b normal emitted + | u8And a b => exact emitByte2_dispatch_normal selector rank first .and a b normal emitted + | u8Or a b => exact emitByte2_dispatch_normal selector rank first .or a b normal emitted + | u8LessThan a b => exact emitByte2_dispatch_normal selector rank first .lessThan a b normal emitted + | u8RangeCheck a b => exact emitByte2_dispatch_normal selector rank first .range a b normal emitted + | u8Mul a b => exact emitByte2_dispatch_normal selector rank first .mul a b normal emitted + | u8XorSplit7 a b => exact emitByte2_dispatch_normal selector rank first .split7 a b normal emitted + | u8XorSplit4 a b => exact emitByte2_dispatch_normal selector rank first .split4 a b normal emitted + | u32LessThan a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact emitU32LessThan_normal _ _ _ _ + | unconstrainedU32Add a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + cases emitted + exact emitWordSum_normal _ (Expr.frontAdd_noConstantNegs + (readWord_normal normal readA) (readWord_normal normal readB)) + | unconstrainedU32Add3 a b c => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i left readA + dsimp only at emitted + split at emitted + · cases emitted + rename_i right readB + dsimp only at emitted + split at emitted + · cases emitted + rename_i third readC + cases emitted + exact emitWordSum_normal _ (Expr.frontAdd_noConstantNegs + (Expr.frontAdd_noConstantNegs (readWord_normal normal readA) (readWord_normal normal readB)) + (readWord_normal normal readC)) + | u32ToField indices => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i word read + cases emitted + exact normal_singleton (readWord_normal normal read) + +end Aiur.NativeAIR.OpEmitter diff --git a/Ix/Aiur/Proofs/OperationRows.lean b/Ix/Aiur/Proofs/OperationRows.lean new file mode 100644 index 000000000..78019efca --- /dev/null +++ b/Ix/Aiur/Proofs/OperationRows.lean @@ -0,0 +1,662 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.GlobalLookups + +/-! +Valued emission and local execution for every native bytecode operation. +The model retains expression degree, constant folding, fresh auxiliary-column +allocation, logical map extension, polynomial values and raw query parts. +Active satisfying emissions derive relational steps and operation sequences +using byte and memory facts from the global lookup pool. + +This is a total Lean model. Identifying its reads and metadata with the Rust +expression emitter, proving index and layout validity, and extracting its +active query parts from shared slots remain explicit obligations. +-/ + +namespace Aiur.AIR +open Bytecode + +/-- One evaluated logical value, retaining the native emitter's expression +degree and whether its frontend expression is syntactically constant. -/ +structure RowValue where + value : G + degree : Nat + constant : Bool + deriving Repr, DecidableEq + +def RowValue.variable (value : G) : RowValue := ⟨value, 1, false⟩ +def RowValue.konst (value : G) : RowValue := ⟨value, 0, true⟩ +def rowValues (values : Array RowValue) : Array G := values.map RowValue.value + +def RowValue.add (left right : RowValue) : RowValue := + ⟨left.value + right.value, max left.degree right.degree, left.constant && right.constant⟩ + +def RowValue.sub (left right : RowValue) : RowValue := + ⟨left.value - right.value, max left.degree right.degree, left.constant && right.constant⟩ + +/-- Multiplication by a known zero also folds a nonconstant expression to +a constant; the native operation's degree bookkeeping remains independent. -/ +def RowValue.mul (left right : RowValue) : RowValue := + ⟨left.value * right.value, left.degree + right.degree, + (left.constant && right.constant) || (left.constant && left.value == 0) || + (right.constant && right.value == 0)⟩ + +def rowAdvice (row : Nat → G) (start count : Nat) : Array RowValue := + Array.ofFn fun index : Fin count => RowValue.variable (row (start + index.val)) + +def RowValue.pack (values : Array RowValue) : RowValue := + ⟨Bytecode.AIR.packWord (rowValues values), + values.toList.foldl (fun degree value => max degree value.degree) 0, + values.all (·.constant)⟩ + +def readRowWord (values : Array RowValue) (indices : Array ValIdx) : Option RowValue := do + let word ← Bytecode.AIR.readWord (rowValues values) indices + let bytes := indices.map fun index => values[index]?.getD (RowValue.konst 0) + return { RowValue.pack bytes with value := word } + +/-- One operation's evaluated outputs and newly emitted constraints. Lookup +messages are ungated contributions; slot assembly supplies their selector. +`used` is the exact number of fresh auxiliary columns consumed. -/ +structure OpEmission where + outputs : Array RowValue := #[] + used : Nat := 0 + equations : List G := [] + queries : List (List G) := [] + calls : List (Bytecode.AIR.Call × (Fin 6 → G)) := [] + +def emitAdvice (row : Nat → G) (count : Nat) : OpEmission := + { outputs := rowAdvice row 0 count, used := count } + +def emitByte1 (row : Nat → G) (kind : Byte1Kind) (index : ValIdx) + (values : Array RowValue) : Option OpEmission := do + let input ← values[index]? + let outputs := rowAdvice row 0 kind.outputSize + return { + outputs, used := kind.outputSize + queries := [byte1Request kind input.value (rowValues outputs)] } + +def Byte2Kind.extendRowOutputs (kind : Byte2Kind) (left right : RowValue) + (outputs : Array RowValue) : Array RowValue := + let low := ((rowValues outputs)[0]?).getD 0 + let degree := max (max left.degree right.degree) 1 + match kind with + | .add => outputs.push ⟨(left.value + right.value - low) * inverse256, degree, false⟩ + | .sub => outputs.push ⟨(low + right.value - left.value) * inverse256, degree, false⟩ + | _ => outputs + +def emitByte2 (row : Nat → G) (kind : Byte2Kind) (left right : ValIdx) + (values : Array RowValue) : Option OpEmission := do + let x ← values[left]? + let y ← values[right]? + let outputs := rowAdvice row 0 kind.outputSize + return { + outputs := kind.extendRowOutputs x y outputs, used := kind.outputSize + queries := [byte2Request kind x.value y.value (rowValues outputs)] } + +def range4Queries (bytes : Fin 4 → G) : List (List G) := + [rangeMessage (bytes 0, bytes 1), rangeMessage (bytes 2, bytes 3)] + +def emitU32LessThan (row : Nat → G) (selector : G) (left right : ValIdx) + (values : Array RowValue) : Option OpEmission := do + let a ← values[left]? + let b ← values[right]? + let x : Fin 4 → G := fun index => row index.val + let y : Fin 4 → G := fun index => row (4 + index.val) + let z : Fin 4 → G := fun index => row (8 + index.val) + return { + outputs := #[⟨1 - u32Carries x y z 4, 1, false⟩], used := 12 + equations := selector * (a.value - pack4 x) :: selector * (b.value - pack4 z) :: + List.ofFn (fun index : Fin 4 => selector * booleanConstraint (u32Carries x y z index.succ)), + queries := range4Queries x ++ range4Queries y ++ range4Queries z } + +def emitU32Add (row : Nat → G) (left right : Array ValIdx) + (third : Option (Array ValIdx)) (values : Array RowValue) : Option OpEmission := do + let x ← readRowWord values left + let y ← readRowWord values right + let sum ← match third with + | none => some (x.add y) + | some indices => (readRowWord values indices).map fun z => (x.add y).add z + let bytes := rowAdvice row 0 4 + let packed := RowValue.pack bytes + return { outputs := bytes.push ⟨(sum.value - packed.value) * 0xfffffffe00000002, + max sum.degree packed.degree, false⟩, used := 4 } + +/-- Valued model of one native operation. Invalid reads and malformed word +widths return `none`. Constant `eq_zero` inputs with positive tracked degree +use the ordinary two-column emission, preserving the compiled layout. +Store operands are checked in the incoming logical scope; identifying that +scope with the Rust emitter's post-pointer reads requires index validity. -/ +def emitOp (row : Nat → G) (selector rank : G) (op : Op) + (values : Array RowValue) : Option OpEmission := + match op with + | .const value => some { outputs := #[RowValue.konst value] } + | .add a b => do return { outputs := #[(← values[a]?).add (← values[b]?)] } + | .sub a b => do return { outputs := #[(← values[a]?).sub (← values[b]?)] } + | .mul a b => do + let x ← values[a]? + let y ← values[b]? + let product := x.mul y + if product.degree < 2 then return { outputs := #[product] } + else return { + outputs := #[RowValue.variable (row 0)], used := 1 + equations := [selector * (row 0 - product.value)] } + | .eqZero a => do + let input ← values[a]? + if input.constant && input.degree == 0 then + return { outputs := #[RowValue.konst (G.eqZero input.value)] } + else return { + outputs := #[RowValue.variable (row 1)], used := 2 + equations := [selector * input.value * row 1, + selector * (input.value * row 0 + row 1 - 1)] } + | .call function indices size unconstrained => + if unconstrained then some (emitAdvice row size) + else do + let inputs ← Bytecode.AIR.readValues (rowValues values) indices + let outputs := rowAdvice row 0 size + let gap : Fin 6 → G := fun index => row (size + index.val) + let request : Bytecode.AIR.Call := + ⟨function, inputs, rowValues outputs, rank + 1 + packRank gap⟩ + return { + outputs, used := size + 6 + queries := functionMessage request :: (rankByteQueries gap).map rangeMessage, + calls := [(request, gap)] } + | .store indices => do + let contents ← Bytecode.AIR.readValues (rowValues values) indices + return { + outputs := #[RowValue.variable (row 0)], used := 1 + queries := [memoryMessage indices.size (row 0) contents] } + | .load size index => do + let pointer ← values[index]? + let outputs := rowAdvice row 0 size + return { + outputs, used := size + queries := [memoryMessage size pointer.value (rowValues outputs)] } + | .assertEq xs ys _ => do + if xs.size ≠ ys.size then none else do + let left ← Bytecode.AIR.readValues (rowValues values) xs + let right ← Bytecode.AIR.readValues (rowValues values) ys + return { equations := List.ofFn fun i : Fin left.size => + selector * (left[i] - right[i.val]?.getD 0) } + | .ioGetInfo .. => some (emitAdvice row 2) + | .ioRead _ _ size => some (emitAdvice row size) + | .ioSetInfo .. | .ioWrite .. | .debug .. => some {} + | .u8BitDecomposition index => emitByte1 row .bits index values + | .u8ShiftLeft index => emitByte1 row .shiftLeft index values + | .u8ShiftRight index => emitByte1 row .shiftRight index values + | .u8Xor a b => emitByte2 row .xor a b values + | .u8Add a b => emitByte2 row .add a b values + | .u8Sub a b => emitByte2 row .sub a b values + | .u8And a b => emitByte2 row .and a b values + | .u8Or a b => emitByte2 row .or a b values + | .u8LessThan a b => emitByte2 row .lessThan a b values + | .u8RangeCheck a b => emitByte2 row .range a b values + | .u8Mul a b => emitByte2 row .mul a b values + | .u8XorSplit7 a b => emitByte2 row .split7 a b values + | .u8XorSplit4 a b => emitByte2 row .split4 a b values + | .u32LessThan a b => emitU32LessThan row selector a b values + | .unconstrainedBigUintDivMod .. => some (emitAdvice row 2) + | .unconstrainedGToBytes .. => some (emitAdvice row 8) + | .unconstrainedGInverse .. => some (emitAdvice row 1) + | .unconstrainedU32Add a b => emitU32Add row a b none values + | .unconstrainedU32Add3 a b c => emitU32Add row a b (some c) values + | .u32ToField indices => do return { outputs := #[← readRowWord values indices] } + +theorem rowValues_read {values : Array RowValue} {index : ValIdx} {value : RowValue} + (read : values[index]? = some value) : (rowValues values)[index]? = some value.value := by + simp only [rowValues, Array.getElem?_map, read, Option.map_some] + +theorem rowValues_advice_size (row : Nat → G) (start count : Nat) : + (rowValues (rowAdvice row start count)).size = count := by + simp only [rowValues, rowAdvice, Array.size_map, Array.size_ofFn] + +theorem rowValues_singleton (value : RowValue) : rowValues #[value] = #[value.value] := by + simp only [rowValues, Array.map_singleton] + +theorem rowValues_empty : rowValues #[] = #[] := by + simp only [rowValues, Array.map_empty] + +theorem rowValues_extendOutputs (kind : Byte2Kind) (left right : RowValue) + (outputs : Array RowValue) : + rowValues (kind.extendRowOutputs left right outputs) = + kind.extendOutputs left.value right.value (rowValues outputs) := by + cases kind <;> simp only [Byte2Kind.extendRowOutputs, Byte2Kind.extendOutputs, + rowValues, Array.map_push] + +theorem readRowWord_value {values : Array RowValue} {indices : Array ValIdx} {word : RowValue} + (read : readRowWord values indices = some word) : + Bytecode.AIR.readWord (rowValues values) indices = some word.value := by + simp only [readRowWord, bind, Option.bind] at read + split at read + · cases read + · have equal := Option.some.inj read + rw [← equal] + assumption + +theorem emitByte1_step {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) (memory : Bytecode.AIR.Memory) + {row : Nat → G} {kind : Byte1Kind} {index : ValIdx} {values : Array RowValue} + {emission : OpEmission} (emitted : emitByte1 row kind index values = some emission) + (queried : emission.queries ⊆ queries) : + Bytecode.AIR.Step memory (kind.op index) (rowValues values) + (rowValues values ++ rowValues emission.outputs) (emission.calls.map Prod.fst) := by + simp only [emitByte1, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i input read + have equal := Option.some.inj emitted + subst emission + exact global.byte1_step memory (rowValues_read read) (rowValues_advice_size _ _ _) + (queried List.mem_cons_self) + +theorem emitByte2_step {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) (memory : Bytecode.AIR.Memory) + {row : Nat → G} {kind : Byte2Kind} {left right : ValIdx} {values : Array RowValue} + {emission : OpEmission} (emitted : emitByte2 row kind left right values = some emission) + (queried : emission.queries ⊆ queries) : + Bytecode.AIR.Step memory (kind.op left right) (rowValues values) + (rowValues values ++ rowValues emission.outputs) (emission.calls.map Prod.fst) := by + simp only [emitByte2, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i x readX + dsimp only at emitted + split at emitted + · cases emitted + · rename_i y readY + have equal := Option.some.inj emitted + subst emission + simp only [rowValues_extendOutputs] + exact global.byte2_step memory (rowValues_read readX) (rowValues_read readY) + (rowValues_advice_size _ _ _) (queried List.mem_cons_self) + +theorem GlobalLookups.range4 {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) (bytes : Fin 4 → G) + (queried : range4Queries bytes ⊆ queries) : ∀ i, (bytes i).n < 256 := by + have first := global.byte2 (kind := .range) (x := bytes 0) (y := bytes 1) (outputs := #[]) rfl + (queried (by simp [range4Queries, rangeMessage])) + have last := global.byte2 (kind := .range) (outputs := #[]) rfl + (queried (by simp [range4Queries, rangeMessage] : rangeMessage (bytes 2, bytes 3) ∈ range4Queries bytes)) + intro i + have cases : i = 0 ∨ i = 1 ∨ i = 2 ∨ i = 3 := by omega + rcases cases with rfl | rfl | rfl | rfl + · exact first.1 + · exact first.2.1 + · exact last.1 + · exact last.2.1 + +theorem emitU32LessThan_step {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) (memory : Bytecode.AIR.Memory) + {row : Nat → G} {selector : G} {left right : ValIdx} {values : Array RowValue} + {emission : OpEmission} (emitted : emitU32LessThan row selector left right values = some emission) + (active : selector = 1) (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (queried : emission.queries ⊆ queries) : + Bytecode.AIR.Step memory (.u32LessThan left right) (rowValues values) + (rowValues values ++ rowValues emission.outputs) (emission.calls.map Prod.fst) := by + simp only [emitU32LessThan, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i a readA + dsimp only at emitted + split at emitted + · cases emitted + · rename_i b readB + have equal := Option.some.inj emitted + subst emission + simp only [rowValues_singleton] + apply active_u32_less_than_step memory active (rowValues_read readA) (rowValues_read readB) + (fun index => row index.val) (fun index => row (4 + index.val)) (fun index => row (8 + index.val)) + · exact global.range4 _ (fun message member => queried + (List.mem_append_left _ (List.mem_append_left _ member))) + · exact global.range4 _ (fun message member => queried + (List.mem_append_left _ (List.mem_append_right _ member))) + · exact global.range4 _ (fun message member => queried (List.mem_append_right _ member)) + · exact satisfied _ List.mem_cons_self + · exact satisfied _ (List.mem_cons_of_mem _ List.mem_cons_self) + · intro index + apply satisfied + exact List.mem_cons_of_mem _ (List.mem_cons_of_mem _ (List.mem_ofFn.mpr ⟨index, rfl⟩)) + +theorem emitU32Add_step (memory : Bytecode.AIR.Memory) + {row : Nat → G} {left right : Array ValIdx} {values : Array RowValue} {emission : OpEmission} + (emitted : emitU32Add row left right none values = some emission) : + Bytecode.AIR.Step memory (.unconstrainedU32Add left right) (rowValues values) + (rowValues values ++ rowValues emission.outputs) (emission.calls.map Prod.fst) := by + simp only [emitU32Add, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i x readX + dsimp only at emitted + split at emitted + · cases emitted + · rename_i y readY + have equal := Option.some.inj emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 4)) + simp only [Bytecode.AIR.primitive, readRowWord_value readX, readRowWord_value readY, + Bytecode.AIR.adviceOfSize, rowValues_advice_size, ite_true, bind, Option.bind] + simp only [RowValue.add, RowValue.pack, rowValues, Array.map_push, pure] + +theorem emitU32Add3_step (memory : Bytecode.AIR.Memory) + {row : Nat → G} {left right third : Array ValIdx} {values : Array RowValue} {emission : OpEmission} + (emitted : emitU32Add row left right (some third) values = some emission) : + Bytecode.AIR.Step memory (.unconstrainedU32Add3 left right third) (rowValues values) + (rowValues values ++ rowValues emission.outputs) (emission.calls.map Prod.fst) := by + simp only [emitU32Add, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i x readX + dsimp only at emitted + split at emitted + · cases emitted + · rename_i y readY + dsimp only at emitted + cases readZ : readRowWord values third with + | none => simp only [readZ, Option.map_none] at emitted; cases emitted + | some z => + simp only [readZ, Option.map_some] at emitted + have equal := Option.some.inj emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 4)) + simp only [Bytecode.AIR.primitive, readRowWord_value readX, readRowWord_value readY, + readRowWord_value readZ, Bytecode.AIR.adviceOfSize, rowValues_advice_size, + ite_true, bind, Option.bind] + simp only [RowValue.add, RowValue.pack, rowValues, Array.map_push, pure] + +theorem active_array_equality {selector : G} {left right : Array G} + (active : selector = 1) (sizes : left.size = right.size) + (equations : ∀ equation ∈ (List.ofFn fun i : Fin left.size => + selector * (left[i] - right[i.val]?.getD 0)), equation = 0) : left = right := by + apply Array.ext sizes + intro index leftBound rightBound + have equal := active_case active (equations _ (List.mem_ofFn.mpr ⟨⟨index, leftBound⟩, rfl⟩)) + simpa only [Fin.getElem_fin, Array.getElem?_eq_getElem rightBound, Option.getD_some] using equal + +/-- A successful valued emission on an active row has the full relational +meaning of its bytecode operation. Byte and memory facts come from the one +global pool; constrained calls remain requests for the later rank induction. -/ +theorem emitOp_step {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + {program : Toplevel} {op : Op} (shape : op.lookupShape program = true) + {row : Nat → G} {selector rank : G} {values : Array RowValue} {emission : OpEmission} + (emitted : emitOp row selector rank op values = some emission) + (active : selector = 1) (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (queried : emission.queries ⊆ queries) : + Bytecode.AIR.Step (memoryFacts tables.memory) op (rowValues values) + (rowValues values ++ rowValues emission.outputs) (emission.calls.map Prod.fst) := by + cases op with + | const value => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues_singleton, RowValue.konst] + | add a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i x readX + dsimp only at emitted + split at emitted + · cases emitted + · rename_i y readY + have equal := Option.some.inj emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues_read readX, rowValues_read readY, + bind, Option.bind, pure, rowValues_singleton, RowValue.add] + | sub a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i x readX + dsimp only at emitted + split at emitted + · cases emitted + · rename_i y readY + have equal := Option.some.inj emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues_read readX, rowValues_read readY, + bind, Option.bind, pure, rowValues_singleton, RowValue.sub] + | mul a b => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i x readX + dsimp only at emitted + split at emitted + · cases emitted + · rename_i y readY + dsimp only at emitted + split at emitted + · have equal := Option.some.inj emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues_read readX, rowValues_read readY, + bind, Option.bind, pure, rowValues_singleton, RowValue.mul] + · have equal := Option.some.inj emitted + subst emission + have product := active_case active (satisfied _ List.mem_cons_self) + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues_read readX, rowValues_read readY, + bind, Option.bind, pure, rowValues_singleton, RowValue.variable, product, RowValue.mul] + | eqZero a => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i input read + dsimp only at emitted + split at emitted + · have equal := Option.some.inj emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues_read read, bind, Option.bind, + pure, rowValues_singleton, RowValue.konst] + · have equal := Option.some.inj emitted + subst emission + have result := active_eqZero active (satisfied _ List.mem_cons_self) + (satisfied _ (List.mem_cons_of_mem _ List.mem_cons_self)) + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues_read read, bind, Option.bind, + pure, rowValues_singleton, RowValue.variable, result] + | call function indices size unconstrained => + cases unconstrained with + | true => + simp only [emitOp, ite_true, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 size)) + simp only [Bytecode.AIR.primitive, Bytecode.AIR.adviceOfSize, rowValues_advice_size, ite_true, emitAdvice] + | false => + simp only [emitOp, Bool.false_eq_true, ite_false, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i inputs read + have equal := Option.some.inj emitted + subst emission + exact Bytecode.AIR.Step.call + (request := ⟨function, inputs, rowValues (rowAdvice row 0 size), + rank + 1 + packRank (fun index => row (size + index.val))⟩) + read (rowValues_advice_size row 0 size) + | store indices => + have widthBound : indices.size < gSize.toNat := by + simpa only [Op.lookupShape, decide_eq_true_eq] using shape + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i contents read + have equal := Option.some.inj emitted + subst emission + have size := Bytecode.AIR.readValues_size read + have fact := global.memory_fact memoryValid canonical widthBound size (queried List.mem_cons_self) + rw [← size] at fact + simpa only [rowValues_singleton, RowValue.variable, Array.push_eq_append, List.map_nil] using + Bytecode.AIR.Step.store read fact + | load size index => + have widthBound : size < gSize.toNat := by + simpa only [Op.lookupShape, decide_eq_true_eq] using shape + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i pointer read + have equal := Option.some.inj emitted + subst emission + exact Bytecode.AIR.Step.load (rowValues_read read) (rowValues_advice_size _ _ _) + (global.memory_fact memoryValid canonical widthBound (rowValues_advice_size _ _ _) + (queried List.mem_cons_self)) + | assertEq xs ys message => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i sameSize + split at emitted + · cases emitted + · rename_i left readLeft + dsimp only at emitted + split at emitted + · cases emitted + · rename_i right readRight + have equal := Option.some.inj emitted + subst emission + have sizes : left.size = right.size := by + have := Bytecode.AIR.readValues_size readLeft + have := Bytecode.AIR.readValues_size readRight + omega + have contents := active_array_equality active sizes satisfied + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [rowValues_empty] + simp only [Bytecode.AIR.primitive, readLeft, readRight, bind, Option.bind, + if_pos contents] + | ioGetInfo key data => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 2)) + simp only [Bytecode.AIR.primitive, Bytecode.AIR.adviceOfSize, rowValues_advice_size, ite_true, emitAdvice] + | ioRead key offset size => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 size)) + simp only [Bytecode.AIR.primitive, Bytecode.AIR.adviceOfSize, rowValues_advice_size, ite_true, emitAdvice] + | ioSetInfo key data flag length => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues, Array.map_empty] + | ioWrite key data => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues, Array.map_empty] + | debug message data => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, rowValues, Array.map_empty] + | u8BitDecomposition index => exact emitByte1_step global _ emitted queried + | u8ShiftLeft index => exact emitByte1_step global _ emitted queried + | u8ShiftRight index => exact emitByte1_step global _ emitted queried + | u8Xor a b => exact emitByte2_step global _ emitted queried + | u8Add a b => exact emitByte2_step global _ emitted queried + | u8Sub a b => exact emitByte2_step global _ emitted queried + | u8And a b => exact emitByte2_step global _ emitted queried + | u8Or a b => exact emitByte2_step global _ emitted queried + | u8LessThan a b => exact emitByte2_step global _ emitted queried + | u8RangeCheck a b => exact emitByte2_step global _ emitted queried + | u8Mul a b => exact emitByte2_step global _ emitted queried + | u8XorSplit7 a b => exact emitByte2_step global _ emitted queried + | u8XorSplit4 a b => exact emitByte2_step global _ emitted queried + | u32LessThan a b => exact emitU32LessThan_step global _ emitted active satisfied queried + | unconstrainedBigUintDivMod a b => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 2)) + simp only [Bytecode.AIR.primitive, Bytecode.AIR.adviceOfSize, rowValues_advice_size, ite_true, emitAdvice] + | unconstrainedGToBytes index => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 8)) + simp only [Bytecode.AIR.primitive, Bytecode.AIR.adviceOfSize, rowValues_advice_size, ite_true, emitAdvice] + | unconstrainedGInverse index => + simp only [emitOp, Option.some.injEq] at emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := rowValues (rowAdvice row 0 1)) + simp only [Bytecode.AIR.primitive, Bytecode.AIR.adviceOfSize, rowValues_advice_size, ite_true, emitAdvice] + | unconstrainedU32Add a b => exact emitU32Add_step _ emitted + | unconstrainedU32Add3 a b c => exact emitU32Add3_step _ emitted + | u32ToField indices => + simp only [emitOp, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i word read + have equal := Option.some.inj emitted + subst emission + apply Bytecode.AIR.Step.primitive (advice := #[]) + simp only [Bytecode.AIR.primitive, readRowWord_value read, bind, Option.bind, + pure, rowValues_singleton] + +structure OpsEmission where + values : Array RowValue + column : Nat + equations : List G := [] + queries : List (List G) := [] + calls : List (Bytecode.AIR.Call × (Fin 6 → G)) := [] + +/-- Native operation order, including the logical map extension and exact +advance of the auxiliary-column cursor after each operation. -/ +def emitOps (row : Nat → G) (selector rank : G) : + List Op → Array RowValue → Nat → Option OpsEmission + | [], values, column => some { values, column } + | op :: ops, values, column => do + let first ← emitOp (fun i => row (column + i)) selector rank op values + let rest ← emitOps row selector rank ops (values ++ first.outputs) (column + first.used) + return { rest with + equations := first.equations ++ rest.equations + queries := first.queries ++ rest.queries + calls := first.calls ++ rest.calls } + +theorem rowValues_append (left right : Array RowValue) : + rowValues (left ++ right) = rowValues left ++ rowValues right := by + simp only [rowValues, Array.map_append] + +theorem emitOps_run {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + {program : Toplevel} {ops : List Op} (shapes : ∀ op ∈ ops, op.lookupShape program = true) + {row : Nat → G} {selector rank : G} {values : Array RowValue} {column : Nat} + {emission : OpsEmission} (emitted : emitOps row selector rank ops values column = some emission) + (active : selector = 1) (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (queried : emission.queries ⊆ queries) : + Bytecode.AIR.RunOps (memoryFacts tables.memory) ops (rowValues values) + (rowValues emission.values) (emission.calls.map Prod.fst) := by + induction ops generalizing values column emission with + | nil => + simp only [emitOps, Option.some.injEq] at emitted + subst emission + exact Bytecode.AIR.RunOps.nil + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + · rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + · rename_i rest restEmitted + have equal := Option.some.inj emitted + subst emission + have firstStep := emitOp_step global memoryValid canonical (shapes op List.mem_cons_self) + firstEmitted active + (fun equation member => satisfied equation (List.mem_append_left _ member)) + (fun message member => queried (List.mem_append_left _ member)) + have restRun := ih (fun op member => shapes op (List.mem_cons_of_mem _ member)) + restEmitted (fun equation member => satisfied equation (List.mem_append_right _ member)) + (fun message member => queried (List.mem_append_right _ member)) + rw [rowValues_append] at restRun + simpa only [List.map_append] using Bytecode.AIR.RunOps.cons firstStep restRun + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/OperationSequences.lean b/Ix/Aiur/Proofs/OperationSequences.lean new file mode 100644 index 000000000..7e24a5bb7 --- /dev/null +++ b/Ix/Aiur/Proofs/OperationSequences.lean @@ -0,0 +1,207 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationReflection + +/-! +Symbolic operation sequences preserve the logical value map and fresh-column +cursor. Their reflection derives the entire valued emission from successful +symbolic emission and defined reads of exactly the consumed column interval. +-/ + +namespace Aiur.NativeAIR.OpEmitter + +theorem evalRows_append {values : Values G} {left right : Array RowExpr} + {a b : Array AIR.RowValue} (leftEval : evalRows values left = some a) + (rightEval : evalRows values right = some b) : + evalRows values (left ++ right) = some (a ++ b) := by + have leftList := congrArg (Functor.map Array.toList) leftEval + have rightList := congrArg (Functor.map Array.toList) rightEval + change (Functor.map Array.toList) (left.mapM (RowExpr.eval values)) = _ at leftList + change (Functor.map Array.toList) (right.mapM (RowExpr.eval values)) = _ at rightList + rw [Array.toList_mapM] at leftList rightList + simp only [Functor.map, Option.map_some] at leftList rightList + simp only [evalRows, Array.mapM_eq_mapM_toList, Array.toList_append, + List.mapM_append, leftList, rightList, bind, Option.bind_some, pure, + Functor.map, Option.map_some] + congr 1 + apply Array.toList_inj.mp + simp only [Array.toList_append] + +theorem Normal.append {left right : Array RowExpr} (a : Normal left) (b : Normal right) : + Normal (left ++ right) := by + intro row member + rcases Array.mem_append.mp member with member | member + · exact a row member + · exact b row member + +theorem Emission.eval_components {values : Values G} {emission : Emission} {result : AIR.OpEmission} + (evaluated : emission.eval values = some result) : + evalRows values emission.outputs = some result.outputs ∧ emission.used = result.used ∧ + emission.equations.mapM (evalExpr values) = some result.equations ∧ + emission.queries.mapM (List.mapM (evalExpr values)) = some result.queries ∧ + emission.calls.mapM (CallExpr.eval values) = some result.calls := by + simp only [Emission.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i outputs outputsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i equations equationsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i queries queriesEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i calls callsEval + cases evaluated + exact ⟨outputsEval, rfl, equationsEval, queriesEval, callsEval⟩ + +structure OpsEmission where + values : Array RowExpr + column : Nat + equations : List Expr := [] + queries : List (List Expr) := [] + calls : List CallExpr := [] + +def OpsEmission.eval (values : Values G) (emission : OpsEmission) : Option AIR.OpsEmission := do + let outputs ← evalRows values emission.values + let equations ← emission.equations.mapM (evalExpr values) + let queries ← emission.queries.mapM (List.mapM (evalExpr values)) + let calls ← emission.calls.mapM (CallExpr.eval values) + return ⟨outputs, emission.column, equations, queries, calls⟩ + +theorem OpsEmission.eval_of {values : Values G} {emission : OpsEmission} {result : AIR.OpsEmission} + (outputs : evalRows values emission.values = some result.values) + (column : emission.column = result.column) + (equations : emission.equations.mapM (evalExpr values) = some result.equations) + (queries : emission.queries.mapM (List.mapM (evalExpr values)) = some result.queries) + (calls : emission.calls.mapM (CallExpr.eval values) = some result.calls) : + emission.eval values = some result := by + simp only [OpsEmission.eval, outputs, equations, queries, calls, column, bind, Option.bind_some, pure] + +theorem OpsEmission.eval_components {values : Values G} {emission : OpsEmission} {result : AIR.OpsEmission} + (evaluated : emission.eval values = some result) : + evalRows values emission.values = some result.values ∧ emission.column = result.column ∧ + emission.equations.mapM (evalExpr values) = some result.equations ∧ + emission.queries.mapM (List.mapM (evalExpr values)) = some result.queries ∧ + emission.calls.mapM (CallExpr.eval values) = some result.calls := by + simp only [OpsEmission.eval, bind, Option.bind] at evaluated + split at evaluated + · cases evaluated + rename_i outputs outputsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i equations equationsEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i queries queriesEval + dsimp only at evaluated + split at evaluated + · cases evaluated + rename_i calls callsEval + cases evaluated + exact ⟨outputsEval, rfl, equationsEval, queriesEval, callsEval⟩ + +def emitOps (selector rank : Expr) : List Bytecode.Op → Array RowExpr → Nat → Option OpsEmission + | [], rows, column => some { values := rows, column } + | op :: ops, rows, column => do + let first ← emitOp selector rank column op rows + let rest ← emitOps selector rank ops (rows ++ first.outputs) (column + first.used) + return { rest with + equations := first.equations ++ rest.equations + queries := first.queries ++ rest.queries + calls := first.calls ++ rest.calls } + +theorem emitOps_column {selector rank : Expr} {ops : List Bytecode.Op} {rows : Array RowExpr} + {column : Nat} {emission : OpsEmission} + (emitted : emitOps selector rank ops rows column = some emission) : column ≤ emission.column := by + induction ops generalizing rows column emission with + | nil => + cases emitted + exact Nat.le_refl _ + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + exact Nat.le_trans (Nat.le_add_right _ _) (ih (emission := rest) restEmitted) + +theorem emitOps_normal {selector rank : Expr} {ops : List Bytecode.Op} {rows : Array RowExpr} + {column : Nat} {emission : OpsEmission} (normal : Normal rows) + (emitted : emitOps selector rank ops rows column = some emission) : Normal emission.values := by + induction ops generalizing rows column emission with + | nil => + cases emitted + exact normal + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + exact ih (emission := rest) (normal.append (emitOp_normal normal firstEmitted)) restEmitted + +theorem emitOps_reflects (values : Values G) (row : Nat → G) + {selector rank : Expr} {s r : G} {ops : List Bytecode.Op} {rows : Array RowExpr} + {inputs : Array AIR.RowValue} {column : Nat} {emission : OpsEmission} + (selectorEval : evalExpr values selector = some s) (rankEval : evalExpr values rank = some r) + (inputEval : evalRows values rows = some inputs) (normal : Normal rows) + (emitted : emitOps selector rank ops rows column = some emission) + (reads : ∀ index, column ≤ index → index < emission.column → + (values.columns .main .current)[index]? = some (row index)) : + ∃ result, AIR.emitOps row s r ops inputs column = some result ∧ emission.eval values = some result := by + induction ops generalizing rows inputs column emission with + | nil => + cases emitted + exact ⟨_, rfl, OpsEmission.eval_of inputEval rfl rfl rfl rfl⟩ + | cons op ops ih => + simp only [emitOps, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + have bound := emitOps_column restEmitted + obtain ⟨firstValue, firstValueEmitted, firstEval⟩ := emitOp_reflects values + (fun index => row (column + index)) selectorEval rankEval inputEval normal firstEmitted + (fun index indexBound => reads (column + index) (by omega) (by dsimp only; omega)) + obtain ⟨firstOutputs, used, firstEquations, firstQueries, firstCalls⟩ := + Emission.eval_components firstEval + obtain ⟨restValue, restValueEmitted, restEval⟩ := ih (evalRows_append inputEval firstOutputs) + (normal.append (emitOp_normal normal firstEmitted)) restEmitted + (fun index lower upper => reads index (by omega) upper) + obtain ⟨restOutputs, finish, restEquations, restQueries, restCalls⟩ := + OpsEmission.eval_components restEval + refine ⟨{ restValue with + equations := firstValue.equations ++ restValue.equations + queries := firstValue.queries ++ restValue.queries + calls := firstValue.calls ++ restValue.calls }, ?_, ?_⟩ + · simp only [AIR.emitOps, firstValueEmitted, bind, Option.bind_some, ← used, + restValueEmitted, pure] + · apply OpsEmission.eval_of + · exact restOutputs + · exact finish + all_goals + simp only [List.mapM_append, firstEquations, restEquations, firstQueries, + restQueries, firstCalls, restCalls, bind, Option.bind_some, pure] + +end Aiur.NativeAIR.OpEmitter diff --git a/Ix/Aiur/Proofs/Polynomial.lean b/Ix/Aiur/Proofs/Polynomial.lean new file mode 100644 index 000000000..1e9c7840f --- /dev/null +++ b/Ix/Aiur/Proofs/Polynomial.lean @@ -0,0 +1,463 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Polynomial +import Ix.Aiur.Proofs.QuotientAlgebra +import Ix.Aiur.Proofs.FriDomain + +/-! Coefficient identities and the distinct-root bound used by native +polynomial checks. Ring identities are separate from the no-zero-divisor +condition, which is proved for both native fields below. +-/ + +namespace Aiur.NativeAIR.Polynomial + +open Lean.Grind +open _root_.Aiur.NativeAIR.Quotient (horner horner_nil horner_cons) + +section Ring + +variable {R : Type} [CommRing R] + +theorem isZero_nil : IsZero ([] : List R) := by intro coefficient member; cases member + +theorem isZero_iff_all [BEq R] [LawfulBEq R] (coefficients : List R) : + IsZero coefficients ↔ coefficients.all (· == 0) = true := by + simp only [IsZero, List.all_eq_true, beq_iff_eq] + +theorem isZero_cons (coefficient : R) (rest : List R) : + IsZero (coefficient :: rest) ↔ coefficient = 0 ∧ IsZero rest := by + simp only [IsZero, List.mem_cons, forall_eq_or_imp] + +theorem isZero_append (left right : List R) : IsZero (left ++ right) ↔ IsZero left ∧ IsZero right := by + constructor + · intro zero + exact ⟨fun value member => zero value (List.mem_append_left _ member), + fun value member => zero value (List.mem_append_right _ member)⟩ + · rintro ⟨leftZero, rightZero⟩ value member + exact (List.mem_append.mp member).elim (leftZero value) (rightZero value) + +theorem monic_nonzero {coefficients : List R} (monic : Monic coefficients) + (nontrivial : (1 : R) ≠ 0) : ¬ IsZero coefficients := by + obtain ⟨initial, rfl⟩ := monic + intro zero + exact nontrivial (zero 1 (by simp)) + +theorem sub_nil (left : List R) : sub left [] = left := by cases left <;> rfl + +theorem horner_zero (point : R) {coefficients : List R} (zero : IsZero coefficients) : + horner point coefficients = 0 := by + induction coefficients with + | nil => rfl + | cons coefficient rest ih => + obtain ⟨first, tail⟩ := (isZero_cons _ _).mp zero + rw [horner_cons, first, ih tail, Semiring.mul_zero, Semiring.add_zero] + +theorem add_length (left right : List R) : (add left right).length = max left.length right.length := by + induction left generalizing right with + | nil => simp only [add, List.length_nil, Nat.zero_max] + | cons first left ih => + cases right with + | nil => simp only [add, List.length_nil, Nat.max_zero] + | cons second right => simp only [add, List.length_cons, ih, Nat.succ_max_succ] + +theorem sub_length (left right : List R) : (sub left right).length = max left.length right.length := by + induction left generalizing right with + | nil => simp only [sub, List.length_map, List.length_nil, Nat.zero_max] + | cons first left ih => + cases right with + | nil => simp only [sub, List.length_nil, Nat.max_zero] + | cons second right => simp only [sub, List.length_cons, ih, Nat.succ_max_succ] + +theorem scale_length (scalar : R) (coefficients : List R) : + (scale scalar coefficients).length = coefficients.length := List.length_map _ + +theorem sub_append (left right firstTail secondTail : List R) (same : left.length = right.length) : + sub (left ++ firstTail) (right ++ secondTail) = sub left right ++ sub firstTail secondTail := by + induction left generalizing right with + | nil => + have empty : right = [] := by simpa using same.symm + subst right + rfl + | cons first left ih => + cases right with + | nil => simp only [List.length_nil, List.length_cons] at same; omega + | cons second right => + have tailSame : left.length = right.length := by simpa only [List.length_cons, Nat.succ.injEq] using same + simp only [List.cons_append, sub, ih right tailSame] + +theorem sub_append_left (left right tail : List R) (bounded : right.length ≤ left.length) : + sub (left ++ tail) right = sub left right ++ tail := by + induction left generalizing right with + | nil => + have empty : right = [] := by simpa using bounded + subst right + simp only [List.nil_append, sub_nil] + | cons first left ih => + cases right with + | nil => simp only [sub_nil] + | cons second right => + have tailBound : right.length ≤ left.length := by simp only [List.length_cons] at bounded; omega + simp only [List.cons_append, sub, ih right tailBound] + +theorem horner_add (point : R) (left right : List R) : + horner point (add left right) = horner point left + horner point right := by + induction left generalizing right with + | nil => rw [add, horner_nil]; grind + | cons first left ih => + cases right with + | nil => change horner point (first :: left) = horner point (first :: left) + 0; grind + | cons second right => rw [add, horner_cons, ih, horner_cons, horner_cons]; grind + +theorem horner_neg (point : R) (coefficients : List R) : + horner point (coefficients.map (0 - ·)) = 0 - horner point coefficients := by + induction coefficients with + | nil => simp only [List.map_nil, horner_nil]; grind + | cons first rest ih => rw [List.map_cons, horner_cons, ih, horner_cons]; grind + +theorem horner_sub (point : R) (left right : List R) : + horner point (sub left right) = horner point left - horner point right := by + induction left generalizing right with + | nil => rw [sub, horner_neg, horner_nil] + | cons first left ih => + cases right with + | nil => change horner point (first :: left) = horner point (first :: left) - 0; grind + | cons second right => rw [sub, horner_cons, ih, horner_cons, horner_cons]; grind + +theorem horner_scale (point scalar : R) (coefficients : List R) : + horner point (scale scalar coefficients) = scalar * horner point coefficients := by + induction coefficients with + | nil => change 0 = scalar * 0; grind + | cons first rest ih => + change scalar * first + point * horner point (scale scalar rest) = scalar * (first + point * horner point rest) + rw [ih] + grind + +theorem mulLinear_length (root : R) (coefficients : List R) : + (mulLinear root coefficients).length = coefficients.length + 1 := by + rw [mulLinear, sub_length, scale_length, List.length_cons, Nat.max_eq_left (by omega)] + +theorem horner_mulLinear (point root : R) (coefficients : List R) : + horner point (mulLinear root coefficients) = (point - root) * horner point coefficients := by + rw [mulLinear, horner_sub, horner_cons, horner_scale] + grind + +theorem fromRoots_length (roots : List R) : (fromRoots roots).length = roots.length + 1 := by + induction roots with + | nil => rfl + | cons root roots ih => + change (mulLinear root (fromRoots roots)).length = (root :: roots).length + 1 + rw [mulLinear_length, ih, List.length_cons] + +theorem horner_fromRoots (point : R) (roots : List R) : + horner point (fromRoots roots) = LogUp.product (roots.map (point - ·)) := by + induction roots with + | nil => change 1 + point * 0 = 1; grind + | cons root roots ih => + change horner point (mulLinear root (fromRoots roots)) = _ + rw [horner_mulLinear, ih, List.map_cons, LogUp.product_cons] + +theorem mulLinear_monic (root : R) {coefficients : List R} (monic : Monic coefficients) : + Monic (mulLinear root coefficients) := by + obtain ⟨initial, rfl⟩ := monic + refine ⟨sub (0 :: initial) (scale root (initial ++ [1])), ?_⟩ + rw [mulLinear, ← List.cons_append, sub_append_left] + simp only [scale_length, List.length_append, List.length_cons, List.length_nil] + omega + +theorem fromRoots_monic (roots : List R) : Monic (fromRoots roots) := by + induction roots with + | nil => exact ⟨[], rfl⟩ + | cons root roots ih => exact mulLinear_monic root ih + +theorem fromRoots_nonzero (roots : List R) (nontrivial : (1 : R) ≠ 0) : ¬ IsZero (fromRoots roots) := + monic_nonzero (fromRoots_monic roots) nontrivial + +theorem fromRoots_vanishes (roots : List R) (point : R) (member : point ∈ roots) : + horner point (fromRoots roots) = 0 := by + induction roots with + | nil => cases member + | cons root roots ih => + change horner point (mulLinear root (fromRoots roots)) = 0 + rw [horner_mulLinear] + rcases List.mem_cons.mp member with same | later + · rw [same]; grind + · rw [ih later, Semiring.mul_zero] + +theorem powerMinus_length (degree : Nat) (constant : R) : + (powerMinus degree constant).length = degree + 1 := by + rw [powerMinus, sub_length] + simp only [List.length_append, List.length_replicate, List.length_cons, List.length_nil] + omega + +theorem powerMinus_monic {degree : Nat} (positive : 0 < degree) (constant : R) : + Monic (powerMinus degree constant) := by + refine ⟨sub (List.replicate degree 0) [constant], ?_⟩ + rw [powerMinus, sub_append_left] + simp only [List.length_cons, List.length_nil, List.length_replicate] + omega + +theorem horner_replicate_zero (point : R) (count : Nat) : horner point (List.replicate count 0) = 0 := + horner_zero point (by intro value member; exact List.mem_replicate.mp member |>.2) + +theorem horner_powerMinus (point constant : R) (degree : Nat) : + horner point (powerMinus degree constant) = point ^ degree - constant := by + rw [powerMinus, horner_sub, Quotient.horner_append, horner_replicate_zero, List.length_replicate] + simp only [horner_cons, horner_nil] + grind + +theorem divide_length (point : R) (coefficients : List R) : + (divide point coefficients).length = coefficients.length - 1 := by + induction coefficients using divide.induct with + | case1 => rfl + | case2 first => rfl + | case3 first next rest ih => + simp only [divide, List.length_cons, ih] + omega + +theorem divide_factor (point root : R) (coefficients : List R) : + horner point coefficients = horner root coefficients + (point - root) * horner point (divide root coefficients) := by + induction coefficients using divide.induct with + | case1 => simp only [divide, horner_nil]; grind + | case2 first => simp only [divide, horner_cons, horner_nil]; grind + | case3 first next rest ih => + change first + point * horner point (next :: rest) = + first + root * horner root (next :: rest) + (point - root) * + (horner root (next :: rest) + point * horner point (divide root (next :: rest))) + grind + +theorem zero_of_divide_zero (root : R) (coefficients : List R) + (vanishes : horner root coefficients = 0) (zero : IsZero (divide root coefficients)) : IsZero coefficients := by + induction coefficients using divide.induct with + | case1 => exact isZero_nil + | case2 first => + apply (isZero_cons _ _).mpr + constructor + · simpa only [horner_cons, horner_nil, Semiring.mul_zero, Semiring.add_zero] using vanishes + · exact isZero_nil + | case3 first next rest ih => + obtain ⟨nextZero, tailZero⟩ := (isZero_cons _ _).mp zero + have tail := ih nextZero tailZero + apply (isZero_cons _ _).mpr + constructor + · simpa only [horner_cons, nextZero, Semiring.mul_zero, Semiring.add_zero] using vanishes + · exact tail + +theorem divide_nonzero (root : R) {coefficients : List R} + (nonzero : ¬ IsZero coefficients) (vanishes : horner root coefficients = 0) : + ¬ IsZero (divide root coefficients) := fun zero => nonzero (zero_of_divide_zero root coefficients vanishes zero) + +end Ring + +section Domain + +variable {R : Type} [CommRing R] +variable (noZeroDivisors : ∀ a b : R, a * b = 0 → a = 0 ∨ b = 0) +include noZeroDivisors + +theorem divide_root (root point : R) (coefficients : List R) + (atRoot : horner root coefficients = 0) (atPoint : horner point coefficients = 0) + (different : point ≠ root) : horner point (divide root coefficients) = 0 := by + have factor := divide_factor point root coefficients + rw [atRoot, atPoint] at factor + have productZero : (point - root) * horner point (divide root coefficients) = 0 := by grind + exact (noZeroDivisors _ _ productZero).resolve_left + (fun zero => different ((LogUp.sub_zero_iff _ _).mp zero)) + +theorem roots_lt_length (coefficients roots : List R) (nonzero : ¬ IsZero coefficients) + (unique : roots.Nodup) (vanishes : ∀ point ∈ roots, horner point coefficients = 0) : + roots.length < coefficients.length := by + suffices bounded : ∀ fuel (coefficients roots : List R), coefficients.length ≤ fuel → + ¬ IsZero coefficients → roots.Nodup → + (∀ point ∈ roots, horner point coefficients = 0) → roots.length < coefficients.length from + bounded coefficients.length coefficients roots (by omega) nonzero unique vanishes + intro fuel + induction fuel with + | zero => + intro coefficients roots lengthBound nonzero unique vanishes + cases coefficients with + | nil => exact False.elim (nonzero isZero_nil) + | cons first rest => simp only [List.length_cons] at lengthBound; omega + | succ fuel ih => + intro coefficients roots lengthBound nonzero unique vanishes + cases roots with + | nil => + cases coefficients with + | nil => exact False.elim (nonzero isZero_nil) + | cons first rest => exact Nat.zero_lt_succ _ + | cons root roots => + obtain ⟨absent, tailUnique⟩ := List.nodup_cons.mp unique + have atRoot := vanishes root (by simp) + have quotientNonzero := divide_nonzero root nonzero atRoot + have quotientBound : (divide root coefficients).length ≤ fuel := by rw [divide_length]; omega + have tailZero : ∀ point ∈ roots, horner point (divide root coefficients) = 0 := by + intro point member + apply divide_root noZeroDivisors root point coefficients atRoot (vanishes point (by simp [member])) + intro equal + exact absent (equal ▸ member) + have shorter := ih (divide root coefficients) roots quotientBound quotientNonzero tailUnique tailZero + rw [divide_length] at shorter + simp only [List.length_cons] + omega + +theorem roots_le_degree (coefficients roots : List R) (nonzero : ¬ IsZero coefficients) + (unique : roots.Nodup) (vanishes : ∀ point ∈ roots, horner point coefficients = 0) : + roots.length ≤ coefficients.length - 1 := by + have := roots_lt_length noZeroDivisors coefficients roots nonzero unique vanishes + omega + +theorem zero_of_roots (coefficients roots : List R) (unique : roots.Nodup) + (enough : coefficients.length ≤ roots.length) + (vanishes : ∀ point ∈ roots, horner point coefficients = 0) : IsZero coefficients := by + apply Classical.byContradiction + intro nonzero + have := roots_lt_length noZeroDivisors coefficients roots nonzero unique vanishes + omega + +theorem zero_sub_of_samples (left right samples : List R) (unique : samples.Nodup) + (leftBound : left.length ≤ samples.length) (rightBound : right.length ≤ samples.length) + (equal : ∀ point ∈ samples, horner point left = horner point right) : IsZero (sub left right) := by + apply zero_of_roots noZeroDivisors (sub left right) samples unique + · rw [sub_length] + exact Nat.max_le.mpr ⟨leftBound, rightBound⟩ + · intro point member + rw [horner_sub, equal point member] + grind + +theorem equal_of_samples (left right samples : List R) (unique : samples.Nodup) + (leftBound : left.length ≤ samples.length) (rightBound : right.length ≤ samples.length) + (equal : ∀ point ∈ samples, horner point left = horner point right) (point : R) : + horner point left = horner point right := by + have zero := horner_zero point (zero_sub_of_samples noZeroDivisors left right samples unique leftBound rightBound equal) + rw [horner_sub] at zero + exact (LogUp.sub_zero_iff _ _).mp zero + +theorem monic_zero_sub_of_samples (left right samples : List R) + (leftMonic : Monic left) (rightMonic : Monic right) (unique : samples.Nodup) + (sameLength : left.length = right.length) (enough : left.length ≤ samples.length + 1) + (equal : ∀ point ∈ samples, horner point left = horner point right) : IsZero (sub left right) := by + obtain ⟨leftPrefix, rfl⟩ := leftMonic + obtain ⟨rightPrefix, rfl⟩ := rightMonic + have same : leftPrefix.length = rightPrefix.length := by + simp only [List.length_append, List.length_cons, List.length_nil] at sameLength + omega + have tail : sub ([1] : List R) [1] = [0] := by simp only [sub]; congr 1; grind + rw [sub_append _ _ _ _ same, tail, isZero_append] + refine ⟨?_, (isZero_cons _ _).mpr ⟨rfl, isZero_nil⟩⟩ + apply zero_of_roots noZeroDivisors (sub leftPrefix rightPrefix) samples unique + · rw [sub_length, same, Nat.max_self] + simp only [List.length_append, List.length_cons, List.length_nil] at enough + omega + · intro point member + have atPoint := equal point member + simp only [Quotient.horner_append, horner_cons, horner_nil, same] at atPoint + rw [horner_sub] + grind + +theorem monic_equal_of_samples (left right samples : List R) + (leftMonic : Monic left) (rightMonic : Monic right) (unique : samples.Nodup) + (sameLength : left.length = right.length) (enough : left.length ≤ samples.length + 1) + (equal : ∀ point ∈ samples, horner point left = horner point right) (point : R) : + horner point left = horner point right := by + have zero := horner_zero point + (monic_zero_sub_of_samples noZeroDivisors left right samples leftMonic rightMonic unique sameLength enough equal) + rw [horner_sub] at zero + exact (LogUp.sub_zero_iff _ _).mp zero + +theorem root_product_identity (roots : List R) (constant : R) (unique : roots.Nodup) + (positive : 0 < roots.length) (powers : ∀ root ∈ roots, root ^ roots.length = constant) (point : R) : + LogUp.product (roots.map (point - ·)) = point ^ roots.length - constant := by + rw [← horner_fromRoots, ← horner_powerMinus] + apply monic_equal_of_samples noZeroDivisors (fromRoots roots) (powerMinus roots.length constant) roots + (fromRoots_monic roots) (powerMinus_monic positive constant) unique + · rw [fromRoots_length, powerMinus_length] + · rw [fromRoots_length] + omega + · intro root member + rw [fromRoots_vanishes roots root member, horner_powerMinus, powers root member] + grind + +theorem root_count_le [BEq R] [LawfulBEq R] (coefficients samples : List R) + (nonzero : ¬ IsZero coefficients) (unique : samples.Nodup) : + (samples.filter (fun point => horner point coefficients == 0)).length ≤ coefficients.length - 1 := by + apply roots_le_degree noZeroDivisors coefficients _ nonzero (unique.filter _) + intro point member + exact beq_iff_eq.mp (List.mem_filter.mp member).2 + +theorem equal_count_le [BEq R] [LawfulBEq R] (left right samples : List R) + (different : ¬ IsZero (sub left right)) (unique : samples.Nodup) : + (samples.filter (fun point => horner point left == horner point right)).length ≤ + max left.length right.length - 1 := by + rw [← sub_length] + apply roots_le_degree noZeroDivisors (sub left right) _ different (unique.filter _) + intro point member + rw [horner_sub, beq_iff_eq.mp (List.mem_filter.mp member).2] + grind + +end Domain + +theorem base_roots_lt_length (coefficients roots : List G) (nonzero : ¬ IsZero coefficients) + (unique : roots.Nodup) (vanishes : ∀ point ∈ roots, horner point coefficients = 0) : + roots.length < coefficients.length := + roots_lt_length (fun a b => (G.mul_eq_zero_iff a b).mp) coefficients roots nonzero unique vanishes + +theorem extension_roots_lt_length (coefficients roots : List ProofCodec.Extension) + (nonzero : ¬ IsZero coefficients) (unique : roots.Nodup) + (vanishes : ∀ point ∈ roots, horner point coefficients = 0) : roots.length < coefficients.length := + roots_lt_length (fun a b => (ProofCodec.Extension.mul_eq_zero_iff a b).mp) coefficients roots nonzero unique vanishes + +theorem base_root_count_le (coefficients samples : List G) + (nonzero : ¬ IsZero coefficients) (unique : samples.Nodup) : + (samples.filter (fun point => horner point coefficients == 0)).length ≤ coefficients.length - 1 := + root_count_le (fun a b => (G.mul_eq_zero_iff a b).mp) coefficients samples nonzero unique + +theorem extension_root_count_le (coefficients samples : List ProofCodec.Extension) + (nonzero : ¬ IsZero coefficients) (unique : samples.Nodup) : + (samples.filter (fun point => horner point coefficients == 0)).length ≤ coefficients.length - 1 := + root_count_le (fun a b => (ProofCodec.Extension.mul_eq_zero_iff a b).mp) coefficients samples nonzero unique + +theorem foldingNodes_length (parent arity : Domain.Subgroup) (index : Nat) : + (foldingNodes parent arity index).length = Domain.size arity := by + simp only [foldingNodes, List.length_map, List.length_range] + +theorem foldingNodes_nodup (parent arity : Domain.Subgroup) (nested : arity.val ≤ parent.val) + {index : Nat} (bounded : index < 2^(parent.val - arity.val)) : + (foldingNodes parent arity index).Nodup := by + unfold foldingNodes + rw [List.nodup_iff_pairwise_ne, List.pairwise_map] + apply List.Pairwise.imp_of_mem (R := fun left right : Nat => left ≠ right) _ List.nodup_range + intro left right leftMem rightMem different equal + exact different (FriDomain.foldNode_injective parent arity nested bounded + (List.mem_range.mp leftMem) (List.mem_range.mp rightMem) equal) + +theorem foldingNodes_powers (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) (index : Nat) : + ∀ node ∈ foldingNodes parent arity index, node ^ Domain.size arity = FriDomain.queryPoint child index := by + intro node member + obtain ⟨slot, _, rfl⟩ := List.mem_map.mp member + exact FriDomain.foldNode_power parent child arity dimensions index slot + +theorem folding_product_identity (parent child arity : Domain.Subgroup) + (dimensions : parent.val = child.val + arity.val) {index : Nat} + (bounded : index < 2^(parent.val - arity.val)) (point : ProofCodec.Extension) : + LogUp.product ((foldingNodes parent arity index).map (fun node => point - ProofCodec.Extension.ofBase node)) = + point ^ Domain.size arity - ProofCodec.Extension.ofBase (FriDomain.queryPoint child index) := by + let roots := (foldingNodes parent arity index).map ProofCodec.Extension.ofBase + have length : roots.length = Domain.size arity := by simp only [roots, List.length_map, foldingNodes_length] + have unique : roots.Nodup := by + rw [show roots = (foldingNodes parent arity index).map ProofCodec.Extension.ofBase from rfl, + List.nodup_iff_pairwise_ne, List.pairwise_map] + exact (foldingNodes_nodup parent arity (by omega) bounded).imp + (fun different equal => different (ProofCodec.Extension.ofBase_injective equal)) + have powers : ∀ root ∈ roots, root ^ roots.length = ProofCodec.Extension.ofBase (FriDomain.queryPoint child index) := by + intro root member + change root ∈ (foldingNodes parent arity index).map ProofCodec.Extension.ofBase at member + obtain ⟨node, nodeMember, rfl⟩ := List.mem_map.mp member + rw [length, ← ProofCodec.Extension.ofBase_power, foldingNodes_powers parent child arity dimensions index node nodeMember] + have result := root_product_identity (fun a b => (ProofCodec.Extension.mul_eq_zero_iff a b).mp) + roots _ unique (by rw [length]; exact Domain.size_positive arity) powers point + simpa only [roots, List.map_map, Function.comp_def, length] using result + +end Aiur.NativeAIR.Polynomial diff --git a/Ix/Aiur/Proofs/ProofCodec.lean b/Ix/Aiur/Proofs/ProofCodec.lean new file mode 100644 index 000000000..8924e342e --- /dev/null +++ b/Ix/Aiur/Proofs/ProofCodec.lean @@ -0,0 +1,315 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ProofCodec +import Ix.Aiur.Proofs.KeyCodec + +/-! Complete proof framing and injective canonical serialization. Bounds +below concern the u64 wire lengths and 32-byte digest arrays, not security. -/ + +namespace Aiur.NativeAIR.ProofCodec + +open KeyCodec (Reader Reads Returns readByte readMany readNat_reads readMany_reads readByte_reads) + +def VectorFits (property : α → Prop) (values : List α) : Prop := + values.length < 256^8 ∧ ∀ value ∈ values, property value + +def CapFits (cap : Cap) : Prop := VectorFits (fun digest => digest.length = 32) cap + +def OpeningsFits (values : Openings α) : Prop := + VectorFits (VectorFits (VectorFits (fun _ => True))) values + +theorem readVector_reads {read : Reader α} (encode : α → List UInt8) (values : List α) + (bounded : values.length < 256^8) + (elements : ∀ value ∈ values, Reads read (encode value) value) : + Reads (readVector read) (encodeVector encode values) values := + (readNat_reads 8 values.length bounded).bind (readMany_reads encode values elements) + +theorem readOption_reads {read : Reader α} (encode : α → List UInt8) (value : Option α) + (element : ∀ entry, value = some entry → Reads read (encode entry) entry) : + Reads (readOption read) (encodeOption encode value) value := by + cases value with + | none => intro rest; rfl + | some value => + unfold readOption encodeOption + exact Reads.byte ((element value rfl).result some) + +theorem readBool_reads (value : Bool) : Reads readBool (encodeBool value) value := by + cases value <;> intro rest <;> rfl + +theorem readField_reads (value : G) : Reads readField (encodeField value) value := by + unfold readField encodeField + apply Reads.bind (readNat_reads 8 value.n (UInt64.toNat_lt value.val)) + rw [if_pos (UInt64.lt_iff_toNat_lt.mp value.property), G.ofNat_n] + exact Reads.pure value + +theorem readExtension_reads (value : Extension) : + Reads readExtension (encodeExtension value) value := + (readField_reads value.c0).bind ((readField_reads value.c1).result (Extension.mk value.c0)) + +theorem readCap_reads (cap : Cap) (fits : CapFits cap) : Reads readCap (encodeCap cap) cap := by + apply readVector_reads id cap fits.1 + intro digest member + rw [← fits.2 digest member] + simpa using readMany_reads (fun byte => [byte]) digest + (fun byte _ => readByte_reads byte) + +theorem readOpenings_reads {read : Reader α} (encode : α → List UInt8) + (element : ∀ value, Reads read (encode value) value) + (values : Openings α) (fits : OpeningsFits values) : + Reads (readOpenings read) (encodeOpenings encode values) values := by + apply readVector_reads _ _ fits.1 + intro matrix member + apply readVector_reads _ _ (fits.2 matrix member).1 + intro row rowMember + exact readVector_reads _ _ ((fits.2 matrix member).2 row rowMember).1 (fun value _ => element value) + +structure CommitmentsFits (value : Commitments) : Prop where + stage1 : CapFits value.stage1 + stage2 : CapFits value.stage2 + quotient : CapFits value.quotient + +theorem readCommitments_reads (value : Commitments) (fits : CommitmentsFits value) : + Reads readCommitments (encodeCommitments value) value := by + unfold readCommitments encodeCommitments + rw [List.append_assoc] + apply Reads.bind (readCap_reads value.stage1 fits.stage1) + exact (readCap_reads value.stage2 fits.stage2).bind + ((readCap_reads value.quotient fits.quotient).result (Commitments.mk value.stage1 value.stage2)) + +structure BatchOpeningFits (value : BatchOpening) : Prop where + values : OpeningsFits value.values + siblingHashes : CapFits value.siblingHashes + +theorem readBatchOpening_reads (value : BatchOpening) (fits : BatchOpeningFits value) : + Reads readBatchOpening (encodeBatchOpening value) value := + (readOpenings_reads encodeField readField_reads value.values fits.values).bind + ((readCap_reads value.siblingHashes fits.siblingHashes).result (BatchOpening.mk value.values)) + +structure CommitStepFits (value : CommitStep) : Prop where + siblingValues : VectorFits (VectorFits (fun _ => True)) value.siblingValues + siblingHashes : CapFits value.siblingHashes + +theorem readCommitStep_reads (value : CommitStep) (fits : CommitStepFits value) : + Reads readCommitStep (encodeCommitStep value) value := by + unfold readCommitStep encodeCommitStep + apply Reads.byte + apply Reads.bind (readVector_reads _ _ fits.siblingValues.1 (fun row member => + readVector_reads _ _ (fits.siblingValues.2 row member).1 (fun item _ => readExtension_reads item))) + exact (readCap_reads value.siblingHashes fits.siblingHashes).result (CommitStep.mk value.logArity value.siblingValues) + +structure FriFits (value : Fri) : Prop where + commits : VectorFits CapFits value.commits + commitPowWitnesses : value.commitPowWitnesses.length < 256^8 + inputOpenings : VectorFits BatchOpeningFits value.inputOpenings + commitOpenings : VectorFits CommitStepFits value.commitOpenings + finalPoly : value.finalPoly.length < 256^8 + +theorem readFri_reads (value : Fri) (fits : FriFits value) : + Reads readFri (encodeFri value) value := by + unfold readFri encodeFri + simp only [List.append_assoc] + apply Reads.bind (readVector_reads _ _ fits.commits.1 + (fun cap member => readCap_reads cap (fits.commits.2 cap member))) + apply Reads.bind (readVector_reads _ _ fits.commitPowWitnesses (fun item _ => readField_reads item)) + apply Reads.bind (readVector_reads _ _ fits.inputOpenings.1 + (fun opening member => readBatchOpening_reads opening (fits.inputOpenings.2 opening member))) + apply Reads.bind (readVector_reads _ _ fits.commitOpenings.1 + (fun opening member => readCommitStep_reads opening (fits.commitOpenings.2 opening member))) + apply Reads.bind (readVector_reads _ _ fits.finalPoly (fun item _ => readExtension_reads item)) + exact (readField_reads value.queryPowWitness).result + (Fri.mk value.commits value.commitPowWitnesses value.inputOpenings value.commitOpenings value.finalPoly) + +structure DataFits (value : Data) : Prop where + active : value.active.length < 256^8 + commitments : CommitmentsFits value.commitments + accumulators : value.accumulators.length < 256^8 + logDegrees : value.logDegrees.length < 256^8 + fri : FriFits value.fri + quotient : OpeningsFits value.quotient + preprocessed : ∀ openings, value.preprocessed = some openings → OpeningsFits openings + stage1 : OpeningsFits value.stage1 + stage2 : OpeningsFits value.stage2 + +theorem readData_reads (value : Data) (fits : DataFits value) : + Reads readData (encodeData value) value := by + unfold readData encodeData + simp only [List.append_assoc] + apply Reads.bind (readVector_reads _ _ fits.active (fun item _ => readBool_reads item)) + apply Reads.bind (readCommitments_reads value.commitments fits.commitments) + apply Reads.bind (readVector_reads _ _ fits.accumulators (fun item _ => readExtension_reads item)) + apply Reads.bind (readVector_reads _ _ fits.logDegrees (fun item _ => readByte_reads item)) + apply Reads.bind (readFri_reads value.fri fits.fri) + apply Reads.bind (readOpenings_reads _ readExtension_reads value.quotient fits.quotient) + apply Reads.bind (readOption_reads _ _ (fun openings present => + readOpenings_reads _ readExtension_reads openings (fits.preprocessed openings present))) + apply Reads.bind (readOpenings_reads _ readExtension_reads value.stage1 fits.stage1) + exact (readOpenings_reads _ readExtension_reads value.stage2 fits.stage2).result + (Data.mk value.active value.commitments value.accumulators value.logDegrees value.fri + value.quotient value.preprocessed value.stage1) + +theorem decode_encode (value : Data) (fits : DataFits value) : decode (encode value) = some value := by + have read := readData_reads value fits [] + simp only [List.append_nil] at read + simp only [decode, encode, List.toList_data_toByteArray, read, + bind, Option.bind_some, List.isEmpty_nil, ite_true] + +theorem decode_success {bytes : ByteArray} {value : Data} (accepted : decode bytes = some value) : + readData bytes.data.toList = some (value, []) := by + unfold decode at accepted + cases parsed : readData bytes.data.toList with + | none => simp [parsed, bind, Option.bind] at accepted + | some pair => + obtain ⟨result, rest⟩ := pair + simp only [parsed, bind, Option.bind_some] at accepted + split at accepted + next empty => cases accepted; simp only [List.isEmpty_iff.mp empty] + next => cases accepted + +theorem decodeCanonical_success {bytes : ByteArray} {value : Data} + (accepted : decodeCanonical bytes = some value) : decode bytes = some value ∧ encode value = bytes := by + unfold decodeCanonical at accepted + cases parsed : decode bytes with + | none => simp [parsed, bind, Option.bind] at accepted + | some result => + simp only [parsed, bind, Option.bind_some] at accepted + split at accepted + next encoded => cases accepted; exact ⟨rfl, encoded⟩ + next => cases accepted + +theorem decodeCanonical_encode (value : Data) (fits : DataFits value) : + decodeCanonical (encode value) = some value := by + simp only [decodeCanonical, decode_encode value fits, bind, Option.bind_some, ite_true] + +theorem canonical_bytes_unique {first second : ByteArray} {value : Data} + (left : decodeCanonical first = some value) (right : decodeCanonical second = some value) : first = second := + (decodeCanonical_success left).2.symm.trans (decodeCanonical_success right).2 + +theorem encode_injective {first second : Data} (leftFits : DataFits first) (rightFits : DataFits second) + (equal : encode first = encode second) : first = second := by + have decoded := congrArg decode equal + rw [decode_encode first leftFits, decode_encode second rightFits] at decoded + exact Option.some.inj decoded + +theorem decode_append_rejected (value : Data) (fits : DataFits value) (suffix : List UInt8) + (nonempty : suffix ≠ []) : decode ((encodeData value ++ suffix).toByteArray) = none := by + have read := readData_reads value fits suffix + simp only [decode, List.toList_data_toByteArray, read, bind, Option.bind_some] + rw [if_neg (by simpa only [List.isEmpty_iff] using nonempty)] + +theorem readNat_returns (count : Nat) : + Returns (KeyCodec.readNat count) (fun value => value < 256^count) := by + induction count with + | zero => exact Returns.pure (by decide) + | succ count ih => + unfold KeyCodec.readNat + apply Returns.bind_any (property := fun value => value < 256^(count + 1)) + intro byte + apply Returns.result (right := fun value => value < 256^(count + 1)) ih + intro value bounded + have small := UInt8.toNat_lt byte + rw [Nat.pow_succ] + omega + +theorem readVector_returns {read : Reader α} {property : α → Prop} + (valid : Returns read property) : Returns (readVector read) (VectorFits property) := by + unfold readVector + apply Returns.bind (right := VectorFits property) (readNat_returns 8) + intro count bounded + exact (KeyCodec.readMany_returns valid count).weaken (fun _ known => ⟨known.1 ▸ bounded, known.2⟩) + +theorem readOption_returns {read : Reader α} {property : α → Prop} + (valid : Returns read property) : Returns (readOption read) + (fun result => ∀ value, result = some value → property value) := by + unfold readOption + apply Returns.bind_any (property := fun result => ∀ value, result = some value → property value) + intro byte + split + · exact Returns.pure (by intro value equal; cases equal) + · apply Returns.result (right := fun result => ∀ value, result = some value → property value) valid + intro value known result equal + cases equal + exact known + · exact Returns.failure _ + +theorem readCap_returns : Returns readCap CapFits := by + apply readVector_returns + exact (KeyCodec.readMany_returns (read := readByte) (property := fun _ => True) + (fun _ _ _ _ => True.intro) 32).weaken (fun _ known => known.1) + +theorem readOpenings_returns (read : Reader α) : Returns (readOpenings read) OpeningsFits := + readVector_returns (readVector_returns (readVector_returns (fun _ _ _ _ => True.intro))) + +theorem readCommitments_returns : Returns readCommitments CommitmentsFits := by + unfold readCommitments + apply Returns.bind (right := CommitmentsFits) readCap_returns + intro first hf + apply Returns.bind (right := CommitmentsFits) readCap_returns + intro second hs + apply Returns.result (right := CommitmentsFits) readCap_returns + intro quotient hq + exact ⟨hf, hs, hq⟩ + +theorem readBatchOpening_returns : Returns readBatchOpening BatchOpeningFits := by + unfold readBatchOpening + apply Returns.bind (right := BatchOpeningFits) (readOpenings_returns readField) + intro values hv + apply Returns.result (right := BatchOpeningFits) readCap_returns + intro hashes hh + exact ⟨hv, hh⟩ + +theorem readCommitStep_returns : Returns readCommitStep CommitStepFits := by + unfold readCommitStep + apply Returns.bind_any (property := CommitStepFits) + intro arity + apply Returns.bind (right := CommitStepFits) + (readVector_returns (readVector_returns (property := fun _ => True) (fun _ _ _ _ => True.intro))) + intro values hv + apply Returns.result (right := CommitStepFits) readCap_returns + intro hashes hh + exact ⟨hv, hh⟩ + +theorem readFri_returns : Returns readFri FriFits := by + unfold readFri + apply Returns.bind (right := FriFits) (readVector_returns readCap_returns) + intro commits hc + apply Returns.bind (right := FriFits) (readVector_returns (property := fun _ => True) (fun _ _ _ _ => True.intro)) + intro witnesses hw + apply Returns.bind (right := FriFits) (readVector_returns readBatchOpening_returns) + intro inputs hi + apply Returns.bind (right := FriFits) (readVector_returns readCommitStep_returns) + intro openings ho + apply Returns.bind (right := FriFits) (readVector_returns (property := fun _ => True) (fun _ _ _ _ => True.intro)) + intro finalPoly hf + apply Returns.bind_any (property := FriFits) + intro witness + exact Returns.pure ⟨hc, hw.1, hi, ho, hf.1⟩ + +theorem readData_returns : Returns readData DataFits := by + unfold readData + apply Returns.bind (right := DataFits) (readVector_returns (property := fun _ => True) (fun _ _ _ _ => True.intro)) + intro active ha + apply Returns.bind (right := DataFits) readCommitments_returns + intro commitments hc + apply Returns.bind (right := DataFits) (readVector_returns (property := fun _ => True) (fun _ _ _ _ => True.intro)) + intro accumulators hs + apply Returns.bind (right := DataFits) (readVector_returns (property := fun _ => True) (fun _ _ _ _ => True.intro)) + intro degrees hd + apply Returns.bind (right := DataFits) readFri_returns + intro fri hf + apply Returns.bind (right := DataFits) (readOpenings_returns readExtension) + intro quotient hq + apply Returns.bind (right := DataFits) (readOption_returns (readOpenings_returns readExtension)) + intro preprocessed hp + apply Returns.bind (right := DataFits) (readOpenings_returns readExtension) + intro first hfirst + apply Returns.result (right := DataFits) (readOpenings_returns readExtension) + intro second hsecond + exact ⟨ha.1, hc, hs.1, hd.1, hf, hq, hp, hfirst, hsecond⟩ + +theorem decode_fits {bytes : ByteArray} {value : Data} (accepted : decode bytes = some value) : DataFits value := + readData_returns _ value [] (decode_success accepted) + +end Aiur.NativeAIR.ProofCodec diff --git a/Ix/Aiur/Proofs/ProofShape.lean b/Ix/Aiur/Proofs/ProofShape.lean new file mode 100644 index 000000000..68d1c9071 --- /dev/null +++ b/Ix/Aiur/Proofs/ProofShape.lean @@ -0,0 +1,173 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ProofShape +import Ix.Aiur.Proofs.CompiledKey + +/-! Shape acceptance supplies the actual selected opening records and their +checked dimensions. Polynomial authentication and trace satisfaction are +not assumed or concluded by these results. -/ + +namespace Aiur.NativeAIR.ProofShape + +open ProofCodec (Data) + +theorem pair_success {values : List (List ProofCodec.Extension)} {result : Pair} + (accepted : pair values = some result) : values = [result.current, result.next] := by + cases values with + | nil => cases accepted + | cons current rest => + cases rest with + | nil => cases accepted + | cons next rest => + cases rest with + | nil => cases accepted; rfl + | cons _ _ => cases accepted + +theorem single_success {values : List α} {result : α} (accepted : single values = some result) : + values = [result] := by + cases values with + | nil => cases accepted + | cons value rest => + cases rest with + | nil => cases accepted; rfl + | cons _ _ => cases accepted + +theorem readPreprocessed_none (proof : Data) : readPreprocessed proof none = some none := rfl + +theorem readPreprocessed_some {proof : Data} {slot : Nat} {result : Option Pair} + (accepted : readPreprocessed proof (some slot) = some result) : + ∃ values opened, proof.preprocessed = some opened ∧ + opened[slot]? = some [values.current, values.next] ∧ result = some values := by + simp only [readPreprocessed, Option.map_eq_some_iff, bind, Option.bind_eq_some_iff] at accepted + obtain ⟨values, ⟨opened, hp, matrix, hm, hv⟩, rfl⟩ := accepted + exact ⟨values, opened, hp, (pair_success hv) ▸ hm, rfl⟩ + +structure Row.Sourced (key : KeyCodec.Key) (proof : Data) (index position : Nat) (row : Row) : Prop where + index_eq : row.circuitIndex = index + circuit : key.circuits[index]? = some row.circuit + degree : proof.logDegrees[position]? = some row.logDegree + stage1 : proof.stage1[position]? = some [row.stage1.current, row.stage1.next] + stage2 : proof.stage2[position]? = some [row.stage2.current, row.stage2.next] + quotient : proof.quotient[position]? = some [row.quotient] + accumulator : proof.accumulators[position]? = some row.accumulator + preprocessed : ∃ slot, key.preprocessedIndices[index]? = some slot ∧ + readPreprocessed proof slot = some row.preprocessed + +theorem readRow_success {key : KeyCodec.Key} {proof : Data} {index position : Nat} {row : Row} + (accepted : readRow key proof index position = some row) : row.Sourced key proof index position := by + simp only [readRow, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at accepted + obtain ⟨circuit, hc, slot, hi, degree, hd, first, hf, firstPair, hfp, + second, hs, secondPair, hsp, quotient, hq, singleQ, hqs, accumulator, ha, + preprocessed, hp, rfl⟩ := accepted + exact ⟨rfl, hc, hd, (pair_success hfp) ▸ hf, (pair_success hsp) ▸ hs, + (single_success hqs) ▸ hq, ha, slot, hi, hp⟩ + +theorem Pair.hasWidth_success {values : Pair} {width : Nat} (accepted : values.hasWidth width = true) : + values.current.length = width ∧ values.next.length = width := by + simpa only [Pair.hasWidth, Bool.and_eq_true, beq_iff_eq] using accepted + +structure Row.Fits (parameters : KeyCodec.Parameters) (row : Row) : Prop where + stage1 : row.stage1.current.length = row.circuit.mainWidth ∧ row.stage1.next.length = row.circuit.mainWidth + stage2 : row.stage2.current.length = row.circuit.widths.stage2 ∧ row.stage2.next.length = row.circuit.widths.stage2 + preprocessed : ∀ values, row.preprocessed = some values → + values.current.length = row.circuit.preprocessedWidth ∧ values.next.length = row.circuit.preprocessedWidth + quotient : row.quotient.length = quotientDegree row.circuit * 2 + degree : row.logDegree.toNat + (quotientDegree row.circuit).log2 ≤ 32 - parameters.logBlowup + +theorem Row.fits_success {parameters : KeyCodec.Parameters} {row : Row} (accepted : row.fits parameters = true) : + row.Fits parameters := by + simp only [Row.fits, Bool.and_eq_true, beq_iff_eq, decide_eq_true_eq] at accepted + obtain ⟨⟨⟨⟨first, second⟩, preprocessed⟩, quotient⟩, degree⟩ := accepted + refine ⟨Pair.hasWidth_success first, Pair.hasWidth_success second, ?_, quotient, degree⟩ + intro values present + rw [present] at preprocessed + exact Pair.hasWidth_success preprocessed + +theorem check_success {key : KeyCodec.Key} {proof : Data} {result : List Row} + (accepted : check key proof = some result) : header key proof = true ∧ + inactivePreprocessed key proof = true ∧ rows key proof = some result ∧ + ∀ row ∈ result, row.Fits key.parameters := by + unfold check at accepted + split at accepted + next initial => + have initial' : header key proof = true ∧ inactivePreprocessed key proof = true := by + simpa only [Bool.and_eq_true] using initial + obtain ⟨header, inactive⟩ := initial' + cases parsed : rows key proof with + | none => simp [parsed, bind, Option.bind] at accepted + | some entries => + simp only [parsed, bind, Option.bind_some] at accepted + split at accepted + next fits => + cases accepted + exact ⟨header, inactive, rfl, fun row member => Row.fits_success (List.all_eq_true.mp fits row member)⟩ + next => cases accepted + next => cases accepted + +theorem check_length {key : KeyCodec.Key} {proof : Data} {result : List Row} + (accepted : check key proof = some result) : result.length = (activeIndices proof).length := by + have parsed := (check_success accepted).2.2.1 + have same := Bytecode.AIR.list_mapM_some_length _ _ _ parsed + simpa only [List.length_zipIdx] using same + +theorem activeIndices_mem {proof : Data} {index : Nat} : + index ∈ activeIndices proof ↔ proof.active[index]? = some true := by + unfold activeIndices + constructor + · intro member + obtain ⟨⟨enabled, ci⟩, present, value⟩ := List.mem_filterMap.mp member + cases enabled with + | false => cases value + | true => + cases value + exact List.mk_mem_zipIdx_iff_getElem?.mp present + · intro present + exact List.mem_filterMap.mpr ⟨(true, index), List.mk_mem_zipIdx_iff_getElem?.mpr present, rfl⟩ + +theorem check_row {key : KeyCodec.Key} {proof : Data} {result : List Row} + (accepted : check key proof = some result) {position : Nat} {row : Row} + (present : result[position]? = some row) : + ∃ index, (activeIndices proof)[position]? = some index ∧ row.Sourced key proof index position ∧ row.Fits key.parameters := by + have parsed := (check_success accepted).2.2.1 + have read := OpEmitter.list_mapM_read parsed position + rw [present] at read + simp only [List.getElem?_zipIdx] at read + cases located : (activeIndices proof)[position]? with + | none => simp [located] at read + | some index => + simp only [located, Option.map_some, bind, Option.bind_some, Nat.zero_add] at read + exact ⟨index, rfl, readRow_success read, + (check_success accepted).2.2.2 row (List.mem_of_getElem? present)⟩ + +theorem check_row_active {key : KeyCodec.Key} {proof : Data} {result : List Row} + (accepted : check key proof = some result) {position : Nat} {row : Row} + (present : result[position]? = some row) : proof.active[row.circuitIndex]? = some true := by + obtain ⟨index, located, sourced, _⟩ := check_row accepted present + rw [sourced.index_eq] + exact activeIndices_mem.mp (List.mem_of_getElem? located) + +theorem check_nonempty {key : KeyCodec.Key} {proof : Data} {result : List Row} + (accepted : check key proof = some result) : result ≠ [] := by + have lengths := check_length accepted + have valid := (check_success accepted).1 + simp only [header, Bool.and_eq_true, beq_iff_eq, decide_eq_true_eq] at valid + intro empty + rw [empty] at lengths + have positive : 0 < (activeIndices proof).length := valid.1.1.1.1.1.1.1.1.2 + simp only [List.length_nil] at lengths + omega + +theorem fixedHeights_sound {key : KeyCodec.Key} {proof : Data} (accepted : fixedHeights key proof = true) : + FixedTraceHeights (key.circuits.map (·.preprocessedHeight)) proof.active (proof.logDegrees.map UInt8.toNat) := + fixedTraceHeights_sound accepted + +theorem queryBound_sound {key : KeyCodec.Key} {proof : Data} {bound : Nat} + (accepted : queryBound key proof = some bound) : + ∃ total, lookupSlotSum (key.circuits.map (·.graph.lookups.length)) proof.active + (proof.logDegrees.map UInt8.toNat) = some total ∧ bound = 1 + total ∧ bound < gSize.toNat := + (lookupQueryBound_sound accepted).2 + +end Aiur.NativeAIR.ProofShape diff --git a/Ix/Aiur/Proofs/ProviderEquivalence.lean b/Ix/Aiur/Proofs/ProviderEquivalence.lean new file mode 100644 index 000000000..2b4c940e1 --- /dev/null +++ b/Ix/Aiur/Proofs/ProviderEquivalence.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRowCounts +import Ix.Aiur.Proofs.CircuitPoolExecution + +/-! Provider replacement preserves padded balance when multiplicities and +nonzero messages agree. A satisfying nonzero circuit provides an actual +return message before any operation or function-row interpretation. -/ + +namespace Aiur.AIR + +/-- Providers have the same contribution to every padded-message balance. +The raw message of a zero-weight provider has no effect. -/ +def Provider.PaddedEq (width : Nat) (left right : Provider (List G)) : Prop := + left.2 = right.2 ∧ (left.2 ≠ 0 → padMessage width left.1 = padMessage width right.1) + +theorem Provider.PaddedEq.refl (width : Nat) (provider : Provider (List G)) : + PaddedEq width provider provider := ⟨rfl, fun _ => rfl⟩ + +theorem Provider.PaddedEq.symm {width : Nat} {left right : Provider (List G)} + (same : PaddedEq width left right) : PaddedEq width right left := + ⟨same.1.symm, fun nonzero => (same.2 (same.1 ▸ nonzero)).symm⟩ + +theorem Provider.PaddedEq.trans {width : Nat} {left middle right : Provider (List G)} + (first : PaddedEq width left middle) (last : PaddedEq width middle right) : PaddedEq width left right := + ⟨first.1.trans last.1, fun nonzero => (first.2 nonzero).trans (last.2 (first.1 ▸ nonzero))⟩ + +theorem suppliedWeight_padded_congr {width : Nat} {left right : List (Provider (List G))} + (related : List.Forall₂ (Provider.PaddedEq width) left right) (message : List G) : + suppliedWeight message (mapProviders (padMessage width) left) = + suppliedWeight message (mapProviders (padMessage width) right) := by + induction related with + | nil => rfl + | @cons first last rest rest' head tail ih => + change (if padMessage width first.1 = message then + first.2 + suppliedWeight message (mapProviders (padMessage width) rest) + else suppliedWeight message (mapProviders (padMessage width) rest)) = + (if padMessage width last.1 = message then + last.2 + suppliedWeight message (mapProviders (padMessage width) rest') + else suppliedWeight message (mapProviders (padMessage width) rest')) + by_cases zero : first.2 = 0 + · have lastZero := head.1.symm.trans zero + simp only [zero, lastZero, G.zero_add, ite_self, ih] + · rw [head.2 zero, head.1, ih] + +theorem PaddedLookupBalance.congr_providers {width : Nat} {queries : List (List G)} + {left right : List (Provider (List G))} (balanced : PaddedLookupBalance width queries left) + (related : List.Forall₂ (Provider.PaddedEq width) left right) : + PaddedLookupBalance width queries right := fun message => + (balanced message).trans (suppliedWeight_padded_congr related message) + +theorem paddedProviders_refl (width : Nat) (providers : List (Provider (List G))) : + List.Forall₂ (Provider.PaddedEq width) providers providers := by + induction providers with + | nil => exact .nil + | cons provider rest ih => exact .cons (Provider.PaddedEq.refl width provider) ih + +def CircuitEmission.provider (emission : CircuitEmission) : Provider (List G) := + ((emission.lookup 0).2, emission.multiplicity) + +theorem CircuitEmission.provider_multiplicity (emission : CircuitEmission) : + (emission.lookup 0).1 = 0 - emission.provider.2 := rfl + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitRow_provider (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) + (validated : circuit.validateRowCounts program = true) + (shape : ∀ part ∈ emission.members, part.function.body.lookupShapes program none = true) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (nonzero : emission.multiplicity ≠ 0) (width : Nat) : + ∃ request : AIR.Call, (1, request) ∈ emission.returns ∧ + padMessage width (emission.lookup 0).2 = padMessage width (functionMessage request) := by + obtain ⟨bounded, _, returnBound, single⟩ := circuit.emitRow_count_bounds row program emitted validated satisfied + obtain ⟨description, indices, source⟩ := circuit.emitRow_spec row program emitted + have size := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at size + have valid : ∀ equation ∈ (circuitEmission row circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have active : (circuitEmission row circuit emission.members).selector = 1 := + nonzero_multiplicity_selector_one (circuitEmission_activity valid) (by + rw [← description] + exact nonzero) + have count := circuitEmission_return_count source shape (by omega) returnBound valid active + rw [← description] at count + have present : (1 : G) ∈ emission.returns.map Prod.fst := List.count_pos_iff.mp (by rw [count]; decide) + obtain ⟨⟨gate, request⟩, member, gateEq⟩ := List.mem_map.mp present + change gate = 1 at gateEq + subst gate + refine ⟨request, member, ?_⟩ + have message := circuitEmission_return_message source shape (by omega) returnBound valid active width + (by rw [← description]; exact single) (by rw [← description]; exact member) + rw [← description] at message + exact message + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/PrunedMerkle.lean b/Ix/Aiur/Proofs/PrunedMerkle.lean new file mode 100644 index 000000000..2937b6c8b --- /dev/null +++ b/Ix/Aiur/Proofs/PrunedMerkle.lean @@ -0,0 +1,743 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.PrunedMerkle +import Ix.Aiur.Proofs.Merkle + +/-! Shared frontier authentication through reconstructed individual paths. +Hash logs include work performed before a rejected group injection. -/ + +namespace Aiur.NativeAIR.Merkle + +theorem walk_append (hash : Hash) (dimensions : List Dimensions) (rows : List (List G)) + (height index : Nat) (current : Digest) (before after : List Digest) : + walk hash dimensions rows height index current (before ++ after) = + let middle := walk hash dimensions rows height index current before + let final := walk hash dimensions rows (height - before.length) (index / 2^before.length) middle.digest after + ⟨final.digest, middle.inputs ++ final.inputs⟩ := by + induction before generalizing height index current with + | nil => simp only [List.nil_append, walk, List.length_nil, Nat.sub_zero, Nat.pow_zero, Nat.div_one] + | cons sibling before ih => + have subtract : height - 1 - before.length = height - (before.length + 1) := by omega + have divide : index / 2 / 2^before.length = index / 2^(before.length + 1) := by + rw [Nat.div_div_eq_div_mul, Nat.pow_succ, Nat.mul_comm 2] + simp only [List.cons_append, walk, ih, List.length_cons, subtract, divide, List.append_assoc] + +end Aiur.NativeAIR.Merkle + +namespace Aiur.NativeAIR.PrunedMerkle + +theorem Logged.bind_success {first : Logged α} {next : α → Logged β} {value : β} + (success : (first >>= next).result = some value) : + ∃ middle, first.result = some middle ∧ (next middle).result = some value ∧ + (first >>= next).inputs = first.inputs ++ (next middle).inputs := by + change (Logged.bind first next).result = some value at success + cases running : first.result with + | none => simp [Logged.bind, running] at success + | some middle => + exact ⟨middle, rfl, by simpa only [Logged.bind, running] using success, + by change (Logged.bind first next).inputs = _; simp only [Logged.bind, running]⟩ + +theorem Logged.bind_input_left {first : Logged α} {next : α → Logged β} {input : List UInt8} + (member : input ∈ first.inputs) : input ∈ (first >>= next).inputs := by + change input ∈ (Logged.bind first next).inputs + cases running : first.result with + | none => simpa only [Logged.bind, running] using member + | some middle => simp only [Logged.bind, running, List.mem_append]; exact Or.inl member + +theorem Logged.bind_input_right {first : Logged α} {next : α → Logged β} {middle : α} + (success : first.result = some middle) {input : List UInt8} (member : input ∈ (next middle).inputs) : + input ∈ (first >>= next).inputs := by + change input ∈ (Logged.bind first next).inputs + simp only [Logged.bind, success, List.mem_append] + exact Or.inr member + +theorem Logged.bind_if (condition : Prop) [Decidable condition] (left right : Logged α) + (next : α → Logged β) : + ((if condition then left else right) >>= next) = + if condition then left >>= next else right >>= next := by + by_cases condition <;> simp only [*, ↓reduceIte] + +theorem hashInput_value (hash : Merkle.Hash) (input : List UInt8) : + (hashInput hash input).result = some (hash input) := rfl + +theorem hashInput_inputs (hash : Merkle.Hash) (input : List UInt8) : + (hashInput hash input).inputs = [input] := rfl + +open Merkle (Digest Hash Dimensions) + +/-- An individual path ending at the current shared node, with every +ordinary hash input contained in the shared execution log. -/ +structure TicketAt (hash : Hash) (dimensions : List Dimensions) (height index : Nat) + (digest : Digest) (inputs : List (List UInt8)) (ticket : Ticket) : Prop where + shape : Merkle.shape dimensions ticket.rows = true + bound : ticket.index < 2^Merkle.maxHeight dimensions + depth : ticket.proof.length + height = Merkle.maxHeight dimensions + position : ticket.index / 2^ticket.proof.length = index + digest_eq : (Merkle.walk hash dimensions ticket.rows (Merkle.maxHeight dimensions) ticket.index + (hash (Merkle.rowBytes dimensions ticket.rows (Merkle.maxHeight dimensions))) ticket.proof).digest = digest + calls : Merkle.rowBytes dimensions ticket.rows (Merkle.maxHeight dimensions) :: + (Merkle.walk hash dimensions ticket.rows (Merkle.maxHeight dimensions) ticket.index + (hash (Merkle.rowBytes dimensions ticket.rows (Merkle.maxHeight dimensions))) ticket.proof).inputs ⊆ inputs + +def NodeAt (hash : Hash) (dimensions : List Dimensions) (height : Nat) + (inputs : List (List UInt8)) (node : Node) : Prop := + ∀ ticket ∈ node.tickets, TicketAt hash dimensions height node.index node.digest inputs ticket + +/-- A sibling has been paired, but shorter rows have not yet been injected. +The native verifier pairs the whole layer before performing these injections. -/ +def PendingAt (hash : Hash) (dimensions : List Dimensions) (height index : Nat) + (digest : Digest) (inputs : List (List UInt8)) (ticket : Ticket) : Prop := + ∃ before sibling previousIndex previousDigest, + ticket = before.extend sibling ∧ + TicketAt hash dimensions (height + 1) previousIndex previousDigest inputs before ∧ + index = previousIndex / 2 ∧ + digest = hash (Merkle.branchBytes previousIndex previousDigest sibling) ∧ + Merkle.branchBytes previousIndex previousDigest sibling ∈ inputs + +def PendingNode (hash : Hash) (dimensions : List Dimensions) (height : Nat) + (inputs : List (List UInt8)) (node : Node) : Prop := + ∀ ticket ∈ node.tickets, PendingAt hash dimensions height node.index node.digest inputs ticket + +def origins (nodes : List Node) : List (Nat × List (List G)) := + nodes.flatMap fun node => node.tickets.map fun ticket => (ticket.index, ticket.rows) + +theorem TicketAt.mono {hash : Hash} {dimensions : List Dimensions} {height index : Nat} + {digest : Digest} {before after : List (List UInt8)} {ticket : Ticket} + (valid : TicketAt hash dimensions height index digest before ticket) (subset : before ⊆ after) : + TicketAt hash dimensions height index digest after ticket := + { valid with calls := fun _ member => subset (valid.calls member) } + +theorem NodeAt.mono {hash : Hash} {dimensions : List Dimensions} {height : Nat} + {before after : List (List UInt8)} {node : Node} + (valid : NodeAt hash dimensions height before node) (subset : before ⊆ after) : + NodeAt hash dimensions height after node := + fun _ member => (valid _ member).mono subset + +theorem PendingAt.mono {hash : Hash} {dimensions : List Dimensions} {height index : Nat} + {digest : Digest} {before after : List (List UInt8)} {ticket : Ticket} + (valid : PendingAt hash dimensions height index digest before ticket) (subset : before ⊆ after) : + PendingAt hash dimensions height index digest after ticket := by + obtain ⟨previous, sibling, previousIndex, previousDigest, same, path, position, digestEq, member⟩ := valid + exact ⟨previous, sibling, previousIndex, previousDigest, same, path.mono subset, + position, digestEq, subset member⟩ + +theorem PendingNode.mono {hash : Hash} {dimensions : List Dimensions} {height : Nat} + {before after : List (List UInt8)} {node : Node} + (valid : PendingNode hash dimensions height before node) (subset : before ⊆ after) : + PendingNode hash dimensions height after node := + fun _ member => (valid _ member).mono subset + +theorem TicketAt.extend {hash : Hash} {dimensions : List Dimensions} {height index : Nat} + {digest : Digest} {inputs : List (List UInt8)} {ticket : Ticket} (sibling : Digest) + (valid : TicketAt hash dimensions (height + 1) index digest inputs ticket) + (member : Merkle.branchBytes index digest sibling ∈ inputs) : + PendingAt hash dimensions height (index / 2) + (hash (Merkle.branchBytes index digest sibling)) inputs (ticket.extend sibling) := + ⟨ticket, sibling, index, digest, rfl, valid, rfl, rfl, member⟩ + +theorem TicketAt.finish {hash : Hash} {dimensions : List Dimensions} {height index : Nat} + {digest : Digest} {inputs : List (List UInt8)} {ticket : Ticket} (sibling : Digest) + (valid : TicketAt hash dimensions (height + 1) index digest inputs ticket) + (calls : (Merkle.step hash dimensions ticket.rows height index digest sibling).inputs ⊆ inputs) : + TicketAt hash dimensions height (index / 2) + (Merkle.step hash dimensions ticket.rows height index digest sibling).digest inputs + (ticket.extend sibling) := by + have level : Merkle.maxHeight dimensions - ticket.proof.length = height + 1 := by + have := valid.depth + omega + have path := Merkle.walk_append hash dimensions ticket.rows (Merkle.maxHeight dimensions) + ticket.index (hash (Merkle.rowBytes dimensions ticket.rows (Merkle.maxHeight dimensions))) + ticket.proof [sibling] + simp only [level, valid.position, valid.digest_eq, Merkle.walk, Nat.add_sub_cancel, + List.append_nil] at path + refine ⟨valid.shape, valid.bound, ?_, ?_, ?_, ?_⟩ + · simp only [Ticket.extend, List.length_append, List.length_singleton] + have := valid.depth + omega + · simp only [Ticket.extend, List.length_append, List.length_singleton, Nat.pow_succ, + ← Nat.div_div_eq_div_mul, valid.position] + · simp only [Ticket.extend, path] + · simp only [Ticket.extend, path] + intro input member + simp only [List.mem_cons, List.mem_append] at member + rcases member with leaf | previous | current + · exact valid.calls (List.mem_cons.mpr (Or.inl leaf)) + · exact valid.calls (List.mem_cons.mpr (Or.inr previous)) + · exact calls current + +theorem PendingAt.finish_absent {hash : Hash} {dimensions : List Dimensions} {height index : Nat} + {digest : Digest} {inputs : List (List UInt8)} {ticket : Ticket} + (valid : PendingAt hash dimensions height index digest inputs ticket) + (absent : Merkle.hasHeight dimensions height = false) : + TicketAt hash dimensions height index digest inputs ticket := by + obtain ⟨before, sibling, previousIndex, previousDigest, rfl, path, rfl, rfl, member⟩ := valid + have calls : (Merkle.step hash dimensions before.rows height previousIndex previousDigest sibling).inputs ⊆ inputs := by + simpa only [Merkle.step, absent, Bool.false_eq_true, ↓reduceIte, List.cons_subset, + List.nil_subset, and_true] using member + simpa only [Merkle.step, absent, Bool.false_eq_true, ↓reduceIte] using path.finish sibling calls + +theorem PendingAt.finish_injected {hash : Hash} {dimensions : List Dimensions} {height index : Nat} + {digest : Digest} {inputs : List (List UInt8)} {ticket : Ticket} {rows : List (List G)} + (valid : PendingAt hash dimensions height index digest inputs ticket) + (present : Merkle.hasHeight dimensions height = true) + (same : Merkle.rowsAt dimensions ticket.rows height = Merkle.rowsAt dimensions rows height) + (leaf : Merkle.rowBytes dimensions rows height ∈ inputs) + (inject : Merkle.pairBytes digest (hash (Merkle.rowBytes dimensions rows height)) ∈ inputs) : + TicketAt hash dimensions height index + (hash (Merkle.pairBytes digest (hash (Merkle.rowBytes dimensions rows height)))) inputs ticket := by + obtain ⟨before, sibling, previousIndex, previousDigest, rfl, path, rfl, rfl, member⟩ := valid + have bytes : Merkle.rowBytes dimensions before.rows height = Merkle.rowBytes dimensions rows height := by + change Merkle.rowsAt dimensions before.rows height = Merkle.rowsAt dimensions rows height at same + exact congrArg (fun (values : List (List G)) => Transcript.fieldsBytes values.flatten) same + have calls : (Merkle.step hash dimensions before.rows height previousIndex previousDigest sibling).inputs ⊆ inputs := by + simpa only [Merkle.step, present, ↓reduceIte, bytes, List.cons_subset, List.nil_subset, and_true] + using And.intro member (And.intro leaf inject) + simpa only [Merkle.step, present, ↓reduceIte, bytes] using path.finish sibling calls + +theorem NodeAt.singleton {hash : Hash} {dimensions : List Dimensions} {height : Nat} + {inputs : List (List UInt8)} {node : Node} (sibling : Digest) + (valid : NodeAt hash dimensions (height + 1) inputs node) + (member : Merkle.branchBytes node.index node.digest sibling ∈ inputs) : + PendingNode hash dimensions height inputs + ⟨node.index / 2, hash (Merkle.branchBytes node.index node.digest sibling), + node.tickets.map (Ticket.extend sibling)⟩ := by + intro ticket ticketMem + obtain ⟨before, beforeMem, rfl⟩ := List.mem_map.mp ticketMem + exact (valid before beforeMem).extend sibling member + +theorem NodeAt.pair {hash : Hash} {dimensions : List Dimensions} {height : Nat} + {inputs : List (List UInt8)} {first second : Node} + (left : NodeAt hash dimensions (height + 1) inputs first) + (right : NodeAt hash dimensions (height + 1) inputs second) + (adjacent : first.index % 2 = 0 ∧ second.index = first.index + 1) + (member : Merkle.pairBytes first.digest second.digest ∈ inputs) : + PendingNode hash dimensions height inputs + ⟨first.index / 2, hash (Merkle.pairBytes first.digest second.digest), + first.tickets.map (Ticket.extend second.digest) ++ second.tickets.map (Ticket.extend first.digest)⟩ := by + have leftBytes : Merkle.branchBytes first.index first.digest second.digest = + Merkle.pairBytes first.digest second.digest := by simp only [Merkle.branchBytes, adjacent.1, ↓reduceIte] + have odd : second.index % 2 ≠ 0 := by omega + have rightBytes : Merkle.branchBytes second.index second.digest first.digest = + Merkle.pairBytes first.digest second.digest := by simp only [Merkle.branchBytes, odd, ↓reduceIte] + have position : second.index / 2 = first.index / 2 := by omega + intro ticket ticketMem + rcases List.mem_append.mp ticketMem with leftMem | rightMem + · obtain ⟨before, beforeMem, rfl⟩ := List.mem_map.mp leftMem + simpa only [leftBytes] using (left before beforeMem).extend second.digest (leftBytes ▸ member) + · obtain ⟨before, beforeMem, rfl⟩ := List.mem_map.mp rightMem + simpa only [rightBytes, position] using (right before beforeMem).extend first.digest (rightBytes ▸ member) + +theorem origins_cons (node : Node) (nodes : List Node) : + origins (node :: nodes) = node.tickets.map (fun ticket => (ticket.index, ticket.rows)) ++ origins nodes := rfl + +theorem origins_extend (tickets : List Ticket) (sibling : Digest) : + (tickets.map (Ticket.extend sibling)).map (fun ticket => (ticket.index, ticket.rows)) = + tickets.map (fun ticket => (ticket.index, ticket.rows)) := by + simp only [List.map_map, Function.comp_def, Ticket.extend] + +theorem combine_refines {hash : Hash} {dimensions : List Dimensions} {height : Nat} + {inputs : List (List UInt8)} {nodes : List Node} {proof : List Digest} + {parents : List Node} {remaining : List Digest} + (valid : ∀ node ∈ nodes, NodeAt hash dimensions (height + 1) inputs node) + (success : (combine hash nodes proof).result = some (parents, remaining)) : + (∀ parent ∈ parents, PendingNode hash dimensions height (inputs ++ (combine hash nodes proof).inputs) parent) ∧ + origins parents = origins nodes := by + fun_induction combine hash nodes proof generalizing parents remaining with + | case1 proof => + have same : ([], proof) = (parents, remaining) := Option.some.inj success + cases same + exact ⟨by simp, rfl⟩ + | case2 first proof second tail adjacent ih => + cases running : (combine hash tail proof).result with + | none => simp [bind, Logged.bind, hashInput, running] at success + | some result => + rcases result with ⟨rest, boundary⟩ + have tailValid : ∀ node ∈ tail, NodeAt hash dimensions (height + 1) inputs node := + fun node member => valid node (by simp only [List.mem_cons]; exact Or.inr (Or.inr member)) + obtain ⟨restValid, restOrigins⟩ := ih tailValid running + simp only [bind, pure, Logged.bind, hashInput, + running, Logged.pure, Option.some.injEq, Prod.mk.injEq] at success + rcases success with ⟨rfl, rfl⟩ + simp only [bind, pure, Logged.bind, hashInput, + running, Logged.pure, List.append_nil] + constructor + · intro node member + rcases List.mem_cons.mp member with rfl | restMem + · apply NodeAt.pair + · exact (valid first (by simp)).mono (by intro input h; simp only [List.mem_append]; exact Or.inl h) + · exact (valid second (by simp)).mono (by intro input h; simp only [List.mem_append]; exact Or.inl h) + · exact adjacent + · simp + · apply (restValid node restMem).mono + intro input h + simp only [List.mem_append] at h ⊢ + exact h.elim Or.inl (fun h => Or.inr (by simp only [List.mem_cons]; exact Or.inr h)) + · simp only [origins_cons, List.map_append, origins_extend, restOrigins, List.append_assoc] + | case3 first second tail adjacent sibling boundary ih => + cases running : (combine hash (second :: tail) boundary).result with + | none => simp [bind, Logged.bind, hashInput, running] at success + | some result => + rcases result with ⟨rest, leftover⟩ + have tailValid : ∀ node ∈ second :: tail, NodeAt hash dimensions (height + 1) inputs node := + fun node member => valid node (List.mem_cons.mpr (Or.inr member)) + obtain ⟨restValid, restOrigins⟩ := ih tailValid running + simp only [bind, pure, Logged.bind, hashInput, + running, Logged.pure, Option.some.injEq, Prod.mk.injEq] at success + rcases success with ⟨rfl, rfl⟩ + simp only [bind, pure, Logged.bind, hashInput, + running, Logged.pure, List.append_nil] + constructor + · intro node member + rcases List.mem_cons.mp member with rfl | restMem + · apply NodeAt.singleton + · exact (valid first (by simp)).mono (by intro input h; simp only [List.mem_append]; exact Or.inl h) + · simp + · apply (restValid node restMem).mono + intro input h + simp only [List.mem_append] at h ⊢ + exact h.elim Or.inl (fun h => Or.inr (by simp only [List.mem_cons]; exact Or.inr h)) + · simp only [origins_cons, origins_extend, restOrigins] + | case4 => cases success + | case5 first sibling boundary => + simp only [bind, pure, Logged.bind, hashInput, Logged.pure, + Option.some.injEq, Prod.mk.injEq] at success + rcases success with ⟨rfl, rfl⟩ + simp only [bind, pure, Logged.bind, hashInput, Logged.pure, List.append_nil] + constructor + · intro node member + obtain rfl := List.mem_singleton.mp member + apply NodeAt.singleton + · exact (valid first (by simp)).mono (by intro input h; simp only [List.mem_append]; exact Or.inl h) + · simp + · simp only [origins_cons, origins_extend] + | case6 => cases success + +theorem inject_refines {hash : Hash} {dimensions : List Dimensions} {height : Nat} + {inputs : List (List UInt8)} {nodes output : List Node} + (present : Merkle.hasHeight dimensions height = true) + (valid : ∀ node ∈ nodes, PendingNode hash dimensions height inputs node) + (success : (inject hash dimensions height nodes).result = some output) : + (∀ node ∈ output, NodeAt hash dimensions height (inputs ++ (inject hash dimensions height nodes).inputs) node) ∧ + origins output = origins nodes := by + induction nodes generalizing output with + | nil => + have same : [] = output := Option.some.inj success + subst output + exact ⟨by simp, rfl⟩ + | cons node nodes ih => + unfold inject at success ⊢ + cases ticketsEq : node.tickets with + | nil => simp only [ticketsEq] at success; cases success + | cons lead members => + simp only [ticketsEq] at success ⊢ + by_cases consistent : (members.all fun ticket => + Merkle.rowsAt dimensions ticket.rows height == Merkle.rowsAt dimensions lead.rows height) = true + · simp only [consistent, Bool.not_true, Bool.false_eq_true, ↓reduceIte] at success ⊢ + cases running : (inject hash dimensions height nodes).result with + | none => simp [bind, Logged.bind, hashInput, running] at success + | some rest => + have tailValid : ∀ child ∈ nodes, PendingNode hash dimensions height inputs child := + fun child member => valid child (List.mem_cons.mpr (Or.inr member)) + obtain ⟨restValid, restOrigins⟩ := ih tailValid running + simp only [bind, pure, Logged.bind, hashInput, running, Logged.pure, Option.some.injEq] at success + subst output + simp only [bind, pure, Logged.bind, hashInput, running, Logged.pure, List.append_nil] + constructor + · intro child member + rcases List.mem_cons.mp member with rfl | restMem + · intro ticket ticketMem + apply PendingAt.finish_injected (rows := lead.rows) + · exact (valid node (by simp) ticket (by simpa only [ticketsEq] using ticketMem)).mono + (by intro input h; simp only [List.mem_append]; exact Or.inl h) + · exact present + · rcases List.mem_cons.mp ticketMem with rfl | member + · rfl + · exact beq_iff_eq.mp (List.all_eq_true.mp consistent ticket member) + · simp + · simp + · apply (restValid child restMem).mono + intro input h + simp only [List.mem_append] at h ⊢ + exact h.elim Or.inl (fun h => Or.inr (by simp only [List.mem_cons]; exact Or.inr (Or.inr h))) + · simp only [origins_cons, restOrigins, ticketsEq] + · have rejected : (members.all fun ticket => + Merkle.rowsAt dimensions ticket.rows height == Merkle.rowsAt dimensions lead.rows height) = false := + Bool.eq_false_iff.mpr consistent + simp only [rejected, Bool.not_false, ↓reduceIte] at success + cases success + +theorem initial_refines {hash : Hash} {dimensions : List Dimensions} + {inputs : List (List UInt8)} {tickets : List Ticket} {nodes : List Node} + (valid : ∀ ticket ∈ tickets, Merkle.shape dimensions ticket.rows = true ∧ + ticket.index < 2^Merkle.maxHeight dimensions ∧ ticket.proof = []) + (success : (initial hash dimensions (Merkle.maxHeight dimensions) tickets).result = some nodes) : + (∀ node ∈ nodes, NodeAt hash dimensions (Merkle.maxHeight dimensions) + (inputs ++ (initial hash dimensions (Merkle.maxHeight dimensions) tickets).inputs) node) ∧ + origins nodes = tickets.map (fun ticket => (ticket.index, ticket.rows)) := by + induction tickets generalizing nodes with + | nil => + have same : [] = nodes := Option.some.inj success + subst nodes + exact ⟨by simp, rfl⟩ + | cons ticket tickets ih => + cases running : (initial hash dimensions (Merkle.maxHeight dimensions) tickets).result with + | none => simp [initial, bind, Logged.bind, hashInput, running] at success + | some rest => + have tailValid : ∀ child ∈ tickets, Merkle.shape dimensions child.rows = true ∧ + child.index < 2^Merkle.maxHeight dimensions ∧ child.proof = [] := + fun child member => valid child (List.mem_cons.mpr (Or.inr member)) + obtain ⟨restValid, restOrigins⟩ := ih tailValid running + simp only [initial, bind, pure, Logged.bind, hashInput, running, Logged.pure, Option.some.injEq] at success + subst nodes + simp only [initial, bind, pure, Logged.bind, hashInput, running, Logged.pure, List.append_nil] + constructor + · intro node member + rcases List.mem_cons.mp member with rfl | restMem + · intro child childMem + obtain rfl := List.mem_singleton.mp childMem + obtain ⟨shape, bound, empty⟩ := valid child (by simp) + refine ⟨shape, bound, ?_, ?_, ?_, ?_⟩ + · simp only [empty, List.length_nil, Nat.zero_add] + · simp only [empty, List.length_nil, Nat.pow_zero, Nat.div_one] + · simp only [empty, Merkle.walk] + · intro input member + simp only [empty, Merkle.walk, List.mem_singleton] at member + subst input + simp + · apply (restValid node restMem).mono + intro input h + simp only [List.mem_append] at h ⊢ + exact h.elim Or.inl (fun h => Or.inr (by simp only [List.mem_cons]; exact Or.inr h)) + · simp only [origins_cons, restOrigins, List.map_cons, List.map_nil, List.singleton_append] + +theorem walk_refines {hash : Hash} {dimensions : List Dimensions} {steps height : Nat} + {inputs : List (List UInt8)} {nodes output : List Node} {proof remaining : List Digest} + (bounded : steps ≤ height) + (valid : ∀ node ∈ nodes, NodeAt hash dimensions height inputs node) + (success : (walk hash dimensions steps height nodes proof).result = some (output, remaining)) : + (∀ node ∈ output, NodeAt hash dimensions (height - steps) + (inputs ++ (walk hash dimensions steps height nodes proof).inputs) node) ∧ + origins output = origins nodes := by + induction steps generalizing height inputs nodes output proof remaining with + | zero => + have same : (nodes, proof) = (output, remaining) := Option.some.inj success + cases same + simp only [walk, pure, Logged.pure, Nat.sub_zero, List.append_nil] + exact ⟨valid, trivial⟩ + | succ steps ih => + have level : height - 1 + 1 = height := by omega + unfold walk at success ⊢ + obtain ⟨⟨parents, boundary⟩, combined, continued, logEq⟩ := Logged.bind_success success + obtain ⟨parentValid, parentOrigins⟩ := combine_refines (height := height - 1) + (by simpa only [level] using valid) combined + dsimp only at continued logEq + rw [← Logged.bind_if] at continued logEq + obtain ⟨next, injected, finished, nextLog⟩ := Logged.bind_success continued + have nextValid : ∀ node ∈ next, NodeAt hash dimensions (height - 1) + ((inputs ++ (combine hash nodes proof).inputs) ++ + (if Merkle.hasHeight dimensions (height - 1) then inject hash dimensions (height - 1) parents + else pure parents).inputs) node := by + by_cases present : Merkle.hasHeight dimensions (height - 1) = true + · simp only [present, ↓reduceIte] at injected ⊢ + exact (inject_refines present parentValid injected).1 + · simp only [present, Bool.false_eq_true, ↓reduceIte] at injected ⊢ + have same : parents = next := Option.some.inj injected + subst next + intro node member ticket ticketMem + have missing : Merkle.hasHeight dimensions (height - 1) = false := Bool.eq_false_iff.mpr present + simpa only [pure, Logged.pure, List.append_nil] using + (parentValid node member ticket ticketMem).finish_absent missing + have nextOrigins : origins next = origins parents := by + split at injected + next present => exact (inject_refines present parentValid injected).2 + next absent => + have same : parents = next := Option.some.inj injected + subst next + rfl + obtain ⟨outputValid, outputOrigins⟩ := ih (by omega) nextValid finished + constructor + · have finalHeight : height - 1 - steps = height - (steps + 1) := by omega + simpa only [logEq, nextLog, List.append_assoc, finalHeight] using outputValid + · exact outputOrigins.trans (nextOrigins.trans parentOrigins) + +theorem mapM_members {read : α → Option β} {inputs : List α} {outputs : List β} + (success : inputs.mapM read = some outputs) : + (∀ input ∈ inputs, ∃ output ∈ outputs, read input = some output) ∧ + (∀ output ∈ outputs, ∃ input ∈ inputs, read input = some output) := by + induction inputs generalizing outputs with + | nil => + have same : [] = outputs := Option.some.inj success + subst outputs + simp + | cons input inputs ih => + simp only [List.mapM_cons, bind, Option.bind_eq_some_iff, pure, Option.some.injEq] at success + obtain ⟨output, first, rest, running, rfl⟩ := success + obtain ⟨forward, backward⟩ := ih running + constructor + · intro source member + rcases List.mem_cons.mp member with rfl | member + · exact ⟨output, by simp, first⟩ + · obtain ⟨result, member, read⟩ := forward source member + exact ⟨result, List.mem_cons.mpr (Or.inr member), read⟩ + · intro result member + rcases List.mem_cons.mp member with rfl | member + · exact ⟨input, by simp, first⟩ + · obtain ⟨source, member, read⟩ := backward result member + exact ⟨source, List.mem_cons.mpr (Or.inr member), read⟩ + +theorem representatives_refines {indices : List Nat} {rows : List (List (List G))} + {tickets : List Ticket} (success : representatives indices rows = some tickets) : + (∀ ticket ∈ tickets, ticket.index ∈ indices ∧ ticket.proof = []) ∧ + ∀ source ∈ indices.zip rows, ∃ ticket ∈ tickets, ticket.index = source.1 ∧ ticket.rows = source.2 := by + let read : Nat → Option Ticket := fun index => do + let (_, values) ← (indices.zip rows).find? fun entry => entry.1 == index + if (indices.zip rows).all (fun entry => entry.1 != index || entry.2 == values) then + some (Ticket.mk index values []) + else none + change (uniqueIndices indices).mapM read = some tickets at success + have readSpec {index : Nat} {ticket : Ticket} (evaluated : read index = some ticket) : + ticket.index = index ∧ ticket.proof = [] ∧ + ∀ source ∈ indices.zip rows, source.1 = index → ticket.rows = source.2 := by + simp only [read, bind, Option.bind_eq_some_iff] at evaluated + obtain ⟨⟨found, values⟩, _, checked⟩ := evaluated + split at checked + next consistent => + have same := Option.some.inj checked + subst ticket + refine ⟨rfl, rfl, ?_⟩ + intro source member atIndex + have equality := List.all_eq_true.mp consistent source member + simp only [atIndex, bne_self_eq_false, Bool.false_or, beq_iff_eq] at equality + exact equality.symm + next => cases checked + obtain ⟨forward, backward⟩ := mapM_members success + constructor + · intro ticket member + obtain ⟨index, indexMem, evaluated⟩ := backward ticket member + obtain ⟨position, empty, _⟩ := readSpec evaluated + refine ⟨?_, empty⟩ + simpa only [position, uniqueIndices, List.mem_eraseDups, List.mem_mergeSort] using indexMem + · intro source member + have indexMem : source.1 ∈ uniqueIndices indices := by + simpa only [uniqueIndices, List.mem_eraseDups, List.mem_mergeSort] using (List.of_mem_zip member).1 + obtain ⟨ticket, ticketMem, evaluated⟩ := forward source.1 indexMem + obtain ⟨position, _, same⟩ := readSpec evaluated + exact ⟨ticket, ticketMem, position, same source member rfl⟩ + +theorem replay_refines {hash : Hash} {dimensions : List Dimensions} {capHeight : Nat} + {indices : List Nat} {rows : List (List (List G))} {proof : List Digest} {nodes : List Node} + (success : (replay hash dimensions capHeight indices rows proof).result = some nodes) : + dimensions ≠ [] ∧ rows.length = indices.length ∧ + (∀ node ∈ nodes, NodeAt hash dimensions (min capHeight (Merkle.maxHeight dimensions)) + (replay hash dimensions capHeight indices rows proof).inputs node) ∧ + ∀ source ∈ indices.zip rows, source ∈ origins nodes := by + unfold replay at success ⊢ + split at success + · cases success + next structural => + have nonempty : dimensions ≠ [] := by + simp only [Bool.or_eq_true, List.isEmpty_iff, bne_iff_ne, not_or] at structural + exact structural.1 + have count : rows.length = indices.length := by + simp only [Bool.or_eq_true, List.isEmpty_iff, bne_iff_ne, not_or] at structural + exact Decidable.not_not.mp structural.2 + simp only [if_neg structural] + dsimp only at success ⊢ + split at success + · cases success + next bounded => + simp only [if_neg bounded] + have bounds : ∀ index ∈ indices, index < 2^Merkle.maxHeight dimensions := by + simpa only [Bool.not_eq_true', Bool.not_eq_false, List.all_eq_true, decide_eq_true_eq] using bounded + obtain ⟨tickets, represented, continued, firstLog⟩ := Logged.bind_success success + have representation : representatives indices rows = some tickets := represented + obtain ⟨ticketIndices, sources⟩ := representatives_refines representation + split at continued + · cases continued + next fitted => + have fits : ∀ ticket ∈ tickets, Merkle.shape dimensions ticket.rows = true := by + have checked := fitted + simp only [Bool.or_eq_true, bne_iff_ne, Bool.not_eq_true', not_or] at checked + exact List.all_eq_true.mp (by simpa only [Bool.not_eq_false] using checked.2) + obtain ⟨leaves, initialized, walked, leafLog⟩ := Logged.bind_success continued + have initialValid : ∀ ticket ∈ tickets, Merkle.shape dimensions ticket.rows = true ∧ + ticket.index < 2^Merkle.maxHeight dimensions ∧ ticket.proof = [] := by + intro ticket member + exact ⟨fits ticket member, bounds ticket.index (ticketIndices ticket member).1, + (ticketIndices ticket member).2⟩ + obtain ⟨leafValid, leafOrigins⟩ := initial_refines (inputs := []) initialValid initialized + obtain ⟨⟨roots, remaining⟩, traversed, finished, walkLog⟩ := Logged.bind_success walked + obtain ⟨rootValid, rootOrigins⟩ := walk_refines (Nat.sub_le _ _) leafValid traversed + dsimp only at finished walkLog + split at finished + next consumed => + have same : roots = nodes := Option.some.inj finished + subst nodes + refine ⟨nonempty, count, ?_, ?_⟩ + · have heightEq : Merkle.maxHeight dimensions - (Merkle.maxHeight dimensions - capHeight) = + min capHeight (Merkle.maxHeight dimensions) := by omega + rw [firstLog, if_neg fitted, leafLog, walkLog] + simpa only [consumed, ↓reduceIte, + pure, Logged.pure, ofOption, List.nil_append, List.append_nil, heightEq] using rootValid + · intro source member + obtain ⟨ticket, ticketMem, indexEq, rowsEq⟩ := sources source member + rw [rootOrigins, leafOrigins] + exact List.mem_map.mpr ⟨ticket, ticketMem, by simp only [indexEq, rowsEq]⟩ + next => cases finished + +/-- Every original query, including duplicates and queries merged along the +frontier, has an individual path reaching its shared node. -/ +theorem replay_individual {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {indices : List Nat} {rows : List (List (List G))} {query : List (List G)} + {proof : List Digest} {nodes : List Node} + (success : (replay hash dimensions capHeight indices rows proof).result = some nodes) + (member : (index, query) ∈ indices.zip rows) : + ∃ node ∈ nodes, ∃ path result, + Merkle.replay hash dimensions capHeight index query path = some result ∧ + result.index = node.index ∧ result.hashing.digest = node.digest ∧ + result.hashing.inputs ⊆ (replay hash dimensions capHeight indices rows proof).inputs := by + obtain ⟨nonempty, _, valid, sources⟩ := replay_refines success + have source := sources (index, query) member + simp only [origins, List.mem_flatMap, List.mem_map] at source + obtain ⟨node, nodeMem, ticket, ticketMem, same⟩ := source + obtain ⟨indexEq, rowsEq⟩ := Prod.mk.inj same + subst index + subst query + have path := valid node nodeMem ticket ticketMem + have count : ticket.proof.length = Merkle.maxHeight dimensions - capHeight := by + have := path.depth + omega + exact ⟨node, nodeMem, ticket.proof, _, + Merkle.replay_complete nonempty path.shape count path.bound, + path.position, path.digest_eq, path.calls⟩ + +theorem verify_individual {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {indices : List Nat} {cap : List Digest} {rows : List (List (List G))} {query : List (List G)} + {proof : List Digest} + (accepted : verify hash dimensions capHeight indices cap rows proof = true) + (member : (index, query) ∈ indices.zip rows) : + ∃ path result, Merkle.replay hash dimensions capHeight index query path = some result ∧ + Merkle.verify hash dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ (replay hash dimensions capHeight indices rows proof).inputs := by + cases running : (replay hash dimensions capHeight indices rows proof).result with + | none => simp only [verify, running, Bool.false_eq_true] at accepted + | some nodes => + obtain ⟨node, nodeMem, path, result, individual, position, digestEq, inputs⟩ := + replay_individual running member + have capEq : cap[node.index]? = some node.digest := by + simp only [verify, running, accepts, List.all_eq_true] at accepted + exact beq_iff_eq.mp (accepted node nodeMem) + refine ⟨path, result, individual, ?_, inputs⟩ + simp only [Merkle.verify, individual, Merkle.accepts, position, digestEq, capEq, beq_self_eq_true] + +theorem verifyCovered_individual {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {indices : List Nat} {cap : List Digest} {rows : List (List (List G))} {query : List (List G)} + {proof : List Digest} + (accepted : verifyCovered hash dimensions capHeight indices cap rows proof = true) + (member : (index, query) ∈ indices.zip rows) : + ∃ path result, Merkle.replay hash dimensions capHeight index query path = some result ∧ + Merkle.verifyCovered hash dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ (replay hash dimensions capHeight indices rows proof).inputs := by + simp only [verifyCovered, Bool.and_eq_true] at accepted + obtain ⟨path, result, individual, verified, inputs⟩ := verify_individual accepted.2 member + exact ⟨path, result, individual, + by simp only [Merkle.verifyCovered, accepted.1, verified, Bool.and_self], inputs⟩ + +/-- Conflicting shared openings at a common public index expose a collision +within two reconstructed paths. All witness inputs occur in the actual +shared executions, although native verification may reuse their hashes. -/ +theorem verify_collision {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {leftIndices rightIndices : List Nat} {cap : List Digest} + {leftRows rightRows : List (List (List G))} {leftQuery rightQuery : List (List G)} + {leftProof rightProof : List Digest} + (coverage : Merkle.covered dimensions capHeight = true) + (left : verify hash dimensions capHeight leftIndices cap leftRows leftProof = true) + (right : verify hash dimensions capHeight rightIndices cap rightRows rightProof = true) + (leftMember : (index, leftQuery) ∈ leftIndices.zip leftRows) + (rightMember : (index, rightQuery) ∈ rightIndices.zip rightRows) + (different : leftQuery ≠ rightQuery) : + ∃ inputs, + inputs ⊆ (replay hash dimensions capHeight leftIndices leftRows leftProof).inputs ++ + (replay hash dimensions capHeight rightIndices rightRows rightProof).inputs ∧ + Merkle.CollisionOn hash inputs ∧ inputs.length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) ∧ + ∀ input ∈ inputs, input.length ≤ max 64 (8 * max leftQuery.flatten.length rightQuery.flatten.length) := by + obtain ⟨leftPath, leftResult, leftReplay, leftAccepted, leftInputs⟩ := verify_individual left leftMember + obtain ⟨rightPath, rightResult, rightReplay, rightAccepted, rightInputs⟩ := verify_individual right rightMember + obtain ⟨leftWitness, rightWitness, leftRun, rightRun, collision, count⟩ := + Merkle.verify_collision coverage leftAccepted rightAccepted different + have leftSame := Option.some.inj (leftRun.symm.trans leftReplay) + have rightSame := Option.some.inj (rightRun.symm.trans rightReplay) + subst leftWitness + subst rightWitness + refine ⟨leftResult.hashing.inputs ++ rightResult.hashing.inputs, ?_, collision, count, ?_⟩ + · intro input member + simp only [List.mem_append] at member ⊢ + exact member.elim (fun h => Or.inl (leftInputs h)) (fun h => Or.inr (rightInputs h)) + · intro input member + rcases List.mem_append.mp member with member | member + · have := Merkle.replay_input_length leftReplay member + omega + · have := Merkle.replay_input_length rightReplay member + omega + +theorem verifyCovered_collision {hash : Hash} {dimensions : List Dimensions} {capHeight index : Nat} + {leftIndices rightIndices : List Nat} {cap : List Digest} + {leftRows rightRows : List (List (List G))} {leftQuery rightQuery : List (List G)} + {leftProof rightProof : List Digest} + (left : verifyCovered hash dimensions capHeight leftIndices cap leftRows leftProof = true) + (right : verifyCovered hash dimensions capHeight rightIndices cap rightRows rightProof = true) + (leftMember : (index, leftQuery) ∈ leftIndices.zip leftRows) + (rightMember : (index, rightQuery) ∈ rightIndices.zip rightRows) + (different : leftQuery ≠ rightQuery) : + ∃ inputs, + inputs ⊆ (replay hash dimensions capHeight leftIndices leftRows leftProof).inputs ++ + (replay hash dimensions capHeight rightIndices rightRows rightProof).inputs ∧ + Merkle.CollisionOn hash inputs ∧ inputs.length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) ∧ + ∀ input ∈ inputs, input.length ≤ max 64 (8 * max leftQuery.flatten.length rightQuery.flatten.length) := by + simp only [verifyCovered, Bool.and_eq_true] at left right + exact verify_collision left.1 left.2 right.2 leftMember rightMember different + +theorem blake3_collision {dimensions : List Dimensions} {capHeight index : Nat} + {leftIndices rightIndices : List Nat} {cap : List Digest} + {leftRows rightRows : List (List (List G))} {leftQuery rightQuery : List (List G)} + {leftProof rightProof : List Digest} + (left : verifyCovered Blake3.digest dimensions capHeight leftIndices cap leftRows leftProof = true) + (right : verifyCovered Blake3.digest dimensions capHeight rightIndices cap rightRows rightProof = true) + (leftMember : (index, leftQuery) ∈ leftIndices.zip leftRows) + (rightMember : (index, rightQuery) ∈ rightIndices.zip rightRows) + (different : leftQuery ≠ rightQuery) : + ∃ inputs, + inputs ⊆ (replay Blake3.digest dimensions capHeight leftIndices leftRows leftProof).inputs ++ + (replay Blake3.digest dimensions capHeight rightIndices rightRows rightProof).inputs ∧ + Merkle.CollisionOn Blake3.digest inputs ∧ + inputs.length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) ∧ + ∀ input ∈ inputs, input.length ≤ max 64 (8 * max leftQuery.flatten.length rightQuery.flatten.length) := + verifyCovered_collision left right leftMember rightMember different + +theorem blake3_native_collision {dimensions : List Dimensions} {capHeight index : Nat} + {leftIndices rightIndices : List Nat} {cap : List Digest} + {leftRows rightRows : List (List (List G))} {leftQuery rightQuery : List (List G)} + {leftProof rightProof : List Digest} + (left : verifyCovered Blake3.digest dimensions capHeight leftIndices cap leftRows leftProof = true) + (right : verifyCovered Blake3.digest dimensions capHeight rightIndices cap rightRows rightProof = true) + (leftMember : (index, leftQuery) ∈ leftIndices.zip leftRows) + (rightMember : (index, rightQuery) ∈ rightIndices.zip rightRows) + (different : leftQuery ≠ rightQuery) + (leftBound : leftQuery.flatten.length < 2^61) (rightBound : rightQuery.flatten.length < 2^61) : + ∃ inputs, + inputs ⊆ (replay Blake3.digest dimensions capHeight leftIndices leftRows leftProof).inputs ++ + (replay Blake3.digest dimensions capHeight rightIndices rightRows rightProof).inputs ∧ + Merkle.CollisionOn Blake3.digest inputs ∧ + inputs.length ≤ 2 + 6 * (Merkle.maxHeight dimensions - capHeight) ∧ + ∀ input ∈ inputs, Blake3.NativeInput input := by + obtain ⟨inputs, subset, collision, count, bytes⟩ := blake3_collision left right leftMember rightMember different + refine ⟨inputs, subset, collision, count, ?_⟩ + intro input member + have := bytes input member + unfold Blake3.NativeInput + omega + +end Aiur.NativeAIR.PrunedMerkle diff --git a/Ix/Aiur/Proofs/PublicCircuitExecution.lean b/Ix/Aiur/Proofs/PublicCircuitExecution.lean new file mode 100644 index 000000000..5239dac92 --- /dev/null +++ b/Ix/Aiur/Proofs/PublicCircuitExecution.lean @@ -0,0 +1,78 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitTableExecution + +/-! Finite execution of the selected public success call from valued circuit +witnesses. Public rank-zero padding is normalized without changing lookup +balance. Native witness/lookup reflection and cryptographic reduction remain +separate obligations. -/ + +namespace Aiur.AIR + +theorem PaddedLookupBalance.congr_queries {width : Nat} {left right : List (List G)} + {providers : List (Provider (List G))} (balanced : PaddedLookupBalance width left providers) + (same : left.map (padMessage width) = right.map (padMessage width)) : + PaddedLookupBalance width right providers := by + change ExactLookupBalance _ _ at balanced ⊢ + rwa [← same] + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem claim_message (selection : Selection) (input : Array G) : + functionMessage ⟨selection.function, input, selection.success, 0⟩ = + (buildClaim selection.function input selection.success).toList ++ [0] := by + simp only [functionMessage, buildClaim, Array.toList_append, List.cons_append, + List.nil_append, functionChannel] + rfl + +/-- The selected public success call executes from valued circuit witnesses +and their physical provider balance. The public query has the actual claim +encoding, whose omitted rank is zero. Native witness extraction, lookup-slot +encoding/layout reflection and the cryptographic reduction remain separate. -/ +theorem Backend.public_circuit_execution {selection : Selection} (backend : Backend selection) + (tables : AuxiliaryTables) (witnesses : List CircuitWitness) (width : Nat) + (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: + circuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : (circuitQueryPool (witnesses.map (·.emission))).length + 1 < gSize.toNat) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ circuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ backend.compiled.bytecode.circuits) + (emitted : ∀ witness ∈ witnesses, witness.Emitted backend.compiled.bytecode) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes backend.compiled.bytecode) + (limits : ∀ witness ∈ witnesses, witness.LookupBounds) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) + ⟨selection.function, input, selection.success, 0⟩ := by + let request : Call := ⟨selection.function, input, selection.success, 0⟩ + have normalized : PaddedLookupBalance width + (functionMessage request :: circuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission))) := by + apply balanced.congr_queries + change padMessage width (buildClaim selection.function input selection.success).toList :: _ = + padMessage width (functionMessage request) :: _ + rw [show padMessage width (functionMessage request) = + padMessage width (buildClaim selection.function input selection.success).toList from + claim_padding selection width input] + apply circuitWitnesses_execute tables witnesses normalized bounded ?_ memoryValid canonical + backend.rowCounts backend.lookupShapes circuits emitted satisfied shapes limits + (fun _ member => List.mem_cons_of_mem _ member) (backend.root_lookupShape input arity) List.mem_cons_self + intro query member + rcases List.mem_cons.mp member with same | rest + · subst query + change (functionMessage ⟨selection.function, input, selection.success, 0⟩).length ≤ width + rw [claim_message, List.length_append, List.length_singleton, Array.length_toList] + exact publicWidth + · exact queryWidths query rest + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/QuerySlotMessages.lean b/Ix/Aiur/Proofs/QuerySlotMessages.lean new file mode 100644 index 000000000..2de72f2ce --- /dev/null +++ b/Ix/Aiur/Proofs/QuerySlotMessages.lean @@ -0,0 +1,216 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockQuerySlots + +/-! +Decode the unique active query in each valued lookup slot. Its message +equals the native-style combined message after padding, and its multiplicity +is zero or one. The decoded list preserves exact padded lookup balance and +has at most one query per allocated slot. + +The single-writer premise for ungated branchless slots remains explicit. +The model-to-native and randomized-compression reductions are separate. +-/ + +namespace Aiur.AIR + +def activeQuerySlot (queries : List QueryPart) (slot : Nat) : List QueryPart := + queries.filter fun query => query.slot == slot && query.selector == 1 + +def querySlotParts (queries : List QueryPart) (slot : Nat) : List (G × List G) := + (queries.filter fun query => query.slot == slot).map fun query => (query.selector, query.message) + +def querySlotMultiplicity (queries : List QueryPart) (slot : Nat) : G := + selectorSum ((querySlotParts queries slot).map Prod.fst) + +def decodedQuery (queries : List QueryPart) (slot : Nat) : Option (List G) := + (activeQuerySlot queries slot).head?.map (·.message) + +def encodedQuery (branchless : Bool) (queries : List QueryPart) (slot : Nat) : Option (List G) := + if querySlotMultiplicity queries slot = 1 then some (slotMessage branchless (querySlotParts queries slot)) + else none + +def decodedQueries (queries : List QueryPart) (limit : Nat) : List (List G) := + (List.range limit).filterMap (decodedQuery queries) + +def encodedQueries (branchless : Bool) (queries : List QueryPart) (limit : Nat) : List (List G) := + (List.range limit).filterMap (encodedQuery branchless queries) + +theorem singleton_of_member_length_le_one {α : Type} {items : List α} {item : α} + (member : item ∈ items) (bound : items.length ≤ 1) : items = [item] := by + cases items with + | nil => cases member + | cons head tail => + have empty : tail = [] := List.length_eq_zero_iff.mp (by simp only [List.length_cons] at bound; omega) + subst tail + have equal := List.mem_singleton.mp member + subst item + rfl + +theorem selector_pair_chosen_count {α : Type} {parts : List (G × α)} + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (count : (parts.map Prod.fst).count 1 = 1) + {chosen : G × α} (member : chosen ∈ parts) (active : chosen.1 = 1) : + ∃ before after, parts = before ++ chosen :: after ∧ + ∀ part ∈ before ++ after, part.1 = 0 := by + obtain ⟨before, after, equal⟩ := List.mem_iff_append.mp member + have counts := count + rw [equal, List.map_append, List.count_append, List.map_cons, active, List.count_cons_self] at counts + have empty : ((before ++ after).map Prod.fst).count 1 = 0 := by + rw [List.map_append, List.count_append] + omega + have absent := List.count_eq_zero.mp empty + refine ⟨before, after, equal, ?_⟩ + intro part present + have original : part ∈ parts := by + rw [equal] + rcases List.mem_append.mp present with left | right + · exact List.mem_append_left _ left + · exact List.mem_append_right _ (List.mem_cons_of_mem _ right) + rcases G.boolean_of_constraint (individual part original) with inactive | selected + · exact inactive + · exact False.elim (absent (List.mem_map.mpr ⟨part, present, selected⟩)) + +theorem slotMessage_chosen_count (width : Nat) (branchless : Bool) {parts : List (G × List G)} + (single : branchless = true → parts.length ≤ 1) + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (count : (parts.map Prod.fst).count 1 = 1) + {chosen : G × List G} (member : chosen ∈ parts) (active : chosen.1 = 1) : + padMessage width (slotMessage branchless parts) = padMessage width chosen.2 := by + cases branchless with + | false => + obtain ⟨before, after, equal, zero⟩ := selector_pair_chosen_count individual count member active + rw [equal] + exact weightedMessage_split width before after chosen active zero + | true => + rw [singleton_of_member_length_le_one member (single rfl)] + rfl + +theorem querySlotParts_count (queries : List QueryPart) (slot : Nat) : + ((querySlotParts queries slot).map Prod.fst).count 1 = queryCount queries slot := by + rw [querySlotParts, List.map_map, List.count_eq_countP, List.countP_map, + List.countP_eq_length_filter, List.filter_filter] + simp only [Function.comp_def, queryCount, Bool.and_comm] + +theorem querySlotParts_member {queries : List QueryPart} {query : QueryPart} + (member : query ∈ queries) : (query.selector, query.message) ∈ querySlotParts queries query.slot := by + apply List.mem_map.mpr + exact ⟨query, List.mem_filter.mpr ⟨member, by simp⟩, rfl⟩ + +theorem QuerySlots.slot_boolean {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (slot : Nat) : + ∀ part ∈ querySlotParts queries slot, booleanConstraint part.1 = 0 := by + intro part member + obtain ⟨query, queryMember, equal⟩ := List.mem_map.mp member + subst part + exact slots.boolean query (List.mem_filter.mp queryMember).1 + +theorem QuerySlots.slot_multiplicity {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (slot : Nat) : + querySlotMultiplicity queries slot = G.ofNat (queryCount queries slot) := by + rw [querySlotMultiplicity, selectorSum_eq_count] + · rw [querySlotParts_count] + · intro value member + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst value + exact G.boolean_of_constraint (slots.slot_boolean slot part partMember) + +theorem QuerySlots.multiplicity_boolean {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (slot : Nat) : + querySlotMultiplicity queries slot = 0 ∨ querySlotMultiplicity queries slot = 1 := by + have bound := Nat.le_trans (slots.count slot) (gateCount_le_one gate) + have count : queryCount queries slot = 0 ∨ queryCount queries slot = 1 := by omega + rw [slots.slot_multiplicity slot] + rcases count with zero | one + · rw [zero] + exact Or.inl rfl + · rw [one] + exact Or.inr rfl + +theorem QuerySlots.active_singleton {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) {query : QueryPart} + (member : query ∈ queries) (active : query.selector = 1) : + activeQuerySlot queries query.slot = [query] := by + apply singleton_of_member_length_le_one + · exact List.mem_filter.mpr ⟨member, by simp only [Bool.and_eq_true, beq_iff_eq]; exact ⟨trivial, active⟩⟩ + · exact Nat.le_trans (slots.count _) (gateCount_le_one gate) + +theorem QuerySlots.decoded {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) {query : QueryPart} + (member : query ∈ queries) (active : query.selector = 1) : + decodedQuery queries query.slot = some query.message := by + rw [decodedQuery, slots.active_singleton member active] + rfl + +theorem QuerySlots.decoded_member {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) {query : QueryPart} + (member : query ∈ queries) (active : query.selector = 1) : + query.message ∈ decodedQueries queries finish := by + apply List.mem_filterMap.mpr + exact ⟨query.slot, List.mem_range.mpr (slots.range query member).2, slots.decoded member active⟩ + +theorem QuerySlots.slot_message {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (width : Nat) (branchless : Bool) + (single : branchless = true → ∀ slot, (querySlotParts queries slot).length ≤ 1) + {query : QueryPart} (member : query ∈ queries) (active : query.selector = 1) : + padMessage width (slotMessage branchless (querySlotParts queries query.slot)) = padMessage width query.message := by + have count : queryCount queries query.slot = 1 := + congrArg List.length (slots.active_singleton member active) + exact slotMessage_chosen_count width branchless (fun enabled => single enabled query.slot) + (slots.slot_boolean _) ((querySlotParts_count _ _).trans count) + (querySlotParts_member member) active + +theorem QuerySlots.slot_reflects {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (width : Nat) (branchless : Bool) + (single : branchless = true → ∀ slot, (querySlotParts queries slot).length ≤ 1) (slot : Nat) : + (encodedQuery branchless queries slot).map (padMessage width) = + (decodedQuery queries slot).map (padMessage width) := by + cases found : activeQuerySlot queries slot with + | nil => + have count : queryCount queries slot = 0 := congrArg List.length found + have inactive : querySlotMultiplicity queries slot = 0 := by rw [slots.slot_multiplicity slot, count]; rfl + simp only [encodedQuery, decodedQuery, found, inactive, Ne.symm G.one_ne_zero, if_false, + List.head?_nil, Option.map_none] + | cons query rest => + have member : query ∈ activeQuerySlot queries slot := by rw [found]; exact List.mem_cons_self + obtain ⟨original, same, active⟩ := by + simpa only [activeQuerySlot, List.mem_filter, Bool.and_eq_true, beq_iff_eq] using member + have singleton := slots.active_singleton original active + rw [same] at singleton + have count : queryCount queries slot = 1 := congrArg List.length singleton + have multiplicity : querySlotMultiplicity queries slot = 1 := by rw [slots.slot_multiplicity slot, count]; rfl + have message := slots.slot_message width branchless single original active + rw [same] at message + simp only [encodedQuery, decodedQuery, singleton, multiplicity, if_true, + List.head?_cons, Option.map_some] + exact congrArg some message + +theorem QuerySlots.queries_reflect {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (width : Nat) (branchless : Bool) + (single : branchless = true → ∀ slot, (querySlotParts queries slot).length ≤ 1) (limit : Nat) : + (encodedQueries branchless queries limit).map (padMessage width) = + (decodedQueries queries limit).map (padMessage width) := by + simp only [encodedQueries, decodedQueries, List.map_filterMap] + apply congrArg (fun read : Nat → Option (List G) => (List.range limit).filterMap read) + funext slot + exact slots.slot_reflects width branchless single slot + +theorem QuerySlots.padded_balance {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (width : Nat) (branchless : Bool) + (single : branchless = true → ∀ slot, (querySlotParts queries slot).length ≤ 1) + (limit : Nat) (providers : List (Provider (List G))) + (balanced : PaddedLookupBalance width (encodedQueries branchless queries limit) providers) : + PaddedLookupBalance width (decodedQueries queries limit) providers := by + unfold PaddedLookupBalance at balanced ⊢ + rw [← slots.queries_reflect width branchless single limit] + exact balanced + +theorem decodedQueries_length (queries : List QueryPart) (limit : Nat) : + (decodedQueries queries limit).length ≤ limit := by + simpa only [decodedQueries, List.length_range] using + List.length_filterMap_le (decodedQuery queries) (List.range limit) + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/QuerySlots.lean b/Ix/Aiur/Proofs/QuerySlots.lean new file mode 100644 index 000000000..0f9d6d5e4 --- /dev/null +++ b/Ix/Aiur/Proofs/QuerySlots.lean @@ -0,0 +1,203 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FunctionRows + +/-! +Lookup-slot intervals and natural active-query counts. Sequential regions +are disjoint, while shared regions combine bounded selector families. The +count invariant excludes duplicate active contributions without requiring +the number of inactive writers in a slot to fit the field characteristic. +-/ + +namespace Aiur.AIR +open Bytecode + +def gateCount (gate : G) : Nat := if gate = 1 then 1 else 0 + +def queryCount (queries : List QueryPart) (slot : Nat) : Nat := + (queries.filter fun query => query.slot == slot && query.selector == 1).length + +structure QuerySlots (gate : G) (start finish : Nat) (queries : List QueryPart) : Prop where + extent : start ≤ finish + range : ∀ query ∈ queries, start ≤ query.slot ∧ query.slot < finish + boolean : ∀ query ∈ queries, booleanConstraint query.selector = 0 + count : ∀ slot, queryCount queries slot ≤ gateCount gate + +theorem gateCount_le_one (gate : G) : gateCount gate ≤ 1 := by + simp only [gateCount] + split <;> omega + +theorem gateCount_zero : gateCount 0 = 0 := by + simp [gateCount, Ne.symm G.one_ne_zero] + +theorem queryCount_append (first rest : List QueryPart) (slot : Nat) : + queryCount (first ++ rest) slot = queryCount first slot + queryCount rest slot := by + simp only [queryCount, List.filter_append, List.length_append] + +theorem QuerySlots.empty (gate : G) (start : Nat) : QuerySlots gate start start [] := + ⟨Nat.le_refl _, by simp, by simp, by simp [queryCount]⟩ + +theorem QuerySlots.outside {gate : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots gate start finish queries) (slot : Nat) + (outside : slot < start ∨ finish ≤ slot) : queryCount queries slot = 0 := by + apply List.length_eq_zero_iff.mpr + apply List.filter_eq_nil_iff.mpr + intro query member + have range := slots.range query member + simp only [Bool.and_eq_true, beq_iff_eq] + intro same + omega + +theorem QuerySlots.weaken {first last : G} {start finish : Nat} {queries : List QueryPart} + (slots : QuerySlots first start finish queries) (bound : gateCount first ≤ gateCount last) : + QuerySlots last start finish queries := + ⟨slots.extent, slots.range, slots.boolean, fun slot => Nat.le_trans (slots.count slot) bound⟩ + +theorem QuerySlots.append {gate : G} {start middle finish : Nat} {first rest : List QueryPart} + (left : QuerySlots gate start middle first) (right : QuerySlots gate middle finish rest) : + QuerySlots gate start finish (first ++ rest) := by + refine ⟨Nat.le_trans left.extent right.extent, ?_, ?_, ?_⟩ + · intro query member + rcases List.mem_append.mp member with before | after + · have range := left.range query before + exact ⟨range.1, Nat.lt_of_lt_of_le range.2 right.extent⟩ + · have range := right.range query after + exact ⟨Nat.le_trans left.extent range.1, range.2⟩ + · intro query member + rcases List.mem_append.mp member with before | after + · exact left.boolean query before + · exact right.boolean query after + · intro slot + rw [queryCount_append] + by_cases before : slot < middle + · rw [right.outside slot (Or.inl before), Nat.add_zero] + exact left.count slot + · rw [left.outside slot (Or.inr (by omega)), Nat.zero_add] + exact right.count slot + +theorem QuerySlots.single (gate : G) (slot : Nat) (message : List G) + (boolean : booleanConstraint gate = 0) : + QuerySlots gate slot (slot + 1) [⟨slot, gate, message⟩] := by + refine ⟨by omega, ?_, ?_, ?_⟩ + · intro query member + have same := List.mem_singleton.mp member + subst query + exact ⟨Nat.le_refl _, Nat.lt_succ_self slot⟩ + · intro query member + have same := List.mem_singleton.mp member + subst query + exact boolean + · intro index + simp only [queryCount, gateCount, List.filter_cons, List.filter_nil, + Bool.and_eq_true, beq_iff_eq] + split + · rename_i selected + rw [selected.2] + exact Nat.le_refl 1 + · exact Nat.zero_le _ + +theorem queryParts_cons (slot : Nat) (gate : G) (message : List G) (queries : List (List G)) : + queryParts slot gate (message :: queries) = + ⟨slot, gate, message⟩ :: queryParts (slot + 1) gate queries := by + simp [queryParts, List.mapIdx_cons, Nat.add_comm, Nat.add_left_comm] + +theorem QuerySlots.indexed (gate : G) (slot : Nat) (queries : List (List G)) + (boolean : booleanConstraint gate = 0) : + QuerySlots gate slot (slot + queries.length) (queryParts slot gate queries) := by + induction queries generalizing slot with + | nil => exact QuerySlots.empty gate slot + | cons message queries ih => + rw [queryParts_cons] + have result := (QuerySlots.single gate slot message boolean).append (ih (slot + 1)) + simpa only [List.singleton_append, List.length_cons, Nat.add_assoc, + Nat.add_comm 1 queries.length] using result + +theorem fold_lookup_start (emissions : List BlockEmission) (start : Nat) : + start ≤ emissions.foldl (fun current emission => max current emission.lookup) start := by + induction emissions generalizing start with + | nil => exact Nat.le_refl _ + | cons emission emissions ih => + exact Nat.le_trans (Nat.le_max_left start emission.lookup) (ih _) + +theorem fold_lookup_member {emissions : List BlockEmission} {emission : BlockEmission} + (member : emission ∈ emissions) (start : Nat) : + emission.lookup ≤ emissions.foldl (fun current emission => max current emission.lookup) start := by + induction emissions generalizing start with + | nil => cases member + | cons head rest ih => + rcases List.mem_cons.mp member with equal | tail + · subst emission + exact Nat.le_trans (Nat.le_max_right start head.lookup) (fold_lookup_start rest _) + · exact ih tail _ + +theorem gateCount_list (gates : List G) : (gates.map gateCount).sum = gates.count 1 := by + induction gates with + | nil => rfl + | cons gate gates ih => + by_cases active : gate = 1 + · subst gate + simp [gateCount, ih, List.count_cons_self, Nat.add_comm] + · simp [gateCount, active, ih] + +theorem selector_gateCount {gates : List G} + (individual : ∀ gate ∈ gates, booleanConstraint gate = 0) + (bounded : gates.length < gSize.toNat) + (combined : booleanConstraint (selectorSum gates) = 0) : + gates.count 1 = gateCount (selectorSum gates) := by + have count := selectorSum_n_eq_count + (fun gate member => G.boolean_of_constraint (individual gate member)) bounded + rcases G.boolean_of_constraint combined with inactive | active + · rw [inactive, gateCount_zero] + exact count.symm.trans (congrArg G.n inactive) + · rw [active] + exact count.symm.trans (congrArg G.n active) + +theorem queryCount_flatMap_le {α : Type} {source : List α} {emissions : List BlockEmission} + (gate : α → G) (start : Nat) + (related : List.Forall₂ (fun item emission => + QuerySlots (gate item) start emission.lookup emission.queries) source emissions) (slot : Nat) : + queryCount (emissions.flatMap (·.queries)) slot ≤ ((source.map gate).map gateCount).sum := by + induction related with + | nil => exact Nat.le_refl 0 + | @cons item emission items emissions first rest ih => + simp only [List.flatMap_cons, queryCount_append, List.map_cons, List.sum_cons] + exact Nat.add_le_add (first.count slot) ih + +theorem forall₂_right_member {α β : Type} {source : List α} {target : List β} + {relation : α → β → Prop} (related : List.Forall₂ relation source target) + {item : β} (member : item ∈ target) : ∃ original ∈ source, relation original item := by + induction related with + | nil => cases member + | @cons head result heads results first rest ih => + rcases List.mem_cons.mp member with equal | tail + · subst item + exact ⟨head, List.mem_cons_self, first⟩ + · obtain ⟨original, present, evidence⟩ := ih tail + exact ⟨original, List.mem_cons_of_mem _ present, evidence⟩ + +theorem QuerySlots.join {α : Type} {source : List α} {emissions : List BlockEmission} + (gate : α → G) (parent : G) (values : Array RowValue) (column lookup : Nat) + (related : List.Forall₂ (fun item emission => + QuerySlots (gate item) lookup emission.lookup emission.queries) source emissions) + (count : (source.map gate).count 1 ≤ gateCount parent) : + QuerySlots parent lookup (joinBlockEmissions values column lookup emissions).lookup + (joinBlockEmissions values column lookup emissions).queries := by + refine ⟨fold_lookup_start emissions lookup, ?_, ?_, ?_⟩ + · intro query member + obtain ⟨emission, emissionMember, queryMember⟩ := List.mem_flatMap.mp member + obtain ⟨item, _, evidence⟩ := forall₂_right_member related emissionMember + have range := evidence.range query queryMember + exact ⟨range.1, Nat.lt_of_lt_of_le range.2 (fold_lookup_member emissionMember lookup)⟩ + · intro query member + obtain ⟨emission, emissionMember, queryMember⟩ := List.mem_flatMap.mp member + obtain ⟨item, _, evidence⟩ := forall₂_right_member related emissionMember + exact evidence.boolean query queryMember + · intro slot + have bounded := queryCount_flatMap_le gate lookup related slot + rw [gateCount_list] at bounded + exact Nat.le_trans bounded count + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/Quotient.lean b/Ix/Aiur/Proofs/Quotient.lean new file mode 100644 index 000000000..345a0e987 --- /dev/null +++ b/Ix/Aiur/Proofs/Quotient.lean @@ -0,0 +1,114 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.QuotientAlgebra +import Ix.Aiur.Proofs.Selectors + +/-! Checked coordinate pairing and the exact out-of-domain equality. +This reflects arithmetic only; commitment binding and low-degree extraction +remain distinct obligations before the equality implies trace constraints. +-/ + +namespace Aiur.NativeAIR.Quotient + +open ProofCodec (Extension) +open LogUp (Coordinates) + +theorem coefficients_flatten (pairs : List (Coordinates Extension)) : + coefficients (Coordinates.flatten pairs) = + some (pairs.map fun pair => pair.c0 + pair.c1 * Extension.basis) := by + induction pairs with + | nil => rfl + | cons pair pairs ih => + simp only [Coordinates.flatten, List.flatMap_cons, List.cons_append, List.nil_append, + List.map_cons] at * + simp only [coefficients, ih, bind, pure, Option.bind_some] + +theorem coefficients_success {row values : List Extension} (accepted : coefficients row = some values) : + ∃ pairs : List (Coordinates Extension), row = Coordinates.flatten pairs ∧ + values = pairs.map (fun pair => pair.c0 + pair.c1 * Extension.basis) := by + induction row using coefficients.induct generalizing values with + | case1 => cases accepted; exact ⟨[], rfl, rfl⟩ + | case2 first => cases accepted + | case3 first second rest ih => + simp only [coefficients, bind, pure, Option.bind_eq_some_iff, Option.some.injEq] at accepted + obtain ⟨tail, tailRead, rfl⟩ := accepted + obtain ⟨pairs, restEqual, tailEqual⟩ := ih tailRead + refine ⟨⟨first, second⟩ :: pairs, ?_, ?_⟩ + · simp only [Coordinates.flatten, List.flatMap_cons, List.cons_append, List.nil_append] at * + rw [restEqual] + · rw [tailEqual]; rfl + +theorem coefficients_length {row values : List Extension} (accepted : coefficients row = some values) : + row.length = 2 * values.length := by + obtain ⟨pairs, rfl, rfl⟩ := coefficients_success accepted + rw [Coordinates.flatten_length, List.length_map] + +theorem coefficients_defined (row : List Extension) (even : row.length % 2 = 0) : + ∃ values, coefficients row = some values := by + induction row using coefficients.induct with + | case1 => exact ⟨[], rfl⟩ + | case2 first => simp only [List.length_cons, List.length_nil] at even; omega + | case3 first second rest ih => + have tailEven : rest.length % 2 = 0 := by + simp only [List.length_cons] at even + omega + obtain ⟨tail, read⟩ := ih tailEven + exact ⟨(first + second * Extension.basis) :: tail, by + simp only [coefficients, read, bind, pure, Option.bind_some]⟩ + +theorem coefficients_defined_iff (row : List Extension) : + (∃ values, coefficients row = some values) ↔ row.length % 2 = 0 := by + constructor + · rintro ⟨values, accepted⟩ + rw [coefficients_length accepted] + omega + · exact coefficients_defined row + +theorem evaluate_success (domain : Domain.Subgroup) (point : Extension) {row : List Extension} {value : Extension} + (accepted : evaluate domain point row = some value) : + ∃ values, coefficients row = some values ∧ + value = horner (point ^ Domain.size domain) values := by + simp only [evaluate, bind, pure, Option.bind_eq_some_iff, Option.some.injEq] at accepted + obtain ⟨values, read, rfl⟩ := accepted + exact ⟨values, read, by rw [Extension.power_eq]⟩ + +theorem evaluate_powers (domain : Domain.Subgroup) (point : Extension) {row : List Extension} {value : Extension} + (accepted : evaluate domain point row = some value) : + ∃ pairs : List (Coordinates Extension), row = Coordinates.flatten pairs ∧ + value = LogUp.sum ((pairs.zipIdx).map fun (pair, index) => + point ^ (Domain.size domain * index) * (pair.c0 + pair.c1 * Extension.basis)) := by + obtain ⟨values, read, rfl⟩ := evaluate_success domain point accepted + obtain ⟨pairs, rowEqual, rfl⟩ := coefficients_success read + refine ⟨pairs, rowEqual, ?_⟩ + have powers := horner_powers (point ^ Domain.size domain) + (pairs.map fun pair => pair.c0 + pair.c1 * Extension.basis) 0 + simp only [Lean.Grind.Semiring.pow_zero, Lean.Grind.Semiring.one_mul] at powers + rw [powers] + simp only [List.zipIdx_map, List.map_map, Function.comp_def, Domain.Algebra.power_mul, + Prod.map, id] + +theorem check_true_iff (domain : Domain.Subgroup) (point alpha : Extension) (constraints row : List Extension) : + check domain point alpha constraints row = some true ↔ + Domain.vanishing domain point ≠ 0 ∧ ∃ values, coefficients row = some values ∧ + composition alpha constraints = + Domain.vanishing domain point * horner (point ^ Domain.size domain) values := by + constructor + · intro accepted + simp only [check, bind, pure, Option.bind_eq_some_iff, Option.some.injEq, beq_iff_eq] at accepted + obtain ⟨selected, selectorsRead, value, valueRead, equal⟩ := accepted + have invert := (Domain.selectors_success domain point selected selectorsRead).2.2.2 + obtain ⟨values, read, valueEqual⟩ := evaluate_success domain point valueRead + refine ⟨(Domain.selectors_defined_iff _ _).mp ⟨selected, selectorsRead⟩, values, read, ?_⟩ + rw [← valueEqual] + exact (inverse_check _ _ _ _ invert).mp equal + · rintro ⟨nonzero, values, read, identity⟩ + obtain ⟨selected, selectorsRead⟩ := Domain.selectors_defined domain point nonzero + have invert := (Domain.selectors_success domain point selected selectorsRead).2.2.2 + have equal := (inverse_check _ _ _ _ invert).mpr identity + simp only [check, selectorsRead, evaluate, read, bind, pure, Option.bind_some, + Extension.power_eq, equal, beq_self_eq_true] + +end Aiur.NativeAIR.Quotient diff --git a/Ix/Aiur/Proofs/QuotientAlgebra.lean b/Ix/Aiur/Proofs/QuotientAlgebra.lean new file mode 100644 index 000000000..e39a36a1d --- /dev/null +++ b/Ix/Aiur/Proofs/QuotientAlgebra.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Quotient +import Ix.Aiur.Proofs.SelectorAlgebra +import Ix.Aiur.Proofs.LogUpAlgebra + +/-! The two Horner conventions used by the native verifier: quotient +coefficients in ascending powers and constraints in descending powers. +-/ + +namespace Aiur.NativeAIR.Quotient + +open Lean.Grind +variable {W : Type} [CommRing W] + +theorem horner_nil (point : W) : horner point [] = 0 := rfl + +theorem horner_cons (point first : W) (rest : List W) : + horner point (first :: rest) = first + point * horner point rest := rfl + +theorem horner_append (point : W) (left right : List W) : + horner point (left ++ right) = horner point left + point ^ left.length * horner point right := by + induction left with + | nil => simp only [List.nil_append, List.length_nil, horner_nil, Semiring.pow_zero]; grind + | cons first rest ih => + simp only [List.cons_append, horner_cons, ih, List.length_cons, Semiring.pow_succ] + grind + +theorem horner_powers (point : W) (values : List W) (offset : Nat) : + point ^ offset * horner point values = + LogUp.sum ((values.zipIdx offset).map fun (value, index) => point ^ index * value) := by + induction values generalizing offset with + | nil => simp only [horner_nil, Semiring.mul_zero, List.zipIdx_nil, List.map_nil, LogUp.sum, List.foldr_nil] + | cons first rest ih => + simp only [horner_cons, List.zipIdx_cons, List.map_cons, LogUp.sum, List.foldr_cons] + have tail := ih (offset + 1) + rw [Semiring.pow_succ] at tail + simp only [LogUp.sum] at tail + grind + +theorem composition_from (point initial : W) (values : List W) : + values.foldl (fun accumulated value => accumulated * point + value) initial = + initial * point ^ values.length + horner point values.reverse := by + induction values generalizing initial with + | nil => simp only [List.foldl_nil, List.length_nil, List.reverse_nil, horner_nil, Semiring.pow_zero]; grind + | cons first rest ih => + simp only [List.foldl_cons, ih, List.length_cons, List.reverse_cons, horner_append, + List.length_reverse, horner_cons, horner_nil, Semiring.pow_succ] + grind + +theorem composition_horner (point : W) (values : List W) : composition point values = horner point values.reverse := by + rw [composition, composition_from, Semiring.zero_mul] + grind + +theorem composition_order (point : W) (values : List W) : + composition point values = + LogUp.sum ((values.reverse.zipIdx).map fun (value, index) => point ^ index * value) := by + rw [composition_horner] + have powers := horner_powers point values.reverse 0 + simpa only [Semiring.pow_zero, Semiring.one_mul] using powers + +theorem composition_append (point : W) (user lookup : List W) : + composition point (user ++ lookup) = + composition point user * point ^ lookup.length + composition point lookup := by + rw [composition, List.foldl_append, composition_from, ← composition_horner] + rfl + +theorem composition_zero (point : W) (values : List W) (zero : ∀ value ∈ values, value = 0) : + composition point values = 0 := by + rw [composition_horner] + suffices h : ∀ values : List W, (∀ value ∈ values, value = 0) → horner point values = 0 from + h values.reverse (by simpa only [List.mem_reverse] using zero) + intro values zero + induction values with + | nil => rfl + | cons first rest ih => + rw [horner_cons, zero first (by simp), ih (fun value member => zero value (by simp [member]))] + grind + +theorem inverse_check (vanishing inverse composition quotient : W) (cancel : vanishing * inverse = 1) : + composition * inverse = quotient ↔ composition = vanishing * quotient := by + constructor + · intro accepted + have multiplied := congrArg (fun value => vanishing * value) accepted + grind + · intro identity + rw [identity] + grind + +end Aiur.NativeAIR.Quotient diff --git a/Ix/Aiur/Proofs/Relayout.lean b/Ix/Aiur/Proofs/Relayout.lean new file mode 100644 index 000000000..9646ca5cb --- /dev/null +++ b/Ix/Aiur/Proofs/Relayout.lean @@ -0,0 +1,346 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Compiler.CallOrder +import Ix.Aiur.Proofs.Metadata +import Ix.Aiur.Proofs.LayoutProjection + +/-! Component selection recomputes continuation column counts. These counts +do not affect reference execution, including errors, early returns, memory, +I/O or fuel. The proof follows the actual stateful layout pass. -/ + +namespace Aiur.Concrete.Bytecode +open Aiur.Bytecode Aiur.Bytecode.Eval + +private def blockCode (block : Block) := + fun (t : Toplevel) fuel st => evalBlock t fuel block st + +private def branchCode (branch : G × Block) := (branch.1, blockCode branch.2) + +private theorem evalMatchArm_congr (t : Toplevel) (fuel : Nat) + (before after : Array (G × Block)) (fallback fallback' : Option Block) + (same : before.map branchCode = after.map branchCode) + (default : ∀ st, evalDefaultBlock t fuel fallback st = + evalDefaultBlock t fuel fallback' st) (scrut : G) (st : EvalState) (i : Nat) : + evalMatchArm t fuel before fallback scrut st i = + evalMatchArm t fuel after fallback' scrut st i := by + have size : before.size = after.size := by + simpa only [Array.size_map] using congrArg Array.size same + rw [evalMatchArm.eq_1 t fuel before, evalMatchArm.eq_1 t fuel after] + by_cases ha : i < before.size + · have hb : i < after.size := by omega + have item : branchCode before[i] = branchCode after[i] := by + have eq := congrArg (fun xs => xs[i]?) same + simpa only [Array.getElem?_map, Array.getElem?_eq_getElem ha, + Array.getElem?_eq_getElem hb, Option.map_some, Option.some.injEq] using eq + have tag : before[i].1 = after[i].1 := + congrArg (fun value => value.1) item + simp only [dif_pos ha, dif_pos hb, tag] + split + · exact congrFun (congrFun (congrFun (congrArg Prod.snd item) t) fuel) st + · exact evalMatchArm_congr t fuel before after fallback fallback' same default scrut st (i + 1) + · have hb : ¬ i < after.size := by omega + simp only [dif_neg ha, dif_neg hb] + exact default st +termination_by before.size - i + +private def branchStep (shared : SharedData) (degrees : Array Nat) + (acc : Array (G × Block) × SharedData) (pair : G × Block) : + LayoutM (Array (G × Block) × SharedData) := do + setSharedData shared + let block ← relayoutBlock pair.2 + let used ← getSharedData + setDegrees degrees + pure (acc.1.push (pair.1, block), acc.2.maximals used) + +private theorem branchFold_code (items : List (G × Block)) + (shared : SharedData) (degrees : Array Nat) + (acc : Array (G × Block) × SharedData) (initial : LayoutMState) + (effect : ∀ pair ∈ items, ∀ state, + blockCode ((relayoutBlock pair.2).run state).1 = blockCode pair.2) : + (((items.foldlM (branchStep shared degrees) acc).run initial).1.1.map branchCode).toList = + (acc.1.map branchCode).toList ++ items.map branchCode := by + induction items generalizing acc initial with + | nil => simp only [List.foldlM_nil, List.map_nil, List.append_nil]; rfl + | cons pair items ih => + rw [List.foldlM_cons] + have first := effect pair List.mem_cons_self + ((setSharedData shared).run initial).2 + have rest := ih ((branchStep shared degrees acc pair).run initial).1 + ((branchStep shared degrees acc pair).run initial).2 + (fun pair member => effect pair (List.mem_cons_of_mem _ member)) + change _ = _ at rest + change (((items.foldlM (branchStep shared degrees) + ((branchStep shared degrees acc pair).run initial).1).run + ((branchStep shared degrees acc pair).run initial).2).1.1.map branchCode).toList = _ + rw [rest] + change ((acc.1.push (pair.1, ((relayoutBlock pair.2).run + ((setSharedData shared).run initial).2).1)).map branchCode).toList ++ _ = _ + simp only [Array.map_push, Array.toList_push, branchCode, first, + List.map_cons, List.append_assoc, List.cons_append, List.nil_append] + +private theorem branchLoop_code (branches : Array (G × Block)) + (shared : SharedData) (degrees : Array Nat) (initial : LayoutMState) + (effect : ∀ pair ∈ branches.toList, ∀ state, + blockCode ((relayoutBlock pair.2).run state).1 = blockCode pair.2) : + ((branches.attach.foldlM (fun acc pair => branchStep shared degrees acc pair.val) + (#[], shared)).run initial).1.1.map branchCode = branches.map branchCode := by + rw [← Array.foldlM_toList, Array.toList_attach, ← List.foldlM_map, + List.attachWith_map_subtype_val] + apply Array.toList_inj.mp + simpa only [Array.map_empty, Array.toList_empty, List.nil_append, Array.toList_map] using + branchFold_code branches.toList shared degrees (#[], shared) initial effect + +private theorem branch_smaller {branches : Array (G × Block)} {pair : G × Block} + (member : pair ∈ branches.toList) : sizeOf pair.2 < sizeOf branches := by + have bound := Array.sizeOf_lt_of_mem (Array.mem_toList_iff.mp member) + cases pair + simp at bound ⊢ + omega + +mutual + +private theorem relayoutCtrl_code (ctrl : Ctrl) (initial : LayoutMState) + (t : Toplevel) (fuel : Nat) (st : EvalState) : + evalCtrl t fuel ((relayoutCtrl ctrl).run initial).1 st = evalCtrl t fuel ctrl st := by + cases ctrl with + | «return» sel outs => rw [relayoutCtrl.eq_def]; rfl + | «yield» sel outs => rw [relayoutCtrl.eq_def]; rfl + | «match» index branches fallback => + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop := branches.attach.foldlM + (fun acc pair => branchStep shared initial.degrees acc pair.val) (#[], shared) + have same := branchLoop_code branches shared initial.degrees initial + (fun pair member state => relayoutBlock_code pair.2 state) + rw [relayoutCtrl.eq_def] + cases fallback with + | none => + change evalCtrl t fuel (.match index (loop.run initial).1.1 none) st = _ + simp only [evalCtrl] + cases readIdx st index with + | error e => rfl + | ok scrut => exact evalMatchArm_congr t fuel _ _ none none same (fun _ => rfl) scrut st 0 + | some block => + let before := ((bumpAuxiliaries (loop.run initial).1.1.size).run + ((setSharedData shared).run (loop.run initial).2).2).2 + change evalCtrl t fuel (.match index (loop.run initial).1.1 + (some ((relayoutBlock block).run before).1)) st = _ + simp only [evalCtrl] + cases readIdx st index with + | error e => rfl + | ok scrut => + apply evalMatchArm_congr t fuel _ _ (some ((relayoutBlock block).run before).1) + (some block) same ?_ scrut st 0 + intro state + simpa only [evalDefaultBlock, blockCode] using + congrFun (congrFun (congrFun (relayoutBlock_code block before) t) fuel) state + | matchContinue index branches fallback size aux slots cont => + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop := branches.attach.foldlM + (fun acc pair => branchStep shared initial.degrees acc pair.val) (#[], shared) + have same := branchLoop_code branches shared initial.degrees initial + (fun pair member state => relayoutBlock_code pair.2 state) + rw [relayoutCtrl.eq_def] + cases fallback with + | none => + change evalCtrl t fuel (.matchContinue index (loop.run initial).1.1 none size _ _ + ((relayoutBlock cont).run _).1) st = _ + simp only [evalCtrl] + cases readIdx st index with + | error e => rfl + | ok scrut => + dsimp only + rw [evalMatchArm_congr t fuel _ _ none none same (fun _ => rfl) scrut st 0] + cases evalMatchArm t fuel branches none scrut st with + | error e => rfl + | ok result => exact congrFun (congrFun (congrFun (relayoutBlock_code cont _) t) fuel) _ + | some block => + let before := ((bumpAuxiliaries (loop.run initial).1.1.size).run + ((setSharedData shared).run (loop.run initial).2).2).2 + have default : ∀ st, evalDefaultBlock t fuel + (some ((relayoutBlock block).run before).1) st = + evalDefaultBlock t fuel (some block) st := fun st => by + simpa only [evalDefaultBlock, blockCode] using congrFun + (congrFun (congrFun (relayoutBlock_code block before) t) fuel) st + change evalCtrl t fuel (.matchContinue index (loop.run initial).1.1 + (some ((relayoutBlock block).run before).1) size _ _ + ((relayoutBlock cont).run _).1) st = _ + simp only [evalCtrl] + cases readIdx st index with + | error e => rfl + | ok scrut => + dsimp only + rw [evalMatchArm_congr t fuel _ _ (some ((relayoutBlock block).run before).1) + (some block) same default scrut st 0] + cases evalMatchArm t fuel branches (some block) scrut st with + | error e => rfl + | ok result => exact congrFun (congrFun (congrFun (relayoutBlock_code cont _) t) fuel) _ +termination_by (sizeOf ctrl, 0) +decreasing_by + all_goals first + | decreasing_tactic + | (have := branch_smaller member; grind) + | grind + +private theorem relayoutBlock_code (block : Block) (initial : LayoutMState) : + blockCode ((relayoutBlock block).run initial).1 = blockCode block := by + funext t fuel st + rw [relayoutBlock.eq_def] + change evalBlock t fuel { ops := block.ops, ctrl := ((relayoutCtrl block.ctrl).run + ((block.ops.forM opLayout).run initial).2).1 } st = evalBlock t fuel block st + simp only [evalBlock] + cases runOps t fuel block.ops st 0 with + | error e => rfl + | ok st' => exact relayoutCtrl_code block.ctrl _ t fuel st' +termination_by (sizeOf block, 1) +decreasing_by + cases block + simp_wf + omega + +end + +/-- Recomputing continuation allocations preserves the complete evaluator result. -/ +theorem relayoutBlock_preserves_execution (block : Block) (initial : LayoutMState) + (t : Toplevel) (fuel : Nat) (st : EvalState) : + evalBlock t fuel ((relayoutBlock block).run initial).1 st = evalBlock t fuel block st := + congrFun (congrFun (congrFun (relayoutBlock_code block initial) t) fuel) st + +private theorem branchFold_context (items : List (G × Block)) + (shared : SharedData) (degrees : Array Nat) + (acc : Array (G × Block) × SharedData) (initial : LayoutMState) + (effect : ∀ pair ∈ items, ∀ state, + ((relayoutBlock pair.2).run state).2.context = + state.context) : + ((items.foldlM (branchStep shared degrees) acc).run initial).2.context = + initial.context := by + induction items generalizing acc initial with + | nil => rfl + | cons pair items ih => + rw [List.foldlM_cons] + have first := effect pair List.mem_cons_self + ((setSharedData shared).run initial).2 + have rest := ih ((branchStep shared degrees acc pair).run initial).1 + ((branchStep shared degrees acc pair).run initial).2 + (fun pair member => effect pair (List.mem_cons_of_mem _ member)) + exact rest.trans first + +private theorem branchLoop_context (branches : Array (G × Block)) + (shared : SharedData) (degrees : Array Nat) (initial : LayoutMState) + (effect : ∀ pair ∈ branches.toList, ∀ state, + ((relayoutBlock pair.2).run state).2.context = + state.context) : + ((branches.attach.foldlM (fun acc pair => branchStep shared degrees acc pair.val) + (#[], shared)).run initial).2.context = initial.context := by + rw [← Array.foldlM_toList, Array.toList_attach, ← List.foldlM_map, + List.attachWith_map_subtype_val] + exact branchFold_context branches.toList shared degrees (#[], shared) initial effect + +mutual + +theorem relayoutCtrl_context (ctrl : Ctrl) (initial : LayoutMState) : + ((relayoutCtrl ctrl).run initial).2.context = + initial.context := by + cases ctrl with + | «return» sel outs => rw [relayoutCtrl.eq_def]; rfl + | «yield» sel outs => rw [relayoutCtrl.eq_def]; rfl + | «match» index branches fallback => + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop := branches.attach.foldlM + (fun acc pair => branchStep shared initial.degrees acc pair.val) (#[], shared) + have fixed := branchLoop_context branches shared initial.degrees initial + (fun pair member state => relayoutBlock_context pair.2 state) + rw [relayoutCtrl.eq_def] + cases fallback with + | none => exact fixed + | some block => + let before := ((bumpAuxiliaries (loop.run initial).1.1.size).run + ((setSharedData shared).run (loop.run initial).2).2).2 + exact (relayoutBlock_context block before).trans fixed + | matchContinue index branches fallback size aux slots cont => + let shared : SharedData := ⟨initial.functionLayout.auxiliaries, initial.functionLayout.lookups⟩ + let loop := branches.attach.foldlM + (fun acc pair => branchStep shared initial.degrees acc pair.val) (#[], shared) + have fixed := branchLoop_context branches shared initial.degrees initial + (fun pair member state => relayoutBlock_context pair.2 state) + rw [relayoutCtrl.eq_def] + cases fallback with + | none => + change ((relayoutBlock cont).run _).2.context = _ + exact (relayoutBlock_context cont _).trans fixed + | some block => + let before := ((bumpAuxiliaries (loop.run initial).1.1.size).run + ((setSharedData shared).run (loop.run initial).2).2).2 + have default := (relayoutBlock_context block before).trans fixed + change ((relayoutBlock cont).run _).2.context = _ + exact (relayoutBlock_context cont _).trans default +termination_by (sizeOf ctrl, 0) +decreasing_by + all_goals first + | decreasing_tactic + | (have := branch_smaller member; grind) + | grind + +theorem relayoutBlock_context (block : Block) (initial : LayoutMState) : + ((relayoutBlock block).run initial).2.context = + initial.context := by + rw [relayoutBlock.eq_def] + exact (relayoutCtrl_context block.ctrl _).trans (opsLayout_context block.ops initial) +termination_by (sizeOf block, 1) +decreasing_by + cases block + simp_wf + omega + +end + +theorem relayoutCtrl_inputSize (ctrl : Ctrl) (initial : LayoutMState) : + ((relayoutCtrl ctrl).run initial).2.functionLayout.inputSize = initial.functionLayout.inputSize := + congrArg Prod.fst (relayoutCtrl_context ctrl initial) + +theorem relayoutBlock_inputSize (block : Block) (initial : LayoutMState) : + ((relayoutBlock block).run initial).2.functionLayout.inputSize = initial.functionLayout.inputSize := + congrArg Prod.fst (relayoutBlock_context block initial) + +theorem relayoutCtrl_callRanks (ctrl : Ctrl) (initial : LayoutMState) : + ((relayoutCtrl ctrl).run initial).2.callRanks = initial.callRanks := + congrArg Prod.snd (relayoutCtrl_context ctrl initial) + +theorem relayoutBlock_callRanks (block : Block) (initial : LayoutMState) : + ((relayoutBlock block).run initial).2.callRanks = initial.callRanks := + congrArg Prod.snd (relayoutBlock_context block initial) + +theorem blockLayout_callRanks (block : Block) (initial : LayoutMState) : + ((blockLayout block).run initial).2.callRanks = initial.callRanks := by + rw [blockLayout_eq_discard_relayout] + exact relayoutBlock_callRanks block initial + +theorem ctrlLayout_callRanks (ctrl : Ctrl) (initial : LayoutMState) : + ((ctrlLayout ctrl).run initial).2.callRanks = initial.callRanks := + relayoutCtrl_callRanks ctrl initial + +end Aiur.Concrete.Bytecode + +namespace Aiur.Bytecode +open Concrete.Bytecode + +/-- The checked component pass preserves instruction behavior and input arity. +Its continuation metadata and other circuit layout fields may change. -/ +theorem Toplevel.withCallComponents_sameCode (top : Toplevel) : + Eval.SameCode top.withCallComponents top := by + unfold Toplevel.withCallComponents + dsimp only + split + · exact ⟨rfl, fun _ _ _ _ _ _ => rfl, fun _ _ _ => rfl⟩ + · constructor + · simp only [Array.size_mapIdx] + · intro i ha hb t fuel st + simp only [Array.getElem_mapIdx] + exact relayoutBlock_preserves_execution _ _ t fuel st + · intro i ha hb + simp only [Array.getElem_mapIdx] + exact relayoutBlock_inputSize _ _ + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/Renaming.lean b/Ix/Aiur/Proofs/Renaming.lean new file mode 100644 index 000000000..ac1117f3d --- /dev/null +++ b/Ix/Aiur/Proofs/Renaming.lean @@ -0,0 +1,284 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Compiler.Dedup +import Ix.Aiur.Semantics.BytecodeEval + +/-! Exact successful-execution equivalence under checked function renaming. +The relation retains memory, I/O and the early-return escape channel. -/ + +namespace Aiur.Bytecode.Eval + +/-- Function renaming preserves the call domain, every rewritten body and +the input arity. It may merge multiple old functions into one target. -/ +structure RenamedCode (a b : Toplevel) (rename : FunIdx → FunIdx) : Prop where + domain : ∀ i, i < a.functions.size ↔ rename i < b.functions.size + body : ∀ i (ha : i < a.functions.size) (hb : rename i < b.functions.size), + rewriteBlock rename a.functions[i].body = b.functions[rename i].body + inputSize : ∀ i (ha : i < a.functions.size) (hb : rename i < b.functions.size), + a.functions[i].layout.inputSize = b.functions[rename i].layout.inputSize + +/-- Errors may contain function indices changed by renaming. Successful +results and the evaluator's early-return channel retain their full values. -/ +def returnObservation : BytecodeError → Option (Array G × EvalState) + | .earlyReturn outs st => some (outs, st) + | _ => none + +def observe (result : Except BytecodeError α) : Except (Option (Array G × EvalState)) α := + result.mapError returnObservation + +theorem observe_ok_iff {result : Except BytecodeError α} {value : α} : + observe result = .ok value ↔ result = .ok value := by + cases result <;> simp [observe, Except.mapError] + +theorem observe_bind {x y : Except BytecodeError α} + (h : observe x = observe y) {f g : α → Except BytecodeError β} + (hf : ∀ value, observe (f value) = observe (g value)) : + observe (match x with | .error e => .error e | .ok value => f value) = + observe (match y with | .error e => .error e | .ok value => g value) := by + cases x <;> cases y <;> simp_all [observe, Except.mapError] + +theorem observe_pairBind {x y : Except BytecodeError (Array G × EvalState)} + (h : observe x = observe y) {f g : Array G → EvalState → Except BytecodeError β} + (hf : ∀ outs st, observe (f outs st) = observe (g outs st)) : + observe (match x with | .error e => .error e | .ok (outs, st) => f outs st) = + observe (match y with | .error e => .error e | .ok (outs, st) => g outs st) := by + cases x <;> cases y <;> simp_all [observe, Except.mapError] + +private def finishCall (st : EvalState) (outputSize : Nat) + (result : Except BytecodeError (Array G × EvalState)) : Except BytecodeError EvalState := + match result with + | .error (.earlyReturn outs innerSt) | .ok (outs, innerSt) => + if outs.size != outputSize then .error .callOutputSizeMismatch + else .ok (appendMap (setIoBuffer { st with memory := innerSt.memory } innerSt.ioBuffer) outs) + | .error e => .error e + +private def finishObservedCall (st : EvalState) (outputSize : Nat) + (result : Except (Option (Array G × EvalState)) (Array G × EvalState)) : + Except (Option (Array G × EvalState)) EvalState := + match result with + | .error (some (outs, innerSt)) | .ok (outs, innerSt) => + if outs.size != outputSize then .error none + else .ok (appendMap (setIoBuffer { st with memory := innerSt.memory } innerSt.ioBuffer) outs) + | .error none => .error none + +private theorem observe_finishCall (st : EvalState) (outputSize : Nat) + (result : Except BytecodeError (Array G × EvalState)) : + observe (finishCall st outputSize result) = + finishObservedCall st outputSize (observe result) := by + cases result with + | ok value => + rcases value with ⟨outs, innerSt⟩ + by_cases h : outs.size != outputSize <;> + simp [finishCall, finishObservedCall, observe, Except.mapError, returnObservation, h] + | error error => + cases error <;> try rfl + case earlyReturn outs innerSt => + by_cases h : outs.size != outputSize <;> + simp [finishCall, finishObservedCall, observe, Except.mapError, returnObservation, h] + +private theorem ops_lt (b : Block) : sizeOf b.ops < sizeOf b := by + cases b; simp; omega + +private theorem ctrl_lt (b : Block) : sizeOf b.ctrl < sizeOf b := by + cases b; simp; omega + +private theorem case_lt (cases : Array (G × Block)) (fallback : Option Block) + (i : Nat) (h : i < cases.size) : + sizeOf cases[i].2 < sizeOf cases + sizeOf fallback := by + have h1 := Array.sizeOf_get cases i h + have h2 : sizeOf cases[i].2 < sizeOf cases[i] := by + cases cases[i]; simp; omega + omega + +mutual + +theorem evalOp_renamed {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (fuel : Nat) (op : Op) (st : EvalState) : + observe (evalOp a fuel op st) = observe (evalOp b fuel (rewriteOp rename op) st) := by + cases op <;> simp only [rewriteOp, evalOp] + all_goals try rfl + case call fi args outputSize unconstrained => + cases hg : readIdxs st args with + | error e => rfl + | ok gs => + simp only [bind, Except.bind] + by_cases ha : fi < a.functions.size + · have hb := (code.domain fi).mp ha + simp only [dif_pos ha, dif_pos hb, code.inputSize fi ha hb] + split + · rfl + · cases fuel with + | zero => rfl + | succ fuel => + change observe (finishCall st outputSize (evalBlock a fuel a.functions[fi].body _)) = + observe (finishCall st outputSize (evalBlock b fuel b.functions[rename fi].body _)) + rw [observe_finishCall, observe_finishCall, + ← code.body fi ha hb, evalBlock_renamed code] + · have hb : ¬ rename fi < b.functions.size := by simpa [← code.domain fi] using ha + simp only [dif_neg ha, dif_neg hb] + rfl +termination_by (fuel, sizeOf op, 0) +decreasing_by all_goals first | decreasing_tactic | omega + +theorem runOps_renamed {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (fuel : Nat) (ops : Array Op) (st : EvalState) (i : Nat) : + observe (runOps a fuel ops st i) = + observe (runOps b fuel (ops.map (rewriteOp rename)) st i) := by + rw [runOps.eq_1 a, runOps.eq_1 b] + simp only [Array.size_map] + by_cases h : i < ops.size + · simp only [dif_pos h, Array.getElem_map] + have related := observe_bind (f := fun st' => runOps a fuel ops st' (i + 1)) + (g := fun st' => runOps b fuel (ops.map (rewriteOp rename)) st' (i + 1)) + (evalOp_renamed code fuel ops[i] st) (fun st' => runOps_renamed code fuel ops st' (i + 1)) + cases hleft : evalOp a fuel ops[i] st <;> + cases hright : evalOp b fuel (rewriteOp rename ops[i]) st <;> + simpa only [hleft, hright] using related + · simp only [dif_neg h] +termination_by (fuel, sizeOf ops, 1 + (ops.size - i)) +decreasing_by all_goals first | decreasing_tactic | omega + +theorem evalBlock_renamed {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (fuel : Nat) (block : Block) (st : EvalState) : + observe (evalBlock a fuel block st) = + observe (evalBlock b fuel (rewriteBlock rename block) st) := by + rw [evalBlock.eq_1 a, evalBlock.eq_1 b] + simp only [rewriteBlock] + have related := observe_bind (f := fun st' => evalCtrl a fuel block.ctrl st') + (g := fun st' => evalCtrl b fuel (rewriteCtrl rename block.ctrl) st') + (runOps_renamed code fuel block.ops st 0) (fun st' => evalCtrl_renamed code fuel block.ctrl st') + cases hleft : runOps a fuel block.ops st 0 <;> + cases hright : runOps b fuel (block.ops.map (rewriteOp rename)) st 0 <;> + simpa only [hleft, hright] using related +termination_by (fuel, sizeOf block, 4) +decreasing_by + all_goals first + | decreasing_tactic + | (apply Prod.Lex.right; apply Prod.Lex.left; exact ops_lt _) + | (apply Prod.Lex.right; apply Prod.Lex.left; exact ctrl_lt _) + | omega + +theorem evalCtrl_renamed {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (fuel : Nat) (ctrl : Ctrl) (st : EvalState) : + observe (evalCtrl a fuel ctrl st) = + observe (evalCtrl b fuel (rewriteCtrl rename ctrl) st) := by + cases ctrl with + | «return» sel outs => simp only [rewriteCtrl, evalCtrl] + | «yield» sel outs => simp only [rewriteCtrl, evalCtrl] + | «match» idx cases fallback => + rw [rewriteCtrl.eq_def] + simp only [evalCtrl] + cases readIdx st idx with + | error e => rfl + | ok scrut => + cases fallback <;> + simpa only [Option.map] using evalMatchArm_renamed code fuel cases _ scrut st 0 + | matchContinue idx cases fallback out aux lookups cont => + rw [rewriteCtrl.eq_def] + simp only [evalCtrl] + cases readIdx st idx with + | error e => rfl + | ok scrut => + cases fallback + all_goals + with_unfolding_all + apply observe_pairBind + (f := fun outs st' => evalBlock a fuel cont { st' with map := st.map ++ outs }) + (g := fun outs st' => evalBlock b fuel (rewriteBlock rename cont) + { st' with map := st.map ++ outs }) + (evalMatchArm_renamed code fuel cases _ scrut st 0) + all_goals intro outs st' + all_goals exact evalBlock_renamed code fuel cont _ +termination_by (fuel, sizeOf ctrl, 3) +decreasing_by all_goals first | decreasing_tactic | omega + +theorem evalMatchArm_renamed {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (fuel : Nat) (cases : Array (G × Block)) + (fallback : Option Block) (scrut : G) (st : EvalState) (i : Nat) : + observe (evalMatchArm a fuel cases fallback scrut st i) = + observe (evalMatchArm b fuel + (cases.attach.map fun pair => (pair.val.1, rewriteBlock rename pair.val.2)) + (fallback.map (rewriteBlock rename)) scrut st i) := by + rw [evalMatchArm.eq_1 a, evalMatchArm.eq_1 b] + simp only [Array.size_map, Array.size_attach] + by_cases h : i < cases.size + · simp only [dif_pos h, Array.getElem_map, Array.getElem_attach] + split + · exact evalBlock_renamed code fuel cases[i].2 st + · exact evalMatchArm_renamed code fuel cases fallback scrut st (i + 1) + · simp only [dif_neg h] + exact evalDefaultBlock_renamed code fuel fallback st +termination_by (fuel, sizeOf cases + sizeOf fallback, 2 + (cases.size - i)) +decreasing_by + all_goals + clean_wf + first + | decreasing_tactic + | (apply Prod.Lex.right; apply Prod.Lex.left; exact case_lt cases fallback i ‹_›) + | (apply Prod.Lex.right; apply Prod.Lex.left + cases cases; simp; omega) + | omega + +theorem evalDefaultBlock_renamed {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (fuel : Nat) (fallback : Option Block) (st : EvalState) : + observe (evalDefaultBlock a fuel fallback st) = + observe (evalDefaultBlock b fuel (fallback.map (rewriteBlock rename)) st) := by + cases fallback with + | none => simp only [Option.map, evalDefaultBlock] + | some block => simpa only [Option.map, evalDefaultBlock] using evalBlock_renamed code fuel block st +termination_by (fuel, sizeOf fallback, 1) +decreasing_by all_goals first | decreasing_tactic | (simp_wf; omega) + +end + +private def finishFunction (result : Except BytecodeError (Array G × EvalState)) : + Except BytecodeError (Array G × IOBuffer) := + match result with + | .error (.earlyReturn outs st) | .ok (outs, st) => .ok (outs, st.ioBuffer) + | .error error => .error error + +private def finishObservedFunction + (result : Except (Option (Array G × EvalState)) (Array G × EvalState)) : + Except (Option (Array G × EvalState)) (Array G × IOBuffer) := + match result with + | .error (some (outs, st)) | .ok (outs, st) => .ok (outs, st.ioBuffer) + | .error none => .error none + +private theorem observe_finishFunction (result : Except BytecodeError (Array G × EvalState)) : + observe (finishFunction result) = finishObservedFunction (observe result) := by + cases result with + | ok value => cases value; rfl + | error error => cases error <;> rfl + +theorem runFunction_renamed {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (function : FunIdx) (args : Array G) (io : IOBuffer) (fuel : Nat) : + observe (runFunction a function args io fuel) = + observe (runFunction b (rename function) args io fuel) := by + rw [runFunction.eq_1 a, runFunction.eq_1 b] + by_cases ha : function < a.functions.size + · have hb := (code.domain function).mp ha + simp only [dif_pos ha, dif_pos hb, code.inputSize function ha hb] + split + · rfl + · change observe (finishFunction (evalBlock a fuel a.functions[function].body _)) = + observe (finishFunction (evalBlock b fuel b.functions[rename function].body _)) + rw [observe_finishFunction, observe_finishFunction, ← code.body function ha hb, + evalBlock_renamed code] + · have hb : ¬ rename function < b.functions.size := by + simpa [← code.domain function] using ha + simp only [dif_neg ha, dif_neg hb] + rfl + +/-- Renaming preserves and reflects every successful result and final I/O +state at the same fuel. Failures may report different function indices. -/ +theorem runFunction_renamed_iff {a b : Toplevel} {rename : FunIdx → FunIdx} + (code : RenamedCode a b rename) (function : FunIdx) (args : Array G) (io : IOBuffer) (fuel : Nat) + (result : Array G × IOBuffer) : + runFunction a function args io fuel = .ok result ↔ + runFunction b (rename function) args io fuel = .ok result := by + rw [← observe_ok_iff, ← observe_ok_iff, runFunction_renamed code] + +end Aiur.Bytecode.Eval diff --git a/Ix/Aiur/Proofs/ReturnGates.lean b/Ix/Aiur/Proofs/ReturnGates.lean new file mode 100644 index 000000000..d9102f296 --- /dev/null +++ b/Ix/Aiur/Proofs/ReturnGates.lean @@ -0,0 +1,214 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.SelectorControl + +/-! +The emitter gates a continuation with its yield sum. Its continuation-link +equation identifies that sum with the continuation block's selector. These +definitions retain the distinction on arbitrary field assignments and prove +that satisfying selector equations identify all return gates with their leaf +selectors. A nonzero provider's combined message then recovers one return. + +Reflection of native argument values and layout remains an obligation. The +branchless single-writer property and terminal-count bound are explicit. +-/ + +namespace Aiur.Bytecode +open Aiur.AIR + +private theorem return_gate_block_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +/-- Return arguments are gated by the selector passed to the emitter. At a +continuation this is the yield sum, equal to the block selector only when +the emitted continuation-link equation is satisfied. -/ +def Ctrl.returnGates (selector : SelIdx → G) (incoming : G) : Ctrl → List G + | .return .. => [incoming] + | .yield .. => [] + | .match _ branches fallback => + (branches.attach.toList.flatMap fun ⟨pair, _⟩ => + pair.2.returnGates selector (pair.2.selectorFlow selector).entry) ++ + (match fallback with + | none => [] + | some block => block.returnGates selector (block.selectorFlow selector).entry) + | .matchContinue _ branches fallback _ _ _ continuation => + (branches.attach.toList.flatMap fun ⟨pair, _⟩ => + pair.2.returnGates selector (pair.2.selectorFlow selector).entry) ++ + (match fallback with + | none => [] + | some block => block.returnGates selector (block.selectorFlow selector).entry) ++ + continuation.returnGates selector + (selectorSum (SelectorFlow.join (branchSelectorFlows selector branches fallback)).yields) +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.returnGates (selector : SelIdx → G) (incoming : G) (block : Block) : List G := + block.ctrl.returnGates selector incoming +termination_by sizeOf block +decreasing_by exact return_gate_block_smaller block + +end + +def branchReturnGates (selector : SelIdx → G) (branches : Array (G × Block)) + (fallback : Option Block) : List G := + branches.toList.flatMap (fun pair => pair.2.returnGates selector (pair.2.selectorFlow selector).entry) ++ + fallback.toList.flatMap (fun block => block.returnGates selector (block.selectorFlow selector).entry) + +private theorem flatMap_attachWith_val {α β : Type} (items : List α) (p : α → Prop) + (h : ∀ item ∈ items, p item) (f : α → List β) : + (items.attachWith p h).flatMap (fun item => f item.val) = items.flatMap f := by + rw [List.flatMap, List.flatMap, List.attachWith_map_val] + +theorem Ctrl.returnGates_match (selector : SelIdx → G) (incoming : G) (index : ValIdx) + (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).returnGates selector incoming = + branchReturnGates selector branches fallback := by + rw [Ctrl.returnGates.eq_def] + simp only [branchReturnGates, Array.toList_attach] + rw [flatMap_attachWith_val _ _ _ (fun pair : G × Block => + pair.2.returnGates selector (pair.2.selectorFlow selector).entry)] + cases fallback <;> simp + +theorem Ctrl.returnGates_matchContinue (selector : SelIdx → G) (incoming : G) (index : ValIdx) + (branches : Array (G × Block)) (fallback : Option Block) + (outputs aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).returnGates selector incoming = + branchReturnGates selector branches fallback ++ continuation.returnGates selector + (selectorSum (SelectorFlow.join (branchSelectorFlows selector branches fallback)).yields) := by + rw [Ctrl.returnGates.eq_def] + simp only [branchReturnGates, Array.toList_attach] + rw [flatMap_attachWith_val _ _ _ (fun pair : G × Block => + pair.2.returnGates selector (pair.2.selectorFlow selector).entry)] + cases fallback <;> simp + +private theorem flatMap_congr_mem {α β : Type} (items : List α) (left right : α → List β) + (equal : ∀ item ∈ items, left item = right item) : items.flatMap left = items.flatMap right := by + rw [List.flatMap, List.flatMap] + exact congrArg List.flatten (List.map_congr_left equal) + +theorem branchReturnGates_reflects (selector : SelIdx → G) (branches : Array (G × Block)) + (fallback : Option Block) + (casesEqual : ∀ pair ∈ branches.toList, + pair.2.returnGates selector (pair.2.selectorFlow selector).entry = + (pair.2.selectorFlow selector).returns) + (fallbackEqual : ∀ block, fallback = some block → + block.returnGates selector (block.selectorFlow selector).entry = + (block.selectorFlow selector).returns) : + branchReturnGates selector branches fallback = + (SelectorFlow.join (branchSelectorFlows selector branches fallback)).returns := by + simp only [branchReturnGates, branchSelectorFlows, SelectorFlow.join, + List.flatMap_append, List.flatMap_map] + congr 1 + · exact flatMap_congr_mem _ _ _ casesEqual + · apply flatMap_congr_mem + intro block member + exact fallbackEqual block (by simpa using member) + +theorem branchSelectorFlows_satisfied (selector : SelIdx → G) (branches : Array (G × Block)) + (fallback : Option Block) + (valid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied) : + (∀ pair ∈ branches.toList, (pair.2.selectorFlow selector).Satisfied) ∧ + (∀ block, fallback = some block → (block.selectorFlow selector).Satisfied) := by + refine ⟨?_, ?_⟩ + · intro pair member + apply SelectorFlow.join_satisfied valid + exact List.mem_append_left _ (List.mem_map.mpr ⟨pair, member, rfl⟩) + · intro block present + apply SelectorFlow.join_satisfied valid + apply List.mem_append_right + rw [present] + exact List.mem_cons_self + +mutual + +theorem Ctrl.returnGates_reflects (selector : SelIdx → G) (incoming : G) (ctrl : Ctrl) + (valid : (ctrl.selectorFlow selector).Satisfied) + (linked : incoming = (ctrl.selectorFlow selector).entry) : + ctrl.returnGates selector incoming = (ctrl.selectorFlow selector).returns := by + cases ctrl with + | «return» index values => + rw [Ctrl.returnGates.eq_def, linked, Ctrl.selectorFlow.eq_def] + rfl + | yield index values => rw [Ctrl.returnGates.eq_def, Ctrl.selectorFlow.eq_def]; rfl + | «match» index branches fallback => + rw [Ctrl.selectorFlow_match] at valid ⊢ + rw [Ctrl.returnGates_match] + obtain ⟨casesValid, fallbackValid⟩ := + branchSelectorFlows_satisfied selector branches fallback (SelectorFlow.guard_satisfied valid) + apply branchReturnGates_reflects + · intro pair member + exact Block.returnGates_reflects selector _ pair.2 (casesValid pair member) rfl + · intro block present + exact Block.returnGates_reflects selector _ block (fallbackValid block present) rfl + | matchContinue index branches fallback outputs aux lookups continuation => + rw [Ctrl.selectorFlow_matchContinue] at valid ⊢ + rw [Ctrl.returnGates_matchContinue] + obtain ⟨branchesValid, contValid, link⟩ := + SelectorFlow.continue_satisfied (SelectorFlow.guard_satisfied valid) + obtain ⟨casesValid, fallbackValid⟩ := branchSelectorFlows_satisfied selector branches fallback branchesValid + change _ ++ _ = _ ++ _ + congr 1 + · apply branchReturnGates_reflects + · intro pair member + exact Block.returnGates_reflects selector _ pair.2 (casesValid pair member) rfl + · intro block present + exact Block.returnGates_reflects selector _ block (fallbackValid block present) rfl + · exact Block.returnGates_reflects selector _ continuation contValid link.symm +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr member); grind) + +theorem Block.returnGates_reflects (selector : SelIdx → G) (incoming : G) (block : Block) + (valid : (block.selectorFlow selector).Satisfied) + (linked : incoming = (block.selectorFlow selector).entry) : + block.returnGates selector incoming = (block.selectorFlow selector).returns := by + rw [Block.returnGates, Block.selectorFlow] at * + exact Ctrl.returnGates_reflects selector incoming block.ctrl valid linked +termination_by sizeOf block +decreasing_by exact return_gate_block_smaller block + +end + +theorem Block.return_message (selector : SelIdx → G) (block : Block) (program : Toplevel) + (shape : block.lookupShapes program none = true) + (valid : (block.selectorFlow selector).Satisfied) + (bounded : (block.selectorFlow selector).returns.length < gSize.toNat) + (multiplicity : G) (nonzero : multiplicity ≠ 0) + (activity : activityConstraint multiplicity (block.selectorFlow selector).entry = 0) + (width : Nat) (branchless : Bool) (parts : List (G × List G)) + (gates : parts.map Prod.fst = block.returnGates selector (block.selectorFlow selector).entry) + (single : branchless = true → parts.length = 1) : + ∃ chosen ∈ parts, chosen.1 = 1 ∧ + padMessage width (slotMessage branchless parts) = padMessage width chosen.2 := by + have reflected := block.returnGates_reflects selector _ valid rfl + rw [reflected] at gates + have empty := block.selectorFlow_yields_empty selector program shape + have conservation := (block.selectorFlow_sound selector valid).conservation + have active := nonzero_multiplicity_selector_one activity nonzero + rw [empty] at conservation + change _ = selectorSum (block.selectorFlow selector).returns + 0 at conservation + rw [G.add_zero, active] at conservation + apply slotMessage_active width branchless single + · intro part member + apply (block.selectorFlow_sound selector valid).returned part.1 + rw [← gates] + exact List.mem_map.mpr ⟨part, member, rfl⟩ + · have lengths := congrArg List.length gates + simp only [List.length_map] at lengths + omega + · rw [gates] + exact conservation.symm + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/RowCounts.lean b/Ix/Aiur/Proofs/RowCounts.lean new file mode 100644 index 000000000..d947d4f2b --- /dev/null +++ b/Ix/Aiur/Proofs/RowCounts.lean @@ -0,0 +1,236 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.RowCounts +import Ix.Aiur.Proofs.CircuitRowExecution + +/-! Control counts bound the selector flow of every field assignment. +The node count also bounds all branch arities and nested continuation joins. +Consumed yields contribute to the leaf count even after leaving the flow. -/ + +namespace Aiur.Bytecode +open Aiur.AIR + +structure ControlCounts.Describes (counts : ControlCounts) (flow : SelectorFlow) : Prop where + returned : flow.returns.length = counts.returns + yielded : flow.yields.length = counts.yields + terminals : counts.returns + counts.yields ≤ counts.leaves + leaves : counts.leaves ≤ counts.nodes + +theorem ControlCounts.Describes.unguard {counts : ControlCounts} {flow : SelectorFlow} + (describes : counts.Describes flow.guard) : counts.Describes flow := + ⟨describes.returned, describes.yielded, describes.terminals, describes.leaves⟩ + +theorem ControlCounts.sum_describes {counts : List ControlCounts} {flows : List SelectorFlow} + (related : List.Forall₂ Describes counts flows) : + (sum counts).Describes (SelectorFlow.join flows) := by + induction related with + | nil => exact ⟨rfl, rfl, Nat.le_refl _, Nat.le_refl _⟩ + | @cons first firstFlow rest restFlows head tail ih => + obtain ⟨hr, hy, ht, hl⟩ := head + obtain ⟨tr, ty, tt, tl⟩ := ih + refine ⟨?_, ?_, ?_, ?_⟩ <;> + dsimp only [sum, SelectorFlow.join] at * <;> + simp only [List.map_cons, List.sum_cons, List.flatMap_cons, List.length_append] at * <;> omega + +theorem ControlCounts.branch_describes {counts : List ControlCounts} {flows : List SelectorFlow} + (related : List.Forall₂ Describes counts flows) : + (branch counts).Describes (SelectorFlow.join flows).guard := by + obtain ⟨returned, yielded, terminals, leaves⟩ := sum_describes related + exact ⟨returned, yielded, terminals, by change (sum counts).leaves ≤ (sum counts).nodes + 1; omega⟩ + +theorem ControlCounts.continue_describes {branches continuation : ControlCounts} + {branchFlow contFlow : SelectorFlow} (first : branches.Describes branchFlow) + (last : continuation.Describes contFlow) : + (branches.continue continuation).Describes (branchFlow.continue contFlow).guard := by + obtain ⟨fr, fy, ft, fl⟩ := first + obtain ⟨lr, ly, lt, ll⟩ := last + refine ⟨?_, ly, ?_, ?_⟩ + · change (branchFlow.returns ++ contFlow.returns).length = _ + rw [List.length_append, fr, lr] + rfl + · change branches.returns + continuation.returns + continuation.yields ≤ branches.leaves + continuation.leaves + omega + · change branches.leaves + continuation.leaves ≤ branches.nodes + continuation.nodes + omega + +theorem ControlCounts.member_nodes_le {items : List ControlCounts} {item : ControlCounts} + (member : item ∈ items) : item.nodes ≤ (sum items).nodes := by + induction items with + | nil => cases member + | cons first rest ih => + rcases List.mem_cons.mp member with equal | member + · subst item + change first.nodes ≤ first.nodes + (sum rest).nodes + omega + · have bounded := ih member + change item.nodes ≤ first.nodes + (sum rest).nodes + omega + +theorem ControlCounts.length_le_nodes {items : List ControlCounts} + (positive : ∀ item ∈ items, 0 < item.nodes) : items.length ≤ (sum items).nodes := by + induction items with + | nil => exact Nat.le_refl _ + | cons first rest ih => + have head := positive first List.mem_cons_self + have tail := ih (fun item member => positive item (List.mem_cons_of_mem _ member)) + change rest.length + 1 ≤ first.nodes + (sum rest).nodes + omega + +theorem branchControlCounts_all {branches : Array (G × Block)} {fallback : Option Block} + (property : ControlCounts → Prop) + (casesValid : ∀ pair ∈ branches.toList, property pair.2.controlCounts) + (fallbackValid : ∀ block, fallback = some block → property block.controlCounts) : + ∀ counts ∈ branchControlCounts branches fallback, property counts := by + intro counts member + rcases List.mem_append.mp member with first | last + · obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp first + subst counts + exact casesValid pair pairMember + · obtain ⟨block, blockMember, equal⟩ := List.mem_map.mp last + subst counts + exact fallbackValid block (by simpa using blockMember) + +theorem branchControlCounts_describes (selector : SelIdx → G) + (branches : Array (G × Block)) (fallback : Option Block) + (casesValid : ∀ pair ∈ branches.toList, pair.2.controlCounts.Describes (pair.2.selectorFlow selector)) + (fallbackValid : ∀ block, fallback = some block → + block.controlCounts.Describes (block.selectorFlow selector)) : + List.Forall₂ ControlCounts.Describes (branchControlCounts branches fallback) + (branchSelectorFlows selector branches fallback) := by + apply forall₂_append + · apply forall₂_map_left + exact forall₂_self_map _ _ _ casesValid + · apply forall₂_map_left + apply forall₂_self_map + intro block member + exact fallbackValid block (by simpa using member) + +theorem branchControlCounts_case_le (branches : Array (G × Block)) (fallback : Option Block) + {pair : G × Block} (member : pair ∈ branches.toList) : + pair.2.controlCounts.nodes ≤ (ControlCounts.sum (branchControlCounts branches fallback)).nodes := + ControlCounts.member_nodes_le (List.mem_append_left _ (List.mem_map.mpr ⟨pair, member, rfl⟩)) + +theorem branchControlCounts_default_le (branches : Array (G × Block)) (fallback : Option Block) + {block : Block} (present : fallback = some block) : + block.controlCounts.nodes ≤ (ControlCounts.sum (branchControlCounts branches fallback)).nodes := by + apply ControlCounts.member_nodes_le + apply List.mem_append_right + rw [present] + exact List.mem_cons_self + +private theorem counts_spec_block_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +theorem Ctrl.controlCounts_spec (selector : SelIdx → G) (ctrl : Ctrl) : + ctrl.controlCounts.Describes (ctrl.selectorFlow selector) ∧ + 0 < ctrl.controlCounts.nodes ∧ + (ctrl.controlCounts.nodes < gSize.toNat → ctrl.rowBounds selector) := by + cases ctrl with + | «return» index values => + rw [Ctrl.controlCounts.eq_def, Ctrl.selectorFlow.eq_def, Ctrl.rowBounds.eq_def] + exact ⟨⟨rfl, rfl, Nat.le_refl _, Nat.le_refl _⟩, Nat.zero_lt_succ 0, fun _ => True.intro⟩ + | yield index values => + rw [Ctrl.controlCounts.eq_def, Ctrl.selectorFlow.eq_def, Ctrl.rowBounds.eq_def] + exact ⟨⟨rfl, rfl, Nat.le_refl _, Nat.le_refl _⟩, Nat.zero_lt_succ 0, fun _ => True.intro⟩ + | «match» index branches fallback => + have casesSpec := fun pair (_ : pair ∈ branches.toList) => Block.controlCounts_spec selector pair.2 + have defaultSpec := fun block (_ : fallback = some block) => Block.controlCounts_spec selector block + have related := branchControlCounts_describes selector branches fallback + (fun pair member => (casesSpec pair member).1) (fun block present => (defaultSpec block present).1) + have positive := branchControlCounts_all (fun counts => 0 < counts.nodes) + (fun pair member => (casesSpec pair member).2.1) (fun block present => (defaultSpec block present).2.1) + have arity : branches.size + fallback.toList.length ≤ + (ControlCounts.sum (branchControlCounts branches fallback)).nodes := by + simpa only [branchControlCounts, List.length_append, List.length_map, Array.length_toList] + using ControlCounts.length_le_nodes positive + rw [Ctrl.controlCounts_match, Ctrl.selectorFlow_match, Ctrl.rowBounds.eq_def] + refine ⟨ControlCounts.branch_describes related, by change 0 < _ + 1; omega, ?_⟩ + intro bounded + change (ControlCounts.sum (branchControlCounts branches fallback)).nodes + 1 < gSize.toNat at bounded + refine ⟨?_, ?_, ?_⟩ + · omega + · intro pair member + apply (casesSpec pair member).2.2 + have le := branchControlCounts_case_le branches fallback member + omega + · cases fallback with + | none => exact True.intro + | some block => + apply (defaultSpec block rfl).2.2 + have le := branchControlCounts_default_le branches (some block) rfl + omega + | matchContinue index branches fallback outputs aux lookups continuation => + have casesSpec := fun pair (_ : pair ∈ branches.toList) => Block.controlCounts_spec selector pair.2 + have defaultSpec := fun block (_ : fallback = some block) => Block.controlCounts_spec selector block + have continued := Block.controlCounts_spec selector continuation + have related := branchControlCounts_describes selector branches fallback + (fun pair member => (casesSpec pair member).1) (fun block present => (defaultSpec block present).1) + have positive := branchControlCounts_all (fun counts => 0 < counts.nodes) + (fun pair member => (casesSpec pair member).2.1) (fun block present => (defaultSpec block present).2.1) + have arity : branches.size + fallback.toList.length ≤ + (ControlCounts.sum (branchControlCounts branches fallback)).nodes := by + simpa only [branchControlCounts, List.length_append, List.length_map, Array.length_toList] + using ControlCounts.length_le_nodes positive + rw [Ctrl.controlCounts_matchContinue, Ctrl.selectorFlow_matchContinue, Ctrl.rowBounds.eq_def] + refine ⟨ControlCounts.continue_describes (ControlCounts.branch_describes related).unguard continued.1, + by change 0 < _ + 1 + _; omega, ?_⟩ + intro bounded + change (ControlCounts.sum (branchControlCounts branches fallback)).nodes + 1 + + continuation.controlCounts.nodes < gSize.toNat at bounded + refine ⟨?_, ?_, ?_, ?_, ?_⟩ + · omega + · obtain ⟨returned, yielded, terminals, leaves⟩ := ControlCounts.sum_describes related + rw [returned, yielded] + omega + · intro pair member + apply (casesSpec pair member).2.2 + have le := branchControlCounts_case_le branches fallback member + omega + · cases fallback with + | none => exact True.intro + | some block => + apply (defaultSpec block rfl).2.2 + have le := branchControlCounts_default_le branches (some block) rfl + omega + · apply continued.2.2 + omega +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr ‹_ ∈ _›); grind) + +theorem Block.controlCounts_spec (selector : SelIdx → G) (block : Block) : + block.controlCounts.Describes (block.selectorFlow selector) ∧ + 0 < block.controlCounts.nodes ∧ + (block.controlCounts.nodes < gSize.toNat → block.rowBounds selector) := by + rw [Block.controlCounts, Block.selectorFlow, Block.rowBounds] + exact Ctrl.controlCounts_spec selector block.ctrl +termination_by sizeOf block +decreasing_by exact counts_spec_block_smaller block + +end + +theorem Block.rowBounds_of_controlCounts (selector : SelIdx → G) (block : Block) + (bounded : block.controlCounts.nodes < gSize.toNat) : block.rowBounds selector := + (block.controlCounts_spec selector).2.2 bounded + +theorem Block.return_bound_of_controlCounts (selector : SelIdx → G) (block : Block) + (bounded : block.controlCounts.nodes < gSize.toNat) : + (block.selectorFlow selector).returns.length < gSize.toNat := by + obtain ⟨returned, _, terminals, leaves⟩ := (block.controlCounts_spec selector).1 + omega + +theorem Block.returns_le_selectors (selector : SelIdx → G) (block : Block) : + (block.selectorFlow selector).returns.length ≤ block.controlCounts.leaves := by + obtain ⟨returned, _, terminals, _⟩ := (block.controlCounts_spec selector).1 + omega + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/SelectorAlgebra.lean b/Ix/Aiur/Proofs/SelectorAlgebra.lean new file mode 100644 index 000000000..c624cdfa6 --- /dev/null +++ b/Ix/Aiur/Proofs/SelectorAlgebra.lean @@ -0,0 +1,78 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ExtensionField + +/-! Polynomial identities underlying the native domain selectors. +The divided-power polynomial is symbolic: native evaluation uses the +checked rational formula away from roots, without enumerating the domain. +-/ + +namespace Aiur.NativeAIR.Domain.Algebra + +open Lean.Grind +attribute [local instance] Semiring.natCast Ring.intCast + +variable {R : Type} [CommRing R] + +theorem power_zero (n : Nat) (positive : 0 < n) : (0 : R) ^ n = 0 := by + have successor : n = (n - 1) + 1 := by omega + rw [successor, Semiring.pow_succ, Semiring.mul_zero] + +theorem power_mul (a : R) (m n : Nat) : a ^ (m * n) = (a ^ m) ^ n := by + induction n with + | zero => simp only [Nat.mul_zero, Semiring.pow_zero] + | succ n ih => rw [Nat.mul_succ, Semiring.pow_add, ih, Semiring.pow_succ] + +theorem power_period (a : R) {period : Nat} (order : a ^ period = 1) (n : Nat) : + a ^ n = a ^ (n % period) := by + conv => lhs; rw [← Nat.mod_add_div n period] + rw [Semiring.pow_add, power_mul, order, Semiring.one_pow, Semiring.mul_one] + +theorem power_inverse (a inverse : R) (cancel : a * inverse = 1) (n : Nat) : + a ^ n * inverse ^ n = 1 := by + rw [← CommSemiring.mul_pow, cancel, Semiring.one_pow] + +theorem predecessor_inverse (a inverse : R) {n : Nat} (positive : 0 < n) + (order : a ^ n = 1) (cancel : a * inverse = 1) : a ^ (n - 1) = inverse := by + have successor : n = (n - 1) + 1 := by omega + rw [successor, Semiring.pow_succ] at order + have multiplied := congrArg (fun x => x * inverse) order + grind + +/-- `sum (x^(n-1-j) * a^j)`, kept out of runtime initialization. -/ +noncomputable def dividedPowers (x a : R) : Nat → R + | 0 => 0 + | n + 1 => x ^ n + a * dividedPowers x a n + +theorem dividedPowers_factor (x a : R) (n : Nat) : + (x - a) * dividedPowers x a n = x ^ n - a ^ n := by + induction n with + | zero => simp only [dividedPowers, Semiring.pow_zero]; grind + | succ n ih => rw [dividedPowers, Semiring.pow_succ, Semiring.pow_succ]; grind + +theorem dividedPowers_diagonal (a : R) (n : Nat) : + dividedPowers a a n = (n : R) * a ^ (n - 1) := by + induction n with + | zero => simp only [dividedPowers, Semiring.natCast_zero, Semiring.zero_mul] + | succ n ih => + rw [dividedPowers, ih, Semiring.natCast_succ] + cases n with + | zero => simp only [Nat.zero_sub, Nat.add_sub_cancel, Semiring.pow_zero, + Semiring.natCast_zero]; grind + | succ n => simp only [Nat.add_sub_cancel, Semiring.pow_succ]; grind + +theorem root_dividedPowers (x a : R) {n : Nat} (root : a ^ n = 1) : + (x - a) * dividedPowers x a n = x ^ n - 1 := by + rw [dividedPowers_factor, root] + +theorem dividedPowers_off_root (x a inverse : R) {n : Nat} + (root : a ^ n = 1) (cancel : (x - a) * inverse = 1) : + (x ^ n - 1) * inverse = dividedPowers x a n := by + have factor := root_dividedPowers x a root + have multiplied := congrArg (fun z => z * inverse) factor + grind + +end Aiur.NativeAIR.Domain.Algebra diff --git a/Ix/Aiur/Proofs/SelectorControl.lean b/Ix/Aiur/Proofs/SelectorControl.lean new file mode 100644 index 000000000..320ee7959 --- /dev/null +++ b/Ix/Aiur/Proofs/SelectorControl.lean @@ -0,0 +1,377 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.SelectorMessages +import Ix.Aiur.Proofs.LookupShapes + +/-! +Conservation and exclusivity for the selector portion of native control +constraints, computed over the actual bytecode tree. A continuation consumes +only its branches' escaping yields; early returns remain function returns. +The existing shape validator excludes yields escaping an entire function. + +Native-expression reflection, value-index and layout correctness, branch +matching and operation extraction remain separate obligations. The terminal +count bound is explicit; this module does not assume it follows from syntax. +-/ + +namespace Aiur.AIR + +/-- Selector-only projection of the native control emitter. `yields` lists +only yields escaping this block to its nearest enclosing continuation. -/ +structure SelectorFlow where + entry : G + returns : List G + yields : List G + equations : List G + deriving Repr + +def SelectorFlow.guard (flow : SelectorFlow) : SelectorFlow := + { flow with equations := oneSubBooleanConstraint flow.entry :: flow.equations } + +def SelectorFlow.join (flows : List SelectorFlow) : SelectorFlow := + ⟨selectorSum (flows.map (·.entry)), flows.flatMap (·.returns), + flows.flatMap (·.yields), flows.flatMap (·.equations)⟩ + +def SelectorFlow.continue (branches continuation : SelectorFlow) : SelectorFlow := + ⟨branches.entry, branches.returns ++ continuation.returns, continuation.yields, + branches.equations ++ + (continuation.entry - selectorSum branches.yields) :: continuation.equations⟩ + +def SelectorFlow.Satisfied (flow : SelectorFlow) : Prop := + ∀ equation ∈ flow.equations, equation = 0 + +structure SelectorFlow.Sound (flow : SelectorFlow) : Prop where + conservation : flow.entry = selectorSum flow.returns + selectorSum flow.yields + returned : ∀ value ∈ flow.returns, booleanConstraint value = 0 + yielded : ∀ value ∈ flow.yields, booleanConstraint value = 0 + +theorem SelectorFlow.guard_sound {flow : SelectorFlow} (sound : flow.Sound) : flow.guard.Sound := + ⟨sound.conservation, sound.returned, sound.yielded⟩ + +theorem SelectorFlow.guard_satisfied {flow : SelectorFlow} (valid : flow.guard.Satisfied) : + flow.Satisfied := fun equation member => valid equation (List.mem_cons_of_mem _ member) + +theorem SelectorFlow.guard_boolean {flow : SelectorFlow} (valid : flow.guard.Satisfied) : + booleanConstraint flow.entry = 0 := by + have boolean := G.boolean_of_one_sub_constraint (valid _ List.mem_cons_self) + rcases boolean with zero | one + · rw [zero]; rfl + · rw [one]; rfl + +theorem SelectorFlow.join_satisfied {flows : List SelectorFlow} (valid : (join flows).Satisfied) : + ∀ flow ∈ flows, flow.Satisfied := by + intro flow member equation equationMember + exact valid equation (List.mem_flatMap.mpr ⟨flow, member, equationMember⟩) + +theorem SelectorFlow.continue_satisfied {branches continuation : SelectorFlow} + (valid : (branches.continue continuation).Satisfied) : + branches.Satisfied ∧ continuation.Satisfied ∧ + continuation.entry = selectorSum branches.yields := by + refine ⟨?_, ?_, ?_⟩ + · exact fun equation member => valid _ (List.mem_append_left _ member) + · exact fun equation member => + valid _ (List.mem_append_right _ (List.mem_cons_of_mem _ member)) + · exact (G.sub_eq_zero_iff _ _).mp + (valid _ (List.mem_append_right _ List.mem_cons_self)) + +theorem SelectorFlow.join_sound {flows : List SelectorFlow} + (sound : ∀ flow ∈ flows, flow.Sound) : (join flows).Sound := by + induction flows with + | nil => exact ⟨rfl, by simp [join], by simp [join]⟩ + | cons flow flows ih => + have head := sound flow List.mem_cons_self + have tail := ih (fun flow member => sound flow (List.mem_cons_of_mem _ member)) + have tailEq := tail.conservation + dsimp only [join] at tailEq + refine ⟨?_, ?_, ?_⟩ + · change selectorSum (flow.entry :: flows.map (·.entry)) = + selectorSum (flow.returns ++ flows.flatMap (·.returns)) + + selectorSum (flow.yields ++ flows.flatMap (·.yields)) + rw [selectorSum_cons, selectorSum_append, selectorSum_append, + head.conservation, tailEq] + simp only [G.add_assoc] + apply congrArg (selectorSum flow.returns + ·) + rw [← G.add_assoc, G.add_comm (selectorSum flow.yields) + (selectorSum (flows.flatMap (·.returns))), G.add_assoc] + · intro value member + change value ∈ flow.returns ++ flows.flatMap (·.returns) at member + rcases List.mem_append.mp member with first | last + · exact head.returned _ first + · exact tail.returned _ last + · intro value member + change value ∈ flow.yields ++ flows.flatMap (·.yields) at member + rcases List.mem_append.mp member with first | last + · exact head.yielded _ first + · exact tail.yielded _ last + +theorem SelectorFlow.continue_sound {branches continuation : SelectorFlow} + (first : branches.Sound) (last : continuation.Sound) + (link : continuation.entry = selectorSum branches.yields) : + (branches.continue continuation).Sound := by + refine ⟨?_, ?_, last.yielded⟩ + · change branches.entry = selectorSum (branches.returns ++ continuation.returns) + + selectorSum continuation.yields + rw [selectorSum_append, G.add_assoc, ← last.conservation, link, ← first.conservation] + · intro value member + rcases List.mem_append.mp member with firstMember | lastMember + · exact first.returned _ firstMember + · exact last.returned _ lastMember + +theorem SelectorFlow.Sound.terminal_boolean {flow : SelectorFlow} (sound : flow.Sound) : + ∀ value ∈ flow.returns ++ flow.yields, booleanConstraint value = 0 := by + intro value member + rcases List.mem_append.mp member with returned | yielded + · exact sound.returned value returned + · exact sound.yielded value yielded + +theorem SelectorFlow.Sound.active_terminal {flow : SelectorFlow} (sound : flow.Sound) + (bounded : flow.returns.length + flow.yields.length < gSize.toNat) + (active : flow.entry = 1) : + ∃ before after, flow.returns ++ flow.yields = before ++ 1 :: after ∧ + ∀ value ∈ before ++ after, value = 0 := by + apply selectorSum_active_split sound.terminal_boolean + (by simpa only [List.length_append] using bounded) + rw [selectorSum_append, ← sound.conservation, active] + +theorem SelectorFlow.Sound.inactive_terminal {flow : SelectorFlow} (sound : flow.Sound) + (bounded : flow.returns.length + flow.yields.length < gSize.toNat) + (inactive : flow.entry = 0) : + ∀ value ∈ flow.returns ++ flow.yields, value = 0 := by + apply selectorSum_inactive sound.terminal_boolean + (by simpa only [List.length_append] using bounded) + rw [selectorSum_append, ← sound.conservation, inactive] + +theorem SelectorFlow.Sound.return_stops_continuation {flow : SelectorFlow} (sound : flow.Sound) + (bounded : flow.returns.length + flow.yields.length < gSize.toNat) + (active : flow.entry = 1) (returned : (1 : G) ∈ flow.returns) : + selectorSum flow.yields = 0 := by + have count := selectorSum_active_count sound.terminal_boolean + (by simpa only [List.length_append] using bounded) + (show selectorSum (flow.returns ++ flow.yields) = 1 by + rw [selectorSum_append, ← sound.conservation, active]) + have positive := List.count_pos_iff.mpr returned + rw [List.count_append] at count + have noYields : flow.yields.count 1 = 0 := by omega + rw [selectorSum_eq_count _ (fun value member => + G.boolean_of_constraint (sound.yielded value member)), noYields] + rfl + +theorem SelectorFlow.Sound.yield_starts_continuation {flow : SelectorFlow} (sound : flow.Sound) + (bounded : flow.returns.length + flow.yields.length < gSize.toNat) + (active : flow.entry = 1) (yielded : (1 : G) ∈ flow.yields) : + selectorSum flow.yields = 1 := by + have count := selectorSum_active_count sound.terminal_boolean + (by simpa only [List.length_append] using bounded) + (show selectorSum (flow.returns ++ flow.yields) = 1 by + rw [selectorSum_append, ← sound.conservation, active]) + have positive := List.count_pos_iff.mpr yielded + rw [List.count_append] at count + have oneYield : flow.yields.count 1 = 1 := by omega + rw [selectorSum_eq_count _ (fun value member => + G.boolean_of_constraint (sound.yielded value member)), oneYield] + rfl + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +private theorem selector_block_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def Ctrl.selectorFlow (selector : SelIdx → G) : Ctrl → SelectorFlow + | .return index _ => (⟨selector index, [selector index], [], []⟩ : SelectorFlow).guard + | .yield index _ => (⟨selector index, [], [selector index], []⟩ : SelectorFlow).guard + | .match _ branches fallback => + (SelectorFlow.join ( + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.selectorFlow selector) ++ + (match fallback with | none => [] | some block => [block.selectorFlow selector]))).guard + | .matchContinue _ branches fallback _ _ _ continuation => + ((SelectorFlow.join ( + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.selectorFlow selector) ++ + (match fallback with | none => [] | some block => [block.selectorFlow selector]))).continue + (continuation.selectorFlow selector)).guard +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.selectorFlow (selector : SelIdx → G) (block : Block) : SelectorFlow := + block.ctrl.selectorFlow selector +termination_by sizeOf block +decreasing_by exact selector_block_smaller block + +end + +def branchSelectorFlows (selector : SelIdx → G) (branches : Array (G × Block)) + (fallback : Option Block) : List SelectorFlow := + branches.toList.map (fun pair => pair.2.selectorFlow selector) ++ + fallback.toList.map (fun block => block.selectorFlow selector) + +theorem Ctrl.selectorFlow_match (selector : SelIdx → G) (index : ValIdx) + (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).selectorFlow selector = + (SelectorFlow.join (branchSelectorFlows selector branches fallback)).guard := by + rw [Ctrl.selectorFlow.eq_def] + simp only [branchSelectorFlows, Array.toList_attach] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.selectorFlow selector)] + cases fallback <;> rfl + +theorem Ctrl.selectorFlow_matchContinue (selector : SelIdx → G) (index : ValIdx) + (branches : Array (G × Block)) (fallback : Option Block) + (outputs aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).selectorFlow selector = + ((SelectorFlow.join (branchSelectorFlows selector branches fallback)).continue + (continuation.selectorFlow selector)).guard := by + rw [Ctrl.selectorFlow.eq_def] + simp only [branchSelectorFlows, Array.toList_attach] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.selectorFlow selector)] + cases fallback <;> rfl + +theorem branchSelectorFlows_sound (selector : SelIdx → G) (branches : Array (G × Block)) + (fallback : Option Block) + (valid : (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Satisfied) + (casesSound : ∀ pair ∈ branches.toList, + (pair.2.selectorFlow selector).Satisfied → (pair.2.selectorFlow selector).Sound) + (fallbackSound : ∀ block, fallback = some block → + (block.selectorFlow selector).Satisfied → (block.selectorFlow selector).Sound) : + (SelectorFlow.join (branchSelectorFlows selector branches fallback)).Sound := by + apply SelectorFlow.join_sound + intro flow member + have flowValid := SelectorFlow.join_satisfied valid flow member + rcases List.mem_append.mp member with caseMember | defaultMember + · obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp caseMember + subst flow + exact casesSound pair pairMember flowValid + · obtain ⟨block, blockMember, equal⟩ := List.mem_map.mp defaultMember + subst flow + exact fallbackSound block (by simpa using blockMember) flowValid + +mutual + +theorem Ctrl.selectorFlow_sound (selector : SelIdx → G) (ctrl : Ctrl) + (valid : (ctrl.selectorFlow selector).Satisfied) : (ctrl.selectorFlow selector).Sound := by + cases ctrl with + | «return» index values => + rw [Ctrl.selectorFlow.eq_def] at valid ⊢ + have boolean := SelectorFlow.guard_boolean valid + exact ⟨by simp only [SelectorFlow.guard, + selectorSum, List.foldl_nil, List.foldl_cons, G.add_zero, G.zero_add], + fun value member => (List.mem_singleton.mp member).symm ▸ boolean, + by simp [SelectorFlow.guard]⟩ + | yield index values => + rw [Ctrl.selectorFlow.eq_def] at valid ⊢ + have boolean := SelectorFlow.guard_boolean valid + exact ⟨by simp only [SelectorFlow.guard, + selectorSum, List.foldl_nil, List.foldl_cons, G.zero_add], + by simp [SelectorFlow.guard], + fun value member => (List.mem_singleton.mp member).symm ▸ boolean⟩ + | «match» index branches fallback => + rw [Ctrl.selectorFlow_match] at valid ⊢ + apply SelectorFlow.guard_sound + apply branchSelectorFlows_sound selector branches fallback (SelectorFlow.guard_satisfied valid) + · intro pair member satisfied + exact Block.selectorFlow_sound selector pair.2 satisfied + · intro block present satisfied + exact Block.selectorFlow_sound selector block satisfied + | matchContinue index branches fallback outputs aux lookups continuation => + rw [Ctrl.selectorFlow_matchContinue] at valid ⊢ + obtain ⟨branchesValid, continuationValid, link⟩ := + SelectorFlow.continue_satisfied (SelectorFlow.guard_satisfied valid) + apply SelectorFlow.guard_sound + apply SelectorFlow.continue_sound _ (Block.selectorFlow_sound selector continuation continuationValid) link + apply branchSelectorFlows_sound selector branches fallback branchesValid + · intro pair member satisfied + exact Block.selectorFlow_sound selector pair.2 satisfied + · intro block present satisfied + exact Block.selectorFlow_sound selector block satisfied +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr ‹_ ∈ _›); grind) + +theorem Block.selectorFlow_sound (selector : SelIdx → G) (block : Block) + (valid : (block.selectorFlow selector).Satisfied) : (block.selectorFlow selector).Sound := by + rw [Block.selectorFlow] at valid ⊢ + exact Ctrl.selectorFlow_sound selector block.ctrl valid +termination_by sizeOf block +decreasing_by exact selector_block_smaller block + +end + +mutual + +theorem Ctrl.selectorFlow_yields_empty (selector : SelIdx → G) (ctrl : Ctrl) + (program : Toplevel) (valid : ctrl.lookupShapes program none = true) : + (ctrl.selectorFlow selector).yields = [] := by + cases ctrl with + | «return» index values => rw [Ctrl.selectorFlow.eq_def]; rfl + | yield index values => simp only [Ctrl.lookupShapes, reduceCtorEq, beq_iff_eq] at valid + | «match» index branches fallback => + obtain ⟨casesValid, fallbackValid⟩ := (lookupShapes_match _ _ _ _ _).mp valid + rw [Ctrl.selectorFlow_match] + change (branchSelectorFlows selector branches fallback).flatMap (·.yields) = [] + apply List.flatMap_eq_nil_iff.mpr + intro flow member + rcases List.mem_append.mp member with caseMember | defaultMember + · obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp caseMember + subst flow + exact Block.selectorFlow_yields_empty selector pair.2 program (casesValid pair pairMember) + · obtain ⟨block, blockMember, equal⟩ := List.mem_map.mp defaultMember + subst flow + have present : fallback = some block := by simpa using blockMember + exact Block.selectorFlow_yields_empty selector block program (fallbackValid block present) + | matchContinue index branches fallback outputs aux lookups continuation => + obtain ⟨_, _, contValid⟩ := (lookupShapes_matchContinue _ _ _ _ _ _ _ _ _).mp valid + rw [Ctrl.selectorFlow_matchContinue] + exact Block.selectorFlow_yields_empty selector continuation program contValid +termination_by sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem (Array.mem_def.mpr pairMember); grind) + +theorem Block.selectorFlow_yields_empty (selector : SelIdx → G) (block : Block) + (program : Toplevel) (valid : block.lookupShapes program none = true) : + (block.selectorFlow selector).yields = [] := by + rw [Block.selectorFlow] + rw [Block.lookupShapes, Bool.and_eq_true] at valid + exact Ctrl.selectorFlow_yields_empty selector block.ctrl program valid.2 +termination_by sizeOf block +decreasing_by exact selector_block_smaller block + +end + +theorem Block.selectorFlow_active_return (selector : SelIdx → G) (block : Block) + (program : Toplevel) (shape : block.lookupShapes program none = true) + (valid : (block.selectorFlow selector).Satisfied) + (bounded : (block.selectorFlow selector).returns.length < gSize.toNat) + (active : (block.selectorFlow selector).entry = 1) : + ∃ before after, (block.selectorFlow selector).returns = before ++ 1 :: after ∧ + ∀ value ∈ before ++ after, value = 0 := by + have empty := block.selectorFlow_yields_empty selector program shape + have sound := block.selectorFlow_sound selector valid + have result := sound.active_terminal (by simpa only [empty, List.length_nil, Nat.add_zero] using bounded) active + simpa only [empty, List.append_nil] using result + +theorem Block.selectorFlow_provider_return (selector : SelIdx → G) (block : Block) + (program : Toplevel) (shape : block.lookupShapes program none = true) + (valid : (block.selectorFlow selector).Satisfied) + (bounded : (block.selectorFlow selector).returns.length < gSize.toNat) + (multiplicity : G) (nonzero : multiplicity ≠ 0) + (activity : activityConstraint multiplicity (block.selectorFlow selector).entry = 0) : + ∃ before after, (block.selectorFlow selector).returns = before ++ 1 :: after ∧ + ∀ value ∈ before ++ after, value = 0 := + block.selectorFlow_active_return selector program shape valid bounded + (nonzero_multiplicity_selector_one activity nonzero) + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/SelectorMessages.lean b/Ix/Aiur/Proofs/SelectorMessages.lean new file mode 100644 index 000000000..0a5efe53e --- /dev/null +++ b/Ix/Aiur/Proofs/SelectorMessages.lean @@ -0,0 +1,217 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LookupMessages +import Ix.Aiur.Proofs.LocalConstraints + +/-! +Selector-weighted messages in the native shared lookup slots and continuation +merges. Adding variable-length messages retains the longer tail; zero padding +recovers the uniquely selected message without a common raw-length premise. + +The field-characteristic bound, selector equations, layout's single-writer +property and continuation parent activity remain explicit. These lemmas do +not by themselves reflect the Rust emitter or extract its satisfying rows. +-/ + +namespace Aiur.AIR + +/-- The native argument combiner adds overlapping fields and retains the +longer tail, so messages of different lengths share zero-padded slots. -/ +def addMessages : List G → List G → List G + | [], right => right + | left, [] => left + | x :: left, y :: right => (x + y) :: addMessages left right + +def scaleMessage (selector : G) (message : List G) : List G := + message.map (selector * ·) + +def weightedMessage (parts : List (G × List G)) : List G := + parts.foldl (fun combined part => addMessages combined (scaleMessage part.1 part.2)) [] + +theorem addMessages_read (left right : List G) (i : Nat) : + (addMessages left right)[i]?.getD 0 = left[i]?.getD 0 + right[i]?.getD 0 := by + induction left generalizing right i with + | nil => simp only [addMessages, List.getElem?_nil, Option.getD_none, G.zero_add] + | cons value left ih => + cases right with + | nil => simp only [addMessages, List.getElem?_nil, Option.getD_none, G.add_zero] + | cons other right => + cases i with + | zero => rfl + | succ i => exact ih right i + +theorem addMessages_length (left right : List G) : + (addMessages left right).length = max left.length right.length := by + induction left generalizing right with + | nil => simp only [addMessages, List.length_nil, Nat.zero_max] + | cons value left ih => + cases right with + | nil => simp only [addMessages, List.length_nil, Nat.max_zero] + | cons other right => simp only [addMessages, List.length_cons, ih, Nat.add_max_add_right] + +theorem scaleMessage_read (selector : G) (message : List G) (i : Nat) : + (scaleMessage selector message)[i]?.getD 0 = selector * message[i]?.getD 0 := by + induction message generalizing i with + | nil => simp only [scaleMessage, List.map_nil, List.getElem?_nil, Option.getD_none, G.mul_zero] + | cons value message ih => + cases i with + | zero => rfl + | succ i => exact ih i + +theorem weightedMessage_fold_read (parts : List (G × List G)) (start : List G) (i : Nat) : + (parts.foldl (fun combined part => addMessages combined (scaleMessage part.1 part.2)) start)[i]?.getD 0 = + (parts.map fun part => part.1 * part.2[i]?.getD 0).foldl (· + ·) (start[i]?.getD 0) := by + induction parts generalizing start with + | nil => rfl + | cons part parts ih => + simp only [List.foldl_cons, List.map_cons, ih, addMessages_read, scaleMessage_read] + +theorem weightedMessage_read (parts : List (G × List G)) (i : Nat) : + (weightedMessage parts)[i]?.getD 0 = selectorSum (parts.map fun part => part.1 * part.2[i]?.getD 0) := + weightedMessage_fold_read parts [] i + +theorem selectorSum_append (left right : List G) : + selectorSum (left ++ right) = selectorSum left + selectorSum right := by + change (left ++ right).foldl (· + ·) 0 = left.foldl (· + ·) 0 + selectorSum right + rw [List.foldl_append, foldl_add_eq] + +theorem weighted_value_zero {parts : List (G × List G)} + (zero : ∀ part ∈ parts, part.1 = 0) (i : Nat) : + selectorSum (parts.map fun part => part.1 * part.2[i]?.getD 0) = 0 := by + induction parts with + | nil => rfl + | cons part parts ih => + have tail := ih (fun p member => zero p (List.mem_cons_of_mem part member)) + simp only [List.map_cons, selectorSum_cons, zero part List.mem_cons_self, + G.mul_comm 0, G.mul_zero, G.zero_add, tail] + +theorem weightedMessage_split (width : Nat) (before after : List (G × List G)) (chosen : G × List G) + (active : chosen.1 = 1) (zero : ∀ part ∈ before ++ after, part.1 = 0) : + padMessage width (weightedMessage (before ++ chosen :: after)) = padMessage width chosen.2 := by + apply congrArg List.ofFn + funext i + have beforeZero := weighted_value_zero (fun p member => zero p (List.mem_append_left _ member)) i.val + have afterZero := weighted_value_zero (fun p member => zero p (List.mem_append_right _ member)) i.val + change (weightedMessage (before ++ chosen :: after))[i.val]?.getD 0 = chosen.2[i.val]?.getD 0 + rw [weightedMessage_read, List.map_append, selectorSum_append, beforeZero, G.zero_add, + List.map_cons, selectorSum_cons, afterZero, G.add_zero, active, G.mul_comm, G.mul_one] + +theorem selector_parts_active_split {parts : List (G × List G)} + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) : + ∃ before chosen after, parts = before ++ chosen :: after ∧ chosen.1 = 1 ∧ + ∀ part ∈ before ++ after, part.1 = 0 := by + obtain ⟨before, after, split, zero⟩ := selectorSum_active_split + (fun value member => by + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst value + exact individual part partMember) + (by simpa only [List.length_map] using bounded) active + obtain ⟨first, rest, partsEq, firstEq, restEq⟩ := List.map_eq_append_iff.mp split + obtain ⟨chosen, last, tailEq, activeChosen, lastEq⟩ := List.map_eq_cons_iff.mp restEq + refine ⟨first, chosen, last, by rw [partsEq, tailEq], activeChosen, ?_⟩ + intro part member + apply zero part.1 + rcases List.mem_append.mp member with firstMember | lastMember + · apply List.mem_append_left + rw [← firstEq] + exact List.mem_map.mpr ⟨part, firstMember, rfl⟩ + · apply List.mem_append_right + rw [← lastEq] + exact List.mem_map.mpr ⟨part, lastMember, rfl⟩ + +/-- A shared slot contains exactly the selected branch's padded message. +Inactive branches may have different lengths and arbitrary field values. -/ +theorem weightedMessage_active (width : Nat) {parts : List (G × List G)} + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) : + ∃ chosen ∈ parts, chosen.1 = 1 ∧ + padMessage width (weightedMessage parts) = padMessage width chosen.2 := by + obtain ⟨before, chosen, after, partsEq, activeChosen, zero⟩ := + selector_parts_active_split individual bounded active + refine ⟨chosen, ?_, activeChosen, ?_⟩ + · rw [partsEq] + exact List.mem_append_right _ List.mem_cons_self + · rw [partsEq] + exact weightedMessage_split width before after chosen activeChosen zero + +theorem weightedMessage_inactive (width : Nat) {parts : List (G × List G)} + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (inactive : selectorSum (parts.map Prod.fst) = 0) : + padMessage width (weightedMessage parts) = padMessage width [] := by + have zero := selectorSum_inactive + (fun value member => by + obtain ⟨part, partMember, equal⟩ := List.mem_map.mp member + subst value + exact individual part partMember) + (by simpa only [List.length_map] using bounded) inactive + apply congrArg List.ofFn + funext i + change (weightedMessage parts)[i.val]?.getD 0 = 0 + rw [weightedMessage_read] + exact weighted_value_zero (fun part member => zero _ (List.mem_map.mpr ⟨part, member, rfl⟩)) i.val + +/-- Native lookup gating omits the selector product for a slot known to +have just one writer. Multiplicity still determines whether it is used. -/ +def gateMessage (branchless : Bool) (selector : G) (message : List G) : List G := + if branchless then message else scaleMessage selector message + +def slotMessage (branchless : Bool) (parts : List (G × List G)) : List G := + parts.foldl (fun combined part => addMessages combined (gateMessage branchless part.1 part.2)) [] + +theorem gateMessage_active (branchless : Bool) {selector : G} (message : List G) + (active : selector = 1) : gateMessage branchless selector message = message := by + cases branchless <;> simp [gateMessage, scaleMessage, active, G.mul_comm, G.mul_one] + +/-- The branchless optimization is sound on an active slot when its layout +actually gives it one writer. That layout property is an explicit premise. -/ +theorem slotMessage_active (width : Nat) (branchless : Bool) {parts : List (G × List G)} + (single : branchless = true → parts.length = 1) + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) : + ∃ chosen ∈ parts, chosen.1 = 1 ∧ + padMessage width (slotMessage branchless parts) = padMessage width chosen.2 := by + cases branchless with + | false => exact weightedMessage_active width individual bounded active + | true => + obtain ⟨part, equal⟩ := List.length_eq_one_iff.mp (single rfl) + subst parts + have selected : part.1 = 1 := by + simpa only [List.map_cons, List.map_nil, selectorSum_cons, + selectorSum, List.foldl_nil, List.foldl_cons, G.zero_add, G.add_zero] using active + exact ⟨part, List.mem_cons_self, selected, rfl⟩ + +/-- A continuation's active merge columns equal the values of its unique +active yield. The caller must establish that the parent is active and that +the native continuation-link equation makes the yield sum one. -/ +theorem continuation_merge {parent : G} {parts : List (G × List G)} {merged : List G} + (parentActive : parent = 1) + (individual : ∀ part ∈ parts, booleanConstraint part.1 = 0) + (bounded : parts.length < gSize.toNat) + (active : selectorSum (parts.map Prod.fst) = 1) + (sizes : ∀ part ∈ parts, part.2.length = merged.length) + (equations : ∀ i, i < merged.length → + parent * (merged[i]?.getD 0 - + selectorSum (parts.map fun part => part.1 * part.2[i]?.getD 0)) = 0) : + ∃ chosen ∈ parts, chosen.1 = 1 ∧ merged = chosen.2 := by + obtain ⟨chosen, member, selected, message⟩ := + weightedMessage_active merged.length individual bounded active + refine ⟨chosen, member, selected, ?_⟩ + apply padMessage_injective_of_length (Nat.le_refl _) (sizes chosen member).symm + apply Eq.trans _ message + apply congrArg List.ofFn + funext i + change merged[i.val]?.getD 0 = (weightedMessage parts)[i.val]?.getD 0 + rw [weightedMessage_read] + have equation := equations i.val i.isLt + rw [parentActive, G.mul_comm, G.mul_one] at equation + exact (G.sub_eq_zero_iff _ _).mp equation + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/Selectors.lean b/Ix/Aiur/Proofs/Selectors.lean new file mode 100644 index 000000000..f80f84b6b --- /dev/null +++ b/Ix/Aiur/Proofs/Selectors.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Domain + +/-! The checked native rational formulas evaluate the selector polynomials +away from the trace domain. Their row values include the native, unnormalized +last-row factor `n * generator`, which is a nonzero Goldilocks element. +-/ + +namespace Aiur.NativeAIR.Domain + +open Lean.Grind +open ProofCodec (Extension) +open Algebra + +theorem first_at_row (domain : Subgroup) (index : Fin (size domain)) : + dividedPowers (point domain index) (1 : G) (size domain) = + if index.val = 0 then G.ofNat (size domain) else 0 := by + by_cases first : index.val = 0 + · rw [if_pos first, (point_first_iff domain index).mpr first, dividedPowers_diagonal, + Semiring.one_pow, Semiring.mul_one] + rfl + · rw [if_neg first] + have factor := root_dividedPowers (point domain index) (1 : G) + (Semiring.one_pow (size domain)) + rw [point_power, (by decide : (1 : G) - 1 = 0)] at factor + exact ((G.mul_eq_zero_iff _ _).mp factor).resolve_left + (fun zero => first ((point_first_iff domain index).mp ((G.sub_eq_zero_iff _ _).mp zero))) + +theorem last_at_row (domain : Subgroup) (index : Fin (size domain)) : + dividedPowers (point domain index) (lastPoint domain) (size domain) = + if index.val = size domain - 1 then normalizer domain else 0 := by + by_cases last : index.val = size domain - 1 + · rw [if_pos last, (point_last_iff domain index).mpr last, dividedPowers_diagonal, + lastPoint_predecessor] + rfl + · rw [if_neg last] + have factor := root_dividedPowers (point domain index) (lastPoint domain) (lastPoint_power domain) + rw [point_power, (by decide : (1 : G) - 1 = 0)] at factor + exact ((G.mul_eq_zero_iff _ _).mp factor).resolve_left + (fun zero => last ((point_last_iff domain index).mp ((G.sub_eq_zero_iff _ _).mp zero))) + +theorem transition_at_row (domain : Subgroup) (index : Fin (size domain)) : + point domain index - lastPoint domain = 0 ↔ index.val = size domain - 1 := by + rw [G.sub_eq_zero_iff, point_last_iff] + +theorem ofBase_dividedPowers (x a : G) (n : Nat) : + Extension.ofBase (dividedPowers x a n) = + dividedPowers (Extension.ofBase x) (Extension.ofBase a) n := by + induction n with + | zero => rfl + | succ n ih => rw [dividedPowers, dividedPowers, Extension.ofBase_add, + Extension.ofBase_mul, Extension.ofBase_power, ih] + +theorem vanishing_eq (domain : Subgroup) (value : Extension) : + vanishing domain value = value ^ size domain - 1 := by + rw [vanishing, Extension.power_eq] + +theorem vanishing_at_row (domain : Subgroup) (index : Fin (size domain)) : + vanishing domain (Extension.ofBase (point domain index)) = 0 := by + rw [vanishing_eq, ← Extension.ofBase_power, point_power] + change (1 : Extension) - 1 = 0 + grind + +theorem lastPoint_extension_power (domain : Subgroup) : + Extension.ofBase (lastPoint domain) ^ size domain = 1 := by + rw [← Extension.ofBase_power, lastPoint_power] + rfl + +theorem root_difference_nonzero (x a : Extension) {n : Nat} + (root : a ^ n = 1) (nonzero : x ^ n - 1 ≠ 0) : x - a ≠ 0 := by + intro zero + have same : x = a := by grind + subst x + apply nonzero + rw [root] + grind + +theorem selectors_success (domain : Subgroup) (value : Extension) (selected : Selectors Extension) + (accepted : selectors domain value = some selected) : + selected.isFirst = dividedPowers value 1 (size domain) ∧ + selected.isLast = dividedPowers value (Extension.ofBase (lastPoint domain)) (size domain) ∧ + selected.isTransition = value - Extension.ofBase (lastPoint domain) ∧ + vanishing domain value * selected.invVanishing = 1 := by + simp only [selectors, bind, pure, Option.bind_eq_some_iff, Option.some.injEq] at accepted + obtain ⟨firstInverse, first, lastInverse, last, vanishingInverse, invert, rfl⟩ := accepted + exact ⟨by + rw [vanishing_eq] + exact dividedPowers_off_root value 1 firstInverse (Semiring.one_pow _) + ((Extension.tryInverse_some_iff _ _).mp first), by + rw [vanishing_eq] + exact dividedPowers_off_root value _ lastInverse (lastPoint_extension_power domain) + ((Extension.tryInverse_some_iff _ _).mp last), rfl, + (Extension.tryInverse_some_iff _ _).mp invert⟩ + +theorem selectors_defined (domain : Subgroup) (value : Extension) + (nonzero : vanishing domain value ≠ 0) : ∃ selected, selectors domain value = some selected := by + have polynomial : value ^ size domain - 1 ≠ 0 := by rwa [vanishing_eq] at nonzero + obtain ⟨first, firstDefined⟩ := Option.ne_none_iff_exists'.mp (fun absent => + root_difference_nonzero value 1 (Semiring.one_pow _) polynomial + ((Extension.tryInverse_none_iff _).mp absent)) + obtain ⟨last, lastDefined⟩ := Option.ne_none_iff_exists'.mp (fun absent => + root_difference_nonzero value _ (lastPoint_extension_power domain) polynomial + ((Extension.tryInverse_none_iff _).mp absent)) + obtain ⟨inverse, inverseDefined⟩ := Option.ne_none_iff_exists'.mp (fun absent => + nonzero ((Extension.tryInverse_none_iff _).mp absent)) + refine ⟨⟨vanishing domain value * first, vanishing domain value * last, + value - Extension.ofBase (lastPoint domain), inverse⟩, ?_⟩ + simp only [selectors, firstDefined, lastDefined, inverseDefined, bind, pure, Option.bind_some] + +theorem selectors_defined_iff (domain : Subgroup) (value : Extension) : + (∃ selected, selectors domain value = some selected) ↔ vanishing domain value ≠ 0 := by + constructor + · rintro ⟨selected, accepted⟩ zero + have inverse := (selectors_success domain value selected accepted).2.2.2 + rw [zero, Extension.zero_mul] at inverse + exact Extension.one_ne_zero inverse.symm + · exact selectors_defined domain value + +theorem selectors_none_at_row (domain : Subgroup) (index : Fin (size domain)) : + selectors domain (Extension.ofBase (point domain index)) = none := by + by_cases absent : selectors domain (Extension.ofBase (point domain index)) = none + · exact absent + · obtain ⟨selected, accepted⟩ := Option.ne_none_iff_exists'.mp absent + exact False.elim ((selectors_defined_iff _ _).mp ⟨selected, accepted⟩ (vanishing_at_row _ _)) + +end Aiur.NativeAIR.Domain diff --git a/Ix/Aiur/Proofs/ShapedVerifier.lean b/Ix/Aiur/Proofs/ShapedVerifier.lean new file mode 100644 index 000000000..fd7054c21 --- /dev/null +++ b/Ix/Aiur/Proofs/ShapedVerifier.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ShapedVerifier +import Ix.Aiur.Proofs.ProofCodec +import Ix.Aiur.Proofs.ProofShape + +/-! Shape and framing facts follow from the bytes accepted by the actual +checked wrapper. Native transcript/PCS/AIR correctness remains to be proved. -/ + +namespace Aiur.BoundVerifier + +theorem CheckedProof.framing {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) : + NativeAIR.ProofCodec.readData bytes.data.toList = some (checked.data, []) ∧ + NativeAIR.ProofCodec.encode checked.data = bytes := by + obtain ⟨decoded, encoded⟩ := NativeAIR.ProofCodec.decodeCanonical_success checked.decoded + exact ⟨NativeAIR.ProofCodec.decode_success decoded, encoded⟩ + +theorem CheckedProof.wire_bounds {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) : NativeAIR.ProofCodec.DataFits checked.data := + NativeAIR.ProofCodec.decode_fits (NativeAIR.ProofCodec.decodeCanonical_success checked.decoded).1 + +theorem CheckedProof.row {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) {position : Nat} {row : NativeAIR.ProofShape.Row} + (present : checked.rows[position]? = some row) : + checked.data.active[row.circuitIndex]? = some true ∧ + row.Sourced key checked.data row.circuitIndex position ∧ row.Fits key.parameters := by + obtain ⟨index, _, sourced, fits⟩ := NativeAIR.ProofShape.check_row checked.shape present + exact ⟨NativeAIR.ProofShape.check_row_active checked.shape present, sourced.index_eq ▸ sourced, fits⟩ + +theorem CheckedProof.nonempty {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) : checked.rows ≠ [] := + NativeAIR.ProofShape.check_nonempty checked.shape + +theorem CheckedProof.fixed_heights {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) : + FixedTraceHeights (key.circuits.map (·.preprocessedHeight)) checked.data.active + (checked.data.logDegrees.map UInt8.toNat) := + NativeAIR.ProofShape.fixedHeights_sound checked.fixed + +theorem CheckedProof.lookup_budget {key : NativeAIR.KeyCodec.Key} {bytes : ByteArray} + (checked : CheckedProof key bytes) : + ∃ total, lookupSlotSum (key.circuits.map (·.graph.lookups.length)) checked.data.active + (checked.data.logDegrees.map UInt8.toNat) = some total ∧ + checked.bound = 1 + total ∧ checked.bound < gSize.toNat := + NativeAIR.ProofShape.queryBound_sound checked.budget + +theorem verifyShaped_acceptance {selection : Selection} {backend : CompiledBackend selection} + {input : Array G} {bytes : ByteArray} (accepted : verifyShaped backend input bytes = .ok ()) : + input.size = selection.inputSize ∧ + ∃ (checked : CheckedProof backend.keyData bytes) (native : Proof), + readProof backend.keyData bytes = .ok checked ∧ Proof.ofBytesChecked bytes = .ok native ∧ + backend.system.verify (buildClaim selection.function input selection.success) native = .ok () := by + obtain ⟨checked, parsed, verified⟩ := verifyShaped_success accepted + obtain ⟨arity, native, decoded, checkedNative⟩ := verifyCompiled_success verified + exact ⟨arity, checked, native, parsed, decoded, checkedNative⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/TableExpressions.lean b/Ix/Aiur/Proofs/TableExpressions.lean new file mode 100644 index 000000000..a136a2a6b --- /dev/null +++ b/Ix/Aiur/Proofs/TableExpressions.lean @@ -0,0 +1,115 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.CompiledKey + +/-! The memory and byte expression builders evaluate to their physical +column models. Every read follows from the matrix dimensions. -/ + +namespace Aiur.NativeAIR.CompiledKey +open Compiler OpEmitter + +def columns (values : Values G) (source : Source) (offset : RowOffset) (width : Nat) : Fin width → G := + fun index => (values.columns source offset)[index.val]?.getD 0 + +theorem column_eval {values : Values G} {widths : GraphWidths} (fits : values.Fits widths) + (source : Source) (offset : RowOffset) {width : Nat} (bound : width ≤ widths.width source) + (index : Fin width) : + (Expr.var ⟨source, offset, index.val⟩).eval goldilocksOps values = + some (columns values source offset width index) := by + have inside : index.val < (values.columns source offset).size := by + rw [fits.1] + exact Nat.lt_of_lt_of_le index.isLt bound + simp only [Expr.eval, columns, Array.getElem?_eq_getElem inside, Option.getD_some] + +theorem memoryEquations_eval {values : Values G} {widths : GraphWidths} (fits : values.Fits widths) + (width : Nat) (bound : 3 + width ≤ widths.main) : + memoryEquations.mapM (Expr.eval goldilocksOps values) = some + (AIR.memoryColumnEquations width (columns values .main .current (3 + width)) + (columns values .main .next (3 + width)) values.isTransition) := by + have cur := column_eval fits .main .current bound + have nxt := column_eval fits .main .next bound + have one : (Expr.konst 1).eval goldilocksOps values = some 1 := rfl + have selector := cur ⟨1, by omega⟩ + have multiplicity := cur ⟨0, by omega⟩ + have transition := Expr.frontMul_eval goldilocksLaws values (nxt ⟨1, by omega⟩) + (show Expr.isTransition.eval goldilocksOps values = some values.isTransition from rfl) + have minusOne := Expr.frontSub_eval goldilocksLaws values selector one + have first := Expr.frontMul_eval goldilocksLaws values selector minusOne + have second := Expr.frontMul_eval goldilocksLaws values multiplicity + (Expr.frontSub_eval goldilocksLaws values one selector) + have third := Expr.frontMul_eval goldilocksLaws values transition minusOne + have fourth := Expr.frontMul_eval goldilocksLaws values transition + (Expr.frontSub_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values (cur ⟨2, by omega⟩) one) (nxt ⟨2, by omega⟩)) + simp only [memoryEquations, main, next, AIR.memoryColumnEquations, List.mapM_cons, List.mapM_nil, + first, second, third, fourth, bind, Option.bind_some, pure] + rfl + +theorem memoryLookup_eval {values : Values G} {widths : GraphWidths} (fits : values.Fits widths) + (width : Nat) (bound : 3 + width ≤ widths.main) : + (memoryLookup width).eval goldilocksOps values = + some (AIR.memoryColumnLookup width (columns values .main .current (3 + width))) := by + let row := columns values .main .current (3 + width) + have cur := column_eval fits .main .current bound + have selector := cur ⟨1, by omega⟩ + have multiplicity := Expr.frontNeg_eval goldilocksLaws values (cur ⟨0, by omega⟩) + have channel := Expr.frontMul_eval goldilocksLaws values selector + (show (Expr.konst 1).eval goldilocksOps values = some 1 from rfl) + have size := Expr.frontMul_eval goldilocksLaws values selector + (show (Expr.konst (G.ofNat width)).eval goldilocksOps values = some (G.ofNat width) from rfl) + have pointer := Expr.frontMul_eval goldilocksLaws values selector (cur ⟨2, by omega⟩) + have contents := list_mapM_ofFn + (fun i : Fin width => (main 1).frontMul (main (3 + i.val))) + (fun i : Fin width => row ⟨1, by omega⟩ * row ⟨3 + i.val, by omega⟩) + (Expr.eval goldilocksOps values) + (fun i => Expr.frontMul_eval goldilocksLaws values selector (cur ⟨3 + i.val, by omega⟩)) + simp only [main] at contents + simp only [memoryLookup, ExprLookup.eval, evalExprs, main, List.map_cons, List.map_nil, + List.cons_append, List.nil_append, List.mapM_cons, + multiplicity, channel, size, pointer, contents, bind, Option.bind_some, pure, + AIR.memoryColumnLookup, AIR.memoryMessage, AIR.decodeMemoryRow, Array.toList_ofFn, + List.map_ofFn, Function.comp_def] + rfl + +theorem byte1Lookup_eval {values : Values G} {widths : GraphWidths} (fits : values.Fits widths) + (mainBound : 3 ≤ widths.main) (preprocessedBound : 11 ≤ widths.preprocessed) (kind : AIR.Byte1Kind) : + (byte1Lookup kind).eval goldilocksOps values = some + (AIR.byte1ColumnLookup kind (columns values .preprocessed .current 11) (columns values .main .current 3)) := by + have cur := column_eval fits .main .current mainBound + have pre (index : Nat) (bound : index < 11) : + (values.columns .preprocessed .current)[index]? = + some (columns values .preprocessed .current 11 ⟨index, bound⟩) := + column_eval fits .preprocessed .current preprocessedBound ⟨index, bound⟩ + have multiplicity := Expr.frontNeg_eval goldilocksLaws values (cur kind.column) + have bits := list_mapM_ofFn (fun i : Fin 8 => preprocessed (1 + i.val)) + (fun i : Fin 8 => columns values .preprocessed .current 11 ⟨1 + i.val, by omega⟩) + (Expr.eval goldilocksOps values) (fun i => pre (1 + i.val) (by omega)) + simp only [preprocessed] at bits + cases kind <;> + simp only [byte1Lookup, ExprLookup.eval, evalExprs, List.cons_append, List.nil_append, + List.mapM_cons, List.mapM_nil, main, multiplicity, preprocessed, Expr.eval, bits, + pre 0 (by decide), pre 9 (by decide), pre 10 (by decide), + bind, Option.bind_some, pure, AIR.byte1ColumnLookup] <;> rfl + +theorem byte2Lookup_eval {values : Values G} {widths : GraphWidths} (fits : values.Fits widths) + (mainBound : 10 ≤ widths.main) (preprocessedBound : 14 ≤ widths.preprocessed) (kind : AIR.Byte2Kind) : + (byte2Lookup kind).eval goldilocksOps values = some + (AIR.byte2ColumnLookup kind (columns values .preprocessed .current 14) (columns values .main .current 10)) := by + have cur := column_eval fits .main .current mainBound + have pre (index : Nat) (bound : index < 14) : + (values.columns .preprocessed .current)[index]? = + some (columns values .preprocessed .current 14 ⟨index, bound⟩) := + column_eval fits .preprocessed .current preprocessedBound ⟨index, bound⟩ + have multiplicity := Expr.frontNeg_eval goldilocksLaws values (cur kind.column) + cases kind <;> + simp only [byte2Lookup, ExprLookup.eval, evalExprs, List.cons_append, List.nil_append, + List.mapM_cons, List.mapM_nil, main, multiplicity, preprocessed, Expr.eval, + pre 0 (by decide), pre 1 (by decide), pre 2 (by decide), pre 3 (by decide), pre 4 (by decide), + pre 5 (by decide), pre 6 (by decide), pre 7 (by decide), pre 8 (by decide), pre 9 (by decide), + pre 10 (by decide), pre 11 (by decide), pre 12 (by decide), pre 13 (by decide), + bind, Option.bind_some, pure, AIR.byte2ColumnLookup] <;> rfl + +end Aiur.NativeAIR.CompiledKey diff --git a/Ix/Aiur/Proofs/TailMatches.lean b/Ix/Aiur/Proofs/TailMatches.lean new file mode 100644 index 000000000..37c429ef7 --- /dev/null +++ b/Ix/Aiur/Proofs/TailMatches.lean @@ -0,0 +1,85 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Semantics.SourceEval + +/-! Tail-match restoration preserves the complete source evaluator result. +This covers the normalization helper used by inlining; expansion and let +hoisting require separate proofs. -/ + +namespace Aiur.Source.Eval + +private theorem evalMatchCases_map (decls : Decls) (fuel : Nat) + (transform : Term → Term) (arms : List (Pattern × Term)) + (equivalent : ∀ arm ∈ arms, ∀ bindings st, + interp decls fuel bindings arm.2 st = interp decls fuel bindings (transform arm.2) st) + (bindings : Bindings) (st : EvalState) (value : Value) : + evalMatchCases decls fuel bindings st value arms = + evalMatchCases decls fuel bindings st value (arms.map fun arm => (arm.1, transform arm.2)) := by + induction arms with + | nil => rfl + | cons arm arms ih => + rcases arm with ⟨pattern, body⟩ + simp only [List.map_cons, evalMatchCases] + cases matchPattern st.store pattern value with + | some bs => exact equivalent (pattern, body) (by simp) (bs ++ bindings) st + | none => exact ih (fun arm member => equivalent arm (by simp [member])) + +/-- All successes, errors and early returns are identical, including their +full memory and I/O states. Fuel is unchanged because it counts calls. -/ +theorem interp_restoreTailMatches (decls : Decls) (fuel : Nat) (term : Term) + (bindings : Bindings) (st : EvalState) : + interp decls fuel bindings term st = + interp decls fuel bindings term.restoreTailMatches st := by + induction term using Term.restoreTailMatches.induct generalizing bindings st with + | case1 x value y same ih => + simp only [Term.restoreTailMatches, if_pos same] + rw [← ih] + simp only [interp] + cases interp decls fuel bindings value st with + | error e => rfl + | ok result => + rcases result with ⟨v, st'⟩ + simp [matchPattern, same] + | case2 x value y different => simp only [Term.restoreTailMatches, if_neg different] + | case3 pattern value body notEta ih => + rw [Term.restoreTailMatches.eq_def] + split + next x value' y impossible => + cases impossible + exact False.elim (notEta x y rfl rfl) + next => + rename_i p v b _ heq + cases heq + simp only [interp] + cases interp decls fuel bindings value st with + | error e => rfl + | ok result => + rcases result with ⟨v, st'⟩ + dsimp only + cases matchPattern st'.store pattern v with + | none => rfl + | some bs => exact ih (bs ++ bindings) st' + next s arms impossible => cases impossible + next => rfl + | case4 scrut arms ih => + simp only [Term.restoreTailMatches, interp] + cases interp decls fuel bindings scrut st with + | error e => rfl + | ok result => + rcases result with ⟨v, st'⟩ + simpa only [List.attach_map_val (f := fun (arm : Pattern × Term) => + (arm.1, arm.2.restoreTailMatches))] using + evalMatchCases_map decls fuel Term.restoreTailMatches arms + (fun arm member => ih ⟨arm, member⟩) bindings st' v + | case5 term notEta notLet notMatch => + rw [Term.restoreTailMatches.eq_def] + split + · exact False.elim (notEta _ _ _ rfl) + · exact False.elim (notLet _ _ _ rfl) + · exact False.elim (notMatch _ _ rfl) + · rfl + +end Aiur.Source.Eval diff --git a/Ix/Aiur/Proofs/Transcript.lean b/Ix/Aiur/Proofs/Transcript.lean new file mode 100644 index 000000000..6c94eec86 --- /dev/null +++ b/Ix/Aiur/Proofs/Transcript.lean @@ -0,0 +1,179 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Transcript +import Ix.Aiur.Proofs.Challenger +import Ix.Aiur.Proofs.VerifierAccumulator + +namespace Aiur.NativeAIR.Transcript + +open Challenger +open ProofCodec (Extension) + +theorem seed_length (parameters : KeyCodec.Parameters) : (seed parameters).length = 70 := by + simp only [seed, parameterWords, List.flatMap_cons, List.flatMap_nil, List.length_append, + KeyCodec.encodeNat_length, List.length_nil] + rfl + +theorem circuitShape_length (circuit : KeyCodec.Circuit) : (circuitShape circuit).length = 7 := by + simp only [circuitShape, List.length_map, List.length_cons, List.length_nil] + +theorem shape_length (key : KeyCodec.Key) : (shape key).length = 1 + 7 * key.circuits.length := by + have length (circuits : List KeyCodec.Circuit) : (circuits.flatMap circuitShape).length = 7 * circuits.length := by + induction circuits with + | nil => rfl + | cons circuit circuits ih => + simp only [List.flatMap_cons, List.length_append, circuitShape_length, List.length_cons, ih] + omega + simp only [shape, List.length_cons, length] + omega + +theorem fieldsBytes_length (values : List G) : (fieldsBytes values).length = 8 * values.length := by + induction values with + | nil => rfl + | cons value values ih => + simp only [fieldsBytes, List.flatMap_cons, List.length_append, ProofCodec.encodeField, + KeyCodec.encodeNat_length, List.length_cons] at * + omega + +theorem observeFields_bytes (state : State) (values : List G) : + values.foldl observeField state = observeBytes state (fieldsBytes values) := by + induction values generalizing state with + | nil => rfl + | cons value values ih => + simp only [List.foldl_cons, ih, fieldsBytes, List.flatMap_cons, observeBytes_append] + rfl + +theorem claimsFields_framing (claims : List (List G)) : + claimsFields claims = G.ofNat claims.length :: claims.flatMap (fun claim => G.ofNat claim.length :: claim) := rfl + +/-- Actual native observation order, including the full activation bitmap +and all claim boundaries, before either lookup challenge is drawn. -/ +theorem lookupState_schedule (key : KeyCodec.Key) (proof : ProofCodec.Data) (claims : List (List G)) : + lookupState key proof claims = + (claimsFields claims).foldl observeField + ((proof.logDegrees.map (fun degree => G.ofNat degree.toNat)).foldl observeField + (observeCap + (observeCap + ((proof.active.map (fun active => if active then 1 else 0)).foldl observeField + ((shape key).foldl observeField (initial (seed key.parameters)))) + (key.preprocessedCommitment.getD [])) + proof.commitments.stage1)) := by + simp only [lookupState, prefixBytes, observeBytes_append, observeFields_bytes, observeCap] + +theorem lookupState_valid (key : KeyCodec.Key) (proof : ProofCodec.Data) (claims : List (List G)) : + (lookupState key proof claims).Valid := observeBytes_valid (initial_valid _) _ + +theorem accumulatorState_valid (proof : ProofCodec.Data) {state : State} (valid : state.Valid) : + (accumulatorState proof state).Valid := observeExtensions_valid (observeCap_valid valid _) _ + +/-- Sampling transitions with the states on both sides of each native +observation. The final state is the one passed into polynomial verification. -/ +structure Replay.Reads (hash : Hash32) (fuel : Nat) (key : KeyCodec.Key) + (proof : ProofCodec.Data) (claims : List (List G)) (result : Replay) : Prop where + states : ∃ afterBeta afterGamma afterAlpha, + sampleExtension hash fuel (lookupState key proof claims) = some (result.challenges.beta, afterBeta) ∧ + sampleExtension hash fuel (observeExtension afterBeta result.challenges.beta) = + some (result.challenges.gamma, afterGamma) ∧ + sampleExtension hash fuel (accumulatorState proof (observeExtension afterGamma result.challenges.gamma)) = + some (result.challenges.alpha, afterAlpha) ∧ + sampleExtension hash fuel (observeCap afterAlpha proof.commitments.quotient) = + some (result.challenges.zeta, result.state) + +theorem replay_success {hash : Hash32} {fuel : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {result : Replay} (accepted : replay hash fuel key proof claims = some result) : + result.Reads hash fuel key proof claims := by + simp only [replay, bind, pure, Option.bind_eq_some_iff, Option.some.injEq, Prod.exists] at accepted + obtain ⟨beta, afterBeta, first, gamma, afterGamma, second, alpha, afterAlpha, third, + zeta, final, fourth, rfl⟩ := accepted + exact ⟨afterBeta, afterGamma, afterAlpha, first, second, third, fourth⟩ + +theorem Replay.Reads.complete {hash : Hash32} {fuel : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {result : Replay} (reads : result.Reads hash fuel key proof claims) : + replay hash fuel key proof claims = some result := by + obtain ⟨afterBeta, afterGamma, afterAlpha, first, second, third, fourth⟩ := reads.states + simp only [replay, first, second, third, fourth, bind, pure, Option.bind_some] + +theorem replay_iff (hash : Hash32) (fuel : Nat) (key : KeyCodec.Key) (proof : ProofCodec.Data) + (claims : List (List G)) (result : Replay) : replay hash fuel key proof claims = some result ↔ + result.Reads hash fuel key proof claims := ⟨replay_success, Replay.Reads.complete⟩ + +theorem replay_mono {hash : Hash32} {fuel more : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {result : Replay} (accepted : replay hash fuel key proof claims = some result) + (bound : fuel ≤ more) : replay hash more key proof claims = some result := by + obtain ⟨afterBeta, afterGamma, afterAlpha, first, second, third, fourth⟩ := (replay_success accepted).states + exact (Replay.Reads.complete ⟨afterBeta, afterGamma, afterAlpha, sampleExtension_mono first bound, + sampleExtension_mono second bound, sampleExtension_mono third bound, sampleExtension_mono fourth bound⟩) + +theorem replay_unique {hash : Hash32} {fuel other : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {left right : Replay} (first : replay hash fuel key proof claims = some left) + (second : replay hash other key proof claims = some right) : left = right := by + have one := replay_mono first (Nat.le_max_left fuel other) + have two := replay_mono second (Nat.le_max_right fuel other) + exact Option.some.inj (one.symm.trans two) + +theorem replay_valid {hash : Hash32} {fuel : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {result : Replay} (accepted : replay hash fuel key proof claims = some result) : + result.state.Valid := by + obtain ⟨afterBeta, afterGamma, afterAlpha, first, second, third, fourth⟩ := (replay_success accepted).states + have beta := sampleExtension_valid first (lookupState_valid key proof claims) + have gamma := sampleExtension_valid second (observeExtension_valid beta _) + have alpha := sampleExtension_valid third (accumulatorState_valid proof (observeExtension_valid gamma _)) + exact sampleExtension_valid fourth (observeCap_valid alpha _) + +theorem verifyArithmetic_success {hash : Hash32} {fuel : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {rows : List ProofShape.Row} {result : Replay} + (accepted : verifyArithmetic hash fuel key proof claims rows = some result) : + replay hash fuel key proof claims = some result ∧ + VerifierArithmetic.verify result.challenges claims rows = some true := by + simp only [verifyArithmetic, bind, Option.bind_eq_some_iff] at accepted + obtain ⟨replayed, replayRead, check, arithmetic, accepted⟩ := accepted + cases check with + | false => cases accepted + | true => cases accepted; exact ⟨replayRead, arithmetic⟩ + +theorem verifyArithmetic_iff (hash : Hash32) (fuel : Nat) (key : KeyCodec.Key) (proof : ProofCodec.Data) + (claims : List (List G)) (rows : List ProofShape.Row) (result : Replay) : + verifyArithmetic hash fuel key proof claims rows = some result ↔ + replay hash fuel key proof claims = some result ∧ + VerifierArithmetic.verify result.challenges claims rows = some true := by + constructor + · exact verifyArithmetic_success + · rintro ⟨replayed, accepted⟩ + simp only [verifyArithmetic, replayed, accepted, bind, Option.bind_some, ↓reduceIte] + +theorem verifyArithmetic_mono {hash : Hash32} {fuel more : Nat} {key : KeyCodec.Key} {proof : ProofCodec.Data} + {claims : List (List G)} {rows : List ProofShape.Row} {result : Replay} + (accepted : verifyArithmetic hash fuel key proof claims rows = some result) (bound : fuel ≤ more) : + verifyArithmetic hash more key proof claims rows = some result := by + obtain ⟨replayed, arithmetic⟩ := verifyArithmetic_success accepted + exact (verifyArithmetic_iff _ _ _ _ _ _ _).mpr ⟨replay_mono replayed bound, arithmetic⟩ + +end Aiur.NativeAIR.Transcript + +namespace Aiur.BoundVerifier +open NativeAIR + +/-- The checked selected key and proof supply the entire transcript. This +conclusion still needs PCS authentication and the cryptographic bad-event +analysis before it can imply a satisfying execution trace. -/ +theorem CompiledBackend.transcript_row {selection : Selection} (backend : CompiledBackend selection) + {bytes : ByteArray} (checked : CheckedProof backend.keyData bytes) {hash : Challenger.Hash32} + {fuel : Nat} {claims : List (List G)} {result : Transcript.Replay} + (accepted : Transcript.verifyArithmetic hash fuel backend.keyData checked.data claims checked.rows = some result) + {position : Nat} {row : ProofShape.Row} (present : checked.rows[position]? = some row) : + result.Reads hash fuel backend.keyData checked.data claims ∧ + row.Sourced backend.keyData checked.data row.circuitIndex position ∧ row.Fits backend.keyData.parameters ∧ + ∃ initial before evaluation, + VerifierArithmetic.initialAccumulator result.challenges claims = some initial ∧ + (initial :: checked.rows.map (·.accumulator))[position]? = some before ∧ + VerifierArithmetic.evaluate result.challenges row before = some evaluation ∧ + Quotient.composition result.challenges.alpha evaluation.constraints = + Domain.vanishing evaluation.domain result.challenges.zeta * evaluation.quotientValue := by + obtain ⟨replayed, arithmetic⟩ := Transcript.verifyArithmetic_success accepted + obtain ⟨_, sourced, fits⟩ := checked.row present + exact ⟨Transcript.replay_success replayed, sourced, fits, VerifierArithmetic.verify_row arithmetic present⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/VerifierAccumulator.lean b/Ix/Aiur/Proofs/VerifierAccumulator.lean new file mode 100644 index 000000000..fadc4a18a --- /dev/null +++ b/Ix/Aiur/Proofs/VerifierAccumulator.lean @@ -0,0 +1,232 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.VerifierArithmetic +import Ix.Aiur.Proofs.DomainAccumulator + +/-! Public claims initialize the positive sum of inverse compressed messages. +Ordered active rows use consecutive accumulator values and finish at zero. +These are arithmetic facts with explicit challenges, without a transcript +or polynomial-authentication assumption disguised as a conclusion. +-/ + +namespace Aiur.NativeAIR.VerifierArithmetic +open ProofCodec (Extension) +open LogUp (Coordinates) + +theorem claimMessage_native (challenges : Challenges) (claim : List G) : + claimMessage challenges claim = challenges.beta + + claim.foldr (fun arg accumulated => accumulated * challenges.gamma + Extension.ofBase arg) 0 := by + rw [claimMessage, LogUp.fingerprint_toExtension] + rfl + +def publicEntries (challenges : Challenges) (claims : List (List G)) : List (Extension × Extension) := + claims.map fun claim => (1, claimMessage challenges claim) + +theorem publicEntries_compress (challenges : Challenges) (claims : List (List G)) : + LogUp.fieldEntries (LogUp.compress (Coordinates.fromExtension challenges.beta) + (Coordinates.fromExtension challenges.gamma) (claims.map fun claim => (1, claim))) = + publicEntries challenges claims := by + simp only [LogUp.fieldEntries, LogUp.compress, publicEntries, List.map_map, Function.comp_def] + apply List.map_congr_left + intro claim _ + change ((1 : Extension), (LogUp.fingerprint (Coordinates.fromExtension challenges.gamma) claim + + Coordinates.fromExtension challenges.beta).toExtension) = (1, claimMessage challenges claim) + rw [Coordinates.toExtension_add, claimMessage] + change ((1 : Extension), _ + challenges.beta) = (1, challenges.beta + _) + rw [Extension.add_comm] + +theorem initialAccumulator_nil (challenges : Challenges) : initialAccumulator challenges [] = some 0 := rfl + +theorem initialAccumulator_cons (challenges : Challenges) (claim : List G) (claims : List (List G)) : + initialAccumulator challenges (claim :: claims) = do + let inverse ← (claimMessage challenges claim).tryInverse + let rest ← initialAccumulator challenges claims + return inverse + rest := by + unfold initialAccumulator + rw [List.mapM_cons] + cases first : (claimMessage challenges claim).tryInverse <;> + cases rest : claims.mapM (fun claim => (claimMessage challenges claim).tryInverse) <;> rfl + +theorem initialAccumulator_success {challenges : Challenges} {claims : List (List G)} {accumulator : Extension} + (accepted : initialAccumulator challenges claims = some accumulator) : + LogUp.PoleFree (publicEntries challenges claims) ∧ + accumulator = LogUp.fractionSum (publicEntries challenges claims) := by + induction claims generalizing accumulator with + | nil => + constructor + · intro _ member; cases member + · cases accepted; rfl + | cons claim claims ih => + rw [initialAccumulator_cons] at accepted + simp only [bind, pure, Option.bind_eq_some_iff, Option.some.injEq] at accepted + obtain ⟨inverse, inverseRead, rest, restRead, rfl⟩ := accepted + obtain ⟨free, equal⟩ := ih restRead + have nonzero : claimMessage challenges claim ≠ 0 := by + intro zero + have none := (Extension.tryInverse_none_iff _).mpr zero + rw [none] at inverseRead + cases inverseRead + refine ⟨?_, ?_⟩ + · intro entry member + simp only [publicEntries, List.map_cons, List.mem_cons] at member + rcases member with rfl | member + · exact nonzero + · exact free entry member + · rw [publicEntries, List.map_cons, LogUp.fractionSum_cons] + simp only [LogUp.inverseValue, inverseRead, Option.getD_some, Lean.Grind.Semiring.one_mul] + rw [equal] + rfl + +theorem initialAccumulator_defined (challenges : Challenges) (claims : List (List G)) + (free : LogUp.PoleFree (publicEntries challenges claims)) : + ∃ accumulator, initialAccumulator challenges claims = some accumulator := by + induction claims with + | nil => exact ⟨0, rfl⟩ + | cons claim claims ih => + have head : claimMessage challenges claim ≠ 0 := free (1, claimMessage challenges claim) List.mem_cons_self + obtain ⟨inverseRead, _⟩ := Extension.inverse_correct _ head + obtain ⟨rest, restRead⟩ := ih (fun entry member => free entry (List.mem_cons_of_mem _ member)) + exact ⟨(claimMessage challenges claim).conjugate.scale (claimMessage challenges claim).norm.inverse + rest, + by simp only [initialAccumulator_cons, inverseRead, restRead, bind, pure, Option.bind_some]⟩ + +theorem initialAccumulator_defined_iff (challenges : Challenges) (claims : List (List G)) : + (∃ accumulator, initialAccumulator challenges claims = some accumulator) ↔ + LogUp.PoleFree (publicEntries challenges claims) := + ⟨fun ⟨_, read⟩ => (initialAccumulator_success read).1, initialAccumulator_defined challenges claims⟩ + +theorem initialAccumulator_lookupFractions {challenges : Challenges} {claims : List (List G)} {accumulator : Extension} + (accepted : initialAccumulator challenges claims = some accumulator) : + accumulator = LogUp.lookupFractions (Coordinates.fromExtension challenges.beta) + (Coordinates.fromExtension challenges.gamma) (claims.map fun claim => (1, claim)) := by + rw [LogUp.lookupFractions, publicEntries_compress] + exact (initialAccumulator_success accepted).2 + +theorem checkRows_cons (challenges : Challenges) (row : ProofShape.Row) (rows : List ProofShape.Row) + (entering final : Extension) : + checkRows challenges (row :: rows) entering = some final ↔ + check challenges row entering = some true ∧ checkRows challenges rows row.accumulator = some final := by + simp only [checkRows, bind, Option.bind_eq_some_iff] + constructor + · rintro ⟨accepted, checked, tail⟩ + cases accepted with + | false => cases tail + | true => exact ⟨checked, tail⟩ + · rintro ⟨checked, tail⟩; exact ⟨true, checked, tail⟩ + +theorem checkRows_final {challenges : Challenges} {rows : List ProofShape.Row} {entering final : Extension} + (accepted : checkRows challenges rows entering = some final) : + rows.foldl (fun _ row => row.accumulator) entering = final := by + induction rows generalizing entering with + | nil => exact Option.some.inj accepted + | cons row rows ih => exact ih ((checkRows_cons _ _ _ _ _).mp accepted).2 + +theorem checkRows_row {challenges : Challenges} {rows : List ProofShape.Row} {entering final : Extension} + (accepted : checkRows challenges rows entering = some final) {position : Nat} {row : ProofShape.Row} + (present : rows[position]? = some row) : + ∃ before, (entering :: rows.map (·.accumulator))[position]? = some before ∧ + check challenges row before = some true := by + induction rows generalizing entering position with + | nil => simp only [List.getElem?_nil, reduceCtorEq] at present + | cons first rows ih => + obtain ⟨checked, tail⟩ := (checkRows_cons _ _ _ _ _).mp accepted + cases position with + | zero => cases present; exact ⟨entering, rfl, checked⟩ + | succ position => + obtain ⟨before, beforeRead, rowRead⟩ := ih tail present + exact ⟨before, beforeRead, rowRead⟩ + +theorem checkRows_sum {challenges : Challenges} {rows : List ProofShape.Row} {entering final : Extension} + (accepted : checkRows challenges rows entering = some final) (fraction : ProofShape.Row → Extension) + (rowIdentity : ∀ row ∈ rows, ∀ before, check challenges row before = some true → + fraction row = row.accumulator - before) : + LogUp.sum (rows.map fraction) = final - entering := by + induction rows generalizing entering with + | nil => + have same := Option.some.inj accepted + change (0 : Extension) = final - entering + rw [same] + grind + | cons row rows ih => + obtain ⟨checked, tail⟩ := (checkRows_cons _ _ _ _ _).mp accepted + have head := rowIdentity row List.mem_cons_self entering checked + have rest := ih tail (fun item member => rowIdentity item (List.mem_cons_of_mem _ member)) + change fraction row + LogUp.sum (rows.map fraction) = final - entering + rw [head, rest] + grind + +theorem verify_true_iff (challenges : Challenges) (claims : List (List G)) (rows : List ProofShape.Row) : + verify challenges claims rows = some true ↔ rows ≠ [] ∧ + ∃ entering, initialAccumulator challenges claims = some entering ∧ checkRows challenges rows entering = some 0 := by + unfold verify + cases rows with + | nil => simp only [List.isEmpty_nil, if_true, reduceCtorEq, ne_eq, not_true_eq_false, false_and] + | cons row rows => + simp only [List.isEmpty_cons, Bool.false_eq_true, if_false, bind, pure, + Option.bind_eq_some_iff, Option.some.injEq, beq_iff_eq, ne_eq, reduceCtorEq, not_false_eq_true, true_and] + constructor + · rintro ⟨entering, initial, final, checked, rfl⟩; exact ⟨entering, initial, checked⟩ + · rintro ⟨entering, initial, checked⟩; exact ⟨entering, initial, 0, checked, rfl⟩ + +theorem verify_lookup_balance {challenges : Challenges} {claims : List (List G)} {rows : List ProofShape.Row} + (accepted : verify challenges claims rows = some true) (fraction : ProofShape.Row → Extension) + (rowIdentity : ∀ row ∈ rows, ∀ before, check challenges row before = some true → + fraction row = row.accumulator - before) : + LogUp.lookupFractions (Coordinates.fromExtension challenges.beta) (Coordinates.fromExtension challenges.gamma) + (claims.map fun claim => (1, claim)) + LogUp.sum (rows.map fraction) = 0 := by + obtain ⟨_, entering, initial, checked⟩ := (verify_true_iff _ _ _).mp accepted + rw [checkRows_sum checked fraction rowIdentity, ← initialAccumulator_lookupFractions initial] + grind + +theorem verify_row {challenges : Challenges} {claims : List (List G)} {rows : List ProofShape.Row} + (accepted : verify challenges claims rows = some true) {position : Nat} {row : ProofShape.Row} + (present : rows[position]? = some row) : + ∃ initial before result, + initialAccumulator challenges claims = some initial ∧ + (initial :: rows.map (·.accumulator))[position]? = some before ∧ + evaluate challenges row before = some result ∧ + Quotient.composition challenges.alpha result.constraints = + Domain.vanishing result.domain challenges.zeta * result.quotientValue := by + obtain ⟨_, initial, initialRead, checked⟩ := (verify_true_iff _ _ _).mp accepted + obtain ⟨before, beforeRead, rowChecked⟩ := checkRows_row checked present + obtain ⟨result, evaluated, identity⟩ := (check_true_iff _ _ _).mp rowChecked + exact ⟨initial, before, result, initialRead, beforeRead, evaluated, identity⟩ + +end Aiur.NativeAIR.VerifierArithmetic + +namespace Aiur.BoundVerifier +open NativeAIR +open NativeAIR.VerifierArithmetic + +/-- Every arithmetic-accepted active opening is tied to its actual key, +proof position, entering accumulator and unfolded graph expressions. -/ +theorem CompiledBackend.checked_row_values {selection : Selection} (backend : CompiledBackend selection) + {bytes : ByteArray} (checked : CheckedProof backend.keyData bytes) {challenges : Challenges} + {claims : List (List G)} (accepted : VerifierArithmetic.verify challenges claims checked.rows = some true) + {position : Nat} {row : ProofShape.Row} (present : checked.rows[position]? = some row) : + row.Sourced backend.keyData checked.data row.circuitIndex position ∧ row.Fits backend.keyData.parameters ∧ + ∃ initial before result trees lookups coordinates, + initialAccumulator challenges claims = some initial ∧ + (initial :: checked.rows.map (·.accumulator))[position]? = some before ∧ + evaluate challenges row before = some result ∧ row.circuit.graph.unfold = some trees ∧ + evalRoots ProofCodec.Extension.evalOps (view challenges row before result.selectors) + trees row.circuit.graph.zeros = some result.userValues ∧ + row.circuit.graph.lookups.mapM + (evalLookup ProofCodec.Extension.evalOps (view challenges row before result.selectors) trees) = some lookups ∧ + LogUp.equations lookups (rowColumns row .stage2 .current) (rowColumns row .stage2 .next) + (publics challenges before row.accumulator) (deltaScaled result.domain before row.accumulator) + result.selectors.isLast row.circuit.lookupGroupSize = some coordinates ∧ + result.lookupValues = LogUp.Coordinates.flatten coordinates ∧ + Quotient.composition challenges.alpha result.constraints = + Domain.vanishing result.domain challenges.zeta * result.quotientValue := by + obtain ⟨_, sourced, fits⟩ := checked.row present + obtain ⟨initial, before, result, initialRead, beforeRead, evaluated, identity⟩ := verify_row accepted present + have valid := backend.toBackend.key_graph_valid (List.mem_of_getElem? sourced.circuit) + obtain ⟨trees, lookups, coordinates, unfolded, _, roots, lookupValues, equations, equal⟩ := + evaluate_reflects evaluated valid + exact ⟨sourced, fits, initial, before, result, trees, lookups, coordinates, initialRead, beforeRead, + evaluated, unfolded, roots, lookupValues, equations, equal, identity⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/VerifierArithmetic.lean b/Ix/Aiur/Proofs/VerifierArithmetic.lean new file mode 100644 index 000000000..c7fef666d --- /dev/null +++ b/Ix/Aiur/Proofs/VerifierArithmetic.lean @@ -0,0 +1,173 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OpeningShape +import Ix.Aiur.Proofs.Quotient + +/-! The complete opened-row arithmetic check has defined reads on a shaped +row from the selected compiled key. Acceptance reflects the graph's unfolded +expressions and the quotient identity at the supplied challenge. It does +not by itself imply individual constraints vanish on the trace domain. +-/ + +namespace Aiur.NativeAIR.VerifierArithmetic +open ProofCodec (Extension) + +structure Evaluation.Reads (challenges : Challenges) (row : ProofShape.Row) (entering : Extension) + (result : Evaluation) : Prop where + domain : Domain.ofLogSize row.logDegree.toNat = some result.domain + selectors : Domain.selectors result.domain challenges.zeta = some result.selectors + nodes : row.circuit.graph.sweep Extension.evalOps (view challenges row entering result.selectors) = some result.nodeValues + user : readNodes result.nodeValues row.circuit.graph.zeros = some result.userValues + lookup : LogUp.constraintValues row.circuit.graph.lookups result.nodeValues + (rowColumns row .stage2 .current) (rowColumns row .stage2 .next) + (publics challenges entering row.accumulator) (deltaScaled result.domain entering row.accumulator) + result.selectors.isLast row.circuit.lookupGroupSize = some result.lookupValues + quotient : Quotient.evaluate result.domain challenges.zeta row.quotient = some result.quotientValue + +theorem evaluate_success {challenges : Challenges} {row : ProofShape.Row} {entering : Extension} + {result : Evaluation} (accepted : evaluate challenges row entering = some result) : + result.Reads challenges row entering := by + simp only [evaluate, bind, pure, Option.bind_eq_some_iff, Option.some.injEq] at accepted + obtain ⟨domain, hd, selectors, hs, nodes, hn, user, hu, lookup, hl, quotient, hq, rfl⟩ := accepted + exact ⟨hd, hs, hn, hu, hl, hq⟩ + +theorem Evaluation.Reads.evaluate {challenges : Challenges} {row : ProofShape.Row} {entering : Extension} + {result : Evaluation} (reads : result.Reads challenges row entering) : + evaluate challenges row entering = some result := by + simp only [VerifierArithmetic.evaluate, bind, pure, Option.bind_eq_some_iff, Option.some.injEq] + exact ⟨result.domain, reads.domain, result.selectors, reads.selectors, result.nodeValues, reads.nodes, + result.userValues, reads.user, result.lookupValues, reads.lookup, result.quotientValue, reads.quotient, rfl⟩ + +theorem evaluate_defined {parameters : KeyCodec.Parameters} {row : ProofShape.Row} + (fits : row.Fits parameters) (valid : row.circuit.valid = true) + (absent : row.preprocessed = none → row.circuit.preprocessedWidth = 0) + (challenges : Challenges) (entering : Extension) {domain : Domain.Subgroup} + (domainRead : Domain.ofLogSize row.logDegree.toNat = some domain) + (nonzero : Domain.vanishing domain challenges.zeta ≠ 0) : + ∃ result, evaluate challenges row entering = some result := by + obtain ⟨positive, bounded, graphValid, _⟩ := KeyCodec.Circuit.valid_graph valid + obtain ⟨selectors, selectorsRead⟩ := Domain.selectors_defined domain challenges.zeta nonzero + let values := view challenges row entering selectors + obtain ⟨nodes, swept, length⟩ := graphValid.sweep_defined Extension.evalOps values + (view_fits fits absent challenges entering selectors) + obtain ⟨user, userRead, _⟩ := readNodes_defined nodes row.circuit.graph.zeros (by + intro index member; rw [length]; exact graphValid.zeros index member) + have widths := stage2_width fits positive + obtain ⟨lookup, lookupRead⟩ := LogUp.constraintValues_defined row.circuit.graph.lookups nodes + (rowColumns row .stage2 .current) (rowColumns row .stage2 .next) + (publics challenges entering row.accumulator) (deltaScaled domain entering row.accumulator) + selectors.isLast row.circuit.lookupGroupSize bounded + (by intro lookup member index root + rw [length] + exact graphValid.lookups index (List.mem_flatMap.mpr ⟨lookup, member, root⟩)) + widths.1 widths.2 (by rw [publics_size]; decide) (by rw [deltaScaled_size]; decide) + obtain ⟨coefficients, coefficientRead⟩ := Quotient.coefficients_defined row.quotient (by rw [fits.quotient]; omega) + refine ⟨⟨domain, selectors, nodes, user, lookup, Quotient.horner (challenges.zeta.power (Domain.size domain)) coefficients⟩, + Evaluation.Reads.evaluate ⟨domainRead, selectorsRead, swept, userRead, lookupRead, ?_⟩⟩ + simp only [Quotient.evaluate, coefficientRead, bind, pure, Option.bind_some] + +theorem evaluate_defined_iff {parameters : KeyCodec.Parameters} {row : ProofShape.Row} + (fits : row.Fits parameters) (valid : row.circuit.valid = true) + (absent : row.preprocessed = none → row.circuit.preprocessedWidth = 0) + (challenges : Challenges) (entering : Extension) : + (∃ result, evaluate challenges row entering = some result) ↔ + ∃ domain, Domain.ofLogSize row.logDegree.toNat = some domain ∧ Domain.vanishing domain challenges.zeta ≠ 0 := by + constructor + · rintro ⟨result, evaluated⟩ + have reads := evaluate_success evaluated + exact ⟨result.domain, reads.domain, (Domain.selectors_defined_iff _ _).mp ⟨result.selectors, reads.selectors⟩⟩ + · rintro ⟨domain, read, nonzero⟩ + exact evaluate_defined fits valid absent challenges entering read nonzero + +theorem evaluate_constraint_count {challenges : Challenges} {row : ProofShape.Row} {entering : Extension} + {result : Evaluation} (accepted : evaluate challenges row entering = some result) + (positive : 0 < row.circuit.lookupGroupSize) : + result.constraints.length = row.circuit.constraintCount := by + have reads := evaluate_success accepted + have user := Bytecode.AIR.list_mapM_some_length _ _ _ reads.user + have lookup := LogUp.constraintValues_length reads.lookup + simp only [Evaluation.constraints, List.length_append, KeyCodec.Circuit.constraintCount, + user, lookup, LogUp.groupCount_key row.circuit positive] + omega + +theorem evaluate_reflects {challenges : Challenges} {row : ProofShape.Row} {entering : Extension} + {result : Evaluation} (accepted : evaluate challenges row entering = some result) + (valid : row.circuit.graph.Valid row.circuit.widths) : + ∃ trees lookups coordinates, + row.circuit.graph.unfold = some trees ∧ + Reflects Extension.evalOps (view challenges row entering result.selectors) trees result.nodeValues ∧ + evalRoots Extension.evalOps (view challenges row entering result.selectors) trees row.circuit.graph.zeros = + some result.userValues ∧ + row.circuit.graph.lookups.mapM (evalLookup Extension.evalOps (view challenges row entering result.selectors) trees) = + some lookups ∧ + LogUp.equations lookups (rowColumns row .stage2 .current) (rowColumns row .stage2 .next) + (publics challenges entering row.accumulator) (deltaScaled result.domain entering row.accumulator) + result.selectors.isLast row.circuit.lookupGroupSize = some coordinates ∧ + result.lookupValues = LogUp.Coordinates.flatten coordinates := by + have reads := evaluate_success accepted + obtain ⟨trees, unfolded, _⟩ := valid.unfold_defined + have reflected := row.circuit.graph.sweep_reflects Extension.evalOps _ unfolded reads.nodes + obtain ⟨lookups, coordinates, lookupRead, equationsRead, equal⟩ := LogUp.constraintValues_success reads.lookup + have same : readLookup result.nodeValues = + evalLookup Extension.evalOps (view challenges row entering result.selectors) trees := + funext reflected.readLookup + exact ⟨trees, lookups, coordinates, unfolded, reflected, + (reflected.readNodes _).symm.trans reads.user, same ▸ lookupRead, equationsRead, equal⟩ + +theorem Evaluation.Reads.identity {challenges : Challenges} {row : ProofShape.Row} {entering : Extension} + {result : Evaluation} (reads : result.Reads challenges row entering) : + result.accepts challenges.alpha = true ↔ + Quotient.composition challenges.alpha result.constraints = + Domain.vanishing result.domain challenges.zeta * result.quotientValue := by + have invert := (Domain.selectors_success _ _ _ reads.selectors).2.2.2 + simp only [Evaluation.accepts, beq_iff_eq] + exact Quotient.inverse_check _ _ _ _ invert + +theorem check_true_iff (challenges : Challenges) (row : ProofShape.Row) (entering : Extension) : + check challenges row entering = some true ↔ + ∃ result, evaluate challenges row entering = some result ∧ + Quotient.composition challenges.alpha result.constraints = + Domain.vanishing result.domain challenges.zeta * result.quotientValue := by + simp only [check, bind, pure, Option.bind_eq_some_iff, Option.some.injEq] + constructor + · rintro ⟨result, read, accepted⟩ + exact ⟨result, read, (evaluate_success read).identity.mp accepted⟩ + · rintro ⟨result, read, identity⟩ + exact ⟨result, read, (evaluate_success read).identity.mpr identity⟩ + +theorem check_quotient {challenges : Challenges} {row : ProofShape.Row} {entering : Extension} + {result : Evaluation} (evaluated : evaluate challenges row entering = some result) : + check challenges row entering = + Quotient.check result.domain challenges.zeta challenges.alpha result.constraints row.quotient := by + have reads := evaluate_success evaluated + simp only [check, evaluated, Quotient.check, reads.selectors, reads.quotient, Evaluation.accepts, + bind, pure, Option.bind_some] + +end Aiur.NativeAIR.VerifierArithmetic + +namespace Aiur.BoundVerifier +open NativeAIR + +theorem CompiledBackend.checked_row_arithmetic {selection : Selection} (backend : CompiledBackend selection) + {bytes : ByteArray} (checked : CheckedProof backend.keyData bytes) {position : Nat} {row : ProofShape.Row} + (present : checked.rows[position]? = some row) + (challenges : VerifierArithmetic.Challenges) (entering : ProofCodec.Extension) : + ∃ domain, Domain.ofLogSize row.logDegree.toNat = some domain ∧ + ((∃ result, VerifierArithmetic.evaluate challenges row entering = some result) ↔ + Domain.vanishing domain challenges.zeta ≠ 0) := by + obtain ⟨_, sourced, fits⟩ := checked.row present + obtain ⟨domain, domainRead⟩ := VerifierArithmetic.domain_defined fits + have valid := (KeyCodec.decode_valid backend.toBackend.key_decodes).1 row.circuit + (List.mem_of_getElem? sourced.circuit) + refine ⟨domain, domainRead, ?_⟩ + rw [VerifierArithmetic.evaluate_defined_iff fits valid (backend.row_preprocessed_absent sourced)] + constructor + · rintro ⟨other, otherRead, nonzero⟩ + cases Option.some.inj (domainRead.symm.trans otherRead) + exact nonzero + · intro nonzero; exact ⟨domain, domainRead, nonzero⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/PrunedMerkle.lean b/Ix/Aiur/PrunedMerkle.lean new file mode 100644 index 000000000..932198dcc --- /dev/null +++ b/Ix/Aiur/PrunedMerkle.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Merkle + +/-! Binary shared MMCS replay. The verifier-selected indices determine the +sorted frontier and the exact boundary proof length. Logs survive rejection: +native group-consistency checks can fail after earlier hashes in the layer. +Reconstructed individual paths are retained for authentication proofs. +-/ + +namespace Aiur.NativeAIR.PrunedMerkle + +open Merkle (Digest Hash Dimensions) + +structure Logged (α : Type) where + result : Option α + inputs : List (List UInt8) + deriving DecidableEq, Repr + +def Logged.pure (value : α) : Logged α := ⟨some value, []⟩ + +def Logged.bind (first : Logged α) (next : α → Logged β) : Logged β := + match first.result with + | none => ⟨none, first.inputs⟩ + | some value => + let rest := next value + ⟨rest.result, first.inputs ++ rest.inputs⟩ + +instance : Monad Logged where + pure := Logged.pure + bind := Logged.bind + +def reject : Logged α := ⟨none, []⟩ + +def ofOption (value : Option α) : Logged α := ⟨value, []⟩ + +def hashInput (hash : Hash) (input : List UInt8) : Logged Digest := ⟨some (hash input), [input]⟩ + +structure Ticket where + index : Nat + rows : List (List G) + proof : List Digest + deriving DecidableEq, Repr + +def Ticket.extend (sibling : Digest) (ticket : Ticket) : Ticket := + { ticket with proof := ticket.proof ++ [sibling] } + +structure Node where + index : Nat + digest : Digest + tickets : List Ticket + deriving DecidableEq, Repr + +def uniqueIndices (indices : List Nat) : List Nat := (indices.mergeSort (· ≤ ·)).eraseDups + +def parentIndices (indices : List Nat) : List Nat := (indices.map (· / 2)).eraseDups + +/-- Each binary parent has two children; only uncovered children are sent. -/ +def boundaryCount : Nat → List Nat → Nat + | 0, _ => 0 + | steps + 1, indices => + let parents := parentIndices indices + (2 * parents.length - indices.length) + boundaryCount steps parents + +def representatives (indices : List Nat) (rows : List (List (List G))) : Option (List Ticket) := + let originals := indices.zip rows + (uniqueIndices indices).mapM fun index => do + let (_, values) ← originals.find? fun entry => entry.1 == index + if originals.all (fun entry => entry.1 != index || entry.2 == values) then + some ⟨index, values, []⟩ + else none + +def initial (hash : Hash) (dimensions : List Dimensions) (height : Nat) : List Ticket → Logged (List Node) + | [] => pure [] + | ticket :: tickets => do + let digest ← hashInput hash (Merkle.rowBytes dimensions ticket.rows height) + let rest ← initial hash dimensions height tickets + return ⟨ticket.index, digest, [ticket]⟩ :: rest + +/-- Pair every parent before injecting any shorter rows at this layer. -/ +def combine (hash : Hash) : List Node → List Digest → Logged (List Node × List Digest) + | [], proof => pure ([], proof) + | first :: rest, proof => + match rest with + | second :: tail => + if first.index % 2 = 0 ∧ second.index = first.index + 1 then do + let digest ← hashInput hash (Merkle.pairBytes first.digest second.digest) + let (nodes, remaining) ← combine hash tail proof + let tickets := first.tickets.map (Ticket.extend second.digest) ++ + second.tickets.map (Ticket.extend first.digest) + return (⟨first.index / 2, digest, tickets⟩ :: nodes, remaining) + else do + let sibling :: remaining := proof | reject + let digest ← hashInput hash (Merkle.branchBytes first.index first.digest sibling) + let (nodes, remaining) ← combine hash rest remaining + return (⟨first.index / 2, digest, first.tickets.map (Ticket.extend sibling)⟩ :: nodes, remaining) + | [] => do + let sibling :: remaining := proof | reject + let digest ← hashInput hash (Merkle.branchBytes first.index first.digest sibling) + return ([⟨first.index / 2, digest, first.tickets.map (Ticket.extend sibling)⟩], remaining) + +def inject (hash : Hash) (dimensions : List Dimensions) (height : Nat) : List Node → Logged (List Node) + | [] => pure [] + | node :: nodes => do + let lead :: members := node.tickets | reject + if !(members.all fun ticket => + Merkle.rowsAt dimensions ticket.rows height == Merkle.rowsAt dimensions lead.rows height) then reject + else + let leaf ← hashInput hash (Merkle.rowBytes dimensions lead.rows height) + let digest ← hashInput hash (Merkle.pairBytes node.digest leaf) + let rest ← inject hash dimensions height nodes + return { node with digest } :: rest + +def walk (hash : Hash) (dimensions : List Dimensions) : + Nat → Nat → List Node → List Digest → Logged (List Node × List Digest) + | 0, _, nodes, proof => pure (nodes, proof) + | steps + 1, height, nodes, proof => do + let (parents, remaining) ← combine hash nodes proof + let next ← if Merkle.hasHeight dimensions (height - 1) then + inject hash dimensions (height - 1) parents else pure parents + walk hash dimensions steps (height - 1) next remaining + +def replay (hash : Hash) (dimensions : List Dimensions) (capHeight : Nat) + (indices : List Nat) (rows : List (List (List G))) (proof : List Digest) : Logged (List Node) := do + if dimensions.isEmpty || rows.length != indices.length then reject + else + let height := Merkle.maxHeight dimensions + let steps := height - capHeight + if !(indices.all fun index => index < 2^height) then reject + else + let tickets ← ofOption (representatives indices rows) + if proof.length != boundaryCount steps (uniqueIndices indices) || + !(tickets.all fun ticket => Merkle.shape dimensions ticket.rows) then reject + else + let leaves ← initial hash dimensions height tickets + let (nodes, remaining) ← walk hash dimensions steps height leaves proof + if remaining.isEmpty then pure nodes else reject + +def accepts (cap : List Digest) (nodes : List Node) : Bool := + nodes.all fun node => cap[node.index]? == some node.digest + +def verify (hash : Hash) (dimensions : List Dimensions) (capHeight : Nat) + (indices : List Nat) (cap : List Digest) (rows : List (List (List G))) (proof : List Digest) : Bool := + match (replay hash dimensions capHeight indices rows proof).result with + | none => false + | some nodes => accepts cap nodes + +def verifyCovered (hash : Hash) (dimensions : List Dimensions) (capHeight : Nat) + (indices : List Nat) (cap : List Digest) (rows : List (List (List G))) (proof : List Digest) : Bool := + Merkle.covered dimensions capHeight && verify hash dimensions capHeight indices cap rows proof + +end Aiur.NativeAIR.PrunedMerkle diff --git a/Ix/Aiur/Quotient.lean b/Ix/Aiur/Quotient.lean new file mode 100644 index 000000000..2b20f627d --- /dev/null +++ b/Ix/Aiur/Quotient.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Domain + +/-! The native composition fold and quotient coefficient recombination. +Each quotient slice combines two challenge-field values with the native +extension basis. An odd number of coordinates or a selector pole is rejected. +-/ + +namespace Aiur.NativeAIR.Quotient + +open ProofCodec (Extension) + +def horner [OfNat W 0] [Add W] [Mul W] (point : W) (coefficients : List W) : W := + coefficients.foldr (fun coefficient rest => coefficient + point * rest) 0 + +def composition [OfNat W 0] [Add W] [Mul W] (alpha : W) (constraints : List W) : W := + constraints.foldl (fun accumulated value => accumulated * alpha + value) 0 + +def coefficients : List Extension → Option (List Extension) + | [] => some [] + | [_] => none + | first :: second :: rest => return (first + second * Extension.basis) :: (← coefficients rest) + +def evaluate (domain : Domain.Subgroup) (point : Extension) (row : List Extension) : Option Extension := do + return horner (point.power (Domain.size domain)) (← coefficients row) + +def check (domain : Domain.Subgroup) (point alpha : Extension) + (constraints row : List Extension) : Option Bool := do + let selected ← Domain.selectors domain point + let quotient ← evaluate domain point row + return composition alpha constraints * selected.invVanishing == quotient + +end Aiur.NativeAIR.Quotient diff --git a/Ix/Aiur/RowCounts.lean b/Ix/Aiur/RowCounts.lean new file mode 100644 index 000000000..81e888c73 --- /dev/null +++ b/Ix/Aiur/RowCounts.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +module +public import Ix.Aiur.Stages.Bytecode + +/-! Total control counts and circuit checks independent of witness values. +These checks bound branch/terminal counts and the number of raw return writers. +Physical columns, lookup cursors and value indices remain separate. -/ + +public section +@[expose] section + +namespace Aiur.Bytecode + +/-- Counts of control nodes, allocated leaf selectors, returns and escaping +yields. Consumed yields still allocate selectors. -/ +structure ControlCounts where + nodes : Nat + leaves : Nat + returns : Nat + yields : Nat + deriving Repr, DecidableEq + +def ControlCounts.sum (items : List ControlCounts) : ControlCounts := + ⟨(items.map (·.nodes)).sum, (items.map (·.leaves)).sum, + (items.map (·.returns)).sum, (items.map (·.yields)).sum⟩ + +def ControlCounts.branch (items : List ControlCounts) : ControlCounts := + { sum items with nodes := (sum items).nodes + 1 } + +def ControlCounts.continue (branches continuation : ControlCounts) : ControlCounts := + ⟨branches.nodes + continuation.nodes, branches.leaves + continuation.leaves, + branches.returns + continuation.returns, continuation.yields⟩ + +private theorem counts_block_smaller (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +def Ctrl.controlCounts : Ctrl → ControlCounts + | .return .. => ⟨1, 1, 1, 0⟩ + | .yield .. => ⟨1, 1, 0, 1⟩ + | .match _ branches fallback => ControlCounts.branch ( + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.controlCounts) ++ + (match fallback with | none => [] | some block => [block.controlCounts])) + | .matchContinue _ branches fallback _ _ _ continuation => (ControlCounts.branch ( + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.controlCounts) ++ + (match fallback with | none => [] | some block => [block.controlCounts]))).continue + continuation.controlCounts +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) + +def Block.controlCounts (block : Block) : ControlCounts := block.ctrl.controlCounts +termination_by sizeOf block +decreasing_by exact counts_block_smaller block + +end + +def branchControlCounts (branches : Array (G × Block)) (fallback : Option Block) : List ControlCounts := + branches.toList.map (fun pair => pair.2.controlCounts) ++ + fallback.toList.map (fun block => block.controlCounts) + +/-- Syntax-only count checks for the functions actually named by a circuit. +The allocated selector count bounds all return/yield leaves, including yields +consumed by continuations. Other layout and value-index checks are separate. -/ +def Circuit.validateRowCounts (program : Toplevel) (circuit : Circuit) : Bool := + circuit.members.size < gSize.toNat && + match circuit.members.toList.mapM (fun index => program.functions[index]?) with + | none => false + | some functions => + functions.all (fun function => function.body.controlCounts.nodes < gSize.toNat) && + (functions.map (fun function => function.body.controlCounts.leaves)).sum ≤ circuit.layout.selectors + +def Toplevel.validateRowCounts (program : Toplevel) : Bool := + program.circuits.all (Circuit.validateRowCounts program) + +theorem Ctrl.controlCounts_match (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).controlCounts = + ControlCounts.branch (branchControlCounts branches fallback) := by + rw [Ctrl.controlCounts.eq_def] + simp only [branchControlCounts, Array.toList_attach] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.controlCounts)] + cases fallback <;> rfl + +theorem Ctrl.controlCounts_matchContinue (index : ValIdx) (branches : Array (G × Block)) + (fallback : Option Block) (outputs aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).controlCounts = + (ControlCounts.branch (branchControlCounts branches fallback)).continue continuation.controlCounts := by + rw [Ctrl.controlCounts.eq_def] + simp only [branchControlCounts, Array.toList_attach] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.controlCounts)] + cases fallback <;> rfl + +end Aiur.Bytecode + +end +end diff --git a/Ix/Aiur/Semantics/AIR.lean b/Ix/Aiur/Semantics/AIR.lean new file mode 100644 index 000000000..f3acc5df8 --- /dev/null +++ b/Ix/Aiur/Semantics/AIR.lean @@ -0,0 +1,214 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +module +public import Ix.Aiur.Stages.Bytecode + +/-! +Relational bytecode semantics for AIR extraction. + +Each local execution records its constrained call requests. Advice is chosen +at each operation, including I/O reads and unconstrained calls. I/O writes, +key insertion and debugging impose no relation, as in the native constraint +emitter. Memory is a shared relation between width, pointer and contents; +its functionality is a separate memory-table obligation. + +`Execution` closes local executions into finite call derivations. It neither +replays the runtime cache nor identifies advice with native hint results. +Proving that arbitrary native AIR rows have these local semantics, and that +the selected certified program checks the advice it needs, remain obligations. +-/ + +public section +@[expose] section + +namespace Aiur.Bytecode.AIR + +/-- Immutable memory facts supplied by the memory tables. -/ +abbrev Memory := Nat → G → Array G → Prop + +/-- A full function lookup, before channel encoding or compression. -/ +structure Call where + function : FunIdx + inputs : Array G + outputs : Array G + rank : G + deriving DecidableEq + +/-- Read all indexed values, rejecting an invalid index. -/ +def readValues (values : Array G) (indices : Array ValIdx) : Option (Array G) := + indices.mapM fun index => values[index]? + +/-- Little-endian packing as field arithmetic. The caller checks length four. -/ +def packWord (bytes : Array G) : G := + bytes.toList.zipIdx.foldl (fun value (byte, index) => + value + byte * G.ofNat (256 ^ index)) 0 + +def adviceOfSize (size : Nat) (advice : Array G) : Option (Array G) := + if advice.size = size then some advice else none + +def unaryByte (values : Array G) (index : ValIdx) + (compute : G → Array G) : Option (Array G) := do + let value ← values[index]? + if value.n < 256 then some (compute value) else none + +def binaryByte (values : Array G) (left right : ValIdx) + (compute : G → G → Array G) : Option (Array G) := do + let x ← values[left]? + let y ← values[right]? + if x.n < 256 ∧ y.n < 256 then some (compute x y) else none + +def pairValues (pair : G × G) : Array G := #[pair.1, pair.2] + +def readWord (values : Array G) (indices : Array ValIdx) : Option G := do + if indices.size ≠ 4 then none else do + let bytes ← readValues values indices + some (packWord bytes) + +/-- Local operation outputs. Calls constrained by function lookups and +memory operations have separate `Step` constructors. All other constructors +are covered here, including the virtual carry of an unconstrained u32 sum. +Byte gadgets require their table input ranges; advice bytes do not. -/ +def primitive (op : Op) (values advice : Array G) : Option (Array G) := + match op with + | .const value => some #[value] + | .add a b => do return #[(← values[a]?) + (← values[b]?)] + | .sub a b => do return #[(← values[a]?) - (← values[b]?)] + | .mul a b => do return #[(← values[a]?) * (← values[b]?)] + | .eqZero a => do return #[G.eqZero (← values[a]?)] + | .call _ _ outputSize true => adviceOfSize outputSize advice + | .call _ _ _ false | .store _ | .load _ _ => none + | .assertEq xs ys _ => do + let left ← readValues values xs + let right ← readValues values ys + if left = right then some #[] else none + | .ioGetInfo _ _ => adviceOfSize 2 advice + | .ioRead _ _ size => adviceOfSize size advice + | .ioSetInfo _ _ _ _ | .ioWrite _ _ | .debug _ _ => some #[] + | .u8BitDecomposition a => unaryByte values a (Array.ofFn ∘ G.u8BitDecomposition) + | .u8ShiftLeft a => unaryByte values a fun x => #[G.u8ShiftLeft x] + | .u8ShiftRight a => unaryByte values a fun x => #[G.u8ShiftRight x] + | .u8Xor a b => binaryByte values a b fun x y => #[G.u8Xor x y] + | .u8Add a b => binaryByte values a b fun x y => pairValues (G.u8Add x y) + | .u8Mul a b => binaryByte values a b fun x y => pairValues (G.u8Mul x y) + | .u8Sub a b => binaryByte values a b fun x y => pairValues (G.u8Sub x y) + | .u8And a b => binaryByte values a b fun x y => #[G.u8And x y] + | .u8Or a b => binaryByte values a b fun x y => #[G.u8Or x y] + | .u8LessThan a b => binaryByte values a b fun x y => #[G.u8LessThan x y] + | .u8XorSplit7 a b => binaryByte values a b fun x y => + let z := x.n ^^^ y.n + #[G.ofNat (z / 128), G.ofNat ((z * 2) % 256)] + | .u8XorSplit4 a b => binaryByte values a b fun x y => + let z := x.n ^^^ y.n + #[G.ofNat (z / 16), G.ofNat ((z * 16) % 256)] + | .u8RangeCheck a b => binaryByte values a b fun _ _ => #[] + | .u32LessThan a b => do + let x ← values[a]? + let y ← values[b]? + if x.n < 2 ^ 32 ∧ y.n < 2 ^ 32 then some #[G.u32LessThan x y] else none + | .unconstrainedBigUintDivMod _ _ => adviceOfSize 2 advice + | .unconstrainedGToBytes _ => adviceOfSize 8 advice + | .unconstrainedGInverse _ => adviceOfSize 1 advice + | .unconstrainedU32Add a b => do + let x ← readWord values a + let y ← readWord values b + let bytes ← adviceOfSize 4 advice + return bytes.push ((x + y - packWord bytes) * 0xfffffffe00000002) + | .unconstrainedU32Add3 a b c => do + let x ← readWord values a + let y ← readWord values b + let z ← readWord values c + let bytes ← adviceOfSize 4 advice + return bytes.push ((x + y + z - packWord bytes) * 0xfffffffe00000002) + | .u32ToField bytes => do return #[← readWord values bytes] + +/-- One operation, with the constrained calls it requests. Advice is local +to this occurrence, even when the same operation appears in another row. -/ +inductive Step (memory : Memory) : Op → Array G → Array G → List Call → Prop + | primitive (evaluated : primitive op values advice = some outputs) : + Step memory op values (values ++ outputs) [] + | call (arguments : readValues values indices = some request.inputs) + (outputSize : request.outputs.size = size) : + Step memory (.call request.function indices size false) values + (values ++ request.outputs) [request] + | store (arguments : readValues values indices = some contents) + (stored : memory contents.size pointer contents) : + Step memory (.store indices) values (values.push pointer) [] + | load (address : values[index]? = some pointer) + (width : contents.size = size) (loaded : memory size pointer contents) : + Step memory (.load size index) values (values ++ contents) [] + +inductive RunOps (memory : Memory) : List Op → Array G → Array G → List Call → Prop + | nil : RunOps memory [] values values [] + | cons (first : Step memory op values intermediate firstCalls) + (rest : RunOps memory ops intermediate finalValues restCalls) : + RunOps memory (op :: ops) values finalValues (firstCalls ++ restCalls) + +/-- Returns escape the function; yields enter the nearest continuation. -/ +inductive Outcome where + | returned : Array G → Outcome + | yielded : Array G → Outcome + +/-- A matching branch, or the default when no discriminant matches. +Duplicate case keys remain nondeterministic here, as permitted by the +selector equations; compiler uniqueness is a separate obligation. -/ +inductive SelectArm (scrutinee : G) (cases : Array (G × Block)) + (fallback : Option Block) : Block → Prop + | case (member : (scrutinee, block) ∈ cases.toList) : + SelectArm scrutinee cases fallback block + | fallback (selected : fallback = some block) + (unmatched : ∀ pair ∈ cases.toList, pair.1 ≠ scrutinee) : + SelectArm scrutinee cases fallback block + +mutual + +inductive RunBlock (memory : Memory) : Block → Array G → Outcome → List Call → Prop + | block (operations : RunOps memory block.ops.toList values intermediate opCalls) + (control : RunCtrl memory block.ctrl intermediate outcome ctrlCalls) : + RunBlock memory block values outcome (opCalls ++ ctrlCalls) + +inductive RunCtrl (memory : Memory) : Ctrl → Array G → Outcome → List Call → Prop + | returned (result : readValues values indices = some outputs) : + RunCtrl memory (.return selector indices) values (.returned outputs) [] + | yielded (result : readValues values indices = some outputs) : + RunCtrl memory (.yield selector indices) values (.yielded outputs) [] + | match (value : values[index]? = some scrutinee) + (selected : SelectArm scrutinee cases fallback arm) + (branch : RunBlock memory arm values outcome calls) : + RunCtrl memory (.match index cases fallback) values outcome calls + | matchContinueReturn (value : values[index]? = some scrutinee) + (selected : SelectArm scrutinee cases fallback arm) + (branch : RunBlock memory arm values (.returned outputs) calls) : + RunCtrl memory (.matchContinue index cases fallback size aux lookups continuation) + values (.returned outputs) calls + | matchContinueYield (value : values[index]? = some scrutinee) + (selected : SelectArm scrutinee cases fallback arm) + (branch : RunBlock memory arm values (.yielded yielded) branchCalls) + (outputSize : yielded.size = size) + (continued : RunBlock memory continuation (values ++ yielded) outcome contCalls) : + RunCtrl memory (.matchContinue index cases fallback size aux lookups continuation) + values outcome (branchCalls ++ contCalls) + +end + +/-- Local meaning of one function row, before resolving its call requests. -/ +inductive RunFunction (program : Toplevel) (memory : Memory) : Call → List Call → Prop + | function (selected : program.functions[request.function]? = some function) + (arity : function.layout.inputSize = request.inputs.size) + (body : RunBlock memory function.body request.inputs (.returned request.outputs) calls) : + RunFunction program memory request calls + +/-- A finite derivation: every constrained call has its own finite derivation. +Rows may be reused by several callers. Advice and immutable memory facts are +retained by the local relations, without asserting sequential cache effects. -/ +inductive Execution (program : Toplevel) (memory : Memory) : Call → Prop + | function (row : RunFunction program memory request calls) + (children : ∀ child ∈ calls, Execution program memory child) : + Execution program memory request + +end Aiur.Bytecode.AIR + +end +end diff --git a/Ix/Aiur/Semantics/BytecodeEval.lean b/Ix/Aiur/Semantics/BytecodeEval.lean index 7656bcec9..987fc6c6f 100644 --- a/Ix/Aiur/Semantics/BytecodeEval.lean +++ b/Ix/Aiur/Semantics/BytecodeEval.lean @@ -6,17 +6,18 @@ public import Ix.IndexMap /-! Lean-native bytecode reference evaluator. -Mirrors `src/aiur/execute.rs` in big-step form: +Uncached big-step model of bytecode operations: - No `QueryRecord` (trace-side bookkeeping). - No call cache. -- No `unconstrained` branching (both branches of every `if unconstrained` produce - the same value; they differ only in whether a query is logged). +- No `unconstrained` branching or constrained promotion. - No stack machine — direct big-step. - Call-only fuel decrement at `Op.call`. - Errors return, never panic. -Per-width memory buckets mirror Rust's `QueryRecord.memory_queries` -(`execute.rs:36-40`). Each `Op.store values` uses `values.size` as the width key. +Runtime cache hits and promotion can change effect multiplicity. Relating this +model to native execution requires a separate refinement argument. Per-width +memory buckets mirror Rust's `QueryRecord.memory_queries`; each +`Op.store values` uses `values.size` as the width key. -/ public section diff --git a/Ix/Aiur/Semantics/Flatten.lean b/Ix/Aiur/Semantics/Flatten.lean index 81c643912..91344179c 100644 --- a/Ix/Aiur/Semantics/Flatten.lean +++ b/Ix/Aiur/Semantics/Flatten.lean @@ -26,12 +26,33 @@ inductive Value : Type where | array : Array Value → Value | ctor : Global → Array Value → Value | fn : Global → Value - /-- `width, index` — width is the flat size of the stored element's type. In the - Source-form evaluator only `index` is meaningful; in the Concrete-form - evaluator `width` selects the per-width memory bucket to match Rust's + /-- `width, index` — width selects the memory bucket and index selects an + entry within that bucket in both reference evaluators, matching Rust's `memory_queries`. -/ | pointer : (width : Nat) → (index : Nat) → Value - deriving Repr, Hashable, Inhabited + deriving Repr, Inhabited + +/-- Total structural hashing for reference-evaluator memory keys. Tags, +array seed and traversal order retain the original native derivation. -/ +def Value.hash : Value → UInt64 + | .unit => 0 + | .field g => mixHash 1 (Hashable.hash g) + | .tuple values => mixHash 2 (values.attach.foldl + (fun acc value => mixHash acc (Value.hash value.val)) 7) + | .array values => mixHash 3 (values.attach.foldl + (fun acc value => mixHash acc (Value.hash value.val)) 7) + | .ctor global values => mixHash (mixHash 4 (Hashable.hash global)) (values.attach.foldl + (fun acc value => mixHash acc (Value.hash value.val)) 7) + | .fn global => mixHash 5 (Hashable.hash global) + | .pointer width index => mixHash (mixHash 6 (Hashable.hash width)) (Hashable.hash index) +termination_by value => sizeOf value +decreasing_by + all_goals + have bound := Array.sizeOf_lt_of_mem value.property + simp_all + omega + +instance : Hashable Value := ⟨Value.hash⟩ deriving instance DecidableEq for Global diff --git a/Ix/Aiur/Semantics/SourceEval.lean b/Ix/Aiur/Semantics/SourceEval.lean index c0ce18fc6..198d84dd2 100644 --- a/Ix/Aiur/Semantics/SourceEval.lean +++ b/Ix/Aiur/Semantics/SourceEval.lean @@ -7,17 +7,18 @@ public import Ix.Aiur.Protocol Source-form reference evaluator — proof-bearing semantics on `Source.Term`. Design: -- **No cache.** The cache is a debug-interpreter optimization (`Ix/Aiur/Interpret.lean`) - and a Rust trace-multiplicity device, not part of the semantic model. +- **Uncached calls.** Runtime and interpreter cache hits can change the I/O of + repeated effectful calls. Relating this model to those engines requires a + separate refinement argument with explicit conditions on the program. - **No stack trace.** Errors are tagged; debugging is the debug interpreter's job. - **Fuel-indexed, call-only accounting.** `fuel : Nat` decrements only at `applyGlobal`. Intra-body recursion is structural. - **Errors return, never panic.** `ioSetInfo` on existing key, `ioRead` OOB, pattern failure, type mismatch, etc. all produce `Except.error`. -This source-level evaluator does not yet distinguish pointer widths — source -pointers are a single global store. The width-bucketed `Concrete.Eval` -evaluator fixes that divergence with Rust. +Memory uses width buckets computed by flattening source values. Relating +these widths to the concrete evaluator's type layouts remains a compiler +reflection obligation. -/ public section @@ -619,7 +620,11 @@ def interp (decls : Decls) (fuel : Nat) (bindings : Bindings) -- `toField` / `u8FromFieldUnsafe` are erased coercions: value unchanged. | .toField t | .u8FromFieldUnsafe t => interp decls fuel bindings t st | .u8Lit n => .ok (.field (G.ofNat n), st) - | .debug _ _ ret => interp decls fuel bindings ret st + | .debug _ none ret => interp decls fuel bindings ret st + | .debug _ (some value) ret => + match interp decls fuel bindings value st with + | .error error => .error error + | .ok (_, st') => interp decls fuel bindings ret st' | .ioGetInfo channel key => match interp decls fuel bindings channel st with | .error e => .error e diff --git a/Ix/Aiur/ShapedVerifier.lean b/Ix/Aiur/ShapedVerifier.lean new file mode 100644 index 000000000..5742474c9 --- /dev/null +++ b/Ix/Aiur/ShapedVerifier.lean @@ -0,0 +1,57 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.CompiledVerifier +import Ix.Aiur.ProofShape +import Ix.Aiur.MerkleCap + +/-! The selected compiled key determines proof framing, active opening +dimensions, fixed trace heights, cap coverage and the lookup budget before native +verification. This still delegates the transcript/PCS/AIR acceptance checks +to the existing FFI and does not instantiate a certified checker release. -/ + +namespace Aiur.BoundVerifier + +structure CheckedProof (key : NativeAIR.KeyCodec.Key) (bytes : ByteArray) where + data : NativeAIR.ProofCodec.Data + rows : List NativeAIR.ProofShape.Row + bound : Nat + decoded : NativeAIR.ProofCodec.decodeCanonical bytes = some data + shape : NativeAIR.ProofShape.check key data = some rows + fixed : NativeAIR.ProofShape.fixedHeights key data = true + budget : NativeAIR.ProofShape.queryBound key data = some bound + cap : NativeAIR.MerkleCap.check key data = true + +def readProof (key : NativeAIR.KeyCodec.Key) (bytes : ByteArray) : Except String (CheckedProof key bytes) := + match parsed : NativeAIR.ProofCodec.decodeCanonical bytes with + | none => .error "proof is not a canonical complete artifact" + | some data => + match shape : NativeAIR.ProofShape.check key data with + | none => .error "proof opening shape differs from the selected key" + | some rows => + if fixed : NativeAIR.ProofShape.fixedHeights key data = true then + match budget : NativeAIR.ProofShape.queryBound key data with + | none => .error "proof lookup budget exceeds its bound" + | some bound => + if cap : NativeAIR.MerkleCap.check key data = true then + .ok ⟨data, rows, bound, parsed, shape, fixed, budget, cap⟩ + else .error "proof Merkle cap omits a committed matrix height" + else .error "proof fixed table heights differ from the selected key" + +def verifyShaped {selection : Selection} (backend : CompiledBackend selection) + (input : Array G) (bytes : ByteArray) : Except String Unit := do + let _ ← readProof backend.keyData bytes + verifyCompiled backend input bytes + +theorem verifyShaped_success {selection : Selection} {backend : CompiledBackend selection} + {input : Array G} {bytes : ByteArray} (accepted : verifyShaped backend input bytes = .ok ()) : + ∃ checked : CheckedProof backend.keyData bytes, readProof backend.keyData bytes = .ok checked ∧ + verifyCompiled backend input bytes = .ok () := by + unfold verifyShaped at accepted + cases parsed : readProof backend.keyData bytes with + | error message => simp [parsed, bind, Except.bind] at accepted + | ok checked => exact ⟨checked, rfl, by simpa [parsed, bind, Except.bind] using accepted⟩ + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Stages/Bytecode.lean b/Ix/Aiur/Stages/Bytecode.lean index a2c178606..09e5baa2f 100644 --- a/Ix/Aiur/Stages/Bytecode.lean +++ b/Ix/Aiur/Stages/Bytecode.lean @@ -72,7 +72,12 @@ inductive Op | unconstrainedU32Add3 : Array ValIdx → Array ValIdx → Array ValIdx → Op /-- Virtual LE-byte packing expression; allocates no auxiliary column. -/ | u32ToField : Array ValIdx → Op - deriving Repr, BEq, Hashable + deriving Repr, BEq, ReflBEq, Hashable + +instance : LawfulBEq Op := ⟨by + deriving_LawfulEq_tactic + intro h + exact congrArg Op.const (eq_of_beq h)⟩ mutual inductive Ctrl where @@ -90,8 +95,204 @@ mutual deriving Inhabited, Repr end -deriving instance BEq, Hashable for Ctrl, Block +/-! Total recursive comparison and hashing for deduplication. The ordinary +mutual deriving handlers produce partial opaque logical defaults with +separate native workers. These definitions expose the actual algorithms to +proofs while retaining the native comparison order, hash tags and seeds. -/ + +private theorem Block.ctrl_lt (block : Block) : sizeOf block.ctrl < sizeOf block := by + cases block + simp + omega + +mutual + +/-- Compare all control fields, including layout metadata and continuations. -/ +def Ctrl.beq : Ctrl → Ctrl → Bool + | .match idx cases fallback, .match idx' cases' fallback' => + idx == idx' && (beqBranches cases cases' && beqFallback fallback fallback') + | .return sel outs, .return sel' outs' => sel == sel' && outs == outs' + | .yield sel outs, .yield sel' outs' => sel == sel' && outs == outs' + | .matchContinue idx cases fallback outputs aux lookups cont, + .matchContinue idx' cases' fallback' outputs' aux' lookups' cont' => + idx == idx' && (beqBranches cases cases' && (beqFallback fallback fallback' && + (outputs == outputs' && (aux == aux' && (lookups == lookups' && Block.beq cont cont'))))) + | _, _ => false +termination_by left _ => (sizeOf left, 0) +decreasing_by all_goals decreasing_tactic + +def Block.beq (left right : Block) : Bool := + left.ops == right.ops && Ctrl.beq left.ctrl right.ctrl +termination_by (sizeOf left, 0) +decreasing_by + apply Prod.Lex.left + exact Block.ctrl_lt left + +def beqFallback : Option Block → Option Block → Bool + | none, none => true + | some left, some right => Block.beq left right + | _, _ => false +termination_by left _ => (sizeOf left, 0) +decreasing_by all_goals decreasing_tactic + +def beqBranches (left right : Array (G × Block)) : Bool := + if h : left.size = right.size then beqBranchesAux left right h left.size (Nat.le_refl _) + else false +termination_by (sizeOf left, left.size + 1) +decreasing_by all_goals decreasing_tactic + +/-- Match `Array.isEqvAux`'s reverse traversal without hiding recursive +block comparisons behind an unbounded callback. -/ +def beqBranchesAux (left right : Array (G × Block)) (hsz : left.size = right.size) : + (n : Nat) → n ≤ left.size → Bool + | 0, _ => true + | n + 1, h => + (left[n].1 == (right[n]'(hsz ▸ h)).1 && Block.beq left[n].2 (right[n]'(hsz ▸ h)).2) && + beqBranchesAux left right hsz n (by omega) +termination_by n _ => (sizeOf left, n) +decreasing_by + all_goals first + | decreasing_tactic + | (apply Prod.Lex.left + have arrayBound := Array.sizeOf_get left n (by omega) + have pairBound : sizeOf left[n].2 < sizeOf left[n] := by + cases left[n]; simp; omega + omega) + +end + +instance : BEq Ctrl := ⟨Ctrl.beq⟩ +instance : BEq Block := ⟨Block.beq⟩ + +mutual + +/-- Boolean comparison reflects exact syntax equality. -/ +theorem Ctrl.beq_eq_true_iff (left right : Ctrl) : Ctrl.beq left right = true ↔ left = right := by + cases left <;> cases right <;> + simp only [Ctrl.beq, Bool.and_eq_true, beq_iff_eq, reduceCtorEq, Bool.false_eq_true, + Ctrl.match.injEq, Ctrl.return.injEq, Ctrl.yield.injEq, Ctrl.matchContinue.injEq] + all_goals rw [beqBranches_eq_true_iff, beqFallback_eq_true_iff] + all_goals rw [Block.beq_eq_true_iff] +termination_by (sizeOf left, 0) +decreasing_by all_goals decreasing_tactic + +theorem Block.beq_eq_true_iff (left right : Block) : Block.beq left right = true ↔ left = right := by + cases left + cases right + simp only [Block.beq, Bool.and_eq_true, beq_iff_eq, Block.mk.injEq] + rw [Ctrl.beq_eq_true_iff] +termination_by (sizeOf left, 0) +decreasing_by all_goals decreasing_tactic + +theorem beqFallback_eq_true_iff (left right : Option Block) : + beqFallback left right = true ↔ left = right := by + cases left <;> cases right <;> + simp only [beqFallback, reduceCtorEq, Bool.false_eq_true, Option.some.injEq] + rw [Block.beq_eq_true_iff] +termination_by (sizeOf left, 0) +decreasing_by all_goals decreasing_tactic + +theorem beqBranches_eq_true_iff (left right : Array (G × Block)) : + beqBranches left right = true ↔ left = right := by + unfold beqBranches + split + next hsz => + rw [beqBranchesAux_eq_true_iff] + constructor + · intro h + exact Array.ext hsz (fun i hi _ => h i hi) + · intro h + subst right + intros + rfl + next hsz => + simp only [Bool.false_eq_true, false_iff] + intro h + exact hsz (congrArg Array.size h) +termination_by (sizeOf left, left.size + 1) +decreasing_by all_goals decreasing_tactic + +theorem beqBranchesAux_eq_true_iff (left right : Array (G × Block)) + (hsz : left.size = right.size) (n : Nat) (hn : n ≤ left.size) : + beqBranchesAux left right hsz n hn = true ↔ + ∀ i (hi : i < n), (left[i]'(by omega)) = (right[i]'(by omega)) := by + cases n with + | zero => simp [beqBranchesAux] + | succ n => + rw [beqBranchesAux, Bool.and_eq_true, Bool.and_eq_true, + beq_iff_eq, Block.beq_eq_true_iff, beqBranchesAux_eq_true_iff] + constructor + · rintro ⟨⟨hg, hb⟩, tail⟩ i hi + by_cases h : i < n + · exact tail i h + · have : i = n := by omega + subst i + exact Prod.ext hg hb + · intro h + refine ⟨⟨congrArg Prod.fst (h n (by omega)), congrArg Prod.snd (h n (by omega))⟩, ?_⟩ + intro i hi + exact h i (by omega) +termination_by (sizeOf left, n) +decreasing_by + all_goals first + | decreasing_tactic + | (apply Prod.Lex.left + have arrayBound := Array.sizeOf_get left n (by omega) + have pairBound : sizeOf left[n].2 < sizeOf left[n] := by + cases left[n]; simp; omega + omega) + +end + +instance : LawfulBEq Ctrl where + eq_of_beq {left right} h := (Ctrl.beq_eq_true_iff left right).mp h + rfl {value} := (Ctrl.beq_eq_true_iff value value).mpr rfl + +instance : LawfulBEq Block where + eq_of_beq {left right} h := (Block.beq_eq_true_iff left right).mp h + rfl {value} := (Block.beq_eq_true_iff value value).mpr rfl + +mutual + +/-- Preserve the derived hash algorithm: constructor tags 0–3, array seed +7, option tags 11/13 and the original left-to-right field mixing. -/ +def Ctrl.hash : Ctrl → UInt64 + | .match idx branches fallback => + let branchesHash := branches.attach.foldl (fun acc pair => + mixHash acc (mixHash (hash pair.val.1) (Block.hash pair.val.2))) 7 + let fallbackHash := match fallback with + | none => 11 + | some block => mixHash (Block.hash block) 13 + mixHash (mixHash (mixHash 0 (hash idx)) branchesHash) fallbackHash + | .return sel outs => mixHash (mixHash 1 (hash sel)) (hash outs) + | .yield sel outs => mixHash (mixHash 2 (hash sel)) (hash outs) + | .matchContinue idx branches fallback outputs aux lookups cont => + let branchesHash := branches.attach.foldl (fun acc pair => + mixHash acc (mixHash (hash pair.val.1) (Block.hash pair.val.2))) 7 + let fallbackHash := match fallback with + | none => 11 + | some block => mixHash (Block.hash block) 13 + mixHash (mixHash (mixHash (mixHash (mixHash (mixHash (mixHash 3 (hash idx)) + branchesHash) fallbackHash) (hash outputs)) (hash aux)) (hash lookups)) (Block.hash cont) +termination_by ctrl => sizeOf ctrl +decreasing_by + all_goals first + | decreasing_tactic + | (have arrayBound := Array.sizeOf_lt_of_mem pair.property + have pairBound : sizeOf pair.val.2 < sizeOf pair.val := by + cases pair.val; simp; omega + simp_all + omega) + +def Block.hash (block : Block) : UInt64 := + mixHash (mixHash 0 (hash block.ops)) (Ctrl.hash block.ctrl) +termination_by sizeOf block +decreasing_by exact Block.ctrl_lt block + +end +instance : Hashable Ctrl := ⟨Ctrl.hash⟩ +instance : Hashable Block := ⟨Block.hash⟩ /-- The circuit layout of a function (non-semantic; the bytecode evaluator ignores it). -/ structure FunctionLayout where @@ -99,7 +300,7 @@ structure FunctionLayout where selectors : Nat auxiliaries : Nat lookups : Nat - deriving Inhabited, Repr, BEq, Hashable, DecidableEq + deriving Inhabited, Repr, BEq, ReflBEq, LawfulBEq, Hashable, DecidableEq def FunctionLayout.width (l : FunctionLayout) : Nat := l.inputSize + l.selectors + l.auxiliaries diff --git a/Ix/Aiur/Stages/Source.lean b/Ix/Aiur/Stages/Source.lean index 924082ea2..25c795764 100644 --- a/Ix/Aiur/Stages/Source.lean +++ b/Ix/Aiur/Stages/Source.lean @@ -379,8 +379,9 @@ namespace Source output columns at the call site). * `unconstrained` — a call whose callee is trusted (no lookup / circuit constraint); the old `unconstrained := true`. -* `inlined` — the callee's body is spliced into the caller at compile - time (no separate circuit, no interface columns). Eliminated by +* `inlined` — request that the callee's body be spliced into the caller. + Callees with explicit returns retain a normal function-call boundary. + Eliminated by `Toplevel.inlineCalls` before typechecking; forbidden for callees that are (transitively) inline-recursive. -/ inductive CallMode @@ -842,9 +843,47 @@ decreasing_by | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) | (have := List.sizeOf_lt_of_mem ‹_ ∈ _›; grind) -/-- Structurally splice every `.app g args .inlined` in `t`, given `done`, +/-- Explicit returns require a function-call boundary when considering +inlining. Splicing them would let a callee return from its caller. -/ +def Term.hasExplicitReturn : Term → Bool + | .ret _ => true + | .var _ | .unit | .field _ | .u8Lit _ | .ref _ => false + | .app _ args _ => args.attach.any fun arg => Term.hasExplicitReturn arg.val + | .tuple terms | .array terms => terms.attach.any fun term => Term.hasExplicitReturn term.val + | .let _ value body => Term.hasExplicitReturn value || Term.hasExplicitReturn body + | .match scrut arms => Term.hasExplicitReturn scrut || + arms.attach.any fun arm => Term.hasExplicitReturn arm.val.2 + | .eqZero a | .proj a _ | .get a _ | .slice a _ _ + | .store a | .load a | .ptrVal a | .ann _ a + | .u8BitDecomposition a | .u8ShiftLeft a | .u8ShiftRight a + | .u32ToField a | .unconstrainedGToBytes a | .unconstrainedGInverse a + | .toField a | .u8FromFieldUnsafe a => Term.hasExplicitReturn a + | .add a b | .sub a b | .mul a b | .set a _ b | .ioGetInfo a b | .ioRead a b _ + | .u8Xor a b | .u8Add a b | .u8Mul a b | .u8Sub a b | .u8And a b | .u8Or a b + | .u8LessThan a b | .u32LessThan a b | .u8XorSplit7 a b | .u8XorSplit4 a b + | .unconstrainedU32Add a b | .unconstrainedBigUintDivMod a b | .u8RangeCheck a b => + Term.hasExplicitReturn a || Term.hasExplicitReturn b + | .assertEq a b _ c | .ioWrite a b c | .unconstrainedU32Add3 a b c => + Term.hasExplicitReturn a || Term.hasExplicitReturn b || Term.hasExplicitReturn c + | .ioSetInfo a b c d e => Term.hasExplicitReturn a || Term.hasExplicitReturn b || + Term.hasExplicitReturn c || Term.hasExplicitReturn d || Term.hasExplicitReturn e + | .debug _ none continuation => Term.hasExplicitReturn continuation + | .debug _ (some value) continuation => + Term.hasExplicitReturn value || Term.hasExplicitReturn continuation +termination_by term => sizeOf term +decreasing_by + all_goals first + | decreasing_tactic + | (have := Array.sizeOf_lt_of_mem term.property; grind) + | (have := List.sizeOf_lt_of_mem arg.property; grind) + | (have := List.sizeOf_lt_of_mem arm.property + have : sizeOf arm.val.2 < sizeOf arm.val := by cases arm.val; simp; omega + simp_all; omega) + +/-- Structurally splice `.app g args .inlined` in `t`, given `done`, which maps each already-expanded callee to its input locals and its (already -inline-free) body. At an inline site the callee's inputs and body are +inline-free) body. Callees with explicit returns become normal calls so their +return cannot escape the caller. At other inline sites the inputs and body are α-renamed to fresh `inl#N` names (`Term.freshen`, seeded with the inputs), then each fresh input is bound to its argument via a `let`. Freshening the inputs BEFORE binding the arguments is essential: arguments are caller terms, @@ -864,6 +903,7 @@ def Term.expandOnce (done : Std.HashMap Global (List Local × Term)) (cnt : Nat) match done[g]? with | none => (cnt, .app g args' .inlined) | some (ins, body) => + if body.hasExplicitReturn then (cnt, .app g args' .normal) else let (cnt, subst, freshInputs) := ins.foldl (init := (cnt, (∅ : Std.HashMap Local Local), ([] : List Local))) fun (cnt, subst, acc) inp => @@ -1059,7 +1099,7 @@ def Term.hoistLetsAux : Term → StateM Nat Term := fun t => do | .proj a n => return Term.hoistUnaryLets (fun a => .proj a n) (← a.hoistLetsAux) | .get a n => return Term.hoistUnaryLets (fun a => .get a n) (← a.hoistLetsAux) | .slice a i j => return Term.hoistUnaryLets (fun a => .slice a i j) (← a.hoistLetsAux) - | .set a n v => Term.hoistBinaryLets (fun a v => .set a n v) (← a.hoistLetsAux) (← v.hoistLetsAux) + | .set a n v => Term.hoistBinaryLets (fun v a => .set a n v) (← v.hoistLetsAux) (← a.hoistLetsAux) | .store a => return Term.hoistUnaryLets .store (← a.hoistLetsAux) | .load a => return Term.hoistUnaryLets .load (← a.hoistLetsAux) | .ptrVal a => return Term.hoistUnaryLets .ptrVal (← a.hoistLetsAux) @@ -1139,14 +1179,22 @@ context; left in tail position it turns a legal tail match into a lowering rejects ("non-tail match in arbitrary position"). The rewrite is the eta step `let x = v; x → v`, applied only through tail positions (let bodies and match arms), so non-tail wraps are untouched. -/ -partial def Term.restoreTailMatches : Term → Term - | .let p v b => - match p, b with - | .var x, .var y => - if x == y then Term.restoreTailMatches v else .let p v b - | _, _ => .let p v (Term.restoreTailMatches b) - | .match s arms => .match s (arms.map fun (p, a) => (p, Term.restoreTailMatches a)) +def Term.restoreTailMatches : Term → Term + | .let (.var x) v (.var y) => + if x == y then Term.restoreTailMatches v else .let (.var x) v (.var y) + | .let p v b => .let p v (Term.restoreTailMatches b) + | .match s arms => + .match s (arms.attach.map fun arm => (arm.val.1, Term.restoreTailMatches arm.val.2)) | t => t +termination_by term => sizeOf term +decreasing_by + all_goals first + | decreasing_tactic + | (have listBound := List.sizeOf_lt_of_mem arm.property + have pairBound : sizeOf arm.val.2 < sizeOf arm.val := by + cases arm.val; simp; omega + simp_all + omega) /-- Inline-expand every function body in the toplevel, eliminating all `.inlined` applications. Run before typechecking. diff --git a/Ix/Aiur/Transcript.lean b/Ix/Aiur/Transcript.lean new file mode 100644 index 000000000..efbed95e5 --- /dev/null +++ b/Ix/Aiur/Transcript.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Challenger +import Ix.Aiur.VerifierArithmetic + +/-! The multi-STARK transcript through the out-of-domain challenge, with +the continuing challenger state retained for PCS verification. This replay +does not authenticate the openings or assert hash security. +-/ + +namespace Aiur.NativeAIR.Transcript + +open Challenger +open ProofCodec (Extension) + +def parameterWords (parameters : KeyCodec.Parameters) : List Nat := + [parameters.logBlowup, parameters.capHeight, parameters.logFinalPolyLen, + parameters.maxLogArity, parameters.numQueries, parameters.commitProofOfWorkBits, + parameters.queryProofOfWorkBits] + +def seed (parameters : KeyCodec.Parameters) : List UInt8 := + "multi-stark/v0".toUTF8.data.toList ++ (parameterWords parameters).flatMap (KeyCodec.encodeNat 8) + +def circuitShape (circuit : KeyCodec.Circuit) : List G := + [circuit.constraintCount, circuit.maxConstraintDegree, circuit.preprocessedHeight, + circuit.preprocessedWidth, circuit.mainWidth, circuit.widths.stage2, circuit.lookupGroupSize].map G.ofNat + +def shape (key : KeyCodec.Key) : List G := + G.ofNat key.circuits.length :: key.circuits.flatMap circuitShape + +def claimsFields (claims : List (List G)) : List G := + G.ofNat claims.length :: claims.flatMap (fun claim => G.ofNat claim.length :: claim) + +def fieldsBytes (values : List G) : List UInt8 := values.flatMap ProofCodec.encodeField + +def prefixBytes (key : KeyCodec.Key) (proof : ProofCodec.Data) (claims : List (List G)) : List UInt8 := + fieldsBytes (shape key) ++ + fieldsBytes (proof.active.map (fun active => if active then 1 else 0)) ++ + (key.preprocessedCommitment.getD []).flatten ++ proof.commitments.stage1.flatten ++ + fieldsBytes (proof.logDegrees.map (fun degree => G.ofNat degree.toNat)) ++ + fieldsBytes (claimsFields claims) + +def lookupState (key : KeyCodec.Key) (proof : ProofCodec.Data) (claims : List (List G)) : State := + observeBytes (initial (seed key.parameters)) (prefixBytes key proof claims) + +def accumulatorState (proof : ProofCodec.Data) (state : State) : State := + proof.accumulators.foldl observeExtension (observeCap state proof.commitments.stage2) + +structure Replay where + challenges : VerifierArithmetic.Challenges + state : State + deriving DecidableEq, Repr + +def replay (hash : Hash32) (fuel : Nat) (key : KeyCodec.Key) + (proof : ProofCodec.Data) (claims : List (List G)) : Option Replay := do + let (beta, afterBeta) ← sampleExtension hash fuel (lookupState key proof claims) + let (gamma, afterGamma) ← sampleExtension hash fuel (observeExtension afterBeta beta) + let (alpha, afterAlpha) ← sampleExtension hash fuel + (accumulatorState proof (observeExtension afterGamma gamma)) + let (zeta, final) ← sampleExtension hash fuel (observeCap afterAlpha proof.commitments.quotient) + return ⟨⟨beta, gamma, alpha, zeta⟩, final⟩ + +/-- Arithmetic with transcript-derived challenges. The PCS still has to +authenticate the polynomial openings using the returned challenger state. -/ +def verifyArithmetic (hash : Hash32) (fuel : Nat) (key : KeyCodec.Key) + (proof : ProofCodec.Data) (claims : List (List G)) (rows : List ProofShape.Row) : Option Replay := do + let result ← replay hash fuel key proof claims + if ← VerifierArithmetic.verify result.challenges claims rows then some result else none + +end Aiur.NativeAIR.Transcript diff --git a/Ix/Aiur/VerifierArithmetic.lean b/Ix/Aiur/VerifierArithmetic.lean new file mode 100644 index 000000000..c3f9cdc9f --- /dev/null +++ b/Ix/Aiur/VerifierArithmetic.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ProofShape +import Ix.Aiur.LogUp +import Ix.Aiur.Quotient + +/-! Total arithmetic on the opened rows of an active circuit. The ordering, +coordinate embedding and boundary normalization follow the pinned native +verifier. Challenges are explicit inputs; this does not authenticate them +or the polynomial openings. +-/ + +namespace Aiur.NativeAIR.VerifierArithmetic + +open ProofCodec (Extension) +open ProofShape (Row Pair) + +structure Challenges where + beta : Extension + gamma : Extension + alpha : Extension + zeta : Extension + deriving DecidableEq, Repr + +def pairColumns (pair : Pair) : RowOffset → Array Extension + | .current => pair.current.toArray + | .next => pair.next.toArray + +def rowColumns (row : Row) : Source → RowOffset → Array Extension + | .preprocessed => match row.preprocessed with + | none => fun _ => #[] + | some pair => pairColumns pair + | .main => pairColumns row.stage1 + | .stage2 => pairColumns row.stage2 + +/-- Each extension value contributes its two base coordinates, each embedded +separately into the working extension field. -/ +def publics (challenges : Challenges) (entering leaving : Extension) : Array Extension := + #[Extension.ofBase challenges.beta.c0, Extension.ofBase challenges.beta.c1, + Extension.ofBase challenges.gamma.c0, Extension.ofBase challenges.gamma.c1, + Extension.ofBase entering.c0, Extension.ofBase entering.c1, + Extension.ofBase leaving.c0, Extension.ofBase leaving.c1] + +def deltaScaled (domain : Domain.Subgroup) (entering leaving : Extension) : Array Extension := + let normalizer := Extension.ofBase (Domain.normalizer domain).inverse + #[(Extension.ofBase leaving.c0 - Extension.ofBase entering.c0) * normalizer, + (Extension.ofBase leaving.c1 - Extension.ofBase entering.c1) * normalizer] + +def view (challenges : Challenges) (row : Row) (entering : Extension) + (selectors : Domain.Selectors Extension) : Values Extension := + ⟨rowColumns row, publics challenges entering row.accumulator, + selectors.isFirst, selectors.isLast, selectors.isTransition⟩ + +structure Evaluation where + domain : Domain.Subgroup + selectors : Domain.Selectors Extension + nodeValues : Array Extension + userValues : List Extension + lookupValues : List Extension + quotientValue : Extension + deriving DecidableEq, Repr + +def Evaluation.constraints (result : Evaluation) : List Extension := + result.userValues ++ result.lookupValues + +def Evaluation.accepts (result : Evaluation) (alpha : Extension) : Bool := + Quotient.composition alpha result.constraints * result.selectors.invVanishing == result.quotientValue + +def evaluate (challenges : Challenges) (row : Row) (entering : Extension) : Option Evaluation := do + let domain ← Domain.ofLogSize row.logDegree.toNat + let selectors ← Domain.selectors domain challenges.zeta + let values := view challenges row entering selectors + let nodes ← row.circuit.graph.sweep Extension.evalOps values + let userValues ← readNodes nodes row.circuit.graph.zeros + let lookupValues ← LogUp.constraintValues row.circuit.graph.lookups nodes + (values.columns .stage2 .current) (values.columns .stage2 .next) values.publics + (deltaScaled domain entering row.accumulator) values.isLastRow row.circuit.lookupGroupSize + let quotientValue ← Quotient.evaluate domain challenges.zeta row.quotient + return ⟨domain, selectors, nodes, userValues, lookupValues, quotientValue⟩ + +def check (challenges : Challenges) (row : Row) (entering : Extension) : Option Bool := do + return (← evaluate challenges row entering).accepts challenges.alpha + +/-- The leaving accumulator of each accepted row enters the next active row. -/ +def checkRows (challenges : Challenges) : List Row → Extension → Option Extension + | [], entering => some entering + | row :: rows, entering => do + if ← check challenges row entering then checkRows challenges rows row.accumulator else none + +def claimMessage (challenges : Challenges) (claim : List G) : Extension := + challenges.beta + (LogUp.fingerprint (LogUp.Coordinates.fromExtension challenges.gamma) claim).toExtension + +def initialAccumulator (challenges : Challenges) (claims : List (List G)) : Option Extension := do + let inverses ← claims.mapM fun claim => (claimMessage challenges claim).tryInverse + return LogUp.sum inverses + +def verify (challenges : Challenges) (claims : List (List G)) (rows : List Row) : Option Bool := do + if rows.isEmpty then none else do + let entering ← initialAccumulator challenges claims + return (← checkRows challenges rows entering) == 0 + +end Aiur.NativeAIR.VerifierArithmetic diff --git a/Ix/MultiStark/SystemDeserialize.lean b/Ix/MultiStark/SystemDeserialize.lean index ee65c7670..51bed17cd 100644 --- a/Ix/MultiStark/SystemDeserialize.lean +++ b/Ix/MultiStark/SystemDeserialize.lean @@ -10,7 +10,7 @@ public import Ix.MultiStark.Deserialize Aiur port of `crates/aiur/src/vk_codec.rs` — reconstructs the verifier's `System` from the bytes the prover places on the IO channel. -Wire format (v3, mirrors `vk_codec.rs` — see its module docs for the full +Wire format (v5, mirrors `vk_codec.rs` — see its module docs for the full layout). The multi-stark constraint-IR migration replaced the per-circuit *symbolic* AIR (`SymbolicExpression` trees + `LookupAir`) with a *compiled* flat base-field node graph, so this reader parses that compiled form: @@ -75,10 +75,10 @@ def systemDeserialize := ⟦ Neg(G) } - -- A compiled circuit: the flat node vector, its length, the constraint-root - -- NodeIds (`zeros`), and the maximum constraint degree (for the quotient - -- degree). The lookups are omitted — their constraints are compiled into - -- `zeros`, so the verifier never needs them. + -- A compiled circuit retains the flat node vector, its length, user + -- constraint-root NodeIds (`zeros`), the combined maximum degree, lookups + -- and their group size. The verifier evaluates logUp directly after the + -- user roots; logUp constraints are not compiled into `zeros`. -- A compiled lookup: multiplicity node id + argument node ids (all into -- the graph's lookup prefix). Drives the direct logUp evaluation. enum SysLookup { Mk(G, List‹G›) } diff --git a/Tests/Aiur/AIRSemantics.lean b/Tests/Aiur/AIRSemantics.lean new file mode 100644 index 000000000..92b8b06fb --- /dev/null +++ b/Tests/Aiur/AIRSemantics.lean @@ -0,0 +1,189 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Execution +import Ix.Aiur.Proofs.Memory +import Ix.Aiur.Proofs.LocalConstraints + +/-! Concrete local semantics and finite-derivation regressions. The native +supplied-row counterparts live in `synthesis/tests/advice.rs`. -/ + +open Aiur Aiur.Bytecode Aiur.Bytecode.AIR + +namespace Tests.Aiur.AIRSemantics + +private def fixtures : Array (String × Op × Array G × Array G × Option (Array G)) := #[ + ("constant", .const 7, #[], #[], some #[7]), + ("addition", .add 0 1, #[255, 2], #[], some #[257]), + ("subtraction", .sub 0 1, #[255, 2], #[], some #[253]), + ("multiplication", .mul 0 1, #[255, 2], #[], some #[510]), + ("zero", .eqZero 0, #[0], #[], some #[1]), + ("nonzero", .eqZero 0, #[9], #[], some #[0]), + ("constrained-call-needs-provider", .call 1 #[0] 1 false, #[3], #[7], none), + ("unconstrained-call-advice", .call 1 #[0] 1 true, #[3], #[7], some #[7]), + ("unconstrained-call-width", .call 1 #[0] 1 true, #[3], #[7, 8], none), + ("store-needs-memory", .store #[0], #[3], #[7], none), + ("load-needs-memory", .load 1 0, #[7], #[3], none), + ("assertion", .assertEq #[0] #[1] none, #[7, 7], #[], some #[]), + ("false-assertion", .assertEq #[0] #[1] none, #[7, 8], #[], none), + ("assertion-width", .assertEq #[0] #[0, 1] none, #[7, 8], #[], none), + ("key-info-advice", .ioGetInfo 0 #[], #[0], #[300, 301], some #[300, 301]), + ("key-insertion-no-relation", .ioSetInfo 0 #[] 1 2, #[0, 9, 4], #[], some #[]), + ("read-advice", .ioRead 0 1 2, #[0, 9], #[302, 303], some #[302, 303]), + ("read-width", .ioRead 0 1 2, #[0, 9], #[302], none), + ("write-no-relation", .ioWrite 0 #[1], #[0, 7], #[], some #[]), + ("bit-decomposition", .u8BitDecomposition 0, #[129], #[], some #[1, 0, 0, 0, 0, 0, 0, 1]), + ("shift-left", .u8ShiftLeft 0, #[129], #[], some #[2]), + ("shift-right", .u8ShiftRight 0, #[129], #[], some #[64]), + ("xor", .u8Xor 0 1, #[255, 2], #[], some #[253]), + ("add-with-carry", .u8Add 0 1, #[255, 2], #[], some #[1, 1]), + ("byte-product", .u8Mul 0 1, #[255, 2], #[], some #[254, 1]), + ("subtract-with-borrow", .u8Sub 0 1, #[2, 255], #[], some #[3, 1]), + ("and", .u8And 0 1, #[255, 2], #[], some #[2]), + ("or", .u8Or 0 1, #[255, 2], #[], some #[255]), + ("byte-less-than", .u8LessThan 0 1, #[2, 255], #[], some #[1]), + ("word-less-than", .u32LessThan 0 1, #[65536, 65537], #[], some #[1]), + ("word-input-range", .u32LessThan 0 1, #[4294967296, 65537], #[], none), + ("split-seven", .u8XorSplit7 0 1, #[255, 2], #[], some #[1, 250]), + ("split-four", .u8XorSplit4 0 1, #[255, 2], #[], some #[15, 208]), + ("debug-no-relation", .debug "test" (some #[0]), #[7], #[], some #[]), + ("byte-range", .u8RangeCheck 0 1, #[255, 0], #[], some #[]), + ("invalid-byte-range", .u8RangeCheck 0 1, #[256, 0], #[], none), + ("byte-operation-requires-range", .u8Xor 0 1, #[256, 0], #[], none), + ("division-advice", .unconstrainedBigUintDivMod 0 1, #[3, 2], #[304, 305], some #[304, 305]), + ("decomposition-advice", .unconstrainedGToBytes 0, #[1], + #[306, 307, 308, 309, 310, 311, 312, 313], some #[306, 307, 308, 309, 310, 311, 312, 313]), + ("inverse-advice", .unconstrainedGInverse 0, #[1], #[314], some #[314]), + ("word-add", .unconstrainedU32Add #[0, 1, 2, 3] #[4, 5, 6, 7], + #[255, 255, 255, 255, 1, 0, 0, 0], #[0, 0, 0, 0], some #[0, 0, 0, 0, 1]), + ("word-add-three", .unconstrainedU32Add3 #[0, 1, 2, 3] #[0, 1, 2, 3] #[0, 1, 2, 3], + #[255, 255, 255, 255], #[253, 255, 255, 255], some #[253, 255, 255, 255, 2]), + ("word-packing", .u32ToField #[0, 1, 2, 3], #[1, 2, 3, 4], #[], some #[67305985]), + ("word-packing-width", .u32ToField #[0, 1, 2], #[1, 2, 3], #[], none), + ("invalid-value-index", .mul 0 2, #[3, 5], #[], none)] + +private def noMemory : Memory := fun _ _ _ => False + +private def identity : Function := + ⟨⟨#[], .return 0 #[0]⟩, ⟨1, 1, 7, 4⟩, false, true⟩ + +private def caller : Function := + ⟨⟨#[.call 1 #[0] 1 false, .call 1 #[0] 1 false, .add 1 2], .return 0 #[3]⟩, + ⟨1, 1, 23, 12⟩, true, true⟩ + +private def sharedProgram : Toplevel := ⟨#[caller, identity], #[], #[], #[]⟩ +private def child : Call := ⟨1, #[3], #[3], 1⟩ +private def parent : Call := ⟨0, #[3], #[6], 0⟩ + +private theorem childExecutes : Execution sharedProgram noMemory child := by + apply Execution.function (calls := []) + · apply RunFunction.function (function := identity) rfl rfl + apply RunBlock.block (intermediate := #[3]) (opCalls := []) (ctrlCalls := []) + · exact RunOps.nil + · exact RunCtrl.returned (by cbv) + · simp + +/-- A shared callee supplies both calls; the finite derivation needs no +sequential cache state or multiplicity-dependent replay. -/ +example : Execution sharedProgram noMemory parent := by + apply Execution.function (calls := [child, child]) + · apply RunFunction.function (function := caller) rfl rfl + apply RunBlock.block (intermediate := #[3, 3, 3, 6]) + (opCalls := [child, child]) (ctrlCalls := []) + · apply RunOps.cons (intermediate := #[3, 3]) (firstCalls := [child]) (restCalls := [child]) + · exact Step.call (request := child) (by cbv) rfl + · apply RunOps.cons (intermediate := #[3, 3, 3]) (firstCalls := [child]) (restCalls := []) + · exact Step.call (request := child) (by cbv) rfl + · exact RunOps.cons (Step.primitive (outputs := #[6]) (advice := #[]) (by cbv)) RunOps.nil + · exact RunCtrl.returned (by cbv) + · intro called member + have : called = child := by simpa using member + subst called + exact childExecutes + +private def yieldingArm : Block := ⟨#[.const 99, .const 5], .yield 0 #[2]⟩ +private def continuation : Block := ⟨#[.const 7, .add 1 2], .return 1 #[3]⟩ + +/-- The branch-local 99 does not leak into the continuation's namespace. -/ +example : RunCtrl noMemory + (.matchContinue 0 #[(0, yieldingArm)] none 1 0 0 continuation) + #[0] (.returned #[12]) [] := by + apply RunCtrl.matchContinueYield (branchCalls := []) (contCalls := []) (yielded := #[5]) + (scrutinee := 0) (arm := yieldingArm) (by cbv) (SelectArm.case (by simp)) + · apply RunBlock.block (intermediate := #[0, 99, 5]) (opCalls := []) (ctrlCalls := []) + · exact RunOps.cons (Step.primitive (outputs := #[99]) (advice := #[]) (by cbv)) + (RunOps.cons (Step.primitive (outputs := #[5]) (advice := #[]) (by cbv)) RunOps.nil) + · exact RunCtrl.yielded (by cbv) + · rfl + · apply RunBlock.block (intermediate := #[0, 5, 7, 12]) (opCalls := []) (ctrlCalls := []) + · exact RunOps.cons (Step.primitive (outputs := #[7]) (advice := #[]) (by cbv)) + (RunOps.cons (Step.primitive (outputs := #[12]) (advice := #[]) (by cbv)) RunOps.nil) + · exact RunCtrl.returned (by cbv) + +private def returningArm : Block := ⟨#[.const 5], .return 0 #[1]⟩ +private def impossibleContinuation : Block := + ⟨#[.const 1, .assertEq #[0] #[1] none], .return 1 #[]⟩ + +/-- A branch return skips an otherwise failing continuation. -/ +example : RunCtrl noMemory + (.matchContinue 0 #[(0, returningArm)] none 0 0 0 impossibleContinuation) + #[0] (.returned #[5]) [] := by + apply RunCtrl.matchContinueReturn (scrutinee := 0) (arm := returningArm) + (by cbv) (SelectArm.case (by simp)) + apply RunBlock.block (intermediate := #[0, 5]) (opCalls := []) (ctrlCalls := []) + · exact RunOps.cons (Step.primitive (outputs := #[5]) (advice := #[]) (by cbv)) RunOps.nil + · exact RunCtrl.returned (by cbv) + +private def memory : Memory := fun width pointer contents => + width = 1 ∧ pointer = 7 ∧ contents = #[3] + +example : Step memory (.store #[0]) #[3] #[3, 7] [] := + Step.store (by cbv) ⟨rfl, rfl, rfl⟩ + +example : Step memory (.load 1 0) #[7] #[7, 3] [] := + Step.load (pointer := 7) (contents := #[3]) (by cbv) rfl ⟨rfl, rfl, rfl⟩ + +private def wrappingRows : Array Aiur.AIR.MemoryRow := #[ + ⟨1, 0, G.ofNat (gSize.toNat - 1), #[7]⟩, + ⟨1, 1, 0, #[8]⟩, + ⟨0, 0, 0, #[0]⟩, + ⟨0, 0, 0, #[0]⟩] + +/-- The same four-row wrapping memory table used by the supplied native proof. -/ +private theorem wrappingRows_polynomials : Aiur.AIR.MemoryRowsPolynomials 1 wrappingRows := by + constructor + all_goals + intro i hi + have cases : i = 0 ∨ i = 1 ∨ i = 2 ∨ i = 3 := by + simp only [wrappingRows, List.size_toArray, List.length_cons, List.length_nil] at hi + omega + rcases cases with rfl | rfl | rfl | rfl + all_goals decide +revert +kernel + +example : wrappingRows[0].pointer ≠ wrappingRows[1].pointer := by + intro same + have impossible := wrappingRows_polynomials.valid.pointer_injective (by decide) 0 1 + (by decide) (by decide) rfl rfl same + contradiction + +def main : IO Unit := do + for (label, op, values, advice, expected) in fixtures do + unless primitive op values advice == expected do + throw (IO.userError s!"AIR semantics fixture failed: {label}") + -- The result bytes of an unchecked u32 sum may exceed 255, while its + -- computed carry must still satisfy the field equation. + let values : Array G := #[1, 2, 3, 4, 5, 6, 7, 8] + let bytes : Array G := #[316, 317, 318, 319] + let some output := primitive (.unconstrainedU32Add #[0, 1, 2, 3] #[4, 5, 6, 7]) values bytes + | throw (IO.userError "unchecked u32 advice was rejected") + unless output.size == 5 && output.extract 0 4 == bytes && + output[4]?.getD 0 * 4294967296 + packWord bytes == + packWord (values.extract 0 4) + packWord (values.extract 4 8) do + throw (IO.userError "virtual u32 carry equation failed") + IO.println s!"AIR semantics: {fixtures.size} operation fixtures and unchecked virtual carry passed." + +end Tests.Aiur.AIRSemantics + +def main := Tests.Aiur.AIRSemantics.main diff --git a/Tests/Aiur/Backend.lean b/Tests/Aiur/Backend.lean new file mode 100644 index 000000000..aa9442ed4 --- /dev/null +++ b/Tests/Aiur/Backend.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.ShapedVerifier +import Ix.Aiur.Meta + +/-! Nonvacuity and rejection tests for the generic program binding component. +The arithmetic source exercises the backend API; it is not a certified Ix +checker and does not license a logical claim about Ix declarations. -/ + +namespace AiurTests.Backend + +open Aiur Aiur.BoundVerifier + +def product := ⟦ + pub fn product(a: G, b: G) -> G { a * b } +⟧ + +def changedProduct := ⟦ + pub fn product(a: G, b: G) -> G { a + b } +⟧ + +def groupedProgram := ⟦ + fn double(x: G) -> G { x + x } + fn bump(x: G) -> G { x + 1 } + pub fn grouped_product(a: G, b: G) -> G { double(a) * bump(b) } +⟧ + +def requireRejected (label : String) (result : Except String α) : IO Unit := + match result with + | .error _ => IO.println s!"PASS {label}: rejected" + | .ok _ => throw (IO.userError s!"unexpected acceptance: {label}") + +def run : IO Unit := do + let compiled ← IO.ofExcept product.compile + let some function := compiled.getFuncIdx `product + | throw (IO.userError "missing product entrypoint") + let cp : CommitmentParameters := { logBlowup := 1, capHeight := 0 } + let fp : FriParameters := { + logFinalPolyLen := 0, maxLogArity := 1, + numQueries := 64, commitProofOfWorkBits := 0, queryProofOfWorkBits := 0 } + let system := AiurSystem.build compiled.bytecode cp fp + let selection : Selection := { + source := product, entrypoint := `product, + function, inputSize := 2, success := #[15], commitment := cp, fri := fp, + key := system.vkBytes } + let backend ← IO.ofExcept (buildCompiled selection) + let (claim, proof, _) ← IO.ofExcept (system.prove function #[3, 5] default) + unless claim == buildClaim function #[3, 5] #[15] do + throw (IO.userError "unexpected public claim") + let bytes := proof.toBytes + IO.ofExcept (verifyShaped backend #[3, 5] bytes) + IO.println "PASS selected program/key/function/input/result: accepted" + requireRejected "changed public input" (verifyShaped backend #[3, 4] bytes) + requireRejected "public input arity" (verifyShaped backend #[3] bytes) + requireRejected "malformed proof" (verifyShaped backend #[3, 5] ByteArray.empty) + let suffixed := bytes.push 0 + let _ ← IO.ofExcept (Proof.ofBytesChecked suffixed) + requireRejected "proof suffix" (verifyShaped backend #[3, 5] suffixed) + let checked ← IO.ofExcept (readProof backend.keyData bytes) + let malformed := { checked.data with stage1 := [] } + let malformedBytes := NativeAIR.ProofCodec.encode malformed + unless (NativeAIR.ProofCodec.decodeCanonical malformedBytes).isSome do + throw (IO.userError "shape mutation is not a canonical proof artifact") + requireRejected "proof opening dimensions" (verifyShaped backend #[3, 5] malformedBytes) + let changedResult ← IO.ofExcept (buildCompiled { selection with success := #[16] }) + requireRejected "changed success result" (verifyShaped changedResult #[3, 5] bytes) + requireRejected "missing success output" (buildCompiled { selection with success := #[] }) + requireRejected "extra zero success output" (buildCompiled { selection with success := #[15, 0] }) + requireRejected "unselected key" (buildCompiled { selection with key := ByteArray.empty }) + requireRejected "changed program" (buildCompiled { selection with source := changedProduct }) + requireRejected "changed function index" (buildCompiled { selection with function := function + 1 }) + requireRejected "changed entrypoint" (buildCompiled { selection with entrypoint := `missing }) + requireRejected "changed expected arity" (buildCompiled { selection with inputSize := 3 }) + requireRejected "unselected grouping" (buildCompiled { selection with groups := #[("bad", #["product"])] }) + requireRejected "changed commitment parameters" (buildCompiled { + selection with commitment := { cp with logBlowup := 2 } }) + requireRejected "changed FRI parameters" (buildCompiled { + selection with fri := { fp with numQueries := 32 } }) + + let initial ← IO.ofExcept groupedProgram.compile + let groups := #[("helpers", #["double", "bump"])] + let grouped ← IO.ofExcept (initial.groupFunctions groups) + unless grouped.bytecode.circuits.size + 1 == initial.bytecode.circuits.size do + throw (IO.userError "grouping did not merge the two helper circuits") + let some groupedFunction := grouped.getFuncIdx `grouped_product + | throw (IO.userError "missing grouped entrypoint") + let groupedSystem := AiurSystem.build grouped.bytecode cp fp + let groupedSelection : Selection := { + source := groupedProgram, groups, entrypoint := `grouped_product, + function := groupedFunction, inputSize := 2, success := #[30], + commitment := cp, fri := fp, key := groupedSystem.vkBytes } + let groupedBackend ← IO.ofExcept (buildCompiled groupedSelection) + let (groupedClaim, groupedProof, _) ← + IO.ofExcept (groupedSystem.prove groupedFunction #[3, 4] default) + unless groupedClaim == buildClaim groupedFunction #[3, 4] #[30] do + throw (IO.userError "unexpected grouped public claim") + IO.ofExcept (verifyShaped groupedBackend #[3, 4] groupedProof.toBytes) + IO.println "PASS selected grouped program: accepted" + requireRejected "grouped key with ungrouped program" + (buildCompiled { groupedSelection with groups := #[] }) + IO.println "backend binding: 2 accepted, 17 rejected, 0 unexpected outcomes" + +end AiurTests.Backend + +def main : IO Unit := AiurTests.Backend.run diff --git a/Tests/Aiur/Blake3.lean b/Tests/Aiur/Blake3.lean new file mode 100644 index 000000000..6e6b46ebc --- /dev/null +++ b/Tests/Aiur/Blake3.lean @@ -0,0 +1,95 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Blake3 +import Tests.Aiur.EmissionReader + +/-! Compare the total checked hash with the pinned native unkeyed hasher, +Plonky3 wrapper, chunk CVs, and internal parent operations. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.Blake3 AiurTests.EmissionReader + +namespace AiurTests.Blake3 + +private def readBytes : Reader (List UInt8) := do + return (← takeBytes (← readCount 10000000)).data.toList + +private def readDigest : Reader Digest := do + let bytes ← takeBytes 32 + if length : bytes.data.size = 32 then return ⟨bytes.data, length⟩ + else throw "incomplete Blake3 digest" + +private def digestCV (bytes : Digest) : CV := + Vector.ofFn fun word => bytesWord (Vector.ofFn fun byte : Fin 4 => bytes[word.val * 4 + byte.val]) + +private def readHashes : Reader Unit := do + unless (← readNat) == 258 do throw "incomplete Blake3 hash cases" + let mut parents := 0 + for _ in [:258] do + let input ← readBytes + let expected ← readDigest + unless digest input == expected do throw s!"Blake3 digest differs at {input.length} bytes" + unless List.ofFn (hash input) == expected.toList do throw "Blake3 transcript byte order differs" + if input.length > 1024 then + parents := parents + 1 + let split ← readNat + unless leftLen input.length == split do throw "Blake3 canonical split differs" + let left ← readDigest + let right ← readDigest + unless cvBytes (subtree 0 (input.take split)).chainingValue == left do throw "Blake3 left subtree differs" + unless cvBytes (subtree (split / 1024) (input.drop split)).chainingValue == right do throw "Blake3 right subtree differs" + unless (parentOutput (digestCV left) (digestCV right)).rootHash == expected do throw "Blake3 root parent differs" + unless parents == 58 do throw "incomplete Blake3 tree cases" + +private def readChunks : Reader Unit := do + unless (← readNat) == 42 do throw "incomplete Blake3 chunk cases" + let mut highCounters := 0 + for _ in [:42] do + let counter ← readNat + let input ← readBytes + let expected ← readDigest + unless input.length > 0 && input.length ≤ 1024 && counter < 2^54 do throw "inadmissible native chunk case" + if counter ≥ 2^32 then highCounters := highCounters + 1 + let output := chunkOutput counter.toUInt64 input + unless cvBytes output.chainingValue == expected do throw s!"Blake3 chunk differs at {counter}, {input.length}" + unless output.counter.toNat == counter do throw "Blake3 chunk counter changed" + unless output.blockLen.toNat == (input.length - 1) % 64 + 1 do throw "Blake3 final block length differs" + unless output.flags == (if input.length ≤ 64 then 3 else 2) do throw "Blake3 chunk flags differ" + unless highCounters == 12 do throw "incomplete 64-bit chunk counters" + +private def readParents : Reader Unit := do + unless (← readNat) == 64 do throw "incomplete Blake3 parent cases" + for _ in [:64] do + let left ← readDigest + let right ← readDigest + let cv ← readDigest + let root ← readDigest + let merkle ← readDigest + let parent := parentOutput (digestCV left) (digestCV right) + unless cvBytes parent.chainingValue == cv do throw "Blake3 internal parent CV differs" + unless parent.rootHash == root do throw "Blake3 internal parent root differs" + unless digest (left.toList ++ right.toList) == merkle do throw "Blake3 PCS Merkle pair differs" + unless root != merkle do throw "missing distinction between internal parent and Merkle hash" + unless cvBytes (digestCV left) == left && cvBytes (digestCV right) == right do throw "Blake3 CV byte packing differs" + +private def readCorpus : Reader Unit := do + let header := "Aiur Blake3 v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "Blake3 snapshot version differs" + readHashes + readChunks + readParents + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "Blake3 snapshot has trailing bytes" + +end AiurTests.Blake3 + +def main (args : List String) : IO Unit := do + match args with + | [path] => + let bytes ← IO.FS.readBinFile path + match AiurTests.Blake3.readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok _ => IO.println "Blake3: 258 full hashes, 58 subtree splits, 42 chunks and 64 parent/Merkle cases match native" + | _ => throw (IO.userError "expected native Blake3 snapshot") diff --git a/Tests/Aiur/BlockExpressions.lean b/Tests/Aiur/BlockExpressions.lean new file mode 100644 index 000000000..8f892ee2e --- /dev/null +++ b/Tests/Aiur/BlockExpressions.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.BlockLookups +import Ix.Aiur.Proofs.BlockAllocation +import Tests.Aiur.EmissionReader + +/-! Compare actual native control trees and full symbolic block emission, +including incoming gates distinct from block entries and prior outer yields. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.OpEmitter Aiur.NativeAIR.Compiler +open Aiur.NativeAIR.BlockEmitter AiurTests.EmissionReader + +namespace AiurTests.BlockExpressions + +private def readEvaluatedMap (size : Nat) : Reader (Array AIR.RowValue) := do + return (← readList size do return AIR.RowValue.mk (← readField) (← readNat) (← readBool)).toArray + +private def readReport (index : Nat) : Reader Nat := do + let label := s!"block {index}" + let branchless ← readBool + let context : Context := ⟨← readNat, ← readNat, ← readExpr 256⟩ + let selectors := (← readList (← readCount) (readExpr 256)).toArray + let column ← readNat + let lookup ← readNat + let incoming ← readExpr 256 + let inputs ← readMap + let block ← readBlock 64 + let entry ← readExpr 256 + unless blockSelector selectors block == some entry do throw s!"native block selector differs: {label}" + let some emitted := emitBlock selectors context incoming inputs column lookup block + | throw s!"symbolic block rejected native inputs: {label}" + unless (← readNat) == emitted.column && (← readNat) == emitted.lookup do + throw s!"native block cursors differ: {label}" + let nativeMap ← readMap + unless nativeMap == emitted.values do throw s!"native block value expressions or degrees differ: {label}" + let equations ← readList (← readCount 8192) (readExpr 256) + unless equations == emitted.equations do throw s!"native block constraint trees differ: {label}" + unless inputs.all (·.expr.noConstantNegs) && emitted.values.all (·.expr.noConstantNegs) do + throw s!"block lost the negation invariant: {label}" + unless inputs.all (fun row => row.degree != 0 || row.expr.isConstant) && + emitted.values.all (fun row => row.degree != 0 || row.expr.isConstant) do + throw s!"block lost the degree-zero constant invariant: {label}" + let initial : Concrete.Bytecode.LayoutMState := + ⟨{ inputSize := context.inputSize, selectors := 0, auxiliaries := column, lookups := lookup }, + .empty, rowDegrees inputs, #[]⟩ + let layout := ((Concrete.Bytecode.blockLayout block).run initial).2 + unless rowDegrees nativeMap == layout.degrees && emitted.column == layout.functionLayout.auxiliaries do + throw s!"native block degrees or column allocation differs from compiler: {label}" + let lookupCount ← readCount 4096 + unless lookupCount == emitted.lookup + 2 do throw "incomplete native lookup range" + let lookups ← readList lookupCount do + return ExprLookup.mk (← readExpr 256) (← readList (← readCount) (readExpr 256)) + for (native, slot) in lookups.zipIdx do + unless native == BlockEmitter.lookup branchless emitted slot do + throw s!"native block lookup expression trees differ: {label}, slot {slot}" + let yields ← readList (← readCount) do + return YieldExpr.mk (← readExpr 256) (← readMap) + let expectedYields := [YieldExpr.mk (.konst 99) inputs, YieldExpr.mk (.konst 100) inputs] ++ emitted.yields + unless yields.map (fun part => (part.selector, part.values)) == + expectedYields.map (fun part => (part.selector, part.values)) do + throw s!"native escaping yield expression trees differ: {label}" + let count ← readCount + unless count == 4 do throw "incomplete native block assignments" + for seed in [:count] do + let row := (← readList (← readCount 8192) readField).toArray + let values := assignment row + let outputValues ← readEvaluatedMap nativeMap.size + let equationValues ← readList equations.length readField + let some evaluated := emitted.eval values | throw s!"undefined block expression: {label}, assignment {seed}" + unless evaluated.values == outputValues && evaluated.equations == equationValues do + throw s!"native block expression values differ: {label}, assignment {seed}" + let some inputValues := evalRows values inputs | throw "undefined incoming block expressions" + let some selected := selectors.mapM (evalExpr values) | throw "undefined block selectors" + let some s := evalExpr values incoming | throw "undefined incoming gate" + let some rank := evalExpr values context.rank | throw "undefined rank" + let some valued := block.emitRow (fun index => row[index]?.getD 0) (selectorAt selected) + (context.valued rank) s inputValues column lookup + | throw s!"valued block rejected symbolic inputs: {label}" + unless sameBlockEmission evaluated valued do throw s!"symbolic/valued block differs: {label}, assignment {seed}" + for (native, slot) in lookups.zipIdx do + let weight ← readField + let message ← readList native.args.length readField + unless native.eval goldilocksOps values == some (weight, message) do + throw s!"native lookup values differ: {label}, slot {slot}, assignment {seed}" + let expected := if slot == 0 then + (0, AIR.slotMessage branchless (valued.returns.map fun part => (part.1, AIR.functionMessage part.2))) + else (AIR.querySlotMultiplicity valued.queries slot, AIR.slotMessage branchless (AIR.querySlotParts valued.queries slot)) + unless (weight, message) == expected do throw s!"symbolic/valued lookup differs: {label}, slot {slot}" + for yielded in yields do + let gate ← readField + let outputs ← readEvaluatedMap yielded.values.size + unless yielded.eval values == some (gate, outputs) do throw s!"native yield values differ: {label}, assignment {seed}" + return count + +private def readCorpus : Reader Unit := do + let header := "Aiur block expressions v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "block snapshot version differs" + unless (← readCount) == 384 do throw "incomplete native control tree corpus" + let mut assignments := 0 + for index in [:384] do assignments := assignments + (← readReport index) + unless assignments == 1536 do throw "incomplete native block coverage" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "block snapshot has trailing bytes" + +def run (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok _ => IO.println "block expressions: 384 native control trees and compiler allocations, 1,536 assignments match" + +end AiurTests.BlockExpressions + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.BlockExpressions.run path + | _ => throw (IO.userError "expected native block expression snapshot") diff --git a/Tests/Aiur/BlockRows.lean b/Tests/Aiur/BlockRows.lean new file mode 100644 index 000000000..a26d610bb --- /dev/null +++ b/Tests/Aiur/BlockRows.lean @@ -0,0 +1,127 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.QuerySlotMessages + +open Aiur Aiur.AIR Aiur.Bytecode + +namespace AiurTests.BlockRows + +private def appendNat (out : ByteArray) (value : Nat) : ByteArray := Id.run do + let mut out := out + for i in [:8] do + out := out.push ((value >>> (8 * i)) % 256).toUInt8 + return out + +private def appendValues (out : ByteArray) (values : List G) : ByteArray := + values.foldl (fun out value => appendNat out value.n) (appendNat out values.length) + +private def appendMap (out : ByteArray) (values : Array RowValue) : ByteArray := + values.foldl (fun out value => appendNat (appendNat (appendNat out value.value.n) + value.degree) (if value.constant then 1 else 0)) (appendNat out values.size) + +private def blockOps (seed initial : Nat) : Array Op × Nat := + let size := seed % 3 + let pointer := initial + 3 + size + (#[.const (G.ofNat (seed + 17)), .mul 0 1, + .eqZero (if seed % 2 == 0 then initial else 0), + .call 17 #[0, initial] size false, .store #[0, initial + 1], + .load size pointer, .u8Add 0 1, .assertEq #[initial + 1] #[0] none], + initial + 6 + 2 * size) + +private def fixture (depth seed initial next : Nat) : Block × Nat := + let (ops, count) := blockOps seed initial + let leaf := (⟨ops, if seed % 2 == 0 then .return next #[count - 2, count - 1] + else .yield next #[count - 2, count - 1]⟩, next + 1) + match depth with + | 0 => leaf + | depth + 1 => + if seed % 5 == 0 then leaf else + let (left, next) := fixture depth (seed * 3 + 1) count next + let (right, next) := fixture depth (seed * 3 + 2) count next + let (fallback, next) := if seed % 2 == 0 then + let (block, next) := fixture depth (seed * 3 + 3) count next + (some block, next) + else (none, next) + let branches := #[(0, left), (1, right)] + let matched := if seed % 2 == 0 then initial else 0 + if seed % 3 == 0 then (⟨ops, .match matched branches fallback⟩, next) + else + let (continuation, next) := fixture depth (seed * 3 + 4) (count + 2) next + (⟨ops, .matchContinue matched branches fallback 2 0 0 continuation⟩, next) + +private def assignment (pattern index count : Nat) : G := + match pattern with + | 0 => 0 + | 1 => 1 + | 2 => 2 + | 3 => 0 - 1 + | 4 => G.ofNat (index + 1) + | 5 => 0 - G.ofNat (index + 1) + | 6 => if index % 2 == 0 then 1 else 0 + | 7 => [0, 0 - 1, 1, 2][index % 4]?.getD 0 + | pattern => if pattern < 8 + count then + (if index == pattern - 8 then 1 else 0) + else if index != pattern - 8 - count then 1 else 0 + +private def row (seed pattern count index : Nat) : G := + if 2 ≤ index ∧ index < 2 + count then assignment pattern (index - 2) count + else + let choices : List G := [0, 1, 0 - 1, 255, 256, G.ofNat (2^32), G.ofNat (2^48 - 1), 17] + choices[(seed + 5 * index) % 8]?.getD 0 + +private def expected : Except String (ByteArray × Nat) := do + let mut out := appendNat "Aiur block rows v1\n".toUTF8 96 + let mut checked := 0 + for branchless in [false, true] do + for depth in [:4] do + for seed in [:12] do + let (block, count) := fixture depth seed 2 0 + out := appendNat out count + out := appendNat out (8 + 2 * count) + for pattern in [:8 + 2 * count] do + let row := row seed pattern count + let selector := fun index => row (2 + index) + let values := #[RowValue.variable (row 0), RowValue.variable (row 1)] + let some emission := block.emitRow row selector ⟨37, 2, 257⟩ + (block.selectorFlow selector).entry values (2 + count) 1 + | throw s!"emission failed at depth {depth}, seed {seed}, pattern {pattern}" + out := appendNat out emission.column + out := appendNat out emission.lookup + out := appendMap out emission.values + out := appendValues out emission.equations + for slot in [:emission.lookup] do + let parts := if slot == 0 then emission.returns.map fun part => + (part.1, functionMessage part.2) + else querySlotParts emission.queries slot + out := appendNat out (if slot == 0 then 0 else querySlotMultiplicity emission.queries slot).n + out := appendValues out (slotMessage branchless parts) + let yields := [(99, values), (100, values)] ++ emission.yields + out := appendNat out yields.length + for (gate, values) in yields do + out := appendNat out gate.n + out := appendMap out values + checked := checked + 1 + return (out, checked) + +def run (path : System.FilePath) : IO Unit := do + let native ← IO.FS.readBinFile path + let (expected, checked) ← match expected with + | .ok value => pure value + | .error error => throw (IO.userError error) + unless checked == 2028 do throw (IO.userError "incomplete block-row corpus") + unless native.size == expected.size do + throw (IO.userError s!"block-row snapshot size differs: {native.size} / {expected.size}") + for i in [:expected.size] do + unless native[i]! == expected[i]! do + throw (IO.userError s!"block-row mismatch at byte {i}: {native[i]!} / {expected[i]!}") + IO.println s!"block rows: {checked} native/Lean assignments with shared columns and slots match" + +end AiurTests.BlockRows + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.BlockRows.run path + | _ => throw (IO.userError "expected native block-row snapshot path") diff --git a/Tests/Aiur/ByteGadgets.lean b/Tests/Aiur/ByteGadgets.lean new file mode 100644 index 000000000..01aed8bd2 --- /dev/null +++ b/Tests/Aiur/ByteGadgets.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ByteColumns + +/-! Exhaustive comparison with the actual Rust preprocessed byte-chip rows, +lookup arguments and multiplicity columns. The component gate exports its +native file into a temporary directory before running this comparison. -/ + +open Aiur Aiur.AIR + +namespace Tests.Aiur.ByteGadgets + +private def appendNat (bytes : ByteArray) (value : Nat) : ByteArray := Id.run do + let mut bytes := bytes + for index in [:8] do + bytes := bytes.push ((value >>> (8 * index)) % 256).toUInt8 + return bytes + +private def appendValues (bytes : ByteArray) (values : List G) : ByteArray := + values.foldl (fun bytes value => appendNat bytes value.n) bytes + +private def byte1Snapshot (bytes : ByteArray) : ByteArray := Id.run do + let mut bytes := appendNat (appendNat (appendNat bytes 256) 11) 3 + for width in [10, 3, 3] do bytes := appendNat bytes width + for index in [:256] do + if h : index < 256 then + let row : Fin 256 := ⟨index, h⟩ + bytes := appendValues bytes (byte1Preprocessed row).toList + for kind in Byte1Kind.all do + let (multiplicity, message) := byte1ColumnLookup kind (byte1PreprocessedColumns row) + (fun column => G.ofNat (column.val + 17)) + bytes := appendNat bytes multiplicity.n + bytes := appendValues bytes message + return bytes + +private def byte2Snapshot (bytes : ByteArray) : ByteArray := Id.run do + let mut bytes := appendNat (appendNat (appendNat bytes 65536) 14) 10 + for width in [4, 4, 4, 4, 4, 4, 3, 5, 5, 5] do bytes := appendNat bytes width + for index in [:65536] do + if h : index < 65536 then + let row : Fin 65536 := ⟨index, h⟩ + bytes := appendValues bytes (byte2Preprocessed row).toList + for kind in Byte2Kind.all do + let (multiplicity, message) := byte2ColumnLookup kind (byte2PreprocessedColumns row) + (fun column => G.ofNat (column.val + 17)) + bytes := appendNat bytes multiplicity.n + bytes := appendValues bytes message + return bytes + +private def expected : ByteArray := + byte2Snapshot (byte1Snapshot "Aiur byte gadgets v1\n".toUTF8) + +def main (args : List String) : IO Unit := do + let [path] := args | throw (IO.userError "expected native byte-gadget snapshot path") + let native ← IO.FS.readBinFile path + let reference := expected + unless native == reference do + let mut first : Option Nat := none + for index in [:min native.size reference.size] do + if native[index]! != reference[index]! then + first := some index + break + throw (IO.userError s!"Byte gadget snapshot differs: native {native.size} bytes, reference {reference.size}; first mismatch {first}") + IO.println s!"Byte gadgets: all 65,792 rows, 656,128 lookup messages and multiplicity columns match ({native.size} bytes)." + +end Tests.Aiur.ByteGadgets + +def main := Tests.Aiur.ByteGadgets.main diff --git a/Tests/Aiur/BytecodeCompare.lean b/Tests/Aiur/BytecodeCompare.lean new file mode 100644 index 000000000..0633fc2e9 --- /dev/null +++ b/Tests/Aiur/BytecodeCompare.lean @@ -0,0 +1,70 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Stages.Bytecode + +/-! Native comparison/hash compatibility fixtures. The frozen output was +captured from the original compiler derivations before making them total. +Every operation constructor and all control forms occur, including nested +branches, defaults, continuations and deliberately different metadata. -/ + +open Aiur Aiur.Bytecode + +namespace Tests.Aiur.BytecodeCompare + +private def operations (n : Nat) : Array Op := + let a := #[n, n + 1, n + 2, n + 3] + #[.const (G.ofNat n), .add n (n + 1), .sub n (n + 1), .mul n (n + 1), + .eqZero n, .call n a 4 false, .call n a 4 true, .call n #[] 0 false, + .store a, .load 4 n, .assertEq a a none, .assertEq a a (some "same fields"), + .ioGetInfo n a, .ioSetInfo n a n (n + 1), .ioRead n (n + 1) 4, .ioWrite n a, + .u8BitDecomposition n, .u8ShiftLeft n, .u8ShiftRight n, + .u8Xor n (n + 1), .u8Add n (n + 1), .u8Mul n (n + 1), .u8Sub n (n + 1), + .u8And n (n + 1), .u8Or n (n + 1), .u8LessThan n (n + 1), .u32LessThan n (n + 1), + .u8XorSplit7 n (n + 1), .u8XorSplit4 n (n + 1), + .debug "comparison fixture" none, .debug "comparison fixture" (some a), + .u8RangeCheck n (n + 1), .unconstrainedBigUintDivMod n (n + 1), + .unconstrainedGToBytes n, .unconstrainedGInverse n, + .unconstrainedU32Add a a.reverse, .unconstrainedU32Add3 a a.reverse a, + .u32ToField a] + +def fixtures : Array Block := Id.run do + let mut blocks := #[] + for n in #[0, 1, 255, 256, 65536] do + let ret : Block := ⟨#[], .return n #[n, n + 1]⟩ + let yielded : Block := ⟨#[], .yield n #[n, n + 1]⟩ + blocks := blocks ++ #[ret, yielded] + for op in operations n do + blocks := blocks.push ⟨#[op], ret.ctrl⟩ + for fallback in #[none, some ret, some yielded] do + for branches in #[#[], #[(G.ofNat n, ret)], #[(G.ofNat n, ret), (G.ofNat (n + 1), yielded)]] do + blocks := blocks.push ⟨#[], .match n branches fallback⟩ + for metadata in #[0, 1, 7] do + blocks := blocks.push ⟨#[], .matchContinue n branches fallback metadata + (n + metadata + 1) (2 * metadata + 3) ret⟩ + -- Long shared prefixes and deep control trees exercise recursive calls + -- beyond the immediate constructor comparisons. + let mut nested := ret + for depth in [:24] do + nested := ⟨(operations n).extract 0 (depth % 8), + .matchContinue n #[(G.ofNat depth, nested)] (some yielded) 2 depth (depth + 1) ret⟩ + blocks := blocks ++ #[nested, nested, ⟨(operations n).reverse, nested.ctrl⟩] + return blocks + +private def report (blocks : Array Block) : IO Unit := do + IO.println s!"BYTECODE COMPARISON FIXTURES {blocks.size}" + for h : i in [:blocks.size] do + let block := blocks[i] + unless block == block do throw (IO.userError s!"block comparison is not reflexive: {i}") + let mut equalIndices : Array Nat := #[] + for k : j in [:blocks.size] do + if block == blocks[j] then equalIndices := equalIndices.push j + IO.println s!"BLOCK {i} HASH {hash block} CONTROL {hash block.ctrl} EQUAL {equalIndices}" + +def main : IO Unit := report fixtures + +end Tests.Aiur.BytecodeCompare + +def main := Tests.Aiur.BytecodeCompare.main diff --git a/Tests/Aiur/CircuitExpressions.lean b/Tests/Aiur/CircuitExpressions.lean new file mode 100644 index 000000000..d1fea1593 --- /dev/null +++ b/Tests/Aiur/CircuitExpressions.lean @@ -0,0 +1,121 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CheckedCircuit +import Tests.Aiur.EmissionReader + +/-! Actual native function and circuit records drive both symbolic and valued +emission. Check all frontend expression trees, physical slots, and metadata. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.OpEmitter Aiur.NativeAIR.Compiler +open Aiur.NativeAIR.CircuitEmitter AiurTests.EmissionReader + +namespace AiurTests.CircuitExpressions + +private def readLayout : Reader Bytecode.FunctionLayout := do + return ⟨← readNat, ← readNat, ← readNat, ← readNat⟩ + +private def sameMember (left right : AIR.MemberEmission) : Bool := + left.functionIndex == right.functionIndex && left.selectorBase == right.selectorBase && + left.function.layout == right.function.layout && left.function.entry == right.function.entry && + left.function.constrained == right.function.constrained && sameBlockEmission left.body right.body + +private def sameEmission (left right : AIR.CircuitEmission) : Bool := + left.members.length == right.members.length && (left.members.zip right.members).all (fun (a, b) => sameMember a b) && + left.selector == right.selector && left.multiplicity == right.multiplicity && + List.ofFn left.rankBytes == List.ofFn right.rankBytes && + left.width == right.width && left.selectorStart == right.selectorStart && left.selectorCount == right.selectorCount && + left.lookupCount == right.lookupCount && left.branchless == right.branchless && left.equations == right.equations && + left.queries.map (fun part => (part.slot, part.selector, part.message)) == + right.queries.map (fun part => (part.slot, part.selector, part.message)) && left.returns == right.returns + +private def readCircuit (program : Bytecode.Toplevel) (circuit : Bytecode.Circuit) (label : String) : Reader Nat := do + unless circuit.validateRowCounts program do throw s!"native circuit fails checked selector bounds: {label}" + unless 7 ≤ circuit.layout.auxiliaries && circuit.members.all (fun index => + program.functions[index]!.layout.inputSize ≤ circuit.layout.inputSize && + program.functions[index]!.layout.auxiliaries ≤ circuit.layout.auxiliaries) do + throw s!"native circuit fails compiler column bounds: {label}" + let some emitted := emitCircuit program circuit | throw s!"symbolic circuit rejected native inputs: {label}" + unless (← readBool) == emitted.branchless do throw s!"native circuit branchless decision differs: {label}" + unless (← readNat) == emitted.width && (← readNat) == emitted.selectorStart && (← readNat) == emitted.selectorCount do + throw s!"native circuit column layout differs: {label}" + unless emitted.readBound ≤ emitted.width do throw s!"circuit read premise exceeds native width: {label}" + let equations ← readList (← readCount 8192) (readExpr 256) + unless equations == emitted.equations do throw s!"native circuit constraint trees differ: {label}" + let lookups ← readList (← readCount 4096) do + return ExprLookup.mk (← readExpr 256) (← readList (← readCount) (readExpr 256)) + unless lookups == emitted.lookups do throw s!"native circuit lookup trees differ: {label}" + let inactiveValues := zeroValues circuit.layout.width + let some inactive := emitted.eval inactiveValues + | throw s!"inactive circuit row has an undefined expression: {label}" + unless inactive.equations.all (· == 0) do throw s!"inactive circuit equation is nonzero: {label}" + let some compiled := compileCircuit (circuitWidths circuit) program circuit + | throw s!"base compilation rejected native circuit expressions: {label}" + let count ← readCount + unless count == 4 do throw "incomplete native circuit assignments" + for seed in [:count] do + let row := (← readList (← readCount 8192) readField).toArray + unless row.size == emitted.width do throw "native circuit assignment has wrong width" + let values := assignment row + let expectedEquations ← readList equations.length readField + let some evaluated := emitted.eval values | throw s!"undefined circuit expression: {label}, assignment {seed}" + unless evaluated.equations == expectedEquations do throw s!"native circuit values differ: {label}, assignment {seed}" + let some valued := circuit.emitRow (fun index => row[index]?.getD 0) program + | throw s!"valued circuit rejected symbolic inputs: {label}" + unless sameEmission evaluated valued do throw s!"symbolic/valued circuit differs: {label}, assignment {seed}" + let some buffer := compiled.base.graph.sweep goldilocksOps values + | throw s!"compiled circuit sweep is undefined: {label}" + let some graphLookups := compiled.base.graph.lookups.mapM (readLookup buffer) + | throw s!"compiled circuit lookup roots are undefined: {label}" + unless graphLookups == List.ofFn (fun slot : Fin valued.lookupCount => valued.lookup slot.val) do + throw s!"compiled circuit lookup meanings differ: {label}, assignment {seed}" + unless compiled.base.graph.zeros.all (fun root => buffer[root]? == some 0) == valued.equations.all (· == 0) do + throw s!"compiled circuit satisfaction differs: {label}, assignment {seed}" + for (lookup, slot) in lookups.zipIdx do + let weight ← readField + let message ← readList lookup.args.length readField + unless lookup.eval goldilocksOps values == some (weight, message) do + throw s!"native circuit lookup values differ: {label}, slot {slot}, assignment {seed}" + unless valued.lookup slot == (weight, message) do throw s!"symbolic/valued circuit lookup differs: {label}, slot {slot}" + return count + +private def readCorpus : Reader Unit := do + let header := "Aiur circuit expressions v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "circuit snapshot version differs" + unless (← readCount) == 12 do throw "incomplete native circuit programs" + let mut reports := 0 + let mut assignments := 0 + for seed in [:12] do + let functions := (← readList (← readCount) do + return Bytecode.Function.mk (← readBlock 64) (← readLayout) (← readBool) (← readBool)).toArray + let circuits := (← readList (← readCount) do + return Bytecode.Circuit.mk "native" (← readIndices) (← readLayout)).toArray + unless functions.size == 4 && circuits.size == 8 do throw "incomplete native circuit shapes" + for (function, index) in functions.toList.zipIdx do + let layout := ((Concrete.Bytecode.blockLayout function.body).run + (.new function.layout.inputSize)).2.functionLayout + unless function.layout == { layout with lookups := layout.lookups + 1 } do + throw s!"native function layout differs from compiler: program {seed}, function {index}" + let program : Bytecode.Toplevel := ⟨functions, #[], circuits, #[]⟩ + unless program.validateEmission do throw s!"native program fails checked emission inputs: {seed}" + for (circuit, index) in circuits.toList.zipIdx do + assignments := assignments + (← readCircuit program circuit s!"program {seed}, circuit {index}") + reports := reports + 1 + unless reports == 96 && assignments == 384 do throw "incomplete native circuit coverage" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "circuit snapshot has trailing bytes" + +def run (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok _ => IO.println "circuit expressions: 96 native circuit bounds, 48 compiler function layouts, 384 assignments and 96 inactive zero rows match" + +end AiurTests.CircuitExpressions + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.CircuitExpressions.run path + | _ => throw (IO.userError "expected native circuit expression snapshot") diff --git a/Tests/Aiur/CircuitRows.lean b/Tests/Aiur/CircuitRows.lean new file mode 100644 index 000000000..ed36178cd --- /dev/null +++ b/Tests/Aiur/CircuitRows.lean @@ -0,0 +1,169 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CircuitRows +import Ix.Aiur.RowCounts + +open Aiur Aiur.AIR Aiur.Bytecode + +namespace AiurTests.CircuitRows + +private def appendNat (out : ByteArray) (value : Nat) : ByteArray := Id.run do + let mut out := out + for i in [:8] do + out := out.push ((value >>> (8 * i)) % 256).toUInt8 + return out + +private def appendValues (out : ByteArray) (values : List G) : ByteArray := + values.foldl (fun out value => appendNat out value.n) (appendNat out values.length) + +private def blockOps (seed initial : Nat) : Array Op × Nat := + let size := seed % 3 + let pointer := initial + 3 + size + (#[.const (G.ofNat (seed + 17)), .mul 0 1, + .eqZero (if seed % 2 == 0 then initial else 0), + .call 17 #[0, initial] size false, .store #[0, initial + 1], + .load size pointer, .u8Add 0 1, .assertEq #[initial + 1] #[0] none], + initial + 6 + 2 * size) + +private def fixture (depth seed initial next : Nat) : Block × Nat := + let (ops, count) := blockOps seed initial + let leaf := (⟨ops, if seed % 2 == 0 then .return next #[count - 2, count - 1] + else .yield next #[count - 2, count - 1]⟩, next + 1) + match depth with + | 0 => leaf + | depth + 1 => + if seed % 5 == 0 then leaf else + let (left, next) := fixture depth (seed * 3 + 1) count next + let (right, next) := fixture depth (seed * 3 + 2) count next + let (fallback, next) := if seed % 2 == 0 then + let (block, next) := fixture depth (seed * 3 + 3) count next + (some block, next) + else (none, next) + let branches := #[(0, left), (1, right)] + let matched := if seed % 2 == 0 then initial else 0 + if seed % 3 == 0 then (⟨ops, .match matched branches fallback⟩, next) + else + let (continuation, next) := fixture depth (seed * 3 + 4) (count + 2) next + (⟨ops, .matchContinue matched branches fallback 2 0 0 continuation⟩, next) + +private def closeReturns (width : Nat) (escapes : Bool) : Nat → Block → Block + | 0, block => block + | fuel + 1, block => { block with ctrl := match block.ctrl with + | .return index outputs => .return index (outputs.extract 0 width) + | .yield index outputs => if escapes then .return index (outputs.extract 0 width) else .yield index outputs + | .match index branches fallback => .match index + (branches.map fun pair => (pair.1, closeReturns width escapes fuel pair.2)) + (fallback.map (closeReturns width escapes fuel)) + | .matchContinue index branches fallback size aux slots continuation => .matchContinue index + (branches.map fun pair => (pair.1, closeReturns width false fuel pair.2)) + (fallback.map (closeReturns width false fuel)) size aux slots + (closeReturns width escapes fuel continuation) } + +private def fixtureFunction (seed index : Nat) : Except String Function := do + let inputSize := 2 + (seed + index) % 3 + let depth := (seed + index) % 3 + let (body, selectors) := fixture depth (seed * 4 + index) inputSize 0 + let body := closeReturns (index % 3) true (depth + 1) body + let body := if seed % 4 == 0 && index == 0 then + { ops := #[], ctrl := .match 0 #[(0, { ops := #[.store #[]], ctrl := .match 0 #[] none }), (1, body)] none } + else body + let some measured := body.emitRow (fun _ => 0) (fun _ => 0) ⟨37, inputSize, 0⟩ + (body.selectorFlow (fun _ => 0)).entry (rowAdvice (fun _ => 0) 0 inputSize) + (inputSize + selectors + 7) 4 + | throw "fixture layout emission failed" + return ⟨body, ⟨inputSize, selectors, measured.column - inputSize - selectors, measured.lookup⟩, true, true⟩ + +private def circuitLayout (functions : Array Function) (members : Array Nat) : Bytecode.FunctionLayout := + members.foldl (fun layout index => match functions[index]? with + | none => layout + | some function => layout.merge function.layout) ⟨0, 0, 7, 4⟩ + +private def groups : List (Array Nat) := [#[0], #[1], #[2], #[3], #[0, 1], #[2, 0, 3], #[3, 2, 1, 0], #[]] + +private def assignment (pattern index count : Nat) : G := + match pattern with + | 0 => 0 + | 1 => 1 + | 2 => 2 + | 3 => 0 - 1 + | 4 => G.ofNat (index + 1) + | 5 => 0 - G.ofNat (index + 1) + | 6 => if index % 2 == 0 then 1 else 0 + | 7 => [0, 0 - 1, 1, 2][index % 4]?.getD 0 + | pattern => if pattern < 8 + count then + (if index == pattern - 8 then 1 else 0) + else if index != pattern - 8 - count then 1 else 0 + +private def row (seed pattern start count index : Nat) : G := + if start ≤ index ∧ index < start + count then assignment pattern (index - start) count + else + let choices : List G := [0, 1, 0 - 1, 255, 256, G.ofNat (2^32), G.ofNat (2^48 - 1), 17] + choices[(seed + 5 * index + 3 * pattern) % 8]?.getD 0 + +private def expected : Except String (ByteArray × Nat) := do + let mut out := appendNat "Aiur circuit rows v3\n".toUTF8 96 + let mut checked := 0 + for seed in [:12] do + let functions ← (List.range 4).mapM (fixtureFunction seed) + let functions := functions.toArray + let circuits := groups.map fun members => Circuit.mk "fixture" members (circuitLayout functions members) + let top : Toplevel := ⟨functions, #[], circuits.toArray, #[]⟩ + for function in functions do + let counts := function.body.controlCounts + unless counts.leaves == function.layout.selectors do throw "leaf allocation differs" + for count in [counts.nodes, counts.leaves, counts.returns, counts.yields] do + out := appendNat out count + unless top.validateRowCounts do throw "circuit count validation failed" + out := out.push (if top.validateRowCounts then 1 else 0) + for circuit in circuits do + let layout := circuit.layout + for limit in [0, layout.selectors - 1, layout.selectors, layout.selectors + 1] do + let variant := { circuit with layout := { layout with selectors := limit } } + out := out.push (if variant.validateRowCounts top then 1 else 0) + let missing := { circuit with members := circuit.members.push functions.size } + unless !missing.validateRowCounts top do throw "missing circuit member accepted" + out := out.push (if missing.validateRowCounts top then 1 else 0) + let doubled := { circuit with members := circuit.members ++ circuit.members } + out := out.push (if doubled.validateRowCounts top then 1 else 0) + let branchless := circuitBranchless layout.selectors + (circuit.members.toList.filterMap fun index => functions[index]?) + out := out.push (if branchless then 1 else 0) + out := appendNat out layout.width + out := appendNat out layout.inputSize + out := appendNat out layout.selectors + out := appendNat out layout.lookups + out := appendNat out (8 + 2 * layout.selectors) + for pattern in [:8 + 2 * layout.selectors] do + let row := row seed pattern layout.inputSize layout.selectors + let some emission := circuit.emitRow row top | throw "circuit emission failed" + unless emission.branchless == branchless do throw "branchless selection differs" + out := appendValues out emission.equations + for slot in [:layout.lookups] do + let (multiplicity, message) := emission.lookup slot + out := appendNat out multiplicity.n + out := appendValues out message + checked := checked + 1 + return (out, checked) + +def run (path : System.FilePath) : IO Unit := do + let native ← IO.FS.readBinFile path + let (expected, checked) ← match expected with + | .ok value => pure value + | .error error => throw (IO.userError error) + unless checked == 2022 do throw (IO.userError "incomplete circuit-row corpus") + unless native.size == expected.size do + throw (IO.userError s!"circuit-row snapshot size differs: {native.size} / {expected.size}") + for i in [:expected.size] do + unless native[i]! == expected[i]! do + throw (IO.userError s!"circuit-row mismatch at byte {i}: {native[i]!} / {expected[i]!}") + IO.println s!"circuit rows: {checked} native/Lean assignments, 48 control counts, 588 count checks and 96 branchless decisions match" + +end AiurTests.CircuitRows + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.CircuitRows.run path + | _ => throw (IO.userError "expected native circuit-row snapshot path") diff --git a/Tests/Aiur/CompiledKey.lean b/Tests/Aiur/CompiledKey.lean new file mode 100644 index 000000000..ce92d52c4 --- /dev/null +++ b/Tests/Aiur/CompiledKey.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CompiledKey +import Tests.Aiur.EmissionReader + +/-! Compare complete native keys and wide matrix assignments with the checked +compiler and physical row models. Structurally valid altered keys must fail +the executable circuit-binding check. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.Compiler Aiur.NativeAIR.CircuitEmitter +open AiurTests.EmissionReader + +namespace AiurTests.CompiledKeys + +private def readLayout : Reader Bytecode.FunctionLayout := do + return ⟨← readNat, ← readNat, ← readNat, ← readNat⟩ + +private def readColumns (width : Nat) : Reader (Array G) := do + let columns := (← readList (← readCount 65536) readField).toArray + unless columns.size == width do throw "native key matrix width differs" + return columns + +private def readValues (widths : GraphWidths) : Reader (Values G) := do + let pre ← readColumns widths.preprocessed + let preNext ← readColumns widths.preprocessed + let main ← readColumns widths.main + let mainNext ← readColumns widths.main + let stage2 ← readColumns widths.stage2 + let stage2Next ← readColumns widths.stage2 + let publics ← readColumns widths.publics + return { + columns := fun source offset => match source, offset with + | .preprocessed, .current => pre | .preprocessed, .next => preNext + | .main, .current => main | .main, .next => mainNext + | .stage2, .current => stage2 | .stage2, .next => stage2Next + publics, isFirstRow := ← readField, isLastRow := ← readField, isTransition := ← readField } + +private def readCircuit (program : Bytecode.Toplevel) (index : Nat) (artifact : KeyCodec.Circuit) : Reader Nat := do + unless (← readCount) == 4 do throw "incomplete native key assignments" + for seed in [:4] do + let label := s!"circuit {index}, assignment {seed}" + let values ← readValues artifact.widths + let equations ← readList (← readCount 65536) readField + let lookups ← readList (← readCount 65536) do + return (← readField, ← readList (← readCount 65536) readField) + let some buffer := artifact.graph.sweep goldilocksOps values | throw s!"undefined native graph: {label}" + unless artifact.graph.zeros.all (fun root => buffer[root]? == some 0) == equations.all (· == 0) do + throw s!"native key graph satisfaction differs: {label}" + unless artifact.graph.lookups.mapM (readLookup buffer) == some lookups do + throw s!"native key graph lookup values differ: {label}" + if index < program.circuits.size then + let source := program.circuits[index]! + let some symbolic := compileCircuit artifact.widths program source + | throw s!"compilation at native widths rejected: {label}" + unless symbolic.base.graph == artifact.graph do throw s!"widened graph differs: {label}" + let some emission := source.emitRow (fun column => (values.columns .main .current)[column]?.getD 0) program + | throw s!"native key function row rejected: {label}" + unless emission.equations == equations && + List.ofFn (fun slot : Fin emission.lookupCount => emission.lookup slot.val) == lookups do + throw s!"native key function meaning differs: {label}" + else if index < program.circuits.size + program.memorySizes.size then + let width := program.memorySizes[index - program.circuits.size]! + let current := CompiledKey.columns values .main .current (3 + width) + let next := CompiledKey.columns values .main .next (3 + width) + unless AIR.memoryColumnEquations width current next values.isTransition == equations && + [AIR.memoryColumnLookup width current] == lookups do + throw s!"native key memory meaning differs: {label}" + else if index == program.circuits.size + program.memorySizes.size then + unless equations.isEmpty && lookups == (AIR.Byte1Kind.all.map fun kind => AIR.byte1ColumnLookup kind + (CompiledKey.columns values .preprocessed .current 11) (CompiledKey.columns values .main .current 3)) do + throw s!"native key byte1 meaning differs: {label}" + else + unless equations.isEmpty && lookups == (AIR.Byte2Kind.all.map fun kind => AIR.byte2ColumnLookup kind + (CompiledKey.columns values .preprocessed .current 14) (CompiledKey.columns values .main .current 10)) do + throw s!"native key byte2 meaning differs: {label}" + return 4 + +private def rejectAltered (program : Bytecode.Toplevel) (original altered : KeyCodec.Key) (label : String) : Reader Unit := do + unless altered != original do throw s!"ineffective altered-key case: {label}" + unless KeyCodec.decodeCanonical (KeyCodec.encode altered) == some altered do + throw s!"altered key must retain valid canonical syntax: {label}" + if CompiledKey.check program altered then throw s!"altered native key accepted: {label}" + +private def alterations (program : Bytecode.Toplevel) (key : KeyCodec.Key) : Reader Nat := do + let some first := key.circuits.head? | throw "missing native function circuit" + let some lookup := first.graph.lookups.head? | throw "missing native function lookup" + let changedCircuits : List (String × KeyCodec.Circuit) := [ + ("unused node", { first with graph.nodes := first.graph.nodes ++ [.konst 17] }), + ("missing constraint", { first with graph.zeros := first.graph.zeros.drop 1 }), + ("extra constraint", { first with graph := { first.graph with + nodes := first.graph.nodes ++ [.konst 0], zeros := first.graph.zeros ++ [first.graph.nodes.length] } }), + ("missing lookup", { first with graph.lookups := first.graph.lookups.drop 1 }), + ("zeroed provider", { first with graph := { first.graph with + nodes := first.graph.nodes ++ [.konst 0], + lookups := first.graph.lookups.set 0 { lookup with multiplicity := first.graph.nodes.length } } }), + ("extended message", { first with graph.lookups := first.graph.lookups.set 0 { lookup with args := lookup.args ++ [lookup.multiplicity] } }), + ("main width", { first with mainWidth := first.mainWidth + 1 }), + ("preprocessed width", { first with preprocessedWidth := first.preprocessedWidth + 1 }), + ("preprocessed height", { first with preprocessedHeight := first.preprocessedHeight + 1 }), + ("lookup grouping", { first with lookupGroupSize := if first.lookupGroupSize == 1 then 2 else 1 })] + for (label, raw) in changedCircuits do + let some degree := raw.computedDegree | throw s!"undefined altered graph degree: {label}" + let circuit := { raw with maxConstraintDegree := degree } + rejectAltered program key { key with circuits := key.circuits.set 0 circuit } label + rejectAltered program key { key with circuits := key.circuits.reverse, preprocessedIndices := key.preprocessedIndices.reverse } "reversed circuit order" + rejectAltered program key { key with circuits := first :: key.circuits, preprocessedIndices := none :: key.preprocessedIndices } "extra circuit" + rejectAltered program key { key with circuits := key.circuits.tail, preprocessedIndices := key.preprocessedIndices.tail } "missing circuit" + rejectAltered program key { key with preprocessedIndices := key.preprocessedIndices.set 0 (some 0) } "preprocessed index" + return changedCircuits.length + 4 + +private def readCorpus : Reader (Nat × Nat × Nat) := do + let header := "Aiur compiled keys v2\n".toUTF8 + unless (← takeBytes header.size) == header do throw "compiled-key snapshot version differs" + unless (← readCount) == 12 do throw "incomplete native key systems" + let mut circuitCount := 0 + let mut assignments := 0 + let mut rejections := 0 + for seed in [:12] do + let functions := (← readList (← readCount) do + return Bytecode.Function.mk (← readBlock 64) (← readLayout) (← readBool) (← readBool)).toArray + let circuits := (← readList (← readCount) do + return Bytecode.Circuit.mk "native" (← readIndices) (← readLayout)).toArray + let memorySizes ← readIndices + let program : Bytecode.Toplevel := ⟨functions, memorySizes, circuits, #[]⟩ + let bytes ← takeBytes (← readCount 1048576) + let some key := KeyCodec.decodeCanonical bytes | throw s!"native key rejected: system {seed}" + unless key.parameters.logBlowup == 1 + seed % 3 do throw "incomplete native lookup-group budgets" + unless CompiledKey.check program key do throw s!"native key differs from compiled program: system {seed}" + unless functions.size == 4 && circuits.size == 8 && memorySizes == #[0, 1, 2, 4, 8] && key.circuits.length == 15 do + throw "incomplete native key circuit families" + for (artifact, index) in key.circuits.zipIdx do + assignments := assignments + (← readCircuit program index artifact) + circuitCount := circuitCount + 1 + rejections := rejections + (← alterations program key) + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "compiled-key snapshot has trailing bytes" + return (circuitCount, assignments, rejections) + +def run (path : System.FilePath) : IO Unit := do + match readCorpus.run (← IO.FS.readBinFile path, 0) with + | .error error => throw (IO.userError error) + | .ok ((circuits, assignments, rejections), _) => + unless circuits == 180 && assignments == 720 && rejections == 168 do + throw (IO.userError "incomplete native key coverage") + IO.println s!"compiled keys: 12 native systems, {circuits} circuits, {assignments} assignments match; {rejections} valid altered keys rejected" + +end AiurTests.CompiledKeys + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.CompiledKeys.run path + | _ => throw (IO.userError "expected native compiled-key snapshot") diff --git a/Tests/Aiur/ConstantDegree.lean b/Tests/Aiur/ConstantDegree.lean new file mode 100644 index 000000000..2f32c28a3 --- /dev/null +++ b/Tests/Aiur/ConstantDegree.lean @@ -0,0 +1,65 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur + +/-! Source-to-proof regressions for constants produced by expression folding +whose conservative compiler degree remains positive. -/ + +open Aiur + +namespace AiurTests.ConstantDegree + +def source := ⟦ + fn zero_left(x: G) -> G { eq_zero(0 * x) } + fn zero_right(x: G) -> G { eq_zero(x * 0) } + fn shifted_one(x: G) -> G { eq_zero(0 * x + 1) } + fn negated_zero(x: G) -> G { eq_zero(0 - 0 * x) } + fn nested_zero(x: G) -> G { eq_zero(eq_zero(0 * x)) } + fn following_mul(x: G) -> G { eq_zero(0 * x) * x } + pub fn check(x: G) -> [G; 6] { + [zero_left(x), zero_right(x), shifted_one(x), negated_zero(x), nested_zero(x), following_mul(x)] + } +⟧ + +def run : IO Unit := do + let decls ← IO.ofExcept (source.mkDecls.mapError toString) + let compiled ← IO.ofExcept source.compile + let cp : CommitmentParameters := { logBlowup := 1, capHeight := 0 } + let fp : FriParameters := { + logFinalPolyLen := 0, maxLogArity := 1, numQueries := 64, + commitProofOfWorkBits := 0, queryProofOfWorkBits := 0 } + let grouped ← IO.ofExcept (compiled.groupFunctions #[ + ("zeroes", #["zero_left", "zero_right"]), + ("shifted", #["shifted_one", "negated_zero"])]) + let mut accepted := 0 + let mut rejected := 0 + for program in [compiled, grouped] do + let some index := program.getFuncIdx `check | throw (IO.userError "missing constant-degree entry") + for input in ([0, 1, 17, 0 - 1] : List Aiur.G) do + let expected : Array Aiur.G := #[1, 1, 0, 1, 0, input] + let (sourceValue, sourceIo) ← IO.ofExcept + ((Source.Eval.runFunction decls (Global.init "check") [.field input] default 100).mapError reprStr) + unless flattenValue decls (fun _ => none) sourceValue == expected && sourceIo == default do + throw (IO.userError "constant-degree source reference differs") + let (reference, _) ← IO.ofExcept + ((Bytecode.Eval.runFunction program.bytecode index #[input] default 100).mapError reprStr) + let (native, _, _) ← IO.ofExcept (program.bytecode.execute index #[input] default) + unless reference == expected && native == expected do throw (IO.userError "constant-degree execution differs") + IO.println s!"constant-degree reference/execution match for input {input}" + let system := AiurSystem.build program.bytecode cp fp + let (claim, proof, _) ← IO.ofExcept (system.prove index #[input] default) + unless claim == buildClaim index #[input] expected do throw (IO.userError "constant-degree proof claim differs") + IO.ofExcept (system.verify claim proof) + accepted := accepted + 1 + match system.verify (buildClaim index #[input] (expected.set! 0 0)) proof with + | .error _ => rejected := rejected + 1 + | .ok _ => throw (IO.userError "changed constant-degree output accepted") + unless accepted == 8 && rejected == 8 do throw (IO.userError "incomplete constant-degree proof corpus") + IO.println s!"constant degree: {accepted} honest proofs, {rejected} changed-output rejections" + +end AiurTests.ConstantDegree + +def main : IO Unit := AiurTests.ConstantDegree.run diff --git a/Tests/Aiur/Dedup.lean b/Tests/Aiur/Dedup.lean new file mode 100644 index 000000000..02a9b5a2f --- /dev/null +++ b/Tests/Aiur/Dedup.lean @@ -0,0 +1,111 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Aiur.DedupFixtures +import Ix.Aiur.Semantics.BytecodeEval + +namespace AiurTests.Dedup + +open Aiur Aiur.Bytecode + +/-- Full syntax and index maps captured before adding checked renaming. -/ +def snapshot : IO Unit := do + for (name, source) in fixtures do + let (target, rename) := source.deduplicate + IO.println s!"PROGRAM {name} FUNCTIONS {source.functions.size} -> {target.functions.size}" + IO.println s!"RENAME {(Array.range (source.functions.size + 3)).map rename}" + IO.println s!"MEMORY {target.memorySizes}" + for i in [:target.functions.size] do + IO.println s!"FUNCTION {i} {repr target.functions[i]!}" + +private def checkRejected (label : String) (source candidate : Toplevel) + (rename : FunIdx → FunIdx) : IO Unit := do + if validatesRenaming source candidate (boundedRenaming source rename) then + throw (IO.userError s!"invalid deduplication accepted: {label}") + let (selected, actualRename) := checkedRenaming source candidate rename + unless reprStr selected == reprStr source do + throw (IO.userError s!"fallback changed the original program: {label}") + for i in [:source.functions.size + 3] do + unless actualRename i == i do + throw (IO.userError s!"fallback changed function index {i}: {label}") + IO.println s!"PASS {label}: rejected and original program retained" + +private def checkExecution (label : String) (source : Toplevel) (args expected : Array G) + (fuel : Nat) (initial final : IOBuffer) : IO Unit := do + let (target, rename) := source.deduplicate + unless target.functions.size < source.functions.size do + throw (IO.userError s!"execution fixture did not merge functions: {label}") + for (program, function) in #[(source, 0), (target, rename 0)] do + match Eval.runFunction program function args initial fuel with + | .error error => throw (IO.userError s!"{label}: {repr error}") + | .ok (output, io) => + unless output == expected && io == final do + throw (IO.userError s!"execution or final I/O changed: {label}") + IO.println s!"PASS {label}: original and merged execution agree" + +/-- The caller loads memory created by a merged callee, then appends to its +I/O output. Pre-existing arena contents and key information must survive. -/ +private def stateful : Toplevel := + let worker : Function := ⟨⟨#[.const 0, .store #[0], .load 1 2, .ioWrite 1 #[3]], + .return 0 #[2, 3]⟩, layout 1, false, false⟩ + let main (target : Nat) : Function := ⟨⟨#[.const 7, .call target #[0] 2 false, + .load 1 1, .const 0, .ioWrite 4 #[3]], .return 0 #[2, 3]⟩, layout, true, false⟩ + program #[main 2, main 3, worker, worker] + +def run : IO Unit := do + for (name, source) in fixtures do + let (candidate, rename) := source.deduplicateCandidate + unless validatesRenaming source candidate (boundedRenaming source rename) do + throw (IO.userError s!"original partition candidate declined: {name}") + IO.println s!"PASS {fixtures.size} original partition candidates: accepted" + + let base := constant 7 true + let source := program #[base, base, base] + let variants : Array (String × Function) := #[ + ("changed-constant", constant 8 true), + ("changed-return-value", { base with body := { base.body with ctrl := .return 0 #[1] } }), + ("changed-return-selector", { base with body := { base.body with ctrl := .return 1 #[0] } }), + ("changed-input-arity", { base with layout := layout 1 }), + ("changed-selector-layout", { base with layout := { layout with selectors := 3 } }), + ("changed-auxiliary-layout", { base with layout := { layout with auxiliaries := 9 } }), + ("changed-lookup-layout", { base with layout := { layout with lookups := 6 } })] + for (label, changed) in variants do + checkRejected label source (program #[changed]) (fun _ => 0) + checkRejected "missing-target" source (program #[]) (fun _ => 0) + checkRejected "invalid-call-domain-expanded" source (program #[base, base, base, base]) (fun _ => 0) + checkRejected "out-of-range-target" source (program #[base]) (fun _ => 1) + + let (candidate, rename) := withContinuations.deduplicateCandidate + let original := candidate.functions[0]! + let .matchContinue idx branches fallback out aux lookups cont := original.body.ctrl + | throw (IO.userError "continuation fixture changed") + let mutations : Array (String × Ctrl) := #[ + ("changed-call-target", .matchContinue idx branches fallback out aux lookups + { cont with ops := #[.call 0 #[2] 1 false] }), + ("changed-call-arguments", .matchContinue idx branches fallback out aux lookups + { cont with ops := #[.call 1 #[] 1 false] }), + ("changed-call-output-size", .matchContinue idx branches fallback out aux lookups + { cont with ops := #[.call 1 #[2] 2 false] }), + ("removed-early-return", .matchContinue idx branches none out aux lookups cont)] + for (label, ctrl) in mutations do + checkRejected label withContinuations + { candidate with functions := candidate.functions.set! 0 { original with body := { original.body with ctrl } } } + rename + + checkExecution "yield-to-continuation" withContinuations #[0] #[7] 1 default default + checkExecution "early-return-skips-continuation" withContinuations #[5] #[5] 0 default default + let initial := (default : IOBuffer).extend 0 #[42] #[99] + let final := { initial with data := initial.data.insert 0 #[99, 7, 7] } + checkExecution "callee-memory-and-io" stateful #[] #[7, 7] 1 initial final + checkExecution "merged-public-entry" source #[] #[7] 0 default default + IO.println s!"deduplication: {fixtures.size} accepted candidates, {variants.size + 3 + mutations.size} rejected candidates, 4 execution cases" + +end AiurTests.Dedup + +def main (args : List String) : IO Unit := + match args with + | [] => AiurTests.Dedup.run + | ["--snapshot"] => AiurTests.Dedup.snapshot + | _ => throw (IO.userError "usage: aiur-dedup-tests [--snapshot]") diff --git a/Tests/Aiur/DedupFixtures.lean b/Tests/Aiur/DedupFixtures.lean new file mode 100644 index 000000000..8f0894619 --- /dev/null +++ b/Tests/Aiur/DedupFixtures.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Compiler.Dedup + +namespace AiurTests.Dedup + +open Aiur Aiur.Bytecode + +def layout (inputs : Nat := 0) : FunctionLayout := ⟨inputs, 2, 8, 5⟩ + +def constant (n : Nat) (entry : Bool := false) : Function := + ⟨⟨#[.const (G.ofNat n)], .return 0 #[0]⟩, layout, entry, false⟩ + +def caller (target : Nat) (entry : Bool := false) : Function := + ⟨⟨#[.call target #[] 1 false], .return 0 #[0]⟩, layout, entry, false⟩ + +def program (functions : Array Function) : Toplevel := ⟨functions, #[1, 2, 10], #[], #[]⟩ + +/-- Two recursive functions form the same bisimulation class. Neither has +a finite successful execution; validation must still handle this syntax. -/ +def mutualCycle : Toplevel := program #[caller 1 true, caller 0] + +/-- A leaf difference propagates through successive refinement rounds. -/ +def chains (depth : Nat) : Toplevel := Id.run do + let mut functions := #[] + for i in [:depth] do + functions := functions ++ #[caller (2 * i + 2) (i == 0), caller (2 * i + 3) (i == 0)] + return program (functions ++ #[constant 7, constant 9]) + +def continuation (target : Nat) (entry : Bool) : Function := + let yielded : Block := ⟨#[], .yield 0 #[1]⟩ + let returned : Block := ⟨#[], .return 0 #[0]⟩ + let cont : Block := ⟨#[.call target #[2] 1 false], .return 0 #[3]⟩ + ⟨⟨#[.const 7], .matchContinue 0 #[(0, yielded)] (some returned) 1 3 2 cont⟩, + layout 1, entry, false⟩ + +/-- Zero takes a yielding arm and calls the continuation. Nonzero returns +from the function directly and must bypass that continuation. -/ +def withContinuations : Toplevel := + let identity : Function := ⟨⟨#[], .return 0 #[0]⟩, layout 1, false, false⟩ + program #[continuation 2 true, continuation 3 false, identity, identity] + +def fixtures : Array (String × Toplevel) := Id.run do + let same := constant 7 + let mut cases := #[ + ("empty", program #[]), + ("entry-union", program #[same, constant 7 true, same]), + ("different-layouts", program #[same, { same with layout := layout 1 }, + { same with layout := { layout with auxiliaries := 9 } }]), + ("mutual-cycle", mutualCycle), + ("invalid-callee", program #[caller 999 true, caller 999]), + ("continuations", withContinuations)] + for depth in [:17] do cases := cases.push (s!"refinement-chain-{depth}", chains depth) + return cases + +end AiurTests.Dedup diff --git a/Tests/Aiur/Domain.lean b/Tests/Aiur/Domain.lean new file mode 100644 index 000000000..68c0eb3ef --- /dev/null +++ b/Tests/Aiur/Domain.lean @@ -0,0 +1,135 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.DomainAccumulator +import Ix.Aiur.Proofs.Quotient +import Tests.Aiur.EmissionReader + +/-! Native domain selectors for every supported logarithm, complete small +cosets, and the quotient arithmetic with both accepting and rejecting cases. +The native domain methods are called directly; quotient fixtures reproduce +the verifier's private iterator expression using native basis and field APIs. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) + +namespace AiurTests.Domain + +private def readExtension : Reader Extension := do return ⟨← readField, ← readField⟩ + +private def readSelectors : Reader (NativeAIR.Domain.Selectors Extension) := do + return ⟨← readExtension, ← readExtension, ← readExtension, ← readExtension⟩ + +private def readVector : Reader (List Extension) := do readList (← readCount) readExtension + +private def readDomain (bits : Nat) : Reader NativeAIR.Domain.Subgroup := do + unless (← readNat) == bits do throw "domain logarithm order differs" + let some domain := NativeAIR.Domain.ofLogSize bits | throw "unsupported domain logarithm" + return domain + +private def readDomains : Reader (Nat × Nat × Nat) := do + let header := "Aiur trace domains v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "domain snapshot version differs" + unless (← readNat) == 33 do throw "incomplete domain inventory" + let mut rows := 0 + let mut accepted := 0 + let mut rejected := 0 + for bits in [:33] do + let domain ← readDomain bits + let n := NativeAIR.Domain.size domain + unless (← readNat) == n do throw "native domain size differs" + unless (← readField) == NativeAIR.Domain.generator domain do throw "native domain generator differs" + unless (← readField) == NativeAIR.Domain.lastPoint domain do throw "native last point differs" + unless (← readField) == NativeAIR.Domain.normalizer domain do throw "native normalizer differs" + unless (← readField) == (NativeAIR.Domain.normalizer domain).inverse do throw "native inverse normalizer differs" + let indices := (List.range (min n 16) ++ [n / 2, n - 1, n - 2] ++ + (List.range 16).map fun seed => seed * 0x0a3751c9 % n).mergeSort (· ≤ ·) |>.eraseDups + unless (← readNat) == indices.length do throw "incomplete domain row samples" + for index in indices do + unless (← readNat) == index do throw "native row index differs" + let fin : Fin n ← if bounded : index < n then pure ⟨index, bounded⟩ else throw "native row index out of bounds" + let point := NativeAIR.Domain.point domain fin + unless (← readField) == point do throw "native row point differs" + unless (← readExtension) == Extension.ofBase (point * NativeAIR.Domain.generator domain) do + throw "native next point differs" + unless NativeAIR.Domain.selectors domain (Extension.ofBase point) == none do throw "trace row pole accepted" + rows := rows + 1 + unless (← readNat) == 64 do throw "incomplete selector assignments" + for _ in [:64] do + let point ← readExtension + unless (← readExtension) == NativeAIR.Domain.vanishing domain point do throw "native vanishing polynomial differs" + let defined ← readBool + let expected ← if defined then some <$> readSelectors else pure none + unless NativeAIR.Domain.selectors domain point == expected do throw "native point selectors differ" + if defined then accepted := accepted + 1 else rejected := rejected + 1 + unless (← readNat) == 9 do throw "incomplete bulk selector domains" + for bits in [:9] do + let domain ← readDomain bits + let n := NativeAIR.Domain.size domain + unless (← readNat) == n do throw "bulk selector count differs" + for _ in [:n] do + let point ← readField + let expected ← readSelectors + unless NativeAIR.Domain.selectors domain (Extension.ofBase point) == some expected do + throw "native bulk selectors differ" + for invalid in [33, 64, 255, 256, 2^64 - 1] do + unless (NativeAIR.Domain.ofLogSize invalid).isNone do throw "invalid domain logarithm accepted" + return (rows, accepted, rejected) + +private def readQuotients : Reader (Nat × Nat) := do + let header := "Aiur quotient arithmetic v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "quotient snapshot version differs" + unless (← readNat) == 704 do throw "incomplete quotient inventory" + let mut accepted := 0 + let mut rejected := 0 + for bits in [0, 1, 2, 4, 8, 16, 31, 32] do + for count in [0, 1, 2, 3, 4, 7, 8, 9, 16, 31, 32] do + for seed in [:8] do + let domain ← readDomain bits + unless (← readNat) == count && (← readNat) == seed do throw "quotient assignment order differs" + let point ← readExtension + let alpha ← readExtension + let constraints ← readVector + let row ← readVector + unless constraints.length == count && row.length == 2 * count do throw "quotient case dimensions differ" + unless (← readExtension) == Quotient.composition alpha constraints do throw "native constraint fold differs" + let expected ← readExtension + unless Quotient.evaluate domain point row == some expected do throw "native quotient recombination differs" + let expectedAcceptance ← readBool + unless Quotient.check domain point alpha constraints row == some expectedAcceptance do + throw "native out-of-domain arithmetic check differs" + unless Quotient.check domain point alpha constraints (row ++ [0]) == none do throw "odd quotient row accepted" + unless Quotient.check domain 1 alpha constraints row == none do throw "first-row pole accepted" + unless Quotient.check domain (Extension.ofBase (NativeAIR.Domain.lastPoint domain)) alpha constraints row == none do + throw "last-row pole accepted" + if expectedAcceptance then + accepted := accepted + 1 + if let first :: rest := row then + unless Quotient.check domain point alpha constraints ((first + 1) :: rest) == some false do + throw "altered quotient coordinate accepted" + else rejected := rejected + 1 + return (accepted, rejected) + +private def runReader (reader : Reader α) (path : System.FilePath) : IO α := do + let bytes ← IO.FS.readBinFile path + match reader.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok (value, (_, cursor)) => + unless cursor == bytes.size do throw (IO.userError "domain snapshot has trailing bytes") + return value + +def run (domains quotients : System.FilePath) : IO Unit := do + let (rows, accepted, rejected) ← runReader readDomains domains + IO.println s!"domains: 33 generators, {rows} row samples, {accepted} defined/{rejected} rejected selectors and 511 bulk points match" + let (accepted, rejected) ← runReader readQuotients quotients + IO.println s!"quotients: {accepted} accepted/{rejected} rejected native arithmetic cases, malformed rows, poles and alterations match" + +end AiurTests.Domain + +def main (args : List String) : IO Unit := do + match args with + | [domains, quotients] => AiurTests.Domain.run domains quotients + | _ => throw (IO.userError "expected native domain and quotient snapshots") diff --git a/Tests/Aiur/EmissionChecks.lean b/Tests/Aiur/EmissionChecks.lean new file mode 100644 index 000000000..310fcad8c --- /dev/null +++ b/Tests/Aiur/EmissionChecks.lean @@ -0,0 +1,89 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.CheckedCircuit +import Tests.Aiur.EmissionReader + +/-! Native guard decisions across operand widths, scopes and control trees. -/ + +open Aiur Aiur.Bytecode Aiur.NativeAIR Aiur.NativeAIR.OpEmitter +open Aiur.NativeAIR.BlockEmitter AiurTests.EmissionReader + +namespace AiurTests.EmissionChecks + +private def readCorpus : Reader (Nat × Nat × Nat) := do + let header := "Aiur emission checks v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "emission check snapshot version differs" + let scopes ← readList (← readCount) readNat + unless scopes == [0, 1, 2, 3, 4, 7, 8, 9, 12, 16, 2^64 - 9, 2^64 - 2, 2^64 - 1] do + throw "emission check snapshot scope boundaries differ" + let mut operationChecks := 0 + let mut sequenceChecks := 0 + let mut controlChecks := 0 + for group in [:← readCount] do + let mut ops := #[] + for index in [:← readCount] do + let op ← readOp + ops := ops.push op + unless (← readNat) == op.outputSize do throw s!"logical output size differs: group {group}, operation {index}" + for available in scopes do + let valid ← readBool + unless valid == op.emissionInputs available do + throw s!"operand check differs: group {group}, operation {index}, scope {available}" + let expected ← readOption readNat + unless expected == checkEmissionOps [op] available do + throw s!"single operation scope differs: group {group}, operation {index}, scope {available}" + if valid && available ≤ 32 && op.outputSize ≤ 64 then + let some emitted := emitOp (.konst 1) (.konst 0) available op (advice 0 available) + | throw "checked operation failed to emit" + unless emitted.outputs.size == op.outputSize do throw "checked operation output size differs" + operationChecks := operationChecks + 1 + for available in scopes do + let expected ← readOption readNat + unless expected == checkEmissionOps ops.toList available do + throw s!"operation sequence scope differs: group {group}, scope {available}" + if let some next := expected then + if available ≤ 32 && next ≤ 128 then + let some emitted := emitOps (.konst 1) (.konst 0) ops.toList (advice 0 available) available + | throw "checked operation sequence failed to emit" + unless emitted.values.size == next do throw "checked sequence final scope differs" + sequenceChecks := sequenceChecks + 1 + for index in [:← readCount] do + let block ← readBlock 64 + for _ in [:← readCount] do + let available ← readNat + let selectors ← readNat + let yieldSize ← readOption readNat + let valid ← readBool + unless valid == block.emissionChecks available selectors yieldSize do + throw s!"control scope differs: block {index}, values {available}, selectors {selectors}, yields {yieldSize}" + if valid && available ≤ 32 then + let selectorTable := CircuitEmitter.selectorExprs available selectors + let some entry := blockSelector selectorTable block | throw "checked block selector is absent" + let some emitted := emitBlock selectorTable ⟨0, available, .konst 0⟩ entry + (advice 0 available) (available + selectors) 0 block + | throw "checked block failed to emit" + unless emitted.yields.all (fun part => yieldSize == some part.values.size) do + throw "checked block escaping yield width differs" + controlChecks := controlChecks + 1 + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "emission check snapshot has trailing bytes" + unless (operationChecks, sequenceChecks, controlChecks) == (1365, 1157, 6500) do + throw "emission check snapshot coverage differs" + return (operationChecks, sequenceChecks, controlChecks) + +def run (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok ((operations, sequences, controls), _) => + IO.println s!"emission checks: {operations} operations, {sequences} sequences and {controls} control scopes match" + +end AiurTests.EmissionChecks + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.EmissionChecks.run path + | _ => throw (IO.userError "expected native emission check snapshot") diff --git a/Tests/Aiur/EmissionReader.lean b/Tests/Aiur/EmissionReader.lean new file mode 100644 index 000000000..9b116b1e7 --- /dev/null +++ b/Tests/Aiur/EmissionReader.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LookupExpressions + +/-! Test transport for native expression trees and operation constructors. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.OpEmitter + +namespace AiurTests.EmissionReader + +abbrev Reader := StateT (ByteArray × Nat) (Except String) + +def takeBytes (count : Nat) : Reader ByteArray := do + let (bytes, cursor) ← get + if cursor + count > bytes.size then throw s!"operation snapshot truncated at {cursor}" + set (bytes, cursor + count) + return bytes.extract cursor (cursor + count) + +def readNat (count : Nat := 8) : Reader Nat := do + let bytes ← takeBytes count + let mut value := 0 + for index in [:count] do value := value + bytes[index]!.toNat * 256^index + return value + +def readCount (limit : Nat := 1024) : Reader Nat := do + let count ← readNat + unless count ≤ limit do throw s!"operation snapshot count exceeds {limit}" + return count + +def readField : Reader G := do + let value ← readNat + unless value < gSize.toNat do throw "noncanonical operation field value" + return G.ofNat value + +def readBool : Reader Bool := do + match ← readNat 1 with + | 0 => return false + | 1 => return true + | _ => throw "invalid operation boolean" + +def readList (count : Nat) (reader : Reader α) : Reader (List α) := + (List.range count).mapM fun _ => reader + +def readValues : Reader (List G) := do readList (← readCount) readField + +def readString : Reader String := do + let bytes ← takeBytes (← readCount) + let some string := String.fromUTF8? bytes | throw "invalid operation text" + return string + +def readOption (reader : Reader α) : Reader (Option α) := do + if ← readBool then return some (← reader) else return none + +def readIndices : Reader (Array Nat) := do + return (← readList (← readCount) readNat).toArray + +def readExpr : Nat → Reader Expr + | 0 => throw "operation expression exceeds snapshot depth bound" + | fuel + 1 => do + match ← readNat 1 with + | 0 => return .konst (← readField) + | 1 => + let source ← match ← readNat 1 with + | 0 => pure Source.preprocessed | 1 => pure Source.main | 2 => pure Source.stage2 + | _ => throw "invalid operation column source" + let offset ← match ← readNat 1 with + | 0 => pure RowOffset.current | 1 => pure RowOffset.next + | _ => throw "invalid operation row offset" + return .var ⟨source, offset, ← readNat⟩ + | 2 => return .publicInput (← readNat) + | 3 => return .isFirstRow + | 4 => return .isLastRow + | 5 => return .isTransition + | 6 => return .add (← readExpr fuel) (← readExpr fuel) + | 7 => return .sub (← readExpr fuel) (← readExpr fuel) + | 8 => return .mul (← readExpr fuel) (← readExpr fuel) + | 9 => return .neg (← readExpr fuel) + | _ => throw "invalid operation expression tag" + +def readMap : Reader (Array RowExpr) := do + return (← readList (← readCount) do + return RowExpr.mk (← readExpr 64) (← readNat)).toArray + +def readOp : Reader Bytecode.Op := do + match ← readNat 1 with + | 0 => return .const (← readField) + | 1 => return .add (← readNat) (← readNat) + | 2 => return .sub (← readNat) (← readNat) + | 3 => return .mul (← readNat) (← readNat) + | 4 => return .eqZero (← readNat) + | 5 => return .call (← readNat) (← readIndices) (← readNat) (← readBool) + | 6 => return .store (← readIndices) + | 7 => return .load (← readNat) (← readNat) + | 8 => return .assertEq (← readIndices) (← readIndices) (← readOption readString) + | 9 => return .ioGetInfo (← readNat) (← readIndices) + | 10 => return .ioSetInfo (← readNat) (← readIndices) (← readNat) (← readNat) + | 11 => return .ioRead (← readNat) (← readNat) (← readNat) + | 12 => return .ioWrite (← readNat) (← readIndices) + | 13 => return .u8BitDecomposition (← readNat) + | 14 => return .u8ShiftLeft (← readNat) + | 15 => return .u8ShiftRight (← readNat) + | 16 => return .u8Xor (← readNat) (← readNat) + | 17 => return .u8Add (← readNat) (← readNat) + | 18 => return .u8Mul (← readNat) (← readNat) + | 19 => return .u8Sub (← readNat) (← readNat) + | 20 => return .u8And (← readNat) (← readNat) + | 21 => return .u8Or (← readNat) (← readNat) + | 22 => return .u8LessThan (← readNat) (← readNat) + | 23 => return .u32LessThan (← readNat) (← readNat) + | 24 => return .u8XorSplit7 (← readNat) (← readNat) + | 25 => return .u8XorSplit4 (← readNat) (← readNat) + | 26 => return .debug (← readString) (← readOption readIndices) + | 27 => return .u8RangeCheck (← readNat) (← readNat) + | 28 => return .unconstrainedBigUintDivMod (← readNat) (← readNat) + | 29 => return .unconstrainedGToBytes (← readNat) + | 30 => return .unconstrainedGInverse (← readNat) + | 31 => return .unconstrainedU32Add (← readIndices) (← readIndices) + | 32 => return .unconstrainedU32Add3 (← readIndices) (← readIndices) (← readIndices) + | 33 => return .u32ToField (← readIndices) + | _ => throw "invalid operation constructor tag" + +def readBlock : Nat → Reader Bytecode.Block + | 0 => throw "native control tree exceeds snapshot depth bound" + | fuel + 1 => do + let ops := (← readList (← readCount) readOp).toArray + let ctrl : Bytecode.Ctrl ← match ← readNat 1 with + | 0 => pure (Bytecode.Ctrl.return (← readNat) (← readIndices)) + | 1 => pure (Bytecode.Ctrl.yield (← readNat) (← readIndices)) + | tag => do + unless tag == 2 || tag == 3 do throw "invalid native control tag" + let index ← readNat + let branches := (← readList (← readCount) do + return (← readField, ← readBlock fuel)).toArray + let fallback ← readOption (readBlock fuel) + if tag == 2 then pure (Bytecode.Ctrl.match index branches fallback) + else pure (Bytecode.Ctrl.matchContinue index branches fallback (← readNat) (← readNat) (← readNat) (← readBlock fuel)) + return ⟨ops, ctrl⟩ + +def assignment (row : Array G) : Values G := + ⟨(fun source _ => match source with | .main => row | _ => #[]), #[], 1, 0, 1⟩ + +def blockCallData (calls : List (G × (Bytecode.AIR.Call × (Fin 6 → G)))) := + calls.map fun (gate, call, gap) => (gate, call, List.ofFn gap) + +def sameBlockEmission (left right : AIR.BlockEmission) : Bool := + left.values == right.values && left.column == right.column && left.lookup == right.lookup && + left.equations == right.equations && + left.queries.map (fun part => (part.slot, part.selector, part.message)) == + right.queries.map (fun part => (part.slot, part.selector, part.message)) && + left.returns == right.returns && left.yields == right.yields && blockCallData left.calls == blockCallData right.calls + +end AiurTests.EmissionReader diff --git a/Tests/Aiur/ExpressionGraph.lean b/Tests/Aiur/ExpressionGraph.lean new file mode 100644 index 000000000..8e222e1ec --- /dev/null +++ b/Tests/Aiur/ExpressionGraph.lean @@ -0,0 +1,156 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.KeyCodec + +open Aiur Aiur.NativeAIR + +namespace AiurTests.ExpressionGraph + +private def appendNat (out : ByteArray) (value : Nat) : ByteArray := Id.run do + let mut out := out + for index in [:8] do out := out.push ((value >>> (8 * index)) % 256).toUInt8 + return out + +private def nodeChoices : List Node := Id.run do + let indices := [0, 1, 3, 7, 8, 65535, 2^32 - 1] + let mut choices : Array Node := #[.konst 0, .konst 1, .konst (0 - 1), .konst 65536, + .isFirstRow, .isLastRow, .isTransition] + for source in [Source.preprocessed, .main, .stage2] do + for offset in [RowOffset.current, .next] do + for index in indices do choices := choices.push (.var ⟨source, offset, index⟩) + for index in indices do choices := choices.push (.publicInput index) + for left in indices do + for right in indices do + choices := choices ++ #[.add left right, .sub left right, .mul left right] + for index in indices do choices := choices.push (.neg index) + return choices.toList + +private def appendShapes (out : ByteArray) (nodes : List Node) : ByteArray := Id.run do + let mut out := out + let count := nodes.length + for width in [0, 1, 4, 8] do + let widths : GraphWidths := ⟨width, width + 1, width + 2, width⟩ + let contexts : List (List Nat × List Lookup) := [ + ([], []), ([0], []), ([count - 1], []), ([count], []), + ([], [⟨0, []⟩]), ([], [⟨count - 1, [0]⟩]), ([], [⟨0, [count]⟩])] + for (zeros, lookups) in contexts do + out := match checkedGraphPrefix widths ⟨nodes, zeros, lookups⟩ with + | none => out.push 0 + | some lookupEnd => appendNat (out.push 1) lookupEnd + return out + +private def expectedShapes : ByteArray × Nat := Id.run do + let mut out := appendShapes "Aiur graph shapes v1\n".toUTF8 [] + let mut checked := 28 + for count in [1, 2, 4, 8] do + for index in [:count] do + for node in nodeChoices do + out := appendShapes out ((List.replicate count (.konst 0)).set index node) + checked := checked + 28 + return (out, checked) + +private abbrev Reader := StateT (ByteArray × Nat) (Except String) + +private def takeBytes (count : Nat) : Reader ByteArray := do + let (bytes, cursor) ← get + if cursor + count > bytes.size then throw s!"graph snapshot truncated at {cursor}" + set (bytes, cursor + count) + return bytes.extract cursor (cursor + count) + +private def readNat (count : Nat) : Reader Nat := do + let bytes ← takeBytes count + let mut value := 0 + for index in [:count] do value := value + bytes[index]!.toNat * 256^index + return value + +private def readList (count : Nat) (read : Reader α) : Reader (List α) := + (List.range count).mapM fun _ => read + +private def readValues : Reader (Array G) := do + let count ← readNat 8 + return (← readList count (return G.ofNat (← readNat 8))).toArray + +private def readAssignment (widths : GraphWidths) (graph : Graph) (trees : Array Expr) : Reader Nat := do + let preCurrent ← readValues + let preNext ← readValues + let mainCurrent ← readValues + let mainNext ← readValues + let stageCurrent ← readValues + let stageNext ← readValues + let publics ← readValues + let first := G.ofNat (← readNat 8) + let last := G.ofNat (← readNat 8) + let transition := G.ofNat (← readNat 8) + let values : Values G := ⟨(fun source offset => match source, offset with + | .preprocessed, .current => preCurrent | .preprocessed, .next => preNext + | .main, .current => mainCurrent | .main, .next => mainNext + | .stage2, .current => stageCurrent | .stage2, .next => stageNext), + publics, first, last, transition⟩ + for source in [Source.preprocessed, .main, .stage2] do + for offset in [RowOffset.current, .next] do + unless (values.columns source offset).size == widths.width source do throw "native graph column width mismatch" + unless publics.size == widths.publics do throw "native graph public width mismatch" + let full ← readValues + let prefixValues ← readValues + let zeros ← readValues + let lookups ← readList (← readNat 8) do + let multiplicity := G.ofNat (← readNat 8) + let args ← readValues + return (multiplicity, args.toList) + unless graph.sweep goldilocksOps values == some full do throw "native graph full sweep differs" + unless graph.sweepLookupPrefix goldilocksOps values == some prefixValues do throw "native graph lookup sweep differs" + unless readNodes full graph.zeros == some zeros.toList do throw "native graph constraints differ" + unless graph.lookups.mapM (readLookup prefixValues) == some lookups do throw "native graph lookups differ" + unless trees.size == full.size do throw "unfolded graph size differs" + for index in [:trees.size] do + let some expr := trees[index]? | throw "unfolded graph index missing" + unless expr.eval goldilocksOps values == full[index]? do throw s!"unfolded graph value differs at {index}" + return full.size + +private def readGraphs : Reader (Nat × Nat) := do + let header := "Aiur expression graphs v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "native graph snapshot version differs" + let mut checked := 0 + let mut nodes := 0 + let count ← readNat 8 + unless count == 10 do throw "incomplete native graph circuit corpus" + for _ in [:count] do + let bytes ← takeBytes (← readNat 8) + let some (circuit, rest) := KeyCodec.readCircuit bytes.data.toList + | throw "native graph circuit failed checked v5 decoding" + unless rest.isEmpty do throw "native graph circuit has trailing bytes" + let widths := circuit.widths + let graph := circuit.graph + let some lookupEnd := checkedGraphPrefix widths graph | throw "actual native graph layout rejected" + unless lookupEnd ≤ graph.nodes.length do throw "native graph lookup prefix out of range" + let some trees := graph.unfold | throw "actual native graph unfolding failed" + let assignments ← readNat 8 + unless assignments == 24 do throw "incomplete native graph assignment corpus" + for _ in [:assignments] do + nodes := nodes + (← readAssignment widths graph trees) + checked := checked + 1 + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "native graph snapshot has trailing bytes" + return (checked, nodes) + +def run (shapePath graphPath : System.FilePath) : IO Unit := do + let shapeBytes ← IO.FS.readBinFile shapePath + let (expected, checked) := expectedShapes + unless checked == 88228 && nodeChoices.length == 210 do throw (IO.userError "incomplete graph-shape corpus") + unless shapeBytes == expected do throw (IO.userError "native/Lean graph-shape checks differ") + IO.println s!"graph shapes: {checked} native/Lean layouts match" + let graphBytes ← IO.FS.readBinFile graphPath + match readGraphs.run (graphBytes, 0) with + | .error error => throw (IO.userError error) + | .ok ((assignments, nodes), _) => + IO.println s!"expression graphs: {assignments} native/Lean assignments, {nodes} node values match" + +end AiurTests.ExpressionGraph + +def main (args : List String) : IO Unit := do + match args with + | [shapePath, graphPath] => AiurTests.ExpressionGraph.run shapePath graphPath + | _ => throw (IO.userError "expected native graph-shape and expression-graph snapshots") diff --git a/Tests/Aiur/Extension.lean b/Tests/Aiur/Extension.lean new file mode 100644 index 000000000..4d2472ede --- /dev/null +++ b/Tests/Aiur/Extension.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ExtensionField +import Tests.Aiur.EmissionReader + +/-! Comparison with the pinned native field implementation and its actual +compiled graphs. Coordinate inputs, all operations and every graph node are +checked independently, including full-width exponents and zero inverses. -/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) + +namespace AiurTests.ExtensionArithmetic + +private def readExtension : Reader Extension := do return ⟨← readField, ← readField⟩ +private def readExtensions : Reader (List Extension) := do readList (← readCount 100000) readExtension + +private def readArithmetic : Reader Unit := do + let header := "Aiur extension arithmetic v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "extension arithmetic snapshot version differs" + let bases ← readCount + unless bases == 16 do throw "incomplete base inverse cases" + for _ in [:bases] do + let value ← readField + unless value.inverse == (← readField) do throw "native base inverse differs" + let values ← readExtensions + unless values.length == 384 do throw "incomplete extension coordinates" + let powers ← readList (← readCount) (readNat 16) + let p := gSize.toNat + let expected := [0, 1, 2, 3, 7, 8, 15, 16, 31, 32, 63, 64, + p - 2, p - 1, p, 2^64 - 1, 2^64, p * p - 2, 2^127 + 1, 2^128 - 1] + unless powers == expected do throw "incomplete extension exponents" + let mut inverses := 0 + for value in values do + unless -value == (← readExtension) do throw "native extension negation differs" + unless value * value == (← readExtension) do throw "native extension square differs" + unless value.conjugate == (← readExtension) do throw "native extension conjugate differs" + unless value.norm == (← readField) do throw "native extension norm differs" + let inverse ← readOption readExtension + unless value.tryInverse == inverse do throw "native extension inverse differs" + if let some inverse := inverse then + unless value * inverse == 1 do throw "extension inverse does not cancel" + inverses := inverses + 1 + for exponent in powers do + unless value.power exponent == (← readExtension) do throw s!"native extension power differs at {exponent}" + unless inverses == 383 do throw "incomplete extension inverse cases" + for left in values do + for right in values do + unless left + right == (← readExtension) do throw "native extension addition differs" + unless left - right == (← readExtension) do throw "native extension subtraction differs" + unless left * right == (← readExtension) do throw "native extension multiplication differs" + +private def readAssignment (circuit : KeyCodec.Circuit) (trees : Array Expr) : Reader Nat := do + let preCurrent := (← readExtensions).toArray + let preNext := (← readExtensions).toArray + let mainCurrent := (← readExtensions).toArray + let mainNext := (← readExtensions).toArray + let stageCurrent := (← readExtensions).toArray + let stageNext := (← readExtensions).toArray + let publics := (← readExtensions).toArray + let first ← readExtension + let last ← readExtension + let transition ← readExtension + let values : Values Extension := ⟨(fun source offset => match source, offset with + | .preprocessed, .current => preCurrent | .preprocessed, .next => preNext + | .main, .current => mainCurrent | .main, .next => mainNext + | .stage2, .current => stageCurrent | .stage2, .next => stageNext), + publics, first, last, transition⟩ + for source in [Source.preprocessed, .main, .stage2] do + for offset in [RowOffset.current, .next] do + unless (values.columns source offset).size == circuit.widths.width source do throw "extension graph width differs" + unless publics.size == circuit.widths.publics do throw "extension graph public width differs" + let buffer := (← readExtensions).toArray + let constraints ← readExtensions + let lookups ← readList (← readCount) do return (← readExtension, ← readExtensions) + unless circuit.graph.sweep Extension.evalOps values == some buffer do throw "native extension sweep differs" + unless readNodes buffer circuit.graph.zeros == some constraints do throw "native extension constraint roots differ" + unless circuit.graph.lookups.mapM (readLookup buffer) == some lookups do throw "native extension lookup roots differ" + unless trees.size == buffer.size do throw "extension graph unfolding length differs" + for index in [:trees.size] do + let some expr := trees[index]? | throw "extension graph expression missing" + unless expr.eval Extension.evalOps values == buffer[index]? do throw "extension expression evaluation differs" + return buffer.size + +private def readGraphs : Reader Unit := do + let header := "Aiur extension graphs v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "extension graph snapshot version differs" + let circuits ← readCount + unless circuits == 10 do throw "incomplete extension graphs" + let mut nodes := 0 + for _ in [:circuits] do + let bytes ← takeBytes (← readCount 1000000) + let some (circuit, []) := KeyCodec.readCircuit bytes.data.toList | throw "invalid extension graph circuit" + let some _ := checkedGraphPrefix circuit.widths circuit.graph | throw "invalid extension graph reads" + let some trees := circuit.graph.unfold | throw "extension graph does not unfold" + let assignments ← readCount + unless assignments == 24 do throw "incomplete extension graph assignments" + for _ in [:assignments] do nodes := nodes + (← readAssignment circuit trees) + unless nodes == 8016 do throw "incomplete extension graph nodes" + +private def runReader (reader : Reader Unit) (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match reader.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok (_, (_, cursor)) => + unless cursor == bytes.size do throw (IO.userError "extension snapshot has trailing bytes") + +def run (arithmetic graphs : System.FilePath) : IO Unit := do + runReader readArithmetic arithmetic + IO.println "extension arithmetic: 16 base inverses, 384 values, 7680 powers and 147456 ordered pairs match native" + runReader readGraphs graphs + IO.println "extension graphs: 240 assignments and 8016 node values match native and expression evaluation" + +end AiurTests.ExtensionArithmetic + +def main (args : List String) : IO Unit := do + match args with + | [arithmetic, graphs] => AiurTests.ExtensionArithmetic.run arithmetic graphs + | _ => throw (IO.userError "expected native extension arithmetic and graph snapshots") diff --git a/Tests/Aiur/ExtensionMmcs.lean b/Tests/Aiur/ExtensionMmcs.lean new file mode 100644 index 000000000..da2b12883 --- /dev/null +++ b/Tests/Aiur/ExtensionMmcs.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ExtensionMmcs +import Tests.Aiur.EmissionReader + +/-! Both native extension MMCS methods, their base-field delegation and +complete hash logs, including release-mode width multiplication overflow. -/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) + +namespace AiurTests.ExtensionMmcs + +private def readExtension : Reader Extension := do return ⟨← readField, ← readField⟩ + +private def readDigest : Reader Merkle.Digest := do + let bytes ← takeBytes 32 + if length : bytes.data.size = 32 then return ⟨bytes.data, length⟩ + else throw "incomplete extension MMCS digest" + +private def readDigests : Reader (List Merkle.Digest) := do readList (← readCount) readDigest + +private def readCall : Reader (List UInt8 × Merkle.Digest) := do + let input ← takeBytes (← readCount 100000) + return (input.data.toList, ← readDigest) + +private def readCorpus : Reader Nat := do + let header := "Aiur extension MMCS v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "extension MMCS snapshot version differs" + let wordBits ← readCount + unless wordBits == 32 || wordBits == 64 do throw "unsupported extension MMCS machine width" + let expected ← readList 7 readNat + let cases := expected[0]! + unless expected == [9597, 7362, 2566, 1661, 507, 3513, 42969] do + throw "incomplete extension MMCS corpus" + let mut shared := 0 + let mut accepted := 0 + let mut omitted := 0 + let mut overflow := 0 + let mut late := 0 + let mut calls := 0 + let mut paths := 0 + for case in [:cases] do + let multi ← readBool + let dimensions ← readList (← readCount) do + return Merkle.Dimensions.mk (← readNat) (← readCount 32) + unless dimensions.all (fun dim => dim.width < 2^wordBits) do + throw "extension MMCS width is not machine-representable" + let capHeight ← readCount + let indices ← readList (← readCount) readNat + let rows ← readList (← readCount) do + readList (← readCount) do readList (← readCount) readExtension + let proof ← readDigests + let cap ← readDigests + let native ← readBool + let covered ← readBool + let widthsFit ← readBool + let hashes ← readList (← readCount) readCall + unless (dimensions.all fun dim => dim.width * 2 < 2^wordBits) == widthsFit do + throw "extension MMCS width overflow differs" + unless Merkle.covered dimensions capHeight == covered do throw "extension MMCS cap coverage differs" + let inputs ← if multi then do + let result := ExtensionMmcs.replayMulti Blake3.digest wordBits dimensions capHeight indices rows proof + unless ExtensionMmcs.verifyMulti Blake3.digest wordBits dimensions capHeight indices cap rows proof == native do + throw s!"extension shared decision differs at {case}" + unless ExtensionMmcs.verifyMultiCovered Blake3.digest wordBits dimensions capHeight indices cap rows proof == + (native && covered) do throw "covered extension shared decision differs" + if let some nodes := result.result then + let tickets := nodes.flatMap PrunedMerkle.Node.tickets + unless tickets.length == (PrunedMerkle.uniqueIndices indices).length do + throw "extension shared ticket count differs" + for (index, query) in indices.zip rows do + unless tickets.any (fun ticket => ticket.index == index && ticket.rows == ExtensionMmcs.baseRows query) do + throw "extension shared reconstruction lost a query" + for node in nodes do + for ticket in node.tickets do + let some (_, query) := (indices.zip rows).find? fun (index, values) => + index == ticket.index && ExtensionMmcs.baseRows values == ticket.rows + | throw "extension shared path lost its original query" + let some path := ExtensionMmcs.replay Blake3.digest wordBits dimensions capHeight ticket.index query ticket.proof + | throw "extension shared path is not individually valid" + unless path.index == node.index && path.hashing.digest == node.digest do + throw "extension shared path reaches a different node" + unless path.hashing.inputs.all result.inputs.contains do + throw "extension shared path uses an unrecorded input" + paths := paths + 1 + pure result.inputs + else do + let [index] := indices | throw "individual extension MMCS has wrong index count" + let [values] := rows | throw "individual extension MMCS has wrong query count" + unless ExtensionMmcs.verify Blake3.digest wordBits dimensions capHeight index cap values proof == native do + throw s!"extension individual decision differs at {case}" + unless ExtensionMmcs.verifyCovered Blake3.digest wordBits dimensions capHeight index cap values proof == + (native && covered) do throw "covered extension individual decision differs" + match ExtensionMmcs.replay Blake3.digest wordBits dimensions capHeight index values proof with + | none => pure [] + | some result => paths := paths + 1; pure result.hashing.inputs + unless inputs == hashes.map Prod.fst do throw s!"extension MMCS hash sequence differs at {case}" + for (input, output) in hashes do + unless Blake3.digest input == output do throw "extension MMCS native hash differs" + if widthsFit then + for values in rows do + unless ExtensionMmcs.shape dimensions values == + Merkle.shape (ExtensionMmcs.baseDimensions wordBits dimensions) (ExtensionMmcs.baseRows values) do + throw "extension row shape differs from bounded base row shape" + if multi then shared := shared + 1 + if native then accepted := accepted + 1 + if native && !covered then omitted := omitted + 1 + if !widthsFit then overflow := overflow + 1 + if !native && !hashes.isEmpty then late := late + 1 + calls := calls + hashes.length + unless expected == [cases, shared, accepted, omitted, overflow, late, calls] do + throw "extension MMCS coverage totals differ" + unless paths == 20448 do throw "incomplete extension MMCS individual paths" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "extension MMCS snapshot has trailing bytes" + return paths + +end AiurTests.ExtensionMmcs + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.ExtensionMmcs.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok (paths, _) => IO.println s!"Extension MMCS: 9597 native decisions, 42969 hash calls and {paths} individual paths match" + | _ => throw (IO.userError "expected native extension MMCS snapshot") diff --git a/Tests/Aiur/Folding.lean b/Tests/Aiur/Folding.lean new file mode 100644 index 000000000..7c4416830 --- /dev/null +++ b/Tests/Aiur/Folding.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Folding +import Tests.Aiur.EmissionReader + +/-! Replay native row and matrix folds of global polynomials, including +partial coefficient blocks and distinct rows attaining the agreement bound. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) + +namespace AiurTests.Folding + +private def readExtension : Reader Extension := return ⟨← readField, ← readField⟩ + +private def readDomain (bits : Nat) : Reader Domain.Subgroup := do + let some domain := Domain.ofLogSize bits | throw "invalid folding domain" + return domain + +private def sample (seed : Nat) : Extension := ⟨G.ofNat (seed * 67 + 3), G.ofNat (seed * 13 + 1)⟩ + +private def coefficients (arity variant : Nat) : List Extension := + let length := match variant with + | 0 => 0 | 1 => 1 | 2 => arity - 1 | 3 => arity + | 4 => arity + 1 | 5 => 2 * arity + 1 | 6 => 3 * arity | _ => 3 * arity + 2 + (List.range length).map (fun index => + if variant == 6 then (if index + 1 == length then 1 else 0) + else if variant == 7 && index > arity then 0 + else sample (index + 17)) + +private def checkValues (expected : List Extension) : Reader Unit := do + unless (← readCount expected.length) == expected.length do throw "native folding vector length differs" + unless (← readList expected.length readExtension) == expected do throw "native folding vector differs" + +private def checkFolded (arity : Domain.Subgroup) (challenge : Extension) + (polynomial : List Extension) : Reader (List Extension) := do + let folded := NativeAIR.Folding.foldCoefficients arity challenge polynomial + checkValues folded + let size := Domain.size arity + unless folded.length == (polynomial.length + size - 1) / size do + throw "folded coefficient bound differs" + return folded + +private def readCorpus : Reader (List Nat) := do + let header := "Aiur global FRI folding v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "global folding version differs" + let mut rows := 0 + let mut evaluations := 0 + for parentBits in [:33] do + let parent ← readDomain parentBits + for arityBits in [:min parentBits 6 + 1] do + let arity ← readDomain arityBits + let child ← readDomain (parentBits - arityBits) + let size := Domain.size arity + let mask := Domain.size child - 1 + let indices := [0, mask / 2, mask] |>.mergeSort (· ≤ ·) |>.eraseDups + unless (← readCount 3) == indices.length do throw "folding index inventory differs" + for index in indices do + unless (← readNat) == index do throw "native folding index differs" + let nodes := (Polynomial.foldingNodes parent arity index).map Extension.ofBase + let childPoint := Extension.ofBase (FriDomain.queryPoint child index) + for variant in [:8] do + let polynomial := coefficients size variant + let values := nodes.map (fun node => Quotient.horner node polynomial) + checkValues polynomial + checkValues values + let row := NativeAIR.Folding.rowCoefficients arity childPoint polynomial + unless row.length ≤ size && nodes.map (fun node => Quotient.horner node row) == values do + throw "restriction to the folding coset differs" + let challenges := [0, sample 41, 1, + Extension.ofBase (FriDomain.foldNode parent arity index 0), + Extension.ofBase (FriDomain.foldNode parent arity index (size - 1))] + for challenge in challenges do + unless (← readExtension) == challenge do throw "native folding challenge differs" + let folded ← checkFolded arity challenge polynomial + let result ← readExtension + unless Interpolation.foldRow parent arity index values challenge == some result && + Quotient.horner childPoint folded == result && Quotient.horner challenge row == result do + throw "native row fold differs from the global folded polynomial" + evaluations := evaluations + 1 + rows := rows + 1 + let mut matrices := 0 + let mut matrixRows := 0 + for parentBits in [1:10] do + let parent ← readDomain parentBits + for arityBits in [1:min parentBits 6 + 1] do + let arity ← readDomain arityBits + let child ← readDomain (parentBits - arityBits) + let size := Domain.size arity + for variant in [:8] do + let polynomial := coefficients size variant + let data := (List.range (Domain.size parent)).map (fun index => + Quotient.horner (Extension.ofBase (FriDomain.queryPoint parent index)) polynomial) + checkValues polynomial + checkValues data + for challenge in [0, sample 41, 1] do + unless (← readExtension) == challenge do throw "native matrix folding challenge differs" + let folded ← checkFolded arity challenge polynomial + unless (← readCount (Domain.size child)) == Domain.size child do throw "native folded matrix height differs" + let result ← readList (Domain.size child) readExtension + for index in [:Domain.size child] do + let row := (data.drop (index * size)).take size + let expected := Quotient.horner (Extension.ofBase (FriDomain.queryPoint child index)) folded + unless result[index]? == some expected && + Interpolation.foldRow parent arity index row challenge == some expected do + throw "native matrix fold differs from the global folded polynomial" + matrixRows := matrixRows + 1 + matrices := matrices + 1 + let mut pairs := 0 + let mut pairEvaluations := 0 + for arityBits in [:7] do + let arity ← readDomain arityBits + let parent ← readDomain (arityBits + 2) + let size := Domain.size arity + let challenges := (Polynomial.foldingNodes parent arity 1).map Extension.ofBase ++ [0, sample 41] + let left := (List.range size).map (fun index => sample (index + 7)) + let right := left.set (size / 2) (sample (size / 2 + 7) + sample 131) + unless challenges.eraseDups == challenges && left != right do throw "row agreement preconditions differ" + checkValues left + checkValues right + let mut agreements := 0 + for challenge in challenges do + unless (← readExtension) == challenge do throw "native row comparison challenge differs" + let first ← readExtension + let second ← readExtension + unless Interpolation.foldRow parent arity 1 left challenge == some first && + Interpolation.foldRow parent arity 1 right challenge == some second do + throw "native distinct row folds differ" + if first == second then agreements := agreements + 1 + pairEvaluations := pairEvaluations + 1 + unless (← readNat) == agreements && agreements == size - 1 do throw "distinct rows miss the sharp agreement bound" + pairs := pairs + 1 + let counts := [rows, evaluations, matrices, matrixRows, pairs, pairEvaluations] + unless counts == [4872, 24360, 936, 24048, 7, 141] do throw "incomplete global folding corpus" + unless (← readList 6 readNat) == counts do throw "global folding coverage totals differ" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "global folding snapshot has trailing bytes" + return counts + +end AiurTests.Folding + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.Folding.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok (counts, _) => IO.println s!"Native global FRI rows, evaluations, matrices, matrix rows, distinct pairs and pair evaluations match: {counts}" + | _ => throw (IO.userError "expected native global FRI folding snapshot") diff --git a/Tests/Aiur/FriDomain.lean b/Tests/Aiur/FriDomain.lean new file mode 100644 index 000000000..5b6af1b10 --- /dev/null +++ b/Tests/Aiur/FriDomain.lean @@ -0,0 +1,113 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FriDomain +import Tests.Aiur.EmissionReader + +/-! Actual native reversal, coset points and FRI folding at every sampled +interpolation node, including singleton helpers and full machine widths. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader + +namespace AiurTests.FriDomain + +private def samples (bits exhaustive : Nat) : List Nat := + let mask := 2^bits - 1 + (List.range (min (mask + 1) exhaustive) ++ [mask, mask / 2, mask - 1] ++ + (List.range 16).map (fun seed => seed * 0x0a3751c9 % 2^bits)).mergeSort (· ≤ ·) |>.eraseDups + +private def checkedIndices (expected : List Nat) : Reader Unit := do + unless (← readCount expected.length) == expected.length do throw "FRI domain index inventory differs" + +private def readDomain (bits : Nat) : Reader Domain.Subgroup := do + let some domain := Domain.ofLogSize bits | throw "invalid FRI domain logarithm" + return domain + +private def readCorpus : Reader (List Nat) := do + let header := "Aiur FRI domains v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "FRI domain version differs" + let wordBits ← readCount 64 + unless wordBits == 32 || wordBits == 64 do throw "unsupported FRI native word width" + let mut reversals := 0 + for bits in [:wordBits + 1] do + let indices := samples bits 1024 + checkedIndices indices + for index in indices do + unless (← readNat) == index do throw "native bit reversal index differs" + let reversed ← readNat + unless FriDomain.reverseBits bits index == reversed && + FriDomain.wordReverse wordBits bits index == reversed && + FriDomain.reverseBits bits reversed == index do throw "native bit reversal differs" + reversals := reversals + 1 + let emptyWidth ← readNat + unless emptyWidth == 2^(wordBits - 1) && FriDomain.wordReverse wordBits 0 1 == emptyWidth && + FriDomain.reverseBits 0 1 == 0 do throw "native zero-width overflow differs" + let mut points := 0 + for bits in [:33] do + let domain ← readDomain bits + let indices := samples bits 1024 + checkedIndices indices + for index in indices do + unless (← readNat) == index do throw "FRI query index differs" + unless (← readField) == FriDomain.queryPoint domain index do throw "FRI query point differs" + unless (← readField) == FriDomain.inputPoint domain index do throw "FRI input coset point differs" + points := points + 1 + let mut nested := 0 + for parentBits in [:33] do + let parent ← readDomain parentBits + for childBits in [:parentBits + 1] do + let child ← readDomain childBits + let indices := samples childBits 4 + checkedIndices indices + for index in indices do + unless (← readNat) == index do throw "FRI nested index differs" + let point ← readField + unless point == FriDomain.queryPoint parent index && point == FriDomain.queryPoint child index do + throw "FRI final-domain point differs" + nested := nested + 1 + let mut rows := 0 + let mut slots := 0 + for parentBits in [:33] do + let parent ← readDomain parentBits + for arityBits in [:min parentBits 8 + 1] do + let arity ← readDomain arityBits + let height := parentBits - arityBits + let child ← readDomain height + let mask := 2^height - 1 + let indices := [0, mask / 2, mask, 0x0a3751c9 % 2^height] |>.mergeSort (· ≤ ·) |>.eraseDups + checkedIndices indices + for index in indices do + unless (← readNat) == index do throw "FRI folding index differs" + for slot in [:Domain.size arity] do + let node ← readField + let power ← readField + let folded : ProofCodec.Extension := ⟨← readField, ← readField⟩ + unless node == FriDomain.foldNode parent arity index slot && + node == FriDomain.queryPoint parent (index * Domain.size arity + slot) do + throw "native FRI folding node differs" + unless power == FriDomain.queryPoint child index && power == node.pow (Domain.size arity) do + throw "native FRI reduced point differs" + unless folded == ProofCodec.Extension.mk (G.ofNat (slot + 1)) (G.ofNat (slot * 19 + 3)) do + throw "native FRI fold_row selected a different evaluation" + slots := slots + 1 + rows := rows + 1 + let counts := [reversals, points, nested, rows, slots] + unless counts == [if wordBits == 64 then 58295 else 24951, 24951, 9617, 990, 50042] do + throw "incomplete FRI domain corpus" + unless (← readList 5 readNat) == counts do throw "FRI domain coverage totals differ" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "FRI domain snapshot has trailing bytes" + return counts + +end AiurTests.FriDomain + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.FriDomain.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok (counts, _) => IO.println s!"FRI native reversals, query points, nested points, rows and fold nodes match: {counts}" + | _ => throw (IO.userError "expected native FRI domain snapshot") diff --git a/Tests/Aiur/FriQuery.lean b/Tests/Aiur/FriQuery.lean new file mode 100644 index 000000000..d1f940d75 --- /dev/null +++ b/Tests/Aiur/FriQuery.lean @@ -0,0 +1,212 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FriQuery +import Tests.Aiur.EmissionReader + +/-! Replay the actual private FRI query routine using calls captured through +the public verifier's folding hook. Inputs come from known source polynomials +and ordinary native PCS proofs, including every authenticated input row. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) + +namespace AiurTests.FriQuery + +private structure Source where + logSize : Nat + columns : List (List G) + +private structure Opening where + arity : Domain.Subgroup + siblings : List (List Extension) + +private def readExtension : Reader Extension := return ⟨← readField, ← readField⟩ + +private def domain (bits : Nat) : Reader Domain.Subgroup := do + let some result := Domain.ofLogSize bits | throw "invalid query domain" + return result + +private def readValues (read : Reader R) (length : Nat) : Reader (List R) := do + unless (← readCount length) == length do throw "native query vector length differs" + readList length read + +private def checkValues [BEq R] (read : Reader R) (expected : List R) : Reader Unit := do + unless (← readValues read expected.length) == expected do throw "native query vector differs" + +private def layout (index finalBits : Nat) : List (List Nat) := + let offsets := match index with + | 0 => [[0]] | 1 => [[2]] | 2 => [[6, 2], [2, 0]] | _ => [[3, 6], [3]] + offsets.map (List.map (fun bits => bits + finalBits + if finalBits == 0 then 0 else 1)) + +private def polynomial (seed bits column : Nat) : List G := + (List.range (2^bits)).map (fun index => G.ofNat (seed * 101 + column * 29 + index * 13 + 1)) + +private def sources (caseIndex finalBits layoutIndex : Nat) : List (List Source) := + (layout layoutIndex finalBits).zipIdx.map fun (matrices, batch) => + matrices.zipIdx.map fun (bits, matrix) => + ⟨bits, (List.range (2 + matrix)).map (polynomial (caseIndex + batch * 7 + matrix) bits)⟩ + +private def readSources (expected : List (List Source)) : Reader Unit := do + unless (← readCount expected.length) == expected.length do throw "query source batch count differs" + for batch in expected do + unless (← readCount batch.length) == batch.length do throw "query source matrix count differs" + for source in batch do + unless (← readNat) == source.logSize do throw "query source height differs" + unless (← readCount source.columns.length) == source.columns.length do throw "query source width differs" + for coefficients in source.columns do checkValues readField coefficients + +/-- Derive each quotient polynomial from its known source coefficients. +The native input-reduction routine is not used to obtain these values. -/ +private def groupedPolynomials (input : List (List Source)) (points : List Extension) + (alpha : Extension) (blowup : Nat) : List (Nat × List Extension) := Id.run do + let terms := input.flatten.flatMap fun source => + points.flatMap fun point => source.columns.map fun coefficients => + (source.logSize + blowup, Polynomial.divide point (coefficients.map Extension.ofBase)) + let heights := terms.map Prod.fst |>.mergeSort (· ≥ ·) |>.eraseDups + return heights.map fun height => + let (_, coefficients) := terms.foldl (fun (power, sum) (logHeight, polynomial) => + if height == logHeight then (power * alpha, Polynomial.add sum (Polynomial.scale power polynomial)) + else (power, sum)) (1, []) + (height, coefficients) + +private def reducedOpenings (initial : Domain.Subgroup) (index : Nat) + (polynomials : List (Nat × List Extension)) : Reader (List (Nat × Extension)) := + polynomials.mapM fun (height, coefficients) => do + let current ← domain height + unless height ≤ initial.val do throw "input exceeds the global query domain" + let reducedIndex := index / 2^(initial.val - height) + return (height, Quotient.horner (Extension.ofBase (FriDomain.inputPoint current reducedIndex)) coefficients) + +private def checkInputRows (input : List (List Source)) (initial : Domain.Subgroup) (indices : List Nat) + (blowup : Nat) (rows : List (List (List (List G)))) : Reader Unit := do + for (batch, queries) in input.zip rows do + for (index, matrices) in indices.zip queries do + for (source, row) in batch.zip matrices do + let current ← domain (source.logSize + blowup) + let point := FriDomain.inputPoint current (index / 2^(initial.val - current.val)) + unless row == source.columns.map (Quotient.horner point) do throw "authenticated native input row differs from its source polynomial" + +private def checkGuards (initial final : Domain.Subgroup) (index : Nat) + (openings : List (Nat × Extension)) (rounds : List NativeAIR.FriQuery.Round) + (finalPolynomial : List Extension) : Reader Unit := do + unless (NativeAIR.FriQuery.run initial final (Domain.size initial) openings rounds).isNone && + (NativeAIR.FriQuery.run initial final index [] rounds).isNone && + (NativeAIR.FriQuery.check initial final index openings rounds (Polynomial.add [1] finalPolynomial)).isNone do + throw "query admission or final polynomial guard differs" + let some (height, value) := openings.head? | throw "missing initial query input" + unless (NativeAIR.FriQuery.run initial final index ((height + 1, value) :: openings.tail) rounds).isNone && + (NativeAIR.FriQuery.run initial final index ((height, value) :: openings) rounds).isNone do + throw "initial or duplicated reduced height was accepted" + if let round :: rest := rounds then + let singleton ← domain 0 + unless (NativeAIR.FriQuery.run initial initial index openings rounds).isNone && + (NativeAIR.FriQuery.run initial final index openings ({ round with arity := singleton } :: rest)).isNone && + (NativeAIR.FriQuery.run initial final index openings ({ round with siblings := 0 :: round.siblings } :: rest)).isNone do + throw "query round shape or terminal height guard differs" + +private def readCase (caseIndex blowup finalBits maxArity layoutIndex : Nat) : Reader (Nat × Nat × Nat) := do + let input := sources caseIndex finalBits layoutIndex + let queries := 1 + layoutIndex + finalBits + let globalBits := ((layout layoutIndex finalBits).flatten.foldl max 0) + blowup + unless (← readList 6 readNat) == [blowup, finalBits, maxArity, queries, layoutIndex, globalBits] do + throw "native query profile differs" + let initial ← domain globalBits + let final ← domain (finalBits + blowup) + readSources input + let points ← readValues readExtension (1 + layoutIndex % 2) + let some first := points.head? | throw "missing opening point" + unless points == (if layoutIndex % 2 == 0 then [first] else [first, first + ⟨19, 3⟩]) do + throw "native query opening points differ" + for batch in input do + for source in batch do + for point in points do + checkValues readExtension (source.columns.map fun coefficients => + Quotient.horner point (coefficients.map Extension.ofBase)) + let inputRows ← input.mapM fun batch => + readList queries (batch.mapM fun source => readValues readField source.columns.length) + let random ← readList (← readCount 34) readExtension + let some alpha := random.head? | throw "missing query batching challenge" + let indices ← readList queries do + unless (← readNat) == globalBits do throw "native query sample width differs" + let index ← readNat + unless index < Domain.size initial do throw "native query index exceeds its domain" + return index + let roundCount ← readCount 32 + unless random.length == roundCount + 1 do throw "native query challenge count differs" + let openings ← readList roundCount do + let arityBits ← readNat + unless 0 < arityBits && arityBits ≤ maxArity do throw "native query arity exceeds its profile" + let arity ← domain arityBits + let siblings ← readList queries (readValues readExtension (Domain.size arity - 1)) + return Opening.mk arity siblings + unless (openings.map (fun opening => opening.arity.val)).sum + final.val == initial.val do + throw "native query round heights do not reach the final domain" + let finalPolynomial ← readValues readExtension (2^finalBits) + checkInputRows input initial indices blowup inputRows + let polynomials := groupedPolynomials input points alpha blowup + let callCount ← readNat + unless callCount == queries * roundCount do throw "native query fold call count differs" + let results ← indices.zipIdx.mapM fun (index, query) => do + let reduced ← reducedOpenings initial index polynomials + let rounds ← (openings.zip random.tail).mapM fun (opening, challenge) => do + let some siblings := opening.siblings[query]? | throw "missing native query siblings" + return NativeAIR.FriQuery.Round.mk opening.arity challenge siblings + let some result := NativeAIR.FriQuery.check initial final index reduced rounds finalPolynomial + | throw "native accepted query fails checked reconstruction or final evaluation" + unless result.rows.length == roundCount && result.state.domain == final && + result.state.index == index / 2^(globalBits - final.val) do + throw "checked query chain dimensions differ" + for (round, row) in rounds.zip result.rows do + unless (← readList 3 readNat) == [row.index, row.domain.val, round.arity.val] && + (← readExtension) == round.challenge do + throw "native query fold metadata differs" + checkValues readExtension row.values + let folded ← readExtension + let parent ← domain (row.domain.val + round.arity.val) + unless Interpolation.foldRow parent round.arity row.index row.values round.challenge == some folded do + throw "native query row folding differs" + checkGuards initial final index reduced rounds finalPolynomial + return result + for result in results do + unless (← readNat) == result.state.index && (← readExtension) == result.state.value && + Quotient.horner (Extension.ofBase (FriDomain.queryPoint final result.state.index)) finalPolynomial == result.state.value do + throw "native query final index or polynomial value differs" + return (queries, roundCount, callCount) + +private def readCorpus : Reader (List Nat) := do + let header := "Aiur native FRI query chains v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "FRI query version differs" + let mut cases := 0 + let mut totalQueries := 0 + let mut totalRounds := 0 + let mut totalCalls := 0 + for blowup in [1:3] do + for finalBits in [:3] do + for maxArity in [1:5] do + for layoutIndex in [:4] do + let (queries, rounds, calls) ← try readCase cases blowup finalBits maxArity layoutIndex + catch message => throw s!"query case {cases}: {message}" + cases := cases + 1 + totalQueries := totalQueries + queries + totalRounds := totalRounds + rounds + totalCalls := totalCalls + calls + let counts := [cases, totalQueries, totalRounds, totalCalls] + unless counts == [96, 336, 246, 1030] do throw "incomplete native query corpus" + unless (← readList 4 readNat) == counts do throw "native query coverage totals differ" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "native query snapshot has trailing bytes" + return counts + +end AiurTests.FriQuery + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.FriQuery.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok (counts, _) => IO.println s!"Native FRI proofs, queries, rounds and fold calls match: {counts}" + | _ => throw (IO.userError "expected native FRI query snapshot") diff --git a/Tests/Aiur/FrontendExpressions.lean b/Tests/Aiur/FrontendExpressions.lean new file mode 100644 index 000000000..508f506cb --- /dev/null +++ b/Tests/Aiur/FrontendExpressions.lean @@ -0,0 +1,181 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.FrontendExpressions + +open Aiur Aiur.NativeAIR + +namespace AiurTests.FrontendExpressions + +private def fixtures : Array Expr := Id.run do + let mut result : Array Expr := #[.konst 0, .konst 1, .konst (0 - 1), .konst 17] + for source in [Source.preprocessed, .main, .stage2] do + for offset in [RowOffset.current, .next] do + result := result.push (.var ⟨source, offset, 2⟩) + let x := (mainCurrent 0).expr + let y := (mainCurrent 1).expr + return result ++ #[.publicInput 0, .publicInput 2, .isFirstRow, .isLastRow, .isTransition, + .neg x, .add x y, .sub (.konst 0) x, .mul (.konst 0) y, + .neg (.konst 0), .neg (.konst 1), .neg (.neg x), .neg (.neg (.konst 1)), + .add (.konst 1) (.konst 1)] + +private def matrix (seed slot : Nat) : Array G := Array.ofFn fun index : Fin 16 => + let choices : Array G := #[0, 1, 2, 17, 255, 256, 65536, 0 - 1] + if slot == 2 && index.val == 6 then (#[0, 1, 2, 0 - 1] : Array G)[seed]?.getD 0 + else choices[(slot * 3 + seed * 5 + index.val * 7) % choices.size]?.getD 0 + +private def assignment (seed : Nat) : Values G := + ⟨(fun source offset => matrix seed + ((match source with | .preprocessed => 0 | .main => 2 | .stage2 => 4) + + (match offset with | .current => 0 | .next => 1))), + matrix seed 6, (if seed == 0 then 1 else 0), (if seed == 3 then 1 else 0), + (if seed == 3 then 0 else 1)⟩ + +private abbrev Reader := StateT (ByteArray × Nat) (Except String) + +private def takeBytes (count : Nat) : Reader ByteArray := do + let (bytes, cursor) ← get + if cursor + count > bytes.size then throw s!"frontend snapshot truncated at {cursor}" + set (bytes, cursor + count) + return bytes.extract cursor (cursor + count) + +private def readNat (count : Nat := 8) : Reader Nat := do + let bytes ← takeBytes count + let mut value := 0 + for index in [:count] do value := value + bytes[index]!.toNat * 256^index + return value + +private def readField : Reader G := do + let value ← readNat + unless value < gSize.toNat do throw "noncanonical frontend field value" + return G.ofNat value + +private def readBool : Reader Bool := do + match ← readNat with + | 0 => return false + | 1 => return true + | _ => throw "invalid frontend boolean" + +private def readList (count : Nat) (reader : Reader α) : Reader (List α) := + (List.range count).mapM fun _ => reader + +private def readExpr : Nat → Reader Expr + | 0 => throw "frontend expression exceeds snapshot depth bound" + | fuel + 1 => do + match ← readNat 1 with + | 0 => return .konst (← readField) + | 1 => + let source ← match ← readNat 1 with + | 0 => pure Source.preprocessed | 1 => pure Source.main | 2 => pure Source.stage2 + | _ => throw "invalid frontend column source" + let offset ← match ← readNat 1 with + | 0 => pure RowOffset.current | 1 => pure RowOffset.next + | _ => throw "invalid frontend row offset" + return .var ⟨source, offset, ← readNat⟩ + | 2 => return .publicInput (← readNat) + | 3 => return .isFirstRow + | 4 => return .isLastRow + | 5 => return .isTransition + | 6 => return .add (← readExpr fuel) (← readExpr fuel) + | 7 => return .sub (← readExpr fuel) (← readExpr fuel) + | 8 => return .mul (← readExpr fuel) (← readExpr fuel) + | 9 => return .neg (← readExpr fuel) + | _ => throw "invalid frontend expression tag" + +private def readFixture : Reader Expr := do + let index ← readNat + let some expr := fixtures[index]? | throw "frontend fixture index out of range" + return expr + +private def readSmart : Reader Unit := do + let kind ← readNat 1 + let left ← readFixture + let right ← readFixture + let expected ← match kind with + | 0 => pure (left.frontAdd right) + | 1 => pure (left.frontSub right) + | 2 => pure (left.frontMul right) + | 3 => pure left.frontNeg + | _ => throw "invalid smart operation tag" + let actual ← readExpr 64 + unless actual == expected do throw s!"native smart-constructor tree differs for operation {kind}" + unless (← readBool) == expected.isConstant do throw "native smart constant flag differs" + if left.noConstantNegs && (kind == 3 || right.noConstantNegs) then + unless expected.noConstantNegs do throw "smart constructor lost the negation invariant" + for seed in [:4] do + let value ← readField + unless expected.eval goldilocksOps (assignment seed) == some value do + throw s!"native smart value differs for operation {kind}, assignment {seed}" + +private def sameEmission (left right : AIR.OpEmission) : Bool := + left.outputs == right.outputs && left.used == right.used && left.equations == right.equations && + left.queries.isEmpty && right.queries.isEmpty && left.calls.isEmpty && right.calls.isEmpty + +private def readEmission : Reader Unit := do + let kind ← readNat 1 + let leftExpr ← readFixture + let rightExpr ← readFixture + let left : RowExpr := ⟨leftExpr, ← readNat⟩ + let right : RowExpr := ⟨rightExpr, ← readNat⟩ + unless left.expr.noConstantNegs && right.expr.noConstantNegs do throw "invalid core expression fixture" + let used ← readNat + let degree ← readNat + let output ← readExpr 64 + let equationCount ← readNat + unless equationCount ≤ 2 do throw "too many core equations" + let equations ← readList equationCount (readExpr 64) + let selector := (mainCurrent 6).expr + let (expected, op) ← match kind with + | 0 => pure (emitEqZero selector 7 left, Bytecode.Op.eqZero 0) + | 1 => pure (ScalarEmission.mk (left.add right) 0 [], Bytecode.Op.add 0 1) + | 2 => pure (ScalarEmission.mk (left.sub right) 0 [], Bytecode.Op.sub 0 1) + | 3 => pure (emitMul selector 7 left right, Bytecode.Op.mul 0 1) + | _ => throw "invalid scalar operation tag" + unless output == expected.output.expr && degree == expected.output.degree && + used == expected.used && equations == expected.equations do + throw s!"native scalar expression emission differs for operation {kind}" + unless expected.output.expr.noConstantNegs do throw "scalar output lost the negation invariant" + for seed in [:4] do + let value ← readField + let constant ← readBool + let polynomialValues ← readList equationCount readField + let values := assignment seed + let some evaluated := expected.eval values | throw "scalar expression evaluation failed" + let native : AIR.OpEmission := { + outputs := #[⟨value, degree, constant⟩], used, equations := polynomialValues } + unless sameEmission evaluated native do throw "native scalar evaluated emission differs" + let some a := left.eval values | throw "scalar left input evaluation failed" + let some b := right.eval values | throw "scalar right input evaluation failed" + let row := fun index => (matrix seed 2)[7 + index]?.getD 0 + let selected := (matrix seed 2)[6]?.getD 0 + let some valued := AIR.emitOp row selected 0 op #[a, b] | throw "valued scalar emission failed" + unless sameEmission evaluated valued do throw "symbolic and valued scalar emissions differ" + +private def readCorpus : Reader Unit := do + let header := "Aiur frontend expressions v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "frontend snapshot version differs" + let count ← readNat + unless count == 24 && fixtures.size == 24 do throw "incomplete frontend fixtures" + unless (← readList count (readExpr 64)).toArray == fixtures do throw "frontend input trees differ" + unless (fixtures.filter (·.noConstantNegs)).size == 21 do throw "incomplete negation-invariant boundary cases" + unless (← readNat) == 1752 do throw "incomplete smart-constructor corpus" + for _ in [:1752] do readSmart + unless (← readNat) == 9804 do throw "incomplete scalar-emission corpus" + for _ in [:9804] do readEmission + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "frontend snapshot has trailing bytes" + +def run (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok _ => IO.println "frontend expressions: 1,752 smart trees, 9,804 scalar emissions and 46,224 native/Lean assignments match" + +end AiurTests.FrontendExpressions + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.FrontendExpressions.run path + | _ => throw (IO.userError "expected native frontend-expression snapshot") diff --git a/Tests/Aiur/GraphCompilation.lean b/Tests/Aiur/GraphCompilation.lean new file mode 100644 index 000000000..68cf01034 --- /dev/null +++ b/Tests/Aiur/GraphCompilation.lean @@ -0,0 +1,189 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.GraphCompilation + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.Compiler + +namespace AiurTests.GraphCompilation + +private abbrev Reader := StateT (ByteArray × Nat) (Except String) + +private def takeBytes (count : Nat) : Reader ByteArray := do + let (bytes, cursor) ← get + if cursor + count > bytes.size then throw s!"compiler snapshot truncated at {cursor}" + set (bytes, cursor + count) + return bytes.extract cursor (cursor + count) + +private def readNat (count : Nat := 8) : Reader Nat := do + let bytes ← takeBytes count + let mut value := 0 + for index in [:count] do value := value + bytes[index]!.toNat * 256^index + return value + +private def readField : Reader G := do + let value ← readNat + unless value < gSize.toNat do throw "noncanonical compiler field value" + return G.ofNat value + +private def readList (count : Nat) (reader : Reader α) : Reader (List α) := + (List.range count).mapM fun _ => reader + +private def readValues : Reader (Array G) := do + return (← readList (← readNat) readField).toArray + +private def readColumn : Reader ColRef := do + let source ← match ← readNat 1 with + | 0 => pure Source.preprocessed | 1 => pure Source.main | 2 => pure Source.stage2 + | _ => throw "invalid compiler column source" + let offset ← match ← readNat 1 with + | 0 => pure RowOffset.current | 1 => pure RowOffset.next + | _ => throw "invalid compiler row offset" + return ⟨source, offset, ← readNat⟩ + +private def readExpr : Nat → Reader Expr + | 0 => throw "compiler expression exceeds snapshot depth bound" + | fuel + 1 => do + match ← readNat 1 with + | 0 => return .konst (← readField) + | 1 => return .var (← readColumn) + | 2 => return .publicInput (← readNat) + | 3 => return .isFirstRow + | 4 => return .isLastRow + | 5 => return .isTransition + | 6 => return .add (← readExpr fuel) (← readExpr fuel) + | 7 => return .sub (← readExpr fuel) (← readExpr fuel) + | 8 => return .mul (← readExpr fuel) (← readExpr fuel) + | 9 => return .neg (← readExpr fuel) + | _ => throw "invalid compiler expression tag" + +private def readNode : Reader Node := do + match ← readNat 1 with + | 0 => return .konst (← readField) + | 1 => return .var (← readColumn) + | 2 => return .publicInput (← readNat) + | 3 => return .isFirstRow + | 4 => return .isLastRow + | 5 => return .isTransition + | 6 => return .add (← readNat) (← readNat) + | 7 => return .sub (← readNat) (← readNat) + | 8 => return .mul (← readNat) (← readNat) + | 9 => return .neg (← readNat) + | _ => throw "invalid compiler node tag" + +private def readSpec : Reader (GraphWidths × List ExprLookup × List Expr) := do + let widths : GraphWidths := ⟨← readNat, ← readNat, ← readNat, ← readNat⟩ + let lookups ← readList (← readNat) do + let multiplicity ← readExpr 64 + let args ← readList (← readNat) (readExpr 64) + return ExprLookup.mk multiplicity args + let constraints ← readList (← readNat) (readExpr 64) + return (widths, lookups, constraints) + +private def nodeDegree (degrees : Array Nat) : Node → Option Nat + | .konst _ | .publicInput _ | .isTransition => some 0 + | .var _ | .isFirstRow | .isLastRow => some 1 + | .add a b | .sub a b => return max (← degrees[a]?) (← degrees[b]?) + | .mul a b => return (← degrees[a]?) + (← degrees[b]?) + | .neg a => degrees[a]? + +private def readGraph : Reader BaseCompilation := do + let nodes ← readList (← readNat) readNode + let mut degrees : Array Nat := #[] + for node in nodes do + let native ← readNat + let some expected := nodeDegree degrees node | throw "native compiler emitted an invalid child read" + unless native == expected && native < 2^32 do throw "compiled node degree differs" + degrees := degrees.push expected + let zeros ← readList (← readNat) readNat + let lookups ← readList (← readNat) do + let multiplicity ← readNat + let args ← readList (← readNat) readNat + return Lookup.mk multiplicity args + let lookupEnd ← readNat + let maximum ← readNat + let some zeroDegrees := zeros.mapM (fun index => degrees[index]?) | throw "invalid native zero root" + unless maximum == zeroDegrees.foldl max 0 do throw "compiled maximum degree differs" + return ⟨⟨nodes, zeros, lookups⟩, lookupEnd⟩ + +private def readAssignment (widths : GraphWidths) (lookups : List ExprLookup) (constraints : List Expr) + (compiled : BaseCompilation) : Reader Nat := do + let preCurrent ← readValues + let preNext ← readValues + let mainCurrent ← readValues + let mainNext ← readValues + let stageCurrent ← readValues + let stageNext ← readValues + let publics ← readValues + let indicators ← readValues + unless preCurrent.size == widths.preprocessed && preNext.size == widths.preprocessed && + mainCurrent.size == widths.main && mainNext.size == widths.main && + stageCurrent.size == widths.stage2 && stageNext.size == widths.stage2 && + publics.size == widths.publics && indicators.size == 3 do throw "compiler assignment dimensions differ" + let values : Values G := ⟨(fun source offset => match source, offset with + | .preprocessed, .current => preCurrent | .preprocessed, .next => preNext + | .main, .current => mainCurrent | .main, .next => mainNext + | .stage2, .current => stageCurrent | .stage2, .next => stageNext), + publics, indicators[0]?.getD 0, indicators[1]?.getD 0, indicators[2]?.getD 0⟩ + let native ← readValues + unless compiled.graph.sweep goldilocksOps values == some native do throw "compiled graph sweep differs" + let nativePrefix ← readValues + unless sweepFrom goldilocksOps values.withoutStage2 (compiled.graph.nodes.take compiled.lookupEnd) #[] == some nativePrefix do + throw "stored lookup-prefix sweep differs" + unless compiled.graph.sweepLookupPrefix goldilocksOps values == some (nativePrefix.extract 0 compiled.graph.lookupPrefix) do + throw "root-derived lookup-prefix sweep differs" + let original ← readValues + unless evalExprs goldilocksOps values constraints == some original.toList do throw "source constraint evaluation differs" + let some zeroValues := readNodes native compiled.graph.zeros | throw "compiled zero root cannot be read" + unless zeroValues.all (· == 0) == original.all (· == 0) do throw "constraint satisfaction changed during compilation" + let nativeLookups ← readList lookups.length do + let multiplicity ← readField + let args ← readValues + return (multiplicity, args.toList) + unless lookups.mapM (ExprLookup.eval goldilocksOps values) == some nativeLookups do throw "source lookup evaluation differs" + unless compiled.graph.lookups.mapM (readLookup native) == some nativeLookups do throw "compiled lookup evaluation differs" + return native.size + +private def readCorpus : Reader (Nat × Nat × Nat × Nat) := do + let header := "Aiur graph compilation v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "invalid graph compiler snapshot header" + let count ← readNat + unless count == 1484 do throw "compiler graph case count differs" + let mut assignments := 0 + let mut nodeValues := 0 + let mut shortened := 0 + for index in [:count] do + let (widths, lookups, constraints) ← readSpec + let native ← readGraph + let some expected := compileBase widths lookups constraints | throw s!"Lean rejected native graph {index}" + unless native == expected do throw s!"compiled graph structure differs at case {index}" + unless checkedGraphPrefix widths native.graph == some native.graph.lookupPrefix do throw "compiled graph failed its layout guard" + unless native.graph.lookupPrefix ≤ native.lookupEnd && native.lookupEnd ≤ native.graph.nodes.length do throw "invalid stored lookup prefix" + if native.graph.lookupPrefix < native.lookupEnd then shortened := shortened + 1 + for _ in [:8] do + nodeValues := nodeValues + (← readAssignment widths lookups constraints native) + assignments := assignments + 1 + unless shortened > 0 do throw "compiler corpus does not cover folded unused lookup nodes" + let rejected ← readNat + unless rejected == 38 do throw "compiler rejection case count differs" + for index in [:rejected] do + let (widths, lookups, constraints) ← readSpec + unless (compileBase widths lookups constraints).isNone do throw s!"Lean accepted native rejection {index}" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "trailing compiler snapshot bytes" + return (count, rejected, assignments, nodeValues) + +def main (args : List String) : IO UInt32 := do + let [path] := args | throw (IO.userError "usage: aiur-graph-compilation-tests ") + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok ((graphs, rejected, assignments, nodes), _) => + IO.println s!"graph compilation: {graphs} complete graphs, {rejected} rejected specifications, {assignments} assignments, {nodes} node values match native Rust" + return 0 + +end AiurTests.GraphCompilation + +def main := AiurTests.GraphCompilation.main diff --git a/Tests/Aiur/Hoisting.lean b/Tests/Aiur/Hoisting.lean new file mode 100644 index 000000000..565162aba --- /dev/null +++ b/Tests/Aiur/Hoisting.lean @@ -0,0 +1,97 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur + +/-! Effect-order regressions for argument normalization. These use the +actual source compiler, both reference evaluators and the native executor. -/ + +open Aiur Aiur.Source + +namespace Tests.Aiur.Hoisting + +private def write (n : Nat) (ret : Term) : Term := + .ioWrite (.field 0) (.array #[.field (G.ofNat n)]) ret + +private def program (body : Term) (output : Typ) + (safe : sigPointerFree [] output = true) : Toplevel := + ⟨#[], #[], #[Function.monoEntry (Global.init "test") [] output body safe], false⟩ + +private def returningHelper (early : Bool) : Toplevel := + let x : Term := .var (.str "x") + let body := if early then + .let (.var (.str "y")) + (.match x [(.field 0, .ret (.field 7)), (.wildcard, .field 4)]) + (.add (.var (.str "y")) (.field 1)) + else .ret (.add x (.field 1)) + let helper := Function.monoNonEntry (Global.init "helper") [(.str "x", .field)] .field body + let main := program (.add (.app (Global.init "helper") [.field 0] .inlined) (.field 3)) + .field (by simp [sigPointerFree, Typ.hasPointer]) + { main with functions := #[helper] ++ main.functions } + +def fixtures : Array (String × Toplevel × Array Aiur.G × Array Aiur.G) := #[ + ("set-argument-order", program + (.set (.let .wildcard (write 1 .unit) (.array #[.field 5])) 0 + (.let .wildcard (write 2 .unit) (.field 9))) (.array .field 1) + (by simp [sigPointerFree, Typ.hasPointer]), #[9], #[2, 1]), + ("operand-core-before-next-frames", program + (.add (write 1 (.field 3)) (.let .wildcard (write 2 .unit) (.field 4))) .field + (by simp [sigPointerFree, Typ.hasPointer]), #[7], #[1, 2]), + ("write-before-continuation", program + (write 1 (.let .wildcard (write 2 .unit) (.field 3))) .field + (by simp [sigPointerFree, Typ.hasPointer]), #[3], #[1, 2]), + ("tuple-element-order", program + (.tuple #[write 1 (.field 3), .let .wildcard (write 2 .unit) (.field 4)]) + (.tuple #[.field, .field]) (by simp [sigPointerFree, Typ.hasPointer]), #[3, 4], #[1, 2]), + ("array-element-order", program + (.array #[write 1 (.field 3), .let .wildcard (write 2 .unit) (.field 4)]) + (.array .field 2) (by simp [sigPointerFree, Typ.hasPointer]), #[3, 4], #[1, 2]), + ("lexical-binding-scope", program + (.let (.var (.str "x")) (.field 10) + (.add (.let (.var (.str "x")) (.field 3) (.var (.str "x"))) (.var (.str "x")))) + .field (by simp [sigPointerFree, Typ.hasPointer]), #[13], #[]), + ("inline-tail-return-boundary", returningHelper false, #[4], #[]), + ("inline-early-return-boundary", returningHelper true, #[10], #[]), + ("debug-value-before-continuation", program + (.debug "debug-value-before-continuation" (some (write 1 (.field 4))) + (write 2 (.field 3))) .field (by simp [sigPointerFree, Typ.hasPointer]), + #[3], #[1, 2])] + +def main : IO Unit := do + let mut failures := 0 + for (label, source, expected, effects) in fixtures do + let decls ← IO.ofExcept (source.mkDecls.mapError toString) + let (value, io) ← IO.ofExcept + ((Source.Eval.runFunction decls (Global.init "test") [] default 100).mapError reprStr) + unless flattenValue decls (fun _ => none) value == expected && io.data.getD 0 #[] == effects do + throw (IO.userError s!"invalid source fixture: {label}") + let (interpreted, state) := Aiur.runFunction decls (Global.init "test") [] default + let interpreted ← IO.ofExcept interpreted + unless flattenValue decls (fun _ => none) interpreted == expected && state.ioBuffer == io do + throw (IO.userError s!"source interpreters disagree: {label}") + match source.compile with + | .error error => + failures := failures + 1 + IO.println s!"FAIL {label}: compilation: {error}" + | .ok compiled => + let some index := compiled.getFuncIdx `test + | throw (IO.userError s!"missing function: {label}") + let reference := (Bytecode.Eval.runFunction compiled.bytecode index #[] default 100).mapError reprStr + let native := (compiled.bytecode.execute index #[] default).map fun (output, state, _) => (output, state) + for (engine, result) in #[("bytecode reference", reference), ("native", native)] do + match result with + | .error error => + failures := failures + 1 + IO.println s!"FAIL {label}: {engine}: {error}" + | .ok (output, actualIo) => + if output == expected && actualIo == io then IO.println s!"PASS {label}: {engine}" + else + failures := failures + 1 + IO.println s!"FAIL {label}: {engine}: output {output}, effects {actualIo.data.getD 0 #[]}; expected {expected}, {effects}" + unless failures == 0 do throw (IO.userError s!"{failures} hoisting regressions") + +end Tests.Aiur.Hoisting + +def main := Tests.Aiur.Hoisting.main diff --git a/Tests/Aiur/Interpolation.lean b/Tests/Aiur/Interpolation.lean new file mode 100644 index 000000000..81320cd23 --- /dev/null +++ b/Tests/Aiur/Interpolation.lean @@ -0,0 +1,123 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Interpolation +import Tests.Aiur.EmissionReader + +/-! Replay actual native FRI row and matrix folds against the checked +interpolator, using known coefficient polynomials and arbitrary matrix rows. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) + +namespace AiurTests.Interpolation + +private def readExtension : Reader Extension := return ⟨← readField, ← readField⟩ + +private def readDomain (bits : Nat) : Reader Domain.Subgroup := do + let some domain := Domain.ofLogSize bits | throw "invalid interpolation domain" + return domain + +private def sample (seed : Nat) : Extension := ⟨G.ofNat (seed * 67 + 3), G.ofNat (seed * 13 + 1)⟩ + +private def coefficients (arity variant : Nat) : List Extension := + match variant with + | 0 => [] + | 1 => [sample 1] + | 2 => (List.range arity).map (fun index => if index + 1 == arity then 1 else 0) + | _ => (List.range arity).map (fun index => sample (index + 17)) + +private def checkValues (expected : List Extension) : Reader Unit := do + unless (← readCount expected.length) == expected.length do throw "native interpolation input length differs" + unless (← readList expected.length readExtension) == expected do throw "native interpolation inputs differ" + +private def readCorpus : Reader (List Nat) := do + let header := "Aiur FRI interpolation v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "interpolation version differs" + let mut rows := 0 + let mut evaluations := 0 + for parentBits in [:33] do + let parent ← readDomain parentBits + for arityBits in [:min parentBits 6 + 1] do + let arity ← readDomain arityBits + let size := Domain.size arity + let mask := 2^(parentBits - arityBits) - 1 + let indices := [0, mask / 2, mask] |>.mergeSort (· ≤ ·) |>.eraseDups + unless (← readCount 3) == indices.length do throw "interpolation index inventory differs" + for index in indices do + unless (← readNat) == index do throw "native interpolation index differs" + let nodes := (Polynomial.foldingNodes parent arity index).map Extension.ofBase + let scale ← readField + unless scale == NativeAIR.Interpolation.foldScale parent arity index do throw "native interpolation normalizer differs" + for variant in [:4] do + let polynomial := coefficients size variant + let values := nodes.map (fun node => Quotient.horner node polynomial) + checkValues polynomial + checkValues values + let samples := NativeAIR.Interpolation.foldSamples parent arity index values + if arityBits ≤ 3 then + let candidate := NativeAIR.Interpolation.coefficients samples (Extension.ofBase scale) + unless candidate.length ≤ size && (Polynomial.sub candidate polynomial).all (· == 0) do + throw "constructed interpolating coefficients differ from the native source polynomial" + let vanishing := Polynomial.fromRoots nodes + for node in nodes do + unless (node * Extension.ofBase scale) * Quotient.horner node (Polynomial.divide node vanishing) == 1 do + throw "interpolation diagonal weight differs" + let points := [0, Extension.ofBase 7, sample 41, + Extension.ofBase (FriDomain.foldNode parent arity index 0), + Extension.ofBase (FriDomain.foldNode parent arity index (size - 1))] + for point in points do + unless (← readExtension) == point do throw "native interpolation challenge differs" + let result ← readExtension + unless NativeAIR.Interpolation.foldRow parent arity index values point == some result && + Quotient.horner point polynomial == result do throw "native FRI row interpolation differs" + evaluations := evaluations + 1 + rows := rows + 1 + let mut matrices := 0 + let mut matrixRows := 0 + for parentBits in [1:10] do + let parent ← readDomain parentBits + for arityBits in [1:min parentBits 6 + 1] do + let arity ← readDomain arityBits + let size := Domain.size arity + let height := 2^(parentBits - arityBits) + let data := (List.range (2^parentBits)).map (fun index => sample (index + parentBits * 19)) + for point in [0, sample 41, 1] do + unless (← readExtension) == point do throw "native matrix folding challenge differs" + checkValues data + unless (← readCount height) == height do throw "native folded matrix height differs" + let folded ← readList height readExtension + unless folded.length == height do throw "native folded matrix height differs" + for index in [:height] do + let row := (data.drop (index * size)).take size + unless NativeAIR.Interpolation.foldRow parent arity index row point == folded[index]? do + throw "native FRI matrix fold differs" + matrixRows := matrixRows + 1 + matrices := matrices + 1 + let counts := [rows, evaluations, matrices, matrixRows] + unless counts == [2436, 12180, 117, 3006] do throw "incomplete interpolation corpus" + unless (← readList 4 readNat) == counts do throw "interpolation coverage totals differ" + let empty ← readDomain 0 + let binary ← readDomain 1 + unless NativeAIR.Interpolation.evaluate 1 0 [] == some 0 && + NativeAIR.Interpolation.foldRow empty binary 0 [0, 1] 0 == none && + NativeAIR.Interpolation.foldRow binary empty 2 [1] 0 == none && + NativeAIR.Interpolation.foldRow binary binary 0 [1] 0 == none && + NativeAIR.Interpolation.foldRow binary binary 0 [1, 2, 3] 0 == none do + throw "interpolation helper boundaries differ" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "interpolation snapshot has trailing bytes" + return counts + +end AiurTests.Interpolation + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.Interpolation.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok (counts, _) => IO.println s!"Native FRI interpolation rows, challenge evaluations, matrices and matrix rows match: {counts}" + | _ => throw (IO.userError "expected native FRI interpolation snapshot") diff --git a/Tests/Aiur/KeyCodec.lean b/Tests/Aiur/KeyCodec.lean new file mode 100644 index 000000000..5b2b69077 --- /dev/null +++ b/Tests/Aiur/KeyCodec.lean @@ -0,0 +1,74 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.KeyCodec +import Tests.Aiur.EmissionReader + +/-! Native v5 keys, canonicalization, derived metadata and malformed bytes. -/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader + +namespace AiurTests.KeyBytes + +private def readBytes : Reader ByteArray := do takeBytes (← readCount 1048576) + +private def readCorpus : Reader (Nat × Nat × Nat × Nat) := do + let header := "Aiur key codec v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "key codec snapshot version differs" + let count ← readCount 100000 + let mut accepted := 0 + let mut noncanonical := 0 + let mut circuits := 0 + for index in [:count] do + let bytes ← readBytes + let expected ← readBool + let decoded := KeyCodec.decode bytes + unless decoded.isSome == expected do throw s!"key decoder decision differs at case {index}" + if expected then + let some key := decoded | throw "accepted key missing" + accepted := accepted + 1 + let canonical ← readBytes + unless KeyCodec.encode key == canonical do throw s!"key canonical bytes differ at case {index}" + unless KeyCodec.decode canonical == some key do throw s!"key round trip differs at case {index}" + unless (KeyCodec.decodeCanonical bytes).isSome == (bytes == canonical) do + throw s!"canonical key decision differs at case {index}" + if bytes != canonical then noncanonical := noncanonical + 1 + unless (← readCount) == key.circuits.length do throw "key circuit count differs" + unless key.preprocessedIndices.length == key.circuits.length do throw "key index count differs" + for circuit in key.circuits do + circuits := circuits + 1 + let some degrees := KeyCodec.nodeDegreesFrom circuit.graph.nodes #[] + | throw "accepted key has undefined node degrees" + let some roots := circuit.graph.zeros.mapM (fun root => degrees[root]?) + | throw "accepted key has undefined root degrees" + let metadata := [circuit.mainWidth, circuit.preprocessedWidth, circuit.preprocessedHeight, + circuit.maxConstraintDegree, circuit.lookupGroupSize, circuit.widths.stage2, circuit.widths.publics, + circuit.constraintCount, circuit.graph.lookupPrefix, roots.foldr max 0] + unless (← readList 10 readNat) == metadata do throw s!"derived key metadata differs at case {index}" + unless (← readList (← readCount 65536) readNat) == degrees.toList do + throw s!"key node degrees differ at case {index}" + unless circuit.computedDegree == some circuit.maxConstraintDegree do + throw "accepted key maximum degree differs" + unless (checkedGraphPrefix circuit.widths circuit.graph).isSome do + throw "accepted key has invalid graph reads" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "key codec snapshot has trailing bytes" + return (count, accepted, noncanonical, circuits) + +def run (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok ((count, accepted, noncanonical, circuits), _) => + unless count == 4536 && accepted == 509 && noncanonical == 22 && circuits == 517 do + throw (IO.userError "incomplete key codec corpus") + IO.println s!"key codec: {count} native/Lean cases, {accepted} accepted, {noncanonical} noncanonical, {circuits} circuits match" + +end AiurTests.KeyBytes + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.KeyBytes.run path + | _ => throw (IO.userError "expected native key codec snapshot") diff --git a/Tests/Aiur/LogUp.lean b/Tests/Aiur/LogUp.lean new file mode 100644 index 000000000..1e147f32b --- /dev/null +++ b/Tests/Aiur/LogUp.lean @@ -0,0 +1,150 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LogUpAccumulator +import Tests.Aiur.EmissionReader + +/-! Comparison with direct native logUp, its symbolic schoolbook reference, +and native stage-2 traces. The corpus includes every group size, empty groups, +uneven tails, variable argument widths, poles and arbitrary extension-valued +coordinates. Malformed reads are tested only through the checked Lean model. -/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) +open LogUp (Coordinates) + +namespace AiurTests.LogUp + +private def counts : List Nat := + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 23, 24, 25, 31, 32, 33, 63, 64, 65] + +private def readExtension : Reader Extension := do return ⟨← readField, ← readField⟩ + +private def readVector (readValue : Reader W) : Reader (Array W) := do + return (← readList (← readCount 4096) readValue).toArray + +private def readLookups : Reader (List Lookup) := do + readList (← readCount) do + return ⟨← readNat, ← readList (← readCount) readNat⟩ + +private def readDirectCases {W : Type} [Lean.Grind.CommRing W] [DecidableEq W] + (readValue : Reader W) : Reader Unit := do + unless (← readCount 10000) == 2376 do throw "incomplete direct logUp cases" + for count in counts do + for groupSize in [:9] do + for seed in [:12] do + unless (← readNat) == count && (← readNat) == groupSize && (← readNat) == seed do + throw "direct logUp case order differs" + let lookups ← readLookups + unless lookups.length == count do throw "direct logUp lookup count differs" + let nodes ← readVector readValue + let current ← readVector readValue + let next ← readVector readValue + let publics ← readVector readValue + let delta ← readVector readValue + let isLast ← readValue + let expected := (← readVector readValue).toList + let evaluate := fun lookups nodes current next publics delta size => + NativeAIR.LogUp.constraintValues lookups nodes current next publics delta isLast size + unless evaluate lookups nodes current next publics delta groupSize == some expected do + throw s!"native logUp differs: {count} lookups, group {groupSize}, assignment {seed}" + unless expected.length == 2 * NativeAIR.LogUp.groupCount groupSize count do throw "logUp coordinate count differs" + unless evaluate lookups nodes current.pop next publics delta groupSize == none do throw "short current row accepted" + unless evaluate lookups nodes current (next.extract 0 1) publics delta groupSize == none do throw "short next row accepted" + unless evaluate lookups nodes current next (publics.extract 0 3) delta groupSize == none do throw "short public input accepted" + unless evaluate lookups nodes current next publics (delta.extract 0 1) groupSize == none do throw "short delta accepted" + unless evaluate (lookups ++ [⟨nodes.size, []⟩]) nodes current next publics delta groupSize == none do + throw "out-of-range multiplicity accepted" + unless evaluate (lookups ++ [⟨0, [nodes.size]⟩]) nodes current next publics delta groupSize == none do + throw "out-of-range argument accepted" + for invalid in [9, 256, 2^64 - 1] do + unless evaluate lookups nodes current next publics delta invalid == none do throw "oversized logUp group accepted" + +private def readDirect : Reader Unit := do + let header := "Aiur grouped logup v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "logUp snapshot version differs" + readDirectCases readField + readDirectCases readExtension + +private def baseCoordinates (values : Array Extension) : Array G := + (Coordinates.flatten (values.toList.map Coordinates.fromExtension)).toArray + +private def readStages : Reader Unit := do + let header := "Aiur grouped logup stages v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "stage-2 snapshot version differs" + unless (← readNat) == 27 do throw "incomplete stage-2 batches" + let mut totalRows := 0 + for groupSize in [:9] do + for seed in [:3] do + unless (← readNat) == groupSize && (← readNat) == seed do throw "stage-2 batch order differs" + let beta ← readExtension + let gamma ← readExtension + let mut entering ← readExtension + unless (← readNat) == 5 do throw "incomplete stage-2 circuits" + for (expectedHeight, expectedLookups) in [(1, 0), (2, 1), (4, 9), (8, 17), (4, 25)] do + let height ← readNat + let count ← readNat + let width ← readNat + unless height == expectedHeight && count == expectedLookups && + width == NativeAIR.LogUp.groupCount groupSize count do throw "stage-2 circuit shape differs" + let matrix ← readVector readExtension + unless matrix.size == height * width do throw "stage-2 matrix length differs" + let leaving ← readExtension + let normalizer ← readField + unless normalizer != 0 do throw "zero last-row normalizer" + let delta := (Coordinates.fromExtension (leaving - entering)).scale normalizer.inverse + let publics := baseCoordinates #[beta, gamma, entering, leaving] + let mut running : Extension := 0 + for row in [:height] do + let lookups ← readList (← readCount) do return (← readField, (← readVector readField).toList) + unless lookups.length == count do throw "stage-2 row lookup count differs" + let native := (← readVector readField).toList + let betaPair := Coordinates.fromExtension beta + let gammaPair := Coordinates.fromExtension gamma + let entries := NativeAIR.LogUp.fieldEntries (NativeAIR.LogUp.compress betaPair gammaPair lookups) + unless entries.all (fun entry => entry.2 != 0) do throw "unexpected stage-2 pole" + let rowFraction := NativeAIR.LogUp.lookupFractions betaPair gammaPair lookups + let before := running + for group in [:width] do + unless matrix[row * width + group]? == some running do throw "native partial accumulator differs" + let chunk := NativeAIR.LogUp.chunk groupSize group lookups + running := running + NativeAIR.LogUp.lookupFractions betaPair gammaPair chunk + unless running == before + rowFraction do throw "grouping changes the row fraction" + let current := baseCoordinates (matrix.extract (row * width) ((row + 1) * width)) + let nextIndex := (row + 1) % height + let next := baseCoordinates (matrix.extract (nextIndex * width) ((nextIndex + 1) * width)) + let isLast := if row + 1 == height then normalizer else 0 + let evaluated := NativeAIR.LogUp.equations lookups current next publics + #[delta.c0, delta.c1] isLast groupSize + unless evaluated.map Coordinates.flatten == some native do throw "native stage-2 equations differ" + unless native.all (· == 0) do throw "native stage-2 equations do not vanish" + let some first := Coordinates.read current 0 | throw "missing stage-2 first accumulator" + let some following := Coordinates.read next 0 | throw "missing stage-2 next accumulator" + unless following.toExtension - first.toExtension + (delta.scale isLast).toExtension == rowFraction do + throw "stage-2 row does not telescope" + totalRows := totalRows + 1 + unless entering + running == leaving do throw "native circuit accumulator differs" + entering := leaving + unless totalRows == 513 do throw "incomplete stage-2 row corpus" + +private def runReader (reader : Reader Unit) (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match reader.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok (_, (_, cursor)) => + unless cursor == bytes.size do throw (IO.userError "logUp snapshot has trailing bytes") + +def run (direct stages : System.FilePath) : IO Unit := do + runReader readDirect direct + IO.println "logUp: 4752 native direct/reference cases and 42768 rejected malformed inputs match" + runReader readStages stages + IO.println "logUp stages: 27 batches, 135 circuits and 513 complete rows match native accumulators and equations" + +end AiurTests.LogUp + +def main (args : List String) : IO Unit := do + match args with + | [direct, stages] => AiurTests.LogUp.run direct stages + | _ => throw (IO.userError "expected native direct logUp and stage-2 snapshots") diff --git a/Tests/Aiur/LookupBudget.lean b/Tests/Aiur/LookupBudget.lean new file mode 100644 index 000000000..56a470542 --- /dev/null +++ b/Tests/Aiur/LookupBudget.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.LookupBudget + +/-! Native/Lean guard comparison across all u8 exponents, machine/field +boundaries, active-position indexing and malformed metadata lengths. -/ + +open Aiur + +namespace AiurTests.LookupBudget + +private def appendResult (bytes : ByteArray) (result : Option Nat) : ByteArray := Id.run do + let mut bytes := bytes.push (if result.isSome then 1 else 0) + let value := result.getD 0 + for index in [:8] do + bytes := bytes.push ((value >>> (8 * index)) % 256).toUInt8 + return bytes + +private def expected : ByteArray := Id.run do + let mut out := "Aiur lookup budget v1\n".toUTF8 + let p := gSize.toNat + let cases := [0, 1, 2, 3, 4, 255, 65536, 2 ^ 31, 2 ^ 32, 2 ^ 32 - 1, + p / 2 - 1, p - 3, p - 2, p - 1, p, 2 ^ 64 - 1] + for slots in cases do + for degree in [:256] do + out := appendResult out (lookupQueryBound [slots] [true] [degree]) + out := appendResult out (lookupQueryBound [2 ^ 64 - 1, slots, 2 ^ 64 - 1] + [false, true, false] [degree]) + out := appendResult out (lookupQueryBound [slots, 3] [true, true] [degree, 31]) + out := appendResult out (lookupQueryBound [3, slots] [true, true] [31, degree]) + let slots := [2, 7, 0, 13] + for slotCount in [:5] do + for activeCount in [:5] do + for mask in [:2 ^ activeCount] do + let active := (List.range activeCount).map fun bit => mask &&& (2 ^ bit) != 0 + for degreeCount in [:6] do + for degree in [0, 1, 31, 63, 64, 255] do + out := appendResult out (lookupQueryBound (slots.take slotCount) active + (List.replicate degreeCount degree)) + return out + +def run (path : System.FilePath) : IO Unit := do + let native ← IO.FS.readBinFile path + unless expected.size == "Aiur lookup budget v1\n".toUTF8.size + 21964 * 9 do + throw (IO.userError "incomplete lookup-budget corpus") + unless native.size == expected.size do + throw (IO.userError s!"lookup-budget snapshot size differs: {native.size} / {expected.size}") + for i in [:expected.size] do + unless native[i]! == expected[i]! do + throw (IO.userError s!"lookup-budget mismatch at byte {i}: {native[i]!} / {expected[i]!}") + IO.println "lookup budget: 21,964 native/Lean boundary, alignment and active-height checks match" + +end AiurTests.LookupBudget + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.LookupBudget.run path + | _ => throw (IO.userError "expected native lookup-budget snapshot path") diff --git a/Tests/Aiur/LookupShapes.lean b/Tests/Aiur/LookupShapes.lean new file mode 100644 index 000000000..861243632 --- /dev/null +++ b/Tests/Aiur/LookupShapes.lean @@ -0,0 +1,95 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.LookupShapes + +/-! Native parity for the structural validators. The corpus deliberately +varies shapes independently of value indices and layouts. These programs +are used only by the validators, never by an evaluator or AIR emitter. -/ + +namespace AiurTests.LookupShapes + +open Aiur Aiur.Bytecode + +def returning (size : Nat) : Block := ⟨#[], .return 0 (Array.replicate size 0)⟩ + +def yielding (size : Nat) : Block := ⟨#[], .yield 0 (Array.replicate size 0)⟩ + +def matched (arm fallback : Option Block) : Block := + ⟨#[], .match 0 (match arm with | none => #[] | some block => #[(0, block)]) fallback⟩ + +def continued (arm continuation : Block) : Block := + ⟨#[], .matchContinue 0 #[(0, arm)] (some (yielding 2)) 2 0 0 continuation⟩ + +def body : Nat → Block + | 0 => returning 0 + | 1 => returning 1 + | 2 => returning 2 + | 3 => yielding 0 + | 4 => yielding 1 + | 5 => matched (some (returning 1)) (some (returning 1)) + | 6 => matched (some (returning 0)) (some (returning 1)) + | 7 => matched (some (returning 1)) none + | 8 => matched none none + | 9 => continued (yielding 2) (returning 1) + | 10 => continued (returning 1) (returning 1) + | 11 => continued (returning 0) (returning 1) + | 12 => continued (yielding 1) (returning 1) + | 13 => continued (yielding 2) (yielding 0) + | 14 => continued (continued (yielding 2) (yielding 2)) (returning 1) + | 15 => continued (continued (yielding 2) (yielding 1)) (returning 1) + | _ => matched (some (continued (returning 1) (returning 1))) (some (returning 1)) + +def function (body : Block) (inputs : Nat) (entry constrained : Bool) : Function := + ⟨body, ⟨inputs, 1, 7, 4⟩, entry, constrained⟩ + +def expected : ByteArray := Id.run do + let mut out := "Aiur lookup shapes v2\n".toUTF8 + for tag in [:17] do + for size in [:4] do + out := out.push (if (body tag).returnsHaveSize size then 1 else 0) + for tag in [:17] do + for calleeInputs in [:4] do + for callerInputs in [:4] do + for outputs in [:4] do + for advice in [false, true] do + for constrained in [false, true] do + let caller := function + ⟨#[.call 1 (Array.replicate callerInputs 0) outputs advice], .return 0 #[]⟩ + 3 true true + let callee := function (body tag) calleeInputs false constrained + let program : Toplevel := ⟨#[caller, callee], #[], #[], #[]⟩ + out := out.push (if program.validateLookupShapes then 1 else 0) + for tag in [:17] do + for inputs in [:4] do + for entry in [false, true] do + for constrained in [false, true] do + let program : Toplevel := ⟨#[function (body tag) inputs entry constrained], #[], #[], #[]⟩ + for channel in [:3] do + for functionIndex in [0, 1, 99] do + for arguments in [:7] do + let claim := #[G.ofNat channel, G.ofNat functionIndex] ++ Array.replicate arguments 0 + -- The native constructor validates the program before + -- returning the cached shapes used by public verification. + out := out.push (if program.validateLookupShapes && program.validClaimShape claim then 1 else 0) + return out + +def run (path : System.FilePath) : IO Unit := do + let native ← IO.FS.readBinFile path + unless expected.size == "Aiur lookup shapes v2\n".toUTF8.size + 21556 do + throw (IO.userError "incomplete lookup-shape corpus") + unless native.size == expected.size do + throw (IO.userError s!"lookup-shape snapshot size differs: {native.size} / {expected.size}") + for i in [:expected.size] do + unless native[i]! == expected[i]! do + throw (IO.userError s!"lookup-shape mismatch at byte {i}: {native[i]!} / {expected[i]!}") + IO.println "lookup shapes: 21,556 native/Lean return, call, continuation and public-claim checks match" + +end AiurTests.LookupShapes + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.LookupShapes.run path + | _ => throw (IO.userError "expected native lookup-shape snapshot path") diff --git a/Tests/Aiur/MemoryRows.lean b/Tests/Aiur/MemoryRows.lean new file mode 100644 index 000000000..3af1fd66e --- /dev/null +++ b/Tests/Aiur/MemoryRows.lean @@ -0,0 +1,72 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.MemoryColumns + +open Aiur Aiur.AIR + +namespace AiurTests.MemoryRows + +private def appendNat (out : ByteArray) (value : Nat) : ByteArray := Id.run do + let mut out := out + for i in [:8] do + out := out.push ((value >>> (8 * i)) % 256).toUInt8 + return out + +private def appendValues (out : ByteArray) (values : List G) : ByteArray := + values.foldl (fun out value => appendNat out value.n) (appendNat out values.length) + +private def row (height pattern index width : Nat) : MemoryColumns width := fun column => + let choices : List G := [0, 1, 0 - 1, 255, 256, G.ofNat (2^32), G.ofNat (2^48 - 1), 17] + let selector : G := match pattern % 8 with + | 0 => 0 + | 1 => 1 + | 2 => if index < (height + 1) / 2 then 1 else 0 + | 3 => if index + 1 == height then 1 else 0 + | 4 => if index % 2 == 0 then 1 else 0 + | 5 => 2 + | 6 => 0 - 1 + | _ => choices[(index + pattern) % 8]?.getD 0 + if pattern == 0 then 0 + else match column.val with + | 0 => if pattern < 8 && selector == 0 then 0 else choices[(3 * index + pattern) % 8]?.getD 0 + | 1 => selector + | 2 => if pattern < 16 then (0 - 1) + G.ofNat index else G.ofNat (255 + 2 * index) + | column => choices[(5 * column + 3 * index + pattern) % 8]?.getD 0 + +private def expected : ByteArray × Nat := Id.run do + let mut out := appendNat "Aiur memory rows v1\n".toUTF8 25 + let mut checked := 0 + for width in [0, 1, 2, 4, 8] do + for height in [0, 1, 2, 4, 8] do + for value in [width, height, 3 + width, 1, 24] do + out := appendNat out value + for pattern in [:24] do + let matrix := fun index : Fin height => row height pattern index.val width + for index in List.finRange height do + out := appendValues out (memoryMatrixEquations width height matrix index) + let (multiplicity, message) := memoryColumnLookup width (matrix index) + out := appendNat out multiplicity.n + out := appendValues out message + checked := checked + 1 + return (out, checked) + +def run (path : System.FilePath) : IO Unit := do + let native ← IO.FS.readBinFile path + let (expected, checked) := expected + unless checked == 1800 do throw (IO.userError "incomplete memory-row corpus") + unless native.size == expected.size do + throw (IO.userError s!"memory-row snapshot size differs: {native.size} / {expected.size}") + for i in [:expected.size] do + unless native[i]! == expected[i]! do + throw (IO.userError s!"memory-row mismatch at byte {i}: {native[i]!} / {expected[i]!}") + IO.println s!"memory rows: {checked} native/Lean assignments across 25 width/height pairs match" + +end AiurTests.MemoryRows + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.MemoryRows.run path + | _ => throw (IO.userError "expected native memory-row snapshot path") diff --git a/Tests/Aiur/Merkle.lean b/Tests/Aiur/Merkle.lean new file mode 100644 index 000000000..f91e44dd5 --- /dev/null +++ b/Tests/Aiur/Merkle.lean @@ -0,0 +1,82 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Merkle +import Tests.Aiur.EmissionReader + +/-! Compare binary path replay with the actual pinned MMCS verifier, +including the complete sequence of byte inputs and native BLAKE3 outputs. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.Merkle AiurTests.EmissionReader + +namespace AiurTests.Merkle + +private def readDigest : Reader Digest := do + let bytes ← takeBytes 32 + if length : bytes.data.size = 32 then return ⟨bytes.data, length⟩ + else throw "incomplete Merkle digest" + +private def readDigests : Reader (List Digest) := do + readList (← readCount) readDigest + +private def readCall : Reader (List UInt8 × Digest) := do + let input ← takeBytes (← readCount 100000) + return (input.data.toList, ← readDigest) + +private def readCorpus : Reader Unit := do + let header := "Aiur Merkle paths v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "Merkle path snapshot version differs" + for count in [8913, 1802, 1161, 3941, 16456] do + unless (← readNat) == count do throw "incomplete native Merkle path corpus" + let mut accepted := 0 + let mut omitted := 0 + let mut unhashed := 0 + let mut calls := 0 + for case in [:8913] do + let dimensions ← readList (← readCount) do + return Dimensions.mk (← readCount) (← readCount 32) + let capHeight ← readCount + let index ← readCount + let rows ← readList (← readCount) readValues + let proof ← readDigests + let cap ← readDigests + let native ← readBool + let coverage ← readBool + let hashes ← readList (← readCount) readCall + unless covered dimensions capHeight == coverage do throw s!"Merkle coverage differs at {case}" + unless verify Blake3.digest dimensions capHeight index cap rows proof == native do + throw s!"Merkle decision differs at {case}" + unless verifyCovered Blake3.digest dimensions capHeight index cap rows proof == (native && coverage) do + throw s!"covered Merkle decision differs at {case}" + match replay Blake3.digest dimensions capHeight index rows proof with + | none => + unless hashes.isEmpty do throw s!"native hashed a structurally rejected path at {case}" + unhashed := unhashed + 1 + | some result => + unless result.hashing.inputs == hashes.map Prod.fst do + throw s!"Merkle hash input sequence differs at {case}" + unless result.logHeight == min capHeight (maxHeight dimensions) && + result.index == index / 2^proof.length do throw "Merkle final position differs" + unless hashes.getLast?.map Prod.snd == some result.hashing.digest do + throw s!"Merkle final digest differs at {case}" + for (input, output) in hashes do + unless Blake3.digest input == output do throw s!"native Merkle hash output differs at {case}" + if native then accepted := accepted + 1 + if native && !coverage then omitted := omitted + 1 + calls := calls + hashes.length + unless accepted == 1802 && omitted == 1161 && unhashed == 3941 && calls == 16456 do + throw "Merkle path coverage totals differ" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "Merkle path snapshot has trailing bytes" + +end AiurTests.Merkle + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.Merkle.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok _ => IO.println "Merkle paths: 8913 native/Lean decisions and 16456 hash calls match" + | _ => throw (IO.userError "expected native Merkle path snapshot") diff --git a/Tests/Aiur/MerkleCap.lean b/Tests/Aiur/MerkleCap.lean new file mode 100644 index 000000000..b4ff2e890 --- /dev/null +++ b/Tests/Aiur/MerkleCap.lean @@ -0,0 +1,38 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.MerkleCap +import Tests.Aiur.EmissionReader + +/-! Every native degree byte, mixed/uniform/empty batches and machine +parameter boundaries for the binary Merkle cap coverage guard. -/ + +open Aiur.NativeAIR AiurTests.EmissionReader + +private def readCorpus : Reader Unit := do + let header := "Aiur Merkle caps v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "Merkle cap snapshot version differs" + let parameters : List Nat := [0, 1, 2, 3, 8, 16, 31, 32, 63, 64, 255, 256, 65535, 2^64 - 256, 2^64 - 1] + let mut total := 0 + for blowup in parameters do + for cap in parameters do + unless (← readBool) == MerkleCap.coverage blowup cap [] do throw "empty cap geometry differs" + total := total + 1 + for degree in [:256] do + for degrees in [[degree], [degree, 0], [degree, 8, 16], [degree, degree], [255, degree]] do + unless (← readBool) == MerkleCap.coverage blowup cap degrees do + throw s!"Merkle cap coverage differs: blowup {blowup}, cap {cap}, degrees {degrees}" + total := total + 1 + unless total == 288225 do throw "incomplete Merkle cap cases" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "Merkle cap snapshot has trailing bytes" + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok _ => IO.println "Merkle caps: 288225 native/Lean degree and parameter cases match" + | _ => throw (IO.userError "expected native Merkle cap snapshot") diff --git a/Tests/Aiur/OperationExpressions.lean b/Tests/Aiur/OperationExpressions.lean new file mode 100644 index 000000000..18a9934cd --- /dev/null +++ b/Tests/Aiur/OperationExpressions.lean @@ -0,0 +1,138 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Tests.Aiur.EmissionReader +import Ix.Aiur.Proofs.EmissionAllocation + +/-! Compare complete native operation and sequence expression trees, including +metadata, cursor movement, equations, and superposed physical lookup slots. +The corpus supplies the actual native operations, inputs, and assignments. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.OpEmitter Aiur.NativeAIR.Compiler + +namespace AiurTests.OperationExpressions + +open AiurTests.EmissionReader + +private def assignment (row : Array G) : Values G := + ⟨(fun source _ => match source with | .main => row | _ => #[]), #[], 1, 0, 1⟩ + +private def callData (calls : List (Bytecode.AIR.Call × (Fin 6 → G))) := + calls.map fun (call, gap) => (call, List.ofFn gap) + +private def sameEmission (left right : AIR.OpsEmission) : Bool := + left.values == right.values && left.column == right.column && left.equations == right.equations && + left.queries == right.queries && callData left.calls == callData right.calls + +private def readSequence (rows : List (Array G)) (label : String) : Reader (List LookupEmitter.QueryExpr × Nat) := do + let first ← readNat + let lookup ← readNat + let selector ← readExpr 64 + let rank ← readExpr 64 + let inputs ← readMap + let ops ← readList (← readCount) readOp + unless inputs.all (·.expr.noConstantNegs) do throw s!"invalid incoming normal form: {label}" + let some emitted := emitOps selector rank ops inputs first + | throw s!"symbolic operation sequence rejected native inputs: {label}" + let column ← readNat + let lookupEnd ← readNat + let nativeMap ← readMap + let equations ← readList (← readCount) (readExpr 64) + unless column == emitted.column && lookupEnd == lookup + emitted.queries.length do + throw s!"native operation cursor differs: {label}" + unless nativeMap == emitted.values do + throw s!"native output expression or degree differs: {label}; ops {repr ops}" + unless equations == emitted.equations do + throw s!"native operation constraint trees differ: {label}; ops {repr ops}" + unless emitted.values.all (·.expr.noConstantNegs) do + throw s!"native output lost the negation invariant: {label}" + let validDegrees := inputs.all fun row => row.degree != 0 || row.expr.isConstant + if validDegrees then + let initial : Concrete.Bytecode.LayoutMState := + ⟨{ inputSize := inputs.size, selectors := 0, auxiliaries := first, lookups := lookup }, + .empty, rowDegrees inputs, #[]⟩ + let layout := ((ops.toArray.forM Concrete.Bytecode.opLayout).run initial).2 + unless rowDegrees nativeMap == layout.degrees && column == layout.functionLayout.auxiliaries do + throw s!"native operation degrees or column allocation differs from compiler: {label}" + unless emitted.values.all (fun row => row.degree != 0 || row.expr.isConstant) do + throw s!"native operation lost the degree-zero constant invariant: {label}" + for (row, seed) in rows.zipIdx do + let expected ← readList nativeMap.size do return (← readField, ← readBool) + let equationValues ← readList equations.length readField + let values := assignment row + let some evaluated := emitted.eval values | throw s!"symbolic evaluation failed: {label}, {seed}" + unless evaluated.values.toList.map (fun value => (value.value, value.constant)) == expected && + evaluated.equations == equationValues do + throw s!"native operation values differ: {label}, assignment {seed}" + let some inputValues := evalRows values inputs | throw "undefined native input expressions" + let some s := evalExpr values selector | throw "undefined native selector" + let some r := evalExpr values rank | throw "undefined native rank" + let some valued := AIR.emitOps (fun index => row[index]?.getD 0) s r ops inputValues first + | throw s!"valued operation sequence rejected symbolic inputs: {label}" + unless sameEmission evaluated valued do throw s!"symbolic/valued sequence differs: {label}, {seed}" + return (LookupEmitter.queryParts lookup selector emitted.queries, if validDegrees then 1 else 0) + +private def readReport (rows : List (Array G)) (index : Nat) : Reader (Nat × Nat × Nat) := do + let branchless ← readBool + let writers ← readCount 3 + unless writers == 1 || writers == 3 do throw "unexpected native writer count" + let mut queries := [] + let mut allocations := 0 + for writer in [:writers] do + let (parts, checked) ← readSequence rows s!"report {index}, writer {writer}" + queries := queries ++ parts + allocations := allocations + checked + let count ← readCount 64 + for slot in [:count] do + let native : ExprLookup := ⟨← readExpr 64, ← readList (← readCount) (readExpr 64)⟩ + let expected := LookupEmitter.slot branchless queries slot + unless native == expected do throw s!"native lookup expression trees differ: report {index}, slot {slot}" + for (row, seed) in rows.zipIdx do + let weight ← readField + let message ← readValues + let values := assignment row + unless expected.eval goldilocksOps values == some (weight, message) do + throw s!"native slot values differ: report {index}, slot {slot}, assignment {seed}" + let some parts := queries.mapM (LookupEmitter.QueryExpr.eval values) + | throw "undefined raw query expressions" + unless weight == AIR.querySlotMultiplicity parts slot && + message == AIR.slotMessage branchless (AIR.querySlotParts parts slot) do + throw "symbolic slot and valued query parts differ" + return (writers, (if writers == 3 then 1 else 0), allocations) + +private def readCorpus : Reader Nat := do + let header := "Aiur operation expressions v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "operation snapshot version differs" + unless (← readCount) == 4 do throw "incomplete operation assignments" + let rows ← readList 4 do return (← readValues).toArray + unless rows.all (·.size == 512) do throw "operation assignment width differs" + unless (← readCount) == 876 do throw "incomplete operation expression corpus" + let mut sequences := 0 + let mut shared := 0 + let mut allocations := 0 + for index in [:876] do + let (count, combined, checked) ← readReport rows index + sequences := sequences + count + shared := shared + combined + allocations := allocations + checked + unless sequences == 1752 && shared == 438 do throw "incomplete native operation coverage" + unless allocations == 1168 do throw "incomplete degree-valid compiler allocation coverage" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "operation snapshot has trailing bytes" + return allocations + +def run (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok (allocations, _) => + IO.println s!"operation expressions: 1,752 native sequences, 7,008 assignments, 438 shared-slot cases and {allocations} compiler allocations match" + +end AiurTests.OperationExpressions + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.OperationExpressions.run path + | _ => throw (IO.userError "expected native operation expression snapshot") diff --git a/Tests/Aiur/OperationRows.lean b/Tests/Aiur/OperationRows.lean new file mode 100644 index 000000000..c24c4d224 --- /dev/null +++ b/Tests/Aiur/OperationRows.lean @@ -0,0 +1,144 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.OperationRows +import Ix.Aiur.Proofs.SelectorMessages + +/-! Compare evaluated native operation emission with Lean, including every +operation constructor, constant folding, virtual/materialized values, logical +output reuse, column allocation, constraints and selector-gated query parts. -/ + +open Aiur Aiur.AIR Aiur.Bytecode + +namespace AiurTests.OperationRows + +private def fixtures : List (List Op) := [ + [.const 0], [.const 1], [.const (0 - 1)], + [.add 0 1], [.add 0 3], [.add 3 4], + [.sub 1 2], [.sub 0 3], [.sub 3 4], + [.mul 0 3], [.mul 1 3], [.mul 2 1], [.mul 3 4], [.mul 5 6], + [.eqZero 0], [.eqZero 1], [.eqZero 2], [.eqZero 3], [.eqZero 4], [.eqZero 5], + [.call 17 #[3, 4, 5] 0 false], [.call 17 #[3, 4, 5] 2 false], + [.call 17 #[3, 4, 5] 0 true], [.call 17 #[3, 4, 5] 2 true], + [.store #[]], [.store #[0, 3, 4]], [.load 0 3], [.load 3 4], + [.assertEq #[] #[] none], [.assertEq #[0, 3, 4] #[1, 4, 3] (some "row")], + [.ioGetInfo 0 #[1, 2]], [.ioRead 0 0 0], [.ioRead 0 3 2], + [.ioSetInfo 0 #[1, 2] 3 4], [.ioWrite 0 #[3, 4]], + [.debug "row" none], [.debug "row" (some #[3, 4])], + [.u8BitDecomposition 3], [.u8ShiftLeft 3], [.u8ShiftRight 3], + [.u8Xor 3 4], [.u8Add 3 4], [.u8Sub 3 4], [.u8And 3 4], [.u8Or 3 4], + [.u8LessThan 3 4], [.u8RangeCheck 3 4], [.u8Mul 3 4], + [.u8XorSplit7 3 4], [.u8XorSplit4 3 4], [.u32LessThan 3 4], + [.unconstrainedBigUintDivMod 3 4], [.unconstrainedGToBytes 3], [.unconstrainedGInverse 4], + [.unconstrainedU32Add #[0, 1, 2, 3] #[4, 5, 6, 7]], + [.unconstrainedU32Add3 #[0, 1, 2, 3] #[4, 5, 6, 7] #[7, 6, 5, 4]], + [.u32ToField #[0, 1, 2, 3]], [], + [.const 0, .mul 8 3], + [.mul 3 4, .add 8 3, .eqZero 9], + [.unconstrainedGToBytes 3, .u8RangeCheck 8 9, .u8Add 8 9, + .assertEq #[16] #[3] none, .unconstrainedGInverse 17], + [.store #[3, 4], .load 2 8, .call 17 #[9, 10] 2 false, .u8Xor 11 12], + [.ioRead 0 0 4, .unconstrainedU32Add #[8, 9, 10, 11] #[0, 1, 2, 7], + .u32ToField #[12, 13, 14, 15]], + [.eqZero 0, .add 8 1, .sub 9 1, .mul 10 7], + [.unconstrainedBigUintDivMod 3 4, .call 17 #[8, 9] 0 false, .debug "row" none]] + +private def inputValues (row : Nat → G) : Array RowValue := #[ + RowValue.konst 0, RowValue.konst 1, RowValue.konst (0 - 1), + RowValue.variable (row 0), RowValue.variable (row 1), + RowValue.variable (row 0 + row 1), RowValue.variable (row 2), RowValue.konst 257] + +private def row (seed : Nat) (selector : G) (index : Nat) : G := + let choices : Array G := #[0, 1, 255, 256, 0 - 1, 0 - 2, + G.ofNat (2 ^ 32 - 1), G.ofNat (2 ^ 32), G.ofNat (2 ^ 48 - 1), 17, 3, 65536] + match index with + | 0 => choices[seed]?.getD 0 + | 1 => choices[(seed + 1) % 12]?.getD 0 + | 2 => choices[(seed + 2) % 12]?.getD 0 + | 3 => selector + | index => choices[(seed + 5 * index) % 12]?.getD 0 + +private def appendNat (out : ByteArray) (value : Nat) : ByteArray := Id.run do + let mut out := out + for i in [:8] do + out := out.push ((value >>> (8 * i)) % 256).toUInt8 + return out + +private def appendValues (out : ByteArray) (values : List G) : ByteArray := + values.foldl (fun out value => appendNat out value.n) (appendNat out values.length) + +private def encode (branchless : Bool) (selector : G) (emission : OpsEmission) : ByteArray := Id.run do + let mut out := appendNat ByteArray.empty emission.column + out := appendNat out emission.values.size + for value in emission.values do + out := appendNat out value.value.n + out := appendNat out value.degree + out := appendNat out (if value.constant then 1 else 0) + out := appendValues out emission.equations + out := appendNat out emission.queries.length + for query in emission.queries do + out := appendNat out selector.n + out := appendValues out (gateMessage branchless selector query) + return out + +private def expected (header : String) (fixtures : List (List Op)) : Except String (Array (String × ByteArray)) := do + let mut records := #[("header", appendNat header.toUTF8 fixtures.length)] + for branchless in [false, true] do + for seed in [:12] do + for selector in ([0, 1, 2, 0 - 1] : List G) do + let row := row seed selector + for (ops, index) in fixtures.zipIdx do + let label := s!"fixture {index}, seed {seed}, selector {selector.n}, branchless {branchless}" + let some emission := emitOps row selector (row 2) ops (inputValues row) 4 + | throw s!"unexpected rejected emission: {label}" + records := records.push (label, encode branchless selector emission) + return records + +private def compare (path : System.FilePath) (header : String) (fixtures : List (List Op)) + (count : Nat) : IO Unit := do + let native ← IO.FS.readBinFile path + let records ← match expected header fixtures with + | .ok records => pure records + | .error error => throw (IO.userError error) + unless records.size == count + 1 do + throw (IO.userError s!"incomplete operation-row corpus: {records.size - 1}") + let mut position := 0 + for (label, expected) in records do + unless position + expected.size ≤ native.size do + throw (IO.userError s!"short operation-row snapshot at {label}") + for i in [:expected.size] do + unless native[position + i]! == expected[i]! do + throw (IO.userError s!"operation-row mismatch at {label}, byte {i} (absolute {position + i}): {native[position + i]!} / {expected[i]!}") + position := position + expected.size + unless position == native.size do + throw (IO.userError s!"extra operation-row snapshot data: {native.size - position} bytes") + +def run (path : System.FilePath) : IO Unit := do + unless fixtures.length == 65 do throw (IO.userError "incomplete operation fixture corpus") + compare path "Aiur operation rows v1\n" fixtures 6240 + IO.println "operation rows: 6,240 native/Lean assignments across all 34 constructors and output-reusing sequences match" + +def runConstantDegree (path : System.FilePath) : IO Unit := do + let fixtures : List (List Op) := [ + [.const 0, .mul 8 3, .eqZero 9], + [.const 0, .mul 3 8, .eqZero 9], + [.mul 0 3, .add 8 1, .eqZero 9], + [.mul 0 3, .sub 0 8, .eqZero 9], + [.mul 0 3, .eqZero 8, .eqZero 9], + [.mul 0 3, .eqZero 8, .mul 9 3], + [.mul 0 3, .mul 8 1, .eqZero 9], + [.mul 0 3, .sub 2 8, .eqZero 9]] + compare path "Aiur constant degree rows v1\n" fixtures 768 + IO.println "constant degree rows: 768 native/Lean arbitrary assignments across eight sequences match" + +end AiurTests.OperationRows + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.OperationRows.run path + | [path, constantPath] => + AiurTests.OperationRows.run path + AiurTests.OperationRows.runConstantDegree constantPath + | _ => throw (IO.userError "expected native operation-row snapshot and optional constant-degree snapshot") diff --git a/Tests/Aiur/Polynomial.lean b/Tests/Aiur/Polynomial.lean new file mode 100644 index 000000000..1f385f760 --- /dev/null +++ b/Tests/Aiur/Polynomial.lean @@ -0,0 +1,125 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Polynomial +import Tests.Aiur.EmissionReader + +/-! Compare the native final-polynomial Horner iterator and independent +upstream coefficient operations over both native fields. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader + +namespace AiurTests.Polynomial + +private def baseSample (seed : Nat) : G := if seed == 2 then 0 - 1 else G.ofNat seed + +private def extensionSample (seed : Nat) : ProofCodec.Extension := + if seed < 3 then .ofBase (baseSample seed) else ⟨G.ofNat (seed * 67), G.ofNat (seed + 1)⟩ + +private def coefficients [OfNat R 0] [OfNat R 1] (length seed : Nat) (sample : Nat → R) : List R := + (List.range length).map fun index => + if seed == 0 then 0 + else if seed == 1 then if index + 1 == length then 1 else 0 + else if seed == 2 && index ≥ length / 2 then 0 + else sample (seed * 67 + index * 13 + 3) + +private def readCases [Lean.Grind.CommRing R] [BEq R] [LawfulBEq R] + (sample : Nat → R) (readValue : Reader R) : Reader (List Nat) := do + let readValues := do readList (← readCount) readValue + let domain ← readValues + unless domain == (List.range 80).map sample do throw "native polynomial sample domain differs" + let mut count := 0 + let mut divisions := 0 + let mut zeroCases := 0 + let mut rootSets := 0 + let mut repeatedSets := 0 + for length in [0, 1, 2, 3, 4, 7, 8, 9, 16, 31, 32, 65] do + for rightLength in [0, 1, length, length + 3] do + for seed in [:8] do + let left ← readValues + let right ← readValues + unless left == coefficients length seed sample && right == coefficients rightLength seed sample do + throw "polynomial coefficient inventory differs" + let root ← readValue + let point ← readValue + unless root == sample seed && point == (if seed % 3 == 0 then root else sample (seed + 19)) do + throw "polynomial evaluation point inventory differs" + let atPoint ← readValue + let atRoot ← readValue + let rightValue ← readValue + unless atPoint == Quotient.horner point left && atRoot == Quotient.horner root left && + rightValue == Quotient.horner point right do throw "native Horner iterator differs" + let added ← readValues + let difference ← readValues + unless added == Polynomial.add left right && difference == Polynomial.sub left right do + throw "native coefficient addition or subtraction differs" + unless Quotient.horner point added == atPoint + rightValue && + Quotient.horner point difference == atPoint - rightValue do throw "coefficient evaluation identity differs" + if left.isEmpty then + unless (Polynomial.divide root left).isEmpty do throw "total empty quotient differs" + else + let quotient ← readValues + let remainder ← readValue + unless quotient == Polynomial.divide root left && remainder == atRoot do + throw "native synthetic quotient or remainder differs" + unless quotient.length + 1 == left.length && + (point - root) * Quotient.horner point quotient + remainder == atPoint do + throw "synthetic division identity differs" + divisions := divisions + 1 + let roots ← readNat + let agreements ← readNat + unless roots == domain.countP (fun value => Quotient.horner value left == 0) && + agreements == domain.countP (fun value => Quotient.horner value difference == 0) do + throw "native polynomial root counts differ" + if left.all (· == 0) then zeroCases := zeroCases + 1 + else unless roots < left.length do throw "polynomial exceeds its distinct-root bound" + unless difference.all (· == 0) || agreements < max left.length right.length do + throw "different polynomials exceed their agreement bound" + count := count + 1 + for length in [0, 1, 2, 3, 7, 16, 31, 32, 63] do + for variant in [:4] do + let roots ← readValues + let expected := (List.range length).map fun index => sample + (if variant == 0 then index else if variant == 1 then length - index - 1 + else if variant == 2 then 0 else index / 2) + unless roots == expected do throw "native root-set inventory differs" + let polynomial ← readValues + unless polynomial == Polynomial.fromRoots roots do throw "native vanishing coefficients differ" + unless polynomial.length == roots.length + 1 && polynomial.getLast? == some 1 do + throw "native vanishing polynomial is not monic" + for point in [sample 0, sample 2, sample 17, sample 79] do + let value ← readValue + unless value == Quotient.horner point polynomial && value == LogUp.product (roots.map (point - ·)) do + throw "native vanishing evaluation differs" + let rootCount ← readNat + unless rootCount == domain.countP (fun point => Quotient.horner point polynomial == 0) && rootCount ≤ roots.length do + throw "native vanishing root count differs" + let repeated := roots.eraseDups.length != roots.length + if repeated then repeatedSets := repeatedSets + 1 + else unless rootCount == roots.length do throw "native distinct-root polynomial lost a root" + rootSets := rootSets + 1 + return [count, divisions, zeroCases, rootSets, repeatedSets] + +private def readCorpus : Reader (List Nat × List Nat) := do + let header := "Aiur coefficient polynomials v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "polynomial snapshot version differs" + let base ← readCases baseSample readField + let extension ← readCases extensionSample (do return ⟨← readField, ← readField⟩) + unless (← readList 10 readNat) == base ++ extension do throw "native polynomial coverage totals differ" + unless base == [384, 352, 80, 36, 14] && extension == base do throw "incomplete native polynomial corpus" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "polynomial snapshot has trailing bytes" + return (base, extension) + +end AiurTests.Polynomial + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.Polynomial.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok (counts, _) => IO.println s!"Native polynomial arithmetic/divisions/zero cases/root sets/repeated sets match: {counts}" + | _ => throw (IO.userError "expected native coefficient polynomial snapshot") diff --git a/Tests/Aiur/ProofCodec.lean b/Tests/Aiur/ProofCodec.lean new file mode 100644 index 000000000..0a4adb0cd --- /dev/null +++ b/Tests/Aiur/ProofCodec.lean @@ -0,0 +1,92 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ShapedVerifier +import Tests.Aiur.EmissionReader + +/-! Native serde decisions and every field of honest and malformed proofs. -/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader + +namespace AiurTests.ProofBytes + +private def vector (item : α → List Nat) (values : List α) : List Nat := + values.length :: values.flatMap item + +private def extension (value : ProofCodec.Extension) : List Nat := [value.c0.n, value.c1.n] + +private def hashes (values : ProofCodec.Cap) : List Nat := vector (List.map UInt8.toNat) values + +private def openings (item : α → List Nat) (values : ProofCodec.Openings α) : List Nat := + vector (vector (vector item)) values + +private def view (value : ProofCodec.Data) : List Nat := + vector (fun degree => [degree.toNat]) value.logDegrees ++ + vector (fun active => [if active then 1 else 0]) value.active ++ + openings extension value.stage2 ++ openings extension value.stage1 ++ + (match value.preprocessed with | none => [0] | some values => 1 :: openings extension values) ++ + openings extension value.quotient ++ vector extension value.accumulators ++ + hashes value.commitments.quotient ++ hashes value.commitments.stage2 ++ hashes value.commitments.stage1 ++ + [value.fri.queryPowWitness.n] ++ vector extension value.fri.finalPoly ++ + vector (fun step => hashes step.siblingHashes ++ vector (vector extension) step.siblingValues ++ + [step.logArity.toNat]) value.fri.commitOpenings ++ + vector (fun batch => hashes batch.siblingHashes ++ openings (fun x => [x.n]) batch.values) value.fri.inputOpenings ++ + vector (fun x => [x.n]) value.fri.commitPowWitnesses ++ vector hashes value.fri.commits + +private def readBytes : Reader ByteArray := do takeBytes (← readCount 16777216) + +private def readCorpus : Reader (Nat × Nat × Nat) := do + let header := "Aiur proof codec v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "proof codec snapshot version differs" + let keys ← readList (← readCount) readBytes + unless keys.length == 4 do throw "missing honest proof systems" + let keys ← keys.mapM fun bytes => do + let some key := KeyCodec.decodeCanonical bytes | throw "honest proof key is not canonical" + return key + let count ← readCount 100000 + let mut accepted := 0 + let mut suffixed := 0 + for index in [:count] do + let bytes ← readBytes + let expected ← readBool + let parsed := ProofCodec.readData bytes.data.toList + unless parsed.isSome == expected do throw s!"native proof parsing differs at case {index}" + if expected then + let some (value, rest) := parsed | throw "missing parsed proof" + let canonical ← readBytes + let words ← readList (← readCount 16777216) readNat + unless view value == words do throw s!"native proof fields differ at case {index}" + unless ProofCodec.encode value == canonical do throw s!"native proof encoding differs at case {index}" + if accepted % 5 == 0 then + let some key := keys[accepted / 5]? | throw "missing honest proof key" + unless (ProofShape.check key value).isSome && ProofShape.fixedHeights key value && + (ProofShape.queryBound key value).isSome do throw "native proof fails preceding shape guards" + unless (BoundVerifier.readProof key canonical).isOk == MerkleCap.check key value do + throw "native proof cap coverage differs from checked admission" + unless ProofCodec.decodeCanonical canonical == some value do throw "canonical proof round trip failed" + unless (ProofCodec.decodeCanonical bytes).isSome == (bytes == canonical) do + throw "canonical proof framing differs" + unless (ProofCodec.decode bytes).isSome == rest.isEmpty do throw "proof suffix framing differs" + accepted := accepted + 1 + if !rest.isEmpty then suffixed := suffixed + 1 + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "proof codec snapshot has trailing bytes" + return (count, accepted, suffixed) + +def run (path : System.FilePath) : IO Unit := do + let bytes ← IO.FS.readBinFile path + match readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok ((count, accepted, suffixed), _) => + unless count == 3636 && accepted == 20 && suffixed == 8 do + throw (IO.userError "incomplete proof codec corpus") + IO.println s!"proof codec: {count} native/Lean byte cases, {accepted} decoded field records, {suffixed} native suffixes rejected by exact framing" + +end AiurTests.ProofBytes + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.ProofBytes.run path + | _ => throw (IO.userError "expected native proof codec snapshot") diff --git a/Tests/Aiur/ProofShape.lean b/Tests/Aiur/ProofShape.lean new file mode 100644 index 000000000..08cf8e30a --- /dev/null +++ b/Tests/Aiur/ProofShape.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ShapedVerifier +import Tests.Aiur.EmissionReader + +/-! Native shape decisions, every u8 domain exponent, independently changed +matrix dimensions, inactive circuits, fixed heights and global budgets. -/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader + +namespace AiurTests.ProofShapes + +private def readBytes : Reader ByteArray := do takeBytes (← readCount 16777216) + +private def readCorpus : Reader (Nat × Nat × Nat) := do + let header := "Aiur proof shapes v2\n".toUTF8 + unless (← takeBytes header.size) == header do throw "proof shape snapshot version differs" + let systems ← readCount + let mut total := 0 + let mut accepted := 0 + let mut guarded := 0 + for system in [:systems] do + let some key := KeyCodec.decodeCanonical (← readBytes) | throw "invalid shape key" + let count ← readCount 100000 + total := total + count + for index in [:count] do + let bytes ← readBytes + let some proof := ProofCodec.decodeCanonical bytes | throw "invalid shape proof framing" + let expected ← readOption (do readList (← readCount) readNat) + let fixed ← readBool + let bound ← readOption readNat + let cap ← readBool + let checked := ProofShape.check key proof + unless checked.map (List.map (ProofShape.quotientDegree ∘ ProofShape.Row.circuit)) == expected do + throw s!"native opening shape differs at system {system}, case {index}" + unless ProofShape.fixedHeights key proof == fixed do throw "fixed proof heights differ" + unless ProofShape.queryBound key proof == bound do throw "proof lookup budget differs" + unless MerkleCap.check key proof == cap do throw "proof Merkle cap coverage differs" + let ready := (BoundVerifier.readProof key bytes).isOk + unless ready == (expected.isSome && fixed && bound.isSome && cap) do throw "checked proof guard differs" + if checked.isSome then accepted := accepted + 1 + if ready then guarded := guarded + 1 + unless systems == 4 do throw "missing proof shape systems" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "proof shape snapshot has trailing bytes" + return (total, accepted, guarded) + +def run (path : System.FilePath) : IO Unit := do + match readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error error => throw (IO.userError error) + | .ok ((total, accepted, guarded), _) => + unless total == 4696 && accepted == 514 do throw (IO.userError "incomplete proof shape corpus") + IO.println s!"proof shapes: {total} native/Lean cases, {accepted} accepted shapes, {guarded} pass fixed-height and budget guards" + +end AiurTests.ProofShapes + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.ProofShapes.run path + | _ => throw (IO.userError "expected native proof shape snapshot") diff --git a/Tests/Aiur/PrunedMerkle.lean b/Tests/Aiur/PrunedMerkle.lean new file mode 100644 index 000000000..05f7a5520 --- /dev/null +++ b/Tests/Aiur/PrunedMerkle.lean @@ -0,0 +1,97 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.PrunedMerkle +import Ix.Aiur.Proofs.PrunedMerkle +import Tests.Aiur.EmissionReader + +/-! Actual native shared openings, complete logs on success and failure, +and reconstructed individual paths with their queried-input inclusion. -/ + +open Aiur Aiur.NativeAIR Aiur.NativeAIR.PrunedMerkle AiurTests.EmissionReader + +namespace AiurTests.PrunedMerkle + +private def readDigest : Reader Merkle.Digest := do + let bytes ← takeBytes 32 + if length : bytes.data.size = 32 then return ⟨bytes.data, length⟩ + else throw "incomplete shared Merkle digest" + +private def readDigests : Reader (List Merkle.Digest) := do + readList (← readCount) readDigest + +private def readCall : Reader (List UInt8 × Merkle.Digest) := do + let input ← takeBytes (← readCount 100000) + return (input.data.toList, ← readDigest) + +private def readCorpus : Reader Nat := do + let header := "Aiur pruned Merkle v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "shared Merkle snapshot version differs" + let expected ← readList 6 readNat + let cases := expected[0]! + unless expected == [7946, 1619, 1069, 3854, 2534, 42803] do throw "incomplete shared Merkle corpus" + let mut accepted := 0 + let mut omitted := 0 + let mut unhashed := 0 + let mut late := 0 + let mut calls := 0 + let mut paths := 0 + for case in [:cases] do + let dimensions ← readList (← readCount) do + return Merkle.Dimensions.mk (← readCount) (← readCount 32) + let capHeight ← readCount + let indices ← readList (← readCount) readNat + let rows ← readList (← readCount) do readList (← readCount) readValues + let proof ← readDigests + let cap ← readDigests + let native ← readBool + let coverage ← readBool + let hashes ← readList (← readCount) readCall + let result := replay Blake3.digest dimensions capHeight indices rows proof + unless result.inputs == hashes.map Prod.fst do + throw s!"shared Merkle hash input sequence differs at {case}" + unless verify Blake3.digest dimensions capHeight indices cap rows proof == native do + throw s!"shared Merkle decision differs at {case}" + unless Merkle.covered dimensions capHeight == coverage do throw "shared Merkle coverage differs" + unless verifyCovered Blake3.digest dimensions capHeight indices cap rows proof == (native && coverage) do + throw "covered shared Merkle decision differs" + for (input, output) in hashes do + unless Blake3.digest input == output do throw s!"shared native hash output differs at {case}" + if let some nodes := result.result then + let tickets := nodes.flatMap Node.tickets + unless tickets.length == (uniqueIndices indices).length do throw "shared ticket count differs" + for (index, values) in indices.zip rows do + unless tickets.any (fun ticket => ticket.index == index && ticket.rows == values) do + throw "shared reconstruction lost a query" + for node in nodes do + for ticket in node.tickets do + let some path := Merkle.replay Blake3.digest dimensions capHeight ticket.index ticket.rows ticket.proof + | throw "shared reconstruction has an invalid individual path" + unless path.index == node.index && path.hashing.digest == node.digest do + throw "shared reconstruction reaches a different node" + unless path.hashing.inputs.all result.inputs.contains do + throw "shared reconstruction uses an unrecorded hash input" + paths := paths + 1 + if native then accepted := accepted + 1 + if native && !coverage then omitted := omitted + 1 + if hashes.isEmpty then unhashed := unhashed + 1 + if !native && !hashes.isEmpty then late := late + 1 + calls := calls + hashes.length + unless expected == [cases, accepted, omitted, unhashed, late, calls] do + throw "shared Merkle coverage totals differ" + unless paths == 19709 do throw "incomplete reconstructed individual paths" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "shared Merkle snapshot has trailing bytes" + return paths + +end AiurTests.PrunedMerkle + +def main (args : List String) : IO Unit := do + match args with + | [path] => + match AiurTests.PrunedMerkle.readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error message => throw (IO.userError message) + | .ok (paths, _) => IO.println s!"Shared Merkle: 7946 native decisions, 42803 hash calls and {paths} individual paths match" + | _ => throw (IO.userError "expected native shared Merkle snapshot") diff --git a/Tests/Aiur/SelectorControl.lean b/Tests/Aiur/SelectorControl.lean new file mode 100644 index 000000000..4ca4e5b03 --- /dev/null +++ b/Tests/Aiur/SelectorControl.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ReturnGates + +/-! Native/Lean comparison for the actual shared argument combiner, block +selectors, selector polynomial projection and nearest-continuation yield +collection. Fixtures include arbitrary field assignments, nested continuations, +early returns, inactive branches and different raw message lengths. -/ + +open Aiur Aiur.AIR Aiur.Bytecode + +namespace AiurTests.SelectorControl + +private def appendNat (out : ByteArray) (value : Nat) : ByteArray := Id.run do + let mut out := out + for i in [:8] do + out := out.push ((value >>> (8 * i)) % 256).toUInt8 + return out + +private def appendValues (out : ByteArray) (values : List G) : ByteArray := + values.foldl (fun out value => appendNat out value.n) (appendNat out values.length) + +private def leaf (seed next : Nat) : Block × Nat := + (⟨#[], if seed % 2 == 0 then .return next #[] else .yield next #[]⟩, next + 1) + +private def fixture : Nat → Nat → Nat → Block × Nat + | 0, seed, next => leaf seed next + | depth + 1, seed, next => + if seed % 5 == 0 then leaf seed next + else + let (left, next) := fixture depth (seed * 3 + 1) next + let (right, next) := fixture depth (seed * 3 + 2) next + let (fallback, next) := if seed % 2 == 0 then + let (block, next) := fixture depth (seed * 3 + 3) next + (some block, next) + else (none, next) + let branches := #[(0, left), (1, right)] + if seed % 3 == 0 then (⟨#[], .match 0 branches fallback⟩, next) + else + let (continuation, next) := fixture depth (seed * 3 + 4) next + (⟨#[], .matchContinue 0 branches fallback 0 0 0 continuation⟩, next) + +private def assignment (pattern index count : Nat) : G := + match pattern with + | 0 => 0 + | 1 => 1 + | 2 => 2 + | 3 => 0 - 1 + | 4 => G.ofNat (index + 1) + | 5 => 0 - G.ofNat (index + 1) + | 6 => if index % 2 == 0 then 1 else 0 + | 7 => [0, 0 - 1, 1, 2][index % 4]?.getD 0 + | pattern => if pattern < 8 + count then + (if index == pattern - 8 then 1 else 0) + else if index != pattern - 8 - count then 1 else 0 + +private def expected : ByteArray × Nat × Nat := Id.run do + let mut out := appendNat "Aiur selector control v1\n".toUTF8 48 + let mut controls := 0 + let mut messages := 0 + for depth in [:4] do + for seed in [:12] do + let (block, count) := fixture depth seed 0 + out := appendNat out count + out := appendNat out (8 + 2 * count) + for pattern in [:8 + 2 * count] do + let flow := block.selectorFlow fun index => assignment pattern index count + out := appendNat out flow.entry.n + out := appendValues out ([99, 100] ++ flow.yields) + out := appendValues out flow.equations + let gates := block.returnGates (fun index => assignment pattern index count) flow.entry + out := appendValues out (weightedMessage + (gates.map fun selector => (selector, [0, 37, 3, 19, 257]))) + controls := controls + 1 + out := appendNat out (2 * 7 * 32 * 8) + for branchless in [false, true] do + for count in [:7] do + for seed in [:32] do + for pattern in [:8] do + let parts := (List.range count).map fun index => + (assignment pattern index count, + (List.range ((seed + index * 3) % 8)).map fun offset => + let value := G.ofNat (17 + seed + index * 5 + offset * 11) + if (seed + offset) % 2 == 0 then value else 0 - value) + out := appendNat out (selectorSum (parts.map Prod.fst)).n + out := appendValues out (slotMessage branchless parts) + messages := messages + 1 + return (out, controls, messages) + +def run (path : System.FilePath) : IO Unit := do + let native ← IO.FS.readBinFile path + let (expected, controls, messages) := expected + unless messages == 3584 do + throw (IO.userError "incomplete shared-message corpus") + unless native.size == expected.size do + throw (IO.userError s!"selector-control snapshot size differs: {native.size} / {expected.size}") + for i in [:expected.size] do + unless native[i]! == expected[i]! do + throw (IO.userError s!"selector-control mismatch at byte {i}: {native[i]!} / {expected[i]!}") + IO.println s!"selector control: {controls} native/Lean assignments and {messages} shared messages match" + +end AiurTests.SelectorControl + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.SelectorControl.run path + | _ => throw (IO.userError "expected native selector-control snapshot path") diff --git a/Tests/Aiur/SourceValues.lean b/Tests/Aiur/SourceValues.lean new file mode 100644 index 000000000..067363e10 --- /dev/null +++ b/Tests/Aiur/SourceValues.lean @@ -0,0 +1,43 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Semantics.Flatten + +/-! Hash snapshots from the original native derivation. Source evaluation +uses these hashes for its memory buckets; totalization must retain them. -/ + +open Aiur + +namespace Tests.Aiur.SourceValues + +def fixtures : Array Value := Id.run do + let global := Global.init "value" + let other := global.pushNamespace "child" + let mut values := #[Value.unit, .tuple #[], .array #[], .ctor global #[], .fn global, .fn other] + for n in #[0, 1, 255, 256, 65536, 18446744069414584320] do + let field := Value.field (G.ofNat n) + let contents := #[Value.unit, field, .pointer n (n + 1)] + values := values ++ #[field, .pointer n 0, .pointer 0 n, .pointer n n, + .tuple contents, .array contents, .ctor global contents, .ctor other contents, + .tuple contents.reverse, .array contents.reverse] + let mut nested := Value.field 7 + for depth in [:33] do + nested := match depth % 3 with + | 0 => .tuple #[nested, .unit] + | 1 => .array #[.field (G.ofNat depth), nested] + | _ => .ctor other #[nested, .pointer depth (depth + 1)] + values := values.push nested + return values + +private def report (values : Array Value) : IO Unit := do + IO.println s!"SOURCE VALUE HASH FIXTURES {values.size}" + for h : i in [:values.size] do + IO.println s!"VALUE {i} HASH {hash values[i]}" + +def main : IO Unit := report fixtures + +end Tests.Aiur.SourceValues + +def main := Tests.Aiur.SourceValues.main diff --git a/Tests/Aiur/TailMatches.lean b/Tests/Aiur/TailMatches.lean new file mode 100644 index 000000000..2df4f97a5 --- /dev/null +++ b/Tests/Aiur/TailMatches.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Stages.Source + +/-! Native syntax snapshots captured before replacing partial tail-match +restoration. Every term and pattern constructor occurs. Tail positions, +non-tail subexpressions, distinct local names and nested matches are covered. -/ + +open Aiur Aiur.Source + +namespace Tests.Aiur.TailMatches + +private def eta (name : Local) (value : Term) : Term := + .let (.var name) value (.var name) + +private def constructors (value : Term) : Array Term := + let global := Global.init "fixture" + #[.unit, .var (.str "x"), .ref global, .field 7, + .tuple #[value], .array #[value], .ret value, + .let .wildcard value value, .match value [(.wildcard, value)], + .app global [value] .normal, .app global [value] .unconstrained, + .app global [value] .inlined, + .add value value, .sub value value, .mul value value, .eqZero value, + .proj value 0, .get value 0, .slice value 0 1, .set value 0 value, + .store value, .load value, .ptrVal value, .ann .field value, + .assertEq value value none value, .assertEq value value (some "check") value, + .ioGetInfo value value, .ioSetInfo value value value value value, + .ioRead value value 1, .ioWrite value value value, + .u8BitDecomposition value, .u8ShiftLeft value, .u8ShiftRight value, + .u8Xor value value, .u8Add value value, .u8Mul value value, + .u8Sub value value, .u8And value value, .u8Or value value, + .u8LessThan value value, .u32LessThan value value, + .u8XorSplit7 value value, .u8XorSplit4 value value, + .unconstrainedU32Add value value, .unconstrainedU32Add3 value value value, + .u32ToField value, .unconstrainedBigUintDivMod value value, + .unconstrainedGToBytes value, .unconstrainedGInverse value, + .u8Lit 255, .u8RangeCheck value value, .toField value, + .u8FromFieldUnsafe value, .debug "message" none value, + .debug "message" (some value) value] + +private def patterns : Array Pattern := + #[.var (.str "x"), .var (.idx 0), .wildcard, + .ref (Global.init "Ctor") [.var (.str "x")], .field 7, + .tuple #[.var (.str "x")], .array #[.wildcard], + .or (.field 7) (.var (.str "x")), .pointer (.var (.str "x"))] + +def fixtures : Array Term := Id.run do + let name : Local := .str "x" + let wrapped := eta name (.field 7) + let mut terms := #[] + for term in constructors wrapped do + terms := terms ++ #[term, eta name term, + .let (.var name) term (.var (.str "y")), + .let .wildcard wrapped (eta name term)] + for pattern in patterns do + terms := terms ++ #[.let pattern wrapped wrapped, + .match wrapped [(pattern, wrapped), (.wildcard, eta name (.ret wrapped))]] + for x in #[Local.str "x", .str "0", .idx 0, .idx 1] do + for y in #[Local.str "x", .str "0", .idx 0, .idx 1] do + terms := terms.push (.let (.var x) wrapped (.var y)) + terms := terms ++ #[.match wrapped [], .match wrapped [(.field 9, wrapped)]] + let mut nested := wrapped + for depth in [:25] do + nested := eta (.idx depth) + (.match wrapped [(.field 7, nested), (.wildcard, eta name (.ret wrapped))]) + terms := terms.push nested + return terms + +private def report (terms : Array Term) : IO Unit := do + IO.println s!"TAIL MATCH FIXTURES {terms.size}" + for h : i in [:terms.size] do + IO.println s!"TERM {i} {(repr terms[i].restoreTailMatches).pretty 1000000}" + +def main : IO Unit := report fixtures + +end Tests.Aiur.TailMatches + +def main := Tests.Aiur.TailMatches.main diff --git a/Tests/Aiur/TraceHeights.lean b/Tests/Aiur/TraceHeights.lean new file mode 100644 index 000000000..2f6b0d4f3 --- /dev/null +++ b/Tests/Aiur/TraceHeights.lean @@ -0,0 +1,49 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ByteColumns + +open Aiur + +namespace AiurTests.TraceHeights + +private def append (out : ByteArray) (heights : List Nat) (active : List Bool) (degrees : List Nat) : ByteArray := + out.push (if fixedTraceHeights heights active degrees then 1 else 0) + +private def expected : ByteArray := Id.run do + let mut out := "Aiur fixed trace heights v1\n".toUTF8 + for height in [0, 1, 2, 3, 256, 65536, 2^31, 2^32, 2^63, 2^64 - 1] do + for degree in [:256] do + out := append out [height] [true] [degree] + out := append out [0, height, 0] [false, true, false] [degree] + out := append out [0, height, 65536] [true, true, true] [2, degree, 16] + let heights := [0, 256, 0, 65536] + for heightCount in [:5] do + for activeCount in [:5] do + for mask in [:2^activeCount] do + let active := (List.range activeCount).map fun bit => (mask &&& (2^bit)) != 0 + for degreeCount in [:6] do + for degree in [0, 1, 7, 8, 9, 15, 16, 17, 63, 64, 255] do + out := append out (heights.take heightCount) active (List.replicate degreeCount degree) + return out + +def run (path : System.FilePath) : IO Unit := do + let native ← IO.FS.readBinFile path + let reference := expected + unless reference.size == "Aiur fixed trace heights v1\n".toUTF8.size + 17910 do + throw (IO.userError "incomplete fixed-trace-height corpus") + unless native.size == reference.size do + throw (IO.userError s!"fixed-trace-height snapshot size differs: {native.size} / {reference.size}") + for index in [:reference.size] do + unless native[index]! == reference[index]! do + throw (IO.userError s!"fixed-trace-height mismatch at byte {index}: {native[index]!} / {reference[index]!}") + IO.println "fixed trace heights: all 17,910 native/Lean checks match" + +end AiurTests.TraceHeights + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.TraceHeights.run path + | _ => throw (IO.userError "expected native fixed-trace-height snapshot path") diff --git a/Tests/Aiur/Transcript.lean b/Tests/Aiur/Transcript.lean new file mode 100644 index 000000000..f10d214fc --- /dev/null +++ b/Tests/Aiur/Transcript.lean @@ -0,0 +1,212 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.Transcript +import Ix.Aiur.Proofs.Blake3 +import Tests.Aiur.EmissionReader +import Blake3.Rust + +/-! Comparison with the instrumented native verifier, including challenger +calls in PCS verification. Replay uses the checked concrete Blake3 hash; +the test also compares it with the independent FFI implementation. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open NativeAIR.Challenger + +namespace AiurTests.Transcript + +private def nativeHash (bytes : List UInt8) : Fin 32 → UInt8 := + let digest := Blake3.Rust.hash bytes.toByteArray + fun index => digest.val[index.val]'(by simpa only [digest.property] using index.isLt) + +private def pureHash : Hash32 := NativeAIR.Blake3.hash + +private def readBytes : Reader (List UInt8) := do + return (← takeBytes (← readCount 10000000)).data.toList + +private inductive Event where + | observe (bytes : List UInt8) + | field (value : G) + | bits (count value : Nat) + | byte (value : UInt8) + deriving DecidableEq, Repr + +private def readEvent : Reader Event := do + match ← readNat 1 with + | 0 => return .observe (← readBytes) + | 1 => return .field (← readField) + | 2 => return .bits (← readNat) (← readNat) + | 3 => return .byte (← readNat 1).toUInt8 + | _ => throw "invalid transcript event" + +private def runEvent (state : State) (event : Event) : Except String State := do + match event with + | .observe bytes => return observeBytes state bytes + | .field expected => + unless sampleField pureHash 16 state == sampleField nativeHash 16 state do throw "pure/FFI field sampling differs" + let some (actual, next) := sampleField pureHash 16 state | throw "native transcript field exhausted" + unless actual == expected do throw "native transcript field differs" + return next + | .bits bits expected => + unless sampleBits pureHash bits state == sampleBits nativeHash bits state do throw "pure/FFI bit sampling differs" + let some (actual, next) := sampleBits pureHash bits state | throw "native transcript bit count invalid" + unless actual == expected do throw "native transcript bits differ" + return next + | .byte expected => + unless sampleByte pureHash state == sampleByte nativeHash state do throw "pure/FFI byte sampling differs" + let (actual, next) := sampleByte pureHash state + unless actual == expected do throw "native transcript byte differs" + return next + +private def observed : List Event → List UInt8 × List Event + | .observe bytes :: rest => + let (more, remaining) := observed rest + (bytes ++ more, remaining) + | rest => ([], rest) + +private def stage (expected : List UInt8) (value : ProofCodec.Extension) (events : List Event) : + Except String (List Event) := do + let (bytes, rest) := observed events + unless bytes == expected do throw "native transcript observation schedule differs" + match rest with + | .field c0 :: .field c1 :: rest => + unless c0 == value.c0 && c1 == value.c1 do throw "native transcript extension basis order differs" + return rest + | _ => throw "native transcript extension sample missing" + +private def checkSchedule (key : KeyCodec.Key) (proof : ProofCodec.Data) (claims : List (List G)) + (result : NativeAIR.Transcript.Replay) (events : List Event) : Except String (List Event) := do + let ch := result.challenges + let rest ← stage (NativeAIR.Transcript.prefixBytes key proof claims) ch.beta events + let rest ← stage (ProofCodec.encodeExtension ch.beta) ch.gamma rest + let rest ← stage (ProofCodec.encodeExtension ch.gamma ++ proof.commitments.stage2.flatten ++ + proof.accumulators.flatMap ProofCodec.encodeExtension) ch.alpha rest + stage proof.commitments.quotient.flatten ch.zeta rest + +private def readStreams : Reader Unit := do + unless (← readNat) == 16 do throw "incomplete byte-stream cases" + for seed in [:16] do + let bytes ← readBytes + unless bytes.length == seed * 17 do throw "byte-stream seed length differs" + unless (← readNat) == 80 do throw "incomplete byte-stream operations" + let events ← readList 80 readEvent + let final ← ofExcept (events.foldlM runEvent (initial bytes)) + unless final.pending.length ≤ 32 do throw "byte-stream pending buffer oversized" + +private def readRejections : Reader Unit := do + unless (← readNat) == 16 do throw "incomplete rejection cases" + let mut rejected := 0 + for mask in [:16] do + unless (← readNat 1) == mask do throw "rejection mask differs" + let first ← takeBytes 32 + let later ← takeBytes 32 + let hash : Hash32 := fun input index => + (if input.length == 1 then first else later)[index.val]! + let c0 ← readField + let c1 ← readField + let firstAttempts ← readCount 5 + let secondAttempts ← readCount 4 + unless firstAttempts > 0 && secondAttempts > 0 do throw "zero rejection attempts" + rejected := rejected + firstAttempts + secondAttempts - 2 + let start := initial [mask.toUInt8] + let some (actual0, middle) := sampleField hash firstAttempts start | throw "forced first field exhausted" + let some (actual1, final) := sampleField hash secondAttempts middle | throw "forced second field exhausted" + unless actual0 == c0 && actual1 == c1 do throw "forced canonical/rejected limb differs" + unless (sampleField hash (firstAttempts - 1) start).isNone && + (sampleField hash (secondAttempts - 1) middle).isNone do throw "rejection sampler returned too early" + unless sampleExtension hash 5 start == some (⟨c0, c1⟩, final) do throw "forced extension sample differs" + unless (sampleExtension hash (max firstAttempts secondAttempts - 1) start).isNone do + throw "extension sampler bypassed exhausted coordinate" + let mut state := final + for bits in [0, 1, 7, 31, 32, 63] do + let expected ← readNat + let some (actual, next) := sampleBits hash bits state | throw "forced bit sample invalid" + unless actual == expected do throw "forced sampling continuation differs" + state := next + for invalid in [64, 65, 100] do + unless (sampleBits hash invalid state).isNone do throw "oversized bit sample accepted" + unless rejected == 26 do throw s!"incomplete forced rejection coverage: {rejected}" + let noncanonical : Hash32 := fun _ _ => 255 + unless (sampleField noncanonical 32 (initial [])).isNone do throw "exhausted sampler fabricated a field" + +private def readWitnesses : Reader Unit := do + unless (← readNat) == 48 do throw "incomplete witness cases" + let mut zeroBits := 0 + for _ in [:48] do + let seed ← readBytes + let before ← readField + let bits ← readNat + let witness ← readField + let accepted ← readBool + let after ← readField + let some (actualBefore, state) := sampleField pureHash 16 (initial seed) | throw "witness prelude exhausted" + unless actualBefore == before do throw "witness prelude sample differs" + let some (actual, next) := checkWitness pureHash bits witness state | throw "witness check undefined" + unless actual == accepted do throw "witness acceptance differs" + if bits == 0 then + zeroBits := zeroBits + 1 + unless next == state do throw "zero-bit witness changed pending output" + let some (actualAfter, _) := sampleField pureHash 16 next | throw "witness continuation exhausted" + unless actualAfter == after do throw "witness continuation differs" + unless zeroBits == 8 do throw "incomplete zero-bit witness coverage" + +private def readVerifiers : Reader Unit := do + unless (← readNat) == 40 do throw "incomplete native verifier cases" + let mut acceptedCount := 0 + let mut eventCount := 0 + let mut pcsCount := 0 + for index in [:40] do + let keyBytes := (← readBytes).toByteArray + let proofBytes := (← readBytes).toByteArray + let some key := KeyCodec.decodeCanonical keyBytes | throw "transcript key is not canonical" + let some proof := ProofCodec.decodeCanonical proofBytes | throw "transcript proof is not canonical" + let claims ← readList (← readCount) readValues + let accepted ← readBool + unless accepted == (index % 10 == 0) do throw "native verifier acceptance inventory differs" + let events ← readList (← readCount 100000) readEvent + eventCount := eventCount + events.length + let some result := NativeAIR.Blake3.replay 16 key proof claims | throw "transcript replay exhausted" + unless NativeAIR.Transcript.replay nativeHash 16 key proof claims == some result do + throw "pure/FFI transcript replay differs" + let pcs ← ofExcept (checkSchedule key proof claims result events) + pcsCount := pcsCount + pcs.length + unless !pcs.isEmpty do throw "native PCS continuation missing" + let continued ← ofExcept (pcs.foldlM runEvent result.state) + let all ← ofExcept (events.foldlM runEvent (initial (NativeAIR.Transcript.seed key.parameters))) + unless continued == all do throw "PCS received a different challenger state" + unless NativeAIR.Blake3.replay 32 key proof claims == some result do + throw "larger replay fuel changed native challenges/state" + unless (NativeAIR.Blake3.replay 0 key proof claims).isNone do throw "zero replay fuel accepted" + let some rows := ProofShape.check key proof | throw "native transcript fixture has invalid shape" + if accepted then + acceptedCount := acceptedCount + 1 + unless NativeAIR.Blake3.verifyArithmetic 16 key proof claims rows == some result do + throw "native accepted proof fails transcript-derived arithmetic" + unless acceptedCount == 4 do throw "incomplete accepted transcript proofs" + unless eventCount > 1000 && pcsCount > 500 do throw "incomplete native transcript/PCS calls" + +private def readCorpus : Reader Unit := do + let header := "Aiur transcript v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "transcript snapshot version differs" + readStreams + readRejections + readWitnesses + readVerifiers + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "transcript snapshot has trailing bytes" + +end AiurTests.Transcript + +def main (args : List String) : IO Unit := do + match args with + | [path] => + let bytes ← IO.FS.readBinFile path + match AiurTests.Transcript.readCorpus.run (bytes, 0) with + | .error error => throw (IO.userError error) + | .ok _ => + IO.println "transcript: 1280 byte operations, 16 forced rejection cases and 48 witness checks match" + IO.println "transcript: pure Blake3 matches FFI and 40 native verifier schedules/PCS continuations; 4 accepted proofs satisfy derived arithmetic" + | _ => throw (IO.userError "expected native transcript snapshot") diff --git a/Tests/Aiur/VerifierArithmetic.lean b/Tests/Aiur/VerifierArithmetic.lean new file mode 100644 index 000000000..cd4737579 --- /dev/null +++ b/Tests/Aiur/VerifierArithmetic.lean @@ -0,0 +1,172 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.VerifierAccumulator +import Tests.Aiur.EmissionReader + +/-! Combined comparison with native graph, LogUp and selector calls. The +native test reproduces the verifier's private wiring/fold/recombination; +its constructed openings are arithmetic fixtures, not authenticated proofs. +-/ + +open Aiur Aiur.NativeAIR AiurTests.EmissionReader +open ProofCodec (Extension) + +namespace AiurTests.VerifierArithmetic + +open NativeAIR.VerifierArithmetic + +private def readExtension : Reader Extension := do return ⟨← readField, ← readField⟩ +private def readExtensions : Reader (List Extension) := do readList (← readCount 100000) readExtension +private def readPair : Reader ProofShape.Pair := do return ⟨← readExtensions, ← readExtensions⟩ +private def readClaims : Reader (List (List G)) := do readList (← readCount) readValues +private def readChallenges : Reader Challenges := do + return ⟨← readExtension, ← readExtension, ← readExtension, ← readExtension⟩ + +private def readOpening (circuits : Array KeyCodec.Circuit) : Reader ProofShape.Row := do + let index ← readNat + let some circuit := circuits[index]? | throw "opening circuit index out of bounds" + let bits ← readNat + unless bits < 256 do throw "opening exponent is not a byte" + let main ← readPair + let stage2 ← readPair + let preprocessed ← readOption readPair + let quotient ← readExtensions + let accumulator ← readExtension + let row : ProofShape.Row := ⟨index, circuit, bits.toUInt8, main, stage2, preprocessed, quotient, accumulator⟩ + unless row.fits ⟨1, 0, 0, 1, 64, 0, 0⟩ do throw "opening fixture is not shaped" + unless row.preprocessed.isNone == (row.circuit.preprocessedWidth == 0) do throw "opening preprocessed slot differs" + return row + +private def readEvaluation (challenges : Challenges) (row : ProofShape.Row) (entering : Extension) : Reader (Nat × Bool) := do + let selectors : NativeAIR.Domain.Selectors Extension := + ⟨← readExtension, ← readExtension, ← readExtension, ← readExtension⟩ + let publics := (← readExtensions).toArray + let delta := (← readExtensions).toArray + let nodes := (← readExtensions).toArray + let user ← readExtensions + let lookups ← readExtensions + let composition ← readExtension + let quotient ← readExtension + let accepted ← readBool + let some result := evaluate challenges row entering | throw "opening arithmetic unexpectedly undefined" + unless result.domain.val == row.logDegree.toNat && result.selectors == selectors do throw "opening domain/selectors differ" + unless NativeAIR.VerifierArithmetic.publics challenges entering row.accumulator == publics do + throw "opening public coordinates differ" + unless deltaScaled result.domain entering row.accumulator == delta do throw "opening normalized delta differs" + unless result.nodeValues == nodes do throw "opening graph node values differ" + unless result.userValues == user && result.lookupValues == lookups do throw "opening constraint order/coordinates differ" + unless result.constraints.length == row.circuit.constraintCount do throw "opening constraint count differs" + unless Quotient.composition challenges.alpha result.constraints == composition do throw "opening Horner fold differs" + unless result.quotientValue == quotient do throw "opening quotient recombination differs" + unless result.accepts challenges.alpha == accepted && check challenges row entering == some accepted do + throw "opening arithmetic acceptance differs" + unless (composition == NativeAIR.Domain.vanishing result.domain challenges.zeta * quotient) == accepted do + throw "opening quotient polynomial identity differs" + return (nodes.size, accepted) + +private def checkGuards (challenges : Challenges) (row : ProofShape.Row) (entering : Extension) (accepted : Bool) : Reader Unit := do + let badCurrent := { row with stage2 := { row.stage2 with current := [] } } + let badNext := { row with stage2 := { row.stage2 with next := [] } } + let badQuotient := { row with quotient := row.quotient ++ [0] } + let badLog := { row with logDegree := 33 } + let badRoot := { row with circuit := { row.circuit with graph := + { row.circuit.graph with zeros := row.circuit.graph.zeros ++ [row.circuit.graph.nodes.length] } } } + for malformed in [badCurrent, badNext, badQuotient, badLog, badRoot] do + unless (evaluate challenges malformed entering).isNone do throw "malformed opening read accepted" + let some domain := NativeAIR.Domain.ofLogSize row.logDegree.toNat | throw "opening domain missing" + for pole in [1, Extension.ofBase (NativeAIR.Domain.lastPoint domain)] do + unless (evaluate { challenges with zeta := pole } row entering).isNone do throw "opening selector pole accepted" + if row.preprocessed.isSome then + unless (evaluate challenges { row with preprocessed := none } entering).isNone do + throw "missing preprocessed opening accepted" + if accepted then + let first :: rest := row.quotient | throw "empty shaped quotient" + unless check challenges { row with quotient := (first + 1) :: rest } entering == some false do + throw "altered opening quotient accepted" + +private def readCorpus : Reader Unit := do + let header := "Aiur verifier arithmetic v1\n".toUTF8 + unless (← takeBytes header.size) == header do throw "verifier arithmetic snapshot version differs" + unless (← readNat) == 10 do throw "incomplete opening circuits" + let circuits := (← readList 10 do + let bytes ← takeBytes (← readCount 1000000) + let some (circuit, []) := KeyCodec.readCircuit bytes.data.toList | throw "invalid opening circuit" + return circuit).toArray + unless (← readNat) == 960 do throw "incomplete opening assignments" + let mut nodeCount := 0 + let mut acceptedCount := 0 + for index in [:circuits.size] do + let some circuit := circuits[index]? | throw "missing opening circuit" + let largest := 31 - (ProofShape.quotientDegree circuit).log2 + for bits in [0, 1, 2, 4, 8, 16, 24, largest] do + for seed in [:12] do + unless (← readNat) == seed do throw "opening seed order differs" + let challenges ← readChallenges + let entering ← readExtension + let row ← readOpening circuits + unless row.circuitIndex == index && row.logDegree.toNat == bits do throw "opening fixture order differs" + let (nodes, accepted) ← readEvaluation challenges row entering + unless accepted == (seed % 2 == 0) do throw "opening acceptance inventory differs" + nodeCount := nodeCount + nodes + if accepted then acceptedCount := acceptedCount + 1 + checkGuards challenges row entering accepted + unless nodeCount == 32064 && acceptedCount == 480 do throw "incomplete opening node/acceptance coverage" + unless (← readNat) == 72 do throw "incomplete claim assignments" + let mut definedClaims := 0 + for seed in [:12] do + for count in [0, 1, 2, 3, 7, 16] do + let challenges ← readChallenges + let claims ← readClaims + unless claims.length == count do throw "public claim count differs" + for claim in claims do + unless claimMessage challenges claim == (← readExtension) do throw "public claim compression differs" + let expected ← readOption readExtension + unless initialAccumulator challenges claims == expected do throw "initial accumulator differs" + unless expected.isSome == (seed % 3 != 0 || count == 0) do throw "public claim pole inventory differs" + if expected.isSome then definedClaims := definedClaims + 1 + unless (verify challenges claims []).isNone do throw "empty active circuit list accepted" + unless definedClaims == 52 do throw "incomplete public claim pole coverage" + unless (← readNat) == 48 do throw "incomplete accumulator chains" + let mut acceptedChains := 0 + let mut unbalancedChains := 0 + let mut rejectedChains := 0 + for _seed in [:12] do + for count in [1, 2, 3, 10] do + let challenges ← readChallenges + let claims ← readClaims + unless (← readNat) == count do throw "accumulator chain length differs" + let some initial := initialAccumulator challenges claims | throw "unexpected chain claim pole" + let mut entering := initial + let mut rows := [] + for _ in [:count] do + let row ← readOpening circuits + let _ ← readEvaluation challenges row entering + rows := rows ++ [row] + entering := row.accumulator + let expected ← readOption readBool + unless verify challenges claims rows == expected do throw "ordered accumulator chain differs" + match expected with + | some true => acceptedChains := acceptedChains + 1 + | some false => unbalancedChains := unbalancedChains + 1 + | none => rejectedChains := rejectedChains + 1 + unless acceptedChains == 16 && unbalancedChains == 16 && rejectedChains == 16 do + throw "incomplete final/interior accumulator rejection coverage" + let (bytes, cursor) ← get + unless cursor == bytes.size do throw "verifier arithmetic snapshot has trailing bytes" + +def run (path : System.FilePath) : IO Unit := do + match readCorpus.run ((← IO.FS.readBinFile path), 0) with + | .error error => throw (IO.userError error) + | .ok _ => + IO.println "verifier arithmetic: 960 openings, 32064 node values and malformed reads/quotients/poles match" + IO.println "verifier accumulators: 52 defined/20 rejected claim cases and 16 accepted/16 unbalanced/16 rejected chains match" + +end AiurTests.VerifierArithmetic + +def main (args : List String) : IO Unit := do + match args with + | [path] => AiurTests.VerifierArithmetic.run path + | _ => throw (IO.userError "expected native verifier arithmetic snapshot") diff --git a/Tests/Aiur/backend-foundation-review.md b/Tests/Aiur/backend-foundation-review.md new file mode 100644 index 000000000..b7b21ccb4 --- /dev/null +++ b/Tests/Aiur/backend-foundation-review.md @@ -0,0 +1,52 @@ +# Aiur proof migration audit + +The source reference is `126000646da3324c26bd21a323b75819b8e2cc21` on +`jcb/monorepo`. The destination retains the newer kernel base and the +optimized Aiur implementation, including checked component layouts. This +review covers the migrated component boundary, not completed IxVM soundness. + +The reviewed report contains 1,574 roots, 988 premise definitions and +197 recursion workers. Compared with the source report, 2,607 sections are +unchanged. No theorem root was removed. There are 58 changed root statements, +21 changed premise sections and one changed worker; 30 roots, 34 premises +and eight workers were added. One obsolete premise and seven workers from +the source implementation were removed. + +| Changed boundary | Reason and reviewed scope | +| --- | --- | +| `opLayout_lookupUsage`, `opsLayout_lookupUsage`, control/block lookup usage, allocation branch lemmas and emitter allocation | The generic emitter uses six gap columns and four logical lookup slots per constrained call. These results now require an empty call-rank table. General allocation uses `Op.allocationFor`, covering zero, boundary and ordered ranks. | +| `finishCompilation`/`compile` lookup layout, lookup bounds, computed layout and column bounds; their `Backend` extraction, compilation and graph corollaries | The optimized component pass changes physical layouts. The migrated generic corollaries explicitly require `source.componentRanks = false`. This premise marks the remaining component-mode extraction obligation. It is not an assertion that the optimized IxVM already satisfies the old layout. | +| `emitCall_reflects`, valued/symbolic call emission, `CallsEmitted`, `TracksCalls`, `Op.allocation` | The child rank is `parent + 1 + packedGap`; there is no separate child column or order constraint. `EquationAvailable` permits a proved zero or an emitted equation. The derived order polynomial is proved identically zero, and satisfaction still follows in both cases. | +| `rewriteOp_layout`, `matchLayout_rewrite`, `rewriteCtrl_layout`, `rewriteBlock_layout` | Function renaming preserves layout when the selected call modes agree under the renaming. The statements compare executions from a supplied state with `LayoutRenaming`; the empty mode table satisfies this condition. | +| `SameCode.mk`, compilation, deduplication and grouping definitions | Component relayout changes continuation metadata. `SameCode` now compares complete block evaluations for every ambient program, fuel and state, while retaining function count and input arity. Relayout's proof establishes this relation directly. Deduplication and grouping retain the new metadata fields. | +| Valued and symbolic `circuitEmission` | An empty circuit emits no rank-range messages. This matches the native builder and was checked against empty-circuit, row and compiled-key corpora. | +| All changed `CompiledKey` constructors, success/selection/reflection lemmas, `CompiledBackend.circuits_bound`, `byte_graphs` and `circuits_preprocessed_absent` | Key reconstruction applies production lookup retuning using `key.parameters.logBlowup`. Success lemmas retain graph and physical dimensions and prove validity; fixed baseline grouping is no longer a conclusion. Exact key equality includes the selected grouping and degree. `circuit_success` now also uses `propext`; its prior axiom set was only `Quot.sound`. | +| Hoisting/inlining premises and the changed `hoistLetsAux` worker | The destination's fresh-name supply, function/argument freshening and unary/binary/list sequencing are retained. The obsolete `bindArguments` premise is replaced with the actual definitions. Targeted fixes preserve value-before-array update order and retain normal calls for explicit-return callees. Reference/native effect-order and return-boundary cases pass; general source reflection remains open. | + +The new roots prove layout context and arity preservation, complete evaluation +preservation by relayout, empty-table specialization, mode-compatible +renaming, the derived call-order identity, and preservation of authored fields +by lookup retuning. Their premise bodies include the actual checked component +assignment and the total cost selector with machine-size and overflow guards. + +The removed workers are the old `blockLayout`/`ctrlLayout` traversals, +`Pattern.freshenBindings`, `Pattern.maxNameLength`, `Term.bindArguments`, +`Term.freshenWith`, and `Term.maxNameLength`. Their replacements are the +two component DFS workers, `relayoutBlock`/`relayoutCtrl`, `Pattern.locals`, +`Pattern.mapLocals`, `Term.freshBound`, and `Term.freshen`. Each worker is +followed to its checked safe source declaration and its implementation is +included in the frozen report. The DFS proposal is independently validated +before it affects layout; the proof does not assume the proposal is correct. + +The exact root axiom sets contain only ordinary Lean logic. The project +runtime boundary still contains `AiurSystem.build`, `AiurSystem.verify`, +`AiurSystem.vkBytes`, and `Proof.ofBytesChecked`; the same three partial +Hashable/Repr sources remain inventoried. There are no additional unsafe +runtime definitions, replacement implementations or excluded `Ix.Compiler` +imports. These runtime checks do not prove native verifier refinement. + +Validation includes all 40 native/model corpora, four unchanged compiler +compatibility snapshots, and a retuned-key corpus covering 12 systems, +180 circuits, 720 assignments and 168 rejected validly encoded alterations. +The full `check-aiur` gate additionally compares the current report byte for +byte with the frozen manifest. diff --git a/Tests/Aiur/backend-foundation.txt b/Tests/Aiur/backend-foundation.txt new file mode 100644 index 000000000..77e80fc36 --- /dev/null +++ b/Tests/Aiur/backend-foundation.txt @@ -0,0 +1,27004 @@ +ROOT Aiur.AIR.callOrderConstraint_derived +∀ (parent gap : Aiur.G), Aiur.AIR.callOrderConstraint parent (parent + 1 + gap) gap = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.EquationAvailable.mono +∀ {first last : List Aiur.G} {value : Aiur.G}, + Aiur.AIR.EquationAvailable first value → first ⊆ last → Aiur.AIR.EquationAvailable last value +AXIOMS [propext] +ROOT Aiur.AIR.EquationAvailable.satisfied +∀ {equations : List Aiur.G} {value : Aiur.G}, + Aiur.AIR.EquationAvailable equations value → (∀ (value : Aiur.G), value ∈ equations → value = 0) → value = 0 +AXIOMS [propext] +ROOT Aiur.Bytecode.Op.allocationFor_empty +∀ (op : Aiur.Bytecode.Op) (degrees : Array Nat), + Aiur.Bytecode.Op.allocationFor #[] degrees op = Aiur.Bytecode.Op.allocation degrees op +AXIOMS [propext] +ROOT Aiur.Bytecode.Eval.SameCode.refl +∀ (t : Aiur.Bytecode.Toplevel), Aiur.Bytecode.Eval.SameCode t t +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Eval.SameCode.ofFunctionsEq +∀ {a b : Aiur.Bytecode.Toplevel}, a.functions = b.functions → Aiur.Bytecode.Eval.SameCode a b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Eval.SameCode.trans +∀ {a b c : Aiur.Bytecode.Toplevel}, + Aiur.Bytecode.Eval.SameCode a b → Aiur.Bytecode.Eval.SameCode b c → Aiur.Bytecode.Eval.SameCode a c +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.inlineCalls_componentRanks +∀ {source inlined : Aiur.Source.Toplevel}, + source.inlineCalls = Except.ok inlined → inlined.componentRanks = source.componentRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opLayout_callRanks +∀ (op : Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.callRanks = initial.callRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opLayout_context +∀ (op : Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.context = initial.context +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opsLayout_context +∀ (ops : Array Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.context = initial.context +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opsLayout_inputSize +∀ (ops : Array Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.functionLayout.inputSize = + initial.functionLayout.inputSize +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.blockLayout_eq_discard_relayout +∀ (block : Aiur.Bytecode.Block), + Aiur.Concrete.Bytecode.blockLayout block = discard (Aiur.Concrete.Bytecode.relayoutBlock block) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.ctrlLayout_eq_def +∀ (ctrl : Aiur.Bytecode.Ctrl), + Aiur.Concrete.Bytecode.ctrlLayout ctrl = + match ctrl with + | Aiur.Bytecode.Ctrl.match a branches fallback => do + let shared ← Aiur.Concrete.Bytecode.getSharedData + let degrees ← Aiur.Concrete.Bytecode.getDegrees + let maximal ← + Array.foldlM (fun acc pair => Aiur.Concrete.Bytecode.summaryStep✝ shared degrees acc pair.val) shared + branches.attach + have __do_jp : Aiur.Concrete.Bytecode.SharedData → Aiur.Concrete.Bytecode.LayoutM Unit := fun final => + Aiur.Concrete.Bytecode.setSharedData final + match fallback with + | none => do + let final ← pure maximal + __do_jp final + | some block => do + Aiur.Concrete.Bytecode.setSharedData shared + Aiur.Concrete.Bytecode.bumpAuxiliaries branches.size + Aiur.Concrete.Bytecode.blockLayout block + let used ← Aiur.Concrete.Bytecode.getSharedData + Aiur.Concrete.Bytecode.setDegrees degrees + let final ← pure (maximal.maximals used) + __do_jp final + | Aiur.Bytecode.Ctrl.return a a_1 => Aiur.Concrete.Bytecode.bumpSelectors + | Aiur.Bytecode.Ctrl.yield a a_1 => Aiur.Concrete.Bytecode.bumpSelectors + | Aiur.Bytecode.Ctrl.matchContinue index branches fallback outputs sharedAuxiliaries sharedLookups cont => do + Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback) + Aiur.Concrete.Bytecode.bumpAuxiliaries outputs + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate outputs 1) + Aiur.Concrete.Bytecode.blockLayout cont +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.relayoutBlock_preserves_execution +∀ (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState) (t : Aiur.Bytecode.Toplevel) + (fuel : Nat) (st : Aiur.Bytecode.Eval.EvalState), + Aiur.Bytecode.Eval.evalBlock t fuel (StateT.run (Aiur.Concrete.Bytecode.relayoutBlock block) initial).fst st = + Aiur.Bytecode.Eval.evalBlock t fuel block st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.relayoutCtrl_context +∀ (ctrl : Aiur.Bytecode.Ctrl) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.relayoutCtrl ctrl) initial).snd.context = initial.context +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.relayoutBlock_context +∀ (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.relayoutBlock block) initial).snd.context = initial.context +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.relayoutCtrl_inputSize +∀ (ctrl : Aiur.Bytecode.Ctrl) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.relayoutCtrl ctrl) initial).snd.functionLayout.inputSize = + initial.functionLayout.inputSize +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.relayoutBlock_inputSize +∀ (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.relayoutBlock block) initial).snd.functionLayout.inputSize = + initial.functionLayout.inputSize +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.relayoutCtrl_callRanks +∀ (ctrl : Aiur.Bytecode.Ctrl) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.relayoutCtrl ctrl) initial).snd.callRanks = initial.callRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.relayoutBlock_callRanks +∀ (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.relayoutBlock block) initial).snd.callRanks = initial.callRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.blockLayout_callRanks +∀ (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) initial).snd.callRanks = initial.callRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.ctrlLayout_callRanks +∀ (ctrl : Aiur.Bytecode.Ctrl) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout ctrl) initial).snd.callRanks = initial.callRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.withCallComponents_sameCode +∀ (top : Aiur.Bytecode.Toplevel), Aiur.Bytecode.Eval.SameCode top.withCallComponents top +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opLayout_genericAllocation +∀ (op : Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = #[] → + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.degrees = + initial.degrees ++ (Aiur.Bytecode.Op.allocation initial.degrees op).degrees ∧ + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.functionLayout.auxiliaries = + initial.functionLayout.auxiliaries + (Aiur.Bytecode.Op.allocation initial.degrees op).auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchStep_callRanks +∀ (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) (acc : Aiur.Concrete.Bytecode.SharedData) + (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc block) initial).snd.callRanks = + initial.callRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchFold_callRanks +∀ {α : Type} (items : List α) (blockOf : α → Aiur.Bytecode.Block) (shared : Aiur.Concrete.Bytecode.SharedData) + (degrees : Array Nat) (acc : Aiur.Concrete.Bytecode.SharedData) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run + (List.foldlM (fun acc item => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc (blockOf item)) + acc items) + initial).snd.callRanks = + initial.callRanks +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.layoutRenaming_empty +∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx), Aiur.Concrete.Bytecode.LayoutRenaming rename #[] +AXIOMS [propext] +ROOT Aiur.NativeAIR.LookupGroups.withGroup_authored +∀ {circuit result : Aiur.NativeAIR.KeyCodec.Circuit} {group : Nat}, + Aiur.NativeAIR.LookupGroups.withGroup circuit group = some result → + Aiur.NativeAIR.LookupGroups.AuthoredFields result = Aiur.NativeAIR.LookupGroups.AuthoredFields circuit +AXIOMS [] +ROOT Aiur.NativeAIR.LookupGroups.retune_authored +∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit) (blowup : Nat), + Aiur.NativeAIR.LookupGroups.AuthoredFields (Aiur.NativeAIR.LookupGroups.retune circuit blowup) = + Aiur.NativeAIR.LookupGroups.AuthoredFields circuit +AXIOMS [propext, Quot.sound] +ROOT Aiur.G.ofNat_n +∀ (a : Aiur.G), Aiur.G.ofNat a.n = a +AXIOMS [propext] +ROOT Aiur.G.mul_one +∀ (a : Aiur.G), a * 1 = a +AXIOMS [propext] +ROOT Aiur.G.mul_zero +∀ (a : Aiur.G), a * 0 = 0 +AXIOMS [propext] +ROOT Aiur.AIR.inactive_multiplicity_zero +∀ {multiplicity selector : Aiur.G}, + selector = 0 → Aiur.AIR.activityConstraint multiplicity selector = 0 → multiplicity = 0 +AXIOMS [propext] +ROOT Aiur.AIR.nonzero_multiplicity_active +∀ {multiplicity selector : Aiur.G}, + Aiur.AIR.activityConstraint multiplicity selector = 0 → multiplicity ≠ 0 → selector ≠ 0 +AXIOMS [propext] +ROOT Aiur.AIR.active_satisfies +∀ (multiplicity : Aiur.G), Aiur.AIR.activityConstraint multiplicity 1 = 0 +AXIOMS [propext] +ROOT Aiur.Bytecode.Eval.runFunction_sameCode +∀ {a b : Aiur.Bytecode.Toplevel}, + Aiur.Bytecode.Eval.SameCode a b → + ∀ (function : Aiur.Bytecode.FunIdx) (args : Array Aiur.G) (io : Aiur.IOBuffer) (fuel : Nat), + Aiur.Bytecode.Eval.runFunction a function args io fuel = Aiur.Bytecode.Eval.runFunction b function args io fuel +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_sameCode +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx), + Aiur.Bytecode.Eval.SameCode (Aiur.finishCompilation source raw names).bytecode raw.deduplicate.fst +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_reflects +∀ {source : Aiur.Source.Toplevel} {raw : Aiur.Bytecode.Toplevel} {names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx} + {function : Aiur.Bytecode.FunIdx} {args : Array Aiur.G} {io : Aiur.IOBuffer} {fuel : Nat} + {result : Array Aiur.G × Aiur.IOBuffer}, + Aiur.Bytecode.Eval.runFunction (Aiur.finishCompilation source raw names).bytecode function args io fuel = + Except.ok result → + Aiur.Bytecode.Eval.runFunction raw.deduplicate.fst function args io fuel = Except.ok result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.compile_artifact_of_ok +∀ {source : Aiur.Source.Toplevel} {compiled : Aiur.CompiledToplevel}, + source.compile = Except.ok compiled → + ∃ inlined typed concrete raw names, + source.inlineCalls = Except.ok inlined ∧ + inlined.checkAndSimplify = Except.ok typed ∧ + typed.concretize = Except.ok concrete ∧ + concrete.toBytecode = Except.ok (raw, names) ∧ compiled = Aiur.finishCompilation inlined raw names +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.build +(selection : Aiur.BoundVerifier.Selection) → Except String (Aiur.BoundVerifier.Backend selection) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.verify_success +∀ {selection : Aiur.BoundVerifier.Selection} {backend : Aiur.BoundVerifier.Backend selection} {input : Array Aiur.G} + {bytes : ByteArray}, + Aiur.BoundVerifier.verify backend input bytes = Except.ok () → + input.size = selection.inputSize ∧ + ∃ proof, + Aiur.Proof.ofBytesChecked bytes = Except.ok proof ∧ + backend.system.verify (Aiur.buildClaim selection.function input selection.success) proof = Except.ok () +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.compilation_stages +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + ∃ initial, + selection.source.compile = Except.ok initial ∧ + (if selection.groups.isEmpty = true then Except.ok initial else initial.groupFunctions selection.groups) = + Except.ok backend.compiled +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.CompiledToplevel.groupFunctions_preserves_code +∀ {before after : Aiur.CompiledToplevel} {groups : Array (String × Array String)}, + before.groupFunctions groups = Except.ok after → + after.source = before.source ∧ + after.nameMap = before.nameMap ∧ + after.bytecode.functions = before.bytecode.functions ∧ after.bytecode.memorySizes = before.bytecode.memorySizes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.CompiledToplevel.groupFunctions_sameCode +∀ {before after : Aiur.CompiledToplevel} {groups : Array (String × Array String)}, + before.groupFunctions groups = Except.ok after → Aiur.Bytecode.Eval.SameCode after.bytecode before.bytecode +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.CompiledToplevel.groupFunctions_preserves_execution +∀ {before after : Aiur.CompiledToplevel} {groups : Array (String × Array String)}, + before.groupFunctions groups = Except.ok after → + ∀ (function : Aiur.Bytecode.FunIdx) (args : Array Aiur.G) (io : Aiur.IOBuffer) (fuel : Nat), + Aiur.Bytecode.Eval.runFunction after.bytecode function args io fuel = + Aiur.Bytecode.Eval.runFunction before.bytecode function args io fuel +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.reference_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + (function : Aiur.Bytecode.FunIdx) (args : Array Aiur.G) (io : Aiur.IOBuffer) (fuel : Nat), + ∃ initial, + selection.source.compile = Except.ok initial ∧ + Aiur.Bytecode.Eval.runFunction backend.compiled.bytecode function args io fuel = + Aiur.Bytecode.Eval.runFunction initial.bytecode function args io fuel +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.execution_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) {args : Array Aiur.G} + {io : Aiur.IOBuffer} {fuel : Nat} {result : Array Aiur.G × Aiur.IOBuffer}, + Aiur.Bytecode.Eval.runFunction backend.compiled.bytecode selection.function args io fuel = Except.ok result → + ∃ inlined typed concrete raw names, + selection.source.inlineCalls = Except.ok inlined ∧ + inlined.checkAndSimplify = Except.ok typed ∧ + typed.concretize = Except.ok concrete ∧ + concrete.toBytecode = Except.ok (raw, names) ∧ + Aiur.Bytecode.Eval.runFunction raw.deduplicate.fst selection.function args io fuel = Except.ok result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Ctrl.beq_eq_true_iff +∀ (left right : Aiur.Bytecode.Ctrl), left.beq right = true ↔ left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.beq_eq_true_iff +∀ (left right : Aiur.Bytecode.Block), left.beq right = true ↔ left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Eval.runFunction_renamed_iff +∀ {a b : Aiur.Bytecode.Toplevel} {rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx}, + Aiur.Bytecode.Eval.RenamedCode a b rename → + ∀ (function : Aiur.Bytecode.FunIdx) (args : Array Aiur.G) (io : Aiur.IOBuffer) (fuel : Nat) + (result : Array Aiur.G × Aiur.IOBuffer), + Aiur.Bytecode.Eval.runFunction a function args io fuel = Except.ok result ↔ + Aiur.Bytecode.Eval.runFunction b (rename function) args io fuel = Except.ok result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Eval.deduplicate_preserves_execution +∀ (source : Aiur.Bytecode.Toplevel) (function : Aiur.Bytecode.FunIdx) (args : Array Aiur.G) (io : Aiur.IOBuffer) + (fuel : Nat) (result : Array Aiur.G × Aiur.IOBuffer), + Aiur.Bytecode.Eval.runFunction source function args io fuel = Except.ok result ↔ + Aiur.Bytecode.Eval.runFunction source.deduplicate.fst (source.deduplicate.snd function) args io fuel = + Except.ok result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_preserves_execution +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx) + (function : Aiur.Bytecode.FunIdx) (args : Array Aiur.G) (io : Aiur.IOBuffer) (fuel : Nat) + (result : Array Aiur.G × Aiur.IOBuffer), + Aiur.Bytecode.Eval.runFunction raw function args io fuel = Except.ok result ↔ + Aiur.Bytecode.Eval.runFunction (Aiur.finishCompilation source raw names).bytecode (raw.deduplicate.snd function) + args io fuel = + Except.ok result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_nameMap_image +∀ {source : Aiur.Source.Toplevel} {raw : Aiur.Bytecode.Toplevel} {names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx} + {name : Name} {function : Aiur.Bytecode.FunIdx}, + (Aiur.finishCompilation source raw names).getFuncIdx name = some function → + ∃ original, names[{ toName := name }]? = some original ∧ raw.deduplicate.snd original = function +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.execution_reflects_raw +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) {args : Array Aiur.G} + {io : Aiur.IOBuffer} {fuel : Nat} {result : Array Aiur.G × Aiur.IOBuffer}, + Aiur.Bytecode.Eval.runFunction backend.compiled.bytecode selection.function args io fuel = Except.ok result → + ∃ inlined typed concrete raw names original, + selection.source.inlineCalls = Except.ok inlined ∧ + inlined.checkAndSimplify = Except.ok typed ∧ + typed.concretize = Except.ok concrete ∧ + concrete.toBytecode = Except.ok (raw, names) ∧ + names[{ toName := selection.entrypoint }]? = some original ∧ + raw.deduplicate.snd original = selection.function ∧ + Aiur.Bytecode.Eval.runFunction raw original args io fuel = Except.ok result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_restoreTailMatches +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (term : Aiur.Source.Term) (bindings : Aiur.Source.Eval.Bindings) + (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings term st = + Aiur.Source.Eval.interp decls fuel bindings term.restoreTailMatches st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_wrapLets +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (frames : List (Aiur.Pattern × Aiur.Source.Term)) (body : Aiur.Source.Term) + (bindings : Aiur.Source.Eval.Bindings) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings (Aiur.Source.Term.wrapLets frames body) st = do + let __x ← Aiur.Source.Eval.evalFrames decls fuel frames bindings st + match __x with + | (bindings, st) => Aiur.Source.Eval.interp decls fuel bindings body st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.evalFrames_append +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (first rest : List (Aiur.Pattern × Aiur.Source.Term)) + (bindings : Aiur.Source.Eval.Bindings) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.evalFrames decls fuel (first ++ rest) bindings st = do + let __x ← Aiur.Source.Eval.evalFrames decls fuel first bindings st + match __x with + | (bindings, st) => Aiur.Source.Eval.evalFrames decls fuel rest bindings st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_peelLets +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (term : Aiur.Source.Term) (bindings : Aiur.Source.Eval.Bindings) + (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings term st = do + let __x ← Aiur.Source.Eval.evalFrames decls fuel term.peelLets.fst bindings st + match __x with + | (bindings, st) => Aiur.Source.Eval.interp decls fuel bindings term.peelLets.snd st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_ret_wrapLets +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (frames : List (Aiur.Pattern × Aiur.Source.Term)) (body : Aiur.Source.Term) + (bindings : Aiur.Source.Eval.Bindings) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings (Aiur.Source.Term.wrapLets frames body).ret st = + Aiur.Source.Eval.interp decls fuel bindings (Aiur.Source.Term.wrapLets frames body.ret) st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_ioWrite_sequence +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (channel data continuation : Aiur.Source.Term) + (bindings : Aiur.Source.Eval.Bindings) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings (channel.ioWrite data continuation) st = + Aiur.Source.Eval.interp decls fuel bindings + (Aiur.Source.Term.let Aiur.Pattern.wildcard (channel.ioWrite data Aiur.Source.Term.unit) continuation) st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_debug_sequence +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (label : String) (value : Option Aiur.Source.Term) + (continuation : Aiur.Source.Term) (bindings : Aiur.Source.Eval.Bindings) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings (Aiur.Source.Term.debug label value continuation) st = + Aiur.Source.Eval.interp decls fuel bindings + (Aiur.Source.Term.let Aiur.Pattern.wildcard (Aiur.Source.Term.debug label value Aiur.Source.Term.unit) + continuation) + st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_assertEq_sequence +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (first second : Aiur.Source.Term) (message : Option String) + (continuation : Aiur.Source.Term) (bindings : Aiur.Source.Eval.Bindings) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings (first.assertEq second message continuation) st = + Aiur.Source.Eval.interp decls fuel bindings + (Aiur.Source.Term.let Aiur.Pattern.wildcard (first.assertEq second message Aiur.Source.Term.unit) continuation) st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_ioSetInfo_sequence +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (channel key index length continuation : Aiur.Source.Term) + (bindings : Aiur.Source.Eval.Bindings) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings (channel.ioSetInfo key index length continuation) st = + Aiur.Source.Eval.interp decls fuel bindings + (Aiur.Source.Term.let Aiur.Pattern.wildcard (channel.ioSetInfo key index length Aiur.Source.Term.unit) + continuation) + st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Eval.interp_app_mode +∀ (decls : Aiur.Source.Decls) (fuel : Nat) (bindings : Aiur.Source.Eval.Bindings) (global : Aiur.Global) + (args : List Aiur.Source.Term) (before after : Aiur.Source.CallMode) (st : Aiur.Source.Eval.EvalState), + Aiur.Source.Eval.interp decls fuel bindings (Aiur.Source.Term.app global args before) st = + Aiur.Source.Eval.interp decls fuel bindings (Aiur.Source.Term.app global args after) st +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.memoryPointerCycle_valid +Aiur.AIR.MemoryRowsValid 1 (Aiur.AIR.memoryPointerCycle Aiur.gSize.toNat) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.memoryPointerCycle_inconsistent +∃ i j, + (Aiur.AIR.memoryPointerCycle Aiur.gSize.toNat)[i].selector = 1 ∧ + (Aiur.AIR.memoryPointerCycle Aiur.gSize.toNat)[j].selector = 1 ∧ + (Aiur.AIR.memoryPointerCycle Aiur.gSize.toNat)[i].pointer = + (Aiur.AIR.memoryPointerCycle Aiur.gSize.toNat)[j].pointer ∧ + (Aiur.AIR.memoryPointerCycle Aiur.gSize.toNat)[i].contents ≠ + (Aiur.AIR.memoryPointerCycle Aiur.gSize.toNat)[j].contents +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.n_ofNat +∀ (n : Nat), (Aiur.G.ofNat n).n = n % Aiur.gSize.toNat +AXIOMS [propext] +ROOT Aiur.G.sub_eq_zero_iff +∀ (a b : Aiur.G), a - b = 0 ↔ a = b +AXIOMS [propext, Quot.sound] +ROOT Aiur.G.n_add +∀ (a b : Aiur.G), (a + b).n = (a.n + b.n) % Aiur.gSize.toNat +AXIOMS [propext] +ROOT Aiur.G.n_mul +∀ (a b : Aiur.G), (a * b).n = a.n * b.n % Aiur.gSize.toNat +AXIOMS [propext] +ROOT Aiur.AIR.packRank_lt +∀ (bytes : Fin 6 → Aiur.G), (∀ (i : Fin 6), (bytes i).n < 256) → (Aiur.AIR.packRank bytes).n < Aiur.AIR.callRankBound +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.call_order_strict +∀ {parent child gap : Aiur.G}, + parent.n < Aiur.AIR.callRankBound → + child.n < Aiur.AIR.callRankBound → + gap.n < Aiur.AIR.callRankBound → Aiur.AIR.callOrderConstraint parent child gap = 0 → parent.n < child.n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.call_order_irrefl +∀ (rank gap : Aiur.G), + rank.n < Aiur.AIR.callRankBound → gap.n < Aiur.AIR.callRankBound → Aiur.AIR.callOrderConstraint rank rank gap ≠ 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.active_call_order_strict +∀ {selector parent child gap : Aiur.G}, + selector = 1 → + parent.n < Aiur.AIR.callRankBound → + child.n < Aiur.AIR.callRankBound → + gap.n < Aiur.AIR.callRankBound → + selector * Aiur.AIR.callOrderConstraint parent child gap = 0 → parent.n < child.n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.packed_call_order_strict +∀ (parent child gap : Fin 6 → Aiur.G), + (∀ (i : Fin 6), (parent i).n < 256) → + (∀ (i : Fin 6), (child i).n < 256) → + (∀ (i : Fin 6), (gap i).n < 256) → + Aiur.AIR.callOrderConstraint (Aiur.AIR.packRank parent) (Aiur.AIR.packRank child) (Aiur.AIR.packRank gap) = 0 → + (Aiur.AIR.packRank parent).n < (Aiur.AIR.packRank child).n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.call_relation_wellFounded +∀ {α : Sort u} (rank : α → Aiur.G), + (∀ (node : α), (rank node).n < Aiur.AIR.callRankBound) → + ∀ (calls : α → α → Prop), + (∀ (child parent : α), + calls child parent → + ∃ gap, gap.n < Aiur.AIR.callRankBound ∧ Aiur.AIR.callOrderConstraint (rank parent) (rank child) gap = 0) → + WellFounded calls +AXIOMS [propext, Quot.sound] +ROOT Aiur.G.zero_add +∀ (a : Aiur.G), 0 + a = a +AXIOMS [propext] +ROOT Aiur.G.ofNat_ne_zero_of_lt +∀ {n : Nat}, 0 < n → n < Aiur.gSize.toNat → Aiur.G.ofNat n ≠ 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.characteristic_queries_balance +∀ {α : Type u_1} [inst : DecidableEq α] (message : α), + Aiur.AIR.ExactLookupBalance (List.replicate Aiur.gSize.toNat message) [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.suppliedWeight_nonzero_provider +∀ {α : Type u_1} [inst : DecidableEq α] (message : α) (providers : List (Aiur.AIR.Provider α)), + Aiur.AIR.suppliedWeight message providers ≠ 0 → + ∃ provider, provider ∈ providers ∧ provider.fst = message ∧ provider.snd ≠ 0 +AXIOMS [propext] +ROOT Aiur.AIR.exactLookupBalance_provider +∀ {α : Type u_1} [inst : DecidableEq α] {queries : List α} {providers : List (Aiur.AIR.Provider α)}, + Aiur.AIR.ExactLookupBalance queries providers → + queries.length < Aiur.gSize.toNat → + ∀ {message : α}, message ∈ queries → ∃ provider, provider ∈ providers ∧ provider.fst = message ∧ provider.snd ≠ 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.byteRangeMessage_bounded +∀ (row : Fin 65536), (Aiur.AIR.byteRangeMessage row).fst.n < 256 ∧ (Aiur.AIR.byteRangeMessage row).snd.n < 256 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_byteRange +∀ {queries : List (Aiur.G × Aiur.G)} (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.byteRangeProviders weights) → + queries.length < Aiur.gSize.toNat → ∀ {a b : Aiur.G}, (a, b) ∈ queries → a.n < 256 ∧ b.n < 256 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_rankBytes +∀ {queries : List (Aiur.G × Aiur.G)} (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.byteRangeProviders weights) → + queries.length < Aiur.gSize.toNat → + ∀ (bytes : Fin 6 → Aiur.G), Aiur.AIR.rankByteQueries bytes ⊆ queries → ∀ (i : Fin 6), (bytes i).n < 256 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_call_order +∀ {queries : List (Aiur.G × Aiur.G)} (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.byteRangeProviders weights) → + queries.length < Aiur.gSize.toNat → + ∀ (parent child gap : Fin 6 → Aiur.G), + Aiur.AIR.rankByteQueries parent ⊆ queries → + Aiur.AIR.rankByteQueries child ⊆ queries → + Aiur.AIR.rankByteQueries gap ⊆ queries → + Aiur.AIR.callOrderConstraint (Aiur.AIR.packRank parent) (Aiur.AIR.packRank child) + (Aiur.AIR.packRank gap) = + 0 → + (Aiur.AIR.packRank parent).n < (Aiur.AIR.packRank child).n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.Valid.active_of_nonzero +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {row : Aiur.AIR.FunctionRow}, + Aiur.AIR.FunctionRow.Valid program memory row → row.multiplicity ≠ 0 → row.selector = 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.functionQueries_provider +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call} + {rows : List Aiur.AIR.FunctionRow}, + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.Valid program memory row) → + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionQueries roots rows) (Aiur.AIR.functionProviders rows) → + (Aiur.AIR.functionQueries roots rows).length < Aiur.gSize.toNat → + ∀ {request : Aiur.Bytecode.AIR.Call}, + request ∈ Aiur.AIR.functionQueries roots rows → ∃ row, row ∈ rows ∧ row.request = request ∧ row.selector = 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.balancedRows_execute +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call} + {rows : List Aiur.AIR.FunctionRow}, + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.Valid program memory row) → + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionQueries roots rows) (Aiur.AIR.functionProviders rows) → + (Aiur.AIR.functionQueries roots rows).length < Aiur.gSize.toNat → + ∀ (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionByteQueries rows) (Aiur.AIR.byteRangeProviders weights) → + (Aiur.AIR.functionByteQueries rows).length < Aiur.gSize.toNat → + ∀ {row : Aiur.AIR.FunctionRow}, + row ∈ rows → row.selector = 1 → Aiur.Bytecode.AIR.Execution program memory row.request +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.balancedRoots_execute +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call} + {rows : List Aiur.AIR.FunctionRow}, + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.Valid program memory row) → + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionQueries roots rows) (Aiur.AIR.functionProviders rows) → + (Aiur.AIR.functionQueries roots rows).length < Aiur.gSize.toNat → + ∀ (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionByteQueries rows) (Aiur.AIR.byteRangeProviders weights) → + (Aiur.AIR.functionByteQueries rows).length < Aiur.gSize.toNat → + ∀ {request : Aiur.Bytecode.AIR.Call}, request ∈ roots → Aiur.Bytecode.AIR.Execution program memory request +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.MemoryRowsValid.pointer_injective +∀ {width : Nat} {rows : Array Aiur.AIR.MemoryRow}, + Aiur.AIR.MemoryRowsValid width rows → + rows.size < Aiur.gSize.toNat → + ∀ (i j : Nat) (hi : i < rows.size) (hj : j < rows.size), + rows[i].selector = 1 → rows[j].selector = 1 → rows[i].pointer = rows[j].pointer → i = j +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.memoryFacts_functional +∀ (tables : Nat → Array Aiur.AIR.MemoryRow), + (∀ (width : Nat), Aiur.AIR.MemoryRowsValid width (tables width)) → + (∀ (width : Nat), (tables width).size < Aiur.gSize.toNat) → + ∀ {width : Nat} {pointer : Aiur.G} {left right : Array Aiur.G}, + Aiur.AIR.memoryFacts tables width pointer left → Aiur.AIR.memoryFacts tables width pointer right → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.memoryQueries_provider +∀ {width : Nat} {rows : Array Aiur.AIR.MemoryRow}, + Aiur.AIR.MemoryRowsValid width rows → + ∀ {queries : List (Aiur.G × Array Aiur.G)}, + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.memoryProviders rows) → + queries.length < Aiur.gSize.toNat → + ∀ {pointer : Aiur.G} {contents : Array Aiur.G}, + (pointer, contents) ∈ queries → + ∃ i hi, rows[i].selector = 1 ∧ rows[i].pointer = pointer ∧ rows[i].contents = contents +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.memoryQueries_width +∀ {width : Nat} {rows : Array Aiur.AIR.MemoryRow}, + Aiur.AIR.MemoryRowsValid width rows → + ∀ {queries : List (Aiur.G × Array Aiur.G)}, + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.memoryProviders rows) → + queries.length < Aiur.gSize.toNat → + ∀ {pointer : Aiur.G} {contents : Array Aiur.G}, (pointer, contents) ∈ queries → contents.size = width +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.memoryQueries_consistent +∀ {width : Nat} {rows : Array Aiur.AIR.MemoryRow}, + Aiur.AIR.MemoryRowsValid width rows → + rows.size < Aiur.gSize.toNat → + ∀ {queries : List (Aiur.G × Array Aiur.G)}, + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.memoryProviders rows) → + queries.length < Aiur.gSize.toNat → + ∀ {pointer : Aiur.G} {left right : Array Aiur.G}, + (pointer, left) ∈ queries → (pointer, right) ∈ queries → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.memoryQueries_fact +∀ (tables : Nat → Array Aiur.AIR.MemoryRow), + (∀ (width : Nat), Aiur.AIR.MemoryRowsValid width (tables width)) → + ∀ (queries : Nat → List (Aiur.G × Array Aiur.G)), + (∀ (width : Nat), Aiur.AIR.ExactLookupBalance (queries width) (Aiur.AIR.memoryProviders (tables width))) → + (∀ (width : Nat), (queries width).length < Aiur.gSize.toNat) → + ∀ {width : Nat} {pointer : Aiur.G} {contents : Array Aiur.G}, + (pointer, contents) ∈ queries width → Aiur.AIR.memoryFacts tables width pointer contents +AXIOMS [propext, Quot.sound] +ROOT Aiur.gSize_prime +1 < Aiur.gSize.toNat ∧ ∀ (d : Nat), d ∣ Aiur.gSize.toNat → d = 1 ∨ d = Aiur.gSize.toNat +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.mul_eq_zero_iff +∀ (a b : Aiur.G), a * b = 0 ↔ a = 0 ∨ b = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.boolean_of_constraint +∀ {value : Aiur.G}, value * (value - 1) = 0 → value = 0 ∨ value = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.boolean_of_one_sub_constraint +∀ {value : Aiur.G}, value * (1 - value) = 0 → value = 0 ∨ value = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.eqZero_of_constraints +∀ {input inverse output : Aiur.G}, input * output = 0 → input * inverse + output - 1 = 0 → output = input.eqZero +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.selectorSum_count_le_one +∀ {selectors : List Aiur.G}, + (∀ (value : Aiur.G), value ∈ selectors → Aiur.AIR.booleanConstraint value = 0) → + Aiur.AIR.oneSubBooleanConstraint (Aiur.AIR.selectorSum selectors) = 0 → + selectors.length < Aiur.gSize.toNat → List.count 1 selectors ≤ 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.selectorSum_inactive +∀ {selectors : List Aiur.G}, + (∀ (value : Aiur.G), value ∈ selectors → Aiur.AIR.booleanConstraint value = 0) → + selectors.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum selectors = 0 → ∀ (value : Aiur.G), value ∈ selectors → value = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.selectorSum_active_split +∀ {selectors : List Aiur.G}, + (∀ (value : Aiur.G), value ∈ selectors → Aiur.AIR.booleanConstraint value = 0) → + selectors.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum selectors = 1 → + ∃ before after, selectors = before ++ 1 :: after ∧ ∀ (value : Aiur.G), value ∈ before ++ after → value = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.selectorSum_characteristic_cancel +Aiur.AIR.selectorSum (List.replicate Aiur.gSize.toNat 1) = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.nonzero_multiplicity_selector_one +∀ {multiplicity selector : Aiur.G}, + Aiur.AIR.activityConstraint multiplicity selector = 0 → multiplicity ≠ 0 → selector = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.active_eqZero +∀ {selector input inverse output : Aiur.G}, + selector = 1 → selector * input * output = 0 → selector * (input * inverse + output - 1) = 0 → output = input.eqZero +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.active_case +∀ {selector matched key : Aiur.G}, selector = 1 → selector * (matched - key) = 0 → matched = key +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.active_default +∀ {selector matched key inverse : Aiur.G}, selector = 1 → selector * ((matched - key) * inverse - 1) = 0 → matched ≠ key +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.MemoryRowsPolynomials.valid +∀ {width : Nat} {rows : Array Aiur.AIR.MemoryRow}, + Aiur.AIR.MemoryRowsPolynomials width rows → Aiur.AIR.MemoryRowsValid width rows +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryRowsPolynomials.functional +∀ (tables : Nat → Array Aiur.AIR.MemoryRow), + (∀ (width : Nat), Aiur.AIR.MemoryRowsPolynomials width (tables width)) → + (∀ (width : Nat), (tables width).size < Aiur.gSize.toNat) → + ∀ {width : Nat} {pointer : Aiur.G} {left right : Array Aiur.G}, + Aiur.AIR.memoryFacts tables width pointer left → Aiur.AIR.memoryFacts tables width pointer right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.inverse256_correct +Aiur.AIR.inverse256 * 256 = 1 +AXIOMS [propext] +ROOT Aiur.AIR.byte_add_carry +∀ {x y low : Aiur.G}, + x.n < 256 → + y.n < 256 → + low = Aiur.G.ofNat ((x.n + y.n) % 256) → (x + y - low) * Aiur.AIR.inverse256 = Aiur.G.ofNat ((x.n + y.n) / 256) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.byte_sub_borrow +∀ {x y low : Aiur.G}, + x.n < 256 → + y.n < 256 → + low = Aiur.G.ofNat ((x.n + 256 - y.n) % 256) → (low + y - x) * Aiur.AIR.inverse256 = if x.n < y.n then 1 else 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.byte_carry_relation +∀ {x y z previous carry : Aiur.G}, + x.n < 256 → + y.n < 256 → + z.n < 256 → + previous = 0 ∨ previous = 1 → + carry = 0 ∨ carry = 1 → + carry = (x + y + previous - z) * Aiur.AIR.inverse256 → x.n + y.n + previous.n = z.n + 256 * carry.n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.pack4_n +∀ (bytes : Fin 4 → Aiur.G), + (∀ (i : Fin 4), (bytes i).n < 256) → + (Aiur.AIR.pack4 bytes).n = Aiur.AIR.pack4Nat bytes ∧ (Aiur.AIR.pack4 bytes).n < 2 ^ 32 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.u32Carry_relation +∀ (x y z : Fin 4 → Aiur.G), + (∀ (i : Fin 4), (x i).n < 256) → + (∀ (i : Fin 4), (y i).n < 256) → + (∀ (i : Fin 4), (z i).n < 256) → + (∀ (i : Fin 4), Aiur.AIR.booleanConstraint (Aiur.AIR.u32Carries x y z i.succ) = 0) → + Aiur.AIR.pack4Nat x + Aiur.AIR.pack4Nat y + 1 = Aiur.AIR.pack4Nat z + 2 ^ 32 * (Aiur.AIR.u32Carries x y z 4).n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.u32_less_than +∀ (x y z : Fin 4 → Aiur.G), + (∀ (i : Fin 4), (x i).n < 256) → + (∀ (i : Fin 4), (y i).n < 256) → + (∀ (i : Fin 4), (z i).n < 256) → + (∀ (i : Fin 4), Aiur.AIR.booleanConstraint (Aiur.AIR.u32Carries x y z i.succ) = 0) → + 1 - Aiur.AIR.u32Carries x y z 4 = (Aiur.AIR.pack4 x).u32LessThan (Aiur.AIR.pack4 z) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.active_u32_less_than +∀ {selector a b : Aiur.G}, + selector = 1 → + ∀ (x y z : Fin 4 → Aiur.G), + (∀ (i : Fin 4), (x i).n < 256) → + (∀ (i : Fin 4), (y i).n < 256) → + (∀ (i : Fin 4), (z i).n < 256) → + selector * (a - Aiur.AIR.pack4 x) = 0 → + selector * (b - Aiur.AIR.pack4 z) = 0 → + (∀ (i : Fin 4), selector * Aiur.AIR.booleanConstraint (Aiur.AIR.u32Carries x y z i.succ) = 0) → + a.n < 2 ^ 32 ∧ b.n < 2 ^ 32 ∧ 1 - Aiur.AIR.u32Carries x y z 4 = a.u32LessThan b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_byte1 +∀ {queries : List (List Aiur.G)} (weights : Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G), + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.byte1Providers weights) → + queries.length < Aiur.gSize.toNat → + ∀ {kind : Aiur.AIR.Byte1Kind} {input : Aiur.G} {outputs : Array Aiur.G}, + Aiur.AIR.byte1Request kind input outputs ∈ queries → input.n < 256 ∧ outputs = kind.result input +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_byte2 +∀ {queries : List (List Aiur.G)} (weights : Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.byte2Providers weights) → + queries.length < Aiur.gSize.toNat → + ∀ {kind : Aiur.AIR.Byte2Kind} {x y : Aiur.G} {outputs : Array Aiur.G}, + Aiur.AIR.byte2Request kind x y outputs ∈ queries → x.n < 256 ∧ y.n < 256 ∧ outputs = kind.result x y +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_byte1_step +∀ {queries : List (List Aiur.G)} (weights : Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G), + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.byte1Providers weights) → + queries.length < Aiur.gSize.toNat → + ∀ (memory : Aiur.Bytecode.AIR.Memory) {kind : Aiur.AIR.Byte1Kind} {values : Array Aiur.G} + {index : Aiur.Bytecode.ValIdx} {input : Aiur.G} {outputs : Array Aiur.G}, + values[index]? = some input → + Aiur.AIR.byte1Request kind input outputs ∈ queries → + Aiur.Bytecode.AIR.Step memory (kind.op index) values (values ++ outputs) [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_byte2_step +∀ {queries : List (List Aiur.G)} (weights : Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance queries (Aiur.AIR.byte2Providers weights) → + queries.length < Aiur.gSize.toNat → + ∀ (memory : Aiur.Bytecode.AIR.Memory) {kind : Aiur.AIR.Byte2Kind} {values : Array Aiur.G} + {left right : Aiur.Bytecode.ValIdx} {x y : Aiur.G} {outputs : Array Aiur.G}, + values[left]? = some x → + values[right]? = some y → + Aiur.AIR.byte2Request kind x y outputs ∈ queries → + Aiur.Bytecode.AIR.Step memory (kind.op left right) values (values ++ kind.extendOutputs x y outputs) [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.active_u32_less_than_step +∀ (memory : Aiur.Bytecode.AIR.Memory) {selector a b : Aiur.G} {values : Array Aiur.G} + {left right : Aiur.Bytecode.ValIdx}, + selector = 1 → + values[left]? = some a → + values[right]? = some b → + ∀ (x y z : Fin 4 → Aiur.G), + (∀ (i : Fin 4), (x i).n < 256) → + (∀ (i : Fin 4), (y i).n < 256) → + (∀ (i : Fin 4), (z i).n < 256) → + selector * (a - Aiur.AIR.pack4 x) = 0 → + selector * (b - Aiur.AIR.pack4 z) = 0 → + (∀ (i : Fin 4), selector * Aiur.AIR.booleanConstraint (Aiur.AIR.u32Carries x y z i.succ) = 0) → + Aiur.Bytecode.AIR.Step memory (Aiur.Bytecode.Op.u32LessThan left right) values + (values ++ #[1 - Aiur.AIR.u32Carries x y z 4]) [] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.padMessage_injective_of_shape +∀ {width : Nat} {widths : Aiur.G → Aiur.G → Nat} {left right : List Aiur.G}, + Aiur.AIR.HasMessageShape widths left → + Aiur.AIR.HasMessageShape widths right → + left.length ≤ width → Aiur.AIR.padMessage width left = Aiur.AIR.padMessage width right → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.exactLookupBalance_of_injective_on +∀ {α : Type u_1} {β : Type u_2} [inst : DecidableEq α] [inst_1 : DecidableEq β] (encode : α → β) + (admissible : α → Prop), + (∀ {left right : α}, admissible left → admissible right → encode left = encode right → left = right) → + ∀ {queries : List α} {providers : List (Aiur.AIR.Provider α)}, + (∀ (query : α), query ∈ queries → admissible query) → + (∀ (provider : Aiur.AIR.Provider α), provider ∈ providers → provider.snd ≠ 0 → admissible provider.fst) → + Aiur.AIR.ExactLookupBalance (List.map encode queries) (Aiur.AIR.mapProviders encode providers) → + Aiur.AIR.ExactLookupBalance queries providers +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.ExactLookupBalance.filter +∀ {α : Type u_1} [inst : DecidableEq α] {queries : List α} {providers : List (Aiur.AIR.Provider α)}, + Aiur.AIR.ExactLookupBalance queries providers → + ∀ (keep : α → Bool), + Aiur.AIR.ExactLookupBalance (List.filter keep queries) (List.filter (fun provider => keep provider.fst) providers) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.paddedLookupBalance_provider +∀ {width : Nat} {queries : List (List Aiur.G)} {providers : List (Aiur.AIR.Provider (List Aiur.G))}, + Aiur.AIR.PaddedLookupBalance width queries providers → + queries.length < Aiur.gSize.toNat → + ∀ {message : List Aiur.G}, + message ∈ queries → + ∃ provider, + provider ∈ providers ∧ + Aiur.AIR.padMessage width provider.fst = Aiur.AIR.padMessage width message ∧ provider.snd ≠ 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.paddedLookupBalance_exact +∀ {width : Nat} (widths : Aiur.G → Aiur.G → Nat) {queries : List (List Aiur.G)} + {providers : List (Aiur.AIR.Provider (List Aiur.G))}, + (∀ (query : List Aiur.G), query ∈ queries → Aiur.AIR.HasMessageShape widths query ∧ query.length ≤ width) → + (∀ (provider : Aiur.AIR.Provider (List Aiur.G)), + provider ∈ providers → + provider.snd ≠ 0 → Aiur.AIR.HasMessageShape widths provider.fst ∧ provider.fst.length ≤ width) → + Aiur.AIR.PaddedLookupBalance width queries providers → Aiur.AIR.ExactLookupBalance queries providers +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.functionMessage_shape +∀ (arities : Aiur.AIR.FunctionArities) (request : Aiur.Bytecode.AIR.Call), + Aiur.AIR.FunctionMessageValid arities request → + Aiur.AIR.HasMessageShape (Aiur.AIR.lookupMessageWidth arities) (Aiur.AIR.functionMessage request) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.memoryMessage_shape +∀ (arities : Aiur.AIR.FunctionArities) (width : Nat) (pointer : Aiur.G) (contents : Array Aiur.G), + width < Aiur.gSize.toNat → + contents.size = width → + Aiur.AIR.HasMessageShape (Aiur.AIR.lookupMessageWidth arities) (Aiur.AIR.memoryMessage width pointer contents) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.byte1Request_shape +∀ (arities : Aiur.AIR.FunctionArities) (kind : Aiur.AIR.Byte1Kind) (input : Aiur.G) (outputs : Array Aiur.G), + outputs.size = kind.outputSize → + Aiur.AIR.HasMessageShape (Aiur.AIR.lookupMessageWidth arities) (Aiur.AIR.byte1Request kind input outputs) +AXIOMS [propext] +ROOT Aiur.AIR.byte2Request_shape +∀ (arities : Aiur.AIR.FunctionArities) (kind : Aiur.AIR.Byte2Kind) (x y : Aiur.G) (outputs : Array Aiur.G), + outputs.size = kind.outputSize → + Aiur.AIR.HasMessageShape (Aiur.AIR.lookupMessageWidth arities) (Aiur.AIR.byte2Request kind x y outputs) +AXIOMS [propext] +ROOT Aiur.AIR.functionMessage_injective +∀ {arities : Aiur.AIR.FunctionArities} {left right : Aiur.Bytecode.AIR.Call}, + Aiur.AIR.FunctionMessageValid arities left → + Aiur.AIR.FunctionMessageValid arities right → + Aiur.AIR.functionMessage left = Aiur.AIR.functionMessage right → left = right +AXIOMS [propext] +ROOT Aiur.AIR.exactLookupBalance_functionMessages +∀ (arities : Aiur.AIR.FunctionArities) {queries : List Aiur.Bytecode.AIR.Call} + {providers : List (Aiur.AIR.Provider Aiur.Bytecode.AIR.Call)}, + (∀ (query : Aiur.Bytecode.AIR.Call), query ∈ queries → Aiur.AIR.FunctionMessageValid arities query) → + (∀ (provider : Aiur.AIR.Provider Aiur.Bytecode.AIR.Call), + provider ∈ providers → provider.snd ≠ 0 → Aiur.AIR.FunctionMessageValid arities provider.fst) → + Aiur.AIR.ExactLookupBalance (List.map Aiur.AIR.functionMessage queries) + (Aiur.AIR.mapProviders Aiur.AIR.functionMessage providers) → + Aiur.AIR.ExactLookupBalance queries providers +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.memoryMessage_injective +∀ {width : Nat} {left right : Aiur.G × Array Aiur.G}, + Aiur.AIR.memoryMessage width left.fst left.snd = Aiur.AIR.memoryMessage width right.fst right.snd → left = right +AXIOMS [propext] +ROOT Aiur.AIR.exactLookupBalance_memoryMessages +∀ (width : Nat) {queries : List (Aiur.G × Array Aiur.G)} {providers : List (Aiur.AIR.Provider (Aiur.G × Array Aiur.G))}, + Aiur.AIR.ExactLookupBalance (List.map (fun request => Aiur.AIR.memoryMessage width request.fst request.snd) queries) + (Aiur.AIR.mapProviders (fun request => Aiur.AIR.memoryMessage width request.fst request.snd) providers) → + Aiur.AIR.ExactLookupBalance queries providers +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.padMessage_append_zero +∀ {width : Nat} (message : List Aiur.G), Aiur.AIR.padMessage width (message ++ [0]) = Aiur.AIR.padMessage width message +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.functionMessage_rank_alias +∀ (width : Nat), + have output := { function := 0, inputs := #[], outputs := #[7], rank := 0 }; + have rank := { function := 0, inputs := #[], outputs := #[], rank := 7 }; + output ≠ rank ∧ + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage output) = + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage rank) +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunBlock.return_size +∀ {memory : Aiur.Bytecode.AIR.Memory} {block : Aiur.Bytecode.Block} {values : Array Aiur.G} + {outcome : Aiur.Bytecode.AIR.Outcome} {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunBlock memory block values outcome calls → + ∀ (size : Nat), Aiur.Bytecode.Block.returnsHaveSize size block = true → outcome.ReturnSize size +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunFunction.return_size +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {request : Aiur.Bytecode.AIR.Call} + {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunFunction program memory request calls → + ∀ {callee : Aiur.Bytecode.Function}, + program.functions[request.function]? = some callee → + ∀ (size : Nat), Aiur.Bytecode.Block.returnsHaveSize size callee.body = true → request.outputs.size = size +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.Step.calls_lookupShape +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {op : Aiur.Bytecode.Op} + {values outputs : Array Aiur.G} {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Step memory op values outputs calls → + Aiur.Bytecode.Op.lookupShape program op = true → + ∀ (request : Aiur.Bytecode.AIR.Call), request ∈ calls → Aiur.Bytecode.AIR.Call.LookupShape program request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunOps.calls_lookupShape +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {ops : List Aiur.Bytecode.Op} + {values outputs : Array Aiur.G} {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunOps memory ops values outputs calls → + (∀ (op : Aiur.Bytecode.Op), op ∈ ops → Aiur.Bytecode.Op.lookupShape program op = true) → + ∀ (request : Aiur.Bytecode.AIR.Call), request ∈ calls → Aiur.Bytecode.AIR.Call.LookupShape program request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunBlock.calls_lookupShape +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {block : Aiur.Bytecode.Block} + {values : Array Aiur.G} {outcome : Aiur.Bytecode.AIR.Outcome} {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunBlock memory block values outcome calls → + ∀ (yieldSize : Option Nat), + Aiur.Bytecode.Block.lookupShapes program yieldSize block = true → + ∀ (request : Aiur.Bytecode.AIR.Call), request ∈ calls → Aiur.Bytecode.AIR.Call.LookupShape program request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunFunction.calls_lookupShape +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {request : Aiur.Bytecode.AIR.Call} + {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunFunction program memory request calls → + program.validateLookupShapes = true → + ∀ {callee : Aiur.Bytecode.Function}, + program.functions[request.function]? = some callee → + callee.constrained = true → + ∀ (child : Aiur.Bytecode.AIR.Call), child ∈ calls → Aiur.Bytecode.AIR.Call.LookupShape program child +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.air_return_size +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + {memory : Aiur.Bytecode.AIR.Memory} {request : Aiur.Bytecode.AIR.Call} {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunFunction backend.compiled.bytecode memory request calls → + request.function = selection.function → request.outputs.size = selection.success.size +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.claim_shape +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) (input : Array Aiur.G), + input.size = selection.inputSize → + backend.compiled.bytecode.validClaimShape (Aiur.buildClaim selection.function input selection.success) = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.padded_functionMessage_reflects +∀ {width : Nat} {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} + {request provided : Aiur.Bytecode.AIR.Call} {calls : List Aiur.Bytecode.AIR.Call}, + program.functions.size < Aiur.gSize.toNat → + Aiur.Bytecode.AIR.Call.LookupShape program request → + Aiur.Bytecode.AIR.RunFunction program memory provided calls → + (Aiur.AIR.functionMessage request).length ≤ width → + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage request) = + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage provided) → + request = provided +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.function_provider +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory}, + (∀ (row : Aiur.AIR.FunctionRow), row ∈ tables.functions → Aiur.AIR.FunctionRow.Valid program memory row) → + program.functions.size < Aiur.gSize.toNat → + ∀ {request : Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Call.LookupShape program request → + Aiur.AIR.functionMessage request ∈ queries → + ∃ row, row ∈ tables.functions ∧ row.request = request ∧ row.selector = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.byte1 +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {kind : Aiur.AIR.Byte1Kind} {input : Aiur.G} {outputs : Array Aiur.G}, + outputs.size = kind.outputSize → + Aiur.AIR.byte1Request kind input outputs ∈ queries → input.n < 256 ∧ outputs = kind.result input +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.byte2 +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {kind : Aiur.AIR.Byte2Kind} {x y : Aiur.G} {outputs : Array Aiur.G}, + outputs.size = kind.outputSize → + Aiur.AIR.byte2Request kind x y outputs ∈ queries → x.n < 256 ∧ y.n < 256 ∧ outputs = kind.result x y +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.memory_fact +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ {size : Nat} {pointer : Aiur.G} {contents : Array Aiur.G}, + size < Aiur.gSize.toNat → + contents.size = size → + Aiur.AIR.memoryMessage size pointer contents ∈ queries → + Aiur.AIR.memoryFacts tables.memory size pointer contents +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.memory_consistent +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), (tables.memory size).size < Aiur.gSize.toNat) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ {size : Nat} {pointer : Aiur.G} {left right : Array Aiur.G}, + size < Aiur.gSize.toNat → + left.size = size → + right.size = size → + Aiur.AIR.memoryMessage size pointer left ∈ queries → + Aiur.AIR.memoryMessage size pointer right ∈ queries → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.byte1_step +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ (memory : Aiur.Bytecode.AIR.Memory) {kind : Aiur.AIR.Byte1Kind} {values : Array Aiur.G} + {index : Aiur.Bytecode.ValIdx} {input : Aiur.G} {outputs : Array Aiur.G}, + values[index]? = some input → + outputs.size = kind.outputSize → + Aiur.AIR.byte1Request kind input outputs ∈ queries → + Aiur.Bytecode.AIR.Step memory (kind.op index) values (values ++ outputs) [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.byte2_step +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ (memory : Aiur.Bytecode.AIR.Memory) {kind : Aiur.AIR.Byte2Kind} {values : Array Aiur.G} + {left right : Aiur.Bytecode.ValIdx} {x y : Aiur.G} {outputs : Array Aiur.G}, + values[left]? = some x → + values[right]? = some y → + outputs.size = kind.outputSize → + Aiur.AIR.byte2Request kind x y outputs ∈ queries → + Aiur.Bytecode.AIR.Step memory (kind.op left right) values (values ++ kind.extendOutputs x y outputs) [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.rank_bytes +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ (bytes : Fin 6 → Aiur.G), + List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries bytes) ⊆ queries → ∀ (i : Fin 6), (bytes i).n < 256 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.rows_execute +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call}, + program.validateLookupShapes = true → + (∀ (row : Aiur.AIR.FunctionRow), row ∈ tables.functions → Aiur.AIR.FunctionRow.Valid program memory row) → + List.map Aiur.AIR.functionMessage (Aiur.AIR.functionQueries roots tables.functions) ⊆ queries → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.functionByteQueries tables.functions) ⊆ queries → + ∀ {row : Aiur.AIR.FunctionRow}, + row ∈ tables.functions → + row.selector = 1 → + Aiur.Bytecode.AIR.Call.LookupShape program row.request → + Aiur.Bytecode.AIR.Execution program memory row.request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.roots_execute +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call}, + program.validateLookupShapes = true → + (∀ (row : Aiur.AIR.FunctionRow), row ∈ tables.functions → Aiur.AIR.FunctionRow.Valid program memory row) → + List.map Aiur.AIR.functionMessage (Aiur.AIR.functionQueries roots tables.functions) ⊆ queries → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.functionByteQueries tables.functions) ⊆ queries → + ∀ {request : Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Call.LookupShape program request → + request ∈ roots → Aiur.Bytecode.AIR.Execution program memory request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.root_lookupShape +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.Bytecode.AIR.Call.LookupShape backend.compiled.bytecode + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.claim_padding +∀ (selection : Aiur.BoundVerifier.Selection) (width : Nat) (input : Array Aiur.G), + Aiur.AIR.padMessage width + (Aiur.AIR.functionMessage + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 }) = + Aiur.AIR.padMessage width (Aiur.buildClaim selection.function input selection.success).toList +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.global_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {memory : Aiur.Bytecode.AIR.Memory} (input : Array Aiur.G), + input.size = selection.inputSize → + (∀ (row : Aiur.AIR.FunctionRow), + row ∈ tables.functions → Aiur.AIR.FunctionRow.Valid backend.compiled.bytecode memory row) → + List.map Aiur.AIR.functionMessage + (Aiur.AIR.functionQueries + [{ function := selection.function, inputs := input, outputs := selection.success, rank := 0 }] + tables.functions) ⊆ + queries → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.functionByteQueries tables.functions) ⊆ queries → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode memory + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.lookupQueryBound_sound +∀ {slots : List Nat} {active : List Bool} {degrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound slots active degrees = some result → + active.any id = true ∧ + ∃ total, Aiur.lookupSlotSum slots active degrees = some total ∧ result = 1 + total ∧ result < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.lookupQueryBound_consumer_count +∀ {slots : List Nat} {active : List Bool} {degrees : List Nat} {result total : Nat}, + Aiur.lookupQueryBound slots active degrees = some result → + Aiur.lookupSlotSum slots active degrees = some total → + ∀ {α : Type u} (queries : List α), queries.length ≤ total → queries.length + 1 < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.lookupQueryBound_shape +∀ {slots : List Nat} {active : List Bool} {degrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound slots active degrees = some result → + active.any id = true ∧ + slots.length = active.length ∧ + degrees.length = List.count true active ∧ ∀ (degree : Nat), degree ∈ degrees → degree < 64 +AXIOMS [propext, Quot.sound] +ROOT Aiur.lookupQueryBound_step_no_overflow +∀ {used height slots : Nat}, + used + height * slots < Aiur.gSize.toNat → height * slots < 2 ^ 64 ∧ used + height * slots < 2 ^ 64 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.lookupQueryBound_complete +∀ {slots : List Nat} {active : List Bool} {degrees : List Nat} {total : Nat}, + active.any id = true → + Aiur.lookupSlotSum slots active degrees = some total → + (∀ (degree : Nat), degree ∈ degrees → degree < 64) → + 1 + total < Aiur.gSize.toNat → Aiur.lookupQueryBound slots active degrees = some (1 + total) +AXIOMS [propext, Quot.sound] +ROOT Aiur.lookupSlotSum_bounded +∀ {slots : List Nat} {active : List Bool} {degrees : List Nat} {total maxSlots maxDegree : Nat}, + Aiur.lookupSlotSum slots active degrees = some total → + (∀ (count : Nat), count ∈ slots → count ≤ maxSlots) → + (∀ (degree : Nat), degree ∈ degrees → degree ≤ maxDegree) → total ≤ slots.length * (2 ^ maxDegree * maxSlots) +AXIOMS [propext, Quot.sound] +ROOT Aiur.lookupQueryBound_encodedKey +∀ {slots : List Nat} {active : List Bool} {degrees : List Nat} {total : Nat}, + active.any id = true → + Aiur.lookupSlotSum slots active degrees = some total → + slots.length < 65536 → + (∀ (count : Nat), count ∈ slots → count < 65536) → + (∀ (degree : Nat), degree ∈ degrees → degree ≤ 32) → + Aiur.lookupQueryBound slots active degrees = some (1 + total) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.of_budget +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {slots : List Nat} {active : List Bool} {degrees : List Nat} + {result total : Nat}, + Aiur.lookupQueryBound slots active degrees = some result → + Aiur.lookupSlotSum slots active degrees = some total → + ∀ (root : List Aiur.G) (queries : List (List Aiur.G)), + queries.length ≤ total → + Aiur.AIR.PaddedLookupBalance width (root :: queries) tables.providers → + (∀ (query : List Aiur.G), query ∈ root :: queries → query.length ≤ width) → + Aiur.AIR.GlobalLookups tables width (root :: queries) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.weightedMessage_active +∀ (width : Nat) {parts : List (Aiur.G × List Aiur.G)}, + (∀ (part : Aiur.G × List Aiur.G), part ∈ parts → Aiur.AIR.booleanConstraint part.fst = 0) → + parts.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum (List.map Prod.fst parts) = 1 → + ∃ chosen, + chosen ∈ parts ∧ + chosen.fst = 1 ∧ + Aiur.AIR.padMessage width (Aiur.AIR.weightedMessage parts) = Aiur.AIR.padMessage width chosen.snd +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.weightedMessage_inactive +∀ (width : Nat) {parts : List (Aiur.G × List Aiur.G)}, + (∀ (part : Aiur.G × List Aiur.G), part ∈ parts → Aiur.AIR.booleanConstraint part.fst = 0) → + parts.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum (List.map Prod.fst parts) = 0 → + Aiur.AIR.padMessage width (Aiur.AIR.weightedMessage parts) = Aiur.AIR.padMessage width [] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.slotMessage_active +∀ (width : Nat) (branchless : Bool) {parts : List (Aiur.G × List Aiur.G)}, + (branchless = true → parts.length = 1) → + (∀ (part : Aiur.G × List Aiur.G), part ∈ parts → Aiur.AIR.booleanConstraint part.fst = 0) → + parts.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum (List.map Prod.fst parts) = 1 → + ∃ chosen, + chosen ∈ parts ∧ + chosen.fst = 1 ∧ + Aiur.AIR.padMessage width (Aiur.AIR.slotMessage branchless parts) = Aiur.AIR.padMessage width chosen.snd +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.continuation_merge +∀ {parent : Aiur.G} {parts : List (Aiur.G × List Aiur.G)} {merged : List Aiur.G}, + parent = 1 → + (∀ (part : Aiur.G × List Aiur.G), part ∈ parts → Aiur.AIR.booleanConstraint part.fst = 0) → + parts.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum (List.map Prod.fst parts) = 1 → + (∀ (part : Aiur.G × List Aiur.G), part ∈ parts → part.snd.length = merged.length) → + (∀ (i : Nat), + i < merged.length → + parent * + (merged[i]?.getD 0 - + Aiur.AIR.selectorSum (List.map (fun part => part.fst * part.snd[i]?.getD 0) parts)) = + 0) → + ∃ chosen, chosen ∈ parts ∧ chosen.fst = 1 ∧ merged = chosen.snd +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.selectorFlow_sound +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block), + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied → (Aiur.Bytecode.Block.selectorFlow selector block).Sound +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.selectorFlow_yields_empty +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block) (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.Block.lookupShapes program none block = true → + (Aiur.Bytecode.Block.selectorFlow selector block).yields = [] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.selectorFlow_active_return +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block) (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.Block.lookupShapes program none block = true → + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied → + (Aiur.Bytecode.Block.selectorFlow selector block).returns.length < Aiur.gSize.toNat → + (Aiur.Bytecode.Block.selectorFlow selector block).entry = 1 → + ∃ before after, + (Aiur.Bytecode.Block.selectorFlow selector block).returns = before ++ 1 :: after ∧ + ∀ (value : Aiur.G), value ∈ before ++ after → value = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.selectorFlow_provider_return +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block) (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.Block.lookupShapes program none block = true → + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied → + (Aiur.Bytecode.Block.selectorFlow selector block).returns.length < Aiur.gSize.toNat → + ∀ (multiplicity : Aiur.G), + multiplicity ≠ 0 → + Aiur.AIR.activityConstraint multiplicity (Aiur.Bytecode.Block.selectorFlow selector block).entry = 0 → + ∃ before after, + (Aiur.Bytecode.Block.selectorFlow selector block).returns = before ++ 1 :: after ∧ + ∀ (value : Aiur.G), value ∈ before ++ after → value = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.SelectorFlow.Sound.inactive_terminal +∀ {flow : Aiur.AIR.SelectorFlow}, + flow.Sound → + flow.returns.length + flow.yields.length < Aiur.gSize.toNat → + flow.entry = 0 → ∀ (value : Aiur.G), value ∈ flow.returns ++ flow.yields → value = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.SelectorFlow.Sound.return_stops_continuation +∀ {flow : Aiur.AIR.SelectorFlow}, + flow.Sound → + flow.returns.length + flow.yields.length < Aiur.gSize.toNat → + flow.entry = 1 → 1 ∈ flow.returns → Aiur.AIR.selectorSum flow.yields = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.SelectorFlow.Sound.yield_starts_continuation +∀ {flow : Aiur.AIR.SelectorFlow}, + flow.Sound → + flow.returns.length + flow.yields.length < Aiur.gSize.toNat → + flow.entry = 1 → 1 ∈ flow.yields → Aiur.AIR.selectorSum flow.yields = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.returnGates_reflects +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (incoming : Aiur.G) (block : Aiur.Bytecode.Block), + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied → + incoming = (Aiur.Bytecode.Block.selectorFlow selector block).entry → + Aiur.Bytecode.Block.returnGates selector incoming block = + (Aiur.Bytecode.Block.selectorFlow selector block).returns +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.return_message +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block) (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.Block.lookupShapes program none block = true → + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied → + (Aiur.Bytecode.Block.selectorFlow selector block).returns.length < Aiur.gSize.toNat → + ∀ (multiplicity : Aiur.G), + multiplicity ≠ 0 → + Aiur.AIR.activityConstraint multiplicity (Aiur.Bytecode.Block.selectorFlow selector block).entry = 0 → + ∀ (width : Nat) (branchless : Bool) (parts : List (Aiur.G × List Aiur.G)), + List.map Prod.fst parts = + Aiur.Bytecode.Block.returnGates selector (Aiur.Bytecode.Block.selectorFlow selector block).entry + block → + (branchless = true → parts.length = 1) → + ∃ chosen, + chosen ∈ parts ∧ + chosen.fst = 1 ∧ + Aiur.AIR.padMessage width (Aiur.AIR.slotMessage branchless parts) = + Aiur.AIR.padMessage width chosen.snd +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitOp_step +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ {program : Aiur.Bytecode.Toplevel} {op : Aiur.Bytecode.Op}, + Aiur.Bytecode.Op.lookupShape program op = true → + ∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {values : Array Aiur.AIR.RowValue} + {emission : Aiur.AIR.OpEmission}, + Aiur.AIR.emitOp row selector rank op values = some emission → + selector = 1 → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.queries ⊆ queries → + Aiur.Bytecode.AIR.Step (Aiur.AIR.memoryFacts tables.memory) op (Aiur.AIR.rowValues values) + (Aiur.AIR.rowValues values ++ Aiur.AIR.rowValues emission.outputs) + (List.map Prod.fst emission.calls) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitOps_run +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ {program : Aiur.Bytecode.Toplevel} {ops : List Aiur.Bytecode.Op}, + (∀ (op : Aiur.Bytecode.Op), op ∈ ops → Aiur.Bytecode.Op.lookupShape program op = true) → + ∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {values : Array Aiur.AIR.RowValue} {column : Nat} + {emission : Aiur.AIR.OpsEmission}, + Aiur.AIR.emitOps row selector rank ops values column = some emission → + selector = 1 → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.queries ⊆ queries → + Aiur.Bytecode.AIR.RunOps (Aiur.AIR.memoryFacts tables.memory) ops (Aiur.AIR.rowValues values) + (Aiur.AIR.rowValues emission.values) (List.map Prod.fst emission.calls) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitOp_calls +∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {op : Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} + {emission : Aiur.AIR.OpEmission}, + Aiur.AIR.emitOp row selector rank op values = some emission → + Aiur.AIR.CallsEmitted rank selector emission.equations emission.queries emission.calls +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.emitOps_calls +∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {ops : List Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} + {column : Nat} {emission : Aiur.AIR.OpsEmission}, + Aiur.AIR.emitOps row selector rank ops values column = some emission → + Aiur.AIR.CallsEmitted rank selector emission.equations emission.queries emission.calls +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.CallsEmitted.ordered +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {pool : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width pool → + ∀ {rank selector : Aiur.G} {equations : List Aiur.G} {queries : List (List Aiur.G)} + {calls : List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G))}, + Aiur.AIR.CallsEmitted rank selector equations queries calls → + selector = 1 → + (∀ (equation : Aiur.G), equation ∈ equations → equation = 0) → + queries ⊆ pool → + rank.n < Aiur.AIR.callRankBound → + ∀ {edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)}, + edge ∈ calls → + edge.fst.rank.n < Aiur.AIR.callRankBound → + Aiur.AIR.functionMessage edge.fst ∈ pool ∧ rank.n < edge.fst.rank.n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.active_array_equality +∀ {selector : Aiur.G} {left right : Array Aiur.G}, + selector = 1 → + ∀ (sizes : left.size = right.size), + (∀ (equation : Aiur.G), (equation ∈ List.ofFn fun i => selector * (left[i] - right[↑i]?.getD 0)) → equation = 0) → + left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.Block.selectorFlow_boolean +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block), + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied → + Aiur.AIR.booleanConstraint (Aiur.Bytecode.Block.selectorFlow selector block).entry = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.MatchPolynomials.active_branch +∀ {selector : Aiur.Bytecode.SelIdx → Aiur.G} {scrutinee : Aiur.G} {branches : Array (Aiur.G × Aiur.Bytecode.Block)} + {fallback : Option Aiur.Bytecode.Block}, + Aiur.Bytecode.MatchPolynomials selector scrutinee branches fallback → + (Aiur.AIR.SelectorFlow.join (Aiur.Bytecode.branchSelectorFlows selector branches fallback)).Satisfied → + branches.size + fallback.toList.length < Aiur.gSize.toNat → + (Aiur.AIR.SelectorFlow.join (Aiur.Bytecode.branchSelectorFlows selector branches fallback)).entry = 1 → + ∃ block, + Aiur.Bytecode.AIR.SelectArm scrutinee branches fallback block ∧ + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied ∧ + (Aiur.Bytecode.Block.selectorFlow selector block).entry = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.MatchPolynomials.active_match +∀ {selector : Aiur.Bytecode.SelIdx → Aiur.G} {scrutinee : Aiur.G} {index : Aiur.Bytecode.ValIdx} + {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block}, + Aiur.Bytecode.MatchPolynomials selector scrutinee branches fallback → + (Aiur.Bytecode.Ctrl.selectorFlow selector (Aiur.Bytecode.Ctrl.match index branches fallback)).Satisfied → + branches.size + fallback.toList.length < Aiur.gSize.toNat → + (Aiur.Bytecode.Ctrl.selectorFlow selector (Aiur.Bytecode.Ctrl.match index branches fallback)).entry = 1 → + ∃ block, + Aiur.Bytecode.AIR.SelectArm scrutinee branches fallback block ∧ + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied ∧ + (Aiur.Bytecode.Block.selectorFlow selector block).entry = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.MatchPolynomials.active_matchContinue +∀ {selector : Aiur.Bytecode.SelIdx → Aiur.G} {scrutinee : Aiur.G} {index : Aiur.Bytecode.ValIdx} + {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} {outputs aux lookups : Nat} + {continuation : Aiur.Bytecode.Block}, + Aiur.Bytecode.MatchPolynomials selector scrutinee branches fallback → + (Aiur.Bytecode.Ctrl.selectorFlow selector + (Aiur.Bytecode.Ctrl.matchContinue index branches fallback outputs aux lookups continuation)).Satisfied → + branches.size + fallback.toList.length < Aiur.gSize.toNat → + (Aiur.Bytecode.Ctrl.selectorFlow selector + (Aiur.Bytecode.Ctrl.matchContinue index branches fallback outputs aux lookups continuation)).entry = + 1 → + ∃ block, + Aiur.Bytecode.AIR.SelectArm scrutinee branches fallback block ∧ + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied ∧ + (Aiur.Bytecode.Block.selectorFlow selector block).entry = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_projection +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block) + {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + Aiur.AIR.EmissionProjection (Aiur.Bytecode.Block.selectorFlow selector block) + (Aiur.Bytecode.Block.returnGates selector incoming block) emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_selectors +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block) + {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + (Aiur.Bytecode.Block.selectorFlow selector block).Satisfied +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.mergeEquations_chosen +∀ (row : Nat → Aiur.G) {parent : Aiur.G} {column size : Nat} {parts : List (Aiur.G × Array Aiur.AIR.RowValue)}, + parent = 1 → + (∀ (part : Aiur.G × Array Aiur.AIR.RowValue), part ∈ parts → Aiur.AIR.booleanConstraint part.fst = 0) → + parts.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum (List.map Prod.fst parts) = 1 → + ∀ {chosen : Array Aiur.AIR.RowValue}, + (1, chosen) ∈ parts → + chosen.size = size → + (∀ (equation : Aiur.G), + equation ∈ Aiur.AIR.mergeEquations row parent column size parts → equation = 0) → + Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row column size) = Aiur.AIR.rowValues chosen +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.branchRows_selected +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (matched : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block) {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.branchRows row selector context matched values column lookup branches fallback = some emission → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + branches.size + fallback.toList.length < Aiur.gSize.toNat → + (Aiur.AIR.SelectorFlow.join (Aiur.Bytecode.branchSelectorFlows selector branches fallback)).entry = 1 → + ∃ block bodyColumn body, + Aiur.Bytecode.AIR.SelectArm matched branches fallback block ∧ + (Aiur.Bytecode.Block.selectorFlow selector block).entry = 1 ∧ + Aiur.Bytecode.Block.emitRow row selector context (Aiur.Bytecode.Block.selectorFlow selector block).entry + values bodyColumn lookup block = + some body ∧ + Aiur.AIR.EmissionIncluded body emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_run +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (program : Aiur.Bytecode.Toplevel) (yieldSize : Option Nat) (row : Nat → Aiur.G) + (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block), + Aiur.Bytecode.Block.lookupShapes program yieldSize block = true → + Aiur.Bytecode.Block.rowBounds selector block → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + incoming = 1 → + incoming = (Aiur.Bytecode.Block.selectorFlow selector block).entry → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.QueriesIn queries → + ∃ outcome calls, + Aiur.Bytecode.AIR.RunBlock (Aiur.AIR.memoryFacts tables.memory) block + (Aiur.AIR.rowValues values) outcome (List.map Prod.fst calls) ∧ + emission.TerminalAt outcome ∧ emission.CallsAt calls +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_tracks_calls +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block) + {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + Aiur.AIR.BlockEmission.TracksCalls context.rank emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_inputs +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block) + {emission : Aiur.AIR.BlockEmission} {inputs : Array Aiur.G}, + Aiur.AIR.RowInputs context.inputSize inputs values → + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + Aiur.AIR.InputPreservation context inputs emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.emitRow_run +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (program : Aiur.Bytecode.Toplevel) (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) + (functionIndex : Aiur.Bytecode.FunIdx) (rank : Aiur.G) (values : Array Aiur.AIR.RowValue) + (column lookup : Nat) (function : Aiur.Bytecode.Function), + program.functions[functionIndex]? = some function → + values.size = function.layout.inputSize → + Aiur.Bytecode.Block.lookupShapes program none function.body = true → + Aiur.Bytecode.Block.rowBounds selector function.body → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Function.emitRow row selector functionIndex rank values column lookup function = + some emission → + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry = 1 → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.QueriesIn queries → + ∃ request calls, + (1, request) ∈ emission.returns ∧ + request.function = functionIndex ∧ + request.inputs = Aiur.AIR.rowValues values ∧ + request.rank = rank ∧ + Aiur.Bytecode.AIR.RunFunction program (Aiur.AIR.memoryFacts tables.memory) request + (List.map Prod.fst calls) ∧ + emission.CallsAt calls ∧ + Aiur.AIR.CallsEmitted rank 1 emission.equations queries calls +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.emitRow_valid +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (program : Aiur.Bytecode.Toplevel) (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) + (functionIndex : Aiur.Bytecode.FunIdx) (rankBytes : Fin 6 → Aiur.G) (values : Array Aiur.AIR.RowValue) + (column lookup : Nat) (function : Aiur.Bytecode.Function), + program.functions[functionIndex]? = some function → + values.size = function.layout.inputSize → + Aiur.Bytecode.Block.lookupShapes program none function.body = true → + Aiur.Bytecode.Block.rowBounds selector function.body → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Function.emitRow row selector functionIndex (Aiur.AIR.packRank rankBytes) values + column lookup function = + some emission → + ∀ (multiplicity : Aiur.G), + multiplicity ≠ 0 → + Aiur.AIR.activityConstraint multiplicity + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry = + 0 → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.QueriesIn queries → + ∃ interpreted, + Aiur.AIR.FunctionRow.Valid program (Aiur.AIR.memoryFacts tables.memory) interpreted ∧ + (1, interpreted.request) ∈ emission.returns ∧ + interpreted.request.function = functionIndex ∧ + interpreted.request.inputs = Aiur.AIR.rowValues values ∧ + interpreted.request.rank = Aiur.AIR.packRank rankBytes ∧ + interpreted.rankBytes = rankBytes ∧ + interpreted.selector = + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry ∧ + interpreted.multiplicity = multiplicity ∧ + emission.CallsAt interpreted.calls ∧ + Aiur.AIR.CallsEmitted (Aiur.AIR.packRank rankBytes) 1 + emission.equations queries interpreted.calls +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.slotMessage_chosen +∀ (width : Nat) (branchless : Bool) {parts : List (Aiur.G × List Aiur.G)}, + (branchless = true → parts.length = 1) → + (∀ (part : Aiur.G × List Aiur.G), part ∈ parts → Aiur.AIR.booleanConstraint part.fst = 0) → + parts.length < Aiur.gSize.toNat → + Aiur.AIR.selectorSum (List.map Prod.fst parts) = 1 → + ∀ {chosen : Aiur.G × List Aiur.G}, + chosen ∈ parts → + chosen.fst = 1 → + Aiur.AIR.padMessage width (Aiur.AIR.slotMessage branchless parts) = Aiur.AIR.padMessage width chosen.snd +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.emitRow_message +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (functionIndex : Aiur.Bytecode.FunIdx) (rank : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (function : Aiur.Bytecode.Function) + (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.Block.lookupShapes program none function.body = true → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Function.emitRow row selector functionIndex rank values column lookup function = some emission → + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry = 1 → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.returns.length < Aiur.gSize.toNat → + ∀ (width : Nat) (branchless : Bool), + (branchless = true → emission.returns.length = 1) → + ∀ {request : Aiur.Bytecode.AIR.Call}, + (1, request) ∈ emission.returns → + Aiur.AIR.padMessage width + (Aiur.AIR.slotMessage branchless + (List.map (fun part => (part.fst, Aiur.AIR.functionMessage part.snd)) emission.returns)) = + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage request) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_equation_querySlots +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block), + Aiur.Bytecode.Block.rowBounds selector block → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + incoming = (Aiur.Bytecode.Block.selectorFlow selector block).entry → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + Aiur.AIR.QuerySlots incoming lookup emission.lookup emission.queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.QuerySlots.slot_multiplicity +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QuerySlots gate start finish queries → + ∀ (slot : Nat), Aiur.AIR.querySlotMultiplicity queries slot = Aiur.G.ofNat (Aiur.AIR.queryCount queries slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.QuerySlots.multiplicity_boolean +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QuerySlots gate start finish queries → + ∀ (slot : Nat), Aiur.AIR.querySlotMultiplicity queries slot = 0 ∨ Aiur.AIR.querySlotMultiplicity queries slot = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.QuerySlots.active_singleton +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QuerySlots gate start finish queries → + ∀ {query : Aiur.AIR.QueryPart}, + query ∈ queries → query.selector = 1 → Aiur.AIR.activeQuerySlot queries query.slot = [query] +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.QuerySlots.slot_message +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QuerySlots gate start finish queries → + ∀ (width : Nat) (branchless : Bool), + (branchless = true → ∀ (slot : Nat), (Aiur.AIR.querySlotParts queries slot).length ≤ 1) → + ∀ {query : Aiur.AIR.QueryPart}, + query ∈ queries → + query.selector = 1 → + Aiur.AIR.padMessage width (Aiur.AIR.slotMessage branchless (Aiur.AIR.querySlotParts queries query.slot)) = + Aiur.AIR.padMessage width query.message +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.QuerySlots.queries_reflect +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QuerySlots gate start finish queries → + ∀ (width : Nat) (branchless : Bool), + (branchless = true → ∀ (slot : Nat), (Aiur.AIR.querySlotParts queries slot).length ≤ 1) → + ∀ (limit : Nat), + List.map (Aiur.AIR.padMessage width) (Aiur.AIR.encodedQueries branchless queries limit) = + List.map (Aiur.AIR.padMessage width) (Aiur.AIR.decodedQueries queries limit) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.QuerySlots.padded_balance +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QuerySlots gate start finish queries → + ∀ (width : Nat) (branchless : Bool), + (branchless = true → ∀ (slot : Nat), (Aiur.AIR.querySlotParts queries slot).length ≤ 1) → + ∀ (limit : Nat) (providers : List (Aiur.AIR.Provider (List Aiur.G))), + Aiur.AIR.PaddedLookupBalance width (Aiur.AIR.encodedQueries branchless queries limit) providers → + Aiur.AIR.PaddedLookupBalance width (Aiur.AIR.decodedQueries queries limit) providers +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.decodedQueries_length +∀ (queries : List Aiur.AIR.QueryPart) (limit : Nat), (Aiur.AIR.decodedQueries queries limit).length ≤ limit +AXIOMS [propext] +ROOT Aiur.Bytecode.Block.emitRow_queried_pool +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block), + Aiur.Bytecode.Block.rowBounds selector block → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + incoming = (Aiur.Bytecode.Block.selectorFlow selector block).entry → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + ∀ {emissions : List Aiur.AIR.BlockEmission}, + emission ∈ emissions → emission.QueriesIn (Aiur.AIR.blockQueryPool emissions) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.emitRow_pool_valid +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {emissions : List Aiur.AIR.BlockEmission}, + Aiur.AIR.GlobalLookups tables width (Aiur.AIR.blockQueryPool emissions) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (program : Aiur.Bytecode.Toplevel) (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) + (functionIndex : Aiur.Bytecode.FunIdx) (rankBytes : Fin 6 → Aiur.G) (values : Array Aiur.AIR.RowValue) + (column lookup : Nat) (function : Aiur.Bytecode.Function), + program.functions[functionIndex]? = some function → + values.size = function.layout.inputSize → + Aiur.Bytecode.Block.lookupShapes program none function.body = true → + Aiur.Bytecode.Block.rowBounds selector function.body → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Function.emitRow row selector functionIndex (Aiur.AIR.packRank rankBytes) values + column lookup function = + some emission → + emission ∈ emissions → + ∀ (multiplicity : Aiur.G), + multiplicity ≠ 0 → + Aiur.AIR.activityConstraint multiplicity + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry = + 0 → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + ∃ interpreted, + Aiur.AIR.FunctionRow.Valid program (Aiur.AIR.memoryFacts tables.memory) interpreted ∧ + (1, interpreted.request) ∈ emission.returns ∧ + interpreted.request.function = functionIndex ∧ + interpreted.request.inputs = Aiur.AIR.rowValues values ∧ + interpreted.request.rank = Aiur.AIR.packRank rankBytes ∧ + interpreted.rankBytes = rankBytes ∧ + interpreted.selector = + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry ∧ + interpreted.multiplicity = multiplicity ∧ + emission.CallsAt interpreted.calls ∧ + Aiur.AIR.CallsEmitted (Aiur.AIR.packRank rankBytes) 1 + emission.equations (Aiur.AIR.blockQueryPool emissions) + interpreted.calls +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitMembers_spec +∀ (row : Nat → Aiur.G) (rank : Aiur.G) (column lookup selectorBase : Nat) (program : Aiur.Bytecode.Toplevel) + (indices : List Aiur.Bytecode.FunIdx) {members : List Aiur.AIR.MemberEmission}, + Aiur.AIR.emitMembers row rank column lookup selectorBase program indices = some members → + List.map Aiur.AIR.MemberEmission.functionIndex members = indices ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_spec +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + emission = Aiur.AIR.circuitEmission row circuit emission.members ∧ + List.map Aiur.AIR.MemberEmission.functionIndex emission.members = circuit.members.toList ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ emission.members → + Aiur.AIR.MemberEmission.FromProgram row (Aiur.AIR.packRank (Aiur.AIR.circuitRankBytes row circuit.layout)) + (circuit.layout.inputSize + circuit.layout.selectors + 1 + 6) 4 program member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_boolean +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + Aiur.AIR.booleanConstraint emission.selector = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_active_member +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + circuit.members.size < Aiur.gSize.toNat → + emission.multiplicity ≠ 0 → + ∃ member, + member ∈ emission.members ∧ + Aiur.AIR.MemberEmission.entry row member = 1 ∧ + Aiur.AIR.MemberEmission.FromProgram row (Aiur.AIR.packRank emission.rankBytes) + (circuit.layout.inputSize + circuit.layout.selectors + 1 + 6) 4 program member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_querySlots +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + circuit.members.size < Aiur.gSize.toNat → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ emission.members → + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row member) member.function.body) → + 4 ≤ circuit.layout.lookups → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ emission.members → member.body.lookup ≤ circuit.layout.lookups) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + Aiur.AIR.QuerySlots emission.selector 1 emission.lookupCount emission.queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitEmission_rank_queried +∀ {row : Nat → Aiur.G} {circuit : Aiur.Bytecode.Circuit} {members : List Aiur.AIR.MemberEmission} + {queries : List (List Aiur.G)}, + (Aiur.AIR.circuitEmission row circuit members).QueriesIn queries → + (Aiur.AIR.circuitEmission row circuit members).selector = 1 → + List.map Aiur.AIR.rangeMessage + (Aiur.AIR.rankByteQueries (Aiur.AIR.circuitEmission row circuit members).rankBytes) ⊆ + queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemberEmission.FromProgram.return_count +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {column lookup : Nat} {program : Aiur.Bytecode.Toplevel} + {member : Aiur.AIR.MemberEmission}, + Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member → + Aiur.Bytecode.Block.lookupShapes program none member.function.body = true → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) + member.function.body).returns.length < + Aiur.gSize.toNat → + (∀ (equation : Aiur.G), equation ∈ member.body.equations → equation = 0) → + List.count 1 (List.map Prod.fst member.body.returns) = + Aiur.AIR.gateCount (Aiur.AIR.MemberEmission.entry row member) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitEmission_return_count +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {column lookup : Nat} {program : Aiur.Bytecode.Toplevel} + {circuit : Aiur.Bytecode.Circuit} {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member) → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.Bytecode.Block.lookupShapes program none member.function.body = true) → + members.length < Aiur.gSize.toNat → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) + member.function.body).returns.length < + Aiur.gSize.toNat) → + (∀ (equation : Aiur.G), equation ∈ (Aiur.AIR.circuitEmission row circuit members).equations → equation = 0) → + (Aiur.AIR.circuitEmission row circuit members).selector = 1 → + List.count 1 (List.map Prod.fst (Aiur.AIR.circuitEmission row circuit members).returns) = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitEmission_return_message +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {column lookup : Nat} {program : Aiur.Bytecode.Toplevel} + {circuit : Aiur.Bytecode.Circuit} {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member) → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.Bytecode.Block.lookupShapes program none member.function.body = true) → + members.length < Aiur.gSize.toNat → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) + member.function.body).returns.length < + Aiur.gSize.toNat) → + (∀ (equation : Aiur.G), equation ∈ (Aiur.AIR.circuitEmission row circuit members).equations → equation = 0) → + (Aiur.AIR.circuitEmission row circuit members).selector = 1 → + ∀ (width : Nat), + ((Aiur.AIR.circuitEmission row circuit members).branchless = true → + (Aiur.AIR.circuitEmission row circuit members).returns.length ≤ 1) → + ∀ {request : Aiur.Bytecode.AIR.Call}, + (1, request) ∈ (Aiur.AIR.circuitEmission row circuit members).returns → + Aiur.AIR.padMessage width ((Aiur.AIR.circuitEmission row circuit members).lookup 0).snd = + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage request) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_valid +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {emissions : List Aiur.AIR.CircuitEmission}, + Aiur.AIR.GlobalLookups tables width (Aiur.AIR.circuitQueryPool emissions) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + emission ∈ emissions → + circuit.members.size < Aiur.gSize.toNat → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row part) part.function.body) → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + Aiur.Bytecode.Block.lookupShapes program none part.function.body = true) → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row part) + part.function.body).returns.length < + Aiur.gSize.toNat) → + 4 ≤ circuit.layout.lookups → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → part.body.lookup ≤ circuit.layout.lookups) → + (emission.branchless = true → emission.returns.length ≤ 1) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.multiplicity ≠ 0 → + ∃ selected, + selected ∈ emission.members ∧ + ∃ interpreted, + Aiur.AIR.FunctionRow.Valid program (Aiur.AIR.memoryFacts tables.memory) + interpreted ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = + Aiur.AIR.rowValues + (Aiur.AIR.rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = Aiur.AIR.packRank emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ + interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + Aiur.AIR.padMessage width (emission.lookup 0).snd = + Aiur.AIR.padMessage width + (Aiur.AIR.functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + List.map Aiur.AIR.functionMessage interpreted.requests ⊆ + Aiur.AIR.circuitQueryPool emissions ∧ + List.map Aiur.AIR.rangeMessage interpreted.byteQueries ⊆ + Aiur.AIR.circuitQueryPool emissions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Ctrl.controlCounts_spec +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (ctrl : Aiur.Bytecode.Ctrl), + ctrl.controlCounts.Describes (Aiur.Bytecode.Ctrl.selectorFlow selector ctrl) ∧ + 0 < ctrl.controlCounts.nodes ∧ + (ctrl.controlCounts.nodes < Aiur.gSize.toNat → Aiur.Bytecode.Ctrl.rowBounds selector ctrl) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.controlCounts_spec +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block), + block.controlCounts.Describes (Aiur.Bytecode.Block.selectorFlow selector block) ∧ + 0 < block.controlCounts.nodes ∧ + (block.controlCounts.nodes < Aiur.gSize.toNat → Aiur.Bytecode.Block.rowBounds selector block) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.rowBounds_of_controlCounts +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block), + block.controlCounts.nodes < Aiur.gSize.toNat → Aiur.Bytecode.Block.rowBounds selector block +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.return_bound_of_controlCounts +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block), + block.controlCounts.nodes < Aiur.gSize.toNat → + (Aiur.Bytecode.Block.selectorFlow selector block).returns.length < Aiur.gSize.toNat +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.returns_le_selectors +∀ (selector : Aiur.Bytecode.SelIdx → Aiur.G) (block : Aiur.Bytecode.Block), + (Aiur.Bytecode.Block.selectorFlow selector block).returns.length ≤ block.controlCounts.leaves +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.validateRowCounts_circuit +∀ {program : Aiur.Bytecode.Toplevel}, + program.validateRowCounts = true → + ∀ {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ program.circuits → Aiur.Bytecode.Circuit.validateRowCounts program circuit = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.validateRowCounts_spec +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + circuit.members.size < Aiur.gSize.toNat ∧ + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → part.function.body.controlCounts.nodes < Aiur.gSize.toNat) ∧ + (List.map (fun part => part.function.body.controlCounts.leaves) emission.members).sum ≤ + circuit.layout.selectors +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_count_bounds +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + circuit.members.size < Aiur.gSize.toNat ∧ + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row part) part.function.body) ∧ + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row part) + part.function.body).returns.length < + Aiur.gSize.toNat) ∧ + (emission.branchless = true → emission.returns.length ≤ 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_valid_checked +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {emissions : List Aiur.AIR.CircuitEmission}, + Aiur.AIR.GlobalLookups tables width (Aiur.AIR.circuitQueryPool emissions) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + emission ∈ emissions → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → Aiur.Bytecode.Block.lookupShapes program none part.function.body = true) → + 4 ≤ circuit.layout.lookups → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → part.body.lookup ≤ circuit.layout.lookups) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.multiplicity ≠ 0 → + ∃ selected, + selected ∈ emission.members ∧ + ∃ interpreted, + Aiur.AIR.FunctionRow.Valid program (Aiur.AIR.memoryFacts tables.memory) interpreted ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = + Aiur.AIR.rowValues + (Aiur.AIR.rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = Aiur.AIR.packRank emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ + interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + Aiur.AIR.padMessage width (emission.lookup 0).snd = + Aiur.AIR.padMessage width + (Aiur.AIR.functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + List.map Aiur.AIR.functionMessage interpreted.requests ⊆ + Aiur.AIR.circuitQueryPool emissions ∧ + List.map Aiur.AIR.rangeMessage interpreted.byteQueries ⊆ + Aiur.AIR.circuitQueryPool emissions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuit_row_counts +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + Aiur.Bytecode.Circuit.validateRowCounts backend.compiled.bytecode circuit = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_valid_in_pool +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {emissions : List Aiur.AIR.CircuitEmission} + {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + emission ∈ emissions → + Aiur.AIR.circuitQueryPool emissions ⊆ queries → + circuit.members.size < Aiur.gSize.toNat → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row part) part.function.body) → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + Aiur.Bytecode.Block.lookupShapes program none part.function.body = true) → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row part) + part.function.body).returns.length < + Aiur.gSize.toNat) → + 4 ≤ circuit.layout.lookups → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → part.body.lookup ≤ circuit.layout.lookups) → + (emission.branchless = true → emission.returns.length ≤ 1) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.multiplicity ≠ 0 → + ∃ selected, + selected ∈ emission.members ∧ + ∃ interpreted, + Aiur.AIR.FunctionRow.Valid program (Aiur.AIR.memoryFacts tables.memory) + interpreted ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = + Aiur.AIR.rowValues + (Aiur.AIR.rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = Aiur.AIR.packRank emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ + interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + Aiur.AIR.padMessage width (emission.lookup 0).snd = + Aiur.AIR.padMessage width + (Aiur.AIR.functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + List.map Aiur.AIR.functionMessage interpreted.requests ⊆ + queries ∧ + List.map Aiur.AIR.rangeMessage interpreted.byteQueries ⊆ + queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.suppliedWeight_padded_congr +∀ {width : Nat} {left right : List (Aiur.AIR.Provider (List Aiur.G))}, + List.Forall₂ (Aiur.AIR.Provider.PaddedEq width) left right → + ∀ (message : List Aiur.G), + Aiur.AIR.suppliedWeight message (Aiur.AIR.mapProviders (Aiur.AIR.padMessage width) left) = + Aiur.AIR.suppliedWeight message (Aiur.AIR.mapProviders (Aiur.AIR.padMessage width) right) +AXIOMS [propext] +ROOT Aiur.AIR.PaddedLookupBalance.congr_providers +∀ {width : Nat} {queries : List (List Aiur.G)} {left right : List (Aiur.AIR.Provider (List Aiur.G))}, + Aiur.AIR.PaddedLookupBalance width queries left → + List.Forall₂ (Aiur.AIR.Provider.PaddedEq width) left right → Aiur.AIR.PaddedLookupBalance width queries right +AXIOMS [propext] +ROOT Aiur.Bytecode.Circuit.emitRow_provider +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → Aiur.Bytecode.Block.lookupShapes program none part.function.body = true) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.multiplicity ≠ 0 → + ∀ (width : Nat), + ∃ request, + (1, request) ∈ emission.returns ∧ + Aiur.AIR.padMessage width (emission.lookup 0).snd = + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage request) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.AuxiliaryTables.global_of_circuit_balance +∀ (tables : Aiur.AIR.AuxiliaryTables) {width : Nat} {queries : List (List Aiur.G)} + {emissions : List Aiur.AIR.CircuitEmission} {functions : List Aiur.AIR.FunctionRow}, + Aiur.AIR.PaddedLookupBalance width queries (tables.circuitProviders emissions) → + queries.length < Aiur.gSize.toNat → + (∀ (query : List Aiur.G), query ∈ queries → query.length ≤ width) → + List.Forall₂ (Aiur.AIR.FunctionRow.Provides width) emissions functions → + Aiur.AIR.GlobalLookups (tables.withFunctions functions) width queries +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.inactive_valid +∀ (program : Aiur.Bytecode.Toplevel) (memory : Aiur.Bytecode.AIR.Memory), + Aiur.AIR.FunctionRow.Valid program memory Aiur.AIR.FunctionRow.inactive +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.provider_row +∀ {program : Aiur.Bytecode.Toplevel} (witness : Aiur.AIR.CircuitWitness), + Aiur.AIR.CircuitWitness.Emitted program witness → + witness.Satisfied → + Aiur.Bytecode.Circuit.validateRowCounts program witness.circuit = true → + Aiur.AIR.CircuitWitness.Shapes program witness → + ∀ (width : Nat), ∃ row, Aiur.AIR.FunctionRow.Provides width witness.emission row +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.interpreted_row +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)} + {emissions : List Aiur.AIR.CircuitEmission}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ {program : Aiur.Bytecode.Toplevel} (witness : Aiur.AIR.CircuitWitness), + Aiur.AIR.CircuitWitness.Emitted program witness → + witness.Satisfied → + Aiur.Bytecode.Circuit.validateRowCounts program witness.circuit = true → + Aiur.AIR.CircuitWitness.Shapes program witness → + witness.LookupBounds → + witness.emission ∈ emissions → + Aiur.AIR.circuitQueryPool emissions ⊆ queries → + ∃ row, + Aiur.AIR.FunctionRow.Valid program (Aiur.AIR.memoryFacts tables.memory) row ∧ + Aiur.AIR.FunctionRow.Provides width witness.emission row ∧ + Aiur.AIR.FunctionRow.QueriesIn queries row +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitWitnesses_interpret +∀ (tables : Aiur.AIR.AuxiliaryTables) {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness) + {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.PaddedLookupBalance width queries (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + queries.length < Aiur.gSize.toNat → + (∀ (query : List Aiur.G), query ∈ queries → query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + program.validateRowCounts = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Emitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) ⊆ queries → + ∃ functions, + List.Forall₂ (Aiur.AIR.FunctionRow.Provides width) + (List.map (fun x => x.emission) witnesses) functions ∧ + Aiur.AIR.GlobalLookups (tables.withFunctions functions) width queries ∧ + (∀ (row : Aiur.AIR.FunctionRow), + row ∈ functions → + Aiur.AIR.FunctionRow.Valid program (Aiur.AIR.memoryFacts tables.memory) row) ∧ + ∀ (row : Aiur.AIR.FunctionRow), + row ∈ functions → Aiur.AIR.FunctionRow.QueriesIn queries row +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitWitnesses_execute +∀ (tables : Aiur.AIR.AuxiliaryTables) {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness) + {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.PaddedLookupBalance width queries (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + queries.length < Aiur.gSize.toNat → + (∀ (query : List Aiur.G), query ∈ queries → query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + program.validateRowCounts = true → + program.validateLookupShapes = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Emitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) ⊆ queries → + ∀ {request : Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Call.LookupShape program request → + Aiur.AIR.functionMessage request ∈ queries → + Aiur.Bytecode.AIR.Execution program (Aiur.AIR.memoryFacts tables.memory) request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.PaddedLookupBalance.congr_queries +∀ {width : Nat} {left right : List (List Aiur.G)} {providers : List (Aiur.AIR.Provider (List Aiur.G))}, + Aiur.AIR.PaddedLookupBalance width left providers → + List.map (Aiur.AIR.padMessage width) left = List.map (Aiur.AIR.padMessage width) right → + Aiur.AIR.PaddedLookupBalance width right providers +AXIOMS [propext] +ROOT Aiur.BoundVerifier.Backend.public_circuit_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + (tables : Aiur.AIR.AuxiliaryTables) (witnesses : List Aiur.AIR.CircuitWitness) (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses)).length + 1 < Aiur.gSize.toNat → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) → query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.circuit ∈ backend.compiled.bytecode.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Emitted backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.QueryWriters.single +∀ {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QueryWriters start finish queries → ∀ (slot : Nat), (Aiur.AIR.querySlotParts queries slot).length ≤ 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.emitRow_terminal_writers +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (function : Aiur.Bytecode.Function) + (functionIndex : Aiur.Bytecode.FunIdx) (rank : Aiur.G) (inputs : Array Aiur.AIR.RowValue) (column lookup : Nat) + {emission : Aiur.AIR.BlockEmission}, + function.hasTerminalControl = true → + Aiur.Bytecode.Function.emitRow row selector functionIndex rank inputs column lookup function = some emission → + Aiur.AIR.QueryWriters lookup emission.lookup emission.queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitEmission_queryWriters +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {column : Nat} {program : Aiur.Bytecode.Toplevel} + {circuit : Aiur.Bytecode.Circuit} {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromProgram row rank column 4 program member) → + (Aiur.AIR.circuitEmission row circuit members).branchless = true → + (∀ (member : Aiur.AIR.MemberEmission), member ∈ members → member.body.lookup ≤ circuit.layout.lookups) → + Aiur.AIR.QueryWriters 1 circuit.layout.lookups (Aiur.AIR.circuitEmission row circuit members).queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_queryWriters +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + emission.branchless = true → + (∀ (member : Aiur.AIR.MemberEmission), member ∈ emission.members → member.body.lookup ≤ circuit.layout.lookups) → + Aiur.AIR.QueryWriters 1 emission.lookupCount emission.queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_queries_reflect +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow row program circuit = some emission → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + 4 ≤ circuit.layout.lookups → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ emission.members → member.body.lookup ≤ circuit.layout.lookups) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + ∀ (width : Nat), + List.map (Aiur.AIR.padMessage width) + (Aiur.AIR.encodedQueries emission.branchless emission.queries emission.lookupCount) = + List.map (Aiur.AIR.padMessage width) (Aiur.AIR.decodedQueries emission.queries emission.lookupCount) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.slotMessage_member_length +∀ (branchless : Bool) {parts : List (Aiur.G × List Aiur.G)} {part : Aiur.G × List Aiur.G}, + part ∈ parts → part.snd.length ≤ (Aiur.AIR.slotMessage branchless parts).length +AXIOMS [propext] +ROOT Aiur.AIR.QuerySlots.decoded_widths +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + Aiur.AIR.QuerySlots gate start finish queries → + ∀ (branchless : Bool) (width : Nat), + (∀ (message : List Aiur.G), + message ∈ Aiur.AIR.encodedQueries branchless queries finish → message.length ≤ width) → + ∀ (message : List Aiur.G), message ∈ Aiur.AIR.decodedQueries queries finish → message.length ≤ width +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitWitnesses_queries_reflect +∀ {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness), + program.validateRowCounts = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → Aiur.AIR.CircuitWitness.Emitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + ∀ (width : Nat), + List.map (Aiur.AIR.padMessage width) + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) = + List.map (Aiur.AIR.padMessage width) + (Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitWitnesses_decoded_widths +∀ {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness), + program.validateRowCounts = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → Aiur.AIR.CircuitWitness.Emitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + ∀ (width : Nat), + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + ∀ (query : List Aiur.G), + query ∈ Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) → query.length ≤ width +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.encoded_circuit_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + (tables : Aiur.AIR.AuxiliaryTables) (witnesses : List Aiur.AIR.CircuitWitness) (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)).length + 1 < Aiur.gSize.toNat → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.circuit ∈ backend.compiled.bytecode.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Emitted backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitTraces.slot_sum_append +∀ {circuits : List Aiur.Bytecode.Circuit} (traces : Aiur.AIR.CircuitTraces circuits) (otherSlots : List Nat) + (otherActive : List Bool) (otherDegrees : List Nat), + Aiur.lookupSlotSum (List.map (fun x => x.layout.lookups) circuits ++ otherSlots) (traces.bitmap ++ otherActive) + (traces.degrees ++ otherDegrees) = + Option.map (fun x => traces.capacity + x) (Aiur.lookupSlotSum otherSlots otherActive otherDegrees) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.CircuitTraces.capacity_bounded +∀ {circuits : List Aiur.Bytecode.Circuit} (traces : Aiur.AIR.CircuitTraces circuits) {otherSlots : List Nat} + {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound (List.map (fun x => x.layout.lookups) circuits ++ otherSlots) (traces.bitmap ++ otherActive) + (traces.degrees ++ otherDegrees) = + some result → + traces.capacity + 1 < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.emitCircuitWitness_spec +∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} {values : Nat → Aiur.G} + {witness : Aiur.AIR.CircuitWitness}, + Aiur.AIR.emitCircuitWitness program circuit values = some witness → + witness.circuit = circuit ∧ + witness.values = values ∧ + Aiur.AIR.CircuitWitness.Emitted program witness ∧ witness.emission.lookupCount = circuit.layout.lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.encodedQueries_length +∀ (branchless : Bool) (queries : List Aiur.AIR.QueryPart) (limit : Nat), + (Aiur.AIR.encodedQueries branchless queries limit).length ≤ limit +AXIOMS [propext] +ROOT Aiur.AIR.encodedCircuitQueryPool_uniform_bound +∀ (witnesses : List Aiur.AIR.CircuitWitness) (slots : Nat), + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.emission.lookupCount ≤ slots) → + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)).length ≤ witnesses.length * slots +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.emitCircuitWitnesses_spec +∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} {values : List (Nat → Aiur.G)} + {witnesses : List Aiur.AIR.CircuitWitness}, + List.mapM (Aiur.AIR.emitCircuitWitness program circuit) values = some witnesses → + witnesses.length = values.length ∧ + ∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → + witness.circuit = circuit ∧ + Aiur.AIR.CircuitWitness.Emitted program witness ∧ witness.emission.lookupCount = circuit.layout.lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitTraces.emitWitnesses_spec +∀ {circuits : List Aiur.Bytecode.Circuit} (traces : Aiur.AIR.CircuitTraces circuits) {program : Aiur.Bytecode.Toplevel} + {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitWitnesses program traces = some witnesses → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.circuit ∈ circuits ∧ Aiur.AIR.CircuitWitness.Emitted program witness) ∧ + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)).length ≤ traces.capacity +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.trace_circuit_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + (tables : Aiur.AIR.AuxiliaryTables) (traces : Aiur.AIR.CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitWitnesses backend.compiled.bytecode traces = some witnesses → + ∀ {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound + (List.map (fun x => x.layout.lookups) backend.compiled.bytecode.circuits.toList ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = + some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, + rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.singletonCircuits_constrained +∀ (program : Aiur.Bytecode.Toplevel) (nameOf : Aiur.Bytecode.FunIdx → String), + Aiur.Bytecode.CircuitsConstrained program.functions (program.singletonCircuits nameOf) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.CompiledToplevel.groupFunctions_constrained +∀ {before after : Aiur.CompiledToplevel} {groups : Array (String × Array String)}, + Aiur.Bytecode.CircuitsConstrained before.bytecode.functions before.bytecode.circuits → + before.groupFunctions groups = Except.ok after → + Aiur.Bytecode.CircuitsConstrained after.bytecode.functions after.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_circuits_constrained +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx), + Aiur.Bytecode.CircuitsConstrained (Aiur.finishCompilation source raw names).bytecode.functions + (Aiur.finishCompilation source raw names).bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.compile_circuits_constrained +∀ {source : Aiur.Source.Toplevel} {compiled : Aiur.CompiledToplevel}, + source.compile = Except.ok compiled → + Aiur.Bytecode.CircuitsConstrained compiled.bytecode.functions compiled.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuits_constrained +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + Aiur.Bytecode.CircuitsConstrained backend.compiled.bytecode.functions backend.compiled.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.validateLookupShapes_function +∀ {program : Aiur.Bytecode.Toplevel}, + program.validateLookupShapes = true → + ∀ {function : Aiur.Bytecode.Function} {index : Aiur.Bytecode.FunIdx}, + program.functions[index]? = some function → + function.constrained = true → Aiur.Bytecode.Block.lookupShapes program none function.body = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.shapes_of_compiled +∀ {program : Aiur.Bytecode.Toplevel}, + program.validateLookupShapes = true → + Aiur.Bytecode.CircuitsConstrained program.functions program.circuits → + ∀ (witness : Aiur.AIR.CircuitWitness), + witness.circuit ∈ program.circuits → + Aiur.AIR.CircuitWitness.Emitted program witness → Aiur.AIR.CircuitWitness.Shapes program witness +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.witness_shapes +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + (witness : Aiur.AIR.CircuitWitness), + witness.circuit ∈ backend.compiled.bytecode.circuits → + Aiur.AIR.CircuitWitness.Emitted backend.compiled.bytecode witness → + Aiur.AIR.CircuitWitness.Shapes backend.compiled.bytecode witness +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.compiled_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + (tables : Aiur.AIR.AuxiliaryTables) (traces : Aiur.AIR.CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitWitnesses backend.compiled.bytecode traces = some witnesses → + ∀ {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound + (List.map (fun x => x.layout.lookups) backend.compiled.bytecode.circuits.toList ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = + some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.LookupBounds) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opLayout_lookupUsage +∀ (op : Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = #[] → + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.functionLayout.lookups = + initial.functionLayout.lookups + op.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opsLayout_lookupUsage +∀ (ops : Array Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = #[] → + (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.functionLayout.lookups = + initial.functionLayout.lookups + (List.map Aiur.Bytecode.Op.lookupUsage ops.toList).sum +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitOp_lookupUsage +∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {op : Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} + {emission : Aiur.AIR.OpEmission}, + Aiur.AIR.emitOp row selector rank op values = some emission → emission.queries.length = op.lookupUsage +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.emitOps_lookupUsage +∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {ops : List Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} + {column : Nat} {emission : Aiur.AIR.OpsEmission}, + Aiur.AIR.emitOps row selector rank ops values column = some emission → + emission.queries.length = (List.map Aiur.Bytecode.Op.lookupUsage ops).sum +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.branchRows_lookupUsage +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (matched : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block) {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.branchRows row selector context matched values column lookup branches fallback = some emission → + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + ∀ (emission : Aiur.AIR.BlockEmission), + Aiur.Bytecode.Block.emitRow row selector context (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry + values column lookup pair.snd = + some emission → + emission.lookup = lookup + pair.snd.lookupUsage) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → + ∀ (emission : Aiur.AIR.BlockEmission), + Aiur.Bytecode.Block.emitRow row selector context (Aiur.Bytecode.Block.selectorFlow selector block).entry + values (column + branches.size) lookup block = + some emission → + emission.lookup = lookup + block.lookupUsage) → + emission.lookup = lookup + Aiur.Bytecode.branchLookupUsage branches fallback +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Ctrl.emitRow_lookupUsage +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (ctrl : Aiur.Bytecode.Ctrl) + {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Ctrl.emitRow row selector context incoming values column lookup ctrl = some emission → + emission.lookup = lookup + ctrl.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_lookupUsage +∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) + (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block) + {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → + emission.lookup = lookup + block.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.ctrlLayout_lookupUsage +∀ (ctrl : Aiur.Bytecode.Ctrl) (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = #[] → + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout ctrl) initial).snd.functionLayout.lookups = + initial.functionLayout.lookups + ctrl.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.blockLayout_lookupUsage +∀ (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = #[] → + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) initial).snd.functionLayout.lookups = + initial.functionLayout.lookups + block.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Function.compile_lookupLayout +∀ {layoutMap : Aiur.LayoutMap} {function : Aiur.Concrete.Function} {body : Aiur.Bytecode.Block} + {state : Aiur.Concrete.Bytecode.LayoutMState}, + Aiur.Concrete.Function.compile layoutMap function = Except.ok (body, state) → + state.functionLayout.lookups = 4 + body.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Decls.toBytecode_lookupLayout +∀ {decls : Aiur.Concrete.Decls} {program : Aiur.Bytecode.Toplevel} + {names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx}, + decls.toBytecode = Except.ok (program, names) → Aiur.Bytecode.FunctionsLookupLayout program.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.rewriteCtrl_lookupUsage +∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) (ctrl : Aiur.Bytecode.Ctrl), + (Aiur.Bytecode.rewriteCtrl rename ctrl).lookupUsage = ctrl.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.rewriteBlock_lookupUsage +∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) (block : Aiur.Bytecode.Block), + (Aiur.Bytecode.rewriteBlock rename block).lookupUsage = block.lookupUsage +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.deduplicate_lookupLayout +∀ (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.FunctionsLookupLayout program.functions → + Aiur.Bytecode.FunctionsLookupLayout program.deduplicate.fst.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_lookupLayout +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx), + Aiur.Bytecode.FunctionsLookupLayout raw.functions → + source.componentRanks = false → + Aiur.Bytecode.FunctionsLookupLayout (Aiur.finishCompilation source raw names).bytecode.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.compile_lookupLayout +∀ {source : Aiur.Source.Toplevel} {compiled : Aiur.CompiledToplevel}, + source.compile = Except.ok compiled → + source.componentRanks = false → Aiur.Bytecode.FunctionsLookupLayout compiled.bytecode.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.functions_lookupLayout +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → Aiur.Bytecode.FunctionsLookupLayout backend.compiled.bytecode.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.singletonCircuits_lookupBound +∀ (program : Aiur.Bytecode.Toplevel) (nameOf : Aiur.Bytecode.FunIdx → String), + Aiur.Bytecode.FunctionsLookupLayout program.functions → + Aiur.Bytecode.CircuitsLookupBound program.functions (program.singletonCircuits nameOf) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.merged_lookupBound +∀ (functions : Array Aiur.Bytecode.Function) (members : Array Aiur.Bytecode.FunIdx), + Aiur.Bytecode.FunctionsLookupLayout functions → + 0 < functions.size → + Aiur.Bytecode.MembersConstrained functions members → + Aiur.Bytecode.MembersLookupBound functions members + (Array.foldl + (fun acc index => if (index == members[0]!) = true then acc else acc.merge functions[index]!.layout) + functions[members[0]!]!.layout members).lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.CompiledToplevel.groupFunctions_lookupBound +∀ {before after : Aiur.CompiledToplevel} {groups : Array (String × Array String)}, + Aiur.Bytecode.FunctionsLookupLayout before.bytecode.functions → + 0 < before.bytecode.functions.size → + Aiur.Bytecode.CircuitsLookupBound before.bytecode.functions before.bytecode.circuits → + before.groupFunctions groups = Except.ok after → + Aiur.Bytecode.CircuitsLookupBound after.bytecode.functions after.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_lookupBound +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx), + Aiur.Bytecode.FunctionsLookupLayout raw.functions → + source.componentRanks = false → + Aiur.Bytecode.CircuitsLookupBound (Aiur.finishCompilation source raw names).bytecode.functions + (Aiur.finishCompilation source raw names).bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.compile_lookupBound +∀ {source : Aiur.Source.Toplevel} {compiled : Aiur.CompiledToplevel}, + source.compile = Except.ok compiled → + source.componentRanks = false → + Aiur.Bytecode.CircuitsLookupBound compiled.bytecode.functions compiled.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuits_lookupBound +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + Aiur.Bytecode.CircuitsLookupBound backend.compiled.bytecode.functions backend.compiled.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.lookupBounds_of_compiled +∀ {program : Aiur.Bytecode.Toplevel}, + Aiur.Bytecode.FunctionsLookupLayout program.functions → + Aiur.Bytecode.CircuitsLookupBound program.functions program.circuits → + ∀ (witness : Aiur.AIR.CircuitWitness), + witness.circuit ∈ program.circuits → Aiur.AIR.CircuitWitness.Emitted program witness → witness.LookupBounds +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.witness_lookupBounds +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ (witness : Aiur.AIR.CircuitWitness), + witness.circuit ∈ backend.compiled.bytecode.circuits → + Aiur.AIR.CircuitWitness.Emitted backend.compiled.bytecode witness → witness.LookupBounds +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.bounded_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ (tables : Aiur.AIR.AuxiliaryTables) (traces : Aiur.AIR.CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitWitnesses backend.compiled.bytecode traces = some witnesses → + ∀ {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound + (List.map (fun x => x.layout.lookups) backend.compiled.bytecode.circuits.toList ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = + some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, + rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.decodeMemoryRow_width +∀ (width : Nat) (columns : Aiur.AIR.MemoryColumns width), (Aiur.AIR.decodeMemoryRow width columns).contents.size = width +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.decodeMemoryRows_size +∀ (width height : Nat) (matrix : Fin height → Aiur.AIR.MemoryColumns width), + (Aiur.AIR.decodeMemoryRows width height matrix).size = height +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.memoryColumnProvider_reflect +∀ (width : Nat) (current next : Aiur.AIR.MemoryColumns width) (transition : Aiur.G), + (∀ (equation : Aiur.G), equation ∈ Aiur.AIR.memoryColumnEquations width current next transition → equation = 0) → + ∀ (messageWidth : Nat), + Aiur.AIR.Provider.PaddedEq messageWidth (Aiur.AIR.memoryColumnProvider width current) + (Aiur.AIR.memoryMessage width (Aiur.AIR.decodeMemoryRow width current).pointer + (Aiur.AIR.decodeMemoryRow width current).contents, + (Aiur.AIR.decodeMemoryRow width current).multiplicity) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.decodeMemoryRows_polynomials +∀ (width height : Nat) (matrix : Fin height → Aiur.AIR.MemoryColumns width), + Aiur.AIR.MemoryMatrixSatisfied width height matrix → + Aiur.AIR.MemoryRowsPolynomials width (Aiur.AIR.decodeMemoryRows width height matrix) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.decodeMemoryRows_valid +∀ (width height : Nat) (matrix : Fin height → Aiur.AIR.MemoryColumns width), + Aiur.AIR.MemoryMatrixSatisfied width height matrix → + Aiur.AIR.MemoryRowsValid width (Aiur.AIR.decodeMemoryRows width height matrix) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.decodeMemoryRows_providers +∀ (width height : Nat) (matrix : Fin height → Aiur.AIR.MemoryColumns width), + Aiur.AIR.mapProviders (fun request => Aiur.AIR.memoryMessage width request.fst request.snd) + (Aiur.AIR.memoryProviders (Aiur.AIR.decodeMemoryRows width height matrix)) = + List.ofFn fun index => + (Aiur.AIR.memoryMessage width (Aiur.AIR.decodeMemoryRow width (matrix index)).pointer + (Aiur.AIR.decodeMemoryRow width (matrix index)).contents, + (Aiur.AIR.decodeMemoryRow width (matrix index)).multiplicity) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.memoryMatrixProviders_reflect +∀ (width height : Nat) (matrix : Fin height → Aiur.AIR.MemoryColumns width), + Aiur.AIR.MemoryMatrixSatisfied width height matrix → + ∀ (messageWidth : Nat), + List.Forall₂ (Aiur.AIR.Provider.PaddedEq messageWidth) (Aiur.AIR.memoryMatrixProviders width height matrix) + (Aiur.AIR.mapProviders (fun request => Aiur.AIR.memoryMessage width request.fst request.snd) + (Aiur.AIR.memoryProviders (Aiur.AIR.decodeMemoryRows width height matrix))) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Decls.toBytecode_memorySizes_distinct +∀ {decls : Aiur.Concrete.Decls} {program : Aiur.Bytecode.Toplevel} + {names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx}, + decls.toBytecode = Except.ok (program, names) → program.memorySizes.toList.Nodup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.deduplicate_memorySizes +∀ (program : Aiur.Bytecode.Toplevel), program.deduplicate.fst.memorySizes = program.memorySizes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_memorySizes +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx), + (Aiur.finishCompilation source raw names).bytecode.memorySizes = raw.memorySizes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.compile_memorySizes_distinct +∀ {source : Aiur.Source.Toplevel} {compiled : Aiur.CompiledToplevel}, + source.compile = Except.ok compiled → compiled.bytecode.memorySizes.toList.Nodup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.memorySizes_distinct +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + backend.compiled.bytecode.memorySizes.toList.Nodup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.memorySizes_canonical +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) (width : Nat), + width ∈ backend.compiled.bytecode.memorySizes.toList → width < Aiur.gSize.toNat +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.slot_sum_append +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths) (otherSlots : List Nat) (otherActive : List Bool) + (otherDegrees : List Nat), + Aiur.lookupSlotSum (List.replicate widths.length 1 ++ otherSlots) (traces.bitmap ++ otherActive) + (traces.degrees ++ otherDegrees) = + Option.map (fun x => traces.capacity + x) (Aiur.lookupSlotSum otherSlots otherActive otherDegrees) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.rows_valid +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths), + traces.Satisfied → ∀ (width : Nat), Aiur.AIR.MemoryRowsValid width (traces.rows width) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.rows_size_le +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths) (width : Nat), (traces.rows width).size ≤ traces.capacity +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.providers_reflect +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths), + widths.Nodup → + traces.Satisfied → + ∀ (messageWidth : Nat), + List.Forall₂ (Aiur.AIR.Provider.PaddedEq messageWidth) traces.providers + (Aiur.AIR.memoryTableProviders widths traces.rows) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.capacity_bounded +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths) {circuits : List Aiur.Bytecode.Circuit} + (functions : Aiur.AIR.CircuitTraces circuits) {otherSlots : List Nat} {otherActive : List Bool} + {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound + (List.map (fun x => x.layout.lookups) circuits ++ (List.replicate widths.length 1 ++ otherSlots)) + (functions.bitmap ++ (traces.bitmap ++ otherActive)) (functions.degrees ++ (traces.degrees ++ otherDegrees)) = + some result → + traces.capacity + 1 < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.functional +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths), + traces.Satisfied → + traces.capacity < Aiur.gSize.toNat → + ∀ {width : Nat} {pointer : Aiur.G} {left right : Array Aiur.G}, + Aiur.AIR.memoryFacts traces.rows width pointer left → + Aiur.AIR.memoryFacts traces.rows width pointer right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.functional_of_budget +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths) {circuits : List Aiur.Bytecode.Circuit} + (functions : Aiur.AIR.CircuitTraces circuits) {otherSlots : List Nat} {otherActive : List Bool} + {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound + (List.map (fun x => x.layout.lookups) circuits ++ (List.replicate widths.length 1 ++ otherSlots)) + (functions.bitmap ++ (traces.bitmap ++ otherActive)) (functions.degrees ++ (traces.degrees ++ otherDegrees)) = + some result → + traces.Satisfied → + ∀ {width : Nat} {pointer : Aiur.G} {left right : Array Aiur.G}, + Aiur.AIR.memoryFacts traces.rows width pointer left → + Aiur.AIR.memoryFacts traces.rows width pointer right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.circuitProviders_reflect +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths), + widths.Nodup → + traces.Satisfied → + ∀ (messageWidth : Nat) (byte1 : Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G) + (byte2 : Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G) (circuits : List Aiur.AIR.CircuitEmission), + List.Forall₂ (Aiur.AIR.Provider.PaddedEq messageWidth) + (Aiur.AIR.circuitProviders circuits ++ + (traces.providers ++ Aiur.AIR.byte1Providers byte1 ++ Aiur.AIR.byte2Providers byte2)) + ((traces.auxiliary byte1 byte2).circuitProviders circuits) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.memory_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ (functions : Aiur.AIR.CircuitTraces backend.compiled.bytecode.circuits.toList) + (memories : Aiur.AIR.MemoryTraces backend.compiled.bytecode.memorySizes.toList) + (byte1 : Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G) (byte2 : Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G) + {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitWitnesses backend.compiled.bytecode functions = some witnesses → + ∀ {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound + (List.map (fun x => x.layout.lookups) backend.compiled.bytecode.circuits.toList ++ + (List.replicate backend.compiled.bytecode.memorySizes.size 1 ++ otherSlots)) + (functions.bitmap ++ (memories.bitmap ++ otherActive)) + (functions.degrees ++ (memories.degrees ++ otherDegrees)) = + some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (Aiur.AIR.circuitProviders (List.map (fun x => x.emission) witnesses) ++ + (memories.providers ++ Aiur.AIR.byte1Providers byte1 ++ Aiur.AIR.byte2Providers byte2)) → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + memories.Satisfied → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts memories.rows) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.fixedTraceHeights_sound +∀ {heights : List Nat} {active : List Bool} {degrees : List Nat}, + Aiur.fixedTraceHeights heights active degrees = true → Aiur.FixedTraceHeights heights active degrees +AXIOMS [propext, Quot.sound] +ROOT Aiur.fixedTraceHeights_complete +∀ {heights : List Nat} {active : List Bool} {degrees : List Nat}, + Aiur.FixedTraceHeights heights active degrees → Aiur.fixedTraceHeights heights active degrees = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.FixedTraceHeights.alignment +∀ {heights : List Nat} {active : List Bool} {degrees : List Nat}, + Aiur.FixedTraceHeights heights active degrees → + heights.length = active.length ∧ degrees.length = (List.filter id active).length +AXIOMS [propext] +ROOT Aiur.fixedTraceHeights_bytes +∀ {active : List Bool} {degrees : List Nat}, + Aiur.fixedTraceHeights [256, 65536] active degrees = true → active = [true, true] ∧ degrees = [8, 16] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.byte1ColumnProvider_reflect +∀ (kind : Aiur.AIR.Byte1Kind) (row : Fin 256) (columns : Aiur.AIR.Byte1Columns), + Aiur.AIR.byte1ColumnProvider kind row columns = + (Aiur.AIR.byte1Request kind (Aiur.G.ofNat ↑row) (Aiur.AIR.byte1Outputs kind row), columns kind.column) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.byte2ColumnProvider_reflect +∀ (kind : Aiur.AIR.Byte2Kind) (row : Fin 65536) (columns : Aiur.AIR.Byte2Columns), + Aiur.AIR.byte2ColumnProvider kind row columns = + (Aiur.AIR.byte2Request kind (Aiur.AIR.byteRangeMessage row).fst (Aiur.AIR.byteRangeMessage row).snd + (Aiur.AIR.byte2Outputs kind row), + columns kind.column) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.CircuitTraces.fixed_heights_append +∀ {circuits : List Aiur.Bytecode.Circuit} (traces : Aiur.AIR.CircuitTraces circuits) (heights : List Nat) + (active : List Bool) (degrees : List Nat), + Aiur.fixedTraceHeights (List.replicate circuits.length 0 ++ heights) (traces.bitmap ++ active) + (traces.degrees ++ degrees) = + Aiur.fixedTraceHeights heights active degrees +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.fixed_heights_append +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths) (heights : List Nat) (active : List Bool) + (degrees : List Nat), + Aiur.fixedTraceHeights (List.replicate widths.length 0 ++ heights) (traces.bitmap ++ active) + (traces.degrees ++ degrees) = + Aiur.fixedTraceHeights heights active degrees +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.canonical_byte_metadata +∀ {circuits : List Aiur.Bytecode.Circuit} (functions : Aiur.AIR.CircuitTraces circuits) {widths : List Nat} + (memories : Aiur.AIR.MemoryTraces widths) {active : List Bool} {degrees : List Nat}, + Aiur.fixedTraceHeights (List.replicate circuits.length 0 ++ (List.replicate widths.length 0 ++ [256, 65536])) + (functions.bitmap ++ (memories.bitmap ++ active)) (functions.degrees ++ (memories.degrees ++ degrees)) = + true → + active = [true, true] ∧ degrees = [8, 16] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.suppliedWeight_perm +∀ {α : Type} [inst : DecidableEq α] {left right : List (Aiur.AIR.Provider α)}, + left.Perm right → ∀ (message : α), Aiur.AIR.suppliedWeight message left = Aiur.AIR.suppliedWeight message right +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.PaddedLookupBalance.perm_providers +∀ {width : Nat} {queries : List (List Aiur.G)} {left right : List (Aiur.AIR.Provider (List Aiur.G))}, + Aiur.AIR.PaddedLookupBalance width queries left → left.Perm right → Aiur.AIR.PaddedLookupBalance width queries right +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.flatMap_map_swap +∀ {α β γ : Type} (left : List α) (right : List β) (value : α → β → γ), + (List.flatMap (fun a => List.map (value a) right) left).Perm + (List.flatMap (fun b => List.map (fun a => value a b) left) right) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.byte1MatrixProviders_reflect +∀ (matrix : Fin 256 → Aiur.AIR.Byte1Columns), + (Aiur.AIR.byte1MatrixProviders matrix).Perm (Aiur.AIR.byte1Providers fun kind row => matrix row kind.column) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.byte2MatrixProviders_reflect +∀ (matrix : Fin 65536 → Aiur.AIR.Byte2Columns), + (Aiur.AIR.byte2MatrixProviders matrix).Perm (Aiur.AIR.byte2Providers fun kind row => matrix row kind.column) +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.ByteTraces.providers_reflect +∀ (traces : Aiur.AIR.ByteTraces), + traces.providers.Perm (Aiur.AIR.byte1Providers traces.byte1Weights ++ Aiur.AIR.byte2Providers traces.byte2Weights) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.SystemTraces.fixed_heights +∀ {program : Aiur.Bytecode.Toplevel} (traces : Aiur.AIR.SystemTraces program), + Aiur.fixedTraceHeights (Aiur.AIR.systemFixedHeights program) traces.bitmap traces.degrees = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.SystemTraces.memory_functional +∀ {program : Aiur.Bytecode.Toplevel} (traces : Aiur.AIR.SystemTraces program) {result : Nat}, + traces.queryBound = some result → + traces.memories.Satisfied → + ∀ {width : Nat} {pointer : Aiur.G} {left right : Array Aiur.G}, + Aiur.AIR.memoryFacts traces.memories.rows width pointer left → + Aiur.AIR.memoryFacts traces.memories.rows width pointer right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.column_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ (traces : Aiur.AIR.SystemTraces backend.compiled.bytecode) {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitWitnesses backend.compiled.bytecode traces.functions = some witnesses → + ∀ {result : Nat}, + traces.queryBound = some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (traces.providers (List.map (fun x => x.emission) witnesses)) → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + traces.memories.Satisfied → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode + (Aiur.AIR.memoryFacts traces.memories.rows) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Node.check_iff +∀ (widths : Aiur.NativeAIR.GraphWidths) (lookupEnd index : Nat) (node : Aiur.NativeAIR.Node), + Aiur.NativeAIR.Node.check widths lookupEnd index node = true ↔ Aiur.NativeAIR.Node.Valid widths lookupEnd index node +AXIOMS [propext] +ROOT Aiur.NativeAIR.checkNodes_iff +∀ (widths : Aiur.NativeAIR.GraphWidths) (lookupEnd index : Nat) (nodes : List Aiur.NativeAIR.Node), + Aiur.NativeAIR.checkNodes widths lookupEnd index nodes = true ↔ Aiur.NativeAIR.ValidNodes widths lookupEnd index nodes +AXIOMS [propext] +ROOT Aiur.NativeAIR.checkedGraphPrefix_iff +∀ (widths : Aiur.NativeAIR.GraphWidths) (graph : Aiur.NativeAIR.Graph) (lookupEnd : Nat), + Aiur.NativeAIR.checkedGraphPrefix widths graph = some lookupEnd ↔ + Aiur.NativeAIR.Graph.Valid widths graph ∧ lookupEnd = graph.lookupPrefix +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.roots_below_prefix +∀ (roots : List Nat) (index : Nat), index ∈ roots → index < List.foldr (fun root rest => max (root + 1) rest) 0 roots +AXIOMS [propext] +ROOT Aiur.NativeAIR.prefix_bounded +∀ (roots : List Nat) (bound : Nat), + (∀ (index : Nat), index ∈ roots → index < bound) → List.foldr (fun root rest => max (root + 1) rest) 0 roots ≤ bound +AXIOMS [propext] +ROOT Aiur.NativeAIR.Graph.Valid.prefix_bounded +∀ {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.Graph.Valid widths graph → graph.lookupPrefix ≤ graph.nodes.length +AXIOMS [propext] +ROOT Aiur.NativeAIR.Node.eval_defined +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) (buffer : Array W) + {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd : Nat} {node : Aiur.NativeAIR.Node}, + values.Fits widths → + Aiur.NativeAIR.Node.Valid widths lookupEnd buffer.size node → + ∃ value, Aiur.NativeAIR.Node.eval ops values buffer node = some value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.sweepFrom_defined +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) (nodes : List Aiur.NativeAIR.Node) + (buffer : Array W) {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd : Nat}, + values.Fits widths → + Aiur.NativeAIR.ValidNodes widths lookupEnd buffer.size nodes → + ∃ result, + Aiur.NativeAIR.sweepFrom ops values nodes buffer = some result ∧ result.size = buffer.size + nodes.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Graph.Valid.sweep_defined +∀ {W : Type u_1} {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.Graph.Valid widths graph → + ∀ (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W), + values.Fits widths → ∃ result, graph.sweep ops values = some result ∧ result.size = graph.nodes.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ValidNodes.take +∀ {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd index : Nat} {nodes : List Aiur.NativeAIR.Node}, + Aiur.NativeAIR.ValidNodes widths lookupEnd index nodes → + ∀ (count : Nat), Aiur.NativeAIR.ValidNodes widths lookupEnd index (List.take count nodes) +AXIOMS [] +ROOT Aiur.NativeAIR.Node.eval_withoutStage2 +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) (buffer : Array W) + {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd : Nat} {node : Aiur.NativeAIR.Node}, + Aiur.NativeAIR.Node.Valid widths lookupEnd buffer.size node → + buffer.size < lookupEnd → + Aiur.NativeAIR.Node.eval ops values.withoutStage2 buffer node = Aiur.NativeAIR.Node.eval ops values buffer node +AXIOMS [propext] +ROOT Aiur.NativeAIR.sweepFrom_withoutStage2 +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) (nodes : List Aiur.NativeAIR.Node) + (buffer : Array W) {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd : Nat}, + Aiur.NativeAIR.ValidNodes widths lookupEnd buffer.size nodes → + buffer.size + nodes.length ≤ lookupEnd → + Aiur.NativeAIR.sweepFrom ops values.withoutStage2 nodes buffer = Aiur.NativeAIR.sweepFrom ops values nodes buffer +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.sweepFrom_append +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) + (left right : List Aiur.NativeAIR.Node) (buffer : Array W), + Aiur.NativeAIR.sweepFrom ops values (left ++ right) buffer = + (Aiur.NativeAIR.sweepFrom ops values left buffer).bind (Aiur.NativeAIR.sweepFrom ops values right) +AXIOMS [] +ROOT Aiur.NativeAIR.sweepFrom_preserves +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) (nodes : List Aiur.NativeAIR.Node) + {buffer result : Array W}, + Aiur.NativeAIR.sweepFrom ops values nodes buffer = some result → + ∀ (index : Nat), index < buffer.size → result[index]? = buffer[index]? +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Graph.Valid.lookup_sweep_defined +∀ {W : Type u_1} {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.Graph.Valid widths graph → + ∀ (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W), + values.Fits widths → ∃ result, graph.sweepLookupPrefix ops values = some result ∧ result.size = graph.lookupPrefix +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Graph.Valid.lookup_sweep_agrees +∀ {W : Type u_1} {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.Graph.Valid widths graph → + ∀ (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) {full prefixValues : Array W}, + graph.sweep ops values = some full → + graph.sweepLookupPrefix ops values = some prefixValues → + ∀ (index : Nat), index < prefixValues.size → full[index]? = prefixValues[index]? +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Node.unfold_eval +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) {trees : Array Aiur.NativeAIR.Expr} + {buffer : Array W}, + Aiur.NativeAIR.Reflects ops values trees buffer → + ∀ (node : Aiur.NativeAIR.Node) {expr : Aiur.NativeAIR.Expr}, + Aiur.NativeAIR.Node.unfold trees node = some expr → + Aiur.NativeAIR.Node.eval ops values buffer node = Aiur.NativeAIR.Expr.eval ops values expr +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Reflects.push +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {trees : Array Aiur.NativeAIR.Expr} + {buffer : Array W}, + Aiur.NativeAIR.Reflects ops values trees buffer → + ∀ (expr : Aiur.NativeAIR.Expr) (value : W), + Aiur.NativeAIR.Expr.eval ops values expr = some value → + Aiur.NativeAIR.Reflects ops values (trees.push expr) (buffer.push value) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Node.unfold_defined +∀ {trees : Array Aiur.NativeAIR.Expr} {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd : Nat} + {node : Aiur.NativeAIR.Node}, + Aiur.NativeAIR.Node.Valid widths lookupEnd trees.size node → ∃ expr, Aiur.NativeAIR.Node.unfold trees node = some expr +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.unfoldFrom_defined +∀ {nodes : List Aiur.NativeAIR.Node} {trees : Array Aiur.NativeAIR.Expr} {widths : Aiur.NativeAIR.GraphWidths} + {lookupEnd : Nat}, + Aiur.NativeAIR.ValidNodes widths lookupEnd trees.size nodes → + ∃ result, Aiur.NativeAIR.unfoldFrom nodes trees = some result ∧ result.size = trees.size + nodes.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.unfoldFrom_reflects +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) (nodes : List Aiur.NativeAIR.Node) + {trees resultTrees : Array Aiur.NativeAIR.Expr} {buffer resultBuffer : Array W}, + Aiur.NativeAIR.Reflects ops values trees buffer → + Aiur.NativeAIR.unfoldFrom nodes trees = some resultTrees → + Aiur.NativeAIR.sweepFrom ops values nodes buffer = some resultBuffer → + Aiur.NativeAIR.Reflects ops values resultTrees resultBuffer +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Graph.Valid.unfold_defined +∀ {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.Graph.Valid widths graph → ∃ trees, graph.unfold = some trees ∧ trees.size = graph.nodes.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Graph.sweep_reflects +∀ {W : Type u_1} (graph : Aiur.NativeAIR.Graph) (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) + {trees : Array Aiur.NativeAIR.Expr} {buffer : Array W}, + graph.unfold = some trees → graph.sweep ops values = some buffer → Aiur.NativeAIR.Reflects ops values trees buffer +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Reflects.readNodes +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {trees : Array Aiur.NativeAIR.Expr} + {buffer : Array W}, + Aiur.NativeAIR.Reflects ops values trees buffer → + ∀ (roots : List Nat), Aiur.NativeAIR.readNodes buffer roots = Aiur.NativeAIR.evalRoots ops values trees roots +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Reflects.readLookup +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {trees : Array Aiur.NativeAIR.Expr} + {buffer : Array W}, + Aiur.NativeAIR.Reflects ops values trees buffer → + ∀ (lookup : Aiur.NativeAIR.Lookup), + Aiur.NativeAIR.readLookup buffer lookup = Aiur.NativeAIR.evalLookup ops values trees lookup +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.readNodes_congr +∀ {W : Type u_1} (left right : Array W) (roots : List Nat), + (∀ (index : Nat), index ∈ roots → left[index]? = right[index]?) → + Aiur.NativeAIR.readNodes left roots = Aiur.NativeAIR.readNodes right roots +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.readNodes_defined +∀ {W : Type u_1} (buffer : Array W) (roots : List Nat), + (∀ (index : Nat), index ∈ roots → index < buffer.size) → + ∃ values, Aiur.NativeAIR.readNodes buffer roots = some values ∧ values.length = roots.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.readLookup_defined +∀ {W : Type u_1} (buffer : Array W) (lookup : Aiur.NativeAIR.Lookup), + (∀ (index : Nat), index ∈ lookup.roots → index < buffer.size) → + ∃ value, Aiur.NativeAIR.readLookup buffer lookup = some value ∧ value.snd.length = lookup.args.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Graph.Valid.lookup_values_agree +∀ {W : Type u_1} {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.Graph.Valid widths graph → + ∀ (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) {full prefixValues : Array W}, + graph.sweep ops values = some full → + graph.sweepLookupPrefix ops values = some prefixValues → + prefixValues.size = graph.lookupPrefix → + ∀ (lookup : Aiur.NativeAIR.Lookup), + lookup ∈ graph.lookups → + Aiur.NativeAIR.readLookup full lookup = Aiur.NativeAIR.readLookup prefixValues lookup +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Graph.Valid.lookup_values_reflect +∀ {W : Type u_1} {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.Graph.Valid widths graph → + ∀ (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) {trees : Array Aiur.NativeAIR.Expr} + {full prefixValues : Array W}, + graph.unfold = some trees → + graph.sweep ops values = some full → + graph.sweepLookupPrefix ops values = some prefixValues → + prefixValues.size = graph.lookupPrefix → + ∀ (lookup : Aiur.NativeAIR.Lookup), + lookup ∈ graph.lookups → + Aiur.NativeAIR.readLookup prefixValues lookup = Aiur.NativeAIR.evalLookup ops values trees lookup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.sub_zero +∀ (value : Aiur.G), value - 0 = value +AXIOMS [propext] +ROOT Aiur.G.neg_neg +∀ (value : Aiur.G), 0 - (0 - value) = value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Expr.isConstant_eq +∀ (expr : Aiur.NativeAIR.Expr), expr.isConstant = expr.constantValue.isSome +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontNeg_noConstantNegs +∀ {expr : Aiur.NativeAIR.Expr}, expr.noConstantNegs = true → expr.frontNeg.noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontNeg_isConstant +∀ {expr : Aiur.NativeAIR.Expr}, expr.noConstantNegs = true → expr.frontNeg.isConstant = expr.isConstant +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontAdd_isConstant +∀ (left right : Aiur.NativeAIR.Expr), (left.frontAdd right).isConstant = (left.isConstant && right.isConstant) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontSub_isConstant +∀ (left right : Aiur.NativeAIR.Expr), + right.noConstantNegs = true → (left.frontSub right).isConstant = (left.isConstant && right.isConstant) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontAdd_noConstantNegs +∀ {left right : Aiur.NativeAIR.Expr}, + left.noConstantNegs = true → right.noConstantNegs = true → (left.frontAdd right).noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontSub_noConstantNegs +∀ {left right : Aiur.NativeAIR.Expr}, + left.noConstantNegs = true → right.noConstantNegs = true → (left.frontSub right).noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontMul_noConstantNegs +∀ {left right : Aiur.NativeAIR.Expr}, + left.noConstantNegs = true → right.noConstantNegs = true → (left.frontMul right).noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontNeg_eval +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.EvalLaws ops → + ∀ (values : Aiur.NativeAIR.Values W) {expr : Aiur.NativeAIR.Expr} {value : W}, + Aiur.NativeAIR.Expr.eval ops values expr = some value → + Aiur.NativeAIR.Expr.eval ops values expr.frontNeg = some (ops.neg value) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.eval_constantValue +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) {expr : Aiur.NativeAIR.Expr} + {value : W} {constant : Aiur.G}, + Aiur.NativeAIR.Expr.eval ops values expr = some value → + expr.constantValue = some constant → ops.konst constant = value +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontAdd_eval +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.EvalLaws ops → + ∀ (values : Aiur.NativeAIR.Values W) {left right : Aiur.NativeAIR.Expr} {a b : W}, + Aiur.NativeAIR.Expr.eval ops values left = some a → + Aiur.NativeAIR.Expr.eval ops values right = some b → + Aiur.NativeAIR.Expr.eval ops values (left.frontAdd right) = some (ops.add a b) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontSub_eval +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.EvalLaws ops → + ∀ (values : Aiur.NativeAIR.Values W) {left right : Aiur.NativeAIR.Expr} {a b : W}, + Aiur.NativeAIR.Expr.eval ops values left = some a → + Aiur.NativeAIR.Expr.eval ops values right = some b → + Aiur.NativeAIR.Expr.eval ops values (left.frontSub right) = some (ops.sub a b) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontMul_eval +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.EvalLaws ops → + ∀ (values : Aiur.NativeAIR.Values W) {left right : Aiur.NativeAIR.Expr} {a b : W}, + Aiur.NativeAIR.Expr.eval ops values left = some a → + Aiur.NativeAIR.Expr.eval ops values right = some b → + Aiur.NativeAIR.Expr.eval ops values (left.frontMul right) = some (ops.mul a b) +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_add_zero +∀ (a : Aiur.G), Aiur.NativeAIR.goldilocksOps.add a (Aiur.NativeAIR.goldilocksOps.konst 0) = a +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_zero_add +∀ (a : Aiur.G), Aiur.NativeAIR.goldilocksOps.add (Aiur.NativeAIR.goldilocksOps.konst 0) a = a +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_sub_zero +∀ (a : Aiur.G), Aiur.NativeAIR.goldilocksOps.sub a (Aiur.NativeAIR.goldilocksOps.konst 0) = a +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_zero_sub +∀ (a : Aiur.G), + Aiur.NativeAIR.goldilocksOps.sub (Aiur.NativeAIR.goldilocksOps.konst 0) a = Aiur.NativeAIR.goldilocksOps.neg a +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_mul_zero +∀ (a : Aiur.G), + Aiur.NativeAIR.goldilocksOps.mul a (Aiur.NativeAIR.goldilocksOps.konst 0) = Aiur.NativeAIR.goldilocksOps.konst 0 +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_zero_mul +∀ (a : Aiur.G), + Aiur.NativeAIR.goldilocksOps.mul (Aiur.NativeAIR.goldilocksOps.konst 0) a = Aiur.NativeAIR.goldilocksOps.konst 0 +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_mul_one +∀ (a : Aiur.G), Aiur.NativeAIR.goldilocksOps.mul a (Aiur.NativeAIR.goldilocksOps.konst 1) = a +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_one_mul +∀ (a : Aiur.G), Aiur.NativeAIR.goldilocksOps.mul (Aiur.NativeAIR.goldilocksOps.konst 1) a = a +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_neg_neg +∀ (a : Aiur.G), Aiur.NativeAIR.goldilocksOps.neg (Aiur.NativeAIR.goldilocksOps.neg a) = a +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.goldilocks_konst_add +∀ (a b : Aiur.G), + Aiur.NativeAIR.goldilocksOps.konst (a + b) = + Aiur.NativeAIR.goldilocksOps.add (Aiur.NativeAIR.goldilocksOps.konst a) (Aiur.NativeAIR.goldilocksOps.konst b) +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_konst +∀ (a : Aiur.G), Aiur.NativeAIR.goldilocksOps.konst a = a +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_add +∀ (a b : Aiur.G), Aiur.NativeAIR.goldilocksOps.add a b = a + b +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_sub +∀ (a b : Aiur.G), Aiur.NativeAIR.goldilocksOps.sub a b = a - b +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_mul +∀ (a b : Aiur.G), Aiur.NativeAIR.goldilocksOps.mul a b = a * b +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_konst_sub +∀ (a b : Aiur.G), + Aiur.NativeAIR.goldilocksOps.konst (a - b) = + Aiur.NativeAIR.goldilocksOps.sub (Aiur.NativeAIR.goldilocksOps.konst a) (Aiur.NativeAIR.goldilocksOps.konst b) +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_konst_mul +∀ (a b : Aiur.G), + Aiur.NativeAIR.goldilocksOps.konst (a * b) = + Aiur.NativeAIR.goldilocksOps.mul (Aiur.NativeAIR.goldilocksOps.konst a) (Aiur.NativeAIR.goldilocksOps.konst b) +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocks_konst_neg +∀ (a : Aiur.G), + Aiur.NativeAIR.goldilocksOps.konst (0 - a) = Aiur.NativeAIR.goldilocksOps.neg (Aiur.NativeAIR.goldilocksOps.konst a) +AXIOMS [propext] +ROOT Aiur.NativeAIR.goldilocksLaws +Aiur.NativeAIR.EvalLaws Aiur.NativeAIR.goldilocksOps +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Expr.constantValue_eq_of_eval +∀ (values : Aiur.NativeAIR.Values Aiur.G) {expr : Aiur.NativeAIR.Expr} {value constant : Aiur.G}, + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values expr = some value → + expr.constantValue = some constant → constant = value +AXIOMS [propext] +ROOT Aiur.NativeAIR.Expr.frontMul_isConstant +∀ (values : Aiur.NativeAIR.Values Aiur.G) {left right : Aiur.NativeAIR.Expr} {a b : Aiur.G}, + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values left = some a → + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values right = some b → + (left.frontMul right).isConstant = + (left.isConstant && right.isConstant || left.isConstant && a == 0 || right.isConstant && b == 0) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.RowExpr.reflects_iff_eval +∀ (values : Aiur.NativeAIR.Values Aiur.G) (expr : Aiur.NativeAIR.RowExpr) (value : Aiur.AIR.RowValue), + Aiur.NativeAIR.RowExpr.Reflects values expr value ↔ Aiur.NativeAIR.RowExpr.eval values expr = some value +AXIOMS [propext] +ROOT Aiur.NativeAIR.RowExpr.konst_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (value : Aiur.G), + Aiur.NativeAIR.RowExpr.Reflects values (Aiur.NativeAIR.RowExpr.konst value) (Aiur.AIR.RowValue.konst value) +AXIOMS [propext] +ROOT Aiur.NativeAIR.RowExpr.variable_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) {column : Aiur.NativeAIR.ColRef} {value : Aiur.G}, + (values.columns column.source column.offset)[column.index]? = some value → + Aiur.NativeAIR.RowExpr.Reflects values (Aiur.NativeAIR.RowExpr.variable column) (Aiur.AIR.RowValue.variable value) +AXIOMS [propext] +ROOT Aiur.NativeAIR.RowExpr.add_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → Aiur.NativeAIR.RowExpr.Reflects values (left.add right) (a.add b) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.RowExpr.sub_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → + right.expr.noConstantNegs = true → Aiur.NativeAIR.RowExpr.Reflects values (left.sub right) (a.sub b) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.RowExpr.mul_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → Aiur.NativeAIR.RowExpr.Reflects values (left.mul right) (a.mul b) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ScalarEmission.eval_of +∀ (values : Aiur.NativeAIR.Values Aiur.G) {output : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue} {used : Nat} + {equations : List Aiur.NativeAIR.Expr} {results : List Aiur.G}, + Aiur.NativeAIR.RowExpr.Reflects values output value → + List.mapM (Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values) equations = some results → + Aiur.NativeAIR.ScalarEmission.eval values { output := output, used := used, equations := equations } = + some { outputs := #[value], used := used, equations := results } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.eqZeroRegular_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {first : Nat} {input : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values selector = some s → + Aiur.NativeAIR.RowExpr.Reflects values input value → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first]? = some (row 0) → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + 1]? = some (row 1) → + Aiur.NativeAIR.ScalarEmission.eval values (Aiur.NativeAIR.eqZeroRegular selector first input) = + some + { outputs := #[Aiur.AIR.RowValue.variable (row 1)], used := 2, + equations := [s * value.value * row 1, s * (value.value * row 0 + row 1 - 1)] } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.emitEqZero_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {first : Nat} {input : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values selector = some s → + Aiur.NativeAIR.RowExpr.Reflects values input value → + (∀ (index : Nat), + index < (Aiur.NativeAIR.emitEqZero selector first input).used → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.ScalarEmission.eval values (Aiur.NativeAIR.emitEqZero selector first input) = + Aiur.AIR.emitOp row s 0 (Aiur.Bytecode.Op.eqZero 0) #[value] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.mulRegular_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {first : Nat} {product : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values selector = some s → + Aiur.NativeAIR.RowExpr.Reflects values product value → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first]? = some (row 0) → + Aiur.NativeAIR.ScalarEmission.eval values (Aiur.NativeAIR.mulRegular selector first product) = + some { outputs := #[Aiur.AIR.RowValue.variable (row 0)], used := 1, equations := [s * (row 0 - value.value)] } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.emitMul_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {first : Nat} {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values selector = some s → + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → + (∀ (index : Nat), + index < (Aiur.NativeAIR.emitMul selector first left right).used → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.ScalarEmission.eval values (Aiur.NativeAIR.emitMul selector first left right) = + Aiur.AIR.emitOp row s 0 (Aiur.Bytecode.Op.mul 0 1) #[a, b] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.emitEqZero_noConstantNegs +∀ (selector : Aiur.NativeAIR.Expr) (first : Nat) (input : Aiur.NativeAIR.RowExpr), + (Aiur.NativeAIR.emitEqZero selector first input).output.expr.noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.emitMul_noConstantNegs +∀ (selector : Aiur.NativeAIR.Expr) (first : Nat) {left right : Aiur.NativeAIR.RowExpr}, + left.expr.noConstantNegs = true → + right.expr.noConstantNegs = true → + (Aiur.NativeAIR.emitMul selector first left right).output.expr.noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.emitAdd_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (selector rank : Aiur.G) + {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → + Aiur.NativeAIR.ScalarEmission.eval values { output := left.add right } = + Aiur.AIR.emitOp row selector rank (Aiur.Bytecode.Op.add 0 1) #[a, b] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.emitSub_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (selector rank : Aiur.G) + {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → + right.expr.noConstantNegs = true → + Aiur.NativeAIR.ScalarEmission.eval values { output := left.sub right } = + Aiur.AIR.emitOp row selector rank (Aiur.Bytecode.Op.sub 0 1) #[a, b] +AXIOMS [propext, Quot.sound] +ROOT Aiur.G.sub_self +∀ (value : Aiur.G), value - value = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.goldilocksGraphLaws +Aiur.NativeAIR.GraphEvalLaws Aiur.NativeAIR.goldilocksOps +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.Extends.refl +∀ {W : Type u_1} (buffer : Array W), Aiur.NativeAIR.Compiler.Extends buffer buffer +AXIOMS [] +ROOT Aiur.NativeAIR.Compiler.Extends.trans +∀ {W : Type u_1} {first second third : Array W}, + Aiur.NativeAIR.Compiler.Extends first second → + Aiur.NativeAIR.Compiler.Extends second third → Aiur.NativeAIR.Compiler.Extends first third +AXIOMS [] +ROOT Aiur.NativeAIR.Compiler.Extends.push +∀ {W : Type u_1} (buffer : Array W) (value : W), Aiur.NativeAIR.Compiler.Extends buffer (buffer.push value) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.eval_extends +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) {before after : Array W}, + Aiur.NativeAIR.Compiler.Extends before after → + ∀ (node : Aiur.NativeAIR.Node) {value : W}, + Aiur.NativeAIR.Node.eval ops values before node = some value → + Aiur.NativeAIR.Node.eval ops values after node = some value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.Evaluation.empty +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W), + Aiur.NativeAIR.Compiler.Evaluation ops values [] #[] +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.Evaluation.push +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ (node : Aiur.NativeAIR.Node) (value : W), + Aiur.NativeAIR.Node.eval ops values buffer node = some value → + Aiur.NativeAIR.Compiler.Evaluation ops values (nodes ++ [node]) (buffer.push value) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.result_same +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {index : Nat} {value : W}, + buffer[index]? = some value → Aiur.NativeAIR.Compiler.Result ops values buffer (nodes, index) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.intern_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ (node : Aiur.NativeAIR.Node) {value : W}, + Aiur.NativeAIR.Node.eval ops values buffer node = some value → + Aiur.NativeAIR.Compiler.Result ops values buffer (Aiur.NativeAIR.Compiler.intern nodes node) value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.asConst_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {index : Nat} {constant : Aiur.G}, + Aiur.NativeAIR.Compiler.asConst nodes index = some constant → buffer[index]? = some (ops.konst constant) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.asConst_value +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {index : Nat} {constant : Aiur.G} {value : W}, + Aiur.NativeAIR.Compiler.asConst nodes index = some constant → + buffer[index]? = some value → value = ops.konst constant +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.konst_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ (value : Aiur.G), + Aiur.NativeAIR.Compiler.Result ops values buffer + (Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.konst value)) (ops.konst value) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.neg_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.EvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {a : Nat} {value : W}, + buffer[a]? = some value → + Aiur.NativeAIR.Compiler.Result ops values buffer (Aiur.NativeAIR.Compiler.neg nodes a) (ops.neg value) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.sortedAdd_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {a b : Nat} {left right : W}, + buffer[a]? = some left → + buffer[b]? = some right → + Aiur.NativeAIR.Compiler.Result ops values buffer (Aiur.NativeAIR.Compiler.sortedAdd nodes a b) + (ops.add left right) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.sortedMul_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {a b : Nat} {left right : W}, + buffer[a]? = some left → + buffer[b]? = some right → + Aiur.NativeAIR.Compiler.Result ops values buffer (Aiur.NativeAIR.Compiler.sortedMul nodes a b) + (ops.mul left right) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.add_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {a b : Nat} {left right : W}, + buffer[a]? = some left → + buffer[b]? = some right → + Aiur.NativeAIR.Compiler.Result ops values buffer (Aiur.NativeAIR.Compiler.add nodes a b) + (ops.add left right) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.sub_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {a b : Nat} {left right : W}, + buffer[a]? = some left → + buffer[b]? = some right → + Aiur.NativeAIR.Compiler.Result ops values buffer (Aiur.NativeAIR.Compiler.sub nodes a b) + (ops.sub left right) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.mul_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {a b : Nat} {left right : W}, + buffer[a]? = some left → + buffer[b]? = some right → + Aiur.NativeAIR.Compiler.Result ops values buffer (Aiur.NativeAIR.Compiler.mul nodes a b) + (ops.mul left right) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.result_prepend +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {before middle : Array W}, + Aiur.NativeAIR.Compiler.Extends before middle → + ∀ {result : List Aiur.NativeAIR.Node × Nat} {value : W}, + Aiur.NativeAIR.Compiler.Result ops values middle result value → + Aiur.NativeAIR.Compiler.Result ops values before result value +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.compileExpr_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (allowStage2 : Bool) (expr : Aiur.NativeAIR.Expr) {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {result : List Aiur.NativeAIR.Node × Nat}, + Aiur.NativeAIR.Compiler.compileExpr widths allowStage2 expr nodes = some result → + ∃ value, + Aiur.NativeAIR.Expr.eval ops values expr = some value ∧ + Aiur.NativeAIR.Compiler.Result ops values buffer result value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileExpr_sweep +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (allowStage2 : Bool) (expr : Aiur.NativeAIR.Expr) {result : List Aiur.NativeAIR.Node × Nat}, + Aiur.NativeAIR.Compiler.compileExpr widths allowStage2 expr [] = some result → + ∃ buffer, + Aiur.NativeAIR.sweepFrom ops values result.fst #[] = some buffer ∧ + buffer[result.snd]? = Aiur.NativeAIR.Expr.eval ops values expr +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.RootsReflect.grow +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {before after : Array W}, + Aiur.NativeAIR.Compiler.Extends before after → + ∀ {roots : List Nat} {exprs : List Aiur.NativeAIR.Expr}, + Aiur.NativeAIR.Compiler.RootsReflect ops values before roots exprs → + Aiur.NativeAIR.Compiler.RootsReflect ops values after roots exprs +AXIOMS [] +ROOT Aiur.NativeAIR.Compiler.compileExprs_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (allowStage2 : Bool) (exprs : List Aiur.NativeAIR.Expr) {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {result : List Aiur.NativeAIR.Node × List Nat}, + Aiur.NativeAIR.Compiler.compileExprs widths allowStage2 exprs nodes = some result → + ∃ after, + Aiur.NativeAIR.Compiler.Evaluation ops values result.fst after ∧ + Aiur.NativeAIR.Compiler.Extends buffer after ∧ + Aiur.NativeAIR.Compiler.RootsReflect ops values after result.snd exprs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.RootsReflect.read +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {buffer : Array W} + {roots : List Nat} {exprs : List Aiur.NativeAIR.Expr}, + Aiur.NativeAIR.Compiler.RootsReflect ops values buffer roots exprs → + ∃ result, + Aiur.NativeAIR.Compiler.evalExprs ops values exprs = some result ∧ + Aiur.NativeAIR.readNodes buffer roots = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileLookup_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (lookup : Aiur.NativeAIR.Compiler.ExprLookup) {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {result : List Aiur.NativeAIR.Node × Aiur.NativeAIR.Lookup}, + Aiur.NativeAIR.Compiler.compileLookup widths lookup nodes = some result → + ∃ after, + Aiur.NativeAIR.Compiler.Evaluation ops values result.fst after ∧ + Aiur.NativeAIR.Compiler.Extends buffer after ∧ + Aiur.NativeAIR.Compiler.RootsReflect ops values after result.snd.roots lookup.exprs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.RootsReflect.readLookup +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {buffer : Array W} + {lookup : Aiur.NativeAIR.Lookup} {exprs : Aiur.NativeAIR.Compiler.ExprLookup}, + Aiur.NativeAIR.Compiler.RootsReflect ops values buffer lookup.roots exprs.exprs → + ∃ read, + Aiur.NativeAIR.Compiler.ExprLookup.eval ops values exprs = some read ∧ + Aiur.NativeAIR.readLookup buffer lookup = some read +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.LookupsReflect.grow +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {before after : Array W}, + Aiur.NativeAIR.Compiler.Extends before after → + ∀ {lookups : List Aiur.NativeAIR.Lookup} {exprs : List Aiur.NativeAIR.Compiler.ExprLookup}, + Aiur.NativeAIR.Compiler.LookupsReflect ops values before lookups exprs → + Aiur.NativeAIR.Compiler.LookupsReflect ops values after lookups exprs +AXIOMS [] +ROOT Aiur.NativeAIR.Compiler.compileLookups_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (lookups : List Aiur.NativeAIR.Compiler.ExprLookup) {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {result : List Aiur.NativeAIR.Node × List Aiur.NativeAIR.Lookup}, + Aiur.NativeAIR.Compiler.compileLookups widths lookups nodes = some result → + ∃ after, + Aiur.NativeAIR.Compiler.Evaluation ops values result.fst after ∧ + Aiur.NativeAIR.Compiler.Extends buffer after ∧ + Aiur.NativeAIR.Compiler.LookupsReflect ops values after result.snd lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.recordZero_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer after : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + Aiur.NativeAIR.Compiler.Extends buffer after → + ∀ {root : Nat} {value : W}, + buffer[root]? = some value → + ∀ {roots : List Nat}, + Aiur.NativeAIR.Compiler.recordZero nodes root = some roots → + (Aiur.NativeAIR.Compiler.Vanishes ops after roots ↔ value = ops.konst 0) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.Vanishes.append +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (buffer : Array W) (left right : List Nat), + Aiur.NativeAIR.Compiler.Vanishes ops buffer (left ++ right) ↔ + Aiur.NativeAIR.Compiler.Vanishes ops buffer left ∧ Aiur.NativeAIR.Compiler.Vanishes ops buffer right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.ExprsVanish.cons +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W) (head : Aiur.NativeAIR.Expr) + (tail : List Aiur.NativeAIR.Expr), + Aiur.NativeAIR.Compiler.ExprsVanish ops values (head :: tail) ↔ + Aiur.NativeAIR.Expr.eval ops values head = some (ops.konst 0) ∧ Aiur.NativeAIR.Compiler.ExprsVanish ops values tail +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.compileZeros_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (exprs : List Aiur.NativeAIR.Expr) {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {result : List Aiur.NativeAIR.Node × List Nat}, + Aiur.NativeAIR.Compiler.compileZeros widths exprs nodes = some result → + ∃ after, + Aiur.NativeAIR.Compiler.Evaluation ops values result.fst after ∧ + Aiur.NativeAIR.Compiler.Extends buffer after ∧ + (Aiur.NativeAIR.Compiler.Vanishes ops after result.snd ↔ + Aiur.NativeAIR.Compiler.ExprsVanish ops values exprs) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.canonicalZeros_vanish +∀ {W : Type u_1} (ops : Aiur.NativeAIR.EvalOps W) (buffer : Array W) (roots : List Nat), + Aiur.NativeAIR.Compiler.Vanishes ops buffer (Aiur.NativeAIR.Compiler.canonicalZeros roots) ↔ + Aiur.NativeAIR.Compiler.Vanishes ops buffer roots +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileBase_reflects +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (lookups : List Aiur.NativeAIR.Compiler.ExprLookup) (constraints : List Aiur.NativeAIR.Expr) + {result : Aiur.NativeAIR.Compiler.BaseCompilation}, + Aiur.NativeAIR.Compiler.compileBase widths lookups constraints = some result → + ∃ buffer, + result.graph.sweep ops values = some buffer ∧ + Aiur.NativeAIR.Compiler.LookupsReflect ops values buffer result.graph.lookups lookups ∧ + (Aiur.NativeAIR.Compiler.Vanishes ops buffer result.graph.zeros ↔ + Aiur.NativeAIR.Compiler.ExprsVanish ops values constraints) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.LookupsReflect.read +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {buffer : Array W} + {lookups : List Aiur.NativeAIR.Lookup} {exprs : List Aiur.NativeAIR.Compiler.ExprLookup}, + Aiur.NativeAIR.Compiler.LookupsReflect ops values buffer lookups exprs → + ∃ result, + List.mapM (Aiur.NativeAIR.Compiler.ExprLookup.eval ops values) exprs = some result ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) lookups = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileBase_satisfaction +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (lookups : List Aiur.NativeAIR.Compiler.ExprLookup) (constraints : List Aiur.NativeAIR.Expr) + {result : Aiur.NativeAIR.Compiler.BaseCompilation}, + Aiur.NativeAIR.Compiler.compileBase widths lookups constraints = some result → + ∀ {buffer : Array W}, + result.graph.sweep ops values = some buffer → + (Aiur.NativeAIR.Compiler.Vanishes ops buffer result.graph.zeros ↔ + Aiur.NativeAIR.Compiler.ExprsVanish ops values constraints) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) result.graph.lookups = + List.mapM (Aiur.NativeAIR.Compiler.ExprLookup.eval ops values) lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_mapM_read +∀ {α β : Type u_1} {read : α → Option β} {inputs : List α} {outputs : List β}, + List.mapM read inputs = some outputs → ∀ (index : Nat), inputs[index]? >>= read = outputs[index]? +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_mapM_read +∀ {α β : Type u_1} {read : α → Option β} {inputs : Array α} {outputs : Array β}, + Array.mapM read inputs = some outputs → ∀ (index : Nat), inputs[index]? >>= read = outputs[index]? +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_mapM_size +∀ {α : Type u_1} {β : Type u_2} {read : α → Option β} {inputs : Array α} {outputs : Array β}, + Array.mapM read inputs = some outputs → outputs.size = inputs.size +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_mapM_push +∀ {α : Type u_1} {β : Type u_2} (read : α → Option β) (inputs : Array α) (input : α), + Array.mapM read (inputs.push input) = do + let outputs ← Array.mapM read inputs + let output ← read input + pure (outputs.push output) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_mapM_of_map +∀ {α : Type u_1} {β : Type u_2} {γ : Type u_3} (items : List α) (input : α → β) (output : α → γ) (read : β → Option γ), + (∀ (item : α), item ∈ items → read (input item) = some (output item)) → + List.mapM read (List.map input items) = some (List.map output items) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_mapM_ofFn +∀ {α : Type u_1} {β : Type u_2} {n : Nat} (input : Fin n → α) (output : Fin n → β) (read : α → Option β), + (∀ (index : Fin n), read (input index) = some (output index)) → + Array.mapM read (Array.ofFn input) = some (Array.ofFn output) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_mapM_ofFn +∀ {α : Type u_1} {β : Type u_2} {n : Nat} (input : Fin n → α) (output : Fin n → β) (read : α → Option β), + (∀ (index : Fin n), read (input index) = some (output index)) → + List.mapM read (List.ofFn input) = some (List.ofFn output) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_mapM_transform +∀ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {read : α → Option β} {inputs : List α} + {outputs : List β}, + List.mapM read inputs = some outputs → + ∀ (input : α → γ) (output : β → δ) (next : γ → Option δ), + (∀ (a : α) (b : β), read a = some b → next (input a) = some (output b)) → + List.mapM next (List.map input inputs) = some (List.map output outputs) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_mapM_transform +∀ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {read : α → Option β} {inputs : Array α} + {outputs : Array β}, + Array.mapM read inputs = some outputs → + ∀ (input : α → γ) (output : β → δ) (next : γ → Option δ), + (∀ (a : α) (b : β), read a = some b → next (input a) = some (output b)) → + Array.mapM next (Array.map input inputs) = some (Array.map output outputs) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_mapM_refine +∀ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {first : α → Option β} {second : α → Option γ} {evaluate : β → Option γ} + {inputs : List α} {outputs : List β}, + List.mapM first inputs = some outputs → + (∀ (input : α) (output : β), + first input = some output → ∃ value, second input = some value ∧ evaluate output = some value) → + ∃ values, List.mapM second inputs = some values ∧ List.mapM evaluate outputs = some values +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_mapM_refine +∀ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {first : α → Option β} {second : α → Option γ} {evaluate : β → Option γ} + {inputs : Array α} {outputs : Array β}, + Array.mapM first inputs = some outputs → + (∀ (input : α) (output : β), + first input = some output → ∃ value, second input = some value ∧ evaluate output = some value) → + ∃ values, Array.mapM second inputs = some values ∧ Array.mapM evaluate outputs = some values +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.evalRows_empty +∀ (values : Aiur.NativeAIR.Values Aiur.G), Aiur.NativeAIR.OpEmitter.evalRows values #[] = some #[] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.evalRows_singleton +∀ {values : Aiur.NativeAIR.Values Aiur.G} {expr : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values expr value → Aiur.NativeAIR.OpEmitter.evalRows values #[expr] = some #[value] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.evalRows_values +∀ {values : Aiur.NativeAIR.Values Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {outputs : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some outputs → + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (Aiur.NativeAIR.OpEmitter.rowExprs rows) = + some (Aiur.AIR.rowValues outputs) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.evalRows_read +∀ {values : Aiur.NativeAIR.Values Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {outputs : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some outputs → + ∀ {index : Nat} {row : Aiur.NativeAIR.RowExpr}, + rows[index]? = some row → + ∃ output, outputs[index]? = some output ∧ Aiur.NativeAIR.RowExpr.Reflects values row output +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.select_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {outputs : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some outputs → + ∀ {indices : Array Nat} {selected : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.select rows indices = some selected → + ∃ results, + Array.mapM (fun index => outputs[index]?) indices = some results ∧ + Aiur.NativeAIR.OpEmitter.evalRows values selected = some results +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.select_values +∀ {rows : Array Aiur.AIR.RowValue} {indices : Array Nat} {outputs : Array Aiur.AIR.RowValue}, + Array.mapM (fun index => rows[index]?) indices = some outputs → + Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues rows) indices = some (Aiur.AIR.rowValues outputs) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.select_normal +∀ {rows : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.Normal rows → + ∀ {indices : Array Nat} {selected : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.select rows indices = some selected → Aiur.NativeAIR.OpEmitter.Normal selected +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_ofFn_getD +∀ {α : Type u_1} (items : Array α) (fallback : α) {count : Nat}, + items.size = count → (Array.ofFn fun index => items[↑index]?.getD fallback) = items +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_map_getD_of_mapM +∀ {α : Type} {items : Array α} {indices : Array Nat} {selected : Array α} (fallback : α), + Array.mapM (fun index => items[index]?) indices = some selected → + Array.map (fun index => items[index]?.getD fallback) indices = selected +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.evalRows_getD +∀ {values : Aiur.NativeAIR.Values Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {outputs : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some outputs → + ∀ {index : Nat}, + index < rows.size → + Aiur.NativeAIR.RowExpr.Reflects values (rows[index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)) + (outputs[index]?.getD (Aiur.AIR.RowValue.konst 0)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.advice_eval +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first count : Nat), + (∀ (index : Nat), + index < count → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.evalRows values (Aiur.NativeAIR.OpEmitter.advice first count) = + some (Aiur.AIR.rowAdvice row 0 count) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.advice_normal +∀ (first count : Nat), Aiur.NativeAIR.OpEmitter.Normal (Aiur.NativeAIR.OpEmitter.advice first count) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.CallExpr.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {call : Aiur.NativeAIR.OpEmitter.CallExpr} {inputs outputs : Array Aiur.G} + {rank : Aiur.G} {gap : Fin 6 → Aiur.G}, + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) call.inputs = some inputs → + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) call.outputs = some outputs → + Aiur.NativeAIR.OpEmitter.evalExpr values call.rank = some rank → + (∀ (index : Fin 6), Aiur.NativeAIR.OpEmitter.evalExpr values (call.gap index) = some (gap index)) → + Aiur.NativeAIR.OpEmitter.CallExpr.eval values call = + some ({ function := call.function, inputs := inputs, outputs := outputs, rank := rank }, gap) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitAdvice_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first count : Nat), + (∀ (index : Nat), + index < count → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.emitAdvice first count) = + some (Aiur.AIR.emitAdvice row count) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.Emission.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.OpEmitter.Emission} {result : Aiur.AIR.OpEmission}, + Aiur.NativeAIR.OpEmitter.evalRows values emission.outputs = some result.outputs → + emission.used = result.used → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations → + List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) emission.queries = some result.queries → + List.mapM (Aiur.NativeAIR.OpEmitter.CallExpr.eval values) emission.calls = some result.calls → + Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte1_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat) (kind : Aiur.AIR.Byte1Kind) + {input : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values input value → + (∀ (index : Nat), + index < kind.outputSize → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.emitByte1 first kind input) = + some + { outputs := Aiur.AIR.rowAdvice row 0 kind.outputSize, used := kind.outputSize, + queries := + [Aiur.AIR.byte1Request kind value.value (Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row 0 kind.outputSize))] } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.scale_isConstant +∀ (expr : Aiur.NativeAIR.Expr) {coefficient : Aiur.G}, + coefficient ≠ 0 → (expr.frontMul (Aiur.NativeAIR.Expr.konst coefficient)).isConstant = expr.isConstant +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.byteCarry_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat) (subtract : Bool) + {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → + left.expr.noConstantNegs = true → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first]? = some (row 0) → + Aiur.NativeAIR.RowExpr.Reflects values (Aiur.NativeAIR.OpEmitter.byteCarry first subtract left right) + { + value := + (if subtract = true then row 0 + b.value - a.value else a.value + b.value - row 0) * + Aiur.AIR.inverse256, + degree := max (max a.degree b.degree) 1, constant := false } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.byteCarry_normal +∀ (first : Nat) (subtract : Bool) {left right : Aiur.NativeAIR.RowExpr}, + left.expr.noConstantNegs = true → + right.expr.noConstantNegs = true → + (Aiur.NativeAIR.OpEmitter.byteCarry first subtract left right).expr.noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitByte2_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat) (kind : Aiur.AIR.Byte2Kind) + {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → + left.expr.noConstantNegs = true → + (∀ (index : Nat), + index < kind.outputSize → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.emitByte2 first kind left right) = + some + { outputs := kind.extendRowOutputs a b (Aiur.AIR.rowAdvice row 0 kind.outputSize), + used := kind.outputSize, + queries := + [Aiur.AIR.byte2Request kind a.value b.value + (Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row 0 kind.outputSize))] } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte2_normal +∀ (first : Nat) (kind : Aiur.AIR.Byte2Kind) {left right : Aiur.NativeAIR.RowExpr}, + left.expr.noConstantNegs = true → + right.expr.noConstantNegs = true → + Aiur.NativeAIR.OpEmitter.Normal (Aiur.NativeAIR.OpEmitter.emitByte2 first kind left right).outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.scale_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) {expr : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values expr value → + ∀ (coefficient : Aiur.G), + coefficient ≠ 0 → + Aiur.NativeAIR.RowExpr.Reflects values (expr.mul (Aiur.NativeAIR.RowExpr.konst coefficient)) + { value := value.value * coefficient, degree := value.degree, constant := value.constant } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_ofFn_four +∀ {α : Type u_1} (values : Fin 4 → α), List.ofFn values = [values 0, values 1, values 2, values 3] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_foldl_zip_four +∀ {α : Type u_1} {β : Type u_2} (values : Fin 4 → α) (step : β → α × Nat → β) (initial : β), + List.foldl step initial (List.ofFn values).zipIdx = + step (step (step (step initial (values 0, 0)) (values 1, 1)) (values 2, 2)) (values 3, 3) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packFour_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (bytes : Fin 4 → Aiur.NativeAIR.RowExpr) + (results : Fin 4 → Aiur.AIR.RowValue), + (∀ (index : Fin 4), Aiur.NativeAIR.RowExpr.Reflects values (bytes index) (results index)) → + Aiur.NativeAIR.RowExpr.Reflects values (Aiur.NativeAIR.OpEmitter.packFour bytes) + (Aiur.AIR.RowValue.pack (Array.ofFn results)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packFour_normal +∀ (bytes : Fin 4 → Aiur.NativeAIR.RowExpr), + (∀ (index : Fin 4), (bytes index).expr.noConstantNegs = true) → + (Aiur.NativeAIR.OpEmitter.packFour bytes).expr.noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.readWord_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {outputs : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some outputs → + ∀ {indices : Array Nat} {word : Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.readWord rows indices = some word → + ∃ value, Aiur.AIR.readRowWord outputs indices = some value ∧ Aiur.NativeAIR.RowExpr.Reflects values word value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.readWord_normal +∀ {rows : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.Normal rows → + ∀ {indices : Array Nat} {word : Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.readWord rows indices = some word → word.expr.noConstantNegs = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packedAdvice_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat), + (∀ (index : Nat), + index < 4 → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.RowExpr.Reflects values (Aiur.NativeAIR.OpEmitter.packedAdvice first) + (Aiur.AIR.RowValue.pack (Aiur.AIR.rowAdvice row 0 4)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packedAdvice_normal +∀ (first : Nat), (Aiur.NativeAIR.OpEmitter.packedAdvice first).expr.noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.packed_advice_not_constant +∀ (row : Nat → Aiur.G), (Aiur.AIR.RowValue.pack (Aiur.AIR.rowAdvice row 0 4)).constant = false +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitWordSum_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat) {sum : Aiur.NativeAIR.RowExpr} + {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values sum value → + (∀ (index : Nat), + index < 4 → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.emitWordSum first sum) = + some + { + outputs := + (Aiur.AIR.rowAdvice row 0 4).push + { + value := + (value.value - (Aiur.AIR.RowValue.pack (Aiur.AIR.rowAdvice row 0 4)).value) * 18446744065119617026, + degree := max value.degree (Aiur.AIR.RowValue.pack (Aiur.AIR.rowAdvice row 0 4)).degree, + constant := false }, + used := 4 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitWordSum_normal +∀ (first : Nat) {sum : Aiur.NativeAIR.RowExpr}, + sum.expr.noConstantNegs = true → + Aiur.NativeAIR.OpEmitter.Normal (Aiur.NativeAIR.OpEmitter.emitWordSum first sum).outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packed_advice_value +∀ (row : Nat → Aiur.G), + (Aiur.AIR.RowValue.pack (Aiur.AIR.rowAdvice row 0 4)).value = Aiur.AIR.pack4 fun index => row ↑index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.carryStep_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {x y z previous : Aiur.NativeAIR.Expr} {a b c d : Aiur.G}, + Aiur.NativeAIR.OpEmitter.evalExpr values x = some a → + Aiur.NativeAIR.OpEmitter.evalExpr values y = some b → + Aiur.NativeAIR.OpEmitter.evalExpr values z = some c → + Aiur.NativeAIR.OpEmitter.evalExpr values previous = some d → + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.OpEmitter.carryStep x y z previous) = + some (Aiur.AIR.carryStep a b c d) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.carryStep_normal +∀ {x y z previous : Aiur.NativeAIR.Expr}, + x.noConstantNegs = true → + y.noConstantNegs = true → + z.noConstantNegs = true → + previous.noConstantNegs = true → (Aiur.NativeAIR.OpEmitter.carryStep x y z previous).noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.carryStep_not_constant +∀ {x y z previous : Aiur.NativeAIR.Expr}, + z.noConstantNegs = true → + z.isConstant = false → (Aiur.NativeAIR.OpEmitter.carryStep x y z previous).isConstant = false +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.carries_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {x y z : Fin 4 → Aiur.NativeAIR.Expr} {a b c : Fin 4 → Aiur.G}, + (∀ (index : Fin 4), Aiur.NativeAIR.OpEmitter.evalExpr values (x index) = some (a index)) → + (∀ (index : Fin 4), Aiur.NativeAIR.OpEmitter.evalExpr values (y index) = some (b index)) → + (∀ (index : Fin 4), Aiur.NativeAIR.OpEmitter.evalExpr values (z index) = some (c index)) → + ∀ (index : Fin 5), + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.OpEmitter.carries x y z index) = + some (Aiur.AIR.u32Carries a b c index) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.carries_normal +∀ {x y z : Fin 4 → Aiur.NativeAIR.Expr}, + (∀ (index : Fin 4), (x index).noConstantNegs = true) → + (∀ (index : Fin 4), (y index).noConstantNegs = true) → + (∀ (index : Fin 4), (z index).noConstantNegs = true) → + ∀ (index : Fin 5), (Aiur.NativeAIR.OpEmitter.carries x y z index).noConstantNegs = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packSix_eval +∀ (values : Aiur.NativeAIR.Values Aiur.G) (bytes : Fin 6 → Aiur.NativeAIR.Expr) (results : Fin 6 → Aiur.G), + (∀ (index : Fin 6), Aiur.NativeAIR.OpEmitter.evalExpr values (bytes index) = some (results index)) → + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.OpEmitter.packSix bytes) = some (Aiur.AIR.packRank results) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rangePair_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {left right : Aiur.NativeAIR.Expr} {a b : Aiur.G}, + Aiur.NativeAIR.OpEmitter.evalExpr values left = some a → + Aiur.NativeAIR.OpEmitter.evalExpr values right = some b → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (Aiur.NativeAIR.OpEmitter.rangePair left right) = + some (Aiur.AIR.rangeMessage (a, b)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rangeSix_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (bytes : Fin 6 → Aiur.NativeAIR.Expr) (results : Fin 6 → Aiur.G), + (∀ (index : Fin 6), Aiur.NativeAIR.OpEmitter.evalExpr values (bytes index) = some (results index)) → + List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) (Aiur.NativeAIR.OpEmitter.rangeSix bytes) = + some (List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries results)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitCall_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first function size : Nat) + {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} {inputs : Array Aiur.NativeAIR.RowExpr} + {arguments : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → + Aiur.NativeAIR.OpEmitter.evalRows values inputs = some arguments → + (∀ (index : Nat), + index < size + 6 → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.Emission.eval values + (Aiur.NativeAIR.OpEmitter.emitCall selector rank first function inputs size) = + some + { outputs := Aiur.AIR.rowAdvice row 0 size, used := size + 6, + queries := + Aiur.AIR.functionMessage + { function := function, inputs := Aiur.AIR.rowValues arguments, + outputs := Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row 0 size), + rank := r + 1 + Aiur.AIR.packRank fun index => row (size + ↑index) } :: + List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries fun index => row (size + ↑index)), + calls := + [({ function := function, inputs := Aiur.AIR.rowValues arguments, + outputs := Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row 0 size), + rank := r + 1 + Aiur.AIR.packRank fun index => row (size + ↑index) }, + fun index => row (size + ↑index))] } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitStore_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat) {contents : Array Aiur.NativeAIR.RowExpr} + {stored : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values contents = some stored → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first]? = some (row 0) → + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.emitStore first contents) = + some + { outputs := Aiur.AIR.rowAdvice row 0 1, used := 1, + queries := [Aiur.AIR.memoryMessage contents.size (row 0) (Aiur.AIR.rowValues stored)] } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitLoad_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first size : Nat) {pointer : Aiur.NativeAIR.RowExpr} + {address : Aiur.AIR.RowValue}, + Aiur.NativeAIR.RowExpr.Reflects values pointer address → + (∀ (index : Nat), + index < size → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.emitLoad first size pointer) = + some + { outputs := Aiur.AIR.rowAdvice row 0 size, used := size, + queries := + [Aiur.AIR.memoryMessage size address.value (Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row 0 size))] } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rangeFour_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (bytes : Fin 4 → Aiur.NativeAIR.Expr) (results : Fin 4 → Aiur.G), + (∀ (index : Fin 4), Aiur.NativeAIR.OpEmitter.evalExpr values (bytes index) = some (results index)) → + List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) (Aiur.NativeAIR.OpEmitter.rangeFour bytes) = + some (Aiur.AIR.range4Queries results) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.booleanExpr_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {expr : Aiur.NativeAIR.Expr} {value : Aiur.G}, + Aiur.NativeAIR.OpEmitter.evalExpr values expr = some value → + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.OpEmitter.booleanExpr expr) = + some (Aiur.AIR.booleanConstraint value) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitU32LessThan_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat) {selector : Aiur.NativeAIR.Expr} + {s : Aiur.G} {left right : Aiur.NativeAIR.RowExpr} {a b : Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + Aiur.NativeAIR.RowExpr.Reflects values left a → + Aiur.NativeAIR.RowExpr.Reflects values right b → + (∀ (index : Nat), + index < 12 → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + Aiur.NativeAIR.OpEmitter.Emission.eval values + (Aiur.NativeAIR.OpEmitter.emitU32LessThan selector first left right) = + some + { + outputs := + #[{ + value := + 1 - Aiur.AIR.u32Carries (fun i => row ↑i) (fun i => row (4 + ↑i)) (fun i => row (8 + ↑i)) 4, + degree := 1, constant := false }], + used := 12, + equations := + s * (a.value - Aiur.AIR.pack4 fun i => row ↑i) :: + s * (b.value - Aiur.AIR.pack4 fun i => row (8 + ↑i)) :: + List.ofFn fun i => + s * + Aiur.AIR.booleanConstraint + (Aiur.AIR.u32Carries (fun i => row ↑i) (fun i => row (4 + ↑i)) (fun i => row (8 + ↑i)) + i.succ), + queries := + ((Aiur.AIR.range4Queries fun i => row ↑i) ++ Aiur.AIR.range4Queries fun i => row (4 + ↑i)) ++ + Aiur.AIR.range4Queries fun i => row (8 + ↑i) } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitU32LessThan_normal +∀ (selector : Aiur.NativeAIR.Expr) (first : Nat) (left right : Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.Normal (Aiur.NativeAIR.OpEmitter.emitU32LessThan selector first left right).outputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rowValues_getD +∀ (rows : Array Aiur.AIR.RowValue) (index : Nat), + (Aiur.AIR.rowValues rows)[index]?.getD 0 = (rows[index]?.getD (Aiur.AIR.RowValue.konst 0)).value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitAssert_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {left right : Array Aiur.NativeAIR.RowExpr} {a b : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + Aiur.NativeAIR.OpEmitter.evalRows values left = some a → + Aiur.NativeAIR.OpEmitter.evalRows values right = some b → + left.size = right.size → + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.emitAssert selector left right) = + some + { + equations := + List.ofFn fun index => + s * ((Aiur.AIR.rowValues a)[↑index]?.getD 0 - (Aiur.AIR.rowValues b)[↑index]?.getD 0) } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.fromScalar_eval +∀ (values : Aiur.NativeAIR.Values Aiur.G) (emission : Aiur.NativeAIR.ScalarEmission), + Aiur.NativeAIR.OpEmitter.Emission.eval values (Aiur.NativeAIR.OpEmitter.fromScalar emission) = + Aiur.NativeAIR.ScalarEmission.eval values emission +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.empty_eval +∀ (values : Aiur.NativeAIR.Values Aiur.G), Aiur.NativeAIR.OpEmitter.Emission.eval values { } = some { } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.normal_empty +Aiur.NativeAIR.OpEmitter.Normal #[] +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.normal_singleton +∀ {row : Aiur.NativeAIR.RowExpr}, row.expr.noConstantNegs = true → Aiur.NativeAIR.OpEmitter.Normal #[row] +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.Normal.read +∀ {rows : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.Normal rows → + ∀ {index : Nat} {row : Aiur.NativeAIR.RowExpr}, rows[index]? = some row → row.expr.noConstantNegs = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_byte1 +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) + (rows : Array Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = do + let __do_lift ← rows[index]? + pure (Aiur.NativeAIR.OpEmitter.emitByte1 first kind __do_lift) +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_byte2 +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (left right : Nat) + (rows : Array Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op left right) rows = do + let __do_lift ← rows[left]? + let __do_lift_1 ← rows[right]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first kind __do_lift __do_lift_1) +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (selector rank : Aiur.NativeAIR.Expr) (s r : Aiur.G) + (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {inputs : Array Aiur.AIR.RowValue} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → + (∀ (index : Nat), + index < emission.used → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + ∃ result, + Aiur.AIR.emitOp row s r (kind.op index) inputs = some result ∧ + Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (selector rank : Aiur.NativeAIR.Expr) (s r : Aiur.G) + (first : Nat) (kind : Aiur.AIR.Byte2Kind) (left right : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {inputs : Array Aiur.AIR.RowValue} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op left right) rows = some emission → + (∀ (index : Nat), + index < emission.used → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + ∃ result, + Aiur.AIR.emitOp row s r (kind.op left right) inputs = some result ∧ + Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.list_ofFn_getD_pair +∀ {α β γ : Type} (left : Array α) (right : Array β) (leftDefault : α) (rightDefault : β) (f : α → β → γ) {count : Nat} + (size : left.size = count), + (List.ofFn fun index => f (left[↑index]?.getD leftDefault) (right[↑index]?.getD rightDefault)) = + List.ofFn fun index => f left[index] (right[↑index]?.getD rightDefault) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} + {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + (∀ (index : Nat), + index < emission.used → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = + some (row index)) → + ∃ result, + Aiur.AIR.emitOp row s r op inputs = some result ∧ + Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_normal +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → + Aiur.NativeAIR.OpEmitter.Normal emission.outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_normal +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (a b : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows = some emission → + Aiur.NativeAIR.OpEmitter.Normal emission.outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_normal +∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + Aiur.NativeAIR.OpEmitter.Normal emission.outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.evalRows_append +∀ {values : Aiur.NativeAIR.Values Aiur.G} {left right : Array Aiur.NativeAIR.RowExpr} {a b : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values left = some a → + Aiur.NativeAIR.OpEmitter.evalRows values right = some b → + Aiur.NativeAIR.OpEmitter.evalRows values (left ++ right) = some (a ++ b) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.Normal.append +∀ {left right : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.Normal left → + Aiur.NativeAIR.OpEmitter.Normal right → Aiur.NativeAIR.OpEmitter.Normal (left ++ right) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.Emission.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.OpEmitter.Emission} {result : Aiur.AIR.OpEmission}, + Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result → + Aiur.NativeAIR.OpEmitter.evalRows values emission.outputs = some result.outputs ∧ + emission.used = result.used ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations ∧ + List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) emission.queries = some result.queries ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.CallExpr.eval values) emission.calls = some result.calls +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.OpsEmission.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} + {result : Aiur.AIR.OpsEmission}, + Aiur.NativeAIR.OpEmitter.evalRows values emission.values = some result.values → + emission.column = result.column → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations → + List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) emission.queries = some result.queries → + List.mapM (Aiur.NativeAIR.OpEmitter.CallExpr.eval values) emission.calls = some result.calls → + Aiur.NativeAIR.OpEmitter.OpsEmission.eval values emission = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.OpsEmission.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} + {result : Aiur.AIR.OpsEmission}, + Aiur.NativeAIR.OpEmitter.OpsEmission.eval values emission = some result → + Aiur.NativeAIR.OpEmitter.evalRows values emission.values = some result.values ∧ + emission.column = result.column ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations ∧ + List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) emission.queries = some result.queries ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.CallExpr.eval values) emission.calls = some result.calls +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitOps_column +∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → column ≤ emission.column +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitOps_normal +∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + Aiur.NativeAIR.OpEmitter.Normal emission.values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOps_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} + {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} {column : Nat} + {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + (∀ (index : Nat), + column ≤ index → + index < emission.column → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + ∃ result, + Aiur.AIR.emitOps row s r ops inputs column = some result ∧ + Aiur.NativeAIR.OpEmitter.OpsEmission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.addArgs_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {left right : List Aiur.NativeAIR.Expr} {a b : List Aiur.G}, + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) left = some a → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) right = some b → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (Aiur.NativeAIR.LookupEmitter.addArgs left right) = + some (Aiur.AIR.addMessages a b) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.gateArgs_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {args : List Aiur.NativeAIR.Expr} {results : List Aiur.G}, + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) args = some results → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (Aiur.NativeAIR.LookupEmitter.gateArgs branchless selector args) = + some (Aiur.AIR.gateMessage branchless s results) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.QueryExpr.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {query : Aiur.NativeAIR.LookupEmitter.QueryExpr} + {result : Aiur.AIR.QueryPart}, + Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values query = some result → + query.slot = result.slot ∧ + Aiur.NativeAIR.OpEmitter.evalExpr values query.selector = some result.selector ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) query.message = some result.message +AXIOMS [propext] +ROOT Aiur.NativeAIR.LookupEmitter.queryParts_cons +∀ (slot : Nat) (selector : Aiur.NativeAIR.Expr) (message : List Aiur.NativeAIR.Expr) + (queries : List (List Aiur.NativeAIR.Expr)), + Aiur.NativeAIR.LookupEmitter.queryParts slot selector (message :: queries) = + { slot := slot, selector := selector, message := message } :: + Aiur.NativeAIR.LookupEmitter.queryParts (slot + 1) selector queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.queryParts_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {queries : List (List Aiur.NativeAIR.Expr)} {messages : List (List Aiur.G)}, + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) queries = some messages → + ∀ (slot : Nat), + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) + (Aiur.NativeAIR.LookupEmitter.queryParts slot selector queries) = + some (Aiur.AIR.queryParts slot s messages) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.accumulate_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {lookup : Aiur.NativeAIR.Compiler.ExprLookup} + {query : Aiur.NativeAIR.LookupEmitter.QueryExpr} {initial : Aiur.G × List Aiur.G} {part : Aiur.AIR.QueryPart}, + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values lookup = some initial → + Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values query = some part → + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values + (Aiur.NativeAIR.LookupEmitter.accumulate branchless lookup query) = + some + (initial.fst + part.selector, + Aiur.AIR.addMessages initial.snd (Aiur.AIR.gateMessage branchless part.selector part.message)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.fold_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {queries : List Aiur.NativeAIR.LookupEmitter.QueryExpr} + {parts : List Aiur.AIR.QueryPart}, + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) queries = some parts → + ∀ {initial : Aiur.NativeAIR.Compiler.ExprLookup} {start : Aiur.G × List Aiur.G}, + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values initial = some start → + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values + (List.foldl (Aiur.NativeAIR.LookupEmitter.accumulate branchless) initial queries) = + some (List.foldl (Aiur.NativeAIR.LookupEmitter.valuedAccumulate branchless) start parts) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.filter_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {queries : List Aiur.NativeAIR.LookupEmitter.QueryExpr} + {parts : List Aiur.AIR.QueryPart}, + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) queries = some parts → + ∀ (slot : Nat), + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) + (List.filter (fun query => query.slot == slot) queries) = + some (List.filter (fun query => query.slot == slot) parts) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.valuedFold_eq +∀ (branchless : Bool) (parts : List Aiur.AIR.QueryPart) (start : Aiur.G × List Aiur.G), + List.foldl (Aiur.NativeAIR.LookupEmitter.valuedAccumulate branchless) start parts = + (List.foldl (fun x1 x2 => x1 + x2) start.fst (List.map Aiur.AIR.QueryPart.selector parts), + List.foldl (fun args part => Aiur.AIR.addMessages args (Aiur.AIR.gateMessage branchless part.fst part.snd)) + start.snd (List.map (fun part => (part.selector, part.message)) parts)) +AXIOMS [propext] +ROOT Aiur.NativeAIR.LookupEmitter.slot_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {queries : List Aiur.NativeAIR.LookupEmitter.QueryExpr} + {parts : List Aiur.AIR.QueryPart}, + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) queries = some parts → + ∀ (index : Nat), + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values + (Aiur.NativeAIR.LookupEmitter.slot branchless queries index) = + some + (Aiur.AIR.querySlotMultiplicity parts index, + Aiur.AIR.slotMessage branchless (Aiur.AIR.querySlotParts parts index)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LookupEmitter.slots_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {queries : List Aiur.NativeAIR.LookupEmitter.QueryExpr} + {parts : List Aiur.AIR.QueryPart}, + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) queries = some parts → + ∀ (count : Nat), + List.mapM (Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values) + (Aiur.NativeAIR.LookupEmitter.slots branchless queries count) = + some + (List.ofFn fun index => + (Aiur.AIR.querySlotMultiplicity parts ↑index, + Aiur.AIR.slotMessage branchless (Aiur.AIR.querySlotParts parts ↑index))) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.evaluated_read +∀ {values : Aiur.NativeAIR.Values Aiur.G} {expressions : Array Aiur.NativeAIR.Expr} {results : Array Aiur.G}, + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) expressions = some results → + ∀ {index : Nat} {expr : Aiur.NativeAIR.Expr}, + expressions[index]? = some expr → Aiur.NativeAIR.OpEmitter.evalExpr values expr = some (results[index]?.getD 0) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.list_mapM_evaluate +∀ {α β γ : Type} {first : α → Option β} {evaluate : β → Option γ} {inputs : List α} {outputs : List β}, + List.mapM first inputs = some outputs → + ∀ (value : α → γ), + (∀ (input : α) (output : β), first input = some output → evaluate output = some (value input)) → + List.mapM evaluate outputs = some (List.map value inputs) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.sum_fold_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {expressions : List Aiur.NativeAIR.Expr} {results : List Aiur.G}, + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) expressions = some results → + ∀ {initial : Aiur.NativeAIR.Expr} {start : Aiur.G}, + Aiur.NativeAIR.OpEmitter.evalExpr values initial = some start → + Aiur.NativeAIR.OpEmitter.evalExpr values (List.foldl Aiur.NativeAIR.Expr.frontAdd initial expressions) = + some (List.foldl (fun x1 x2 => x1 + x2) start results) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.sum_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {expressions : List Aiur.NativeAIR.Expr} {results : List Aiur.G}, + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) expressions = some results → + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.BlockEmitter.sum expressions) = + some (Aiur.AIR.selectorSum results) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.selectors_array_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selectors : Array Aiur.NativeAIR.Expr} {results : Array Aiur.G}, + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) selectors = some results → + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors fun index => results[index]?.getD 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.ctrlSelector_reads +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selectors : Array Aiur.NativeAIR.Expr} {selector : Nat → Aiur.G}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selector → + ∀ (ctrl : Aiur.Bytecode.Ctrl) {expr : Aiur.NativeAIR.Expr}, + Aiur.NativeAIR.BlockEmitter.ctrlSelector selectors ctrl = some expr → + Aiur.NativeAIR.OpEmitter.evalExpr values expr = some (Aiur.Bytecode.Ctrl.selectorFlow selector ctrl).entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.blockSelector_reads +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selectors : Array Aiur.NativeAIR.Expr} {selector : Nat → Aiur.G}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selector → + ∀ (block : Aiur.Bytecode.Block) {expr : Aiur.NativeAIR.Expr}, + Aiur.NativeAIR.BlockEmitter.blockSelector selectors block = some expr → + Aiur.NativeAIR.OpEmitter.evalExpr values expr = some (Aiur.Bytecode.Block.selectorFlow selector block).entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.ctrlSelector_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selectors : Array Aiur.NativeAIR.Expr} {results : Array Aiur.G}, + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) selectors = some results → + ∀ (ctrl : Aiur.Bytecode.Ctrl) {expr : Aiur.NativeAIR.Expr}, + Aiur.NativeAIR.BlockEmitter.ctrlSelector selectors ctrl = some expr → + Aiur.NativeAIR.OpEmitter.evalExpr values expr = + some (Aiur.Bytecode.Ctrl.selectorFlow (fun index => results[index]?.getD 0) ctrl).entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.blockSelector_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selectors : Array Aiur.NativeAIR.Expr} {results : Array Aiur.G}, + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) selectors = some results → + ∀ (block : Aiur.Bytecode.Block) {expr : Aiur.NativeAIR.Expr}, + Aiur.NativeAIR.BlockEmitter.blockSelector selectors block = some expr → + Aiur.NativeAIR.OpEmitter.evalExpr values expr = + some (Aiur.Bytecode.Block.selectorFlow (fun index => results[index]?.getD 0) block).entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.list_mapM_flatMap +∀ {α β γ δ : Type} {read : α → Option β} {inputs : List α} {outputs : List β}, + List.mapM read inputs = some outputs → + ∀ (first : α → List γ) (second : β → List δ) (evaluate : γ → Option δ), + (∀ (input : α) (output : β), read input = some output → List.mapM evaluate (first input) = some (second output)) → + List.mapM evaluate (List.flatMap first inputs) = some (List.flatMap second outputs) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.list_mapM_foldl +∀ {α β γ : Type} {read : α → Option β} {inputs : List α} {outputs : List β}, + List.mapM read inputs = some outputs → + ∀ (first : γ → α → γ) (second : γ → β → γ), + (∀ (input : α) (output : β), read input = some output → ∀ (start : γ), first start input = second start output) → + ∀ (start : γ), List.foldl first start inputs = List.foldl second start outputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.Emission.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.BlockEmitter.Emission} + {result : Aiur.AIR.BlockEmission}, + Aiur.NativeAIR.OpEmitter.evalRows values emission.values = some result.values → + emission.column = result.column → + emission.lookup = result.lookup → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations → + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) emission.queries = some result.queries → + List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) emission.returns = some result.returns → + List.mapM (Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values) emission.yields = some result.yields → + List.mapM (Aiur.NativeAIR.BlockEmitter.evalGatedCall values) emission.calls = some result.calls → + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.Emission.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.BlockEmitter.Emission} + {result : Aiur.AIR.BlockEmission}, + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result → + Aiur.NativeAIR.OpEmitter.evalRows values emission.values = some result.values ∧ + emission.column = result.column ∧ + emission.lookup = result.lookup ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations ∧ + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) emission.queries = some result.queries ∧ + List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) emission.returns = some result.returns ∧ + List.mapM (Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values) emission.yields = some result.yields ∧ + List.mapM (Aiur.NativeAIR.BlockEmitter.evalGatedCall values) emission.calls = some result.calls +AXIOMS [propext] +ROOT Aiur.NativeAIR.BlockEmitter.Emission.prefix_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.BlockEmitter.Emission} + {result : Aiur.AIR.BlockEmission} {equations : List Aiur.NativeAIR.Expr} {results : List Aiur.G}, + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) equations = some results → + Aiur.NativeAIR.BlockEmitter.Emission.eval values + (Aiur.NativeAIR.BlockEmitter.Emission.prefix equations emission) = + some (Aiur.AIR.BlockEmission.prefix results result) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.Emission.afterOps_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {incoming : Aiur.NativeAIR.Expr} {s : Aiur.G} (lookup : Nat) + {ops : Aiur.NativeAIR.OpEmitter.OpsEmission} {operations : Aiur.AIR.OpsEmission} + {control : Aiur.NativeAIR.BlockEmitter.Emission} {result : Aiur.AIR.BlockEmission}, + Aiur.NativeAIR.OpEmitter.evalExpr values incoming = some s → + Aiur.NativeAIR.OpEmitter.OpsEmission.eval values ops = some operations → + Aiur.NativeAIR.BlockEmitter.Emission.eval values control = some result → + Aiur.NativeAIR.BlockEmitter.Emission.eval values + (Aiur.NativeAIR.BlockEmitter.Emission.afterOps incoming lookup ops control) = + some (Aiur.AIR.BlockEmission.afterOps s lookup operations result) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.join_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + ∀ (column lookup : Nat) {emissions : List Aiur.NativeAIR.BlockEmitter.Emission} + {results : List Aiur.AIR.BlockEmission}, + List.mapM (Aiur.NativeAIR.BlockEmitter.Emission.eval values) emissions = some results → + Aiur.NativeAIR.BlockEmitter.Emission.eval values + (Aiur.NativeAIR.BlockEmitter.join rows column lookup emissions) = + some (Aiur.AIR.joinBlockEmissions inputs column lookup results) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.Emission.continued_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {branches continuation : Aiur.NativeAIR.BlockEmitter.Emission} + {first last : Aiur.AIR.BlockEmission} {equations : List Aiur.NativeAIR.Expr} {results : List Aiur.G}, + Aiur.NativeAIR.BlockEmitter.Emission.eval values branches = some first → + Aiur.NativeAIR.BlockEmitter.Emission.eval values continuation = some last → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) equations = some results → + Aiur.NativeAIR.BlockEmitter.Emission.eval values (branches.continued equations continuation) = + some (first.continued results last) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.YieldExpr.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {yielded : Aiur.NativeAIR.BlockEmitter.YieldExpr} {s : Aiur.G} + {outputs : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalExpr values yielded.selector = some s → + Aiur.NativeAIR.OpEmitter.evalRows values yielded.values = some outputs → + Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values yielded = some (s, outputs) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.YieldExpr.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {yielded : Aiur.NativeAIR.BlockEmitter.YieldExpr} + {result : Aiur.G × Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values yielded = some result → + Aiur.NativeAIR.OpEmitter.evalExpr values yielded.selector = some result.fst ∧ + Aiur.NativeAIR.OpEmitter.evalRows values yielded.values = some result.snd +AXIOMS [propext] +ROOT Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {returned : Aiur.NativeAIR.BlockEmitter.ReturnExpr} {s r : Aiur.G} + {inputs outputs : Array Aiur.G}, + Aiur.NativeAIR.OpEmitter.evalExpr values returned.selector = some s → + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) returned.inputs = some inputs → + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) returned.outputs = some outputs → + Aiur.NativeAIR.OpEmitter.evalExpr values returned.rank = some r → + Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values returned = + some (s, { function := returned.function, inputs := inputs, outputs := outputs, rank := r }) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {returned : Aiur.NativeAIR.BlockEmitter.ReturnExpr} + {result : Aiur.G × Aiur.Bytecode.AIR.Call}, + Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values returned = some result → + returned.function = result.snd.function ∧ + Aiur.NativeAIR.OpEmitter.evalExpr values returned.selector = some result.fst ∧ + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) returned.inputs = some result.snd.inputs ∧ + Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) returned.outputs = some result.snd.outputs ∧ + Aiur.NativeAIR.OpEmitter.evalExpr values returned.rank = some result.snd.rank +AXIOMS [propext] +ROOT Aiur.NativeAIR.BlockEmitter.ReturnExpr.message_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {returned : Aiur.NativeAIR.BlockEmitter.ReturnExpr} + {result : Aiur.G × Aiur.Bytecode.AIR.Call}, + Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values returned = some result → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) returned.message = some (Aiur.AIR.functionMessage result.snd) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.returned_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {s r : Aiur.G} {rows inputs outputs : Array Aiur.NativeAIR.RowExpr} + {a b c : Array Aiur.AIR.RowValue} (column lookup : Nat), + Aiur.NativeAIR.OpEmitter.evalExpr values incoming = some s → + Aiur.NativeAIR.OpEmitter.evalExpr values context.rank = some r → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some a → + Aiur.NativeAIR.OpEmitter.evalRows values inputs = some b → + Aiur.NativeAIR.OpEmitter.evalRows values outputs = some c → + Aiur.NativeAIR.BlockEmitter.Emission.eval values + (Aiur.NativeAIR.BlockEmitter.returned context incoming rows inputs outputs column lookup) = + some + { values := a, column := column, lookup := lookup, + returns := + [(s, + { function := context.function, inputs := Aiur.AIR.rowValues b, outputs := Aiur.AIR.rowValues c, + rank := r })] } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.yielded_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {selector : Aiur.NativeAIR.Expr} {s : Aiur.G} + {rows outputs : Array Aiur.NativeAIR.RowExpr} {a b : Array Aiur.AIR.RowValue} (column lookup : Nat), + Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some a → + Aiur.NativeAIR.OpEmitter.evalRows values outputs = some b → + Aiur.NativeAIR.BlockEmitter.Emission.eval values + (Aiur.NativeAIR.BlockEmitter.yielded selector rows outputs column lookup) = + some { values := a, column := column, lookup := lookup, yields := [(s, b)] } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.evalRows_getD_any +∀ {values : Aiur.NativeAIR.Values Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {results : Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalRows values rows = some results → + ∀ (index : Nat), + Aiur.NativeAIR.RowExpr.Reflects values (rows[index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)) + (results[index]?.getD (Aiur.AIR.RowValue.konst 0)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.yieldValue_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {yielded : Aiur.NativeAIR.BlockEmitter.YieldExpr} + {result : Aiur.G × Array Aiur.AIR.RowValue}, + Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values yielded = some result → + ∀ (index : Nat), + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.BlockEmitter.yieldValue yielded index) = + some (result.fst * (Aiur.AIR.rowValues result.snd)[index]?.getD 0) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.yieldGate_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {yields : List Aiur.NativeAIR.BlockEmitter.YieldExpr} + {results : List (Aiur.G × Array Aiur.AIR.RowValue)}, + List.mapM (Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values) yields = some results → + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.BlockEmitter.yieldGate yields) = + some (Aiur.AIR.selectorSum (List.map Prod.fst results)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.mergeEquations_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {incoming : Aiur.NativeAIR.Expr} {s : Aiur.G} + (column size : Nat) {yields : List Aiur.NativeAIR.BlockEmitter.YieldExpr} + {results : List (Aiur.G × Array Aiur.AIR.RowValue)}, + Aiur.NativeAIR.OpEmitter.evalExpr values incoming = some s → + List.mapM (Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values) yields = some results → + (∀ (index : Nat), + index < size → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[column + index]? = + some (row (column + index))) → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (Aiur.NativeAIR.BlockEmitter.mergeEquations incoming column size yields) = + some (Aiur.AIR.mergeEquations row s column size results) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.yields_size +∀ {values : Aiur.NativeAIR.Values Aiur.G} {yields : List Aiur.NativeAIR.BlockEmitter.YieldExpr} + {results : List (Aiur.G × Array Aiur.AIR.RowValue)}, + List.mapM (Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values) yields = some results → + ∀ (size : Nat), (yields.all fun part => part.values.size == size) = results.all fun part => part.snd.size == size +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.caseEquation_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {entry : Aiur.NativeAIR.Expr} {s : Aiur.G} {matched : Aiur.NativeAIR.RowExpr} + {value : Aiur.AIR.RowValue}, + Aiur.NativeAIR.OpEmitter.evalExpr values entry = some s → + Aiur.NativeAIR.RowExpr.Reflects values matched value → + ∀ (branch : Aiur.G), + Aiur.NativeAIR.OpEmitter.evalExpr values (Aiur.NativeAIR.BlockEmitter.caseEquation entry matched branch) = + some (s * (value.value - branch)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.defaultEquations_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {entry : Aiur.NativeAIR.Expr} {s : Aiur.G} + {matched : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue} (column : Nat) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)), + Aiur.NativeAIR.OpEmitter.evalExpr values entry = some s → + Aiur.NativeAIR.RowExpr.Reflects values matched value → + (∀ (index : Nat), + index < branches.size → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[column + index]? = + some (row (column + index))) → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (Aiur.NativeAIR.BlockEmitter.defaultEquations entry matched column branches) = + some + (List.mapIdx (fun index pair => s * ((value.value - pair.fst) * row (column + index) - 1)) branches.toList) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.fold_max_start +∀ {α : Type u_1} (measure : α → Nat) (items : List α) (start : Nat), + start ≤ List.foldl (fun current item => max current (measure item)) start items +AXIOMS [propext] +ROOT Aiur.NativeAIR.BlockEmitter.fold_max_member +∀ {α : Type u_1} (measure : α → Nat) {items : List α} {item : α}, + item ∈ items → ∀ (start : Nat), measure item ≤ List.foldl (fun current item => max current (measure item)) start items +AXIOMS [propext] +ROOT Aiur.NativeAIR.BlockEmitter.emitCtrl_match +∀ (selectors : Array Aiur.NativeAIR.Expr) (context : Aiur.NativeAIR.BlockEmitter.Context) + (incoming : Aiur.NativeAIR.Expr) (rows : Array Aiur.NativeAIR.RowExpr) (column lookup index : Nat) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block), + Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup + (Aiur.Bytecode.Ctrl.match index branches fallback) = + do + let matched ← rows[index]? + Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitCtrl_matchContinue +∀ (selectors : Array Aiur.NativeAIR.Expr) (context : Aiur.NativeAIR.BlockEmitter.Context) + (incoming : Aiur.NativeAIR.Expr) (rows : Array Aiur.NativeAIR.RowExpr) (column lookup index : Nat) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block) (size aux slots : Nat) + (continuation : Aiur.Bytecode.Block), + Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup + (Aiur.Bytecode.Ctrl.matchContinue index branches fallback size aux slots continuation) = + do + let matched ← rows[index]? + let joined ← Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback + Aiur.NativeAIR.BlockEmitter.continueRow selectors context incoming rows size continuation joined +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.branchRows_invariants +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {matched : Aiur.NativeAIR.RowExpr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} + {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback = + some emission → + Aiur.NativeAIR.OpEmitter.Normal emission.values ∧ column ≤ emission.column +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitCtrl_invariants +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + (ctrl : Aiur.Bytecode.Ctrl) {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup ctrl = some emission → + Aiur.NativeAIR.OpEmitter.Normal emission.values ∧ column ≤ emission.column +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitBlock_invariants +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + (block : Aiur.Bytecode.Block) {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context incoming rows column lookup block = some emission → + Aiur.NativeAIR.OpEmitter.Normal emission.values ∧ column ≤ emission.column +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.list_mapM_refine_mem +∀ {α β γ : Type} {first : α → Option β} {second : α → Option γ} {evaluate : β → Option γ} {inputs : List α} + {outputs : List β}, + List.mapM first inputs = some outputs → + (∀ (input : α), + input ∈ inputs → + ∀ (output : β), + output ∈ outputs → + first input = some output → ∃ value, second input = some value ∧ evaluate output = some value) → + ∃ values, List.mapM second inputs = some values ∧ List.mapM evaluate outputs = some values +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.caseRows_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {selectors : Array Aiur.NativeAIR.Expr} + {selected : Nat → Aiur.G} {context : Aiur.NativeAIR.BlockEmitter.Context} (rank : Aiur.G) + {matched : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue} {rows : Array Aiur.NativeAIR.RowExpr} + {inputs : Array Aiur.AIR.RowValue} (column lookup limit : Nat) {branches : Array (Aiur.G × Aiur.Bytecode.Block)} + {emissions : List Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selected → + Aiur.NativeAIR.RowExpr.Reflects values matched value → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + List.mapM (Aiur.NativeAIR.BlockEmitter.caseRow selectors context matched rows column lookup) branches.toList = + some emissions → + (∀ (emission : Aiur.NativeAIR.BlockEmitter.Emission), emission ∈ emissions → emission.column ≤ limit) → + (∀ (index : Nat), + column ≤ index → + index < limit → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + Aiur.NativeAIR.BlockEmitter.BlockReflects values row selectors selected context rank pair.snd) → + ∃ results, + List.mapM + (Aiur.Bytecode.caseRow row selected (context.valued rank) value.value inputs column lookup) + branches.toList = + some results ∧ + List.mapM (Aiur.NativeAIR.BlockEmitter.Emission.eval values) emissions = some results +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.defaultRow_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {selectors : Array Aiur.NativeAIR.Expr} + {selected : Nat → Aiur.G} {context : Aiur.NativeAIR.BlockEmitter.Context} (rank : Aiur.G) + {matched : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue} {rows : Array Aiur.NativeAIR.RowExpr} + {inputs : Array Aiur.AIR.RowValue} (column lookup limit : Nat) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + {fallback : Option Aiur.Bytecode.Block} {emissions : List Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selected → + Aiur.NativeAIR.RowExpr.Reflects values matched value → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.defaultRow selectors context matched rows column lookup branches fallback = + some emissions → + (∀ (emission : Aiur.NativeAIR.BlockEmitter.Emission), emission ∈ emissions → emission.column ≤ limit) → + (∀ (index : Nat), + column ≤ index → + index < limit → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + (∀ (block : Aiur.Bytecode.Block), + block ∈ fallback.toList → + Aiur.NativeAIR.BlockEmitter.BlockReflects values row selectors selected context rank block) → + ∃ results, + Aiur.Bytecode.defaultRow row selected (context.valued rank) value.value inputs column lookup + branches fallback = + some results ∧ + List.mapM (Aiur.NativeAIR.BlockEmitter.Emission.eval values) emissions = some results +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.branchRows_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {selectors : Array Aiur.NativeAIR.Expr} + {selected : Nat → Aiur.G} {context : Aiur.NativeAIR.BlockEmitter.Context} (rank : Aiur.G) + {matched : Aiur.NativeAIR.RowExpr} {value : Aiur.AIR.RowValue} {rows : Array Aiur.NativeAIR.RowExpr} + {inputs : Array Aiur.AIR.RowValue} {column lookup : Nat} {branches : Array (Aiur.G × Aiur.Bytecode.Block)} + {fallback : Option Aiur.Bytecode.Block} {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selected → + Aiur.NativeAIR.RowExpr.Reflects values matched value → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback = + some emission → + (∀ (index : Nat), + column ≤ index → + index < emission.column → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + Aiur.NativeAIR.BlockEmitter.BlockReflects values row selectors selected context rank pair.snd) → + (∀ (block : Aiur.Bytecode.Block), + block ∈ fallback.toList → + Aiur.NativeAIR.BlockEmitter.BlockReflects values row selectors selected context rank block) → + ∃ result, + Aiur.Bytecode.branchRows row selected (context.valued rank) value.value inputs column lookup + branches fallback = + some result ∧ + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.continueRow_column +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {rows : Array Aiur.NativeAIR.RowExpr} {size : Nat} + {continuation : Aiur.Bytecode.Block} {joined emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.continueRow selectors context incoming rows size continuation joined = some emission → + joined.column ≤ emission.column +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.advice_absolute_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) (column size : Nat), + (∀ (index : Nat), + index < size → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[column + index]? = + some (row (column + index))) → + Aiur.NativeAIR.OpEmitter.evalRows values (Aiur.NativeAIR.OpEmitter.advice column size) = + some (Aiur.AIR.rowAdvice row column size) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.continueRow_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {selectors : Array Aiur.NativeAIR.Expr} + {selected : Nat → Aiur.G} {context : Aiur.NativeAIR.BlockEmitter.Context} (rank : Aiur.G) + {incoming : Aiur.NativeAIR.Expr} {s : Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} + (size : Nat) (continuation : Aiur.Bytecode.Block) {joined emission : Aiur.NativeAIR.BlockEmitter.Emission} + {branches : Aiur.AIR.BlockEmission}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selected → + Aiur.NativeAIR.OpEmitter.evalExpr values incoming = some s → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.Emission.eval values joined = some branches → + Aiur.NativeAIR.BlockEmitter.continueRow selectors context incoming rows size continuation joined = + some emission → + (∀ (index : Nat), + joined.column ≤ index → + index < emission.column → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + Aiur.NativeAIR.BlockEmitter.BlockReflects values row selectors selected context rank continuation → + ∃ result, + Aiur.Bytecode.continueRow row selected (context.valued rank) s inputs size continuation branches = + some result ∧ + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.ctrl_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selectors : Array Aiur.NativeAIR.Expr} + {selected : Nat → Aiur.G} {context : Aiur.NativeAIR.BlockEmitter.Context} {rank : Aiur.G}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selected → + Aiur.NativeAIR.OpEmitter.evalExpr values context.rank = some rank → + ∀ (ctrl : Aiur.Bytecode.Ctrl), + Aiur.NativeAIR.BlockEmitter.CtrlReflects values row selectors selected context rank ctrl +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.block_reflects +∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selectors : Array Aiur.NativeAIR.Expr} + {selected : Nat → Aiur.G} {context : Aiur.NativeAIR.BlockEmitter.Context} {rank : Aiur.G}, + Aiur.NativeAIR.BlockEmitter.SelectorReads values selectors selected → + Aiur.NativeAIR.OpEmitter.evalExpr values context.rank = some rank → + ∀ (block : Aiur.Bytecode.Block), + Aiur.NativeAIR.BlockEmitter.BlockReflects values row selectors selected context rank block +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.returnArgs_fold_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {returns : List Aiur.NativeAIR.BlockEmitter.ReturnExpr} + {results : List (Aiur.G × Aiur.Bytecode.AIR.Call)}, + List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) returns = some results → + ∀ {initial : List Aiur.NativeAIR.Expr} {start : List Aiur.G}, + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) initial = some start → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (List.foldl + (fun args returned => + Aiur.NativeAIR.LookupEmitter.addArgs args + (Aiur.NativeAIR.LookupEmitter.gateArgs branchless returned.selector returned.message)) + initial returns) = + some + (List.foldl + (fun args part => + Aiur.AIR.addMessages args + (Aiur.AIR.gateMessage branchless part.fst (Aiur.AIR.functionMessage part.snd))) + start results) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.returnArgs_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {returns : List Aiur.NativeAIR.BlockEmitter.ReturnExpr} + {results : List (Aiur.G × Aiur.Bytecode.AIR.Call)}, + List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) returns = some results → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (Aiur.NativeAIR.BlockEmitter.returnArgs branchless returns) = + some + (Aiur.AIR.slotMessage branchless (List.map (fun part => (part.fst, Aiur.AIR.functionMessage part.snd)) results)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.lookup_eval +∀ (branchless : Bool) {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.BlockEmitter.Emission} + {result : Aiur.AIR.BlockEmission}, + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result → + ∀ (slot : Nat), + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values + (Aiur.NativeAIR.BlockEmitter.lookup branchless emission slot) = + some + (if slot = 0 then + (0, + Aiur.AIR.slotMessage branchless + (List.map (fun part => (part.fst, Aiur.AIR.functionMessage part.snd)) result.returns)) + else + (Aiur.AIR.querySlotMultiplicity result.queries slot, + Aiur.AIR.slotMessage branchless (Aiur.AIR.querySlotParts result.queries slot))) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.selectorExprs_reads +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) (base count : Nat), + (∀ (index : Nat), + index < count → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[base + index]? = + some (row (base + index))) → + Aiur.NativeAIR.BlockEmitter.SelectorReads values (Aiur.NativeAIR.CircuitEmitter.selectorExprs base count) + fun index => row (base + index) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Member.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {member : Aiur.NativeAIR.CircuitEmitter.Member} + {body : Aiur.AIR.BlockEmission}, + Aiur.NativeAIR.BlockEmitter.Emission.eval values member.body = some body → + Aiur.NativeAIR.CircuitEmitter.Member.eval values member = + some + { functionIndex := member.functionIndex, function := member.function, selectorBase := member.selectorBase, + body := body } +AXIOMS [propext] +ROOT Aiur.NativeAIR.CircuitEmitter.Member.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {member : Aiur.NativeAIR.CircuitEmitter.Member} + {result : Aiur.AIR.MemberEmission}, + Aiur.NativeAIR.CircuitEmitter.Member.eval values member = some result → + member.functionIndex = result.functionIndex ∧ + member.function = result.function ∧ + member.selectorBase = result.selectorBase ∧ + Aiur.NativeAIR.BlockEmitter.Emission.eval values member.body = some result.body +AXIOMS [propext] +ROOT Aiur.NativeAIR.CircuitEmitter.selectorEquations_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) (layout : Aiur.Bytecode.FunctionLayout), + (∀ (index : Nat), + index < layout.selectors → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[layout.inputSize + index]? = + some (row (layout.inputSize + index))) → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (Aiur.NativeAIR.CircuitEmitter.selectorEquations layout) = + some + (List.map (fun index => Aiur.AIR.booleanConstraint (row (layout.inputSize + index))) + (List.range layout.selectors)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.evalFin_of +∀ {size : Nat} {values : Aiur.NativeAIR.Values Aiur.G} {expressions : Fin size → Aiur.NativeAIR.Expr} + {results : Fin size → Aiur.G}, + (∀ (index : Fin size), Aiur.NativeAIR.OpEmitter.evalExpr values (expressions index) = some (results index)) → + Aiur.NativeAIR.CircuitEmitter.evalFin values expressions = some results +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.evalFin_components +∀ {size : Nat} {values : Aiur.NativeAIR.Values Aiur.G} {expressions : Fin size → Aiur.NativeAIR.Expr} + {results : Fin size → Aiur.G}, + Aiur.NativeAIR.CircuitEmitter.evalFin values expressions = some results → + ∀ (index : Fin size), Aiur.NativeAIR.OpEmitter.evalExpr values (expressions index) = some (results index) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.eval_of +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} + {result : Aiur.AIR.CircuitEmission}, + List.mapM (Aiur.NativeAIR.CircuitEmitter.Member.eval values) emission.members = some result.members → + Aiur.NativeAIR.OpEmitter.evalExpr values emission.selector = some result.selector → + Aiur.NativeAIR.OpEmitter.evalExpr values emission.multiplicity = some result.multiplicity → + (∀ (index : Fin 6), + Aiur.NativeAIR.OpEmitter.evalExpr values (emission.rankBytes index) = some (result.rankBytes index)) → + emission.width = result.width → + emission.selectorStart = result.selectorStart → + emission.selectorCount = result.selectorCount → + emission.lookupCount = result.lookupCount → + emission.branchless = result.branchless → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations → + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) emission.queries = + some result.queries → + List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) emission.returns = + some result.returns → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.eval_components +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} + {result : Aiur.AIR.CircuitEmission}, + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → + List.mapM (Aiur.NativeAIR.CircuitEmitter.Member.eval values) emission.members = some result.members ∧ + Aiur.NativeAIR.OpEmitter.evalExpr values emission.selector = some result.selector ∧ + Aiur.NativeAIR.OpEmitter.evalExpr values emission.multiplicity = some result.multiplicity ∧ + (∀ (index : Fin 6), + Aiur.NativeAIR.OpEmitter.evalExpr values (emission.rankBytes index) = some (result.rankBytes index)) ∧ + emission.width = result.width ∧ + emission.selectorStart = result.selectorStart ∧ + emission.selectorCount = result.selectorCount ∧ + emission.lookupCount = result.lookupCount ∧ + emission.branchless = result.branchless ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations = some result.equations ∧ + List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) emission.queries = + some result.queries ∧ + List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) emission.returns = + some result.returns +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.lookup_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} + {result : Aiur.AIR.CircuitEmission}, + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → + ∀ (slot : Nat), + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values (emission.lookup slot) = + some (result.lookup slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.lookups_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} + {result : Aiur.AIR.CircuitEmission}, + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → + List.mapM (Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values) emission.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitMember_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {rank : Aiur.NativeAIR.Expr} {r : Aiur.G} + {column lookup selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} {functionIndex : Nat} + {member : Aiur.NativeAIR.CircuitEmitter.Member}, + Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → + Aiur.NativeAIR.CircuitEmitter.emitMember rank column lookup selectorBase program functionIndex = some member → + (∀ (index : Nat), + index < member.readBound → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → + ∃ result, + Aiur.AIR.emitMember row r column lookup selectorBase program functionIndex = some result ∧ + Aiur.NativeAIR.CircuitEmitter.Member.eval values member = some result ∧ + Aiur.NativeAIR.OpEmitter.evalExpr values member.entry = some (Aiur.AIR.MemberEmission.entry row result) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitMembers_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {rank : Aiur.NativeAIR.Expr} {r : Aiur.G} + (column lookup selectorBase : Nat) (program : Aiur.Bytecode.Toplevel) (indices : List Nat) + {members : List Aiur.NativeAIR.CircuitEmitter.Member}, + Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → + Aiur.NativeAIR.CircuitEmitter.emitMembers rank column lookup selectorBase program indices = some members → + (∀ (member : Aiur.NativeAIR.CircuitEmitter.Member), + member ∈ members → + ∀ (index : Nat), + index < member.readBound → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + ∃ results, + Aiur.AIR.emitMembers row r column lookup selectorBase program indices = some results ∧ + List.mapM (Aiur.NativeAIR.CircuitEmitter.Member.eval values) members = some results ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (List.map Aiur.NativeAIR.CircuitEmitter.Member.entry members) = + some (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) results) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.circuitEmission_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) (circuit : Aiur.Bytecode.Circuit) + {members : List Aiur.NativeAIR.CircuitEmitter.Member} {results : List Aiur.AIR.MemberEmission}, + List.mapM (Aiur.NativeAIR.CircuitEmitter.Member.eval values) members = some results → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (List.map Aiur.NativeAIR.CircuitEmitter.Member.entry members) = + some (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) results) → + (∀ (index : Nat), + index < circuit.layout.inputSize + circuit.layout.selectors + 1 + 6 → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values + (Aiur.NativeAIR.CircuitEmitter.circuitEmission circuit members) = + some (Aiur.AIR.circuitEmission row circuit results) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitCircuit_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) + (circuit : Aiur.Bytecode.Circuit) {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.emitCircuit program circuit = some emission → + (∀ (index : Nat), + index < emission.readBound → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → + ∃ result, + Aiur.Bytecode.Circuit.emitRow row program circuit = some result ∧ + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.equations_vanish +∀ {values : Aiur.NativeAIR.Values Aiur.G} {expressions : List Aiur.NativeAIR.Expr} {results : List Aiur.G}, + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) expressions = some results → + (Aiur.NativeAIR.Compiler.ExprsVanish Aiur.NativeAIR.goldilocksOps values expressions ↔ + ∀ (result : Aiur.G), result ∈ results → result = 0) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCircuit_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileCircuit widths program circuit = some compiled → + (∀ (index : Nat), + index < compiled.emission.readBound → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitRow row program circuit = some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.selectedDegree_initial +∀ (degrees indices : Array Nat) (initial : Nat), + Aiur.Bytecode.selectedDegree degrees indices initial = max initial (Aiur.Bytecode.selectedDegree degrees indices 0) +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.selectedDegree_append +∀ (degrees left right : Array Nat) (initial : Nat), + Aiur.Bytecode.selectedDegree degrees (left ++ right) initial = + max (Aiur.Bytecode.selectedDegree degrees left initial) (Aiur.Bytecode.selectedDegree degrees right 0) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.getDegree_list +∀ (indices : List Aiur.Bytecode.ValIdx) (initial : Aiur.Concrete.Bytecode.LayoutMState), + StateT.run (List.mapM Aiur.Concrete.Bytecode.getDegree indices) initial = + (List.map (fun i => initial.degrees[i]?.getD 0) indices, initial) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.getDegree_array +∀ (indices : Array Aiur.Bytecode.ValIdx), + Array.mapM Aiur.Concrete.Bytecode.getDegree indices = fun initial => + pure (Array.map (fun i => initial.degrees[i]?.getD 0) indices, initial) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opLayout_allocation +∀ (op : Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.degrees = + initial.degrees ++ (Aiur.Bytecode.Op.allocationFor initial.callRanks initial.degrees op).degrees ∧ + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.functionLayout.auxiliaries = + initial.functionLayout.auxiliaries + + (Aiur.Bytecode.Op.allocationFor initial.callRanks initial.degrees op).auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.RowExpr.ZeroConstant.konst +∀ (value : Aiur.G), (Aiur.NativeAIR.RowExpr.konst value).ZeroConstant +AXIOMS [] +ROOT Aiur.NativeAIR.RowExpr.ZeroConstant.variable +∀ (column : Aiur.NativeAIR.ColRef), (Aiur.NativeAIR.RowExpr.variable column).ZeroConstant +AXIOMS [] +ROOT Aiur.NativeAIR.RowExpr.ZeroConstant.add +∀ {left right : Aiur.NativeAIR.RowExpr}, left.ZeroConstant → right.ZeroConstant → (left.add right).ZeroConstant +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.RowExpr.ZeroConstant.sub +∀ {left right : Aiur.NativeAIR.RowExpr}, left.ZeroConstant → right.ZeroConstant → (left.sub right).ZeroConstant +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.RowExpr.ZeroConstant.mul +∀ {left right : Aiur.NativeAIR.RowExpr}, left.ZeroConstant → right.ZeroConstant → (left.mul right).ZeroConstant +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.DegreeValid.empty +Aiur.NativeAIR.OpEmitter.DegreeValid #[] +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.DegreeValid.singleton +∀ {row : Aiur.NativeAIR.RowExpr}, row.ZeroConstant → Aiur.NativeAIR.OpEmitter.DegreeValid #[row] +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.DegreeValid.append +∀ {left right : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.DegreeValid left → + Aiur.NativeAIR.OpEmitter.DegreeValid right → Aiur.NativeAIR.OpEmitter.DegreeValid (left ++ right) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.DegreeValid.push +∀ {rows : Array Aiur.NativeAIR.RowExpr} {row : Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → row.ZeroConstant → Aiur.NativeAIR.OpEmitter.DegreeValid (rows.push row) +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.DegreeValid.read +∀ {rows : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + ∀ {index : Nat} {row : Aiur.NativeAIR.RowExpr}, rows[index]? = some row → row.ZeroConstant +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.DegreeValid.getD +∀ {rows : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + ∀ (index : Nat), (rows[index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)).ZeroConstant +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.DegreeValid.select +∀ {rows : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + ∀ {indices : Array Nat} {selected : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.select rows indices = some selected → Aiur.NativeAIR.OpEmitter.DegreeValid selected +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.advice_degreeValid +∀ (first count : Nat), Aiur.NativeAIR.OpEmitter.DegreeValid (Aiur.NativeAIR.OpEmitter.advice first count) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packFour_degreeValid +∀ (bytes : Fin 4 → Aiur.NativeAIR.RowExpr), + (∀ (index : Fin 4), (bytes index).ZeroConstant) → (Aiur.NativeAIR.OpEmitter.packFour bytes).ZeroConstant +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.readWord_degreeValid +∀ {rows : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + ∀ {indices : Array Nat} {word : Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.readWord rows indices = some word → word.ZeroConstant +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.fromScalar_degreeValid +∀ {scalar : Aiur.NativeAIR.ScalarEmission}, + scalar.output.ZeroConstant → Aiur.NativeAIR.OpEmitter.DegreeValid (Aiur.NativeAIR.OpEmitter.fromScalar scalar).outputs +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitMul_degreeValid +∀ (selector : Aiur.NativeAIR.Expr) (first : Nat) {left right : Aiur.NativeAIR.RowExpr}, + left.ZeroConstant → right.ZeroConstant → (Aiur.NativeAIR.emitMul selector first left right).output.ZeroConstant +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitEqZero_degreeValid +∀ (selector : Aiur.NativeAIR.Expr) (first : Nat) (input : Aiur.NativeAIR.RowExpr), + (Aiur.NativeAIR.emitEqZero selector first input).output.ZeroConstant +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitByte2_degreeValid +∀ (first : Nat) (kind : Aiur.AIR.Byte2Kind) (left right : Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.DegreeValid (Aiur.NativeAIR.OpEmitter.emitByte2 first kind left right).outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitWordSum_degreeValid +∀ (first : Nat) {sum : Aiur.NativeAIR.RowExpr}, + sum.ZeroConstant → Aiur.NativeAIR.OpEmitter.DegreeValid (Aiur.NativeAIR.OpEmitter.emitWordSum first sum).outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitU32LessThan_degreeValid +∀ (selector : Aiur.NativeAIR.Expr) (first : Nat) (left right : Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.DegreeValid (Aiur.NativeAIR.OpEmitter.emitU32LessThan selector first left right).outputs +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_degreeValid +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → + Aiur.NativeAIR.OpEmitter.DegreeValid emission.outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_degreeValid +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (a b : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows = some emission → + Aiur.NativeAIR.OpEmitter.DegreeValid emission.outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_degreeValid +∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + Aiur.NativeAIR.OpEmitter.DegreeValid emission.outputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOps_degreeValid +∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + Aiur.NativeAIR.OpEmitter.DegreeValid emission.values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitEqZero_allocation +∀ (selector : Aiur.NativeAIR.Expr) (first : Nat) {input : Aiur.NativeAIR.RowExpr}, + input.ZeroConstant → + ((Aiur.NativeAIR.emitEqZero selector first input).used, + (Aiur.NativeAIR.emitEqZero selector first input).output.degree) = + if input.degree = 0 then (0, 0) else (2, 1) +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.rowDegrees_empty +Aiur.NativeAIR.OpEmitter.rowDegrees #[] = #[] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rowDegrees_append +∀ (left right : Array Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.rowDegrees (left ++ right) = + Aiur.NativeAIR.OpEmitter.rowDegrees left ++ Aiur.NativeAIR.OpEmitter.rowDegrees right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rowDegrees_push +∀ (rows : Array Aiur.NativeAIR.RowExpr) (row : Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.rowDegrees (rows.push row) = (Aiur.NativeAIR.OpEmitter.rowDegrees rows).push row.degree +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rowDegrees_singleton +∀ (row : Aiur.NativeAIR.RowExpr), Aiur.NativeAIR.OpEmitter.rowDegrees #[row] = #[row.degree] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rowDegrees_getD +∀ (rows : Array Aiur.NativeAIR.RowExpr) (index : Nat), + (Aiur.NativeAIR.OpEmitter.rowDegrees rows)[index]?.getD 0 = + (rows[index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)).degree +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.rowDegrees_read +∀ {rows : Array Aiur.NativeAIR.RowExpr} {index : Nat} {row : Aiur.NativeAIR.RowExpr}, + rows[index]? = some row → (Aiur.NativeAIR.OpEmitter.rowDegrees rows)[index]?.getD 0 = row.degree +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.select_degrees +∀ {rows : Array Aiur.NativeAIR.RowExpr} {indices : Array Nat} {selected : Array Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.select rows indices = some selected → + Array.map (fun index => (Aiur.NativeAIR.OpEmitter.rowDegrees rows)[index]?.getD 0) indices = + Aiur.NativeAIR.OpEmitter.rowDegrees selected +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.advice_degrees +∀ (first count : Nat), + Aiur.NativeAIR.OpEmitter.rowDegrees (Aiur.NativeAIR.OpEmitter.advice first count) = Array.replicate count 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.packFour_degree +∀ (bytes : Fin 4 → Aiur.NativeAIR.RowExpr), + (Aiur.NativeAIR.OpEmitter.packFour bytes).degree = + Array.foldl Nat.max 0 (Aiur.NativeAIR.OpEmitter.rowDegrees (Array.ofFn bytes)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.readWord_degree +∀ {rows : Array Aiur.NativeAIR.RowExpr} {indices : Array Nat} {word : Aiur.NativeAIR.RowExpr}, + Aiur.NativeAIR.OpEmitter.readWord rows indices = some word → + word.degree = Aiur.Bytecode.selectedDegree (Aiur.NativeAIR.OpEmitter.rowDegrees rows) indices 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitAdvice_allocation +∀ (first count : Nat), + (Aiur.NativeAIR.OpEmitter.emitAdvice first count).allocation = Aiur.Bytecode.OpAllocation.advice count +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitWordSum_allocation +∀ (first : Nat) (sum : Aiur.NativeAIR.RowExpr), + (Aiur.NativeAIR.OpEmitter.emitWordSum first sum).allocation = + { degrees := (Array.replicate 4 1).push (max sum.degree 1), auxiliaries := 4 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_allocation +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → + emission.allocation = Aiur.Bytecode.Op.allocation (Aiur.NativeAIR.OpEmitter.rowDegrees rows) (kind.op index) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_allocation +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (a b : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows = some emission → + emission.allocation = Aiur.Bytecode.Op.allocation (Aiur.NativeAIR.OpEmitter.rowDegrees rows) (kind.op a b) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_allocation +∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + emission.allocation = Aiur.Bytecode.Op.allocation (Aiur.NativeAIR.OpEmitter.rowDegrees rows) op +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_layout +∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission} (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.degrees = + Aiur.NativeAIR.OpEmitter.rowDegrees (rows ++ emission.outputs) ∧ + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.functionLayout.auxiliaries = + initial.functionLayout.auxiliaries + emission.used +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOps_fold_layout +∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} (initial : Aiur.Concrete.Bytecode.LayoutMState) + (base : Nat), + initial.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → + column = base + initial.functionLayout.auxiliaries → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + (StateT.run (List.foldlM (fun x op => Aiur.Concrete.Bytecode.opLayout op) () ops) initial).snd.degrees = + Aiur.NativeAIR.OpEmitter.rowDegrees emission.values ∧ + emission.column = + base + + (StateT.run (List.foldlM (fun x op => Aiur.Concrete.Bytecode.opLayout op) () ops) + initial).snd.functionLayout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOps_layout +∀ {selector rank : Aiur.NativeAIR.Expr} {ops : Array Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} (initial : Aiur.Concrete.Bytecode.LayoutMState) + (base : Nat), + initial.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → + column = base + initial.functionLayout.auxiliaries → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops.toList rows column = some emission → + (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.degrees = + Aiur.NativeAIR.OpEmitter.rowDegrees emission.values ∧ + emission.column = + base + + (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.functionLayout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchStep_degrees +∀ (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) (acc : Aiur.Concrete.Bytecode.SharedData) + (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc block) initial).snd.degrees = degrees +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchStep_column +∀ (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) (acc : Aiur.Concrete.Bytecode.SharedData) + (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState) (base column : Nat), + initial.degrees = degrees → + initial.callRanks = #[] → + (∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = #[] → + state.degrees = degrees → + state.functionLayout.auxiliaries = shared.auxiliaries → + column = + base + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) state).snd.functionLayout.auxiliaries) → + base + + (StateT.run (Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc block) + initial).fst.auxiliaries = + max (base + acc.auxiliaries) column +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchFold +∀ {α β : Type} {items : List α} {emissions : List β} (blockOf : α → Aiur.Bytecode.Block) (measure : β → Nat) + (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) (base : Nat), + List.Forall₂ + (fun item emission => + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = #[] → + state.degrees = degrees → + state.functionLayout.auxiliaries = shared.auxiliaries → + measure emission = + base + + (StateT.run (Aiur.Concrete.Bytecode.blockLayout (blockOf item)) + state).snd.functionLayout.auxiliaries) + items emissions → + ∀ (acc : Aiur.Concrete.Bytecode.SharedData) (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.degrees = degrees → + initial.callRanks = #[] → + (StateT.run + (List.foldlM + (fun acc item => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc (blockOf item)) + acc items) + initial).snd.degrees = + degrees ∧ + base + + (StateT.run + (List.foldlM + (fun acc item => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc (blockOf item)) + acc items) + initial).fst.auxiliaries = + List.foldl (fun current emission => max current (measure emission)) (base + acc.auxiliaries) emissions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchLoop +∀ (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat), + Array.foldlM (fun acc pair => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc pair.val.snd) shared + branches.attach = + List.foldlM (fun acc pair => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc pair.snd) shared + branches.toList +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.matchLayout_allocation +∀ {β : Type} (index : Aiur.Bytecode.ValIdx) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat) + (measure : β → Nat) {cases defaults : List β}, + initial.callRanks = #[] → + List.Forall₂ + (fun pair emission => + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = #[] → + state.degrees = initial.degrees → + state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → + measure emission = + base + + (StateT.run (Aiur.Concrete.Bytecode.blockLayout pair.snd) state).snd.functionLayout.auxiliaries) + branches.toList cases → + List.Forall₂ + (fun block emission => + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = #[] → + state.degrees = initial.degrees → + state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + branches.size → + measure emission = + base + + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) state).snd.functionLayout.auxiliaries) + fallback.toList defaults → + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback)) + initial).snd.degrees = + initial.degrees ∧ + base + + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback)) + initial).snd.functionLayout.auxiliaries = + List.foldl (fun current emission => max current (measure emission)) + (base + initial.functionLayout.auxiliaries) (cases ++ defaults) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.ctrlLayout_continue +∀ (index : Aiur.Bytecode.ValIdx) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block) (size aux slots : Nat) (continuation : Aiur.Bytecode.Block), + Aiur.Concrete.Bytecode.ctrlLayout + (Aiur.Bytecode.Ctrl.matchContinue index branches fallback size aux slots continuation) = + do + Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback) + Aiur.Concrete.Bytecode.bumpAuxiliaries size + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate size 1) + Aiur.Concrete.Bytecode.blockLayout continuation +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.branchRows_values +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {matched : Aiur.NativeAIR.RowExpr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} + {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback = + some emission → + emission.values = rows +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitCtrl_degreeValid +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + (ctrl : Aiur.Bytecode.Ctrl) {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup ctrl = some emission → + Aiur.NativeAIR.OpEmitter.DegreeValid emission.values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitBlock_degreeValid +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + (block : Aiur.Bytecode.Block) {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context incoming rows column lookup block = some emission → + Aiur.NativeAIR.OpEmitter.DegreeValid emission.values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.branchRows_layout +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {matched : Aiur.NativeAIR.RowExpr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} + {emission : Aiur.NativeAIR.BlockEmitter.Emission} (index : Nat) (initial : Aiur.Concrete.Bytecode.LayoutMState) + (base : Nat), + initial.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → + column = base + initial.functionLayout.auxiliaries → + Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback = + some emission → + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + ∀ (entry : Aiur.NativeAIR.Expr) (result : Aiur.NativeAIR.BlockEmitter.Emission) + (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = state.degrees → + column = base + state.functionLayout.auxiliaries → + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows column lookup pair.snd = + some result → + result.column = + base + + (StateT.run (Aiur.Concrete.Bytecode.blockLayout pair.snd) + state).snd.functionLayout.auxiliaries) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → + ∀ (entry : Aiur.NativeAIR.Expr) (result : Aiur.NativeAIR.BlockEmitter.Emission) + (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = state.degrees → + column + branches.size = base + state.functionLayout.auxiliaries → + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows (column + branches.size) + lookup block = + some result → + result.column = + base + + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) + state).snd.functionLayout.auxiliaries) → + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback)) + initial).snd.degrees = + Aiur.NativeAIR.OpEmitter.rowDegrees emission.values ∧ + emission.column = + base + + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback)) + initial).snd.functionLayout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitCtrl_layout +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + (ctrl : Aiur.Bytecode.Ctrl) {emission : Aiur.NativeAIR.BlockEmitter.Emission} + (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat), + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + initial.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → + column = base + initial.functionLayout.auxiliaries → + Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup ctrl = some emission → + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout ctrl) initial).snd.degrees = + Aiur.NativeAIR.OpEmitter.rowDegrees emission.values ∧ + emission.column = + base + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout ctrl) initial).snd.functionLayout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitBlock_layout +∀ {selectors : Array Aiur.NativeAIR.Expr} {context : Aiur.NativeAIR.BlockEmitter.Context} + {incoming : Aiur.NativeAIR.Expr} {rows : Array Aiur.NativeAIR.RowExpr} {column lookup : Nat} + (block : Aiur.Bytecode.Block) {emission : Aiur.NativeAIR.BlockEmitter.Emission} + (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat), + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + initial.callRanks = #[] → + Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → + column = base + initial.functionLayout.auxiliaries → + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context incoming rows column lookup block = some emission → + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) initial).snd.degrees = + Aiur.NativeAIR.OpEmitter.rowDegrees emission.values ∧ + emission.column = + base + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) initial).snd.functionLayout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opLayout_fixed +∀ (op : Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.functionLayout.inputSize = + initial.functionLayout.inputSize ∧ + (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.functionLayout.selectors = + initial.functionLayout.selectors +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.opsLayout_fields +∀ (ops : Array Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), + have final := (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.functionLayout; + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors ∧ initial.functionLayout.auxiliaries ≤ final.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchStep_fields +∀ (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) (acc : Aiur.Concrete.Bytecode.SharedData) + (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) state).snd.functionLayout.inputSize = + state.functionLayout.inputSize ∧ + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) state).snd.functionLayout.selectors = + state.functionLayout.selectors + block.controlCounts.leaves) → + have final := StateT.run (Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc block) initial; + final.snd.functionLayout.inputSize = initial.functionLayout.inputSize ∧ + final.snd.functionLayout.selectors = initial.functionLayout.selectors + block.controlCounts.leaves ∧ + acc.auxiliaries ≤ final.fst.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.allocationBranchFold_fields +∀ {α : Type} (items : List α) (blockOf : α → Aiur.Bytecode.Block) (shared : Aiur.Concrete.Bytecode.SharedData) + (degrees : Array Nat) (acc : Aiur.Concrete.Bytecode.SharedData) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (∀ (item : α), + item ∈ items → + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.blockLayout (blockOf item)) state).snd.functionLayout.inputSize = + state.functionLayout.inputSize ∧ + (StateT.run (Aiur.Concrete.Bytecode.blockLayout (blockOf item)) state).snd.functionLayout.selectors = + state.functionLayout.selectors + (blockOf item).controlCounts.leaves) → + have final := + StateT.run + (List.foldlM (fun acc item => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc (blockOf item)) acc + items) + initial; + final.snd.functionLayout.inputSize = initial.functionLayout.inputSize ∧ + final.snd.functionLayout.selectors = + initial.functionLayout.selectors + (List.map (fun item => (blockOf item).controlCounts.leaves) items).sum ∧ + acc.auxiliaries ≤ final.fst.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.matchLayout_fields +∀ (index : Aiur.Bytecode.ValIdx) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.blockLayout pair.snd) state).snd.functionLayout.inputSize = + state.functionLayout.inputSize ∧ + (StateT.run (Aiur.Concrete.Bytecode.blockLayout pair.snd) state).snd.functionLayout.selectors = + state.functionLayout.selectors + pair.snd.controlCounts.leaves) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) state).snd.functionLayout.inputSize = + state.functionLayout.inputSize ∧ + (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) state).snd.functionLayout.selectors = + state.functionLayout.selectors + block.controlCounts.leaves) → + have final := + (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback)) + initial).snd.functionLayout; + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = + initial.functionLayout.selectors + + (Aiur.Bytecode.ControlCounts.sum (Aiur.Bytecode.branchControlCounts branches fallback)).leaves ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.ctrlLayout_fields +∀ (ctrl : Aiur.Bytecode.Ctrl) (initial : Aiur.Concrete.Bytecode.LayoutMState), + have final := (StateT.run (Aiur.Concrete.Bytecode.ctrlLayout ctrl) initial).snd.functionLayout; + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors + ctrl.controlCounts.leaves ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.blockLayout_fields +∀ (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState), + have final := (StateT.run (Aiur.Concrete.Bytecode.blockLayout block) initial).snd.functionLayout; + final.inputSize = initial.functionLayout.inputSize ∧ + final.selectors = initial.functionLayout.selectors + block.controlCounts.leaves ∧ + initial.functionLayout.auxiliaries ≤ final.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.ctrlLayout_match_list +∀ (index : Aiur.Bytecode.ValIdx) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block), + Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback) = do + let shared ← Aiur.Concrete.Bytecode.getSharedData + let degrees ← Aiur.Concrete.Bytecode.getDegrees + let acc ← + List.foldlM (fun acc pair => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc pair.snd) shared + branches.toList + have __do_jp : Aiur.Concrete.Bytecode.SharedData → Aiur.Concrete.Bytecode.LayoutM Unit := fun final => + Aiur.Concrete.Bytecode.setSharedData final + match fallback with + | none => do + let final ← pure acc + __do_jp final + | some block => do + Aiur.Concrete.Bytecode.setSharedData shared + Aiur.Concrete.Bytecode.bumpAuxiliaries branches.size + Aiur.Concrete.Bytecode.blockLayout block + let used ← Aiur.Concrete.Bytecode.getSharedData + Aiur.Concrete.Bytecode.setDegrees degrees + let final ← pure (acc.maximals used) + __do_jp final +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.rewriteOp_layout +∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) (op : Aiur.Bytecode.Op) + (initial : Aiur.Concrete.Bytecode.LayoutMState), + Aiur.Concrete.Bytecode.LayoutRenaming rename initial.callRanks → + StateT.run (Aiur.Concrete.Bytecode.opLayout (Aiur.Bytecode.rewriteOp rename op)) initial = + StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.matchLayout_rewrite +∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) (index : Aiur.Bytecode.ValIdx) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block) + (ranks : Array Aiur.Bytecode.CallRank) (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = ranks → + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = ranks → + StateT.run (Aiur.Concrete.Bytecode.blockLayout (Aiur.Bytecode.rewriteBlock rename pair.snd)) state = + StateT.run (Aiur.Concrete.Bytecode.blockLayout pair.snd) state) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → + ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), + state.callRanks = ranks → + StateT.run (Aiur.Concrete.Bytecode.blockLayout (Aiur.Bytecode.rewriteBlock rename block)) state = + StateT.run (Aiur.Concrete.Bytecode.blockLayout block) state) → + StateT.run + (Aiur.Concrete.Bytecode.ctrlLayout + (Aiur.Bytecode.Ctrl.match index + (Array.map + (fun x => + match x with + | ⟨(tag, block), property⟩ => (tag, Aiur.Bytecode.rewriteBlock rename block)) + branches.attach) + (Option.map (Aiur.Bytecode.rewriteBlock rename) fallback))) + initial = + StateT.run (Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.Ctrl.match index branches fallback)) initial +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.rewriteCtrl_layout +∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) (ctrl : Aiur.Bytecode.Ctrl) + (initial : Aiur.Concrete.Bytecode.LayoutMState), + Aiur.Concrete.Bytecode.LayoutRenaming rename initial.callRanks → + StateT.run (Aiur.Concrete.Bytecode.ctrlLayout (Aiur.Bytecode.rewriteCtrl rename ctrl)) initial = + StateT.run (Aiur.Concrete.Bytecode.ctrlLayout ctrl) initial +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Bytecode.rewriteBlock_layout +∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) (block : Aiur.Bytecode.Block) + (initial : Aiur.Concrete.Bytecode.LayoutMState), + Aiur.Concrete.Bytecode.LayoutRenaming rename initial.callRanks → + StateT.run (Aiur.Concrete.Bytecode.blockLayout (Aiur.Bytecode.rewriteBlock rename block)) initial = + StateT.run (Aiur.Concrete.Bytecode.blockLayout block) initial +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.functionsComputedLayout_empty +Aiur.Bytecode.FunctionsComputedLayout #[] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.functionsComputedLayout_push +∀ {functions : Array Aiur.Bytecode.Function} {function : Aiur.Bytecode.Function}, + Aiur.Bytecode.FunctionsComputedLayout functions → + function.ComputedLayout → Aiur.Bytecode.FunctionsComputedLayout (functions.push function) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.ComputedLayout.auxiliaries +∀ {function : Aiur.Bytecode.Function}, + function.ComputedLayout → + function.layout.auxiliaries = + (StateT.run (Aiur.Concrete.Bytecode.blockLayout function.body) + (Aiur.Concrete.Bytecode.LayoutMState.new function.layout.inputSize)).snd.functionLayout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.ComputedLayout.reserved +∀ {function : Aiur.Bytecode.Function}, function.ComputedLayout → 7 ≤ function.layout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.ComputedLayout.selectors +∀ {function : Aiur.Bytecode.Function}, + function.ComputedLayout → function.layout.selectors = function.body.controlCounts.leaves +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Function.compile_computedLayout +∀ {layoutMap : Aiur.LayoutMap} {function : Aiur.Concrete.Function} {body : Aiur.Bytecode.Block} + {state : Aiur.Concrete.Bytecode.LayoutMState}, + Aiur.Concrete.Function.compile layoutMap function = Except.ok (body, state) → + ∀ (entry constrained : Bool), + { body := body, layout := state.functionLayout, entry := entry, constrained := constrained }.ComputedLayout +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Concrete.Decls.toBytecode_computedLayout +∀ {decls : Aiur.Concrete.Decls} {program : Aiur.Bytecode.Toplevel} + {names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx}, + decls.toBytecode = Except.ok (program, names) → Aiur.Bytecode.FunctionsComputedLayout program.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.ComputedLayout.rewrite +∀ {function : Aiur.Bytecode.Function}, + function.ComputedLayout → + ∀ (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx), + { body := Aiur.Bytecode.rewriteBlock rename function.body, layout := function.layout, entry := function.entry, + constrained := function.constrained }.ComputedLayout +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.deduplicate_newFunctions_computedLayout +∀ (functions : Array Aiur.Bytecode.Function) (classes : Array Nat) (canonical : Array Bool) + (rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx), + Aiur.Bytecode.FunctionsComputedLayout functions → + Aiur.Bytecode.FunctionsComputedLayout (Aiur.Bytecode.deduplicate_newFunctions functions classes canonical rename) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.deduplicateCandidate_computedLayout +∀ (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.FunctionsComputedLayout program.deduplicateCandidate.fst.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.deduplicate_computedLayout +∀ (program : Aiur.Bytecode.Toplevel), + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.FunctionsComputedLayout program.deduplicate.fst.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_computedLayout +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx), + Aiur.Bytecode.FunctionsComputedLayout raw.functions → + source.componentRanks = false → + Aiur.Bytecode.FunctionsComputedLayout (Aiur.finishCompilation source raw names).bytecode.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.compile_computedLayout +∀ {source : Aiur.Source.Toplevel} {compiled : Aiur.CompiledToplevel}, + source.compile = Except.ok compiled → + source.componentRanks = false → Aiur.Bytecode.FunctionsComputedLayout compiled.bytecode.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.functions_computedLayout +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → Aiur.Bytecode.FunctionsComputedLayout backend.compiled.bytecode.functions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.merged_columnBound +∀ (functions : Array Aiur.Bytecode.Function) (members : Array Aiur.Bytecode.FunIdx), + Aiur.Bytecode.FunctionsComputedLayout functions → + 0 < functions.size → + Aiur.Bytecode.MembersConstrained functions members → + Aiur.Bytecode.MembersColumnBound functions members + (Array.foldl + (fun acc index => if (index == members[0]!) = true then acc else acc.merge functions[index]!.layout) + functions[members[0]!]!.layout members) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.singletonCircuits_columnBound +∀ (program : Aiur.Bytecode.Toplevel) (nameOf : Aiur.Bytecode.FunIdx → String), + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.CircuitsColumnBound program.functions (program.singletonCircuits nameOf) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.CompiledToplevel.groupFunctions_columnBound +∀ {before after : Aiur.CompiledToplevel} {groups : Array (String × Array String)}, + Aiur.Bytecode.FunctionsComputedLayout before.bytecode.functions → + 0 < before.bytecode.functions.size → + Aiur.Bytecode.CircuitsColumnBound before.bytecode.functions before.bytecode.circuits → + before.groupFunctions groups = Except.ok after → + Aiur.Bytecode.CircuitsColumnBound after.bytecode.functions after.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.finishCompilation_columnBound +∀ (source : Aiur.Source.Toplevel) (raw : Aiur.Bytecode.Toplevel) (names : Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx), + Aiur.Bytecode.FunctionsComputedLayout raw.functions → + source.componentRanks = false → + Aiur.Bytecode.CircuitsColumnBound (Aiur.finishCompilation source raw names).bytecode.functions + (Aiur.finishCompilation source raw names).bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Source.Toplevel.compile_columnBound +∀ {source : Aiur.Source.Toplevel} {compiled : Aiur.CompiledToplevel}, + source.compile = Except.ok compiled → + source.componentRanks = false → + Aiur.Bytecode.CircuitsColumnBound compiled.bytecode.functions compiled.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuits_columnBound +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + Aiur.Bytecode.CircuitsColumnBound backend.compiled.bytecode.functions backend.compiled.bytecode.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitMember_layout +∀ {rank : Aiur.NativeAIR.Expr} {column lookup selectorBase base : Nat} {program : Aiur.Bytecode.Toplevel} + {functionIndex : Nat} {member : Aiur.NativeAIR.CircuitEmitter.Member}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + column = base + 7 → + Aiur.NativeAIR.CircuitEmitter.emitMember rank column lookup selectorBase program functionIndex = some member → + member.functionIndex = functionIndex ∧ + program.functions[functionIndex]? = some member.function ∧ + member.selectorBase = selectorBase ∧ member.body.column = base + member.function.layout.auxiliaries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitMembers_layout +∀ {rank : Aiur.NativeAIR.Expr} (column lookup selectorBase base : Nat) (program : Aiur.Bytecode.Toplevel) + (indices : List Nat) {members : List Aiur.NativeAIR.CircuitEmitter.Member}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + column = base + 7 → + Aiur.NativeAIR.CircuitEmitter.emitMembers rank column lookup selectorBase program indices = some members → + List.map Aiur.NativeAIR.CircuitEmitter.Member.functionIndex members = indices ∧ + ∀ (member : Aiur.NativeAIR.CircuitEmitter.Member), + member ∈ members → + program.functions[member.functionIndex]? = some member.function ∧ + member.body.column = base + member.function.layout.auxiliaries ∧ + member.selectorBase + member.function.layout.selectors ≤ + selectorBase + (List.map (fun part => part.function.layout.selectors) members).sum +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitMembers_selectors +∀ {rank : Aiur.NativeAIR.Expr} (column lookup selectorBase base : Nat) (program : Aiur.Bytecode.Toplevel) + (circuit : Aiur.Bytecode.Circuit) {members : List Aiur.NativeAIR.CircuitEmitter.Member}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + column = base + 7 → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + Aiur.NativeAIR.CircuitEmitter.emitMembers rank column lookup selectorBase program circuit.members.toList = + some members → + (List.map (fun member => member.function.layout.selectors) members).sum ≤ circuit.layout.selectors +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitCircuit_readBound +∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.MembersColumnBound program.functions circuit.members circuit.layout → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + Aiur.NativeAIR.CircuitEmitter.emitCircuit program circuit = some emission → + emission.readBound ≤ circuit.layout.width +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCircuit_readBound +∀ {widths : Aiur.NativeAIR.GraphWidths} (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.MembersColumnBound program.functions circuit.members circuit.layout → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + Aiur.NativeAIR.CircuitEmitter.compileCircuit widths program circuit = some compiled → + compiled.emission.readBound ≤ circuit.layout.width +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCircuit_physical_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.MembersColumnBound program.functions circuit.members circuit.layout → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + widths.main = circuit.layout.width → + Aiur.NativeAIR.CircuitEmitter.compileCircuit widths program circuit = some compiled → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + program circuit = + some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuit_readBound +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + ∀ {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.emitCircuit backend.compiled.bytecode circuit = some emission → + emission.readBound ≤ circuit.layout.width +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.compileCircuit_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + ∀ {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + widths.main = circuit.layout.width → + Aiur.NativeAIR.CircuitEmitter.compileCircuit widths backend.compiled.bytecode circuit = some compiled → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + backend.compiled.bytecode circuit = + some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer + compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileExpr_defined +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} + {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (allowStage2 : Bool), + widths.stage2 = 0 ∨ allowStage2 = true → + ∀ (expr : Aiur.NativeAIR.Expr) (nodes : List Aiur.NativeAIR.Node) {value : W}, + Aiur.NativeAIR.Expr.eval ops values expr = some value → + ∃ result, Aiur.NativeAIR.Compiler.compileExpr widths allowStage2 expr nodes = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileExprs_defined +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} + {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (allowStage2 : Bool), + widths.stage2 = 0 ∨ allowStage2 = true → + ∀ (exprs : List Aiur.NativeAIR.Expr) (nodes : List Aiur.NativeAIR.Node) {results : List W}, + Aiur.NativeAIR.Compiler.evalExprs ops values exprs = some results → + ∃ result, Aiur.NativeAIR.Compiler.compileExprs widths allowStage2 exprs nodes = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileLookup_defined +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} + {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + widths.stage2 = 0 → + ∀ (lookup : Aiur.NativeAIR.Compiler.ExprLookup) (nodes : List Aiur.NativeAIR.Node) {value : W × List W}, + Aiur.NativeAIR.Compiler.ExprLookup.eval ops values lookup = some value → + ∃ result, Aiur.NativeAIR.Compiler.compileLookup widths lookup nodes = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileLookups_defined +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} + {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + widths.stage2 = 0 → + ∀ (lookups : List Aiur.NativeAIR.Compiler.ExprLookup) (nodes : List Aiur.NativeAIR.Node) + {valuesRead : List (W × List W)}, + List.mapM (Aiur.NativeAIR.Compiler.ExprLookup.eval ops values) lookups = some valuesRead → + ∃ result, Aiur.NativeAIR.Compiler.compileLookups widths lookups nodes = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.recordZero_defined +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + Function.Injective ops.konst → + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + ∀ {root : Nat}, + buffer[root]? = some (ops.konst 0) → ∃ roots, Aiur.NativeAIR.Compiler.recordZero nodes root = some roots +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileZeros_defined +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + Function.Injective ops.konst → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + widths.stage2 = 0 → + ∀ (exprs : List Aiur.NativeAIR.Expr) {nodes : List Aiur.NativeAIR.Node} {buffer : Array W}, + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer → + Aiur.NativeAIR.Compiler.ExprsVanish ops values exprs → + ∃ result, Aiur.NativeAIR.Compiler.compileZeros widths exprs nodes = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileBase_defined +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.GraphEvalLaws ops → + Function.Injective ops.konst → + ∀ {values : Aiur.NativeAIR.Values W} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + widths.stage2 = 0 → + ∀ (lookups : List Aiur.NativeAIR.Compiler.ExprLookup) (constraints : List Aiur.NativeAIR.Expr) + {valuesRead : List (W × List W)}, + List.mapM (Aiur.NativeAIR.Compiler.ExprLookup.eval ops values) lookups = some valuesRead → + Aiur.NativeAIR.Compiler.ExprsVanish ops values constraints → + ∃ result, Aiur.NativeAIR.Compiler.compileBase widths lookups constraints = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.selectorSum_zero +∀ (values : List Aiur.G), (∀ (value : Aiur.G), value ∈ values → value = 0) → Aiur.AIR.selectorSum values = 0 +AXIOMS [propext] +ROOT Aiur.AIR.emitOp_inactive +∀ {row : Nat → Aiur.G} {rank : Aiur.G} (op : Aiur.Bytecode.Op) {values : Array Aiur.AIR.RowValue} + {emission : Aiur.AIR.OpEmission}, + Aiur.AIR.emitOp row 0 rank op values = some emission → + ∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.emitOps_inactive +∀ {row : Nat → Aiur.G} {rank : Aiur.G} (ops : List Aiur.Bytecode.Op) {values : Array Aiur.AIR.RowValue} {column : Nat} + {emission : Aiur.AIR.OpsEmission}, + Aiur.AIR.emitOps row 0 rank ops values column = some emission → + ∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.BlockEmission.Inactive.prefix +∀ {emission : Aiur.AIR.BlockEmission}, + emission.Inactive → + ∀ (equations : List Aiur.G), + (∀ (equation : Aiur.G), equation ∈ equations → equation = 0) → + (Aiur.AIR.BlockEmission.prefix equations emission).Inactive +AXIOMS [propext] +ROOT Aiur.AIR.BlockEmission.Inactive.afterOps +∀ {emission : Aiur.AIR.BlockEmission}, + emission.Inactive → + ∀ (incoming : Aiur.G) (lookup : Nat) (ops : Aiur.AIR.OpsEmission), + (∀ (equation : Aiur.G), equation ∈ ops.equations → equation = 0) → + (Aiur.AIR.BlockEmission.afterOps incoming lookup ops emission).Inactive +AXIOMS [propext] +ROOT Aiur.AIR.joinBlockEmissions_inactive +∀ (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (emissions : List Aiur.AIR.BlockEmission), + (∀ (emission : Aiur.AIR.BlockEmission), emission ∈ emissions → emission.Inactive) → + (Aiur.AIR.joinBlockEmissions values column lookup emissions).Inactive +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.BlockEmission.Inactive.continued +∀ {branches continuation : Aiur.AIR.BlockEmission}, + branches.Inactive → + continuation.Inactive → + ∀ (equations : List Aiur.G), + (∀ (equation : Aiur.G), equation ∈ equations → equation = 0) → + (branches.continued equations continuation).Inactive +AXIOMS [propext] +ROOT Aiur.Bytecode.branchSelectorFlows_entry_zero +∀ (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block), + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → (Aiur.Bytecode.Block.selectorFlow (fun x => 0) pair.snd).entry = 0) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → (Aiur.Bytecode.Block.selectorFlow (fun x => 0) block).entry = 0) → + (Aiur.AIR.SelectorFlow.join (Aiur.Bytecode.branchSelectorFlows (fun x => 0) branches fallback)).entry = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Ctrl.selectorFlow_entry_zero +∀ (ctrl : Aiur.Bytecode.Ctrl), (Aiur.Bytecode.Ctrl.selectorFlow (fun x => 0) ctrl).entry = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.selectorFlow_entry_zero +∀ (block : Aiur.Bytecode.Block), (Aiur.Bytecode.Block.selectorFlow (fun x => 0) block).entry = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.branchRows_inactive +∀ (row : Nat → Aiur.G) (context : Aiur.AIR.RowContext) (matched : Aiur.G) (values : Array Aiur.AIR.RowValue) + (column lookup : Nat) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block) + {emission : Aiur.AIR.BlockEmission}, + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + ∀ (result : Aiur.AIR.BlockEmission), + Aiur.Bytecode.Block.emitRow row (fun x => 0) context 0 values column lookup pair.snd = some result → + result.Inactive) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → + ∀ (result : Aiur.AIR.BlockEmission), + Aiur.Bytecode.Block.emitRow row (fun x => 0) context 0 values (column + branches.size) lookup block = + some result → + result.Inactive) → + Aiur.Bytecode.branchRows row (fun x => 0) context matched values column lookup branches fallback = some emission → + emission.Inactive +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Ctrl.emitRow_inactive +∀ (row : Nat → Aiur.G) (context : Aiur.AIR.RowContext) (ctrl : Aiur.Bytecode.Ctrl) (values : Array Aiur.AIR.RowValue) + (column lookup : Nat) {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Ctrl.emitRow row (fun x => 0) context 0 values column lookup ctrl = some emission → emission.Inactive +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emitRow_inactive +∀ (row : Nat → Aiur.G) (context : Aiur.AIR.RowContext) (block : Aiur.Bytecode.Block) (values : Array Aiur.AIR.RowValue) + (column lookup : Nat) {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Block.emitRow row (fun x => 0) context 0 values column lookup block = some emission → emission.Inactive +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemberEmission.entry_zero +∀ (member : Aiur.AIR.MemberEmission), Aiur.AIR.MemberEmission.entry (fun x => 0) member = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitMember_zero +∀ {rank : Aiur.G} {column lookup selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} + {functionIndex : Aiur.Bytecode.FunIdx} {member : Aiur.AIR.MemberEmission}, + Aiur.AIR.emitMember (fun x => 0) rank column lookup selectorBase program functionIndex = some member → + member.body.Inactive +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitMembers_zero +∀ {rank : Aiur.G} (column lookup selectorBase : Nat) (program : Aiur.Bytecode.Toplevel) + (indices : List Aiur.Bytecode.FunIdx) {members : List Aiur.AIR.MemberEmission}, + Aiur.AIR.emitMembers (fun x => 0) rank column lookup selectorBase program indices = some members → + ∀ (member : Aiur.AIR.MemberEmission), member ∈ members → member.body.Inactive +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitEmission_zero +∀ (circuit : Aiur.Bytecode.Circuit) (members : List Aiur.AIR.MemberEmission), + (∀ (member : Aiur.AIR.MemberEmission), member ∈ members → member.body.Inactive) → + ∀ (equation : Aiur.G), equation ∈ (Aiur.AIR.circuitEmission (fun x => 0) circuit members).equations → equation = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitRow_zero +∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitRow (fun x => 0) program circuit = some emission → + ∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.zeroValues_fits +∀ (circuit : Aiur.Bytecode.Circuit), + (Aiur.NativeAIR.CircuitEmitter.zeroValues circuit.layout.width).Fits + (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) +AXIOMS [propext] +ROOT Aiur.NativeAIR.CircuitEmitter.zeroValues_read +∀ (width index : Nat), + index < width → + ((Aiur.NativeAIR.CircuitEmitter.zeroValues width).columns Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current)[index]? = + some 0 +AXIOMS [propext] +ROOT Aiur.NativeAIR.CircuitEmitter.emitCircuit_zero_eval +∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.MembersColumnBound program.functions circuit.members circuit.layout → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + Aiur.NativeAIR.CircuitEmitter.emitCircuit program circuit = some emission → + ∃ result, + Aiur.NativeAIR.CircuitEmitter.Emission.eval (Aiur.NativeAIR.CircuitEmitter.zeroValues circuit.layout.width) + emission = + some result ∧ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitCircuit_compiles +∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.MembersColumnBound program.functions circuit.members circuit.layout → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + Aiur.NativeAIR.CircuitEmitter.emitCircuit program circuit = some emission → + ∃ compiled, + Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) program + circuit = + some compiled ∧ + compiled.emission = emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCircuit_defined_iff +∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit), + Aiur.Bytecode.FunctionsComputedLayout program.functions → + Aiur.Bytecode.MembersColumnBound program.functions circuit.members circuit.layout → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + ((Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) program + circuit).isSome = + true ↔ + (Aiur.NativeAIR.CircuitEmitter.emitCircuit program circuit).isSome = true) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.emitCircuit_compiles +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + ∀ {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.emitCircuit backend.compiled.bytecode circuit = some emission → + ∃ compiled, + Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) + backend.compiled.bytecode circuit = + some compiled ∧ + compiled.emission = emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.emittedCircuit_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) → + ∀ {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.emitCircuit backend.compiled.bytecode circuit = some emission → + ∃ compiled result buffer, + Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) + backend.compiled.bytecode circuit = + some compiled ∧ + compiled.emission = emission ∧ + Aiur.Bytecode.Circuit.emitRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD + 0) + backend.compiled.bytecode circuit = + some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer + compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.indicesInScope_spec +∀ (available : Nat) (indices : Array Aiur.Bytecode.ValIdx), + Aiur.Bytecode.indicesInScope available indices = true ↔ + ∀ (index : Aiur.Bytecode.ValIdx), index ∈ indices → index < available +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.wordInScope_spec +∀ (available : Nat) (indices : Array Aiur.Bytecode.ValIdx), + Aiur.Bytecode.wordInScope available indices = true ↔ + indices.size = 4 ∧ Aiur.Bytecode.indicesInScope available indices = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.addScope_eq +∀ {available count next : Nat}, + Aiur.Bytecode.addScope available count = some next → next = available + count ∧ next < 2 ^ 64 +AXIOMS [] +ROOT Aiur.Bytecode.checkEmissionOps_cons +∀ {op : Aiur.Bytecode.Op} {ops : List Aiur.Bytecode.Op} {available next : Nat}, + Aiur.Bytecode.checkEmissionOps (op :: ops) available = some next → + Aiur.Bytecode.Op.emissionInputs available op = true ∧ + ∃ after, + Aiur.Bytecode.addScope available op.outputSize = some after ∧ + Aiur.Bytecode.checkEmissionOps ops after = some next +AXIOMS [propext] +ROOT Aiur.Bytecode.checkEmissionOps_le +∀ {ops : List Aiur.Bytecode.Op} {available next : Nat}, + Aiur.Bytecode.checkEmissionOps ops available = some next → available ≤ next +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.Op.allocation_outputSize +∀ (op : Aiur.Bytecode.Op) (degrees : Array Nat), (Aiur.Bytecode.Op.allocation degrees op).degrees.size = op.outputSize +AXIOMS [propext] +ROOT Aiur.NativeAIR.OpEmitter.list_mapM_defined +∀ {α : Type u_1} {β : Type u_2} {read : α → Option β} (inputs : List α), + (∀ (input : α), input ∈ inputs → ∃ output, read input = some output) → ∃ outputs, List.mapM read inputs = some outputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.array_mapM_defined +∀ {α : Type u_1} {β : Type u_2} {read : α → Option β} (inputs : Array α), + (∀ (input : α), input ∈ inputs → ∃ output, read input = some output) → + ∃ outputs, Array.mapM read inputs = some outputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.select_defined +∀ {rows : Array Aiur.NativeAIR.RowExpr} {indices : Array Nat}, + Aiur.Bytecode.indicesInScope rows.size indices = true → + ∃ outputs, Aiur.NativeAIR.OpEmitter.select rows indices = some outputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.readWord_defined +∀ {rows : Array Aiur.NativeAIR.RowExpr} {indices : Array Nat}, + Aiur.Bytecode.wordInScope rows.size indices = true → + ∃ output, Aiur.NativeAIR.OpEmitter.readWord rows indices = some output +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_defined +∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (op : Aiur.Bytecode.Op) (rows : Array Aiur.NativeAIR.RowExpr), + Aiur.Bytecode.Op.emissionInputs rows.size op = true → + ∃ emission, Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_outputSize +∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → emission.outputs.size = op.outputSize +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOps_defined +∀ (selector rank : Aiur.NativeAIR.Expr) (ops : List Aiur.Bytecode.Op) (rows : Array Aiur.NativeAIR.RowExpr) + (column : Nat) {next : Nat}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.Bytecode.checkEmissionOps ops rows.size = some next → + ∃ emission, + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission ∧ emission.values.size = next +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.emissionChecks_match +∀ (available selectors : Nat) (yieldSize : Option Nat) (index : Aiur.Bytecode.ValIdx) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block), + Aiur.Bytecode.Ctrl.emissionChecks available selectors yieldSize (Aiur.Bytecode.Ctrl.match index branches fallback) = + true ↔ + index < available ∧ + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → Aiur.Bytecode.Block.emissionChecks available selectors yieldSize pair.snd = true) ∧ + ∀ (block : Aiur.Bytecode.Block), + fallback = some block → Aiur.Bytecode.Block.emissionChecks available selectors yieldSize block = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.emissionChecks_matchContinue +∀ (available selectors : Nat) (yieldSize : Option Nat) (index : Aiur.Bytecode.ValIdx) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block) (size aux lookups : Nat) + (continuation : Aiur.Bytecode.Block), + Aiur.Bytecode.Ctrl.emissionChecks available selectors yieldSize + (Aiur.Bytecode.Ctrl.matchContinue index branches fallback size aux lookups continuation) = + true ↔ + index < available ∧ + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → Aiur.Bytecode.Block.emissionChecks available selectors (some size) pair.snd = true) ∧ + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → Aiur.Bytecode.Block.emissionChecks available selectors (some size) block = true) ∧ + ∃ next, + Aiur.Bytecode.addScope available size = some next ∧ + Aiur.Bytecode.Block.emissionChecks next selectors yieldSize continuation = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Block.emissionChecks_parts +∀ {block : Aiur.Bytecode.Block} {available selectors : Nat} {yieldSize : Option Nat}, + Aiur.Bytecode.Block.emissionChecks available selectors yieldSize block = true → + ∃ next, + Aiur.Bytecode.checkEmissionOps block.ops.toList available = some next ∧ + Aiur.Bytecode.Ctrl.emissionChecks next selectors yieldSize block.ctrl = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.validateEmission_function +∀ {program : Aiur.Bytecode.Toplevel}, + program.validateEmission = true → + ∀ {function : Aiur.Bytecode.Function}, + function ∈ program.functions → function.constrained = true → function.emissionChecks = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.ctrlSelector_defined +∀ (selectors : Array Aiur.NativeAIR.Expr) (ctrl : Aiur.Bytecode.Ctrl) {available : Nat} {yieldSize : Option Nat}, + Aiur.Bytecode.Ctrl.emissionChecks available selectors.size yieldSize ctrl = true → + ∃ entry, Aiur.NativeAIR.BlockEmitter.ctrlSelector selectors ctrl = some entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.blockSelector_defined +∀ (selectors : Array Aiur.NativeAIR.Expr) (block : Aiur.Bytecode.Block) {available : Nat} {yieldSize : Option Nat}, + Aiur.Bytecode.Block.emissionChecks available selectors.size yieldSize block = true → + ∃ entry, Aiur.NativeAIR.BlockEmitter.blockSelector selectors block = some entry +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.Emission.YieldShape.prefix +∀ {emission : Aiur.NativeAIR.BlockEmitter.Emission} {size : Option Nat}, + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size emission → + ∀ (equations : List Aiur.NativeAIR.Expr), + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size + (Aiur.NativeAIR.BlockEmitter.Emission.prefix equations emission) +AXIOMS [] +ROOT Aiur.NativeAIR.BlockEmitter.join_yieldShape +∀ (rows : Array Aiur.NativeAIR.RowExpr) (column lookup : Nat) (emissions : List Aiur.NativeAIR.BlockEmitter.Emission) + {size : Option Nat}, + (∀ (emission : Aiur.NativeAIR.BlockEmitter.Emission), + emission ∈ emissions → Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size emission) → + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size (Aiur.NativeAIR.BlockEmitter.join rows column lookup emissions) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.branchRows_defined +∀ (selectors : Array Aiur.NativeAIR.Expr) (context : Aiur.NativeAIR.BlockEmitter.Context) + (matched : Aiur.NativeAIR.RowExpr) (rows : Array Aiur.NativeAIR.RowExpr) (column lookup : Nat) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block) (size : Option Nat), + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + ∃ entry emission, + Aiur.NativeAIR.BlockEmitter.blockSelector selectors pair.snd = some entry ∧ + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows column lookup pair.snd = some emission ∧ + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size emission) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → + ∃ entry emission, + Aiur.NativeAIR.BlockEmitter.blockSelector selectors block = some entry ∧ + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows (column + branches.size) lookup block = + some emission ∧ + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size emission) → + ∃ emission, + Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback = + some emission ∧ + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitCtrl_defined +∀ (selectors : Array Aiur.NativeAIR.Expr) (context : Aiur.NativeAIR.BlockEmitter.Context) + (incoming : Aiur.NativeAIR.Expr) (rows : Array Aiur.NativeAIR.RowExpr) (column lookup : Nat) + (ctrl : Aiur.Bytecode.Ctrl) {size : Option Nat}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + context.inputSize ≤ rows.size → + Aiur.Bytecode.Ctrl.emissionChecks rows.size selectors.size size ctrl = true → + ∃ emission, + Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup ctrl = some emission ∧ + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.BlockEmitter.emitBlock_defined +∀ (selectors : Array Aiur.NativeAIR.Expr) (context : Aiur.NativeAIR.BlockEmitter.Context) + (incoming : Aiur.NativeAIR.Expr) (rows : Array Aiur.NativeAIR.RowExpr) (column lookup : Nat) + (block : Aiur.Bytecode.Block) {size : Option Nat}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + context.inputSize ≤ rows.size → + Aiur.Bytecode.Block.emissionChecks rows.size selectors.size size block = true → + ∃ emission, + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context incoming rows column lookup block = some emission ∧ + Aiur.NativeAIR.BlockEmitter.Emission.YieldShape size emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitMember_defined +∀ (rank : Aiur.NativeAIR.Expr) (column lookup selectorBase : Nat) (program : Aiur.Bytecode.Toplevel) (index : Nat) + {function : Aiur.Bytecode.Function}, + program.functions[index]? = some function → + function.emissionChecks = true → + ∃ member, Aiur.NativeAIR.CircuitEmitter.emitMember rank column lookup selectorBase program index = some member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitMembers_defined +∀ (rank : Aiur.NativeAIR.Expr) (column lookup selectorBase : Nat) (program : Aiur.Bytecode.Toplevel) + (indices : List Nat), + (∀ (index : Nat), + index ∈ indices → ∃ function, program.functions[index]? = some function ∧ function.emissionChecks = true) → + ∃ members, Aiur.NativeAIR.CircuitEmitter.emitMembers rank column lookup selectorBase program indices = some members +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitCircuit_defined +∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit), + program.validateEmission = true → + Aiur.Bytecode.MembersConstrained program.functions circuit.members → + ∃ emission, Aiur.NativeAIR.CircuitEmitter.emitCircuit program circuit = some emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuit_emits +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + ∃ emission, Aiur.NativeAIR.CircuitEmitter.emitCircuit backend.compiled.bytecode circuit = some emission +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuit_compiles +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + ∃ compiled, + Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) + backend.compiled.bytecode circuit = + some compiled +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.circuit_graph_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + selection.source.componentRanks = false → + ∀ {circuit : Aiur.Bytecode.Circuit}, + circuit ∈ backend.compiled.bytecode.circuits → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) → + ∃ compiled result buffer, + Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit) + backend.compiled.bytecode circuit = + some compiled ∧ + Aiur.Bytecode.Circuit.emitRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + backend.compiled.bytecode circuit = + some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.Reads.pure +∀ {α : Type} (value : α), Aiur.NativeAIR.KeyCodec.Reads (pure value) [] value +AXIOMS [] +ROOT Aiur.NativeAIR.KeyCodec.Reads.bind +∀ {α β : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {next : α → Aiur.NativeAIR.KeyCodec.Reader β} + {left right : List UInt8} {middle : α} {value : β}, + Aiur.NativeAIR.KeyCodec.Reads read left middle → + Aiur.NativeAIR.KeyCodec.Reads (next middle) right value → + Aiur.NativeAIR.KeyCodec.Reads (read >>= next) (left ++ right) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.Reads.map +∀ {α β : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {bytes : List UInt8} {value : α}, + Aiur.NativeAIR.KeyCodec.Reads read bytes value → + ∀ (f : α → β), Aiur.NativeAIR.KeyCodec.Reads (f <$> read) bytes (f value) +AXIOMS [] +ROOT Aiur.NativeAIR.KeyCodec.Reads.result +∀ {α β : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {bytes : List UInt8} {value : α}, + Aiur.NativeAIR.KeyCodec.Reads read bytes value → + ∀ (f : α → β), + Aiur.NativeAIR.KeyCodec.Reads + (do + let value ← read + pure (f value)) + bytes (f value) +AXIOMS [] +ROOT Aiur.NativeAIR.KeyCodec.readByte_reads +∀ (byte : UInt8), Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readByte [byte] byte +AXIOMS [] +ROOT Aiur.NativeAIR.KeyCodec.Reads.byte +∀ {α : Type} {next : UInt8 → Aiur.NativeAIR.KeyCodec.Reader α} {byte : UInt8} {bytes : List UInt8} {value : α}, + Aiur.NativeAIR.KeyCodec.Reads (next byte) bytes value → + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.KeyCodec.readByte >>= next) (byte :: bytes) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.encodeNat_length +∀ (count value : Nat), (Aiur.NativeAIR.KeyCodec.encodeNat count value).length = count +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readNat_reads +∀ (count value : Nat), + value < 256 ^ count → + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.KeyCodec.readNat count) + (Aiur.NativeAIR.KeyCodec.encodeNat count value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readMany_reads +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} (encode : α → List UInt8) (values : List α), + (∀ (value : α), value ∈ values → Aiur.NativeAIR.KeyCodec.Reads read (encode value) value) → + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.KeyCodec.readMany read values.length) (List.flatMap encode values) + values +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readVector_reads +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} (encode : α → List UInt8) (values : List α), + values.length < 65536 → + (∀ (value : α), value ∈ values → Aiur.NativeAIR.KeyCodec.Reads read (encode value) value) → + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.KeyCodec.readVector read) + (Aiur.NativeAIR.KeyCodec.encodeVector encode values) values +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readNode_reads +∀ (node : Aiur.NativeAIR.Node), + Aiur.NativeAIR.KeyCodec.NodeWireFits node → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readNode (Aiur.NativeAIR.KeyCodec.encodeNode node) node +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readLookup_reads +∀ (lookup : Aiur.NativeAIR.Lookup), + Aiur.NativeAIR.KeyCodec.LookupWireFits lookup → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readLookup (Aiur.NativeAIR.KeyCodec.encodeLookup lookup) + lookup +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readCircuitData_reads +∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), + Aiur.NativeAIR.KeyCodec.CircuitWireFits circuit → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readCircuitData + (Aiur.NativeAIR.KeyCodec.encodeCircuit circuit) circuit +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readCircuit_reads +∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), + Aiur.NativeAIR.KeyCodec.CircuitWireFits circuit → + circuit.valid = true → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readCircuit (Aiur.NativeAIR.KeyCodec.encodeCircuit circuit) + circuit +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readParameters_reads +∀ (parameters : Aiur.NativeAIR.KeyCodec.Parameters), + Aiur.NativeAIR.KeyCodec.ParametersWireFits parameters → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readParameters + (Aiur.NativeAIR.KeyCodec.encodeParameters parameters) parameters +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readCommitment_reads +∀ (commitment : Option Aiur.NativeAIR.KeyCodec.MerkleCap), + Aiur.NativeAIR.KeyCodec.CommitmentWireFits commitment → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readCommitment + (Aiur.NativeAIR.KeyCodec.encodeCommitment commitment) commitment +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readIndex_reads +∀ (index : Option Nat), + Aiur.NativeAIR.KeyCodec.IndexWireFits index → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readIndex (Aiur.NativeAIR.KeyCodec.encodeIndex index) index +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readKey_reads +∀ (key : Aiur.NativeAIR.KeyCodec.Key), + Aiur.NativeAIR.KeyCodec.KeyWireFits key → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ key.circuits → circuit.valid = true) → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.KeyCodec.readKey (Aiur.NativeAIR.KeyCodec.encodeKey key) key +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decode_encode +∀ (key : Aiur.NativeAIR.KeyCodec.Key), + Aiur.NativeAIR.KeyCodec.KeyWireFits key → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ key.circuits → circuit.valid = true) → + Aiur.NativeAIR.KeyCodec.decode (Aiur.NativeAIR.KeyCodec.encode key) = some key +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decodeCanonical_success +∀ {bytes : ByteArray} {key : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.decodeCanonical bytes = some key → + Aiur.NativeAIR.KeyCodec.decode bytes = some key ∧ Aiur.NativeAIR.KeyCodec.encode key = bytes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decodeCanonical_encode +∀ (key : Aiur.NativeAIR.KeyCodec.Key), + Aiur.NativeAIR.KeyCodec.KeyWireFits key → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ key.circuits → circuit.valid = true) → + Aiur.NativeAIR.KeyCodec.decodeCanonical (Aiur.NativeAIR.KeyCodec.encode key) = some key +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.canonical_bytes_unique +∀ {first second : ByteArray} {key : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.decodeCanonical first = some key → + Aiur.NativeAIR.KeyCodec.decodeCanonical second = some key → first = second +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.encode_injective +∀ {first second : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.KeyWireFits first → + Aiur.NativeAIR.KeyCodec.KeyWireFits second → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ first.circuits → circuit.valid = true) → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ second.circuits → circuit.valid = true) → + Aiur.NativeAIR.KeyCodec.encode first = Aiur.NativeAIR.KeyCodec.encode second → first = second +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.Returns.pure +∀ {α : Type} {value : α} {property : α → Prop}, property value → Aiur.NativeAIR.KeyCodec.Returns (pure value) property +AXIOMS [] +ROOT Aiur.NativeAIR.KeyCodec.Returns.failure +∀ {α : Type} (property : α → Prop), Aiur.NativeAIR.KeyCodec.Returns failure property +AXIOMS [] +ROOT Aiur.NativeAIR.KeyCodec.Returns.bind +∀ {α β : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {next : α → Aiur.NativeAIR.KeyCodec.Reader β} {left : α → Prop} + {right : β → Prop}, + Aiur.NativeAIR.KeyCodec.Returns read left → + (∀ (value : α), left value → Aiur.NativeAIR.KeyCodec.Returns (next value) right) → + Aiur.NativeAIR.KeyCodec.Returns (read >>= next) right +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.Returns.bind_any +∀ {α β : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {next : α → Aiur.NativeAIR.KeyCodec.Reader β} + {property : β → Prop}, + (∀ (value : α), Aiur.NativeAIR.KeyCodec.Returns (next value) property) → + Aiur.NativeAIR.KeyCodec.Returns (read >>= next) property +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.Returns.weaken +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {left right : α → Prop}, + Aiur.NativeAIR.KeyCodec.Returns read left → + (∀ (value : α), left value → right value) → Aiur.NativeAIR.KeyCodec.Returns read right +AXIOMS [] +ROOT Aiur.NativeAIR.KeyCodec.Returns.result +∀ {α β : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {left : α → Prop} {right : β → Prop}, + Aiur.NativeAIR.KeyCodec.Returns read left → + ∀ (f : α → β), + (∀ (value : α), left value → right (f value)) → + Aiur.NativeAIR.KeyCodec.Returns + (do + let value ← read + pure (f value)) + right +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readMany_returns +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {property : α → Prop}, + Aiur.NativeAIR.KeyCodec.Returns read property → + ∀ (count : Nat), + Aiur.NativeAIR.KeyCodec.Returns (Aiur.NativeAIR.KeyCodec.readMany read count) fun values => + values.length = count ∧ ∀ (value : α), value ∈ values → property value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readVector_returns +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {property : α → Prop}, + Aiur.NativeAIR.KeyCodec.Returns read property → + Aiur.NativeAIR.KeyCodec.Returns (Aiur.NativeAIR.KeyCodec.readVector read) fun values => + ∀ (value : α), value ∈ values → property value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readCircuit_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.KeyCodec.readCircuit fun circuit => circuit.valid = true +AXIOMS [propext] +ROOT Aiur.NativeAIR.KeyCodec.readCommitment_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.KeyCodec.readCommitment Aiur.NativeAIR.KeyCodec.CommitmentValid +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readKey_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.KeyCodec.readKey fun key => + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ key.circuits → circuit.valid = true) ∧ + key.preprocessedIndices.length = key.circuits.length +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decode_success +∀ {bytes : ByteArray} {key : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.decode bytes = some key → Aiur.NativeAIR.KeyCodec.readKey bytes.data.toList = some (key, []) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decode_valid +∀ {bytes : ByteArray} {key : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.decode bytes = some key → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ key.circuits → circuit.valid = true) ∧ + key.preprocessedIndices.length = key.circuits.length +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.readKey_commitment +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.KeyCodec.readKey fun key => + Aiur.NativeAIR.KeyCodec.CommitmentValid key.preprocessedCommitment +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decode_commitment +∀ {bytes : ByteArray} {key : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.decode bytes = some key → Aiur.NativeAIR.KeyCodec.CommitmentValid key.preprocessedCommitment +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.Circuit.valid_graph +∀ {circuit : Aiur.NativeAIR.KeyCodec.Circuit}, + circuit.valid = true → + 1 ≤ circuit.lookupGroupSize ∧ + circuit.lookupGroupSize ≤ 8 ∧ + Aiur.NativeAIR.Graph.Valid circuit.widths circuit.graph ∧ + circuit.computedDegree = some circuit.maxConstraintDegree +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decoded_graph_sweeps +∀ {W : Type u_1} {bytes : ByteArray} {key : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.decode bytes = some key → + ∀ {circuit : Aiur.NativeAIR.KeyCodec.Circuit}, + circuit ∈ key.circuits → + ∀ (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W), + values.Fits circuit.widths → + ∃ buffer, circuit.graph.sweep ops values = some buffer ∧ buffer.size = circuit.graph.nodes.length +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.KeyCodec.decode_encoded_suffix +∀ (key : Aiur.NativeAIR.KeyCodec.Key), + Aiur.NativeAIR.KeyCodec.KeyWireFits key → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), circuit ∈ key.circuits → circuit.valid = true) → + ∀ (rest : List UInt8), + Aiur.NativeAIR.KeyCodec.decode (Aiur.NativeAIR.KeyCodec.encodeKey key ++ rest).toByteArray = + if rest = [] then some key else none +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.key_decodes +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + Aiur.NativeAIR.KeyCodec.decode selection.key = some backend.keyData +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.native_key_decodes +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + Aiur.NativeAIR.KeyCodec.decodeCanonical backend.system.vkBytes = some backend.keyData +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.native_key_encoding +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + Aiur.NativeAIR.KeyCodec.encode backend.keyData = backend.system.vkBytes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.key_commitment +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + Aiur.NativeAIR.KeyCodec.CommitmentValid backend.keyData.preprocessedCommitment +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.key_graph_valid +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + {circuit : Aiur.NativeAIR.KeyCodec.Circuit}, + circuit ∈ backend.keyData.circuits → Aiur.NativeAIR.Graph.Valid circuit.widths circuit.graph +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.key_graph_reflects +∀ {W : Type u_1} {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection) + {circuit : Aiur.NativeAIR.KeyCodec.Circuit}, + circuit ∈ backend.keyData.circuits → + ∀ (ops : Aiur.NativeAIR.EvalOps W) (values : Aiur.NativeAIR.Values W), + values.Fits circuit.widths → + ∃ trees full lookupValues, + circuit.graph.unfold = some trees ∧ + circuit.graph.sweep ops values = some full ∧ + circuit.graph.sweepLookupPrefix ops values = some lookupValues ∧ + trees.size = circuit.graph.nodes.length ∧ + full.size = circuit.graph.nodes.length ∧ + lookupValues.size = circuit.graph.lookupPrefix ∧ + Aiur.NativeAIR.Reflects ops values trees full ∧ + Aiur.NativeAIR.readNodes full circuit.graph.zeros = + Aiur.NativeAIR.evalRoots ops values trees circuit.graph.zeros ∧ + ∀ (lookup : Aiur.NativeAIR.Lookup), + lookup ∈ circuit.graph.lookups → + Aiur.NativeAIR.readLookup lookupValues lookup = Aiur.NativeAIR.readLookup full lookup ∧ + Aiur.NativeAIR.readLookup lookupValues lookup = + Aiur.NativeAIR.evalLookup ops values trees lookup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.circuits_bound +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), + Aiur.NativeAIR.CompiledKey.circuits backend.keyData.parameters.logBlowup backend.compiled.bytecode = + some backend.keyData.circuits +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.preprocessed_indices +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), + backend.keyData.preprocessedIndices = Aiur.NativeAIR.CompiledKey.preprocessedIndices backend.compiled.bytecode +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.verifyCompiled_success +∀ {selection : Aiur.BoundVerifier.Selection} {backend : Aiur.BoundVerifier.CompiledBackend selection} + {input : Array Aiur.G} {bytes : ByteArray}, + Aiur.BoundVerifier.verifyCompiled backend input bytes = Except.ok () → + input.size = selection.inputSize ∧ + ∃ proof, + Aiur.Proof.ofBytesChecked bytes = Except.ok proof ∧ + backend.system.verify (Aiur.buildClaim selection.function input selection.success) proof = Except.ok () +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileExpr_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ (allowStage2 : Bool) (expr : Aiur.NativeAIR.Expr) {nodes : List Aiur.NativeAIR.Node} + {result : List Aiur.NativeAIR.Node × Nat}, + Aiur.NativeAIR.Compiler.compileExpr small allowStage2 expr nodes = some result → + Aiur.NativeAIR.Compiler.compileExpr large allowStage2 expr nodes = some result +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.compileExprs_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ (allowStage2 : Bool) (exprs : List Aiur.NativeAIR.Expr) {nodes : List Aiur.NativeAIR.Node} + {result : List Aiur.NativeAIR.Node × List Nat}, + Aiur.NativeAIR.Compiler.compileExprs small allowStage2 exprs nodes = some result → + Aiur.NativeAIR.Compiler.compileExprs large allowStage2 exprs nodes = some result +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.compileLookup_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ (lookup : Aiur.NativeAIR.Compiler.ExprLookup) {nodes : List Aiur.NativeAIR.Node} + {result : List Aiur.NativeAIR.Node × Aiur.NativeAIR.Lookup}, + Aiur.NativeAIR.Compiler.compileLookup small lookup nodes = some result → + Aiur.NativeAIR.Compiler.compileLookup large lookup nodes = some result +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.compileLookups_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ (lookups : List Aiur.NativeAIR.Compiler.ExprLookup) {nodes : List Aiur.NativeAIR.Node} + {result : List Aiur.NativeAIR.Node × List Aiur.NativeAIR.Lookup}, + Aiur.NativeAIR.Compiler.compileLookups small lookups nodes = some result → + Aiur.NativeAIR.Compiler.compileLookups large lookups nodes = some result +AXIOMS [propext] +ROOT Aiur.NativeAIR.Compiler.compileZeros_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ (exprs : List Aiur.NativeAIR.Expr) {nodes : List Aiur.NativeAIR.Node} + {result : List Aiur.NativeAIR.Node × List Nat}, + Aiur.NativeAIR.Compiler.compileZeros small exprs nodes = some result → + Aiur.NativeAIR.Compiler.compileZeros large exprs nodes = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Compiler.compileBase_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ (lookups : List Aiur.NativeAIR.Compiler.ExprLookup) (constraints : List Aiur.NativeAIR.Expr) + {result : Aiur.NativeAIR.Compiler.BaseCompilation}, + Aiur.NativeAIR.Compiler.compileBase small lookups constraints = some result → + Aiur.NativeAIR.Compiler.compileBase large lookups constraints = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCircuit_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileCircuit small program circuit = some compiled → + Aiur.NativeAIR.CircuitEmitter.compileCircuit large program circuit = some compiled +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.circuitWidths_le +∀ {circuit : Aiur.Bytecode.Circuit} {widths : Aiur.NativeAIR.GraphWidths}, + circuit.layout.width ≤ widths.main → (Aiur.NativeAIR.CircuitEmitter.circuitWidths circuit).Le widths +AXIOMS [propext] +ROOT Aiur.NativeAIR.CompiledKey.column_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (source : Aiur.NativeAIR.Source) (offset : Aiur.NativeAIR.RowOffset) {width : Nat}, + width ≤ widths.width source → + ∀ (index : Fin width), + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values + (Aiur.NativeAIR.Expr.var { source := source, offset := offset, index := ↑index }) = + some (Aiur.NativeAIR.CompiledKey.columns values source offset width index) +AXIOMS [propext] +ROOT Aiur.NativeAIR.CompiledKey.memoryEquations_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (width : Nat), + 3 + width ≤ widths.main → + List.mapM (Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values) + Aiur.NativeAIR.CompiledKey.memoryEquations = + some + (Aiur.AIR.memoryColumnEquations width + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current + (3 + width)) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.next + (3 + width)) + values.isTransition) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.memoryLookup_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ (width : Nat), + 3 + width ≤ widths.main → + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values + (Aiur.NativeAIR.CompiledKey.memoryLookup width) = + some + (Aiur.AIR.memoryColumnLookup width + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current + (3 + width))) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte1Lookup_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + 3 ≤ widths.main → + 11 ≤ widths.preprocessed → + ∀ (kind : Aiur.AIR.Byte1Kind), + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values + (Aiur.NativeAIR.CompiledKey.byte1Lookup kind) = + some + (Aiur.AIR.byte1ColumnLookup kind + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.preprocessed + Aiur.NativeAIR.RowOffset.current 11) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current + 3)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte2Lookup_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + 10 ≤ widths.main → + 14 ≤ widths.preprocessed → + ∀ (kind : Aiur.AIR.Byte2Kind), + Aiur.NativeAIR.Compiler.ExprLookup.eval Aiur.NativeAIR.goldilocksOps values + (Aiur.NativeAIR.CompiledKey.byte2Lookup kind) = + some + (Aiur.AIR.byte2ColumnLookup kind + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.preprocessed + Aiur.NativeAIR.RowOffset.current 14) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current + 10)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuit_success +∀ {logBlowup mainWidth preprocessedWidth preprocessedHeight groupSize : Nat} + {base : Aiur.NativeAIR.Compiler.BaseCompilation} {result : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuit logBlowup mainWidth preprocessedWidth preprocessedHeight groupSize base = + some result → + result.graph = base.graph ∧ + result.mainWidth = mainWidth ∧ + result.preprocessedWidth = preprocessedWidth ∧ + result.preprocessedHeight = preprocessedHeight ∧ result.valid = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.functionCircuit_success +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {source : Aiur.Bytecode.Circuit} + {result : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some result → + ∃ compiled, + Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths source) program source = + some compiled ∧ + result.graph = compiled.base.graph ∧ + result.mainWidth = source.layout.width ∧ + result.preprocessedWidth = 0 ∧ result.preprocessedHeight = 0 ∧ result.valid = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.memoryCircuit_success +∀ {logBlowup width : Nat} {result : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup width = some result → + ∃ base, + Aiur.NativeAIR.Compiler.compileBase { preprocessed := 0, main := 3 + width, stage2 := 0, publics := 0 } + [Aiur.NativeAIR.CompiledKey.memoryLookup width] Aiur.NativeAIR.CompiledKey.memoryEquations = + some base ∧ + result.graph = base.graph ∧ + result.mainWidth = 3 + width ∧ + result.preprocessedWidth = 0 ∧ result.preprocessedHeight = 0 ∧ result.valid = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte1Circuit_success +∀ {logBlowup : Nat} {result : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte1Circuit logBlowup = some result → + ∃ base, + Aiur.NativeAIR.Compiler.compileBase { preprocessed := 11, main := 3, stage2 := 0, publics := 0 } + (List.map Aiur.NativeAIR.CompiledKey.byte1Lookup Aiur.AIR.Byte1Kind.all) [] = + some base ∧ + result.graph = base.graph ∧ + result.mainWidth = 3 ∧ result.preprocessedWidth = 11 ∧ result.preprocessedHeight = 256 ∧ result.valid = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte2Circuit_success +∀ {logBlowup : Nat} {result : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte2Circuit logBlowup = some result → + ∃ base, + Aiur.NativeAIR.Compiler.compileBase { preprocessed := 14, main := 10, stage2 := 0, publics := 0 } + (List.map Aiur.NativeAIR.CompiledKey.byte2Lookup Aiur.AIR.Byte2Kind.all) [] = + some base ∧ + result.graph = base.graph ∧ + result.mainWidth = 10 ∧ + result.preprocessedWidth = 14 ∧ result.preprocessedHeight = 65536 ∧ result.valid = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuits_parts +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {result : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some result → + ∃ functions memories byte1 byte2, + List.mapM (Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program) program.circuits.toList = + some functions ∧ + List.mapM (Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup) program.memorySizes.toList = some memories ∧ + Aiur.NativeAIR.CompiledKey.byte1Circuit logBlowup = some byte1 ∧ + Aiur.NativeAIR.CompiledKey.byte2Circuit logBlowup = some byte2 ∧ + result = functions ++ memories ++ [byte1, byte2] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuits_length +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {result : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some result → + result.length = program.circuits.size + program.memorySizes.size + 2 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuits_function +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {result : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some result → + ∀ {index : Nat} {source : Aiur.Bytecode.Circuit} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + program.circuits[index]? = some source → + result[index]? = some artifact → + Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some artifact +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuits_memory +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {result : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some result → + ∀ {index width : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + program.memorySizes[index]? = some width → + result[program.circuits.size + index]? = some artifact → + Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup width = some artifact +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuits_bytes +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {result : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some result → + ∃ byte1 byte2, + Aiur.NativeAIR.CompiledKey.byte1Circuit logBlowup = some byte1 ∧ + Aiur.NativeAIR.CompiledKey.byte2Circuit logBlowup = some byte2 ∧ + result[program.circuits.size + program.memorySizes.size]? = some byte1 ∧ + result[program.circuits.size + program.memorySizes.size + 1]? = some byte2 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.memoryCircuit_reflects +∀ {logBlowup width : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup width = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ buffer, + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + ∀ (equation : Aiur.G), + equation ∈ + Aiur.AIR.memoryColumnEquations width + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current (3 + width)) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.next (3 + width)) + values.isTransition → + equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some + [Aiur.AIR.memoryColumnLookup width + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current (3 + width))] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte1Circuit_reflects +∀ {logBlowup : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte1Circuit logBlowup = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ buffer, + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some + (List.map + (fun kind => + Aiur.AIR.byte1ColumnLookup kind + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.preprocessed + Aiur.NativeAIR.RowOffset.current 11) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current 3)) + Aiur.AIR.Byte1Kind.all) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte2Circuit_reflects +∀ {logBlowup : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte2Circuit logBlowup = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ buffer, + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some + (List.map + (fun kind => + Aiur.AIR.byte2ColumnLookup kind + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.preprocessed + Aiur.NativeAIR.RowOffset.current 14) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current 10)) + Aiur.AIR.Byte2Kind.all) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.circuit_count +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), + backend.keyData.circuits.length = + backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size + 2 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.function_graph_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), + selection.source.componentRanks = false → + ∀ {index : Nat} {source : Aiur.Bytecode.Circuit} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + backend.compiled.bytecode.circuits[index]? = some source → + backend.keyData.circuits[index]? = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + backend.compiled.bytecode source = + some result ∧ + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.memory_graph_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {index width : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + backend.compiled.bytecode.memorySizes[index]? = some width → + backend.keyData.circuits[backend.compiled.bytecode.circuits.size + index]? = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ buffer, + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + ∀ (equation : Aiur.G), + equation ∈ + Aiur.AIR.memoryColumnEquations width + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current (3 + width)) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.next (3 + width)) + values.isTransition → + equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some + [Aiur.AIR.memoryColumnLookup width + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current (3 + width))] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.byte_graphs +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), + ∃ byte1 byte2, + Aiur.NativeAIR.CompiledKey.byte1Circuit backend.keyData.parameters.logBlowup = some byte1 ∧ + Aiur.NativeAIR.CompiledKey.byte2Circuit backend.keyData.parameters.logBlowup = some byte2 ∧ + backend.keyData.circuits[backend.compiled.bytecode.circuits.size + + backend.compiled.bytecode.memorySizes.size]? = + some byte1 ∧ + backend.keyData.circuits[backend.compiled.bytecode.circuits.size + + backend.compiled.bytecode.memorySizes.size + + 1]? = + some byte2 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.byte1_graph_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + backend.keyData.circuits[backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size]? = + some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ buffer, + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some + (List.map + (fun kind => + Aiur.AIR.byte1ColumnLookup kind + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.preprocessed + Aiur.NativeAIR.RowOffset.current 11) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current 3)) + Aiur.AIR.Byte1Kind.all) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.byte2_graph_reflects +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + backend.keyData.circuits[backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size + 1]? = + some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ buffer, + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some + (List.map + (fun kind => + Aiur.AIR.byte2ColumnLookup kind + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.preprocessed + Aiur.NativeAIR.RowOffset.current 14) + (Aiur.NativeAIR.CompiledKey.columns values Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current 10)) + Aiur.AIR.Byte2Kind.all) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.verifyShaped_success +∀ {selection : Aiur.BoundVerifier.Selection} {backend : Aiur.BoundVerifier.CompiledBackend selection} + {input : Array Aiur.G} {bytes : ByteArray}, + Aiur.BoundVerifier.verifyShaped backend input bytes = Except.ok () → + ∃ checked, + Aiur.BoundVerifier.readProof backend.keyData bytes = Except.ok checked ∧ + Aiur.BoundVerifier.verifyCompiled backend input bytes = Except.ok () +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readVector_reads +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} (encode : α → List UInt8) (values : List α), + values.length < 256 ^ 8 → + (∀ (value : α), value ∈ values → Aiur.NativeAIR.KeyCodec.Reads read (encode value) value) → + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.ProofCodec.readVector read) + (Aiur.NativeAIR.ProofCodec.encodeVector encode values) values +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readOption_reads +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} (encode : α → List UInt8) (value : Option α), + (∀ (entry : α), value = some entry → Aiur.NativeAIR.KeyCodec.Reads read (encode entry) entry) → + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.ProofCodec.readOption read) + (Aiur.NativeAIR.ProofCodec.encodeOption encode value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readBool_reads +∀ (value : Bool), + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readBool (Aiur.NativeAIR.ProofCodec.encodeBool value) value +AXIOMS [] +ROOT Aiur.NativeAIR.ProofCodec.readField_reads +∀ (value : Aiur.G), + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readField (Aiur.NativeAIR.ProofCodec.encodeField value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readExtension_reads +∀ (value : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readExtension + (Aiur.NativeAIR.ProofCodec.encodeExtension value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readCap_reads +∀ (cap : Aiur.NativeAIR.ProofCodec.Cap), + Aiur.NativeAIR.ProofCodec.CapFits cap → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readCap (Aiur.NativeAIR.ProofCodec.encodeCap cap) cap +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readOpenings_reads +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} (encode : α → List UInt8), + (∀ (value : α), Aiur.NativeAIR.KeyCodec.Reads read (encode value) value) → + ∀ (values : Aiur.NativeAIR.ProofCodec.Openings α), + Aiur.NativeAIR.ProofCodec.OpeningsFits values → + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.ProofCodec.readOpenings read) + (Aiur.NativeAIR.ProofCodec.encodeOpenings encode values) values +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readCommitments_reads +∀ (value : Aiur.NativeAIR.ProofCodec.Commitments), + Aiur.NativeAIR.ProofCodec.CommitmentsFits value → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readCommitments + (Aiur.NativeAIR.ProofCodec.encodeCommitments value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readBatchOpening_reads +∀ (value : Aiur.NativeAIR.ProofCodec.BatchOpening), + Aiur.NativeAIR.ProofCodec.BatchOpeningFits value → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readBatchOpening + (Aiur.NativeAIR.ProofCodec.encodeBatchOpening value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readCommitStep_reads +∀ (value : Aiur.NativeAIR.ProofCodec.CommitStep), + Aiur.NativeAIR.ProofCodec.CommitStepFits value → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readCommitStep + (Aiur.NativeAIR.ProofCodec.encodeCommitStep value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readFri_reads +∀ (value : Aiur.NativeAIR.ProofCodec.Fri), + Aiur.NativeAIR.ProofCodec.FriFits value → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readFri (Aiur.NativeAIR.ProofCodec.encodeFri value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readData_reads +∀ (value : Aiur.NativeAIR.ProofCodec.Data), + Aiur.NativeAIR.ProofCodec.DataFits value → + Aiur.NativeAIR.KeyCodec.Reads Aiur.NativeAIR.ProofCodec.readData (Aiur.NativeAIR.ProofCodec.encodeData value) value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.decode_encode +∀ (value : Aiur.NativeAIR.ProofCodec.Data), + Aiur.NativeAIR.ProofCodec.DataFits value → + Aiur.NativeAIR.ProofCodec.decode (Aiur.NativeAIR.ProofCodec.encode value) = some value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.decode_success +∀ {bytes : ByteArray} {value : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.ProofCodec.decode bytes = some value → + Aiur.NativeAIR.ProofCodec.readData bytes.data.toList = some (value, []) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.decodeCanonical_success +∀ {bytes : ByteArray} {value : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.ProofCodec.decodeCanonical bytes = some value → + Aiur.NativeAIR.ProofCodec.decode bytes = some value ∧ Aiur.NativeAIR.ProofCodec.encode value = bytes +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.decodeCanonical_encode +∀ (value : Aiur.NativeAIR.ProofCodec.Data), + Aiur.NativeAIR.ProofCodec.DataFits value → + Aiur.NativeAIR.ProofCodec.decodeCanonical (Aiur.NativeAIR.ProofCodec.encode value) = some value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.canonical_bytes_unique +∀ {first second : ByteArray} {value : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.ProofCodec.decodeCanonical first = some value → + Aiur.NativeAIR.ProofCodec.decodeCanonical second = some value → first = second +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.encode_injective +∀ {first second : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.ProofCodec.DataFits first → + Aiur.NativeAIR.ProofCodec.DataFits second → + Aiur.NativeAIR.ProofCodec.encode first = Aiur.NativeAIR.ProofCodec.encode second → first = second +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.decode_append_rejected +∀ (value : Aiur.NativeAIR.ProofCodec.Data), + Aiur.NativeAIR.ProofCodec.DataFits value → + ∀ (suffix : List UInt8), + suffix ≠ [] → + Aiur.NativeAIR.ProofCodec.decode (Aiur.NativeAIR.ProofCodec.encodeData value ++ suffix).toByteArray = none +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readNat_returns +∀ (count : Nat), + Aiur.NativeAIR.KeyCodec.Returns (Aiur.NativeAIR.KeyCodec.readNat count) fun value => value < 256 ^ count +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readVector_returns +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {property : α → Prop}, + Aiur.NativeAIR.KeyCodec.Returns read property → + Aiur.NativeAIR.KeyCodec.Returns (Aiur.NativeAIR.ProofCodec.readVector read) + (Aiur.NativeAIR.ProofCodec.VectorFits property) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readOption_returns +∀ {α : Type} {read : Aiur.NativeAIR.KeyCodec.Reader α} {property : α → Prop}, + Aiur.NativeAIR.KeyCodec.Returns read property → + Aiur.NativeAIR.KeyCodec.Returns (Aiur.NativeAIR.ProofCodec.readOption read) fun result => + ∀ (value : α), result = some value → property value +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.readCap_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.ProofCodec.readCap Aiur.NativeAIR.ProofCodec.CapFits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readOpenings_returns +∀ {α : Type} (read : Aiur.NativeAIR.KeyCodec.Reader α), + Aiur.NativeAIR.KeyCodec.Returns (Aiur.NativeAIR.ProofCodec.readOpenings read) Aiur.NativeAIR.ProofCodec.OpeningsFits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readCommitments_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.ProofCodec.readCommitments Aiur.NativeAIR.ProofCodec.CommitmentsFits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readBatchOpening_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.ProofCodec.readBatchOpening Aiur.NativeAIR.ProofCodec.BatchOpeningFits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readCommitStep_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.ProofCodec.readCommitStep Aiur.NativeAIR.ProofCodec.CommitStepFits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readFri_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.ProofCodec.readFri Aiur.NativeAIR.ProofCodec.FriFits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.readData_returns +Aiur.NativeAIR.KeyCodec.Returns Aiur.NativeAIR.ProofCodec.readData Aiur.NativeAIR.ProofCodec.DataFits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.decode_fits +∀ {bytes : ByteArray} {value : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.ProofCodec.decode bytes = some value → Aiur.NativeAIR.ProofCodec.DataFits value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.pair_success +∀ {values : List (List Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.ProofShape.Pair}, + Aiur.NativeAIR.ProofShape.pair values = some result → values = [result.current, result.next] +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofShape.single_success +∀ {α : Type u_1} {values : List α} {result : α}, + Aiur.NativeAIR.ProofShape.single values = some result → values = [result] +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofShape.readPreprocessed_none +∀ (proof : Aiur.NativeAIR.ProofCodec.Data), Aiur.NativeAIR.ProofShape.readPreprocessed proof none = some none +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofShape.readPreprocessed_some +∀ {proof : Aiur.NativeAIR.ProofCodec.Data} {slot : Nat} {result : Option Aiur.NativeAIR.ProofShape.Pair}, + Aiur.NativeAIR.ProofShape.readPreprocessed proof (some slot) = some result → + ∃ values opened, + proof.preprocessed = some opened ∧ opened[slot]? = some [values.current, values.next] ∧ result = some values +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.readRow_success +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} {index position : Nat} + {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.readRow key proof index position = some row → + Aiur.NativeAIR.ProofShape.Row.Sourced key proof index position row +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.Pair.hasWidth_success +∀ {values : Aiur.NativeAIR.ProofShape.Pair} {width : Nat}, + values.hasWidth width = true → values.current.length = width ∧ values.next.length = width +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.Row.fits_success +∀ {parameters : Aiur.NativeAIR.KeyCodec.Parameters} {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.Row.fits parameters row = true → Aiur.NativeAIR.ProofShape.Row.Fits parameters row +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.check_success +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} + {result : List Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.check key proof = some result → + Aiur.NativeAIR.ProofShape.header key proof = true ∧ + Aiur.NativeAIR.ProofShape.inactivePreprocessed key proof = true ∧ + Aiur.NativeAIR.ProofShape.rows key proof = some result ∧ + ∀ (row : Aiur.NativeAIR.ProofShape.Row), row ∈ result → Aiur.NativeAIR.ProofShape.Row.Fits key.parameters row +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.check_length +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} + {result : List Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.check key proof = some result → + result.length = (Aiur.NativeAIR.ProofShape.activeIndices proof).length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.activeIndices_mem +∀ {proof : Aiur.NativeAIR.ProofCodec.Data} {index : Nat}, + index ∈ Aiur.NativeAIR.ProofShape.activeIndices proof ↔ proof.active[index]? = some true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.check_row +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} + {result : List Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.check key proof = some result → + ∀ {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + result[position]? = some row → + ∃ index, + (Aiur.NativeAIR.ProofShape.activeIndices proof)[position]? = some index ∧ + Aiur.NativeAIR.ProofShape.Row.Sourced key proof index position row ∧ + Aiur.NativeAIR.ProofShape.Row.Fits key.parameters row +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.check_row_active +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} + {result : List Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.check key proof = some result → + ∀ {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + result[position]? = some row → proof.active[row.circuitIndex]? = some true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.check_nonempty +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} + {result : List Aiur.NativeAIR.ProofShape.Row}, Aiur.NativeAIR.ProofShape.check key proof = some result → result ≠ [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.fixedHeights_sound +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.ProofShape.fixedHeights key proof = true → + Aiur.FixedTraceHeights (List.map (fun x => x.preprocessedHeight) key.circuits) proof.active + (List.map UInt8.toNat proof.logDegrees) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofShape.queryBound_sound +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} {bound : Nat}, + Aiur.NativeAIR.ProofShape.queryBound key proof = some bound → + ∃ total, + Aiur.lookupSlotSum (List.map (fun x => x.graph.lookups.length) key.circuits) proof.active + (List.map UInt8.toNat proof.logDegrees) = + some total ∧ + bound = 1 + total ∧ bound < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.framing +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes), + Aiur.NativeAIR.ProofCodec.readData bytes.data.toList = some (checked.data, []) ∧ + Aiur.NativeAIR.ProofCodec.encode checked.data = bytes +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.wire_bounds +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes), + Aiur.NativeAIR.ProofCodec.DataFits checked.data +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.row +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes) + {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + checked.rows[position]? = some row → + checked.data.active[row.circuitIndex]? = some true ∧ + Aiur.NativeAIR.ProofShape.Row.Sourced key checked.data row.circuitIndex position row ∧ + Aiur.NativeAIR.ProofShape.Row.Fits key.parameters row +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.nonempty +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes), + checked.rows ≠ [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.fixed_heights +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes), + Aiur.FixedTraceHeights (List.map (fun x => x.preprocessedHeight) key.circuits) checked.data.active + (List.map UInt8.toNat checked.data.logDegrees) +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.lookup_budget +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes), + ∃ total, + Aiur.lookupSlotSum (List.map (fun x => x.graph.lookups.length) key.circuits) checked.data.active + (List.map UInt8.toNat checked.data.logDegrees) = + some total ∧ + checked.bound = 1 + total ∧ checked.bound < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.verifyShaped_acceptance +∀ {selection : Aiur.BoundVerifier.Selection} {backend : Aiur.BoundVerifier.CompiledBackend selection} + {input : Array Aiur.G} {bytes : ByteArray}, + Aiur.BoundVerifier.verifyShaped backend input bytes = Except.ok () → + input.size = selection.inputSize ∧ + ∃ checked native, + Aiur.BoundVerifier.readProof backend.keyData bytes = Except.ok checked ∧ + Aiur.Proof.ofBytesChecked bytes = Except.ok native ∧ + backend.system.verify (Aiur.buildClaim selection.function input selection.success) native = Except.ok () +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.residue_injective +∀ {a b : Aiur.G}, a.residue = b.residue → a = b +AXIOMS [] +ROOT Aiur.G.residue_ofNat +∀ (n : Nat), (Aiur.G.ofNat n).residue = Fin.ofNat Aiur.gSize.toNat n +AXIOMS [propext] +ROOT Aiur.G.residue_add +∀ (a b : Aiur.G), (a + b).residue = a.residue + b.residue +AXIOMS [propext] +ROOT Aiur.G.residue_mul +∀ (a b : Aiur.G), (a * b).residue = a.residue * b.residue +AXIOMS [propext] +ROOT Aiur.G.residue_sub +∀ (a b : Aiur.G), (a - b).residue = a.residue - b.residue +AXIOMS [propext] +ROOT Aiur.G.residue_numeral +∀ (n : Nat), Aiur.G.residue (OfNat.ofNat n) = OfNat.ofNat n +AXIOMS [propext] +ROOT Aiur.G.residue_zero +Aiur.G.residue 0 = 0 +AXIOMS [propext] +ROOT Aiur.G.residue_one +Aiur.G.residue 1 = 1 +AXIOMS [propext] +ROOT Aiur.G.residue_neg +∀ (a : Aiur.G), (-a).residue = -a.residue +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.residue_ofInt +∀ (n : Int), (Aiur.G.ofInt n).residue = ↑n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.left_distrib +∀ (a b c : Aiur.G), a * (b + c) = a * b + a * c +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.neg_add_cancel +∀ (a : Aiur.G), -a + a = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.sub_eq_add_neg +∀ (a b : Aiur.G), a - b = a + -b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.ofInt_neg +∀ (n : Int), Aiur.G.ofInt (-n) = -Aiur.G.ofInt n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.neg_mul +∀ (a b : Aiur.G), -a * b = -(a * b) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.pow_go_eq +∀ (a : Aiur.G) (n fuel : Nat), n < 2 ^ fuel → Aiur.G.pow.go✝ a n fuel = a ^ n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.pow_eq +∀ (a : Aiur.G) (n : Nat), n < 2 ^ 64 → a.pow n = a ^ n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.inverse_eq_power +∀ (a : Aiur.G), a.inverse = a ^ (Aiur.gSize.toNat - 2) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.n_power +∀ (a : Aiur.G) (n : Nat), (a ^ n).n = a.n ^ n % Aiur.gSize.toNat +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.mul_right_cancel +∀ {a b c : Aiur.G}, c ≠ 0 → a * c = b * c → a = b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.nonzeroResidues_length +Aiur.G.nonzeroResidues.length = Aiur.gSize.toNat - 1 +AXIOMS [propext] +ROOT Aiur.G.mem_nonzeroResidues +∀ (a : Aiur.G), a ∈ Aiur.G.nonzeroResidues ↔ a ≠ 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.G.nonzeroResidues_nodup +Aiur.G.nonzeroResidues.Nodup +AXIOMS [propext, Quot.sound] +ROOT Aiur.G.map_perm_of_injective +∀ (values : List Aiur.G) (f : Aiur.G → Aiur.G), + values.Nodup → (∀ {x y : Aiur.G}, f x = f y → x = y) → List.map f values ⊆ values → (List.map f values).Perm values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.multiplication_perm +∀ (a : Aiur.G), a ≠ 0 → (List.map (fun x => a * x) Aiur.G.nonzeroResidues).Perm Aiur.G.nonzeroResidues +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.product_nonzero +∀ (values : List Aiur.G), (∀ (x : Aiur.G), x ∈ values → x ≠ 0) → Aiur.G.product values ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.product_perm +∀ {left right : List Aiur.G}, left.Perm right → Aiur.G.product left = Aiur.G.product right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.product_map_mul +∀ (a : Aiur.G) (values : List Aiur.G), + Aiur.G.product (List.map (fun x => a * x) values) = a ^ values.length * Aiur.G.product values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.power_eq_one_of_perm +∀ (a : Aiur.G) (values : List Aiur.G), + (∀ (x : Aiur.G), x ∈ values → x ≠ 0) → (List.map (fun x => a * x) values).Perm values → a ^ values.length = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.fermat +∀ (a : Aiur.G), a ≠ 0 → a ^ (Aiur.gSize.toNat - 1) = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.inverse_zero +Aiur.G.inverse 0 = 0 +AXIOMS [propext] +ROOT Aiur.G.mul_inverse_cancel +∀ (a : Aiur.G), a ≠ 0 → a * a.inverse = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.ext +∀ {a b : Aiur.NativeAIR.ProofCodec.Extension}, a.c0 = b.c0 → a.c1 = b.c1 → a = b +AXIOMS [] +ROOT Aiur.NativeAIR.ProofCodec.Extension.ofBase_injective +∀ {a b : Aiur.G}, Aiur.NativeAIR.ProofCodec.Extension.ofBase a = Aiur.NativeAIR.ProofCodec.Extension.ofBase b → a = b +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.Extension.ofBase_add +∀ (a b : Aiur.G), + Aiur.NativeAIR.ProofCodec.Extension.ofBase (a + b) = + Aiur.NativeAIR.ProofCodec.Extension.ofBase a + Aiur.NativeAIR.ProofCodec.Extension.ofBase b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.ofBase_sub +∀ (a b : Aiur.G), + Aiur.NativeAIR.ProofCodec.Extension.ofBase (a - b) = + Aiur.NativeAIR.ProofCodec.Extension.ofBase a - Aiur.NativeAIR.ProofCodec.Extension.ofBase b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.ofBase_neg +∀ (a : Aiur.G), Aiur.NativeAIR.ProofCodec.Extension.ofBase (-a) = -Aiur.NativeAIR.ProofCodec.Extension.ofBase a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.ofBase_mul +∀ (a b : Aiur.G), + Aiur.NativeAIR.ProofCodec.Extension.ofBase (a * b) = + Aiur.NativeAIR.ProofCodec.Extension.ofBase a * Aiur.NativeAIR.ProofCodec.Extension.ofBase b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.add_zero +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), a + 0 = a +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.Extension.add_comm +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), a + b = b + a +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.add_assoc +∀ (a b c : Aiur.NativeAIR.ProofCodec.Extension), a + b + c = a + (b + c) +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.Extension.mul_one +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), a * 1 = a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.zero_mul +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), 0 * a = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.mul_comm +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), a * b = b * a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.mul_assoc +∀ (a b c : Aiur.NativeAIR.ProofCodec.Extension), a * b * c = a * (b * c) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.left_distrib +∀ (a b c : Aiur.NativeAIR.ProofCodec.Extension), a * (b + c) = a * b + a * c +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.neg_add_cancel +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), -a + a = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.sub_eq_add_neg +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), a - b = a + -b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.neg_mul +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), -a * b = -(a * b) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.basis_square +Aiur.NativeAIR.ProofCodec.Extension.basis * Aiur.NativeAIR.ProofCodec.Extension.basis = + Aiur.NativeAIR.ProofCodec.Extension.ofBase 7 +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.Extension.coordinates +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), + a = + Aiur.NativeAIR.ProofCodec.Extension.ofBase a.c0 + + Aiur.NativeAIR.ProofCodec.Extension.ofBase a.c1 * Aiur.NativeAIR.ProofCodec.Extension.basis +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.scale_eq_mul +∀ (a : Aiur.NativeAIR.ProofCodec.Extension) (b : Aiur.G), a.scale b = a * Aiur.NativeAIR.ProofCodec.Extension.ofBase b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.conjugate_conjugate +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), a.conjugate.conjugate = a +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.mul_conjugate +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), a * a.conjugate = Aiur.NativeAIR.ProofCodec.Extension.ofBase a.norm +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.conjugate_mul +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), (a * b).conjugate = a.conjugate * b.conjugate +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.norm_mul +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), (a * b).norm = a.norm * b.norm +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.evalLaws +Aiur.NativeAIR.EvalLaws Aiur.NativeAIR.ProofCodec.Extension.evalOps +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.powBits_eq +∀ (a : Aiur.NativeAIR.ProofCodec.Extension) (n fuel : Nat), n < 2 ^ fuel → a.powBits n fuel = a ^ n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.power_eq +∀ (a : Aiur.NativeAIR.ProofCodec.Extension) (n : Nat), a.power n = a ^ n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.ofBase_power +∀ (a : Aiur.G) (n : Nat), + Aiur.NativeAIR.ProofCodec.Extension.ofBase (a ^ n) = Aiur.NativeAIR.ProofCodec.Extension.ofBase a ^ n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.inverse_formula +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), + a.tryInverse = + if a = 0 then none + else some (a.conjugate * Aiur.NativeAIR.ProofCodec.Extension.ofBase (a.norm ^ (Aiur.gSize.toNat - 2))) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.seven_euler_certificate +Aiur.G.pow 7 ((Aiur.gSize.toNat - 1) / 2) = 0 - 1 +AXIOMS [propext] +ROOT Aiur.G.seven_not_square +∀ (a : Aiur.G), a * a ≠ 7 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.G.square_ratio +∀ (x y inverse : Aiur.G), x * x = 7 * (y * y) → y * inverse = 1 → x * inverse * (x * inverse) = 7 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.norm_zero_iff +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), a.norm = 0 ↔ a = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.mul_eq_zero_iff +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), a * b = 0 ↔ a = 0 ∨ b = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.one_ne_zero +1 ≠ 0 +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.Extension.mul_left_cancel +∀ {a b c : Aiur.NativeAIR.ProofCodec.Extension}, a ≠ 0 → a * b = a * c → b = c +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.inverse_correct +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), + a ≠ 0 → a.tryInverse = some (a.conjugate.scale a.norm.inverse) ∧ a * a.conjugate.scale a.norm.inverse = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ProofCodec.Extension.tryInverse_none_iff +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), a.tryInverse = none ↔ a = 0 +AXIOMS [propext] +ROOT Aiur.NativeAIR.ProofCodec.Extension.tryInverse_some_iff +∀ (a b : Aiur.NativeAIR.ProofCodec.Extension), a.tryInverse = some b ↔ a * b = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.ext +∀ {W : Type u_1} {a b : Aiur.NativeAIR.LogUp.Coordinates W}, a.c0 = b.c0 → a.c1 = b.c1 → a = b +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.Coordinates.zero_iff +∀ {W : Type u_1} [inst : OfNat W 0] (a : Aiur.NativeAIR.LogUp.Coordinates W), a = 0 ↔ a.c0 = 0 ∧ a.c1 = 0 +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.Coordinates.flatten_length +∀ {W : Type u_1} (values : List (Aiur.NativeAIR.LogUp.Coordinates W)), + (Aiur.NativeAIR.LogUp.Coordinates.flatten values).length = 2 * values.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.flatten_zero_iff +∀ {W : Type u_1} [inst : OfNat W 0] (values : List (Aiur.NativeAIR.LogUp.Coordinates W)), + (∀ (x : W), x ∈ Aiur.NativeAIR.LogUp.Coordinates.flatten values → x = 0) ↔ + ∀ (value : Aiur.NativeAIR.LogUp.Coordinates W), value ∈ values → value = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.mul_schoolbook +∀ {W : Type u} [inst : Grind.CommRing W] (a b : Aiur.NativeAIR.LogUp.Coordinates W), + a * b = { c0 := a.c0 * b.c0 + 7 * a.c1 * b.c1, c1 := a.c0 * b.c1 + a.c1 * b.c0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.add_zero +∀ {W : Type u} [inst : Grind.CommRing W] (a : Aiur.NativeAIR.LogUp.Coordinates W), a + 0 = a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.add_comm +∀ {W : Type u} [inst : Grind.CommRing W] (a b : Aiur.NativeAIR.LogUp.Coordinates W), a + b = b + a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.add_assoc +∀ {W : Type u} [inst : Grind.CommRing W] (a b c : Aiur.NativeAIR.LogUp.Coordinates W), a + b + c = a + (b + c) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.mul_one +∀ {W : Type u} [inst : Grind.CommRing W] (a : Aiur.NativeAIR.LogUp.Coordinates W), a * 1 = a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.mul_zero +∀ {W : Type u} [inst : Grind.CommRing W] (a : Aiur.NativeAIR.LogUp.Coordinates W), a * 0 = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.mul_comm +∀ {W : Type u} [inst : Grind.CommRing W] (a b : Aiur.NativeAIR.LogUp.Coordinates W), a * b = b * a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.mul_assoc +∀ {W : Type u} [inst : Grind.CommRing W] (a b c : Aiur.NativeAIR.LogUp.Coordinates W), a * b * c = a * (b * c) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.left_distrib +∀ {W : Type u} [inst : Grind.CommRing W] (a b c : Aiur.NativeAIR.LogUp.Coordinates W), a * (b + c) = a * b + a * c +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.neg_add_cancel +∀ {W : Type u} [inst : Grind.CommRing W] (a : Aiur.NativeAIR.LogUp.Coordinates W), -a + a = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.sub_eq_add_neg +∀ {W : Type u} [inst : Grind.CommRing W] (a b : Aiur.NativeAIR.LogUp.Coordinates W), a - b = a + -b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.ofBase_add +∀ {W : Type u} [inst : Grind.CommRing W] (a b : W), + Aiur.NativeAIR.LogUp.Coordinates.ofBase (a + b) = + Aiur.NativeAIR.LogUp.Coordinates.ofBase a + Aiur.NativeAIR.LogUp.Coordinates.ofBase b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.ofBase_neg +∀ {W : Type u} [inst : Grind.CommRing W] (a : W), + Aiur.NativeAIR.LogUp.Coordinates.ofBase (-a) = -Aiur.NativeAIR.LogUp.Coordinates.ofBase a +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.ofBase_mul +∀ {W : Type u} [inst : Grind.CommRing W] (a b : W), + Aiur.NativeAIR.LogUp.Coordinates.ofBase (a * b) = + Aiur.NativeAIR.LogUp.Coordinates.ofBase a * Aiur.NativeAIR.LogUp.Coordinates.ofBase b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.neg_mul +∀ {W : Type u} [inst : Grind.CommRing W] (a b : Aiur.NativeAIR.LogUp.Coordinates W), -a * b = -(a * b) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.scale_eq_mul +∀ {W : Type u} [inst : Grind.CommRing W] (a : Aiur.NativeAIR.LogUp.Coordinates W) (b : W), + a.scale b = a * Aiur.NativeAIR.LogUp.Coordinates.ofBase b +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.toExtension_injective +∀ {a b : Aiur.NativeAIR.LogUp.Coordinates Aiur.G}, a.toExtension = b.toExtension → a = b +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.Coordinates.toExtension_fromExtension +∀ (a : Aiur.NativeAIR.ProofCodec.Extension), (Aiur.NativeAIR.LogUp.Coordinates.fromExtension a).toExtension = a +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.Coordinates.fromExtension_toExtension +∀ (a : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), Aiur.NativeAIR.LogUp.Coordinates.fromExtension a.toExtension = a +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.Coordinates.toExtension_zero_iff +∀ (a : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), a.toExtension = 0 ↔ a = 0 +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.Coordinates.toExtension_ofBase +∀ (a : Aiur.G), (Aiur.NativeAIR.LogUp.Coordinates.ofBase a).toExtension = Aiur.NativeAIR.ProofCodec.Extension.ofBase a +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.Coordinates.toExtension_add +∀ (a b : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), (a + b).toExtension = a.toExtension + b.toExtension +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.Coordinates.toExtension_sub +∀ (a b : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), (a - b).toExtension = a.toExtension - b.toExtension +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.Coordinates.toExtension_mul +∀ (a b : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), (a * b).toExtension = a.toExtension * b.toExtension +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.Coordinates.collapse_loses_constraint +have a := { c0 := -Aiur.NativeAIR.ProofCodec.Extension.basis, c1 := 1 }; +a ≠ 0 ∧ a.c0 + a.c1 * Aiur.NativeAIR.ProofCodec.Extension.basis = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.sub_zero_iff +∀ {R : Type u} [inst : Grind.CommRing R] (left right : R), left - right = 0 ↔ left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.clears_cons +∀ {R : Type u} [inst : Grind.CommRing R] (weight message inverse denominator fractions cleared : R), + message * inverse = 1 → + denominator * fractions = cleared → + message * denominator * (weight * inverse + fractions) = weight * denominator + message * cleared +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.product_cons +∀ {R : Type u} [inst : Grind.CommRing R] (value : R) (values : List R), + Aiur.NativeAIR.LogUp.product (value :: values) = value * Aiur.NativeAIR.LogUp.product values +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.product_append +∀ {R : Type u} [inst : Grind.CommRing R] (left right : List R), + Aiur.NativeAIR.LogUp.product (left ++ right) = Aiur.NativeAIR.LogUp.product left * Aiur.NativeAIR.LogUp.product right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.product_foldl +∀ {R : Type u} [inst : Grind.CommRing R] (values : List R) (initial : R), + List.foldl (fun x1 x2 => x1 * x2) initial values = initial * Aiur.NativeAIR.LogUp.product values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.sum_foldl +∀ {R : Type u} [inst : Grind.CommRing R] (values : List R) (initial : R), + List.foldl (fun x1 x2 => x1 + x2) initial values = initial + Aiur.NativeAIR.LogUp.sum values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.sum_append +∀ {R : Type u} [inst : Grind.CommRing R] (left right : List R), + Aiur.NativeAIR.LogUp.sum (left ++ right) = Aiur.NativeAIR.LogUp.sum left + Aiur.NativeAIR.LogUp.sum right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.telescope +∀ {R : Type u} [inst : Grind.CommRing R] (states increments : Nat → R) (count : Nat), + (∀ (index : Nat), index < count → states (index + 1) - states index = increments index) → + states count - states 0 = Aiur.NativeAIR.LogUp.sum (List.map increments (List.range count)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.cyclic_accumulator +∀ {R : Type u} [inst : Grind.CommRing R] (states fractions : Nat → R) (count : Nat) (delta : R), + 0 < count → + states count = states 0 → + (∀ (index : Nat), + index < count → + (states (index + 1) - states index + if index + 1 = count then delta else 0) = fractions index) → + Aiur.NativeAIR.LogUp.sum (List.map fractions (List.range count)) = delta +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.final_accumulator +∀ {R : Type u} [inst : Grind.CommRing R] (accumulators contributions : Nat → R) (count : Nat), + accumulators count = 0 → + (∀ (index : Nat), index < count → accumulators (index + 1) - accumulators index = contributions index) → + accumulators 0 + Aiur.NativeAIR.LogUp.sum (List.map contributions (List.range count)) = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.prefix_products +∀ {R : Type u} [inst : Grind.CommRing R] (values : List R) (initial : R) (index : Nat), + (List.scanl (fun x1 x2 => x1 * x2) initial values)[index]? = + if index ≤ values.length then some (initial * Aiur.NativeAIR.LogUp.product (List.take index values)) else none +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.prefix_seeded +∀ {R : Type u} [inst : Grind.CommRing R] (first : R) (rest : List R), + List.scanl (fun x1 x2 => x1 * x2) 1 (first :: rest) = 1 :: List.scanl (fun x1 x2 => x1 * x2) first rest +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.suffix_seeded +∀ {R : Type u} [inst : Grind.CommRing R] (rest : List R) (last : R), + List.scanr (fun x1 x2 => x1 * x2) 1 (rest ++ [last]) = List.scanr (fun x1 x2 => x1 * x2) last rest ++ [1] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.suffix_products +∀ {R : Type u} [inst : Grind.CommRing R] (values : List R) (index : Nat), + (List.scanr (fun x1 x2 => x1 * x2) 1 values)[index]? = + if index ≤ values.length then some (Aiur.NativeAIR.LogUp.product (List.drop index values)) else none +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.prefixSuffixTerms_cons +∀ {R : Type u} [inst : Grind.CommRing R] (weight message initial : R) (entries : List (R × R)), + Aiur.NativeAIR.LogUp.prefixSuffixTerms initial ((weight, message) :: entries) = + initial * Aiur.NativeAIR.LogUp.product (List.map Prod.snd entries) * weight :: + Aiur.NativeAIR.LogUp.prefixSuffixTerms (initial * message) entries +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.prefixSuffixTerms_sum +∀ {R : Type u} [inst : Grind.CommRing R] (entries : List (R × R)) (initial : R), + Aiur.NativeAIR.LogUp.sum (Aiur.NativeAIR.LogUp.prefixSuffixTerms initial entries) = + initial * Aiur.NativeAIR.LogUp.numerator entries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.groupEquation_polynomial +∀ {R : Type u} [inst : Grind.CommRing R] (entries : List (R × R)) (difference : R), + Aiur.NativeAIR.LogUp.groupEquation entries difference = + Aiur.NativeAIR.LogUp.product (List.map Prod.snd entries) * difference - Aiur.NativeAIR.LogUp.numerator entries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.numerator_append +∀ {R : Type u} [inst : Grind.CommRing R] (left right : List (R × R)), + Aiur.NativeAIR.LogUp.numerator (left ++ right) = + Aiur.NativeAIR.LogUp.numerator left * Aiur.NativeAIR.LogUp.product (List.map Prod.snd right) + + Aiur.NativeAIR.LogUp.product (List.map Prod.snd left) * Aiur.NativeAIR.LogUp.numerator right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fingerprint_reverse_horner +∀ {W : Type u} [inst : Grind.CommRing W] (gamma : Aiur.NativeAIR.LogUp.Coordinates W) (args : List W), + Aiur.NativeAIR.LogUp.fingerprint gamma args = + List.foldl (fun acc arg => acc * gamma + Aiur.NativeAIR.LogUp.Coordinates.ofBase arg) 0 args.reverse +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fingerprint_nil +∀ {W : Type u} [inst : Grind.CommRing W] (gamma : Aiur.NativeAIR.LogUp.Coordinates W), + Aiur.NativeAIR.LogUp.fingerprint gamma [] = 0 +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.fingerprint_cons +∀ {W : Type u} [inst : Grind.CommRing W] (gamma : Aiur.NativeAIR.LogUp.Coordinates W) (arg : W) (args : List W), + Aiur.NativeAIR.LogUp.fingerprint gamma (arg :: args) = + Aiur.NativeAIR.LogUp.fingerprint gamma args * gamma + Aiur.NativeAIR.LogUp.Coordinates.ofBase arg +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.fingerprint_trailing_zero +∀ {W : Type u} [inst : Grind.CommRing W] (gamma : Aiur.NativeAIR.LogUp.Coordinates W) (args : List W), + Aiur.NativeAIR.LogUp.fingerprint gamma (args ++ [0]) = Aiur.NativeAIR.LogUp.fingerprint gamma args +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fingerprint_padding +∀ {W : Type u} [inst : Grind.CommRing W] (gamma : Aiur.NativeAIR.LogUp.Coordinates W) (args : List W) (count : Nat), + Aiur.NativeAIR.LogUp.fingerprint gamma (args ++ List.replicate count 0) = Aiur.NativeAIR.LogUp.fingerprint gamma args +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.groupCount_positive +∀ (groupSize lookupCount : Nat), 0 < Aiur.NativeAIR.LogUp.groupCount groupSize lookupCount +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.groupCount_covers +∀ (groupSize lookupCount : Nat), lookupCount ≤ Aiur.NativeAIR.LogUp.groupCount groupSize lookupCount * max groupSize 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.groupCount_zero +∀ (lookupCount : Nat), Aiur.NativeAIR.LogUp.groupCount 0 lookupCount = Aiur.NativeAIR.LogUp.groupCount 1 lookupCount +AXIOMS [] +ROOT Aiur.NativeAIR.LogUp.groupCount_empty +∀ (groupSize : Nat), Aiur.NativeAIR.LogUp.groupCount groupSize 0 = 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.groupCount_key +∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), + 0 < circuit.lookupGroupSize → + Aiur.NativeAIR.LogUp.groupCount circuit.lookupGroupSize circuit.graph.lookups.length = circuit.groups +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.chunk_length +∀ {α : Type u_1} (groupSize index : Nat) (values : List α), + (Aiur.NativeAIR.LogUp.chunk groupSize index values).length = + min (max groupSize 1) (values.length - index * max groupSize 1) +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.chunks_take +∀ {α : Type u_1} (groupSize count : Nat) (values : List α), + List.flatMap (fun index => Aiur.NativeAIR.LogUp.chunk groupSize index values) (List.range count) = + List.take (count * max groupSize 1) values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.chunks_cover +∀ {α : Type u_1} (groupSize : Nat) (values : List α), + List.flatMap (fun index => Aiur.NativeAIR.LogUp.chunk groupSize index values) + (List.range (Aiur.NativeAIR.LogUp.groupCount groupSize values.length)) = + values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.chunk_mem +∀ {α : Type u_1} {groupSize index : Nat} {values : List α} {value : α}, + value ∈ Aiur.NativeAIR.LogUp.chunk groupSize index values → value ∈ values +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.chunk_map +∀ {α : Type u_1} {β : Type u_2} (groupSize index : Nat) (values : List α) (f : α → β), + Aiur.NativeAIR.LogUp.chunk groupSize index (List.map f values) = + List.map f (Aiur.NativeAIR.LogUp.chunk groupSize index values) +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.mapM_some_reads +∀ {α : Type u_1} {β : Type u_2} {read : α → Option β} {inputs : List α} {outputs : List β}, + List.mapM read inputs = some outputs → + outputs.length = inputs.length ∧ + ∀ (index : Nat) (input : α), + inputs[index]? = some input → ∃ output, outputs[index]? = some output ∧ read input = some output +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.mapM_defined +∀ {α : Type u_1} {β : Type u_2} (inputs : List α) (read : α → Option β), + (∀ (input : α), input ∈ inputs → ∃ output, read input = some output) → ∃ outputs, List.mapM read inputs = some outputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.read_coordinates_defined +∀ {W : Type u_1} (values : Array W) (slot : Nat), + 2 * slot + 1 < values.size → ∃ value, Aiur.NativeAIR.LogUp.Coordinates.read values slot = some value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.read_coordinates_success +∀ {W : Type u_1} {values : Array W} {slot : Nat} {value : Aiur.NativeAIR.LogUp.Coordinates W}, + Aiur.NativeAIR.LogUp.Coordinates.read values slot = some value → + values[2 * slot]? = some value.c0 ∧ values[2 * slot + 1]? = some value.c1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.step_polynomial +∀ {W : Type u} [inst : Grind.CommRing W] {beta gamma injection next : Aiur.NativeAIR.LogUp.Coordinates W} + {stageCurrent : Array W} {lookups : List (W × List W)} {groupSize index : Nat} + {result : Aiur.NativeAIR.LogUp.Coordinates W}, + Aiur.NativeAIR.LogUp.step beta gamma injection next stageCurrent lookups groupSize index = some result → + ∃ source target, + Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent index = some source ∧ + (if index + 1 < Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length then + Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent (index + 1) + else some (next + injection)) = + some target ∧ + result = + Aiur.NativeAIR.LogUp.product + (List.map Prod.snd + (Aiur.NativeAIR.LogUp.compress beta gamma (Aiur.NativeAIR.LogUp.chunk groupSize index lookups))) * + (target - source) - + Aiur.NativeAIR.LogUp.numerator + (Aiur.NativeAIR.LogUp.compress beta gamma (Aiur.NativeAIR.LogUp.chunk groupSize index lookups)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.step_defined +∀ {W : Type u} [inst : Grind.CommRing W] (beta gamma injection next : Aiur.NativeAIR.LogUp.Coordinates W) + (stageCurrent : Array W) (lookups : List (W × List W)) (groupSize index : Nat), + Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length * 2 ≤ stageCurrent.size → + index < Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length → + ∃ result, Aiur.NativeAIR.LogUp.step beta gamma injection next stageCurrent lookups groupSize index = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.equations_success +∀ {W : Type u} [inst : Grind.CommRing W] {lookups : List (W × List W)} + {stageCurrent stageNext publics deltaScaled : Array W} {isLast : W} {groupSize : Nat} + {result : List (Aiur.NativeAIR.LogUp.Coordinates W)}, + Aiur.NativeAIR.LogUp.equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = some result → + groupSize ≤ 8 ∧ + ∃ beta gamma delta next, + Aiur.NativeAIR.LogUp.Coordinates.read publics 0 = some beta ∧ + Aiur.NativeAIR.LogUp.Coordinates.read publics 1 = some gamma ∧ + Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 = some delta ∧ + Aiur.NativeAIR.LogUp.Coordinates.read stageNext 0 = some next ∧ + result.length = Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length ∧ + ∀ (index : Nat), + index < Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length → + ∃ value, + result[index]? = some value ∧ + Aiur.NativeAIR.LogUp.step beta gamma (delta.scale isLast) next stageCurrent lookups groupSize + index = + some value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.equations_defined +∀ {W : Type u} [inst : Grind.CommRing W] (lookups : List (W × List W)) + (stageCurrent stageNext publics deltaScaled : Array W) (isLast : W) (groupSize : Nat), + groupSize ≤ 8 → + Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length * 2 ≤ stageCurrent.size → + 2 ≤ stageNext.size → + 4 ≤ publics.size → + 2 ≤ deltaScaled.size → + ∃ result, + Aiur.NativeAIR.LogUp.equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = + some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.equations_zero +∀ {W : Type u} [inst : Grind.CommRing W] {lookups : List (W × List W)} + {stageCurrent stageNext publics deltaScaled : Array W} {isLast : W} {groupSize : Nat} + {result : List (Aiur.NativeAIR.LogUp.Coordinates W)}, + Aiur.NativeAIR.LogUp.equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = some result → + (∀ (value : Aiur.NativeAIR.LogUp.Coordinates W), value ∈ result → value = 0) → + ∃ beta gamma delta next, + Aiur.NativeAIR.LogUp.Coordinates.read publics 0 = some beta ∧ + Aiur.NativeAIR.LogUp.Coordinates.read publics 1 = some gamma ∧ + Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 = some delta ∧ + Aiur.NativeAIR.LogUp.Coordinates.read stageNext 0 = some next ∧ + ∀ (index : Nat), + index < Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length → + ∃ source target, + Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent index = some source ∧ + (if index + 1 < Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length then + Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent (index + 1) + else some (next + delta.scale isLast)) = + some target ∧ + Aiur.NativeAIR.LogUp.product + (List.map Prod.snd + (Aiur.NativeAIR.LogUp.compress beta gamma + (Aiur.NativeAIR.LogUp.chunk groupSize index lookups))) * + (target - source) = + Aiur.NativeAIR.LogUp.numerator + (Aiur.NativeAIR.LogUp.compress beta gamma + (Aiur.NativeAIR.LogUp.chunk groupSize index lookups)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.constraintValues_success +∀ {W : Type u} [inst : Grind.CommRing W] {lookups : List Aiur.NativeAIR.Lookup} + {nodeValues stageCurrent stageNext publics deltaScaled : Array W} {isLast : W} {groupSize : Nat} {result : List W}, + Aiur.NativeAIR.LogUp.constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled isLast groupSize = + some result → + ∃ values coordinates, + List.mapM (Aiur.NativeAIR.readLookup nodeValues) lookups = some values ∧ + Aiur.NativeAIR.LogUp.equations values stageCurrent stageNext publics deltaScaled isLast groupSize = + some coordinates ∧ + result = Aiur.NativeAIR.LogUp.Coordinates.flatten coordinates +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.constraintValues_length +∀ {W : Type u} [inst : Grind.CommRing W] {lookups : List Aiur.NativeAIR.Lookup} + {nodeValues stageCurrent stageNext publics deltaScaled : Array W} {isLast : W} {groupSize : Nat} {result : List W}, + Aiur.NativeAIR.LogUp.constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled isLast groupSize = + some result → + result.length = 2 * Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.constraintValues_defined +∀ {W : Type u} [inst : Grind.CommRing W] (lookups : List Aiur.NativeAIR.Lookup) + (nodeValues stageCurrent stageNext publics deltaScaled : Array W) (isLast : W) (groupSize : Nat), + groupSize ≤ 8 → + (∀ (lookup : Aiur.NativeAIR.Lookup), + lookup ∈ lookups → ∀ (index : Nat), index ∈ lookup.roots → index < nodeValues.size) → + Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length * 2 ≤ stageCurrent.size → + 2 ≤ stageNext.size → + 4 ≤ publics.size → + 2 ≤ deltaScaled.size → + ∃ result, + Aiur.NativeAIR.LogUp.constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled + isLast groupSize = + some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.constraintValues_reflect +∀ {W : Type u} [inst : Grind.CommRing W] {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} + {trees : Array Aiur.NativeAIR.Expr} {buffer : Array W}, + Aiur.NativeAIR.Reflects ops values trees buffer → + ∀ (lookups : List Aiur.NativeAIR.Lookup) (stageCurrent stageNext publics deltaScaled : Array W) (isLast : W) + (groupSize : Nat), + Aiur.NativeAIR.LogUp.constraintValues lookups buffer stageCurrent stageNext publics deltaScaled isLast groupSize = + do + let lookupValues ← List.mapM (Aiur.NativeAIR.evalLookup ops values trees) lookups + let __do_lift ← + Aiur.NativeAIR.LogUp.equations lookupValues stageCurrent stageNext publics deltaScaled isLast groupSize + pure (Aiur.NativeAIR.LogUp.Coordinates.flatten __do_lift) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.inverseValue_correct +∀ (value : Aiur.NativeAIR.ProofCodec.Extension), value ≠ 0 → value * Aiur.NativeAIR.LogUp.inverseValue value = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.product_nonzero +∀ (values : List Aiur.NativeAIR.ProofCodec.Extension), + (∀ (value : Aiur.NativeAIR.ProofCodec.Extension), value ∈ values → value ≠ 0) → + Aiur.NativeAIR.LogUp.product values ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.poleFree_product +∀ (entries : List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)), + Aiur.NativeAIR.LogUp.PoleFree entries → Aiur.NativeAIR.LogUp.product (List.map Prod.snd entries) ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fractionSum_cons +∀ (weight message : Aiur.NativeAIR.ProofCodec.Extension) + (entries : List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)), + Aiur.NativeAIR.LogUp.fractionSum ((weight, message) :: entries) = + weight * Aiur.NativeAIR.LogUp.inverseValue message + Aiur.NativeAIR.LogUp.fractionSum entries +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.fractionSum_append +∀ (left right : List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)), + Aiur.NativeAIR.LogUp.fractionSum (left ++ right) = + Aiur.NativeAIR.LogUp.fractionSum left + Aiur.NativeAIR.LogUp.fractionSum right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fractionSum_clears +∀ (entries : List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)), + Aiur.NativeAIR.LogUp.PoleFree entries → + Aiur.NativeAIR.LogUp.product (List.map Prod.snd entries) * Aiur.NativeAIR.LogUp.fractionSum entries = + Aiur.NativeAIR.LogUp.numerator entries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.groupEquation_zero_iff +∀ (entries : List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)) + (difference : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.LogUp.PoleFree entries → + (Aiur.NativeAIR.LogUp.groupEquation entries difference = 0 ↔ difference = Aiur.NativeAIR.LogUp.fractionSum entries) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.product_toExtension +∀ (values : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G)), + (Aiur.NativeAIR.LogUp.product values).toExtension = + Aiur.NativeAIR.LogUp.product (List.map Aiur.NativeAIR.LogUp.Coordinates.toExtension values) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fieldEntries_messages +∀ (entries : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G × Aiur.NativeAIR.LogUp.Coordinates Aiur.G)), + List.map Prod.snd (Aiur.NativeAIR.LogUp.fieldEntries entries) = + List.map Aiur.NativeAIR.LogUp.Coordinates.toExtension (List.map Prod.snd entries) +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.numerator_toExtension +∀ (entries : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G × Aiur.NativeAIR.LogUp.Coordinates Aiur.G)), + (Aiur.NativeAIR.LogUp.numerator entries).toExtension = + Aiur.NativeAIR.LogUp.numerator (Aiur.NativeAIR.LogUp.fieldEntries entries) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.groupEquation_toExtension +∀ (entries : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G × Aiur.NativeAIR.LogUp.Coordinates Aiur.G)) + (difference : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), + (Aiur.NativeAIR.LogUp.groupEquation entries difference).toExtension = + Aiur.NativeAIR.LogUp.groupEquation (Aiur.NativeAIR.LogUp.fieldEntries entries) difference.toExtension +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.coordinate_group_zero_iff +∀ (entries : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G × Aiur.NativeAIR.LogUp.Coordinates Aiur.G)) + (difference : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), + Aiur.NativeAIR.LogUp.PoleFree (Aiur.NativeAIR.LogUp.fieldEntries entries) → + (Aiur.NativeAIR.LogUp.groupEquation entries difference = 0 ↔ + difference.toExtension = Aiur.NativeAIR.LogUp.fractionSum (Aiur.NativeAIR.LogUp.fieldEntries entries)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.coordinate_polynomial_zero_iff +∀ (entries : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G × Aiur.NativeAIR.LogUp.Coordinates Aiur.G)) + (difference : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), + Aiur.NativeAIR.LogUp.PoleFree (Aiur.NativeAIR.LogUp.fieldEntries entries) → + (Aiur.NativeAIR.LogUp.product (List.map Prod.snd entries) * difference = Aiur.NativeAIR.LogUp.numerator entries ↔ + difference.toExtension = Aiur.NativeAIR.LogUp.fractionSum (Aiur.NativeAIR.LogUp.fieldEntries entries)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fingerprint_toExtension +∀ (gamma : Aiur.NativeAIR.LogUp.Coordinates Aiur.G) (args : List Aiur.G), + (Aiur.NativeAIR.LogUp.fingerprint gamma args).toExtension = + List.foldr (fun arg acc => acc * gamma.toExtension + Aiur.NativeAIR.ProofCodec.Extension.ofBase arg) 0 args +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.pole_can_hide_step +Aiur.NativeAIR.LogUp.groupEquation [(0, 0)] 1 = 0 ∧ 1 ≠ Aiur.NativeAIR.LogUp.fractionSum [(0, 0)] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fractionSum_flatMap +∀ {α : Type u_1} (inputs : List α) + (entries : α → List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)), + Aiur.NativeAIR.LogUp.fractionSum (List.flatMap entries inputs) = + Aiur.NativeAIR.LogUp.sum (List.map (fun input => Aiur.NativeAIR.LogUp.fractionSum (entries input)) inputs) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.fieldEntries_compress_chunk +∀ (beta gamma : Aiur.NativeAIR.LogUp.Coordinates Aiur.G) (lookups : List (Aiur.G × List Aiur.G)) + (groupSize index : Nat), + Aiur.NativeAIR.LogUp.fieldEntries + (Aiur.NativeAIR.LogUp.compress beta gamma (Aiur.NativeAIR.LogUp.chunk groupSize index lookups)) = + Aiur.NativeAIR.LogUp.chunk groupSize index + (Aiur.NativeAIR.LogUp.fieldEntries (Aiur.NativeAIR.LogUp.compress beta gamma lookups)) +AXIOMS [propext] +ROOT Aiur.NativeAIR.LogUp.lookupFractions_chunks +∀ (beta gamma : Aiur.NativeAIR.LogUp.Coordinates Aiur.G) (lookups : List (Aiur.G × List Aiur.G)) (groupSize : Nat), + Aiur.NativeAIR.LogUp.sum + (List.map + (fun index => + Aiur.NativeAIR.LogUp.lookupFractions beta gamma (Aiur.NativeAIR.LogUp.chunk groupSize index lookups)) + (List.range (Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length))) = + Aiur.NativeAIR.LogUp.lookupFractions beta gamma lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.equations_accumulator +∀ {lookups : List (Aiur.G × List Aiur.G)} {stageCurrent stageNext publics deltaScaled : Array Aiur.G} {isLast : Aiur.G} + {groupSize : Nat} {result : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G)} + {beta gamma : Aiur.NativeAIR.LogUp.Coordinates Aiur.G}, + Aiur.NativeAIR.LogUp.Coordinates.read publics 0 = some beta → + Aiur.NativeAIR.LogUp.Coordinates.read publics 1 = some gamma → + Aiur.NativeAIR.LogUp.equations lookups stageCurrent stageNext publics deltaScaled isLast groupSize = some result → + (∀ (value : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), value ∈ result → value = 0) → + Aiur.NativeAIR.LogUp.PoleFree + (Aiur.NativeAIR.LogUp.fieldEntries (Aiur.NativeAIR.LogUp.compress beta gamma lookups)) → + ∃ first next delta, + Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent 0 = some first ∧ + Aiur.NativeAIR.LogUp.Coordinates.read stageNext 0 = some next ∧ + Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 = some delta ∧ + next.toExtension - first.toExtension + (delta.scale isLast).toExtension = + Aiur.NativeAIR.LogUp.lookupFractions beta gamma lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.constraintValues_accumulator +∀ {lookups : List Aiur.NativeAIR.Lookup} {nodeValues stageCurrent stageNext publics deltaScaled : Array Aiur.G} + {isLast : Aiur.G} {groupSize : Nat} {result : List Aiur.G} {beta gamma : Aiur.NativeAIR.LogUp.Coordinates Aiur.G}, + Aiur.NativeAIR.LogUp.Coordinates.read publics 0 = some beta → + Aiur.NativeAIR.LogUp.Coordinates.read publics 1 = some gamma → + Aiur.NativeAIR.LogUp.constraintValues lookups nodeValues stageCurrent stageNext publics deltaScaled isLast + groupSize = + some result → + (∀ (value : Aiur.G), value ∈ result → value = 0) → + (∀ (values : List (Aiur.G × List Aiur.G)), + List.mapM (Aiur.NativeAIR.readLookup nodeValues) lookups = some values → + Aiur.NativeAIR.LogUp.PoleFree + (Aiur.NativeAIR.LogUp.fieldEntries (Aiur.NativeAIR.LogUp.compress beta gamma values))) → + ∃ values first next delta, + List.mapM (Aiur.NativeAIR.readLookup nodeValues) lookups = some values ∧ + Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent 0 = some first ∧ + Aiur.NativeAIR.LogUp.Coordinates.read stageNext 0 = some next ∧ + Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 = some delta ∧ + next.toExtension - first.toExtension + (delta.scale isLast).toExtension = + Aiur.NativeAIR.LogUp.lookupFractions beta gamma values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.generators_size +Aiur.NativeAIR.Domain.generators.size = 33 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Domain.Algebra.power_zero +∀ {R : Type} [inst : Grind.CommRing R] (n : Nat), 0 < n → 0 ^ n = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Domain.Algebra.power_mul +∀ {R : Type} [inst : Grind.CommRing R] (a : R) (m n : Nat), a ^ (m * n) = (a ^ m) ^ n +AXIOMS [propext] +ROOT Aiur.NativeAIR.Domain.Algebra.power_period +∀ {R : Type} [inst : Grind.CommRing R] (a : R) {period : Nat}, a ^ period = 1 → ∀ (n : Nat), a ^ n = a ^ (n % period) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Domain.Algebra.power_inverse +∀ {R : Type} [inst : Grind.CommRing R] (a inverse : R), a * inverse = 1 → ∀ (n : Nat), a ^ n * inverse ^ n = 1 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Domain.Algebra.predecessor_inverse +∀ {R : Type} [inst : Grind.CommRing R] (a inverse : R) {n : Nat}, + 0 < n → a ^ n = 1 → a * inverse = 1 → a ^ (n - 1) = inverse +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.Algebra.dividedPowers_factor +∀ {R : Type} [inst : Grind.CommRing R] (x a : R) (n : Nat), + (x - a) * Aiur.NativeAIR.Domain.Algebra.dividedPowers x a n = x ^ n - a ^ n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.Algebra.dividedPowers_diagonal +∀ {R : Type} [inst : Grind.CommRing R] (a : R) (n : Nat), + Aiur.NativeAIR.Domain.Algebra.dividedPowers a a n = ↑n * a ^ (n - 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.Algebra.root_dividedPowers +∀ {R : Type} [inst : Grind.CommRing R] (x a : R) {n : Nat}, + a ^ n = 1 → (x - a) * Aiur.NativeAIR.Domain.Algebra.dividedPowers x a n = x ^ n - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.Algebra.dividedPowers_off_root +∀ {R : Type} [inst : Grind.CommRing R] (x a inverse : R) {n : Nat}, + a ^ n = 1 → (x - a) * inverse = 1 → (x ^ n - 1) * inverse = Aiur.NativeAIR.Domain.Algebra.dividedPowers x a n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.ofLogSize_some +∀ {bits : Nat} {domain : Aiur.NativeAIR.Domain.Subgroup}, + Aiur.NativeAIR.Domain.ofLogSize bits = some domain → ↑domain = bits +AXIOMS [] +ROOT Aiur.NativeAIR.Domain.ofLogSize_defined +∀ (bits : Nat), ((Aiur.NativeAIR.Domain.ofLogSize bits).isSome = true) = (bits < 33) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Domain.size_positive +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), 0 < Aiur.NativeAIR.Domain.size domain +AXIOMS [] +ROOT Aiur.NativeAIR.Domain.size_bound +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.Domain.size domain ≤ 2 ^ 32 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Domain.size_lt_characteristic +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.Domain.size domain < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Domain.size_lt_u64 +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.Domain.size domain < 2 ^ 64 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Domain.generator_zero +Aiur.NativeAIR.Domain.generator 0 = 1 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Domain.generator_square_certificate +∀ (index : Fin 32), + Aiur.NativeAIR.Domain.generator ⟨↑index + 1, ⋯⟩ * Aiur.NativeAIR.Domain.generator ⟨↑index + 1, ⋯⟩ = + Aiur.NativeAIR.Domain.generator ⟨↑index, ⋯⟩ +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Domain.generator_full_certificate +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + (Aiur.NativeAIR.Domain.generator domain).pow (Aiur.NativeAIR.Domain.size domain) = 1 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Domain.generator_half_certificate +∀ (index : Fin 32), (Aiur.NativeAIR.Domain.generator ⟨↑index + 1, ⋯⟩).pow (2 ^ ↑index) = 0 - 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Domain.generator_power +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + Aiur.NativeAIR.Domain.generator domain ^ Aiur.NativeAIR.Domain.size domain = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.generator_half +∀ (index : Fin 32), Aiur.NativeAIR.Domain.generator ⟨↑index + 1, ⋯⟩ ^ 2 ^ ↑index = 0 - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.generator_nonzero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.Domain.generator domain ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_eq +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.point domain index = Aiur.NativeAIR.Domain.generator domain ^ ↑index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_injective +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) {i j : Fin (Aiur.NativeAIR.Domain.size domain)}, + Aiur.NativeAIR.Domain.point domain i = Aiur.NativeAIR.Domain.point domain j → i = j +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.generator_order +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (n : Nat), + Aiur.NativeAIR.Domain.generator domain ^ n = 1 ↔ Aiur.NativeAIR.Domain.size domain ∣ n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_zero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.Domain.point domain ⟨0, ⋯⟩ = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_power +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.point domain index ^ Aiur.NativeAIR.Domain.size domain = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_nonzero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.point domain index ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_next +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.point domain ⟨(↑index + 1) % Aiur.NativeAIR.Domain.size domain, ⋯⟩ = + Aiur.NativeAIR.Domain.point domain index * Aiur.NativeAIR.Domain.generator domain +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_first_iff +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.point domain index = 1 ↔ ↑index = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.lastPoint_eq_power +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + Aiur.NativeAIR.Domain.lastPoint domain = + Aiur.NativeAIR.Domain.generator domain ^ (Aiur.NativeAIR.Domain.size domain - 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_last +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + Aiur.NativeAIR.Domain.point domain ⟨Aiur.NativeAIR.Domain.size domain - 1, ⋯⟩ = Aiur.NativeAIR.Domain.lastPoint domain +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.lastPoint_power +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + Aiur.NativeAIR.Domain.lastPoint domain ^ Aiur.NativeAIR.Domain.size domain = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.point_last_iff +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.point domain index = Aiur.NativeAIR.Domain.lastPoint domain ↔ + ↑index = Aiur.NativeAIR.Domain.size domain - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.lastPoint_nonzero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.Domain.lastPoint domain ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.lastPoint_inverse +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + Aiur.NativeAIR.Domain.lastPoint domain * Aiur.NativeAIR.Domain.generator domain = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.lastPoint_predecessor +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + Aiur.NativeAIR.Domain.lastPoint domain ^ (Aiur.NativeAIR.Domain.size domain - 1) = + Aiur.NativeAIR.Domain.generator domain +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.normalizer_nonzero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.Domain.normalizer domain ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.first_at_row +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.Algebra.dividedPowers (Aiur.NativeAIR.Domain.point domain index) 1 + (Aiur.NativeAIR.Domain.size domain) = + if ↑index = 0 then Aiur.G.ofNat (Aiur.NativeAIR.Domain.size domain) else 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.last_at_row +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.Algebra.dividedPowers (Aiur.NativeAIR.Domain.point domain index) + (Aiur.NativeAIR.Domain.lastPoint domain) (Aiur.NativeAIR.Domain.size domain) = + if ↑index = Aiur.NativeAIR.Domain.size domain - 1 then Aiur.NativeAIR.Domain.normalizer domain else 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.transition_at_row +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.point domain index - Aiur.NativeAIR.Domain.lastPoint domain = 0 ↔ + ↑index = Aiur.NativeAIR.Domain.size domain - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.ofBase_dividedPowers +∀ (x a : Aiur.G) (n : Nat), + Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.Algebra.dividedPowers x a n) = + Aiur.NativeAIR.Domain.Algebra.dividedPowers (Aiur.NativeAIR.ProofCodec.Extension.ofBase x) + (Aiur.NativeAIR.ProofCodec.Extension.ofBase a) n +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.vanishing_eq +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (value : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Domain.vanishing domain value = value ^ Aiur.NativeAIR.Domain.size domain - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.vanishing_at_row +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.vanishing domain + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.point domain index)) = + 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.lastPoint_extension_power +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), + Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.lastPoint domain) ^ + Aiur.NativeAIR.Domain.size domain = + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.root_difference_nonzero +∀ (x a : Aiur.NativeAIR.ProofCodec.Extension) {n : Nat}, a ^ n = 1 → x ^ n - 1 ≠ 0 → x - a ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.selectors_success +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (value : Aiur.NativeAIR.ProofCodec.Extension) + (selected : Aiur.NativeAIR.Domain.Selectors Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Domain.selectors domain value = some selected → + selected.isFirst = Aiur.NativeAIR.Domain.Algebra.dividedPowers value 1 (Aiur.NativeAIR.Domain.size domain) ∧ + selected.isLast = + Aiur.NativeAIR.Domain.Algebra.dividedPowers value + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.lastPoint domain)) + (Aiur.NativeAIR.Domain.size domain) ∧ + selected.isTransition = + value - Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.lastPoint domain) ∧ + Aiur.NativeAIR.Domain.vanishing domain value * selected.invVanishing = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.selectors_defined +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (value : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Domain.vanishing domain value ≠ 0 → + ∃ selected, Aiur.NativeAIR.Domain.selectors domain value = some selected +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.selectors_defined_iff +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (value : Aiur.NativeAIR.ProofCodec.Extension), + (∃ selected, Aiur.NativeAIR.Domain.selectors domain value = some selected) ↔ + Aiur.NativeAIR.Domain.vanishing domain value ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Domain.selectors_none_at_row +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.Domain.selectors domain + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.point domain index)) = + none +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.normalized_injection +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)) + (delta : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), + (delta.scale (Aiur.NativeAIR.Domain.normalizer domain).inverse).scale + (Aiur.NativeAIR.Domain.Algebra.dividedPowers (Aiur.NativeAIR.Domain.point domain index) + (Aiur.NativeAIR.Domain.lastPoint domain) (Aiur.NativeAIR.Domain.size domain)) = + if ↑index = Aiur.NativeAIR.Domain.size domain - 1 then delta else 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.equations_domain_row +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)) + {lookups : List (Aiur.G × List Aiur.G)} {stageCurrent stageNext publics deltaScaled : Array Aiur.G} {groupSize : Nat} + {result : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G)} + {beta gamma delta : Aiur.NativeAIR.LogUp.Coordinates Aiur.G}, + Aiur.NativeAIR.LogUp.Coordinates.read publics 0 = some beta → + Aiur.NativeAIR.LogUp.Coordinates.read publics 1 = some gamma → + Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 = + some (delta.scale (Aiur.NativeAIR.Domain.normalizer domain).inverse) → + Aiur.NativeAIR.LogUp.equations lookups stageCurrent stageNext publics deltaScaled + (Aiur.NativeAIR.Domain.Algebra.dividedPowers (Aiur.NativeAIR.Domain.point domain index) + (Aiur.NativeAIR.Domain.lastPoint domain) (Aiur.NativeAIR.Domain.size domain)) + groupSize = + some result → + (∀ (value : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), value ∈ result → value = 0) → + Aiur.NativeAIR.LogUp.PoleFree + (Aiur.NativeAIR.LogUp.fieldEntries (Aiur.NativeAIR.LogUp.compress beta gamma lookups)) → + ∃ first next, + Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent 0 = some first ∧ + Aiur.NativeAIR.LogUp.Coordinates.read stageNext 0 = some next ∧ + (next.toExtension - first.toExtension + + if ↑index = Aiur.NativeAIR.Domain.size domain - 1 then delta.toExtension else 0) = + Aiur.NativeAIR.LogUp.lookupFractions beta gamma lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.equations_domain_sum +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) + (lookups : Fin (Aiur.NativeAIR.Domain.size domain) → List (Aiur.G × List Aiur.G)) + (stageRows : Fin (Aiur.NativeAIR.Domain.size domain) → Array Aiur.G) (publics deltaScaled : Array Aiur.G) + (groupSize : Nat) (beta gamma delta : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), + Aiur.NativeAIR.LogUp.Coordinates.read publics 0 = some beta → + Aiur.NativeAIR.LogUp.Coordinates.read publics 1 = some gamma → + Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 = + some (delta.scale (Aiur.NativeAIR.Domain.normalizer domain).inverse) → + (∀ (index : Fin (Aiur.NativeAIR.Domain.size domain)), + ∃ result, + Aiur.NativeAIR.LogUp.equations (lookups index) (stageRows index) + (stageRows ⟨(↑index + 1) % Aiur.NativeAIR.Domain.size domain, ⋯⟩) publics deltaScaled + (Aiur.NativeAIR.Domain.Algebra.dividedPowers (Aiur.NativeAIR.Domain.point domain index) + (Aiur.NativeAIR.Domain.lastPoint domain) (Aiur.NativeAIR.Domain.size domain)) + groupSize = + some result ∧ + ∀ (value : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), value ∈ result → value = 0) → + (∀ (index : Fin (Aiur.NativeAIR.Domain.size domain)), + Aiur.NativeAIR.LogUp.PoleFree + (Aiur.NativeAIR.LogUp.fieldEntries (Aiur.NativeAIR.LogUp.compress beta gamma (lookups index)))) → + Aiur.NativeAIR.LogUp.sum + (List.ofFn fun index => Aiur.NativeAIR.LogUp.lookupFractions beta gamma (lookups index)) = + delta.toExtension +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.LogUp.constraintValues_domain_sum +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (lookups : List Aiur.NativeAIR.Lookup) + (nodeRows stageRows : Fin (Aiur.NativeAIR.Domain.size domain) → Array Aiur.G) (publics deltaScaled : Array Aiur.G) + (groupSize : Nat) (beta gamma delta : Aiur.NativeAIR.LogUp.Coordinates Aiur.G), + Aiur.NativeAIR.LogUp.Coordinates.read publics 0 = some beta → + Aiur.NativeAIR.LogUp.Coordinates.read publics 1 = some gamma → + Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 = + some (delta.scale (Aiur.NativeAIR.Domain.normalizer domain).inverse) → + (∀ (index : Fin (Aiur.NativeAIR.Domain.size domain)), + ∃ result, + Aiur.NativeAIR.LogUp.constraintValues lookups (nodeRows index) (stageRows index) + (stageRows ⟨(↑index + 1) % Aiur.NativeAIR.Domain.size domain, ⋯⟩) publics deltaScaled + (Aiur.NativeAIR.Domain.Algebra.dividedPowers (Aiur.NativeAIR.Domain.point domain index) + (Aiur.NativeAIR.Domain.lastPoint domain) (Aiur.NativeAIR.Domain.size domain)) + groupSize = + some result ∧ + ∀ (value : Aiur.G), value ∈ result → value = 0) → + (∀ (index : Fin (Aiur.NativeAIR.Domain.size domain)) (values : List (Aiur.G × List Aiur.G)), + List.mapM (Aiur.NativeAIR.readLookup (nodeRows index)) lookups = some values → + Aiur.NativeAIR.LogUp.PoleFree + (Aiur.NativeAIR.LogUp.fieldEntries (Aiur.NativeAIR.LogUp.compress beta gamma values))) → + ∃ values, + (∀ (index : Fin (Aiur.NativeAIR.Domain.size domain)), + List.mapM (Aiur.NativeAIR.readLookup (nodeRows index)) lookups = some (values index)) ∧ + Aiur.NativeAIR.LogUp.sum + (List.ofFn fun index => Aiur.NativeAIR.LogUp.lookupFractions beta gamma (values index)) = + delta.toExtension +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.horner_nil +∀ {W : Type} [inst : Grind.CommRing W] (point : W), Aiur.NativeAIR.Quotient.horner point [] = 0 +AXIOMS [] +ROOT Aiur.NativeAIR.Quotient.horner_cons +∀ {W : Type} [inst : Grind.CommRing W] (point first : W) (rest : List W), + Aiur.NativeAIR.Quotient.horner point (first :: rest) = first + point * Aiur.NativeAIR.Quotient.horner point rest +AXIOMS [] +ROOT Aiur.NativeAIR.Quotient.horner_append +∀ {W : Type} [inst : Grind.CommRing W] (point : W) (left right : List W), + Aiur.NativeAIR.Quotient.horner point (left ++ right) = + Aiur.NativeAIR.Quotient.horner point left + point ^ left.length * Aiur.NativeAIR.Quotient.horner point right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.horner_powers +∀ {W : Type} [inst : Grind.CommRing W] (point : W) (values : List W) (offset : Nat), + point ^ offset * Aiur.NativeAIR.Quotient.horner point values = + Aiur.NativeAIR.LogUp.sum + (List.map + (fun x => + match x with + | (value, index) => point ^ index * value) + (values.zipIdx offset)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.composition_from +∀ {W : Type} [inst : Grind.CommRing W] (point initial : W) (values : List W), + List.foldl (fun accumulated value => accumulated * point + value) initial values = + initial * point ^ values.length + Aiur.NativeAIR.Quotient.horner point values.reverse +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.composition_horner +∀ {W : Type} [inst : Grind.CommRing W] (point : W) (values : List W), + Aiur.NativeAIR.Quotient.composition point values = Aiur.NativeAIR.Quotient.horner point values.reverse +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.composition_order +∀ {W : Type} [inst : Grind.CommRing W] (point : W) (values : List W), + Aiur.NativeAIR.Quotient.composition point values = + Aiur.NativeAIR.LogUp.sum + (List.map + (fun x => + match x with + | (value, index) => point ^ index * value) + values.reverse.zipIdx) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.composition_append +∀ {W : Type} [inst : Grind.CommRing W] (point : W) (user lookup : List W), + Aiur.NativeAIR.Quotient.composition point (user ++ lookup) = + Aiur.NativeAIR.Quotient.composition point user * point ^ lookup.length + + Aiur.NativeAIR.Quotient.composition point lookup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.composition_zero +∀ {W : Type} [inst : Grind.CommRing W] (point : W) (values : List W), + (∀ (value : W), value ∈ values → value = 0) → Aiur.NativeAIR.Quotient.composition point values = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.inverse_check +∀ {W : Type} [inst : Grind.CommRing W] (vanishing inverse composition quotient : W), + vanishing * inverse = 1 → (composition * inverse = quotient ↔ composition = vanishing * quotient) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.coefficients_flatten +∀ (pairs : List (Aiur.NativeAIR.LogUp.Coordinates Aiur.NativeAIR.ProofCodec.Extension)), + Aiur.NativeAIR.Quotient.coefficients (Aiur.NativeAIR.LogUp.Coordinates.flatten pairs) = + some (List.map (fun pair => pair.c0 + pair.c1 * Aiur.NativeAIR.ProofCodec.Extension.basis) pairs) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Quotient.coefficients_success +∀ {row values : List Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Quotient.coefficients row = some values → + ∃ pairs, + row = Aiur.NativeAIR.LogUp.Coordinates.flatten pairs ∧ + values = List.map (fun pair => pair.c0 + pair.c1 * Aiur.NativeAIR.ProofCodec.Extension.basis) pairs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.coefficients_length +∀ {row values : List Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Quotient.coefficients row = some values → row.length = 2 * values.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.coefficients_defined +∀ (row : List Aiur.NativeAIR.ProofCodec.Extension), + row.length % 2 = 0 → ∃ values, Aiur.NativeAIR.Quotient.coefficients row = some values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.coefficients_defined_iff +∀ (row : List Aiur.NativeAIR.ProofCodec.Extension), + (∃ values, Aiur.NativeAIR.Quotient.coefficients row = some values) ↔ row.length % 2 = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.evaluate_success +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (point : Aiur.NativeAIR.ProofCodec.Extension) + {row : List Aiur.NativeAIR.ProofCodec.Extension} {value : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Quotient.evaluate domain point row = some value → + ∃ values, + Aiur.NativeAIR.Quotient.coefficients row = some values ∧ + value = Aiur.NativeAIR.Quotient.horner (point ^ Aiur.NativeAIR.Domain.size domain) values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.evaluate_powers +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (point : Aiur.NativeAIR.ProofCodec.Extension) + {row : List Aiur.NativeAIR.ProofCodec.Extension} {value : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Quotient.evaluate domain point row = some value → + ∃ pairs, + row = Aiur.NativeAIR.LogUp.Coordinates.flatten pairs ∧ + value = + Aiur.NativeAIR.LogUp.sum + (List.map + (fun x => + match x with + | (pair, index) => + point ^ (Aiur.NativeAIR.Domain.size domain * index) * + (pair.c0 + pair.c1 * Aiur.NativeAIR.ProofCodec.Extension.basis)) + pairs.zipIdx) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Quotient.check_true_iff +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (point alpha : Aiur.NativeAIR.ProofCodec.Extension) + (constraints row : List Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Quotient.check domain point alpha constraints row = some true ↔ + Aiur.NativeAIR.Domain.vanishing domain point ≠ 0 ∧ + ∃ values, + Aiur.NativeAIR.Quotient.coefficients row = some values ∧ + Aiur.NativeAIR.Quotient.composition alpha constraints = + Aiur.NativeAIR.Domain.vanishing domain point * + Aiur.NativeAIR.Quotient.horner (point ^ Aiur.NativeAIR.Domain.size domain) values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.preprocessedIndices_none +∀ (program : Aiur.Bytecode.Toplevel) (index : Nat), + (Aiur.NativeAIR.CompiledKey.preprocessedIndices program)[index]? = some none ↔ + index < program.circuits.size + program.memorySizes.size +AXIOMS [propext] +ROOT Aiur.NativeAIR.CompiledKey.circuits_preprocessed_absent +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {result : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some result → + ∀ {index : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + result[index]? = some artifact → + (Aiur.NativeAIR.CompiledKey.preprocessedIndices program)[index]? = some none → artifact.preprocessedWidth = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.row_preprocessed_absent +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {proof : Aiur.NativeAIR.ProofCodec.Data} {index position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.Row.Sourced backend.keyData proof index position row → + row.preprocessed = none → row.circuit.preprocessedWidth = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.publics_size +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering leaving : Aiur.NativeAIR.ProofCodec.Extension), + (Aiur.NativeAIR.VerifierArithmetic.publics challenges entering leaving).size = 8 +AXIOMS [propext] +ROOT Aiur.NativeAIR.VerifierArithmetic.publics_beta +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering leaving : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.LogUp.Coordinates.read (Aiur.NativeAIR.VerifierArithmetic.publics challenges entering leaving) 0 = + some + (Aiur.NativeAIR.LogUp.Coordinates.map Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.beta)) +AXIOMS [propext] +ROOT Aiur.NativeAIR.VerifierArithmetic.publics_gamma +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering leaving : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.LogUp.Coordinates.read (Aiur.NativeAIR.VerifierArithmetic.publics challenges entering leaving) 1 = + some + (Aiur.NativeAIR.LogUp.Coordinates.map Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.gamma)) +AXIOMS [propext] +ROOT Aiur.NativeAIR.VerifierArithmetic.publics_entering +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering leaving : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.LogUp.Coordinates.read (Aiur.NativeAIR.VerifierArithmetic.publics challenges entering leaving) 2 = + some + (Aiur.NativeAIR.LogUp.Coordinates.map Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.LogUp.Coordinates.fromExtension entering)) +AXIOMS [propext] +ROOT Aiur.NativeAIR.VerifierArithmetic.publics_leaving +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering leaving : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.LogUp.Coordinates.read (Aiur.NativeAIR.VerifierArithmetic.publics challenges entering leaving) 3 = + some + (Aiur.NativeAIR.LogUp.Coordinates.map Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.LogUp.Coordinates.fromExtension leaving)) +AXIOMS [propext] +ROOT Aiur.NativeAIR.VerifierArithmetic.deltaScaled_size +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (entering leaving : Aiur.NativeAIR.ProofCodec.Extension), + (Aiur.NativeAIR.VerifierArithmetic.deltaScaled domain entering leaving).size = 2 +AXIOMS [propext] +ROOT Aiur.NativeAIR.VerifierArithmetic.deltaScaled_coordinates +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (entering leaving : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.LogUp.Coordinates.read (Aiur.NativeAIR.VerifierArithmetic.deltaScaled domain entering leaving) 0 = + some + (Aiur.NativeAIR.LogUp.Coordinates.map Aiur.NativeAIR.ProofCodec.Extension.ofBase + ((Aiur.NativeAIR.LogUp.Coordinates.fromExtension (leaving - entering)).scale + (Aiur.NativeAIR.Domain.normalizer domain).inverse)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.view_fits +∀ {parameters : Aiur.NativeAIR.KeyCodec.Parameters} {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.Row.Fits parameters row → + (row.preprocessed = none → row.circuit.preprocessedWidth = 0) → + ∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering : Aiur.NativeAIR.ProofCodec.Extension) + (selectors : Aiur.NativeAIR.Domain.Selectors Aiur.NativeAIR.ProofCodec.Extension), + (Aiur.NativeAIR.VerifierArithmetic.view challenges row entering selectors).Fits row.circuit.widths +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.domain_defined +∀ {parameters : Aiur.NativeAIR.KeyCodec.Parameters} {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.Row.Fits parameters row → + ∃ domain, Aiur.NativeAIR.Domain.ofLogSize row.logDegree.toNat = some domain +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.stage2_width +∀ {parameters : Aiur.NativeAIR.KeyCodec.Parameters} {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.Row.Fits parameters row → + 0 < row.circuit.lookupGroupSize → + Aiur.NativeAIR.LogUp.groupCount row.circuit.lookupGroupSize row.circuit.graph.lookups.length * 2 ≤ + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.current).size ∧ + 2 ≤ + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.next).size +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.evaluate_success +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {row : Aiur.NativeAIR.ProofShape.Row} + {entering : Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.VerifierArithmetic.Evaluation}, + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result → + Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads challenges row entering result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.evaluate +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {row : Aiur.NativeAIR.ProofShape.Row} + {entering : Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.VerifierArithmetic.Evaluation}, + Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads challenges row entering result → + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.evaluate_defined +∀ {parameters : Aiur.NativeAIR.KeyCodec.Parameters} {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.Row.Fits parameters row → + row.circuit.valid = true → + (row.preprocessed = none → row.circuit.preprocessedWidth = 0) → + ∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering : Aiur.NativeAIR.ProofCodec.Extension) + {domain : Aiur.NativeAIR.Domain.Subgroup}, + Aiur.NativeAIR.Domain.ofLogSize row.logDegree.toNat = some domain → + Aiur.NativeAIR.Domain.vanishing domain challenges.zeta ≠ 0 → + ∃ result, Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.evaluate_defined_iff +∀ {parameters : Aiur.NativeAIR.KeyCodec.Parameters} {row : Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.ProofShape.Row.Fits parameters row → + row.circuit.valid = true → + (row.preprocessed = none → row.circuit.preprocessedWidth = 0) → + ∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering : Aiur.NativeAIR.ProofCodec.Extension), + (∃ result, Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result) ↔ + ∃ domain, + Aiur.NativeAIR.Domain.ofLogSize row.logDegree.toNat = some domain ∧ + Aiur.NativeAIR.Domain.vanishing domain challenges.zeta ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.evaluate_constraint_count +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {row : Aiur.NativeAIR.ProofShape.Row} + {entering : Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.VerifierArithmetic.Evaluation}, + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result → + 0 < row.circuit.lookupGroupSize → result.constraints.length = row.circuit.constraintCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.evaluate_reflects +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {row : Aiur.NativeAIR.ProofShape.Row} + {entering : Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.VerifierArithmetic.Evaluation}, + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result → + Aiur.NativeAIR.Graph.Valid row.circuit.widths row.circuit.graph → + ∃ trees lookups coordinates, + row.circuit.graph.unfold = some trees ∧ + Aiur.NativeAIR.Reflects Aiur.NativeAIR.ProofCodec.Extension.evalOps + (Aiur.NativeAIR.VerifierArithmetic.view challenges row entering result.selectors) trees + result.nodeValues ∧ + Aiur.NativeAIR.evalRoots Aiur.NativeAIR.ProofCodec.Extension.evalOps + (Aiur.NativeAIR.VerifierArithmetic.view challenges row entering result.selectors) trees + row.circuit.graph.zeros = + some result.userValues ∧ + List.mapM + (Aiur.NativeAIR.evalLookup Aiur.NativeAIR.ProofCodec.Extension.evalOps + (Aiur.NativeAIR.VerifierArithmetic.view challenges row entering result.selectors) trees) + row.circuit.graph.lookups = + some lookups ∧ + Aiur.NativeAIR.LogUp.equations lookups + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.current) + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.next) + (Aiur.NativeAIR.VerifierArithmetic.publics challenges entering row.accumulator) + (Aiur.NativeAIR.VerifierArithmetic.deltaScaled result.domain entering row.accumulator) + result.selectors.isLast row.circuit.lookupGroupSize = + some coordinates ∧ + result.lookupValues = Aiur.NativeAIR.LogUp.Coordinates.flatten coordinates +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.identity +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {row : Aiur.NativeAIR.ProofShape.Row} + {entering : Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.VerifierArithmetic.Evaluation}, + Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads challenges row entering result → + (result.accepts challenges.alpha = true ↔ + Aiur.NativeAIR.Quotient.composition challenges.alpha result.constraints = + Aiur.NativeAIR.Domain.vanishing result.domain challenges.zeta * result.quotientValue) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.check_true_iff +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (row : Aiur.NativeAIR.ProofShape.Row) + (entering : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.VerifierArithmetic.check challenges row entering = some true ↔ + ∃ result, + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result ∧ + Aiur.NativeAIR.Quotient.composition challenges.alpha result.constraints = + Aiur.NativeAIR.Domain.vanishing result.domain challenges.zeta * result.quotientValue +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.check_quotient +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {row : Aiur.NativeAIR.ProofShape.Row} + {entering : Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.VerifierArithmetic.Evaluation}, + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result → + Aiur.NativeAIR.VerifierArithmetic.check challenges row entering = + Aiur.NativeAIR.Quotient.check result.domain challenges.zeta challenges.alpha result.constraints row.quotient +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.checked_row_arithmetic +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof backend.keyData bytes) {position : Nat} + {row : Aiur.NativeAIR.ProofShape.Row}, + checked.rows[position]? = some row → + ∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (entering : Aiur.NativeAIR.ProofCodec.Extension), + ∃ domain, + Aiur.NativeAIR.Domain.ofLogSize row.logDegree.toNat = some domain ∧ + ((∃ result, Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering = some result) ↔ + Aiur.NativeAIR.Domain.vanishing domain challenges.zeta ≠ 0) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.claimMessage_native +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (claim : List Aiur.G), + Aiur.NativeAIR.VerifierArithmetic.claimMessage challenges claim = + challenges.beta + + List.foldr + (fun arg accumulated => accumulated * challenges.gamma + Aiur.NativeAIR.ProofCodec.Extension.ofBase arg) 0 claim +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.publicEntries_compress +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (claims : List (List Aiur.G)), + Aiur.NativeAIR.LogUp.fieldEntries + (Aiur.NativeAIR.LogUp.compress (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.beta) + (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.gamma) (List.map (fun claim => (1, claim)) claims)) = + Aiur.NativeAIR.VerifierArithmetic.publicEntries challenges claims +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_nil +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges), + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges [] = some 0 +AXIOMS [propext] +ROOT Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_cons +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (claim : List Aiur.G) (claims : List (List Aiur.G)), + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges (claim :: claims) = do + let inverse ← (Aiur.NativeAIR.VerifierArithmetic.claimMessage challenges claim).tryInverse + let rest ← Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims + pure (inverse + rest) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_success +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {claims : List (List Aiur.G)} + {accumulator : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims = some accumulator → + Aiur.NativeAIR.LogUp.PoleFree (Aiur.NativeAIR.VerifierArithmetic.publicEntries challenges claims) ∧ + accumulator = Aiur.NativeAIR.LogUp.fractionSum (Aiur.NativeAIR.VerifierArithmetic.publicEntries challenges claims) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_defined +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (claims : List (List Aiur.G)), + Aiur.NativeAIR.LogUp.PoleFree (Aiur.NativeAIR.VerifierArithmetic.publicEntries challenges claims) → + ∃ accumulator, Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims = some accumulator +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_defined_iff +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (claims : List (List Aiur.G)), + (∃ accumulator, Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims = some accumulator) ↔ + Aiur.NativeAIR.LogUp.PoleFree (Aiur.NativeAIR.VerifierArithmetic.publicEntries challenges claims) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.initialAccumulator_lookupFractions +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {claims : List (List Aiur.G)} + {accumulator : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims = some accumulator → + accumulator = + Aiur.NativeAIR.LogUp.lookupFractions (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.beta) + (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.gamma) (List.map (fun claim => (1, claim)) claims) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.checkRows_cons +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (row : Aiur.NativeAIR.ProofShape.Row) + (rows : List Aiur.NativeAIR.ProofShape.Row) (entering final : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.VerifierArithmetic.checkRows challenges (row :: rows) entering = some final ↔ + Aiur.NativeAIR.VerifierArithmetic.check challenges row entering = some true ∧ + Aiur.NativeAIR.VerifierArithmetic.checkRows challenges rows row.accumulator = some final +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.checkRows_final +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {rows : List Aiur.NativeAIR.ProofShape.Row} + {entering final : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.VerifierArithmetic.checkRows challenges rows entering = some final → + List.foldl (fun x row => row.accumulator) entering rows = final +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.checkRows_row +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {rows : List Aiur.NativeAIR.ProofShape.Row} + {entering final : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.VerifierArithmetic.checkRows challenges rows entering = some final → + ∀ {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + rows[position]? = some row → + ∃ before, + (entering :: List.map (fun x => x.accumulator) rows)[position]? = some before ∧ + Aiur.NativeAIR.VerifierArithmetic.check challenges row before = some true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.checkRows_sum +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {rows : List Aiur.NativeAIR.ProofShape.Row} + {entering final : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.VerifierArithmetic.checkRows challenges rows entering = some final → + ∀ (fraction : Aiur.NativeAIR.ProofShape.Row → Aiur.NativeAIR.ProofCodec.Extension), + (∀ (row : Aiur.NativeAIR.ProofShape.Row), + row ∈ rows → + ∀ (before : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.VerifierArithmetic.check challenges row before = some true → + fraction row = row.accumulator - before) → + Aiur.NativeAIR.LogUp.sum (List.map fraction rows) = final - entering +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.verify_true_iff +∀ (challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges) (claims : List (List Aiur.G)) + (rows : List Aiur.NativeAIR.ProofShape.Row), + Aiur.NativeAIR.VerifierArithmetic.verify challenges claims rows = some true ↔ + rows ≠ [] ∧ + ∃ entering, + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims = some entering ∧ + Aiur.NativeAIR.VerifierArithmetic.checkRows challenges rows entering = some 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.verify_lookup_balance +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {claims : List (List Aiur.G)} + {rows : List Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.VerifierArithmetic.verify challenges claims rows = some true → + ∀ (fraction : Aiur.NativeAIR.ProofShape.Row → Aiur.NativeAIR.ProofCodec.Extension), + (∀ (row : Aiur.NativeAIR.ProofShape.Row), + row ∈ rows → + ∀ (before : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.VerifierArithmetic.check challenges row before = some true → + fraction row = row.accumulator - before) → + Aiur.NativeAIR.LogUp.lookupFractions (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.beta) + (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.gamma) + (List.map (fun claim => (1, claim)) claims) + + Aiur.NativeAIR.LogUp.sum (List.map fraction rows) = + 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.VerifierArithmetic.verify_row +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {claims : List (List Aiur.G)} + {rows : List Aiur.NativeAIR.ProofShape.Row}, + Aiur.NativeAIR.VerifierArithmetic.verify challenges claims rows = some true → + ∀ {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + rows[position]? = some row → + ∃ initial before result, + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims = some initial ∧ + (initial :: List.map (fun x => x.accumulator) rows)[position]? = some before ∧ + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row before = some result ∧ + Aiur.NativeAIR.Quotient.composition challenges.alpha result.constraints = + Aiur.NativeAIR.Domain.vanishing result.domain challenges.zeta * result.quotientValue +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.checked_row_values +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof backend.keyData bytes) + {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {claims : List (List Aiur.G)}, + Aiur.NativeAIR.VerifierArithmetic.verify challenges claims checked.rows = some true → + ∀ {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + checked.rows[position]? = some row → + Aiur.NativeAIR.ProofShape.Row.Sourced backend.keyData checked.data row.circuitIndex position row ∧ + Aiur.NativeAIR.ProofShape.Row.Fits backend.keyData.parameters row ∧ + ∃ initial before result trees lookups coordinates, + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims = some initial ∧ + (initial :: List.map (fun x => x.accumulator) checked.rows)[position]? = some before ∧ + Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row before = some result ∧ + row.circuit.graph.unfold = some trees ∧ + Aiur.NativeAIR.evalRoots Aiur.NativeAIR.ProofCodec.Extension.evalOps + (Aiur.NativeAIR.VerifierArithmetic.view challenges row before result.selectors) trees + row.circuit.graph.zeros = + some result.userValues ∧ + List.mapM + (Aiur.NativeAIR.evalLookup Aiur.NativeAIR.ProofCodec.Extension.evalOps + (Aiur.NativeAIR.VerifierArithmetic.view challenges row before result.selectors) trees) + row.circuit.graph.lookups = + some lookups ∧ + Aiur.NativeAIR.LogUp.equations lookups + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.current) + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.next) + (Aiur.NativeAIR.VerifierArithmetic.publics challenges before row.accumulator) + (Aiur.NativeAIR.VerifierArithmetic.deltaScaled result.domain before row.accumulator) + result.selectors.isLast row.circuit.lookupGroupSize = + some coordinates ∧ + result.lookupValues = Aiur.NativeAIR.LogUp.Coordinates.flatten coordinates ∧ + Aiur.NativeAIR.Quotient.composition challenges.alpha result.constraints = + Aiur.NativeAIR.Domain.vanishing result.domain challenges.zeta * result.quotientValue +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.initial_valid +∀ (seed : List UInt8), (Aiur.NativeAIR.Challenger.initial seed).Valid +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.State.Valid.bound +∀ {state : Aiur.NativeAIR.Challenger.State}, state.Valid → state.pending.length ≤ 32 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.observeBytes_nil +∀ (state : Aiur.NativeAIR.Challenger.State), Aiur.NativeAIR.Challenger.observeBytes state [] = state +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeBytes_append +∀ (state : Aiur.NativeAIR.Challenger.State) (left right : List UInt8), + Aiur.NativeAIR.Challenger.observeBytes state (left ++ right) = + Aiur.NativeAIR.Challenger.observeBytes (Aiur.NativeAIR.Challenger.observeBytes state left) right +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.observeBytes_value +∀ (state : Aiur.NativeAIR.Challenger.State) (bytes : List UInt8), + Aiur.NativeAIR.Challenger.observeBytes state bytes = + if bytes.isEmpty = true then state else { input := state.input ++ bytes, pending := [] } +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeBytes_fold +∀ (state : Aiur.NativeAIR.Challenger.State) (bytes : List UInt8), + Aiur.NativeAIR.Challenger.observeBytes state bytes = List.foldl Aiur.NativeAIR.Challenger.observeByte state bytes +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.observeBytes_valid +∀ {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → ∀ (bytes : List UInt8), (Aiur.NativeAIR.Challenger.observeBytes state bytes).Valid +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeField_value +∀ (state : Aiur.NativeAIR.Challenger.State) (value : Aiur.G), + Aiur.NativeAIR.Challenger.observeField state value = + { input := state.input ++ Aiur.NativeAIR.ProofCodec.encodeField value, pending := [] } +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeField_valid +∀ {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → ∀ (value : Aiur.G), (Aiur.NativeAIR.Challenger.observeField state value).Valid +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeExtension_bytes +∀ (state : Aiur.NativeAIR.Challenger.State) (value : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Challenger.observeExtension state value = + Aiur.NativeAIR.Challenger.observeBytes state (Aiur.NativeAIR.ProofCodec.encodeExtension value) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.observeExtension_valid +∀ {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → + ∀ (value : Aiur.NativeAIR.ProofCodec.Extension), (Aiur.NativeAIR.Challenger.observeExtension state value).Valid +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeExtensions_valid +∀ {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → + ∀ (values : List Aiur.NativeAIR.ProofCodec.Extension), + (List.foldl Aiur.NativeAIR.Challenger.observeExtension state values).Valid +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeCap_empty +∀ (state : Aiur.NativeAIR.Challenger.State), Aiur.NativeAIR.Challenger.observeCap state [] = state +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.observeCap_valid +∀ {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → ∀ (cap : Aiur.NativeAIR.KeyCodec.MerkleCap), (Aiur.NativeAIR.Challenger.observeCap state cap).Valid +AXIOMS [] +ROOT Aiur.NativeAIR.Challenger.sampleByte_buffered +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (input : List UInt8) (byte : UInt8) (rest : List UInt8), + Aiur.NativeAIR.Challenger.sampleByte hash { input := input, pending := byte :: rest } = + (byte, { input := input, pending := rest }) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleByte_refill +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (input : List UInt8), + Aiur.NativeAIR.Challenger.sampleByte hash { input := input, pending := [] } = + (hash input 31, { input := List.ofFn (hash input), pending := List.drop 1 (List.ofFn (hash input)).reverse }) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleByte_valid +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → (Aiur.NativeAIR.Challenger.sampleByte hash state).snd.Valid +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.digest_reverse +∀ (digest : Fin 32 → UInt8), (List.ofFn digest).reverse = digest 31 :: List.drop 1 (List.ofFn digest).reverse +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleByte_pending_bound +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (state : Aiur.NativeAIR.Challenger.State), + state.pending.length ≤ 32 → (Aiur.NativeAIR.Challenger.sampleByte hash state).snd.pending.length ≤ 32 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleBytes_length +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (count : Nat) (state : Aiur.NativeAIR.Challenger.State), + (Aiur.NativeAIR.Challenger.sampleBytes hash count state).fst.length = count +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleBytes_pending_bound +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (count : Nat) (state : Aiur.NativeAIR.Challenger.State), + state.pending.length ≤ 32 → (Aiur.NativeAIR.Challenger.sampleBytes hash count state).snd.pending.length ≤ 32 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleBytes_valid +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (count : Nat) {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → (Aiur.NativeAIR.Challenger.sampleBytes hash count state).snd.Valid +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleBytes_buffered +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (input bytes rest : List UInt8), + Aiur.NativeAIR.Challenger.sampleBytes hash bytes.length { input := input, pending := bytes ++ rest } = + (bytes, { input := input, pending := rest }) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleBytes_refill +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (input : List UInt8), + Aiur.NativeAIR.Challenger.sampleBytes hash 32 { input := input, pending := [] } = + ((List.ofFn (hash input)).reverse, { input := List.ofFn (hash input), pending := [] }) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.littleEndian_bound +∀ (bytes : List UInt8), Aiur.NativeAIR.Challenger.littleEndian bytes < 256 ^ bytes.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.littleEndian_encode +∀ (count value : Nat), + value < 256 ^ count → Aiur.NativeAIR.Challenger.littleEndian (Aiur.NativeAIR.KeyCodec.encodeNat count value) = value +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.littleEndian_reads +∀ (bytes : List UInt8), + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.KeyCodec.readNat bytes.length) bytes + (Aiur.NativeAIR.Challenger.littleEndian bytes) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleWord_bound +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (state : Aiur.NativeAIR.Challenger.State), + (Aiur.NativeAIR.Challenger.sampleWord hash state).fst < 2 ^ 64 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleWord_full_mask +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (state : Aiur.NativeAIR.Challenger.State), + (Aiur.NativeAIR.Challenger.sampleWord hash state).fst &&& 2 ^ 64 - 1 = + (Aiur.NativeAIR.Challenger.sampleWord hash state).fst +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleWord_reads +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (state : Aiur.NativeAIR.Challenger.State), + Aiur.NativeAIR.KeyCodec.Reads (Aiur.NativeAIR.KeyCodec.readNat 8) + (Aiur.NativeAIR.Challenger.sampleBytes hash 8 state).fst (Aiur.NativeAIR.Challenger.sampleWord hash state).fst +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.FieldSample.positive +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {state final : Aiur.NativeAIR.Challenger.State} {count : Nat} + {value : Aiur.G}, Aiur.NativeAIR.Challenger.FieldSample hash state count value final → 0 < count +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleField_success +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {state final : Aiur.NativeAIR.Challenger.State} + {value : Aiur.G}, + Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (value, final) → + ∃ count, count ≤ fuel ∧ Aiur.NativeAIR.Challenger.FieldSample hash state count value final +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.FieldSample.complete +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {state final : Aiur.NativeAIR.Challenger.State} {count : Nat} + {value : Aiur.G}, + Aiur.NativeAIR.Challenger.FieldSample hash state count value final → + ∀ (fuel : Nat), count ≤ fuel → Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (value, final) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleField_iff +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (fuel : Nat) (state final : Aiur.NativeAIR.Challenger.State) + (value : Aiur.G), + Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (value, final) ↔ + ∃ count, count ≤ fuel ∧ Aiur.NativeAIR.Challenger.FieldSample hash state count value final +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleField_mono +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel more : Nat} {state final : Aiur.NativeAIR.Challenger.State} + {value : Aiur.G}, + Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (value, final) → + fuel ≤ more → Aiur.NativeAIR.Challenger.sampleField hash more state = some (value, final) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleField_unique +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel other : Nat} {state left right : Aiur.NativeAIR.Challenger.State} + {a b : Aiur.G}, + Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (a, left) → + Aiur.NativeAIR.Challenger.sampleField hash other state = some (b, right) → a = b ∧ left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.FieldSample.valid +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {state final : Aiur.NativeAIR.Challenger.State} {count : Nat} + {value : Aiur.G}, Aiur.NativeAIR.Challenger.FieldSample hash state count value final → state.Valid → final.Valid +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleField_valid +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {state final : Aiur.NativeAIR.Challenger.State} + {value : Aiur.G}, + Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (value, final) → state.Valid → final.Valid +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleField_canonical +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {state final : Aiur.NativeAIR.Challenger.State} + {value : Aiur.G}, + Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (value, final) → + ∃ before, Aiur.NativeAIR.Challenger.sampleWord hash before = (value.n, final) ∧ value.n < Aiur.gSize.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleExtension_success +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {state final : Aiur.NativeAIR.Challenger.State} + {value : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Challenger.sampleExtension hash fuel state = some (value, final) → + ∃ next, + Aiur.NativeAIR.Challenger.sampleField hash fuel state = some (value.c0, next) ∧ + Aiur.NativeAIR.Challenger.sampleField hash fuel next = some (value.c1, final) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleExtension_mono +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel more : Nat} {state final : Aiur.NativeAIR.Challenger.State} + {value : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Challenger.sampleExtension hash fuel state = some (value, final) → + fuel ≤ more → Aiur.NativeAIR.Challenger.sampleExtension hash more state = some (value, final) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleExtension_valid +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {state final : Aiur.NativeAIR.Challenger.State} + {value : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Challenger.sampleExtension hash fuel state = some (value, final) → state.Valid → final.Valid +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleBits_success +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {bits value : Nat} {state final : Aiur.NativeAIR.Challenger.State}, + Aiur.NativeAIR.Challenger.sampleBits hash bits state = some (value, final) → + bits < 64 ∧ + 2 ^ bits < Aiur.gSize.toNat ∧ + value = (Aiur.NativeAIR.Challenger.sampleWord hash state).fst % 2 ^ bits ∧ + final = (Aiur.NativeAIR.Challenger.sampleWord hash state).snd ∧ value < 2 ^ bits +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleBits_zero +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (state : Aiur.NativeAIR.Challenger.State), + Aiur.NativeAIR.Challenger.sampleBits hash 0 state = some (0, (Aiur.NativeAIR.Challenger.sampleWord hash state).snd) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.sampleBits_mask +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {bits value : Nat} {state final : Aiur.NativeAIR.Challenger.State}, + Aiur.NativeAIR.Challenger.sampleBits hash bits state = some (value, final) → + value = (Aiur.NativeAIR.Challenger.sampleWord hash state).fst &&& 2 ^ bits - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.sampleBits_valid +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {bits value : Nat} {state final : Aiur.NativeAIR.Challenger.State}, + Aiur.NativeAIR.Challenger.sampleBits hash bits state = some (value, final) → state.Valid → final.Valid +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.checkWitness_zero +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (witness : Aiur.G) (state : Aiur.NativeAIR.Challenger.State), + Aiur.NativeAIR.Challenger.checkWitness hash 0 witness state = some (true, state) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.checkWitness_positive +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) {bits : Nat}, + bits ≠ 0 → + ∀ (witness : Aiur.G) (state : Aiur.NativeAIR.Challenger.State), + Aiur.NativeAIR.Challenger.checkWitness hash bits witness state = do + let __x ← Aiur.NativeAIR.Challenger.sampleBits hash bits (Aiur.NativeAIR.Challenger.observeField state witness) + match __x with + | (value, next) => pure (value == 0, next) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Challenger.checkWitness_true_iff +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (bits : Nat) (witness : Aiur.G) + (state final : Aiur.NativeAIR.Challenger.State), + Aiur.NativeAIR.Challenger.checkWitness hash bits witness state = some (true, final) ↔ + bits = 0 ∧ final = state ∨ + bits ≠ 0 ∧ + Aiur.NativeAIR.Challenger.sampleBits hash bits (Aiur.NativeAIR.Challenger.observeField state witness) = + some (0, final) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Challenger.checkWitness_valid +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {bits : Nat} {witness : Aiur.G} + {state final : Aiur.NativeAIR.Challenger.State} {accepted : Bool}, + Aiur.NativeAIR.Challenger.checkWitness hash bits witness state = some (accepted, final) → state.Valid → final.Valid +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.seed_length +∀ (parameters : Aiur.NativeAIR.KeyCodec.Parameters), (Aiur.NativeAIR.Transcript.seed parameters).length = 70 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Transcript.circuitShape_length +∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), (Aiur.NativeAIR.Transcript.circuitShape circuit).length = 7 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Transcript.shape_length +∀ (key : Aiur.NativeAIR.KeyCodec.Key), (Aiur.NativeAIR.Transcript.shape key).length = 1 + 7 * key.circuits.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.fieldsBytes_length +∀ (values : List Aiur.G), (Aiur.NativeAIR.Transcript.fieldsBytes values).length = 8 * values.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.observeFields_bytes +∀ (state : Aiur.NativeAIR.Challenger.State) (values : List Aiur.G), + List.foldl Aiur.NativeAIR.Challenger.observeField state values = + Aiur.NativeAIR.Challenger.observeBytes state (Aiur.NativeAIR.Transcript.fieldsBytes values) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Transcript.claimsFields_framing +∀ (claims : List (List Aiur.G)), + Aiur.NativeAIR.Transcript.claimsFields claims = + Aiur.G.ofNat claims.length :: List.flatMap (fun claim => Aiur.G.ofNat claim.length :: claim) claims +AXIOMS [propext] +ROOT Aiur.NativeAIR.Transcript.lookupState_schedule +∀ (key : Aiur.NativeAIR.KeyCodec.Key) (proof : Aiur.NativeAIR.ProofCodec.Data) (claims : List (List Aiur.G)), + Aiur.NativeAIR.Transcript.lookupState key proof claims = + List.foldl Aiur.NativeAIR.Challenger.observeField + (List.foldl Aiur.NativeAIR.Challenger.observeField + (Aiur.NativeAIR.Challenger.observeCap + (Aiur.NativeAIR.Challenger.observeCap + (List.foldl Aiur.NativeAIR.Challenger.observeField + (List.foldl Aiur.NativeAIR.Challenger.observeField + (Aiur.NativeAIR.Challenger.initial (Aiur.NativeAIR.Transcript.seed key.parameters)) + (Aiur.NativeAIR.Transcript.shape key)) + (List.map (fun active => if active = true then 1 else 0) proof.active)) + (key.preprocessedCommitment.getD [])) + proof.commitments.stage1) + (List.map (fun degree => Aiur.G.ofNat degree.toNat) proof.logDegrees)) + (Aiur.NativeAIR.Transcript.claimsFields claims) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Transcript.lookupState_valid +∀ (key : Aiur.NativeAIR.KeyCodec.Key) (proof : Aiur.NativeAIR.ProofCodec.Data) (claims : List (List Aiur.G)), + (Aiur.NativeAIR.Transcript.lookupState key proof claims).Valid +AXIOMS [propext] +ROOT Aiur.NativeAIR.Transcript.accumulatorState_valid +∀ (proof : Aiur.NativeAIR.ProofCodec.Data) {state : Aiur.NativeAIR.Challenger.State}, + state.Valid → (Aiur.NativeAIR.Transcript.accumulatorState proof state).Valid +AXIOMS [] +ROOT Aiur.NativeAIR.Transcript.replay_success +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some result → + Aiur.NativeAIR.Transcript.Replay.Reads hash fuel key proof claims result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.Replay.Reads.complete +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.Replay.Reads hash fuel key proof claims result → + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some result +AXIOMS [propext] +ROOT Aiur.NativeAIR.Transcript.replay_iff +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (fuel : Nat) (key : Aiur.NativeAIR.KeyCodec.Key) + (proof : Aiur.NativeAIR.ProofCodec.Data) (claims : List (List Aiur.G)) (result : Aiur.NativeAIR.Transcript.Replay), + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some result ↔ + Aiur.NativeAIR.Transcript.Replay.Reads hash fuel key proof claims result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.replay_mono +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel more : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some result → + fuel ≤ more → Aiur.NativeAIR.Transcript.replay hash more key proof claims = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.replay_unique +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel other : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} + {left right : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some left → + Aiur.NativeAIR.Transcript.replay hash other key proof claims = some right → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.replay_valid +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some result → result.state.Valid +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.verifyArithmetic_success +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} {rows : List Aiur.NativeAIR.ProofShape.Row} + {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.verifyArithmetic hash fuel key proof claims rows = some result → + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some result ∧ + Aiur.NativeAIR.VerifierArithmetic.verify result.challenges claims rows = some true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.verifyArithmetic_iff +∀ (hash : Aiur.NativeAIR.Challenger.Hash32) (fuel : Nat) (key : Aiur.NativeAIR.KeyCodec.Key) + (proof : Aiur.NativeAIR.ProofCodec.Data) (claims : List (List Aiur.G)) (rows : List Aiur.NativeAIR.ProofShape.Row) + (result : Aiur.NativeAIR.Transcript.Replay), + Aiur.NativeAIR.Transcript.verifyArithmetic hash fuel key proof claims rows = some result ↔ + Aiur.NativeAIR.Transcript.replay hash fuel key proof claims = some result ∧ + Aiur.NativeAIR.VerifierArithmetic.verify result.challenges claims rows = some true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Transcript.verifyArithmetic_mono +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel more : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} {rows : List Aiur.NativeAIR.ProofShape.Row} + {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.verifyArithmetic hash fuel key proof claims rows = some result → + fuel ≤ more → Aiur.NativeAIR.Transcript.verifyArithmetic hash more key proof claims rows = some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.transcript_row +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof backend.keyData bytes) + {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {claims : List (List Aiur.G)} + {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Transcript.verifyArithmetic hash fuel backend.keyData checked.data claims checked.rows = some result → + ∀ {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + checked.rows[position]? = some row → + Aiur.NativeAIR.Transcript.Replay.Reads hash fuel backend.keyData checked.data claims result ∧ + Aiur.NativeAIR.ProofShape.Row.Sourced backend.keyData checked.data row.circuitIndex position row ∧ + Aiur.NativeAIR.ProofShape.Row.Fits backend.keyData.parameters row ∧ + ∃ initial before evaluation, + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator result.challenges claims = some initial ∧ + (initial :: List.map (fun x => x.accumulator) checked.rows)[position]? = some before ∧ + Aiur.NativeAIR.VerifierArithmetic.evaluate result.challenges row before = some evaluation ∧ + Aiur.NativeAIR.Quotient.composition result.challenges.alpha evaluation.constraints = + Aiur.NativeAIR.Domain.vanishing evaluation.domain result.challenges.zeta * + evaluation.quotientValue +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.leftLen_positive +∀ (size : Nat), 0 < Aiur.NativeAIR.Blake3.leftLen size +AXIOMS [] +ROOT Aiur.NativeAIR.Blake3.leftLen_lt +∀ {size : Nat}, 1024 < size → Aiur.NativeAIR.Blake3.leftLen size < size +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.schedules_permute +∀ (index : Fin 7), Aiur.NativeAIR.Blake3.schedules[index].toList.Perm (List.finRange 16) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.schedules_next +∀ (index : Fin 6), + Aiur.NativeAIR.Blake3.schedules[↑index + 1] = + Vector.ofFn fun position => Aiur.NativeAIR.Blake3.schedules[↑index][Aiur.NativeAIR.Blake3.schedules[1][position]] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.rotateRight_bits +∀ (word count : UInt32), + 0 < count.toNat → + count.toNat < 32 → (Aiur.NativeAIR.Blake3.rotateRight word count).toBitVec = word.toBitVec.rotateRight count.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.bytesWord_value +∀ (bytes : Vector UInt8 4), + (Aiur.NativeAIR.Blake3.bytesWord bytes).toNat = Aiur.NativeAIR.Challenger.littleEndian bytes.toList +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.wordBytes_encoding +∀ (word : UInt32), (Aiur.NativeAIR.Blake3.wordBytes word).toList = Aiur.NativeAIR.KeyCodec.encodeNat 4 word.toNat +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.bytesWord_wordBytes +∀ (word : UInt32), Aiur.NativeAIR.Blake3.bytesWord (Aiur.NativeAIR.Blake3.wordBytes word) = word +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.bytesWord_pack +∀ (a b c d : UInt8), + (Aiur.NativeAIR.Blake3.bytesWord #v[a, b, c, d]).toNat = a.toNat + 256 * (b.toNat + 256 * (c.toNat + 256 * d.toNat)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.wordBytes_pack +∀ (a b c d : UInt8), Aiur.NativeAIR.Blake3.wordBytes (Aiur.NativeAIR.Blake3.bytesWord #v[a, b, c, d]) = #v[a, b, c, d] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.wordBytes_bytesWord +∀ (bytes : Vector UInt8 4), Aiur.NativeAIR.Blake3.wordBytes (Aiur.NativeAIR.Blake3.bytesWord bytes) = bytes +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.bytesWord_injective +∀ {first second : Vector UInt8 4}, + Aiur.NativeAIR.Blake3.bytesWord first = Aiur.NativeAIR.Blake3.bytesWord second → first = second +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.blockWords_byte +∀ (input : List UInt8) (word : Fin 16) (byte : Fin 4), + (Vector.ofFn fun byte => input.toArray[↑word * 4 + ↑byte]?.getD 0)[byte] = input[↑word * 4 + ↑byte]?.getD 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.blockWords_value +∀ (input : List UInt8) (word : Fin 16), + (Aiur.NativeAIR.Blake3.blockWords input)[word].toNat = + Aiur.NativeAIR.Challenger.littleEndian (List.ofFn fun byte => input[↑word * 4 + ↑byte]?.getD 0) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.cvBytes_value +∀ (cv : Aiur.NativeAIR.Blake3.CV) (index : Fin 32), + (Aiur.NativeAIR.Blake3.cvBytes cv)[index] = (cv[↑index / 4].toNat / 256 ^ (↑index % 4)).toUInt8 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.g_unchanged +∀ (state : Aiur.NativeAIR.Blake3.Block) (a b c d index : Fin 16) (x y : UInt32), + a ≠ index → b ≠ index → c ≠ index → d ≠ index → (Aiur.NativeAIR.Blake3.g state a b c d x y)[index] = state[index] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.g_values +∀ (state : Aiur.NativeAIR.Blake3.Block) (a b c d : Fin 16) (x y : UInt32), + a ≠ b → + a ≠ c → + a ≠ d → + b ≠ c → + b ≠ d → + c ≠ d → + have words := Aiur.NativeAIR.Blake3.mix state[a] state[b] state[c] state[d] x y; + (Aiur.NativeAIR.Blake3.g state a b c d x y)[a] = words[0] ∧ + (Aiur.NativeAIR.Blake3.g state a b c d x y)[b] = words[1] ∧ + (Aiur.NativeAIR.Blake3.g state a b c d x y)[c] = words[2] ∧ + (Aiur.NativeAIR.Blake3.g state a b c d x y)[d] = words[3] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.initialWords_counter +∀ (cv : Aiur.NativeAIR.Blake3.CV) (counter : UInt64) (blockLen flags : UInt32), + (Aiur.NativeAIR.Blake3.initialWords cv counter blockLen flags)[12].toNat + + 2 ^ 32 * (Aiur.NativeAIR.Blake3.initialWords cv counter blockLen flags)[13].toNat = + counter.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.parentOutput_values +∀ (left right : Aiur.NativeAIR.Blake3.CV), + (Aiur.NativeAIR.Blake3.parentOutput left right).cv = Aiur.NativeAIR.Blake3.iv ∧ + (Aiur.NativeAIR.Blake3.parentOutput left right).block = left ++ right ∧ + (Aiur.NativeAIR.Blake3.parentOutput left right).blockLen = 64 ∧ + (Aiur.NativeAIR.Blake3.parentOutput left right).counter = 0 ∧ + (Aiur.NativeAIR.Blake3.parentOutput left right).flags = 4 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.leftLen_bounds +∀ {size : Nat}, 1024 < size → Aiur.NativeAIR.Blake3.leftLen size < size ∧ size ≤ 2 * Aiur.NativeAIR.Blake3.leftLen size +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.leftLen_chunks +∀ {size : Nat}, 1024 < size → ∃ exponent, Aiur.NativeAIR.Blake3.leftLen size = 1024 * 2 ^ exponent +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.leftLen_chunk_multiple +∀ {size : Nat}, 1024 < size → Aiur.NativeAIR.Blake3.leftLen size / 1024 * 1024 = Aiur.NativeAIR.Blake3.leftLen size +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.leftLen_unique +∀ {left right exponent : Nat}, + left = 1024 * 2 ^ exponent → 0 < right → right ≤ left → Aiur.NativeAIR.Blake3.leftLen (left + right) = left +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.chunkLoop_small +∀ (counter : UInt64) (cv : Aiur.NativeAIR.Blake3.CV) (start : Bool) (input : List UInt8), + input.length ≤ 64 → + Aiur.NativeAIR.Blake3.chunkLoop counter cv start input = + { cv := cv, block := Aiur.NativeAIR.Blake3.blockWords input, blockLen := input.length.toUInt32, + counter := counter, flags := (if start = true then 1 else 0) ||| 2 } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.chunkLoop_step +∀ (counter : UInt64) (cv : Aiur.NativeAIR.Blake3.CV) (start : Bool) (input : List UInt8), + 64 < input.length → + Aiur.NativeAIR.Blake3.chunkLoop counter cv start input = + Aiur.NativeAIR.Blake3.chunkLoop counter + (Aiur.NativeAIR.Blake3.compress cv (Aiur.NativeAIR.Blake3.blockWords (List.take 64 input)) counter 64 + (if start = true then 1 else 0)) + false (List.drop 64 input) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.chunkLoop_counter +∀ (counter : UInt64) (cv : Aiur.NativeAIR.Blake3.CV) (start : Bool) (input : List UInt8), + (Aiur.NativeAIR.Blake3.chunkLoop counter cv start input).counter = counter +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.chunkOutput_counter +∀ (counter : UInt64) (input : List UInt8), (Aiur.NativeAIR.Blake3.chunkOutput counter input).counter = counter +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.chunkLoop_reads +∀ (counter : UInt64) (cv : Aiur.NativeAIR.Blake3.CV) (start : Bool) (input : List UInt8), + Aiur.NativeAIR.Blake3.ChunkReads counter cv start input (Aiur.NativeAIR.Blake3.chunkLoop counter cv start input) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.ChunkReads.complete +∀ {counter : UInt64} {cv : Aiur.NativeAIR.Blake3.CV} {start : Bool} {input : List UInt8} + {output : Aiur.NativeAIR.Blake3.Output}, + Aiur.NativeAIR.Blake3.ChunkReads counter cv start input output → + Aiur.NativeAIR.Blake3.chunkLoop counter cv start input = output +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.chunkLoop_iff +∀ (counter : UInt64) (cv : Aiur.NativeAIR.Blake3.CV) (start : Bool) (input : List UInt8) + (output : Aiur.NativeAIR.Blake3.Output), + Aiur.NativeAIR.Blake3.chunkLoop counter cv start input = output ↔ + Aiur.NativeAIR.Blake3.ChunkReads counter cv start input output +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.ChunkReads.framing +∀ {counter : UInt64} {cv : Aiur.NativeAIR.Blake3.CV} {start : Bool} {input : List UInt8} + {output : Aiur.NativeAIR.Blake3.Output}, + Aiur.NativeAIR.Blake3.ChunkReads counter cv start input output → + ∃ count, + have remaining := List.drop (64 * count) input; + remaining.length ≤ 64 ∧ + (input ≠ [] → 0 < remaining.length) ∧ + output.block = Aiur.NativeAIR.Blake3.blockWords remaining ∧ + output.blockLen.toNat = remaining.length ∧ + output.counter = counter ∧ output.flags = (if (start && count == 0) = true then 1 else 0) ||| 2 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.chunkOutput_framing +∀ (counter : UInt64) (input : List UInt8), + input.length ≤ 1024 → + ∃ count, + count < 16 ∧ + have remaining := List.drop (64 * count) input; + remaining.length ≤ 64 ∧ + (input ≠ [] → 0 < remaining.length) ∧ + (Aiur.NativeAIR.Blake3.chunkOutput counter input).block = Aiur.NativeAIR.Blake3.blockWords remaining ∧ + (Aiur.NativeAIR.Blake3.chunkOutput counter input).blockLen.toNat = remaining.length ∧ + (Aiur.NativeAIR.Blake3.chunkOutput counter input).counter = counter ∧ + (Aiur.NativeAIR.Blake3.chunkOutput counter input).flags = if count = 0 then 3 else 2 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.subtree_small +∀ (counter : Nat) (input : List UInt8), + input.length ≤ 1024 → + Aiur.NativeAIR.Blake3.subtree counter input = Aiur.NativeAIR.Blake3.chunkOutput counter.toUInt64 input +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.subtree_step +∀ (counter : Nat) (input : List UInt8), + 1024 < input.length → + Aiur.NativeAIR.Blake3.subtree counter input = + Aiur.NativeAIR.Blake3.parentOutput + (Aiur.NativeAIR.Blake3.subtree counter + (List.take (Aiur.NativeAIR.Blake3.leftLen input.length) input)).chainingValue + (Aiur.NativeAIR.Blake3.subtree (counter + Aiur.NativeAIR.Blake3.leftLen input.length / 1024) + (List.drop (Aiur.NativeAIR.Blake3.leftLen input.length) input)).chainingValue +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.subtree_root_counter +∀ (input : List UInt8), (Aiur.NativeAIR.Blake3.subtree 0 input).counter = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.subtree_tree +∀ (counter : Nat) (input : List UInt8), + Aiur.NativeAIR.Blake3.TreeHash counter input (Aiur.NativeAIR.Blake3.subtree counter input) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.TreeHash.complete +∀ {counter : Nat} {input : List UInt8} {output : Aiur.NativeAIR.Blake3.Output}, + Aiur.NativeAIR.Blake3.TreeHash counter input output → Aiur.NativeAIR.Blake3.subtree counter input = output +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.subtree_iff +∀ (counter : Nat) (input : List UInt8) (output : Aiur.NativeAIR.Blake3.Output), + Aiur.NativeAIR.Blake3.subtree counter input = output ↔ Aiur.NativeAIR.Blake3.TreeHash counter input output +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.TreeHash.unique +∀ {counter : Nat} {input : List UInt8} {first second : Aiur.NativeAIR.Blake3.Output}, + Aiur.NativeAIR.Blake3.TreeHash counter input first → + Aiur.NativeAIR.Blake3.TreeHash counter input second → first = second +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.native_counter +∀ {counter : Nat} {input : List UInt8}, + counter * 1024 + input.length < 2 ^ 64 → counter < 2 ^ 54 ∧ counter.toUInt64.toNat = counter +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.native_child_spans +∀ {counter : Nat} {input : List UInt8}, + counter * 1024 + input.length < 2 ^ 64 → + 1024 < input.length → + counter * 1024 + (List.take (Aiur.NativeAIR.Blake3.leftLen input.length) input).length < 2 ^ 64 ∧ + (counter + Aiur.NativeAIR.Blake3.leftLen input.length / 1024) * 1024 + + (List.drop (Aiur.NativeAIR.Blake3.leftLen input.length) input).length < + 2 ^ 64 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.ChunkAt.native +∀ {counter leaf : Nat} {input bytes : List UInt8}, + Aiur.NativeAIR.Blake3.ChunkAt counter input leaf bytes → + counter * 1024 + input.length < 2 ^ 64 → bytes.length ≤ 1024 ∧ leaf < 2 ^ 54 ∧ leaf.toUInt64.toNat = leaf +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.digest_native_counters +∀ {input bytes : List UInt8}, + Aiur.NativeAIR.Blake3.NativeInput input → + ∀ {leaf : Nat}, + Aiur.NativeAIR.Blake3.ChunkAt 0 input leaf bytes → + bytes.length ≤ 1024 ∧ leaf < 2 ^ 54 ∧ leaf.toUInt64.toNat = leaf +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.digest_tree +∀ (input : List UInt8), + ∃ output, + Aiur.NativeAIR.Blake3.TreeHash 0 input output ∧ + output.counter = 0 ∧ Aiur.NativeAIR.Blake3.digest input = output.rootHash +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.replay_iff +∀ (fuel : Nat) (key : Aiur.NativeAIR.KeyCodec.Key) (proof : Aiur.NativeAIR.ProofCodec.Data) + (claims : List (List Aiur.G)) (result : Aiur.NativeAIR.Transcript.Replay), + Aiur.NativeAIR.Blake3.replay fuel key proof claims = some result ↔ + Aiur.NativeAIR.Transcript.Replay.Reads Aiur.NativeAIR.Blake3.hash fuel key proof claims result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.replay_unique +∀ {fuel more : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} + {claims : List (List Aiur.G)} {first second : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Blake3.replay fuel key proof claims = some first → + Aiur.NativeAIR.Blake3.replay more key proof claims = some second → first = second +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.verifyArithmetic_iff +∀ (fuel : Nat) (key : Aiur.NativeAIR.KeyCodec.Key) (proof : Aiur.NativeAIR.ProofCodec.Data) + (claims : List (List Aiur.G)) (rows : List Aiur.NativeAIR.ProofShape.Row) (result : Aiur.NativeAIR.Transcript.Replay), + Aiur.NativeAIR.Blake3.verifyArithmetic fuel key proof claims rows = some result ↔ + Aiur.NativeAIR.Blake3.replay fuel key proof claims = some result ∧ + Aiur.NativeAIR.VerifierArithmetic.verify result.challenges claims rows = some true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Blake3.hash_bytes +∀ (input : List UInt8), + List.ofFn (Aiur.NativeAIR.Blake3.hash input) = Vector.toList (Aiur.NativeAIR.Blake3.digest input) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.blake3_transcript_row +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof backend.keyData bytes) {fuel : Nat} + {claims : List (List Aiur.G)} {result : Aiur.NativeAIR.Transcript.Replay}, + Aiur.NativeAIR.Blake3.verifyArithmetic fuel backend.keyData checked.data claims checked.rows = some result → + ∀ {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + checked.rows[position]? = some row → + Aiur.NativeAIR.Transcript.Replay.Reads Aiur.NativeAIR.Blake3.hash fuel backend.keyData checked.data claims + result ∧ + Aiur.NativeAIR.ProofShape.Row.Sourced backend.keyData checked.data row.circuitIndex position row ∧ + Aiur.NativeAIR.ProofShape.Row.Fits backend.keyData.parameters row ∧ + ∃ initial before evaluation, + Aiur.NativeAIR.VerifierArithmetic.initialAccumulator result.challenges claims = some initial ∧ + (initial :: List.map (fun x => x.accumulator) checked.rows)[position]? = some before ∧ + Aiur.NativeAIR.VerifierArithmetic.evaluate result.challenges row before = some evaluation ∧ + Aiur.NativeAIR.Quotient.composition result.challenges.alpha evaluation.constraints = + Aiur.NativeAIR.Domain.vanishing evaluation.domain result.challenges.zeta * + evaluation.quotientValue +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.maxDegree_nil +Aiur.NativeAIR.MerkleCap.maxDegree [] = 0 +AXIOMS [] +ROOT Aiur.NativeAIR.MerkleCap.maxDegree_cons +∀ (degree : Nat) (degrees : List Nat), + Aiur.NativeAIR.MerkleCap.maxDegree (degree :: degrees) = max degree (Aiur.NativeAIR.MerkleCap.maxDegree degrees) +AXIOMS [] +ROOT Aiur.NativeAIR.MerkleCap.degree_le_max +∀ {degree : Nat} {degrees : List Nat}, degree ∈ degrees → degree ≤ Aiur.NativeAIR.MerkleCap.maxDegree degrees +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.maxDegree_le +∀ {degrees : List Nat} {bound : Nat}, + (∀ (degree : Nat), degree ∈ degrees → degree ≤ bound) → Aiur.NativeAIR.MerkleCap.maxDegree degrees ≤ bound +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.maxDegree_mono +∀ {selected degrees : List Nat}, + (∀ (degree : Nat), degree ∈ selected → degree ∈ degrees) → + Aiur.NativeAIR.MerkleCap.maxDegree selected ≤ Aiur.NativeAIR.MerkleCap.maxDegree degrees +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.coverage_iff +∀ {logBlowup capHeight : Nat} {degrees : List Nat}, + Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = true ↔ + ∀ (degree : Nat), + degree ∈ degrees → min (capHeight - logBlowup) (Aiur.NativeAIR.MerkleCap.maxDegree degrees) ≤ degree +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.coverage_height_iff +∀ {logBlowup capHeight : Nat} {degrees : List Nat}, + Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = true ↔ + ∀ (degree : Nat), + degree ∈ degrees → min capHeight (logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees) ≤ logBlowup + degree +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.coverage_empty +∀ (logBlowup capHeight : Nat), Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight [] = true +AXIOMS [] +ROOT Aiur.NativeAIR.MerkleCap.coverage_low_cap +∀ {logBlowup capHeight : Nat}, + capHeight ≤ logBlowup → ∀ (degrees : List Nat), Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.coverage_uniform +∀ {logBlowup capHeight degree : Nat} {degrees : List Nat}, + (∀ (d : Nat), d ∈ degrees → d = degree) → Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.coverage_subset +∀ {logBlowup capHeight : Nat} {degrees selected : List Nat}, + Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = true → + (∀ (degree : Nat), degree ∈ selected → degree ∈ degrees) → + Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight selected = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.coverage_injection +∀ {logBlowup capHeight : Nat} {degrees : List Nat}, + Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = true → + ∀ {degree : Nat}, + degree ∈ degrees → + logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees - (logBlowup + degree) ≤ + logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees - + min capHeight (logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.coverage_cap_size +∀ {logBlowup capHeight : Nat} {degrees : List Nat}, + Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = true → + ∀ {degree : Nat}, + degree ∈ degrees → + 2 ^ min capHeight (logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees) ≤ 2 ^ (logBlowup + degree) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.omitted_rejected +∀ {logBlowup capHeight degree : Nat} {degrees : List Nat}, + degree ∈ degrees → + logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees - + min capHeight (logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees) < + logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree degrees - (logBlowup + degree) → + Aiur.NativeAIR.MerkleCap.coverage logBlowup capHeight degrees = false +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.shorter_matrix_rejected +Aiur.NativeAIR.MerkleCap.coverage 0 2 [3, 1] = false +AXIOMS [] +ROOT Aiur.NativeAIR.MerkleCap.exact_injection_accepted +Aiur.NativeAIR.MerkleCap.coverage 0 1 [3, 1] = true +AXIOMS [] +ROOT Aiur.NativeAIR.MerkleCap.check_iff +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.MerkleCap.check key proof = true ↔ + ∀ (degree : UInt8), + degree ∈ proof.logDegrees → + min key.parameters.capHeight + (key.parameters.logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree (List.map UInt8.toNat proof.logDegrees)) ≤ + key.parameters.logBlowup + degree.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.MerkleCap.check_degree +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data}, + Aiur.NativeAIR.MerkleCap.check key proof = true → + ∀ {position : Nat} {degree : UInt8}, + proof.logDegrees[position]? = some degree → + min key.parameters.capHeight + (key.parameters.logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree (List.map UInt8.toNat proof.logDegrees)) ≤ + key.parameters.logBlowup + degree.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.cap_coverage +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes), + Aiur.NativeAIR.MerkleCap.coverage key.parameters.logBlowup key.parameters.capHeight + (List.map UInt8.toNat checked.data.logDegrees) = + true +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.row_cap +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes) + {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + checked.rows[position]? = some row → + min key.parameters.capHeight + (key.parameters.logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree (List.map UInt8.toNat checked.data.logDegrees)) ≤ + key.parameters.logBlowup + row.logDegree.toNat +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.CheckedProof.row_injection +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof key bytes) + {position : Nat} {row : Aiur.NativeAIR.ProofShape.Row}, + checked.rows[position]? = some row → + key.parameters.logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree (List.map UInt8.toNat checked.data.logDegrees) - + (key.parameters.logBlowup + row.logDegree.toNat) ≤ + key.parameters.logBlowup + Aiur.NativeAIR.MerkleCap.maxDegree (List.map UInt8.toNat checked.data.logDegrees) - + key.parameters.capHeight +AXIOMS [propext, Quot.sound] +ROOT Aiur.BoundVerifier.verifyShaped_cap +∀ {selection : Aiur.BoundVerifier.Selection} {backend : Aiur.BoundVerifier.CompiledBackend selection} + {input : Array Aiur.G} {bytes : ByteArray}, + Aiur.BoundVerifier.verifyShaped backend input bytes = Except.ok () → + ∃ checked, + Aiur.BoundVerifier.readProof backend.keyData bytes = Except.ok checked ∧ + Aiur.NativeAIR.MerkleCap.check backend.keyData checked.data = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.fieldsBytes_injective +∀ {left right : List Aiur.G}, + Aiur.NativeAIR.Transcript.fieldsBytes left = Aiur.NativeAIR.Transcript.fieldsBytes right → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.pairBytes_length +∀ (left right : Aiur.NativeAIR.Merkle.Digest), (Aiur.NativeAIR.Merkle.pairBytes left right).length = 64 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Merkle.pairBytes_injective +∀ {left right otherLeft otherRight : Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.Merkle.pairBytes left right = Aiur.NativeAIR.Merkle.pairBytes otherLeft otherRight → + left = otherLeft ∧ right = otherRight +AXIOMS [propext] +ROOT Aiur.NativeAIR.Merkle.branchBytes_injective +∀ {index : Nat} {left right leftSibling rightSibling : Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.Merkle.branchBytes index left leftSibling = + Aiur.NativeAIR.Merkle.branchBytes index right rightSibling → + left = right ∧ leftSibling = rightSibling +AXIOMS [propext] +ROOT Aiur.NativeAIR.Merkle.shape_length +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {rows : List (List Aiur.G)}, + Aiur.NativeAIR.Merkle.shape dimensions rows = true → rows.length = dimensions.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.rowsAt_absent +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {rows : List (List Aiur.G)} {height : Nat}, + Aiur.NativeAIR.Merkle.hasHeight dimensions height = false → Aiur.NativeAIR.Merkle.rowsAt dimensions rows height = [] +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.rowsAt_injective +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {left right : List (List Aiur.G)}, + Aiur.NativeAIR.Merkle.shape dimensions left = true → + Aiur.NativeAIR.Merkle.shape dimensions right = true → + (∀ (height : Nat), + (Aiur.NativeAIR.Merkle.rowsAt dimensions left height).flatten = + (Aiur.NativeAIR.Merkle.rowsAt dimensions right height).flatten) → + left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.rowBytes_injective +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {left right : List (List Aiur.G)}, + Aiur.NativeAIR.Merkle.shape dimensions left = true → + Aiur.NativeAIR.Merkle.shape dimensions right = true → + (∀ (height : Nat), + Aiur.NativeAIR.Merkle.rowBytes dimensions left height = + Aiur.NativeAIR.Merkle.rowBytes dimensions right height) → + left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.CollisionOn.mono +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {smaller larger : List (List UInt8)}, + (∀ (input : List UInt8), input ∈ smaller → input ∈ larger) → + Aiur.NativeAIR.Merkle.CollisionOn hash smaller → Aiur.NativeAIR.Merkle.CollisionOn hash larger +AXIOMS [] +ROOT Aiur.NativeAIR.Merkle.equal_of_no_collision +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {inputs : List (List UInt8)}, + ¬Aiur.NativeAIR.Merkle.CollisionOn hash inputs → + ∀ {left right : List UInt8}, left ∈ inputs → right ∈ inputs → hash left = hash right → left = right +AXIOMS [] +ROOT Aiur.NativeAIR.Merkle.step_calls +∀ (hash : Aiur.NativeAIR.Merkle.Hash) (dimensions : List Aiur.NativeAIR.Merkle.Dimensions) (rows : List (List Aiur.G)) + (height index : Nat) (current sibling : Aiur.NativeAIR.Merkle.Digest), + (Aiur.NativeAIR.Merkle.step hash dimensions rows height index current sibling).inputs.length ≤ 3 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.walk_calls +∀ (hash : Aiur.NativeAIR.Merkle.Hash) (dimensions : List Aiur.NativeAIR.Merkle.Dimensions) (rows : List (List Aiur.G)) + (height index : Nat) (current : Aiur.NativeAIR.Merkle.Digest) (proof : List Aiur.NativeAIR.Merkle.Digest), + (Aiur.NativeAIR.Merkle.walk hash dimensions rows height index current proof).inputs.length ≤ 3 * proof.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.step_binding +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} + {leftRows rightRows : List (List Aiur.G)} {height index : Nat} + {left right leftSibling rightSibling : Aiur.NativeAIR.Merkle.Digest}, + ¬Aiur.NativeAIR.Merkle.CollisionOn hash + ((Aiur.NativeAIR.Merkle.step hash dimensions leftRows height index left leftSibling).inputs ++ + (Aiur.NativeAIR.Merkle.step hash dimensions rightRows height index right rightSibling).inputs) → + (Aiur.NativeAIR.Merkle.step hash dimensions leftRows height index left leftSibling).digest = + (Aiur.NativeAIR.Merkle.step hash dimensions rightRows height index right rightSibling).digest → + left = right ∧ + (Aiur.NativeAIR.Merkle.hasHeight dimensions height = true → + Aiur.NativeAIR.Merkle.rowBytes dimensions leftRows height = + Aiur.NativeAIR.Merkle.rowBytes dimensions rightRows height) +AXIOMS [propext] +ROOT Aiur.NativeAIR.Merkle.walk_binding +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} + {leftRows rightRows : List (List Aiur.G)} {height index : Nat} {left right : Aiur.NativeAIR.Merkle.Digest} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + leftProof.length = rightProof.length → + ¬Aiur.NativeAIR.Merkle.CollisionOn hash + ((Aiur.NativeAIR.Merkle.walk hash dimensions leftRows height index left leftProof).inputs ++ + (Aiur.NativeAIR.Merkle.walk hash dimensions rightRows height index right rightProof).inputs) → + (Aiur.NativeAIR.Merkle.walk hash dimensions leftRows height index left leftProof).digest = + (Aiur.NativeAIR.Merkle.walk hash dimensions rightRows height index right rightProof).digest → + left = right ∧ + ∀ (depth : Nat), + depth < leftProof.length → + Aiur.NativeAIR.Merkle.hasHeight dimensions (height - (depth + 1)) = true → + Aiur.NativeAIR.Merkle.rowBytes dimensions leftRows (height - (depth + 1)) = + Aiur.NativeAIR.Merkle.rowBytes dimensions rightRows (height - (depth + 1)) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_success +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = some result → + dimensions ≠ [] ∧ + Aiur.NativeAIR.Merkle.shape dimensions rows = true ∧ + proof.length = Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight ∧ + index < 2 ^ Aiur.NativeAIR.Merkle.maxHeight dimensions ∧ + result = + { logHeight := Aiur.NativeAIR.Merkle.maxHeight dimensions - proof.length, + index := index / 2 ^ proof.length, + hashing := + { + digest := + (Aiur.NativeAIR.Merkle.walk hash dimensions rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) + index + (hash + (Aiur.NativeAIR.Merkle.rowBytes dimensions rows + (Aiur.NativeAIR.Merkle.maxHeight dimensions))) + proof).digest, + inputs := + Aiur.NativeAIR.Merkle.rowBytes dimensions rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) :: + (Aiur.NativeAIR.Merkle.walk hash dimensions rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) + index + (hash + (Aiur.NativeAIR.Merkle.rowBytes dimensions rows + (Aiur.NativeAIR.Merkle.maxHeight dimensions))) + proof).inputs } } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_complete +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest}, + dimensions ≠ [] → + Aiur.NativeAIR.Merkle.shape dimensions rows = true → + proof.length = Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight → + index < 2 ^ Aiur.NativeAIR.Merkle.maxHeight dimensions → + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = + some + { logHeight := Aiur.NativeAIR.Merkle.maxHeight dimensions - proof.length, + index := index / 2 ^ proof.length, + hashing := + { + digest := + (Aiur.NativeAIR.Merkle.walk hash dimensions rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) + index + (hash + (Aiur.NativeAIR.Merkle.rowBytes dimensions rows + (Aiur.NativeAIR.Merkle.maxHeight dimensions))) + proof).digest, + inputs := + Aiur.NativeAIR.Merkle.rowBytes dimensions rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) :: + (Aiur.NativeAIR.Merkle.walk hash dimensions rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) + index + (hash + (Aiur.NativeAIR.Merkle.rowBytes dimensions rows + (Aiur.NativeAIR.Merkle.maxHeight dimensions))) + proof).inputs } } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_calls +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = some result → + result.hashing.inputs.length ≤ 1 + 3 * proof.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_position +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = some result → + result.logHeight = min capHeight (Aiur.NativeAIR.Merkle.maxHeight dimensions) ∧ + result.index = index / 2 ^ (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_index_bound +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = some result → + result.index < 2 ^ result.logHeight +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.hasHeight_iff +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height : Nat}, + Aiur.NativeAIR.Merkle.hasHeight dimensions height = true ↔ + ∃ dimension, dimension ∈ dimensions ∧ dimension.logHeight = height +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.height_le_max +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {dimension : Aiur.NativeAIR.Merkle.Dimensions}, + dimension ∈ dimensions → dimension.logHeight ≤ Aiur.NativeAIR.Merkle.maxHeight dimensions +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.covered_iff +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight : Nat}, + Aiur.NativeAIR.Merkle.covered dimensions capHeight = true ↔ + ∀ (dimension : Aiur.NativeAIR.Merkle.Dimensions), + dimension ∈ dimensions → min capHeight (Aiur.NativeAIR.Merkle.maxHeight dimensions) ≤ dimension.logHeight +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_binding +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {leftRows rightRows : List (List Aiur.G)} {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest} + {left right : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.Merkle.covered dimensions capHeight = true → + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index leftRows leftProof = some left → + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rightRows rightProof = some right → + ¬Aiur.NativeAIR.Merkle.CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) → + left.hashing.digest = right.hashing.digest → leftRows = rightRows +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.verify_success +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {cap : List Aiur.NativeAIR.Merkle.Digest} {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.Merkle.verify hash dimensions capHeight index cap rows proof = true → + ∃ result, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = some result ∧ + cap[result.index]? = some result.hashing.digest +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.verify_collision +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {cap : List Aiur.NativeAIR.Merkle.Digest} {leftRows rightRows : List (List Aiur.G)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.Merkle.covered dimensions capHeight = true → + Aiur.NativeAIR.Merkle.verify hash dimensions capHeight index cap leftRows leftProof = true → + Aiur.NativeAIR.Merkle.verify hash dimensions capHeight index cap rightRows rightProof = true → + leftRows ≠ rightRows → + ∃ left right, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index leftRows leftProof = some left ∧ + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rightRows rightProof = some right ∧ + Aiur.NativeAIR.Merkle.CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ + 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.verifyCovered_collision +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {cap : List Aiur.NativeAIR.Merkle.Digest} {leftRows rightRows : List (List Aiur.G)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.Merkle.verifyCovered hash dimensions capHeight index cap leftRows leftProof = true → + Aiur.NativeAIR.Merkle.verifyCovered hash dimensions capHeight index cap rightRows rightProof = true → + leftRows ≠ rightRows → + ∃ left right, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index leftRows leftProof = some left ∧ + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rightRows rightProof = some right ∧ + Aiur.NativeAIR.Merkle.CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ + 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.blake3_collision +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} + {leftRows rightRows : List (List Aiur.G)} {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.Merkle.verifyCovered Aiur.NativeAIR.Blake3.digest dimensions capHeight index cap leftRows leftProof = + true → + Aiur.NativeAIR.Merkle.verifyCovered Aiur.NativeAIR.Blake3.digest dimensions capHeight index cap rightRows + rightProof = + true → + leftRows ≠ rightRows → + ∃ left right, + Aiur.NativeAIR.Merkle.replay Aiur.NativeAIR.Blake3.digest dimensions capHeight index leftRows leftProof = + some left ∧ + Aiur.NativeAIR.Merkle.replay Aiur.NativeAIR.Blake3.digest dimensions capHeight index rightRows rightProof = + some right ∧ + Aiur.NativeAIR.Merkle.CollisionOn Aiur.NativeAIR.Blake3.digest + (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ + 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.branchBytes_length +∀ (index : Nat) (current sibling : Aiur.NativeAIR.Merkle.Digest), + (Aiur.NativeAIR.Merkle.branchBytes index current sibling).length = 64 +AXIOMS [propext] +ROOT Aiur.NativeAIR.Merkle.rowsAt_fields_le +∀ (dimensions : List Aiur.NativeAIR.Merkle.Dimensions) (rows : List (List Aiur.G)) (height : Nat), + (Aiur.NativeAIR.Merkle.rowsAt dimensions rows height).flatten.length ≤ rows.flatten.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.rowBytes_length_le +∀ (dimensions : List Aiur.NativeAIR.Merkle.Dimensions) (rows : List (List Aiur.G)) (height : Nat), + (Aiur.NativeAIR.Merkle.rowBytes dimensions rows height).length ≤ 8 * rows.flatten.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.step_input_length +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {rows : List (List Aiur.G)} + {height index : Nat} {current sibling : Aiur.NativeAIR.Merkle.Digest} {input : List UInt8}, + input ∈ (Aiur.NativeAIR.Merkle.step hash dimensions rows height index current sibling).inputs → + input.length ≤ max 64 (8 * rows.flatten.length) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.walk_input_length +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {rows : List (List Aiur.G)} + {height index : Nat} {current : Aiur.NativeAIR.Merkle.Digest} {proof : List Aiur.NativeAIR.Merkle.Digest} + {input : List UInt8}, + input ∈ (Aiur.NativeAIR.Merkle.walk hash dimensions rows height index current proof).inputs → + input.length ≤ max 64 (8 * rows.flatten.length) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_input_length +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = some result → + ∀ {input : List UInt8}, input ∈ result.hashing.inputs → input.length ≤ max 64 (8 * rows.flatten.length) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.replay_native_input +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {rows : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof = some result → + rows.flatten.length < 2 ^ 61 → + ∀ {input : List UInt8}, input ∈ result.hashing.inputs → Aiur.NativeAIR.Blake3.NativeInput input +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Merkle.walk_append +∀ (hash : Aiur.NativeAIR.Merkle.Hash) (dimensions : List Aiur.NativeAIR.Merkle.Dimensions) (rows : List (List Aiur.G)) + (height index : Nat) (current : Aiur.NativeAIR.Merkle.Digest) (before after : List Aiur.NativeAIR.Merkle.Digest), + Aiur.NativeAIR.Merkle.walk hash dimensions rows height index current (before ++ after) = + have middle := Aiur.NativeAIR.Merkle.walk hash dimensions rows height index current before; + have final := + Aiur.NativeAIR.Merkle.walk hash dimensions rows (height - before.length) (index / 2 ^ before.length) middle.digest + after; + { digest := final.digest, inputs := middle.inputs ++ final.inputs } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.Logged.bind_success +∀ {α β : Type} {first : Aiur.NativeAIR.PrunedMerkle.Logged α} {next : α → Aiur.NativeAIR.PrunedMerkle.Logged β} + {value : β}, + (first >>= next).result = some value → + ∃ middle, + first.result = some middle ∧ + (next middle).result = some value ∧ (first >>= next).inputs = first.inputs ++ (next middle).inputs +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.Logged.bind_input_left +∀ {α β : Type} {first : Aiur.NativeAIR.PrunedMerkle.Logged α} {next : α → Aiur.NativeAIR.PrunedMerkle.Logged β} + {input : List UInt8}, input ∈ first.inputs → input ∈ (first >>= next).inputs +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.Logged.bind_input_right +∀ {α β : Type} {first : Aiur.NativeAIR.PrunedMerkle.Logged α} {next : α → Aiur.NativeAIR.PrunedMerkle.Logged β} + {middle : α}, + first.result = some middle → ∀ {input : List UInt8}, input ∈ (next middle).inputs → input ∈ (first >>= next).inputs +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.Logged.bind_if +∀ {α β : Type} (condition : Prop) [inst : Decidable condition] (left right : Aiur.NativeAIR.PrunedMerkle.Logged α) + (next : α → Aiur.NativeAIR.PrunedMerkle.Logged β), + (if condition then left else right) >>= next = if condition then left >>= next else right >>= next +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.hashInput_value +∀ (hash : Aiur.NativeAIR.Merkle.Hash) (input : List UInt8), + (Aiur.NativeAIR.PrunedMerkle.hashInput hash input).result = some (hash input) +AXIOMS [] +ROOT Aiur.NativeAIR.PrunedMerkle.hashInput_inputs +∀ (hash : Aiur.NativeAIR.Merkle.Hash) (input : List UInt8), + (Aiur.NativeAIR.PrunedMerkle.hashInput hash input).inputs = [input] +AXIOMS [] +ROOT Aiur.NativeAIR.PrunedMerkle.TicketAt.mono +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height index : Nat} + {digest : Aiur.NativeAIR.Merkle.Digest} {before after : List (List UInt8)} + {ticket : Aiur.NativeAIR.PrunedMerkle.Ticket}, + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions height index digest before ticket → + before ⊆ after → Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions height index digest after ticket +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.NodeAt.mono +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height : Nat} + {before after : List (List UInt8)} {node : Aiur.NativeAIR.PrunedMerkle.Node}, + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions height before node → + before ⊆ after → Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions height after node +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.PendingAt.mono +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height index : Nat} + {digest : Aiur.NativeAIR.Merkle.Digest} {before after : List (List UInt8)} + {ticket : Aiur.NativeAIR.PrunedMerkle.Ticket}, + Aiur.NativeAIR.PrunedMerkle.PendingAt hash dimensions height index digest before ticket → + before ⊆ after → Aiur.NativeAIR.PrunedMerkle.PendingAt hash dimensions height index digest after ticket +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.PendingNode.mono +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height : Nat} + {before after : List (List UInt8)} {node : Aiur.NativeAIR.PrunedMerkle.Node}, + Aiur.NativeAIR.PrunedMerkle.PendingNode hash dimensions height before node → + before ⊆ after → Aiur.NativeAIR.PrunedMerkle.PendingNode hash dimensions height after node +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.TicketAt.extend +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height index : Nat} + {digest : Aiur.NativeAIR.Merkle.Digest} {inputs : List (List UInt8)} {ticket : Aiur.NativeAIR.PrunedMerkle.Ticket} + (sibling : Aiur.NativeAIR.Merkle.Digest), + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions (height + 1) index digest inputs ticket → + Aiur.NativeAIR.Merkle.branchBytes index digest sibling ∈ inputs → + Aiur.NativeAIR.PrunedMerkle.PendingAt hash dimensions height (index / 2) + (hash (Aiur.NativeAIR.Merkle.branchBytes index digest sibling)) inputs + (Aiur.NativeAIR.PrunedMerkle.Ticket.extend sibling ticket) +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.TicketAt.finish +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height index : Nat} + {digest : Aiur.NativeAIR.Merkle.Digest} {inputs : List (List UInt8)} {ticket : Aiur.NativeAIR.PrunedMerkle.Ticket} + (sibling : Aiur.NativeAIR.Merkle.Digest), + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions (height + 1) index digest inputs ticket → + (Aiur.NativeAIR.Merkle.step hash dimensions ticket.rows height index digest sibling).inputs ⊆ inputs → + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions height (index / 2) + (Aiur.NativeAIR.Merkle.step hash dimensions ticket.rows height index digest sibling).digest inputs + (Aiur.NativeAIR.PrunedMerkle.Ticket.extend sibling ticket) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.PendingAt.finish_absent +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height index : Nat} + {digest : Aiur.NativeAIR.Merkle.Digest} {inputs : List (List UInt8)} {ticket : Aiur.NativeAIR.PrunedMerkle.Ticket}, + Aiur.NativeAIR.PrunedMerkle.PendingAt hash dimensions height index digest inputs ticket → + Aiur.NativeAIR.Merkle.hasHeight dimensions height = false → + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions height index digest inputs ticket +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.PendingAt.finish_injected +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height index : Nat} + {digest : Aiur.NativeAIR.Merkle.Digest} {inputs : List (List UInt8)} {ticket : Aiur.NativeAIR.PrunedMerkle.Ticket} + {rows : List (List Aiur.G)}, + Aiur.NativeAIR.PrunedMerkle.PendingAt hash dimensions height index digest inputs ticket → + Aiur.NativeAIR.Merkle.hasHeight dimensions height = true → + Aiur.NativeAIR.Merkle.rowsAt dimensions ticket.rows height = Aiur.NativeAIR.Merkle.rowsAt dimensions rows height → + Aiur.NativeAIR.Merkle.rowBytes dimensions rows height ∈ inputs → + Aiur.NativeAIR.Merkle.pairBytes digest (hash (Aiur.NativeAIR.Merkle.rowBytes dimensions rows height)) ∈ + inputs → + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions height index + (hash + (Aiur.NativeAIR.Merkle.pairBytes digest (hash (Aiur.NativeAIR.Merkle.rowBytes dimensions rows height)))) + inputs ticket +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.NodeAt.singleton +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height : Nat} + {inputs : List (List UInt8)} {node : Aiur.NativeAIR.PrunedMerkle.Node} (sibling : Aiur.NativeAIR.Merkle.Digest), + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions (height + 1) inputs node → + Aiur.NativeAIR.Merkle.branchBytes node.index node.digest sibling ∈ inputs → + Aiur.NativeAIR.PrunedMerkle.PendingNode hash dimensions height inputs + { index := node.index / 2, digest := hash (Aiur.NativeAIR.Merkle.branchBytes node.index node.digest sibling), + tickets := List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend sibling) node.tickets } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.NodeAt.pair +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height : Nat} + {inputs : List (List UInt8)} {first second : Aiur.NativeAIR.PrunedMerkle.Node}, + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions (height + 1) inputs first → + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions (height + 1) inputs second → + first.index % 2 = 0 ∧ second.index = first.index + 1 → + Aiur.NativeAIR.Merkle.pairBytes first.digest second.digest ∈ inputs → + Aiur.NativeAIR.PrunedMerkle.PendingNode hash dimensions height inputs + { index := first.index / 2, digest := hash (Aiur.NativeAIR.Merkle.pairBytes first.digest second.digest), + tickets := + List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend second.digest) first.tickets ++ + List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend first.digest) second.tickets } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.origins_cons +∀ (node : Aiur.NativeAIR.PrunedMerkle.Node) (nodes : List Aiur.NativeAIR.PrunedMerkle.Node), + Aiur.NativeAIR.PrunedMerkle.origins (node :: nodes) = + List.map (fun ticket => (ticket.index, ticket.rows)) node.tickets ++ Aiur.NativeAIR.PrunedMerkle.origins nodes +AXIOMS [] +ROOT Aiur.NativeAIR.PrunedMerkle.origins_extend +∀ (tickets : List Aiur.NativeAIR.PrunedMerkle.Ticket) (sibling : Aiur.NativeAIR.Merkle.Digest), + List.map (fun ticket => (ticket.index, ticket.rows)) + (List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend sibling) tickets) = + List.map (fun ticket => (ticket.index, ticket.rows)) tickets +AXIOMS [propext] +ROOT Aiur.NativeAIR.PrunedMerkle.combine_refines +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height : Nat} + {inputs : List (List UInt8)} {nodes : List Aiur.NativeAIR.PrunedMerkle.Node} + {proof : List Aiur.NativeAIR.Merkle.Digest} {parents : List Aiur.NativeAIR.PrunedMerkle.Node} + {remaining : List Aiur.NativeAIR.Merkle.Digest}, + (∀ (node : Aiur.NativeAIR.PrunedMerkle.Node), + node ∈ nodes → Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions (height + 1) inputs node) → + (Aiur.NativeAIR.PrunedMerkle.combine hash nodes proof).result = some (parents, remaining) → + (∀ (parent : Aiur.NativeAIR.PrunedMerkle.Node), + parent ∈ parents → + Aiur.NativeAIR.PrunedMerkle.PendingNode hash dimensions height + (inputs ++ (Aiur.NativeAIR.PrunedMerkle.combine hash nodes proof).inputs) parent) ∧ + Aiur.NativeAIR.PrunedMerkle.origins parents = Aiur.NativeAIR.PrunedMerkle.origins nodes +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.inject_refines +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height : Nat} + {inputs : List (List UInt8)} {nodes output : List Aiur.NativeAIR.PrunedMerkle.Node}, + Aiur.NativeAIR.Merkle.hasHeight dimensions height = true → + (∀ (node : Aiur.NativeAIR.PrunedMerkle.Node), + node ∈ nodes → Aiur.NativeAIR.PrunedMerkle.PendingNode hash dimensions height inputs node) → + (Aiur.NativeAIR.PrunedMerkle.inject hash dimensions height nodes).result = some output → + (∀ (node : Aiur.NativeAIR.PrunedMerkle.Node), + node ∈ output → + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions height + (inputs ++ (Aiur.NativeAIR.PrunedMerkle.inject hash dimensions height nodes).inputs) node) ∧ + Aiur.NativeAIR.PrunedMerkle.origins output = Aiur.NativeAIR.PrunedMerkle.origins nodes +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.initial_refines +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {inputs : List (List UInt8)} + {tickets : List Aiur.NativeAIR.PrunedMerkle.Ticket} {nodes : List Aiur.NativeAIR.PrunedMerkle.Node}, + (∀ (ticket : Aiur.NativeAIR.PrunedMerkle.Ticket), + ticket ∈ tickets → + Aiur.NativeAIR.Merkle.shape dimensions ticket.rows = true ∧ + ticket.index < 2 ^ Aiur.NativeAIR.Merkle.maxHeight dimensions ∧ ticket.proof = []) → + (Aiur.NativeAIR.PrunedMerkle.initial hash dimensions (Aiur.NativeAIR.Merkle.maxHeight dimensions) tickets).result = + some nodes → + (∀ (node : Aiur.NativeAIR.PrunedMerkle.Node), + node ∈ nodes → + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions (Aiur.NativeAIR.Merkle.maxHeight dimensions) + (inputs ++ + (Aiur.NativeAIR.PrunedMerkle.initial hash dimensions (Aiur.NativeAIR.Merkle.maxHeight dimensions) + tickets).inputs) + node) ∧ + Aiur.NativeAIR.PrunedMerkle.origins nodes = List.map (fun ticket => (ticket.index, ticket.rows)) tickets +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.walk_refines +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {steps height : Nat} + {inputs : List (List UInt8)} {nodes output : List Aiur.NativeAIR.PrunedMerkle.Node} + {proof remaining : List Aiur.NativeAIR.Merkle.Digest}, + steps ≤ height → + (∀ (node : Aiur.NativeAIR.PrunedMerkle.Node), + node ∈ nodes → Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions height inputs node) → + (Aiur.NativeAIR.PrunedMerkle.walk hash dimensions steps height nodes proof).result = some (output, remaining) → + (∀ (node : Aiur.NativeAIR.PrunedMerkle.Node), + node ∈ output → + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions (height - steps) + (inputs ++ (Aiur.NativeAIR.PrunedMerkle.walk hash dimensions steps height nodes proof).inputs) node) ∧ + Aiur.NativeAIR.PrunedMerkle.origins output = Aiur.NativeAIR.PrunedMerkle.origins nodes +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.mapM_members +∀ {α : Type u_1} {β : Type u_2} {read : α → Option β} {inputs : List α} {outputs : List β}, + List.mapM read inputs = some outputs → + (∀ (input : α), input ∈ inputs → ∃ output, output ∈ outputs ∧ read input = some output) ∧ + ∀ (output : β), output ∈ outputs → ∃ input, input ∈ inputs ∧ read input = some output +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.representatives_refines +∀ {indices : List Nat} {rows : List (List (List Aiur.G))} {tickets : List Aiur.NativeAIR.PrunedMerkle.Ticket}, + Aiur.NativeAIR.PrunedMerkle.representatives indices rows = some tickets → + (∀ (ticket : Aiur.NativeAIR.PrunedMerkle.Ticket), ticket ∈ tickets → ticket.index ∈ indices ∧ ticket.proof = []) ∧ + ∀ (source : Nat × List (List Aiur.G)), + source ∈ indices.zip rows → ∃ ticket, ticket ∈ tickets ∧ ticket.index = source.fst ∧ ticket.rows = source.snd +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.replay_refines +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight : Nat} + {indices : List Nat} {rows : List (List (List Aiur.G))} {proof : List Aiur.NativeAIR.Merkle.Digest} + {nodes : List Aiur.NativeAIR.PrunedMerkle.Node}, + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight indices rows proof).result = some nodes → + dimensions ≠ [] ∧ + rows.length = indices.length ∧ + (∀ (node : Aiur.NativeAIR.PrunedMerkle.Node), + node ∈ nodes → + Aiur.NativeAIR.PrunedMerkle.NodeAt hash dimensions + (min capHeight (Aiur.NativeAIR.Merkle.maxHeight dimensions)) + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight indices rows proof).inputs node) ∧ + ∀ (source : Nat × List (List Aiur.G)), + source ∈ indices.zip rows → source ∈ Aiur.NativeAIR.PrunedMerkle.origins nodes +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.replay_individual +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {indices : List Nat} {rows : List (List (List Aiur.G))} {query : List (List Aiur.G)} + {proof : List Aiur.NativeAIR.Merkle.Digest} {nodes : List Aiur.NativeAIR.PrunedMerkle.Node}, + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight indices rows proof).result = some nodes → + (index, query) ∈ indices.zip rows → + ∃ node, + node ∈ nodes ∧ + ∃ path result, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index query path = some result ∧ + result.index = node.index ∧ + result.hashing.digest = node.digest ∧ + result.hashing.inputs ⊆ + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight indices rows proof).inputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.verify_individual +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {indices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} {rows : List (List (List Aiur.G))} + {query : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.PrunedMerkle.verify hash dimensions capHeight indices cap rows proof = true → + (index, query) ∈ indices.zip rows → + ∃ path result, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index query path = some result ∧ + Aiur.NativeAIR.Merkle.verify hash dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight indices rows proof).inputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.verifyCovered_individual +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {indices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} {rows : List (List (List Aiur.G))} + {query : List (List Aiur.G)} {proof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.PrunedMerkle.verifyCovered hash dimensions capHeight indices cap rows proof = true → + (index, query) ∈ indices.zip rows → + ∃ path result, + Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index query path = some result ∧ + Aiur.NativeAIR.Merkle.verifyCovered hash dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight indices rows proof).inputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.verify_collision +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {leftIndices rightIndices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} + {leftRows rightRows : List (List (List Aiur.G))} {leftQuery rightQuery : List (List Aiur.G)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.Merkle.covered dimensions capHeight = true → + Aiur.NativeAIR.PrunedMerkle.verify hash dimensions capHeight leftIndices cap leftRows leftProof = true → + Aiur.NativeAIR.PrunedMerkle.verify hash dimensions capHeight rightIndices cap rightRows rightProof = true → + (index, leftQuery) ∈ leftIndices.zip leftRows → + (index, rightQuery) ∈ rightIndices.zip rightRows → + leftQuery ≠ rightQuery → + ∃ inputs, + inputs ⊆ + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight leftIndices leftRows + leftProof).inputs ++ + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight rightIndices rightRows + rightProof).inputs ∧ + Aiur.NativeAIR.Merkle.CollisionOn hash inputs ∧ + inputs.length ≤ 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) ∧ + ∀ (input : List UInt8), + input ∈ inputs → + input.length ≤ max 64 (8 * max leftQuery.flatten.length rightQuery.flatten.length) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.verifyCovered_collision +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} + {leftIndices rightIndices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} + {leftRows rightRows : List (List (List Aiur.G))} {leftQuery rightQuery : List (List Aiur.G)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.PrunedMerkle.verifyCovered hash dimensions capHeight leftIndices cap leftRows leftProof = true → + Aiur.NativeAIR.PrunedMerkle.verifyCovered hash dimensions capHeight rightIndices cap rightRows rightProof = true → + (index, leftQuery) ∈ leftIndices.zip leftRows → + (index, rightQuery) ∈ rightIndices.zip rightRows → + leftQuery ≠ rightQuery → + ∃ inputs, + inputs ⊆ + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight leftIndices leftRows + leftProof).inputs ++ + (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight rightIndices rightRows + rightProof).inputs ∧ + Aiur.NativeAIR.Merkle.CollisionOn hash inputs ∧ + inputs.length ≤ 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) ∧ + ∀ (input : List UInt8), + input ∈ inputs → + input.length ≤ max 64 (8 * max leftQuery.flatten.length rightQuery.flatten.length) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.blake3_collision +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} {leftIndices rightIndices : List Nat} + {cap : List Aiur.NativeAIR.Merkle.Digest} {leftRows rightRows : List (List (List Aiur.G))} + {leftQuery rightQuery : List (List Aiur.G)} {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.PrunedMerkle.verifyCovered Aiur.NativeAIR.Blake3.digest dimensions capHeight leftIndices cap leftRows + leftProof = + true → + Aiur.NativeAIR.PrunedMerkle.verifyCovered Aiur.NativeAIR.Blake3.digest dimensions capHeight rightIndices cap + rightRows rightProof = + true → + (index, leftQuery) ∈ leftIndices.zip leftRows → + (index, rightQuery) ∈ rightIndices.zip rightRows → + leftQuery ≠ rightQuery → + ∃ inputs, + inputs ⊆ + (Aiur.NativeAIR.PrunedMerkle.replay Aiur.NativeAIR.Blake3.digest dimensions capHeight leftIndices + leftRows leftProof).inputs ++ + (Aiur.NativeAIR.PrunedMerkle.replay Aiur.NativeAIR.Blake3.digest dimensions capHeight rightIndices + rightRows rightProof).inputs ∧ + Aiur.NativeAIR.Merkle.CollisionOn Aiur.NativeAIR.Blake3.digest inputs ∧ + inputs.length ≤ 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) ∧ + ∀ (input : List UInt8), + input ∈ inputs → + input.length ≤ max 64 (8 * max leftQuery.flatten.length rightQuery.flatten.length) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.PrunedMerkle.blake3_native_collision +∀ {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {capHeight index : Nat} {leftIndices rightIndices : List Nat} + {cap : List Aiur.NativeAIR.Merkle.Digest} {leftRows rightRows : List (List (List Aiur.G))} + {leftQuery rightQuery : List (List Aiur.G)} {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.PrunedMerkle.verifyCovered Aiur.NativeAIR.Blake3.digest dimensions capHeight leftIndices cap leftRows + leftProof = + true → + Aiur.NativeAIR.PrunedMerkle.verifyCovered Aiur.NativeAIR.Blake3.digest dimensions capHeight rightIndices cap + rightRows rightProof = + true → + (index, leftQuery) ∈ leftIndices.zip leftRows → + (index, rightQuery) ∈ rightIndices.zip rightRows → + leftQuery ≠ rightQuery → + leftQuery.flatten.length < 2 ^ 61 → + rightQuery.flatten.length < 2 ^ 61 → + ∃ inputs, + inputs ⊆ + (Aiur.NativeAIR.PrunedMerkle.replay Aiur.NativeAIR.Blake3.digest dimensions capHeight leftIndices + leftRows leftProof).inputs ++ + (Aiur.NativeAIR.PrunedMerkle.replay Aiur.NativeAIR.Blake3.digest dimensions capHeight + rightIndices rightRows rightProof).inputs ∧ + Aiur.NativeAIR.Merkle.CollisionOn Aiur.NativeAIR.Blake3.digest inputs ∧ + inputs.length ≤ 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) ∧ + ∀ (input : List UInt8), input ∈ inputs → Aiur.NativeAIR.Blake3.NativeInput input +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseRow_length +∀ (values : List Aiur.NativeAIR.ProofCodec.Extension), + (Aiur.NativeAIR.ExtensionMmcs.baseRow values).length = values.length * 2 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseRow_injective +∀ {left right : List Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.ExtensionMmcs.baseRow left = Aiur.NativeAIR.ExtensionMmcs.baseRow right → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseRows_length +∀ (rows : List (List Aiur.NativeAIR.ProofCodec.Extension)), + (Aiur.NativeAIR.ExtensionMmcs.baseRows rows).length = rows.length +AXIOMS [propext] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseRows_injective +∀ {left right : List (List Aiur.NativeAIR.ProofCodec.Extension)}, + Aiur.NativeAIR.ExtensionMmcs.baseRows left = Aiur.NativeAIR.ExtensionMmcs.baseRows right → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseRows_fields +∀ (rows : List (List Aiur.NativeAIR.ProofCodec.Extension)), + (Aiur.NativeAIR.ExtensionMmcs.baseRows rows).flatten.length = rows.flatten.length * 2 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseDimensions_length +∀ (wordBits : Nat) (dimensions : List Aiur.NativeAIR.Merkle.Dimensions), + (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions).length = dimensions.length +AXIOMS [propext] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseDimensions_heights +∀ (wordBits : Nat) (dimensions : List Aiur.NativeAIR.Merkle.Dimensions), + List.map Aiur.NativeAIR.Merkle.Dimensions.logHeight + (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) = + List.map Aiur.NativeAIR.Merkle.Dimensions.logHeight dimensions +AXIOMS [propext] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseDimensions_maxHeight +∀ (wordBits : Nat) (dimensions : List Aiur.NativeAIR.Merkle.Dimensions), + Aiur.NativeAIR.Merkle.maxHeight (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) = + Aiur.NativeAIR.Merkle.maxHeight dimensions +AXIOMS [propext] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseDimensions_covered +∀ (wordBits : Nat) (dimensions : List Aiur.NativeAIR.Merkle.Dimensions) (capHeight : Nat), + Aiur.NativeAIR.Merkle.covered (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) capHeight = + Aiur.NativeAIR.Merkle.covered dimensions capHeight +AXIOMS [propext] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseDimensions_exact +∀ {wordBits : Nat} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions}, + Aiur.NativeAIR.ExtensionMmcs.WidthsFit wordBits dimensions → + Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions = + List.map (fun dimension => { width := dimension.width * 2, logHeight := dimension.logHeight }) dimensions +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.shape_base +∀ {wordBits : Nat} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} + {rows : List (List Aiur.NativeAIR.ProofCodec.Extension)}, + Aiur.NativeAIR.ExtensionMmcs.WidthsFit wordBits dimensions → + Aiur.NativeAIR.Merkle.shape (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) + (Aiur.NativeAIR.ExtensionMmcs.baseRows rows) = + Aiur.NativeAIR.ExtensionMmcs.shape dimensions rows +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.fri_width_fits +∀ {logArity height : Nat}, + logArity ≤ 32 → Aiur.NativeAIR.ExtensionMmcs.WidthsFit 64 [{ width := 2 ^ logArity, logHeight := height }] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.baseRows_query +∀ {indices : List Nat} {rows : List (List (List Aiur.NativeAIR.ProofCodec.Extension))} {index : Nat} + {query : List (List Aiur.NativeAIR.ProofCodec.Extension)}, + (index, query) ∈ indices.zip rows → + (index, Aiur.NativeAIR.ExtensionMmcs.baseRows query) ∈ + indices.zip (List.map Aiur.NativeAIR.ExtensionMmcs.baseRows rows) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.replay_shape +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {wordBits capHeight index : Nat} + {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {rows : List (List Aiur.NativeAIR.ProofCodec.Extension)} + {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.ExtensionMmcs.WidthsFit wordBits dimensions → + Aiur.NativeAIR.ExtensionMmcs.replay hash wordBits dimensions capHeight index rows proof = some result → + Aiur.NativeAIR.ExtensionMmcs.shape dimensions rows = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.verifyMulti_individual +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {wordBits capHeight index : Nat} + {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {indices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} + {rows : List (List (List Aiur.NativeAIR.ProofCodec.Extension))} + {query : List (List Aiur.NativeAIR.ProofCodec.Extension)} {proof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.ExtensionMmcs.verifyMulti hash wordBits dimensions capHeight indices cap rows proof = true → + (index, query) ∈ indices.zip rows → + ∃ path result, + Aiur.NativeAIR.ExtensionMmcs.replay hash wordBits dimensions capHeight index query path = some result ∧ + Aiur.NativeAIR.ExtensionMmcs.verify hash wordBits dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ + (Aiur.NativeAIR.ExtensionMmcs.replayMulti hash wordBits dimensions capHeight indices rows proof).inputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.verifyMulti_shape +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {wordBits capHeight index : Nat} + {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {indices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} + {rows : List (List (List Aiur.NativeAIR.ProofCodec.Extension))} + {query : List (List Aiur.NativeAIR.ProofCodec.Extension)} {proof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.ExtensionMmcs.WidthsFit wordBits dimensions → + Aiur.NativeAIR.ExtensionMmcs.verifyMulti hash wordBits dimensions capHeight indices cap rows proof = true → + (index, query) ∈ indices.zip rows → Aiur.NativeAIR.ExtensionMmcs.shape dimensions query = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered_individual +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {wordBits capHeight index : Nat} + {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {indices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} + {rows : List (List (List Aiur.NativeAIR.ProofCodec.Extension))} + {query : List (List Aiur.NativeAIR.ProofCodec.Extension)} {proof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered hash wordBits dimensions capHeight indices cap rows proof = true → + (index, query) ∈ indices.zip rows → + ∃ path result, + Aiur.NativeAIR.ExtensionMmcs.replay hash wordBits dimensions capHeight index query path = some result ∧ + Aiur.NativeAIR.ExtensionMmcs.verifyCovered hash wordBits dimensions capHeight index cap query path = true ∧ + result.hashing.inputs ⊆ + (Aiur.NativeAIR.ExtensionMmcs.replayMulti hash wordBits dimensions capHeight indices rows proof).inputs +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.replay_native_input +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {wordBits capHeight index : Nat} + {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {rows : List (List Aiur.NativeAIR.ProofCodec.Extension)} + {proof : List Aiur.NativeAIR.Merkle.Digest} {result : Aiur.NativeAIR.Merkle.Replay}, + Aiur.NativeAIR.ExtensionMmcs.replay hash wordBits dimensions capHeight index rows proof = some result → + rows.flatten.length < 2 ^ 60 → + ∀ {input : List UInt8}, input ∈ result.hashing.inputs → Aiur.NativeAIR.Blake3.NativeInput input +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.verifyCovered_collision +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {wordBits capHeight index : Nat} + {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {cap : List Aiur.NativeAIR.Merkle.Digest} + {leftRows rightRows : List (List Aiur.NativeAIR.ProofCodec.Extension)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.ExtensionMmcs.verifyCovered hash wordBits dimensions capHeight index cap leftRows leftProof = true → + Aiur.NativeAIR.ExtensionMmcs.verifyCovered hash wordBits dimensions capHeight index cap rightRows rightProof = + true → + leftRows ≠ rightRows → + ∃ left right, + Aiur.NativeAIR.ExtensionMmcs.replay hash wordBits dimensions capHeight index leftRows leftProof = some left ∧ + Aiur.NativeAIR.ExtensionMmcs.replay hash wordBits dimensions capHeight index rightRows rightProof = + some right ∧ + Aiur.NativeAIR.Merkle.CollisionOn hash (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ + 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered_collision +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {wordBits capHeight index : Nat} + {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {leftIndices rightIndices : List Nat} + {cap : List Aiur.NativeAIR.Merkle.Digest} + {leftRows rightRows : List (List (List Aiur.NativeAIR.ProofCodec.Extension))} + {leftQuery rightQuery : List (List Aiur.NativeAIR.ProofCodec.Extension)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered hash wordBits dimensions capHeight leftIndices cap leftRows + leftProof = + true → + Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered hash wordBits dimensions capHeight rightIndices cap rightRows + rightProof = + true → + (index, leftQuery) ∈ leftIndices.zip leftRows → + (index, rightQuery) ∈ rightIndices.zip rightRows → + leftQuery ≠ rightQuery → + ∃ inputs, + inputs ⊆ + (Aiur.NativeAIR.ExtensionMmcs.replayMulti hash wordBits dimensions capHeight leftIndices leftRows + leftProof).inputs ++ + (Aiur.NativeAIR.ExtensionMmcs.replayMulti hash wordBits dimensions capHeight rightIndices rightRows + rightProof).inputs ∧ + Aiur.NativeAIR.Merkle.CollisionOn hash inputs ∧ + inputs.length ≤ 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) ∧ + ∀ (input : List UInt8), + input ∈ inputs → + input.length ≤ max 64 (16 * max leftQuery.flatten.length rightQuery.flatten.length) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.blake3_native_collision +∀ {wordBits capHeight index : Nat} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} + {cap : List Aiur.NativeAIR.Merkle.Digest} {leftRows rightRows : List (List Aiur.NativeAIR.ProofCodec.Extension)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.ExtensionMmcs.verifyCovered Aiur.NativeAIR.Blake3.digest wordBits dimensions capHeight index cap + leftRows leftProof = + true → + Aiur.NativeAIR.ExtensionMmcs.verifyCovered Aiur.NativeAIR.Blake3.digest wordBits dimensions capHeight index cap + rightRows rightProof = + true → + leftRows ≠ rightRows → + leftRows.flatten.length < 2 ^ 60 → + rightRows.flatten.length < 2 ^ 60 → + ∃ left right, + Aiur.NativeAIR.ExtensionMmcs.replay Aiur.NativeAIR.Blake3.digest wordBits dimensions capHeight index + leftRows leftProof = + some left ∧ + Aiur.NativeAIR.ExtensionMmcs.replay Aiur.NativeAIR.Blake3.digest wordBits dimensions capHeight index + rightRows rightProof = + some right ∧ + Aiur.NativeAIR.Merkle.CollisionOn Aiur.NativeAIR.Blake3.digest + (left.hashing.inputs ++ right.hashing.inputs) ∧ + (left.hashing.inputs ++ right.hashing.inputs).length ≤ + 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) ∧ + ∀ (input : List UInt8), + input ∈ left.hashing.inputs ++ right.hashing.inputs → Aiur.NativeAIR.Blake3.NativeInput input +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.ExtensionMmcs.blake3_multi_native_collision +∀ {wordBits capHeight index : Nat} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} + {leftIndices rightIndices : List Nat} {cap : List Aiur.NativeAIR.Merkle.Digest} + {leftRows rightRows : List (List (List Aiur.NativeAIR.ProofCodec.Extension))} + {leftQuery rightQuery : List (List Aiur.NativeAIR.ProofCodec.Extension)} + {leftProof rightProof : List Aiur.NativeAIR.Merkle.Digest}, + Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered Aiur.NativeAIR.Blake3.digest wordBits dimensions capHeight leftIndices + cap leftRows leftProof = + true → + Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered Aiur.NativeAIR.Blake3.digest wordBits dimensions capHeight + rightIndices cap rightRows rightProof = + true → + (index, leftQuery) ∈ leftIndices.zip leftRows → + (index, rightQuery) ∈ rightIndices.zip rightRows → + leftQuery ≠ rightQuery → + leftQuery.flatten.length < 2 ^ 60 → + rightQuery.flatten.length < 2 ^ 60 → + ∃ inputs, + inputs ⊆ + (Aiur.NativeAIR.ExtensionMmcs.replayMulti Aiur.NativeAIR.Blake3.digest wordBits dimensions + capHeight leftIndices leftRows leftProof).inputs ++ + (Aiur.NativeAIR.ExtensionMmcs.replayMulti Aiur.NativeAIR.Blake3.digest wordBits dimensions + capHeight rightIndices rightRows rightProof).inputs ∧ + Aiur.NativeAIR.Merkle.CollisionOn Aiur.NativeAIR.Blake3.digest inputs ∧ + inputs.length ≤ 2 + 6 * (Aiur.NativeAIR.Merkle.maxHeight dimensions - capHeight) ∧ + ∀ (input : List UInt8), input ∈ inputs → Aiur.NativeAIR.Blake3.NativeInput input +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_bound +∀ (bits index : Nat), Aiur.NativeAIR.FriDomain.reverseBits bits index < 2 ^ bits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_zero +∀ (bits : Nat), Aiur.NativeAIR.FriDomain.reverseBits bits 0 = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_zero_width +∀ (index : Nat), Aiur.NativeAIR.FriDomain.reverseBits 0 index = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_mod +∀ (bits index : Nat), + Aiur.NativeAIR.FriDomain.reverseBits bits (index % 2 ^ bits) = Aiur.NativeAIR.FriDomain.reverseBits bits index +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_involution +∀ (bits index : Nat), + Aiur.NativeAIR.FriDomain.reverseBits bits (Aiur.NativeAIR.FriDomain.reverseBits bits index) = index % 2 ^ bits +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_injective +∀ {bits left right : Nat}, + left < 2 ^ bits → + right < 2 ^ bits → + Aiur.NativeAIR.FriDomain.reverseBits bits left = Aiur.NativeAIR.FriDomain.reverseBits bits right → left = right +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_surjective +∀ {bits index : Nat}, + index < 2 ^ bits → ∃ original, original < 2 ^ bits ∧ Aiur.NativeAIR.FriDomain.reverseBits bits original = index +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.index_split_bound +∀ {low high index : Nat}, index < 2 ^ (high + low) → index / 2 ^ low < 2 ^ high +AXIOMS [propext] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_split +∀ {high low index : Nat}, + index < 2 ^ (high + low) → + Aiur.NativeAIR.FriDomain.reverseBits (high + low) index = + Aiur.NativeAIR.FriDomain.reverseBits low (index % 2 ^ low) * 2 ^ high + + Aiur.NativeAIR.FriDomain.reverseBits high (index / 2 ^ low) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_padding +∀ {bits index : Nat}, + index < 2 ^ bits → + ∀ (extra : Nat), + Aiur.NativeAIR.FriDomain.reverseBits (extra + bits) index = + Aiur.NativeAIR.FriDomain.reverseBits bits index * 2 ^ extra +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.wordReverse_eq +∀ {wordBits bits index : Nat}, + bits ≤ wordBits → + index < 2 ^ bits → + Aiur.NativeAIR.FriDomain.wordReverse wordBits bits index = Aiur.NativeAIR.FriDomain.reverseBits bits index +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.generator_nested +∀ (parent child : Aiur.NativeAIR.Domain.Subgroup), + ↑child ≤ ↑parent → + Aiur.NativeAIR.Domain.generator parent ^ 2 ^ (↑parent - ↑child) = Aiur.NativeAIR.Domain.generator child +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_eq +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), + Aiur.NativeAIR.FriDomain.queryPoint domain index = + Aiur.NativeAIR.Domain.generator domain ^ Aiur.NativeAIR.FriDomain.reverseBits (↑domain) index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_domain +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), + Aiur.NativeAIR.FriDomain.queryPoint domain index = + Aiur.NativeAIR.Domain.point domain ⟨Aiur.NativeAIR.FriDomain.reverseBits (↑domain) index, ⋯⟩ +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_injective +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) {left right : Nat}, + left < Aiur.NativeAIR.Domain.size domain → + right < Aiur.NativeAIR.Domain.size domain → + Aiur.NativeAIR.FriDomain.queryPoint domain left = Aiur.NativeAIR.FriDomain.queryPoint domain right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_surjective +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Fin (Aiur.NativeAIR.Domain.size domain)), + ∃ query, + query < Aiur.NativeAIR.Domain.size domain ∧ + Aiur.NativeAIR.FriDomain.queryPoint domain query = Aiur.NativeAIR.Domain.point domain index +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_nonzero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), Aiur.NativeAIR.FriDomain.queryPoint domain index ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_power +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), + Aiur.NativeAIR.FriDomain.queryPoint domain index ^ Aiur.NativeAIR.Domain.size domain = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_zero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), Aiur.NativeAIR.FriDomain.queryPoint domain 0 = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_padding +∀ (parent child : Aiur.NativeAIR.Domain.Subgroup), + ↑child ≤ ↑parent → + ∀ {index : Nat}, + index < Aiur.NativeAIR.Domain.size child → + Aiur.NativeAIR.FriDomain.queryPoint parent index = Aiur.NativeAIR.FriDomain.queryPoint child index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.index_join_bound +∀ {high low index slot : Nat}, index < 2 ^ high → slot < 2 ^ low → index * 2 ^ low + slot < 2 ^ (high + low) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.reverseBits_join +∀ {high low index slot : Nat}, + index < 2 ^ high → + slot < 2 ^ low → + Aiur.NativeAIR.FriDomain.reverseBits (high + low) (index * 2 ^ low + slot) = + Aiur.NativeAIR.FriDomain.reverseBits low slot * 2 ^ high + Aiur.NativeAIR.FriDomain.reverseBits high index +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.foldNode_eq +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup), + ↑arity ≤ ↑parent → + ∀ {index slot : Nat}, + index < 2 ^ (↑parent - ↑arity) → + slot < Aiur.NativeAIR.Domain.size arity → + Aiur.NativeAIR.FriDomain.foldNode parent arity index slot = + Aiur.NativeAIR.FriDomain.queryPoint parent (index * Aiur.NativeAIR.Domain.size arity + slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.foldNode_injective +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup), + ↑arity ≤ ↑parent → + ∀ {index left right : Nat}, + index < 2 ^ (↑parent - ↑arity) → + left < Aiur.NativeAIR.Domain.size arity → + right < Aiur.NativeAIR.Domain.size arity → + Aiur.NativeAIR.FriDomain.foldNode parent arity index left = + Aiur.NativeAIR.FriDomain.foldNode parent arity index right → + left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.foldNode_nonzero +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup), + ↑arity ≤ ↑parent → + ∀ {index slot : Nat}, + index < 2 ^ (↑parent - ↑arity) → + slot < Aiur.NativeAIR.Domain.size arity → Aiur.NativeAIR.FriDomain.foldNode parent arity index slot ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.foldNode_power +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ (index slot : Nat), + Aiur.NativeAIR.FriDomain.foldNode parent arity index slot ^ Aiur.NativeAIR.Domain.size arity = + Aiur.NativeAIR.FriDomain.queryPoint child index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.queryPoint_reduce +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < Aiur.NativeAIR.Domain.size parent → + Aiur.NativeAIR.FriDomain.queryPoint parent index ^ Aiur.NativeAIR.Domain.size arity = + Aiur.NativeAIR.FriDomain.queryPoint child (index / Aiur.NativeAIR.Domain.size arity) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.inputPoint_nonzero +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), Aiur.NativeAIR.FriDomain.inputPoint domain index ≠ 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.inputPoint_injective +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) {left right : Nat}, + left < Aiur.NativeAIR.Domain.size domain → + right < Aiur.NativeAIR.Domain.size domain → + Aiur.NativeAIR.FriDomain.inputPoint domain left = Aiur.NativeAIR.FriDomain.inputPoint domain right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.inputPoint_power +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), + Aiur.NativeAIR.FriDomain.inputPoint domain index ^ Aiur.NativeAIR.Domain.size domain = + 7 ^ Aiur.NativeAIR.Domain.size domain +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.coset_shift_certificate +Aiur.G.pow 7 (2 ^ 32) ≠ 1 +AXIOMS [propext] +ROOT Aiur.NativeAIR.FriDomain.coset_shift_not_root +∀ (domain : Aiur.NativeAIR.Domain.Subgroup), 7 ^ Aiur.NativeAIR.Domain.size domain ≠ 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.inputPoint_not_root +∀ (domain : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), + Aiur.NativeAIR.FriDomain.inputPoint domain index ^ Aiur.NativeAIR.Domain.size domain ≠ 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriDomain.inputPoint_trace_disjoint +∀ (query trace : Aiur.NativeAIR.Domain.Subgroup), + ↑trace ≤ ↑query → + ∀ (index : Nat) (row : Fin (Aiur.NativeAIR.Domain.size trace)), + Aiur.NativeAIR.FriDomain.inputPoint query index ≠ Aiur.NativeAIR.Domain.point trace row +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.isZero_nil +∀ {R : Type} [inst : Grind.CommRing R], Aiur.NativeAIR.Polynomial.IsZero [] +AXIOMS [] +ROOT Aiur.NativeAIR.Polynomial.isZero_iff_all +∀ {R : Type} [inst : Grind.CommRing R] [inst_1 : BEq R] [LawfulBEq R] (coefficients : List R), + Aiur.NativeAIR.Polynomial.IsZero coefficients ↔ (coefficients.all fun x => x == 0) = true +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.isZero_cons +∀ {R : Type} [inst : Grind.CommRing R] (coefficient : R) (rest : List R), + Aiur.NativeAIR.Polynomial.IsZero (coefficient :: rest) ↔ coefficient = 0 ∧ Aiur.NativeAIR.Polynomial.IsZero rest +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.isZero_append +∀ {R : Type} [inst : Grind.CommRing R] (left right : List R), + Aiur.NativeAIR.Polynomial.IsZero (left ++ right) ↔ + Aiur.NativeAIR.Polynomial.IsZero left ∧ Aiur.NativeAIR.Polynomial.IsZero right +AXIOMS [propext] +ROOT Aiur.NativeAIR.Polynomial.monic_nonzero +∀ {R : Type} [inst : Grind.CommRing R] {coefficients : List R}, + Aiur.NativeAIR.Polynomial.Monic coefficients → 1 ≠ 0 → ¬Aiur.NativeAIR.Polynomial.IsZero coefficients +AXIOMS [propext] +ROOT Aiur.NativeAIR.Polynomial.sub_nil +∀ {R : Type} [inst : Grind.CommRing R] (left : List R), Aiur.NativeAIR.Polynomial.sub left [] = left +AXIOMS [] +ROOT Aiur.NativeAIR.Polynomial.horner_zero +∀ {R : Type} [inst : Grind.CommRing R] (point : R) {coefficients : List R}, + Aiur.NativeAIR.Polynomial.IsZero coefficients → Aiur.NativeAIR.Quotient.horner point coefficients = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.add_length +∀ {R : Type} [inst : Grind.CommRing R] (left right : List R), + (Aiur.NativeAIR.Polynomial.add left right).length = max left.length right.length +AXIOMS [propext] +ROOT Aiur.NativeAIR.Polynomial.sub_length +∀ {R : Type} [inst : Grind.CommRing R] (left right : List R), + (Aiur.NativeAIR.Polynomial.sub left right).length = max left.length right.length +AXIOMS [propext] +ROOT Aiur.NativeAIR.Polynomial.scale_length +∀ {R : Type} [inst : Grind.CommRing R] (scalar : R) (coefficients : List R), + (Aiur.NativeAIR.Polynomial.scale scalar coefficients).length = coefficients.length +AXIOMS [propext] +ROOT Aiur.NativeAIR.Polynomial.sub_append +∀ {R : Type} [inst : Grind.CommRing R] (left right firstTail secondTail : List R), + left.length = right.length → + Aiur.NativeAIR.Polynomial.sub (left ++ firstTail) (right ++ secondTail) = + Aiur.NativeAIR.Polynomial.sub left right ++ Aiur.NativeAIR.Polynomial.sub firstTail secondTail +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.sub_append_left +∀ {R : Type} [inst : Grind.CommRing R] (left right tail : List R), + right.length ≤ left.length → + Aiur.NativeAIR.Polynomial.sub (left ++ tail) right = Aiur.NativeAIR.Polynomial.sub left right ++ tail +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_add +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (left right : List R), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.add left right) = + Aiur.NativeAIR.Quotient.horner point left + Aiur.NativeAIR.Quotient.horner point right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_neg +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner point (List.map (fun x => 0 - x) coefficients) = + 0 - Aiur.NativeAIR.Quotient.horner point coefficients +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_sub +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (left right : List R), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.sub left right) = + Aiur.NativeAIR.Quotient.horner point left - Aiur.NativeAIR.Quotient.horner point right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_scale +∀ {R : Type} [inst : Grind.CommRing R] (point scalar : R) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.scale scalar coefficients) = + scalar * Aiur.NativeAIR.Quotient.horner point coefficients +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.mulLinear_length +∀ {R : Type} [inst : Grind.CommRing R] (root : R) (coefficients : List R), + (Aiur.NativeAIR.Polynomial.mulLinear root coefficients).length = coefficients.length + 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_mulLinear +∀ {R : Type} [inst : Grind.CommRing R] (point root : R) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.mulLinear root coefficients) = + (point - root) * Aiur.NativeAIR.Quotient.horner point coefficients +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.fromRoots_length +∀ {R : Type} [inst : Grind.CommRing R] (roots : List R), + (Aiur.NativeAIR.Polynomial.fromRoots roots).length = roots.length + 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_fromRoots +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (roots : List R), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.fromRoots roots) = + Aiur.NativeAIR.LogUp.product (List.map (fun x => point - x) roots) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.mulLinear_monic +∀ {R : Type} [inst : Grind.CommRing R] (root : R) {coefficients : List R}, + Aiur.NativeAIR.Polynomial.Monic coefficients → + Aiur.NativeAIR.Polynomial.Monic (Aiur.NativeAIR.Polynomial.mulLinear root coefficients) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.fromRoots_monic +∀ {R : Type} [inst : Grind.CommRing R] (roots : List R), + Aiur.NativeAIR.Polynomial.Monic (Aiur.NativeAIR.Polynomial.fromRoots roots) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.fromRoots_nonzero +∀ {R : Type} [inst : Grind.CommRing R] (roots : List R), + 1 ≠ 0 → ¬Aiur.NativeAIR.Polynomial.IsZero (Aiur.NativeAIR.Polynomial.fromRoots roots) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.fromRoots_vanishes +∀ {R : Type} [inst : Grind.CommRing R] (roots : List R) (point : R), + point ∈ roots → Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.fromRoots roots) = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.powerMinus_length +∀ {R : Type} [inst : Grind.CommRing R] (degree : Nat) (constant : R), + (Aiur.NativeAIR.Polynomial.powerMinus degree constant).length = degree + 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.powerMinus_monic +∀ {R : Type} [inst : Grind.CommRing R] {degree : Nat}, + 0 < degree → ∀ (constant : R), Aiur.NativeAIR.Polynomial.Monic (Aiur.NativeAIR.Polynomial.powerMinus degree constant) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_replicate_zero +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (count : Nat), + Aiur.NativeAIR.Quotient.horner point (List.replicate count 0) = 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.horner_powerMinus +∀ {R : Type} [inst : Grind.CommRing R] (point constant : R) (degree : Nat), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.powerMinus degree constant) = + point ^ degree - constant +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.divide_length +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (coefficients : List R), + (Aiur.NativeAIR.Polynomial.divide point coefficients).length = coefficients.length - 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.divide_factor +∀ {R : Type} [inst : Grind.CommRing R] (point root : R) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner point coefficients = + Aiur.NativeAIR.Quotient.horner root coefficients + + (point - root) * Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.divide root coefficients) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.zero_of_divide_zero +∀ {R : Type} [inst : Grind.CommRing R] (root : R) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner root coefficients = 0 → + Aiur.NativeAIR.Polynomial.IsZero (Aiur.NativeAIR.Polynomial.divide root coefficients) → + Aiur.NativeAIR.Polynomial.IsZero coefficients +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.divide_nonzero +∀ {R : Type} [inst : Grind.CommRing R] (root : R) {coefficients : List R}, + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + Aiur.NativeAIR.Quotient.horner root coefficients = 0 → + ¬Aiur.NativeAIR.Polynomial.IsZero (Aiur.NativeAIR.Polynomial.divide root coefficients) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.divide_root +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (root point : R) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner root coefficients = 0 → + Aiur.NativeAIR.Quotient.horner point coefficients = 0 → + point ≠ root → Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.divide root coefficients) = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.roots_lt_length +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (coefficients roots : List R), + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + roots.Nodup → + (∀ (point : R), point ∈ roots → Aiur.NativeAIR.Quotient.horner point coefficients = 0) → + roots.length < coefficients.length +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.roots_le_degree +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (coefficients roots : List R), + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + roots.Nodup → + (∀ (point : R), point ∈ roots → Aiur.NativeAIR.Quotient.horner point coefficients = 0) → + roots.length ≤ coefficients.length - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.zero_of_roots +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (coefficients roots : List R), + roots.Nodup → + coefficients.length ≤ roots.length → + (∀ (point : R), point ∈ roots → Aiur.NativeAIR.Quotient.horner point coefficients = 0) → + Aiur.NativeAIR.Polynomial.IsZero coefficients +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.zero_sub_of_samples +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (left right samples : List R), + samples.Nodup → + left.length ≤ samples.length → + right.length ≤ samples.length → + (∀ (point : R), + point ∈ samples → + Aiur.NativeAIR.Quotient.horner point left = Aiur.NativeAIR.Quotient.horner point right) → + Aiur.NativeAIR.Polynomial.IsZero (Aiur.NativeAIR.Polynomial.sub left right) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.equal_of_samples +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (left right samples : List R), + samples.Nodup → + left.length ≤ samples.length → + right.length ≤ samples.length → + (∀ (point : R), + point ∈ samples → + Aiur.NativeAIR.Quotient.horner point left = Aiur.NativeAIR.Quotient.horner point right) → + ∀ (point : R), Aiur.NativeAIR.Quotient.horner point left = Aiur.NativeAIR.Quotient.horner point right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.monic_zero_sub_of_samples +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (left right samples : List R), + Aiur.NativeAIR.Polynomial.Monic left → + Aiur.NativeAIR.Polynomial.Monic right → + samples.Nodup → + left.length = right.length → + left.length ≤ samples.length + 1 → + (∀ (point : R), + point ∈ samples → + Aiur.NativeAIR.Quotient.horner point left = Aiur.NativeAIR.Quotient.horner point right) → + Aiur.NativeAIR.Polynomial.IsZero (Aiur.NativeAIR.Polynomial.sub left right) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.monic_equal_of_samples +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (left right samples : List R), + Aiur.NativeAIR.Polynomial.Monic left → + Aiur.NativeAIR.Polynomial.Monic right → + samples.Nodup → + left.length = right.length → + left.length ≤ samples.length + 1 → + (∀ (point : R), + point ∈ samples → + Aiur.NativeAIR.Quotient.horner point left = Aiur.NativeAIR.Quotient.horner point right) → + ∀ (point : R), Aiur.NativeAIR.Quotient.horner point left = Aiur.NativeAIR.Quotient.horner point right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.root_product_identity +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (roots : List R) (constant : R), + roots.Nodup → + 0 < roots.length → + (∀ (root : R), root ∈ roots → root ^ roots.length = constant) → + ∀ (point : R), + Aiur.NativeAIR.LogUp.product (List.map (fun x => point - x) roots) = point ^ roots.length - constant +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.root_count_le +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ [inst_1 : BEq R] [LawfulBEq R] (coefficients samples : List R), + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + samples.Nodup → + (List.filter (fun point => Aiur.NativeAIR.Quotient.horner point coefficients == 0) samples).length ≤ + coefficients.length - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.equal_count_le +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ [inst_1 : BEq R] [LawfulBEq R] (left right samples : List R), + ¬Aiur.NativeAIR.Polynomial.IsZero (Aiur.NativeAIR.Polynomial.sub left right) → + samples.Nodup → + (List.filter + (fun point => Aiur.NativeAIR.Quotient.horner point left == Aiur.NativeAIR.Quotient.horner point right) + samples).length ≤ + max left.length right.length - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.base_roots_lt_length +∀ (coefficients roots : List Aiur.G), + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + roots.Nodup → + (∀ (point : Aiur.G), point ∈ roots → Aiur.NativeAIR.Quotient.horner point coefficients = 0) → + roots.length < coefficients.length +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.extension_roots_lt_length +∀ (coefficients roots : List Aiur.NativeAIR.ProofCodec.Extension), + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + roots.Nodup → + (∀ (point : Aiur.NativeAIR.ProofCodec.Extension), + point ∈ roots → Aiur.NativeAIR.Quotient.horner point coefficients = 0) → + roots.length < coefficients.length +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.base_root_count_le +∀ (coefficients samples : List Aiur.G), + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + samples.Nodup → + (List.filter (fun point => Aiur.NativeAIR.Quotient.horner point coefficients == 0) samples).length ≤ + coefficients.length - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.extension_root_count_le +∀ (coefficients samples : List Aiur.NativeAIR.ProofCodec.Extension), + ¬Aiur.NativeAIR.Polynomial.IsZero coefficients → + samples.Nodup → + (List.filter (fun point => Aiur.NativeAIR.Quotient.horner point coefficients == 0) samples).length ≤ + coefficients.length - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.foldingNodes_length +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup) (index : Nat), + (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index).length = Aiur.NativeAIR.Domain.size arity +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.foldingNodes_nodup +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup), + ↑arity ≤ ↑parent → + ∀ {index : Nat}, index < 2 ^ (↑parent - ↑arity) → (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index).Nodup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.foldingNodes_powers +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ (index : Nat) (node : Aiur.G), + node ∈ Aiur.NativeAIR.Polynomial.foldingNodes parent arity index → + node ^ Aiur.NativeAIR.Domain.size arity = Aiur.NativeAIR.FriDomain.queryPoint child index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Polynomial.folding_product_identity +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (point : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.LogUp.product + (List.map (fun node => point - Aiur.NativeAIR.ProofCodec.Extension.ofBase node) + (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index)) = + point ^ Aiur.NativeAIR.Domain.size arity - + Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint child index) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.derivative_zero +∀ {R : Type} [inst : Grind.CommRing R] (point : R) {coefficients : List R}, + Aiur.NativeAIR.Polynomial.IsZero coefficients → Aiur.NativeAIR.Interpolation.derivativeValue point coefficients = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.derivative_neg +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (coefficients : List R), + Aiur.NativeAIR.Interpolation.derivativeValue point (List.map (fun x => 0 - x) coefficients) = + 0 - Aiur.NativeAIR.Interpolation.derivativeValue point coefficients +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.derivative_sub +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (left right : List R), + Aiur.NativeAIR.Interpolation.derivativeValue point (Aiur.NativeAIR.Polynomial.sub left right) = + Aiur.NativeAIR.Interpolation.derivativeValue point left - Aiur.NativeAIR.Interpolation.derivativeValue point right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.divide_diagonal +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.divide point coefficients) = + Aiur.NativeAIR.Interpolation.derivativeValue point coefficients +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.monomial_value +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (degree : Nat), + Aiur.NativeAIR.Quotient.horner point (List.replicate degree 0 ++ [1]) = point ^ degree +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.monomial_derivative +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (degree : Nat), + Aiur.NativeAIR.Interpolation.derivativeValue point (List.replicate degree 0 ++ [1]) = ↑degree * point ^ (degree - 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.powerMinus_derivative +∀ {R : Type} [inst : Grind.CommRing R] (point constant : R) (degree : Nat), + Aiur.NativeAIR.Interpolation.derivativeValue point (Aiur.NativeAIR.Polynomial.powerMinus degree constant) = + ↑degree * point ^ (degree - 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.root_product_derivative +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (roots : List R) (constant : R), + roots.Nodup → + 0 < roots.length → + (∀ (root : R), root ∈ roots → root ^ roots.length = constant) → + ∀ (point : R), + Aiur.NativeAIR.Interpolation.derivativeValue point (Aiur.NativeAIR.Polynomial.fromRoots roots) = + ↑roots.length * point ^ (roots.length - 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.root_quotient_diagonal +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (roots : List R) (constant : R), + roots.Nodup → + 0 < roots.length → + (∀ (root : R), root ∈ roots → root ^ roots.length = constant) → + ∀ (point : R), + Aiur.NativeAIR.Quotient.horner point + (Aiur.NativeAIR.Polynomial.divide point (Aiur.NativeAIR.Polynomial.fromRoots roots)) = + ↑roots.length * point ^ (roots.length - 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.closed_weight_diagonal +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (roots : List R) (constant scale root : R), + roots.Nodup → + 0 < roots.length → + (∀ (root : R), root ∈ roots → root ^ roots.length = constant) → + root ∈ roots → + ↑roots.length * constant * scale = 1 → + root * scale * + Aiur.NativeAIR.Quotient.horner root + (Aiur.NativeAIR.Polynomial.divide root (Aiur.NativeAIR.Polynomial.fromRoots roots)) = + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.combine_length +∀ {R : Type} [inst : Grind.CommRing R] (vanishing : List R) (scale : R) (samples : List (R × R)), + (Aiur.NativeAIR.Interpolation.combine vanishing scale samples).length ≤ vanishing.length - 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.coefficients_length +∀ {R : Type} [inst : Grind.CommRing R] (samples : List (R × R)) (scale : R), + (Aiur.NativeAIR.Interpolation.coefficients samples scale).length ≤ samples.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.combine_zero +∀ {R : Type} [inst : Grind.CommRing R] (vanishing : List R) (scale point : R) (samples : List (R × R)), + (∀ (sample : R × R), + sample ∈ samples → + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.divide sample.fst vanishing) = 0) → + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Interpolation.combine vanishing scale samples) = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.combine_at_node +∀ {R : Type} [inst : Grind.CommRing R] (vanishing : List R) (scale root value : R) (samples : List (R × R)), + (List.map Prod.fst samples).Nodup → + (root, value) ∈ samples → + root * scale * Aiur.NativeAIR.Quotient.horner root (Aiur.NativeAIR.Polynomial.divide root vanishing) = 1 → + (∀ (sample : R × R), + sample ∈ samples → + sample.fst ≠ root → + Aiur.NativeAIR.Quotient.horner root (Aiur.NativeAIR.Polynomial.divide sample.fst vanishing) = 0) → + Aiur.NativeAIR.Quotient.horner root (Aiur.NativeAIR.Interpolation.combine vanishing scale samples) = value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.coefficients_at_node +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (samples : List (R × R)) (constant scale root value : R), + (List.map Prod.fst samples).Nodup → + 0 < samples.length → + (∀ (sample : R × R), sample ∈ samples → sample.fst ^ samples.length = constant) → + ↑samples.length * constant * scale = 1 → + (root, value) ∈ samples → + Aiur.NativeAIR.Quotient.horner root (Aiur.NativeAIR.Interpolation.coefficients samples scale) = value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.coefficients_unique +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (samples : List (R × R)) (constant scale : R) (candidate : List R), + (List.map Prod.fst samples).Nodup → + 0 < samples.length → + (∀ (sample : R × R), sample ∈ samples → sample.fst ^ samples.length = constant) → + ↑samples.length * constant * scale = 1 → + candidate.length ≤ samples.length → + (∀ (sample : R × R), + sample ∈ samples → Aiur.NativeAIR.Quotient.horner sample.fst candidate = sample.snd) → + Aiur.NativeAIR.Polynomial.IsZero + (Aiur.NativeAIR.Polynomial.sub candidate (Aiur.NativeAIR.Interpolation.coefficients samples scale)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.coefficients_evaluate +∀ {R : Type} [inst : Grind.CommRing R], + (∀ (a b : R), a * b = 0 → a = 0 ∨ b = 0) → + ∀ (samples : List (R × R)) (constant scale : R) (candidate : List R), + (List.map Prod.fst samples).Nodup → + 0 < samples.length → + (∀ (sample : R × R), sample ∈ samples → sample.fst ^ samples.length = constant) → + ↑samples.length * constant * scale = 1 → + candidate.length ≤ samples.length → + (∀ (sample : R × R), + sample ∈ samples → Aiur.NativeAIR.Quotient.horner sample.fst candidate = sample.snd) → + ∀ (point : R), + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Interpolation.coefficients samples scale) = + Aiur.NativeAIR.Quotient.horner point candidate +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.divide_inverse_value +∀ {R : Type} [inst : Grind.CommRing R] (vanishing : List R) (point root inverse : R), + Aiur.NativeAIR.Quotient.horner root vanishing = 0 → + (point - root) * inverse = 1 → + inverse * Aiur.NativeAIR.Quotient.horner point vanishing = + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Polynomial.divide root vanishing) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.weightedSum_polynomial +∀ (vanishing : List Aiur.NativeAIR.ProofCodec.Extension) (scale point : Aiur.NativeAIR.ProofCodec.Extension) + (samples : List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)), + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ samples → Aiur.NativeAIR.Quotient.horner sample.fst vanishing = 0) → + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ samples → point ≠ sample.fst) → + ∃ result, + Aiur.NativeAIR.Interpolation.weightedSum scale point samples = some result ∧ + result * Aiur.NativeAIR.Quotient.horner point vanishing = + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Interpolation.combine vanishing scale samples) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.evaluate_polynomial +∀ (samples : List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension)) + (constant scale point : Aiur.NativeAIR.ProofCodec.Extension), + (List.map Prod.fst samples).Nodup → + 0 < samples.length → + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ samples → sample.fst ^ samples.length = constant) → + ↑samples.length * constant * scale = 1 → + Aiur.NativeAIR.Interpolation.evaluate scale point samples = + some (Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Interpolation.coefficients samples scale)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldSamples_roots +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup) (index : Nat) (values : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + List.map Prod.fst (Aiur.NativeAIR.Interpolation.foldSamples parent arity index values) = + List.map Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldSamples_length +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup) (index : Nat) (values : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + (Aiur.NativeAIR.Interpolation.foldSamples parent arity index values).length = Aiur.NativeAIR.Domain.size arity +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldSamples_nodup +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup), + ↑arity ≤ ↑parent → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (values : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + (List.map Prod.fst (Aiur.NativeAIR.Interpolation.foldSamples parent arity index values)).Nodup +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldSamples_powers +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ (index : Nat) (values : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + ∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ Aiur.NativeAIR.Interpolation.foldSamples parent arity index values → + sample.fst ^ (Aiur.NativeAIR.Interpolation.foldSamples parent arity index values).length = + Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint child index) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldScale_inverse +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ (index : Nat), + ↑(Aiur.NativeAIR.Domain.size arity) * + Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint child index) * + Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Interpolation.foldScale parent arity index) = + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldRow_polynomial +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (values : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + ∀ (point : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Interpolation.foldRow parent arity index values point = + some + (Aiur.NativeAIR.Quotient.horner point + (Aiur.NativeAIR.Interpolation.coefficients + (Aiur.NativeAIR.Interpolation.foldSamples parent arity index values) + (Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.Interpolation.foldScale parent arity index)))) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldRow_reject_shape +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup) (index : Nat) (values : List Aiur.NativeAIR.ProofCodec.Extension) + (point : Aiur.NativeAIR.ProofCodec.Extension), + ↑arity > ↑parent ∨ index ≥ 2 ^ (↑parent - ↑arity) ∨ values.length ≠ Aiur.NativeAIR.Domain.size arity → + Aiur.NativeAIR.Interpolation.foldRow parent arity index values point = none +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldRow_at_node +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (values : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + ∀ (root value : Aiur.NativeAIR.ProofCodec.Extension), + (root, value) ∈ Aiur.NativeAIR.Interpolation.foldSamples parent arity index values → + Aiur.NativeAIR.Interpolation.foldRow parent arity index values root = some value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldRow_evaluate +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (values candidate : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + candidate.length ≤ Aiur.NativeAIR.Domain.size arity → + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ Aiur.NativeAIR.Interpolation.foldSamples parent arity index values → + Aiur.NativeAIR.Quotient.horner sample.fst candidate = sample.snd) → + ∀ (point : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Interpolation.foldRow parent arity index values point = + some (Aiur.NativeAIR.Quotient.horner point candidate) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Interpolation.foldRow_success +∀ {parent arity : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} {values : List Aiur.NativeAIR.ProofCodec.Extension} + {point result : Aiur.NativeAIR.ProofCodec.Extension}, + Aiur.NativeAIR.Interpolation.foldRow parent arity index values point = some result → + ↑arity ≤ ↑parent ∧ + index < 2 ^ (↑parent - ↑arity) ∧ + values.length = Aiur.NativeAIR.Domain.size arity ∧ + ∃ candidate, + candidate.length ≤ Aiur.NativeAIR.Domain.size arity ∧ + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ Aiur.NativeAIR.Interpolation.foldSamples parent arity index values → + Aiur.NativeAIR.Quotient.horner sample.fst candidate = sample.snd) ∧ + result = Aiur.NativeAIR.Quotient.horner point candidate +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.horner_split +∀ {R : Type} [inst : Grind.CommRing R] (point : R) (width : Nat) (coefficients : List R), + Aiur.NativeAIR.Quotient.horner point coefficients = + Aiur.NativeAIR.Quotient.horner point (List.take width coefficients) + + point ^ width * Aiur.NativeAIR.Quotient.horner point (List.drop width coefficients) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.rowCoefficients_length +∀ {R : Type} [inst : Grind.CommRing R] (arity : Aiur.NativeAIR.Domain.Subgroup) (point : R) (coefficients : List R), + (Aiur.NativeAIR.Folding.rowCoefficients arity point coefficients).length ≤ Aiur.NativeAIR.Domain.size arity +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Folding.rowCoefficients_value +∀ {R : Type} [inst : Grind.CommRing R] (arity : Aiur.NativeAIR.Domain.Subgroup) (point root : R) + (coefficients : List R), + root ^ Aiur.NativeAIR.Domain.size arity = point → + Aiur.NativeAIR.Quotient.horner root (Aiur.NativeAIR.Folding.rowCoefficients arity point coefficients) = + Aiur.NativeAIR.Quotient.horner root coefficients +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.rowCoefficients_fold +∀ {R : Type} [inst : Grind.CommRing R] (arity : Aiur.NativeAIR.Domain.Subgroup) (point challenge : R) + (coefficients : List R), + Aiur.NativeAIR.Quotient.horner challenge (Aiur.NativeAIR.Folding.rowCoefficients arity point coefficients) = + Aiur.NativeAIR.Quotient.horner point (Aiur.NativeAIR.Folding.foldCoefficients arity challenge coefficients) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.foldCoefficients_degree +∀ {R : Type} [inst : Grind.CommRing R] (arity : Aiur.NativeAIR.Domain.Subgroup) (challenge : R) (degree : Nat) + (coefficients : List R), + coefficients.length ≤ Aiur.NativeAIR.Domain.size arity * degree → + (Aiur.NativeAIR.Folding.foldCoefficients arity challenge coefficients).length ≤ degree +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Folding.foldRow_global +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (values coefficients : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ Aiur.NativeAIR.Interpolation.foldSamples parent arity index values → + Aiur.NativeAIR.Quotient.horner sample.fst coefficients = sample.snd) → + ∀ (challenge : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Interpolation.foldRow parent arity index values challenge = + some + (Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint child index)) + (Aiur.NativeAIR.Folding.foldCoefficients arity challenge coefficients)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.foldRow_codeword +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (coefficients : List Aiur.NativeAIR.ProofCodec.Extension) (challenge : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.Interpolation.foldRow parent arity index + (List.map + (fun root => + Aiur.NativeAIR.Quotient.horner (Aiur.NativeAIR.ProofCodec.Extension.ofBase root) coefficients) + (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index)) + challenge = + some + (Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint child index)) + (Aiur.NativeAIR.Folding.foldCoefficients arity challenge coefficients)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.foldRow_codeword_degree +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ (degree : Nat) (coefficients : List Aiur.NativeAIR.ProofCodec.Extension), + coefficients.length ≤ Aiur.NativeAIR.Domain.size arity * degree → + ∀ (challenge : Aiur.NativeAIR.ProofCodec.Extension), + ∃ folded, + folded.length ≤ degree ∧ + ∀ (index : Nat), + index < 2 ^ (↑parent - ↑arity) → + Aiur.NativeAIR.Interpolation.foldRow parent arity index + (List.map + (fun root => + Aiur.NativeAIR.Quotient.horner (Aiur.NativeAIR.ProofCodec.Extension.ofBase root) coefficients) + (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index)) + challenge = + some + (Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint child index)) + folded) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.values_of_agreement +∀ (parent arity : Aiur.NativeAIR.Domain.Subgroup) (index : Nat) + (values coefficients : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ Aiur.NativeAIR.Interpolation.foldSamples parent arity index values → + Aiur.NativeAIR.Quotient.horner sample.fst coefficients = sample.snd) → + values = + List.map + (fun root => Aiur.NativeAIR.Quotient.horner (Aiur.NativeAIR.ProofCodec.Extension.ofBase root) coefficients) + (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.Folding.interpolant_values +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (values : List Aiur.NativeAIR.ProofCodec.Extension), + values.length = Aiur.NativeAIR.Domain.size arity → + values = + List.map + (fun root => + Aiur.NativeAIR.Quotient.horner (Aiur.NativeAIR.ProofCodec.Extension.ofBase root) + (Aiur.NativeAIR.Interpolation.coefficients + (Aiur.NativeAIR.Interpolation.foldSamples parent arity index values) + (Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.Interpolation.foldScale parent arity index)))) + (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.interpolants_different +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (left right : List Aiur.NativeAIR.ProofCodec.Extension), + left.length = Aiur.NativeAIR.Domain.size arity → + right.length = Aiur.NativeAIR.Domain.size arity → + left ≠ right → + ¬Aiur.NativeAIR.Polynomial.IsZero + (Aiur.NativeAIR.Polynomial.sub + (Aiur.NativeAIR.Interpolation.coefficients + (Aiur.NativeAIR.Interpolation.foldSamples parent arity index left) + (Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.Interpolation.foldScale parent arity index))) + (Aiur.NativeAIR.Interpolation.coefficients + (Aiur.NativeAIR.Interpolation.foldSamples parent arity index right) + (Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.Interpolation.foldScale parent arity index)))) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.Folding.foldRow_equal_count_le +∀ (parent child arity : Aiur.NativeAIR.Domain.Subgroup), + ↑parent = ↑child + ↑arity → + ∀ {index : Nat}, + index < 2 ^ (↑parent - ↑arity) → + ∀ (left right challenges : List Aiur.NativeAIR.ProofCodec.Extension), + left.length = Aiur.NativeAIR.Domain.size arity → + right.length = Aiur.NativeAIR.Domain.size arity → + left ≠ right → + challenges.Nodup → + (List.filter + (fun challenge => + Aiur.NativeAIR.Interpolation.foldRow parent arity index left challenge == + Aiur.NativeAIR.Interpolation.foldRow parent arity index right challenge) + challenges).length ≤ + Aiur.NativeAIR.Domain.size arity - 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.reconstruct_eq +∀ {R : Type u_1} (arity : Aiur.NativeAIR.Domain.Subgroup) (index : Nat) (value : R) (siblings : List R), + siblings.length + 1 = Aiur.NativeAIR.Domain.size arity → + Aiur.NativeAIR.FriQuery.reconstruct arity index value siblings = + some (siblings.insertIdx (index % Aiur.NativeAIR.Domain.size arity) value) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.reconstruct_success +∀ {R : Type u_1} {arity : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R}, + Aiur.NativeAIR.FriQuery.reconstruct arity index value siblings = some row → + siblings.length + 1 = Aiur.NativeAIR.Domain.size arity ∧ + row = siblings.insertIdx (index % Aiur.NativeAIR.Domain.size arity) value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.reconstruct_length +∀ {R : Type u_1} {arity : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R}, + Aiur.NativeAIR.FriQuery.reconstruct arity index value siblings = some row → + row.length = Aiur.NativeAIR.Domain.size arity +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.reconstruct_self +∀ {R : Type u_1} {arity : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R}, + Aiur.NativeAIR.FriQuery.reconstruct arity index value siblings = some row → + row[index % Aiur.NativeAIR.Domain.size arity]? = some value +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.reconstruct_siblings +∀ {R : Type u_1} {arity : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} {value : R} {siblings row : List R}, + Aiur.NativeAIR.FriQuery.reconstruct arity index value siblings = some row → + row.eraseIdx (index % Aiur.NativeAIR.Domain.size arity) = siblings +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.step_success +∀ {state : Aiur.NativeAIR.FriQuery.State} {round : Aiur.NativeAIR.FriQuery.Round} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.StepResult}, + Aiur.NativeAIR.FriQuery.step state round openings = some result → + 0 < ↑round.arity ∧ + ↑round.arity ≤ ↑state.domain ∧ + ∃ child values folded, + Aiur.NativeAIR.Domain.ofLogSize (↑state.domain - ↑round.arity) = some child ∧ + Aiur.NativeAIR.FriQuery.reconstruct round.arity state.index state.value round.siblings = some values ∧ + Aiur.NativeAIR.Interpolation.foldRow state.domain round.arity + (state.index / Aiur.NativeAIR.Domain.size round.arity) values round.challenge = + some folded ∧ + result = + { + state := + { domain := child, index := state.index / Aiur.NativeAIR.Domain.size round.arity, + value := + (Aiur.NativeAIR.FriQuery.roll (↑child) + (round.challenge.power (Aiur.NativeAIR.Domain.size round.arity)) folded openings).fst }, + remaining := + (Aiur.NativeAIR.FriQuery.roll (↑child) + (round.challenge.power (Aiur.NativeAIR.Domain.size round.arity)) folded openings).snd, + row := + { domain := child, index := state.index / Aiur.NativeAIR.Domain.size round.arity, + values := values } } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.step_dimensions +∀ {state : Aiur.NativeAIR.FriQuery.State} {round : Aiur.NativeAIR.FriQuery.Round} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.StepResult}, + Aiur.NativeAIR.FriQuery.step state round openings = some result → + 0 < ↑round.arity ∧ + ↑state.domain = ↑result.state.domain + ↑round.arity ∧ + result.state.index = state.index / Aiur.NativeAIR.Domain.size round.arity ∧ + result.state.index < Aiur.NativeAIR.Domain.size result.state.domain ∧ + result.row.domain = result.state.domain ∧ result.row.index = result.state.index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.step_row +∀ {state : Aiur.NativeAIR.FriQuery.State} {round : Aiur.NativeAIR.FriQuery.Round} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.StepResult}, + Aiur.NativeAIR.FriQuery.step state round openings = some result → + result.row.values.length = Aiur.NativeAIR.Domain.size round.arity ∧ + result.row.values[state.index % Aiur.NativeAIR.Domain.size round.arity]? = some state.value ∧ + result.row.values.eraseIdx (state.index % Aiur.NativeAIR.Domain.size round.arity) = round.siblings +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.step_index_bound +∀ {state : Aiur.NativeAIR.FriQuery.State} {round : Aiur.NativeAIR.FriQuery.Round} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.StepResult}, + Aiur.NativeAIR.FriQuery.step state round openings = some result → + state.index < Aiur.NativeAIR.Domain.size state.domain +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.step_self_sample +∀ {state : Aiur.NativeAIR.FriQuery.State} {round : Aiur.NativeAIR.FriQuery.Round} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.StepResult}, + Aiur.NativeAIR.FriQuery.step state round openings = some result → + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint state.domain state.index), + state.value) ∈ + Aiur.NativeAIR.Interpolation.foldSamples state.domain round.arity result.state.index result.row.values +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.step_polynomial +∀ {state : Aiur.NativeAIR.FriQuery.State} {round : Aiur.NativeAIR.FriQuery.Round} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.StepResult}, + Aiur.NativeAIR.FriQuery.step state round openings = some result → + ∃ candidate, + candidate.length ≤ Aiur.NativeAIR.Domain.size round.arity ∧ + Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.FriDomain.queryPoint state.domain state.index)) + candidate = + state.value ∧ + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ + Aiur.NativeAIR.Interpolation.foldSamples state.domain round.arity result.state.index + result.row.values → + Aiur.NativeAIR.Quotient.horner sample.fst candidate = sample.snd) ∧ + (result.state.value, result.remaining) = + Aiur.NativeAIR.FriQuery.roll (↑result.state.domain) + (round.challenge.power (Aiur.NativeAIR.Domain.size round.arity)) + (Aiur.NativeAIR.Quotient.horner round.challenge candidate) openings +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.step_global +∀ {state : Aiur.NativeAIR.FriQuery.State} {round : Aiur.NativeAIR.FriQuery.Round} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.StepResult}, + Aiur.NativeAIR.FriQuery.step state round openings = some result → + ∀ (coefficients : List Aiur.NativeAIR.ProofCodec.Extension), + (∀ (sample : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), + sample ∈ + Aiur.NativeAIR.Interpolation.foldSamples state.domain round.arity result.state.index result.row.values → + Aiur.NativeAIR.Quotient.horner sample.fst coefficients = sample.snd) → + (result.state.value, result.remaining) = + Aiur.NativeAIR.FriQuery.roll (↑result.state.domain) + (round.challenge.power (Aiur.NativeAIR.Domain.size round.arity)) + (Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.FriDomain.queryPoint result.state.domain result.state.index)) + (Aiur.NativeAIR.Folding.foldCoefficients round.arity round.challenge coefficients)) + openings +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.roll_length +∀ (height : Nat) (factor value : Aiur.NativeAIR.ProofCodec.Extension) + (openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)), + (Aiur.NativeAIR.FriQuery.roll height factor value openings).snd.length ≤ openings.length +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.roll_empty +∀ (height : Nat) (factor value : Aiur.NativeAIR.ProofCodec.Extension), + Aiur.NativeAIR.FriQuery.roll height factor value [] = (value, []) +AXIOMS [propext] +ROOT Aiur.NativeAIR.FriQuery.roll_matching +∀ (height : Nat) (factor value next : Aiur.NativeAIR.ProofCodec.Extension) + (rest : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)), + Aiur.NativeAIR.FriQuery.roll height factor value ((height, next) :: rest) = (value + factor * next, rest) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.roll_other +∀ (height nextHeight : Nat) (factor value next : Aiur.NativeAIR.ProofCodec.Extension) + (rest : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)), + nextHeight ≠ height → + Aiur.NativeAIR.FriQuery.roll height factor value ((nextHeight, next) :: rest) = (value, (nextHeight, next) :: rest) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.roll_count +∀ (height : Nat) (factor value : Aiur.NativeAIR.ProofCodec.Extension) + (openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)), + openings.length ≤ (Aiur.NativeAIR.FriQuery.roll height factor value openings).snd.length + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.roll_order +∀ (height : Nat) (factor value : Aiur.NativeAIR.ProofCodec.Extension) + (openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)), + List.Pairwise (fun left right => right.fst < left.fst) + (Aiur.NativeAIR.FriQuery.roll height factor value openings).snd → + (∀ (entry : Nat × Aiur.NativeAIR.ProofCodec.Extension), + entry ∈ (Aiur.NativeAIR.FriQuery.roll height factor value openings).snd → entry.fst < height) → + List.Pairwise (fun left right => right.fst < left.fst) openings ∧ + ∀ (entry : Nat × Aiur.NativeAIR.ProofCodec.Extension), entry ∈ openings → entry.fst ≤ height +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.walk_nil_success +∀ {final : Aiur.NativeAIR.Domain.Subgroup} {state : Aiur.NativeAIR.FriQuery.State} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.walk final state openings [] = some result → + state.domain = final ∧ openings = [] ∧ result = { state := state, rows := [] } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.walk_cons_success +∀ {final : Aiur.NativeAIR.Domain.Subgroup} {state : Aiur.NativeAIR.FriQuery.State} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {round : Aiur.NativeAIR.FriQuery.Round} + {rest : List Aiur.NativeAIR.FriQuery.Round} {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.walk final state openings (round :: rest) = some result → + ∃ head tail, + Aiur.NativeAIR.FriQuery.step state round openings = some head ∧ + Aiur.NativeAIR.FriQuery.walk final head.state head.remaining rest = some tail ∧ + result = { state := tail.state, rows := head.row :: tail.rows } +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.walk_summary +∀ {final : Aiur.NativeAIR.Domain.Subgroup} {state : Aiur.NativeAIR.FriQuery.State} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {rounds : List Aiur.NativeAIR.FriQuery.Round} + {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.walk final state openings rounds = some result → + result.state.domain = final ∧ + result.rows.length = rounds.length ∧ + ↑state.domain = ↑final + (List.map (fun round => ↑round.arity) rounds).sum ∧ + result.state.index = state.index / 2 ^ (List.map (fun round => ↑round.arity) rounds).sum +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.walk_openings +∀ {final : Aiur.NativeAIR.Domain.Subgroup} {state : Aiur.NativeAIR.FriQuery.State} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {rounds : List Aiur.NativeAIR.FriQuery.Round} + {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.walk final state openings rounds = some result → + List.Pairwise (fun left right => right.fst < left.fst) openings ∧ + (∀ (entry : Nat × Aiur.NativeAIR.ProofCodec.Extension), entry ∈ openings → entry.fst < ↑state.domain) ∧ + openings.length ≤ rounds.length +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.run_success +∀ {initial final : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {rounds : List Aiur.NativeAIR.FriQuery.Round} + {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.run initial final index openings rounds = some result → + index < Aiur.NativeAIR.Domain.size initial ∧ + ∃ value rest, + openings = (↑initial, value) :: rest ∧ + Aiur.NativeAIR.FriQuery.walk final { domain := initial, index := index, value := value } rest rounds = + some result +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.run_summary +∀ {initial final : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {rounds : List Aiur.NativeAIR.FriQuery.Round} + {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.run initial final index openings rounds = some result → + index < Aiur.NativeAIR.Domain.size initial ∧ + result.state.domain = final ∧ + result.rows.length = rounds.length ∧ + ↑initial = ↑final + (List.map (fun round => ↑round.arity) rounds).sum ∧ + result.state.index = index / 2 ^ (List.map (fun round => ↑round.arity) rounds).sum ∧ + result.state.index < Aiur.NativeAIR.Domain.size final ∧ + List.Pairwise (fun left right => right.fst < left.fst) openings ∧ openings.length ≤ rounds.length + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.check_success +∀ {initial final : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {rounds : List Aiur.NativeAIR.FriQuery.Round} + {finalPolynomial : List Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.check initial final index openings rounds finalPolynomial = some result → + Aiur.NativeAIR.FriQuery.run initial final index openings rounds = some result ∧ + Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint initial result.state.index)) + finalPolynomial = + result.state.value +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.FriQuery.check_final_polynomial +∀ {initial final : Aiur.NativeAIR.Domain.Subgroup} {index : Nat} + {openings : List (Nat × Aiur.NativeAIR.ProofCodec.Extension)} {rounds : List Aiur.NativeAIR.FriQuery.Round} + {finalPolynomial : List Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.FriQuery.Result}, + Aiur.NativeAIR.FriQuery.check initial final index openings rounds finalPolynomial = some result → + Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.FriDomain.queryPoint final result.state.index)) + finalPolynomial = + result.state.value +AXIOMS [propext, Classical.choice, Quot.sound] +PREMISE Aiur.Bytecode.CallRank.zero +Aiur.Bytecode.CallRank +PREMISE Aiur.Bytecode.CallRank.bound +Aiur.Bytecode.CallRank +PREMISE Aiur.Bytecode.CallRank.ordered +Aiur.Bytecode.CallRank +PREMISE Aiur.Bytecode.CallComponent.mk +Nat → Bool → Aiur.Bytecode.CallComponent +PREMISE Aiur.Bytecode.CallComponent.permits +Aiur.Bytecode.CallComponent → Aiur.Bytecode.CallComponent → Bool +DEFINITION +fun parent child => decide (parent.order < child.order) || parent.order == child.order && parent.ranked && child.ranked +PREMISE Aiur.Bytecode.Toplevel.mk +Array Aiur.Bytecode.Function → + Array Nat → Array Aiur.Bytecode.Circuit → Array Aiur.Bytecode.CallComponent → Aiur.Bytecode.Toplevel +PREMISE Aiur.Bytecode.Toplevel.validCallComponents +Aiur.Bytecode.Toplevel → Bool +DEFINITION +fun t => + (t.callComponents.size == t.functions.size && t.callComponents.all fun c => decide (c.order < t.functions.size)) && + (Array.mapIdx + (fun i f => + !f.constrained || + f.body.collectConstrainedCallees.all fun j => + match t.callComponents[i]?, t.callComponents[j]? with + | some parent, some child => parent.permits child + | x, x_1 => false) + t.functions).all + id +PREMISE Aiur.Bytecode.Toplevel.findCallComponents +Aiur.Bytecode.Toplevel → Array Aiur.Bytecode.CallComponent +DEFINITION +fun t => + (have n := t.functions.size; + have graph := + Array.map (fun f => if f.constrained = true then f.body.collectConstrainedCallees else #[]) t.functions; + have reverse := Array.replicate n #[]; + do + let __s ← + forIn [:n] reverse fun i __s => + have reverse := __s; + do + let __s ← + forIn graph[i]! reverse fun j __s => + have reverse := __s; + have reverse := reverse.set! j (reverse[j]!.push i); + pure (ForInStep.yield reverse) + have reverse : Array (Array Nat) := __s + pure (ForInStep.yield reverse) + have reverse : Array (Array Nat) := __s + have visited : Array Bool × Array Nat := (Array.replicate n false, #[]) + let __s ← + forIn [:n] visited fun i __s => + have visited := __s; + have visited := Aiur.Bytecode.callOrderFinishDfs graph n i visited; + pure (ForInStep.yield visited) + have visited : Array Bool × Array Nat := __s + have labels : Array Nat := Array.replicate n n + have count : Nat := 0 + let __s ← + forIn visited.snd.reverse (labels, count) fun i __s => + have labels := __s.fst; + have count := __s.snd; + if (labels[i]! == n) = true then + have labels := Aiur.Bytecode.callOrderComponentDfs reverse count n i labels; + have count := count + 1; + pure (ForInStep.yield (labels, count)) + else pure (ForInStep.yield (labels, count)) + have labels : Array Nat := __s.fst + have count : Nat := __s.snd + have sizes : Array Nat := Array.replicate count 0 + let __s ← + forIn labels sizes fun label __s => + have sizes := __s; + have sizes := sizes.set! label (sizes[label]! + 1); + pure (ForInStep.yield sizes) + have sizes : Array Nat := __s + pure + (Array.mapIdx (fun i label => { order := label, ranked := decide (sizes[label]! > 1) || graph[i]!.contains i }) + labels)).run +PREMISE Aiur.Bytecode.Toplevel.callRanksFor +Aiur.Bytecode.Toplevel → Nat → Array Aiur.Bytecode.CallRank +DEFINITION +fun t parent => + Array.map + (fun child => + if (t.callComponents[parent]!.order == child.order) = true then Aiur.Bytecode.CallRank.ordered + else if child.ranked = true then Aiur.Bytecode.CallRank.bound else Aiur.Bytecode.CallRank.zero) + t.callComponents +PREMISE Aiur.Bytecode.Toplevel.withCallComponents +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Toplevel +DEFINITION +fun t => + have callComponents := t.findCallComponents; + have candidate := + { functions := t.functions, memorySizes := t.memorySizes, circuits := t.circuits, + callComponents := callComponents }; + if (!candidate.validCallComponents) = true then t + else + have functions := + Array.mapIdx + (fun i function => + have initial := + Aiur.Concrete.Bytecode.LayoutMState.withCallRanks function.layout.inputSize callComponents[i]!.ranked + (candidate.callRanksFor i); + match StateT.run (Aiur.Concrete.Bytecode.relayoutBlock function.body) initial with + | (body, state) => + { body := body, + layout := + have __src := state.functionLayout; + { inputSize := __src.inputSize, selectors := __src.selectors, auxiliaries := __src.auxiliaries, + lookups := state.functionLayout.lookups + 1 }, + entry := function.entry, constrained := function.constrained }) + t.functions; + { functions := functions, memorySizes := candidate.memorySizes, circuits := candidate.circuits, + callComponents := candidate.callComponents } +PREMISE Aiur.Bytecode.Op.allocationFor +Array Aiur.Bytecode.CallRank → Array Nat → Aiur.Bytecode.Op → Aiur.Bytecode.OpAllocation +DEFINITION +fun callRanks degrees x => + match x with + | Aiur.Bytecode.Op.call function a size unconstrained => + have extra := + if unconstrained = true then 0 + else + match callRanks[function]?.getD Aiur.Bytecode.CallRank.ordered with + | Aiur.Bytecode.CallRank.zero => 0 + | Aiur.Bytecode.CallRank.bound => 1 + | Aiur.Bytecode.CallRank.ordered => 6; + { degrees := Array.replicate size 1, auxiliaries := size + extra } + | op => Aiur.Bytecode.Op.allocation degrees op +PREMISE Aiur.Concrete.Bytecode.LayoutMState.withCallRanks +Nat → Bool → Array Aiur.Bytecode.CallRank → Aiur.Concrete.Bytecode.LayoutMState +DEFINITION +fun inputSize ranked callRanks => + { + functionLayout := + { inputSize := inputSize, selectors := 0, auxiliaries := if ranked = true then 7 else 1, + lookups := if ranked = true then 3 else 0 }, + memSizes := Std.TreeSet.empty, degrees := Array.replicate inputSize 1, callRanks := callRanks } +PREMISE Aiur.Concrete.Bytecode.LayoutMState.context +Aiur.Concrete.Bytecode.LayoutMState → Nat × Array Aiur.Bytecode.CallRank +DEFINITION +fun state => (state.functionLayout.inputSize, state.callRanks) +PREMISE Aiur.Concrete.Bytecode.LayoutRenaming +(Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) → Array Aiur.Bytecode.CallRank → Prop +DEFINITION +fun rename ranks => + ∀ (function : Aiur.Bytecode.FunIdx), + ranks[rename function]?.getD Aiur.Bytecode.CallRank.ordered = ranks[function]?.getD Aiur.Bytecode.CallRank.ordered +PREMISE Aiur.Concrete.Bytecode.relayoutCtrl +Aiur.Bytecode.Ctrl → Aiur.Concrete.Bytecode.LayoutM Aiur.Bytecode.Ctrl +DEFINITION +fun c => Aiur.Concrete.Bytecode.relayoutCtrl._mutual (PSum.inl c) +PREMISE Aiur.Concrete.Bytecode.relayoutBlock +Aiur.Bytecode.Block → Aiur.Concrete.Bytecode.LayoutM Aiur.Bytecode.Block +DEFINITION +fun block => Aiur.Concrete.Bytecode.relayoutCtrl._mutual (PSum.inr block) +PREMISE Aiur.AIR.EquationAvailable +List Aiur.G → Aiur.G → Prop +DEFINITION +fun equations value => value = 0 ∨ value ∈ equations +PREMISE Aiur.NativeAIR.LookupGroups.FftCost.mk +Nat → Nat → Nat → Nat → Aiur.NativeAIR.LookupGroups.FftCost +PREMISE Aiur.NativeAIR.LookupGroups.checked128 +Nat → Option Nat +DEFINITION +fun value => if value < 2 ^ 128 then some value else none +PREMISE Aiur.NativeAIR.LookupGroups.FftCost.make +Nat → Nat → Nat → Nat → Option Aiur.NativeAIR.LookupGroups.FftCost +DEFINITION +fun stage2 quotient blowup degree => + if + (decide (stage2 ≥ 2 ^ 64) || decide (quotient ≥ 2 ^ 64) || decide (blowup ≥ 2 ^ 64) || decide (degree ≥ 2 ^ 64)) = + true then + none + else + if + (decide (quotient = 0) || quotient.nextPowerOfTwo != quotient || decide (blowup = 0) || + blowup.nextPowerOfTwo != blowup) = + true then + none + else + have logQ := quotient.log2; + have logB := blowup.log2; + do + let qd ← Aiur.NativeAIR.LookupGroups.checked128 (quotient * degree) + let trace ← Aiur.NativeAIR.LookupGroups.checked128 ((blowup + 1) * stage2) + let combined ← Aiur.NativeAIR.LookupGroups.checked128 (stage2 + qd) + let slope ← Aiur.NativeAIR.LookupGroups.checked128 ((blowup + 1) * combined) + let scaledLog ← Aiur.NativeAIR.LookupGroups.checked128 (blowup * logB) + let logs ← Aiur.NativeAIR.LookupGroups.checked128 (logQ + scaledLog) + let intercept ← Aiur.NativeAIR.LookupGroups.checked128 (qd * logs) + let scaledOneLog ← Aiur.NativeAIR.LookupGroups.checked128 (blowup * max logB 1) + let oneLogs ← Aiur.NativeAIR.LookupGroups.checked128 (max logQ 1 + scaledOneLog) + let quotientOne ← Aiur.NativeAIR.LookupGroups.checked128 (qd * oneLogs) + let one ← Aiur.NativeAIR.LookupGroups.checked128 (trace + quotientOne) + let two ← Aiur.NativeAIR.LookupGroups.checked128 (slope + intercept) + pure { one := one, two := two, slope := slope, intercept := intercept } +PREMISE Aiur.NativeAIR.LookupGroups.FftCost.noWorse +Aiur.NativeAIR.LookupGroups.FftCost → Aiur.NativeAIR.LookupGroups.FftCost → Bool +DEFINITION +fun candidate baseline => + decide (candidate.one ≤ baseline.one) && decide (candidate.two ≤ baseline.two) && + decide (candidate.slope ≤ baseline.slope) +PREMISE Aiur.NativeAIR.LookupGroups.FftCost.scoreLess +Aiur.NativeAIR.LookupGroups.FftCost → Aiur.NativeAIR.LookupGroups.FftCost → Bool +DEFINITION +fun candidate current => + decide (candidate.slope < current.slope) || + candidate.slope == current.slope && + (decide (candidate.intercept < current.intercept) || + candidate.intercept == current.intercept && decide (candidate.one < current.one)) +PREMISE Aiur.NativeAIR.LookupGroups.quotientDegree +Aiur.NativeAIR.KeyCodec.Circuit → Nat +DEFINITION +fun circuit => (max circuit.maxConstraintDegree 2 - 1).nextPowerOfTwo +PREMISE Aiur.NativeAIR.LookupGroups.withGroup +Aiur.NativeAIR.KeyCodec.Circuit → Nat → Option Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +fun circuit group => + have candidate := + { mainWidth := circuit.mainWidth, preprocessedWidth := circuit.preprocessedWidth, + preprocessedHeight := circuit.preprocessedHeight, maxConstraintDegree := circuit.maxConstraintDegree, + lookupGroupSize := group, graph := circuit.graph }; + do + let degree ← candidate.computedDegree + pure + { mainWidth := candidate.mainWidth, preprocessedWidth := candidate.preprocessedWidth, + preprocessedHeight := candidate.preprocessedHeight, maxConstraintDegree := degree, + lookupGroupSize := candidate.lookupGroupSize, graph := candidate.graph } +PREMISE Aiur.NativeAIR.LookupGroups.selectGroup +Aiur.NativeAIR.KeyCodec.Circuit → Nat → Option Nat +DEFINITION +fun circuit blowup => + if + (circuit.graph.nodes.any fun node => + match node with + | Aiur.NativeAIR.Node.var column => column.source == Aiur.NativeAIR.Source.stage2 + | x => false) = + true then + none + else do + let baseline ← + Aiur.NativeAIR.LookupGroups.FftCost.make circuit.widths.stage2 + (Aiur.NativeAIR.LookupGroups.quotientDegree circuit) blowup 2 + have best : Nat × Aiur.NativeAIR.LookupGroups.FftCost := + List.foldl + (fun best offset => + have group := offset + 1; + match Aiur.NativeAIR.LookupGroups.withGroup circuit group with + | none => best + | some candidate => + have quotient := Aiur.NativeAIR.LookupGroups.quotientDegree candidate; + if (decide (quotient ≥ 2 ^ 64) || decide (quotient > blowup)) = true then best + else + match Aiur.NativeAIR.LookupGroups.FftCost.make candidate.widths.stage2 quotient blowup 2 with + | none => best + | some cost => if (cost.noWorse baseline && cost.scoreLess best.snd) = true then (group, cost) else best) + (circuit.lookupGroupSize, baseline) (List.range (min 8 (max 1 circuit.graph.lookups.length))) + pure best.fst +PREMISE Aiur.NativeAIR.LookupGroups.retune +Aiur.NativeAIR.KeyCodec.Circuit → Nat → Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +fun circuit blowup => + match Aiur.NativeAIR.LookupGroups.selectGroup circuit blowup with + | none => circuit + | some group => (Aiur.NativeAIR.LookupGroups.withGroup circuit group).getD circuit +PREMISE Aiur.NativeAIR.LookupGroups.AuthoredFields +Aiur.NativeAIR.KeyCodec.Circuit → Aiur.NativeAIR.Graph × Nat × Nat × Nat +DEFINITION +fun circuit => (circuit.graph, circuit.mainWidth, circuit.preprocessedWidth, circuit.preprocessedHeight) +PREMISE Aiur.AIR.activityConstraint +Aiur.G → Aiur.G → Aiur.G +DEFINITION +fun multiplicity selector => multiplicity * (1 - selector) +PREMISE Aiur.Bytecode.Eval.SameCode.mk +∀ {a b : Aiur.Bytecode.Toplevel}, + a.functions.size = b.functions.size → + (∀ (i : Nat) (ha : i < a.functions.size) (hb : i < b.functions.size) (t : Aiur.Bytecode.Toplevel) (fuel : Nat) + (st : Aiur.Bytecode.Eval.EvalState), + Aiur.Bytecode.Eval.evalBlock t fuel a.functions[i].body st = + Aiur.Bytecode.Eval.evalBlock t fuel b.functions[i].body st) → + (∀ (i : Nat) (ha : i < a.functions.size) (hb : i < b.functions.size), + a.functions[i].layout.inputSize = b.functions[i].layout.inputSize) → + Aiur.Bytecode.Eval.SameCode a b +PREMISE Aiur.finishCompilation +Aiur.Source.Toplevel → Aiur.Bytecode.Toplevel → Std.HashMap Aiur.Global Aiur.Bytecode.FunIdx → Aiur.CompiledToplevel +DEFINITION +fun t bytecodeRaw preNameMap => + (match bytecodeRaw.deduplicate with + | (bytecodeDedup, remap) => + have needs := bytecodeDedup.needsCircuit; + have bytecode := + { + functions := + Array.mapIdx (fun i f => { body := f.body, layout := f.layout, entry := f.entry, constrained := needs[i]! }) + bytecodeDedup.functions, + memorySizes := bytecodeDedup.memorySizes, circuits := bytecodeDedup.circuits, + callComponents := bytecodeDedup.callComponents }; + have bytecode := if t.componentRanks = true then bytecode.withCallComponents else bytecode; + have nameMap := Std.HashMap.fold (fun acc name idx => acc.insert name (remap idx)) ∅ preNameMap; + have reverseMap := + Std.HashMap.fold + (fun acc global idx => if acc.contains idx = true then acc else acc.insert idx (toString global)) ∅ nameMap; + have bytecode := + { functions := bytecode.functions, memorySizes := bytecode.memorySizes, + circuits := + bytecode.singletonCircuits fun i => reverseMap[i]?.getD (toString ""), + callComponents := bytecode.callComponents }; + pure { source := t, bytecode := bytecode, nameMap := nameMap }).run +PREMISE Aiur.BoundVerifier.Selection.mk +Aiur.Source.Toplevel → + Array (String × Array String) → + Name → + Aiur.Bytecode.FunIdx → + Nat → Array Aiur.G → Aiur.CommitmentParameters → Aiur.FriParameters → ByteArray → Aiur.BoundVerifier.Selection +PREMISE Aiur.BoundVerifier.Selection.compile +Aiur.BoundVerifier.Selection → Except String Aiur.CompiledToplevel +DEFINITION +fun selection => do + let compiled ← selection.source.compile + if selection.groups.isEmpty = true then pure compiled else compiled.groupFunctions selection.groups +PREMISE Aiur.BoundVerifier.Selection.system +Aiur.BoundVerifier.Selection → Aiur.CompiledToplevel → Aiur.AiurSystem +DEFINITION +fun selection compiled => Aiur.AiurSystem.build compiled.bytecode selection.commitment selection.fri +PREMISE Aiur.BoundVerifier.Backend.mk +{selection : Aiur.BoundVerifier.Selection} → + (compiled : Aiur.CompiledToplevel) → + selection.compile = Except.ok compiled → + (system : Aiur.AiurSystem) → + system = selection.system compiled → + compiled.getFuncIdx selection.entrypoint = some selection.function → + selection.function < Aiur.gSize.toNat → + (entry : Aiur.Bytecode.Function) → + compiled.bytecode.functions[selection.function]? = some entry → + entry.entry = true → + entry.constrained = true → + entry.layout.inputSize = selection.inputSize → + Aiur.Bytecode.Block.returnsHaveSize selection.success.size entry.body = true → + compiled.bytecode.validateLookupShapes = true → + compiled.bytecode.validateRowCounts = true → + compiled.bytecode.validateEmission = true → + system.vkBytes = selection.key → + (keyData : Aiur.NativeAIR.KeyCodec.Key) → + Aiur.NativeAIR.KeyCodec.decodeCanonical selection.key = some keyData → + keyData.parameters = selection.keyParameters → + Aiur.BoundVerifier.Backend selection +PREMISE Aiur.BoundVerifier.verify +{selection : Aiur.BoundVerifier.Selection} → + Aiur.BoundVerifier.Backend selection → Array Aiur.G → ByteArray → Except String Unit +DEFINITION +fun {selection} backend input bytes => + have __do_jp := fun __r => do + let proof ← Aiur.Proof.ofBytesChecked bytes + backend.system.verify (Aiur.buildClaim selection.function input selection.success) proof; + if (input.size != selection.inputSize) = true then do + let __r ← throw "public input arity differs" + __do_jp __r + else __do_jp () +PREMISE Aiur.CompiledToplevel.groupFunctions +Aiur.CompiledToplevel → Array (String × Array String) → Except String Aiur.CompiledToplevel +DEFINITION +fun ct groups => + have t := ct.bytecode; + have byName := Std.HashMap.fold (fun acc g i => acc.insert (toString g) i) ∅ ct.nameMap; + have grouped := ∅; + have resolved := #[]; + do + let __s ← + forIn groups (grouped, resolved) fun x __s => + have grouped := __s.fst; + have resolved := __s.snd; + match x with + | (gname, names) => + have __do_jp := fun __r => + have members := #[]; + do + let __s ← + forIn names (grouped, members) fun name __s => + have grouped := __s.fst; + have members := __s.snd; + match byName[name]? with + | some i => + have f := t.functions[i]!; + have __do_jp := fun __r => + have __do_jp := fun __r => + have __do_jp := fun __r => + have grouped := grouped.insert i resolved.size; + have members := members.push i; + pure (ForInStep.yield (grouped, members)); + if grouped.contains i = true then do + let __r ← + throw + (toString "group " ++ toString gname ++ toString ": " ++ toString name ++ + toString " is already grouped") + __do_jp __r + else __do_jp (); + if f.entry = true then do + let __r ← + throw + (toString "group " ++ toString gname ++ toString ": " ++ toString name ++ + toString " is an entry function") + __do_jp __r + else __do_jp (); + if f.constrained = true then __do_jp () + else do + let __r ← + throw + (toString "group " ++ toString gname ++ toString ": " ++ toString name ++ + toString " is unconstrained (it has no circuit)") + __do_jp __r + | x => do + throw (toString "group " ++ toString gname ++ toString ": unknown function " ++ toString name) + pure (ForInStep.yield (grouped, members)) + have grouped : Std.HashMap Aiur.Bytecode.FunIdx Nat := __s.fst + have members : Array Aiur.Bytecode.FunIdx := __s.snd + have resolved : Array (String × Array Aiur.Bytecode.FunIdx) := resolved.push (gname, members) + pure (ForInStep.yield (grouped, resolved)); + if names.isEmpty = true then do + let __r ← throw (toString "group " ++ toString gname ++ toString " is empty") + __do_jp __r + else __do_jp () + have grouped : Std.HashMap Aiur.Bytecode.FunIdx Nat := __s.fst + have resolved : Array (String × Array Aiur.Bytecode.FunIdx) := __s.snd + have circuits : Array Aiur.Bytecode.Circuit := #[] + have placed : Array Bool := Array.replicate resolved.size false + let __s ← + forIn t.circuits (circuits, placed) fun c __s => + have circuits := __s.fst; + have placed := __s.snd; + let members := c.members; + if h : members.size = 1 then + have i := members[0]; + match grouped[i]? with + | none => + have circuits := circuits.push c; + pure (ForInStep.yield (circuits, placed)) + | some g => + if placed[g]! = true then pure (ForInStep.yield (circuits, placed)) + else + have placed := placed.set! g true; + match resolved[g]! with + | (gname, ms) => + have layout := + Array.foldl (fun acc m => if (m == ms[0]!) = true then acc else acc.merge t.functions[m]!.layout) + t.functions[ms[0]!]!.layout ms; + have circuits := circuits.push { name := gname, members := ms, layout := layout }; + pure (ForInStep.yield (circuits, placed)) + else do + throw "groupFunctions: partition already grouped; group from a freshly compiled toplevel" + pure (ForInStep.yield (circuits, placed)) + have circuits : Array Aiur.Bytecode.Circuit := __s.fst + pure + { source := ct.source, + bytecode := + { functions := t.functions, memorySizes := t.memorySizes, circuits := circuits, + callComponents := t.callComponents }, + nameMap := ct.nameMap } +PREMISE Aiur.AIR.callRankBound +Nat +DEFINITION +2 ^ 48 +PREMISE Aiur.AIR.packRank +(Fin 6 → Aiur.G) → Aiur.G +DEFINITION +fun bytes => + bytes 0 + 256 * bytes 1 + 65536 * bytes 2 + 16777216 * bytes 3 + 4294967296 * bytes 4 + 1099511627776 * bytes 5 +PREMISE Aiur.AIR.callOrderConstraint +Aiur.G → Aiur.G → Aiur.G → Aiur.G +DEFINITION +fun parent child gap => child - parent - 1 - gap +PREMISE Aiur.Concrete.Bytecode.LayoutMState.new +Nat → Aiur.Concrete.Bytecode.LayoutMState +DEFINITION +fun inputSize => + { functionLayout := { inputSize := inputSize, selectors := 0, auxiliaries := 7, lookups := 3 }, + memSizes := Std.TreeSet.empty, degrees := Array.replicate inputSize 1 } +PREMISE Aiur.Concrete.Bytecode.opLayout +Aiur.Bytecode.Op → Aiur.Concrete.Bytecode.LayoutM Unit +DEFINITION +fun x => + match x with + | Aiur.Bytecode.Op.const a => Aiur.Concrete.Bytecode.pushDegree 0 + | Aiur.Bytecode.Op.add a b => do + let aDegree ← Aiur.Concrete.Bytecode.getDegree a + let bDegree ← Aiur.Concrete.Bytecode.getDegree b + Aiur.Concrete.Bytecode.pushDegree (aDegree.max bDegree) + | Aiur.Bytecode.Op.sub a b => do + let aDegree ← Aiur.Concrete.Bytecode.getDegree a + let bDegree ← Aiur.Concrete.Bytecode.getDegree b + Aiur.Concrete.Bytecode.pushDegree (aDegree.max bDegree) + | Aiur.Bytecode.Op.mul a b => do + let aDegree ← Aiur.Concrete.Bytecode.getDegree a + let bDegree ← Aiur.Concrete.Bytecode.getDegree b + have degree : Nat := aDegree + bDegree + if degree < 2 then Aiur.Concrete.Bytecode.pushDegree degree + else do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + | Aiur.Bytecode.Op.eqZero a => do + let degree ← Aiur.Concrete.Bytecode.getDegree a + if degree = 0 then Aiur.Concrete.Bytecode.pushDegree 0 + else do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries 2 + | Aiur.Bytecode.Op.call function a outputSize unconstrained => do + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate outputSize 1) + Aiur.Concrete.Bytecode.bumpAuxiliaries outputSize + if (!unconstrained) = true then do + Aiur.Concrete.Bytecode.bumpLookups + let __do_lift ← get + match __do_lift.callRanks[function]?.getD Aiur.Bytecode.CallRank.ordered with + | Aiur.Bytecode.CallRank.zero => pure () + | Aiur.Bytecode.CallRank.bound => Aiur.Concrete.Bytecode.bumpAuxiliaries + | Aiur.Bytecode.CallRank.ordered => do + Aiur.Concrete.Bytecode.bumpAuxiliaries 6 + Aiur.Concrete.Bytecode.bumpLookups 3 + else pure () + | Aiur.Bytecode.Op.store values => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + Aiur.Concrete.Bytecode.addMemSize values.size + | Aiur.Bytecode.Op.load size a => do + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate size 1) + Aiur.Concrete.Bytecode.bumpAuxiliaries size + Aiur.Concrete.Bytecode.bumpLookups + Aiur.Concrete.Bytecode.addMemSize size + | Aiur.Bytecode.Op.assertEq a a_1 a_2 => pure () + | Aiur.Bytecode.Op.ioGetInfo a a_1 => do + Aiur.Concrete.Bytecode.pushDegrees #[1, 1] + Aiur.Concrete.Bytecode.bumpAuxiliaries 2 + | Aiur.Bytecode.Op.ioSetInfo a a_1 a_2 a_3 => pure () + | Aiur.Bytecode.Op.ioRead a a_1 len => do + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate len 1) + Aiur.Concrete.Bytecode.bumpAuxiliaries len + | Aiur.Bytecode.Op.ioWrite a a_1 => pure () + | Aiur.Bytecode.Op.u8BitDecomposition a => do + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate 8 1) + Aiur.Concrete.Bytecode.bumpAuxiliaries 8 + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8ShiftLeft a => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8ShiftRight a => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8Xor a a_1 => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8And a a_1 => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8Or a a_1 => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8Add a b => do + let aDegree ← Aiur.Concrete.Bytecode.getDegree a + let bDegree ← Aiur.Concrete.Bytecode.getDegree b + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.pushDegree ((aDegree.max bDegree).max 1) + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8Sub a b => do + let aDegree ← Aiur.Concrete.Bytecode.getDegree a + let bDegree ← Aiur.Concrete.Bytecode.getDegree b + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.pushDegree ((aDegree.max bDegree).max 1) + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8Mul a a_1 => do + Aiur.Concrete.Bytecode.pushDegrees #[1, 1] + Aiur.Concrete.Bytecode.bumpAuxiliaries 2 + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8XorSplit7 a a_1 => do + Aiur.Concrete.Bytecode.pushDegrees #[1, 1] + Aiur.Concrete.Bytecode.bumpAuxiliaries 2 + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8XorSplit4 a a_1 => do + Aiur.Concrete.Bytecode.pushDegrees #[1, 1] + Aiur.Concrete.Bytecode.bumpAuxiliaries 2 + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u8LessThan a a_1 => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.u32LessThan a a_1 => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries 12 + Aiur.Concrete.Bytecode.bumpLookups 6 + | Aiur.Bytecode.Op.unconstrainedU32Add a b => do + let degrees ← Array.mapM Aiur.Concrete.Bytecode.getDegree (a ++ b) + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate 4 1) + Aiur.Concrete.Bytecode.pushDegree (Array.foldl Nat.max 1 degrees) + Aiur.Concrete.Bytecode.bumpAuxiliaries 4 + | Aiur.Bytecode.Op.unconstrainedU32Add3 a b c => do + let degrees ← Array.mapM Aiur.Concrete.Bytecode.getDegree (a ++ b ++ c) + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate 4 1) + Aiur.Concrete.Bytecode.pushDegree (Array.foldl Nat.max 1 degrees) + Aiur.Concrete.Bytecode.bumpAuxiliaries 4 + | Aiur.Bytecode.Op.u32ToField a => do + let degrees ← Array.mapM Aiur.Concrete.Bytecode.getDegree a + Aiur.Concrete.Bytecode.pushDegree (Array.foldl Nat.max 0 degrees) + | Aiur.Bytecode.Op.u8RangeCheck a a_1 => Aiur.Concrete.Bytecode.bumpLookups + | Aiur.Bytecode.Op.unconstrainedBigUintDivMod a a_1 => do + Aiur.Concrete.Bytecode.pushDegrees #[1, 1] + Aiur.Concrete.Bytecode.bumpAuxiliaries 2 + | Aiur.Bytecode.Op.unconstrainedGToBytes a => do + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate 8 1) + Aiur.Concrete.Bytecode.bumpAuxiliaries 8 + | Aiur.Bytecode.Op.unconstrainedGInverse a => do + Aiur.Concrete.Bytecode.pushDegree 1 + Aiur.Concrete.Bytecode.bumpAuxiliaries + | Aiur.Bytecode.Op.debug a a_1 => pure () +PREMISE Aiur.AIR.suppliedWeight +{α : Type u_1} → [DecidableEq α] → α → List (Aiur.AIR.Provider α) → Aiur.G +DEFINITION +fun {α} [DecidableEq α] message providers => + List.foldr (fun provider rest => if provider.fst = message then provider.snd + rest else rest) 0 providers +PREMISE Aiur.AIR.ExactLookupBalance +{α : Type u_1} → [DecidableEq α] → List α → List (Aiur.AIR.Provider α) → Prop +DEFINITION +fun {α} [DecidableEq α] queries providers => + ∀ (message : α), Aiur.G.ofNat (List.count message queries) = Aiur.AIR.suppliedWeight message providers +PREMISE Aiur.AIR.byteRangeMessage +Fin 65536 → Aiur.G × Aiur.G +DEFINITION +fun row => (Aiur.G.ofNat (↑row / 256), Aiur.G.ofNat (↑row % 256)) +PREMISE Aiur.AIR.byteRangeProviders +(Fin 65536 → Aiur.G) → List (Aiur.AIR.Provider (Aiur.G × Aiur.G)) +DEFINITION +fun weights => List.ofFn fun row => (Aiur.AIR.byteRangeMessage row, weights row) +PREMISE Aiur.AIR.rankByteQueries +(Fin 6 → Aiur.G) → List (Aiur.G × Aiur.G) +DEFINITION +fun bytes => [(bytes 0, bytes 1), (bytes 2, bytes 3), (bytes 4, bytes 5)] +PREMISE Aiur.Bytecode.instBEqCtrl +BEq Aiur.Bytecode.Ctrl +DEFINITION +{ beq := Aiur.Bytecode.Ctrl.beq } +PREMISE Aiur.Bytecode.instBEqBlock +BEq Aiur.Bytecode.Block +DEFINITION +{ beq := Aiur.Bytecode.Block.beq } +PREMISE Aiur.Bytecode.instHashableCtrl +Hashable Aiur.Bytecode.Ctrl +DEFINITION +{ hash := Aiur.Bytecode.Ctrl.hash } +PREMISE Aiur.Bytecode.instHashableBlock +Hashable Aiur.Bytecode.Block +DEFINITION +{ hash := Aiur.Bytecode.Block.hash } +PREMISE Aiur.Bytecode.Eval.RenamedCode.mk +∀ {a b : Aiur.Bytecode.Toplevel} {rename : Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx}, + (∀ (i : Nat), i < a.functions.size ↔ rename i < b.functions.size) → + (∀ (i : Nat) (ha : i < a.functions.size) (hb : rename i < b.functions.size), + Aiur.Bytecode.rewriteBlock rename a.functions[i].body = b.functions[rename i].body) → + (∀ (i : Nat) (ha : i < a.functions.size) (hb : rename i < b.functions.size), + a.functions[i].layout.inputSize = b.functions[rename i].layout.inputSize) → + Aiur.Bytecode.Eval.RenamedCode a b rename +PREMISE Aiur.Bytecode.boundedRenaming +Aiur.Bytecode.Toplevel → (Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) → Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx +DEFINITION +fun source rename i => if i < source.functions.size then rename i else i +PREMISE Aiur.Bytecode.validatesRenaming +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Toplevel → (Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) → Bool +DEFINITION +fun source target rename => + decide (target.functions.size ≤ source.functions.size) && + (Array.range source.functions.size).all fun i => + if hi : i < source.functions.size then + if hj : rename i < target.functions.size then + source.functions[i].layout == target.functions[rename i].layout && + Aiur.Bytecode.rewriteBlock rename source.functions[i].body == target.functions[rename i].body + else false + else false +PREMISE Aiur.Bytecode.checkedRenaming +Aiur.Bytecode.Toplevel → + Aiur.Bytecode.Toplevel → + (Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) → + Aiur.Bytecode.Toplevel × (Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) +DEFINITION +fun source candidate rename => + have bounded := Aiur.Bytecode.boundedRenaming source rename; + if Aiur.Bytecode.validatesRenaming source candidate bounded = true then (candidate, bounded) else (source, id) +PREMISE Aiur.Bytecode.Toplevel.deduplicate +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Toplevel × (Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) +DEFINITION +fun source => + have candidate := source.deduplicateCandidate; + Aiur.Bytecode.checkedRenaming source candidate.fst candidate.snd +PREMISE Aiur.Bytecode.Toplevel.deduplicateCandidate +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Toplevel × (Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) +DEFINITION +fun t => + have functions := t.functions; + have n := functions.size; + if (n == 0) = true then (t, id) + else + have skeletons := Array.map (fun f => (Aiur.Bytecode.skeletonBlock f.body, f.layout)) functions; + match Aiur.Bytecode.assignClasses skeletons with + | (initClasses, snd) => + have callees := Array.map (fun f => Aiur.Bytecode.collectCalleesBlock f.body) functions; + have classes := Aiur.Bytecode.partitionRefine initClasses callees; + match Aiur.Bytecode.deduplicate_canonical classes with + | (canonical, _top_cls) => + have remapFn := Aiur.Bytecode.deduplicate_remap classes; + have newFunctions := Aiur.Bytecode.deduplicate_newFunctions functions classes canonical remapFn; + ({ functions := newFunctions, memorySizes := t.memorySizes, circuits := t.circuits, + callComponents := t.callComponents }, + remapFn) +PREMISE Aiur.Source.Term.restoreTailMatches +Aiur.Source.Term → Aiur.Source.Term +DEFINITION +WellFounded.Nat.fix (fun x => sizeOf x) fun a a_1 => + (match (motive := + (x : Aiur.Source.Term) → + ((y : Aiur.Source.Term) → InvImage (fun x1 x2 => x1 < x2) (fun x => sizeOf x) y x → Aiur.Source.Term) → + Aiur.Source.Term) + a with + | Aiur.Source.Term.let (Aiur.Pattern.var x) v (Aiur.Source.Term.var y) => fun x_1 => + if h : (x == y) = true then x_1 v ⋯ else Aiur.Source.Term.let (Aiur.Pattern.var x) v (Aiur.Source.Term.var y) + | Aiur.Source.Term.let p v b => fun x => Aiur.Source.Term.let p v (x b ⋯) + | s.match arms => fun x => s.match (List.map (fun arm => (arm.val.fst, x arm.val.snd ⋯)) arms.attach) + | t => fun x => t) + a_1 +PREMISE Aiur.instHashableValue +Hashable Aiur.Value +DEFINITION +{ hash := Aiur.Value.hash } +PREMISE Aiur.Source.Term.hoistLets +Aiur.Source.Term → Aiur.Source.Term +DEFINITION +fun t => + match Aiur.Source.Term.freshen t.freshBound ∅ t with + | (cnt, t) => (t.hoistLetsAux cnt).fst +PREMISE Aiur.Source.Term.hoistLetsAux +Aiur.Source.Term → StateM Nat Aiur.Source.Term +DEFINITION +WellFounded.Nat.fix (fun x => sizeOf x) fun a a_1 => + (match (motive := + (t : Aiur.Source.Term) → + ((y : Aiur.Source.Term) → + InvImage (fun x1 x2 => x1 < x2) (fun x => sizeOf x) y t → StateM Nat Aiur.Source.Term) → + StateM Nat Aiur.Source.Term) + a with + | Aiur.Source.Term.unit => fun x => pure a + | Aiur.Source.Term.var a_2 => fun x => pure a + | Aiur.Source.Term.ref a_2 => fun x => pure a + | Aiur.Source.Term.field a_2 => fun x => pure a + | Aiur.Source.Term.u8Lit a_2 => fun x => pure a + | Aiur.Source.Term.let p v b => fun x => do + let __do_lift ← x v ⋯ + let __do_lift_1 ← x b ⋯ + pure (Aiur.Source.Term.let p __do_lift __do_lift_1) + | s.match arms => fun x => do + let __do_lift ← x s ⋯ + match __do_lift.peelLets with + | (fs, sc) => do + let arms ← + List.mapM + (fun x_1 => + match x_1 with + | ⟨(p, a), property⟩ => do + let __do_lift ← x a ⋯ + pure (p, __do_lift)) + arms.attach + pure (Aiur.Source.Term.wrapLets fs (sc.match arms)) + | a.ret => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.ret __do_lift) + | Aiur.Source.Term.debug s o a => fun x => + let __do_jp := fun o' => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.let Aiur.Pattern.wildcard (Aiur.Source.Term.debug s o' Aiur.Source.Term.unit) __do_lift); + (match (motive := + (o : Option Aiur.Source.Term) → + ((y : Aiur.Source.Term) → + InvImage (fun x1 x2 => x1 < x2) (fun x => sizeOf x) y (Aiur.Source.Term.debug s o a) → + StateM Nat Aiur.Source.Term) → + StateM Nat Aiur.Source.Term) + o with + | none => fun x => do + let o' ← pure none + __do_jp o' + | some x => fun x_1 => do + let x ← x_1 x ⋯ + let o' ← pure (some x) + __do_jp o') + x + | Aiur.Source.Term.tuple ts => fun x => do + let ts ← + Array.mapM + (fun x_1 => + match x_1 with + | ⟨x_2, property⟩ => x x_2 ⋯) + ts.attach + let __x ← Aiur.Source.Term.peelListLets ts.toList + match __x with + | (fs, cs) => pure (Aiur.Source.Term.wrapLets fs (Aiur.Source.Term.tuple cs.toArray)) + | Aiur.Source.Term.array ts => fun x => do + let ts ← + Array.mapM + (fun x_1 => + match x_1 with + | ⟨x_2, property⟩ => x x_2 ⋯) + ts.attach + let __x ← Aiur.Source.Term.peelListLets ts.toList + match __x with + | (fs, cs) => pure (Aiur.Source.Term.wrapLets fs (Aiur.Source.Term.array cs.toArray)) + | Aiur.Source.Term.app g args mode => fun x => do + let args ← + List.mapM + (fun x_1 => + match x_1 with + | ⟨x_2, property⟩ => x x_2 ⋯) + args.attach + let __x ← Aiur.Source.Term.peelListLets args + match __x with + | (fs, cs) => pure (Aiur.Source.Term.wrapLets fs (Aiur.Source.Term.app g cs mode)) + | a.assertEq b msg c => fun x => do + let a_2 ← x a ⋯ + let b_1 ← x b ⋯ + let c ← x c ⋯ + Aiur.Source.Term.hoistBinaryLets + (fun a b => Aiur.Source.Term.let Aiur.Pattern.wildcard (a.assertEq b msg Aiur.Source.Term.unit) c) a_2 b_1 + | a_2.ioSetInfo b c d e => fun x => do + let __do_lift ← x a_2 ⋯ + let __do_lift_1 ← x b ⋯ + let __do_lift_2 ← x c ⋯ + let __do_lift_3 ← x d ⋯ + let args : List Aiur.Source.Term := [__do_lift, __do_lift_1, __do_lift_2, __do_lift_3] + let e ← x e ⋯ + let __x ← Aiur.Source.Term.peelListLets args + match __x with + | (fs, cs) => + match cs with + | [a, b, c, d] => + pure + (Aiur.Source.Term.wrapLets fs + (Aiur.Source.Term.let Aiur.Pattern.wildcard (a.ioSetInfo b c d Aiur.Source.Term.unit) e)) + | x => pure a + | a.ioWrite b c => fun x => do + let a_2 ← x a ⋯ + let b_1 ← x b ⋯ + let c ← x c ⋯ + Aiur.Source.Term.hoistBinaryLets + (fun a b => Aiur.Source.Term.let Aiur.Pattern.wildcard (a.ioWrite b Aiur.Source.Term.unit) c) a_2 b_1 + | a.ioGetInfo b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.ioGetInfo __do_lift __do_lift_1 + | a.ioRead b n => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets (fun a b => a.ioRead b n) __do_lift __do_lift_1 + | a.add b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.add __do_lift __do_lift_1 + | a.sub b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.sub __do_lift __do_lift_1 + | a.mul b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.mul __do_lift __do_lift_1 + | a.eqZero => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.eqZero __do_lift) + | a.proj n => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets (fun a => a.proj n) __do_lift) + | a.get n => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets (fun a => a.get n) __do_lift) + | a.slice i j => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets (fun a => a.slice i j) __do_lift) + | a.set n v => fun x => do + let __do_lift ← x v ⋯ + let __do_lift_1 ← x a ⋯ + Aiur.Source.Term.hoistBinaryLets (fun v a => a.set n v) __do_lift __do_lift_1 + | a.store => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.store __do_lift) + | a.load => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.load __do_lift) + | a.ptrVal => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.ptrVal __do_lift) + | Aiur.Source.Term.ann τ a => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets (Aiur.Source.Term.ann τ) __do_lift) + | a.u8BitDecomposition => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8BitDecomposition __do_lift) + | a.u8ShiftLeft => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8ShiftLeft __do_lift) + | a.u8ShiftRight => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8ShiftRight __do_lift) + | a.toField => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.toField __do_lift) + | a.u8FromFieldUnsafe => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8FromFieldUnsafe __do_lift) + | a.unconstrainedGToBytes => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.unconstrainedGToBytes __do_lift) + | a.unconstrainedGInverse => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.unconstrainedGInverse __do_lift) + | a.u8Xor b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Xor __do_lift __do_lift_1 + | a.u8Add b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Add __do_lift __do_lift_1 + | a.u8Mul b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Mul __do_lift __do_lift_1 + | a.u8Sub b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Sub __do_lift __do_lift_1 + | a.u8And b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8And __do_lift __do_lift_1 + | a.u8Or b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Or __do_lift __do_lift_1 + | a.u8LessThan b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8LessThan __do_lift __do_lift_1 + | a.u32LessThan b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u32LessThan __do_lift __do_lift_1 + | a.u8XorSplit7 b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8XorSplit7 __do_lift __do_lift_1 + | a.u8XorSplit4 b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8XorSplit4 __do_lift __do_lift_1 + | a.unconstrainedU32Add b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.unconstrainedU32Add __do_lift __do_lift_1 + | a_2.unconstrainedU32Add3 b c => fun x => do + let __do_lift ← x a_2 ⋯ + let __do_lift_1 ← x b ⋯ + let __do_lift_2 ← x c ⋯ + let args : List Aiur.Source.Term := [__do_lift, __do_lift_1, __do_lift_2] + let __x ← Aiur.Source.Term.peelListLets args + match __x with + | (fs, cs) => + match cs with + | [a, b, c] => pure (Aiur.Source.Term.wrapLets fs (a.unconstrainedU32Add3 b c)) + | x => pure a + | a.u32ToField => fun x => do + let __do_lift ← x a ⋯ + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u32ToField __do_lift) + | a.unconstrainedBigUintDivMod b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.unconstrainedBigUintDivMod __do_lift __do_lift_1 + | a.u8RangeCheck b => fun x => do + let __do_lift ← x a ⋯ + let __do_lift_1 ← x b ⋯ + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8RangeCheck __do_lift __do_lift_1) + a_1 +PREMISE Aiur.Source.Term.hoistBinaryLets +(Aiur.Source.Term → Aiur.Source.Term → Aiur.Source.Term) → + Aiur.Source.Term → Aiur.Source.Term → StateM Nat Aiur.Source.Term +DEFINITION +fun build a b => + match a.peelLets with + | (fa, a) => + match b.peelLets with + | (fb, b) => + if (fb.isEmpty || a.isAtomic) = true then pure (Aiur.Source.Term.wrapLets (fa ++ fb) (build a b)) + else do + let cnt ← getThe Nat + modify fun n => n + 1 + have out : Aiur.Local := Aiur.Local.str (toString "inl#" ++ toString cnt) + pure (Aiur.Source.Term.wrapLets (fa ++ (Aiur.Pattern.var out, a) :: fb) (build (Aiur.Source.Term.var out) b)) +PREMISE Aiur.Source.Term.peelListLets +List Aiur.Source.Term → StateM Nat (List (Aiur.Pattern × Aiur.Source.Term) × List Aiur.Source.Term) +DEFINITION +fun ts => + List.foldrM + (fun t x => + match x with + | (fs, cs) => + match t.peelLets with + | (f, c) => + if (fs.isEmpty || c.isAtomic) = true then pure (f ++ fs, c :: cs) + else do + let cnt ← getThe Nat + modify fun n => n + 1 + have out : Aiur.Local := Aiur.Local.str (toString "inl#" ++ toString cnt) + pure (f ++ (Aiur.Pattern.var out, c) :: fs, Aiur.Source.Term.var out :: cs)) + ([], []) ts +PREMISE Aiur.Source.Term.freshen +Nat → Std.HashMap Aiur.Local Aiur.Local → Aiur.Source.Term → Nat × Aiur.Source.Term +DEFINITION +fun cnt subst a => Aiur.Source.Term.freshen._unary ⟨cnt, ⟨subst, a⟩⟩ +PREMISE Aiur.Source.Term.freshBound +Aiur.Source.Term → Nat +DEFINITION +WellFounded.Nat.fix (fun x => sizeOf x) fun a a_1 => + (match (motive := + (x : Aiur.Source.Term) → + ((y : Aiur.Source.Term) → InvImage (fun x1 x2 => x1 < x2) (fun x => sizeOf x) y x → Nat) → Nat) + a with + | Aiur.Source.Term.unit => fun x => 0 + | Aiur.Source.Term.field a => fun x => 0 + | Aiur.Source.Term.u8Lit a => fun x => 0 + | Aiur.Source.Term.var x => fun x_1 => Aiur.Source.localFreshBound x + | Aiur.Source.Term.ref g => fun x => Aiur.Source.globalFreshBound g + | Aiur.Source.Term.app g args mode => fun x => + List.foldl + (fun acc x_1 => + match x_1 with + | ⟨a, property⟩ => max acc (x a ⋯)) + (Aiur.Source.globalFreshBound g) args.attach + | Aiur.Source.Term.tuple ts => fun x => + Array.foldl + (fun acc x_1 => + match x_1 with + | ⟨a, property⟩ => max acc (x a ⋯)) + 0 ts.attach + | Aiur.Source.Term.array ts => fun x => + Array.foldl + (fun acc x_1 => + match x_1 with + | ⟨a, property⟩ => max acc (x a ⋯)) + 0 ts.attach + | Aiur.Source.Term.let p v b => fun x => + max (List.foldl (fun n x => max n (Aiur.Source.localFreshBound x)) 0 (Aiur.Source.Pattern.locals p)) + (max (x v ⋯) (x b ⋯)) + | s.match arms => fun x => + List.foldl + (fun acc x_1 => + match x_1 with + | ⟨(p, a), property⟩ => + max acc + (max (List.foldl (fun n x => max n (Aiur.Source.localFreshBound x)) 0 (Aiur.Source.Pattern.locals p)) + (x a ⋯))) + (x s ⋯) arms.attach + | a.add b => fun x => max (x a ⋯) (x b ⋯) + | a.sub b => fun x => max (x a ⋯) (x b ⋯) + | a.mul b => fun x => max (x a ⋯) (x b ⋯) + | a.set a_2 b => fun x => max (x a ⋯) (x b ⋯) + | a.u8Xor b => fun x => max (x a ⋯) (x b ⋯) + | a.u8Add b => fun x => max (x a ⋯) (x b ⋯) + | a.u8Mul b => fun x => max (x a ⋯) (x b ⋯) + | a.u8Sub b => fun x => max (x a ⋯) (x b ⋯) + | a.u8And b => fun x => max (x a ⋯) (x b ⋯) + | a.u8Or b => fun x => max (x a ⋯) (x b ⋯) + | a.u8LessThan b => fun x => max (x a ⋯) (x b ⋯) + | a.u32LessThan b => fun x => max (x a ⋯) (x b ⋯) + | a.u8XorSplit7 b => fun x => max (x a ⋯) (x b ⋯) + | a.u8XorSplit4 b => fun x => max (x a ⋯) (x b ⋯) + | a.unconstrainedU32Add b => fun x => max (x a ⋯) (x b ⋯) + | a.unconstrainedBigUintDivMod b => fun x => max (x a ⋯) (x b ⋯) + | a.u8RangeCheck b => fun x => max (x a ⋯) (x b ⋯) + | a.ioGetInfo b => fun x => max (x a ⋯) (x b ⋯) + | a.ioRead b len => fun x => max (x a ⋯) (x b ⋯) + | a.assertEq b msg c => fun x => max (x a ⋯) (max (x b ⋯) (x c ⋯)) + | a.ioWrite b c => fun x => max (x a ⋯) (max (x b ⋯) (x c ⋯)) + | a.unconstrainedU32Add3 b c => fun x => max (x a ⋯) (max (x b ⋯) (x c ⋯)) + | c.ioSetInfo k i l r => fun x => max (x c ⋯) (max (x k ⋯) (max (x i ⋯) (max (x l ⋯) (x r ⋯)))) + | a.ret => fun x => x a ⋯ + | a.eqZero => fun x => x a ⋯ + | a.proj a_2 => fun x => x a ⋯ + | a.get a_2 => fun x => x a ⋯ + | a.slice a_2 a_3 => fun x => x a ⋯ + | a.store => fun x => x a ⋯ + | a.load => fun x => x a ⋯ + | a.ptrVal => fun x => x a ⋯ + | Aiur.Source.Term.ann a a_2 => fun x => x a_2 ⋯ + | a.u8BitDecomposition => fun x => x a ⋯ + | a.u8ShiftLeft => fun x => x a ⋯ + | a.u8ShiftRight => fun x => x a ⋯ + | a.toField => fun x => x a ⋯ + | a.u8FromFieldUnsafe => fun x => x a ⋯ + | a.unconstrainedGToBytes => fun x => x a ⋯ + | a.unconstrainedGInverse => fun x => x a ⋯ + | a.u32ToField => fun x => x a ⋯ + | Aiur.Source.Term.debug a o a_2 => fun x => + max (x a_2 ⋯) + ((match (motive := + (o : Option Aiur.Source.Term) → + ((y : Aiur.Source.Term) → + InvImage (fun x1 x2 => x1 < x2) (fun x => sizeOf x) y (Aiur.Source.Term.debug a o a_2) → Nat) → + Nat) + o with + | none => fun x => 0 + | some b => fun x => x b ⋯) + x)) + a_1 +PREMISE Aiur.Source.Term.hasExplicitReturn +Aiur.Source.Term → Bool +DEFINITION +WellFounded.Nat.fix (fun x => sizeOf x) fun a a_1 => + (match (motive := + (x : Aiur.Source.Term) → + ((y : Aiur.Source.Term) → InvImage (fun x1 x2 => x1 < x2) (fun x => sizeOf x) y x → Bool) → Bool) + a with + | a.ret => fun x => true + | Aiur.Source.Term.var a => fun x => false + | Aiur.Source.Term.unit => fun x => false + | Aiur.Source.Term.field a => fun x => false + | Aiur.Source.Term.u8Lit a => fun x => false + | Aiur.Source.Term.ref a => fun x => false + | Aiur.Source.Term.app a args mode => fun x => args.attach.any fun arg => x arg.val ⋯ + | Aiur.Source.Term.tuple terms => fun x => terms.attach.any fun term => x term.val ⋯ + | Aiur.Source.Term.array terms => fun x => terms.attach.any fun term => x term.val ⋯ + | Aiur.Source.Term.let a value body => fun x => x value ⋯ || x body ⋯ + | scrut.match arms => fun x => x scrut ⋯ || arms.attach.any fun arm => x arm.val.snd ⋯ + | a.eqZero => fun x => x a ⋯ + | a.proj a_2 => fun x => x a ⋯ + | a.get a_2 => fun x => x a ⋯ + | a.slice a_2 a_3 => fun x => x a ⋯ + | a.store => fun x => x a ⋯ + | a.load => fun x => x a ⋯ + | a.ptrVal => fun x => x a ⋯ + | Aiur.Source.Term.ann a a_2 => fun x => x a_2 ⋯ + | a.u8BitDecomposition => fun x => x a ⋯ + | a.u8ShiftLeft => fun x => x a ⋯ + | a.u8ShiftRight => fun x => x a ⋯ + | a.u32ToField => fun x => x a ⋯ + | a.unconstrainedGToBytes => fun x => x a ⋯ + | a.unconstrainedGInverse => fun x => x a ⋯ + | a.toField => fun x => x a ⋯ + | a.u8FromFieldUnsafe => fun x => x a ⋯ + | a.add b => fun x => x a ⋯ || x b ⋯ + | a.sub b => fun x => x a ⋯ || x b ⋯ + | a.mul b => fun x => x a ⋯ || x b ⋯ + | a.set a_2 b => fun x => x a ⋯ || x b ⋯ + | a.ioGetInfo b => fun x => x a ⋯ || x b ⋯ + | a.ioRead b len => fun x => x a ⋯ || x b ⋯ + | a.u8Xor b => fun x => x a ⋯ || x b ⋯ + | a.u8Add b => fun x => x a ⋯ || x b ⋯ + | a.u8Mul b => fun x => x a ⋯ || x b ⋯ + | a.u8Sub b => fun x => x a ⋯ || x b ⋯ + | a.u8And b => fun x => x a ⋯ || x b ⋯ + | a.u8Or b => fun x => x a ⋯ || x b ⋯ + | a.u8LessThan b => fun x => x a ⋯ || x b ⋯ + | a.u32LessThan b => fun x => x a ⋯ || x b ⋯ + | a.u8XorSplit7 b => fun x => x a ⋯ || x b ⋯ + | a.u8XorSplit4 b => fun x => x a ⋯ || x b ⋯ + | a.unconstrainedU32Add b => fun x => x a ⋯ || x b ⋯ + | a.unconstrainedBigUintDivMod b => fun x => x a ⋯ || x b ⋯ + | a.u8RangeCheck b => fun x => x a ⋯ || x b ⋯ + | a.assertEq b msg c => fun x => x a ⋯ || x b ⋯ || x c ⋯ + | a.ioWrite b c => fun x => x a ⋯ || x b ⋯ || x c ⋯ + | a.unconstrainedU32Add3 b c => fun x => x a ⋯ || x b ⋯ || x c ⋯ + | a.ioSetInfo b c d e => fun x => x a ⋯ || x b ⋯ || x c ⋯ || x d ⋯ || x e ⋯ + | Aiur.Source.Term.debug a none continuation => fun x => x continuation ⋯ + | Aiur.Source.Term.debug a (some value) continuation => fun x => x value ⋯ || x continuation ⋯) + a_1 +PREMISE Aiur.Source.Term.expandOnce +Std.HashMap Aiur.Global (List Aiur.Local × Aiur.Source.Term) → Nat → Aiur.Source.Term → Nat × Aiur.Source.Term +DEFINITION +fun done cnt a => Aiur.Source.Term.expandOnce._unary done ⟨cnt, a⟩ +PREMISE Aiur.Source.Toplevel.inlineCalls +Aiur.Source.Toplevel → Except String Aiur.Source.Toplevel +DEFINITION +fun t => + have cnt := + Array.foldl + (fun cnt f => + List.foldl + (fun cnt x => + match x with + | (x, snd) => max cnt (Aiur.Source.localFreshBound x)) + (max cnt (max (Aiur.Source.globalFreshBound f.name) f.body.freshBound)) f.inputs) + 0 t.functions; + match + Array.foldl + (fun x f => + match x with + | (cnt, fs) => + match Aiur.Source.Function.freshen cnt f with + | (cnt, f) => (cnt, fs.push f)) + (cnt, #[]) t.functions with + | (cnt, functions) => + have t := + { dataTypes := t.dataTypes, typeAliases := t.typeAliases, functions := functions, + componentRanks := t.componentRanks }; + have funcs := Array.foldl (fun m f => m.insert f.name f) ∅ t.functions; + do + let deps ← + Array.foldlM + (fun deps f => do + let gs ← + List.foldlM + (fun acc x => + match x with + | (g, n) => + match funcs[g]? with + | some callee => + have __do_jp := fun __r => pure (acc ++ [g]); + if (n != callee.inputs.length) = true then do + let __r ← + throw + (toString "inline `" ++ toString g.toName ++ toString "`: got " ++ toString n ++ + toString " args, expects " ++ + toString callee.inputs.length) + __do_jp __r + else __do_jp () + | x => throw (toString "inline call to unknown function `" ++ toString g.toName ++ toString "`")) + [] f.body.inlineCallSites + pure (deps.insert f.name gs)) + ∅ t.functions + have names : List Aiur.Global := List.map Aiur.Source.Function.name t.functions.toList + let order ← Aiur.Source.inlineTopo deps names.length names ∅ [] + match + List.foldl + (fun x g => + match x with + | (cnt, done) => + match funcs[g]? with + | none => (cnt, done) + | some f => + match Aiur.Source.Term.expandOnce done cnt f.body with + | (cnt, body) => (cnt, done.insert g (List.map Prod.fst f.inputs, body))) + (cnt, ∅) order with + | (fst, done) => + have functions := + Array.map + (fun f => + match done[f.name]? with + | none => f + | some (fst, body) => + { name := f.name, params := f.params, inputs := f.inputs, output := f.output, + body := body.restoreTailMatches.hoistLets, entry := f.entry, entryMonomorphic := ⋯, + entryPointerFree := ⋯ }) + t.functions; + pure + { dataTypes := t.dataTypes, typeAliases := t.typeAliases, functions := functions, + componentRanks := t.componentRanks } +PREMISE Aiur.Bytecode.AIR.Memory +Type +DEFINITION +Nat → Aiur.G → Array Aiur.G → Prop +PREMISE Aiur.Bytecode.AIR.Call.mk +Aiur.Bytecode.FunIdx → Array Aiur.G → Array Aiur.G → Aiur.G → Aiur.Bytecode.AIR.Call +PREMISE Aiur.Bytecode.AIR.primitive +Aiur.Bytecode.Op → Array Aiur.G → Array Aiur.G → Option (Array Aiur.G) +DEFINITION +fun op values advice => + match op with + | Aiur.Bytecode.Op.const value => some #[value] + | Aiur.Bytecode.Op.add a b => do + let __do_lift ← values[a]? + let __do_lift_1 ← values[b]? + pure #[__do_lift + __do_lift_1] + | Aiur.Bytecode.Op.sub a b => do + let __do_lift ← values[a]? + let __do_lift_1 ← values[b]? + pure #[__do_lift - __do_lift_1] + | Aiur.Bytecode.Op.mul a b => do + let __do_lift ← values[a]? + let __do_lift_1 ← values[b]? + pure #[__do_lift * __do_lift_1] + | Aiur.Bytecode.Op.eqZero a => do + let __do_lift ← values[a]? + pure #[__do_lift.eqZero] + | Aiur.Bytecode.Op.call a a_1 outputSize true => Aiur.Bytecode.AIR.adviceOfSize outputSize advice + | Aiur.Bytecode.Op.call a a_1 outputSize false => none + | Aiur.Bytecode.Op.store a => none + | Aiur.Bytecode.Op.load size a => none + | Aiur.Bytecode.Op.assertEq xs ys a => do + let left ← Aiur.Bytecode.AIR.readValues values xs + let right ← Aiur.Bytecode.AIR.readValues values ys + if left = right then some #[] else none + | Aiur.Bytecode.Op.ioGetInfo a a_1 => Aiur.Bytecode.AIR.adviceOfSize 2 advice + | Aiur.Bytecode.Op.ioRead a a_1 size => Aiur.Bytecode.AIR.adviceOfSize size advice + | Aiur.Bytecode.Op.ioSetInfo a a_1 a_2 a_3 => some #[] + | Aiur.Bytecode.Op.ioWrite a a_1 => some #[] + | Aiur.Bytecode.Op.debug a a_1 => some #[] + | Aiur.Bytecode.Op.u8BitDecomposition a => + Aiur.Bytecode.AIR.unaryByte values a (Array.ofFn ∘ Aiur.G.u8BitDecomposition) + | Aiur.Bytecode.Op.u8ShiftLeft a => Aiur.Bytecode.AIR.unaryByte values a fun x => #[x.u8ShiftLeft] + | Aiur.Bytecode.Op.u8ShiftRight a => Aiur.Bytecode.AIR.unaryByte values a fun x => #[x.u8ShiftRight] + | Aiur.Bytecode.Op.u8Xor a b => Aiur.Bytecode.AIR.binaryByte values a b fun x y => #[x.u8Xor y] + | Aiur.Bytecode.Op.u8Add a b => + Aiur.Bytecode.AIR.binaryByte values a b fun x y => Aiur.Bytecode.AIR.pairValues (x.u8Add y) + | Aiur.Bytecode.Op.u8Mul a b => + Aiur.Bytecode.AIR.binaryByte values a b fun x y => Aiur.Bytecode.AIR.pairValues (x.u8Mul y) + | Aiur.Bytecode.Op.u8Sub a b => + Aiur.Bytecode.AIR.binaryByte values a b fun x y => Aiur.Bytecode.AIR.pairValues (x.u8Sub y) + | Aiur.Bytecode.Op.u8And a b => Aiur.Bytecode.AIR.binaryByte values a b fun x y => #[x.u8And y] + | Aiur.Bytecode.Op.u8Or a b => Aiur.Bytecode.AIR.binaryByte values a b fun x y => #[x.u8Or y] + | Aiur.Bytecode.Op.u8LessThan a b => Aiur.Bytecode.AIR.binaryByte values a b fun x y => #[x.u8LessThan y] + | Aiur.Bytecode.Op.u8XorSplit7 a b => + Aiur.Bytecode.AIR.binaryByte values a b fun x y => + have z := x.n ^^^ y.n; + #[Aiur.G.ofNat (z / 128), Aiur.G.ofNat (z * 2 % 256)] + | Aiur.Bytecode.Op.u8XorSplit4 a b => + Aiur.Bytecode.AIR.binaryByte values a b fun x y => + have z := x.n ^^^ y.n; + #[Aiur.G.ofNat (z / 16), Aiur.G.ofNat (z * 16 % 256)] + | Aiur.Bytecode.Op.u8RangeCheck a b => Aiur.Bytecode.AIR.binaryByte values a b fun x x_1 => #[] + | Aiur.Bytecode.Op.u32LessThan a b => do + let x ← values[a]? + let y ← values[b]? + if x.n < 2 ^ 32 ∧ y.n < 2 ^ 32 then some #[x.u32LessThan y] else none + | Aiur.Bytecode.Op.unconstrainedBigUintDivMod a a_1 => Aiur.Bytecode.AIR.adviceOfSize 2 advice + | Aiur.Bytecode.Op.unconstrainedGToBytes a => Aiur.Bytecode.AIR.adviceOfSize 8 advice + | Aiur.Bytecode.Op.unconstrainedGInverse a => Aiur.Bytecode.AIR.adviceOfSize 1 advice + | Aiur.Bytecode.Op.unconstrainedU32Add a b => do + let x ← Aiur.Bytecode.AIR.readWord values a + let y ← Aiur.Bytecode.AIR.readWord values b + let bytes ← Aiur.Bytecode.AIR.adviceOfSize 4 advice + pure (bytes.push ((x + y - Aiur.Bytecode.AIR.packWord bytes) * 18446744065119617026)) + | Aiur.Bytecode.Op.unconstrainedU32Add3 a b c => do + let x ← Aiur.Bytecode.AIR.readWord values a + let y ← Aiur.Bytecode.AIR.readWord values b + let z ← Aiur.Bytecode.AIR.readWord values c + let bytes ← Aiur.Bytecode.AIR.adviceOfSize 4 advice + pure (bytes.push ((x + y + z - Aiur.Bytecode.AIR.packWord bytes) * 18446744065119617026)) + | Aiur.Bytecode.Op.u32ToField bytes => do + let __do_lift ← Aiur.Bytecode.AIR.readWord values bytes + pure #[__do_lift] +PREMISE Aiur.Bytecode.AIR.readValues +Array Aiur.G → Array Aiur.Bytecode.ValIdx → Option (Array Aiur.G) +DEFINITION +fun values indices => Array.mapM (fun index => values[index]?) indices +PREMISE Aiur.Bytecode.AIR.packWord +Array Aiur.G → Aiur.G +DEFINITION +fun bytes => + List.foldl + (fun value x => + match x with + | (byte, index) => value + byte * Aiur.G.ofNat (256 ^ index)) + 0 bytes.toList.zipIdx +PREMISE Aiur.Bytecode.AIR.adviceOfSize +Nat → Array Aiur.G → Option (Array Aiur.G) +DEFINITION +fun size advice => if advice.size = size then some advice else none +PREMISE Aiur.Bytecode.AIR.unaryByte +Array Aiur.G → Aiur.Bytecode.ValIdx → (Aiur.G → Array Aiur.G) → Option (Array Aiur.G) +DEFINITION +fun values index compute => do + let value ← values[index]? + if value.n < 256 then some (compute value) else none +PREMISE Aiur.Bytecode.AIR.binaryByte +Array Aiur.G → Aiur.Bytecode.ValIdx → Aiur.Bytecode.ValIdx → (Aiur.G → Aiur.G → Array Aiur.G) → Option (Array Aiur.G) +DEFINITION +fun values left right compute => do + let x ← values[left]? + let y ← values[right]? + if x.n < 256 ∧ y.n < 256 then some (compute x y) else none +PREMISE Aiur.Bytecode.AIR.pairValues +Aiur.G × Aiur.G → Array Aiur.G +DEFINITION +fun pair => #[pair.fst, pair.snd] +PREMISE Aiur.Bytecode.AIR.readWord +Array Aiur.G → Array Aiur.Bytecode.ValIdx → Option Aiur.G +DEFINITION +fun values indices => + if indices.size ≠ 4 then none + else do + let bytes ← Aiur.Bytecode.AIR.readValues values indices + some (Aiur.Bytecode.AIR.packWord bytes) +PREMISE Aiur.Bytecode.AIR.Step.primitive +∀ {memory : Aiur.Bytecode.AIR.Memory} {op : Aiur.Bytecode.Op} {values advice outputs : Array Aiur.G}, + Aiur.Bytecode.AIR.primitive op values advice = some outputs → + Aiur.Bytecode.AIR.Step memory op values (values ++ outputs) [] +PREMISE Aiur.Bytecode.AIR.Step.call +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {indices : Array Aiur.Bytecode.ValIdx} {size : Nat} + {request : Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.readValues values indices = some request.inputs → + request.outputs.size = size → + Aiur.Bytecode.AIR.Step memory (Aiur.Bytecode.Op.call request.function indices size false) values + (values ++ request.outputs) [request] +PREMISE Aiur.Bytecode.AIR.Step.store +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {indices : Array Aiur.Bytecode.ValIdx} + {contents : Array Aiur.G} {pointer : Aiur.G}, + Aiur.Bytecode.AIR.readValues values indices = some contents → + memory contents.size pointer contents → + Aiur.Bytecode.AIR.Step memory (Aiur.Bytecode.Op.store indices) values (values.push pointer) [] +PREMISE Aiur.Bytecode.AIR.Step.load +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {index : Aiur.Bytecode.ValIdx} {pointer : Aiur.G} + {size : Nat} {contents : Array Aiur.G}, + values[index]? = some pointer → + contents.size = size → + memory size pointer contents → + Aiur.Bytecode.AIR.Step memory (Aiur.Bytecode.Op.load size index) values (values ++ contents) [] +PREMISE Aiur.Bytecode.AIR.RunOps.nil +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G}, Aiur.Bytecode.AIR.RunOps memory [] values values [] +PREMISE Aiur.Bytecode.AIR.RunOps.cons +∀ {memory : Aiur.Bytecode.AIR.Memory} {op : Aiur.Bytecode.Op} {values intermediate : Array Aiur.G} + {firstCalls : List Aiur.Bytecode.AIR.Call} {ops : List Aiur.Bytecode.Op} {finalValues : Array Aiur.G} + {restCalls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Step memory op values intermediate firstCalls → + Aiur.Bytecode.AIR.RunOps memory ops intermediate finalValues restCalls → + Aiur.Bytecode.AIR.RunOps memory (op :: ops) values finalValues (firstCalls ++ restCalls) +PREMISE Aiur.Bytecode.AIR.SelectArm.case +∀ {scrutinee : Aiur.G} {cases : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} + {block : Aiur.Bytecode.Block}, + (scrutinee, block) ∈ cases.toList → Aiur.Bytecode.AIR.SelectArm scrutinee cases fallback block +PREMISE Aiur.Bytecode.AIR.SelectArm.fallback +∀ {scrutinee : Aiur.G} {cases : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} + {block : Aiur.Bytecode.Block}, + fallback = some block → + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), pair ∈ cases.toList → pair.fst ≠ scrutinee) → + Aiur.Bytecode.AIR.SelectArm scrutinee cases fallback block +PREMISE Aiur.Bytecode.AIR.RunBlock.block +∀ {memory : Aiur.Bytecode.AIR.Memory} {values intermediate : Array Aiur.G} {opCalls : List Aiur.Bytecode.AIR.Call} + {outcome : Aiur.Bytecode.AIR.Outcome} {ctrlCalls : List Aiur.Bytecode.AIR.Call} {block : Aiur.Bytecode.Block}, + Aiur.Bytecode.AIR.RunOps memory block.ops.toList values intermediate opCalls → + Aiur.Bytecode.AIR.RunCtrl memory block.ctrl intermediate outcome ctrlCalls → + Aiur.Bytecode.AIR.RunBlock memory block values outcome (opCalls ++ ctrlCalls) +PREMISE Aiur.Bytecode.AIR.RunCtrl.returned +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {indices : Array Aiur.Bytecode.ValIdx} + {outputs : Array Aiur.G} {selector : Aiur.Bytecode.SelIdx}, + Aiur.Bytecode.AIR.readValues values indices = some outputs → + Aiur.Bytecode.AIR.RunCtrl memory (Aiur.Bytecode.Ctrl.return selector indices) values + (Aiur.Bytecode.AIR.Outcome.returned outputs) [] +PREMISE Aiur.Bytecode.AIR.RunCtrl.yielded +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {indices : Array Aiur.Bytecode.ValIdx} + {outputs : Array Aiur.G} {selector : Aiur.Bytecode.SelIdx}, + Aiur.Bytecode.AIR.readValues values indices = some outputs → + Aiur.Bytecode.AIR.RunCtrl memory (Aiur.Bytecode.Ctrl.yield selector indices) values + (Aiur.Bytecode.AIR.Outcome.yielded outputs) [] +PREMISE Aiur.Bytecode.AIR.RunCtrl.match +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {index : Aiur.Bytecode.ValIdx} {scrutinee : Aiur.G} + {cases : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} {arm : Aiur.Bytecode.Block} + {outcome : Aiur.Bytecode.AIR.Outcome} {calls : List Aiur.Bytecode.AIR.Call}, + values[index]? = some scrutinee → + Aiur.Bytecode.AIR.SelectArm scrutinee cases fallback arm → + Aiur.Bytecode.AIR.RunBlock memory arm values outcome calls → + Aiur.Bytecode.AIR.RunCtrl memory (Aiur.Bytecode.Ctrl.match index cases fallback) values outcome calls +PREMISE Aiur.Bytecode.AIR.RunCtrl.matchContinueReturn +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {index : Aiur.Bytecode.ValIdx} {scrutinee : Aiur.G} + {cases : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} {arm : Aiur.Bytecode.Block} + {outputs : Array Aiur.G} {calls : List Aiur.Bytecode.AIR.Call} {size aux lookups : Nat} + {continuation : Aiur.Bytecode.Block}, + values[index]? = some scrutinee → + Aiur.Bytecode.AIR.SelectArm scrutinee cases fallback arm → + Aiur.Bytecode.AIR.RunBlock memory arm values (Aiur.Bytecode.AIR.Outcome.returned outputs) calls → + Aiur.Bytecode.AIR.RunCtrl memory + (Aiur.Bytecode.Ctrl.matchContinue index cases fallback size aux lookups continuation) values + (Aiur.Bytecode.AIR.Outcome.returned outputs) calls +PREMISE Aiur.Bytecode.AIR.RunCtrl.matchContinueYield +∀ {memory : Aiur.Bytecode.AIR.Memory} {values : Array Aiur.G} {index : Aiur.Bytecode.ValIdx} {scrutinee : Aiur.G} + {cases : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} {arm : Aiur.Bytecode.Block} + {yielded : Array Aiur.G} {branchCalls : List Aiur.Bytecode.AIR.Call} {size : Nat} {continuation : Aiur.Bytecode.Block} + {outcome : Aiur.Bytecode.AIR.Outcome} {contCalls : List Aiur.Bytecode.AIR.Call} {aux lookups : Nat}, + values[index]? = some scrutinee → + Aiur.Bytecode.AIR.SelectArm scrutinee cases fallback arm → + Aiur.Bytecode.AIR.RunBlock memory arm values (Aiur.Bytecode.AIR.Outcome.yielded yielded) branchCalls → + yielded.size = size → + Aiur.Bytecode.AIR.RunBlock memory continuation (values ++ yielded) outcome contCalls → + Aiur.Bytecode.AIR.RunCtrl memory + (Aiur.Bytecode.Ctrl.matchContinue index cases fallback size aux lookups continuation) values outcome + (branchCalls ++ contCalls) +PREMISE Aiur.Bytecode.AIR.RunFunction.function +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {function : Aiur.Bytecode.Function} + {calls : List Aiur.Bytecode.AIR.Call} {request : Aiur.Bytecode.AIR.Call}, + program.functions[request.function]? = some function → + function.layout.inputSize = request.inputs.size → + Aiur.Bytecode.AIR.RunBlock memory function.body request.inputs + (Aiur.Bytecode.AIR.Outcome.returned request.outputs) calls → + Aiur.Bytecode.AIR.RunFunction program memory request calls +PREMISE Aiur.Bytecode.AIR.Execution.function +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {request : Aiur.Bytecode.AIR.Call} + {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunFunction program memory request calls → + (∀ (child : Aiur.Bytecode.AIR.Call), child ∈ calls → Aiur.Bytecode.AIR.Execution program memory child) → + Aiur.Bytecode.AIR.Execution program memory request +PREMISE Aiur.AIR.FunctionRow.mk +Aiur.Bytecode.AIR.Call → + List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → (Fin 6 → Aiur.G) → Aiur.G → Aiur.G → Aiur.AIR.FunctionRow +PREMISE Aiur.AIR.FunctionRow.Valid.mk +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {row : Aiur.AIR.FunctionRow}, + row.selector = 0 ∨ row.selector = 1 → + Aiur.AIR.activityConstraint row.multiplicity row.selector = 0 → + (row.selector = 1 → row.request.rank = Aiur.AIR.packRank row.rankBytes) → + (row.selector = 1 → Aiur.Bytecode.AIR.RunFunction program memory row.request row.requests) → + (∀ (edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)), + edge ∈ row.calls → + row.selector * + Aiur.AIR.callOrderConstraint row.request.rank edge.fst.rank (Aiur.AIR.packRank edge.snd) = + 0) → + Aiur.AIR.FunctionRow.Valid program memory row +PREMISE Aiur.AIR.FunctionRow.requests +Aiur.AIR.FunctionRow → List Aiur.Bytecode.AIR.Call +DEFINITION +fun row => List.map Prod.fst row.calls +PREMISE Aiur.AIR.FunctionRow.byteQueries +Aiur.AIR.FunctionRow → List (Aiur.G × Aiur.G) +DEFINITION +fun row => + Aiur.AIR.rankByteQueries row.rankBytes ++ List.flatMap (fun edge => Aiur.AIR.rankByteQueries edge.snd) row.calls +PREMISE Aiur.AIR.functionProviders +List Aiur.AIR.FunctionRow → List (Aiur.AIR.Provider Aiur.Bytecode.AIR.Call) +DEFINITION +fun rows => List.map (fun row => (row.request, row.multiplicity)) rows +PREMISE Aiur.AIR.functionQueries +List Aiur.Bytecode.AIR.Call → List Aiur.AIR.FunctionRow → List Aiur.Bytecode.AIR.Call +DEFINITION +fun roots rows => roots ++ List.flatMap (fun row => if row.selector = 1 then row.requests else []) rows +PREMISE Aiur.AIR.functionByteQueries +List Aiur.AIR.FunctionRow → List (Aiur.G × Aiur.G) +DEFINITION +fun rows => List.flatMap (fun row => if row.selector = 1 then row.byteQueries else []) rows +PREMISE Aiur.AIR.MemoryRow.mk +Aiur.G → Aiur.G → Aiur.G → Array Aiur.G → Aiur.AIR.MemoryRow +PREMISE Aiur.AIR.memoryActivityTransition +Aiur.AIR.MemoryRow → Aiur.AIR.MemoryRow → Aiur.G +DEFINITION +fun row next => next.selector * (row.selector - 1) +PREMISE Aiur.AIR.memoryPointerTransition +Aiur.AIR.MemoryRow → Aiur.AIR.MemoryRow → Aiur.G +DEFINITION +fun row next => next.selector * (row.pointer + 1 - next.pointer) +PREMISE Aiur.AIR.MemoryRowsValid.mk +∀ {width : Nat} {rows : Array Aiur.AIR.MemoryRow}, + (∀ (i : Nat) (hi : i < rows.size), rows[i].selector = 0 ∨ rows[i].selector = 1) → + (∀ (i : Nat) (hi : i < rows.size), Aiur.AIR.activityConstraint rows[i].multiplicity rows[i].selector = 0) → + (∀ (i : Nat) (hi : i < rows.size), rows[i].contents.size = width) → + (∀ (i : Nat) (hi : i + 1 < rows.size), Aiur.AIR.memoryActivityTransition rows[i] rows[i + 1] = 0) → + (∀ (i : Nat) (hi : i + 1 < rows.size), Aiur.AIR.memoryPointerTransition rows[i] rows[i + 1] = 0) → + Aiur.AIR.MemoryRowsValid width rows +PREMISE Aiur.AIR.memoryFacts +(Nat → Array Aiur.AIR.MemoryRow) → Aiur.Bytecode.AIR.Memory +DEFINITION +fun tables width pointer contents => + ∃ i hi, (tables width)[i].selector = 1 ∧ (tables width)[i].pointer = pointer ∧ (tables width)[i].contents = contents +PREMISE Aiur.AIR.memoryProviders +Array Aiur.AIR.MemoryRow → List (Aiur.AIR.Provider (Aiur.G × Array Aiur.G)) +DEFINITION +fun rows => List.ofFn fun i => ((rows[i].pointer, rows[i].contents), rows[i].multiplicity) +PREMISE Aiur.AIR.memoryPointerCycle +Nat → Array Aiur.AIR.MemoryRow +DEFINITION +fun period => + Array.ofFn fun i => + { selector := 1, multiplicity := 0, pointer := Aiur.G.ofNat ↑i, contents := #[Aiur.G.ofNat (↑i / period)] } +PREMISE Aiur.GoldilocksProof.squareMod +Nat → Nat → Nat → Nat +DEFINITION +fun modulus base x => Nat.brecOn x (Aiur.GoldilocksProof.squareMod._f modulus base) +PREMISE Aiur.AIR.booleanConstraint +Aiur.G → Aiur.G +DEFINITION +fun value => value * (value - 1) +PREMISE Aiur.AIR.oneSubBooleanConstraint +Aiur.G → Aiur.G +DEFINITION +fun value => value * (1 - value) +PREMISE Aiur.AIR.selectorSum +List Aiur.G → Aiur.G +DEFINITION +fun selectors => List.foldl (fun x1 x2 => x1 + x2) 0 selectors +PREMISE Aiur.AIR.MemoryRowsPolynomials.mk +∀ {width : Nat} {rows : Array Aiur.AIR.MemoryRow}, + (∀ (i : Nat) (hi : i < rows.size), Aiur.AIR.booleanConstraint rows[i].selector = 0) → + (∀ (i : Nat) (hi : i < rows.size), Aiur.AIR.activityConstraint rows[i].multiplicity rows[i].selector = 0) → + (∀ (i : Nat) (hi : i < rows.size), rows[i].contents.size = width) → + (∀ (i : Nat) (hi : i + 1 < rows.size), Aiur.AIR.memoryActivityTransition rows[i] rows[i + 1] = 0) → + (∀ (i : Nat) (hi : i + 1 < rows.size), Aiur.AIR.memoryPointerTransition rows[i] rows[i + 1] = 0) → + Aiur.AIR.MemoryRowsPolynomials width rows +PREMISE Aiur.AIR.inverse256 +Aiur.G +DEFINITION +18374686475393433601 +PREMISE Aiur.AIR.pack4 +(Fin 4 → Aiur.G) → Aiur.G +DEFINITION +fun bytes => bytes 0 + 256 * bytes 1 + 65536 * bytes 2 + 16777216 * bytes 3 +PREMISE Aiur.AIR.pack4Nat +(Fin 4 → Aiur.G) → Nat +DEFINITION +fun bytes => (bytes 0).n + 256 * (bytes 1).n + 65536 * (bytes 2).n + 16777216 * (bytes 3).n +PREMISE Aiur.AIR.carryStep +Aiur.G → Aiur.G → Aiur.G → Aiur.G → Aiur.G +DEFINITION +fun x y z previous => (x + y + previous - z) * Aiur.AIR.inverse256 +PREMISE Aiur.AIR.u32Carries +(Fin 4 → Aiur.G) → (Fin 4 → Aiur.G) → (Fin 4 → Aiur.G) → Fin 5 → Aiur.G +DEFINITION +fun x y z => + have c1 := Aiur.AIR.carryStep (x 0) (y 0) (z 0) 1; + have c2 := Aiur.AIR.carryStep (x 1) (y 1) (z 1) c1; + have c3 := Aiur.AIR.carryStep (x 2) (y 2) (z 2) c2; + have c4 := Aiur.AIR.carryStep (x 3) (y 3) (z 3) c3; + fun i => + match i with + | 0 => 1 + | 1 => c1 + | 2 => c2 + | 3 => c3 + | 4 => c4 +PREMISE Aiur.AIR.Byte1Kind.all +List Aiur.AIR.Byte1Kind +DEFINITION +[Aiur.AIR.Byte1Kind.bits, Aiur.AIR.Byte1Kind.shiftLeft, Aiur.AIR.Byte1Kind.shiftRight] +PREMISE Aiur.AIR.Byte1Kind.channel +Aiur.AIR.Byte1Kind → Aiur.G +DEFINITION +fun x => + match x with + | Aiur.AIR.Byte1Kind.bits => 2 + | Aiur.AIR.Byte1Kind.shiftLeft => 3 + | Aiur.AIR.Byte1Kind.shiftRight => 4 +PREMISE Aiur.AIR.Byte1Kind.result +Aiur.AIR.Byte1Kind → Aiur.G → Array Aiur.G +DEFINITION +fun x x_1 => + match x, x_1 with + | Aiur.AIR.Byte1Kind.bits, input => Array.ofFn input.u8BitDecomposition + | Aiur.AIR.Byte1Kind.shiftLeft, input => #[input.u8ShiftLeft] + | Aiur.AIR.Byte1Kind.shiftRight, input => #[input.u8ShiftRight] +PREMISE Aiur.AIR.byte1Outputs +Aiur.AIR.Byte1Kind → Fin 256 → Array Aiur.G +DEFINITION +fun kind row => + match kind with + | Aiur.AIR.Byte1Kind.bits => Array.ofFn fun bit => Aiur.G.ofNat (↑row >>> ↑bit &&& 1) + | Aiur.AIR.Byte1Kind.shiftLeft => #[Aiur.G.ofNat (↑row * 2 % 256)] + | Aiur.AIR.Byte1Kind.shiftRight => #[Aiur.G.ofNat (↑row / 2)] +PREMISE Aiur.AIR.byte1Request +Aiur.AIR.Byte1Kind → Aiur.G → Array Aiur.G → List Aiur.G +DEFINITION +fun kind input outputs => kind.channel :: input :: outputs.toList +PREMISE Aiur.AIR.byte1Providers +(Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G) → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun weights => + List.flatMap + (fun kind => + List.ofFn fun row => + (Aiur.AIR.byte1Request kind (Aiur.G.ofNat ↑row) (Aiur.AIR.byte1Outputs kind row), weights kind row)) + Aiur.AIR.Byte1Kind.all +PREMISE Aiur.AIR.Byte1Kind.op +Aiur.AIR.Byte1Kind → Aiur.Bytecode.ValIdx → Aiur.Bytecode.Op +DEFINITION +fun x => + match (motive := Aiur.AIR.Byte1Kind → Aiur.Bytecode.ValIdx → Aiur.Bytecode.Op) x with + | Aiur.AIR.Byte1Kind.bits => Aiur.Bytecode.Op.u8BitDecomposition + | Aiur.AIR.Byte1Kind.shiftLeft => Aiur.Bytecode.Op.u8ShiftLeft + | Aiur.AIR.Byte1Kind.shiftRight => Aiur.Bytecode.Op.u8ShiftRight +PREMISE Aiur.AIR.Byte2Kind.all +List Aiur.AIR.Byte2Kind +DEFINITION +[Aiur.AIR.Byte2Kind.xor, Aiur.AIR.Byte2Kind.add, Aiur.AIR.Byte2Kind.sub, Aiur.AIR.Byte2Kind.and, Aiur.AIR.Byte2Kind.or, + Aiur.AIR.Byte2Kind.lessThan, Aiur.AIR.Byte2Kind.range, Aiur.AIR.Byte2Kind.mul, Aiur.AIR.Byte2Kind.split7, + Aiur.AIR.Byte2Kind.split4] +PREMISE Aiur.AIR.Byte2Kind.channel +Aiur.AIR.Byte2Kind → Aiur.G +DEFINITION +fun x => + match x with + | Aiur.AIR.Byte2Kind.xor => 5 + | Aiur.AIR.Byte2Kind.add => 6 + | Aiur.AIR.Byte2Kind.sub => 7 + | Aiur.AIR.Byte2Kind.and => 8 + | Aiur.AIR.Byte2Kind.or => 9 + | Aiur.AIR.Byte2Kind.lessThan => 10 + | Aiur.AIR.Byte2Kind.range => 11 + | Aiur.AIR.Byte2Kind.mul => 12 + | Aiur.AIR.Byte2Kind.split7 => 13 + | Aiur.AIR.Byte2Kind.split4 => 14 +PREMISE Aiur.AIR.Byte2Kind.result +Aiur.AIR.Byte2Kind → Aiur.G → Aiur.G → Array Aiur.G +DEFINITION +fun x x_1 x_2 => + match x, x_1, x_2 with + | Aiur.AIR.Byte2Kind.xor, x, y => #[x.u8Xor y] + | Aiur.AIR.Byte2Kind.add, x, y => #[(x.u8Add y).fst] + | Aiur.AIR.Byte2Kind.sub, x, y => #[(x.u8Sub y).fst] + | Aiur.AIR.Byte2Kind.and, x, y => #[x.u8And y] + | Aiur.AIR.Byte2Kind.or, x, y => #[x.u8Or y] + | Aiur.AIR.Byte2Kind.lessThan, x, y => #[x.u8LessThan y] + | Aiur.AIR.Byte2Kind.range, x, x_3 => #[] + | Aiur.AIR.Byte2Kind.mul, x, y => Aiur.Bytecode.AIR.pairValues (x.u8Mul y) + | Aiur.AIR.Byte2Kind.split7, x, y => #[Aiur.G.ofNat ((x.n ^^^ y.n) / 128), Aiur.G.ofNat ((x.n ^^^ y.n) * 2 % 256)] + | Aiur.AIR.Byte2Kind.split4, x, y => #[Aiur.G.ofNat ((x.n ^^^ y.n) / 16), Aiur.G.ofNat ((x.n ^^^ y.n) * 16 % 256)] +PREMISE Aiur.AIR.byte2Outputs +Aiur.AIR.Byte2Kind → Fin 65536 → Array Aiur.G +DEFINITION +fun kind row => + have x := ↑row / 256; + have y := ↑row % 256; + match kind with + | Aiur.AIR.Byte2Kind.xor => #[Aiur.G.ofNat (x ^^^ y)] + | Aiur.AIR.Byte2Kind.add => #[Aiur.G.ofNat ((x + y) % 256)] + | Aiur.AIR.Byte2Kind.sub => #[Aiur.G.ofNat ((x + 256 - y) % 256)] + | Aiur.AIR.Byte2Kind.and => #[Aiur.G.ofNat (x &&& y)] + | Aiur.AIR.Byte2Kind.or => #[Aiur.G.ofNat (x ||| y)] + | Aiur.AIR.Byte2Kind.lessThan => #[if x < y then 1 else 0] + | Aiur.AIR.Byte2Kind.range => #[] + | Aiur.AIR.Byte2Kind.mul => #[Aiur.G.ofNat (x * y % 256), Aiur.G.ofNat (x * y / 256)] + | Aiur.AIR.Byte2Kind.split7 => #[Aiur.G.ofNat ((x ^^^ y) / 128), Aiur.G.ofNat ((x ^^^ y) * 2 % 256)] + | Aiur.AIR.Byte2Kind.split4 => #[Aiur.G.ofNat ((x ^^^ y) / 16), Aiur.G.ofNat ((x ^^^ y) * 16 % 256)] +PREMISE Aiur.AIR.byte2Request +Aiur.AIR.Byte2Kind → Aiur.G → Aiur.G → Array Aiur.G → List Aiur.G +DEFINITION +fun kind x y outputs => kind.channel :: x :: y :: outputs.toList +PREMISE Aiur.AIR.byte2Providers +(Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G) → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun weights => + List.flatMap + (fun kind => + List.ofFn fun row => + have inputs := Aiur.AIR.byteRangeMessage row; + (Aiur.AIR.byte2Request kind inputs.fst inputs.snd (Aiur.AIR.byte2Outputs kind row), weights kind row)) + Aiur.AIR.Byte2Kind.all +PREMISE Aiur.AIR.Byte2Kind.op +Aiur.AIR.Byte2Kind → Aiur.Bytecode.ValIdx → Aiur.Bytecode.ValIdx → Aiur.Bytecode.Op +DEFINITION +fun x => + match (motive := Aiur.AIR.Byte2Kind → Aiur.Bytecode.ValIdx → Aiur.Bytecode.ValIdx → Aiur.Bytecode.Op) x with + | Aiur.AIR.Byte2Kind.xor => Aiur.Bytecode.Op.u8Xor + | Aiur.AIR.Byte2Kind.add => Aiur.Bytecode.Op.u8Add + | Aiur.AIR.Byte2Kind.sub => Aiur.Bytecode.Op.u8Sub + | Aiur.AIR.Byte2Kind.and => Aiur.Bytecode.Op.u8And + | Aiur.AIR.Byte2Kind.or => Aiur.Bytecode.Op.u8Or + | Aiur.AIR.Byte2Kind.lessThan => Aiur.Bytecode.Op.u8LessThan + | Aiur.AIR.Byte2Kind.range => Aiur.Bytecode.Op.u8RangeCheck + | Aiur.AIR.Byte2Kind.mul => Aiur.Bytecode.Op.u8Mul + | Aiur.AIR.Byte2Kind.split7 => Aiur.Bytecode.Op.u8XorSplit7 + | Aiur.AIR.Byte2Kind.split4 => Aiur.Bytecode.Op.u8XorSplit4 +PREMISE Aiur.AIR.Byte2Kind.extendOutputs +Aiur.AIR.Byte2Kind → Aiur.G → Aiur.G → Array Aiur.G → Array Aiur.G +DEFINITION +fun kind x y outputs => + match kind with + | Aiur.AIR.Byte2Kind.add => outputs.push ((x + y - outputs[0]?.getD 0) * Aiur.AIR.inverse256) + | Aiur.AIR.Byte2Kind.sub => outputs.push ((outputs[0]?.getD 0 + y - x) * Aiur.AIR.inverse256) + | x => outputs +PREMISE Aiur.AIR.byte1Preprocessed +Fin 256 → Array Aiur.G +DEFINITION +fun row => + #[Aiur.G.ofNat ↑row] ++ Aiur.AIR.byte1Outputs Aiur.AIR.Byte1Kind.bits row ++ + Aiur.AIR.byte1Outputs Aiur.AIR.Byte1Kind.shiftLeft row ++ + Aiur.AIR.byte1Outputs Aiur.AIR.Byte1Kind.shiftRight row +PREMISE Aiur.AIR.byte2Preprocessed +Fin 65536 → Array Aiur.G +DEFINITION +fun row => + have inputs := Aiur.AIR.byteRangeMessage row; + #[inputs.fst, inputs.snd] ++ Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.xor row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.add row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.sub row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.and row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.or row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.lessThan row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.mul row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.split7 row ++ + Aiur.AIR.byte2Outputs Aiur.AIR.Byte2Kind.split4 row +PREMISE Aiur.AIR.padMessage +Nat → List Aiur.G → List Aiur.G +DEFINITION +fun width message => List.ofFn fun i => message[↑i]?.getD 0 +PREMISE Aiur.AIR.HasMessageShape +(Aiur.G → Aiur.G → Nat) → List Aiur.G → Prop +DEFINITION +fun widths message => 2 ≤ message.length ∧ message.length = widths (message[0]?.getD 0) (message[1]?.getD 0) +PREMISE Aiur.AIR.mapProviders +{α : Type u_1} → {β : Type u_2} → (α → β) → List (Aiur.AIR.Provider α) → List (Aiur.AIR.Provider β) +DEFINITION +fun {α} {β} encode providers => List.map (fun provider => (encode provider.fst, provider.snd)) providers +PREMISE Aiur.AIR.PaddedLookupBalance +Nat → List (List Aiur.G) → List (Aiur.AIR.Provider (List Aiur.G)) → Prop +DEFINITION +fun width queries providers => + Aiur.AIR.ExactLookupBalance (List.map (Aiur.AIR.padMessage width) queries) + (Aiur.AIR.mapProviders (Aiur.AIR.padMessage width) providers) +PREMISE Aiur.AIR.functionMessage +Aiur.Bytecode.AIR.Call → List Aiur.G +DEFINITION +fun request => 0 :: Aiur.G.ofNat request.function :: (request.inputs.toList ++ request.outputs.toList ++ [request.rank]) +PREMISE Aiur.AIR.memoryMessage +Nat → Aiur.G → Array Aiur.G → List Aiur.G +DEFINITION +fun width pointer contents => 1 :: Aiur.G.ofNat width :: pointer :: contents.toList +PREMISE Aiur.AIR.Byte1Kind.outputSize +Aiur.AIR.Byte1Kind → Nat +DEFINITION +fun x => + match x with + | Aiur.AIR.Byte1Kind.bits => 8 + | Aiur.AIR.Byte1Kind.shiftLeft => 1 + | Aiur.AIR.Byte1Kind.shiftRight => 1 +PREMISE Aiur.AIR.Byte2Kind.outputSize +Aiur.AIR.Byte2Kind → Nat +DEFINITION +fun x => + match x with + | Aiur.AIR.Byte2Kind.range => 0 + | Aiur.AIR.Byte2Kind.mul => 2 + | Aiur.AIR.Byte2Kind.split7 => 2 + | Aiur.AIR.Byte2Kind.split4 => 2 + | x => 1 +PREMISE Aiur.AIR.lookupMessageWidth +Aiur.AIR.FunctionArities → Aiur.G → Aiur.G → Nat +DEFINITION +fun arities channel key => + match channel.n with + | 0 => 3 + (arities key.n).fst + (arities key.n).snd + | 1 => 3 + key.n + | 2 => 10 + | 3 => 3 + | 4 => 3 + | 5 => 4 + | 6 => 4 + | 7 => 4 + | 8 => 4 + | 9 => 4 + | 10 => 4 + | 11 => 3 + | 12 => 5 + | 13 => 5 + | 14 => 5 + | x => 0 +PREMISE Aiur.AIR.FunctionMessageValid +Aiur.AIR.FunctionArities → Aiur.Bytecode.AIR.Call → Prop +DEFINITION +fun arities request => + request.function < Aiur.gSize.toNat ∧ + request.inputs.size = (arities request.function).fst ∧ request.outputs.size = (arities request.function).snd +PREMISE Aiur.Bytecode.Ctrl.returnsHaveSize +Nat → Aiur.Bytecode.Ctrl → Bool +DEFINITION +fun size a => Aiur.Bytecode.Ctrl.returnsHaveSize._mutual size (PSum.inl a) +PREMISE Aiur.Bytecode.Block.returnsHaveSize +Nat → Aiur.Bytecode.Block → Bool +DEFINITION +fun size block => Aiur.Bytecode.Ctrl.returnsHaveSize._mutual size (PSum.inr block) +PREMISE Aiur.Bytecode.Op.lookupShape +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Op → Bool +DEFINITION +fun program x => + match x with + | Aiur.Bytecode.Op.call index inputs outputs false => + match program.functions[index]? with + | none => false + | some callee => + callee.constrained && + (callee.layout.inputSize == inputs.size && Aiur.Bytecode.Block.returnsHaveSize outputs callee.body) + | Aiur.Bytecode.Op.store values => decide (values.size < Aiur.gSize.toNat) + | Aiur.Bytecode.Op.load size a => decide (size < Aiur.gSize.toNat) + | x => true +PREMISE Aiur.Bytecode.Ctrl.lookupShapes +Aiur.Bytecode.Toplevel → Option Nat → Aiur.Bytecode.Ctrl → Bool +DEFINITION +fun program yieldSize a => Aiur.Bytecode.Ctrl.lookupShapes._mutual program (PSum.inl ⟨yieldSize, a⟩) +PREMISE Aiur.Bytecode.Block.lookupShapes +Aiur.Bytecode.Toplevel → Option Nat → Aiur.Bytecode.Block → Bool +DEFINITION +fun program yieldSize block => Aiur.Bytecode.Ctrl.lookupShapes._mutual program (PSum.inr ⟨yieldSize, block⟩) +PREMISE Aiur.Bytecode.Toplevel.validateLookupShapes +Aiur.Bytecode.Toplevel → Bool +DEFINITION +fun program => + decide (program.functions.size < Aiur.gSize.toNat) && + ((program.memorySizes.all fun size => decide (size < Aiur.gSize.toNat)) && + program.functions.all fun function => + !function.constrained || Aiur.Bytecode.Block.lookupShapes program none function.body) +PREMISE Aiur.Bytecode.Toplevel.validClaimShape +Aiur.Bytecode.Toplevel → Array Aiur.G → Bool +DEFINITION +fun program claim => + match claim.toList with + | channel :: index :: arguments => + channel == 0 && + match program.functions[index.n]? with + | none => false + | some function => + function.entry && function.constrained && + (decide (function.layout.inputSize ≤ arguments.length) && + Aiur.Bytecode.Block.returnsHaveSize (arguments.length - function.layout.inputSize) function.body) + | x => false +PREMISE Aiur.Bytecode.AIR.Call.LookupShape +Aiur.Bytecode.Toplevel → Aiur.Bytecode.AIR.Call → Prop +DEFINITION +fun program request => + ∃ callee, + program.functions[request.function]? = some callee ∧ + callee.constrained = true ∧ + callee.layout.inputSize = request.inputs.size ∧ + Aiur.Bytecode.Block.returnsHaveSize request.outputs.size callee.body = true +PREMISE Aiur.Bytecode.AIR.Outcome.ReturnSize +Aiur.Bytecode.AIR.Outcome → Nat → Prop +DEFINITION +fun outcome size => + match outcome with + | Aiur.Bytecode.AIR.Outcome.returned outputs => outputs.size = size + | Aiur.Bytecode.AIR.Outcome.yielded a => True +PREMISE Aiur.AIR.LookupTables.mk +List Aiur.AIR.FunctionRow → + List Nat → + (Nat → Array Aiur.AIR.MemoryRow) → + (Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G) → (Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G) → Aiur.AIR.LookupTables +PREMISE Aiur.AIR.LookupTables.providers +Aiur.AIR.LookupTables → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun tables => + Aiur.AIR.mapProviders Aiur.AIR.functionMessage (Aiur.AIR.functionProviders tables.functions) ++ + List.flatMap + (fun width => + Aiur.AIR.mapProviders (fun request => Aiur.AIR.memoryMessage width request.fst request.snd) + (Aiur.AIR.memoryProviders (tables.memory width))) + tables.memoryWidths ++ + Aiur.AIR.byte1Providers tables.byte1 ++ + Aiur.AIR.byte2Providers tables.byte2 +PREMISE Aiur.AIR.GlobalLookups.mk +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.PaddedLookupBalance width queries tables.providers → + queries.length < Aiur.gSize.toNat → + (∀ (query : List Aiur.G), query ∈ queries → query.length ≤ width) → Aiur.AIR.GlobalLookups tables width queries +PREMISE Aiur.AIR.rangeMessage +Aiur.G × Aiur.G → List Aiur.G +DEFINITION +fun pair => Aiur.AIR.byte2Request Aiur.AIR.Byte2Kind.range pair.fst pair.snd #[] +PREMISE Aiur.lookupSlotSum +List Nat → List Bool → List Nat → Option Nat +DEFINITION +fun x x_1 x_2 => List.brecOn (motive := fun x => List Bool → List Nat → Option Nat) x Aiur.lookupSlotSum._f x_1 x_2 +PREMISE Aiur.lookupQueryBoundAux +List Nat → List Bool → List Nat → Nat → Option Nat +DEFINITION +fun x x_1 x_2 x_3 => + List.brecOn (motive := fun x => List Bool → List Nat → Nat → Option Nat) x Aiur.lookupQueryBoundAux._f x_1 x_2 x_3 +PREMISE Aiur.lookupQueryBound +List Nat → List Bool → List Nat → Option Nat +DEFINITION +fun slots active degrees => if active.any id = true then Aiur.lookupQueryBoundAux slots active degrees 1 else none +PREMISE Aiur.AIR.addMessages +List Aiur.G → List Aiur.G → List Aiur.G +DEFINITION +fun x x_1 => List.brecOn (motive := fun x => List Aiur.G → List Aiur.G) x Aiur.AIR.addMessages._f x_1 +PREMISE Aiur.AIR.scaleMessage +Aiur.G → List Aiur.G → List Aiur.G +DEFINITION +fun selector message => List.map (fun x => selector * x) message +PREMISE Aiur.AIR.weightedMessage +List (Aiur.G × List Aiur.G) → List Aiur.G +DEFINITION +fun parts => + List.foldl (fun combined part => Aiur.AIR.addMessages combined (Aiur.AIR.scaleMessage part.fst part.snd)) [] parts +PREMISE Aiur.AIR.gateMessage +Bool → Aiur.G → List Aiur.G → List Aiur.G +DEFINITION +fun branchless selector message => if branchless = true then message else Aiur.AIR.scaleMessage selector message +PREMISE Aiur.AIR.slotMessage +Bool → List (Aiur.G × List Aiur.G) → List Aiur.G +DEFINITION +fun branchless parts => + List.foldl (fun combined part => Aiur.AIR.addMessages combined (Aiur.AIR.gateMessage branchless part.fst part.snd)) [] + parts +PREMISE Aiur.AIR.SelectorFlow.mk +Aiur.G → List Aiur.G → List Aiur.G → List Aiur.G → Aiur.AIR.SelectorFlow +PREMISE Aiur.AIR.SelectorFlow.guard +Aiur.AIR.SelectorFlow → Aiur.AIR.SelectorFlow +DEFINITION +fun flow => + { entry := flow.entry, returns := flow.returns, yields := flow.yields, + equations := Aiur.AIR.oneSubBooleanConstraint flow.entry :: flow.equations } +PREMISE Aiur.AIR.SelectorFlow.join +List Aiur.AIR.SelectorFlow → Aiur.AIR.SelectorFlow +DEFINITION +fun flows => + { entry := Aiur.AIR.selectorSum (List.map (fun x => x.entry) flows), + returns := List.flatMap (fun x => x.returns) flows, yields := List.flatMap (fun x => x.yields) flows, + equations := List.flatMap (fun x => x.equations) flows } +PREMISE Aiur.AIR.SelectorFlow.continue +Aiur.AIR.SelectorFlow → Aiur.AIR.SelectorFlow → Aiur.AIR.SelectorFlow +DEFINITION +fun branches continuation => + { entry := branches.entry, returns := branches.returns ++ continuation.returns, yields := continuation.yields, + equations := + branches.equations ++ (continuation.entry - Aiur.AIR.selectorSum branches.yields) :: continuation.equations } +PREMISE Aiur.AIR.SelectorFlow.Satisfied +Aiur.AIR.SelectorFlow → Prop +DEFINITION +fun flow => ∀ (equation : Aiur.G), equation ∈ flow.equations → equation = 0 +PREMISE Aiur.AIR.SelectorFlow.Sound.mk +∀ {flow : Aiur.AIR.SelectorFlow}, + flow.entry = Aiur.AIR.selectorSum flow.returns + Aiur.AIR.selectorSum flow.yields → + (∀ (value : Aiur.G), value ∈ flow.returns → Aiur.AIR.booleanConstraint value = 0) → + (∀ (value : Aiur.G), value ∈ flow.yields → Aiur.AIR.booleanConstraint value = 0) → flow.Sound +PREMISE Aiur.Bytecode.Ctrl.selectorFlow +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Ctrl → Aiur.AIR.SelectorFlow +DEFINITION +fun selector a => Aiur.Bytecode.Ctrl.selectorFlow._mutual selector (PSum.inl a) +PREMISE Aiur.Bytecode.Block.selectorFlow +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Block → Aiur.AIR.SelectorFlow +DEFINITION +fun selector block => Aiur.Bytecode.Ctrl.selectorFlow._mutual selector (PSum.inr block) +PREMISE Aiur.Bytecode.branchSelectorFlows +(Aiur.Bytecode.SelIdx → Aiur.G) → + Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → List Aiur.AIR.SelectorFlow +DEFINITION +fun selector branches fallback => + List.map (fun pair => Aiur.Bytecode.Block.selectorFlow selector pair.snd) branches.toList ++ + List.map (fun block => Aiur.Bytecode.Block.selectorFlow selector block) fallback.toList +PREMISE Aiur.Bytecode.Ctrl.returnGates +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.G → Aiur.Bytecode.Ctrl → List Aiur.G +DEFINITION +fun selector incoming a => Aiur.Bytecode.Ctrl.returnGates._mutual selector (PSum.inl ⟨incoming, a⟩) +PREMISE Aiur.Bytecode.Block.returnGates +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.G → Aiur.Bytecode.Block → List Aiur.G +DEFINITION +fun selector incoming block => Aiur.Bytecode.Ctrl.returnGates._mutual selector (PSum.inr ⟨incoming, block⟩) +PREMISE Aiur.Bytecode.branchReturnGates +(Aiur.Bytecode.SelIdx → Aiur.G) → Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → List Aiur.G +DEFINITION +fun selector branches fallback => + List.flatMap + (fun pair => + Aiur.Bytecode.Block.returnGates selector (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry pair.snd) + branches.toList ++ + List.flatMap + (fun block => + Aiur.Bytecode.Block.returnGates selector (Aiur.Bytecode.Block.selectorFlow selector block).entry block) + fallback.toList +PREMISE Aiur.AIR.RowValue.mk +Aiur.G → Nat → Bool → Aiur.AIR.RowValue +PREMISE Aiur.AIR.RowValue.variable +Aiur.G → Aiur.AIR.RowValue +DEFINITION +fun value => { value := value, degree := 1, constant := false } +PREMISE Aiur.AIR.RowValue.konst +Aiur.G → Aiur.AIR.RowValue +DEFINITION +fun value => { value := value, degree := 0, constant := true } +PREMISE Aiur.AIR.rowValues +Array Aiur.AIR.RowValue → Array Aiur.G +DEFINITION +fun values => Array.map Aiur.AIR.RowValue.value values +PREMISE Aiur.AIR.RowValue.add +Aiur.AIR.RowValue → Aiur.AIR.RowValue → Aiur.AIR.RowValue +DEFINITION +fun left right => + { value := left.value + right.value, degree := max left.degree right.degree, + constant := left.constant && right.constant } +PREMISE Aiur.AIR.RowValue.sub +Aiur.AIR.RowValue → Aiur.AIR.RowValue → Aiur.AIR.RowValue +DEFINITION +fun left right => + { value := left.value - right.value, degree := max left.degree right.degree, + constant := left.constant && right.constant } +PREMISE Aiur.AIR.RowValue.mul +Aiur.AIR.RowValue → Aiur.AIR.RowValue → Aiur.AIR.RowValue +DEFINITION +fun left right => + { value := left.value * right.value, degree := left.degree + right.degree, + constant := + left.constant && right.constant || left.constant && left.value == 0 || right.constant && right.value == 0 } +PREMISE Aiur.AIR.rowAdvice +(Nat → Aiur.G) → Nat → Nat → Array Aiur.AIR.RowValue +DEFINITION +fun row start count => Array.ofFn fun index => Aiur.AIR.RowValue.variable (row (start + ↑index)) +PREMISE Aiur.AIR.RowValue.pack +Array Aiur.AIR.RowValue → Aiur.AIR.RowValue +DEFINITION +fun values => + { value := Aiur.Bytecode.AIR.packWord (Aiur.AIR.rowValues values), + degree := List.foldl (fun degree value => max degree value.degree) 0 values.toList, + constant := values.all fun x => x.constant } +PREMISE Aiur.AIR.readRowWord +Array Aiur.AIR.RowValue → Array Aiur.Bytecode.ValIdx → Option Aiur.AIR.RowValue +DEFINITION +fun values indices => do + let word ← Aiur.Bytecode.AIR.readWord (Aiur.AIR.rowValues values) indices + have bytes : Array Aiur.AIR.RowValue := + Array.map (fun index => values[index]?.getD (Aiur.AIR.RowValue.konst 0)) indices + pure + (have __src := Aiur.AIR.RowValue.pack bytes; + { value := word, degree := __src.degree, constant := __src.constant }) +PREMISE Aiur.AIR.OpEmission.mk +Array Aiur.AIR.RowValue → + Nat → List Aiur.G → List (List Aiur.G) → List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → Aiur.AIR.OpEmission +PREMISE Aiur.AIR.emitAdvice +(Nat → Aiur.G) → Nat → Aiur.AIR.OpEmission +DEFINITION +fun row count => { outputs := Aiur.AIR.rowAdvice row 0 count, used := count } +PREMISE Aiur.AIR.emitByte1 +(Nat → Aiur.G) → Aiur.AIR.Byte1Kind → Aiur.Bytecode.ValIdx → Array Aiur.AIR.RowValue → Option Aiur.AIR.OpEmission +DEFINITION +fun row kind index values => do + let input ← values[index]? + have outputs : Array Aiur.AIR.RowValue := Aiur.AIR.rowAdvice row 0 kind.outputSize + pure + { outputs := outputs, used := kind.outputSize, + queries := [Aiur.AIR.byte1Request kind input.value (Aiur.AIR.rowValues outputs)] } +PREMISE Aiur.AIR.Byte2Kind.extendRowOutputs +Aiur.AIR.Byte2Kind → Aiur.AIR.RowValue → Aiur.AIR.RowValue → Array Aiur.AIR.RowValue → Array Aiur.AIR.RowValue +DEFINITION +fun kind left right outputs => + have low := (Aiur.AIR.rowValues outputs)[0]?.getD 0; + have degree := max (max left.degree right.degree) 1; + match kind with + | Aiur.AIR.Byte2Kind.add => + outputs.push + { value := (left.value + right.value - low) * Aiur.AIR.inverse256, degree := degree, constant := false } + | Aiur.AIR.Byte2Kind.sub => + outputs.push + { value := (low + right.value - left.value) * Aiur.AIR.inverse256, degree := degree, constant := false } + | x => outputs +PREMISE Aiur.AIR.emitByte2 +(Nat → Aiur.G) → + Aiur.AIR.Byte2Kind → + Aiur.Bytecode.ValIdx → Aiur.Bytecode.ValIdx → Array Aiur.AIR.RowValue → Option Aiur.AIR.OpEmission +DEFINITION +fun row kind left right values => do + let x ← values[left]? + let y ← values[right]? + have outputs : Array Aiur.AIR.RowValue := Aiur.AIR.rowAdvice row 0 kind.outputSize + pure + { outputs := kind.extendRowOutputs x y outputs, used := kind.outputSize, + queries := [Aiur.AIR.byte2Request kind x.value y.value (Aiur.AIR.rowValues outputs)] } +PREMISE Aiur.AIR.range4Queries +(Fin 4 → Aiur.G) → List (List Aiur.G) +DEFINITION +fun bytes => [Aiur.AIR.rangeMessage (bytes 0, bytes 1), Aiur.AIR.rangeMessage (bytes 2, bytes 3)] +PREMISE Aiur.AIR.emitU32LessThan +(Nat → Aiur.G) → + Aiur.G → Aiur.Bytecode.ValIdx → Aiur.Bytecode.ValIdx → Array Aiur.AIR.RowValue → Option Aiur.AIR.OpEmission +DEFINITION +fun row selector left right values => do + let a ← values[left]? + let b ← values[right]? + have x : Fin 4 → Aiur.G := fun index => row ↑index + have y : Fin 4 → Aiur.G := fun index => row (4 + ↑index) + have z : Fin 4 → Aiur.G := fun index => row (8 + ↑index) + pure + { outputs := #[{ value := 1 - Aiur.AIR.u32Carries x y z 4, degree := 1, constant := false }], used := 12, + equations := + selector * (a.value - Aiur.AIR.pack4 x) :: + selector * (b.value - Aiur.AIR.pack4 z) :: + List.ofFn fun index => selector * Aiur.AIR.booleanConstraint (Aiur.AIR.u32Carries x y z index.succ), + queries := Aiur.AIR.range4Queries x ++ Aiur.AIR.range4Queries y ++ Aiur.AIR.range4Queries z } +PREMISE Aiur.AIR.emitU32Add +(Nat → Aiur.G) → + Array Aiur.Bytecode.ValIdx → + Array Aiur.Bytecode.ValIdx → + Option (Array Aiur.Bytecode.ValIdx) → Array Aiur.AIR.RowValue → Option Aiur.AIR.OpEmission +DEFINITION +fun row left right third values => do + let x ← Aiur.AIR.readRowWord values left + let y ← Aiur.AIR.readRowWord values right + have __do_jp : Aiur.AIR.RowValue → Option Aiur.AIR.OpEmission := fun sum => + have bytes := Aiur.AIR.rowAdvice row 0 4; + have packed := Aiur.AIR.RowValue.pack bytes; + pure + { + outputs := + bytes.push + { value := (sum.value - packed.value) * 18446744065119617026, degree := max sum.degree packed.degree, + constant := false }, + used := 4 } + match third with + | none => do + let sum ← some (x.add y) + __do_jp sum + | some indices => do + let sum ← Option.map (fun z => (x.add y).add z) (Aiur.AIR.readRowWord values indices) + __do_jp sum +PREMISE Aiur.AIR.emitOp +(Nat → Aiur.G) → Aiur.G → Aiur.G → Aiur.Bytecode.Op → Array Aiur.AIR.RowValue → Option Aiur.AIR.OpEmission +DEFINITION +fun row selector rank op values => + match op with + | Aiur.Bytecode.Op.const value => some { outputs := #[Aiur.AIR.RowValue.konst value] } + | Aiur.Bytecode.Op.add a b => do + let __do_lift ← values[a]? + let __do_lift_1 ← values[b]? + pure { outputs := #[__do_lift.add __do_lift_1] } + | Aiur.Bytecode.Op.sub a b => do + let __do_lift ← values[a]? + let __do_lift_1 ← values[b]? + pure { outputs := #[__do_lift.sub __do_lift_1] } + | Aiur.Bytecode.Op.mul a b => do + let x ← values[a]? + let y ← values[b]? + have product : Aiur.AIR.RowValue := x.mul y + if product.degree < 2 then pure { outputs := #[product] } + else + pure + { outputs := #[Aiur.AIR.RowValue.variable (row 0)], used := 1, + equations := [selector * (row 0 - product.value)] } + | Aiur.Bytecode.Op.eqZero a => do + let input ← values[a]? + if (input.constant && input.degree == 0) = true then + pure { outputs := #[Aiur.AIR.RowValue.konst input.value.eqZero] } + else + pure + { outputs := #[Aiur.AIR.RowValue.variable (row 1)], used := 2, + equations := [selector * input.value * row 1, selector * (input.value * row 0 + row 1 - 1)] } + | Aiur.Bytecode.Op.call function indices size unconstrained => + if unconstrained = true then some (Aiur.AIR.emitAdvice row size) + else do + let inputs ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) indices + have outputs : Array Aiur.AIR.RowValue := Aiur.AIR.rowAdvice row 0 size + have gap : Fin 6 → Aiur.G := fun index => row (size + ↑index) + have request : Aiur.Bytecode.AIR.Call := + { function := function, inputs := inputs, outputs := Aiur.AIR.rowValues outputs, + rank := rank + 1 + Aiur.AIR.packRank gap } + pure + { outputs := outputs, used := size + 6, + queries := + Aiur.AIR.functionMessage request :: List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries gap), + calls := [(request, gap)] } + | Aiur.Bytecode.Op.store indices => do + let contents ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) indices + pure + { outputs := #[Aiur.AIR.RowValue.variable (row 0)], used := 1, + queries := [Aiur.AIR.memoryMessage indices.size (row 0) contents] } + | Aiur.Bytecode.Op.load size index => do + let pointer ← values[index]? + have outputs : Array Aiur.AIR.RowValue := Aiur.AIR.rowAdvice row 0 size + pure + { outputs := outputs, used := size, + queries := [Aiur.AIR.memoryMessage size pointer.value (Aiur.AIR.rowValues outputs)] } + | Aiur.Bytecode.Op.assertEq xs ys a => + if xs.size ≠ ys.size then none + else do + let left ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) xs + let right ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) ys + pure { equations := List.ofFn fun i => selector * (left[i] - right[↑i]?.getD 0) } + | Aiur.Bytecode.Op.ioGetInfo a a_1 => some (Aiur.AIR.emitAdvice row 2) + | Aiur.Bytecode.Op.ioRead a a_1 size => some (Aiur.AIR.emitAdvice row size) + | Aiur.Bytecode.Op.ioSetInfo a a_1 a_2 a_3 => some { } + | Aiur.Bytecode.Op.ioWrite a a_1 => some { } + | Aiur.Bytecode.Op.debug a a_1 => some { } + | Aiur.Bytecode.Op.u8BitDecomposition index => Aiur.AIR.emitByte1 row Aiur.AIR.Byte1Kind.bits index values + | Aiur.Bytecode.Op.u8ShiftLeft index => Aiur.AIR.emitByte1 row Aiur.AIR.Byte1Kind.shiftLeft index values + | Aiur.Bytecode.Op.u8ShiftRight index => Aiur.AIR.emitByte1 row Aiur.AIR.Byte1Kind.shiftRight index values + | Aiur.Bytecode.Op.u8Xor a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.xor a b values + | Aiur.Bytecode.Op.u8Add a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.add a b values + | Aiur.Bytecode.Op.u8Sub a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.sub a b values + | Aiur.Bytecode.Op.u8And a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.and a b values + | Aiur.Bytecode.Op.u8Or a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.or a b values + | Aiur.Bytecode.Op.u8LessThan a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.lessThan a b values + | Aiur.Bytecode.Op.u8RangeCheck a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.range a b values + | Aiur.Bytecode.Op.u8Mul a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.mul a b values + | Aiur.Bytecode.Op.u8XorSplit7 a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.split7 a b values + | Aiur.Bytecode.Op.u8XorSplit4 a b => Aiur.AIR.emitByte2 row Aiur.AIR.Byte2Kind.split4 a b values + | Aiur.Bytecode.Op.u32LessThan a b => Aiur.AIR.emitU32LessThan row selector a b values + | Aiur.Bytecode.Op.unconstrainedBigUintDivMod a a_1 => some (Aiur.AIR.emitAdvice row 2) + | Aiur.Bytecode.Op.unconstrainedGToBytes a => some (Aiur.AIR.emitAdvice row 8) + | Aiur.Bytecode.Op.unconstrainedGInverse a => some (Aiur.AIR.emitAdvice row 1) + | Aiur.Bytecode.Op.unconstrainedU32Add a b => Aiur.AIR.emitU32Add row a b none values + | Aiur.Bytecode.Op.unconstrainedU32Add3 a b c => Aiur.AIR.emitU32Add row a b (some c) values + | Aiur.Bytecode.Op.u32ToField indices => do + let __do_lift ← Aiur.AIR.readRowWord values indices + pure { outputs := #[__do_lift] } +PREMISE Aiur.AIR.OpsEmission.mk +Array Aiur.AIR.RowValue → + Nat → List Aiur.G → List (List Aiur.G) → List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → Aiur.AIR.OpsEmission +PREMISE Aiur.AIR.emitOps +(Nat → Aiur.G) → Aiur.G → Aiur.G → List Aiur.Bytecode.Op → Array Aiur.AIR.RowValue → Nat → Option Aiur.AIR.OpsEmission +DEFINITION +fun row selector rank x x_1 x_2 => + List.brecOn (motive := fun x => Array Aiur.AIR.RowValue → Nat → Option Aiur.AIR.OpsEmission) x + (Aiur.AIR.emitOps._f row selector rank) x_1 x_2 +PREMISE Aiur.AIR.CallsEmitted +Aiur.G → Aiur.G → List Aiur.G → List (List Aiur.G) → List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → Prop +DEFINITION +fun rank selector equations queries calls => + ∀ (edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)), + edge ∈ calls → + Aiur.AIR.functionMessage edge.fst ∈ queries ∧ + List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries edge.snd) ⊆ queries ∧ + Aiur.AIR.EquationAvailable equations + (selector * Aiur.AIR.callOrderConstraint rank edge.fst.rank (Aiur.AIR.packRank edge.snd)) +PREMISE Aiur.Bytecode.MatchPolynomials.mk +∀ {selector : Aiur.Bytecode.SelIdx → Aiur.G} {scrutinee : Aiur.G} {branches : Array (Aiur.G × Aiur.Bytecode.Block)} + {fallback : Option Aiur.Bytecode.Block}, + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry * (scrutinee - pair.fst) = 0) → + (∀ (block : Aiur.Bytecode.Block), + fallback = some block → + ∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → + ∃ inverse, + (Aiur.Bytecode.Block.selectorFlow selector block).entry * ((scrutinee - pair.fst) * inverse - 1) = 0) → + Aiur.Bytecode.MatchPolynomials selector scrutinee branches fallback +PREMISE Aiur.AIR.RowContext.mk +Aiur.Bytecode.FunIdx → Nat → Aiur.G → Aiur.AIR.RowContext +PREMISE Aiur.AIR.QueryPart.mk +Nat → Aiur.G → List Aiur.G → Aiur.AIR.QueryPart +PREMISE Aiur.AIR.queryParts +Nat → Aiur.G → List (List Aiur.G) → List Aiur.AIR.QueryPart +DEFINITION +fun slot selector queries => + List.mapIdx (fun index message => { slot := slot + index, selector := selector, message := message }) queries +PREMISE Aiur.AIR.BlockEmission.mk +Array Aiur.AIR.RowValue → + Nat → + Nat → + List Aiur.G → + List Aiur.AIR.QueryPart → + List (Aiur.G × Aiur.Bytecode.AIR.Call) → + List (Aiur.G × Array Aiur.AIR.RowValue) → + List (Aiur.G × Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → Aiur.AIR.BlockEmission +PREMISE Aiur.AIR.BlockEmission.prefix +List Aiur.G → Aiur.AIR.BlockEmission → Aiur.AIR.BlockEmission +DEFINITION +fun equations emission => + { values := emission.values, column := emission.column, lookup := emission.lookup, + equations := equations ++ emission.equations, queries := emission.queries, returns := emission.returns, + yields := emission.yields, calls := emission.calls } +PREMISE Aiur.AIR.BlockEmission.afterOps +Aiur.G → Nat → Aiur.AIR.OpsEmission → Aiur.AIR.BlockEmission → Aiur.AIR.BlockEmission +DEFINITION +fun incoming lookup ops control => + { values := control.values, column := control.column, lookup := control.lookup, + equations := ops.equations ++ control.equations, + queries := Aiur.AIR.queryParts lookup incoming ops.queries ++ control.queries, returns := control.returns, + yields := control.yields, calls := List.map (fun x => (incoming, x)) ops.calls ++ control.calls } +PREMISE Aiur.AIR.joinBlockEmissions +Array Aiur.AIR.RowValue → Nat → Nat → List Aiur.AIR.BlockEmission → Aiur.AIR.BlockEmission +DEFINITION +fun values column lookup emissions => + { values := values, column := List.foldl (fun column emission => max column emission.column) column emissions, + lookup := List.foldl (fun lookup emission => max lookup emission.lookup) lookup emissions, + equations := List.flatMap (fun x => x.equations) emissions, queries := List.flatMap (fun x => x.queries) emissions, + returns := List.flatMap (fun x => x.returns) emissions, yields := List.flatMap (fun x => x.yields) emissions, + calls := List.flatMap (fun x => x.calls) emissions } +PREMISE Aiur.AIR.mergeEquations +(Nat → Aiur.G) → Aiur.G → Nat → Nat → List (Aiur.G × Array Aiur.AIR.RowValue) → List Aiur.G +DEFINITION +fun row parent column size yields => + List.map + (fun index => + parent * + (row (column + index) - + Aiur.AIR.selectorSum (List.map (fun part => part.fst * (Aiur.AIR.rowValues part.snd)[index]?.getD 0) yields))) + (List.range size) +PREMISE Aiur.AIR.BlockEmission.continued +Aiur.AIR.BlockEmission → List Aiur.G → Aiur.AIR.BlockEmission → Aiur.AIR.BlockEmission +DEFINITION +fun branches equations continuation => + { values := continuation.values, column := continuation.column, lookup := continuation.lookup, + equations := branches.equations ++ equations ++ continuation.equations, + queries := branches.queries ++ continuation.queries, returns := branches.returns ++ continuation.returns, + yields := continuation.yields, calls := branches.calls ++ continuation.calls } +PREMISE Aiur.Bytecode.Ctrl.emitRow +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.Bytecode.Ctrl → Option Aiur.AIR.BlockEmission +DEFINITION +fun row selector context incoming values column lookup a => + Aiur.Bytecode.Ctrl.emitRow._mutual row selector context (PSum.inl ⟨incoming, ⟨values, ⟨column, ⟨lookup, a⟩⟩⟩⟩) +PREMISE Aiur.Bytecode.Block.emitRow +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.Bytecode.Block → Option Aiur.AIR.BlockEmission +DEFINITION +fun row selector context incoming values column lookup block => + Aiur.Bytecode.Ctrl.emitRow._mutual row selector context (PSum.inr ⟨incoming, ⟨values, ⟨column, ⟨lookup, block⟩⟩⟩⟩) +PREMISE Aiur.AIR.SelectorFlow.unguard +Aiur.AIR.SelectorFlow → Aiur.AIR.SelectorFlow +DEFINITION +fun flow => { entry := flow.entry, returns := flow.returns, yields := flow.yields, equations := flow.equations.tail } +PREMISE Aiur.AIR.EmissionProjection.mk +∀ {flow : Aiur.AIR.SelectorFlow} {gates : List Aiur.G} {emission : Aiur.AIR.BlockEmission}, + List.map Prod.fst emission.returns = gates → + List.map Prod.fst emission.yields = flow.yields → + flow.equations ⊆ emission.equations → Aiur.AIR.EmissionProjection flow gates emission +PREMISE Aiur.Bytecode.caseRow +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.G × Aiur.Bytecode.Block → Option Aiur.AIR.BlockEmission +DEFINITION +fun row selector context matched values column lookup pair => + have entry := (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry; + do + let emission ← Aiur.Bytecode.Block.emitRow row selector context entry values column lookup pair.snd + pure (Aiur.AIR.BlockEmission.prefix [entry * (matched - pair.fst)] emission) +PREMISE Aiur.Bytecode.defaultRow +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → + Array Aiur.AIR.RowValue → + Nat → + Nat → + Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → Option (List Aiur.AIR.BlockEmission) +DEFINITION +fun row selector context matched values column lookup branches fallback => + match fallback with + | none => some [] + | some block => + have entry := (Aiur.Bytecode.Block.selectorFlow selector block).entry; + do + let emission ← Aiur.Bytecode.Block.emitRow row selector context entry values (column + branches.size) lookup block + pure + [Aiur.AIR.BlockEmission.prefix + (List.mapIdx (fun i pair => entry * ((matched - pair.fst) * row (column + i) - 1)) branches.toList) + emission] +PREMISE Aiur.Bytecode.branchRows +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → + Array Aiur.AIR.RowValue → + Nat → Nat → Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → Option Aiur.AIR.BlockEmission +DEFINITION +fun row selector context matched values column lookup branches fallback => do + let cases ← List.mapM (Aiur.Bytecode.caseRow row selector context matched values column lookup) branches.toList + let default ← Aiur.Bytecode.defaultRow row selector context matched values column lookup branches fallback + pure (Aiur.AIR.joinBlockEmissions values column lookup (cases ++ default)) +PREMISE Aiur.Bytecode.continueRow +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → + Array Aiur.AIR.RowValue → Nat → Aiur.Bytecode.Block → Aiur.AIR.BlockEmission → Option Aiur.AIR.BlockEmission +DEFINITION +fun row selector context incoming values size continuation joined => + if (joined.yields.all fun part => part.snd.size == size) = true then + have gate := Aiur.AIR.selectorSum (List.map Prod.fst joined.yields); + have merged := Aiur.AIR.rowAdvice row joined.column size; + have equations := + Aiur.AIR.mergeEquations row incoming joined.column size joined.yields ++ + [(Aiur.Bytecode.Block.selectorFlow selector continuation).entry - gate]; + do + let continued ← + Aiur.Bytecode.Block.emitRow row selector context gate (values ++ merged) (joined.column + size) joined.lookup + continuation + pure (joined.continued equations continued) + else none +PREMISE Aiur.AIR.BlockEmission.QueriesIn +Aiur.AIR.BlockEmission → List (List Aiur.G) → Prop +DEFINITION +fun emission queries => + ∀ (part : Aiur.AIR.QueryPart), part ∈ emission.queries → part.selector = 1 → part.message ∈ queries +PREMISE Aiur.AIR.BlockEmission.CallsAt +Aiur.AIR.BlockEmission → List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → Prop +DEFINITION +fun emission calls => ∀ (edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)), edge ∈ calls → (1, edge) ∈ emission.calls +PREMISE Aiur.AIR.BlockEmission.TerminalAt +Aiur.AIR.BlockEmission → Aiur.Bytecode.AIR.Outcome → Prop +DEFINITION +fun emission x => + match x with + | Aiur.Bytecode.AIR.Outcome.returned outputs => ∃ request, (1, request) ∈ emission.returns ∧ request.outputs = outputs + | Aiur.Bytecode.AIR.Outcome.yielded outputs => + ∃ yielded, (1, yielded) ∈ emission.yields ∧ Aiur.AIR.rowValues yielded = outputs +PREMISE Aiur.AIR.EmissionIncluded.mk +∀ {part whole : Aiur.AIR.BlockEmission}, + part.equations ⊆ whole.equations → + part.queries ⊆ whole.queries → + part.returns ⊆ whole.returns → + part.yields ⊆ whole.yields → part.calls ⊆ whole.calls → Aiur.AIR.EmissionIncluded part whole +PREMISE Aiur.Bytecode.Ctrl.rowBounds +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Ctrl → Prop +DEFINITION +fun selector a => Aiur.Bytecode.Ctrl.rowBounds._mutual selector (PSum.inl a) +PREMISE Aiur.Bytecode.Block.rowBounds +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Block → Prop +DEFINITION +fun selector block => Aiur.Bytecode.Ctrl.rowBounds._mutual selector (PSum.inr block) +PREMISE Aiur.AIR.BlockEmission.HasQuery +Aiur.AIR.BlockEmission → Aiur.G → List Aiur.G → Prop +DEFINITION +fun emission selector message => ∃ part, part ∈ emission.queries ∧ part.selector = selector ∧ part.message = message +PREMISE Aiur.AIR.BlockEmission.TracksCalls +Aiur.G → Aiur.AIR.BlockEmission → Prop +DEFINITION +fun rank emission => + ∀ (part : Aiur.G × Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)), + part ∈ emission.calls → + emission.HasQuery part.fst (Aiur.AIR.functionMessage part.snd.fst) ∧ + (∀ (message : List Aiur.G), + message ∈ List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries part.snd.snd) → + emission.HasQuery part.fst message) ∧ + Aiur.AIR.EquationAvailable emission.equations + (part.fst * Aiur.AIR.callOrderConstraint rank part.snd.fst.rank (Aiur.AIR.packRank part.snd.snd)) +PREMISE Aiur.AIR.RowInputs +Nat → Array Aiur.G → Array Aiur.AIR.RowValue → Prop +DEFINITION +fun size inputs values => Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) (Array.range size) = some inputs +PREMISE Aiur.AIR.InputPreservation.mk +∀ {context : Aiur.AIR.RowContext} {inputs : Array Aiur.G} {emission : Aiur.AIR.BlockEmission}, + Aiur.AIR.RowInputs context.inputSize inputs emission.values → + (∀ (part : Aiur.G × Aiur.Bytecode.AIR.Call), + part ∈ emission.returns → + part.snd.function = context.function ∧ part.snd.inputs = inputs ∧ part.snd.rank = context.rank) → + Aiur.AIR.InputPreservation context inputs emission +PREMISE Aiur.Bytecode.Function.emitRow +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.Bytecode.FunIdx → + Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.Bytecode.Function → Option Aiur.AIR.BlockEmission +DEFINITION +fun row selector functionIndex rank values column lookup function => + Aiur.Bytecode.Block.emitRow row selector + { function := functionIndex, inputSize := function.layout.inputSize, rank := rank } + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry values column lookup function.body +PREMISE Aiur.AIR.gateCount +Aiur.G → Nat +DEFINITION +fun gate => if gate = 1 then 1 else 0 +PREMISE Aiur.AIR.queryCount +List Aiur.AIR.QueryPart → Nat → Nat +DEFINITION +fun queries slot => (List.filter (fun query => query.slot == slot && query.selector == 1) queries).length +PREMISE Aiur.AIR.QuerySlots.mk +∀ {gate : Aiur.G} {start finish : Nat} {queries : List Aiur.AIR.QueryPart}, + start ≤ finish → + (∀ (query : Aiur.AIR.QueryPart), query ∈ queries → start ≤ query.slot ∧ query.slot < finish) → + (∀ (query : Aiur.AIR.QueryPart), query ∈ queries → Aiur.AIR.booleanConstraint query.selector = 0) → + (∀ (slot : Nat), Aiur.AIR.queryCount queries slot ≤ Aiur.AIR.gateCount gate) → + Aiur.AIR.QuerySlots gate start finish queries +PREMISE Aiur.AIR.activeQuerySlot +List Aiur.AIR.QueryPart → Nat → List Aiur.AIR.QueryPart +DEFINITION +fun queries slot => List.filter (fun query => query.slot == slot && query.selector == 1) queries +PREMISE Aiur.AIR.querySlotParts +List Aiur.AIR.QueryPart → Nat → List (Aiur.G × List Aiur.G) +DEFINITION +fun queries slot => + List.map (fun query => (query.selector, query.message)) (List.filter (fun query => query.slot == slot) queries) +PREMISE Aiur.AIR.querySlotMultiplicity +List Aiur.AIR.QueryPart → Nat → Aiur.G +DEFINITION +fun queries slot => Aiur.AIR.selectorSum (List.map Prod.fst (Aiur.AIR.querySlotParts queries slot)) +PREMISE Aiur.AIR.decodedQuery +List Aiur.AIR.QueryPart → Nat → Option (List Aiur.G) +DEFINITION +fun queries slot => Option.map (fun x => x.message) (Aiur.AIR.activeQuerySlot queries slot).head? +PREMISE Aiur.AIR.encodedQuery +Bool → List Aiur.AIR.QueryPart → Nat → Option (List Aiur.G) +DEFINITION +fun branchless queries slot => + if Aiur.AIR.querySlotMultiplicity queries slot = 1 then + some (Aiur.AIR.slotMessage branchless (Aiur.AIR.querySlotParts queries slot)) + else none +PREMISE Aiur.AIR.decodedQueries +List Aiur.AIR.QueryPart → Nat → List (List Aiur.G) +DEFINITION +fun queries limit => List.filterMap (Aiur.AIR.decodedQuery queries) (List.range limit) +PREMISE Aiur.AIR.encodedQueries +Bool → List Aiur.AIR.QueryPart → Nat → List (List Aiur.G) +DEFINITION +fun branchless queries limit => List.filterMap (Aiur.AIR.encodedQuery branchless queries) (List.range limit) +PREMISE Aiur.AIR.blockQueryPool +List Aiur.AIR.BlockEmission → List (List Aiur.G) +DEFINITION +fun emissions => List.flatMap (fun emission => Aiur.AIR.decodedQueries emission.queries emission.lookup) emissions +PREMISE Aiur.AIR.MemberEmission.mk +Aiur.Bytecode.FunIdx → Aiur.Bytecode.Function → Nat → Aiur.AIR.BlockEmission → Aiur.AIR.MemberEmission +PREMISE Aiur.AIR.MemberEmission.selector +(Nat → Aiur.G) → Aiur.AIR.MemberEmission → Aiur.Bytecode.SelIdx → Aiur.G +DEFINITION +fun row member index => row (member.selectorBase + index) +PREMISE Aiur.AIR.MemberEmission.entry +(Nat → Aiur.G) → Aiur.AIR.MemberEmission → Aiur.G +DEFINITION +fun row member => + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) member.function.body).entry +PREMISE Aiur.AIR.emitMember +(Nat → Aiur.G) → + Aiur.G → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → Aiur.Bytecode.FunIdx → Option Aiur.AIR.MemberEmission +DEFINITION +fun row rank column lookup selectorBase program functionIndex => do + let function ← program.functions[functionIndex]? + let body ← + Aiur.Bytecode.Function.emitRow row (fun index => row (selectorBase + index)) functionIndex rank + (Aiur.AIR.rowAdvice row 0 function.layout.inputSize) column lookup function + pure { functionIndex := functionIndex, function := function, selectorBase := selectorBase, body := body } +PREMISE Aiur.AIR.emitMembers +(Nat → Aiur.G) → + Aiur.G → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → List Aiur.Bytecode.FunIdx → Option (List Aiur.AIR.MemberEmission) +DEFINITION +fun row rank column lookup selectorBase program x => + List.brecOn (motive := fun x => Nat → Option (List Aiur.AIR.MemberEmission)) x + (Aiur.AIR.emitMembers._f row rank column lookup program) selectorBase +PREMISE Aiur.AIR.CircuitEmission.mk +List Aiur.AIR.MemberEmission → + Aiur.G → + Aiur.G → + (Fin 6 → Aiur.G) → + Nat → + Nat → + Nat → + Nat → + Bool → + List Aiur.G → + List Aiur.AIR.QueryPart → List (Aiur.G × Aiur.Bytecode.AIR.Call) → Aiur.AIR.CircuitEmission +PREMISE Aiur.AIR.circuitRankBytes +(Nat → Aiur.G) → Aiur.Bytecode.FunctionLayout → Fin 6 → Aiur.G +DEFINITION +fun row layout index => row (layout.inputSize + layout.selectors + 1 + ↑index) +PREMISE Aiur.AIR.circuitEmission +(Nat → Aiur.G) → Aiur.Bytecode.Circuit → List Aiur.AIR.MemberEmission → Aiur.AIR.CircuitEmission +DEFINITION +fun row circuit members => + have selector := Aiur.AIR.selectorSum (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) members); + have multiplicity := row (circuit.layout.inputSize + circuit.layout.selectors); + have rankBytes := Aiur.AIR.circuitRankBytes row circuit.layout; + { members := members, selector := selector, multiplicity := multiplicity, rankBytes := rankBytes, + width := circuit.layout.width, selectorStart := circuit.layout.inputSize, selectorCount := circuit.layout.selectors, + lookupCount := circuit.layout.lookups, + branchless := Aiur.Bytecode.circuitBranchless circuit.layout.selectors (List.map (fun x => x.function) members), + equations := + (List.flatMap (fun x => x.body.equations) members ++ + List.map (fun index => Aiur.AIR.booleanConstraint (row (circuit.layout.inputSize + index))) + (List.range circuit.layout.selectors) ++ + if 1 < circuit.members.size then [Aiur.AIR.oneSubBooleanConstraint selector] else []) ++ + [Aiur.AIR.activityConstraint multiplicity selector], + queries := + List.flatMap (fun x => x.body.queries) members ++ + if members.isEmpty = true then [] + else Aiur.AIR.queryParts 1 selector (List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries rankBytes)), + returns := List.flatMap (fun x => x.body.returns) members } +PREMISE Aiur.AIR.CircuitEmission.lookup +Aiur.AIR.CircuitEmission → Nat → Aiur.G × List Aiur.G +DEFINITION +fun emission slot => + if slot = 0 then + (0 - emission.multiplicity, + Aiur.AIR.slotMessage emission.branchless + (List.map (fun part => (part.fst, Aiur.AIR.functionMessage part.snd)) emission.returns)) + else + (Aiur.AIR.querySlotMultiplicity emission.queries slot, + Aiur.AIR.slotMessage emission.branchless (Aiur.AIR.querySlotParts emission.queries slot)) +PREMISE Aiur.Bytecode.Circuit.emitRow +(Nat → Aiur.G) → Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.AIR.CircuitEmission +DEFINITION +fun row program circuit => + have rank := Aiur.AIR.packRank (Aiur.AIR.circuitRankBytes row circuit.layout); + have column := circuit.layout.inputSize + circuit.layout.selectors + 1 + 6; + do + let members ← Aiur.AIR.emitMembers row rank column 4 circuit.layout.inputSize program circuit.members.toList + pure (Aiur.AIR.circuitEmission row circuit members) +PREMISE Aiur.AIR.MemberEmission.FromProgram.mk +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {column lookup : Nat} {program : Aiur.Bytecode.Toplevel} + {member : Aiur.AIR.MemberEmission}, + program.functions[member.functionIndex]? = some member.function → + Aiur.Bytecode.Function.emitRow row (Aiur.AIR.MemberEmission.selector row member) member.functionIndex rank + (Aiur.AIR.rowAdvice row 0 member.function.layout.inputSize) column lookup member.function = + some member.body → + Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member +PREMISE Aiur.AIR.CircuitEmission.QueriesIn +Aiur.AIR.CircuitEmission → List (List Aiur.G) → Prop +DEFINITION +fun emission queries => + ∀ (part : Aiur.AIR.QueryPart), part ∈ emission.queries → part.selector = 1 → part.message ∈ queries +PREMISE Aiur.AIR.circuitQueryPool +List Aiur.AIR.CircuitEmission → List (List Aiur.G) +DEFINITION +fun emissions => List.flatMap (fun emission => Aiur.AIR.decodedQueries emission.queries emission.lookupCount) emissions +PREMISE Aiur.Bytecode.FunctionLayout.width +Aiur.Bytecode.FunctionLayout → Nat +DEFINITION +fun l => l.inputSize + l.selectors + l.auxiliaries +PREMISE Aiur.Bytecode.ControlCounts.mk +Nat → Nat → Nat → Nat → Aiur.Bytecode.ControlCounts +PREMISE Aiur.Bytecode.ControlCounts.sum +List Aiur.Bytecode.ControlCounts → Aiur.Bytecode.ControlCounts +DEFINITION +fun items => + { nodes := (List.map (fun x => x.nodes) items).sum, leaves := (List.map (fun x => x.leaves) items).sum, + returns := (List.map (fun x => x.returns) items).sum, yields := (List.map (fun x => x.yields) items).sum } +PREMISE Aiur.Bytecode.ControlCounts.branch +List Aiur.Bytecode.ControlCounts → Aiur.Bytecode.ControlCounts +DEFINITION +fun items => + have __src := Aiur.Bytecode.ControlCounts.sum items; + { nodes := (Aiur.Bytecode.ControlCounts.sum items).nodes + 1, leaves := __src.leaves, returns := __src.returns, + yields := __src.yields } +PREMISE Aiur.Bytecode.ControlCounts.continue +Aiur.Bytecode.ControlCounts → Aiur.Bytecode.ControlCounts → Aiur.Bytecode.ControlCounts +DEFINITION +fun branches continuation => + { nodes := branches.nodes + continuation.nodes, leaves := branches.leaves + continuation.leaves, + returns := branches.returns + continuation.returns, yields := continuation.yields } +PREMISE Aiur.Bytecode.Ctrl.controlCounts +Aiur.Bytecode.Ctrl → Aiur.Bytecode.ControlCounts +DEFINITION +fun a => Aiur.Bytecode.Ctrl.controlCounts._mutual (PSum.inl a) +PREMISE Aiur.Bytecode.Block.controlCounts +Aiur.Bytecode.Block → Aiur.Bytecode.ControlCounts +DEFINITION +fun block => Aiur.Bytecode.Ctrl.controlCounts._mutual (PSum.inr block) +PREMISE Aiur.Bytecode.branchControlCounts +Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → List Aiur.Bytecode.ControlCounts +DEFINITION +fun branches fallback => + List.map (fun pair => pair.snd.controlCounts) branches.toList ++ + List.map (fun block => block.controlCounts) fallback.toList +PREMISE Aiur.Bytecode.Circuit.validateRowCounts +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Bool +DEFINITION +fun program circuit => + decide (circuit.members.size < Aiur.gSize.toNat) && + match List.mapM (fun index => program.functions[index]?) circuit.members.toList with + | none => false + | some functions => + (functions.all fun function => decide (function.body.controlCounts.nodes < Aiur.gSize.toNat)) && + decide + ((List.map (fun function => function.body.controlCounts.leaves) functions).sum ≤ circuit.layout.selectors) +PREMISE Aiur.Bytecode.Toplevel.validateRowCounts +Aiur.Bytecode.Toplevel → Bool +DEFINITION +fun program => program.circuits.all (Aiur.Bytecode.Circuit.validateRowCounts program) +PREMISE Aiur.Bytecode.ControlCounts.Describes.mk +∀ {counts : Aiur.Bytecode.ControlCounts} {flow : Aiur.AIR.SelectorFlow}, + flow.returns.length = counts.returns → + flow.yields.length = counts.yields → + counts.returns + counts.yields ≤ counts.leaves → counts.leaves ≤ counts.nodes → counts.Describes flow +PREMISE Aiur.BoundVerifier.build +(selection : Aiur.BoundVerifier.Selection) → Except String (Aiur.BoundVerifier.Backend selection) +DEFINITION +fun selection => + match hc : selection.compile with + | Except.error e => Except.error e + | Except.ok compiled => + if hs : compiled.getFuncIdx selection.entrypoint = some selection.function then + if hr : selection.function < Aiur.gSize.toNat then + match hp : compiled.bytecode.functions[selection.function]? with + | none => Except.error "selected function is absent" + | some entry => + if he : entry.entry = true ∧ entry.constrained = true ∧ entry.layout.inputSize = selection.inputSize then + if ho : Aiur.Bytecode.Block.returnsHaveSize selection.success.size entry.body = true then + if hl : compiled.bytecode.validateLookupShapes = true then + if hn : compiled.bytecode.validateRowCounts = true then + if hi : compiled.bytecode.validateEmission = true then + let system := selection.system compiled; + if hk : system.vkBytes = selection.key then + match hd : Aiur.NativeAIR.KeyCodec.decodeCanonical selection.key with + | none => Except.error "verification key is not a checked canonical v5 artifact" + | some keyData => + if hm : keyData.parameters = selection.keyParameters then + Except.ok + { compiled := compiled, compilation := hc, system := system, systemBuilt := ⋯, + selected := hs, functionRange := hr, entry := entry, present := hp, publicEntry := ⋯, + constrained := ⋯, arity := ⋯, returnArity := ho, lookupShapes := hl, rowCounts := hn, + emissionChecks := hi, keyBound := hk, keyData := keyData, keyDecoded := hd, + keyParameters := hm } + else Except.error "verification key parameters differ from the selected parameters" + else Except.error "verification key differs from the selected key" + else Except.error "compiled circuit reads an invalid logical value or selector" + else Except.error "compiled circuit control counts exceed their bounds" + else Except.error "compiled lookup message arities differ" + else Except.error "selected success result has the wrong output arity" + else Except.error "selected function is not a constrained public entry of the expected arity" + else Except.error "function index is not a canonical field element" + else Except.error "entrypoint differs from the selected function" +PREMISE Aiur.AIR.Provider.PaddedEq +Nat → Aiur.AIR.Provider (List Aiur.G) → Aiur.AIR.Provider (List Aiur.G) → Prop +DEFINITION +fun width left right => + left.snd = right.snd ∧ (left.snd ≠ 0 → Aiur.AIR.padMessage width left.fst = Aiur.AIR.padMessage width right.fst) +PREMISE Aiur.AIR.CircuitEmission.provider +Aiur.AIR.CircuitEmission → Aiur.AIR.Provider (List Aiur.G) +DEFINITION +fun emission => ((emission.lookup 0).snd, emission.multiplicity) +PREMISE Aiur.AIR.AuxiliaryTables.mk +List Nat → + (Nat → Array Aiur.AIR.MemoryRow) → + (Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G) → (Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G) → Aiur.AIR.AuxiliaryTables +PREMISE Aiur.AIR.AuxiliaryTables.withFunctions +Aiur.AIR.AuxiliaryTables → List Aiur.AIR.FunctionRow → Aiur.AIR.LookupTables +DEFINITION +fun tables functions => + { functions := functions, memoryWidths := tables.memoryWidths, memory := tables.memory, byte1 := tables.byte1, + byte2 := tables.byte2 } +PREMISE Aiur.AIR.AuxiliaryTables.providers +Aiur.AIR.AuxiliaryTables → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun tables => + List.flatMap + (fun width => + Aiur.AIR.mapProviders (fun request => Aiur.AIR.memoryMessage width request.fst request.snd) + (Aiur.AIR.memoryProviders (tables.memory width))) + tables.memoryWidths ++ + Aiur.AIR.byte1Providers tables.byte1 ++ + Aiur.AIR.byte2Providers tables.byte2 +PREMISE Aiur.AIR.AuxiliaryTables.circuitProviders +Aiur.AIR.AuxiliaryTables → List Aiur.AIR.CircuitEmission → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun tables emissions => Aiur.AIR.circuitProviders emissions ++ tables.providers +PREMISE Aiur.AIR.circuitProviders +List Aiur.AIR.CircuitEmission → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun emissions => List.map Aiur.AIR.CircuitEmission.provider emissions +PREMISE Aiur.AIR.FunctionRow.Provides +Nat → Aiur.AIR.CircuitEmission → Aiur.AIR.FunctionRow → Prop +DEFINITION +fun width emission row => + Aiur.AIR.Provider.PaddedEq width emission.provider (Aiur.AIR.functionMessage row.request, row.multiplicity) +PREMISE Aiur.AIR.FunctionRow.inactive +Aiur.AIR.FunctionRow +DEFINITION +{ request := { function := 0, inputs := #[], outputs := #[], rank := 0 }, calls := [], rankBytes := fun x => 0, + selector := 0, multiplicity := 0 } +PREMISE Aiur.AIR.FunctionRow.QueriesIn +List (List Aiur.G) → Aiur.AIR.FunctionRow → Prop +DEFINITION +fun queries row => + row.selector = 1 → + List.map Aiur.AIR.functionMessage row.requests ⊆ queries ∧ List.map Aiur.AIR.rangeMessage row.byteQueries ⊆ queries +PREMISE Aiur.AIR.CircuitWitness.mk +Aiur.Bytecode.Circuit → (Nat → Aiur.G) → Aiur.AIR.CircuitEmission → Aiur.AIR.CircuitWitness +PREMISE Aiur.AIR.CircuitWitness.Emitted +Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun program witness => Aiur.Bytecode.Circuit.emitRow witness.values program witness.circuit = some witness.emission +PREMISE Aiur.AIR.CircuitWitness.Satisfied +Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun witness => ∀ (equation : Aiur.G), equation ∈ witness.emission.equations → equation = 0 +PREMISE Aiur.AIR.CircuitWitness.Shapes +Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun program witness => + ∀ (part : Aiur.AIR.MemberEmission), + part ∈ witness.emission.members → Aiur.Bytecode.Block.lookupShapes program none part.function.body = true +PREMISE Aiur.AIR.CircuitWitness.LookupBounds +Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun witness => + 4 ≤ witness.circuit.layout.lookups ∧ + ∀ (part : Aiur.AIR.MemberEmission), + part ∈ witness.emission.members → part.body.lookup ≤ witness.circuit.layout.lookups +PREMISE Aiur.Bytecode.Function.hasTerminalControl +Aiur.Bytecode.Function → Bool +DEFINITION +fun function => + match function.body.ctrl with + | Aiur.Bytecode.Ctrl.return a a_1 => true + | Aiur.Bytecode.Ctrl.yield a a_1 => true + | x => false +PREMISE Aiur.Bytecode.circuitBranchless +Nat → List Aiur.Bytecode.Function → Bool +DEFINITION +fun selectors functions => + selectors == 1 && + match functions with + | [function] => function.hasTerminalControl + | x => false +PREMISE Aiur.AIR.unitQuerySelectors +List Aiur.AIR.QueryPart → List Aiur.AIR.QueryPart +DEFINITION +fun queries => List.map (fun query => { slot := query.slot, selector := 1, message := query.message }) queries +PREMISE Aiur.AIR.QueryWriters +Nat → Nat → List Aiur.AIR.QueryPart → Prop +DEFINITION +fun start finish queries => Aiur.AIR.QuerySlots 1 start finish (Aiur.AIR.unitQuerySelectors queries) +PREMISE Aiur.AIR.encodedCircuitQueryPool +List Aiur.AIR.CircuitEmission → List (List Aiur.G) +DEFINITION +fun emissions => + List.flatMap (fun emission => Aiur.AIR.encodedQueries emission.branchless emission.queries emission.lookupCount) + emissions +PREMISE Aiur.AIR.CircuitTraces.nil +Aiur.AIR.CircuitTraces [] +PREMISE Aiur.AIR.CircuitTraces.inactive +(circuit : Aiur.Bytecode.Circuit) → + {circuits : List Aiur.Bytecode.Circuit} → + Aiur.AIR.CircuitTraces circuits → Aiur.AIR.CircuitTraces (circuit :: circuits) +PREMISE Aiur.AIR.CircuitTraces.active +(circuit : Aiur.Bytecode.Circuit) → + (degree : Nat) → + (Fin (2 ^ degree) → Nat → Aiur.G) → + {circuits : List Aiur.Bytecode.Circuit} → + Aiur.AIR.CircuitTraces circuits → Aiur.AIR.CircuitTraces (circuit :: circuits) +PREMISE Aiur.AIR.CircuitTraces.bitmap +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → List Bool +DEFINITION +fun {circuits} x => Aiur.AIR.CircuitTraces.brecOn x @Aiur.AIR.CircuitTraces.bitmap._f +PREMISE Aiur.AIR.CircuitTraces.degrees +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → List Nat +DEFINITION +fun {circuits} x => Aiur.AIR.CircuitTraces.brecOn x @Aiur.AIR.CircuitTraces.degrees._f +PREMISE Aiur.AIR.CircuitTraces.capacity +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → Nat +DEFINITION +fun {circuits} x => Aiur.AIR.CircuitTraces.brecOn x @Aiur.AIR.CircuitTraces.capacity._f +PREMISE Aiur.AIR.emitCircuitWitness +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → (Nat → Aiur.G) → Option Aiur.AIR.CircuitWitness +DEFINITION +fun program circuit values => do + let emission ← Aiur.Bytecode.Circuit.emitRow values program circuit + pure { circuit := circuit, values := values, emission := emission } +PREMISE Aiur.AIR.CircuitTraces.emitWitnesses +{circuits : List Aiur.Bytecode.Circuit} → + Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitTraces circuits → Option (List Aiur.AIR.CircuitWitness) +DEFINITION +fun {circuits} program x => Aiur.AIR.CircuitTraces.brecOn x (@Aiur.AIR.CircuitTraces.emitWitnesses._f program) +PREMISE Aiur.Bytecode.Toplevel.singletonCircuits +Aiur.Bytecode.Toplevel → (Aiur.Bytecode.FunIdx → String) → Array Aiur.Bytecode.Circuit +DEFINITION +fun t nameOf => + (have circuits := #[]; + do + let __s ← + forIn' [:t.functions.size] circuits fun i h __s => + have circuits := __s; + have f := t.functions[i]; + if f.constrained = true then + have circuits := circuits.push { name := nameOf i, members := #[i], layout := f.layout }; + pure (ForInStep.yield circuits) + else pure (ForInStep.yield circuits) + have circuits : Array Aiur.Bytecode.Circuit := __s + pure circuits).run +PREMISE Aiur.Bytecode.MembersConstrained +Array Aiur.Bytecode.Function → Array Aiur.Bytecode.FunIdx → Prop +DEFINITION +fun functions members => + ∀ (index : Aiur.Bytecode.FunIdx), + index ∈ members → ∃ function, functions[index]? = some function ∧ function.constrained = true +PREMISE Aiur.Bytecode.CircuitsConstrained +Array Aiur.Bytecode.Function → Array Aiur.Bytecode.Circuit → Prop +DEFINITION +fun functions circuits => + ∀ (circuit : Aiur.Bytecode.Circuit), circuit ∈ circuits → Aiur.Bytecode.MembersConstrained functions circuit.members +PREMISE Aiur.Bytecode.Op.lookupUsage +Aiur.Bytecode.Op → Nat +DEFINITION +fun x => + match x with + | Aiur.Bytecode.Op.call a a_1 outputSize unconstrained => if unconstrained = true then 0 else 4 + | Aiur.Bytecode.Op.store a => 1 + | Aiur.Bytecode.Op.load size a => 1 + | Aiur.Bytecode.Op.u8BitDecomposition a => 1 + | Aiur.Bytecode.Op.u8ShiftLeft a => 1 + | Aiur.Bytecode.Op.u8ShiftRight a => 1 + | Aiur.Bytecode.Op.u8Xor a a_1 => 1 + | Aiur.Bytecode.Op.u8And a a_1 => 1 + | Aiur.Bytecode.Op.u8Or a a_1 => 1 + | Aiur.Bytecode.Op.u8Add a a_1 => 1 + | Aiur.Bytecode.Op.u8Sub a a_1 => 1 + | Aiur.Bytecode.Op.u8Mul a a_1 => 1 + | Aiur.Bytecode.Op.u8XorSplit7 a a_1 => 1 + | Aiur.Bytecode.Op.u8XorSplit4 a a_1 => 1 + | Aiur.Bytecode.Op.u8LessThan a a_1 => 1 + | Aiur.Bytecode.Op.u8RangeCheck a a_1 => 1 + | Aiur.Bytecode.Op.u32LessThan a a_1 => 6 + | x => 0 +PREMISE Aiur.Bytecode.Ctrl.lookupUsage +Aiur.Bytecode.Ctrl → Nat +DEFINITION +fun a => Aiur.Bytecode.Ctrl.lookupUsage._mutual (PSum.inl a) +PREMISE Aiur.Bytecode.Block.lookupUsage +Aiur.Bytecode.Block → Nat +DEFINITION +fun block => Aiur.Bytecode.Ctrl.lookupUsage._mutual (PSum.inr block) +PREMISE Aiur.Bytecode.branchLookupUsage +Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → Nat +DEFINITION +fun branches fallback => + List.foldl Nat.max 0 + (List.map (fun pair => pair.snd.lookupUsage) branches.toList ++ + List.map (fun block => block.lookupUsage) fallback.toList) +PREMISE Aiur.Bytecode.Function.LookupLayout +Aiur.Bytecode.Function → Prop +DEFINITION +fun function => function.layout.lookups = 4 + function.body.lookupUsage +PREMISE Aiur.Bytecode.FunctionsLookupLayout +Array Aiur.Bytecode.Function → Prop +DEFINITION +fun functions => ∀ (function : Aiur.Bytecode.Function), function ∈ functions → function.LookupLayout +PREMISE Aiur.Bytecode.MembersLookupBound +Array Aiur.Bytecode.Function → Array Aiur.Bytecode.FunIdx → Nat → Prop +DEFINITION +fun functions members slots => + 4 ≤ slots ∧ ∀ (index : Aiur.Bytecode.FunIdx), index ∈ members → functions[index]!.layout.lookups ≤ slots +PREMISE Aiur.Bytecode.CircuitsLookupBound +Array Aiur.Bytecode.Function → Array Aiur.Bytecode.Circuit → Prop +DEFINITION +fun functions circuits => + ∀ (circuit : Aiur.Bytecode.Circuit), + circuit ∈ circuits → Aiur.Bytecode.MembersLookupBound functions circuit.members circuit.layout.lookups +PREMISE Aiur.AIR.MemoryColumns +Nat → Type +DEFINITION +fun width => Fin (3 + width) → Aiur.G +PREMISE Aiur.AIR.decodeMemoryRow +(width : Nat) → Aiur.AIR.MemoryColumns width → Aiur.AIR.MemoryRow +DEFINITION +fun width columns => + { selector := columns ⟨1, ⋯⟩, multiplicity := columns ⟨0, ⋯⟩, pointer := columns ⟨2, ⋯⟩, + contents := Array.ofFn fun i => columns ⟨3 + ↑i, ⋯⟩ } +PREMISE Aiur.AIR.memoryColumnEquations +(width : Nat) → Aiur.AIR.MemoryColumns width → Aiur.AIR.MemoryColumns width → Aiur.G → List Aiur.G +DEFINITION +fun width current next transition => + have selector := current ⟨1, ⋯⟩; + have nextSelector := next ⟨1, ⋯⟩; + [selector * (selector - 1), current ⟨0, ⋯⟩ * (1 - selector), nextSelector * transition * (selector - 1), + nextSelector * transition * (current ⟨2, ⋯⟩ + 1 - next ⟨2, ⋯⟩)] +PREMISE Aiur.AIR.memoryColumnLookup +(width : Nat) → Aiur.AIR.MemoryColumns width → Aiur.G × List Aiur.G +DEFINITION +fun width columns => + (0 - columns ⟨0, ⋯⟩, + List.map (fun value => columns ⟨1, ⋯⟩ * value) + (Aiur.AIR.memoryMessage width (columns ⟨2, ⋯⟩) (Aiur.AIR.decodeMemoryRow width columns).contents)) +PREMISE Aiur.AIR.memoryColumnProvider +(width : Nat) → Aiur.AIR.MemoryColumns width → Aiur.AIR.Provider (List Aiur.G) +DEFINITION +fun width columns => ((Aiur.AIR.memoryColumnLookup width columns).snd, columns ⟨0, ⋯⟩) +PREMISE Aiur.AIR.memoryNextIndex +{height : Nat} → Fin height → Fin height +DEFINITION +fun {height} index => if next : ↑index + 1 < height then ⟨↑index + 1, next⟩ else ⟨0, ⋯⟩ +PREMISE Aiur.AIR.memoryMatrixEquations +(width height : Nat) → (Fin height → Aiur.AIR.MemoryColumns width) → Fin height → List Aiur.G +DEFINITION +fun width height matrix index => + Aiur.AIR.memoryColumnEquations width (matrix index) (matrix (Aiur.AIR.memoryNextIndex index)) + (if ↑index + 1 < height then 1 else 0) +PREMISE Aiur.AIR.MemoryMatrixSatisfied +(width height : Nat) → (Fin height → Aiur.AIR.MemoryColumns width) → Prop +DEFINITION +fun width height matrix => + ∀ (index : Fin height) (equation : Aiur.G), + equation ∈ Aiur.AIR.memoryMatrixEquations width height matrix index → equation = 0 +PREMISE Aiur.AIR.decodeMemoryRows +(width height : Nat) → (Fin height → Aiur.AIR.MemoryColumns width) → Array Aiur.AIR.MemoryRow +DEFINITION +fun width height matrix => Array.ofFn fun index => Aiur.AIR.decodeMemoryRow width (matrix index) +PREMISE Aiur.AIR.memoryMatrixProviders +(width height : Nat) → (Fin height → Aiur.AIR.MemoryColumns width) → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun width height matrix => List.ofFn fun index => Aiur.AIR.memoryColumnProvider width (matrix index) +PREMISE Aiur.AIR.MemoryTraces.nil +Aiur.AIR.MemoryTraces [] +PREMISE Aiur.AIR.MemoryTraces.inactive +(width : Nat) → {widths : List Nat} → Aiur.AIR.MemoryTraces widths → Aiur.AIR.MemoryTraces (width :: widths) +PREMISE Aiur.AIR.MemoryTraces.active +(width degree : Nat) → + (Fin (2 ^ degree) → Aiur.AIR.MemoryColumns width) → + {widths : List Nat} → Aiur.AIR.MemoryTraces widths → Aiur.AIR.MemoryTraces (width :: widths) +PREMISE Aiur.AIR.MemoryTraces.bitmap +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List Bool +DEFINITION +fun {widths} x => Aiur.AIR.MemoryTraces.brecOn x @Aiur.AIR.MemoryTraces.bitmap._f +PREMISE Aiur.AIR.MemoryTraces.degrees +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List Nat +DEFINITION +fun {widths} x => Aiur.AIR.MemoryTraces.brecOn x @Aiur.AIR.MemoryTraces.degrees._f +PREMISE Aiur.AIR.MemoryTraces.capacity +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → Nat +DEFINITION +fun {widths} x => Aiur.AIR.MemoryTraces.brecOn x @Aiur.AIR.MemoryTraces.capacity._f +PREMISE Aiur.AIR.MemoryTraces.rows +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → Nat → Array Aiur.AIR.MemoryRow +DEFINITION +fun {widths} x x_1 => + Aiur.AIR.MemoryTraces.brecOn (motive := fun {widths} x => Nat → Array Aiur.AIR.MemoryRow) x + (@Aiur.AIR.MemoryTraces.rows._f) x_1 +PREMISE Aiur.AIR.MemoryTraces.providers +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun {widths} x => Aiur.AIR.MemoryTraces.brecOn x @Aiur.AIR.MemoryTraces.providers._f +PREMISE Aiur.AIR.MemoryTraces.Satisfied +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → Prop +DEFINITION +fun {widths} x => Aiur.AIR.MemoryTraces.brecOn x @Aiur.AIR.MemoryTraces.Satisfied._f +PREMISE Aiur.AIR.memoryTableProviders +List Nat → (Nat → Array Aiur.AIR.MemoryRow) → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun widths rows => + List.flatMap + (fun width => + Aiur.AIR.mapProviders (fun request => Aiur.AIR.memoryMessage width request.fst request.snd) + (Aiur.AIR.memoryProviders (rows width))) + widths +PREMISE Aiur.AIR.MemoryTraces.auxiliary +{widths : List Nat} → + Aiur.AIR.MemoryTraces widths → + (Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G) → (Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G) → Aiur.AIR.AuxiliaryTables +DEFINITION +fun {widths} traces byte1 byte2 => { memoryWidths := widths, memory := traces.rows, byte1 := byte1, byte2 := byte2 } +PREMISE Aiur.fixedTraceHeights +List Nat → List Bool → List Nat → Bool +DEFINITION +fun x x_1 x_2 => List.brecOn (motive := fun x => List Bool → List Nat → Bool) x Aiur.fixedTraceHeights._f x_1 x_2 +PREMISE Aiur.FixedTraceHeights.nil +Aiur.FixedTraceHeights [] [] [] +PREMISE Aiur.FixedTraceHeights.inactive +∀ {heights : List Nat} {active : List Bool} {degrees : List Nat}, + Aiur.FixedTraceHeights heights active degrees → Aiur.FixedTraceHeights (0 :: heights) (false :: active) degrees +PREMISE Aiur.FixedTraceHeights.active +∀ (height degree : Nat) {heights : List Nat} {active : List Bool} {degrees : List Nat}, + height = 0 ∨ degree < 64 ∧ height = 2 ^ degree → + Aiur.FixedTraceHeights heights active degrees → + Aiur.FixedTraceHeights (height :: heights) (true :: active) (degree :: degrees) +PREMISE Aiur.AIR.Byte1Columns +Type +DEFINITION +Fin 3 → Aiur.G +PREMISE Aiur.AIR.Byte2Columns +Type +DEFINITION +Fin 10 → Aiur.G +PREMISE Aiur.AIR.Byte1Kind.column +Aiur.AIR.Byte1Kind → Fin 3 +DEFINITION +fun x => + match x with + | Aiur.AIR.Byte1Kind.bits => 0 + | Aiur.AIR.Byte1Kind.shiftLeft => 1 + | Aiur.AIR.Byte1Kind.shiftRight => 2 +PREMISE Aiur.AIR.Byte2Kind.column +Aiur.AIR.Byte2Kind → Fin 10 +DEFINITION +fun x => + match x with + | Aiur.AIR.Byte2Kind.xor => 0 + | Aiur.AIR.Byte2Kind.add => 1 + | Aiur.AIR.Byte2Kind.sub => 2 + | Aiur.AIR.Byte2Kind.and => 3 + | Aiur.AIR.Byte2Kind.or => 4 + | Aiur.AIR.Byte2Kind.lessThan => 5 + | Aiur.AIR.Byte2Kind.range => 6 + | Aiur.AIR.Byte2Kind.mul => 7 + | Aiur.AIR.Byte2Kind.split7 => 8 + | Aiur.AIR.Byte2Kind.split4 => 9 +PREMISE Aiur.AIR.byte1PreprocessedColumns +Fin 256 → Fin 11 → Aiur.G +DEFINITION +fun row column => (Aiur.AIR.byte1Preprocessed row)[↑column]?.getD 0 +PREMISE Aiur.AIR.byte2PreprocessedColumns +Fin 65536 → Fin 14 → Aiur.G +DEFINITION +fun row column => (Aiur.AIR.byte2Preprocessed row)[↑column]?.getD 0 +PREMISE Aiur.AIR.byte1ColumnLookup +Aiur.AIR.Byte1Kind → (Fin 11 → Aiur.G) → Aiur.AIR.Byte1Columns → Aiur.G × List Aiur.G +DEFINITION +fun kind preprocessed columns => + (0 - columns kind.column, + match kind with + | Aiur.AIR.Byte1Kind.bits => [2, preprocessed 0] ++ List.ofFn fun bit => preprocessed ⟨1 + ↑bit, ⋯⟩ + | Aiur.AIR.Byte1Kind.shiftLeft => [3, preprocessed 0, preprocessed 9] + | Aiur.AIR.Byte1Kind.shiftRight => [4, preprocessed 0, preprocessed 10]) +PREMISE Aiur.AIR.byte2ColumnLookup +Aiur.AIR.Byte2Kind → (Fin 14 → Aiur.G) → Aiur.AIR.Byte2Columns → Aiur.G × List Aiur.G +DEFINITION +fun kind preprocessed columns => + (0 - columns kind.column, + [kind.channel, preprocessed 0, preprocessed 1] ++ + match kind with + | Aiur.AIR.Byte2Kind.xor => [preprocessed 2] + | Aiur.AIR.Byte2Kind.add => [preprocessed 3] + | Aiur.AIR.Byte2Kind.sub => [preprocessed 4] + | Aiur.AIR.Byte2Kind.and => [preprocessed 5] + | Aiur.AIR.Byte2Kind.or => [preprocessed 6] + | Aiur.AIR.Byte2Kind.lessThan => [preprocessed 7] + | Aiur.AIR.Byte2Kind.range => [] + | Aiur.AIR.Byte2Kind.mul => [preprocessed 8, preprocessed 9] + | Aiur.AIR.Byte2Kind.split7 => [preprocessed 10, preprocessed 11] + | Aiur.AIR.Byte2Kind.split4 => [preprocessed 12, preprocessed 13]) +PREMISE Aiur.AIR.byte1ColumnProvider +Aiur.AIR.Byte1Kind → Fin 256 → Aiur.AIR.Byte1Columns → Aiur.AIR.Provider (List Aiur.G) +DEFINITION +fun kind row columns => + ((Aiur.AIR.byte1ColumnLookup kind (Aiur.AIR.byte1PreprocessedColumns row) columns).snd, columns kind.column) +PREMISE Aiur.AIR.byte2ColumnProvider +Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.AIR.Byte2Columns → Aiur.AIR.Provider (List Aiur.G) +DEFINITION +fun kind row columns => + ((Aiur.AIR.byte2ColumnLookup kind (Aiur.AIR.byte2PreprocessedColumns row) columns).snd, columns kind.column) +PREMISE Aiur.AIR.byte1MatrixProviders +(Fin 256 → Aiur.AIR.Byte1Columns) → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun matrix => + List.flatMap + (fun row => List.map (fun kind => Aiur.AIR.byte1ColumnProvider kind row (matrix row)) Aiur.AIR.Byte1Kind.all) + (List.finRange 256) +PREMISE Aiur.AIR.byte2MatrixProviders +(Fin 65536 → Aiur.AIR.Byte2Columns) → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun matrix => + List.flatMap + (fun row => List.map (fun kind => Aiur.AIR.byte2ColumnProvider kind row (matrix row)) Aiur.AIR.Byte2Kind.all) + (List.finRange 65536) +PREMISE Aiur.AIR.ByteTraces.mk +(Fin 256 → Aiur.AIR.Byte1Columns) → (Fin 65536 → Aiur.AIR.Byte2Columns) → Aiur.AIR.ByteTraces +PREMISE Aiur.AIR.ByteTraces.providers +Aiur.AIR.ByteTraces → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun traces => Aiur.AIR.byte1MatrixProviders traces.unary ++ Aiur.AIR.byte2MatrixProviders traces.binary +PREMISE Aiur.AIR.ByteTraces.byte1Weights +Aiur.AIR.ByteTraces → Aiur.AIR.Byte1Kind → Fin 256 → Aiur.G +DEFINITION +fun traces kind row => traces.unary row kind.column +PREMISE Aiur.AIR.ByteTraces.byte2Weights +Aiur.AIR.ByteTraces → Aiur.AIR.Byte2Kind → Fin 65536 → Aiur.G +DEFINITION +fun traces kind row => traces.binary row kind.column +PREMISE Aiur.AIR.SystemTraces.mk +{program : Aiur.Bytecode.Toplevel} → + Aiur.AIR.CircuitTraces program.circuits.toList → + Aiur.AIR.MemoryTraces program.memorySizes.toList → Aiur.AIR.ByteTraces → Aiur.AIR.SystemTraces program +PREMISE Aiur.AIR.SystemTraces.bitmap +{program : Aiur.Bytecode.Toplevel} → Aiur.AIR.SystemTraces program → List Bool +DEFINITION +fun {program} traces => traces.functions.bitmap ++ (traces.memories.bitmap ++ [true, true]) +PREMISE Aiur.AIR.SystemTraces.degrees +{program : Aiur.Bytecode.Toplevel} → Aiur.AIR.SystemTraces program → List Nat +DEFINITION +fun {program} traces => traces.functions.degrees ++ (traces.memories.degrees ++ [8, 16]) +PREMISE Aiur.AIR.SystemTraces.queryBound +{program : Aiur.Bytecode.Toplevel} → Aiur.AIR.SystemTraces program → Option Nat +DEFINITION +fun {program} traces => Aiur.lookupQueryBound (Aiur.AIR.systemLookupSlots program) traces.bitmap traces.degrees +PREMISE Aiur.AIR.SystemTraces.providers +{program : Aiur.Bytecode.Toplevel} → + Aiur.AIR.SystemTraces program → List Aiur.AIR.CircuitEmission → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun {program} traces circuits => + Aiur.AIR.circuitProviders circuits ++ (traces.memories.providers ++ traces.bytes.providers) +PREMISE Aiur.AIR.systemFixedHeights +Aiur.Bytecode.Toplevel → List Nat +DEFINITION +fun program => List.replicate program.circuits.size 0 ++ (List.replicate program.memorySizes.size 0 ++ [256, 65536]) +PREMISE Aiur.AIR.systemLookupSlots +Aiur.Bytecode.Toplevel → List Nat +DEFINITION +fun program => + List.map (fun x => x.layout.lookups) program.circuits.toList ++ (List.replicate program.memorySizes.size 1 ++ [3, 10]) +PREMISE Aiur.NativeAIR.Source.preprocessed +Aiur.NativeAIR.Source +PREMISE Aiur.NativeAIR.Source.main +Aiur.NativeAIR.Source +PREMISE Aiur.NativeAIR.Source.stage2 +Aiur.NativeAIR.Source +PREMISE Aiur.NativeAIR.RowOffset.current +Aiur.NativeAIR.RowOffset +PREMISE Aiur.NativeAIR.RowOffset.next +Aiur.NativeAIR.RowOffset +PREMISE Aiur.NativeAIR.ColRef.mk +Aiur.NativeAIR.Source → Aiur.NativeAIR.RowOffset → Nat → Aiur.NativeAIR.ColRef +PREMISE Aiur.NativeAIR.Node.konst +Aiur.G → Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.var +Aiur.NativeAIR.ColRef → Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.publicInput +Nat → Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.isFirstRow +Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.isLastRow +Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.isTransition +Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.add +Nat → Nat → Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.sub +Nat → Nat → Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.mul +Nat → Nat → Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.Node.neg +Nat → Aiur.NativeAIR.Node +PREMISE Aiur.NativeAIR.GraphWidths.mk +Nat → Nat → Nat → Nat → Aiur.NativeAIR.GraphWidths +PREMISE Aiur.NativeAIR.GraphWidths.width +Aiur.NativeAIR.GraphWidths → Aiur.NativeAIR.Source → Nat +DEFINITION +fun widths x => + match x with + | Aiur.NativeAIR.Source.preprocessed => widths.preprocessed + | Aiur.NativeAIR.Source.main => widths.main + | Aiur.NativeAIR.Source.stage2 => widths.stage2 +PREMISE Aiur.NativeAIR.Lookup.mk +Nat → List Nat → Aiur.NativeAIR.Lookup +PREMISE Aiur.NativeAIR.Graph.mk +List Aiur.NativeAIR.Node → List Nat → List Aiur.NativeAIR.Lookup → Aiur.NativeAIR.Graph +PREMISE Aiur.NativeAIR.Lookup.roots +Aiur.NativeAIR.Lookup → List Nat +DEFINITION +fun lookup => lookup.multiplicity :: lookup.args +PREMISE Aiur.NativeAIR.Graph.lookupRoots +Aiur.NativeAIR.Graph → List Nat +DEFINITION +fun graph => List.flatMap Aiur.NativeAIR.Lookup.roots graph.lookups +PREMISE Aiur.NativeAIR.Graph.lookupPrefix +Aiur.NativeAIR.Graph → Nat +DEFINITION +fun graph => List.foldr (fun index rest => max (index + 1) rest) 0 graph.lookupRoots +PREMISE Aiur.NativeAIR.Node.Valid +Aiur.NativeAIR.GraphWidths → Nat → Nat → Aiur.NativeAIR.Node → Prop +DEFINITION +fun widths lookupEnd index x => + match x with + | Aiur.NativeAIR.Node.konst value => True + | Aiur.NativeAIR.Node.isFirstRow => True + | Aiur.NativeAIR.Node.isLastRow => True + | Aiur.NativeAIR.Node.isTransition => True + | Aiur.NativeAIR.Node.var column => + column.index < widths.width column.source ∧ (column.source = Aiur.NativeAIR.Source.stage2 → lookupEnd ≤ index) + | Aiur.NativeAIR.Node.publicInput input => input < widths.publics + | Aiur.NativeAIR.Node.add a b => a < index ∧ b < index + | Aiur.NativeAIR.Node.sub a b => a < index ∧ b < index + | Aiur.NativeAIR.Node.mul a b => a < index ∧ b < index + | Aiur.NativeAIR.Node.neg a => a < index +PREMISE Aiur.NativeAIR.Node.check +Aiur.NativeAIR.GraphWidths → Nat → Nat → Aiur.NativeAIR.Node → Bool +DEFINITION +fun widths lookupEnd index x => + match x with + | Aiur.NativeAIR.Node.konst value => true + | Aiur.NativeAIR.Node.isFirstRow => true + | Aiur.NativeAIR.Node.isLastRow => true + | Aiur.NativeAIR.Node.isTransition => true + | Aiur.NativeAIR.Node.var column => + decide (column.index < widths.width column.source) && + (column.source != Aiur.NativeAIR.Source.stage2 || decide (lookupEnd ≤ index)) + | Aiur.NativeAIR.Node.publicInput input => decide (input < widths.publics) + | Aiur.NativeAIR.Node.add a b => decide (a < index) && decide (b < index) + | Aiur.NativeAIR.Node.sub a b => decide (a < index) && decide (b < index) + | Aiur.NativeAIR.Node.mul a b => decide (a < index) && decide (b < index) + | Aiur.NativeAIR.Node.neg a => decide (a < index) +PREMISE Aiur.NativeAIR.checkNodes +Aiur.NativeAIR.GraphWidths → Nat → Nat → List Aiur.NativeAIR.Node → Bool +DEFINITION +fun widths lookupEnd x x_1 => + List.brecOn (motive := fun x => Nat → Bool) x_1 (Aiur.NativeAIR.checkNodes._f widths lookupEnd) x +PREMISE Aiur.NativeAIR.ValidNodes.nil +∀ {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd : Nat} (index : Nat), + Aiur.NativeAIR.ValidNodes widths lookupEnd index [] +PREMISE Aiur.NativeAIR.ValidNodes.cons +∀ {widths : Aiur.NativeAIR.GraphWidths} {lookupEnd index : Nat} {node : Aiur.NativeAIR.Node} + {nodes : List Aiur.NativeAIR.Node}, + Aiur.NativeAIR.Node.Valid widths lookupEnd index node → + Aiur.NativeAIR.ValidNodes widths lookupEnd (index + 1) nodes → + Aiur.NativeAIR.ValidNodes widths lookupEnd index (node :: nodes) +PREMISE Aiur.NativeAIR.checkedGraphPrefix +Aiur.NativeAIR.GraphWidths → Aiur.NativeAIR.Graph → Option Nat +DEFINITION +fun widths graph => + if + (((graph.zeros.all fun x => decide (x < graph.nodes.length)) && + graph.lookupRoots.all fun x => decide (x < graph.nodes.length)) && + Aiur.NativeAIR.checkNodes widths graph.lookupPrefix 0 graph.nodes) = + true then + some graph.lookupPrefix + else none +PREMISE Aiur.NativeAIR.Graph.Valid.mk +∀ {widths : Aiur.NativeAIR.GraphWidths} {graph : Aiur.NativeAIR.Graph}, + Aiur.NativeAIR.ValidNodes widths graph.lookupPrefix 0 graph.nodes → + (∀ (index : Nat), index ∈ graph.zeros → index < graph.nodes.length) → + (∀ (index : Nat), index ∈ graph.lookupRoots → index < graph.nodes.length) → + Aiur.NativeAIR.Graph.Valid widths graph +PREMISE Aiur.NativeAIR.EvalOps.mk +{W : Type u} → (Aiur.G → W) → (W → W → W) → (W → W → W) → (W → W → W) → (W → W) → Aiur.NativeAIR.EvalOps W +PREMISE Aiur.NativeAIR.Values.mk +{W : Type u} → + (Aiur.NativeAIR.Source → Aiur.NativeAIR.RowOffset → Array W) → Array W → W → W → W → Aiur.NativeAIR.Values W +PREMISE Aiur.NativeAIR.Values.Fits +{W : Type u_1} → Aiur.NativeAIR.Values W → Aiur.NativeAIR.GraphWidths → Prop +DEFINITION +fun {W} values widths => + (∀ (source : Aiur.NativeAIR.Source) (offset : Aiur.NativeAIR.RowOffset), + (values.columns source offset).size = widths.width source) ∧ + values.publics.size = widths.publics +PREMISE Aiur.NativeAIR.Node.eval +{W : Type u_1} → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Array W → Aiur.NativeAIR.Node → Option W +DEFINITION +fun {W} ops values buffer x => + match x with + | Aiur.NativeAIR.Node.konst value => some (ops.konst value) + | Aiur.NativeAIR.Node.var column => (values.columns column.source column.offset)[column.index]? + | Aiur.NativeAIR.Node.publicInput index => values.publics[index]? + | Aiur.NativeAIR.Node.isFirstRow => some values.isFirstRow + | Aiur.NativeAIR.Node.isLastRow => some values.isLastRow + | Aiur.NativeAIR.Node.isTransition => some values.isTransition + | Aiur.NativeAIR.Node.add a b => do + let __do_lift ← buffer[a]? + let __do_lift_1 ← buffer[b]? + pure (ops.add __do_lift __do_lift_1) + | Aiur.NativeAIR.Node.sub a b => do + let __do_lift ← buffer[a]? + let __do_lift_1 ← buffer[b]? + pure (ops.sub __do_lift __do_lift_1) + | Aiur.NativeAIR.Node.mul a b => do + let __do_lift ← buffer[a]? + let __do_lift_1 ← buffer[b]? + pure (ops.mul __do_lift __do_lift_1) + | Aiur.NativeAIR.Node.neg a => do + let __do_lift ← buffer[a]? + pure (ops.neg __do_lift) +PREMISE Aiur.NativeAIR.sweepFrom +{W : Type u_1} → + Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → List Aiur.NativeAIR.Node → Array W → Option (Array W) +DEFINITION +fun {W} ops values x x_1 => + List.brecOn (motive := fun x => Array W → Option (Array W)) x (Aiur.NativeAIR.sweepFrom._f ops values) x_1 +PREMISE Aiur.NativeAIR.Graph.sweep +{W : Type u_1} → Aiur.NativeAIR.Graph → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Option (Array W) +DEFINITION +fun {W} graph ops values => Aiur.NativeAIR.sweepFrom ops values graph.nodes #[] +PREMISE Aiur.NativeAIR.Values.withoutStage2 +{W : Type u_1} → Aiur.NativeAIR.Values W → Aiur.NativeAIR.Values W +DEFINITION +fun {W} values => + { + columns := fun source offset => + match source with + | Aiur.NativeAIR.Source.stage2 => #[] + | x => values.columns source offset, + publics := values.publics, isFirstRow := values.isFirstRow, isLastRow := values.isLastRow, + isTransition := values.isTransition } +PREMISE Aiur.NativeAIR.Graph.sweepLookupPrefix +{W : Type u_1} → Aiur.NativeAIR.Graph → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Option (Array W) +DEFINITION +fun {W} graph ops values => + Aiur.NativeAIR.sweepFrom ops values.withoutStage2 (List.take graph.lookupPrefix graph.nodes) #[] +PREMISE Aiur.NativeAIR.Expr.konst +Aiur.G → Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.var +Aiur.NativeAIR.ColRef → Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.publicInput +Nat → Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.isFirstRow +Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.isLastRow +Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.isTransition +Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.add +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.sub +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.mul +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.neg +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +PREMISE Aiur.NativeAIR.Expr.eval +{W : Type u_1} → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Aiur.NativeAIR.Expr → Option W +DEFINITION +fun {W} ops values x => Aiur.NativeAIR.Expr.brecOn x (Aiur.NativeAIR.Expr.eval._f ops values) +PREMISE Aiur.NativeAIR.Node.unfold +Array Aiur.NativeAIR.Expr → Aiur.NativeAIR.Node → Option Aiur.NativeAIR.Expr +DEFINITION +fun trees x => + match x with + | Aiur.NativeAIR.Node.konst value => some (Aiur.NativeAIR.Expr.konst value) + | Aiur.NativeAIR.Node.var column => some (Aiur.NativeAIR.Expr.var column) + | Aiur.NativeAIR.Node.publicInput index => some (Aiur.NativeAIR.Expr.publicInput index) + | Aiur.NativeAIR.Node.isFirstRow => some Aiur.NativeAIR.Expr.isFirstRow + | Aiur.NativeAIR.Node.isLastRow => some Aiur.NativeAIR.Expr.isLastRow + | Aiur.NativeAIR.Node.isTransition => some Aiur.NativeAIR.Expr.isTransition + | Aiur.NativeAIR.Node.add a b => do + let __do_lift ← trees[a]? + let __do_lift_1 ← trees[b]? + pure (__do_lift.add __do_lift_1) + | Aiur.NativeAIR.Node.sub a b => do + let __do_lift ← trees[a]? + let __do_lift_1 ← trees[b]? + pure (__do_lift.sub __do_lift_1) + | Aiur.NativeAIR.Node.mul a b => do + let __do_lift ← trees[a]? + let __do_lift_1 ← trees[b]? + pure (__do_lift.mul __do_lift_1) + | Aiur.NativeAIR.Node.neg a => do + let __do_lift ← trees[a]? + pure __do_lift.neg +PREMISE Aiur.NativeAIR.Reflects +{W : Type u_1} → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Array Aiur.NativeAIR.Expr → Array W → Prop +DEFINITION +fun {W} ops values trees buffer => + buffer.size = trees.size ∧ ∀ (index : Nat), buffer[index]? = trees[index]?.bind (Aiur.NativeAIR.Expr.eval ops values) +PREMISE Aiur.NativeAIR.unfoldFrom +List Aiur.NativeAIR.Node → Array Aiur.NativeAIR.Expr → Option (Array Aiur.NativeAIR.Expr) +DEFINITION +fun x x_1 => + List.brecOn (motive := fun x => Array Aiur.NativeAIR.Expr → Option (Array Aiur.NativeAIR.Expr)) x + Aiur.NativeAIR.unfoldFrom._f x_1 +PREMISE Aiur.NativeAIR.Graph.unfold +Aiur.NativeAIR.Graph → Option (Array Aiur.NativeAIR.Expr) +DEFINITION +fun graph => Aiur.NativeAIR.unfoldFrom graph.nodes #[] +PREMISE Aiur.NativeAIR.readNodes +{W : Type u_1} → Array W → List Nat → Option (List W) +DEFINITION +fun {W} buffer roots => List.mapM (fun index => buffer[index]?) roots +PREMISE Aiur.NativeAIR.evalRoots +{W : Type u_1} → + Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Array Aiur.NativeAIR.Expr → List Nat → Option (List W) +DEFINITION +fun {W} ops values trees roots => + List.mapM (fun index => trees[index]?.bind (Aiur.NativeAIR.Expr.eval ops values)) roots +PREMISE Aiur.NativeAIR.readLookup +{W : Type u_1} → Array W → Aiur.NativeAIR.Lookup → Option (W × List W) +DEFINITION +fun {W} buffer lookup => do + let multiplicity ← buffer[lookup.multiplicity]? + let args ← Aiur.NativeAIR.readNodes buffer lookup.args + pure (multiplicity, args) +PREMISE Aiur.NativeAIR.evalLookup +{W : Type u_1} → + Aiur.NativeAIR.EvalOps W → + Aiur.NativeAIR.Values W → Array Aiur.NativeAIR.Expr → Aiur.NativeAIR.Lookup → Option (W × List W) +DEFINITION +fun {W} ops values trees lookup => do + let multiplicity ← trees[lookup.multiplicity]?.bind (Aiur.NativeAIR.Expr.eval ops values) + let args ← Aiur.NativeAIR.evalRoots ops values trees lookup.args + pure (multiplicity, args) +PREMISE Aiur.NativeAIR.goldilocksOps +Aiur.NativeAIR.EvalOps Aiur.G +DEFINITION +{ konst := id, add := fun x1 x2 => x1 + x2, sub := fun x1 x2 => x1 - x2, mul := fun x1 x2 => x1 * x2, + neg := fun x => 0 - x } +PREMISE Aiur.NativeAIR.Expr.isConstant +Aiur.NativeAIR.Expr → Bool +DEFINITION +fun x => + match x with + | Aiur.NativeAIR.Expr.konst value => true + | x => false +PREMISE Aiur.NativeAIR.Expr.constantValue +Aiur.NativeAIR.Expr → Option Aiur.G +DEFINITION +fun x => + match x with + | Aiur.NativeAIR.Expr.konst value => some value + | x => none +PREMISE Aiur.NativeAIR.Expr.frontNeg +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +DEFINITION +fun x => + match x with + | Aiur.NativeAIR.Expr.konst value => Aiur.NativeAIR.Expr.konst (0 - value) + | value.neg => value + | value => value.neg +PREMISE Aiur.NativeAIR.Expr.frontAdd +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +DEFINITION +fun left right => + match left.constantValue, right.constantValue with + | some a, some b => Aiur.NativeAIR.Expr.konst (a + b) + | some a, none => if (a == 0) = true then right else left.add right + | none, some b => if (b == 0) = true then left else left.add right + | none, none => left.add right +PREMISE Aiur.NativeAIR.Expr.frontSub +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +DEFINITION +fun left right => + match left.constantValue, right.constantValue with + | some a, some b => Aiur.NativeAIR.Expr.konst (a - b) + | none, some b => if (b == 0) = true then left else left.sub right + | some a, none => if (a == 0) = true then right.frontNeg else left.sub right + | none, none => left.sub right +PREMISE Aiur.NativeAIR.Expr.frontMul +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +DEFINITION +fun left right => + match left.constantValue, right.constantValue with + | some a, some b => Aiur.NativeAIR.Expr.konst (a * b) + | some a, none => + if (a == 0) = true then Aiur.NativeAIR.Expr.konst 0 else if (a == 1) = true then right else left.mul right + | none, some b => + if (b == 0) = true then Aiur.NativeAIR.Expr.konst 0 else if (b == 1) = true then left else left.mul right + | none, none => left.mul right +PREMISE Aiur.NativeAIR.EvalLaws.mk +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + (∀ (a b : Aiur.G), ops.konst (a + b) = ops.add (ops.konst a) (ops.konst b)) → + (∀ (a b : Aiur.G), ops.konst (a - b) = ops.sub (ops.konst a) (ops.konst b)) → + (∀ (a b : Aiur.G), ops.konst (a * b) = ops.mul (ops.konst a) (ops.konst b)) → + (∀ (a : Aiur.G), ops.konst (0 - a) = ops.neg (ops.konst a)) → + (∀ (a : W), ops.add a (ops.konst 0) = a) → + (∀ (a : W), ops.add (ops.konst 0) a = a) → + (∀ (a : W), ops.sub a (ops.konst 0) = a) → + (∀ (a : W), ops.sub (ops.konst 0) a = ops.neg a) → + (∀ (a : W), ops.mul a (ops.konst 0) = ops.konst 0) → + (∀ (a : W), ops.mul (ops.konst 0) a = ops.konst 0) → + (∀ (a : W), ops.mul a (ops.konst 1) = a) → + (∀ (a : W), ops.mul (ops.konst 1) a = a) → + (∀ (a : W), ops.neg (ops.neg a) = a) → Aiur.NativeAIR.EvalLaws ops +PREMISE Aiur.NativeAIR.Expr.noConstantNegs +Aiur.NativeAIR.Expr → Bool +DEFINITION +fun x => Aiur.NativeAIR.Expr.brecOn x Aiur.NativeAIR.Expr.noConstantNegs._f +PREMISE Aiur.NativeAIR.RowExpr.mk +Aiur.NativeAIR.Expr → Nat → Aiur.NativeAIR.RowExpr +PREMISE Aiur.NativeAIR.RowExpr.konst +Aiur.G → Aiur.NativeAIR.RowExpr +DEFINITION +fun value => { expr := Aiur.NativeAIR.Expr.konst value, degree := 0 } +PREMISE Aiur.NativeAIR.RowExpr.variable +Aiur.NativeAIR.ColRef → Aiur.NativeAIR.RowExpr +DEFINITION +fun column => { expr := Aiur.NativeAIR.Expr.var column, degree := 1 } +PREMISE Aiur.NativeAIR.RowExpr.add +Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr +DEFINITION +fun left right => { expr := left.expr.frontAdd right.expr, degree := max left.degree right.degree } +PREMISE Aiur.NativeAIR.RowExpr.sub +Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr +DEFINITION +fun left right => { expr := left.expr.frontSub right.expr, degree := max left.degree right.degree } +PREMISE Aiur.NativeAIR.RowExpr.mul +Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr +DEFINITION +fun left right => { expr := left.expr.frontMul right.expr, degree := left.degree + right.degree } +PREMISE Aiur.NativeAIR.RowExpr.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.RowExpr → Option Aiur.AIR.RowValue +DEFINITION +fun values expr => do + let value ← Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values expr.expr + pure { value := value, degree := expr.degree, constant := expr.expr.isConstant } +PREMISE Aiur.NativeAIR.RowExpr.Reflects +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.RowExpr → Aiur.AIR.RowValue → Prop +DEFINITION +fun values expr value => + Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values expr.expr = some value.value ∧ + expr.degree = value.degree ∧ expr.expr.isConstant = value.constant +PREMISE Aiur.NativeAIR.ScalarEmission.mk +Aiur.NativeAIR.RowExpr → Nat → List Aiur.NativeAIR.Expr → Aiur.NativeAIR.ScalarEmission +PREMISE Aiur.NativeAIR.ScalarEmission.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.ScalarEmission → Option Aiur.AIR.OpEmission +DEFINITION +fun values emission => do + let output ← Aiur.NativeAIR.RowExpr.eval values emission.output + let equations ← List.mapM (Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values) emission.equations + pure { outputs := #[output], used := emission.used, equations := equations } +PREMISE Aiur.NativeAIR.mainCurrent +Nat → Aiur.NativeAIR.RowExpr +DEFINITION +fun index => + Aiur.NativeAIR.RowExpr.variable + { source := Aiur.NativeAIR.Source.main, offset := Aiur.NativeAIR.RowOffset.current, index := index } +PREMISE Aiur.NativeAIR.eqZeroRegular +Aiur.NativeAIR.Expr → Nat → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.ScalarEmission +DEFINITION +fun selector first input => + have d := Aiur.NativeAIR.mainCurrent first; + have x := Aiur.NativeAIR.mainCurrent (first + 1); + { output := x, used := 2, + equations := + [(selector.frontMul input.expr).frontMul x.expr, + selector.frontMul (((input.expr.frontMul d.expr).frontAdd x.expr).frontSub (Aiur.NativeAIR.Expr.konst 1))] } +PREMISE Aiur.NativeAIR.emitEqZero +Aiur.NativeAIR.Expr → Nat → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.ScalarEmission +DEFINITION +fun selector first input => + match input.expr.constantValue, input.degree with + | some value, 0 => { output := Aiur.NativeAIR.RowExpr.konst value.eqZero } + | x, x_1 => Aiur.NativeAIR.eqZeroRegular selector first input +PREMISE Aiur.NativeAIR.mulRegular +Aiur.NativeAIR.Expr → Nat → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.ScalarEmission +DEFINITION +fun selector first product => + have output := Aiur.NativeAIR.mainCurrent first; + { output := output, used := 1, equations := [selector.frontMul (output.expr.frontSub product.expr)] } +PREMISE Aiur.NativeAIR.emitMul +Aiur.NativeAIR.Expr → Nat → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.ScalarEmission +DEFINITION +fun selector first left right => + have product := left.mul right; + if product.degree < 2 then { output := product } else Aiur.NativeAIR.mulRegular selector first product +PREMISE Aiur.NativeAIR.GraphEvalLaws.mk +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W}, + Aiur.NativeAIR.EvalLaws ops → + (∀ (a b : W), ops.add a b = ops.add b a) → + (∀ (a b : W), ops.mul a b = ops.mul b a) → + (∀ (a : W), ops.sub a a = ops.konst 0) → Aiur.NativeAIR.GraphEvalLaws ops +PREMISE Aiur.NativeAIR.Compiler.Extends +{W : Type u_1} → Array W → Array W → Prop +DEFINITION +fun {W} before after => ∀ (index : Nat) (value : W), before[index]? = some value → after[index]? = some value +PREMISE Aiur.NativeAIR.Compiler.Evaluation.mk +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {nodes : List Aiur.NativeAIR.Node} + {buffer : Array W}, + buffer.size = nodes.length → + Aiur.NativeAIR.sweepFrom ops values nodes #[] = some buffer → + (∀ (index : Nat) (node : Aiur.NativeAIR.Node), + nodes[index]? = some node → Aiur.NativeAIR.Node.eval ops values buffer node = buffer[index]?) → + Aiur.NativeAIR.Compiler.Evaluation ops values nodes buffer +PREMISE Aiur.NativeAIR.Compiler.intern +List Aiur.NativeAIR.Node → Aiur.NativeAIR.Node → List Aiur.NativeAIR.Node × Nat +DEFINITION +fun nodes node => + match List.findIdx? (fun old => decide (old = node)) nodes with + | some index => (nodes, index) + | none => (nodes ++ [node], nodes.length) +PREMISE Aiur.NativeAIR.Compiler.asConst +List Aiur.NativeAIR.Node → Nat → Option Aiur.G +DEFINITION +fun nodes index => + match nodes[index]? with + | some (Aiur.NativeAIR.Node.konst value) => some value + | x => none +PREMISE Aiur.NativeAIR.Compiler.Result +{W : Type u_1} → + Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Array W → List Aiur.NativeAIR.Node × Nat → W → Prop +DEFINITION +fun {W} ops values before result value => + ∃ after, + Aiur.NativeAIR.Compiler.Evaluation ops values result.fst after ∧ + Aiur.NativeAIR.Compiler.Extends before after ∧ after[result.snd]? = some value +PREMISE Aiur.NativeAIR.Compiler.neg +List Aiur.NativeAIR.Node → Nat → List Aiur.NativeAIR.Node × Nat +DEFINITION +fun nodes a => + match Aiur.NativeAIR.Compiler.asConst nodes a with + | some value => Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.konst (0 - value)) + | none => + match nodes[a]? with + | some (Aiur.NativeAIR.Node.neg inner) => (nodes, inner) + | x => Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.neg a) +PREMISE Aiur.NativeAIR.Compiler.sortedAdd +List Aiur.NativeAIR.Node → Nat → Nat → List Aiur.NativeAIR.Node × Nat +DEFINITION +fun nodes a b => + Aiur.NativeAIR.Compiler.intern nodes (if a ≤ b then Aiur.NativeAIR.Node.add a b else Aiur.NativeAIR.Node.add b a) +PREMISE Aiur.NativeAIR.Compiler.sortedMul +List Aiur.NativeAIR.Node → Nat → Nat → List Aiur.NativeAIR.Node × Nat +DEFINITION +fun nodes a b => + Aiur.NativeAIR.Compiler.intern nodes (if a ≤ b then Aiur.NativeAIR.Node.mul a b else Aiur.NativeAIR.Node.mul b a) +PREMISE Aiur.NativeAIR.Compiler.add +List Aiur.NativeAIR.Node → Nat → Nat → List Aiur.NativeAIR.Node × Nat +DEFINITION +fun nodes a b => + match Aiur.NativeAIR.Compiler.asConst nodes a, Aiur.NativeAIR.Compiler.asConst nodes b with + | some x, some y => Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.konst (x + y)) + | some x, none => if (x == 0) = true then (nodes, b) else Aiur.NativeAIR.Compiler.sortedAdd nodes a b + | none, some y => if (y == 0) = true then (nodes, a) else Aiur.NativeAIR.Compiler.sortedAdd nodes a b + | none, none => Aiur.NativeAIR.Compiler.sortedAdd nodes a b +PREMISE Aiur.NativeAIR.Compiler.sub +List Aiur.NativeAIR.Node → Nat → Nat → List Aiur.NativeAIR.Node × Nat +DEFINITION +fun nodes a b => + if a = b then Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.konst 0) + else + match Aiur.NativeAIR.Compiler.asConst nodes a, Aiur.NativeAIR.Compiler.asConst nodes b with + | some x, some y => Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.konst (x - y)) + | none, some y => + if (y == 0) = true then (nodes, a) else Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.sub a b) + | some x, none => + if (x == 0) = true then Aiur.NativeAIR.Compiler.neg nodes b + else Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.sub a b) + | none, none => Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.sub a b) +PREMISE Aiur.NativeAIR.Compiler.mul +List Aiur.NativeAIR.Node → Nat → Nat → List Aiur.NativeAIR.Node × Nat +DEFINITION +fun nodes a b => + match Aiur.NativeAIR.Compiler.asConst nodes a, Aiur.NativeAIR.Compiler.asConst nodes b with + | some x, some y => Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.konst (x * y)) + | some x, none => + if (x == 0) = true then (nodes, a) + else if (x == 1) = true then (nodes, b) else Aiur.NativeAIR.Compiler.sortedMul nodes a b + | none, some y => + if (y == 0) = true then (nodes, b) + else if (y == 1) = true then (nodes, a) else Aiur.NativeAIR.Compiler.sortedMul nodes a b + | none, none => Aiur.NativeAIR.Compiler.sortedMul nodes a b +PREMISE Aiur.NativeAIR.Compiler.compileExpr +Aiur.NativeAIR.GraphWidths → + Bool → Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × Nat) +DEFINITION +fun widths allowStage2 x x_1 => + Aiur.NativeAIR.Expr.brecOn (motive := fun x => List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × Nat)) x + (Aiur.NativeAIR.Compiler.compileExpr._f widths allowStage2) x_1 +PREMISE Aiur.NativeAIR.Compiler.compileExprs +Aiur.NativeAIR.GraphWidths → + Bool → List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Nat) +DEFINITION +fun widths allowStage2 x x_1 => + List.brecOn (motive := fun x => List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Nat)) x + (Aiur.NativeAIR.Compiler.compileExprs._f widths allowStage2) x_1 +PREMISE Aiur.NativeAIR.Compiler.RootsReflect.nil +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {buffer : Array W}, + Aiur.NativeAIR.Compiler.RootsReflect ops values buffer [] [] +PREMISE Aiur.NativeAIR.Compiler.RootsReflect.cons +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {buffer : Array W} {root : Nat} + {expr : Aiur.NativeAIR.Expr} {roots : List Nat} {exprs : List Aiur.NativeAIR.Expr}, + (∃ value, Aiur.NativeAIR.Expr.eval ops values expr = some value ∧ buffer[root]? = some value) → + Aiur.NativeAIR.Compiler.RootsReflect ops values buffer roots exprs → + Aiur.NativeAIR.Compiler.RootsReflect ops values buffer (root :: roots) (expr :: exprs) +PREMISE Aiur.NativeAIR.Compiler.evalExprs +{W : Type u_1} → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → List Aiur.NativeAIR.Expr → Option (List W) +DEFINITION +fun {W} ops values exprs => List.mapM (Aiur.NativeAIR.Expr.eval ops values) exprs +PREMISE Aiur.NativeAIR.Compiler.ExprLookup.mk +Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr → Aiur.NativeAIR.Compiler.ExprLookup +PREMISE Aiur.NativeAIR.Compiler.ExprLookup.exprs +Aiur.NativeAIR.Compiler.ExprLookup → List Aiur.NativeAIR.Expr +DEFINITION +fun lookup => lookup.multiplicity :: lookup.args +PREMISE Aiur.NativeAIR.Compiler.ExprLookup.eval +{W : Type u_1} → + Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Aiur.NativeAIR.Compiler.ExprLookup → Option (W × List W) +DEFINITION +fun {W} ops values lookup => do + let multiplicity ← Aiur.NativeAIR.Expr.eval ops values lookup.multiplicity + let args ← Aiur.NativeAIR.Compiler.evalExprs ops values lookup.args + pure (multiplicity, args) +PREMISE Aiur.NativeAIR.Compiler.compileLookup +Aiur.NativeAIR.GraphWidths → + Aiur.NativeAIR.Compiler.ExprLookup → + List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × Aiur.NativeAIR.Lookup) +DEFINITION +fun widths lookup nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileExprs widths false lookup.exprs nodes + match __x with + | (nodes, roots) => + match roots with + | [] => none + | root :: roots => pure (nodes, { multiplicity := root, args := roots }) +PREMISE Aiur.NativeAIR.Compiler.compileLookups +Aiur.NativeAIR.GraphWidths → + List Aiur.NativeAIR.Compiler.ExprLookup → + List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Aiur.NativeAIR.Lookup) +DEFINITION +fun widths x x_1 => + List.brecOn (motive := fun x => + List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Aiur.NativeAIR.Lookup)) x + (Aiur.NativeAIR.Compiler.compileLookups._f widths) x_1 +PREMISE Aiur.NativeAIR.Compiler.LookupsReflect.nil +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {buffer : Array W}, + Aiur.NativeAIR.Compiler.LookupsReflect ops values buffer [] [] +PREMISE Aiur.NativeAIR.Compiler.LookupsReflect.cons +∀ {W : Type u_1} {ops : Aiur.NativeAIR.EvalOps W} {values : Aiur.NativeAIR.Values W} {buffer : Array W} + {lookup : Aiur.NativeAIR.Lookup} {expr : Aiur.NativeAIR.Compiler.ExprLookup} {lookups : List Aiur.NativeAIR.Lookup} + {exprs : List Aiur.NativeAIR.Compiler.ExprLookup}, + Aiur.NativeAIR.Compiler.RootsReflect ops values buffer lookup.roots expr.exprs → + Aiur.NativeAIR.Compiler.LookupsReflect ops values buffer lookups exprs → + Aiur.NativeAIR.Compiler.LookupsReflect ops values buffer (lookup :: lookups) (expr :: exprs) +PREMISE Aiur.NativeAIR.Compiler.recordZero +List Aiur.NativeAIR.Node → Nat → Option (List Nat) +DEFINITION +fun nodes root => + match Aiur.NativeAIR.Compiler.asConst nodes root with + | none => some [root] + | some value => if (value == 0) = true then some [] else none +PREMISE Aiur.NativeAIR.Compiler.Vanishes +{W : Type u_1} → Aiur.NativeAIR.EvalOps W → Array W → List Nat → Prop +DEFINITION +fun {W} ops buffer roots => ∀ (root : Nat), root ∈ roots → buffer[root]? = some (ops.konst 0) +PREMISE Aiur.NativeAIR.Compiler.ExprsVanish +{W : Type u_1} → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → List Aiur.NativeAIR.Expr → Prop +DEFINITION +fun {W} ops values exprs => + ∀ (expr : Aiur.NativeAIR.Expr), expr ∈ exprs → Aiur.NativeAIR.Expr.eval ops values expr = some (ops.konst 0) +PREMISE Aiur.NativeAIR.Compiler.compileZeros +Aiur.NativeAIR.GraphWidths → + List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Nat) +DEFINITION +fun widths x x_1 => + List.brecOn (motive := fun x => List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Nat)) x + (Aiur.NativeAIR.Compiler.compileZeros._f widths) x_1 +PREMISE Aiur.NativeAIR.Compiler.canonicalZeros +List Nat → List Nat +DEFINITION +fun roots => (roots.mergeSort fun x1 x2 => decide (x1 ≤ x2)).eraseDups +PREMISE Aiur.NativeAIR.Compiler.BaseCompilation.mk +Aiur.NativeAIR.Graph → Nat → Aiur.NativeAIR.Compiler.BaseCompilation +PREMISE Aiur.NativeAIR.Compiler.compileBase +Aiur.NativeAIR.GraphWidths → + List Aiur.NativeAIR.Compiler.ExprLookup → List Aiur.NativeAIR.Expr → Option Aiur.NativeAIR.Compiler.BaseCompilation +DEFINITION +fun widths lookups constraints => do + let __x ← Aiur.NativeAIR.Compiler.compileLookups widths lookups [] + match __x with + | (lookupNodes, lookups) => do + let __x ← Aiur.NativeAIR.Compiler.compileZeros widths constraints lookupNodes + match __x with + | (nodes, zeros) => + pure + { graph := { nodes := nodes, zeros := Aiur.NativeAIR.Compiler.canonicalZeros zeros, lookups := lookups }, + lookupEnd := lookupNodes.length } +PREMISE Aiur.NativeAIR.OpEmitter.evalExpr +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.Expr → Option Aiur.G +DEFINITION +fun values => Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values +PREMISE Aiur.NativeAIR.OpEmitter.evalRows +Aiur.NativeAIR.Values Aiur.G → Array Aiur.NativeAIR.RowExpr → Option (Array Aiur.AIR.RowValue) +DEFINITION +fun values rows => Array.mapM (Aiur.NativeAIR.RowExpr.eval values) rows +PREMISE Aiur.NativeAIR.OpEmitter.rowExprs +Array Aiur.NativeAIR.RowExpr → Array Aiur.NativeAIR.Expr +DEFINITION +fun rows => Array.map Aiur.NativeAIR.RowExpr.expr rows +PREMISE Aiur.NativeAIR.OpEmitter.Normal +Array Aiur.NativeAIR.RowExpr → Prop +DEFINITION +fun rows => ∀ (row : Aiur.NativeAIR.RowExpr), row ∈ rows → row.expr.noConstantNegs = true +PREMISE Aiur.NativeAIR.OpEmitter.select +Array Aiur.NativeAIR.RowExpr → Array Nat → Option (Array Aiur.NativeAIR.RowExpr) +DEFINITION +fun rows indices => Array.mapM (fun index => rows[index]?) indices +PREMISE Aiur.NativeAIR.OpEmitter.advice +Nat → Nat → Array Aiur.NativeAIR.RowExpr +DEFINITION +fun first count => Array.ofFn fun index => Aiur.NativeAIR.mainCurrent (first + ↑index) +PREMISE Aiur.NativeAIR.OpEmitter.CallExpr.mk +Nat → + Array Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → (Fin 6 → Aiur.NativeAIR.Expr) → Aiur.NativeAIR.OpEmitter.CallExpr +PREMISE Aiur.NativeAIR.OpEmitter.CallExpr.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.OpEmitter.CallExpr → Option (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) +DEFINITION +fun values call => do + let inputs ← Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) call.inputs + let outputs ← Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) call.outputs + let rank ← Aiur.NativeAIR.Expr.eval Aiur.NativeAIR.goldilocksOps values call.rank + let gap ← Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (Array.ofFn call.gap) + pure + ({ function := call.function, inputs := inputs, outputs := outputs, rank := rank }, fun index => + gap[↑index]?.getD 0) +PREMISE Aiur.NativeAIR.OpEmitter.Emission.mk +Array Aiur.NativeAIR.RowExpr → + Nat → + List Aiur.NativeAIR.Expr → + List (List Aiur.NativeAIR.Expr) → List Aiur.NativeAIR.OpEmitter.CallExpr → Aiur.NativeAIR.OpEmitter.Emission +PREMISE Aiur.NativeAIR.OpEmitter.Emission.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.OpEmitter.Emission → Option Aiur.AIR.OpEmission +DEFINITION +fun values emission => do + let outputs ← Aiur.NativeAIR.OpEmitter.evalRows values emission.outputs + let equations ← List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations + let queries ← List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) emission.queries + let calls ← List.mapM (Aiur.NativeAIR.OpEmitter.CallExpr.eval values) emission.calls + pure { outputs := outputs, used := emission.used, equations := equations, queries := queries, calls := calls } +PREMISE Aiur.NativeAIR.OpEmitter.fromScalar +Aiur.NativeAIR.ScalarEmission → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun emission => { outputs := #[emission.output], used := emission.used, equations := emission.equations } +PREMISE Aiur.NativeAIR.OpEmitter.emitAdvice +Nat → Nat → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun first count => { outputs := Aiur.NativeAIR.OpEmitter.advice first count, used := count } +PREMISE Aiur.NativeAIR.OpEmitter.emitByte1 +Nat → Aiur.AIR.Byte1Kind → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun first kind input => + have outputs := Aiur.NativeAIR.OpEmitter.advice first kind.outputSize; + { outputs := outputs, used := kind.outputSize, + queries := + [[Aiur.NativeAIR.Expr.konst kind.channel, input.expr] ++ (Aiur.NativeAIR.OpEmitter.rowExprs outputs).toList] } +PREMISE Aiur.NativeAIR.OpEmitter.byteCarry +Nat → Bool → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr +DEFINITION +fun first subtract left right => + have low := (Aiur.NativeAIR.mainCurrent first).expr; + have numerator := + if subtract = true then (low.frontAdd right.expr).frontSub left.expr + else (left.expr.frontAdd right.expr).frontSub low; + { expr := numerator.frontMul (Aiur.NativeAIR.Expr.konst Aiur.AIR.inverse256), + degree := max (max left.degree right.degree) 1 } +PREMISE Aiur.NativeAIR.OpEmitter.emitByte2 +Nat → Aiur.AIR.Byte2Kind → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun first kind left right => + have allocated := Aiur.NativeAIR.OpEmitter.advice first kind.outputSize; + have outputs := + match kind with + | Aiur.AIR.Byte2Kind.add => allocated.push (Aiur.NativeAIR.OpEmitter.byteCarry first false left right) + | Aiur.AIR.Byte2Kind.sub => allocated.push (Aiur.NativeAIR.OpEmitter.byteCarry first true left right) + | x => allocated; + { outputs := outputs, used := kind.outputSize, + queries := + [[Aiur.NativeAIR.Expr.konst kind.channel, left.expr, right.expr] ++ + (Aiur.NativeAIR.OpEmitter.rowExprs allocated).toList] } +PREMISE Aiur.NativeAIR.OpEmitter.packFour +(Fin 4 → Aiur.NativeAIR.RowExpr) → Aiur.NativeAIR.RowExpr +DEFINITION +fun bytes => + ((((Aiur.NativeAIR.RowExpr.konst 0).add ((bytes 0).mul (Aiur.NativeAIR.RowExpr.konst (Aiur.G.ofNat (256 ^ 0))))).add + ((bytes 1).mul (Aiur.NativeAIR.RowExpr.konst (Aiur.G.ofNat (256 ^ 1))))).add + ((bytes 2).mul (Aiur.NativeAIR.RowExpr.konst (Aiur.G.ofNat (256 ^ 2))))).add + ((bytes 3).mul (Aiur.NativeAIR.RowExpr.konst (Aiur.G.ofNat (256 ^ 3)))) +PREMISE Aiur.NativeAIR.OpEmitter.readWord +Array Aiur.NativeAIR.RowExpr → Array Nat → Option Aiur.NativeAIR.RowExpr +DEFINITION +fun rows indices => + if indices.size ≠ 4 then none + else do + let bytes ← Aiur.NativeAIR.OpEmitter.select rows indices + pure (Aiur.NativeAIR.OpEmitter.packFour fun index => bytes[↑index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)) +PREMISE Aiur.NativeAIR.OpEmitter.packedAdvice +Nat → Aiur.NativeAIR.RowExpr +DEFINITION +fun first => Aiur.NativeAIR.OpEmitter.packFour fun index => Aiur.NativeAIR.mainCurrent (first + ↑index) +PREMISE Aiur.NativeAIR.OpEmitter.emitWordSum +Nat → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun first sum => + have packed := Aiur.NativeAIR.OpEmitter.packedAdvice first; + { + outputs := + (Aiur.NativeAIR.OpEmitter.advice first 4).push + ((sum.sub packed).mul (Aiur.NativeAIR.RowExpr.konst 18446744065119617026)), + used := 4 } +PREMISE Aiur.NativeAIR.OpEmitter.carryStep +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +DEFINITION +fun x y z previous => + (((x.frontAdd y).frontAdd previous).frontSub z).frontMul (Aiur.NativeAIR.Expr.konst Aiur.AIR.inverse256) +PREMISE Aiur.NativeAIR.OpEmitter.carries +(Fin 4 → Aiur.NativeAIR.Expr) → + (Fin 4 → Aiur.NativeAIR.Expr) → (Fin 4 → Aiur.NativeAIR.Expr) → Fin 5 → Aiur.NativeAIR.Expr +DEFINITION +fun x y z => + have c1 := Aiur.NativeAIR.OpEmitter.carryStep (x 0) (y 0) (z 0) (Aiur.NativeAIR.Expr.konst 1); + have c2 := Aiur.NativeAIR.OpEmitter.carryStep (x 1) (y 1) (z 1) c1; + have c3 := Aiur.NativeAIR.OpEmitter.carryStep (x 2) (y 2) (z 2) c2; + have c4 := Aiur.NativeAIR.OpEmitter.carryStep (x 3) (y 3) (z 3) c3; + fun index => + match index with + | 0 => Aiur.NativeAIR.Expr.konst 1 + | 1 => c1 + | 2 => c2 + | 3 => c3 + | 4 => c4 +PREMISE Aiur.NativeAIR.OpEmitter.packSix +(Fin 6 → Aiur.NativeAIR.Expr) → Aiur.NativeAIR.Expr +DEFINITION +fun bytes => + ((((((Aiur.NativeAIR.Expr.konst 0).frontAdd ((bytes 0).frontMul (Aiur.NativeAIR.Expr.konst 1))).frontAdd + ((bytes 1).frontMul (Aiur.NativeAIR.Expr.konst 256))).frontAdd + ((bytes 2).frontMul (Aiur.NativeAIR.Expr.konst 65536))).frontAdd + ((bytes 3).frontMul (Aiur.NativeAIR.Expr.konst 16777216))).frontAdd + ((bytes 4).frontMul (Aiur.NativeAIR.Expr.konst 4294967296))).frontAdd + ((bytes 5).frontMul (Aiur.NativeAIR.Expr.konst 1099511627776)) +PREMISE Aiur.NativeAIR.OpEmitter.rangePair +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr +DEFINITION +fun left right => [Aiur.NativeAIR.Expr.konst 11, left, right] +PREMISE Aiur.NativeAIR.OpEmitter.rangeSix +(Fin 6 → Aiur.NativeAIR.Expr) → List (List Aiur.NativeAIR.Expr) +DEFINITION +fun bytes => + [Aiur.NativeAIR.OpEmitter.rangePair (bytes 0) (bytes 1), Aiur.NativeAIR.OpEmitter.rangePair (bytes 2) (bytes 3), + Aiur.NativeAIR.OpEmitter.rangePair (bytes 4) (bytes 5)] +PREMISE Aiur.NativeAIR.OpEmitter.emitCall +Aiur.NativeAIR.Expr → + Aiur.NativeAIR.Expr → Nat → Nat → Array Aiur.NativeAIR.RowExpr → Nat → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun _selector rank first function inputs size => + have outputs := Aiur.NativeAIR.OpEmitter.advice first size; + have gap := fun index => (Aiur.NativeAIR.mainCurrent (first + size + ↑index)).expr; + have child := (rank.frontAdd (Aiur.NativeAIR.Expr.konst 1)).frontAdd (Aiur.NativeAIR.OpEmitter.packSix gap); + { outputs := outputs, used := size + 6, + queries := + ([Aiur.NativeAIR.Expr.konst 0, Aiur.NativeAIR.Expr.konst (Aiur.G.ofNat function)] ++ + (Aiur.NativeAIR.OpEmitter.rowExprs inputs).toList ++ + (Aiur.NativeAIR.OpEmitter.rowExprs outputs).toList ++ + [child]) :: + Aiur.NativeAIR.OpEmitter.rangeSix gap, + calls := + [{ function := function, inputs := Aiur.NativeAIR.OpEmitter.rowExprs inputs, + outputs := Aiur.NativeAIR.OpEmitter.rowExprs outputs, rank := child, gap := gap }] } +PREMISE Aiur.NativeAIR.OpEmitter.emitStore +Nat → Array Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun first contents => + { outputs := Aiur.NativeAIR.OpEmitter.advice first 1, used := 1, + queries := + [[Aiur.NativeAIR.Expr.konst 1, Aiur.NativeAIR.Expr.konst (Aiur.G.ofNat contents.size), + (Aiur.NativeAIR.mainCurrent first).expr] ++ + (Aiur.NativeAIR.OpEmitter.rowExprs contents).toList] } +PREMISE Aiur.NativeAIR.OpEmitter.emitLoad +Nat → Nat → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun first size pointer => + have outputs := Aiur.NativeAIR.OpEmitter.advice first size; + { outputs := outputs, used := size, + queries := + [[Aiur.NativeAIR.Expr.konst 1, Aiur.NativeAIR.Expr.konst (Aiur.G.ofNat size), pointer.expr] ++ + (Aiur.NativeAIR.OpEmitter.rowExprs outputs).toList] } +PREMISE Aiur.NativeAIR.OpEmitter.rangeFour +(Fin 4 → Aiur.NativeAIR.Expr) → List (List Aiur.NativeAIR.Expr) +DEFINITION +fun bytes => + [Aiur.NativeAIR.OpEmitter.rangePair (bytes 0) (bytes 1), Aiur.NativeAIR.OpEmitter.rangePair (bytes 2) (bytes 3)] +PREMISE Aiur.NativeAIR.OpEmitter.booleanExpr +Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +DEFINITION +fun expr => expr.frontMul (expr.frontSub (Aiur.NativeAIR.Expr.konst 1)) +PREMISE Aiur.NativeAIR.OpEmitter.emitU32LessThan +Aiur.NativeAIR.Expr → Nat → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun selector first left right => + have x := fun index => (Aiur.NativeAIR.mainCurrent (first + ↑index)).expr; + have y := fun index => (Aiur.NativeAIR.mainCurrent (first + 4 + ↑index)).expr; + have z := fun index => (Aiur.NativeAIR.mainCurrent (first + 8 + ↑index)).expr; + have chain := Aiur.NativeAIR.OpEmitter.carries x y z; + { outputs := #[{ expr := (Aiur.NativeAIR.Expr.konst 1).frontSub (chain 4), degree := 1 }], used := 12, + equations := + selector.frontMul (left.expr.frontSub (Aiur.NativeAIR.OpEmitter.packedAdvice first).expr) :: + selector.frontMul (right.expr.frontSub (Aiur.NativeAIR.OpEmitter.packedAdvice (first + 8)).expr) :: + List.ofFn fun index => selector.frontMul (Aiur.NativeAIR.OpEmitter.booleanExpr (chain index.succ)), + queries := + Aiur.NativeAIR.OpEmitter.rangeFour x ++ Aiur.NativeAIR.OpEmitter.rangeFour y ++ + Aiur.NativeAIR.OpEmitter.rangeFour z } +PREMISE Aiur.NativeAIR.OpEmitter.emitAssert +Aiur.NativeAIR.Expr → Array Aiur.NativeAIR.RowExpr → Array Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun selector left right => + { + equations := + List.ofFn fun index => + selector.frontMul + ((left[↑index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)).expr.frontSub + (right[↑index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)).expr) } +PREMISE Aiur.NativeAIR.OpEmitter.emitOp +Aiur.NativeAIR.Expr → + Aiur.NativeAIR.Expr → Nat → Aiur.Bytecode.Op → Array Aiur.NativeAIR.RowExpr → Option Aiur.NativeAIR.OpEmitter.Emission +DEFINITION +fun selector rank first op rows => + match op with + | Aiur.Bytecode.Op.const value => + some (Aiur.NativeAIR.OpEmitter.fromScalar { output := Aiur.NativeAIR.RowExpr.konst value }) + | Aiur.Bytecode.Op.add a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.fromScalar { output := __do_lift.add __do_lift_1 }) + | Aiur.Bytecode.Op.sub a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.fromScalar { output := __do_lift.sub __do_lift_1 }) + | Aiur.Bytecode.Op.mul a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.fromScalar (Aiur.NativeAIR.emitMul selector first __do_lift __do_lift_1)) + | Aiur.Bytecode.Op.eqZero a => do + let __do_lift ← rows[a]? + pure (Aiur.NativeAIR.OpEmitter.fromScalar (Aiur.NativeAIR.emitEqZero selector first __do_lift)) + | Aiur.Bytecode.Op.call function indices size unconstrained => + if unconstrained = true then some (Aiur.NativeAIR.OpEmitter.emitAdvice first size) + else do + let __do_lift ← Aiur.NativeAIR.OpEmitter.select rows indices + pure (Aiur.NativeAIR.OpEmitter.emitCall selector rank first function __do_lift size) + | Aiur.Bytecode.Op.store indices => do + let __do_lift ← Aiur.NativeAIR.OpEmitter.select rows indices + pure (Aiur.NativeAIR.OpEmitter.emitStore first __do_lift) + | Aiur.Bytecode.Op.load size index => do + let __do_lift ← rows[index]? + pure (Aiur.NativeAIR.OpEmitter.emitLoad first size __do_lift) + | Aiur.Bytecode.Op.assertEq xs ys a => + if xs.size ≠ ys.size then none + else do + let __do_lift ← Aiur.NativeAIR.OpEmitter.select rows xs + let __do_lift_1 ← Aiur.NativeAIR.OpEmitter.select rows ys + pure (Aiur.NativeAIR.OpEmitter.emitAssert selector __do_lift __do_lift_1) + | Aiur.Bytecode.Op.ioGetInfo a a_1 => some (Aiur.NativeAIR.OpEmitter.emitAdvice first 2) + | Aiur.Bytecode.Op.ioRead a a_1 size => some (Aiur.NativeAIR.OpEmitter.emitAdvice first size) + | Aiur.Bytecode.Op.ioSetInfo a a_1 a_2 a_3 => some { } + | Aiur.Bytecode.Op.ioWrite a a_1 => some { } + | Aiur.Bytecode.Op.debug a a_1 => some { } + | Aiur.Bytecode.Op.u8BitDecomposition index => do + let __do_lift ← rows[index]? + pure (Aiur.NativeAIR.OpEmitter.emitByte1 first Aiur.AIR.Byte1Kind.bits __do_lift) + | Aiur.Bytecode.Op.u8ShiftLeft index => do + let __do_lift ← rows[index]? + pure (Aiur.NativeAIR.OpEmitter.emitByte1 first Aiur.AIR.Byte1Kind.shiftLeft __do_lift) + | Aiur.Bytecode.Op.u8ShiftRight index => do + let __do_lift ← rows[index]? + pure (Aiur.NativeAIR.OpEmitter.emitByte1 first Aiur.AIR.Byte1Kind.shiftRight __do_lift) + | Aiur.Bytecode.Op.u8Xor a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.xor __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8Add a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.add __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8Sub a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.sub __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8And a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.and __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8Or a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.or __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8LessThan a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.lessThan __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8RangeCheck a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.range __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8Mul a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.mul __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8XorSplit7 a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.split7 __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u8XorSplit4 a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitByte2 first Aiur.AIR.Byte2Kind.split4 __do_lift __do_lift_1) + | Aiur.Bytecode.Op.u32LessThan a b => do + let __do_lift ← rows[a]? + let __do_lift_1 ← rows[b]? + pure (Aiur.NativeAIR.OpEmitter.emitU32LessThan selector first __do_lift __do_lift_1) + | Aiur.Bytecode.Op.unconstrainedBigUintDivMod a a_1 => some (Aiur.NativeAIR.OpEmitter.emitAdvice first 2) + | Aiur.Bytecode.Op.unconstrainedGToBytes a => some (Aiur.NativeAIR.OpEmitter.emitAdvice first 8) + | Aiur.Bytecode.Op.unconstrainedGInverse a => some (Aiur.NativeAIR.OpEmitter.emitAdvice first 1) + | Aiur.Bytecode.Op.unconstrainedU32Add a b => do + let __do_lift ← Aiur.NativeAIR.OpEmitter.readWord rows a + let __do_lift_1 ← Aiur.NativeAIR.OpEmitter.readWord rows b + pure (Aiur.NativeAIR.OpEmitter.emitWordSum first (__do_lift.add __do_lift_1)) + | Aiur.Bytecode.Op.unconstrainedU32Add3 a b c => do + let __do_lift ← Aiur.NativeAIR.OpEmitter.readWord rows a + let __do_lift_1 ← Aiur.NativeAIR.OpEmitter.readWord rows b + let __do_lift_2 ← Aiur.NativeAIR.OpEmitter.readWord rows c + pure (Aiur.NativeAIR.OpEmitter.emitWordSum first ((__do_lift.add __do_lift_1).add __do_lift_2)) + | Aiur.Bytecode.Op.u32ToField indices => do + let __do_lift ← Aiur.NativeAIR.OpEmitter.readWord rows indices + pure (Aiur.NativeAIR.OpEmitter.fromScalar { output := __do_lift }) +PREMISE Aiur.NativeAIR.OpEmitter.OpsEmission.mk +Array Aiur.NativeAIR.RowExpr → + Nat → + List Aiur.NativeAIR.Expr → + List (List Aiur.NativeAIR.Expr) → List Aiur.NativeAIR.OpEmitter.CallExpr → Aiur.NativeAIR.OpEmitter.OpsEmission +PREMISE Aiur.NativeAIR.OpEmitter.OpsEmission.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.OpEmitter.OpsEmission → Option Aiur.AIR.OpsEmission +DEFINITION +fun values emission => do + let outputs ← Aiur.NativeAIR.OpEmitter.evalRows values emission.values + let equations ← List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations + let queries ← List.mapM (List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values)) emission.queries + let calls ← List.mapM (Aiur.NativeAIR.OpEmitter.CallExpr.eval values) emission.calls + pure { values := outputs, column := emission.column, equations := equations, queries := queries, calls := calls } +PREMISE Aiur.NativeAIR.OpEmitter.emitOps +Aiur.NativeAIR.Expr → + Aiur.NativeAIR.Expr → + List Aiur.Bytecode.Op → Array Aiur.NativeAIR.RowExpr → Nat → Option Aiur.NativeAIR.OpEmitter.OpsEmission +DEFINITION +fun selector rank x x_1 x_2 => + List.brecOn (motive := fun x => Array Aiur.NativeAIR.RowExpr → Nat → Option Aiur.NativeAIR.OpEmitter.OpsEmission) x + (Aiur.NativeAIR.OpEmitter.emitOps._f selector rank) x_1 x_2 +PREMISE Aiur.NativeAIR.LookupEmitter.addArgs +List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr +DEFINITION +fun x x_1 => + List.brecOn (motive := fun x => List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr) x + Aiur.NativeAIR.LookupEmitter.addArgs._f x_1 +PREMISE Aiur.NativeAIR.LookupEmitter.gateArgs +Bool → Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr +DEFINITION +fun branchless selector args => if branchless = true then args else List.map selector.frontMul args +PREMISE Aiur.NativeAIR.LookupEmitter.QueryExpr.mk +Nat → Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr → Aiur.NativeAIR.LookupEmitter.QueryExpr +PREMISE Aiur.NativeAIR.LookupEmitter.QueryExpr.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.LookupEmitter.QueryExpr → Option Aiur.AIR.QueryPart +DEFINITION +fun values query => do + let selector ← Aiur.NativeAIR.OpEmitter.evalExpr values query.selector + let message ← List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) query.message + pure { slot := query.slot, selector := selector, message := message } +PREMISE Aiur.NativeAIR.LookupEmitter.queryParts +Nat → Aiur.NativeAIR.Expr → List (List Aiur.NativeAIR.Expr) → List Aiur.NativeAIR.LookupEmitter.QueryExpr +DEFINITION +fun slot selector queries => + List.mapIdx (fun index message => { slot := slot + index, selector := selector, message := message }) queries +PREMISE Aiur.NativeAIR.LookupEmitter.accumulate +Bool → Aiur.NativeAIR.Compiler.ExprLookup → Aiur.NativeAIR.LookupEmitter.QueryExpr → Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun branchless lookup query => + { multiplicity := lookup.multiplicity.frontAdd query.selector, + args := + Aiur.NativeAIR.LookupEmitter.addArgs lookup.args + (Aiur.NativeAIR.LookupEmitter.gateArgs branchless query.selector query.message) } +PREMISE Aiur.NativeAIR.LookupEmitter.valuedAccumulate +Bool → Aiur.G × List Aiur.G → Aiur.AIR.QueryPart → Aiur.G × List Aiur.G +DEFINITION +fun branchless lookup query => + (lookup.fst + query.selector, + Aiur.AIR.addMessages lookup.snd (Aiur.AIR.gateMessage branchless query.selector query.message)) +PREMISE Aiur.NativeAIR.LookupEmitter.slot +Bool → List Aiur.NativeAIR.LookupEmitter.QueryExpr → Nat → Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun branchless queries index => + List.foldl (Aiur.NativeAIR.LookupEmitter.accumulate branchless) + { multiplicity := Aiur.NativeAIR.Expr.konst 0, args := [] } (List.filter (fun query => query.slot == index) queries) +PREMISE Aiur.NativeAIR.LookupEmitter.slots +Bool → List Aiur.NativeAIR.LookupEmitter.QueryExpr → Nat → List Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun branchless queries count => List.ofFn fun index => Aiur.NativeAIR.LookupEmitter.slot branchless queries ↑index +PREMISE Aiur.NativeAIR.BlockEmitter.sum +List Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr +DEFINITION +fun expressions => List.foldl Aiur.NativeAIR.Expr.frontAdd (Aiur.NativeAIR.Expr.konst 0) expressions +PREMISE Aiur.NativeAIR.BlockEmitter.SelectorReads +Aiur.NativeAIR.Values Aiur.G → Array Aiur.NativeAIR.Expr → (Nat → Aiur.G) → Prop +DEFINITION +fun values selectors selector => + ∀ {index : Nat} {expr : Aiur.NativeAIR.Expr}, + selectors[index]? = some expr → Aiur.NativeAIR.OpEmitter.evalExpr values expr = some (selector index) +PREMISE Aiur.NativeAIR.BlockEmitter.ctrlSelector +Array Aiur.NativeAIR.Expr → Aiur.Bytecode.Ctrl → Option Aiur.NativeAIR.Expr +DEFINITION +fun selectors a => Aiur.NativeAIR.BlockEmitter.ctrlSelector._mutual selectors (PSum.inl a) +PREMISE Aiur.NativeAIR.BlockEmitter.blockSelector +Array Aiur.NativeAIR.Expr → Aiur.Bytecode.Block → Option Aiur.NativeAIR.Expr +DEFINITION +fun selectors block => Aiur.NativeAIR.BlockEmitter.ctrlSelector._mutual selectors (PSum.inr block) +PREMISE Aiur.NativeAIR.BlockEmitter.Context.mk +Nat → Nat → Aiur.NativeAIR.Expr → Aiur.NativeAIR.BlockEmitter.Context +PREMISE Aiur.NativeAIR.BlockEmitter.ReturnExpr.mk +Aiur.NativeAIR.Expr → + Nat → + Array Aiur.NativeAIR.Expr → Array Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → Aiur.NativeAIR.BlockEmitter.ReturnExpr +PREMISE Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.BlockEmitter.ReturnExpr → Option (Aiur.G × Aiur.Bytecode.AIR.Call) +DEFINITION +fun values returned => do + let selector ← Aiur.NativeAIR.OpEmitter.evalExpr values returned.selector + let inputs ← Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) returned.inputs + let outputs ← Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) returned.outputs + let rank ← Aiur.NativeAIR.OpEmitter.evalExpr values returned.rank + pure (selector, { function := returned.function, inputs := inputs, outputs := outputs, rank := rank }) +PREMISE Aiur.NativeAIR.BlockEmitter.ReturnExpr.message +Aiur.NativeAIR.BlockEmitter.ReturnExpr → List Aiur.NativeAIR.Expr +DEFINITION +fun returned => + [Aiur.NativeAIR.Expr.konst 0, Aiur.NativeAIR.Expr.konst (Aiur.G.ofNat returned.function)] ++ returned.inputs.toList ++ + returned.outputs.toList ++ + [returned.rank] +PREMISE Aiur.NativeAIR.BlockEmitter.YieldExpr.mk +Aiur.NativeAIR.Expr → Array Aiur.NativeAIR.RowExpr → Aiur.NativeAIR.BlockEmitter.YieldExpr +PREMISE Aiur.NativeAIR.BlockEmitter.YieldExpr.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.BlockEmitter.YieldExpr → Option (Aiur.G × Array Aiur.AIR.RowValue) +DEFINITION +fun values yielded => do + let selector ← Aiur.NativeAIR.OpEmitter.evalExpr values yielded.selector + let outputs ← Aiur.NativeAIR.OpEmitter.evalRows values yielded.values + pure (selector, outputs) +PREMISE Aiur.NativeAIR.BlockEmitter.evalGatedCall +Aiur.NativeAIR.Values Aiur.G → + Aiur.NativeAIR.Expr × Aiur.NativeAIR.OpEmitter.CallExpr → Option (Aiur.G × Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) +DEFINITION +fun values called => do + let selector ← Aiur.NativeAIR.OpEmitter.evalExpr values called.fst + let call ← Aiur.NativeAIR.OpEmitter.CallExpr.eval values called.snd + pure (selector, call) +PREMISE Aiur.NativeAIR.BlockEmitter.Emission.mk +Array Aiur.NativeAIR.RowExpr → + Nat → + Nat → + List Aiur.NativeAIR.Expr → + List Aiur.NativeAIR.LookupEmitter.QueryExpr → + List Aiur.NativeAIR.BlockEmitter.ReturnExpr → + List Aiur.NativeAIR.BlockEmitter.YieldExpr → + List (Aiur.NativeAIR.Expr × Aiur.NativeAIR.OpEmitter.CallExpr) → Aiur.NativeAIR.BlockEmitter.Emission +PREMISE Aiur.NativeAIR.BlockEmitter.Emission.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.BlockEmitter.Emission → Option Aiur.AIR.BlockEmission +DEFINITION +fun values emission => do + let outputs ← Aiur.NativeAIR.OpEmitter.evalRows values emission.values + let equations ← List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations + let queries ← List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) emission.queries + let returns ← List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) emission.returns + let yields ← List.mapM (Aiur.NativeAIR.BlockEmitter.YieldExpr.eval values) emission.yields + let calls ← List.mapM (Aiur.NativeAIR.BlockEmitter.evalGatedCall values) emission.calls + pure + { values := outputs, column := emission.column, lookup := emission.lookup, equations := equations, + queries := queries, returns := returns, yields := yields, calls := calls } +PREMISE Aiur.NativeAIR.BlockEmitter.Emission.prefix +List Aiur.NativeAIR.Expr → Aiur.NativeAIR.BlockEmitter.Emission → Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun equations emission => + { values := emission.values, column := emission.column, lookup := emission.lookup, + equations := equations ++ emission.equations, queries := emission.queries, returns := emission.returns, + yields := emission.yields, calls := emission.calls } +PREMISE Aiur.NativeAIR.BlockEmitter.Emission.afterOps +Aiur.NativeAIR.Expr → + Nat → + Aiur.NativeAIR.OpEmitter.OpsEmission → Aiur.NativeAIR.BlockEmitter.Emission → Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun incoming lookup ops control => + { values := control.values, column := control.column, lookup := control.lookup, + equations := ops.equations ++ control.equations, + queries := Aiur.NativeAIR.LookupEmitter.queryParts lookup incoming ops.queries ++ control.queries, + returns := control.returns, yields := control.yields, + calls := List.map (fun x => (incoming, x)) ops.calls ++ control.calls } +PREMISE Aiur.NativeAIR.BlockEmitter.join +Array Aiur.NativeAIR.RowExpr → + Nat → Nat → List Aiur.NativeAIR.BlockEmitter.Emission → Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun values column lookup emissions => + { values := values, column := List.foldl (fun column emission => max column emission.column) column emissions, + lookup := List.foldl (fun lookup emission => max lookup emission.lookup) lookup emissions, + equations := List.flatMap (fun x => x.equations) emissions, queries := List.flatMap (fun x => x.queries) emissions, + returns := List.flatMap (fun x => x.returns) emissions, yields := List.flatMap (fun x => x.yields) emissions, + calls := List.flatMap (fun x => x.calls) emissions } +PREMISE Aiur.NativeAIR.BlockEmitter.Emission.continued +Aiur.NativeAIR.BlockEmitter.Emission → + List Aiur.NativeAIR.Expr → Aiur.NativeAIR.BlockEmitter.Emission → Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun branches equations continuation => + { values := continuation.values, column := continuation.column, lookup := continuation.lookup, + equations := branches.equations ++ equations ++ continuation.equations, + queries := branches.queries ++ continuation.queries, returns := branches.returns ++ continuation.returns, + yields := continuation.yields, calls := branches.calls ++ continuation.calls } +PREMISE Aiur.NativeAIR.BlockEmitter.returned +Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.RowExpr → + Array Aiur.NativeAIR.RowExpr → Array Aiur.NativeAIR.RowExpr → Nat → Nat → Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun context incoming rows inputs outputs column lookup => + { values := rows, column := column, lookup := lookup, + returns := + [{ selector := incoming, function := context.function, inputs := Aiur.NativeAIR.OpEmitter.rowExprs inputs, + outputs := Aiur.NativeAIR.OpEmitter.rowExprs outputs, rank := context.rank }] } +PREMISE Aiur.NativeAIR.BlockEmitter.yielded +Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.RowExpr → Array Aiur.NativeAIR.RowExpr → Nat → Nat → Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun selector rows outputs column lookup => + { values := rows, column := column, lookup := lookup, yields := [{ selector := selector, values := outputs }] } +PREMISE Aiur.NativeAIR.BlockEmitter.yieldValue +Aiur.NativeAIR.BlockEmitter.YieldExpr → Nat → Aiur.NativeAIR.Expr +DEFINITION +fun yielded index => yielded.selector.frontMul (yielded.values[index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)).expr +PREMISE Aiur.NativeAIR.BlockEmitter.yieldGate +List Aiur.NativeAIR.BlockEmitter.YieldExpr → Aiur.NativeAIR.Expr +DEFINITION +fun yields => Aiur.NativeAIR.BlockEmitter.sum (List.map (fun x => x.selector) yields) +PREMISE Aiur.NativeAIR.BlockEmitter.mergeEquations +Aiur.NativeAIR.Expr → Nat → Nat → List Aiur.NativeAIR.BlockEmitter.YieldExpr → List Aiur.NativeAIR.Expr +DEFINITION +fun incoming column size yields => + List.map + (fun index => + incoming.frontMul + ((Aiur.NativeAIR.mainCurrent (column + index)).expr.frontSub + (Aiur.NativeAIR.BlockEmitter.sum + (List.map (fun x => Aiur.NativeAIR.BlockEmitter.yieldValue x index) yields)))) + (List.range size) +PREMISE Aiur.NativeAIR.BlockEmitter.caseEquation +Aiur.NativeAIR.Expr → Aiur.NativeAIR.RowExpr → Aiur.G → Aiur.NativeAIR.Expr +DEFINITION +fun entry matched value => entry.frontMul (matched.expr.frontSub (Aiur.NativeAIR.Expr.konst value)) +PREMISE Aiur.NativeAIR.BlockEmitter.defaultEquations +Aiur.NativeAIR.Expr → Aiur.NativeAIR.RowExpr → Nat → Array (Aiur.G × Aiur.Bytecode.Block) → List Aiur.NativeAIR.Expr +DEFINITION +fun entry matched column branches => + List.mapIdx + (fun index pair => + entry.frontMul + (((matched.expr.frontSub (Aiur.NativeAIR.Expr.konst pair.fst)).frontMul + (Aiur.NativeAIR.mainCurrent (column + index)).expr).frontSub + (Aiur.NativeAIR.Expr.konst 1))) + branches.toList +PREMISE Aiur.NativeAIR.BlockEmitter.emitCtrl +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.RowExpr → Nat → Nat → Aiur.Bytecode.Ctrl → Option Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun selectors context incoming rows column lookup a => + Aiur.NativeAIR.BlockEmitter.emitCtrl._mutual selectors context (PSum.inl ⟨incoming, ⟨rows, ⟨column, ⟨lookup, a⟩⟩⟩⟩) +PREMISE Aiur.NativeAIR.BlockEmitter.emitBlock +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.RowExpr → Nat → Nat → Aiur.Bytecode.Block → Option Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun selectors context incoming rows column lookup block => + Aiur.NativeAIR.BlockEmitter.emitCtrl._mutual selectors context + (PSum.inr ⟨incoming, ⟨rows, ⟨column, ⟨lookup, block⟩⟩⟩⟩) +PREMISE Aiur.NativeAIR.BlockEmitter.caseRow +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.RowExpr → + Array Aiur.NativeAIR.RowExpr → + Nat → Nat → Aiur.G × Aiur.Bytecode.Block → Option Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun selectors context matched rows column lookup pair => do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors pair.snd + let emission ← Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows column lookup pair.snd + pure + (Aiur.NativeAIR.BlockEmitter.Emission.prefix [Aiur.NativeAIR.BlockEmitter.caseEquation entry matched pair.fst] + emission) +PREMISE Aiur.NativeAIR.BlockEmitter.defaultRow +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.RowExpr → + Array Aiur.NativeAIR.RowExpr → + Nat → + Nat → + Array (Aiur.G × Aiur.Bytecode.Block) → + Option Aiur.Bytecode.Block → Option (List Aiur.NativeAIR.BlockEmitter.Emission) +DEFINITION +fun selectors context matched rows column lookup branches fallback => + match fallback with + | none => some [] + | some block => do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors block + let emission ← + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows (column + branches.size) lookup block + pure + [Aiur.NativeAIR.BlockEmitter.Emission.prefix + (Aiur.NativeAIR.BlockEmitter.defaultEquations entry matched column branches) emission] +PREMISE Aiur.NativeAIR.BlockEmitter.branchRows +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.RowExpr → + Array Aiur.NativeAIR.RowExpr → + Nat → + Nat → + Array (Aiur.G × Aiur.Bytecode.Block) → + Option Aiur.Bytecode.Block → Option Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun selectors context matched rows column lookup branches fallback => do + let cases ← + List.mapM (Aiur.NativeAIR.BlockEmitter.caseRow selectors context matched rows column lookup) branches.toList + let default ← Aiur.NativeAIR.BlockEmitter.defaultRow selectors context matched rows column lookup branches fallback + pure (Aiur.NativeAIR.BlockEmitter.join rows column lookup (cases ++ default)) +PREMISE Aiur.NativeAIR.BlockEmitter.continueRow +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.RowExpr → + Nat → Aiur.Bytecode.Block → Aiur.NativeAIR.BlockEmitter.Emission → Option Aiur.NativeAIR.BlockEmitter.Emission +DEFINITION +fun selectors context incoming rows size continuation joined => + if (joined.yields.all fun part => part.values.size == size) = true then + have gate := Aiur.NativeAIR.BlockEmitter.yieldGate joined.yields; + do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors continuation + have equations : List Aiur.NativeAIR.Expr := + Aiur.NativeAIR.BlockEmitter.mergeEquations incoming joined.column size joined.yields ++ [entry.frontSub gate] + let continued ← + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context gate + (rows ++ Aiur.NativeAIR.OpEmitter.advice joined.column size) (joined.column + size) joined.lookup continuation + pure (joined.continued equations continued) + else none +PREMISE Aiur.NativeAIR.BlockEmitter.selectorAt +Array Aiur.G → Nat → Aiur.G +DEFINITION +fun selectors index => selectors[index]?.getD 0 +PREMISE Aiur.NativeAIR.BlockEmitter.Context.valued +Aiur.NativeAIR.BlockEmitter.Context → Aiur.G → Aiur.AIR.RowContext +DEFINITION +fun context rank => { function := context.function, inputSize := context.inputSize, rank := rank } +PREMISE Aiur.NativeAIR.BlockEmitter.BlockReflects +Aiur.NativeAIR.Values Aiur.G → + (Nat → Aiur.G) → + Array Aiur.NativeAIR.Expr → + (Nat → Aiur.G) → Aiur.NativeAIR.BlockEmitter.Context → Aiur.G → Aiur.Bytecode.Block → Prop +DEFINITION +fun values row selectors selected context rank block => + ∀ {incoming : Aiur.NativeAIR.Expr} {s : Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} + {inputs : Array Aiur.AIR.RowValue} {column lookup : Nat} {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.evalExpr values incoming = some s → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.emitBlock selectors context incoming rows column lookup block = some emission → + (∀ (index : Nat), + column ≤ index → + index < emission.column → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + ∃ result, + Aiur.Bytecode.Block.emitRow row selected (context.valued rank) s inputs column lookup block = + some result ∧ + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result +PREMISE Aiur.NativeAIR.BlockEmitter.CtrlReflects +Aiur.NativeAIR.Values Aiur.G → + (Nat → Aiur.G) → + Array Aiur.NativeAIR.Expr → + (Nat → Aiur.G) → Aiur.NativeAIR.BlockEmitter.Context → Aiur.G → Aiur.Bytecode.Ctrl → Prop +DEFINITION +fun values row selectors selected context rank ctrl => + ∀ {incoming : Aiur.NativeAIR.Expr} {s : Aiur.G} {rows : Array Aiur.NativeAIR.RowExpr} + {inputs : Array Aiur.AIR.RowValue} {column lookup : Nat} {emission : Aiur.NativeAIR.BlockEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.evalExpr values incoming = some s → + Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → + Aiur.NativeAIR.OpEmitter.Normal rows → + Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup ctrl = some emission → + (∀ (index : Nat), + column ≤ index → + index < emission.column → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + ∃ result, + Aiur.Bytecode.Ctrl.emitRow row selected (context.valued rank) s inputs column lookup ctrl = + some result ∧ + Aiur.NativeAIR.BlockEmitter.Emission.eval values emission = some result +PREMISE Aiur.NativeAIR.BlockEmitter.returnArgs +Bool → List Aiur.NativeAIR.BlockEmitter.ReturnExpr → List Aiur.NativeAIR.Expr +DEFINITION +fun branchless returns => + List.foldl + (fun args returned => + Aiur.NativeAIR.LookupEmitter.addArgs args + (Aiur.NativeAIR.LookupEmitter.gateArgs branchless returned.selector returned.message)) + [] returns +PREMISE Aiur.NativeAIR.BlockEmitter.lookup +Bool → Aiur.NativeAIR.BlockEmitter.Emission → Nat → Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun branchless emission slot => + if slot = 0 then + { multiplicity := Aiur.NativeAIR.Expr.konst 0, + args := Aiur.NativeAIR.BlockEmitter.returnArgs branchless emission.returns } + else Aiur.NativeAIR.LookupEmitter.slot branchless emission.queries slot +PREMISE Aiur.NativeAIR.CircuitEmitter.selectorExprs +Nat → Nat → Array Aiur.NativeAIR.Expr +DEFINITION +fun base count => Array.ofFn fun index => (Aiur.NativeAIR.mainCurrent (base + ↑index)).expr +PREMISE Aiur.NativeAIR.CircuitEmitter.Member.mk +Nat → + Aiur.Bytecode.Function → + Nat → Aiur.NativeAIR.Expr → Aiur.NativeAIR.BlockEmitter.Emission → Aiur.NativeAIR.CircuitEmitter.Member +PREMISE Aiur.NativeAIR.CircuitEmitter.Member.readBound +Aiur.NativeAIR.CircuitEmitter.Member → Nat +DEFINITION +fun member => + max member.function.layout.inputSize (max (member.selectorBase + member.function.layout.selectors) member.body.column) +PREMISE Aiur.NativeAIR.CircuitEmitter.Member.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.CircuitEmitter.Member → Option Aiur.AIR.MemberEmission +DEFINITION +fun values member => do + let body ← Aiur.NativeAIR.BlockEmitter.Emission.eval values member.body + pure + { functionIndex := member.functionIndex, function := member.function, selectorBase := member.selectorBase, + body := body } +PREMISE Aiur.NativeAIR.CircuitEmitter.emitMember +Aiur.NativeAIR.Expr → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → Nat → Option Aiur.NativeAIR.CircuitEmitter.Member +DEFINITION +fun rank column lookup selectorBase program functionIndex => do + let function ← program.functions[functionIndex]? + have selectors : Array Aiur.NativeAIR.Expr := + Aiur.NativeAIR.CircuitEmitter.selectorExprs selectorBase function.layout.selectors + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors function.body + let body ← + Aiur.NativeAIR.BlockEmitter.emitBlock selectors + { function := functionIndex, inputSize := function.layout.inputSize, rank := rank } entry + (Aiur.NativeAIR.OpEmitter.advice 0 function.layout.inputSize) column lookup function.body + pure + { functionIndex := functionIndex, function := function, selectorBase := selectorBase, entry := entry, + body := body } +PREMISE Aiur.NativeAIR.CircuitEmitter.emitMembers +Aiur.NativeAIR.Expr → + Nat → Nat → Nat → Aiur.Bytecode.Toplevel → List Nat → Option (List Aiur.NativeAIR.CircuitEmitter.Member) +DEFINITION +fun rank column lookup selectorBase program x => + List.brecOn (motive := fun x => Nat → Option (List Aiur.NativeAIR.CircuitEmitter.Member)) x + (Aiur.NativeAIR.CircuitEmitter.emitMembers._f rank column lookup program) selectorBase +PREMISE Aiur.NativeAIR.CircuitEmitter.rankBytes +Aiur.Bytecode.FunctionLayout → Fin 6 → Aiur.NativeAIR.Expr +DEFINITION +fun layout index => (Aiur.NativeAIR.mainCurrent (layout.inputSize + layout.selectors + 1 + ↑index)).expr +PREMISE Aiur.NativeAIR.CircuitEmitter.selectorEquations +Aiur.Bytecode.FunctionLayout → List Aiur.NativeAIR.Expr +DEFINITION +fun layout => + List.map + (fun index => + have selector := (Aiur.NativeAIR.mainCurrent (layout.inputSize + index)).expr; + selector.frontMul (selector.frontSub (Aiur.NativeAIR.Expr.konst 1))) + (List.range layout.selectors) +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.mk +List Aiur.NativeAIR.CircuitEmitter.Member → + Aiur.NativeAIR.Expr → + Aiur.NativeAIR.Expr → + (Fin 6 → Aiur.NativeAIR.Expr) → + Nat → + Nat → + Nat → + Nat → + Bool → + List Aiur.NativeAIR.Expr → + List Aiur.NativeAIR.LookupEmitter.QueryExpr → + List Aiur.NativeAIR.BlockEmitter.ReturnExpr → Aiur.NativeAIR.CircuitEmitter.Emission +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.readBound +Aiur.NativeAIR.CircuitEmitter.Emission → Nat +DEFINITION +fun emission => + List.foldl (fun bound member => max bound member.readBound) (emission.selectorStart + emission.selectorCount + 1 + 6) + emission.members +PREMISE Aiur.NativeAIR.CircuitEmitter.circuitEmission +Aiur.Bytecode.Circuit → List Aiur.NativeAIR.CircuitEmitter.Member → Aiur.NativeAIR.CircuitEmitter.Emission +DEFINITION +fun circuit members => + have selector := Aiur.NativeAIR.BlockEmitter.sum (List.map (fun x => x.entry) members); + have multiplicity := (Aiur.NativeAIR.mainCurrent (circuit.layout.inputSize + circuit.layout.selectors)).expr; + have bytes := Aiur.NativeAIR.CircuitEmitter.rankBytes circuit.layout; + { members := members, selector := selector, multiplicity := multiplicity, rankBytes := bytes, + width := circuit.layout.width, selectorStart := circuit.layout.inputSize, selectorCount := circuit.layout.selectors, + lookupCount := circuit.layout.lookups, + branchless := Aiur.Bytecode.circuitBranchless circuit.layout.selectors (List.map (fun x => x.function) members), + equations := + (List.flatMap (fun x => x.body.equations) members ++ + Aiur.NativeAIR.CircuitEmitter.selectorEquations circuit.layout ++ + if 1 < circuit.members.size then [selector.frontMul ((Aiur.NativeAIR.Expr.konst 1).frontSub selector)] + else []) ++ + [multiplicity.frontMul ((Aiur.NativeAIR.Expr.konst 1).frontSub selector)], + queries := + List.flatMap (fun x => x.body.queries) members ++ + if members.isEmpty = true then [] + else Aiur.NativeAIR.LookupEmitter.queryParts 1 selector (Aiur.NativeAIR.OpEmitter.rangeSix bytes), + returns := List.flatMap (fun x => x.body.returns) members } +PREMISE Aiur.NativeAIR.CircuitEmitter.emitCircuit +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeAIR.CircuitEmitter.Emission +DEFINITION +fun program circuit => + have rank := Aiur.NativeAIR.OpEmitter.packSix (Aiur.NativeAIR.CircuitEmitter.rankBytes circuit.layout); + have column := circuit.layout.inputSize + circuit.layout.selectors + 1 + 6; + do + let members ← + Aiur.NativeAIR.CircuitEmitter.emitMembers rank column 4 circuit.layout.inputSize program circuit.members.toList + pure (Aiur.NativeAIR.CircuitEmitter.circuitEmission circuit members) +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.lookup +Aiur.NativeAIR.CircuitEmitter.Emission → Nat → Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun emission slot => + if slot = 0 then + { multiplicity := emission.multiplicity.frontNeg, + args := Aiur.NativeAIR.BlockEmitter.returnArgs emission.branchless emission.returns } + else Aiur.NativeAIR.LookupEmitter.slot emission.branchless emission.queries slot +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.lookups +Aiur.NativeAIR.CircuitEmitter.Emission → List Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun emission => List.ofFn fun slot => emission.lookup ↑slot +PREMISE Aiur.NativeAIR.CircuitEmitter.evalFin +{size : Nat} → Aiur.NativeAIR.Values Aiur.G → (Fin size → Aiur.NativeAIR.Expr) → Option (Fin size → Aiur.G) +DEFINITION +fun {size} values expressions => do + let results ← Array.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (Array.ofFn expressions) + pure fun index => results[↑index]?.getD 0 +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.eval +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.CircuitEmitter.Emission → Option Aiur.AIR.CircuitEmission +DEFINITION +fun values emission => do + let members ← List.mapM (Aiur.NativeAIR.CircuitEmitter.Member.eval values) emission.members + let selector ← Aiur.NativeAIR.OpEmitter.evalExpr values emission.selector + let multiplicity ← Aiur.NativeAIR.OpEmitter.evalExpr values emission.multiplicity + let rankBytes ← Aiur.NativeAIR.CircuitEmitter.evalFin values emission.rankBytes + let equations ← List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) emission.equations + let queries ← List.mapM (Aiur.NativeAIR.LookupEmitter.QueryExpr.eval values) emission.queries + let returns ← List.mapM (Aiur.NativeAIR.BlockEmitter.ReturnExpr.eval values) emission.returns + pure + { members := members, selector := selector, multiplicity := multiplicity, rankBytes := rankBytes, + width := emission.width, selectorStart := emission.selectorStart, selectorCount := emission.selectorCount, + lookupCount := emission.lookupCount, branchless := emission.branchless, equations := equations, + queries := queries, returns := returns } +PREMISE Aiur.NativeAIR.CircuitEmitter.Compiled.mk +Aiur.NativeAIR.CircuitEmitter.Emission → + Aiur.NativeAIR.Compiler.BaseCompilation → Aiur.NativeAIR.CircuitEmitter.Compiled +PREMISE Aiur.NativeAIR.CircuitEmitter.compileCircuit +Aiur.NativeAIR.GraphWidths → + Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeAIR.CircuitEmitter.Compiled +DEFINITION +fun widths program circuit => do + let emission ← Aiur.NativeAIR.CircuitEmitter.emitCircuit program circuit + let base ← Aiur.NativeAIR.Compiler.compileBase widths emission.lookups emission.equations + pure { emission := emission, base := base } +PREMISE Aiur.Bytecode.OpAllocation.mk +Array Nat → Nat → Aiur.Bytecode.OpAllocation +PREMISE Aiur.Bytecode.OpAllocation.advice +Nat → Aiur.Bytecode.OpAllocation +DEFINITION +fun size => { degrees := Array.replicate size 1, auxiliaries := size } +PREMISE Aiur.Bytecode.selectedDegree +Array Nat → Array Nat → Nat → Nat +DEFINITION +fun degrees indices initial => Array.foldl Nat.max initial (Array.map (fun index => degrees[index]?.getD 0) indices) +PREMISE Aiur.Bytecode.Op.allocation +Array Nat → Aiur.Bytecode.Op → Aiur.Bytecode.OpAllocation +DEFINITION +fun degrees x => + match x with + | Aiur.Bytecode.Op.const a => { degrees := #[0], auxiliaries := 0 } + | Aiur.Bytecode.Op.add a b => { degrees := #[max (degrees[a]?.getD 0) (degrees[b]?.getD 0)], auxiliaries := 0 } + | Aiur.Bytecode.Op.sub a b => { degrees := #[max (degrees[a]?.getD 0) (degrees[b]?.getD 0)], auxiliaries := 0 } + | Aiur.Bytecode.Op.mul a b => + have degree := degrees[a]?.getD 0 + degrees[b]?.getD 0; + if degree < 2 then { degrees := #[degree], auxiliaries := 0 } else Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.eqZero a => + if degrees[a]?.getD 0 = 0 then { degrees := #[0], auxiliaries := 0 } else { degrees := #[1], auxiliaries := 2 } + | Aiur.Bytecode.Op.call a a_1 size unconstrained => + { degrees := Array.replicate size 1, auxiliaries := size + if unconstrained = true then 0 else 6 } + | Aiur.Bytecode.Op.store a => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.load size a => Aiur.Bytecode.OpAllocation.advice size + | Aiur.Bytecode.Op.ioRead a a_1 size => Aiur.Bytecode.OpAllocation.advice size + | Aiur.Bytecode.Op.assertEq a a_1 a_2 => { degrees := #[], auxiliaries := 0 } + | Aiur.Bytecode.Op.ioSetInfo a a_1 a_2 a_3 => { degrees := #[], auxiliaries := 0 } + | Aiur.Bytecode.Op.ioWrite a a_1 => { degrees := #[], auxiliaries := 0 } + | Aiur.Bytecode.Op.debug a a_1 => { degrees := #[], auxiliaries := 0 } + | Aiur.Bytecode.Op.u8RangeCheck a a_1 => { degrees := #[], auxiliaries := 0 } + | Aiur.Bytecode.Op.ioGetInfo a a_1 => Aiur.Bytecode.OpAllocation.advice 2 + | Aiur.Bytecode.Op.unconstrainedBigUintDivMod a a_1 => Aiur.Bytecode.OpAllocation.advice 2 + | Aiur.Bytecode.Op.u8BitDecomposition a => Aiur.Bytecode.OpAllocation.advice 8 + | Aiur.Bytecode.Op.unconstrainedGToBytes a => Aiur.Bytecode.OpAllocation.advice 8 + | Aiur.Bytecode.Op.u8ShiftLeft a => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.u8ShiftRight a => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.u8Xor a a_1 => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.u8And a a_1 => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.u8Or a a_1 => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.u8LessThan a a_1 => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.unconstrainedGInverse a => Aiur.Bytecode.OpAllocation.advice 1 + | Aiur.Bytecode.Op.u8Add a b => + { degrees := #[1, max (max (degrees[a]?.getD 0) (degrees[b]?.getD 0)) 1], auxiliaries := 1 } + | Aiur.Bytecode.Op.u8Sub a b => + { degrees := #[1, max (max (degrees[a]?.getD 0) (degrees[b]?.getD 0)) 1], auxiliaries := 1 } + | Aiur.Bytecode.Op.u8Mul a a_1 => Aiur.Bytecode.OpAllocation.advice 2 + | Aiur.Bytecode.Op.u8XorSplit7 a a_1 => Aiur.Bytecode.OpAllocation.advice 2 + | Aiur.Bytecode.Op.u8XorSplit4 a a_1 => Aiur.Bytecode.OpAllocation.advice 2 + | Aiur.Bytecode.Op.u32LessThan a a_1 => { degrees := #[1], auxiliaries := 12 } + | Aiur.Bytecode.Op.unconstrainedU32Add a b => + { degrees := (Array.replicate 4 1).push (Aiur.Bytecode.selectedDegree degrees (a ++ b) 1), auxiliaries := 4 } + | Aiur.Bytecode.Op.unconstrainedU32Add3 a b c => + { degrees := (Array.replicate 4 1).push (Aiur.Bytecode.selectedDegree degrees (a ++ b ++ c) 1), auxiliaries := 4 } + | Aiur.Bytecode.Op.u32ToField indices => + { degrees := #[Aiur.Bytecode.selectedDegree degrees indices 0], auxiliaries := 0 } +PREMISE Aiur.NativeAIR.RowExpr.ZeroConstant +Aiur.NativeAIR.RowExpr → Prop +DEFINITION +fun row => row.degree = 0 → ∃ value, row.expr = Aiur.NativeAIR.Expr.konst value +PREMISE Aiur.NativeAIR.OpEmitter.DegreeValid +Array Aiur.NativeAIR.RowExpr → Prop +DEFINITION +fun rows => ∀ (row : Aiur.NativeAIR.RowExpr), row ∈ rows → row.ZeroConstant +PREMISE Aiur.NativeAIR.OpEmitter.rowDegrees +Array Aiur.NativeAIR.RowExpr → Array Nat +DEFINITION +fun rows => Array.map Aiur.NativeAIR.RowExpr.degree rows +PREMISE Aiur.NativeAIR.OpEmitter.Emission.allocation +Aiur.NativeAIR.OpEmitter.Emission → Aiur.Bytecode.OpAllocation +DEFINITION +fun emission => { degrees := Aiur.NativeAIR.OpEmitter.rowDegrees emission.outputs, auxiliaries := emission.used } +PREMISE Aiur.Concrete.Bytecode.allocationBranchStep +Aiur.Concrete.Bytecode.SharedData → + Array Nat → + Aiur.Concrete.Bytecode.SharedData → + Aiur.Bytecode.Block → Aiur.Concrete.Bytecode.LayoutM Aiur.Concrete.Bytecode.SharedData +DEFINITION +fun shared degrees acc block => do + Aiur.Concrete.Bytecode.setSharedData shared + Aiur.Concrete.Bytecode.blockLayout block + let used ← Aiur.Concrete.Bytecode.getSharedData + Aiur.Concrete.Bytecode.setDegrees degrees + pure (acc.maximals used) +PREMISE Aiur.Bytecode.Function.ComputedLayout +Aiur.Bytecode.Function → Prop +DEFINITION +fun function => + have computed := + (StateT.run (Aiur.Concrete.Bytecode.blockLayout function.body) + (Aiur.Concrete.Bytecode.LayoutMState.new function.layout.inputSize)).snd.functionLayout; + function.layout = + { inputSize := computed.inputSize, selectors := computed.selectors, auxiliaries := computed.auxiliaries, + lookups := computed.lookups + 1 } +PREMISE Aiur.Bytecode.FunctionsComputedLayout +Array Aiur.Bytecode.Function → Prop +DEFINITION +fun functions => ∀ (function : Aiur.Bytecode.Function), function ∈ functions → function.ComputedLayout +PREMISE Aiur.Bytecode.MembersColumnBound +Array Aiur.Bytecode.Function → Array Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunctionLayout → Prop +DEFINITION +fun functions members layout => + 7 ≤ layout.auxiliaries ∧ + ∀ (index : Aiur.Bytecode.FunIdx), + index ∈ members → + functions[index]!.layout.inputSize ≤ layout.inputSize ∧ + functions[index]!.layout.auxiliaries ≤ layout.auxiliaries +PREMISE Aiur.Bytecode.CircuitsColumnBound +Array Aiur.Bytecode.Function → Array Aiur.Bytecode.Circuit → Prop +DEFINITION +fun functions circuits => + ∀ (circuit : Aiur.Bytecode.Circuit), + circuit ∈ circuits → Aiur.Bytecode.MembersColumnBound functions circuit.members circuit.layout +PREMISE Aiur.AIR.BlockEmission.Inactive +Aiur.AIR.BlockEmission → Prop +DEFINITION +fun emission => + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) ∧ + ∀ (part : Aiur.G × Array Aiur.AIR.RowValue), part ∈ emission.yields → part.fst = 0 +PREMISE Aiur.NativeAIR.CircuitEmitter.circuitWidths +Aiur.Bytecode.Circuit → Aiur.NativeAIR.GraphWidths +DEFINITION +fun circuit => { preprocessed := 0, main := circuit.layout.width, stage2 := 0, publics := 0 } +PREMISE Aiur.NativeAIR.CircuitEmitter.zeroValues +Nat → Aiur.NativeAIR.Values Aiur.G +DEFINITION +fun width => + { + columns := fun source x => + match source with + | Aiur.NativeAIR.Source.main => Array.replicate width 0 + | x => #[], + publics := #[], isFirstRow := 0, isLastRow := 0, isTransition := 0 } +PREMISE Aiur.Bytecode.indicesInScope +Nat → Array Aiur.Bytecode.ValIdx → Bool +DEFINITION +fun available indices => indices.all fun index => decide (index < available) +PREMISE Aiur.Bytecode.wordInScope +Nat → Array Aiur.Bytecode.ValIdx → Bool +DEFINITION +fun available indices => indices.size == 4 && Aiur.Bytecode.indicesInScope available indices +PREMISE Aiur.Bytecode.Op.outputSize +Aiur.Bytecode.Op → Nat +DEFINITION +fun x => + match x with + | Aiur.Bytecode.Op.const a => 1 + | Aiur.Bytecode.Op.add a a_1 => 1 + | Aiur.Bytecode.Op.sub a a_1 => 1 + | Aiur.Bytecode.Op.mul a a_1 => 1 + | Aiur.Bytecode.Op.eqZero a => 1 + | Aiur.Bytecode.Op.store a => 1 + | Aiur.Bytecode.Op.u8ShiftLeft a => 1 + | Aiur.Bytecode.Op.u8ShiftRight a => 1 + | Aiur.Bytecode.Op.u8Xor a a_1 => 1 + | Aiur.Bytecode.Op.u8And a a_1 => 1 + | Aiur.Bytecode.Op.u8Or a a_1 => 1 + | Aiur.Bytecode.Op.u8LessThan a a_1 => 1 + | Aiur.Bytecode.Op.u32LessThan a a_1 => 1 + | Aiur.Bytecode.Op.unconstrainedGInverse a => 1 + | Aiur.Bytecode.Op.u32ToField a => 1 + | Aiur.Bytecode.Op.call a a_1 size unconstrained => size + | Aiur.Bytecode.Op.load size a => size + | Aiur.Bytecode.Op.ioRead a a_1 size => size + | Aiur.Bytecode.Op.assertEq a a_1 a_2 => 0 + | Aiur.Bytecode.Op.ioSetInfo a a_1 a_2 a_3 => 0 + | Aiur.Bytecode.Op.ioWrite a a_1 => 0 + | Aiur.Bytecode.Op.debug a a_1 => 0 + | Aiur.Bytecode.Op.u8RangeCheck a a_1 => 0 + | Aiur.Bytecode.Op.ioGetInfo a a_1 => 2 + | Aiur.Bytecode.Op.u8Add a a_1 => 2 + | Aiur.Bytecode.Op.u8Mul a a_1 => 2 + | Aiur.Bytecode.Op.u8Sub a a_1 => 2 + | Aiur.Bytecode.Op.u8XorSplit7 a a_1 => 2 + | Aiur.Bytecode.Op.u8XorSplit4 a a_1 => 2 + | Aiur.Bytecode.Op.unconstrainedBigUintDivMod a a_1 => 2 + | Aiur.Bytecode.Op.u8BitDecomposition a => 8 + | Aiur.Bytecode.Op.unconstrainedGToBytes a => 8 + | Aiur.Bytecode.Op.unconstrainedU32Add a a_1 => 5 + | Aiur.Bytecode.Op.unconstrainedU32Add3 a a_1 a_2 => 5 +PREMISE Aiur.Bytecode.Op.emissionInputs +Nat → Aiur.Bytecode.Op → Bool +DEFINITION +fun available x => + match x with + | Aiur.Bytecode.Op.add a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.sub a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.mul a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8Xor a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8Add a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8Mul a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8Sub a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8And a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8Or a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8LessThan a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u32LessThan a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8XorSplit7 a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8XorSplit4 a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.u8RangeCheck a b => decide (a < available) && decide (b < available) + | Aiur.Bytecode.Op.eqZero index => decide (index < available) + | Aiur.Bytecode.Op.load size index => decide (index < available) + | Aiur.Bytecode.Op.u8BitDecomposition index => decide (index < available) + | Aiur.Bytecode.Op.u8ShiftLeft index => decide (index < available) + | Aiur.Bytecode.Op.u8ShiftRight index => decide (index < available) + | Aiur.Bytecode.Op.call a indices outputSize false => Aiur.Bytecode.indicesInScope available indices + | Aiur.Bytecode.Op.store indices => Aiur.Bytecode.indicesInScope available indices + | Aiur.Bytecode.Op.assertEq left right a => + left.size == right.size && + (Aiur.Bytecode.indicesInScope available left && Aiur.Bytecode.indicesInScope available right) + | Aiur.Bytecode.Op.unconstrainedU32Add left right => + Aiur.Bytecode.wordInScope available left && Aiur.Bytecode.wordInScope available right + | Aiur.Bytecode.Op.unconstrainedU32Add3 left middle right => + Aiur.Bytecode.wordInScope available left && + (Aiur.Bytecode.wordInScope available middle && Aiur.Bytecode.wordInScope available right) + | Aiur.Bytecode.Op.u32ToField indices => Aiur.Bytecode.wordInScope available indices + | x => true +PREMISE Aiur.Bytecode.addScope +Nat → Nat → Option Nat +DEFINITION +fun available count => + have next := available + count; + if next < 2 ^ 64 then some next else none +PREMISE Aiur.Bytecode.checkEmissionOps +List Aiur.Bytecode.Op → Nat → Option Nat +DEFINITION +fun x x_1 => List.brecOn (motive := fun x => Nat → Option Nat) x Aiur.Bytecode.checkEmissionOps._f x_1 +PREMISE Aiur.Bytecode.Ctrl.emissionChecks +Nat → Nat → Option Nat → Aiur.Bytecode.Ctrl → Bool +DEFINITION +fun available selectors yieldSize a => + Aiur.Bytecode.Ctrl.emissionChecks._mutual selectors (PSum.inl ⟨available, ⟨yieldSize, a⟩⟩) +PREMISE Aiur.Bytecode.Block.emissionChecks +Nat → Nat → Option Nat → Aiur.Bytecode.Block → Bool +DEFINITION +fun available selectors yieldSize block => + Aiur.Bytecode.Ctrl.emissionChecks._mutual selectors (PSum.inr ⟨available, ⟨yieldSize, block⟩⟩) +PREMISE Aiur.Bytecode.Function.emissionChecks +Aiur.Bytecode.Function → Bool +DEFINITION +fun function => + decide (function.layout.inputSize < 2 ^ 64) && + Aiur.Bytecode.Block.emissionChecks function.layout.inputSize function.layout.selectors none function.body +PREMISE Aiur.Bytecode.Toplevel.validateEmission +Aiur.Bytecode.Toplevel → Bool +DEFINITION +fun program => program.functions.all fun function => !function.constrained || function.emissionChecks +PREMISE Aiur.NativeAIR.BlockEmitter.Emission.YieldShape +Option Nat → Aiur.NativeAIR.BlockEmitter.Emission → Prop +DEFINITION +fun size emission => + ∀ (part : Aiur.NativeAIR.BlockEmitter.YieldExpr), part ∈ emission.yields → size = some part.values.size +PREMISE Aiur.BoundVerifier.Selection.keyParameters +Aiur.BoundVerifier.Selection → Aiur.NativeAIR.KeyCodec.Parameters +DEFINITION +fun selection => + { logBlowup := selection.commitment.logBlowup, capHeight := selection.commitment.capHeight, + logFinalPolyLen := selection.fri.logFinalPolyLen, maxLogArity := selection.fri.maxLogArity, + numQueries := selection.fri.numQueries, commitProofOfWorkBits := selection.fri.commitProofOfWorkBits, + queryProofOfWorkBits := selection.fri.queryProofOfWorkBits } +PREMISE Aiur.NativeAIR.KeyCodec.Reader +Type → Type +DEFINITION +StateT (List UInt8) Option +PREMISE Aiur.NativeAIR.KeyCodec.readByte +Aiur.NativeAIR.KeyCodec.Reader UInt8 +DEFINITION +fun x => + match x with + | [] => none + | byte :: rest => some (byte, rest) +PREMISE Aiur.NativeAIR.KeyCodec.readNat +Nat → Aiur.NativeAIR.KeyCodec.Reader Nat +DEFINITION +fun x => Nat.brecOn x Aiur.NativeAIR.KeyCodec.readNat._f +PREMISE Aiur.NativeAIR.KeyCodec.readMany +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → Nat → Aiur.NativeAIR.KeyCodec.Reader (List α) +DEFINITION +fun {α} read x => Nat.brecOn x (Aiur.NativeAIR.KeyCodec.readMany._f read) +PREMISE Aiur.NativeAIR.KeyCodec.readVector +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → Aiur.NativeAIR.KeyCodec.Reader (List α) +DEFINITION +fun {α} read => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + Aiur.NativeAIR.KeyCodec.readMany read __do_lift +PREMISE Aiur.NativeAIR.KeyCodec.encodeNat +Nat → Nat → List UInt8 +DEFINITION +fun x x_1 => Nat.brecOn (motive := fun x => Nat → List UInt8) x Aiur.NativeAIR.KeyCodec.encodeNat._f x_1 +PREMISE Aiur.NativeAIR.KeyCodec.encodeVector +{α : Type u_1} → (α → List UInt8) → List α → List UInt8 +DEFINITION +fun {α} encode values => Aiur.NativeAIR.KeyCodec.encodeNat 2 values.length ++ List.flatMap encode values +PREMISE Aiur.NativeAIR.KeyCodec.readNode +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.Node +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readByte + match __do_lift.toNat with + | 0 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure (Aiur.NativeAIR.Node.konst (Aiur.G.ofNat __do_lift)) + | 1 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 8 + pure (Aiur.NativeAIR.Node.konst (Aiur.G.ofNat __do_lift)) + | 2 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 1 + pure (Aiur.NativeAIR.Node.publicInput __do_lift) + | 3 => pure Aiur.NativeAIR.Node.isFirstRow + | 4 => pure Aiur.NativeAIR.Node.isLastRow + | 5 => pure Aiur.NativeAIR.Node.isTransition + | 6 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_1 ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure (Aiur.NativeAIR.Node.add __do_lift __do_lift_1) + | 7 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_1 ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure (Aiur.NativeAIR.Node.sub __do_lift __do_lift_1) + | 8 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_1 ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure (Aiur.NativeAIR.Node.mul __do_lift __do_lift_1) + | 9 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure (Aiur.NativeAIR.Node.neg __do_lift) + | 10 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure + (Aiur.NativeAIR.Node.var + { source := Aiur.NativeAIR.Source.preprocessed, offset := Aiur.NativeAIR.RowOffset.current, + index := __do_lift }) + | 11 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure + (Aiur.NativeAIR.Node.var + { source := Aiur.NativeAIR.Source.preprocessed, offset := Aiur.NativeAIR.RowOffset.next, + index := __do_lift }) + | 12 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure + (Aiur.NativeAIR.Node.var + { source := Aiur.NativeAIR.Source.main, offset := Aiur.NativeAIR.RowOffset.current, index := __do_lift }) + | 13 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure + (Aiur.NativeAIR.Node.var + { source := Aiur.NativeAIR.Source.main, offset := Aiur.NativeAIR.RowOffset.next, index := __do_lift }) + | 14 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure + (Aiur.NativeAIR.Node.var + { source := Aiur.NativeAIR.Source.stage2, offset := Aiur.NativeAIR.RowOffset.current, index := __do_lift }) + | 15 => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure + (Aiur.NativeAIR.Node.var + { source := Aiur.NativeAIR.Source.stage2, offset := Aiur.NativeAIR.RowOffset.next, index := __do_lift }) + | x => failure +PREMISE Aiur.NativeAIR.KeyCodec.encodeNode +Aiur.NativeAIR.Node → List UInt8 +DEFINITION +fun x => + match x with + | Aiur.NativeAIR.Node.konst value => + if value.n < 65536 then 0 :: Aiur.NativeAIR.KeyCodec.encodeNat 2 value.n + else 1 :: Aiur.NativeAIR.KeyCodec.encodeNat 8 value.n + | Aiur.NativeAIR.Node.publicInput index => 2 :: Aiur.NativeAIR.KeyCodec.encodeNat 1 index + | Aiur.NativeAIR.Node.isFirstRow => [3] + | Aiur.NativeAIR.Node.isLastRow => [4] + | Aiur.NativeAIR.Node.isTransition => [5] + | Aiur.NativeAIR.Node.add a b => 6 :: (Aiur.NativeAIR.KeyCodec.encodeNat 2 a ++ Aiur.NativeAIR.KeyCodec.encodeNat 2 b) + | Aiur.NativeAIR.Node.sub a b => 7 :: (Aiur.NativeAIR.KeyCodec.encodeNat 2 a ++ Aiur.NativeAIR.KeyCodec.encodeNat 2 b) + | Aiur.NativeAIR.Node.mul a b => 8 :: (Aiur.NativeAIR.KeyCodec.encodeNat 2 a ++ Aiur.NativeAIR.KeyCodec.encodeNat 2 b) + | Aiur.NativeAIR.Node.neg child => 9 :: Aiur.NativeAIR.KeyCodec.encodeNat 2 child + | Aiur.NativeAIR.Node.var column => + have tag := + match column.source, column.offset with + | Aiur.NativeAIR.Source.preprocessed, Aiur.NativeAIR.RowOffset.current => 10 + | Aiur.NativeAIR.Source.preprocessed, Aiur.NativeAIR.RowOffset.next => 11 + | Aiur.NativeAIR.Source.main, Aiur.NativeAIR.RowOffset.current => 12 + | Aiur.NativeAIR.Source.main, Aiur.NativeAIR.RowOffset.next => 13 + | Aiur.NativeAIR.Source.stage2, Aiur.NativeAIR.RowOffset.current => 14 + | Aiur.NativeAIR.Source.stage2, Aiur.NativeAIR.RowOffset.next => 15; + tag :: Aiur.NativeAIR.KeyCodec.encodeNat 2 column.index +PREMISE Aiur.NativeAIR.KeyCodec.readLookup +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.Lookup +DEFINITION +do + let multiplicity ← Aiur.NativeAIR.KeyCodec.readNat 2 + let args ← Aiur.NativeAIR.KeyCodec.readVector (Aiur.NativeAIR.KeyCodec.readNat 2) + pure { multiplicity := multiplicity, args := args } +PREMISE Aiur.NativeAIR.KeyCodec.encodeLookup +Aiur.NativeAIR.Lookup → List UInt8 +DEFINITION +fun lookup => + Aiur.NativeAIR.KeyCodec.encodeNat 2 lookup.multiplicity ++ + Aiur.NativeAIR.KeyCodec.encodeVector (Aiur.NativeAIR.KeyCodec.encodeNat 2) lookup.args +PREMISE Aiur.NativeAIR.KeyCodec.Circuit.mk +Nat → Nat → Nat → Nat → Nat → Aiur.NativeAIR.Graph → Aiur.NativeAIR.KeyCodec.Circuit +PREMISE Aiur.NativeAIR.KeyCodec.Circuit.groups +Aiur.NativeAIR.KeyCodec.Circuit → Nat +DEFINITION +fun circuit => max 1 ((circuit.graph.lookups.length + circuit.lookupGroupSize - 1) / circuit.lookupGroupSize) +PREMISE Aiur.NativeAIR.KeyCodec.Circuit.widths +Aiur.NativeAIR.KeyCodec.Circuit → Aiur.NativeAIR.GraphWidths +DEFINITION +fun circuit => + { preprocessed := circuit.preprocessedWidth, main := circuit.mainWidth, stage2 := circuit.groups * 2, publics := 8 } +PREMISE Aiur.NativeAIR.KeyCodec.Circuit.constraintCount +Aiur.NativeAIR.KeyCodec.Circuit → Nat +DEFINITION +fun circuit => circuit.graph.zeros.length + circuit.groups * 2 +PREMISE Aiur.NativeAIR.KeyCodec.nodeDegree +Array Nat → Aiur.NativeAIR.Node → Option Nat +DEFINITION +fun degrees x => + match x with + | Aiur.NativeAIR.Node.konst value => some 0 + | Aiur.NativeAIR.Node.publicInput index => some 0 + | Aiur.NativeAIR.Node.isTransition => some 0 + | Aiur.NativeAIR.Node.var column => some 1 + | Aiur.NativeAIR.Node.isFirstRow => some 1 + | Aiur.NativeAIR.Node.isLastRow => some 1 + | Aiur.NativeAIR.Node.add a b => do + let __do_lift ← degrees[a]? + let __do_lift_1 ← degrees[b]? + pure (max __do_lift __do_lift_1) + | Aiur.NativeAIR.Node.sub a b => do + let __do_lift ← degrees[a]? + let __do_lift_1 ← degrees[b]? + pure (max __do_lift __do_lift_1) + | Aiur.NativeAIR.Node.mul a b => do + let __do_lift ← degrees[a]? + let __do_lift_1 ← degrees[b]? + have sum : Nat := __do_lift + __do_lift_1 + if sum < 2 ^ 32 then some sum else none + | Aiur.NativeAIR.Node.neg child => degrees[child]? +PREMISE Aiur.NativeAIR.KeyCodec.nodeDegreesFrom +List Aiur.NativeAIR.Node → Array Nat → Option (Array Nat) +DEFINITION +fun x x_1 => + List.brecOn (motive := fun x => Array Nat → Option (Array Nat)) x Aiur.NativeAIR.KeyCodec.nodeDegreesFrom._f x_1 +PREMISE Aiur.NativeAIR.KeyCodec.lookupDegrees +Array Nat → Aiur.NativeAIR.Lookup → Option (Nat × Nat) +DEFINITION +fun degrees lookup => do + let multiplicity ← degrees[lookup.multiplicity]? + let args ← List.mapM (fun index => degrees[index]?) lookup.args + pure (multiplicity, List.foldr max 0 args) +PREMISE Aiur.NativeAIR.KeyCodec.groupDegree +List (Nat × Nat) → Nat +DEFINITION +fun degrees => + have sum := (List.map Prod.snd degrees).sum; + List.foldr max (sum + 1) + (List.map + (fun x => + match x with + | (multiplicity, message) => multiplicity + sum - message) + degrees) +PREMISE Aiur.NativeAIR.KeyCodec.Circuit.computedDegree +Aiur.NativeAIR.KeyCodec.Circuit → Option Nat +DEFINITION +fun circuit => do + let degrees ← Aiur.NativeAIR.KeyCodec.nodeDegreesFrom circuit.graph.nodes #[] + let zeros ← List.mapM (fun index => degrees[index]?) circuit.graph.zeros + let lookups ← List.mapM (Aiur.NativeAIR.KeyCodec.lookupDegrees degrees) circuit.graph.lookups + have groups : List Nat := + List.map + (fun index => + Aiur.NativeAIR.KeyCodec.groupDegree + (List.take circuit.lookupGroupSize (List.drop (index * circuit.lookupGroupSize) lookups))) + (List.range circuit.groups) + pure (List.foldr max (max 1 (List.foldr max 0 zeros)) groups) +PREMISE Aiur.NativeAIR.KeyCodec.Circuit.valid +Aiur.NativeAIR.KeyCodec.Circuit → Bool +DEFINITION +fun circuit => + decide (1 ≤ circuit.lookupGroupSize) && decide (circuit.lookupGroupSize ≤ 8) && + (Aiur.NativeAIR.checkedGraphPrefix circuit.widths circuit.graph).isSome && + circuit.computedDegree == some circuit.maxConstraintDegree +PREMISE Aiur.NativeAIR.KeyCodec.readCircuitData +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +do + let main ← Aiur.NativeAIR.KeyCodec.readNat 2 + let preprocessed ← Aiur.NativeAIR.KeyCodec.readNat 2 + let height ← Aiur.NativeAIR.KeyCodec.readNat 4 + let degree ← Aiur.NativeAIR.KeyCodec.readNat 2 + let group ← Aiur.NativeAIR.KeyCodec.readNat 1 + let nodes ← Aiur.NativeAIR.KeyCodec.readVector Aiur.NativeAIR.KeyCodec.readNode + let zeros ← Aiur.NativeAIR.KeyCodec.readVector (Aiur.NativeAIR.KeyCodec.readNat 2) + let lookups ← Aiur.NativeAIR.KeyCodec.readVector Aiur.NativeAIR.KeyCodec.readLookup + pure + { mainWidth := main, preprocessedWidth := preprocessed, preprocessedHeight := height, + maxConstraintDegree := degree, lookupGroupSize := group, + graph := { nodes := nodes, zeros := zeros, lookups := lookups } } +PREMISE Aiur.NativeAIR.KeyCodec.readCircuit +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +do + let circuit ← Aiur.NativeAIR.KeyCodec.readCircuitData + if circuit.valid = true then pure circuit else failure +PREMISE Aiur.NativeAIR.KeyCodec.encodeCircuit +Aiur.NativeAIR.KeyCodec.Circuit → List UInt8 +DEFINITION +fun circuit => + Aiur.NativeAIR.KeyCodec.encodeNat 2 circuit.mainWidth ++ + Aiur.NativeAIR.KeyCodec.encodeNat 2 circuit.preprocessedWidth ++ + Aiur.NativeAIR.KeyCodec.encodeNat 4 circuit.preprocessedHeight ++ + Aiur.NativeAIR.KeyCodec.encodeNat 2 circuit.maxConstraintDegree ++ + Aiur.NativeAIR.KeyCodec.encodeNat 1 circuit.lookupGroupSize ++ + Aiur.NativeAIR.KeyCodec.encodeVector Aiur.NativeAIR.KeyCodec.encodeNode circuit.graph.nodes ++ + Aiur.NativeAIR.KeyCodec.encodeVector (Aiur.NativeAIR.KeyCodec.encodeNat 2) circuit.graph.zeros ++ + Aiur.NativeAIR.KeyCodec.encodeVector Aiur.NativeAIR.KeyCodec.encodeLookup circuit.graph.lookups +PREMISE Aiur.NativeAIR.KeyCodec.Parameters.mk +Nat → Nat → Nat → Nat → Nat → Nat → Nat → Aiur.NativeAIR.KeyCodec.Parameters +PREMISE Aiur.NativeAIR.KeyCodec.readParameters +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.KeyCodec.Parameters +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_1 ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_2 ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_3 ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_4 ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_5 ← Aiur.NativeAIR.KeyCodec.readNat 2 + let __do_lift_6 ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure + { logBlowup := __do_lift, capHeight := __do_lift_1, logFinalPolyLen := __do_lift_2, maxLogArity := __do_lift_3, + numQueries := __do_lift_4, commitProofOfWorkBits := __do_lift_5, queryProofOfWorkBits := __do_lift_6 } +PREMISE Aiur.NativeAIR.KeyCodec.encodeParameters +Aiur.NativeAIR.KeyCodec.Parameters → List UInt8 +DEFINITION +fun parameters => + List.flatMap (Aiur.NativeAIR.KeyCodec.encodeNat 2) + [parameters.logBlowup, parameters.capHeight, parameters.logFinalPolyLen, parameters.maxLogArity, + parameters.numQueries, parameters.commitProofOfWorkBits, parameters.queryProofOfWorkBits] +PREMISE Aiur.NativeAIR.KeyCodec.MerkleCap +Type +DEFINITION +List (List UInt8) +PREMISE Aiur.NativeAIR.KeyCodec.readCommitment +Aiur.NativeAIR.KeyCodec.Reader (Option Aiur.NativeAIR.KeyCodec.MerkleCap) +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readByte + match __do_lift.toNat with + | 0 => pure none + | 1 => do + let cap ← + Aiur.NativeAIR.KeyCodec.readVector (Aiur.NativeAIR.KeyCodec.readMany Aiur.NativeAIR.KeyCodec.readByte 32) + if cap.length.isPowerOfTwo then pure (some cap) else failure + | x => failure +PREMISE Aiur.NativeAIR.KeyCodec.encodeCommitment +Option Aiur.NativeAIR.KeyCodec.MerkleCap → List UInt8 +DEFINITION +fun x => + match x with + | none => [0] + | some cap => 1 :: Aiur.NativeAIR.KeyCodec.encodeVector id cap +PREMISE Aiur.NativeAIR.KeyCodec.readIndex +Aiur.NativeAIR.KeyCodec.Reader (Option Nat) +DEFINITION +do + let index ← Aiur.NativeAIR.KeyCodec.readNat 2 + pure (if index = 65535 then none else some index) +PREMISE Aiur.NativeAIR.KeyCodec.encodeIndex +Option Nat → List UInt8 +DEFINITION +fun index => Aiur.NativeAIR.KeyCodec.encodeNat 2 (index.getD 65535) +PREMISE Aiur.NativeAIR.KeyCodec.Key.mk +Aiur.NativeAIR.KeyCodec.Parameters → + List Aiur.NativeAIR.KeyCodec.Circuit → + Option Aiur.NativeAIR.KeyCodec.MerkleCap → List (Option Nat) → Aiur.NativeAIR.KeyCodec.Key +PREMISE Aiur.NativeAIR.KeyCodec.readKey +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.KeyCodec.Key +DEFINITION +do + let parameters ← Aiur.NativeAIR.KeyCodec.readParameters + let circuits ← Aiur.NativeAIR.KeyCodec.readVector Aiur.NativeAIR.KeyCodec.readCircuit + let commitment ← Aiur.NativeAIR.KeyCodec.readCommitment + let indices ← Aiur.NativeAIR.KeyCodec.readMany Aiur.NativeAIR.KeyCodec.readIndex circuits.length + pure + { parameters := parameters, circuits := circuits, preprocessedCommitment := commitment, + preprocessedIndices := indices } +PREMISE Aiur.NativeAIR.KeyCodec.encodeKey +Aiur.NativeAIR.KeyCodec.Key → List UInt8 +DEFINITION +fun key => + Aiur.NativeAIR.KeyCodec.encodeParameters key.parameters ++ + Aiur.NativeAIR.KeyCodec.encodeVector Aiur.NativeAIR.KeyCodec.encodeCircuit key.circuits ++ + Aiur.NativeAIR.KeyCodec.encodeCommitment key.preprocessedCommitment ++ + List.flatMap Aiur.NativeAIR.KeyCodec.encodeIndex key.preprocessedIndices +PREMISE Aiur.NativeAIR.KeyCodec.decode +ByteArray → Option Aiur.NativeAIR.KeyCodec.Key +DEFINITION +fun bytes => do + let __x ← Aiur.NativeAIR.KeyCodec.readKey bytes.data.toList + match __x with + | (key, rest) => if rest.isEmpty = true then some key else none +PREMISE Aiur.NativeAIR.KeyCodec.encode +Aiur.NativeAIR.KeyCodec.Key → ByteArray +DEFINITION +fun key => (Aiur.NativeAIR.KeyCodec.encodeKey key).toByteArray +PREMISE Aiur.NativeAIR.KeyCodec.decodeCanonical +ByteArray → Option Aiur.NativeAIR.KeyCodec.Key +DEFINITION +fun bytes => do + let key ← Aiur.NativeAIR.KeyCodec.decode bytes + if Aiur.NativeAIR.KeyCodec.encode key = bytes then some key else none +PREMISE Aiur.NativeAIR.KeyCodec.Reads +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → List UInt8 → α → Prop +DEFINITION +fun {α} read bytes value => ∀ (rest : List UInt8), read (bytes ++ rest) = some (value, rest) +PREMISE Aiur.NativeAIR.KeyCodec.NodeWireFits +Aiur.NativeAIR.Node → Prop +DEFINITION +fun x => + match x with + | Aiur.NativeAIR.Node.konst value => True + | Aiur.NativeAIR.Node.isFirstRow => True + | Aiur.NativeAIR.Node.isLastRow => True + | Aiur.NativeAIR.Node.isTransition => True + | Aiur.NativeAIR.Node.var column => column.index < 65536 + | Aiur.NativeAIR.Node.publicInput index => index < 256 + | Aiur.NativeAIR.Node.add a b => a < 65536 ∧ b < 65536 + | Aiur.NativeAIR.Node.sub a b => a < 65536 ∧ b < 65536 + | Aiur.NativeAIR.Node.mul a b => a < 65536 ∧ b < 65536 + | Aiur.NativeAIR.Node.neg child => child < 65536 +PREMISE Aiur.NativeAIR.KeyCodec.LookupWireFits.mk +∀ {lookup : Aiur.NativeAIR.Lookup}, + lookup.multiplicity < 65536 → + lookup.args.length < 65536 → + (∀ (arg : Nat), arg ∈ lookup.args → arg < 65536) → Aiur.NativeAIR.KeyCodec.LookupWireFits lookup +PREMISE Aiur.NativeAIR.KeyCodec.CircuitWireFits.mk +∀ {circuit : Aiur.NativeAIR.KeyCodec.Circuit}, + circuit.mainWidth < 65536 → + circuit.preprocessedWidth < 65536 → + circuit.preprocessedHeight < 2 ^ 32 → + circuit.maxConstraintDegree < 65536 → + circuit.lookupGroupSize < 256 → + circuit.graph.nodes.length < 65536 → + (∀ (node : Aiur.NativeAIR.Node), node ∈ circuit.graph.nodes → Aiur.NativeAIR.KeyCodec.NodeWireFits node) → + circuit.graph.zeros.length < 65536 → + (∀ (index : Nat), index ∈ circuit.graph.zeros → index < 65536) → + circuit.graph.lookups.length < 65536 → + (∀ (lookup : Aiur.NativeAIR.Lookup), + lookup ∈ circuit.graph.lookups → Aiur.NativeAIR.KeyCodec.LookupWireFits lookup) → + Aiur.NativeAIR.KeyCodec.CircuitWireFits circuit +PREMISE Aiur.NativeAIR.KeyCodec.ParametersWireFits +Aiur.NativeAIR.KeyCodec.Parameters → Prop +DEFINITION +fun parameters => + ∀ (value : Nat), + value ∈ + [parameters.logBlowup, parameters.capHeight, parameters.logFinalPolyLen, parameters.maxLogArity, + parameters.numQueries, parameters.commitProofOfWorkBits, parameters.queryProofOfWorkBits] → + value < 65536 +PREMISE Aiur.NativeAIR.KeyCodec.CommitmentWireFits +Option Aiur.NativeAIR.KeyCodec.MerkleCap → Prop +DEFINITION +fun x => + match x with + | none => True + | some cap => + List.length cap < 65536 ∧ + (List.length cap).isPowerOfTwo ∧ ∀ (digest : List UInt8), digest ∈ cap → digest.length = 32 +PREMISE Aiur.NativeAIR.KeyCodec.IndexWireFits +Option Nat → Prop +DEFINITION +fun x => + match x with + | none => True + | some index => index < 65535 +PREMISE Aiur.NativeAIR.KeyCodec.KeyWireFits.mk +∀ {key : Aiur.NativeAIR.KeyCodec.Key}, + Aiur.NativeAIR.KeyCodec.ParametersWireFits key.parameters → + key.circuits.length < 65536 → + (∀ (circuit : Aiur.NativeAIR.KeyCodec.Circuit), + circuit ∈ key.circuits → Aiur.NativeAIR.KeyCodec.CircuitWireFits circuit) → + Aiur.NativeAIR.KeyCodec.CommitmentWireFits key.preprocessedCommitment → + key.preprocessedIndices.length = key.circuits.length → + (∀ (index : Option Nat), index ∈ key.preprocessedIndices → Aiur.NativeAIR.KeyCodec.IndexWireFits index) → + Aiur.NativeAIR.KeyCodec.KeyWireFits key +PREMISE Aiur.NativeAIR.KeyCodec.Returns +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → (α → Prop) → Prop +DEFINITION +fun {α} read property => + ∀ (bytes : List UInt8) (value : α) (rest : List UInt8), read bytes = some (value, rest) → property value +PREMISE Aiur.NativeAIR.KeyCodec.CommitmentValid +Option Aiur.NativeAIR.KeyCodec.MerkleCap → Prop +DEFINITION +fun x => + match x with + | none => True + | some cap => (List.length cap).isPowerOfTwo ∧ ∀ (digest : List UInt8), digest ∈ cap → digest.length = 32 +PREMISE Aiur.NativeAIR.CompiledKey.main +Nat → Aiur.NativeAIR.Expr +DEFINITION +fun index => + Aiur.NativeAIR.Expr.var + { source := Aiur.NativeAIR.Source.main, offset := Aiur.NativeAIR.RowOffset.current, index := index } +PREMISE Aiur.NativeAIR.CompiledKey.next +Nat → Aiur.NativeAIR.Expr +DEFINITION +fun index => + Aiur.NativeAIR.Expr.var + { source := Aiur.NativeAIR.Source.main, offset := Aiur.NativeAIR.RowOffset.next, index := index } +PREMISE Aiur.NativeAIR.CompiledKey.preprocessed +Nat → Aiur.NativeAIR.Expr +DEFINITION +fun index => + Aiur.NativeAIR.Expr.var + { source := Aiur.NativeAIR.Source.preprocessed, offset := Aiur.NativeAIR.RowOffset.current, index := index } +PREMISE Aiur.NativeAIR.CompiledKey.memoryEquations +List Aiur.NativeAIR.Expr +DEFINITION +have selector := Aiur.NativeAIR.CompiledKey.main 1; +have transition := (Aiur.NativeAIR.CompiledKey.next 1).frontMul Aiur.NativeAIR.Expr.isTransition; +[selector.frontMul (selector.frontSub (Aiur.NativeAIR.Expr.konst 1)), + (Aiur.NativeAIR.CompiledKey.main 0).frontMul ((Aiur.NativeAIR.Expr.konst 1).frontSub selector), + transition.frontMul (selector.frontSub (Aiur.NativeAIR.Expr.konst 1)), + transition.frontMul + (((Aiur.NativeAIR.CompiledKey.main 2).frontAdd (Aiur.NativeAIR.Expr.konst 1)).frontSub + (Aiur.NativeAIR.CompiledKey.next 2))] +PREMISE Aiur.NativeAIR.CompiledKey.memoryLookup +Nat → Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun width => + { multiplicity := (Aiur.NativeAIR.CompiledKey.main 0).frontNeg, + args := + List.map (Aiur.NativeAIR.CompiledKey.main 1).frontMul + [Aiur.NativeAIR.Expr.konst 1, Aiur.NativeAIR.Expr.konst (Aiur.G.ofNat width), + Aiur.NativeAIR.CompiledKey.main 2] ++ + List.ofFn fun i => (Aiur.NativeAIR.CompiledKey.main 1).frontMul (Aiur.NativeAIR.CompiledKey.main (3 + ↑i)) } +PREMISE Aiur.NativeAIR.CompiledKey.byte1Lookup +Aiur.AIR.Byte1Kind → Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun kind => + { multiplicity := (Aiur.NativeAIR.CompiledKey.main ↑kind.column).frontNeg, + args := + match kind with + | Aiur.AIR.Byte1Kind.bits => + [Aiur.NativeAIR.Expr.konst 2, Aiur.NativeAIR.CompiledKey.preprocessed 0] ++ + List.ofFn fun i => Aiur.NativeAIR.CompiledKey.preprocessed (1 + ↑i) + | Aiur.AIR.Byte1Kind.shiftLeft => + [Aiur.NativeAIR.Expr.konst 3, Aiur.NativeAIR.CompiledKey.preprocessed 0, + Aiur.NativeAIR.CompiledKey.preprocessed 9] + | Aiur.AIR.Byte1Kind.shiftRight => + [Aiur.NativeAIR.Expr.konst 4, Aiur.NativeAIR.CompiledKey.preprocessed 0, + Aiur.NativeAIR.CompiledKey.preprocessed 10] } +PREMISE Aiur.NativeAIR.CompiledKey.byte2Lookup +Aiur.AIR.Byte2Kind → Aiur.NativeAIR.Compiler.ExprLookup +DEFINITION +fun kind => + { multiplicity := (Aiur.NativeAIR.CompiledKey.main ↑kind.column).frontNeg, + args := + [Aiur.NativeAIR.Expr.konst kind.channel, Aiur.NativeAIR.CompiledKey.preprocessed 0, + Aiur.NativeAIR.CompiledKey.preprocessed 1] ++ + match kind with + | Aiur.AIR.Byte2Kind.xor => [Aiur.NativeAIR.CompiledKey.preprocessed 2] + | Aiur.AIR.Byte2Kind.add => [Aiur.NativeAIR.CompiledKey.preprocessed 3] + | Aiur.AIR.Byte2Kind.sub => [Aiur.NativeAIR.CompiledKey.preprocessed 4] + | Aiur.AIR.Byte2Kind.and => [Aiur.NativeAIR.CompiledKey.preprocessed 5] + | Aiur.AIR.Byte2Kind.or => [Aiur.NativeAIR.CompiledKey.preprocessed 6] + | Aiur.AIR.Byte2Kind.lessThan => [Aiur.NativeAIR.CompiledKey.preprocessed 7] + | Aiur.AIR.Byte2Kind.range => [] + | Aiur.AIR.Byte2Kind.mul => + [Aiur.NativeAIR.CompiledKey.preprocessed 8, Aiur.NativeAIR.CompiledKey.preprocessed 9] + | Aiur.AIR.Byte2Kind.split7 => + [Aiur.NativeAIR.CompiledKey.preprocessed 10, Aiur.NativeAIR.CompiledKey.preprocessed 11] + | Aiur.AIR.Byte2Kind.split4 => + [Aiur.NativeAIR.CompiledKey.preprocessed 12, Aiur.NativeAIR.CompiledKey.preprocessed 13] } +PREMISE Aiur.NativeAIR.CompiledKey.circuit +Nat → Nat → Nat → Nat → Nat → Aiur.NativeAIR.Compiler.BaseCompilation → Option Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +fun logBlowup mainWidth preprocessedWidth preprocessedHeight groupSize base => + have raw := + { mainWidth := mainWidth, preprocessedWidth := preprocessedWidth, preprocessedHeight := preprocessedHeight, + maxConstraintDegree := 0, lookupGroupSize := groupSize, graph := base.graph }; + do + let degree ← raw.computedDegree + have result : Aiur.NativeAIR.KeyCodec.Circuit := + Aiur.NativeAIR.LookupGroups.retune + { mainWidth := raw.mainWidth, preprocessedWidth := raw.preprocessedWidth, + preprocessedHeight := raw.preprocessedHeight, maxConstraintDegree := degree, + lookupGroupSize := raw.lookupGroupSize, graph := raw.graph } + (2 ^ logBlowup) + if result.valid = true then some result else none +PREMISE Aiur.NativeAIR.CompiledKey.functionCircuit +Nat → Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +fun logBlowup program source => do + let compiled ← + Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths source) program source + have groupSize : Nat := + if (compiled.emission.branchless && decide (2 ≤ compiled.emission.lookups.length)) = true then 2 else 1 + Aiur.NativeAIR.CompiledKey.circuit logBlowup source.layout.width 0 0 groupSize compiled.base +PREMISE Aiur.NativeAIR.CompiledKey.memoryCircuit +Nat → Nat → Option Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +fun logBlowup width => do + let base ← + Aiur.NativeAIR.Compiler.compileBase { preprocessed := 0, main := 3 + width, stage2 := 0, publics := 0 } + [Aiur.NativeAIR.CompiledKey.memoryLookup width] Aiur.NativeAIR.CompiledKey.memoryEquations + Aiur.NativeAIR.CompiledKey.circuit logBlowup (3 + width) 0 0 1 base +PREMISE Aiur.NativeAIR.CompiledKey.byte1Circuit +Nat → Option Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +fun logBlowup => do + let base ← + Aiur.NativeAIR.Compiler.compileBase { preprocessed := 11, main := 3, stage2 := 0, publics := 0 } + (List.map Aiur.NativeAIR.CompiledKey.byte1Lookup Aiur.AIR.Byte1Kind.all) [] + Aiur.NativeAIR.CompiledKey.circuit logBlowup 3 11 256 2 base +PREMISE Aiur.NativeAIR.CompiledKey.byte2Circuit +Nat → Option Aiur.NativeAIR.KeyCodec.Circuit +DEFINITION +fun logBlowup => do + let base ← + Aiur.NativeAIR.Compiler.compileBase { preprocessed := 14, main := 10, stage2 := 0, publics := 0 } + (List.map Aiur.NativeAIR.CompiledKey.byte2Lookup Aiur.AIR.Byte2Kind.all) [] + Aiur.NativeAIR.CompiledKey.circuit logBlowup 10 14 65536 2 base +PREMISE Aiur.NativeAIR.CompiledKey.circuits +Nat → Aiur.Bytecode.Toplevel → Option (List Aiur.NativeAIR.KeyCodec.Circuit) +DEFINITION +fun logBlowup program => do + let functions ← List.mapM (Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program) program.circuits.toList + let memories ← List.mapM (Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup) program.memorySizes.toList + let byte1 ← Aiur.NativeAIR.CompiledKey.byte1Circuit logBlowup + let byte2 ← Aiur.NativeAIR.CompiledKey.byte2Circuit logBlowup + pure (functions ++ memories ++ [byte1, byte2]) +PREMISE Aiur.NativeAIR.CompiledKey.preprocessedIndices +Aiur.Bytecode.Toplevel → List (Option Nat) +DEFINITION +fun program => List.replicate (program.circuits.size + program.memorySizes.size) none ++ [some 0, some 1] +PREMISE Aiur.NativeAIR.CompiledKey.check +Aiur.Bytecode.Toplevel → Aiur.NativeAIR.KeyCodec.Key → Bool +DEFINITION +fun program key => + Aiur.NativeAIR.CompiledKey.circuits key.parameters.logBlowup program == some key.circuits && + key.preprocessedIndices == Aiur.NativeAIR.CompiledKey.preprocessedIndices program +PREMISE Aiur.BoundVerifier.CompiledBackend.mk +{selection : Aiur.BoundVerifier.Selection} → + (toBackend : Aiur.BoundVerifier.Backend selection) → + Aiur.NativeAIR.CompiledKey.check toBackend.compiled.bytecode toBackend.keyData = true → + Aiur.BoundVerifier.CompiledBackend selection +PREMISE Aiur.BoundVerifier.buildCompiled +(selection : Aiur.BoundVerifier.Selection) → Except String (Aiur.BoundVerifier.CompiledBackend selection) +DEFINITION +fun selection => do + let backend ← Aiur.BoundVerifier.build selection + if checked : Aiur.NativeAIR.CompiledKey.check backend.compiled.bytecode backend.keyData = true then + pure { toBackend := backend, graphsChecked := checked } + else throw "verification key circuits differ from the checked compilation" +PREMISE Aiur.BoundVerifier.verifyCompiled +{selection : Aiur.BoundVerifier.Selection} → + Aiur.BoundVerifier.CompiledBackend selection → Array Aiur.G → ByteArray → Except String Unit +DEFINITION +fun {selection} backend input bytes => Aiur.BoundVerifier.verify backend.toBackend input bytes +PREMISE Aiur.NativeAIR.GraphWidths.Le +Aiur.NativeAIR.GraphWidths → Aiur.NativeAIR.GraphWidths → Prop +DEFINITION +fun small large => + (∀ (source : Aiur.NativeAIR.Source), small.width source ≤ large.width source) ∧ small.publics ≤ large.publics +PREMISE Aiur.NativeAIR.CompiledKey.columns +Aiur.NativeAIR.Values Aiur.G → Aiur.NativeAIR.Source → Aiur.NativeAIR.RowOffset → (width : Nat) → Fin width → Aiur.G +DEFINITION +fun values source offset width index => (values.columns source offset)[↑index]?.getD 0 +PREMISE Aiur.NativeAIR.ProofCodec.Extension.mk +Aiur.G → Aiur.G → Aiur.NativeAIR.ProofCodec.Extension +PREMISE Aiur.NativeAIR.ProofCodec.Digest +Type +DEFINITION +List UInt8 +PREMISE Aiur.NativeAIR.ProofCodec.Cap +Type +DEFINITION +List Aiur.NativeAIR.ProofCodec.Digest +PREMISE Aiur.NativeAIR.ProofCodec.Openings +Type → Type +DEFINITION +fun α => List (List (List α)) +PREMISE Aiur.NativeAIR.ProofCodec.readVector +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → Aiur.NativeAIR.KeyCodec.Reader (List α) +DEFINITION +fun {α} read => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readNat 8 + Aiur.NativeAIR.KeyCodec.readMany read __do_lift +PREMISE Aiur.NativeAIR.ProofCodec.encodeVector +{α : Type u_1} → (α → List UInt8) → List α → List UInt8 +DEFINITION +fun {α} encode values => Aiur.NativeAIR.KeyCodec.encodeNat 8 values.length ++ List.flatMap encode values +PREMISE Aiur.NativeAIR.ProofCodec.readOption +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → Aiur.NativeAIR.KeyCodec.Reader (Option α) +DEFINITION +fun {α} read => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readByte + match __do_lift.toNat with + | 0 => pure none + | 1 => do + let __do_lift ← read + pure (some __do_lift) + | x => failure +PREMISE Aiur.NativeAIR.ProofCodec.encodeOption +{α : Type u_1} → (α → List UInt8) → Option α → List UInt8 +DEFINITION +fun {α} encode x => + match x with + | none => [0] + | some value => 1 :: encode value +PREMISE Aiur.NativeAIR.ProofCodec.readBool +Aiur.NativeAIR.KeyCodec.Reader Bool +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readByte + match __do_lift.toNat with + | 0 => pure false + | 1 => pure true + | x => failure +PREMISE Aiur.NativeAIR.ProofCodec.encodeBool +Bool → List UInt8 +DEFINITION +fun value => [if value = true then 1 else 0] +PREMISE Aiur.NativeAIR.ProofCodec.readField +Aiur.NativeAIR.KeyCodec.Reader Aiur.G +DEFINITION +do + let value ← Aiur.NativeAIR.KeyCodec.readNat 8 + if value < Aiur.gSize.toNat then pure (Aiur.G.ofNat value) else failure +PREMISE Aiur.NativeAIR.ProofCodec.encodeField +Aiur.G → List UInt8 +DEFINITION +fun value => Aiur.NativeAIR.KeyCodec.encodeNat 8 value.n +PREMISE Aiur.NativeAIR.ProofCodec.readExtension +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.ProofCodec.readField + let __do_lift_1 ← Aiur.NativeAIR.ProofCodec.readField + pure { c0 := __do_lift, c1 := __do_lift_1 } +PREMISE Aiur.NativeAIR.ProofCodec.encodeExtension +Aiur.NativeAIR.ProofCodec.Extension → List UInt8 +DEFINITION +fun value => Aiur.NativeAIR.ProofCodec.encodeField value.c0 ++ Aiur.NativeAIR.ProofCodec.encodeField value.c1 +PREMISE Aiur.NativeAIR.ProofCodec.readCap +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.ProofCodec.Cap +DEFINITION +Aiur.NativeAIR.ProofCodec.readVector (Aiur.NativeAIR.KeyCodec.readMany Aiur.NativeAIR.KeyCodec.readByte 32) +PREMISE Aiur.NativeAIR.ProofCodec.encodeCap +Aiur.NativeAIR.ProofCodec.Cap → List UInt8 +DEFINITION +fun cap => Aiur.NativeAIR.ProofCodec.encodeVector id cap +PREMISE Aiur.NativeAIR.ProofCodec.readOpenings +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → Aiur.NativeAIR.KeyCodec.Reader (Aiur.NativeAIR.ProofCodec.Openings α) +DEFINITION +fun {α} read => + Aiur.NativeAIR.ProofCodec.readVector + (Aiur.NativeAIR.ProofCodec.readVector (Aiur.NativeAIR.ProofCodec.readVector read)) +PREMISE Aiur.NativeAIR.ProofCodec.encodeOpenings +{α : Type} → (α → List UInt8) → Aiur.NativeAIR.ProofCodec.Openings α → List UInt8 +DEFINITION +fun {α} encode values => + Aiur.NativeAIR.ProofCodec.encodeVector + (Aiur.NativeAIR.ProofCodec.encodeVector (Aiur.NativeAIR.ProofCodec.encodeVector encode)) values +PREMISE Aiur.NativeAIR.ProofCodec.Commitments.mk +Aiur.NativeAIR.ProofCodec.Cap → + Aiur.NativeAIR.ProofCodec.Cap → Aiur.NativeAIR.ProofCodec.Cap → Aiur.NativeAIR.ProofCodec.Commitments +PREMISE Aiur.NativeAIR.ProofCodec.readCommitments +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.ProofCodec.Commitments +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.ProofCodec.readCap + let __do_lift_1 ← Aiur.NativeAIR.ProofCodec.readCap + let __do_lift_2 ← Aiur.NativeAIR.ProofCodec.readCap + pure { stage1 := __do_lift, stage2 := __do_lift_1, quotient := __do_lift_2 } +PREMISE Aiur.NativeAIR.ProofCodec.encodeCommitments +Aiur.NativeAIR.ProofCodec.Commitments → List UInt8 +DEFINITION +fun value => + Aiur.NativeAIR.ProofCodec.encodeCap value.stage1 ++ Aiur.NativeAIR.ProofCodec.encodeCap value.stage2 ++ + Aiur.NativeAIR.ProofCodec.encodeCap value.quotient +PREMISE Aiur.NativeAIR.ProofCodec.BatchOpening.mk +Aiur.NativeAIR.ProofCodec.Openings Aiur.G → + List Aiur.NativeAIR.ProofCodec.Digest → Aiur.NativeAIR.ProofCodec.BatchOpening +PREMISE Aiur.NativeAIR.ProofCodec.readBatchOpening +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.ProofCodec.BatchOpening +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.ProofCodec.readOpenings Aiur.NativeAIR.ProofCodec.readField + let __do_lift_1 ← Aiur.NativeAIR.ProofCodec.readCap + pure { values := __do_lift, siblingHashes := __do_lift_1 } +PREMISE Aiur.NativeAIR.ProofCodec.encodeBatchOpening +Aiur.NativeAIR.ProofCodec.BatchOpening → List UInt8 +DEFINITION +fun value => + Aiur.NativeAIR.ProofCodec.encodeOpenings Aiur.NativeAIR.ProofCodec.encodeField value.values ++ + Aiur.NativeAIR.ProofCodec.encodeCap value.siblingHashes +PREMISE Aiur.NativeAIR.ProofCodec.CommitStep.mk +UInt8 → + List (List Aiur.NativeAIR.ProofCodec.Extension) → + List Aiur.NativeAIR.ProofCodec.Digest → Aiur.NativeAIR.ProofCodec.CommitStep +PREMISE Aiur.NativeAIR.ProofCodec.readCommitStep +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.ProofCodec.CommitStep +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.KeyCodec.readByte + let __do_lift_1 ← + Aiur.NativeAIR.ProofCodec.readVector (Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readExtension) + let __do_lift_2 ← Aiur.NativeAIR.ProofCodec.readCap + pure { logArity := __do_lift, siblingValues := __do_lift_1, siblingHashes := __do_lift_2 } +PREMISE Aiur.NativeAIR.ProofCodec.encodeCommitStep +Aiur.NativeAIR.ProofCodec.CommitStep → List UInt8 +DEFINITION +fun value => + value.logArity :: + (Aiur.NativeAIR.ProofCodec.encodeVector + (Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeExtension) value.siblingValues ++ + Aiur.NativeAIR.ProofCodec.encodeCap value.siblingHashes) +PREMISE Aiur.NativeAIR.ProofCodec.Fri.mk +List Aiur.NativeAIR.ProofCodec.Cap → + List Aiur.G → + List Aiur.NativeAIR.ProofCodec.BatchOpening → + List Aiur.NativeAIR.ProofCodec.CommitStep → + List Aiur.NativeAIR.ProofCodec.Extension → Aiur.G → Aiur.NativeAIR.ProofCodec.Fri +PREMISE Aiur.NativeAIR.ProofCodec.readFri +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.ProofCodec.Fri +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readCap + let __do_lift_1 ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readField + let __do_lift_2 ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readBatchOpening + let __do_lift_3 ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readCommitStep + let __do_lift_4 ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readExtension + let __do_lift_5 ← Aiur.NativeAIR.ProofCodec.readField + pure + { commits := __do_lift, commitPowWitnesses := __do_lift_1, inputOpenings := __do_lift_2, + commitOpenings := __do_lift_3, finalPoly := __do_lift_4, queryPowWitness := __do_lift_5 } +PREMISE Aiur.NativeAIR.ProofCodec.encodeFri +Aiur.NativeAIR.ProofCodec.Fri → List UInt8 +DEFINITION +fun value => + Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeCap value.commits ++ + Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeField value.commitPowWitnesses ++ + Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeBatchOpening value.inputOpenings ++ + Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeCommitStep value.commitOpenings ++ + Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeExtension value.finalPoly ++ + Aiur.NativeAIR.ProofCodec.encodeField value.queryPowWitness +PREMISE Aiur.NativeAIR.ProofCodec.Data.mk +List Bool → + Aiur.NativeAIR.ProofCodec.Commitments → + List Aiur.NativeAIR.ProofCodec.Extension → + List UInt8 → + Aiur.NativeAIR.ProofCodec.Fri → + Aiur.NativeAIR.ProofCodec.Openings Aiur.NativeAIR.ProofCodec.Extension → + Option (Aiur.NativeAIR.ProofCodec.Openings Aiur.NativeAIR.ProofCodec.Extension) → + Aiur.NativeAIR.ProofCodec.Openings Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Openings Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofCodec.Data +PREMISE Aiur.NativeAIR.ProofCodec.readData +Aiur.NativeAIR.KeyCodec.Reader Aiur.NativeAIR.ProofCodec.Data +DEFINITION +do + let __do_lift ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readBool + let __do_lift_1 ← Aiur.NativeAIR.ProofCodec.readCommitments + let __do_lift_2 ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.ProofCodec.readExtension + let __do_lift_3 ← Aiur.NativeAIR.ProofCodec.readVector Aiur.NativeAIR.KeyCodec.readByte + let __do_lift_4 ← Aiur.NativeAIR.ProofCodec.readFri + let __do_lift_5 ← Aiur.NativeAIR.ProofCodec.readOpenings Aiur.NativeAIR.ProofCodec.readExtension + let __do_lift_6 ← + Aiur.NativeAIR.ProofCodec.readOption + (Aiur.NativeAIR.ProofCodec.readOpenings Aiur.NativeAIR.ProofCodec.readExtension) + let __do_lift_7 ← Aiur.NativeAIR.ProofCodec.readOpenings Aiur.NativeAIR.ProofCodec.readExtension + let __do_lift_8 ← Aiur.NativeAIR.ProofCodec.readOpenings Aiur.NativeAIR.ProofCodec.readExtension + pure + { active := __do_lift, commitments := __do_lift_1, accumulators := __do_lift_2, logDegrees := __do_lift_3, + fri := __do_lift_4, quotient := __do_lift_5, preprocessed := __do_lift_6, stage1 := __do_lift_7, + stage2 := __do_lift_8 } +PREMISE Aiur.NativeAIR.ProofCodec.encodeData +Aiur.NativeAIR.ProofCodec.Data → List UInt8 +DEFINITION +fun value => + Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeBool value.active ++ + Aiur.NativeAIR.ProofCodec.encodeCommitments value.commitments ++ + Aiur.NativeAIR.ProofCodec.encodeVector Aiur.NativeAIR.ProofCodec.encodeExtension value.accumulators ++ + Aiur.NativeAIR.ProofCodec.encodeVector (fun b => [b]) value.logDegrees ++ + Aiur.NativeAIR.ProofCodec.encodeFri value.fri ++ + Aiur.NativeAIR.ProofCodec.encodeOpenings Aiur.NativeAIR.ProofCodec.encodeExtension value.quotient ++ + Aiur.NativeAIR.ProofCodec.encodeOption + (Aiur.NativeAIR.ProofCodec.encodeOpenings Aiur.NativeAIR.ProofCodec.encodeExtension) value.preprocessed ++ + Aiur.NativeAIR.ProofCodec.encodeOpenings Aiur.NativeAIR.ProofCodec.encodeExtension value.stage1 ++ + Aiur.NativeAIR.ProofCodec.encodeOpenings Aiur.NativeAIR.ProofCodec.encodeExtension value.stage2 +PREMISE Aiur.NativeAIR.ProofCodec.decode +ByteArray → Option Aiur.NativeAIR.ProofCodec.Data +DEFINITION +fun bytes => do + let __x ← Aiur.NativeAIR.ProofCodec.readData bytes.data.toList + match __x with + | (value, rest) => if rest.isEmpty = true then some value else none +PREMISE Aiur.NativeAIR.ProofCodec.encode +Aiur.NativeAIR.ProofCodec.Data → ByteArray +DEFINITION +fun value => (Aiur.NativeAIR.ProofCodec.encodeData value).toByteArray +PREMISE Aiur.NativeAIR.ProofCodec.decodeCanonical +ByteArray → Option Aiur.NativeAIR.ProofCodec.Data +DEFINITION +fun bytes => do + let value ← Aiur.NativeAIR.ProofCodec.decode bytes + if Aiur.NativeAIR.ProofCodec.encode value = bytes then some value else none +PREMISE Aiur.NativeAIR.ProofShape.Pair.mk +List Aiur.NativeAIR.ProofCodec.Extension → List Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofShape.Pair +PREMISE Aiur.NativeAIR.ProofShape.pair +List (List Aiur.NativeAIR.ProofCodec.Extension) → Option Aiur.NativeAIR.ProofShape.Pair +DEFINITION +fun x => + match x with + | [current, next] => some { current := current, next := next } + | x => none +PREMISE Aiur.NativeAIR.ProofShape.single +{α : Type u_1} → List α → Option α +DEFINITION +fun {α} x => + match x with + | [value] => some value + | x => none +PREMISE Aiur.NativeAIR.ProofShape.activeIndices +Aiur.NativeAIR.ProofCodec.Data → List Nat +DEFINITION +fun proof => + List.filterMap + (fun x => + match x with + | (active, index) => if active = true then some index else none) + proof.active.zipIdx +PREMISE Aiur.NativeAIR.ProofShape.quotientDegree +Aiur.NativeAIR.KeyCodec.Circuit → Nat +DEFINITION +fun circuit => (max circuit.maxConstraintDegree 2 - 1).nextPowerOfTwo +PREMISE Aiur.NativeAIR.ProofShape.Row.mk +Nat → + Aiur.NativeAIR.KeyCodec.Circuit → + UInt8 → + Aiur.NativeAIR.ProofShape.Pair → + Aiur.NativeAIR.ProofShape.Pair → + Option Aiur.NativeAIR.ProofShape.Pair → + List Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofShape.Row +PREMISE Aiur.NativeAIR.ProofShape.readPreprocessed +Aiur.NativeAIR.ProofCodec.Data → Option Nat → Option (Option Aiur.NativeAIR.ProofShape.Pair) +DEFINITION +fun proof x => + match x with + | none => some none + | some slot => Option.map some (proof.preprocessed >>= fun opened => opened[slot]? >>= Aiur.NativeAIR.ProofShape.pair) +PREMISE Aiur.NativeAIR.ProofShape.readRow +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Nat → Nat → Option Aiur.NativeAIR.ProofShape.Row +DEFINITION +fun key proof index position => do + let circuit ← key.circuits[index]? + let preprocessedIndex ← key.preprocessedIndices[index]? + let degree ← proof.logDegrees[position]? + let __do_lift ← proof.stage1[position]? + let stage1 ← Aiur.NativeAIR.ProofShape.pair __do_lift + let __do_lift ← proof.stage2[position]? + let stage2 ← Aiur.NativeAIR.ProofShape.pair __do_lift + let __do_lift ← proof.quotient[position]? + let quotient ← Aiur.NativeAIR.ProofShape.single __do_lift + let accumulator ← proof.accumulators[position]? + let preprocessed ← Aiur.NativeAIR.ProofShape.readPreprocessed proof preprocessedIndex + pure + { circuitIndex := index, circuit := circuit, logDegree := degree, stage1 := stage1, stage2 := stage2, + preprocessed := preprocessed, quotient := quotient, accumulator := accumulator } +PREMISE Aiur.NativeAIR.ProofShape.Pair.hasWidth +Aiur.NativeAIR.ProofShape.Pair → Nat → Bool +DEFINITION +fun values width => values.current.length == width && values.next.length == width +PREMISE Aiur.NativeAIR.ProofShape.Row.fits +Aiur.NativeAIR.KeyCodec.Parameters → Aiur.NativeAIR.ProofShape.Row → Bool +DEFINITION +fun parameters row => + (row.stage1.hasWidth row.circuit.mainWidth && row.stage2.hasWidth row.circuit.widths.stage2 && + match row.preprocessed with + | none => true + | some values => values.hasWidth row.circuit.preprocessedWidth) && + row.quotient.length == Aiur.NativeAIR.ProofShape.quotientDegree row.circuit * 2 && + decide + (row.logDegree.toNat + (Aiur.NativeAIR.ProofShape.quotientDegree row.circuit).log2 ≤ 32 - parameters.logBlowup) +PREMISE Aiur.NativeAIR.ProofShape.header +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Bool +DEFINITION +fun key proof => + have active := (Aiur.NativeAIR.ProofShape.activeIndices proof).length; + have preprocessed := (List.filter Option.isSome key.preprocessedIndices).length; + !key.circuits.isEmpty && proof.active.length == key.circuits.length && decide (active > 0) && + key.preprocessedIndices.length == key.circuits.length && + proof.logDegrees.length == active && + key.preprocessedCommitment.isNone == (preprocessed == 0) && + List.length (proof.preprocessed.getD []) == preprocessed && + List.length proof.stage1 == active && + List.length proof.stage2 == active && + List.length proof.quotient == active && + proof.accumulators.length == active +PREMISE Aiur.NativeAIR.ProofShape.inactivePreprocessed +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Bool +DEFINITION +fun key proof => + (key.preprocessedIndices.zip proof.active).all fun x => + match x with + | (slot, active) => + match slot, active with + | some index, false => (proof.preprocessed.getD [])[index]? == some [] + | x, x_1 => true +PREMISE Aiur.NativeAIR.ProofShape.rows +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Option (List Aiur.NativeAIR.ProofShape.Row) +DEFINITION +fun key proof => + List.mapM + (fun x => + match x with + | (index, position) => Aiur.NativeAIR.ProofShape.readRow key proof index position) + (Aiur.NativeAIR.ProofShape.activeIndices proof).zipIdx +PREMISE Aiur.NativeAIR.ProofShape.check +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Option (List Aiur.NativeAIR.ProofShape.Row) +DEFINITION +fun key proof => + if + (Aiur.NativeAIR.ProofShape.header key proof && Aiur.NativeAIR.ProofShape.inactivePreprocessed key proof) = + true then + do + let result ← Aiur.NativeAIR.ProofShape.rows key proof + if result.all (Aiur.NativeAIR.ProofShape.Row.fits key.parameters) = true then some result else none + else none +PREMISE Aiur.NativeAIR.ProofShape.fixedHeights +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Bool +DEFINITION +fun key proof => + Aiur.fixedTraceHeights (List.map (fun x => x.preprocessedHeight) key.circuits) proof.active + (List.map UInt8.toNat proof.logDegrees) +PREMISE Aiur.NativeAIR.ProofShape.queryBound +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Option Nat +DEFINITION +fun key proof => + Aiur.lookupQueryBound (List.map (fun x => x.graph.lookups.length) key.circuits) proof.active + (List.map UInt8.toNat proof.logDegrees) +PREMISE Aiur.BoundVerifier.CheckedProof.mk +{key : Aiur.NativeAIR.KeyCodec.Key} → + {bytes : ByteArray} → + (data : Aiur.NativeAIR.ProofCodec.Data) → + (rows : List Aiur.NativeAIR.ProofShape.Row) → + (bound : Nat) → + Aiur.NativeAIR.ProofCodec.decodeCanonical bytes = some data → + Aiur.NativeAIR.ProofShape.check key data = some rows → + Aiur.NativeAIR.ProofShape.fixedHeights key data = true → + Aiur.NativeAIR.ProofShape.queryBound key data = some bound → + Aiur.NativeAIR.MerkleCap.check key data = true → Aiur.BoundVerifier.CheckedProof key bytes +PREMISE Aiur.BoundVerifier.readProof +(key : Aiur.NativeAIR.KeyCodec.Key) → (bytes : ByteArray) → Except String (Aiur.BoundVerifier.CheckedProof key bytes) +DEFINITION +fun key bytes => + match parsed : Aiur.NativeAIR.ProofCodec.decodeCanonical bytes with + | none => Except.error "proof is not a canonical complete artifact" + | some data => + match shape : Aiur.NativeAIR.ProofShape.check key data with + | none => Except.error "proof opening shape differs from the selected key" + | some rows => + if fixed : Aiur.NativeAIR.ProofShape.fixedHeights key data = true then + match budget : Aiur.NativeAIR.ProofShape.queryBound key data with + | none => Except.error "proof lookup budget exceeds its bound" + | some bound => + if cap : Aiur.NativeAIR.MerkleCap.check key data = true then + Except.ok + { data := data, rows := rows, bound := bound, decoded := parsed, shape := shape, fixed := fixed, + budget := budget, cap := cap } + else Except.error "proof Merkle cap omits a committed matrix height" + else Except.error "proof fixed table heights differ from the selected key" +PREMISE Aiur.BoundVerifier.verifyShaped +{selection : Aiur.BoundVerifier.Selection} → + Aiur.BoundVerifier.CompiledBackend selection → Array Aiur.G → ByteArray → Except String Unit +DEFINITION +fun {selection} backend input bytes => do + let _ ← Aiur.BoundVerifier.readProof backend.keyData bytes + Aiur.BoundVerifier.verifyCompiled backend input bytes +PREMISE Aiur.NativeAIR.ProofCodec.VectorFits +{α : Type u_1} → (α → Prop) → List α → Prop +DEFINITION +fun {α} property values => values.length < 256 ^ 8 ∧ ∀ (value : α), value ∈ values → property value +PREMISE Aiur.NativeAIR.ProofCodec.CapFits +Aiur.NativeAIR.ProofCodec.Cap → Prop +DEFINITION +fun cap => Aiur.NativeAIR.ProofCodec.VectorFits (fun digest => List.length digest = 32) cap +PREMISE Aiur.NativeAIR.ProofCodec.OpeningsFits +{α : Type} → Aiur.NativeAIR.ProofCodec.Openings α → Prop +DEFINITION +fun {α} values => + Aiur.NativeAIR.ProofCodec.VectorFits + (Aiur.NativeAIR.ProofCodec.VectorFits (Aiur.NativeAIR.ProofCodec.VectorFits fun x => True)) values +PREMISE Aiur.NativeAIR.ProofCodec.CommitmentsFits.mk +∀ {value : Aiur.NativeAIR.ProofCodec.Commitments}, + Aiur.NativeAIR.ProofCodec.CapFits value.stage1 → + Aiur.NativeAIR.ProofCodec.CapFits value.stage2 → + Aiur.NativeAIR.ProofCodec.CapFits value.quotient → Aiur.NativeAIR.ProofCodec.CommitmentsFits value +PREMISE Aiur.NativeAIR.ProofCodec.BatchOpeningFits.mk +∀ {value : Aiur.NativeAIR.ProofCodec.BatchOpening}, + Aiur.NativeAIR.ProofCodec.OpeningsFits value.values → + Aiur.NativeAIR.ProofCodec.CapFits value.siblingHashes → Aiur.NativeAIR.ProofCodec.BatchOpeningFits value +PREMISE Aiur.NativeAIR.ProofCodec.CommitStepFits.mk +∀ {value : Aiur.NativeAIR.ProofCodec.CommitStep}, + Aiur.NativeAIR.ProofCodec.VectorFits (Aiur.NativeAIR.ProofCodec.VectorFits fun x => True) value.siblingValues → + Aiur.NativeAIR.ProofCodec.CapFits value.siblingHashes → Aiur.NativeAIR.ProofCodec.CommitStepFits value +PREMISE Aiur.NativeAIR.ProofCodec.FriFits.mk +∀ {value : Aiur.NativeAIR.ProofCodec.Fri}, + Aiur.NativeAIR.ProofCodec.VectorFits Aiur.NativeAIR.ProofCodec.CapFits value.commits → + value.commitPowWitnesses.length < 256 ^ 8 → + Aiur.NativeAIR.ProofCodec.VectorFits Aiur.NativeAIR.ProofCodec.BatchOpeningFits value.inputOpenings → + Aiur.NativeAIR.ProofCodec.VectorFits Aiur.NativeAIR.ProofCodec.CommitStepFits value.commitOpenings → + value.finalPoly.length < 256 ^ 8 → Aiur.NativeAIR.ProofCodec.FriFits value +PREMISE Aiur.NativeAIR.ProofCodec.DataFits.mk +∀ {value : Aiur.NativeAIR.ProofCodec.Data}, + value.active.length < 256 ^ 8 → + Aiur.NativeAIR.ProofCodec.CommitmentsFits value.commitments → + value.accumulators.length < 256 ^ 8 → + value.logDegrees.length < 256 ^ 8 → + Aiur.NativeAIR.ProofCodec.FriFits value.fri → + Aiur.NativeAIR.ProofCodec.OpeningsFits value.quotient → + (∀ (openings : Aiur.NativeAIR.ProofCodec.Openings Aiur.NativeAIR.ProofCodec.Extension), + value.preprocessed = some openings → Aiur.NativeAIR.ProofCodec.OpeningsFits openings) → + Aiur.NativeAIR.ProofCodec.OpeningsFits value.stage1 → + Aiur.NativeAIR.ProofCodec.OpeningsFits value.stage2 → Aiur.NativeAIR.ProofCodec.DataFits value +PREMISE Aiur.NativeAIR.ProofShape.Row.Sourced.mk +∀ {key : Aiur.NativeAIR.KeyCodec.Key} {proof : Aiur.NativeAIR.ProofCodec.Data} {index position : Nat} + {row : Aiur.NativeAIR.ProofShape.Row}, + row.circuitIndex = index → + key.circuits[index]? = some row.circuit → + proof.logDegrees[position]? = some row.logDegree → + proof.stage1[position]? = some [row.stage1.current, row.stage1.next] → + proof.stage2[position]? = some [row.stage2.current, row.stage2.next] → + proof.quotient[position]? = some [row.quotient] → + proof.accumulators[position]? = some row.accumulator → + (∃ slot, + key.preprocessedIndices[index]? = some slot ∧ + Aiur.NativeAIR.ProofShape.readPreprocessed proof slot = some row.preprocessed) → + Aiur.NativeAIR.ProofShape.Row.Sourced key proof index position row +PREMISE Aiur.NativeAIR.ProofShape.Row.Fits.mk +∀ {parameters : Aiur.NativeAIR.KeyCodec.Parameters} {row : Aiur.NativeAIR.ProofShape.Row}, + row.stage1.current.length = row.circuit.mainWidth ∧ row.stage1.next.length = row.circuit.mainWidth → + row.stage2.current.length = row.circuit.widths.stage2 ∧ row.stage2.next.length = row.circuit.widths.stage2 → + (∀ (values : Aiur.NativeAIR.ProofShape.Pair), + row.preprocessed = some values → + values.current.length = row.circuit.preprocessedWidth ∧ + values.next.length = row.circuit.preprocessedWidth) → + row.quotient.length = Aiur.NativeAIR.ProofShape.quotientDegree row.circuit * 2 → + row.logDegree.toNat + (Aiur.NativeAIR.ProofShape.quotientDegree row.circuit).log2 ≤ + 32 - parameters.logBlowup → + Aiur.NativeAIR.ProofShape.Row.Fits parameters row +PREMISE Aiur.NativeAIR.ProofCodec.Extension.ofBase +Aiur.G → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value => { c0 := value, c1 := 0 } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.ofNat +{n : Nat} → OfNat Aiur.NativeAIR.ProofCodec.Extension n +DEFINITION +fun {n} => { ofNat := Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.G.ofNat n) } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.add +Add Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ add := fun a b => { c0 := a.c0 + b.c0, c1 := a.c1 + b.c1 } } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.sub +Sub Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ sub := fun a b => { c0 := a.c0 - b.c0, c1 := a.c1 - b.c1 } } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.neg +Neg Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ neg := fun a => { c0 := 0 - a.c0, c1 := 0 - a.c1 } } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.mul +Mul Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ mul := fun a b => { c0 := a.c0 * b.c0 + a.c1 * (b.c1 * 7), c1 := a.c0 * b.c1 + a.c1 * b.c0 } } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.basis +Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ c0 := 0, c1 := 1 } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.conjugate +Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value => { c0 := value.c0, c1 := 0 - value.c1 } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.norm +Aiur.NativeAIR.ProofCodec.Extension → Aiur.G +DEFINITION +fun value => value.c0 * value.c0 - 7 * (value.c1 * value.c1) +PREMISE Aiur.NativeAIR.ProofCodec.Extension.scale +Aiur.NativeAIR.ProofCodec.Extension → Aiur.G → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value scalar => { c0 := value.c0 * scalar, c1 := value.c1 * scalar } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.powBits +Aiur.NativeAIR.ProofCodec.Extension → Nat → Nat → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value exponent x => + Nat.brecOn (motive := fun x => Nat → Aiur.NativeAIR.ProofCodec.Extension) x + (Aiur.NativeAIR.ProofCodec.Extension.powBits._f value) exponent +PREMISE Aiur.NativeAIR.ProofCodec.Extension.power +Aiur.NativeAIR.ProofCodec.Extension → Nat → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value exponent => value.powBits exponent (exponent.log2 + 1) +PREMISE Aiur.NativeAIR.ProofCodec.Extension.tryInverse +Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value => if (value == 0) = true then none else some (value.conjugate.scale value.norm.inverse) +PREMISE Aiur.NativeAIR.ProofCodec.Extension.evalOps +Aiur.NativeAIR.EvalOps Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ konst := Aiur.NativeAIR.ProofCodec.Extension.ofBase, add := fun x1 x2 => x1 + x2, sub := fun x1 x2 => x1 - x2, + mul := fun x1 x2 => x1 * x2, neg := fun x => -x } +PREMISE Aiur.G.characteristicNeZero +NeZero Aiur.gSize.toNat +PREMISE Aiur.G.residue +Aiur.G → Fin Aiur.gSize.toNat +DEFINITION +fun value => ⟨value.n, ⋯⟩ +PREMISE Aiur.G.neg +Neg Aiur.G +DEFINITION +{ neg := fun x => 0 - x } +PREMISE Aiur.G.natCast +NatCast Aiur.G +DEFINITION +{ natCast := Aiur.G.ofNat } +PREMISE Aiur.G.ofInt +Int → Aiur.G +DEFINITION +fun x => + match x with + | Int.ofNat n => Aiur.G.ofNat n + | Int.negSucc n => -Aiur.G.ofNat (n + 1) +PREMISE Aiur.G.intCast +IntCast Aiur.G +DEFINITION +{ intCast := Aiur.G.ofInt } +PREMISE Aiur.G.nsmul +SMul Nat Aiur.G +DEFINITION +{ smul := fun n a => Aiur.G.ofNat n * a } +PREMISE Aiur.G.zsmul +SMul Int Aiur.G +DEFINITION +{ smul := fun n a => Aiur.G.ofInt n * a } +PREMISE Aiur.G.npow +HPow Aiur.G Nat Aiur.G +DEFINITION +{ hPow := fun a n => npowRec n a } +PREMISE Aiur.G.commRing +Grind.CommRing Aiur.G +DEFINITION +{ toAdd := Aiur.instAddG, toMul := Aiur.instMulG, natCast := Aiur.G.natCast, ofNat := @Aiur.instOfNatG, + nsmul := Aiur.G.nsmul, npow := Aiur.G.npow, add_zero := Aiur.G.add_zero, add_comm := Aiur.G.add_comm, + add_assoc := Aiur.G.add_assoc, mul_assoc := Aiur.G.mul_assoc, mul_one := Aiur.G.mul_one, + one_mul := Aiur.G.commRing._proof_1, left_distrib := Aiur.G.left_distrib, right_distrib := Aiur.G.commRing._proof_2, + zero_mul := Aiur.G.commRing._proof_3, mul_zero := Aiur.G.mul_zero, pow_zero := Aiur.G.commRing._proof_4, + pow_succ := Aiur.G.commRing._proof_5, ofNat_succ := Aiur.G.commRing._proof_6, + ofNat_eq_natCast := Aiur.G.commRing._proof_7, nsmul_eq_natCast_mul := Aiur.G.commRing._proof_8, toNeg := Aiur.G.neg, + toSub := Aiur.instSubG, intCast := Aiur.G.intCast, zsmul := Aiur.G.zsmul, neg_add_cancel := Aiur.G.neg_add_cancel, + sub_eq_add_neg := Aiur.G.sub_eq_add_neg, neg_zsmul := Aiur.G.commRing._proof_9, + zsmul_natCast_eq_nsmul := Aiur.G.commRing._proof_10, intCast_ofNat := Aiur.G.commRing._proof_11, + intCast_neg := Aiur.G.ofInt_neg, mul_comm := Aiur.G.mul_comm } +PREMISE Aiur.G.nonzeroResidues +List Aiur.G +DEFINITION +List.ofFn fun index => Aiur.G.ofNat (↑index + 1) +PREMISE Aiur.G.product +List Aiur.G → Aiur.G +DEFINITION +fun x => List.brecOn x Aiur.G.product._f +PREMISE Aiur.NativeAIR.ProofCodec.Extension.natCast +NatCast Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ natCast := fun n => Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.G.ofNat n) } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.intCast +IntCast Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ intCast := fun n => Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.G.ofInt n) } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.nsmul +SMul Nat Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ smul := fun n a => Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.G.ofNat n) * a } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.zsmul +SMul Int Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ smul := fun n a => Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.G.ofInt n) * a } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.npow +HPow Aiur.NativeAIR.ProofCodec.Extension Nat Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ hPow := fun a n => npowRec n a } +PREMISE Aiur.NativeAIR.ProofCodec.Extension.commRing +Grind.CommRing Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +{ toAdd := Aiur.NativeAIR.ProofCodec.Extension.add, toMul := Aiur.NativeAIR.ProofCodec.Extension.mul, + natCast := Aiur.NativeAIR.ProofCodec.Extension.natCast, ofNat := @Aiur.NativeAIR.ProofCodec.Extension.ofNat, + nsmul := Aiur.NativeAIR.ProofCodec.Extension.nsmul, npow := Aiur.NativeAIR.ProofCodec.Extension.npow, + add_zero := Aiur.NativeAIR.ProofCodec.Extension.add_zero, add_comm := Aiur.NativeAIR.ProofCodec.Extension.add_comm, + add_assoc := Aiur.NativeAIR.ProofCodec.Extension.add_assoc, + mul_assoc := Aiur.NativeAIR.ProofCodec.Extension.mul_assoc, mul_one := Aiur.NativeAIR.ProofCodec.Extension.mul_one, + one_mul := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_1, + left_distrib := Aiur.NativeAIR.ProofCodec.Extension.left_distrib, + right_distrib := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_2, + zero_mul := Aiur.NativeAIR.ProofCodec.Extension.zero_mul, + mul_zero := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_3, + pow_zero := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_4, + pow_succ := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_5, + ofNat_succ := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_6, + ofNat_eq_natCast := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_7, + nsmul_eq_natCast_mul := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_8, + toNeg := Aiur.NativeAIR.ProofCodec.Extension.neg, toSub := Aiur.NativeAIR.ProofCodec.Extension.sub, + intCast := Aiur.NativeAIR.ProofCodec.Extension.intCast, zsmul := Aiur.NativeAIR.ProofCodec.Extension.zsmul, + neg_add_cancel := Aiur.NativeAIR.ProofCodec.Extension.neg_add_cancel, + sub_eq_add_neg := Aiur.NativeAIR.ProofCodec.Extension.sub_eq_add_neg, + neg_zsmul := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_9, + zsmul_natCast_eq_nsmul := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_10, + intCast_ofNat := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_11, + intCast_neg := Aiur.NativeAIR.ProofCodec.Extension.commRing._proof_12, + mul_comm := Aiur.NativeAIR.ProofCodec.Extension.mul_comm } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.mk +{W : Type u} → W → W → Aiur.NativeAIR.LogUp.Coordinates W +PREMISE Aiur.NativeAIR.LogUp.Coordinates.ofBase +{W : Type u_1} → [OfNat W 0] → W → Aiur.NativeAIR.LogUp.Coordinates W +DEFINITION +fun {W} [OfNat W 0] value => { c0 := value, c1 := 0 } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.ofNat +{W : Type u_1} → {n : Nat} → [OfNat W n] → [OfNat W 0] → OfNat (Aiur.NativeAIR.LogUp.Coordinates W) n +DEFINITION +fun {W} {n} [OfNat W n] [OfNat W 0] => { ofNat := Aiur.NativeAIR.LogUp.Coordinates.ofBase (OfNat.ofNat n) } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.add +{W : Type u_1} → [Add W] → Add (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Add W] => { add := fun a b => { c0 := a.c0 + b.c0, c1 := a.c1 + b.c1 } } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.sub +{W : Type u_1} → [Sub W] → Sub (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Sub W] => { sub := fun a b => { c0 := a.c0 - b.c0, c1 := a.c1 - b.c1 } } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.neg +{W : Type u_1} → [Neg W] → Neg (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Neg W] => { neg := fun a => { c0 := -a.c0, c1 := -a.c1 } } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.mul +{W : Type u_1} → [OfNat W 7] → [Add W] → [Sub W] → [Mul W] → Mul (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [OfNat W 7] [Add W] [Sub W] [Mul W] => + { + mul := fun a b => + have v0 := a.c0 * b.c0; + have v1 := a.c1 * b.c1; + { c0 := v0 + v1 * 7, c1 := (a.c0 + a.c1) * (b.c0 + b.c1) - v0 - v1 } } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.scale +{W : Type u_1} → [Mul W] → Aiur.NativeAIR.LogUp.Coordinates W → W → Aiur.NativeAIR.LogUp.Coordinates W +DEFINITION +fun {W} [Mul W] value scalar => { c0 := value.c0 * scalar, c1 := value.c1 * scalar } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.map +{W : Type u_1} → {V : Type u_2} → (W → V) → Aiur.NativeAIR.LogUp.Coordinates W → Aiur.NativeAIR.LogUp.Coordinates V +DEFINITION +fun {W} {V} f value => { c0 := f value.c0, c1 := f value.c1 } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.read +{W : Type u_1} → Array W → Nat → Option (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} values slot => do + let __do_lift ← values[2 * slot]? + let __do_lift_1 ← values[2 * slot + 1]? + pure { c0 := __do_lift, c1 := __do_lift_1 } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.flatten +{W : Type u_1} → List (Aiur.NativeAIR.LogUp.Coordinates W) → List W +DEFINITION +fun {W} values => List.flatMap (fun value => [value.c0, value.c1]) values +PREMISE Aiur.NativeAIR.LogUp.Coordinates.toExtension +Aiur.NativeAIR.LogUp.Coordinates Aiur.G → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value => { c0 := value.c0, c1 := value.c1 } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.fromExtension +Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.LogUp.Coordinates Aiur.G +DEFINITION +fun value => { c0 := value.c0, c1 := value.c1 } +PREMISE Aiur.NativeAIR.LogUp.product +{R : Type u_1} → [OfNat R 1] → [Mul R] → List R → R +DEFINITION +fun {R} [OfNat R 1] [Mul R] values => List.foldr (fun x1 x2 => x1 * x2) 1 values +PREMISE Aiur.NativeAIR.LogUp.sum +{R : Type u_1} → [OfNat R 0] → [Add R] → List R → R +DEFINITION +fun {R} [OfNat R 0] [Add R] values => List.foldr (fun x1 x2 => x1 + x2) 0 values +PREMISE Aiur.NativeAIR.LogUp.numerator +{R : Type u_1} → [OfNat R 0] → [OfNat R 1] → [Add R] → [Mul R] → List (R × R) → R +DEFINITION +fun {R} [OfNat R 0] [OfNat R 1] [Add R] [Mul R] x => List.brecOn x Aiur.NativeAIR.LogUp.numerator._f +PREMISE Aiur.NativeAIR.LogUp.prefixSuffixTerms +{R : Type u_1} → [OfNat R 1] → [Mul R] → R → List (R × R) → List R +DEFINITION +fun {R} [OfNat R 1] [Mul R] initial entries => + have messages := List.map Prod.snd entries; + have prefixes := List.scanl (fun x1 x2 => x1 * x2) initial messages; + have suffixes := (List.scanr (fun x1 x2 => x1 * x2) 1 messages).tail; + List.map + (fun x => + match x with + | (entry, before, after) => before * after * entry.fst) + (entries.zip (prefixes.zip suffixes)) +PREMISE Aiur.NativeAIR.LogUp.groupEquation +{R : Type u_1} → [OfNat R 0] → [OfNat R 1] → [Add R] → [Sub R] → [Mul R] → List (R × R) → R → R +DEFINITION +fun {R} [OfNat R 0] [OfNat R 1] [Add R] [Sub R] [Mul R] entries difference => + match entries with + | [] => difference + | [(weight, message)] => message * difference - weight + | x => + List.foldl (fun x1 x2 => x1 * x2) 1 (List.map Prod.snd entries) * difference - + List.foldl (fun x1 x2 => x1 + x2) 0 (Aiur.NativeAIR.LogUp.prefixSuffixTerms 1 entries) +PREMISE Aiur.NativeAIR.LogUp.fingerprint +{W : Type u} → + [OfNat W 0] → + [OfNat W 7] → + [Add W] → [Sub W] → [Mul W] → Aiur.NativeAIR.LogUp.Coordinates W → List W → Aiur.NativeAIR.LogUp.Coordinates W +DEFINITION +fun {W} [OfNat W 0] [OfNat W 7] [Add W] [Sub W] [Mul W] gamma args => + List.foldr (fun arg acc => acc * gamma + Aiur.NativeAIR.LogUp.Coordinates.ofBase arg) 0 args +PREMISE Aiur.NativeAIR.LogUp.compress +{W : Type u} → + [OfNat W 0] → + [OfNat W 7] → + [Add W] → + [Sub W] → + [Mul W] → + Aiur.NativeAIR.LogUp.Coordinates W → + Aiur.NativeAIR.LogUp.Coordinates W → + List (W × List W) → List (Aiur.NativeAIR.LogUp.Coordinates W × Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [OfNat W 0] [OfNat W 7] [Add W] [Sub W] [Mul W] beta gamma lookups => + List.map + (fun x => + match x with + | (multiplicity, args) => + (Aiur.NativeAIR.LogUp.Coordinates.ofBase multiplicity, Aiur.NativeAIR.LogUp.fingerprint gamma args + beta)) + lookups +PREMISE Aiur.NativeAIR.LogUp.groupCount +Nat → Nat → Nat +DEFINITION +fun groupSize lookupCount => max 1 ((lookupCount + max groupSize 1 - 1) / max groupSize 1) +PREMISE Aiur.NativeAIR.LogUp.chunk +{α : Type u_1} → Nat → Nat → List α → List α +DEFINITION +fun {α} groupSize index lookups => List.take (max groupSize 1) (List.drop (index * max groupSize 1) lookups) +PREMISE Aiur.NativeAIR.LogUp.step +{W : Type u} → + [OfNat W 0] → + [OfNat W 1] → + [OfNat W 7] → + [Add W] → + [Sub W] → + [Mul W] → + Aiur.NativeAIR.LogUp.Coordinates W → + Aiur.NativeAIR.LogUp.Coordinates W → + Aiur.NativeAIR.LogUp.Coordinates W → + Aiur.NativeAIR.LogUp.Coordinates W → + Array W → List (W × List W) → Nat → Nat → Option (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [OfNat W 0] [OfNat W 1] [OfNat W 7] [Add W] [Sub W] [Mul W] beta gamma injection next stageCurrent lookups + groupSize index => + do + let source ← Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent index + have __do_jp : Aiur.NativeAIR.LogUp.Coordinates W → Option (Aiur.NativeAIR.LogUp.Coordinates W) := fun target => + pure + (Aiur.NativeAIR.LogUp.groupEquation + (Aiur.NativeAIR.LogUp.compress beta gamma (Aiur.NativeAIR.LogUp.chunk groupSize index lookups)) + (target - source)) + if index + 1 < Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length then do + let target ← Aiur.NativeAIR.LogUp.Coordinates.read stageCurrent (index + 1) + __do_jp target + else do + let target ← some (next + injection) + __do_jp target +PREMISE Aiur.NativeAIR.LogUp.equations +{W : Type u} → + [OfNat W 0] → + [OfNat W 1] → + [OfNat W 7] → + [Add W] → + [Sub W] → + [Mul W] → + List (W × List W) → + Array W → Array W → Array W → Array W → W → Nat → Option (List (Aiur.NativeAIR.LogUp.Coordinates W)) +DEFINITION +fun {W} [OfNat W 0] [OfNat W 1] [OfNat W 7] [Add W] [Sub W] [Mul W] lookups stageCurrent stageNext publics deltaScaled + isLast groupSize => + if 8 < groupSize then none + else do + let beta ← Aiur.NativeAIR.LogUp.Coordinates.read publics 0 + let gamma ← Aiur.NativeAIR.LogUp.Coordinates.read publics 1 + let delta ← Aiur.NativeAIR.LogUp.Coordinates.read deltaScaled 0 + have injection : Aiur.NativeAIR.LogUp.Coordinates W := delta.scale isLast + let next ← Aiur.NativeAIR.LogUp.Coordinates.read stageNext 0 + have groups : Nat := Aiur.NativeAIR.LogUp.groupCount groupSize lookups.length + List.mapM (Aiur.NativeAIR.LogUp.step beta gamma injection next stageCurrent lookups groupSize) (List.range groups) +PREMISE Aiur.NativeAIR.LogUp.constraintValues +{W : Type u} → + [OfNat W 0] → + [OfNat W 1] → + [OfNat W 7] → + [Add W] → + [Sub W] → + [Mul W] → + List Aiur.NativeAIR.Lookup → Array W → Array W → Array W → Array W → Array W → W → Nat → Option (List W) +DEFINITION +fun {W} [OfNat W 0] [OfNat W 1] [OfNat W 7] [Add W] [Sub W] [Mul W] lookups nodeValues stageCurrent stageNext publics + deltaScaled isLast groupSize => + do + let values ← List.mapM (Aiur.NativeAIR.readLookup nodeValues) lookups + let __do_lift ← Aiur.NativeAIR.LogUp.equations values stageCurrent stageNext publics deltaScaled isLast groupSize + pure (Aiur.NativeAIR.LogUp.Coordinates.flatten __do_lift) +PREMISE Aiur.NativeAIR.LogUp.Coordinates.natCast +{W : Type u} → [Grind.CommRing W] → NatCast (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Grind.CommRing W] => { natCast := fun n => Aiur.NativeAIR.LogUp.Coordinates.ofBase ↑n } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.intCast +{W : Type u} → [Grind.CommRing W] → IntCast (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Grind.CommRing W] => { intCast := fun n => Aiur.NativeAIR.LogUp.Coordinates.ofBase ↑n } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.nsmul +{W : Type u} → [Grind.CommRing W] → SMul Nat (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Grind.CommRing W] => { smul := fun n a => Aiur.NativeAIR.LogUp.Coordinates.ofBase ↑n * a } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.zsmul +{W : Type u} → [Grind.CommRing W] → SMul Int (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Grind.CommRing W] => { smul := fun n a => Aiur.NativeAIR.LogUp.Coordinates.ofBase ↑n * a } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.npow +{W : Type u} → [Grind.CommRing W] → HPow (Aiur.NativeAIR.LogUp.Coordinates W) Nat (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Grind.CommRing W] => { hPow := fun a n => npowRec n a } +PREMISE Aiur.NativeAIR.LogUp.Coordinates.commRing +{W : Type u} → [Grind.CommRing W] → Grind.CommRing (Aiur.NativeAIR.LogUp.Coordinates W) +DEFINITION +fun {W} [Grind.CommRing W] => + { toAdd := Aiur.NativeAIR.LogUp.Coordinates.add, toMul := Aiur.NativeAIR.LogUp.Coordinates.mul, + natCast := Aiur.NativeAIR.LogUp.Coordinates.natCast, ofNat := fun n => Aiur.NativeAIR.LogUp.Coordinates.ofNat, + nsmul := Aiur.NativeAIR.LogUp.Coordinates.nsmul, npow := Aiur.NativeAIR.LogUp.Coordinates.npow, add_zero := ⋯, + add_comm := ⋯, add_assoc := ⋯, mul_assoc := ⋯, mul_one := ⋯, one_mul := ⋯, left_distrib := ⋯, right_distrib := ⋯, + zero_mul := ⋯, mul_zero := ⋯, pow_zero := ⋯, pow_succ := ⋯, ofNat_succ := ⋯, ofNat_eq_natCast := ⋯, + nsmul_eq_natCast_mul := ⋯, toNeg := Aiur.NativeAIR.LogUp.Coordinates.neg, + toSub := Aiur.NativeAIR.LogUp.Coordinates.sub, intCast := Aiur.NativeAIR.LogUp.Coordinates.intCast, + zsmul := Aiur.NativeAIR.LogUp.Coordinates.zsmul, neg_add_cancel := ⋯, sub_eq_add_neg := ⋯, neg_zsmul := ⋯, + zsmul_natCast_eq_nsmul := ⋯, intCast_ofNat := ⋯, intCast_neg := ⋯, mul_comm := ⋯ } +PREMISE Aiur.NativeAIR.LogUp.inverseValue +Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun value => value.tryInverse.getD 0 +PREMISE Aiur.NativeAIR.LogUp.fractionSum +List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun entries => + Aiur.NativeAIR.LogUp.sum + (List.map + (fun x => + match x with + | (weight, message) => weight * Aiur.NativeAIR.LogUp.inverseValue message) + entries) +PREMISE Aiur.NativeAIR.LogUp.PoleFree +List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) → Prop +DEFINITION +fun entries => + ∀ (entry : Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension), entry ∈ entries → entry.snd ≠ 0 +PREMISE Aiur.NativeAIR.LogUp.fieldEntries +List (Aiur.NativeAIR.LogUp.Coordinates Aiur.G × Aiur.NativeAIR.LogUp.Coordinates Aiur.G) → + List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) +DEFINITION +fun entries => + List.map + (fun x => + match x with + | (weight, message) => (weight.toExtension, message.toExtension)) + entries +PREMISE Aiur.NativeAIR.LogUp.lookupFractions +Aiur.NativeAIR.LogUp.Coordinates Aiur.G → + Aiur.NativeAIR.LogUp.Coordinates Aiur.G → List (Aiur.G × List Aiur.G) → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun beta gamma lookups => + Aiur.NativeAIR.LogUp.fractionSum + (Aiur.NativeAIR.LogUp.fieldEntries (Aiur.NativeAIR.LogUp.compress beta gamma lookups)) +PREMISE Aiur.NativeAIR.Domain.generators +Array Aiur.G +DEFINITION +(have y := + have y := + have y := + [6414415596519834757, 16116352524544190054, 9123114210336311365, 4614640910117430873, 1753635133440165772]; + 9713644485405565297 :: 5456943929260765144 :: 17096174751763063430 :: 1213594585890690845 :: y; + have y := 3511170319078647661 :: 17654865857378133588 :: 5416168637041100469 :: 16905767614792059275 :: y; + 6115771955107415310 :: 12380578893860276750 :: 9306717745644682924 :: 18146160046829613826 :: y; + have y := + have y := 17492915097719143606 :: 1532612707718625687 :: 16207902636198568418 :: 17776499369601055404 :: y; + 13797081185216407910 :: 1803076106186727246 :: 11353340290879379826 :: 455906449640507599 :: y; + have y := 17293822564807737345 :: 70368744161280 :: 549755813888 :: 17870292113338400769 :: y; + 1 :: 18446744069414584320 :: 281474976710656 :: 18446744069397807105 :: y).toArray +PREMISE Aiur.NativeAIR.Domain.Subgroup +Type +DEFINITION +Fin 33 +PREMISE Aiur.NativeAIR.Domain.ofLogSize +Nat → Option Aiur.NativeAIR.Domain.Subgroup +DEFINITION +fun bits => if bounded : bits < 33 then some ⟨bits, bounded⟩ else none +PREMISE Aiur.NativeAIR.Domain.size +Aiur.NativeAIR.Domain.Subgroup → Nat +DEFINITION +fun domain => 2 ^ ↑domain +PREMISE Aiur.NativeAIR.Domain.generator +Aiur.NativeAIR.Domain.Subgroup → Aiur.G +DEFINITION +fun domain => Aiur.NativeAIR.Domain.generators[↑domain] +PREMISE Aiur.NativeAIR.Domain.point +(domain : Aiur.NativeAIR.Domain.Subgroup) → Fin (Aiur.NativeAIR.Domain.size domain) → Aiur.G +DEFINITION +fun domain index => (Aiur.NativeAIR.Domain.generator domain).pow ↑index +PREMISE Aiur.NativeAIR.Domain.lastPoint +Aiur.NativeAIR.Domain.Subgroup → Aiur.G +DEFINITION +fun domain => (Aiur.NativeAIR.Domain.generator domain).inverse +PREMISE Aiur.NativeAIR.Domain.normalizer +Aiur.NativeAIR.Domain.Subgroup → Aiur.G +DEFINITION +fun domain => Aiur.G.ofNat (Aiur.NativeAIR.Domain.size domain) * Aiur.NativeAIR.Domain.generator domain +PREMISE Aiur.NativeAIR.Domain.Selectors.mk +{W : Type} → W → W → W → W → Aiur.NativeAIR.Domain.Selectors W +PREMISE Aiur.NativeAIR.Domain.vanishing +Aiur.NativeAIR.Domain.Subgroup → Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun domain value => value.power (Aiur.NativeAIR.Domain.size domain) - 1 +PREMISE Aiur.NativeAIR.Domain.selectors +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.ProofCodec.Extension → Option (Aiur.NativeAIR.Domain.Selectors Aiur.NativeAIR.ProofCodec.Extension) +DEFINITION +fun domain value => + have z := Aiur.NativeAIR.Domain.vanishing domain value; + have lastDenominator := value - Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.lastPoint domain); + do + let firstInverse ← (value - 1).tryInverse + let lastInverse ← lastDenominator.tryInverse + let vanishingInverse ← z.tryInverse + pure + { isFirst := z * firstInverse, isLast := z * lastInverse, isTransition := lastDenominator, + invVanishing := vanishingInverse } +PREMISE Aiur.NativeAIR.Quotient.horner +{W : Type u_1} → [OfNat W 0] → [Add W] → [Mul W] → W → List W → W +DEFINITION +fun {W} [OfNat W 0] [Add W] [Mul W] point coefficients => + List.foldr (fun coefficient rest => coefficient + point * rest) 0 coefficients +PREMISE Aiur.NativeAIR.Quotient.composition +{W : Type u_1} → [OfNat W 0] → [Add W] → [Mul W] → W → List W → W +DEFINITION +fun {W} [OfNat W 0] [Add W] [Mul W] alpha constraints => + List.foldl (fun accumulated value => accumulated * alpha + value) 0 constraints +PREMISE Aiur.NativeAIR.Quotient.coefficients +List Aiur.NativeAIR.ProofCodec.Extension → Option (List Aiur.NativeAIR.ProofCodec.Extension) +DEFINITION +fun x => List.brecOn x Aiur.NativeAIR.Quotient.coefficients._f +PREMISE Aiur.NativeAIR.Quotient.evaluate +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.ProofCodec.Extension → + List Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun domain point row => do + let __do_lift ← Aiur.NativeAIR.Quotient.coefficients row + pure (Aiur.NativeAIR.Quotient.horner (point.power (Aiur.NativeAIR.Domain.size domain)) __do_lift) +PREMISE Aiur.NativeAIR.Quotient.check +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → + List Aiur.NativeAIR.ProofCodec.Extension → List Aiur.NativeAIR.ProofCodec.Extension → Option Bool +DEFINITION +fun domain point alpha constraints row => do + let selected ← Aiur.NativeAIR.Domain.selectors domain point + let quotient ← Aiur.NativeAIR.Quotient.evaluate domain point row + pure (Aiur.NativeAIR.Quotient.composition alpha constraints * selected.invVanishing == quotient) +PREMISE Aiur.NativeAIR.Domain.Algebra.dividedPowers +{R : Type} → [Grind.CommRing R] → R → R → Nat → R +DEFINITION +fun {R} [Grind.CommRing R] x a x_1 => Nat.brecOn x_1 (Aiur.NativeAIR.Domain.Algebra.dividedPowers._f x a) +PREMISE Aiur.NativeAIR.VerifierArithmetic.Challenges.mk +Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.VerifierArithmetic.Challenges +PREMISE Aiur.NativeAIR.VerifierArithmetic.pairColumns +Aiur.NativeAIR.ProofShape.Pair → Aiur.NativeAIR.RowOffset → Array Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun pair x => + match x with + | Aiur.NativeAIR.RowOffset.current => pair.current.toArray + | Aiur.NativeAIR.RowOffset.next => pair.next.toArray +PREMISE Aiur.NativeAIR.VerifierArithmetic.rowColumns +Aiur.NativeAIR.ProofShape.Row → + Aiur.NativeAIR.Source → Aiur.NativeAIR.RowOffset → Array Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun row x => + match (motive := Aiur.NativeAIR.Source → Aiur.NativeAIR.RowOffset → Array Aiur.NativeAIR.ProofCodec.Extension) x with + | Aiur.NativeAIR.Source.preprocessed => + match (motive := + Option Aiur.NativeAIR.ProofShape.Pair → Aiur.NativeAIR.RowOffset → Array Aiur.NativeAIR.ProofCodec.Extension) + row.preprocessed with + | none => fun x => #[] + | some pair => Aiur.NativeAIR.VerifierArithmetic.pairColumns pair + | Aiur.NativeAIR.Source.main => Aiur.NativeAIR.VerifierArithmetic.pairColumns row.stage1 + | Aiur.NativeAIR.Source.stage2 => Aiur.NativeAIR.VerifierArithmetic.pairColumns row.stage2 +PREMISE Aiur.NativeAIR.VerifierArithmetic.publics +Aiur.NativeAIR.VerifierArithmetic.Challenges → + Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofCodec.Extension → Array Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun challenges entering leaving => + #[Aiur.NativeAIR.ProofCodec.Extension.ofBase challenges.beta.c0, + Aiur.NativeAIR.ProofCodec.Extension.ofBase challenges.beta.c1, + Aiur.NativeAIR.ProofCodec.Extension.ofBase challenges.gamma.c0, + Aiur.NativeAIR.ProofCodec.Extension.ofBase challenges.gamma.c1, + Aiur.NativeAIR.ProofCodec.Extension.ofBase entering.c0, Aiur.NativeAIR.ProofCodec.Extension.ofBase entering.c1, + Aiur.NativeAIR.ProofCodec.Extension.ofBase leaving.c0, Aiur.NativeAIR.ProofCodec.Extension.ofBase leaving.c1] +PREMISE Aiur.NativeAIR.VerifierArithmetic.deltaScaled +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.ProofCodec.Extension → Array Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun domain entering leaving => + have normalizer := Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Domain.normalizer domain).inverse; + #[(Aiur.NativeAIR.ProofCodec.Extension.ofBase leaving.c0 - Aiur.NativeAIR.ProofCodec.Extension.ofBase entering.c0) * + normalizer, + (Aiur.NativeAIR.ProofCodec.Extension.ofBase leaving.c1 - Aiur.NativeAIR.ProofCodec.Extension.ofBase entering.c1) * + normalizer] +PREMISE Aiur.NativeAIR.VerifierArithmetic.view +Aiur.NativeAIR.VerifierArithmetic.Challenges → + Aiur.NativeAIR.ProofShape.Row → + Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.Domain.Selectors Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.Values Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun challenges row entering selectors => + { columns := Aiur.NativeAIR.VerifierArithmetic.rowColumns row, + publics := Aiur.NativeAIR.VerifierArithmetic.publics challenges entering row.accumulator, + isFirstRow := selectors.isFirst, isLastRow := selectors.isLast, isTransition := selectors.isTransition } +PREMISE Aiur.NativeAIR.VerifierArithmetic.Evaluation.mk +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.Domain.Selectors Aiur.NativeAIR.ProofCodec.Extension → + Array Aiur.NativeAIR.ProofCodec.Extension → + List Aiur.NativeAIR.ProofCodec.Extension → + List Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.VerifierArithmetic.Evaluation +PREMISE Aiur.NativeAIR.VerifierArithmetic.Evaluation.constraints +Aiur.NativeAIR.VerifierArithmetic.Evaluation → List Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun result => result.userValues ++ result.lookupValues +PREMISE Aiur.NativeAIR.VerifierArithmetic.Evaluation.accepts +Aiur.NativeAIR.VerifierArithmetic.Evaluation → Aiur.NativeAIR.ProofCodec.Extension → Bool +DEFINITION +fun result alpha => + Aiur.NativeAIR.Quotient.composition alpha result.constraints * result.selectors.invVanishing == result.quotientValue +PREMISE Aiur.NativeAIR.VerifierArithmetic.evaluate +Aiur.NativeAIR.VerifierArithmetic.Challenges → + Aiur.NativeAIR.ProofShape.Row → + Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.VerifierArithmetic.Evaluation +DEFINITION +fun challenges row entering => do + let domain ← Aiur.NativeAIR.Domain.ofLogSize row.logDegree.toNat + let selectors ← Aiur.NativeAIR.Domain.selectors domain challenges.zeta + have values : Aiur.NativeAIR.Values Aiur.NativeAIR.ProofCodec.Extension := + Aiur.NativeAIR.VerifierArithmetic.view challenges row entering selectors + let nodes ← row.circuit.graph.sweep Aiur.NativeAIR.ProofCodec.Extension.evalOps values + let userValues ← Aiur.NativeAIR.readNodes nodes row.circuit.graph.zeros + let lookupValues ← + Aiur.NativeAIR.LogUp.constraintValues row.circuit.graph.lookups nodes + (values.columns Aiur.NativeAIR.Source.stage2 Aiur.NativeAIR.RowOffset.current) + (values.columns Aiur.NativeAIR.Source.stage2 Aiur.NativeAIR.RowOffset.next) values.publics + (Aiur.NativeAIR.VerifierArithmetic.deltaScaled domain entering row.accumulator) values.isLastRow + row.circuit.lookupGroupSize + let quotientValue ← Aiur.NativeAIR.Quotient.evaluate domain challenges.zeta row.quotient + pure + { domain := domain, selectors := selectors, nodeValues := nodes, userValues := userValues, + lookupValues := lookupValues, quotientValue := quotientValue } +PREMISE Aiur.NativeAIR.VerifierArithmetic.check +Aiur.NativeAIR.VerifierArithmetic.Challenges → + Aiur.NativeAIR.ProofShape.Row → Aiur.NativeAIR.ProofCodec.Extension → Option Bool +DEFINITION +fun challenges row entering => do + let __do_lift ← Aiur.NativeAIR.VerifierArithmetic.evaluate challenges row entering + pure (__do_lift.accepts challenges.alpha) +PREMISE Aiur.NativeAIR.VerifierArithmetic.checkRows +Aiur.NativeAIR.VerifierArithmetic.Challenges → + List Aiur.NativeAIR.ProofShape.Row → Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun challenges x x_1 => + List.brecOn (motive := fun x => Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.ProofCodec.Extension) x + (Aiur.NativeAIR.VerifierArithmetic.checkRows._f challenges) x_1 +PREMISE Aiur.NativeAIR.VerifierArithmetic.claimMessage +Aiur.NativeAIR.VerifierArithmetic.Challenges → List Aiur.G → Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun challenges claim => + challenges.beta + + (Aiur.NativeAIR.LogUp.fingerprint (Aiur.NativeAIR.LogUp.Coordinates.fromExtension challenges.gamma) + claim).toExtension +PREMISE Aiur.NativeAIR.VerifierArithmetic.initialAccumulator +Aiur.NativeAIR.VerifierArithmetic.Challenges → List (List Aiur.G) → Option Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun challenges claims => do + let inverses ← + List.mapM (fun claim => (Aiur.NativeAIR.VerifierArithmetic.claimMessage challenges claim).tryInverse) claims + pure (Aiur.NativeAIR.LogUp.sum inverses) +PREMISE Aiur.NativeAIR.VerifierArithmetic.verify +Aiur.NativeAIR.VerifierArithmetic.Challenges → List (List Aiur.G) → List Aiur.NativeAIR.ProofShape.Row → Option Bool +DEFINITION +fun challenges claims rows => + if rows.isEmpty = true then none + else do + let entering ← Aiur.NativeAIR.VerifierArithmetic.initialAccumulator challenges claims + let __do_lift ← Aiur.NativeAIR.VerifierArithmetic.checkRows challenges rows entering + pure (__do_lift == 0) +PREMISE Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads.mk +∀ {challenges : Aiur.NativeAIR.VerifierArithmetic.Challenges} {row : Aiur.NativeAIR.ProofShape.Row} + {entering : Aiur.NativeAIR.ProofCodec.Extension} {result : Aiur.NativeAIR.VerifierArithmetic.Evaluation}, + Aiur.NativeAIR.Domain.ofLogSize row.logDegree.toNat = some result.domain → + Aiur.NativeAIR.Domain.selectors result.domain challenges.zeta = some result.selectors → + row.circuit.graph.sweep Aiur.NativeAIR.ProofCodec.Extension.evalOps + (Aiur.NativeAIR.VerifierArithmetic.view challenges row entering result.selectors) = + some result.nodeValues → + Aiur.NativeAIR.readNodes result.nodeValues row.circuit.graph.zeros = some result.userValues → + Aiur.NativeAIR.LogUp.constraintValues row.circuit.graph.lookups result.nodeValues + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.current) + (Aiur.NativeAIR.VerifierArithmetic.rowColumns row Aiur.NativeAIR.Source.stage2 + Aiur.NativeAIR.RowOffset.next) + (Aiur.NativeAIR.VerifierArithmetic.publics challenges entering row.accumulator) + (Aiur.NativeAIR.VerifierArithmetic.deltaScaled result.domain entering row.accumulator) + result.selectors.isLast row.circuit.lookupGroupSize = + some result.lookupValues → + Aiur.NativeAIR.Quotient.evaluate result.domain challenges.zeta row.quotient = some result.quotientValue → + Aiur.NativeAIR.VerifierArithmetic.Evaluation.Reads challenges row entering result +PREMISE Aiur.NativeAIR.VerifierArithmetic.publicEntries +Aiur.NativeAIR.VerifierArithmetic.Challenges → + List (List Aiur.G) → List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) +DEFINITION +fun challenges claims => + List.map (fun claim => (1, Aiur.NativeAIR.VerifierArithmetic.claimMessage challenges claim)) claims +PREMISE Aiur.NativeAIR.Challenger.Hash32 +Type +DEFINITION +List UInt8 → Fin 32 → UInt8 +PREMISE Aiur.NativeAIR.Challenger.State.mk +List UInt8 → List UInt8 → Aiur.NativeAIR.Challenger.State +PREMISE Aiur.NativeAIR.Challenger.initial +List UInt8 → Aiur.NativeAIR.Challenger.State +DEFINITION +fun seed => { input := seed, pending := [] } +PREMISE Aiur.NativeAIR.Challenger.observeByte +Aiur.NativeAIR.Challenger.State → UInt8 → Aiur.NativeAIR.Challenger.State +DEFINITION +fun state byte => { input := state.input ++ [byte], pending := [] } +PREMISE Aiur.NativeAIR.Challenger.observeBytes +Aiur.NativeAIR.Challenger.State → List UInt8 → Aiur.NativeAIR.Challenger.State +DEFINITION +fun state bytes => if bytes.isEmpty = true then state else { input := state.input ++ bytes, pending := [] } +PREMISE Aiur.NativeAIR.Challenger.observeField +Aiur.NativeAIR.Challenger.State → Aiur.G → Aiur.NativeAIR.Challenger.State +DEFINITION +fun state value => Aiur.NativeAIR.Challenger.observeBytes state (Aiur.NativeAIR.ProofCodec.encodeField value) +PREMISE Aiur.NativeAIR.Challenger.observeExtension +Aiur.NativeAIR.Challenger.State → Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.Challenger.State +DEFINITION +fun state value => + Aiur.NativeAIR.Challenger.observeField (Aiur.NativeAIR.Challenger.observeField state value.c0) value.c1 +PREMISE Aiur.NativeAIR.Challenger.observeCap +Aiur.NativeAIR.Challenger.State → Aiur.NativeAIR.KeyCodec.MerkleCap → Aiur.NativeAIR.Challenger.State +DEFINITION +fun state cap => Aiur.NativeAIR.Challenger.observeBytes state (List.flatten cap) +PREMISE Aiur.NativeAIR.Challenger.sampleByte +Aiur.NativeAIR.Challenger.Hash32 → Aiur.NativeAIR.Challenger.State → UInt8 × Aiur.NativeAIR.Challenger.State +DEFINITION +fun hash state => + match state.pending with + | byte :: rest => (byte, { input := state.input, pending := rest }) + | [] => + have digest := hash state.input; + (digest 31, { input := List.ofFn digest, pending := List.drop 1 (List.ofFn digest).reverse }) +PREMISE Aiur.NativeAIR.Challenger.sampleBytes +Aiur.NativeAIR.Challenger.Hash32 → Nat → Aiur.NativeAIR.Challenger.State → List UInt8 × Aiur.NativeAIR.Challenger.State +DEFINITION +fun hash x x_1 => + Nat.brecOn (motive := fun x => Aiur.NativeAIR.Challenger.State → List UInt8 × Aiur.NativeAIR.Challenger.State) x + (Aiur.NativeAIR.Challenger.sampleBytes._f hash) x_1 +PREMISE Aiur.NativeAIR.Challenger.littleEndian +List UInt8 → Nat +DEFINITION +fun bytes => List.foldr (fun byte rest => byte.toNat + 256 * rest) 0 bytes +PREMISE Aiur.NativeAIR.Challenger.sampleWord +Aiur.NativeAIR.Challenger.Hash32 → Aiur.NativeAIR.Challenger.State → Nat × Aiur.NativeAIR.Challenger.State +DEFINITION +fun hash state => + match Aiur.NativeAIR.Challenger.sampleBytes hash 8 state with + | (bytes, next) => (Aiur.NativeAIR.Challenger.littleEndian bytes, next) +PREMISE Aiur.NativeAIR.Challenger.sampleField +Aiur.NativeAIR.Challenger.Hash32 → + Nat → Aiur.NativeAIR.Challenger.State → Option (Aiur.G × Aiur.NativeAIR.Challenger.State) +DEFINITION +fun hash x x_1 => + Nat.brecOn (motive := fun x => Aiur.NativeAIR.Challenger.State → Option (Aiur.G × Aiur.NativeAIR.Challenger.State)) x + (Aiur.NativeAIR.Challenger.sampleField._f hash) x_1 +PREMISE Aiur.NativeAIR.Challenger.sampleExtension +Aiur.NativeAIR.Challenger.Hash32 → + Nat → Aiur.NativeAIR.Challenger.State → Option (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.Challenger.State) +DEFINITION +fun hash fuel state => do + let __x ← Aiur.NativeAIR.Challenger.sampleField hash fuel state + match __x with + | (c0, next) => do + let __x ← Aiur.NativeAIR.Challenger.sampleField hash fuel next + match __x with + | (c1, final) => pure ({ c0 := c0, c1 := c1 }, final) +PREMISE Aiur.NativeAIR.Challenger.sampleBits +Aiur.NativeAIR.Challenger.Hash32 → + Nat → Aiur.NativeAIR.Challenger.State → Option (Nat × Aiur.NativeAIR.Challenger.State) +DEFINITION +fun hash bits state => + if bits < 64 ∧ 2 ^ bits < Aiur.gSize.toNat then + match Aiur.NativeAIR.Challenger.sampleWord hash state with + | (word, next) => some (word % 2 ^ bits, next) + else none +PREMISE Aiur.NativeAIR.Challenger.checkWitness +Aiur.NativeAIR.Challenger.Hash32 → + Nat → Aiur.G → Aiur.NativeAIR.Challenger.State → Option (Bool × Aiur.NativeAIR.Challenger.State) +DEFINITION +fun hash bits witness state => + if bits = 0 then pure (true, state) + else do + let __x ← Aiur.NativeAIR.Challenger.sampleBits hash bits (Aiur.NativeAIR.Challenger.observeField state witness) + match __x with + | (value, next) => pure (value == 0, next) +PREMISE Aiur.NativeAIR.Transcript.parameterWords +Aiur.NativeAIR.KeyCodec.Parameters → List Nat +DEFINITION +fun parameters => + [parameters.logBlowup, parameters.capHeight, parameters.logFinalPolyLen, parameters.maxLogArity, + parameters.numQueries, parameters.commitProofOfWorkBits, parameters.queryProofOfWorkBits] +PREMISE Aiur.NativeAIR.Transcript.seed +Aiur.NativeAIR.KeyCodec.Parameters → List UInt8 +DEFINITION +fun parameters => + "multi-stark/v0".toUTF8.data.toList ++ + List.flatMap (Aiur.NativeAIR.KeyCodec.encodeNat 8) (Aiur.NativeAIR.Transcript.parameterWords parameters) +PREMISE Aiur.NativeAIR.Transcript.circuitShape +Aiur.NativeAIR.KeyCodec.Circuit → List Aiur.G +DEFINITION +fun circuit => + List.map Aiur.G.ofNat + [circuit.constraintCount, circuit.maxConstraintDegree, circuit.preprocessedHeight, circuit.preprocessedWidth, + circuit.mainWidth, circuit.widths.stage2, circuit.lookupGroupSize] +PREMISE Aiur.NativeAIR.Transcript.shape +Aiur.NativeAIR.KeyCodec.Key → List Aiur.G +DEFINITION +fun key => Aiur.G.ofNat key.circuits.length :: List.flatMap Aiur.NativeAIR.Transcript.circuitShape key.circuits +PREMISE Aiur.NativeAIR.Transcript.claimsFields +List (List Aiur.G) → List Aiur.G +DEFINITION +fun claims => Aiur.G.ofNat claims.length :: List.flatMap (fun claim => Aiur.G.ofNat claim.length :: claim) claims +PREMISE Aiur.NativeAIR.Transcript.fieldsBytes +List Aiur.G → List UInt8 +DEFINITION +fun values => List.flatMap Aiur.NativeAIR.ProofCodec.encodeField values +PREMISE Aiur.NativeAIR.Transcript.prefixBytes +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → List (List Aiur.G) → List UInt8 +DEFINITION +fun key proof claims => + Aiur.NativeAIR.Transcript.fieldsBytes (Aiur.NativeAIR.Transcript.shape key) ++ + Aiur.NativeAIR.Transcript.fieldsBytes + (List.map (fun active => if active = true then 1 else 0) proof.active) ++ + List.flatten (key.preprocessedCommitment.getD []) ++ + List.flatten proof.commitments.stage1 ++ + Aiur.NativeAIR.Transcript.fieldsBytes (List.map (fun degree => Aiur.G.ofNat degree.toNat) proof.logDegrees) ++ + Aiur.NativeAIR.Transcript.fieldsBytes (Aiur.NativeAIR.Transcript.claimsFields claims) +PREMISE Aiur.NativeAIR.Transcript.lookupState +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → List (List Aiur.G) → Aiur.NativeAIR.Challenger.State +DEFINITION +fun key proof claims => + Aiur.NativeAIR.Challenger.observeBytes + (Aiur.NativeAIR.Challenger.initial (Aiur.NativeAIR.Transcript.seed key.parameters)) + (Aiur.NativeAIR.Transcript.prefixBytes key proof claims) +PREMISE Aiur.NativeAIR.Transcript.accumulatorState +Aiur.NativeAIR.ProofCodec.Data → Aiur.NativeAIR.Challenger.State → Aiur.NativeAIR.Challenger.State +DEFINITION +fun proof state => + List.foldl Aiur.NativeAIR.Challenger.observeExtension + (Aiur.NativeAIR.Challenger.observeCap state proof.commitments.stage2) proof.accumulators +PREMISE Aiur.NativeAIR.Transcript.Replay.mk +Aiur.NativeAIR.VerifierArithmetic.Challenges → Aiur.NativeAIR.Challenger.State → Aiur.NativeAIR.Transcript.Replay +PREMISE Aiur.NativeAIR.Transcript.replay +Aiur.NativeAIR.Challenger.Hash32 → + Nat → + Aiur.NativeAIR.KeyCodec.Key → + Aiur.NativeAIR.ProofCodec.Data → List (List Aiur.G) → Option Aiur.NativeAIR.Transcript.Replay +DEFINITION +fun hash fuel key proof claims => do + let __x ← Aiur.NativeAIR.Challenger.sampleExtension hash fuel (Aiur.NativeAIR.Transcript.lookupState key proof claims) + match __x with + | (beta, afterBeta) => do + let __x ← + Aiur.NativeAIR.Challenger.sampleExtension hash fuel (Aiur.NativeAIR.Challenger.observeExtension afterBeta beta) + match __x with + | (gamma, afterGamma) => do + let __x ← + Aiur.NativeAIR.Challenger.sampleExtension hash fuel + (Aiur.NativeAIR.Transcript.accumulatorState proof + (Aiur.NativeAIR.Challenger.observeExtension afterGamma gamma)) + match __x with + | (alpha, afterAlpha) => do + let __x ← + Aiur.NativeAIR.Challenger.sampleExtension hash fuel + (Aiur.NativeAIR.Challenger.observeCap afterAlpha proof.commitments.quotient) + match __x with + | (zeta, final) => + pure { challenges := { beta := beta, gamma := gamma, alpha := alpha, zeta := zeta }, state := final } +PREMISE Aiur.NativeAIR.Transcript.verifyArithmetic +Aiur.NativeAIR.Challenger.Hash32 → + Nat → + Aiur.NativeAIR.KeyCodec.Key → + Aiur.NativeAIR.ProofCodec.Data → + List (List Aiur.G) → List Aiur.NativeAIR.ProofShape.Row → Option Aiur.NativeAIR.Transcript.Replay +DEFINITION +fun hash fuel key proof claims rows => do + let result ← Aiur.NativeAIR.Transcript.replay hash fuel key proof claims + let __do_lift ← Aiur.NativeAIR.VerifierArithmetic.verify result.challenges claims rows + if __do_lift = true then some result else none +PREMISE Aiur.NativeAIR.Challenger.State.Valid +Aiur.NativeAIR.Challenger.State → Prop +DEFINITION +fun state => + state.pending = [] ∨ ∃ consumed, state.input.length = 32 ∧ state.pending = List.drop consumed state.input.reverse +PREMISE Aiur.NativeAIR.Challenger.FieldSample.accept +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {state : Aiur.NativeAIR.Challenger.State}, + (Aiur.NativeAIR.Challenger.sampleWord hash state).fst < Aiur.gSize.toNat → + Aiur.NativeAIR.Challenger.FieldSample hash state 1 + (Aiur.G.ofNat (Aiur.NativeAIR.Challenger.sampleWord hash state).fst) + (Aiur.NativeAIR.Challenger.sampleWord hash state).snd +PREMISE Aiur.NativeAIR.Challenger.FieldSample.reject +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {state final : Aiur.NativeAIR.Challenger.State} {count : Nat} + {value : Aiur.G}, + ¬(Aiur.NativeAIR.Challenger.sampleWord hash state).fst < Aiur.gSize.toNat → + Aiur.NativeAIR.Challenger.FieldSample hash (Aiur.NativeAIR.Challenger.sampleWord hash state).snd count value final → + Aiur.NativeAIR.Challenger.FieldSample hash state (count + 1) value final +PREMISE Aiur.NativeAIR.Transcript.Replay.Reads.mk +∀ {hash : Aiur.NativeAIR.Challenger.Hash32} {fuel : Nat} {key : Aiur.NativeAIR.KeyCodec.Key} + {proof : Aiur.NativeAIR.ProofCodec.Data} {claims : List (List Aiur.G)} {result : Aiur.NativeAIR.Transcript.Replay}, + (∃ afterBeta afterGamma afterAlpha, + Aiur.NativeAIR.Challenger.sampleExtension hash fuel (Aiur.NativeAIR.Transcript.lookupState key proof claims) = + some (result.challenges.beta, afterBeta) ∧ + Aiur.NativeAIR.Challenger.sampleExtension hash fuel + (Aiur.NativeAIR.Challenger.observeExtension afterBeta result.challenges.beta) = + some (result.challenges.gamma, afterGamma) ∧ + Aiur.NativeAIR.Challenger.sampleExtension hash fuel + (Aiur.NativeAIR.Transcript.accumulatorState proof + (Aiur.NativeAIR.Challenger.observeExtension afterGamma result.challenges.gamma)) = + some (result.challenges.alpha, afterAlpha) ∧ + Aiur.NativeAIR.Challenger.sampleExtension hash fuel + (Aiur.NativeAIR.Challenger.observeCap afterAlpha proof.commitments.quotient) = + some (result.challenges.zeta, result.state)) → + Aiur.NativeAIR.Transcript.Replay.Reads hash fuel key proof claims result +PREMISE Aiur.NativeAIR.Blake3.CV +Type +DEFINITION +Vector UInt32 8 +PREMISE Aiur.NativeAIR.Blake3.Block +Type +DEFINITION +Vector UInt32 16 +PREMISE Aiur.NativeAIR.Blake3.Digest +Type +DEFINITION +Vector UInt8 32 +PREMISE Aiur.NativeAIR.Blake3.iv +Aiur.NativeAIR.Blake3.CV +DEFINITION +#v[1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225] +PREMISE Aiur.NativeAIR.Blake3.schedules +Vector (Vector (Fin 16) 16) 7 +DEFINITION +#v[#v[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], #v[2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8], + #v[3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1], #v[10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6], + #v[12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4], #v[9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7], + #v[11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13]] +PREMISE Aiur.NativeAIR.Blake3.rotateRight +UInt32 → UInt32 → UInt32 +DEFINITION +fun word count => word >>> count ||| word <<< (32 - count) +PREMISE Aiur.NativeAIR.Blake3.mix +UInt32 → UInt32 → UInt32 → UInt32 → UInt32 → UInt32 → Vector UInt32 4 +DEFINITION +fun a b c d x y => + let a_1 := a + b + x; + let d_1 := Aiur.NativeAIR.Blake3.rotateRight (d ^^^ a_1) 16; + let c_1 := c + d_1; + let b_1 := Aiur.NativeAIR.Blake3.rotateRight (b ^^^ c_1) 12; + let a_2 := a_1 + b_1 + y; + let d_2 := Aiur.NativeAIR.Blake3.rotateRight (d_1 ^^^ a_2) 8; + let c_2 := c_1 + d_2; + let b_2 := Aiur.NativeAIR.Blake3.rotateRight (b_1 ^^^ c_2) 7; + #v[a_2, b_2, c_2, d_2] +PREMISE Aiur.NativeAIR.Blake3.g +Aiur.NativeAIR.Blake3.Block → Fin 16 → Fin 16 → Fin 16 → Fin 16 → UInt32 → UInt32 → Aiur.NativeAIR.Blake3.Block +DEFINITION +fun state a b c d x y => + have words := Aiur.NativeAIR.Blake3.mix state[a] state[b] state[c] state[d] x y; + (((Vector.set state (↑a) words[0] ⋯).set (↑b) words[1] ⋯).set (↑c) words[2] ⋯).set (↑d) words[3] ⋯ +PREMISE Aiur.NativeAIR.Blake3.round +Aiur.NativeAIR.Blake3.Block → Aiur.NativeAIR.Blake3.Block → Vector (Fin 16) 16 → Aiur.NativeAIR.Blake3.Block +DEFINITION +fun state message schedule => + have state := Aiur.NativeAIR.Blake3.g state 0 4 8 12 message[schedule[0]] message[schedule[1]]; + have state := Aiur.NativeAIR.Blake3.g state 1 5 9 13 message[schedule[2]] message[schedule[3]]; + have state := Aiur.NativeAIR.Blake3.g state 2 6 10 14 message[schedule[4]] message[schedule[5]]; + have state := Aiur.NativeAIR.Blake3.g state 3 7 11 15 message[schedule[6]] message[schedule[7]]; + have state := Aiur.NativeAIR.Blake3.g state 0 5 10 15 message[schedule[8]] message[schedule[9]]; + have state := Aiur.NativeAIR.Blake3.g state 1 6 11 12 message[schedule[10]] message[schedule[11]]; + have state := Aiur.NativeAIR.Blake3.g state 2 7 8 13 message[schedule[12]] message[schedule[13]]; + Aiur.NativeAIR.Blake3.g state 3 4 9 14 message[schedule[14]] message[schedule[15]] +PREMISE Aiur.NativeAIR.Blake3.initialWords +Aiur.NativeAIR.Blake3.CV → UInt64 → UInt32 → UInt32 → Aiur.NativeAIR.Blake3.Block +DEFINITION +fun cv counter blockLen flags => + #v[cv[0], cv[1], cv[2], cv[3], cv[4], cv[5], cv[6], cv[7], Aiur.NativeAIR.Blake3.iv[0], Aiur.NativeAIR.Blake3.iv[1], + Aiur.NativeAIR.Blake3.iv[2], Aiur.NativeAIR.Blake3.iv[3], counter.toUInt32, (counter >>> 32).toUInt32, blockLen, + flags] +PREMISE Aiur.NativeAIR.Blake3.compress +Aiur.NativeAIR.Blake3.CV → Aiur.NativeAIR.Blake3.Block → UInt64 → UInt32 → UInt32 → Aiur.NativeAIR.Blake3.CV +DEFINITION +fun cv message counter blockLen flags => + have state := + Vector.foldl (fun state schedule => Aiur.NativeAIR.Blake3.round state message schedule) + (Aiur.NativeAIR.Blake3.initialWords cv counter blockLen flags) Aiur.NativeAIR.Blake3.schedules; + Vector.ofFn fun index => state[↑index] ^^^ state[↑index + 8] +PREMISE Aiur.NativeAIR.Blake3.wordBytes +UInt32 → Vector UInt8 4 +DEFINITION +fun word => Vector.ofFn fun index => (word.toNat / 256 ^ ↑index).toUInt8 +PREMISE Aiur.NativeAIR.Blake3.bytesWord +Vector UInt8 4 → UInt32 +DEFINITION +fun bytes => UInt32.ofNat (Aiur.NativeAIR.Challenger.littleEndian bytes.toList) +PREMISE Aiur.NativeAIR.Blake3.blockWords +List UInt8 → Aiur.NativeAIR.Blake3.Block +DEFINITION +fun bytes => + have input := bytes.toArray; + Vector.ofFn fun word => Aiur.NativeAIR.Blake3.bytesWord (Vector.ofFn fun byte => input[↑word * 4 + ↑byte]?.getD 0) +PREMISE Aiur.NativeAIR.Blake3.cvBytes +Aiur.NativeAIR.Blake3.CV → Aiur.NativeAIR.Blake3.Digest +DEFINITION +fun cv => Vector.ofFn fun index => (Aiur.NativeAIR.Blake3.wordBytes cv[↑index / 4])[↑index % 4] +PREMISE Aiur.NativeAIR.Blake3.Output.mk +Aiur.NativeAIR.Blake3.CV → Aiur.NativeAIR.Blake3.Block → UInt32 → UInt64 → UInt32 → Aiur.NativeAIR.Blake3.Output +PREMISE Aiur.NativeAIR.Blake3.Output.chainingValue +Aiur.NativeAIR.Blake3.Output → Aiur.NativeAIR.Blake3.CV +DEFINITION +fun output => Aiur.NativeAIR.Blake3.compress output.cv output.block output.counter output.blockLen output.flags +PREMISE Aiur.NativeAIR.Blake3.Output.rootHash +Aiur.NativeAIR.Blake3.Output → Aiur.NativeAIR.Blake3.Digest +DEFINITION +fun output => + Aiur.NativeAIR.Blake3.cvBytes + (Aiur.NativeAIR.Blake3.compress output.cv output.block 0 output.blockLen (output.flags ||| 8)) +PREMISE Aiur.NativeAIR.Blake3.chunkLoop +UInt64 → Aiur.NativeAIR.Blake3.CV → Bool → List UInt8 → Aiur.NativeAIR.Blake3.Output +DEFINITION +fun counter cv start input => Aiur.NativeAIR.Blake3.chunkLoop._unary counter ⟨cv, ⟨start, input⟩⟩ +PREMISE Aiur.NativeAIR.Blake3.chunkOutput +UInt64 → List UInt8 → Aiur.NativeAIR.Blake3.Output +DEFINITION +fun counter input => Aiur.NativeAIR.Blake3.chunkLoop counter Aiur.NativeAIR.Blake3.iv true input +PREMISE Aiur.NativeAIR.Blake3.parentOutput +Aiur.NativeAIR.Blake3.CV → Aiur.NativeAIR.Blake3.CV → Aiur.NativeAIR.Blake3.Output +DEFINITION +fun left right => { cv := Aiur.NativeAIR.Blake3.iv, block := left ++ right, blockLen := 64, counter := 0, flags := 4 } +PREMISE Aiur.NativeAIR.Blake3.leftLen +Nat → Nat +DEFINITION +fun size => 2 ^ (size - 1).log2 +PREMISE Aiur.NativeAIR.Blake3.subtree +Nat → List UInt8 → Aiur.NativeAIR.Blake3.Output +DEFINITION +fun counter input => Aiur.NativeAIR.Blake3.subtree._unary ⟨counter, input⟩ +PREMISE Aiur.NativeAIR.Blake3.digest +List UInt8 → Aiur.NativeAIR.Blake3.Digest +DEFINITION +fun input => (Aiur.NativeAIR.Blake3.subtree 0 input).rootHash +PREMISE Aiur.NativeAIR.Blake3.hash +Aiur.NativeAIR.Challenger.Hash32 +DEFINITION +fun input => + have bytes := Aiur.NativeAIR.Blake3.digest input; + fun index => bytes[index] +PREMISE Aiur.NativeAIR.Blake3.NativeInput +List UInt8 → Prop +DEFINITION +fun input => input.length < 2 ^ 64 +PREMISE Aiur.NativeAIR.Blake3.replay +Nat → + Aiur.NativeAIR.KeyCodec.Key → + Aiur.NativeAIR.ProofCodec.Data → List (List Aiur.G) → Option Aiur.NativeAIR.Transcript.Replay +DEFINITION +fun fuel key proof claims => Aiur.NativeAIR.Transcript.replay Aiur.NativeAIR.Blake3.hash fuel key proof claims +PREMISE Aiur.NativeAIR.Blake3.verifyArithmetic +Nat → + Aiur.NativeAIR.KeyCodec.Key → + Aiur.NativeAIR.ProofCodec.Data → + List (List Aiur.G) → List Aiur.NativeAIR.ProofShape.Row → Option Aiur.NativeAIR.Transcript.Replay +DEFINITION +fun fuel key proof claims rows => + Aiur.NativeAIR.Transcript.verifyArithmetic Aiur.NativeAIR.Blake3.hash fuel key proof claims rows +PREMISE Aiur.NativeAIR.Blake3.ChunkReads.last +∀ {counter : UInt64} (cv : Aiur.NativeAIR.Blake3.CV) (start : Bool) (input : List UInt8), + input.length ≤ 64 → + Aiur.NativeAIR.Blake3.ChunkReads counter cv start input + { cv := cv, block := Aiur.NativeAIR.Blake3.blockWords input, blockLen := input.length.toUInt32, + counter := counter, flags := (if start = true then 1 else 0) ||| 2 } +PREMISE Aiur.NativeAIR.Blake3.ChunkReads.step +∀ {counter : UInt64} (cv : Aiur.NativeAIR.Blake3.CV) (start : Bool) (input : List UInt8) + (output : Aiur.NativeAIR.Blake3.Output), + 64 < input.length → + Aiur.NativeAIR.Blake3.ChunkReads counter + (Aiur.NativeAIR.Blake3.compress cv (Aiur.NativeAIR.Blake3.blockWords (List.take 64 input)) counter 64 + (if start = true then 1 else 0)) + false (List.drop 64 input) output → + Aiur.NativeAIR.Blake3.ChunkReads counter cv start input output +PREMISE Aiur.NativeAIR.Blake3.TreeHash.chunk +∀ (counter : Nat) (input : List UInt8) (output : Aiur.NativeAIR.Blake3.Output), + input.length ≤ 1024 → + Aiur.NativeAIR.Blake3.ChunkReads counter.toUInt64 Aiur.NativeAIR.Blake3.iv true input output → + Aiur.NativeAIR.Blake3.TreeHash counter input output +PREMISE Aiur.NativeAIR.Blake3.TreeHash.parent +∀ (counter exponent : Nat) (left right : List UInt8) (leftOutput rightOutput : Aiur.NativeAIR.Blake3.Output), + left.length = 1024 * 2 ^ exponent → + 0 < right.length → + right.length ≤ left.length → + Aiur.NativeAIR.Blake3.TreeHash counter left leftOutput → + Aiur.NativeAIR.Blake3.TreeHash (counter + left.length / 1024) right rightOutput → + Aiur.NativeAIR.Blake3.TreeHash counter (left ++ right) + (Aiur.NativeAIR.Blake3.parentOutput leftOutput.chainingValue rightOutput.chainingValue) +PREMISE Aiur.NativeAIR.Blake3.ChunkAt.leaf +∀ (counter : Nat) (input : List UInt8), input.length ≤ 1024 → Aiur.NativeAIR.Blake3.ChunkAt counter input counter input +PREMISE Aiur.NativeAIR.Blake3.ChunkAt.left +∀ {counter leaf : Nat} {input bytes : List UInt8}, + 1024 < input.length → + Aiur.NativeAIR.Blake3.ChunkAt counter (List.take (Aiur.NativeAIR.Blake3.leftLen input.length) input) leaf bytes → + Aiur.NativeAIR.Blake3.ChunkAt counter input leaf bytes +PREMISE Aiur.NativeAIR.Blake3.ChunkAt.right +∀ {counter leaf : Nat} {input bytes : List UInt8}, + 1024 < input.length → + Aiur.NativeAIR.Blake3.ChunkAt (counter + Aiur.NativeAIR.Blake3.leftLen input.length / 1024) + (List.drop (Aiur.NativeAIR.Blake3.leftLen input.length) input) leaf bytes → + Aiur.NativeAIR.Blake3.ChunkAt counter input leaf bytes +PREMISE Aiur.NativeAIR.MerkleCap.maxDegree +List Nat → Nat +DEFINITION +fun degrees => List.foldr max 0 degrees +PREMISE Aiur.NativeAIR.MerkleCap.coverage +Nat → Nat → List Nat → Bool +DEFINITION +fun logBlowup capHeight degrees => + have effective := min (capHeight - logBlowup) (Aiur.NativeAIR.MerkleCap.maxDegree degrees); + degrees.all fun degree => decide (effective ≤ degree) +PREMISE Aiur.NativeAIR.MerkleCap.check +Aiur.NativeAIR.KeyCodec.Key → Aiur.NativeAIR.ProofCodec.Data → Bool +DEFINITION +fun key proof => + Aiur.NativeAIR.MerkleCap.coverage key.parameters.logBlowup key.parameters.capHeight + (List.map UInt8.toNat proof.logDegrees) +PREMISE Aiur.NativeAIR.Merkle.Digest +Type +DEFINITION +Aiur.NativeAIR.Blake3.Digest +PREMISE Aiur.NativeAIR.Merkle.Hash +Type +DEFINITION +List UInt8 → Aiur.NativeAIR.Merkle.Digest +PREMISE Aiur.NativeAIR.Merkle.Dimensions.mk +Nat → Nat → Aiur.NativeAIR.Merkle.Dimensions +PREMISE Aiur.NativeAIR.Merkle.maxHeight +List Aiur.NativeAIR.Merkle.Dimensions → Nat +DEFINITION +fun dimensions => Aiur.NativeAIR.MerkleCap.maxDegree (List.map Aiur.NativeAIR.Merkle.Dimensions.logHeight dimensions) +PREMISE Aiur.NativeAIR.Merkle.shape +List Aiur.NativeAIR.Merkle.Dimensions → List (List Aiur.G) → Bool +DEFINITION +fun x x_1 => List.brecOn (motive := fun x => List (List Aiur.G) → Bool) x Aiur.NativeAIR.Merkle.shape._f x_1 +PREMISE Aiur.NativeAIR.Merkle.hasHeight +List Aiur.NativeAIR.Merkle.Dimensions → Nat → Bool +DEFINITION +fun dimensions height => dimensions.any fun dimension => dimension.logHeight == height +PREMISE Aiur.NativeAIR.Merkle.rowsAt +List Aiur.NativeAIR.Merkle.Dimensions → List (List Aiur.G) → Nat → List (List Aiur.G) +DEFINITION +fun x x_1 x_2 => + List.brecOn (motive := fun x => List (List Aiur.G) → Nat → List (List Aiur.G)) x Aiur.NativeAIR.Merkle.rowsAt._f x_1 + x_2 +PREMISE Aiur.NativeAIR.Merkle.rowBytes +List Aiur.NativeAIR.Merkle.Dimensions → List (List Aiur.G) → Nat → List UInt8 +DEFINITION +fun dimensions rows height => + Aiur.NativeAIR.Transcript.fieldsBytes (Aiur.NativeAIR.Merkle.rowsAt dimensions rows height).flatten +PREMISE Aiur.NativeAIR.Merkle.pairBytes +Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Digest → List UInt8 +DEFINITION +fun left right => Vector.toList left ++ Vector.toList right +PREMISE Aiur.NativeAIR.Merkle.branchBytes +Nat → Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Digest → List UInt8 +DEFINITION +fun index current sibling => + if index % 2 = 0 then Aiur.NativeAIR.Merkle.pairBytes current sibling + else Aiur.NativeAIR.Merkle.pairBytes sibling current +PREMISE Aiur.NativeAIR.Merkle.Hashing.mk +Aiur.NativeAIR.Merkle.Digest → List (List UInt8) → Aiur.NativeAIR.Merkle.Hashing +PREMISE Aiur.NativeAIR.Merkle.step +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + List (List Aiur.G) → + Nat → Nat → Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Hashing +DEFINITION +fun hash dimensions rows height index current sibling => + have input := Aiur.NativeAIR.Merkle.branchBytes index current sibling; + have parent := hash input; + if Aiur.NativeAIR.Merkle.hasHeight dimensions height = true then + have leaf := Aiur.NativeAIR.Merkle.rowBytes dimensions rows height; + have inject := Aiur.NativeAIR.Merkle.pairBytes parent (hash leaf); + { digest := hash inject, inputs := [input, leaf, inject] } + else { digest := parent, inputs := [input] } +PREMISE Aiur.NativeAIR.Merkle.walk +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + List (List Aiur.G) → + Nat → Nat → Aiur.NativeAIR.Merkle.Digest → List Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Hashing +DEFINITION +fun hash dimensions rows height index current x => + List.brecOn (motive := fun x => Nat → Nat → Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Hashing) x + (Aiur.NativeAIR.Merkle.walk._f hash dimensions rows) height index current +PREMISE Aiur.NativeAIR.Merkle.Replay.mk +Nat → Nat → Aiur.NativeAIR.Merkle.Hashing → Aiur.NativeAIR.Merkle.Replay +PREMISE Aiur.NativeAIR.Merkle.replay +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → Nat → List (List Aiur.G) → List Aiur.NativeAIR.Merkle.Digest → Option Aiur.NativeAIR.Merkle.Replay +DEFINITION +fun hash dimensions capHeight index rows proof => + have height := Aiur.NativeAIR.Merkle.maxHeight dimensions; + if + (dimensions.isEmpty || !Aiur.NativeAIR.Merkle.shape dimensions rows || proof.length != height - capHeight || + !decide (index < 2 ^ height)) = + true then + none + else + have leaf := Aiur.NativeAIR.Merkle.rowBytes dimensions rows height; + have result := Aiur.NativeAIR.Merkle.walk hash dimensions rows height index (hash leaf) proof; + some + { logHeight := height - proof.length, index := index / 2 ^ proof.length, + hashing := { digest := result.digest, inputs := leaf :: result.inputs } } +PREMISE Aiur.NativeAIR.Merkle.accepts +List Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Replay → Bool +DEFINITION +fun cap result => cap[result.index]? == some result.hashing.digest +PREMISE Aiur.NativeAIR.Merkle.verify +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → Nat → List Aiur.NativeAIR.Merkle.Digest → List (List Aiur.G) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash dimensions capHeight index cap rows proof => + match Aiur.NativeAIR.Merkle.replay hash dimensions capHeight index rows proof with + | none => false + | some result => Aiur.NativeAIR.Merkle.accepts cap result +PREMISE Aiur.NativeAIR.Merkle.covered +List Aiur.NativeAIR.Merkle.Dimensions → Nat → Bool +DEFINITION +fun dimensions capHeight => + Aiur.NativeAIR.MerkleCap.coverage 0 capHeight (List.map Aiur.NativeAIR.Merkle.Dimensions.logHeight dimensions) +PREMISE Aiur.NativeAIR.Merkle.verifyCovered +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → Nat → List Aiur.NativeAIR.Merkle.Digest → List (List Aiur.G) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash dimensions capHeight index cap rows proof => + Aiur.NativeAIR.Merkle.covered dimensions capHeight && + Aiur.NativeAIR.Merkle.verify hash dimensions capHeight index cap rows proof +PREMISE Aiur.NativeAIR.Merkle.CollisionOn +Aiur.NativeAIR.Merkle.Hash → List (List UInt8) → Prop +DEFINITION +fun hash inputs => ∃ left, left ∈ inputs ∧ ∃ right, right ∈ inputs ∧ left ≠ right ∧ hash left = hash right +PREMISE Aiur.NativeAIR.PrunedMerkle.Logged.mk +{α : Type} → Option α → List (List UInt8) → Aiur.NativeAIR.PrunedMerkle.Logged α +PREMISE Aiur.NativeAIR.PrunedMerkle.Logged.pure +{α : Type} → α → Aiur.NativeAIR.PrunedMerkle.Logged α +DEFINITION +fun {α} value => { result := some value, inputs := [] } +PREMISE Aiur.NativeAIR.PrunedMerkle.Logged.bind +{α β : Type} → + Aiur.NativeAIR.PrunedMerkle.Logged α → + (α → Aiur.NativeAIR.PrunedMerkle.Logged β) → Aiur.NativeAIR.PrunedMerkle.Logged β +DEFINITION +fun {α β} first next => + match first.result with + | none => { result := none, inputs := first.inputs } + | some value => + have rest := next value; + { result := rest.result, inputs := first.inputs ++ rest.inputs } +PREMISE Aiur.NativeAIR.PrunedMerkle.reject +{α : Type} → Aiur.NativeAIR.PrunedMerkle.Logged α +DEFINITION +fun {α} => { result := none, inputs := [] } +PREMISE Aiur.NativeAIR.PrunedMerkle.ofOption +{α : Type} → Option α → Aiur.NativeAIR.PrunedMerkle.Logged α +DEFINITION +fun {α} value => { result := value, inputs := [] } +PREMISE Aiur.NativeAIR.PrunedMerkle.hashInput +Aiur.NativeAIR.Merkle.Hash → List UInt8 → Aiur.NativeAIR.PrunedMerkle.Logged Aiur.NativeAIR.Merkle.Digest +DEFINITION +fun hash input => { result := some (hash input), inputs := [input] } +PREMISE Aiur.NativeAIR.PrunedMerkle.Ticket.mk +Nat → List (List Aiur.G) → List Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.PrunedMerkle.Ticket +PREMISE Aiur.NativeAIR.PrunedMerkle.Ticket.extend +Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.PrunedMerkle.Ticket → Aiur.NativeAIR.PrunedMerkle.Ticket +DEFINITION +fun sibling ticket => { index := ticket.index, rows := ticket.rows, proof := ticket.proof ++ [sibling] } +PREMISE Aiur.NativeAIR.PrunedMerkle.Node.mk +Nat → Aiur.NativeAIR.Merkle.Digest → List Aiur.NativeAIR.PrunedMerkle.Ticket → Aiur.NativeAIR.PrunedMerkle.Node +PREMISE Aiur.NativeAIR.PrunedMerkle.uniqueIndices +List Nat → List Nat +DEFINITION +fun indices => (indices.mergeSort fun x1 x2 => decide (x1 ≤ x2)).eraseDups +PREMISE Aiur.NativeAIR.PrunedMerkle.parentIndices +List Nat → List Nat +DEFINITION +fun indices => (List.map (fun x => x / 2) indices).eraseDups +PREMISE Aiur.NativeAIR.PrunedMerkle.boundaryCount +Nat → List Nat → Nat +DEFINITION +fun x x_1 => Nat.brecOn (motive := fun x => List Nat → Nat) x Aiur.NativeAIR.PrunedMerkle.boundaryCount._f x_1 +PREMISE Aiur.NativeAIR.PrunedMerkle.representatives +List Nat → List (List (List Aiur.G)) → Option (List Aiur.NativeAIR.PrunedMerkle.Ticket) +DEFINITION +fun indices rows => + have originals := indices.zip rows; + List.mapM + (fun index => do + let __x ← List.find? (fun entry => entry.fst == index) originals + match __x with + | (fst, values) => + if (originals.all fun entry => entry.fst != index || entry.snd == values) = true then + some { index := index, rows := values, proof := [] } + else none) + (Aiur.NativeAIR.PrunedMerkle.uniqueIndices indices) +PREMISE Aiur.NativeAIR.PrunedMerkle.initial +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Aiur.NativeAIR.PrunedMerkle.Ticket → + Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node) +DEFINITION +fun hash dimensions height x => List.brecOn x (Aiur.NativeAIR.PrunedMerkle.initial._f hash dimensions height) +PREMISE Aiur.NativeAIR.PrunedMerkle.combine +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.PrunedMerkle.Node → + List Aiur.NativeAIR.Merkle.Digest → + Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node × List Aiur.NativeAIR.Merkle.Digest) +DEFINITION +fun hash a a_1 => Aiur.NativeAIR.PrunedMerkle.combine._unary hash ⟨a, a_1⟩ +PREMISE Aiur.NativeAIR.PrunedMerkle.inject +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Aiur.NativeAIR.PrunedMerkle.Node → Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node) +DEFINITION +fun hash dimensions height x => List.brecOn x (Aiur.NativeAIR.PrunedMerkle.inject._f hash dimensions height) +PREMISE Aiur.NativeAIR.PrunedMerkle.walk +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + Nat → + List Aiur.NativeAIR.PrunedMerkle.Node → + List Aiur.NativeAIR.Merkle.Digest → + Aiur.NativeAIR.PrunedMerkle.Logged + (List Aiur.NativeAIR.PrunedMerkle.Node × List Aiur.NativeAIR.Merkle.Digest) +DEFINITION +fun hash dimensions x x_1 x_2 x_3 => + Nat.brecOn (motive := fun x => + Nat → + List Aiur.NativeAIR.PrunedMerkle.Node → + List Aiur.NativeAIR.Merkle.Digest → + Aiur.NativeAIR.PrunedMerkle.Logged + (List Aiur.NativeAIR.PrunedMerkle.Node × List Aiur.NativeAIR.Merkle.Digest)) + x (Aiur.NativeAIR.PrunedMerkle.walk._f hash dimensions) x_1 x_2 x_3 +PREMISE Aiur.NativeAIR.PrunedMerkle.replay +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Nat → + List (List (List Aiur.G)) → + List Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node) +DEFINITION +fun hash dimensions capHeight indices rows proof => + if (dimensions.isEmpty || rows.length != indices.length) = true then Aiur.NativeAIR.PrunedMerkle.reject + else + have height := Aiur.NativeAIR.Merkle.maxHeight dimensions; + have steps := height - capHeight; + if (!indices.all fun index => decide (index < 2 ^ height)) = true then Aiur.NativeAIR.PrunedMerkle.reject + else do + let tickets ← Aiur.NativeAIR.PrunedMerkle.ofOption (Aiur.NativeAIR.PrunedMerkle.representatives indices rows) + if + (proof.length != + Aiur.NativeAIR.PrunedMerkle.boundaryCount steps (Aiur.NativeAIR.PrunedMerkle.uniqueIndices indices) || + !tickets.all fun ticket => Aiur.NativeAIR.Merkle.shape dimensions ticket.rows) = + true then + Aiur.NativeAIR.PrunedMerkle.reject + else do + let leaves ← Aiur.NativeAIR.PrunedMerkle.initial hash dimensions height tickets + let __x ← Aiur.NativeAIR.PrunedMerkle.walk hash dimensions steps height leaves proof + match __x with + | (nodes, remaining) => if remaining.isEmpty = true then pure nodes else Aiur.NativeAIR.PrunedMerkle.reject +PREMISE Aiur.NativeAIR.PrunedMerkle.accepts +List Aiur.NativeAIR.Merkle.Digest → List Aiur.NativeAIR.PrunedMerkle.Node → Bool +DEFINITION +fun cap nodes => nodes.all fun node => cap[node.index]? == some node.digest +PREMISE Aiur.NativeAIR.PrunedMerkle.verify +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Nat → + List Aiur.NativeAIR.Merkle.Digest → List (List (List Aiur.G)) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash dimensions capHeight indices cap rows proof => + match (Aiur.NativeAIR.PrunedMerkle.replay hash dimensions capHeight indices rows proof).result with + | none => false + | some nodes => Aiur.NativeAIR.PrunedMerkle.accepts cap nodes +PREMISE Aiur.NativeAIR.PrunedMerkle.verifyCovered +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Nat → + List Aiur.NativeAIR.Merkle.Digest → List (List (List Aiur.G)) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash dimensions capHeight indices cap rows proof => + Aiur.NativeAIR.Merkle.covered dimensions capHeight && + Aiur.NativeAIR.PrunedMerkle.verify hash dimensions capHeight indices cap rows proof +PREMISE Aiur.NativeAIR.PrunedMerkle.TicketAt.mk +∀ {hash : Aiur.NativeAIR.Merkle.Hash} {dimensions : List Aiur.NativeAIR.Merkle.Dimensions} {height index : Nat} + {digest : Aiur.NativeAIR.Merkle.Digest} {inputs : List (List UInt8)} {ticket : Aiur.NativeAIR.PrunedMerkle.Ticket}, + Aiur.NativeAIR.Merkle.shape dimensions ticket.rows = true → + ticket.index < 2 ^ Aiur.NativeAIR.Merkle.maxHeight dimensions → + ticket.proof.length + height = Aiur.NativeAIR.Merkle.maxHeight dimensions → + ticket.index / 2 ^ ticket.proof.length = index → + (Aiur.NativeAIR.Merkle.walk hash dimensions ticket.rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) + ticket.index + (hash + (Aiur.NativeAIR.Merkle.rowBytes dimensions ticket.rows + (Aiur.NativeAIR.Merkle.maxHeight dimensions))) + ticket.proof).digest = + digest → + Aiur.NativeAIR.Merkle.rowBytes dimensions ticket.rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) :: + (Aiur.NativeAIR.Merkle.walk hash dimensions ticket.rows (Aiur.NativeAIR.Merkle.maxHeight dimensions) + ticket.index + (hash + (Aiur.NativeAIR.Merkle.rowBytes dimensions ticket.rows + (Aiur.NativeAIR.Merkle.maxHeight dimensions))) + ticket.proof).inputs ⊆ + inputs → + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions height index digest inputs ticket +PREMISE Aiur.NativeAIR.PrunedMerkle.NodeAt +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → Nat → List (List UInt8) → Aiur.NativeAIR.PrunedMerkle.Node → Prop +DEFINITION +fun hash dimensions height inputs node => + ∀ (ticket : Aiur.NativeAIR.PrunedMerkle.Ticket), + ticket ∈ node.tickets → + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions height node.index node.digest inputs ticket +PREMISE Aiur.NativeAIR.PrunedMerkle.PendingAt +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → Nat → Aiur.NativeAIR.Merkle.Digest → List (List UInt8) → Aiur.NativeAIR.PrunedMerkle.Ticket → Prop +DEFINITION +fun hash dimensions height index digest inputs ticket => + ∃ before sibling previousIndex previousDigest, + ticket = Aiur.NativeAIR.PrunedMerkle.Ticket.extend sibling before ∧ + Aiur.NativeAIR.PrunedMerkle.TicketAt hash dimensions (height + 1) previousIndex previousDigest inputs before ∧ + index = previousIndex / 2 ∧ + digest = hash (Aiur.NativeAIR.Merkle.branchBytes previousIndex previousDigest sibling) ∧ + Aiur.NativeAIR.Merkle.branchBytes previousIndex previousDigest sibling ∈ inputs +PREMISE Aiur.NativeAIR.PrunedMerkle.PendingNode +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → Nat → List (List UInt8) → Aiur.NativeAIR.PrunedMerkle.Node → Prop +DEFINITION +fun hash dimensions height inputs node => + ∀ (ticket : Aiur.NativeAIR.PrunedMerkle.Ticket), + ticket ∈ node.tickets → + Aiur.NativeAIR.PrunedMerkle.PendingAt hash dimensions height node.index node.digest inputs ticket +PREMISE Aiur.NativeAIR.PrunedMerkle.origins +List Aiur.NativeAIR.PrunedMerkle.Node → List (Nat × List (List Aiur.G)) +DEFINITION +fun nodes => List.flatMap (fun node => List.map (fun ticket => (ticket.index, ticket.rows)) node.tickets) nodes +PREMISE Aiur.NativeAIR.PrunedMerkle.instMonadLogged +Monad Aiur.NativeAIR.PrunedMerkle.Logged +DEFINITION +{ + map := fun {α β} f x => + (fun {α β} => Aiur.NativeAIR.PrunedMerkle.Logged.bind) x ((fun {α} => Aiur.NativeAIR.PrunedMerkle.Logged.pure) ∘ f), + pure := fun {α} => Aiur.NativeAIR.PrunedMerkle.Logged.pure, + seq := fun {α β} f x => + (fun {α β} => Aiur.NativeAIR.PrunedMerkle.Logged.bind) f fun y => + (fun {α β} => Aiur.NativeAIR.PrunedMerkle.Logged.bind) (x ()) + ((fun {α} => Aiur.NativeAIR.PrunedMerkle.Logged.pure) ∘ y), + seqLeft := fun {α β} x y => + (fun {α β} => Aiur.NativeAIR.PrunedMerkle.Logged.bind) x fun a => + (fun {α β} => Aiur.NativeAIR.PrunedMerkle.Logged.bind) (y ()) fun x => + (fun {α} => Aiur.NativeAIR.PrunedMerkle.Logged.pure) a, + seqRight := fun {α β} x y => (fun {α β} => Aiur.NativeAIR.PrunedMerkle.Logged.bind) x fun x => y (), + bind := fun {α β} => Aiur.NativeAIR.PrunedMerkle.Logged.bind } +PREMISE Aiur.NativeAIR.ExtensionMmcs.baseRow +List Aiur.NativeAIR.ProofCodec.Extension → List Aiur.G +DEFINITION +fun values => List.flatMap (fun value => [value.c0, value.c1]) values +PREMISE Aiur.NativeAIR.ExtensionMmcs.baseRows +List (List Aiur.NativeAIR.ProofCodec.Extension) → List (List Aiur.G) +DEFINITION +fun rows => List.map Aiur.NativeAIR.ExtensionMmcs.baseRow rows +PREMISE Aiur.NativeAIR.ExtensionMmcs.baseDimensions +Nat → List Aiur.NativeAIR.Merkle.Dimensions → List Aiur.NativeAIR.Merkle.Dimensions +DEFINITION +fun wordBits dimensions => + List.map (fun dimension => { width := dimension.width * 2 % 2 ^ wordBits, logHeight := dimension.logHeight }) + dimensions +PREMISE Aiur.NativeAIR.ExtensionMmcs.WidthsFit +Nat → List Aiur.NativeAIR.Merkle.Dimensions → Prop +DEFINITION +fun wordBits dimensions => + ∀ (dimension : Aiur.NativeAIR.Merkle.Dimensions), dimension ∈ dimensions → dimension.width * 2 < 2 ^ wordBits +PREMISE Aiur.NativeAIR.ExtensionMmcs.shape +List Aiur.NativeAIR.Merkle.Dimensions → List (List Aiur.NativeAIR.ProofCodec.Extension) → Bool +DEFINITION +fun x x_1 => + List.brecOn (motive := fun x => List (List Aiur.NativeAIR.ProofCodec.Extension) → Bool) x + Aiur.NativeAIR.ExtensionMmcs.shape._f x_1 +PREMISE Aiur.NativeAIR.ExtensionMmcs.replay +Aiur.NativeAIR.Merkle.Hash → + Nat → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + Nat → + List (List Aiur.NativeAIR.ProofCodec.Extension) → + List Aiur.NativeAIR.Merkle.Digest → Option Aiur.NativeAIR.Merkle.Replay +DEFINITION +fun hash wordBits dimensions capHeight index rows proof => + Aiur.NativeAIR.Merkle.replay hash (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) capHeight index + (Aiur.NativeAIR.ExtensionMmcs.baseRows rows) proof +PREMISE Aiur.NativeAIR.ExtensionMmcs.verify +Aiur.NativeAIR.Merkle.Hash → + Nat → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + Nat → + List Aiur.NativeAIR.Merkle.Digest → + List (List Aiur.NativeAIR.ProofCodec.Extension) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash wordBits dimensions capHeight index cap rows proof => + Aiur.NativeAIR.Merkle.verify hash (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) capHeight index + cap (Aiur.NativeAIR.ExtensionMmcs.baseRows rows) proof +PREMISE Aiur.NativeAIR.ExtensionMmcs.verifyCovered +Aiur.NativeAIR.Merkle.Hash → + Nat → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + Nat → + List Aiur.NativeAIR.Merkle.Digest → + List (List Aiur.NativeAIR.ProofCodec.Extension) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash wordBits dimensions capHeight index cap rows proof => + Aiur.NativeAIR.Merkle.covered dimensions capHeight && + Aiur.NativeAIR.ExtensionMmcs.verify hash wordBits dimensions capHeight index cap rows proof +PREMISE Aiur.NativeAIR.ExtensionMmcs.replayMulti +Aiur.NativeAIR.Merkle.Hash → + Nat → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Nat → + List (List (List Aiur.NativeAIR.ProofCodec.Extension)) → + List Aiur.NativeAIR.Merkle.Digest → + Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node) +DEFINITION +fun hash wordBits dimensions capHeight indices rows proof => + Aiur.NativeAIR.PrunedMerkle.replay hash (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) capHeight + indices (List.map Aiur.NativeAIR.ExtensionMmcs.baseRows rows) proof +PREMISE Aiur.NativeAIR.ExtensionMmcs.verifyMulti +Aiur.NativeAIR.Merkle.Hash → + Nat → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Nat → + List Aiur.NativeAIR.Merkle.Digest → + List (List (List Aiur.NativeAIR.ProofCodec.Extension)) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash wordBits dimensions capHeight indices cap rows proof => + Aiur.NativeAIR.PrunedMerkle.verify hash (Aiur.NativeAIR.ExtensionMmcs.baseDimensions wordBits dimensions) capHeight + indices cap (List.map Aiur.NativeAIR.ExtensionMmcs.baseRows rows) proof +PREMISE Aiur.NativeAIR.ExtensionMmcs.verifyMultiCovered +Aiur.NativeAIR.Merkle.Hash → + Nat → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Nat → + List Aiur.NativeAIR.Merkle.Digest → + List (List (List Aiur.NativeAIR.ProofCodec.Extension)) → List Aiur.NativeAIR.Merkle.Digest → Bool +DEFINITION +fun hash wordBits dimensions capHeight indices cap rows proof => + Aiur.NativeAIR.Merkle.covered dimensions capHeight && + Aiur.NativeAIR.ExtensionMmcs.verifyMulti hash wordBits dimensions capHeight indices cap rows proof +PREMISE Aiur.NativeAIR.FriDomain.reverseBits +Nat → Nat → Nat +DEFINITION +fun bits index => (BitVec.ofNat bits index).reverse.toNat +PREMISE Aiur.NativeAIR.FriDomain.wordReverse +Nat → Nat → Nat → Nat +DEFINITION +fun wordBits bits index => ((BitVec.ofNat wordBits index).reverse >>> ((wordBits - bits) % wordBits)).toNat +PREMISE Aiur.NativeAIR.FriDomain.queryPoint +Aiur.NativeAIR.Domain.Subgroup → Nat → Aiur.G +DEFINITION +fun domain index => (Aiur.NativeAIR.Domain.generator domain).pow (Aiur.NativeAIR.FriDomain.reverseBits (↑domain) index) +PREMISE Aiur.NativeAIR.FriDomain.inputPoint +Aiur.NativeAIR.Domain.Subgroup → Nat → Aiur.G +DEFINITION +fun domain index => 7 * Aiur.NativeAIR.FriDomain.queryPoint domain index +PREMISE Aiur.NativeAIR.FriDomain.foldNode +Aiur.NativeAIR.Domain.Subgroup → Aiur.NativeAIR.Domain.Subgroup → Nat → Nat → Aiur.G +DEFINITION +fun parent arity index slot => + (Aiur.NativeAIR.Domain.generator parent).pow (Aiur.NativeAIR.FriDomain.reverseBits (↑parent - ↑arity) index) * + (Aiur.NativeAIR.Domain.generator arity).pow (Aiur.NativeAIR.FriDomain.reverseBits (↑arity) slot) +PREMISE Aiur.NativeAIR.Polynomial.IsZero +{R : Type u_1} → [OfNat R 0] → List R → Prop +DEFINITION +fun {R} [OfNat R 0] coefficients => ∀ (coefficient : R), coefficient ∈ coefficients → coefficient = 0 +PREMISE Aiur.NativeAIR.Polynomial.Monic +{R : Type u_1} → [OfNat R 1] → List R → Prop +DEFINITION +fun {R} [OfNat R 1] coefficients => ∃ initial, coefficients = initial ++ [1] +PREMISE Aiur.NativeAIR.Polynomial.add +{R : Type u_1} → [Add R] → List R → List R → List R +DEFINITION +fun {R} [Add R] x x_1 => List.brecOn (motive := fun x => List R → List R) x Aiur.NativeAIR.Polynomial.add._f x_1 +PREMISE Aiur.NativeAIR.Polynomial.sub +{R : Type u_1} → [OfNat R 0] → [Sub R] → List R → List R → List R +DEFINITION +fun {R} [OfNat R 0] [Sub R] x x_1 => + List.brecOn (motive := fun x => List R → List R) x Aiur.NativeAIR.Polynomial.sub._f x_1 +PREMISE Aiur.NativeAIR.Polynomial.scale +{R : Type u_1} → [Mul R] → R → List R → List R +DEFINITION +fun {R} [Mul R] scalar coefficients => List.map (fun x => scalar * x) coefficients +PREMISE Aiur.NativeAIR.Polynomial.mulLinear +{R : Type u_1} → [OfNat R 0] → [Sub R] → [Mul R] → R → List R → List R +DEFINITION +fun {R} [OfNat R 0] [Sub R] [Mul R] root coefficients => + Aiur.NativeAIR.Polynomial.sub (0 :: coefficients) (Aiur.NativeAIR.Polynomial.scale root coefficients) +PREMISE Aiur.NativeAIR.Polynomial.fromRoots +{R : Type u_1} → [OfNat R 0] → [OfNat R 1] → [Sub R] → [Mul R] → List R → List R +DEFINITION +fun {R} [OfNat R 0] [OfNat R 1] [Sub R] [Mul R] roots => List.foldr Aiur.NativeAIR.Polynomial.mulLinear [1] roots +PREMISE Aiur.NativeAIR.Polynomial.powerMinus +{R : Type u_1} → [OfNat R 0] → [OfNat R 1] → [Sub R] → Nat → R → List R +DEFINITION +fun {R} [OfNat R 0] [OfNat R 1] [Sub R] degree constant => + Aiur.NativeAIR.Polynomial.sub (List.replicate degree 0 ++ [1]) [constant] +PREMISE Aiur.NativeAIR.Polynomial.divide +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → R → List R → List R +DEFINITION +fun {R} [OfNat R 0] [Add R] [Mul R] point x => List.brecOn x (Aiur.NativeAIR.Polynomial.divide._f point) +PREMISE Aiur.NativeAIR.Polynomial.foldingNodes +Aiur.NativeAIR.Domain.Subgroup → Aiur.NativeAIR.Domain.Subgroup → Nat → List Aiur.G +DEFINITION +fun parent arity index => + List.map (Aiur.NativeAIR.FriDomain.foldNode parent arity index) (List.range (Aiur.NativeAIR.Domain.size arity)) +PREMISE Aiur.NativeAIR.Interpolation.derivativeValue +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → R → List R → R +DEFINITION +fun {R} [OfNat R 0] [Add R] [Mul R] point x => List.brecOn x (Aiur.NativeAIR.Interpolation.derivativeValue._f point) +PREMISE Aiur.NativeAIR.Interpolation.combine +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → List R → R → List (R × R) → List R +DEFINITION +fun {R} [OfNat R 0] [Add R] [Mul R] vanishing scale x => + List.brecOn x (Aiur.NativeAIR.Interpolation.combine._f vanishing scale) +PREMISE Aiur.NativeAIR.Interpolation.coefficients +{R : Type u_1} → [OfNat R 0] → [OfNat R 1] → [Add R] → [Sub R] → [Mul R] → List (R × R) → R → List R +DEFINITION +fun {R} [OfNat R 0] [OfNat R 1] [Add R] [Sub R] [Mul R] samples scale => + Aiur.NativeAIR.Interpolation.combine (Aiur.NativeAIR.Polynomial.fromRoots (List.map Prod.fst samples)) scale samples +PREMISE Aiur.NativeAIR.Interpolation.weightedSum +Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → + List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) → + Option Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun scale point x => List.brecOn x (Aiur.NativeAIR.Interpolation.weightedSum._f scale point) +PREMISE Aiur.NativeAIR.Interpolation.evaluate +Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → + List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) → + Option Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun scale point samples => + match List.find? (fun sample => point == sample.fst) samples with + | some sample => some sample.snd + | none => do + let sum ← Aiur.NativeAIR.Interpolation.weightedSum scale point samples + pure (sum * Aiur.NativeAIR.LogUp.product (List.map (fun sample => point - sample.fst) samples)) +PREMISE Aiur.NativeAIR.Interpolation.foldSamples +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.Domain.Subgroup → + Nat → + List Aiur.NativeAIR.ProofCodec.Extension → + List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) +DEFINITION +fun parent arity index values => + (List.map Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Polynomial.foldingNodes parent arity index)).zip + values +PREMISE Aiur.NativeAIR.Interpolation.foldScale +Aiur.NativeAIR.Domain.Subgroup → Aiur.NativeAIR.Domain.Subgroup → Nat → Aiur.G +DEFINITION +fun parent arity index => + (Aiur.G.ofNat (Aiur.NativeAIR.Domain.size arity) * + (Aiur.NativeAIR.FriDomain.foldNode parent arity index 0).pow (Aiur.NativeAIR.Domain.size arity)).inverse +PREMISE Aiur.NativeAIR.Interpolation.foldRow +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.Domain.Subgroup → + Nat → + List Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.ProofCodec.Extension +DEFINITION +fun parent arity index values point => + if + (decide (↑arity > ↑parent) || decide (index ≥ 2 ^ (↑parent - ↑arity)) || + values.length != Aiur.NativeAIR.Domain.size arity) = + true then + none + else + Aiur.NativeAIR.Interpolation.evaluate + (Aiur.NativeAIR.ProofCodec.Extension.ofBase (Aiur.NativeAIR.Interpolation.foldScale parent arity index)) point + (Aiur.NativeAIR.Interpolation.foldSamples parent arity index values) +PREMISE Aiur.NativeAIR.Folding.foldCoefficients +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → Aiur.NativeAIR.Domain.Subgroup → R → List R → List R +DEFINITION +fun {R} [OfNat R 0] [Add R] [Mul R] arity challenge => + WellFounded.Nat.fix (fun x => x.length) fun coefficients a => + if _empty : coefficients = [] then [] + else + Aiur.NativeAIR.Quotient.horner challenge (List.take (Aiur.NativeAIR.Domain.size arity) coefficients) :: + a (List.drop (Aiur.NativeAIR.Domain.size arity) coefficients) ⋯ +PREMISE Aiur.NativeAIR.Folding.rowCoefficients +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → Aiur.NativeAIR.Domain.Subgroup → R → List R → List R +DEFINITION +fun {R} [OfNat R 0] [Add R] [Mul R] arity point => + WellFounded.Nat.fix (fun x => x.length) fun coefficients a => + if _empty : coefficients = [] then [] + else + Aiur.NativeAIR.Polynomial.add (List.take (Aiur.NativeAIR.Domain.size arity) coefficients) + (Aiur.NativeAIR.Polynomial.scale point (a (List.drop (Aiur.NativeAIR.Domain.size arity) coefficients) ⋯)) +PREMISE Aiur.NativeAIR.FriQuery.reconstruct +{R : Type u_1} → Aiur.NativeAIR.Domain.Subgroup → Nat → R → List R → Option (List R) +DEFINITION +fun {R} arity index value siblings => + if (siblings.length + 1 == Aiur.NativeAIR.Domain.size arity) = true then + some (siblings.insertIdx (index % Aiur.NativeAIR.Domain.size arity) value) + else none +PREMISE Aiur.NativeAIR.FriQuery.State.mk +Aiur.NativeAIR.Domain.Subgroup → Nat → Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.FriQuery.State +PREMISE Aiur.NativeAIR.FriQuery.Round.mk +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.ProofCodec.Extension → List Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.FriQuery.Round +PREMISE Aiur.NativeAIR.FriQuery.Row.mk +Aiur.NativeAIR.Domain.Subgroup → Nat → List Aiur.NativeAIR.ProofCodec.Extension → Aiur.NativeAIR.FriQuery.Row +PREMISE Aiur.NativeAIR.FriQuery.roll +Nat → + Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → + Aiur.NativeAIR.ProofCodec.Extension × List (Nat × Aiur.NativeAIR.ProofCodec.Extension) +DEFINITION +fun height factor value x => + match x with + | [] => (value, []) + | (nextHeight, next) :: rest => + if (nextHeight == height) = true then (value + factor * next, rest) else (value, (nextHeight, next) :: rest) +PREMISE Aiur.NativeAIR.FriQuery.StepResult.mk +Aiur.NativeAIR.FriQuery.State → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → Aiur.NativeAIR.FriQuery.Row → Aiur.NativeAIR.FriQuery.StepResult +PREMISE Aiur.NativeAIR.FriQuery.step +Aiur.NativeAIR.FriQuery.State → + Aiur.NativeAIR.FriQuery.Round → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → Option Aiur.NativeAIR.FriQuery.StepResult +DEFINITION +fun state round openings => + if (↑round.arity == 0 || decide (↑round.arity > ↑state.domain)) = true then none + else do + let child ← Aiur.NativeAIR.Domain.ofLogSize (↑state.domain - ↑round.arity) + let values ← Aiur.NativeAIR.FriQuery.reconstruct round.arity state.index state.value round.siblings + have index : Nat := state.index / Aiur.NativeAIR.Domain.size round.arity + let folded ← Aiur.NativeAIR.Interpolation.foldRow state.domain round.arity index values round.challenge + match + Aiur.NativeAIR.FriQuery.roll (↑child) (round.challenge.power (Aiur.NativeAIR.Domain.size round.arity)) folded + openings with + | (value, remaining) => + pure + { state := { domain := child, index := index, value := value }, remaining := remaining, + row := { domain := child, index := index, values := values } } +PREMISE Aiur.NativeAIR.FriQuery.Result.mk +Aiur.NativeAIR.FriQuery.State → List Aiur.NativeAIR.FriQuery.Row → Aiur.NativeAIR.FriQuery.Result +PREMISE Aiur.NativeAIR.FriQuery.walk +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.FriQuery.State → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → + List Aiur.NativeAIR.FriQuery.Round → Option Aiur.NativeAIR.FriQuery.Result +DEFINITION +fun final state openings x => + List.brecOn (motive := fun x => + Aiur.NativeAIR.FriQuery.State → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → Option Aiur.NativeAIR.FriQuery.Result) + x (Aiur.NativeAIR.FriQuery.walk._f final) state openings +PREMISE Aiur.NativeAIR.FriQuery.run +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.Domain.Subgroup → + Nat → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → + List Aiur.NativeAIR.FriQuery.Round → Option Aiur.NativeAIR.FriQuery.Result +DEFINITION +fun initial final index openings rounds => + if index ≥ Aiur.NativeAIR.Domain.size initial then none + else + match openings with + | [] => none + | (height, value) :: rest => + if (height == ↑initial) = true then + Aiur.NativeAIR.FriQuery.walk final { domain := initial, index := index, value := value } rest rounds + else none +PREMISE Aiur.NativeAIR.FriQuery.check +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.Domain.Subgroup → + Nat → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → + List Aiur.NativeAIR.FriQuery.Round → + List Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.FriQuery.Result +DEFINITION +fun initial final index openings rounds finalPolynomial => do + let result ← Aiur.NativeAIR.FriQuery.run initial final index openings rounds + if + (Aiur.NativeAIR.Quotient.horner + (Aiur.NativeAIR.ProofCodec.Extension.ofBase + (Aiur.NativeAIR.FriDomain.queryPoint initial result.state.index)) + finalPolynomial == + result.state.value) = + true then + some result + else none +RECURSION WORKER Aiur.buildArgs._unsafe_rec +Aiur.LayoutMap → + Std.HashMap Aiur.Local (Array Aiur.Bytecode.ValIdx) → + List Aiur.Concrete.Term → optParam (Array Aiur.Bytecode.ValIdx) #[] → Aiur.CompileM (Array Aiur.Bytecode.ValIdx) +IMPLEMENTATION +fun layoutMap bindings args init => + List.foldlM + (fun acc x => + match x with + | ⟨arg, property⟩ => do + let __do_lift ← Aiur.toIndex._unsafe_rec layoutMap bindings arg + pure (acc.append __do_lift)) + init args.attach +RECURSION WORKER Aiur.checkArgsAndInputs._unsafe_rec +Aiur.Global → List Aiur.Source.Term → List Aiur.Typ → Aiur.CheckM (List Aiur.Typed.Term) +IMPLEMENTATION +fun func args inputs => + let lenArgs := args.length; + let lenInputs := inputs.length; + have __do_jp := fun __r => + List.mapM + (fun x => + match x with + | (⟨arg, property⟩, input) => Aiur.checkNoEscape._unsafe_rec arg input) + (args.attach.zip inputs); + if (lenArgs == lenInputs) = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.wrongNumArgs func lenArgs lenInputs) + __do_jp __r +RECURSION WORKER Aiur.checkMatchBranch._unsafe_rec +Aiur.Typ → + Aiur.Pattern × Aiur.Source.Term → + List (Aiur.Pattern × Aiur.Typed.Term) × Option (Aiur.Typ × Bool) → + Aiur.CheckM (List (Aiur.Pattern × Aiur.Typed.Term) × Option (Aiur.Typ × Bool)) +IMPLEMENTATION +fun patTyp branchData acc => + match branchData with + | (pat, branch) => + match acc with + | (typedBranches, currentTypOpt) => do + let bindings ← Aiur.checkPattern pat patTyp + withReader (Aiur.bindIdents bindings) + (match currentTypOpt with + | none => do + let typedBranch ← Aiur.inferTerm._unsafe_rec branch + pure ((pat, typedBranch) :: typedBranches, some (typedBranch.typ, typedBranch.escapes)) + | some (matchTyp, matchEscapes) => do + let typedBranch ← Aiur.inferTerm._unsafe_rec branch + let typedBranches : List (Aiur.Pattern × Aiur.Typed.Term) := (pat, typedBranch) :: typedBranches + if typedBranch.escapes = true then pure (typedBranches, currentTypOpt) + else + if matchEscapes = true then pure (typedBranches, some (typedBranch.typ, false)) + else do + let __do_lift ← Aiur.unifyTyp matchTyp typedBranch.typ + have __do_jp : + Unit → Aiur.CheckM (List (Aiur.Pattern × Aiur.Typed.Term) × Option (Aiur.Typ × Bool)) := fun __r => + pure (typedBranches, currentTypOpt) + if __do_lift = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.branchMismatch matchTyp typedBranch.typ) + __do_jp __r) +RECURSION WORKER Aiur.checkNoEscape._unsafe_rec +Aiur.Source.Term → Aiur.Typ → Aiur.CheckM Aiur.Typed.Term +IMPLEMENTATION +fun term typ => do + let typedTerm ← Aiur.inferTerm._unsafe_rec term + have __do_jp : Unit → Aiur.CheckM Aiur.Typed.Term := fun __r => do + let __do_lift ← Aiur.unifyTyp typ typedTerm.typ + have __do_jp : Unit → Aiur.CheckM Aiur.Typed.Term := fun __r => pure typedTerm + if __do_lift = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.typeMismatch typ typedTerm.typ) + __do_jp __r + if typedTerm.escapes = true then do + let __r ← throw Aiur.CheckError.illegalReturn + __do_jp __r + else __do_jp () +RECURSION WORKER Aiur.checkPatternAux._unsafe_rec +Aiur.Pattern → Aiur.Typ → Aiur.CheckM (List (Aiur.Local × Aiur.Typ)) +IMPLEMENTATION +fun pat typ => do + let typ ← Aiur.walkTyp typ + match pat with + | Aiur.Pattern.var var => pure [(var, typ)] + | Aiur.Pattern.wildcard => pure [] + | Aiur.Pattern.field a => + match typ with + | Aiur.Typ.field => pure [] + | Aiur.Typ.u8 => pure [] + | x => throw (Aiur.CheckError.incompatiblePattern pat typ) + | Aiur.Pattern.tuple pats => + match typ with + | Aiur.Typ.tuple typs => + have __do_jp := fun __r => Aiur.checkPatternsArr._unsafe_rec pats typs; + if (pats.size == typs.size) = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.incompatiblePattern pat typ) + __do_jp __r + | x => throw (Aiur.CheckError.incompatiblePattern pat typ) + | Aiur.Pattern.array pats => + match typ with + | innerTyp.array n => + have __do_jp := fun __r => Aiur.checkPatternsArrUniform._unsafe_rec pats innerTyp; + if (pats.size == n) = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.incompatiblePattern pat typ) + __do_jp __r + | x => throw (Aiur.CheckError.incompatiblePattern pat typ) + | Aiur.Pattern.ref refName pats => + match typ with + | tFn@h:(Aiur.Typ.function a a_1) => + if pats.isEmpty = true then do + let ctx ← read + match IndexMap.getByKey ctx.decls refName with + | some (Aiur.Source.Declaration.function function) => + let typ' := Aiur.Typ.function (List.map Prod.snd function.inputs) function.output; + do + let __do_lift ← Aiur.unifyTyp tFn typ' + have __do_jp : Unit → Aiur.CheckM (List (Aiur.Local × Aiur.Typ)) := fun __r => pure [] + if __do_lift = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.typeMismatch tFn typ') + __do_jp __r + | x => throw (Aiur.CheckError.incompatiblePattern pat typ) + else throw (Aiur.CheckError.incompatiblePattern pat typ) + | Aiur.Typ.ref dataTypeRef => do + let ctx ← read + match IndexMap.getByKey ctx.decls dataTypeRef with + | some (Aiur.Source.Declaration.dataType dataType) => + match IndexMap.getByKey ctx.decls refName with + | some (Aiur.Source.Declaration.constructor dataType' constr) => + have __do_jp := fun __r => + let typs := constr.argTypes; + have __do_jp := fun __r => Aiur.checkPatternsList._unsafe_rec pats typs; + if (pats.length == typs.length) = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.wrongNumArgs refName pats.length typs.length) + __do_jp __r; + if (dataType == dataType') = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.incompatiblePattern pat typ) + __do_jp __r + | x => throw (Aiur.CheckError.notAConstructor refName) + | x => throw (Aiur.CheckError.unboundGlobal dataTypeRef) + | Aiur.Typ.app dataTypeRef args => do + let ctx ← read + match IndexMap.getByKey ctx.decls dataTypeRef with + | some (Aiur.Source.Declaration.dataType dataType) => + match IndexMap.getByKey ctx.decls refName with + | some (Aiur.Source.Declaration.constructor dataType' constr) => + have __do_jp := fun __r => + let subst := Aiur.mkParamSubst dataType.params args; + let typs := List.map (Aiur.Typ.instantiate subst) constr.argTypes; + have __do_jp := fun __r => Aiur.checkPatternsList._unsafe_rec pats typs; + if (pats.length == typs.length) = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.wrongNumArgs refName pats.length typs.length) + __do_jp __r; + if (dataType == dataType') = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.incompatiblePattern pat typ) + __do_jp __r + | x => throw (Aiur.CheckError.notAConstructor refName) + | x => throw (Aiur.CheckError.unboundGlobal dataTypeRef) + | x => throw (Aiur.CheckError.incompatiblePattern pat typ) + | p1.or p2 => do + let bind ← Aiur.checkPatternAux._unsafe_rec p1 typ + let bind' ← Aiur.checkPatternAux._unsafe_rec p2 typ + if (bind != bind') = true then throw (Aiur.CheckError.differentBindings bind bind') else pure bind + | p.pointer => + match typ with + | innerTyp.pointer => Aiur.checkPatternAux._unsafe_rec p innerTyp + | x => throw (Aiur.CheckError.incompatiblePattern pat typ) +RECURSION WORKER Aiur.checkPatternsArr._unsafe_rec +Array Aiur.Pattern → Array Aiur.Typ → Aiur.CheckM (List (Aiur.Local × Aiur.Typ)) +IMPLEMENTATION +fun pats typs => + Array.foldlM + (fun acc x => + match x with + | (⟨pat, hmem⟩, typ) => + have this := ⋯; + do + let sub ← Aiur.checkPatternAux._unsafe_rec pat typ + pure (acc.append sub)) + [] (pats.attach.zip typs) +RECURSION WORKER Aiur.checkPatternsArrUniform._unsafe_rec +Array Aiur.Pattern → Aiur.Typ → Aiur.CheckM (List (Aiur.Local × Aiur.Typ)) +IMPLEMENTATION +fun pats innerTyp => + Array.foldlM + (fun acc x => + match x with + | ⟨pat, hmem⟩ => + have this := ⋯; + do + let sub ← Aiur.checkPatternAux._unsafe_rec pat innerTyp + pure (acc.append sub)) + [] pats.attach +RECURSION WORKER Aiur.checkPatternsList._unsafe_rec +List Aiur.Pattern → List Aiur.Typ → Aiur.CheckM (List (Aiur.Local × Aiur.Typ)) +IMPLEMENTATION +fun pats typs => + List.foldlM + (fun acc x => + match x with + | (⟨pat, hmem⟩, typ) => + have this := ⋯; + do + let sub ← Aiur.checkPatternAux._unsafe_rec pat typ + pure (acc.append sub)) + [] (pats.attach.zip typs) +RECURSION WORKER Aiur.collectCalls._unsafe_rec +Aiur.Typed.Decls → + Std.HashSet (Aiur.Global × Array Aiur.Typ) → Aiur.Typed.Term → Std.HashSet (Aiur.Global × Array Aiur.Typ) +IMPLEMENTATION +fun decls seen x => + match x with + | Aiur.Typed.Term.app typ escapes g tArgs args unconstrained => + let seen := + List.foldl + (fun s x => + match x with + | ⟨a, property⟩ => Aiur.collectCalls._unsafe_rec decls s a) + seen args.attach; + if tArgs.isEmpty = true then seen + else + match IndexMap.getByKey decls g with + | some (Aiur.Typed.Declaration.function a) => seen.insert (g, tArgs) + | some (Aiur.Typed.Declaration.constructor dt a) => seen.insert (dt.name, tArgs) + | x => seen + | Aiur.Typed.Term.ref typ escapes g tArgs => + if tArgs.isEmpty = true then seen + else + match IndexMap.getByKey decls g with + | some (Aiur.Typed.Declaration.function a) => seen.insert (g, tArgs) + | some (Aiur.Typed.Declaration.constructor dt a) => seen.insert (dt.name, tArgs) + | x => seen + | Aiur.Typed.Term.unit typ escapes => seen + | Aiur.Typed.Term.var typ escapes l => seen + | Aiur.Typed.Term.field typ escapes g => seen + | Aiur.Typed.Term.tuple typ escapes ts => + Array.foldl + (fun s x => + match x with + | ⟨t, property⟩ => Aiur.collectCalls._unsafe_rec decls s t) + seen ts.attach + | Aiur.Typed.Term.array typ escapes ts => + Array.foldl + (fun s x => + match x with + | ⟨t, property⟩ => Aiur.collectCalls._unsafe_rec decls s t) + seen ts.attach + | Aiur.Typed.Term.ret typ escapes r => Aiur.collectCalls._unsafe_rec decls seen r + | Aiur.Typed.Term.let typ escapes pat v b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen v) b + | Aiur.Typed.Term.match typ escapes scrut bs => + let seen := Aiur.collectCalls._unsafe_rec decls seen scrut; + List.foldl + (fun s x => + match x with + | ⟨(fst, b), property⟩ => Aiur.collectCalls._unsafe_rec decls s b) + seen bs.attach + | Aiur.Typed.Term.add typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.sub typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.mul typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8Xor typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8Add typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8Mul typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8Sub typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8XorSplit7 typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8XorSplit4 typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8RangeCheck typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.unconstrainedBigUintDivMod typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8And typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8Or typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u8LessThan typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.u32LessThan typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.unconstrainedU32Add typ escapes a b => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b + | Aiur.Typed.Term.unconstrainedU32Add3 typ escapes a b c => + Aiur.collectCalls._unsafe_rec decls + (Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b) c + | Aiur.Typed.Term.eqZero typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.store typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.load typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.ptrVal typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.toField typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.u8FromFieldUnsafe typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.unconstrainedGToBytes typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.unconstrainedGInverse typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.u32ToField typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.u8BitDecomposition typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.u8ShiftLeft typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.u8ShiftRight typ escapes a => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.ioGetInfo typ escapes c k => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen c) k + | Aiur.Typed.Term.proj typ escapes a n => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.get typ escapes a n => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.slice typ escapes a i j => Aiur.collectCalls._unsafe_rec decls seen a + | Aiur.Typed.Term.set typ escapes a n v => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) v + | Aiur.Typed.Term.assertEq typ escapes a b msg r => + Aiur.collectCalls._unsafe_rec decls + (Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen a) b) r + | Aiur.Typed.Term.ioSetInfo typ escapes c k i l r => + Aiur.collectCalls._unsafe_rec decls + (Aiur.collectCalls._unsafe_rec decls + (Aiur.collectCalls._unsafe_rec decls + (Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen c) k) i) + l) + r + | Aiur.Typed.Term.ioRead typ escapes c i n => + Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen c) i + | Aiur.Typed.Term.ioWrite typ escapes c d r => + Aiur.collectCalls._unsafe_rec decls + (Aiur.collectCalls._unsafe_rec decls (Aiur.collectCalls._unsafe_rec decls seen c) d) r + | Aiur.Typed.Term.debug typ escapes label t r => + let seen := + match t with + | some t => Aiur.collectCalls._unsafe_rec decls seen t + | none => seen; + Aiur.collectCalls._unsafe_rec decls seen r +RECURSION WORKER Aiur.collectInTyp._unsafe_rec +Std.HashSet (Aiur.Global × Array Aiur.Typ) → Aiur.Typ → Std.HashSet (Aiur.Global × Array Aiur.Typ) +IMPLEMENTATION +fun seen x => + match x with + | Aiur.Typ.app g args => + let seen := + Array.foldl + (fun s x => + match x with + | ⟨t, property⟩ => Aiur.collectInTyp._unsafe_rec s t) + seen args.attach; + seen.insert (g, args) + | Aiur.Typ.tuple ts => + Array.foldl + (fun s x => + match x with + | ⟨t, property⟩ => Aiur.collectInTyp._unsafe_rec s t) + seen ts.attach + | t.array a => Aiur.collectInTyp._unsafe_rec seen t + | t.pointer => Aiur.collectInTyp._unsafe_rec seen t + | Aiur.Typ.function ins out => + let seen := + List.foldl + (fun s x => + match x with + | ⟨t, property⟩ => Aiur.collectInTyp._unsafe_rec s t) + seen ins.attach; + Aiur.collectInTyp._unsafe_rec seen out + | x => seen +RECURSION WORKER Aiur.collectInTypedTerm._unsafe_rec +Std.HashSet (Aiur.Global × Array Aiur.Typ) → Aiur.Typed.Term → Std.HashSet (Aiur.Global × Array Aiur.Typ) +IMPLEMENTATION +fun seen x => + match x with + | Aiur.Typed.Term.unit τ escapes => Aiur.collectInTyp seen τ + | Aiur.Typed.Term.var τ escapes l => Aiur.collectInTyp seen τ + | Aiur.Typed.Term.ref τ escapes g tArgs => + let seen := Aiur.collectInTyp seen τ; + Array.foldl Aiur.collectInTyp seen tArgs + | Aiur.Typed.Term.field τ escapes g => Aiur.collectInTyp seen τ + | Aiur.Typed.Term.tuple τ escapes ts => + let seen := Aiur.collectInTyp seen τ; + Array.foldl + (fun s x => + match x with + | ⟨t, property⟩ => Aiur.collectInTypedTerm._unsafe_rec s t) + seen ts.attach + | Aiur.Typed.Term.array τ escapes ts => + let seen := Aiur.collectInTyp seen τ; + Array.foldl + (fun s x => + match x with + | ⟨t, property⟩ => Aiur.collectInTypedTerm._unsafe_rec s t) + seen ts.attach + | Aiur.Typed.Term.ret τ escapes r => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) r + | Aiur.Typed.Term.let τ escapes pat v b => + let seen := Aiur.collectInTyp seen τ; + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec seen v) b + | Aiur.Typed.Term.match τ escapes scrut bs => + let seen := Aiur.collectInTyp seen τ; + let seen := Aiur.collectInTypedTerm._unsafe_rec seen scrut; + List.foldl + (fun s x => + match x with + | ⟨(fst, b), property⟩ => Aiur.collectInTypedTerm._unsafe_rec s b) + seen bs.attach + | Aiur.Typed.Term.app τ escapes g tArgs args unconstrained => + let seen := Aiur.collectInTyp seen τ; + let seen := Array.foldl Aiur.collectInTyp seen tArgs; + List.foldl + (fun s x => + match x with + | ⟨a, property⟩ => Aiur.collectInTypedTerm._unsafe_rec s a) + seen args.attach + | Aiur.Typed.Term.add τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.sub τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.mul τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8Xor τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8Add τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8Mul τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8Sub τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8XorSplit7 τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8XorSplit4 τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8RangeCheck τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.unconstrainedBigUintDivMod τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8And τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8Or τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u8LessThan τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.u32LessThan τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.unconstrainedU32Add τ escapes a b => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b + | Aiur.Typed.Term.unconstrainedU32Add3 τ escapes a b c => + Aiur.collectInTypedTerm._unsafe_rec + (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b) c + | Aiur.Typed.Term.eqZero τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.store τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.load τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.ptrVal τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.toField τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.u8FromFieldUnsafe τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.unconstrainedGToBytes τ escapes a => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.unconstrainedGInverse τ escapes a => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.u32ToField τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.u8BitDecomposition τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.u8ShiftLeft τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.u8ShiftRight τ escapes a => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.ioGetInfo τ escapes c k => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) c) k + | Aiur.Typed.Term.proj τ escapes a n => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.get τ escapes a n => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.slice τ escapes a i j => Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a + | Aiur.Typed.Term.set τ escapes a n v => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) v + | Aiur.Typed.Term.assertEq τ escapes a b msg r => + Aiur.collectInTypedTerm._unsafe_rec + (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) a) b) r + | Aiur.Typed.Term.ioSetInfo τ escapes c k i l r => + Aiur.collectInTypedTerm._unsafe_rec + (Aiur.collectInTypedTerm._unsafe_rec + (Aiur.collectInTypedTerm._unsafe_rec + (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) c) k) i) + l) + r + | Aiur.Typed.Term.ioRead τ escapes c i n => + Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) c) i + | Aiur.Typed.Term.ioWrite τ escapes c d r => + Aiur.collectInTypedTerm._unsafe_rec + (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTypedTerm._unsafe_rec (Aiur.collectInTyp seen τ) c) d) r + | Aiur.Typed.Term.debug τ escapes label t r => + let seen := Aiur.collectInTyp seen τ; + let seen := + match t with + | some t => Aiur.collectInTypedTerm._unsafe_rec seen t + | none => seen; + Aiur.collectInTypedTerm._unsafe_rec seen r +RECURSION WORKER Aiur.concretizeDrain._unsafe_rec +Aiur.Typed.Decls → Nat → Aiur.DrainState → Except Aiur.ConcretizeError Aiur.DrainState +IMPLEMENTATION +fun decls x x_1 => + match x, x_1 with + | 0, state => if state.pending.isEmpty = true then pure state else throw Aiur.ConcretizeError.fuelExhausted + | fuel.succ, state => + if state.pending.isEmpty = true then pure state + else do + let state' ← Aiur.concretizeDrainIter decls state + Aiur.concretizeDrain._unsafe_rec decls fuel state' +RECURSION WORKER Aiur.dataTypeFlatSizeBound._unsafe_rec +Aiur.Source.Decls → Nat → Std.HashSet Aiur.Global → Aiur.DataType → Nat +IMPLEMENTATION +fun decls x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, x_3 => 1 + | bound.succ, visited, dt => + let ctorSizes := + List.map + (fun ctor => + List.foldl (fun acc t => acc + Aiur.typFlatSizeBound._unsafe_rec decls bound visited t) 0 ctor.argTypes) + dt.constructors; + if (dt.constructors.length == 1) = true then List.foldl max 0 ctorSizes else List.foldl max 0 ctorSizes + 1 +RECURSION WORKER Aiur.expandPattern._unsafe_rec +Aiur.Concrete.Typ → + Aiur.Local → + Aiur.Pattern → Aiur.Concrete.Term → Except Aiur.ConcretizeError (Array (Aiur.Concrete.Pattern × Aiur.Concrete.Term)) +IMPLEMENTATION +fun scrutTyp scrutLocal x x_1 => + match x, x_1 with + | Aiur.Pattern.wildcard, cb => pure #[(Aiur.Concrete.Pattern.wildcard, cb)] + | Aiur.Pattern.var x, cb => + pure + #[(Aiur.Concrete.Pattern.wildcard, + Aiur.Concrete.Term.letVar cb.typ cb.escapes x (Aiur.Concrete.Term.var scrutTyp false scrutLocal) cb)] + | Aiur.Pattern.field g, cb => pure #[(Aiur.Concrete.Pattern.field g, cb)] + | Aiur.Pattern.ref g pats, cb => do + let locals ← Aiur.subPatternsToLocals pats + pure #[(Aiur.Concrete.Pattern.ref g locals, cb)] + | Aiur.Pattern.tuple pats, cb => do + let locals ← Aiur.subPatternsToLocalsArr pats + pure #[(Aiur.Concrete.Pattern.tuple locals, cb)] + | Aiur.Pattern.array pats, cb => do + let locals ← Aiur.subPatternsToLocalsArr pats + pure #[(Aiur.Concrete.Pattern.array locals, cb)] + | p1.or p2, cb => do + let __do_lift ← Aiur.expandPattern._unsafe_rec scrutTyp scrutLocal p1 cb + let __do_lift_1 ← Aiur.expandPattern._unsafe_rec scrutTyp scrutLocal p2 cb + pure (__do_lift ++ __do_lift_1) + | x, x_2 => throw Aiur.ConcretizeError.unsupportedPattern +RECURSION WORKER Aiur.expandTypeMBound._unsafe_rec +Nat → + Std.HashSet Aiur.Global → + Array Aiur.TypeAlias → Aiur.Typ → StateT (Std.HashMap Aiur.Global Aiur.Typ) (Except Aiur.CheckError) Aiur.Typ +IMPLEMENTATION +fun x x_1 x_2 x_3 => + match x, x_1, x_2, x_3 with + | x, x_4, x_5, Aiur.Typ.unit => pure Aiur.Typ.unit + | x, x_4, x_5, Aiur.Typ.field => pure Aiur.Typ.field + | x, x_4, x_5, Aiur.Typ.u8 => pure Aiur.Typ.u8 + | bound, visited, tops, t.pointer => do + let __do_lift ← Aiur.expandTypeMBound._unsafe_rec bound visited tops t + pure __do_lift.pointer + | bound, visited, tops, Aiur.Typ.function inputs output => do + let inputs' ← + List.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.expandTypeMBound._unsafe_rec bound visited tops t) + inputs.attach + let output' ← Aiur.expandTypeMBound._unsafe_rec bound visited tops output + pure (Aiur.Typ.function inputs' output') + | bound, visited, tops, Aiur.Typ.tuple ts => do + let ts' ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.expandTypeMBound._unsafe_rec bound visited tops t) + ts.attach + pure (Aiur.Typ.tuple ts') + | bound, visited, tops, t.array n => do + let t' ← Aiur.expandTypeMBound._unsafe_rec bound visited tops t + pure (t'.array n) + | bound, visited, tops, Aiur.Typ.app g args => do + let args' ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.expandTypeMBound._unsafe_rec bound visited tops t) + args.attach + match Array.find? (fun x => x.name == g) tops with + | some «alias» => + have __do_jp := fun __r => + have __do_jp := fun __r => + let subst := Aiur.mkParamSubst «alias».params args'; + let instantiated := Aiur.Typ.instantiate subst «alias».expansion; + match bound with + | 0 => pure (Aiur.Typ.app g args') + | bound.succ => Aiur.expandTypeMBound._unsafe_rec bound (visited.insert g) tops instantiated; + if («alias».params.length != args'.size) = true then do + let __r ← throw (Aiur.CheckError.wrongNumTypeArgs g «alias».params.length args'.size) + __do_jp __r + else __do_jp (); + if visited.contains g = true then do + let __r ← throw (Aiur.CheckError.typeAliasCycle g) + __do_jp __r + else __do_jp () + | x => pure (Aiur.Typ.app g args') + | bound, visited, tops, Aiur.Typ.ref g => do + let aliasMap ← get + match aliasMap[g]? with + | some expanded => pure expanded + | x => + match Array.find? (fun x => x.name == g) tops with + | some «alias» => + have __do_jp := fun __r => + have __do_jp := fun __r => + match bound with + | 0 => pure (Aiur.Typ.ref g) + | bound.succ => do + let expanded ← Aiur.expandTypeMBound._unsafe_rec bound (visited.insert g) tops «alias».expansion + set (aliasMap.insert g expanded) + pure expanded; + if (!«alias».params.isEmpty) = true then do + let __r ← throw (Aiur.CheckError.wrongNumTypeArgs g «alias».params.length 0) + __do_jp __r + else __do_jp (); + if visited.contains g = true then do + let __r ← throw (Aiur.CheckError.typeAliasCycle g) + __do_jp __r + else __do_jp () + | x => pure (Aiur.Typ.ref g) + | x, x_4, x_5, Aiur.Typ.mvar n => pure (Aiur.Typ.mvar n) +RECURSION WORKER Aiur.expectIdx._unsafe_rec +Aiur.LayoutMap → + Std.HashMap Aiur.Local (Array Aiur.Bytecode.ValIdx) → Aiur.Concrete.Term → Aiur.CompileM Aiur.Bytecode.ValIdx +IMPLEMENTATION +fun layoutMap bindings term => do + let idxs ← Aiur.toIndex._unsafe_rec layoutMap bindings term + if h : idxs.size = 1 then + have this := ⋯; + pure idxs[0] + else throw "Term is not of size 1" +RECURSION WORKER Aiur.fixedTraceHeights._unsafe_rec +List Nat → List Bool → List Nat → Bool +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | [], [], [] => true + | height :: heights, false :: active, degrees => + height == 0 && Aiur.fixedTraceHeights._unsafe_rec heights active degrees + | height :: heights, true :: active, degree :: degrees => + (height == 0 || decide (degree < 64) && height == 2 ^ degree) && + Aiur.fixedTraceHeights._unsafe_rec heights active degrees + | x, x_3, x_4 => false +RECURSION WORKER Aiur.flattenValue._unsafe_rec +Aiur.Source.Decls → (Aiur.Global → Option Nat) → Aiur.Value → Array Aiur.G +IMPLEMENTATION +fun decls funcIdx x => + match x with + | Aiur.Value.unit => #[] + | Aiur.Value.field g => #[g] + | Aiur.Value.pointer width n => #[Aiur.G.ofNat n] + | Aiur.Value.fn g => #[Aiur.G.ofNat ((funcIdx g).getD 0)] + | Aiur.Value.tuple vs => + Array.flatMap + (fun x => + match x with + | ⟨v, property⟩ => Aiur.flattenValue._unsafe_rec decls funcIdx v) + vs.attach + | Aiur.Value.array vs => + Array.flatMap + (fun x => + match x with + | ⟨v, property⟩ => Aiur.flattenValue._unsafe_rec decls funcIdx v) + vs.attach + | Aiur.Value.ctor g args => + match IndexMap.getByKey decls g with + | some (Aiur.Source.Declaration.constructor dt ctor) => + let dtSize := Aiur.dataTypeFlatSize decls ∅ dt; + let argsFlat := + Array.flatMap + (fun x => + match x with + | ⟨v, property⟩ => Aiur.flattenValue._unsafe_rec decls funcIdx v) + args.attach; + let flat := + if (dt.constructors.length == 1) = true then argsFlat + else + let ctorIndex := (List.findIdx? (fun x => x == ctor) dt.constructors).getD 0; + #[Aiur.G.ofNat ctorIndex] ++ argsFlat; + let padding := dtSize - flat.size; + flat ++ Array.replicate padding 0 + | x => + Array.flatMap + (fun x => + match x with + | ⟨v, property⟩ => Aiur.flattenValue._unsafe_rec decls funcIdx v) + args.attach +RECURSION WORKER Aiur.inferNoEscape._unsafe_rec +Aiur.Source.Term → Aiur.CheckM Aiur.Typed.Term +IMPLEMENTATION +fun term => do + let typedTerm ← Aiur.inferTerm._unsafe_rec term + have __do_jp : Unit → Aiur.CheckM Aiur.Typed.Term := fun __r => pure typedTerm + if typedTerm.escapes = true then do + let __r ← throw Aiur.CheckError.illegalReturn + __do_jp __r + else __do_jp () +RECURSION WORKER Aiur.inferTerm._unsafe_rec +Aiur.Source.Term → Aiur.CheckM Aiur.Typed.Term +IMPLEMENTATION +fun t => + match t with + | Aiur.Source.Term.unit => pure (Aiur.Typed.Term.unit Aiur.Typ.unit false) + | Aiur.Source.Term.var x => do + let ctx ← read + match (ctx.varTypes[x]?, x) with + | (some t, snd) => pure (Aiur.Typed.Term.var t false x) + | (none, Aiur.Local.str localName) => do + let __x ← Aiur.refLookup (Aiur.Global.init localName) + match __x with + | (typ, snd) => pure (Aiur.Typed.Term.var typ false x) + | (none, snd) => throw (Aiur.CheckError.unboundLocal x) + | Aiur.Source.Term.ref x => do + let __x ← Aiur.refLookup x + match __x with + | (typ, tArgs) => pure (Aiur.Typed.Term.ref typ false x tArgs) + | term.ret => do + let ctx ← read + let term' ← Aiur.checkNoEscape._unsafe_rec term ctx.returnType + pure (Aiur.Typed.Term.ret ctx.returnType true term') + | Aiur.Source.Term.field g => pure (Aiur.Typed.Term.field Aiur.Typ.field false g) + | Aiur.Source.Term.tuple ts => do + let typedTerms ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.inferNoEscape._unsafe_rec t) + ts.attach + let typs : Array Aiur.Typ := Array.map (fun x => x.typ) typedTerms + pure (Aiur.Typed.Term.tuple (Aiur.Typ.tuple typs) false typedTerms) + | Aiur.Source.Term.array ts => + if h : ts.size > 0 then do + let first ← Aiur.inferNoEscape._unsafe_rec ts[0] + let typedTerms ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.checkNoEscape._unsafe_rec t first.typ) + ts.attach + pure (Aiur.Typed.Term.array (first.typ.array ts.size) false typedTerms) + else throw Aiur.CheckError.emptyArray + | Aiur.Source.Term.let pat expr body => do + let expr' ← Aiur.inferNoEscape._unsafe_rec expr + let bindings ← Aiur.checkPattern pat expr'.typ + let body' ← withReader (Aiur.bindIdents bindings) (Aiur.inferTerm._unsafe_rec body) + pure (Aiur.Typed.Term.let body'.typ body'.escapes pat expr' body') + | term.match branches => do + let term' ← Aiur.inferNoEscape._unsafe_rec term + let init : List (Aiur.Pattern × Aiur.Typed.Term) × Option (Aiur.Typ × Bool) := ([], none) + let __x ← + List.foldrM + (fun x acc => + match x with + | ⟨branchData, property⟩ => Aiur.checkMatchBranch._unsafe_rec term'.typ branchData acc) + init branches.attach + match __x with + | (branches', typOpt) => + match typOpt with + | some (typ, escapes) => pure (Aiur.Typed.Term.match typ escapes term' branches') + | none => throw Aiur.CheckError.emptyMatch + | Aiur.Source.Term.app func args mode => + have __do_jp := fun u => do + let ctx ← read + let localLookup : Option (Except Aiur.CheckError (Aiur.Typ × List Aiur.Typ)) := + match func.toName with + | Name.anonymous.str s => + match ctx.varTypes[Aiur.Local.str s]? with + | some (Aiur.Typ.function ins out) => some (Except.ok (out, ins)) + | some val => some (Except.error (Aiur.CheckError.notAFunction func)) + | none => none + | x => none + match localLookup with + | some (Except.error e) => throw e + | some (Except.ok (output, inputs)) => do + let args' ← Aiur.checkArgsAndInputs._unsafe_rec func args inputs + pure (Aiur.Typed.Term.app output false func #[] args' u) + | none => + match IndexMap.getByKey ctx.decls func with + | some (Aiur.Source.Declaration.function function) => + if function.params.isEmpty = true then do + let args' ← Aiur.checkArgsAndInputs._unsafe_rec func args (List.map Prod.snd function.inputs) + pure (Aiur.Typed.Term.app function.output false func #[] args' u) + else do + let __x ← Aiur.instantiateParams function.params + match __x with + | (mvars, subst) => + let inputTypes := List.map (Aiur.Typ.instantiate subst ∘ Prod.snd) function.inputs; + let output := Aiur.Typ.instantiate subst function.output; + do + let args' ← Aiur.checkArgsAndInputs._unsafe_rec func args inputTypes + pure (Aiur.Typed.Term.app output false func mvars args' u) + | some (Aiur.Source.Declaration.constructor dataType constr) => + have __do_jp := fun __r => + if dataType.params.isEmpty = true then do + let args' ← Aiur.checkArgsAndInputs._unsafe_rec func args constr.argTypes + pure (Aiur.Typed.Term.app (Aiur.Typ.ref dataType.name) false func #[] args' u) + else do + let __x ← Aiur.instantiateParams dataType.params + match __x with + | (mvars, subst) => + let argTypes := List.map (Aiur.Typ.instantiate subst) constr.argTypes; + do + let args' ← Aiur.checkArgsAndInputs._unsafe_rec func args argTypes + pure (Aiur.Typed.Term.app (Aiur.Typ.app dataType.name mvars) false func mvars args' u); + if u = true then do + let __r ← throw (Aiur.CheckError.unconstrainedConstructor func) + __do_jp __r + else __do_jp () + | x => throw (Aiur.CheckError.cannotApply func); + match mode with + | Aiur.Source.CallMode.normal => do + let u ← pure false + __do_jp u + | Aiur.Source.CallMode.unconstrained => do + let u ← pure true + __do_jp u + | Aiur.Source.CallMode.inlined => do + let u ← throw (Aiur.CheckError.cannotApply func) + __do_jp u + | Aiur.Source.Term.ann typ term => Aiur.checkNoEscape._unsafe_rec term typ + | tup.proj i => do + let tup' ← Aiur.inferNoEscape._unsafe_rec tup + let __do_lift ← Aiur.walkTyp tup'.typ + match __do_lift with + | Aiur.Typ.tuple typs => + if h : i < typs.size then pure (Aiur.Typed.Term.proj typs[i] false tup' i) + else throw (Aiur.CheckError.indexOoB i) + | typ' => throw (Aiur.CheckError.notATuple typ') + | arr.get i => do + let arr' ← Aiur.inferNoEscape._unsafe_rec arr + let __do_lift ← Aiur.walkTyp arr'.typ + match __do_lift with + | typ.array n => if i ≥ n then throw (Aiur.CheckError.indexOoB i) else pure (Aiur.Typed.Term.get typ false arr' i) + | typ' => throw (Aiur.CheckError.notAnArray typ') + | arr.slice i j => + if j < i then throw (Aiur.CheckError.negativeRange i j) + else do + let arr' ← Aiur.inferNoEscape._unsafe_rec arr + let __do_lift ← Aiur.walkTyp arr'.typ + match __do_lift with + | typ.array n => + if j ≤ n then pure (Aiur.Typed.Term.slice (typ.array (j - i)) false arr' i j) + else throw (Aiur.CheckError.rangeOoB i j) + | typ' => throw (Aiur.CheckError.notAnArray typ') + | arr.set i val => do + let arr' ← Aiur.inferNoEscape._unsafe_rec arr + let __do_lift ← Aiur.walkTyp arr'.typ + match __do_lift with + | typ.array n => + if i ≥ n then throw (Aiur.CheckError.indexOoB i) + else do + let val' ← Aiur.checkNoEscape._unsafe_rec val typ + pure (Aiur.Typed.Term.set (typ.array n) false arr' i val') + | typ' => throw (Aiur.CheckError.notAnArray typ') + | term.store => do + let term' ← Aiur.inferNoEscape._unsafe_rec term + pure (Aiur.Typed.Term.store term'.typ.pointer false term') + | term.load => do + let term' ← Aiur.inferNoEscape._unsafe_rec term + let __do_lift ← Aiur.walkTyp term'.typ + match __do_lift with + | innerTyp.pointer => pure (Aiur.Typed.Term.load innerTyp false term') + | typ' => throw (Aiur.CheckError.notAPointer typ') + | term.ptrVal => do + let term' ← Aiur.inferNoEscape._unsafe_rec term + let __do_lift ← Aiur.walkTyp term'.typ + match __do_lift with + | a.pointer => pure (Aiur.Typed.Term.ptrVal Aiur.Typ.field false term') + | typ' => throw (Aiur.CheckError.notAPointer typ') + | a.eqZero => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + pure (Aiur.Typed.Term.eqZero Aiur.Typ.field false a') + | a.add b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.field + pure (Aiur.Typed.Term.add Aiur.Typ.field false a' b') + | a.sub b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.field + pure (Aiur.Typed.Term.sub Aiur.Typ.field false a' b') + | a.mul b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.field + pure (Aiur.Typed.Term.mul Aiur.Typ.field false a' b') + | a.u8ShiftLeft => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8ShiftLeft Aiur.Typ.u8 false a') + | a.u8ShiftRight => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8ShiftRight Aiur.Typ.u8 false a') + | a.u8BitDecomposition => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8BitDecomposition (Aiur.Typ.field.array 8) false a') + | a.u8Xor b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8Xor Aiur.Typ.u8 false a' b') + | a.u8And b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8And Aiur.Typ.u8 false a' b') + | a.u8Or b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8Or Aiur.Typ.u8 false a' b') + | a.u8Add b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8Add (Aiur.Typ.tuple #[Aiur.Typ.u8, Aiur.Typ.u8]) false a' b') + | a.u8Mul b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8Mul (Aiur.Typ.tuple #[Aiur.Typ.u8, Aiur.Typ.u8]) false a' b') + | a.u8XorSplit7 b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8XorSplit7 (Aiur.Typ.tuple #[Aiur.Typ.u8, Aiur.Typ.u8]) false a' b') + | a.u8XorSplit4 b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8XorSplit4 (Aiur.Typ.tuple #[Aiur.Typ.u8, Aiur.Typ.u8]) false a' b') + | a.u8Sub b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8Sub (Aiur.Typ.tuple #[Aiur.Typ.u8, Aiur.Typ.u8]) false a' b') + | a.u8LessThan b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.u8 + pure (Aiur.Typed.Term.u8LessThan Aiur.Typ.field false a' b') + | a.u32LessThan b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.field + pure (Aiur.Typed.Term.u32LessThan Aiur.Typ.field false a' b') + | a.unconstrainedU32Add b => + let word := Aiur.Typ.u8.array 4; + do + let a' ← Aiur.checkNoEscape._unsafe_rec a word + let b' ← Aiur.checkNoEscape._unsafe_rec b word + pure (Aiur.Typed.Term.unconstrainedU32Add (Aiur.Typ.tuple #[Aiur.Typ.field.array 4, Aiur.Typ.field]) false a' b') + | a.unconstrainedU32Add3 b c => + let word := Aiur.Typ.u8.array 4; + do + let a' ← Aiur.checkNoEscape._unsafe_rec a word + let b' ← Aiur.checkNoEscape._unsafe_rec b word + let c' ← Aiur.checkNoEscape._unsafe_rec c word + pure + (Aiur.Typed.Term.unconstrainedU32Add3 (Aiur.Typ.tuple #[Aiur.Typ.field.array 4, Aiur.Typ.field]) false a' b' c') + | a.u32ToField => do + let a' ← Aiur.checkNoEscape._unsafe_rec a (Aiur.Typ.u8.array 4) + pure (Aiur.Typed.Term.u32ToField Aiur.Typ.field false a') + | Aiur.Source.Term.u8Lit n => + have __do_jp := fun __r => pure (Aiur.Typed.Term.field Aiur.Typ.u8 false (Aiur.G.ofNat n)); + if n ≥ 256 then do + let __r ← throw (Aiur.CheckError.u8LitOutOfRange n) + __do_jp __r + else __do_jp () + | a.u8RangeCheck b => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + let b' ← Aiur.checkNoEscape._unsafe_rec b Aiur.Typ.field + pure (Aiur.Typed.Term.u8RangeCheck (Aiur.Typ.tuple #[Aiur.Typ.u8, Aiur.Typ.u8]) false a' b') + | a.unconstrainedBigUintDivMod b => do + let a' ← Aiur.inferNoEscape._unsafe_rec a + let b' ← Aiur.checkNoEscape._unsafe_rec b a'.typ + let __do_lift ← Aiur.zonkTyp a'.typ + let τ ← Aiur.bigUintDivModResultTyp __do_lift + pure (Aiur.Typed.Term.unconstrainedBigUintDivMod (Aiur.Typ.tuple #[τ, τ]) false a' b') + | a.unconstrainedGToBytes => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + pure (Aiur.Typed.Term.unconstrainedGToBytes (Aiur.Typ.field.array 8) false a') + | a.unconstrainedGInverse => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + pure (Aiur.Typed.Term.unconstrainedGInverse Aiur.Typ.field false a') + | a.toField => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.u8 + pure (Aiur.Typed.Term.toField Aiur.Typ.field false a') + | a.u8FromFieldUnsafe => do + let a' ← Aiur.checkNoEscape._unsafe_rec a Aiur.Typ.field + pure (Aiur.Typed.Term.u8FromFieldUnsafe Aiur.Typ.u8 false a') + | channel.ioGetInfo key => do + let channel' ← Aiur.checkNoEscape._unsafe_rec channel Aiur.Typ.field + let key' ← Aiur.inferNoEscape._unsafe_rec key + let __do_lift ← Aiur.walkTyp key'.typ + match __do_lift with + | a.array a_1 => + pure (Aiur.Typed.Term.ioGetInfo (Aiur.Typ.tuple #[Aiur.Typ.field, Aiur.Typ.field]) false channel' key') + | typ' => throw (Aiur.CheckError.notAnArray typ') + | channel.ioSetInfo key idx len ret => do + let channel' ← Aiur.checkNoEscape._unsafe_rec channel Aiur.Typ.field + let key' ← Aiur.inferNoEscape._unsafe_rec key + let __do_lift ← Aiur.walkTyp key'.typ + match __do_lift with + | keyEltTyp.array a => do + let __do_lift ← Aiur.unifyTyp keyEltTyp Aiur.Typ.field + have __do_jp : Unit → Aiur.CheckM Aiur.Typed.Term := fun __r => do + let idx' ← Aiur.checkNoEscape._unsafe_rec idx Aiur.Typ.field + let len' ← Aiur.checkNoEscape._unsafe_rec len Aiur.Typ.field + let ret' ← Aiur.inferTerm._unsafe_rec ret + pure (Aiur.Typed.Term.ioSetInfo ret'.typ ret'.escapes channel' key' idx' len' ret') + if __do_lift = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.typeMismatch Aiur.Typ.field keyEltTyp) + __do_jp __r + | typ' => throw (Aiur.CheckError.notAnArray typ') + | channel.ioRead idx len => + have __do_jp := fun __r => do + let channel' ← Aiur.checkNoEscape._unsafe_rec channel Aiur.Typ.field + let idx' ← Aiur.checkNoEscape._unsafe_rec idx Aiur.Typ.field + pure (Aiur.Typed.Term.ioRead (Aiur.Typ.field.array len) false channel' idx' len); + if len = 0 then do + let __r ← throw Aiur.CheckError.emptyArray + __do_jp __r + else __do_jp () + | channel.ioWrite data ret => do + let channel' ← Aiur.checkNoEscape._unsafe_rec channel Aiur.Typ.field + let data' ← Aiur.inferNoEscape._unsafe_rec data + let __do_lift ← Aiur.walkTyp data'.typ + match __do_lift with + | dataEltTyp.array a => do + let __do_lift ← Aiur.unifyTyp dataEltTyp Aiur.Typ.field + have __do_jp : Unit → Aiur.CheckM Aiur.Typed.Term := fun __r => do + let ret' ← Aiur.inferTerm._unsafe_rec ret + pure (Aiur.Typed.Term.ioWrite ret'.typ ret'.escapes channel' data' ret') + if __do_lift = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.typeMismatch Aiur.Typ.field dataEltTyp) + __do_jp __r + | typ' => throw (Aiur.CheckError.notAnArray typ') + | a.assertEq b msg ret => do + let a' ← Aiur.inferNoEscape._unsafe_rec a + let b' ← Aiur.checkNoEscape._unsafe_rec b a'.typ + let ret' ← Aiur.inferTerm._unsafe_rec ret + pure (Aiur.Typed.Term.assertEq ret'.typ ret'.escapes a' b' msg ret') + | Aiur.Source.Term.debug label term ret => + have __do_jp := fun term' => do + let ret' ← Aiur.inferTerm._unsafe_rec ret + pure (Aiur.Typed.Term.debug ret'.typ ret'.escapes label term' ret'); + match term with + | none => do + let term' ← pure none + __do_jp term' + | some sub => do + let __do_lift ← Aiur.inferTerm._unsafe_rec sub + let term' ← pure (some __do_lift) + __do_jp term' +RECURSION WORKER Aiur.lookupQueryBoundAux._unsafe_rec +List Nat → List Bool → List Nat → Nat → Option Nat +IMPLEMENTATION +fun x x_1 x_2 x_3 => + match x, x_1, x_2, x_3 with + | [], [], [], used => some used + | head :: slots, false :: active, degrees, used => Aiur.lookupQueryBoundAux._unsafe_rec slots active degrees used + | slots :: rest, true :: active, degree :: degrees, used => + if degree < 64 then + let next := used + 2 ^ degree * slots; + if next < Aiur.gSize.toNat then Aiur.lookupQueryBoundAux._unsafe_rec rest active degrees next else none + else none + | x, x_4, x_5, x_6 => none +RECURSION WORKER Aiur.lookupSlotSum._unsafe_rec +List Nat → List Bool → List Nat → Option Nat +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | [], [], [] => some 0 + | head :: slots, false :: active, degrees => Aiur.lookupSlotSum._unsafe_rec slots active degrees + | slots :: rest, true :: active, degree :: degrees => do + let tail ← Aiur.lookupSlotSum._unsafe_rec rest active degrees + pure (2 ^ degree * slots + tail) + | x, x_3, x_4 => none +RECURSION WORKER Aiur.mkLetFloating._unsafe_rec +Aiur.Typ → Bool → Aiur.Pattern → Aiur.Typed.Term → Aiur.Typed.Term → Aiur.Typed.Term +IMPLEMENTATION +fun τ e pat v b => + match v with + | Aiur.Typed.Term.let τ' e' pat' v' rest => + Aiur.Typed.Term.let τ' e' pat' v' (Aiur.mkLetFloating._unsafe_rec τ e pat rest b) + | x => Aiur.Typed.Term.let τ e pat v b +RECURSION WORKER Aiur.natToLimbsLE._unsafe_rec +Nat → List (Array Aiur.G) +IMPLEMENTATION +fun n => + if h : n = 0 then [] + else + let limb := n % 2 ^ 64; + let bytes := Array.ofFn fun i => Aiur.G.ofNat (limb >>> (8 * ↑i) % 256); + bytes :: Aiur.natToLimbsLE._unsafe_rec (n / 2 ^ 64) +RECURSION WORKER Aiur.occursInBound._unsafe_rec +Nat → Nat → Std.HashSet Nat → Aiur.Typ → Aiur.CheckM Bool +IMPLEMENTATION +fun x x_1 x_2 x_3 => + match x, x_1, x_2, x_3 with + | id, bound, visited, Aiur.Typ.mvar id' => + if (id == id') = true then pure true + else + if visited.contains id' = true then pure false + else + match bound with + | 0 => pure false + | bound.succ => do + let __do_lift ← get + match __do_lift.mvarSubst[id']? with + | some t => Aiur.occursInBound._unsafe_rec id bound (visited.insert id') t + | none => pure false + | id, bound, visited, Aiur.Typ.tuple ts => + Array.anyM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.occursInBound._unsafe_rec id bound visited t) + ts.attach + | id, bound, visited, t.array a => Aiur.occursInBound._unsafe_rec id bound visited t + | id, bound, visited, t.pointer => Aiur.occursInBound._unsafe_rec id bound visited t + | id, bound, visited, Aiur.Typ.function ins out => do + let __do_lift ← + List.anyM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.occursInBound._unsafe_rec id bound visited t) + ins.attach + if __do_lift = true then pure true else Aiur.occursInBound._unsafe_rec id bound visited out + | id, bound, visited, Aiur.Typ.app a args => + Array.anyM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.occursInBound._unsafe_rec id bound visited t) + args.attach + | x, x_4, x_5, x_6 => pure false +RECURSION WORKER Aiur.rewritePattern._unsafe_rec +Aiur.Typed.Decls → Aiur.MonoMap → Aiur.Typ → Aiur.Pattern → Aiur.Pattern +IMPLEMENTATION +fun decls mono expectedTyp x => + match x with + | Aiur.Pattern.ref g pats => + let tArgs := + match expectedTyp with + | Aiur.Typ.app a args => args + | x => #[]; + let g' := Aiur.rewriteGlobal decls mono g tArgs; + let pats' := + List.map + (fun x => + match x with + | ⟨p, property⟩ => Aiur.rewritePattern._unsafe_rec decls mono Aiur.Typ.unit p) + pats.attach; + Aiur.Pattern.ref g' pats' + | Aiur.Pattern.tuple pats => + Aiur.Pattern.tuple + (Array.map + (fun x => + match x with + | ⟨p, property⟩ => Aiur.rewritePattern._unsafe_rec decls mono Aiur.Typ.unit p) + pats.attach) + | Aiur.Pattern.array pats => + let innerTyp := + match expectedTyp with + | t.array a => t + | x => Aiur.Typ.unit; + Aiur.Pattern.array + (Array.map + (fun x => + match x with + | ⟨p, property⟩ => Aiur.rewritePattern._unsafe_rec decls mono innerTyp p) + pats.attach) + | a.or b => + (Aiur.rewritePattern._unsafe_rec decls mono expectedTyp a).or + (Aiur.rewritePattern._unsafe_rec decls mono expectedTyp b) + | p.pointer => + match expectedTyp with + | inner.pointer => (Aiur.rewritePattern._unsafe_rec decls mono inner p).pointer + | x => p.pointer + | p => p +RECURSION WORKER Aiur.rewriteTyp._unsafe_rec +(Aiur.Global → Option Aiur.Typ) → Aiur.MonoMap → Aiur.Typ → Aiur.Typ +IMPLEMENTATION +fun subst mono x => + match x with + | Aiur.Typ.ref g => (subst g).getD (Aiur.Typ.ref g) + | Aiur.Typ.app g args => + match mono[(g, args)]? with + | some concName => Aiur.Typ.ref concName + | none => + Aiur.Typ.app g + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.rewriteTyp._unsafe_rec subst mono t) + args.attach) + | Aiur.Typ.tuple ts => + Aiur.Typ.tuple + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.rewriteTyp._unsafe_rec subst mono t) + ts.attach) + | t.array n => (Aiur.rewriteTyp._unsafe_rec subst mono t).array n + | t.pointer => (Aiur.rewriteTyp._unsafe_rec subst mono t).pointer + | Aiur.Typ.function ins out => + Aiur.Typ.function + (List.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.rewriteTyp._unsafe_rec subst mono t) + ins.attach) + (Aiur.rewriteTyp._unsafe_rec subst mono out) + | t => t +RECURSION WORKER Aiur.rewriteTypedTerm._unsafe_rec +Aiur.Typed.Decls → (Aiur.Global → Option Aiur.Typ) → Aiur.MonoMap → Aiur.Typed.Term → Aiur.Typed.Term +IMPLEMENTATION +fun decls subst mono x => + match x with + | Aiur.Typed.Term.unit τ e => Aiur.Typed.Term.unit (Aiur.rewriteTyp subst mono τ) e + | Aiur.Typed.Term.var τ e x => Aiur.Typed.Term.var (Aiur.rewriteTyp subst mono τ) e x + | Aiur.Typed.Term.ref τ e g tArgs => + let g' := Aiur.rewriteGlobal decls mono g tArgs; + Aiur.Typed.Term.ref (Aiur.rewriteTyp subst mono τ) e g' (Array.map (Aiur.rewriteTyp subst mono) tArgs) + | Aiur.Typed.Term.field τ e v => Aiur.Typed.Term.field (Aiur.rewriteTyp subst mono τ) e v + | Aiur.Typed.Term.tuple τ e ts => + Aiur.Typed.Term.tuple (Aiur.rewriteTyp subst mono τ) e + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.rewriteTypedTerm._unsafe_rec decls subst mono t) + ts.attach) + | Aiur.Typed.Term.array τ e ts => + Aiur.Typed.Term.array (Aiur.rewriteTyp subst mono τ) e + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.rewriteTypedTerm._unsafe_rec decls subst mono t) + ts.attach) + | Aiur.Typed.Term.ret τ e r => + Aiur.Typed.Term.ret (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono r) + | Aiur.Typed.Term.let τ e p v b => + let vTyp := v.typ; + Aiur.Typed.Term.let (Aiur.rewriteTyp subst mono τ) e (Aiur.rewritePattern decls mono vTyp p) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono v) (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.match τ e scrut bs => + let scrutTyp := scrut.typ; + Aiur.Typed.Term.match (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono scrut) + (List.map + (fun x => + match x with + | ⟨(p, b), property⟩ => + (Aiur.rewritePattern decls mono scrutTyp p, Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b)) + bs.attach) + | Aiur.Typed.Term.app τ e g tArgs args u => + let g' := Aiur.rewriteGlobal decls mono g tArgs; + Aiur.Typed.Term.app (Aiur.rewriteTyp subst mono τ) e g' #[] + (List.map + (fun x => + match x with + | ⟨a, property⟩ => Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + args.attach) + u + | Aiur.Typed.Term.add τ e a b => + Aiur.Typed.Term.add (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.sub τ e a b => + Aiur.Typed.Term.sub (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.mul τ e a b => + Aiur.Typed.Term.mul (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.eqZero τ e a => + Aiur.Typed.Term.eqZero (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.proj τ e a n => + Aiur.Typed.Term.proj (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) n + | Aiur.Typed.Term.get τ e a n => + Aiur.Typed.Term.get (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) n + | Aiur.Typed.Term.slice τ e a i j => + Aiur.Typed.Term.slice (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) i j + | Aiur.Typed.Term.set τ e a n v => + Aiur.Typed.Term.set (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) n + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono v) + | Aiur.Typed.Term.store τ e a => + Aiur.Typed.Term.store (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.load τ e a => + Aiur.Typed.Term.load (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.ptrVal τ e a => + Aiur.Typed.Term.ptrVal (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.assertEq τ e a b msg r => + Aiur.Typed.Term.assertEq (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) msg (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono r) + | Aiur.Typed.Term.ioGetInfo τ e c k => + Aiur.Typed.Term.ioGetInfo (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono c) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono k) + | Aiur.Typed.Term.ioSetInfo τ e c k i l r => + Aiur.Typed.Term.ioSetInfo (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono c) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono k) (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono i) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono l) (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono r) + | Aiur.Typed.Term.ioRead τ e c i n => + Aiur.Typed.Term.ioRead (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono c) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono i) n + | Aiur.Typed.Term.ioWrite τ e c d r => + Aiur.Typed.Term.ioWrite (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono c) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono d) (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono r) + | Aiur.Typed.Term.u8BitDecomposition τ e a => + Aiur.Typed.Term.u8BitDecomposition (Aiur.rewriteTyp subst mono τ) e + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.u8ShiftLeft τ e a => + Aiur.Typed.Term.u8ShiftLeft (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.u8ShiftRight τ e a => + Aiur.Typed.Term.u8ShiftRight (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.u8Xor τ e a b => + Aiur.Typed.Term.u8Xor (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8Add τ e a b => + Aiur.Typed.Term.u8Add (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8Mul τ e a b => + Aiur.Typed.Term.u8Mul (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8XorSplit7 τ e a b => + Aiur.Typed.Term.u8XorSplit7 (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8XorSplit4 τ e a b => + Aiur.Typed.Term.u8XorSplit4 (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8Sub τ e a b => + Aiur.Typed.Term.u8Sub (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8And τ e a b => + Aiur.Typed.Term.u8And (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8Or τ e a b => + Aiur.Typed.Term.u8Or (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u8LessThan τ e a b => + Aiur.Typed.Term.u8LessThan (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.u32LessThan τ e a b => + Aiur.Typed.Term.u32LessThan (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.unconstrainedU32Add τ e a b => + Aiur.Typed.Term.unconstrainedU32Add (Aiur.rewriteTyp subst mono τ) e + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.unconstrainedU32Add3 τ e a b c => + Aiur.Typed.Term.unconstrainedU32Add3 (Aiur.rewriteTyp subst mono τ) e + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono c) + | Aiur.Typed.Term.u32ToField τ e a => + Aiur.Typed.Term.u32ToField (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.u8RangeCheck τ e a b => + Aiur.Typed.Term.u8RangeCheck (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.unconstrainedBigUintDivMod τ e a b => + Aiur.Typed.Term.unconstrainedBigUintDivMod (Aiur.rewriteTyp subst mono τ) e + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono b) + | Aiur.Typed.Term.unconstrainedGToBytes τ e a => + Aiur.Typed.Term.unconstrainedGToBytes (Aiur.rewriteTyp subst mono τ) e + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.unconstrainedGInverse τ e a => + Aiur.Typed.Term.unconstrainedGInverse (Aiur.rewriteTyp subst mono τ) e + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.toField τ e a => + Aiur.Typed.Term.toField (Aiur.rewriteTyp subst mono τ) e (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.u8FromFieldUnsafe τ e a => + Aiur.Typed.Term.u8FromFieldUnsafe (Aiur.rewriteTyp subst mono τ) e + (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono a) + | Aiur.Typed.Term.debug τ e l t r => + let t' := + match t with + | none => none + | some sub => some (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono sub); + Aiur.Typed.Term.debug (Aiur.rewriteTyp subst mono τ) e l t' (Aiur.rewriteTypedTerm._unsafe_rec decls subst mono r) +RECURSION WORKER Aiur.simplifyTypedTerm._unsafe_rec +Aiur.Source.Decls → Aiur.Typed.Term → Except Aiur.CheckError Aiur.Typed.Term +IMPLEMENTATION +fun decls x => + match x with + | Aiur.Typed.Term.let τ e (Aiur.Pattern.var x) v b => do + let v' ← Aiur.simplifyTypedTerm._unsafe_rec decls v + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.mkLetFloating τ e (Aiur.Pattern.var x) v' b') + | Aiur.Typed.Term.let τ e Aiur.Pattern.wildcard v b => do + let v' ← Aiur.simplifyTypedTerm._unsafe_rec decls v + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.mkLetFloating τ e Aiur.Pattern.wildcard v' b') + | Aiur.Typed.Term.let τ e pat v b => do + let v' ← Aiur.simplifyTypedTerm._unsafe_rec decls v + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + let tmp : Aiur.Typed.Term := Aiur.Typed.Term.var v'.typ false Aiur.tmpVar + match Aiur.MatchCompiler.runMatchCompiler decls tmp [(pat, b')] with + | (tree, _diag) => + let body := + match Aiur.MatchCompiler.decisionToTyped b'.typ tmp.typ tree with + | some rewrite => rewrite + | none => Aiur.Typed.Term.match b'.typ b'.escapes tmp [(pat, b')]; + pure (Aiur.mkLetFloating τ e (Aiur.Pattern.var Aiur.tmpVar) v' body) + | Aiur.Typed.Term.match τ e scrut branches => do + let scrut' ← Aiur.simplifyTypedTerm._unsafe_rec decls scrut + let branches' ← + List.mapM (fun pb => Except.map (Prod.mk pb.val.fst) (Aiur.simplifyTypedTerm._unsafe_rec decls pb.val.snd)) + branches.attach + match Aiur.MatchCompiler.runMatchCompiler decls scrut' branches' with + | (tree, _diag) => + match Aiur.MatchCompiler.decisionToTyped τ scrut'.typ tree with + | some rewrite => pure rewrite + | none => + match scrut' with + | Aiur.Typed.Term.var typ escapes l => pure (Aiur.Typed.Term.match τ e scrut' branches') + | x => + let tmp := Aiur.Typed.Term.var scrut'.typ false Aiur.tmpVar; + let inner := Aiur.Typed.Term.match τ e tmp branches'; + pure (Aiur.Typed.Term.let τ e (Aiur.Pattern.var Aiur.tmpVar) scrut' inner) + | Aiur.Typed.Term.ret τ e r => do + let r' ← Aiur.simplifyTypedTerm._unsafe_rec decls r + pure (Aiur.Typed.Term.ret τ e r') + | Aiur.Typed.Term.app τ e g tArgs args u => do + let args' ← + List.mapM + (fun x => + match x with + | ⟨a, property⟩ => Aiur.simplifyTypedTerm._unsafe_rec decls a) + args.attach + pure (Aiur.Typed.Term.app τ e g tArgs args' u) + | Aiur.Typed.Term.tuple τ e ts => do + let ts' ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.simplifyTypedTerm._unsafe_rec decls t) + ts.attach + pure (Aiur.Typed.Term.tuple τ e ts') + | Aiur.Typed.Term.array τ e ts => do + let ts' ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.simplifyTypedTerm._unsafe_rec decls t) + ts.attach + pure (Aiur.Typed.Term.array τ e ts') + | Aiur.Typed.Term.debug τ e l t r => + have __do_jp := fun t' => do + let r' ← Aiur.simplifyTypedTerm._unsafe_rec decls r + pure (Aiur.Typed.Term.debug τ e l t' r'); + match t with + | none => do + let t' ← pure none + __do_jp t' + | some sub => do + let __do_lift ← Aiur.simplifyTypedTerm._unsafe_rec decls sub + let t' ← pure (some __do_lift) + __do_jp t' + | Aiur.Typed.Term.assertEq τ e a b msg r => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + let r' ← Aiur.simplifyTypedTerm._unsafe_rec decls r + pure (Aiur.Typed.Term.assertEq τ e a' b' msg r') + | Aiur.Typed.Term.ioSetInfo τ e c k i l r => do + let c' ← Aiur.simplifyTypedTerm._unsafe_rec decls c + let k' ← Aiur.simplifyTypedTerm._unsafe_rec decls k + let i' ← Aiur.simplifyTypedTerm._unsafe_rec decls i + let l' ← Aiur.simplifyTypedTerm._unsafe_rec decls l + let r' ← Aiur.simplifyTypedTerm._unsafe_rec decls r + pure (Aiur.Typed.Term.ioSetInfo τ e c' k' i' l' r') + | Aiur.Typed.Term.ioWrite τ e c d r => do + let c' ← Aiur.simplifyTypedTerm._unsafe_rec decls c + let d' ← Aiur.simplifyTypedTerm._unsafe_rec decls d + let r' ← Aiur.simplifyTypedTerm._unsafe_rec decls r + pure (Aiur.Typed.Term.ioWrite τ e c' d' r') + | Aiur.Typed.Term.u8LessThan τ e a b => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.Typed.Term.u8LessThan τ e a' b') + | Aiur.Typed.Term.u8XorSplit7 τ e a b => do + let __do_lift ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let __do_lift_1 ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.Typed.Term.u8XorSplit7 τ e __do_lift __do_lift_1) + | Aiur.Typed.Term.u8XorSplit4 τ e a b => do + let __do_lift ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let __do_lift_1 ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.Typed.Term.u8XorSplit4 τ e __do_lift __do_lift_1) + | Aiur.Typed.Term.u32LessThan τ e a b => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.Typed.Term.u32LessThan τ e a' b') + | Aiur.Typed.Term.u8RangeCheck τ e a b => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.Typed.Term.u8RangeCheck τ e a' b') + | Aiur.Typed.Term.unconstrainedBigUintDivMod τ e a b => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let b' ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.Typed.Term.unconstrainedBigUintDivMod τ e a' b') + | Aiur.Typed.Term.unconstrainedGToBytes τ e a => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + pure (Aiur.Typed.Term.unconstrainedGToBytes τ e a') + | Aiur.Typed.Term.unconstrainedU32Add τ e a b => do + let __do_lift ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let __do_lift_1 ← Aiur.simplifyTypedTerm._unsafe_rec decls b + pure (Aiur.Typed.Term.unconstrainedU32Add τ e __do_lift __do_lift_1) + | Aiur.Typed.Term.unconstrainedU32Add3 τ e a b c => do + let __do_lift ← Aiur.simplifyTypedTerm._unsafe_rec decls a + let __do_lift_1 ← Aiur.simplifyTypedTerm._unsafe_rec decls b + let __do_lift_2 ← Aiur.simplifyTypedTerm._unsafe_rec decls c + pure (Aiur.Typed.Term.unconstrainedU32Add3 τ e __do_lift __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u32ToField τ e a => do + let __do_lift ← Aiur.simplifyTypedTerm._unsafe_rec decls a + pure (Aiur.Typed.Term.u32ToField τ e __do_lift) + | Aiur.Typed.Term.unconstrainedGInverse τ e a => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + pure (Aiur.Typed.Term.unconstrainedGInverse τ e a') + | Aiur.Typed.Term.toField τ e a => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + pure (Aiur.Typed.Term.toField τ e a') + | Aiur.Typed.Term.u8FromFieldUnsafe τ e a => do + let a' ← Aiur.simplifyTypedTerm._unsafe_rec decls a + pure (Aiur.Typed.Term.u8FromFieldUnsafe τ e a') + | t => pure t +RECURSION WORKER Aiur.substInTypedTerm._unsafe_rec +(Aiur.Global → Option Aiur.Typ) → Aiur.Typed.Term → Aiur.Typed.Term +IMPLEMENTATION +fun subst x => + match x with + | Aiur.Typed.Term.unit τ e => Aiur.Typed.Term.unit (Aiur.Typ.instantiate subst τ) e + | Aiur.Typed.Term.var τ e x => Aiur.Typed.Term.var (Aiur.Typ.instantiate subst τ) e x + | Aiur.Typed.Term.ref τ e g tArgs => + Aiur.Typed.Term.ref (Aiur.Typ.instantiate subst τ) e g (Array.map (Aiur.Typ.instantiate subst) tArgs) + | Aiur.Typed.Term.field τ e v => Aiur.Typed.Term.field (Aiur.Typ.instantiate subst τ) e v + | Aiur.Typed.Term.tuple τ e ts => + Aiur.Typed.Term.tuple (Aiur.Typ.instantiate subst τ) e + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.substInTypedTerm._unsafe_rec subst t) + ts.attach) + | Aiur.Typed.Term.array τ e ts => + Aiur.Typed.Term.array (Aiur.Typ.instantiate subst τ) e + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.substInTypedTerm._unsafe_rec subst t) + ts.attach) + | Aiur.Typed.Term.ret τ e r => + Aiur.Typed.Term.ret (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst r) + | Aiur.Typed.Term.let τ e p v b => + Aiur.Typed.Term.let (Aiur.Typ.instantiate subst τ) e p (Aiur.substInTypedTerm._unsafe_rec subst v) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.match τ e scrut bs => + Aiur.Typed.Term.match (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst scrut) + (List.map + (fun x => + match x with + | ⟨(p, b), property⟩ => (p, Aiur.substInTypedTerm._unsafe_rec subst b)) + bs.attach) + | Aiur.Typed.Term.app τ e g tArgs args u => + Aiur.Typed.Term.app (Aiur.Typ.instantiate subst τ) e g (Array.map (Aiur.Typ.instantiate subst) tArgs) + (List.map + (fun x => + match x with + | ⟨a, property⟩ => Aiur.substInTypedTerm._unsafe_rec subst a) + args.attach) + u + | Aiur.Typed.Term.add τ e a b => + Aiur.Typed.Term.add (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.sub τ e a b => + Aiur.Typed.Term.sub (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.mul τ e a b => + Aiur.Typed.Term.mul (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.eqZero τ e a => + Aiur.Typed.Term.eqZero (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.proj τ e a n => + Aiur.Typed.Term.proj (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) n + | Aiur.Typed.Term.get τ e a n => + Aiur.Typed.Term.get (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) n + | Aiur.Typed.Term.slice τ e a i j => + Aiur.Typed.Term.slice (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) i j + | Aiur.Typed.Term.set τ e a n v => + Aiur.Typed.Term.set (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) n + (Aiur.substInTypedTerm._unsafe_rec subst v) + | Aiur.Typed.Term.store τ e a => + Aiur.Typed.Term.store (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.load τ e a => + Aiur.Typed.Term.load (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.ptrVal τ e a => + Aiur.Typed.Term.ptrVal (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.assertEq τ e a b msg r => + Aiur.Typed.Term.assertEq (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) msg (Aiur.substInTypedTerm._unsafe_rec subst r) + | Aiur.Typed.Term.ioGetInfo τ e c k => + Aiur.Typed.Term.ioGetInfo (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst c) + (Aiur.substInTypedTerm._unsafe_rec subst k) + | Aiur.Typed.Term.ioSetInfo τ e c k i l r => + Aiur.Typed.Term.ioSetInfo (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst c) + (Aiur.substInTypedTerm._unsafe_rec subst k) (Aiur.substInTypedTerm._unsafe_rec subst i) + (Aiur.substInTypedTerm._unsafe_rec subst l) (Aiur.substInTypedTerm._unsafe_rec subst r) + | Aiur.Typed.Term.ioRead τ e c i n => + Aiur.Typed.Term.ioRead (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst c) + (Aiur.substInTypedTerm._unsafe_rec subst i) n + | Aiur.Typed.Term.ioWrite τ e c d r => + Aiur.Typed.Term.ioWrite (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst c) + (Aiur.substInTypedTerm._unsafe_rec subst d) (Aiur.substInTypedTerm._unsafe_rec subst r) + | Aiur.Typed.Term.u8BitDecomposition τ e a => + Aiur.Typed.Term.u8BitDecomposition (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.u8ShiftLeft τ e a => + Aiur.Typed.Term.u8ShiftLeft (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.u8ShiftRight τ e a => + Aiur.Typed.Term.u8ShiftRight (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.u8Xor τ e a b => + Aiur.Typed.Term.u8Xor (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8Add τ e a b => + Aiur.Typed.Term.u8Add (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8Mul τ e a b => + Aiur.Typed.Term.u8Mul (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8XorSplit7 τ e a b => + Aiur.Typed.Term.u8XorSplit7 (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8XorSplit4 τ e a b => + Aiur.Typed.Term.u8XorSplit4 (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8Sub τ e a b => + Aiur.Typed.Term.u8Sub (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8And τ e a b => + Aiur.Typed.Term.u8And (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8Or τ e a b => + Aiur.Typed.Term.u8Or (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u8LessThan τ e a b => + Aiur.Typed.Term.u8LessThan (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.u32LessThan τ e a b => + Aiur.Typed.Term.u32LessThan (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.unconstrainedU32Add τ e a b => + Aiur.Typed.Term.unconstrainedU32Add (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.unconstrainedU32Add3 τ e a b c => + Aiur.Typed.Term.unconstrainedU32Add3 (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) (Aiur.substInTypedTerm._unsafe_rec subst c) + | Aiur.Typed.Term.u32ToField τ e a => + Aiur.Typed.Term.u32ToField (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.u8RangeCheck τ e a b => + Aiur.Typed.Term.u8RangeCheck (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.unconstrainedBigUintDivMod τ e a b => + Aiur.Typed.Term.unconstrainedBigUintDivMod (Aiur.Typ.instantiate subst τ) e + (Aiur.substInTypedTerm._unsafe_rec subst a) (Aiur.substInTypedTerm._unsafe_rec subst b) + | Aiur.Typed.Term.unconstrainedGToBytes τ e a => + Aiur.Typed.Term.unconstrainedGToBytes (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.unconstrainedGInverse τ e a => + Aiur.Typed.Term.unconstrainedGInverse (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.toField τ e a => + Aiur.Typed.Term.toField (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.u8FromFieldUnsafe τ e a => + Aiur.Typed.Term.u8FromFieldUnsafe (Aiur.Typ.instantiate subst τ) e (Aiur.substInTypedTerm._unsafe_rec subst a) + | Aiur.Typed.Term.debug τ e l t r => + let t' := + match t with + | none => none + | some sub => some (Aiur.substInTypedTerm._unsafe_rec subst sub); + Aiur.Typed.Term.debug (Aiur.Typ.instantiate subst τ) e l t' (Aiur.substInTypedTerm._unsafe_rec subst r) +RECURSION WORKER Aiur.termToConcrete._unsafe_rec +Std.HashMap (Aiur.Global × Array Aiur.Typ) Aiur.Global → + Aiur.Typed.Term → Except Aiur.ConcretizeError Aiur.Concrete.Term +IMPLEMENTATION +fun mono x => + match x with + | Aiur.Typed.Term.unit τ e => do + let __do_lift ← Aiur.typToConcrete mono τ + pure (Aiur.Concrete.Term.unit __do_lift e) + | Aiur.Typed.Term.var τ e x => do + let __do_lift ← Aiur.typToConcrete mono τ + pure (Aiur.Concrete.Term.var __do_lift e x) + | Aiur.Typed.Term.ref τ e g _tArgs => do + let __do_lift ← Aiur.typToConcrete mono τ + pure (Aiur.Concrete.Term.ref __do_lift e g) + | Aiur.Typed.Term.field τ e g => do + let __do_lift ← Aiur.typToConcrete mono τ + pure (Aiur.Concrete.Term.field __do_lift e g) + | Aiur.Typed.Term.tuple τ e ts => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Array.mapM (Aiur.termToConcrete._unsafe_rec mono) ts + pure (Aiur.Concrete.Term.tuple __do_lift e __do_lift_1) + | Aiur.Typed.Term.array τ e ts => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Array.mapM (Aiur.termToConcrete._unsafe_rec mono) ts + pure (Aiur.Concrete.Term.array __do_lift e __do_lift_1) + | Aiur.Typed.Term.ret τ e r => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono r + pure (Aiur.Concrete.Term.ret __do_lift e __do_lift_1) + | Aiur.Typed.Term.let τ e pat v b => do + let τ' ← Aiur.typToConcrete mono τ + let v' ← Aiur.termToConcrete._unsafe_rec mono v + let b' ← Aiur.termToConcrete._unsafe_rec mono b + match pat with + | Aiur.Pattern.var x => pure (Aiur.Concrete.Term.letVar τ' e x v' b') + | x => pure (Aiur.Concrete.Term.letWild τ' e v' b') + | Aiur.Typed.Term.match τ e scrut bs => do + let τ' ← Aiur.typToConcrete mono τ + let scrut' ← Aiur.termToConcrete._unsafe_rec mono scrut + match scrut' with + | Aiur.Concrete.Term.var scrutTyp escapes scrutLocal => + let scrutTerm := Aiur.Concrete.Term.var scrutTyp false scrutLocal; + have __do_jp := fun __r => + have __do_jp := fun __r => do + let cases ← + Array.foldlM + (fun acc x => + match x with + | ⟨(p, b), property⟩ => do + let cb ← Aiur.termToConcrete._unsafe_rec mono b + let __do_lift ← Aiur.expandPattern scrutTyp scrutLocal p cb + pure (acc ++ __do_lift)) + #[] bs.toArray.attach + pure (Aiur.Concrete.Term.match τ' e scrutLocal cases none); + match bs with + | [(Aiur.Pattern.array pats, body)] => + match scrutTyp with + | eltTyp.array a => do + let cb ← Aiur.termToConcrete._unsafe_rec mono body + pure (Aiur.destructureArray scrutTerm pats eltTyp cb) + | x => __do_jp () + | x => __do_jp (); + match bs with + | [(Aiur.Pattern.tuple pats, body)] => + match scrutTyp with + | Aiur.Concrete.Typ.tuple ts => do + let cb ← Aiur.termToConcrete._unsafe_rec mono body + pure (Aiur.destructureTuple scrutTerm pats ts cb) + | x => __do_jp () + | x => __do_jp () + | x => throw Aiur.ConcretizeError.unsupportedMatchScrutinee + | Aiur.Typed.Term.app τ e g _tArgs args u => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← List.mapM (Aiur.termToConcrete._unsafe_rec mono) args + pure (Aiur.Concrete.Term.app __do_lift e g __do_lift_1 u) + | Aiur.Typed.Term.add τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.add __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.sub τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.sub __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.mul τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.mul __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.eqZero τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.eqZero __do_lift e __do_lift_1) + | Aiur.Typed.Term.proj τ e a n => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.proj __do_lift e __do_lift_1 n) + | Aiur.Typed.Term.get τ e a n => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.get __do_lift e __do_lift_1 n) + | Aiur.Typed.Term.slice τ e a i j => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.slice __do_lift e __do_lift_1 i j) + | Aiur.Typed.Term.set τ e a n v => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono v + pure (Aiur.Concrete.Term.set __do_lift e __do_lift_1 n __do_lift_2) + | Aiur.Typed.Term.store τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.store __do_lift e __do_lift_1) + | Aiur.Typed.Term.load τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.load __do_lift e __do_lift_1) + | Aiur.Typed.Term.ptrVal τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.ptrVal __do_lift e __do_lift_1) + | Aiur.Typed.Term.assertEq τ e a b msg r => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + let __do_lift_3 ← Aiur.termToConcrete._unsafe_rec mono r + pure (Aiur.Concrete.Term.assertEq __do_lift e __do_lift_1 __do_lift_2 msg __do_lift_3) + | Aiur.Typed.Term.ioGetInfo τ e c k => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono c + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono k + pure (Aiur.Concrete.Term.ioGetInfo __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.ioSetInfo τ e c k i l r => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono c + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono k + let __do_lift_3 ← Aiur.termToConcrete._unsafe_rec mono i + let __do_lift_4 ← Aiur.termToConcrete._unsafe_rec mono l + let __do_lift_5 ← Aiur.termToConcrete._unsafe_rec mono r + pure (Aiur.Concrete.Term.ioSetInfo __do_lift e __do_lift_1 __do_lift_2 __do_lift_3 __do_lift_4 __do_lift_5) + | Aiur.Typed.Term.ioRead τ e c i n => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono c + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono i + pure (Aiur.Concrete.Term.ioRead __do_lift e __do_lift_1 __do_lift_2 n) + | Aiur.Typed.Term.ioWrite τ e c d r => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono c + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono d + let __do_lift_3 ← Aiur.termToConcrete._unsafe_rec mono r + pure (Aiur.Concrete.Term.ioWrite __do_lift e __do_lift_1 __do_lift_2 __do_lift_3) + | Aiur.Typed.Term.u8BitDecomposition τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.u8BitDecomposition __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8ShiftLeft τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.u8ShiftLeft __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8ShiftRight τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.u8ShiftRight __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8Xor τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8Xor __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Add τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8Add __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Mul τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8Mul __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8XorSplit7 τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8XorSplit7 __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8XorSplit4 τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8XorSplit4 __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Sub τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8Sub __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8And τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8And __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Or τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8Or __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8LessThan τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8LessThan __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u32LessThan τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u32LessThan __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.unconstrainedU32Add τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.unconstrainedU32Add __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.unconstrainedU32Add3 τ e a b c => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + let __do_lift_3 ← Aiur.termToConcrete._unsafe_rec mono c + pure (Aiur.Concrete.Term.unconstrainedU32Add3 __do_lift e __do_lift_1 __do_lift_2 __do_lift_3) + | Aiur.Typed.Term.u32ToField τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.u32ToField __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8RangeCheck τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.u8RangeCheck __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.unconstrainedBigUintDivMod τ e a b => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + let __do_lift_2 ← Aiur.termToConcrete._unsafe_rec mono b + pure (Aiur.Concrete.Term.unconstrainedBigUintDivMod __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.unconstrainedGToBytes τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.unconstrainedGToBytes __do_lift e __do_lift_1) + | Aiur.Typed.Term.unconstrainedGInverse τ e a => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono a + pure (Aiur.Concrete.Term.unconstrainedGInverse __do_lift e __do_lift_1) + | Aiur.Typed.Term.toField typ escapes a => Aiur.termToConcrete._unsafe_rec mono a + | Aiur.Typed.Term.u8FromFieldUnsafe typ escapes a => Aiur.termToConcrete._unsafe_rec mono a + | Aiur.Typed.Term.debug τ e l t r => + have __do_jp := fun t' => do + let __do_lift ← Aiur.typToConcrete mono τ + let __do_lift_1 ← Aiur.termToConcrete._unsafe_rec mono r + pure (Aiur.Concrete.Term.debug __do_lift e l t' __do_lift_1); + match t with + | none => do + let t' ← pure none + __do_jp t' + | some sub => do + let __do_lift ← Aiur.termToConcrete._unsafe_rec mono sub + let t' ← pure (some __do_lift) + __do_jp t' +RECURSION WORKER Aiur.toIndex._unsafe_rec +Aiur.LayoutMap → + Std.HashMap Aiur.Local (Array Aiur.Bytecode.ValIdx) → Aiur.Concrete.Term → Aiur.CompileM (Array Aiur.Bytecode.ValIdx) +IMPLEMENTATION +fun layoutMap bindings term => + match term with + | Aiur.Concrete.Term.unit typ escapes => pure #[] + | Aiur.Concrete.Term.ret typ escapes sub => throw "ret in value position (should not happen after typechecking)" + | Aiur.Concrete.Term.match typ escapes scrut cases defaultOpt => + throw "Non-tail match in arbitrary position (not supported)" + | Aiur.Concrete.Term.letLoad typ escapes dst dstTyp src bod => + have __do_jp := fun size => + let ptrIdxs := bindings[src]?.getD #[0]; + do + let loaded ← Aiur.pushOp (Aiur.Bytecode.Op.load size ptrIdxs[0]!) size + Aiur.toIndex._unsafe_rec layoutMap (bindings.insert dst loaded) bod; + match Aiur.typSize layoutMap dstTyp with + | Except.error e => do + let size ← throw e + __do_jp size + | Except.ok n => do + let size ← pure n + __do_jp size + | Aiur.Concrete.Term.var typ escapes name => pure (bindings[name]?.getD #[]) + | Aiur.Concrete.Term.ref typ escapes name => + match layoutMap[name]? with + | some (Aiur.Layout.function layout) => Aiur.pushOp (Aiur.Bytecode.Op.const (Aiur.G.ofNat layout.index)) + | some (Aiur.Layout.constructor layout) => + let size := layout.size; + if layout.tagless = true then + if (size == 0) = true then pure #[] + else do + let __do_lift ← Aiur.pushOp (Aiur.Bytecode.Op.const (Aiur.G.ofNat 0)) + let padding : Aiur.Bytecode.ValIdx := __do_lift[0]! + pure (Array.replicate size padding) + else + let paddingOp := Aiur.Bytecode.Op.const (Aiur.G.ofNat layout.index); + do + let index ← Aiur.pushOp paddingOp + if index.size < size then do + let __do_lift ← Aiur.pushOp paddingOp + let padding : Aiur.Bytecode.ValIdx := __do_lift[0]! + pure (index ++ Array.replicate (size - index.size) padding) + else pure index + | x => throw (toString "ref: layout missing for `" ++ toString name ++ toString "`") + | Aiur.Concrete.Term.field typ escapes g => Aiur.pushOp (Aiur.Bytecode.Op.const g) + | Aiur.Concrete.Term.tuple typ escapes terms => + Array.foldlM + (fun acc arg => do + let __do_lift ← Aiur.toIndex._unsafe_rec layoutMap bindings arg + pure (acc ++ __do_lift)) + #[] terms + | Aiur.Concrete.Term.array typ escapes terms => + Array.foldlM + (fun acc arg => do + let __do_lift ← Aiur.toIndex._unsafe_rec layoutMap bindings arg + pure (acc ++ __do_lift)) + #[] terms + | Aiur.Concrete.Term.letVar typ escapes var val bod => do + let val ← Aiur.toIndex._unsafe_rec layoutMap bindings val + Aiur.toIndex._unsafe_rec layoutMap (bindings.insert var val) bod + | Aiur.Concrete.Term.letWild typ escapes val bod => do + let _ ← Aiur.toIndex._unsafe_rec layoutMap bindings val + Aiur.toIndex._unsafe_rec layoutMap bindings bod + | Aiur.Concrete.Term.add typ escapes a b => do + let a ← Aiur.expectIdx._unsafe_rec layoutMap bindings a + let b ← Aiur.expectIdx._unsafe_rec layoutMap bindings b + Aiur.pushOp (Aiur.Bytecode.Op.add a b) + | Aiur.Concrete.Term.sub typ escapes a b => do + let a ← Aiur.expectIdx._unsafe_rec layoutMap bindings a + let b ← Aiur.expectIdx._unsafe_rec layoutMap bindings b + Aiur.pushOp (Aiur.Bytecode.Op.sub a b) + | Aiur.Concrete.Term.mul typ escapes a b => do + let a ← Aiur.expectIdx._unsafe_rec layoutMap bindings a + let b ← Aiur.expectIdx._unsafe_rec layoutMap bindings b + Aiur.pushOp (Aiur.Bytecode.Op.mul a b) + | Aiur.Concrete.Term.eqZero typ escapes a => do + let a ← Aiur.expectIdx._unsafe_rec layoutMap bindings a + Aiur.pushOp (Aiur.Bytecode.Op.eqZero a) + | Aiur.Concrete.Term.app typ escapes name args unconstrained => + match layoutMap[name]? with + | some (Aiur.Layout.function layout) => do + let args ← Aiur.buildArgs._unsafe_rec layoutMap bindings args + Aiur.pushOp (Aiur.Bytecode.Op.call layout.index args layout.outputSize unconstrained) layout.outputSize + | some (Aiur.Layout.constructor layout) => + let size := layout.size; + have __do_jp := fun index => do + let index ← Aiur.buildArgs._unsafe_rec layoutMap bindings args index + if index.size < size then do + let __do_lift ← Aiur.pushOp (Aiur.Bytecode.Op.const (Aiur.G.ofNat 0)) + let padding : Aiur.Bytecode.ValIdx := __do_lift[0]! + pure (index ++ Array.replicate (size - index.size) padding) + else pure index; + if layout.tagless = true then do + let index ← pure #[] + __do_jp index + else do + let index ← Aiur.pushOp (Aiur.Bytecode.Op.const (Aiur.G.ofNat layout.index)) + __do_jp index + | x => throw (toString "app: layout missing for `" ++ toString name ++ toString "`") + | Aiur.Concrete.Term.proj typ escapes arg i => + have __do_jp := fun typs => do + let offset ← + Array.foldlM + (fun acc typ => + have __do_jp := fun typLen => pure (typLen + acc); + match Aiur.typSize layoutMap typ with + | Except.error e => do + let typLen ← throw e + __do_jp typLen + | Except.ok len => do + let typLen ← pure len + __do_jp typLen) + 0 (typs.extract 0 i) + let arg ← Aiur.toIndex._unsafe_rec layoutMap bindings arg + have __do_jp : Nat → Aiur.CompileM (Array Aiur.Bytecode.ValIdx) := fun iLen => + pure (arg.extract offset (offset + iLen)) + match Aiur.typSize layoutMap (typs[i]?.getD Aiur.Concrete.Typ.unit) with + | Except.error e => do + let iLen ← throw e + __do_jp iLen + | Except.ok len => do + let iLen ← pure len + __do_jp iLen; + match arg.typ with + | Aiur.Concrete.Typ.tuple typs => do + let typs ← pure typs + __do_jp typs + | x => do + let typs ← throw "proj on non-tuple" + __do_jp typs + | Aiur.Concrete.Term.get typ escapes arr i => + have __do_jp := fun eltTyp => + have __do_jp := fun eltSize => + let offset := i * eltSize; + do + let arr ← Aiur.toIndex._unsafe_rec layoutMap bindings arr + pure (arr.extract offset (offset + eltSize)); + match Aiur.typSize layoutMap eltTyp with + | Except.error e => do + let eltSize ← throw e + __do_jp eltSize + | Except.ok len => do + let eltSize ← pure len + __do_jp eltSize; + match arr.typ with + | typ.array a => do + let eltTyp ← pure typ + __do_jp eltTyp + | x => do + let eltTyp ← throw "get on non-array" + __do_jp eltTyp + | Aiur.Concrete.Term.slice typ escapes arr i j => + have __do_jp := fun eltTyp => + have __do_jp := fun eltSize => do + let arr ← Aiur.toIndex._unsafe_rec layoutMap bindings arr + pure (arr.extract (i * eltSize) (j * eltSize)); + match Aiur.typSize layoutMap eltTyp with + | Except.error e => do + let eltSize ← throw e + __do_jp eltSize + | Except.ok len => do + let eltSize ← pure len + __do_jp eltSize; + match arr.typ with + | typ.array a => do + let eltTyp ← pure typ + __do_jp eltTyp + | x => do + let eltTyp ← throw "slice on non-array" + __do_jp eltTyp + | Aiur.Concrete.Term.set typ escapes arr i val => + have __do_jp := fun eltTyp => + have __do_jp := fun eltSize => do + let val ← Aiur.toIndex._unsafe_rec layoutMap bindings val + let arr ← Aiur.toIndex._unsafe_rec layoutMap bindings arr + let left : Array Aiur.Bytecode.ValIdx := arr.extract 0 (i * eltSize) + let right : Array Aiur.Bytecode.ValIdx := arr.extract ((i + 1) * eltSize) + pure (left ++ val ++ right); + match Aiur.typSize layoutMap eltTyp with + | Except.error e => do + let eltSize ← throw e + __do_jp eltSize + | Except.ok len => do + let eltSize ← pure len + __do_jp eltSize; + match arr.typ with + | typ.array a => do + let eltTyp ← pure typ + __do_jp eltTyp + | x => do + let eltTyp ← throw "set on non-array" + __do_jp eltTyp + | Aiur.Concrete.Term.store typ escapes arg => do + let args ← Aiur.toIndex._unsafe_rec layoutMap bindings arg + Aiur.pushOp (Aiur.Bytecode.Op.store args) + | Aiur.Concrete.Term.load typ escapes ptr => + have __do_jp := fun size => do + let ptr ← Aiur.expectIdx._unsafe_rec layoutMap bindings ptr + Aiur.pushOp (Aiur.Bytecode.Op.load size ptr) size; + match ptr.typ with + | typ.pointer => + match Aiur.typSize layoutMap typ with + | Except.error e => do + let size ← throw e + __do_jp size + | Except.ok len => do + let size ← pure len + __do_jp size + | x => do + let size ← throw "load on non-pointer" + __do_jp size + | Aiur.Concrete.Term.ptrVal typ escapes ptr => Aiur.toIndex._unsafe_rec layoutMap bindings ptr + | Aiur.Concrete.Term.assertEq typ escapes a b msg ret => do + let a ← Aiur.toIndex._unsafe_rec layoutMap bindings a + let b ← Aiur.toIndex._unsafe_rec layoutMap bindings b + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.assertEq a b msg), selIdx := stt.selIdx, + degrees := stt.degrees } + Aiur.toIndex._unsafe_rec layoutMap bindings ret + | Aiur.Concrete.Term.ioGetInfo typ escapes channel key => do + let channel ← Aiur.expectIdx._unsafe_rec layoutMap bindings channel + let key ← Aiur.toIndex._unsafe_rec layoutMap bindings key + Aiur.pushOp (Aiur.Bytecode.Op.ioGetInfo channel key) 2 + | Aiur.Concrete.Term.ioSetInfo typ escapes channel key idx len ret => do + let channel ← Aiur.expectIdx._unsafe_rec layoutMap bindings channel + let key ← Aiur.toIndex._unsafe_rec layoutMap bindings key + let idx ← Aiur.expectIdx._unsafe_rec layoutMap bindings idx + let len ← Aiur.expectIdx._unsafe_rec layoutMap bindings len + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.ioSetInfo channel key idx len), + selIdx := stt.selIdx, degrees := stt.degrees } + Aiur.toIndex._unsafe_rec layoutMap bindings ret + | Aiur.Concrete.Term.ioRead typ escapes channel idx len => do + let channel ← Aiur.expectIdx._unsafe_rec layoutMap bindings channel + let idx ← Aiur.expectIdx._unsafe_rec layoutMap bindings idx + Aiur.pushOp (Aiur.Bytecode.Op.ioRead channel idx len) len + | Aiur.Concrete.Term.ioWrite typ escapes channel data ret => do + let channel ← Aiur.expectIdx._unsafe_rec layoutMap bindings channel + let data ← Aiur.toIndex._unsafe_rec layoutMap bindings data + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.ioWrite channel data), selIdx := stt.selIdx, + degrees := stt.degrees } + Aiur.toIndex._unsafe_rec layoutMap bindings ret + | Aiur.Concrete.Term.u8BitDecomposition typ escapes byte => do + let byte ← Aiur.expectIdx._unsafe_rec layoutMap bindings byte + Aiur.pushOp (Aiur.Bytecode.Op.u8BitDecomposition byte) 8 + | Aiur.Concrete.Term.u8ShiftLeft typ escapes byte => do + let byte ← Aiur.expectIdx._unsafe_rec layoutMap bindings byte + Aiur.pushOp (Aiur.Bytecode.Op.u8ShiftLeft byte) + | Aiur.Concrete.Term.u8ShiftRight typ escapes byte => do + let byte ← Aiur.expectIdx._unsafe_rec layoutMap bindings byte + Aiur.pushOp (Aiur.Bytecode.Op.u8ShiftRight byte) + | Aiur.Concrete.Term.u8Xor typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8Xor i j) + | Aiur.Concrete.Term.u8Add typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8Add i j) 2 + | Aiur.Concrete.Term.u8Mul typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8Mul i j) 2 + | Aiur.Concrete.Term.u8XorSplit7 typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8XorSplit7 i j) 2 + | Aiur.Concrete.Term.u8XorSplit4 typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8XorSplit4 i j) 2 + | Aiur.Concrete.Term.u8Sub typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8Sub i j) 2 + | Aiur.Concrete.Term.u8And typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8And i j) + | Aiur.Concrete.Term.u8Or typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8Or i j) + | Aiur.Concrete.Term.u8LessThan typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u8LessThan i j) + | Aiur.Concrete.Term.u32LessThan typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + Aiur.pushOp (Aiur.Bytecode.Op.u32LessThan i j) + | Aiur.Concrete.Term.unconstrainedU32Add typ escapes a b => do + let a ← Aiur.toIndex._unsafe_rec layoutMap bindings a + let b ← Aiur.toIndex._unsafe_rec layoutMap bindings b + Aiur.pushOp (Aiur.Bytecode.Op.unconstrainedU32Add a b) 5 + | Aiur.Concrete.Term.unconstrainedU32Add3 typ escapes a b c => do + let a ← Aiur.toIndex._unsafe_rec layoutMap bindings a + let b ← Aiur.toIndex._unsafe_rec layoutMap bindings b + let c ← Aiur.toIndex._unsafe_rec layoutMap bindings c + Aiur.pushOp (Aiur.Bytecode.Op.unconstrainedU32Add3 a b c) 5 + | Aiur.Concrete.Term.u32ToField typ escapes a => do + let a ← Aiur.toIndex._unsafe_rec layoutMap bindings a + Aiur.pushOp (Aiur.Bytecode.Op.u32ToField a) + | Aiur.Concrete.Term.u8RangeCheck typ escapes i j => do + let i ← Aiur.expectIdx._unsafe_rec layoutMap bindings i + let j ← Aiur.expectIdx._unsafe_rec layoutMap bindings j + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.u8RangeCheck i j), selIdx := stt.selIdx, + degrees := stt.degrees } + pure #[i, j] + | Aiur.Concrete.Term.unconstrainedBigUintDivMod typ escapes a b => do + let a ← Aiur.expectIdx._unsafe_rec layoutMap bindings a + let b ← Aiur.expectIdx._unsafe_rec layoutMap bindings b + Aiur.pushOp (Aiur.Bytecode.Op.unconstrainedBigUintDivMod a b) 2 + | Aiur.Concrete.Term.unconstrainedGToBytes typ escapes a => do + let a ← Aiur.expectIdx._unsafe_rec layoutMap bindings a + Aiur.pushOp (Aiur.Bytecode.Op.unconstrainedGToBytes a) 8 + | Aiur.Concrete.Term.unconstrainedGInverse typ escapes a => do + let a ← Aiur.expectIdx._unsafe_rec layoutMap bindings a + Aiur.pushOp (Aiur.Bytecode.Op.unconstrainedGInverse a) + | Aiur.Concrete.Term.debug typ escapes label term ret => + have __do_jp := fun term => do + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.debug label term), selIdx := stt.selIdx, + degrees := stt.degrees } + Aiur.toIndex._unsafe_rec layoutMap bindings ret; + match term with + | none => do + let term ← pure none + __do_jp term + | some sub => do + let __do_lift ← Aiur.toIndex._unsafe_rec layoutMap bindings sub + let term ← pure (some __do_lift) + __do_jp term +RECURSION WORKER Aiur.typFlatSizeBound._unsafe_rec +Aiur.Source.Decls → Nat → Std.HashSet Aiur.Global → Aiur.Typ → Nat +IMPLEMENTATION +fun decls x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, x_3 => 0 + | n.succ, x, Aiur.Typ.unit => 0 + | n.succ, x, Aiur.Typ.field => 1 + | n.succ, x, Aiur.Typ.u8 => 1 + | n.succ, x, a.pointer => 1 + | n.succ, x, Aiur.Typ.function a a_1 => 1 + | bound.succ, visited, Aiur.Typ.tuple ts => + Array.foldl + (fun acc x => + match x with + | ⟨t, property⟩ => acc + Aiur.typFlatSizeBound._unsafe_rec decls bound visited t) + 0 ts.attach + | bound.succ, visited, t.array n => n * Aiur.typFlatSizeBound._unsafe_rec decls bound visited t + | bound.succ, visited, Aiur.Typ.ref g => + if visited.contains g = true then 0 + else + match IndexMap.getByKey decls g with + | some (Aiur.Source.Declaration.dataType dt) => + Aiur.dataTypeFlatSizeBound._unsafe_rec decls bound (visited.insert g) dt + | x => 0 + | bound.succ, visited, Aiur.Typ.app g a => + if visited.contains g = true then 0 + else + match IndexMap.getByKey decls g with + | some (Aiur.Source.Declaration.dataType dt) => + Aiur.dataTypeFlatSizeBound._unsafe_rec decls bound (visited.insert g) dt + | x => 0 + | n.succ, x, Aiur.Typ.mvar a => 0 +RECURSION WORKER Aiur.typSize._unsafe_rec +Aiur.LayoutMap → Aiur.Concrete.Typ → Except String Nat +IMPLEMENTATION +fun layoutMap x => + match x with + | Aiur.Concrete.Typ.unit => pure 0 + | Aiur.Concrete.Typ.field => pure 1 + | a.pointer => pure 1 + | Aiur.Concrete.Typ.function a a_1 => pure 1 + | Aiur.Concrete.Typ.tuple ts => + Array.foldlM + (fun acc t => do + let tSize ← Aiur.typSize._unsafe_rec layoutMap t + pure (acc + tSize)) + 0 ts + | typ.array n => do + let size ← Aiur.typSize._unsafe_rec layoutMap typ + pure (n * size) + | Aiur.Concrete.Typ.ref g => + match layoutMap[g]? with + | some (Aiur.Layout.dataType size) => pure size + | x => throw (toString "Layout missing for `" ++ toString g ++ toString "`") +RECURSION WORKER Aiur.typToConcrete._unsafe_rec +Std.HashMap (Aiur.Global × Array Aiur.Typ) Aiur.Global → Aiur.Typ → Except Aiur.ConcretizeError Aiur.Concrete.Typ +IMPLEMENTATION +fun mono x => + match x with + | Aiur.Typ.unit => pure Aiur.Concrete.Typ.unit + | Aiur.Typ.field => pure Aiur.Concrete.Typ.field + | Aiur.Typ.u8 => pure Aiur.Concrete.Typ.field + | Aiur.Typ.tuple ts => do + let __do_lift ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.typToConcrete._unsafe_rec mono t) + ts.attach + pure (Aiur.Concrete.Typ.tuple __do_lift) + | t.array n => do + let __do_lift ← Aiur.typToConcrete._unsafe_rec mono t + pure (__do_lift.array n) + | t.pointer => do + let __do_lift ← Aiur.typToConcrete._unsafe_rec mono t + pure __do_lift.pointer + | Aiur.Typ.function ins out => do + let ins' ← + List.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.typToConcrete._unsafe_rec mono t) + ins.attach + let out' ← Aiur.typToConcrete._unsafe_rec mono out + pure (Aiur.Concrete.Typ.function ins' out') + | Aiur.Typ.ref g => pure (Aiur.Concrete.Typ.ref g) + | Aiur.Typ.app g args => + match mono[(g, args)]? with + | some concName => pure (Aiur.Concrete.Typ.ref concName) + | none => pure (Aiur.Concrete.Typ.ref g) + | Aiur.Typ.mvar n => Except.error (Aiur.ConcretizeError.unresolvedMVar n) +RECURSION WORKER Aiur.unifyTypBound._unsafe_rec +Nat → Aiur.Typ → Aiur.Typ → Aiur.CheckM Bool +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, x_3 => pure false + | bound.succ, t1, t2 => do + let t1 ← Aiur.walkTyp t1 + let t2 ← Aiur.walkTyp t2 + match t1, t2 with + | Aiur.Typ.mvar a, Aiur.Typ.mvar b => + if (a == b) = true then pure true + else do + Aiur.bindMVar a (Aiur.Typ.mvar b) + pure true + | Aiur.Typ.mvar a, x => do + Aiur.bindMVar a t2 + pure true + | x, Aiur.Typ.mvar b => do + Aiur.bindMVar b t1 + pure true + | Aiur.Typ.unit, Aiur.Typ.unit => pure true + | Aiur.Typ.field, Aiur.Typ.field => pure true + | Aiur.Typ.u8, Aiur.Typ.u8 => pure true + | Aiur.Typ.tuple ts1, Aiur.Typ.tuple ts2 => + if (ts1.size != ts2.size) = true then pure false + else + Array.allM + (fun x => + match x with + | (x, y) => Aiur.unifyTypBound._unsafe_rec bound x y) + (ts1.zip ts2) + | t1'.array n1, t2'.array n2 => + if (n1 != n2) = true then pure false else Aiur.unifyTypBound._unsafe_rec bound t1' t2' + | t1'.pointer, t2'.pointer => Aiur.unifyTypBound._unsafe_rec bound t1' t2' + | Aiur.Typ.ref g1, Aiur.Typ.ref g2 => pure (g1 == g2) + | Aiur.Typ.function ins1 out1, Aiur.Typ.function ins2 out2 => + if (ins1.length != ins2.length) = true then pure false + else do + let inOk ← + List.allM + (fun x => + match x with + | (x, y) => Aiur.unifyTypBound._unsafe_rec bound x y) + (ins1.zip ins2) + if (!inOk) = true then pure false else Aiur.unifyTypBound._unsafe_rec bound out1 out2 + | Aiur.Typ.app g1 a1, Aiur.Typ.app g2 a2 => + if (g1 != g2 || a1.size != a2.size) = true then pure false + else + Array.allM + (fun x => + match x with + | (x, y) => Aiur.unifyTypBound._unsafe_rec bound x y) + (a1.zip a2) + | x, x_3 => pure false +RECURSION WORKER Aiur.walkTypBound._unsafe_rec +Nat → Std.HashSet Nat → Aiur.Typ → Aiur.CheckM Aiur.Typ +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | bound, visited, Aiur.Typ.mvar id => + if visited.contains id = true then pure (Aiur.Typ.mvar id) + else + match bound with + | 0 => pure (Aiur.Typ.mvar id) + | bound.succ => do + let __do_lift ← get + match __do_lift.mvarSubst[id]? with + | some t => Aiur.walkTypBound._unsafe_rec bound (visited.insert id) t + | none => pure (Aiur.Typ.mvar id) + | x, x_3, t => pure t +RECURSION WORKER Aiur.zonkTypBound._unsafe_rec +Nat → Std.HashSet Nat → Aiur.Typ → Aiur.CheckM Aiur.Typ +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | bound, visited, Aiur.Typ.mvar id => + if visited.contains id = true then pure (Aiur.Typ.mvar id) + else + match bound with + | 0 => pure (Aiur.Typ.mvar id) + | bound.succ => do + let __do_lift ← get + match __do_lift.mvarSubst[id]? with + | some t => Aiur.zonkTypBound._unsafe_rec bound (visited.insert id) t + | none => pure (Aiur.Typ.mvar id) + | bound, visited, Aiur.Typ.tuple ts => do + let __do_lift ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.zonkTypBound._unsafe_rec bound visited t) + ts.attach + pure (Aiur.Typ.tuple __do_lift) + | bound, visited, t.array n => do + let __do_lift ← Aiur.zonkTypBound._unsafe_rec bound visited t + pure (__do_lift.array n) + | bound, visited, t.pointer => do + let __do_lift ← Aiur.zonkTypBound._unsafe_rec bound visited t + pure __do_lift.pointer + | bound, visited, Aiur.Typ.function ins out => do + let __do_lift ← + List.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.zonkTypBound._unsafe_rec bound visited t) + ins.attach + let __do_lift_1 ← Aiur.zonkTypBound._unsafe_rec bound visited out + pure (Aiur.Typ.function __do_lift __do_lift_1) + | bound, visited, Aiur.Typ.app g args => do + let __do_lift ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.zonkTypBound._unsafe_rec bound visited t) + args.attach + pure (Aiur.Typ.app g __do_lift) + | x, x_3, t => pure t +RECURSION WORKER Aiur.zonkTypedTerm._unsafe_rec +Aiur.Typed.Term → Aiur.CheckM Aiur.Typed.Term +IMPLEMENTATION +fun t => + match t with + | Aiur.Typed.Term.unit τ e => do + let __do_lift ← Aiur.zonkTyp τ + pure (Aiur.Typed.Term.unit __do_lift e) + | Aiur.Typed.Term.var τ e l => do + let __do_lift ← Aiur.zonkTyp τ + pure (Aiur.Typed.Term.var __do_lift e l) + | Aiur.Typed.Term.ref τ e g tArgs => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Array.mapM Aiur.zonkTyp tArgs + pure (Aiur.Typed.Term.ref __do_lift e g __do_lift_1) + | Aiur.Typed.Term.field τ e g => do + let __do_lift ← Aiur.zonkTyp τ + pure (Aiur.Typed.Term.field __do_lift e g) + | Aiur.Typed.Term.tuple τ e ts => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.zonkTypedTerm._unsafe_rec t) + ts.attach + pure (Aiur.Typed.Term.tuple __do_lift e __do_lift_1) + | Aiur.Typed.Term.array τ e ts => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← + Array.mapM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.zonkTypedTerm._unsafe_rec t) + ts.attach + pure (Aiur.Typed.Term.array __do_lift e __do_lift_1) + | Aiur.Typed.Term.ret τ e sub => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec sub + pure (Aiur.Typed.Term.ret __do_lift e __do_lift_1) + | Aiur.Typed.Term.let τ e pat v b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec v + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.let __do_lift e pat __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.match τ e scrut bs => do + let scrut' ← Aiur.zonkTypedTerm._unsafe_rec scrut + let bs' ← + List.mapM + (fun x => + match x with + | ⟨(p, b), property⟩ => do + let __do_lift ← Aiur.zonkTypedTerm._unsafe_rec b + pure (p, __do_lift)) + bs.attach + let __do_lift ← Aiur.zonkTyp τ + pure (Aiur.Typed.Term.match __do_lift e scrut' bs') + | Aiur.Typed.Term.app τ e g tArgs args u => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Array.mapM Aiur.zonkTyp tArgs + let __do_lift_2 ← + List.mapM + (fun x => + match x with + | ⟨a, property⟩ => Aiur.zonkTypedTerm._unsafe_rec a) + args.attach + pure (Aiur.Typed.Term.app __do_lift e g __do_lift_1 __do_lift_2 u) + | Aiur.Typed.Term.add τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.add __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.sub τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.sub __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.mul τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.mul __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.eqZero τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.eqZero __do_lift e __do_lift_1) + | Aiur.Typed.Term.proj τ e a n => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.proj __do_lift e __do_lift_1 n) + | Aiur.Typed.Term.get τ e a n => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.get __do_lift e __do_lift_1 n) + | Aiur.Typed.Term.slice τ e a i j => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.slice __do_lift e __do_lift_1 i j) + | Aiur.Typed.Term.set τ e a n v => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec v + pure (Aiur.Typed.Term.set __do_lift e __do_lift_1 n __do_lift_2) + | Aiur.Typed.Term.store τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.store __do_lift e __do_lift_1) + | Aiur.Typed.Term.load τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.load __do_lift e __do_lift_1) + | Aiur.Typed.Term.ptrVal τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.ptrVal __do_lift e __do_lift_1) + | Aiur.Typed.Term.assertEq τ e a b msg r => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + let __do_lift_3 ← Aiur.zonkTypedTerm._unsafe_rec r + pure (Aiur.Typed.Term.assertEq __do_lift e __do_lift_1 __do_lift_2 msg __do_lift_3) + | Aiur.Typed.Term.ioGetInfo τ e c k => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec c + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec k + pure (Aiur.Typed.Term.ioGetInfo __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.ioSetInfo τ e c k i l r => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec c + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec k + let __do_lift_3 ← Aiur.zonkTypedTerm._unsafe_rec i + let __do_lift_4 ← Aiur.zonkTypedTerm._unsafe_rec l + let __do_lift_5 ← Aiur.zonkTypedTerm._unsafe_rec r + pure (Aiur.Typed.Term.ioSetInfo __do_lift e __do_lift_1 __do_lift_2 __do_lift_3 __do_lift_4 __do_lift_5) + | Aiur.Typed.Term.ioRead τ e c i n => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec c + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec i + pure (Aiur.Typed.Term.ioRead __do_lift e __do_lift_1 __do_lift_2 n) + | Aiur.Typed.Term.ioWrite τ e c d r => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec c + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec d + let __do_lift_3 ← Aiur.zonkTypedTerm._unsafe_rec r + pure (Aiur.Typed.Term.ioWrite __do_lift e __do_lift_1 __do_lift_2 __do_lift_3) + | Aiur.Typed.Term.u8BitDecomposition τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.u8BitDecomposition __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8ShiftLeft τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.u8ShiftLeft __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8ShiftRight τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.u8ShiftRight __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8Xor τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8Xor __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Add τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8Add __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Mul τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8Mul __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8XorSplit7 τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8XorSplit7 __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8XorSplit4 τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8XorSplit4 __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Sub τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8Sub __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8And τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8And __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8Or τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8Or __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8LessThan τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8LessThan __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u32LessThan τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u32LessThan __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.u8RangeCheck τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.u8RangeCheck __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.unconstrainedBigUintDivMod τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.unconstrainedBigUintDivMod __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.unconstrainedGToBytes τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.unconstrainedGToBytes __do_lift e __do_lift_1) + | Aiur.Typed.Term.unconstrainedGInverse τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.unconstrainedGInverse __do_lift e __do_lift_1) + | Aiur.Typed.Term.unconstrainedU32Add τ e a b => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + pure (Aiur.Typed.Term.unconstrainedU32Add __do_lift e __do_lift_1 __do_lift_2) + | Aiur.Typed.Term.unconstrainedU32Add3 τ e a b c => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + let __do_lift_2 ← Aiur.zonkTypedTerm._unsafe_rec b + let __do_lift_3 ← Aiur.zonkTypedTerm._unsafe_rec c + pure (Aiur.Typed.Term.unconstrainedU32Add3 __do_lift e __do_lift_1 __do_lift_2 __do_lift_3) + | Aiur.Typed.Term.u32ToField τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.u32ToField __do_lift e __do_lift_1) + | Aiur.Typed.Term.toField τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.toField __do_lift e __do_lift_1) + | Aiur.Typed.Term.u8FromFieldUnsafe τ e a => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec a + pure (Aiur.Typed.Term.u8FromFieldUnsafe __do_lift e __do_lift_1) + | Aiur.Typed.Term.debug τ e label t r => + have __do_jp := fun t' => do + let __do_lift ← Aiur.zonkTyp τ + let __do_lift_1 ← Aiur.zonkTypedTerm._unsafe_rec r + pure (Aiur.Typed.Term.debug __do_lift e label t' __do_lift_1); + match t with + | none => do + let t' ← pure none + __do_jp t' + | some sub => do + let __do_lift ← Aiur.zonkTypedTerm._unsafe_rec sub + let t' ← pure (some __do_lift) + __do_jp t' +RECURSION WORKER Aiur.AIR.addMessages._unsafe_rec +List Aiur.G → List Aiur.G → List Aiur.G +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], right => right + | left, [] => left + | x :: left, y :: right => (x + y) :: Aiur.AIR.addMessages._unsafe_rec left right +RECURSION WORKER Aiur.AIR.emitMembers._unsafe_rec +(Nat → Aiur.G) → + Aiur.G → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → List Aiur.Bytecode.FunIdx → Option (List Aiur.AIR.MemberEmission) +IMPLEMENTATION +fun row rank column lookup selectorBase program x => + match x with + | [] => some [] + | index :: indices => do + let member ← Aiur.AIR.emitMember row rank column lookup selectorBase program index + let rest ← + Aiur.AIR.emitMembers._unsafe_rec row rank column lookup (selectorBase + member.function.layout.selectors) program + indices + pure (member :: rest) +RECURSION WORKER Aiur.AIR.emitOps._unsafe_rec +(Nat → Aiur.G) → Aiur.G → Aiur.G → List Aiur.Bytecode.Op → Array Aiur.AIR.RowValue → Nat → Option Aiur.AIR.OpsEmission +IMPLEMENTATION +fun row selector rank x x_1 x_2 => + match x, x_1, x_2 with + | [], values, column => some { values := values, column := column } + | op :: ops, values, column => do + let first ← Aiur.AIR.emitOp (fun i => row (column + i)) selector rank op values + let rest ← Aiur.AIR.emitOps._unsafe_rec row selector rank ops (values ++ first.outputs) (column + first.used) + pure + { values := rest.values, column := rest.column, equations := first.equations ++ rest.equations, + queries := first.queries ++ rest.queries, calls := first.calls ++ rest.calls } +RECURSION WORKER Aiur.Bytecode.beqBranches._unsafe_rec +Array (Aiur.G × Aiur.Bytecode.Block) → Array (Aiur.G × Aiur.Bytecode.Block) → Bool +IMPLEMENTATION +fun left right => + if h : left.size = right.size then Aiur.Bytecode.beqBranchesAux._unsafe_rec left right h left.size ⋯ else false +RECURSION WORKER Aiur.Bytecode.beqBranchesAux._unsafe_rec +(left right : Array (Aiur.G × Aiur.Bytecode.Block)) → left.size = right.size → (n : Nat) → n ≤ left.size → Bool +IMPLEMENTATION +fun left right hsz x x_1 => + match x, x_1 with + | 0, x => true + | n.succ, h => + left[n].fst == right[n].fst && Aiur.Bytecode.Block.beq._unsafe_rec left[n].snd right[n].snd && + Aiur.Bytecode.beqBranchesAux._unsafe_rec left right hsz n ⋯ +RECURSION WORKER Aiur.Bytecode.beqFallback._unsafe_rec +Option Aiur.Bytecode.Block → Option Aiur.Bytecode.Block → Bool +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | none, none => true + | some left, some right => Aiur.Bytecode.Block.beq._unsafe_rec left right + | x, x_2 => false +RECURSION WORKER Aiur.Bytecode.callOrderComponentDfs._unsafe_rec +Array (Array Nat) → Nat → Nat → Nat → Array Nat → Array Nat +IMPLEMENTATION +fun graph component x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, labels => labels + | fuel.succ, node, labels => + if labels[node]! < graph.size then labels + else + Array.foldl + (fun labels child => Aiur.Bytecode.callOrderComponentDfs._unsafe_rec graph component fuel child labels) + (labels.set! node component) graph[node]! +RECURSION WORKER Aiur.Bytecode.callOrderFinishDfs._unsafe_rec +Array (Array Nat) → Nat → Nat → Array Bool × Array Nat → Array Bool × Array Nat +IMPLEMENTATION +fun graph x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, state => state + | fuel.succ, node, state => + if state.fst[node]! = true then state + else + let state := (state.fst.set! node true, state.snd); + let state := + Array.foldl (fun state child => Aiur.Bytecode.callOrderFinishDfs._unsafe_rec graph fuel child state) state + graph[node]!; + (state.fst, state.snd.push node) +RECURSION WORKER Aiur.Bytecode.checkEmissionOps._unsafe_rec +List Aiur.Bytecode.Op → Nat → Option Nat +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], available => some available + | op :: ops, available => + if (!Aiur.Bytecode.Op.emissionInputs available op) = true then none + else do + let next ← Aiur.Bytecode.addScope available op.outputSize + Aiur.Bytecode.checkEmissionOps._unsafe_rec ops next +RECURSION WORKER Aiur.Bytecode.collectCalleesBlock._unsafe_rec +Aiur.Bytecode.Block → Array Aiur.Bytecode.FunIdx +IMPLEMENTATION +fun block => + let opCallees := Array.foldl (fun acc op => acc ++ Aiur.Bytecode.collectCalleesOp op) #[] block.ops; + opCallees ++ Aiur.Bytecode.collectCalleesCtrl._unsafe_rec block.ctrl +RECURSION WORKER Aiur.Bytecode.collectCalleesCtrl._unsafe_rec +Aiur.Bytecode.Ctrl → Array Aiur.Bytecode.FunIdx +IMPLEMENTATION +fun c => + match c with + | Aiur.Bytecode.Ctrl.match a branches def_ => + let branchCallees := + Array.foldl + (fun acc x => + match x with + | ⟨(fst, b), property⟩ => acc ++ Aiur.Bytecode.collectCalleesBlock._unsafe_rec b) + #[] branches.attach; + match def_ with + | none => branchCallees + | some b => branchCallees ++ Aiur.Bytecode.collectCalleesBlock._unsafe_rec b + | Aiur.Bytecode.Ctrl.return a a_1 => #[] + | Aiur.Bytecode.Ctrl.yield a a_1 => #[] + | Aiur.Bytecode.Ctrl.matchContinue a branches def_ outputSize sharedAuxiliaries sharedLookups cont => + let branchCallees := + Array.foldl + (fun acc x => + match x with + | ⟨(fst, b), property⟩ => acc ++ Aiur.Bytecode.collectCalleesBlock._unsafe_rec b) + #[] branches.attach; + let withDefault := + match def_ with + | none => branchCallees + | some b => branchCallees ++ Aiur.Bytecode.collectCalleesBlock._unsafe_rec b; + withDefault ++ Aiur.Bytecode.collectCalleesBlock._unsafe_rec cont +RECURSION WORKER Aiur.Bytecode.partitionRefineBound._unsafe_rec +Nat → Array Nat → Array (Array Aiur.Bytecode.FunIdx) → Array Nat +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | 0, classes, x => classes + | bound.succ, classes, callees => + let signatures := + Array.mapIdx (fun i cls => (cls, Array.map (fun callee => classes[callee]?.getD 0) (callees[i]?.getD #[]))) + classes; + match Aiur.Bytecode.assignClasses signatures with + | (newClasses, snd) => + if (newClasses == classes) = true then classes + else Aiur.Bytecode.partitionRefineBound._unsafe_rec bound newClasses callees +RECURSION WORKER Aiur.Bytecode.rewriteBlock._unsafe_rec +(Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) → Aiur.Bytecode.Block → Aiur.Bytecode.Block +IMPLEMENTATION +fun f block => + { ops := Array.map (Aiur.Bytecode.rewriteOp f) block.ops, ctrl := Aiur.Bytecode.rewriteCtrl._unsafe_rec f block.ctrl } +RECURSION WORKER Aiur.Bytecode.rewriteCtrl._unsafe_rec +(Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx) → Aiur.Bytecode.Ctrl → Aiur.Bytecode.Ctrl +IMPLEMENTATION +fun f c => + match c with + | Aiur.Bytecode.Ctrl.match v branches def_ => + Aiur.Bytecode.Ctrl.match v + (Array.map + (fun x => + match x with + | ⟨(g, b), property⟩ => (g, Aiur.Bytecode.rewriteBlock._unsafe_rec f b)) + branches.attach) + (match def_ with + | none => none + | some b => some (Aiur.Bytecode.rewriteBlock._unsafe_rec f b)) + | Aiur.Bytecode.Ctrl.return s vs => Aiur.Bytecode.Ctrl.return s vs + | Aiur.Bytecode.Ctrl.yield s vs => Aiur.Bytecode.Ctrl.yield s vs + | Aiur.Bytecode.Ctrl.matchContinue v branches def_ outputSize sharedAux sharedLookups cont => + Aiur.Bytecode.Ctrl.matchContinue v + (Array.map + (fun x => + match x with + | ⟨(g, b), property⟩ => (g, Aiur.Bytecode.rewriteBlock._unsafe_rec f b)) + branches.attach) + (match def_ with + | none => none + | some b => some (Aiur.Bytecode.rewriteBlock._unsafe_rec f b)) + outputSize sharedAux sharedLookups (Aiur.Bytecode.rewriteBlock._unsafe_rec f cont) +RECURSION WORKER Aiur.Bytecode.skeletonBlock._unsafe_rec +Aiur.Bytecode.Block → Aiur.Bytecode.Block +IMPLEMENTATION +fun block => + { ops := Array.map Aiur.Bytecode.skeletonOp block.ops, ctrl := Aiur.Bytecode.skeletonCtrl._unsafe_rec block.ctrl } +RECURSION WORKER Aiur.Bytecode.skeletonCtrl._unsafe_rec +Aiur.Bytecode.Ctrl → Aiur.Bytecode.Ctrl +IMPLEMENTATION +fun x => + match x with + | Aiur.Bytecode.Ctrl.match v branches def_ => + Aiur.Bytecode.Ctrl.match v + (Array.map + (fun x => + match x with + | ⟨(g, b), property⟩ => (g, Aiur.Bytecode.skeletonBlock._unsafe_rec b)) + branches.attach) + (match def_ with + | none => none + | some b => some (Aiur.Bytecode.skeletonBlock._unsafe_rec b)) + | Aiur.Bytecode.Ctrl.return s vs => Aiur.Bytecode.Ctrl.return s vs + | Aiur.Bytecode.Ctrl.yield s vs => Aiur.Bytecode.Ctrl.yield s vs + | Aiur.Bytecode.Ctrl.matchContinue v branches def_ outputSize sharedAux sharedLookups cont => + Aiur.Bytecode.Ctrl.matchContinue v + (Array.map + (fun x => + match x with + | ⟨(g, b), property⟩ => (g, Aiur.Bytecode.skeletonBlock._unsafe_rec b)) + branches.attach) + (match def_ with + | none => none + | some b => some (Aiur.Bytecode.skeletonBlock._unsafe_rec b)) + outputSize sharedAux sharedLookups (Aiur.Bytecode.skeletonBlock._unsafe_rec cont) +RECURSION WORKER Aiur.Concrete.addCase._unsafe_rec +Aiur.LayoutMap → + Std.HashMap Aiur.Local (Array Aiur.Bytecode.ValIdx) → + Aiur.Concrete.Typ → + Array Aiur.Bytecode.ValIdx → + optParam Bool false → + Array (Aiur.G × Aiur.Bytecode.Block) × Option Aiur.Bytecode.Block → + Aiur.Concrete.Pattern × Aiur.Concrete.Term → + Aiur.CompileM (Array (Aiur.G × Aiur.Bytecode.Block) × Option Aiur.Bytecode.Block) +IMPLEMENTATION +fun layoutMap bindings returnTyp idxs yieldCtrl x x_1 => + match x with + | (cases, defaultBlock) => + match x_1 with + | (pat, term) => + match pat with + | Aiur.Concrete.Pattern.field g => do + let initState ← get + let term ← Aiur.Concrete.Term.compile._unsafe_rec term returnTyp layoutMap bindings yieldCtrl + let __do_lift ← get + set + { valIdx := initState.valIdx, ops := initState.ops, selIdx := __do_lift.selIdx, + degrees := initState.degrees } + pure (cases.push (g, term), defaultBlock) + | Aiur.Concrete.Pattern.ref global pats => + have __do_jp := fun __x => + match __x with + | (index, offsets, tagless) => + let base := if tagless = true then 0 else 1; + let ptrBindings := + Array.foldl + (fun acc i => + let startOff := base + offsets[i]?.getD 0; + let endOff := base + offsets[i + 1]?.getD (offsets[i]?.getD 0); + let slice := idxs.extract startOff endOff; + let patLocal := pats[i]?.getD (Aiur.Local.idx 0); + acc.insert patLocal slice) + bindings (Array.range pats.size); + do + let initState ← get + let term ← Aiur.Concrete.Term.compile._unsafe_rec term returnTyp layoutMap ptrBindings yieldCtrl + let __do_lift ← get + set + { valIdx := initState.valIdx, ops := initState.ops, selIdx := __do_lift.selIdx, + degrees := initState.degrees } + if tagless = true then pure (cases, some term) + else pure (cases.push (Aiur.G.ofNat index, term), defaultBlock); + match layoutMap[global]? with + | some (Aiur.Layout.function layout) => do + let __x ← pure (layout.index, layout.offsets, false) + __do_jp __x + | some (Aiur.Layout.constructor layout) => do + let __x ← pure (layout.index, layout.offsets, layout.tagless) + __do_jp __x + | x => do + let __x ← throw (toString "addCase: layout missing for `" ++ toString global ++ toString "`") + __do_jp __x + | Aiur.Concrete.Pattern.wildcard => do + let initState ← get + let term ← Aiur.Concrete.Term.compile._unsafe_rec term returnTyp layoutMap bindings yieldCtrl + let __do_lift ← get + set + { valIdx := initState.valIdx, ops := initState.ops, selIdx := __do_lift.selIdx, + degrees := initState.degrees } + pure (cases, some term) + | x => throw "addCase: unsupported pattern in concrete lower" +RECURSION WORKER Aiur.G.product._unsafe_rec +List Aiur.G → Aiur.G +IMPLEMENTATION +fun x => + match x with + | [] => 1 + | value :: values => value * Aiur.G.product._unsafe_rec values +RECURSION WORKER Aiur.GoldilocksProof.squareMod._unsafe_rec +Nat → Nat → Nat → Nat +IMPLEMENTATION +fun modulus base x => + match x with + | 0 => base % modulus + | n.succ => + let previous := Aiur.GoldilocksProof.squareMod._unsafe_rec modulus base n; + previous * previous % modulus +RECURSION WORKER Aiur.MatchCompiler.compileRowsBound._unsafe_rec +Nat → Array Aiur.MatchCompiler.Row → Aiur.MatchCompiler.CompilerM Aiur.MatchCompiler.Decision +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | 0, x => do + Aiur.MatchCompiler.modifyDiagnostics fun d => { missing := true, reachable := d.reachable } + pure Aiur.MatchCompiler.Decision.failure + | bound.succ, rows => + match rows[0]? with + | some row => + match row.clauses[0]? with + | some clause => Aiur.MatchCompiler.compileSwitchBound._unsafe_rec bound rows clause.body + | none => do + Aiur.MatchCompiler.modifyDiagnostics fun d => + { missing := d.missing, reachable := row.body.value :: d.reachable } + pure (Aiur.MatchCompiler.Decision.success row.body) + | none => do + Aiur.MatchCompiler.modifyDiagnostics fun d => { missing := true, reachable := d.reachable } + pure Aiur.MatchCompiler.Decision.failure +RECURSION WORKER Aiur.MatchCompiler.compileSwitchBound._unsafe_rec +Nat → + Array Aiur.MatchCompiler.Row → Aiur.MatchCompiler.UniqTerm → Aiur.MatchCompiler.CompilerM Aiur.MatchCompiler.Decision +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, x_3 => pure Aiur.MatchCompiler.Decision.failure + | bound.succ, rows, term => do + let stt ← get + let numCases : Nat := Aiur.MatchCompiler.patTypeLength stt.decls rows[0]!.clauses[0]!.pat + let spatMap : SmallMap Aiur.MatchCompiler.SPattern (Array Aiur.MatchCompiler.Row) := + Aiur.MatchCompiler.extractSPatterns rows term + let size : Nat := spatMap.size + if (size == numCases) = true then do + let __x ← Array.foldlM (Aiur.MatchCompiler.processRow✝ term) (spatMap, #[]) rows + match __x with + | (rowMap, snd) => do + let cases ← + List.mapM + (fun x => + match x with + | (pat, rows) => Prod.mk pat <$> Aiur.MatchCompiler.compileRowsBound._unsafe_rec bound rows) + rowMap.toList + Aiur.MatchCompiler.setId stt.uniqId + pure (Aiur.MatchCompiler.switch cases Aiur.MatchCompiler.Decision.failure term) + else do + let __x ← Array.foldlM (Aiur.MatchCompiler.processRow✝ term) (spatMap, #[]) rows + match __x with + | (rowMap, fallbackRows) => do + let cases ← + List.mapM + (fun x => + match x with + | (pat, rows) => Prod.mk pat <$> Aiur.MatchCompiler.compileRowsBound._unsafe_rec bound rows) + rowMap.toList + let fallback ← Aiur.MatchCompiler.compileRowsBound._unsafe_rec bound fallbackRows + Aiur.MatchCompiler.setId stt.uniqId + pure (Aiur.MatchCompiler.switch cases fallback term) +RECURSION WORKER Aiur.MatchCompiler.decisionToTyped._unsafe_rec +Aiur.Typ → Aiur.Typ → Aiur.MatchCompiler.Decision → Option Aiur.Typed.Term +IMPLEMENTATION +fun retTyp scrutTyp x => + match x with + | Aiur.MatchCompiler.Decision.failure => none + | Aiur.MatchCompiler.Decision.success { renames := renames, value := value } => + some + (Array.foldr + (fun x acc => + match x with + | (x, term) => Aiur.Typed.Term.let acc.typ acc.escapes (Aiur.Pattern.var x) term acc) + value renames) + | Aiur.MatchCompiler.Decision.switch ptr a [(Aiur.MatchCompiler.SPattern.pointer val innerTyp, body)] a_1 => + match Aiur.MatchCompiler.decisionToTyped._unsafe_rec retTyp innerTyp body with + | none => none + | some body' => + let loadTerm := Aiur.Typed.Term.load innerTyp false (Aiur.Typed.Term.var innerTyp.pointer false ptr); + some (Aiur.Typed.Term.let body'.typ body'.escapes (Aiur.Pattern.var val) loadTerm body') + | Aiur.MatchCompiler.Decision.switch var switchTyp branches dflt => + let defaultOpt := Aiur.MatchCompiler.decisionToTyped._unsafe_rec retTyp switchTyp dflt; + do + let cases ← + List.foldlM + (fun acc x => + match x with + | ⟨(spat, tree), property⟩ => + match Aiur.MatchCompiler.sPatternToTypedPattern spat with + | none => none + | some pat => do + let body ← Aiur.MatchCompiler.decisionToTyped._unsafe_rec retTyp switchTyp tree + pure (acc.push (pat, body))) + #[] branches.attach + let casesList : List (Aiur.Pattern × Aiur.Typed.Term) := cases.toList + let casesList : List (Aiur.Pattern × Aiur.Typed.Term) := + match defaultOpt with + | some d => casesList ++ [(Aiur.Pattern.wildcard, d)] + | none => casesList + some (Aiur.Typed.Term.match retTyp false (Aiur.Typed.Term.var switchTyp false var) casesList) + | Aiur.MatchCompiler.Decision.letLoad dst dstTyp src body => + match Aiur.MatchCompiler.decisionToTyped._unsafe_rec retTyp scrutTyp body with + | none => none + | some body' => + let loadTerm := Aiur.Typed.Term.load dstTyp false (Aiur.Typed.Term.var dstTyp.pointer false src); + some (Aiur.Typed.Term.let body'.typ body'.escapes (Aiur.Pattern.var dst) loadTerm body') + | Aiur.MatchCompiler.Decision.let var term body => + match Aiur.MatchCompiler.decisionToTyped._unsafe_rec retTyp scrutTyp body with + | none => none + | some body' => some (Aiur.Typed.Term.let body'.typ body'.escapes (Aiur.Pattern.var var) term body') +RECURSION WORKER Aiur.NativeAIR.checkNodes._unsafe_rec +Aiur.NativeAIR.GraphWidths → Nat → Nat → List Aiur.NativeAIR.Node → Bool +IMPLEMENTATION +fun widths lookupEnd x x_1 => + match x, x_1 with + | x, [] => true + | index, node :: nodes => + Aiur.NativeAIR.Node.check widths lookupEnd index node && + Aiur.NativeAIR.checkNodes._unsafe_rec widths lookupEnd (index + 1) nodes +RECURSION WORKER Aiur.NativeAIR.sweepFrom._unsafe_rec +{W : Type u_1} → + Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → List Aiur.NativeAIR.Node → Array W → Option (Array W) +IMPLEMENTATION +fun {W} ops values x x_1 => + match x, x_1 with + | [], buffer => some buffer + | node :: nodes, buffer => do + let value ← Aiur.NativeAIR.Node.eval ops values buffer node + Aiur.NativeAIR.sweepFrom._unsafe_rec ops values nodes (buffer.push value) +RECURSION WORKER Aiur.NativeAIR.unfoldFrom._unsafe_rec +List Aiur.NativeAIR.Node → Array Aiur.NativeAIR.Expr → Option (Array Aiur.NativeAIR.Expr) +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], trees => some trees + | node :: nodes, trees => do + let expr ← Aiur.NativeAIR.Node.unfold trees node + Aiur.NativeAIR.unfoldFrom._unsafe_rec nodes (trees.push expr) +RECURSION WORKER Aiur.Source.inlineTopo._unsafe_rec +Std.HashMap Aiur.Global (List Aiur.Global) → + Nat → List Aiur.Global → Std.HashSet Aiur.Global → List Aiur.Global → Except String (List Aiur.Global) +IMPLEMENTATION +fun deps x x_1 x_2 x_3 => + match x, x_1, x_2, x_3 with + | 0, remaining, x, acc => + if remaining.isEmpty = true then pure acc else throw "inline recursion: dependency graph did not converge" + | rounds.succ, remaining, emitted, acc => + match remaining with + | [] => pure acc + | x => + match List.partition (fun g => (deps.getD g []).all emitted.contains) remaining with + | (ready, notReady) => + match ready with + | [] => throw (toString "inline recursion among: " ++ toString (List.map Aiur.Global.toName remaining)) + | x => + let emitted := List.foldl (fun s g => s.insert g) emitted ready; + Aiur.Source.inlineTopo._unsafe_rec deps rounds notReady emitted (acc ++ ready) +RECURSION WORKER Aiur.Typ.appendNameLimbs._unsafe_rec +Aiur.Global → Aiur.Typ → Aiur.Global +IMPLEMENTATION +fun g x => + match x with + | Aiur.Typ.field => g.pushNamespace "G" + | Aiur.Typ.u8 => g.pushNamespace "U8" + | Aiur.Typ.unit => g.pushNamespace "Unit" + | Aiur.Typ.ref g' => Aiur.Typ.appendNameLimbs.pushAll g g'.toName + | t.pointer => Aiur.Typ.appendNameLimbs._unsafe_rec (g.pushNamespace "Ptr") t + | Aiur.Typ.tuple ts => + Array.foldl + (fun acc x => + match x with + | ⟨t, property⟩ => Aiur.Typ.appendNameLimbs._unsafe_rec acc t) + (g.pushNamespace "Tup") ts.attach + | t.array n => g.pushNamespace (t.toFlatName ++ "_" ++ toString n) + | Aiur.Typ.function a a_1 => g.pushNamespace "Fn" + | Aiur.Typ.app name args => + Array.foldl + (fun acc x => + match x with + | ⟨t, property⟩ => Aiur.Typ.appendNameLimbs._unsafe_rec acc t) + (Aiur.Typ.appendNameLimbs._unsafe_rec g (Aiur.Typ.ref name)) args.attach + | Aiur.Typ.mvar id => g.pushNamespace (toString "?" ++ toString id) +RECURSION WORKER Aiur.Typ.beq._unsafe_rec +Aiur.Typ → Aiur.Typ → Bool +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | Aiur.Typ.unit, Aiur.Typ.unit => true + | Aiur.Typ.field, Aiur.Typ.field => true + | Aiur.Typ.u8, Aiur.Typ.u8 => true + | Aiur.Typ.tuple ts, Aiur.Typ.tuple ts' => + if hsz : ts.size = ts'.size then (List.finRange ts.size).all fun i => Aiur.Typ.beq._unsafe_rec ts[↑i] ts'[↑i] + else false + | t.array n, t'.array n' => Aiur.Typ.beq._unsafe_rec t t' && n == n' + | t.pointer, t'.pointer => Aiur.Typ.beq._unsafe_rec t t' + | Aiur.Typ.ref g, Aiur.Typ.ref g' => g == g' + | Aiur.Typ.app g args, Aiur.Typ.app g' args' => + g == g' && + if hsz : args.size = args'.size then + (List.finRange args.size).all fun i => Aiur.Typ.beq._unsafe_rec args[↑i] args'[↑i] + else false + | Aiur.Typ.function ins out, Aiur.Typ.function ins' out' => + Aiur.Typ.beq._unsafe_rec out out' && Aiur.Typ.beq.listBeqAux._unsafe_rec ins ins' + | Aiur.Typ.mvar n, Aiur.Typ.mvar n' => n == n' + | x, x_2 => false +RECURSION WORKER Aiur.Typ.hasPointer._unsafe_rec +Aiur.Typ → Bool +IMPLEMENTATION +fun x => + match x with + | Aiur.Typ.unit => false + | Aiur.Typ.field => false + | Aiur.Typ.u8 => false + | Aiur.Typ.ref a => false + | Aiur.Typ.mvar a => false + | a.pointer => true + | Aiur.Typ.tuple ts => + ts.attach.any fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.hasPointer._unsafe_rec t + | t.array a => Aiur.Typ.hasPointer._unsafe_rec t + | Aiur.Typ.app a args => + args.attach.any fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.hasPointer._unsafe_rec t + | Aiur.Typ.function ins out => + Aiur.Typ.hasPointer._unsafe_rec out || + ins.attach.any fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.hasPointer._unsafe_rec t +RECURSION WORKER Aiur.Typ.instantiate._unsafe_rec +(Aiur.Global → Option Aiur.Typ) → Aiur.Typ → Aiur.Typ +IMPLEMENTATION +fun subst x => + match x with + | Aiur.Typ.unit => Aiur.Typ.unit + | Aiur.Typ.field => Aiur.Typ.field + | Aiur.Typ.u8 => Aiur.Typ.u8 + | Aiur.Typ.tuple ts => + Aiur.Typ.tuple + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.instantiate._unsafe_rec subst t) + ts.attach) + | t.array n => (Aiur.Typ.instantiate._unsafe_rec subst t).array n + | t.pointer => (Aiur.Typ.instantiate._unsafe_rec subst t).pointer + | Aiur.Typ.ref g => (subst g).getD (Aiur.Typ.ref g) + | Aiur.Typ.app g args => + Aiur.Typ.app g + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.instantiate._unsafe_rec subst t) + args.attach) + | Aiur.Typ.function ins out => + Aiur.Typ.function + (List.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.instantiate._unsafe_rec subst t) + ins.attach) + (Aiur.Typ.instantiate._unsafe_rec subst out) + | Aiur.Typ.mvar n => Aiur.Typ.mvar n +RECURSION WORKER Aiur.Typ.nodeCount._unsafe_rec +Aiur.Typ → Nat +IMPLEMENTATION +fun x => + match x with + | Aiur.Typ.unit => 1 + | Aiur.Typ.field => 1 + | Aiur.Typ.u8 => 1 + | Aiur.Typ.mvar a => 1 + | Aiur.Typ.ref a => 1 + | t.pointer => 1 + Aiur.Typ.nodeCount._unsafe_rec t + | t.array a => 1 + Aiur.Typ.nodeCount._unsafe_rec t + | Aiur.Typ.tuple ts => + 1 + + Array.foldl + (fun acc x => + match x with + | ⟨t, property⟩ => acc + Aiur.Typ.nodeCount._unsafe_rec t) + 0 ts.attach + | Aiur.Typ.function ins out => + 1 + Aiur.Typ.nodeCount._unsafe_rec out + List.foldl (fun acc t => acc + Aiur.Typ.nodeCount._unsafe_rec t) 0 ins + | Aiur.Typ.app a args => + 1 + + Array.foldl + (fun acc x => + match x with + | ⟨t, property⟩ => acc + Aiur.Typ.nodeCount._unsafe_rec t) + 0 args.attach +RECURSION WORKER Aiur.Typ.toFlatName._unsafe_rec +Aiur.Typ → String +IMPLEMENTATION +fun x => + match x with + | Aiur.Typ.field => "G" + | Aiur.Typ.u8 => "U8" + | Aiur.Typ.unit => "Unit" + | Aiur.Typ.ref g => g.toName.toString false + | t.pointer => "Ptr_" ++ Aiur.Typ.toFlatName._unsafe_rec t + | Aiur.Typ.tuple ts => + "Tup_" ++ + "_".intercalate + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.toFlatName._unsafe_rec t) + ts.attach).toList + | t.array n => Aiur.Typ.toFlatName._unsafe_rec t ++ "_" ++ toString n + | Aiur.Typ.function a a_1 => "Fn" + | Aiur.Typ.app name args => + name.toName.toString false ++ "_" ++ + "_".intercalate + (Array.map + (fun x => + match x with + | ⟨t, property⟩ => Aiur.Typ.toFlatName._unsafe_rec t) + args.attach).toList + | Aiur.Typ.mvar id => toString "?" ++ toString id +RECURSION WORKER Aiur.Value.arrayDecEq._unsafe_rec +(a b : Array Aiur.Value) → Decidable (a = b) +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | { toList := as }, { toList := bs } => + match Aiur.Value.listDecEq._unsafe_rec as bs with + | isTrue h => isTrue ⋯ + | isFalse h => isFalse ⋯ +RECURSION WORKER Aiur.Value.decEq._unsafe_rec +(a b : Aiur.Value) → Decidable (a = b) +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | Aiur.Value.unit, Aiur.Value.unit => isTrue ⋯ + | Aiur.Value.field g₁, Aiur.Value.field g₂ => if h : g₁ = g₂ then isTrue ⋯ else isFalse ⋯ + | Aiur.Value.tuple vs₁, Aiur.Value.tuple vs₂ => + match Aiur.Value.arrayDecEq._unsafe_rec vs₁ vs₂ with + | isTrue h => isTrue ⋯ + | isFalse h => isFalse ⋯ + | Aiur.Value.array vs₁, Aiur.Value.array vs₂ => + match Aiur.Value.arrayDecEq._unsafe_rec vs₁ vs₂ with + | isTrue h => isTrue ⋯ + | isFalse h => isFalse ⋯ + | Aiur.Value.ctor g₁ vs₁, Aiur.Value.ctor g₂ vs₂ => + if hg : g₁ = g₂ then + match Aiur.Value.arrayDecEq._unsafe_rec vs₁ vs₂ with + | isTrue hvs => isTrue ⋯ + | isFalse hvs => isFalse ⋯ + else isFalse ⋯ + | Aiur.Value.fn g₁, Aiur.Value.fn g₂ => if h : g₁ = g₂ then isTrue ⋯ else isFalse ⋯ + | Aiur.Value.pointer w₁ n₁, Aiur.Value.pointer w₂ n₂ => + if hw : w₁ = w₂ then if hn : n₁ = n₂ then isTrue ⋯ else isFalse ⋯ else isFalse ⋯ + | Aiur.Value.unit, Aiur.Value.field a => isFalse ⋯ + | Aiur.Value.unit, Aiur.Value.tuple a => isFalse ⋯ + | Aiur.Value.unit, Aiur.Value.array a => isFalse ⋯ + | Aiur.Value.unit, Aiur.Value.ctor a a_1 => isFalse ⋯ + | Aiur.Value.unit, Aiur.Value.fn a => isFalse ⋯ + | Aiur.Value.unit, Aiur.Value.pointer width index => isFalse ⋯ + | Aiur.Value.field a, Aiur.Value.unit => isFalse ⋯ + | Aiur.Value.field a, Aiur.Value.tuple a_1 => isFalse ⋯ + | Aiur.Value.field a, Aiur.Value.array a_1 => isFalse ⋯ + | Aiur.Value.field a, Aiur.Value.ctor a_1 a_2 => isFalse ⋯ + | Aiur.Value.field a, Aiur.Value.fn a_1 => isFalse ⋯ + | Aiur.Value.field a, Aiur.Value.pointer width index => isFalse ⋯ + | Aiur.Value.tuple a, Aiur.Value.unit => isFalse ⋯ + | Aiur.Value.tuple a, Aiur.Value.field a_1 => isFalse ⋯ + | Aiur.Value.tuple a, Aiur.Value.array a_1 => isFalse ⋯ + | Aiur.Value.tuple a, Aiur.Value.ctor a_1 a_2 => isFalse ⋯ + | Aiur.Value.tuple a, Aiur.Value.fn a_1 => isFalse ⋯ + | Aiur.Value.tuple a, Aiur.Value.pointer width index => isFalse ⋯ + | Aiur.Value.array a, Aiur.Value.unit => isFalse ⋯ + | Aiur.Value.array a, Aiur.Value.field a_1 => isFalse ⋯ + | Aiur.Value.array a, Aiur.Value.tuple a_1 => isFalse ⋯ + | Aiur.Value.array a, Aiur.Value.ctor a_1 a_2 => isFalse ⋯ + | Aiur.Value.array a, Aiur.Value.fn a_1 => isFalse ⋯ + | Aiur.Value.array a, Aiur.Value.pointer width index => isFalse ⋯ + | Aiur.Value.ctor a a_1, Aiur.Value.unit => isFalse ⋯ + | Aiur.Value.ctor a a_1, Aiur.Value.field a_2 => isFalse ⋯ + | Aiur.Value.ctor a a_1, Aiur.Value.tuple a_2 => isFalse ⋯ + | Aiur.Value.ctor a a_1, Aiur.Value.array a_2 => isFalse ⋯ + | Aiur.Value.ctor a a_1, Aiur.Value.fn a_2 => isFalse ⋯ + | Aiur.Value.ctor a a_1, Aiur.Value.pointer width index => isFalse ⋯ + | Aiur.Value.fn a, Aiur.Value.unit => isFalse ⋯ + | Aiur.Value.fn a, Aiur.Value.field a_1 => isFalse ⋯ + | Aiur.Value.fn a, Aiur.Value.tuple a_1 => isFalse ⋯ + | Aiur.Value.fn a, Aiur.Value.array a_1 => isFalse ⋯ + | Aiur.Value.fn a, Aiur.Value.ctor a_1 a_2 => isFalse ⋯ + | Aiur.Value.fn a, Aiur.Value.pointer width index => isFalse ⋯ + | Aiur.Value.pointer width index, Aiur.Value.unit => isFalse ⋯ + | Aiur.Value.pointer width index, Aiur.Value.field a => isFalse ⋯ + | Aiur.Value.pointer width index, Aiur.Value.tuple a => isFalse ⋯ + | Aiur.Value.pointer width index, Aiur.Value.array a => isFalse ⋯ + | Aiur.Value.pointer width index, Aiur.Value.ctor a a_1 => isFalse ⋯ + | Aiur.Value.pointer width index, Aiur.Value.fn a => isFalse ⋯ +RECURSION WORKER Aiur.Value.hash._unsafe_rec +Aiur.Value → UInt64 +IMPLEMENTATION +fun x => + match x with + | Aiur.Value.unit => 0 + | Aiur.Value.field g => mixHash 1 (hash g) + | Aiur.Value.tuple values => + mixHash 2 (Array.foldl (fun acc value => mixHash acc (Aiur.Value.hash._unsafe_rec value.val)) 7 values.attach) + | Aiur.Value.array values => + mixHash 3 (Array.foldl (fun acc value => mixHash acc (Aiur.Value.hash._unsafe_rec value.val)) 7 values.attach) + | Aiur.Value.ctor global values => + mixHash (mixHash 4 (hash global)) + (Array.foldl (fun acc value => mixHash acc (Aiur.Value.hash._unsafe_rec value.val)) 7 values.attach) + | Aiur.Value.fn global => mixHash 5 (hash global) + | Aiur.Value.pointer width index => mixHash (mixHash 6 (hash width)) (hash index) +RECURSION WORKER Aiur.Value.listDecEq._unsafe_rec +(as bs : List Aiur.Value) → Decidable (as = bs) +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], [] => isTrue ⋯ + | [], head :: tail => isFalse ⋯ + | head :: tail, [] => isFalse ⋯ + | a :: as, b :: bs => + match Aiur.Value.decEq._unsafe_rec a b, Aiur.Value.listDecEq._unsafe_rec as bs with + | isTrue ha, isTrue ht => isTrue ⋯ + | isFalse h, x => isFalse ⋯ + | x, isFalse h => isFalse ⋯ +RECURSION WORKER Aiur.instHashableTyp.hash._unsafe_rec +Aiur.Typ → UInt64 +IMPLEMENTATION +fun x => + let localinst := { hash := Aiur.instHashableTyp.hash._unsafe_rec }; + match x with + | Aiur.Typ.unit => 0 + | Aiur.Typ.field => 1 + | Aiur.Typ.u8 => 2 + | Aiur.Typ.tuple a => mixHash 3 (hash a) + | a.array a_1 => mixHash (mixHash 4 (Aiur.instHashableTyp.hash._unsafe_rec a)) (hash a_1) + | a.pointer => mixHash 5 (Aiur.instHashableTyp.hash._unsafe_rec a) + | Aiur.Typ.ref a => mixHash 6 (hash a) + | Aiur.Typ.app a a_1 => mixHash (mixHash 7 (hash a)) (hash a_1) + | Aiur.Typ.function a a_1 => mixHash (mixHash 8 (hash a)) (Aiur.instHashableTyp.hash._unsafe_rec a_1) + | Aiur.Typ.mvar a => mixHash 9 (hash a) +RECURSION WORKER Aiur.instReprPattern.repr._unsafe_rec +Aiur.Pattern → Nat → Format +IMPLEMENTATION +fun x prec => + let localinst := { reprPrec := Aiur.instReprPattern.repr._unsafe_rec }; + match x with + | Aiur.Pattern.var a => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Pattern.var" ++ Format.line ++ reprArg a)).group + prec + | Aiur.Pattern.wildcard => + Repr.addAppParen (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Pattern.wildcard")).group prec + | Aiur.Pattern.ref a a_1 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Aiur.Pattern.ref" ++ Format.line ++ reprArg a ++ Format.line ++ reprArg a_1)).group + prec + | Aiur.Pattern.field a => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Pattern.field" ++ Format.line ++ reprArg a)).group + prec + | Aiur.Pattern.tuple a => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Pattern.tuple" ++ Format.line ++ reprArg a)).group + prec + | Aiur.Pattern.array a => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Pattern.array" ++ Format.line ++ reprArg a)).group + prec + | a.or a_1 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Aiur.Pattern.or" ++ Format.line ++ Aiur.instReprPattern.repr._unsafe_rec a 1024 ++ + Format.line ++ + Aiur.instReprPattern.repr._unsafe_rec a_1 1024)).group + prec + | a.pointer => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Aiur.Pattern.pointer" ++ Format.line ++ Aiur.instReprPattern.repr._unsafe_rec a 1024)).group + prec +RECURSION WORKER Aiur.instReprTyp.repr._unsafe_rec +Aiur.Typ → Nat → Format +IMPLEMENTATION +fun x prec => + let localinst := { reprPrec := Aiur.instReprTyp.repr._unsafe_rec }; + match x with + | Aiur.Typ.unit => + Repr.addAppParen (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Typ.unit")).group prec + | Aiur.Typ.field => + Repr.addAppParen (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Typ.field")).group prec + | Aiur.Typ.u8 => Repr.addAppParen (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Typ.u8")).group prec + | Aiur.Typ.tuple a => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Typ.tuple" ++ Format.line ++ reprArg a)).group prec + | a.array a_1 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Aiur.Typ.array" ++ Format.line ++ Aiur.instReprTyp.repr._unsafe_rec a 1024 ++ Format.line ++ + reprArg a_1)).group + prec + | a.pointer => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Aiur.Typ.pointer" ++ Format.line ++ Aiur.instReprTyp.repr._unsafe_rec a 1024)).group + prec + | Aiur.Typ.ref a => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Typ.ref" ++ Format.line ++ reprArg a)).group prec + | Aiur.Typ.app a a_1 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Aiur.Typ.app" ++ Format.line ++ reprArg a ++ Format.line ++ reprArg a_1)).group + prec + | Aiur.Typ.function a a_1 => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) + (Format.text "Aiur.Typ.function" ++ Format.line ++ reprArg a ++ Format.line ++ + Aiur.instReprTyp.repr._unsafe_rec a_1 1024)).group + prec + | Aiur.Typ.mvar a => + Repr.addAppParen + (Format.nest (if prec ≥ 1024 then 1 else 2) (Format.text "Aiur.Typ.mvar" ++ Format.line ++ reprArg a)).group prec +RECURSION WORKER Aiur.wellFormedDecls.wellFormedType._unsafe_rec +Aiur.Source.Decls → List String → Aiur.Typ → EStateM Aiur.CheckError (Std.HashSet Aiur.Global) Unit +IMPLEMENTATION +fun decls params a => + match a with + | Aiur.Typ.tuple typs => + Array.forM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.wellFormedDecls.wellFormedType._unsafe_rec decls params t) + typs.attach + | pointerTyp.pointer => Aiur.wellFormedDecls.wellFormedType._unsafe_rec decls params pointerTyp + | t.array a => Aiur.wellFormedDecls.wellFormedType._unsafe_rec decls params t + | Aiur.Typ.ref ref => + if (params.any fun x => x == ref.toName.toString) = true then pure () + else + match IndexMap.getByKey decls ref with + | some (Aiur.Source.Declaration.dataType dt) => + if dt.params.isEmpty = true then pure () else throw (Aiur.CheckError.wrongNumTypeArgs ref 0 dt.params.length) + | some val => throw (Aiur.CheckError.notADataType ref) + | none => throw (Aiur.CheckError.unboundGlobal ref) + | Aiur.Typ.app g args => + match IndexMap.getByKey decls g with + | some (Aiur.Source.Declaration.dataType dt) => + have __do_jp := fun __r => + Array.forM + (fun x => + match x with + | ⟨t, property⟩ => Aiur.wellFormedDecls.wellFormedType._unsafe_rec decls params t) + args.attach; + if (args.size == dt.params.length) = true then __do_jp () + else do + let __r ← throw (Aiur.CheckError.wrongNumTypeArgs g args.size dt.params.length) + __do_jp __r + | some val => throw (Aiur.CheckError.notADataType g) + | none => throw (Aiur.CheckError.unboundGlobal g) + | x => pure () +RECURSION WORKER Aiur.AIR.CircuitTraces.bitmap._unsafe_rec +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → List Bool +IMPLEMENTATION +fun {circuits} x => + match circuits, x with + | .([]), Aiur.AIR.CircuitTraces.nil => [] + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest => + false :: Aiur.AIR.CircuitTraces.bitmap._unsafe_rec rest + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree values rest => + true :: Aiur.AIR.CircuitTraces.bitmap._unsafe_rec rest +RECURSION WORKER Aiur.AIR.CircuitTraces.capacity._unsafe_rec +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → Nat +IMPLEMENTATION +fun {circuits} x => + match circuits, x with + | .([]), Aiur.AIR.CircuitTraces.nil => 0 + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest => + Aiur.AIR.CircuitTraces.capacity._unsafe_rec rest + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree values rest => + 2 ^ degree * circuit.layout.lookups + Aiur.AIR.CircuitTraces.capacity._unsafe_rec rest +RECURSION WORKER Aiur.AIR.CircuitTraces.degrees._unsafe_rec +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → List Nat +IMPLEMENTATION +fun {circuits} x => + match circuits, x with + | .([]), Aiur.AIR.CircuitTraces.nil => [] + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest => + Aiur.AIR.CircuitTraces.degrees._unsafe_rec rest + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree values rest => + degree :: Aiur.AIR.CircuitTraces.degrees._unsafe_rec rest +RECURSION WORKER Aiur.AIR.CircuitTraces.emitWitnesses._unsafe_rec +{circuits : List Aiur.Bytecode.Circuit} → + Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitTraces circuits → Option (List Aiur.AIR.CircuitWitness) +IMPLEMENTATION +fun {circuits} program x => + match circuits, x with + | .([]), Aiur.AIR.CircuitTraces.nil => some [] + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest => + Aiur.AIR.CircuitTraces.emitWitnesses._unsafe_rec program rest + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree values rest => do + let first ← List.mapM (Aiur.AIR.emitCircuitWitness program circuit) (List.ofFn values) + let later ← Aiur.AIR.CircuitTraces.emitWitnesses._unsafe_rec program rest + pure (first ++ later) +RECURSION WORKER Aiur.AIR.MemoryTraces.Satisfied._unsafe_rec +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → Prop +IMPLEMENTATION +fun {widths} x => + match widths, x with + | .([]), Aiur.AIR.MemoryTraces.nil => True + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest => Aiur.AIR.MemoryTraces.Satisfied._unsafe_rec rest + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest => + Aiur.AIR.MemoryMatrixSatisfied width (2 ^ degree) matrix ∧ Aiur.AIR.MemoryTraces.Satisfied._unsafe_rec rest +RECURSION WORKER Aiur.AIR.MemoryTraces.bitmap._unsafe_rec +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List Bool +IMPLEMENTATION +fun {widths} x => + match widths, x with + | .([]), Aiur.AIR.MemoryTraces.nil => [] + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest => + false :: Aiur.AIR.MemoryTraces.bitmap._unsafe_rec rest + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest => + true :: Aiur.AIR.MemoryTraces.bitmap._unsafe_rec rest +RECURSION WORKER Aiur.AIR.MemoryTraces.capacity._unsafe_rec +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → Nat +IMPLEMENTATION +fun {widths} x => + match widths, x with + | .([]), Aiur.AIR.MemoryTraces.nil => 0 + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest => Aiur.AIR.MemoryTraces.capacity._unsafe_rec rest + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest => + 2 ^ degree + Aiur.AIR.MemoryTraces.capacity._unsafe_rec rest +RECURSION WORKER Aiur.AIR.MemoryTraces.degrees._unsafe_rec +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List Nat +IMPLEMENTATION +fun {widths} x => + match widths, x with + | .([]), Aiur.AIR.MemoryTraces.nil => [] + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest => Aiur.AIR.MemoryTraces.degrees._unsafe_rec rest + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest => + degree :: Aiur.AIR.MemoryTraces.degrees._unsafe_rec rest +RECURSION WORKER Aiur.AIR.MemoryTraces.providers._unsafe_rec +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List (Aiur.AIR.Provider (List Aiur.G)) +IMPLEMENTATION +fun {widths} x => + match widths, x with + | .([]), Aiur.AIR.MemoryTraces.nil => [] + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest => Aiur.AIR.MemoryTraces.providers._unsafe_rec rest + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest => + Aiur.AIR.memoryMatrixProviders width (2 ^ degree) matrix ++ Aiur.AIR.MemoryTraces.providers._unsafe_rec rest +RECURSION WORKER Aiur.AIR.MemoryTraces.rows._unsafe_rec +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → Nat → Array Aiur.AIR.MemoryRow +IMPLEMENTATION +fun {widths} x x_1 => + match widths, x, x_1 with + | .([]), Aiur.AIR.MemoryTraces.nil, x => #[] + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest, size => + if size = width then #[] else Aiur.AIR.MemoryTraces.rows._unsafe_rec rest size + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest, size => + if size = width then Aiur.AIR.decodeMemoryRows width (2 ^ degree) matrix + else Aiur.AIR.MemoryTraces.rows._unsafe_rec rest size +RECURSION WORKER Aiur.Bytecode.Block.beq._unsafe_rec +Aiur.Bytecode.Block → Aiur.Bytecode.Block → Bool +IMPLEMENTATION +fun left right => left.ops == right.ops && Aiur.Bytecode.Ctrl.beq._unsafe_rec left.ctrl right.ctrl +RECURSION WORKER Aiur.Bytecode.Block.collectConstrainedCallees._unsafe_rec +Aiur.Bytecode.Block → Array Aiur.Bytecode.FunIdx +IMPLEMENTATION +fun b => + let opCallees := + Array.foldl + (fun acc op => + match op with + | Aiur.Bytecode.Op.call idx a outputSize false => acc.push idx + | x => acc) + #[] b.ops; + opCallees ++ Aiur.Bytecode.Ctrl.collectConstrainedCallees._unsafe_rec b.ctrl +RECURSION WORKER Aiur.Bytecode.Block.controlCounts._unsafe_rec +Aiur.Bytecode.Block → Aiur.Bytecode.ControlCounts +IMPLEMENTATION +fun block => Aiur.Bytecode.Ctrl.controlCounts._unsafe_rec block.ctrl +RECURSION WORKER Aiur.Bytecode.Block.emissionChecks._unsafe_rec +Nat → Nat → Option Nat → Aiur.Bytecode.Block → Bool +IMPLEMENTATION +fun available selectors yieldSize block => + match Aiur.Bytecode.checkEmissionOps block.ops.toList available with + | none => false + | some next => Aiur.Bytecode.Ctrl.emissionChecks._unsafe_rec next selectors yieldSize block.ctrl +RECURSION WORKER Aiur.Bytecode.Block.emitRow._unsafe_rec +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.Bytecode.Block → Option Aiur.AIR.BlockEmission +IMPLEMENTATION +fun row selector context incoming values column lookup block => do + let operations ← Aiur.AIR.emitOps row incoming context.rank block.ops.toList values column + let control ← + Aiur.Bytecode.Ctrl.emitRow._unsafe_rec row selector context incoming operations.values operations.column + (lookup + operations.queries.length) block.ctrl + pure + (Aiur.AIR.BlockEmission.prefix + [Aiur.AIR.oneSubBooleanConstraint (Aiur.Bytecode.Block.selectorFlow selector block).entry] + (Aiur.AIR.BlockEmission.afterOps incoming lookup operations control)) +RECURSION WORKER Aiur.Bytecode.Block.hash._unsafe_rec +Aiur.Bytecode.Block → UInt64 +IMPLEMENTATION +fun block => mixHash (mixHash 0 (hash block.ops)) (Aiur.Bytecode.Ctrl.hash._unsafe_rec block.ctrl) +RECURSION WORKER Aiur.Bytecode.Block.lookupShapes._unsafe_rec +Aiur.Bytecode.Toplevel → Option Nat → Aiur.Bytecode.Block → Bool +IMPLEMENTATION +fun program yieldSize block => + block.ops.all (Aiur.Bytecode.Op.lookupShape program) && + Aiur.Bytecode.Ctrl.lookupShapes._unsafe_rec program yieldSize block.ctrl +RECURSION WORKER Aiur.Bytecode.Block.lookupUsage._unsafe_rec +Aiur.Bytecode.Block → Nat +IMPLEMENTATION +fun block => + (List.map Aiur.Bytecode.Op.lookupUsage block.ops.toList).sum + Aiur.Bytecode.Ctrl.lookupUsage._unsafe_rec block.ctrl +RECURSION WORKER Aiur.Bytecode.Block.returnGates._unsafe_rec +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.G → Aiur.Bytecode.Block → List Aiur.G +IMPLEMENTATION +fun selector incoming block => Aiur.Bytecode.Ctrl.returnGates._unsafe_rec selector incoming block.ctrl +RECURSION WORKER Aiur.Bytecode.Block.returnsHaveSize._unsafe_rec +Nat → Aiur.Bytecode.Block → Bool +IMPLEMENTATION +fun size block => Aiur.Bytecode.Ctrl.returnsHaveSize._unsafe_rec size block.ctrl +RECURSION WORKER Aiur.Bytecode.Block.rowBounds._unsafe_rec +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Block → Prop +IMPLEMENTATION +fun selector block => Aiur.Bytecode.Ctrl.rowBounds._unsafe_rec selector block.ctrl +RECURSION WORKER Aiur.Bytecode.Block.selectorFlow._unsafe_rec +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Block → Aiur.AIR.SelectorFlow +IMPLEMENTATION +fun selector block => Aiur.Bytecode.Ctrl.selectorFlow._unsafe_rec selector block.ctrl +RECURSION WORKER Aiur.Bytecode.Ctrl.beq._unsafe_rec +Aiur.Bytecode.Ctrl → Aiur.Bytecode.Ctrl → Bool +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | Aiur.Bytecode.Ctrl.match idx cases fallback, Aiur.Bytecode.Ctrl.match idx' cases' fallback' => + idx == idx' && + (Aiur.Bytecode.beqBranches._unsafe_rec cases cases' && Aiur.Bytecode.beqFallback._unsafe_rec fallback fallback') + | Aiur.Bytecode.Ctrl.return sel outs, Aiur.Bytecode.Ctrl.return sel' outs' => sel == sel' && outs == outs' + | Aiur.Bytecode.Ctrl.yield sel outs, Aiur.Bytecode.Ctrl.yield sel' outs' => sel == sel' && outs == outs' + | Aiur.Bytecode.Ctrl.matchContinue idx cases fallback outputs aux lookups cont, + Aiur.Bytecode.Ctrl.matchContinue idx' cases' fallback' outputs' aux' lookups' cont' => + idx == idx' && + (Aiur.Bytecode.beqBranches._unsafe_rec cases cases' && + (Aiur.Bytecode.beqFallback._unsafe_rec fallback fallback' && + (outputs == outputs' && + (aux == aux' && (lookups == lookups' && Aiur.Bytecode.Block.beq._unsafe_rec cont cont'))))) + | x, x_2 => false +RECURSION WORKER Aiur.Bytecode.Ctrl.collectConstrainedCallees._unsafe_rec +Aiur.Bytecode.Ctrl → Array Aiur.Bytecode.FunIdx +IMPLEMENTATION +fun c => + match c with + | Aiur.Bytecode.Ctrl.match a cases default? => + let branchCallees := + Array.foldl + (fun acc x => + match x with + | ⟨(fst, block), property⟩ => acc ++ Aiur.Bytecode.Block.collectConstrainedCallees._unsafe_rec block) + #[] cases.attach; + match default? with + | some block => branchCallees ++ Aiur.Bytecode.Block.collectConstrainedCallees._unsafe_rec block + | none => branchCallees + | Aiur.Bytecode.Ctrl.matchContinue a cases default? outputSize sharedAuxiliaries sharedLookups continuation => + let branchCallees := + Array.foldl + (fun acc x => + match x with + | ⟨(fst, block), property⟩ => acc ++ Aiur.Bytecode.Block.collectConstrainedCallees._unsafe_rec block) + #[] cases.attach; + let withDefault := + match default? with + | some block => branchCallees ++ Aiur.Bytecode.Block.collectConstrainedCallees._unsafe_rec block + | none => branchCallees; + withDefault ++ Aiur.Bytecode.Block.collectConstrainedCallees._unsafe_rec continuation + | Aiur.Bytecode.Ctrl.return a a_1 => #[] + | Aiur.Bytecode.Ctrl.yield a a_1 => #[] +RECURSION WORKER Aiur.Bytecode.Ctrl.controlCounts._unsafe_rec +Aiur.Bytecode.Ctrl → Aiur.Bytecode.ControlCounts +IMPLEMENTATION +fun x => + match x with + | Aiur.Bytecode.Ctrl.return a a_1 => { nodes := 1, leaves := 1, returns := 1, yields := 0 } + | Aiur.Bytecode.Ctrl.yield a a_1 => { nodes := 1, leaves := 1, returns := 0, yields := 1 } + | Aiur.Bytecode.Ctrl.match a branches fallback => + Aiur.Bytecode.ControlCounts.branch + (List.map + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.Bytecode.Block.controlCounts._unsafe_rec pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => [Aiur.Bytecode.Block.controlCounts._unsafe_rec block]) + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups continuation => + (Aiur.Bytecode.ControlCounts.branch + (List.map + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.Bytecode.Block.controlCounts._unsafe_rec pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => [Aiur.Bytecode.Block.controlCounts._unsafe_rec block])).continue + (Aiur.Bytecode.Block.controlCounts._unsafe_rec continuation) +RECURSION WORKER Aiur.Bytecode.Ctrl.emissionChecks._unsafe_rec +Nat → Nat → Option Nat → Aiur.Bytecode.Ctrl → Bool +IMPLEMENTATION +fun available selectors yieldSize x => + match x with + | Aiur.Bytecode.Ctrl.return index outputs => + decide (index < selectors) && Aiur.Bytecode.indicesInScope available outputs + | Aiur.Bytecode.Ctrl.yield index outputs => + decide (index < selectors) && (Aiur.Bytecode.indicesInScope available outputs && yieldSize == some outputs.size) + | Aiur.Bytecode.Ctrl.match index branches fallback => + decide (index < available) && + ((branches.attach.all fun x => + match x with + | ⟨(fst, block), property⟩ => + Aiur.Bytecode.Block.emissionChecks._unsafe_rec available selectors yieldSize block) && + match fallback with + | none => true + | some block => Aiur.Bytecode.Block.emissionChecks._unsafe_rec available selectors yieldSize block) + | Aiur.Bytecode.Ctrl.matchContinue index branches fallback size sharedAuxiliaries sharedLookups continuation => + decide (index < available) && + ((branches.attach.all fun x => + match x with + | ⟨(fst, block), property⟩ => + Aiur.Bytecode.Block.emissionChecks._unsafe_rec available selectors (some size) block) && + ((match fallback with + | none => true + | some block => Aiur.Bytecode.Block.emissionChecks._unsafe_rec available selectors (some size) block) && + match Aiur.Bytecode.addScope available size with + | none => false + | some next => Aiur.Bytecode.Block.emissionChecks._unsafe_rec next selectors yieldSize continuation)) +RECURSION WORKER Aiur.Bytecode.Ctrl.emitRow._unsafe_rec +(Nat → Aiur.G) → + (Aiur.Bytecode.SelIdx → Aiur.G) → + Aiur.AIR.RowContext → + Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.Bytecode.Ctrl → Option Aiur.AIR.BlockEmission +IMPLEMENTATION +fun row selector context incoming values column lookup x => + match x with + | Aiur.Bytecode.Ctrl.return a indices => do + let inputs ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) (Array.range context.inputSize) + let outputs ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) indices + pure + { values := values, column := column, lookup := lookup, + returns := + [(incoming, { function := context.function, inputs := inputs, outputs := outputs, rank := context.rank })] } + | Aiur.Bytecode.Ctrl.yield index indices => do + let outputs ← List.mapM (fun index => values[index]?) indices.toList + pure { values := values, column := column, lookup := lookup, yields := [(selector index, outputs.toArray)] } + | Aiur.Bytecode.Ctrl.match index branches fallback => do + let matched ← values[index]? + let cases ← + List.mapM + (fun x => + match x with + | ⟨pair, property⟩ => + let entry := (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry; + do + let emission ← + Aiur.Bytecode.Block.emitRow._unsafe_rec row selector context entry values column lookup pair.snd + pure (Aiur.AIR.BlockEmission.prefix [entry * (matched.value - pair.fst)] emission)) + branches.attach.toList + have __do_jp : List Aiur.AIR.BlockEmission → Option Aiur.AIR.BlockEmission := fun default => + pure (Aiur.AIR.joinBlockEmissions values column lookup (cases ++ default)) + match fallback with + | none => do + let default ← some [] + __do_jp default + | some block => + let entry := (Aiur.Bytecode.Block.selectorFlow selector block).entry; + do + let emission ← + Aiur.Bytecode.Block.emitRow._unsafe_rec row selector context entry values (column + branches.size) lookup + block + let default ← + pure + [Aiur.AIR.BlockEmission.prefix + (List.mapIdx (fun i pair => entry * ((matched.value - pair.fst) * row (column + i) - 1)) + branches.toList) + emission] + __do_jp default + | Aiur.Bytecode.Ctrl.matchContinue index branches fallback size sharedAuxiliaries sharedLookups continuation => do + let matched ← values[index]? + let cases ← + List.mapM + (fun x => + match x with + | ⟨pair, property⟩ => + let entry := (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry; + do + let emission ← + Aiur.Bytecode.Block.emitRow._unsafe_rec row selector context entry values column lookup pair.snd + pure (Aiur.AIR.BlockEmission.prefix [entry * (matched.value - pair.fst)] emission)) + branches.attach.toList + have __do_jp : List Aiur.AIR.BlockEmission → Option Aiur.AIR.BlockEmission := fun default => + let joined := Aiur.AIR.joinBlockEmissions values column lookup (cases ++ default); + if (joined.yields.all fun part => part.snd.size == size) = true then + let gate := Aiur.AIR.selectorSum (List.map Prod.fst joined.yields); + let merged := Aiur.AIR.rowAdvice row joined.column size; + let equations := + Aiur.AIR.mergeEquations row incoming joined.column size joined.yields ++ + [(Aiur.Bytecode.Block.selectorFlow selector continuation).entry - gate]; + do + let continued ← + Aiur.Bytecode.Block.emitRow._unsafe_rec row selector context gate (values ++ merged) (joined.column + size) + joined.lookup continuation + pure (joined.continued equations continued) + else none + match fallback with + | none => do + let default ← some [] + __do_jp default + | some block => + let entry := (Aiur.Bytecode.Block.selectorFlow selector block).entry; + do + let emission ← + Aiur.Bytecode.Block.emitRow._unsafe_rec row selector context entry values (column + branches.size) lookup + block + let default ← + pure + [Aiur.AIR.BlockEmission.prefix + (List.mapIdx (fun i pair => entry * ((matched.value - pair.fst) * row (column + i) - 1)) + branches.toList) + emission] + __do_jp default +RECURSION WORKER Aiur.Bytecode.Ctrl.hash._unsafe_rec +Aiur.Bytecode.Ctrl → UInt64 +IMPLEMENTATION +fun x => + match x with + | Aiur.Bytecode.Ctrl.match idx branches fallback => + let branchesHash := + Array.foldl + (fun acc pair => mixHash acc (mixHash (hash pair.val.fst) (Aiur.Bytecode.Block.hash._unsafe_rec pair.val.snd))) + 7 branches.attach; + let fallbackHash := + match fallback with + | none => 11 + | some block => mixHash (Aiur.Bytecode.Block.hash._unsafe_rec block) 13; + mixHash (mixHash (mixHash 0 (hash idx)) branchesHash) fallbackHash + | Aiur.Bytecode.Ctrl.return sel outs => mixHash (mixHash 1 (hash sel)) (hash outs) + | Aiur.Bytecode.Ctrl.yield sel outs => mixHash (mixHash 2 (hash sel)) (hash outs) + | Aiur.Bytecode.Ctrl.matchContinue idx branches fallback outputs aux lookups cont => + let branchesHash := + Array.foldl + (fun acc pair => mixHash acc (mixHash (hash pair.val.fst) (Aiur.Bytecode.Block.hash._unsafe_rec pair.val.snd))) + 7 branches.attach; + let fallbackHash := + match fallback with + | none => 11 + | some block => mixHash (Aiur.Bytecode.Block.hash._unsafe_rec block) 13; + mixHash + (mixHash + (mixHash (mixHash (mixHash (mixHash (mixHash 3 (hash idx)) branchesHash) fallbackHash) (hash outputs)) + (hash aux)) + (hash lookups)) + (Aiur.Bytecode.Block.hash._unsafe_rec cont) +RECURSION WORKER Aiur.Bytecode.Ctrl.lookupShapes._unsafe_rec +Aiur.Bytecode.Toplevel → Option Nat → Aiur.Bytecode.Ctrl → Bool +IMPLEMENTATION +fun program yieldSize x => + match x with + | Aiur.Bytecode.Ctrl.return a a_1 => true + | Aiur.Bytecode.Ctrl.yield a values => yieldSize == some values.size + | Aiur.Bytecode.Ctrl.match a branches fallback => + (branches.attach.all fun x => + match x with + | ⟨(fst, block), property⟩ => Aiur.Bytecode.Block.lookupShapes._unsafe_rec program yieldSize block) && + match fallback with + | none => true + | some block => Aiur.Bytecode.Block.lookupShapes._unsafe_rec program yieldSize block + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback size sharedAuxiliaries sharedLookups continuation => + (branches.attach.all fun x => + match x with + | ⟨(fst, block), property⟩ => Aiur.Bytecode.Block.lookupShapes._unsafe_rec program (some size) block) && + ((match fallback with + | none => true + | some block => Aiur.Bytecode.Block.lookupShapes._unsafe_rec program (some size) block) && + Aiur.Bytecode.Block.lookupShapes._unsafe_rec program yieldSize continuation) +RECURSION WORKER Aiur.Bytecode.Ctrl.lookupUsage._unsafe_rec +Aiur.Bytecode.Ctrl → Nat +IMPLEMENTATION +fun x => + match x with + | Aiur.Bytecode.Ctrl.return a a_1 => 0 + | Aiur.Bytecode.Ctrl.yield a a_1 => 0 + | Aiur.Bytecode.Ctrl.match a branches fallback => + List.foldl Nat.max 0 + (List.map + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.Bytecode.Block.lookupUsage._unsafe_rec pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => [Aiur.Bytecode.Block.lookupUsage._unsafe_rec block]) + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups continuation => + List.foldl Nat.max 0 + (List.map + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.Bytecode.Block.lookupUsage._unsafe_rec pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => [Aiur.Bytecode.Block.lookupUsage._unsafe_rec block]) + + Aiur.Bytecode.Block.lookupUsage._unsafe_rec continuation +RECURSION WORKER Aiur.Bytecode.Ctrl.returnGates._unsafe_rec +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.G → Aiur.Bytecode.Ctrl → List Aiur.G +IMPLEMENTATION +fun selector incoming x => + match x with + | Aiur.Bytecode.Ctrl.return a a_1 => [incoming] + | Aiur.Bytecode.Ctrl.yield a a_1 => [] + | Aiur.Bytecode.Ctrl.match a branches fallback => + List.flatMap + (fun x => + match x with + | ⟨pair, property⟩ => + Aiur.Bytecode.Block.returnGates._unsafe_rec selector + (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => + Aiur.Bytecode.Block.returnGates._unsafe_rec selector (Aiur.Bytecode.Block.selectorFlow selector block).entry + block + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups continuation => + (List.flatMap + (fun x => + match x with + | ⟨pair, property⟩ => + Aiur.Bytecode.Block.returnGates._unsafe_rec selector + (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => + Aiur.Bytecode.Block.returnGates._unsafe_rec selector (Aiur.Bytecode.Block.selectorFlow selector block).entry + block) ++ + Aiur.Bytecode.Block.returnGates._unsafe_rec selector + (Aiur.AIR.selectorSum + (Aiur.AIR.SelectorFlow.join (Aiur.Bytecode.branchSelectorFlows selector branches fallback)).yields) + continuation +RECURSION WORKER Aiur.Bytecode.Ctrl.returnsHaveSize._unsafe_rec +Nat → Aiur.Bytecode.Ctrl → Bool +IMPLEMENTATION +fun size x => + match x with + | Aiur.Bytecode.Ctrl.return a values => values.size == size + | Aiur.Bytecode.Ctrl.yield a a_1 => true + | Aiur.Bytecode.Ctrl.match a branches fallback => + (branches.attach.all fun x => + match x with + | ⟨(fst, block), property⟩ => Aiur.Bytecode.Block.returnsHaveSize._unsafe_rec size block) && + match fallback with + | none => true + | some block => Aiur.Bytecode.Block.returnsHaveSize._unsafe_rec size block + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups continuation => + (branches.attach.all fun x => + match x with + | ⟨(fst, block), property⟩ => Aiur.Bytecode.Block.returnsHaveSize._unsafe_rec size block) && + ((match fallback with + | none => true + | some block => Aiur.Bytecode.Block.returnsHaveSize._unsafe_rec size block) && + Aiur.Bytecode.Block.returnsHaveSize._unsafe_rec size continuation) +RECURSION WORKER Aiur.Bytecode.Ctrl.rowBounds._unsafe_rec +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Ctrl → Prop +IMPLEMENTATION +fun selector x => + match x with + | Aiur.Bytecode.Ctrl.return a a_1 => True + | Aiur.Bytecode.Ctrl.yield a a_1 => True + | Aiur.Bytecode.Ctrl.match a branches fallback => + branches.size + fallback.toList.length < Aiur.gSize.toNat ∧ + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → Aiur.Bytecode.Block.rowBounds._unsafe_rec selector pair.snd) ∧ + match fallback with + | none => True + | some block => Aiur.Bytecode.Block.rowBounds._unsafe_rec selector block + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups continuation => + let flow := Aiur.AIR.SelectorFlow.join (Aiur.Bytecode.branchSelectorFlows selector branches fallback); + branches.size + fallback.toList.length < Aiur.gSize.toNat ∧ + flow.returns.length + flow.yields.length < Aiur.gSize.toNat ∧ + (∀ (pair : Aiur.G × Aiur.Bytecode.Block), + pair ∈ branches.toList → Aiur.Bytecode.Block.rowBounds._unsafe_rec selector pair.snd) ∧ + (match fallback with + | none => True + | some block => Aiur.Bytecode.Block.rowBounds._unsafe_rec selector block) ∧ + Aiur.Bytecode.Block.rowBounds._unsafe_rec selector continuation +RECURSION WORKER Aiur.Bytecode.Ctrl.selectorFlow._unsafe_rec +(Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.Ctrl → Aiur.AIR.SelectorFlow +IMPLEMENTATION +fun selector x => + match x with + | Aiur.Bytecode.Ctrl.return index a => + { entry := selector index, returns := [selector index], yields := [], equations := [] }.guard + | Aiur.Bytecode.Ctrl.yield index a => + { entry := selector index, returns := [], yields := [selector index], equations := [] }.guard + | Aiur.Bytecode.Ctrl.match a branches fallback => + (Aiur.AIR.SelectorFlow.join + (List.map + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.Bytecode.Block.selectorFlow._unsafe_rec selector pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => [Aiur.Bytecode.Block.selectorFlow._unsafe_rec selector block])).guard + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups continuation => + ((Aiur.AIR.SelectorFlow.join + (List.map + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.Bytecode.Block.selectorFlow._unsafe_rec selector pair.snd) + branches.attach.toList ++ + match fallback with + | none => [] + | some block => [Aiur.Bytecode.Block.selectorFlow._unsafe_rec selector block])).continue + (Aiur.Bytecode.Block.selectorFlow._unsafe_rec selector continuation)).guard +RECURSION WORKER Aiur.Bytecode.Eval.buildLimbChain._unsafe_rec +Aiur.Bytecode.Eval.EvalState → List (Array Aiur.G) → Aiur.Bytecode.Eval.EvalState × Nat +IMPLEMENTATION +fun st x => + match x with + | [] => Aiur.Bytecode.Eval.memStore st (#[1] ++ Array.replicate 9 0) + | limb :: rest => + match Aiur.Bytecode.Eval.buildLimbChain._unsafe_rec st rest with + | (st', restPtr) => Aiur.Bytecode.Eval.memStore st' (#[0] ++ limb ++ #[Aiur.G.ofNat restPtr]) +RECURSION WORKER Aiur.Bytecode.Eval.evalBlock._unsafe_rec +Aiur.Bytecode.Toplevel → + Nat → + Aiur.Bytecode.Block → + Aiur.Bytecode.Eval.EvalState → + Except Aiur.Bytecode.Eval.BytecodeError (Array Aiur.G × Aiur.Bytecode.Eval.EvalState) +IMPLEMENTATION +fun t fuel b st => + match Aiur.Bytecode.Eval.runOps._unsafe_rec t fuel b.ops st 0 with + | Except.error e => Except.error e + | Except.ok st' => Aiur.Bytecode.Eval.evalCtrl._unsafe_rec t fuel b.ctrl st' +RECURSION WORKER Aiur.Bytecode.Eval.evalCtrl._unsafe_rec +Aiur.Bytecode.Toplevel → + Nat → + Aiur.Bytecode.Ctrl → + Aiur.Bytecode.Eval.EvalState → + Except Aiur.Bytecode.Eval.BytecodeError (Array Aiur.G × Aiur.Bytecode.Eval.EvalState) +IMPLEMENTATION +fun t fuel ctrl st => + match ctrl with + | Aiur.Bytecode.Ctrl.return a outs => + match Aiur.Bytecode.Eval.readIdxs st outs with + | Except.error e => Except.error e + | Except.ok gs => Except.error (Aiur.Bytecode.Eval.BytecodeError.earlyReturn gs st) + | Aiur.Bytecode.Ctrl.yield a outs => + match Aiur.Bytecode.Eval.readIdxs st outs with + | Except.error e => Except.error e + | Except.ok gs => Except.ok (gs, st) + | Aiur.Bytecode.Ctrl.match scrutIdx cases defaultBlock => + match Aiur.Bytecode.Eval.readIdx st scrutIdx with + | Except.error e => Except.error e + | Except.ok scrut => Aiur.Bytecode.Eval.evalMatchArm._unsafe_rec t fuel cases defaultBlock scrut st + | Aiur.Bytecode.Ctrl.matchContinue scrutIdx cases defaultBlock _outputSize _sharedAux _sharedLookups cont => + match Aiur.Bytecode.Eval.readIdx st scrutIdx with + | Except.error e => Except.error e + | Except.ok scrut => + match Aiur.Bytecode.Eval.evalMatchArm._unsafe_rec t fuel cases defaultBlock scrut st with + | Except.error e => Except.error e + | Except.ok (gs, st') => + let stMerged := { map := st.map ++ gs, memory := st'.memory, ioBuffer := st'.ioBuffer }; + Aiur.Bytecode.Eval.evalBlock._unsafe_rec t fuel cont stMerged +RECURSION WORKER Aiur.Bytecode.Eval.evalDefaultBlock._unsafe_rec +Aiur.Bytecode.Toplevel → + Nat → + Option Aiur.Bytecode.Block → + Aiur.Bytecode.Eval.EvalState → + Except Aiur.Bytecode.Eval.BytecodeError (Array Aiur.G × Aiur.Bytecode.Eval.EvalState) +IMPLEMENTATION +fun t fuel defaultBlock st => + match defaultBlock with + | some block => Aiur.Bytecode.Eval.evalBlock._unsafe_rec t fuel block st + | none => Except.error Aiur.Bytecode.Eval.BytecodeError.unreachableAfterLayout +RECURSION WORKER Aiur.Bytecode.Eval.evalMatchArm._unsafe_rec +Aiur.Bytecode.Toplevel → + Nat → + Array (Aiur.G × Aiur.Bytecode.Block) → + Option Aiur.Bytecode.Block → + Aiur.G → + Aiur.Bytecode.Eval.EvalState → + optParam Nat 0 → Except Aiur.Bytecode.Eval.BytecodeError (Array Aiur.G × Aiur.Bytecode.Eval.EvalState) +IMPLEMENTATION +fun t fuel cases defaultBlock scrut st i => + if h : i < cases.size then + if (cases[i].fst == scrut) = true then Aiur.Bytecode.Eval.evalBlock._unsafe_rec t fuel cases[i].snd st + else Aiur.Bytecode.Eval.evalMatchArm._unsafe_rec t fuel cases defaultBlock scrut st (i + 1) + else Aiur.Bytecode.Eval.evalDefaultBlock._unsafe_rec t fuel defaultBlock st +RECURSION WORKER Aiur.Bytecode.Eval.evalOp._unsafe_rec +Aiur.Bytecode.Toplevel → + Nat → + Aiur.Bytecode.Op → + Aiur.Bytecode.Eval.EvalState → Except Aiur.Bytecode.Eval.BytecodeError Aiur.Bytecode.Eval.EvalState +IMPLEMENTATION +fun t fuel op st => + match op with + | Aiur.Bytecode.Op.const g => Except.ok (Aiur.Bytecode.Eval.pushMap st g) + | Aiur.Bytecode.Op.add a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (x + y)) + | Aiur.Bytecode.Op.sub a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (x - y)) + | Aiur.Bytecode.Op.mul a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (x * y)) + | Aiur.Bytecode.Op.eqZero a => do + let x ← Aiur.Bytecode.Eval.readIdx st a + pure (Aiur.Bytecode.Eval.pushMap st (if (x.val == 0) = true then 1 else 0)) + | Aiur.Bytecode.Op.call fi args outputSize _unconstrained => do + let argGs ← Aiur.Bytecode.Eval.readIdxs st args + if h : fi < t.functions.size then + let f := t.functions[fi]; + if (f.layout.inputSize != argGs.size) = true then + Except.error (Aiur.Bytecode.Eval.BytecodeError.arityMismatch fi) + else + let innerSt := { map := argGs, memory := st.memory, ioBuffer := st.ioBuffer }; + match fuel with + | 0 => Except.error Aiur.Bytecode.Eval.BytecodeError.outOfFuel + | fuel.succ => + match Aiur.Bytecode.Eval.evalBlock._unsafe_rec t fuel f.body innerSt with + | Except.error (Aiur.Bytecode.Eval.BytecodeError.earlyReturn outs innerSt') => + if (outs.size != outputSize) = true then + Except.error Aiur.Bytecode.Eval.BytecodeError.callOutputSizeMismatch + else + pure + (Aiur.Bytecode.Eval.appendMap + (Aiur.Bytecode.Eval.setIoBuffer + { map := st.map, memory := innerSt'.memory, ioBuffer := st.ioBuffer } innerSt'.ioBuffer) + outs) + | Except.ok (outs, innerSt') => + if (outs.size != outputSize) = true then + Except.error Aiur.Bytecode.Eval.BytecodeError.callOutputSizeMismatch + else + pure + (Aiur.Bytecode.Eval.appendMap + (Aiur.Bytecode.Eval.setIoBuffer + { map := st.map, memory := innerSt'.memory, ioBuffer := st.ioBuffer } innerSt'.ioBuffer) + outs) + | Except.error e => Except.error e + else Except.error (Aiur.Bytecode.Eval.BytecodeError.invalidFunIdx fi) + | Aiur.Bytecode.Op.store vals => do + let argGs ← Aiur.Bytecode.Eval.readIdxs st vals + match Aiur.Bytecode.Eval.memStore st argGs with + | (st', idx) => pure (Aiur.Bytecode.Eval.pushMap st' (Aiur.G.ofNat idx)) + | Aiur.Bytecode.Op.load size ptr => do + let ptrG ← Aiur.Bytecode.Eval.readIdx st ptr + let vs ← Aiur.Bytecode.Eval.memLoad st size ptrG.val.toNat + pure (Aiur.Bytecode.Eval.appendMap st vs) + | Aiur.Bytecode.Op.assertEq as bs a => do + let aGs ← Aiur.Bytecode.Eval.readIdxs st as + let bGs ← Aiur.Bytecode.Eval.readIdxs st bs + if (aGs == bGs) = true then Except.ok st else Except.error Aiur.Bytecode.Eval.BytecodeError.assertFailed + | Aiur.Bytecode.Op.ioGetInfo channelIdx keyIdxs => do + let channelG ← Aiur.Bytecode.Eval.readIdx st channelIdx + let keyGs ← Aiur.Bytecode.Eval.readIdxs st keyIdxs + match st.ioBuffer.map[(channelG, keyGs)]? with + | some info => + let st1 := Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofNat info.idx); + pure (Aiur.Bytecode.Eval.pushMap st1 (Aiur.G.ofNat info.len)) + | none => Except.error Aiur.Bytecode.Eval.BytecodeError.ioKeyNotFound + | Aiur.Bytecode.Op.ioSetInfo channelIdx keyIdxs idxIdx lenIdx => do + let channelG ← Aiur.Bytecode.Eval.readIdx st channelIdx + let keyGs ← Aiur.Bytecode.Eval.readIdxs st keyIdxs + let iG ← Aiur.Bytecode.Eval.readIdx st idxIdx + let lG ← Aiur.Bytecode.Eval.readIdx st lenIdx + if st.ioBuffer.map.contains (channelG, keyGs) = true then + Except.error Aiur.Bytecode.Eval.BytecodeError.ioKeyAlreadySet + else + let info := { idx := iG.val.toNat, len := lG.val.toNat }; + let newMap := st.ioBuffer.map.insert (channelG, keyGs) info; + pure + (Aiur.Bytecode.Eval.setIoBuffer st + (let __src := st.ioBuffer; + { data := __src.data, map := newMap })) + | Aiur.Bytecode.Op.ioRead channelIdx idxIdx len => do + let channelG ← Aiur.Bytecode.Eval.readIdx st channelIdx + let iG ← Aiur.Bytecode.Eval.readIdx st idxIdx + let start : Nat := iG.val.toNat + let arena : Array Aiur.G := st.ioBuffer.data.getD channelG #[] + if start + len > arena.size then Except.error Aiur.Bytecode.Eval.BytecodeError.ioReadOoB + else pure (Aiur.Bytecode.Eval.appendMap st (arena.extract start (start + len))) + | Aiur.Bytecode.Op.ioWrite channelIdx dataIdxs => do + let channelG ← Aiur.Bytecode.Eval.readIdx st channelIdx + let dataGs ← Aiur.Bytecode.Eval.readIdxs st dataIdxs + let arena : Array Aiur.G := st.ioBuffer.data.getD channelG #[] + let newData : Std.HashMap Aiur.G (Array Aiur.G) := st.ioBuffer.data.insert channelG (arena ++ dataGs) + pure + (Aiur.Bytecode.Eval.setIoBuffer st + (let __src := st.ioBuffer; + { data := newData, map := __src.map })) + | Aiur.Bytecode.Op.u8BitDecomposition idx => do + let g ← Aiur.Bytecode.Eval.readIdx st idx + let byte : UInt8 := g.val.toUInt8 + let bits : Array Aiur.G := Array.ofFn fun i => Aiur.G.ofUInt8 (byte >>> (↑i).toUInt8 &&& 1) + pure (Aiur.Bytecode.Eval.appendMap st bits) + | Aiur.Bytecode.Op.u8ShiftLeft idx => do + let g ← Aiur.Bytecode.Eval.readIdx st idx + pure (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (g.val.toUInt8 <<< 1))) + | Aiur.Bytecode.Op.u8ShiftRight idx => do + let g ← Aiur.Bytecode.Eval.readIdx st idx + pure (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (g.val.toUInt8 >>> 1))) + | Aiur.Bytecode.Op.u8Xor a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (x.val.toUInt8 ^^^ y.val.toUInt8))) + | Aiur.Bytecode.Op.u8Add a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + let sum : Nat := x.val.toUInt8.toNat + y.val.toUInt8.toNat + let st1 : Aiur.Bytecode.Eval.EvalState := Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 sum.toUInt8) + pure (Aiur.Bytecode.Eval.pushMap st1 (if sum ≥ 256 then 1 else 0)) + | Aiur.Bytecode.Op.u8Mul a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + let prod : Nat := x.val.toUInt8.toNat * y.val.toUInt8.toNat + let st1 : Aiur.Bytecode.Eval.EvalState := Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 prod.toUInt8) + pure (Aiur.Bytecode.Eval.pushMap st1 (Aiur.G.ofUInt8 (prod / 256).toUInt8)) + | Aiur.Bytecode.Op.u8XorSplit7 a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + let z : UInt8 := x.val.toUInt8 ^^^ y.val.toUInt8 + pure + (Aiur.Bytecode.Eval.pushMap (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (z >>> 7))) + (Aiur.G.ofUInt8 (z <<< 1))) + | Aiur.Bytecode.Op.u8XorSplit4 a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + let z : UInt8 := x.val.toUInt8 ^^^ y.val.toUInt8 + pure + (Aiur.Bytecode.Eval.pushMap (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (z >>> 4))) + (Aiur.G.ofUInt8 (z <<< 4))) + | Aiur.Bytecode.Op.u8Sub a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + let i : UInt8 := x.val.toUInt8 + let j : UInt8 := y.val.toUInt8 + let st1 : Aiur.Bytecode.Eval.EvalState := Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (i - j)) + pure (Aiur.Bytecode.Eval.pushMap st1 (if j > i then 1 else 0)) + | Aiur.Bytecode.Op.u8And a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (x.val.toUInt8 &&& y.val.toUInt8))) + | Aiur.Bytecode.Op.u8Or a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofUInt8 (x.val.toUInt8 ||| y.val.toUInt8))) + | Aiur.Bytecode.Op.u8LessThan a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (if x.val.toUInt8 < y.val.toUInt8 then 1 else 0)) + | Aiur.Bytecode.Op.u32LessThan a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + pure (Aiur.Bytecode.Eval.pushMap st (if x.val.toUInt32 < y.val.toUInt32 then 1 else 0)) + | Aiur.Bytecode.Op.unconstrainedU32Add a b => + let pack := fun idxs => + List.foldl + (fun n x => + match x with + | (idx, i) => n + (st.map[idx]?.getD 0).val.toNat * 256 ^ i) + 0 idxs.toList.zipIdx; + let sum := pack a + pack b; + let bytes := Array.map (fun i => Aiur.G.ofNat (sum / 256 ^ i % 256)) #[0, 1, 2, 3]; + pure (Aiur.Bytecode.Eval.pushMap (Aiur.Bytecode.Eval.appendMap st bytes) (Aiur.G.ofNat (sum / 4294967296))) + | Aiur.Bytecode.Op.unconstrainedU32Add3 a b c => + let pack := fun idxs => + List.foldl + (fun n x => + match x with + | (idx, i) => n + (st.map[idx]?.getD 0).val.toNat * 256 ^ i) + 0 idxs.toList.zipIdx; + let sum := pack a + pack b + pack c; + let bytes := Array.map (fun i => Aiur.G.ofNat (sum / 256 ^ i % 256)) #[0, 1, 2, 3]; + pure (Aiur.Bytecode.Eval.pushMap (Aiur.Bytecode.Eval.appendMap st bytes) (Aiur.G.ofNat (sum / 4294967296))) + | Aiur.Bytecode.Op.u32ToField bytes => + let word := + List.foldl + (fun n x => + match x with + | (idx, i) => n + (st.map[idx]?.getD 0).val.toNat * 256 ^ i) + 0 bytes.toList.zipIdx; + pure (Aiur.Bytecode.Eval.pushMap st (Aiur.G.ofNat word)) + | Aiur.Bytecode.Op.u8RangeCheck a b => do + let x ← Aiur.Bytecode.Eval.readIdx st a + let y ← Aiur.Bytecode.Eval.readIdx st b + if (decide (x.val < 256) && decide (y.val < 256)) = true then Except.ok st + else Except.error Aiur.Bytecode.Eval.BytecodeError.u8RangeCheckFailed + | Aiur.Bytecode.Op.unconstrainedBigUintDivMod a b => do + let aPtr ← Aiur.Bytecode.Eval.readIdx st a + let bPtr ← Aiur.Bytecode.Eval.readIdx st b + let bound : Nat := (Option.map (fun x => x.size) (IndexMap.getByKey st.memory 10)).getD 0 + 1 + let aLimbs ← Aiur.Bytecode.Eval.readLimbChain st bound aPtr.val.toNat + let bLimbs ← Aiur.Bytecode.Eval.readLimbChain st bound bPtr.val.toNat + let aVal : Nat := Aiur.limbsVal aLimbs + let bVal : Nat := Aiur.limbsVal bLimbs + match Aiur.Bytecode.Eval.buildLimbChain st (Aiur.natToLimbsLE (aVal / bVal)) with + | (st1, qPtr) => + match Aiur.Bytecode.Eval.buildLimbChain st1 (Aiur.natToLimbsLE (aVal % bVal)) with + | (st2, rPtr) => + pure (Aiur.Bytecode.Eval.pushMap (Aiur.Bytecode.Eval.pushMap st2 (Aiur.G.ofNat qPtr)) (Aiur.G.ofNat rPtr)) + | Aiur.Bytecode.Op.unconstrainedGToBytes idx => do + let g ← Aiur.Bytecode.Eval.readIdx st idx + pure (Aiur.Bytecode.Eval.appendMap st (Array.ofFn g.toLeBytes)) + | Aiur.Bytecode.Op.unconstrainedGInverse idx => do + let g ← Aiur.Bytecode.Eval.readIdx st idx + pure (Aiur.Bytecode.Eval.pushMap st g.inverse) + | Aiur.Bytecode.Op.debug a a_1 => Except.ok st +RECURSION WORKER Aiur.Bytecode.Eval.readLimbChain._unsafe_rec +Aiur.Bytecode.Eval.EvalState → Nat → Nat → Except Aiur.Bytecode.Eval.BytecodeError (List (Array Aiur.G)) +IMPLEMENTATION +fun st x x_1 => + match x, x_1 with + | 0, x => Except.error Aiur.Bytecode.Eval.BytecodeError.unconstrainedBigUintDivModFailed + | steps.succ, ptr => do + let vs ← Aiur.Bytecode.Eval.memLoad st 10 ptr + match vs[0]?, vs[9]? with + | some tag, some next => + if (tag == 1) = true then pure [] + else + if (tag == 0) = true then + let bytes := vs.extract 1 9; + if (bytes.size == 8 && bytes.all fun x => decide (x.val < 256)) = true then do + let rest ← Aiur.Bytecode.Eval.readLimbChain._unsafe_rec st steps next.val.toNat + pure (bytes :: rest) + else Except.error Aiur.Bytecode.Eval.BytecodeError.unconstrainedBigUintDivModFailed + else Except.error Aiur.Bytecode.Eval.BytecodeError.unconstrainedBigUintDivModFailed + | x, x_2 => Except.error Aiur.Bytecode.Eval.BytecodeError.unconstrainedBigUintDivModFailed +RECURSION WORKER Aiur.Bytecode.Eval.runOps._unsafe_rec +Aiur.Bytecode.Toplevel → + Nat → + Array Aiur.Bytecode.Op → + Aiur.Bytecode.Eval.EvalState → Nat → Except Aiur.Bytecode.Eval.BytecodeError Aiur.Bytecode.Eval.EvalState +IMPLEMENTATION +fun t fuel ops st i => + if h : i < ops.size then + match Aiur.Bytecode.Eval.evalOp._unsafe_rec t fuel ops[i] st with + | Except.error e => Except.error e + | Except.ok st' => Aiur.Bytecode.Eval.runOps._unsafe_rec t fuel ops st' (i + 1) + else Except.ok st +RECURSION WORKER Aiur.Concrete.Bytecode.relayoutBlock._unsafe_rec +Aiur.Bytecode.Block → Aiur.Concrete.Bytecode.LayoutM Aiur.Bytecode.Block +IMPLEMENTATION +fun block => do + Array.forM Aiur.Concrete.Bytecode.opLayout block.ops + let __do_lift ← Aiur.Concrete.Bytecode.relayoutCtrl._unsafe_rec block.ctrl + pure { ops := block.ops, ctrl := __do_lift } +RECURSION WORKER Aiur.Concrete.Bytecode.relayoutCtrl._unsafe_rec +Aiur.Bytecode.Ctrl → Aiur.Concrete.Bytecode.LayoutM Aiur.Bytecode.Ctrl +IMPLEMENTATION +fun c => + match c with + | Aiur.Bytecode.Ctrl.match value branches defaultBranch => do + let initSharedData ← Aiur.Concrete.Bytecode.getSharedData + let degrees ← Aiur.Concrete.Bytecode.getDegrees + let __x ← + Array.foldlM + (fun x x_1 => + match x with + | (done, currMax) => + match x_1 with + | ⟨(value, block), property⟩ => do + Aiur.Concrete.Bytecode.setSharedData initSharedData + let block ← Aiur.Concrete.Bytecode.relayoutBlock._unsafe_rec block + let blockSharedData ← Aiur.Concrete.Bytecode.getSharedData + Aiur.Concrete.Bytecode.setDegrees degrees + pure (done.push (value, block), currMax.maximals blockSharedData)) + (#[], initSharedData) branches.attach + match __x with + | (branches, maximalSharedData) => + have __do_jp := fun __x => + match __x with + | (defaultBranch, finalMax) => do + Aiur.Concrete.Bytecode.setSharedData finalMax + pure (Aiur.Bytecode.Ctrl.match value branches defaultBranch); + match defaultBranch with + | none => do + let __x ← pure (none, maximalSharedData) + __do_jp __x + | some defaultBlock => do + Aiur.Concrete.Bytecode.setSharedData initSharedData + Aiur.Concrete.Bytecode.bumpAuxiliaries branches.size + let defaultBlock ← Aiur.Concrete.Bytecode.relayoutBlock._unsafe_rec defaultBlock + let defaultBlockSharedData ← Aiur.Concrete.Bytecode.getSharedData + Aiur.Concrete.Bytecode.setDegrees degrees + let __x ← pure (some defaultBlock, maximalSharedData.maximals defaultBlockSharedData) + __do_jp __x + | Aiur.Bytecode.Ctrl.return a a_1 => do + Aiur.Concrete.Bytecode.bumpSelectors + pure c + | Aiur.Bytecode.Ctrl.yield a a_1 => do + Aiur.Concrete.Bytecode.bumpSelectors + pure c + | Aiur.Bytecode.Ctrl.matchContinue value branches defaultBranch outputSize _sharedAux _sharedLookups continuation => + do + let initSharedData ← Aiur.Concrete.Bytecode.getSharedData + let degrees ← Aiur.Concrete.Bytecode.getDegrees + let __x ← + Array.foldlM + (fun x x_1 => + match x with + | (done, currMax) => + match x_1 with + | ⟨(value, block), property⟩ => do + Aiur.Concrete.Bytecode.setSharedData initSharedData + let block ← Aiur.Concrete.Bytecode.relayoutBlock._unsafe_rec block + let blockSharedData ← Aiur.Concrete.Bytecode.getSharedData + Aiur.Concrete.Bytecode.setDegrees degrees + pure (done.push (value, block), currMax.maximals blockSharedData)) + (#[], initSharedData) branches.attach + match __x with + | (branches, maximalSharedData) => + have __do_jp := fun __x => + match __x with + | (defaultBranch, finalMax) => do + Aiur.Concrete.Bytecode.setSharedData finalMax + Aiur.Concrete.Bytecode.bumpAuxiliaries outputSize + Aiur.Concrete.Bytecode.pushDegrees (Array.replicate outputSize 1) + let continuation ← Aiur.Concrete.Bytecode.relayoutBlock._unsafe_rec continuation + pure + (Aiur.Bytecode.Ctrl.matchContinue value branches defaultBranch outputSize + (finalMax.auxiliaries - initSharedData.auxiliaries) (finalMax.lookups - initSharedData.lookups) + continuation); + match defaultBranch with + | none => do + let __x ← pure (none, maximalSharedData) + __do_jp __x + | some defaultBlock => do + Aiur.Concrete.Bytecode.setSharedData initSharedData + Aiur.Concrete.Bytecode.bumpAuxiliaries branches.size + let defaultBlock ← Aiur.Concrete.Bytecode.relayoutBlock._unsafe_rec defaultBlock + let defaultBlockSharedData ← Aiur.Concrete.Bytecode.getSharedData + Aiur.Concrete.Bytecode.setDegrees degrees + let __x ← pure (some defaultBlock, maximalSharedData.maximals defaultBlockSharedData) + __do_jp __x +RECURSION WORKER Aiur.Concrete.Constructor.sizeBound._unsafe_rec +Aiur.Concrete.Decls → Nat → Std.HashSet Aiur.Global → Aiur.Concrete.Constructor → Except String Nat +IMPLEMENTATION +fun decls bound visited c => + List.foldlM + (fun acc t => do + let s ← Aiur.Concrete.Typ.sizeBound._unsafe_rec decls bound visited t + pure (acc + s)) + 0 c.argTypes +RECURSION WORKER Aiur.Concrete.DataType.sizeBound._unsafe_rec +Aiur.Concrete.Decls → Nat → Std.HashSet Aiur.Global → Aiur.Concrete.DataType → Except String Nat +IMPLEMENTATION +fun decls x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, x_3 => pure 1 + | bound.succ, visited, dt => + if visited.contains dt.name = true then + throw (toString "Cycle detected at datatype `" ++ toString dt.name ++ toString "`") + else + let visited := visited.insert dt.name; + do + let ctorSizes ← List.mapM (Aiur.Concrete.Constructor.sizeBound._unsafe_rec decls bound visited) dt.constructors + let maxFields : Nat := List.foldl max 0 ctorSizes + if (dt.constructors.length == 1) = true then pure maxFields else pure (maxFields + 1) +RECURSION WORKER Aiur.Concrete.Term.compile._unsafe_rec +Aiur.Concrete.Term → + Aiur.Concrete.Typ → + Aiur.LayoutMap → + Std.HashMap Aiur.Local (Array Aiur.Bytecode.ValIdx) → optParam Bool false → Aiur.CompileM Aiur.Bytecode.Block +IMPLEMENTATION +fun term returnTyp layoutMap bindings yieldCtrl => + match term with + | + Aiur.Concrete.Term.letVar typ escapes var (Aiur.Concrete.Term.match matchTyp valEscapes scrut cases defaultOpt) bod => + if valEscapes = true then + Aiur.Concrete.Term.compile._unsafe_rec (Aiur.Concrete.Term.match matchTyp valEscapes scrut cases defaultOpt) + returnTyp layoutMap bindings yieldCtrl + else + let idxs := bindings[scrut]?.getD #[0]; + do + let ops ← Aiur.extractOps + let __x ← + Array.foldlM (Aiur.Concrete.addCase._unsafe_rec layoutMap bindings returnTyp idxs true) (#[], none) cases + match __x with + | (matchCases, defaultBlock) => + have __do_jp := fun defaultBlock => + have __do_jp := fun outputSize => do + let __x ← Aiur.Concrete.computeSharedLayout matchCases defaultBlock + match __x with + | (sharedAux, sharedLookups) => do + let __do_lift ← get + let mergedStart : Aiur.Bytecode.ValIdx := __do_lift.valIdx + modify fun s => + { valIdx := s.valIdx + outputSize, ops := s.ops, selIdx := s.selIdx, + degrees := Array.foldl (fun x1 x2 => x1.push x2) s.degrees (Array.replicate outputSize 1) } + let mergedIdxs : Array Nat := Array.range' mergedStart outputSize + let continuation ← + Aiur.Concrete.Term.compile._unsafe_rec bod returnTyp layoutMap (bindings.insert var mergedIdxs) + yieldCtrl + let ctrl : Aiur.Bytecode.Ctrl := + Aiur.Bytecode.Ctrl.matchContinue idxs[0]! matchCases defaultBlock outputSize sharedAux sharedLookups + continuation + pure { ops := ops, ctrl := ctrl }; + match Aiur.typSize layoutMap matchTyp with + | Except.error e => do + let outputSize ← throw e + __do_jp outputSize + | Except.ok n => do + let outputSize ← pure n + __do_jp outputSize; + match defaultOpt with + | some t => do + let blk ← Aiur.Concrete.Term.compile._unsafe_rec t returnTyp layoutMap bindings true + let defaultBlock ← pure (some blk) + __do_jp defaultBlock + | none => do + let defaultBlock ← pure defaultBlock + __do_jp defaultBlock + | Aiur.Concrete.Term.letWild typ escapes (Aiur.Concrete.Term.match matchTyp valEscapes scrut cases defaultOpt) bod => + if valEscapes = true then + Aiur.Concrete.Term.compile._unsafe_rec (Aiur.Concrete.Term.match matchTyp valEscapes scrut cases defaultOpt) + returnTyp layoutMap bindings yieldCtrl + else + let idxs := bindings[scrut]?.getD #[0]; + do + let ops ← Aiur.extractOps + let __x ← + Array.foldlM (Aiur.Concrete.addCase._unsafe_rec layoutMap bindings returnTyp idxs true) (#[], none) cases + match __x with + | (matchCases, defaultBlock) => + have __do_jp := fun defaultBlock => + have __do_jp := fun outputSize => do + let __x ← Aiur.Concrete.computeSharedLayout matchCases defaultBlock + match __x with + | (sharedAux, sharedLookups) => do + modify fun s => + { valIdx := s.valIdx + outputSize, ops := s.ops, selIdx := s.selIdx, + degrees := Array.foldl (fun x1 x2 => x1.push x2) s.degrees (Array.replicate outputSize 1) } + let continuation ← Aiur.Concrete.Term.compile._unsafe_rec bod returnTyp layoutMap bindings yieldCtrl + let ctrl : Aiur.Bytecode.Ctrl := + Aiur.Bytecode.Ctrl.matchContinue idxs[0]! matchCases defaultBlock outputSize sharedAux sharedLookups + continuation + pure { ops := ops, ctrl := ctrl }; + match Aiur.typSize layoutMap matchTyp with + | Except.error e => do + let outputSize ← throw e + __do_jp outputSize + | Except.ok n => do + let outputSize ← pure n + __do_jp outputSize; + match defaultOpt with + | some t => do + let blk ← Aiur.Concrete.Term.compile._unsafe_rec t returnTyp layoutMap bindings true + let defaultBlock ← pure (some blk) + __do_jp defaultBlock + | none => do + let defaultBlock ← pure defaultBlock + __do_jp defaultBlock + | Aiur.Concrete.Term.letVar typ escapes var val bod => do + let val ← Aiur.toIndex layoutMap bindings val + Aiur.Concrete.Term.compile._unsafe_rec bod returnTyp layoutMap (bindings.insert var val) yieldCtrl + | Aiur.Concrete.Term.letWild typ escapes val bod => do + let _ ← Aiur.toIndex layoutMap bindings val + Aiur.Concrete.Term.compile._unsafe_rec bod returnTyp layoutMap bindings yieldCtrl + | Aiur.Concrete.Term.letLoad typ escapes dst dstTyp src bod => + have __do_jp := fun size => + let ptrIdxs := bindings[src]?.getD #[0]; + do + let loaded ← Aiur.pushOp (Aiur.Bytecode.Op.load size ptrIdxs[0]!) size + Aiur.Concrete.Term.compile._unsafe_rec bod returnTyp layoutMap (bindings.insert dst loaded) yieldCtrl; + match Aiur.typSize layoutMap dstTyp with + | Except.error e => do + let size ← throw e + __do_jp size + | Except.ok n => do + let size ← pure n + __do_jp size + | Aiur.Concrete.Term.debug typ escapes label term ret => do + let term ← Option.mapM (Aiur.toIndex layoutMap bindings) term + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.debug label term), selIdx := stt.selIdx, + degrees := stt.degrees } + Aiur.Concrete.Term.compile._unsafe_rec ret returnTyp layoutMap bindings yieldCtrl + | Aiur.Concrete.Term.assertEq typ escapes a b msg ret => do + let a ← Aiur.toIndex layoutMap bindings a + let b ← Aiur.toIndex layoutMap bindings b + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.assertEq a b msg), selIdx := stt.selIdx, + degrees := stt.degrees } + Aiur.Concrete.Term.compile._unsafe_rec ret returnTyp layoutMap bindings yieldCtrl + | Aiur.Concrete.Term.ioSetInfo typ escapes channel key idx len ret => do + let channel ← Aiur.toIndex layoutMap bindings channel + let key ← Aiur.toIndex layoutMap bindings key + let idx ← Aiur.toIndex layoutMap bindings idx + let len ← Aiur.toIndex layoutMap bindings len + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.ioSetInfo channel[0]! key idx[0]! len[0]!), + selIdx := stt.selIdx, degrees := stt.degrees } + Aiur.Concrete.Term.compile._unsafe_rec ret returnTyp layoutMap bindings yieldCtrl + | Aiur.Concrete.Term.ioWrite typ escapes channel data ret => do + let channel ← Aiur.toIndex layoutMap bindings channel + let data ← Aiur.toIndex layoutMap bindings data + modify fun stt => + { valIdx := stt.valIdx, ops := stt.ops.push (Aiur.Bytecode.Op.ioWrite channel[0]! data), selIdx := stt.selIdx, + degrees := stt.degrees } + Aiur.Concrete.Term.compile._unsafe_rec ret returnTyp layoutMap bindings yieldCtrl + | Aiur.Concrete.Term.match typ escapes scrut cases defaultOpt => + let idxs := bindings[scrut]?.getD #[0]; + do + let ops ← Aiur.extractOps + let __x ← + Array.foldlM (Aiur.Concrete.addCase._unsafe_rec layoutMap bindings returnTyp idxs yieldCtrl) (#[], none) cases + match __x with + | (bcCases, defaultBlock) => + have __do_jp := fun defaultBlock => + let ctrl := Aiur.Bytecode.Ctrl.match idxs[0]! bcCases defaultBlock; + pure { ops := ops, ctrl := ctrl }; + match defaultOpt with + | some t => do + let blk ← Aiur.Concrete.Term.compile._unsafe_rec t returnTyp layoutMap bindings yieldCtrl + let defaultBlock ← pure (some blk) + __do_jp defaultBlock + | none => do + let defaultBlock ← pure defaultBlock + __do_jp defaultBlock + | Aiur.Concrete.Term.ret typ escapes term => do + let idxs ← Aiur.toIndex layoutMap bindings term + let state ← get + let state : Aiur.CompilerState := + { valIdx := state.valIdx, ops := state.ops, selIdx := state.selIdx + 1, degrees := state.degrees } + set state + let ops : Array Aiur.Bytecode.Op := state.ops + let id : Aiur.Bytecode.SelIdx := state.selIdx + pure { ops := ops, ctrl := Aiur.Bytecode.Ctrl.return (id - 1) idxs } + | x => do + let idxs ← Aiur.toIndex layoutMap bindings term + let state ← get + let state : Aiur.CompilerState := + { valIdx := state.valIdx, ops := state.ops, selIdx := state.selIdx + 1, degrees := state.degrees } + set state + let ops : Array Aiur.Bytecode.Op := state.ops + let id : Aiur.Bytecode.SelIdx := state.selIdx + let ctrl : Aiur.Bytecode.Ctrl := + if (yieldCtrl && !term.escapes) = true then Aiur.Bytecode.Ctrl.yield (id - 1) idxs + else Aiur.Bytecode.Ctrl.return (id - 1) idxs + pure { ops := ops, ctrl := ctrl } +RECURSION WORKER Aiur.Concrete.Typ.sizeBound._unsafe_rec +Aiur.Concrete.Decls → Nat → Std.HashSet Aiur.Global → Aiur.Concrete.Typ → Except String Nat +IMPLEMENTATION +fun decls x x_1 x_2 => + match x, x_1, x_2 with + | 0, x, x_3 => pure 0 + | n.succ, x, Aiur.Concrete.Typ.unit => pure 0 + | n.succ, x, Aiur.Concrete.Typ.field => pure 1 + | n.succ, x, a.pointer => pure 1 + | n.succ, x, Aiur.Concrete.Typ.function a a_1 => pure 1 + | bound.succ, visited, Aiur.Concrete.Typ.tuple ts => + Array.foldlM + (fun acc x => + match x with + | ⟨t, property⟩ => do + let s ← Aiur.Concrete.Typ.sizeBound._unsafe_rec decls bound visited t + pure (acc + s)) + 0 ts.attach + | bound.succ, visited, t.array n => do + let s ← Aiur.Concrete.Typ.sizeBound._unsafe_rec decls bound visited t + pure (n * s) + | bound.succ, visited, Aiur.Concrete.Typ.ref g => + match IndexMap.getByKey decls g with + | some (Aiur.Concrete.Declaration.dataType dt) => + Aiur.Concrete.DataType.sizeBound._unsafe_rec decls bound visited dt + | x => throw (toString "Datatype not found: `" ++ toString g ++ toString "`") +RECURSION WORKER Aiur.NativeAIR.Blake3.chunkLoop._unsafe_rec +UInt64 → Aiur.NativeAIR.Blake3.CV → Bool → List UInt8 → Aiur.NativeAIR.Blake3.Output +IMPLEMENTATION +fun counter cv start input => + if h : input.length ≤ 64 then + { cv := cv, block := Aiur.NativeAIR.Blake3.blockWords input, blockLen := input.length.toUInt32, counter := counter, + flags := (if start = true then 1 else 0) ||| 2 } + else + let next := + Aiur.NativeAIR.Blake3.compress cv (Aiur.NativeAIR.Blake3.blockWords (List.take 64 input)) counter 64 + (if start = true then 1 else 0); + Aiur.NativeAIR.Blake3.chunkLoop._unsafe_rec counter next false (List.drop 64 input) +RECURSION WORKER Aiur.NativeAIR.Blake3.subtree._unsafe_rec +Nat → List UInt8 → Aiur.NativeAIR.Blake3.Output +IMPLEMENTATION +fun counter input => + if _h : input.length ≤ 1024 then Aiur.NativeAIR.Blake3.chunkOutput counter.toUInt64 input + else + let split := Aiur.NativeAIR.Blake3.leftLen input.length; + let left := Aiur.NativeAIR.Blake3.subtree._unsafe_rec counter (List.take split input); + let right := Aiur.NativeAIR.Blake3.subtree._unsafe_rec (counter + split / 1024) (List.drop split input); + Aiur.NativeAIR.Blake3.parentOutput left.chainingValue right.chainingValue +RECURSION WORKER Aiur.NativeAIR.BlockEmitter.blockSelector._unsafe_rec +Array Aiur.NativeAIR.Expr → Aiur.Bytecode.Block → Option Aiur.NativeAIR.Expr +IMPLEMENTATION +fun selectors block => Aiur.NativeAIR.BlockEmitter.ctrlSelector._unsafe_rec selectors block.ctrl +RECURSION WORKER Aiur.NativeAIR.BlockEmitter.ctrlSelector._unsafe_rec +Array Aiur.NativeAIR.Expr → Aiur.Bytecode.Ctrl → Option Aiur.NativeAIR.Expr +IMPLEMENTATION +fun selectors x => + match x with + | Aiur.Bytecode.Ctrl.return index a => selectors[index]? + | Aiur.Bytecode.Ctrl.yield index a => selectors[index]? + | Aiur.Bytecode.Ctrl.match a branches fallback => do + let entries ← + List.mapM + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.NativeAIR.BlockEmitter.blockSelector._unsafe_rec selectors pair.snd) + branches.attach.toList + have __do_jp : List Aiur.NativeAIR.Expr → Option Aiur.NativeAIR.Expr := fun last => + pure (Aiur.NativeAIR.BlockEmitter.sum (entries ++ last)) + match fallback with + | none => do + let last ← some [] + __do_jp last + | some block => do + let last ← + Option.map (fun expr => [expr]) (Aiur.NativeAIR.BlockEmitter.blockSelector._unsafe_rec selectors block) + __do_jp last + | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups a_1 => do + let entries ← + List.mapM + (fun x => + match x with + | ⟨pair, property⟩ => Aiur.NativeAIR.BlockEmitter.blockSelector._unsafe_rec selectors pair.snd) + branches.attach.toList + have __do_jp : List Aiur.NativeAIR.Expr → Option Aiur.NativeAIR.Expr := fun last => + pure (Aiur.NativeAIR.BlockEmitter.sum (entries ++ last)) + match fallback with + | none => do + let last ← some [] + __do_jp last + | some block => do + let last ← + Option.map (fun expr => [expr]) (Aiur.NativeAIR.BlockEmitter.blockSelector._unsafe_rec selectors block) + __do_jp last +RECURSION WORKER Aiur.NativeAIR.BlockEmitter.emitBlock._unsafe_rec +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.RowExpr → Nat → Nat → Aiur.Bytecode.Block → Option Aiur.NativeAIR.BlockEmitter.Emission +IMPLEMENTATION +fun selectors context incoming rows column lookup block => do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors block + let operations ← Aiur.NativeAIR.OpEmitter.emitOps incoming context.rank block.ops.toList rows column + let control ← + Aiur.NativeAIR.BlockEmitter.emitCtrl._unsafe_rec selectors context incoming operations.values operations.column + (lookup + operations.queries.length) block.ctrl + pure + (Aiur.NativeAIR.BlockEmitter.Emission.prefix [entry.frontMul ((Aiur.NativeAIR.Expr.konst 1).frontSub entry)] + (Aiur.NativeAIR.BlockEmitter.Emission.afterOps incoming lookup operations control)) +RECURSION WORKER Aiur.NativeAIR.BlockEmitter.emitCtrl._unsafe_rec +Array Aiur.NativeAIR.Expr → + Aiur.NativeAIR.BlockEmitter.Context → + Aiur.NativeAIR.Expr → + Array Aiur.NativeAIR.RowExpr → Nat → Nat → Aiur.Bytecode.Ctrl → Option Aiur.NativeAIR.BlockEmitter.Emission +IMPLEMENTATION +fun selectors context incoming rows column lookup x => + match x with + | Aiur.Bytecode.Ctrl.return a indices => do + let inputs ← Aiur.NativeAIR.OpEmitter.select rows (Array.range context.inputSize) + let outputs ← Aiur.NativeAIR.OpEmitter.select rows indices + pure (Aiur.NativeAIR.BlockEmitter.returned context incoming rows inputs outputs column lookup) + | Aiur.Bytecode.Ctrl.yield index indices => do + let selector ← selectors[index]? + let outputs ← Aiur.NativeAIR.OpEmitter.select rows indices + pure (Aiur.NativeAIR.BlockEmitter.yielded selector rows outputs column lookup) + | Aiur.Bytecode.Ctrl.match index branches fallback => do + let matched ← rows[index]? + let cases ← + List.mapM + (fun x => + match x with + | ⟨pair, property⟩ => do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors pair.snd + let emission ← + Aiur.NativeAIR.BlockEmitter.emitBlock._unsafe_rec selectors context entry rows column lookup pair.snd + pure + (Aiur.NativeAIR.BlockEmitter.Emission.prefix + [Aiur.NativeAIR.BlockEmitter.caseEquation entry matched pair.fst] emission)) + branches.attach.toList + have __do_jp : List Aiur.NativeAIR.BlockEmitter.Emission → Option Aiur.NativeAIR.BlockEmitter.Emission := + fun default => pure (Aiur.NativeAIR.BlockEmitter.join rows column lookup (cases ++ default)) + match fallback with + | none => do + let default ← some [] + __do_jp default + | some block => do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors block + let emission ← + Aiur.NativeAIR.BlockEmitter.emitBlock._unsafe_rec selectors context entry rows (column + branches.size) lookup + block + let default ← + pure + [Aiur.NativeAIR.BlockEmitter.Emission.prefix + (Aiur.NativeAIR.BlockEmitter.defaultEquations entry matched column branches) emission] + __do_jp default + | Aiur.Bytecode.Ctrl.matchContinue index branches fallback size sharedAuxiliaries sharedLookups continuation => do + let matched ← rows[index]? + let cases ← + List.mapM + (fun x => + match x with + | ⟨pair, property⟩ => do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors pair.snd + let emission ← + Aiur.NativeAIR.BlockEmitter.emitBlock._unsafe_rec selectors context entry rows column lookup pair.snd + pure + (Aiur.NativeAIR.BlockEmitter.Emission.prefix + [Aiur.NativeAIR.BlockEmitter.caseEquation entry matched pair.fst] emission)) + branches.attach.toList + have __do_jp : List Aiur.NativeAIR.BlockEmitter.Emission → Option Aiur.NativeAIR.BlockEmitter.Emission := + fun default => + let joined := Aiur.NativeAIR.BlockEmitter.join rows column lookup (cases ++ default); + if (joined.yields.all fun part => part.values.size == size) = true then + let gate := Aiur.NativeAIR.BlockEmitter.yieldGate joined.yields; + do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors continuation + let equations : List Aiur.NativeAIR.Expr := + Aiur.NativeAIR.BlockEmitter.mergeEquations incoming joined.column size joined.yields ++ [entry.frontSub gate] + let continued ← + Aiur.NativeAIR.BlockEmitter.emitBlock._unsafe_rec selectors context gate + (rows ++ Aiur.NativeAIR.OpEmitter.advice joined.column size) (joined.column + size) joined.lookup + continuation + pure (joined.continued equations continued) + else none + match fallback with + | none => do + let default ← some [] + __do_jp default + | some block => do + let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors block + let emission ← + Aiur.NativeAIR.BlockEmitter.emitBlock._unsafe_rec selectors context entry rows (column + branches.size) lookup + block + let default ← + pure + [Aiur.NativeAIR.BlockEmitter.Emission.prefix + (Aiur.NativeAIR.BlockEmitter.defaultEquations entry matched column branches) emission] + __do_jp default +RECURSION WORKER Aiur.NativeAIR.Challenger.sampleBytes._unsafe_rec +Aiur.NativeAIR.Challenger.Hash32 → Nat → Aiur.NativeAIR.Challenger.State → List UInt8 × Aiur.NativeAIR.Challenger.State +IMPLEMENTATION +fun hash x x_1 => + match x, x_1 with + | 0, state => ([], state) + | count.succ, state => + match Aiur.NativeAIR.Challenger.sampleByte hash state with + | (byte, next) => + match Aiur.NativeAIR.Challenger.sampleBytes._unsafe_rec hash count next with + | (rest, final) => (byte :: rest, final) +RECURSION WORKER Aiur.NativeAIR.Challenger.sampleField._unsafe_rec +Aiur.NativeAIR.Challenger.Hash32 → + Nat → Aiur.NativeAIR.Challenger.State → Option (Aiur.G × Aiur.NativeAIR.Challenger.State) +IMPLEMENTATION +fun hash x x_1 => + match x, x_1 with + | 0, x => none + | fuel.succ, state => + match Aiur.NativeAIR.Challenger.sampleWord hash state with + | (word, next) => + if word < Aiur.gSize.toNat then some (Aiur.G.ofNat word, next) + else Aiur.NativeAIR.Challenger.sampleField._unsafe_rec hash fuel next +RECURSION WORKER Aiur.NativeAIR.CircuitEmitter.emitMembers._unsafe_rec +Aiur.NativeAIR.Expr → + Nat → Nat → Nat → Aiur.Bytecode.Toplevel → List Nat → Option (List Aiur.NativeAIR.CircuitEmitter.Member) +IMPLEMENTATION +fun rank column lookup selectorBase program x => + match x with + | [] => some [] + | index :: indices => do + let member ← Aiur.NativeAIR.CircuitEmitter.emitMember rank column lookup selectorBase program index + let rest ← + Aiur.NativeAIR.CircuitEmitter.emitMembers._unsafe_rec rank column lookup + (selectorBase + member.function.layout.selectors) program indices + pure (member :: rest) +RECURSION WORKER Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec +Aiur.NativeAIR.GraphWidths → + Bool → Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × Nat) +IMPLEMENTATION +fun widths allowStage2 x x_1 => + match x, x_1 with + | Aiur.NativeAIR.Expr.konst value, nodes => + some (Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.konst value)) + | Aiur.NativeAIR.Expr.var column, nodes => + if + ((column.source != Aiur.NativeAIR.Source.stage2 || allowStage2) && + decide (column.index < widths.width column.source)) = + true then + some (Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.var column)) + else none + | Aiur.NativeAIR.Expr.publicInput index, nodes => + if index < widths.publics then some (Aiur.NativeAIR.Compiler.intern nodes (Aiur.NativeAIR.Node.publicInput index)) + else none + | Aiur.NativeAIR.Expr.isFirstRow, nodes => some (Aiur.NativeAIR.Compiler.intern nodes Aiur.NativeAIR.Node.isFirstRow) + | Aiur.NativeAIR.Expr.isLastRow, nodes => some (Aiur.NativeAIR.Compiler.intern nodes Aiur.NativeAIR.Node.isLastRow) + | Aiur.NativeAIR.Expr.isTransition, nodes => + some (Aiur.NativeAIR.Compiler.intern nodes Aiur.NativeAIR.Node.isTransition) + | left.add right, nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec widths allowStage2 left nodes + match __x with + | (nodes, a) => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec widths allowStage2 right nodes + match __x with + | (nodes, b) => pure (Aiur.NativeAIR.Compiler.add nodes a b) + | left.sub right, nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec widths allowStage2 left nodes + match __x with + | (nodes, a) => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec widths allowStage2 right nodes + match __x with + | (nodes, b) => pure (Aiur.NativeAIR.Compiler.sub nodes a b) + | left.mul right, nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec widths allowStage2 left nodes + match __x with + | (nodes, a) => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec widths allowStage2 right nodes + match __x with + | (nodes, b) => pure (Aiur.NativeAIR.Compiler.mul nodes a b) + | child.neg, nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr._unsafe_rec widths allowStage2 child nodes + match __x with + | (nodes, a) => pure (Aiur.NativeAIR.Compiler.neg nodes a) +RECURSION WORKER Aiur.NativeAIR.Compiler.compileExprs._unsafe_rec +Aiur.NativeAIR.GraphWidths → + Bool → List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Nat) +IMPLEMENTATION +fun widths allowStage2 x x_1 => + match x, x_1 with + | [], nodes => some (nodes, []) + | expr :: exprs, nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr widths allowStage2 expr nodes + match __x with + | (nodes, root) => do + let __x ← Aiur.NativeAIR.Compiler.compileExprs._unsafe_rec widths allowStage2 exprs nodes + match __x with + | (nodes, roots) => pure (nodes, root :: roots) +RECURSION WORKER Aiur.NativeAIR.Compiler.compileLookups._unsafe_rec +Aiur.NativeAIR.GraphWidths → + List Aiur.NativeAIR.Compiler.ExprLookup → + List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Aiur.NativeAIR.Lookup) +IMPLEMENTATION +fun widths x x_1 => + match x, x_1 with + | [], nodes => some (nodes, []) + | lookup :: lookups, nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileLookup widths lookup nodes + match __x with + | (nodes, root) => do + let __x ← Aiur.NativeAIR.Compiler.compileLookups._unsafe_rec widths lookups nodes + match __x with + | (nodes, roots) => pure (nodes, root :: roots) +RECURSION WORKER Aiur.NativeAIR.Compiler.compileZeros._unsafe_rec +Aiur.NativeAIR.GraphWidths → + List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Node → Option (List Aiur.NativeAIR.Node × List Nat) +IMPLEMENTATION +fun widths x x_1 => + match x, x_1 with + | [], nodes => some (nodes, []) + | expr :: exprs, nodes => do + let __x ← Aiur.NativeAIR.Compiler.compileExpr widths false expr nodes + match __x with + | (nodes, root) => do + let head ← Aiur.NativeAIR.Compiler.recordZero nodes root + let __x ← Aiur.NativeAIR.Compiler.compileZeros._unsafe_rec widths exprs nodes + match __x with + | (nodes, roots) => pure (nodes, head ++ roots) +RECURSION WORKER Aiur.NativeAIR.Expr.eval._unsafe_rec +{W : Type u_1} → Aiur.NativeAIR.EvalOps W → Aiur.NativeAIR.Values W → Aiur.NativeAIR.Expr → Option W +IMPLEMENTATION +fun {W} ops values x => + match x with + | Aiur.NativeAIR.Expr.konst value => some (ops.konst value) + | Aiur.NativeAIR.Expr.var column => (values.columns column.source column.offset)[column.index]? + | Aiur.NativeAIR.Expr.publicInput index => values.publics[index]? + | Aiur.NativeAIR.Expr.isFirstRow => some values.isFirstRow + | Aiur.NativeAIR.Expr.isLastRow => some values.isLastRow + | Aiur.NativeAIR.Expr.isTransition => some values.isTransition + | a.add b => do + let __do_lift ← Aiur.NativeAIR.Expr.eval._unsafe_rec ops values a + let __do_lift_1 ← Aiur.NativeAIR.Expr.eval._unsafe_rec ops values b + pure (ops.add __do_lift __do_lift_1) + | a.sub b => do + let __do_lift ← Aiur.NativeAIR.Expr.eval._unsafe_rec ops values a + let __do_lift_1 ← Aiur.NativeAIR.Expr.eval._unsafe_rec ops values b + pure (ops.sub __do_lift __do_lift_1) + | a.mul b => do + let __do_lift ← Aiur.NativeAIR.Expr.eval._unsafe_rec ops values a + let __do_lift_1 ← Aiur.NativeAIR.Expr.eval._unsafe_rec ops values b + pure (ops.mul __do_lift __do_lift_1) + | a.neg => do + let __do_lift ← Aiur.NativeAIR.Expr.eval._unsafe_rec ops values a + pure (ops.neg __do_lift) +RECURSION WORKER Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec +Aiur.NativeAIR.Expr → Bool +IMPLEMENTATION +fun x => + match x with + | child.neg => !child.isConstant && Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec child + | a.add b => Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec a && Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec b + | a.sub b => Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec a && Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec b + | a.mul b => Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec a && Aiur.NativeAIR.Expr.noConstantNegs._unsafe_rec b + | x => true +RECURSION WORKER Aiur.NativeAIR.ExtensionMmcs.shape._unsafe_rec +List Aiur.NativeAIR.Merkle.Dimensions → List (List Aiur.NativeAIR.ProofCodec.Extension) → Bool +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], [] => true + | dimension :: dimensions, row :: rows => + row.length == dimension.width && Aiur.NativeAIR.ExtensionMmcs.shape._unsafe_rec dimensions rows + | x, x_2 => false +RECURSION WORKER Aiur.NativeAIR.Folding.foldCoefficients._unsafe_rec +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → Aiur.NativeAIR.Domain.Subgroup → R → List R → List R +IMPLEMENTATION +fun {R} [OfNat R 0] [Add R] [Mul R] arity challenge coefficients => + if _empty : coefficients = [] then [] + else + Aiur.NativeAIR.Quotient.horner challenge (List.take (Aiur.NativeAIR.Domain.size arity) coefficients) :: + Aiur.NativeAIR.Folding.foldCoefficients._unsafe_rec arity challenge + (List.drop (Aiur.NativeAIR.Domain.size arity) coefficients) +RECURSION WORKER Aiur.NativeAIR.Folding.rowCoefficients._unsafe_rec +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → Aiur.NativeAIR.Domain.Subgroup → R → List R → List R +IMPLEMENTATION +fun {R} [OfNat R 0] [Add R] [Mul R] arity point coefficients => + if _empty : coefficients = [] then [] + else + Aiur.NativeAIR.Polynomial.add (List.take (Aiur.NativeAIR.Domain.size arity) coefficients) + (Aiur.NativeAIR.Polynomial.scale point + (Aiur.NativeAIR.Folding.rowCoefficients._unsafe_rec arity point + (List.drop (Aiur.NativeAIR.Domain.size arity) coefficients))) +RECURSION WORKER Aiur.NativeAIR.FriQuery.walk._unsafe_rec +Aiur.NativeAIR.Domain.Subgroup → + Aiur.NativeAIR.FriQuery.State → + List (Nat × Aiur.NativeAIR.ProofCodec.Extension) → + List Aiur.NativeAIR.FriQuery.Round → Option Aiur.NativeAIR.FriQuery.Result +IMPLEMENTATION +fun final state openings x => + match x with + | [] => if (state.domain == final && openings.isEmpty) = true then some { state := state, rows := [] } else none + | round :: rest => do + let result ← Aiur.NativeAIR.FriQuery.step state round openings + let tail ← Aiur.NativeAIR.FriQuery.walk._unsafe_rec final result.state result.remaining rest + pure { state := tail.state, rows := result.row :: tail.rows } +RECURSION WORKER Aiur.NativeAIR.Interpolation.combine._unsafe_rec +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → List R → R → List (R × R) → List R +IMPLEMENTATION +fun {R} [OfNat R 0] [Add R] [Mul R] vanishing scale x => + match x with + | [] => [] + | (root, value) :: rest => + Aiur.NativeAIR.Polynomial.add + (Aiur.NativeAIR.Polynomial.scale (value * (root * scale)) (Aiur.NativeAIR.Polynomial.divide root vanishing)) + (Aiur.NativeAIR.Interpolation.combine._unsafe_rec vanishing scale rest) +RECURSION WORKER Aiur.NativeAIR.Interpolation.derivativeValue._unsafe_rec +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → R → List R → R +IMPLEMENTATION +fun {R} [OfNat R 0] [Add R] [Mul R] point x => + match x with + | [] => 0 + | head :: rest => + Aiur.NativeAIR.Quotient.horner point rest + + point * Aiur.NativeAIR.Interpolation.derivativeValue._unsafe_rec point rest +RECURSION WORKER Aiur.NativeAIR.Interpolation.weightedSum._unsafe_rec +Aiur.NativeAIR.ProofCodec.Extension → + Aiur.NativeAIR.ProofCodec.Extension → + List (Aiur.NativeAIR.ProofCodec.Extension × Aiur.NativeAIR.ProofCodec.Extension) → + Option Aiur.NativeAIR.ProofCodec.Extension +IMPLEMENTATION +fun scale point x => + match x with + | [] => some 0 + | (root, value) :: rest => do + let inverse ← (point - root).tryInverse + let tail ← Aiur.NativeAIR.Interpolation.weightedSum._unsafe_rec scale point rest + pure (value * (root * scale) * inverse + tail) +RECURSION WORKER Aiur.NativeAIR.KeyCodec.encodeNat._unsafe_rec +Nat → Nat → List UInt8 +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | 0, x => [] + | count.succ, value => value.toUInt8 :: Aiur.NativeAIR.KeyCodec.encodeNat._unsafe_rec count (value / 256) +RECURSION WORKER Aiur.NativeAIR.KeyCodec.nodeDegreesFrom._unsafe_rec +List Aiur.NativeAIR.Node → Array Nat → Option (Array Nat) +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], degrees => some degrees + | node :: nodes, degrees => do + let __do_lift ← Aiur.NativeAIR.KeyCodec.nodeDegree degrees node + Aiur.NativeAIR.KeyCodec.nodeDegreesFrom._unsafe_rec nodes (degrees.push __do_lift) +RECURSION WORKER Aiur.NativeAIR.KeyCodec.readMany._unsafe_rec +{α : Type} → Aiur.NativeAIR.KeyCodec.Reader α → Nat → Aiur.NativeAIR.KeyCodec.Reader (List α) +IMPLEMENTATION +fun {α} read x => + match x with + | 0 => pure [] + | count.succ => do + let first ← read + let rest ← Aiur.NativeAIR.KeyCodec.readMany._unsafe_rec read count + pure (first :: rest) +RECURSION WORKER Aiur.NativeAIR.KeyCodec.readNat._unsafe_rec +Nat → Aiur.NativeAIR.KeyCodec.Reader Nat +IMPLEMENTATION +fun x => + match x with + | 0 => pure 0 + | count.succ => do + let byte ← Aiur.NativeAIR.KeyCodec.readByte + let rest ← Aiur.NativeAIR.KeyCodec.readNat._unsafe_rec count + pure (byte.toNat + 256 * rest) +RECURSION WORKER Aiur.NativeAIR.LogUp.numerator._unsafe_rec +{R : Type u_1} → [OfNat R 0] → [OfNat R 1] → [Add R] → [Mul R] → List (R × R) → R +IMPLEMENTATION +fun {R} [OfNat R 0] [OfNat R 1] [Add R] [Mul R] x => + match x with + | [] => 0 + | (weight, message) :: rest => + weight * Aiur.NativeAIR.LogUp.product (List.map Prod.snd rest) + + message * Aiur.NativeAIR.LogUp.numerator._unsafe_rec rest +RECURSION WORKER Aiur.NativeAIR.LookupEmitter.addArgs._unsafe_rec +List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], right => right + | left, [] => left + | x :: left, y :: right => x.frontAdd y :: Aiur.NativeAIR.LookupEmitter.addArgs._unsafe_rec left right +RECURSION WORKER Aiur.NativeAIR.Merkle.rowsAt._unsafe_rec +List Aiur.NativeAIR.Merkle.Dimensions → List (List Aiur.G) → Nat → List (List Aiur.G) +IMPLEMENTATION +fun x x_1 x_2 => + match x, x_1, x_2 with + | dimension :: dimensions, row :: rows, height => + if dimension.logHeight = height then row :: Aiur.NativeAIR.Merkle.rowsAt._unsafe_rec dimensions rows height + else Aiur.NativeAIR.Merkle.rowsAt._unsafe_rec dimensions rows height + | x, x_3, x_4 => [] +RECURSION WORKER Aiur.NativeAIR.Merkle.shape._unsafe_rec +List Aiur.NativeAIR.Merkle.Dimensions → List (List Aiur.G) → Bool +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], [] => true + | dimension :: dimensions, row :: rows => + row.length == dimension.width && Aiur.NativeAIR.Merkle.shape._unsafe_rec dimensions rows + | x, x_2 => false +RECURSION WORKER Aiur.NativeAIR.Merkle.walk._unsafe_rec +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + List (List Aiur.G) → + Nat → Nat → Aiur.NativeAIR.Merkle.Digest → List Aiur.NativeAIR.Merkle.Digest → Aiur.NativeAIR.Merkle.Hashing +IMPLEMENTATION +fun hash dimensions rows height index current x => + match x with + | [] => { digest := current, inputs := [] } + | sibling :: proof => + let first := Aiur.NativeAIR.Merkle.step hash dimensions rows (height - 1) index current sibling; + let rest := Aiur.NativeAIR.Merkle.walk._unsafe_rec hash dimensions rows (height - 1) (index / 2) first.digest proof; + { digest := rest.digest, inputs := first.inputs ++ rest.inputs } +RECURSION WORKER Aiur.NativeAIR.OpEmitter.emitOps._unsafe_rec +Aiur.NativeAIR.Expr → + Aiur.NativeAIR.Expr → + List Aiur.Bytecode.Op → Array Aiur.NativeAIR.RowExpr → Nat → Option Aiur.NativeAIR.OpEmitter.OpsEmission +IMPLEMENTATION +fun selector rank x x_1 x_2 => + match x, x_1, x_2 with + | [], rows, column => some { values := rows, column := column } + | op :: ops, rows, column => do + let first ← Aiur.NativeAIR.OpEmitter.emitOp selector rank column op rows + let rest ← + Aiur.NativeAIR.OpEmitter.emitOps._unsafe_rec selector rank ops (rows ++ first.outputs) (column + first.used) + pure + { values := rest.values, column := rest.column, equations := first.equations ++ rest.equations, + queries := first.queries ++ rest.queries, calls := first.calls ++ rest.calls } +RECURSION WORKER Aiur.NativeAIR.Polynomial.add._unsafe_rec +{R : Type u_1} → [Add R] → List R → List R → List R +IMPLEMENTATION +fun {R} [Add R] x x_1 => + match x, x_1 with + | [], right => right + | left, [] => left + | first :: left, second :: right => (first + second) :: Aiur.NativeAIR.Polynomial.add._unsafe_rec left right +RECURSION WORKER Aiur.NativeAIR.Polynomial.divide._unsafe_rec +{R : Type u_1} → [OfNat R 0] → [Add R] → [Mul R] → R → List R → List R +IMPLEMENTATION +fun {R} [OfNat R 0] [Add R] [Mul R] point x => + match x with + | [] => [] + | [head] => [] + | head :: next :: rest => + Aiur.NativeAIR.Quotient.horner point (next :: rest) :: + Aiur.NativeAIR.Polynomial.divide._unsafe_rec point (next :: rest) +RECURSION WORKER Aiur.NativeAIR.Polynomial.sub._unsafe_rec +{R : Type u_1} → [OfNat R 0] → [Sub R] → List R → List R → List R +IMPLEMENTATION +fun {R} [OfNat R 0] [Sub R] x x_1 => + match x, x_1 with + | [], right => List.map (fun x => 0 - x) right + | left, [] => left + | first :: left, second :: right => (first - second) :: Aiur.NativeAIR.Polynomial.sub._unsafe_rec left right +RECURSION WORKER Aiur.NativeAIR.PrunedMerkle.boundaryCount._unsafe_rec +Nat → List Nat → Nat +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | 0, x => 0 + | steps.succ, indices => + let parents := Aiur.NativeAIR.PrunedMerkle.parentIndices indices; + 2 * parents.length - indices.length + Aiur.NativeAIR.PrunedMerkle.boundaryCount._unsafe_rec steps parents +RECURSION WORKER Aiur.NativeAIR.PrunedMerkle.combine._unsafe_rec +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.PrunedMerkle.Node → + List Aiur.NativeAIR.Merkle.Digest → + Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node × List Aiur.NativeAIR.Merkle.Digest) +IMPLEMENTATION +fun hash x x_1 => + match x, x_1 with + | [], proof => pure ([], proof) + | first :: rest, proof => + match rest with + | second :: tail => + if first.index % 2 = 0 ∧ second.index = first.index + 1 then do + let digest ← + Aiur.NativeAIR.PrunedMerkle.hashInput hash (Aiur.NativeAIR.Merkle.pairBytes first.digest second.digest) + let __x ← Aiur.NativeAIR.PrunedMerkle.combine._unsafe_rec hash tail proof + match __x with + | (nodes, remaining) => + let tickets := + List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend second.digest) first.tickets ++ + List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend first.digest) second.tickets; + pure ({ index := first.index / 2, digest := digest, tickets := tickets } :: nodes, remaining) + else + match proof with + | sibling :: remaining => do + let digest ← + Aiur.NativeAIR.PrunedMerkle.hashInput hash + (Aiur.NativeAIR.Merkle.branchBytes first.index first.digest sibling) + let __x ← Aiur.NativeAIR.PrunedMerkle.combine._unsafe_rec hash rest remaining + match __x with + | (nodes, remaining) => + pure + ({ index := first.index / 2, digest := digest, + tickets := List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend sibling) first.tickets } :: + nodes, + remaining) + | x => Aiur.NativeAIR.PrunedMerkle.reject + | [] => + match proof with + | sibling :: remaining => do + let digest ← + Aiur.NativeAIR.PrunedMerkle.hashInput hash + (Aiur.NativeAIR.Merkle.branchBytes first.index first.digest sibling) + pure + ([{ index := first.index / 2, digest := digest, + tickets := List.map (Aiur.NativeAIR.PrunedMerkle.Ticket.extend sibling) first.tickets }], + remaining) + | x => Aiur.NativeAIR.PrunedMerkle.reject +RECURSION WORKER Aiur.NativeAIR.PrunedMerkle.initial._unsafe_rec +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Aiur.NativeAIR.PrunedMerkle.Ticket → + Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node) +IMPLEMENTATION +fun hash dimensions height x => + match x with + | [] => pure [] + | ticket :: tickets => do + let digest ← + Aiur.NativeAIR.PrunedMerkle.hashInput hash (Aiur.NativeAIR.Merkle.rowBytes dimensions ticket.rows height) + let rest ← Aiur.NativeAIR.PrunedMerkle.initial._unsafe_rec hash dimensions height tickets + pure ({ index := ticket.index, digest := digest, tickets := [ticket] } :: rest) +RECURSION WORKER Aiur.NativeAIR.PrunedMerkle.inject._unsafe_rec +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + List Aiur.NativeAIR.PrunedMerkle.Node → Aiur.NativeAIR.PrunedMerkle.Logged (List Aiur.NativeAIR.PrunedMerkle.Node) +IMPLEMENTATION +fun hash dimensions height x => + match x with + | [] => pure [] + | node :: nodes => + match node.tickets with + | lead :: members => + if + (!members.all fun ticket => + Aiur.NativeAIR.Merkle.rowsAt dimensions ticket.rows height == + Aiur.NativeAIR.Merkle.rowsAt dimensions lead.rows height) = + true then + Aiur.NativeAIR.PrunedMerkle.reject + else do + let leaf ← + Aiur.NativeAIR.PrunedMerkle.hashInput hash (Aiur.NativeAIR.Merkle.rowBytes dimensions lead.rows height) + let digest ← Aiur.NativeAIR.PrunedMerkle.hashInput hash (Aiur.NativeAIR.Merkle.pairBytes node.digest leaf) + let rest ← Aiur.NativeAIR.PrunedMerkle.inject._unsafe_rec hash dimensions height nodes + pure ({ index := node.index, digest := digest, tickets := node.tickets } :: rest) + | x => Aiur.NativeAIR.PrunedMerkle.reject +RECURSION WORKER Aiur.NativeAIR.PrunedMerkle.walk._unsafe_rec +Aiur.NativeAIR.Merkle.Hash → + List Aiur.NativeAIR.Merkle.Dimensions → + Nat → + Nat → + List Aiur.NativeAIR.PrunedMerkle.Node → + List Aiur.NativeAIR.Merkle.Digest → + Aiur.NativeAIR.PrunedMerkle.Logged + (List Aiur.NativeAIR.PrunedMerkle.Node × List Aiur.NativeAIR.Merkle.Digest) +IMPLEMENTATION +fun hash dimensions x x_1 x_2 x_3 => + match x, x_1, x_2, x_3 with + | 0, x, nodes, proof => pure (nodes, proof) + | steps.succ, height, nodes, proof => do + let __x ← Aiur.NativeAIR.PrunedMerkle.combine hash nodes proof + match __x with + | (parents, remaining) => + have __do_jp := fun next => + Aiur.NativeAIR.PrunedMerkle.walk._unsafe_rec hash dimensions steps (height - 1) next remaining; + if Aiur.NativeAIR.Merkle.hasHeight dimensions (height - 1) = true then do + let next ← Aiur.NativeAIR.PrunedMerkle.inject hash dimensions (height - 1) parents + __do_jp next + else do + let next ← pure parents + __do_jp next +RECURSION WORKER Aiur.NativeAIR.Quotient.coefficients._unsafe_rec +List Aiur.NativeAIR.ProofCodec.Extension → Option (List Aiur.NativeAIR.ProofCodec.Extension) +IMPLEMENTATION +fun x => + match x with + | [] => some [] + | [head] => none + | first :: second :: rest => do + let __do_lift ← Aiur.NativeAIR.Quotient.coefficients._unsafe_rec rest + pure ((first + second * Aiur.NativeAIR.ProofCodec.Extension.basis) :: __do_lift) +RECURSION WORKER Aiur.NativeAIR.VerifierArithmetic.checkRows._unsafe_rec +Aiur.NativeAIR.VerifierArithmetic.Challenges → + List Aiur.NativeAIR.ProofShape.Row → Aiur.NativeAIR.ProofCodec.Extension → Option Aiur.NativeAIR.ProofCodec.Extension +IMPLEMENTATION +fun challenges x x_1 => + match x, x_1 with + | [], entering => some entering + | row :: rows, entering => do + let __do_lift ← Aiur.NativeAIR.VerifierArithmetic.check challenges row entering + if __do_lift = true then Aiur.NativeAIR.VerifierArithmetic.checkRows._unsafe_rec challenges rows row.accumulator + else none +RECURSION WORKER Aiur.Source.Eval.applyGlobal._unsafe_rec +Aiur.Source.Decls → Nat → Aiur.Global → List Aiur.Value → Aiur.Source.Eval.EvalState → Aiur.Source.Eval.EvalResult +IMPLEMENTATION +fun decls fuel g args st => + match fuel with + | 0 => Except.error Aiur.Source.Eval.SourceError.outOfFuel + | fuel.succ => + match IndexMap.getByKey decls g with + | some (Aiur.Source.Declaration.function f) => + if (args.length != f.inputs.length) = true then Except.error (Aiur.Source.Eval.SourceError.arityMismatch g) + else + let bindings := (List.map (fun x => x.fst) f.inputs).zip args; + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings f.body st with + | Except.error (Aiur.Source.Eval.SourceError.earlyReturn v st') => Except.ok (v, st') + | Except.error e => Except.error e + | Except.ok (v, st') => Except.ok (v, st') + | some (Aiur.Source.Declaration.constructor a a_1) => Except.ok (Aiur.Value.ctor g args.toArray, st) + | none => Except.error (Aiur.Source.Eval.SourceError.unboundGlobal g) + | some (Aiur.Source.Declaration.dataType a) => Except.error (Aiur.Source.Eval.SourceError.notCallable g) +RECURSION WORKER Aiur.Source.Eval.applyLocal._unsafe_rec +Aiur.Source.Decls → Nat → Aiur.Value → List Aiur.Value → Aiur.Source.Eval.EvalState → Aiur.Source.Eval.EvalResult +IMPLEMENTATION +fun decls fuel v args st => + match v with + | Aiur.Value.fn g => Aiur.Source.Eval.applyGlobal._unsafe_rec decls fuel g args st + | x => Except.error Aiur.Source.Eval.SourceError.notAFunctionValue +RECURSION WORKER Aiur.Source.Eval.buildLimbChain._unsafe_rec +Aiur.Source.Decls → + Aiur.Global → Aiur.Global → Aiur.Source.Eval.EvalState → List (Array Aiur.G) → Aiur.Value × Aiur.Source.Eval.EvalState +IMPLEMENTATION +fun decls consG nilG st x => + match x with + | [] => Aiur.Source.Eval.storeValue decls st (Aiur.Value.ctor nilG #[]) + | limb :: rest => + match Aiur.Source.Eval.buildLimbChain._unsafe_rec decls consG nilG st rest with + | (restPtr, st') => + Aiur.Source.Eval.storeValue decls st' + (Aiur.Value.ctor consG #[Aiur.Value.array (Array.map Aiur.Value.field limb), restPtr]) +RECURSION WORKER Aiur.Source.Eval.evalFrames._unsafe_rec +Aiur.Source.Decls → + Nat → + List (Aiur.Pattern × Aiur.Source.Term) → + Aiur.Source.Eval.Bindings → + Aiur.Source.Eval.EvalState → + Except Aiur.Source.Eval.SourceError (Aiur.Source.Eval.Bindings × Aiur.Source.Eval.EvalState) +IMPLEMENTATION +fun decls fuel x x_1 x_2 => + match x, x_1, x_2 with + | [], bindings, st => Except.ok (bindings, st) + | (pattern, value) :: frames, bindings, st => do + let __x ← Aiur.Source.Eval.interp decls fuel bindings value st + match __x with + | (value, st) => + match Aiur.Source.Eval.matchPattern st.store pattern value with + | some added => Aiur.Source.Eval.evalFrames._unsafe_rec decls fuel frames (added ++ bindings) st + | x => Except.error Aiur.Source.Eval.SourceError.patternFail +RECURSION WORKER Aiur.Source.Eval.evalList._unsafe_rec +Aiur.Source.Decls → + Nat → + Aiur.Source.Eval.Bindings → + List Aiur.Source.Term → + Aiur.Source.Eval.EvalState → Except Aiur.Source.Eval.SourceError (Array Aiur.Value × Aiur.Source.Eval.EvalState) +IMPLEMENTATION +fun decls fuel bindings x x_1 => + match x, x_1 with + | [], st => Except.ok (#[], st) + | t :: ts, st => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match Aiur.Source.Eval.evalList._unsafe_rec decls fuel bindings ts st' with + | Except.error e => Except.error e + | Except.ok (vs, st'') => Except.ok (#[v] ++ vs, st'') +RECURSION WORKER Aiur.Source.Eval.evalMatchCases._unsafe_rec +Aiur.Source.Decls → + Nat → + Aiur.Source.Eval.Bindings → + Aiur.Source.Eval.EvalState → Aiur.Value → List (Aiur.Pattern × Aiur.Source.Term) → Aiur.Source.Eval.EvalResult +IMPLEMENTATION +fun decls fuel bindings st v x => + match x with + | [] => Except.error Aiur.Source.Eval.SourceError.nonExhaustiveMatch + | (p, body) :: rest => + match Aiur.Source.Eval.matchPattern st.store p v with + | some bs => Aiur.Source.Eval.interp._unsafe_rec decls fuel (bs ++ bindings) body st + | none => Aiur.Source.Eval.evalMatchCases._unsafe_rec decls fuel bindings st v rest +RECURSION WORKER Aiur.Source.Eval.interp._unsafe_rec +Aiur.Source.Decls → + Nat → Aiur.Source.Eval.Bindings → Aiur.Source.Term → Aiur.Source.Eval.EvalState → Aiur.Source.Eval.EvalResult +IMPLEMENTATION +fun decls fuel bindings t st => + match t with + | Aiur.Source.Term.unit => Except.ok (Aiur.Value.unit, st) + | Aiur.Source.Term.var l => + match List.find? (fun x => x.fst == l) bindings with + | some (fst, v) => Except.ok (v, st) + | none => Except.error (Aiur.Source.Eval.SourceError.unboundVar l) + | Aiur.Source.Term.ref g => + match IndexMap.getByKey decls g with + | some (Aiur.Source.Declaration.function a) => Except.ok (Aiur.Value.fn g, st) + | some (Aiur.Source.Declaration.constructor a ctor) => + if ctor.argTypes.isEmpty = true then Except.ok (Aiur.Value.ctor g #[], st) + else Except.error (Aiur.Source.Eval.SourceError.notCallable g) + | some (Aiur.Source.Declaration.dataType a) => Except.error (Aiur.Source.Eval.SourceError.notCallable g) + | none => Except.error (Aiur.Source.Eval.SourceError.unboundGlobal g) + | Aiur.Source.Term.field g => Except.ok (Aiur.Value.field g, st) + | Aiur.Source.Term.tuple ts => + match Aiur.Source.Eval.evalList._unsafe_rec decls fuel bindings ts.toList st with + | Except.error e => Except.error e + | Except.ok (vs, st') => Except.ok (Aiur.Value.tuple vs, st') + | Aiur.Source.Term.array ts => + match Aiur.Source.Eval.evalList._unsafe_rec decls fuel bindings ts.toList st with + | Except.error e => Except.error e + | Except.ok (vs, st') => Except.ok (Aiur.Value.array vs, st') + | Aiur.Source.Term.ann a t => Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st + | sub.ret => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings sub st with + | Except.error e => Except.error e + | Except.ok (v, st') => Except.error (Aiur.Source.Eval.SourceError.earlyReturn v st') + | Aiur.Source.Term.let p t1 t2 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match Aiur.Source.Eval.matchPattern st'.store p v with + | some bs => Aiur.Source.Eval.interp._unsafe_rec decls fuel (bs ++ bindings) t2 st' + | none => Except.error Aiur.Source.Eval.SourceError.patternFail + | t.match cases => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => Aiur.Source.Eval.evalMatchCases._unsafe_rec decls fuel bindings st' v cases + | Aiur.Source.Term.app g args mode => + match Aiur.Source.Eval.evalList._unsafe_rec decls fuel bindings args st with + | Except.error e => Except.error e + | Except.ok (vs, st') => + match Aiur.Source.Eval.tryLocalLookup g bindings with + | some v => Aiur.Source.Eval.applyLocal._unsafe_rec decls fuel v vs.toList st' + | none => Aiur.Source.Eval.applyGlobal._unsafe_rec decls fuel g vs.toList st' + | t1.add t2 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v1, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (v2, st2) => + match v1, v2 with + | Aiur.Value.field a, Aiur.Value.field b => Except.ok (Aiur.Value.field (a + b), st2) + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "add") + | t1.sub t2 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v1, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (v2, st2) => + match v1, v2 with + | Aiur.Value.field a, Aiur.Value.field b => Except.ok (Aiur.Value.field (a - b), st2) + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "sub") + | t1.mul t2 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v1, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (v2, st2) => + match v1, v2 with + | Aiur.Value.field a, Aiur.Value.field b => Except.ok (Aiur.Value.field (a * b), st2) + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "mul") + | t.eqZero => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.field g => Except.ok (Aiur.Value.field (if (g.val == 0) = true then 1 else 0), st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "eqZero") + | t.proj n => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.tuple vs => + if h : n < vs.size then Except.ok (vs[n], st') else Except.error (Aiur.Source.Eval.SourceError.indexOoB n) + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "proj") + | t.get n => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.array vs => + if h : n < vs.size then Except.ok (vs[n], st') else Except.error (Aiur.Source.Eval.SourceError.indexOoB n) + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "get") + | t.slice i j => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.array vs => Except.ok (Aiur.Value.array (vs.extract i j), st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "slice") + | t.set n vT => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings vT st with + | Except.error e => Except.error e + | Except.ok (val, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st1 with + | Except.error e => Except.error e + | Except.ok (arr, st2) => + match arr with + | Aiur.Value.array vs => + if h : n < vs.size then Except.ok (Aiur.Value.array (vs.set n val h), st2) + else Except.error (Aiur.Source.Eval.SourceError.indexOoB n) + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "set") + | t.store => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match Aiur.Source.Eval.storeValue decls st' v with + | (ptr, st'') => Except.ok (ptr, st'') + | t.load => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.pointer w n => + match Aiur.Source.Eval.loadValue st' w n with + | Except.ok v' => Except.ok (v', st') + | Except.error e => Except.error e + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "load") + | t.ptrVal => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.pointer width n => Except.ok (Aiur.Value.field (Aiur.G.ofNat n), st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ptrVal") + | t1.assertEq t2 msg ret => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v1, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (v2, st2) => + if (v1 != v2) = true then + Except.error + (Aiur.Source.Eval.SourceError.typeMismatch + (match msg with + | some m => toString "assertEq: " ++ toString m + | none => "assertEq")) + else Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings ret st2 + | t.u8BitDecomposition => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.field g => + let byte := g.val.toUInt8; + Except.ok + (Aiur.Value.array (Array.ofFn fun i => Aiur.Value.field (Aiur.G.ofUInt8 (byte >>> (↑i).toUInt8 &&& 1))), st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "u8BitDecomposition") + | t.u8ShiftLeft => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.field g => Except.ok (Aiur.Value.field (Aiur.G.ofUInt8 (g.val.toUInt8 <<< 1)), st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "u8ShiftLeft") + | t.u8ShiftRight => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.field g => Except.ok (Aiur.Value.field (Aiur.G.ofUInt8 (g.val.toUInt8 >>> 1)), st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "u8ShiftRight") + | t1.u8Xor t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => Aiur.Value.field (Aiur.G.ofUInt8 (a.val.toUInt8 ^^^ b.val.toUInt8))) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8Add t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => + let x := a.val.toUInt8.toNat + b.val.toUInt8.toNat; + Aiur.Value.tuple #[Aiur.Value.field (Aiur.G.ofUInt8 x.toUInt8), Aiur.Value.field (if x ≥ 256 then 1 else 0)]) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8Mul t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => + let x := a.val.toUInt8.toNat * b.val.toUInt8.toNat; + Aiur.Value.tuple + #[Aiur.Value.field (Aiur.G.ofUInt8 x.toUInt8), Aiur.Value.field (Aiur.G.ofUInt8 (x / 256).toUInt8)]) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8XorSplit7 t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => + let x := a.val.toUInt8 ^^^ b.val.toUInt8; + Aiur.Value.tuple #[Aiur.Value.field (Aiur.G.ofUInt8 (x >>> 7)), Aiur.Value.field (Aiur.G.ofUInt8 (x <<< 1))]) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8XorSplit4 t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => + let x := a.val.toUInt8 ^^^ b.val.toUInt8; + Aiur.Value.tuple #[Aiur.Value.field (Aiur.G.ofUInt8 (x >>> 4)), Aiur.Value.field (Aiur.G.ofUInt8 (x <<< 4))]) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8Sub t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => + let i := a.val.toUInt8; + let j := b.val.toUInt8; + Aiur.Value.tuple #[Aiur.Value.field (Aiur.G.ofUInt8 (i - j)), Aiur.Value.field (if j > i then 1 else 0)]) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8And t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => Aiur.Value.field (Aiur.G.ofUInt8 (a.val.toUInt8 &&& b.val.toUInt8))) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8Or t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => Aiur.Value.field (Aiur.G.ofUInt8 (a.val.toUInt8 ||| b.val.toUInt8))) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u8LessThan t2 => + Aiur.Source.Eval.combineFieldsResult (fun a b => Aiur.Value.field (if a.val.toUInt8 < b.val.toUInt8 then 1 else 0)) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.u32LessThan t2 => + Aiur.Source.Eval.combineFieldsResult + (fun a b => Aiur.Value.field (if a.val.toUInt32 < b.val.toUInt32 then 1 else 0)) + (Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st) fun st1 => + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 + | t1.unconstrainedU32Add t2 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v1, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (v2, st2) => + match v1, v2 with + | Aiur.Value.array a, Aiur.Value.array b => + let pack := fun xs => + List.foldl + (fun n x => + match x with + | (v, i) => + match v with + | Aiur.Value.field g => n + g.val.toNat * 256 ^ i + | x => n) + 0 xs.toList.zipIdx; + let sum := pack a + pack b; + Except.ok + (Aiur.Value.tuple + #[Aiur.Value.array + (Array.map (fun i => Aiur.Value.field (Aiur.G.ofNat (sum / 256 ^ i % 256))) #[0, 1, 2, 3]), + Aiur.Value.field (Aiur.G.ofNat (sum / 4294967296))], + st2) + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedU32Add") + | t1.unconstrainedU32Add3 t2 t3 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v1, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (v2, st2) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t3 st2 with + | Except.error e => Except.error e + | Except.ok (v3, st3) => + match v1, v2, v3 with + | Aiur.Value.array a, Aiur.Value.array b, Aiur.Value.array c => + let pack := fun xs => + List.foldl + (fun n x => + match x with + | (v, i) => + match v with + | Aiur.Value.field g => n + g.val.toNat * 256 ^ i + | x => n) + 0 xs.toList.zipIdx; + let sum := pack a + pack b + pack c; + Except.ok + (Aiur.Value.tuple + #[Aiur.Value.array + (Array.map (fun i => Aiur.Value.field (Aiur.G.ofNat (sum / 256 ^ i % 256))) #[0, 1, 2, 3]), + Aiur.Value.field (Aiur.G.ofNat (sum / 4294967296))], + st3) + | x, x_1, x_2 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedU32Add3") + | t.u32ToField => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (Aiur.Value.array a, st') => + Except.ok + (Aiur.Value.field + (Aiur.G.ofNat + (List.foldl + (fun n x => + match x with + | (v, i) => + match v with + | Aiur.Value.field g => n + g.val.toNat * 256 ^ i + | x => n) + 0 a.toList.zipIdx)), + st') + | Except.ok a => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "u32ToField") + | t1.u8RangeCheck t2 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (v1, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (v2, st2) => + match v1, v2 with + | Aiur.Value.field a, Aiur.Value.field b => + if (decide (a.val < 256) && decide (b.val < 256)) = true then + Except.ok (Aiur.Value.tuple #[Aiur.Value.field a, Aiur.Value.field b], st2) + else Except.error (Aiur.Source.Eval.SourceError.typeMismatch "u8RangeCheck") + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "u8RangeCheck") + | t1.unconstrainedBigUintDivMod t2 => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t1 st with + | Except.error e => Except.error e + | Except.ok (aPtr, st1) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t2 st1 with + | Except.error e => Except.error e + | Except.ok (bPtr, st2) => Aiur.Source.Eval.bigUintDivModValue decls aPtr bPtr st2 + | t.unconstrainedGToBytes => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.field g => Except.ok (Aiur.Value.array (Array.ofFn fun i => Aiur.Value.field (g.toLeBytes i)), st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedGToBytes") + | t.unconstrainedGInverse => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st with + | Except.error e => Except.error e + | Except.ok (v, st') => + match v with + | Aiur.Value.field g => Except.ok (Aiur.Value.field g.inverse, st') + | x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedGInverse") + | t.toField => Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st + | t.u8FromFieldUnsafe => Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings t st + | Aiur.Source.Term.u8Lit n => Except.ok (Aiur.Value.field (Aiur.G.ofNat n), st) + | Aiur.Source.Term.debug a none ret => Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings ret st + | Aiur.Source.Term.debug a (some value) ret => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings value st with + | Except.error error => Except.error error + | Except.ok (fst, st') => Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings ret st' + | channel.ioGetInfo key => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings channel st with + | Except.error e => Except.error e + | Except.ok (vc, stc) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings key stc with + | Except.error e => Except.error e + | Except.ok (v, st') => + match vc, v with + | Aiur.Value.field channelG, Aiur.Value.array vs => + match Aiur.Source.Eval.expectFieldArray vs with + | none => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ioGetInfo key") + | some keyGs => + match st'.ioBuffer.map[(channelG, keyGs)]? with + | some info => + Except.ok + (Aiur.Value.tuple #[Aiur.Value.field (Aiur.G.ofNat info.idx), Aiur.Value.field (Aiur.G.ofNat info.len)], + st') + | none => Except.error Aiur.Source.Eval.SourceError.ioKeyNotFound + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ioGetInfo") + | channel.ioSetInfo key idx len ret => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings channel st with + | Except.error e => Except.error e + | Except.ok (vc, stc) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings key stc with + | Except.error e => Except.error e + | Except.ok (vk, stk) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings idx stk with + | Except.error e => Except.error e + | Except.ok (vi, sti) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings len sti with + | Except.error e => Except.error e + | Except.ok (vl, stl) => + match vc, vk, vi, vl with + | Aiur.Value.field channelG, Aiur.Value.array vs, Aiur.Value.field iG, Aiur.Value.field lG => + match Aiur.Source.Eval.expectFieldArray vs with + | none => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ioSetInfo key") + | some keyGs => + if stl.ioBuffer.map.contains (channelG, keyGs) = true then + Except.error Aiur.Source.Eval.SourceError.ioKeyAlreadySet + else + let info := { idx := iG.val.toNat, len := lG.val.toNat }; + let st' := + { store := stl.store, + ioBuffer := + let __src := stl.ioBuffer; + { data := __src.data, map := stl.ioBuffer.map.insert (channelG, keyGs) info } }; + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings ret st' + | x, x_1, x_2, x_3 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ioSetInfo") + | channel.ioRead idx len => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings channel st with + | Except.error e => Except.error e + | Except.ok (vc, stc) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings idx stc with + | Except.error e => Except.error e + | Except.ok (v, st') => + match vc, v with + | Aiur.Value.field channelG, Aiur.Value.field g => + let start := g.val.toNat; + let arena := st'.ioBuffer.data.getD channelG #[]; + if start + len > arena.size then Except.error Aiur.Source.Eval.SourceError.ioReadOoB + else Except.ok (Aiur.Value.array (Array.map Aiur.Value.field (arena.extract start (start + len))), st') + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ioRead") + | channel.ioWrite data ret => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings channel st with + | Except.error e => Except.error e + | Except.ok (vc, stc) => + match Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings data stc with + | Except.error e => Except.error e + | Except.ok (v, st') => + match vc, v with + | Aiur.Value.field channelG, Aiur.Value.array vs => + match Aiur.Source.Eval.expectFieldArray vs with + | none => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ioWrite") + | some dataGs => + let arena := st'.ioBuffer.data.getD channelG #[]; + let st'' := + { store := st'.store, + ioBuffer := + let __src := st'.ioBuffer; + { data := st'.ioBuffer.data.insert channelG (arena ++ dataGs), map := __src.map } }; + Aiur.Source.Eval.interp._unsafe_rec decls fuel bindings ret st'' + | x, x_1 => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "ioWrite") +RECURSION WORKER Aiur.Source.Eval.matchPatsArr._unsafe_rec +Aiur.Source.Eval.Store → Array Aiur.Pattern → Array Aiur.Value → Option Aiur.Source.Eval.Bindings +IMPLEMENTATION +fun store pats vs => Aiur.Source.Eval.matchPatsList._unsafe_rec store pats.toList vs.toList +RECURSION WORKER Aiur.Source.Eval.matchPatsList._unsafe_rec +Aiur.Source.Eval.Store → List Aiur.Pattern → List Aiur.Value → Option Aiur.Source.Eval.Bindings +IMPLEMENTATION +fun store x x_1 => + match x, x_1 with + | [], [] => some [] + | p :: ps, v :: vs => do + let b1 ← Aiur.Source.Eval.matchPattern._unsafe_rec store p v + let b2 ← Aiur.Source.Eval.matchPatsList._unsafe_rec store ps vs + pure (b1 ++ b2) + | x, x_2 => none +RECURSION WORKER Aiur.Source.Eval.matchPattern._unsafe_rec +Aiur.Source.Eval.Store → Aiur.Pattern → Aiur.Value → Option Aiur.Source.Eval.Bindings +IMPLEMENTATION +fun store x x_1 => + match x, x_1 with + | Aiur.Pattern.wildcard, x => some [] + | Aiur.Pattern.var l, v => some [(l, v)] + | Aiur.Pattern.field g, Aiur.Value.field g' => if (g == g') = true then some [] else none + | Aiur.Pattern.tuple pats, Aiur.Value.tuple vs => Aiur.Source.Eval.matchPatsArr._unsafe_rec store pats vs + | Aiur.Pattern.array pats, Aiur.Value.array vs => Aiur.Source.Eval.matchPatsArr._unsafe_rec store pats vs + | Aiur.Pattern.ref g pats, Aiur.Value.ctor g' vs => + if (g != g') = true then none else Aiur.Source.Eval.matchPatsList._unsafe_rec store pats vs.toList + | p1.or p2, v => + Aiur.Source.Eval.matchPattern._unsafe_rec store p1 v <|> Aiur.Source.Eval.matchPattern._unsafe_rec store p2 v + | p.pointer, Aiur.Value.pointer w n => + match store[w]? with + | some inner => + match inner.getByIdx n with + | some (vs, snd) => vs[0]?.bind fun x => Aiur.Source.Eval.matchPattern._unsafe_rec store p x + | none => none + | none => none + | x, x_2 => none +RECURSION WORKER Aiur.Source.Eval.readLimbChain._unsafe_rec +Aiur.Source.Decls → + Aiur.Source.Eval.EvalState → + Nat → Aiur.Value → Except Aiur.Source.Eval.SourceError (Aiur.DataType × List (Array Aiur.G)) +IMPLEMENTATION +fun decls st x x_1 => + match x, x_1 with + | 0, x => Except.error (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedBigUintDivMod: cyclic limb list") + | steps.succ, ptrVal => + match ptrVal with + | Aiur.Value.pointer w n => do + let __do_lift ← Aiur.Source.Eval.loadValue st w n + match __do_lift with + | Aiur.Value.ctor g args => do + let __x ← Aiur.Source.Eval.ctorInfo decls g + match __x with + | (dt, tag) => + if (tag == 1) = true then pure (dt, []) + else + if (tag == 0) = true then + match args with + | #[Aiur.Value.array byteVals, rest] => do + let bytes ← + Array.mapM + (fun bv => + match bv with + | Aiur.Value.field b => + if b.val < 256 then pure b + else + throw + (Aiur.Source.Eval.SourceError.typeMismatch + "unconstrainedBigUintDivMod: limb byte out of range") + | x => + throw + (Aiur.Source.Eval.SourceError.typeMismatch + "unconstrainedBigUintDivMod: limb byte not a field")) + byteVals + if (bytes.size == 8) = true then do + let __x ← Aiur.Source.Eval.readLimbChain._unsafe_rec decls st steps rest + match __x with + | (fst, restLimbs) => pure (dt, bytes :: restLimbs) + else + throw + (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedBigUintDivMod: limb is not [U8; 8]") + | x => + throw (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedBigUintDivMod: malformed Cons node") + else + throw + (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedBigUintDivMod: unexpected constructor tag") + | x => throw (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedBigUintDivMod: node is not a constructor") + | x => throw (Aiur.Source.Eval.SourceError.typeMismatch "unconstrainedBigUintDivMod: input is not a pointer") +RECURSION WORKER Aiur.Source.Pattern.locals._unsafe_rec +Aiur.Pattern → List Aiur.Local +IMPLEMENTATION +fun x => + match x with + | Aiur.Pattern.var x => [x] + | Aiur.Pattern.wildcard => [] + | Aiur.Pattern.field a => [] + | Aiur.Pattern.ref a ps => + List.foldl + (fun acc x => + match x with + | ⟨p, property⟩ => acc ++ Aiur.Source.Pattern.locals._unsafe_rec p) + [] ps.attach + | Aiur.Pattern.tuple ps => + Array.foldl + (fun acc x => + match x with + | ⟨p, property⟩ => acc ++ Aiur.Source.Pattern.locals._unsafe_rec p) + [] ps.attach + | Aiur.Pattern.array ps => + Array.foldl + (fun acc x => + match x with + | ⟨p, property⟩ => acc ++ Aiur.Source.Pattern.locals._unsafe_rec p) + [] ps.attach + | p.or q => Aiur.Source.Pattern.locals._unsafe_rec p ++ Aiur.Source.Pattern.locals._unsafe_rec q + | p.pointer => Aiur.Source.Pattern.locals._unsafe_rec p +RECURSION WORKER Aiur.Source.Pattern.mapLocals._unsafe_rec +(Aiur.Local → Aiur.Local) → Aiur.Pattern → Aiur.Pattern +IMPLEMENTATION +fun f x => + match x with + | Aiur.Pattern.var x => Aiur.Pattern.var (f x) + | Aiur.Pattern.wildcard => Aiur.Pattern.wildcard + | Aiur.Pattern.field g => Aiur.Pattern.field g + | Aiur.Pattern.ref g ps => + Aiur.Pattern.ref g + (List.map + (fun x => + match x with + | ⟨p, property⟩ => Aiur.Source.Pattern.mapLocals._unsafe_rec f p) + ps.attach) + | Aiur.Pattern.tuple ps => + Aiur.Pattern.tuple + (Array.map + (fun x => + match x with + | ⟨p, property⟩ => Aiur.Source.Pattern.mapLocals._unsafe_rec f p) + ps.attach) + | Aiur.Pattern.array ps => + Aiur.Pattern.array + (Array.map + (fun x => + match x with + | ⟨p, property⟩ => Aiur.Source.Pattern.mapLocals._unsafe_rec f p) + ps.attach) + | p.or q => (Aiur.Source.Pattern.mapLocals._unsafe_rec f p).or (Aiur.Source.Pattern.mapLocals._unsafe_rec f q) + | p.pointer => (Aiur.Source.Pattern.mapLocals._unsafe_rec f p).pointer +RECURSION WORKER Aiur.Source.Term.expandOnce._unsafe_rec +Std.HashMap Aiur.Global (List Aiur.Local × Aiur.Source.Term) → Nat → Aiur.Source.Term → Nat × Aiur.Source.Term +IMPLEMENTATION +fun done cnt t => + match t with + | Aiur.Source.Term.app g args Aiur.Source.CallMode.inlined => + match + List.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨a, property⟩ => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, acc ++ [a'])) + (cnt, []) args.attach with + | (cnt, args') => + match done[g]? with + | none => (cnt, Aiur.Source.Term.app g args' Aiur.Source.CallMode.inlined) + | some (ins, body) => + if body.hasExplicitReturn = true then (cnt, Aiur.Source.Term.app g args' Aiur.Source.CallMode.normal) + else + match + List.foldl + (fun x inp => + match x with + | (cnt, subst, acc) => + let inp' := Aiur.Local.str (toString "inl#" ++ toString cnt); + (cnt + 1, subst.insert inp inp', acc ++ [inp'])) + (cnt, ∅, []) ins with + | (cnt, subst, freshInputs) => + match Aiur.Source.Term.freshen cnt subst body with + | (cnt, freshBody) => + match + match freshBody.peelLets with + | (fs, core@h:(a.match a_1)) => + let out := Aiur.Local.str (toString "inl#" ++ toString cnt); + (cnt + 1, + Aiur.Source.Term.wrapLets fs + (Aiur.Source.Term.let (Aiur.Pattern.var out) core (Aiur.Source.Term.var out))) + | x => (cnt, freshBody) with + | (cnt, freshBody) => + (cnt, + List.foldr + (fun x acc => + match x with + | (input, arg) => Aiur.Source.Term.let (Aiur.Pattern.var input) arg acc) + freshBody (freshInputs.zip args')) + | Aiur.Source.Term.app g args mode => + match + List.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨a, property⟩ => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, acc ++ [a'])) + (cnt, []) args.attach with + | (cnt, args') => (cnt, Aiur.Source.Term.app g args' mode) + | Aiur.Source.Term.unit => (cnt, t) + | Aiur.Source.Term.var a => (cnt, t) + | Aiur.Source.Term.ref a => (cnt, t) + | Aiur.Source.Term.field a => (cnt, t) + | Aiur.Source.Term.u8Lit a => (cnt, t) + | Aiur.Source.Term.tuple ts => + match + Array.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨a, property⟩ => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, acc.push a')) + (cnt, #[]) ts.attach with + | (cnt, ts') => (cnt, Aiur.Source.Term.tuple ts') + | Aiur.Source.Term.array ts => + match + Array.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨a, property⟩ => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, acc.push a')) + (cnt, #[]) ts.attach with + | (cnt, ts') => (cnt, Aiur.Source.Term.array ts') + | s.match arms => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt s with + | (cnt, s') => + match + List.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨(p, a), property⟩ => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, acc ++ [(p, a')])) + (cnt, []) arms.attach with + | (cnt, arms') => (cnt, s'.match arms') + | Aiur.Source.Term.let p v b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt v with + | (cnt, v') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, Aiur.Source.Term.let p v' b') + | a.ret => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.ret) + | a.add b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.add b') + | a.sub b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.sub b') + | a.mul b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.mul b') + | a.eqZero => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.eqZero) + | a.proj n => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.proj n) + | a.get n => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.get n) + | a.slice i j => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.slice i j) + | a.set n v => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt v with + | (cnt, v') => (cnt, a'.set n v') + | a.store => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.store) + | a.load => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.load) + | a.ptrVal => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.ptrVal) + | Aiur.Source.Term.ann τ a => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, Aiur.Source.Term.ann τ a') + | a.assertEq b msg c => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt c with + | (cnt, c') => (cnt, a'.assertEq b' msg c') + | c.ioGetInfo k => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt c with + | (cnt, c') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt k with + | (cnt, k') => (cnt, c'.ioGetInfo k') + | c.ioSetInfo k i l rv => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt c with + | (cnt, c') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt k with + | (cnt, k') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt i with + | (cnt, i') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt l with + | (cnt, l') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt rv with + | (cnt, rv') => (cnt, c'.ioSetInfo k' i' l' rv') + | c.ioRead i n => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt c with + | (cnt, c') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt i with + | (cnt, i') => (cnt, c'.ioRead i' n) + | c.ioWrite d rv => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt c with + | (cnt, c') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt d with + | (cnt, d') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt rv with + | (cnt, rv') => (cnt, c'.ioWrite d' rv') + | a.u8BitDecomposition => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.u8BitDecomposition) + | a.u8ShiftLeft => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.u8ShiftLeft) + | a.u8ShiftRight => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.u8ShiftRight) + | a.u8Xor b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8Xor b') + | a.u8Add b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8Add b') + | a.u8Mul b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8Mul b') + | a.u8Sub b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8Sub b') + | a.u8And b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8And b') + | a.u8Or b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8Or b') + | a.u8LessThan b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8LessThan b') + | a.u32LessThan b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u32LessThan b') + | a.u8XorSplit7 b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8XorSplit7 b') + | a.u8XorSplit4 b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8XorSplit4 b') + | a.unconstrainedU32Add b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.unconstrainedU32Add b') + | a.unconstrainedU32Add3 b c => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt c with + | (cnt, c') => (cnt, a'.unconstrainedU32Add3 b' c') + | a.u32ToField => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.u32ToField) + | a.unconstrainedBigUintDivMod b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.unconstrainedBigUintDivMod b') + | a.u8RangeCheck b => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt b with + | (cnt, b') => (cnt, a'.u8RangeCheck b') + | a.toField => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.toField) + | a.u8FromFieldUnsafe => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.u8FromFieldUnsafe) + | a.unconstrainedGToBytes => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.unconstrainedGToBytes) + | a.unconstrainedGInverse => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, a'.unconstrainedGInverse) + | Aiur.Source.Term.debug s o a => + match + match o with + | none => (cnt, none) + | some x => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt x with + | (cnt, x') => (cnt, some x') with + | (cnt, o') => + match Aiur.Source.Term.expandOnce._unsafe_rec done cnt a with + | (cnt, a') => (cnt, Aiur.Source.Term.debug s o' a') +RECURSION WORKER Aiur.Source.Term.freshBound._unsafe_rec +Aiur.Source.Term → Nat +IMPLEMENTATION +fun x => + match x with + | Aiur.Source.Term.unit => 0 + | Aiur.Source.Term.field a => 0 + | Aiur.Source.Term.u8Lit a => 0 + | Aiur.Source.Term.var x => Aiur.Source.localFreshBound x + | Aiur.Source.Term.ref g => Aiur.Source.globalFreshBound g + | Aiur.Source.Term.app g args mode => + List.foldl + (fun acc x => + match x with + | ⟨a, property⟩ => max acc (Aiur.Source.Term.freshBound._unsafe_rec a)) + (Aiur.Source.globalFreshBound g) args.attach + | Aiur.Source.Term.tuple ts => + Array.foldl + (fun acc x => + match x with + | ⟨a, property⟩ => max acc (Aiur.Source.Term.freshBound._unsafe_rec a)) + 0 ts.attach + | Aiur.Source.Term.array ts => + Array.foldl + (fun acc x => + match x with + | ⟨a, property⟩ => max acc (Aiur.Source.Term.freshBound._unsafe_rec a)) + 0 ts.attach + | Aiur.Source.Term.let p v b => + max (List.foldl (fun n x => max n (Aiur.Source.localFreshBound x)) 0 (Aiur.Source.Pattern.locals p)) + (max (Aiur.Source.Term.freshBound._unsafe_rec v) (Aiur.Source.Term.freshBound._unsafe_rec b)) + | s.match arms => + List.foldl + (fun acc x => + match x with + | ⟨(p, a), property⟩ => + max acc + (max (List.foldl (fun n x => max n (Aiur.Source.localFreshBound x)) 0 (Aiur.Source.Pattern.locals p)) + (Aiur.Source.Term.freshBound._unsafe_rec a))) + (Aiur.Source.Term.freshBound._unsafe_rec s) arms.attach + | a.add b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.sub b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.mul b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.set a_1 b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8Xor b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8Add b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8Mul b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8Sub b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8And b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8Or b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8LessThan b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u32LessThan b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8XorSplit7 b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8XorSplit4 b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.unconstrainedU32Add b => + max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.unconstrainedBigUintDivMod b => + max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.u8RangeCheck b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.ioGetInfo b => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.ioRead b len => max (Aiur.Source.Term.freshBound._unsafe_rec a) (Aiur.Source.Term.freshBound._unsafe_rec b) + | a.assertEq b msg c => + max (Aiur.Source.Term.freshBound._unsafe_rec a) + (max (Aiur.Source.Term.freshBound._unsafe_rec b) (Aiur.Source.Term.freshBound._unsafe_rec c)) + | a.ioWrite b c => + max (Aiur.Source.Term.freshBound._unsafe_rec a) + (max (Aiur.Source.Term.freshBound._unsafe_rec b) (Aiur.Source.Term.freshBound._unsafe_rec c)) + | a.unconstrainedU32Add3 b c => + max (Aiur.Source.Term.freshBound._unsafe_rec a) + (max (Aiur.Source.Term.freshBound._unsafe_rec b) (Aiur.Source.Term.freshBound._unsafe_rec c)) + | c.ioSetInfo k i l r => + max (Aiur.Source.Term.freshBound._unsafe_rec c) + (max (Aiur.Source.Term.freshBound._unsafe_rec k) + (max (Aiur.Source.Term.freshBound._unsafe_rec i) + (max (Aiur.Source.Term.freshBound._unsafe_rec l) (Aiur.Source.Term.freshBound._unsafe_rec r)))) + | a.ret => Aiur.Source.Term.freshBound._unsafe_rec a + | a.eqZero => Aiur.Source.Term.freshBound._unsafe_rec a + | a.proj a_1 => Aiur.Source.Term.freshBound._unsafe_rec a + | a.get a_1 => Aiur.Source.Term.freshBound._unsafe_rec a + | a.slice a_1 a_2 => Aiur.Source.Term.freshBound._unsafe_rec a + | a.store => Aiur.Source.Term.freshBound._unsafe_rec a + | a.load => Aiur.Source.Term.freshBound._unsafe_rec a + | a.ptrVal => Aiur.Source.Term.freshBound._unsafe_rec a + | Aiur.Source.Term.ann a a_1 => Aiur.Source.Term.freshBound._unsafe_rec a_1 + | a.u8BitDecomposition => Aiur.Source.Term.freshBound._unsafe_rec a + | a.u8ShiftLeft => Aiur.Source.Term.freshBound._unsafe_rec a + | a.u8ShiftRight => Aiur.Source.Term.freshBound._unsafe_rec a + | a.toField => Aiur.Source.Term.freshBound._unsafe_rec a + | a.u8FromFieldUnsafe => Aiur.Source.Term.freshBound._unsafe_rec a + | a.unconstrainedGToBytes => Aiur.Source.Term.freshBound._unsafe_rec a + | a.unconstrainedGInverse => Aiur.Source.Term.freshBound._unsafe_rec a + | a.u32ToField => Aiur.Source.Term.freshBound._unsafe_rec a + | Aiur.Source.Term.debug a o a_1 => + max (Aiur.Source.Term.freshBound._unsafe_rec a_1) + (match o with + | none => 0 + | some b => Aiur.Source.Term.freshBound._unsafe_rec b) +RECURSION WORKER Aiur.Source.Term.freshen._unsafe_rec +Nat → Std.HashMap Aiur.Local Aiur.Local → Aiur.Source.Term → Nat × Aiur.Source.Term +IMPLEMENTATION +fun cnt subst t => + match t with + | Aiur.Source.Term.var x => (cnt, Aiur.Source.Term.var (subst.getD x x)) + | Aiur.Source.Term.unit => (cnt, t) + | Aiur.Source.Term.ref a => (cnt, t) + | Aiur.Source.Term.field a => (cnt, t) + | Aiur.Source.Term.u8Lit a => (cnt, t) + | Aiur.Source.Term.let p v b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst v with + | (cnt, v') => + match Aiur.Source.Pattern.freshen cnt subst p with + | (cnt, subst', p') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst' b with + | (cnt, b') => (cnt, Aiur.Source.Term.let p' v' b') + | s.match arms => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst s with + | (cnt, s') => + match + List.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨(p, a), property⟩ => + match Aiur.Source.Pattern.freshen cnt subst p with + | (cnt, subst', p') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst' a with + | (cnt, a') => (cnt, acc ++ [(p', a')])) + (cnt, []) arms.attach with + | (cnt, arms') => (cnt, s'.match arms') + | Aiur.Source.Term.tuple ts => + match + Array.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨x, property⟩ => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst x with + | (cnt, x') => (cnt, acc.push x')) + (cnt, #[]) ts.attach with + | (cnt, ts') => (cnt, Aiur.Source.Term.tuple ts') + | Aiur.Source.Term.array ts => + match + Array.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨x, property⟩ => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst x with + | (cnt, x') => (cnt, acc.push x')) + (cnt, #[]) ts.attach with + | (cnt, ts') => (cnt, Aiur.Source.Term.array ts') + | Aiur.Source.Term.app g args mode => + match + List.foldl + (fun x x_1 => + match x with + | (cnt, acc) => + match x_1 with + | ⟨x, property⟩ => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst x with + | (cnt, x') => (cnt, acc ++ [x'])) + (cnt, []) args.attach with + | (cnt, args') => (cnt, Aiur.Source.Term.app (Aiur.Source.freshenCall subst g) args' mode) + | a.ret => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.ret) + | a.add b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.add b') + | a.sub b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.sub b') + | a.mul b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.mul b') + | a.eqZero => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.eqZero) + | a.proj n => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.proj n) + | a.get n => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.get n) + | a.slice i j => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.slice i j) + | a.set n v => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst v with + | (cnt, v') => (cnt, a'.set n v') + | a.store => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.store) + | a.load => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.load) + | a.ptrVal => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.ptrVal) + | Aiur.Source.Term.ann τ a => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, Aiur.Source.Term.ann τ a') + | a.assertEq b msg c => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst c with + | (cnt, c') => (cnt, a'.assertEq b' msg c') + | c.ioGetInfo k => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst c with + | (cnt, c') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst k with + | (cnt, k') => (cnt, c'.ioGetInfo k') + | c.ioSetInfo k i l rv => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst c with + | (cnt, c') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst k with + | (cnt, k') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst i with + | (cnt, i') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst l with + | (cnt, l') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst rv with + | (cnt, rv') => (cnt, c'.ioSetInfo k' i' l' rv') + | c.ioRead i n => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst c with + | (cnt, c') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst i with + | (cnt, i') => (cnt, c'.ioRead i' n) + | c.ioWrite d rv => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst c with + | (cnt, c') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst d with + | (cnt, d') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst rv with + | (cnt, rv') => (cnt, c'.ioWrite d' rv') + | a.u8BitDecomposition => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.u8BitDecomposition) + | a.u8ShiftLeft => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.u8ShiftLeft) + | a.u8ShiftRight => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.u8ShiftRight) + | a.u8Xor b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8Xor b') + | a.u8Add b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8Add b') + | a.u8Mul b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8Mul b') + | a.u8Sub b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8Sub b') + | a.u8And b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8And b') + | a.u8Or b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8Or b') + | a.u8LessThan b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8LessThan b') + | a.u32LessThan b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u32LessThan b') + | a.u8XorSplit7 b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8XorSplit7 b') + | a.u8XorSplit4 b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8XorSplit4 b') + | a.unconstrainedU32Add b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.unconstrainedU32Add b') + | a.unconstrainedU32Add3 b c => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst c with + | (cnt, c') => (cnt, a'.unconstrainedU32Add3 b' c') + | a.u32ToField => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.u32ToField) + | a.unconstrainedBigUintDivMod b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.unconstrainedBigUintDivMod b') + | a.u8RangeCheck b => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst b with + | (cnt, b') => (cnt, a'.u8RangeCheck b') + | a.toField => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.toField) + | a.u8FromFieldUnsafe => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.u8FromFieldUnsafe) + | a.unconstrainedGToBytes => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.unconstrainedGToBytes) + | a.unconstrainedGInverse => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, a'.unconstrainedGInverse) + | Aiur.Source.Term.debug s o a => + match + match o with + | none => (cnt, none) + | some x => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst x with + | (cnt, x') => (cnt, some x') with + | (cnt, o') => + match Aiur.Source.Term.freshen._unsafe_rec cnt subst a with + | (cnt, a') => (cnt, Aiur.Source.Term.debug s o' a') +RECURSION WORKER Aiur.Source.Term.hasExplicitReturn._unsafe_rec +Aiur.Source.Term → Bool +IMPLEMENTATION +fun x => + match x with + | a.ret => true + | Aiur.Source.Term.var a => false + | Aiur.Source.Term.unit => false + | Aiur.Source.Term.field a => false + | Aiur.Source.Term.u8Lit a => false + | Aiur.Source.Term.ref a => false + | Aiur.Source.Term.app a args mode => + args.attach.any fun arg => Aiur.Source.Term.hasExplicitReturn._unsafe_rec arg.val + | Aiur.Source.Term.tuple terms => terms.attach.any fun term => Aiur.Source.Term.hasExplicitReturn._unsafe_rec term.val + | Aiur.Source.Term.array terms => terms.attach.any fun term => Aiur.Source.Term.hasExplicitReturn._unsafe_rec term.val + | Aiur.Source.Term.let a value body => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec value || Aiur.Source.Term.hasExplicitReturn._unsafe_rec body + | scrut.match arms => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec scrut || + arms.attach.any fun arm => Aiur.Source.Term.hasExplicitReturn._unsafe_rec arm.val.snd + | a.eqZero => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.proj a_1 => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.get a_1 => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.slice a_1 a_2 => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.store => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.load => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.ptrVal => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | Aiur.Source.Term.ann a a_1 => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a_1 + | a.u8BitDecomposition => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.u8ShiftLeft => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.u8ShiftRight => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.u32ToField => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.unconstrainedGToBytes => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.unconstrainedGInverse => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.toField => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.u8FromFieldUnsafe => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a + | a.add b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.sub b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.mul b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.set a_1 b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.ioGetInfo b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.ioRead b len => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8Xor b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8Add b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8Mul b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8Sub b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8And b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8Or b => Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8LessThan b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u32LessThan b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8XorSplit7 b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8XorSplit4 b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.unconstrainedU32Add b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.unconstrainedBigUintDivMod b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.u8RangeCheck b => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b + | a.assertEq b msg c => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b || + Aiur.Source.Term.hasExplicitReturn._unsafe_rec c + | a.ioWrite b c => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b || + Aiur.Source.Term.hasExplicitReturn._unsafe_rec c + | a.unconstrainedU32Add3 b c => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b || + Aiur.Source.Term.hasExplicitReturn._unsafe_rec c + | a.ioSetInfo b c d e => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec a || Aiur.Source.Term.hasExplicitReturn._unsafe_rec b || + Aiur.Source.Term.hasExplicitReturn._unsafe_rec c || + Aiur.Source.Term.hasExplicitReturn._unsafe_rec d || + Aiur.Source.Term.hasExplicitReturn._unsafe_rec e + | Aiur.Source.Term.debug a none continuation => Aiur.Source.Term.hasExplicitReturn._unsafe_rec continuation + | Aiur.Source.Term.debug a (some value) continuation => + Aiur.Source.Term.hasExplicitReturn._unsafe_rec value || Aiur.Source.Term.hasExplicitReturn._unsafe_rec continuation +RECURSION WORKER Aiur.Source.Term.hoistLetsAux._unsafe_rec +Aiur.Source.Term → StateM Nat Aiur.Source.Term +IMPLEMENTATION +fun t => + match t with + | Aiur.Source.Term.unit => pure t + | Aiur.Source.Term.var a => pure t + | Aiur.Source.Term.ref a => pure t + | Aiur.Source.Term.field a => pure t + | Aiur.Source.Term.u8Lit a => pure t + | Aiur.Source.Term.let p v b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec v + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + pure (Aiur.Source.Term.let p __do_lift __do_lift_1) + | s.match arms => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec s + match __do_lift.peelLets with + | (fs, sc) => do + let arms ← + List.mapM + (fun x => + match x with + | ⟨(p, a), property⟩ => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (p, __do_lift)) + arms.attach + pure (Aiur.Source.Term.wrapLets fs (sc.match arms)) + | a.ret => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.ret __do_lift) + | Aiur.Source.Term.debug s o a => + have __do_jp := fun o' => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.let Aiur.Pattern.wildcard (Aiur.Source.Term.debug s o' Aiur.Source.Term.unit) __do_lift); + match o with + | none => do + let o' ← pure none + __do_jp o' + | some x => do + let x ← Aiur.Source.Term.hoistLetsAux._unsafe_rec x + let o' ← pure (some x) + __do_jp o' + | Aiur.Source.Term.tuple ts => do + let ts ← + Array.mapM + (fun x => + match x with + | ⟨x, property⟩ => Aiur.Source.Term.hoistLetsAux._unsafe_rec x) + ts.attach + let __x ← Aiur.Source.Term.peelListLets ts.toList + match __x with + | (fs, cs) => pure (Aiur.Source.Term.wrapLets fs (Aiur.Source.Term.tuple cs.toArray)) + | Aiur.Source.Term.array ts => do + let ts ← + Array.mapM + (fun x => + match x with + | ⟨x, property⟩ => Aiur.Source.Term.hoistLetsAux._unsafe_rec x) + ts.attach + let __x ← Aiur.Source.Term.peelListLets ts.toList + match __x with + | (fs, cs) => pure (Aiur.Source.Term.wrapLets fs (Aiur.Source.Term.array cs.toArray)) + | Aiur.Source.Term.app g args mode => do + let args ← + List.mapM + (fun x => + match x with + | ⟨x, property⟩ => Aiur.Source.Term.hoistLetsAux._unsafe_rec x) + args.attach + let __x ← Aiur.Source.Term.peelListLets args + match __x with + | (fs, cs) => pure (Aiur.Source.Term.wrapLets fs (Aiur.Source.Term.app g cs mode)) + | a.assertEq b msg c => do + let a ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let b ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + let c ← Aiur.Source.Term.hoistLetsAux._unsafe_rec c + Aiur.Source.Term.hoistBinaryLets + (fun a b => Aiur.Source.Term.let Aiur.Pattern.wildcard (a.assertEq b msg Aiur.Source.Term.unit) c) a b + | a.ioSetInfo b c d e => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + let __do_lift_2 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec c + let __do_lift_3 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec d + let args : List Aiur.Source.Term := [__do_lift, __do_lift_1, __do_lift_2, __do_lift_3] + let e ← Aiur.Source.Term.hoistLetsAux._unsafe_rec e + let __x ← Aiur.Source.Term.peelListLets args + match __x with + | (fs, cs) => + match cs with + | [a, b, c, d] => + pure + (Aiur.Source.Term.wrapLets fs + (Aiur.Source.Term.let Aiur.Pattern.wildcard (a.ioSetInfo b c d Aiur.Source.Term.unit) e)) + | x => pure t + | a.ioWrite b c => do + let a ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let b ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + let c ← Aiur.Source.Term.hoistLetsAux._unsafe_rec c + Aiur.Source.Term.hoistBinaryLets + (fun a b => Aiur.Source.Term.let Aiur.Pattern.wildcard (a.ioWrite b Aiur.Source.Term.unit) c) a b + | a.ioGetInfo b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.ioGetInfo __do_lift __do_lift_1 + | a.ioRead b n => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets (fun a b => a.ioRead b n) __do_lift __do_lift_1 + | a.add b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.add __do_lift __do_lift_1 + | a.sub b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.sub __do_lift __do_lift_1 + | a.mul b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.mul __do_lift __do_lift_1 + | a.eqZero => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.eqZero __do_lift) + | a.proj n => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets (fun a => a.proj n) __do_lift) + | a.get n => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets (fun a => a.get n) __do_lift) + | a.slice i j => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets (fun a => a.slice i j) __do_lift) + | a.set n v => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec v + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + Aiur.Source.Term.hoistBinaryLets (fun v a => a.set n v) __do_lift __do_lift_1 + | a.store => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.store __do_lift) + | a.load => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.load __do_lift) + | a.ptrVal => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.ptrVal __do_lift) + | Aiur.Source.Term.ann τ a => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets (Aiur.Source.Term.ann τ) __do_lift) + | a.u8BitDecomposition => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8BitDecomposition __do_lift) + | a.u8ShiftLeft => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8ShiftLeft __do_lift) + | a.u8ShiftRight => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8ShiftRight __do_lift) + | a.toField => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.toField __do_lift) + | a.u8FromFieldUnsafe => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u8FromFieldUnsafe __do_lift) + | a.unconstrainedGToBytes => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.unconstrainedGToBytes __do_lift) + | a.unconstrainedGInverse => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.unconstrainedGInverse __do_lift) + | a.u8Xor b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Xor __do_lift __do_lift_1 + | a.u8Add b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Add __do_lift __do_lift_1 + | a.u8Mul b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Mul __do_lift __do_lift_1 + | a.u8Sub b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Sub __do_lift __do_lift_1 + | a.u8And b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8And __do_lift __do_lift_1 + | a.u8Or b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8Or __do_lift __do_lift_1 + | a.u8LessThan b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8LessThan __do_lift __do_lift_1 + | a.u32LessThan b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u32LessThan __do_lift __do_lift_1 + | a.u8XorSplit7 b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8XorSplit7 __do_lift __do_lift_1 + | a.u8XorSplit4 b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8XorSplit4 __do_lift __do_lift_1 + | a.unconstrainedU32Add b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.unconstrainedU32Add __do_lift __do_lift_1 + | a.unconstrainedU32Add3 b c => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + let __do_lift_2 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec c + let args : List Aiur.Source.Term := [__do_lift, __do_lift_1, __do_lift_2] + let __x ← Aiur.Source.Term.peelListLets args + match __x with + | (fs, cs) => + match cs with + | [a, b, c] => pure (Aiur.Source.Term.wrapLets fs (a.unconstrainedU32Add3 b c)) + | x => pure t + | a.u32ToField => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + pure (Aiur.Source.Term.hoistUnaryLets Aiur.Source.Term.u32ToField __do_lift) + | a.unconstrainedBigUintDivMod b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.unconstrainedBigUintDivMod __do_lift __do_lift_1 + | a.u8RangeCheck b => do + let __do_lift ← Aiur.Source.Term.hoistLetsAux._unsafe_rec a + let __do_lift_1 ← Aiur.Source.Term.hoistLetsAux._unsafe_rec b + Aiur.Source.Term.hoistBinaryLets Aiur.Source.Term.u8RangeCheck __do_lift __do_lift_1 +RECURSION WORKER Aiur.Source.Term.inlineCallSites._unsafe_rec +Aiur.Source.Term → List (Aiur.Global × Nat) +IMPLEMENTATION +fun x => + match x with + | Aiur.Source.Term.app g args Aiur.Source.CallMode.inlined => + List.foldl + (fun acc x => + match x with + | ⟨a, property⟩ => acc ++ Aiur.Source.Term.inlineCallSites._unsafe_rec a) + [(g, args.length)] args.attach + | Aiur.Source.Term.app a args mode => + List.foldl + (fun acc x => + match x with + | ⟨a, property⟩ => acc ++ Aiur.Source.Term.inlineCallSites._unsafe_rec a) + [] args.attach + | Aiur.Source.Term.unit => [] + | Aiur.Source.Term.var a => [] + | Aiur.Source.Term.ref a => [] + | Aiur.Source.Term.field a => [] + | Aiur.Source.Term.u8Lit a => [] + | Aiur.Source.Term.tuple ts => + Array.foldl + (fun acc x => + match x with + | ⟨a, property⟩ => acc ++ Aiur.Source.Term.inlineCallSites._unsafe_rec a) + [] ts.attach + | Aiur.Source.Term.array ts => + Array.foldl + (fun acc x => + match x with + | ⟨a, property⟩ => acc ++ Aiur.Source.Term.inlineCallSites._unsafe_rec a) + [] ts.attach + | s.match arms => + List.foldl + (fun acc x => + match x with + | ⟨(fst, a), property⟩ => acc ++ Aiur.Source.Term.inlineCallSites._unsafe_rec a) + (Aiur.Source.Term.inlineCallSites._unsafe_rec s) arms.attach + | Aiur.Source.Term.let a v b => + Aiur.Source.Term.inlineCallSites._unsafe_rec v ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.add b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.sub b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.mul b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.set a_1 b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8Xor b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8Add b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8Mul b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8Sub b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8And b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8Or b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8LessThan b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u32LessThan b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8XorSplit7 b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8XorSplit4 b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.unconstrainedU32Add b => + Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.unconstrainedBigUintDivMod b => + Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.u8RangeCheck b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.ioGetInfo b => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.assertEq b msg c => + Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b ++ + Aiur.Source.Term.inlineCallSites._unsafe_rec c + | a.ioWrite b c => + Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b ++ + Aiur.Source.Term.inlineCallSites._unsafe_rec c + | c.ioSetInfo k i l rv => + Aiur.Source.Term.inlineCallSites._unsafe_rec c ++ Aiur.Source.Term.inlineCallSites._unsafe_rec k ++ + Aiur.Source.Term.inlineCallSites._unsafe_rec i ++ + Aiur.Source.Term.inlineCallSites._unsafe_rec l ++ + Aiur.Source.Term.inlineCallSites._unsafe_rec rv + | a.ioRead b len => Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b + | a.ret => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.eqZero => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.proj a_1 => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.get a_1 => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.slice a_1 a_2 => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.store => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.load => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.ptrVal => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | Aiur.Source.Term.ann a a_1 => Aiur.Source.Term.inlineCallSites._unsafe_rec a_1 + | a.u8BitDecomposition => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.u8ShiftLeft => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.u8ShiftRight => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.toField => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.u8FromFieldUnsafe => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.unconstrainedGToBytes => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.unconstrainedGInverse => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.u32ToField => Aiur.Source.Term.inlineCallSites._unsafe_rec a + | a.unconstrainedU32Add3 b c => + Aiur.Source.Term.inlineCallSites._unsafe_rec a ++ Aiur.Source.Term.inlineCallSites._unsafe_rec b ++ + Aiur.Source.Term.inlineCallSites._unsafe_rec c + | Aiur.Source.Term.debug a o a_1 => + (match o with + | none => [] + | some x => Aiur.Source.Term.inlineCallSites._unsafe_rec x) ++ + Aiur.Source.Term.inlineCallSites._unsafe_rec a_1 +RECURSION WORKER Aiur.Source.Term.peelLets._unsafe_rec +Aiur.Source.Term → List (Aiur.Pattern × Aiur.Source.Term) × Aiur.Source.Term +IMPLEMENTATION +fun x => + match x with + | Aiur.Source.Term.let p v b => + match Aiur.Source.Term.peelLets._unsafe_rec b with + | (fs, c) => ((p, v) :: fs, c) + | t => ([], t) +RECURSION WORKER Aiur.Source.Term.restoreTailMatches._unsafe_rec +Aiur.Source.Term → Aiur.Source.Term +IMPLEMENTATION +fun x => + match x with + | Aiur.Source.Term.let (Aiur.Pattern.var x) v (Aiur.Source.Term.var y) => + if (x == y) = true then Aiur.Source.Term.restoreTailMatches._unsafe_rec v + else Aiur.Source.Term.let (Aiur.Pattern.var x) v (Aiur.Source.Term.var y) + | Aiur.Source.Term.let p v b => Aiur.Source.Term.let p v (Aiur.Source.Term.restoreTailMatches._unsafe_rec b) + | s.match arms => + s.match + (List.map (fun arm => (arm.val.fst, Aiur.Source.Term.restoreTailMatches._unsafe_rec arm.val.snd)) arms.attach) + | t => t +RECURSION WORKER Aiur.Source.Term.wrapLets._unsafe_rec +List (Aiur.Pattern × Aiur.Source.Term) → Aiur.Source.Term → Aiur.Source.Term +IMPLEMENTATION +fun x x_1 => + match x, x_1 with + | [], body => body + | (p, v) :: fs, body => Aiur.Source.Term.let p v (Aiur.Source.Term.wrapLets._unsafe_rec fs body) +RECURSION WORKER Aiur.Typ.appendNameLimbs.pushAll._unsafe_rec +Aiur.Global → Name → Aiur.Global +IMPLEMENTATION +fun g a => + match a with + | parent.str s => (Aiur.Typ.appendNameLimbs.pushAll._unsafe_rec g parent).pushNamespace s + | x => g +RECURSION WORKER Aiur.Typ.beq.listBeqAux._unsafe_rec +List Aiur.Typ → List Aiur.Typ → Bool +IMPLEMENTATION +fun a a_1 => + match a, a_1 with + | [], [] => true + | head :: tail, [] => false + | [], head :: tail => false + | t :: rest, t' :: rest' => Aiur.Typ.beq._unsafe_rec t t' && Aiur.Typ.beq.listBeqAux._unsafe_rec rest rest' +RECURSION WORKER Aiur.wellFormedDecls.checkUniqueParams.go._unsafe_rec +Aiur.Global → List String → Std.HashSet String → EStateM Aiur.CheckError (Std.HashSet Aiur.Global) Unit +IMPLEMENTATION +fun name a a_1 => + match a, a_1 with + | [], x => pure () + | p :: ps, seen => + if seen.contains p = true then throw (Aiur.CheckError.duplicatedTypeParam name p) + else Aiur.wellFormedDecls.checkUniqueParams.go._unsafe_rec name ps (seen.insert p) +RECURSION WORKER _private.Ix.Aiur.Goldilocks.0.Aiur.G.pow.go._unsafe_rec +Aiur.G → Nat → Nat → Aiur.G +IMPLEMENTATION +fun x n fuel => + match fuel with + | 0 => 1 + | fuel.succ => + if (n == 0) = true then 1 + else + let h := Aiur.G.pow.go._unsafe_rec✝ x (n / 2) fuel; + let sq := h * h; + if (n % 2 == 0) = true then sq else sq * x +RECURSION WORKER _private.Ix.Aiur.Compiler.Match.0.Aiur.MatchCompiler.dnfProd.aux._unsafe_rec +Aiur.MatchCompiler.TermId → + Aiur.Source.Decls → + Array (Aiur.Local × Aiur.Typed.Term) → + Array Aiur.MatchCompiler.Clause → + List (Aiur.Pattern × Aiur.MatchCompiler.UniqTerm) → + Aiur.MatchCompiler.ExtTerm → Aiur.MatchCompiler.CompilerM (Array Aiur.MatchCompiler.Row) +IMPLEMENTATION +fun initId decls renames clauses branches body => + match branches with + | [] => do + let id ← Aiur.MatchCompiler.Compiler.uniqId <$> get + let row : Aiur.MatchCompiler.Row := + { clauses := clauses, body := { renames := body.renames ++ renames, value := body.value }, uniqId := id } + Aiur.MatchCompiler.setId initId + pure #[row] + | (patL.or patR, term) :: rest => do + let rowsL ← Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames clauses ((patL, term) :: rest) body + let rowsR ← Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames clauses ((patR, term) :: rest) body + pure (rowsL ++ rowsR) + | (Aiur.Pattern.wildcard, snd) :: rest => + Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames clauses rest body + | (Aiur.Pattern.var var, fst, term) :: rest => + Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls (renames.push (var, term)) clauses rest body + | (Aiur.Pattern.field g, term) :: rest => + Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames + (clauses.push { pat := Aiur.MatchCompiler.SPattern.field g, guards := #[], body := term }) rest body + | (Aiur.Pattern.tuple args, term) :: rest => + let argTypes := + match term.snd.typ with + | Aiur.Typ.tuple ts => ts + | x => Array.replicate args.size Aiur.Typ.unit; + do + let __x ← Aiur.MatchCompiler.dnfProd.flattenArgs✝ args argTypes + match __x with + | (vars, guards) => + let clause := { pat := Aiur.MatchCompiler.SPattern.tuple vars, guards := guards, body := term }; + Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames (clauses.push clause) rest body + | (Aiur.Pattern.array args, term) :: rest => + let eltTyp := + match term.snd.typ with + | t.array a => t + | x => Aiur.Typ.unit; + let argTypes := Array.replicate args.size eltTyp; + do + let __x ← Aiur.MatchCompiler.dnfProd.flattenArgs✝ args argTypes + match __x with + | (vars, guards) => + let clause := { pat := Aiur.MatchCompiler.SPattern.array vars, guards := guards, body := term }; + Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames (clauses.push clause) rest body + | (Aiur.Pattern.ref global args, term) :: rest => + let argTypes := Aiur.MatchCompiler.constructorArgTypes✝ decls global term.snd.typ; + do + let __x ← Aiur.MatchCompiler.dnfProd.flattenArgs✝ args.toArray argTypes + match __x with + | (vars, guards) => + let clause := { pat := Aiur.MatchCompiler.SPattern.ref global vars, guards := guards, body := term }; + Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames (clauses.push clause) rest body + | (arg.pointer, term) :: rest => do + let id ← Aiur.MatchCompiler.newId + let var : Aiur.Local := Aiur.Local.idx id + let innerTyp : Aiur.Typ := + match term.snd.typ with + | t.pointer => t + | x => Aiur.Typ.unit + let guards : Array (Aiur.Pattern × Aiur.MatchCompiler.TermId × Aiur.Typed.Term) := + #[(arg, id, Aiur.Typed.Term.var innerTyp false var)] + let clause : Aiur.MatchCompiler.Clause := + { pat := Aiur.MatchCompiler.SPattern.pointer var innerTyp, guards := guards, body := term } + Aiur.MatchCompiler.dnfProd.aux._unsafe_rec✝ initId decls renames (clauses.push clause) rest body +RECURSION WORKER Aiur.NativeAIR.ProofCodec.Extension.powBits._unsafe_rec +Aiur.NativeAIR.ProofCodec.Extension → Nat → Nat → Aiur.NativeAIR.ProofCodec.Extension +IMPLEMENTATION +fun value exponent x => + match x with + | 0 => 1 + | fuel.succ => + if (exponent == 0) = true then 1 + else + let half := Aiur.NativeAIR.ProofCodec.Extension.powBits._unsafe_rec value (exponent / 2) fuel; + let square := half * half; + if (exponent % 2 == 0) = true then square else square * value +C8 component ROOTS 1574; LOGICAL DECLARATIONS 20519; WITH RUNTIME 21338 +IX RUNTIME EXTERNS [Aiur.AiurSystem.build, Aiur.AiurSystem.verify, Aiur.AiurSystem.vkBytes, Aiur.Proof.ofBytesChecked] +PARTIAL OPAQUE SOURCES [Aiur.instHashableTyp.hash, Aiur.instReprPattern.repr, Aiur.instReprTyp.repr] +OTHER UNSAFE RUNTIME [] +RECURSION WORKERS 197 +Runtime diagnostics cover Ix modules, including private constants. Lean/Std runtime primitives remain an external execution boundary. Partial opaque implementations are inventoried, not proved to refine their logical defaults. +The runtime inventory and theorem premises are frozen separately. These roots do not establish full compiler/AIR reflection or public certified claim semantics. diff --git a/Tests/Aiur/bytecode-compatibility.txt b/Tests/Aiur/bytecode-compatibility.txt new file mode 100644 index 000000000..6b604e6e8 --- /dev/null +++ b/Tests/Aiur/bytecode-compatibility.txt @@ -0,0 +1,396 @@ +BYTECODE COMPARISON FIXTURES 395 +BLOCK 0 HASH 618374249549425031 CONTROL 9285540956611923268 EQUAL #[0] +BLOCK 1 HASH 10767362259901604917 CONTROL 6836250532619648879 EQUAL #[1] +BLOCK 2 HASH 11672108002333575424 CONTROL 9285540956611923268 EQUAL #[2] +BLOCK 3 HASH 13567776331674792218 CONTROL 9285540956611923268 EQUAL #[3] +BLOCK 4 HASH 5882612929627746006 CONTROL 9285540956611923268 EQUAL #[4] +BLOCK 5 HASH 15738423084920187207 CONTROL 9285540956611923268 EQUAL #[5] +BLOCK 6 HASH 8339378633421865408 CONTROL 9285540956611923268 EQUAL #[6] +BLOCK 7 HASH 9048624632441819154 CONTROL 9285540956611923268 EQUAL #[7] +BLOCK 8 HASH 476257331868625673 CONTROL 9285540956611923268 EQUAL #[8] +BLOCK 9 HASH 9619198049311423339 CONTROL 9285540956611923268 EQUAL #[9] +BLOCK 10 HASH 10053140698542559660 CONTROL 9285540956611923268 EQUAL #[10] +BLOCK 11 HASH 16142299799675066055 CONTROL 9285540956611923268 EQUAL #[11] +BLOCK 12 HASH 8460708323736300895 CONTROL 9285540956611923268 EQUAL #[12] +BLOCK 13 HASH 14064263600456978268 CONTROL 9285540956611923268 EQUAL #[13] +BLOCK 14 HASH 349930326508970344 CONTROL 9285540956611923268 EQUAL #[14] +BLOCK 15 HASH 2823160669760411641 CONTROL 9285540956611923268 EQUAL #[15] +BLOCK 16 HASH 15190639785503822565 CONTROL 9285540956611923268 EQUAL #[16] +BLOCK 17 HASH 2618898095466958846 CONTROL 9285540956611923268 EQUAL #[17] +BLOCK 18 HASH 4016723164930384913 CONTROL 9285540956611923268 EQUAL #[18] +BLOCK 19 HASH 7522974378207777983 CONTROL 9285540956611923268 EQUAL #[19] +BLOCK 20 HASH 291555211599457042 CONTROL 9285540956611923268 EQUAL #[20] +BLOCK 21 HASH 3930346390669372951 CONTROL 9285540956611923268 EQUAL #[21] +BLOCK 22 HASH 3206432457045056339 CONTROL 9285540956611923268 EQUAL #[22] +BLOCK 23 HASH 9646947391128649297 CONTROL 9285540956611923268 EQUAL #[23] +BLOCK 24 HASH 1434544142018062473 CONTROL 9285540956611923268 EQUAL #[24] +BLOCK 25 HASH 11531913990625414641 CONTROL 9285540956611923268 EQUAL #[25] +BLOCK 26 HASH 17864658416170291104 CONTROL 9285540956611923268 EQUAL #[26] +BLOCK 27 HASH 15707162891451276999 CONTROL 9285540956611923268 EQUAL #[27] +BLOCK 28 HASH 9110709247370404019 CONTROL 9285540956611923268 EQUAL #[28] +BLOCK 29 HASH 7282864665841768941 CONTROL 9285540956611923268 EQUAL #[29] +BLOCK 30 HASH 17878598160472452876 CONTROL 9285540956611923268 EQUAL #[30] +BLOCK 31 HASH 9131874713094089536 CONTROL 9285540956611923268 EQUAL #[31] +BLOCK 32 HASH 9206845510160007850 CONTROL 9285540956611923268 EQUAL #[32] +BLOCK 33 HASH 18411462278693569584 CONTROL 9285540956611923268 EQUAL #[33] +BLOCK 34 HASH 12249543226618914073 CONTROL 9285540956611923268 EQUAL #[34] +BLOCK 35 HASH 13305176274105683490 CONTROL 9285540956611923268 EQUAL #[35] +BLOCK 36 HASH 626254262210408935 CONTROL 9285540956611923268 EQUAL #[36] +BLOCK 37 HASH 66266134359554334 CONTROL 9285540956611923268 EQUAL #[37] +BLOCK 38 HASH 4722821071429242579 CONTROL 9285540956611923268 EQUAL #[38] +BLOCK 39 HASH 2591955576747446219 CONTROL 9285540956611923268 EQUAL #[39] +BLOCK 40 HASH 123081820534452520 CONTROL 442260967249929706 EQUAL #[40] +BLOCK 41 HASH 2269127429092526664 CONTROL 7368886074157430835 EQUAL #[41] +BLOCK 42 HASH 6972128161722958508 CONTROL 8099949975056009608 EQUAL #[42] +BLOCK 43 HASH 9378383683697981412 CONTROL 12287981519385779728 EQUAL #[43] +BLOCK 44 HASH 13030451103740552621 CONTROL 8750347727180497316 EQUAL #[44] +BLOCK 45 HASH 7163820565924969022 CONTROL 8541860137754334797 EQUAL #[45] +BLOCK 46 HASH 16811152477437330821 CONTROL 3731605226305634582 EQUAL #[46] +BLOCK 47 HASH 7259229959211084775 CONTROL 9727055256702545294 EQUAL #[47] +BLOCK 48 HASH 792296228035146239 CONTROL 2624280346791568358 EQUAL #[48] +BLOCK 49 HASH 9462357318678034408 CONTROL 1025175301796357359 EQUAL #[49] +BLOCK 50 HASH 13907099015722761018 CONTROL 10046770220800461300 EQUAL #[50] +BLOCK 51 HASH 17877525535566776336 CONTROL 9256014151676554028 EQUAL #[51] +BLOCK 52 HASH 9332988922403297458 CONTROL 17794894587962055635 EQUAL #[52] +BLOCK 53 HASH 6962274207880604662 CONTROL 18252359267413485426 EQUAL #[53] +BLOCK 54 HASH 16513437812367402178 CONTROL 16818496739035924833 EQUAL #[54] +BLOCK 55 HASH 14293640645409139514 CONTROL 8625692579045300697 EQUAL #[55] +BLOCK 56 HASH 16526029939492997083 CONTROL 8934133331990604517 EQUAL #[56] +BLOCK 57 HASH 13823931130195299110 CONTROL 1320777040509452772 EQUAL #[57] +BLOCK 58 HASH 1144443015364867233 CONTROL 9711647431898321223 EQUAL #[58] +BLOCK 59 HASH 7176117492116446776 CONTROL 549193491256352175 EQUAL #[59] +BLOCK 60 HASH 4342164131208559031 CONTROL 3352624905678114087 EQUAL #[60] +BLOCK 61 HASH 13179500588532732117 CONTROL 12158506884767977126 EQUAL #[61] +BLOCK 62 HASH 1072227324077203834 CONTROL 5919442857798660357 EQUAL #[62] +BLOCK 63 HASH 8936741155375479642 CONTROL 9460575193024119757 EQUAL #[63] +BLOCK 64 HASH 2528818410938476416 CONTROL 13659450731802344926 EQUAL #[64] +BLOCK 65 HASH 9971581454819281316 CONTROL 8326825899499085215 EQUAL #[65] +BLOCK 66 HASH 10411899777951044952 CONTROL 11787513862943280324 EQUAL #[66] +BLOCK 67 HASH 13542459157806783444 CONTROL 7276143994603534460 EQUAL #[67] +BLOCK 68 HASH 14861287983348871617 CONTROL 2738270753240256240 EQUAL #[68] +BLOCK 69 HASH 11868535493272160426 CONTROL 7935514033972273153 EQUAL #[69] +BLOCK 70 HASH 4840191378550344899 CONTROL 12588597752625930266 EQUAL #[70] +BLOCK 71 HASH 14002491812871334650 CONTROL 5974536654261613602 EQUAL #[71] +BLOCK 72 HASH 17194110321127950249 CONTROL 6218681475608484146 EQUAL #[72] +BLOCK 73 HASH 15383477069917739851 CONTROL 5226745078584996419 EQUAL #[73] +BLOCK 74 HASH 8644283588974591927 CONTROL 18221978229553308984 EQUAL #[74] +BLOCK 75 HASH 793158955187790018 CONTROL 5942474650035376320 EQUAL #[75] +BLOCK 76 HASH 5046099744285162722 CONTROL 1227879464581278383 EQUAL #[76, 77] +BLOCK 77 HASH 5046099744285162722 CONTROL 1227879464581278383 EQUAL #[76, 77] +BLOCK 78 HASH 14434027012720595378 CONTROL 1227879464581278383 EQUAL #[78] +BLOCK 79 HASH 15593214182835131542 CONTROL 8784252495883746449 EQUAL #[79] +BLOCK 80 HASH 6870429911899794176 CONTROL 5031497259189885290 EQUAL #[80] +BLOCK 81 HASH 11228586072522957117 CONTROL 8784252495883746449 EQUAL #[81] +BLOCK 82 HASH 13477987559259585252 CONTROL 8784252495883746449 EQUAL #[82] +BLOCK 83 HASH 17135159117916155065 CONTROL 8784252495883746449 EQUAL #[83] +BLOCK 84 HASH 11794633473663537442 CONTROL 8784252495883746449 EQUAL #[84] +BLOCK 85 HASH 12950004568662697645 CONTROL 8784252495883746449 EQUAL #[85] +BLOCK 86 HASH 15491984793067098838 CONTROL 8784252495883746449 EQUAL #[86] +BLOCK 87 HASH 3030620686625893817 CONTROL 8784252495883746449 EQUAL #[87] +BLOCK 88 HASH 4669408539669772990 CONTROL 8784252495883746449 EQUAL #[88] +BLOCK 89 HASH 7768620375418789214 CONTROL 8784252495883746449 EQUAL #[89] +BLOCK 90 HASH 2654856332192868711 CONTROL 8784252495883746449 EQUAL #[90] +BLOCK 91 HASH 11140533640375000682 CONTROL 8784252495883746449 EQUAL #[91] +BLOCK 92 HASH 15744784955530291696 CONTROL 8784252495883746449 EQUAL #[92] +BLOCK 93 HASH 17601358025109035212 CONTROL 8784252495883746449 EQUAL #[93] +BLOCK 94 HASH 16883637298171234440 CONTROL 8784252495883746449 EQUAL #[94] +BLOCK 95 HASH 14507023773745916734 CONTROL 8784252495883746449 EQUAL #[95] +BLOCK 96 HASH 9316443224328059401 CONTROL 8784252495883746449 EQUAL #[96] +BLOCK 97 HASH 17461166695896006315 CONTROL 8784252495883746449 EQUAL #[97] +BLOCK 98 HASH 6128950249435413453 CONTROL 8784252495883746449 EQUAL #[98] +BLOCK 99 HASH 1831537920616591979 CONTROL 8784252495883746449 EQUAL #[99] +BLOCK 100 HASH 14350866197508785408 CONTROL 8784252495883746449 EQUAL #[100] +BLOCK 101 HASH 10761897014089548388 CONTROL 8784252495883746449 EQUAL #[101] +BLOCK 102 HASH 5020673946780198162 CONTROL 8784252495883746449 EQUAL #[102] +BLOCK 103 HASH 7344345781785311212 CONTROL 8784252495883746449 EQUAL #[103] +BLOCK 104 HASH 16495682629274189661 CONTROL 8784252495883746449 EQUAL #[104] +BLOCK 105 HASH 5171338963310349593 CONTROL 8784252495883746449 EQUAL #[105] +BLOCK 106 HASH 11657291387755173558 CONTROL 8784252495883746449 EQUAL #[106] +BLOCK 107 HASH 7519375929998021380 CONTROL 8784252495883746449 EQUAL #[107] +BLOCK 108 HASH 8841095143167053894 CONTROL 8784252495883746449 EQUAL #[108] +BLOCK 109 HASH 12204384250884847614 CONTROL 8784252495883746449 EQUAL #[109] +BLOCK 110 HASH 13287577812951221113 CONTROL 8784252495883746449 EQUAL #[110] +BLOCK 111 HASH 17806865421501680675 CONTROL 8784252495883746449 EQUAL #[111] +BLOCK 112 HASH 1090978459723504726 CONTROL 8784252495883746449 EQUAL #[112] +BLOCK 113 HASH 16486163545670406625 CONTROL 8784252495883746449 EQUAL #[113] +BLOCK 114 HASH 10317805833216091280 CONTROL 8784252495883746449 EQUAL #[114] +BLOCK 115 HASH 18432780923276165067 CONTROL 8784252495883746449 EQUAL #[115] +BLOCK 116 HASH 6862647800684957780 CONTROL 8784252495883746449 EQUAL #[116] +BLOCK 117 HASH 1699812483050273097 CONTROL 8784252495883746449 EQUAL #[117] +BLOCK 118 HASH 13693044082596212025 CONTROL 8784252495883746449 EQUAL #[118] +BLOCK 119 HASH 14456975777343617427 CONTROL 6203731646402738190 EQUAL #[119] +BLOCK 120 HASH 10822122504004831819 CONTROL 5122488561581784412 EQUAL #[120] +BLOCK 121 HASH 209350869627849625 CONTROL 2470556298702175255 EQUAL #[121] +BLOCK 122 HASH 1984990494015217724 CONTROL 18339464206584115167 EQUAL #[122] +BLOCK 123 HASH 11568910206272915584 CONTROL 13529796445238207056 EQUAL #[123] +BLOCK 124 HASH 1832402004605126241 CONTROL 47464743328756682 EQUAL #[124] +BLOCK 125 HASH 15025537237962902193 CONTROL 4520577957331705713 EQUAL #[125] +BLOCK 126 HASH 2449783759168503400 CONTROL 13065218925294200329 EQUAL #[126] +BLOCK 127 HASH 518562794364551831 CONTROL 5073790739569167119 EQUAL #[127] +BLOCK 128 HASH 14918149910095476447 CONTROL 14218246878766364077 EQUAL #[128] +BLOCK 129 HASH 5887591544949002135 CONTROL 8401608799272219326 EQUAL #[129] +BLOCK 130 HASH 16583739283095924894 CONTROL 4955196834704457846 EQUAL #[130] +BLOCK 131 HASH 16252481252968914360 CONTROL 6857465993183697657 EQUAL #[131] +BLOCK 132 HASH 6292858437620421432 CONTROL 7750032337035065955 EQUAL #[132] +BLOCK 133 HASH 11484065554089991150 CONTROL 16210096123913723904 EQUAL #[133] +BLOCK 134 HASH 11823408709769897484 CONTROL 933528679431178984 EQUAL #[134] +BLOCK 135 HASH 7142567934441389978 CONTROL 183835739773987727 EQUAL #[135] +BLOCK 136 HASH 13131128633786316581 CONTROL 14239324964574065229 EQUAL #[136] +BLOCK 137 HASH 17078064776857431687 CONTROL 9266877669054722718 EQUAL #[137] +BLOCK 138 HASH 2148828171051292821 CONTROL 3296820152665538198 EQUAL #[138] +BLOCK 139 HASH 1722994774935311210 CONTROL 7510598364130417360 EQUAL #[139] +BLOCK 140 HASH 16329381174783010487 CONTROL 7693462472108927402 EQUAL #[140] +BLOCK 141 HASH 12150683071829182844 CONTROL 15400027340878189073 EQUAL #[141] +BLOCK 142 HASH 10409933514622992242 CONTROL 18018849807154746857 EQUAL #[142] +BLOCK 143 HASH 12271041658409189545 CONTROL 13777559853531555046 EQUAL #[143] +BLOCK 144 HASH 947419858078852370 CONTROL 11285603661166613876 EQUAL #[144] +BLOCK 145 HASH 14767787222335820379 CONTROL 11203312843384486319 EQUAL #[145] +BLOCK 146 HASH 18100704755056617074 CONTROL 12655290107111833223 EQUAL #[146] +BLOCK 147 HASH 11134828345163871534 CONTROL 656857140206167336 EQUAL #[147] +BLOCK 148 HASH 1916137348187063063 CONTROL 13951641050356124242 EQUAL #[148] +BLOCK 149 HASH 16334426986765523389 CONTROL 5754028386739114873 EQUAL #[149] +BLOCK 150 HASH 15023064395313836703 CONTROL 13445039757214890209 EQUAL #[150] +BLOCK 151 HASH 4933993368756487521 CONTROL 15133198741730790887 EQUAL #[151] +BLOCK 152 HASH 13701879806998378282 CONTROL 6665581908433556629 EQUAL #[152] +BLOCK 153 HASH 7755549216534273852 CONTROL 244239508757426726 EQUAL #[153] +BLOCK 154 HASH 15458302475149362676 CONTROL 4664917923743035406 EQUAL #[154] +BLOCK 155 HASH 12651650412334410450 CONTROL 5815682396845256326 EQUAL #[155, 156] +BLOCK 156 HASH 12651650412334410450 CONTROL 5815682396845256326 EQUAL #[155, 156] +BLOCK 157 HASH 12838375498233594114 CONTROL 5815682396845256326 EQUAL #[157] +BLOCK 158 HASH 1283267760902138737 CONTROL 7672978788370522085 EQUAL #[158] +BLOCK 159 HASH 1884363252718491921 CONTROL 5149645617458545238 EQUAL #[159] +BLOCK 160 HASH 15123317700383798921 CONTROL 7672978788370522085 EQUAL #[160] +BLOCK 161 HASH 13947326510846006736 CONTROL 7672978788370522085 EQUAL #[161] +BLOCK 162 HASH 3426605980619719249 CONTROL 7672978788370522085 EQUAL #[162] +BLOCK 163 HASH 7209255731814999571 CONTROL 7672978788370522085 EQUAL #[163] +BLOCK 164 HASH 18228949997554902956 CONTROL 7672978788370522085 EQUAL #[164] +BLOCK 165 HASH 1411810313083244633 CONTROL 7672978788370522085 EQUAL #[165] +BLOCK 166 HASH 567972741979504646 CONTROL 7672978788370522085 EQUAL #[166] +BLOCK 167 HASH 1574972134704558712 CONTROL 7672978788370522085 EQUAL #[167] +BLOCK 168 HASH 7097805197569488943 CONTROL 7672978788370522085 EQUAL #[168] +BLOCK 169 HASH 3598976423589741836 CONTROL 7672978788370522085 EQUAL #[169] +BLOCK 170 HASH 18076216439856153132 CONTROL 7672978788370522085 EQUAL #[170] +BLOCK 171 HASH 14427324802773785495 CONTROL 7672978788370522085 EQUAL #[171] +BLOCK 172 HASH 5664450267676950274 CONTROL 7672978788370522085 EQUAL #[172] +BLOCK 173 HASH 672982601460096800 CONTROL 7672978788370522085 EQUAL #[173] +BLOCK 174 HASH 8508828043863792852 CONTROL 7672978788370522085 EQUAL #[174] +BLOCK 175 HASH 18429923591208970006 CONTROL 7672978788370522085 EQUAL #[175] +BLOCK 176 HASH 16082858208762997193 CONTROL 7672978788370522085 EQUAL #[176] +BLOCK 177 HASH 12832962972040815598 CONTROL 7672978788370522085 EQUAL #[177] +BLOCK 178 HASH 18267133736975463729 CONTROL 7672978788370522085 EQUAL #[178] +BLOCK 179 HASH 3571883277244661591 CONTROL 7672978788370522085 EQUAL #[179] +BLOCK 180 HASH 8257699755391402114 CONTROL 7672978788370522085 EQUAL #[180] +BLOCK 181 HASH 6900735505115440733 CONTROL 7672978788370522085 EQUAL #[181] +BLOCK 182 HASH 10706003055777563366 CONTROL 7672978788370522085 EQUAL #[182] +BLOCK 183 HASH 6629805224997183593 CONTROL 7672978788370522085 EQUAL #[183] +BLOCK 184 HASH 10209298439094032157 CONTROL 7672978788370522085 EQUAL #[184] +BLOCK 185 HASH 5200245702257074099 CONTROL 7672978788370522085 EQUAL #[185] +BLOCK 186 HASH 567159334841412781 CONTROL 7672978788370522085 EQUAL #[186] +BLOCK 187 HASH 14903449863862145522 CONTROL 7672978788370522085 EQUAL #[187] +BLOCK 188 HASH 15348691934452634153 CONTROL 7672978788370522085 EQUAL #[188] +BLOCK 189 HASH 5288489006398901758 CONTROL 7672978788370522085 EQUAL #[189] +BLOCK 190 HASH 13955901823420288825 CONTROL 7672978788370522085 EQUAL #[190] +BLOCK 191 HASH 1918250980888382833 CONTROL 7672978788370522085 EQUAL #[191] +BLOCK 192 HASH 12117297154071734272 CONTROL 7672978788370522085 EQUAL #[192] +BLOCK 193 HASH 6306647992692426176 CONTROL 7672978788370522085 EQUAL #[193] +BLOCK 194 HASH 18291848165696743141 CONTROL 7672978788370522085 EQUAL #[194] +BLOCK 195 HASH 7733461127087210941 CONTROL 7672978788370522085 EQUAL #[195] +BLOCK 196 HASH 3822529860578977889 CONTROL 7672978788370522085 EQUAL #[196] +BLOCK 197 HASH 7828019728678658568 CONTROL 7672978788370522085 EQUAL #[197] +BLOCK 198 HASH 198431472103947920 CONTROL 16825163729238218580 EQUAL #[198] +BLOCK 199 HASH 2328022609132471740 CONTROL 16864498735519437028 EQUAL #[199] +BLOCK 200 HASH 5518293941933170447 CONTROL 705860499898407377 EQUAL #[200] +BLOCK 201 HASH 7086633813526480806 CONTROL 2120727659526319965 EQUAL #[201] +BLOCK 202 HASH 7544604200239110848 CONTROL 5501555016000168213 EQUAL #[202] +BLOCK 203 HASH 1327977292673188868 CONTROL 7167479335275031301 EQUAL #[203] +BLOCK 204 HASH 6995139991587641016 CONTROL 5306712755674392544 EQUAL #[204] +BLOCK 205 HASH 2869329674000347995 CONTROL 13838270730535029092 EQUAL #[205] +BLOCK 206 HASH 7540513984832443031 CONTROL 3351801062277294600 EQUAL #[206] +BLOCK 207 HASH 14351243101849938939 CONTROL 7614625664420287296 EQUAL #[207] +BLOCK 208 HASH 13531312153612296043 CONTROL 7891804896811708485 EQUAL #[208] +BLOCK 209 HASH 1998244710432636421 CONTROL 17285568389751612585 EQUAL #[209] +BLOCK 210 HASH 11941311214155962856 CONTROL 520615414868360800 EQUAL #[210] +BLOCK 211 HASH 5197532886255551202 CONTROL 8560734315700569392 EQUAL #[211] +BLOCK 212 HASH 12576702381080013224 CONTROL 16334122009680349909 EQUAL #[212] +BLOCK 213 HASH 16417317276331008323 CONTROL 11512241375656347097 EQUAL #[213] +BLOCK 214 HASH 7282052706654027122 CONTROL 12075866798987247561 EQUAL #[214] +BLOCK 215 HASH 6356154908647557244 CONTROL 17730125356489253065 EQUAL #[215] +BLOCK 216 HASH 13254216122449771798 CONTROL 11431982434788764524 EQUAL #[216] +BLOCK 217 HASH 9537842138074422592 CONTROL 3059905783217945816 EQUAL #[217] +BLOCK 218 HASH 9349095545095618561 CONTROL 6364398609764915452 EQUAL #[218] +BLOCK 219 HASH 5371829853627181735 CONTROL 14853108725724458868 EQUAL #[219] +BLOCK 220 HASH 11990493234764055494 CONTROL 7648355342318868161 EQUAL #[220] +BLOCK 221 HASH 7166728261378469222 CONTROL 4476462443417450093 EQUAL #[221] +BLOCK 222 HASH 10107621913334223336 CONTROL 15670488636498815496 EQUAL #[222] +BLOCK 223 HASH 4743457210413836307 CONTROL 27611921795077048 EQUAL #[223] +BLOCK 224 HASH 6507888404916187446 CONTROL 1761815328202991213 EQUAL #[224] +BLOCK 225 HASH 9466209696331067265 CONTROL 12885850262253222945 EQUAL #[225] +BLOCK 226 HASH 10989349617707478133 CONTROL 4709089612658109297 EQUAL #[226] +BLOCK 227 HASH 10661371310995142763 CONTROL 16200754376417689185 EQUAL #[227] +BLOCK 228 HASH 16225858480419194612 CONTROL 5362159836533946996 EQUAL #[228] +BLOCK 229 HASH 8944826474749893854 CONTROL 2661323665792140752 EQUAL #[229] +BLOCK 230 HASH 14708006028794950073 CONTROL 9512598258868672340 EQUAL #[230] +BLOCK 231 HASH 1910416286691691802 CONTROL 17765048123077364028 EQUAL #[231] +BLOCK 232 HASH 14606456589376999212 CONTROL 7907470118315484697 EQUAL #[232] +BLOCK 233 HASH 8591020620007062366 CONTROL 13834573667365444661 EQUAL #[233] +BLOCK 234 HASH 829527346973826275 CONTROL 11030345794345088650 EQUAL #[234, 235] +BLOCK 235 HASH 829527346973826275 CONTROL 11030345794345088650 EQUAL #[234, 235] +BLOCK 236 HASH 8138522887513815913 CONTROL 11030345794345088650 EQUAL #[236] +BLOCK 237 HASH 13995316751874110918 CONTROL 1412341037314722380 EQUAL #[237] +BLOCK 238 HASH 18020510042460779070 CONTROL 14509346486066595023 EQUAL #[238] +BLOCK 239 HASH 2325722907376616799 CONTROL 1412341037314722380 EQUAL #[239] +BLOCK 240 HASH 16369690687557828028 CONTROL 1412341037314722380 EQUAL #[240] +BLOCK 241 HASH 2675804253565710522 CONTROL 1412341037314722380 EQUAL #[241] +BLOCK 242 HASH 3761327872365045708 CONTROL 1412341037314722380 EQUAL #[242] +BLOCK 243 HASH 8179585094746246508 CONTROL 1412341037314722380 EQUAL #[243] +BLOCK 244 HASH 4073918353814983293 CONTROL 1412341037314722380 EQUAL #[244] +BLOCK 245 HASH 4905762299860004433 CONTROL 1412341037314722380 EQUAL #[245] +BLOCK 246 HASH 12596693210464903654 CONTROL 1412341037314722380 EQUAL #[246] +BLOCK 247 HASH 16599953839193188956 CONTROL 1412341037314722380 EQUAL #[247] +BLOCK 248 HASH 15850628249433035745 CONTROL 1412341037314722380 EQUAL #[248] +BLOCK 249 HASH 4179529552794659453 CONTROL 1412341037314722380 EQUAL #[249] +BLOCK 250 HASH 9468805364482338310 CONTROL 1412341037314722380 EQUAL #[250] +BLOCK 251 HASH 3863474582015271553 CONTROL 1412341037314722380 EQUAL #[251] +BLOCK 252 HASH 7205344154507129833 CONTROL 1412341037314722380 EQUAL #[252] +BLOCK 253 HASH 13436535963662627343 CONTROL 1412341037314722380 EQUAL #[253] +BLOCK 254 HASH 12377483774483520813 CONTROL 1412341037314722380 EQUAL #[254] +BLOCK 255 HASH 4282037769824259431 CONTROL 1412341037314722380 EQUAL #[255] +BLOCK 256 HASH 7385376240264034152 CONTROL 1412341037314722380 EQUAL #[256] +BLOCK 257 HASH 806452055526413109 CONTROL 1412341037314722380 EQUAL #[257] +BLOCK 258 HASH 15000388160001968739 CONTROL 1412341037314722380 EQUAL #[258] +BLOCK 259 HASH 17367695747249965684 CONTROL 1412341037314722380 EQUAL #[259] +BLOCK 260 HASH 1122340963572135819 CONTROL 1412341037314722380 EQUAL #[260] +BLOCK 261 HASH 7789880408650510209 CONTROL 1412341037314722380 EQUAL #[261] +BLOCK 262 HASH 1869500212260374831 CONTROL 1412341037314722380 EQUAL #[262] +BLOCK 263 HASH 14845287494291971596 CONTROL 1412341037314722380 EQUAL #[263] +BLOCK 264 HASH 14075713458717556763 CONTROL 1412341037314722380 EQUAL #[264] +BLOCK 265 HASH 10864881960281298525 CONTROL 1412341037314722380 EQUAL #[265] +BLOCK 266 HASH 13459867850344339846 CONTROL 1412341037314722380 EQUAL #[266] +BLOCK 267 HASH 2819728148997170702 CONTROL 1412341037314722380 EQUAL #[267] +BLOCK 268 HASH 4527503802875146153 CONTROL 1412341037314722380 EQUAL #[268] +BLOCK 269 HASH 18029620499192445347 CONTROL 1412341037314722380 EQUAL #[269] +BLOCK 270 HASH 7402134703085508897 CONTROL 1412341037314722380 EQUAL #[270] +BLOCK 271 HASH 5257146648189379704 CONTROL 1412341037314722380 EQUAL #[271] +BLOCK 272 HASH 1395176487860975178 CONTROL 1412341037314722380 EQUAL #[272] +BLOCK 273 HASH 15691405994808164562 CONTROL 1412341037314722380 EQUAL #[273] +BLOCK 274 HASH 16453288715351159105 CONTROL 1412341037314722380 EQUAL #[274] +BLOCK 275 HASH 1379807177850769112 CONTROL 1412341037314722380 EQUAL #[275] +BLOCK 276 HASH 11377702386000080636 CONTROL 1412341037314722380 EQUAL #[276] +BLOCK 277 HASH 5198926819085355727 CONTROL 4103347131404716257 EQUAL #[277] +BLOCK 278 HASH 17268730218823233171 CONTROL 4007854741778933750 EQUAL #[278] +BLOCK 279 HASH 6923055678665536144 CONTROL 10499270455681555439 EQUAL #[279] +BLOCK 280 HASH 10427933834192710213 CONTROL 8711154114120874639 EQUAL #[280] +BLOCK 281 HASH 3433869452976212206 CONTROL 16702709322516330853 EQUAL #[281] +BLOCK 282 HASH 9924846121775755015 CONTROL 6073005231246686738 EQUAL #[282] +BLOCK 283 HASH 14362650825028221940 CONTROL 6462996632176444379 EQUAL #[283] +BLOCK 284 HASH 6210270071042925381 CONTROL 9815223537327002699 EQUAL #[284] +BLOCK 285 HASH 12376074138572659249 CONTROL 12492989825141361904 EQUAL #[285] +BLOCK 286 HASH 10160745485024405551 CONTROL 2527833134488699487 EQUAL #[286] +BLOCK 287 HASH 13032917679763405545 CONTROL 7939604329859445710 EQUAL #[287] +BLOCK 288 HASH 4069468452703318071 CONTROL 11731051236880384494 EQUAL #[288] +BLOCK 289 HASH 6019780007050549552 CONTROL 1745119938756421140 EQUAL #[289] +BLOCK 290 HASH 2669765899957771226 CONTROL 17965183165604085707 EQUAL #[290] +BLOCK 291 HASH 16695280086327466198 CONTROL 6291746971986477946 EQUAL #[291] +BLOCK 292 HASH 3970101118045276049 CONTROL 3508421241767877690 EQUAL #[292] +BLOCK 293 HASH 12475248795862969402 CONTROL 6164182821519423720 EQUAL #[293] +BLOCK 294 HASH 6793070773433536541 CONTROL 18404655147469866807 EQUAL #[294] +BLOCK 295 HASH 11591324004765997935 CONTROL 4284497748849439318 EQUAL #[295] +BLOCK 296 HASH 2292506223546533055 CONTROL 15379096783635824966 EQUAL #[296] +BLOCK 297 HASH 3349721624328230677 CONTROL 13368057163843177117 EQUAL #[297] +BLOCK 298 HASH 5987935174962115052 CONTROL 8264178947098801098 EQUAL #[298] +BLOCK 299 HASH 3544709462059876847 CONTROL 6684397670075172195 EQUAL #[299] +BLOCK 300 HASH 14514956999628286581 CONTROL 8096479539679101667 EQUAL #[300] +BLOCK 301 HASH 7753915019778992118 CONTROL 1548763615490106882 EQUAL #[301] +BLOCK 302 HASH 15339629469836035716 CONTROL 16445791782020682133 EQUAL #[302] +BLOCK 303 HASH 18404753015914565380 CONTROL 12224237222522533764 EQUAL #[303] +BLOCK 304 HASH 17657906620874486700 CONTROL 2836452298334761684 EQUAL #[304] +BLOCK 305 HASH 12564877604107370077 CONTROL 6670796226598270766 EQUAL #[305] +BLOCK 306 HASH 6021569980085899890 CONTROL 2078114244397823785 EQUAL #[306] +BLOCK 307 HASH 13362446263138031960 CONTROL 15980171678204417448 EQUAL #[307] +BLOCK 308 HASH 11828915085031845700 CONTROL 12085007552390234184 EQUAL #[308] +BLOCK 309 HASH 9572299576371803449 CONTROL 9584311880370436259 EQUAL #[309] +BLOCK 310 HASH 7032639628468476577 CONTROL 4355079370103907660 EQUAL #[310] +BLOCK 311 HASH 10375434173908757476 CONTROL 596485669595795621 EQUAL #[311] +BLOCK 312 HASH 5429498755990243399 CONTROL 4838876700937453365 EQUAL #[312] +BLOCK 313 HASH 17347111138569683660 CONTROL 6891737007990255529 EQUAL #[313, 314] +BLOCK 314 HASH 17347111138569683660 CONTROL 6891737007990255529 EQUAL #[313, 314] +BLOCK 315 HASH 12793518802252659619 CONTROL 6891737007990255529 EQUAL #[315] +BLOCK 316 HASH 17396942995469564620 CONTROL 10111039913815581524 EQUAL #[316] +BLOCK 317 HASH 7395771211528490766 CONTROL 4923741496511561015 EQUAL #[317] +BLOCK 318 HASH 11958775702934124315 CONTROL 10111039913815581524 EQUAL #[318] +BLOCK 319 HASH 12558764532647427787 CONTROL 10111039913815581524 EQUAL #[319] +BLOCK 320 HASH 3303962430515397446 CONTROL 10111039913815581524 EQUAL #[320] +BLOCK 321 HASH 14497296920499756023 CONTROL 10111039913815581524 EQUAL #[321] +BLOCK 322 HASH 9293355396482176270 CONTROL 10111039913815581524 EQUAL #[322] +BLOCK 323 HASH 17020255087388553673 CONTROL 10111039913815581524 EQUAL #[323] +BLOCK 324 HASH 18022541800919561563 CONTROL 10111039913815581524 EQUAL #[324] +BLOCK 325 HASH 5329262065989236996 CONTROL 10111039913815581524 EQUAL #[325] +BLOCK 326 HASH 8103858485944049393 CONTROL 10111039913815581524 EQUAL #[326] +BLOCK 327 HASH 14955793653111087838 CONTROL 10111039913815581524 EQUAL #[327] +BLOCK 328 HASH 13265825227251964457 CONTROL 10111039913815581524 EQUAL #[328] +BLOCK 329 HASH 13797303288319867553 CONTROL 10111039913815581524 EQUAL #[329] +BLOCK 330 HASH 13526190796425931218 CONTROL 10111039913815581524 EQUAL #[330] +BLOCK 331 HASH 17653705181118661873 CONTROL 10111039913815581524 EQUAL #[331] +BLOCK 332 HASH 9888594606432366249 CONTROL 10111039913815581524 EQUAL #[332] +BLOCK 333 HASH 16061937400486026778 CONTROL 10111039913815581524 EQUAL #[333] +BLOCK 334 HASH 1339991747367352032 CONTROL 10111039913815581524 EQUAL #[334] +BLOCK 335 HASH 4106839568144158271 CONTROL 10111039913815581524 EQUAL #[335] +BLOCK 336 HASH 624488278046428057 CONTROL 10111039913815581524 EQUAL #[336] +BLOCK 337 HASH 4791780238874226976 CONTROL 10111039913815581524 EQUAL #[337] +BLOCK 338 HASH 2549204908341292891 CONTROL 10111039913815581524 EQUAL #[338] +BLOCK 339 HASH 17393202699407333126 CONTROL 10111039913815581524 EQUAL #[339] +BLOCK 340 HASH 16729521677551450223 CONTROL 10111039913815581524 EQUAL #[340] +BLOCK 341 HASH 14046795466796139769 CONTROL 10111039913815581524 EQUAL #[341] +BLOCK 342 HASH 17244808746743603066 CONTROL 10111039913815581524 EQUAL #[342] +BLOCK 343 HASH 357131586064755288 CONTROL 10111039913815581524 EQUAL #[343] +BLOCK 344 HASH 9825633885977324157 CONTROL 10111039913815581524 EQUAL #[344] +BLOCK 345 HASH 6093831873016308859 CONTROL 10111039913815581524 EQUAL #[345] +BLOCK 346 HASH 3334986794196549607 CONTROL 10111039913815581524 EQUAL #[346] +BLOCK 347 HASH 12990557889253082435 CONTROL 10111039913815581524 EQUAL #[347] +BLOCK 348 HASH 15707689599940537801 CONTROL 10111039913815581524 EQUAL #[348] +BLOCK 349 HASH 8483639990306509221 CONTROL 10111039913815581524 EQUAL #[349] +BLOCK 350 HASH 12316535972453623549 CONTROL 10111039913815581524 EQUAL #[350] +BLOCK 351 HASH 2119475818599562037 CONTROL 10111039913815581524 EQUAL #[351] +BLOCK 352 HASH 12460275699257548894 CONTROL 10111039913815581524 EQUAL #[352] +BLOCK 353 HASH 17723859533048463367 CONTROL 10111039913815581524 EQUAL #[353] +BLOCK 354 HASH 5642427221652085281 CONTROL 10111039913815581524 EQUAL #[354] +BLOCK 355 HASH 3077243899097199008 CONTROL 10111039913815581524 EQUAL #[355] +BLOCK 356 HASH 13280011609265517776 CONTROL 15500831552078857548 EQUAL #[356] +BLOCK 357 HASH 7905944290590112291 CONTROL 6275641937893928157 EQUAL #[357] +BLOCK 358 HASH 4131924236762677050 CONTROL 12884018430940676164 EQUAL #[358] +BLOCK 359 HASH 6916397007785288159 CONTROL 8576487449635554020 EQUAL #[359] +BLOCK 360 HASH 15210863163515614870 CONTROL 969811232201239729 EQUAL #[360] +BLOCK 361 HASH 15195684589045868964 CONTROL 4905959146870202528 EQUAL #[361] +BLOCK 362 HASH 1503938963055340732 CONTROL 1985079156278829681 EQUAL #[362] +BLOCK 363 HASH 2365151368809476361 CONTROL 2077361599890669393 EQUAL #[363] +BLOCK 364 HASH 10999260526465423687 CONTROL 6185567526471332579 EQUAL #[364] +BLOCK 365 HASH 3446508141076101049 CONTROL 5944627260938225042 EQUAL #[365] +BLOCK 366 HASH 17978585659460548788 CONTROL 5208797646224817875 EQUAL #[366] +BLOCK 367 HASH 4926882075722585297 CONTROL 9953689383195313651 EQUAL #[367] +BLOCK 368 HASH 1100093574257362442 CONTROL 5593113768580818747 EQUAL #[368] +BLOCK 369 HASH 762571127927728934 CONTROL 13135516762971280330 EQUAL #[369] +BLOCK 370 HASH 4312654927614717844 CONTROL 6798742700128601403 EQUAL #[370] +BLOCK 371 HASH 5189908211140690792 CONTROL 16172196083033309579 EQUAL #[371] +BLOCK 372 HASH 1523660456902965926 CONTROL 96537915912427798 EQUAL #[372] +BLOCK 373 HASH 14809050674462328488 CONTROL 11145844428156386855 EQUAL #[373] +BLOCK 374 HASH 6289283848394829839 CONTROL 5306547137240675726 EQUAL #[374] +BLOCK 375 HASH 6248289876444817171 CONTROL 8736063782003645758 EQUAL #[375] +BLOCK 376 HASH 18044315872383447031 CONTROL 9409322752807515732 EQUAL #[376] +BLOCK 377 HASH 2384528439596981710 CONTROL 13132565993859078085 EQUAL #[377] +BLOCK 378 HASH 5984068352564312457 CONTROL 17160255557431003644 EQUAL #[378] +BLOCK 379 HASH 7370891269108435707 CONTROL 17455658824208243724 EQUAL #[379] +BLOCK 380 HASH 3864065152202817903 CONTROL 10811805574918315592 EQUAL #[380] +BLOCK 381 HASH 18423723933967337188 CONTROL 7543598783917654769 EQUAL #[381] +BLOCK 382 HASH 3987886884471801983 CONTROL 7489975184861568472 EQUAL #[382] +BLOCK 383 HASH 1146403553216458886 CONTROL 16503978377546628136 EQUAL #[383] +BLOCK 384 HASH 16241997409853664705 CONTROL 8630172209403223821 EQUAL #[384] +BLOCK 385 HASH 8042865936385108754 CONTROL 15522664873330487684 EQUAL #[385] +BLOCK 386 HASH 17526027368373611076 CONTROL 4179870005768539125 EQUAL #[386] +BLOCK 387 HASH 5058091090490480864 CONTROL 16043815558281953093 EQUAL #[387] +BLOCK 388 HASH 18200964524490689 CONTROL 7376963370091842527 EQUAL #[388] +BLOCK 389 HASH 11609471004306675606 CONTROL 5573518497212771958 EQUAL #[389] +BLOCK 390 HASH 6707570023566297342 CONTROL 14602017055763573303 EQUAL #[390] +BLOCK 391 HASH 15709873628515650384 CONTROL 16115191450497768871 EQUAL #[391] +BLOCK 392 HASH 7721969574442238250 CONTROL 8703802100742699184 EQUAL #[392, 393] +BLOCK 393 HASH 7721969574442238250 CONTROL 8703802100742699184 EQUAL #[392, 393] +BLOCK 394 HASH 1378429354119706722 CONTROL 8703802100742699184 EQUAL #[394] diff --git a/Tests/Aiur/dedup-compatibility.txt b/Tests/Aiur/dedup-compatibility.txt new file mode 100644 index 000000000..92b628aef --- /dev/null +++ b/Tests/Aiur/dedup-compatibility.txt @@ -0,0 +1,1333 @@ +PROGRAM empty FUNCTIONS 0 -> 0 +RENAME #[0, 1, 2] +MEMORY #[1, 2, 10] +PROGRAM entry-union FUNCTIONS 3 -> 1 +RENAME #[0, 0, 0, 3, 4, 5] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +PROGRAM different-layouts FUNCTIONS 3 -> 3 +RENAME #[0, 1, 2, 3, 4, 5] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 1, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 9, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM mutual-cycle FUNCTIONS 2 -> 1 +RENAME #[0, 0, 2, 3, 4] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 0 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +PROGRAM invalid-callee FUNCTIONS 2 -> 1 +RENAME #[0, 0, 2, 3, 4] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 999 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +PROGRAM continuations FUNCTIONS 4 -> 2 +RENAME #[0, 0, 1, 1, 4, 5, 6] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.const 7], + ctrl := Aiur.Bytecode.Ctrl.matchContinue + 0 + #[(0, { ops := #[], ctrl := Aiur.Bytecode.Ctrl.yield 0 #[1] })] + (some { ops := #[], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }) + 1 + 3 + 2 + { ops := #[Aiur.Bytecode.Op.call 1 #[2] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[3] } }, + layout := { inputSize := 1, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 1, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-0 FUNCTIONS 2 -> 2 +RENAME #[0, 1, 2, 3, 4] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-1 FUNCTIONS 4 -> 4 +RENAME #[0, 1, 2, 3, 4, 5, 6] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-2 FUNCTIONS 6 -> 6 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-3 FUNCTIONS 8 -> 8 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-4 FUNCTIONS 10 -> 10 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-5 FUNCTIONS 12 -> 12 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-6 FUNCTIONS 14 -> 14 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-7 FUNCTIONS 16 -> 16 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-8 FUNCTIONS 18 -> 18 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-9 FUNCTIONS 20 -> 20 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-10 FUNCTIONS 22 -> 22 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.call 20 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.call 21 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 20 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 21 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-11 FUNCTIONS 24 -> 24 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.call 20 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.call 21 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 20 { body := { ops := #[Aiur.Bytecode.Op.call 22 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 21 { body := { ops := #[Aiur.Bytecode.Op.call 23 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 22 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 23 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-12 FUNCTIONS 26 -> 26 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.call 20 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.call 21 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 20 { body := { ops := #[Aiur.Bytecode.Op.call 22 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 21 { body := { ops := #[Aiur.Bytecode.Op.call 23 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 22 { body := { ops := #[Aiur.Bytecode.Op.call 24 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 23 { body := { ops := #[Aiur.Bytecode.Op.call 25 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 24 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 25 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-13 FUNCTIONS 28 -> 28 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.call 20 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.call 21 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 20 { body := { ops := #[Aiur.Bytecode.Op.call 22 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 21 { body := { ops := #[Aiur.Bytecode.Op.call 23 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 22 { body := { ops := #[Aiur.Bytecode.Op.call 24 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 23 { body := { ops := #[Aiur.Bytecode.Op.call 25 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 24 { body := { ops := #[Aiur.Bytecode.Op.call 26 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 25 { body := { ops := #[Aiur.Bytecode.Op.call 27 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 26 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 27 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-14 FUNCTIONS 30 -> 30 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.call 20 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.call 21 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 20 { body := { ops := #[Aiur.Bytecode.Op.call 22 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 21 { body := { ops := #[Aiur.Bytecode.Op.call 23 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 22 { body := { ops := #[Aiur.Bytecode.Op.call 24 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 23 { body := { ops := #[Aiur.Bytecode.Op.call 25 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 24 { body := { ops := #[Aiur.Bytecode.Op.call 26 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 25 { body := { ops := #[Aiur.Bytecode.Op.call 27 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 26 { body := { ops := #[Aiur.Bytecode.Op.call 28 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 27 { body := { ops := #[Aiur.Bytecode.Op.call 29 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 28 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 29 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-15 FUNCTIONS 32 -> 32 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.call 20 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.call 21 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 20 { body := { ops := #[Aiur.Bytecode.Op.call 22 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 21 { body := { ops := #[Aiur.Bytecode.Op.call 23 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 22 { body := { ops := #[Aiur.Bytecode.Op.call 24 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 23 { body := { ops := #[Aiur.Bytecode.Op.call 25 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 24 { body := { ops := #[Aiur.Bytecode.Op.call 26 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 25 { body := { ops := #[Aiur.Bytecode.Op.call 27 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 26 { body := { ops := #[Aiur.Bytecode.Op.call 28 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 27 { body := { ops := #[Aiur.Bytecode.Op.call 29 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 28 { body := { ops := #[Aiur.Bytecode.Op.call 30 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 29 { body := { ops := #[Aiur.Bytecode.Op.call 31 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 30 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 31 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +PROGRAM refinement-chain-16 FUNCTIONS 34 -> 34 +RENAME #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36] +MEMORY #[1, 2, 10] +FUNCTION 0 { body := { ops := #[Aiur.Bytecode.Op.call 2 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 1 { body := { ops := #[Aiur.Bytecode.Op.call 3 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := true, + constrained := false } +FUNCTION 2 { body := { ops := #[Aiur.Bytecode.Op.call 4 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 3 { body := { ops := #[Aiur.Bytecode.Op.call 5 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 4 { body := { ops := #[Aiur.Bytecode.Op.call 6 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 5 { body := { ops := #[Aiur.Bytecode.Op.call 7 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 6 { body := { ops := #[Aiur.Bytecode.Op.call 8 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 7 { body := { ops := #[Aiur.Bytecode.Op.call 9 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 8 { body := { ops := #[Aiur.Bytecode.Op.call 10 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 9 { body := { ops := #[Aiur.Bytecode.Op.call 11 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 10 { body := { ops := #[Aiur.Bytecode.Op.call 12 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 11 { body := { ops := #[Aiur.Bytecode.Op.call 13 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 12 { body := { ops := #[Aiur.Bytecode.Op.call 14 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 13 { body := { ops := #[Aiur.Bytecode.Op.call 15 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 14 { body := { ops := #[Aiur.Bytecode.Op.call 16 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 15 { body := { ops := #[Aiur.Bytecode.Op.call 17 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 16 { body := { ops := #[Aiur.Bytecode.Op.call 18 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 17 { body := { ops := #[Aiur.Bytecode.Op.call 19 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 18 { body := { ops := #[Aiur.Bytecode.Op.call 20 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 19 { body := { ops := #[Aiur.Bytecode.Op.call 21 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 20 { body := { ops := #[Aiur.Bytecode.Op.call 22 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 21 { body := { ops := #[Aiur.Bytecode.Op.call 23 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 22 { body := { ops := #[Aiur.Bytecode.Op.call 24 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 23 { body := { ops := #[Aiur.Bytecode.Op.call 25 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 24 { body := { ops := #[Aiur.Bytecode.Op.call 26 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 25 { body := { ops := #[Aiur.Bytecode.Op.call 27 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 26 { body := { ops := #[Aiur.Bytecode.Op.call 28 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 27 { body := { ops := #[Aiur.Bytecode.Op.call 29 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 28 { body := { ops := #[Aiur.Bytecode.Op.call 30 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 29 { body := { ops := #[Aiur.Bytecode.Op.call 31 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 30 { body := { ops := #[Aiur.Bytecode.Op.call 32 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 31 { body := { ops := #[Aiur.Bytecode.Op.call 33 #[] 1 false], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 32 { body := { ops := #[Aiur.Bytecode.Op.const 7], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } +FUNCTION 33 { body := { ops := #[Aiur.Bytecode.Op.const 9], ctrl := Aiur.Bytecode.Ctrl.return 0 #[0] }, + layout := { inputSize := 0, selectors := 2, auxiliaries := 8, lookups := 5 }, + entry := false, + constrained := false } diff --git a/Tests/Aiur/source-value-compatibility.txt b/Tests/Aiur/source-value-compatibility.txt new file mode 100644 index 000000000..a7fec6baa --- /dev/null +++ b/Tests/Aiur/source-value-compatibility.txt @@ -0,0 +1,100 @@ +SOURCE VALUE HASH FIXTURES 99 +VALUE 0 HASH 0 +VALUE 1 HASH 8749354384435707241 +VALUE 2 HASH 12882348691112465364 +VALUE 3 HASH 2377845632408581361 +VALUE 4 HASH 11632597162316755711 +VALUE 5 HASH 5530045286768123853 +VALUE 6 HASH 7999773623304365860 +VALUE 7 HASH 3720670971919179042 +VALUE 8 HASH 3720670971919179042 +VALUE 9 HASH 3720670971919179042 +VALUE 10 HASH 15320573189724115100 +VALUE 11 HASH 11187578883047356977 +VALUE 12 HASH 425165588333083028 +VALUE 13 HASH 15849745100916035534 +VALUE 14 HASH 458840319313485945 +VALUE 15 HASH 4591834625990244068 +VALUE 16 HASH 3904241366544532200 +VALUE 17 HASH 2372720083837327878 +VALUE 18 HASH 13396906709469468990 +VALUE 19 HASH 8630906389795451290 +VALUE 20 HASH 3549314381222846376 +VALUE 21 HASH 17863064148255639869 +VALUE 22 HASH 16889408581382503904 +VALUE 23 HASH 1362967498803569690 +VALUE 24 HASH 14155676960900291531 +VALUE 25 HASH 18288671267577049654 +VALUE 26 HASH 16813174585923137922 +VALUE 27 HASH 4522384026810106468 +VALUE 28 HASH 1159157090964788868 +VALUE 29 HASH 8242814138854491714 +VALUE 30 HASH 5206700930677556320 +VALUE 31 HASH 1073706624000798197 +VALUE 32 HASH 10031353126198601256 +VALUE 33 HASH 1057982919846479074 +VALUE 34 HASH 17831831747438059647 +VALUE 35 HASH 3518081980405266154 +VALUE 36 HASH 16936691439974984567 +VALUE 37 HASH 17497591706831603213 +VALUE 38 HASH 11728232621475673721 +VALUE 39 HASH 14617821723611521678 +VALUE 40 HASH 3390044753914760435 +VALUE 41 HASH 7523039060591518558 +VALUE 42 HASH 11978281817061994171 +VALUE 43 HASH 15448649667467085601 +VALUE 44 HASH 17726834112050484513 +VALUE 45 HASH 3413084345017691020 +VALUE 46 HASH 8486376434432214938 +VALUE 47 HASH 6539708471159116732 +VALUE 48 HASH 13577379645960254956 +VALUE 49 HASH 9535173859574451250 +VALUE 50 HASH 3340619801374861623 +VALUE 51 HASH 7473614108051619746 +VALUE 52 HASH 4438482188659876207 +VALUE 53 HASH 308585577653266613 +VALUE 54 HASH 1575809756895362131 +VALUE 55 HASH 5708804063572120254 +VALUE 56 HASH 5877511752852517224 +VALUE 57 HASH 8037021573386070406 +VALUE 58 HASH 14668200699750263486 +VALUE 59 HASH 10055143394274591386 +VALUE 60 HASH 15854127891854726589 +VALUE 61 HASH 1540378124821933096 +VALUE 62 HASH 10160078024048964597 +VALUE 63 HASH 5647184145953969711 +VALUE 64 HASH 1670291516117959835 +VALUE 65 HASH 5803285822794717958 +VALUE 66 HASH 16947754315310826609 +VALUE 67 HASH 3811587103178222492 +VALUE 68 HASH 3586205689759573117 +VALUE 69 HASH 13857231994817767843 +VALUE 70 HASH 6449109682227641737 +VALUE 71 HASH 456604136828682370 +VALUE 72 HASH 10282900939567356395 +VALUE 73 HASH 12598141728558465643 +VALUE 74 HASH 18305444248414093273 +VALUE 75 HASH 6521790106739756299 +VALUE 76 HASH 11782062519623288512 +VALUE 77 HASH 7957016415365316137 +VALUE 78 HASH 1613491961129078381 +VALUE 79 HASH 14344968043142879526 +VALUE 80 HASH 3369383947544867319 +VALUE 81 HASH 511930786863132171 +VALUE 82 HASH 2998475890800806647 +VALUE 83 HASH 3183140925414804714 +VALUE 84 HASH 13040122459803691049 +VALUE 85 HASH 3165285364197100220 +VALUE 86 HASH 8868022099410756417 +VALUE 87 HASH 8038379054726876786 +VALUE 88 HASH 15903808653746511106 +VALUE 89 HASH 11524449674585483172 +VALUE 90 HASH 15385025462028698787 +VALUE 91 HASH 7885845618262242016 +VALUE 92 HASH 11534418552294313664 +VALUE 93 HASH 14697586262333512277 +VALUE 94 HASH 18421564212326130901 +VALUE 95 HASH 16458453681622390642 +VALUE 96 HASH 4664628051155748896 +VALUE 97 HASH 3714145596340391514 +VALUE 98 HASH 16235546750463173208 diff --git a/Tests/Aiur/tail-match-compatibility.txt b/Tests/Aiur/tail-match-compatibility.txt new file mode 100644 index 000000000..22f4af00b --- /dev/null +++ b/Tests/Aiur/tail-match-compatibility.txt @@ -0,0 +1,282 @@ +TAIL MATCH FIXTURES 281 +TERM 0 Aiur.Source.Term.unit +TERM 1 Aiur.Source.Term.unit +TERM 2 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.unit) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 3 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.unit) +TERM 4 Aiur.Source.Term.var (Aiur.Local.str "x") +TERM 5 Aiur.Source.Term.var (Aiur.Local.str "x") +TERM 6 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.var (Aiur.Local.str "x")) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 7 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.str "x")) +TERM 8 Aiur.Source.Term.ref { toName := `fixture } +TERM 9 Aiur.Source.Term.ref { toName := `fixture } +TERM 10 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ref { toName := `fixture }) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 11 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ref { toName := `fixture }) +TERM 12 Aiur.Source.Term.field 7 +TERM 13 Aiur.Source.Term.field 7 +TERM 14 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 15 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 16 Aiur.Source.Term.tuple #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] +TERM 17 Aiur.Source.Term.tuple #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] +TERM 18 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.tuple #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))]) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 19 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.tuple #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))]) +TERM 20 Aiur.Source.Term.array #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] +TERM 21 Aiur.Source.Term.array #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] +TERM 22 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.array #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))]) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 23 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.array #[Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))]) +TERM 24 Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 25 Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 26 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 27 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 28 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 29 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 30 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 31 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7)) +TERM 32 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.wildcard, Aiur.Source.Term.field 7)] +TERM 33 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.wildcard, Aiur.Source.Term.field 7)] +TERM 34 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.wildcard, Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))]) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 35 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.wildcard, Aiur.Source.Term.field 7)]) +TERM 36 Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.normal) +TERM 37 Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.normal) +TERM 38 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.normal)) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 39 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.normal)) +TERM 40 Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.unconstrained) +TERM 41 Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.unconstrained) +TERM 42 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.unconstrained)) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 43 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.unconstrained)) +TERM 44 Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.inlined) +TERM 45 Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.inlined) +TERM 46 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.inlined)) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 47 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.app { toName := `fixture } [Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))] (Aiur.Source.CallMode.inlined)) +TERM 48 Aiur.Source.Term.add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 49 Aiur.Source.Term.add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 50 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 51 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 52 Aiur.Source.Term.sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 53 Aiur.Source.Term.sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 54 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 55 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 56 Aiur.Source.Term.mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 57 Aiur.Source.Term.mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 58 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 59 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 60 Aiur.Source.Term.eqZero (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 61 Aiur.Source.Term.eqZero (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 62 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.eqZero (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 63 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.eqZero (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 64 Aiur.Source.Term.proj (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 +TERM 65 Aiur.Source.Term.proj (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 +TERM 66 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.proj (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 67 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.proj (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0) +TERM 68 Aiur.Source.Term.get (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 +TERM 69 Aiur.Source.Term.get (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 +TERM 70 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.get (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 71 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.get (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0) +TERM 72 Aiur.Source.Term.slice (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 1 +TERM 73 Aiur.Source.Term.slice (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 1 +TERM 74 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.slice (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 1) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 75 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.slice (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 1) +TERM 76 Aiur.Source.Term.set (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 77 Aiur.Source.Term.set (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 78 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.set (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 79 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.set (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 0 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 80 Aiur.Source.Term.store (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 81 Aiur.Source.Term.store (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 82 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.store (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 83 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.store (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 84 Aiur.Source.Term.load (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 85 Aiur.Source.Term.load (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 86 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.load (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 87 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.load (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 88 Aiur.Source.Term.ptrVal (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 89 Aiur.Source.Term.ptrVal (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 90 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ptrVal (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 91 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ptrVal (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 92 Aiur.Source.Term.ann (Aiur.Typ.field) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 93 Aiur.Source.Term.ann (Aiur.Typ.field) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 94 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ann (Aiur.Typ.field) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 95 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ann (Aiur.Typ.field) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 96 Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 97 Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 98 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 99 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 100 Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (some "check") (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 101 Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (some "check") (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 102 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (some "check") (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 103 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.assertEq (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (some "check") (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 104 Aiur.Source.Term.ioGetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 105 Aiur.Source.Term.ioGetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 106 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ioGetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 107 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ioGetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 108 Aiur.Source.Term.ioSetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 109 Aiur.Source.Term.ioSetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 110 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ioSetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 111 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ioSetInfo (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 112 Aiur.Source.Term.ioRead (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 1 +TERM 113 Aiur.Source.Term.ioRead (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 1 +TERM 114 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ioRead (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 1) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 115 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ioRead (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) 1) +TERM 116 Aiur.Source.Term.ioWrite (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 117 Aiur.Source.Term.ioWrite (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 118 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.ioWrite (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 119 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.ioWrite (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 120 Aiur.Source.Term.u8BitDecomposition (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 121 Aiur.Source.Term.u8BitDecomposition (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 122 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8BitDecomposition (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 123 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8BitDecomposition (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 124 Aiur.Source.Term.u8ShiftLeft (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 125 Aiur.Source.Term.u8ShiftLeft (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 126 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8ShiftLeft (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 127 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8ShiftLeft (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 128 Aiur.Source.Term.u8ShiftRight (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 129 Aiur.Source.Term.u8ShiftRight (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 130 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8ShiftRight (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 131 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8ShiftRight (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 132 Aiur.Source.Term.u8Xor (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 133 Aiur.Source.Term.u8Xor (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 134 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8Xor (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 135 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8Xor (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 136 Aiur.Source.Term.u8Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 137 Aiur.Source.Term.u8Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 138 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 139 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 140 Aiur.Source.Term.u8Mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 141 Aiur.Source.Term.u8Mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 142 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8Mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 143 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8Mul (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 144 Aiur.Source.Term.u8Sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 145 Aiur.Source.Term.u8Sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 146 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8Sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 147 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8Sub (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 148 Aiur.Source.Term.u8And (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 149 Aiur.Source.Term.u8And (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 150 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8And (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 151 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8And (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 152 Aiur.Source.Term.u8Or (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 153 Aiur.Source.Term.u8Or (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 154 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8Or (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 155 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8Or (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 156 Aiur.Source.Term.u8LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 157 Aiur.Source.Term.u8LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 158 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 159 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 160 Aiur.Source.Term.u32LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 161 Aiur.Source.Term.u32LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 162 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u32LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 163 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u32LessThan (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 164 Aiur.Source.Term.u8XorSplit7 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 165 Aiur.Source.Term.u8XorSplit7 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 166 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8XorSplit7 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 167 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8XorSplit7 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 168 Aiur.Source.Term.u8XorSplit4 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 169 Aiur.Source.Term.u8XorSplit4 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 170 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8XorSplit4 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 171 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8XorSplit4 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 172 Aiur.Source.Term.unconstrainedU32Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 173 Aiur.Source.Term.unconstrainedU32Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 174 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.unconstrainedU32Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 175 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.unconstrainedU32Add (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 176 Aiur.Source.Term.unconstrainedU32Add3 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 177 Aiur.Source.Term.unconstrainedU32Add3 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 178 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.unconstrainedU32Add3 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 179 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.unconstrainedU32Add3 (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 180 Aiur.Source.Term.u32ToField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 181 Aiur.Source.Term.u32ToField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 182 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u32ToField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 183 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u32ToField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 184 Aiur.Source.Term.unconstrainedBigUintDivMod (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 185 Aiur.Source.Term.unconstrainedBigUintDivMod (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 186 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.unconstrainedBigUintDivMod (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 187 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.unconstrainedBigUintDivMod (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 188 Aiur.Source.Term.unconstrainedGToBytes (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 189 Aiur.Source.Term.unconstrainedGToBytes (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 190 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.unconstrainedGToBytes (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 191 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.unconstrainedGToBytes (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 192 Aiur.Source.Term.unconstrainedGInverse (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 193 Aiur.Source.Term.unconstrainedGInverse (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 194 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.unconstrainedGInverse (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 195 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.unconstrainedGInverse (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 196 Aiur.Source.Term.u8Lit 255 +TERM 197 Aiur.Source.Term.u8Lit 255 +TERM 198 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8Lit 255) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 199 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8Lit 255) +TERM 200 Aiur.Source.Term.u8RangeCheck (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 201 Aiur.Source.Term.u8RangeCheck (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 202 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8RangeCheck (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 203 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8RangeCheck (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 204 Aiur.Source.Term.toField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 205 Aiur.Source.Term.toField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 206 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.toField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 207 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.toField (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 208 Aiur.Source.Term.u8FromFieldUnsafe (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 209 Aiur.Source.Term.u8FromFieldUnsafe (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 210 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.u8FromFieldUnsafe (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 211 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.u8FromFieldUnsafe (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 212 Aiur.Source.Term.debug "message" none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 213 Aiur.Source.Term.debug "message" none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 214 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.debug "message" none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 215 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.debug "message" none (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 216 Aiur.Source.Term.debug "message" (some (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 217 Aiur.Source.Term.debug "message" (some (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) +TERM 218 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.debug "message" (some (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.var (Aiur.Local.str "y")) +TERM 219 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.debug "message" (some (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x")))) +TERM 220 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 221 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.var (Aiur.Local.str "x"), Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 222 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.idx 0)) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 223 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.var (Aiur.Local.idx 0), Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 224 Aiur.Source.Term.let (Aiur.Pattern.wildcard) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 225 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.wildcard, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 226 Aiur.Source.Term.let (Aiur.Pattern.ref { toName := `Ctor } [Aiur.Pattern.var (Aiur.Local.str "x")]) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 227 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.ref { toName := `Ctor } [Aiur.Pattern.var (Aiur.Local.str "x")], Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 228 Aiur.Source.Term.let (Aiur.Pattern.field 7) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 229 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 230 Aiur.Source.Term.let (Aiur.Pattern.tuple #[Aiur.Pattern.var (Aiur.Local.str "x")]) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 231 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.tuple #[Aiur.Pattern.var (Aiur.Local.str "x")], Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 232 Aiur.Source.Term.let (Aiur.Pattern.array #[Aiur.Pattern.wildcard]) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 233 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.array #[Aiur.Pattern.wildcard], Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 234 Aiur.Source.Term.let (Aiur.Pattern.or (Aiur.Pattern.field 7) (Aiur.Pattern.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 235 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.or (Aiur.Pattern.field 7) (Aiur.Pattern.var (Aiur.Local.str "x")), Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 236 Aiur.Source.Term.let (Aiur.Pattern.pointer (Aiur.Pattern.var (Aiur.Local.str "x"))) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.field 7) +TERM 237 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.pointer (Aiur.Pattern.var (Aiur.Local.str "x")), Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 238 Aiur.Source.Term.field 7 +TERM 239 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.str "0")) +TERM 240 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.idx 0)) +TERM 241 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.idx 1)) +TERM 242 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "0")) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.str "x")) +TERM 243 Aiur.Source.Term.field 7 +TERM 244 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "0")) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.idx 0)) +TERM 245 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "0")) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.idx 1)) +TERM 246 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.idx 0)) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.str "x")) +TERM 247 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.idx 0)) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.str "0")) +TERM 248 Aiur.Source.Term.field 7 +TERM 249 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.idx 0)) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.idx 1)) +TERM 250 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.idx 1)) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.str "x")) +TERM 251 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.idx 1)) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.str "0")) +TERM 252 Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.idx 1)) (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) (Aiur.Source.Term.var (Aiur.Local.idx 0)) +TERM 253 Aiur.Source.Term.field 7 +TERM 254 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [] +TERM 255 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 9, Aiur.Source.Term.field 7)] +TERM 256 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 257 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 258 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 259 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 260 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 261 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 262 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 263 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 264 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 265 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 266 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 267 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 268 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 269 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 270 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 271 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 272 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 273 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 274 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 275 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 276 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 277 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 278 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 279 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] +TERM 280 Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.match (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))) [(Aiur.Pattern.field 7, Aiur.Source.Term.field 7), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))]), (Aiur.Pattern.wildcard, Aiur.Source.Term.ret (Aiur.Source.Term.let (Aiur.Pattern.var (Aiur.Local.str "x")) (Aiur.Source.Term.field 7) (Aiur.Source.Term.var (Aiur.Local.str "x"))))] diff --git a/crates/aiur/Cargo.toml b/crates/aiur/Cargo.toml index 26c92ad6d..03f03117a 100644 --- a/crates/aiur/Cargo.toml +++ b/crates/aiur/Cargo.toml @@ -16,10 +16,21 @@ tracing = { workspace = true } tracing-texray = { workspace = true } [dev-dependencies] -# Exercise the native MMCS at the same Plonky3 revision as multi-stark. -p3-blake3 = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +# Compare checked chunk and parent hashing with the pinned native implementation. +blake3 = "=1.8.5" +# Test the actual selector methods from the same Plonky3 revision as multi-stark. p3-commit = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +# Instrument the native verifier's actual challenger without changing the protocol. +p3-blake3 = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +p3-challenger = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } p3-symmetric = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +# Capture actual binary MMCS hash calls at the same pinned revision. +p3-merkle-tree = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +# Exercise the actual FRI folding strategy and its index permutation. +p3-fri = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +p3-util = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } +# Compare coefficient arithmetic with the pinned upstream polynomial utilities. +p3-stir = { git = "https://github.com/Plonky3/Plonky3", rev = "3152b14a89067c83775a8076cc262ffc48a1fd7c" } [features] default = [] diff --git a/crates/aiur/src/constraints.rs b/crates/aiur/src/constraints.rs index 7f635c985..b5ad2d5e6 100644 --- a/crates/aiur/src/constraints.rs +++ b/crates/aiur/src/constraints.rs @@ -967,3 +967,5 @@ fn combine_lookup_args( ); lookup.args.extend(args_iterator); } +#[cfg(test)] +mod tests; diff --git a/crates/aiur/src/constraints/tests.rs b/crates/aiur/src/constraints/tests.rs new file mode 100644 index 000000000..08d581948 --- /dev/null +++ b/crates/aiur/src/constraints/tests.rs @@ -0,0 +1,290 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Compare the actual argument combiner, selector expressions and escaping +//! yield collector with the checked Lean selector model. The control fixtures +//! have no operations and zero-width yields, allowing their selector-only +//! polynomial positions to be identified without evaluating an executor. + +use std::{ + fs::File, + io::{self, BufWriter, Write}, +}; + +use multi_stark::{ + eval::{VarValues, eval_expr}, + p3_field::PrimeField64, +}; + +use super::*; + +mod block_expressions; +mod block_rows; +mod circuit_expressions; +mod circuit_rows; +mod compiled_keys; +mod emission_checks; +mod frontend_expressions; +mod memory_rows; +mod operation_expressions; +mod operation_rows; + +fn write_u64(out: &mut impl Write, value: u64) -> io::Result<()> { + out.write_all(&value.to_le_bytes()) +} + +fn write_values(out: &mut impl Write, values: &[G]) -> io::Result<()> { + write_u64(out, values.len() as u64)?; + for value in values { + write_u64(out, value.as_canonical_u64())?; + } + Ok(()) +} + +fn local_values(row: &[G]) -> VarValues<'_, G> { + VarValues { + preprocessed: [&[], &[]], + main: [row, row], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ONE, + is_last_row: G::ZERO, + is_transition: G::ONE, + } +} + +fn state(selector_count: usize, branchless: bool) -> ConstraintState<'static> { + ConstraintState { + function: 37, + call_components: &[], + function_index: G::from_u64(37), + rank: konst(G::from_u64(257)), + branchless, + input_size: 2, + sel_base: 2, + column: 2 + selector_count, + lookup: 1, + lookups: vec![empty_lookup()], + map: vec![(var(0), 1), (var(1), 1)], + constraints: Constraints { + zeros: vec![], + selectors: 2..2 + selector_count, + width: 2 + selector_count + 1024, + }, + // A nested continuation must preserve yields collected before its own + // branch region. These distinct markers are never selector columns. + yield_info: vec![ + (konst(G::from_u64(99)), vec![]), + (konst(G::from_u64(100)), vec![]), + ], + } +} + +fn fixture(depth: usize, seed: usize, next_selector: &mut usize) -> Block { + let ctrl = if depth == 0 || seed.is_multiple_of(5) { + let selector = *next_selector; + *next_selector += 1; + if seed.is_multiple_of(2) { + Ctrl::Return(selector, vec![]) + } else { + Ctrl::Yield(selector, vec![]) + } + } else { + let mut cases = FxIndexMap::default(); + cases.insert(G::ZERO, fixture(depth - 1, seed * 3 + 1, next_selector)); + cases.insert(G::ONE, fixture(depth - 1, seed * 3 + 2, next_selector)); + let fallback = seed + .is_multiple_of(2) + .then(|| Box::new(fixture(depth - 1, seed * 3 + 3, next_selector))); + if seed.is_multiple_of(3) { + Ctrl::Match(0, cases, fallback) + } else { + Ctrl::MatchContinue( + 0, + cases, + fallback, + 0, + 0, + 0, + Box::new(fixture(depth - 1, seed * 3 + 4, next_selector)), + ) + } + }; + Block { ops: vec![], ctrl } +} + +/// Locate selector booleans and continuation links in the actual emitted +/// constraint vector. All skipped entries are case/default-match equations; +/// the zero-width fixtures have no merge-column equations or operations. +fn selector_equation_indices( + block: &Block, + cursor: &mut usize, + selected: &mut Vec, +) { + assert!(block.ops.is_empty()); + selected.push(*cursor); + *cursor += 1; + match &block.ctrl { + Ctrl::Return(..) | Ctrl::Yield(..) => {}, + Ctrl::Match(_, cases, fallback) + | Ctrl::MatchContinue(_, cases, fallback, ..) => { + for branch in cases.values() { + *cursor += 1; + selector_equation_indices(branch, cursor, selected); + } + if let Some(branch) = fallback { + *cursor += cases.len(); + selector_equation_indices(branch, cursor, selected); + } + if let Ctrl::MatchContinue(_, _, _, outputs, _, _, continuation) = + &block.ctrl + { + assert_eq!(*outputs, 0); + selected.push(*cursor); + *cursor += 1; + selector_equation_indices(continuation, cursor, selected); + } + }, + } +} + +fn assignment(pattern: usize, index: usize, count: usize) -> G { + match pattern { + 0 => G::ZERO, + 1 => G::ONE, + 2 => G::TWO, + 3 => -G::ONE, + 4 => G::from_usize(index + 1), + 5 => -G::from_usize(index + 1), + 6 => G::from_bool(index.is_multiple_of(2)), + 7 => [G::ZERO, -G::ONE, G::ONE, G::TWO][index % 4], + hot if hot < 8 + count => G::from_bool(index == hot - 8), + cold => G::from_bool(index != cold - 8 - count), + } +} + +fn export_control(out: &mut impl Write) -> io::Result { + write_u64(out, 48)?; + let mut checked = 0; + let mut satisfying = 0; + for depth in 0..4 { + for seed in 0..12 { + let mut selector_count = 0; + let block = fixture(depth, seed, &mut selector_count); + let mut state = state(selector_count, false); + let entry = block.get_block_selector(&state); + block.collect_constraints(entry.clone(), &mut state); + let mut equation_indices = vec![]; + let mut cursor = 0; + selector_equation_indices(&block, &mut cursor, &mut equation_indices); + assert_eq!(cursor, state.constraints.zeros.len()); + assert!(state.column <= state.constraints.width); + let mut row: Vec = + (0..state.constraints.width).map(|i| G::from_usize(i + 11)).collect(); + row[0] = G::from_u64(3); + row[1] = G::from_u64(19); + write_u64(out, selector_count as u64)?; + write_u64(out, (8 + 2 * selector_count) as u64)?; + for pattern in 0..8 + 2 * selector_count { + for index in 0..selector_count { + row[index + 2] = assignment(pattern, index, selector_count); + } + let values = local_values(&row); + let entry = eval_expr(&entry, &values); + let yields: Vec<_> = state + .yield_info + .iter() + .map(|(selector, outputs)| { + assert!(outputs.is_empty()); + eval_expr(selector, &values) + }) + .collect(); + assert_eq!(&yields[..2], &[G::from_u64(99), G::from_u64(100)]); + let equations: Vec<_> = equation_indices + .iter() + .map(|&index| eval_expr(&state.constraints.zeros[index], &values)) + .collect(); + let message: Vec<_> = state.lookups[0] + .args + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect(); + if equations.iter().all(|value| value.is_zero()) { + let return_sum = + message.get(1).copied().unwrap_or(G::ZERO) / G::from_u64(37); + assert_eq!( + entry, + return_sum + yields[2..].iter().copied().sum::() + ); + satisfying += 1; + } + write_u64(out, entry.as_canonical_u64())?; + write_values(out, &yields)?; + write_values(out, &equations)?; + write_values(out, &message)?; + checked += 1; + } + } + } + assert!(satisfying > 100, "exercise active and inactive solutions"); + Ok(checked) +} + +fn export_messages(out: &mut impl Write) -> io::Result { + write_u64(out, 2 * 7 * 32 * 8)?; + let values = local_values(&[]); + let mut checked = 0; + for branchless in [false, true] { + let state = state(0, branchless); + for count in 0..7 { + for seed in 0..32 { + for pattern in 0..8 { + let mut lookup = empty_lookup(); + for index in 0..count { + let selector = konst(assignment(pattern, index, count)); + let message = (0..(seed + index * 3) % 8).map(|offset| { + let value = G::from_usize(17 + seed + index * 5 + offset * 11); + state.gate( + &selector, + konst(if (seed + offset).is_multiple_of(2) { + value + } else { + -value + }), + ) + }); + combine_lookup_args(&mut lookup, message); + lookup.multiplicity = lookup.multiplicity + selector; + } + write_u64( + out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + let message: Vec<_> = + lookup.args.iter().map(|expr| eval_expr(expr, &values)).collect(); + write_values(out, &message)?; + checked += 1; + } + } + } + } + Ok(checked) +} + +#[test] +fn selector_control_snapshot() -> io::Result<()> { + let mut out = Vec::new(); + out.write_all(b"Aiur selector control v1\n")?; + let controls = export_control(&mut out)?; + let messages = export_messages(&mut out)?; + assert_eq!(messages, 3584); + if let Some(path) = std::env::var_os("IX_SELECTOR_CONTROL_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "selector control: {controls} assignments, {messages} shared messages" + ); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/block_expressions.rs b/crates/aiur/src/constraints/tests/block_expressions.rs new file mode 100644 index 000000000..ef96ef31f --- /dev/null +++ b/crates/aiur/src/constraints/tests/block_expressions.rs @@ -0,0 +1,194 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Exact expression reflection for complete blocks. The transport includes +//! the actual control tree, so Lean does not reconstruct an independent fixture. + +use super::{ + frontend_expressions::write_expr, + operation_expressions::{write_exprs, write_indices, write_map, write_op}, + *, +}; + +pub(super) fn write_block( + out: &mut impl Write, + block: &Block, +) -> io::Result<()> { + write_u64(out, block.ops.len() as u64)?; + for op in &block.ops { + write_op(out, op)?; + } + match &block.ctrl { + Ctrl::Return(index, values) | Ctrl::Yield(index, values) => { + out.write_all(&[u8::from(matches!(block.ctrl, Ctrl::Yield(..)))])?; + write_u64(out, *index as u64)?; + write_indices(out, values) + }, + Ctrl::Match(index, cases, fallback) + | Ctrl::MatchContinue(index, cases, fallback, ..) => { + let continued = matches!(block.ctrl, Ctrl::MatchContinue(..)); + out.write_all(&[if continued { 3 } else { 2 }])?; + write_u64(out, *index as u64)?; + write_u64(out, cases.len() as u64)?; + for (value, block) in cases { + write_u64(out, value.as_canonical_u64())?; + write_block(out, block)?; + } + out.write_all(&[u8::from(fallback.is_some())])?; + if let Some(block) = fallback { + write_block(out, block)?; + } + if let Ctrl::MatchContinue(_, _, _, size, aux, slots, block) = &block.ctrl + { + write_u64(out, *size as u64)?; + write_u64(out, *aux as u64)?; + write_u64(out, *slots as u64)?; + write_block(out, block)?; + } + Ok(()) + }, + } +} + +fn write_evaluated_map( + out: &mut impl Write, + map: &[(Expr, Degree)], + values: &VarValues<'_, G>, +) -> io::Result<()> { + for (expr, degree) in map { + write_u64(out, eval_expr(expr, values).as_canonical_u64())?; + write_u64(out, u64::from(*degree))?; + out.write_all(&[u8::from(matches!(expr, Expr::Const(_)))])?; + } + Ok(()) +} + +#[test] +fn block_expressions_snapshot() -> io::Result<()> { + let choices = [ + G::ZERO, + G::ONE, + -G::ONE, + G::from_u64(255), + G::from_u64(256), + G::from_u64(1 << 32), + G::from_u64((1 << 48) - 1), + G::from_u64(17), + ]; + let mut out = Vec::new(); + out.write_all(b"Aiur block expressions v1\n")?; + write_u64(&mut out, 384)?; + let mut reports = 0; + let mut checked = 0; + for branchless in [false, true] { + for populated in [false, true] { + for external_gate in [false, true] { + for depth in 0..4 { + for seed in 0..12 { + let mut selector_count = 0; + let block = if populated { + block_rows::block_fixture(depth, seed, 2, &mut selector_count) + } else { + fixture(depth, seed, &mut selector_count) + }; + let mut state = state(selector_count, branchless); + state.constraints.width = 2 + selector_count + 4096; + state.lookups = (0..4096).map(|_| empty_lookup()).collect(); + for (_, values) in &mut state.yield_info { + *values = state.map.clone(); + } + let selectors: Vec<_> = (0..selector_count) + .map(|index| var(state.sel_base + index)) + .collect(); + let entry = block.get_block_selector(&state); + let incoming = if external_gate { + konst(G::TWO) - var(0) + } else { + entry.clone() + }; + out.write_all(&[u8::from(branchless)])?; + write_u64(&mut out, state.function_index.as_canonical_u64())?; + write_u64(&mut out, state.input_size as u64)?; + write_expr(&mut out, &state.rank)?; + write_exprs(&mut out, &selectors)?; + write_u64(&mut out, state.column as u64)?; + write_u64(&mut out, state.lookup as u64)?; + write_expr(&mut out, &incoming)?; + write_map(&mut out, &state.map)?; + write_block(&mut out, &block)?; + write_expr(&mut out, &entry)?; + block.collect_constraints(incoming, &mut state); + assert!(state.column <= state.constraints.width); + assert!(state.lookup + 2 <= state.lookups.len()); + write_u64(&mut out, state.column as u64)?; + write_u64(&mut out, state.lookup as u64)?; + write_map(&mut out, &state.map)?; + write_exprs(&mut out, &state.constraints.zeros)?; + // Include unused slots as well as the shared return channel. + write_u64(&mut out, (state.lookup + 2) as u64)?; + for lookup in &state.lookups[..state.lookup + 2] { + write_expr(&mut out, &lookup.multiplicity)?; + write_exprs(&mut out, &lookup.args)?; + } + write_u64(&mut out, state.yield_info.len() as u64)?; + for (gate, map) in &state.yield_info { + write_expr(&mut out, gate)?; + write_map(&mut out, map)?; + } + write_u64(&mut out, 4)?; + for pattern in [0, 1, 2, 7] { + let mut row: Vec<_> = (0..state.column) + .map(|index| { + choices[(seed + 5 * index + pattern) % choices.len()] + }) + .collect(); + for index in 0..selector_count { + row[index + 2] = assignment(pattern, index, selector_count); + } + write_values(&mut out, &row)?; + let values = local_values(&row); + write_evaluated_map(&mut out, &state.map, &values)?; + for expr in &state.constraints.zeros { + write_u64( + &mut out, + eval_expr(expr, &values).as_canonical_u64(), + )?; + } + for lookup in &state.lookups[..state.lookup + 2] { + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + for arg in &lookup.args { + write_u64( + &mut out, + eval_expr(arg, &values).as_canonical_u64(), + )?; + } + } + for (gate, map) in &state.yield_info { + write_u64( + &mut out, + eval_expr(gate, &values).as_canonical_u64(), + )?; + write_evaluated_map(&mut out, map, &values)?; + } + checked += 1; + } + reports += 1; + } + } + } + } + } + assert_eq!((reports, checked), (384, 1536)); + if let Some(path) = std::env::var_os("IX_BLOCK_EXPRESSION_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "block expressions: {reports} control trees, {checked} assignments" + ); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/block_rows.rs b/crates/aiur/src/constraints/tests/block_rows.rs new file mode 100644 index 000000000..5e7b3e100 --- /dev/null +++ b/crates/aiur/src/constraints/tests/block_rows.rs @@ -0,0 +1,168 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Full block emission with shared branch storage and nonempty yields. +//! Rows include arbitrary selectors and advice, without an executor filter. + +use super::*; + +pub(super) fn block_fixture( + depth: usize, + seed: usize, + initial_values: usize, + next_selector: &mut usize, +) -> Block { + let size = seed % 3; + let pointer = initial_values + 3 + size; + let count = initial_values + 6 + 2 * size; + let ops = vec![ + Op::Const(G::from_usize(seed + 17)), + Op::Mul(0, 1), + Op::EqZero(if seed.is_multiple_of(2) { initial_values } else { 0 }), + Op::Call(17, vec![0, initial_values], size, false), + Op::Store(vec![0, initial_values + 1]), + Op::Load(size, pointer), + Op::U8Add(0, 1), + Op::AssertEq(vec![initial_values + 1], vec![0], None), + ]; + let ctrl = if depth == 0 || seed.is_multiple_of(5) { + let selector = *next_selector; + *next_selector += 1; + let outputs = vec![count - 2, count - 1]; + if seed.is_multiple_of(2) { + Ctrl::Return(selector, outputs) + } else { + Ctrl::Yield(selector, outputs) + } + } else { + let mut cases = FxIndexMap::default(); + cases.insert( + G::ZERO, + block_fixture(depth - 1, seed * 3 + 1, count, next_selector), + ); + cases.insert( + G::ONE, + block_fixture(depth - 1, seed * 3 + 2, count, next_selector), + ); + let fallback = seed.is_multiple_of(2).then(|| { + Box::new(block_fixture(depth - 1, seed * 3 + 3, count, next_selector)) + }); + let matched = if seed.is_multiple_of(2) { initial_values } else { 0 }; + if seed.is_multiple_of(3) { + Ctrl::Match(matched, cases, fallback) + } else { + Ctrl::MatchContinue( + matched, + cases, + fallback, + 2, + 0, + 0, + Box::new(block_fixture( + depth - 1, + seed * 3 + 4, + count + 2, + next_selector, + )), + ) + } + }; + Block { ops, ctrl } +} + +fn write_map( + out: &mut impl Write, + map: &[(Expr, Degree)], + values: &VarValues<'_, G>, +) -> io::Result<()> { + write_u64(out, map.len() as u64)?; + for (expr, degree) in map { + write_u64(out, eval_expr(expr, values).as_canonical_u64())?; + write_u64(out, u64::from(*degree))?; + write_u64(out, u64::from(matches!(expr, Expr::Const(_))))?; + } + Ok(()) +} + +#[test] +fn block_rows_snapshot() -> io::Result<()> { + let choices = [ + G::ZERO, + G::ONE, + -G::ONE, + G::from_u64(255), + G::from_u64(256), + G::from_u64(1 << 32), + G::from_u64((1 << 48) - 1), + G::from_u64(17), + ]; + let mut out = Vec::new(); + out.write_all(b"Aiur block rows v1\n")?; + write_u64(&mut out, 96)?; + let mut checked = 0; + for branchless in [false, true] { + for depth in 0..4 { + for seed in 0..12 { + let mut selector_count = 0; + let block = block_fixture(depth, seed, 2, &mut selector_count); + let mut state = state(selector_count, branchless); + state.constraints.width = 2 + selector_count + 4096; + state.lookups = (0..4096).map(|_| empty_lookup()).collect(); + for (_, values) in &mut state.yield_info { + *values = vec![(var(0), 1), (var(1), 1)]; + } + let entry = block.get_block_selector(&state); + block.collect_constraints(entry, &mut state); + assert!(state.column <= state.constraints.width); + assert!(state.lookup <= state.lookups.len()); + let mut row: Vec<_> = (0..state.constraints.width) + .map(|index| choices[(seed + 5 * index) % choices.len()]) + .collect(); + write_u64(&mut out, selector_count as u64)?; + write_u64(&mut out, (8 + 2 * selector_count) as u64)?; + for pattern in 0..8 + 2 * selector_count { + for index in 0..selector_count { + row[index + 2] = assignment(pattern, index, selector_count); + } + let values = local_values(&row); + write_u64(&mut out, state.column as u64)?; + write_u64(&mut out, state.lookup as u64)?; + write_map(&mut out, &state.map, &values)?; + let equations: Vec<_> = state + .constraints + .zeros + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect(); + write_values(&mut out, &equations)?; + for lookup in &state.lookups[..state.lookup] { + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + let args: Vec<_> = + lookup.args.iter().map(|expr| eval_expr(expr, &values)).collect(); + write_values(&mut out, &args)?; + } + write_u64(&mut out, state.yield_info.len() as u64)?; + for (selector, map) in &state.yield_info { + write_u64( + &mut out, + eval_expr(selector, &values).as_canonical_u64(), + )?; + write_map(&mut out, map, &values)?; + } + checked += 1; + } + } + } + } + assert_eq!(checked, 2028); + if let Some(path) = std::env::var_os("IX_BLOCK_ROW_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!("block rows: {checked} assignments with shared columns and slots"); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/circuit_expressions.rs b/crates/aiur/src/constraints/tests/circuit_expressions.rs new file mode 100644 index 000000000..30bba57c3 --- /dev/null +++ b/crates/aiur/src/constraints/tests/circuit_expressions.rs @@ -0,0 +1,138 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Transport actual programs and complete circuit-builder expressions. + +use super::{ + block_expressions::write_block, + circuit_rows::{circuit_layout, fixture_function}, + frontend_expressions::write_expr, + operation_expressions::{write_exprs, write_indices}, + *, +}; +use crate::bytecode::{Circuit, FunctionLayout}; + +pub(super) fn write_layout( + out: &mut impl Write, + layout: FunctionLayout, +) -> io::Result<()> { + for count in + [layout.input_size, layout.selectors, layout.auxiliaries, layout.lookups] + { + write_u64(out, count as u64)?; + } + Ok(()) +} + +#[test] +fn circuit_expressions_snapshot() -> io::Result<()> { + let groups: &[&[usize]] = + &[&[0], &[1], &[2], &[3], &[0, 1], &[2, 0, 3], &[3, 2, 1, 0], &[]]; + let choices = [ + G::ZERO, + G::ONE, + -G::ONE, + G::from_u64(255), + G::from_u64(256), + G::from_u64(1 << 32), + G::from_u64((1 << 48) - 1), + G::from_u64(17), + ]; + let mut out = Vec::new(); + out.write_all(b"Aiur circuit expressions v1\n")?; + write_u64(&mut out, 12)?; + let mut reports = 0; + let mut checked = 0; + for seed in 0..12 { + let functions: Vec<_> = + (0..4).map(|index| fixture_function(seed, index)).collect(); + let circuits = groups + .iter() + .map(|members| Circuit { + members: members.to_vec(), + layout: circuit_layout(&functions, members), + }) + .collect(); + let top = Toplevel { + functions, + circuits, + memory_sizes: vec![], + call_components: vec![], + }; + assert!(top.validate_row_counts().is_ok()); + assert!(top.validate_emission().is_ok()); + write_u64(&mut out, top.functions.len() as u64)?; + for function in &top.functions { + write_block(&mut out, &function.body)?; + write_layout(&mut out, function.layout)?; + out.write_all(&[ + u8::from(function.entry), + u8::from(function.constrained), + ])?; + } + write_u64(&mut out, top.circuits.len() as u64)?; + for circuit in &top.circuits { + write_indices(&mut out, &circuit.members)?; + write_layout(&mut out, circuit.layout)?; + } + for (index, circuit) in top.circuits.iter().enumerate() { + out.write_all(&[u8::from(top.circuit_is_branchless(index))])?; + let (constraints, lookups) = top.build_constraints(index); + let inactive_row = vec![G::ZERO; constraints.width]; + let inactive_values = local_values(&inactive_row); + assert!( + constraints + .zeros + .iter() + .all(|expr| eval_expr(expr, &inactive_values) == G::ZERO) + ); + write_u64(&mut out, constraints.width as u64)?; + write_u64(&mut out, constraints.selectors.start as u64)?; + write_u64(&mut out, constraints.selectors.len() as u64)?; + write_exprs(&mut out, &constraints.zeros)?; + write_u64(&mut out, lookups.len() as u64)?; + for lookup in &lookups { + write_expr(&mut out, &lookup.multiplicity)?; + write_exprs(&mut out, &lookup.args)?; + } + write_u64(&mut out, 4)?; + for pattern in [0, 1, 2, 7] { + let mut row: Vec<_> = (0..constraints.width) + .map(|column| { + choices[(seed + 5 * column + 3 * pattern) % choices.len()] + }) + .collect(); + for column in 0..circuit.layout.selectors { + row[constraints.selectors.start + column] = + assignment(pattern, column, circuit.layout.selectors); + } + write_values(&mut out, &row)?; + let values = local_values(&row); + for expr in &constraints.zeros { + write_u64(&mut out, eval_expr(expr, &values).as_canonical_u64())?; + } + for lookup in &lookups { + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + for arg in &lookup.args { + write_u64(&mut out, eval_expr(arg, &values).as_canonical_u64())?; + } + } + checked += 1; + } + reports += 1; + } + } + assert_eq!((reports, checked), (96, 384)); + if let Some(path) = std::env::var_os("IX_CIRCUIT_EXPRESSION_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "circuit expressions: {reports} circuits, {checked} assignments, {reports} inactive zero rows" + ); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/circuit_rows.rs b/crates/aiur/src/constraints/tests/circuit_rows.rs new file mode 100644 index 000000000..a795d1d55 --- /dev/null +++ b/crates/aiur/src/constraints/tests/circuit_rows.rs @@ -0,0 +1,219 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! The actual whole-circuit builder, including grouped member offsets, +//! shared multiplicity/rank columns, and all physical lookup slots. + +use super::*; +use crate::bytecode::{Circuit, Function, FunctionLayout}; + +fn close_returns(block: &mut Block, width: usize, escapes: bool) { + match &mut block.ctrl { + Ctrl::Return(_, outputs) => outputs.truncate(width), + Ctrl::Yield(selector, outputs) => { + if escapes { + block.ctrl = Ctrl::Return(*selector, outputs[..width].to_vec()); + } + }, + Ctrl::Match(_, cases, fallback) => { + for body in cases.values_mut() { + close_returns(body, width, escapes); + } + if let Some(body) = fallback { + close_returns(body, width, escapes); + } + }, + Ctrl::MatchContinue(_, cases, fallback, _, _, _, continuation) => { + for body in cases.values_mut() { + close_returns(body, width, false); + } + if let Some(body) = fallback { + close_returns(body, width, false); + } + close_returns(continuation, width, escapes); + }, + } +} + +pub(super) fn fixture_function(seed: usize, index: usize) -> Function { + let input_size = 2 + (seed + index) % 3; + let depth = (seed + index) % 3; + let mut selectors = 0; + let mut body = block_rows::block_fixture( + depth, + seed * 4 + index, + input_size, + &mut selectors, + ); + close_returns(&mut body, index % 3, true); + if seed.is_multiple_of(4) && index == 0 { + body = Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + [ + ( + G::ZERO, + Block { + ops: vec![Op::Store(vec![])], + ctrl: Ctrl::Match(0, FxIndexMap::default(), None), + }, + ), + (G::ONE, body), + ] + .into_iter() + .collect(), + None, + ), + }; + } + let mut measured = state(selectors, false); + measured.input_size = input_size; + measured.sel_base = input_size; + measured.column = input_size + selectors + 7; + measured.lookup = 4; + measured.map = (0..input_size).map(|i| (var(i), 1)).collect(); + measured.lookups = (0..4096).map(|_| empty_lookup()).collect(); + measured.yield_info.clear(); + let selector = body.get_block_selector(&measured); + body.collect_constraints(selector, &mut measured); + assert!(measured.yield_info.is_empty()); + Function { + body, + layout: FunctionLayout { + input_size, + selectors, + auxiliaries: measured.column - input_size - selectors, + lookups: measured.lookup, + }, + entry: true, + constrained: true, + } +} + +pub(super) fn circuit_layout( + functions: &[Function], + members: &[usize], +) -> FunctionLayout { + let mut layout = + FunctionLayout { input_size: 0, selectors: 0, auxiliaries: 7, lookups: 4 }; + for &member in members { + let next = functions[member].layout; + layout.input_size = layout.input_size.max(next.input_size); + layout.selectors += next.selectors; + layout.auxiliaries = layout.auxiliaries.max(next.auxiliaries); + layout.lookups = layout.lookups.max(next.lookups); + } + layout +} + +#[test] +fn circuit_rows_snapshot() -> io::Result<()> { + let groups: &[&[usize]] = + &[&[0], &[1], &[2], &[3], &[0, 1], &[2, 0, 3], &[3, 2, 1, 0], &[]]; + let choices = [ + G::ZERO, + G::ONE, + -G::ONE, + G::from_u64(255), + G::from_u64(256), + G::from_u64(1 << 32), + G::from_u64((1 << 48) - 1), + G::from_u64(17), + ]; + let mut out = Vec::new(); + out.write_all(b"Aiur circuit rows v3\n")?; + write_u64(&mut out, (12 * groups.len()) as u64)?; + let mut checked = 0; + for seed in 0..12 { + let functions: Vec<_> = (0..4).map(|i| fixture_function(seed, i)).collect(); + let circuits = groups + .iter() + .map(|members| Circuit { + members: members.to_vec(), + layout: circuit_layout(&functions, members), + }) + .collect(); + let top = Toplevel { + functions, + circuits, + memory_sizes: vec![], + call_components: vec![], + }; + for function in &top.functions { + let counts = function.body.control_counts().expect("control counts fit"); + assert_eq!(counts.leaves, function.layout.selectors); + for count in [counts.nodes, counts.leaves, counts.returns, counts.yields] + { + write_u64(&mut out, count as u64)?; + } + } + assert!(top.validate_row_counts().is_ok()); + out.push(u8::from(top.validate_row_counts().is_ok())); + for circuit_index in 0..groups.len() { + let circuit = &top.circuits[circuit_index]; + let count = circuit.layout.selectors; + for limit in [0, count.saturating_sub(1), count, count + 1] { + let variant = Circuit { + members: circuit.members.clone(), + layout: FunctionLayout { selectors: limit, ..circuit.layout }, + }; + out.push(u8::from(variant.validate_row_counts(&top).is_ok())); + } + let mut missing = circuit.members.clone(); + missing.push(top.functions.len()); + let missing = Circuit { members: missing, layout: circuit.layout }; + assert!(missing.validate_row_counts(&top).is_err()); + out.push(u8::from(missing.validate_row_counts(&top).is_ok())); + let doubled = + Circuit { members: circuit.members.repeat(2), layout: circuit.layout }; + out.push(u8::from(doubled.validate_row_counts(&top).is_ok())); + out.push(u8::from(top.circuit_is_branchless(circuit_index))); + let (constraints, lookups) = top.build_constraints(circuit_index); + let selector_count = constraints.selectors.len(); + write_u64(&mut out, constraints.width as u64)?; + write_u64(&mut out, constraints.selectors.start as u64)?; + write_u64(&mut out, selector_count as u64)?; + write_u64(&mut out, lookups.len() as u64)?; + write_u64(&mut out, (8 + 2 * selector_count) as u64)?; + for pattern in 0..8 + 2 * selector_count { + let mut row: Vec<_> = (0..constraints.width) + .map(|index| { + choices[(seed + 5 * index + 3 * pattern) % choices.len()] + }) + .collect(); + for index in 0..selector_count { + row[constraints.selectors.start + index] = + assignment(pattern, index, selector_count); + } + let values = local_values(&row); + let equations: Vec<_> = constraints + .zeros + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect(); + write_values(&mut out, &equations)?; + for lookup in &lookups { + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + let message: Vec<_> = + lookup.args.iter().map(|expr| eval_expr(expr, &values)).collect(); + write_values(&mut out, &message)?; + } + checked += 1; + } + } + } + assert_eq!(checked, 2022); + if let Some(path) = std::env::var_os("IX_CIRCUIT_ROW_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "circuit rows: {checked} assignments, 48 control counts, 588 count checks, 96 branchless decisions" + ); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/compiled_keys.rs b/crates/aiur/src/constraints/tests/compiled_keys.rs new file mode 100644 index 000000000..843b06e71 --- /dev/null +++ b/crates/aiur/src/constraints/tests/compiled_keys.rs @@ -0,0 +1,217 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Native key construction from transported function fixtures, memories and +//! both byte tables. Include all native matrix families in the assignments. + +use super::{ + block_expressions::write_block, + circuit_expressions::write_layout, + circuit_rows::{circuit_layout, fixture_function}, + operation_expressions::write_indices, + *, +}; +use crate::{ + bytecode::Circuit, + gadgets::{AiurGadget, bytes1::Bytes1, bytes2::Bytes2}, + memory::Memory, + synthesis::AiurConfig, + vk_codec, +}; +use multi_stark::{ + config::StarkGenericConfig, + p3_field::BasedVectorSpace, + system::{CircuitInputs, System}, + types::{CommitmentParameters, ExtVal, FriParameters}, +}; + +fn inputs(top: &Toplevel) -> Vec> { + let mut result = Vec::new(); + for (index, _) in top.circuits.iter().enumerate() { + let (constraints, lookups) = top.build_constraints(index); + let lookup_group_size = + if top.circuit_is_branchless(index) && lookups.len() >= 2 { + 2 + } else { + 1 + }; + result.push(CircuitInputs { + main_width: constraints.width, + constraints: constraints.zeros, + lookups, + lookup_group_size, + ..CircuitInputs::default() + }); + } + for &width in &top.memory_sizes { + let (memory, constraints, lookups) = Memory::build(width); + result.push(CircuitInputs { + main_width: memory.width, + constraints, + lookups, + lookup_group_size: 1, + ..CircuitInputs::default() + }); + } + result.extend([ + CircuitInputs { + main_width: Bytes1.main_width(), + preprocessed: Bytes1.preprocessed(), + lookups: Bytes1.lookups(), + lookup_group_size: 2, + ..CircuitInputs::default() + }, + CircuitInputs { + main_width: Bytes2.main_width(), + preprocessed: Bytes2.preprocessed(), + lookups: Bytes2.lookups(), + lookup_group_size: 2, + ..CircuitInputs::default() + }, + ]); + result +} + +fn columns(width: usize, seed: usize, family: usize) -> Vec { + (0..width) + .map(|index| match seed { + 0 => G::ZERO, + 1 => G::ONE, + 2 => -G::ONE, + _ => G::from_usize(17 + family * 31 + index * 13), + }) + .collect() +} + +#[test] +fn compiled_key_snapshot() -> io::Result<()> { + let groups: &[&[usize]] = + &[&[0], &[1], &[2], &[3], &[0, 1], &[2, 0, 3], &[3, 2, 1, 0], &[]]; + let fp = FriParameters { + log_final_poly_len: 0, + max_log_arity: 1, + num_queries: 64, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + }; + let mut out = b"Aiur compiled keys v2\n".to_vec(); + write_u64(&mut out, 12)?; + let mut assignments = 0; + for seed in 0..12 { + let cp = CommitmentParameters { log_blowup: 1 + seed % 3, cap_height: 0 }; + let functions: Vec<_> = + (0..4).map(|index| fixture_function(seed, index)).collect(); + let circuits = groups + .iter() + .map(|members| Circuit { + members: members.to_vec(), + layout: circuit_layout(&functions, members), + }) + .collect(); + let top = Toplevel { + functions, + circuits, + memory_sizes: vec![0, 1, 2, 4, 8], + call_components: vec![], + }; + write_u64(&mut out, top.functions.len() as u64)?; + for function in &top.functions { + write_block(&mut out, &function.body)?; + write_layout(&mut out, function.layout)?; + out.extend([u8::from(function.entry), u8::from(function.constrained)]); + } + write_u64(&mut out, top.circuits.len() as u64)?; + for circuit in &top.circuits { + write_indices(&mut out, &circuit.members)?; + write_layout(&mut out, circuit.layout)?; + } + write_indices(&mut out, &top.memory_sizes)?; + let inputs = inputs(&top); + let expressions: Vec<_> = inputs + .iter() + .map(|input| (input.constraints.clone(), input.lookups.clone())) + .collect(); + let mut system = System::new(AiurConfig::new(cp, fp), inputs).0; + let blowup = system.config.max_quotient_degree(); + for circuit in &mut system.circuits { + crate::lookup_groups::retune( + circuit, + blowup, + >::DIMENSION, + ); + } + let bytes1 = &system.circuits[system.circuits.len() - 2]; + assert_eq!(bytes1.preprocessed_height, 256); + assert_eq!(bytes1.lookup_group_size, 1); + assert_eq!(bytes1.quotient_degree(), 1); + let key = vk_codec::to_bytes(&system, cp, fp); + write_u64(&mut out, key.len() as u64)?; + out.extend(key); + assert_eq!(system.circuits.len(), 15); + for (circuit, (constraints, lookups)) in + system.circuits.iter().zip(expressions) + { + write_u64(&mut out, 4)?; + for pattern in 0..4 { + let pre = columns(circuit.preprocessed_width, pattern, 0); + let pre_next = columns(circuit.preprocessed_width, pattern, 1); + let main = columns(circuit.main_width, pattern, 2); + let main_next = columns(circuit.main_width, pattern, 3); + let stage2 = columns(circuit.stage_2_width, pattern, 4); + let stage2_next = columns(circuit.stage_2_width, pattern, 5); + let publics = columns(circuit.num_publics, pattern, 6); + for cols in + [&pre, &pre_next, &main, &main_next, &stage2, &stage2_next, &publics] + { + write_values(&mut out, cols)?; + } + let selectors = columns(3, pattern, 7); + for selector in &selectors { + write_u64(&mut out, selector.as_canonical_u64())?; + } + let values = VarValues { + preprocessed: [&pre, &pre_next], + main: [&main, &main_next], + stage2: [&stage2, &stage2_next], + publics: &publics, + is_first_row: selectors[0], + is_last_row: selectors[1], + is_transition: selectors[2], + }; + write_values( + &mut out, + &constraints + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect::>(), + )?; + write_u64(&mut out, lookups.len() as u64)?; + for lookup in &lookups { + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + write_values( + &mut out, + &lookup + .args + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect::>(), + )?; + } + assignments += 1; + } + } + } + assert_eq!(assignments, 720); + if let Some(path) = std::env::var_os("IX_COMPILED_KEY_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "compiled keys: 12 systems, 180 circuits, {assignments} assignments" + ); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/emission_checks.rs b/crates/aiur/src/constraints/tests/emission_checks.rs new file mode 100644 index 000000000..c9bfae43a --- /dev/null +++ b/crates/aiur/src/constraints/tests/emission_checks.rs @@ -0,0 +1,192 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Compare checked scopes without allocating values near machine bounds. + +use super::{ + block_expressions::write_block, block_rows::block_fixture, + operation_expressions::write_op, operation_rows::fixtures, *, +}; +use crate::emission_checks::check_emission_ops; + +fn write_result(out: &mut impl Write, result: Option) -> io::Result<()> { + out.write_all(&[u8::from(result.is_some())])?; + if let Some(value) = result { + write_u64(out, value as u64)?; + } + Ok(()) +} + +fn edge_blocks() -> Vec { + fn ret(index: usize, outputs: Vec) -> Block { + Block { ops: vec![], ctrl: Ctrl::Return(index, outputs) } + } + fn yielded(index: usize, outputs: Vec) -> Block { + Block { ops: vec![], ctrl: Ctrl::Yield(index, outputs) } + } + fn continued(arm: Block, size: usize, cont: Block) -> Block { + Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + [(G::ZERO, arm)].into_iter().collect(), + Some(Box::new(ret(1, vec![]))), + size, + 0, + 0, + Box::new(cont), + ), + } + } + vec![ + ret(0, vec![]), + ret(0, vec![0]), + ret(1, vec![]), + ret(usize::MAX, vec![]), + yielded(0, vec![]), + yielded(0, vec![0]), + Block { ops: vec![], ctrl: Ctrl::Match(0, Default::default(), None) }, + Block { ops: vec![Op::Store(vec![0])], ctrl: Ctrl::Return(0, vec![0]) }, + Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + [ + ( + G::ZERO, + Block { + ops: vec![Op::Const(G::ONE)], + ctrl: Ctrl::Return(0, vec![1]), + }, + ), + (G::ONE, ret(1, vec![1])), + ] + .into_iter() + .collect(), + None, + ), + }, + continued(yielded(0, vec![0]), 1, ret(2, vec![1])), + continued(yielded(0, vec![0]), 1, ret(2, vec![2])), + continued(yielded(0, vec![]), 1, ret(2, vec![1])), + continued(yielded(0, vec![0, 0]), 1, ret(2, vec![1])), + continued(ret(0, vec![0]), 0, yielded(2, vec![0])), + continued( + continued(yielded(0, vec![0]), 1, yielded(2, vec![1])), + 1, + ret(3, vec![1]), + ), + continued( + continued(yielded(0, vec![0]), 1, yielded(2, vec![])), + 1, + ret(3, vec![1]), + ), + continued(yielded(0, vec![]), usize::MAX, ret(2, vec![])), + ] +} + +#[test] +fn emission_checks_snapshot() -> io::Result<()> { + let scopes = [ + 0, + 1, + 2, + 3, + 4, + 7, + 8, + 9, + 12, + 16, + usize::MAX - 8, + usize::MAX - 1, + usize::MAX, + ]; + let mut groups = fixtures(); + for width in [0, 1, 2, 3, 5, 6] { + groups.push(vec![Op::U32ToField(vec![0; width])]); + groups.push(vec![Op::UnconstrainedU32Add(vec![0; 4], vec![0; width])]); + groups.push(vec![Op::UnconstrainedU32Add3( + vec![0; 4], + vec![0; width], + vec![0; 4], + )]); + } + groups.extend([ + vec![Op::AssertEq(vec![0], vec![], None)], + vec![Op::AssertEq(vec![], vec![0], None)], + vec![Op::Store(vec![usize::MAX])], + vec![Op::IORead(0, 0, usize::MAX)], + vec![Op::Load(usize::MAX, 0)], + vec![Op::Call(0, vec![], usize::MAX, true)], + ]); + let mut out = b"Aiur emission checks v1\n".to_vec(); + write_u64(&mut out, scopes.len() as u64)?; + for &scope in &scopes { + write_u64(&mut out, scope as u64)?; + } + write_u64(&mut out, groups.len() as u64)?; + let mut operation_checks = 0; + for ops in &groups { + write_u64(&mut out, ops.len() as u64)?; + for op in ops { + write_op(&mut out, op)?; + write_u64(&mut out, op.output_size() as u64)?; + for &scope in &scopes { + out.push(u8::from(op.emission_inputs(scope))); + write_result( + &mut out, + check_emission_ops(std::slice::from_ref(op), scope).ok(), + )?; + operation_checks += 1; + } + } + for &scope in &scopes { + write_result(&mut out, check_emission_ops(ops, scope).ok())?; + } + } + let mut blocks = Vec::new(); + for depth in 0..4 { + for seed in 0..12 { + let mut selectors = 0; + let block = block_fixture(depth, seed, 2, &mut selectors); + blocks.push((block, selectors)); + } + } + blocks.extend(edge_blocks().into_iter().map(|block| (block, 4))); + write_u64(&mut out, blocks.len() as u64)?; + let mut block_checks = 0; + for (block, selectors) in &blocks { + write_block(&mut out, block)?; + let available = [0, 1, 2, 3, usize::MAX]; + let selectors = [0, selectors.saturating_sub(1), *selectors, selectors + 1]; + let yields = [None, Some(0), Some(1), Some(2), Some(3)]; + write_u64( + &mut out, + (available.len() * selectors.len() * yields.len()) as u64, + )?; + for available in available { + for selectors in selectors { + for yield_size in yields { + write_u64(&mut out, available as u64)?; + write_u64(&mut out, selectors as u64)?; + write_result(&mut out, yield_size)?; + out.push(u8::from( + block.check_emission(available, selectors, yield_size).is_ok(), + )); + block_checks += 1; + } + } + } + } + if let Some(path) = std::env::var_os("IX_EMISSION_CHECK_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "emission checks: {operation_checks} operations, {} sequences, {block_checks} control scopes", + groups.len() * scopes.len() + ); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/frontend_expressions.rs b/crates/aiur/src/constraints/tests/frontend_expressions.rs new file mode 100644 index 000000000..818202518 --- /dev/null +++ b/crates/aiur/src/constraints/tests/frontend_expressions.rs @@ -0,0 +1,238 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Export actual smart-constructor trees and scalar operation emission. +//! Deliberate raw negated constants test the boundary of the folding invariant. + +use super::*; +use multi_stark::expr::{ColRef, RowOffset, Source}; + +fn fixtures() -> Vec { + let mut result = + vec![konst(G::ZERO), konst(G::ONE), konst(-G::ONE), konst(G::from_u64(17))]; + for source in [Source::Preprocessed, Source::Main, Source::Stage2] { + for offset in [RowOffset::Current, RowOffset::Next] { + result.push(Expr::Var(ColRef { source, offset, index: 2 })); + } + } + result.extend([ + Expr::Public(0), + Expr::Public(2), + Expr::IsFirstRow, + Expr::IsLastRow, + Expr::IsTransition, + -var(0), + Expr::Add(Box::new(var(0)), Box::new(var(1))), + Expr::Sub(Box::new(konst(G::ZERO)), Box::new(var(0))), + Expr::Mul(Box::new(konst(G::ZERO)), Box::new(var(1))), + Expr::Neg(Box::new(konst(G::ZERO))), + Expr::Neg(Box::new(konst(G::ONE))), + Expr::Neg(Box::new(Expr::Neg(Box::new(var(0))))), + Expr::Neg(Box::new(Expr::Neg(Box::new(konst(G::ONE))))), + Expr::Add(Box::new(konst(G::ONE)), Box::new(konst(G::ONE))), + ]); + result +} + +pub(super) fn write_expr(out: &mut impl Write, expr: &Expr) -> io::Result<()> { + match expr { + Expr::Const(value) => { + out.write_all(&[0])?; + write_u64(out, value.as_canonical_u64()) + }, + Expr::Var(column) => { + let source = match column.source { + Source::Preprocessed => 0, + Source::Main => 1, + Source::Stage2 => 2, + }; + let offset = match column.offset { + RowOffset::Current => 0, + RowOffset::Next => 1, + }; + out.write_all(&[1, source, offset])?; + write_u64(out, u64::from(column.index)) + }, + Expr::Public(index) => { + out.write_all(&[2])?; + write_u64(out, u64::from(*index)) + }, + Expr::IsFirstRow => out.write_all(&[3]), + Expr::IsLastRow => out.write_all(&[4]), + Expr::IsTransition => out.write_all(&[5]), + Expr::Add(a, b) | Expr::Sub(a, b) | Expr::Mul(a, b) => { + let tag = match expr { + Expr::Add(..) => 6, + Expr::Sub(..) => 7, + _ => 8, + }; + out.write_all(&[tag])?; + write_expr(out, a)?; + write_expr(out, b) + }, + Expr::Neg(child) => { + out.write_all(&[9])?; + write_expr(out, child) + }, + } +} + +fn assignment(seed: usize) -> [[G; 16]; 7] { + let choices = [ + G::ZERO, + G::ONE, + G::TWO, + G::from_u64(17), + G::from_u64(255), + G::from_u64(256), + G::from_u64(65536), + -G::ONE, + ]; + let mut rows = array::from_fn(|slot| { + array::from_fn(|index| { + choices[(slot * 3 + seed * 5 + index * 7) % choices.len()] + }) + }); + rows[2][6] = [G::ZERO, G::ONE, G::TWO, -G::ONE][seed]; + rows +} + +fn eval(expr: &Expr, rows: &[[G; 16]; 7], seed: usize) -> G { + eval_expr( + expr, + &VarValues { + preprocessed: [&rows[0], &rows[1]], + main: [&rows[2], &rows[3]], + stage2: [&rows[4], &rows[5]], + publics: &rows[6], + is_first_row: G::from_bool(seed == 0), + is_last_row: G::from_bool(seed == 3), + is_transition: G::from_bool(seed != 3), + }, + ) +} + +fn write_smart( + out: &mut impl Write, + tag: u8, + left: usize, + right: usize, + expr: &Expr, +) -> io::Result<()> { + out.write_all(&[tag])?; + write_u64(out, left as u64)?; + write_u64(out, right as u64)?; + write_expr(out, expr)?; + write_u64(out, u64::from(matches!(expr, Expr::Const(_))))?; + for seed in 0..4 { + write_u64(out, eval(expr, &assignment(seed), seed).as_canonical_u64())?; + } + Ok(()) +} + +fn write_emission( + out: &mut impl Write, + fixtures: &[Expr], + left: usize, + right: usize, + a_degree: Degree, + b_degree: Degree, + kind: u8, +) -> io::Result<()> { + let mut state = state(5, false); + state.map = vec![ + (fixtures[left].clone(), a_degree), + (fixtures[right].clone(), b_degree), + ]; + state.lookup = 0; + state.lookups.clear(); + let op = match kind { + 0 => Op::EqZero(0), + 1 => Op::Add(0, 1), + 2 => Op::Sub(0, 1), + 3 => Op::Mul(0, 1), + _ => unreachable!(), + }; + op.collect_constraints(&var(6), &mut state); + assert_eq!(state.map.len(), 3); + assert_eq!(state.lookup, 0); + assert!(state.lookups.is_empty()); + let (output, degree) = &state.map[2]; + out.write_all(&[kind])?; + for number in [ + left, + right, + a_degree as usize, + b_degree as usize, + state.column - 7, + *degree as usize, + ] { + write_u64(out, number as u64)?; + } + write_expr(out, output)?; + write_u64(out, state.constraints.zeros.len() as u64)?; + for expr in &state.constraints.zeros { + write_expr(out, expr)?; + } + for seed in 0..4 { + let rows = assignment(seed); + write_u64(out, eval(output, &rows, seed).as_canonical_u64())?; + write_u64(out, u64::from(matches!(output, Expr::Const(_))))?; + for expr in &state.constraints.zeros { + write_u64(out, eval(expr, &rows, seed).as_canonical_u64())?; + } + } + Ok(()) +} + +#[test] +fn frontend_expressions_snapshot() -> io::Result<()> { + let fixtures = fixtures(); + assert_eq!(fixtures.len(), 24); + let mut out = Vec::new(); + out.write_all(b"Aiur frontend expressions v1\n")?; + write_u64(&mut out, fixtures.len() as u64)?; + for expr in &fixtures { + write_expr(&mut out, expr)?; + } + write_u64(&mut out, 1752)?; + let mut smart = 0; + for (left, a) in fixtures.iter().enumerate() { + write_smart(&mut out, 3, left, left, &-a.clone())?; + smart += 1; + for (right, b) in fixtures.iter().enumerate() { + for (tag, expr) in [ + (0, a.clone() + b.clone()), + (1, a.clone() - b.clone()), + (2, a.clone() * b.clone()), + ] { + write_smart(&mut out, tag, left, right, &expr)?; + smart += 1; + } + } + } + assert_eq!(smart, 1752); + write_u64(&mut out, 9804)?; + let mut emitted = 0; + for left in 0..19 { + for a_degree in 0..3 { + write_emission(&mut out, &fixtures, left, left, a_degree, a_degree, 0)?; + emitted += 1; + for right in 0..19 { + for b_degree in 0..3 { + for kind in 1..4 { + write_emission( + &mut out, &fixtures, left, right, a_degree, b_degree, kind, + )?; + emitted += 1; + } + } + } + } + } + assert_eq!(emitted, 9804); + if let Some(path) = std::env::var_os("IX_FRONTEND_EXPRESSION_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/memory_rows.rs b/crates/aiur/src/constraints/tests/memory_rows.rs new file mode 100644 index 000000000..931764e3d --- /dev/null +++ b/crates/aiur/src/constraints/tests/memory_rows.rs @@ -0,0 +1,101 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Evaluate the actual memory chip's four equations and its physical lookup, +//! including cyclic next-row openings and the disabled final transition. + +use super::*; +use crate::memory::Memory; + +fn row(height: usize, pattern: usize, index: usize, width: usize) -> Vec { + let choices = [ + G::ZERO, + G::ONE, + -G::ONE, + G::from_u64(255), + G::from_u64(256), + G::from_u64(1 << 32), + G::from_u64((1 << 48) - 1), + G::from_u64(17), + ]; + let selector = match pattern % 8 { + 0 => G::ZERO, + 1 => G::ONE, + 2 => G::from_bool(index < height.div_ceil(2)), + 3 => G::from_bool(index + 1 == height), + 4 => G::from_bool(index.is_multiple_of(2)), + 5 => G::TWO, + 6 => -G::ONE, + _ => choices[(index + pattern) % 8], + }; + (0..width) + .map(|column| { + if pattern == 0 { + return G::ZERO; + } + match column { + 0 if pattern < 8 && selector == G::ZERO => G::ZERO, + 0 => choices[(3 * index + pattern) % 8], + 1 => selector, + 2 if pattern < 16 => -G::ONE + G::from_usize(index), + 2 => G::from_usize(255 + 2 * index), + _ => choices[(5 * column + 3 * index + pattern) % 8], + } + }) + .collect() +} + +#[test] +fn memory_rows_snapshot() -> io::Result<()> { + let mut out = Vec::new(); + out.write_all(b"Aiur memory rows v1\n")?; + write_u64(&mut out, 25)?; + let mut checked = 0; + for size in [0, 1, 2, 4, 8] { + let (memory, constraints, lookups) = Memory::build(size); + assert_eq!(memory.width, 3 + size); + assert_eq!(constraints.len(), 4); + assert_eq!(lookups.len(), 1); + for height in [0, 1, 2, 4, 8] { + for value in [size, height, memory.width, lookups.len(), 24] { + write_u64(&mut out, value as u64)?; + } + for pattern in 0..24 { + for index in 0..height { + let current = row(height, pattern, index, memory.width); + let next = row(height, pattern, (index + 1) % height, memory.width); + let values = VarValues { + preprocessed: [&[], &[]], + main: [¤t, &next], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::from_bool(index == 0), + is_last_row: G::from_bool(index + 1 == height), + is_transition: G::from_bool(index + 1 < height), + }; + let equations: Vec<_> = + constraints.iter().map(|expr| eval_expr(expr, &values)).collect(); + write_values(&mut out, &equations)?; + for lookup in &lookups { + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + let message: Vec<_> = + lookup.args.iter().map(|expr| eval_expr(expr, &values)).collect(); + write_values(&mut out, &message)?; + } + checked += 1; + } + } + } + } + assert_eq!(checked, 1800); + if let Some(path) = std::env::var_os("IX_MEMORY_ROW_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!("memory rows: {checked} assignments across 25 width/height pairs"); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/operation_expressions.rs b/crates/aiur/src/constraints/tests/operation_expressions.rs new file mode 100644 index 000000000..3e9443a80 --- /dev/null +++ b/crates/aiur/src/constraints/tests/operation_expressions.rs @@ -0,0 +1,301 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Export actual operations, incoming expression maps, and complete native +//! emission. Multiple writers restart their lookup cursors to exercise exact +//! argument superposition, with different message widths and input metadata. + +use std::collections::HashSet; + +use super::{frontend_expressions::write_expr, operation_rows, *}; + +pub(super) fn write_indices( + out: &mut impl Write, + indices: &[usize], +) -> io::Result<()> { + write_u64(out, indices.len() as u64)?; + for index in indices { + write_u64(out, *index as u64)?; + } + Ok(()) +} + +fn write_string(out: &mut impl Write, value: &str) -> io::Result<()> { + write_u64(out, value.len() as u64)?; + out.write_all(value.as_bytes()) +} + +fn write_option( + out: &mut W, + value: Option<&T>, + write: impl FnOnce(&mut W, &T) -> io::Result<()>, +) -> io::Result<()> { + match value { + None => out.write_all(&[0]), + Some(value) => { + out.write_all(&[1])?; + write(out, value) + }, + } +} + +// Test transport tags are explicit and exhaustive, independent of Rust enum +// layout. The Lean reader receives the operations used by collect_constraints. +pub(super) fn write_op(out: &mut impl Write, op: &Op) -> io::Result<()> { + use Op::*; + let tag = match op { + Const(_) => 0, + Add(..) => 1, + Sub(..) => 2, + Mul(..) => 3, + EqZero(_) => 4, + Call(..) => 5, + Store(_) => 6, + Load(..) => 7, + AssertEq(..) => 8, + IOGetInfo(..) => 9, + IOSetInfo(..) => 10, + IORead(..) => 11, + IOWrite(..) => 12, + U8BitDecomposition(_) => 13, + U8ShiftLeft(_) => 14, + U8ShiftRight(_) => 15, + U8Xor(..) => 16, + U8Add(..) => 17, + U8Mul(..) => 18, + U8Sub(..) => 19, + U8And(..) => 20, + U8Or(..) => 21, + U8LessThan(..) => 22, + U32LessThan(..) => 23, + U8XorSplit7(..) => 24, + U8XorSplit4(..) => 25, + Debug(..) => 26, + U8RangeCheck(..) => 27, + UnconstrainedBigUintDivMod(..) => 28, + UnconstrainedGToBytes(_) => 29, + UnconstrainedGInverse(_) => 30, + UnconstrainedU32Add(..) => 31, + UnconstrainedU32Add3(..) => 32, + U32ToField(_) => 33, + }; + out.write_all(&[tag])?; + match op { + Const(value) => write_u64(out, value.as_canonical_u64()), + Add(a, b) + | Sub(a, b) + | Mul(a, b) + | U8Xor(a, b) + | U8Add(a, b) + | U8Mul(a, b) + | U8Sub(a, b) + | U8And(a, b) + | U8Or(a, b) + | U8LessThan(a, b) + | U32LessThan(a, b) + | U8XorSplit7(a, b) + | U8XorSplit4(a, b) + | U8RangeCheck(a, b) + | UnconstrainedBigUintDivMod(a, b) + | Load(a, b) => { + write_u64(out, *a as u64)?; + write_u64(out, *b as u64) + }, + EqZero(a) + | U8BitDecomposition(a) + | U8ShiftLeft(a) + | U8ShiftRight(a) + | UnconstrainedGToBytes(a) + | UnconstrainedGInverse(a) => write_u64(out, *a as u64), + Call(function, indices, size, unconstrained) => { + write_u64(out, *function as u64)?; + write_indices(out, indices)?; + write_u64(out, *size as u64)?; + out.write_all(&[u8::from(*unconstrained)]) + }, + Store(indices) | U32ToField(indices) => write_indices(out, indices), + AssertEq(xs, ys, message) => { + write_indices(out, xs)?; + write_indices(out, ys)?; + write_option(out, message.as_ref(), |out, value| write_string(out, value)) + }, + IOGetInfo(a, indices) | IOWrite(a, indices) => { + write_u64(out, *a as u64)?; + write_indices(out, indices) + }, + IOSetInfo(a, indices, b, c) => { + write_u64(out, *a as u64)?; + write_indices(out, indices)?; + write_u64(out, *b as u64)?; + write_u64(out, *c as u64) + }, + IORead(a, b, size) => { + write_u64(out, *a as u64)?; + write_u64(out, *b as u64)?; + write_u64(out, *size as u64) + }, + Debug(message, indices) => { + write_string(out, message)?; + write_option(out, indices.as_ref(), |out, values| { + write_indices(out, values) + }) + }, + UnconstrainedU32Add(a, b) => { + write_indices(out, a)?; + write_indices(out, b) + }, + UnconstrainedU32Add3(a, b, c) => { + write_indices(out, a)?; + write_indices(out, b)?; + write_indices(out, c) + }, + } +} + +pub(super) fn write_exprs( + out: &mut impl Write, + exprs: &[Expr], +) -> io::Result<()> { + write_u64(out, exprs.len() as u64)?; + for expr in exprs { + write_expr(out, expr)?; + } + Ok(()) +} + +pub(super) fn write_map( + out: &mut impl Write, + map: &[(Expr, Degree)], +) -> io::Result<()> { + write_u64(out, map.len() as u64)?; + for (expr, degree) in map { + write_expr(out, expr)?; + write_u64(out, u64::from(*degree))?; + } + Ok(()) +} + +#[test] +fn operation_expressions_snapshot() -> io::Result<()> { + let mut fixtures = operation_rows::fixtures(); + fixtures.extend(operation_rows::constant_degree_fixtures()); + assert_eq!(fixtures.len(), 73); + let kinds: HashSet<_> = + fixtures.iter().flatten().map(std::mem::discriminant).collect(); + assert_eq!(kinds.len(), 34); + + let rows: Vec<_> = [G::ZERO, G::ONE, G::TWO, -G::ONE] + .into_iter() + .enumerate() + .map(|(seed, selector)| operation_rows::row(seed, selector)) + .collect(); + let mut out = Vec::new(); + out.write_all(b"Aiur operation expressions v1\n")?; + write_u64(&mut out, rows.len() as u64)?; + for row in &rows { + write_values(&mut out, row)?; + } + write_u64(&mut out, 876)?; + let mut reports = 0; + let mut sequences = 0; + let mut shared_slots = 0; + for branchless in [false, true] { + for metadata in 0..3 { + for fixture in 0..fixtures.len() { + for writers in [1_usize, 3] { + out.write_all(&[u8::from(branchless)])?; + write_u64(&mut out, writers as u64)?; + let mut state = state(0, branchless); + state.lookups = (0..64).map(|_| empty_lookup()).collect(); + let mut lookup_end = 0; + for writer in 0..writers { + let ops = &fixtures[(fixture + 23 * writer) % fixtures.len()]; + state.column = 4 + 40 * writer; + state.lookup = writer % 2; + state.rank = + if writer == 2 { konst(G::from_u64(257)) } else { var(2) }; + state.map = operation_rows::input_map(); + // Degree tracking is independent of frontend constant folding. + // Exercise zero, ordinary, and conservative positive metadata. + if metadata != 1 { + state.map[0].1 = metadata; + state.map[3].1 = metadata; + state.map[5].1 = 2 * metadata; + } + let selector = var(3 + writer); + write_u64(&mut out, state.column as u64)?; + write_u64(&mut out, state.lookup as u64)?; + write_expr(&mut out, &selector)?; + write_expr(&mut out, &state.rank)?; + write_map(&mut out, &state.map)?; + write_u64(&mut out, ops.len() as u64)?; + for op in ops { + write_op(&mut out, op)?; + } + let equation_start = state.constraints.zeros.len(); + for op in ops { + op.collect_constraints(&selector, &mut state); + } + let equations = &state.constraints.zeros[equation_start..]; + assert!(state.column <= rows[0].len()); + write_u64(&mut out, state.column as u64)?; + write_u64(&mut out, state.lookup as u64)?; + write_map(&mut out, &state.map)?; + write_exprs(&mut out, equations)?; + for row in &rows { + let values = local_values(row); + for (expr, _) in &state.map { + write_u64( + &mut out, + eval_expr(expr, &values).as_canonical_u64(), + )?; + out.write_all(&[u8::from(matches!(expr, Expr::Const(_)))])?; + } + for expr in equations { + write_u64( + &mut out, + eval_expr(expr, &values).as_canonical_u64(), + )?; + } + } + lookup_end = lookup_end.max(state.lookup); + sequences += 1; + } + // Include untouched slots as well as all slots with contributions. + write_u64(&mut out, (lookup_end + 2) as u64)?; + for lookup in &state.lookups[..lookup_end + 2] { + write_expr(&mut out, &lookup.multiplicity)?; + write_exprs(&mut out, &lookup.args)?; + for row in &rows { + let values = local_values(row); + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + let args: Vec<_> = lookup + .args + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect(); + write_values(&mut out, &args)?; + } + } + if writers == 3 { + shared_slots += 1; + } + reports += 1; + } + } + } + } + assert_eq!((reports, sequences, shared_slots), (876, 1752, 438)); + if let Some(path) = std::env::var_os("IX_OPERATION_EXPRESSION_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "operation expressions: {reports} reports, {sequences} native sequences, {shared_slots} shared-slot cases" + ); + Ok(()) +} diff --git a/crates/aiur/src/constraints/tests/operation_rows.rs b/crates/aiur/src/constraints/tests/operation_rows.rs new file mode 100644 index 000000000..e425637e6 --- /dev/null +++ b/crates/aiur/src/constraints/tests/operation_rows.rs @@ -0,0 +1,246 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Evaluate all operation forms against arbitrary rows, including metadata, +//! allocation, polynomial values and every lookup argument. Sequences reuse +//! logical outputs and advance the native auxiliary/lookup cursors. + +use std::collections::HashSet; + +use super::*; + +pub(super) fn fixtures() -> Vec> { + use Op::*; + vec![ + vec![Const(G::ZERO)], + vec![Const(G::ONE)], + vec![Const(-G::ONE)], + vec![Add(0, 1)], + vec![Add(0, 3)], + vec![Add(3, 4)], + vec![Sub(1, 2)], + vec![Sub(0, 3)], + vec![Sub(3, 4)], + vec![Mul(0, 3)], + vec![Mul(1, 3)], + vec![Mul(2, 1)], + vec![Mul(3, 4)], + vec![Mul(5, 6)], + vec![EqZero(0)], + vec![EqZero(1)], + vec![EqZero(2)], + vec![EqZero(3)], + vec![EqZero(4)], + vec![EqZero(5)], + vec![Call(17, vec![3, 4, 5], 0, false)], + vec![Call(17, vec![3, 4, 5], 2, false)], + vec![Call(17, vec![3, 4, 5], 0, true)], + vec![Call(17, vec![3, 4, 5], 2, true)], + vec![Store(vec![])], + vec![Store(vec![0, 3, 4])], + vec![Load(0, 3)], + vec![Load(3, 4)], + vec![AssertEq(vec![], vec![], None)], + vec![AssertEq(vec![0, 3, 4], vec![1, 4, 3], Some("row".into()))], + vec![IOGetInfo(0, vec![1, 2])], + vec![IORead(0, 0, 0)], + vec![IORead(0, 3, 2)], + vec![IOSetInfo(0, vec![1, 2], 3, 4)], + vec![IOWrite(0, vec![3, 4])], + vec![Debug("row".into(), None)], + vec![Debug("row".into(), Some(vec![3, 4]))], + vec![U8BitDecomposition(3)], + vec![U8ShiftLeft(3)], + vec![U8ShiftRight(3)], + vec![U8Xor(3, 4)], + vec![U8Add(3, 4)], + vec![U8Sub(3, 4)], + vec![U8And(3, 4)], + vec![U8Or(3, 4)], + vec![U8LessThan(3, 4)], + vec![U8RangeCheck(3, 4)], + vec![U8Mul(3, 4)], + vec![U8XorSplit7(3, 4)], + vec![U8XorSplit4(3, 4)], + vec![U32LessThan(3, 4)], + vec![UnconstrainedBigUintDivMod(3, 4)], + vec![UnconstrainedGToBytes(3)], + vec![UnconstrainedGInverse(4)], + vec![UnconstrainedU32Add(vec![0, 1, 2, 3], vec![4, 5, 6, 7])], + vec![UnconstrainedU32Add3( + vec![0, 1, 2, 3], + vec![4, 5, 6, 7], + vec![7, 6, 5, 4], + )], + vec![U32ToField(vec![0, 1, 2, 3])], + vec![], + vec![Const(G::ZERO), Mul(8, 3)], + vec![Mul(3, 4), Add(8, 3), EqZero(9)], + vec![ + UnconstrainedGToBytes(3), + U8RangeCheck(8, 9), + U8Add(8, 9), + AssertEq(vec![16], vec![3], None), + UnconstrainedGInverse(17), + ], + vec![ + Store(vec![3, 4]), + Load(2, 8), + Call(17, vec![9, 10], 2, false), + U8Xor(11, 12), + ], + vec![ + IORead(0, 0, 4), + UnconstrainedU32Add(vec![8, 9, 10, 11], vec![0, 1, 2, 7]), + U32ToField(vec![12, 13, 14, 15]), + ], + vec![EqZero(0), Add(8, 1), Sub(9, 1), Mul(10, 7)], + vec![ + UnconstrainedBigUintDivMod(3, 4), + Call(17, vec![8, 9], 0, false), + Debug("row".into(), None), + ], + ] +} + +pub(super) fn input_map() -> Vec<(Expr, Degree)> { + vec![ + (konst(G::ZERO), 0), + (konst(G::ONE), 0), + (konst(-G::ONE), 0), + (var(0), 1), + (var(1), 1), + (var(0) + var(1), 1), + (var(2), 1), + (konst(G::from_u64(257)), 0), + ] +} + +pub(super) fn row(seed: usize, selector: G) -> Vec { + let choices = [ + G::ZERO, + G::ONE, + G::from_u64(255), + G::from_u64(256), + -G::ONE, + -G::TWO, + G::from_u64((1 << 32) - 1), + G::from_u64(1 << 32), + G::from_u64((1 << 48) - 1), + G::from_u64(17), + G::from_u64(3), + G::from_u64(65536), + ]; + let mut row: Vec<_> = + (0..512).map(|i| choices[(seed + 5 * i) % choices.len()]).collect(); + row[0] = choices[seed]; + row[1] = choices[(seed + 1) % choices.len()]; + row[2] = choices[(seed + 2) % choices.len()]; + row[3] = selector; + row +} + +fn write_corpus( + header: &[u8], + fixtures: &[Vec], +) -> io::Result<(Vec, usize)> { + let mut out = Vec::new(); + out.write_all(header)?; + write_u64(&mut out, fixtures.len() as u64)?; + let mut checked = 0; + for branchless in [false, true] { + for seed in 0..12 { + for selector in [G::ZERO, G::ONE, G::TWO, -G::ONE] { + let row = row(seed, selector); + let values = local_values(&row); + for ops in fixtures { + let mut state = state(0, branchless); + state.column = 4; + state.lookup = 0; + state.lookups = (0..64).map(|_| empty_lookup()).collect(); + state.rank = var(2); + state.map = input_map(); + for op in ops { + op.collect_constraints(&var(3), &mut state); + } + assert!(state.column <= row.len()); + write_u64(&mut out, state.column as u64)?; + write_u64(&mut out, state.map.len() as u64)?; + for (expr, degree) in &state.map { + write_u64(&mut out, eval_expr(expr, &values).as_canonical_u64())?; + write_u64(&mut out, u64::from(*degree))?; + write_u64(&mut out, u64::from(matches!(expr, Expr::Const(_))))?; + } + let equations: Vec<_> = state + .constraints + .zeros + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect(); + write_values(&mut out, &equations)?; + write_u64(&mut out, state.lookup as u64)?; + for lookup in &state.lookups[..state.lookup] { + write_u64( + &mut out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + let args: Vec<_> = + lookup.args.iter().map(|expr| eval_expr(expr, &values)).collect(); + write_values(&mut out, &args)?; + } + checked += 1; + } + } + } + } + Ok((out, checked)) +} + +#[test] +fn operation_rows_snapshot() -> io::Result<()> { + let fixtures = fixtures(); + let kinds: HashSet<_> = + fixtures.iter().flatten().map(std::mem::discriminant).collect(); + assert_eq!(kinds.len(), 34, "every bytecode operation constructor"); + assert_eq!(fixtures.len(), 65, "operation and sequence corpus"); + let (out, checked) = write_corpus(b"Aiur operation rows v1\n", &fixtures)?; + assert_eq!(checked, 6240); + if let Some(path) = std::env::var_os("IX_OPERATION_ROW_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!("operation rows: {checked} assignments across all 34 constructors"); + Ok(()) +} + +pub(super) fn constant_degree_fixtures() -> Vec> { + use Op::*; + vec![ + vec![Const(G::ZERO), Mul(8, 3), EqZero(9)], + vec![Const(G::ZERO), Mul(3, 8), EqZero(9)], + vec![Mul(0, 3), Add(8, 1), EqZero(9)], + vec![Mul(0, 3), Sub(0, 8), EqZero(9)], + vec![Mul(0, 3), EqZero(8), EqZero(9)], + vec![Mul(0, 3), EqZero(8), Mul(9, 3)], + vec![Mul(0, 3), Mul(8, 1), EqZero(9)], + vec![Mul(0, 3), Sub(2, 8), EqZero(9)], + ] +} + +#[test] +fn constant_degree_rows_snapshot() -> io::Result<()> { + let fixtures = constant_degree_fixtures(); + let (out, checked) = + write_corpus(b"Aiur constant degree rows v1\n", &fixtures)?; + assert_eq!(checked, 768); + if let Some(path) = std::env::var_os("IX_CONSTANT_DEGREE_ROW_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + eprintln!( + "constant degree rows: {checked} arbitrary assignments across eight sequences" + ); + Ok(()) +} diff --git a/crates/aiur/src/graph_shape.rs b/crates/aiur/src/graph_shape.rs new file mode 100644 index 000000000..89614ee81 --- /dev/null +++ b/crates/aiur/src/graph_shape.rs @@ -0,0 +1,184 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use multi_stark::{ + expr::Source, + graph::{Node, NodeId}, + lookup::Lookup, +}; + +use crate::G; + +#[derive(Clone, Copy)] +pub(crate) struct GraphWidths { + pub preprocessed: usize, + pub main: usize, + pub stage2: usize, + pub publics: usize, +} + +/// Check every read made by a full sweep and by the lookup-prefix sweep. +/// The latter has no stage-2 values. Check roots before deriving the prefix, +/// and children before degree recomputation or the native unchecked sweep. +pub(crate) fn checked_graph_prefix( + nodes: &[Node], + zeros: &[NodeId], + lookups: &[Lookup], + widths: GraphWidths, +) -> Option { + let in_bounds = |id: NodeId| id.index() < nodes.len(); + if !zeros.iter().copied().all(in_bounds) + || !lookups.iter().all(|lookup| { + in_bounds(lookup.multiplicity) + && lookup.args.iter().copied().all(in_bounds) + }) + { + return None; + } + let prefix = lookups + .iter() + .flat_map(|lookup| { + std::iter::once(lookup.multiplicity).chain(lookup.args.iter().copied()) + }) + .map(|id| id.index() + 1) + .max() + .unwrap_or(0); + for (index, node) in nodes.iter().enumerate() { + let valid = match *node { + Node::Const(_) + | Node::IsFirstRow + | Node::IsLastRow + | Node::IsTransition => true, + Node::Var(col) => { + let width = match col.source { + Source::Preprocessed => widths.preprocessed, + Source::Main => widths.main, + Source::Stage2 => { + if index < prefix { + return None; + } + widths.stage2 + }, + }; + (col.index as usize) < width + }, + Node::Public(public) => (public as usize) < widths.publics, + Node::Add(a, b) | Node::Sub(a, b) | Node::Mul(a, b) => { + a.index() < index && b.index() < index + }, + Node::Neg(a) => a.index() < index, + }; + if !valid { + return None; + } + } + Some(prefix) +} + +#[cfg(test)] +mod tests { + use super::*; + use multi_stark::{ + expr::{ColRef, RowOffset}, + p3_field::PrimeCharacteristicRing, + }; + use std::{ + fs::File, + io::{self, Write}, + }; + + fn node_choices() -> Vec> { + let indices = [0, 1, 3, 7, 8, u16::MAX.into(), u32::MAX]; + let mut choices = vec![ + Node::Const(G::ZERO), + Node::Const(G::ONE), + Node::Const(-G::ONE), + Node::Const(G::from_u64(65536)), + Node::IsFirstRow, + Node::IsLastRow, + Node::IsTransition, + ]; + for source in [Source::Preprocessed, Source::Main, Source::Stage2] { + for offset in [RowOffset::Current, RowOffset::Next] { + for index in indices { + choices.push(Node::Var(ColRef { source, offset, index })); + } + } + } + for index in indices { + choices.push(Node::Public(index)); + } + for left in indices { + for right in indices { + choices.extend([ + Node::Add(NodeId(left), NodeId(right)), + Node::Sub(NodeId(left), NodeId(right)), + Node::Mul(NodeId(left), NodeId(right)), + ]); + } + } + for index in indices { + choices.push(Node::Neg(NodeId(index))); + } + assert_eq!(choices.len(), 210); + choices + } + + fn write_shapes(out: &mut Vec, nodes: &[Node]) -> usize { + let count = u32::try_from(nodes.len()).expect("small test graph"); + let last = count.saturating_sub(1); + for width in [0, 1, 4, 8] { + let widths = GraphWidths { + preprocessed: width, + main: width + 1, + stage2: width + 2, + publics: width, + }; + for (zeros, lookups) in [ + (vec![], vec![]), + (vec![NodeId(0)], vec![]), + (vec![NodeId(last)], vec![]), + (vec![NodeId(count)], vec![]), + (vec![], vec![Lookup { multiplicity: NodeId(0), args: vec![] }]), + ( + vec![], + vec![Lookup { multiplicity: NodeId(last), args: vec![NodeId(0)] }], + ), + ( + vec![], + vec![Lookup { multiplicity: NodeId(0), args: vec![NodeId(count)] }], + ), + ] { + match checked_graph_prefix(nodes, &zeros, &lookups, widths) { + None => out.push(0), + Some(prefix) => { + out.push(1); + out.extend_from_slice(&(prefix as u64).to_le_bytes()); + }, + } + } + } + 28 + } + + #[test] + fn graph_shape_snapshot() -> io::Result<()> { + let mut out = b"Aiur graph shapes v1\n".to_vec(); + let mut checked = write_shapes(&mut out, &[]); + for count in [1, 2, 4, 8] { + for index in 0..count { + for node in node_choices() { + let mut nodes = vec![Node::Const(G::ZERO); count]; + nodes[index] = node; + checked += write_shapes(&mut out, &nodes); + } + } + } + assert_eq!(checked, 88_228); + if let Some(path) = std::env::var_os("IX_GRAPH_SHAPE_SNAPSHOT") { + File::create(path)?.write_all(&out)?; + } + eprintln!("graph shapes: {checked} checked layouts"); + Ok(()) + } +} diff --git a/crates/aiur/src/lib.rs b/crates/aiur/src/lib.rs index b1364c12a..f4b4212b0 100644 --- a/crates/aiur/src/lib.rs +++ b/crates/aiur/src/lib.rs @@ -4,6 +4,7 @@ pub mod constraints; mod emission_checks; pub mod execute; pub mod gadgets; +mod graph_shape; mod lookup_budget; mod lookup_groups; mod lookup_shapes; diff --git a/crates/aiur/src/synthesis.rs b/crates/aiur/src/synthesis.rs index 29602a76d..8ab5a23f4 100644 --- a/crates/aiur/src/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -675,16 +675,32 @@ impl AiurSystem { #[cfg(test)] mod tests { mod acceptance; + mod advice; + mod blake3; mod branchless; + mod byte_gadgets; mod byte_shapes; mod call_order; mod constant_degree; + mod extension_mmcs; + mod folding; + mod fri_domain; + mod fri_query; mod host_timings; + mod interpolation; mod lookup_budget; mod lookup_groups; mod lookup_shapes; + mod memory; + mod merkle; mod mmcs; mod peak; + mod polynomial; + mod proof_codec; + mod proof_shapes; + mod pruned_merkle; + mod scalar; + mod transcript; use super::*; use crate::{ diff --git a/crates/aiur/src/synthesis/tests/advice.rs b/crates/aiur/src/synthesis/tests/advice.rs new file mode 100644 index 000000000..ced84d0ad --- /dev/null +++ b/crates/aiur/src/synthesis/tests/advice.rs @@ -0,0 +1,156 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; + +/// Supply function rows directly, with only the rank-zero byte requests. +/// This deliberately does not use the executor or its hint implementations. +fn supplied_proof( + system: &AiurSystem, + claim: &[G], + input: &[G], + auxiliaries_after_rank: &[G], +) -> AiurProof { + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(index, shape)| { + let height = if index == 0 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if index == 0 { + rows[..input.len()].copy_from_slice(input); + rows[input.len()] = G::ONE; // selector + rows[input.len() + 1] = G::ONE; // public return multiplicity + let start = input.len() + 8; // selector, multiplicity, six rank bytes + assert_eq!(start + auxiliaries_after_rank.len(), shape.main_width); + rows[start..shape.main_width].copy_from_slice(auxiliaries_after_rank); + } else if index == system.toplevel.circuits.len() + 1 { + rows[6] = G::from_u8(3); // three rank-byte pairs (0, 0) + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + system.system.prove(&system.key, claim, witness) +} + +fn pack_word(bytes: &[G]) -> G { + assert_eq!(bytes.len(), 4); + bytes.iter().enumerate().fold(G::ZERO, |sum, (index, byte)| { + sum + *byte * G::from_u64(1 << (8 * index)) + }) +} + +/// All unconstrained operations can receive arbitrary per-row advice. +/// The u32 carries are virtual expressions and therefore are still pinned. +/// I/O writes, key insertion and debugging do not constrain these rows. +#[test] +fn supplied_advice_has_relational_semantics() { + let function = Function { + body: Block { + ops: vec![ + Op::IOGetInfo(0, vec![]), + Op::IORead(0, 1, 2), + Op::UnconstrainedBigUintDivMod(0, 1), + Op::UnconstrainedGToBytes(0), + Op::UnconstrainedGInverse(0), + Op::Call(1, vec![0], 1, true), + Op::UnconstrainedU32Add(vec![0, 1, 2, 3], vec![4, 5, 6, 7]), + Op::UnconstrainedU32Add3( + vec![0, 1, 2, 3], + vec![4, 5, 6, 7], + vec![8, 9, 10, 11], + ), + Op::IOSetInfo(0, vec![], 1, 2), + Op::IOWrite(0, vec![12, 13]), + Op::Debug("advice effects".into(), Some(vec![14, 15])), + ], + ctrl: Ctrl::Return(0, (12..38).collect()), + }, + layout: FunctionLayout { + input_size: 12, + selectors: 1, + auxiliaries: 31, + lookups: 4, + }, + entry: true, + constrained: true, + }; + let callee = Function { + body: Block { + ops: vec![Op::Const(G::ZERO)], + ctrl: Ctrl::Return(0, vec![1]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 7, + lookups: 4, + }, + entry: false, + constrained: false, + }; + let (cp, fp) = test_parameters(); + let system = AiurSystem::build( + with_singleton_circuits(vec![function, callee], vec![]), + cp, + fp, + ); + let input: Vec<_> = (1..=12).map(G::from_u64).collect(); + // Even the advice called "bytes" is outside the byte range. The bare + // hints impose no range check; a caller must add one when required. + let advice: Vec<_> = (300..324).map(G::from_u64).collect(); + let mut output = advice[..20].to_vec(); + let inverse_2_32 = G::from_u64(0xffff_fffe_0000_0002); + let x = pack_word(&input[..4]); + let y = pack_word(&input[4..8]); + let z = pack_word(&input[8..12]); + output.push((x + y - pack_word(&advice[16..20])) * inverse_2_32); + output.extend_from_slice(&advice[20..24]); + output.push((x + y + z - pack_word(&advice[20..24])) * inverse_2_32); + let mut claim = vec![function_channel(), G::ZERO]; + claim.extend_from_slice(&input); + claim.extend_from_slice(&output); + let proof = supplied_proof(&system, &claim, &input, &advice); + system.verify(&claim, &proof).expect("unchecked advice is permitted"); + + // A changed public carry is not supplied by this same local computation. + *claim.last_mut().unwrap() += G::ONE; + let proof = supplied_proof(&system, &claim, &input, &advice); + assert!(system.verify(&claim, &proof).is_err()); +} + +#[test] +fn checked_inverse_advice_rejects_incorrect_value() { + let function = Function { + body: Block { + ops: vec![ + Op::UnconstrainedGInverse(0), + Op::Mul(0, 1), + Op::Const(G::ONE), + Op::AssertEq(vec![2], vec![3], None), + ], + ctrl: Ctrl::Return(0, vec![1]), + }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 9, + lookups: 4, + }, + entry: true, + constrained: true, + }; + let (cp, fp) = test_parameters(); + let system = + AiurSystem::build(with_singleton_circuits(vec![function], vec![]), cp, fp); + let input = [G::from_u8(3)]; + let wrong = G::from_u8(4); + let claim = [function_channel(), G::ZERO, input[0], wrong]; + let proof = + supplied_proof(&system, &claim, &input, &[wrong, input[0] * wrong]); + assert!(system.verify(&claim, &proof).is_err()); + let (claim, proof) = system.prove(0, &input, &mut empty_io_buffer()); + system.verify(&claim, &proof).expect("checked honest inverse must verify"); +} diff --git a/crates/aiur/src/synthesis/tests/blake3.rs b/crates/aiur/src/synthesis/tests/blake3.rs new file mode 100644 index 000000000..e93d9b81c --- /dev/null +++ b/crates/aiur/src/synthesis/tests/blake3.rs @@ -0,0 +1,101 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Independent native outputs for the checked unkeyed BLAKE3 implementation. + +use ::blake3::{ + Hasher, + hazmat::{ + HasherExt, Mode, left_subtree_len, merge_subtrees_non_root, + merge_subtrees_root, + }, +}; +use p3_symmetric::CryptographicHasher; +use std::collections::BTreeSet; + +fn number(out: &mut Vec, value: u64) { + out.extend(value.to_le_bytes()); +} + +fn bytes(out: &mut Vec, value: &[u8]) { + number(out, u64::try_from(value.len()).unwrap()); + out.extend(value); +} + +fn input(length: usize, salt: usize) -> Vec { + (0..length) + .map(|i| u8::try_from((i * 17 + i / 251 * 13 + salt * 29) % 256).unwrap()) + .collect() +} + +#[test] +fn blake3_snapshot() -> std::io::Result<()> { + let mut out = b"Aiur Blake3 v1\n".to_vec(); + let mut lengths: BTreeSet = (0..=128).chain(960..=1024).collect(); + lengths.extend([255, 256, 257, 511, 512, 513]); + for chunks in (1..=17).chain([32, 64, 128]) { + lengths.extend([chunks * 1024 - 1, chunks * 1024, chunks * 1024 + 1]); + } + number(&mut out, u64::try_from(lengths.len()).unwrap()); + for (case, length) in lengths.into_iter().enumerate() { + let data = input(length, case); + let expected = ::blake3::hash(&data); + let p3: [u8; 32] = p3_blake3::Blake3.hash_iter(data.iter().copied()); + assert_eq!(p3, *expected.as_bytes()); + let mut stream = Hasher::new(); + for part in + data.chunks([1, 63, 64, 65, 511, 512, 1023, 1024, 1025][case % 9]) + { + stream.update(part); + } + assert_eq!(stream.finalize(), expected); + bytes(&mut out, &data); + out.extend(expected.as_bytes()); + if length > 1024 { + let split = left_subtree_len(u64::try_from(length).unwrap()); + number(&mut out, split); + let split = usize::try_from(split).unwrap(); + let left = Hasher::new().update(&data[..split]).finalize_non_root(); + let right = Hasher::new() + .set_input_offset(u64::try_from(split).unwrap()) + .update(&data[split..]) + .finalize_non_root(); + assert_eq!(merge_subtrees_root(&left, &right, Mode::Hash), expected); + out.extend(left); + out.extend(right); + } + } + let counters = [0, 1, 2, 255, (1 << 32) - 1, 1 << 32, (1 << 54) - 1]; + let chunk_lengths = [1, 63, 64, 65, 1023, 1024]; + number( + &mut out, + u64::try_from(counters.len() * chunk_lengths.len()).unwrap(), + ); + for counter in counters { + for length in chunk_lengths { + let data = input(length, usize::try_from(counter % 251).unwrap()); + let cv = Hasher::new() + .set_input_offset(counter * 1024) + .update(&data) + .finalize_non_root(); + number(&mut out, counter); + bytes(&mut out, &data); + out.extend(cv); + } + } + number(&mut out, 64); + for salt in 0..64 { + let left: [u8; 32] = input(32, salt).try_into().unwrap(); + let right: [u8; 32] = input(32, salt + 83).try_into().unwrap(); + out.extend(left); + out.extend(right); + out.extend(merge_subtrees_non_root(&left, &right, Mode::Hash)); + out.extend(merge_subtrees_root(&left, &right, Mode::Hash).as_bytes()); + // PCS Merkle compression is an ordinary hash of 64 digest bytes. + out.extend(::blake3::hash(&[left, right].concat()).as_bytes()); + } + if let Some(path) = std::env::var_os("IX_BLAKE3_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/byte_gadgets.rs b/crates/aiur/src/synthesis/tests/byte_gadgets.rs new file mode 100644 index 000000000..6bad5671c --- /dev/null +++ b/crates/aiur/src/synthesis/tests/byte_gadgets.rs @@ -0,0 +1,243 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Export the actual fixed byte-chip rows and evaluated lookup messages for +//! the Lean component gate. No program executor is involved. + +use std::{ + fs::File, + io::{self, BufWriter, Write}, +}; + +use super::{ + AiurSystem, Block, Ctrl, Function, FunctionLayout, Op, RowMajorMatrix, + SystemWitness, function_channel, test_parameters, with_singleton_circuits, +}; +use crate::{ + G, + gadgets::{AiurGadget, bytes1::Bytes1, bytes2::Bytes2}, +}; +use multi_stark::{ + eval::{VarValues, eval_expr}, + p3_field::{PrimeCharacteristicRing, PrimeField64}, + p3_matrix::Matrix, +}; + +fn local_values(row: &[G]) -> VarValues<'_, G> { + VarValues { + preprocessed: [&[], &[]], + main: [row, row], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ONE, + is_last_row: G::ZERO, + is_transition: G::ONE, + } +} + +fn write_u64(out: &mut impl Write, value: u64) -> io::Result<()> { + out.write_all(&value.to_le_bytes()) +} + +fn export(gadget: &T, out: &mut impl Write) -> io::Result<()> { + let preprocessed = gadget.preprocessed().expect("fixed byte chip"); + let lookups = gadget.lookups(); + write_u64(out, preprocessed.height() as u64)?; + write_u64(out, preprocessed.width() as u64)?; + write_u64(out, lookups.len() as u64)?; + for lookup in &lookups { + write_u64(out, lookup.args.len() as u64)?; + } + // Distinct weights also pin the lookup-slot-to-multiplicity-column map. + let weights: Vec = + (0..gadget.main_width()).map(|index| G::from_usize(index + 17)).collect(); + for row in preprocessed.values.chunks_exact(preprocessed.width()) { + for value in row { + write_u64(out, value.as_canonical_u64())?; + } + let values = VarValues { + preprocessed: [row, row], + main: [&weights, &weights], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ZERO, + is_last_row: G::ZERO, + is_transition: G::ZERO, + }; + for lookup in &lookups { + write_u64( + out, + eval_expr(&lookup.multiplicity, &values).as_canonical_u64(), + )?; + for argument in &lookup.args { + write_u64(out, eval_expr(argument, &values).as_canonical_u64())?; + } + } + } + Ok(()) +} + +#[test] +fn byte_gadget_snapshot() -> io::Result<()> { + let mut out = Vec::new(); + out.write_all(b"Aiur byte gadgets v1\n")?; + export(&Bytes1, &mut out)?; + export(&Bytes2, &mut out)?; + assert_eq!(out.len(), 34_664_621, "complete row and lookup inventory"); + if let Some(path) = std::env::var_os("IX_BYTE_GADGET_SNAPSHOT") { + let mut file = BufWriter::new(File::create(path)?); + file.write_all(&out)?; + file.flush()?; + } + Ok(()) +} + +#[test] +fn emitted_virtual_byte_carries_match_all_input_pairs() { + for addition in [true, false] { + let op = if addition { Op::U8Add(0, 1) } else { Op::U8Sub(0, 1) }; + let top = with_singleton_circuits( + vec![Function { + body: Block { ops: vec![op], ctrl: Ctrl::Return(0, vec![2, 3]) }, + layout: FunctionLayout { + input_size: 2, + selectors: 1, + auxiliaries: 8, + lookups: 5, + }, + entry: true, + constrained: true, + }], + vec![], + ); + let (constraints, lookups) = top.build_constraints(0); + assert_eq!(constraints.width, 11); + let mut row = vec![G::ZERO; constraints.width]; + row[2] = G::ONE; + row[3] = G::ONE; + for x in 0..=u8::MAX { + for y in 0..=u8::MAX { + let (low, carry) = + if addition { x.overflowing_add(y) } else { x.overflowing_sub(y) }; + row[0] = G::from_u8(x); + row[1] = G::from_u8(y); + row[10] = G::from_u8(low); + let values = local_values(&row); + assert_eq!(eval_expr(&lookups[0].args[4], &values), G::from_u8(low)); + assert_eq!( + eval_expr(&lookups[0].args[5], &values), + G::from_bool(carry), + "addition {addition}, x {x}, y {y}" + ); + } + } + } +} + +#[test] +fn supplied_u32_comparison_checks_carries_decomposition_and_range() { + let top = with_singleton_circuits( + vec![Function { + body: Block { + ops: vec![Op::U32LessThan(0, 1)], + ctrl: Ctrl::Return(0, vec![2]), + }, + layout: FunctionLayout { + input_size: 2, + selectors: 1, + auxiliaries: 19, + lookups: 10, + }, + entry: true, + constrained: true, + }], + vec![], + ); + let (constraints, lookups) = top.build_constraints(0); + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(top, cp, fp); + let honest = [ + (0u32, 0u32), + (0, 1), + (1, 0), + (u32::MAX, u32::MAX), + (u32::MAX, 0), + (0, u32::MAX), + (256, 255), + ]; + // Kind 0 is honest; mutations 1, 2 and 3 isolate carry, decomposition + // and byte-range constraints while keeping the public return message. + let cases = honest.into_iter().map(|(x, z)| (x, z, 0)).chain([ + (0, 1, 1), + (0, 1, 2), + (0, 1, 3), + ]); + for (x, z, mutation) in cases { + let y = z.wrapping_sub(x).wrapping_sub(1); + let mut row = vec![G::ZERO; constraints.width]; + row[0] = G::from_u32(x); + row[1] = G::from_u32(z); + row[2] = G::ONE; + row[3] = G::ONE; + for (slot, byte) in row[10..].iter_mut().zip( + x.to_le_bytes().into_iter().chain(y.to_le_bytes()).chain(z.to_le_bytes()), + ) { + *slot = G::from_u8(byte); + } + match mutation { + 1 => row[14] = G::ONE, + 2 => row[0] = G::from_u8(2), + 3 => row[14..18].copy_from_slice(&[ + G::from_u16(256), + G::from_u8(255), + G::from_u8(255), + G::from_u8(255), + ]), + _ => (), + } + let values = local_values(&row); + let output = eval_expr(&lookups[0].args[4], &values); + assert_eq!( + constraints.zeros.iter().all(|e| eval_expr(e, &values) == G::ZERO), + mutation == 0 || mutation == 3 + ); + if mutation == 0 { + assert_eq!(output, G::from_bool(x < z)); + } else if mutation == 2 { + assert_eq!(output, G::ONE, "forged 2 < 1"); + } else if mutation == 3 { + assert_eq!(output, G::ZERO, "forged 0 >= 1 with out-of-range byte"); + } + let claim = [function_channel(), G::ZERO, row[0], row[1], output]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(index, shape)| { + let height = if index == 0 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if index == 0 { + rows[..row.len()].copy_from_slice(&row); + } else if index == 2 { + rows[6] = G::from_u8(3); + for pair in row[10..].as_chunks::<2>().0 { + let first = pair[0].as_canonical_u64(); + let second = pair[1].as_canonical_u64(); + if first < 256 && second < 256 { + let index = usize::try_from(first * 256 + second).unwrap(); + rows[index * shape.main_width + 6] += G::ONE; + } + } + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert_eq!( + system.verify(&claim, &proof).is_ok(), + mutation == 0, + "x {x}, z {z}, mutation {mutation}" + ); + } +} diff --git a/crates/aiur/src/synthesis/tests/byte_shapes.rs b/crates/aiur/src/synthesis/tests/byte_shapes.rs index e980fa2e5..75a4ef945 100644 --- a/crates/aiur/src/synthesis/tests/byte_shapes.rs +++ b/crates/aiur/src/synthesis/tests/byte_shapes.rs @@ -33,6 +33,55 @@ fn fixed_heights_follow_active_positions_and_require_fixed_tables() { } } +/// All degree bytes, non-power-of-two heights, inactive positions and +/// independently malformed sequence lengths match the total Lean guard. +#[cfg(target_pointer_width = "64")] +#[test] +fn fixed_trace_height_snapshot() -> std::io::Result<()> { + let header = b"Aiur fixed trace heights v1\n"; + let mut out = header.to_vec(); + for height in [0, 1, 2, 3, 256, 65536, 1 << 31, 1 << 32, 1 << 63, usize::MAX] + { + for degree in 0..=255 { + out.push(u8::from(fixed(&[height], &[true], &[degree]))); + out.push(u8::from(fixed( + &[0, height, 0], + &[false, true, false], + &[degree], + ))); + out.push(u8::from(fixed( + &[0, height, 65536], + &[true, true, true], + &[2, degree, 16], + ))); + } + } + let heights = [0, 256, 0, 65536]; + for height_count in 0..=4 { + for active_count in 0..=4 { + for mask in 0..(1 << active_count) { + let active = (0..active_count) + .map(|bit| mask & (1 << bit) != 0) + .collect::>(); + for degree_count in 0..=5 { + for degree in [0, 1, 7, 8, 9, 15, 16, 17, 63, 64, 255] { + out.push(u8::from(fixed( + &heights[..height_count], + &active, + &vec![degree; degree_count], + ))); + } + } + } + } + } + assert_eq!(out.len(), header.len() + 17_910); + if let Some(path) = std::env::var_os("IX_FIXED_TRACE_HEIGHT_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} + #[test] fn public_verify_checks_fixed_byte_heights_before_openings() { let (cp, fp) = test_parameters(); diff --git a/crates/aiur/src/synthesis/tests/extension_mmcs.rs b/crates/aiur/src/synthesis/tests/extension_mmcs.rs new file mode 100644 index 000000000..9d2906d4c --- /dev/null +++ b/crates/aiur/src/synthesis/tests/extension_mmcs.rs @@ -0,0 +1,363 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Actual extension MMCS delegation, coordinate order and machine widths. + +use super::merkle::{ + Calls, Digest, RecordingHash, RecordingMmcs, digests, number, +}; +use super::*; +use multi_stark::{ + p3_field::{BasedVectorSpace, PrimeField64}, + p3_matrix::{Dimensions, Matrix}, + types::{ExtMmcs, ExtVal, Mmcs}, +}; +use p3_blake3::Blake3; +use p3_commit::{BatchOpeningRef, ExtensionMmcs, Mmcs as _}; +use p3_merkle_tree::PrunedMerklePaths; +use p3_symmetric::{ + CompressionFunctionFromHasher, MerkleCap, SerializingHasher, +}; + +#[derive(Clone)] +struct Case { + shared: bool, + dimensions: Vec, + indices: Vec, + rows: Vec>>, + proof: Vec, + cap: Vec, + cap_height: usize, +} + +#[derive(Default)] +struct Corpus { + body: Vec, + count: usize, + shared: usize, + accepted: usize, + omitted: usize, + overflow: usize, + late: usize, + calls: usize, +} + +impl Corpus { + fn record(&mut self, case: &Case, expected: Option) { + let base = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + case.cap_height, + ); + let native = ExtMmcs::new(base.clone()); + let cap = MerkleCap::new(case.cap.clone()); + let proof = PrunedMerklePaths { sibling_hashes: case.proof.clone() }; + let accepted = if case.shared { + native.verify_multi_batch( + &cap, + &case.dimensions, + &case.indices, + &case.rows, + &proof, + ) + } else { + native.verify_batch( + &cap, + &case.dimensions, + case.indices[0], + BatchOpeningRef::new(&case.rows[0], &case.proof), + ) + } + .is_ok(); + if let Some(expected) = expected { + assert_eq!(accepted, expected); + } + let dimensions: Vec<_> = case + .dimensions + .iter() + .map(|dim| Dimensions { + width: dim.width.wrapping_mul(2), + height: dim.height, + }) + .collect(); + let rows: Vec>> = case + .rows + .iter() + .map(|rows| rows.iter().cloned().map(ExtVal::flatten_to_base).collect()) + .collect(); + let delegated = if case.shared { + base.verify_multi_batch(&cap, &dimensions, &case.indices, &rows, &proof) + } else { + base.verify_batch( + &cap, + &dimensions, + case.indices[0], + BatchOpeningRef::new(&rows[0], &case.proof), + ) + } + .is_ok(); + assert_eq!(accepted, delegated); + let calls = Calls::default(); + let hash = RecordingHash(calls.clone()); + let recording = ExtensionMmcs::::new(RecordingMmcs::new( + SerializingHasher::new(hash.clone()), + CompressionFunctionFromHasher::new(hash), + case.cap_height, + )); + let recorded = if case.shared { + recording.verify_multi_batch( + &cap, + &case.dimensions, + &case.indices, + &case.rows, + &proof, + ) + } else { + recording.verify_batch( + &cap, + &case.dimensions, + case.indices[0], + BatchOpeningRef::new(&case.rows[0], &case.proof), + ) + } + .is_ok(); + assert_eq!(accepted, recorded); + let calls = calls.lock().unwrap(); + let degrees: Vec = case + .dimensions + .iter() + .map(|dim| u8::try_from(dim.height.ilog2()).unwrap()) + .collect(); + let covered = trace_cap_coverage(0, case.cap_height, °rees); + let widths_fit = + case.dimensions.iter().all(|dim| dim.width.checked_mul(2).is_some()); + self.count += 1; + self.shared += usize::from(case.shared); + self.accepted += usize::from(accepted); + self.omitted += usize::from(accepted && !covered); + self.overflow += usize::from(!widths_fit); + self.late += usize::from(!accepted && !calls.is_empty()); + self.calls += calls.len(); + let out = &mut self.body; + out.push(u8::from(case.shared)); + number(out, case.dimensions.len()); + for dim in &case.dimensions { + number(out, dim.width); + number(out, usize::try_from(dim.height.ilog2()).unwrap()); + } + number(out, case.cap_height); + number(out, case.indices.len()); + for &index in &case.indices { + number(out, index); + } + number(out, case.rows.len()); + for rows in &case.rows { + number(out, rows.len()); + for row in rows { + number(out, row.len()); + for value in row { + let coordinates: &[G] = value.as_basis_coefficients_slice(); + for coordinate in coordinates { + out.extend(coordinate.as_canonical_u64().to_le_bytes()); + } + } + } + } + digests(out, &case.proof); + digests(out, &case.cap); + out.extend([u8::from(accepted), u8::from(covered), u8::from(widths_fit)]); + number(out, calls.len()); + for (input, digest) in calls.iter() { + number(out, input.len()); + out.extend(input); + out.extend(digest); + } + } + + fn mutations(&mut self, case: &Case, logs: &[usize]) { + self.record(case, Some(true)); + let mut changed = case.clone(); + changed.proof.push([0; 32]); + self.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.dimensions.clear(); + self.record(&changed, Some(false)); + if case.shared { + let mut changed = case.clone(); + changed.rows.push(vec![]); + self.record(&changed, Some(false)); + } + if case.indices.is_empty() { + return; + } + let max_log = *logs.iter().max().unwrap(); + for (matrix, &log) in logs.iter().enumerate() { + let omitted = log < case.cap_height.min(max_log); + for increment in [ExtVal::ONE, ExtVal::new([G::ZERO, G::ONE])] { + let mut changed = case.clone(); + for query in &mut changed.rows { + query[matrix][0] += increment; + } + self.record(&changed, Some(omitted)); + if case.shared { + let mut changed = case.clone(); + changed.rows[0][matrix][0] += increment; + self.record(&changed, if omitted { None } else { Some(false) }); + } + } + } + if !case.proof.is_empty() { + let mut changed = case.clone(); + changed.proof.pop(); + self.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.proof[0][0] ^= 1; + self.record(&changed, Some(false)); + } + let mut changed = case.clone(); + changed.dimensions[0].width += 1; + self.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.indices[0] = 1 << max_log; + self.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.cap[0][0] ^= 1; + self.record(&changed, None); + let mut changed = case.clone(); + changed.cap.truncate(1); + self.record(&changed, None); + let mut changed = case.clone(); + changed.rows[0].pop(); + self.record(&changed, Some(false)); + // The adapter multiplies verifier metadata using release usize arithmetic. + // Exercise the wrap explicitly; debug builds instead check overflow. + if !cfg!(debug_assertions) { + let mut changed = case.clone(); + changed.dimensions[0].width += 1usize << (usize::BITS - 1); + self.record(&changed, Some(true)); + } + } +} + +#[test] +fn extension_mmcs_snapshot() -> std::io::Result<()> { + let shapes = [ + vec![0], + vec![1], + vec![3], + vec![5], + vec![3, 1], + vec![1, 3], + vec![3, 0, 2, 1], + vec![2, 2, 2], + vec![1, 4, 1, 4, 0], + ]; + let widths = [1, 2, 3, 9, 17, 65]; + let mut corpus = Corpus::default(); + for (fixture, logs) in shapes.into_iter().enumerate() { + let max_log = *logs.iter().max().unwrap(); + let height = 1 << max_log; + let matrices: Vec<_> = logs + .iter() + .enumerate() + .map(|(matrix, log)| { + let width = widths[(fixture + matrix * 3) % widths.len()]; + let values = (0..width * (1 << log)) + .map(|i| { + ExtVal::new([ + G::from_u64(u64::try_from(i * 65537 + fixture).unwrap()), + if i % 3 == 0 { + -G::ONE + } else { + G::from_u64(u64::try_from(i * 257 + matrix + 1).unwrap()) + }, + ]) + }) + .collect(); + RowMajorMatrix::new(values, width) + }) + .collect(); + let dimensions: Vec<_> = matrices.iter().map(Matrix::dimensions).collect(); + let flat_matrices: Vec<_> = matrices + .iter() + .map(|matrix| { + RowMajorMatrix::new( + ExtVal::flatten_to_base(matrix.values.clone()), + matrix.width * 2, + ) + }) + .collect(); + let queries = [ + vec![], + vec![0], + vec![height - 1], + (0..height).rev().collect(), + (0..height).step_by(2).collect(), + (1..height).step_by(2).collect(), + vec![height - 1, 0, height / 2, height - 1, 0], + vec![0, (2 % height)], + ]; + for cap_height in 0..=max_log + 2 { + let base = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + cap_height, + ); + let mmcs = ExtMmcs::new(base.clone()); + let (cap, data) = mmcs.commit(matrices.clone()); + let (base_cap, _) = base.commit(flat_matrices.clone()); + assert_eq!(cap, base_cap); + for index in [0, height / 2, height - 1] { + let (rows, proof) = mmcs.open_batch(index, &data).unpack(); + corpus.mutations( + &Case { + shared: false, + dimensions: dimensions.clone(), + indices: vec![index], + rows: vec![rows], + proof, + cap: cap.roots().to_vec(), + cap_height, + }, + &logs, + ); + } + for indices in &queries { + let (rows, proof) = mmcs.open_multi_batch(indices, &data); + corpus.mutations( + &Case { + shared: true, + dimensions: dimensions.clone(), + indices: indices.clone(), + rows, + proof: proof.sibling_hashes, + cap: cap.roots().to_vec(), + cap_height, + }, + &logs, + ); + } + } + } + let counts = [ + corpus.count, + corpus.shared, + corpus.accepted, + corpus.omitted, + corpus.overflow, + corpus.late, + corpus.calls, + ]; + assert!(corpus.count > 1000 && corpus.calls > 1000); + println!("Extension MMCS: {counts:?}"); + let mut out = b"Aiur extension MMCS v1\n".to_vec(); + number(&mut out, usize::BITS as usize); + for count in counts { + number(&mut out, count); + } + out.extend(corpus.body); + if let Some(path) = std::env::var_os("IX_EXTENSION_MMCS_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/folding.rs b/crates/aiur/src/synthesis/tests/folding.rs new file mode 100644 index 000000000..55af36f4f --- /dev/null +++ b/crates/aiur/src/synthesis/tests/folding.rs @@ -0,0 +1,230 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Native FRI folds of global polynomials spanning several coefficient blocks. + +use multi_stark::{ + p3_field::{ + BasedVectorSpace, HornerIter, PrimeCharacteristicRing, PrimeField64, + TwoAdicField, + }, + p3_matrix::dense::RowMajorMatrix, + types::{ExtVal, Val}, +}; +use p3_fri::{FriFoldingStrategy, TwoAdicFriFolding}; +use p3_util::reverse_bits_len; +use std::{io, marker::PhantomData}; + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + let coordinates: &[Val] = value.as_basis_coefficients_slice(); + for &coordinate in coordinates { + out.extend(coordinate.as_canonical_u64().to_le_bytes()); + } +} + +fn extensions(out: &mut Vec, values: &[ExtVal]) { + nat(out, values.len()); + for &value in values { + extension(out, value); + } +} + +fn sample(seed: usize) -> ExtVal { + ExtVal::new([Val::from_usize(seed * 67 + 3), Val::from_usize(seed * 13 + 1)]) +} + +fn coefficients(arity: usize, variant: usize) -> Vec { + let length = match variant { + 0 => 0, + 1 => 1, + 2 => arity - 1, + 3 => arity, + 4 => arity + 1, + 5 => 2 * arity + 1, + 6 => 3 * arity, + _ => 3 * arity + 2, + }; + (0..length) + .map(|index| match variant { + 6 => { + if index + 1 == length { + ExtVal::ONE + } else { + ExtVal::ZERO + } + }, + 7 if index > arity => ExtVal::ZERO, + _ => sample(index + 17), + }) + .collect() +} + +fn query_point(bits: usize, index: usize) -> ExtVal { + Val::two_adic_generator(bits) + .exp_u64(u64::try_from(reverse_bits_len(index, bits)).unwrap()) + .into() +} + +fn nodes(parent: usize, log_arity: usize, index: usize) -> Vec { + (0..1 << log_arity) + .map(|slot| query_point(parent, (index << log_arity) + slot)) + .collect() +} + +fn fold_row( + index: usize, + height: usize, + log_arity: usize, + challenge: ExtVal, + values: &[ExtVal], +) -> ExtVal { + as FriFoldingStrategy>::fold_row( + &TwoAdicFriFolding(PhantomData), + index, + height, + log_arity, + challenge, + values.iter().copied(), + ) +} + +fn folded_coefficients( + coefficients: &[ExtVal], + arity: usize, + challenge: ExtVal, +) -> Vec { + coefficients + .chunks(arity) + .map(|block| block.iter().copied().horner(challenge)) + .collect() +} + +#[test] +fn folding_snapshot() -> io::Result<()> { + let mut out = b"Aiur global FRI folding v1\n".to_vec(); + let mut rows = 0; + let mut evaluations = 0; + for parent in 0..=32 { + for log_arity in 0..=parent.min(6) { + let height = parent - log_arity; + let arity = 1 << log_arity; + let mask = (1_usize << height) - 1; + let mut indices = vec![0, mask / 2, mask]; + indices.sort_unstable(); + indices.dedup(); + nat(&mut out, indices.len()); + for index in indices { + nat(&mut out, index); + let nodes = nodes(parent, log_arity, index); + for variant in 0..8 { + let polynomial = coefficients(arity, variant); + let values: Vec<_> = nodes + .iter() + .map(|&node| polynomial.iter().copied().horner(node)) + .collect(); + extensions(&mut out, &polynomial); + extensions(&mut out, &values); + for challenge in + [ExtVal::ZERO, sample(41), ExtVal::ONE, nodes[0], nodes[arity - 1]] + { + let folded = folded_coefficients(&polynomial, arity, challenge); + let result = fold_row(index, height, log_arity, challenge, &values); + assert_eq!( + result, + folded.iter().copied().horner(query_point(height, index)) + ); + extension(&mut out, challenge); + extensions(&mut out, &folded); + extension(&mut out, result); + evaluations += 1; + } + rows += 1; + } + } + } + } + let mut matrices = 0; + let mut matrix_rows = 0; + for parent in 1..=9 { + for log_arity in 1..=parent.min(6) { + let arity = 1 << log_arity; + let height = parent - log_arity; + for variant in 0..8 { + let polynomial = coefficients(arity, variant); + let data: Vec<_> = (0..1 << parent) + .map(|index| { + polynomial.iter().copied().horner(query_point(parent, index)) + }) + .collect(); + extensions(&mut out, &polynomial); + extensions(&mut out, &data); + for challenge in [ExtVal::ZERO, sample(41), ExtVal::ONE] { + let folded = folded_coefficients(&polynomial, arity, challenge); + let result = as FriFoldingStrategy< + Val, + ExtVal, + >>::fold_matrix( + &TwoAdicFriFolding(PhantomData), + challenge, + log_arity, + RowMajorMatrix::new(data.clone(), arity), + ); + assert_eq!(result.len(), 1 << height); + for (index, &value) in result.iter().enumerate() { + assert_eq!( + value, + folded.iter().copied().horner(query_point(height, index)) + ); + matrix_rows += 1; + } + extension(&mut out, challenge); + extensions(&mut out, &folded); + extensions(&mut out, &result); + matrices += 1; + } + } + } + } + let mut pairs = 0; + let mut pair_evaluations = 0; + for log_arity in 0..=6 { + let arity = 1 << log_arity; + let parent = log_arity + 2; + let mut challenges = nodes(parent, log_arity, 1); + challenges.extend([ExtVal::ZERO, sample(41)]); + let left: Vec<_> = (0..arity).map(|index| sample(index + 7)).collect(); + let mut right = left.clone(); + right[arity / 2] += sample(131); + extensions(&mut out, &left); + extensions(&mut out, &right); + let mut agreements = 0; + for challenge in challenges { + let first = fold_row(1, 2, log_arity, challenge, &left); + let second = fold_row(1, 2, log_arity, challenge, &right); + agreements += usize::from(first == second); + extension(&mut out, challenge); + extension(&mut out, first); + extension(&mut out, second); + pair_evaluations += 1; + } + assert_eq!(agreements, arity - 1); + nat(&mut out, agreements); + pairs += 1; + } + for count in + [rows, evaluations, matrices, matrix_rows, pairs, pair_evaluations] + { + nat(&mut out, count); + } + if let Ok(path) = std::env::var("IX_FOLDING_SNAPSHOT") { + std::fs::write(path, out)?; + } + println!( + "Global FRI folding: {rows} rows, {evaluations} evaluations, {matrices} matrices, {matrix_rows} matrix rows, {pairs} distinct row pairs, {pair_evaluations} pair evaluations" + ); + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/fri_domain.rs b/crates/aiur/src/synthesis/tests/fri_domain.rs new file mode 100644 index 000000000..20ca63b1d --- /dev/null +++ b/crates/aiur/src/synthesis/tests/fri_domain.rs @@ -0,0 +1,180 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Native bit reversal, FRI interpolation node selection and domain reduction. + +use multi_stark::{ + p3_field::{ + BasedVectorSpace, PrimeCharacteristicRing, PrimeField64, TwoAdicField, + }, + types::{ExtVal, Val}, +}; +use p3_fri::{FriFoldingStrategy, TwoAdicFriFolding}; +use p3_util::{reverse_bits_len, reverse_slice_index_bits}; +use std::{io, marker::PhantomData}; + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + let coordinates: &[Val] = value.as_basis_coefficients_slice(); + for &coordinate in coordinates { + field(out, coordinate); + } +} + +fn samples(bits: usize, exhaustive: usize) -> Vec { + let mask = + if bits == 0 { 0 } else { usize::MAX >> (usize::BITS as usize - bits) }; + let mut indices: Vec<_> = (0..=mask.min(exhaustive - 1)).collect(); + indices.extend([mask, mask / 2, mask.saturating_sub(1)]); + for seed in 0..16_usize { + indices.push(seed.wrapping_mul(0x0a37_51c9) & mask); + } + indices.sort_unstable(); + indices.dedup(); + indices +} + +#[test] +fn fri_domain_snapshot() -> io::Result<()> { + let mut out = b"Aiur FRI domains v1\n".to_vec(); + let word_bits = usize::BITS as usize; + assert!(word_bits == 32 || word_bits == 64); + nat(&mut out, word_bits); + let mut reversals = 0; + for bits in 0..=word_bits { + let indices = samples(bits, 1024); + nat(&mut out, indices.len()); + for index in indices { + let reversed = reverse_bits_len(index, bits); + assert_eq!(reverse_bits_len(reversed, bits), index); + nat(&mut out, index); + nat(&mut out, reversed); + reversals += 1; + } + } + // Width zero is an overflowing shift, so an inadmissible nonzero index + // retains its full-word reverse. The correspondence theorem needs a bound. + nat(&mut out, reverse_bits_len(1, 0)); + assert_eq!(reverse_bits_len(1, 0), 1 << (word_bits - 1)); + + let mut points = 0; + for bits in 0..=32 { + let generator = Val::two_adic_generator(bits); + let indices = samples(bits, 1024); + nat(&mut out, indices.len()); + for index in indices { + let reversed = reverse_bits_len(index, bits); + let point = generator.exp_u64(u64::try_from(reversed).unwrap()); + let input = Val::from_u64(7) * point; + assert_eq!(point.exp_power_of_2(bits), Val::ONE); + assert_ne!(input.exp_power_of_2(bits), Val::ONE); + nat(&mut out, index); + field(&mut out, point); + field(&mut out, input); + points += 1; + } + } + + let mut nested = 0; + for parent in 0..=32 { + let generator = Val::two_adic_generator(parent); + for child in 0..=parent { + assert_eq!( + generator.exp_power_of_2(parent - child), + Val::two_adic_generator(child) + ); + let indices = samples(child, 4); + nat(&mut out, indices.len()); + for index in indices { + let padded = generator + .exp_u64(u64::try_from(reverse_bits_len(index, parent)).unwrap()); + let reduced = Val::two_adic_generator(child) + .exp_u64(u64::try_from(reverse_bits_len(index, child)).unwrap()); + assert_eq!(padded, reduced); + nat(&mut out, index); + field(&mut out, padded); + nested += 1; + } + } + } + + let folding = TwoAdicFriFolding::<(), ()>(PhantomData); + assert_eq!( as FriFoldingStrategy>::extra_query_index_bits(&folding), 0); + let mut rows = 0; + let mut slots = 0; + for parent in 0..=32 { + // Arity one covers the public helper's boundary. Accepted FRI rounds + // additionally require a positive arity logarithm. + for log_arity in 0..=parent.min(8) { + let height = parent - log_arity; + let arity = 1 << log_arity; + let mask = + if height == 0 { 0 } else { usize::MAX >> (word_bits - height) }; + let mut indices = vec![0, mask / 2, mask, 0x0a37_51c9 & mask]; + indices.sort_unstable(); + indices.dedup(); + nat(&mut out, indices.len()); + for index in indices { + nat(&mut out, index); + let start = Val::two_adic_generator(parent) + .exp_u64(u64::try_from(reverse_bits_len(index, height)).unwrap()); + let mut nodes: Vec<_> = Val::two_adic_generator(log_arity) + .shifted_powers(start) + .take(arity) + .collect(); + reverse_slice_index_bits(&mut nodes); + let values: Vec<_> = (0..arity) + .map(|slot| { + ExtVal::new([ + Val::from_usize(slot + 1), + Val::from_usize(slot * 19 + 3), + ]) + }) + .collect(); + let child = Val::two_adic_generator(height) + .exp_u64(u64::try_from(reverse_bits_len(index, height)).unwrap()); + for (slot, &node) in nodes.iter().enumerate() { + let query = index * arity + slot; + let direct = Val::two_adic_generator(parent) + .exp_u64(u64::try_from(reverse_bits_len(query, parent)).unwrap()); + assert_eq!(node, direct); + assert_eq!(node.exp_power_of_2(log_arity), child); + let folded = as FriFoldingStrategy< + Val, + ExtVal, + >>::fold_row( + &folding, + index, + height, + log_arity, + ExtVal::from(node), + values.iter().copied(), + ); + assert_eq!(folded, values[slot]); + field(&mut out, node); + field(&mut out, child); + extension(&mut out, folded); + slots += 1; + } + rows += 1; + } + } + } + for count in [reversals, points, nested, rows, slots] { + nat(&mut out, count); + } + if let Ok(path) = std::env::var("IX_FRI_DOMAIN_SNAPSHOT") { + std::fs::write(path, out)?; + } + println!( + "FRI domains: {reversals} reversals, {points} query points, {nested} nested points, {rows} rows and {slots} native fold-node selections" + ); + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/fri_query.rs b/crates/aiur/src/synthesis/tests/fri_query.rs new file mode 100644 index 000000000..64323ece4 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/fri_query.rs @@ -0,0 +1,439 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Record the real FRI verifier's private query routine through its public +//! folding strategy hook, with honest PCS proofs and the concrete MMCS. + +use super::*; +use multi_stark::{ + config::StarkGenericConfig, + p3_field::{BasedVectorSpace, Field, HornerIter, PrimeField64, TwoAdicField}, + p3_matrix::{Matrix, dense::RowMajorMatrix}, + types::{Challenger, ExtMmcs, ExtVal, Mmcs, Pcs, Val}, +}; +use p3_blake3::Blake3; +use p3_challenger::{ + CanObserve, CanSample, CanSampleBits, FieldChallenger, GrindingChallenger, +}; +use p3_commit::{Mmcs as MmcsTrait, Pcs as PcsTrait}; +use p3_fri::{ + BatchMultiOpening, FriFoldingStrategy, FriParameters as NativeParameters, + TwoAdicFriFolding, verifier::verify_fri, +}; +use p3_symmetric::{ + CompressionFunctionFromHasher, MerkleCap, SerializingHasher, +}; +use p3_util::reverse_bits_len; +use std::{cell::RefCell, io, marker::PhantomData}; + +type Dft = ::Dft; +type Commitment = MerkleCap; +type NativeFolding = TwoAdicFriFolding< + Vec>, + >::Error, +>; + +struct FoldCall { + index: usize, + height: usize, + log_arity: usize, + challenge: ExtVal, + values: Vec, + result: ExtVal, +} + +#[derive(Default)] +struct RecordingFolding(RefCell>); + +impl FriFoldingStrategy for RecordingFolding { + type InputProof = Vec>; + type InputError = >::Error; + + fn extra_query_index_bits(&self) -> usize { + let native: NativeFolding = TwoAdicFriFolding(PhantomData); + >::extra_query_index_bits( + &native, + ) + } + + fn fold_row( + &self, + index: usize, + height: usize, + log_arity: usize, + challenge: ExtVal, + evals: impl Iterator, + ) -> ExtVal { + let values: Vec<_> = evals.collect(); + let native: NativeFolding = TwoAdicFriFolding(PhantomData); + let result = >::fold_row( + &native, + index, + height, + log_arity, + challenge, + values.iter().copied(), + ); + self.0.borrow_mut().push(FoldCall { + index, + height, + log_arity, + challenge, + values, + result, + }); + result + } + + fn fold_matrix>( + &self, + challenge: ExtVal, + log_arity: usize, + matrix: M, + ) -> Vec { + let native: NativeFolding = TwoAdicFriFolding(PhantomData); + >::fold_matrix( + &native, challenge, log_arity, matrix, + ) + } +} + +#[derive(Clone)] +struct RecordingChallenger { + inner: Challenger, + fields: Vec, + indices: Vec<(usize, usize)>, +} + +impl CanObserve for RecordingChallenger { + fn observe(&mut self, value: Val) { + self.inner.observe(value); + } +} + +impl CanObserve for RecordingChallenger { + fn observe(&mut self, value: Commitment) { + self.inner.observe(value); + } +} + +impl CanSample for RecordingChallenger { + fn sample(&mut self) -> Val { + let value = self.inner.sample(); + self.fields.push(value); + value + } +} + +impl CanSample for RecordingChallenger { + fn sample(&mut self) -> ExtVal { + self.sample_algebra_element() + } +} + +impl CanSampleBits for RecordingChallenger { + fn sample_bits(&mut self, bits: usize) -> usize { + let value = self.inner.sample_bits(bits); + self.indices.push((bits, value)); + value + } +} + +impl FieldChallenger for RecordingChallenger {} + +impl GrindingChallenger for RecordingChallenger { + type Witness = Val; + + fn grind(&mut self, bits: usize) -> Val { + self.inner.grind(bits) + } +} + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + for &coordinate in value.as_basis_coefficients_slice() { + field(out, coordinate); + } +} + +fn extensions(out: &mut Vec, values: &[ExtVal]) { + nat(out, values.len()); + for &value in values { + extension(out, value); + } +} + +fn query_point(bits: usize, index: usize) -> Val { + Val::two_adic_generator(bits) + .exp_u64(u64::try_from(reverse_bits_len(index, bits)).unwrap()) +} + +fn layout(index: usize, final_bits: usize) -> Vec> { + let offsets = match index { + 0 => vec![vec![0]], + 1 => vec![vec![2]], + 2 => vec![vec![6, 2], vec![2, 0]], + _ => vec![vec![3, 6], vec![3]], + }; + offsets + .into_iter() + .map(|batch| { + batch + .into_iter() + .map(|bits| bits + final_bits + usize::from(final_bits != 0)) + .collect() + }) + .collect() +} + +fn polynomial(seed: usize, bits: usize, column: usize) -> Vec { + (0..1 << bits) + .map(|index| Val::from_usize(seed * 101 + column * 29 + index * 13 + 1)) + .collect() +} + +#[test] +fn fri_query_snapshot() -> io::Result<()> { + let mut out = b"Aiur native FRI query chains v1\n".to_vec(); + let mut cases = 0; + let mut total_queries = 0; + let mut total_rounds = 0; + let mut total_calls = 0; + for blowup in 1..=2 { + for final_bits in 0..=2 { + for max_arity in 1..=4 { + for layout_index in 0..4 { + let logs = layout(layout_index, final_bits); + let queries = 1 + layout_index + final_bits; + let global_bits = + logs.iter().flatten().copied().max().unwrap() + blowup; + let mmcs = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + 0, + ); + let parameters = NativeParameters { + log_blowup: blowup, + log_final_poly_len: final_bits, + max_log_arity: max_arity, + num_queries: queries, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + mmcs: ExtMmcs::new(mmcs.clone()), + }; + let pcs = Pcs::new(Dft::default(), mmcs.clone(), parameters.clone()); + let sources: Vec>>> = logs + .iter() + .enumerate() + .map(|(batch, matrices)| { + matrices + .iter() + .enumerate() + .map(|(matrix, &bits)| { + (0..2 + matrix) + .map(|column| { + polynomial(cases + batch * 7 + matrix, bits, column) + }) + .collect() + }) + .collect() + }) + .collect(); + let (commits, data): (Vec<_>, Vec<_>) = logs + .iter() + .zip(&sources) + .map(|(matrices, sources)| { + let evaluations = matrices.iter().zip(sources).map(|(&bits, columns)| { + let domain = >::natural_domain_for_degree(&pcs, 1 << bits); + let mut values = Vec::new(); + for point in Val::two_adic_generator(bits).powers().take(1 << bits) { + values.extend(columns.iter().map(|p| p.iter().copied().horner::(point))); + } + (domain, RowMajorMatrix::new(values, columns.len())) + }); + >::commit(&pcs, evaluations) + }) + .unzip(); + let mut prefix = + Challenger::from_hasher(b"ix/fri-query-corpus/v1".to_vec(), Blake3); + prefix.observe_slice(&commits); + let zeta: ExtVal = prefix.sample_algebra_element(); + let mut points = vec![zeta]; + if layout_index % 2 == 1 { + points + .push(zeta + ExtVal::new([Val::from_u64(19), Val::from_u64(3)])); + } + let requests = data + .iter() + .zip(&logs) + .map(|(data, matrices)| { + (data, matrices.iter().map(|_| points.clone()).collect()) + }) + .collect(); + let (opened, proof) = pcs.open(requests, &mut prefix.clone()); + let claims: Vec<_> = commits.into_iter().zip(&logs).zip(&opened).map(|((commit, matrices), opened)| { + let matrices = matrices.iter().zip(opened).map(|(&bits, values)| { + let domain = >::natural_domain_for_degree(&pcs, 1 << bits); + (domain, points.iter().copied().zip(values.iter().cloned()).collect()) + }).collect(); + (commit, matrices) + }).collect(); + let ordinary = + pcs.verify(claims.clone(), &proof, &mut prefix.clone()); + assert!(ordinary.is_ok(), "ordinary PCS case {cases}: {ordinary:?}"); + // The PCS caller absorbs every claimed evaluation before it + // enters verify_fri. Preserve that exact prefix for the recorder. + for values in opened.iter().flatten().flatten() { + prefix.observe_algebra_slice(values); + } + let folding = RecordingFolding::default(); + let mut challenger = RecordingChallenger { + inner: prefix, + fields: vec![], + indices: vec![], + }; + verify_fri( + &folding, + ¶meters, + &proof, + &mut challenger, + &claims, + &mmcs, + ) + .unwrap(); + let rounds = proof.commit_phase_openings.len(); + assert_eq!(challenger.fields.len(), 2 * (rounds + 1)); + assert_eq!(challenger.indices.len(), queries); + let random: Vec<_> = challenger + .fields + .as_chunks::<2>() + .0 + .iter() + .map(|pair| ExtVal::new([pair[0], pair[1]])) + .collect(); + let calls = folding.0.into_inner(); + assert_eq!(calls.len(), queries * rounds); + for value in + [blowup, final_bits, max_arity, queries, layout_index, global_bits] + { + nat(&mut out, value); + } + nat(&mut out, logs.len()); + for (batch, (matrices, columns)) in + logs.iter().zip(&sources).enumerate() + { + nat(&mut out, matrices.len()); + for (matrix, (&bits, columns)) in + matrices.iter().zip(columns).enumerate() + { + nat(&mut out, bits); + nat(&mut out, columns.len()); + for polynomial in columns { + nat(&mut out, polynomial.len()); + for &coefficient in polynomial { + field(&mut out, coefficient); + } + } + for (&point, values) in points.iter().zip(&opened[batch][matrix]) + { + let expected: Vec<_> = columns + .iter() + .map(|p| p.iter().copied().map(ExtVal::from).horner(point)) + .collect(); + assert_eq!(*values, expected); + } + } + } + extensions(&mut out, &points); + for batch in &opened { + for matrix in batch { + for point in matrix { + extensions(&mut out, point); + } + } + } + for (batch, opened_batch) in proof.input_openings.iter().enumerate() { + for (query, &(width, index)) in + challenger.indices.iter().enumerate() + { + assert_eq!(width, global_bits); + for (matrix, row) in + opened_batch.opened_values[query].iter().enumerate() + { + let height = logs[batch][matrix] + blowup; + let point = Val::GENERATOR + * query_point(height, index >> (global_bits - height)); + let expected: Vec<_> = sources[batch][matrix] + .iter() + .map(|p| p.iter().copied().horner(point)) + .collect(); + assert_eq!(*row, expected); + nat(&mut out, row.len()); + for &value in row { + field(&mut out, value); + } + } + } + } + extensions(&mut out, &random); + for &(width, index) in &challenger.indices { + nat(&mut out, width); + nat(&mut out, index); + } + nat(&mut out, rounds); + for round in &proof.commit_phase_openings { + nat(&mut out, usize::from(round.log_arity)); + for siblings in &round.sibling_values { + extensions(&mut out, siblings); + } + } + extensions(&mut out, &proof.final_poly); + nat(&mut out, calls.len()); + for call in &calls { + for value in [call.index, call.height, call.log_arity] { + nat(&mut out, value); + } + extension(&mut out, call.challenge); + extensions(&mut out, &call.values); + extension(&mut out, call.result); + } + for (query, &(_, index)) in challenger.indices.iter().enumerate() { + let final_index = if rounds == 0 { + index + } else { + calls[(query + 1) * rounds - 1].index + }; + let value: ExtVal = proof + .final_poly + .iter() + .copied() + .horner(query_point(global_bits, final_index)); + nat(&mut out, final_index); + extension(&mut out, value); + } + cases += 1; + total_queries += queries; + total_rounds += rounds; + total_calls += calls.len(); + } + } + } + } + for value in [cases, total_queries, total_rounds, total_calls] { + nat(&mut out, value); + } + if let Ok(path) = std::env::var("IX_FRI_QUERY_SNAPSHOT") { + std::fs::write(path, out)?; + } + println!( + "Native FRI query chains: {cases} proofs, {total_queries} queries, {total_rounds} rounds, {total_calls} fold calls" + ); + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/interpolation.rs b/crates/aiur/src/synthesis/tests/interpolation.rs new file mode 100644 index 000000000..a1c315180 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/interpolation.rs @@ -0,0 +1,174 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Actual FRI row interpolation and both native matrix folding paths. + +use multi_stark::{ + p3_field::{ + BasedVectorSpace, Field, HornerIter, PrimeCharacteristicRing, PrimeField64, + TwoAdicField, + }, + p3_matrix::dense::RowMajorMatrix, + types::{ExtVal, Val}, +}; +use p3_fri::{FriFoldingStrategy, TwoAdicFriFolding}; +use p3_util::{reverse_bits_len, reverse_slice_index_bits}; +use std::{io, marker::PhantomData}; + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + let coordinates: &[Val] = value.as_basis_coefficients_slice(); + for &coordinate in coordinates { + field(out, coordinate); + } +} + +fn extensions(out: &mut Vec, values: &[ExtVal]) { + nat(out, values.len()); + for &value in values { + extension(out, value); + } +} + +fn sample(seed: usize) -> ExtVal { + ExtVal::new([Val::from_usize(seed * 67 + 3), Val::from_usize(seed * 13 + 1)]) +} + +fn coefficients(arity: usize, variant: usize) -> Vec { + match variant { + 0 => vec![], + 1 => vec![sample(1)], + 2 => (0..arity) + .map(|index| if index + 1 == arity { ExtVal::ONE } else { ExtVal::ZERO }) + .collect(), + _ => (0..arity).map(|index| sample(index + 17)).collect(), + } +} + +fn fold_row( + index: usize, + height: usize, + log_arity: usize, + point: ExtVal, + values: &[ExtVal], +) -> ExtVal { + as FriFoldingStrategy>::fold_row( + &TwoAdicFriFolding(PhantomData), + index, + height, + log_arity, + point, + values.iter().copied(), + ) +} + +#[test] +fn interpolation_snapshot() -> io::Result<()> { + let mut out = b"Aiur FRI interpolation v1\n".to_vec(); + let mut rows = 0; + let mut evaluations = 0; + for parent in 0..=32 { + for log_arity in 0..=parent.min(6) { + let height = parent - log_arity; + let arity = 1 << log_arity; + let mask = if height == 0 { + 0 + } else { + usize::MAX >> (usize::BITS as usize - height) + }; + let mut indices = vec![0, mask / 2, mask]; + indices.sort_unstable(); + indices.dedup(); + nat(&mut out, indices.len()); + for index in indices { + nat(&mut out, index); + let start = Val::two_adic_generator(parent) + .exp_u64(u64::try_from(reverse_bits_len(index, height)).unwrap()); + let mut nodes: Vec<_> = Val::two_adic_generator(log_arity) + .shifted_powers(start) + .take(arity) + .collect(); + reverse_slice_index_bits(&mut nodes); + let scale = (Val::from_usize(arity) + * nodes[0].exp_power_of_2(log_arity)) + .inverse(); + field(&mut out, scale); + for variant in 0..4 { + let polynomial = coefficients(arity, variant); + let values: Vec = nodes + .iter() + .map(|&node| polynomial.iter().copied().horner(ExtVal::from(node))) + .collect(); + extensions(&mut out, &polynomial); + extensions(&mut out, &values); + for point in [ + ExtVal::ZERO, + ExtVal::from(Val::from_u64(7)), + sample(41), + ExtVal::from(nodes[0]), + ExtVal::from(nodes[arity - 1]), + ] { + let result = fold_row(index, height, log_arity, point, &values); + assert_eq!(result, polynomial.iter().copied().horner(point)); + extension(&mut out, point); + extension(&mut out, result); + evaluations += 1; + } + rows += 1; + } + } + } + } + let mut matrices = 0; + let mut matrix_rows = 0; + for parent in 1..=9 { + // fold_matrix requires a positive arity logarithm in the accepted FRI + // profile; the row helper above also tests its singleton boundary. + for log_arity in 1..=parent.min(6) { + let arity = 1 << log_arity; + let height = parent - log_arity; + let data: Vec<_> = + (0..1 << parent).map(|index| sample(index + parent * 19)).collect(); + for point in [ExtVal::ZERO, sample(41), ExtVal::ONE] { + let folded = as FriFoldingStrategy< + Val, + ExtVal, + >>::fold_matrix( + &TwoAdicFriFolding(PhantomData), + point, + log_arity, + RowMajorMatrix::new(data.clone(), arity), + ); + assert_eq!(folded.len(), 1 << height); + for (index, row) in data.chunks_exact(arity).enumerate() { + assert_eq!( + folded[index], + fold_row(index, height, log_arity, point, row) + ); + matrix_rows += 1; + } + extension(&mut out, point); + extensions(&mut out, &data); + extensions(&mut out, &folded); + matrices += 1; + } + } + } + for count in [rows, evaluations, matrices, matrix_rows] { + nat(&mut out, count); + } + if let Ok(path) = std::env::var("IX_INTERPOLATION_SNAPSHOT") { + std::fs::write(path, out)?; + } + println!( + "FRI interpolation: {rows} rows, {evaluations} challenge evaluations, {matrices} matrices, {matrix_rows} matrix rows" + ); + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/lookup_budget.rs b/crates/aiur/src/synthesis/tests/lookup_budget.rs index a4fc44cb8..adb55e575 100644 --- a/crates/aiur/src/synthesis/tests/lookup_budget.rs +++ b/crates/aiur/src/synthesis/tests/lookup_budget.rs @@ -7,6 +7,77 @@ fn bound(slots: &[usize], active: &[bool], degrees: &[u8]) -> Option { lookup_query_bound(slots.iter().copied(), active, degrees) } +/// The corpus exercises every u8 exponent, machine/field boundaries, +/// active-position indexing and independently malformed sequence lengths. +#[cfg(target_pointer_width = "64")] +#[test] +fn lookup_budget_snapshot() -> std::io::Result<()> { + use multi_stark::p3_field::PrimeField64; + fn append(out: &mut Vec, value: Option) { + out.push(u8::from(value.is_some())); + out.extend(value.unwrap_or(0).to_le_bytes()); + } + let header = b"Aiur lookup budget v1\n"; + let mut out = header.to_vec(); + let p = usize::try_from(G::ORDER_U64).unwrap(); + let cases = [ + 0, + 1, + 2, + 3, + 4, + 255, + 65536, + 1 << 31, + 1 << 32, + (1 << 32) - 1, + p / 2 - 1, + p - 3, + p - 2, + p - 1, + p, + usize::MAX, + ]; + for slots in cases { + for degree in 0..=255 { + append(&mut out, bound(&[slots], &[true], &[degree])); + append( + &mut out, + bound( + &[usize::MAX, slots, usize::MAX], + &[false, true, false], + &[degree], + ), + ); + append(&mut out, bound(&[slots, 3], &[true, true], &[degree, 31])); + append(&mut out, bound(&[3, slots], &[true, true], &[31, degree])); + } + } + let slots = [2, 7, 0, 13]; + for slot_count in 0..=4 { + for active_count in 0..=4 { + for mask in 0..(1 << active_count) { + let active = (0..active_count) + .map(|bit| mask & (1 << bit) != 0) + .collect::>(); + for degree_count in 0..=5 { + for degree in [0, 1, 31, 63, 64, 255] { + append( + &mut out, + bound(&slots[..slot_count], &active, &vec![degree; degree_count]), + ); + } + } + } + } + } + assert_eq!(out.len(), header.len() + 21_964 * 9); + if let Some(path) = std::env::var_os("IX_LOOKUP_BUDGET_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} + #[test] fn query_budget_uses_canonical_slots_and_active_heights() { assert_eq!( diff --git a/crates/aiur/src/synthesis/tests/lookup_shapes.rs b/crates/aiur/src/synthesis/tests/lookup_shapes.rs index d3f7c6082..0901a2c0f 100644 --- a/crates/aiur/src/synthesis/tests/lookup_shapes.rs +++ b/crates/aiur/src/synthesis/tests/lookup_shapes.rs @@ -3,6 +3,169 @@ use super::*; +fn snapshot_body(tag: usize) -> Block { + fn ret(size: usize) -> Block { + Block { ops: vec![], ctrl: Ctrl::Return(0, vec![0; size]) } + } + fn yield_values(size: usize) -> Block { + Block { ops: vec![], ctrl: Ctrl::Yield(0, vec![0; size]) } + } + fn matched(arm: Option, fallback: Option) -> Block { + Block { + ops: vec![], + ctrl: Ctrl::Match( + 0, + arm.into_iter().map(|block| (G::ZERO, block)).collect(), + fallback.map(Box::new), + ), + } + } + fn continued(arm: Block, continuation: Block) -> Block { + Block { + ops: vec![], + ctrl: Ctrl::MatchContinue( + 0, + [(G::ZERO, arm)].into_iter().collect(), + Some(Box::new(yield_values(2))), + 2, + 0, + 0, + Box::new(continuation), + ), + } + } + match tag { + 0..=2 => ret(tag), + 3 => yield_values(0), + 4 => yield_values(1), + 5 => matched(Some(ret(1)), Some(ret(1))), + 6 => matched(Some(ret(0)), Some(ret(1))), + 7 => matched(Some(ret(1)), None), + 8 => matched(None, None), + 9 => continued(yield_values(2), ret(1)), + 10 => continued(ret(1), ret(1)), + 11 => continued(ret(0), ret(1)), + 12 => continued(yield_values(1), ret(1)), + 13 => continued(yield_values(2), yield_values(0)), + 14 => continued(continued(yield_values(2), yield_values(2)), ret(1)), + 15 => continued(continued(yield_values(2), yield_values(1)), ret(1)), + 16 => matched(Some(continued(ret(1), ret(1))), Some(ret(1))), + _ => unreachable!(), + } +} + +fn snapshot_function( + body: Block, + inputs: usize, + entry: bool, + constrained: bool, +) -> Function { + Function { + body, + layout: FunctionLayout { + input_size: inputs, + selectors: 1, + auxiliaries: 7, + lookups: 4, + }, + entry, + constrained, + } +} + +/// Compare the Rust guards with the total Lean validators across nested +/// control forms, all small arities, visibility and advice-call modes. +/// These fixtures test structural checks independently of layout/value +/// validation; they are never passed to the constraint emitter. +#[test] +fn lookup_shape_snapshot() -> std::io::Result<()> { + let header = b"Aiur lookup shapes v2\n"; + let mut out = header.to_vec(); + for tag in 0..17 { + for size in 0..4 { + out.push(u8::from(snapshot_body(tag).returns_have_size(size))); + } + } + for tag in 0..17 { + for callee_inputs in 0..4 { + for caller_inputs in 0..4 { + for outputs in 0..4 { + for advice in [false, true] { + for constrained in [false, true] { + let caller = snapshot_function( + Block { + ops: vec![Op::Call( + 1, + vec![0; caller_inputs], + outputs, + advice, + )], + ctrl: Ctrl::Return(0, vec![]), + }, + 3, + true, + true, + ); + let callee = snapshot_function( + snapshot_body(tag), + callee_inputs, + false, + constrained, + ); + let top = Toplevel { + functions: vec![caller, callee], + memory_sizes: vec![], + circuits: vec![], + call_components: vec![], + }; + out.push(u8::from(top.validate_lookup_shapes().is_ok())); + } + } + } + } + } + } + for tag in 0..17 { + for inputs in 0..4 { + for entry in [false, true] { + for constrained in [false, true] { + let top = Toplevel { + functions: vec![snapshot_function( + snapshot_body(tag), + inputs, + entry, + constrained, + )], + memory_sizes: vec![], + circuits: vec![], + call_components: vec![], + }; + // Cache construction includes the structural program guard. + let shapes = top.checked_claim_shapes(); + for channel in 0..3 { + for function in [0, 1, 99] { + for arguments in 0..7 { + let mut claim = vec![G::from_u8(channel), G::from_u8(function)]; + claim.extend(std::iter::repeat_n(G::ZERO, arguments)); + out.push(u8::from( + shapes + .as_ref() + .is_ok_and(|shapes| valid_claim_shape(shapes, &claim)), + )); + } + } + } + } + } + } + } + assert_eq!(out.len(), header.len() + 21_556); + if let Some(path) = std::env::var_os("IX_LOOKUP_SHAPE_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} + /// The public claim omits rank zero. A short return at rank seven must not /// be interpreted as a public return value of seven through zero padding. #[test] diff --git a/crates/aiur/src/synthesis/tests/memory.rs b/crates/aiur/src/synthesis/tests/memory.rs new file mode 100644 index 000000000..0cc61f6c6 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/memory.rs @@ -0,0 +1,112 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use multi_stark::eval::{VarValues, eval_expr}; + +fn values<'a>(row: &'a [G], next: &'a [G]) -> VarValues<'a, G> { + VarValues { + preprocessed: [&[], &[]], + main: [row, next], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ZERO, + is_last_row: G::ZERO, + is_transition: G::ONE, + } +} + +#[test] +fn memory_transitions_allow_wrap_but_reject_duplicate_pointers() { + for width in [1, 4, 8] { + let (memory, constraints, _) = Memory::build(width); + for first in [G::from_u8(7), -G::from_u8(2)] { + let rows: Vec<_> = (0..4) + .map(|index| { + let mut row = vec![G::ZERO; memory.width]; + row[0] = G::ONE; + row[1] = G::ONE; + row[2] = first + G::from_u64(index); + row[3..].fill(G::from_u64(index + 3)); + row + }) + .collect(); + for pair in rows.windows(2) { + assert!(constraints.iter().all(|constraint| eval_expr( + constraint, + &values(&pair[0], &pair[1]) + ) == G::ZERO)); + } + let mut duplicate = rows[1].clone(); + duplicate[2] = rows[0][2]; + assert_ne!( + eval_expr(&constraints[3], &values(&rows[0], &duplicate)), + G::ZERO, + "the pointer transition must reject consecutive duplicates" + ); + let mut inactive = rows[0].clone(); + inactive[0] = G::ZERO; + inactive[1] = G::ZERO; + assert_ne!( + eval_expr(&constraints[2], &values(&inactive, &rows[1])), + G::ZERO, + "an active successor requires an active predecessor" + ); + } + } +} + +/// The memory table is immutable witness data, with no first-pointer-zero +/// constraint or requirement for a preceding runtime store. Here pointers +/// start at p-1 and wrap to zero. The zero pointer must load the second row. +#[test] +fn supplied_wrapping_memory_load_verifies() { + let function = Function { + body: Block { ops: vec![Op::Load(1, 0)], ctrl: Ctrl::Return(0, vec![1]) }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 8, + lookups: 5, + }, + entry: true, + constrained: true, + }; + let (cp, fp) = test_parameters(); + let system = + AiurSystem::build(with_singleton_circuits(vec![function], vec![1]), cp, fp); + let expected = G::from_u8(8); + let claim = [function_channel(), G::ZERO, G::ZERO, expected]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(index, shape)| { + let height = if index < 2 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if index == 0 { + rows[1] = G::ONE; + rows[2] = G::ONE; + rows[9] = expected; + } else if index == 1 { + assert_eq!(shape.main_width, 4); + rows[..8].copy_from_slice(&[ + G::ZERO, + G::ONE, + -G::ONE, + G::from_u8(7), + G::ONE, + G::ONE, + G::ZERO, + expected, + ]); + } else if index == 3 { + rows[6] = G::from_u8(3); + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + system.verify(&claim, &proof).expect("wrapping immutable memory is allowed"); +} diff --git a/crates/aiur/src/synthesis/tests/merkle.rs b/crates/aiur/src/synthesis/tests/merkle.rs new file mode 100644 index 000000000..679a06531 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/merkle.rs @@ -0,0 +1,286 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Record the pinned native individual verifier's actual hash calls. +//! Commit/open use the production CPU MMCS; the recording hasher delegates +//! every call to the same native BLAKE3 implementation. + +use super::*; +use multi_stark::{ + p3_field::PrimeField64, + p3_matrix::{Dimensions, Matrix}, + types::Mmcs, +}; +use p3_blake3::Blake3; +use p3_commit::{BatchOpeningRef, Mmcs as _}; +use p3_merkle_tree::MerkleTreeMmcs; +use p3_symmetric::{ + CompressionFunctionFromHasher, CryptographicHasher, MerkleCap, + SerializingHasher, +}; +use std::sync::{Arc, Mutex}; + +pub(super) type Digest = [u8; 32]; +pub(super) type Calls = Arc, Digest)>>>; + +#[derive(Clone)] +pub(super) struct RecordingHash(pub(super) Calls); + +impl CryptographicHasher for RecordingHash { + fn hash_iter>(&self, input: I) -> Digest { + let bytes: Vec<_> = input.into_iter().collect(); + let digest = Blake3.hash_iter(bytes.iter().copied()); + self.0.lock().unwrap().push((bytes, digest)); + digest + } +} + +pub(super) type RecordingMmcs = MerkleTreeMmcs< + G, + u8, + SerializingHasher, + CompressionFunctionFromHasher, + 2, + 32, +>; + +#[derive(Clone)] +struct Case { + dimensions: Vec, + rows: Vec>, + proof: Vec, + cap: Vec, + cap_height: usize, + index: usize, +} + +pub(super) fn number(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +pub(super) fn digests(out: &mut Vec, values: &[Digest]) { + number(out, values.len()); + out.extend(values.iter().flatten()); +} + +#[derive(Default)] +struct Corpus { + body: Vec, + count: usize, + accepted: usize, + omitted: usize, + unhashed: usize, + calls: usize, +} + +impl Corpus { + fn record(&mut self, case: &Case, expected: Option) { + let native = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + case.cap_height, + ); + let cap = MerkleCap::new(case.cap.clone()); + let accepted = native + .verify_batch( + &cap, + &case.dimensions, + case.index, + BatchOpeningRef::new(&case.rows, &case.proof), + ) + .is_ok(); + if let Some(expected) = expected { + assert_eq!(accepted, expected); + } + let calls = Calls::default(); + let hash = RecordingHash(calls.clone()); + let recording = RecordingMmcs::new( + SerializingHasher::new(hash.clone()), + CompressionFunctionFromHasher::new(hash), + case.cap_height, + ); + let recorded = recording + .verify_batch( + &cap, + &case.dimensions, + case.index, + BatchOpeningRef::new(&case.rows, &case.proof), + ) + .is_ok(); + assert_eq!(accepted, recorded); + let calls = calls.lock().unwrap(); + let degrees: Vec = case + .dimensions + .iter() + .map(|dims| u8::try_from(dims.height.ilog2()).unwrap()) + .collect(); + let covered = trace_cap_coverage(0, case.cap_height, °rees); + self.count += 1; + self.accepted += usize::from(accepted); + self.omitted += usize::from(accepted && !covered); + self.unhashed += usize::from(calls.is_empty()); + self.calls += calls.len(); + let out = &mut self.body; + number(out, case.dimensions.len()); + for dims in &case.dimensions { + number(out, dims.width); + number(out, usize::try_from(dims.height.ilog2()).unwrap()); + } + number(out, case.cap_height); + number(out, case.index); + number(out, case.rows.len()); + for row in &case.rows { + number(out, row.len()); + for value in row { + out.extend(value.as_canonical_u64().to_le_bytes()); + } + } + digests(out, &case.proof); + digests(out, &case.cap); + out.extend([u8::from(accepted), u8::from(covered)]); + number(out, calls.len()); + for (input, digest) in calls.iter() { + number(out, input.len()); + out.extend(input); + out.extend(digest); + } + } +} + +#[test] +fn merkle_path_snapshot() -> std::io::Result<()> { + let shapes = [ + vec![0], + vec![1], + vec![2], + vec![3], + vec![4], + vec![7], + vec![3, 1], + vec![1, 3], + vec![3, 0, 2, 1], + vec![2, 2, 2], + vec![1, 4, 1, 4, 0], + vec![4, 2, 3, 2], + ]; + let widths = [1, 2, 3, 7, 8, 9, 16, 17, 31, 32, 33, 129]; + let mut corpus = Corpus::default(); + for (fixture, logs) in shapes.into_iter().enumerate() { + let max_log = *logs.iter().max().unwrap(); + let height = 1 << max_log; + let matrices: Vec<_> = logs + .iter() + .enumerate() + .map(|(matrix, log)| { + let width = widths[(fixture + matrix * 3) % widths.len()]; + let values = (0..width * (1 << log)) + .map(|i| { + let value = match i % 7 { + 0 => 0, + 1 => 1, + 2 => 0xffff_ffff_0000_0000, + 3 => 0xffff_ffff, + 4 => 0x1_0000_0000, + _ => u64::try_from(i * 65537 + matrix * 257 + fixture).unwrap(), + }; + G::from_u64(value) + }) + .collect(); + RowMajorMatrix::new(values, width) + }) + .collect(); + let dimensions: Vec<_> = matrices.iter().map(Matrix::dimensions).collect(); + let indices: Vec<_> = if height <= 16 { + (0..height).collect() + } else { + vec![0, 1, 2, height / 2 - 1, height / 2, height - 2, height - 1] + }; + for cap_height in 0..=max_log + 2 { + let mmcs = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + cap_height, + ); + let (cap, data) = mmcs.commit(matrices.clone()); + for &index in &indices { + let opening = mmcs.open_batch(index, &data); + let case = Case { + dimensions: dimensions.clone(), + rows: opening.opened_values, + proof: opening.opening_proof, + cap: cap.roots().to_vec(), + cap_height, + index, + }; + corpus.record(&case, Some(true)); + for (matrix, &log) in logs.iter().enumerate() { + let mut changed = case.clone(); + changed.rows[matrix][0] += G::ONE; + corpus.record(&changed, Some(log < cap_height.min(max_log))); + } + if !case.proof.is_empty() { + let mut changed = case.clone(); + changed.proof.pop(); + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.proof[0][index % 32] ^= 1; + corpus.record(&changed, Some(false)); + } + let mut changed = case.clone(); + changed.proof.push([0; 32]); + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.rows.pop(); + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.dimensions[0].width += 1; + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.index = height; + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.cap[index >> case.proof.len()][index % 32] ^= 1; + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.dimensions[0].height *= 2; + corpus.record(&changed, None); + let mut changed = case.clone(); + changed.dimensions[0].width = 0; + changed.rows[0].clear(); + corpus.record(&changed, None); + let mut changed = case.clone(); + changed.cap.truncate(1); + corpus.record(&changed, None); + let mut changed = case.clone(); + changed.dimensions.clear(); + changed.rows.clear(); + corpus.record(&changed, Some(false)); + } + } + } + assert!(corpus.accepted > 500 && corpus.omitted > 100); + assert!(corpus.unhashed > 1000 && corpus.calls > 10000); + let mut out = b"Aiur Merkle paths v1\n".to_vec(); + for count in [ + corpus.count, + corpus.accepted, + corpus.omitted, + corpus.unhashed, + corpus.calls, + ] { + number(&mut out, count); + } + out.extend(corpus.body); + println!( + "Merkle paths: {} cases, {} accepted, {} omitted, {} unhashed, {} calls", + corpus.count, + corpus.accepted, + corpus.omitted, + corpus.unhashed, + corpus.calls + ); + if let Some(path) = std::env::var_os("IX_MERKLE_PATH_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/mmcs.rs b/crates/aiur/src/synthesis/tests/mmcs.rs index e04dd1db3..8cfb961fd 100644 --- a/crates/aiur/src/synthesis/tests/mmcs.rs +++ b/crates/aiur/src/synthesis/tests/mmcs.rs @@ -88,8 +88,10 @@ fn public_verify_accepts_a_cap_at_the_shortest_trace_lde() { assert!(system.verify(&changed, &proof).is_err()); } +#[cfg(target_pointer_width = "64")] #[test] -fn cap_coverage_matches_injection_geometry_at_integer_boundaries() { +fn merkle_cap_snapshot() -> std::io::Result<()> { + let mut out = b"Aiur Merkle caps v1\n".to_vec(); let parameters = [ 0, 1, @@ -111,6 +113,7 @@ fn cap_coverage_matches_injection_geometry_at_integer_boundaries() { for blowup in parameters { for cap in parameters { assert!(trace_cap_coverage(blowup, cap, &[])); + out.push(u8::from(trace_cap_coverage(blowup, cap, &[]))); total += 1; for degree in 0..=255 { for degrees in [ @@ -132,10 +135,15 @@ fn cap_coverage_matches_injection_geometry_at_integer_boundaries() { expected, "blowup={blowup}, cap={cap}, degrees={degrees:?}" ); + out.push(u8::from(trace_cap_coverage(blowup, cap, °rees))); total += 1; } } } } assert_eq!(total, 288225); + if let Some(path) = std::env::var_os("IX_MERKLE_CAP_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) } diff --git a/crates/aiur/src/synthesis/tests/polynomial.rs b/crates/aiur/src/synthesis/tests/polynomial.rs new file mode 100644 index 000000000..8ab59a530 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/polynomial.rs @@ -0,0 +1,214 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Native final-polynomial Horner evaluation and upstream coefficient helpers. + +use multi_stark::{ + p3_field::{ + BasedVectorSpace, Field, HornerIter, PrimeCharacteristicRing, PrimeField64, + }, + types::{ExtVal, Val}, +}; +use p3_stir::utils::{ + add_polys, divide_by_linear, eval_poly, vanishing_poly_from_roots, +}; +use std::io; + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + let coordinates: &[Val] = value.as_basis_coefficients_slice(); + for &coordinate in coordinates { + field(out, coordinate); + } +} + +fn values( + out: &mut Vec, + values: &[F], + write: fn(&mut Vec, F), +) { + nat(out, values.len()); + for &value in values { + write(out, value); + } +} + +fn base_sample(seed: usize) -> Val { + if seed == 2 { Val::NEG_ONE } else { Val::from_usize(seed) } +} + +fn extension_sample(seed: usize) -> ExtVal { + if seed < 3 { + ExtVal::from(base_sample(seed)) + } else { + ExtVal::new([Val::from_usize(seed * 67), Val::from_usize(seed + 1)]) + } +} + +fn coefficients( + length: usize, + seed: usize, + sample: fn(usize) -> F, +) -> Vec { + (0..length) + .map(|index| match seed { + 0 => F::ZERO, + 1 => { + if index + 1 == length { + F::ONE + } else { + F::ZERO + } + }, + 2 if index >= length / 2 => F::ZERO, + _ => sample(seed * 67 + index * 13 + 3), + }) + .collect() +} + +fn cases( + out: &mut Vec, + sample: fn(usize) -> F, + write: fn(&mut Vec, F), +) -> [usize; 5] { + let domain: Vec<_> = (0..80).map(sample).collect(); + for (index, value) in domain.iter().enumerate() { + assert!(!domain[..index].contains(value)); + } + values(out, &domain, write); + let mut count = 0; + let mut divisions = 0; + let mut zero_cases = 0; + let mut root_sets = 0; + let mut repeated_sets = 0; + for length in [0, 1, 2, 3, 4, 7, 8, 9, 16, 31, 32, 65] { + for right_length in [0, 1, length, length + 3] { + for seed in 0..8 { + let left = coefficients(length, seed, sample); + let right = coefficients(right_length, seed, sample); + let root = sample(seed); + let point = if seed % 3 == 0 { root } else { sample(seed + 19) }; + values(out, &left, write); + values(out, &right, write); + write(out, root); + write(out, point); + let at_point: F = left.iter().copied().horner(point); + let at_root: F = left.iter().copied().horner(root); + let right_value: F = right.iter().copied().horner(point); + assert_eq!(at_point, eval_poly(&left, point)); + assert_eq!(at_root, eval_poly(&left, root)); + assert_eq!(right_value, eval_poly(&right, point)); + write(out, at_point); + write(out, at_root); + write(out, right_value); + let added = add_polys(&left, &right); + let difference = add_polys( + &left, + &right.iter().map(|&value| -value).collect::>(), + ); + values(out, &added, write); + values(out, &difference, write); + assert_eq!(eval_poly(&added, point), at_point + right_value); + assert_eq!(eval_poly(&difference, point), at_point - right_value); + if !left.is_empty() { + let (quotient, remainder) = divide_by_linear(&left, root); + assert_eq!(quotient.len(), left.len() - 1); + assert_eq!(remainder, at_root); + assert_eq!( + (point - root) * eval_poly("ient, point) + remainder, + at_point + ); + values(out, "ient, write); + write(out, remainder); + divisions += 1; + } + let roots = domain + .iter() + .filter(|&&value| eval_poly(&left, value).is_zero()) + .count(); + let agreements = domain + .iter() + .filter(|&&value| eval_poly(&difference, value).is_zero()) + .count(); + let zero = left.iter().all(|value| value.is_zero()); + if zero { + zero_cases += 1; + } else { + assert!(roots < left.len()); + } + if difference.iter().any(|value| !value.is_zero()) { + assert!(agreements < left.len().max(right.len())); + } + nat(out, roots); + nat(out, agreements); + count += 1; + } + } + } + for length in [0, 1, 2, 3, 7, 16, 31, 32, 63] { + for variant in 0..4 { + let roots: Vec<_> = (0..length) + .map(|index| { + sample(match variant { + 0 => index, + 1 => length - index - 1, + 2 => 0, + _ => index / 2, + }) + }) + .collect(); + let repeated = roots + .iter() + .enumerate() + .any(|(index, value)| roots[..index].contains(value)); + let polynomial = vanishing_poly_from_roots(&roots); + assert_eq!(polynomial.len(), roots.len() + 1); + assert_eq!(polynomial.last(), Some(&F::ONE)); + values(out, &roots, write); + values(out, &polynomial, write); + for point in [sample(0), sample(2), sample(17), sample(79)] { + assert_eq!( + eval_poly(&polynomial, point), + roots.iter().map(|&root| point - root).product() + ); + write(out, eval_poly(&polynomial, point)); + } + let count = domain + .iter() + .filter(|&&point| eval_poly(&polynomial, point).is_zero()) + .count(); + assert!(count <= roots.len()); + if !repeated { + assert_eq!(count, roots.len()); + } + nat(out, count); + root_sets += 1; + repeated_sets += usize::from(repeated); + } + } + [count, divisions, zero_cases, root_sets, repeated_sets] +} + +#[test] +fn polynomial_snapshot() -> io::Result<()> { + let mut out = b"Aiur coefficient polynomials v1\n".to_vec(); + let base = cases(&mut out, base_sample, field); + let extension = cases(&mut out, extension_sample, extension); + for count in base.into_iter().chain(extension) { + nat(&mut out, count); + } + if let Ok(path) = std::env::var("IX_POLYNOMIAL_SNAPSHOT") { + std::fs::write(path, out)?; + } + println!( + "Native polynomial arithmetic/divisions/zero cases/root sets/repeated sets: base {base:?}, extension {extension:?}" + ); + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/proof_codec.rs b/crates/aiur/src/synthesis/tests/proof_codec.rs new file mode 100644 index 000000000..16278d2d1 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/proof_codec.rs @@ -0,0 +1,258 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Compare the complete native proof object with the total Lean codec. +//! The semantic view deliberately differs from bincode's field order and +//! represents every scalar/digest byte as a u64 to expose framing mistakes. + +use super::*; +use multi_stark::{ + p3_field::{BasedVectorSpace, PrimeField64}, + types::ExtVal, +}; + +fn vector( + out: &mut Vec, + values: &[T], + item: impl Fn(&mut Vec, &T), +) { + out.push(u64::try_from(values.len()).unwrap()); + for value in values { + item(out, value); + } +} + +fn field(out: &mut Vec, value: &G) { + out.push(value.as_canonical_u64()); +} + +fn extension(out: &mut Vec, value: &ExtVal) { + let coordinates: &[G] = value.as_basis_coefficients_slice(); + out.push(coordinates[0].as_canonical_u64()); + out.push(coordinates[1].as_canonical_u64()); +} + +fn hashes(out: &mut Vec, values: &[[u8; 32]]) { + vector(out, values, |out, digest| { + out.extend(digest.iter().map(|byte| u64::from(*byte))); + }); +} + +fn openings( + out: &mut Vec, + values: &[Vec>], + item: impl Fn(&mut Vec, &T), +) { + vector(out, values, |out, matrix| { + vector(out, matrix, |out, row| vector(out, row, &item)); + }); +} + +fn view(proof: &AiurProof) -> Vec { + let mut out = Vec::new(); + vector(&mut out, &proof.log_degrees, |out, degree| { + out.push(u64::from(*degree)); + }); + vector(&mut out, &proof.active, |out, enabled| { + out.push(u64::from(*enabled)); + }); + openings(&mut out, &proof.stage_2_opened_values, extension); + openings(&mut out, &proof.stage_1_opened_values, extension); + out.push(u64::from(proof.preprocessed_opened_values.is_some())); + if let Some(values) = &proof.preprocessed_opened_values { + openings(&mut out, values, extension); + } + openings(&mut out, &proof.quotient_opened_values, extension); + vector(&mut out, &proof.intermediate_accumulators, extension); + hashes(&mut out, proof.commitments.quotient_chunks.roots()); + hashes(&mut out, proof.commitments.stage_2_trace.roots()); + hashes(&mut out, proof.commitments.stage_1_trace.roots()); + let fri = &proof.opening_proof; + field(&mut out, &fri.query_pow_witness); + vector(&mut out, &fri.final_poly, extension); + vector(&mut out, &fri.commit_phase_openings, |out, step| { + hashes(out, &step.opening_proof.sibling_hashes); + vector(out, &step.sibling_values, |out, row| vector(out, row, extension)); + out.push(u64::from(step.log_arity)); + }); + vector(&mut out, &fri.input_openings, |out, batch| { + hashes(out, &batch.opening_proof.sibling_hashes); + openings(out, &batch.opened_values, field); + }); + vector(&mut out, &fri.commit_pow_witnesses, field); + vector(&mut out, &fri.commit_phase_commits, |out, cap| { + hashes(out, cap.roots()); + }); + out +} + +fn bytes(out: &mut Vec, value: &[u8]) { + out.extend(u64::try_from(value.len()).unwrap().to_le_bytes()); + out.extend(value); +} + +fn write_case(out: &mut Vec, value: &[u8]) -> bool { + bytes(out, value); + let parsed = AiurProof::from_bytes(value); + out.push(u8::from(parsed.is_ok())); + if let Ok(proof) = parsed { + bytes(out, &proof.to_bytes().unwrap()); + let words = view(&proof); + out.extend(u64::try_from(words.len()).unwrap().to_le_bytes()); + out.extend(words.iter().flat_map(|word| word.to_le_bytes())); + true + } else { + false + } +} + +fn sparse(proof: &AiurProof) -> AiurProof { + let mut result = proof.clone(); + result.active = vec![true, false, true]; + result.log_degrees = vec![0, 8, 16, 255]; + result.intermediate_accumulators = vec![ + ExtVal::from_basis_coefficients_slice(&[G::ZERO, -G::ONE]).unwrap(), + ExtVal::from_basis_coefficients_slice(&[G::ONE, G::from_u64(1 << 32)]) + .unwrap(), + ]; + result.quotient_opened_values = vec![vec![], vec![vec![]]]; + result.preprocessed_opened_values = None; + result.stage_1_opened_values = vec![]; + result.stage_2_opened_values = + vec![vec![result.intermediate_accumulators.clone()]]; + let fri = &mut result.opening_proof; + fri.commit_phase_commits.truncate(1); + fri.commit_pow_witnesses = vec![G::ZERO, G::ONE, -G::ONE]; + fri.input_openings.truncate(1); + for batch in &mut fri.input_openings { + batch.opened_values = vec![vec![], vec![vec![G::ONE, -G::ONE]]]; + batch.opening_proof.sibling_hashes.truncate(3); + } + fri.commit_phase_openings.truncate(1); + for step in &mut fri.commit_phase_openings { + step.log_arity = 255; + step.sibling_values = + vec![vec![], result.intermediate_accumulators.clone()]; + step.opening_proof.sibling_hashes.truncate(2); + } + fri.final_poly = result.intermediate_accumulators.clone(); + fri.query_pow_witness = -G::ONE; + result +} + +#[test] +fn proof_codec_snapshot() -> std::io::Result<()> { + let mut cases = Vec::new(); + let mut keys = Vec::new(); + for seed in 0..4 { + let (mut cp, mut fp) = test_parameters(); + cp.cap_height = seed % 2 * 2; + fp.max_log_arity = seed % 2 + 1; + fp.num_queries = 8; + let top = match seed { + 0 => mul_toplevel(), + 1 => call_and_memory_toplevel(), + 2 => xor_splits_toplevel(), + _ => unconstrained_call_promotion_toplevel(), + }; + let input = if seed == 3 { + vec![G::from_u8(7)] + } else { + vec![G::from_u8(3), G::from_u8(5)] + }; + let system = AiurSystem::build(top, cp, fp); + let (claim, proof) = system.prove(0, &input, &mut empty_io_buffer()); + system.system.verify(&claim, &proof).unwrap(); + // Preserve the original wire corpus, including native-accepted caps + // whose shortest trace is now excluded by the Aiur coverage guard. + assert_eq!( + system.verify(&claim, &proof).is_ok(), + trace_cap_coverage(cp.log_blowup, cp.cap_height, &proof.log_degrees) + ); + keys.push(crate::vk_codec::to_bytes(&system.system, cp, fp)); + cases.push(proof.to_bytes().unwrap()); + let fixture = sparse(&proof); + let encoded = fixture.to_bytes().unwrap(); + cases.push(encoded.clone()); + let mut some_empty = fixture.clone(); + some_empty.preprocessed_opened_values = Some(vec![]); + cases.push(some_empty.to_bytes().unwrap()); + for suffix in [&[0][..], &[1, 2, 3][..]] { + let mut changed = encoded.clone(); + changed.extend(suffix); + assert!(AiurProof::from_bytes(&changed).is_ok()); + cases.push(changed); + } + // Truncate at every byte of the small, fully populated fixture. Native + // serde must fail even inside extension coordinates and digest arrays. + for length in 0..encoded.len() { + let changed = encoded[..length].to_vec(); + assert!(AiurProof::from_bytes(&changed).is_err()); + cases.push(changed); + } + // The first active boolean and the first extension coordinate have + // independently known offsets from the native object's lengths. + for tag in [2, 127, 255] { + let mut changed = encoded.clone(); + changed[8] = tag; + assert!(AiurProof::from_bytes(&changed).is_err()); + cases.push(changed); + } + let first_accumulator = 8 + + fixture.active.len() + + 3 * 8 + + 32 + * (fixture.commitments.stage_1_trace.num_roots() + + fixture.commitments.stage_2_trace.num_roots() + + fixture.commitments.quotient_chunks.num_roots()) + + 8; + for offset in [first_accumulator, first_accumulator + 8] { + for noncanonical in [G::ORDER_U64, u64::MAX] { + let mut changed = encoded.clone(); + changed[offset..offset + 8] + .copy_from_slice(&noncanonical.to_le_bytes()); + assert!(AiurProof::from_bytes(&changed).is_err()); + cases.push(changed); + } + } + } + let mut out = b"Aiur proof codec v1\n".to_vec(); + out.extend(u64::try_from(keys.len()).unwrap().to_le_bytes()); + for key in &keys { + bytes(&mut out, key); + } + out.extend(u64::try_from(cases.len()).unwrap().to_le_bytes()); + let mut accepted = 0; + for case in &cases { + accepted += usize::from(write_case(&mut out, case)); + } + assert_eq!(accepted, 20); + assert_eq!(cases.len(), 3636); + if let Some(path) = std::env::var_os("IX_PROOF_CODEC_SNAPSHOT") { + std::fs::write(path, out)?; + } + eprintln!( + "proof codec: 4 verified native proofs, {} byte cases, {accepted} decodable", + cases.len() + ); + Ok(()) +} + +#[test] +fn malformed_proof_caps_reject_without_panicking() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(mul_toplevel(), cp, fp); + let (claim, proof) = + system.prove(0, &[G::ONE, G::ONE], &mut empty_io_buffer()); + let mut bytes = proof.to_bytes().unwrap(); + let offset = 8 + proof.active.len(); + let roots = proof.commitments.stage_1_trace.num_roots(); + bytes[offset..offset + 8].copy_from_slice(&0_u64.to_le_bytes()); + bytes.drain(offset + 8..offset + 8 + roots * 32); + let malformed = AiurProof::from_bytes(&bytes).unwrap(); + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + system.verify(&claim, &malformed) + })); + assert!(result.is_ok(), "deserialized proof cap caused verifier panic"); + assert!(result.unwrap().is_err()); +} diff --git a/crates/aiur/src/synthesis/tests/proof_shapes.rs b/crates/aiur/src/synthesis/tests/proof_shapes.rs new file mode 100644 index 000000000..2e3878164 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/proof_shapes.rs @@ -0,0 +1,206 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Complete native shape checks with independent activation, domain and +//! matrix dimension mutations. The PCS data is removed because shape +//! acceptance alone makes no polynomial authentication assertion. + +use super::*; +use multi_stark::types::ExtVal; + +fn bytes(out: &mut Vec, value: &[u8]) { + out.extend(u64::try_from(value.len()).unwrap().to_le_bytes()); + out.extend(value); +} + +fn modified( + proof: &AiurProof, + change: impl FnOnce(&mut AiurProof), +) -> AiurProof { + let mut result = proof.clone(); + change(&mut result); + result +} + +fn remove_active(system: &AiurSystem, proof: &mut AiurProof, ci: usize) { + let position = proof.active[..ci].iter().filter(|&&active| active).count(); + assert!(proof.active[ci]); + proof.active[ci] = false; + proof.log_degrees.remove(position); + let _ = proof.intermediate_accumulators.remove(position); + proof.stage_1_opened_values.remove(position); + proof.stage_2_opened_values.remove(position); + proof.quotient_opened_values.remove(position); + if let Some(slot) = system.system.preprocessed_indices[ci] { + proof.preprocessed_opened_values.as_mut().unwrap()[slot].clear(); + } +} + +fn variants(system: &AiurSystem, proof: &AiurProof) -> Vec { + let mut cases = vec![proof.clone()]; + cases.extend([ + modified(proof, |p| p.active.clear()), + modified(proof, |p| p.active.push(false)), + modified(proof, |p| { + p.active.pop(); + }), + modified(proof, |p| p.active.fill(false)), + modified(proof, |p| p.log_degrees.clear()), + modified(proof, |p| p.log_degrees.push(0)), + modified(proof, |p| { + p.log_degrees.pop(); + }), + modified(proof, |p| p.intermediate_accumulators.clear()), + modified(proof, |p| p.intermediate_accumulators.push(ExtVal::ZERO)), + modified(proof, |p| { + p.intermediate_accumulators.pop(); + }), + modified(proof, |p| p.intermediate_accumulators.fill(ExtVal::ONE)), + modified(proof, |p| p.preprocessed_opened_values = None), + modified(proof, |p| p.preprocessed_opened_values = Some(vec![])), + modified(proof, |p| { + p.preprocessed_opened_values.as_mut().unwrap().push(vec![]) + }), + modified(proof, |p| { + p.preprocessed_opened_values.as_mut().unwrap().pop(); + }), + ]); + for ci in 0..proof.active.len() { + cases.push(modified(proof, |p| p.active[ci] = !p.active[ci])); + if proof.active[ci] { + let inactive = modified(proof, |p| remove_active(system, p, ci)); + system.system.verify_shape(&inactive).unwrap(); + cases.push(inactive); + } + } + for position in 0..proof.log_degrees.len() { + for degree in 0..=255 { + cases.push(modified(proof, |p| p.log_degrees[position] = degree)); + } + } + // Independently remove/append outer matrices, opening points and columns + // in each of the four rounds, including every quotient slice coordinate. + for round in 0..4 { + let select: fn(&mut AiurProof) -> &mut Vec>> = match round { + 0 => |p| &mut p.stage_1_opened_values, + 1 => |p| &mut p.stage_2_opened_values, + 2 => |p| &mut p.quotient_opened_values, + _ => |p| p.preprocessed_opened_values.as_mut().unwrap(), + }; + cases.push(modified(proof, |p| select(p).clear())); + cases.push(modified(proof, |p| select(p).push(vec![]))); + cases.push(modified(proof, |p| { + select(p).pop(); + })); + let values = match round { + 0 => &proof.stage_1_opened_values, + 1 => &proof.stage_2_opened_values, + 2 => &proof.quotient_opened_values, + _ => proof.preprocessed_opened_values.as_ref().unwrap(), + }; + for (matrix, points) in values.iter().enumerate() { + cases.push(modified(proof, |p| select(p)[matrix].clear())); + cases.push(modified(proof, |p| select(p)[matrix].push(vec![]))); + cases.push(modified(proof, |p| { + select(p)[matrix].pop(); + })); + for point in 0..points.len() { + cases.push(modified(proof, |p| select(p)[matrix][point].clear())); + cases.push(modified(proof, |p| { + select(p)[matrix][point].push(ExtVal::ZERO) + })); + cases.push(modified(proof, |p| { + select(p)[matrix][point].pop(); + })); + } + } + } + cases +} + +#[test] +fn proof_shape_snapshot() -> std::io::Result<()> { + let mut out = b"Aiur proof shapes v2\n".to_vec(); + out.extend(4_u64.to_le_bytes()); + let mut total = 0; + let mut accepted = 0; + for seed in 0..4 { + let (mut cp, mut fp) = test_parameters(); + cp.log_blowup = 1 + seed % 2; + cp.cap_height = seed % 2 * 2; + fp.max_log_arity = seed % 2 + 1; + fp.num_queries = 8; + let top = match seed { + 0 => mul_toplevel(), + 1 => call_and_memory_toplevel(), + 2 => xor_splits_toplevel(), + _ => unconstrained_call_promotion_toplevel(), + }; + let input = if seed == 3 { + vec![G::from_u8(7)] + } else { + vec![G::from_u8(3), G::from_u8(5)] + }; + let system = AiurSystem::build(top, cp, fp); + let (claim, mut proof) = system.prove(0, &input, &mut empty_io_buffer()); + system.verify(&claim, &proof).unwrap(); + proof.opening_proof.commit_phase_commits.clear(); + proof.opening_proof.commit_pow_witnesses.clear(); + proof.opening_proof.input_openings.clear(); + proof.opening_proof.commit_phase_openings.clear(); + proof.opening_proof.final_poly.clear(); + proof.opening_proof.query_pow_witness = G::ZERO; + bytes(&mut out, &crate::vk_codec::to_bytes(&system.system, cp, fp)); + let cases = variants(&system, &proof); + let accepted_before = accepted; + total += cases.len(); + out.extend(u64::try_from(cases.len()).unwrap().to_le_bytes()); + for case in cases { + bytes(&mut out, &case.to_bytes().unwrap()); + let result = system.system.verify_shape(&case); + out.push(u8::from(result.is_ok())); + if let Ok(degrees) = result { + accepted += 1; + out.extend(u64::try_from(degrees.len()).unwrap().to_le_bytes()); + for degree in degrees { + out.extend(u64::try_from(degree).unwrap().to_le_bytes()); + } + } + out.push(u8::from(fixed_trace_heights( + system.system.circuits.iter().map(|c| c.preprocessed_height), + &case.active, + &case.log_degrees, + ))); + let budget = lookup_query_bound( + system.slot_widths.iter().map(Vec::len), + &case.active, + &case.log_degrees, + ); + out.push(u8::from(budget.is_some())); + if let Some(bound) = budget { + out.extend(bound.to_le_bytes()); + } + out.push(u8::from(trace_cap_coverage( + cp.log_blowup, + cp.cap_height, + &case.log_degrees, + ))); + } + // Retuning the Bytes1 circuit reduces its quotient degree from two to + // one. Its domain mutations therefore admit one additional exponent + // in each system, independently of the fixed-height acceptance guard. + let bytes1 = &system.system.circuits[system.system.circuits.len() - 2]; + assert_eq!(bytes1.preprocessed_height, 256); + assert_eq!(bytes1.quotient_degree(), 1); + assert_eq!( + accepted - accepted_before, + if seed % 2 == 0 { 99 } else { 158 } + ); + } + if let Some(path) = std::env::var_os("IX_PROOF_SHAPE_SNAPSHOT") { + std::fs::write(path, out)?; + } + assert_eq!((total, accepted), (4696, 514)); + eprintln!("proof shapes: {total} native cases, {accepted} accepted shapes"); + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/pruned_merkle.rs b/crates/aiur/src/synthesis/tests/pruned_merkle.rs new file mode 100644 index 000000000..caccd6f32 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/pruned_merkle.rs @@ -0,0 +1,278 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Actual shared MMCS decisions and hash calls, including late failures. + +use super::merkle::{ + Calls, Digest, RecordingHash, RecordingMmcs, digests, number, +}; +use super::*; +use multi_stark::{ + p3_field::PrimeField64, + p3_matrix::{Dimensions, Matrix}, + types::Mmcs, +}; +use p3_blake3::Blake3; +use p3_commit::Mmcs as _; +use p3_merkle_tree::PrunedMerklePaths; +use p3_symmetric::{ + CompressionFunctionFromHasher, MerkleCap, SerializingHasher, +}; + +#[derive(Clone)] +struct Case { + dimensions: Vec, + indices: Vec, + rows: Vec>>, + proof: Vec, + cap: Vec, + cap_height: usize, +} + +#[derive(Default)] +struct Corpus { + body: Vec, + count: usize, + accepted: usize, + omitted: usize, + unhashed: usize, + late: usize, + calls: usize, +} + +impl Corpus { + fn record(&mut self, case: &Case, expected: Option) -> usize { + let native = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + case.cap_height, + ); + let cap = MerkleCap::new(case.cap.clone()); + let proof = PrunedMerklePaths { sibling_hashes: case.proof.clone() }; + let accepted = native + .verify_multi_batch( + &cap, + &case.dimensions, + &case.indices, + &case.rows, + &proof, + ) + .is_ok(); + if let Some(expected) = expected { + assert_eq!(accepted, expected); + } + let calls = Calls::default(); + let hash = RecordingHash(calls.clone()); + let recording = RecordingMmcs::new( + SerializingHasher::new(hash.clone()), + CompressionFunctionFromHasher::new(hash), + case.cap_height, + ); + let recorded = recording + .verify_multi_batch( + &cap, + &case.dimensions, + &case.indices, + &case.rows, + &proof, + ) + .is_ok(); + assert_eq!(accepted, recorded); + let calls = calls.lock().unwrap(); + let degrees: Vec = case + .dimensions + .iter() + .map(|dims| u8::try_from(dims.height.ilog2()).unwrap()) + .collect(); + let covered = trace_cap_coverage(0, case.cap_height, °rees); + self.count += 1; + self.accepted += usize::from(accepted); + self.omitted += usize::from(accepted && !covered); + self.unhashed += usize::from(calls.is_empty()); + self.late += usize::from(!accepted && !calls.is_empty()); + self.calls += calls.len(); + let out = &mut self.body; + number(out, case.dimensions.len()); + for dims in &case.dimensions { + number(out, dims.width); + number(out, usize::try_from(dims.height.ilog2()).unwrap()); + } + number(out, case.cap_height); + number(out, case.indices.len()); + for &index in &case.indices { + number(out, index); + } + number(out, case.rows.len()); + for query in &case.rows { + number(out, query.len()); + for row in query { + number(out, row.len()); + for value in row { + out.extend(value.as_canonical_u64().to_le_bytes()); + } + } + } + digests(out, &case.proof); + digests(out, &case.cap); + out.extend([u8::from(accepted), u8::from(covered)]); + number(out, calls.len()); + for (input, digest) in calls.iter() { + number(out, input.len()); + out.extend(input); + out.extend(digest); + } + calls.len() + } +} + +#[test] +fn pruned_merkle_snapshot() -> std::io::Result<()> { + let shapes = [ + vec![0], + vec![1], + vec![3], + vec![5], + vec![3, 1], + vec![1, 3], + vec![3, 0, 2, 1], + vec![2, 2, 2], + vec![1, 4, 1, 4, 0], + vec![4, 2, 3, 2], + ]; + let widths = [1, 2, 3, 17, 33, 129]; + let mut corpus = Corpus::default(); + for (fixture, logs) in shapes.into_iter().enumerate() { + let max_log = *logs.iter().max().unwrap(); + let height = 1 << max_log; + let matrices: Vec<_> = logs + .iter() + .enumerate() + .map(|(matrix, log)| { + let width = widths[(fixture + matrix * 3) % widths.len()]; + let values = (0..width * (1 << log)) + .map(|i| { + if i % 5 == 0 { + -G::ONE + } else { + G::from_u64( + u64::try_from(i * 65537 + matrix * 257 + fixture).unwrap(), + ) + } + }) + .collect(); + RowMajorMatrix::new(values, width) + }) + .collect(); + let dimensions: Vec<_> = matrices.iter().map(Matrix::dimensions).collect(); + let queries = [ + vec![], + vec![0], + vec![height - 1], + (0..height).collect(), + (0..height).rev().collect(), + (0..height).step_by(2).collect(), + (1..height).step_by(2).collect(), + vec![height - 1, 0, height / 2, height - 1, 0], + vec![0, 0, 0], + vec![0, (2 % height)], + ]; + for cap_height in 0..=max_log + 2 { + let mmcs = Mmcs::new( + SerializingHasher::new(Blake3), + CompressionFunctionFromHasher::new(Blake3), + cap_height, + ); + let (cap, data) = mmcs.commit(matrices.clone()); + for indices in &queries { + let (rows, proof) = mmcs.open_multi_batch(indices, &data); + let case = Case { + dimensions: dimensions.clone(), + indices: indices.clone(), + rows, + proof: proof.sibling_hashes, + cap: cap.roots().to_vec(), + cap_height, + }; + corpus.record(&case, Some(true)); + let mut changed = case.clone(); + changed.proof.push([0; 32]); + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.rows.push(vec![]); + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.dimensions.clear(); + corpus.record(&changed, Some(false)); + if case.indices.is_empty() { + continue; + } + for (matrix, &log) in logs.iter().enumerate() { + let omitted = log < cap_height.min(max_log); + let mut changed = case.clone(); + for query in &mut changed.rows { + query[matrix][0] += G::ONE; + } + corpus.record(&changed, Some(omitted)); + let mut changed = case.clone(); + changed.rows[0][matrix][0] += G::ONE; + corpus.record(&changed, if omitted { None } else { Some(false) }); + } + if !case.proof.is_empty() { + let mut changed = case.clone(); + changed.proof.pop(); + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.proof[0][fixture % 32] ^= 1; + corpus.record(&changed, Some(false)); + } + let mut changed = case.clone(); + changed.dimensions[0].width += 1; + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.indices[0] = height; + corpus.record(&changed, Some(false)); + let mut changed = case.clone(); + changed.cap[0][fixture % 32] ^= 1; + corpus.record(&changed, None); + let mut changed = case.clone(); + changed.cap.truncate(1); + corpus.record(&changed, None); + let mut changed = case.clone(); + changed.rows[0].pop(); + corpus.record(&changed, Some(false)); + if logs == [3, 1] && cap_height == 0 && indices == &[0, 2] { + let mut changed = case.clone(); + changed.rows[1][1][0] += G::ONE; + assert_eq!(corpus.record(&changed, Some(false)), 5); + } + } + } + } + assert!(corpus.accepted > 100 && corpus.omitted > 100); + assert!(corpus.unhashed > 1000 && corpus.late > 1000); + let mut out = b"Aiur pruned Merkle v1\n".to_vec(); + for count in [ + corpus.count, + corpus.accepted, + corpus.omitted, + corpus.unhashed, + corpus.late, + corpus.calls, + ] { + number(&mut out, count); + } + out.extend(corpus.body); + println!( + "Pruned Merkle: {} cases, {} accepted, {} omitted, {} unhashed, {} late, {} calls", + corpus.count, + corpus.accepted, + corpus.omitted, + corpus.unhashed, + corpus.late, + corpus.calls + ); + if let Some(path) = std::env::var_os("IX_PRUNED_MERKLE_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} diff --git a/crates/aiur/src/synthesis/tests/scalar.rs b/crates/aiur/src/synthesis/tests/scalar.rs new file mode 100644 index 000000000..09be7db57 --- /dev/null +++ b/crates/aiur/src/synthesis/tests/scalar.rs @@ -0,0 +1,125 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use multi_stark::eval::{VarValues, eval_expr}; +use multi_stark::p3_field::Field; + +fn eq_zero_program() -> Toplevel { + with_singleton_circuits( + vec![Function { + body: Block { ops: vec![Op::EqZero(0)], ctrl: Ctrl::Return(0, vec![1]) }, + layout: FunctionLayout { + input_size: 1, + selectors: 1, + auxiliaries: 9, + lookups: 4, + }, + entry: true, + constrained: true, + }], + vec![], + ) +} + +/// Check the actual emitted expressions over inactive, active and malformed +/// selectors. Inactive rows may carry arbitrary equality-test advice. +#[test] +fn scalar_constraints_extract_boolean_and_eq_zero_semantics() { + let top = eq_zero_program(); + let (function, _) = top.build_constraints(0); + let (_, memory, _) = Memory::build(1); + let inputs = [G::ZERO, G::from_u8(3), -G::ONE]; + let selectors = [G::ZERO, G::ONE, G::from_u8(2), -G::ONE]; + let outputs = [G::ZERO, G::ONE, G::from_u8(2)]; + for input in inputs { + for selector in selectors { + for output in outputs { + for inverse in + [G::ZERO, G::from_u8(4), input.try_inverse().unwrap_or_default()] + { + let mut row = vec![G::ZERO; function.width]; + row[0] = input; + row[1] = selector; + row[9] = inverse; + row[10] = output; + let values = VarValues { + preprocessed: [&[], &[]], + main: [&row, &row], + stage2: [&[], &[]], + publics: &[], + is_first_row: G::ZERO, + is_last_row: G::ONE, + is_transition: G::ZERO, + }; + let satisfied = + function.zeros.iter().all(|e| eval_expr(e, &values) == G::ZERO); + let expected = selector == G::ZERO + || (selector == G::ONE + && output == G::from_bool(input == G::ZERO) + && (input == G::ZERO || Some(inverse) == input.try_inverse())); + assert_eq!( + satisfied, expected, + "input {input}, selector {selector}, output {output}, inverse {inverse}" + ); + // Same selector column in memory. Multiplicity remains zero and + // this last row has no active transition constraints. + let memory_row = [G::ZERO, selector, G::from_u8(7), G::from_u8(8)]; + let memory_values = + VarValues { main: [&memory_row, &memory_row], ..values }; + assert_eq!( + memory.iter().all(|e| eval_expr(e, &memory_values) == G::ZERO), + selector == G::ZERO || selector == G::ONE, + "memory selector {selector}" + ); + } + } + } + } +} + +/// Supply rows independently of the executor, with balanced public/function +/// and rank-byte messages. Forged outputs must fail the native verifier. +#[test] +fn supplied_eq_zero_outputs_are_constrained() { + let (cp, fp) = test_parameters(); + let system = AiurSystem::build(eq_zero_program(), cp, fp); + let three = G::from_u8(3); + let inverse = three.inverse(); + let cases = [ + (G::ZERO, G::from_u8(4), G::ONE, true), + (three, inverse, G::ZERO, true), + (G::ZERO, G::from_u8(4), G::ZERO, false), + (three, G::ZERO, G::ONE, false), + (three, -inverse, G::from_u8(2), false), + ]; + for (input, advice, output, accepted) in cases { + let claim = [function_channel(), G::ZERO, input, output]; + let traces = system + .circuit_shapes() + .iter() + .enumerate() + .map(|(index, shape)| { + let height = if index == 0 { 4 } else { shape.preprocessed_height }; + let mut rows = vec![G::ZERO; height * shape.main_width]; + if index == 0 { + rows[0] = input; + rows[1] = G::ONE; + rows[2] = G::ONE; + rows[9] = advice; + rows[10] = output; + } else if index == 2 { + rows[6] = G::from_u8(3); + } + RowMajorMatrix::new(rows, shape.main_width) + }) + .collect(); + let witness = SystemWitness::from_stage_1(traces, &system.system); + let proof = system.system.prove(&system.key, &claim, witness); + assert_eq!( + system.verify(&claim, &proof).is_ok(), + accepted, + "input {input}, inverse advice {advice}, output {output}" + ); + } +} diff --git a/crates/aiur/src/synthesis/tests/transcript.rs b/crates/aiur/src/synthesis/tests/transcript.rs new file mode 100644 index 000000000..91c1bb82c --- /dev/null +++ b/crates/aiur/src/synthesis/tests/transcript.rs @@ -0,0 +1,379 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Record the actual generic native verifier's transcript, including its +//! PCS continuation. The wrapper delegates every operation to the pinned +//! challenger. Separate mock-hash cases force rejection sampling boundaries. + +use super::*; +use multi_stark::{ + config::StarkGenericConfig, + p3_field::PrimeField64, + types::{Challenger, ExtVal, Pcs}, +}; +use p3_blake3::Blake3; +use p3_challenger::{ + CanObserve, CanSample, CanSampleBits, FieldChallenger, GrindingChallenger, + HashChallenger, SerializingChallenger64, +}; +use p3_symmetric::{CryptographicHasher, MerkleCap}; +use std::sync::{Arc, Mutex}; + +#[derive(Clone, Debug)] +enum Event { + Observe(Vec), + Field(G), + Bits(usize, usize), +} + +type Events = Arc>>; +type Dft = ::Dft; +type Commitment = MerkleCap; + +#[derive(Clone)] +struct RecordingChallenger { + inner: Challenger, + events: Events, +} + +impl CanObserve for RecordingChallenger { + fn observe(&mut self, value: G) { + self.inner.observe(value); + self + .events + .lock() + .unwrap() + .push(Event::Observe(value.as_canonical_u64().to_le_bytes().to_vec())); + } +} + +impl CanObserve for RecordingChallenger { + fn observe(&mut self, value: Commitment) { + self.inner.observe(value.clone()); + self + .events + .lock() + .unwrap() + .push(Event::Observe(value.roots().iter().flatten().copied().collect())); + } +} + +impl CanSample for RecordingChallenger { + fn sample(&mut self) -> G { + let value = self.inner.sample(); + self.events.lock().unwrap().push(Event::Field(value)); + value + } +} + +impl CanSample for RecordingChallenger { + fn sample(&mut self) -> ExtVal { + self.sample_algebra_element() + } +} + +impl CanSampleBits for RecordingChallenger { + fn sample_bits(&mut self, bits: usize) -> usize { + let value = self.inner.sample_bits(bits); + self.events.lock().unwrap().push(Event::Bits(bits, value)); + value + } +} + +impl FieldChallenger for RecordingChallenger {} + +impl GrindingChallenger for RecordingChallenger { + type Witness = G; + + fn grind(&mut self, bits: usize) -> G { + self.inner.grind(bits) + } + // The trait's check_witness calls our observed-field and sampled-bit + // methods, and consumes nothing at zero bits, just like the native type. +} + +struct RecordingConfig { + inner: AiurConfig, + events: Events, +} + +impl StarkGenericConfig for RecordingConfig { + type Pcs = Pcs; + type Dft = Dft; + type Challenge = ExtVal; + type Challenger = RecordingChallenger; + + fn pcs(&self) -> &Pcs { + self.inner.pcs() + } + fn dft(&self) -> &Dft { + self.inner.dft() + } + fn initialise_challenger(&self) -> RecordingChallenger { + RecordingChallenger { + inner: self.inner.initialise_challenger(), + events: self.events.clone(), + } + } + fn max_log_degree(&self) -> usize { + self.inner.max_log_degree() + } + fn max_quotient_degree(&self) -> usize { + self.inner.max_quotient_degree() + } + fn log_blowup(&self) -> usize { + self.inner.log_blowup() + } +} + +fn number(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn bytes(out: &mut Vec, value: &[u8]) { + number(out, value.len()); + out.extend(value); +} + +fn field(out: &mut Vec, value: G) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn event(out: &mut Vec, event: &Event) { + match event { + Event::Observe(value) => { + out.push(0); + bytes(out, value); + }, + Event::Field(value) => { + out.push(1); + field(out, *value); + }, + Event::Bits(bits, value) => { + out.push(2); + number(out, *bits); + number(out, *value); + }, + } +} + +fn record( + out: &mut Vec, + system: &AiurSystem, + proof: &AiurProof, + claims: &[Vec], + expected: bool, +) { + let cp = system.commitment_parameters; + let fp = system.fri_parameters; + let events = Events::default(); + let key_bytes = crate::vk_codec::to_bytes(&system.system, cp, fp); + let (decoded, _, _) = crate::vk_codec::from_bytes(&key_bytes).unwrap(); + let instrumented = System { + config: RecordingConfig { + inner: AiurConfig::new(cp, fp), + events: events.clone(), + }, + circuits: decoded.circuits, + preprocessed_commit: decoded.preprocessed_commit, + preprocessed_indices: decoded.preprocessed_indices, + }; + let proof_bytes = proof.to_bytes().unwrap(); + let copied = Proof::::from_bytes(&proof_bytes).unwrap(); + let claim_slices: Vec<&[G]> = claims.iter().map(Vec::as_slice).collect(); + let accepted = instrumented.verify_multiple_claims(&claim_slices, &copied); + assert_eq!(accepted.is_ok(), expected); + // Compare with the original concrete native configuration as well. + assert_eq!( + system.system.verify_multiple_claims(&claim_slices, proof).is_ok(), + expected + ); + let events = events.lock().unwrap(); + assert!(events.iter().filter(|e| matches!(e, Event::Field(_))).count() >= 8); + bytes(out, &key_bytes); + bytes(out, &proof_bytes); + number(out, claims.len()); + for claim in claims { + number(out, claim.len()); + for value in claim { + field(out, *value); + } + } + out.push(u8::from(expected)); + number(out, events.len()); + for value in events.iter() { + event(out, value); + } +} + +#[derive(Clone)] +struct ScriptHasher { + first: [u8; 32], + later: [u8; 32], +} + +impl CryptographicHasher for ScriptHasher { + fn hash_iter>(&self, input: I) -> [u8; 32] { + if input.into_iter().count() == 1 { self.first } else { self.later } + } +} + +#[derive(Clone)] +struct CountedBytes { + inner: C, + consumed: Arc>, +} + +impl> CanSample for CountedBytes { + fn sample(&mut self) -> u8 { + *self.consumed.lock().unwrap() += 1; + self.inner.sample() + } +} + +impl> CanObserve for CountedBytes { + fn observe(&mut self, value: u8) { + self.inner.observe(value); + } +} + +fn digest(words: [u64; 4]) -> [u8; 32] { + let mut value: Vec = + words.iter().flat_map(|word| word.to_le_bytes()).collect(); + value.reverse(); + value.try_into().unwrap() +} + +fn rejections(out: &mut Vec) { + number(out, 16); + for mask in 0..16 { + let first = digest(std::array::from_fn(|i| { + if mask & (1 << i) == 0 { + [G::ORDER_U64, G::ORDER_U64 + 1, u64::MAX, G::ORDER_U64 + 3][i] + } else { + [0, G::ORDER_U64 - 1, 1 << 32, u64::MAX - (1 << 32)][i] + } + })); + let later = digest([11, 12, 13, 14]); + let consumed = Arc::new(Mutex::new(0)); + let inner = HashChallenger::new(vec![mask], ScriptHasher { first, later }); + let mut native = SerializingChallenger64::::new(CountedBytes { + inner, + consumed: consumed.clone(), + }); + let c0: G = native.sample(); + let first_attempts = *consumed.lock().unwrap() / 8; + let c1: G = native.sample(); + let second_attempts = *consumed.lock().unwrap() / 8 - first_attempts; + assert!((1..=5).contains(&first_attempts)); + assert!((1..=4).contains(&second_attempts)); + out.push(mask); + out.extend(first); + out.extend(later); + field(out, c0); + field(out, c1); + number(out, first_attempts); + number(out, second_attempts); + // Raw bit samples also verify where both rejection loops left the stream. + for bits in [0, 1, 7, 31, 32, 63] { + number(out, native.sample_bits(bits)); + } + } +} + +fn byte_streams(out: &mut Vec) { + number(out, 16); + for seed in 0..16usize { + let initial: Vec = + (0..seed * 17).map(|i| u8::try_from(i * 73 % 256).unwrap()).collect(); + bytes(out, &initial); + let mut native = HashChallenger::new(initial, Blake3); + number(out, 80); + for step in 0..80 { + if step % 7 == 0 { + let values: Vec = (0..(step + seed) % 5) + .map(|i| u8::try_from((i + step * 31) % 256).unwrap()) + .collect(); + native.observe_slice(&values); + event(out, &Event::Observe(values)); + } else { + let value: u8 = native.sample(); + out.push(3); + out.push(value); + } + } + } +} + +fn witnesses(out: &mut Vec) { + number(out, 48); + for seed in 0..8 { + for bits in [0, 1, 2, 3, 7, 12] { + let initial = vec![seed, 93, bits]; + bytes(out, &initial); + let mut native = Challenger::from_hasher(initial, Blake3); + // Populate pending output first to distinguish an empty observation + // from an output reset, including the zero-bit witness branch. + field(out, native.sample()); + number(out, usize::from(bits)); + let witness = G::from_u8(seed) - G::ONE; + field(out, witness); + out.push(u8::from(native.check_witness(usize::from(bits), witness))); + field(out, native.sample()); + } + } +} + +#[test] +fn transcript_snapshot() -> std::io::Result<()> { + let mut out = b"Aiur transcript v1\n".to_vec(); + byte_streams(&mut out); + rejections(&mut out); + witnesses(&mut out); + number(&mut out, 40); + for seed in 0..4 { + let (mut cp, mut fp) = test_parameters(); + cp.cap_height = seed % 2 * 2; + fp.max_log_arity = seed % 2 + 1; + fp.num_queries = 8; + fp.commit_proof_of_work_bits = if seed == 2 { 3 } else { 0 }; + fp.query_proof_of_work_bits = if seed == 2 { 3 } else { 0 }; + let top = match seed { + 0 => mul_toplevel(), + 1 => call_and_memory_toplevel(), + 2 => xor_splits_toplevel(), + _ => unconstrained_call_promotion_toplevel(), + }; + let input = if seed == 3 { + vec![G::from_u8(7)] + } else { + vec![G::from_u8(3), G::from_u8(5)] + }; + let system = AiurSystem::build(top, cp, fp); + let (claim, proof) = system.prove(0, &input, &mut empty_io_buffer()); + for variant in 0..10 { + let mut proof = proof.clone(); + let mut claims = vec![claim.clone()]; + match variant { + 0 => {}, + 1 => claims[0][0] += G::ONE, + 2 => claims = vec![claim[..1].to_vec(), claim[1..].to_vec()], + 3 => claims.clear(), + 4 => claims = vec![vec![], vec![]], + 5 => claims[0].push(G::ZERO), + 6 => claims.insert(0, vec![]), + 7 => { + proof.commitments.stage_1_trace = + proof.commitments.stage_2_trace.clone() + }, + 8 => proof.stage_1_opened_values[0][0][0] += ExtVal::ONE, + _ => proof.log_degrees[0] += 1, + } + record(&mut out, &system, &proof, &claims, variant == 0); + } + } + if let Some(path) = std::env::var_os("IX_TRANSCRIPT_SNAPSHOT") { + std::fs::write(path, out)?; + } + Ok(()) +} diff --git a/crates/aiur/src/vk_codec.rs b/crates/aiur/src/vk_codec.rs index 9fa9e00ec..f70657734 100644 --- a/crates/aiur/src/vk_codec.rs +++ b/crates/aiur/src/vk_codec.rs @@ -28,12 +28,11 @@ //! log_final_poly_len, max_log_arity, num_queries, //! commit_proof_of_work_bits, query_proof_of_work_bits) //! u16 circuit count -//! PER-CIRCUIT RECORDS (circuit count times; each is `u32 LE len` + `len` bytes -//! so a record is a contiguous byte range) +//! PER-CIRCUIT RECORDS (circuit count times, without a length prefix) //! u16 main_width, u16 preprocessed_width, u32 preprocessed_height, //! u16 max_constraint_degree (combined user + logUp), //! u8 lookup_group_size (k: lookups per chained accumulator step) -//! node_count nodes, each a u8 tag then payload: +//! u16 node_count, then node_count nodes, each a u8 tag then payload: //! 0 ConstSmall: u16 LE canonical value //! 1 ConstBig: u64 LE canonical value //! 2 Public: u8 index @@ -42,8 +41,8 @@ //! 9 Neg: u16 LE child node id //! 10..=15 Var (tag = 10 + 2*source + offset; source 0 Preprocessed //! 1 Main 2 Stage2, offset 0 current 1 next): u16 LE column -//! u32 zero_count, then zero_count x u16 LE constraint-root node ids -//! u32 lookup_count, then per lookup: +//! u16 zero_count, then zero_count x u16 LE constraint-root node ids +//! u16 lookup_count, then per lookup: //! u16 LE multiplicity node id //! u16 LE arg count, then arg_count x u16 LE arg node ids //! TRAILER @@ -70,11 +69,40 @@ use multi_stark::{ types::{Commitment, CommitmentParameters, FriParameters, Val}, }; +use crate::graph_shape::{GraphWidths, checked_graph_prefix}; use crate::synthesis::{AiurConfig, AiurSystem}; /// Sentinel for `None` in the preprocessed-index trailer. const NO_PREP_INDEX: u16 = u16::MAX; +#[cfg(test)] +#[path = "vk_codec/tests/graphs.rs"] +mod graph_tests; + +#[cfg(test)] +#[path = "vk_codec/tests/compilation.rs"] +mod compilation_tests; + +#[cfg(test)] +#[path = "vk_codec/tests/codec.rs"] +mod codec_tests; + +#[cfg(test)] +#[path = "vk_codec/tests/extension_arithmetic.rs"] +mod extension_arithmetic_tests; + +#[cfg(test)] +#[path = "vk_codec/tests/logup.rs"] +mod logup_tests; + +#[cfg(test)] +#[path = "vk_codec/tests/domain.rs"] +mod domain_tests; + +#[cfg(test)] +#[path = "vk_codec/tests/verifier_arithmetic.rs"] +mod verifier_arithmetic_tests; + // ════════════════════════════════════════════════════════════════════════════ // Encoder — System -> bytes // ════════════════════════════════════════════════════════════════════════════ @@ -321,7 +349,7 @@ fn decode_node(seg: &mut Seg<'_>) -> Result, String> { /// Recompute per-node degree multiples in node order (children precede parents /// in the compiled vector). -fn recompute_degrees(nodes: &[Node]) -> Vec { +fn recompute_degrees(nodes: &[Node]) -> Result, String> { let mut degrees: Vec = Vec::with_capacity(nodes.len()); for node in nodes { let d = match *node { @@ -330,12 +358,37 @@ fn recompute_degrees(nodes: &[Node]) -> Vec { Node::Add(a, b) | Node::Sub(a, b) => { degrees[a.0 as usize].max(degrees[b.0 as usize]) }, - Node::Mul(a, b) => degrees[a.0 as usize] + degrees[b.0 as usize], + Node::Mul(a, b) => degrees[a.0 as usize] + .checked_add(degrees[b.0 as usize]) + .ok_or("node degree overflow")?, Node::Neg(a) => degrees[a.0 as usize], }; degrees.push(d); } - degrees + Ok(degrees) +} + +/// Use u64 for the at-most-eight-term degree sums so malformed graphs cannot +/// overflow the native u32 analytic logUp calculation before rejection. +fn checked_max_degree( + graph: &ConstraintGraph, + group_size: usize, +) -> Result { + let degree = |id: NodeId| u64::from(graph.degrees[id.index()]); + let mut maximum = u64::from(graph.max_constraint_degree).max(1); + for group in graph.lookups.chunks(group_size) { + let messages: Vec<_> = group + .iter() + .map(|lookup| lookup.args.iter().copied().map(degree).max().unwrap_or(0)) + .collect(); + let sum: u64 = messages.iter().sum(); + maximum = maximum.max(sum + 1); + for (lookup, message_degree) in group.iter().zip(messages) { + maximum = maximum.max(degree(lookup.multiplicity) + sum - message_degree); + } + } + usize::try_from(maximum) + .map_err(|error| format!("constraint degree overflow: {error}")) } fn decode_circuit(seg: &mut Seg<'_>) -> Result, String> { @@ -369,7 +422,30 @@ fn decode_circuit(seg: &mut Seg<'_>) -> Result, String> { lookups.push(Lookup { multiplicity, args }); } - let degrees = recompute_degrees(&nodes); + let num_lookups = lookups.len(); + let ext_degree = + >::DIMENSION; + let stage_2_width = multi_stark::lookup::stage2_width( + num_lookups, + lookup_group_size, + ext_degree, + ); + let num_publics = multi_stark::lookup::num_publics(ext_degree); + let lookup_prefix_len = checked_graph_prefix( + &nodes, + &zeros, + &lookups, + GraphWidths { + preprocessed: preprocessed_width, + main: main_width, + stage2: stage_2_width, + publics: num_publics, + }, + ) + .ok_or("invalid graph indices or lookup prefix")?; + let degrees = recompute_degrees(&nodes)?; // The graph's own max degree covers only the user roots (the serialized // `max_constraint_degree` is the combined user + analytic-logUp value). let user_max_degree = zeros @@ -377,15 +453,6 @@ fn decode_circuit(seg: &mut Seg<'_>) -> Result, String> { .map(|z| degrees[usize::try_from(z.0).expect("node id")]) .max() .unwrap_or(0); - // The lookup prefix is exactly the nodes interned while compiling the - // lookup expressions, all of which are reachable from (and bounded by) - // the lookup roots — children always precede parents. - let lookup_prefix_len = lookups - .iter() - .flat_map(|l| std::iter::once(l.multiplicity).chain(l.args.iter().copied())) - .map(|id| id.0 as usize + 1) - .max() - .unwrap_or(0); let graph = ConstraintGraph { nodes, degrees, @@ -394,11 +461,9 @@ fn decode_circuit(seg: &mut Seg<'_>) -> Result, String> { lookup_prefix_len, max_constraint_degree: user_max_degree, }; - let num_lookups = graph.lookups.len(); - let ext_degree = - >::DIMENSION; + if checked_max_degree(&graph, lookup_group_size)? != max_constraint_degree { + return Err("incorrect maximum constraint degree".into()); + } Ok(Circuit { graph, main_width, @@ -406,12 +471,8 @@ fn decode_circuit(seg: &mut Seg<'_>) -> Result, String> { preprocessed_width, preprocessed_height, num_lookups, - stage_2_width: multi_stark::lookup::stage2_width( - num_lookups, - lookup_group_size, - ext_degree, - ), - num_publics: multi_stark::lookup::num_publics(ext_degree), + stage_2_width, + num_publics, lookup_group_size, constraint_count: zeros_plus_logup( zero_count, @@ -462,6 +523,9 @@ pub(crate) fn from_bytes( 0 => None, 1 => { let n = r.u16()? as usize; + if !n.is_power_of_two() { + return Err("preprocessed cap size must be a power of two".into()); + } let mut caps = Vec::with_capacity(n.min(1 << 16)); for _ in 0..n { let mut d = [0u8; 32]; @@ -571,8 +635,7 @@ mod tests { assert!(from_bytes(&bytes).is_err(), "should reject trailing data"); } - /// A tampered per-circuit record length must be rejected (the record reader - /// enforces exact consumption). + /// Truncation and trailing bytes must be rejected for the unframed stream. #[test] fn rejects_bad_record_length() { let (system, cp, fp) = test_system(); @@ -588,4 +651,119 @@ mod tests { padded.push(0); assert!(from_bytes(&padded).is_err(), "should reject padded vk"); } + + #[test] + fn rejects_forward_node_reference_without_panicking() { + let mut bytes = Vec::new(); + for width in [1, 0] { + push_u16(&mut bytes, width); + } + push_u32(&mut bytes, 0); + push_u16(&mut bytes, 2); + bytes.push(1); + push_u16(&mut bytes, 1); + push_node(&mut bytes, &Node::Neg(NodeId(0))); + push_u16(&mut bytes, 0); + push_u16(&mut bytes, 0); + let decoded = std::panic::catch_unwind(|| { + decode_circuit(&mut Seg { buf: &bytes, pos: 0 }) + }); + assert!(decoded.is_ok(), "malformed graph must return an error"); + assert!(decoded.unwrap().is_err(), "self-reference must be rejected"); + } + + fn circuit_bytes( + nodes: &[Node], + zeros: &[NodeId], + lookups: &[Lookup], + maximum: usize, + ) -> Vec { + let mut bytes = Vec::new(); + push_u16(&mut bytes, 1); + push_u16(&mut bytes, 1); + push_u32(&mut bytes, 256); + push_u16(&mut bytes, maximum); + bytes.push(1); + push_u16(&mut bytes, nodes.len()); + for node in nodes { + push_node(&mut bytes, node); + } + push_u16(&mut bytes, zeros.len()); + for &root in zeros { + push_node_id(&mut bytes, root); + } + push_u16(&mut bytes, lookups.len()); + for lookup in lookups { + push_node_id(&mut bytes, lookup.multiplicity); + push_u16(&mut bytes, lookup.args.len()); + for &arg in &lookup.args { + push_node_id(&mut bytes, arg); + } + } + bytes + } + + fn assert_bad_graph(bytes: &[u8]) { + let decoded = std::panic::catch_unwind(|| { + decode_circuit(&mut Seg { buf: bytes, pos: 0 }) + }); + assert!(decoded.is_ok(), "invalid graph must not panic"); + assert!(decoded.unwrap().is_err(), "invalid graph must be rejected"); + } + + #[test] + fn rejects_malformed_graph_reads() { + let leaf = Node::Const(Val::ONE); + for node in [ + Node::Add(NodeId(0), NodeId(1)), + Node::Sub(NodeId(1), NodeId(0)), + Node::Mul(NodeId(0), NodeId(u16::MAX.into())), + Node::Neg(NodeId(2)), + ] { + assert_bad_graph(&circuit_bytes(&[leaf, node], &[], &[], 1)); + } + assert_bad_graph(&circuit_bytes(&[leaf], &[NodeId(1)], &[], 1)); + for lookup in [ + Lookup { multiplicity: NodeId(1), args: vec![] }, + Lookup { multiplicity: NodeId(0), args: vec![NodeId(1)] }, + ] { + assert_bad_graph(&circuit_bytes(&[leaf], &[], &[lookup], 1)); + } + for source in [Source::Preprocessed, Source::Main, Source::Stage2] { + for offset in [RowOffset::Current, RowOffset::Next] { + let index = if source == Source::Stage2 { 2 } else { 1 }; + let node = Node::Var(ColRef { source, offset, index }); + assert_bad_graph(&circuit_bytes(&[node], &[], &[], 1)); + } + } + assert_bad_graph(&circuit_bytes(&[Node::Public(8)], &[], &[], 1)); + let stage2 = Node::Var(ColRef { + source: Source::Stage2, + offset: RowOffset::Current, + index: 0, + }); + // Even an unreachable stage-2 node in the dense prefix is read by its sweep. + let lookup = Lookup { multiplicity: NodeId(1), args: vec![] }; + assert_bad_graph(&circuit_bytes(&[stage2, leaf], &[], &[lookup], 1)); + let bytes = circuit_bytes(&[stage2], &[NodeId(0)], &[], 1); + assert!(decode_circuit(&mut Seg { buf: &bytes, pos: 0 }).is_ok()); + } + + #[test] + fn rejects_overflowing_and_incorrect_graph_degrees() { + let mut nodes = vec![Node::IsFirstRow]; + for i in 0..32 { + nodes.push(Node::Mul(NodeId(i), NodeId(i))); + } + assert_bad_graph(&circuit_bytes(&nodes, &[], &[], 1)); + // Each node fits u32, but the product's analytic logUp degree exceeds it. + nodes.pop(); + let lookup = Lookup { multiplicity: NodeId(31), args: vec![NodeId(31)] }; + let mut bytes = circuit_bytes(&nodes, &[], &[lookup.clone(), lookup], 1); + bytes[10] = 2; + assert_bad_graph(&bytes); + for maximum in [0, 2, u16::MAX.into()] { + assert_bad_graph(&circuit_bytes(&[Node::IsFirstRow], &[], &[], maximum)); + } + } } diff --git a/crates/aiur/src/vk_codec/tests/codec.rs b/crates/aiur/src/vk_codec/tests/codec.rs new file mode 100644 index 000000000..ee9baa323 --- /dev/null +++ b/crates/aiur/src/vk_codec/tests/codec.rs @@ -0,0 +1,297 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Transport actual full keys and adversarial v5 bytes to the total Lean codec. + +use super::*; +use multi_stark::system::CircuitInputs; +use std::{fs, io}; + +fn parameters() -> (CommitmentParameters, FriParameters) { + ( + CommitmentParameters { log_blowup: 1, cap_height: 0 }, + FriParameters { + log_final_poly_len: 0, + max_log_arity: 1, + num_queries: 64, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + }, + ) +} + +fn record( + nodes: Vec>, + zeros: Vec, + lookups: Vec>, + group: usize, + maximum: usize, +) -> Vec { + let circuit = Circuit { + graph: ConstraintGraph { + nodes, + zeros, + lookups, + degrees: vec![], + lookup_prefix_len: 0, + max_constraint_degree: 0, + }, + main_width: 1, + preprocessed: None, + preprocessed_width: 1, + preprocessed_height: 256, + lookup_group_size: group, + max_constraint_degree: maximum, + num_lookups: 0, + stage_2_width: 0, + num_publics: 8, + constraint_count: 0, + }; + let mut bytes = vec![]; + encode_circuit(&mut bytes, &circuit); + bytes +} + +fn key(records: &[Vec], commitment: Option<&[u8]>) -> Vec { + let mut bytes = vec![]; + for parameter in [1, 0, 0, 1, 64, 0, 0] { + push_u16(&mut bytes, parameter); + } + push_u16(&mut bytes, records.len()); + for record in records { + bytes.extend_from_slice(record); + } + match commitment { + None => bytes.push(0), + Some(digests) => { + assert_eq!(digests.len() % 32, 0); + bytes.push(1); + push_u16(&mut bytes, digests.len() / 32); + bytes.extend_from_slice(digests); + }, + } + for index in 0..records.len() { + push_u16(&mut bytes, if commitment.is_some() { index } else { 65535 }); + } + bytes +} + +fn every_tag_record() -> Vec { + let mut nodes = vec![ + Node::Const(Val::ZERO), + Node::Const(Val::ONE), + Node::Const(Val::from_u64(65535)), + Node::Const(Val::from_u64(65536)), + Node::Const(-Val::ONE), + Node::Public(7), + Node::IsFirstRow, + Node::IsLastRow, + Node::IsTransition, + Node::Add(NodeId(1), NodeId(6)), + Node::Sub(NodeId(9), NodeId(2)), + Node::Mul(NodeId(9), NodeId(10)), + Node::Neg(NodeId(11)), + ]; + for source in [Source::Preprocessed, Source::Main, Source::Stage2] { + for offset in [RowOffset::Current, RowOffset::Next] { + nodes.push(Node::Var(ColRef { source, offset, index: 0 })); + } + } + record( + nodes, + vec![NodeId(12), NodeId(17), NodeId(18)], + vec![Lookup { multiplicity: NodeId(1), args: vec![NodeId(9)] }], + 1, + 2, + ) +} + +fn cases() -> Vec> { + let (cp, fp) = parameters(); + let actual = graph_tests::graph_system(); + let mut cases = vec![to_bytes(&actual, cp, fp)]; + for inputs in [vec![], vec![CircuitInputs::default()]] { + let system = System::new(AiurConfig::new(cp, fp), inputs).0; + cases.push(to_bytes(&system, cp, fp)); + } + let every_tag = every_tag_record(); + let mut small = vec![ + key(&[], None), + key(&[], Some(&[])), + key(std::slice::from_ref(&every_tag), None), + key(std::slice::from_ref(&every_tag), Some(&[7; 32])), + key(&[every_tag.clone(), every_tag.clone()], Some(&[19; 64])), + ]; + // Constants that the decoder reduces or accepts in a nonminimal tag. + for value in [0, 1, 65535, 65536, Val::ORDER_U64, u64::MAX] { + let mut record = record(vec![Node::Const(Val::ONE)], vec![], vec![], 1, 1); + record.splice(13..16, std::iter::once(1).chain(value.to_le_bytes())); + small.push(key(&[record], None)); + } + cases.extend(small.iter().cloned()); + for bytes in &small { + // Every truncation and every trailing-byte value, including zeros. + cases.extend((0..bytes.len()).map(|end| bytes[..end].to_vec())); + for suffix in 0..=255 { + let mut extended = bytes.clone(); + extended.push(suffix); + cases.push(extended); + } + } + let mutations = key(&[every_tag], Some(&[7; 32])); + for offset in 14..mutations.len() { + for value in [0, 1, 15, 16, 255] { + let mut bytes = mutations.clone(); + bytes[offset] = value; + cases.push(bytes); + } + } + let leaf = Node::Const(Val::ONE); + for group in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255] { + for count in [0, 1, 2, 3, 7, 8, 9, 16, 17] { + let lookups = + vec![Lookup { multiplicity: NodeId(0), args: vec![] }; count]; + cases.push(key(&[record(vec![leaf], vec![], lookups, group, 1)], None)); + } + } + for node in [ + Node::Add(NodeId(0), NodeId(1)), + Node::Sub(NodeId(1), NodeId(0)), + Node::Mul(NodeId(0), NodeId(65535)), + Node::Neg(NodeId(1)), + Node::Public(8), + Node::Public(255), + ] { + cases.push(key(&[record(vec![leaf, node], vec![], vec![], 1, 1)], None)); + } + for source in [Source::Preprocessed, Source::Main, Source::Stage2] { + for offset in [RowOffset::Current, RowOffset::Next] { + for index in [0, 1, 2, 65535] { + let var = Node::Var(ColRef { source, offset, index }); + for lookups in + [vec![], vec![Lookup { multiplicity: NodeId(1), args: vec![] }]] + { + cases + .push(key(&[record(vec![var, leaf], vec![], lookups, 1, 1)], None)); + } + } + } + } + for invalid in [1, 65535] { + cases.push(key( + &[record(vec![leaf], vec![NodeId(invalid)], vec![], 1, 1)], + None, + )); + for lookup in [ + Lookup { multiplicity: NodeId(invalid), args: vec![] }, + Lookup { multiplicity: NodeId(0), args: vec![NodeId(invalid)] }, + ] { + cases.push(key(&[record(vec![leaf], vec![], vec![lookup], 1, 1)], None)); + } + } + for maximum in [0, 1, 2, 65535] { + cases.push(key( + &[record(vec![Node::IsFirstRow], vec![], vec![], 1, maximum)], + None, + )); + } + let mut nodes = vec![Node::IsFirstRow]; + for index in 0..32 { + nodes.push(Node::Mul(NodeId(index), NodeId(index))); + } + cases.push(key(&[record(nodes.clone(), vec![], vec![], 1, 1)], None)); + nodes.pop(); + for group in 1..=8 { + let lookup = Lookup { multiplicity: NodeId(31), args: vec![NodeId(31)] }; + cases.push(key( + &[record(nodes.clone(), vec![], vec![lookup; group], group, 1)], + None, + )); + } + // The largest serialized degree is valid, even though this decoder does + // not check the chosen PCS's quotient budget (System::new does). + nodes.truncate(16); + let mut root = 15; + for power in (0..15).rev() { + nodes.push(Node::Mul(NodeId(root), NodeId(power))); + root += 1; + } + let mut maximum = record(nodes, vec![NodeId(root)], vec![], 8, 65535); + maximum[0..4].copy_from_slice(&[255; 4]); + maximum[4..8].copy_from_slice(&[255; 4]); + cases.push(key(&[maximum], Some(&[255; 32]))); + cases +} + +fn write_nat(out: &mut Vec, value: usize) { + out.extend_from_slice(&(value as u64).to_le_bytes()); +} + +fn write_bytes(out: &mut Vec, bytes: &[u8]) { + write_nat(out, bytes.len()); + out.extend_from_slice(bytes); +} + +#[test] +fn rejects_invalid_commitment_cap_sizes_without_panicking() { + for count in [0, 3, 5, 7] { + let bytes = key(&[], Some(&vec![0; count * 32])); + let decoded = std::panic::catch_unwind(|| from_bytes(&bytes)); + assert!(decoded.is_ok(), "invalid cap size must return an error"); + assert!(decoded.unwrap().is_err(), "invalid cap size must be rejected"); + } +} + +#[test] +fn key_codec_snapshot() -> io::Result<()> { + let cases = cases(); + let mut out = b"Aiur key codec v1\n".to_vec(); + write_nat(&mut out, cases.len()); + let mut accepted = 0; + let mut noncanonical = 0; + let mut circuits = 0; + for bytes in &cases { + write_bytes(&mut out, bytes); + match from_bytes(bytes) { + Err(_) => out.push(0), + Ok((system, cp, fp)) => { + out.push(1); + accepted += 1; + let canonical = to_bytes(&system, cp, fp); + noncanonical += usize::from(canonical != *bytes); + write_bytes(&mut out, &canonical); + write_nat(&mut out, system.circuits.len()); + for circuit in system.circuits { + circuits += 1; + for value in [ + circuit.main_width, + circuit.preprocessed_width, + circuit.preprocessed_height, + circuit.max_constraint_degree, + circuit.lookup_group_size, + circuit.stage_2_width, + circuit.num_publics, + circuit.constraint_count, + circuit.graph.lookup_prefix_len, + circuit.graph.max_constraint_degree as usize, + ] { + write_nat(&mut out, value); + } + write_nat(&mut out, circuit.graph.degrees.len()); + for degree in circuit.graph.degrees { + write_nat(&mut out, degree as usize); + } + } + }, + } + } + assert!(accepted > 100 && noncanonical >= 5 && circuits > 100); + if let Ok(path) = std::env::var("IX_KEY_CODEC_SNAPSHOT") { + fs::write(path, out)?; + } + println!( + "key codec: {} cases, {accepted} accepted, {noncanonical} noncanonical, {circuits} circuits", + cases.len(), + ); + Ok(()) +} diff --git a/crates/aiur/src/vk_codec/tests/compilation.rs b/crates/aiur/src/vk_codec/tests/compilation.rs new file mode 100644 index 000000000..5cfeb8121 --- /dev/null +++ b/crates/aiur/src/vk_codec/tests/compilation.rs @@ -0,0 +1,490 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Export complete native base graphs and rejected source specifications. + +use super::*; +use multi_stark::{ + eval::{VarValues, eval_expr}, + expr::Expr, + p3_matrix::dense::RowMajorMatrix, + system::CircuitInputs, +}; +use std::{fs, io, panic::catch_unwind}; + +#[derive(Clone)] +struct Spec { + constraints: Vec>, + lookups: Vec>>, +} + +impl Spec { + fn inputs(&self) -> CircuitInputs { + CircuitInputs { + main_width: 4, + preprocessed: Some(RowMajorMatrix::new(vec![Val::ZERO; 8], 4)), + constraints: self.constraints.clone(), + lookups: self.lookups.clone(), + ..CircuitInputs::default() + } + } + + fn widths(&self) -> [usize; 4] { + [4, 4, self.lookups.len().max(1) * 2, 8] + } +} + +fn binary(kind: usize, a: &Expr, b: &Expr) -> Expr { + let a = Box::new(a.clone()); + let b = Box::new(b.clone()); + match kind { + 0 => Expr::Add(a, b), + 1 => Expr::Sub(a, b), + _ => Expr::Mul(a, b), + } +} + +fn fixtures() -> Vec> { + let x = Expr::main(0); + let y = Expr::main(1); + let zero = Expr::Const(Val::ZERO); + let one = Expr::Const(Val::ONE); + let mut result = vec![ + zero.clone(), + one.clone(), + Expr::Const(-Val::ONE), + Expr::Const(Val::from_u64(17)), + ]; + for source in [Source::Preprocessed, Source::Main] { + for offset in [RowOffset::Current, RowOffset::Next] { + result.push(Expr::Var(ColRef { source, offset, index: 2 })); + } + } + result.extend([ + Expr::Public(0), + Expr::Public(2), + Expr::IsFirstRow, + Expr::IsLastRow, + Expr::IsTransition, + Expr::Neg(Box::new(x.clone())), + binary(0, &x, &y), + binary(1, &zero, &x), + binary(2, &zero, &y), + Expr::Neg(Box::new(zero)), + Expr::Neg(Box::new(one.clone())), + Expr::Neg(Box::new(Expr::Neg(Box::new(x)))), + Expr::Neg(Box::new(Expr::Neg(Box::new(one.clone())))), + binary(0, &one, &one), + ]); + assert_eq!(result.len(), 22); + result +} + +fn accepted_specs() -> Vec { + let fixtures = fixtures(); + let zero = Expr::Const(Val::ZERO); + let one = Expr::Const(Val::ONE); + let anchor = Expr::main(3); + let mut specs = vec![ + Spec { constraints: vec![], lookups: vec![] }, + Spec { + constraints: vec![zero.clone()], + lookups: vec![Lookup { + multiplicity: one.clone(), + args: fixtures.clone(), + }], + }, + ]; + for left in &fixtures { + for right in &fixtures { + for kind in 0..3 { + let root = binary(kind, left, right); + let reverse = binary(kind, right, left); + let constraint = binary(1, &root, &anchor); + specs.push(Spec { + constraints: vec![ + constraint.clone(), + constraint, + binary(1, &reverse, &anchor), + binary(1, &root, &root), + ], + lookups: vec![ + Lookup { + multiplicity: left.clone(), + args: vec![right.clone(), root.clone(), reverse, root], + }, + // The final unused leaf extends the stored lookup prefix. + Lookup { + multiplicity: one.clone(), + args: vec![binary(2, &zero, &anchor)], + }, + ], + }); + } + } + let negated = Expr::Neg(Box::new(left.clone())); + specs.push(Spec { + constraints: vec![binary(1, &negated, &anchor)], + lookups: vec![Lookup { + multiplicity: one.clone(), + args: vec![left.clone(), negated], + }], + }); + } + let x = Expr::main(0); + let y = Expr::main(1); + let mut ordered = vec![ + binary(0, &x, &y), + binary(0, &y, &x), + binary(2, &x, &y), + binary(2, &y, &x), + binary(1, &x, &y), + binary(1, &y, &x), + Expr::Neg(Box::new(x.clone())), + Expr::Neg(Box::new(Expr::Neg(Box::new(x)))), + ]; + for _ in 0..8 { + specs.push(Spec { constraints: ordered.clone(), lookups: vec![] }); + ordered.rotate_left(1); + } + assert_eq!(specs.len(), 1484); + specs +} + +fn rejected_specs() -> Vec<(Spec, &'static str)> { + let mut specs = Vec::new(); + let lookup_spec = |expr| Spec { + constraints: vec![], + lookups: vec![Lookup { + multiplicity: Expr::Const(Val::ONE), + args: vec![expr], + }], + }; + for source in [Source::Preprocessed, Source::Main, Source::Stage2] { + let error = if source == Source::Stage2 { + "Stage2InBaseContext" + } else { + "ColumnOutOfRange" + }; + for offset in [RowOffset::Current, RowOffset::Next] { + for index in [4, 7, u32::MAX] { + specs.push(( + lookup_spec(Expr::Var(ColRef { source, offset, index })), + error, + )); + } + let index = if source == Source::Stage2 { 0 } else { 4 }; + let invalid = Expr::Var(ColRef { source, offset, index }); + // Raw folds still visit and reject their invalid children. + specs.push(( + lookup_spec(binary(2, &Expr::Const(Val::ZERO), &invalid)), + error, + )); + specs.push((lookup_spec(binary(1, &invalid, &invalid)), error)); + } + } + for index in [8, 9, u32::MAX] { + specs.push((lookup_spec(Expr::Public(index)), "PublicOutOfRange")); + } + for constant in [Val::ONE, -Val::ONE, Val::from_u64(17)] { + specs.push(( + Spec { constraints: vec![Expr::Const(constant)], lookups: vec![] }, + "UnsatisfiableConstant", + )); + } + specs.push(( + Spec { + constraints: vec![binary( + 0, + &Expr::Const(Val::ONE), + &Expr::Const(Val::ONE), + )], + lookups: vec![], + }, + "UnsatisfiableConstant", + )); + specs.push(( + Spec { + constraints: vec![Expr::main(0), Expr::Const(Val::ONE)], + lookups: vec![], + }, + "UnsatisfiableConstant", + )); + assert_eq!(specs.len(), 38); + specs +} + +fn write_nat(out: &mut Vec, value: usize) { + out.extend_from_slice(&(value as u64).to_le_bytes()); +} + +fn write_field(out: &mut Vec, value: Val) { + out.extend_from_slice(&value.as_canonical_u64().to_le_bytes()); +} + +fn write_values(out: &mut Vec, values: &[Val]) { + write_nat(out, values.len()); + for &value in values { + write_field(out, value); + } +} + +fn write_column(out: &mut Vec, column: ColRef) { + out.push(match column.source { + Source::Preprocessed => 0, + Source::Main => 1, + Source::Stage2 => 2, + }); + out.push(match column.offset { + RowOffset::Current => 0, + RowOffset::Next => 1, + }); + write_nat(out, column.index as usize); +} + +fn write_expr(out: &mut Vec, expr: &Expr) { + match expr { + Expr::Const(value) => { + out.push(0); + write_field(out, *value); + }, + Expr::Var(column) => { + out.push(1); + write_column(out, *column); + }, + Expr::Public(index) => { + out.push(2); + write_nat(out, *index as usize); + }, + Expr::IsFirstRow => out.push(3), + Expr::IsLastRow => out.push(4), + Expr::IsTransition => out.push(5), + Expr::Add(a, b) | Expr::Sub(a, b) | Expr::Mul(a, b) => { + out.push(match expr { + Expr::Add(..) => 6, + Expr::Sub(..) => 7, + _ => 8, + }); + write_expr(out, a); + write_expr(out, b); + }, + Expr::Neg(child) => { + out.push(9); + write_expr(out, child); + }, + } +} + +fn write_spec(out: &mut Vec, spec: &Spec) { + for width in spec.widths() { + write_nat(out, width); + } + write_nat(out, spec.lookups.len()); + for lookup in &spec.lookups { + write_expr(out, &lookup.multiplicity); + write_nat(out, lookup.args.len()); + for arg in &lookup.args { + write_expr(out, arg); + } + } + write_nat(out, spec.constraints.len()); + for expr in &spec.constraints { + write_expr(out, expr); + } +} + +fn write_graph(out: &mut Vec, graph: &ConstraintGraph) { + write_nat(out, graph.nodes.len()); + for node in &graph.nodes { + match *node { + Node::Const(value) => { + out.push(0); + write_field(out, value); + }, + Node::Var(column) => { + out.push(1); + write_column(out, column); + }, + Node::Public(index) => { + out.push(2); + write_nat(out, index as usize); + }, + Node::IsFirstRow => out.push(3), + Node::IsLastRow => out.push(4), + Node::IsTransition => out.push(5), + Node::Add(a, b) | Node::Sub(a, b) | Node::Mul(a, b) => { + out.push(match node { + Node::Add(..) => 6, + Node::Sub(..) => 7, + _ => 8, + }); + write_nat(out, a.index()); + write_nat(out, b.index()); + }, + Node::Neg(child) => { + out.push(9); + write_nat(out, child.index()); + }, + } + } + for °ree in &graph.degrees { + write_nat(out, degree as usize); + } + write_nat(out, graph.zeros.len()); + for root in &graph.zeros { + write_nat(out, root.index()); + } + write_nat(out, graph.lookups.len()); + for lookup in &graph.lookups { + write_nat(out, lookup.multiplicity.index()); + write_nat(out, lookup.args.len()); + for arg in &lookup.args { + write_nat(out, arg.index()); + } + } + write_nat(out, graph.lookup_prefix_len); + write_nat(out, graph.max_constraint_degree as usize); +} + +fn config() -> AiurConfig { + AiurConfig::new( + CommitmentParameters { log_blowup: 3, cap_height: 0 }, + FriParameters { + log_final_poly_len: 0, + max_log_arity: 1, + num_queries: 64, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + }, + ) +} + +fn assignment(width: usize, slot: usize, seed: usize) -> Vec { + let choices = [ + Val::ZERO, + Val::ONE, + -Val::ONE, + Val::from_u64(17), + Val::from_u64(255), + Val::from_u64(256), + Val::from_u64(65536), + Val::TWO, + ]; + (0..width) + .map(|index| { + if seed < 3 { + choices[seed] + } else { + choices[(3 * slot + 5 * seed + 7 * index) % choices.len()] + } + }) + .collect() +} + +#[test] +fn graph_compilation_snapshot() -> io::Result<()> { + let specs = accepted_specs(); + let (system, _) = System::new(config(), specs.iter().map(Spec::inputs)); + let mut out = b"Aiur graph compilation v1\n".to_vec(); + write_nat(&mut out, specs.len()); + let mut assignments = 0; + let mut node_values = 0; + for (spec, circuit) in specs.iter().zip(&system.circuits) { + assert_eq!( + spec.widths(), + [ + circuit.preprocessed_width, + circuit.main_width, + circuit.stage_2_width, + circuit.num_publics + ] + ); + write_spec(&mut out, spec); + write_graph(&mut out, &circuit.graph); + for seed in 0..8 { + let [pre, main, stage, publics] = spec.widths(); + let rows: Vec<_> = [pre, pre, main, main, stage, stage, publics, 3] + .into_iter() + .enumerate() + .map(|(slot, width)| assignment(width, slot, seed)) + .collect(); + for row in &rows { + write_values(&mut out, row); + } + let values = VarValues { + preprocessed: [&rows[0], &rows[1]], + main: [&rows[2], &rows[3]], + stage2: [&rows[4], &rows[5]], + publics: &rows[6], + is_first_row: rows[7][0], + is_last_row: rows[7][1], + is_transition: rows[7][2], + }; + let mut buffer = Vec::new(); + circuit.graph.sweep(&values, &mut buffer); + write_values(&mut out, &buffer); + let mut prefix = Vec::new(); + circuit.graph.sweep_lookup_prefix( + &VarValues { stage2: [&[], &[]], ..values }, + &mut prefix, + ); + assert_eq!(prefix, buffer[..circuit.graph.lookup_prefix_len]); + write_values(&mut out, &prefix); + let original: Vec<_> = + spec.constraints.iter().map(|expr| eval_expr(expr, &values)).collect(); + write_values(&mut out, &original); + assert_eq!( + original.iter().all(|v| *v == Val::ZERO), + circuit + .graph + .constraint_values(&buffer) + .iter() + .all(|v| *v == Val::ZERO) + ); + let lookups: Vec<_> = spec + .lookups + .iter() + .map(|lookup| Lookup { + multiplicity: eval_expr(&lookup.multiplicity, &values), + args: lookup + .args + .iter() + .map(|expr| eval_expr(expr, &values)) + .collect(), + }) + .collect(); + assert_eq!(lookups, circuit.graph.lookup_values(&prefix)); + for lookup in lookups { + write_field(&mut out, lookup.multiplicity); + write_values(&mut out, &lookup.args); + } + assignments += 1; + node_values += buffer.len(); + } + } + let rejected = rejected_specs(); + write_nat(&mut out, rejected.len()); + for (spec, expected_error) in &rejected { + let failed = catch_unwind(|| System::new(config(), [spec.inputs()])); + let Err(error) = failed else { + panic!("invalid graph unexpectedly compiled") + }; + let message = error + .downcast_ref::() + .map(String::as_str) + .or_else(|| error.downcast_ref::<&str>().copied()) + .expect("string compilation error"); + assert!(message.contains("constraint compilation failed:"), "{message}"); + assert!(message.contains(expected_error), "{message}"); + write_spec(&mut out, spec); + } + if let Some(path) = std::env::var_os("IX_GRAPH_COMPILATION_SNAPSHOT") { + fs::write(path, out)?; + } + eprintln!( + "graph compilation: {} complete graphs, {} rejected specifications, {assignments} assignments, {node_values} node values", + specs.len(), + rejected.len() + ); + Ok(()) +} diff --git a/crates/aiur/src/vk_codec/tests/domain.rs b/crates/aiur/src/vk_codec/tests/domain.rs new file mode 100644 index 000000000..88ea5a3d6 --- /dev/null +++ b/crates/aiur/src/vk_codec/tests/domain.rs @@ -0,0 +1,249 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! The actual pinned polynomial-space selectors, at all supported domain +//! sizes and on complete small cosets. Large domains are never enumerated. + +use super::*; +use multi_stark::{ + p3_field::{ + BasedVectorSpace, Field, TwoAdicField, coset::TwoAdicMultiplicativeCoset, + }, + types::ExtVal, +}; +use p3_commit::PolynomialSpace; +use std::io; + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + for &coordinate in value.as_basis_coefficients_slice() { + field(out, coordinate); + } +} + +fn selector_values( + out: &mut Vec, + values: &p3_commit::LagrangeSelectors, +) { + extension(out, values.is_first_row); + extension(out, values.is_last_row); + extension(out, values.is_transition); + extension(out, values.inv_vanishing); +} + +fn challenges(last: Val) -> Vec { + let mut values: Vec<_> = [ + Val::ZERO, + Val::ONE, + Val::NEG_ONE, + last, + Val::from_u64(7), + Val::from_u64(1 << 32), + Val::from_u64(1 << 63), + Val::from_u64(Val::ORDER_U64 - 2), + ] + .into_iter() + .map(ExtVal::from) + .collect(); + let mut state = 0x04c9_bd65_a678_10fb_u64; + let mut next = || { + state ^= state << 13; + state ^= state >> 7; + state ^= state << 17; + Val::from_u64(state) + }; + for _ in 0..56 { + values.push(ExtVal::new([next(), next()])); + } + values +} + +#[test] +fn domain_snapshot() -> io::Result<()> { + let mut out = b"Aiur trace domains v1\n".to_vec(); + assert_eq!(Val::TWO_ADICITY, 32); + nat(&mut out, 33); + for bits in 0..=32 { + let domain = + TwoAdicMultiplicativeCoset::::new(Val::ONE, bits).unwrap(); + let n = domain.size(); + let generator = domain.subgroup_generator(); + let last = generator.inverse(); + let normalizer = Val::from_usize(n) * generator; + nat(&mut out, bits); + nat(&mut out, n); + field(&mut out, generator); + field(&mut out, last); + field(&mut out, normalizer); + field(&mut out, normalizer.inverse()); + assert_eq!(domain.first_point(), Val::ONE); + assert_eq!(generator.exp_power_of_2(bits), Val::ONE); + if bits > 0 { + assert_eq!(generator.exp_power_of_2(bits - 1), Val::NEG_ONE); + } + let mut indices: Vec<_> = (0..n.min(16)).collect(); + indices.extend([n / 2, n - 1, n.saturating_sub(2)]); + for seed in 0..16_usize { + indices.push(seed.wrapping_mul(0x0a37_51c9) % n); + } + indices.sort_unstable(); + indices.dedup(); + nat(&mut out, indices.len()); + for index in indices { + let point = generator.exp_u64(u64::try_from(index).unwrap()); + let next = domain.next_point(ExtVal::from(point)).unwrap(); + nat(&mut out, index); + field(&mut out, point); + extension(&mut out, next); + assert_eq!(next, ExtVal::from(point * generator)); + assert_eq!( + next, + ExtVal::from( + generator.exp_u64(u64::try_from((index + 1) % n).unwrap()) + ) + ); + assert_eq!( + domain.vanishing_poly_at_point(ExtVal::from(point)), + ExtVal::ZERO + ); + } + let points = challenges(last); + nat(&mut out, points.len()); + for point in points { + let vanishing = domain.vanishing_poly_at_point(point); + extension(&mut out, point); + extension(&mut out, vanishing); + out.push(u8::from(vanishing != ExtVal::ZERO)); + if vanishing != ExtVal::ZERO { + selector_values(&mut out, &domain.selectors_at_point(point)); + } + } + } + // Each complete coset is disjoint from the trace domain. The bulk native + // algorithm and the single-point native algorithm must agree at every point. + nat(&mut out, 9); + for bits in 0..9 { + let domain = + TwoAdicMultiplicativeCoset::::new(Val::ONE, bits).unwrap(); + let coset = + TwoAdicMultiplicativeCoset::::new(Val::GENERATOR, bits).unwrap(); + let bulk = domain.selectors_on_coset(coset); + nat(&mut out, bits); + nat(&mut out, coset.size()); + for (index, point) in coset.iter().enumerate() { + let single = domain.selectors_at_point(ExtVal::from(point)); + assert_eq!(single.is_first_row, ExtVal::from(bulk.is_first_row[index])); + assert_eq!(single.is_last_row, ExtVal::from(bulk.is_last_row[index])); + assert_eq!(single.is_transition, ExtVal::from(bulk.is_transition[index])); + assert_eq!(single.inv_vanishing, ExtVal::from(bulk.inv_vanishing[index])); + field(&mut out, point); + selector_values(&mut out, &single); + } + } + for invalid in [33, 64, 255, 256, usize::MAX] { + assert!( + TwoAdicMultiplicativeCoset::::new(Val::ONE, invalid).is_none() + ); + } + if let Some(path) = std::env::var_os("IX_DOMAIN_SNAPSHOT") { + std::fs::write(path, &out)?; + } + Ok(()) +} + +fn extensions(out: &mut Vec, values: &[ExtVal]) { + nat(out, values.len()); + for &value in values { + extension(out, value); + } +} + +// This reproduces the verifier's private recombination helper with native +// basis elements, power iterator and field operations. Domain selector calls +// above and below invoke PolynomialSpace's actual implementation directly. +fn quotient_value(point: ExtVal, bits: usize, row: &[ExtVal]) -> ExtVal { + row + .as_chunks::<2>() + .0 + .iter() + .zip(point.exp_power_of_2(bits).powers()) + .map(|(chunk, power)| { + let coefficient = chunk + .iter() + .enumerate() + .map(|(index, value)| { + *value + * >::ith_basis_element(index) + .unwrap() + }) + .sum::(); + power * coefficient + }) + .sum() +} + +#[test] +fn quotient_snapshot() -> io::Result<()> { + let mut out = b"Aiur quotient arithmetic v1\n".to_vec(); + let logs = [0, 1, 2, 4, 8, 16, 31, 32]; + let counts = [0, 1, 2, 3, 4, 7, 8, 9, 16, 31, 32]; + let values = challenges(Val::from_u64(17)); + nat(&mut out, logs.len() * counts.len() * 8); + for bits in logs { + let domain = + TwoAdicMultiplicativeCoset::::new(Val::ONE, bits).unwrap(); + for count in counts { + for seed in 0..8 { + let point = values[8 + seed]; + let alpha = values[seed]; + let constraints: Vec<_> = (0..count) + .map(|index| values[(index * 7 + seed) % values.len()]) + .collect(); + let composition = constraints + .iter() + .fold(ExtVal::ZERO, |acc, &value| acc * alpha + value); + let mut row: Vec<_> = (0..2 * count) + .map(|index| values[(index * 11 + seed + 13) % values.len()]) + .collect(); + let selectors = domain.selectors_at_point(point); + let expected = composition * selectors.inv_vanishing; + if seed % 2 == 0 && count != 0 { + let error = expected - quotient_value(point, bits, &row); + row[0] += error; + } + let quotient = quotient_value(point, bits, &row); + let accepted = expected == quotient; + if seed % 2 == 0 || count == 0 { + assert!(accepted); + } else { + assert!(!accepted); + } + nat(&mut out, bits); + nat(&mut out, count); + nat(&mut out, seed); + extension(&mut out, point); + extension(&mut out, alpha); + extensions(&mut out, &constraints); + extensions(&mut out, &row); + extension(&mut out, composition); + extension(&mut out, quotient); + out.push(u8::from(accepted)); + if accepted && !row.is_empty() { + row[0] += ExtVal::ONE; + assert_ne!(expected, quotient_value(point, bits, &row)); + } + } + } + } + if let Some(path) = std::env::var_os("IX_QUOTIENT_SNAPSHOT") { + std::fs::write(path, &out)?; + } + Ok(()) +} diff --git a/crates/aiur/src/vk_codec/tests/extension_arithmetic.rs b/crates/aiur/src/vk_codec/tests/extension_arithmetic.rs new file mode 100644 index 000000000..2ffef7095 --- /dev/null +++ b/crates/aiur/src/vk_codec/tests/extension_arithmetic.rs @@ -0,0 +1,256 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Arithmetic from the pinned field implementation, including full-width +//! exponents and arbitrary quadratic values in the actual compiled graphs. + +use super::*; +use multi_stark::{ + eval::VarValues, + p3_field::{BasedVectorSpace, Field, extension::HasFrobenius}, + types::ExtVal, +}; +use std::io; + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + for &coordinate in value.as_basis_coefficients_slice() { + field(out, coordinate); + } +} + +fn extensions(out: &mut Vec, values: &[ExtVal]) { + nat(out, values.len()); + for &value in values { + extension(out, value); + } +} + +fn inverse(out: &mut Vec, value: Option) { + out.push(u8::from(value.is_some())); + if let Some(value) = value { + extension(out, value); + } +} + +fn scalars() -> Vec { + let p = Val::ORDER_U64; + [ + 0, + 1, + 2, + 7, + 17, + 255, + 256, + 65535, + 65536, + (1 << 32) - 1, + 1 << 32, + (1 << 48) - 1, + 1 << 63, + p - 3, + p - 2, + p - 1, + ] + .into_iter() + .map(Val::from_u64) + .collect() +} + +fn values() -> Vec { + let scalars = scalars(); + let mut values = Vec::new(); + for &first in &scalars { + for &second in &scalars { + values.push(ExtVal::new([first, second])); + } + } + // Reproducible full-word coordinates, independent in the two slots. + let mut state = 0x19a9_391d_0582_a7a5_u64; + let mut next = || { + state ^= state << 13; + state ^= state >> 7; + state ^= state << 17; + Val::from_u64(state) + }; + for _ in 0..128 { + values.push(ExtVal::new([next(), next()])); + } + values +} + +fn exponents() -> [u128; 20] { + let p = u128::from(Val::ORDER_U64); + [ + 0, + 1, + 2, + 3, + 7, + 8, + 15, + 16, + 31, + 32, + 63, + 64, + p - 2, + p - 1, + p, + u128::from(u64::MAX), + 1 << 64, + p * p - 2, + (1 << 127) + 1, + u128::MAX, + ] +} + +fn native_power(value: ExtVal, exponent: u128) -> ExtVal { + let low = u64::try_from(exponent & u128::from(u64::MAX)).unwrap(); + let high = u64::try_from(exponent >> 64).unwrap(); + value.exp_u64(low) * value.exp_u64(high).exp_power_of_2(64) +} + +#[test] +fn extension_arithmetic_snapshot() -> io::Result<()> { + let mut out = b"Aiur extension arithmetic v1\n".to_vec(); + let scalars = scalars(); + nat(&mut out, scalars.len()); + for value in scalars { + field(&mut out, value); + field(&mut out, value.try_inverse().unwrap_or(Val::ZERO)); + } + let values = values(); + let exponents = exponents(); + extensions(&mut out, &values); + nat(&mut out, exponents.len()); + for exponent in exponents { + out.extend(exponent.to_le_bytes()); + } + let mut inverses = 0; + for &value in &values { + extension(&mut out, -value); + extension(&mut out, value.square()); + extension(&mut out, value.frobenius()); + let norm = value * value.frobenius(); + let norm_coordinates: &[Val] = norm.as_basis_coefficients_slice(); + assert_eq!(norm_coordinates[1], Val::ZERO); + field(&mut out, norm_coordinates[0]); + let inv = value.try_inverse(); + if let Some(inv) = inv { + assert_eq!(value * inv, ExtVal::ONE); + inverses += 1; + } + inverse(&mut out, inv); + for exponent in exponents { + extension(&mut out, native_power(value, exponent)); + } + } + for &left in &values { + for &right in &values { + extension(&mut out, left + right); + extension(&mut out, left - right); + extension(&mut out, left * right); + } + } + assert_eq!((values.len(), inverses), (384, 383)); + if let Some(path) = std::env::var_os("IX_EXTENSION_ARITHMETIC_SNAPSHOT") { + std::fs::write(path, out)?; + } + eprintln!( + "extension arithmetic: {} values, {} powers, {} ordered pairs", + values.len(), + values.len() * exponents.len(), + values.len() * values.len() + ); + Ok(()) +} + +fn assignment( + values: &[ExtVal], + width: usize, + slot: usize, + seed: usize, +) -> Vec { + (0..width) + .map(|index| match seed { + 0 => ExtVal::ZERO, + 1 => ExtVal::ONE, + 2 => -ExtVal::ONE, + _ => values[(index * 37 + slot * 61 + seed * 19) % values.len()], + }) + .collect() +} + +#[test] +fn extension_graph_snapshot() -> io::Result<()> { + let system = graph_tests::graph_system(); + let values = values(); + let mut out = b"Aiur extension graphs v1\n".to_vec(); + nat(&mut out, system.circuits.len()); + let mut nodes = 0; + for circuit in &system.circuits { + let mut encoded = Vec::new(); + encode_circuit(&mut encoded, circuit); + nat(&mut out, encoded.len()); + out.extend(encoded); + nat(&mut out, 24); + for seed in 0..24 { + let widths = [ + circuit.preprocessed_width, + circuit.preprocessed_width, + circuit.main_width, + circuit.main_width, + circuit.stage_2_width, + circuit.stage_2_width, + circuit.num_publics, + ]; + let rows: Vec<_> = widths + .into_iter() + .enumerate() + .map(|(slot, width)| assignment(&values, width, slot, seed)) + .collect(); + for row in &rows { + extensions(&mut out, row); + } + let selectors = assignment(&values, 3, 7, seed); + for &selector in &selectors { + extension(&mut out, selector); + } + let view = VarValues { + preprocessed: [&rows[0], &rows[1]], + main: [&rows[2], &rows[3]], + stage2: [&rows[4], &rows[5]], + publics: &rows[6], + is_first_row: selectors[0], + is_last_row: selectors[1], + is_transition: selectors[2], + }; + let mut buffer = Vec::new(); + circuit.graph.sweep(&view, &mut buffer); + nodes += buffer.len(); + extensions(&mut out, &buffer); + extensions(&mut out, &circuit.graph.constraint_values(&buffer)); + let lookups = circuit.graph.lookup_values(&buffer); + nat(&mut out, lookups.len()); + for lookup in lookups { + extension(&mut out, lookup.multiplicity); + extensions(&mut out, &lookup.args); + } + } + } + assert_eq!((system.circuits.len(), nodes), (10, 8016)); + if let Some(path) = std::env::var_os("IX_EXTENSION_GRAPH_SNAPSHOT") { + std::fs::write(path, out)?; + } + eprintln!("extension graphs: 240 native assignments, {nodes} node values"); + Ok(()) +} diff --git a/crates/aiur/src/vk_codec/tests/graphs.rs b/crates/aiur/src/vk_codec/tests/graphs.rs new file mode 100644 index 000000000..a36926d3d --- /dev/null +++ b/crates/aiur/src/vk_codec/tests/graphs.rs @@ -0,0 +1,286 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::*; +use crate::{ + bytecode::{ + Block, Circuit as BytecodeCircuit, Ctrl, Function, FunctionLayout, Op, + Toplevel, + }, + gadgets::{AiurGadget, bytes1::Bytes1, bytes2::Bytes2}, + memory::Memory, +}; +use multi_stark::{ + eval::VarValues, + expr::{Expr, ExtExpr}, + p3_matrix::dense::RowMajorMatrix, + system::CircuitInputs, +}; +use std::{ + fs::File, + io::{self, Write}, +}; + +fn expression_input() -> CircuitInputs { + let x = Expr::main(0); + let y = Expr::main_next(1); + let constraints = vec![ + x.clone() + Expr::preprocessed(0), + y.clone() - Expr::public(1), + -x.clone(), + Expr::IsTransition * (x.clone() * x.clone() - y.clone()), + // Exercise explicit frontend nodes, folding and duplicate roots. + Expr::Add(Box::new(Expr::Const(Val::ZERO)), Box::new(x.clone())), + Expr::Sub(Box::new(x.clone()), Box::new(x.clone())), + x.clone(), + x.clone(), + ]; + let ext = ExtExpr::stage2(0, 2, RowOffset::Current); + let ext_constraints = vec![ + ext.clone() * ext.clone() - ExtExpr::stage2(0, 2, RowOffset::Next), + -ext + ExtExpr::Coords(vec![x.clone(), y.clone()]), + ]; + let lookups = vec![Lookup { + multiplicity: -x.clone(), + args: vec![ + x, + y, + Expr::preprocessed(1), + Expr::preprocessed_next(0), + Expr::public(0), + Expr::IsFirstRow, + Expr::IsLastRow, + Expr::IsTransition, + Expr::Const(Val::from_u64(65536)), + Expr::Const(-Val::ONE), + // Compilation interns Main(2), then folds the expression to zero. + // The compiler's lookup prefix can therefore exceed the root-derived + // prefix reconstructed by the codec, without changing lookup values. + Expr::Mul(Box::new(Expr::Const(Val::ZERO)), Box::new(Expr::main(2))), + ], + }]; + CircuitInputs { + main_width: 3, + preprocessed: Some(RowMajorMatrix::new(vec![Val::ZERO; 4], 2)), + constraints, + ext_constraints, + lookups, + lookup_group_size: 1, + } +} + +fn function_inputs() -> Vec> { + let layout = + FunctionLayout { input_size: 2, selectors: 1, auxiliaries: 8, lookups: 4 }; + let function = || Function { + body: Block { ops: vec![Op::Mul(0, 1)], ctrl: Ctrl::Return(0, vec![2]) }, + layout, + entry: true, + constrained: true, + }; + let top = Toplevel { + functions: vec![function(), function()], + circuits: vec![ + BytecodeCircuit { members: vec![0], layout }, + BytecodeCircuit { + members: vec![0, 1], + layout: FunctionLayout { selectors: 2, ..layout }, + }, + ], + memory_sizes: vec![], + call_components: vec![], + }; + (0..top.circuits.len()) + .map(|index| { + let (constraints, lookups) = top.build_constraints(index); + CircuitInputs { + main_width: constraints.width, + constraints: constraints.zeros, + lookups, + lookup_group_size: 1, + ..CircuitInputs::default() + } + }) + .collect() +} + +pub(super) fn graph_system() -> System { + let mut inputs = vec![expression_input()]; + for size in [0, 1, 2, 4, 8] { + let (memory, constraints, lookups) = Memory::build(size); + inputs.push(CircuitInputs { + main_width: memory.width, + constraints, + lookups, + lookup_group_size: 1, + ..CircuitInputs::default() + }); + } + inputs.extend([ + CircuitInputs { + main_width: Bytes1.main_width(), + preprocessed: Bytes1.preprocessed(), + lookups: Bytes1.lookups(), + lookup_group_size: 1, + ..CircuitInputs::default() + }, + CircuitInputs { + main_width: Bytes2.main_width(), + preprocessed: Bytes2.preprocessed(), + lookups: Bytes2.lookups(), + lookup_group_size: 2, + ..CircuitInputs::default() + }, + ]); + inputs.extend(function_inputs()); + let cp = CommitmentParameters { log_blowup: 1, cap_height: 0 }; + let fp = FriParameters { + log_final_poly_len: 0, + max_log_arity: 1, + num_queries: 64, + commit_proof_of_work_bits: 0, + query_proof_of_work_bits: 0, + }; + System::new(AiurConfig::new(cp, fp), inputs).0 +} + +fn write_nat(out: &mut Vec, value: usize) { + out.extend_from_slice(&(value as u64).to_le_bytes()); +} + +fn write_values(out: &mut Vec, values: &[Val]) { + write_nat(out, values.len()); + for value in values { + out.extend_from_slice(&value.as_canonical_u64().to_le_bytes()); + } +} + +fn assignment(width: usize, matrix: usize, pattern: usize) -> Vec { + let choices = [ + Val::ZERO, + Val::ONE, + -Val::ONE, + Val::from_u64(255), + Val::from_u64(256), + Val::from_u64(1 << 32), + Val::from_u64((1 << 48) - 1), + Val::from_u64(17), + ]; + (0..width) + .map(|index| match pattern { + 0 => Val::ZERO, + 1 => Val::ONE, + 2 => -Val::ONE, + _ => choices[(5 * index + 3 * pattern + matrix) % choices.len()], + }) + .collect() +} + +#[test] +fn expression_graph_snapshot() -> io::Result<()> { + let system = graph_system(); + let mut out = b"Aiur expression graphs v1\n".to_vec(); + write_nat(&mut out, system.circuits.len()); + let mut checked = 0; + let mut nodes_evaluated = 0; + let mut shortened_prefixes = 0; + for circuit in &system.circuits { + let mut encoded = Vec::new(); + encode_circuit(&mut encoded, circuit); + // Exercise the production decoder's new checks on every actual graph. + let mut segment = Seg { buf: &encoded, pos: 0 }; + let decoded = decode_circuit(&mut segment).expect("actual graph decodes"); + segment.done("circuit").unwrap(); + assert_eq!(decoded.graph.nodes, circuit.graph.nodes); + assert_eq!(decoded.graph.degrees, circuit.graph.degrees); + assert_eq!(decoded.graph.zeros, circuit.graph.zeros); + assert_eq!(decoded.graph.lookups, circuit.graph.lookups); + assert_eq!( + decoded.graph.max_constraint_degree, + circuit.graph.max_constraint_degree + ); + assert!(decoded.graph.lookup_prefix_len <= circuit.graph.lookup_prefix_len); + if decoded.graph.lookup_prefix_len < circuit.graph.lookup_prefix_len { + shortened_prefixes += 1; + } + let mut reencoded = Vec::new(); + encode_circuit(&mut reencoded, &decoded); + assert_eq!(reencoded, encoded); + write_nat(&mut out, encoded.len()); + out.extend_from_slice(&encoded); + write_nat(&mut out, 24); + for pattern in 0..24 { + let widths = [ + circuit.preprocessed_width, + circuit.preprocessed_width, + circuit.main_width, + circuit.main_width, + circuit.stage_2_width, + circuit.stage_2_width, + ]; + let rows: Vec<_> = widths + .into_iter() + .enumerate() + .map(|(matrix, width)| assignment(width, matrix, pattern)) + .collect(); + let publics = assignment(circuit.num_publics, 6, pattern); + for row in &rows { + write_values(&mut out, row); + } + write_values(&mut out, &publics); + let selectors = [ + Val::from_bool(pattern % 4 == 0), + Val::from_bool(pattern % 4 == 1), + Val::from_bool(pattern % 4 != 1), + ]; + for value in selectors { + out.extend_from_slice(&value.as_canonical_u64().to_le_bytes()); + } + let values = VarValues { + preprocessed: [&rows[0], &rows[1]], + main: [&rows[2], &rows[3]], + stage2: [&rows[4], &rows[5]], + publics: &publics, + is_first_row: selectors[0], + is_last_row: selectors[1], + is_transition: selectors[2], + }; + let mut full = Vec::new(); + circuit.graph.sweep(&values, &mut full); + let mut prefix = Vec::new(); + let mut compiled_prefix = Vec::new(); + circuit.graph.sweep_lookup_prefix( + &VarValues { stage2: [&[], &[]], ..values }, + &mut compiled_prefix, + ); + decoded.graph.sweep_lookup_prefix( + &VarValues { stage2: [&[], &[]], ..values }, + &mut prefix, + ); + assert_eq!(prefix, compiled_prefix[..prefix.len()]); + assert_eq!(prefix, full[..prefix.len()]); + write_values(&mut out, &full); + write_values(&mut out, &prefix); + write_values(&mut out, &circuit.graph.constraint_values(&full)); + let lookups = circuit.graph.lookup_values(&prefix); + write_nat(&mut out, lookups.len()); + for lookup in lookups { + out.extend_from_slice( + &lookup.multiplicity.as_canonical_u64().to_le_bytes(), + ); + write_values(&mut out, &lookup.args); + } + nodes_evaluated += full.len(); + checked += 1; + } + } + assert_eq!(checked, 240); + assert!(shortened_prefixes > 0, "include folded, unused lookup nodes"); + if let Some(path) = std::env::var_os("IX_EXPRESSION_GRAPH_SNAPSHOT") { + File::create(path)?.write_all(&out)?; + } + eprintln!( + "expression graphs: {checked} native assignments, {nodes_evaluated} node values" + ); + Ok(()) +} diff --git a/crates/aiur/src/vk_codec/tests/logup.rs b/crates/aiur/src/vk_codec/tests/logup.rs new file mode 100644 index 000000000..a1400b6b5 --- /dev/null +++ b/crates/aiur/src/vk_codec/tests/logup.rs @@ -0,0 +1,355 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! The pinned direct evaluator in both scalar domains, its independent +//! symbolic specification, and the actual grouped stage-2 trace builder. + +use super::*; +use multi_stark::{ + eval::{VarValues, eval_ext_expr}, + expr::Expr, + graph::ExtensionParams, + lookup::{ + LookupValues, logup_constraint_values, stage2_width, synthesize_lookups, + }, + p3_field::{ + Algebra, BasedVectorSpace, Field, TwoAdicField, + extension::BinomiallyExtendable, + }, + types::ExtVal, +}; +use std::io; + +const COUNTS: [usize; 22] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 23, 24, 25, 31, 32, 33, 63, 64, 65, +]; +const ARITIES: [usize; 10] = [0, 1, 2, 3, 4, 7, 8, 9, 16, 17]; +const SEEDS: usize = 12; + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + for &coordinate in value.as_basis_coefficients_slice() { + field(out, coordinate); + } +} + +fn vector( + out: &mut Vec, + values: &[W], + encode: fn(&mut Vec, W), +) { + nat(out, values.len()); + for &value in values { + encode(out, value); + } +} + +fn scalar(seed: usize, slot: usize, index: usize) -> Val { + let mut value = 0x508c_4dd3_50c9_1a2b_u64 + .wrapping_add(u64::try_from(seed).unwrap().wrapping_mul(0x36d3_2817)) + .wrapping_add(u64::try_from(slot).unwrap().wrapping_mul(0x792b_586f)) + .wrapping_add(u64::try_from(index).unwrap().wrapping_mul(0x650d_810b)); + for _ in 0..4 { + value ^= value << 13; + value ^= value >> 7; + value ^= value << 17; + } + if seed < 6 { + let boundary = [ + 0, + 1, + 2, + 7, + 255, + 65536, + (1 << 32) - 1, + 1 << 63, + Val::ORDER_U64 - 2, + Val::ORDER_U64 - 1, + ]; + Val::from_u64(boundary[(seed + slot + index) % boundary.len()]) + } else { + Val::from_u64(value) + } +} + +fn assignment( + seed: usize, + slot: usize, + length: usize, + make: fn(Val, Val) -> W, +) -> Vec { + (0..length) + .map(|index| match seed { + 0 => W::ZERO, + 1 => W::ONE, + 2 => W::NEG_ONE, + _ => { + make(scalar(seed, 2 * slot, index), scalar(seed, 2 * slot + 1, index)) + }, + }) + .collect() +} + +fn lookup_ids(count: usize) -> (Vec>, usize) { + let mut next = 1; + let lookups = (0..count) + .map(|index| { + let multiplicity = NodeId(u32::try_from(next).unwrap()); + next += 1; + let args = (0..ARITIES[index % ARITIES.len()]) + .map(|arg| { + let id = if arg % 3 == 2 { 0 } else { next }; + next += 1; + NodeId(u32::try_from(id).unwrap()) + }) + .collect(); + Lookup { multiplicity, args } + }) + .collect(); + (lookups, next) +} + +fn encode_ids(out: &mut Vec, lookups: &[Lookup]) { + nat(out, lookups.len()); + for lookup in lookups { + nat(out, lookup.multiplicity.index()); + nat(out, lookup.args.len()); + for &arg in &lookup.args { + nat(out, arg.index()); + } + } +} + +fn direct_cases>( + out: &mut Vec, + make: fn(Val, Val) -> W, + encode: fn(&mut Vec, W), +) { + nat(out, COUNTS.len() * 9 * SEEDS); + for count in COUNTS { + let (lookups, nodes) = lookup_ids(count); + let symbolic: Vec>> = lookups + .iter() + .map(|lookup| Lookup { + multiplicity: Expr::main(lookup.multiplicity.0), + args: lookup.args.iter().map(|id| Expr::main(id.0)).collect(), + }) + .collect(); + for group_size in 0..=8 { + let expressions = synthesize_lookups(&symbolic, 2, group_size); + let params = ExtensionParams { + degree: 2, + w: W::from(Val::from_u8(7)), + karatsuba: false, + }; + for seed in 0..SEEDS { + nat(out, count); + nat(out, group_size); + nat(out, seed); + encode_ids(out, &lookups); + let node_values = assignment(seed, 0, nodes, make); + let width = stage2_width(count, group_size, 2); + let current = assignment(seed, 1, width, make); + let next = assignment(seed, 2, width, make); + let publics = assignment(seed, 3, 8, make); + let delta = [publics[6] - publics[4], publics[7] - publics[5]]; + let is_last = assignment(seed, 4, 1, make)[0]; + let view = VarValues { + preprocessed: [&[], &[]], + main: [&node_values, &[]], + stage2: [¤t, &next], + publics: &publics, + is_first_row: W::ZERO, + is_last_row: is_last, + is_transition: W::ONE, + }; + let reference: Vec = expressions + .iter() + .flat_map(|expression| eval_ext_expr(expression, &view, ¶ms)) + .collect(); + // Appending must retain the user constraints that precede logUp. + let mut direct = vec![W::from_u8(3), W::from_u8(9)]; + logup_constraint_values( + &lookups, + &node_values, + ¤t, + &next, + &publics, + &delta, + is_last, + Val::from_u8(7), + 2, + group_size, + &mut direct, + ); + assert_eq!(&direct[..2], &[W::from_u8(3), W::from_u8(9)]); + assert_eq!(&direct[2..], reference); + assert_eq!(reference.len(), width); + for values in [&node_values, ¤t, &next, &publics] { + vector(out, values, encode); + } + vector(out, &delta, encode); + encode(out, is_last); + vector(out, &direct[2..], encode); + } + } + } +} + +#[test] +fn logup_snapshot() -> io::Result<()> { + assert_eq!(>::DIMENSION, 2); + assert_eq!(>::W, Val::from_u8(7)); + let mut out = b"Aiur grouped logup v1\n".to_vec(); + direct_cases(&mut out, |first, _| first, field); + direct_cases( + &mut out, + |first, second| ExtVal::new([first, second]), + extension, + ); + if let Some(path) = std::env::var_os("IX_LOGUP_SNAPSHOT") { + std::fs::write(path, out)?; + } + eprintln!( + "grouped logup: {} direct/reference cases", + 2 * COUNTS.len() * 9 * SEEDS + ); + Ok(()) +} + +fn flatten(values: &[ExtVal]) -> Vec { + values + .iter() + .flat_map(|value| value.as_basis_coefficients_slice().iter().copied()) + .collect() +} + +fn rows(circuit: usize, seed: usize) -> Vec>> { + let height = [1, 2, 4, 8, 4][circuit]; + let count = [0, 1, 9, 17, 25][circuit]; + (0..height) + .map(|row| { + (0..count) + .map(|lookup| Lookup { + multiplicity: scalar(seed + 3, row, lookup), + args: (0..ARITIES[(lookup + row) % ARITIES.len()]) + .map(|arg| scalar(seed + 7, lookup, arg + row * 31)) + .collect(), + }) + .collect() + }) + .collect() +} + +fn message(beta: ExtVal, gamma: ExtVal, args: &[Val]) -> ExtVal { + beta + args.iter().rev().fold(ExtVal::ZERO, |acc, &arg| acc * gamma + arg) +} + +#[test] +fn logup_stage_snapshot() -> io::Result<()> { + let mut out = b"Aiur grouped logup stages v1\n".to_vec(); + nat(&mut out, 27); + let mut row_count = 0; + for group_size in 0..=8 { + for seed in 0..3 { + let beta = ExtVal::new([Val::from_usize(5 + seed), Val::from_u8(13)]); + let gamma = ExtVal::new([Val::from_u8(7), Val::from_usize(11 + seed)]); + let initial = ExtVal::new([Val::from_u8(17), Val::from_usize(19 + seed)]); + let raw: Vec<_> = (0..5).map(|circuit| rows(circuit, seed)).collect(); + for row in raw.iter().flatten() { + for lookup in row { + assert!(message(beta, gamma, &lookup.args).try_inverse().is_some()); + } + } + let circuits: Vec<_> = + raw.iter().cloned().map(LookupValues::from_rows).collect(); + let (traces, accumulators) = LookupValues::stage_2_traces( + &circuits, + &[group_size; 5], + beta, + &gamma, + initial, + ); + nat(&mut out, group_size); + nat(&mut out, seed); + extension(&mut out, beta); + extension(&mut out, gamma); + extension(&mut out, initial); + nat(&mut out, raw.len()); + let mut entering = initial; + for ((rows, trace), &leaving) in + raw.iter().zip(&traces).zip(&accumulators) + { + nat(&mut out, rows.len()); + nat(&mut out, rows[0].len()); + nat(&mut out, trace.width); + vector(&mut out, &trace.values, extension); + extension(&mut out, leaving); + let normalizer = Val::from_usize(rows.len()) + * Val::two_adic_generator( + usize::try_from(rows.len().ilog2()).unwrap(), + ); + field(&mut out, normalizer); + let delta = flatten(&[(leaving - entering) * normalizer.inverse()]); + let publics = flatten(&[beta, gamma, entering, leaving]); + for (row_index, row) in rows.iter().enumerate() { + nat(&mut out, row.len()); + let mut node_values = Vec::new(); + let mut ids = Vec::new(); + for lookup in row { + field(&mut out, lookup.multiplicity); + vector(&mut out, &lookup.args, field); + let multiplicity = + NodeId(u32::try_from(node_values.len()).unwrap()); + node_values.push(lookup.multiplicity); + let mut args = Vec::new(); + for &arg in &lookup.args { + args.push(NodeId(u32::try_from(node_values.len()).unwrap())); + node_values.push(arg); + } + ids.push(Lookup { multiplicity, args }); + } + let start = row_index * trace.width; + let next_start = (row_index + 1) % rows.len() * trace.width; + let current = flatten(&trace.values[start..start + trace.width]); + let next = + flatten(&trace.values[next_start..next_start + trace.width]); + let is_last = + if row_index + 1 == rows.len() { normalizer } else { Val::ZERO }; + let mut equations = Vec::new(); + logup_constraint_values( + &ids, + &node_values, + ¤t, + &next, + &publics, + &delta, + is_last, + Val::from_u8(7), + 2, + group_size, + &mut equations, + ); + assert!(equations.iter().all(|&value| value == Val::ZERO)); + vector(&mut out, &equations, field); + row_count += 1; + } + entering = leaving; + } + } + } + assert_eq!(row_count, 513); + if let Some(path) = std::env::var_os("IX_LOGUP_STAGE_SNAPSHOT") { + std::fs::write(path, out)?; + } + eprintln!("grouped stages: 27 batches, 135 circuits, {row_count} rows"); + Ok(()) +} diff --git a/crates/aiur/src/vk_codec/tests/verifier_arithmetic.rs b/crates/aiur/src/vk_codec/tests/verifier_arithmetic.rs new file mode 100644 index 000000000..0438e5e76 --- /dev/null +++ b/crates/aiur/src/vk_codec/tests/verifier_arithmetic.rs @@ -0,0 +1,432 @@ +// Copyright (c) 2026 Argument Computer Corporation. +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Combined opened-row arithmetic using the actual graph sweep, direct +//! logUp evaluator and domain selectors. The private verifier's wiring, +//! Horner fold, quotient recombination and claim loop are reproduced here; +//! these deliberately constructed openings are not authenticated proofs. + +use super::*; +use multi_stark::{ + eval::VarValues, + lookup::logup_constraint_values, + p3_field::{ + BasedVectorSpace, Field, TwoAdicField, coset::TwoAdicMultiplicativeCoset, + }, + system::Circuit, + types::ExtVal, +}; +use p3_commit::{LagrangeSelectors, PolynomialSpace}; +use std::io; + +#[derive(Clone, Copy)] +struct Challenges { + beta: ExtVal, + gamma: ExtVal, + alpha: ExtVal, + zeta: ExtVal, +} + +struct Opening { + index: usize, + bits: usize, + main: [Vec; 2], + stage2: [Vec; 2], + preprocessed: Option<[Vec; 2]>, + quotient: Vec, + accumulator: ExtVal, +} + +struct Evaluation { + selectors: LagrangeSelectors, + publics: Vec, + delta: Vec, + nodes: Vec, + user: Vec, + lookups: Vec, + composition: ExtVal, + quotient: ExtVal, +} + +impl Evaluation { + fn accepts(&self) -> bool { + self.composition * self.selectors.inv_vanishing == self.quotient + } +} + +fn nat(out: &mut Vec, value: usize) { + out.extend(u64::try_from(value).unwrap().to_le_bytes()); +} + +fn field(out: &mut Vec, value: Val) { + out.extend(value.as_canonical_u64().to_le_bytes()); +} + +fn extension(out: &mut Vec, value: ExtVal) { + for &value in value.as_basis_coefficients_slice() { + field(out, value); + } +} + +fn extensions(out: &mut Vec, values: &[ExtVal]) { + nat(out, values.len()); + for &value in values { + extension(out, value); + } +} + +fn scalar(seed: usize, slot: usize, index: usize) -> Val { + let mut word = 0x79e3_4987_6a8b_051f_u64 + .wrapping_add(u64::try_from(seed).unwrap().wrapping_mul(0x74d8_b901)) + .wrapping_add(u64::try_from(slot).unwrap().wrapping_mul(0x5982_6407)) + .wrapping_add(u64::try_from(index).unwrap().wrapping_mul(0x8071_5823)); + for _ in 0..4 { + word ^= word << 13; + word ^= word >> 7; + word ^= word << 17; + } + Val::from_u64(word) +} + +fn value(seed: usize, slot: usize, index: usize) -> ExtVal { + ExtVal::new([ + scalar(seed, slot * 2, index), + scalar(seed, slot * 2 + 1, index), + ]) +} + +fn challenges(seed: usize) -> Challenges { + Challenges { + beta: value(seed, 40, 0), + gamma: value(seed, 41, 0), + alpha: match seed % 6 { + 0 => ExtVal::ZERO, + 1 => ExtVal::ONE, + 2 => ExtVal::NEG_ONE, + 3 => ExtVal::new([Val::ZERO, Val::ONE]), + _ => value(seed, 42, 0), + }, + zeta: value(seed, 43, 0), + } +} + +fn opening( + circuit: &Circuit, + index: usize, + bits: usize, + seed: usize, +) -> Opening { + let assignment = + |width, slot| (0..width).map(|index| value(seed, slot, index)).collect(); + Opening { + index, + bits, + main: [ + assignment(circuit.main_width, 0), + assignment(circuit.main_width, 1), + ], + stage2: [ + assignment(circuit.stage_2_width, 2), + assignment(circuit.stage_2_width, 3), + ], + preprocessed: (circuit.preprocessed_width != 0).then(|| { + [ + assignment(circuit.preprocessed_width, 4), + assignment(circuit.preprocessed_width, 5), + ] + }), + quotient: assignment(circuit.quotient_degree() * 2, 6), + accumulator: value(seed, 7, 0), + } +} + +fn evaluate( + circuit: &Circuit, + row: &Opening, + challenges: Challenges, + entering: ExtVal, +) -> Evaluation { + let domain = + TwoAdicMultiplicativeCoset::::new(Val::ONE, row.bits).unwrap(); + assert_ne!(domain.vanishing_poly_at_point(challenges.zeta), ExtVal::ZERO); + let selectors = domain.selectors_at_point(challenges.zeta); + let publics: Vec<_> = + [challenges.beta, challenges.gamma, entering, row.accumulator] + .iter() + .flat_map(|value| { + let coordinates: &[Val] = value.as_basis_coefficients_slice(); + coordinates.iter().copied().map(ExtVal::from) + }) + .collect(); + let norm = ExtVal::from( + (Val::from_usize(domain.size()) * Val::two_adic_generator(row.bits)) + .inverse(), + ); + let delta: Vec<_> = (0..2) + .map(|index| (publics[6 + index] - publics[4 + index]) * norm) + .collect(); + let empty = Vec::new(); + let preprocessed = row + .preprocessed + .as_ref() + .map_or([&empty, &empty], |rows| [&rows[0], &rows[1]]); + let view = VarValues { + preprocessed: [preprocessed[0], preprocessed[1]], + main: [&row.main[0], &row.main[1]], + stage2: [&row.stage2[0], &row.stage2[1]], + publics: &publics, + is_first_row: selectors.is_first_row, + is_last_row: selectors.is_last_row, + is_transition: selectors.is_transition, + }; + let mut nodes = Vec::new(); + circuit.graph.sweep(&view, &mut nodes); + let user = circuit.graph.constraint_values(&nodes); + let mut lookups = Vec::new(); + logup_constraint_values( + &circuit.graph.lookups, + &nodes, + view.stage2[0], + view.stage2[1], + &publics, + &delta, + selectors.is_last_row, + Val::from_u64(7), + 2, + circuit.lookup_group_size, + &mut lookups, + ); + assert_eq!(user.len() + lookups.len(), circuit.constraint_count()); + let composition = user + .iter() + .chain(&lookups) + .fold(ExtVal::ZERO, |acc, &value| acc * challenges.alpha + value); + let quotient = row + .quotient + .as_chunks::<2>() + .0 + .iter() + .zip(challenges.zeta.exp_power_of_2(row.bits).powers()) + .map(|(chunk, power)| { + power + * (chunk[0] + + chunk[1] + * >::ith_basis_element(1).unwrap()) + }) + .sum(); + Evaluation { + selectors, + publics, + delta, + nodes, + user, + lookups, + composition, + quotient, + } +} + +fn adjust( + circuit: &Circuit, + row: &mut Opening, + challenges: Challenges, + entering: ExtVal, + accepted: bool, +) { + let evaluated = evaluate(circuit, row, challenges, entering); + row.quotient[0] += evaluated.composition * evaluated.selectors.inv_vanishing + - evaluated.quotient; + if !accepted { + row.quotient[0] += ExtVal::ONE; + } + assert_eq!(evaluate(circuit, row, challenges, entering).accepts(), accepted); +} + +fn write_challenges(out: &mut Vec, challenges: Challenges) { + for value in + [challenges.beta, challenges.gamma, challenges.alpha, challenges.zeta] + { + extension(out, value); + } +} + +fn write_opening(out: &mut Vec, row: &Opening) { + nat(out, row.index); + nat(out, row.bits); + for pair in [&row.main, &row.stage2] { + for values in pair { + extensions(out, values); + } + } + out.push(u8::from(row.preprocessed.is_some())); + if let Some(rows) = &row.preprocessed { + for values in rows { + extensions(out, values); + } + } + extensions(out, &row.quotient); + extension(out, row.accumulator); +} + +fn write_evaluation(out: &mut Vec, evaluated: &Evaluation) { + for value in [ + evaluated.selectors.is_first_row, + evaluated.selectors.is_last_row, + evaluated.selectors.is_transition, + evaluated.selectors.inv_vanishing, + ] { + extension(out, value); + } + for values in [ + &evaluated.publics, + &evaluated.delta, + &evaluated.nodes, + &evaluated.user, + &evaluated.lookups, + ] { + extensions(out, values); + } + extension(out, evaluated.composition); + extension(out, evaluated.quotient); + out.push(u8::from(evaluated.accepts())); +} + +fn claim_message(challenges: Challenges, claim: &[Val]) -> ExtVal { + challenges.beta + + claim + .iter() + .rfold(ExtVal::ZERO, |acc, &value| acc * challenges.gamma + value) +} + +fn initial(challenges: Challenges, claims: &[Vec]) -> Option { + claims.iter().try_fold(ExtVal::ZERO, |acc, claim| { + Some(acc + claim_message(challenges, claim).try_inverse()?) + }) +} + +fn claims(seed: usize, count: usize) -> Vec> { + let lengths = [0, 1, 2, 3, 7, 16, 17]; + (0..count) + .map(|index| { + (0..lengths[(seed + index) % lengths.len()]) + .map(|arg| scalar(seed, 70 + index, arg)) + .collect() + }) + .collect() +} + +fn write_claims(out: &mut Vec, claims: &[Vec]) { + nat(out, claims.len()); + for claim in claims { + nat(out, claim.len()); + for &value in claim { + field(out, value); + } + } +} + +#[test] +fn verifier_arithmetic_snapshot() -> io::Result<()> { + let system = graph_tests::graph_system(); + let mut out = b"Aiur verifier arithmetic v1\n".to_vec(); + nat(&mut out, system.circuits.len()); + for circuit in &system.circuits { + let mut encoded = Vec::new(); + encode_circuit(&mut encoded, circuit); + nat(&mut out, encoded.len()); + out.extend(encoded); + } + nat(&mut out, system.circuits.len() * 8 * 12); + let mut nodes = 0; + for (index, circuit) in system.circuits.iter().enumerate() { + let largest = + 31 - usize::try_from(circuit.quotient_degree().trailing_zeros()).unwrap(); + for bits in [0, 1, 2, 4, 8, 16, 24, largest] { + for seed in 0..12 { + let challenges = challenges(seed); + let entering = value(seed, 50, 0); + let mut row = opening(circuit, index, bits, seed); + adjust(circuit, &mut row, challenges, entering, seed % 2 == 0); + let evaluated = evaluate(circuit, &row, challenges, entering); + nat(&mut out, seed); + write_challenges(&mut out, challenges); + extension(&mut out, entering); + write_opening(&mut out, &row); + write_evaluation(&mut out, &evaluated); + nodes += evaluated.nodes.len(); + } + } + } + // Direct native inverse calls also cover poles; the total Lean model + // rejects them before the private verifier's unguarded inverse call. + nat(&mut out, 12 * 6); + for seed in 0..12 { + for count in [0, 1, 2, 3, 7, 16] { + let mut challenges = challenges(seed); + let claims = claims(seed, count); + if seed % 3 == 0 && count != 0 { + challenges.beta -= claim_message(challenges, &claims[0]); + } + let accumulator = initial(challenges, &claims); + assert_eq!(accumulator.is_some(), seed % 3 != 0 || count == 0); + write_challenges(&mut out, challenges); + write_claims(&mut out, &claims); + for claim in &claims { + extension(&mut out, claim_message(challenges, claim)); + } + out.push(u8::from(accumulator.is_some())); + if let Some(accumulator) = accumulator { + extension(&mut out, accumulator); + } + } + } + // Vary the active order, chain length, final boundary and an interior + // quotient. Reusing the initial accumulator on every row changes these + // native node/public/lookup values even when alpha is zero or one. + nat(&mut out, 12 * 4); + for seed in 0..12 { + for count in [1, 2, 3, 10] { + let challenges = challenges(seed + 20); + let claims = claims(seed + 20, seed % 4); + let mut entering = initial(challenges, &claims).unwrap(); + write_challenges(&mut out, challenges); + write_claims(&mut out, &claims); + nat(&mut out, count); + let all_rows = seed % 3 != 1; + for position in 0..count { + let index = (position * 7 + seed) % system.circuits.len(); + let circuit = &system.circuits[index]; + let mut row = + opening(circuit, index, 2 + position % 7, seed + 20 + position); + if position + 1 == count && seed % 3 != 2 { + row.accumulator = ExtVal::ZERO; + } + adjust( + circuit, + &mut row, + challenges, + entering, + all_rows || position != count / 2, + ); + write_opening(&mut out, &row); + write_evaluation( + &mut out, + &evaluate(circuit, &row, challenges, entering), + ); + entering = row.accumulator; + } + out.push(u8::from(all_rows)); + if all_rows { + out.push(u8::from(entering == ExtVal::ZERO)); + } + } + } + assert_eq!((system.circuits.len(), nodes), (10, 32064)); + if let Some(path) = std::env::var_os("IX_VERIFIER_ARITHMETIC_SNAPSHOT") { + std::fs::write(path, &out)?; + } + eprintln!( + "verifier arithmetic: 960 openings, {nodes} node values, 72 claim cases, 48 accumulator chains" + ); + Ok(()) +} diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index 6f3a2c32d..eddfa929a 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -222,3 +222,43 @@ lake test -- --ignored ixvm These repairs and regression tests address the defects above. They do not establish complete compiler preservation or cryptographic soundness. + +## Checked proof components + +`IxAiurVerify` contains the migrated Aiur row, expression, key, verifier +arithmetic and FRI query components. `lake run check-aiur` checks their exact +theorem types, premise definitions, transitive axioms and project runtime +implementations against `Tests/Aiur/backend-foundation.txt`. The audit also +rejects a dependency on the independent `Ix.Compiler` library. Native/Lean +corpora check the executable models against the pinned backend; this is +regression evidence, separate from a universal native refinement theorem. + +Generic call emission now uses the six gap columns and derived child rank +described above. The call-order equation is proved identically zero; it is +not an extra native constraint. The corresponding allocation and extraction +results state their generic-layout premise explicitly. The component layout +pass is proved to preserve input arity and complete evaluator results, +including shared continuations, while its allocation model covers zero, +boundary and ordered call ranks. Extracting execution from physical rows in +all component modes remains the next proof obligation. + +Compiled-key comparison includes production lookup retuning with the key's +blowup parameter. Its total selector retains the machine-size and overflow +guards and the baseline FFT cost comparison. Retuning preserves the authored +graph, main width and preprocessed dimensions; the compared key includes the +resulting group and degree. The key corpus exercises three blowup settings, +function and memory circuits, both byte tables, empty circuits and validly +encoded altered keys. + +The source compatibility checks also cover strict effect order and explicit +returns. Array update evaluates its new value before the array expression, +consistently with the interpreter. Inlining leaves a normal call around a +callee with an explicit return, preserving its return boundary. These repairs +do not supply the still-missing general backward compiler theorem. + +These component theorems are conditional building blocks for IxVM consistency. +Public verifier acceptance still needs authenticated satisfying traces and +exact bounded lookup balance, compiler and guest reflection, general kernel +model preservation, and the quantitative cryptographic composition. The +runtime inventory names the native verifier interface; it does not establish +its soundness. diff --git a/lakefile.lean b/lakefile.lean index e2c94dad0..25f707248 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -260,6 +260,145 @@ lean_lib IxKernelConsistency where roots := #[`Ix.Kernel.Verify.Consistency] globs := #[.andSubmodules `Ix.Kernel.Verify.Consistency] +/- Compiler and verifier-binding components with an independent exact audit. -/ +lean_lib IxAiurVerify where + roots := #[`Ix.Aiur.Proofs] + globs := #[.andSubmodules `Ix.Aiur.Proofs] + +lean_exe «aiur-backend-tests» where + root := `Tests.Aiur.Backend + +lean_exe «aiur-bytecode-tests» where + root := `Tests.Aiur.BytecodeCompare + supportInterpreter := true + +lean_exe «aiur-dedup-tests» where + root := `Tests.Aiur.Dedup + supportInterpreter := true + +lean_exe «aiur-tail-match-tests» where + root := `Tests.Aiur.TailMatches + supportInterpreter := true + +lean_exe «aiur-source-value-tests» where + root := `Tests.Aiur.SourceValues + supportInterpreter := true + +lean_exe «aiur-hoisting-tests» where + root := `Tests.Aiur.Hoisting + supportInterpreter := true + +lean_exe «aiur-air-tests» where + root := `Tests.Aiur.AIRSemantics + +lean_exe «aiur-byte-gadget-tests» where + root := `Tests.Aiur.ByteGadgets + +lean_exe «aiur-lookup-shape-tests» where + root := `Tests.Aiur.LookupShapes + +lean_exe «aiur-lookup-budget-tests» where + root := `Tests.Aiur.LookupBudget + +lean_exe «aiur-selector-control-tests» where + root := `Tests.Aiur.SelectorControl + +lean_exe «aiur-operation-row-tests» where + root := `Tests.Aiur.OperationRows + +lean_exe «aiur-block-row-tests» where + root := `Tests.Aiur.BlockRows + +lean_exe «aiur-circuit-row-tests» where + root := `Tests.Aiur.CircuitRows + +lean_exe «aiur-memory-row-tests» where + root := `Tests.Aiur.MemoryRows + +lean_exe «aiur-trace-height-tests» where + root := `Tests.Aiur.TraceHeights + +lean_exe «aiur-expression-graph-tests» where + root := `Tests.Aiur.ExpressionGraph + +lean_exe «aiur-constant-degree-tests» where + root := `Tests.Aiur.ConstantDegree + +lean_exe «aiur-frontend-expression-tests» where + root := `Tests.Aiur.FrontendExpressions + +lean_exe «aiur-graph-compilation-tests» where + root := `Tests.Aiur.GraphCompilation + +lean_exe «aiur-operation-expression-tests» where + root := `Tests.Aiur.OperationExpressions + +lean_exe «aiur-block-expression-tests» where + root := `Tests.Aiur.BlockExpressions + +lean_exe «aiur-circuit-expression-tests» where + root := `Tests.Aiur.CircuitExpressions + +lean_exe «aiur-emission-check-tests» where + root := `Tests.Aiur.EmissionChecks + +lean_exe «aiur-key-codec-tests» where + root := `Tests.Aiur.KeyCodec + +lean_exe «aiur-compiled-key-tests» where + root := `Tests.Aiur.CompiledKey + +lean_exe «aiur-proof-codec-tests» where + root := `Tests.Aiur.ProofCodec + +lean_exe «aiur-proof-shape-tests» where + root := `Tests.Aiur.ProofShape + +lean_exe «aiur-extension-tests» where + root := `Tests.Aiur.Extension + +lean_exe «aiur-logup-tests» where + root := `Tests.Aiur.LogUp + +lean_exe «aiur-domain-tests» where + root := `Tests.Aiur.Domain + +lean_exe «aiur-verifier-arithmetic-tests» where + root := `Tests.Aiur.VerifierArithmetic + +lean_exe «aiur-transcript-tests» where + root := `Tests.Aiur.Transcript + +lean_exe «aiur-blake3-tests» where + root := `Tests.Aiur.Blake3 + +lean_exe «aiur-merkle-cap-tests» where + root := `Tests.Aiur.MerkleCap + +lean_exe «aiur-merkle-tests» where + root := `Tests.Aiur.Merkle + +lean_exe «aiur-pruned-merkle-tests» where + root := `Tests.Aiur.PrunedMerkle + +lean_exe «aiur-extension-mmcs-tests» where + root := `Tests.Aiur.ExtensionMmcs + +lean_exe «aiur-fri-domain-tests» where + root := `Tests.Aiur.FriDomain + +lean_exe «aiur-polynomial-tests» where + root := `Tests.Aiur.Polynomial + +lean_exe «aiur-interpolation-tests» where + root := `Tests.Aiur.Interpolation + +lean_exe «aiur-folding-tests» where + root := `Tests.Aiur.Folding + +lean_exe «aiur-fri-query-tests» where + root := `Tests.Aiur.FriQuery + section IxCompileVerify /- Formal verification of the Lean-to-Ixon compiler against the same @@ -489,3 +628,182 @@ script "check-kernel" (args) := do run "lake" #["-d", "Models/SetTheory", "build", "--wfail"] IO.println "Kernel certification checks passed." return 0 + +/-- Audit Aiur components and exercise their actual native verifier binding. -/ +script "check-aiur" := do + run "lake" #["build", "--wfail", "IxAiurVerify", "aiur-backend-tests", + "aiur-bytecode-tests", "aiur-dedup-tests", "aiur-tail-match-tests", "aiur-source-value-tests", + "aiur-hoisting-tests", "aiur-air-tests", "aiur-byte-gadget-tests", "aiur-lookup-shape-tests", + "aiur-lookup-budget-tests", "aiur-selector-control-tests", "aiur-operation-row-tests", + "aiur-block-row-tests", "aiur-circuit-row-tests", "aiur-memory-row-tests", "aiur-trace-height-tests", + "aiur-expression-graph-tests", "aiur-constant-degree-tests", "aiur-frontend-expression-tests", + "aiur-graph-compilation-tests", "aiur-operation-expression-tests", "aiur-block-expression-tests", + "aiur-circuit-expression-tests", "aiur-emission-check-tests", "aiur-key-codec-tests", "aiur-compiled-key-tests", + "aiur-proof-codec-tests", "aiur-proof-shape-tests", "aiur-extension-tests", "aiur-logup-tests", "aiur-domain-tests", + "aiur-verifier-arithmetic-tests", "aiur-transcript-tests", "aiur-blake3-tests", "aiur-merkle-cap-tests", + "aiur-merkle-tests", "aiur-pruned-merkle-tests", "aiur-extension-mmcs-tests", "aiur-fri-domain-tests", + "aiur-polynomial-tests", "aiur-interpolation-tests", "aiur-folding-tests", "aiur-fri-query-tests"] + let report ← IO.Process.output { + cmd := "lake", args := #["env", "lean", "-DwarningAsError=true", "Ix/Aiur/Proofs/Audit.lean"] } + unless report.exitCode == 0 do throw (IO.userError s!"{report.stdout}{report.stderr}") + let expectedPath := "Tests/Aiur/backend-foundation.txt" + let expected ← IO.FS.readFile expectedPath + unless report.stdout == expected do + IO.FS.withTempFile fun handle path => do + handle.putStr report.stdout + handle.flush + let child ← IO.Process.spawn { + cmd := "diff", args := #["-u", expectedPath, path.toString] + stdout := .inherit, stderr := .inherit } + let _ ← child.wait + throw (IO.userError "Aiur component report differs from the reviewed manifest") + let snapshots : Array (String × Array String × String) := #[ + ("aiur-bytecode-tests", #[], "Tests/Aiur/bytecode-compatibility.txt"), + ("aiur-dedup-tests", #["--snapshot"], "Tests/Aiur/dedup-compatibility.txt"), + ("aiur-tail-match-tests", #[], "Tests/Aiur/tail-match-compatibility.txt"), + ("aiur-source-value-tests", #[], "Tests/Aiur/source-value-compatibility.txt")] + for (program, args, comparisonPath) in snapshots do + let comparison ← IO.Process.output { cmd := s!".lake/build/bin/{program}", args } + unless comparison.exitCode == 0 && comparison.stderr.isEmpty do + throw (IO.userError s!"{comparison.stdout}{comparison.stderr}") + unless comparison.stdout == (← IO.FS.readFile comparisonPath) do + IO.FS.withTempFile fun handle path => do + handle.putStr comparison.stdout + handle.flush + let child ← IO.Process.spawn { + cmd := "diff", args := #["-u", comparisonPath, path.toString] + stdout := .inherit, stderr := .inherit } + let _ ← child.wait + throw (IO.userError s!"{program} differs from its original native snapshot") + run ".lake/build/bin/aiur-dedup-tests" + run ".lake/build/bin/aiur-hoisting-tests" + run ".lake/build/bin/aiur-air-tests" + run ".lake/build/bin/aiur-constant-degree-tests" + IO.FS.withTempDir fun directory => do + let snapshot := directory / "native-byte-gadgets.bin" + let shapeSnapshot := directory / "native-lookup-shapes.bin" + let budgetSnapshot := directory / "native-lookup-budget.bin" + let selectorSnapshot := directory / "native-selector-control.bin" + let operationSnapshot := directory / "native-operation-rows.bin" + let blockSnapshot := directory / "native-block-rows.bin" + let circuitSnapshot := directory / "native-circuit-rows.bin" + let memorySnapshot := directory / "native-memory-rows.bin" + let traceHeightSnapshot := directory / "native-trace-heights.bin" + let graphShapeSnapshot := directory / "native-graph-shapes.bin" + let expressionGraphSnapshot := directory / "native-expression-graphs.bin" + let constantDegreeSnapshot := directory / "native-constant-degree-rows.bin" + let frontendSnapshot := directory / "native-frontend-expressions.bin" + let compilationSnapshot := directory / "native-graph-compilation.bin" + let operationExpressionSnapshot := directory / "native-operation-expressions.bin" + let blockExpressionSnapshot := directory / "native-block-expressions.bin" + let circuitExpressionSnapshot := directory / "native-circuit-expressions.bin" + let emissionCheckSnapshot := directory / "native-emission-checks.bin" + let keyCodecSnapshot := directory / "native-key-codec.bin" + let compiledKeySnapshot := directory / "native-compiled-keys.bin" + let proofCodecSnapshot := directory / "native-proof-codec.bin" + let proofShapeSnapshot := directory / "native-proof-shapes.bin" + let extensionSnapshot := directory / "native-extension-arithmetic.bin" + let extensionGraphSnapshot := directory / "native-extension-graphs.bin" + let logupSnapshot := directory / "native-logup.bin" + let logupStageSnapshot := directory / "native-logup-stages.bin" + let domainSnapshot := directory / "native-domains.bin" + let quotientSnapshot := directory / "native-quotients.bin" + let verifierArithmeticSnapshot := directory / "native-verifier-arithmetic.bin" + let transcriptSnapshot := directory / "native-transcript.bin" + let blake3Snapshot := directory / "native-blake3.bin" + let merkleCapSnapshot := directory / "native-merkle-cap.bin" + let merklePathSnapshot := directory / "native-merkle-path.bin" + let prunedMerkleSnapshot := directory / "native-pruned-merkle.bin" + let extensionMmcsSnapshot := directory / "native-extension-mmcs.bin" + let friDomainSnapshot := directory / "native-fri-domains.bin" + let polynomialSnapshot := directory / "native-polynomials.bin" + let interpolationSnapshot := directory / "native-interpolation.bin" + let foldingSnapshot := directory / "native-folding.bin" + let friQuerySnapshot := directory / "native-fri-query.bin" + let exporter ← IO.Process.spawn { + cmd := "cargo" + args := #["test", "--locked", "--release", "-p", "aiur", + "_snapshot"] + env := #[("IX_BYTE_GADGET_SNAPSHOT", some snapshot.toString), + ("IX_LOOKUP_SHAPE_SNAPSHOT", some shapeSnapshot.toString), + ("IX_LOOKUP_BUDGET_SNAPSHOT", some budgetSnapshot.toString), + ("IX_SELECTOR_CONTROL_SNAPSHOT", some selectorSnapshot.toString), + ("IX_OPERATION_ROW_SNAPSHOT", some operationSnapshot.toString), + ("IX_BLOCK_ROW_SNAPSHOT", some blockSnapshot.toString), + ("IX_CIRCUIT_ROW_SNAPSHOT", some circuitSnapshot.toString), + ("IX_MEMORY_ROW_SNAPSHOT", some memorySnapshot.toString), + ("IX_FIXED_TRACE_HEIGHT_SNAPSHOT", some traceHeightSnapshot.toString), + ("IX_GRAPH_SHAPE_SNAPSHOT", some graphShapeSnapshot.toString), + ("IX_EXPRESSION_GRAPH_SNAPSHOT", some expressionGraphSnapshot.toString), + ("IX_CONSTANT_DEGREE_ROW_SNAPSHOT", some constantDegreeSnapshot.toString), + ("IX_FRONTEND_EXPRESSION_SNAPSHOT", some frontendSnapshot.toString), + ("IX_GRAPH_COMPILATION_SNAPSHOT", some compilationSnapshot.toString), + ("IX_OPERATION_EXPRESSION_SNAPSHOT", some operationExpressionSnapshot.toString), + ("IX_BLOCK_EXPRESSION_SNAPSHOT", some blockExpressionSnapshot.toString), + ("IX_CIRCUIT_EXPRESSION_SNAPSHOT", some circuitExpressionSnapshot.toString), + ("IX_EMISSION_CHECK_SNAPSHOT", some emissionCheckSnapshot.toString), + ("IX_KEY_CODEC_SNAPSHOT", some keyCodecSnapshot.toString), + ("IX_COMPILED_KEY_SNAPSHOT", some compiledKeySnapshot.toString), + ("IX_PROOF_CODEC_SNAPSHOT", some proofCodecSnapshot.toString), + ("IX_PROOF_SHAPE_SNAPSHOT", some proofShapeSnapshot.toString), + ("IX_EXTENSION_ARITHMETIC_SNAPSHOT", some extensionSnapshot.toString), + ("IX_EXTENSION_GRAPH_SNAPSHOT", some extensionGraphSnapshot.toString), + ("IX_LOGUP_SNAPSHOT", some logupSnapshot.toString), + ("IX_LOGUP_STAGE_SNAPSHOT", some logupStageSnapshot.toString), + ("IX_DOMAIN_SNAPSHOT", some domainSnapshot.toString), + ("IX_QUOTIENT_SNAPSHOT", some quotientSnapshot.toString), + ("IX_VERIFIER_ARITHMETIC_SNAPSHOT", some verifierArithmeticSnapshot.toString), + ("IX_TRANSCRIPT_SNAPSHOT", some transcriptSnapshot.toString), + ("IX_BLAKE3_SNAPSHOT", some blake3Snapshot.toString), + ("IX_MERKLE_CAP_SNAPSHOT", some merkleCapSnapshot.toString), + ("IX_MERKLE_PATH_SNAPSHOT", some merklePathSnapshot.toString), + ("IX_PRUNED_MERKLE_SNAPSHOT", some prunedMerkleSnapshot.toString), + ("IX_EXTENSION_MMCS_SNAPSHOT", some extensionMmcsSnapshot.toString), + ("IX_FRI_DOMAIN_SNAPSHOT", some friDomainSnapshot.toString), + ("IX_POLYNOMIAL_SNAPSHOT", some polynomialSnapshot.toString), + ("IX_INTERPOLATION_SNAPSHOT", some interpolationSnapshot.toString), + ("IX_FOLDING_SNAPSHOT", some foldingSnapshot.toString), + ("IX_FRI_QUERY_SNAPSHOT", some friQuerySnapshot.toString)] + stdout := .inherit + stderr := .inherit } + unless (← exporter.wait) == 0 do + throw (IO.userError "native Aiur component snapshot export failed") + run ".lake/build/bin/aiur-byte-gadget-tests" #[snapshot.toString] + run ".lake/build/bin/aiur-lookup-shape-tests" #[shapeSnapshot.toString] + run ".lake/build/bin/aiur-lookup-budget-tests" #[budgetSnapshot.toString] + run ".lake/build/bin/aiur-selector-control-tests" #[selectorSnapshot.toString] + run ".lake/build/bin/aiur-operation-row-tests" #[operationSnapshot.toString, constantDegreeSnapshot.toString] + run ".lake/build/bin/aiur-frontend-expression-tests" #[frontendSnapshot.toString] + run ".lake/build/bin/aiur-graph-compilation-tests" #[compilationSnapshot.toString] + run ".lake/build/bin/aiur-operation-expression-tests" #[operationExpressionSnapshot.toString] + run ".lake/build/bin/aiur-block-expression-tests" #[blockExpressionSnapshot.toString] + run ".lake/build/bin/aiur-circuit-expression-tests" #[circuitExpressionSnapshot.toString] + run ".lake/build/bin/aiur-emission-check-tests" #[emissionCheckSnapshot.toString] + run ".lake/build/bin/aiur-key-codec-tests" #[keyCodecSnapshot.toString] + run ".lake/build/bin/aiur-compiled-key-tests" #[compiledKeySnapshot.toString] + run ".lake/build/bin/aiur-proof-codec-tests" #[proofCodecSnapshot.toString] + run ".lake/build/bin/aiur-proof-shape-tests" #[proofShapeSnapshot.toString] + run ".lake/build/bin/aiur-extension-tests" #[extensionSnapshot.toString, extensionGraphSnapshot.toString] + run ".lake/build/bin/aiur-logup-tests" #[logupSnapshot.toString, logupStageSnapshot.toString] + run ".lake/build/bin/aiur-domain-tests" #[domainSnapshot.toString, quotientSnapshot.toString] + run ".lake/build/bin/aiur-verifier-arithmetic-tests" #[verifierArithmeticSnapshot.toString] + run ".lake/build/bin/aiur-transcript-tests" #[transcriptSnapshot.toString] + run ".lake/build/bin/aiur-blake3-tests" #[blake3Snapshot.toString] + run ".lake/build/bin/aiur-merkle-cap-tests" #[merkleCapSnapshot.toString] + run ".lake/build/bin/aiur-merkle-tests" #[merklePathSnapshot.toString] + run ".lake/build/bin/aiur-pruned-merkle-tests" #[prunedMerkleSnapshot.toString] + run ".lake/build/bin/aiur-extension-mmcs-tests" #[extensionMmcsSnapshot.toString] + run ".lake/build/bin/aiur-fri-domain-tests" #[friDomainSnapshot.toString] + run ".lake/build/bin/aiur-polynomial-tests" #[polynomialSnapshot.toString] + run ".lake/build/bin/aiur-interpolation-tests" #[interpolationSnapshot.toString] + run ".lake/build/bin/aiur-folding-tests" #[foldingSnapshot.toString] + run ".lake/build/bin/aiur-fri-query-tests" #[friQuerySnapshot.toString] + run ".lake/build/bin/aiur-block-row-tests" #[blockSnapshot.toString] + run ".lake/build/bin/aiur-circuit-row-tests" #[circuitSnapshot.toString] + run ".lake/build/bin/aiur-memory-row-tests" #[memorySnapshot.toString] + run ".lake/build/bin/aiur-trace-height-tests" #[traceHeightSnapshot.toString] + run ".lake/build/bin/aiur-expression-graph-tests" #[graphShapeSnapshot.toString, expressionGraphSnapshot.toString] + run ".lake/build/bin/aiur-backend-tests" + IO.println "Aiur component checks passed: exact proof/runtime boundaries, compiler compatibility and native binding." + return 0 + From 033e84d99188f8a884ed984a597cbf57913d48f0 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Sun, 13 Sep 2026 23:05:15 -0400 Subject: [PATCH 22/30] Prove optimized AIR execution from physical traces --- Ix/Aiur/CompiledKey.lean | 9 +- Ix/Aiur/CompiledVerifier.lean | 11 +- Ix/Aiur/Proofs/Audit.lean | 22 +- Ix/Aiur/Proofs/BlockAllocation.lean | 14 +- Ix/Aiur/Proofs/BlockCompletion.lean | 3 +- Ix/Aiur/Proofs/BlockExpressions.lean | 3 +- Ix/Aiur/Proofs/BlockReflection.lean | 5 +- Ix/Aiur/Proofs/BlockRowCalls.lean | 92 +- Ix/Aiur/Proofs/BlockRowInputs.lean | 4 +- Ix/Aiur/Proofs/BlockRows.lean | 3 +- Ix/Aiur/Proofs/BranchlessSlots.lean | 4 +- Ix/Aiur/Proofs/CallInventory.lean | 81 +- Ix/Aiur/Proofs/CheckedCircuit.lean | 2 +- Ix/Aiur/Proofs/CircuitExpressions.lean | 5 +- Ix/Aiur/Proofs/CircuitReflection.lean | 5 +- Ix/Aiur/Proofs/CircuitRowCounts.lean | 25 +- Ix/Aiur/Proofs/CircuitRowMembers.lean | 28 +- Ix/Aiur/Proofs/CircuitRowQueries.lean | 3 +- Ix/Aiur/Proofs/CircuitRowReturns.lean | 9 +- Ix/Aiur/Proofs/CircuitRows.lean | 5 +- Ix/Aiur/Proofs/CircuitTableExecution.lean | 2 +- Ix/Aiur/Proofs/CompiledKey.lean | 48 +- Ix/Aiur/Proofs/CompilerBranches.lean | 18 +- Ix/Aiur/Proofs/ComponentCalls.lean | 271 ++ Ix/Aiur/Proofs/ComponentCircuitCounts.lean | 188 + Ix/Aiur/Proofs/ComponentCircuitExecution.lean | 173 + .../Proofs/ComponentCircuitExpressions.lean | 73 + Ix/Aiur/Proofs/ComponentCircuitMembers.lean | 147 + Ix/Aiur/Proofs/ComponentCircuitQueries.lean | 197 ++ .../Proofs/ComponentCircuitReflection.lean | 202 ++ Ix/Aiur/Proofs/ComponentCircuitRows.lean | 110 + Ix/Aiur/Proofs/ComponentCompiledRows.lean | 111 + Ix/Aiur/Proofs/ComponentEncodedExecution.lean | 183 + Ix/Aiur/Proofs/ComponentExecution.lean | 177 + Ix/Aiur/Proofs/ComponentFunctionRows.lean | 71 + Ix/Aiur/Proofs/ComponentGlobalExecution.lean | 155 + Ix/Aiur/Proofs/ComponentTableExecution.lean | 181 + Ix/Aiur/Proofs/EmissionAllocation.lean | 42 +- Ix/Aiur/Proofs/EmissionInputs.lean | 19 +- Ix/Aiur/Proofs/FunctionRows.lean | 15 +- Ix/Aiur/Proofs/GraphLookupTraces.lean | 168 + Ix/Aiur/Proofs/GraphTraces.lean | 208 ++ Ix/Aiur/Proofs/InactiveRows.lean | 8 +- Ix/Aiur/Proofs/LookupLayout.lean | 86 +- Ix/Aiur/Proofs/NativeCircuitExecution.lean | 150 + Ix/Aiur/Proofs/NativeCompiledRows.lean | 198 ++ Ix/Aiur/Proofs/NativeExecutionAudit.lean | 311 ++ Ix/Aiur/Proofs/NativeTraceExecution.lean | 165 + Ix/Aiur/Proofs/NativeTraceMetadata.lean | 118 + Ix/Aiur/Proofs/OperationDegrees.lean | 8 +- Ix/Aiur/Proofs/OperationExpressions.lean | 90 +- Ix/Aiur/Proofs/OperationReflection.lean | 31 +- Ix/Aiur/Proofs/OperationRows.lean | 66 +- Ix/Aiur/Proofs/OperationSequences.lean | 22 +- Ix/Aiur/Proofs/SystemGraphExecution.lean | 128 + Ix/Aiur/Proofs/TableGraphTraces.lean | 187 + Tests/Aiur/BlockExpressions.lean | 2 +- Tests/Aiur/BlockRows.lean | 2 +- Tests/Aiur/CircuitRows.lean | 2 +- Tests/Aiur/CompiledKey.lean | 37 +- Tests/Aiur/EmissionChecks.lean | 2 +- Tests/Aiur/ProductionKey.lean | 41 + Tests/Aiur/backend-foundation-review.md | 52 + Tests/Aiur/backend-foundation.txt | 3060 +++++++++++++++-- .../src/constraints/tests/compiled_keys.rs | 131 +- docs/aiur-soundness.md | 35 +- lakefile.lean | 6 +- 67 files changed, 7431 insertions(+), 599 deletions(-) create mode 100644 Ix/Aiur/Proofs/ComponentCalls.lean create mode 100644 Ix/Aiur/Proofs/ComponentCircuitCounts.lean create mode 100644 Ix/Aiur/Proofs/ComponentCircuitExecution.lean create mode 100644 Ix/Aiur/Proofs/ComponentCircuitExpressions.lean create mode 100644 Ix/Aiur/Proofs/ComponentCircuitMembers.lean create mode 100644 Ix/Aiur/Proofs/ComponentCircuitQueries.lean create mode 100644 Ix/Aiur/Proofs/ComponentCircuitReflection.lean create mode 100644 Ix/Aiur/Proofs/ComponentCircuitRows.lean create mode 100644 Ix/Aiur/Proofs/ComponentCompiledRows.lean create mode 100644 Ix/Aiur/Proofs/ComponentEncodedExecution.lean create mode 100644 Ix/Aiur/Proofs/ComponentExecution.lean create mode 100644 Ix/Aiur/Proofs/ComponentFunctionRows.lean create mode 100644 Ix/Aiur/Proofs/ComponentGlobalExecution.lean create mode 100644 Ix/Aiur/Proofs/ComponentTableExecution.lean create mode 100644 Ix/Aiur/Proofs/GraphLookupTraces.lean create mode 100644 Ix/Aiur/Proofs/GraphTraces.lean create mode 100644 Ix/Aiur/Proofs/NativeCircuitExecution.lean create mode 100644 Ix/Aiur/Proofs/NativeCompiledRows.lean create mode 100644 Ix/Aiur/Proofs/NativeExecutionAudit.lean create mode 100644 Ix/Aiur/Proofs/NativeTraceExecution.lean create mode 100644 Ix/Aiur/Proofs/NativeTraceMetadata.lean create mode 100644 Ix/Aiur/Proofs/SystemGraphExecution.lean create mode 100644 Ix/Aiur/Proofs/TableGraphTraces.lean create mode 100644 Tests/Aiur/ProductionKey.lean diff --git a/Ix/Aiur/CompiledKey.lean b/Ix/Aiur/CompiledKey.lean index 310c7df77..6c10fe3c5 100644 --- a/Ix/Aiur/CompiledKey.lean +++ b/Ix/Aiur/CompiledKey.lean @@ -3,7 +3,7 @@ Copyright (c) 2026 Argument Computer Corporation. SPDX-License-Identifier: MIT OR Apache-2.0 -/ -import Ix.Aiur.Proofs.CompiledCircuitRows +import Ix.Aiur.Proofs.NativeCompiledRows import Ix.Aiur.Proofs.CircuitCompletion import Ix.Aiur.Proofs.ByteColumns import Ix.Aiur.LookupGroups @@ -60,7 +60,7 @@ def circuit (logBlowup mainWidth preprocessedWidth preprocessedHeight groupSize if result.valid then some result else none def functionCircuit (logBlowup : Nat) (program : Bytecode.Toplevel) (source : Bytecode.Circuit) : Option KeyCodec.Circuit := do - let compiled ← compileCircuit (circuitWidths source) program source + let compiled ← compileNativeCircuit (circuitWidths source) program source let groupSize := if compiled.emission.branchless && 2 ≤ compiled.emission.lookups.length then 2 else 1 circuit logBlowup source.layout.width 0 0 groupSize compiled.base @@ -87,7 +87,8 @@ def preprocessedIndices (program : Bytecode.Toplevel) : List (Option Nat) := List.replicate (program.circuits.size + program.memorySizes.size) none ++ [some 0, some 1] def check (program : Bytecode.Toplevel) (key : KeyCodec.Key) : Bool := - circuits key.parameters.logBlowup program == some key.circuits && - key.preprocessedIndices == preprocessedIndices program + (program.callComponents.isEmpty || program.validCallComponents) && + (circuits key.parameters.logBlowup program == some key.circuits && + key.preprocessedIndices == preprocessedIndices program) end Aiur.NativeAIR.CompiledKey diff --git a/Ix/Aiur/CompiledVerifier.lean b/Ix/Aiur/CompiledVerifier.lean index 1b31df6b0..18c55eaa8 100644 --- a/Ix/Aiur/CompiledVerifier.lean +++ b/Ix/Aiur/CompiledVerifier.lean @@ -30,13 +30,20 @@ theorem CompiledBackend.circuits_bound {selection : Selection} (backend : Compil some backend.keyData.circuits := by have checked := backend.graphsChecked simp only [NativeAIR.CompiledKey.check, Bool.and_eq_true, beq_iff_eq] at checked - exact checked.1 + exact checked.2.1 theorem CompiledBackend.preprocessed_indices {selection : Selection} (backend : CompiledBackend selection) : backend.keyData.preprocessedIndices = NativeAIR.CompiledKey.preprocessedIndices backend.compiled.bytecode := by have checked := backend.graphsChecked simp only [NativeAIR.CompiledKey.check, Bool.and_eq_true, beq_iff_eq] at checked - exact checked.2 + exact checked.2.2 + +theorem CompiledBackend.components_checked {selection : Selection} (backend : CompiledBackend selection) : + backend.compiled.bytecode.callComponents.isEmpty = true ∨ + backend.compiled.bytecode.validCallComponents = true := by + have checked := backend.graphsChecked + simp only [NativeAIR.CompiledKey.check, Bool.and_eq_true, Bool.or_eq_true] at checked + exact checked.1 theorem verifyCompiled_success {selection : Selection} {backend : CompiledBackend selection} {input : Array G} {bytes : ByteArray} (accepted : verifyCompiled backend input bytes = .ok ()) : diff --git a/Ix/Aiur/Proofs/Audit.lean b/Ix/Aiur/Proofs/Audit.lean index d7c9ebe54..76f3a2cc7 100644 --- a/Ix/Aiur/Proofs/Audit.lean +++ b/Ix/Aiur/Proofs/Audit.lean @@ -41,6 +41,7 @@ import Ix.Aiur.Proofs.CircuitCompletion import Ix.Aiur.Proofs.CheckedCircuit import Ix.Aiur.Proofs.KeyArtifact import Ix.Aiur.Proofs.CompiledKey +import Ix.Aiur.Proofs.NativeExecutionAudit import Ix.Aiur.Proofs.ShapedVerifier import Ix.Aiur.Proofs.ExtensionField import Ix.Aiur.Proofs.LogUpAccumulator @@ -3364,10 +3365,10 @@ def friQueryPremises : Array Lean.Name := #[ `Aiur.NativeAIR.FriQuery.run, `Aiur.NativeAIR.FriQuery.check] -/-! The migration retains generic dynamic-rank extraction and makes that -layout premise explicit. Component relayout preserves evaluator behavior; -physical extraction for every component rank mode is a separate obligation. -Lookup retuning preserves authored fields and is included in key equality. -/ +/-! Generic defaults remain available. The native execution roots derive +the selected rank policy from the checked component table. Relayout preserves +evaluator behavior; lookup retuning preserves authored fields and participates +in the enforced key comparison. -/ def optimizedLayoutRoots : Array Lean.Name := #[ `Aiur.AIR.callOrderConstraint_derived, `Aiur.AIR.EquationAvailable.mono, @@ -3439,7 +3440,7 @@ def optimizedLayoutPremises : Array Lean.Name := #[ `Aiur.NativeAIR.LookupGroups.retune, `Aiur.NativeAIR.LookupGroups.AuthoredFields] -def roots : Array Lean.Name := optimizedLayoutRoots ++ #[ +def roots : Array Lean.Name := nativeExecutionRoots ++ optimizedLayoutRoots ++ #[ `Aiur.G.ofNat_n, `Aiur.G.mul_one, `Aiur.G.mul_zero, `Aiur.AIR.inactive_multiplicity_zero, `Aiur.AIR.nonzero_multiplicity_active, `Aiur.AIR.active_satisfies, @@ -3477,7 +3478,7 @@ def roots : Array Lean.Name := optimizedLayoutRoots ++ #[ selectorControlRoots ++ operationRowRoots ++ blockRowRoots ++ querySlotRoots ++ circuitRowRoots ++ rowCountRoots ++ circuitTableRoots ++ branchlessRoots ++ circuitTraceRoots ++ circuitMembershipRoots ++ lookupLayoutRoots ++ memoryColumnRoots ++ byteColumnRoots ++ expressionGraphRoots ++ frontendExpressionRoots ++ graphCompilationRoots ++ operationExpressionRoots ++ blockCircuitRoots ++ allocationRoots ++ circuitAllocationRoots ++ circuitCompletionRoots ++ checkedCircuitRoots ++ keyCodecRoots ++ compiledKeyRoots ++ proofAcceptanceRoots ++ extensionRoots ++ logUpRoots ++ domainRoots ++ verifierArithmeticRoots ++ transcriptRoots ++ blake3Roots ++ merkleCapRoots ++ merkleRoots ++ prunedMerkleRoots ++ extensionMmcsRoots ++ friDomainRoots ++ polynomialRoots ++ interpolationRoots ++ foldingRoots ++ friQueryRoots -def premises : Array Lean.Name := optimizedLayoutPremises ++ #[ +def premises : Array Lean.Name := nativeExecutionPremises ++ optimizedLayoutPremises ++ #[ `Aiur.AIR.activityConstraint, `Aiur.Bytecode.Eval.SameCode.mk, `Aiur.finishCompilation, @@ -3799,7 +3800,12 @@ run_cmd do throwError "Aiur consistency components depend on the excluded compiler library" for root in roots do let some info := env.checked.get.find? root | throwError "C8 component audit: missing root {root}" - let expected := if optimizedLayoutRoots.contains root then + let expected := if nativeExecutionRoots.contains root then + if nativeExecutionAxiomFreeRoots.contains root then #[] + else if nativeExecutionPropextRoots.contains root then #[``propext] + else if nativeExecutionQuotRoots.contains root then #[``propext, ``Quot.sound] + else #[``propext, ``Classical.choice, ``Quot.sound] + else if optimizedLayoutRoots.contains root then if root == `Aiur.NativeAIR.LookupGroups.withGroup_authored then #[] else if optimizedLayoutPropextRoots.contains root then #[``propext] else if optimizedLayoutQuotRoots.contains root then #[``propext, ``Quot.sound] @@ -4030,4 +4036,4 @@ run_cmd do logInfo m!"C8 component ROOTS {roots.size}; LOGICAL DECLARATIONS {logical.size}; WITH RUNTIME {reachable.length}" logInfo m!"IX RUNTIME EXTERNS {externs}\nPARTIAL OPAQUE SOURCES {partials}\nOTHER UNSAFE RUNTIME {runtime}\nRECURSION WORKERS {workers.size}" logInfo "Runtime diagnostics cover Ix modules, including private constants. Lean/Std runtime primitives remain an external execution boundary. Partial opaque implementations are inventoried, not proved to refine their logical defaults." - logInfo "The runtime inventory and theorem premises are frozen separately. These roots do not establish full compiler/AIR reflection or public certified claim semantics." + logInfo "The runtime inventory and theorem premises are frozen separately. These roots do not establish compiler-to-source semantic reflection, authenticated proof traces or public certified claim semantics." diff --git a/Ix/Aiur/Proofs/BlockAllocation.lean b/Ix/Aiur/Proofs/BlockAllocation.lean index b3d303920..52d54d77b 100644 --- a/Ix/Aiur/Proofs/BlockAllocation.lean +++ b/Ix/Aiur/Proofs/BlockAllocation.lean @@ -16,15 +16,15 @@ open OpEmitter Aiur.Bytecode Concrete.Bytecode theorem branchRows_layout {selectors : Array Expr} {context : Context} {matched : RowExpr} {rows : Array RowExpr} {column lookup : Nat} {branches : Array (G × Block)} {fallback : Option Block} {emission : Emission} (index : Nat) (initial : LayoutMState) (base : Nat) - (generic : initial.callRanks = #[]) + (generic : initial.callRanks = context.callRanks) (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) (emitted : branchRows selectors context matched rows column lookup branches fallback = some emission) (caseSound : ∀ pair ∈ branches.toList, ∀ entry result state, - state.callRanks = #[] → rowDegrees rows = state.degrees → column = base + state.functionLayout.auxiliaries → + state.callRanks = context.callRanks → rowDegrees rows = state.degrees → column = base + state.functionLayout.auxiliaries → emitBlock selectors context entry rows column lookup pair.2 = some result → result.column = base + ((blockLayout pair.2).run state).2.functionLayout.auxiliaries) (defaultSound : ∀ block, fallback = some block → ∀ entry result state, - state.callRanks = #[] → rowDegrees rows = state.degrees → column + branches.size = base + state.functionLayout.auxiliaries → + state.callRanks = context.callRanks → rowDegrees rows = state.degrees → column + branches.size = base + state.functionLayout.auxiliaries → emitBlock selectors context entry rows (column + branches.size) lookup block = some result → result.column = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) : ((ctrlLayout (.match index branches fallback)).run initial).2.degrees = rowDegrees emission.values ∧ @@ -39,7 +39,7 @@ theorem branchRows_layout {selectors : Array Expr} {context : Context} {matched rename_i defaults defaultsEmitted cases emitted have caseEffects : List.Forall₂ (fun pair result => ∀ state : LayoutMState, - state.callRanks = #[] → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → + state.callRanks = context.callRanks → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → result.column = base + ((blockLayout pair.2).run state).2.functionLayout.auxiliaries) branches.toList cases := by apply AIR.mapM_forall₂ casesEmitted @@ -57,7 +57,7 @@ theorem branchRows_layout {selectors : Array Expr} {context : Context} {matched exact caseSound pair member entry body state stateGeneric (aligned.trans degrees.symm) (by rw [auxiliaries]; exact cursor) bodyEmitted have defaultEffects : List.Forall₂ (fun block result => ∀ state : LayoutMState, - state.callRanks = #[] → state.degrees = initial.degrees → + state.callRanks = context.callRanks → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + branches.size → result.column = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) fallback.toList defaults := by @@ -101,7 +101,7 @@ mutual theorem emitCtrl_layout {selectors : Array Expr} {context : Context} {incoming : Expr} {rows : Array RowExpr} {column lookup : Nat} (ctrl : Ctrl) {emission : Emission} (initial : LayoutMState) (base : Nat) (valid : DegreeValid rows) - (generic : initial.callRanks = #[]) + (generic : initial.callRanks = context.callRanks) (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) (emitted : emitCtrl selectors context incoming rows column lookup ctrl = some emission) : ((ctrlLayout ctrl).run initial).2.degrees = rowDegrees emission.values ∧ @@ -178,7 +178,7 @@ decreasing_by theorem emitBlock_layout {selectors : Array Expr} {context : Context} {incoming : Expr} {rows : Array RowExpr} {column lookup : Nat} (block : Block) {emission : Emission} (initial : LayoutMState) (base : Nat) (valid : DegreeValid rows) - (generic : initial.callRanks = #[]) + (generic : initial.callRanks = context.callRanks) (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) (emitted : emitBlock selectors context incoming rows column lookup block = some emission) : ((blockLayout block).run initial).2.degrees = rowDegrees emission.values ∧ diff --git a/Ix/Aiur/Proofs/BlockCompletion.lean b/Ix/Aiur/Proofs/BlockCompletion.lean index 17bb5bb60..642cd4248 100644 --- a/Ix/Aiur/Proofs/BlockCompletion.lean +++ b/Ix/Aiur/Proofs/BlockCompletion.lean @@ -160,7 +160,8 @@ theorem emitBlock_defined (selectors : Array Expr) (context : Context) (incoming ∃ emission, emitBlock selectors context incoming rows column lookup block = some emission ∧ emission.YieldShape size := by obtain ⟨next, checkedOps, checkedCtrl⟩ := Block.emissionChecks_parts checked obtain ⟨entry, selected⟩ := blockSelector_defined selectors block checked - obtain ⟨operations, operationsEmitted, valuesSize⟩ := emitOps_defined incoming context.rank block.ops.toList rows column valid checkedOps + obtain ⟨operations, operationsEmitted, valuesSize⟩ := emitOps_defined (callRanks := context.callRanks) + incoming context.rank block.ops.toList rows column valid checkedOps obtain ⟨control, controlEmitted, shape⟩ := emitCtrl_defined selectors context incoming operations.values operations.column (lookup + operations.queries.length) block.ctrl (emitOps_degreeValid valid operationsEmitted) (by have mono := checkEmissionOps_le checkedOps; omega) (valuesSize ▸ checkedCtrl) diff --git a/Ix/Aiur/Proofs/BlockExpressions.lean b/Ix/Aiur/Proofs/BlockExpressions.lean index cc08fb25f..e7d49aa15 100644 --- a/Ix/Aiur/Proofs/BlockExpressions.lean +++ b/Ix/Aiur/Proofs/BlockExpressions.lean @@ -62,6 +62,7 @@ structure Context where function : Nat inputSize : Nat rank : Expr + callRanks : Array Bytecode.CallRank := #[] structure ReturnExpr where selector : Expr @@ -539,7 +540,7 @@ decreasing_by def emitBlock (selectors : Array Expr) (context : Context) (incoming : Expr) (rows : Array RowExpr) (column lookup : Nat) (block : Bytecode.Block) : Option Emission := do let entry ← blockSelector selectors block - let operations ← OpEmitter.emitOps incoming context.rank block.ops.toList rows column + let operations ← OpEmitter.emitOps incoming context.rank block.ops.toList rows column context.callRanks let control ← emitCtrl selectors context incoming operations.values operations.column (lookup + operations.queries.length) block.ctrl return (control.afterOps incoming lookup operations).prefix diff --git a/Ix/Aiur/Proofs/BlockReflection.lean b/Ix/Aiur/Proofs/BlockReflection.lean index 06ed6dd4f..99a1b55bd 100644 --- a/Ix/Aiur/Proofs/BlockReflection.lean +++ b/Ix/Aiur/Proofs/BlockReflection.lean @@ -17,7 +17,7 @@ open OpEmitter LookupEmitter def selectorAt (selectors : Array G) (index : Nat) : G := selectors[index]?.getD 0 def Context.valued (context : Context) (rank : G) : AIR.RowContext := - ⟨context.function, context.inputSize, rank⟩ + ⟨context.function, context.inputSize, rank, context.callRanks⟩ def BlockReflects (values : Values G) (row : Nat → G) (selectors : Array Expr) (selected : Nat → G) (context : Context) (rank : G) (block : Bytecode.Block) : Prop := @@ -402,7 +402,8 @@ theorem block_reflects (values : Values G) (row : Nat → G) simp only [List.mapM_cons, List.mapM_nil, guard, bind, Option.bind_some, pure, goldilocks_mul, goldilocks_sub] rfl refine ⟨_, ?_, Emission.prefix_eval (Emission.afterOps_eval lookup incomingEval opEval resultEval) guarded⟩ - simp only [Bytecode.Block.emitRow, show (context.valued rank).rank = rank from rfl, opEmitted, + simp only [Bytecode.Block.emitRow, show (context.valued rank).rank = rank from rfl, + show (context.valued rank).callRanks = context.callRanks from rfl, opEmitted, bind, Option.bind_some, ← columnEq, queryCount, resultEmitted, pure] termination_by sizeOf block decreasing_by exact block_smaller block diff --git a/Ix/Aiur/Proofs/BlockRowCalls.lean b/Ix/Aiur/Proofs/BlockRowCalls.lean index 3374c311d..e75b8a225 100644 --- a/Ix/Aiur/Proofs/BlockRowCalls.lean +++ b/Ix/Aiur/Proofs/BlockRowCalls.lean @@ -18,12 +18,11 @@ open Bytecode def BlockEmission.HasQuery (emission : BlockEmission) (selector : G) (message : List G) : Prop := ∃ part ∈ emission.queries, part.selector = selector ∧ part.message = message -def BlockEmission.TracksCalls (rank : G) (emission : BlockEmission) : Prop := +def BlockEmission.TracksCalls (rank : G) (emission : BlockEmission) + (callRanks : Array CallRank := #[]) : Prop := ∀ part ∈ emission.calls, emission.HasQuery part.1 (functionMessage part.2.1) ∧ - (∀ message ∈ (rankByteQueries part.2.2).map rangeMessage, emission.HasQuery part.1 message) ∧ - EquationAvailable emission.equations - (part.1 * callOrderConstraint rank part.2.1.rank (packRank part.2.2)) + CallRankChecks callRanks rank part.1 emission.equations (emission.HasQuery part.1) part.2 theorem BlockEmission.HasQuery.mono {first last : BlockEmission} (included : first.queries ⊆ last.queries) {selector : G} {message : List G} @@ -38,67 +37,72 @@ theorem BlockEmission.HasQuery.active {emission : BlockEmission} {queries : List rw [← equal] exact queried part member gate +variable {callRanks : Array CallRank} + theorem BlockEmission.TracksCalls.prefix {rank : G} {emission : BlockEmission} - (tracked : emission.TracksCalls rank) (equations : List G) : - (emission.prefix equations).TracksCalls rank := by + (tracked : emission.TracksCalls rank callRanks) (equations : List G) : + (emission.prefix equations).TracksCalls rank callRanks := by intro part member - obtain ⟨query, bytes, equation⟩ := tracked part member - exact ⟨query, bytes, equation.mono (fun _ member => List.mem_append_right _ member)⟩ + obtain ⟨query, checked⟩ := tracked part member + exact ⟨query, checked.mono (fun _ member => List.mem_append_right _ member) (fun _ query => query)⟩ theorem BlockEmission.TracksCalls.afterOps {rank incoming : G} {lookup : Nat} {operations : OpsEmission} {control : BlockEmission} - (opsTracked : CallsEmitted rank incoming operations.equations operations.queries operations.calls) - (ctrlTracked : control.TracksCalls rank) : - (control.afterOps incoming lookup operations).TracksCalls rank := by + (opsTracked : CallsEmitted rank incoming operations.equations operations.queries operations.calls callRanks) + (ctrlTracked : control.TracksCalls rank callRanks) : + (control.afterOps incoming lookup operations).TracksCalls rank callRanks := by intro part member rcases List.mem_append.mp member with first | last · obtain ⟨edge, edgeMember, equal⟩ := List.mem_map.mp first subst part - obtain ⟨query, bytes, equation⟩ := opsTracked edge edgeMember + obtain ⟨query, checked⟩ := opsTracked edge edgeMember have memberQuery : ∀ message ∈ operations.queries, (control.afterOps incoming lookup operations).HasQuery incoming message := by intro message member obtain ⟨query, queryMember, gate, equal⟩ := queryParts_member lookup incoming member exact ⟨query, List.mem_append_left _ queryMember, gate, equal⟩ - exact ⟨memberQuery _ query, fun message member => memberQuery message (bytes member), - equation.mono (fun _ member => List.mem_append_left _ member)⟩ - · obtain ⟨query, bytes, equation⟩ := ctrlTracked part last - exact ⟨query.mono (fun _ member => List.mem_append_right _ member), - fun message member => (bytes message member).mono (fun _ member => List.mem_append_right _ member), - equation.mono (fun _ member => List.mem_append_right _ member)⟩ + exact ⟨memberQuery _ query, checked.mono + (fun _ member => List.mem_append_left _ member) memberQuery⟩ + · obtain ⟨query, checked⟩ := ctrlTracked part last + exact ⟨query.mono (fun _ member => List.mem_append_right _ member), checked.mono + (fun _ member => List.mem_append_right _ member) + (fun _ query => query.mono (fun _ member => List.mem_append_right _ member))⟩ theorem BlockEmission.TracksCalls.join (rank : G) (values : Array RowValue) (column lookup : Nat) - (emissions : List BlockEmission) (tracked : ∀ emission ∈ emissions, emission.TracksCalls rank) : - (joinBlockEmissions values column lookup emissions).TracksCalls rank := by + (emissions : List BlockEmission) + (tracked : ∀ emission ∈ emissions, emission.TracksCalls rank callRanks) : + (joinBlockEmissions values column lookup emissions).TracksCalls rank callRanks := by intro part member obtain ⟨emission, emissionMember, partMember⟩ := List.mem_flatMap.mp member - obtain ⟨query, bytes, equation⟩ := tracked emission emissionMember part partMember + obtain ⟨query, checked⟩ := tracked emission emissionMember part partMember have included := EmissionIncluded.join values column lookup emissionMember - exact ⟨query.mono included.queries, fun message member => (bytes message member).mono included.queries, - equation.mono included.equations⟩ + exact ⟨query.mono included.queries, checked.mono included.equations + (fun _ query => query.mono included.queries)⟩ theorem BlockEmission.TracksCalls.continued {rank : G} {branches continuation : BlockEmission} - (first : branches.TracksCalls rank) (last : continuation.TracksCalls rank) (equations : List G) : - (branches.continued equations continuation).TracksCalls rank := by + (first : branches.TracksCalls rank callRanks) (last : continuation.TracksCalls rank callRanks) + (equations : List G) : + (branches.continued equations continuation).TracksCalls rank callRanks := by intro part member rcases List.mem_append.mp member with left | right - · obtain ⟨query, bytes, equation⟩ := first part left - exact ⟨query.mono (fun _ member => List.mem_append_left _ member), - fun message member => (bytes message member).mono (fun _ member => List.mem_append_left _ member), - equation.mono (fun _ member => List.mem_append_left _ (List.mem_append_left _ member))⟩ - · obtain ⟨query, bytes, equation⟩ := last part right - exact ⟨query.mono (fun _ member => List.mem_append_right _ member), - fun message member => (bytes message member).mono (fun _ member => List.mem_append_right _ member), - equation.mono (fun _ member => List.mem_append_right _ member)⟩ + · obtain ⟨query, checked⟩ := first part left + exact ⟨query.mono (fun _ member => List.mem_append_left _ member), checked.mono + (fun _ member => List.mem_append_left _ (List.mem_append_left _ member)) + (fun _ query => query.mono (fun _ member => List.mem_append_left _ member))⟩ + · obtain ⟨query, checked⟩ := last part right + exact ⟨query.mono (fun _ member => List.mem_append_right _ member), checked.mono + (fun _ member => List.mem_append_right _ member) + (fun _ query => query.mono (fun _ member => List.mem_append_right _ member))⟩ theorem BlockEmission.TracksCalls.active {rank : G} {emission : BlockEmission} - (tracked : emission.TracksCalls rank) + (tracked : emission.TracksCalls rank callRanks) {queries : List (List G)} (queried : emission.QueriesIn queries) {calls : List (Bytecode.AIR.Call × (Fin 6 → G))} (called : emission.CallsAt calls) : - CallsEmitted rank 1 emission.equations queries calls := by + CallsEmitted rank 1 emission.equations queries calls callRanks := by intro edge member - obtain ⟨query, bytes, equation⟩ := tracked (1, edge) (called edge member) - exact ⟨query.active queried, fun _ member => (bytes _ member).active queried, equation⟩ + obtain ⟨query, checked⟩ := tracked (1, edge) (called edge member) + exact ⟨query.active queried, checked.mono (fun _ member => member) + (fun _ query => query.active queried)⟩ theorem forall₂_right_property {α β : Type} {source : List α} {emissions : List β} {property : β → Prop} (related : List.Forall₂ (fun _ emission => property emission) source emissions) : @@ -122,11 +126,11 @@ theorem branchRows_tracks_calls (row : Nat → G) (selector : SelIdx → G) (con (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) (caseSound : ∀ pair ∈ branches.toList, ∀ emission, pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → - emission.TracksCalls context.rank) + emission.TracksCalls context.rank context.callRanks) (defaultSound : ∀ block, fallback = some block → ∀ emission, block.emitRow row selector context (block.selectorFlow selector).entry values - (column + branches.size) lookup = some emission → emission.TracksCalls context.rank) : - emission.TracksCalls context.rank := by + (column + branches.size) lookup = some emission → emission.TracksCalls context.rank context.callRanks) : + emission.TracksCalls context.rank context.callRanks := by simp only [branchRows, bind, Option.bind] at emitted split at emitted · cases emitted @@ -137,7 +141,7 @@ theorem branchRows_tracks_calls (row : Nat → G) (selector : SelIdx → G) (con · rename_i default defaultEmitted have equal := Option.some.inj emitted subst emission - have casesTracked : ∀ emission ∈ cases, emission.TracksCalls context.rank := by + have casesTracked : ∀ emission ∈ cases, emission.TracksCalls context.rank context.callRanks := by apply forall₂_right_property apply mapM_forall₂ casesEmitted intro pair member result resultEmitted @@ -148,7 +152,7 @@ theorem branchRows_tracks_calls (row : Nat → G) (selector : SelIdx → G) (con have equal := Option.some.inj resultEmitted subst result exact (caseSound pair member body bodyEmitted).prefix _ - have defaultTracked : ∀ emission ∈ default, emission.TracksCalls context.rank := by + have defaultTracked : ∀ emission ∈ default, emission.TracksCalls context.rank context.callRanks := by cases fallback with | none => simp only [defaultRow, Option.some.injEq] at defaultEmitted @@ -182,7 +186,7 @@ theorem Ctrl.emitRow_tracks_calls (row : Nat → G) (selector : SelIdx → G) (c (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) {emission : BlockEmission} (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) : - emission.TracksCalls context.rank := by + emission.TracksCalls context.rank context.callRanks := by cases ctrl with | «return» index indices => rw [Ctrl.emitRow.eq_def] at emitted @@ -251,7 +255,7 @@ theorem Block.emitRow_tracks_calls (row : Nat → G) (selector : SelIdx → G) ( (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) {emission : BlockEmission} (emitted : block.emitRow row selector context incoming values column lookup = some emission) : - emission.TracksCalls context.rank := by + emission.TracksCalls context.rank context.callRanks := by rw [Block.emitRow] at emitted simp only [bind, Option.bind] at emitted split at emitted diff --git a/Ix/Aiur/Proofs/BlockRowInputs.lean b/Ix/Aiur/Proofs/BlockRowInputs.lean index 22870e7e6..796505a89 100644 --- a/Ix/Aiur/Proofs/BlockRowInputs.lean +++ b/Ix/Aiur/Proofs/BlockRowInputs.lean @@ -86,8 +86,8 @@ theorem RowInputs.full (values : Array RowValue) : RowInputs values.size (rowVal simpa only [RowInputs, rowValues, Array.size_map] using read theorem emitOps_inputs {row : Nat → G} {selector rank : G} {ops : List Op} - {values : Array RowValue} {column : Nat} {emission : OpsEmission} - (emitted : emitOps row selector rank ops values column = some emission) + {values : Array RowValue} {column : Nat} {emission : OpsEmission} {callRanks : Array CallRank} + (emitted : emitOps row selector rank ops values column callRanks = some emission) {size : Nat} {inputs : Array G} (preserved : RowInputs size inputs values) : RowInputs size inputs emission.values := by induction ops generalizing values column emission with diff --git a/Ix/Aiur/Proofs/BlockRows.lean b/Ix/Aiur/Proofs/BlockRows.lean index 2d392f8c7..b442d08fd 100644 --- a/Ix/Aiur/Proofs/BlockRows.lean +++ b/Ix/Aiur/Proofs/BlockRows.lean @@ -23,6 +23,7 @@ structure RowContext where function : FunIdx inputSize : Nat rank : G + callRanks : Array CallRank := #[] structure QueryPart where slot : Nat @@ -146,7 +147,7 @@ decreasing_by def Block.emitRow (row : Nat → G) (selector : SelIdx → G) (context : RowContext) (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) : Option BlockEmission := do - let operations ← emitOps row incoming context.rank block.ops.toList values column + let operations ← emitOps row incoming context.rank block.ops.toList values column context.callRanks let control ← block.ctrl.emitRow row selector context incoming operations.values operations.column (lookup + operations.queries.length) return (control.afterOps incoming lookup operations).prefix diff --git a/Ix/Aiur/Proofs/BranchlessSlots.lean b/Ix/Aiur/Proofs/BranchlessSlots.lean index 9bc477be6..73cff67e1 100644 --- a/Ix/Aiur/Proofs/BranchlessSlots.lean +++ b/Ix/Aiur/Proofs/BranchlessSlots.lean @@ -67,9 +67,9 @@ open Aiur.AIR theorem Function.emitRow_terminal_writers (row : Nat → G) (selector : SelIdx → G) (function : Function) (functionIndex : FunIdx) (rank : G) - (inputs : Array RowValue) (column lookup : Nat) {emission : BlockEmission} + (inputs : Array RowValue) (column lookup : Nat) {emission : BlockEmission} {callRanks : Array CallRank} (terminal : function.hasTerminalControl = true) - (emitted : function.emitRow row selector functionIndex rank inputs column lookup = some emission) : + (emitted : function.emitRow row selector functionIndex rank inputs column lookup callRanks = some emission) : QueryWriters lookup emission.lookup emission.queries := by rw [Function.emitRow, Block.emitRow] at emitted simp only [bind, Option.bind] at emitted diff --git a/Ix/Aiur/Proofs/CallInventory.lean b/Ix/Aiur/Proofs/CallInventory.lean index b33f2f268..2cd40236c 100644 --- a/Ix/Aiur/Proofs/CallInventory.lean +++ b/Ix/Aiur/Proofs/CallInventory.lean @@ -29,18 +29,54 @@ theorem EquationAvailable.satisfied {equations : List G} {value : G} (zero : ∀ value ∈ equations, value = 0) : value = 0 := equation.elim id (zero value) -/-- Every recorded call has its function query, all gap range queries and -an established selector-gated order relation. -/ +/-- Every call has its complete function query. Ordered calls additionally +have gap range queries and a selector-gated order relation. -/ +def CallRankChecks (callRanks : Array CallRank) (rank selector : G) (equations : List G) + (hasQuery : List G → Prop) (edge : Bytecode.AIR.Call × (Fin 6 → G)) : Prop := + match callRanks[edge.1.function]?.getD .ordered with + | .ordered => (∀ ⦃message⦄, message ∈ (rankByteQueries edge.2).map rangeMessage → hasQuery message) ∧ + EquationAvailable equations (selector * callOrderConstraint rank edge.1.rank (packRank edge.2)) + | .zero | .bound => True + +theorem CallRankChecks.mono {callRanks : Array CallRank} {rank selector : G} + {firstEquations lastEquations : List G} {firstQuery lastQuery : List G → Prop} + {edge : Bytecode.AIR.Call × (Fin 6 → G)} + (checked : CallRankChecks callRanks rank selector firstEquations firstQuery edge) + (equations : firstEquations ⊆ lastEquations) + (queries : ∀ message, firstQuery message → lastQuery message) : + CallRankChecks callRanks rank selector lastEquations lastQuery edge := by + unfold CallRankChecks at * + cases mode : callRanks[edge.1.function]?.getD .ordered <;> simp only [mode] at checked ⊢ + exact ⟨fun {message} member => queries message (checked.1 member), checked.2.mono equations⟩ + +theorem CallRankChecks.ordered {callRanks : Array CallRank} {rank selector : G} + {equations : List G} {hasQuery : List G → Prop} {edge : Bytecode.AIR.Call × (Fin 6 → G)} + (checked : CallRankChecks callRanks rank selector equations hasQuery edge) + (mode : callRanks[edge.1.function]?.getD .ordered = .ordered) : + (∀ ⦃message⦄, message ∈ (rankByteQueries edge.2).map rangeMessage → hasQuery message) ∧ + EquationAvailable equations (selector * callOrderConstraint rank edge.1.rank (packRank edge.2)) := by + simpa only [CallRankChecks, mode] using checked + def CallsEmitted (rank selector : G) (equations : List G) (queries : List (List G)) - (calls : List (Bytecode.AIR.Call × (Fin 6 → G))) : Prop := + (calls : List (Bytecode.AIR.Call × (Fin 6 → G))) + (callRanks : Array CallRank := #[]) : Prop := ∀ edge ∈ calls, functionMessage edge.1 ∈ queries ∧ - (rankByteQueries edge.2).map rangeMessage ⊆ queries ∧ - EquationAvailable equations (selector * callOrderConstraint rank edge.1.rank (packRank edge.2)) + CallRankChecks callRanks rank selector equations (· ∈ queries) edge + +theorem emitCallRow_calls (row : Nat → G) (rank selector : G) (function : FunIdx) + (inputs : Array G) (size : Nat) (callRanks : Array CallRank) : + let emission := emitCallRow row rank function inputs size (callRanks[function]?.getD .ordered) + CallsEmitted rank selector emission.equations emission.queries emission.calls callRanks := by + cases mode : callRanks[function]?.getD .ordered <;> + simp only [emitCallRow, CallsEmitted, List.mem_singleton, forall_eq, List.mem_cons_self, + true_and, CallRankChecks, mode, calleeRank, callGap, callRangeQueries] + exact ⟨fun _ member => List.mem_cons_of_mem _ member, + Or.inl (by rw [callOrderConstraint_derived, G.mul_zero])⟩ theorem emitOp_calls {row : Nat → G} {selector rank : G} {op : Op} - {values : Array RowValue} {emission : OpEmission} - (emitted : emitOp row selector rank op values = some emission) : - CallsEmitted rank selector emission.equations emission.queries emission.calls := by + {values : Array RowValue} {emission : OpEmission} {callRanks : Array CallRank} + (emitted : emitOp row selector rank op values callRanks = some emission) : + CallsEmitted rank selector emission.equations emission.queries emission.calls callRanks := by cases op <;> simp only [emitOp, emitByte1, emitByte2, emitU32LessThan, emitU32Add, emitAdvice, bind, Option.bind, Option.map, pure] at emitted all_goals @@ -48,30 +84,29 @@ theorem emitOp_calls {row : Nat → G} {selector rank : G} {op : Op} | split at emitted | (dsimp only at emitted; split at emitted) all_goals cases emitted - all_goals simp [CallsEmitted, EquationAvailable, callOrderConstraint_derived, G.mul_zero] + all_goals first | exact emitCallRow_calls _ _ _ _ _ _ _ | simp [CallsEmitted] theorem CallsEmitted.append {rank selector : G} {firstEquations restEquations : List G} {firstQueries restQueries : List (List G)} {firstCalls restCalls : List (Bytecode.AIR.Call × (Fin 6 → G))} - (first : CallsEmitted rank selector firstEquations firstQueries firstCalls) - (rest : CallsEmitted rank selector restEquations restQueries restCalls) : + {callRanks : Array CallRank} + (first : CallsEmitted rank selector firstEquations firstQueries firstCalls callRanks) + (rest : CallsEmitted rank selector restEquations restQueries restCalls callRanks) : CallsEmitted rank selector (firstEquations ++ restEquations) - (firstQueries ++ restQueries) (firstCalls ++ restCalls) := by + (firstQueries ++ restQueries) (firstCalls ++ restCalls) callRanks := by intro edge member rcases List.mem_append.mp member with left | right - · obtain ⟨query, bytes, equation⟩ := first edge left - exact ⟨List.mem_append_left _ query, - fun _ member => List.mem_append_left _ (bytes member), - equation.mono (fun _ member => List.mem_append_left _ member)⟩ - · obtain ⟨query, bytes, equation⟩ := rest edge right - exact ⟨List.mem_append_right _ query, - fun _ member => List.mem_append_right _ (bytes member), - equation.mono (fun _ member => List.mem_append_right _ member)⟩ + · obtain ⟨query, ordered⟩ := first edge left + exact ⟨List.mem_append_left _ query, ordered.mono + (fun _ member => List.mem_append_left _ member) (fun _ member => List.mem_append_left _ member)⟩ + · obtain ⟨query, ordered⟩ := rest edge right + exact ⟨List.mem_append_right _ query, ordered.mono + (fun _ member => List.mem_append_right _ member) (fun _ member => List.mem_append_right _ member)⟩ theorem emitOps_calls {row : Nat → G} {selector rank : G} {ops : List Op} - {values : Array RowValue} {column : Nat} {emission : OpsEmission} - (emitted : emitOps row selector rank ops values column = some emission) : - CallsEmitted rank selector emission.equations emission.queries emission.calls := by + {values : Array RowValue} {column : Nat} {emission : OpsEmission} {callRanks : Array CallRank} + (emitted : emitOps row selector rank ops values column callRanks = some emission) : + CallsEmitted rank selector emission.equations emission.queries emission.calls callRanks := by induction ops generalizing values column emission with | nil => simp only [emitOps, Option.some.injEq] at emitted diff --git a/Ix/Aiur/Proofs/CheckedCircuit.lean b/Ix/Aiur/Proofs/CheckedCircuit.lean index 52014c675..b95e04324 100644 --- a/Ix/Aiur/Proofs/CheckedCircuit.lean +++ b/Ix/Aiur/Proofs/CheckedCircuit.lean @@ -21,7 +21,7 @@ theorem emitMember_defined (rank : Expr) (column lookup selectorBase : Nat) simpa only [advice, selectorExprs, Array.size_ofFn] using checked.2 obtain ⟨entry, selected⟩ := blockSelector_defined (selectorExprs selectorBase function.layout.selectors) function.body bodyChecks obtain ⟨body, emitted, _⟩ := emitBlock_defined (selectorExprs selectorBase function.layout.selectors) - ⟨index, function.layout.inputSize, rank⟩ entry (advice 0 function.layout.inputSize) column lookup function.body + ⟨index, function.layout.inputSize, rank, #[]⟩ entry (advice 0 function.layout.inputSize) column lookup function.body (advice_degreeValid _ _) (by simp only [advice, Array.size_ofFn, Nat.le_refl]) bodyChecks refine ⟨⟨index, function, selectorBase, entry, body⟩, ?_⟩ simp only [emitMember, present, selected, emitted, bind, Option.bind_some, pure] diff --git a/Ix/Aiur/Proofs/CircuitExpressions.lean b/Ix/Aiur/Proofs/CircuitExpressions.lean index 2ead63209..6c623c1db 100644 --- a/Ix/Aiur/Proofs/CircuitExpressions.lean +++ b/Ix/Aiur/Proofs/CircuitExpressions.lean @@ -64,11 +64,12 @@ theorem Member.eval_components {values : Values G} {member : Member} {result : A exact ⟨rfl, rfl, rfl, bodyEval⟩ def emitMember (rank : Expr) (column lookup selectorBase : Nat) - (program : Bytecode.Toplevel) (functionIndex : Nat) : Option Member := do + (program : Bytecode.Toplevel) (functionIndex : Nat) + (callRanks : Array Bytecode.CallRank := #[]) : Option Member := do let function ← program.functions[functionIndex]? let selectors := selectorExprs selectorBase function.layout.selectors let entry ← blockSelector selectors function.body - let body ← emitBlock selectors ⟨functionIndex, function.layout.inputSize, rank⟩ entry + let body ← emitBlock selectors ⟨functionIndex, function.layout.inputSize, rank, callRanks⟩ entry (advice 0 function.layout.inputSize) column lookup function.body return ⟨functionIndex, function, selectorBase, entry, body⟩ diff --git a/Ix/Aiur/Proofs/CircuitReflection.lean b/Ix/Aiur/Proofs/CircuitReflection.lean index b049164f7..716032194 100644 --- a/Ix/Aiur/Proofs/CircuitReflection.lean +++ b/Ix/Aiur/Proofs/CircuitReflection.lean @@ -16,10 +16,11 @@ open OpEmitter LookupEmitter BlockEmitter Compiler theorem emitMember_reflects {values : Values G} (row : Nat → G) {rank : Expr} {r : G} {column lookup selectorBase : Nat} {program : Bytecode.Toplevel} {functionIndex : Nat} {member : Member} + {callRanks : Array Bytecode.CallRank} (rankEval : evalExpr values rank = some r) - (emitted : emitMember rank column lookup selectorBase program functionIndex = some member) + (emitted : emitMember rank column lookup selectorBase program functionIndex callRanks = some member) (reads : ∀ index < member.readBound, (values.columns .main .current)[index]? = some (row index)) : - ∃ result, AIR.emitMember row r column lookup selectorBase program functionIndex = some result ∧ + ∃ result, AIR.emitMember row r column lookup selectorBase program functionIndex callRanks = some result ∧ member.eval values = some result ∧ evalExpr values member.entry = some (result.entry row) := by simp only [emitMember, bind, Option.bind] at emitted split at emitted diff --git a/Ix/Aiur/Proofs/CircuitRowCounts.lean b/Ix/Aiur/Proofs/CircuitRowCounts.lean index 6304c6e6e..f23100b63 100644 --- a/Ix/Aiur/Proofs/CircuitRowCounts.lean +++ b/Ix/Aiur/Proofs/CircuitRowCounts.lean @@ -28,6 +28,21 @@ private theorem mapM_of_members {α β γ : Type} (items : List α) (index : α ih (fun item member => present item (List.mem_cons_of_mem _ member))] rfl +theorem Circuit.validateRowCounts_members (program : Toplevel) (circuit : Circuit) + (members : List MemberEmission) + (indices : members.map MemberEmission.functionIndex = circuit.members.toList) + (source : ∀ member ∈ members, program.functions[member.functionIndex]? = some member.function) + (validated : circuit.validateRowCounts program = true) : + circuit.members.size < gSize.toNat ∧ + (∀ part ∈ members, part.function.body.controlCounts.nodes < gSize.toNat) ∧ + (members.map (fun part => part.function.body.controlCounts.leaves)).sum ≤ circuit.layout.selectors := by + have present := mapM_of_members members (·.functionIndex) (·.function) + (fun index => program.functions[index]?) source + rw [indices] at present + rw [Circuit.validateRowCounts, present] at validated + simpa only [Bool.and_eq_true, decide_eq_true_eq, List.all_map, List.all_eq_true, + List.map_map, Function.comp_def] using validated + theorem Circuit.validateRowCounts_spec (row : Nat → G) (program : Toplevel) (circuit : Circuit) {emission : CircuitEmission} (emitted : circuit.emitRow row program = some emission) (validated : circuit.validateRowCounts program = true) : @@ -35,14 +50,10 @@ theorem Circuit.validateRowCounts_spec (row : Nat → G) (program : Toplevel) (c (∀ part ∈ emission.members, part.function.body.controlCounts.nodes < gSize.toNat) ∧ (emission.members.map (fun part => part.function.body.controlCounts.leaves)).sum ≤ circuit.layout.selectors := by obtain ⟨_, indices, source⟩ := circuit.emitRow_spec row program emitted - have present := mapM_of_members emission.members (·.functionIndex) (·.function) - (fun index => program.functions[index]?) (fun part member => (source part member).present) - rw [indices] at present - rw [Circuit.validateRowCounts, present] at validated - simpa only [Bool.and_eq_true, decide_eq_true_eq, List.all_map, List.all_eq_true, - List.map_map, Function.comp_def] using validated + exact circuit.validateRowCounts_members program emission.members indices + (fun part member => (source part member).present) validated -private theorem flatMap_length_le_sum {α β : Type} (items : List α) (parts : α → List β) +theorem flatMap_length_le_sum {α β : Type} (items : List α) (parts : α → List β) (bound : α → Nat) (bounded : ∀ item ∈ items, (parts item).length ≤ bound item) : (items.flatMap parts).length ≤ (items.map bound).sum := by induction items with diff --git a/Ix/Aiur/Proofs/CircuitRowMembers.lean b/Ix/Aiur/Proofs/CircuitRowMembers.lean index 57f34166b..040d4c85b 100644 --- a/Ix/Aiur/Proofs/CircuitRowMembers.lean +++ b/Ix/Aiur/Proofs/CircuitRowMembers.lean @@ -16,16 +16,16 @@ namespace Aiur.AIR open Bytecode structure MemberEmission.FromProgram (row : Nat → G) (rank : G) (column lookup : Nat) - (program : Toplevel) (member : MemberEmission) : Prop where + (program : Toplevel) (member : MemberEmission) (callRanks : Array CallRank := #[]) : Prop where present : program.functions[member.functionIndex]? = some member.function emitted : member.function.emitRow row (member.selector row) member.functionIndex rank - (rowAdvice row 0 member.function.layout.inputSize) column lookup = some member.body + (rowAdvice row 0 member.function.layout.inputSize) column lookup callRanks = some member.body theorem emitMember_spec (row : Nat → G) (rank : G) (column lookup selectorBase : Nat) - (program : Toplevel) (functionIndex : FunIdx) {member : MemberEmission} - (emitted : emitMember row rank column lookup selectorBase program functionIndex = some member) : + (program : Toplevel) (functionIndex : FunIdx) {member : MemberEmission} {callRanks : Array CallRank} + (emitted : emitMember row rank column lookup selectorBase program functionIndex callRanks = some member) : member.functionIndex = functionIndex ∧ member.selectorBase = selectorBase ∧ - member.FromProgram row rank column lookup program := by + member.FromProgram row rank column lookup program callRanks := by simp only [emitMember, bind, Option.bind] at emitted split at emitted · cases emitted @@ -69,7 +69,8 @@ theorem emitMembers_spec (row : Nat → G) (rank : G) (column lookup selectorBas · exact remaining item tail theorem MemberEmission.FromProgram.selector_satisfied {row : Nat → G} {rank : G} {column lookup : Nat} - {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + {program : Toplevel} {member : MemberEmission} {callRanks : Array CallRank} + (source : member.FromProgram row rank column lookup program callRanks) (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : (member.function.body.selectorFlow (member.selector row)).Satisfied := by have emitted := source.emitted @@ -100,9 +101,8 @@ theorem circuitEmission_member_boolean {row : Nat → G} {rank : G} {column look exact member.function.body.selectorFlow_boolean (member.selector row) ((source member present).selector_satisfied (circuitEmission_member_satisfied satisfied present)) -theorem circuitEmission_boolean {row : Nat → G} {rank : G} {column lookup : Nat} - {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} - (source : ∀ member ∈ members, member.FromProgram row rank column lookup program) +theorem circuitEmission_boolean_of_members {row : Nat → G} {circuit : Circuit} {members : List MemberEmission} + (individual : ∀ member ∈ members, booleanConstraint (member.entry row) = 0) (count : members.length = circuit.members.size) (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) : booleanConstraint (circuitEmission row circuit members).selector = 0 := by @@ -124,13 +124,21 @@ theorem circuitEmission_boolean {row : Nat → G} {rank : G} {column lookup : Na | cons member rest => have empty : rest = [] := List.length_eq_zero_iff.mp (by simp only [List.length_cons] at bounded; omega) subst rest - have boolean := circuitEmission_member_boolean source satisfied member List.mem_cons_self + have boolean := individual member List.mem_cons_self change booleanConstraint (selectorSum [member.entry row]) = 0 rw [selectorSum_cons] change booleanConstraint (member.entry row + 0) = 0 rw [G.add_zero] exact boolean +theorem circuitEmission_boolean {row : Nat → G} {rank : G} {column lookup : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromProgram row rank column lookup program) + (count : members.length = circuit.members.size) + (satisfied : ∀ equation ∈ (circuitEmission row circuit members).equations, equation = 0) : + booleanConstraint (circuitEmission row circuit members).selector = 0 := + circuitEmission_boolean_of_members (circuitEmission_member_boolean source satisfied) count satisfied + end Aiur.AIR namespace Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/CircuitRowQueries.lean b/Ix/Aiur/Proofs/CircuitRowQueries.lean index 7cd70664e..17fd6ef80 100644 --- a/Ix/Aiur/Proofs/CircuitRowQueries.lean +++ b/Ix/Aiur/Proofs/CircuitRowQueries.lean @@ -52,7 +52,8 @@ theorem forall₂_self_map {α β : Type} (items : List α) (map : α → β) (r exact .cons (related item List.mem_cons_self) (ih (fun item member => related item (List.mem_cons_of_mem _ member))) theorem MemberEmission.FromProgram.querySlots {row : Nat → G} {rank : G} {column lookup : Nat} - {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + {program : Toplevel} {member : MemberEmission} {callRanks : Array CallRank} + (source : member.FromProgram row rank column lookup program callRanks) (bounds : member.function.body.rowBounds (member.selector row)) (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : QuerySlots (member.entry row) lookup member.body.lookup member.body.queries := by diff --git a/Ix/Aiur/Proofs/CircuitRowReturns.lean b/Ix/Aiur/Proofs/CircuitRowReturns.lean index 77ed1e5df..f5f8884d8 100644 --- a/Ix/Aiur/Proofs/CircuitRowReturns.lean +++ b/Ix/Aiur/Proofs/CircuitRowReturns.lean @@ -16,7 +16,8 @@ namespace Aiur.AIR open Bytecode theorem MemberEmission.FromProgram.return_gates {row : Nat → G} {rank : G} {column lookup : Nat} - {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + {program : Toplevel} {member : MemberEmission} {callRanks : Array CallRank} + (source : member.FromProgram row rank column lookup program callRanks) (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : member.body.returns.map Prod.fst = (member.function.body.selectorFlow (member.selector row)).returns := by have emitted := source.emitted @@ -26,7 +27,8 @@ theorem MemberEmission.FromProgram.return_gates {row : Nat → G} {rank : G} {co (source.selector_satisfied satisfied) rfl) theorem MemberEmission.FromProgram.return_boolean {row : Nat → G} {rank : G} {column lookup : Nat} - {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + {program : Toplevel} {member : MemberEmission} {callRanks : Array CallRank} + (source : member.FromProgram row rank column lookup program callRanks) (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : ∀ part ∈ member.body.returns, booleanConstraint part.1 = 0 := by intro part present @@ -36,7 +38,8 @@ theorem MemberEmission.FromProgram.return_boolean {row : Nat → G} {rank : G} { exact List.mem_map.mpr ⟨part, present, rfl⟩ theorem MemberEmission.FromProgram.return_count {row : Nat → G} {rank : G} {column lookup : Nat} - {program : Toplevel} {member : MemberEmission} (source : member.FromProgram row rank column lookup program) + {program : Toplevel} {member : MemberEmission} {callRanks : Array CallRank} + (source : member.FromProgram row rank column lookup program callRanks) (shape : member.function.body.lookupShapes program none = true) (bounded : (member.function.body.selectorFlow (member.selector row)).returns.length < gSize.toNat) (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : diff --git a/Ix/Aiur/Proofs/CircuitRows.lean b/Ix/Aiur/Proofs/CircuitRows.lean index 1e5d1dd20..0fdae3470 100644 --- a/Ix/Aiur/Proofs/CircuitRows.lean +++ b/Ix/Aiur/Proofs/CircuitRows.lean @@ -31,10 +31,11 @@ def MemberEmission.entry (row : Nat → G) (member : MemberEmission) : G := (member.function.body.selectorFlow (member.selector row)).entry def emitMember (row : Nat → G) (rank : G) (column lookup selectorBase : Nat) - (program : Toplevel) (functionIndex : FunIdx) : Option MemberEmission := do + (program : Toplevel) (functionIndex : FunIdx) + (callRanks : Array CallRank := #[]) : Option MemberEmission := do let function ← program.functions[functionIndex]? let body ← function.emitRow row (fun index => row (selectorBase + index)) functionIndex rank - (rowAdvice row 0 function.layout.inputSize) column lookup + (rowAdvice row 0 function.layout.inputSize) column lookup callRanks return ⟨functionIndex, function, selectorBase, body⟩ def emitMembers (row : Nat → G) (rank : G) (column lookup selectorBase : Nat) diff --git a/Ix/Aiur/Proofs/CircuitTableExecution.lean b/Ix/Aiur/Proofs/CircuitTableExecution.lean index f4a1e2e85..817d7872b 100644 --- a/Ix/Aiur/Proofs/CircuitTableExecution.lean +++ b/Ix/Aiur/Proofs/CircuitTableExecution.lean @@ -13,7 +13,7 @@ Native extraction and the explicit layout/shape conditions remain separate. -/ namespace Aiur.AIR open Bytecode -private theorem forall₂_weaken {α β : Type} {left : List α} {right : List β} +theorem forall₂_weaken {α β : Type} {left : List α} {right : List β} {first second : α → β → Prop} (related : List.Forall₂ first left right) (weaken : ∀ a b, first a b → second a b) : List.Forall₂ second left right := by induction related with diff --git a/Ix/Aiur/Proofs/CompiledKey.lean b/Ix/Aiur/Proofs/CompiledKey.lean index f3f2f1e30..8fc46ac47 100644 --- a/Ix/Aiur/Proofs/CompiledKey.lean +++ b/Ix/Aiur/Proofs/CompiledKey.lean @@ -38,11 +38,11 @@ theorem circuit_success {logBlowup mainWidth preprocessedWidth preprocessedHeigh theorem functionCircuit_success {logBlowup : Nat} {program : Bytecode.Toplevel} {source : Bytecode.Circuit} {result : KeyCodec.Circuit} (built : functionCircuit logBlowup program source = some result) : - ∃ compiled, compileCircuit (circuitWidths source) program source = some compiled ∧ + ∃ compiled, compileNativeCircuit (circuitWidths source) program source = some compiled ∧ result.graph = compiled.base.graph ∧ result.mainWidth = source.layout.width ∧ result.preprocessedWidth = 0 ∧ result.preprocessedHeight = 0 ∧ result.valid = true := by - cases compiled : compileCircuit (circuitWidths source) program source with + cases compiled : compileNativeCircuit (circuitWidths source) program source with | none => simp only [functionCircuit, compiled, bind, Option.bind_none, reduceCtorEq] at built | some output => simp only [functionCircuit, compiled, bind, Option.bind_some] at built @@ -159,6 +159,25 @@ theorem circuits_bytes {logBlowup : Nat} {program : Bytecode.Toplevel} {result : · rw [equal, List.getElem?_append_right (by omega), length] simp only [Nat.add_sub_cancel_left, List.getElem?_cons_succ, List.getElem?_cons_zero] +theorem functionCircuit_reflects {logBlowup : Nat} {program : Bytecode.Toplevel} {source : Bytecode.Circuit} + {artifact : KeyCodec.Circuit} (built : functionCircuit logBlowup program source = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ result buffer, + source.emitNativeRow (fun index => (values.columns .main .current)[index]?.getD 0) program = some result ∧ + artifact.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + artifact.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) ∧ + 0 < result.lookupCount ∧ + (∀ part ∈ result.queries, 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + (program.callComponents.isEmpty = true → 4 ≤ result.lookupCount ∧ + ∀ member ∈ result.members, member.body.lookup ≤ result.lookupCount) := by + obtain ⟨compiled, compiledEq, graph, mainWidth, _, _, _⟩ := functionCircuit_success built + have physical : artifact.widths.main = source.layout.width := mainWidth + have wide := compileNativeCircuit_widen (circuitWidths_le (Nat.le_of_eq physical.symm)) compiledEq + obtain ⟨result, buffer, emitted, swept, satisfied, lookups, slots⟩ := compileNativeCircuit_reflects fits wide + exact ⟨result, buffer, emitted, graph ▸ swept, graph ▸ satisfied, graph ▸ lookups, slots⟩ + theorem memoryCircuit_reflects {logBlowup width : Nat} {artifact : KeyCodec.Circuit} (built : memoryCircuit logBlowup width = some artifact) {values : Values G} (fits : values.Fits artifact.widths) : ∃ buffer, artifact.graph.sweep goldilocksOps values = some buffer ∧ @@ -246,24 +265,31 @@ theorem CompiledBackend.circuit_count {selection : Selection} (backend : Compile CompiledKey.circuits_length backend.circuits_bound theorem CompiledBackend.function_graph_reflects {selection : Selection} (backend : CompiledBackend selection) - (generic : selection.source.componentRanks = false) {index : Nat} {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} (present : backend.compiled.bytecode.circuits[index]? = some source) (selected : backend.keyData.circuits[index]? = some artifact) {values : Values G} (fits : values.Fits artifact.widths) : ∃ result buffer, - source.emitRow (fun index => (values.columns .main .current)[index]?.getD 0) backend.compiled.bytecode = some result ∧ + source.emitNativeRow (fun index => (values.columns .main .current)[index]?.getD 0) backend.compiled.bytecode = some result ∧ artifact.graph.sweep goldilocksOps values = some buffer ∧ (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ artifact.graph.lookups.mapM (readLookup buffer) = - some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) := by + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) ∧ + 0 < result.lookupCount ∧ + (∀ part ∈ result.queries, 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + (backend.compiled.bytecode.callComponents.isEmpty = true → 4 ≤ result.lookupCount ∧ + ∀ member ∈ result.members, member.body.lookup ≤ result.lookupCount) := + CompiledKey.functionCircuit_reflects (CompiledKey.circuits_function backend.circuits_bound present selected) fits + +theorem CompiledBackend.function_components_checked {selection : Selection} (backend : CompiledBackend selection) + {index : Nat} {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (present : backend.compiled.bytecode.circuits[index]? = some source) + (selected : backend.keyData.circuits[index]? = some artifact) : + backend.compiled.bytecode.callComponents.isEmpty = true ∨ + backend.compiled.bytecode.validCallComponents = true := by have bound := CompiledKey.circuits_function backend.circuits_bound present selected - obtain ⟨compiled, built, graph, mainWidth, _, _, _⟩ := CompiledKey.functionCircuit_success bound - have physical : artifact.widths.main = source.layout.width := mainWidth - have wide := compileCircuit_widen (circuitWidths_le (Nat.le_of_eq physical.symm)) _ _ built - obtain ⟨result, buffer, emitted, swept, satisfied, lookups⟩ := backend.toBackend.compileCircuit_reflects - generic fits (Array.mem_of_getElem? present) physical wide - exact ⟨result, buffer, emitted, graph ▸ swept, graph ▸ satisfied, graph ▸ lookups⟩ + obtain ⟨_, built, _⟩ := CompiledKey.functionCircuit_success bound + exact compileNativeCircuit_components built theorem CompiledBackend.memory_graph_reflects {selection : Selection} (backend : CompiledBackend selection) {index width : Nat} {artifact : KeyCodec.Circuit} diff --git a/Ix/Aiur/Proofs/CompilerBranches.lean b/Ix/Aiur/Proofs/CompilerBranches.lean index d69b39f1f..897c95828 100644 --- a/Ix/Aiur/Proofs/CompilerBranches.lean +++ b/Ix/Aiur/Proofs/CompilerBranches.lean @@ -12,6 +12,8 @@ physical allocation, including the inverse columns of a default branch. -/ namespace Aiur.Concrete.Bytecode open Aiur.Bytecode +variable {callRanks : Array CallRank} + def allocationBranchStep (shared : SharedData) (degrees : Array Nat) (acc : SharedData) (block : Block) : LayoutM SharedData := do setSharedData shared @@ -43,8 +45,8 @@ theorem allocationBranchFold_callRanks {α : Type} (items : List α) (blockOf : theorem allocationBranchStep_column (shared : SharedData) (degrees : Array Nat) (acc : SharedData) (block : Block) (initial : LayoutMState) (base column : Nat) (aligned : initial.degrees = degrees) - (generic : initial.callRanks = #[]) - (effect : ∀ state : LayoutMState, state.callRanks = #[] → state.degrees = degrees → + (generic : initial.callRanks = callRanks) + (effect : ∀ state : LayoutMState, state.callRanks = callRanks → state.degrees = degrees → state.functionLayout.auxiliaries = shared.auxiliaries → column = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) : base + ((allocationBranchStep shared degrees acc block).run initial).1.auxiliaries = @@ -57,11 +59,11 @@ theorem allocationBranchStep_column (shared : SharedData) (degrees : Array Nat) theorem allocationBranchFold {α β : Type} {items : List α} {emissions : List β} (blockOf : α → Block) (measure : β → Nat) (shared : SharedData) (degrees : Array Nat) (base : Nat) (related : List.Forall₂ (fun item emission => ∀ state : LayoutMState, - state.callRanks = #[] → state.degrees = degrees → state.functionLayout.auxiliaries = shared.auxiliaries → + state.callRanks = callRanks → state.degrees = degrees → state.functionLayout.auxiliaries = shared.auxiliaries → measure emission = base + ((blockLayout (blockOf item)).run state).2.functionLayout.auxiliaries) items emissions) (acc : SharedData) (initial : LayoutMState) (aligned : initial.degrees = degrees) - (generic : initial.callRanks = #[]) : + (generic : initial.callRanks = callRanks) : ((items.foldlM (fun acc item => allocationBranchStep shared degrees acc (blockOf item)) acc).run initial).2.degrees = degrees ∧ base + ((items.foldlM (fun acc item => allocationBranchStep shared degrees acc (blockOf item)) acc).run initial).1.auxiliaries = @@ -87,13 +89,13 @@ theorem allocationBranchLoop (branches : Array (G × Block)) (shared : SharedDat theorem matchLayout_allocation {β : Type} (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) (initial : LayoutMState) (base : Nat) (measure : β → Nat) {cases defaults : List β} - (generic : initial.callRanks = #[]) + (generic : initial.callRanks = callRanks) (caseEffects : List.Forall₂ (fun pair emission => ∀ state : LayoutMState, - state.callRanks = #[] → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → + state.callRanks = callRanks → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → measure emission = base + ((blockLayout pair.2).run state).2.functionLayout.auxiliaries) branches.toList cases) (defaultEffects : List.Forall₂ (fun block emission => ∀ state : LayoutMState, - state.callRanks = #[] → state.degrees = initial.degrees → + state.callRanks = callRanks → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + branches.size → measure emission = base + ((blockLayout block).run state).2.functionLayout.auxiliaries) fallback.toList defaults) : @@ -111,7 +113,7 @@ theorem matchLayout_allocation {β : Type} (index : ValIdx) (branches : Array (G dsimp only [loop] rw [allocationBranchLoop] exact allocationBranchFold Prod.snd measure shared initial.degrees base caseEffects shared initial rfl generic - have loopRanks : (loop.run initial).2.callRanks = #[] := by + have loopRanks : (loop.run initial).2.callRanks = callRanks := by dsimp only [loop] rw [allocationBranchLoop] exact (allocationBranchFold_callRanks branches.toList Prod.snd shared initial.degrees shared initial).trans generic diff --git a/Ix/Aiur/Proofs/ComponentCalls.lean b/Ix/Aiur/Proofs/ComponentCalls.lean new file mode 100644 index 000000000..17eb3a6ab --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCalls.lean @@ -0,0 +1,271 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Compiler.CallOrder +import Ix.Aiur.Semantics.AIR + +/-! Every constrained request in local AIR execution occurs in the +syntactic call collector used by the checked component certificate. The +certificate supplies endpoint bounds, component order and call rank modes. -/ + +namespace Aiur.Bytecode + +def Op.constrainedCalls : Op → List FunIdx + | .call function _ _ false => [function] + | _ => [] + +private theorem opFold_calls (ops : List Op) (acc : Array FunIdx) : + (ops.foldl (fun acc op => match op with + | .call function _ _ false => acc.push function | _ => acc) acc).toList = + acc.toList ++ ops.flatMap Op.constrainedCalls := by + induction ops generalizing acc with + | nil => simp + | cons op ops ih => + simp only [List.foldl_cons, ih, List.flatMap_cons] + cases op <;> try rfl + rename_i function indices size unconstrained + cases unconstrained <;> simp [Op.constrainedCalls, Array.toList_push, List.append_assoc] + +theorem Block.collect_calls (block : Block) : + block.collectConstrainedCallees.toList = + block.ops.toList.flatMap Op.constrainedCalls ++ block.ctrl.collectConstrainedCallees.toList := by + rw [Block.collectConstrainedCallees] + simp only [Array.toList_append, ← Array.foldl_toList] + exact congrArg (· ++ block.ctrl.collectConstrainedCallees.toList) (opFold_calls block.ops.toList #[]) + +private theorem branchFold_calls (items : List (G × Block)) (acc : Array FunIdx) : + (items.foldl (fun acc pair => acc ++ pair.2.collectConstrainedCallees) acc).toList = + acc.toList ++ items.flatMap (fun pair => pair.2.collectConstrainedCallees.toList) := by + induction items generalizing acc with + | nil => simp + | cons pair items ih => simp [List.foldl_cons, ih, List.append_assoc] + +private theorem branchArray_calls (branches : Array (G × Block)) : + (branches.attach.foldl (fun acc pair => acc ++ pair.val.2.collectConstrainedCallees) #[]).toList = + branches.toList.flatMap (fun pair => pair.2.collectConstrainedCallees.toList) := by + rw [← Array.foldl_toList] + have mapped := List.foldl_map (f := fun (pair : { x // x ∈ branches }) => pair.val) + (g := fun (acc : Array FunIdx) pair => acc ++ pair.2.collectConstrainedCallees) + (l := branches.attach.toList) (init := #[]) + rw [← mapped] + have values : branches.attach.toList.map (fun pair => pair.val) = branches.toList := by + rw [Array.toList_attach, List.attachWith_map_subtype_val] + rw [values, branchFold_calls] + rfl + +def branchCalls (branches : Array (G × Block)) (fallback : Option Block) : List FunIdx := + branches.toList.flatMap (fun pair => pair.2.collectConstrainedCallees.toList) ++ + fallback.toList.flatMap (fun block => block.collectConstrainedCallees.toList) + +theorem Ctrl.collect_match (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : + (Ctrl.match index branches fallback).collectConstrainedCallees.toList = branchCalls branches fallback := by + rw [Ctrl.collectConstrainedCallees.eq_def] + cases fallback <;> simp [branchCalls] + all_goals simpa only [Array.size_attach] using branchArray_calls branches + +theorem Ctrl.collect_continue (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) + (size aux lookups : Nat) (continuation : Block) : + (Ctrl.matchContinue index branches fallback size aux lookups continuation).collectConstrainedCallees.toList = + branchCalls branches fallback ++ continuation.collectConstrainedCallees.toList := by + rw [Ctrl.collectConstrainedCallees.eq_def] + cases fallback <;> simp [branchCalls, List.append_assoc] + all_goals simpa only [Array.size_attach] using branchArray_calls branches + +namespace AIR + +theorem Step.calls_collected {memory : Memory} {op : Op} {values outputs : Array G} {calls : List Call} + (execution : Step memory op values outputs calls) : ∀ child ∈ calls, child.function ∈ op.constrainedCalls := by + intro child member + cases execution with + | primitive _ => cases member + | call _ _ => simp only [List.mem_singleton.mp member, Op.constrainedCalls, List.mem_singleton] + | store _ _ => cases member + | load _ _ _ => cases member + +theorem RunOps.calls_collected {memory : Memory} {ops : List Op} {values outputs : Array G} {calls : List Call} + (execution : RunOps memory ops values outputs calls) : + ∀ child ∈ calls, child.function ∈ ops.flatMap Op.constrainedCalls := by + induction execution with + | nil => intro child member; cases member + | @cons op ops values intermediate firstCalls outputs restCalls first rest ih => + intro child member + simp only [List.flatMap_cons] + rcases List.mem_append.mp member with head | tail + · exact List.mem_append_left _ (first.calls_collected child head) + · exact List.mem_append_right _ (ih child tail) + +theorem SelectArm.calls_collected {scrutinee : G} {branches : Array (G × Block)} + {fallback : Option Block} {arm : Block} (selected : SelectArm scrutinee branches fallback arm) : + arm.collectConstrainedCallees.toList ⊆ branchCalls branches fallback := by + intro child member + cases selected with + | case present => + exact List.mem_append_left _ (List.mem_flatMap.mpr ⟨_, present, member⟩) + | fallback present _ => + exact List.mem_append_right _ (List.mem_flatMap.mpr ⟨arm, by simp [present], member⟩) + +theorem RunBlock.calls_collected {memory : Memory} {block : Block} {values : Array G} + {outcome : Outcome} {calls : List Call} (execution : RunBlock memory block values outcome calls) : + ∀ child ∈ calls, child.function ∈ block.collectConstrainedCallees.toList := by + induction execution using RunBlock.rec + (motive_2 := fun ctrl _ _ calls _ => ∀ child ∈ calls, child.function ∈ ctrl.collectConstrainedCallees.toList) with + | block operations control ih => + intro child member + rw [Block.collect_calls] + rcases List.mem_append.mp member with first | last + · exact List.mem_append_left _ (operations.calls_collected child first) + · exact List.mem_append_right _ (ih child last) + | returned _ child member => cases member + | yielded _ child member => cases member + | «match» value selected branch ih child member => + rw [Ctrl.collect_match] + exact selected.calls_collected (ih child member) + | matchContinueReturn value selected branch ih child member => + rw [Ctrl.collect_continue] + exact List.mem_append_left _ (selected.calls_collected (ih child member)) + | matchContinueYield value selected branch outputSize continued ihBranch ihCont child member => + rw [Ctrl.collect_continue] + rcases List.mem_append.mp member with first | last + · exact List.mem_append_left _ (selected.calls_collected (ihBranch child first)) + · exact List.mem_append_right _ (ihCont child last) + +end AIR + +theorem Toplevel.validCallComponents_size {program : Toplevel} + (valid : program.validCallComponents = true) : program.callComponents.size = program.functions.size := by + simp only [Toplevel.validCallComponents, Bool.and_eq_true, beq_iff_eq] at valid + exact valid.1.1 + +theorem Toplevel.validCallComponents_order {program : Toplevel} + (valid : program.validCallComponents = true) {index : Nat} {component : CallComponent} + (present : program.callComponents[index]? = some component) : component.order < program.functions.size := by + simp only [Toplevel.validCallComponents, Bool.and_eq_true] at valid + have bounds := valid.1.2 + exact decide_eq_true_eq.mp (Array.all_eq_true'.mp bounds component (Array.mem_of_getElem? present)) + +def Toplevel.ComponentEdge (program : Toplevel) (parent child : FunIdx) : Prop := + ∃ parentComponent childComponent, + program.callComponents[parent]? = some parentComponent ∧ + program.callComponents[child]? = some childComponent ∧ parentComponent.permits childComponent = true + +theorem Toplevel.validCallComponents_edge {program : Toplevel} + (valid : program.validCallComponents = true) {parent child : FunIdx} {function : Function} + (present : program.functions[parent]? = some function) (constrained : function.constrained = true) + (called : child ∈ function.body.collectConstrainedCallees.toList) : program.ComponentEdge parent child := by + simp only [Toplevel.validCallComponents, Bool.and_eq_true] at valid + have functions := valid.2 + obtain ⟨bound, rfl⟩ := Array.getElem?_eq_some_iff.mp present + have atParent := Array.all_eq_true'.mp functions _ + (Array.getElem_mem (xs := program.functions.mapIdx fun i f => !f.constrained || + f.body.collectConstrainedCallees.all (fun j => match program.callComponents[i]?, program.callComponents[j]? with + | some parent, some child => parent.permits child | _, _ => false)) + (i := parent) (by simpa only [Array.size_mapIdx] using bound)) + simp only [Array.getElem_mapIdx, constrained, Bool.not_true, Bool.false_or, id_eq] at atParent + have edge := Array.all_eq_true'.mp atParent child (Array.mem_toList_iff.mp called) + unfold Toplevel.ComponentEdge + cases parentComponent : program.callComponents[parent]? <;> + cases childComponent : program.callComponents[child]? <;> + simp only [parentComponent, childComponent, Bool.false_eq_true] at edge + exact ⟨_, _, rfl, rfl, edge⟩ + +theorem AIR.RunFunction.calls_components {program : Toplevel} {memory : AIR.Memory} + {request : AIR.Call} {calls : List AIR.Call} (execution : AIR.RunFunction program memory request calls) + (valid : program.validCallComponents = true) {function : Function} + (present : program.functions[request.function]? = some function) (constrained : function.constrained = true) : + ∀ child ∈ calls, program.ComponentEdge request.function child.function := by + cases execution with + | function selected arity body => + have same := Option.some.inj (selected.symm.trans present) + subst function + intro child called + exact Toplevel.validCallComponents_edge valid selected constrained (body.calls_collected child called) + +theorem Toplevel.callRanksFor_read {program : Toplevel} {parent child : FunIdx} + {parentComponent childComponent : CallComponent} + (parentPresent : program.callComponents[parent]? = some parentComponent) + (childPresent : program.callComponents[child]? = some childComponent) : + (program.callRanksFor parent)[child]? = some + (if parentComponent.order == childComponent.order then .ordered + else if childComponent.ranked then .bound else .zero) := by + simp only [Toplevel.callRanksFor, Array.getElem?_map, childPresent, Option.map_some] + rw [Array.getElem!_eq_getD, Array.getD_eq_getD_getElem?, parentPresent] + rfl + +theorem CallComponent.permits_same {parent child : CallComponent} + (permitted : parent.permits child = true) (same : parent.order = child.order) : + parent.ranked = true ∧ child.ranked = true := by + simpa only [CallComponent.permits, same, Nat.lt_irrefl, decide_false, Bool.false_or, + BEq.rfl, Bool.true_and, Bool.and_eq_true] using permitted + +theorem CallComponent.permits_other {parent child : CallComponent} + (permitted : parent.permits child = true) (different : parent.order ≠ child.order) : + parent.order < child.order := by + simpa only [CallComponent.permits, beq_eq_false_iff_ne.mpr different, Bool.false_and, + Bool.or_false, decide_eq_true_eq] using permitted + +theorem Toplevel.ComponentEdge.ordered {program : Toplevel} {parent child : FunIdx} + (edge : program.ComponentEdge parent child) {parentComponent childComponent : CallComponent} + (parentPresent : program.callComponents[parent]? = some parentComponent) + (childPresent : program.callComponents[child]? = some childComponent) + (same : parentComponent.order = childComponent.order) : + parentComponent.ranked = true ∧ childComponent.ranked = true ∧ + (program.callRanksFor parent)[child]? = some .ordered := by + obtain ⟨a, b, parentRead, childRead, permitted⟩ := edge + have sameParent := Option.some.inj (parentRead.symm.trans parentPresent) + have sameChild := Option.some.inj (childRead.symm.trans childPresent) + subst a b + obtain ⟨parentRanked, childRanked⟩ := CallComponent.permits_same permitted same + refine ⟨parentRanked, childRanked, ?_⟩ + simpa only [same, BEq.rfl, if_true] using Toplevel.callRanksFor_read parentPresent childPresent + +theorem Toplevel.ComponentEdge.cross {program : Toplevel} {parent child : FunIdx} + (edge : program.ComponentEdge parent child) {parentComponent childComponent : CallComponent} + (parentPresent : program.callComponents[parent]? = some parentComponent) + (childPresent : program.callComponents[child]? = some childComponent) + (different : parentComponent.order ≠ childComponent.order) : + parentComponent.order < childComponent.order ∧ + (program.callRanksFor parent)[child]? = some (if childComponent.ranked then .bound else .zero) := by + obtain ⟨a, b, parentRead, childRead, permitted⟩ := edge + have sameParent := Option.some.inj (parentRead.symm.trans parentPresent) + have sameChild := Option.some.inj (childRead.symm.trans childPresent) + subst a b + refine ⟨CallComponent.permits_other permitted different, ?_⟩ + simpa only [beq_eq_false_iff_ne.mpr different, Bool.false_eq_true, if_false] using + Toplevel.callRanksFor_read parentPresent childPresent + +def Toplevel.componentFor (program : Toplevel) (function : FunIdx) : CallComponent := + program.callComponents[function]?.getD default + +theorem Toplevel.componentFor_read {program : Toplevel} {function : FunIdx} {component : CallComponent} + (present : program.callComponents[function]? = some component) : program.componentFor function = component := by + simp only [Toplevel.componentFor, present, Option.getD_some] + +theorem Toplevel.ComponentEdge.permits {program : Toplevel} {parent child : FunIdx} + (edge : program.ComponentEdge parent child) : + (program.componentFor parent).permits (program.componentFor child) = true := by + obtain ⟨a, b, parentRead, childRead, permitted⟩ := edge + simpa only [Toplevel.componentFor_read parentRead, Toplevel.componentFor_read childRead] using permitted + +theorem Toplevel.ComponentEdge.rankMode {program : Toplevel} {parent child : FunIdx} + (edge : program.ComponentEdge parent child) + (same : (program.componentFor parent).order = (program.componentFor child).order) : + (program.callRanksFor parent)[child]?.getD .ordered = .ordered := by + obtain ⟨a, b, parentRead, childRead, _⟩ := edge + simp only [Toplevel.componentFor_read parentRead, Toplevel.componentFor_read childRead] at same + rw [Toplevel.callRanksFor_read parentRead childRead] + simp only [same, BEq.rfl, if_true, Option.getD_some] + +theorem Toplevel.validCallComponents_component_order {program : Toplevel} + (valid : program.validCallComponents = true) {index : FunIdx} {function : Function} + (present : program.functions[index]? = some function) : + (program.componentFor index).order < program.functions.size := by + have bound : index < program.callComponents.size := by + rw [Toplevel.validCallComponents_size valid] + exact (Array.getElem?_eq_some_iff.mp present).1 + have read := Array.getElem?_eq_getElem bound + rw [Toplevel.componentFor_read read] + exact Toplevel.validCallComponents_order valid read + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ComponentCircuitCounts.lean b/Ix/Aiur/Proofs/ComponentCircuitCounts.lean new file mode 100644 index 000000000..810f384ed --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCircuitCounts.lean @@ -0,0 +1,188 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitMembers +import Ix.Aiur.Proofs.CircuitRowCounts + +/-! The enforced row-count check controls component members, branches and +returns. A nonzero shared provider supplies the selected component member's +actual return message before interpreting any of its calls. -/ + +namespace Aiur.AIR +open Bytecode + +theorem componentCircuitEmission_return_count {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (shape : ∀ member ∈ members, member.function.body.lookupShapes program none = true) + (bounded : members.length < gSize.toNat) + (returnBound : ∀ member ∈ members, + (member.function.body.selectorFlow (member.selector row)).returns.length < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) + (active : (componentCircuitEmission row program circuit members).selector = 1) : + ((componentCircuitEmission row program circuit members).returns.map Prod.fst).count 1 = 1 := by + have each := fun member present => MemberEmission.FromProgram.return_count (source member present) + (shape member present) (returnBound member present) (circuitEmission_member_satisfied satisfied present) + change ((members.flatMap (·.body.returns)).map Prod.fst).count 1 = 1 + rw [flatMap_return_count members (fun member => member.entry row) (fun member => member.body.returns) each] + apply selectorSum_active_count + · intro gate present + obtain ⟨member, memberPresent, same⟩ := List.mem_map.mp present + subst gate + exact componentCircuitEmission_member_boolean source satisfied member memberPresent + · simpa only [List.length_map] using bounded + · exact active + +theorem componentCircuitEmission_return_message {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (shape : ∀ member ∈ members, member.function.body.lookupShapes program none = true) + (bounded : members.length < gSize.toNat) + (returnBound : ∀ member ∈ members, + (member.function.body.selectorFlow (member.selector row)).returns.length < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) + (active : (componentCircuitEmission row program circuit members).selector = 1) + (width : Nat) + (single : (componentCircuitEmission row program circuit members).branchless = true → + (componentCircuitEmission row program circuit members).returns.length ≤ 1) + {request : Bytecode.AIR.Call} (present : (1, request) ∈ (componentCircuitEmission row program circuit members).returns) : + padMessage width ((componentCircuitEmission row program circuit members).lookup 0).2 = + padMessage width (functionMessage request) := by + have count := componentCircuitEmission_return_count source shape bounded returnBound satisfied active + apply slotMessage_chosen_count width (componentCircuitEmission row program circuit members).branchless + (by simpa only [List.length_map] using single) + (fun part member => ?_) + (by simpa only [List.map_map, Function.comp_def] using count) + (List.mem_map.mpr ⟨(1, request), present, rfl⟩) rfl + obtain ⟨returned, returnMember, same⟩ := List.mem_map.mp member + subst part + obtain ⟨body, bodyMember, returnedMember⟩ := List.mem_flatMap.mp returnMember + exact MemberEmission.FromProgram.return_boolean (source body bodyMember) + (circuitEmission_member_satisfied satisfied bodyMember) returned returnedMember + +theorem componentCircuitEmission_member_rank {row : Nat → G} {program : Toplevel} + {circuit : Circuit} {members : List MemberEmission} {member : MemberEmission} (present : member ∈ members) : + (if (program.componentFor member.functionIndex).ranked then + packRank (componentCircuitEmission row program circuit members).rankBytes else 0) = + (if (program.componentFor member.functionIndex).ranked then packRank (circuitRankBytes row circuit.layout) else 0) := by + cases ranked : (program.componentFor member.functionIndex).ranked with + | false => simp only [Bool.false_eq_true, if_false] + | true => + have inside : member ∈ componentMembers program members := List.mem_filter.mpr ⟨present, ranked⟩ + have nonempty := List.isEmpty_eq_false_iff_exists_mem.mpr ⟨member, inside⟩ + simp only [if_true, componentCircuitEmission, nonempty, Bool.false_eq_true, if_false] + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitComponentRow_count_bounds (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) + (validated : circuit.validateRowCounts program = true) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + circuit.members.size < gSize.toNat ∧ + (∀ part ∈ emission.members, part.function.body.rowBounds (part.selector row)) ∧ + (∀ part ∈ emission.members, + (part.function.body.selectorFlow (part.selector row)).returns.length < gSize.toNat) ∧ + (emission.branchless = true → emission.returns.length ≤ 1) := by + obtain ⟨description, indices, source⟩ := circuit.emitComponentRow_spec row program emitted + obtain ⟨bounded, nodes, leaves⟩ := circuit.validateRowCounts_members program emission.members indices + (fun part member => (source part member).present) validated + refine ⟨bounded, ?_, ?_, ?_⟩ + · intro part member + exact part.function.body.rowBounds_of_controlCounts (part.selector row) (nodes part member) + · intro part member + exact part.function.body.return_bound_of_controlCounts (part.selector row) (nodes part member) + · intro branchless + have valid : ∀ equation ∈ (componentCircuitEmission row program circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have each : ∀ part ∈ emission.members, part.body.returns.length ≤ part.function.body.controlCounts.leaves := by + intro part member + have gates := congrArg List.length (MemberEmission.FromProgram.return_gates (source part member) + (circuitEmission_member_satisfied valid member)) + simp only [List.length_map] at gates + rw [gates] + exact part.function.body.returns_le_selectors (part.selector row) + have combined := flatMap_length_le_sum emission.members (·.body.returns) + (fun part => part.function.body.controlCounts.leaves) each + have returnsEq := congrArg CircuitEmission.returns description + rw [returnsEq] + rw [description] at branchless + change circuitBranchless circuit.layout.selectors (emission.members.map (·.function)) = true at branchless + unfold circuitBranchless at branchless + rw [Bool.and_eq_true] at branchless + have one := beq_iff_eq.mp branchless.1 + change (emission.members.flatMap (·.body.returns)).length ≤ 1 + omega + +theorem Circuit.emitComponentRow_active_member (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (bounded : circuit.members.size < gSize.toNat) (nonzero : emission.multiplicity ≠ 0) : + ∃ member ∈ emission.members, member.entry row = 1 ∧ + member.FromComponent row (packRank emission.rankBytes) + (circuit.layout.inputSize + circuit.layout.selectors + 1) program := by + obtain ⟨description, indices, source⟩ := circuit.emitComponentRow_spec row program emitted + have length := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at length + have valid : ∀ equation ∈ (componentCircuitEmission row program circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have activity := circuitEmission_activity valid + have multiplicityEq := congrArg CircuitEmission.multiplicity description + change emission.multiplicity = (circuitEmission row circuit emission.members).multiplicity at multiplicityEq + have active := nonzero_multiplicity_selector_one activity (multiplicityEq ▸ nonzero) + change selectorSum (emission.members.map (fun member : MemberEmission => member.entry row)) = 1 at active + have count := selectorSum_active_count + (selectors := emission.members.map (fun member : MemberEmission => member.entry row)) + (fun gate present => by + obtain ⟨member, memberPresent, same⟩ := List.mem_map.mp present + subst gate + exact componentCircuitEmission_member_boolean source valid member memberPresent) + (by simpa only [List.length_map, length] using bounded) active + have existsOne : (1 : G) ∈ emission.members.map (·.entry row) := List.count_pos_iff.mp (by omega) + obtain ⟨member, present, selected⟩ := List.mem_map.mp existsOne + refine ⟨member, present, selected, ?_⟩ + have rankEq := componentCircuitEmission_member_rank (program := program) (circuit := circuit) (row := row) present + rw [← description] at rankEq + unfold MemberEmission.FromComponent + rw [rankEq] + exact source member present + +theorem Circuit.emitComponentRow_provider (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) + (validated : circuit.validateRowCounts program = true) + (shape : ∀ part ∈ emission.members, part.function.body.lookupShapes program none = true) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) + (nonzero : emission.multiplicity ≠ 0) (width : Nat) : + ∃ request : AIR.Call, (1, request) ∈ emission.returns ∧ + padMessage width (emission.lookup 0).2 = padMessage width (functionMessage request) := by + obtain ⟨bounded, _, returnBound, single⟩ := circuit.emitComponentRow_count_bounds row program emitted validated satisfied + obtain ⟨description, indices, source⟩ := circuit.emitComponentRow_spec row program emitted + have size := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at size + have valid : ∀ equation ∈ (componentCircuitEmission row program circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have active : (componentCircuitEmission row program circuit emission.members).selector = 1 := + nonzero_multiplicity_selector_one (circuitEmission_activity valid) (by + change (componentCircuitEmission row program circuit emission.members).multiplicity ≠ 0 + rw [← description] + exact nonzero) + have count := componentCircuitEmission_return_count source shape (by omega) returnBound valid active + rw [← description] at count + have present : (1 : G) ∈ emission.returns.map Prod.fst := List.count_pos_iff.mp (by rw [count]; decide) + obtain ⟨⟨gate, request⟩, member, gateEq⟩ := List.mem_map.mp present + change gate = 1 at gateEq + subst gate + refine ⟨request, member, ?_⟩ + have message := componentCircuitEmission_return_message source shape (by omega) returnBound valid active width + (by rw [← description]; exact single) (by rw [← description]; exact member) + rw [← description] at message + exact message + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ComponentCircuitExecution.lean b/Ix/Aiur/Proofs/ComponentCircuitExecution.lean new file mode 100644 index 000000000..17b6eac26 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCircuitExecution.lean @@ -0,0 +1,173 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitCounts +import Ix.Aiur.Proofs.ComponentCircuitQueries + +/-! A nonzero component circuit provider yields a locally valid function +row. Its actual call messages and precisely the rank ranges used by the +component order belong to the balanced physical query pool. -/ + +namespace Aiur.AIR +open Bytecode + +theorem componentCircuitEmission_member_queried {row : Nat → G} {program : Toplevel} + {circuit : Circuit} {members : List MemberEmission} {queries : List (List G)} + (queried : (componentCircuitEmission row program circuit members).QueriesIn queries) + {member : MemberEmission} (present : member ∈ members) : member.body.QueriesIn queries := by + intro query queryPresent active + exact queried query (List.mem_append_left _ (List.mem_flatMap.mpr ⟨member, present, queryPresent⟩)) active + +theorem componentCircuitEmission_rank_active {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) (bounded : circuit.members.size < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) + {member : MemberEmission} (present : member ∈ members) + (ranked : (program.componentFor member.functionIndex).ranked = true) (active : member.entry row = 1) : + selectorSum ((componentMembers program members).map (·.entry row)) = 1 := by + have individual : ∀ gate ∈ (componentMembers program members).map (·.entry row), gate = 0 ∨ gate = 1 := by + intro gate gatePresent + obtain ⟨part, partPresent, same⟩ := List.mem_map.mp gatePresent + subst gate + exact G.boolean_of_constraint + (componentCircuitEmission_member_boolean source satisfied part (List.mem_filter.mp partPresent).1) + have inside : (1 : G) ∈ (componentMembers program members).map (·.entry row) := + List.mem_map.mpr ⟨member, List.mem_filter.mpr ⟨present, ranked⟩, active⟩ + have counts := componentCircuitEmission_rank_count source count bounded satisfied + rw [gateCount_list] at counts + have positive := List.count_pos_iff.mpr inside + have limit := gateCount_le_one (selectorSum ((componentMembers program members).map (·.entry row))) + have one : ((componentMembers program members).map (·.entry row)).count 1 = 1 := by omega + rw [selectorSum_eq_count _ individual, one] + rfl + +theorem componentCircuitEmission_rank_queried {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} {queries : List (List G)} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) (bounded : circuit.members.size < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) + (queried : (componentCircuitEmission row program circuit members).QueriesIn queries) + {member : MemberEmission} (present : member ∈ members) + (ranked : (program.componentFor member.functionIndex).ranked = true) (active : member.entry row = 1) : + (rankByteQueries (componentCircuitEmission row program circuit members).rankBytes).map rangeMessage ⊆ queries := by + have rankActive := componentCircuitEmission_rank_active source count bounded satisfied present ranked active + have inside : member ∈ componentMembers program members := List.mem_filter.mpr ⟨present, ranked⟩ + have nonempty := List.isEmpty_eq_false_iff_exists_mem.mpr ⟨member, inside⟩ + simp only [componentCircuitEmission, nonempty, Bool.false_eq_true, if_false] at queried ⊢ + intro message messagePresent + obtain ⟨part, partPresent, selectorEq, messageEq⟩ := + queryParts_member 1 (selectorSum ((componentMembers program members).map (·.entry row))) messagePresent + have found := queried part (List.mem_append_right _ partPresent) (selectorEq.trans rankActive) + rwa [messageEq] at found + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitComponentRow_valid_in_pool {tables : LookupTables} {width : Nat} + {emissions : List CircuitEmission} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (row : Nat → G) (program : Toplevel) (components : program.validCallComponents = true) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) + (member : emission ∈ emissions) (pooled : circuitQueryPool emissions ⊆ queries) + (validated : circuit.validateRowCounts program = true) + (shape : ∀ part ∈ emission.members, part.function.body.lookupShapes program none = true) + (constrained : ∀ part ∈ emission.members, part.function.constrained = true) + (reserved : 0 < emission.lookupCount) + (ranges : ∀ part ∈ emission.queries, 0 < part.slot ∧ part.slot < emission.lookupCount) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (nonzero : emission.multiplicity ≠ 0) : + ∃ selected ∈ emission.members, ∃ interpreted : FunctionRow, + interpreted.ComponentValid program (memoryFacts tables.memory) ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = rowValues (rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = program.componentRowRank selected.functionIndex emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + padMessage width (emission.lookup 0).2 = padMessage width (functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + (interpreted.requests.map functionMessage) ⊆ queries ∧ + ((interpreted.componentByteQueries program).map rangeMessage) ⊆ queries := by + obtain ⟨bounded, bounds, returnBound, single⟩ := circuit.emitComponentRow_count_bounds row program emitted validated satisfied + obtain ⟨description, indices, source⟩ := circuit.emitComponentRow_spec row program emitted + have count := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at count + have valid : ∀ equation ∈ (componentCircuitEmission row program circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have slots := circuit.emitComponentRow_querySlots row program emitted bounded bounds reserved ranges satisfied + have inCircuit := slots.circuit_pool member + have queried : emission.QueriesIn queries := fun query present active => pooled (inCircuit query present active) + have wholeQueried : (componentCircuitEmission row program circuit emission.members).QueriesIn queries := by + rw [← description] + exact queried + have activity := circuitEmission_activity valid + change activityConstraint (componentCircuitEmission row program circuit emission.members).multiplicity + (componentCircuitEmission row program circuit emission.members).selector = 0 at activity + rw [← description] at activity + have active := nonzero_multiplicity_selector_one activity nonzero + obtain ⟨selected, selectedMember, selectedActive, selectedSource⟩ := + circuit.emitComponentRow_active_member row program emitted satisfied bounded nonzero + have bodySatisfied := circuitEmission_member_satisfied valid selectedMember + have bodyQueried := componentCircuitEmission_member_queried wholeQueried selectedMember + have selectedActivity : activityConstraint emission.multiplicity + (selected.function.body.selectorFlow (selected.selector row)).entry = 0 := by + change activityConstraint emission.multiplicity (selected.entry row) = 0 + rw [selectedActive] + rw [active] at activity + exact activity + obtain ⟨interpreted, interpretedValid, returned, functionEq, inputsEq, rankEq, + rankBytesEq, selectorEq, multiplicityEq, called, inventory⟩ := + selected.function.emitRow_componentValid global memoryValid canonical program components row (selected.selector row) + selected.functionIndex emission.rankBytes (rowAdvice row 0 selected.function.layout.inputSize) + _ _ selectedSource.present (constrained selected selectedMember) (by simp only [rowAdvice, Array.size_ofFn]) + (shape selected selectedMember) (bounds selected selectedMember) selectedSource.emitted + emission.multiplicity nonzero selectedActivity bodySatisfied bodyQueried + have interpretedActive : interpreted.selector = 1 := selectorEq.trans selectedActive + have returnMember : (1, interpreted.request) ∈ emission.returns := by + have returnsEq := congrArg CircuitEmission.returns description + rw [returnsEq] + exact List.mem_flatMap.mpr ⟨selected, selectedMember, returned⟩ + have message := componentCircuitEmission_return_message source shape (by omega) returnBound valid + (by rw [← description]; exact active) width + (by rw [← description]; exact single) (by rw [← description]; exact returnMember) + rw [← description] at message + refine ⟨selected, selectedMember, interpreted, interpretedValid, functionEq, inputsEq, rankEq, + rankBytesEq, interpretedActive.trans active.symm, multiplicityEq, returnMember, message, called, ?_, ?_⟩ + · intro message present + simp only [FunctionRow.requests, List.map_map, List.mem_map, Function.comp_def] at present + obtain ⟨edge, edgeMember, same⟩ := present + rw [← same] + exact (inventory edge edgeMember).1 + · intro message present + rw [FunctionRow.componentByteQueries, List.map_append] at present + rcases List.mem_append.mp present with header | gap + · cases ranked : (program.componentFor interpreted.request.function).ranked with + | false => simp only [ranked, Bool.false_eq_true, if_false, List.map_nil, List.not_mem_nil] at header + | true => + simp only [ranked, if_true, rankBytesEq] at header + have selectedRanked : (program.componentFor selected.functionIndex).ranked = true := functionEq ▸ ranked + have headers := componentCircuitEmission_rank_queried source count bounded valid wholeQueried + selectedMember selectedRanked selectedActive + rw [← description] at headers + exact headers header + · obtain ⟨pair, pairMember, messageEq⟩ := List.mem_map.mp gap + obtain ⟨edge, edgeMember, pairMember⟩ := List.mem_flatMap.mp pairMember + split at pairMember + · rename_i same + obtain ⟨function, present, functionConstrained⟩ := interpretedValid.constrained interpretedActive + have componentEdge := (interpretedValid.execution interpretedActive).calls_components components + present functionConstrained edge.1 (List.mem_map.mpr ⟨edge, edgeMember, rfl⟩) + have mode := componentEdge.rankMode same + rw [functionEq] at mode + rw [← messageEq] + exact ((inventory edge edgeMember).2.ordered mode).1 (List.mem_map.mpr ⟨pair, pairMember, rfl⟩) + · cases pairMember + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ComponentCircuitExpressions.lean b/Ix/Aiur/Proofs/ComponentCircuitExpressions.lean new file mode 100644 index 000000000..79fd5ad4c --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCircuitExpressions.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitRows +import Ix.Aiur.Proofs.CompiledCircuitRows + +/-! Native expression order for circuits with static components. The generic +circuit emitter remains available for programs using the fallback layout. -/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter LookupEmitter BlockEmitter Compiler Bytecode + +def emitComponentMember (rank : Expr) (base selectorBase : Nat) + (program : Toplevel) (functionIndex : Nat) : Option Member := + let ranked := (program.componentFor functionIndex).ranked + emitMember (if ranked then rank else .konst 0) (AIR.componentColumn ranked base) + (AIR.componentLookup ranked) selectorBase program functionIndex (program.callRanksFor functionIndex) + +def emitComponentMembers (rank : Expr) (base selectorBase : Nat) + (program : Toplevel) : List Nat → Option (List Member) + | [] => some [] + | index :: indices => do + let member ← emitComponentMember rank base selectorBase program index + let rest ← emitComponentMembers rank base (selectorBase + member.function.layout.selectors) program indices + return member :: rest + +def componentMembers (program : Toplevel) (members : List Member) : List Member := + members.filter fun member => (program.componentFor member.functionIndex).ranked + +def componentCircuitEmission (program : Toplevel) (circuit : Circuit) (members : List Member) : Emission := + let ranked := componentMembers program members + let bytes := rankBytes circuit.layout + let rankSelector := sum (ranked.map (·.entry)) + { circuitEmission circuit members with + rankBytes := if ranked.isEmpty then fun _ => .konst 0 else bytes + queries := members.flatMap (·.body.queries) ++ + (if ranked.isEmpty then [] else queryParts 1 rankSelector (rangeSix bytes)) } + +def emitComponentCircuit (program : Toplevel) (circuit : Circuit) : Option Emission := do + let rank := packSix (rankBytes circuit.layout) + let base := circuit.layout.inputSize + circuit.layout.selectors + 1 + let members ← emitComponentMembers rank base circuit.layout.inputSize program circuit.members.toList + return componentCircuitEmission program circuit members + +/-- The metadata includes rank reads only when a ranked member exists. -/ +def Emission.componentReadBound (program : Toplevel) (emission : Emission) : Nat := + emission.members.foldl (fun bound member => max bound member.readBound) + (emission.selectorStart + emission.selectorCount + 1 + + if (componentMembers program emission.members).isEmpty then 0 else 6) + +/-- Checked extents needed to interpret every emitted read and logical slot. +Slot zero is reserved for the shared provider. -/ +def Emission.componentFootprint (program : Toplevel) (width : Nat) (emission : Emission) : Bool := + emission.componentReadBound program ≤ width && + (0 < emission.lookupCount && + emission.queries.all (fun part => 0 < part.slot && part.slot < emission.lookupCount)) + +theorem Emission.componentFootprint_read {program : Toplevel} {width : Nat} {emission : Emission} + (checked : emission.componentFootprint program width = true) : emission.componentReadBound program ≤ width := by + simp only [componentFootprint, Bool.and_eq_true, decide_eq_true_eq] at checked + exact checked.1 + +theorem Emission.componentFootprint_slots {program : Toplevel} {width : Nat} {emission : Emission} + (checked : emission.componentFootprint program width = true) : + ∀ part ∈ emission.queries, 0 < part.slot ∧ part.slot < emission.lookupCount := by + intro part present + simp only [componentFootprint, Bool.and_eq_true, decide_eq_true_eq] at checked + have bound := List.all_eq_true.mp checked.2.2 part present + simpa only [Bool.and_eq_true, decide_eq_true_eq] using bound + +end Aiur.NativeAIR.CircuitEmitter diff --git a/Ix/Aiur/Proofs/ComponentCircuitMembers.lean b/Ix/Aiur/Proofs/ComponentCircuitMembers.lean new file mode 100644 index 000000000..6cb84e2b4 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCircuitMembers.lean @@ -0,0 +1,147 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitRows +import Ix.Aiur.Proofs.CircuitRowReturns + +/-! Component member provenance and selector conservation. The circuit +header equations are shared across rank policies; each body retains its +own rank, column cursor, lookup cursor and call-rank table. -/ + +namespace Aiur.AIR +open Bytecode + +def MemberEmission.FromComponent (row : Nat → G) (rank : G) (base : Nat) + (program : Toplevel) (member : MemberEmission) : Prop := + member.FromProgram row (if (program.componentFor member.functionIndex).ranked then rank else 0) + (componentColumn (program.componentFor member.functionIndex).ranked base) + (componentLookup (program.componentFor member.functionIndex).ranked) + program (program.callRanksFor member.functionIndex) + +theorem emitComponentMember_spec {row : Nat → G} {rank : G} {base selectorBase : Nat} + {program : Toplevel} {functionIndex : FunIdx} {member : MemberEmission} + (emitted : emitComponentMember row rank base selectorBase program functionIndex = some member) : + member.functionIndex = functionIndex ∧ member.FromComponent row rank base program := by + obtain ⟨index, present, _, body⟩ := emitComponentMember_present emitted + refine ⟨index, ?_⟩ + unfold MemberEmission.FromComponent + rw [index] + exact ⟨by rw [index]; exact present, by simpa only [index] using body⟩ + +theorem componentCircuitEmission_member_boolean {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) : + ∀ member ∈ members, booleanConstraint (member.entry row) = 0 := by + intro member present + exact member.function.body.selectorFlow_boolean (member.selector row) + (MemberEmission.FromProgram.selector_satisfied (source member present) + (circuitEmission_member_satisfied satisfied present)) + +theorem componentCircuitEmission_boolean {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) : + booleanConstraint (componentCircuitEmission row program circuit members).selector = 0 := + circuitEmission_boolean_of_members (componentCircuitEmission_member_boolean source satisfied) count satisfied + +theorem componentCircuitEmission_gateCount {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) (bounded : circuit.members.size < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) : + ((members.map (·.entry row)).map gateCount).sum = + gateCount (componentCircuitEmission row program circuit members).selector := by + rw [gateCount_list] + apply selector_gateCount + · intro gate present + obtain ⟨member, memberPresent, same⟩ := List.mem_map.mp present + subst gate + exact componentCircuitEmission_member_boolean source satisfied member memberPresent + · simpa only [List.length_map, count] using bounded + · exact componentCircuitEmission_boolean source count satisfied + +theorem selectorSum_boolean_of_count {gates : List G} + (individual : ∀ gate ∈ gates, booleanConstraint gate = 0) (count : gates.count 1 ≤ 1) : + booleanConstraint (selectorSum gates) = 0 := by + rw [selectorSum_eq_count gates (fun gate present => G.boolean_of_constraint (individual gate present))] + have alternatives : gates.count 1 = 0 ∨ gates.count 1 = 1 := by omega + rcases alternatives with zero | one + · rw [zero] + rfl + · rw [one] + rfl + +theorem componentCircuitEmission_rank_boolean {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) (bounded : circuit.members.size < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) : + booleanConstraint (selectorSum ((componentMembers program members).map (·.entry row))) = 0 := by + have individual := componentCircuitEmission_member_boolean source satisfied + apply selectorSum_boolean_of_count + · intro gate present + obtain ⟨member, memberPresent, same⟩ := List.mem_map.mp present + subst gate + exact individual member (List.mem_filter.mp memberPresent).1 + · have subset := (List.filter_sublist (p := fun member : MemberEmission => + (program.componentFor member.functionIndex).ranked) (l := members)).map (fun member => member.entry row) + have smaller := subset.count_le (1 : G) + have counts := componentCircuitEmission_gateCount source count bounded satisfied + rw [gateCount_list] at counts + exact Nat.le_trans smaller (counts ▸ gateCount_le_one _) + +theorem componentCircuitEmission_rank_count {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) (bounded : circuit.members.size < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) : + (((componentMembers program members).map (·.entry row)).map gateCount).sum = + gateCount (selectorSum ((componentMembers program members).map (·.entry row))) := by + rw [gateCount_list] + apply selector_gateCount + · intro gate present + obtain ⟨member, memberPresent, same⟩ := List.mem_map.mp present + subst gate + exact componentCircuitEmission_member_boolean source satisfied member (List.mem_filter.mp memberPresent).1 + · simp only [List.length_map] + exact Nat.lt_of_le_of_lt (List.length_filter_le _ _) (count ▸ bounded) + · exact componentCircuitEmission_rank_boolean source count bounded satisfied + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitComponentRow_spec (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) : + emission = componentCircuitEmission row program circuit emission.members ∧ + emission.members.map MemberEmission.functionIndex = circuit.members.toList ∧ + ∀ member ∈ emission.members, member.FromComponent row (packRank (circuitRankBytes row circuit.layout)) + (circuit.layout.inputSize + circuit.layout.selectors + 1) program := by + simp only [Circuit.emitComponentRow, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i members membersEmitted + cases emitted + obtain ⟨indices, source⟩ := emitComponentMembers_present membersEmitted + exact ⟨rfl, indices, fun member present => (emitComponentMember_spec (source member present)).2⟩ + +theorem Circuit.emitComponentRow_boolean (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + booleanConstraint emission.selector = 0 := by + obtain ⟨description, indices, source⟩ := circuit.emitComponentRow_spec row program emitted + have count := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at count + have valid : ∀ equation ∈ (componentCircuitEmission row program circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have boolean := componentCircuitEmission_boolean source count valid + rw [← description] at boolean + exact boolean + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ComponentCircuitQueries.lean b/Ix/Aiur/Proofs/ComponentCircuitQueries.lean new file mode 100644 index 000000000..234c6cb54 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCircuitQueries.lean @@ -0,0 +1,197 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitMembers + +/-! Mixed circuits reuse rank slots for acyclic members. Distributing the +rank queries over their member selectors preserves natural active counts, +so member exclusivity still gives at most one active request per slot. -/ + +namespace Aiur.AIR +open Bytecode + +theorem queryCount_singleton (query : QueryPart) (slot : Nat) : + queryCount [query] slot = if query.slot = slot then gateCount query.selector else 0 := by + simp only [queryCount, List.filter_cons, List.filter_nil, Bool.and_eq_true, beq_iff_eq, gateCount] + by_cases equal : query.slot = slot <;> by_cases active : query.selector = 1 <;> + simp only [equal, active, if_true, if_false, List.length_cons, List.length_nil, + and_self, and_true, and_false] + +theorem queryParts_boolean (gate : G) (messages : List (List G)) (start : Nat) + (boolean : booleanConstraint gate = 0) : + ∀ query ∈ queryParts start gate messages, booleanConstraint query.selector = 0 := by + induction messages generalizing start with + | nil => simp [queryParts] + | cons message messages ih => + intro query present + rw [queryParts_cons] at present + rcases List.mem_cons.mp present with equal | later + · subst query + exact boolean + · exact ih (start + 1) query later + +theorem queryCount_queryParts (gate : G) (messages : List (List G)) (start slot : Nat) : + queryCount (queryParts start gate messages) slot = + gateCount gate * queryCount (queryParts start 1 messages) slot := by + induction messages generalizing start with + | nil => simp [queryParts, queryCount] + | cons message messages ih => + rw [queryParts_cons, queryParts_cons] + change queryCount ([⟨start, gate, message⟩] ++ queryParts (start + 1) gate messages) slot = + gateCount gate * queryCount ([⟨start, 1, message⟩] ++ queryParts (start + 1) 1 messages) slot + rw [queryCount_append, queryCount_append, queryCount_singleton, queryCount_singleton, ih, Nat.mul_add] + by_cases equal : start = slot <;> + simp only [equal, if_true, if_false, show gateCount (1 : G) = 1 from rfl, Nat.mul_one, Nat.mul_zero] + +theorem queryCount_flatMap_indexed {α : Type} (items : List α) (gate : α → G) + (messages : List (List G)) (start slot : Nat) : + queryCount (items.flatMap fun item => queryParts start (gate item) messages) slot = + ((items.map gate).map gateCount).sum * queryCount (queryParts start 1 messages) slot := by + induction items with + | nil => simp [queryCount] + | cons item items ih => + rw [List.flatMap_cons, queryCount_append, queryCount_queryParts, ih] + simp only [List.map_cons, List.sum_cons, Nat.add_mul] + +theorem queryCount_flatMap_append {α : Type} (items : List α) (left right : α → List QueryPart) (slot : Nat) : + queryCount (items.flatMap fun item => left item ++ right item) slot = + queryCount (items.flatMap left) slot + queryCount (items.flatMap right) slot := by + induction items with + | nil => rfl + | cons item items ih => + simp only [List.flatMap_cons, queryCount_append, ih] + omega + +theorem flatMap_if_filter {α β : Type} (items : List α) (chosen : α → Bool) (parts : α → List β) : + (items.flatMap fun item => if chosen item then parts item else []) = + (items.filter chosen).flatMap parts := by + induction items with + | nil => rfl + | cons item items ih => + cases selected : chosen item <;> + simp only [List.flatMap_cons, List.filter_cons, selected, Bool.false_eq_true, + if_true, if_false, ih, List.nil_append] + +theorem queryCount_flatMap_le_sum {α : Type} (items : List α) (parts : α → List QueryPart) + (gate : α → G) (slot : Nat) + (bounded : ∀ item ∈ items, queryCount (parts item) slot ≤ gateCount (gate item)) : + queryCount (items.flatMap parts) slot ≤ ((items.map gate).map gateCount).sum := by + induction items with + | nil => exact Nat.le_refl 0 + | cons item items ih => + simp only [List.flatMap_cons, queryCount_append, List.map_cons, List.sum_cons] + exact Nat.add_le_add (bounded item List.mem_cons_self) + (ih (fun item present => bounded item (List.mem_cons_of_mem _ present))) + +def MemberEmission.componentQueries (row : Nat → G) (rankBytes : Fin 6 → G) + (program : Toplevel) (member : MemberEmission) : List QueryPart := + member.body.queries ++ if (program.componentFor member.functionIndex).ranked then + queryParts 1 (member.entry row) ((rankByteQueries rankBytes).map rangeMessage) else [] + +theorem MemberEmission.FromComponent.querySlots {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {member : MemberEmission} (source : member.FromComponent row rank base program) + (rankBytes : Fin 6 → G) (bounds : member.function.body.rowBounds (member.selector row)) + (satisfied : ∀ equation ∈ member.body.equations, equation = 0) : + QuerySlots (member.entry row) 1 member.body.lookup (member.componentQueries row rankBytes program) := by + have bodySlots := MemberEmission.FromProgram.querySlots source bounds satisfied + have boolean := member.function.body.selectorFlow_boolean (member.selector row) + (MemberEmission.FromProgram.selector_satisfied source satisfied) + cases ranked : (program.componentFor member.functionIndex).ranked with + | false => + simpa only [MemberEmission.componentQueries, ranked, Bool.false_eq_true, if_false, + List.append_nil, componentLookup, Nat.add_zero] using bodySlots + | true => + have rankSlots : QuerySlots (member.entry row) 1 4 + (queryParts 1 (member.entry row) ((rankByteQueries rankBytes).map rangeMessage)) := + QuerySlots.indexed (member.entry row) 1 ((rankByteQueries rankBytes).map rangeMessage) boolean + have combined := (rankSlots.append (by simpa only [componentLookup, ranked, if_true] using bodySlots)).permuted + List.perm_append_comm + simpa only [MemberEmission.componentQueries, ranked, if_true] using combined + +theorem componentCircuitEmission_queries_count {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) (bounded : circuit.members.size < gSize.toNat) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) + (slot : Nat) : + queryCount (componentCircuitEmission row program circuit members).queries slot = + queryCount (members.flatMap fun member => + member.componentQueries row (circuitRankBytes row circuit.layout) program) slot := by + unfold MemberEmission.componentQueries + rw [queryCount_flatMap_append, flatMap_if_filter] + change queryCount (members.flatMap (·.body.queries) ++ + (if (componentMembers program members).isEmpty then [] else + queryParts 1 (selectorSum ((componentMembers program members).map (·.entry row))) + ((rankByteQueries (circuitRankBytes row circuit.layout)).map rangeMessage))) slot = _ + rw [queryCount_append] + congr 1 + change _ = queryCount ((componentMembers program members).flatMap fun member => + queryParts 1 (member.entry row) ((rankByteQueries (circuitRankBytes row circuit.layout)).map rangeMessage)) slot + cases empty : (componentMembers program members).isEmpty with + | true => + have absent : componentMembers program members = [] := List.isEmpty_iff.mp empty + simp only [if_true, absent, List.flatMap_nil] + | false => + simp only [Bool.false_eq_true, if_false] + rw [queryCount_queryParts, queryCount_flatMap_indexed] + exact congrArg (fun count => count * queryCount + (queryParts 1 1 ((rankByteQueries (circuitRankBytes row circuit.layout)).map rangeMessage)) slot) + (componentCircuitEmission_rank_count source count bounded satisfied).symm + +theorem componentCircuitEmission_querySlots {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (count : members.length = circuit.members.size) (bounded : circuit.members.size < gSize.toNat) + (bounds : ∀ member ∈ members, member.function.body.rowBounds (member.selector row)) + (reserved : 0 < circuit.layout.lookups) + (ranges : ∀ part ∈ (componentCircuitEmission row program circuit members).queries, + 0 < part.slot ∧ part.slot < circuit.layout.lookups) + (satisfied : ∀ equation ∈ (componentCircuitEmission row program circuit members).equations, equation = 0) : + QuerySlots (componentCircuitEmission row program circuit members).selector 1 circuit.layout.lookups + (componentCircuitEmission row program circuit members).queries := by + have each := fun member present => MemberEmission.FromComponent.querySlots (source member present) + (circuitRankBytes row circuit.layout) (bounds member present) (circuitEmission_member_satisfied satisfied present) + refine ⟨reserved, fun query present => ⟨(ranges query present).1, (ranges query present).2⟩, ?_, ?_⟩ + · intro query present + change query ∈ members.flatMap (·.body.queries) ++ _ at present + rcases List.mem_append.mp present with body | header + · obtain ⟨member, memberPresent, queryPresent⟩ := List.mem_flatMap.mp body + exact (each member memberPresent).boolean query (List.mem_append_left _ queryPresent) + · have rankedBoolean := componentCircuitEmission_rank_boolean source count bounded satisfied + split at header + · cases header + · exact queryParts_boolean _ _ _ rankedBoolean query header + · intro slot + rw [componentCircuitEmission_queries_count source count bounded satisfied] + exact Nat.le_trans (queryCount_flatMap_le_sum members _ (fun member => member.entry row) slot + (fun member present => (each member present).count slot)) + (Nat.le_of_eq (componentCircuitEmission_gateCount source count bounded satisfied)) + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitComponentRow_querySlots (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) + (bounded : circuit.members.size < gSize.toNat) + (bounds : ∀ member ∈ emission.members, member.function.body.rowBounds (member.selector row)) + (reserved : 0 < emission.lookupCount) + (ranges : ∀ part ∈ emission.queries, 0 < part.slot ∧ part.slot < emission.lookupCount) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) : + QuerySlots emission.selector 1 emission.lookupCount emission.queries := by + obtain ⟨description, indices, source⟩ := circuit.emitComponentRow_spec row program emitted + have count := congrArg List.length indices + simp only [List.length_map, Array.length_toList] at count + have lookupEq : emission.lookupCount = circuit.layout.lookups := congrArg CircuitEmission.lookupCount description + have valid : ∀ equation ∈ (componentCircuitEmission row program circuit emission.members).equations, equation = 0 := by + rw [← description] + exact satisfied + have slots := componentCircuitEmission_querySlots source count bounded bounds + (lookupEq ▸ reserved) (by rw [← description, ← lookupEq]; exact ranges) valid + rw [← description, ← lookupEq] at slots + exact slots + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ComponentCircuitReflection.lean b/Ix/Aiur/Proofs/ComponentCircuitReflection.lean new file mode 100644 index 000000000..8f824c6e1 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCircuitReflection.lean @@ -0,0 +1,202 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitExpressions + +/-! Expression reflection for mixed component circuits, including their +member-specific cursors and the selector that gates shared rank ranges. -/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter LookupEmitter BlockEmitter Compiler Bytecode + +theorem emitComponentMember_fields {rank : Expr} {base selectorBase : Nat} + {program : Toplevel} {functionIndex : Nat} {member : Member} + (emitted : emitComponentMember rank base selectorBase program functionIndex = some member) : + member.functionIndex = functionIndex ∧ program.functions[functionIndex]? = some member.function ∧ + member.selectorBase = selectorBase := by + simp only [emitComponentMember, emitMember, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i function present + dsimp only at emitted + split at emitted + · cases emitted + dsimp only at emitted + split at emitted + · cases emitted + cases emitted + exact ⟨rfl, present, rfl⟩ + +theorem emitComponentMember_reflects {values : Values G} (row : Nat → G) {rank : Expr} {r : G} + {base selectorBase : Nat} {program : Toplevel} {functionIndex : Nat} {member : Member} + (rankEval : (program.componentFor functionIndex).ranked = true → evalExpr values rank = some r) + (emitted : emitComponentMember rank base selectorBase program functionIndex = some member) + (reads : ∀ index < member.readBound, (values.columns .main .current)[index]? = some (row index)) : + ∃ result, AIR.emitComponentMember row r base selectorBase program functionIndex = some result ∧ + member.eval values = some result ∧ evalExpr values member.entry = some (result.entry row) := by + have selected : evalExpr values (if (program.componentFor functionIndex).ranked then rank else .konst 0) = + some (if (program.componentFor functionIndex).ranked then r else 0) := by + cases ranked : (program.componentFor functionIndex).ranked + · rfl + · exact rankEval ranked + exact emitMember_reflects row selected emitted reads + +theorem emitComponentMembers_reflects {values : Values G} (row : Nat → G) {rank : Expr} {r : G} + (base selectorBase : Nat) (program : Toplevel) (indices : List Nat) {members : List Member} + (rankEval : ∀ member ∈ members, (program.componentFor member.functionIndex).ranked = true → + evalExpr values rank = some r) + (emitted : emitComponentMembers rank base selectorBase program indices = some members) + (reads : ∀ member ∈ members, ∀ index < member.readBound, + (values.columns .main .current)[index]? = some (row index)) : + ∃ results, AIR.emitComponentMembers row r base selectorBase program indices = some results ∧ + members.mapM (Member.eval values) = some results ∧ + (members.map Member.entry).mapM (evalExpr values) = some (results.map (·.entry row)) ∧ + ((componentMembers program members).map Member.entry).mapM (evalExpr values) = + some ((AIR.componentMembers program results).map (·.entry row)) := by + induction indices generalizing selectorBase members with + | nil => cases emitted; exact ⟨[], rfl, rfl, rfl, rfl⟩ + | cons index indices ih => + simp only [emitComponentMembers, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i member memberEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i tail tailEmitted + cases emitted + have indexEq := (emitComponentMember_fields memberEmitted).1 + obtain ⟨result, memberRead, memberEval, entryEval⟩ := emitComponentMember_reflects row + (by rw [← indexEq]; exact rankEval member List.mem_cons_self) memberEmitted + (reads member List.mem_cons_self) + obtain ⟨results, resultsRead, resultsEval, entriesEval, rankedEval⟩ := ih _ + (fun member present => rankEval member (List.mem_cons_of_mem _ present)) tailEmitted + (fun member present => reads member (List.mem_cons_of_mem _ present)) + have fields := Member.eval_components memberEval + refine ⟨result :: results, ?_, ?_, ?_, ?_⟩ + · simp only [AIR.emitComponentMembers, memberRead, bind, Option.bind_some, ← fields.2.1, resultsRead, pure] + · simp only [List.mapM_cons, memberEval, resultsEval, bind, Option.bind_some, pure] + · simp only [List.map_cons, List.mapM_cons, entryEval, entriesEval, bind, Option.bind_some, pure] + · simp only [componentMembers, AIR.componentMembers, List.filter_cons, fields.1] + simp only [componentMembers, AIR.componentMembers] at rankedEval + split + · simp only [List.map_cons, List.mapM_cons, entryEval, bind, Option.bind_some] + rw [rankedEval] + rfl + · exact rankedEval + +theorem componentCircuitEmission_eval {values : Values G} (row : Nat → G) (program : Toplevel) + (circuit : Circuit) {members : List Member} {results : List AIR.MemberEmission} + (membersEval : members.mapM (Member.eval values) = some results) + (entriesEval : (members.map Member.entry).mapM (evalExpr values) = some (results.map (·.entry row))) + (rankedEval : ((componentMembers program members).map Member.entry).mapM (evalExpr values) = + some ((AIR.componentMembers program results).map (·.entry row))) + (reads : ∀ index < circuit.layout.inputSize + circuit.layout.selectors + 1 + + (if (componentMembers program members).isEmpty then 0 else 6), + (values.columns .main .current)[index]? = some (row index)) : + (componentCircuitEmission program circuit members).eval values = + some (AIR.componentCircuitEmission row program circuit results) := by + have selectorEval := sum_eval entriesEval + have rankSelectorEval := sum_eval rankedEval + have empty : (componentMembers program members).isEmpty = (AIR.componentMembers program results).isEmpty := by + have length := Bytecode.AIR.list_mapM_some_length _ _ _ rankedEval + simp only [List.length_map] at length + cases source : componentMembers program members <;> + cases target : AIR.componentMembers program results <;> simp_all + have physicalRanks (nonempty : (componentMembers program members).isEmpty = false) (index : Fin 6) : + evalExpr values (rankBytes circuit.layout index) = + some (AIR.circuitRankBytes row circuit.layout index) := by + exact reads (circuit.layout.inputSize + circuit.layout.selectors + 1 + index.val) (by + rw [nonempty]; simp only [Bool.false_eq_true, if_false]; omega) + have ranks (index : Fin 6) : + evalExpr values ((componentCircuitEmission program circuit members).rankBytes index) = + some ((AIR.componentCircuitEmission row program circuit results).rankBytes index) := by + cases present : (componentMembers program members).isEmpty + · simpa only [componentCircuitEmission, AIR.componentCircuitEmission, ← empty, present, + Bool.false_eq_true, if_false] using physicalRanks present index + · simp only [componentCircuitEmission, AIR.componentCircuitEmission, ← empty, present, if_true] + rfl + have multiplicityEval : evalExpr values (mainCurrent (circuit.layout.inputSize + circuit.layout.selectors)).expr = + some (row (circuit.layout.inputSize + circuit.layout.selectors)) := + reads (circuit.layout.inputSize + circuit.layout.selectors) (by omega) + have functions : members.map Member.function = results.map AIR.MemberEmission.function := by + have relation := AIR.mapM_forall₂ membersEval (fun _ _ _ reflected => (Member.eval_components reflected).2.1) + clear membersEval entriesEval selectorEval rankedEval rankSelectorEval empty physicalRanks ranks reads + induction relation with + | nil => rfl + | cons equal _ ih => simp only [List.map_cons, equal, ih] + have equations : (members.flatMap (·.body.equations)).mapM (evalExpr values) = + some (results.flatMap (·.body.equations)) := + list_mapM_flatMap membersEval (fun member => member.body.equations) (fun result => result.body.equations) + (evalExpr values) (fun _ _ reflected => + (BlockEmitter.Emission.eval_components (Member.eval_components reflected).2.2.2).2.2.2.1) + have queries : (members.flatMap (·.body.queries)).mapM (QueryExpr.eval values) = + some (results.flatMap (·.body.queries)) := + list_mapM_flatMap membersEval (fun member => member.body.queries) (fun result => result.body.queries) + (QueryExpr.eval values) (fun _ _ reflected => + (BlockEmitter.Emission.eval_components (Member.eval_components reflected).2.2.2).2.2.2.2.1) + have returns : (members.flatMap (·.body.returns)).mapM (ReturnExpr.eval values) = + some (results.flatMap (·.body.returns)) := + list_mapM_flatMap membersEval (fun member => member.body.returns) (fun result => result.body.returns) + (ReturnExpr.eval values) (fun _ _ reflected => + (BlockEmitter.Emission.eval_components (Member.eval_components reflected).2.2.2).2.2.2.2.2.1) + have oneMinus := Expr.frontSub_eval goldilocksLaws values + (show evalExpr values (.konst 1) = some 1 from rfl) selectorEval + have exclusive := Expr.frontMul_eval goldilocksLaws values selectorEval oneMinus + have activity := Expr.frontMul_eval goldilocksLaws values multiplicityEval oneMinus + have selectors := selectorEquations_eval row circuit.layout + (fun index bound => reads (circuit.layout.inputSize + index) (by omega)) + apply Emission.eval_of membersEval selectorEval multiplicityEval ranks rfl rfl rfl rfl + · simp only [componentCircuitEmission, AIR.componentCircuitEmission, circuitEmission, AIR.circuitEmission, functions] + · simp only [componentCircuitEmission, AIR.componentCircuitEmission, circuitEmission, AIR.circuitEmission, + List.mapM_append] + split <;> simp only [List.mapM_cons, List.mapM_nil, equations, selectors, exclusive, activity, + bind, Option.bind_some, pure, goldilocks_mul, goldilocks_sub, + AIR.oneSubBooleanConstraint, AIR.activityConstraint] + · cases present : (componentMembers program members).isEmpty + · have rankQueries := queryParts_eval rankSelectorEval (rangeSix_eval (rankBytes circuit.layout) + (AIR.circuitRankBytes row circuit.layout) (physicalRanks present)) 1 + simp only [componentCircuitEmission, AIR.componentCircuitEmission, ← empty, present, + Bool.false_eq_true, if_false, List.mapM_append, queries, rankQueries, bind, Option.bind_some, pure] + · simp only [componentCircuitEmission, AIR.componentCircuitEmission, ← empty, present, if_true, + List.append_nil, queries] + · exact returns + +theorem emitComponentCircuit_reflects {values : Values G} (row : Nat → G) (program : Toplevel) + (circuit : Circuit) {emission : Emission} + (emitted : emitComponentCircuit program circuit = some emission) + (reads : ∀ index < emission.componentReadBound program, + (values.columns .main .current)[index]? = some (row index)) : + ∃ result, circuit.emitComponentRow row program = some result ∧ emission.eval values = some result := by + simp only [emitComponentCircuit, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i members membersEmitted + cases emitted + let start := circuit.layout.inputSize + circuit.layout.selectors + 1 + + if (componentMembers program members).isEmpty then 0 else 6 + have header := fold_max_start Member.readBound members start + have headerReads : ∀ index < start, (values.columns .main .current)[index]? = some (row index) := + fun index bound => reads index (Nat.lt_of_lt_of_le bound header) + have rankEval : ∀ member ∈ members, (program.componentFor member.functionIndex).ranked = true → + evalExpr values (packSix (rankBytes circuit.layout)) = + some (AIR.packRank (AIR.circuitRankBytes row circuit.layout)) := by + intro member present ranked + have chosen : member ∈ componentMembers program members := List.mem_filter.mpr ⟨present, ranked⟩ + have nonempty : (componentMembers program members).isEmpty = false := + List.isEmpty_eq_false_iff.mpr (fun empty => by rw [empty] at chosen; cases chosen) + apply packSix_eval + intro index + exact headerReads (circuit.layout.inputSize + circuit.layout.selectors + 1 + index.val) (by + simp only [start, nonempty, Bool.false_eq_true, if_false]; omega) + obtain ⟨results, resultsRead, resultsEval, entriesEval, rankedEval⟩ := emitComponentMembers_reflects row + (circuit.layout.inputSize + circuit.layout.selectors + 1) circuit.layout.inputSize program circuit.members.toList + rankEval membersEmitted (fun member present index bound => reads index + (Nat.lt_of_lt_of_le bound (fold_max_member Member.readBound present start))) + refine ⟨AIR.componentCircuitEmission row program circuit results, ?_, + componentCircuitEmission_eval row program circuit resultsEval entriesEval rankedEval headerReads⟩ + simp only [Circuit.emitComponentRow, resultsRead, bind, Option.bind_some, pure] + +end Aiur.NativeAIR.CircuitEmitter diff --git a/Ix/Aiur/Proofs/ComponentCircuitRows.lean b/Ix/Aiur/Proofs/ComponentCircuitRows.lean new file mode 100644 index 000000000..7534f5430 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCircuitRows.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentFunctionRows +import Ix.Aiur.Proofs.CircuitRows + +/-! Valued circuit emission for checked static components. Each member +starts at its own auxiliary and lookup offsets. Acyclic members reuse the +rank columns and slots; only ranked member selectors gate rank ranges. -/ + +namespace Aiur.AIR +open Bytecode + +def componentColumn (ranked : Bool) (base : Nat) : Nat := base + if ranked then 6 else 0 +def componentLookup (ranked : Bool) : Nat := 1 + if ranked then 3 else 0 + +def emitComponentMember (row : Nat → G) (rank : G) (base selectorBase : Nat) + (program : Toplevel) (functionIndex : FunIdx) : Option MemberEmission := + let ranked := (program.componentFor functionIndex).ranked + emitMember row (if ranked then rank else 0) (componentColumn ranked base) + (componentLookup ranked) selectorBase program functionIndex (program.callRanksFor functionIndex) + +def emitComponentMembers (row : Nat → G) (rank : G) (base selectorBase : Nat) + (program : Toplevel) : List FunIdx → Option (List MemberEmission) + | [] => some [] + | index :: indices => do + let member ← emitComponentMember row rank base selectorBase program index + let rest ← emitComponentMembers row rank base + (selectorBase + member.function.layout.selectors) program indices + return member :: rest + +def componentMembers (program : Toplevel) (members : List MemberEmission) : List MemberEmission := + members.filter fun member => (program.componentFor member.functionIndex).ranked + +def componentCircuitEmission (row : Nat → G) (program : Toplevel) (circuit : Circuit) + (members : List MemberEmission) : CircuitEmission := + let ranked := componentMembers program members + let rankBytes := circuitRankBytes row circuit.layout + let rankSelector := selectorSum (ranked.map (·.entry row)) + { circuitEmission row circuit members with + rankBytes := if ranked.isEmpty then fun _ => 0 else rankBytes + queries := members.flatMap (·.body.queries) ++ + (if ranked.isEmpty then [] else + queryParts 1 rankSelector ((rankByteQueries rankBytes).map rangeMessage)) } + +theorem emitComponentMember_present {row : Nat → G} {rank : G} {base selectorBase : Nat} + {program : Toplevel} {functionIndex : FunIdx} {member : MemberEmission} + (emitted : emitComponentMember row rank base selectorBase program functionIndex = some member) : + member.functionIndex = functionIndex ∧ program.functions[functionIndex]? = some member.function ∧ + member.selectorBase = selectorBase ∧ + member.function.emitRow row (member.selector row) functionIndex + (if (program.componentFor functionIndex).ranked then rank else 0) + (rowAdvice row 0 member.function.layout.inputSize) + (componentColumn (program.componentFor functionIndex).ranked base) + (componentLookup (program.componentFor functionIndex).ranked) + (program.callRanksFor functionIndex) = some member.body := by + simp only [emitComponentMember, emitMember, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i function present + dsimp only at emitted + split at emitted + · cases emitted + rename_i body bodyEmitted + cases emitted + exact ⟨rfl, present, rfl, bodyEmitted⟩ + +theorem emitComponentMembers_present {row : Nat → G} {rank : G} {base selectorBase : Nat} + {program : Toplevel} {indices : List FunIdx} {members : List MemberEmission} + (emitted : emitComponentMembers row rank base selectorBase program indices = some members) : + members.map MemberEmission.functionIndex = indices ∧ + ∀ member ∈ members, + emitComponentMember row rank base member.selectorBase program member.functionIndex = some member := by + induction indices generalizing selectorBase members with + | nil => cases emitted; exact ⟨rfl, by simp⟩ + | cons index indices ih => + simp only [emitComponentMembers, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i rest restEmitted + cases emitted + obtain ⟨functionEq, _, selectorEq, _⟩ := emitComponentMember_present firstEmitted + obtain ⟨indicesEq, membersEq⟩ := ih restEmitted + refine ⟨by simp only [List.map_cons, functionEq, indicesEq], ?_⟩ + intro member present + rcases List.mem_cons.mp present with equal | later + · subst member + rw [functionEq, selectorEq] + exact firstEmitted + · exact membersEq member later + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +def Circuit.emitComponentRow (row : Nat → G) (program : Toplevel) (circuit : Circuit) : + Option CircuitEmission := do + let rank := packRank (circuitRankBytes row circuit.layout) + let base := circuit.layout.inputSize + circuit.layout.selectors + 1 + let members ← emitComponentMembers row rank base circuit.layout.inputSize program circuit.members.toList + return componentCircuitEmission row program circuit members + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ComponentCompiledRows.lean b/Ix/Aiur/Proofs/ComponentCompiledRows.lean new file mode 100644 index 000000000..300e505d3 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentCompiledRows.lean @@ -0,0 +1,111 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitReflection +import Ix.Aiur.Proofs.GraphWidths + +/-! The reconstructed component artifact checks its own column and slot +extents. Successful graph compilation supplies physical reflection without +an external layout-equality or read-bound premise. -/ + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter LookupEmitter BlockEmitter Compiler Bytecode + +def compileComponentCircuit (widths : GraphWidths) (program : Toplevel) (circuit : Circuit) : + Option Compiled := + if program.validCallComponents then do + let emission ← emitComponentCircuit program circuit + if emission.componentFootprint program widths.main then do + let base ← compileBase widths emission.lookups emission.equations + return ⟨emission, base⟩ + else none + else none + +theorem compileComponentCircuit_parts {widths : GraphWidths} {program : Toplevel} {circuit : Circuit} + {compiled : Compiled} (built : compileComponentCircuit widths program circuit = some compiled) : + program.validCallComponents = true ∧ + emitComponentCircuit program circuit = some compiled.emission ∧ + compiled.emission.componentFootprint program widths.main = true ∧ + compileBase widths compiled.emission.lookups compiled.emission.equations = some compiled.base := by + simp only [compileComponentCircuit, bind, Option.bind] at built + split at built + · rename_i components + split at built + · cases built + rename_i emission emitted + dsimp only at built + split at built + · rename_i footprint + split at built + · cases built + rename_i base compiled + cases built + exact ⟨components, emitted, footprint, compiled⟩ + · cases built + · cases built + +theorem Emission.componentFootprint_slots_eval {program : Toplevel} {width : Nat} + {emission : Emission} {values : Values G} {result : AIR.CircuitEmission} + (checked : emission.componentFootprint program width = true) + (evaluated : emission.eval values = some result) : + ∀ part ∈ result.queries, 0 < part.slot ∧ part.slot < result.lookupCount := by + obtain ⟨_, _, _, _, _, _, _, count, _, _, queries, _⟩ := Emission.eval_components evaluated + apply AIR.forall₂_right_property + apply AIR.mapM_forall₂ queries + intro query present part partEval + have bounded := Emission.componentFootprint_slots checked query present + rw [(QueryExpr.eval_components partEval).1, count] at bounded + exact bounded + +theorem Emission.componentFootprint_count_eval {program : Toplevel} {width : Nat} + {emission : Emission} {values : Values G} {result : AIR.CircuitEmission} + (checked : emission.componentFootprint program width = true) + (evaluated : emission.eval values = some result) : 0 < result.lookupCount := by + have count := (Emission.eval_components evaluated).2.2.2.2.2.2.2.1 + simp only [Emission.componentFootprint, Bool.and_eq_true, decide_eq_true_eq] at checked + rw [← count] + exact checked.2.1 + +theorem compileComponentCircuit_reflects {values : Values G} {widths : GraphWidths} + (fits : values.Fits widths) {program : Toplevel} {circuit : Circuit} {compiled : Compiled} + (built : compileComponentCircuit widths program circuit = some compiled) : + ∃ result buffer, + circuit.emitComponentRow (fun index => (values.columns .main .current)[index]?.getD 0) program = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) ∧ + 0 < result.lookupCount ∧ + (∀ part ∈ result.queries, 0 < part.slot ∧ part.slot < result.lookupCount) := by + obtain ⟨_, emitted, footprint, baseCompiled⟩ := compileComponentCircuit_parts built + have bound := Emission.componentFootprint_read footprint + obtain ⟨result, resultEmitted, evaluated⟩ := emitComponentCircuit_reflects (values := values) + (fun index => (values.columns .main .current)[index]?.getD 0) program circuit emitted (by + intro index indexBound + have size : index < (values.columns .main .current).size := by + rw [fits.1, GraphWidths.width] + exact Nat.lt_of_lt_of_le indexBound bound + simp only [Array.getElem?_eq_getElem size, Option.getD_some]) + obtain ⟨buffer, swept, lookups, zeros⟩ := compileBase_reflects goldilocksGraphLaws fits + compiled.emission.lookups compiled.emission.equations baseCompiled + have equations := (Emission.eval_components evaluated).2.2.2.2.2.2.2.2.2.1 + obtain ⟨messages, exprReads, graphReads⟩ := lookups.read + exact ⟨result, buffer, resultEmitted, swept, zeros.trans (equations_vanish equations), + graphReads.trans (exprReads.symm.trans (Emission.lookups_eval evaluated)), + Emission.componentFootprint_count_eval footprint evaluated, + Emission.componentFootprint_slots_eval footprint evaluated⟩ + +theorem compileComponentCircuit_widen {small large : GraphWidths} (widths : small.Le large) + {program : Toplevel} {circuit : Circuit} {compiled : Compiled} + (built : compileComponentCircuit small program circuit = some compiled) : + compileComponentCircuit large program circuit = some compiled := by + obtain ⟨components, emitted, footprint, baseCompiled⟩ := compileComponentCircuit_parts built + have bounded : compiled.emission.componentFootprint program large.main = true := by + simp only [Emission.componentFootprint, Bool.and_eq_true, decide_eq_true_eq] at footprint ⊢ + exact ⟨Nat.le_trans footprint.1 (widths.1 .main), footprint.2⟩ + simp only [compileComponentCircuit, components, if_true, emitted, bounded, + compileBase_widen widths _ _ baseCompiled, bind, Option.bind_some, pure] + +end Aiur.NativeAIR.CircuitEmitter diff --git a/Ix/Aiur/Proofs/ComponentEncodedExecution.lean b/Ix/Aiur/Proofs/ComponentEncodedExecution.lean new file mode 100644 index 000000000..4b545453d --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentEncodedExecution.lean @@ -0,0 +1,183 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentTableExecution +import Ix.Aiur.Proofs.EncodedCircuitExecution + +/-! Encoded native slots and decoded component requests have identical +padded messages. The existing branchless guard supplies a single terminal +member, so the ungated optimization also has one writer in each slot. -/ + +namespace Aiur.AIR +open Bytecode + +theorem componentCircuitEmission_single_writer {row : Nat → G} {rank : G} {base : Nat} + {program : Toplevel} {circuit : Circuit} {members : List MemberEmission} + (source : ∀ member ∈ members, member.FromComponent row rank base program) + (enabled : (componentCircuitEmission row program circuit members).branchless = true) + (slot : Nat) : + (querySlotParts (componentCircuitEmission row program circuit members).queries slot).length ≤ 1 := by + obtain ⟨member, membersEq, terminal⟩ := circuitBranchless_member enabled + subst members + have body := member.function.emitRow_terminal_writers row (member.selector row) member.functionIndex + (if (program.componentFor member.functionIndex).ranked then rank else 0) + (rowAdvice row 0 member.function.layout.inputSize) + (componentColumn (program.componentFor member.functionIndex).ranked base) + (componentLookup (program.componentFor member.functionIndex).ranked) + terminal (source member List.mem_cons_self).emitted + cases ranked : (program.componentFor member.functionIndex).ranked with + | false => + simpa only [componentCircuitEmission, componentMembers, List.filter_cons, ranked, Bool.false_eq_true, + if_false, List.filter_nil, List.isEmpty_nil, if_true, List.flatMap_cons, List.flatMap_nil, + List.append_nil] using body.single slot + | true => + have body' : QueryWriters 4 member.body.lookup member.body.queries := by + simpa only [componentLookup, ranked, if_true] using body + have headers := QueryWriters.indexed 1 (selectorSum [member.entry row]) + ((rankByteQueries (circuitRankBytes row circuit.layout)).map rangeMessage) + have combined := (headers.append body').permuted List.perm_append_comm + simpa only [componentCircuitEmission, componentMembers, List.filter_cons, ranked, if_true, + List.filter_nil, List.isEmpty_cons, Bool.false_eq_true, if_false, List.flatMap_cons, + List.flatMap_nil, List.append_nil, List.map_cons, List.map_nil] using combined.single slot + +end Aiur.AIR + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitComponentRow_queries_reflect (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitComponentRow row program = some emission) + (validated : circuit.validateRowCounts program = true) + (reserved : 0 < emission.lookupCount) + (ranges : ∀ part ∈ emission.queries, 0 < part.slot ∧ part.slot < emission.lookupCount) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (width : Nat) : + (encodedQueries emission.branchless emission.queries emission.lookupCount).map (padMessage width) = + (decodedQueries emission.queries emission.lookupCount).map (padMessage width) := by + obtain ⟨bounded, bounds, _, _⟩ := circuit.emitComponentRow_count_bounds row program emitted validated satisfied + have slots := circuit.emitComponentRow_querySlots row program emitted bounded bounds reserved ranges satisfied + obtain ⟨description, _, source⟩ := circuit.emitComponentRow_spec row program emitted + apply slots.queries_reflect + intro enabled slot + have writers := componentCircuitEmission_single_writer source (by rw [← description]; exact enabled) slot + rw [← description] at writers + exact writers + +end Aiur.Bytecode + +namespace Aiur.AIR +open Bytecode + +theorem componentCircuitWitnesses_queries_reflect {program : Toplevel} (witnesses : List CircuitWitness) + (counted : program.validateRowCounts = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.ComponentEmitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (ranges : ∀ witness ∈ witnesses, witness.QueryRanges) (width : Nat) : + (encodedCircuitQueryPool (witnesses.map (·.emission))).map (padMessage width) = + (circuitQueryPool (witnesses.map (·.emission))).map (padMessage width) := by + simp only [encodedCircuitQueryPool, circuitQueryPool, List.map_flatMap] + rw [List.flatMap, List.flatMap] + apply congrArg List.flatten + apply List.map_congr_left + intro emission member + obtain ⟨witness, witnessMember, equal⟩ := List.mem_map.mp member + subst emission + exact witness.circuit.emitComponentRow_queries_reflect witness.values program (emitted witness witnessMember) + (Toplevel.validateRowCounts_circuit counted (circuits witness witnessMember)) + (ranges witness witnessMember).1 (ranges witness witnessMember).2 (satisfied witness witnessMember) width + +theorem componentCircuitWitnesses_decoded_widths {program : Toplevel} (witnesses : List CircuitWitness) + (counted : program.validateRowCounts = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.ComponentEmitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (ranges : ∀ witness ∈ witnesses, witness.QueryRanges) (width : Nat) + (widths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) : + ∀ query ∈ circuitQueryPool (witnesses.map (·.emission)), query.length ≤ width := by + intro query member + obtain ⟨emission, emissionMember, queryMember⟩ := List.mem_flatMap.mp member + obtain ⟨witness, witnessMember, equal⟩ := List.mem_map.mp emissionMember + subst emission + obtain ⟨bounded, bounds, _, _⟩ := witness.circuit.emitComponentRow_count_bounds witness.values program + (emitted witness witnessMember) (Toplevel.validateRowCounts_circuit counted (circuits witness witnessMember)) + (satisfied witness witnessMember) + have slots := witness.circuit.emitComponentRow_querySlots witness.values program (emitted witness witnessMember) + bounded bounds (ranges witness witnessMember).1 (ranges witness witnessMember).2 (satisfied witness witnessMember) + exact slots.decoded_widths witness.emission.branchless width + (fun message present => widths message (List.mem_flatMap.mpr + ⟨witness.emission, List.mem_map.mpr ⟨witness, witnessMember, rfl⟩, present⟩)) query queryMember + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem Backend.public_component_circuit_execution {selection : Selection} (backend : Backend selection) + (components : backend.compiled.bytecode.validCallComponents = true) + (tables : AuxiliaryTables) (witnesses : List CircuitWitness) (width : Nat) + (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: circuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : (circuitQueryPool (witnesses.map (·.emission))).length + 1 < gSize.toNat) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ circuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ backend.compiled.bytecode.circuits) + (emitted : ∀ witness ∈ witnesses, witness.ComponentEmitted backend.compiled.bytecode) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes backend.compiled.bytecode) + (constrained : ∀ witness ∈ witnesses, witness.Constrained) + (ranges : ∀ witness ∈ witnesses, witness.QueryRanges) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) ⟨selection.function, input, selection.success, 0⟩ := by + let request : Call := ⟨selection.function, input, selection.success, 0⟩ + have normalized : PaddedLookupBalance width + (functionMessage request :: circuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission))) := by + apply balanced.congr_queries + change padMessage width (buildClaim selection.function input selection.success).toList :: _ = + padMessage width (functionMessage request) :: _ + rw [show padMessage width (functionMessage request) = + padMessage width (buildClaim selection.function input selection.success).toList from claim_padding selection width input] + apply componentCircuitWitnesses_execute tables witnesses normalized bounded ?_ memoryValid canonical + components backend.rowCounts backend.lookupShapes circuits emitted satisfied shapes constrained ranges + (fun _ member => List.mem_cons_of_mem _ member) (backend.root_lookupShape input arity) List.mem_cons_self + intro query member + rcases List.mem_cons.mp member with same | rest + · subst query + change (functionMessage ⟨selection.function, input, selection.success, 0⟩).length ≤ width + rw [claim_message, List.length_append, List.length_singleton, Array.length_toList] + exact publicWidth + · exact queryWidths query rest + +theorem Backend.encoded_component_circuit_execution {selection : Selection} (backend : Backend selection) + (components : backend.compiled.bytecode.validCallComponents = true) + (tables : AuxiliaryTables) (witnesses : List CircuitWitness) (width : Nat) + (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: encodedCircuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : (encodedCircuitQueryPool (witnesses.map (·.emission))).length + 1 < gSize.toNat) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ backend.compiled.bytecode.circuits) + (emitted : ∀ witness ∈ witnesses, witness.ComponentEmitted backend.compiled.bytecode) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes backend.compiled.bytecode) + (constrained : ∀ witness ∈ witnesses, witness.Constrained) + (ranges : ∀ witness ∈ witnesses, witness.QueryRanges) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) ⟨selection.function, input, selection.success, 0⟩ := by + have messages := componentCircuitWitnesses_queries_reflect witnesses backend.rowCounts circuits emitted satisfied ranges width + have lengths := congrArg List.length messages + simp only [List.length_map] at lengths + exact backend.public_component_circuit_execution components tables witnesses width input arity + (balanced.congr_queries (by simp only [List.map_cons, messages])) (by rwa [← lengths]) publicWidth + (componentCircuitWitnesses_decoded_widths witnesses backend.rowCounts circuits emitted satisfied ranges width queryWidths) + memoryValid canonical circuits emitted satisfied shapes constrained ranges + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/ComponentExecution.lean b/Ix/Aiur/Proofs/ComponentExecution.lean new file mode 100644 index 000000000..930987ab2 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentExecution.lean @@ -0,0 +1,177 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCalls +import Ix.Aiur.Proofs.Execution + +/-! Static-component row obligations and exact byte-query accounting. +The component certificate supplies constrained edges; range lookups supply +dynamic rank bounds. Physical emitter reflection is a separate link. -/ + +namespace Aiur.AIR +open Bytecode.AIR + +def FunctionRow.componentByteQueries (program : Bytecode.Toplevel) (row : FunctionRow) : List (G × G) := + (if (program.componentFor row.request.function).ranked then rankByteQueries row.rankBytes else []) ++ + row.calls.flatMap (fun edge => + if (program.componentFor row.request.function).order = (program.componentFor edge.1.function).order then + rankByteQueries edge.2 else []) + +def componentFunctionByteQueries (program : Bytecode.Toplevel) (rows : List FunctionRow) : List (G × G) := + rows.flatMap fun row => if row.selector = 1 then row.componentByteQueries program else [] + +/-- Local obligations for static components. The checked bytecode certificate +supplies component edges; row constraints supply ranks only where used. -/ +structure FunctionRow.ComponentValid (program : Bytecode.Toplevel) (memory : Memory) + (row : FunctionRow) : Prop where + selector : row.selector = 0 ∨ row.selector = 1 + activity : activityConstraint row.multiplicity row.selector = 0 + constrained : row.selector = 1 → ∃ function, + program.functions[row.request.function]? = some function ∧ function.constrained = true + rank : row.selector = 1 → row.request.rank = + if (program.componentFor row.request.function).ranked then packRank row.rankBytes else 0 + execution : row.selector = 1 → RunFunction program memory row.request row.requests + order : ∀ edge ∈ row.calls, + (program.componentFor row.request.function).order = (program.componentFor edge.1.function).order → + row.selector * callOrderConstraint row.request.rank edge.1.rank (packRank edge.2) = 0 + +theorem FunctionRow.ComponentValid.active_of_nonzero {program : Bytecode.Toplevel} + {memory : Memory} {row : FunctionRow} (valid : row.ComponentValid program memory) + (nonzero : row.multiplicity ≠ 0) : row.selector = 1 := by + rcases valid.selector with inactive | active + · exact False.elim (nonzero (inactive_multiplicity_zero inactive valid.activity)) + · exact active + +theorem componentByteQueries_member {program : Bytecode.Toplevel} {rows : List FunctionRow} {row : FunctionRow} + (member : row ∈ rows) (active : row.selector = 1) : + row.componentByteQueries program ⊆ componentFunctionByteQueries program rows := by + intro query queried + exact List.mem_flatMap.mpr ⟨row, member, by simpa only [if_pos active] using queried⟩ + +theorem componentQueries_provider {program : Bytecode.Toplevel} {memory : Memory} + {roots : List Call} {rows : List FunctionRow} + (valid : ∀ row ∈ rows, row.ComponentValid program memory) + (balanced : ExactLookupBalance (functionQueries roots rows) (functionProviders rows)) + (bounded : (functionQueries roots rows).length < gSize.toNat) + {request : Call} (queried : request ∈ functionQueries roots rows) : + ∃ row ∈ rows, row.request = request ∧ row.selector = 1 := by + obtain ⟨provider, member, same, nonzero⟩ := exactLookupBalance_provider balanced bounded queried + obtain ⟨row, rowMember, providerEq⟩ := List.mem_map.mp member + subst provider + exact ⟨row, rowMember, same, (valid row rowMember).active_of_nonzero nonzero⟩ + +theorem FunctionRow.ComponentValid.rank_bounded {program : Bytecode.Toplevel} + {memory : Memory} {rows : List FunctionRow} {row : FunctionRow} + (valid : row.ComponentValid program memory) (member : row ∈ rows) (active : row.selector = 1) + (weights : Fin 65536 → G) + (balanced : ExactLookupBalance (componentFunctionByteQueries program rows) (byteRangeProviders weights)) + (bounded : (componentFunctionByteQueries program rows).length < gSize.toNat) : + row.request.rank.n < callRankBound := by + rw [valid.rank active] + cases ranked : (program.componentFor row.request.function).ranked + · simp only [Bool.false_eq_true, if_false] + decide + · simp only [if_true] + apply packRank_lt + apply exactLookupBalance_rankBytes weights balanced bounded + intro pair queried + apply componentByteQueries_member member active + apply List.mem_append_left + simpa only [ranked, if_true] using queried + +theorem FunctionRow.ComponentValid.call_order {program : Bytecode.Toplevel} {memory : Memory} + {rows : List FunctionRow} {row : FunctionRow} (valid : row.ComponentValid program memory) + (member : row ∈ rows) (active : row.selector = 1) + (weights : Fin 65536 → G) + (balanced : ExactLookupBalance (componentFunctionByteQueries program rows) (byteRangeProviders weights)) + (bounded : (componentFunctionByteQueries program rows).length < gSize.toNat) + {edge : Call × (Fin 6 → G)} (called : edge ∈ row.calls) + (same : (program.componentFor row.request.function).order = (program.componentFor edge.1.function).order) + (childBound : edge.1.rank.n < callRankBound) : row.request.rank.n < edge.1.rank.n := by + have gapBound : (packRank edge.2).n < callRankBound := by + apply packRank_lt + apply exactLookupBalance_rankBytes weights balanced bounded + intro pair queried + apply componentByteQueries_member member active + apply List.mem_append_right + exact List.mem_flatMap.mpr ⟨edge, called, by simpa only [if_pos same] using queried⟩ + exact active_call_order_strict active (valid.rank_bounded member active weights balanced bounded) + childBound gapBound (valid.order edge called same) + +/-- Exact providers and checked component edges give finite execution. A +boundary call binds its child's rank through the full provider message; +only calls within a component use the gap-range queries. -/ +theorem componentRows_execute {program : Bytecode.Toplevel} {memory : Memory} + {roots : List Call} {rows : List FunctionRow} + (components : program.validCallComponents = true) + (valid : ∀ row ∈ rows, row.ComponentValid program memory) + (balanced : ExactLookupBalance (functionQueries roots rows) (functionProviders rows)) + (bounded : (functionQueries roots rows).length < gSize.toNat) + (weights : Fin 65536 → G) + (bytesBalanced : ExactLookupBalance (componentFunctionByteQueries program rows) (byteRangeProviders weights)) + (bytesBounded : (componentFunctionByteQueries program rows).length < gSize.toNat) + {row : FunctionRow} (member : row ∈ rows) (active : row.selector = 1) : + Execution program memory row.request := by + let ActiveRow := { row : FunctionRow // row ∈ rows ∧ row.selector = 1 } + let component := fun row : ActiveRow => program.componentFor row.val.request.function + let rank := fun row : ActiveRow => row.val.request.rank.n + have componentBound : ∀ row : ActiveRow, (component row).order < program.functions.size := by + intro current + obtain ⟨function, present, _⟩ := (valid current.val current.property.1).constrained current.property.2 + exact Bytecode.Toplevel.validCallComponents_component_order components present + have rankBound : ∀ row : ActiveRow, rank row < callRankBound := by + intro current + exact (valid current.val current.property.1).rank_bounded current.property.1 current.property.2 + weights bytesBalanced bytesBounded + have wellFounded := Bytecode.CallComponent.wellFounded_calls component rank + program.functions.size callRankBound componentBound rankBound + have all : ∀ current : ActiveRow, Execution program memory current.val.request := by + intro current + induction current using wellFounded.induction with + | h parent ih => + have parentValid := valid parent.val parent.property.1 + have localExecution := parentValid.execution parent.property.2 + obtain ⟨function, present, constrained⟩ := parentValid.constrained parent.property.2 + apply Execution.function localExecution + intro child called + obtain ⟨provider, providerMember, same, providerActive⟩ := + componentQueries_provider valid balanced bounded + (functionQueries_member parent.property.1 parent.property.2 called) + let found : ActiveRow := ⟨provider, providerMember, providerActive⟩ + have permitted := (localExecution.calls_components components present constrained child called).permits + have relation : (component parent).permits (component found) = true ∧ + ((component parent).order = (component found).order → rank parent < rank found) := by + constructor + · simpa only [component, found, same] using permitted + · intro shared + obtain ⟨edge, edgeMember, edgeEq⟩ := List.mem_map.mp called + have childBound := rankBound found + have sameComponent : (program.componentFor parent.val.request.function).order = + (program.componentFor edge.1.function).order := by + simpa only [component, found, same, edgeEq] using shared + have edgeBound : edge.1.rank.n < callRankBound := by + simpa only [rank, found, same, edgeEq] using childBound + have order := parentValid.call_order parent.property.1 parent.property.2 + weights bytesBalanced bytesBounded edgeMember sameComponent edgeBound + simpa only [rank, found, same, edgeEq] using order + simpa only [found, same] using ih found relation + exact all ⟨row, member, active⟩ + +theorem componentRoots_execute {program : Bytecode.Toplevel} {memory : Memory} + {roots : List Call} {rows : List FunctionRow} + (components : program.validCallComponents = true) + (valid : ∀ row ∈ rows, row.ComponentValid program memory) + (balanced : ExactLookupBalance (functionQueries roots rows) (functionProviders rows)) + (bounded : (functionQueries roots rows).length < gSize.toNat) + (weights : Fin 65536 → G) + (bytesBalanced : ExactLookupBalance (componentFunctionByteQueries program rows) (byteRangeProviders weights)) + (bytesBounded : (componentFunctionByteQueries program rows).length < gSize.toNat) + {request : Call} (root : request ∈ roots) : Execution program memory request := by + obtain ⟨row, member, same, active⟩ := componentQueries_provider valid balanced bounded + (List.mem_append_left _ root) + rw [← same] + exact componentRows_execute components valid balanced bounded weights bytesBalanced bytesBounded member active + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/ComponentFunctionRows.lean b/Ix/Aiur/Proofs/ComponentFunctionRows.lean new file mode 100644 index 000000000..e389a8ee8 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentFunctionRows.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentExecution +import Ix.Aiur.Proofs.FunctionRows + +/-! Component row obligations derived from the valued function emitter. +The checked call collector determines the mode of every executed edge. -/ + +namespace Aiur.Bytecode +open Aiur.AIR + +def Toplevel.componentRowRank (program : Toplevel) (functionIndex : FunIdx) + (rankBytes : Fin 6 → G) : G := + if (program.componentFor functionIndex).ranked then packRank rankBytes else 0 + +theorem Function.emitRow_componentValid {tables : LookupTables} {width : Nat} {queries : List (List G)} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (program : Toplevel) (components : program.validCallComponents = true) + (row : Nat → G) (selector : SelIdx → G) + (functionIndex : FunIdx) (rankBytes : Fin 6 → G) (values : Array RowValue) (column lookup : Nat) + (function : Function) (present : program.functions[functionIndex]? = some function) + (constrained : function.constrained = true) + (arity : values.size = function.layout.inputSize) + (shape : function.body.lookupShapes program none = true) (bounds : function.body.rowBounds selector) + {emission : BlockEmission} + (emitted : function.emitRow row selector functionIndex (program.componentRowRank functionIndex rankBytes) + values column lookup (program.callRanksFor functionIndex) = some emission) + (multiplicity : G) (nonzero : multiplicity ≠ 0) + (activity : activityConstraint multiplicity (function.body.selectorFlow selector).entry = 0) + (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.QueriesIn queries) : + ∃ interpreted : FunctionRow, interpreted.ComponentValid program (memoryFacts tables.memory) ∧ + (1, interpreted.request) ∈ emission.returns ∧ + interpreted.request.function = functionIndex ∧ interpreted.request.inputs = rowValues values ∧ + interpreted.request.rank = program.componentRowRank functionIndex rankBytes ∧ + interpreted.rankBytes = rankBytes ∧ + interpreted.selector = (function.body.selectorFlow selector).entry ∧ + interpreted.multiplicity = multiplicity ∧ emission.CallsAt interpreted.calls ∧ + CallsEmitted (program.componentRowRank functionIndex rankBytes) 1 emission.equations queries + interpreted.calls (program.callRanksFor functionIndex) := by + have active := nonzero_multiplicity_selector_one activity nonzero + obtain ⟨request, calls, member, functionEq, inputsEq, rankEq, execution, called, inventory⟩ := + function.emitRow_run global memoryValid canonical program row selector functionIndex + (program.componentRowRank functionIndex rankBytes) values column lookup + present arity shape bounds emitted active satisfied queried + let interpreted : FunctionRow := ⟨request, calls, rankBytes, 1, multiplicity⟩ + refine ⟨interpreted, ?_, member, functionEq, inputsEq, rankEq, rfl, active.symm, rfl, called, inventory⟩ + have selected : program.functions[request.function]? = some function := by + rw [functionEq] + exact present + refine ⟨Or.inr rfl, ?_, fun _ => ⟨function, selected, constrained⟩, ?_, fun _ => execution, ?_⟩ + · rw [active] at activity + exact activity + · intro _ + change request.rank = if (program.componentFor request.function).ranked then packRank rankBytes else 0 + rw [functionEq] + exact rankEq + · intro edge edgeMember same + have componentEdge := execution.calls_components components selected constrained edge.1 + (List.mem_map.mpr ⟨edge, edgeMember, rfl⟩) + have mode := componentEdge.rankMode same + rw [functionEq] at mode + change 1 * callOrderConstraint request.rank edge.1.rank (packRank edge.2) = 0 + rw [rankEq] + exact ((inventory edge edgeMember).2.ordered mode).2.satisfied satisfied + +end Aiur.Bytecode diff --git a/Ix/Aiur/Proofs/ComponentGlobalExecution.lean b/Ix/Aiur/Proofs/ComponentGlobalExecution.lean new file mode 100644 index 000000000..cb3ae21e2 --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentGlobalExecution.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentExecution +import Ix.Aiur.Proofs.GlobalLookups + +/-! Finite component execution from a single mixed padded balance. The +global consumer bound gives active providers; only the component-selected +rank and gap queries are used to rule out dynamic cycles. -/ + +namespace Aiur.AIR +open Bytecode.AIR + +theorem GlobalLookups.component_function_provider {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} + (valid : ∀ row ∈ tables.functions, row.ComponentValid program memory) + (programBound : program.functions.size < gSize.toNat) + {request : Call} (shape : request.LookupShape program) (queried : functionMessage request ∈ queries) : + ∃ row ∈ tables.functions, row.request = request ∧ row.selector = 1 := by + obtain ⟨provider, member, same, nonzero⟩ := paddedLookupBalance_provider global.balance global.count queried + have widthBound := global.widths _ queried + have minimum := functionMessage_minimum request + have channel := padMessage_channel (by omega : 0 < width) same + obtain ⟨row, rowMember, equal⟩ := tables.function_provider member channel + subst provider + have active := (valid row rowMember).active_of_nonzero nonzero + have exactCall := padded_functionMessage_reflects programBound shape + ((valid row rowMember).execution active) widthBound same.symm + exact ⟨row, rowMember, exactCall.symm, active⟩ + +theorem FunctionRow.ComponentValid.global_rank_bounded {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {row : FunctionRow} + (valid : row.ComponentValid program memory) (member : row ∈ tables.functions) (active : row.selector = 1) + (queried : (componentFunctionByteQueries program tables.functions).map rangeMessage ⊆ queries) : + row.request.rank.n < callRankBound := by + rw [valid.rank active] + cases ranked : (program.componentFor row.request.function).ranked with + | false => + simp only [Bool.false_eq_true, if_false] + decide + | true => + simp only [if_true] + apply packRank_lt + apply global.rank_bytes + intro message messageMember + obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp messageMember + apply queried + refine List.mem_map.mpr ⟨pair, componentByteQueries_member member active ?_, equal⟩ + apply List.mem_append_left + simpa only [ranked, if_true] using pairMember + +theorem FunctionRow.ComponentValid.global_call_order {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {row : FunctionRow} + (valid : row.ComponentValid program memory) (member : row ∈ tables.functions) (active : row.selector = 1) + (queried : (componentFunctionByteQueries program tables.functions).map rangeMessage ⊆ queries) + {edge : Call × (Fin 6 → G)} (called : edge ∈ row.calls) + (same : (program.componentFor row.request.function).order = (program.componentFor edge.1.function).order) + (childBound : edge.1.rank.n < callRankBound) : row.request.rank.n < edge.1.rank.n := by + have gapBound : (packRank edge.2).n < callRankBound := by + apply packRank_lt + apply global.rank_bytes + intro message messageMember + obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp messageMember + apply queried + refine List.mem_map.mpr ⟨pair, componentByteQueries_member member active ?_, equal⟩ + apply List.mem_append_right + exact List.mem_flatMap.mpr ⟨edge, called, by simpa only [if_pos same] using pairMember⟩ + exact active_call_order_strict active (valid.global_rank_bounded global member active queried) + childBound gapBound (valid.order edge called same) + +theorem GlobalLookups.component_rows_execute {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {roots : List Call} + (components : program.validCallComponents = true) (programValid : program.validateLookupShapes = true) + (valid : ∀ row ∈ tables.functions, row.ComponentValid program memory) + (functionsQueried : (functionQueries roots tables.functions).map functionMessage ⊆ queries) + (bytesQueried : (componentFunctionByteQueries program tables.functions).map rangeMessage ⊆ queries) + {row : FunctionRow} (member : row ∈ tables.functions) (active : row.selector = 1) + (shape : row.request.LookupShape program) : Execution program memory row.request := by + have programBound : program.functions.size < gSize.toNat := by + have checked := programValid + simp only [Bytecode.Toplevel.validateLookupShapes, Bool.and_eq_true, decide_eq_true_eq] at checked + exact checked.1 + let ActiveRow := { row : FunctionRow // row ∈ tables.functions ∧ row.selector = 1 ∧ row.request.LookupShape program } + let component := fun row : ActiveRow => program.componentFor row.val.request.function + let rank := fun row : ActiveRow => row.val.request.rank.n + have componentBound : ∀ row : ActiveRow, (component row).order < program.functions.size := by + intro current + obtain ⟨function, present, _⟩ := (valid current.val current.property.1).constrained current.property.2.1 + exact Bytecode.Toplevel.validCallComponents_component_order components present + have rankBound : ∀ row : ActiveRow, rank row < callRankBound := by + intro current + exact (valid current.val current.property.1).global_rank_bounded global + current.property.1 current.property.2.1 bytesQueried + have wellFounded := Bytecode.CallComponent.wellFounded_calls component rank + program.functions.size callRankBound componentBound rankBound + have all : ∀ current : ActiveRow, Execution program memory current.val.request := by + intro current + induction current using wellFounded.induction with + | h parent ih => + have parentValid := valid parent.val parent.property.1 + have localExecution := parentValid.execution parent.property.2.1 + obtain ⟨function, present, constrained, _, _⟩ := parent.property.2.2 + have children := localExecution.calls_lookupShape programValid present constrained + apply Execution.function localExecution + intro child called + obtain ⟨provider, providerMember, same, providerActive⟩ := + global.component_function_provider valid programBound (children child called) + (functionsQueried (List.mem_map.mpr + ⟨child, functionQueries_member parent.property.1 parent.property.2.1 called, rfl⟩)) + let found : ActiveRow := ⟨provider, providerMember, providerActive, by rw [same]; exact children child called⟩ + have permitted := (localExecution.calls_components components present constrained child called).permits + have relation : (component parent).permits (component found) = true ∧ + ((component parent).order = (component found).order → rank parent < rank found) := by + constructor + · simpa only [component, found, same] using permitted + · intro shared + obtain ⟨edge, edgeMember, edgeEq⟩ := List.mem_map.mp called + have childBound := rankBound found + have sameComponent : (program.componentFor parent.val.request.function).order = + (program.componentFor edge.1.function).order := by + simpa only [component, found, same, edgeEq] using shared + have edgeBound : edge.1.rank.n < callRankBound := by + simpa only [rank, found, same, edgeEq] using childBound + have order := parentValid.global_call_order global parent.property.1 parent.property.2.1 + bytesQueried edgeMember sameComponent edgeBound + simpa only [rank, found, same, edgeEq] using order + simpa only [found, same] using ih found relation + exact all ⟨row, member, active, shape⟩ + +theorem GlobalLookups.component_roots_execute {tables : LookupTables} {width : Nat} + {queries : List (List G)} (global : GlobalLookups tables width queries) + {program : Bytecode.Toplevel} {memory : Memory} {roots : List Call} + (components : program.validCallComponents = true) (programValid : program.validateLookupShapes = true) + (valid : ∀ row ∈ tables.functions, row.ComponentValid program memory) + (functionsQueried : (functionQueries roots tables.functions).map functionMessage ⊆ queries) + (bytesQueried : (componentFunctionByteQueries program tables.functions).map rangeMessage ⊆ queries) + {request : Call} (shape : request.LookupShape program) (root : request ∈ roots) : + Execution program memory request := by + have programBound : program.functions.size < gSize.toNat := by + have checked := programValid + simp only [Bytecode.Toplevel.validateLookupShapes, Bool.and_eq_true, decide_eq_true_eq] at checked + exact checked.1 + obtain ⟨row, member, same, active⟩ := global.component_function_provider valid programBound shape + (functionsQueried (List.mem_map.mpr ⟨request, List.mem_append_left _ root, rfl⟩)) + rw [← same] + exact global.component_rows_execute components programValid valid functionsQueried bytesQueried + member active (same ▸ shape) + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/ComponentTableExecution.lean b/Ix/Aiur/Proofs/ComponentTableExecution.lean new file mode 100644 index 000000000..5be317baa --- /dev/null +++ b/Ix/Aiur/Proofs/ComponentTableExecution.lean @@ -0,0 +1,181 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCircuitExecution +import Ix.Aiur.Proofs.ComponentGlobalExecution +import Ix.Aiur.Proofs.CircuitTableExecution + +/-! Construct component function rows from physical circuit providers in +two stages. Neither the provisional providers nor the final function rows +are assumed to be an honest execution trace. -/ + +namespace Aiur.AIR +open Bytecode + +def CircuitWitness.ComponentEmitted (program : Toplevel) (witness : CircuitWitness) : Prop := + witness.circuit.emitComponentRow witness.values program = some witness.emission + +def CircuitWitness.QueryRanges (witness : CircuitWitness) : Prop := + 0 < witness.emission.lookupCount ∧ + ∀ part ∈ witness.emission.queries, 0 < part.slot ∧ part.slot < witness.emission.lookupCount + +def CircuitWitness.Constrained (witness : CircuitWitness) : Prop := + ∀ part ∈ witness.emission.members, part.function.constrained = true + +def FunctionRow.ComponentQueriesIn (program : Toplevel) (queries : List (List G)) (row : FunctionRow) : Prop := + row.selector = 1 → row.requests.map functionMessage ⊆ queries ∧ + (row.componentByteQueries program).map rangeMessage ⊆ queries + +theorem FunctionRow.inactive_componentValid (program : Toplevel) (memory : Bytecode.AIR.Memory) : + inactive.ComponentValid program memory := by + have notActive : inactive.selector ≠ 1 := by + intro equal + have bad := congrArg G.n equal + change 0 = 1 at bad + omega + refine ⟨Or.inl rfl, ?_, fun active => False.elim (notActive active), + fun active => False.elim (notActive active), fun active => False.elim (notActive active), ?_⟩ + · change (0 : G) * (1 - 0) = 0 + rw [G.mul_comm, G.mul_zero] + · intro edge present + cases present + +theorem FunctionRow.inactive_componentQueried (program : Toplevel) (queries : List (List G)) : + inactive.ComponentQueriesIn program queries := by + intro active + have bad := congrArg G.n active + change 0 = 1 at bad + omega + +theorem CircuitWitness.component_provider_row {program : Toplevel} (witness : CircuitWitness) + (emitted : witness.ComponentEmitted program) (satisfied : witness.Satisfied) + (validated : witness.circuit.validateRowCounts program = true) (shape : witness.Shapes program) + (width : Nat) : ∃ row : FunctionRow, row.Provides width witness.emission := by + by_cases zero : witness.emission.multiplicity = 0 + · exact ⟨FunctionRow.inactive, FunctionRow.inactive_provides width zero⟩ + · obtain ⟨request, _, message⟩ := witness.circuit.emitComponentRow_provider witness.values program + emitted validated shape satisfied zero width + exact ⟨⟨request, [], witness.emission.rankBytes, 0, witness.emission.multiplicity⟩, + rfl, fun _ => message⟩ + +theorem CircuitWitness.component_interpreted_row {tables : LookupTables} {width : Nat} + {queries : List (List G)} {emissions : List CircuitEmission} + (global : GlobalLookups tables width queries) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + {program : Toplevel} (components : program.validCallComponents = true) (witness : CircuitWitness) + (emitted : witness.ComponentEmitted program) (satisfied : witness.Satisfied) + (validated : witness.circuit.validateRowCounts program = true) (shape : witness.Shapes program) + (constrained : witness.Constrained) (ranges : witness.QueryRanges) (member : witness.emission ∈ emissions) + (pooled : circuitQueryPool emissions ⊆ queries) : + ∃ row : FunctionRow, row.ComponentValid program (memoryFacts tables.memory) ∧ + row.Provides width witness.emission ∧ row.ComponentQueriesIn program queries := by + by_cases zero : witness.emission.multiplicity = 0 + · exact ⟨FunctionRow.inactive, FunctionRow.inactive_componentValid _ _, + FunctionRow.inactive_provides width zero, FunctionRow.inactive_componentQueried program queries⟩ + · obtain ⟨_, _, row, valid, _, _, _, _, _, multiplicity, _, message, _, called, bytes⟩ := + witness.circuit.emitComponentRow_valid_in_pool global memoryValid canonical witness.values program components + emitted member pooled validated shape constrained ranges.1 ranges.2 satisfied zero + exact ⟨row, valid, ⟨multiplicity.symm, fun _ => message⟩, fun _ => ⟨called, bytes⟩⟩ + +theorem componentFunctionQueries_in_pool {program : Toplevel} {queries : List (List G)} + {roots : List Bytecode.AIR.Call} {rows : List FunctionRow} + (rootQueries : roots.map functionMessage ⊆ queries) + (queried : ∀ row ∈ rows, row.ComponentQueriesIn program queries) : + (functionQueries roots rows).map functionMessage ⊆ queries := by + intro message present + obtain ⟨request, requestPresent, equal⟩ := List.mem_map.mp present + subst message + rcases List.mem_append.mp requestPresent with root | called + · exact rootQueries (List.mem_map.mpr ⟨request, root, rfl⟩) + · obtain ⟨row, rowMember, callMember⟩ := List.mem_flatMap.mp called + by_cases active : row.selector = 1 + · rw [if_pos active] at callMember + exact (queried row rowMember active).1 (List.mem_map.mpr ⟨request, callMember, rfl⟩) + · rw [if_neg active] at callMember + cases callMember + +theorem componentFunctionByteQueries_in_pool {program : Toplevel} {queries : List (List G)} + {rows : List FunctionRow} (queried : ∀ row ∈ rows, row.ComponentQueriesIn program queries) : + (componentFunctionByteQueries program rows).map rangeMessage ⊆ queries := by + intro message present + obtain ⟨pair, pairMember, equal⟩ := List.mem_map.mp present + subst message + obtain ⟨row, rowMember, queryMember⟩ := List.mem_flatMap.mp pairMember + by_cases active : row.selector = 1 + · rw [if_pos active] at queryMember + exact (queried row rowMember active).2 (List.mem_map.mpr ⟨pair, queryMember, rfl⟩) + · rw [if_neg active] at queryMember + cases queryMember + +theorem componentCircuitWitnesses_interpret (tables : AuxiliaryTables) {program : Toplevel} + (witnesses : List CircuitWitness) {width : Nat} {queries : List (List G)} + (balanced : PaddedLookupBalance width queries (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : queries.length < gSize.toNat) (widths : ∀ query ∈ queries, query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (components : program.validCallComponents = true) (counted : program.validateRowCounts = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.ComponentEmitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes program) + (constrained : ∀ witness ∈ witnesses, witness.Constrained) + (ranges : ∀ witness ∈ witnesses, witness.QueryRanges) + (pooled : circuitQueryPool (witnesses.map (·.emission)) ⊆ queries) : + ∃ functions : List FunctionRow, + List.Forall₂ (FunctionRow.Provides width) (witnesses.map (·.emission)) functions ∧ + GlobalLookups (tables.withFunctions functions) width queries ∧ + (∀ row ∈ functions, row.ComponentValid program (memoryFacts tables.memory)) ∧ + (∀ row ∈ functions, row.ComponentQueriesIn program queries) := by + have counts := fun witness member => Toplevel.validateRowCounts_circuit counted (circuits witness member) + obtain ⟨provisional, providers⟩ := forall₂_exists_right witnesses + (fun witness (row : FunctionRow) => row.Provides width witness.emission) + (fun witness member => witness.component_provider_row (emitted witness member) (satisfied witness member) + (counts witness member) (shapes witness member) width) + have providerRows := forall₂_map_left providers + have global := tables.global_of_circuit_balance balanced bounded widths providerRows + obtain ⟨functions, interpreted⟩ := forall₂_exists_right witnesses + (fun witness (row : FunctionRow) => row.ComponentValid program (memoryFacts tables.memory) ∧ + row.Provides width witness.emission ∧ row.ComponentQueriesIn program queries) + (fun witness member => witness.component_interpreted_row global memoryValid canonical components + (emitted witness member) (satisfied witness member) (counts witness member) (shapes witness member) + (constrained witness member) (ranges witness member) (List.mem_map.mpr ⟨witness, member, rfl⟩) pooled) + have provided : List.Forall₂ (FunctionRow.Provides width) (witnesses.map (·.emission)) functions := by + apply forall₂_map_left + exact forall₂_weaken interpreted (fun _ _ evidence => evidence.2.1) + refine ⟨functions, provided, tables.global_of_circuit_balance balanced bounded widths provided, ?_, ?_⟩ + · intro row member + obtain ⟨witness, _, evidence⟩ := forall₂_right_member interpreted member + exact evidence.1 + · intro row member + obtain ⟨witness, _, evidence⟩ := forall₂_right_member interpreted member + exact evidence.2.2 + +theorem componentCircuitWitnesses_execute (tables : AuxiliaryTables) {program : Toplevel} + (witnesses : List CircuitWitness) {width : Nat} {queries : List (List G)} + (balanced : PaddedLookupBalance width queries (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : queries.length < gSize.toNat) (widths : ∀ query ∈ queries, query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (components : program.validCallComponents = true) (counted : program.validateRowCounts = true) + (programShapes : program.validateLookupShapes = true) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ program.circuits) + (emitted : ∀ witness ∈ witnesses, witness.ComponentEmitted program) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (shapes : ∀ witness ∈ witnesses, witness.Shapes program) + (constrained : ∀ witness ∈ witnesses, witness.Constrained) + (ranges : ∀ witness ∈ witnesses, witness.QueryRanges) + (pooled : circuitQueryPool (witnesses.map (·.emission)) ⊆ queries) + {request : Bytecode.AIR.Call} (shape : request.LookupShape program) (root : functionMessage request ∈ queries) : + Bytecode.AIR.Execution program (memoryFacts tables.memory) request := by + obtain ⟨functions, _, global, valid, queried⟩ := componentCircuitWitnesses_interpret tables witnesses + balanced bounded widths memoryValid canonical components counted circuits emitted satisfied shapes constrained ranges pooled + apply global.component_roots_execute (roots := [request]) components programShapes valid + (componentFunctionQueries_in_pool ?_ queried) (componentFunctionByteQueries_in_pool queried) shape List.mem_cons_self + intro message member + have equal : message = functionMessage request := List.mem_singleton.mp member + rwa [equal] + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/EmissionAllocation.lean b/Ix/Aiur/Proofs/EmissionAllocation.lean index d72e5d8d0..c92c9f382 100644 --- a/Ix/Aiur/Proofs/EmissionAllocation.lean +++ b/Ix/Aiur/Proofs/EmissionAllocation.lean @@ -13,6 +13,8 @@ preserved from the initial advice map. -/ namespace Aiur.NativeAIR.OpEmitter open Aiur.Bytecode +variable {callRanks : Array CallRank} + def rowDegrees (rows : Array RowExpr) : Array Nat := rows.map RowExpr.degree theorem rowDegrees_empty : rowDegrees #[] = #[] := Array.map_empty @@ -86,7 +88,7 @@ theorem emitWordSum_allocation (first : Nat) (sum : RowExpr) : theorem emitByte1_dispatch_allocation (selector rank : Expr) (first : Nat) (kind : AIR.Byte1Kind) (index : Nat) {rows : Array RowExpr} {emission : Emission} - (emitted : emitOp selector rank first (kind.op index) rows = some emission) : + (emitted : emitOp selector rank first (kind.op index) rows callRanks = some emission) : emission.allocation = (kind.op index).allocation (rowDegrees rows) := by rw [emitOp_byte1] at emitted simp only [bind, Option.bind] at emitted @@ -98,7 +100,7 @@ theorem emitByte1_dispatch_allocation (selector rank : Expr) (first : Nat) (kind theorem emitByte2_dispatch_allocation (selector rank : Expr) (first : Nat) (kind : AIR.Byte2Kind) (a b : Nat) {rows : Array RowExpr} {emission : Emission} - (emitted : emitOp selector rank first (kind.op a b) rows = some emission) : + (emitted : emitOp selector rank first (kind.op a b) rows callRanks = some emission) : emission.allocation = (kind.op a b).allocation (rowDegrees rows) := by rw [emitOp_byte2] at emitted simp only [bind, Option.bind] at emitted @@ -116,10 +118,11 @@ theorem emitByte2_dispatch_allocation (selector rank : Expr) (first : Nat) (kind AIR.Byte2Kind.op, AIR.Byte2Kind.outputSize, Op.allocation, OpAllocation.advice, byteCarry, degreeA, degreeB] <;> rfl -theorem emitOp_allocation {selector rank : Expr} {first : Nat} {op : Op} +theorem emitOp_allocationFor {selector rank : Expr} {first : Nat} {op : Op} {rows : Array RowExpr} {emission : Emission} (valid : DegreeValid rows) - (emitted : emitOp selector rank first op rows = some emission) : - emission.allocation = op.allocation (rowDegrees rows) := by + (emitted : emitOp selector rank first op rows callRanks = some emission) : + emission.allocation = op.allocationFor callRanks (rowDegrees rows) := by + unfold Op.allocationFor cases op with | const value => cases emitted @@ -155,14 +158,14 @@ theorem emitOp_allocation {selector rank : Expr} {first : Nat} {op : Op} cases unconstrained with | true => cases emitted - simp only [emitAdvice_allocation, Op.allocation, if_true, Nat.add_zero, OpAllocation.advice] + simp only [emitAdvice_allocation, if_true, Nat.add_zero, OpAllocation.advice] | false => simp only [emitOp, Bool.false_eq_true, if_false, bind, Option.bind] at emitted split at emitted · cases emitted cases emitted - simp only [Emission.allocation, emitCall, advice_degrees, Op.allocation, - Bool.false_eq_true, if_false] + simp only [Emission.allocation, emitCall, advice_degrees, Bool.false_eq_true, if_false] + cases callRanks[function]?.getD .ordered <;> rfl | store indices | load size index => simp only [emitOp, bind, Option.bind] at emitted split at emitted @@ -249,19 +252,26 @@ theorem emitOp_allocation {selector rank : Expr} {first : Nat} {op : Op} cases emitted simp only [Emission.allocation, fromScalar, rowDegrees_singleton, Op.allocation, readWord_degree read] +theorem emitOp_allocation {selector rank : Expr} {first : Nat} {op : Op} + {rows : Array RowExpr} {emission : Emission} (valid : DegreeValid rows) + (emitted : emitOp selector rank first op rows = some emission) : + emission.allocation = op.allocation (rowDegrees rows) := by + simpa only [Op.allocationFor_empty] using emitOp_allocationFor valid emitted + theorem emitOp_layout {selector rank : Expr} {first : Nat} {op : Op} {rows : Array RowExpr} {emission : Emission} (initial : Concrete.Bytecode.LayoutMState) - (generic : initial.callRanks = #[]) + (generic : initial.callRanks = callRanks) (valid : DegreeValid rows) (aligned : rowDegrees rows = initial.degrees) - (emitted : emitOp selector rank first op rows = some emission) : + (emitted : emitOp selector rank first op rows callRanks = some emission) : ((Concrete.Bytecode.opLayout op).run initial).2.degrees = rowDegrees (rows ++ emission.outputs) ∧ ((Concrete.Bytecode.opLayout op).run initial).2.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + emission.used := by - have allocated := emitOp_allocation valid emitted + have allocated := emitOp_allocationFor valid emitted rw [aligned] at allocated have degrees := congrArg OpAllocation.degrees allocated have auxiliaries := congrArg OpAllocation.auxiliaries allocated - obtain ⟨layoutDegrees, layoutAux⟩ := Concrete.Bytecode.opLayout_genericAllocation op initial generic + obtain ⟨layoutDegrees, layoutAux⟩ := Concrete.Bytecode.opLayout_allocation op initial + rw [generic] at layoutDegrees layoutAux simp only [Emission.allocation] at degrees auxiliaries rw [← degrees] at layoutDegrees rw [← auxiliaries] at layoutAux @@ -269,10 +279,10 @@ theorem emitOp_layout {selector rank : Expr} {first : Nat} {op : Op} theorem emitOps_fold_layout {selector rank : Expr} {ops : List Op} {rows : Array RowExpr} {column : Nat} {emission : OpsEmission} (initial : Concrete.Bytecode.LayoutMState) (base : Nat) - (generic : initial.callRanks = #[]) + (generic : initial.callRanks = callRanks) (valid : DegreeValid rows) (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) - (emitted : emitOps selector rank ops rows column = some emission) : + (emitted : emitOps selector rank ops rows column callRanks = some emission) : ((ops.foldlM (fun _ op => Concrete.Bytecode.opLayout op) ()).run initial).2.degrees = rowDegrees emission.values ∧ emission.column = base + @@ -301,10 +311,10 @@ theorem emitOps_fold_layout {selector rank : Expr} {ops : List Op} {rows : Array theorem emitOps_layout {selector rank : Expr} {ops : Array Op} {rows : Array RowExpr} {column : Nat} {emission : OpsEmission} (initial : Concrete.Bytecode.LayoutMState) (base : Nat) - (generic : initial.callRanks = #[]) + (generic : initial.callRanks = callRanks) (valid : DegreeValid rows) (aligned : rowDegrees rows = initial.degrees) (cursor : column = base + initial.functionLayout.auxiliaries) - (emitted : emitOps selector rank ops.toList rows column = some emission) : + (emitted : emitOps selector rank ops.toList rows column callRanks = some emission) : ((ops.forM Concrete.Bytecode.opLayout).run initial).2.degrees = rowDegrees emission.values ∧ emission.column = base + ((ops.forM Concrete.Bytecode.opLayout).run initial).2.functionLayout.auxiliaries := by unfold Array.forM diff --git a/Ix/Aiur/Proofs/EmissionInputs.lean b/Ix/Aiur/Proofs/EmissionInputs.lean index a1f0ed67d..2a24c613c 100644 --- a/Ix/Aiur/Proofs/EmissionInputs.lean +++ b/Ix/Aiur/Proofs/EmissionInputs.lean @@ -59,11 +59,18 @@ theorem Op.allocation_outputSize (op : Op) (degrees : Array Nat) : | simp only [Array.size_replicate] | (split <;> rfl) +theorem Op.allocationFor_outputSize (op : Op) (callRanks : Array CallRank) (degrees : Array Nat) : + (op.allocationFor callRanks degrees).degrees.size = op.outputSize := by + cases op <;> simp only [Op.allocationFor, Op.allocation_outputSize] + simp only [Op.outputSize, Array.size_replicate] + end Aiur.Bytecode namespace Aiur.NativeAIR.OpEmitter open Bytecode +variable {callRanks : Array CallRank} + theorem list_mapM_defined {read : α → Option β} (inputs : List α) (defined : ∀ input ∈ inputs, ∃ output, read input = some output) : ∃ outputs, inputs.mapM read = some outputs := by @@ -95,7 +102,7 @@ theorem readWord_defined {rows : Array RowExpr} {indices : Array Nat} bind, Option.bind_some, pure]; rfl⟩ theorem emitOp_defined (selector rank : Expr) (first : Nat) (op : Op) (rows : Array RowExpr) - (checked : op.emissionInputs rows.size = true) : ∃ emission, emitOp selector rank first op rows = some emission := by + (checked : op.emissionInputs rows.size = true) : ∃ emission, emitOp selector rank first op rows callRanks = some emission := by cases op with | const | ioGetInfo | ioRead | ioSetInfo | ioWrite | debug | unconstrainedBigUintDivMod | unconstrainedGToBytes | unconstrainedGInverse => exact ⟨_, rfl⟩ @@ -146,19 +153,19 @@ theorem emitOp_defined (selector rank : Expr) (first : Nat) (op : Op) (rows : Ar theorem emitOp_outputSize {selector rank : Expr} {first : Nat} {op : Op} {rows : Array RowExpr} {emission : Emission} (valid : DegreeValid rows) - (emitted : emitOp selector rank first op rows = some emission) : + (emitted : emitOp selector rank first op rows callRanks = some emission) : emission.outputs.size = op.outputSize := by - have allocated := congrArg (fun allocation => allocation.degrees.size) (emitOp_allocation valid emitted) - simpa only [Emission.allocation, rowDegrees, Array.size_map, Op.allocation_outputSize] using allocated + have allocated := congrArg (fun allocation => allocation.degrees.size) (emitOp_allocationFor valid emitted) + simpa only [Emission.allocation, rowDegrees, Array.size_map, Op.allocationFor_outputSize] using allocated theorem emitOps_defined (selector rank : Expr) (ops : List Op) (rows : Array RowExpr) (column : Nat) {next : Nat} (valid : DegreeValid rows) (checked : checkEmissionOps ops rows.size = some next) : - ∃ emission, emitOps selector rank ops rows column = some emission ∧ emission.values.size = next := by + ∃ emission, emitOps selector rank ops rows column callRanks = some emission ∧ emission.values.size = next := by induction ops generalizing rows column with | nil => cases checked; exact ⟨_, rfl, rfl⟩ | cons op ops ih => obtain ⟨inputs, after, added, rest⟩ := checkEmissionOps_cons checked - obtain ⟨first, firstEmitted⟩ := emitOp_defined selector rank column op rows inputs + obtain ⟨first, firstEmitted⟩ := emitOp_defined (callRanks := callRanks) selector rank column op rows inputs have size := emitOp_outputSize valid firstEmitted have nextSize : (rows ++ first.outputs).size = after := by simp only [Array.size_append, size, (addScope_eq added).1] diff --git a/Ix/Aiur/Proofs/FunctionRows.lean b/Ix/Aiur/Proofs/FunctionRows.lean index 1cd904cb4..a15fffb78 100644 --- a/Ix/Aiur/Proofs/FunctionRows.lean +++ b/Ix/Aiur/Proofs/FunctionRows.lean @@ -42,8 +42,9 @@ namespace Aiur.Bytecode open Aiur.AIR def Function.emitRow (row : Nat → G) (selector : SelIdx → G) (functionIndex : FunIdx) (rank : G) - (values : Array RowValue) (column lookup : Nat) (function : Function) : Option BlockEmission := - function.body.emitRow row selector ⟨functionIndex, function.layout.inputSize, rank⟩ + (values : Array RowValue) (column lookup : Nat) (function : Function) + (callRanks : Array CallRank := #[]) : Option BlockEmission := + function.body.emitRow row selector ⟨functionIndex, function.layout.inputSize, rank, callRanks⟩ (function.body.selectorFlow selector).entry values column lookup theorem Function.emitRow_run {tables : LookupTables} {width : Nat} {queries : List (List G)} @@ -55,14 +56,14 @@ theorem Function.emitRow_run {tables : LookupTables} {width : Nat} {queries : Li (function : Function) (present : program.functions[functionIndex]? = some function) (arity : values.size = function.layout.inputSize) (shape : function.body.lookupShapes program none = true) (bounds : function.body.rowBounds selector) - {emission : BlockEmission} - (emitted : function.emitRow row selector functionIndex rank values column lookup = some emission) + {emission : BlockEmission} {callRanks : Array CallRank} + (emitted : function.emitRow row selector functionIndex rank values column lookup callRanks = some emission) (active : (function.body.selectorFlow selector).entry = 1) (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.QueriesIn queries) : ∃ request calls, (1, request) ∈ emission.returns ∧ request.function = functionIndex ∧ request.inputs = rowValues values ∧ request.rank = rank ∧ AIR.RunFunction program (memoryFacts tables.memory) request (calls.map Prod.fst) ∧ - emission.CallsAt calls ∧ CallsEmitted rank 1 emission.equations queries calls := by + emission.CallsAt calls ∧ CallsEmitted rank 1 emission.equations queries calls callRanks := by have bodyEmitted := emitted rw [Function.emitRow] at bodyEmitted have initial : RowInputs function.layout.inputSize (rowValues values) values := by @@ -132,8 +133,8 @@ theorem Function.emitRow_message (row : Nat → G) (selector : SelIdx → G) (functionIndex : FunIdx) (rank : G) (values : Array RowValue) (column lookup : Nat) (function : Function) (program : Toplevel) (shape : function.body.lookupShapes program none = true) - {emission : BlockEmission} - (emitted : function.emitRow row selector functionIndex rank values column lookup = some emission) + {emission : BlockEmission} {callRanks : Array CallRank} + (emitted : function.emitRow row selector functionIndex rank values column lookup callRanks = some emission) (active : (function.body.selectorFlow selector).entry = 1) (satisfied : ∀ equation ∈ emission.equations, equation = 0) (bounded : emission.returns.length < gSize.toNat) diff --git a/Ix/Aiur/Proofs/GraphLookupTraces.lean b/Ix/Aiur/Proofs/GraphLookupTraces.lean new file mode 100644 index 000000000..be4f2405b --- /dev/null +++ b/Ix/Aiur/Proofs/GraphLookupTraces.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.GraphTraces + +/-! Preserve the physical graph's row and slot order through trace extraction. +Slot zero is the function provider; the remaining slots are unit consumers. +This separation also applies when a provider's negative field multiplicity +happens to be one. -/ + +namespace Aiur.NativeAIR +open AIR Compiler OpEmitter + +abbrev LookupRow := List (G × List G) + +def Graph.readLookups (graph : Graph) (values : Values G) : Option LookupRow := do + let buffer ← graph.sweep goldilocksOps values + graph.lookups.mapM (readLookup buffer) + +def Graph.readTraceLookups (graph : Graph) (widths : GraphWidths) {height : Nat} + (matrix : Fin height → Nat → G) : Option (List LookupRow) := + (List.ofFn id).mapM fun index => graph.readLookups (traceRowValues widths matrix index) + +def emissionLookupRow (emission : CircuitEmission) : LookupRow := + List.ofFn fun slot : Fin emission.lookupCount => emission.lookup slot.val + +def graphRowQueries (row : LookupRow) : List (List G) := + (List.range row.length).filterMap fun slot => + if slot = 0 then none else do + let lookup ← row[slot]? + if lookup.1 = 1 then some lookup.2 else none + +def graphRowProvider (row : LookupRow) : Option (Provider (List G)) := + row[0]?.map fun lookup => (lookup.2, 0 - lookup.1) + +def graphFunctionQueries (rows : List LookupRow) : List (List G) := rows.flatMap graphRowQueries + +def graphFunctionProviders (rows : List LookupRow) : List (Provider (List G)) := rows.filterMap graphRowProvider + +theorem filterMap_eq_of_eq_on {left right : α → Option β} (inputs : List α) + (equal : ∀ input ∈ inputs, left input = right input) : inputs.filterMap left = inputs.filterMap right := by + induction inputs with + | nil => rfl + | cons input inputs ih => + simp only [List.filterMap_cons, equal input List.mem_cons_self, + ih (fun value member => equal value (List.mem_cons_of_mem _ member))] + +theorem encodedQuery_zero {emission : CircuitEmission} + (ranges : ∀ query ∈ emission.queries, 0 < query.slot) : + encodedQuery emission.branchless emission.queries 0 = none := by + have empty : emission.queries.filter (fun query => query.slot == 0) = [] := by + apply List.filter_eq_nil_iff.mpr + intro query member + simpa only [beq_iff_eq, Nat.ne_zero_iff_zero_lt] using ranges query member + simp only [encodedQuery, querySlotMultiplicity, querySlotParts, empty, + List.map_nil, selectorSum, List.foldl_nil, Ne.symm G.one_ne_zero, if_false] + +theorem graphRowQueries_emission (emission : CircuitEmission) + (ranges : ∀ query ∈ emission.queries, 0 < query.slot) : + graphRowQueries (emissionLookupRow emission) = + encodedQueries emission.branchless emission.queries emission.lookupCount := by + simp only [graphRowQueries, emissionLookupRow, List.length_ofFn, encodedQueries] + apply filterMap_eq_of_eq_on + intro slot member + have inside := List.mem_range.mp member + by_cases zero : slot = 0 + · subst slot + simp only [if_true, encodedQuery_zero ranges] + · simp only [zero, if_false, List.getElem?_ofFn, inside, dif_pos, bind, Option.bind_some, + CircuitEmission.lookup, encodedQuery] + +theorem graphRowProvider_emission (emission : CircuitEmission) (positive : 0 < emission.lookupCount) : + graphRowProvider (emissionLookupRow emission) = some emission.provider := by + simp only [graphRowProvider, emissionLookupRow, List.getElem?_ofFn, positive, dif_pos, Option.map_some, + CircuitEmission.lookup, if_true, CircuitEmission.provider, G.neg_neg] + +theorem graphFunctionQueries_emissions (emissions : List CircuitEmission) + (ranges : ∀ emission ∈ emissions, ∀ query ∈ emission.queries, 0 < query.slot) : + graphFunctionQueries (emissions.map emissionLookupRow) = encodedCircuitQueryPool emissions := by + induction emissions with + | nil => rfl + | cons emission emissions ih => + simp only [List.map_cons, graphFunctionQueries, List.flatMap_cons, encodedCircuitQueryPool, + graphRowQueries_emission emission (ranges emission List.mem_cons_self)] + exact congrArg (_ ++ ·) (ih (fun value member => ranges value (List.mem_cons_of_mem _ member))) + +theorem graphFunctionProviders_emissions (emissions : List CircuitEmission) + (positive : ∀ emission ∈ emissions, 0 < emission.lookupCount) : + graphFunctionProviders (emissions.map emissionLookupRow) = circuitProviders emissions := by + induction emissions with + | nil => rfl + | cons emission emissions ih => + simp only [List.map_cons, graphFunctionProviders, List.filterMap_cons, + graphRowProvider_emission emission (positive emission List.mem_cons_self), circuitProviders] + exact congrArg (emission.provider :: ·) (ih (fun value member => positive value (List.mem_cons_of_mem _ member))) + +theorem CompiledKey.functionCircuit_matrix_extract {logBlowup : Nat} {program : Bytecode.Toplevel} + {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (built : CompiledKey.functionCircuit logBlowup program source = some artifact) + {height : Nat} (matrix : Fin height → Nat → G) + (satisfied : artifact.graph.TraceSatisfied artifact.widths matrix) : + ∃ witnesses, (List.ofFn matrix).mapM (emitNativeCircuitWitness program source) = some witnesses ∧ + (∀ witness ∈ witnesses, witness.Satisfied ∧ witness.NativeBounds program) ∧ + artifact.graph.readTraceLookups artifact.widths matrix = + some (witnesses.map fun witness => emissionLookupRow witness.emission) := by + have each := fun index => CompiledKey.functionCircuit_trace_witness built matrix index (satisfied index) + let witnesses := fun index => (each index).choose + have produced (index : Fin height) : emitNativeCircuitWitness program source (matrix index) = some (witnesses index) := + (each index).choose_spec.choose_spec.1 + have valid (index : Fin height) : (witnesses index).Satisfied ∧ (witnesses index).NativeBounds program := + ⟨(each index).choose_spec.choose_spec.2.1, (each index).choose_spec.choose_spec.2.2.1⟩ + have read (index : Fin height) : artifact.graph.readLookups (traceRowValues artifact.widths matrix index) = + some (emissionLookupRow (witnesses index).emission) := by + dsimp only [witnesses, emissionLookupRow] + obtain ⟨buffer, _, _, _, swept, lookups⟩ := (each index).choose_spec + simp only [Graph.readLookups, swept, bind, Option.bind_some, lookups] + refine ⟨List.ofFn witnesses, list_mapM_ofFn matrix witnesses _ produced, ?_, ?_⟩ + · intro witness member + obtain ⟨index, rfl⟩ := List.mem_ofFn.mp member + exact valid index + · simpa only [Graph.readTraceLookups, List.map_ofFn, Function.comp_def] using + list_mapM_ofFn id (fun index => emissionLookupRow (witnesses index).emission) + (fun index => artifact.graph.readLookups (traceRowValues artifact.widths matrix index)) read + +end Aiur.NativeAIR + +namespace Aiur.AIR +open Bytecode NativeAIR + +def CircuitTraces.graphLookups {circuits : List Circuit} : CircuitTraces circuits → List KeyCodec.Circuit → Option (List LookupRow) + | .nil, [] => some [] + | .inactive _ rest, _ :: keys => rest.graphLookups keys + | .active _ _ matrix rest, key :: keys => do + let first ← key.graph.readTraceLookups key.widths matrix + let later ← rest.graphLookups keys + return first ++ later + | _, _ => none + +theorem CircuitTraces.graph_extract {circuits : List Circuit} (traces : CircuitTraces circuits) + {logBlowup : Nat} {program : Toplevel} {keys : List KeyCodec.Circuit} + (built : circuits.mapM (CompiledKey.functionCircuit logBlowup program) = some keys) + (satisfied : traces.GraphSatisfied keys) : + ∃ witnesses, traces.emitNativeWitnesses program = some witnesses ∧ + (∀ witness ∈ witnesses, witness.Satisfied ∧ witness.NativeBounds program) ∧ + traces.graphLookups keys = some (witnesses.map fun witness => emissionLookupRow witness.emission) := by + induction traces generalizing keys with + | nil => + have empty : keys = [] := satisfied + subst keys + exact ⟨[], rfl, (fun _ member => nomatch member), rfl⟩ + | inactive circuit rest ih => + obtain ⟨key, keys, _, tail, equal⟩ := list_mapM_cons_parts built + subst equal + exact ih tail satisfied + | active circuit degree matrix rest ih => + obtain ⟨key, keys, head, tail, equal⟩ := list_mapM_cons_parts built + subst equal + obtain ⟨later, laterEq, laterValid, laterRead⟩ := ih tail satisfied.2 + obtain ⟨first, firstEq, firstValid, firstRead⟩ := CompiledKey.functionCircuit_matrix_extract head matrix satisfied.1 + refine ⟨first ++ later, ?_, ?_, ?_⟩ + · simp only [emitNativeWitnesses, firstEq, laterEq, bind, Option.bind_some, pure] + · intro witness member + exact (List.mem_append.mp member).elim (firstValid witness) (laterValid witness) + · simp only [graphLookups, firstRead, laterRead, bind, Option.bind_some, pure, List.map_append] + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/GraphTraces.lean b/Ix/Aiur/Proofs/GraphTraces.lean new file mode 100644 index 000000000..8b06f52d2 --- /dev/null +++ b/Ix/Aiur/Proofs/GraphTraces.lean @@ -0,0 +1,208 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.NativeTraceExecution + +/-! Base graphs evaluated on the physical main rows supply the witnesses, +equations and lookup slots used by execution extraction. Unused stage-two, +public and preprocessing columns are zero here; these graphs are the base +graphs reconstructed by `CompiledKey`, before LogUp constraints are added. -/ + +namespace Aiur.NativeAIR +open AIR Compiler + +def traceRowValues (widths : GraphWidths) {height : Nat} (matrix : Fin height → Nat → G) + (index : Fin height) : Values G where + columns + | .main, .current => Array.ofFn fun column : Fin widths.main => matrix index column.val + | .main, .next => Array.ofFn fun column : Fin widths.main => matrix (memoryNextIndex index) column.val + | .preprocessed, _ => Array.replicate widths.preprocessed 0 + | .stage2, _ => Array.replicate widths.stage2 0 + publics := Array.replicate widths.publics 0 + isFirstRow := if index.val = 0 then 1 else 0 + isLastRow := if index.val + 1 = height then 1 else 0 + isTransition := if index.val + 1 < height then 1 else 0 + +theorem traceRowValues_fits (widths : GraphWidths) {height : Nat} (matrix : Fin height → Nat → G) + (index : Fin height) : (traceRowValues widths matrix index).Fits widths := by + refine ⟨?_, ?_⟩ + · intro source offset + cases source <;> cases offset <;> simp only [traceRowValues, GraphWidths.width, Array.size_ofFn, Array.size_replicate] + · exact Array.size_replicate + +theorem traceRowValues_current (widths : GraphWidths) {height : Nat} (matrix : Fin height → Nat → G) + (index : Fin height) : + (fun column => ((traceRowValues widths matrix index).columns .main .current)[column]?.getD 0) = + boundedTraceRow widths.main (matrix index) := rfl + +def finiteTraceMatrix {height width : Nat} (matrix : Fin height → Fin width → G) : Fin height → Nat → G := + fun row column => (Array.ofFn (matrix row))[column]?.getD 0 + +theorem traceRowValues_finite_columns {widths : GraphWidths} {height width : Nat} + (matrix : Fin height → Fin width → G) (index : Fin height) (bound : width ≤ widths.main) : + CompiledKey.columns (traceRowValues widths (finiteTraceMatrix matrix) index) .main .current width = matrix index ∧ + CompiledKey.columns (traceRowValues widths (finiteTraceMatrix matrix) index) .main .next width = + matrix (memoryNextIndex index) := by + constructor <;> funext column + all_goals + have inside := Nat.lt_of_lt_of_le column.isLt bound + simp only [CompiledKey.columns, traceRowValues, finiteTraceMatrix, Array.getElem?_ofFn, + inside, column.isLt, dif_pos, Option.getD_some] + +def Graph.RowSatisfied (graph : Graph) (values : Values G) : Prop := + ∃ buffer, graph.sweep goldilocksOps values = some buffer ∧ Vanishes goldilocksOps buffer graph.zeros + +def Graph.TraceSatisfied (graph : Graph) (widths : GraphWidths) {height : Nat} + (matrix : Fin height → Nat → G) : Prop := + ∀ index, graph.RowSatisfied (traceRowValues widths matrix index) + +theorem CompiledKey.functionCircuit_trace_witness {logBlowup : Nat} {program : Bytecode.Toplevel} + {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (built : CompiledKey.functionCircuit logBlowup program source = some artifact) + {height : Nat} (matrix : Fin height → Nat → G) (index : Fin height) + (satisfied : artifact.graph.RowSatisfied (traceRowValues artifact.widths matrix index)) : + ∃ witness : CircuitWitness, ∃ buffer, + emitNativeCircuitWitness program source (matrix index) = some witness ∧ + witness.Satisfied ∧ witness.NativeBounds program ∧ + artifact.graph.sweep goldilocksOps (traceRowValues artifact.widths matrix index) = some buffer ∧ + artifact.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin witness.emission.lookupCount => witness.emission.lookup slot.val) := by + obtain ⟨witness, buffer, circuit, row, emitted, bounds, swept, equations, lookups⟩ := + CompiledKey.functionCircuit_witness built (traceRowValues_fits artifact.widths matrix index) + have mainWidth := (CompiledKey.functionCircuit_success built).choose_spec.2.2.1 + have physical : artifact.widths.main = source.layout.width := mainWidth + rw [traceRowValues_current, physical] at row + have witnessEq : witness = ⟨source, boundedTraceRow source.layout.width (matrix index), witness.emission⟩ := by + cases witness + simp only [CircuitWitness.mk.injEq] at * + exact ⟨circuit, row, trivial⟩ + have produced : emitNativeCircuitWitness program source (matrix index) = some witness := by + have step := emitted + change witness.circuit.emitNativeRow witness.values program = some witness.emission at step + rw [circuit, row] at step + simp only [emitNativeCircuitWitness, step, bind, Option.bind_some, pure] + exact congrArg some witnessEq.symm + obtain ⟨actual, read, zeros⟩ := satisfied + have equal := Option.some.inj (swept.symm.trans read) + subst actual + exact ⟨witness, buffer, produced, equations.mp zeros, bounds, swept, lookups⟩ + +theorem CompiledKey.memoryCircuit_trace_reflects {logBlowup width : Nat} {artifact : KeyCodec.Circuit} + (built : CompiledKey.memoryCircuit logBlowup width = some artifact) {height : Nat} + (matrix : Fin height → MemoryColumns width) (index : Fin height) : + ∃ buffer, artifact.graph.sweep goldilocksOps + (traceRowValues artifact.widths (finiteTraceMatrix matrix) index) = some buffer ∧ + (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ + ∀ equation ∈ memoryMatrixEquations width height matrix index, equation = 0) ∧ + artifact.graph.lookups.mapM (readLookup buffer) = some [memoryColumnLookup width (matrix index)] := by + obtain ⟨buffer, swept, equations, lookups⟩ := + CompiledKey.memoryCircuit_reflects built (traceRowValues_fits artifact.widths (finiteTraceMatrix matrix) index) + have mainWidth := (CompiledKey.memoryCircuit_success built).choose_spec.2.2.1 + have physical : artifact.widths.main = 3 + width := mainWidth + have columns := traceRowValues_finite_columns matrix index (Nat.le_of_eq physical.symm) + rw [columns.1, columns.2] at equations + rw [columns.1] at lookups + exact ⟨buffer, swept, equations, lookups⟩ + +theorem CompiledKey.memoryCircuit_trace_satisfied {logBlowup width : Nat} {artifact : KeyCodec.Circuit} + (built : CompiledKey.memoryCircuit logBlowup width = some artifact) {height : Nat} + (matrix : Fin height → MemoryColumns width) + (satisfied : artifact.graph.TraceSatisfied artifact.widths (finiteTraceMatrix matrix)) : + MemoryMatrixSatisfied width height matrix := by + intro index + obtain ⟨buffer, swept, equations, _⟩ := CompiledKey.memoryCircuit_trace_reflects built matrix index + obtain ⟨actual, read, zeros⟩ := satisfied index + have equal := Option.some.inj (swept.symm.trans read) + subst actual + exact equations.mp zeros + +end Aiur.NativeAIR + +namespace Aiur.AIR +open Bytecode NativeAIR NativeAIR.OpEmitter + +def CircuitTraces.GraphSatisfied {circuits : List Circuit} : CircuitTraces circuits → List KeyCodec.Circuit → Prop + | .nil, keys => keys = [] + | .inactive _ rest, _ :: keys => rest.GraphSatisfied keys + | .active _ _ matrix rest, key :: keys => + key.graph.TraceSatisfied key.widths matrix ∧ rest.GraphSatisfied keys + | .inactive _ _, [] => False + | .active _ _ _ _, [] => False + +theorem list_mapM_cons_parts {read : α → Option β} {input : α} {inputs : List α} {outputs : List β} + (built : (input :: inputs).mapM read = some outputs) : + ∃ first rest, read input = some first ∧ inputs.mapM read = some rest ∧ outputs = first :: rest := by + simp only [List.mapM_cons, bind, Option.bind] at built + split at built + · cases built + rename_i first head + dsimp only at built + split at built + · cases built + rename_i rest tail + exact ⟨first, rest, head, tail, (Option.some.inj built).symm⟩ + +theorem CircuitTraces.graph_emits {circuits : List Circuit} (traces : CircuitTraces circuits) + {logBlowup : Nat} {program : Toplevel} {keys : List KeyCodec.Circuit} + (built : circuits.mapM (CompiledKey.functionCircuit logBlowup program) = some keys) + (satisfied : traces.GraphSatisfied keys) : + ∃ witnesses, traces.emitNativeWitnesses program = some witnesses ∧ + ∀ witness ∈ witnesses, witness.Satisfied ∧ witness.NativeBounds program := by + induction traces generalizing keys with + | nil => exact ⟨[], rfl, fun _ member => nomatch member⟩ + | inactive circuit rest ih => + obtain ⟨key, keys, _, tail, equal⟩ := list_mapM_cons_parts built + subst equal + exact ih tail satisfied + | active circuit degree matrix rest ih => + obtain ⟨key, keys, head, tail, equal⟩ := list_mapM_cons_parts built + subst equal + obtain ⟨later, laterEq, laterValid⟩ := ih tail satisfied.2 + have each : ∀ values ∈ List.ofFn matrix, ∃ witness, + emitNativeCircuitWitness program circuit values = some witness ∧ + witness.Satisfied ∧ witness.NativeBounds program := by + intro values member + obtain ⟨index, rfl⟩ := List.mem_ofFn.mp member + obtain ⟨witness, _, produced, valid, bounds, _⟩ := + CompiledKey.functionCircuit_trace_witness head matrix index (satisfied.1 index) + exact ⟨witness, produced, valid, bounds⟩ + obtain ⟨first, firstEq⟩ := list_mapM_defined (List.ofFn matrix) (fun values member => by + obtain ⟨witness, produced, _⟩ := each values member + exact ⟨witness, produced⟩) + have valid := mapM_forall₂ firstEq (fun values member witness produced => by + obtain ⟨actual, emitted, valid⟩ := each values member + have equal := Option.some.inj (produced.symm.trans emitted) + exact equal ▸ valid) + refine ⟨first ++ later, ?_, ?_⟩ + · simp only [emitNativeWitnesses, firstEq, laterEq, bind, Option.bind_some, pure] + · intro witness member + rcases List.mem_append.mp member with before | after + · exact (forall₂_right_member valid before).choose_spec.2 + · exact laterValid witness after + +def MemoryTraces.GraphSatisfied {widths : List Nat} : MemoryTraces widths → List KeyCodec.Circuit → Prop + | .nil, keys => keys = [] + | .inactive _ rest, _ :: keys => rest.GraphSatisfied keys + | .active _ _ matrix rest, key :: keys => + key.graph.TraceSatisfied key.widths (finiteTraceMatrix matrix) ∧ rest.GraphSatisfied keys + | .inactive _ _, [] => False + | .active _ _ _ _, [] => False + +theorem MemoryTraces.graph_satisfied {widths : List Nat} (traces : MemoryTraces widths) + {logBlowup : Nat} {keys : List KeyCodec.Circuit} + (built : widths.mapM (CompiledKey.memoryCircuit logBlowup) = some keys) + (satisfied : traces.GraphSatisfied keys) : traces.Satisfied := by + induction traces generalizing keys with + | nil => trivial + | inactive width rest ih => + obtain ⟨key, keys, _, tail, equal⟩ := list_mapM_cons_parts built + subst equal + exact ih tail satisfied + | active width degree matrix rest ih => + obtain ⟨key, keys, head, tail, equal⟩ := list_mapM_cons_parts built + subst equal + exact ⟨CompiledKey.memoryCircuit_trace_satisfied head matrix satisfied.1, ih tail satisfied.2⟩ + +end Aiur.AIR diff --git a/Ix/Aiur/Proofs/InactiveRows.lean b/Ix/Aiur/Proofs/InactiveRows.lean index 7fa115fd7..9e9ac18fe 100644 --- a/Ix/Aiur/Proofs/InactiveRows.lean +++ b/Ix/Aiur/Proofs/InactiveRows.lean @@ -12,6 +12,8 @@ symbolic circuit constraints contain no contradictory constant equation. -/ namespace Aiur.AIR open Bytecode +variable {callRanks : Array CallRank} + theorem selectorSum_zero (values : List G) (zero : ∀ value ∈ values, value = 0) : selectorSum values = 0 := by induction values with @@ -21,16 +23,16 @@ theorem selectorSum_zero (values : List G) (zero : ∀ value ∈ values, value = ih (fun value member => zero value (List.mem_cons_of_mem _ member)), G.zero_add] theorem emitOp_inactive {row : Nat → G} {rank : G} (op : Op) {values : Array RowValue} - {emission : OpEmission} (emitted : emitOp row 0 rank op values = some emission) : + {emission : OpEmission} (emitted : emitOp row 0 rank op values callRanks = some emission) : ∀ equation ∈ emission.equations, equation = 0 := by cases op <;> simp only [emitOp, emitAdvice, emitByte1, emitByte2, emitU32LessThan, emitU32Add, bind, Option.bind] at emitted all_goals repeat' first | split at emitted | (dsimp only at emitted; split at emitted) all_goals cases emitted - all_goals simp [G.mul_comm (0 : G), G.mul_zero] + all_goals simp [emitCallRow, G.mul_comm (0 : G), G.mul_zero] theorem emitOps_inactive {row : Nat → G} {rank : G} (ops : List Op) {values : Array RowValue} - {column : Nat} {emission : OpsEmission} (emitted : emitOps row 0 rank ops values column = some emission) : + {column : Nat} {emission : OpsEmission} (emitted : emitOps row 0 rank ops values column callRanks = some emission) : ∀ equation ∈ emission.equations, equation = 0 := by induction ops generalizing values column emission with | nil => cases emitted; simp diff --git a/Ix/Aiur/Proofs/LookupLayout.lean b/Ix/Aiur/Proofs/LookupLayout.lean index 6076e9909..2299afa5a 100644 --- a/Ix/Aiur/Proofs/LookupLayout.lean +++ b/Ix/Aiur/Proofs/LookupLayout.lean @@ -17,8 +17,13 @@ compiler and certified semantic/cryptographic endpoint remain obligations. namespace Aiur.Bytecode -def Op.lookupUsage : Op → Nat - | .call _ _ _ unconstrained => if unconstrained then 0 else 4 +def Op.lookupUsage (op : Op) (callRanks : Array CallRank := #[]) : Nat := + match op with + | .call function _ _ unconstrained => + if unconstrained then 0 else + match callRanks[function]?.getD .ordered with + | .zero | .bound => 1 + | .ordered => 4 | .store _ | .load _ _ | .u8BitDecomposition _ | .u8ShiftLeft _ | .u8ShiftRight _ | .u8Xor .. | .u8And .. | .u8Or .. | .u8Add .. | .u8Sub .. | .u8Mul .. | .u8XorSplit7 .. | .u8XorSplit4 .. | .u8LessThan .. | .u8RangeCheck .. => 1 @@ -32,46 +37,48 @@ private theorem lookup_block_smaller (block : Block) : sizeOf block.ctrl < sizeO mutual -def Ctrl.lookupUsage : Ctrl → Nat +def Ctrl.lookupUsage (ctrl : Ctrl) (callRanks : Array CallRank := #[]) : Nat := + match ctrl with | .return .. | .yield .. => 0 | .match _ branches fallback => ( - (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.lookupUsage) ++ - (match fallback with | none => [] | some block => [block.lookupUsage])).foldl Nat.max 0 + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.lookupUsage callRanks) ++ + (match fallback with | none => [] | some block => [block.lookupUsage callRanks])).foldl Nat.max 0 | .matchContinue _ branches fallback _ _ _ continuation => ( - (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.lookupUsage) ++ - (match fallback with | none => [] | some block => [block.lookupUsage])).foldl Nat.max 0 + - continuation.lookupUsage -termination_by ctrl => sizeOf ctrl + (branches.attach.toList.map fun ⟨pair, _⟩ => pair.2.lookupUsage callRanks) ++ + (match fallback with | none => [] | some block => [block.lookupUsage callRanks])).foldl Nat.max 0 + + continuation.lookupUsage callRanks +termination_by sizeOf ctrl decreasing_by all_goals first | decreasing_tactic | (have := Array.sizeOf_lt_of_mem ‹_ ∈ _›; grind) -def Block.lookupUsage (block : Block) : Nat := - (block.ops.toList.map Op.lookupUsage).sum + block.ctrl.lookupUsage +def Block.lookupUsage (block : Block) (callRanks : Array CallRank := #[]) : Nat := + (block.ops.toList.map (fun op => op.lookupUsage callRanks)).sum + block.ctrl.lookupUsage callRanks termination_by sizeOf block decreasing_by exact lookup_block_smaller block end -def branchLookupUsage (branches : Array (G × Block)) (fallback : Option Block) : Nat := - (branches.toList.map (fun pair => pair.2.lookupUsage) ++ - fallback.toList.map (fun block => block.lookupUsage)).foldl Nat.max 0 +def branchLookupUsage (branches : Array (G × Block)) (fallback : Option Block) + (callRanks : Array CallRank := #[]) : Nat := + (branches.toList.map (fun pair => pair.2.lookupUsage callRanks) ++ + fallback.toList.map (fun block => block.lookupUsage callRanks)).foldl Nat.max 0 -theorem Ctrl.lookupUsage_match (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) : - (Ctrl.match index branches fallback).lookupUsage = branchLookupUsage branches fallback := by +theorem Ctrl.lookupUsage_match (index : ValIdx) (branches : Array (G × Block)) (fallback : Option Block) {callRanks : Array CallRank} : + (Ctrl.match index branches fallback).lookupUsage callRanks = branchLookupUsage branches fallback callRanks := by rw [Ctrl.lookupUsage.eq_def] simp only [branchLookupUsage, Array.toList_attach] - rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.lookupUsage)] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.lookupUsage callRanks)] cases fallback <;> rfl theorem Ctrl.lookupUsage_matchContinue (index : ValIdx) (branches : Array (G × Block)) - (fallback : Option Block) (outputs aux lookups : Nat) (continuation : Block) : - (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).lookupUsage = - branchLookupUsage branches fallback + continuation.lookupUsage := by + (fallback : Option Block) (outputs aux lookups : Nat) (continuation : Block) {callRanks : Array CallRank} : + (Ctrl.matchContinue index branches fallback outputs aux lookups continuation).lookupUsage callRanks = + branchLookupUsage branches fallback callRanks + continuation.lookupUsage callRanks := by rw [Ctrl.lookupUsage.eq_def] simp only [branchLookupUsage, Array.toList_attach] - rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.lookupUsage)] + rw [List.attachWith_map_val (f := fun pair : G × Block => pair.2.lookupUsage callRanks)] cases fallback <;> rfl end Aiur.Bytecode @@ -123,7 +130,7 @@ theorem opLayout_lookupUsage (op : Op) (initial : LayoutMState) private theorem ops_fold_lookupUsage (ops : List Op) (initial : LayoutMState) (generic : initial.callRanks = #[]) : ((ops.foldlM (fun _ op => opLayout op) ()).run initial).2.functionLayout.lookups = - initial.functionLayout.lookups + (ops.map Op.lookupUsage).sum := by + initial.functionLayout.lookups + (ops.map (fun op => op.lookupUsage)).sum := by induction ops generalizing initial with | nil => rfl | cons op ops ih => @@ -135,7 +142,7 @@ private theorem ops_fold_lookupUsage (ops : List Op) (initial : LayoutMState) theorem opsLayout_lookupUsage (ops : Array Op) (initial : LayoutMState) (generic : initial.callRanks = #[]) : ((ops.forM opLayout).run initial).2.functionLayout.lookups = - initial.functionLayout.lookups + (ops.toList.map Op.lookupUsage).sum := by + initial.functionLayout.lookups + (ops.toList.map (fun op => op.lookupUsage)).sum := by unfold Array.forM rw [← Array.foldlM_toList] exact ops_fold_lookupUsage ops.toList initial generic @@ -271,10 +278,12 @@ end Aiur.Bytecode namespace Aiur.AIR open Bytecode +variable {callRanks : Array CallRank} + theorem emitOp_lookupUsage {row : Nat → G} {selector rank : G} {op : Op} {values : Array RowValue} {emission : OpEmission} - (emitted : emitOp row selector rank op values = some emission) : - emission.queries.length = op.lookupUsage := by + (emitted : emitOp row selector rank op values callRanks = some emission) : + emission.queries.length = op.lookupUsage callRanks := by cases op <;> simp only [emitOp, emitByte1, emitByte2, emitU32LessThan, emitU32Add, emitAdvice, bind, Option.bind, Option.map, pure] at emitted all_goals @@ -282,12 +291,13 @@ theorem emitOp_lookupUsage {row : Nat → G} {selector rank : G} {op : Op} | split at emitted | (dsimp only at emitted; split at emitted) all_goals cases emitted - all_goals simp_all [Op.lookupUsage, rankByteQueries, range4Queries] + all_goals simp_all [Op.lookupUsage, emitCallRow, callRangeQueries, rankByteQueries, range4Queries] + all_goals split <;> simp_all theorem emitOps_lookupUsage {row : Nat → G} {selector rank : G} {ops : List Op} {values : Array RowValue} {column : Nat} {emission : OpsEmission} - (emitted : emitOps row selector rank ops values column = some emission) : - emission.queries.length = (ops.map Op.lookupUsage).sum := by + (emitted : emitOps row selector rank ops values column callRanks = some emission) : + emission.queries.length = (ops.map (fun op => op.lookupUsage callRanks)).sum := by induction ops generalizing values column emission with | nil => have equal := Option.some.inj emitted @@ -312,11 +322,11 @@ end Aiur.AIR namespace Aiur.Bytecode open Aiur.AIR -private theorem lookup_fold_related {blocks : List Block} {emissions : List BlockEmission} {lookup : Nat} - (related : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage) blocks emissions) +private theorem lookup_fold_related {callRanks : Array CallRank} {blocks : List Block} {emissions : List BlockEmission} {lookup : Nat} + (related : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage callRanks) blocks emissions) (acc : Nat) : emissions.foldl (fun value emission => max value emission.lookup) (lookup + acc) = - lookup + (blocks.map Block.lookupUsage).foldl Nat.max acc := by + lookup + (blocks.map (fun block => block.lookupUsage callRanks)).foldl Nat.max acc := by induction related generalizing acc with | nil => rfl | cons first rest ih => @@ -329,12 +339,12 @@ theorem branchRows_lookupUsage (row : Nat → G) (selector : SelIdx → G) (cont (emitted : branchRows row selector context matched values column lookup branches fallback = some emission) (caseSound : ∀ pair ∈ branches.toList, ∀ emission, pair.2.emitRow row selector context (pair.2.selectorFlow selector).entry values column lookup = some emission → - emission.lookup = lookup + pair.2.lookupUsage) + emission.lookup = lookup + pair.2.lookupUsage context.callRanks) (defaultSound : ∀ block, fallback = some block → ∀ emission, block.emitRow row selector context (block.selectorFlow selector).entry values (column + branches.size) lookup = some emission → - emission.lookup = lookup + block.lookupUsage) : - emission.lookup = lookup + branchLookupUsage branches fallback := by + emission.lookup = lookup + block.lookupUsage context.callRanks) : + emission.lookup = lookup + branchLookupUsage branches fallback context.callRanks := by simp only [branchRows, bind, Option.bind] at emitted split at emitted · cases emitted @@ -345,7 +355,7 @@ theorem branchRows_lookupUsage (row : Nat → G) (selector : SelIdx → G) (cont · rename_i default defaultEmitted have equal := Option.some.inj emitted subst emission - have casesRelated : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage) + have casesRelated : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage context.callRanks) (branches.toList.map Prod.snd) cases := by apply forall₂_map_left apply mapM_forall₂ casesEmitted @@ -357,7 +367,7 @@ theorem branchRows_lookupUsage (row : Nat → G) (selector : SelIdx → G) (cont have equal := Option.some.inj emitted subst emission exact caseSound pair member body bodyEmitted - have defaultRelated : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage) + have defaultRelated : List.Forall₂ (fun block emission => emission.lookup = lookup + block.lookupUsage context.callRanks) fallback.toList default := by cases fallbackEq : fallback with | none => @@ -392,7 +402,7 @@ theorem Ctrl.emitRow_lookupUsage (row : Nat → G) (selector : SelIdx → G) (co (incoming : G) (values : Array RowValue) (column lookup : Nat) (ctrl : Ctrl) {emission : BlockEmission} (emitted : ctrl.emitRow row selector context incoming values column lookup = some emission) : - emission.lookup = lookup + ctrl.lookupUsage := by + emission.lookup = lookup + ctrl.lookupUsage context.callRanks := by cases ctrlEq : ctrl with | «return» index indices => rw [ctrlEq] at emitted @@ -475,7 +485,7 @@ theorem Block.emitRow_lookupUsage (row : Nat → G) (selector : SelIdx → G) (c (incoming : G) (values : Array RowValue) (column lookup : Nat) (block : Block) {emission : BlockEmission} (emitted : block.emitRow row selector context incoming values column lookup = some emission) : - emission.lookup = lookup + block.lookupUsage := by + emission.lookup = lookup + block.lookupUsage context.callRanks := by rw [Block.emitRow] at emitted simp only [bind, Option.bind] at emitted split at emitted diff --git a/Ix/Aiur/Proofs/NativeCircuitExecution.lean b/Ix/Aiur/Proofs/NativeCircuitExecution.lean new file mode 100644 index 000000000..a124d0949 --- /dev/null +++ b/Ix/Aiur/Proofs/NativeCircuitExecution.lean @@ -0,0 +1,150 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentEncodedExecution +import Ix.Aiur.Proofs.CompiledKey + +/-! One execution endpoint for the rank policy selected by the accepted +compiled key. Circuit membership supplies constrained functions and lookup +shapes; reconstructed graph extents supply the remaining layout bounds. -/ + +namespace Aiur.Bytecode +open Aiur.AIR + +theorem Circuit.emitNativeRow_members (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitNativeRow row program = some emission) : + emission.members.map MemberEmission.functionIndex = circuit.members.toList ∧ + ∀ member ∈ emission.members, program.functions[member.functionIndex]? = some member.function := by + simp only [Circuit.emitNativeRow] at emitted + split at emitted + · obtain ⟨_, indices, source⟩ := circuit.emitRow_spec row program emitted + exact ⟨indices, fun member present => (source member present).present⟩ + · obtain ⟨_, indices, source⟩ := circuit.emitComponentRow_spec row program emitted + exact ⟨indices, fun member present => (source member present).present⟩ + +theorem Circuit.emitNativeRow_lookupCount (row : Nat → G) (program : Toplevel) (circuit : Circuit) + {emission : CircuitEmission} (emitted : circuit.emitNativeRow row program = some emission) : + emission.lookupCount = circuit.layout.lookups := by + simp only [Circuit.emitNativeRow] at emitted + split at emitted + · exact congrArg CircuitEmission.lookupCount (circuit.emitRow_spec row program emitted).1 + · exact congrArg CircuitEmission.lookupCount (circuit.emitComponentRow_spec row program emitted).1 + +end Aiur.Bytecode + +namespace Aiur.AIR +open Bytecode + +def CircuitWitness.NativeEmitted (program : Toplevel) (witness : CircuitWitness) : Prop := + witness.circuit.emitNativeRow witness.values program = some witness.emission + +def CircuitWitness.NativeBounds (program : Toplevel) (witness : CircuitWitness) : Prop := + witness.QueryRanges ∧ (program.callComponents.isEmpty = true → witness.LookupBounds) + +theorem CircuitWitness.native_constrained {program : Toplevel} + (constrained : CircuitsConstrained program.functions program.circuits) + (witness : CircuitWitness) (circuit : witness.circuit ∈ program.circuits) + (emitted : witness.NativeEmitted program) : witness.Constrained := by + obtain ⟨indices, source⟩ := witness.circuit.emitNativeRow_members witness.values program emitted + intro part member + have index : part.functionIndex ∈ witness.circuit.members := by + apply Array.mem_toList_iff.mp + rw [← indices] + exact List.mem_map.mpr ⟨part, member, rfl⟩ + obtain ⟨function, present, isConstrained⟩ := constrained witness.circuit circuit part.functionIndex index + have equal := Option.some.inj (present.symm.trans (source part member)) + subst function + exact isConstrained + +theorem CircuitWitness.native_shapes {program : Toplevel} (shapes : program.validateLookupShapes = true) + (constrained : CircuitsConstrained program.functions program.circuits) + (witness : CircuitWitness) (circuit : witness.circuit ∈ program.circuits) + (emitted : witness.NativeEmitted program) : witness.Shapes program := by + have valid := witness.native_constrained constrained circuit emitted + have source := (witness.circuit.emitNativeRow_members witness.values program emitted).2 + exact fun part member => Toplevel.validateLookupShapes_function shapes (source part member) (valid part member) + +end Aiur.AIR + +namespace Aiur.NativeAIR.CompiledKey +open AIR Bytecode.AIR Compiler + +theorem functionCircuit_witness {logBlowup : Nat} {program : Bytecode.Toplevel} + {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (built : functionCircuit logBlowup program source = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ witness : CircuitWitness, ∃ buffer, + witness.circuit = source ∧ + witness.values = (fun column => (values.columns .main .current)[column]?.getD 0) ∧ + witness.NativeEmitted program ∧ witness.NativeBounds program ∧ + artifact.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ witness.Satisfied) ∧ + artifact.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin witness.emission.lookupCount => witness.emission.lookup slot.val) := by + obtain ⟨emission, buffer, emitted, swept, zeros, lookups, count, ranges, limits⟩ := + functionCircuit_reflects built fits + let witness : CircuitWitness := ⟨source, (fun column => (values.columns .main .current)[column]?.getD 0), emission⟩ + have lookupCount := source.emitNativeRow_lookupCount witness.values program emitted + refine ⟨witness, buffer, rfl, rfl, emitted, ⟨⟨count, ranges⟩, ?_⟩, swept, zeros, lookups⟩ + intro generic + obtain ⟨reserved, bodyLimits⟩ := limits generic + exact ⟨lookupCount ▸ reserved, fun part member => lookupCount ▸ bodyLimits part member⟩ + +end Aiur.NativeAIR.CompiledKey + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR NativeAIR NativeAIR.Compiler + +theorem CompiledBackend.function_witness {selection : Selection} (backend : CompiledBackend selection) + {index : Nat} {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (present : backend.compiled.bytecode.circuits[index]? = some source) + (selected : backend.keyData.circuits[index]? = some artifact) + {values : Values G} (fits : values.Fits artifact.widths) : + ∃ witness : CircuitWitness, ∃ buffer, + witness.circuit = source ∧ + witness.values = (fun column => (values.columns .main .current)[column]?.getD 0) ∧ + witness.NativeEmitted backend.compiled.bytecode ∧ witness.NativeBounds backend.compiled.bytecode ∧ + artifact.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer artifact.graph.zeros ↔ witness.Satisfied) ∧ + artifact.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin witness.emission.lookupCount => witness.emission.lookup slot.val) := + CompiledKey.functionCircuit_witness (CompiledKey.circuits_function backend.circuits_bound present selected) fits + +theorem CompiledBackend.encoded_native_circuit_execution {selection : Selection} (backend : CompiledBackend selection) + (tables : AuxiliaryTables) (witnesses : List CircuitWitness) (width : Nat) + (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: encodedCircuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (bounded : (encodedCircuitQueryPool (witnesses.map (·.emission))).length + 1 < gSize.toNat) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (circuits : ∀ witness ∈ witnesses, witness.circuit ∈ backend.compiled.bytecode.circuits) + (emitted : ∀ witness ∈ witnesses, witness.NativeEmitted backend.compiled.bytecode) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (bounds : ∀ witness ∈ witnesses, witness.NativeBounds backend.compiled.bytecode) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) ⟨selection.function, input, selection.success, 0⟩ := by + have constrained := fun (witness : CircuitWitness) member => witness.native_constrained backend.toBackend.circuits_constrained + (circuits witness member) (emitted witness member) + have shapes := fun (witness : CircuitWitness) member => witness.native_shapes backend.lookupShapes backend.toBackend.circuits_constrained + (circuits witness member) (emitted witness member) + cases generic : backend.compiled.bytecode.callComponents.isEmpty with + | true => + apply backend.toBackend.encoded_circuit_execution tables witnesses width input arity balanced bounded + publicWidth queryWidths memoryValid canonical circuits ?_ satisfied shapes (fun witness member => (bounds witness member).2 generic) + intro witness member + simpa only [CircuitWitness.NativeEmitted, CircuitWitness.Emitted, + Bytecode.Circuit.emitNativeRow, generic, if_true] using emitted witness member + | false => + have components := backend.components_checked.resolve_left (by simp only [generic, Bool.false_eq_true, not_false_eq_true]) + apply backend.toBackend.encoded_component_circuit_execution components tables witnesses width input arity balanced bounded + publicWidth queryWidths memoryValid canonical circuits ?_ satisfied shapes constrained (fun witness member => (bounds witness member).1) + intro witness member + simpa only [CircuitWitness.NativeEmitted, CircuitWitness.ComponentEmitted, + Bytecode.Circuit.emitNativeRow, generic, Bool.false_eq_true, if_false] using emitted witness member + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/NativeCompiledRows.lean b/Ix/Aiur/Proofs/NativeCompiledRows.lean new file mode 100644 index 000000000..615f27156 --- /dev/null +++ b/Ix/Aiur/Proofs/NativeCompiledRows.lean @@ -0,0 +1,198 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.ComponentCompiledRows + +/-! Select the native rank policy from the transported component table. +Both branches check the read and lookup extents needed by physical row +extraction, including reads eliminated by expression folding. -/ + +namespace Aiur.Bytecode + +def Circuit.emitNativeRow (row : Nat → G) (program : Toplevel) (circuit : Circuit) : + Option AIR.CircuitEmission := + if program.callComponents.isEmpty then circuit.emitRow row program + else circuit.emitComponentRow row program + +end Aiur.Bytecode + +namespace Aiur.NativeAIR.CircuitEmitter +open OpEmitter LookupEmitter BlockEmitter Compiler Bytecode + +def Emission.footprint (width : Nat) (emission : Emission) : Bool := + emission.readBound ≤ width && + (0 < emission.lookupCount && + emission.queries.all (fun part => 0 < part.slot && part.slot < emission.lookupCount)) + +def Emission.genericLimits (emission : Emission) : Bool := + 4 ≤ emission.lookupCount && emission.members.all (fun member => member.body.lookup ≤ emission.lookupCount) + +def compileCheckedCircuit (widths : GraphWidths) (program : Toplevel) (circuit : Circuit) : + Option Compiled := do + let compiled ← compileCircuit widths program circuit + if compiled.emission.footprint widths.main && compiled.emission.genericLimits then some compiled else none + +theorem compileCheckedCircuit_parts {widths : GraphWidths} {program : Toplevel} {circuit : Circuit} + {compiled : Compiled} (built : compileCheckedCircuit widths program circuit = some compiled) : + compileCircuit widths program circuit = some compiled ∧ + compiled.emission.footprint widths.main = true ∧ compiled.emission.genericLimits = true := by + simp only [compileCheckedCircuit, bind, Option.bind] at built + split at built + · cases built + rename_i result compiled + dsimp only at built + split at built + · rename_i bounds + cases built + refine ⟨compiled, ?_⟩ + simpa only [Bool.and_eq_true] using bounds + · cases built + +theorem Emission.footprint_read {width : Nat} {emission : Emission} + (checked : emission.footprint width = true) : emission.readBound ≤ width := by + simp only [footprint, Bool.and_eq_true, decide_eq_true_eq] at checked + exact checked.1 + +theorem Emission.footprint_slots_eval {width : Nat} {emission : Emission} + {values : Values G} {result : AIR.CircuitEmission} + (checked : emission.footprint width = true) (evaluated : emission.eval values = some result) : + ∀ part ∈ result.queries, 0 < part.slot ∧ part.slot < result.lookupCount := by + obtain ⟨_, _, _, _, _, _, _, count, _, _, queries, _⟩ := Emission.eval_components evaluated + simp only [footprint, Bool.and_eq_true, decide_eq_true_eq] at checked + apply AIR.forall₂_right_property + apply AIR.mapM_forall₂ queries + intro query present part partEval + have bounded := List.all_eq_true.mp checked.2.2 query present + simp only [Bool.and_eq_true, decide_eq_true_eq] at bounded + rw [(QueryExpr.eval_components partEval).1, count] at bounded + exact bounded + +theorem Emission.footprint_count_eval {width : Nat} {emission : Emission} + {values : Values G} {result : AIR.CircuitEmission} + (checked : emission.footprint width = true) (evaluated : emission.eval values = some result) : + 0 < result.lookupCount := by + have count := (Emission.eval_components evaluated).2.2.2.2.2.2.2.1 + simp only [footprint, Bool.and_eq_true, decide_eq_true_eq] at checked + rw [← count] + exact checked.2.1 + +theorem Emission.genericLimits_eval {emission : Emission} {values : Values G} {result : AIR.CircuitEmission} + (checked : emission.genericLimits = true) (evaluated : emission.eval values = some result) : + 4 ≤ result.lookupCount ∧ ∀ member ∈ result.members, member.body.lookup ≤ result.lookupCount := by + obtain ⟨members, _, _, _, _, _, _, count, _⟩ := Emission.eval_components evaluated + simp only [genericLimits, Bool.and_eq_true, decide_eq_true_eq] at checked + refine ⟨count ▸ checked.1, ?_⟩ + apply AIR.forall₂_right_property + apply AIR.mapM_forall₂ members + intro member present part partEval + have bound := List.all_eq_true.mp checked.2 member present + simp only [decide_eq_true_eq] at bound + have body := (Member.eval_components partEval).2.2.2 + rw [(BlockEmitter.Emission.eval_components body).2.2.1, count] at bound + exact bound + +theorem compileCheckedCircuit_reflects {values : Values G} {widths : GraphWidths} + (fits : values.Fits widths) {program : Toplevel} {circuit : Circuit} {compiled : Compiled} + (built : compileCheckedCircuit widths program circuit = some compiled) : + ∃ result buffer, + circuit.emitRow (fun index => (values.columns .main .current)[index]?.getD 0) program = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) ∧ + 0 < result.lookupCount ∧ + (∀ part ∈ result.queries, 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + 4 ≤ result.lookupCount ∧ (∀ member ∈ result.members, member.body.lookup ≤ result.lookupCount) := by + obtain ⟨compiled, footprint, limits⟩ := compileCheckedCircuit_parts built + have bound := Emission.footprint_read footprint + simp only [compileCircuit, bind, Option.bind] at compiled + split at compiled + · cases compiled + rename_i emission emitted + dsimp only at compiled + split at compiled + · cases compiled + rename_i base baseCompiled + cases compiled + obtain ⟨result, resultEmitted, evaluated⟩ := emitCircuit_reflects (values := values) + (fun index => (values.columns .main .current)[index]?.getD 0) program circuit emitted (by + intro index indexBound + have size : index < (values.columns .main .current).size := by + rw [fits.1, GraphWidths.width] + exact Nat.lt_of_lt_of_le indexBound bound + simp only [Array.getElem?_eq_getElem size, Option.getD_some]) + obtain ⟨buffer, swept, lookups, zeros⟩ := compileBase_reflects goldilocksGraphLaws fits + emission.lookups emission.equations baseCompiled + have equations := (Emission.eval_components evaluated).2.2.2.2.2.2.2.2.2.1 + obtain ⟨messages, exprReads, graphReads⟩ := lookups.read + exact ⟨result, buffer, resultEmitted, swept, zeros.trans (equations_vanish equations), + graphReads.trans (exprReads.symm.trans (Emission.lookups_eval evaluated)), + Emission.footprint_count_eval footprint evaluated, + Emission.footprint_slots_eval footprint evaluated, Emission.genericLimits_eval limits evaluated⟩ + +theorem compileCheckedCircuit_widen {small large : GraphWidths} (widths : small.Le large) + {program : Toplevel} {circuit : Circuit} {compiled : Compiled} + (built : compileCheckedCircuit small program circuit = some compiled) : + compileCheckedCircuit large program circuit = some compiled := by + obtain ⟨baseBuilt, footprint, limits⟩ := compileCheckedCircuit_parts built + have bounded : _ := footprint + simp only [Emission.footprint, Bool.and_eq_true, decide_eq_true_eq] at bounded + have wide : compiled.emission.footprint large.main = true := by + simp only [Emission.footprint, Bool.and_eq_true, decide_eq_true_eq] + exact ⟨Nat.le_trans bounded.1 (widths.1 .main), bounded.2⟩ + simp only [compileCheckedCircuit, compileCircuit_widen widths _ _ baseBuilt, + wide, limits, Bool.true_and, if_true, bind, Option.bind_some] + +def compileNativeCircuit (widths : GraphWidths) (program : Toplevel) (circuit : Circuit) : + Option Compiled := + if program.callComponents.isEmpty then compileCheckedCircuit widths program circuit + else compileComponentCircuit widths program circuit + +theorem compileNativeCircuit_components {widths : GraphWidths} {program : Toplevel} {circuit : Circuit} + {compiled : Compiled} (built : compileNativeCircuit widths program circuit = some compiled) : + program.callComponents.isEmpty = true ∨ program.validCallComponents = true := by + simp only [compileNativeCircuit] at built + split at built + · exact Or.inl ‹_› + · exact Or.inr (compileComponentCircuit_parts built).1 + +theorem compileNativeCircuit_reflects {values : Values G} {widths : GraphWidths} + (fits : values.Fits widths) {program : Toplevel} {circuit : Circuit} {compiled : Compiled} + (built : compileNativeCircuit widths program circuit = some compiled) : + ∃ result buffer, + circuit.emitNativeRow (fun index => (values.columns .main .current)[index]?.getD 0) program = some result ∧ + compiled.base.graph.sweep goldilocksOps values = some buffer ∧ + (Vanishes goldilocksOps buffer compiled.base.graph.zeros ↔ ∀ equation ∈ result.equations, equation = 0) ∧ + compiled.base.graph.lookups.mapM (readLookup buffer) = + some (List.ofFn fun slot : Fin result.lookupCount => result.lookup slot.val) ∧ + 0 < result.lookupCount ∧ + (∀ part ∈ result.queries, 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + (program.callComponents.isEmpty = true → 4 ≤ result.lookupCount ∧ + ∀ member ∈ result.members, member.body.lookup ≤ result.lookupCount) := by + simp only [compileNativeCircuit] at built + split at built + · rename_i generic + obtain ⟨result, buffer, emitted, swept, zeros, lookups, count, ranges, limits⟩ := compileCheckedCircuit_reflects fits built + exact ⟨result, buffer, by simpa only [Circuit.emitNativeRow, generic, if_true] using emitted, + swept, zeros, lookups, count, ranges, fun _ => limits⟩ + · rename_i components + obtain ⟨result, buffer, emitted, swept, zeros, lookups, count, ranges⟩ := compileComponentCircuit_reflects fits built + refine ⟨result, buffer, by simpa only [Circuit.emitNativeRow, components, Bool.false_eq_true, if_false] using emitted, + swept, zeros, lookups, count, ranges, ?_⟩ + intro generic + simp only [components, Bool.false_eq_true] at generic + +theorem compileNativeCircuit_widen {small large : GraphWidths} (widths : small.Le large) + {program : Toplevel} {circuit : Circuit} {compiled : Compiled} + (built : compileNativeCircuit small program circuit = some compiled) : + compileNativeCircuit large program circuit = some compiled := by + simp only [compileNativeCircuit] at built ⊢ + split at built + · rename_i generic + simpa only [generic, if_true] using compileCheckedCircuit_widen widths built + · rename_i components + simpa only [components, Bool.false_eq_true, if_false] using compileComponentCircuit_widen widths built + +end Aiur.NativeAIR.CircuitEmitter diff --git a/Ix/Aiur/Proofs/NativeExecutionAudit.lean b/Ix/Aiur/Proofs/NativeExecutionAudit.lean new file mode 100644 index 000000000..b031b5337 --- /dev/null +++ b/Ix/Aiur/Proofs/NativeExecutionAudit.lean @@ -0,0 +1,311 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Lean +import Ix.Aiur.Proofs.NativeTraceMetadata + +/-! The deterministic native-layout execution boundary: checked component +edges, actual row emission, complete graph slots, physical table providers +and the single bounded global balance. Cryptographic trace authentication +and source-level checker soundness are later contracts. -/ + +namespace Aiur.Proofs.Audit + +def nativeExecutionRoots : Array Lean.Name := #[ + `Aiur.AIR.CallRankChecks.mono, + `Aiur.AIR.CallRankChecks.ordered, + `Aiur.AIR.CircuitTraces.emitNativeWitnesses_spec, + `Aiur.AIR.CircuitTraces.graph_emits, + `Aiur.AIR.CircuitTraces.graph_extract, + `Aiur.AIR.CircuitWitness.component_interpreted_row, + `Aiur.AIR.CircuitWitness.component_provider_row, + `Aiur.AIR.CircuitWitness.native_constrained, + `Aiur.AIR.CircuitWitness.native_shapes, + `Aiur.AIR.FunctionRow.ComponentValid.active_of_nonzero, + `Aiur.AIR.FunctionRow.ComponentValid.call_order, + `Aiur.AIR.FunctionRow.ComponentValid.global_call_order, + `Aiur.AIR.FunctionRow.ComponentValid.global_rank_bounded, + `Aiur.AIR.FunctionRow.ComponentValid.rank_bounded, + `Aiur.AIR.FunctionRow.inactive_componentQueried, + `Aiur.AIR.FunctionRow.inactive_componentValid, + `Aiur.AIR.GlobalLookups.component_function_provider, + `Aiur.AIR.GlobalLookups.component_roots_execute, + `Aiur.AIR.GlobalLookups.component_rows_execute, + `Aiur.AIR.MemberEmission.FromComponent.querySlots, + `Aiur.AIR.MemoryTraces.graph_providers, + `Aiur.AIR.MemoryTraces.graph_satisfied, + `Aiur.AIR.SystemTraces.graph_extract, + `Aiur.AIR.circuitEmission_boolean_of_members, + `Aiur.AIR.componentByteQueries_member, + `Aiur.AIR.componentCircuitEmission_boolean, + `Aiur.AIR.componentCircuitEmission_gateCount, + `Aiur.AIR.componentCircuitEmission_member_boolean, + `Aiur.AIR.componentCircuitEmission_member_queried, + `Aiur.AIR.componentCircuitEmission_member_rank, + `Aiur.AIR.componentCircuitEmission_queries_count, + `Aiur.AIR.componentCircuitEmission_querySlots, + `Aiur.AIR.componentCircuitEmission_rank_active, + `Aiur.AIR.componentCircuitEmission_rank_boolean, + `Aiur.AIR.componentCircuitEmission_rank_count, + `Aiur.AIR.componentCircuitEmission_rank_queried, + `Aiur.AIR.componentCircuitEmission_return_count, + `Aiur.AIR.componentCircuitEmission_return_message, + `Aiur.AIR.componentCircuitEmission_single_writer, + `Aiur.AIR.componentCircuitWitnesses_decoded_widths, + `Aiur.AIR.componentCircuitWitnesses_execute, + `Aiur.AIR.componentCircuitWitnesses_interpret, + `Aiur.AIR.componentCircuitWitnesses_queries_reflect, + `Aiur.AIR.componentFunctionByteQueries_in_pool, + `Aiur.AIR.componentFunctionQueries_in_pool, + `Aiur.AIR.componentQueries_provider, + `Aiur.AIR.componentRoots_execute, + `Aiur.AIR.componentRows_execute, + `Aiur.AIR.emitCallRow_calls, + `Aiur.AIR.emitComponentMember_present, + `Aiur.AIR.emitComponentMember_spec, + `Aiur.AIR.emitComponentMembers_present, + `Aiur.AIR.emitNativeCircuitWitness_spec, + `Aiur.AIR.emitNativeCircuitWitnesses_spec, + `Aiur.AIR.flatMap_if_filter, + `Aiur.AIR.forall₂_weaken, + `Aiur.AIR.list_mapM_cons_parts, + `Aiur.AIR.queryCount_flatMap_append, + `Aiur.AIR.queryCount_flatMap_indexed, + `Aiur.AIR.queryCount_flatMap_le_sum, + `Aiur.AIR.queryCount_queryParts, + `Aiur.AIR.queryCount_singleton, + `Aiur.AIR.queryParts_boolean, + `Aiur.AIR.selectorSum_boolean_of_count, + `Aiur.BoundVerifier.Backend.encoded_component_circuit_execution, + `Aiur.BoundVerifier.Backend.public_component_circuit_execution, + `Aiur.BoundVerifier.CompiledBackend.checked_graph_trace_execution, + `Aiur.BoundVerifier.CompiledBackend.checked_trace_budget, + `Aiur.BoundVerifier.CompiledBackend.components_checked, + `Aiur.BoundVerifier.CompiledBackend.encoded_native_circuit_execution, + `Aiur.BoundVerifier.CompiledBackend.function_components_checked, + `Aiur.BoundVerifier.CompiledBackend.function_witness, + `Aiur.BoundVerifier.CompiledBackend.graph_trace_execution, + `Aiur.BoundVerifier.CompiledBackend.native_column_trace_execution, + `Aiur.BoundVerifier.CompiledBackend.native_trace_execution, + `Aiur.BoundVerifier.CompiledBackend.trace_metadata, + `Aiur.Bytecode.AIR.RunBlock.calls_collected, + `Aiur.Bytecode.AIR.RunFunction.calls_components, + `Aiur.Bytecode.AIR.RunOps.calls_collected, + `Aiur.Bytecode.AIR.SelectArm.calls_collected, + `Aiur.Bytecode.AIR.Step.calls_collected, + `Aiur.Bytecode.Block.collect_calls, + `Aiur.Bytecode.CallComponent.permits_other, + `Aiur.Bytecode.CallComponent.permits_same, + `Aiur.Bytecode.Circuit.emitComponentRow_active_member, + `Aiur.Bytecode.Circuit.emitComponentRow_boolean, + `Aiur.Bytecode.Circuit.emitComponentRow_count_bounds, + `Aiur.Bytecode.Circuit.emitComponentRow_provider, + `Aiur.Bytecode.Circuit.emitComponentRow_queries_reflect, + `Aiur.Bytecode.Circuit.emitComponentRow_querySlots, + `Aiur.Bytecode.Circuit.emitComponentRow_spec, + `Aiur.Bytecode.Circuit.emitComponentRow_valid_in_pool, + `Aiur.Bytecode.Circuit.emitNativeRow_lookupCount, + `Aiur.Bytecode.Circuit.emitNativeRow_members, + `Aiur.Bytecode.Circuit.validateRowCounts_members, + `Aiur.Bytecode.Ctrl.collect_continue, + `Aiur.Bytecode.Ctrl.collect_match, + `Aiur.Bytecode.Function.emitRow_componentValid, + `Aiur.Bytecode.Op.allocationFor_outputSize, + `Aiur.Bytecode.Toplevel.ComponentEdge.cross, + `Aiur.Bytecode.Toplevel.ComponentEdge.ordered, + `Aiur.Bytecode.Toplevel.ComponentEdge.permits, + `Aiur.Bytecode.Toplevel.ComponentEdge.rankMode, + `Aiur.Bytecode.Toplevel.callRanksFor_read, + `Aiur.Bytecode.Toplevel.componentFor_read, + `Aiur.Bytecode.Toplevel.validCallComponents_component_order, + `Aiur.Bytecode.Toplevel.validCallComponents_edge, + `Aiur.Bytecode.Toplevel.validCallComponents_order, + `Aiur.Bytecode.Toplevel.validCallComponents_size, + `Aiur.Bytecode.flatMap_length_le_sum, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_count_eval, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_read, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_slots, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_slots_eval, + `Aiur.NativeAIR.CircuitEmitter.Emission.footprint_count_eval, + `Aiur.NativeAIR.CircuitEmitter.Emission.footprint_read, + `Aiur.NativeAIR.CircuitEmitter.Emission.footprint_slots_eval, + `Aiur.NativeAIR.CircuitEmitter.Emission.genericLimits_eval, + `Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit_parts, + `Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit_reflects, + `Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit_widen, + `Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit_parts, + `Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit_reflects, + `Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit_widen, + `Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit_components, + `Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit_reflects, + `Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit_widen, + `Aiur.NativeAIR.CircuitEmitter.componentCircuitEmission_eval, + `Aiur.NativeAIR.CircuitEmitter.emitComponentCircuit_reflects, + `Aiur.NativeAIR.CircuitEmitter.emitComponentMember_fields, + `Aiur.NativeAIR.CircuitEmitter.emitComponentMember_reflects, + `Aiur.NativeAIR.CircuitEmitter.emitComponentMembers_reflects, + `Aiur.NativeAIR.CompiledKey.byte1Circuit_matrix_lookups, + `Aiur.NativeAIR.CompiledKey.byte1Circuit_trace_metadata, + `Aiur.NativeAIR.CompiledKey.byte2Circuit_matrix_lookups, + `Aiur.NativeAIR.CompiledKey.byte2Circuit_trace_metadata, + `Aiur.NativeAIR.CompiledKey.circuits_trace_metadata, + `Aiur.NativeAIR.CompiledKey.circuits_trace_parts, + `Aiur.NativeAIR.CompiledKey.functionCircuit_matrix_extract, + `Aiur.NativeAIR.CompiledKey.functionCircuit_reflects, + `Aiur.NativeAIR.CompiledKey.functionCircuit_trace_metadata, + `Aiur.NativeAIR.CompiledKey.functionCircuit_trace_witness, + `Aiur.NativeAIR.CompiledKey.functionCircuit_witness, + `Aiur.NativeAIR.CompiledKey.list_mapM_project, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_matrix_lookups, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_trace_metadata, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_trace_reflects, + `Aiur.NativeAIR.CompiledKey.memoryCircuit_trace_satisfied, + `Aiur.NativeAIR.OpEmitter.emitOp_allocationFor, + `Aiur.NativeAIR.encodedQuery_zero, + `Aiur.NativeAIR.filterMap_eq_of_eq_on, + `Aiur.NativeAIR.graphFunctionProviders_emissions, + `Aiur.NativeAIR.graphFunctionQueries_emissions, + `Aiur.NativeAIR.graphLookupProvider_byte1, + `Aiur.NativeAIR.graphLookupProvider_byte2, + `Aiur.NativeAIR.graphLookupProvider_memory, + `Aiur.NativeAIR.graphRowProvider_emission, + `Aiur.NativeAIR.graphRowQueries_emission, + `Aiur.NativeAIR.graphTableProviders_append, + `Aiur.NativeAIR.graphTableProviders_byte1, + `Aiur.NativeAIR.graphTableProviders_byte2, + `Aiur.NativeAIR.graphTableProviders_memory, + `Aiur.NativeAIR.traceRowValuesWithPreprocessed_columns, + `Aiur.NativeAIR.traceRowValuesWithPreprocessed_fits, + `Aiur.NativeAIR.traceRowValues_current, + `Aiur.NativeAIR.traceRowValues_finite_columns, + `Aiur.NativeAIR.traceRowValues_fits] + +def nativeExecutionPremises : Array Lean.Name := #[ + `Aiur.AIR.CallRankChecks, + `Aiur.AIR.CircuitTraces.GraphSatisfied, + `Aiur.AIR.CircuitTraces.emitNativeWitnesses, + `Aiur.AIR.CircuitTraces.graphLookups, + `Aiur.AIR.CircuitWitness.ComponentEmitted, + `Aiur.AIR.CircuitWitness.Constrained, + `Aiur.AIR.CircuitWitness.NativeBounds, + `Aiur.AIR.CircuitWitness.NativeEmitted, + `Aiur.AIR.CircuitWitness.QueryRanges, + `Aiur.AIR.FunctionRow.ComponentQueriesIn, + `Aiur.AIR.FunctionRow.ComponentValid.mk, + `Aiur.AIR.FunctionRow.componentByteQueries, + `Aiur.AIR.GraphLookupData.mk, + `Aiur.AIR.GraphLookupData.providers, + `Aiur.AIR.GraphLookupData.queries, + `Aiur.AIR.MemberEmission.FromComponent, + `Aiur.AIR.MemberEmission.componentQueries, + `Aiur.AIR.MemoryTraces.GraphSatisfied, + `Aiur.AIR.MemoryTraces.graphLookups, + `Aiur.AIR.SystemTraces.GraphSatisfied, + `Aiur.AIR.SystemTraces.graphLookupData, + `Aiur.AIR.boundedTraceRow, + `Aiur.AIR.callAuxiliaries, + `Aiur.AIR.callGap, + `Aiur.AIR.callRangeQueries, + `Aiur.AIR.calleeRank, + `Aiur.AIR.componentCircuitEmission, + `Aiur.AIR.componentColumn, + `Aiur.AIR.componentFunctionByteQueries, + `Aiur.AIR.componentLookup, + `Aiur.AIR.componentMembers, + `Aiur.AIR.emitCallRow, + `Aiur.AIR.emitComponentMember, + `Aiur.AIR.emitComponentMembers, + `Aiur.AIR.emitNativeCircuitWitness, + `Aiur.Bytecode.Circuit.emitComponentRow, + `Aiur.Bytecode.Circuit.emitNativeRow, + `Aiur.Bytecode.Op.constrainedCalls, + `Aiur.Bytecode.Toplevel.ComponentEdge, + `Aiur.Bytecode.Toplevel.componentFor, + `Aiur.Bytecode.Toplevel.componentRowRank, + `Aiur.Bytecode.branchCalls, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentReadBound, + `Aiur.NativeAIR.CircuitEmitter.Emission.footprint, + `Aiur.NativeAIR.CircuitEmitter.Emission.genericLimits, + `Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit, + `Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit, + `Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit, + `Aiur.NativeAIR.CircuitEmitter.componentCircuitEmission, + `Aiur.NativeAIR.CircuitEmitter.componentMembers, + `Aiur.NativeAIR.CircuitEmitter.emitComponentCircuit, + `Aiur.NativeAIR.CircuitEmitter.emitComponentMember, + `Aiur.NativeAIR.CircuitEmitter.emitComponentMembers, + `Aiur.NativeAIR.Graph.RowSatisfied, + `Aiur.NativeAIR.Graph.TraceSatisfied, + `Aiur.NativeAIR.Graph.readLookups, + `Aiur.NativeAIR.Graph.readPreprocessedTraceLookups, + `Aiur.NativeAIR.Graph.readTraceLookups, + `Aiur.NativeAIR.OpEmitter.callGapExpr, + `Aiur.NativeAIR.OpEmitter.callRangeExprs, + `Aiur.NativeAIR.OpEmitter.calleeRankExpr, + `Aiur.NativeAIR.emissionLookupRow, + `Aiur.NativeAIR.finiteTraceMatrix, + `Aiur.NativeAIR.graphFunctionProviders, + `Aiur.NativeAIR.graphFunctionQueries, + `Aiur.NativeAIR.graphLookupProvider, + `Aiur.NativeAIR.graphRowProvider, + `Aiur.NativeAIR.graphRowQueries, + `Aiur.NativeAIR.graphTableProviders, + `Aiur.NativeAIR.traceRowValues, + `Aiur.NativeAIR.traceRowValuesWithPreprocessed] + +def nativeExecutionAxiomFreeRoots : Array Lean.Name := #[ + `Aiur.AIR.forall₂_weaken] + +def nativeExecutionPropextRoots : Array Lean.Name := #[ + `Aiur.AIR.CallRankChecks.mono, + `Aiur.AIR.CallRankChecks.ordered, + `Aiur.AIR.flatMap_if_filter, + `Aiur.AIR.queryCount_flatMap_le_sum, + `Aiur.Bytecode.Op.allocationFor_outputSize, + `Aiur.Bytecode.Toplevel.ComponentEdge.permits, + `Aiur.Bytecode.Toplevel.componentFor_read, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_read, + `Aiur.NativeAIR.CircuitEmitter.Emission.footprint_read, + `Aiur.NativeAIR.graphTableProviders_append] + +def nativeExecutionQuotRoots : Array Lean.Name := #[ + `Aiur.AIR.FunctionRow.ComponentValid.active_of_nonzero, + `Aiur.AIR.FunctionRow.ComponentValid.call_order, + `Aiur.AIR.FunctionRow.ComponentValid.global_call_order, + `Aiur.AIR.FunctionRow.ComponentValid.global_rank_bounded, + `Aiur.AIR.FunctionRow.ComponentValid.rank_bounded, + `Aiur.AIR.FunctionRow.inactive_componentQueried, + `Aiur.AIR.FunctionRow.inactive_componentValid, + `Aiur.AIR.componentByteQueries_member, + `Aiur.AIR.componentFunctionByteQueries_in_pool, + `Aiur.AIR.componentFunctionQueries_in_pool, + `Aiur.AIR.componentQueries_provider, + `Aiur.AIR.emitCallRow_calls, + `Aiur.AIR.list_mapM_cons_parts, + `Aiur.AIR.queryCount_flatMap_append, + `Aiur.AIR.queryCount_singleton, + `Aiur.Bytecode.AIR.RunOps.calls_collected, + `Aiur.Bytecode.AIR.Step.calls_collected, + `Aiur.Bytecode.CallComponent.permits_other, + `Aiur.Bytecode.Toplevel.ComponentEdge.cross, + `Aiur.Bytecode.Toplevel.callRanksFor_read, + `Aiur.Bytecode.flatMap_length_le_sum, + `Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_slots, + `Aiur.NativeAIR.CompiledKey.list_mapM_project, + `Aiur.NativeAIR.filterMap_eq_of_eq_on, + `Aiur.NativeAIR.graphFunctionProviders_emissions, + `Aiur.NativeAIR.graphLookupProvider_byte1, + `Aiur.NativeAIR.graphLookupProvider_byte2, + `Aiur.NativeAIR.graphLookupProvider_memory, + `Aiur.NativeAIR.graphRowProvider_emission, + `Aiur.NativeAIR.graphTableProviders_byte1, + `Aiur.NativeAIR.graphTableProviders_byte2, + `Aiur.NativeAIR.graphTableProviders_memory, + `Aiur.NativeAIR.traceRowValuesWithPreprocessed_fits, + `Aiur.NativeAIR.traceRowValues_current, + `Aiur.NativeAIR.traceRowValues_fits] + +end Aiur.Proofs.Audit diff --git a/Ix/Aiur/Proofs/NativeTraceExecution.lean b/Ix/Aiur/Proofs/NativeTraceExecution.lean new file mode 100644 index 000000000..9f5c261a8 --- /dev/null +++ b/Ix/Aiur/Proofs/NativeTraceExecution.lean @@ -0,0 +1,165 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.NativeCircuitExecution + +/-! Canonical traces use the accepted key's rank policy. The native-style +logical-slot budget bounds all consumers before lookup grouping. Memory and +byte columns supply their existing checked provider interpretations. -/ + +namespace Aiur.AIR +open Bytecode + +def boundedTraceRow (width : Nat) (values : Nat → G) : Nat → G := + fun column => (Array.ofFn fun index : Fin width => values index.val)[column]?.getD 0 + +def emitNativeCircuitWitness (program : Toplevel) (circuit : Circuit) (values : Nat → G) : Option CircuitWitness := do + let row := boundedTraceRow circuit.layout.width values + let emission ← circuit.emitNativeRow row program + return ⟨circuit, row, emission⟩ + +def CircuitTraces.emitNativeWitnesses {circuits : List Circuit} (program : Toplevel) : + CircuitTraces circuits → Option (List CircuitWitness) + | .nil => some [] + | .inactive _ rest => rest.emitNativeWitnesses program + | .active circuit _ values rest => do + let first ← (List.ofFn values).mapM (emitNativeCircuitWitness program circuit) + let later ← rest.emitNativeWitnesses program + return first ++ later + +theorem emitNativeCircuitWitness_spec {program : Toplevel} {circuit : Circuit} {values : Nat → G} + {witness : CircuitWitness} (emitted : emitNativeCircuitWitness program circuit values = some witness) : + witness.circuit = circuit ∧ witness.values = boundedTraceRow circuit.layout.width values ∧ witness.NativeEmitted program ∧ + witness.emission.lookupCount = circuit.layout.lookups := by + simp only [emitNativeCircuitWitness, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i emission emissionEq + cases emitted + exact ⟨rfl, rfl, emissionEq, circuit.emitNativeRow_lookupCount _ program emissionEq⟩ + +theorem emitNativeCircuitWitnesses_spec {program : Toplevel} {circuit : Circuit} + {values : List (Nat → G)} {witnesses : List CircuitWitness} + (emitted : values.mapM (emitNativeCircuitWitness program circuit) = some witnesses) : + witnesses.length = values.length ∧ + (∀ witness ∈ witnesses, witness.circuit = circuit ∧ witness.NativeEmitted program ∧ + witness.emission.lookupCount = circuit.layout.lookups) := by + have related : List.Forall₂ (fun _ witness => witness.circuit = circuit ∧ witness.NativeEmitted program ∧ + witness.emission.lookupCount = circuit.layout.lookups) values witnesses := by + apply mapM_forall₂ emitted + intro value member witness produced + obtain ⟨same, _, emitted, count⟩ := emitNativeCircuitWitness_spec produced + exact ⟨same, emitted, count⟩ + have length : witnesses.length = values.length := by + clear emitted + induction related with + | nil => rfl + | cons first rest ih => simpa only [List.length_cons] using congrArg (· + 1) ih + refine ⟨length, ?_⟩ + intro witness member + obtain ⟨_, _, evidence⟩ := forall₂_right_member related member + exact evidence + +theorem CircuitTraces.emitNativeWitnesses_spec {circuits : List Circuit} (traces : CircuitTraces circuits) + {program : Toplevel} {witnesses : List CircuitWitness} + (emitted : traces.emitNativeWitnesses program = some witnesses) : + (∀ witness ∈ witnesses, witness.circuit ∈ circuits ∧ witness.NativeEmitted program) ∧ + (encodedCircuitQueryPool (witnesses.map (·.emission))).length ≤ traces.capacity := by + induction traces generalizing witnesses with + | nil => + cases emitted + exact ⟨by simp only [List.not_mem_nil, false_implies, implies_true], Nat.le_refl 0⟩ + | inactive circuit rest ih => + obtain ⟨valid, bounded⟩ := ih emitted + exact ⟨fun witness member => ⟨List.mem_cons_of_mem _ (valid witness member).1, + (valid witness member).2⟩, bounded⟩ + | active circuit degree values rest ih => + simp only [emitNativeWitnesses, bind, Option.bind] at emitted + split at emitted + · cases emitted + rename_i first firstEmitted + dsimp only at emitted + split at emitted + · cases emitted + rename_i later laterEmitted + cases emitted + obtain ⟨valid, bounded⟩ := ih laterEmitted + obtain ⟨length, firstValid⟩ := emitNativeCircuitWitnesses_spec firstEmitted + have firstBound := encodedCircuitQueryPool_uniform_bound first circuit.layout.lookups + (fun witness member => Nat.le_of_eq (firstValid witness member).2.2) + simp only [List.length_ofFn] at length + rw [length] at firstBound + refine ⟨?_, ?_⟩ + · intro witness member + rcases List.mem_append.mp member with before | after + · have evidence := firstValid witness before + exact ⟨List.mem_cons.mpr (Or.inl evidence.1), evidence.2.1⟩ + · exact ⟨List.mem_cons_of_mem _ (valid witness after).1, (valid witness after).2⟩ + · simp only [encodedCircuitQueryPool, List.map_append, List.flatMap_append, List.length_append, capacity] at * + omega + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem CompiledBackend.native_trace_execution {selection : Selection} (backend : CompiledBackend selection) + (tables : AuxiliaryTables) (traces : CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List CircuitWitness} + (emitted : traces.emitNativeWitnesses backend.compiled.bytecode = some witnesses) + {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat} + (budget : lookupQueryBound + (backend.compiled.bytecode.circuits.toList.map (·.layout.lookups) ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: encodedCircuitQueryPool (witnesses.map (·.emission))) + (tables.circuitProviders (witnesses.map (·.emission)))) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (memoryValid : ∀ size, MemoryRowsValid size (tables.memory size)) + (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (bounds : ∀ witness ∈ witnesses, witness.NativeBounds backend.compiled.bytecode) : + Execution backend.compiled.bytecode (memoryFacts tables.memory) ⟨selection.function, input, selection.success, 0⟩ := by + obtain ⟨valid, count⟩ := traces.emitNativeWitnesses_spec emitted + have totalBound := traces.capacity_bounded budget + exact backend.encoded_native_circuit_execution tables witnesses width input arity balanced (by omega) + publicWidth queryWidths memoryValid canonical + (fun witness member => by simpa using (valid witness member).1) + (fun witness member => (valid witness member).2) satisfied bounds + +theorem CompiledBackend.native_column_trace_execution {selection : Selection} (backend : CompiledBackend selection) + (traces : SystemTraces backend.compiled.bytecode) {witnesses : List CircuitWitness} + (emitted : traces.functions.emitNativeWitnesses backend.compiled.bytecode = some witnesses) + {result : Nat} (budget : traces.queryBound = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: encodedCircuitQueryPool (witnesses.map (·.emission))) + (traces.providers (witnesses.map (·.emission)))) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ encodedCircuitQueryPool (witnesses.map (·.emission)), query.length ≤ width) + (satisfied : ∀ witness ∈ witnesses, witness.Satisfied) + (bounds : ∀ witness ∈ witnesses, witness.NativeBounds backend.compiled.bytecode) + (memorySatisfied : traces.memories.Satisfied) : + Execution backend.compiled.bytecode (memoryFacts traces.memories.rows) ⟨selection.function, input, selection.success, 0⟩ ∧ + ∀ size pointer left right, memoryFacts traces.memories.rows size pointer left → + memoryFacts traces.memories.rows size pointer right → left = right := by + unfold SystemTraces.providers at balanced + have replaced := balanced.perm_providers + ((traces.bytes.providers_reflect.append_left traces.memories.providers).append_left + (circuitProviders (witnesses.map CircuitWitness.emission))) + rw [← List.append_assoc traces.memories.providers] at replaced + have decoded := replaced.congr_providers + (traces.memories.circuitProviders_reflect backend.toBackend.memorySizes_distinct memorySatisfied width + traces.bytes.byte1Weights traces.bytes.byte2Weights _) + refine ⟨?_, ?_⟩ + · exact backend.native_trace_execution (traces.memories.auxiliary traces.bytes.byte1Weights traces.bytes.byte2Weights) + traces.functions emitted budget width input arity decoded publicWidth queryWidths + (traces.memories.rows_valid memorySatisfied) backend.toBackend.memorySizes_canonical satisfied bounds + · intro size pointer left right loadedLeft loadedRight + exact traces.memory_functional budget memorySatisfied loadedLeft loadedRight + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/NativeTraceMetadata.lean b/Ix/Aiur/Proofs/NativeTraceMetadata.lean new file mode 100644 index 000000000..a5509f321 --- /dev/null +++ b/Ix/Aiur/Proofs/NativeTraceMetadata.lean @@ -0,0 +1,118 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.SystemGraphExecution +import Ix.Aiur.Proofs.ShapedVerifier + +/-! The selected key's physical lookup counts and fixed heights agree with +the canonical execution traces. Consequently the already enforced proof +budget supplies the execution bound when PCS supplies the same trace metadata. -/ + +namespace Aiur.NativeAIR.CompiledKey +open AIR + +theorem functionCircuit_trace_metadata {logBlowup : Nat} {program : Bytecode.Toplevel} + {source : Bytecode.Circuit} {artifact : KeyCodec.Circuit} + (built : functionCircuit logBlowup program source = some artifact) : + artifact.graph.lookups.length = source.layout.lookups ∧ artifact.preprocessedHeight = 0 := by + obtain ⟨result, _, emitted, _, _, lookups, _⟩ := functionCircuit_reflects built + (traceRowValues_fits artifact.widths (fun _ : Fin 1 => fun _ => 0) 0) + have count := Bytecode.AIR.list_mapM_some_length _ _ _ lookups + have extent := source.emitNativeRow_lookupCount _ program emitted + simp only [List.length_ofFn] at count + exact ⟨count.symm.trans extent, (functionCircuit_success built).choose_spec.2.2.2.2.1⟩ + +theorem memoryCircuit_trace_metadata {logBlowup width : Nat} {artifact : KeyCodec.Circuit} + (built : memoryCircuit logBlowup width = some artifact) : + artifact.graph.lookups.length = 1 ∧ artifact.preprocessedHeight = 0 := by + obtain ⟨_, _, _, lookups⟩ := memoryCircuit_reflects built + (traceRowValues_fits artifact.widths (fun _ : Fin 1 => fun _ => 0) 0) + have count := Bytecode.AIR.list_mapM_some_length _ _ _ lookups + exact ⟨count.symm, (memoryCircuit_success built).choose_spec.2.2.2.2.1⟩ + +theorem byte1Circuit_trace_metadata {logBlowup : Nat} {artifact : KeyCodec.Circuit} + (built : byte1Circuit logBlowup = some artifact) : + artifact.graph.lookups.length = 3 ∧ artifact.preprocessedHeight = 256 := by + obtain ⟨_, _, _, lookups⟩ := byte1Circuit_reflects built + (traceRowValues_fits artifact.widths (fun _ : Fin 1 => fun _ => 0) 0) + have count := Bytecode.AIR.list_mapM_some_length _ _ _ lookups + exact ⟨count.symm, (byte1Circuit_success built).choose_spec.2.2.2.2.1⟩ + +theorem byte2Circuit_trace_metadata {logBlowup : Nat} {artifact : KeyCodec.Circuit} + (built : byte2Circuit logBlowup = some artifact) : + artifact.graph.lookups.length = 10 ∧ artifact.preprocessedHeight = 65536 := by + obtain ⟨_, _, _, lookups⟩ := byte2Circuit_reflects built + (traceRowValues_fits artifact.widths (fun _ : Fin 1 => fun _ => 0) 0) + have count := Bytecode.AIR.list_mapM_some_length _ _ _ lookups + exact ⟨count.symm, (byte2Circuit_success built).choose_spec.2.2.2.2.1⟩ + +theorem list_mapM_project {α β γ : Type} {read : α → Option β} {inputs : List α} {outputs : List β} + (built : inputs.mapM read = some outputs) (input : α → γ) (output : β → γ) + (each : ∀ a b, read a = some b → output b = input a) : outputs.map output = inputs.map input := by + have related : List.Forall₂ (fun a b => output b = input a) inputs outputs := by + apply mapM_forall₂ built + intro a _ b produced + exact each a b produced + clear built each + induction related with + | nil => rfl + | cons first rest ih => simp only [List.map_cons, first, ih] + +theorem circuits_trace_metadata {logBlowup : Nat} {program : Bytecode.Toplevel} {keys : List KeyCodec.Circuit} + (built : circuits logBlowup program = some keys) : + keys.map (·.graph.lookups.length) = systemLookupSlots program ∧ + keys.map (·.preprocessedHeight) = systemFixedHeights program := by + obtain ⟨functions, memories, byte1, byte2, functionsBuilt, memoriesBuilt, first, second, equal⟩ := circuits_parts built + have fs := list_mapM_project functionsBuilt (fun circuit => circuit.layout.lookups) (fun key => key.graph.lookups.length) + (fun _ _ produced => (functionCircuit_trace_metadata produced).1) + have fh := list_mapM_project functionsBuilt (fun _ => 0) (fun key => key.preprocessedHeight) + (fun _ _ produced => (functionCircuit_trace_metadata produced).2) + have ms := list_mapM_project memoriesBuilt (fun _ => 1) (fun key => key.graph.lookups.length) + (fun _ _ produced => (memoryCircuit_trace_metadata produced).1) + have mh := list_mapM_project memoriesBuilt (fun _ => 0) (fun key => key.preprocessedHeight) + (fun _ _ produced => (memoryCircuit_trace_metadata produced).2) + have unary := byte1Circuit_trace_metadata first + have binary := byte2Circuit_trace_metadata second + constructor <;> + simp only [equal, List.map_append, List.map_cons, List.map_nil, fs, fh, ms, mh, + unary.1, unary.2, binary.1, binary.2, systemLookupSlots, systemFixedHeights, + List.map_const', Array.length_toList, List.append_assoc] + +end Aiur.NativeAIR.CompiledKey + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem CompiledBackend.trace_metadata {selection : Selection} (backend : CompiledBackend selection) : + backend.keyData.circuits.map (·.graph.lookups.length) = systemLookupSlots backend.compiled.bytecode ∧ + backend.keyData.circuits.map (·.preprocessedHeight) = systemFixedHeights backend.compiled.bytecode := + NativeAIR.CompiledKey.circuits_trace_metadata backend.circuits_bound + +theorem CompiledBackend.checked_trace_budget {selection : Selection} (backend : CompiledBackend selection) + {bytes : ByteArray} (checked : CheckedProof backend.keyData bytes) (traces : SystemTraces backend.compiled.bytecode) + (active : traces.bitmap = checked.data.active) + (degrees : traces.degrees = checked.data.logDegrees.map UInt8.toNat) : + traces.queryBound = some checked.bound := by + have budget := checked.budget + simpa only [NativeAIR.ProofShape.queryBound, backend.trace_metadata.1, SystemTraces.queryBound, active, degrees] using budget + +theorem CompiledBackend.checked_graph_trace_execution {selection : Selection} (backend : CompiledBackend selection) + {bytes : ByteArray} (checked : CheckedProof backend.keyData bytes) (traces : SystemTraces backend.compiled.bytecode) + (active : traces.bitmap = checked.data.active) + (degrees : traces.degrees = checked.data.logDegrees.map UInt8.toNat) + (data : GraphLookupData) (lookups : traces.graphLookupData backend.keyData.circuits = some data) + (satisfied : traces.GraphSatisfied backend.keyData.circuits) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: data.queries) data.providers) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ data.queries, query.length ≤ width) : + Execution backend.compiled.bytecode (memoryFacts traces.memories.rows) ⟨selection.function, input, selection.success, 0⟩ ∧ + ∀ size pointer left right, memoryFacts traces.memories.rows size pointer left → + memoryFacts traces.memories.rows size pointer right → left = right := + backend.graph_trace_execution traces data lookups satisfied (backend.checked_trace_budget checked traces active degrees) + width input arity balanced publicWidth queryWidths + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/OperationDegrees.lean b/Ix/Aiur/Proofs/OperationDegrees.lean index 5c262d43b..8fabd2d72 100644 --- a/Ix/Aiur/Proofs/OperationDegrees.lean +++ b/Ix/Aiur/Proofs/OperationDegrees.lean @@ -162,7 +162,7 @@ theorem emitU32LessThan_degreeValid (selector : Expr) (first : Nat) (left right theorem emitByte1_dispatch_degreeValid (selector rank : Expr) (first : Nat) (kind : AIR.Byte1Kind) (index : Nat) {rows : Array RowExpr} {emission : Emission} - (emitted : emitOp selector rank first (kind.op index) rows = some emission) : DegreeValid emission.outputs := by + (emitted : emitOp selector rank first (kind.op index) rows callRanks = some emission) : DegreeValid emission.outputs := by rw [emitOp_byte1] at emitted simp only [bind, Option.bind] at emitted split at emitted @@ -172,7 +172,7 @@ theorem emitByte1_dispatch_degreeValid (selector rank : Expr) (first : Nat) (kin theorem emitByte2_dispatch_degreeValid (selector rank : Expr) (first : Nat) (kind : AIR.Byte2Kind) (a b : Nat) {rows : Array RowExpr} {emission : Emission} - (emitted : emitOp selector rank first (kind.op a b) rows = some emission) : DegreeValid emission.outputs := by + (emitted : emitOp selector rank first (kind.op a b) rows callRanks = some emission) : DegreeValid emission.outputs := by rw [emitOp_byte2] at emitted simp only [bind, Option.bind] at emitted split at emitted @@ -185,7 +185,7 @@ theorem emitByte2_dispatch_degreeValid (selector rank : Expr) (first : Nat) (kin theorem emitOp_degreeValid {selector rank : Expr} {first : Nat} {op : Bytecode.Op} {rows : Array RowExpr} {emission : Emission} (valid : DegreeValid rows) - (emitted : emitOp selector rank first op rows = some emission) : + (emitted : emitOp selector rank first op rows callRanks = some emission) : DegreeValid emission.outputs := by cases op with | const value => @@ -308,7 +308,7 @@ theorem emitOp_degreeValid {selector rank : Expr} {first : Nat} {op : Bytecode.O theorem emitOps_degreeValid {selector rank : Expr} {ops : List Bytecode.Op} {rows : Array RowExpr} {column : Nat} {emission : OpsEmission} (valid : DegreeValid rows) - (emitted : emitOps selector rank ops rows column = some emission) : DegreeValid emission.values := by + (emitted : emitOps selector rank ops rows column callRanks = some emission) : DegreeValid emission.values := by induction ops generalizing rows column emission with | nil => cases emitted diff --git a/Ix/Aiur/Proofs/OperationExpressions.lean b/Ix/Aiur/Proofs/OperationExpressions.lean index bdef0f6f7..6b11dfb54 100644 --- a/Ix/Aiur/Proofs/OperationExpressions.lean +++ b/Ix/Aiur/Proofs/OperationExpressions.lean @@ -816,59 +816,83 @@ theorem rangeSix_eval {values : Values G} (bytes : Fin 6 → Expr) (results : Fi rangePair_eval (evaluated 4) (evaluated 5), bind, Option.bind_some, pure] rfl +def callGapExpr (mode : Bytecode.CallRank) (first size : Nat) : Fin 6 → Expr := + match mode with + | .ordered => fun index => (mainCurrent (first + size + index.val)).expr + | .zero | .bound => fun _ => .konst 0 + +def calleeRankExpr (mode : Bytecode.CallRank) (rank : Expr) (first size : Nat) : Expr := + match mode with + | .zero => .konst 0 + | .bound => (mainCurrent (first + size)).expr + | .ordered => (rank.frontAdd (.konst 1)).frontAdd (packSix (callGapExpr mode first size)) + +def callRangeExprs (mode : Bytecode.CallRank) (gap : Fin 6 → Expr) : List (List Expr) := + match mode with + | .ordered => rangeSix gap + | .zero | .bound => [] + def emitCall (_selector rank : Expr) (first function : Nat) (inputs : Array RowExpr) - (size : Nat) : Emission := + (size : Nat) (mode : Bytecode.CallRank := .ordered) : Emission := let outputs := advice first size - let gap : Fin 6 → Expr := fun index => (mainCurrent (first + size + index.val)).expr - let child := (rank.frontAdd (.konst 1)).frontAdd (packSix gap) - { outputs, used := size + 6, + let gap := callGapExpr mode first size + let child := calleeRankExpr mode rank first size + { outputs, used := size + AIR.callAuxiliaries mode, queries := ([.konst 0, .konst (G.ofNat function)] ++ - (rowExprs inputs).toList ++ (rowExprs outputs).toList ++ [child]) :: rangeSix gap, + (rowExprs inputs).toList ++ (rowExprs outputs).toList ++ [child]) :: callRangeExprs mode gap, calls := [⟨function, rowExprs inputs, rowExprs outputs, child, gap⟩] } theorem emitCall_reflects (values : Values G) (row : Nat → G) (first function size : Nat) {selector rank : Expr} {s r : G} {inputs : Array RowExpr} {arguments : Array AIR.RowValue} + {mode : Bytecode.CallRank} (_selectorEval : evalExpr values selector = some s) (rankEval : evalExpr values rank = some r) (inputEval : evalRows values inputs = some arguments) - (reads : ∀ index < size + 6, + (reads : ∀ index < size + AIR.callAuxiliaries mode, (values.columns .main .current)[first + index]? = some (row index)) : - (emitCall selector rank first function inputs size).eval values = - some { outputs := AIR.rowAdvice row 0 size, used := size + 6, - queries := AIR.functionMessage - ⟨function, AIR.rowValues arguments, AIR.rowValues (AIR.rowAdvice row 0 size), - r + 1 + AIR.packRank (fun index => row (size + index.val))⟩ :: - (AIR.rankByteQueries (fun index => row (size + index.val))).map AIR.rangeMessage, - calls := [(⟨function, AIR.rowValues arguments, AIR.rowValues (AIR.rowAdvice row 0 size), - r + 1 + AIR.packRank (fun index => row (size + index.val))⟩, - fun index => row (size + index.val))] } := by + (emitCall selector rank first function inputs size mode).eval values = + some (AIR.emitCallRow row r function (AIR.rowValues arguments) size mode) := by have outputs := advice_eval values row first size (fun index bound => reads index (by omega)) have gap (index : Fin 6) : - evalExpr values (mainCurrent (first + size + index.val)).expr = - some (row (size + index.val)) := by - change (values.columns .main .current)[first + size + index.val]? = _ - simpa only [Nat.add_assoc] using reads (size + index.val) (by omega) - have child := Expr.frontAdd_eval goldilocksLaws values - (Expr.frontAdd_eval goldilocksLaws values rankEval - (show evalExpr values (.konst 1) = some 1 from rfl)) - (packSix_eval values _ _ gap) + evalExpr values (callGapExpr mode first size index) = + some (AIR.callGap mode row size index) := by + cases mode with + | zero | bound => rfl + | ordered => + change (values.columns .main .current)[first + size + index.val]? = _ + simpa only [Nat.add_assoc, AIR.callGap] using reads (size + index.val) (by + simp only [AIR.callAuxiliaries]; omega) + have child : evalExpr values (calleeRankExpr mode rank first size) = + some (AIR.calleeRank mode row r size) := by + cases mode with + | zero => rfl + | bound => exact reads size (by simp only [AIR.callAuxiliaries]; omega) + | ordered => + exact Expr.frontAdd_eval goldilocksLaws values + (Expr.frontAdd_eval goldilocksLaws values rankEval + (show evalExpr values (.konst 1) = some 1 from rfl)) + (packSix_eval values _ _ gap) + have ranges : (callRangeExprs mode (callGapExpr mode first size)).mapM + (List.mapM (evalExpr values)) = + some (AIR.callRangeQueries mode (AIR.callGap mode row size)) := by + cases mode with + | zero | bound => rfl + | ordered => exact rangeSix_eval _ _ gap have args := congrArg (Functor.map Array.toList) (evalRows_values inputEval) have outs := congrArg (Functor.map Array.toList) (evalRows_values outputs) rw [Array.toList_mapM] at args outs simp only [Functor.map, Option.map_some] at args outs apply Emission.eval_of outputs rfl rfl ?_ ?_ - · simp only [emitCall, List.mapM_cons, List.mapM_append, List.mapM_nil, + · simp only [emitCall, AIR.emitCallRow, List.mapM_cons, List.mapM_append, List.mapM_nil, show evalExpr values (.konst 0) = some 0 from rfl, show evalExpr values (.konst (G.ofNat function)) = some (G.ofNat function) from rfl, - args, outs, child, rangeSix_eval _ _ gap, bind, Option.bind_some, pure] + args, outs, child, ranges, bind, Option.bind_some, pure] rfl · have call := CallExpr.eval_of (call := ⟨function, rowExprs inputs, rowExprs (advice first size), - (rank.frontAdd (.konst 1)).frontAdd (packSix - (fun index => (mainCurrent (first + size + index.val)).expr)), - fun index => (mainCurrent (first + size + index.val)).expr⟩) + calleeRankExpr mode rank first size, callGapExpr mode first size⟩) (evalRows_values inputEval) (evalRows_values outputs) child gap - simp only [emitCall, List.mapM_cons, List.mapM_nil, call, bind, Option.bind_some, pure] - rfl + simp only [emitCall, AIR.emitCallRow, List.mapM_cons, List.mapM_nil, + call, bind, Option.bind_some, pure] def emitStore (first : Nat) (contents : Array RowExpr) : Emission := { outputs := advice first 1, used := 1, @@ -1053,7 +1077,7 @@ Operand reads here are checked in the incoming logical scope. The native store reads after pushing its pointer, so that correspondence also uses the checked program's incoming-scope index validity. -/ def emitOp (selector rank : Expr) (first : Nat) (op : Bytecode.Op) - (rows : Array RowExpr) : Option Emission := + (rows : Array RowExpr) (callRanks : Array Bytecode.CallRank := #[]) : Option Emission := match op with | .const value => some (fromScalar ⟨.konst value, 0, []⟩) | .add a b => do return fromScalar ⟨(← rows[a]?).add (← rows[b]?), 0, []⟩ @@ -1062,7 +1086,9 @@ def emitOp (selector rank : Expr) (first : Nat) (op : Bytecode.Op) | .eqZero a => do return fromScalar (NativeAIR.emitEqZero selector first (← rows[a]?)) | .call function indices size unconstrained => if unconstrained then some (emitAdvice first size) - else do return emitCall selector rank first function (← select rows indices) size + else do + return emitCall selector rank first function (← select rows indices) size + (callRanks[function]?.getD .ordered) | .store indices => do return emitStore first (← select rows indices) | .load size index => do return emitLoad first size (← rows[index]?) | .assertEq xs ys _ => diff --git a/Ix/Aiur/Proofs/OperationReflection.lean b/Ix/Aiur/Proofs/OperationReflection.lean index 1896f63fc..f4ae18aba 100644 --- a/Ix/Aiur/Proofs/OperationReflection.lean +++ b/Ix/Aiur/Proofs/OperationReflection.lean @@ -13,6 +13,8 @@ derive all output values, metadata, equations, raw queries and call records. namespace Aiur.NativeAIR.OpEmitter +variable {callRanks : Array Bytecode.CallRank} + theorem fromScalar_eval (values : Values G) (emission : ScalarEmission) : (fromScalar emission).eval values = emission.eval values := by have singleton : evalRows values #[emission.output] = do @@ -45,13 +47,13 @@ theorem Normal.read {rows : Array RowExpr} (normal : Normal rows) theorem emitOp_byte1 (selector rank : Expr) (first : Nat) (kind : AIR.Byte1Kind) (index : Nat) (rows : Array RowExpr) : - emitOp selector rank first (kind.op index) rows = do + emitOp selector rank first (kind.op index) rows callRanks = do return emitByte1 first kind (← rows[index]?) := by cases kind <;> rfl theorem emitOp_byte2 (selector rank : Expr) (first : Nat) (kind : AIR.Byte2Kind) (left right : Nat) (rows : Array RowExpr) : - emitOp selector rank first (kind.op left right) rows = do + emitOp selector rank first (kind.op left right) rows callRanks = do return emitByte2 first kind (← rows[left]?) (← rows[right]?) := by cases kind <;> rfl @@ -59,10 +61,10 @@ theorem emitByte1_dispatch (values : Values G) (row : Nat → G) (selector rank (s r : G) (first : Nat) (kind : AIR.Byte1Kind) (index : Nat) {rows : Array RowExpr} {inputs : Array AIR.RowValue} {emission : Emission} (inputEval : evalRows values rows = some inputs) - (emitted : emitOp selector rank first (kind.op index) rows = some emission) + (emitted : emitOp selector rank first (kind.op index) rows callRanks = some emission) (reads : ∀ index < emission.used, (values.columns .main .current)[first + index]? = some (row index)) : - ∃ result, AIR.emitOp row s r (kind.op index) inputs = some result ∧ + ∃ result, AIR.emitOp row s r (kind.op index) inputs callRanks = some result ∧ emission.eval values = some result := by rw [emitOp_byte1] at emitted simp only [bind, Option.bind] at emitted @@ -79,10 +81,10 @@ theorem emitByte2_dispatch (values : Values G) (row : Nat → G) (selector rank (s r : G) (first : Nat) (kind : AIR.Byte2Kind) (left right : Nat) {rows : Array RowExpr} {inputs : Array AIR.RowValue} {emission : Emission} (inputEval : evalRows values rows = some inputs) (normal : Normal rows) - (emitted : emitOp selector rank first (kind.op left right) rows = some emission) + (emitted : emitOp selector rank first (kind.op left right) rows callRanks = some emission) (reads : ∀ index < emission.used, (values.columns .main .current)[first + index]? = some (row index)) : - ∃ result, AIR.emitOp row s r (kind.op left right) inputs = some result ∧ + ∃ result, AIR.emitOp row s r (kind.op left right) inputs callRanks = some result ∧ emission.eval values = some result := by rw [emitOp_byte2] at emitted simp only [bind, Option.bind] at emitted @@ -117,10 +119,10 @@ theorem emitOp_reflects (values : Values G) (row : Nat → G) {rows : Array RowExpr} {inputs : Array AIR.RowValue} {emission : Emission} (selectorEval : evalExpr values selector = some s) (rankEval : evalExpr values rank = some r) (inputEval : evalRows values rows = some inputs) (normal : Normal rows) - (emitted : emitOp selector rank first op rows = some emission) + (emitted : emitOp selector rank first op rows callRanks = some emission) (reads : ∀ index < emission.used, (values.columns .main .current)[first + index]? = some (row index)) : - ∃ result, AIR.emitOp row s r op inputs = some result ∧ emission.eval values = some result := by + ∃ result, AIR.emitOp row s r op inputs callRanks = some result ∧ emission.eval values = some result := by cases op with | const value => cases emitted @@ -173,7 +175,7 @@ theorem emitOp_reflects (values : Values G) (row : Nat → G) obtain ⟨x, readX, refX⟩ := evalRows_read inputEval readA obtain ⟨y, readY, refY⟩ := evalRows_read inputEval readB have reflected := NativeAIR.emitMul_reflects values row selectorEval refX refY reads - have indexed : AIR.emitOp row s r (.mul a b) inputs = AIR.emitOp row s 0 (.mul 0 1) #[x, y] := by + have indexed : AIR.emitOp row s r (.mul a b) inputs callRanks = AIR.emitOp row s 0 (.mul 0 1) #[x, y] := by simp only [AIR.emitOp, readX, readY, show #[x, y][0]? = some x from rfl, show #[x, y][1]? = some y from rfl, bind, Option.bind_some] rw [indexed] @@ -191,7 +193,7 @@ theorem emitOp_reflects (values : Values G) (row : Nat → G) cases emitted obtain ⟨value, readValue, refValue⟩ := evalRows_read inputEval read have reflected := NativeAIR.emitEqZero_reflects values row selectorEval refValue reads - have indexed : AIR.emitOp row s r (.eqZero index) inputs = AIR.emitOp row s 0 (.eqZero 0) #[value] := by + have indexed : AIR.emitOp row s r (.eqZero index) inputs callRanks = AIR.emitOp row s 0 (.eqZero 0) #[value] := by simp only [AIR.emitOp, readValue, show #[value][0]? = some value from rfl, bind, Option.bind_some] rw [indexed] have total : ∃ result, AIR.emitOp row s 0 (.eqZero 0) #[value] = some result := by @@ -211,7 +213,8 @@ theorem emitOp_reflects (values : Values G) (row : Nat → G) rename_i arguments selected cases emitted obtain ⟨args, argsRead, argsEval⟩ := select_reflects inputEval selected - refine ⟨_, ?_, emitCall_reflects values row first function size selectorEval rankEval argsEval reads⟩ + refine ⟨_, ?_, emitCall_reflects values row first function size + (mode := callRanks[function]?.getD .ordered) selectorEval rankEval argsEval reads⟩ simp only [AIR.emitOp, Bool.false_eq_true, if_false, select_values argsRead, bind, Option.bind_some, pure] | store indices => @@ -343,7 +346,7 @@ theorem emitOp_reflects (values : Values G) (row : Nat → G) theorem emitByte1_dispatch_normal (selector rank : Expr) (first : Nat) (kind : AIR.Byte1Kind) (index : Nat) {rows : Array RowExpr} {emission : Emission} - (emitted : emitOp selector rank first (kind.op index) rows = some emission) : + (emitted : emitOp selector rank first (kind.op index) rows callRanks = some emission) : Normal emission.outputs := by rw [emitOp_byte1] at emitted simp only [bind, Option.bind] at emitted @@ -355,7 +358,7 @@ theorem emitByte1_dispatch_normal (selector rank : Expr) (first : Nat) theorem emitByte2_dispatch_normal (selector rank : Expr) (first : Nat) (kind : AIR.Byte2Kind) (a b : Nat) {rows : Array RowExpr} {emission : Emission} (normal : Normal rows) - (emitted : emitOp selector rank first (kind.op a b) rows = some emission) : + (emitted : emitOp selector rank first (kind.op a b) rows callRanks = some emission) : Normal emission.outputs := by rw [emitOp_byte2] at emitted simp only [bind, Option.bind] at emitted @@ -371,7 +374,7 @@ theorem emitByte2_dispatch_normal (selector rank : Expr) (first : Nat) theorem emitOp_normal {selector rank : Expr} {first : Nat} {op : Bytecode.Op} {rows : Array RowExpr} {emission : Emission} (normal : Normal rows) - (emitted : emitOp selector rank first op rows = some emission) : + (emitted : emitOp selector rank first op rows callRanks = some emission) : Normal emission.outputs := by cases op with | const value => diff --git a/Ix/Aiur/Proofs/OperationRows.lean b/Ix/Aiur/Proofs/OperationRows.lean index 78019efca..241bee26f 100644 --- a/Ix/Aiur/Proofs/OperationRows.lean +++ b/Ix/Aiur/Proofs/OperationRows.lean @@ -125,13 +125,46 @@ def emitU32Add (row : Nat → G) (left right : Array ValIdx) return { outputs := bytes.push ⟨(sum.value - packed.value) * 0xfffffffe00000002, max sum.degree packed.degree, false⟩, used := 4 } +def callAuxiliaries : CallRank → Nat + | .zero => 0 + | .bound => 1 + | .ordered => 6 + +def callGap (mode : CallRank) (row : Nat → G) (size : Nat) : Fin 6 → G := + match mode with + | .ordered => fun index => row (size + index.val) + | .zero | .bound => fun _ => 0 + +def calleeRank (mode : CallRank) (row : Nat → G) (rank : G) (size : Nat) : G := + match mode with + | .zero => 0 + | .bound => row size + | .ordered => rank + 1 + packRank (callGap mode row size) + +def callRangeQueries (mode : CallRank) (gap : Fin 6 → G) : List (List G) := + match mode with + | .ordered => (rankByteQueries gap).map rangeMessage + | .zero | .bound => [] + +/-- Boundary calls bind the selected callee rank in the complete function +message. Only an ordered call allocates and queries a six-byte gap. -/ +def emitCallRow (row : Nat → G) (rank : G) (function : FunIdx) (inputs : Array G) + (size : Nat) (mode : CallRank) : OpEmission := + let outputs := rowAdvice row 0 size + let gap := callGap mode row size + let request : Bytecode.AIR.Call := + ⟨function, inputs, rowValues outputs, calleeRank mode row rank size⟩ + { outputs, used := size + callAuxiliaries mode + queries := functionMessage request :: callRangeQueries mode gap + calls := [(request, gap)] } + /-- Valued model of one native operation. Invalid reads and malformed word widths return `none`. Constant `eq_zero` inputs with positive tracked degree use the ordinary two-column emission, preserving the compiled layout. Store operands are checked in the incoming logical scope; identifying that scope with the Rust emitter's post-pointer reads requires index validity. -/ def emitOp (row : Nat → G) (selector rank : G) (op : Op) - (values : Array RowValue) : Option OpEmission := + (values : Array RowValue) (callRanks : Array CallRank := #[]) : Option OpEmission := match op with | .const value => some { outputs := #[RowValue.konst value] } | .add a b => do return { outputs := #[(← values[a]?).add (← values[b]?)] } @@ -156,14 +189,7 @@ def emitOp (row : Nat → G) (selector rank : G) (op : Op) if unconstrained then some (emitAdvice row size) else do let inputs ← Bytecode.AIR.readValues (rowValues values) indices - let outputs := rowAdvice row 0 size - let gap : Fin 6 → G := fun index => row (size + index.val) - let request : Bytecode.AIR.Call := - ⟨function, inputs, rowValues outputs, rank + 1 + packRank gap⟩ - return { - outputs, used := size + 6 - queries := functionMessage request :: (rankByteQueries gap).map rangeMessage, - calls := [(request, gap)] } + return emitCallRow row rank function inputs size (callRanks[function]?.getD .ordered) | .store indices => do let contents ← Bytecode.AIR.readValues (rowValues values) indices return { @@ -384,7 +410,8 @@ theorem emitOp_step {tables : LookupTables} {width : Nat} {queries : List (List (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) {program : Toplevel} {op : Op} (shape : op.lookupShape program = true) {row : Nat → G} {selector rank : G} {values : Array RowValue} {emission : OpEmission} - (emitted : emitOp row selector rank op values = some emission) + {callRanks : Array CallRank} + (emitted : emitOp row selector rank op values callRanks = some emission) (active : selector = 1) (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.queries ⊆ queries) : Bytecode.AIR.Step (memoryFacts tables.memory) op (rowValues values) @@ -480,7 +507,7 @@ theorem emitOp_step {tables : LookupTables} {width : Nat} {queries : List (List subst emission exact Bytecode.AIR.Step.call (request := ⟨function, inputs, rowValues (rowAdvice row 0 size), - rank + 1 + packRank (fun index => row (size + index.val))⟩) + calleeRank (callRanks[function]?.getD .ordered) row rank size⟩) read (rowValues_advice_size row 0 size) | store indices => have widthBound : indices.size < gSize.toNat := by @@ -607,12 +634,14 @@ structure OpsEmission where /-- Native operation order, including the logical map extension and exact advance of the auxiliary-column cursor after each operation. -/ -def emitOps (row : Nat → G) (selector rank : G) : - List Op → Array RowValue → Nat → Option OpsEmission - | [], values, column => some { values, column } - | op :: ops, values, column => do - let first ← emitOp (fun i => row (column + i)) selector rank op values - let rest ← emitOps row selector rank ops (values ++ first.outputs) (column + first.used) +def emitOps (row : Nat → G) (selector rank : G) (ops : List Op) + (values : Array RowValue) (column : Nat) (callRanks : Array CallRank := #[]) : + Option OpsEmission := + match ops with + | [] => some { values, column } + | op :: ops => do + let first ← emitOp (fun i => row (column + i)) selector rank op values callRanks + let rest ← emitOps row selector rank ops (values ++ first.outputs) (column + first.used) callRanks return { rest with equations := first.equations ++ rest.equations queries := first.queries ++ rest.queries @@ -628,7 +657,8 @@ theorem emitOps_run {tables : LookupTables} {width : Nat} {queries : List (List (canonical : ∀ size ∈ tables.memoryWidths, size < gSize.toNat) {program : Toplevel} {ops : List Op} (shapes : ∀ op ∈ ops, op.lookupShape program = true) {row : Nat → G} {selector rank : G} {values : Array RowValue} {column : Nat} - {emission : OpsEmission} (emitted : emitOps row selector rank ops values column = some emission) + {emission : OpsEmission} {callRanks : Array CallRank} + (emitted : emitOps row selector rank ops values column callRanks = some emission) (active : selector = 1) (satisfied : ∀ equation ∈ emission.equations, equation = 0) (queried : emission.queries ⊆ queries) : Bytecode.AIR.RunOps (memoryFacts tables.memory) ops (rowValues values) diff --git a/Ix/Aiur/Proofs/OperationSequences.lean b/Ix/Aiur/Proofs/OperationSequences.lean index 7e24a5bb7..ec0736c0b 100644 --- a/Ix/Aiur/Proofs/OperationSequences.lean +++ b/Ix/Aiur/Proofs/OperationSequences.lean @@ -13,6 +13,8 @@ symbolic emission and defined reads of exactly the consumed column interval. namespace Aiur.NativeAIR.OpEmitter +variable {callRanks : Array Bytecode.CallRank} + theorem evalRows_append {values : Values G} {left right : Array RowExpr} {a b : Array AIR.RowValue} (leftEval : evalRows values left = some a) (rightEval : evalRows values right = some b) : @@ -110,11 +112,13 @@ theorem OpsEmission.eval_components {values : Values G} {emission : OpsEmission} cases evaluated exact ⟨outputsEval, rfl, equationsEval, queriesEval, callsEval⟩ -def emitOps (selector rank : Expr) : List Bytecode.Op → Array RowExpr → Nat → Option OpsEmission - | [], rows, column => some { values := rows, column } - | op :: ops, rows, column => do - let first ← emitOp selector rank column op rows - let rest ← emitOps selector rank ops (rows ++ first.outputs) (column + first.used) +def emitOps (selector rank : Expr) (ops : List Bytecode.Op) (rows : Array RowExpr) + (column : Nat) (callRanks : Array Bytecode.CallRank := #[]) : Option OpsEmission := + match ops with + | [] => some { values := rows, column } + | op :: ops => do + let first ← emitOp selector rank column op rows callRanks + let rest ← emitOps selector rank ops (rows ++ first.outputs) (column + first.used) callRanks return { rest with equations := first.equations ++ rest.equations queries := first.queries ++ rest.queries @@ -122,7 +126,7 @@ def emitOps (selector rank : Expr) : List Bytecode.Op → Array RowExpr → Nat theorem emitOps_column {selector rank : Expr} {ops : List Bytecode.Op} {rows : Array RowExpr} {column : Nat} {emission : OpsEmission} - (emitted : emitOps selector rank ops rows column = some emission) : column ≤ emission.column := by + (emitted : emitOps selector rank ops rows column callRanks = some emission) : column ≤ emission.column := by induction ops generalizing rows column emission with | nil => cases emitted @@ -140,7 +144,7 @@ theorem emitOps_column {selector rank : Expr} {ops : List Bytecode.Op} {rows : A theorem emitOps_normal {selector rank : Expr} {ops : List Bytecode.Op} {rows : Array RowExpr} {column : Nat} {emission : OpsEmission} (normal : Normal rows) - (emitted : emitOps selector rank ops rows column = some emission) : Normal emission.values := by + (emitted : emitOps selector rank ops rows column callRanks = some emission) : Normal emission.values := by induction ops generalizing rows column emission with | nil => cases emitted @@ -162,10 +166,10 @@ theorem emitOps_reflects (values : Values G) (row : Nat → G) {inputs : Array AIR.RowValue} {column : Nat} {emission : OpsEmission} (selectorEval : evalExpr values selector = some s) (rankEval : evalExpr values rank = some r) (inputEval : evalRows values rows = some inputs) (normal : Normal rows) - (emitted : emitOps selector rank ops rows column = some emission) + (emitted : emitOps selector rank ops rows column callRanks = some emission) (reads : ∀ index, column ≤ index → index < emission.column → (values.columns .main .current)[index]? = some (row index)) : - ∃ result, AIR.emitOps row s r ops inputs column = some result ∧ emission.eval values = some result := by + ∃ result, AIR.emitOps row s r ops inputs column callRanks = some result ∧ emission.eval values = some result := by induction ops generalizing rows inputs column emission with | nil => cases emitted diff --git a/Ix/Aiur/Proofs/SystemGraphExecution.lean b/Ix/Aiur/Proofs/SystemGraphExecution.lean new file mode 100644 index 000000000..504488760 --- /dev/null +++ b/Ix/Aiur/Proofs/SystemGraphExecution.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.TableGraphTraces + +/-! Execution from the selected compiled key's physical base graphs and one +bounded global balance equation. Graph evaluation supplies every emitted +row, layout bound and local equation. PCS authentication, fixed-preprocessing +binding and randomized lookup soundness remain the cryptographic boundary. -/ + +namespace Aiur.NativeAIR.CompiledKey + +theorem circuits_trace_parts {logBlowup : Nat} {program : Bytecode.Toplevel} {keys : List KeyCodec.Circuit} + (built : circuits logBlowup program = some keys) : + program.circuits.toList.mapM (functionCircuit logBlowup program) = + some (keys.take program.circuits.size) ∧ + program.memorySizes.toList.mapM (memoryCircuit logBlowup) = + some ((keys.drop program.circuits.size).take program.memorySizes.size) := by + obtain ⟨functions, memories, _, _, functionsBuilt, memoriesBuilt, _, _, equal⟩ := circuits_parts built + have fl := Bytecode.AIR.list_mapM_some_length _ _ _ functionsBuilt + have ml := Bytecode.AIR.list_mapM_some_length _ _ _ memoriesBuilt + simp only [Array.length_toList] at fl ml + have first : keys.take program.circuits.size = functions := by + rw [equal, List.append_assoc, ← fl, List.take_left] + have second : (keys.drop program.circuits.size).take program.memorySizes.size = memories := by + rw [equal, List.append_assoc, ← fl, List.drop_left, ← ml, List.take_left] + exact ⟨first ▸ functionsBuilt, second ▸ memoriesBuilt⟩ + +end Aiur.NativeAIR.CompiledKey + +namespace Aiur.AIR +open NativeAIR + +structure GraphLookupData where + functions : List LookupRow + memories : List LookupRow + unary : List LookupRow + binary : List LookupRow + +def GraphLookupData.queries (data : GraphLookupData) : List (List G) := graphFunctionQueries data.functions + +def GraphLookupData.providers (data : GraphLookupData) : List (Provider (List G)) := + graphFunctionProviders data.functions ++ + (graphTableProviders data.memories ++ (graphTableProviders data.unary ++ graphTableProviders data.binary)) + +def SystemTraces.GraphSatisfied {program : Bytecode.Toplevel} (traces : SystemTraces program) + (keys : List KeyCodec.Circuit) : Prop := + traces.functions.GraphSatisfied (keys.take program.circuits.size) ∧ + traces.memories.GraphSatisfied ((keys.drop program.circuits.size).take program.memorySizes.size) + +def SystemTraces.graphLookupData {program : Bytecode.Toplevel} (traces : SystemTraces program) + (keys : List KeyCodec.Circuit) : Option GraphLookupData := do + let functions ← traces.functions.graphLookups (keys.take program.circuits.size) + let memories ← traces.memories.graphLookups ((keys.drop program.circuits.size).take program.memorySizes.size) + let byte1 ← keys[program.circuits.size + program.memorySizes.size]? + let byte2 ← keys[program.circuits.size + program.memorySizes.size + 1]? + let unary ← byte1.graph.readPreprocessedTraceLookups byte1.widths (finiteTraceMatrix traces.bytes.unary) + (finiteTraceMatrix byte1PreprocessedColumns) + let binary ← byte2.graph.readPreprocessedTraceLookups byte2.widths (finiteTraceMatrix traces.bytes.binary) + (finiteTraceMatrix byte2PreprocessedColumns) + return ⟨functions, memories, unary, binary⟩ + +theorem SystemTraces.graph_extract {program : Bytecode.Toplevel} (traces : SystemTraces program) + {logBlowup : Nat} {keys : List KeyCodec.Circuit} + (built : CompiledKey.circuits logBlowup program = some keys) (satisfied : traces.GraphSatisfied keys) : + ∃ witnesses data, traces.functions.emitNativeWitnesses program = some witnesses ∧ + (∀ witness ∈ witnesses, witness.Satisfied ∧ witness.NativeBounds program) ∧ + traces.memories.Satisfied ∧ traces.graphLookupData keys = some data ∧ + data.queries = encodedCircuitQueryPool (witnesses.map (·.emission)) ∧ + data.providers = traces.providers (witnesses.map (·.emission)) := by + have parts := CompiledKey.circuits_trace_parts built + obtain ⟨witnesses, emitted, valid, functionRead⟩ := traces.functions.graph_extract parts.1 satisfied.1 + obtain ⟨memoryRows, memoryRead, memoryProviders⟩ := traces.memories.graph_providers parts.2 + have memorySatisfied := traces.memories.graph_satisfied parts.2 satisfied.2 + obtain ⟨byte1, byte2, first, second, firstIndex, secondIndex⟩ := CompiledKey.circuits_bytes built + have unaryRead := CompiledKey.byte1Circuit_matrix_lookups first traces.bytes.unary + have binaryRead := CompiledKey.byte2Circuit_matrix_lookups second traces.bytes.binary + let data : GraphLookupData := + ⟨witnesses.map (fun witness => emissionLookupRow witness.emission), memoryRows, + List.ofFn (fun index => Byte1Kind.all.map fun kind => byte1ColumnLookup kind (byte1PreprocessedColumns index) (traces.bytes.unary index)), + List.ofFn (fun index => Byte2Kind.all.map fun kind => byte2ColumnLookup kind (byte2PreprocessedColumns index) (traces.bytes.binary index))⟩ + refine ⟨witnesses, data, emitted, valid, memorySatisfied, ?_, ?_, ?_⟩ + · simp only [graphLookupData, functionRead, memoryRead, firstIndex, secondIndex, + unaryRead, binaryRead, bind, Option.bind_some, pure] + rfl + · have equality := graphFunctionQueries_emissions (witnesses.map (·.emission)) (by + intro emission member query queryMember + obtain ⟨witness, witnessMember, rfl⟩ := List.mem_map.mp member + exact ((valid witness witnessMember).2.1.2 query queryMember).1) + simpa only [data, GraphLookupData.queries, List.map_map, Function.comp_def] using equality + · have equality := graphFunctionProviders_emissions (witnesses.map (·.emission)) (by + intro emission member + obtain ⟨witness, witnessMember, rfl⟩ := List.mem_map.mp member + exact (valid witness witnessMember).2.1.1) + simp only [List.map_map, Function.comp_def] at equality + simp only [data, GraphLookupData.providers, equality, memoryProviders, + graphTableProviders_byte1, graphTableProviders_byte2, SystemTraces.providers, ByteTraces.providers] + +end Aiur.AIR + +namespace Aiur.BoundVerifier +open AIR Bytecode.AIR + +theorem CompiledBackend.graph_trace_execution {selection : Selection} (backend : CompiledBackend selection) + (traces : SystemTraces backend.compiled.bytecode) (data : GraphLookupData) + (lookups : traces.graphLookupData backend.keyData.circuits = some data) + (satisfied : traces.GraphSatisfied backend.keyData.circuits) + {result : Nat} (budget : traces.queryBound = some result) + (width : Nat) (input : Array G) (arity : input.size = selection.inputSize) + (balanced : PaddedLookupBalance width + ((buildClaim selection.function input selection.success).toList :: data.queries) data.providers) + (publicWidth : (buildClaim selection.function input selection.success).size + 1 ≤ width) + (queryWidths : ∀ query ∈ data.queries, query.length ≤ width) : + Execution backend.compiled.bytecode (memoryFacts traces.memories.rows) ⟨selection.function, input, selection.success, 0⟩ ∧ + ∀ size pointer left right, memoryFacts traces.memories.rows size pointer left → + memoryFacts traces.memories.rows size pointer right → left = right := by + obtain ⟨witnesses, actual, emitted, valid, memorySatisfied, read, queries, providers⟩ := + traces.graph_extract backend.circuits_bound satisfied + have equal := Option.some.inj (read.symm.trans lookups) + subst actual + rw [queries, providers] at balanced + rw [queries] at queryWidths + exact backend.native_column_trace_execution traces emitted budget width input arity balanced publicWidth queryWidths + (fun witness member => (valid witness member).1) (fun witness member => (valid witness member).2) memorySatisfied + +end Aiur.BoundVerifier diff --git a/Ix/Aiur/Proofs/TableGraphTraces.lean b/Ix/Aiur/Proofs/TableGraphTraces.lean new file mode 100644 index 000000000..3a53e044b --- /dev/null +++ b/Ix/Aiur/Proofs/TableGraphTraces.lean @@ -0,0 +1,187 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.Proofs.GraphLookupTraces + +/-! Physical memory and byte graph lookups have the provider interpretation +used by the single global pool. Byte preprocessing is the canonical fixed +matrix; binding the committed preprocessing to this matrix is a separate +PCS obligation. -/ + +namespace Aiur.NativeAIR +open AIR Compiler OpEmitter + +def graphLookupProvider (lookup : G × List G) : Provider (List G) := (lookup.2, 0 - lookup.1) + +def graphTableProviders (rows : List LookupRow) : List (Provider (List G)) := + rows.flatMap fun row => row.map graphLookupProvider + +theorem graphTableProviders_append (first rest : List LookupRow) : + graphTableProviders (first ++ rest) = graphTableProviders first ++ graphTableProviders rest := + List.flatMap_append + +theorem graphLookupProvider_memory (width : Nat) (columns : MemoryColumns width) : + graphLookupProvider (memoryColumnLookup width columns) = memoryColumnProvider width columns := by + simp only [graphLookupProvider, memoryColumnProvider, memoryColumnLookup, G.neg_neg] + +theorem graphTableProviders_memory (width height : Nat) (matrix : Fin height → MemoryColumns width) : + graphTableProviders (List.ofFn fun index => [memoryColumnLookup width (matrix index)]) = + memoryMatrixProviders width height matrix := by + induction height with + | zero => rfl + | succ height ih => + simp only [graphTableProviders, List.ofFn_succ, List.flatMap_cons, List.map_cons, List.map_nil, + List.singleton_append, memoryMatrixProviders, graphLookupProvider_memory] + exact congrArg (_ :: ·) (ih (fun index => matrix index.succ)) + +theorem CompiledKey.memoryCircuit_matrix_lookups {logBlowup width : Nat} {artifact : KeyCodec.Circuit} + (built : CompiledKey.memoryCircuit logBlowup width = some artifact) {height : Nat} + (matrix : Fin height → MemoryColumns width) : + artifact.graph.readTraceLookups artifact.widths (finiteTraceMatrix matrix) = + some (List.ofFn fun index => [memoryColumnLookup width (matrix index)]) := by + apply list_mapM_ofFn id _ _ + intro index + obtain ⟨buffer, swept, _, lookups⟩ := CompiledKey.memoryCircuit_trace_reflects built matrix index + simp only [id_eq, Graph.readLookups, swept, bind, Option.bind_some, lookups] + +def traceRowValuesWithPreprocessed (widths : GraphWidths) {height : Nat} + (matrix preprocessed : Fin height → Nat → G) (index : Fin height) : Values G := + { traceRowValues widths matrix index with + columns := fun source offset => match source, offset with + | .preprocessed, .current => Array.ofFn fun column : Fin widths.preprocessed => preprocessed index column.val + | .preprocessed, .next => Array.ofFn fun column : Fin widths.preprocessed => preprocessed (memoryNextIndex index) column.val + | source, offset => (traceRowValues widths matrix index).columns source offset } + +theorem traceRowValuesWithPreprocessed_fits (widths : GraphWidths) {height : Nat} + (matrix preprocessed : Fin height → Nat → G) (index : Fin height) : + (traceRowValuesWithPreprocessed widths matrix preprocessed index).Fits widths := by + refine ⟨?_, Array.size_replicate⟩ + intro source offset + cases source <;> cases offset <;> + simp only [traceRowValuesWithPreprocessed, traceRowValues, GraphWidths.width, Array.size_ofFn, Array.size_replicate] + +theorem traceRowValuesWithPreprocessed_columns {widths : GraphWidths} {height mainWidth preprocessedWidth : Nat} + (matrix : Fin height → Fin mainWidth → G) (preprocessed : Fin height → Fin preprocessedWidth → G) + (index : Fin height) (mainBound : mainWidth ≤ widths.main) (preprocessedBound : preprocessedWidth ≤ widths.preprocessed) : + CompiledKey.columns (traceRowValuesWithPreprocessed widths (finiteTraceMatrix matrix) (finiteTraceMatrix preprocessed) index) + .main .current mainWidth = matrix index ∧ + CompiledKey.columns (traceRowValuesWithPreprocessed widths (finiteTraceMatrix matrix) (finiteTraceMatrix preprocessed) index) + .preprocessed .current preprocessedWidth = preprocessed index := by + refine ⟨(traceRowValues_finite_columns matrix index mainBound).1, ?_⟩ + funext column + have inside := Nat.lt_of_lt_of_le column.isLt preprocessedBound + simp only [CompiledKey.columns, traceRowValuesWithPreprocessed, finiteTraceMatrix, + Array.getElem?_ofFn, inside, column.isLt, dif_pos, Option.getD_some] + +def Graph.readPreprocessedTraceLookups (graph : Graph) (widths : GraphWidths) {height : Nat} + (matrix preprocessed : Fin height → Nat → G) : Option (List LookupRow) := + (List.ofFn id).mapM fun index => graph.readLookups (traceRowValuesWithPreprocessed widths matrix preprocessed index) + +theorem CompiledKey.byte1Circuit_matrix_lookups {logBlowup : Nat} {artifact : KeyCodec.Circuit} + (built : CompiledKey.byte1Circuit logBlowup = some artifact) (matrix : Fin 256 → Byte1Columns) : + artifact.graph.readPreprocessedTraceLookups artifact.widths (finiteTraceMatrix matrix) + (finiteTraceMatrix byte1PreprocessedColumns) = + some (List.ofFn fun index => Byte1Kind.all.map fun kind => + byte1ColumnLookup kind (byte1PreprocessedColumns index) (matrix index)) := by + obtain ⟨_, _, _, mainWidth, preWidth, _⟩ := CompiledKey.byte1Circuit_success built + apply list_mapM_ofFn id _ _ + intro index + obtain ⟨buffer, swept, _, lookups⟩ := CompiledKey.byte1Circuit_reflects built + (traceRowValuesWithPreprocessed_fits artifact.widths (finiteTraceMatrix matrix) + (finiteTraceMatrix byte1PreprocessedColumns) index) + have columns := traceRowValuesWithPreprocessed_columns matrix byte1PreprocessedColumns index + (show 3 ≤ artifact.widths.main from Nat.le_of_eq mainWidth.symm) + (show 11 ≤ artifact.widths.preprocessed from Nat.le_of_eq preWidth.symm) + rw [columns.1, columns.2] at lookups + simp only [id_eq, Graph.readLookups, swept, bind, Option.bind_some, lookups] + +theorem CompiledKey.byte2Circuit_matrix_lookups {logBlowup : Nat} {artifact : KeyCodec.Circuit} + (built : CompiledKey.byte2Circuit logBlowup = some artifact) (matrix : Fin 65536 → Byte2Columns) : + artifact.graph.readPreprocessedTraceLookups artifact.widths (finiteTraceMatrix matrix) + (finiteTraceMatrix byte2PreprocessedColumns) = + some (List.ofFn fun index => Byte2Kind.all.map fun kind => + byte2ColumnLookup kind (byte2PreprocessedColumns index) (matrix index)) := by + obtain ⟨_, _, _, mainWidth, preWidth, _⟩ := CompiledKey.byte2Circuit_success built + apply list_mapM_ofFn id _ _ + intro index + obtain ⟨buffer, swept, _, lookups⟩ := CompiledKey.byte2Circuit_reflects built + (traceRowValuesWithPreprocessed_fits artifact.widths (finiteTraceMatrix matrix) + (finiteTraceMatrix byte2PreprocessedColumns) index) + have columns := traceRowValuesWithPreprocessed_columns matrix byte2PreprocessedColumns index + (show 10 ≤ artifact.widths.main from Nat.le_of_eq mainWidth.symm) + (show 14 ≤ artifact.widths.preprocessed from Nat.le_of_eq preWidth.symm) + rw [columns.1, columns.2] at lookups + simp only [id_eq, Graph.readLookups, swept, bind, Option.bind_some, lookups] + +theorem graphLookupProvider_byte1 (kind : Byte1Kind) (index : Fin 256) (columns : Byte1Columns) : + graphLookupProvider (byte1ColumnLookup kind (byte1PreprocessedColumns index) columns) = + byte1ColumnProvider kind index columns := by + simp only [graphLookupProvider, byte1ColumnProvider, byte1ColumnLookup, G.neg_neg] + +theorem graphLookupProvider_byte2 (kind : Byte2Kind) (index : Fin 65536) (columns : Byte2Columns) : + graphLookupProvider (byte2ColumnLookup kind (byte2PreprocessedColumns index) columns) = + byte2ColumnProvider kind index columns := by + simp only [graphLookupProvider, byte2ColumnProvider, byte2ColumnLookup, G.neg_neg] + +theorem graphTableProviders_byte1 (matrix : Fin 256 → Byte1Columns) : + graphTableProviders (List.ofFn fun index => Byte1Kind.all.map fun kind => + byte1ColumnLookup kind (byte1PreprocessedColumns index) (matrix index)) = byte1MatrixProviders matrix := by + have mapped := List.map_ofFn (f := id (α := Fin 256)) (g := fun index => Byte1Kind.all.map fun kind => + byte1ColumnLookup kind (byte1PreprocessedColumns index) (matrix index)) + simp only [Function.comp_id] at mapped + rw [← mapped] + simp only [graphTableProviders, List.flatMap_map, Function.comp_def, List.map_map, + graphLookupProvider_byte1, byte1MatrixProviders, List.finRange] + rfl + +theorem graphTableProviders_byte2 (matrix : Fin 65536 → Byte2Columns) : + graphTableProviders (List.ofFn fun index => Byte2Kind.all.map fun kind => + byte2ColumnLookup kind (byte2PreprocessedColumns index) (matrix index)) = byte2MatrixProviders matrix := by + have mapped := List.map_ofFn (f := id (α := Fin 65536)) (g := fun index => Byte2Kind.all.map fun kind => + byte2ColumnLookup kind (byte2PreprocessedColumns index) (matrix index)) + simp only [Function.comp_id] at mapped + rw [← mapped] + simp only [graphTableProviders, List.flatMap_map, Function.comp_def, List.map_map, + graphLookupProvider_byte2, byte2MatrixProviders, List.finRange] + rfl + +end Aiur.NativeAIR + +namespace Aiur.AIR +open NativeAIR + +def MemoryTraces.graphLookups {widths : List Nat} : MemoryTraces widths → List KeyCodec.Circuit → Option (List LookupRow) + | .nil, [] => some [] + | .inactive _ rest, _ :: keys => rest.graphLookups keys + | .active _ _ matrix rest, key :: keys => do + let first ← key.graph.readTraceLookups key.widths (finiteTraceMatrix matrix) + let later ← rest.graphLookups keys + return first ++ later + | _, _ => none + +theorem MemoryTraces.graph_providers {widths : List Nat} (traces : MemoryTraces widths) + {logBlowup : Nat} {keys : List KeyCodec.Circuit} + (built : widths.mapM (CompiledKey.memoryCircuit logBlowup) = some keys) : + ∃ rows, traces.graphLookups keys = some rows ∧ graphTableProviders rows = traces.providers := by + induction traces generalizing keys with + | nil => + have empty : keys = [] := (Option.some.inj built).symm + subst keys + exact ⟨[], rfl, rfl⟩ + | inactive width rest ih => + obtain ⟨key, keys, _, tail, equal⟩ := list_mapM_cons_parts built + subst equal + exact ih tail + | active width degree matrix rest ih => + obtain ⟨key, keys, head, tail, equal⟩ := list_mapM_cons_parts built + subst equal + obtain ⟨later, laterEq, laterProviders⟩ := ih tail + have firstEq := CompiledKey.memoryCircuit_matrix_lookups head matrix + refine ⟨(List.ofFn fun index => [memoryColumnLookup width (matrix index)]) ++ later, ?_, ?_⟩ + · simp only [graphLookups, firstEq, laterEq, bind, Option.bind_some, pure] + · rw [graphTableProviders_append, graphTableProviders_memory, laterProviders] + rfl + +end Aiur.AIR diff --git a/Tests/Aiur/BlockExpressions.lean b/Tests/Aiur/BlockExpressions.lean index 8f892ee2e..ee5327321 100644 --- a/Tests/Aiur/BlockExpressions.lean +++ b/Tests/Aiur/BlockExpressions.lean @@ -21,7 +21,7 @@ private def readEvaluatedMap (size : Nat) : Reader (Array AIR.RowValue) := do private def readReport (index : Nat) : Reader Nat := do let label := s!"block {index}" let branchless ← readBool - let context : Context := ⟨← readNat, ← readNat, ← readExpr 256⟩ + let context : Context := ⟨← readNat, ← readNat, ← readExpr 256, #[]⟩ let selectors := (← readList (← readCount) (readExpr 256)).toArray let column ← readNat let lookup ← readNat diff --git a/Tests/Aiur/BlockRows.lean b/Tests/Aiur/BlockRows.lean index a26d610bb..26bc008cc 100644 --- a/Tests/Aiur/BlockRows.lean +++ b/Tests/Aiur/BlockRows.lean @@ -85,7 +85,7 @@ private def expected : Except String (ByteArray × Nat) := do let row := row seed pattern count let selector := fun index => row (2 + index) let values := #[RowValue.variable (row 0), RowValue.variable (row 1)] - let some emission := block.emitRow row selector ⟨37, 2, 257⟩ + let some emission := block.emitRow row selector ⟨37, 2, 257, #[]⟩ (block.selectorFlow selector).entry values (2 + count) 1 | throw s!"emission failed at depth {depth}, seed {seed}, pattern {pattern}" out := appendNat out emission.column diff --git a/Tests/Aiur/CircuitRows.lean b/Tests/Aiur/CircuitRows.lean index ed36178cd..41d88653f 100644 --- a/Tests/Aiur/CircuitRows.lean +++ b/Tests/Aiur/CircuitRows.lean @@ -70,7 +70,7 @@ private def fixtureFunction (seed index : Nat) : Except String Function := do let body := if seed % 4 == 0 && index == 0 then { ops := #[], ctrl := .match 0 #[(0, { ops := #[.store #[]], ctrl := .match 0 #[] none }), (1, body)] none } else body - let some measured := body.emitRow (fun _ => 0) (fun _ => 0) ⟨37, inputSize, 0⟩ + let some measured := body.emitRow (fun _ => 0) (fun _ => 0) ⟨37, inputSize, 0, #[]⟩ (body.selectorFlow (fun _ => 0)).entry (rowAdvice (fun _ => 0) 0 inputSize) (inputSize + selectors + 7) 4 | throw "fixture layout emission failed" diff --git a/Tests/Aiur/CompiledKey.lean b/Tests/Aiur/CompiledKey.lean index ce92d52c4..19e3d8e96 100644 --- a/Tests/Aiur/CompiledKey.lean +++ b/Tests/Aiur/CompiledKey.lean @@ -53,10 +53,10 @@ private def readCircuit (program : Bytecode.Toplevel) (index : Nat) (artifact : throw s!"native key graph lookup values differ: {label}" if index < program.circuits.size then let source := program.circuits[index]! - let some symbolic := compileCircuit artifact.widths program source + let some symbolic := compileNativeCircuit artifact.widths program source | throw s!"compilation at native widths rejected: {label}" unless symbolic.base.graph == artifact.graph do throw s!"widened graph differs: {label}" - let some emission := source.emitRow (fun column => (values.columns .main .current)[column]?.getD 0) program + let some emission := source.emitNativeRow (fun column => (values.columns .main .current)[column]?.getD 0) program | throw s!"native key function row rejected: {label}" unless emission.equations == equations && List.ofFn (fun slot : Fin emission.lookupCount => emission.lookup slot.val) == lookups do @@ -111,20 +111,40 @@ private def alterations (program : Bytecode.Toplevel) (key : KeyCodec.Key) : Rea rejectAltered program key { key with preprocessedIndices := key.preprocessedIndices.set 0 (some 0) } "preprocessed index" return changedCircuits.length + 4 +private def rejectComponents (program : Bytecode.Toplevel) (key : KeyCodec.Key) : Reader Nat := do + if program.callComponents.isEmpty then return 0 + let components := program.callComponents + let invalid := [ + components.pop, + components.set! 0 ⟨program.functions.size, false⟩, + components.set! 1 ⟨1, false⟩, + components.set! 0 ⟨3, false⟩] + for components in invalid do + let altered := { program with callComponents := components } + if altered.validCallComponents then throw "component rejection fixture is valid" + if CompiledKey.check altered key then throw "invalid component certificate accepted" + return invalid.length + private def readCorpus : Reader (Nat × Nat × Nat) := do - let header := "Aiur compiled keys v2\n".toUTF8 + let header := "Aiur compiled keys v3\n".toUTF8 unless (← takeBytes header.size) == header do throw "compiled-key snapshot version differs" - unless (← readCount) == 12 do throw "incomplete native key systems" + unless (← readCount) == 24 do throw "incomplete native key systems" let mut circuitCount := 0 let mut assignments := 0 let mut rejections := 0 - for seed in [:12] do + for seed in [:24] do let functions := (← readList (← readCount) do return Bytecode.Function.mk (← readBlock 64) (← readLayout) (← readBool) (← readBool)).toArray let circuits := (← readList (← readCount) do return Bytecode.Circuit.mk "native" (← readIndices) (← readLayout)).toArray let memorySizes ← readIndices - let program : Bytecode.Toplevel := ⟨functions, memorySizes, circuits, #[]⟩ + let components := (← readList (← readCount) do + return Bytecode.CallComponent.mk (← readNat) (← readBool)).toArray + let program : Bytecode.Toplevel := ⟨functions, memorySizes, circuits, components⟩ + unless components.size == (if seed < 12 then 0 else 4) do + throw "incomplete native component policies" + unless components.isEmpty || program.validCallComponents do + throw "invalid native component fixture" let bytes ← takeBytes (← readCount 1048576) let some key := KeyCodec.decodeCanonical bytes | throw s!"native key rejected: system {seed}" unless key.parameters.logBlowup == 1 + seed % 3 do throw "incomplete native lookup-group budgets" @@ -135,6 +155,7 @@ private def readCorpus : Reader (Nat × Nat × Nat) := do assignments := assignments + (← readCircuit program index artifact) circuitCount := circuitCount + 1 rejections := rejections + (← alterations program key) + rejections := rejections + (← rejectComponents program key) let (bytes, cursor) ← get unless cursor == bytes.size do throw "compiled-key snapshot has trailing bytes" return (circuitCount, assignments, rejections) @@ -143,9 +164,9 @@ def run (path : System.FilePath) : IO Unit := do match readCorpus.run (← IO.FS.readBinFile path, 0) with | .error error => throw (IO.userError error) | .ok ((circuits, assignments, rejections), _) => - unless circuits == 180 && assignments == 720 && rejections == 168 do + unless circuits == 360 && assignments == 1440 && rejections == 384 do throw (IO.userError "incomplete native key coverage") - IO.println s!"compiled keys: 12 native systems, {circuits} circuits, {assignments} assignments match; {rejections} valid altered keys rejected" + IO.println s!"compiled keys: 24 native systems (12 component layouts), {circuits} circuits, {assignments} assignments match; 336 valid altered keys and 48 invalid component certificates rejected" end AiurTests.CompiledKeys diff --git a/Tests/Aiur/EmissionChecks.lean b/Tests/Aiur/EmissionChecks.lean index 310fcad8c..8b9f7613d 100644 --- a/Tests/Aiur/EmissionChecks.lean +++ b/Tests/Aiur/EmissionChecks.lean @@ -62,7 +62,7 @@ private def readCorpus : Reader (Nat × Nat × Nat) := do if valid && available ≤ 32 then let selectorTable := CircuitEmitter.selectorExprs available selectors let some entry := blockSelector selectorTable block | throw "checked block selector is absent" - let some emitted := emitBlock selectorTable ⟨0, available, .konst 0⟩ entry + let some emitted := emitBlock selectorTable ⟨0, available, .konst 0, #[]⟩ entry (advice 0 available) (available + selectors) 0 block | throw "checked block failed to emit" unless emitted.yields.all (fun part => yieldSize == some part.values.size) do diff --git a/Tests/Aiur/ProductionKey.lean b/Tests/Aiur/ProductionKey.lean new file mode 100644 index 000000000..f1601a6da --- /dev/null +++ b/Tests/Aiur/ProductionKey.lean @@ -0,0 +1,41 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Aiur.CompiledKey +import Ix.IxVM.Toplevel +import Ix.IxVM.FunctionGroups + +/-! Compare the complete native key of the pruned production `verify_claim` +image with the checked compiler. These are test protocol parameters; this +regression neither certifies the guest checker nor instantiates release +cryptographic security. -/ + +open Aiur Aiur.NativeAIR + +def main : IO Unit := do + let source ← IO.ofExcept (IxVM.ixVM.mapError toString) + let compiled ← IO.ofExcept source.compile + let compiled ← IO.ofExcept (compiled.groupFunctions IxVM.functionGroups) + let program := compiled.bytecode + unless !program.callComponents.isEmpty && program.validCallComponents do + throw (IO.userError "production image lacks its checked component assignment") + let some entry := compiled.getFuncIdx `verify_claim + | throw (IO.userError "production claim entrypoint is missing") + for debugEntry in [`verify_const, `verify_check, `verify_check_env] do + unless (compiled.getFuncIdx debugEntry).isNone do + throw (IO.userError s!"debug entrypoint remains in the production image: {debugEntry}") + IO.println s!"production IxVM: {program.functions.size} functions, {program.circuits.size} function circuits, claim entry {entry}" + let commitment : CommitmentParameters := { logBlowup := 2, capHeight := 0 } + let fri : FriParameters := { + logFinalPolyLen := 0, maxLogArity := 1, numQueries := 64, + commitProofOfWorkBits := 0, queryProofOfWorkBits := 0 } + let system := AiurSystem.build program commitment fri + let bytes := system.vkBytes + let some key := KeyCodec.decodeCanonical bytes + | throw (IO.userError "production native key failed canonical decoding") + IO.println s!"production native key: {key.circuits.length} circuits, {bytes.size} bytes" + unless CompiledKey.check program key do + throw (IO.userError "production native key differs from the checked native-layout compiler") + IO.println "PASS production verify_claim image: every native circuit and retuned lookup group matches the checked key" diff --git a/Tests/Aiur/backend-foundation-review.md b/Tests/Aiur/backend-foundation-review.md index b7b21ccb4..df52fb1e4 100644 --- a/Tests/Aiur/backend-foundation-review.md +++ b/Tests/Aiur/backend-foundation-review.md @@ -50,3 +50,55 @@ compatibility snapshots, and a retuned-key corpus covering 12 systems, 180 circuits, 720 assignments and 168 rejected validly encoded alterations. The full `check-aiur` gate additionally compares the current report byte for byte with the frozen manifest. + +## Native component and physical-trace execution + +The next reviewed boundary extends destination checkpoint +`11be019508abe48573cdb11063c3db8b40f1c607`. It adds 167 roots and 72 premise +definitions: 1,741 roots and 1,060 premises in total. The previous boundary +retains every root, premise and worker. Fifty existing root statements and +20 premise sections change; six worker implementations change and seven +workers are added, for 204 workers. Existing root axiom sets are unchanged. +The new roots use only the standard Lean axioms: one is axiom-free, ten use +`propext`, 35 also use `Quot.sound`, and 121 also use `Classical.choice`. + +| Boundary | Reviewed meaning | +| --- | --- | +| Shared operation, block and member emission | An explicit call-rank table selects zero, boundary or ordered layout. Execution, call inventories, inactive rows, input preservation, auxiliary allocation and lookup cursors carry that same table. The empty-table default retains the fallback semantics. | +| `CallRankChecks`, component edge collection and finite execution | Every call still has its complete function message. Only same-component calls require gap ranges and the derived order equation. The actual constrained calls are included in the checked bytecode edge inventory. A boundary call's rank is bound by its active callee provider; an acyclic provider returns rank zero. | +| Component circuit members, queries and returns | Each member starts at its native column and slot offsets. Rank-range messages are gated by ranked members. Boolean selectors and checked branch/return counts imply query exclusivity, return selection and the terminal single-writer condition, including mixed circuits and empty circuits. | +| `compileNativeCircuit`, `CompiledKey.functionCircuit`, `CompiledKey.check` | The compared key chooses its emission policy from the actual component table. The global check rejects malformed nonempty component tables even when there are no function circuits. Constructors check physical read bounds, positive slot counts, raw query slot ranges and fallback member extents. Lookup retuning remains part of exact key equality. | +| `CompiledBackend.function_graph_reflects` | The former generic-layout premise is removed. The conclusion uses the selected native emitter and derives positive slot counts and bounds. Array widths and the successful checked constructor supply all physical reads; no graph-equality premise is added. | +| Component rows and the global pool | Provisional physical providers are interpreted before local execution is established. A single padded balance and a consumer count below the characteristic supply active callees and byte ranges. Local validity of the provisional table and separate function/byte balance are not premises of the physical endpoint. | +| `GraphSatisfied`, `graphLookupData`, `graph_trace_execution` | Function and memory matrices follow the actual key order and active-height metadata. Finite physical main rows supply valued witnesses. Every graph lookup is preserved in row/slot order; slot zero remains a provider regardless of its field multiplicity. Canonical byte columns and memory graph lookups supply the other providers. The endpoint proves the selected finite execution and functional memory. | +| Key trace metadata and `checked_graph_trace_execution` | Physical graph slot counts equal the execution trace's logical counts, including fallback/component layouts and all auxiliary tables. Fixed heights also agree. Matching the extracted trace bitmap and degrees to `CheckedProof` therefore supplies the exact budget already enforced during proof decoding, independently of lookup grouping. | + +The new workers traverse component members, canonical function/memory traces, +their graph-satisfaction predicates and graph lookup extraction. The six +changed workers forward the selected mode table through the existing valued, +symbolic and lookup-usage traversals. Each has a checked safe source. The +four native externs, three partial Hashable/Repr sources and empty additional +unsafe/replacement inventories are unchanged; `Ix.Compiler` remains excluded. + +The theorem's remaining inputs are physical base-graph satisfaction, canonical +fixed preprocessing, trace activation/height metadata, a checked logical-slot +budget, message widths and exact padded balance. PCS must authenticate those +traces and preprocessing; randomized lookup soundness must derive balance. +Compiler-to-source reflection and guest/kernel soundness are separate later +contracts. This endpoint is not an acceptance-to-no-False theorem. + +The native key corpus now covers 24 systems, 360 circuits and 1,440 arbitrary +assignments. It rejects 336 validly encoded altered keys and 48 invalid +component certificates. A separate production-image check reconstructs the +pruned, grouped `verify_claim` image: 793 functions, 181 function circuits and +201 total key circuits. All native graphs, dimensions, lookup groups and +degrees match the checked key. Its 915,765-byte key uses explicit test +protocol parameters and is not a pinned production security release. + +The full `check-aiur` gate passes: 605 strict build jobs, exact audit-manifest +comparison, four unchanged compiler snapshots, all 40 native/model corpora, +the production-image key check and backend acceptance/rejection tests. +Parallel release Rust tests pass (112 enabled tests), as do Clippy and +formatting. The selected integration suites, all three code-generation +comparisons and the complete 83-fixture IxVM corpus also pass. The generated +images and shard FFT cost of 8,523,899,042 are unchanged. diff --git a/Tests/Aiur/backend-foundation.txt b/Tests/Aiur/backend-foundation.txt index 77e80fc36..975217edd 100644 --- a/Tests/Aiur/backend-foundation.txt +++ b/Tests/Aiur/backend-foundation.txt @@ -1,3 +1,1819 @@ +ROOT Aiur.AIR.CallRankChecks.mono +∀ {callRanks : Array Aiur.Bytecode.CallRank} {rank selector : Aiur.G} {firstEquations lastEquations : List Aiur.G} + {firstQuery lastQuery : List Aiur.G → Prop} {edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)}, + Aiur.AIR.CallRankChecks callRanks rank selector firstEquations firstQuery edge → + firstEquations ⊆ lastEquations → + (∀ (message : List Aiur.G), firstQuery message → lastQuery message) → + Aiur.AIR.CallRankChecks callRanks rank selector lastEquations lastQuery edge +AXIOMS [propext] +ROOT Aiur.AIR.CallRankChecks.ordered +∀ {callRanks : Array Aiur.Bytecode.CallRank} {rank selector : Aiur.G} {equations : List Aiur.G} + {hasQuery : List Aiur.G → Prop} {edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)}, + Aiur.AIR.CallRankChecks callRanks rank selector equations hasQuery edge → + callRanks[edge.fst.function]?.getD Aiur.Bytecode.CallRank.ordered = Aiur.Bytecode.CallRank.ordered → + (∀ ⦃message : List Aiur.G⦄, + message ∈ List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries edge.snd) → hasQuery message) ∧ + Aiur.AIR.EquationAvailable equations + (selector * Aiur.AIR.callOrderConstraint rank edge.fst.rank (Aiur.AIR.packRank edge.snd)) +AXIOMS [propext] +ROOT Aiur.AIR.CircuitTraces.emitNativeWitnesses_spec +∀ {circuits : List Aiur.Bytecode.Circuit} (traces : Aiur.AIR.CircuitTraces circuits) {program : Aiur.Bytecode.Toplevel} + {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitNativeWitnesses program traces = some witnesses → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.circuit ∈ circuits ∧ Aiur.AIR.CircuitWitness.NativeEmitted program witness) ∧ + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)).length ≤ traces.capacity +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitTraces.graph_emits +∀ {circuits : List Aiur.Bytecode.Circuit} (traces : Aiur.AIR.CircuitTraces circuits) {logBlowup : Nat} + {program : Aiur.Bytecode.Toplevel} {keys : List Aiur.NativeAIR.KeyCodec.Circuit}, + List.mapM (Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program) circuits = some keys → + traces.GraphSatisfied keys → + ∃ witnesses, + Aiur.AIR.CircuitTraces.emitNativeWitnesses program traces = some witnesses ∧ + ∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.Satisfied ∧ Aiur.AIR.CircuitWitness.NativeBounds program witness +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitTraces.graph_extract +∀ {circuits : List Aiur.Bytecode.Circuit} (traces : Aiur.AIR.CircuitTraces circuits) {logBlowup : Nat} + {program : Aiur.Bytecode.Toplevel} {keys : List Aiur.NativeAIR.KeyCodec.Circuit}, + List.mapM (Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program) circuits = some keys → + traces.GraphSatisfied keys → + ∃ witnesses, + Aiur.AIR.CircuitTraces.emitNativeWitnesses program traces = some witnesses ∧ + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.Satisfied ∧ Aiur.AIR.CircuitWitness.NativeBounds program witness) ∧ + traces.graphLookups keys = + some (List.map (fun witness => Aiur.NativeAIR.emissionLookupRow witness.emission) witnesses) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.component_interpreted_row +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)} + {emissions : List Aiur.AIR.CircuitEmission}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ {program : Aiur.Bytecode.Toplevel}, + program.validCallComponents = true → + ∀ (witness : Aiur.AIR.CircuitWitness), + Aiur.AIR.CircuitWitness.ComponentEmitted program witness → + witness.Satisfied → + Aiur.Bytecode.Circuit.validateRowCounts program witness.circuit = true → + Aiur.AIR.CircuitWitness.Shapes program witness → + witness.Constrained → + witness.QueryRanges → + witness.emission ∈ emissions → + Aiur.AIR.circuitQueryPool emissions ⊆ queries → + ∃ row, + Aiur.AIR.FunctionRow.ComponentValid program (Aiur.AIR.memoryFacts tables.memory) row ∧ + Aiur.AIR.FunctionRow.Provides width witness.emission row ∧ + Aiur.AIR.FunctionRow.ComponentQueriesIn program queries row +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.component_provider_row +∀ {program : Aiur.Bytecode.Toplevel} (witness : Aiur.AIR.CircuitWitness), + Aiur.AIR.CircuitWitness.ComponentEmitted program witness → + witness.Satisfied → + Aiur.Bytecode.Circuit.validateRowCounts program witness.circuit = true → + Aiur.AIR.CircuitWitness.Shapes program witness → + ∀ (width : Nat), ∃ row, Aiur.AIR.FunctionRow.Provides width witness.emission row +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.native_constrained +∀ {program : Aiur.Bytecode.Toplevel}, + Aiur.Bytecode.CircuitsConstrained program.functions program.circuits → + ∀ (witness : Aiur.AIR.CircuitWitness), + witness.circuit ∈ program.circuits → Aiur.AIR.CircuitWitness.NativeEmitted program witness → witness.Constrained +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.CircuitWitness.native_shapes +∀ {program : Aiur.Bytecode.Toplevel}, + program.validateLookupShapes = true → + Aiur.Bytecode.CircuitsConstrained program.functions program.circuits → + ∀ (witness : Aiur.AIR.CircuitWitness), + witness.circuit ∈ program.circuits → + Aiur.AIR.CircuitWitness.NativeEmitted program witness → Aiur.AIR.CircuitWitness.Shapes program witness +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.FunctionRow.ComponentValid.active_of_nonzero +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {row : Aiur.AIR.FunctionRow}, + Aiur.AIR.FunctionRow.ComponentValid program memory row → row.multiplicity ≠ 0 → row.selector = 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.ComponentValid.call_order +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {rows : List Aiur.AIR.FunctionRow} + {row : Aiur.AIR.FunctionRow}, + Aiur.AIR.FunctionRow.ComponentValid program memory row → + row ∈ rows → + row.selector = 1 → + ∀ (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance (Aiur.AIR.componentFunctionByteQueries program rows) + (Aiur.AIR.byteRangeProviders weights) → + (Aiur.AIR.componentFunctionByteQueries program rows).length < Aiur.gSize.toNat → + ∀ {edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)}, + edge ∈ row.calls → + (program.componentFor row.request.function).order = (program.componentFor edge.fst.function).order → + edge.fst.rank.n < Aiur.AIR.callRankBound → row.request.rank.n < edge.fst.rank.n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.ComponentValid.global_call_order +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {row : Aiur.AIR.FunctionRow}, + Aiur.AIR.FunctionRow.ComponentValid program memory row → + row ∈ tables.functions → + row.selector = 1 → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.componentFunctionByteQueries program tables.functions) ⊆ queries → + ∀ {edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)}, + edge ∈ row.calls → + (program.componentFor row.request.function).order = (program.componentFor edge.fst.function).order → + edge.fst.rank.n < Aiur.AIR.callRankBound → row.request.rank.n < edge.fst.rank.n +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.ComponentValid.global_rank_bounded +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {row : Aiur.AIR.FunctionRow}, + Aiur.AIR.FunctionRow.ComponentValid program memory row → + row ∈ tables.functions → + row.selector = 1 → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.componentFunctionByteQueries program tables.functions) ⊆ queries → + row.request.rank.n < Aiur.AIR.callRankBound +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.ComponentValid.rank_bounded +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {rows : List Aiur.AIR.FunctionRow} + {row : Aiur.AIR.FunctionRow}, + Aiur.AIR.FunctionRow.ComponentValid program memory row → + row ∈ rows → + row.selector = 1 → + ∀ (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance (Aiur.AIR.componentFunctionByteQueries program rows) + (Aiur.AIR.byteRangeProviders weights) → + (Aiur.AIR.componentFunctionByteQueries program rows).length < Aiur.gSize.toNat → + row.request.rank.n < Aiur.AIR.callRankBound +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.inactive_componentQueried +∀ (program : Aiur.Bytecode.Toplevel) (queries : List (List Aiur.G)), + Aiur.AIR.FunctionRow.ComponentQueriesIn program queries Aiur.AIR.FunctionRow.inactive +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.FunctionRow.inactive_componentValid +∀ (program : Aiur.Bytecode.Toplevel) (memory : Aiur.Bytecode.AIR.Memory), + Aiur.AIR.FunctionRow.ComponentValid program memory Aiur.AIR.FunctionRow.inactive +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.component_function_provider +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory}, + (∀ (row : Aiur.AIR.FunctionRow), + row ∈ tables.functions → Aiur.AIR.FunctionRow.ComponentValid program memory row) → + program.functions.size < Aiur.gSize.toNat → + ∀ {request : Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Call.LookupShape program request → + Aiur.AIR.functionMessage request ∈ queries → + ∃ row, row ∈ tables.functions ∧ row.request = request ∧ row.selector = 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.component_roots_execute +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call}, + program.validCallComponents = true → + program.validateLookupShapes = true → + (∀ (row : Aiur.AIR.FunctionRow), + row ∈ tables.functions → Aiur.AIR.FunctionRow.ComponentValid program memory row) → + List.map Aiur.AIR.functionMessage (Aiur.AIR.functionQueries roots tables.functions) ⊆ queries → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.componentFunctionByteQueries program tables.functions) ⊆ + queries → + ∀ {request : Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Call.LookupShape program request → + request ∈ roots → Aiur.Bytecode.AIR.Execution program memory request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.GlobalLookups.component_rows_execute +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + ∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call}, + program.validCallComponents = true → + program.validateLookupShapes = true → + (∀ (row : Aiur.AIR.FunctionRow), + row ∈ tables.functions → Aiur.AIR.FunctionRow.ComponentValid program memory row) → + List.map Aiur.AIR.functionMessage (Aiur.AIR.functionQueries roots tables.functions) ⊆ queries → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.componentFunctionByteQueries program tables.functions) ⊆ + queries → + ∀ {row : Aiur.AIR.FunctionRow}, + row ∈ tables.functions → + row.selector = 1 → + Aiur.Bytecode.AIR.Call.LookupShape program row.request → + Aiur.Bytecode.AIR.Execution program memory row.request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemberEmission.FromComponent.querySlots +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} + {member : Aiur.AIR.MemberEmission}, + Aiur.AIR.MemberEmission.FromComponent row rank base program member → + ∀ (rankBytes : Fin 6 → Aiur.G), + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row member) member.function.body → + (∀ (equation : Aiur.G), equation ∈ member.body.equations → equation = 0) → + Aiur.AIR.QuerySlots (Aiur.AIR.MemberEmission.entry row member) 1 member.body.lookup + (Aiur.AIR.MemberEmission.componentQueries row rankBytes program member) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.graph_providers +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths) {logBlowup : Nat} + {keys : List Aiur.NativeAIR.KeyCodec.Circuit}, + List.mapM (Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup) widths = some keys → + ∃ rows, traces.graphLookups keys = some rows ∧ Aiur.NativeAIR.graphTableProviders rows = traces.providers +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.MemoryTraces.graph_satisfied +∀ {widths : List Nat} (traces : Aiur.AIR.MemoryTraces widths) {logBlowup : Nat} + {keys : List Aiur.NativeAIR.KeyCodec.Circuit}, + List.mapM (Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup) widths = some keys → + traces.GraphSatisfied keys → traces.Satisfied +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.SystemTraces.graph_extract +∀ {program : Aiur.Bytecode.Toplevel} (traces : Aiur.AIR.SystemTraces program) {logBlowup : Nat} + {keys : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some keys → + traces.GraphSatisfied keys → + ∃ witnesses data, + Aiur.AIR.CircuitTraces.emitNativeWitnesses program traces.functions = some witnesses ∧ + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.Satisfied ∧ Aiur.AIR.CircuitWitness.NativeBounds program witness) ∧ + traces.memories.Satisfied ∧ + traces.graphLookupData keys = some data ∧ + data.queries = Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) ∧ + data.providers = traces.providers (List.map (fun x => x.emission) witnesses) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.circuitEmission_boolean_of_members +∀ {row : Nat → Aiur.G} {circuit : Aiur.Bytecode.Circuit} {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.booleanConstraint (Aiur.AIR.MemberEmission.entry row member) = 0) → + members.length = circuit.members.size → + (∀ (equation : Aiur.G), equation ∈ (Aiur.AIR.circuitEmission row circuit members).equations → equation = 0) → + Aiur.AIR.booleanConstraint (Aiur.AIR.circuitEmission row circuit members).selector = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentByteQueries_member +∀ {program : Aiur.Bytecode.Toplevel} {rows : List Aiur.AIR.FunctionRow} {row : Aiur.AIR.FunctionRow}, + row ∈ rows → + row.selector = 1 → + Aiur.AIR.FunctionRow.componentByteQueries program row ⊆ Aiur.AIR.componentFunctionByteQueries program rows +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_boolean +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + Aiur.AIR.booleanConstraint (Aiur.AIR.componentCircuitEmission row program circuit members).selector = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_gateCount +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + circuit.members.size < Aiur.gSize.toNat → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + (List.map Aiur.AIR.gateCount (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) members)).sum = + Aiur.AIR.gateCount (Aiur.AIR.componentCircuitEmission row program circuit members).selector +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_member_boolean +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.booleanConstraint (Aiur.AIR.MemberEmission.entry row member) = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_member_queried +∀ {row : Nat → Aiur.G} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission} {queries : List (List Aiur.G)}, + (Aiur.AIR.componentCircuitEmission row program circuit members).QueriesIn queries → + ∀ {member : Aiur.AIR.MemberEmission}, member ∈ members → member.body.QueriesIn queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_member_rank +∀ {row : Nat → Aiur.G} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission} {member : Aiur.AIR.MemberEmission}, + member ∈ members → + (if (program.componentFor member.functionIndex).ranked = true then + Aiur.AIR.packRank (Aiur.AIR.componentCircuitEmission row program circuit members).rankBytes + else 0) = + if (program.componentFor member.functionIndex).ranked = true then + Aiur.AIR.packRank (Aiur.AIR.circuitRankBytes row circuit.layout) + else 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_queries_count +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + circuit.members.size < Aiur.gSize.toNat → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + ∀ (slot : Nat), + Aiur.AIR.queryCount (Aiur.AIR.componentCircuitEmission row program circuit members).queries slot = + Aiur.AIR.queryCount + (List.flatMap + (fun member => + Aiur.AIR.MemberEmission.componentQueries row (Aiur.AIR.circuitRankBytes row circuit.layout) program + member) + members) + slot +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_querySlots +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + circuit.members.size < Aiur.gSize.toNat → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row member) member.function.body) → + 0 < circuit.layout.lookups → + (∀ (part : Aiur.AIR.QueryPart), + part ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).queries → + 0 < part.slot ∧ part.slot < circuit.layout.lookups) → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + Aiur.AIR.QuerySlots (Aiur.AIR.componentCircuitEmission row program circuit members).selector 1 + circuit.layout.lookups (Aiur.AIR.componentCircuitEmission row program circuit members).queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_rank_active +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + circuit.members.size < Aiur.gSize.toNat → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + ∀ {member : Aiur.AIR.MemberEmission}, + member ∈ members → + (program.componentFor member.functionIndex).ranked = true → + Aiur.AIR.MemberEmission.entry row member = 1 → + Aiur.AIR.selectorSum + (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) + (Aiur.AIR.componentMembers program members)) = + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_rank_boolean +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + circuit.members.size < Aiur.gSize.toNat → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + Aiur.AIR.booleanConstraint + (Aiur.AIR.selectorSum + (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) (Aiur.AIR.componentMembers program members))) = + 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_rank_count +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + circuit.members.size < Aiur.gSize.toNat → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + (List.map Aiur.AIR.gateCount + (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) + (Aiur.AIR.componentMembers program members))).sum = + Aiur.AIR.gateCount + (Aiur.AIR.selectorSum + (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) (Aiur.AIR.componentMembers program members))) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_rank_queried +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission} {queries : List (List Aiur.G)}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + members.length = circuit.members.size → + circuit.members.size < Aiur.gSize.toNat → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + (Aiur.AIR.componentCircuitEmission row program circuit members).QueriesIn queries → + ∀ {member : Aiur.AIR.MemberEmission}, + member ∈ members → + (program.componentFor member.functionIndex).ranked = true → + Aiur.AIR.MemberEmission.entry row member = 1 → + List.map Aiur.AIR.rangeMessage + (Aiur.AIR.rankByteQueries + (Aiur.AIR.componentCircuitEmission row program circuit members).rankBytes) ⊆ + queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_return_count +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.Bytecode.Block.lookupShapes program none member.function.body = true) → + members.length < Aiur.gSize.toNat → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) + member.function.body).returns.length < + Aiur.gSize.toNat) → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + (Aiur.AIR.componentCircuitEmission row program circuit members).selector = 1 → + List.count 1 (List.map Prod.fst (Aiur.AIR.componentCircuitEmission row program circuit members).returns) = + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_return_message +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.Bytecode.Block.lookupShapes program none member.function.body = true) → + members.length < Aiur.gSize.toNat → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) + member.function.body).returns.length < + Aiur.gSize.toNat) → + (∀ (equation : Aiur.G), + equation ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).equations → equation = 0) → + (Aiur.AIR.componentCircuitEmission row program circuit members).selector = 1 → + ∀ (width : Nat), + ((Aiur.AIR.componentCircuitEmission row program circuit members).branchless = true → + (Aiur.AIR.componentCircuitEmission row program circuit members).returns.length ≤ 1) → + ∀ {request : Aiur.Bytecode.AIR.Call}, + (1, request) ∈ (Aiur.AIR.componentCircuitEmission row program circuit members).returns → + Aiur.AIR.padMessage width + ((Aiur.AIR.componentCircuitEmission row program circuit members).lookup 0).snd = + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage request) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitEmission_single_writer +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base : Nat} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {members : List Aiur.AIR.MemberEmission}, + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → Aiur.AIR.MemberEmission.FromComponent row rank base program member) → + (Aiur.AIR.componentCircuitEmission row program circuit members).branchless = true → + ∀ (slot : Nat), + (Aiur.AIR.querySlotParts (Aiur.AIR.componentCircuitEmission row program circuit members).queries slot).length ≤ + 1 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitWitnesses_decoded_widths +∀ {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness), + program.validateRowCounts = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.ComponentEmitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.QueryRanges) → + ∀ (width : Nat), + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + ∀ (query : List Aiur.G), + query ∈ Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) → query.length ≤ width +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitWitnesses_execute +∀ (tables : Aiur.AIR.AuxiliaryTables) {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness) + {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.PaddedLookupBalance width queries (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + queries.length < Aiur.gSize.toNat → + (∀ (query : List Aiur.G), query ∈ queries → query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + program.validCallComponents = true → + program.validateRowCounts = true → + program.validateLookupShapes = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.ComponentEmitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Constrained) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.QueryRanges) → + Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) ⊆ queries → + ∀ {request : Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Call.LookupShape program request → + Aiur.AIR.functionMessage request ∈ queries → + Aiur.Bytecode.AIR.Execution program (Aiur.AIR.memoryFacts tables.memory) request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitWitnesses_interpret +∀ (tables : Aiur.AIR.AuxiliaryTables) {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness) + {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.PaddedLookupBalance width queries (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + queries.length < Aiur.gSize.toNat → + (∀ (query : List Aiur.G), query ∈ queries → query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + program.validCallComponents = true → + program.validateRowCounts = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.ComponentEmitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Constrained) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.QueryRanges) → + Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) ⊆ queries → + ∃ functions, + List.Forall₂ (Aiur.AIR.FunctionRow.Provides width) + (List.map (fun x => x.emission) witnesses) functions ∧ + Aiur.AIR.GlobalLookups (tables.withFunctions functions) width queries ∧ + (∀ (row : Aiur.AIR.FunctionRow), + row ∈ functions → + Aiur.AIR.FunctionRow.ComponentValid program + (Aiur.AIR.memoryFacts tables.memory) row) ∧ + ∀ (row : Aiur.AIR.FunctionRow), + row ∈ functions → Aiur.AIR.FunctionRow.ComponentQueriesIn program queries row +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentCircuitWitnesses_queries_reflect +∀ {program : Aiur.Bytecode.Toplevel} (witnesses : List Aiur.AIR.CircuitWitness), + program.validateRowCounts = true → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.circuit ∈ program.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.ComponentEmitted program witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.QueryRanges) → + ∀ (width : Nat), + List.map (Aiur.AIR.padMessage width) + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) = + List.map (Aiur.AIR.padMessage width) + (Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentFunctionByteQueries_in_pool +∀ {program : Aiur.Bytecode.Toplevel} {queries : List (List Aiur.G)} {rows : List Aiur.AIR.FunctionRow}, + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.ComponentQueriesIn program queries row) → + List.map Aiur.AIR.rangeMessage (Aiur.AIR.componentFunctionByteQueries program rows) ⊆ queries +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.componentFunctionQueries_in_pool +∀ {program : Aiur.Bytecode.Toplevel} {queries : List (List Aiur.G)} {roots : List Aiur.Bytecode.AIR.Call} + {rows : List Aiur.AIR.FunctionRow}, + List.map Aiur.AIR.functionMessage roots ⊆ queries → + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.ComponentQueriesIn program queries row) → + List.map Aiur.AIR.functionMessage (Aiur.AIR.functionQueries roots rows) ⊆ queries +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.componentQueries_provider +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call} + {rows : List Aiur.AIR.FunctionRow}, + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.ComponentValid program memory row) → + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionQueries roots rows) (Aiur.AIR.functionProviders rows) → + (Aiur.AIR.functionQueries roots rows).length < Aiur.gSize.toNat → + ∀ {request : Aiur.Bytecode.AIR.Call}, + request ∈ Aiur.AIR.functionQueries roots rows → ∃ row, row ∈ rows ∧ row.request = request ∧ row.selector = 1 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.componentRoots_execute +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call} + {rows : List Aiur.AIR.FunctionRow}, + program.validCallComponents = true → + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.ComponentValid program memory row) → + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionQueries roots rows) (Aiur.AIR.functionProviders rows) → + (Aiur.AIR.functionQueries roots rows).length < Aiur.gSize.toNat → + ∀ (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance (Aiur.AIR.componentFunctionByteQueries program rows) + (Aiur.AIR.byteRangeProviders weights) → + (Aiur.AIR.componentFunctionByteQueries program rows).length < Aiur.gSize.toNat → + ∀ {request : Aiur.Bytecode.AIR.Call}, + request ∈ roots → Aiur.Bytecode.AIR.Execution program memory request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.componentRows_execute +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {roots : List Aiur.Bytecode.AIR.Call} + {rows : List Aiur.AIR.FunctionRow}, + program.validCallComponents = true → + (∀ (row : Aiur.AIR.FunctionRow), row ∈ rows → Aiur.AIR.FunctionRow.ComponentValid program memory row) → + Aiur.AIR.ExactLookupBalance (Aiur.AIR.functionQueries roots rows) (Aiur.AIR.functionProviders rows) → + (Aiur.AIR.functionQueries roots rows).length < Aiur.gSize.toNat → + ∀ (weights : Fin 65536 → Aiur.G), + Aiur.AIR.ExactLookupBalance (Aiur.AIR.componentFunctionByteQueries program rows) + (Aiur.AIR.byteRangeProviders weights) → + (Aiur.AIR.componentFunctionByteQueries program rows).length < Aiur.gSize.toNat → + ∀ {row : Aiur.AIR.FunctionRow}, + row ∈ rows → row.selector = 1 → Aiur.Bytecode.AIR.Execution program memory row.request +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitCallRow_calls +∀ (row : Nat → Aiur.G) (rank selector : Aiur.G) (function : Aiur.Bytecode.FunIdx) (inputs : Array Aiur.G) (size : Nat) + (callRanks : Array Aiur.Bytecode.CallRank), + have emission := + Aiur.AIR.emitCallRow row rank function inputs size (callRanks[function]?.getD Aiur.Bytecode.CallRank.ordered); + Aiur.AIR.CallsEmitted rank selector emission.equations emission.queries emission.calls callRanks +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.emitComponentMember_present +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} + {functionIndex : Aiur.Bytecode.FunIdx} {member : Aiur.AIR.MemberEmission}, + Aiur.AIR.emitComponentMember row rank base selectorBase program functionIndex = some member → + member.functionIndex = functionIndex ∧ + program.functions[functionIndex]? = some member.function ∧ + member.selectorBase = selectorBase ∧ + Aiur.Bytecode.Function.emitRow row (Aiur.AIR.MemberEmission.selector row member) functionIndex + (if (program.componentFor functionIndex).ranked = true then rank else 0) + (Aiur.AIR.rowAdvice row 0 member.function.layout.inputSize) + (Aiur.AIR.componentColumn (program.componentFor functionIndex).ranked base) + (Aiur.AIR.componentLookup (program.componentFor functionIndex).ranked) member.function + (program.callRanksFor functionIndex) = + some member.body +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitComponentMember_spec +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} + {functionIndex : Aiur.Bytecode.FunIdx} {member : Aiur.AIR.MemberEmission}, + Aiur.AIR.emitComponentMember row rank base selectorBase program functionIndex = some member → + member.functionIndex = functionIndex ∧ Aiur.AIR.MemberEmission.FromComponent row rank base program member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitComponentMembers_present +∀ {row : Nat → Aiur.G} {rank : Aiur.G} {base selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} + {indices : List Aiur.Bytecode.FunIdx} {members : List Aiur.AIR.MemberEmission}, + Aiur.AIR.emitComponentMembers row rank base selectorBase program indices = some members → + List.map Aiur.AIR.MemberEmission.functionIndex members = indices ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → + Aiur.AIR.emitComponentMember row rank base member.selectorBase program member.functionIndex = some member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitNativeCircuitWitness_spec +∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} {values : Nat → Aiur.G} + {witness : Aiur.AIR.CircuitWitness}, + Aiur.AIR.emitNativeCircuitWitness program circuit values = some witness → + witness.circuit = circuit ∧ + witness.values = Aiur.AIR.boundedTraceRow circuit.layout.width values ∧ + Aiur.AIR.CircuitWitness.NativeEmitted program witness ∧ witness.emission.lookupCount = circuit.layout.lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.emitNativeCircuitWitnesses_spec +∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} {values : List (Nat → Aiur.G)} + {witnesses : List Aiur.AIR.CircuitWitness}, + List.mapM (Aiur.AIR.emitNativeCircuitWitness program circuit) values = some witnesses → + witnesses.length = values.length ∧ + ∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → + witness.circuit = circuit ∧ + Aiur.AIR.CircuitWitness.NativeEmitted program witness ∧ + witness.emission.lookupCount = circuit.layout.lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.flatMap_if_filter +∀ {α β : Type} (items : List α) (chosen : α → Bool) (parts : α → List β), + List.flatMap (fun item => if chosen item = true then parts item else []) items = + List.flatMap parts (List.filter chosen items) +AXIOMS [propext] +ROOT Aiur.AIR.forall₂_weaken +∀ {α β : Type} {left : List α} {right : List β} {first second : α → β → Prop}, + List.Forall₂ first left right → (∀ (a : α) (b : β), first a b → second a b) → List.Forall₂ second left right +AXIOMS [] +ROOT Aiur.AIR.list_mapM_cons_parts +∀ {α : Type u_1} {β : Type u_2} {read : α → Option β} {input : α} {inputs : List α} {outputs : List β}, + List.mapM read (input :: inputs) = some outputs → + ∃ first rest, read input = some first ∧ List.mapM read inputs = some rest ∧ outputs = first :: rest +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.queryCount_flatMap_append +∀ {α : Type} (items : List α) (left right : α → List Aiur.AIR.QueryPart) (slot : Nat), + Aiur.AIR.queryCount (List.flatMap (fun item => left item ++ right item) items) slot = + Aiur.AIR.queryCount (List.flatMap left items) slot + Aiur.AIR.queryCount (List.flatMap right items) slot +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.queryCount_flatMap_indexed +∀ {α : Type} (items : List α) (gate : α → Aiur.G) (messages : List (List Aiur.G)) (start slot : Nat), + Aiur.AIR.queryCount (List.flatMap (fun item => Aiur.AIR.queryParts start (gate item) messages) items) slot = + (List.map Aiur.AIR.gateCount (List.map gate items)).sum * + Aiur.AIR.queryCount (Aiur.AIR.queryParts start 1 messages) slot +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.queryCount_flatMap_le_sum +∀ {α : Type} (items : List α) (parts : α → List Aiur.AIR.QueryPart) (gate : α → Aiur.G) (slot : Nat), + (∀ (item : α), item ∈ items → Aiur.AIR.queryCount (parts item) slot ≤ Aiur.AIR.gateCount (gate item)) → + Aiur.AIR.queryCount (List.flatMap parts items) slot ≤ (List.map Aiur.AIR.gateCount (List.map gate items)).sum +AXIOMS [propext] +ROOT Aiur.AIR.queryCount_queryParts +∀ (gate : Aiur.G) (messages : List (List Aiur.G)) (start slot : Nat), + Aiur.AIR.queryCount (Aiur.AIR.queryParts start gate messages) slot = + Aiur.AIR.gateCount gate * Aiur.AIR.queryCount (Aiur.AIR.queryParts start 1 messages) slot +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.queryCount_singleton +∀ (query : Aiur.AIR.QueryPart) (slot : Nat), + Aiur.AIR.queryCount [query] slot = if query.slot = slot then Aiur.AIR.gateCount query.selector else 0 +AXIOMS [propext, Quot.sound] +ROOT Aiur.AIR.queryParts_boolean +∀ (gate : Aiur.G) (messages : List (List Aiur.G)) (start : Nat), + Aiur.AIR.booleanConstraint gate = 0 → + ∀ (query : Aiur.AIR.QueryPart), + query ∈ Aiur.AIR.queryParts start gate messages → Aiur.AIR.booleanConstraint query.selector = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.AIR.selectorSum_boolean_of_count +∀ {gates : List Aiur.G}, + (∀ (gate : Aiur.G), gate ∈ gates → Aiur.AIR.booleanConstraint gate = 0) → + List.count 1 gates ≤ 1 → Aiur.AIR.booleanConstraint (Aiur.AIR.selectorSum gates) = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.encoded_component_circuit_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + backend.compiled.bytecode.validCallComponents = true → + ∀ (tables : Aiur.AIR.AuxiliaryTables) (witnesses : List Aiur.AIR.CircuitWitness) (width : Nat) + (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)).length + 1 < Aiur.gSize.toNat → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.circuit ∈ backend.compiled.bytecode.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → + Aiur.AIR.CircuitWitness.ComponentEmitted backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Constrained) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.QueryRanges) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode + (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, + rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.Backend.public_component_circuit_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.Backend selection), + backend.compiled.bytecode.validCallComponents = true → + ∀ (tables : Aiur.AIR.AuxiliaryTables) (witnesses : List Aiur.AIR.CircuitWitness) (width : Nat) + (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses)).length + 1 < Aiur.gSize.toNat → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.circuitQueryPool (List.map (fun x => x.emission) witnesses) → query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.circuit ∈ backend.compiled.bytecode.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → + Aiur.AIR.CircuitWitness.ComponentEmitted backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.Shapes backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Constrained) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.QueryRanges) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode + (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, + rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.checked_graph_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof backend.keyData bytes) + (traces : Aiur.AIR.SystemTraces backend.compiled.bytecode), + traces.bitmap = checked.data.active → + traces.degrees = List.map UInt8.toNat checked.data.logDegrees → + ∀ (data : Aiur.AIR.GraphLookupData), + traces.graphLookupData backend.keyData.circuits = some data → + traces.GraphSatisfied backend.keyData.circuits → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: data.queries) + data.providers → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), query ∈ data.queries → query.length ≤ width) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts traces.memories.rows) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } ∧ + ∀ (size : Nat) (pointer : Aiur.G) (left right : Array Aiur.G), + Aiur.AIR.memoryFacts traces.memories.rows size pointer left → + Aiur.AIR.memoryFacts traces.memories.rows size pointer right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.checked_trace_budget +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + {bytes : ByteArray} (checked : Aiur.BoundVerifier.CheckedProof backend.keyData bytes) + (traces : Aiur.AIR.SystemTraces backend.compiled.bytecode), + traces.bitmap = checked.data.active → + traces.degrees = List.map UInt8.toNat checked.data.logDegrees → traces.queryBound = some checked.bound +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.components_checked +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), + backend.compiled.bytecode.callComponents.isEmpty = true ∨ backend.compiled.bytecode.validCallComponents = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.encoded_native_circuit_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + (tables : Aiur.AIR.AuxiliaryTables) (witnesses : List Aiur.AIR.CircuitWitness) (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)).length + 1 < Aiur.gSize.toNat → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.circuit ∈ backend.compiled.bytecode.circuits) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.NativeEmitted backend.compiled.bytecode witness) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → + Aiur.AIR.CircuitWitness.NativeBounds backend.compiled.bytecode witness) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.function_components_checked +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) {index : Nat} + {source : Aiur.Bytecode.Circuit} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + backend.compiled.bytecode.circuits[index]? = some source → + backend.keyData.circuits[index]? = some artifact → + backend.compiled.bytecode.callComponents.isEmpty = true ∨ backend.compiled.bytecode.validCallComponents = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.function_witness +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) {index : Nat} + {source : Aiur.Bytecode.Circuit} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + backend.compiled.bytecode.circuits[index]? = some source → + backend.keyData.circuits[index]? = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ witness buffer, + witness.circuit = source ∧ + (witness.values = fun column => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[column]?.getD 0) ∧ + Aiur.AIR.CircuitWitness.NativeEmitted backend.compiled.bytecode witness ∧ + Aiur.AIR.CircuitWitness.NativeBounds backend.compiled.bytecode witness ∧ + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + witness.Satisfied) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some (List.ofFn fun slot => witness.emission.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.graph_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + (traces : Aiur.AIR.SystemTraces backend.compiled.bytecode) (data : Aiur.AIR.GraphLookupData), + traces.graphLookupData backend.keyData.circuits = some data → + traces.GraphSatisfied backend.keyData.circuits → + ∀ {result : Nat}, + traces.queryBound = some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: data.queries) data.providers → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), query ∈ data.queries → query.length ≤ width) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts traces.memories.rows) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } ∧ + ∀ (size : Nat) (pointer : Aiur.G) (left right : Array Aiur.G), + Aiur.AIR.memoryFacts traces.memories.rows size pointer left → + Aiur.AIR.memoryFacts traces.memories.rows size pointer right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.native_column_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + (traces : Aiur.AIR.SystemTraces backend.compiled.bytecode) {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitNativeWitnesses backend.compiled.bytecode traces.functions = some witnesses → + ∀ {result : Nat}, + traces.queryBound = some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (traces.providers (List.map (fun x => x.emission) witnesses)) → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → Aiur.AIR.CircuitWitness.NativeBounds backend.compiled.bytecode witness) → + traces.memories.Satisfied → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode + (Aiur.AIR.memoryFacts traces.memories.rows) + { function := selection.function, inputs := input, outputs := selection.success, + rank := 0 } ∧ + ∀ (size : Nat) (pointer : Aiur.G) (left right : Array Aiur.G), + Aiur.AIR.memoryFacts traces.memories.rows size pointer left → + Aiur.AIR.memoryFacts traces.memories.rows size pointer right → left = right +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.native_trace_execution +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) + (tables : Aiur.AIR.AuxiliaryTables) (traces : Aiur.AIR.CircuitTraces backend.compiled.bytecode.circuits.toList) + {witnesses : List Aiur.AIR.CircuitWitness}, + Aiur.AIR.CircuitTraces.emitNativeWitnesses backend.compiled.bytecode traces = some witnesses → + ∀ {otherSlots : List Nat} {otherActive : List Bool} {otherDegrees : List Nat} {result : Nat}, + Aiur.lookupQueryBound + (List.map (fun x => x.layout.lookups) backend.compiled.bytecode.circuits.toList ++ otherSlots) + (traces.bitmap ++ otherActive) (traces.degrees ++ otherDegrees) = + some result → + ∀ (width : Nat) (input : Array Aiur.G), + input.size = selection.inputSize → + Aiur.AIR.PaddedLookupBalance width + ((Aiur.buildClaim selection.function input selection.success).toList :: + Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses)) + (tables.circuitProviders (List.map (fun x => x.emission) witnesses)) → + (Aiur.buildClaim selection.function input selection.success).size + 1 ≤ width → + (∀ (query : List Aiur.G), + query ∈ Aiur.AIR.encodedCircuitQueryPool (List.map (fun x => x.emission) witnesses) → + query.length ≤ width) → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + (∀ (witness : Aiur.AIR.CircuitWitness), witness ∈ witnesses → witness.Satisfied) → + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → + Aiur.AIR.CircuitWitness.NativeBounds backend.compiled.bytecode witness) → + Aiur.Bytecode.AIR.Execution backend.compiled.bytecode (Aiur.AIR.memoryFacts tables.memory) + { function := selection.function, inputs := input, outputs := selection.success, rank := 0 } +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.BoundVerifier.CompiledBackend.trace_metadata +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), + List.map (fun x => x.graph.lookups.length) backend.keyData.circuits = + Aiur.AIR.systemLookupSlots backend.compiled.bytecode ∧ + List.map (fun x => x.preprocessedHeight) backend.keyData.circuits = + Aiur.AIR.systemFixedHeights backend.compiled.bytecode +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunBlock.calls_collected +∀ {memory : Aiur.Bytecode.AIR.Memory} {block : Aiur.Bytecode.Block} {values : Array Aiur.G} + {outcome : Aiur.Bytecode.AIR.Outcome} {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunBlock memory block values outcome calls → + ∀ (child : Aiur.Bytecode.AIR.Call), child ∈ calls → child.function ∈ block.collectConstrainedCallees.toList +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunFunction.calls_components +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {request : Aiur.Bytecode.AIR.Call} + {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunFunction program memory request calls → + program.validCallComponents = true → + ∀ {function : Aiur.Bytecode.Function}, + program.functions[request.function]? = some function → + function.constrained = true → + ∀ (child : Aiur.Bytecode.AIR.Call), child ∈ calls → program.ComponentEdge request.function child.function +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.RunOps.calls_collected +∀ {memory : Aiur.Bytecode.AIR.Memory} {ops : List Aiur.Bytecode.Op} {values outputs : Array Aiur.G} + {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.RunOps memory ops values outputs calls → + ∀ (child : Aiur.Bytecode.AIR.Call), + child ∈ calls → child.function ∈ List.flatMap Aiur.Bytecode.Op.constrainedCalls ops +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.AIR.SelectArm.calls_collected +∀ {scrutinee : Aiur.G} {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} + {arm : Aiur.Bytecode.Block}, + Aiur.Bytecode.AIR.SelectArm scrutinee branches fallback arm → + arm.collectConstrainedCallees.toList ⊆ Aiur.Bytecode.branchCalls branches fallback +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.AIR.Step.calls_collected +∀ {memory : Aiur.Bytecode.AIR.Memory} {op : Aiur.Bytecode.Op} {values outputs : Array Aiur.G} + {calls : List Aiur.Bytecode.AIR.Call}, + Aiur.Bytecode.AIR.Step memory op values outputs calls → + ∀ (child : Aiur.Bytecode.AIR.Call), child ∈ calls → child.function ∈ op.constrainedCalls +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.Block.collect_calls +∀ (block : Aiur.Bytecode.Block), + block.collectConstrainedCallees.toList = + List.flatMap Aiur.Bytecode.Op.constrainedCalls block.ops.toList ++ block.ctrl.collectConstrainedCallees.toList +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.CallComponent.permits_other +∀ {parent child : Aiur.Bytecode.CallComponent}, + parent.permits child = true → parent.order ≠ child.order → parent.order < child.order +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.CallComponent.permits_same +∀ {parent child : Aiur.Bytecode.CallComponent}, + parent.permits child = true → parent.order = child.order → parent.ranked = true ∧ child.ranked = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_active_member +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + circuit.members.size < Aiur.gSize.toNat → + emission.multiplicity ≠ 0 → + ∃ member, + member ∈ emission.members ∧ + Aiur.AIR.MemberEmission.entry row member = 1 ∧ + Aiur.AIR.MemberEmission.FromComponent row (Aiur.AIR.packRank emission.rankBytes) + (circuit.layout.inputSize + circuit.layout.selectors + 1) program member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_boolean +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + Aiur.AIR.booleanConstraint emission.selector = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_count_bounds +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + circuit.members.size < Aiur.gSize.toNat ∧ + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row part) part.function.body) ∧ + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row part) + part.function.body).returns.length < + Aiur.gSize.toNat) ∧ + (emission.branchless = true → emission.returns.length ≤ 1) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_provider +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → Aiur.Bytecode.Block.lookupShapes program none part.function.body = true) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.multiplicity ≠ 0 → + ∀ (width : Nat), + ∃ request, + (1, request) ∈ emission.returns ∧ + Aiur.AIR.padMessage width (emission.lookup 0).snd = + Aiur.AIR.padMessage width (Aiur.AIR.functionMessage request) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_queries_reflect +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + 0 < emission.lookupCount → + (∀ (part : Aiur.AIR.QueryPart), part ∈ emission.queries → 0 < part.slot ∧ part.slot < emission.lookupCount) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + ∀ (width : Nat), + List.map (Aiur.AIR.padMessage width) + (Aiur.AIR.encodedQueries emission.branchless emission.queries emission.lookupCount) = + List.map (Aiur.AIR.padMessage width) (Aiur.AIR.decodedQueries emission.queries emission.lookupCount) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_querySlots +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + circuit.members.size < Aiur.gSize.toNat → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ emission.members → + Aiur.Bytecode.Block.rowBounds (Aiur.AIR.MemberEmission.selector row member) member.function.body) → + 0 < emission.lookupCount → + (∀ (part : Aiur.AIR.QueryPart), part ∈ emission.queries → 0 < part.slot ∧ part.slot < emission.lookupCount) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + Aiur.AIR.QuerySlots emission.selector 1 emission.lookupCount emission.queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_spec +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + emission = Aiur.AIR.componentCircuitEmission row program circuit emission.members ∧ + List.map Aiur.AIR.MemberEmission.functionIndex emission.members = circuit.members.toList ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ emission.members → + Aiur.AIR.MemberEmission.FromComponent row (Aiur.AIR.packRank (Aiur.AIR.circuitRankBytes row circuit.layout)) + (circuit.layout.inputSize + circuit.layout.selectors + 1) program member +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitComponentRow_valid_in_pool +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {emissions : List Aiur.AIR.CircuitEmission} + {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel), + program.validCallComponents = true → + ∀ (circuit : Aiur.Bytecode.Circuit) {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some emission → + emission ∈ emissions → + Aiur.AIR.circuitQueryPool emissions ⊆ queries → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → + Aiur.Bytecode.Block.lookupShapes program none part.function.body = true) → + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ emission.members → part.function.constrained = true) → + 0 < emission.lookupCount → + (∀ (part : Aiur.AIR.QueryPart), + part ∈ emission.queries → 0 < part.slot ∧ part.slot < emission.lookupCount) → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.multiplicity ≠ 0 → + ∃ selected, + selected ∈ emission.members ∧ + ∃ interpreted, + Aiur.AIR.FunctionRow.ComponentValid program (Aiur.AIR.memoryFacts tables.memory) + interpreted ∧ + interpreted.request.function = selected.functionIndex ∧ + interpreted.request.inputs = + Aiur.AIR.rowValues + (Aiur.AIR.rowAdvice row 0 selected.function.layout.inputSize) ∧ + interpreted.request.rank = + program.componentRowRank selected.functionIndex emission.rankBytes ∧ + interpreted.rankBytes = emission.rankBytes ∧ + interpreted.selector = emission.selector ∧ + interpreted.multiplicity = emission.multiplicity ∧ + (1, interpreted.request) ∈ emission.returns ∧ + Aiur.AIR.padMessage width (emission.lookup 0).snd = + Aiur.AIR.padMessage width + (Aiur.AIR.functionMessage interpreted.request) ∧ + selected.body.CallsAt interpreted.calls ∧ + List.map Aiur.AIR.functionMessage interpreted.requests ⊆ + queries ∧ + List.map Aiur.AIR.rangeMessage + (Aiur.AIR.FunctionRow.componentByteQueries program + interpreted) ⊆ + queries +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitNativeRow_lookupCount +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitNativeRow row program circuit = some emission → + emission.lookupCount = circuit.layout.lookups +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.emitNativeRow_members +∀ (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) + {emission : Aiur.AIR.CircuitEmission}, + Aiur.Bytecode.Circuit.emitNativeRow row program circuit = some emission → + List.map Aiur.AIR.MemberEmission.functionIndex emission.members = circuit.members.toList ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ emission.members → program.functions[member.functionIndex]? = some member.function +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Circuit.validateRowCounts_members +∀ (program : Aiur.Bytecode.Toplevel) (circuit : Aiur.Bytecode.Circuit) (members : List Aiur.AIR.MemberEmission), + List.map Aiur.AIR.MemberEmission.functionIndex members = circuit.members.toList → + (∀ (member : Aiur.AIR.MemberEmission), + member ∈ members → program.functions[member.functionIndex]? = some member.function) → + Aiur.Bytecode.Circuit.validateRowCounts program circuit = true → + circuit.members.size < Aiur.gSize.toNat ∧ + (∀ (part : Aiur.AIR.MemberEmission), + part ∈ members → part.function.body.controlCounts.nodes < Aiur.gSize.toNat) ∧ + (List.map (fun part => part.function.body.controlCounts.leaves) members).sum ≤ circuit.layout.selectors +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Ctrl.collect_continue +∀ (index : Aiur.Bytecode.ValIdx) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block) (size aux lookups : Nat) (continuation : Aiur.Bytecode.Block), + (Aiur.Bytecode.Ctrl.matchContinue index branches fallback size aux lookups + continuation).collectConstrainedCallees.toList = + Aiur.Bytecode.branchCalls branches fallback ++ continuation.collectConstrainedCallees.toList +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Ctrl.collect_match +∀ (index : Aiur.Bytecode.ValIdx) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) + (fallback : Option Aiur.Bytecode.Block), + (Aiur.Bytecode.Ctrl.match index branches fallback).collectConstrainedCallees.toList = + Aiur.Bytecode.branchCalls branches fallback +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Function.emitRow_componentValid +∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, + Aiur.AIR.GlobalLookups tables width queries → + (∀ (size : Nat), Aiur.AIR.MemoryRowsValid size (tables.memory size)) → + (∀ (size : Nat), size ∈ tables.memoryWidths → size < Aiur.gSize.toNat) → + ∀ (program : Aiur.Bytecode.Toplevel), + program.validCallComponents = true → + ∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (functionIndex : Aiur.Bytecode.FunIdx) + (rankBytes : Fin 6 → Aiur.G) (values : Array Aiur.AIR.RowValue) (column lookup : Nat) + (function : Aiur.Bytecode.Function), + program.functions[functionIndex]? = some function → + function.constrained = true → + values.size = function.layout.inputSize → + Aiur.Bytecode.Block.lookupShapes program none function.body = true → + Aiur.Bytecode.Block.rowBounds selector function.body → + ∀ {emission : Aiur.AIR.BlockEmission}, + Aiur.Bytecode.Function.emitRow row selector functionIndex + (program.componentRowRank functionIndex rankBytes) values column lookup function + (program.callRanksFor functionIndex) = + some emission → + ∀ (multiplicity : Aiur.G), + multiplicity ≠ 0 → + Aiur.AIR.activityConstraint multiplicity + (Aiur.Bytecode.Block.selectorFlow selector function.body).entry = + 0 → + (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → + emission.QueriesIn queries → + ∃ interpreted, + Aiur.AIR.FunctionRow.ComponentValid program (Aiur.AIR.memoryFacts tables.memory) + interpreted ∧ + (1, interpreted.request) ∈ emission.returns ∧ + interpreted.request.function = functionIndex ∧ + interpreted.request.inputs = Aiur.AIR.rowValues values ∧ + interpreted.request.rank = + program.componentRowRank functionIndex rankBytes ∧ + interpreted.rankBytes = rankBytes ∧ + interpreted.selector = + (Aiur.Bytecode.Block.selectorFlow selector + function.body).entry ∧ + interpreted.multiplicity = multiplicity ∧ + emission.CallsAt interpreted.calls ∧ + Aiur.AIR.CallsEmitted + (program.componentRowRank functionIndex rankBytes) 1 + emission.equations queries interpreted.calls + (program.callRanksFor functionIndex) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Op.allocationFor_outputSize +∀ (op : Aiur.Bytecode.Op) (callRanks : Array Aiur.Bytecode.CallRank) (degrees : Array Nat), + (Aiur.Bytecode.Op.allocationFor callRanks degrees op).degrees.size = op.outputSize +AXIOMS [propext] +ROOT Aiur.Bytecode.Toplevel.ComponentEdge.cross +∀ {program : Aiur.Bytecode.Toplevel} {parent child : Aiur.Bytecode.FunIdx}, + program.ComponentEdge parent child → + ∀ {parentComponent childComponent : Aiur.Bytecode.CallComponent}, + program.callComponents[parent]? = some parentComponent → + program.callComponents[child]? = some childComponent → + parentComponent.order ≠ childComponent.order → + parentComponent.order < childComponent.order ∧ + (program.callRanksFor parent)[child]? = + some + (if childComponent.ranked = true then Aiur.Bytecode.CallRank.bound else Aiur.Bytecode.CallRank.zero) +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.ComponentEdge.ordered +∀ {program : Aiur.Bytecode.Toplevel} {parent child : Aiur.Bytecode.FunIdx}, + program.ComponentEdge parent child → + ∀ {parentComponent childComponent : Aiur.Bytecode.CallComponent}, + program.callComponents[parent]? = some parentComponent → + program.callComponents[child]? = some childComponent → + parentComponent.order = childComponent.order → + parentComponent.ranked = true ∧ + childComponent.ranked = true ∧ (program.callRanksFor parent)[child]? = some Aiur.Bytecode.CallRank.ordered +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.ComponentEdge.permits +∀ {program : Aiur.Bytecode.Toplevel} {parent child : Aiur.Bytecode.FunIdx}, + program.ComponentEdge parent child → (program.componentFor parent).permits (program.componentFor child) = true +AXIOMS [propext] +ROOT Aiur.Bytecode.Toplevel.ComponentEdge.rankMode +∀ {program : Aiur.Bytecode.Toplevel} {parent child : Aiur.Bytecode.FunIdx}, + program.ComponentEdge parent child → + (program.componentFor parent).order = (program.componentFor child).order → + (program.callRanksFor parent)[child]?.getD Aiur.Bytecode.CallRank.ordered = Aiur.Bytecode.CallRank.ordered +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.callRanksFor_read +∀ {program : Aiur.Bytecode.Toplevel} {parent child : Aiur.Bytecode.FunIdx} + {parentComponent childComponent : Aiur.Bytecode.CallComponent}, + program.callComponents[parent]? = some parentComponent → + program.callComponents[child]? = some childComponent → + (program.callRanksFor parent)[child]? = + some + (if (parentComponent.order == childComponent.order) = true then Aiur.Bytecode.CallRank.ordered + else if childComponent.ranked = true then Aiur.Bytecode.CallRank.bound else Aiur.Bytecode.CallRank.zero) +AXIOMS [propext, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.componentFor_read +∀ {program : Aiur.Bytecode.Toplevel} {function : Aiur.Bytecode.FunIdx} {component : Aiur.Bytecode.CallComponent}, + program.callComponents[function]? = some component → program.componentFor function = component +AXIOMS [propext] +ROOT Aiur.Bytecode.Toplevel.validCallComponents_component_order +∀ {program : Aiur.Bytecode.Toplevel}, + program.validCallComponents = true → + ∀ {index : Aiur.Bytecode.FunIdx} {function : Aiur.Bytecode.Function}, + program.functions[index]? = some function → (program.componentFor index).order < program.functions.size +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.validCallComponents_edge +∀ {program : Aiur.Bytecode.Toplevel}, + program.validCallComponents = true → + ∀ {parent child : Aiur.Bytecode.FunIdx} {function : Aiur.Bytecode.Function}, + program.functions[parent]? = some function → + function.constrained = true → + child ∈ function.body.collectConstrainedCallees.toList → program.ComponentEdge parent child +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.validCallComponents_order +∀ {program : Aiur.Bytecode.Toplevel}, + program.validCallComponents = true → + ∀ {index : Nat} {component : Aiur.Bytecode.CallComponent}, + program.callComponents[index]? = some component → component.order < program.functions.size +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.Toplevel.validCallComponents_size +∀ {program : Aiur.Bytecode.Toplevel}, + program.validCallComponents = true → program.callComponents.size = program.functions.size +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.Bytecode.flatMap_length_le_sum +∀ {α β : Type} (items : List α) (parts : α → List β) (bound : α → Nat), + (∀ (item : α), item ∈ items → (parts item).length ≤ bound item) → + (List.flatMap parts items).length ≤ (List.map bound items).sum +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_count_eval +∀ {program : Aiur.Bytecode.Toplevel} {width : Nat} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} + {values : Aiur.NativeAIR.Values Aiur.G} {result : Aiur.AIR.CircuitEmission}, + Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint program width emission = true → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → 0 < result.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_read +∀ {program : Aiur.Bytecode.Toplevel} {width : Nat} {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint program width emission = true → + Aiur.NativeAIR.CircuitEmitter.Emission.componentReadBound program emission ≤ width +AXIOMS [propext] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_slots +∀ {program : Aiur.Bytecode.Toplevel} {width : Nat} {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint program width emission = true → + ∀ (part : Aiur.NativeAIR.LookupEmitter.QueryExpr), + part ∈ emission.queries → 0 < part.slot ∧ part.slot < emission.lookupCount +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint_slots_eval +∀ {program : Aiur.Bytecode.Toplevel} {width : Nat} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} + {values : Aiur.NativeAIR.Values Aiur.G} {result : Aiur.AIR.CircuitEmission}, + Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint program width emission = true → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → + ∀ (part : Aiur.AIR.QueryPart), part ∈ result.queries → 0 < part.slot ∧ part.slot < result.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.footprint_count_eval +∀ {width : Nat} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} {values : Aiur.NativeAIR.Values Aiur.G} + {result : Aiur.AIR.CircuitEmission}, + Aiur.NativeAIR.CircuitEmitter.Emission.footprint width emission = true → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → 0 < result.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.footprint_read +∀ {width : Nat} {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.Emission.footprint width emission = true → emission.readBound ≤ width +AXIOMS [propext] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.footprint_slots_eval +∀ {width : Nat} {emission : Aiur.NativeAIR.CircuitEmitter.Emission} {values : Aiur.NativeAIR.Values Aiur.G} + {result : Aiur.AIR.CircuitEmission}, + Aiur.NativeAIR.CircuitEmitter.Emission.footprint width emission = true → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → + ∀ (part : Aiur.AIR.QueryPart), part ∈ result.queries → 0 < part.slot ∧ part.slot < result.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.Emission.genericLimits_eval +∀ {emission : Aiur.NativeAIR.CircuitEmitter.Emission} {values : Aiur.NativeAIR.Values Aiur.G} + {result : Aiur.AIR.CircuitEmission}, + emission.genericLimits = true → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result → + 4 ≤ result.lookupCount ∧ + ∀ (member : Aiur.AIR.MemberEmission), member ∈ result.members → member.body.lookup ≤ result.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit_parts +∀ {widths : Aiur.NativeAIR.GraphWidths} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit widths program circuit = some compiled → + Aiur.NativeAIR.CircuitEmitter.compileCircuit widths program circuit = some compiled ∧ + Aiur.NativeAIR.CircuitEmitter.Emission.footprint widths.main compiled.emission = true ∧ + compiled.emission.genericLimits = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit widths program circuit = some compiled → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + program circuit = + some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) ∧ + 0 < result.lookupCount ∧ + (∀ (part : Aiur.AIR.QueryPart), + part ∈ result.queries → 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + 4 ≤ result.lookupCount ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ result.members → member.body.lookup ≤ result.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit small program circuit = some compiled → + Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit large program circuit = some compiled +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit_parts +∀ {widths : Aiur.NativeAIR.GraphWidths} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit widths program circuit = some compiled → + program.validCallComponents = true ∧ + Aiur.NativeAIR.CircuitEmitter.emitComponentCircuit program circuit = some compiled.emission ∧ + Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint program widths.main compiled.emission = true ∧ + Aiur.NativeAIR.Compiler.compileBase widths compiled.emission.lookups compiled.emission.equations = + some compiled.base +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit widths program circuit = some compiled → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitComponentRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + program circuit = + some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) ∧ + 0 < result.lookupCount ∧ + ∀ (part : Aiur.AIR.QueryPart), + part ∈ result.queries → 0 < part.slot ∧ part.slot < result.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit small program circuit = some compiled → + Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit large program circuit = some compiled +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit_components +∀ {widths : Aiur.NativeAIR.GraphWidths} {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit widths program circuit = some compiled → + program.callComponents.isEmpty = true ∨ program.validCallComponents = true +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} {widths : Aiur.NativeAIR.GraphWidths}, + values.Fits widths → + ∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit widths program circuit = some compiled → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitNativeRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + program circuit = + some result ∧ + compiled.base.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer compiled.base.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) compiled.base.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) ∧ + 0 < result.lookupCount ∧ + (∀ (part : Aiur.AIR.QueryPart), + part ∈ result.queries → 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + (program.callComponents.isEmpty = true → + 4 ≤ result.lookupCount ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ result.members → member.body.lookup ≤ result.lookupCount) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit_widen +∀ {small large : Aiur.NativeAIR.GraphWidths}, + small.Le large → + ∀ {program : Aiur.Bytecode.Toplevel} {circuit : Aiur.Bytecode.Circuit} + {compiled : Aiur.NativeAIR.CircuitEmitter.Compiled}, + Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit small program circuit = some compiled → + Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit large program circuit = some compiled +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.componentCircuitEmission_eval +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) + (circuit : Aiur.Bytecode.Circuit) {members : List Aiur.NativeAIR.CircuitEmitter.Member} + {results : List Aiur.AIR.MemberEmission}, + List.mapM (Aiur.NativeAIR.CircuitEmitter.Member.eval values) members = some results → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) (List.map Aiur.NativeAIR.CircuitEmitter.Member.entry members) = + some (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) results) → + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (List.map Aiur.NativeAIR.CircuitEmitter.Member.entry + (Aiur.NativeAIR.CircuitEmitter.componentMembers program members)) = + some (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) (Aiur.AIR.componentMembers program results)) → + (∀ (index : Nat), + (index < + circuit.layout.inputSize + circuit.layout.selectors + 1 + + if (Aiur.NativeAIR.CircuitEmitter.componentMembers program members).isEmpty = true then 0 else 6) → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → + Aiur.NativeAIR.CircuitEmitter.Emission.eval values + (Aiur.NativeAIR.CircuitEmitter.componentCircuitEmission program circuit members) = + some (Aiur.AIR.componentCircuitEmission row program circuit results) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitComponentCircuit_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) (program : Aiur.Bytecode.Toplevel) + (circuit : Aiur.Bytecode.Circuit) {emission : Aiur.NativeAIR.CircuitEmitter.Emission}, + Aiur.NativeAIR.CircuitEmitter.emitComponentCircuit program circuit = some emission → + (∀ (index : Nat), + index < Aiur.NativeAIR.CircuitEmitter.Emission.componentReadBound program emission → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → + ∃ result, + Aiur.Bytecode.Circuit.emitComponentRow row program circuit = some result ∧ + Aiur.NativeAIR.CircuitEmitter.Emission.eval values emission = some result +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitComponentMember_fields +∀ {rank : Aiur.NativeAIR.Expr} {base selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} {functionIndex : Nat} + {member : Aiur.NativeAIR.CircuitEmitter.Member}, + Aiur.NativeAIR.CircuitEmitter.emitComponentMember rank base selectorBase program functionIndex = some member → + member.functionIndex = functionIndex ∧ + program.functions[functionIndex]? = some member.function ∧ member.selectorBase = selectorBase +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitComponentMember_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {rank : Aiur.NativeAIR.Expr} {r : Aiur.G} + {base selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} {functionIndex : Nat} + {member : Aiur.NativeAIR.CircuitEmitter.Member}, + ((program.componentFor functionIndex).ranked = true → Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r) → + Aiur.NativeAIR.CircuitEmitter.emitComponentMember rank base selectorBase program functionIndex = some member → + (∀ (index : Nat), + index < member.readBound → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → + ∃ result, + Aiur.AIR.emitComponentMember row r base selectorBase program functionIndex = some result ∧ + Aiur.NativeAIR.CircuitEmitter.Member.eval values member = some result ∧ + Aiur.NativeAIR.OpEmitter.evalExpr values member.entry = some (Aiur.AIR.MemberEmission.entry row result) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CircuitEmitter.emitComponentMembers_reflects +∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {rank : Aiur.NativeAIR.Expr} {r : Aiur.G} + (base selectorBase : Nat) (program : Aiur.Bytecode.Toplevel) (indices : List Nat) + {members : List Aiur.NativeAIR.CircuitEmitter.Member}, + (∀ (member : Aiur.NativeAIR.CircuitEmitter.Member), + member ∈ members → + (program.componentFor member.functionIndex).ranked = true → + Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r) → + Aiur.NativeAIR.CircuitEmitter.emitComponentMembers rank base selectorBase program indices = some members → + (∀ (member : Aiur.NativeAIR.CircuitEmitter.Member), + member ∈ members → + ∀ (index : Nat), + index < member.readBound → + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = + some (row index)) → + ∃ results, + Aiur.AIR.emitComponentMembers row r base selectorBase program indices = some results ∧ + List.mapM (Aiur.NativeAIR.CircuitEmitter.Member.eval values) members = some results ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (List.map Aiur.NativeAIR.CircuitEmitter.Member.entry members) = + some (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) results) ∧ + List.mapM (Aiur.NativeAIR.OpEmitter.evalExpr values) + (List.map Aiur.NativeAIR.CircuitEmitter.Member.entry + (Aiur.NativeAIR.CircuitEmitter.componentMembers program members)) = + some + (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) + (Aiur.AIR.componentMembers program results)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte1Circuit_matrix_lookups +∀ {logBlowup : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte1Circuit logBlowup = some artifact → + ∀ (matrix : Fin 256 → Aiur.AIR.Byte1Columns), + artifact.graph.readPreprocessedTraceLookups artifact.widths (Aiur.NativeAIR.finiteTraceMatrix matrix) + (Aiur.NativeAIR.finiteTraceMatrix Aiur.AIR.byte1PreprocessedColumns) = + some + (List.ofFn fun index => + List.map + (fun kind => Aiur.AIR.byte1ColumnLookup kind (Aiur.AIR.byte1PreprocessedColumns index) (matrix index)) + Aiur.AIR.Byte1Kind.all) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte1Circuit_trace_metadata +∀ {logBlowup : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte1Circuit logBlowup = some artifact → + artifact.graph.lookups.length = 3 ∧ artifact.preprocessedHeight = 256 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte2Circuit_matrix_lookups +∀ {logBlowup : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte2Circuit logBlowup = some artifact → + ∀ (matrix : Fin 65536 → Aiur.AIR.Byte2Columns), + artifact.graph.readPreprocessedTraceLookups artifact.widths (Aiur.NativeAIR.finiteTraceMatrix matrix) + (Aiur.NativeAIR.finiteTraceMatrix Aiur.AIR.byte2PreprocessedColumns) = + some + (List.ofFn fun index => + List.map + (fun kind => Aiur.AIR.byte2ColumnLookup kind (Aiur.AIR.byte2PreprocessedColumns index) (matrix index)) + Aiur.AIR.Byte2Kind.all) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.byte2Circuit_trace_metadata +∀ {logBlowup : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.byte2Circuit logBlowup = some artifact → + artifact.graph.lookups.length = 10 ∧ artifact.preprocessedHeight = 65536 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuits_trace_metadata +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {keys : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some keys → + List.map (fun x => x.graph.lookups.length) keys = Aiur.AIR.systemLookupSlots program ∧ + List.map (fun x => x.preprocessedHeight) keys = Aiur.AIR.systemFixedHeights program +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.circuits_trace_parts +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {keys : List Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.circuits logBlowup program = some keys → + List.mapM (Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program) program.circuits.toList = + some (List.take program.circuits.size keys) ∧ + List.mapM (Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup) program.memorySizes.toList = + some (List.take program.memorySizes.size (List.drop program.circuits.size keys)) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.functionCircuit_matrix_extract +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {source : Aiur.Bytecode.Circuit} + {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some artifact → + ∀ {height : Nat} (matrix : Fin height → Nat → Aiur.G), + artifact.graph.TraceSatisfied artifact.widths matrix → + ∃ witnesses, + List.mapM (Aiur.AIR.emitNativeCircuitWitness program source) (List.ofFn matrix) = some witnesses ∧ + (∀ (witness : Aiur.AIR.CircuitWitness), + witness ∈ witnesses → witness.Satisfied ∧ Aiur.AIR.CircuitWitness.NativeBounds program witness) ∧ + artifact.graph.readTraceLookups artifact.widths matrix = + some (List.map (fun witness => Aiur.NativeAIR.emissionLookupRow witness.emission) witnesses) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.functionCircuit_reflects +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {source : Aiur.Bytecode.Circuit} + {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitNativeRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + program source = + some result ∧ + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) ∧ + 0 < result.lookupCount ∧ + (∀ (part : Aiur.AIR.QueryPart), + part ∈ result.queries → 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + (program.callComponents.isEmpty = true → + 4 ≤ result.lookupCount ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ result.members → member.body.lookup ≤ result.lookupCount) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.functionCircuit_trace_metadata +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {source : Aiur.Bytecode.Circuit} + {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some artifact → + artifact.graph.lookups.length = source.layout.lookups ∧ artifact.preprocessedHeight = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.functionCircuit_trace_witness +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {source : Aiur.Bytecode.Circuit} + {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some artifact → + ∀ {height : Nat} (matrix : Fin height → Nat → Aiur.G) (index : Fin height), + artifact.graph.RowSatisfied (Aiur.NativeAIR.traceRowValues artifact.widths matrix index) → + ∃ witness buffer, + Aiur.AIR.emitNativeCircuitWitness program source (matrix index) = some witness ∧ + witness.Satisfied ∧ + Aiur.AIR.CircuitWitness.NativeBounds program witness ∧ + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps + (Aiur.NativeAIR.traceRowValues artifact.widths matrix index) = + some buffer ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some (List.ofFn fun slot => witness.emission.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.functionCircuit_witness +∀ {logBlowup : Nat} {program : Aiur.Bytecode.Toplevel} {source : Aiur.Bytecode.Circuit} + {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ witness buffer, + witness.circuit = source ∧ + (witness.values = fun column => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[column]?.getD 0) ∧ + Aiur.AIR.CircuitWitness.NativeEmitted program witness ∧ + Aiur.AIR.CircuitWitness.NativeBounds program witness ∧ + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + witness.Satisfied) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some (List.ofFn fun slot => witness.emission.lookup ↑slot) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.list_mapM_project +∀ {α β γ : Type} {read : α → Option β} {inputs : List α} {outputs : List β}, + List.mapM read inputs = some outputs → + ∀ (input : α → γ) (output : β → γ), + (∀ (a : α) (b : β), read a = some b → output b = input a) → List.map output outputs = List.map input inputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.memoryCircuit_matrix_lookups +∀ {logBlowup width : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup width = some artifact → + ∀ {height : Nat} (matrix : Fin height → Aiur.AIR.MemoryColumns width), + artifact.graph.readTraceLookups artifact.widths (Aiur.NativeAIR.finiteTraceMatrix matrix) = + some (List.ofFn fun index => [Aiur.AIR.memoryColumnLookup width (matrix index)]) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.memoryCircuit_trace_metadata +∀ {logBlowup width : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup width = some artifact → + artifact.graph.lookups.length = 1 ∧ artifact.preprocessedHeight = 0 +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.memoryCircuit_trace_reflects +∀ {logBlowup width : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup width = some artifact → + ∀ {height : Nat} (matrix : Fin height → Aiur.AIR.MemoryColumns width) (index : Fin height), + ∃ buffer, + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps + (Aiur.NativeAIR.traceRowValues artifact.widths (Aiur.NativeAIR.finiteTraceMatrix matrix) index) = + some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + ∀ (equation : Aiur.G), + equation ∈ Aiur.AIR.memoryMatrixEquations width height matrix index → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some [Aiur.AIR.memoryColumnLookup width (matrix index)] +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.CompiledKey.memoryCircuit_trace_satisfied +∀ {logBlowup width : Nat} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + Aiur.NativeAIR.CompiledKey.memoryCircuit logBlowup width = some artifact → + ∀ {height : Nat} (matrix : Fin height → Aiur.AIR.MemoryColumns width), + artifact.graph.TraceSatisfied artifact.widths (Aiur.NativeAIR.finiteTraceMatrix matrix) → + Aiur.AIR.MemoryMatrixSatisfied width height matrix +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.OpEmitter.emitOp_allocationFor +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.DegreeValid rows → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows callRanks = some emission → + emission.allocation = Aiur.Bytecode.Op.allocationFor callRanks (Aiur.NativeAIR.OpEmitter.rowDegrees rows) op +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.encodedQuery_zero +∀ {emission : Aiur.AIR.CircuitEmission}, + (∀ (query : Aiur.AIR.QueryPart), query ∈ emission.queries → 0 < query.slot) → + Aiur.AIR.encodedQuery emission.branchless emission.queries 0 = none +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.filterMap_eq_of_eq_on +∀ {α : Type u_1} {β : Type u_2} {left right : α → Option β} (inputs : List α), + (∀ (input : α), input ∈ inputs → left input = right input) → List.filterMap left inputs = List.filterMap right inputs +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphFunctionProviders_emissions +∀ (emissions : List Aiur.AIR.CircuitEmission), + (∀ (emission : Aiur.AIR.CircuitEmission), emission ∈ emissions → 0 < emission.lookupCount) → + Aiur.NativeAIR.graphFunctionProviders (List.map Aiur.NativeAIR.emissionLookupRow emissions) = + Aiur.AIR.circuitProviders emissions +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphFunctionQueries_emissions +∀ (emissions : List Aiur.AIR.CircuitEmission), + (∀ (emission : Aiur.AIR.CircuitEmission), + emission ∈ emissions → ∀ (query : Aiur.AIR.QueryPart), query ∈ emission.queries → 0 < query.slot) → + Aiur.NativeAIR.graphFunctionQueries (List.map Aiur.NativeAIR.emissionLookupRow emissions) = + Aiur.AIR.encodedCircuitQueryPool emissions +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.graphLookupProvider_byte1 +∀ (kind : Aiur.AIR.Byte1Kind) (index : Fin 256) (columns : Aiur.AIR.Byte1Columns), + Aiur.NativeAIR.graphLookupProvider + (Aiur.AIR.byte1ColumnLookup kind (Aiur.AIR.byte1PreprocessedColumns index) columns) = + Aiur.AIR.byte1ColumnProvider kind index columns +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphLookupProvider_byte2 +∀ (kind : Aiur.AIR.Byte2Kind) (index : Fin 65536) (columns : Aiur.AIR.Byte2Columns), + Aiur.NativeAIR.graphLookupProvider + (Aiur.AIR.byte2ColumnLookup kind (Aiur.AIR.byte2PreprocessedColumns index) columns) = + Aiur.AIR.byte2ColumnProvider kind index columns +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphLookupProvider_memory +∀ (width : Nat) (columns : Aiur.AIR.MemoryColumns width), + Aiur.NativeAIR.graphLookupProvider (Aiur.AIR.memoryColumnLookup width columns) = + Aiur.AIR.memoryColumnProvider width columns +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphRowProvider_emission +∀ (emission : Aiur.AIR.CircuitEmission), + 0 < emission.lookupCount → + Aiur.NativeAIR.graphRowProvider (Aiur.NativeAIR.emissionLookupRow emission) = some emission.provider +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphRowQueries_emission +∀ (emission : Aiur.AIR.CircuitEmission), + (∀ (query : Aiur.AIR.QueryPart), query ∈ emission.queries → 0 < query.slot) → + Aiur.NativeAIR.graphRowQueries (Aiur.NativeAIR.emissionLookupRow emission) = + Aiur.AIR.encodedQueries emission.branchless emission.queries emission.lookupCount +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.graphTableProviders_append +∀ (first rest : List Aiur.NativeAIR.LookupRow), + Aiur.NativeAIR.graphTableProviders (first ++ rest) = + Aiur.NativeAIR.graphTableProviders first ++ Aiur.NativeAIR.graphTableProviders rest +AXIOMS [propext] +ROOT Aiur.NativeAIR.graphTableProviders_byte1 +∀ (matrix : Fin 256 → Aiur.AIR.Byte1Columns), + Aiur.NativeAIR.graphTableProviders + (List.ofFn fun index => + List.map (fun kind => Aiur.AIR.byte1ColumnLookup kind (Aiur.AIR.byte1PreprocessedColumns index) (matrix index)) + Aiur.AIR.Byte1Kind.all) = + Aiur.AIR.byte1MatrixProviders matrix +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphTableProviders_byte2 +∀ (matrix : Fin 65536 → Aiur.AIR.Byte2Columns), + Aiur.NativeAIR.graphTableProviders + (List.ofFn fun index => + List.map (fun kind => Aiur.AIR.byte2ColumnLookup kind (Aiur.AIR.byte2PreprocessedColumns index) (matrix index)) + Aiur.AIR.Byte2Kind.all) = + Aiur.AIR.byte2MatrixProviders matrix +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.graphTableProviders_memory +∀ (width height : Nat) (matrix : Fin height → Aiur.AIR.MemoryColumns width), + Aiur.NativeAIR.graphTableProviders (List.ofFn fun index => [Aiur.AIR.memoryColumnLookup width (matrix index)]) = + Aiur.AIR.memoryMatrixProviders width height matrix +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.traceRowValuesWithPreprocessed_columns +∀ {widths : Aiur.NativeAIR.GraphWidths} {height mainWidth preprocessedWidth : Nat} + (matrix : Fin height → Fin mainWidth → Aiur.G) (preprocessed : Fin height → Fin preprocessedWidth → Aiur.G) + (index : Fin height), + mainWidth ≤ widths.main → + preprocessedWidth ≤ widths.preprocessed → + Aiur.NativeAIR.CompiledKey.columns + (Aiur.NativeAIR.traceRowValuesWithPreprocessed widths (Aiur.NativeAIR.finiteTraceMatrix matrix) + (Aiur.NativeAIR.finiteTraceMatrix preprocessed) index) + Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current mainWidth = + matrix index ∧ + Aiur.NativeAIR.CompiledKey.columns + (Aiur.NativeAIR.traceRowValuesWithPreprocessed widths (Aiur.NativeAIR.finiteTraceMatrix matrix) + (Aiur.NativeAIR.finiteTraceMatrix preprocessed) index) + Aiur.NativeAIR.Source.preprocessed Aiur.NativeAIR.RowOffset.current preprocessedWidth = + preprocessed index +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.traceRowValuesWithPreprocessed_fits +∀ (widths : Aiur.NativeAIR.GraphWidths) {height : Nat} (matrix preprocessed : Fin height → Nat → Aiur.G) + (index : Fin height), (Aiur.NativeAIR.traceRowValuesWithPreprocessed widths matrix preprocessed index).Fits widths +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.traceRowValues_current +∀ (widths : Aiur.NativeAIR.GraphWidths) {height : Nat} (matrix : Fin height → Nat → Aiur.G) (index : Fin height), + (fun column => + ((Aiur.NativeAIR.traceRowValues widths matrix index).columns Aiur.NativeAIR.Source.main + Aiur.NativeAIR.RowOffset.current)[column]?.getD + 0) = + Aiur.AIR.boundedTraceRow widths.main (matrix index) +AXIOMS [propext, Quot.sound] +ROOT Aiur.NativeAIR.traceRowValues_finite_columns +∀ {widths : Aiur.NativeAIR.GraphWidths} {height width : Nat} (matrix : Fin height → Fin width → Aiur.G) + (index : Fin height), + width ≤ widths.main → + Aiur.NativeAIR.CompiledKey.columns + (Aiur.NativeAIR.traceRowValues widths (Aiur.NativeAIR.finiteTraceMatrix matrix) index) + Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current width = + matrix index ∧ + Aiur.NativeAIR.CompiledKey.columns + (Aiur.NativeAIR.traceRowValues widths (Aiur.NativeAIR.finiteTraceMatrix matrix) index) + Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.next width = + matrix (Aiur.AIR.memoryNextIndex index) +AXIOMS [propext, Classical.choice, Quot.sound] +ROOT Aiur.NativeAIR.traceRowValues_fits +∀ (widths : Aiur.NativeAIR.GraphWidths) {height : Nat} (matrix : Fin height → Nat → Aiur.G) (index : Fin height), + (Aiur.NativeAIR.traceRowValues widths matrix index).Fits widths +AXIOMS [propext, Quot.sound] ROOT Aiur.AIR.callOrderConstraint_derived ∀ (parent gap : Aiur.G), Aiur.AIR.callOrderConstraint parent (parent + 1 + gap) gap = 0 AXIOMS [propext, Quot.sound] @@ -1233,8 +3049,8 @@ ROOT Aiur.AIR.emitOp_step ∀ {program : Aiur.Bytecode.Toplevel} {op : Aiur.Bytecode.Op}, Aiur.Bytecode.Op.lookupShape program op = true → ∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {values : Array Aiur.AIR.RowValue} - {emission : Aiur.AIR.OpEmission}, - Aiur.AIR.emitOp row selector rank op values = some emission → + {emission : Aiur.AIR.OpEmission} {callRanks : Array Aiur.Bytecode.CallRank}, + Aiur.AIR.emitOp row selector rank op values callRanks = some emission → selector = 1 → (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → emission.queries ⊆ queries → @@ -1250,8 +3066,8 @@ ROOT Aiur.AIR.emitOps_run ∀ {program : Aiur.Bytecode.Toplevel} {ops : List Aiur.Bytecode.Op}, (∀ (op : Aiur.Bytecode.Op), op ∈ ops → Aiur.Bytecode.Op.lookupShape program op = true) → ∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {values : Array Aiur.AIR.RowValue} {column : Nat} - {emission : Aiur.AIR.OpsEmission}, - Aiur.AIR.emitOps row selector rank ops values column = some emission → + {emission : Aiur.AIR.OpsEmission} {callRanks : Array Aiur.Bytecode.CallRank}, + Aiur.AIR.emitOps row selector rank ops values column callRanks = some emission → selector = 1 → (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → emission.queries ⊆ queries → @@ -1260,15 +3076,15 @@ ROOT Aiur.AIR.emitOps_run AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.AIR.emitOp_calls ∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {op : Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} - {emission : Aiur.AIR.OpEmission}, - Aiur.AIR.emitOp row selector rank op values = some emission → - Aiur.AIR.CallsEmitted rank selector emission.equations emission.queries emission.calls + {emission : Aiur.AIR.OpEmission} {callRanks : Array Aiur.Bytecode.CallRank}, + Aiur.AIR.emitOp row selector rank op values callRanks = some emission → + Aiur.AIR.CallsEmitted rank selector emission.equations emission.queries emission.calls callRanks AXIOMS [propext, Quot.sound] ROOT Aiur.AIR.emitOps_calls ∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {ops : List Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} - {column : Nat} {emission : Aiur.AIR.OpsEmission}, - Aiur.AIR.emitOps row selector rank ops values column = some emission → - Aiur.AIR.CallsEmitted rank selector emission.equations emission.queries emission.calls + {column : Nat} {emission : Aiur.AIR.OpsEmission} {callRanks : Array Aiur.Bytecode.CallRank}, + Aiur.AIR.emitOps row selector rank ops values column callRanks = some emission → + Aiur.AIR.CallsEmitted rank selector emission.equations emission.queries emission.calls callRanks AXIOMS [propext, Quot.sound] ROOT Aiur.AIR.CallsEmitted.ordered ∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {pool : List (List Aiur.G)}, @@ -1408,7 +3224,7 @@ ROOT Aiur.Bytecode.Block.emitRow_tracks_calls (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block) {emission : Aiur.AIR.BlockEmission}, Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → - Aiur.AIR.BlockEmission.TracksCalls context.rank emission + Aiur.AIR.BlockEmission.TracksCalls context.rank emission context.callRanks AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Bytecode.Block.emitRow_inputs ∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) @@ -1430,8 +3246,9 @@ ROOT Aiur.Bytecode.Function.emitRow_run values.size = function.layout.inputSize → Aiur.Bytecode.Block.lookupShapes program none function.body = true → Aiur.Bytecode.Block.rowBounds selector function.body → - ∀ {emission : Aiur.AIR.BlockEmission}, - Aiur.Bytecode.Function.emitRow row selector functionIndex rank values column lookup function = + ∀ {emission : Aiur.AIR.BlockEmission} {callRanks : Array Aiur.Bytecode.CallRank}, + Aiur.Bytecode.Function.emitRow row selector functionIndex rank values column lookup function + callRanks = some emission → (Aiur.Bytecode.Block.selectorFlow selector function.body).entry = 1 → (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → @@ -1444,7 +3261,7 @@ ROOT Aiur.Bytecode.Function.emitRow_run Aiur.Bytecode.AIR.RunFunction program (Aiur.AIR.memoryFacts tables.memory) request (List.map Prod.fst calls) ∧ emission.CallsAt calls ∧ - Aiur.AIR.CallsEmitted rank 1 emission.equations queries calls + Aiur.AIR.CallsEmitted rank 1 emission.equations queries calls callRanks AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Bytecode.Function.emitRow_valid ∀ {tables : Aiur.AIR.LookupTables} {width : Nat} {queries : List (List Aiur.G)}, @@ -1499,8 +3316,9 @@ ROOT Aiur.Bytecode.Function.emitRow_message (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (function : Aiur.Bytecode.Function) (program : Aiur.Bytecode.Toplevel), Aiur.Bytecode.Block.lookupShapes program none function.body = true → - ∀ {emission : Aiur.AIR.BlockEmission}, - Aiur.Bytecode.Function.emitRow row selector functionIndex rank values column lookup function = some emission → + ∀ {emission : Aiur.AIR.BlockEmission} {callRanks : Array Aiur.Bytecode.CallRank}, + Aiur.Bytecode.Function.emitRow row selector functionIndex rank values column lookup function callRanks = + some emission → (Aiur.Bytecode.Block.selectorFlow selector function.body).entry = 1 → (∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0) → emission.returns.length < Aiur.gSize.toNat → @@ -1684,8 +3502,8 @@ ROOT Aiur.AIR.circuitEmission_rank_queried AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.AIR.MemberEmission.FromProgram.return_count ∀ {row : Nat → Aiur.G} {rank : Aiur.G} {column lookup : Nat} {program : Aiur.Bytecode.Toplevel} - {member : Aiur.AIR.MemberEmission}, - Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member → + {member : Aiur.AIR.MemberEmission} {callRanks : Array Aiur.Bytecode.CallRank}, + Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member callRanks → Aiur.Bytecode.Block.lookupShapes program none member.function.body = true → (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) member.function.body).returns.length < @@ -2095,9 +3913,10 @@ AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Bytecode.Function.emitRow_terminal_writers ∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (function : Aiur.Bytecode.Function) (functionIndex : Aiur.Bytecode.FunIdx) (rank : Aiur.G) (inputs : Array Aiur.AIR.RowValue) (column lookup : Nat) - {emission : Aiur.AIR.BlockEmission}, + {emission : Aiur.AIR.BlockEmission} {callRanks : Array Aiur.Bytecode.CallRank}, function.hasTerminalControl = true → - Aiur.Bytecode.Function.emitRow row selector functionIndex rank inputs column lookup function = some emission → + Aiur.Bytecode.Function.emitRow row selector functionIndex rank inputs column lookup function callRanks = + some emission → Aiur.AIR.QueryWriters lookup emission.lookup emission.queries AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.AIR.circuitEmission_queryWriters @@ -2359,18 +4178,19 @@ ROOT Aiur.Concrete.Bytecode.opsLayout_lookupUsage ∀ (ops : Array Aiur.Bytecode.Op) (initial : Aiur.Concrete.Bytecode.LayoutMState), initial.callRanks = #[] → (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.functionLayout.lookups = - initial.functionLayout.lookups + (List.map Aiur.Bytecode.Op.lookupUsage ops.toList).sum + initial.functionLayout.lookups + (List.map (fun op => op.lookupUsage) ops.toList).sum AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.AIR.emitOp_lookupUsage -∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {op : Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} - {emission : Aiur.AIR.OpEmission}, - Aiur.AIR.emitOp row selector rank op values = some emission → emission.queries.length = op.lookupUsage +∀ {callRanks : Array Aiur.Bytecode.CallRank} {row : Nat → Aiur.G} {selector rank : Aiur.G} {op : Aiur.Bytecode.Op} + {values : Array Aiur.AIR.RowValue} {emission : Aiur.AIR.OpEmission}, + Aiur.AIR.emitOp row selector rank op values callRanks = some emission → + emission.queries.length = op.lookupUsage callRanks AXIOMS [propext, Quot.sound] ROOT Aiur.AIR.emitOps_lookupUsage -∀ {row : Nat → Aiur.G} {selector rank : Aiur.G} {ops : List Aiur.Bytecode.Op} {values : Array Aiur.AIR.RowValue} - {column : Nat} {emission : Aiur.AIR.OpsEmission}, - Aiur.AIR.emitOps row selector rank ops values column = some emission → - emission.queries.length = (List.map Aiur.Bytecode.Op.lookupUsage ops).sum +∀ {callRanks : Array Aiur.Bytecode.CallRank} {row : Nat → Aiur.G} {selector rank : Aiur.G} {ops : List Aiur.Bytecode.Op} + {values : Array Aiur.AIR.RowValue} {column : Nat} {emission : Aiur.AIR.OpsEmission}, + Aiur.AIR.emitOps row selector rank ops values column callRanks = some emission → + emission.queries.length = (List.map (fun op => op.lookupUsage callRanks) ops).sum AXIOMS [propext, Quot.sound] ROOT Aiur.Bytecode.branchRows_lookupUsage ∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (matched : Aiur.G) @@ -2383,29 +4203,29 @@ ROOT Aiur.Bytecode.branchRows_lookupUsage Aiur.Bytecode.Block.emitRow row selector context (Aiur.Bytecode.Block.selectorFlow selector pair.snd).entry values column lookup pair.snd = some emission → - emission.lookup = lookup + pair.snd.lookupUsage) → + emission.lookup = lookup + pair.snd.lookupUsage context.callRanks) → (∀ (block : Aiur.Bytecode.Block), fallback = some block → ∀ (emission : Aiur.AIR.BlockEmission), Aiur.Bytecode.Block.emitRow row selector context (Aiur.Bytecode.Block.selectorFlow selector block).entry values (column + branches.size) lookup block = some emission → - emission.lookup = lookup + block.lookupUsage) → - emission.lookup = lookup + Aiur.Bytecode.branchLookupUsage branches fallback + emission.lookup = lookup + block.lookupUsage context.callRanks) → + emission.lookup = lookup + Aiur.Bytecode.branchLookupUsage branches fallback context.callRanks AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Bytecode.Ctrl.emitRow_lookupUsage ∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (ctrl : Aiur.Bytecode.Ctrl) {emission : Aiur.AIR.BlockEmission}, Aiur.Bytecode.Ctrl.emitRow row selector context incoming values column lookup ctrl = some emission → - emission.lookup = lookup + ctrl.lookupUsage + emission.lookup = lookup + ctrl.lookupUsage context.callRanks AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Bytecode.Block.emitRow_lookupUsage ∀ (row : Nat → Aiur.G) (selector : Aiur.Bytecode.SelIdx → Aiur.G) (context : Aiur.AIR.RowContext) (incoming : Aiur.G) (values : Array Aiur.AIR.RowValue) (column lookup : Nat) (block : Aiur.Bytecode.Block) {emission : Aiur.AIR.BlockEmission}, Aiur.Bytecode.Block.emitRow row selector context incoming values column lookup block = some emission → - emission.lookup = lookup + block.lookupUsage + emission.lookup = lookup + block.lookupUsage context.callRanks AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Concrete.Bytecode.ctrlLayout_lookupUsage ∀ (ctrl : Aiur.Bytecode.Ctrl) (initial : Aiur.Concrete.Bytecode.LayoutMState), @@ -3945,29 +5765,17 @@ AXIOMS [propext, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitCall_reflects ∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first function size : Nat) {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} {inputs : Array Aiur.NativeAIR.RowExpr} - {arguments : Array Aiur.AIR.RowValue}, + {arguments : Array Aiur.AIR.RowValue} {mode : Aiur.Bytecode.CallRank}, Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → Aiur.NativeAIR.OpEmitter.evalRows values inputs = some arguments → (∀ (index : Nat), - index < size + 6 → + index < size + Aiur.AIR.callAuxiliaries mode → (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = some (row index)) → Aiur.NativeAIR.OpEmitter.Emission.eval values - (Aiur.NativeAIR.OpEmitter.emitCall selector rank first function inputs size) = - some - { outputs := Aiur.AIR.rowAdvice row 0 size, used := size + 6, - queries := - Aiur.AIR.functionMessage - { function := function, inputs := Aiur.AIR.rowValues arguments, - outputs := Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row 0 size), - rank := r + 1 + Aiur.AIR.packRank fun index => row (size + ↑index) } :: - List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries fun index => row (size + ↑index)), - calls := - [({ function := function, inputs := Aiur.AIR.rowValues arguments, - outputs := Aiur.AIR.rowValues (Aiur.AIR.rowAdvice row 0 size), - rank := r + 1 + Aiur.AIR.packRank fun index => row (size + ↑index) }, - fun index => row (size + ↑index))] } + (Aiur.NativeAIR.OpEmitter.emitCall selector rank first function inputs size mode) = + some (Aiur.AIR.emitCallRow row r function (Aiur.AIR.rowValues arguments) size mode) AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitStore_reflects ∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (first : Nat) {contents : Array Aiur.NativeAIR.RowExpr} @@ -4079,47 +5887,49 @@ ROOT Aiur.NativeAIR.OpEmitter.Normal.read ∀ {index : Nat} {row : Aiur.NativeAIR.RowExpr}, rows[index]? = some row → row.expr.noConstantNegs = true AXIOMS [propext] ROOT Aiur.NativeAIR.OpEmitter.emitOp_byte1 -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) - (rows : Array Aiur.NativeAIR.RowExpr), - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = do +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte1Kind) (index : Nat) (rows : Array Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows callRanks = do let __do_lift ← rows[index]? pure (Aiur.NativeAIR.OpEmitter.emitByte1 first kind __do_lift) AXIOMS [propext] ROOT Aiur.NativeAIR.OpEmitter.emitOp_byte2 -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (left right : Nat) - (rows : Array Aiur.NativeAIR.RowExpr), - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op left right) rows = do +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte2Kind) (left right : Nat) (rows : Array Aiur.NativeAIR.RowExpr), + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op left right) rows callRanks = do let __do_lift ← rows[left]? let __do_lift_1 ← rows[right]? pure (Aiur.NativeAIR.OpEmitter.emitByte2 first kind __do_lift __do_lift_1) AXIOMS [propext] ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch -∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (selector rank : Aiur.NativeAIR.Expr) (s r : Aiur.G) - (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) {rows : Array Aiur.NativeAIR.RowExpr} - {inputs : Array Aiur.AIR.RowValue} {emission : Aiur.NativeAIR.OpEmitter.Emission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) + (selector rank : Aiur.NativeAIR.Expr) (s r : Aiur.G) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows callRanks = some emission → (∀ (index : Nat), index < emission.used → (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = some (row index)) → ∃ result, - Aiur.AIR.emitOp row s r (kind.op index) inputs = some result ∧ + Aiur.AIR.emitOp row s r (kind.op index) inputs callRanks = some result ∧ Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch -∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) (selector rank : Aiur.NativeAIR.Expr) (s r : Aiur.G) - (first : Nat) (kind : Aiur.AIR.Byte2Kind) (left right : Nat) {rows : Array Aiur.NativeAIR.RowExpr} - {inputs : Array Aiur.AIR.RowValue} {emission : Aiur.NativeAIR.OpEmitter.Emission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) + (selector rank : Aiur.NativeAIR.Expr) (s r : Aiur.G) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (left right : Nat) + {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → Aiur.NativeAIR.OpEmitter.Normal rows → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op left right) rows = some emission → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op left right) rows callRanks = some emission → (∀ (index : Nat), index < emission.used → (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = some (row index)) → ∃ result, - Aiur.AIR.emitOp row s r (kind.op left right) inputs = some result ∧ + Aiur.AIR.emitOp row s r (kind.op left right) inputs callRanks = some result ∧ Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.list_ofFn_getD_pair @@ -4129,40 +5939,43 @@ ROOT Aiur.NativeAIR.OpEmitter.list_ofFn_getD_pair List.ofFn fun index => f left[index] (right[↑index]?.getD rightDefault) AXIOMS [propext, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOp_reflects -∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} - {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} +∀ {callRanks : Array Aiur.Bytecode.CallRank} (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) + {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} {first : Nat} {op : Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} {emission : Aiur.NativeAIR.OpEmitter.Emission}, Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → Aiur.NativeAIR.OpEmitter.Normal rows → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows callRanks = some emission → (∀ (index : Nat), index < emission.used → (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[first + index]? = some (row index)) → ∃ result, - Aiur.AIR.emitOp row s r op inputs = some result ∧ + Aiur.AIR.emitOp row s r op inputs callRanks = some result ∧ Aiur.NativeAIR.OpEmitter.Emission.eval values emission = some result AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_normal -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) - {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte1Kind) (index : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows callRanks = some emission → Aiur.NativeAIR.OpEmitter.Normal emission.outputs AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_normal -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (a b : Nat) - {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte2Kind) (a b : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, Aiur.NativeAIR.OpEmitter.Normal rows → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows = some emission → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows callRanks = some emission → Aiur.NativeAIR.OpEmitter.Normal emission.outputs AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOp_normal -∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {emission : Aiur.NativeAIR.OpEmitter.Emission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, Aiur.NativeAIR.OpEmitter.Normal rows → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows callRanks = some emission → Aiur.NativeAIR.OpEmitter.Normal emission.outputs AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.evalRows_append @@ -4206,33 +6019,34 @@ ROOT Aiur.NativeAIR.OpEmitter.OpsEmission.eval_components List.mapM (Aiur.NativeAIR.OpEmitter.CallExpr.eval values) emission.calls = some result.calls AXIOMS [propext] ROOT Aiur.NativeAIR.OpEmitter.emitOps_column -∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, - Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → column ≤ emission.column +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column callRanks = some emission → column ≤ emission.column AXIOMS [propext] ROOT Aiur.NativeAIR.OpEmitter.emitOps_normal -∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, Aiur.NativeAIR.OpEmitter.Normal rows → - Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column callRanks = some emission → Aiur.NativeAIR.OpEmitter.Normal emission.values AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOps_reflects -∀ (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} - {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} {column : Nat} +∀ {callRanks : Array Aiur.Bytecode.CallRank} (values : Aiur.NativeAIR.Values Aiur.G) (row : Nat → Aiur.G) + {selector rank : Aiur.NativeAIR.Expr} {s r : Aiur.G} {ops : List Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {inputs : Array Aiur.AIR.RowValue} {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, Aiur.NativeAIR.OpEmitter.evalExpr values selector = some s → Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → Aiur.NativeAIR.OpEmitter.evalRows values rows = some inputs → Aiur.NativeAIR.OpEmitter.Normal rows → - Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column callRanks = some emission → (∀ (index : Nat), column ≤ index → index < emission.column → (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → ∃ result, - Aiur.AIR.emitOps row s r ops inputs column = some result ∧ + Aiur.AIR.emitOps row s r ops inputs column callRanks = some result ∧ Aiur.NativeAIR.OpEmitter.OpsEmission.eval values emission = some result AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.LookupEmitter.addArgs_eval @@ -4970,14 +6784,15 @@ AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.CircuitEmitter.emitMember_reflects ∀ {values : Aiur.NativeAIR.Values Aiur.G} (row : Nat → Aiur.G) {rank : Aiur.NativeAIR.Expr} {r : Aiur.G} {column lookup selectorBase : Nat} {program : Aiur.Bytecode.Toplevel} {functionIndex : Nat} - {member : Aiur.NativeAIR.CircuitEmitter.Member}, + {member : Aiur.NativeAIR.CircuitEmitter.Member} {callRanks : Array Aiur.Bytecode.CallRank}, Aiur.NativeAIR.OpEmitter.evalExpr values rank = some r → - Aiur.NativeAIR.CircuitEmitter.emitMember rank column lookup selectorBase program functionIndex = some member → + Aiur.NativeAIR.CircuitEmitter.emitMember rank column lookup selectorBase program functionIndex callRanks = + some member → (∀ (index : Nat), index < member.readBound → (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]? = some (row index)) → ∃ result, - Aiur.AIR.emitMember row r column lookup selectorBase program functionIndex = some result ∧ + Aiur.AIR.emitMember row r column lookup selectorBase program functionIndex callRanks = some result ∧ Aiur.NativeAIR.CircuitEmitter.Member.eval values member = some result ∧ Aiur.NativeAIR.OpEmitter.evalExpr values member.entry = some (Aiur.AIR.MemberEmission.entry row result) AXIOMS [propext, Classical.choice, Quot.sound] @@ -5158,29 +6973,31 @@ ROOT Aiur.NativeAIR.OpEmitter.emitU32LessThan_degreeValid Aiur.NativeAIR.OpEmitter.DegreeValid (Aiur.NativeAIR.OpEmitter.emitU32LessThan selector first left right).outputs AXIOMS [propext] ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_degreeValid -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) - {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte1Kind) (index : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows callRanks = some emission → Aiur.NativeAIR.OpEmitter.DegreeValid emission.outputs AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_degreeValid -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (a b : Nat) - {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows = some emission → +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte2Kind) (a b : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows callRanks = some emission → Aiur.NativeAIR.OpEmitter.DegreeValid emission.outputs AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOp_degreeValid -∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {emission : Aiur.NativeAIR.OpEmitter.Emission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, Aiur.NativeAIR.OpEmitter.DegreeValid rows → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows callRanks = some emission → Aiur.NativeAIR.OpEmitter.DegreeValid emission.outputs AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOps_degreeValid -∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission}, Aiur.NativeAIR.OpEmitter.DegreeValid rows → - Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column callRanks = some emission → Aiur.NativeAIR.OpEmitter.DegreeValid emission.values AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitEqZero_allocation @@ -5244,15 +7061,17 @@ ROOT Aiur.NativeAIR.OpEmitter.emitWordSum_allocation { degrees := (Array.replicate 4 1).push (max sum.degree 1), auxiliaries := 4 } AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitByte1_dispatch_allocation -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte1Kind) (index : Nat) - {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows = some emission → +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte1Kind) (index : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op index) rows callRanks = some emission → emission.allocation = Aiur.Bytecode.Op.allocation (Aiur.NativeAIR.OpEmitter.rowDegrees rows) (kind.op index) AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitByte2_dispatch_allocation -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (kind : Aiur.AIR.Byte2Kind) (a b : Nat) - {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, - Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows = some emission → +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) + (kind : Aiur.AIR.Byte2Kind) (a b : Nat) {rows : Array Aiur.NativeAIR.RowExpr} + {emission : Aiur.NativeAIR.OpEmitter.Emission}, + Aiur.NativeAIR.OpEmitter.emitOp selector rank first (kind.op a b) rows callRanks = some emission → emission.allocation = Aiur.Bytecode.Op.allocation (Aiur.NativeAIR.OpEmitter.rowDegrees rows) (kind.op a b) AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOp_allocation @@ -5263,26 +7082,27 @@ ROOT Aiur.NativeAIR.OpEmitter.emitOp_allocation emission.allocation = Aiur.Bytecode.Op.allocation (Aiur.NativeAIR.OpEmitter.rowDegrees rows) op AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOp_layout -∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {emission : Aiur.NativeAIR.OpEmitter.Emission} (initial : Aiur.Concrete.Bytecode.LayoutMState), - initial.callRanks = #[] → +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission} + (initial : Aiur.Concrete.Bytecode.LayoutMState), + initial.callRanks = callRanks → Aiur.NativeAIR.OpEmitter.DegreeValid rows → Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows callRanks = some emission → (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.degrees = Aiur.NativeAIR.OpEmitter.rowDegrees (rows ++ emission.outputs) ∧ (StateT.run (Aiur.Concrete.Bytecode.opLayout op) initial).snd.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + emission.used AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOps_fold_layout -∀ {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} (initial : Aiur.Concrete.Bytecode.LayoutMState) - (base : Nat), - initial.callRanks = #[] → +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {ops : List Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} + (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat), + initial.callRanks = callRanks → Aiur.NativeAIR.OpEmitter.DegreeValid rows → Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → column = base + initial.functionLayout.auxiliaries → - Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column callRanks = some emission → (StateT.run (List.foldlM (fun x op => Aiur.Concrete.Bytecode.opLayout op) () ops) initial).snd.degrees = Aiur.NativeAIR.OpEmitter.rowDegrees emission.values ∧ emission.column = @@ -5291,14 +7111,14 @@ ROOT Aiur.NativeAIR.OpEmitter.emitOps_fold_layout initial).snd.functionLayout.auxiliaries AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOps_layout -∀ {selector rank : Aiur.NativeAIR.Expr} {ops : Array Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} (initial : Aiur.Concrete.Bytecode.LayoutMState) - (base : Nat), - initial.callRanks = #[] → +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {ops : Array Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {column : Nat} {emission : Aiur.NativeAIR.OpEmitter.OpsEmission} + (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat), + initial.callRanks = callRanks → Aiur.NativeAIR.OpEmitter.DegreeValid rows → Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → column = base + initial.functionLayout.auxiliaries → - Aiur.NativeAIR.OpEmitter.emitOps selector rank ops.toList rows column = some emission → + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops.toList rows column callRanks = some emission → (StateT.run (Array.forM Aiur.Concrete.Bytecode.opLayout ops) initial).snd.degrees = Aiur.NativeAIR.OpEmitter.rowDegrees emission.values ∧ emission.column = @@ -5311,12 +7131,13 @@ ROOT Aiur.Concrete.Bytecode.allocationBranchStep_degrees (StateT.run (Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc block) initial).snd.degrees = degrees AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Concrete.Bytecode.allocationBranchStep_column -∀ (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) (acc : Aiur.Concrete.Bytecode.SharedData) - (block : Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState) (base column : Nat), +∀ {callRanks : Array Aiur.Bytecode.CallRank} (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) + (acc : Aiur.Concrete.Bytecode.SharedData) (block : Aiur.Bytecode.Block) + (initial : Aiur.Concrete.Bytecode.LayoutMState) (base column : Nat), initial.degrees = degrees → - initial.callRanks = #[] → + initial.callRanks = callRanks → (∀ (state : Aiur.Concrete.Bytecode.LayoutMState), - state.callRanks = #[] → + state.callRanks = callRanks → state.degrees = degrees → state.functionLayout.auxiliaries = shared.auxiliaries → column = @@ -5327,12 +7148,13 @@ ROOT Aiur.Concrete.Bytecode.allocationBranchStep_column max (base + acc.auxiliaries) column AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Concrete.Bytecode.allocationBranchFold -∀ {α β : Type} {items : List α} {emissions : List β} (blockOf : α → Aiur.Bytecode.Block) (measure : β → Nat) - (shared : Aiur.Concrete.Bytecode.SharedData) (degrees : Array Nat) (base : Nat), +∀ {callRanks : Array Aiur.Bytecode.CallRank} {α β : Type} {items : List α} {emissions : List β} + (blockOf : α → Aiur.Bytecode.Block) (measure : β → Nat) (shared : Aiur.Concrete.Bytecode.SharedData) + (degrees : Array Nat) (base : Nat), List.Forall₂ (fun item emission => ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), - state.callRanks = #[] → + state.callRanks = callRanks → state.degrees = degrees → state.functionLayout.auxiliaries = shared.auxiliaries → measure emission = @@ -5342,7 +7164,7 @@ ROOT Aiur.Concrete.Bytecode.allocationBranchFold items emissions → ∀ (acc : Aiur.Concrete.Bytecode.SharedData) (initial : Aiur.Concrete.Bytecode.LayoutMState), initial.degrees = degrees → - initial.callRanks = #[] → + initial.callRanks = callRanks → (StateT.run (List.foldlM (fun acc item => Aiur.Concrete.Bytecode.allocationBranchStep shared degrees acc (blockOf item)) @@ -5365,14 +7187,14 @@ ROOT Aiur.Concrete.Bytecode.allocationBranchLoop branches.toList AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Concrete.Bytecode.matchLayout_allocation -∀ {β : Type} (index : Aiur.Bytecode.ValIdx) (branches : Array (Aiur.G × Aiur.Bytecode.Block)) - (fallback : Option Aiur.Bytecode.Block) (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat) - (measure : β → Nat) {cases defaults : List β}, - initial.callRanks = #[] → +∀ {callRanks : Array Aiur.Bytecode.CallRank} {β : Type} (index : Aiur.Bytecode.ValIdx) + (branches : Array (Aiur.G × Aiur.Bytecode.Block)) (fallback : Option Aiur.Bytecode.Block) + (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat) (measure : β → Nat) {cases defaults : List β}, + initial.callRanks = callRanks → List.Forall₂ (fun pair emission => ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), - state.callRanks = #[] → + state.callRanks = callRanks → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries → measure emission = @@ -5382,7 +7204,7 @@ ROOT Aiur.Concrete.Bytecode.matchLayout_allocation List.Forall₂ (fun block emission => ∀ (state : Aiur.Concrete.Bytecode.LayoutMState), - state.callRanks = #[] → + state.callRanks = callRanks → state.degrees = initial.degrees → state.functionLayout.auxiliaries = initial.functionLayout.auxiliaries + branches.size → measure emission = @@ -5440,7 +7262,7 @@ ROOT Aiur.NativeAIR.BlockEmitter.branchRows_layout {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block} {emission : Aiur.NativeAIR.BlockEmitter.Emission} (index : Nat) (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat), - initial.callRanks = #[] → + initial.callRanks = context.callRanks → Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → column = base + initial.functionLayout.auxiliaries → Aiur.NativeAIR.BlockEmitter.branchRows selectors context matched rows column lookup branches fallback = @@ -5449,7 +7271,7 @@ ROOT Aiur.NativeAIR.BlockEmitter.branchRows_layout pair ∈ branches.toList → ∀ (entry : Aiur.NativeAIR.Expr) (result : Aiur.NativeAIR.BlockEmitter.Emission) (state : Aiur.Concrete.Bytecode.LayoutMState), - state.callRanks = #[] → + state.callRanks = context.callRanks → Aiur.NativeAIR.OpEmitter.rowDegrees rows = state.degrees → column = base + state.functionLayout.auxiliaries → Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows column lookup pair.snd = @@ -5462,7 +7284,7 @@ ROOT Aiur.NativeAIR.BlockEmitter.branchRows_layout fallback = some block → ∀ (entry : Aiur.NativeAIR.Expr) (result : Aiur.NativeAIR.BlockEmitter.Emission) (state : Aiur.Concrete.Bytecode.LayoutMState), - state.callRanks = #[] → + state.callRanks = context.callRanks → Aiur.NativeAIR.OpEmitter.rowDegrees rows = state.degrees → column + branches.size = base + state.functionLayout.auxiliaries → Aiur.NativeAIR.BlockEmitter.emitBlock selectors context entry rows (column + branches.size) @@ -5486,7 +7308,7 @@ ROOT Aiur.NativeAIR.BlockEmitter.emitCtrl_layout (ctrl : Aiur.Bytecode.Ctrl) {emission : Aiur.NativeAIR.BlockEmitter.Emission} (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat), Aiur.NativeAIR.OpEmitter.DegreeValid rows → - initial.callRanks = #[] → + initial.callRanks = context.callRanks → Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → column = base + initial.functionLayout.auxiliaries → Aiur.NativeAIR.BlockEmitter.emitCtrl selectors context incoming rows column lookup ctrl = some emission → @@ -5501,7 +7323,7 @@ ROOT Aiur.NativeAIR.BlockEmitter.emitBlock_layout (block : Aiur.Bytecode.Block) {emission : Aiur.NativeAIR.BlockEmitter.Emission} (initial : Aiur.Concrete.Bytecode.LayoutMState) (base : Nat), Aiur.NativeAIR.OpEmitter.DegreeValid rows → - initial.callRanks = #[] → + initial.callRanks = context.callRanks → Aiur.NativeAIR.OpEmitter.rowDegrees rows = initial.degrees → column = base + initial.functionLayout.auxiliaries → Aiur.NativeAIR.BlockEmitter.emitBlock selectors context incoming rows column lookup block = some emission → @@ -5965,15 +7787,15 @@ ROOT Aiur.AIR.selectorSum_zero ∀ (values : List Aiur.G), (∀ (value : Aiur.G), value ∈ values → value = 0) → Aiur.AIR.selectorSum values = 0 AXIOMS [propext] ROOT Aiur.AIR.emitOp_inactive -∀ {row : Nat → Aiur.G} {rank : Aiur.G} (op : Aiur.Bytecode.Op) {values : Array Aiur.AIR.RowValue} - {emission : Aiur.AIR.OpEmission}, - Aiur.AIR.emitOp row 0 rank op values = some emission → +∀ {callRanks : Array Aiur.Bytecode.CallRank} {row : Nat → Aiur.G} {rank : Aiur.G} (op : Aiur.Bytecode.Op) + {values : Array Aiur.AIR.RowValue} {emission : Aiur.AIR.OpEmission}, + Aiur.AIR.emitOp row 0 rank op values callRanks = some emission → ∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0 AXIOMS [propext, Quot.sound] ROOT Aiur.AIR.emitOps_inactive -∀ {row : Nat → Aiur.G} {rank : Aiur.G} (ops : List Aiur.Bytecode.Op) {values : Array Aiur.AIR.RowValue} {column : Nat} - {emission : Aiur.AIR.OpsEmission}, - Aiur.AIR.emitOps row 0 rank ops values column = some emission → +∀ {callRanks : Array Aiur.Bytecode.CallRank} {row : Nat → Aiur.G} {rank : Aiur.G} (ops : List Aiur.Bytecode.Op) + {values : Array Aiur.AIR.RowValue} {column : Nat} {emission : Aiur.AIR.OpsEmission}, + Aiur.AIR.emitOps row 0 rank ops values column callRanks = some emission → ∀ (equation : Aiur.G), equation ∈ emission.equations → equation = 0 AXIOMS [propext, Quot.sound] ROOT Aiur.AIR.BlockEmission.Inactive.prefix @@ -6207,23 +8029,26 @@ ROOT Aiur.NativeAIR.OpEmitter.readWord_defined ∃ output, Aiur.NativeAIR.OpEmitter.readWord rows indices = some output AXIOMS [propext, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOp_defined -∀ (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (op : Aiur.Bytecode.Op) (rows : Array Aiur.NativeAIR.RowExpr), +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (first : Nat) (op : Aiur.Bytecode.Op) + (rows : Array Aiur.NativeAIR.RowExpr), Aiur.Bytecode.Op.emissionInputs rows.size op = true → - ∃ emission, Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission + ∃ emission, Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows callRanks = some emission AXIOMS [propext, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOp_outputSize -∀ {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} {rows : Array Aiur.NativeAIR.RowExpr} - {emission : Aiur.NativeAIR.OpEmitter.Emission}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} {selector rank : Aiur.NativeAIR.Expr} {first : Nat} {op : Aiur.Bytecode.Op} + {rows : Array Aiur.NativeAIR.RowExpr} {emission : Aiur.NativeAIR.OpEmitter.Emission}, Aiur.NativeAIR.OpEmitter.DegreeValid rows → - Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows = some emission → emission.outputs.size = op.outputSize + Aiur.NativeAIR.OpEmitter.emitOp selector rank first op rows callRanks = some emission → + emission.outputs.size = op.outputSize AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.NativeAIR.OpEmitter.emitOps_defined -∀ (selector rank : Aiur.NativeAIR.Expr) (ops : List Aiur.Bytecode.Op) (rows : Array Aiur.NativeAIR.RowExpr) - (column : Nat) {next : Nat}, +∀ {callRanks : Array Aiur.Bytecode.CallRank} (selector rank : Aiur.NativeAIR.Expr) (ops : List Aiur.Bytecode.Op) + (rows : Array Aiur.NativeAIR.RowExpr) (column : Nat) {next : Nat}, Aiur.NativeAIR.OpEmitter.DegreeValid rows → Aiur.Bytecode.checkEmissionOps ops rows.size = some next → ∃ emission, - Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column = some emission ∧ emission.values.size = next + Aiur.NativeAIR.OpEmitter.emitOps selector rank ops rows column callRanks = some emission ∧ + emission.values.size = next AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.Bytecode.emissionChecks_match ∀ (available selectors : Nat) (yieldSize : Option Nat) (index : Aiur.Bytecode.ValIdx) @@ -6828,7 +8653,8 @@ ROOT Aiur.NativeAIR.CompiledKey.functionCircuit_success {result : Aiur.NativeAIR.KeyCodec.Circuit}, Aiur.NativeAIR.CompiledKey.functionCircuit logBlowup program source = some result → ∃ compiled, - Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths source) program source = + Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths source) program + source = some compiled ∧ result.graph = compiled.base.graph ∧ result.mainWidth = source.layout.width ∧ @@ -6974,24 +8800,30 @@ ROOT Aiur.BoundVerifier.CompiledBackend.circuit_count backend.compiled.bytecode.circuits.size + backend.compiled.bytecode.memorySizes.size + 2 AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.BoundVerifier.CompiledBackend.function_graph_reflects -∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection), - selection.source.componentRanks = false → - ∀ {index : Nat} {source : Aiur.Bytecode.Circuit} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, - backend.compiled.bytecode.circuits[index]? = some source → - backend.keyData.circuits[index]? = some artifact → - ∀ {values : Aiur.NativeAIR.Values Aiur.G}, - values.Fits artifact.widths → - ∃ result buffer, - Aiur.Bytecode.Circuit.emitRow - (fun index => - (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) - backend.compiled.bytecode source = - some result ∧ - artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ - (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ - ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ - List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = - some (List.ofFn fun slot => result.lookup ↑slot) +∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) {index : Nat} + {source : Aiur.Bytecode.Circuit} {artifact : Aiur.NativeAIR.KeyCodec.Circuit}, + backend.compiled.bytecode.circuits[index]? = some source → + backend.keyData.circuits[index]? = some artifact → + ∀ {values : Aiur.NativeAIR.Values Aiur.G}, + values.Fits artifact.widths → + ∃ result buffer, + Aiur.Bytecode.Circuit.emitNativeRow + (fun index => + (values.columns Aiur.NativeAIR.Source.main Aiur.NativeAIR.RowOffset.current)[index]?.getD 0) + backend.compiled.bytecode source = + some result ∧ + artifact.graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + (Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer artifact.graph.zeros ↔ + ∀ (equation : Aiur.G), equation ∈ result.equations → equation = 0) ∧ + List.mapM (Aiur.NativeAIR.readLookup buffer) artifact.graph.lookups = + some (List.ofFn fun slot => result.lookup ↑slot) ∧ + 0 < result.lookupCount ∧ + (∀ (part : Aiur.AIR.QueryPart), + part ∈ result.queries → 0 < part.slot ∧ part.slot < result.lookupCount) ∧ + (backend.compiled.bytecode.callComponents.isEmpty = true → + 4 ≤ result.lookupCount ∧ + ∀ (member : Aiur.AIR.MemberEmission), + member ∈ result.members → member.body.lookup ≤ result.lookupCount) AXIOMS [propext, Classical.choice, Quot.sound] ROOT Aiur.BoundVerifier.CompiledBackend.memory_graph_reflects ∀ {selection : Aiur.BoundVerifier.Selection} (backend : Aiur.BoundVerifier.CompiledBackend selection) @@ -11682,6 +13514,551 @@ ROOT Aiur.NativeAIR.FriQuery.check_final_polynomial finalPolynomial = result.state.value AXIOMS [propext, Classical.choice, Quot.sound] +PREMISE Aiur.AIR.CallRankChecks +Array Aiur.Bytecode.CallRank → + Aiur.G → Aiur.G → List Aiur.G → (List Aiur.G → Prop) → Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G) → Prop +DEFINITION +fun callRanks rank selector equations hasQuery edge => + match callRanks[edge.fst.function]?.getD Aiur.Bytecode.CallRank.ordered with + | Aiur.Bytecode.CallRank.ordered => + (∀ ⦃message : List Aiur.G⦄, + message ∈ List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries edge.snd) → hasQuery message) ∧ + Aiur.AIR.EquationAvailable equations + (selector * Aiur.AIR.callOrderConstraint rank edge.fst.rank (Aiur.AIR.packRank edge.snd)) + | Aiur.Bytecode.CallRank.zero => True + | Aiur.Bytecode.CallRank.bound => True +PREMISE Aiur.AIR.CircuitTraces.GraphSatisfied +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → List Aiur.NativeAIR.KeyCodec.Circuit → Prop +DEFINITION +fun {circuits} x x_1 => + Aiur.AIR.CircuitTraces.brecOn (motive := fun {circuits} x => List Aiur.NativeAIR.KeyCodec.Circuit → Prop) x + (@Aiur.AIR.CircuitTraces.GraphSatisfied._f) x_1 +PREMISE Aiur.AIR.CircuitTraces.emitNativeWitnesses +{circuits : List Aiur.Bytecode.Circuit} → + Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitTraces circuits → Option (List Aiur.AIR.CircuitWitness) +DEFINITION +fun {circuits} program x => Aiur.AIR.CircuitTraces.brecOn x (@Aiur.AIR.CircuitTraces.emitNativeWitnesses._f program) +PREMISE Aiur.AIR.CircuitTraces.graphLookups +{circuits : List Aiur.Bytecode.Circuit} → + Aiur.AIR.CircuitTraces circuits → List Aiur.NativeAIR.KeyCodec.Circuit → Option (List Aiur.NativeAIR.LookupRow) +DEFINITION +fun {circuits} x x_1 => + Aiur.AIR.CircuitTraces.brecOn (motive := fun {circuits} x => + List Aiur.NativeAIR.KeyCodec.Circuit → Option (List Aiur.NativeAIR.LookupRow)) x + (@Aiur.AIR.CircuitTraces.graphLookups._f) x_1 +PREMISE Aiur.AIR.CircuitWitness.ComponentEmitted +Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun program witness => + Aiur.Bytecode.Circuit.emitComponentRow witness.values program witness.circuit = some witness.emission +PREMISE Aiur.AIR.CircuitWitness.Constrained +Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun witness => ∀ (part : Aiur.AIR.MemberEmission), part ∈ witness.emission.members → part.function.constrained = true +PREMISE Aiur.AIR.CircuitWitness.NativeBounds +Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun program witness => witness.QueryRanges ∧ (program.callComponents.isEmpty = true → witness.LookupBounds) +PREMISE Aiur.AIR.CircuitWitness.NativeEmitted +Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun program witness => + Aiur.Bytecode.Circuit.emitNativeRow witness.values program witness.circuit = some witness.emission +PREMISE Aiur.AIR.CircuitWitness.QueryRanges +Aiur.AIR.CircuitWitness → Prop +DEFINITION +fun witness => + 0 < witness.emission.lookupCount ∧ + ∀ (part : Aiur.AIR.QueryPart), + part ∈ witness.emission.queries → 0 < part.slot ∧ part.slot < witness.emission.lookupCount +PREMISE Aiur.AIR.FunctionRow.ComponentQueriesIn +Aiur.Bytecode.Toplevel → List (List Aiur.G) → Aiur.AIR.FunctionRow → Prop +DEFINITION +fun program queries row => + row.selector = 1 → + List.map Aiur.AIR.functionMessage row.requests ⊆ queries ∧ + List.map Aiur.AIR.rangeMessage (Aiur.AIR.FunctionRow.componentByteQueries program row) ⊆ queries +PREMISE Aiur.AIR.FunctionRow.ComponentValid.mk +∀ {program : Aiur.Bytecode.Toplevel} {memory : Aiur.Bytecode.AIR.Memory} {row : Aiur.AIR.FunctionRow}, + row.selector = 0 ∨ row.selector = 1 → + Aiur.AIR.activityConstraint row.multiplicity row.selector = 0 → + (row.selector = 1 → + ∃ function, program.functions[row.request.function]? = some function ∧ function.constrained = true) → + (row.selector = 1 → + row.request.rank = + if (program.componentFor row.request.function).ranked = true then Aiur.AIR.packRank row.rankBytes + else 0) → + (row.selector = 1 → Aiur.Bytecode.AIR.RunFunction program memory row.request row.requests) → + (∀ (edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)), + edge ∈ row.calls → + (program.componentFor row.request.function).order = (program.componentFor edge.fst.function).order → + row.selector * + Aiur.AIR.callOrderConstraint row.request.rank edge.fst.rank (Aiur.AIR.packRank edge.snd) = + 0) → + Aiur.AIR.FunctionRow.ComponentValid program memory row +PREMISE Aiur.AIR.FunctionRow.componentByteQueries +Aiur.Bytecode.Toplevel → Aiur.AIR.FunctionRow → List (Aiur.G × Aiur.G) +DEFINITION +fun program row => + (if (program.componentFor row.request.function).ranked = true then Aiur.AIR.rankByteQueries row.rankBytes else []) ++ + List.flatMap + (fun edge => + if (program.componentFor row.request.function).order = (program.componentFor edge.fst.function).order then + Aiur.AIR.rankByteQueries edge.snd + else []) + row.calls +PREMISE Aiur.AIR.GraphLookupData.mk +List Aiur.NativeAIR.LookupRow → + List Aiur.NativeAIR.LookupRow → + List Aiur.NativeAIR.LookupRow → List Aiur.NativeAIR.LookupRow → Aiur.AIR.GraphLookupData +PREMISE Aiur.AIR.GraphLookupData.providers +Aiur.AIR.GraphLookupData → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun data => + Aiur.NativeAIR.graphFunctionProviders data.functions ++ + (Aiur.NativeAIR.graphTableProviders data.memories ++ + (Aiur.NativeAIR.graphTableProviders data.unary ++ Aiur.NativeAIR.graphTableProviders data.binary)) +PREMISE Aiur.AIR.GraphLookupData.queries +Aiur.AIR.GraphLookupData → List (List Aiur.G) +DEFINITION +fun data => Aiur.NativeAIR.graphFunctionQueries data.functions +PREMISE Aiur.AIR.MemberEmission.FromComponent +(Nat → Aiur.G) → Aiur.G → Nat → Aiur.Bytecode.Toplevel → Aiur.AIR.MemberEmission → Prop +DEFINITION +fun row rank base program member => + Aiur.AIR.MemberEmission.FromProgram row + (if (program.componentFor member.functionIndex).ranked = true then rank else 0) + (Aiur.AIR.componentColumn (program.componentFor member.functionIndex).ranked base) + (Aiur.AIR.componentLookup (program.componentFor member.functionIndex).ranked) program member + (program.callRanksFor member.functionIndex) +PREMISE Aiur.AIR.MemberEmission.componentQueries +(Nat → Aiur.G) → (Fin 6 → Aiur.G) → Aiur.Bytecode.Toplevel → Aiur.AIR.MemberEmission → List Aiur.AIR.QueryPart +DEFINITION +fun row rankBytes program member => + member.body.queries ++ + if (program.componentFor member.functionIndex).ranked = true then + Aiur.AIR.queryParts 1 (Aiur.AIR.MemberEmission.entry row member) + (List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries rankBytes)) + else [] +PREMISE Aiur.AIR.MemoryTraces.GraphSatisfied +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List Aiur.NativeAIR.KeyCodec.Circuit → Prop +DEFINITION +fun {widths} x x_1 => + Aiur.AIR.MemoryTraces.brecOn (motive := fun {widths} x => List Aiur.NativeAIR.KeyCodec.Circuit → Prop) x + (@Aiur.AIR.MemoryTraces.GraphSatisfied._f) x_1 +PREMISE Aiur.AIR.MemoryTraces.graphLookups +{widths : List Nat} → + Aiur.AIR.MemoryTraces widths → List Aiur.NativeAIR.KeyCodec.Circuit → Option (List Aiur.NativeAIR.LookupRow) +DEFINITION +fun {widths} x x_1 => + Aiur.AIR.MemoryTraces.brecOn (motive := fun {widths} x => + List Aiur.NativeAIR.KeyCodec.Circuit → Option (List Aiur.NativeAIR.LookupRow)) x + (@Aiur.AIR.MemoryTraces.graphLookups._f) x_1 +PREMISE Aiur.AIR.SystemTraces.GraphSatisfied +{program : Aiur.Bytecode.Toplevel} → Aiur.AIR.SystemTraces program → List Aiur.NativeAIR.KeyCodec.Circuit → Prop +DEFINITION +fun {program} traces keys => + traces.functions.GraphSatisfied (List.take program.circuits.size keys) ∧ + traces.memories.GraphSatisfied (List.take program.memorySizes.size (List.drop program.circuits.size keys)) +PREMISE Aiur.AIR.SystemTraces.graphLookupData +{program : Aiur.Bytecode.Toplevel} → + Aiur.AIR.SystemTraces program → List Aiur.NativeAIR.KeyCodec.Circuit → Option Aiur.AIR.GraphLookupData +DEFINITION +fun {program} traces keys => do + let functions ← traces.functions.graphLookups (List.take program.circuits.size keys) + let memories ← + traces.memories.graphLookups (List.take program.memorySizes.size (List.drop program.circuits.size keys)) + let byte1 ← keys[program.circuits.size + program.memorySizes.size]? + let byte2 ← keys[program.circuits.size + program.memorySizes.size + 1]? + let unary ← + byte1.graph.readPreprocessedTraceLookups byte1.widths (Aiur.NativeAIR.finiteTraceMatrix traces.bytes.unary) + (Aiur.NativeAIR.finiteTraceMatrix Aiur.AIR.byte1PreprocessedColumns) + let binary ← + byte2.graph.readPreprocessedTraceLookups byte2.widths (Aiur.NativeAIR.finiteTraceMatrix traces.bytes.binary) + (Aiur.NativeAIR.finiteTraceMatrix Aiur.AIR.byte2PreprocessedColumns) + pure { functions := functions, memories := memories, unary := unary, binary := binary } +PREMISE Aiur.AIR.boundedTraceRow +Nat → (Nat → Aiur.G) → Nat → Aiur.G +DEFINITION +fun width values column => (Array.ofFn fun index => values ↑index)[column]?.getD 0 +PREMISE Aiur.AIR.callAuxiliaries +Aiur.Bytecode.CallRank → Nat +DEFINITION +fun x => + match x with + | Aiur.Bytecode.CallRank.zero => 0 + | Aiur.Bytecode.CallRank.bound => 1 + | Aiur.Bytecode.CallRank.ordered => 6 +PREMISE Aiur.AIR.callGap +Aiur.Bytecode.CallRank → (Nat → Aiur.G) → Nat → Fin 6 → Aiur.G +DEFINITION +fun mode row size => + match (motive := Aiur.Bytecode.CallRank → Fin 6 → Aiur.G) mode with + | Aiur.Bytecode.CallRank.ordered => fun index => row (size + ↑index) + | Aiur.Bytecode.CallRank.zero => fun x => 0 + | Aiur.Bytecode.CallRank.bound => fun x => 0 +PREMISE Aiur.AIR.callRangeQueries +Aiur.Bytecode.CallRank → (Fin 6 → Aiur.G) → List (List Aiur.G) +DEFINITION +fun mode gap => + match mode with + | Aiur.Bytecode.CallRank.ordered => List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries gap) + | Aiur.Bytecode.CallRank.zero => [] + | Aiur.Bytecode.CallRank.bound => [] +PREMISE Aiur.AIR.calleeRank +Aiur.Bytecode.CallRank → (Nat → Aiur.G) → Aiur.G → Nat → Aiur.G +DEFINITION +fun mode row rank size => + match mode with + | Aiur.Bytecode.CallRank.zero => 0 + | Aiur.Bytecode.CallRank.bound => row size + | Aiur.Bytecode.CallRank.ordered => rank + 1 + Aiur.AIR.packRank (Aiur.AIR.callGap mode row size) +PREMISE Aiur.AIR.componentCircuitEmission +(Nat → Aiur.G) → + Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → List Aiur.AIR.MemberEmission → Aiur.AIR.CircuitEmission +DEFINITION +fun row program circuit members => + have ranked := Aiur.AIR.componentMembers program members; + have rankBytes := Aiur.AIR.circuitRankBytes row circuit.layout; + have rankSelector := Aiur.AIR.selectorSum (List.map (fun x => Aiur.AIR.MemberEmission.entry row x) ranked); + have __src := Aiur.AIR.circuitEmission row circuit members; + { members := __src.members, selector := __src.selector, multiplicity := __src.multiplicity, + rankBytes := if ranked.isEmpty = true then fun x => 0 else rankBytes, width := __src.width, + selectorStart := __src.selectorStart, selectorCount := __src.selectorCount, lookupCount := __src.lookupCount, + branchless := __src.branchless, equations := __src.equations, + queries := + List.flatMap (fun x => x.body.queries) members ++ + if ranked.isEmpty = true then [] + else Aiur.AIR.queryParts 1 rankSelector (List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries rankBytes)), + returns := __src.returns } +PREMISE Aiur.AIR.componentColumn +Bool → Nat → Nat +DEFINITION +fun ranked base => base + if ranked = true then 6 else 0 +PREMISE Aiur.AIR.componentFunctionByteQueries +Aiur.Bytecode.Toplevel → List Aiur.AIR.FunctionRow → List (Aiur.G × Aiur.G) +DEFINITION +fun program rows => + List.flatMap (fun row => if row.selector = 1 then Aiur.AIR.FunctionRow.componentByteQueries program row else []) rows +PREMISE Aiur.AIR.componentLookup +Bool → Nat +DEFINITION +fun ranked => 1 + if ranked = true then 3 else 0 +PREMISE Aiur.AIR.componentMembers +Aiur.Bytecode.Toplevel → List Aiur.AIR.MemberEmission → List Aiur.AIR.MemberEmission +DEFINITION +fun program members => List.filter (fun member => (program.componentFor member.functionIndex).ranked) members +PREMISE Aiur.AIR.emitCallRow +(Nat → Aiur.G) → Aiur.G → Aiur.Bytecode.FunIdx → Array Aiur.G → Nat → Aiur.Bytecode.CallRank → Aiur.AIR.OpEmission +DEFINITION +fun row rank function inputs size mode => + have outputs := Aiur.AIR.rowAdvice row 0 size; + have gap := Aiur.AIR.callGap mode row size; + have request := + { function := function, inputs := inputs, outputs := Aiur.AIR.rowValues outputs, + rank := Aiur.AIR.calleeRank mode row rank size }; + { outputs := outputs, used := size + Aiur.AIR.callAuxiliaries mode, + queries := Aiur.AIR.functionMessage request :: Aiur.AIR.callRangeQueries mode gap, calls := [(request, gap)] } +PREMISE Aiur.AIR.emitComponentMember +(Nat → Aiur.G) → Aiur.G → Nat → Nat → Aiur.Bytecode.Toplevel → Aiur.Bytecode.FunIdx → Option Aiur.AIR.MemberEmission +DEFINITION +fun row rank base selectorBase program functionIndex => + have ranked := (program.componentFor functionIndex).ranked; + Aiur.AIR.emitMember row (if ranked = true then rank else 0) (Aiur.AIR.componentColumn ranked base) + (Aiur.AIR.componentLookup ranked) selectorBase program functionIndex (program.callRanksFor functionIndex) +PREMISE Aiur.AIR.emitComponentMembers +(Nat → Aiur.G) → + Aiur.G → Nat → Nat → Aiur.Bytecode.Toplevel → List Aiur.Bytecode.FunIdx → Option (List Aiur.AIR.MemberEmission) +DEFINITION +fun row rank base selectorBase program x => + List.brecOn (motive := fun x => Nat → Option (List Aiur.AIR.MemberEmission)) x + (Aiur.AIR.emitComponentMembers._f row rank base program) selectorBase +PREMISE Aiur.AIR.emitNativeCircuitWitness +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → (Nat → Aiur.G) → Option Aiur.AIR.CircuitWitness +DEFINITION +fun program circuit values => + have row := Aiur.AIR.boundedTraceRow circuit.layout.width values; + do + let emission ← Aiur.Bytecode.Circuit.emitNativeRow row program circuit + pure { circuit := circuit, values := row, emission := emission } +PREMISE Aiur.Bytecode.Circuit.emitComponentRow +(Nat → Aiur.G) → Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.AIR.CircuitEmission +DEFINITION +fun row program circuit => + have rank := Aiur.AIR.packRank (Aiur.AIR.circuitRankBytes row circuit.layout); + have base := circuit.layout.inputSize + circuit.layout.selectors + 1; + do + let members ← Aiur.AIR.emitComponentMembers row rank base circuit.layout.inputSize program circuit.members.toList + pure (Aiur.AIR.componentCircuitEmission row program circuit members) +PREMISE Aiur.Bytecode.Circuit.emitNativeRow +(Nat → Aiur.G) → Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.AIR.CircuitEmission +DEFINITION +fun row program circuit => + if program.callComponents.isEmpty = true then Aiur.Bytecode.Circuit.emitRow row program circuit + else Aiur.Bytecode.Circuit.emitComponentRow row program circuit +PREMISE Aiur.Bytecode.Op.constrainedCalls +Aiur.Bytecode.Op → List Aiur.Bytecode.FunIdx +DEFINITION +fun x => + match x with + | Aiur.Bytecode.Op.call function a outputSize false => [function] + | x => [] +PREMISE Aiur.Bytecode.Toplevel.ComponentEdge +Aiur.Bytecode.Toplevel → Aiur.Bytecode.FunIdx → Aiur.Bytecode.FunIdx → Prop +DEFINITION +fun program parent child => + ∃ parentComponent childComponent, + program.callComponents[parent]? = some parentComponent ∧ + program.callComponents[child]? = some childComponent ∧ parentComponent.permits childComponent = true +PREMISE Aiur.Bytecode.Toplevel.componentFor +Aiur.Bytecode.Toplevel → Aiur.Bytecode.FunIdx → Aiur.Bytecode.CallComponent +DEFINITION +fun program function => program.callComponents[function]?.getD default +PREMISE Aiur.Bytecode.Toplevel.componentRowRank +Aiur.Bytecode.Toplevel → Aiur.Bytecode.FunIdx → (Fin 6 → Aiur.G) → Aiur.G +DEFINITION +fun program functionIndex rankBytes => + if (program.componentFor functionIndex).ranked = true then Aiur.AIR.packRank rankBytes else 0 +PREMISE Aiur.Bytecode.branchCalls +Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → List Aiur.Bytecode.FunIdx +DEFINITION +fun branches fallback => + List.flatMap (fun pair => pair.snd.collectConstrainedCallees.toList) branches.toList ++ + List.flatMap (fun block => block.collectConstrainedCallees.toList) fallback.toList +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint +Aiur.Bytecode.Toplevel → Nat → Aiur.NativeAIR.CircuitEmitter.Emission → Bool +DEFINITION +fun program width emission => + decide (Aiur.NativeAIR.CircuitEmitter.Emission.componentReadBound program emission ≤ width) && + (decide (0 < emission.lookupCount) && + emission.queries.all fun part => decide (0 < part.slot) && decide (part.slot < emission.lookupCount)) +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.componentReadBound +Aiur.Bytecode.Toplevel → Aiur.NativeAIR.CircuitEmitter.Emission → Nat +DEFINITION +fun program emission => + List.foldl (fun bound member => max bound member.readBound) + (emission.selectorStart + emission.selectorCount + 1 + + if (Aiur.NativeAIR.CircuitEmitter.componentMembers program emission.members).isEmpty = true then 0 else 6) + emission.members +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.footprint +Nat → Aiur.NativeAIR.CircuitEmitter.Emission → Bool +DEFINITION +fun width emission => + decide (emission.readBound ≤ width) && + (decide (0 < emission.lookupCount) && + emission.queries.all fun part => decide (0 < part.slot) && decide (part.slot < emission.lookupCount)) +PREMISE Aiur.NativeAIR.CircuitEmitter.Emission.genericLimits +Aiur.NativeAIR.CircuitEmitter.Emission → Bool +DEFINITION +fun emission => + decide (4 ≤ emission.lookupCount) && + emission.members.all fun member => decide (member.body.lookup ≤ emission.lookupCount) +PREMISE Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit +Aiur.NativeAIR.GraphWidths → + Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeAIR.CircuitEmitter.Compiled +DEFINITION +fun widths program circuit => do + let compiled ← Aiur.NativeAIR.CircuitEmitter.compileCircuit widths program circuit + if + (Aiur.NativeAIR.CircuitEmitter.Emission.footprint widths.main compiled.emission && + compiled.emission.genericLimits) = + true then + some compiled + else none +PREMISE Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit +Aiur.NativeAIR.GraphWidths → + Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeAIR.CircuitEmitter.Compiled +DEFINITION +fun widths program circuit => + if program.validCallComponents = true then do + let emission ← Aiur.NativeAIR.CircuitEmitter.emitComponentCircuit program circuit + if Aiur.NativeAIR.CircuitEmitter.Emission.componentFootprint program widths.main emission = true then do + let base ← Aiur.NativeAIR.Compiler.compileBase widths emission.lookups emission.equations + pure { emission := emission, base := base } + else none + else none +PREMISE Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit +Aiur.NativeAIR.GraphWidths → + Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeAIR.CircuitEmitter.Compiled +DEFINITION +fun widths program circuit => + if program.callComponents.isEmpty = true then + Aiur.NativeAIR.CircuitEmitter.compileCheckedCircuit widths program circuit + else Aiur.NativeAIR.CircuitEmitter.compileComponentCircuit widths program circuit +PREMISE Aiur.NativeAIR.CircuitEmitter.componentCircuitEmission +Aiur.Bytecode.Toplevel → + Aiur.Bytecode.Circuit → List Aiur.NativeAIR.CircuitEmitter.Member → Aiur.NativeAIR.CircuitEmitter.Emission +DEFINITION +fun program circuit members => + have ranked := Aiur.NativeAIR.CircuitEmitter.componentMembers program members; + have bytes := Aiur.NativeAIR.CircuitEmitter.rankBytes circuit.layout; + have rankSelector := Aiur.NativeAIR.BlockEmitter.sum (List.map (fun x => x.entry) ranked); + have __src := Aiur.NativeAIR.CircuitEmitter.circuitEmission circuit members; + { members := __src.members, selector := __src.selector, multiplicity := __src.multiplicity, + rankBytes := if ranked.isEmpty = true then fun x => Aiur.NativeAIR.Expr.konst 0 else bytes, width := __src.width, + selectorStart := __src.selectorStart, selectorCount := __src.selectorCount, lookupCount := __src.lookupCount, + branchless := __src.branchless, equations := __src.equations, + queries := + List.flatMap (fun x => x.body.queries) members ++ + if ranked.isEmpty = true then [] + else Aiur.NativeAIR.LookupEmitter.queryParts 1 rankSelector (Aiur.NativeAIR.OpEmitter.rangeSix bytes), + returns := __src.returns } +PREMISE Aiur.NativeAIR.CircuitEmitter.componentMembers +Aiur.Bytecode.Toplevel → List Aiur.NativeAIR.CircuitEmitter.Member → List Aiur.NativeAIR.CircuitEmitter.Member +DEFINITION +fun program members => List.filter (fun member => (program.componentFor member.functionIndex).ranked) members +PREMISE Aiur.NativeAIR.CircuitEmitter.emitComponentCircuit +Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeAIR.CircuitEmitter.Emission +DEFINITION +fun program circuit => + have rank := Aiur.NativeAIR.OpEmitter.packSix (Aiur.NativeAIR.CircuitEmitter.rankBytes circuit.layout); + have base := circuit.layout.inputSize + circuit.layout.selectors + 1; + do + let members ← + Aiur.NativeAIR.CircuitEmitter.emitComponentMembers rank base circuit.layout.inputSize program circuit.members.toList + pure (Aiur.NativeAIR.CircuitEmitter.componentCircuitEmission program circuit members) +PREMISE Aiur.NativeAIR.CircuitEmitter.emitComponentMember +Aiur.NativeAIR.Expr → Nat → Nat → Aiur.Bytecode.Toplevel → Nat → Option Aiur.NativeAIR.CircuitEmitter.Member +DEFINITION +fun rank base selectorBase program functionIndex => + have ranked := (program.componentFor functionIndex).ranked; + Aiur.NativeAIR.CircuitEmitter.emitMember (if ranked = true then rank else Aiur.NativeAIR.Expr.konst 0) + (Aiur.AIR.componentColumn ranked base) (Aiur.AIR.componentLookup ranked) selectorBase program functionIndex + (program.callRanksFor functionIndex) +PREMISE Aiur.NativeAIR.CircuitEmitter.emitComponentMembers +Aiur.NativeAIR.Expr → Nat → Nat → Aiur.Bytecode.Toplevel → List Nat → Option (List Aiur.NativeAIR.CircuitEmitter.Member) +DEFINITION +fun rank base selectorBase program x => + List.brecOn (motive := fun x => Nat → Option (List Aiur.NativeAIR.CircuitEmitter.Member)) x + (Aiur.NativeAIR.CircuitEmitter.emitComponentMembers._f rank base program) selectorBase +PREMISE Aiur.NativeAIR.Graph.RowSatisfied +Aiur.NativeAIR.Graph → Aiur.NativeAIR.Values Aiur.G → Prop +DEFINITION +fun graph values => + ∃ buffer, + graph.sweep Aiur.NativeAIR.goldilocksOps values = some buffer ∧ + Aiur.NativeAIR.Compiler.Vanishes Aiur.NativeAIR.goldilocksOps buffer graph.zeros +PREMISE Aiur.NativeAIR.Graph.TraceSatisfied +Aiur.NativeAIR.Graph → Aiur.NativeAIR.GraphWidths → {height : Nat} → (Fin height → Nat → Aiur.G) → Prop +DEFINITION +fun graph widths {height} matrix => + ∀ (index : Fin height), graph.RowSatisfied (Aiur.NativeAIR.traceRowValues widths matrix index) +PREMISE Aiur.NativeAIR.Graph.readLookups +Aiur.NativeAIR.Graph → Aiur.NativeAIR.Values Aiur.G → Option Aiur.NativeAIR.LookupRow +DEFINITION +fun graph values => do + let buffer ← graph.sweep Aiur.NativeAIR.goldilocksOps values + List.mapM (Aiur.NativeAIR.readLookup buffer) graph.lookups +PREMISE Aiur.NativeAIR.Graph.readPreprocessedTraceLookups +Aiur.NativeAIR.Graph → + Aiur.NativeAIR.GraphWidths → + {height : Nat} → (Fin height → Nat → Aiur.G) → (Fin height → Nat → Aiur.G) → Option (List Aiur.NativeAIR.LookupRow) +DEFINITION +fun graph widths {height} matrix preprocessed => + List.mapM + (fun index => graph.readLookups (Aiur.NativeAIR.traceRowValuesWithPreprocessed widths matrix preprocessed index)) + (List.ofFn id) +PREMISE Aiur.NativeAIR.Graph.readTraceLookups +Aiur.NativeAIR.Graph → + Aiur.NativeAIR.GraphWidths → {height : Nat} → (Fin height → Nat → Aiur.G) → Option (List Aiur.NativeAIR.LookupRow) +DEFINITION +fun graph widths {height} matrix => + List.mapM (fun index => graph.readLookups (Aiur.NativeAIR.traceRowValues widths matrix index)) (List.ofFn id) +PREMISE Aiur.NativeAIR.OpEmitter.callGapExpr +Aiur.Bytecode.CallRank → Nat → Nat → Fin 6 → Aiur.NativeAIR.Expr +DEFINITION +fun mode first size => + match (motive := Aiur.Bytecode.CallRank → Fin 6 → Aiur.NativeAIR.Expr) mode with + | Aiur.Bytecode.CallRank.ordered => fun index => (Aiur.NativeAIR.mainCurrent (first + size + ↑index)).expr + | Aiur.Bytecode.CallRank.zero => fun x => Aiur.NativeAIR.Expr.konst 0 + | Aiur.Bytecode.CallRank.bound => fun x => Aiur.NativeAIR.Expr.konst 0 +PREMISE Aiur.NativeAIR.OpEmitter.callRangeExprs +Aiur.Bytecode.CallRank → (Fin 6 → Aiur.NativeAIR.Expr) → List (List Aiur.NativeAIR.Expr) +DEFINITION +fun mode gap => + match mode with + | Aiur.Bytecode.CallRank.ordered => Aiur.NativeAIR.OpEmitter.rangeSix gap + | Aiur.Bytecode.CallRank.zero => [] + | Aiur.Bytecode.CallRank.bound => [] +PREMISE Aiur.NativeAIR.OpEmitter.calleeRankExpr +Aiur.Bytecode.CallRank → Aiur.NativeAIR.Expr → Nat → Nat → Aiur.NativeAIR.Expr +DEFINITION +fun mode rank first size => + match mode with + | Aiur.Bytecode.CallRank.zero => Aiur.NativeAIR.Expr.konst 0 + | Aiur.Bytecode.CallRank.bound => (Aiur.NativeAIR.mainCurrent (first + size)).expr + | Aiur.Bytecode.CallRank.ordered => + (rank.frontAdd (Aiur.NativeAIR.Expr.konst 1)).frontAdd + (Aiur.NativeAIR.OpEmitter.packSix (Aiur.NativeAIR.OpEmitter.callGapExpr mode first size)) +PREMISE Aiur.NativeAIR.emissionLookupRow +Aiur.AIR.CircuitEmission → Aiur.NativeAIR.LookupRow +DEFINITION +fun emission => List.ofFn fun slot => emission.lookup ↑slot +PREMISE Aiur.NativeAIR.finiteTraceMatrix +{height width : Nat} → (Fin height → Fin width → Aiur.G) → Fin height → Nat → Aiur.G +DEFINITION +fun {height width} matrix row column => (Array.ofFn (matrix row))[column]?.getD 0 +PREMISE Aiur.NativeAIR.graphFunctionProviders +List Aiur.NativeAIR.LookupRow → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun rows => List.filterMap Aiur.NativeAIR.graphRowProvider rows +PREMISE Aiur.NativeAIR.graphFunctionQueries +List Aiur.NativeAIR.LookupRow → List (List Aiur.G) +DEFINITION +fun rows => List.flatMap Aiur.NativeAIR.graphRowQueries rows +PREMISE Aiur.NativeAIR.graphLookupProvider +Aiur.G × List Aiur.G → Aiur.AIR.Provider (List Aiur.G) +DEFINITION +fun lookup => (lookup.snd, 0 - lookup.fst) +PREMISE Aiur.NativeAIR.graphRowProvider +Aiur.NativeAIR.LookupRow → Option (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun row => Option.map (fun lookup => (lookup.snd, 0 - lookup.fst)) row[0]? +PREMISE Aiur.NativeAIR.graphRowQueries +Aiur.NativeAIR.LookupRow → List (List Aiur.G) +DEFINITION +fun row => + List.filterMap + (fun slot => + if slot = 0 then none + else do + let lookup ← row[slot]? + if lookup.fst = 1 then some lookup.snd else none) + (List.range (List.length row)) +PREMISE Aiur.NativeAIR.graphTableProviders +List Aiur.NativeAIR.LookupRow → List (Aiur.AIR.Provider (List Aiur.G)) +DEFINITION +fun rows => List.flatMap (fun row => List.map Aiur.NativeAIR.graphLookupProvider row) rows +PREMISE Aiur.NativeAIR.traceRowValues +Aiur.NativeAIR.GraphWidths → {height : Nat} → (Fin height → Nat → Aiur.G) → Fin height → Aiur.NativeAIR.Values Aiur.G +DEFINITION +fun widths {height} matrix index => + { + columns := fun x x_1 => + match x, x_1 with + | Aiur.NativeAIR.Source.main, Aiur.NativeAIR.RowOffset.current => Array.ofFn fun column => matrix index ↑column + | Aiur.NativeAIR.Source.main, Aiur.NativeAIR.RowOffset.next => + Array.ofFn fun column => matrix (Aiur.AIR.memoryNextIndex index) ↑column + | Aiur.NativeAIR.Source.preprocessed, x => Array.replicate widths.preprocessed 0 + | Aiur.NativeAIR.Source.stage2, x => Array.replicate widths.stage2 0, + publics := Array.replicate widths.publics 0, isFirstRow := if ↑index = 0 then 1 else 0, + isLastRow := if ↑index + 1 = height then 1 else 0, isTransition := if ↑index + 1 < height then 1 else 0 } +PREMISE Aiur.NativeAIR.traceRowValuesWithPreprocessed +Aiur.NativeAIR.GraphWidths → + {height : Nat} → (Fin height → Nat → Aiur.G) → (Fin height → Nat → Aiur.G) → Fin height → Aiur.NativeAIR.Values Aiur.G +DEFINITION +fun widths {height} matrix preprocessed index => + have __src := Aiur.NativeAIR.traceRowValues widths matrix index; + { + columns := fun source offset => + match source, offset with + | Aiur.NativeAIR.Source.preprocessed, Aiur.NativeAIR.RowOffset.current => + Array.ofFn fun column => preprocessed index ↑column + | Aiur.NativeAIR.Source.preprocessed, Aiur.NativeAIR.RowOffset.next => + Array.ofFn fun column => preprocessed (Aiur.AIR.memoryNextIndex index) ↑column + | source, offset => (Aiur.NativeAIR.traceRowValues widths matrix index).columns source offset, + publics := __src.publics, isFirstRow := __src.isFirstRow, isLastRow := __src.isLastRow, + isTransition := __src.isTransition } PREMISE Aiur.Bytecode.CallRank.zero Aiur.Bytecode.CallRank PREMISE Aiur.Bytecode.CallRank.bound @@ -13874,9 +16251,13 @@ fun row left right third values => do let sum ← Option.map (fun z => (x.add y).add z) (Aiur.AIR.readRowWord values indices) __do_jp sum PREMISE Aiur.AIR.emitOp -(Nat → Aiur.G) → Aiur.G → Aiur.G → Aiur.Bytecode.Op → Array Aiur.AIR.RowValue → Option Aiur.AIR.OpEmission +(Nat → Aiur.G) → + Aiur.G → + Aiur.G → + Aiur.Bytecode.Op → + Array Aiur.AIR.RowValue → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.AIR.OpEmission DEFINITION -fun row selector rank op values => +fun row selector rank op values callRanks => match op with | Aiur.Bytecode.Op.const value => some { outputs := #[Aiur.AIR.RowValue.konst value] } | Aiur.Bytecode.Op.add a b => do @@ -13908,16 +16289,9 @@ fun row selector rank op values => if unconstrained = true then some (Aiur.AIR.emitAdvice row size) else do let inputs ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) indices - have outputs : Array Aiur.AIR.RowValue := Aiur.AIR.rowAdvice row 0 size - have gap : Fin 6 → Aiur.G := fun index => row (size + ↑index) - have request : Aiur.Bytecode.AIR.Call := - { function := function, inputs := inputs, outputs := Aiur.AIR.rowValues outputs, - rank := rank + 1 + Aiur.AIR.packRank gap } pure - { outputs := outputs, used := size + 6, - queries := - Aiur.AIR.functionMessage request :: List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries gap), - calls := [(request, gap)] } + (Aiur.AIR.emitCallRow row rank function inputs size + (callRanks[function]?.getD Aiur.Bytecode.CallRank.ordered)) | Aiur.Bytecode.Op.store indices => do let contents ← Aiur.Bytecode.AIR.readValues (Aiur.AIR.rowValues values) indices pure @@ -13966,21 +16340,27 @@ PREMISE Aiur.AIR.OpsEmission.mk Array Aiur.AIR.RowValue → Nat → List Aiur.G → List (List Aiur.G) → List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → Aiur.AIR.OpsEmission PREMISE Aiur.AIR.emitOps -(Nat → Aiur.G) → Aiur.G → Aiur.G → List Aiur.Bytecode.Op → Array Aiur.AIR.RowValue → Nat → Option Aiur.AIR.OpsEmission +(Nat → Aiur.G) → + Aiur.G → + Aiur.G → + List Aiur.Bytecode.Op → + Array Aiur.AIR.RowValue → Nat → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.AIR.OpsEmission DEFINITION -fun row selector rank x x_1 x_2 => - List.brecOn (motive := fun x => Array Aiur.AIR.RowValue → Nat → Option Aiur.AIR.OpsEmission) x - (Aiur.AIR.emitOps._f row selector rank) x_1 x_2 +fun row selector rank ops values column callRanks => + List.brecOn (motive := fun ops => Array Aiur.AIR.RowValue → Nat → Option Aiur.AIR.OpsEmission) ops + (Aiur.AIR.emitOps._f row selector rank callRanks) values column PREMISE Aiur.AIR.CallsEmitted -Aiur.G → Aiur.G → List Aiur.G → List (List Aiur.G) → List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → Prop +Aiur.G → + Aiur.G → + List Aiur.G → + List (List Aiur.G) → + List (Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)) → optParam (Array Aiur.Bytecode.CallRank) #[] → Prop DEFINITION -fun rank selector equations queries calls => +fun rank selector equations queries calls callRanks => ∀ (edge : Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)), edge ∈ calls → Aiur.AIR.functionMessage edge.fst ∈ queries ∧ - List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries edge.snd) ⊆ queries ∧ - Aiur.AIR.EquationAvailable equations - (selector * Aiur.AIR.callOrderConstraint rank edge.fst.rank (Aiur.AIR.packRank edge.snd)) + Aiur.AIR.CallRankChecks callRanks rank selector equations (fun x => x ∈ queries) edge PREMISE Aiur.Bytecode.MatchPolynomials.mk ∀ {selector : Aiur.Bytecode.SelIdx → Aiur.G} {scrutinee : Aiur.G} {branches : Array (Aiur.G × Aiur.Bytecode.Block)} {fallback : Option Aiur.Bytecode.Block}, @@ -13995,7 +16375,7 @@ PREMISE Aiur.Bytecode.MatchPolynomials.mk (Aiur.Bytecode.Block.selectorFlow selector block).entry * ((scrutinee - pair.fst) * inverse - 1) = 0) → Aiur.Bytecode.MatchPolynomials selector scrutinee branches fallback PREMISE Aiur.AIR.RowContext.mk -Aiur.Bytecode.FunIdx → Nat → Aiur.G → Aiur.AIR.RowContext +Aiur.Bytecode.FunIdx → Nat → Aiur.G → Array Aiur.Bytecode.CallRank → Aiur.AIR.RowContext PREMISE Aiur.AIR.QueryPart.mk Nat → Aiur.G → List Aiur.G → Aiur.AIR.QueryPart PREMISE Aiur.AIR.queryParts @@ -14179,17 +16559,13 @@ Aiur.AIR.BlockEmission → Aiur.G → List Aiur.G → Prop DEFINITION fun emission selector message => ∃ part, part ∈ emission.queries ∧ part.selector = selector ∧ part.message = message PREMISE Aiur.AIR.BlockEmission.TracksCalls -Aiur.G → Aiur.AIR.BlockEmission → Prop +Aiur.G → Aiur.AIR.BlockEmission → optParam (Array Aiur.Bytecode.CallRank) #[] → Prop DEFINITION -fun rank emission => +fun rank emission callRanks => ∀ (part : Aiur.G × Aiur.Bytecode.AIR.Call × (Fin 6 → Aiur.G)), part ∈ emission.calls → emission.HasQuery part.fst (Aiur.AIR.functionMessage part.snd.fst) ∧ - (∀ (message : List Aiur.G), - message ∈ List.map Aiur.AIR.rangeMessage (Aiur.AIR.rankByteQueries part.snd.snd) → - emission.HasQuery part.fst message) ∧ - Aiur.AIR.EquationAvailable emission.equations - (part.fst * Aiur.AIR.callOrderConstraint rank part.snd.fst.rank (Aiur.AIR.packRank part.snd.snd)) + Aiur.AIR.CallRankChecks callRanks rank part.fst emission.equations (emission.HasQuery part.fst) part.snd PREMISE Aiur.AIR.RowInputs Nat → Array Aiur.G → Array Aiur.AIR.RowValue → Prop DEFINITION @@ -14205,11 +16581,14 @@ PREMISE Aiur.Bytecode.Function.emitRow (Nat → Aiur.G) → (Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.Bytecode.FunIdx → - Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.Bytecode.Function → Option Aiur.AIR.BlockEmission + Aiur.G → + Array Aiur.AIR.RowValue → + Nat → + Nat → Aiur.Bytecode.Function → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.AIR.BlockEmission DEFINITION -fun row selector functionIndex rank values column lookup function => +fun row selector functionIndex rank values column lookup function callRanks => Aiur.Bytecode.Block.emitRow row selector - { function := functionIndex, inputSize := function.layout.inputSize, rank := rank } + { function := functionIndex, inputSize := function.layout.inputSize, rank := rank, callRanks := callRanks } (Aiur.Bytecode.Block.selectorFlow selector function.body).entry values column lookup function.body PREMISE Aiur.AIR.gateCount Aiur.G → Nat @@ -14275,13 +16654,18 @@ fun row member => (Aiur.Bytecode.Block.selectorFlow (Aiur.AIR.MemberEmission.selector row member) member.function.body).entry PREMISE Aiur.AIR.emitMember (Nat → Aiur.G) → - Aiur.G → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → Aiur.Bytecode.FunIdx → Option Aiur.AIR.MemberEmission + Aiur.G → + Nat → + Nat → + Nat → + Aiur.Bytecode.Toplevel → + Aiur.Bytecode.FunIdx → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.AIR.MemberEmission DEFINITION -fun row rank column lookup selectorBase program functionIndex => do +fun row rank column lookup selectorBase program functionIndex callRanks => do let function ← program.functions[functionIndex]? let body ← Aiur.Bytecode.Function.emitRow row (fun index => row (selectorBase + index)) functionIndex rank - (Aiur.AIR.rowAdvice row 0 function.layout.inputSize) column lookup function + (Aiur.AIR.rowAdvice row 0 function.layout.inputSize) column lookup function callRanks pure { functionIndex := functionIndex, function := function, selectorBase := selectorBase, body := body } PREMISE Aiur.AIR.emitMembers (Nat → Aiur.G) → @@ -14350,12 +16734,12 @@ fun row program circuit => pure (Aiur.AIR.circuitEmission row circuit members) PREMISE Aiur.AIR.MemberEmission.FromProgram.mk ∀ {row : Nat → Aiur.G} {rank : Aiur.G} {column lookup : Nat} {program : Aiur.Bytecode.Toplevel} - {member : Aiur.AIR.MemberEmission}, + {member : Aiur.AIR.MemberEmission} {callRanks : optParam (Array Aiur.Bytecode.CallRank) #[]}, program.functions[member.functionIndex]? = some member.function → Aiur.Bytecode.Function.emitRow row (Aiur.AIR.MemberEmission.selector row member) member.functionIndex rank - (Aiur.AIR.rowAdvice row 0 member.function.layout.inputSize) column lookup member.function = + (Aiur.AIR.rowAdvice row 0 member.function.layout.inputSize) column lookup member.function callRanks = some member.body → - Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member + Aiur.AIR.MemberEmission.FromProgram row rank column lookup program member callRanks PREMISE Aiur.AIR.CircuitEmission.QueriesIn Aiur.AIR.CircuitEmission → List (List Aiur.G) → Prop DEFINITION @@ -14632,11 +17016,17 @@ DEFINITION fun functions circuits => ∀ (circuit : Aiur.Bytecode.Circuit), circuit ∈ circuits → Aiur.Bytecode.MembersConstrained functions circuit.members PREMISE Aiur.Bytecode.Op.lookupUsage -Aiur.Bytecode.Op → Nat +Aiur.Bytecode.Op → optParam (Array Aiur.Bytecode.CallRank) #[] → Nat DEFINITION -fun x => - match x with - | Aiur.Bytecode.Op.call a a_1 outputSize unconstrained => if unconstrained = true then 0 else 4 +fun op callRanks => + match op with + | Aiur.Bytecode.Op.call function a outputSize unconstrained => + if unconstrained = true then 0 + else + match callRanks[function]?.getD Aiur.Bytecode.CallRank.ordered with + | Aiur.Bytecode.CallRank.zero => 1 + | Aiur.Bytecode.CallRank.bound => 1 + | Aiur.Bytecode.CallRank.ordered => 4 | Aiur.Bytecode.Op.store a => 1 | Aiur.Bytecode.Op.load size a => 1 | Aiur.Bytecode.Op.u8BitDecomposition a => 1 @@ -14655,20 +17045,20 @@ fun x => | Aiur.Bytecode.Op.u32LessThan a a_1 => 6 | x => 0 PREMISE Aiur.Bytecode.Ctrl.lookupUsage -Aiur.Bytecode.Ctrl → Nat +Aiur.Bytecode.Ctrl → optParam (Array Aiur.Bytecode.CallRank) #[] → Nat DEFINITION -fun a => Aiur.Bytecode.Ctrl.lookupUsage._mutual (PSum.inl a) +fun ctrl callRanks => Aiur.Bytecode.Ctrl.lookupUsage._mutual callRanks (PSum.inl ctrl) PREMISE Aiur.Bytecode.Block.lookupUsage -Aiur.Bytecode.Block → Nat +Aiur.Bytecode.Block → optParam (Array Aiur.Bytecode.CallRank) #[] → Nat DEFINITION -fun block => Aiur.Bytecode.Ctrl.lookupUsage._mutual (PSum.inr block) +fun block callRanks => Aiur.Bytecode.Ctrl.lookupUsage._mutual callRanks (PSum.inr block) PREMISE Aiur.Bytecode.branchLookupUsage -Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → Nat +Array (Aiur.G × Aiur.Bytecode.Block) → Option Aiur.Bytecode.Block → optParam (Array Aiur.Bytecode.CallRank) #[] → Nat DEFINITION -fun branches fallback => +fun branches fallback callRanks => List.foldl Nat.max 0 - (List.map (fun pair => pair.snd.lookupUsage) branches.toList ++ - List.map (fun block => block.lookupUsage) fallback.toList) + (List.map (fun pair => pair.snd.lookupUsage callRanks) branches.toList ++ + List.map (fun block => block.lookupUsage callRanks) fallback.toList) PREMISE Aiur.Bytecode.Function.LookupLayout Aiur.Bytecode.Function → Prop DEFINITION @@ -15745,19 +18135,23 @@ fun bytes => Aiur.NativeAIR.OpEmitter.rangePair (bytes 4) (bytes 5)] PREMISE Aiur.NativeAIR.OpEmitter.emitCall Aiur.NativeAIR.Expr → - Aiur.NativeAIR.Expr → Nat → Nat → Array Aiur.NativeAIR.RowExpr → Nat → Aiur.NativeAIR.OpEmitter.Emission + Aiur.NativeAIR.Expr → + Nat → + Nat → + Array Aiur.NativeAIR.RowExpr → + Nat → optParam Aiur.Bytecode.CallRank Aiur.Bytecode.CallRank.ordered → Aiur.NativeAIR.OpEmitter.Emission DEFINITION -fun _selector rank first function inputs size => +fun _selector rank first function inputs size mode => have outputs := Aiur.NativeAIR.OpEmitter.advice first size; - have gap := fun index => (Aiur.NativeAIR.mainCurrent (first + size + ↑index)).expr; - have child := (rank.frontAdd (Aiur.NativeAIR.Expr.konst 1)).frontAdd (Aiur.NativeAIR.OpEmitter.packSix gap); - { outputs := outputs, used := size + 6, + have gap := Aiur.NativeAIR.OpEmitter.callGapExpr mode first size; + have child := Aiur.NativeAIR.OpEmitter.calleeRankExpr mode rank first size; + { outputs := outputs, used := size + Aiur.AIR.callAuxiliaries mode, queries := ([Aiur.NativeAIR.Expr.konst 0, Aiur.NativeAIR.Expr.konst (Aiur.G.ofNat function)] ++ (Aiur.NativeAIR.OpEmitter.rowExprs inputs).toList ++ (Aiur.NativeAIR.OpEmitter.rowExprs outputs).toList ++ [child]) :: - Aiur.NativeAIR.OpEmitter.rangeSix gap, + Aiur.NativeAIR.OpEmitter.callRangeExprs mode gap, calls := [{ function := function, inputs := Aiur.NativeAIR.OpEmitter.rowExprs inputs, outputs := Aiur.NativeAIR.OpEmitter.rowExprs outputs, rank := child, gap := gap }] } @@ -15816,9 +18210,13 @@ fun selector left right => (right[↑index]?.getD (Aiur.NativeAIR.RowExpr.konst 0)).expr) } PREMISE Aiur.NativeAIR.OpEmitter.emitOp Aiur.NativeAIR.Expr → - Aiur.NativeAIR.Expr → Nat → Aiur.Bytecode.Op → Array Aiur.NativeAIR.RowExpr → Option Aiur.NativeAIR.OpEmitter.Emission + Aiur.NativeAIR.Expr → + Nat → + Aiur.Bytecode.Op → + Array Aiur.NativeAIR.RowExpr → + optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.NativeAIR.OpEmitter.Emission DEFINITION -fun selector rank first op rows => +fun selector rank first op rows callRanks => match op with | Aiur.Bytecode.Op.const value => some (Aiur.NativeAIR.OpEmitter.fromScalar { output := Aiur.NativeAIR.RowExpr.konst value }) @@ -15841,7 +18239,9 @@ fun selector rank first op rows => if unconstrained = true then some (Aiur.NativeAIR.OpEmitter.emitAdvice first size) else do let __do_lift ← Aiur.NativeAIR.OpEmitter.select rows indices - pure (Aiur.NativeAIR.OpEmitter.emitCall selector rank first function __do_lift size) + pure + (Aiur.NativeAIR.OpEmitter.emitCall selector rank first function __do_lift size + (callRanks[function]?.getD Aiur.Bytecode.CallRank.ordered)) | Aiur.Bytecode.Op.store indices => do let __do_lift ← Aiur.NativeAIR.OpEmitter.select rows indices pure (Aiur.NativeAIR.OpEmitter.emitStore first __do_lift) @@ -15944,11 +18344,13 @@ fun values emission => do PREMISE Aiur.NativeAIR.OpEmitter.emitOps Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → - List Aiur.Bytecode.Op → Array Aiur.NativeAIR.RowExpr → Nat → Option Aiur.NativeAIR.OpEmitter.OpsEmission + List Aiur.Bytecode.Op → + Array Aiur.NativeAIR.RowExpr → + Nat → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.NativeAIR.OpEmitter.OpsEmission DEFINITION -fun selector rank x x_1 x_2 => - List.brecOn (motive := fun x => Array Aiur.NativeAIR.RowExpr → Nat → Option Aiur.NativeAIR.OpEmitter.OpsEmission) x - (Aiur.NativeAIR.OpEmitter.emitOps._f selector rank) x_1 x_2 +fun selector rank ops rows column callRanks => + List.brecOn (motive := fun ops => Array Aiur.NativeAIR.RowExpr → Nat → Option Aiur.NativeAIR.OpEmitter.OpsEmission) + ops (Aiur.NativeAIR.OpEmitter.emitOps._f selector rank callRanks) rows column PREMISE Aiur.NativeAIR.LookupEmitter.addArgs List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr → List Aiur.NativeAIR.Expr DEFINITION @@ -16016,7 +18418,7 @@ Array Aiur.NativeAIR.Expr → Aiur.Bytecode.Block → Option Aiur.NativeAIR.Expr DEFINITION fun selectors block => Aiur.NativeAIR.BlockEmitter.ctrlSelector._mutual selectors (PSum.inr block) PREMISE Aiur.NativeAIR.BlockEmitter.Context.mk -Nat → Nat → Aiur.NativeAIR.Expr → Aiur.NativeAIR.BlockEmitter.Context +Nat → Nat → Aiur.NativeAIR.Expr → Array Aiur.Bytecode.CallRank → Aiur.NativeAIR.BlockEmitter.Context PREMISE Aiur.NativeAIR.BlockEmitter.ReturnExpr.mk Aiur.NativeAIR.Expr → Nat → @@ -16255,7 +18657,8 @@ fun selectors index => selectors[index]?.getD 0 PREMISE Aiur.NativeAIR.BlockEmitter.Context.valued Aiur.NativeAIR.BlockEmitter.Context → Aiur.G → Aiur.AIR.RowContext DEFINITION -fun context rank => { function := context.function, inputSize := context.inputSize, rank := rank } +fun context rank => + { function := context.function, inputSize := context.inputSize, rank := rank, callRanks := context.callRanks } PREMISE Aiur.NativeAIR.BlockEmitter.BlockReflects Aiur.NativeAIR.Values Aiur.G → (Nat → Aiur.G) → @@ -16339,17 +18742,22 @@ fun values member => do { functionIndex := member.functionIndex, function := member.function, selectorBase := member.selectorBase, body := body } PREMISE Aiur.NativeAIR.CircuitEmitter.emitMember -Aiur.NativeAIR.Expr → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → Nat → Option Aiur.NativeAIR.CircuitEmitter.Member +Aiur.NativeAIR.Expr → + Nat → + Nat → + Nat → + Aiur.Bytecode.Toplevel → + Nat → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.NativeAIR.CircuitEmitter.Member DEFINITION -fun rank column lookup selectorBase program functionIndex => do +fun rank column lookup selectorBase program functionIndex callRanks => do let function ← program.functions[functionIndex]? have selectors : Array Aiur.NativeAIR.Expr := Aiur.NativeAIR.CircuitEmitter.selectorExprs selectorBase function.layout.selectors let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors function.body let body ← Aiur.NativeAIR.BlockEmitter.emitBlock selectors - { function := functionIndex, inputSize := function.layout.inputSize, rank := rank } entry - (Aiur.NativeAIR.OpEmitter.advice 0 function.layout.inputSize) column lookup function.body + { function := functionIndex, inputSize := function.layout.inputSize, rank := rank, callRanks := callRanks } + entry (Aiur.NativeAIR.OpEmitter.advice 0 function.layout.inputSize) column lookup function.body pure { functionIndex := functionIndex, function := function, selectorBase := selectorBase, entry := entry, body := body } @@ -17266,7 +19674,8 @@ Nat → Aiur.Bytecode.Toplevel → Aiur.Bytecode.Circuit → Option Aiur.NativeA DEFINITION fun logBlowup program source => do let compiled ← - Aiur.NativeAIR.CircuitEmitter.compileCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths source) program source + Aiur.NativeAIR.CircuitEmitter.compileNativeCircuit (Aiur.NativeAIR.CircuitEmitter.circuitWidths source) program + source have groupSize : Nat := if (compiled.emission.branchless && decide (2 ≤ compiled.emission.lookups.length)) = true then 2 else 1 Aiur.NativeAIR.CompiledKey.circuit logBlowup source.layout.width 0 0 groupSize compiled.base @@ -17311,8 +19720,9 @@ PREMISE Aiur.NativeAIR.CompiledKey.check Aiur.Bytecode.Toplevel → Aiur.NativeAIR.KeyCodec.Key → Bool DEFINITION fun program key => - Aiur.NativeAIR.CompiledKey.circuits key.parameters.logBlowup program == some key.circuits && - key.preprocessedIndices == Aiur.NativeAIR.CompiledKey.preprocessedIndices program + (program.callComponents.isEmpty || program.validCallComponents) && + (Aiur.NativeAIR.CompiledKey.circuits key.parameters.logBlowup program == some key.circuits && + key.preprocessedIndices == Aiur.NativeAIR.CompiledKey.preprocessedIndices program) PREMISE Aiur.BoundVerifier.CompiledBackend.mk {selection : Aiur.BoundVerifier.Selection} → (toBackend : Aiur.BoundVerifier.Backend selection) → @@ -22370,6 +24780,19 @@ fun x x_1 => | [], right => right | left, [] => left | x :: left, y :: right => (x + y) :: Aiur.AIR.addMessages._unsafe_rec left right +RECURSION WORKER Aiur.AIR.emitComponentMembers._unsafe_rec +(Nat → Aiur.G) → + Aiur.G → Nat → Nat → Aiur.Bytecode.Toplevel → List Aiur.Bytecode.FunIdx → Option (List Aiur.AIR.MemberEmission) +IMPLEMENTATION +fun row rank base selectorBase program x => + match x with + | [] => some [] + | index :: indices => do + let member ← Aiur.AIR.emitComponentMember row rank base selectorBase program index + let rest ← + Aiur.AIR.emitComponentMembers._unsafe_rec row rank base (selectorBase + member.function.layout.selectors) program + indices + pure (member :: rest) RECURSION WORKER Aiur.AIR.emitMembers._unsafe_rec (Nat → Aiur.G) → Aiur.G → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → List Aiur.Bytecode.FunIdx → Option (List Aiur.AIR.MemberEmission) @@ -22384,14 +24807,19 @@ fun row rank column lookup selectorBase program x => indices pure (member :: rest) RECURSION WORKER Aiur.AIR.emitOps._unsafe_rec -(Nat → Aiur.G) → Aiur.G → Aiur.G → List Aiur.Bytecode.Op → Array Aiur.AIR.RowValue → Nat → Option Aiur.AIR.OpsEmission +(Nat → Aiur.G) → + Aiur.G → + Aiur.G → + List Aiur.Bytecode.Op → + Array Aiur.AIR.RowValue → Nat → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.AIR.OpsEmission IMPLEMENTATION -fun row selector rank x x_1 x_2 => - match x, x_1, x_2 with - | [], values, column => some { values := values, column := column } - | op :: ops, values, column => do - let first ← Aiur.AIR.emitOp (fun i => row (column + i)) selector rank op values - let rest ← Aiur.AIR.emitOps._unsafe_rec row selector rank ops (values ++ first.outputs) (column + first.used) +fun row selector rank ops values column callRanks => + match ops with + | [] => some { values := values, column := column } + | op :: ops => do + let first ← Aiur.AIR.emitOp (fun i => row (column + i)) selector rank op values callRanks + let rest ← + Aiur.AIR.emitOps._unsafe_rec row selector rank ops (values ++ first.outputs) (column + first.used) callRanks pure { values := rest.values, column := rest.column, equations := first.equations ++ rest.equations, queries := first.queries ++ rest.queries, calls := first.calls ++ rest.calls } @@ -23209,6 +25637,18 @@ fun decls params a => | some val => throw (Aiur.CheckError.notADataType g) | none => throw (Aiur.CheckError.unboundGlobal g) | x => pure () +RECURSION WORKER Aiur.AIR.CircuitTraces.GraphSatisfied._unsafe_rec +{circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → List Aiur.NativeAIR.KeyCodec.Circuit → Prop +IMPLEMENTATION +fun {circuits} x x_1 => + match circuits, x, x_1 with + | .([]), Aiur.AIR.CircuitTraces.nil, keys => keys = [] + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest, head :: keys => + Aiur.AIR.CircuitTraces.GraphSatisfied._unsafe_rec rest keys + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree matrix rest, key :: keys => + key.graph.TraceSatisfied key.widths matrix ∧ Aiur.AIR.CircuitTraces.GraphSatisfied._unsafe_rec rest keys + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest, [] => False + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree values rest, [] => False RECURSION WORKER Aiur.AIR.CircuitTraces.bitmap._unsafe_rec {circuits : List Aiur.Bytecode.Circuit} → Aiur.AIR.CircuitTraces circuits → List Bool IMPLEMENTATION @@ -23239,6 +25679,19 @@ fun {circuits} x => Aiur.AIR.CircuitTraces.degrees._unsafe_rec rest | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree values rest => degree :: Aiur.AIR.CircuitTraces.degrees._unsafe_rec rest +RECURSION WORKER Aiur.AIR.CircuitTraces.emitNativeWitnesses._unsafe_rec +{circuits : List Aiur.Bytecode.Circuit} → + Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitTraces circuits → Option (List Aiur.AIR.CircuitWitness) +IMPLEMENTATION +fun {circuits} program x => + match circuits, x with + | .([]), Aiur.AIR.CircuitTraces.nil => some [] + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest => + Aiur.AIR.CircuitTraces.emitNativeWitnesses._unsafe_rec program rest + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree values rest => do + let first ← List.mapM (Aiur.AIR.emitNativeCircuitWitness program circuit) (List.ofFn values) + let later ← Aiur.AIR.CircuitTraces.emitNativeWitnesses._unsafe_rec program rest + pure (first ++ later) RECURSION WORKER Aiur.AIR.CircuitTraces.emitWitnesses._unsafe_rec {circuits : List Aiur.Bytecode.Circuit} → Aiur.Bytecode.Toplevel → Aiur.AIR.CircuitTraces circuits → Option (List Aiur.AIR.CircuitWitness) @@ -23252,6 +25705,33 @@ fun {circuits} program x => let first ← List.mapM (Aiur.AIR.emitCircuitWitness program circuit) (List.ofFn values) let later ← Aiur.AIR.CircuitTraces.emitWitnesses._unsafe_rec program rest pure (first ++ later) +RECURSION WORKER Aiur.AIR.CircuitTraces.graphLookups._unsafe_rec +{circuits : List Aiur.Bytecode.Circuit} → + Aiur.AIR.CircuitTraces circuits → List Aiur.NativeAIR.KeyCodec.Circuit → Option (List Aiur.NativeAIR.LookupRow) +IMPLEMENTATION +fun {circuits} x x_1 => + match circuits, x, x_1 with + | .([]), Aiur.AIR.CircuitTraces.nil, [] => some [] + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.inactive circuit rest, head :: keys => + Aiur.AIR.CircuitTraces.graphLookups._unsafe_rec rest keys + | .(circuit :: circuits), Aiur.AIR.CircuitTraces.active circuit degree matrix rest, key :: keys => do + let first ← key.graph.readTraceLookups key.widths matrix + let later ← Aiur.AIR.CircuitTraces.graphLookups._unsafe_rec rest keys + pure (first ++ later) + | circuits, x, x_2 => none +RECURSION WORKER Aiur.AIR.MemoryTraces.GraphSatisfied._unsafe_rec +{widths : List Nat} → Aiur.AIR.MemoryTraces widths → List Aiur.NativeAIR.KeyCodec.Circuit → Prop +IMPLEMENTATION +fun {widths} x x_1 => + match widths, x, x_1 with + | .([]), Aiur.AIR.MemoryTraces.nil, keys => keys = [] + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest, head :: keys => + Aiur.AIR.MemoryTraces.GraphSatisfied._unsafe_rec rest keys + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest, key :: keys => + key.graph.TraceSatisfied key.widths (Aiur.NativeAIR.finiteTraceMatrix matrix) ∧ + Aiur.AIR.MemoryTraces.GraphSatisfied._unsafe_rec rest keys + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest, [] => False + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest, [] => False RECURSION WORKER Aiur.AIR.MemoryTraces.Satisfied._unsafe_rec {widths : List Nat} → Aiur.AIR.MemoryTraces widths → Prop IMPLEMENTATION @@ -23289,6 +25769,20 @@ fun {widths} x => | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest => Aiur.AIR.MemoryTraces.degrees._unsafe_rec rest | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest => degree :: Aiur.AIR.MemoryTraces.degrees._unsafe_rec rest +RECURSION WORKER Aiur.AIR.MemoryTraces.graphLookups._unsafe_rec +{widths : List Nat} → + Aiur.AIR.MemoryTraces widths → List Aiur.NativeAIR.KeyCodec.Circuit → Option (List Aiur.NativeAIR.LookupRow) +IMPLEMENTATION +fun {widths} x x_1 => + match widths, x, x_1 with + | .([]), Aiur.AIR.MemoryTraces.nil, [] => some [] + | .(width :: widths), Aiur.AIR.MemoryTraces.inactive width rest, head :: keys => + Aiur.AIR.MemoryTraces.graphLookups._unsafe_rec rest keys + | .(width :: widths), Aiur.AIR.MemoryTraces.active width degree matrix rest, key :: keys => do + let first ← key.graph.readTraceLookups key.widths (Aiur.NativeAIR.finiteTraceMatrix matrix) + let later ← Aiur.AIR.MemoryTraces.graphLookups._unsafe_rec rest keys + pure (first ++ later) + | widths, x, x_2 => none RECURSION WORKER Aiur.AIR.MemoryTraces.providers._unsafe_rec {widths : List Nat} → Aiur.AIR.MemoryTraces widths → List (Aiur.AIR.Provider (List Aiur.G)) IMPLEMENTATION @@ -23343,7 +25837,7 @@ RECURSION WORKER Aiur.Bytecode.Block.emitRow._unsafe_rec Aiur.G → Array Aiur.AIR.RowValue → Nat → Nat → Aiur.Bytecode.Block → Option Aiur.AIR.BlockEmission IMPLEMENTATION fun row selector context incoming values column lookup block => do - let operations ← Aiur.AIR.emitOps row incoming context.rank block.ops.toList values column + let operations ← Aiur.AIR.emitOps row incoming context.rank block.ops.toList values column context.callRanks let control ← Aiur.Bytecode.Ctrl.emitRow._unsafe_rec row selector context incoming operations.values operations.column (lookup + operations.queries.length) block.ctrl @@ -23362,10 +25856,11 @@ fun program yieldSize block => block.ops.all (Aiur.Bytecode.Op.lookupShape program) && Aiur.Bytecode.Ctrl.lookupShapes._unsafe_rec program yieldSize block.ctrl RECURSION WORKER Aiur.Bytecode.Block.lookupUsage._unsafe_rec -Aiur.Bytecode.Block → Nat +Aiur.Bytecode.Block → optParam (Array Aiur.Bytecode.CallRank) #[] → Nat IMPLEMENTATION -fun block => - (List.map Aiur.Bytecode.Op.lookupUsage block.ops.toList).sum + Aiur.Bytecode.Ctrl.lookupUsage._unsafe_rec block.ctrl +fun block callRanks => + (List.map (fun op => op.lookupUsage callRanks) block.ops.toList).sum + + Aiur.Bytecode.Ctrl.lookupUsage._unsafe_rec block.ctrl callRanks RECURSION WORKER Aiur.Bytecode.Block.returnGates._unsafe_rec (Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.G → Aiur.Bytecode.Block → List Aiur.G IMPLEMENTATION @@ -23636,10 +26131,10 @@ fun program yieldSize x => | some block => Aiur.Bytecode.Block.lookupShapes._unsafe_rec program (some size) block) && Aiur.Bytecode.Block.lookupShapes._unsafe_rec program yieldSize continuation) RECURSION WORKER Aiur.Bytecode.Ctrl.lookupUsage._unsafe_rec -Aiur.Bytecode.Ctrl → Nat +Aiur.Bytecode.Ctrl → optParam (Array Aiur.Bytecode.CallRank) #[] → Nat IMPLEMENTATION -fun x => - match x with +fun ctrl callRanks => + match ctrl with | Aiur.Bytecode.Ctrl.return a a_1 => 0 | Aiur.Bytecode.Ctrl.yield a a_1 => 0 | Aiur.Bytecode.Ctrl.match a branches fallback => @@ -23647,22 +26142,22 @@ fun x => (List.map (fun x => match x with - | ⟨pair, property⟩ => Aiur.Bytecode.Block.lookupUsage._unsafe_rec pair.snd) + | ⟨pair, property⟩ => Aiur.Bytecode.Block.lookupUsage._unsafe_rec pair.snd callRanks) branches.attach.toList ++ match fallback with | none => [] - | some block => [Aiur.Bytecode.Block.lookupUsage._unsafe_rec block]) + | some block => [Aiur.Bytecode.Block.lookupUsage._unsafe_rec block callRanks]) | Aiur.Bytecode.Ctrl.matchContinue a branches fallback outputSize sharedAuxiliaries sharedLookups continuation => List.foldl Nat.max 0 (List.map (fun x => match x with - | ⟨pair, property⟩ => Aiur.Bytecode.Block.lookupUsage._unsafe_rec pair.snd) + | ⟨pair, property⟩ => Aiur.Bytecode.Block.lookupUsage._unsafe_rec pair.snd callRanks) branches.attach.toList ++ match fallback with | none => [] - | some block => [Aiur.Bytecode.Block.lookupUsage._unsafe_rec block]) + - Aiur.Bytecode.Block.lookupUsage._unsafe_rec continuation + | some block => [Aiur.Bytecode.Block.lookupUsage._unsafe_rec block callRanks]) + + Aiur.Bytecode.Block.lookupUsage._unsafe_rec continuation callRanks RECURSION WORKER Aiur.Bytecode.Ctrl.returnGates._unsafe_rec (Aiur.Bytecode.SelIdx → Aiur.G) → Aiur.G → Aiur.Bytecode.Ctrl → List Aiur.G IMPLEMENTATION @@ -24508,7 +27003,7 @@ Array Aiur.NativeAIR.Expr → IMPLEMENTATION fun selectors context incoming rows column lookup block => do let entry ← Aiur.NativeAIR.BlockEmitter.blockSelector selectors block - let operations ← Aiur.NativeAIR.OpEmitter.emitOps incoming context.rank block.ops.toList rows column + let operations ← Aiur.NativeAIR.OpEmitter.emitOps incoming context.rank block.ops.toList rows column context.callRanks let control ← Aiur.NativeAIR.BlockEmitter.emitCtrl._unsafe_rec selectors context incoming operations.values operations.column (lookup + operations.queries.length) block.ctrl @@ -24627,6 +27122,18 @@ fun hash x x_1 => | (word, next) => if word < Aiur.gSize.toNat then some (Aiur.G.ofNat word, next) else Aiur.NativeAIR.Challenger.sampleField._unsafe_rec hash fuel next +RECURSION WORKER Aiur.NativeAIR.CircuitEmitter.emitComponentMembers._unsafe_rec +Aiur.NativeAIR.Expr → Nat → Nat → Aiur.Bytecode.Toplevel → List Nat → Option (List Aiur.NativeAIR.CircuitEmitter.Member) +IMPLEMENTATION +fun rank base selectorBase program x => + match x with + | [] => some [] + | index :: indices => do + let member ← Aiur.NativeAIR.CircuitEmitter.emitComponentMember rank base selectorBase program index + let rest ← + Aiur.NativeAIR.CircuitEmitter.emitComponentMembers._unsafe_rec rank base + (selectorBase + member.function.layout.selectors) program indices + pure (member :: rest) RECURSION WORKER Aiur.NativeAIR.CircuitEmitter.emitMembers._unsafe_rec Aiur.NativeAIR.Expr → Nat → Nat → Nat → Aiur.Bytecode.Toplevel → List Nat → Option (List Aiur.NativeAIR.CircuitEmitter.Member) @@ -24927,15 +27434,18 @@ fun hash dimensions rows height index current x => RECURSION WORKER Aiur.NativeAIR.OpEmitter.emitOps._unsafe_rec Aiur.NativeAIR.Expr → Aiur.NativeAIR.Expr → - List Aiur.Bytecode.Op → Array Aiur.NativeAIR.RowExpr → Nat → Option Aiur.NativeAIR.OpEmitter.OpsEmission + List Aiur.Bytecode.Op → + Array Aiur.NativeAIR.RowExpr → + Nat → optParam (Array Aiur.Bytecode.CallRank) #[] → Option Aiur.NativeAIR.OpEmitter.OpsEmission IMPLEMENTATION -fun selector rank x x_1 x_2 => - match x, x_1, x_2 with - | [], rows, column => some { values := rows, column := column } - | op :: ops, rows, column => do - let first ← Aiur.NativeAIR.OpEmitter.emitOp selector rank column op rows +fun selector rank ops rows column callRanks => + match ops with + | [] => some { values := rows, column := column } + | op :: ops => do + let first ← Aiur.NativeAIR.OpEmitter.emitOp selector rank column op rows callRanks let rest ← Aiur.NativeAIR.OpEmitter.emitOps._unsafe_rec selector rank ops (rows ++ first.outputs) (column + first.used) + callRanks pure { values := rest.values, column := rest.column, equations := first.equations ++ rest.equations, queries := first.queries ++ rest.queries, calls := first.calls ++ rest.calls } @@ -26995,10 +29505,10 @@ fun value exponent x => let half := Aiur.NativeAIR.ProofCodec.Extension.powBits._unsafe_rec value (exponent / 2) fuel; let square := half * half; if (exponent % 2 == 0) = true then square else square * value -C8 component ROOTS 1574; LOGICAL DECLARATIONS 20519; WITH RUNTIME 21338 +C8 component ROOTS 1741; LOGICAL DECLARATIONS 20902; WITH RUNTIME 21729 IX RUNTIME EXTERNS [Aiur.AiurSystem.build, Aiur.AiurSystem.verify, Aiur.AiurSystem.vkBytes, Aiur.Proof.ofBytesChecked] PARTIAL OPAQUE SOURCES [Aiur.instHashableTyp.hash, Aiur.instReprPattern.repr, Aiur.instReprTyp.repr] OTHER UNSAFE RUNTIME [] -RECURSION WORKERS 197 +RECURSION WORKERS 204 Runtime diagnostics cover Ix modules, including private constants. Lean/Std runtime primitives remain an external execution boundary. Partial opaque implementations are inventoried, not proved to refine their logical defaults. -The runtime inventory and theorem premises are frozen separately. These roots do not establish full compiler/AIR reflection or public certified claim semantics. +The runtime inventory and theorem premises are frozen separately. These roots do not establish compiler-to-source semantic reflection, authenticated proof traces or public certified claim semantics. diff --git a/crates/aiur/src/constraints/tests/compiled_keys.rs b/crates/aiur/src/constraints/tests/compiled_keys.rs index 843b06e71..99c791d78 100644 --- a/crates/aiur/src/constraints/tests/compiled_keys.rs +++ b/crates/aiur/src/constraints/tests/compiled_keys.rs @@ -12,7 +12,7 @@ use super::{ *, }; use crate::{ - bytecode::Circuit, + bytecode::{CallComponent, Circuit, Function, FunctionLayout}, gadgets::{AiurGadget, bytes1::Bytes1, bytes2::Bytes2}, memory::Memory, synthesis::AiurConfig, @@ -83,6 +83,74 @@ fn columns(width: usize, seed: usize, family: usize) -> Vec { .collect() } +// Exercise the component policy inside branches, defaults and shared +// continuations, preserving the fixture's value indices and return shapes. +fn component_calls(block: &mut Block, parent: usize, cursor: &mut usize) { + for op in &mut block.ops { + if let Op::Call(child, _, _, unconstrained) = op { + *unconstrained = parent == 3; + *child = if cursor.is_multiple_of(2) { + match parent { + 0 | 2 => 1, + 1 => 2, + _ => 3, + } + } else { + 3 + }; + *cursor += 1; + } + } + match &mut block.ctrl { + Ctrl::Return(..) | Ctrl::Yield(..) => {}, + Ctrl::Match(_, cases, fallback) => { + for branch in cases.values_mut() { + component_calls(branch, parent, cursor); + } + if let Some(branch) = fallback { + component_calls(branch, parent, cursor); + } + }, + Ctrl::MatchContinue(_, cases, fallback, _, _, _, continuation) => { + for branch in cases.values_mut() { + component_calls(branch, parent, cursor); + } + if let Some(branch) = fallback { + component_calls(branch, parent, cursor); + } + component_calls(continuation, parent, cursor); + }, + } +} + +fn component_layout( + function: &mut Function, + index: usize, + components: &[CallComponent], +) { + let input_size = function.layout.input_size; + let selectors = function.layout.selectors; + let ranked = components[index].ranked; + let mut measured = ConstraintState { + function: index, + call_components: components, + function_index: G::from_usize(index), + input_size, + sel_base: input_size, + column: input_size + selectors + 1 + if ranked { RANK_BYTES } else { 0 }, + lookup: 1 + if ranked { RANK_LOOKUPS } else { 0 }, + map: (0..input_size).map(|i| (var(i), 1)).collect(), + lookups: (0..4096).map(|_| empty_lookup()).collect(), + yield_info: vec![], + ..state(selectors, false) + }; + let entry = function.body.get_block_selector(&measured); + function.body.collect_constraints(entry, &mut measured); + assert!(measured.yield_info.is_empty()); + function.layout.auxiliaries = measured.column - input_size - selectors; + function.layout.lookups = measured.lookup; +} + #[test] fn compiled_key_snapshot() -> io::Result<()> { let groups: &[&[usize]] = @@ -94,26 +162,64 @@ fn compiled_key_snapshot() -> io::Result<()> { commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, }; - let mut out = b"Aiur compiled keys v2\n".to_vec(); - write_u64(&mut out, 12)?; + let mut out = b"Aiur compiled keys v3\n".to_vec(); + write_u64(&mut out, 24)?; let mut assignments = 0; - for seed in 0..12 { + for seed in 0..24 { let cp = CommitmentParameters { log_blowup: 1 + seed % 3, cap_height: 0 }; - let functions: Vec<_> = - (0..4).map(|index| fixture_function(seed, index)).collect(); + let optimized = seed >= 12; + let call_components = if optimized { + vec![ + CallComponent { order: 0, ranked: false }, + CallComponent { order: 1, ranked: true }, + CallComponent { order: 1, ranked: true }, + CallComponent { order: 2, ranked: false }, + ] + } else { + vec![] + }; + let mut functions: Vec<_> = + (0..4).map(|index| fixture_function(seed % 12, index)).collect(); + if optimized { + for (index, function) in functions.iter_mut().enumerate() { + component_calls(&mut function.body, index, &mut 0); + component_layout(function, index, &call_components); + } + } let circuits = groups .iter() .map(|members| Circuit { members: members.to_vec(), - layout: circuit_layout(&functions, members), + layout: if optimized { + members.iter().fold( + FunctionLayout { + input_size: 0, + selectors: 0, + auxiliaries: 1, + lookups: 1, + }, + |layout, &member| { + let next = functions[member].layout; + FunctionLayout { + input_size: layout.input_size.max(next.input_size), + selectors: layout.selectors + next.selectors, + auxiliaries: layout.auxiliaries.max(next.auxiliaries), + lookups: layout.lookups.max(next.lookups), + } + }, + ) + } else { + circuit_layout(&functions, members) + }, }) .collect(); let top = Toplevel { functions, circuits, memory_sizes: vec![0, 1, 2, 4, 8], - call_components: vec![], + call_components, }; + assert!(top.validate_call_components().is_ok()); write_u64(&mut out, top.functions.len() as u64)?; for function in &top.functions { write_block(&mut out, &function.body)?; @@ -126,6 +232,11 @@ fn compiled_key_snapshot() -> io::Result<()> { write_layout(&mut out, circuit.layout)?; } write_indices(&mut out, &top.memory_sizes)?; + write_u64(&mut out, top.call_components.len() as u64)?; + for component in &top.call_components { + write_u64(&mut out, component.order as u64)?; + out.push(u8::from(component.ranked)); + } let inputs = inputs(&top); let expressions: Vec<_> = inputs .iter() @@ -204,14 +315,14 @@ fn compiled_key_snapshot() -> io::Result<()> { } } } - assert_eq!(assignments, 720); + assert_eq!(assignments, 1440); if let Some(path) = std::env::var_os("IX_COMPILED_KEY_SNAPSHOT") { let mut file = BufWriter::new(File::create(path)?); file.write_all(&out)?; file.flush()?; } eprintln!( - "compiled keys: 12 systems, 180 circuits, {assignments} assignments" + "compiled keys: 24 systems (12 component layouts), 360 circuits, {assignments} assignments" ); Ok(()) } diff --git a/docs/aiur-soundness.md b/docs/aiur-soundness.md index eddfa929a..d5baecd54 100644 --- a/docs/aiur-soundness.md +++ b/docs/aiur-soundness.md @@ -235,20 +235,37 @@ regression evidence, separate from a universal native refinement theorem. Generic call emission now uses the six gap columns and derived child rank described above. The call-order equation is proved identically zero; it is -not an extra native constraint. The corresponding allocation and extraction -results state their generic-layout premise explicitly. The component layout -pass is proved to preserve input arity and complete evaluator results, -including shared continuations, while its allocation model covers zero, -boundary and ordered call ranks. Extracting execution from physical rows in -all component modes remains the next proof obligation. +not an extra native constraint. The shared row and expression proofs also +cover zero and boundary ranks. The component layout pass preserves input +arity and complete evaluator results, including shared continuations. + +[`CompiledBackend.checked_graph_trace_execution`](../Ix/Aiur/Proofs/NativeTraceMetadata.lean) +extracts finite execution and functional memory from the selected key's +physical base graphs. It handles fallback layouts, recursive components, +acyclic members and mixed circuits. The key check validates component edges, +physical column reads, logical slot ranges and fallback member extents. +Graph reflection then supplies row emission, satisfaction and these bounds; +the execution theorem has no separate honest-row or generic-layout premise. + +The theorem takes satisfying base graphs and exact padded balance of their +physical messages. Matching the extracted trace bitmap and degrees to the +decoded proof supplies the lookup budget already enforced by the wrapper; +physical graph counts are proved equal to the logical trace counts. Function slot +zero is a provider even when its negative field multiplicity equals one. +Memory and canonical byte preprocessing contribute to the same global pool. +The byte-table commitment, active trace metadata and graph satisfaction must +still be authenticated by the PCS theorem; randomized LogUp soundness must +still establish exact balance. The physical trace theorem itself assumes +neither source execution nor a sound guest checker. Compiled-key comparison includes production lookup retuning with the key's blowup parameter. Its total selector retains the machine-size and overflow guards and the baseline FFT cost comparison. Retuning preserves the authored graph, main width and preprocessed dimensions; the compared key includes the -resulting group and degree. The key corpus exercises three blowup settings, -function and memory circuits, both byte tables, empty circuits and validly -encoded altered keys. +resulting group and degree. The key corpus exercises three blowup settings +and 24 systems, including 12 component layouts: 360 function, memory and byte +circuits with 1,440 arbitrary assignments. It includes empty circuits and +rejects 336 validly encoded altered keys and 48 invalid component certificates. The source compatibility checks also cover strict effect order and explicit returns. Array update evaluates its new value before the array expression, diff --git a/lakefile.lean b/lakefile.lean index 25f707248..d93622001 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -348,6 +348,9 @@ lean_exe «aiur-key-codec-tests» where lean_exe «aiur-compiled-key-tests» where root := `Tests.Aiur.CompiledKey +lean_exe «aiur-production-key-tests» where + root := `Tests.Aiur.ProductionKey + lean_exe «aiur-proof-codec-tests» where root := `Tests.Aiur.ProofCodec @@ -639,6 +642,7 @@ script "check-aiur" := do "aiur-expression-graph-tests", "aiur-constant-degree-tests", "aiur-frontend-expression-tests", "aiur-graph-compilation-tests", "aiur-operation-expression-tests", "aiur-block-expression-tests", "aiur-circuit-expression-tests", "aiur-emission-check-tests", "aiur-key-codec-tests", "aiur-compiled-key-tests", + "aiur-production-key-tests", "aiur-proof-codec-tests", "aiur-proof-shape-tests", "aiur-extension-tests", "aiur-logup-tests", "aiur-domain-tests", "aiur-verifier-arithmetic-tests", "aiur-transcript-tests", "aiur-blake3-tests", "aiur-merkle-cap-tests", "aiur-merkle-tests", "aiur-pruned-merkle-tests", "aiur-extension-mmcs-tests", "aiur-fri-domain-tests", @@ -679,6 +683,7 @@ script "check-aiur" := do run ".lake/build/bin/aiur-hoisting-tests" run ".lake/build/bin/aiur-air-tests" run ".lake/build/bin/aiur-constant-degree-tests" + run ".lake/build/bin/aiur-production-key-tests" IO.FS.withTempDir fun directory => do let snapshot := directory / "native-byte-gadgets.bin" let shapeSnapshot := directory / "native-lookup-shapes.bin" @@ -806,4 +811,3 @@ script "check-aiur" := do run ".lake/build/bin/aiur-backend-tests" IO.println "Aiur component checks passed: exact proof/runtime boundaries, compiler compatibility and native binding." return 0 - From 04f15cbe6f385b1dbecfb531356ebcfd1b2736d4 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 00:01:42 -0400 Subject: [PATCH 23/30] Extend consistency readings and maintained cache invariants --- Ix/Kernel/Verify/Consistency.lean | 15 +- Ix/Kernel/Verify/Consistency/Application.lean | 27 +- Ix/Kernel/Verify/Consistency/Audit.lean | 119 ++++++- .../Verify/Consistency/BinderOpening.lean | 24 +- .../Verify/Consistency/CacheInvariant.lean | 278 +++++++++++++++ .../Verify/Consistency/CacheLifecycle.lean | 95 ++++++ Ix/Kernel/Verify/Consistency/Expr.lean | 7 +- Ix/Kernel/Verify/Consistency/InstUniv.lean | 9 +- .../Verify/Consistency/InternInvariant.lean | 89 +++++ Ix/Kernel/Verify/Consistency/ScopedExpr.lean | 58 +++- .../Verify/Consistency/ScopedInstUniv.lean | 14 +- .../Verify/Consistency/StringExpansion.lean | 316 ++++++++++++++++++ .../Verify/Consistency/StringReading.lean | 157 +++++++++ Ix/Theory/ExprSubstitution.lean | 161 +++++++++ docs/kernel-verification.md | 26 +- 15 files changed, 1358 insertions(+), 37 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/CacheInvariant.lean create mode 100644 Ix/Kernel/Verify/Consistency/CacheLifecycle.lean create mode 100644 Ix/Kernel/Verify/Consistency/InternInvariant.lean create mode 100644 Ix/Kernel/Verify/Consistency/StringExpansion.lean create mode 100644 Ix/Kernel/Verify/Consistency/StringReading.lean create mode 100644 Ix/Theory/ExprSubstitution.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 94f9f3ef5..730267b8c 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -21,6 +21,10 @@ import Ix.Kernel.Verify.Consistency.BinderOpening import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.RecursiveCache +import Ix.Kernel.Verify.Consistency.CacheInvariant +import Ix.Kernel.Verify.Consistency.CacheLifecycle +import Ix.Kernel.Verify.Consistency.InternInvariant +import Ix.Kernel.Verify.Consistency.StringExpansion import Ix.Kernel.Verify.Consistency.Production import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Consistency.Audit @@ -62,5 +66,14 @@ outside that footprint, loaded declarations, and checking policy. This derives later constant witnesses and sort leaves without new cache-hit observations. Initial agreement, finite execution resources, trace construction, lazy loading, and preservation for keys inside the footprint remain explicit obligations. -General checker soundness remains outside this fragment. + +The general reading now includes lets and strings. Binder opening, abstraction, +term substitution and universe substitution cover their nested occurrences. +String expansion follows the actual production intern sequence and preserves +the reading and table coherence under one finite allocation-pool condition. +The complete inference-cache invariant gives a fact for every entry in both +partitions. Writes, hits, initialization, clearing, scope/policy cleanup and +error isolation preserve these facts. Its parameterized entry meaning and +uncached-body preservation contract remain to be instantiated by the general +mutual semantic proof. General checker soundness remains outside this fragment. -/ diff --git a/Ix/Kernel/Verify/Consistency/Application.lean b/Ix/Kernel/Verify/Consistency/Application.lean index 9af94b268..1549f38f9 100644 --- a/Ix/Kernel/Verify/Consistency/Application.lean +++ b/Ix/Kernel/Verify/Consistency/Application.lean @@ -66,7 +66,19 @@ theorem readScopedExpr?_liftSpec obtain ⟨ref, resolved, reading⟩ := bind_success reading cases reading simp [KExpr.liftSpec, readScopedExpr?, resolved, VExpr.liftN] - | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | str value _ _ => + rw [readString?_liftN reading] + exact reading + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readScopedExpr?_let_parts reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.liftSpec, hA (by omega) aReads, hv (by omega) vReads, + VExpr.liftN_inst_hi, show depth.toNat + shift.toNat + 1 = + depth.toNat + 1 + shift.toNat by omega, bodyOut] | app fn arg info hf ha => rw [readScopedExpr?] at reading obtain ⟨f, fReads, reading⟩ := bind_success reading @@ -141,7 +153,18 @@ theorem readScopedExpr?_substSpec obtain ⟨ref, resolved, bodyReads⟩ := bind_success bodyReads cases bodyReads simp [KExpr.substSpec, readScopedExpr?, resolved, VExpr.inst] - | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | str value _ _ => + rw [readString?_inst bodyReads] + exact bodyReads + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readScopedExpr?_let_parts bodyReads + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.substSpec, hA (by omega) aReads, hv (by omega) vReads, + VExpr.inst0_inst_hi, bodyOut] | app fn value info hf ha => rw [readScopedExpr?] at bodyReads obtain ⟨f, fReads, bodyReads⟩ := bind_success bodyReads diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 3af2d24df..29e11b6a3 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -7,6 +7,8 @@ import Ix.Kernel.Verify.Consistency.Infer import Ix.Kernel.Verify.Consistency.Constant import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Consistency.RecursiveCache +import Ix.Kernel.Verify.Consistency.CacheLifecycle +import Ix.Kernel.Verify.Consistency.StringExpansion import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -86,6 +88,32 @@ private def cacheKeyRoots : Array Lean.Name := #[ ``withLctxScope_eq, ``PreservesInferenceCache.withLctxScope ] +private def cacheInvariantFrameRoots : Array Lean.Name := #[ + ``InferenceCacheInvariant.frame, ``InferenceCacheInvariant.mono, + ``InferenceCacheInvariant.runIntern, ``InferenceCacheInvariant.restoreCheckCachesOnError, + ``InferenceCacheInvariant.isolateCheckErrors, ``PreservesInferenceInvariant.pure, + ``PreservesInferenceInvariant.bind, ``PreservesInferenceInvariant.runIntern, + ``PreservesInferenceInvariant.withInferOnly +] + +private def cacheInvariantMapRoots : Array Lean.Name := #[ + ``InferenceCacheInvariant.empty, ``InferenceCacheInvariant.write, + ``InferenceCacheInvariant.clearReductionCaches, ``InferenceCacheInvariant.reset, + ``InferenceCacheInvariant.finishAnonCheckItem +] + +private def cacheInvariantKeyRoots : Array Lean.Name := #[ + ``InferenceCacheInvariant.inferKey, ``InferenceCacheInvariant.selected, + ``InferenceCacheInvariant.openBinder, ``PreservesInferenceInvariant.withLctxScope, + ``inferKey_total +] + +private def cacheInvariantDriverRoots : Array Lean.Name := #[ + ``InferenceCacheInvariant.checkConst_error, ``InferenceCacheInvariant.runAnonCheckItem, + ``InferenceCacheInvariant.runAnonCheckList, + ``InferenceCacheInvariant.initialized_runAnonCheckList +] + private def recursiveCacheRoots : Array Lean.Name := #[ ``ApplicationInferenceTrace.output_state, ``ForallInferenceTrace.output_state, ``LambdaInferenceTrace.output_state, ``isDefEq_hash_state, ``isDefEq_hash_frame, @@ -105,13 +133,54 @@ private def productionRoots : Array Lean.Name := #[ ``checkEnvAnon_atomic_no_false ] +private def localIndexRoots : Array Lean.Name := #[ + ``localIndex?_mem, ``localIndex?_getElem, ``localIndex?_fresh +] + private def scopedRoots : Array Lean.Name := #[ - ``localIndex?_mem, ``localIndex?_getElem, ``localIndex?_fresh, ``readScopedExpr?_closed, ``readScopedExpr?_weaken_closed, ``readScopedExpr?_eraseMeta, ``beq_readScopedExpr?, ``internExpr_readScopedExpr?, ``readScopedExpr?_push, ``LocalContextReading.empty ] +private def stringListRoots : Array Lean.Name := #[ + ``StringPrimitiveRefs.listExpr_liftN, ``StringPrimitiveRefs.listExpr_inst, + ``StringPrimitiveRefs.listExpr_instL, ``StringPrimitiveRefs.listExpr_closed +] + +/-- `String.toList` carries standard-library choice and quotient dependencies. +The full dependency audit includes this executable definition in reader types. -/ +private def stringRoots : Array Lean.Name := #[ + ``StringPrimitiveRefs.expr_liftN, ``StringPrimitiveRefs.expr_inst, + ``StringPrimitiveRefs.expr_instL, ``StringPrimitiveRefs.expr_closed, + ``StringPrimitiveRefs.expr_levelWF, ``readString?_parts, ``readString?_liftN, + ``readString?_inst, ``readString?_instL, ``readString?_closed, ``readString?_levelWF, + ``StringPrimitiveRefs.resolve?_fields +] + +private def internFrameRoots : Array Lean.Name := #[ + ``ExpressionInternInvariant.mono, ``ExpressionInternInvariant.result_eq, ``intern_eq +] + +private def internMapRoots : Array Lean.Name := #[ + ``ExpressionInternInvariant.empty, ``ExpressionInternInvariant.internExpr, + ``ExpressionInternInvariant.internUniv, ``ExpressionInternInvariant.internExprList +] + +private def stringExpansionRoots : Array Lean.Name := #[ + ``StringExpansion.list_run, ``StringExpansion.candidates_length, ``StringExpansion.run, + ``StringExpansion.run_finite, ``StringExpansion.listResult_read +] + +private def letSubstitutionRoots : Array Lean.Name := #[ + ``Theory.VExpr.liftN_combine, ``Theory.VExpr.liftN_comm, + ``Theory.VExpr.liftN_instVar_lo, ``Theory.VExpr.liftN_inst_lo, + ``Theory.VExpr.liftN_instVar_hi, ``Theory.VExpr.liftN_inst_hi_at, + ``Theory.VExpr.liftN_inst_hi, ``Theory.VExpr.inst_liftN, + ``Theory.VExpr.inst_instVar_hi, ``Theory.VExpr.inst_inst_hi, + ``Theory.VExpr.inst0_inst_hi +] + private def contextRoots : Array Lean.Name := #[ ``localContext_find?_push_same, ``localContext_find?_push_ne, ``LocalContextReading.push, ``ScopedModelTyping.closed @@ -147,12 +216,22 @@ def roots : Array RootAllowance := #[ { root := ``univGeq_sound, standardAxioms := standard }, { root := ``readExpr?_mkSort, standardAxioms := standard, nativeAxioms := #[expressionNative] }, - { root := ``readExpr?_eraseMeta, standardAxioms := #[``propext, ``Quot.sound] }, - { root := ``readScopedExpr?_lam_parts }, - { root := ``readScopedExpr?_app_parts }, - { root := ``readScopedExpr?_all_parts }, - { root := ``beq_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, - { root := ``internExpr_readExpr?, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``readExpr?_eraseMeta, standardAxioms := standard }, + { root := ``readScopedExpr?_lam_parts, standardAxioms := standard }, + { root := ``readScopedExpr?_app_parts, standardAxioms := standard }, + { root := ``readScopedExpr?_all_parts, standardAxioms := standard }, + { root := ``readScopedExpr?_let_parts, standardAxioms := standard }, + { root := ``readScopedExpr?_mkLet, standardAxioms := standard, + nativeAxioms := #[expressionNative] }, + { root := ``Theory.liftVar_lt }, + { root := ``Theory.liftVar_le }, + { root := ``Theory.VExpr.liftN_zero, standardAxioms := #[``propext] }, + { root := ``beq_readExpr?, standardAxioms := standard }, + { root := ``internExpr_readExpr?, standardAxioms := standard }, + { root := ``StringPrimitiveRefs.listExpr_levelWF, standardAxioms := #[``propext, ``Quot.sound] }, + { root := ``StringExpansion.listCandidates_length, + standardAxioms := #[``propext, ``Classical.choice], nativeAxioms := #[expressionNative], + forbiddenDependencies := forbiddenProduction }, { root := ``ModelTyping.sort, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative] }, { root := ``ModelTyping.of_beq, standardAxioms := standard }, @@ -188,19 +267,35 @@ def roots : Array RootAllowance := #[ { root := ``Theory.Model.CheckingClaim.typing, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.typingSort, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.lam, standardAxioms := standard } -] ++ (scopedRoots ++ cacheFrameRoots).map (fun root => { +] ++ stringListRoots.map (fun root => { + root, standardAxioms := #[``propext], forbiddenDependencies := forbiddenProduction +}) ++ (localIndexRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ + internFrameRoots).map (fun root => { root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction -}) ++ (contextRoots ++ cacheMapRoots).map (fun root => { +}) ++ (contextRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ + internMapRoots).map (fun root => { root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction -}) ++ (binderWalkerRoots ++ cacheKeyRoots).map (fun root => { +}) ++ (binderWalkerRoots ++ cacheKeyRoots ++ cacheInvariantKeyRoots ++ stringExpansionRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative], forbiddenDependencies := forbiddenProduction -}) ++ (atomicRoots ++ instantiationRoots ++ recursiveCacheRoots).map (fun root => { +}) ++ (atomicRoots ++ instantiationRoots ++ recursiveCacheRoots ++ + #[``InferenceCacheInvariant.infer]).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], forbiddenDependencies := forbiddenProduction -}) ++ productionRoots.map (fun root => { +}) ++ (productionRoots ++ cacheInvariantDriverRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := productionNative, forbiddenDependencies := forbiddenProduction +}) ++ #[``InferenceCacheInvariant.newLazyAnon, + ``InferenceCacheInvariant.initialAnonCheckLoopState].map (fun root => { + root, standardAxioms := standard, + nativeAxioms := #[expressionNative, levelNative, + nativeAxiom `Ix.Environment `Ix.Name.mkStr._native.native_decide.ax_1], + forbiddenDependencies := forbiddenProduction +}) ++ #[``StringExpansion.result_read, ``StringExpansion.read_of_run].map (fun root => { + root, standardAxioms := standard, + nativeAxioms := #[expressionNative, + nativeAxiom `Ix.Environment `Ix.Name.mkStr._native.native_decide.ax_1], + forbiddenDependencies := forbiddenProduction }) ++ #[{ root := ``extend_atomic_definition, standardAxioms := standard }] run_cmd Kernel.Verify.Audit.check roots diff --git a/Ix/Kernel/Verify/Consistency/BinderOpening.lean b/Ix/Kernel/Verify/Consistency/BinderOpening.lean index 16c35701e..77366c2c3 100644 --- a/Ix/Kernel/Verify/Consistency/BinderOpening.lean +++ b/Ix/Kernel/Verify/Consistency/BinderOpening.lean @@ -70,8 +70,16 @@ theorem readScopedExpr?_instantiateRevSpec cases reading simp [KExpr.instantiateRevSpec, readScopedExpr?, localIndex?_fresh absent found, Nat.add_assoc, Nat.add_comm 1] - | sort _ _ | const _ _ _ | nat _ _ _ => exact reading - | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => exact reading + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readScopedExpr?_let_parts reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.instantiateRevSpec, hA (by omega) aReads, + hv (by omega) vReads, bodyOut] | app fn arg info hf ha => rw [readScopedExpr?] at reading obtain ⟨f, fReads, reading⟩ := bind_success reading @@ -150,8 +158,16 @@ theorem readScopedExpr?_abstractFVarsSpec simp [KExpr.abstractFVarsSpec, Ne.symm equal, readScopedExpr?, found, Nat.add_assoc, Nat.add_comm 1] - | sort _ _ | const _ _ _ | nat _ _ _ => exact reading - | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => exact reading + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readScopedExpr?_let_parts reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.abstractFVarsSpec, hA (by omega) aReads, + hv (by omega) vReads, bodyOut] | app fn arg info hf ha => rw [readScopedExpr?] at reading obtain ⟨f, fReads, reading⟩ := bind_success reading diff --git a/Ix/Kernel/Verify/Consistency/CacheInvariant.lean b/Ix/Kernel/Verify/Consistency/CacheInvariant.lean new file mode 100644 index 000000000..625737a07 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/CacheInvariant.lean @@ -0,0 +1,278 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.InferenceCache + +/-! +# Invariants for every inference-cache entry + +Both physical maps carry one invariant, with separate full-checking and +inference-only meanings. Every insertion establishes its own entry's meaning +and preserves all other entries. A caller never supplies an outside-write +condition or a new agreement witness for a hit. + +The cache shell is independent of the eventual semantic interpretation of a +key. Its uncached-body premise is the induction obligation for inference, +reduction and conversion; these structural laws do not assume it is discharged. +-/ + +namespace Ix.Kernel.Consistency + +/-- The boolean identifies the partition that originally produced a result, +not the current caller's policy. -/ +abbrev InferenceCacheMeaning := Bool → (Address × Address) → KExpr .anon → Prop + +/-- Every present entry has the meaning of its actual production partition. +This permits full checking and synthesis to have different contracts. -/ +structure InferenceCacheInvariant (meaning : InferenceCacheMeaning) + (state : TcState .anon) : Prop where + full : ∀ key type, state.env.inferCache[key]? = some type → meaning false key type + only : ∀ key type, state.env.inferOnlyCache[key]? = some type → meaning true key type + +namespace InferenceCacheInvariant + +theorem empty {meaning : InferenceCacheMeaning} {state : TcState .anon} + (full : state.env.inferCache = {}) (only : state.env.inferOnlyCache = {}) : + InferenceCacheInvariant meaning state := by + constructor <;> intro key type found + · simp [full] at found + · simp [only] at found + +theorem frame {meaning : InferenceCacheMeaning} {before after : TcState .anon} + (valid : InferenceCacheInvariant meaning before) + (full : after.env.inferCache = before.env.inferCache) + (only : after.env.inferOnlyCache = before.env.inferOnlyCache) : + InferenceCacheInvariant meaning after := by + constructor + · intro key type found; exact valid.full key type (full ▸ found) + · intro key type found; exact valid.only key type (only ▸ found) + +/-- Environment extension can transport all stored facts at once. -/ +theorem mono {beforeMeaning afterMeaning : InferenceCacheMeaning} + {state : TcState .anon} (valid : InferenceCacheInvariant beforeMeaning state) + (transport : ∀ policy key type, beforeMeaning policy key type → afterMeaning policy key type) : + InferenceCacheInvariant afterMeaning state := + ⟨fun key type found => transport false key type (valid.full key type found), + fun key type found => transport true key type (valid.only key type found)⟩ + +/-- The old contents at the overwritten key need not equal the new result. +Only the result actually inserted must satisfy its partition's contract. -/ +theorem write {meaning : InferenceCacheMeaning} {before after : TcState .anon} + {policy : Bool} {key : Address × Address} {type : KExpr .anon} + {methods : Methods .anon} (valid : InferenceCacheInvariant meaning before) + (fact : meaning policy key type) + (run : RecM.cacheInferResult policy key type methods before = .ok () after) : + InferenceCacheInvariant meaning after := by + rw [cacheInferResult_eq] at run + cases policy <;> cases run + · refine ⟨?_, valid.only⟩ + intro other cached found + change (before.env.inferCache.insert key type)[other]? = some cached at found + by_cases equal : key = other + · subst other + simp only [Std.HashMap.getElem?_insert_self, Option.some.injEq] at found + exact found ▸ fact + · simp only [Std.HashMap.getElem?_insert, beq_iff_eq, equal, if_false] at found + exact valid.full other cached found + · refine ⟨valid.full, ?_⟩ + intro other cached found + change (before.env.inferOnlyCache.insert key type)[other]? = some cached at found + by_cases equal : key = other + · subst other + simp only [Std.HashMap.getElem?_insert_self, Option.some.injEq] at found + exact found ▸ fact + · simp only [Std.HashMap.getElem?_insert, beq_iff_eq, equal, if_false] at found + exact valid.only other cached found + +theorem inferKey {meaning : InferenceCacheMeaning} {before after : TcState .anon} + {term : KExpr .anon} {key : Address × Address} + (valid : InferenceCacheInvariant meaning before) + (run : TcM.inferKey term before = .ok key after) : + InferenceCacheInvariant meaning after := by + constructor + · intro other type found + have frame := PreservesInferenceCache.inferKey other term before + rw [run] at frame + exact valid.full other type (frame.full.symm.trans found) + · intro other type found + have frame := PreservesInferenceCache.inferKey other term before + rw [run] at frame + exact valid.only other type (frame.only.symm.trans found) + +/-- A successful hit supplies the stored partition's fact. Full mode cannot +obtain a fact from the synthesis-only partition. -/ +theorem selected {meaning : InferenceCacheMeaning} {before : TcState .anon} + {term : KExpr .anon} (valid : InferenceCacheInvariant meaning before) + (hit : InferenceCacheHit before term) : + meaning false hit.key hit.cached ∨ + (before.inferOnly = true ∧ meaning true hit.key hit.cached) := by + have keyed := valid.inferKey hit.keyRun + rcases hit.selected with full | ⟨_, policy, only⟩ + · exact .inl (keyed.full _ _ full) + · exact .inr ⟨policy, keyed.only _ _ only⟩ + +theorem runIntern {meaning : InferenceCacheMeaning} {before after : TcState .anon} + {action : InternM .anon α} {value : α} + (valid : InferenceCacheInvariant meaning before) + (run : TcM.runIntern action before = .ok value after) : + InferenceCacheInvariant meaning after := by + cases run + exact valid.frame rfl rfl + +theorem openBinder {meaning : InferenceCacheMeaning} {before after : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {domain body opened : KExpr .anon} {fresh : FVarId} + (valid : InferenceCacheInvariant meaning before) + (run : TcM.openBinder name bi domain body before = .ok (opened, fresh) after) : + InferenceCacheInvariant meaning after := by + constructor + · intro key type found + have frame := PreservesInferenceCache.openBinder key name bi domain body before + rw [run] at frame + exact valid.full key type (frame.full.symm.trans found) + · intro key type found + have frame := PreservesInferenceCache.openBinder key name bi domain body before + rw [run] at frame + exact valid.only key type (frame.only.symm.trans found) + +theorem clearReductionCaches (meaning : InferenceCacheMeaning) (state : TcState .anon) : + InferenceCacheInvariant meaning {state with env := state.env.clearReductionCaches} := + empty rfl rfl + +theorem reset {meaning : InferenceCacheMeaning} {before after : TcState .anon} + (valid : InferenceCacheInvariant meaning before) + (run : TcM.reset before = .ok () after) : InferenceCacheInvariant meaning after := by + cases run + exact valid.frame rfl rfl + +/-- Error isolation restores the complete trusted cache invariant, even if +the failed computation inserted results with no established meaning. -/ +theorem restoreCheckCachesOnError {meaning : InferenceCacheMeaning} + {before : TcState .anon} (valid : InferenceCacheInvariant meaning before) + (failed : TcState .anon) : + InferenceCacheInvariant meaning (before.restoreCheckCachesOnError failed) := + valid.frame rfl rfl + +theorem isolateCheckErrors {meaning : InferenceCacheMeaning} {action : TcM .anon α} + {before after : TcState .anon} {error : TcError .anon} + (valid : InferenceCacheInvariant meaning before) + (run : TcM.isolateCheckErrors action before = .error error after) : + InferenceCacheInvariant meaning after := by + unfold TcM.isolateCheckErrors at run + cases result : action before with + | ok value finished => rw [result] at run; contradiction + | error error failed => + rw [result] at run + cases run + exact valid.restoreCheckCachesOnError failed + +end InferenceCacheInvariant + +/-- Preservation includes the state returned on failure, because a caller +may catch an error and continue using the same environment. -/ +def PreservesInferenceInvariant (meaning : InferenceCacheMeaning) (action : TcM .anon α) : Prop := + ∀ before, InferenceCacheInvariant meaning before → + match action before with + | .ok _ after | .error _ after => InferenceCacheInvariant meaning after + +namespace PreservesInferenceInvariant + +theorem pure (meaning : InferenceCacheMeaning) (value : α) : + PreservesInferenceInvariant meaning (Pure.pure value) := fun _ valid => valid + +theorem bind {meaning : InferenceCacheMeaning} {action : TcM .anon α} + {next : α → TcM .anon γ} + (first : PreservesInferenceInvariant meaning action) + (rest : ∀ value, PreservesInferenceInvariant meaning (next value)) : + PreservesInferenceInvariant meaning (action >>= next) := by + intro before valid + have intermediate := first before valid + change match EStateM.bind action next before with + | .ok _ after | .error _ after => InferenceCacheInvariant meaning after + cases run : action before with + | error err after => + rw [EStateM.bind, run] + simpa only [run] using intermediate + | ok value after => + rw [run] at intermediate + rw [EStateM.bind, run] + exact rest value after intermediate + +theorem runIntern (meaning : InferenceCacheMeaning) (action : InternM .anon α) : + PreservesInferenceInvariant meaning (TcM.runIntern action) := by + intro before valid + exact valid.frame rfl rfl + +theorem withLctxScope {meaning : InferenceCacheMeaning} {action : RecM .anon α} + {methods : Methods .anon} + (body : PreservesInferenceInvariant meaning (action.run methods)) : + PreservesInferenceInvariant meaning ((RecM.withLctxScope action).run methods) := by + intro before valid + rw [withLctxScope_eq] + have inner := body before valid + cases run : action.run methods before <;> rw [run] at inner <;> + exact inner.frame rfl rfl + +theorem withInferOnly {meaning : InferenceCacheMeaning} {action : TcM .anon α} + (body : PreservesInferenceInvariant meaning action) : + PreservesInferenceInvariant meaning (TcM.withInferOnly action) := by + intro before valid + rw [withInferOnly_eq] + have inner := body {before with inferOnly := true} (valid.frame rfl rfl) + cases run : action {before with inferOnly := true} <;> rw [run] at inner <;> + exact inner.frame rfl rfl + +end PreservesInferenceInvariant + +/-- The actual key computation has a successful result for every state; +observing a hit or miss never requires a caller-supplied key witness. -/ +theorem inferKey_total (term : KExpr .anon) (before : TcState .anon) : + ∃ key after, TcM.inferKey term before = .ok key after := by + unfold TcM.inferKey TcM.ctxAddrForLbr + change ∃ key after, EStateM.bind (fun state => + EStateM.bind (get : TcM .anon (TcState .anon)) _ state) _ before = .ok key after + simp only [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] + by_cases fast : (term.lbr == 0 || before.ctx.isEmpty) = true + · rw [if_pos fast] + exact ⟨_, _, rfl⟩ + · rw [if_neg fast] + cases cached : before.ctxAddrCache[(before.ctxId, term.lbr)]? <;> exact ⟨_, _, rfl⟩ + +/-- Close the real inference cache shell around a proof of its uncached +body. Recursive body writes are included in `bodyValid`; each outer write is +handled here for every key and both partitions. No fragment tree, hit +agreement or write-footprint exclusion is an input. -/ +theorem InferenceCacheInvariant.infer {meaning : InferenceCacheMeaning} + {before after : TcState .anon} {term result : KExpr .anon} {methods : Methods .anon} + (valid : InferenceCacheInvariant meaning before) + (uncached : ∀ key keyed type finished, + TcM.inferKey term before = .ok key keyed → + InferenceCacheInvariant meaning keyed → + RecM.inferUncached RecM.inferCall before.inferOnly term methods keyed = + .ok type finished → + InferenceCacheInvariant meaning finished ∧ meaning before.inferOnly key type) + (run : RecM.infer term methods before = .ok result after) : + InferenceCacheInvariant meaning after ∧ + ∃ key keyed, TcM.inferKey term before = .ok key keyed ∧ + (meaning false key result ∨ (before.inferOnly = true ∧ meaning true key result)) := by + obtain ⟨key, keyed, keyRun⟩ := inferKey_total term before + rcases observeInferenceCache keyRun with ⟨hit, keyEq, stateEq⟩ | ⟨miss, keyEq, stateEq⟩ + · have hitRun := hit.run methods + rw [hitRun] at run + cases run + exact ⟨valid.inferKey hit.keyRun, hit.key, hit.keyed, hit.keyRun, valid.selected hit⟩ + · obtain ⟨finished, bodyRun, written⟩ := infer_uncached_success_state miss run + obtain ⟨bodyValid, fact⟩ := uncached miss.key miss.keyed result finished + miss.keyRun (valid.inferKey miss.keyRun) bodyRun + have writeRun : RecM.cacheInferResult before.inferOnly miss.key result methods finished = + .ok () after := by + rw [cacheInferResult_eq, written] + refine ⟨bodyValid.write fact writeRun, miss.key, miss.keyed, miss.keyRun, ?_⟩ + cases policy : before.inferOnly with + | false => exact .inl (by simpa only [policy] using fact) + | true => exact .inr ⟨rfl, by simpa only [policy] using fact⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/CacheLifecycle.lean b/Ix/Kernel/Verify/Consistency/CacheLifecycle.lean new file mode 100644 index 000000000..5dda13453 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/CacheLifecycle.lean @@ -0,0 +1,95 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.CacheInvariant +import Ix.Kernel.Driver + +/-! +# Inference-cache initialization and declaration boundaries + +The real lazy driver starts with empty caches. Failed declaration checks +restore their incoming cache facts; periodic clearing also preserves the +invariant. Thus only successful declaration checking has a remaining +preservation obligation in the serial loop. This module does not assume +that loaded declarations are already semantically admitted. +-/ + +namespace Ix.Kernel.Consistency + +namespace InferenceCacheInvariant + +theorem newLazyAnon (meaning : InferenceCacheMeaning) (source : Ixon.Env) (verify : Bool) : + InferenceCacheInvariant meaning (TcState.newLazyAnon source verify) := + empty rfl rfl + +theorem initialAnonCheckLoopState (meaning : InferenceCacheMeaning) + (source : Ixon.Env) (cfg : CheckCfg) : + InferenceCacheInvariant meaning (Kernel.initialAnonCheckLoopState source cfg).checker := + newLazyAnon meaning source cfg.verifyHashes + +/-- Every failure of the actual public constant checker returns the +restored pre-check inference maps, including a failure after recursive writes. -/ +theorem checkConst_error {meaning : InferenceCacheMeaning} {before after : TcState .anon} + {id : KId .anon} {error : TcError .anon} + (valid : InferenceCacheInvariant meaning before) + (run : TcM.checkConst id before = .error error after) : + InferenceCacheInvariant meaning after := by + unfold TcM.checkConst at run + exact valid.isolateCheckErrors run + +theorem finishAnonCheckItem {meaning : InferenceCacheMeaning} (cfg : CheckCfg) + (before : AnonCheckLoopState) (item : AnonWorkItem) {checker : TcState .anon} + (error : Option String) (valid : InferenceCacheInvariant meaning checker) : + InferenceCacheInvariant meaning (Kernel.finishAnonCheckItem cfg before item checker error).checker := by + unfold Kernel.finishAnonCheckItem + dsimp only + split + · exact clearReductionCaches meaning checker + · exact valid + +/-- The loop uses one preservation contract for successful declarations. +Error isolation and cache clearing are discharged from production code. -/ +theorem runAnonCheckItem {meaning : InferenceCacheMeaning} (cfg : CheckCfg) + (item : AnonWorkItem) {before : AnonCheckLoopState} + (valid : InferenceCacheInvariant meaning before.checker) + (checked : ∀ after, TcM.checkConst (⟨item.primary, ()⟩ : KId .anon) before.checker = + .ok () after → InferenceCacheInvariant meaning after) : + InferenceCacheInvariant meaning (Kernel.runAnonCheckItem cfg before item).checker := by + simp only [Kernel.runAnonCheckItem, EStateM.run] + cases run : TcM.checkConst (⟨item.primary, ()⟩ : KId .anon) before.checker with + | ok value after => + cases value + exact finishAnonCheckItem cfg before item none (checked after run) + | error error after => + exact finishAnonCheckItem cfg before item (some (toString error)) + (valid.checkConst_error run) + +theorem runAnonCheckList {meaning : InferenceCacheMeaning} (cfg : CheckCfg) + (work : List AnonWorkItem) {before : AnonCheckLoopState} + (valid : InferenceCacheInvariant meaning before.checker) + (checked : ∀ item ∈ work, ∀ state after, + InferenceCacheInvariant meaning state → + TcM.checkConst (⟨item.primary, ()⟩ : KId .anon) state = .ok () after → + InferenceCacheInvariant meaning after) : + InferenceCacheInvariant meaning (Kernel.runAnonCheckList cfg work before).checker := by + induction work generalizing before with + | nil => exact valid + | cons item rest ih => + exact ih (runAnonCheckItem cfg item valid + (fun after run => checked item (by simp) before.checker after valid run)) + (fun other member => checked other (by simp [member])) + +theorem initialized_runAnonCheckList (meaning : InferenceCacheMeaning) (source : Ixon.Env) + (cfg : CheckCfg) (work : List AnonWorkItem) + (checked : ∀ item ∈ work, ∀ state after, + InferenceCacheInvariant meaning state → + TcM.checkConst (⟨item.primary, ()⟩ : KId .anon) state = .ok () after → + InferenceCacheInvariant meaning after) : + InferenceCacheInvariant meaning (Kernel.runAnonCheckList cfg work + (Kernel.initialAnonCheckLoopState source cfg)).checker := + runAnonCheckList cfg work (initialAnonCheckLoopState meaning source cfg) checked + +end InferenceCacheInvariant +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Expr.lean b/Ix/Kernel/Verify/Consistency/Expr.lean index 2166660f7..c72315a3e 100644 --- a/Ix/Kernel/Verify/Consistency/Expr.lean +++ b/Ix/Kernel/Verify/Consistency/Expr.lean @@ -4,6 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Level +import Ix.Kernel.Verify.Consistency.StringReading import Ix.Kernel.Verify.Expr import Ix.Theory.Expr @@ -13,8 +14,8 @@ import Ix.Theory.Expr References are resolved to explicit block/member/constructor coordinates. The reader uses the expression tree, not cached hashes or scope annotations. It preserves projections and natural literals, and expands a let by -capture-avoiding substitution. Free variables, unresolved references, and -string literals have no reading in this initial fragment. +capture-avoiding substitution. String literals expand through the canonical +character and list primitives. Free variables and unresolved references fail. The theorems below connect the production hash-equality fast path and intern table to this reading. Their finite-support collision hypotheses are retained; @@ -51,7 +52,7 @@ def readExpr? (resolve : Address → Option (Theory.ConstRef β)) : let ref ← resolve id.addr return .proj ref index.toNat (← readExpr? resolve value) | .nat value _ _ => some (.natLit value) - | .str .. => none + | .str value _ _ => readString? resolve value /-- Hashing and display metadata do not change a smart-constructed sort. -/ @[simp] theorem readExpr?_mkSort diff --git a/Ix/Kernel/Verify/Consistency/InstUniv.lean b/Ix/Kernel/Verify/Consistency/InstUniv.lean index 2381f2840..89cd0e9f2 100644 --- a/Ix/Kernel/Verify/Consistency/InstUniv.lean +++ b/Ix/Kernel/Verify/Consistency/InstUniv.lean @@ -141,7 +141,7 @@ private theorem option_bind_success {α γ : Type _} {action : Option α} /-- Successful pure instantiation reads as model substitution, up to equivalent universe levels. All expression positions are covered; the reader's existing -exclusions of free variables, strings, and unresolved references are retained. -/ +exclusions of free variables and unresolved references are retained. -/ theorem instUnivSpec_readExpr?_withScope {resolve : Address → Option (ConstRef β)} {arguments : Array (KUniv .anon)} {term result : KExpr .anon} {source : VExpr β} (support : UniverseSubstitutionSupport arguments term) @@ -155,7 +155,12 @@ theorem instUnivSpec_readExpr?_withScope {resolve : Address → Option (ConstRef cases run cases reading exact ⟨_, rfl, .bvar _, fun _ _ => trivial⟩ - | fvar _ _ _ | str _ _ _ => contradiction + | fvar _ _ _ => contradiction + | str value _ _ => + cases run + refine ⟨source, reading, ?_, fun n _ => readString?_levelWF reading n⟩ + rw [readString?_instL reading] + exact VExpr.LevelEquivalent.refl source | nat value name info => cases run cases reading diff --git a/Ix/Kernel/Verify/Consistency/InternInvariant.lean b/Ix/Kernel/Verify/Consistency/InternInvariant.lean new file mode 100644 index 000000000..9e3c69002 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/InternInvariant.lean @@ -0,0 +1,89 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Expr +import Ix.Kernel.Monad + +/-! +# Maintained expression support for interning + +The pool includes the initial table and the finitely many candidates a +computation can create. Each insertion preserves key coherence and support; +finite key faithfulness then gives exact anonymous syntax for every result. +Universe interning preserves the same expression invariant. +-/ + +namespace Ix.Kernel.Consistency + +structure ExpressionInternInvariant (pool : KExpr .anon → Prop) + (table : InternTable .anon) : Prop where + coherent : table.WF + supported : ∀ term, table.ExprSupport term → pool term + +namespace ExpressionInternInvariant + +theorem empty (pool : KExpr .anon → Prop) : ExpressionInternInvariant pool .empty := by + refine ⟨.empty, ?_⟩ + intro term ⟨key, found⟩ + simp [InternTable.empty] at found + +theorem mono {pool larger : KExpr .anon → Prop} {table : InternTable .anon} + (valid : ExpressionInternInvariant pool table) (included : ∀ term, pool term → larger term) : + ExpressionInternInvariant larger table := + ⟨valid.coherent, fun term found => included term (valid.supported term found)⟩ + +theorem internExpr {pool : KExpr .anon → Prop} {table : InternTable .anon} + {candidate : KExpr .anon} (valid : ExpressionInternInvariant pool table) + (allowed : pool candidate) : ExpressionInternInvariant pool (table.internExpr candidate).2 := by + refine ⟨valid.coherent.internExpr candidate, ?_⟩ + intro term found + rcases InternTable.ExprSupport.of_internExpr found with old | rfl + · exact valid.supported term old + · exact allowed + +theorem internUniv {pool : KExpr .anon → Prop} {table : InternTable .anon} + (valid : ExpressionInternInvariant pool table) (level : KUniv .anon) : + ExpressionInternInvariant pool (table.internUniv level).2 := by + refine ⟨valid.coherent.internUniv level, ?_⟩ + intro term ⟨key, found⟩ + exact valid.supported term ⟨key, by simpa using found⟩ + +theorem result_eq {pool : KExpr .anon → Prop} {table : InternTable .anon} + {candidate : KExpr .anon} (valid : ExpressionInternInvariant pool table) + (faithful : KExpr.KeyCollisionFree pool) (allowed : pool candidate) : + (table.internExpr candidate).1 = candidate := by + have result := table.internExpr_eraseMeta valid.coherent (fun {_} left {_} right same => + faithful (left.elim (valid.supported _) (fun equal => equal.symm ▸ allowed)) + (right.elim (valid.supported _) (fun equal => equal.symm ▸ allowed)) same) + simpa only [KExpr.eraseMeta_anon] using result + +end ExpressionInternInvariant + +def internExprState (before : TcState .anon) (candidate : KExpr .anon) : TcState .anon := + {before with env := {before.env with intern := (before.env.intern.internExpr candidate).2}} + +theorem intern_eq {pool : KExpr .anon → Prop} {before : TcState .anon} + {candidate : KExpr .anon} (valid : ExpressionInternInvariant pool before.env.intern) + (faithful : KExpr.KeyCollisionFree pool) (allowed : pool candidate) : + TcM.intern candidate before = .ok candidate (internExprState before candidate) := by + change EStateM.Result.ok (before.env.intern.internExpr candidate).1 + (internExprState before candidate) = _ + rw [valid.result_eq faithful allowed] + +def internExprList (table : InternTable .anon) (candidates : List (KExpr .anon)) : + InternTable .anon := + candidates.foldl (fun current candidate => (current.internExpr candidate).2) table + +theorem ExpressionInternInvariant.internExprList {pool : KExpr .anon → Prop} + {table : InternTable .anon} (valid : ExpressionInternInvariant pool table) + (candidates : List (KExpr .anon)) (allowed : ∀ term ∈ candidates, pool term) : + ExpressionInternInvariant pool (internExprList table candidates) := by + induction candidates generalizing table with + | nil => exact valid + | cons term rest ih => + exact ih (valid.internExpr (allowed term (by simp))) + (fun term member => allowed term (by simp [member])) + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/ScopedExpr.lean b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean index 82dd5ebff..7f9b70275 100644 --- a/Ix/Kernel/Verify/Consistency/ScopedExpr.lean +++ b/Ix/Kernel/Verify/Consistency/ScopedExpr.lean @@ -4,6 +4,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 -/ import Ix.Kernel.Verify.Consistency.Expr +import Ix.Theory.ExprSubstitution import Ix.Theory.Model.LevelCongruence /-! @@ -12,8 +13,9 @@ import Ix.Theory.Model.LevelCongruence The production binder paths use free variables for their active locals. `readScopedExpr?` maps those identifiers to model de Bruijn indices, keeping syntactically bound variables distinct from active locals. Unknown free -variables and loose legacy variables fail. This binder fragment also excludes -lets and strings; the original closed reader remains available independently. +variables and loose legacy variables fail. Lets are read by capture-avoiding +substitution in the same context, including nested lets under binders. Strings +use the closed canonical character/list expansion. The local identifier list is newest first, matching `Model.Context.push`. No local declaration's type or semantic validity is assumed by this reader. @@ -85,7 +87,12 @@ def readScopedExpr? (resolve : Address → Option (ConstRef β)) (locals : List return .proj (← resolve id.addr) index.toNat (← readScopedExpr? resolve locals value depth) | .nat value _ _, _ => some (.natLit value) - | .letE .., _ | .str .., _ => none + | .letE _ domain value body _ _, depth => do + let _ ← readScopedExpr? resolve locals domain depth + let value ← readScopedExpr? resolve locals value depth + let body ← readScopedExpr? resolve locals body (depth + 1) + return body.inst value + | .str value _ _, _ => readString? resolve value @[simp] theorem readScopedExpr?_mkVar (resolve : Address → Option (ConstRef β)) (locals : List FVarId) (index : UInt64) (name : m.F Name) (depth : Nat) : @@ -127,6 +134,15 @@ def readScopedExpr? (resolve : Address → Option (ConstRef β)) (locals : List return .proj (← resolve id.addr) index.toNat (← readScopedExpr? resolve locals value depth) := rfl +@[simp] theorem readScopedExpr?_mkLet (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (name : m.F Name) (domain value body : KExpr m) + (nonDep : Bool) (depth : Nat) : + readScopedExpr? resolve locals (KExpr.mkLet name domain value body nonDep) depth = do + let _ ← readScopedExpr? resolve locals domain depth + let value ← readScopedExpr? resolve locals value depth + let body ← readScopedExpr? resolve locals body (depth + 1) + return body.inst value := rfl + private theorem option_bind_success {α γ : Type _} {action : Option α} {next : α → Option γ} {result : γ} (run : action.bind next = some result) : ∃ intermediate, action = some intermediate ∧ next intermediate = some result := by @@ -172,6 +188,21 @@ theorem readScopedExpr?_all_parts {resolve : Address → Option (ConstRef β)} cases reading exact ⟨domainReads, bodyReads⟩ +theorem readScopedExpr?_let_parts {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {name : m.F Name} {domain value body : KExpr m} + {nonDep : Bool} {info : ExprInfo m} {source : VExpr β} {depth : Nat} + (reading : readScopedExpr? resolve locals (.letE name domain value body nonDep info) + depth = some source) : + ∃ A v b, readScopedExpr? resolve locals domain depth = some A ∧ + readScopedExpr? resolve locals value depth = some v ∧ + readScopedExpr? resolve locals body (depth + 1) = some b ∧ source = b.inst v := by + rw [readScopedExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := option_bind_success reading + obtain ⟨v, valueReads, reading⟩ := option_bind_success reading + obtain ⟨b, bodyReads, reading⟩ := option_bind_success reading + cases reading + exact ⟨A, v, b, domainReads, valueReads, bodyReads, rfl⟩ + /-- A term readable without registered locals keeps that reading in any local context. Its syntactic binders retain the same indices. -/ theorem readScopedExpr?_weaken_closed {resolve : Address → Option (ConstRef β)} @@ -179,8 +210,11 @@ theorem readScopedExpr?_weaken_closed {resolve : Address → Option (ConstRef β (reading : readScopedExpr? resolve [] term depth = some source) (locals : List FVarId) : readScopedExpr? resolve locals term depth = some source := by induction term generalizing source depth with - | var _ _ _ | sort _ _ | const _ _ _ | nat _ _ _ => exact reading - | fvar _ _ _ | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | var _ _ _ | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => exact reading + | fvar _ _ _ => contradiction + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readScopedExpr?_let_parts reading + simp [readScopedExpr?, hA aReads, hv vReads, hb bReads] | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => rw [readScopedExpr?] at reading obtain ⟨f, fReads, reading⟩ := option_bind_success reading @@ -205,8 +239,11 @@ theorem readScopedExpr?_closed {resolve : Address → Option (ConstRef β)} split at reading · exact reading · contradiction - | fvar _ _ _ | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction - | sort _ _ | const _ _ _ | nat _ _ _ => exact reading + | fvar _ _ _ => contradiction + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readScopedExpr?_let_parts reading + simp [readExpr?, hA aReads, hv vReads, hb bReads] + | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => exact reading | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => rw [readScopedExpr?] at reading obtain ⟨f, fReads, reading⟩ := option_bind_success reading @@ -268,7 +305,12 @@ theorem readScopedExpr?_push {resolve : Address → Option (ConstRef β)} cases reading simp [readScopedExpr?, localIndex?_fresh absent found, VExpr.liftN, liftVar, Nat.not_lt.mpr (Nat.le_add_right depth index), Nat.add_assoc, Nat.add_comm 1] - | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction + | str value _ _ => + rw [readString?_liftN reading] + exact reading + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readScopedExpr?_let_parts reading + simp [readScopedExpr?, hA aReads, hv vReads, hb bReads, VExpr.liftN_inst_hi] | sort level info => cases reading; rfl | nat value name info => cases reading; rfl | const id levels info => diff --git a/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean b/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean index 1cb237e01..6aadb54e5 100644 --- a/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean +++ b/Ix/Kernel/Verify/Consistency/ScopedInstUniv.lean @@ -51,8 +51,18 @@ theorem instUnivSpec_scoped_eq {resolve : Address → Option (ConstRef β)} split at reading next bound => simp [bound, readExpr?] · contradiction - | fvar _ _ _ | letE _ _ _ _ _ _ _ _ _ | str _ _ _ => contradiction - | nat _ _ _ => cases run; rfl + | fvar _ _ _ => contradiction + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, _⟩ := readScopedExpr?_let_parts reading + rw [KExpr.instUnivSpec] at run + obtain ⟨domain', aRun, run⟩ := except_bind_success run + obtain ⟨value', vRun, run⟩ := except_bind_success run + obtain ⟨body', bRun, run⟩ := except_bind_success run + cases run + simp only [readScopedExpr?_mkLet] + rw [hA aReads aRun, hv vReads vRun, hb bReads bRun] + rfl + | nat _ _ _ | str _ _ _ => cases run; rfl | sort _ _ | const _ _ _ => rw [KExpr.instUnivSpec] at run obtain ⟨_, _, run⟩ := except_bind_success run diff --git a/Ix/Kernel/Verify/Consistency/StringExpansion.lean b/Ix/Kernel/Verify/Consistency/StringExpansion.lean new file mode 100644 index 000000000..cd288aa0d --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/StringExpansion.lean @@ -0,0 +1,316 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.InternInvariant +import Ix.Kernel.Verify.Consistency.ScopedExpr +import Ix.Kernel.Whnf + +/-! +# Production string expansion + +The candidate list is computed from the source characters and primitive +expressions. One collision condition on that list plus the initial table +discharges every intern call. The result and complete final state follow +from the actual production recursion, without a supplied execution plan. +-/ + +namespace Ix.Kernel.Consistency + +open Theory + +namespace StringExpansion + +attribute [local irreducible] InternTable.internExpr + +def charValue (charOfNat : KExpr .anon) (char : Char) : KExpr .anon := + .mkApp charOfNat (RecM.natExprFromValue char.toNat) + +def listStep (charOfNat cons : KExpr .anon) (char : Char) (list : KExpr .anon) : KExpr .anon := + .mkApp (.mkApp cons (charValue charOfNat char)) list + +def listResult (charOfNat cons : KExpr .anon) : List Char → KExpr .anon → KExpr .anon + | [], list => list + | char :: chars, list => listResult charOfNat cons chars (listStep charOfNat cons char list) + +def listCandidates (charOfNat cons : KExpr .anon) : List Char → KExpr .anon → List (KExpr .anon) + | [], _ => [] + | char :: chars, list => + RecM.natExprFromValue char.toNat :: charValue charOfNat char :: + KExpr.mkApp cons (charValue charOfNat char) :: listStep charOfNat cons char list :: + listCandidates charOfNat cons chars (listStep charOfNat cons char list) + +theorem listCandidates_length (charOfNat cons : KExpr .anon) (chars : List Char) + (list : KExpr .anon) : (listCandidates charOfNat cons chars list).length = 4 * chars.length := by + induction chars generalizing list with + | nil => rfl + | cons char chars ih => simp [listCandidates, ih, Nat.mul_add, Nat.add_assoc] + +theorem list_run {pool : KExpr .anon → Prop} (faithful : KExpr.KeyCollisionFree pool) + (methods : Methods .anon) (charOfNat cons : KExpr .anon) (chars : List Char) + (list : KExpr .anon) {before : TcState .anon} + (valid : ExpressionInternInvariant pool before.env.intern) + (allowed : ∀ term ∈ listCandidates charOfNat cons chars list, pool term) : + (RecM.strLitListToConstructor charOfNat cons chars list).run methods before = + .ok (listResult charOfNat cons chars list) + {before with env := {before.env with intern := (internExprList before.env.intern + (listCandidates charOfNat cons chars list))}} := by + induction chars generalizing list before with + | nil => rfl + | cons char chars ih => + let n : KExpr .anon := RecM.natExprFromValue char.toNat + let c := charValue charOfNat char + let headApp := KExpr.mkApp cons c + let next := listStep charOfNat cons char list + have hn : pool n := allowed n (by simp [n, listCandidates]) + have hc : pool c := allowed c (by simp [c, listCandidates]) + have hp : pool headApp := allowed headApp (by simp [headApp, c, listCandidates]) + have hl : pool next := allowed next (by simp [next, listCandidates]) + let s1 := internExprState before n + let s2 := internExprState s1 c + let s3 := internExprState s2 headApp + let s4 := internExprState s3 next + have v1 : ExpressionInternInvariant pool s1.env.intern := valid.internExpr hn + have v2 : ExpressionInternInvariant pool s2.env.intern := v1.internExpr hc + have v3 : ExpressionInternInvariant pool s3.env.intern := v2.internExpr hp + have v4 : ExpressionInternInvariant pool s4.env.intern := v3.internExpr hl + have tailAllowed : ∀ term ∈ listCandidates charOfNat cons chars next, pool term := by + intro term member + exact allowed term (by simp [listCandidates, next, member]) + have tailRun := ih next v4 tailAllowed + unfold RecM.strLitListToConstructor + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern n) _ before = _ + rw [EStateM.bind, intern_eq valid faithful hn] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern c) _ s1 = _ + rw [EStateM.bind, intern_eq v1 faithful hc] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern headApp) _ s2 = _ + rw [EStateM.bind, intern_eq v2 faithful hp] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern next) _ s3 = _ + rw [EStateM.bind, intern_eq v3 faithful hl] + simp only + simpa only [listResult, listCandidates, internExprList, List.foldl_cons, + s4, s3, s2, s1, internExprState, n, c, headApp, next] using tailRun + + +def charType (prims : Primitives .anon) : KExpr .anon := .mkConst prims.charType #[] +def charFunction (prims : Primitives .anon) : KExpr .anon := .mkConst prims.charOfNat #[] +def stringFunction (prims : Primitives .anon) : KExpr .anon := .mkConst prims.stringOfList #[] +def nilFunction (prims : Primitives .anon) : KExpr .anon := .mkConst prims.listNil #[.mkZero] +def nilValue (prims : Primitives .anon) : KExpr .anon := .mkApp (nilFunction prims) (charType prims) +def consFunction (prims : Primitives .anon) : KExpr .anon := .mkConst prims.listCons #[.mkZero] +def consValue (prims : Primitives .anon) : KExpr .anon := .mkApp (consFunction prims) (charType prims) + +def prefixNodes (prims : Primitives .anon) : List (KExpr .anon) := + [charType prims, charFunction prims, stringFunction prims, nilFunction prims, + nilValue prims, consFunction prims, consValue prims] + +def result (prims : Primitives .anon) (value : String) : KExpr .anon := + .mkApp (stringFunction prims) + (listResult (charFunction prims) (consValue prims) value.toList.reverse (nilValue prims)) + +def candidates (prims : Primitives .anon) (value : String) : List (KExpr .anon) := + prefixNodes prims ++ + listCandidates (charFunction prims) (consValue prims) value.toList.reverse (nilValue prims) ++ + [result prims value] + +theorem candidates_length (prims : Primitives .anon) (value : String) : + (candidates prims value).length = 8 + 4 * value.toList.length := by + simp only [candidates, prefixNodes, List.length_append, List.length_cons, List.length_nil, + listCandidates_length, List.length_reverse] + omega + +/-- Exact production execution for every string, including empty strings and +repeated characters. No method callback is used by this operation. -/ +theorem run {pool : KExpr .anon → Prop} (faithful : KExpr.KeyCollisionFree pool) + (methods : Methods .anon) (value : String) {before : TcState .anon} + (valid : ExpressionInternInvariant pool before.env.intern) + (allowed : ∀ term ∈ candidates before.prims value, pool term) : + (RecM.strLitToConstructor value).run methods before = + .ok (result before.prims value) + {before with env := {before.env with intern := (internExprList before.env.intern + (candidates before.prims value))}} := by + let p := before.prims + have h1 : pool (charType p) := allowed _ (by simp [candidates, prefixNodes, p]) + let s1 := internExprState before (charType p) + have v1 : ExpressionInternInvariant pool s1.env.intern := valid.internExpr h1 + have h2 : pool (charFunction p) := allowed _ (by simp [candidates, prefixNodes, p]) + let s2 := internExprState s1 (charFunction p) + have v2 : ExpressionInternInvariant pool s2.env.intern := v1.internExpr h2 + have h3 : pool (stringFunction p) := allowed _ (by simp [candidates, prefixNodes, p]) + let s3 := internExprState s2 (stringFunction p) + have v3 : ExpressionInternInvariant pool s3.env.intern := v2.internExpr h3 + have h4 : pool (nilFunction p) := allowed _ (by simp [candidates, prefixNodes, p]) + let s4 := internExprState s3 (nilFunction p) + have v4 : ExpressionInternInvariant pool s4.env.intern := v3.internExpr h4 + have h5 : pool (nilValue p) := allowed _ (by simp [candidates, prefixNodes, p]) + let s5 := internExprState s4 (nilValue p) + have v5 : ExpressionInternInvariant pool s5.env.intern := v4.internExpr h5 + have h6 : pool (consFunction p) := allowed _ (by simp [candidates, prefixNodes, p]) + let s6 := internExprState s5 (consFunction p) + have v6 : ExpressionInternInvariant pool s6.env.intern := v5.internExpr h6 + have h7 : pool (consValue p) := allowed _ (by simp [candidates, prefixNodes, p]) + let s7 := internExprState s6 (consValue p) + have v7 : ExpressionInternInvariant pool s7.env.intern := v6.internExpr h7 + have listAllowed : ∀ term ∈ listCandidates (charFunction p) (consValue p) + value.toList.reverse (nilValue p), pool term := by + intro term member + exact allowed term (by simp [candidates, p, member]) + have lastAllowed : pool (result p value) := allowed _ (by simp [candidates, p]) + let s8 : TcState .anon := + {s7 with env := {s7.env with intern := (internExprList s7.env.intern + (listCandidates (charFunction p) (consValue p) value.toList.reverse (nilValue p)))}} + have v8 : ExpressionInternInvariant pool s8.env.intern := + v7.internExprList _ listAllowed + have listRun := list_run faithful methods (charFunction p) (consValue p) + value.toList.reverse (nilValue p) v7 listAllowed + unfold RecM.strLitToConstructor + rw [ReaderT.run_bind] + change EStateM.bind (ReaderT.run RecM.prims methods) _ before = _ + rw [EStateM.bind, show ReaderT.run RecM.prims methods before = .ok p before from rfl] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern (charType p)) _ before = _ + rw [EStateM.bind, intern_eq valid faithful h1] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern (charFunction p)) _ s1 = _ + rw [EStateM.bind, intern_eq v1 faithful h2] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern (stringFunction p)) _ s2 = _ + rw [EStateM.bind, intern_eq v2 faithful h3] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern (nilFunction p)) _ s3 = _ + rw [EStateM.bind, intern_eq v3 faithful h4] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern (nilValue p)) _ s4 = _ + rw [EStateM.bind, intern_eq v4 faithful h5] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern (consFunction p)) _ s5 = _ + rw [EStateM.bind, intern_eq v5 faithful h6] + simp only + rw [ReaderT.run_bind, ReaderT.run_monadLift] + change EStateM.bind (TcM.intern (consValue p)) _ s6 = _ + rw [EStateM.bind, intern_eq v6 faithful h7] + simp only + rw [ReaderT.run_bind] + change EStateM.bind + (ReaderT.run (RecM.strLitListToConstructor (charFunction p) (consValue p) + value.toList.reverse (nilValue p)) methods) _ s7 = _ + rw [EStateM.bind, listRun] + simp only + rw [ReaderT.run_monadLift] + change TcM.intern (result p value) s8 = _ + rw [intern_eq v8 faithful lastAllowed] + simp only [s8, s7, s6, s5, s4, s3, s2, s1, internExprState, + candidates, prefixNodes, internExprList, List.foldl_append, List.foldl_cons, + List.foldl_nil, p] + +/-- A single finite-support assumption supplies all the internal memberships. +The theorem also preserves the invariant for the complete final table. -/ +theorem run_finite (methods : Methods .anon) (value : String) (before : TcState .anon) + (coherent : before.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun term => before.env.intern.ExprSupport term ∨ + term ∈ candidates before.prims value) : + (RecM.strLitToConstructor value).run methods before = + .ok (result before.prims value) + {before with env := {before.env with intern := (internExprList before.env.intern + (candidates before.prims value))}} ∧ + ExpressionInternInvariant + (fun term => before.env.intern.ExprSupport term ∨ term ∈ candidates before.prims value) + (internExprList before.env.intern (candidates before.prims value)) := by + have valid : ExpressionInternInvariant + (fun term => before.env.intern.ExprSupport term ∨ term ∈ candidates before.prims value) + before.env.intern := ⟨coherent, fun _ member => .inl member⟩ + exact ⟨run faithful methods value valid (fun _ member => .inr member), + valid.internExprList _ (fun _ member => .inr member)⟩ + + +theorem listResult_read {β : Type u} {resolve : Address → Option (ConstRef β)} + {locals : List FVarId} {depth : Nat} (refs : StringPrimitiveRefs β) + {charOfNat cons : KExpr .anon} (chars : List Char) {list : KExpr .anon} {source : VExpr β} + (charReads : readScopedExpr? resolve locals charOfNat depth = some (.const refs.charOfNat [])) + (consReads : readScopedExpr? resolve locals cons depth = some refs.consExpr) + (listReads : readScopedExpr? resolve locals list depth = some source) : + readScopedExpr? resolve locals (listResult charOfNat cons chars list) depth = + some (chars.foldl (fun current char => + .app (.app refs.consExpr (refs.charExpr char)) current) source) := by + induction chars generalizing list source with + | nil => exact listReads + | cons char chars ih => + apply ih + simp [listStep, charValue, RecM.natExprFromValue, readScopedExpr?, + charReads, consReads, listReads, StringPrimitiveRefs.charExpr, KExpr.mkNat] + +theorem result_read {β : Type u} {resolve : Address → Option (ConstRef β)} + (locals : List FVarId) (depth : Nat) (value : String) {refs : StringPrimitiveRefs β} + (resolved : StringPrimitiveRefs.resolve? resolve = some refs) : + readScopedExpr? resolve locals (result Primitives.ofAnonAddrs value) depth = + some (refs.expr value) := by + obtain ⟨typeResolved, charResolved, stringResolved, nilResolved, consResolved⟩ := + StringPrimitiveRefs.resolve?_fields resolved + have charReads : readScopedExpr? resolve locals (charFunction Primitives.ofAnonAddrs) depth = + some (.const refs.charOfNat []) := by + change (do return VExpr.const (← resolve PrimAddrs.canonical.charOfNat) []) = _ + simp [charResolved] + have typeReads : readScopedExpr? resolve locals (charType Primitives.ofAnonAddrs) depth = + some (.const refs.charType []) := by + change (do return VExpr.const (← resolve PrimAddrs.canonical.charType) []) = _ + simp [typeResolved] + have consFnReads : readScopedExpr? resolve locals (consFunction Primitives.ofAnonAddrs) depth = + some (.const refs.listCons [.zero]) := by + change (do return VExpr.const (← resolve PrimAddrs.canonical.listCons) [.zero]) = _ + simp [consResolved] + have nilFnReads : readScopedExpr? resolve locals (nilFunction Primitives.ofAnonAddrs) depth = + some (.const refs.listNil [.zero]) := by + change (do return VExpr.const (← resolve PrimAddrs.canonical.listNil) [.zero]) = _ + simp [nilResolved] + have stringFnReads : readScopedExpr? resolve locals (stringFunction Primitives.ofAnonAddrs) depth = + some (.const refs.stringOfList []) := by + change (do return VExpr.const (← resolve PrimAddrs.canonical.stringOfList) []) = _ + simp [stringResolved] + have consReads : readScopedExpr? resolve locals (consValue Primitives.ofAnonAddrs) depth = + some refs.consExpr := by + simp [consValue, consFnReads, typeReads, StringPrimitiveRefs.consExpr] + have nilReads : readScopedExpr? resolve locals (nilValue Primitives.ofAnonAddrs) depth = + some refs.nilExpr := by + simp [nilValue, nilFnReads, typeReads, StringPrimitiveRefs.nilExpr] + have listReads := listResult_read refs value.toList.reverse charReads consReads nilReads + simp only [List.foldl_reverse] at listReads + unfold result + rw [readScopedExpr?_mkApp, listReads] + simp [stringFnReads, StringPrimitiveRefs.expr, StringPrimitiveRefs.listExpr] + +/-- The actual output has exactly the string literal's structural reading. +The public hypotheses are canonical primitives, resolvable references, +table coherence and collision freedom on the explicit finite allocation list. -/ +theorem read_of_run {β : Type u} {resolve : Address → Option (ConstRef β)} + {methods : Methods .anon} {value : String} {before after : TcState .anon} + {output : KExpr .anon} {source : VExpr β} + (canonical : before.prims = Primitives.ofAnonAddrs) + (reading : readString? resolve value = some source) + (coherent : before.env.intern.WF) + (faithful : KExpr.KeyCollisionFree fun term => before.env.intern.ExprSupport term ∨ + term ∈ candidates before.prims value) + (accepted : (RecM.strLitToConstructor value).run methods before = .ok output after) + (locals : List FVarId) (depth : Nat) : + readScopedExpr? resolve locals output depth = some source ∧ after.env.intern.WF := by + obtain ⟨run, valid⟩ := run_finite methods value before coherent faithful + rw [run] at accepted + cases accepted + obtain ⟨refs, resolved, rfl⟩ := readString?_parts reading + exact ⟨by simpa only [canonical] using result_read locals depth value resolved, valid.coherent⟩ + +end StringExpansion +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/StringReading.lean b/Ix/Kernel/Verify/Consistency/StringReading.lean new file mode 100644 index 000000000..609dc85b5 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/StringReading.lean @@ -0,0 +1,157 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Primitive +import Ix.Theory.Expr + +/-! +# Structural reading of string literals + +The reading uses the same five canonical primitives as production's +`strLitToConstructor`. It expands characters through `Char.ofNat` and lists +through `List.nil`/`List.cons`, preserving source order. Unknown primitive +references fail just as unknown explicit constants do. No new model syntax +or assumed meaning for the primitives is introduced here. +-/ + +namespace Ix.Kernel.Consistency + +open Theory + +universe u +variable {β : Type u} + +structure StringPrimitiveRefs (β : Type u) where + charType : ConstRef β + charOfNat : ConstRef β + stringOfList : ConstRef β + listNil : ConstRef β + listCons : ConstRef β + +namespace StringPrimitiveRefs + +def resolve? (resolve : Address → Option (ConstRef β)) : Option (StringPrimitiveRefs β) := do + return ⟨← resolve PrimAddrs.canonical.charType, ← resolve PrimAddrs.canonical.charOfNat, + ← resolve PrimAddrs.canonical.stringOfList, ← resolve PrimAddrs.canonical.listNil, + ← resolve PrimAddrs.canonical.listCons⟩ + +theorem resolve?_fields {resolve : Address → Option (ConstRef β)} + {refs : StringPrimitiveRefs β} (reading : resolve? resolve = some refs) : + resolve PrimAddrs.canonical.charType = some refs.charType ∧ + resolve PrimAddrs.canonical.charOfNat = some refs.charOfNat ∧ + resolve PrimAddrs.canonical.stringOfList = some refs.stringOfList ∧ + resolve PrimAddrs.canonical.listNil = some refs.listNil ∧ + resolve PrimAddrs.canonical.listCons = some refs.listCons := by + unfold resolve? at reading + obtain ⟨typeRef, typeReads, reading⟩ := Option.bind_eq_some_iff.mp reading + obtain ⟨charRef, charReads, reading⟩ := Option.bind_eq_some_iff.mp reading + obtain ⟨stringRef, stringReads, reading⟩ := Option.bind_eq_some_iff.mp reading + obtain ⟨nilRef, nilReads, reading⟩ := Option.bind_eq_some_iff.mp reading + obtain ⟨consRef, consReads, reading⟩ := Option.bind_eq_some_iff.mp reading + cases reading + exact ⟨typeReads, charReads, stringReads, nilReads, consReads⟩ + +def charExpr (refs : StringPrimitiveRefs β) (char : Char) : VExpr β := + .app (.const refs.charOfNat []) (.natLit char.toNat) + +def nilExpr (refs : StringPrimitiveRefs β) : VExpr β := + .app (.const refs.listNil [.zero]) (.const refs.charType []) + +def consExpr (refs : StringPrimitiveRefs β) : VExpr β := + .app (.const refs.listCons [.zero]) (.const refs.charType []) + +def listExpr (refs : StringPrimitiveRefs β) (chars : List Char) : VExpr β := + chars.foldr (fun char rest => .app (.app refs.consExpr (refs.charExpr char)) rest) refs.nilExpr + +def expr (refs : StringPrimitiveRefs β) (value : String) : VExpr β := + .app (.const refs.stringOfList []) (refs.listExpr value.toList) + +@[simp] theorem listExpr_liftN (refs : StringPrimitiveRefs β) (chars : List Char) + (shift cutoff : Nat) : (refs.listExpr chars).liftN shift cutoff = refs.listExpr chars := by + induction chars <;> + simp_all [listExpr, charExpr, nilExpr, consExpr, VExpr.liftN] + +@[simp] theorem expr_liftN (refs : StringPrimitiveRefs β) (value : String) + (shift cutoff : Nat) : (refs.expr value).liftN shift cutoff = refs.expr value := by + simp [expr, VExpr.liftN] + +@[simp] theorem listExpr_inst (refs : StringPrimitiveRefs β) (chars : List Char) + (arg : VExpr β) (cutoff : Nat) : (refs.listExpr chars).inst arg cutoff = refs.listExpr chars := by + induction chars <;> + simp_all [listExpr, charExpr, nilExpr, consExpr, VExpr.inst] + +@[simp] theorem expr_inst (refs : StringPrimitiveRefs β) (value : String) + (arg : VExpr β) (cutoff : Nat) : (refs.expr value).inst arg cutoff = refs.expr value := by + simp [expr, VExpr.inst] + +@[simp] theorem listExpr_instL (refs : StringPrimitiveRefs β) (chars : List Char) + (levels : List VLevel) : (refs.listExpr chars).instL levels = refs.listExpr chars := by + induction chars <;> + simp_all [listExpr, charExpr, nilExpr, consExpr, VExpr.instL, VLevel.inst] + +@[simp] theorem expr_instL (refs : StringPrimitiveRefs β) (value : String) + (levels : List VLevel) : (refs.expr value).instL levels = refs.expr value := by + simp [expr, VExpr.instL] + +theorem listExpr_closed (refs : StringPrimitiveRefs β) (chars : List Char) (depth : Nat) : + (refs.listExpr chars).ClosedN depth := by + induction chars <;> + simp_all [listExpr, charExpr, nilExpr, consExpr, VExpr.ClosedN] + +theorem expr_closed (refs : StringPrimitiveRefs β) (value : String) (depth : Nat) : + (refs.expr value).ClosedN depth := by + simpa only [expr, VExpr.ClosedN, true_and] using refs.listExpr_closed value.toList depth + +theorem listExpr_levelWF (refs : StringPrimitiveRefs β) (chars : List Char) (arity : Nat) : + (refs.listExpr chars).LevelWF arity := by + induction chars <;> + simp_all [listExpr, charExpr, nilExpr, consExpr, VExpr.LevelWF, VLevel.WF] + +theorem expr_levelWF (refs : StringPrimitiveRefs β) (value : String) (arity : Nat) : + (refs.expr value).LevelWF arity := by + simpa [expr, VExpr.LevelWF] using refs.listExpr_levelWF value.toList arity + +end StringPrimitiveRefs + +def readString? (resolve : Address → Option (ConstRef β)) (value : String) : Option (VExpr β) := + (StringPrimitiveRefs.resolve? resolve).map (·.expr value) + +theorem readString?_parts {resolve : Address → Option (ConstRef β)} {value : String} + {source : VExpr β} (reading : readString? resolve value = some source) : + ∃ refs, StringPrimitiveRefs.resolve? resolve = some refs ∧ source = refs.expr value := by + obtain ⟨refs, resolved, same⟩ := Option.map_eq_some_iff.mp reading + exact ⟨refs, resolved, same.symm⟩ + +theorem readString?_liftN {resolve : Address → Option (ConstRef β)} {value : String} + {source : VExpr β} (reading : readString? resolve value = some source) (shift cutoff : Nat) : + source.liftN shift cutoff = source := by + obtain ⟨refs, _, rfl⟩ := readString?_parts reading + exact refs.expr_liftN value shift cutoff + +theorem readString?_inst {resolve : Address → Option (ConstRef β)} {value : String} + {source : VExpr β} (reading : readString? resolve value = some source) + (arg : VExpr β) (cutoff : Nat) : source.inst arg cutoff = source := by + obtain ⟨refs, _, rfl⟩ := readString?_parts reading + exact refs.expr_inst value arg cutoff + +theorem readString?_instL {resolve : Address → Option (ConstRef β)} {value : String} + {source : VExpr β} (reading : readString? resolve value = some source) + (levels : List VLevel) : source.instL levels = source := by + obtain ⟨refs, _, rfl⟩ := readString?_parts reading + exact refs.expr_instL value levels + +theorem readString?_closed {resolve : Address → Option (ConstRef β)} {value : String} + {source : VExpr β} (reading : readString? resolve value = some source) (depth : Nat) : + source.ClosedN depth := by + obtain ⟨refs, _, rfl⟩ := readString?_parts reading + exact refs.expr_closed value depth + +theorem readString?_levelWF {resolve : Address → Option (ConstRef β)} {value : String} + {source : VExpr β} (reading : readString? resolve value = some source) (arity : Nat) : + source.LevelWF arity := by + obtain ⟨refs, _, rfl⟩ := readString?_parts reading + exact refs.expr_levelWF value arity + +end Ix.Kernel.Consistency diff --git a/Ix/Theory/ExprSubstitution.lean b/Ix/Theory/ExprSubstitution.lean new file mode 100644 index 000000000..54a6c3380 --- /dev/null +++ b/Ix/Theory/ExprSubstitution.lean @@ -0,0 +1,161 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Expr + +/-! +# Substitution through erased lets + +The structural reader eliminates a let by substitution. These syntactic +identities allow context extension and production substitution to commute +with that elimination, including inside dependent binders. The proofs use +the anonymous model syntax directly and include projections and literals. +-/ + +namespace Ix.Theory + +universe u +variable {β : Type u} + +theorem liftVar_lt {i k n : Nat} (h : i < k) : liftVar n i k = i := if_pos h +theorem liftVar_le {i k n : Nat} (h : k ≤ i) : liftVar n i k = n + i := + if_neg (Nat.not_lt.mpr h) + +namespace VExpr + +@[simp] theorem liftN_zero (e : VExpr β) (k : Nat) : e.liftN 0 k = e := by + induction e generalizing k <;> simp_all [liftN, liftVar] + +theorem liftN_combine {e : VExpr β} {n₁ n₂ k₁ k₂ : Nat} + (lower : k₁ ≤ k₂) (upper : k₂ ≤ n₁ + k₁) : + (e.liftN n₁ k₁).liftN n₂ k₂ = e.liftN (n₁ + n₂) k₁ := by + induction e generalizing k₁ k₂ with + | bvar i => + simp only [liftN, liftVar, VExpr.bvar.injEq] + split <;> split <;> omega + | lam _ _ hA hb | forallE _ _ hA hb => + simp only [liftN, hA lower upper, + hb (k₁ := k₁ + 1) (k₂ := k₂ + 1) (by omega) (by omega)] + | _ => simp_all [liftN] + +theorem liftN_comm (e : VExpr β) (n₁ n₂ k₁ k₂ : Nat) (order : k₂ ≤ k₁) : + (e.liftN n₁ k₁).liftN n₂ k₂ = (e.liftN n₂ k₂).liftN n₁ (n₂ + k₁) := by + induction e generalizing k₁ k₂ with + | bvar i => + simp only [liftN, liftVar, VExpr.bvar.injEq] + split <;> split <;> (try split) <;> (try split) <;> omega + | lam _ _ hA hb | forallE _ _ hA hb => + simp only [liftN, hA k₁ k₂ order, Nat.add_assoc, + hb (k₁ + 1) (k₂ + 1) (by omega)] + | _ => simp_all [liftN] + +theorem liftN_instVar_lo (n : Nat) (e : VExpr β) (i j k : Nat) (order : k ≤ j) : + (instVar i e j).liftN n k = instVar (liftVar n i k) e (n + j) := by + simp only [instVar] + split <;> rename_i before + · rw [if_pos] + · rfl + · simp only [liftVar]; split <;> omega + split <;> rename_i equal + · subst i + rw [liftN_combine (Nat.zero_le _) order, liftVar_le order, + if_neg (by omega), if_pos rfl, Nat.add_comm] + · have greater : j < i := by omega + rw [liftVar_le (by omega : k ≤ i), if_neg (by omega), if_neg (by omega)] + simp only [liftN, liftVar_le (by omega : k ≤ i - 1), VExpr.bvar.injEq] + omega + +theorem liftN_inst_lo (n : Nat) (e a : VExpr β) (j k : Nat) (order : k ≤ j) : + (e.inst a j).liftN n k = (e.liftN n k).inst a (n + j) := by + induction e generalizing j k with + | bvar i => exact liftN_instVar_lo n a i j k order + | lam _ _ hA hb | forallE _ _ hA hb => + simp only [inst, liftN, hA j k order, hb (j + 1) (k + 1) (by omega), Nat.add_assoc] + | _ => simp_all [inst, liftN] + +theorem liftN_instVar_hi (i : Nat) (a : VExpr β) (n k j : Nat) : + (instVar i a j).liftN n (k + j) = + instVar (liftVar n i (k + j + 1)) (a.liftN n k) j := by + simp only [instVar] + split <;> rename_i before + · rw [liftVar_lt (by omega : i < k + j + 1), if_pos before] + simp [liftN, liftVar_lt (by omega : i < k + j)] + split <;> rename_i equal + · subst i + simp only [liftVar_lt (by omega : j < k + j + 1), Nat.lt_irrefl, + if_false, if_true] + rw [liftN_comm a n j k 0 (Nat.zero_le _), Nat.add_comm] + · by_cases cut : i < k + j + 1 + · rw [liftVar_lt cut, if_neg before, if_neg equal] + simp [liftN, liftVar_lt (by omega : i - 1 < k + j)] + · rw [liftVar_le (by omega : k + j + 1 ≤ i), if_neg (by omega), if_neg (by omega)] + simp only [liftN, liftVar_le (by omega : k + j ≤ i - 1), VExpr.bvar.injEq] + omega + +theorem liftN_inst_hi_at (e a : VExpr β) (n k j : Nat) : + (e.inst a j).liftN n (k + j) = + (e.liftN n (k + j + 1)).inst (a.liftN n k) j := by + induction e generalizing j with + | bvar i => exact liftN_instVar_hi i a n k j + | lam _ _ hA hb | forallE _ _ hA hb => + simp only [inst, liftN, hA, Nat.add_assoc, hb] + | _ => simp_all [inst, liftN] + +theorem liftN_inst_hi (e a : VExpr β) (n k : Nat) : + (e.inst a).liftN n k = (e.liftN n (k + 1)).inst (a.liftN n k) := + liftN_inst_hi_at e a n k 0 + +theorem inst_liftN (e a : VExpr β) (k : Nat) : (e.liftN 1 k).inst a k = e := by + induction e generalizing k with + | bvar i => + simp only [liftN, inst, liftVar] + split <;> rename_i before + · simp [instVar, before] + · simp only [instVar, if_neg (by omega : ¬ 1 + i < k), + if_neg (by omega : 1 + i ≠ k), VExpr.bvar.injEq] + omega + | _ => simp_all [liftN, inst] + +theorem inst_instVar_hi (i : Nat) (a b : VExpr β) (k j : Nat) : + (instVar i a k).inst b (j + k) = + (instVar i b (j + k + 1)).inst (a.inst b j) k := by + simp only [instVar] + split <;> rename_i before + · simp [inst, instVar, before, show i < j + k + 1 by omega, + show i < j + k by omega] + split <;> rename_i equal + · subst i + simp only [if_pos (by omega : k < j + k + 1), inst, instVar, + Nat.lt_irrefl, if_false, if_true] + simpa only [Nat.zero_add, Nat.add_comm] using + (liftN_inst_lo k a b j 0 (Nat.zero_le _)).symm + · by_cases below : i < j + k + 1 + · simp [inst, instVar, below, before, equal, show i - 1 < j + k by omega] + · by_cases sameIndex : i = j + k + 1 + · subst i + simp only [if_true, + show j + k + 1 - 1 = j + k by omega, inst, instVar, + Nat.lt_irrefl, if_false, if_true] + rw [← liftN_combine (e := b) (n₁ := j + k) (n₂ := 1) + (k₁ := 0) (k₂ := k) (by omega) (by omega), inst_liftN] + · simp only [if_neg below, if_neg sameIndex, inst, instVar, + if_neg (by omega : ¬ i - 1 < j + k), if_neg (by omega : i - 1 ≠ j + k), + if_neg (by omega : ¬ i - 1 < k), if_neg (by omega : i - 1 ≠ k)] + +theorem inst_inst_hi (e a b : VExpr β) (k j : Nat) : + (e.inst a k).inst b (j + k) = + (e.inst b (j + k + 1)).inst (a.inst b j) k := by + induction e generalizing k with + | bvar i => exact inst_instVar_hi i a b k j + | lam _ _ hA hb | forallE _ _ hA hb => + simp only [inst, hA, Nat.add_assoc, hb] + | _ => simp_all [inst] + +theorem inst0_inst_hi (e a b : VExpr β) (j : Nat) : + (e.inst a).inst b j = (e.inst b (j + 1)).inst (a.inst b j) := + inst_inst_hi e a b 0 j + +end VExpr +end Ix.Theory diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 22496e4d0..ee1e804bd 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -30,10 +30,19 @@ increasing sequence of strongly inaccessible cardinals. under the existing finite address-faithfulness and arithmetic bounds. - A structural reader maps kernel expressions to model syntax, resolves addresses to explicit store references, preserves projections and natural - literals, and substitutes let values. This closed reader excludes free - variables, unresolved addresses, and string literals. The binder reader + literals, substitutes let values, and expands strings through the canonical + character and list primitives. This closed reader excludes free + variables and unresolved addresses. The binder reader `readScopedExpr?` maps registered free variables to model context indices; - unknown locals, loose legacy variables, lets, and strings fail that reader. + unknown locals and loose legacy variables fail that reader. Its let and + string readings commute with binder opening, abstraction, term substitution + and universe substitution, including nested occurrences. +- `StringExpansion.read_of_run` proves that production string expansion returns + the literal's model reading and preserves intern-table coherence. All + intermediate allocations are derived from the string: eight fixed nodes + and four per character. One collision condition covers this explicit list + and the initial table. The primitive table must be canonical and its + references resolvable; semantic admission of those primitives is separate. - Hash equality and intern-table reuse preserve that reading under their stated address/key collision assumptions. Metadata cannot change it. - `inferUncached_sort_sound` interprets an actual successful execution of the @@ -121,6 +130,15 @@ increasing sequence of strongly inaccessible cardinals. - `checkEnvAnon_atomic_preserves_model` connects a supported production environment run to model extension. `checkEnvAnon_atomic_no_false` excludes a declaration at an axiom type interpreted as empty, including False. +- `InferenceCacheInvariant` covers every entry in both production maps, with + separate full-checking and inference-only meanings. Hits obtain stored facts + directly; each insertion establishes its own fact and preserves all other + entries. Key computation, interning, local scopes, policy changes and reset + preserve the invariant. The actual lazy driver starts with empty caches; + failed declaration checks restore the incoming maps, and periodic clearing + preserves validity. The remaining successful-body preservation obligation is + explicit. These structural laws have a parameterized cache meaning; the + general mutual semantic proof must instantiate it and discharge that obligation. `ModelTyping.no_false` assumes semantic typing; the production fragment below derives it for its supported paths. Full checker refinement still requires the @@ -363,6 +381,8 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Constant cache selection, writes, and typing | [`Consistency/ConstantCache.lean`](../Ix/Kernel/Verify/Consistency/ConstantCache.lean) | | Cache invariants and sort cache typing | [`Consistency/InferenceCache.lean`](../Ix/Kernel/Verify/Consistency/InferenceCache.lean), [`SortCache.lean`](../Ix/Kernel/Verify/Consistency/SortCache.lean) | | Recursive cache preservation and witness reuse | [`Consistency/RecursiveCache.lean`](../Ix/Kernel/Verify/Consistency/RecursiveCache.lean) | +| Complete inference-cache maps and driver lifecycle | [`Consistency/CacheInvariant.lean`](../Ix/Kernel/Verify/Consistency/CacheInvariant.lean), [`CacheLifecycle.lean`](../Ix/Kernel/Verify/Consistency/CacheLifecycle.lean) | +| Finite intern support and production string expansion | [`Consistency/InternInvariant.lean`](../Ix/Kernel/Verify/Consistency/InternInvariant.lean), [`StringExpansion.lean`](../Ix/Kernel/Verify/Consistency/StringExpansion.lean), [`StringReading.lean`](../Ix/Kernel/Verify/Consistency/StringReading.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | From f0ca9f1aa0d1eb74b64642e175b70f2ac7086d7b Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 06:10:15 -0400 Subject: [PATCH 24/30] Reject circular safe definitions in host kernels --- Ix/Kernel/Check.lean | 10 +- Ix/Kernel/DefinitionOrder.lean | 80 +++++ Ix/Kernel/Verify/Check/BlockDefinition.lean | 6 + Ix/Kernel/Verify/Check/MemberEvidence.lean | 6 + .../Verify/Check/ScopedMemberEvidence.lean | 6 + Ix/Kernel/Verify/Consistency.lean | 7 + Ix/Kernel/Verify/Consistency/Audit.lean | 10 +- .../Verify/Consistency/DefinitionOrder.lean | 280 ++++++++++++++++++ Ix/Kernel/Verify/Consistency/Production.lean | 14 +- Tests/Ix/Kernel/CheckTests.lean | 50 +++- Tests/Theory/ImportManifest.lean | 1 + crates/kernel/src/check.rs | 152 +++++++++- docs/kernel-verification.md | 12 + 13 files changed, 628 insertions(+), 6 deletions(-) create mode 100644 Ix/Kernel/DefinitionOrder.lean create mode 100644 Ix/Kernel/Verify/Consistency/DefinitionOrder.lean diff --git a/Ix/Kernel/Check.lean b/Ix/Kernel/Check.lean index f2d2e14e6..ce619030c 100644 --- a/Ix/Kernel/Check.lean +++ b/Ix/Kernel/Check.lean @@ -1,6 +1,7 @@ module public import Ix.Kernel.Inductive +public import Ix.Kernel.DefinitionOrder /-! Mirror: crates/kernel/src/check.rs @@ -14,7 +15,9 @@ Constant checking dispatch: validation (closed at top level, univ params in range, const arities, known prj heads), then kind dispatch — axioms/quots infer+sort; definitions additionally def-eq the value type (theorems must be Prop) and - run the safety lattice; inductives/ctors/recursors run inference plus the + run the safety lattice. Safe definitions reject self-reference, and safe + members of definition blocks must admit a dependency order before any + member is checked. Inductives/ctors/recursors run inference plus the inductive machinery. The inductive and recursor member/block validators live in @@ -419,6 +422,9 @@ def checkConstMember (id : KId m) (c : KConst m) : RecM m Unit := do let t ← infer ty let _ ← ensureSortDirect t | .defn (ty := ty) (val := val) (safety := safety) (kind := kind) .. => + if safety == .safe && + (exprMentionsAddr ty id.addr || exprMentionsAddr val id.addr) then + throw (.other "circular safe definition dependency") let t ← infer ty let lvl ← ensureSortDirect t -- Theorems must have types in Prop (Sort 0). @@ -462,6 +468,8 @@ def checkClassifiedBlock (kind : CheckBlockKind) (block : KId m) validateConstWellScoped c match kind with | .defn => + if !(← get).env.definitionBlockAcyclic members then + throw (.other "circular safe definition dependency in block") let mut peak : UInt32 := 0 for member in members do checkConstMemberFresh member diff --git a/Ix/Kernel/DefinitionOrder.lean b/Ix/Kernel/DefinitionOrder.lean new file mode 100644 index 000000000..9162e22c7 --- /dev/null +++ b/Ix/Kernel/DefinitionOrder.lean @@ -0,0 +1,80 @@ +module + +public import Ix.Kernel.Monad + +/-! +Dependency ordering inside an anonymous or named definition block. A safe +definition's type and value may use an earlier member, but may not obtain +their justification from a cycle of pending safe definitions. Inductive +and recursor blocks have separate validators for their recursive structure. + +This check concerns the local declaration/block boundary. Ordering external +dependencies is a separate obligation of environment and claim admission. +-/ + +public section +@[expose] section + +namespace Ix.Kernel + +/-- The fields consulted when ordering safe definitions. -/ +structure SafeDefinition (m : Mode) where + id : KId m + ty : KExpr m + val : KExpr m + +namespace SafeDefinition + +def ofConst? (id : KId m) : KConst m → Option (SafeDefinition m) + | .defn (safety := .safe) (ty := ty) (val := val) .. => some ⟨id, ty, val⟩ + | _ => none + +/-- Projection heads count as dependencies, as do ordinary constant nodes. -/ +def mentions (definition : SafeDefinition m) (id : KId m) : Bool := + exprMentionsAddr definition.ty id.addr || exprMentionsAddr definition.val id.addr + +def ready (pending : List (SafeDefinition m)) (definition : SafeDefinition m) : Bool := + pending.all fun dependency => !definition.mentions dependency.id + +/-- Simultaneously remove every member whose dependencies have already been +removed. The fuel bounds rejected cyclic inputs as well as accepted ones. -/ +def order? : Nat → List (SafeDefinition m) → Option (List (SafeDefinition m)) + | _, [] => some [] + | 0, _ :: _ => none + | fuel + 1, pending@(_ :: _) => + let ready := pending.filter (ready pending) + if ready.isEmpty then none + else + let rest := pending.filter fun definition => !definition.ready pending + (order? fuel rest).map (ready ++ ·) + +def acyclic (pending : List (SafeDefinition m)) : Bool := + (order? pending.length pending).isSome + +end SafeDefinition + +namespace KEnv + +/-- Read the complete pending safe subset. Missing or non-definition members +fail closed; the block classifier normally rejects these first. -/ +def safeDefinitions? (env : KEnv m) : List (KId m) → Option (List (SafeDefinition m)) + | [] => some [] + | id :: rest => do + let declaration ← env.consts[id]? + let .defn .. := declaration | none + let tail ← env.safeDefinitions? rest + match SafeDefinition.ofConst? id declaration with + | some definition => some (definition :: tail) + | none => some tail + +def definitionBlockAcyclic (env : KEnv m) (members : Array (KId m)) : Bool := + match env.safeDefinitions? members.toList with + | some pending => SafeDefinition.acyclic pending + | none => false + +end KEnv + +end Ix.Kernel + +end +end diff --git a/Ix/Kernel/Verify/Check/BlockDefinition.lean b/Ix/Kernel/Verify/Check/BlockDefinition.lean index dfb91e859..85db0e184 100644 --- a/Ix/Kernel/Verify/Check/BlockDefinition.lean +++ b/Ix/Kernel/Verify/Check/BlockDefinition.lean @@ -2,6 +2,7 @@ import Ix.Kernel.Verify.Check.BlockTransaction import Ix.Kernel.Verify.Check.BlockClassification import Ix.Kernel.Verify.Check.ScopedStandaloneDriver import Ix.Kernel.Verify.Check.StandaloneDriver +import Ix.Kernel.Verify.Consistency.DefinitionOrder /-! # Singleton definition blocks @@ -28,9 +29,14 @@ theorem checkClassifiedBlock_singleton_definition_success (hrun : (checkClassifiedBlock .defn block #[id]).run methods before = .ok () after) : (checkConstMemberFresh id).run methods before = .ok () after := by + have hguard := Consistency.DefinitionOrder.block_guard hrun unfold checkClassifiedBlock at hrun have hneq : ((.defn : CheckBlockKind) != .defn) = false := by rfl rw [hneq] at hrun + simp only [Bool.false_eq_true, if_false, ReaderT.run_bind] at hrun + change ((if (!before.env.definitionBlockAcyclic #[id]) = true then _ else _) : + RecM .anon Unit).run methods before = .ok () after at hrun + simp only [hguard, Bool.not_true, Bool.false_eq_true, if_false] at hrun simp at hrun change EStateM.bind ((checkConstMemberFresh id).run methods) _ before = .ok () after at hrun diff --git a/Ix/Kernel/Verify/Check/MemberEvidence.lean b/Ix/Kernel/Verify/Check/MemberEvidence.lean index 84a3fa286..16cd58227 100644 --- a/Ix/Kernel/Verify/Check/MemberEvidence.lean +++ b/Ix/Kernel/Verify/Check/MemberEvidence.lean @@ -208,6 +208,12 @@ theorem checkConstMember_defn_sound contradiction | ok validationValue afterValidation => simp only [runTcBind, hvalidation] at hrun + have hcycle : ¬(safety == .safe && + (exprMentionsAddr type id.addr || exprMentionsAddr value id.addr)) := by + intro rejected + simp only [rejected, if_true] at hrun + contradiction + simp only [hcycle, Bool.false_eq_true, if_false, ReaderT.run_bind, runTcBind] at hrun have hIValidation : WhnfStateInv .noAccel (kernelCacheSemantics model.keys trProj) trProj world support model.keys.uvars [] afterValidation := by diff --git a/Ix/Kernel/Verify/Check/ScopedMemberEvidence.lean b/Ix/Kernel/Verify/Check/ScopedMemberEvidence.lean index 450878f28..bbff447c8 100644 --- a/Ix/Kernel/Verify/Check/ScopedMemberEvidence.lean +++ b/Ix/Kernel/Verify/Check/ScopedMemberEvidence.lean @@ -184,6 +184,12 @@ theorem checkConstMember_defn_scoped_sound contradiction | ok validationValue afterValidation => simp only [scopedRunTcBind, hvalidation] at hrun + have hcycle : ¬(safety == .safe && + (exprMentionsAddr type id.addr || exprMentionsAddr value id.addr)) := by + intro rejected + simp only [rejected, if_true] at hrun + contradiction + simp only [hcycle, Bool.false_eq_true, if_false, ReaderT.run_bind, scopedRunTcBind] at hrun have hIValidation : ScopedWhnfStateInv model .noAccel (kernelCacheSemantics model.keys trProj) support [] afterValidation := by diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 730267b8c..2b5b530b3 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -25,6 +25,7 @@ import Ix.Kernel.Verify.Consistency.CacheInvariant import Ix.Kernel.Verify.Consistency.CacheLifecycle import Ix.Kernel.Verify.Consistency.InternInvariant import Ix.Kernel.Verify.Consistency.StringExpansion +import Ix.Kernel.Verify.Consistency.DefinitionOrder import Ix.Kernel.Verify.Consistency.Production import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Consistency.Audit @@ -76,4 +77,10 @@ partitions. Writes, hits, initialization, clearing, scope/policy cleanup and error isolation preserve these facts. Its parameterized entry meaning and uncached-body preservation contract remain to be instantiated by the general mutual semantic proof. General checker soundness remains outside this fragment. + +The safe-definition guard excludes self-reference for both modes and arbitrary +universe arities. Successful definition-block execution computes an order of +all loaded safe members and implies a well-founded internal dependency relation. +External dependency admission and the meaning of cached block successes remain +obligations of the general environment proof. -/ diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 29e11b6a3..af8ace938 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -9,6 +9,7 @@ import Ix.Kernel.Verify.Consistency.Environment import Ix.Kernel.Verify.Consistency.RecursiveCache import Ix.Kernel.Verify.Consistency.CacheLifecycle import Ix.Kernel.Verify.Consistency.StringExpansion +import Ix.Kernel.Verify.Consistency.DefinitionOrder import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -126,6 +127,9 @@ private def recursiveCacheRoots : Array Lean.Name := #[ private def productionRoots : Array Lean.Name := #[ ``StandalonePrefix.member_success, ``definition_body_trace, + ``DefinitionOrder.member_no_self, ``DefinitionOrder.block_guard, + ``DefinitionOrder.block_rank, ``DefinitionOrder.block_wellFounded, + ``DefinitionOrder.block_no_cycle, ``AtomicDefinitionRun.sound, ``AtomicDefinitionRun.no_self_alias, ``WorkPosition.check_success, ``AtomicDefinitionPlan.extends, ``AtomicDefinitionPlan.sound, ``AtomicDefinitionPlan.represents, @@ -270,10 +274,12 @@ def roots : Array RootAllowance := #[ ] ++ stringListRoots.map (fun root => { root, standardAxioms := #[``propext], forbiddenDependencies := forbiddenProduction }) ++ (localIndexRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ - internFrameRoots).map (fun root => { + internFrameRoots ++ #[``DefinitionOrder.ready_independent, + ``DefinitionOrder.order?_sound, ``DefinitionOrder.member_of_read]).map (fun root => { root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction }) ++ (contextRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ - internMapRoots).map (fun root => { + internMapRoots ++ #[``DefinitionOrder.order?_rank, + ``DefinitionOrder.acyclic_rank]).map (fun root => { root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction }) ++ (binderWalkerRoots ++ cacheKeyRoots ++ cacheInvariantKeyRoots ++ stringExpansionRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative], diff --git a/Ix/Kernel/Verify/Consistency/DefinitionOrder.lean b/Ix/Kernel/Verify/Consistency/DefinitionOrder.lean new file mode 100644 index 000000000..93711ad93 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/DefinitionOrder.lean @@ -0,0 +1,280 @@ +import Ix.Kernel.Check + +/-! +The production definition-block guard computes a dependency order. Its +successful result contains every pending safe definition and gives every +internal dependency a strictly smaller rank. No ordering certificate is +supplied by a caller, and no claim about external dependencies is hidden in +this local block theorem. +-/ + +namespace Ix.Kernel.Consistency + +namespace DefinitionOrder + +private theorem pairwise_of_all {α : Type} {R : α → α → Prop} + {xs : List α} (all : ∀ a ∈ xs, ∀ b ∈ xs, R a b) : xs.Pairwise R := by + induction xs with + | nil => exact .nil + | cons a rest ih => + exact .cons (fun b hb => all a (by simp) b (by simp [hb])) + (ih (fun b hb c hc => all b (by simp [hb]) c (by simp [hc]))) + +/-- Every member selected in one peeling round is independent of the +complete pending set, including itself and all other selected members. -/ +theorem ready_independent {pending : List (SafeDefinition m)} + {definition dependency : SafeDefinition m} + (selected : definition ∈ pending.filter (SafeDefinition.ready pending)) + (member : dependency ∈ pending) : definition.mentions dependency.id = false := by + have ready := (List.mem_filter.mp selected).2 + have noRef := List.all_eq_true.mp ready dependency member + simpa using noRef + +/-- A successful production sort preserves every member and orders all +internal references from later members to earlier members. -/ +theorem order?_sound {fuel : Nat} {pending ordered : List (SafeDefinition m)} + (run : SafeDefinition.order? fuel pending = some ordered) : + (∀ definition, definition ∈ ordered ↔ definition ∈ pending) ∧ + (∀ definition ∈ ordered, definition.mentions definition.id = false) ∧ + ordered.Pairwise (fun definition dependency => definition.mentions dependency.id = false) := by + induction fuel generalizing pending ordered with + | zero => + cases pending with + | nil => simp [SafeDefinition.order?] at run; subst ordered; simp + | cons definition rest => simp [SafeDefinition.order?] at run + | succ fuel ih => + cases pending with + | nil => simp [SafeDefinition.order?] at run; subst ordered; simp + | cons definition rest => + let pending := definition :: rest + let selected := pending.filter (SafeDefinition.ready pending) + let remaining := pending.filter fun d => !d.ready pending + change (if selected.isEmpty then none else + (SafeDefinition.order? fuel remaining).map (selected ++ ·)) = some ordered at run + split at run + · contradiction + · cases next : SafeDefinition.order? fuel remaining with + | none => simp [next] at run + | some tail => + simp only [next, Option.map_some, Option.some.injEq] at run + subst ordered + obtain ⟨members, noSelf, pairwise⟩ := ih next + have selected_mem {d : SafeDefinition m} (hd : d ∈ selected) : d ∈ pending := + (List.mem_filter.mp hd).1 + have tail_mem {d : SafeDefinition m} (hd : d ∈ tail) : d ∈ pending := + (List.mem_filter.mp ((members d).mp hd)).1 + refine ⟨?_, ?_, ?_⟩ + · intro d + simp only [List.mem_append, members, selected, remaining, List.mem_filter] + cases d.ready pending <;> simp [pending] + · intro d hd + rcases List.mem_append.mp hd with hs | ht + · exact ready_independent hs (selected_mem hs) + · exact noSelf d ht + · apply List.pairwise_append.mpr + refine ⟨pairwise_of_all (fun d hd dep hp => + ready_independent hd (selected_mem hp)), pairwise, ?_⟩ + intro d hd dep hp + exact ready_independent hd (tail_mem hp) + +/-- Finite ranks obtained from the computed order, rather than assumed as +an environment invariant. The scope is precisely the supplied pending set. -/ +theorem order?_rank {fuel : Nat} {pending ordered : List (SafeDefinition m)} + (run : SafeDefinition.order? fuel pending = some ordered) : + ∃ rank : SafeDefinition m → Nat, + ∀ definition ∈ pending, ∀ dependency ∈ pending, + definition.mentions dependency.id = true → rank dependency < rank definition := by + classical + obtain ⟨members, noSelf, pairwise⟩ := order?_sound run + refine ⟨fun definition => ordered.idxOf definition, ?_⟩ + intro definition hd dependency hp mentions + have hd := (members definition).mpr hd + have hp := (members dependency).mpr hp + have hdBound := List.idxOf_lt_length_of_mem hd + have hpBound := List.idxOf_lt_length_of_mem hp + have hdGet := List.getElem_idxOf hdBound + have hpGet := List.getElem_idxOf hpBound + by_contra notEarlier + dsimp only at notEarlier + have le : ordered.idxOf definition ≤ ordered.idxOf dependency := by omega + by_cases same : ordered.idxOf definition = ordered.idxOf dependency + · have equal : definition = dependency := by + rw [← hdGet, ← hpGet] + simp only [same] + subst dependency + simp [noSelf definition hd] at mentions + · have lt : ordered.idxOf definition < ordered.idxOf dependency := by omega + have noRef := List.pairwise_iff_getElem.mp pairwise + (ordered.idxOf definition) (ordered.idxOf dependency) hdBound hpBound lt + rw [hdGet, hpGet] at noRef + simp [noRef] at mentions + +theorem acyclic_rank {pending : List (SafeDefinition m)} + (accepted : SafeDefinition.acyclic pending = true) : + ∃ rank : SafeDefinition m → Nat, + ∀ definition ∈ pending, ∀ dependency ∈ pending, + definition.mentions dependency.id = true → rank dependency < rank definition := by + unfold SafeDefinition.acyclic at accepted + cases run : SafeDefinition.order? pending.length pending with + | none => simp [run] at accepted + | some ordered => exact order?_rank run + +/-- Every safe declaration found at a requested member key occurs in the +computed pending set. The successful read also verifies that all other +member keys exist and contain definitions. -/ +theorem member_of_read {env : KEnv m} {ids : List (KId m)} + {pending : List (SafeDefinition m)} + (run : env.safeDefinitions? ids = some pending) + {id : KId m} {declaration : KConst m} {definition : SafeDefinition m} + (member : id ∈ ids) (loaded : env.consts[id]? = some declaration) + (safe : SafeDefinition.ofConst? id declaration = some definition) : + definition ∈ pending := by + induction ids generalizing pending with + | nil => simp at member + | cons head rest ih => + cases headRead : env.consts[head]? with + | none => simp [KEnv.safeDefinitions?, headRead] at run + | some entry => + cases entry <;> try simp [KEnv.safeDefinitions?, headRead] at run + case defn name params kind safety hints levels ty val all block => + cases tailRead : env.safeDefinitions? rest with + | none => simp [tailRead] at run + | some tail => + cases headSafe : SafeDefinition.ofConst? head + (.defn name params kind safety hints levels ty val all block) with + | none => + simp only [Option.bind_some, tailRead, headSafe, Option.some.injEq] at run + subst pending + rcases List.mem_cons.mp member with same | later + · subst id + have equal := Option.some.inj (headRead.symm.trans loaded) + subst declaration + simp [headSafe] at safe + · exact ih tailRead later + | some first => + simp only [Option.bind_some, tailRead, headSafe, Option.some.injEq] at run + subst pending + rcases List.mem_cons.mp member with same | later + · subst id + have equal := Option.some.inj (headRead.symm.trans loaded) + subst declaration + have equal := Option.some.inj (headSafe.symm.trans safe) + simp [← equal] + · exact List.mem_cons_of_mem _ (ih tailRead later) + +/-- Safe member success excludes self-reference in both the type and value, +for arbitrary universe arities and either kernel representation mode. -/ +theorem member_no_self {methods : Methods m} {id : KId m} {constant : KConst m} + {definition : SafeDefinition m} {before after : TcState m} + (selected : SafeDefinition.ofConst? id constant = some definition) + (run : (RecM.checkConstMember id constant).run methods before = .ok () after) : + definition.mentions id = false := by + cases constant <;> try simp [SafeDefinition.ofConst?] at selected + case defn name params kind safety hints levels ty val all block => + cases safety <;> try simp at selected + case safe => + subst definition + unfold RecM.checkConstMember at run + simp only [KConst.levelParams] at run + by_cases duplicates : params.hasDups + · simp only [duplicates, if_true] at run + contradiction + · simp only [duplicates, Bool.false_eq_true, if_false, ReaderT.run_bind] at run + change EStateM.bind ((RecM.validateConstWellScoped + (.defn name params kind .safe hints levels ty val all block)).run methods) + _ before = _ at run + unfold EStateM.bind at run + cases validated : (RecM.validateConstWellScoped + (.defn name params kind .safe hints levels ty val all block)).run methods before with + | error error state => rw [validated] at run; contradiction + | ok _ state => + rw [validated] at run + change (exprMentionsAddr ty id.addr || exprMentionsAddr val id.addr) = false + cases mentions : (exprMentionsAddr ty id.addr || exprMentionsAddr val id.addr) with + | false => rfl + | true => + have same : ((Ix.DefinitionSafety.safe : Ix.DefinitionSafety) == .safe) = true := rfl + simp only [same, Bool.true_and, mentions, if_true] at run + contradiction + +/-- The guard is extracted from the exact production block execution. It +runs before member checking and leaves the state unchanged. -/ +theorem block_guard {methods : Methods m} {block : KId m} + {members : Array (KId m)} {before after : TcState m} + (run : (RecM.checkClassifiedBlock .defn block members).run methods before = + .ok () after) : before.env.definitionBlockAcyclic members = true := by + cases guard : before.env.definitionBlockAcyclic members with + | true => rfl + | false => + have same : ((CheckBlockKind.defn : CheckBlockKind) != .defn) = false := rfl + simp only [RecM.checkClassifiedBlock, same, Bool.false_eq_true, if_false, + ReaderT.run_bind] at run + change ((if (!before.env.definitionBlockAcyclic members) = true then _ else _) : + RecM m Unit).run methods before = EStateM.Result.ok () after at run + simp only [guard, Bool.not_false, if_true] at run + contradiction + +/-- Actual block success supplies the pending declarations and their finite +rank function. Neither is an additional acceptance premise. -/ +theorem block_rank {methods : Methods m} {block : KId m} + {members : Array (KId m)} {before after : TcState m} + (run : (RecM.checkClassifiedBlock .defn block members).run methods before = + .ok () after) : + ∃ pending : List (SafeDefinition m), ∃ rank : SafeDefinition m → Nat, + before.env.safeDefinitions? members.toList = some pending ∧ + ∀ definition ∈ pending, ∀ dependency ∈ pending, + definition.mentions dependency.id = true → rank dependency < rank definition := by + have accepted := block_guard run + unfold KEnv.definitionBlockAcyclic at accepted + cases read : before.env.safeDefinitions? members.toList with + | none => simp [read] at accepted + | some pending => + simp only [read] at accepted + obtain ⟨rank, descending⟩ := acyclic_rank accepted + exact ⟨pending, rank, rfl, descending⟩ + +/-- A safe definition actually loaded at a member key of this block. -/ +def LoadedMember (env : KEnv m) (members : Array (KId m)) + (definition : SafeDefinition m) : Prop := + definition.id ∈ members ∧ ∃ declaration, + env.consts[definition.id]? = some declaration ∧ + SafeDefinition.ofConst? definition.id declaration = some definition + +/-- Dependency direction: the referenced declaration precedes its user. -/ +def Dependency (env : KEnv m) (members : Array (KId m)) + (dependency definition : SafeDefinition m) : Prop := + LoadedMember env members definition ∧ LoadedMember env members dependency ∧ + definition.mentions dependency.id = true + +/-- No cycle of safe definitions can be hidden inside a successfully checked +definition block. The relation reads the actual pre-check environment. -/ +theorem block_wellFounded {methods : Methods m} {block : KId m} + {members : Array (KId m)} {before after : TcState m} + (run : (RecM.checkClassifiedBlock .defn block members).run methods before = + .ok () after) : WellFounded (Dependency before.env members) := by + obtain ⟨pending, rank, read, descending⟩ := block_rank run + refine Subrelation.wf (r := fun dependency definition => rank dependency < rank definition) + ?_ (InvImage.wf rank Nat.lt_wfRel.wf) + intro dependency definition edge + rcases edge with ⟨⟨hd, cd, hdRead, hdSafe⟩, ⟨hp, cp, hpRead, hpSafe⟩, mentions⟩ + exact descending definition (member_of_read read (by simpa using hd) hdRead hdSafe) + dependency (member_of_read read (by simpa using hp) hpRead hpSafe) mentions + +private theorem accessible_no_self {α : Sort u} {relation : α → α → Prop} + {value : α} (accessible : Acc relation value) : ¬relation value value := by + induction accessible with + | intro value _ ih => + intro cycle + exact ih value cycle cycle + +/-- Explicit exclusion of every nonempty dependency cycle, of any length. -/ +theorem block_no_cycle {methods : Methods m} {block : KId m} + {members : Array (KId m)} {before after : TcState m} + (run : (RecM.checkClassifiedBlock .defn block members).run methods before = + .ok () after) (definition : SafeDefinition m) : + ¬Relation.TransGen (Dependency before.env members) definition definition := + accessible_no_self ((block_wellFounded run).transGen.apply definition) + +end DefinitionOrder + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/Production.lean b/Ix/Kernel/Verify/Consistency/Production.lean index 894a75e71..e821b1d27 100644 --- a/Ix/Kernel/Verify/Consistency/Production.lean +++ b/Ix/Kernel/Verify/Consistency/Production.lean @@ -197,6 +197,9 @@ structure DefinitionBodyTrace (input : DefinitionInput) (methods : Methods .anon conversionEnd : TcState .anon validationRun : (RecM.validateConstWellScoped input.constant).run methods before = .ok () validated + dependencyGuard : (input.safety == .safe && + (exprMentionsAddr input.type input.id.addr || + exprMentionsAddr input.value input.id.addr)) = false typeRun : (RecM.infer input.type).run methods validated = .ok inferredType typeState sortRun : (RecM.ensureSortDirect inferredType).run methods typeState = .ok level valueStart theoremGuard : (input.kind == .thm && !univEq level .mkZero) = false @@ -215,6 +218,15 @@ theorem definition_body_trace {input : DefinitionInput} {methods : Methods .anon change EStateM.bind ((RecM.validateConstWellScoped input.constant).run methods) _ before = _ at accepted obtain ⟨⟨⟩, validated, validationRun, accepted⟩ := bind_success accepted + have dependencyGuard : (input.safety == .safe && + (exprMentionsAddr input.type input.id.addr || + exprMentionsAddr input.value input.id.addr)) = false := by + cases guard : (input.safety == .safe && + (exprMentionsAddr input.type input.id.addr || + exprMentionsAddr input.value input.id.addr)) with + | false => rfl + | true => simp only [guard, if_true] at accepted; contradiction + simp only [dependencyGuard, Bool.false_eq_true, if_false, ReaderT.run_bind] at accepted change EStateM.bind ((RecM.infer input.type).run methods) _ validated = _ at accepted obtain ⟨inferredType, typeState, typeRun, accepted⟩ := bind_success accepted change EStateM.bind ((RecM.ensureSortDirect inferredType).run methods) @@ -237,7 +249,7 @@ theorem definition_body_trace {input : DefinitionInput} {methods : Methods .anon exact ⟨{ validated, inferredType, typeState, level, valueStart, inferredValue, conversionStart, conversionEnd, - validationRun, typeRun, sortRun, + validationRun, dependencyGuard, typeRun, sortRun, theoremGuard := Bool.eq_false_iff.mpr guard, valueRun, conversionRun }⟩ /-- Operational support for the selected production definition fragment. diff --git a/Tests/Ix/Kernel/CheckTests.lean b/Tests/Ix/Kernel/CheckTests.lean index 3d54dcfb5..83e853a31 100644 --- a/Tests/Ix/Kernel/CheckTests.lean +++ b/Tests/Ix/Kernel/CheckTests.lean @@ -347,6 +347,54 @@ def quotTests : TestSeq := /-! ### Block coordination -/ +/-- Closed, axiom-free proposition. A circular body must not establish it. -/ +def circularProposition : Ixon.Expr := .leanAll (.sort 0) (.var 0) + +def circularFailure (row : CheckResult) : Bool := + row.err?.any fun error => (error.splitOn "circular safe definition").length > 1 + +def circularDefinitionTests : TestSeq := + ([Ix.DefKind.defn, .thm, .opaq].foldl (init := .done) fun tests kind => + tests ++ test s!"safe {repr kind} cannot justify its own declared type" + ((let declaration : Ixon.Constant := + ⟨.defn ⟨kind, .safe, 0, circularProposition, .recur 0 #[]⟩, + #[], #[], #[.zero]⟩ + let (source, target) := storeConst {} declaration + match checkEnvAnon source { verifyHashes := true } with + | .ok rows => rows.size == 1 && rows[0]!.addr == target + && circularFailure rows[0]! + | .error _ => false : Bool))) + ++ test "safe mutual definitions cannot justify each other" + ((let f : Ixon.MutConst := + .defn ⟨.thm, .safe, 0, circularProposition, .recur 1 #[]⟩ + let g : Ixon.MutConst := + .defn ⟨.thm, .safe, 0, circularProposition, .recur 0 #[]⟩ + let (source, _) := storeMutsWithProjs {} + ⟨.muts #[f, g], #[], #[], #[.zero]⟩ + match checkEnvAnon source { verifyHashes := true } with + | .ok rows => rows.size == 2 && rows.all circularFailure + | .error _ => false : Bool)) + ++ test "safe mutual cycle is rejected alongside an independent member" + ((let good : Ixon.MutConst := + .defn ⟨.defn, .safe, 0, .leanAll (.sort 0) (.sort 0), + .leanLam (.sort 0) (.var 0)⟩ + let f : Ixon.MutConst := + .defn ⟨.thm, .safe, 0, circularProposition, .recur 2 #[]⟩ + let g : Ixon.MutConst := + .defn ⟨.thm, .safe, 0, circularProposition, .recur 1 #[]⟩ + let (source, _) := storeMutsWithProjs {} + ⟨.muts #[good, f, g], #[], #[], #[.zero]⟩ + match checkEnvAnon source { verifyHashes := true } with + | .ok rows => rows.size == 3 && rows.all circularFailure + | .error _ => false : Bool)) + ++ test "partial and unsafe recursion remains outside safe admission" + (([Ix.DefinitionSafety.part, .unsaf].all fun safety => + let declaration : Ixon.Constant := + ⟨.defn ⟨.defn, safety, 0, circularProposition, .recur 0 #[]⟩, + #[], #[], #[.zero]⟩ + let (source, target) := storeConst {} declaration + passes source target : Bool)) + def blockTests : TestSeq := test "defn block failure replays for every member" ((let (ixon, aAddr) := envA @@ -1019,7 +1067,7 @@ def parallelTests : TestSeq := public def suite : List TestSeq := [acceptRejectTests, wellScopedTests, totalizationTests, safetyTests, - quotTests, blockTests, + quotTests, circularDefinitionTests, blockTests, lazyTests, cacheIsolationTests, primVerifyTests, inductiveTests, recursorTests, parallelTests] diff --git a/Tests/Theory/ImportManifest.lean b/Tests/Theory/ImportManifest.lean index ee4f7d141..b61e4a3cd 100644 --- a/Tests/Theory/ImportManifest.lean +++ b/Tests/Theory/ImportManifest.lean @@ -17,6 +17,7 @@ def conLecheRevision : String := "86cd20a65660d757cedc81561a44579099b565d0" /-- New mathematical modules authored in Ix, with no imported source hash. -/ def authored : Array String := #[ + "Ix/Theory/ExprSubstitution.lean", "Ix/Theory/Model/Checking.lean", "Ix/Theory/Model/LevelCongruence.lean" ] diff --git a/crates/kernel/src/check.rs b/crates/kernel/src/check.rs index e6a71854c..714fa2ee4 100644 --- a/crates/kernel/src/check.rs +++ b/crates/kernel/src/check.rs @@ -16,7 +16,7 @@ use super::id::KId; use super::level::{KUniv, UnivData, univ_eq}; use super::mode::{CheckDupLevelParams, KernelMode}; use super::primitive::Primitives; -use super::tc::TypeChecker; +use super::tc::{TypeChecker, expr_mentions_addr}; /// Emit `[decl diff]` when a `Defn`'s value fails the `is_def_eq(val_ty, /// ty)` check. The error itself (`DeclTypeMismatch`) carries no payload, @@ -330,6 +330,14 @@ impl TypeChecker<'_, M> { }, KConst::Defn { ty, val, safety, kind, .. } => { + if *safety == DefinitionSafety::Safe + && (expr_mentions_addr(ty, &id.addr) + || expr_mentions_addr(val, &id.addr)) + { + return Err(TcError::Other( + "circular safe definition dependency".into(), + )); + } let t_infer_ty_start = overall.map(|_| Instant::now()); let t = self.infer(ty)?; let lvl = self.ensure_sort(&t)?; @@ -579,6 +587,7 @@ impl TypeChecker<'_, M> { let body_start = overall.map(|_| Instant::now()); let result = match kind { CheckBlockKind::Defn => { + self.check_definition_block_acyclic(&members)?; let mut peak = 0; for member in &members { self.check_const_member_fresh(member)?; @@ -978,6 +987,52 @@ impl TypeChecker<'_, M> { Ok(()) } + // ----------------------------------------------------------------------- + // Definition dependency ordering + // ----------------------------------------------------------------------- + + /// Remove safe block members whose type and value no longer mention any + /// pending safe member. A remaining cycle cannot justify its own types. + /// External dependencies belong to the environment/claim admission order; + /// inductive and recursor recursion has separate structural validators. + fn check_definition_block_acyclic( + &self, + members: &[KId], + ) -> Result<(), TcError> { + let reject = + || TcError::Other("circular safe definition dependency in block".into()); + let mut pending = Vec::new(); + for member in members { + let Some(KConst::Defn { ty, val, safety, .. }) = self.env.get(member) + else { + return Err(reject()); + }; + if safety == DefinitionSafety::Safe { + pending.push((member, ty, val)); + } + } + while !pending.is_empty() { + let ready: Vec = pending + .iter() + .map(|(_, ty, val)| { + pending.iter().all(|(dependency, _, _)| { + !expr_mentions_addr(ty, &dependency.addr) + && !expr_mentions_addr(val, &dependency.addr) + }) + }) + .collect(); + if !ready.iter().any(|ready| *ready) { + return Err(reject()); + } + pending = pending + .into_iter() + .zip(ready) + .filter_map(|(definition, ready)| (!ready).then_some(definition)) + .collect(); + } + Ok(()) + } + // ----------------------------------------------------------------------- // #9: Safety level checking // ----------------------------------------------------------------------- @@ -1803,6 +1858,101 @@ mod tests { ); } + #[test] + fn reject_circular_safe_standalone_definitions() { + use ixon::constant::{Constant, ConstantInfo, Definition}; + use ixon::expr::Expr; + use ixon::univ::Univ; + + for kind in [DefKind::Definition, DefKind::Theorem, DefKind::Opaque] { + let declaration = Constant::with_tables( + ConstantInfo::Defn(Definition { + kind, + safety: DefinitionSafety::Safe, + lvls: 0, + typ: Expr::all(Expr::sort(0), Expr::var(0)), + value: Expr::rec(0, vec![]), + }), + vec![], + vec![], + vec![Univ::zero()], + ); + let (addr, _) = declaration.commit(); + let source = ixon::env::Env::new(); + source.store_const(addr.clone(), declaration); + let mut env = KEnv::::new(); + assert!( + crate::ingress::ingress_anon_addr_shallow(&mut env, &source, &addr,) + .unwrap() + ); + let err = TypeChecker::new(&mut env) + .check_const(&KId::new(addr, ())) + .expect_err("a declaration must not justify its type by citing itself"); + assert!(err.to_string().contains("circular safe definition"), "{err}"); + } + } + + #[test] + fn reject_circular_safe_definition_block() { + let mut env = KEnv::::new(); + let block = mk_id("circular_block"); + let f = mk_id("circular_f"); + let g = mk_id("circular_g"); + let good = mk_id("independent_member"); + insert_id_def(&mut env, good.clone(), block.clone()); + for (id, peer) in [(&f, &g), (&g, &f)] { + env.insert( + id.clone(), + KConst::Defn { + name: (), + level_params: (), + kind: DefKind::Theorem, + safety: DefinitionSafety::Safe, + hints: ReducibilityHints::Regular(0), + lvls: 0, + ty: AE::all((), (), sort0(), AE::var(0, ())), + val: AE::cnst(peer.clone(), Box::new([])), + lean_all: (), + block: block.clone(), + }, + ); + } + env.insert_block(block, vec![good.clone(), f.clone(), g.clone()]); + let mut tc = TypeChecker::new(&mut env); + let first = tc.check_const(&good).unwrap_err().to_string(); + assert!(first.contains("circular safe definition"), "{first}"); + assert_eq!(tc.check_const(&f).unwrap_err().to_string(), first); + assert_eq!(tc.check_const(&g).unwrap_err().to_string(), first); + } + + #[test] + fn accept_acyclic_safe_definition_block() { + let mut env = KEnv::::new(); + let block = mk_id("acyclic_block"); + let f = mk_id("acyclic_f"); + let g = mk_id("acyclic_g"); + insert_id_def(&mut env, g.clone(), block.clone()); + env.insert( + f.clone(), + KConst::Defn { + name: (), + level_params: (), + kind: DefKind::Definition, + safety: DefinitionSafety::Safe, + hints: ReducibilityHints::Regular(0), + lvls: 0, + ty: AE::all((), (), sort0(), sort0()), + val: AE::cnst(g.clone(), Box::new([])), + lean_all: (), + block: block.clone(), + }, + ); + env.insert_block(block, vec![f.clone(), g.clone()]); + let mut tc = TypeChecker::new(&mut env); + tc.check_const(&f).unwrap(); + tc.check_const(&g).unwrap(); + } + #[test] fn checking_one_definition_checks_sibling_block() { let mut env = KEnv::::new(); diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index ee1e804bd..f3301fce7 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -139,6 +139,17 @@ increasing sequence of strongly inaccessible cardinals. preserves validity. The remaining successful-body preservation obligation is explicit. These structural laws have a parameterized cache meaning; the general mutual semantic proof must instantiate it and discharge that obligation. +- Safe definitions cannot cite themselves in their types or values. Definition + blocks compute a dependency order for their safe members before checking any + member. `DefinitionOrder.block_wellFounded` and `block_no_cycle` derive the + absence of every internal safe-definition cycle from actual block success. + The order includes every safe declaration loaded at a member key; callers + supply no order or rank certificate. Acyclic references between block members + remain supported. This closes the host acceptance of hash-verified circular + definitions, theorems, and opaque definitions. The guest already rejects safe + `recur` references at ingress, including acyclic peer references; that policy + difference remains explicit. External dependency ordering, cache provenance, + and general model preservation remain separate obligations. `ModelTyping.no_false` assumes semantic typing; the production fragment below derives it for its supported paths. Full checker refinement still requires the @@ -385,6 +396,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Finite intern support and production string expansion | [`Consistency/InternInvariant.lean`](../Ix/Kernel/Verify/Consistency/InternInvariant.lean), [`StringExpansion.lean`](../Ix/Kernel/Verify/Consistency/StringExpansion.lean), [`StringReading.lean`](../Ix/Kernel/Verify/Consistency/StringReading.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | +| Safe definition self-reference and block dependency order | [`DefinitionOrder.lean`](../Ix/Kernel/DefinitionOrder.lean), [`Consistency/DefinitionOrder.lean`](../Ix/Kernel/Verify/Consistency/DefinitionOrder.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | | Host commands, receipts, and frozen regression evidence | [Certified checking guide](certified-checking.md) | | Concrete set-theory instance | [Separate model package](../Models/SetTheory/README.md) | From 520ca3180c7d115148866191f6c47537163a6325 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 06:55:39 -0400 Subject: [PATCH 25/30] Preserve model readings through local values and binder opening --- Ix/Kernel/Verify/Consistency.lean | 10 + Ix/Kernel/Verify/Consistency/Audit.lean | 28 +- .../Verify/Consistency/LocalOpening.lean | 241 ++++++++ Ix/Kernel/Verify/Consistency/LocalValues.lean | 540 ++++++++++++++++++ Ix/Kernel/Verify/Ctx.lean | 127 +--- Ix/Kernel/Verify/LocalContext.lean | 150 +++++ Ix/Theory/Model/ContextTransport.lean | 39 ++ Tests/Theory/ImportManifest.lean | 1 + docs/kernel-verification.md | 11 + 9 files changed, 1017 insertions(+), 130 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/LocalOpening.lean create mode 100644 Ix/Kernel/Verify/Consistency/LocalValues.lean create mode 100644 Ix/Kernel/Verify/LocalContext.lean create mode 100644 Ix/Theory/Model/ContextTransport.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 2b5b530b3..a854474f5 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -18,6 +18,7 @@ import Ix.Kernel.Verify.Consistency.SortCache import Ix.Kernel.Verify.Consistency.ConstantCache import Ix.Kernel.Verify.Consistency.Context import Ix.Kernel.Verify.Consistency.BinderOpening +import Ix.Kernel.Verify.Consistency.LocalOpening import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.RecursiveCache @@ -78,6 +79,15 @@ error isolation preserve these facts. Its parameterized entry meaning and uncached-body preservation contract remain to be instantiated by the general mutual semantic proof. General checker soundness remains outside this fragment. +Value-aware local readings additionally record a let's stored value in the +same model context. Successful production opening preserves these readings, +local lookup completeness, the allocation-counter bound and intern coherence; +let-bound free-variable reduction preserves the model value. Regular binders +lift the earlier readings into the extended model context. The scoped reader +is recovered by mapping every local to its variable index. The let value's +typing, general reduction and inference, legacy local frames and the semantic +cache invariant remain obligations of the mutual execution proof. + The safe-definition guard excludes self-reference for both modes and arbitrary universe arities. Successful definition-block execution computes an order of all loaded safe members and implies a well-founded internal dependency relation. diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index af8ace938..72834680c 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -10,6 +10,7 @@ import Ix.Kernel.Verify.Consistency.RecursiveCache import Ix.Kernel.Verify.Consistency.CacheLifecycle import Ix.Kernel.Verify.Consistency.StringExpansion import Ix.Kernel.Verify.Consistency.DefinitionOrder +import Ix.Kernel.Verify.Consistency.LocalOpening import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -41,6 +42,7 @@ private def atomicRoots : Array Lean.Name := #[ ``AtomicInferenceSupport.reads, ``AtomicInferenceSupport.output, ``AtomicInferenceSupport.scopeAndReferences, ``AtomicInference.sound, ``inferUncached_fvar_sound, ``infer_fvar_sound, + ``inferUncached_fvar_local_sound, ``whnfCoreWithFlagsStep_fvar_local_sound, ``FVarInferenceSupport.output, ``FVarInferenceSupport.sound, ``InferenceCacheHit.run, ``infer_sort_cached_sound, ``infer_sort_cache_agreement, ``infer_sort_cache_frame, ``BinderInference.sortOfAgreement, @@ -195,7 +197,19 @@ private def binderWalkerRoots : Array Lean.Name := #[ ``readScopedExpr?_instantiateRevSpec, ``readScopedExpr?_abstractFVarsSpec, ``openBinder_eq, ``openBinder_sound, ``abstractFVars_singleton_spec, ``abstractFVars_readScopedExpr?, - ``readScopedExpr?_liftSpec, ``readScopedExpr?_substSpec, ``subst_readScopedExpr? + ``readScopedExpr?_liftSpec, ``readScopedExpr?_substSpec, ``subst_readScopedExpr?, + ``LocalContextValues.empty, ``openLet_eq, + ``LocalContextValues.openLet, ``LocalContextValues.openBinder, + ``readLocalExpr?_instantiateLetSpec, ``readLocalExpr?_instantiateBinderSpec, + ``openLet_local_sound, ``openBinder_local_sound +] + +private def localValueRoots : Array Lean.Name := #[ + ``Theory.Model.Context.Valid.pop, ``Theory.Model.TypingClaim.weaken, + ``readLocalExpr?_scoped, ``readLocalExpr?_eraseMeta, ``internExpr_readLocalExpr?, + ``readLocalExpr?_extend, ``readLocalExpr?_lift, ``localContext_find?_push_ne_eq, + ``LocalContextValues.index_none, ``LocalContextValues.pushLet, + ``LocalContextValues.pushBinder, ``LocalModelTyping.closed ] /-- Production roots must not acquire a checker-soundness assumption @@ -208,6 +222,10 @@ private def forbiddenProduction : Array Lean.Name := #[ ] def roots : Array RootAllowance := #[ + { root := ``LocalValues.Below.empty, standardAxioms := #[], + forbiddenDependencies := forbiddenProduction }, + { root := ``LocalValues.Below.absent, standardAxioms := #[], + forbiddenDependencies := forbiddenProduction }, { root := ``readLevel_eq, standardAxioms := #[``propext] }, { root := ``readLevel_eval, standardAxioms := #[``propext] }, { root := ``readLevel_wf, standardAxioms := #[``propext] }, @@ -271,13 +289,15 @@ def roots : Array RootAllowance := #[ { root := ``Theory.Model.CheckingClaim.typing, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.typingSort, standardAxioms := standard }, { root := ``Theory.Model.CheckingClaim.lam, standardAxioms := standard } -] ++ stringListRoots.map (fun root => { +] ++ (stringListRoots ++ #[``LocalValues.pushLet_extends, + ``LocalValues.pushBinder_lifts, ``LocalValues.Below.pushLet]).map (fun root => { root, standardAxioms := #[``propext], forbiddenDependencies := forbiddenProduction }) ++ (localIndexRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ internFrameRoots ++ #[``DefinitionOrder.ready_independent, - ``DefinitionOrder.order?_sound, ``DefinitionOrder.member_of_read]).map (fun root => { + ``DefinitionOrder.order?_sound, ``DefinitionOrder.member_of_read, + ``LocalValues.Below.pushBinder]).map (fun root => { root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction -}) ++ (contextRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ +}) ++ (contextRoots ++ localValueRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ internMapRoots ++ #[``DefinitionOrder.order?_rank, ``DefinitionOrder.acyclic_rank]).map (fun root => { root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction diff --git a/Ix/Kernel/Verify/Consistency/LocalOpening.lean b/Ix/Kernel/Verify/Consistency/LocalOpening.lean new file mode 100644 index 000000000..a60741f18 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LocalOpening.lean @@ -0,0 +1,241 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalValues + +/-! +# Opening binders with value-aware local readings + +The production opening walker replaces a syntactic variable with an interned +fresh local. For a let, reading the result substitutes that local's stored +value. For a regular binder, reading preserves the body in the extended model +context. These facts cover every expression constructor, including nested +lets, projections and the canonical string expansion. + +The operational theorems use the existing finite interning/walker support: +constructed source data, bounded machine indices and collision freedom on +exactly the table and reachable terms. They also preserve the local-context +invariant and the actual resulting intern table. +-/ + + +namespace Ix.Kernel.Consistency +open Theory Theory.Model +universe u v +variable {β : Type u} + +private theorem bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ value, action = some value ∧ next value = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +private theorem depth_succ {depth : UInt64} (bound : depth.toNat + 1 < UInt64.size) : + (depth + 1).toNat = depth.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt bound] + +private theorem inst_lift_above (source : VExpr β) (depth : Nat) : + (source.liftN 1 (depth + 1)).inst (.bvar 0) depth = source := by + induction source generalizing depth with + | bvar index => + simp only [VExpr.liftN, VExpr.inst, liftVar, VExpr.instVar] + split <;> split <;> (try split) <;> + simp_all <;> omega + | _ => simp_all [VExpr.liftN, VExpr.inst] + +theorem readLocalExpr?_instantiateLetSpec + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {body : KExpr .anon} {source : VExpr β} {value : AExpr β} + {depth : UInt64} {fresh : FVarId} + (absent : values fresh = none) + (bound : depth.toNat + body.size + 1 < UInt64.size) + (reading : readLocalExpr? resolve values body (depth.toNat + 1) = some source) : + readLocalExpr? resolve (values.pushLet fresh value) + (KExpr.instantiateRevSpec body #[KExpr.mkFVar fresh ()] depth) depth.toNat = + some (source.inst value.erase depth.toNat) := by + induction body generalizing source depth with + | var index name info => + simp only [readLocalExpr?] at reading + split at reading + next inScope => + cases reading + have next := depth_succ (depth := depth) (by simp only [KExpr.size] at bound; omega) + by_cases equal : index = depth + · subst index + simp [KExpr.instantiateRevSpec, UInt64.lt_iff_toNat_lt, next, + LocalValues.pushLet, VExpr.inst, VExpr.instVar] + · have smaller : index.toNat < depth.toNat := by + have : index.toNat ≠ depth.toNat := fun h => equal (UInt64.toNat_inj.mp h) + omega + have before : ¬ index ≥ depth := by simp only [UInt64.le_iff_toNat_le]; omega + have beforeNext : ¬ index ≥ depth + 1 := by + simp only [UInt64.le_iff_toNat_le, next]; omega + simp [KExpr.instantiateRevSpec, before, beforeNext, readLocalExpr?, smaller, + VExpr.inst, VExpr.instVar] + · contradiction + | fvar id name info => + obtain ⟨localValue, found, rfl⟩ := Option.map_eq_some_iff.mp reading + have out := LocalValues.pushLet_extends absent value id localValue found + simp only [KExpr.instantiateRevSpec, readLocalExpr?, out, Option.map_some] + congr 1 + rw [← VExpr.liftN_combine (e := localValue.erase) (n₁ := depth.toNat) (n₂ := 1) + (k₁ := 0) (k₂ := depth.toNat) (Nat.zero_le _) (by omega), VExpr.inst_liftN] + | sort _ _ | nat _ _ _ => cases reading; rfl + | const id levels info => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + cases reading + simp [KExpr.instantiateRevSpec, readLocalExpr?, resolved, VExpr.inst] + | str value name info => + rw [readString?_inst reading] + exact reading + | letE name domain value body nonDep info hA hv hb => + rw [readLocalExpr?] at reading + obtain ⟨A, aReads, reading⟩ := bind_success reading + obtain ⟨v, vReads, reading⟩ := bind_success reading + obtain ⟨b, bReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.instantiateRevSpec, hA (by omega) aReads, + hv (by omega) vReads, bodyOut, VExpr.inst0_inst_hi] + | app fn arg info hf ha => + rw [readLocalExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.instantiateRevSpec, VExpr.inst, + hf (by omega) fReads, ha (by omega) aReads] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readLocalExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := bind_success reading + obtain ⟨B, bodyReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bodyReads) + simp only [next] at bodyOut + simp [KExpr.instantiateRevSpec, VExpr.inst, + hd (by omega) domainReads, bodyOut] + | prj id index value info ih => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.instantiateRevSpec, VExpr.inst, resolved, + ih (by omega) valueReads] + +theorem readLocalExpr?_instantiateBinderSpec + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {body : KExpr .anon} {source : VExpr β} {depth : UInt64} {fresh : FVarId} + (absent : values fresh = none) + (bound : depth.toNat + body.size + 1 < UInt64.size) + (reading : readLocalExpr? resolve values body (depth.toNat + 1) = some source) : + readLocalExpr? resolve (values.pushBinder fresh) + (KExpr.instantiateRevSpec body #[KExpr.mkFVar fresh ()] depth) depth.toNat = + some source := by + let lifted : LocalValues β := fun id => (values id).map (·.liftN 1) + have liftReads := readLocalExpr?_lift (more := lifted) (by intros; simp_all [lifted]) reading + have opened := readLocalExpr?_instantiateLetSpec (value := .bvar 0) + (fresh := fresh) (by simp [lifted, absent]) bound liftReads + have maps : lifted.pushLet fresh (.bvar 0) = values.pushBinder fresh := rfl + rw [maps] at opened + simpa only [AExpr.erase, inst_lift_above] using opened + +private theorem BinderOpeningSupport.localWalk {before : TcState .anon} + {body : KExpr .anon} (support : BinderOpeningSupport before body) : + let fv := KExpr.mkFVar (m := .anon) ⟨before.env.nextFVarId⟩ () + let interned := before.env.intern.internExpr fv + let walked := instantiateRev body #[fv] interned.2 + interned.1 = fv ∧ walked.1 = KExpr.instantiateRevSpec body #[fv] 0 ∧ walked.2.WF := by + have keyFaithful : KExpr.KeyCollisionFree (fun term => + before.env.intern.ExprSupport term ∨ term = KExpr.mkFVar ⟨before.env.nextFVarId⟩ ()) := + KExpr.keyCollisionFree_anon.mpr + (support.faithful.mono fun term h => h.elim Or.inl (fun equal => .inr (.inl equal))) + have interned : (before.env.intern.internExpr + (KExpr.mkFVar ⟨before.env.nextFVarId⟩ ())).1 = + KExpr.mkFVar ⟨before.env.nextFVarId⟩ () := by + simpa only [KExpr.eraseMeta_anon] using + before.env.intern.internExpr_eraseMeta support.coherent keyFaithful + have walk := instantiateRev_spec (fvars := #[KExpr.mkFVar ⟨before.env.nextFVarId⟩ ()]) + support.faithful support.constructed (by simpa using support.bound) + (fun _ reached => .inr (.inr reached)) + (support.coherent.internExpr (KExpr.mkFVar ⟨before.env.nextFVarId⟩ ())) + (fun _ member => (InternTable.ExprSupport.of_internExpr member).elim + Or.inl (fun equal => .inr (.inl equal))) + exact ⟨interned, walk.1, walk.2.1⟩ + +theorem openLet_local_sound + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {values : LocalValues β} {context : Model.Context β} + {type value body opened : KExpr .anon} {A e : AExpr β} {b : VExpr β} + {fresh : FVarId} {before after : TcState .anon} {name : Mode.anon.F Name} + (support : BinderOpeningSupport before body) + (agreement : LocalContextValues.{u,v} resolve entries values before.lctx context) + (below : values.Below before.env.nextFVarId) + (typeReads : readLocalExpr? resolve values type = some A.erase) + (valueReads : readLocalExpr? resolve values value = some e.erase) + (bodyReads : readLocalExpr? resolve values body 1 = some b) + (typed : TypingClaim.{u,v} entries context e A) + (accepted : TcM.openLet name type value body before = .ok (opened, fresh) after) : + fresh = ⟨before.env.nextFVarId⟩ ∧ + readLocalExpr? resolve (values.pushLet fresh e) opened = some (b.inst e.erase) ∧ + LocalContextValues.{u,v} resolve entries (values.pushLet fresh e) after.lctx context ∧ + (values.pushLet fresh e).Below after.env.nextFVarId ∧ after.env.intern.WF := by + have nameUnit : name = () := Subsingleton.elim _ _ + subst name + have absent := below.absent + have walk := support.localWalk + rw [openLet_eq] at accepted + split at accepted + next room => + simp only [walk.1] at accepted + cases accepted + refine ⟨rfl, ?_, agreement.pushLet absent typeReads valueReads typed, + below.pushLet e room, walk.2.2⟩ + rw [walk.2.1] + exact readLocalExpr?_instantiateLetSpec absent (by simpa using support.bound) bodyReads + · contradiction + +theorem openBinder_local_sound + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {values : LocalValues β} {context : Model.Context β} + {type body opened : KExpr .anon} {A : AExpr β} {b : VExpr β} + {fresh : FVarId} {before after : TcState .anon} + {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + (support : BinderOpeningSupport before body) + (agreement : LocalContextValues.{u,v} resolve entries values before.lctx context) + (below : values.Below before.env.nextFVarId) + (typeReads : readLocalExpr? resolve values type = some A.erase) + (bodyReads : readLocalExpr? resolve values body 1 = some b) + (accepted : TcM.openBinder name bi type body before = .ok (opened, fresh) after) : + fresh = ⟨before.env.nextFVarId⟩ ∧ + readLocalExpr? resolve (values.pushBinder fresh) opened = some b ∧ + LocalContextValues.{u,v} resolve entries (values.pushBinder fresh) + after.lctx (context.push A) ∧ (values.pushBinder fresh).Below after.env.nextFVarId ∧ + after.env.intern.WF := by + have nameUnit : name = () := Subsingleton.elim _ _ + have biUnit : bi = () := Subsingleton.elim _ _ + subst name bi + have absent := below.absent + have walk := support.localWalk + rw [openBinder_eq] at accepted + split at accepted + next room => + simp only [walk.1] at accepted + cases accepted + refine ⟨rfl, ?_, agreement.pushBinder absent typeReads, below.pushBinder room, walk.2.2⟩ + rw [walk.2.1] + exact readLocalExpr?_instantiateBinderSpec absent (by simpa using support.bound) bodyReads + · contradiction + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/LocalValues.lean b/Ix/Kernel/Verify/Consistency/LocalValues.lean new file mode 100644 index 000000000..490ae7338 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LocalValues.lean @@ -0,0 +1,540 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.ContextTransport +import Ix.Kernel.Verify.LocalContext +import Ix.Kernel.Verify.Consistency.BinderOpening + +/-! +# Reading production locals by their values + +Regular binders map to model variables. Let-bound locals map to the already +checked value stored by the production declaration. This extends the scoped +reader and makes local zeta reduction preserve the reading itself. A regular +binder extends the model context and lifts older readings; a let leaves the +model context unchanged. Both operations preserve lookup completeness and +the exact types and stored values returned by the production local context. + +The typing premise of a let push is the recursive inference obligation for +its value. General inference and cache preservation must still discharge it; +these local rules do not assume a general checker-soundness theorem. +-/ + +namespace Ix.Kernel.Consistency +open Theory Theory.Model +universe u v +variable {β : Type u} {m : Mode} + +abbrev LocalValues (β : Type u) := FVarId → Option (AExpr β) + +def readLocalExpr? (resolve : Address → Option (ConstRef β)) (values : LocalValues β) : + KExpr m → (depth : Nat := 0) → Option (VExpr β) + | .var index _ _, depth => + if index.toNat < depth then some (.bvar index.toNat) else none + | .fvar id _ _, depth => (values id).map (fun value => value.erase.liftN depth) + | .sort level _, _ => some (.sort (readLevel level)) + | .const id levels _, _ => do + return .const (← resolve id.addr) (levels.toList.map readLevel) + | .app fn arg _, depth => do + return .app (← readLocalExpr? resolve values fn depth) + (← readLocalExpr? resolve values arg depth) + | .lam _ _ domain body _, depth => do + return .lam (← readLocalExpr? resolve values domain depth) + (← readLocalExpr? resolve values body (depth + 1)) + | .all _ _ domain body _, depth => do + return .forallE (← readLocalExpr? resolve values domain depth) + (← readLocalExpr? resolve values body (depth + 1)) + | .prj id index value _, depth => do + return .proj (← resolve id.addr) index.toNat + (← readLocalExpr? resolve values value depth) + | .nat value _ _, _ => some (.natLit value) + | .letE _ domain value body _ _, depth => do + let _ ← readLocalExpr? resolve values domain depth + let value ← readLocalExpr? resolve values value depth + let body ← readLocalExpr? resolve values body (depth + 1) + return body.inst value + | .str value _ _, _ => readString? resolve value + +@[simp] theorem readLocalExpr?_mkFVar (resolve : Address → Option (ConstRef β)) + (values : LocalValues β) (id : FVarId) (name : m.F Name) (depth : Nat) : + readLocalExpr? resolve values (KExpr.mkFVar id name) depth = + (values id).map (fun value => value.erase.liftN depth) := rfl + +@[simp] theorem readLocalExpr?_mkApp (resolve : Address → Option (ConstRef β)) + (values : LocalValues β) (fn arg : KExpr m) (depth : Nat) : + readLocalExpr? resolve values (KExpr.mkApp fn arg) depth = do + return .app (← readLocalExpr? resolve values fn depth) + (← readLocalExpr? resolve values arg depth) := rfl + +@[simp] theorem readLocalExpr?_mkLam (resolve : Address → Option (ConstRef β)) + (values : LocalValues β) (name : m.F Name) (bi : m.F Lean.BinderInfo) + (domain body : KExpr m) (depth : Nat) : + readLocalExpr? resolve values (KExpr.mkLam name bi domain body) depth = do + return .lam (← readLocalExpr? resolve values domain depth) + (← readLocalExpr? resolve values body (depth + 1)) := rfl + +@[simp] theorem readLocalExpr?_mkAll (resolve : Address → Option (ConstRef β)) + (values : LocalValues β) (name : m.F Name) (bi : m.F Lean.BinderInfo) + (domain body : KExpr m) (depth : Nat) : + readLocalExpr? resolve values (KExpr.mkAll name bi domain body) depth = do + return .forallE (← readLocalExpr? resolve values domain depth) + (← readLocalExpr? resolve values body (depth + 1)) := rfl + +@[simp] theorem readLocalExpr?_mkPrj (resolve : Address → Option (ConstRef β)) + (values : LocalValues β) (id : KId m) (index : UInt64) (value : KExpr m) (depth : Nat) : + readLocalExpr? resolve values (KExpr.mkPrj id index value) depth = do + return .proj (← resolve id.addr) index.toNat + (← readLocalExpr? resolve values value depth) := rfl + +@[simp] theorem readLocalExpr?_mkLet (resolve : Address → Option (ConstRef β)) + (values : LocalValues β) (name : m.F Name) (domain value body : KExpr m) + (nonDep : Bool) (depth : Nat) : + readLocalExpr? resolve values (KExpr.mkLet name domain value body nonDep) depth = do + let _ ← readLocalExpr? resolve values domain depth + let value ← readLocalExpr? resolve values value depth + let body ← readLocalExpr? resolve values body (depth + 1) + return body.inst value := rfl + +theorem readLocalExpr?_scoped (resolve : Address → Option (ConstRef β)) + (locals : List FVarId) (term : KExpr m) (depth : Nat) : + readLocalExpr? resolve (fun id => (localIndex? locals id).map AExpr.bvar) term depth = + readScopedExpr? resolve locals term depth := by + induction term generalizing depth with + | fvar id name info => + cases found : localIndex? locals id <;> + simp [readLocalExpr?, readScopedExpr?, found, AExpr.erase, VExpr.liftN, liftVar] + | _ => simp_all [readLocalExpr?, readScopedExpr?] + +@[simp] theorem readLocalExpr?_eraseMeta + (resolve : Address → Option (ConstRef β)) (values : LocalValues β) + (term : KExpr m) (depth : Nat) : + readLocalExpr? resolve values term.eraseMeta depth = + readLocalExpr? resolve values term depth := by + induction term generalizing depth <;> + simp_all [readLocalExpr?, KExpr.eraseMeta, KId.eraseMeta, + Array.toList_map, List.map_map, Function.comp_def] + +theorem internExpr_readLocalExpr? {resolve : Address → Option (ConstRef β)} + {values : LocalValues β} {table : InternTable m} {term : KExpr m} {depth : Nat} + (coherent : table.WF) + (faithful : KExpr.KeyCollisionFree fun value => table.ExprSupport value ∨ value = term) : + readLocalExpr? resolve values (table.internExpr term).1 depth = + readLocalExpr? resolve values term depth := by + simpa only [readLocalExpr?_eraseMeta] using + congrArg (fun term => readLocalExpr? resolve values term depth) + (table.internExpr_eraseMeta coherent faithful) + +private theorem option_bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ value, action = some value ∧ next value = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +theorem readLocalExpr?_extend {resolve : Address → Option (ConstRef β)} + {values more : LocalValues β} {term : KExpr m} {depth : Nat} {source : VExpr β} + (extension : ∀ id value, values id = some value → more id = some value) + (reading : readLocalExpr? resolve values term depth = some source) : + readLocalExpr? resolve more term depth = some source := by + induction term generalizing source depth with + | fvar id name info => + obtain ⟨value, found, rfl⟩ := Option.map_eq_some_iff.mp reading + simp [readLocalExpr?, extension _ _ found] + | var _ _ _ | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => exact reading + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readLocalExpr?] at reading + obtain ⟨f, fReads, reading⟩ := option_bind_success reading + obtain ⟨a, aReads, reading⟩ := option_bind_success reading + cases reading + simp [readLocalExpr?, hf fReads, ha aReads] + | prj id index value info ih => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := option_bind_success reading + obtain ⟨value, valueReads, reading⟩ := option_bind_success reading + cases reading + simp [readLocalExpr?, resolved, ih valueReads] + | letE name domain value body nonDep info hA hv hb => + rw [readLocalExpr?] at reading + obtain ⟨A, aReads, reading⟩ := option_bind_success reading + obtain ⟨v, vReads, reading⟩ := option_bind_success reading + obtain ⟨b, bReads, reading⟩ := option_bind_success reading + cases reading + simp [readLocalExpr?, hA aReads, hv vReads, hb bReads] + +theorem readLocalExpr?_lift {resolve : Address → Option (ConstRef β)} + {values more : LocalValues β} {term : KExpr m} {depth : Nat} {source : VExpr β} + (extension : ∀ id value, values id = some value → more id = some (value.liftN 1)) + (reading : readLocalExpr? resolve values term depth = some source) : + readLocalExpr? resolve more term depth = some (source.liftN 1 depth) := by + induction term generalizing source depth with + | var index name info => + simp only [readLocalExpr?] at reading ⊢ + split at reading + next bound => + cases reading + simp [bound, VExpr.liftN, liftVar] + · contradiction + | fvar id name info => + obtain ⟨value, found, rfl⟩ := Option.map_eq_some_iff.mp reading + simp only [readLocalExpr?, extension _ _ found, Option.map_some, AExpr.erase_liftN] + congr 1 + rw [VExpr.liftN_combine (Nat.zero_le 0) (Nat.zero_le 1), + VExpr.liftN_combine (Nat.zero_le depth) (by omega), Nat.add_comm] + | str value _ _ => + rw [readString?_liftN reading] + exact reading + | sort _ _ | nat _ _ _ => cases reading; rfl + | const id levels info => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := option_bind_success reading + cases reading + simp [readLocalExpr?, resolved, VExpr.liftN] + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readLocalExpr?] at reading + obtain ⟨f, fReads, reading⟩ := option_bind_success reading + obtain ⟨a, aReads, reading⟩ := option_bind_success reading + cases reading + simp [readLocalExpr?, hf fReads, ha aReads, VExpr.liftN] + | prj id index value info ih => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := option_bind_success reading + obtain ⟨value, valueReads, reading⟩ := option_bind_success reading + cases reading + simp [readLocalExpr?, resolved, ih valueReads, VExpr.liftN] + | letE name domain value body nonDep info hA hv hb => + rw [readLocalExpr?] at reading + obtain ⟨A, aReads, reading⟩ := option_bind_success reading + obtain ⟨v, vReads, reading⟩ := option_bind_success reading + obtain ⟨b, bReads, reading⟩ := option_bind_success reading + cases reading + simp [readLocalExpr?, hA aReads, hv vReads, hb bReads, VExpr.liftN_inst_hi] + +private local instance : LawfulBEq FVarId where + eq_of_beq := by + intro left right equal + cases left + cases right + congr 1 + exact eq_of_beq equal + rfl {a} := by + cases a with + | mk x => show (x == x) = true; exact beq_self_eq_true x + +theorem localContext_find?_push_ne_eq {context : LocalContext m} {id fresh : FVarId} + {decl : LocalDecl m} (coherent : context.WF) (different : id ≠ fresh) : + (context.push fresh decl).find? id = context.find? id := by + cases index : context.index[id]? with + | none => + simp [LocalContext.find?, LocalContext.push, Std.HashMap.getElem?_insert, + Ne.symm different, index] + | some position => + have bound := coherent.index_lt index + simp [LocalContext.find?, LocalContext.push, Std.HashMap.getElem?_insert, + Ne.symm different, index, Array.getElem?_push, Nat.ne_of_lt bound] + +def LocalValues.pushLet (values : LocalValues β) (fresh : FVarId) (value : AExpr β) : + LocalValues β := fun id => if id = fresh then some value else values id + +def LocalValues.pushBinder (values : LocalValues β) (fresh : FVarId) : LocalValues β := + fun id => if id = fresh then some (.bvar 0) else (values id).map (·.liftN 1) + +/-- The live readings use only identifiers already allocated by the +production counter. Successful allocation checks that its increment fits. -/ +def LocalValues.Below (values : LocalValues β) (next : UInt64) : Prop := + ∀ id value, values id = some value → id.id.toNat < next.toNat + +theorem LocalValues.Below.empty (next : UInt64) : + LocalValues.Below (β := β) (fun _ => none) next := by + intro id value found + contradiction + +theorem LocalValues.Below.absent {values : LocalValues β} {next : UInt64} + (below : values.Below next) : values ⟨next⟩ = none := by + cases found : values ⟨next⟩ with + | none => rfl + | some value => exact False.elim (Nat.lt_irrefl _ (below _ _ found)) + +theorem LocalValues.Below.pushLet {values : LocalValues β} {next : UInt64} + (below : values.Below next) (value : AExpr β) + (room : next.toNat + 1 < UInt64.size) : + (values.pushLet ⟨next⟩ value).Below (next + 1) := by + have advance : (next + 1).toNat = next.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt room] + intro id e found + rw [advance] + by_cases equal : id = ⟨next⟩ + · subst id; exact Nat.lt_succ_self _ + · simp only [LocalValues.pushLet, equal, if_false] at found + exact Nat.lt_trans (below _ _ found) (Nat.lt_succ_self _) + +theorem LocalValues.Below.pushBinder {values : LocalValues β} {next : UInt64} + (below : values.Below next) (room : next.toNat + 1 < UInt64.size) : + (values.pushBinder ⟨next⟩).Below (next + 1) := by + have advance : (next + 1).toNat = next.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt room] + intro id e found + rw [advance] + by_cases equal : id = ⟨next⟩ + · subst id; exact Nat.lt_succ_self _ + · simp only [LocalValues.pushBinder, equal, if_false] at found + obtain ⟨previous, hit, _⟩ := Option.map_eq_some_iff.mp found + exact Nat.lt_trans (below _ _ hit) (Nat.lt_succ_self _) + +theorem LocalValues.pushLet_extends {values : LocalValues β} {fresh : FVarId} + (absent : values fresh = none) (added : AExpr β) : + ∀ id value, values id = some value → values.pushLet fresh added id = some value := by + intro id value found + have different : id ≠ fresh := by intro equal; subst id; simp [absent] at found + simp [pushLet, different, found] + +theorem LocalValues.pushBinder_lifts {values : LocalValues β} {fresh : FVarId} + (absent : values fresh = none) : + ∀ id value, values id = some value → values.pushBinder fresh id = some (value.liftN 1) := by + intro id value found + have different : id ≠ fresh := by intro equal; subst id; simp [absent] at found + simp [pushBinder, different, found] + +structure LocalContextValues (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) (values : LocalValues β) + (concrete : LocalContext .anon) (context : Model.Context β) : Prop where + coherent : concrete.WF + complete : ∀ id decl, concrete.find? id = some decl → ∃ value, values id = some value + lookup : ∀ id value, values id = some value → + ∃ decl type, concrete.find? id = some decl ∧ + readLocalExpr? resolve values decl.ty = some type.erase ∧ + TypingClaim.{u,v} entries context value type ∧ + ∀ stored, decl.val? = some stored → readLocalExpr? resolve values stored = some value.erase + +theorem LocalContextValues.empty (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) : + LocalContextValues.{u,v} resolve entries (fun _ => none) .empty [] := by + refine ⟨.empty, ?_, ?_⟩ + · intro id decl found + simp [LocalContext.find?, LocalContext.empty] at found + · intro id value found + contradiction + +theorem LocalContextValues.index_none {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} + {concrete : LocalContext .anon} {context : Model.Context β} {id : FVarId} + (agreement : LocalContextValues.{u,v} resolve entries values concrete context) + (absent : values id = none) : concrete.index[id]? = none := by + cases index : concrete.index[id]? with + | none => rfl + | some position => + obtain ⟨decl, atIndex⟩ := agreement.coherent.sound index + have found : concrete.find? id = some decl := by simp [LocalContext.find?, index, atIndex] + obtain ⟨value, read⟩ := agreement.complete _ _ found + simp [absent] at read + +theorem LocalContextValues.pushLet {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} + {concrete : LocalContext .anon} {context : Model.Context β} + {fresh : FVarId} {name : Mode.anon.F Name} {type value : KExpr .anon} + {A e : AExpr β} + (agreement : LocalContextValues.{u,v} resolve entries values concrete context) + (absent : values fresh = none) + (typeReads : readLocalExpr? resolve values type = some A.erase) + (valueReads : readLocalExpr? resolve values value = some e.erase) + (typed : TypingClaim.{u,v} entries context e A) : + LocalContextValues.{u,v} resolve entries (values.pushLet fresh e) + (concrete.push fresh (.ldecl name type value)) context := by + have extended := LocalValues.pushLet_extends absent e + refine ⟨agreement.coherent.push (agreement.index_none absent), ?_, ?_⟩ + · intro id decl found + by_cases equal : id = fresh + · subst id; exact ⟨e, by simp [LocalValues.pushLet]⟩ + · rw [localContext_find?_push_ne_eq agreement.coherent equal] at found + obtain ⟨v, hit⟩ := agreement.complete _ _ found + exact ⟨v, extended _ _ hit⟩ + · intro id v hit + by_cases equal : id = fresh + · subst id + simp only [LocalValues.pushLet, if_true, Option.some.injEq] at hit + subst v + refine ⟨.ldecl name type value, A, localContext_find?_push_same _ _ _, + readLocalExpr?_extend extended typeReads, typed, ?_⟩ + intro stored found + cases found + exact readLocalExpr?_extend extended valueReads + · simp only [LocalValues.pushLet, equal, if_false] at hit + obtain ⟨decl, B, found, reading, vTyped, valueReading⟩ := agreement.lookup _ _ hit + exact ⟨decl, B, localContext_find?_push_ne equal found, + readLocalExpr?_extend extended reading, vTyped, + fun stored found => readLocalExpr?_extend extended (valueReading stored found)⟩ + +theorem LocalContextValues.pushBinder {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} + {concrete : LocalContext .anon} {context : Model.Context β} + {fresh : FVarId} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {type : KExpr .anon} {A : AExpr β} + (agreement : LocalContextValues.{u,v} resolve entries values concrete context) + (absent : values fresh = none) + (typeReads : readLocalExpr? resolve values type = some A.erase) : + LocalContextValues.{u,v} resolve entries (values.pushBinder fresh) + (concrete.push fresh (.cdecl name bi type)) (context.push A) := by + have extended := LocalValues.pushBinder_lifts absent + refine ⟨agreement.coherent.push (agreement.index_none absent), ?_, ?_⟩ + · intro id decl found + by_cases equal : id = fresh + · subst id; exact ⟨.bvar 0, by simp [LocalValues.pushBinder]⟩ + · rw [localContext_find?_push_ne_eq agreement.coherent equal] at found + obtain ⟨v, hit⟩ := agreement.complete _ _ found + exact ⟨v.liftN 1, extended _ _ hit⟩ + · intro id v hit + by_cases equal : id = fresh + · subst id + simp only [LocalValues.pushBinder, if_true, Option.some.injEq] at hit + subst v + refine ⟨.cdecl name bi type, A.liftN 1, localContext_find?_push_same _ _ _, + ?_, TypingClaim.bvar rfl, ?_⟩ + · simpa only [AExpr.erase_liftN, LocalDecl.ty] using readLocalExpr?_lift extended typeReads + · intro stored found; contradiction + · simp only [LocalValues.pushBinder, equal, if_false] at hit + obtain ⟨previous, previousHit, rfl⟩ := Option.map_eq_some_iff.mp hit + obtain ⟨decl, B, found, reading, vTyped, valueReading⟩ := agreement.lookup _ _ previousHit + refine ⟨decl, B.liftN 1, localContext_find?_push_ne equal found, ?_, + vTyped.weaken A, ?_⟩ + · simpa only [AExpr.erase_liftN] using readLocalExpr?_lift extended reading + · intro stored found + simpa only [AExpr.erase_liftN] using readLocalExpr?_lift extended (valueReading stored found) + +def LocalModelTyping (resolve : Address → Option (ConstRef β)) + (entries : Model.Environment β) (values : LocalValues β) (context : Model.Context β) + (term type : KExpr .anon) : Prop := + ∃ e A : AExpr β, readLocalExpr? resolve values term = some e.erase ∧ + readLocalExpr? resolve values type = some A.erase ∧ + TypingClaim.{u,v} entries context e A + +theorem LocalModelTyping.closed {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {term type : KExpr .anon} + (typed : LocalModelTyping.{u,v} resolve entries (fun _ => none) [] term type) : + ModelTyping.{u,v} resolve entries [] term type := by + obtain ⟨e, A, termReads, typeReads, typed⟩ := typed + have asScoped (t : KExpr .anon) : readLocalExpr? resolve (fun _ => none) t = + readScopedExpr? resolve [] t := readLocalExpr?_scoped resolve [] t 0 + rw [asScoped] at termReads typeReads + exact ⟨e, A, readScopedExpr?_closed termReads, readScopedExpr?_closed typeReads, typed⟩ + +theorem inferUncached_fvar_local_sound {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} {context : Model.Context β} + {id : FVarId} {name : Mode.anon.F Name} {info : ExprInfo .anon} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {inferOnly : Bool} + {methods : Methods .anon} {before after : TcState .anon} {type : KExpr .anon} + (agreement : LocalContextValues.{u,v} resolve entries values before.lctx context) + (accepted : RecM.inferUncached inferRec inferOnly (.fvar id name info) + methods before = .ok type after) : + LocalModelTyping.{u,v} resolve entries values context (.fvar id name info) type := by + change (RecM.inferUncached inferRec inferOnly (.fvar id name info)).run + methods before = .ok type after at accepted + unfold RecM.inferUncached at accepted + simp only [ReaderT.run_bind] at accepted + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ at accepted + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] at accepted + cases found : before.lctx.find? id with + | none => simp only [found] at accepted; contradiction + | some decl => + simp only [found] at accepted + cases accepted + obtain ⟨value, hit⟩ := agreement.complete _ _ found + obtain ⟨decl', A, found', reading, typed, _⟩ := agreement.lookup _ _ hit + have equal : decl' = decl := Option.some.inj (found'.symm.trans found) + subst decl' + exact ⟨value, A, by simp [readLocalExpr?, hit], reading, typed⟩ + +theorem whnfCoreWithFlagsStep_fvar_local_sound + {resolve : Address → Option (ConstRef β)} {entries : Model.Environment β} + {values : LocalValues β} {context : Model.Context β} + {id : FVarId} {name : Mode.anon.F Name} {info : ExprInfo .anon} + {methods : Methods .anon} {before after : TcState .anon} + {flags : WhnfFlags} {result : KExpr .anon} + (agreement : LocalContextValues.{u,v} resolve entries values before.lctx context) + (accepted : RecM.whnfCoreWithFlagsStep (.fvar id name info) flags + methods before = .ok (.next result) after) : + after = before ∧ ∃ e A : AExpr β, + readLocalExpr? resolve values (.fvar id name info) = some e.erase ∧ + readLocalExpr? resolve values result = some e.erase ∧ + TypingClaim.{u,v} entries context e A := by + change (RecM.whnfCoreWithFlagsStep (.fvar id name info) flags).run + methods before = .ok (.next result) after at accepted + unfold RecM.whnfCoreWithFlagsStep at accepted + simp only [ReaderT.run_bind] at accepted + change EStateM.bind (get : TcM .anon (TcState .anon)) _ before = _ at accepted + rw [EStateM.bind, show (get : TcM .anon (TcState .anon)) before = + .ok before before from rfl] at accepted + cases found : before.lctx.find? id with + | none => simp only [found] at accepted; cases accepted + | some decl => + cases decl with + | cdecl n bi ty => simp only [found] at accepted; cases accepted + | ldecl n ty value => + simp only [found] at accepted + cases accepted + obtain ⟨value, hit⟩ := agreement.complete _ _ found + obtain ⟨decl, A, found', _, typed, reading⟩ := agreement.lookup _ _ hit + have equal : decl = .ldecl n ty result := Option.some.inj (found'.symm.trans found) + subst decl + exact ⟨rfl, value, A, by simp [readLocalExpr?, hit], reading result rfl, typed⟩ + +theorem openLet_eq (name : Mode.anon.F Name) (type value body : KExpr .anon) + (before : TcState .anon) : + TcM.openLet name type value body before = + if before.env.nextFVarId.toNat + 1 < UInt64.size then + let fresh : FVarId := ⟨before.env.nextFVarId⟩ + let internedLocal := before.env.intern.internExpr (KExpr.mkFVar fresh name) + let opened := instantiateRev body #[internedLocal.1] internedLocal.2 + .ok (opened.1, fresh) {before with + env := {before.env with + nextFVarId := before.env.nextFVarId + 1 + intern := opened.2} + lctx := before.lctx.push fresh (.ldecl name type value)} + else .error (.other "free-variable id space exhausted") before := by + unfold TcM.openLet + change EStateM.bind TcM.freshFVarId _ before = _ + rw [EStateM.bind, TcM.freshFVarId] + by_cases room : before.env.nextFVarId.toNat + 1 < UInt64.size + · simp only [room, if_true] + rfl + · simp only [room, if_false] + +theorem LocalContextValues.openLet {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} + {context : Model.Context β} {before after : TcState .anon} + {fresh : FVarId} {name : Mode.anon.F Name} {type value body opened : KExpr .anon} + {A e : AExpr β} + (agreement : LocalContextValues.{u,v} resolve entries values before.lctx context) + (absent : values ⟨before.env.nextFVarId⟩ = none) + (typeReads : readLocalExpr? resolve values type = some A.erase) + (valueReads : readLocalExpr? resolve values value = some e.erase) + (typed : TypingClaim.{u,v} entries context e A) + (accepted : TcM.openLet name type value body before = .ok (opened, fresh) after) : + fresh = ⟨before.env.nextFVarId⟩ ∧ + LocalContextValues.{u,v} resolve entries (values.pushLet fresh e) after.lctx context := by + rw [openLet_eq] at accepted + split at accepted + · cases accepted + exact ⟨rfl, agreement.pushLet absent typeReads valueReads typed⟩ + · contradiction + +theorem LocalContextValues.openBinder {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} + {context : Model.Context β} {before after : TcState .anon} + {fresh : FVarId} {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {type body opened : KExpr .anon} {A : AExpr β} + (agreement : LocalContextValues.{u,v} resolve entries values before.lctx context) + (absent : values ⟨before.env.nextFVarId⟩ = none) + (typeReads : readLocalExpr? resolve values type = some A.erase) + (accepted : TcM.openBinder name bi type body before = .ok (opened, fresh) after) : + fresh = ⟨before.env.nextFVarId⟩ ∧ + LocalContextValues.{u,v} resolve entries (values.pushBinder fresh) + after.lctx (context.push A) := by + rw [openBinder_eq] at accepted + split at accepted + · cases accepted + exact ⟨rfl, agreement.pushBinder absent typeReads⟩ + · contradiction + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Ctx.lean b/Ix/Kernel/Verify/Ctx.lean index 6fbce5403..bb6f49765 100644 --- a/Ix/Kernel/Verify/Ctx.lean +++ b/Ix/Kernel/Verify/Ctx.lean @@ -1,5 +1,5 @@ import Ix.Kernel.Verify.State -import Ix.Kernel.Lctx +import Ix.Kernel.Verify.LocalContext /-! # Dual-context reconciliation: `CtxRecon` @@ -111,131 +111,6 @@ def KVLCtx.bvarLets : KVLCtx → Nat {fv : FVarId × List FVarId} {d : VLocalDecl} : KVLCtx.bvarLets ((some fv, d) :: Δ) = KVLCtx.bvarLets Δ := rfl -/-! ### Concrete `LocalContext` well-formedness - -The invariant is deliberately extensional in the hash-map representation: -every successful index lookup must point to a declaration carrying the same -id. An earlier push-history inductive was too strong for production -`truncate`: `erase (insert map key value) key` is lookup-equivalent to `map` -when the key was absent, but `Std.HashMap` does not promise representation -equality after that mutation pair. -/ - -structure LocalContext.WF {m : Mode} (lctx : LocalContext m) : Prop where - sound : ∀ {fv : FVarId} {i : Nat}, lctx.index[fv]? = some i → - ∃ d, lctx.decls[i]? = some (fv, d) - -protected theorem LocalContext.WF.empty : - LocalContext.WF ({} : LocalContext m) where - sound := by simp - -protected theorem LocalContext.WF.push {m : Mode} - {lctx : LocalContext m} {fv : FVarId} {d : LocalDecl m} - (h : lctx.WF) (hfree : lctx.index[fv]? = none) : - (lctx.push fv d).WF where - sound := by - have _hfree := hfree - intro queried i hi - simp only [LocalContext.push] at hi ⊢ - rw [Std.HashMap.getElem?_insert] at hi - split at hi - · next heq => - cases hi - have hid : fv = queried := eq_of_beq heq - subst queried - refine ⟨d, ?_⟩ - rw [Array.getElem?_push] - simp - · obtain ⟨decl, hd⟩ := h.sound hi - refine ⟨decl, ?_⟩ - rw [Array.getElem?_push, if_neg] - · exact hd - · intro hieq - subst i - obtain ⟨hlt, _⟩ := Array.getElem?_eq_some_iff.mp hd - omega - -theorem LocalContext.WF.mem_of_index {m : Mode} - {lctx : LocalContext m} (h : lctx.WF) {fv : FVarId} {i : Nat} - (hi : lctx.index[fv]? = some i) : - ∃ p ∈ lctx.decls.toList, p.1 = fv := by - obtain ⟨d, hd⟩ := h.sound hi - refine ⟨(fv, d), ?_, rfl⟩ - apply List.mem_of_getElem? - rw [Array.getElem?_toList] - exact hd - -theorem LocalContext.WF.index_lt {m : Mode} {lctx : LocalContext m} - (h : lctx.WF) {fv : FVarId} {i : Nat} - (hi : lctx.index[fv]? = some i) : i < lctx.decls.size := by - obtain ⟨d, hd⟩ := h.sound hi - exact (Array.getElem?_eq_some_iff.mp hd).choose - -/-- The index is positionally coherent: a hit points at an entry - carrying exactly the queried id. -/ -theorem LocalContext.WF.getElem?_of_index {m : Mode} - {lctx : LocalContext m} (h : lctx.WF) {fv : FVarId} {i : Nat} - (hi : lctx.index[fv]? = some i) : - ∃ d, lctx.decls[i]? = some (fv, d) := - h.sound hi - -/-- Truncating a one-entry extension produces the exact declaration-array -prefix and an index whose remaining hits are still sound. The index is not -claimed equal to any earlier hash-map value. -/ -theorem LocalContext.truncate_pred_eval {m : Mode} - {lctx : LocalContext m} {len : Nat} - (hsize : lctx.decls.size = len + 1) : - lctx.truncate len = - { decls := lctx.decls.pop - index := lctx.index.erase lctx.decls.back!.1 } := by - unfold LocalContext.truncate - simp [hsize, LocalContext.truncate.go] - -theorem LocalContext.WF.truncate_pred {m : Mode} - {lctx : LocalContext m} {len : Nat} - (h : lctx.WF) (hsize : lctx.decls.size = len + 1) : - (lctx.truncate len).WF := by - rw [LocalContext.truncate_pred_eval hsize] - constructor - intro fv i hi - change (lctx.index.erase lctx.decls.back!.1)[fv]? = some i at hi - rw [Std.HashMap.getElem?_erase] at hi - split at hi - · contradiction - · next hne => - obtain ⟨d, hd⟩ := h.sound hi - by_cases hlt : i < lctx.decls.pop.size - · refine ⟨d, ?_⟩ - rw [Array.getElem?_pop, if_pos (by simpa using hlt)] - exact hd - · have hiOld : i < lctx.decls.size := - (Array.getElem?_eq_some_iff.mp hd).choose - have hiLast : i = lctx.decls.size - 1 := by - simp only [Array.size_pop] at hlt - omega - subst i - obtain ⟨hiBound, hget⟩ := Array.getElem?_eq_some_iff.mp hd - have hback : lctx.decls.back! = (fv, d) := by - simp only [Array.back!] - rw [getElem!_pos lctx.decls (lctx.decls.size - 1) hiBound] - exact hget - exfalso - rw [hback] at hne - simp at hne - -/-- Unpack the concrete `find?` read into a positional hit. -/ -theorem LocalContext.WF.find?_pos {m : Mode} {lctx : LocalContext m} - (h : lctx.WF) {fv : FVarId} {d : LocalDecl m} - (hf : lctx.find? fv = some d) : - ∃ i, i < lctx.decls.size ∧ lctx.decls[i]? = some (fv, d) := by - match hi : lctx.index[fv]? with - | none => simp [LocalContext.find?, hi] at hf - | some i => - obtain ⟨d', hd⟩ := h.getElem?_of_index hi - have hlt := h.index_lt hi - refine ⟨i, hlt, ?_⟩ - simp [LocalContext.find?, hi, hd] at hf - rw [hd, hf] - /-! ### Per-declaration translation (upstream `TrLocalDecl`) -/ variable (env : VEnv) (uvars : Nat) (nameOf : Address → Option Lean.Name) diff --git a/Ix/Kernel/Verify/LocalContext.lean b/Ix/Kernel/Verify/LocalContext.lean new file mode 100644 index 000000000..bfe2c765c --- /dev/null +++ b/Ix/Kernel/Verify/LocalContext.lean @@ -0,0 +1,150 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Lctx +import Std.Data.HashMap.Lemmas + +/-! +# Concrete local-context coherence + +Every successful index lookup points at a declaration carrying the queried +identifier. These structural facts are shared by the direct set-model proof +and the named translation, without importing either semantic development. +They concern the actual production context, including truncation. +-/ + +namespace Ix.Kernel + +private local instance : LawfulBEq FVarId where + eq_of_beq := by + intro left right equal + cases left + cases right + congr 1 + exact eq_of_beq equal + rfl {a} := by + cases a with + | mk x => show (x == x) = true; exact beq_self_eq_true x + +/-! The invariant is extensional in the index map. Truncation need not +reconstruct a previous hash-map representation to preserve it. -/ + +structure LocalContext.WF {m : Mode} (lctx : LocalContext m) : Prop where + sound : ∀ {fv : FVarId} {i : Nat}, lctx.index[fv]? = some i → + ∃ d, lctx.decls[i]? = some (fv, d) + +protected theorem LocalContext.WF.empty : + LocalContext.WF ({} : LocalContext m) where + sound := by simp + +protected theorem LocalContext.WF.push {m : Mode} + {lctx : LocalContext m} {fv : FVarId} {d : LocalDecl m} + (h : lctx.WF) (hfree : lctx.index[fv]? = none) : + (lctx.push fv d).WF where + sound := by + have _hfree := hfree + intro queried i hi + simp only [LocalContext.push] at hi ⊢ + rw [Std.HashMap.getElem?_insert] at hi + split at hi + · next heq => + cases hi + have hid : fv = queried := eq_of_beq heq + subst queried + refine ⟨d, ?_⟩ + rw [Array.getElem?_push] + simp + · obtain ⟨decl, hd⟩ := h.sound hi + refine ⟨decl, ?_⟩ + rw [Array.getElem?_push, if_neg] + · exact hd + · intro hieq + subst i + obtain ⟨hlt, _⟩ := Array.getElem?_eq_some_iff.mp hd + omega + +theorem LocalContext.WF.mem_of_index {m : Mode} + {lctx : LocalContext m} (h : lctx.WF) {fv : FVarId} {i : Nat} + (hi : lctx.index[fv]? = some i) : + ∃ p ∈ lctx.decls.toList, p.1 = fv := by + obtain ⟨d, hd⟩ := h.sound hi + refine ⟨(fv, d), ?_, rfl⟩ + apply List.mem_of_getElem? + rw [Array.getElem?_toList] + exact hd + +theorem LocalContext.WF.index_lt {m : Mode} {lctx : LocalContext m} + (h : lctx.WF) {fv : FVarId} {i : Nat} + (hi : lctx.index[fv]? = some i) : i < lctx.decls.size := by + obtain ⟨d, hd⟩ := h.sound hi + exact (Array.getElem?_eq_some_iff.mp hd).choose + +/-- The index is positionally coherent: a hit points at an entry + carrying exactly the queried id. -/ +theorem LocalContext.WF.getElem?_of_index {m : Mode} + {lctx : LocalContext m} (h : lctx.WF) {fv : FVarId} {i : Nat} + (hi : lctx.index[fv]? = some i) : + ∃ d, lctx.decls[i]? = some (fv, d) := + h.sound hi + +/-- Truncating a one-entry extension produces the exact declaration-array +prefix and an index whose remaining hits are still sound. The index is not +claimed equal to any earlier hash-map value. -/ +theorem LocalContext.truncate_pred_eval {m : Mode} + {lctx : LocalContext m} {len : Nat} + (hsize : lctx.decls.size = len + 1) : + lctx.truncate len = + { decls := lctx.decls.pop + index := lctx.index.erase lctx.decls.back!.1 } := by + unfold LocalContext.truncate + simp [hsize, LocalContext.truncate.go] + +theorem LocalContext.WF.truncate_pred {m : Mode} + {lctx : LocalContext m} {len : Nat} + (h : lctx.WF) (hsize : lctx.decls.size = len + 1) : + (lctx.truncate len).WF := by + rw [LocalContext.truncate_pred_eval hsize] + constructor + intro fv i hi + change (lctx.index.erase lctx.decls.back!.1)[fv]? = some i at hi + rw [Std.HashMap.getElem?_erase] at hi + split at hi + · contradiction + · next hne => + obtain ⟨d, hd⟩ := h.sound hi + by_cases hlt : i < lctx.decls.pop.size + · refine ⟨d, ?_⟩ + rw [Array.getElem?_pop, if_pos (by simpa using hlt)] + exact hd + · have hiOld : i < lctx.decls.size := + (Array.getElem?_eq_some_iff.mp hd).choose + have hiLast : i = lctx.decls.size - 1 := by + simp only [Array.size_pop] at hlt + omega + subst i + obtain ⟨hiBound, hget⟩ := Array.getElem?_eq_some_iff.mp hd + have hback : lctx.decls.back! = (fv, d) := by + simp only [Array.back!] + rw [getElem!_pos lctx.decls (lctx.decls.size - 1) hiBound] + exact hget + exfalso + rw [hback] at hne + simp at hne + +/-- Unpack the concrete `find?` read into a positional hit. -/ +theorem LocalContext.WF.find?_pos {m : Mode} {lctx : LocalContext m} + (h : lctx.WF) {fv : FVarId} {d : LocalDecl m} + (hf : lctx.find? fv = some d) : + ∃ i, i < lctx.decls.size ∧ lctx.decls[i]? = some (fv, d) := by + match hi : lctx.index[fv]? with + | none => simp [LocalContext.find?, hi] at hf + | some i => + obtain ⟨d', hd⟩ := h.getElem?_of_index hi + have hlt := h.index_lt hi + refine ⟨i, hlt, ?_⟩ + simp [LocalContext.find?, hi, hd] at hf + rw [hd, hf] + +end Ix.Kernel diff --git a/Ix/Theory/Model/ContextTransport.lean b/Ix/Theory/Model/ContextTransport.lean new file mode 100644 index 000000000..a1fa2d30e --- /dev/null +++ b/Ix/Theory/Model/ContextTransport.lean @@ -0,0 +1,39 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Theory.Model.Judgment + +/-! +# Transport across context extension + +A valuation satisfying an extended context also satisfies its previous +context after dropping the newest variable. Consequently every existing +semantic typing claim can be lifted into that extension. +-/ + +namespace Ix.Theory.Model +universe u v +variable {β : Type u} + +open SetTheory + +theorem Context.Valid.pop {V : Type v} [SetTheory V] + {constants : Assignment β V} {levels : List Nat} {Γ : Context β} + {env : Nat → V} {A : AExpr β} + (valid : (Γ.push A).Valid constants levels env) : + Γ.Valid constants levels (Valuation.skip 1 0 env) := by + intro i B found + have previous := valid (i + 1) (B.liftN 1) (by simp [Context.push, found]) + simpa only [wellDenoted_liftN, interp_liftN, Valuation.skip, Nat.not_lt_zero, + if_false, Nat.add_comm 1] using previous + +theorem TypingClaim.weaken {entries : Environment β} {Γ : Context β} + {e A : AExpr β} (typed : TypingClaim.{u,v} entries Γ e A) (D : AExpr β) : + TypingClaim.{u,v} entries (Γ.push D) (e.liftN 1) (A.liftN 1) := by + intro V _ constants realized levels env valid + simpa only [wellDenoted_liftN, interp_liftN] using + typed V constants realized levels (Valuation.skip 1 0 env) valid.pop + +end Ix.Theory.Model diff --git a/Tests/Theory/ImportManifest.lean b/Tests/Theory/ImportManifest.lean index b61e4a3cd..21c9d1282 100644 --- a/Tests/Theory/ImportManifest.lean +++ b/Tests/Theory/ImportManifest.lean @@ -18,6 +18,7 @@ def conLecheRevision : String := "86cd20a65660d757cedc81561a44579099b565d0" /-- New mathematical modules authored in Ix, with no imported source hash. -/ def authored : Array String := #[ "Ix/Theory/ExprSubstitution.lean", + "Ix/Theory/Model/ContextTransport.lean", "Ix/Theory/Model/Checking.lean", "Ix/Theory/Model/LevelCongruence.lean" ] diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index f3301fce7..1433627a9 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -130,6 +130,16 @@ increasing sequence of strongly inaccessible cardinals. - `checkEnvAnon_atomic_preserves_model` connects a supported production environment run to model extension. `checkEnvAnon_atomic_no_false` excludes a declaration at an axiom type interpreted as empty, including False. +- `LocalContextValues` includes the stored values of let-bound free variables. + Its reader recovers the existing scoped reader when all locals are ordinary + variables. Actual binder and let opening preserve the reading, complete + local lookup, the bound on allocated identifiers, and intern-table coherence. + A let leaves the model context unchanged; a regular binder lifts older + readings into the extended context. The production free-variable inference + branch is typed by this invariant, and its zeta-reduction step preserves the + model value. General inference must still supply the let value's typing; + closing the returned type, general reduction, legacy local frames, and + semantic cache preservation remain separate obligations. - `InferenceCacheInvariant` covers every entry in both production maps, with separate full-checking and inference-only meanings. Hits obtain stored facts directly; each insertion establishes its own fact and preserves all other @@ -395,6 +405,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Complete inference-cache maps and driver lifecycle | [`Consistency/CacheInvariant.lean`](../Ix/Kernel/Verify/Consistency/CacheInvariant.lean), [`CacheLifecycle.lean`](../Ix/Kernel/Verify/Consistency/CacheLifecycle.lean) | | Finite intern support and production string expansion | [`Consistency/InternInvariant.lean`](../Ix/Kernel/Verify/Consistency/InternInvariant.lean), [`StringExpansion.lean`](../Ix/Kernel/Verify/Consistency/StringExpansion.lean), [`StringReading.lean`](../Ix/Kernel/Verify/Consistency/StringReading.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | +| Let-bound values, local allocation and shared context coherence | [`Consistency/LocalValues.lean`](../Ix/Kernel/Verify/Consistency/LocalValues.lean), [`LocalOpening.lean`](../Ix/Kernel/Verify/Consistency/LocalOpening.lean), [`Verify/LocalContext.lean`](../Ix/Kernel/Verify/LocalContext.lean), [`Model/ContextTransport.lean`](../Ix/Theory/Model/ContextTransport.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Safe definition self-reference and block dependency order | [`DefinitionOrder.lean`](../Ix/Kernel/DefinitionOrder.lean), [`Consistency/DefinitionOrder.lean`](../Ix/Kernel/Verify/Consistency/DefinitionOrder.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | From c0227f2627b2d9cfc44d7b072599ddc50fe08e0d Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 07:25:23 -0400 Subject: [PATCH 26/30] Derive production let traces and preserve substituted type readings --- Ix/Kernel/Verify/Consistency.lean | 15 +- Ix/Kernel/Verify/Consistency/Audit.lean | 12 +- .../Verify/Consistency/LetInference.lean | 190 +++++++ .../Verify/Consistency/LocalSubstitution.lean | 510 ++++++++++++++++++ docs/kernel-verification.md | 17 +- 5 files changed, 736 insertions(+), 8 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/LetInference.lean create mode 100644 Ix/Kernel/Verify/Consistency/LocalSubstitution.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index a854474f5..7fc2f2804 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -19,6 +19,8 @@ import Ix.Kernel.Verify.Consistency.ConstantCache import Ix.Kernel.Verify.Consistency.Context import Ix.Kernel.Verify.Consistency.BinderOpening import Ix.Kernel.Verify.Consistency.LocalOpening +import Ix.Kernel.Verify.Consistency.LocalSubstitution +import Ix.Kernel.Verify.Consistency.LetInference import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.RecursiveCache @@ -84,9 +86,16 @@ same model context. Successful production opening preserves these readings, local lookup completeness, the allocation-counter bound and intern coherence; let-bound free-variable reduction preserves the model value. Regular binders lift the earlier readings into the extended model context. The scoped reader -is recovered by mapping every local to its variable index. The let value's -typing, general reduction and inference, legacy local frames and the semantic -cache invariant remain obligations of the mutual execution proof. +is recovered by mapping every local to its variable index. Actual abstraction +followed by substitution closes a let body's inferred type with the same +reading and preserves intern coherence; its residual abstraction is derived +from the body reading. The let value's typing, cheap beta and general +reduction and inference, legacy local frames and the semantic cache invariant +remain obligations of the mutual execution proof. +Successful let inference yields its full operational trace in both policies, +including computed sort exposure and conversion. This trace transports the +recursive body's typing to the original let and its substituted type before +the final cheap-beta pass. The safe-definition guard excludes self-reference for both modes and arbitrary universe arities. Successful definition-block execution computes an order of diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 72834680c..5fe044e67 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -11,6 +11,8 @@ import Ix.Kernel.Verify.Consistency.CacheLifecycle import Ix.Kernel.Verify.Consistency.StringExpansion import Ix.Kernel.Verify.Consistency.DefinitionOrder import Ix.Kernel.Verify.Consistency.LocalOpening +import Ix.Kernel.Verify.Consistency.LocalSubstitution +import Ix.Kernel.Verify.Consistency.LetInference import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -48,6 +50,7 @@ private def atomicRoots : Array Lean.Name := #[ ``infer_sort_cache_agreement, ``infer_sort_cache_frame, ``BinderInference.sortOfAgreement, ``ForallInferenceTrace.output, ``LambdaInferenceTrace.output, ``BinderInference.sound, ``inferUncached_monomorphic_const_scoped, ``ApplicationInferenceTrace.output, + ``LetInferenceTrace.of_success, ``LetInferenceTrace.beforeBeta_typing, ``BinderInference.soundWithSynthesis, ``BinderInference.synthesis, ``DefinitionBodySupport.sound ] @@ -201,7 +204,10 @@ private def binderWalkerRoots : Array Lean.Name := #[ ``LocalContextValues.empty, ``openLet_eq, ``LocalContextValues.openLet, ``LocalContextValues.openBinder, ``readLocalExpr?_instantiateLetSpec, ``readLocalExpr?_instantiateBinderSpec, - ``openLet_local_sound, ``openBinder_local_sound + ``openLet_local_sound, ``openBinder_local_sound, + ``readLocalExpr?_liftSpec, ``readLocalExpr?_substSpec, ``subst_readLocalExpr?, + ``readLocalExpr?_abstractFVarsSpec, ``abstractFVars_readLocalExpr?, + ``KExpr.abstractFVarsSpec_size, ``closeLetType_readLocalExpr? ] private def localValueRoots : Array Lean.Name := #[ @@ -209,7 +215,9 @@ private def localValueRoots : Array Lean.Name := #[ ``readLocalExpr?_scoped, ``readLocalExpr?_eraseMeta, ``internExpr_readLocalExpr?, ``readLocalExpr?_extend, ``readLocalExpr?_lift, ``localContext_find?_push_ne_eq, ``LocalContextValues.index_none, ``LocalContextValues.pushLet, - ``LocalContextValues.pushBinder, ``LocalModelTyping.closed + ``LocalContextValues.pushBinder, ``LocalModelTyping.closed, + ``readLocalExpr?_readable, ``readLocalExpr?_instantiateLocal, + ``readLocalExpr?_letResidual ] /-- Production roots must not acquire a checker-soundness assumption diff --git a/Ix/Kernel/Verify/Consistency/LetInference.lean b/Ix/Kernel/Verify/Consistency/LetInference.lean new file mode 100644 index 000000000..6fb23497b --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LetInference.lean @@ -0,0 +1,190 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalSubstitution +import Ix.Kernel.Verify.Consistency.InferenceCache +import Ix.Kernel.Knot + +/-! +# The production let-inference path + +Successful execution produces the complete trace in either validation mode, +including reduction-dependent sort exposure and conversion. Opening and +closing preserve the source and inferred-type readings before the final +cheap-beta pass. The value and body typing premises are the recursive +inference obligations; this module does not supply general reduction or +cache soundness. +-/ + +namespace Ix.Kernel.Consistency + +/-- Successful validation before the local scope is opened. Infer-only skips +both checks. Full mode follows the actual sort-exposure and conversion calls, +including their reduction-dependent paths and state changes. -/ +inductive LetValidationTrace + (inferRec : KExpr .anon → RecM .anon (KExpr .anon)) + (methods : Methods .anon) (type value : KExpr .anon) : + Bool → TcState .anon → TcState .anon → Prop + | skipped (before : TcState .anon) : LetValidationTrace inferRec methods type value true before before + | full {before typeState sorted valueState checked : TcState .anon} + {typeType valueType : KExpr .anon} {level : KUniv .anon} + (typeRun : inferRec type methods before = .ok typeType typeState) + (sortRun : RecM.ensureSortDirect typeType methods typeState = .ok level sorted) + (valueRun : inferRec value methods sorted = .ok valueType valueState) + (conversion : RecM.isDefEqCall valueType type methods valueState = .ok true checked) : + LetValidationTrace inferRec methods type value false before checked + +/-- Actual successful let inference, with the deterministic closing sequence +and final local-scope cleanup. This trace is extracted from execution. -/ +structure LetInferenceTrace + (inferRec : KExpr .anon → RecM .anon (KExpr .anon)) + (methods : Methods .anon) (inferOnly : Bool) + (name : Mode.anon.F Name) (type value body : KExpr .anon) + (before : TcState .anon) (result : KExpr .anon) (after : TcState .anon) where + validated : TcState .anon + validation : LetValidationTrace inferRec methods type value inferOnly before validated + opened : KExpr .anon + fresh : FVarId + openedState : TcState .anon + bodyType : KExpr .anon + bodyState : TcState .anon + openRun : TcM.openLet name type value body validated = .ok (opened, fresh) openedState + bodyRun : inferRec opened methods openedState = .ok bodyType bodyState + resultEq : + let abstracted := abstractFVars bodyType #[fresh] bodyState.env.intern + let substituted := subst abstracted.1 value 0 abstracted.2 + result = (cheapBetaReduce substituted.1 substituted.2).1 + stateEq : + let abstracted := abstractFVars bodyType #[fresh] bodyState.env.intern + let substituted := subst abstracted.1 value 0 abstracted.2 + let reduced := cheapBetaReduce substituted.1 substituted.2 + after = {bodyState with + env := {bodyState.env with intern := reduced.2} + lctx := bodyState.lctx.truncate validated.lctx.size} + +private theorem bind_success {α γ : Type _} {action : TcM .anon α} + {next : α → TcM .anon γ} {before after : TcState .anon} {result : γ} + (run : (action >>= next) before = .ok result after) : + ∃ value state, action before = .ok value state ∧ next value state = .ok result after := by + cases first : action before with + | error error state => simp [bind, EStateM.bind, first] at run + | ok value state => + refine ⟨value, state, rfl, ?_⟩ + simpa [bind, EStateM.bind, first] using run + +private theorem withLctxScope_success {action : RecM .anon α} + {methods : Methods .anon} {before after : TcState .anon} {result : α} + (run : (RecM.withLctxScope action).run methods before = .ok result after) : + ∃ state, action.run methods before = .ok result state ∧ + after = {state with lctx := state.lctx.truncate before.lctx.size} := by + rw [withLctxScope_eq] at run + cases bodyRun : action.run methods before with + | error error state => rw [bodyRun] at run; contradiction + | ok value state => + rw [bodyRun] at run + cases run + exact ⟨state, rfl, rfl⟩ + +private theorem let_scope_success + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {methods : Methods .anon} + {inferOnly : Bool} {name : Mode.anon.F Name} {type value body result : KExpr .anon} + {before validated after : TcState .anon} + (validation : LetValidationTrace inferRec methods type value inferOnly before validated) + (run : ((RecM.withLctxScope (m := .anon) do + let (opened, fresh) ← TcM.openLet name type value body + let bodyType ← inferRec opened + let abstracted ← TcM.runIntern (abstractFVars bodyType #[fresh]) + let substituted ← TcM.runIntern (subst abstracted value 0) + TcM.runIntern (cheapBetaReduce substituted)).run methods) validated = .ok result after) : + Nonempty (LetInferenceTrace inferRec methods inferOnly name type value body before result after) := by + obtain ⟨finished, run, cleanup⟩ := withLctxScope_success run + simp only [ReaderT.run_bind, ReaderT.run_monadLift] at run + obtain ⟨⟨opened, fresh⟩, openedState, openRun, run⟩ := bind_success run + obtain ⟨bodyType, bodyState, bodyRun, run⟩ := bind_success run + change EStateM.Result.ok _ _ = .ok result finished at run + obtain ⟨out, state⟩ := EStateM.Result.ok.inj run + refine ⟨⟨validated, validation, opened, fresh, openedState, bodyType, bodyState, + openRun, bodyRun, out.symm, ?_⟩⟩ + rw [cleanup, ← state] + rfl + +/-- Every successful production let branch yields the entire operational +trace in either policy. No cache-miss tree, syntactic sort result, conversion +shortcut or precomputed trace is supplied. -/ +theorem LetInferenceTrace.of_success + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {methods : Methods .anon} + {inferOnly : Bool} {name : Mode.anon.F Name} + {type value body result : KExpr .anon} {nonDep : Bool} {info : ExprInfo .anon} + {before after : TcState .anon} + (run : RecM.inferUncached inferRec inferOnly (.letE name type value body nonDep info) + methods before = .ok result after) : + Nonempty (LetInferenceTrace inferRec methods inferOnly name type value body before result after) := by + change (RecM.inferUncached inferRec inferOnly (.letE name type value body nonDep info)).run + methods before = .ok result after at run + unfold RecM.inferUncached at run + cases inferOnly with + | true => + simp only [Bool.not_true, Bool.false_eq_true, if_false] at run + exact let_scope_success (.skipped before) run + | false => + simp only [Bool.not_false, if_true, ReaderT.run_bind] at run + obtain ⟨typeType, typeState, typeRun, run⟩ := bind_success run + obtain ⟨level, sorted, sortRun, run⟩ := bind_success run + obtain ⟨valueType, valueState, valueRun, run⟩ := bind_success run + obtain ⟨equal, checked, conversion, run⟩ := bind_success run + cases equal with + | false => contradiction + | true => + simp only [Bool.not_true, Bool.false_eq_true, if_false] at run + exact let_scope_success (.full typeRun sortRun valueRun conversion) run + +open Theory Theory.Model + +universe u v + +/-- The actual opening and closing sequence transports the recursive body's +typing to the original let expression and its substituted type. The final +cheap-beta pass remains a separate reduction obligation. -/ +theorem LetInferenceTrace.beforeBeta_typing + {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} {context : Model.Context β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {methods : Methods .anon} + {inferOnly : Bool} {name : Mode.anon.F Name} {type value body result : KExpr .anon} + {before after : TcState .anon} {A e : AExpr β} {b : VExpr β} + (trace : LetInferenceTrace inferRec methods inferOnly name type value body before result after) + (support : BinderOpeningSupport trace.validated body) + (agreement : LocalContextValues.{u,v} resolve entries values trace.validated.lctx context) + (below : values.Below trace.validated.env.nextFVarId) + (typeReads : readLocalExpr? resolve values type = some A.erase) + (valueReads : readLocalExpr? resolve values value = some e.erase) + (bodyReads : readLocalExpr? resolve values body 1 = some b) + (valueTyped : TypingClaim.{u,v} entries context e A) + (bodyTyped : LocalModelTyping.{u,v} resolve entries (values.pushLet trace.fresh e) + context trace.opened trace.bodyType) + (constructed : trace.bodyType.Constructed) (valueConstructed : value.Constructed) + (bound : trace.bodyType.lbr.toNat + trace.bodyType.size + 1 < UInt64.size) + (valueBound : value.size < UInt64.size) (coherent : trace.bodyState.env.intern.WF) + (abstractFaithful : KExpr.CollisionFree fun term => trace.bodyState.env.intern.ExprSupport term ∨ + KExpr.AbstractReach ((∅ : Std.HashMap FVarId UInt64).insert trace.fresh 0) 1 trace.bodyType 0 term) + (substFaithful : + let abstracted := abstractFVars trace.bodyType #[trace.fresh] trace.bodyState.env.intern + KExpr.CollisionFree fun term => abstracted.2.ExprSupport term ∨ + KExpr.SubstReach value abstracted.1 0 term) + (nonDep : Bool) (info : ExprInfo .anon) : + let abstracted := abstractFVars trace.bodyType #[trace.fresh] trace.bodyState.env.intern + let substituted := subst abstracted.1 value 0 abstracted.2 + LocalModelTyping.{u,v} resolve entries values context + (.letE name type value body nonDep info) substituted.1 ∧ substituted.2.WF := by + have opened := openLet_local_sound support agreement below typeReads valueReads bodyReads + valueTyped trace.openRun + obtain ⟨source, inferred, sourceReads, inferredReads, typed⟩ := bodyTyped + have sameSource : b.inst e.erase = source.erase := + Option.some.inj (opened.2.1.symm.trans sourceReads) + have closed := closeLetType_readLocalExpr? constructed valueConstructed bound valueBound + coherent abstractFaithful substFaithful inferredReads valueReads + refine ⟨⟨source, inferred, ?_, closed.1, typed⟩, closed.2⟩ + simp [readLocalExpr?, typeReads, valueReads, bodyReads, sameSource] + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/LocalSubstitution.lean b/Ix/Kernel/Verify/Consistency/LocalSubstitution.lean new file mode 100644 index 000000000..08906b2c6 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LocalSubstitution.lean @@ -0,0 +1,510 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalOpening + +/-! +# Substitution and let-type closing with local values + +Registered values remain free in the kernel tree while their model indices +move below each syntactic binder. The actual memoized substitution and +singleton abstraction walkers preserve this reading. In particular, closing +an inferred let-body type and substituting the stored value preserves its +original reading and intern-table coherence. The residual abstraction is +derived from the body's reading, rather than supplied by the caller. +-/ + +namespace Ix.Kernel.Consistency + +open Theory Theory.Model + +universe u +variable {β : Type u} + +private theorem bind_success {α γ : Type _} {action : Option α} + {next : α → Option γ} {result : γ} (run : action.bind next = some result) : + ∃ intermediate, action = some intermediate ∧ next intermediate = some result := by + cases action with + | none => contradiction + | some value => exact ⟨value, rfl, run⟩ + +private theorem depth_succ {depth : UInt64} (bound : depth.toNat + 1 < UInt64.size) : + (depth + 1).toNat = depth.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt bound] + +private theorem readLocalExpr?_let_parts {resolve : Address → Option (ConstRef β)} + {values : LocalValues β} {name : Mode.anon.F Name} {domain value body : KExpr .anon} + {nonDep : Bool} {info : ExprInfo .anon} {source : VExpr β} {depth : Nat} + (reading : readLocalExpr? resolve values (.letE name domain value body nonDep info) + depth = some source) : + ∃ A v b, readLocalExpr? resolve values domain depth = some A ∧ + readLocalExpr? resolve values value depth = some v ∧ + readLocalExpr? resolve values body (depth + 1) = some b ∧ source = b.inst v := by + rw [readLocalExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := bind_success reading + obtain ⟨v, valueReads, reading⟩ := bind_success reading + obtain ⟨b, bodyReads, reading⟩ := bind_success reading + cases reading + exact ⟨A, v, b, domainReads, valueReads, bodyReads, rfl⟩ + +/-- Lifting a term with no loose legacy variables shifts the reading of its +registered values beneath the new syntactic binders. -/ +theorem readLocalExpr?_liftSpec + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {term : KExpr .anon} {source : VExpr β} {depth shift : UInt64} + (bound : depth.toNat + term.size < UInt64.size) + (reading : readLocalExpr? resolve values term depth.toNat = some source) : + readLocalExpr? resolve values (KExpr.liftSpec term shift depth) + (depth.toNat + shift.toNat) = some (source.liftN shift.toNat depth.toNat) := by + induction term generalizing source depth with + | var index name info => + simp only [readLocalExpr?] at reading + split at reading + next inScope => + cases reading + have below : ¬ index ≥ depth := by + simp only [UInt64.le_iff_toNat_le]; omega + simp [KExpr.liftSpec, below, readLocalExpr?, show index.toNat < + depth.toNat + shift.toNat by omega, VExpr.liftN, liftVar, inScope] + · contradiction + | fvar id name info => + rw [readLocalExpr?] at reading + obtain ⟨value, found, reading⟩ := Option.map_eq_some_iff.mp reading + cases reading + simp only [KExpr.liftSpec, readLocalExpr?, found, Option.map_some] + congr 1 + exact (VExpr.liftN_combine (Nat.zero_le _) (by omega)).symm + | sort _ _ | nat _ _ _ => cases reading; rfl + | const id levels info => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + cases reading + simp [KExpr.liftSpec, readLocalExpr?, resolved, VExpr.liftN] + | str value _ _ => + rw [readString?_liftN reading] + exact reading + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readLocalExpr?_let_parts reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.liftSpec, hA (by omega) aReads, hv (by omega) vReads, + VExpr.liftN_inst_hi, show depth.toNat + shift.toNat + 1 = + depth.toNat + 1 + shift.toNat by omega, bodyOut] + | app fn arg info hf ha => + rw [readLocalExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.liftSpec, hf (by omega) fReads, ha (by omega) aReads, VExpr.liftN] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readLocalExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := bind_success reading + obtain ⟨B, bodyReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bodyReads) + simp only [next] at bodyOut + simp [KExpr.liftSpec, hd (by omega) domainReads, VExpr.liftN, + show depth.toNat + shift.toNat + 1 = depth.toNat + 1 + shift.toNat by omega, + bodyOut] + | prj id index value info ih => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.liftSpec, resolved, ih (by omega) valueReads, VExpr.liftN] + +/-- Removing one syntactic binder agrees with model substitution, including +arguments that contain registered values and their own nested binders. -/ +theorem readLocalExpr?_substSpec + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {body arg : KExpr .anon} {source argument : VExpr β} {depth : UInt64} + (bound : depth.toNat + body.size + 1 < UInt64.size) + (argBound : arg.size < UInt64.size) + (bodyReads : readLocalExpr? resolve values body (depth.toNat + 1) = some source) + (argReads : readLocalExpr? resolve values arg = some argument) : + readLocalExpr? resolve values (KExpr.substSpec body arg depth) depth.toNat = + some (source.inst argument depth.toNat) := by + induction body generalizing source depth with + | var index name info => + simp only [readLocalExpr?] at bodyReads + split at bodyReads + next inScope => + cases bodyReads + by_cases equal : index = depth + · subst index + simp only [KExpr.substSpec, beq_self_eq_true, if_true, VExpr.inst, VExpr.instVar, + Nat.lt_irrefl, if_false] + simpa only [UInt64.toNat_zero, Nat.zero_add] using + (readLocalExpr?_liftSpec (depth := 0) (shift := depth) + (by simpa using argBound) argReads) + · have smaller : index.toNat < depth.toNat := by + have : index.toNat ≠ depth.toNat := fun h => equal (UInt64.toNat_inj.mp h) + omega + have below : ¬ index > depth := by + simp only [UInt64.lt_iff_toNat_lt]; omega + simp [KExpr.substSpec, equal, below, readLocalExpr?, smaller, + VExpr.inst, VExpr.instVar] + · contradiction + | fvar id name info => + rw [readLocalExpr?] at bodyReads + obtain ⟨value, found, bodyReads⟩ := Option.map_eq_some_iff.mp bodyReads + cases bodyReads + simp only [KExpr.substSpec, readLocalExpr?, found, Option.map_some] + congr 1 + rw [← VExpr.liftN_combine (e := value.erase) (n₁ := depth.toNat) (n₂ := 1) + (k₁ := 0) (k₂ := depth.toNat) (Nat.zero_le _) (by omega), VExpr.inst_liftN] + | sort _ _ | nat _ _ _ => cases bodyReads; rfl + | const id levels info => + rw [readLocalExpr?] at bodyReads + obtain ⟨ref, resolved, bodyReads⟩ := bind_success bodyReads + cases bodyReads + simp [KExpr.substSpec, readLocalExpr?, resolved, VExpr.inst] + | str value _ _ => + rw [readString?_inst bodyReads] + exact bodyReads + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readLocalExpr?_let_parts bodyReads + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.substSpec, hA (by omega) aReads, hv (by omega) vReads, + VExpr.inst0_inst_hi, bodyOut] + | app fn value info hf ha => + rw [readLocalExpr?] at bodyReads + obtain ⟨f, fReads, bodyReads⟩ := bind_success bodyReads + obtain ⟨a, aReads, bodyReads⟩ := bind_success bodyReads + cases bodyReads + simp only [KExpr.size] at bound + simp [KExpr.substSpec, hf (by omega) fReads, ha (by omega) aReads, VExpr.inst] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readLocalExpr?] at bodyReads + obtain ⟨A, domainReads, bodyReads⟩ := bind_success bodyReads + obtain ⟨B, innerReads, reading⟩ := bind_success bodyReads + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using innerReads) + simp only [next] at bodyOut + simp [KExpr.substSpec, hd (by omega) domainReads, bodyOut, VExpr.inst] + | prj id index value info ih => + rw [readLocalExpr?] at bodyReads + obtain ⟨ref, resolved, bodyReads⟩ := bind_success bodyReads + obtain ⟨value, valueReads, bodyReads⟩ := bind_success bodyReads + cases bodyReads + simp only [KExpr.size] at bound + simp [KExpr.substSpec, resolved, ih (by omega) valueReads, VExpr.inst] + +/-- The actual memoized, interned walker inherits the structural substitution +reading under finite collision freedom and bounds excluding index overflow. -/ +theorem subst_readLocalExpr? + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {body arg : KExpr .anon} {source argument : VExpr β} {table : InternTable .anon} + (bodyConstructed : body.Constructed) (argConstructed : arg.Constructed) + (bodyBound : body.size + 1 < UInt64.size) (argBound : arg.size < UInt64.size) + (coherent : table.WF) + (faithful : KExpr.CollisionFree fun term => table.ExprSupport term ∨ + KExpr.SubstReach arg body 0 term) + (bodyReads : readLocalExpr? resolve values body 1 = some source) + (argReads : readLocalExpr? resolve values arg = some argument) : + readLocalExpr? resolve values (subst body arg 0 table).1 = some (source.inst argument) ∧ + (subst body arg 0 table).2.WF := by + obtain ⟨result, coherent, _⟩ := subst_spec faithful bodyConstructed argConstructed + (by simpa using (show body.size < UInt64.size by omega)) argBound + (fun _ h => Or.inr h) coherent (fun _ h => Or.inl h) + refine ⟨?_, coherent⟩ + rw [result] + exact readLocalExpr?_substSpec (depth := 0) (by simpa using bodyBound) + argBound bodyReads argReads + +private local instance : LawfulBEq FVarId where + eq_of_beq := by + intro left right equal + cases left + cases right + congr 1 + exact eq_of_beq equal + rfl {a} := by + cases a with + | mk x => show (x == x) = true; exact beq_self_eq_true x + +@[simp] private theorem readLocalExpr?_mkVar (resolve : Address → Option (ConstRef β)) + (values : LocalValues β) (index : UInt64) (name : Mode.anon.F Name) (depth : Nat) : + readLocalExpr? resolve values (KExpr.mkVar index name) depth = + if index.toNat < depth then some (.bvar index.toNat) else none := rfl + +theorem readLocalExpr?_abstractFVarsSpec + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {body : KExpr .anon} {source : VExpr β} {depth : UInt64} {fresh : FVarId} + (bound : depth.toNat + body.size + 1 < UInt64.size) + (reading : readLocalExpr? resolve (values.pushBinder fresh) body depth.toNat = some source) : + readLocalExpr? resolve values + (KExpr.abstractFVarsSpec body ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) + 1 depth) (depth.toNat + 1) = some source := by + induction body generalizing source depth with + | var index name info => + simp only [readLocalExpr?] at reading + split at reading + next inScope => + cases reading + have before : ¬ index ≥ depth := by + simp only [UInt64.le_iff_toNat_le]; omega + simp [KExpr.abstractFVarsSpec, before, readLocalExpr?, show index.toNat < + depth.toNat + 1 by omega] + · contradiction + | fvar id name info => + by_cases equal : id = fresh + · subst id + simp [readLocalExpr?, LocalValues.pushBinder, AExpr.erase, VExpr.liftN, liftVar] at reading + cases reading + simp [KExpr.abstractFVarsSpec] + · simp only [readLocalExpr?, LocalValues.pushBinder, equal, if_false, Option.map_map] at reading + obtain ⟨value, found, reading⟩ := Option.map_eq_some_iff.mp reading + cases reading + have combined : (value.erase.liftN 1).liftN depth.toNat = + value.erase.liftN (depth.toNat + 1) := by + rw [VExpr.liftN_combine (Nat.zero_le 0) (Nat.zero_le 1), Nat.add_comm] + simp [KExpr.abstractFVarsSpec, Ne.symm equal, + readLocalExpr?, found, AExpr.erase_liftN, combined] + | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => exact reading + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readLocalExpr?_let_parts reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyOut := hb (depth := depth + 1) (by rw [next]; omega) + (by simpa only [next] using bReads) + simp only [next] at bodyOut + simp [KExpr.abstractFVarsSpec, hA (by omega) aReads, + hv (by omega) vReads, bodyOut] + | app fn arg info hf ha => + rw [readLocalExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.abstractFVarsSpec, + hf (by omega) fReads, ha (by omega) aReads] + | lam name bi domain body info hd hb | all name bi domain body info hd hb => + rw [readLocalExpr?] at reading + obtain ⟨A, domainReads, reading⟩ := bind_success reading + obtain ⟨B, bodyReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + have next := depth_succ (depth := depth) (by omega) + have bodyBound : (depth + 1).toNat + body.size + 1 < UInt64.size := by + rw [next]; omega + have bodyReads' : readLocalExpr? resolve (values.pushBinder fresh) body (depth + 1).toNat = + some B := by simpa only [next] using bodyReads + have bodyOut : readLocalExpr? resolve values + (KExpr.abstractFVarsSpec body ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) + 1 (depth + 1)) (depth.toNat + 1 + 1) = some B := by + simpa only [next] using hb bodyBound bodyReads' + simp [KExpr.abstractFVarsSpec, hd (by omega) domainReads, bodyOut] + | prj id index value info ih => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, reading⟩ := bind_success reading + cases reading + simp only [KExpr.size] at bound + simp [KExpr.abstractFVarsSpec, resolved, + ih (by omega) valueReads] +theorem abstractFVars_readLocalExpr? + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {body : KExpr .anon} {fresh : FVarId} {source : VExpr β} + {table : InternTable .anon} + (constructed : body.Constructed) (bound : body.size + 1 < UInt64.size) + (coherent : table.WF) + (faithful : KExpr.CollisionFree fun term => table.ExprSupport term ∨ + KExpr.AbstractReach ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) 1 body 0 term) + (reading : readLocalExpr? resolve (values.pushBinder fresh) body = some source) : + readLocalExpr? resolve values (abstractFVars body #[fresh] table).1 1 = some source ∧ + (abstractFVars body #[fresh] table).2.WF := by + obtain ⟨result, coherent⟩ := abstractFVars_singleton_spec constructed (by omega) + faithful coherent (fun _ => Or.inl) (fun _ => Or.inr) + refine ⟨?_, coherent⟩ + rw [result] + exact readLocalExpr?_abstractFVarsSpec (by simpa using bound) reading + +theorem readLocalExpr?_readable {resolve : Address → Option (ConstRef β)} + {values more : LocalValues β} {term : KExpr .anon} {depth : Nat} {source : VExpr β} + (coverage : ∀ id value, values id = some value → ∃ value', more id = some value') + (reading : readLocalExpr? resolve values term depth = some source) : + ∃ source', readLocalExpr? resolve more term depth = some source' := by + induction term generalizing source depth with + | fvar id name info => + obtain ⟨value, found, _⟩ := Option.map_eq_some_iff.mp reading + obtain ⟨value', found'⟩ := coverage _ _ found + exact ⟨value'.erase.liftN depth, by simp [readLocalExpr?, found']⟩ + | var _ _ _ | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => exact ⟨source, reading⟩ + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readLocalExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, _⟩ := bind_success reading + obtain ⟨f', fReads'⟩ := hf fReads + obtain ⟨a', aReads'⟩ := ha aReads + simp [readLocalExpr?, fReads', aReads'] + | prj id index value info ih => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, _⟩ := bind_success reading + obtain ⟨value', valueReads'⟩ := ih valueReads + simp [readLocalExpr?, resolved, valueReads'] + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, _⟩ := readLocalExpr?_let_parts reading + obtain ⟨A', aReads'⟩ := hA aReads + obtain ⟨v', vReads'⟩ := hv vReads + obtain ⟨b', bReads'⟩ := hb bReads + simp [readLocalExpr?, aReads', vReads', bReads'] + +theorem readLocalExpr?_instantiateLocal {resolve : Address → Option (ConstRef β)} + {values : LocalValues β} {fresh : FVarId} {value : AExpr β} + {term : KExpr .anon} {depth : Nat} {source : VExpr β} + (reading : readLocalExpr? resolve (values.pushBinder fresh) term depth = some source) : + readLocalExpr? resolve (values.pushLet fresh value) term depth = + some (source.inst value.erase depth) := by + induction term generalizing source depth with + | var index name info => + simp only [readLocalExpr?] at reading ⊢ + split at reading + next bound => + cases reading + simp [bound, VExpr.inst, VExpr.instVar] + · contradiction + | fvar id name info => + by_cases equal : id = fresh + · subst id + simp [readLocalExpr?, LocalValues.pushBinder, AExpr.erase, VExpr.liftN, liftVar] at reading + cases reading + simp [readLocalExpr?, LocalValues.pushLet, VExpr.inst, VExpr.instVar] + · simp only [readLocalExpr?, LocalValues.pushBinder, equal, if_false, Option.map_map] at reading + obtain ⟨previous, found, reading⟩ := Option.map_eq_some_iff.mp reading + cases reading + simp only [readLocalExpr?, LocalValues.pushLet, equal, if_false, + found, Option.map_some, Function.comp_def, AExpr.erase_liftN] + congr 1 + rw [VExpr.liftN_combine (Nat.zero_le 0) (Nat.zero_le 1), Nat.add_comm 1 depth, + ← VExpr.liftN_combine (e := previous.erase) (n₁ := depth) (n₂ := 1) + (k₁ := 0) (k₂ := depth) (Nat.zero_le _) (by omega), VExpr.inst_liftN] + | sort _ _ | nat _ _ _ => cases reading; rfl + | const id levels info => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + cases reading + simp [readLocalExpr?, resolved, VExpr.inst] + | str value name info => + rw [readString?_inst reading] + exact reading + | app fn arg info hf ha | lam _ _ fn arg info hf ha | all _ _ fn arg info hf ha => + rw [readLocalExpr?] at reading + obtain ⟨f, fReads, reading⟩ := bind_success reading + obtain ⟨a, aReads, reading⟩ := bind_success reading + cases reading + simp [readLocalExpr?, hf fReads, ha aReads, VExpr.inst] + | prj id index value info ih => + rw [readLocalExpr?] at reading + obtain ⟨ref, resolved, reading⟩ := bind_success reading + obtain ⟨value, valueReads, reading⟩ := bind_success reading + cases reading + simp [readLocalExpr?, resolved, ih valueReads, VExpr.inst] + | letE name domain value body nonDep info hA hv hb => + obtain ⟨A, v, b, aReads, vReads, bReads, rfl⟩ := readLocalExpr?_let_parts reading + simp [readLocalExpr?, hA aReads, hv vReads, hb bReads, VExpr.inst0_inst_hi] + +theorem readLocalExpr?_letResidual {resolve : Address → Option (ConstRef β)} + {values : LocalValues β} {fresh : FVarId} {value : AExpr β} + {term : KExpr .anon} {depth : Nat} {source : VExpr β} + (reading : readLocalExpr? resolve (values.pushLet fresh value) term depth = some source) : + ∃ residual, readLocalExpr? resolve (values.pushBinder fresh) term depth = some residual ∧ + source = residual.inst value.erase depth := by + have coverage : ∀ id v, values.pushLet fresh value id = some v → + ∃ v', values.pushBinder fresh id = some v' := by + intro id v hit + by_cases equal : id = fresh + · subst id; simp [LocalValues.pushBinder] + · simp only [LocalValues.pushLet, equal, if_false] at hit + simp [LocalValues.pushBinder, equal, hit] + obtain ⟨residual, readResidual⟩ := readLocalExpr?_readable coverage reading + have instantiated := readLocalExpr?_instantiateLocal (value := value) readResidual + exact ⟨residual, readResidual, Option.some.inj (reading.symm.trans instantiated)⟩ + +theorem _root_.Ix.Kernel.KExpr.abstractFVarsSpec_size + (body : KExpr .anon) (pos : Std.HashMap FVarId UInt64) + (count depth : UInt64) : + (KExpr.abstractFVarsSpec body pos count depth).size = body.size := by + open KExpr in + induction body generalizing depth with + | var index name info => + simp only [abstractFVarsSpec] + split <;> rfl + | fvar id name info => + simp only [abstractFVarsSpec] + split <;> rfl + | app fn arg info hf ha => + change (abstractFVarsSpec fn pos count depth).size + + (abstractFVarsSpec arg pos count depth).size + 1 = _ + rw [hf, ha]; rfl + | lam name bi domain body info hA hb | all name bi domain body info hA hb => + change (abstractFVarsSpec domain pos count depth).size + + (abstractFVarsSpec body pos count (depth + 1)).size + 1 = _ + rw [hA, hb]; rfl + | letE name domain value body nonDep info hA hv hb => + change (abstractFVarsSpec domain pos count depth).size + + (abstractFVarsSpec value pos count depth).size + + (abstractFVarsSpec body pos count (depth + 1)).size + 1 = _ + rw [hA, hv, hb]; rfl + | prj id index value info ih => + change (abstractFVarsSpec value pos count depth).size + 1 = _ + rw [ih]; rfl + | sort _ _ | const _ _ _ | nat _ _ _ | str _ _ _ => rfl + +theorem closeLetType_readLocalExpr? + {resolve : Address → Option (ConstRef β)} {values : LocalValues β} + {body value : KExpr .anon} {fresh : FVarId} {e : AExpr β} {source : VExpr β} + {table : InternTable .anon} + (constructed : body.Constructed) (valueConstructed : value.Constructed) + (bound : body.lbr.toNat + body.size + 1 < UInt64.size) + (valueBound : value.size < UInt64.size) (coherent : table.WF) + (abstractFaithful : KExpr.CollisionFree fun term => table.ExprSupport term ∨ + KExpr.AbstractReach ((∅ : Std.HashMap FVarId UInt64).insert fresh 0) 1 body 0 term) + (substFaithful : + let abstracted := abstractFVars body #[fresh] table + KExpr.CollisionFree fun term => abstracted.2.ExprSupport term ∨ + KExpr.SubstReach value abstracted.1 0 term) + (reading : readLocalExpr? resolve (values.pushLet fresh e) body = some source) + (valueReads : readLocalExpr? resolve values value = some e.erase) : + let abstracted := abstractFVars body #[fresh] table + let result := subst abstracted.1 value 0 abstracted.2 + readLocalExpr? resolve values result.1 = some source ∧ result.2.WF := by + obtain ⟨residual, residualReads, rfl⟩ := readLocalExpr?_letResidual reading + have spec := (abstractFVars_singleton_spec constructed (by omega) + abstractFaithful coherent (fun _ => Or.inl) (fun _ => Or.inr)).1 + have readClosed := abstractFVars_readLocalExpr? constructed (by omega) + coherent abstractFaithful residualReads + have closedConstructed : (abstractFVars body #[fresh] table).1.Constructed := by + rw [spec] + apply constructed.abstractFVarsSpec + · intro id position found + simp only [Std.HashMap.getElem?_insert, Std.HashMap.getElem?_empty] at found + split at found + · cases found; decide + · contradiction + · simpa using bound + have closedBound : (abstractFVars body #[fresh] table).1.size + 1 < UInt64.size := by + rw [spec, KExpr.abstractFVarsSpec_size] + omega + exact subst_readLocalExpr? closedConstructed valueConstructed closedBound + valueBound readClosed.2 substFaithful readClosed.1 valueReads + +end Ix.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 1433627a9..6c35b426d 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -137,9 +137,19 @@ increasing sequence of strongly inaccessible cardinals. A let leaves the model context unchanged; a regular binder lifts older readings into the extended context. The production free-variable inference branch is typed by this invariant, and its zeta-reduction step preserves the - model value. General inference must still supply the let value's typing; - closing the returned type, general reduction, legacy local frames, and - semantic cache preservation remain separate obligations. + model value. The memoized abstraction-and-substitution sequence closes a + let body's inferred type with exactly its original model reading and + preserves intern-table coherence. The residual abstraction is derived from + that reading, including nested lets and other local values. General + inference must still supply the let value's typing; cheap beta, general + reduction, legacy local frames, and semantic cache preservation remain + separate obligations. +- `LetInferenceTrace.of_success` extracts the complete production let trace + in either validation mode, including computed sort exposure, conversion, + opening, recursive body inference, the deterministic closing sequence, and + final scope cleanup. It requires no precomputed execution tree. Under the + local-state and finite walker invariants, the trace transports the recursive + body's typing to the original let and its substituted type before cheap beta. - `InferenceCacheInvariant` covers every entry in both production maps, with separate full-checking and inference-only meanings. Hits obtain stored facts directly; each insertion establishes its own fact and preserves all other @@ -406,6 +416,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Finite intern support and production string expansion | [`Consistency/InternInvariant.lean`](../Ix/Kernel/Verify/Consistency/InternInvariant.lean), [`StringExpansion.lean`](../Ix/Kernel/Verify/Consistency/StringExpansion.lean), [`StringReading.lean`](../Ix/Kernel/Verify/Consistency/StringReading.lean) | | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Let-bound values, local allocation and shared context coherence | [`Consistency/LocalValues.lean`](../Ix/Kernel/Verify/Consistency/LocalValues.lean), [`LocalOpening.lean`](../Ix/Kernel/Verify/Consistency/LocalOpening.lean), [`Verify/LocalContext.lean`](../Ix/Kernel/Verify/LocalContext.lean), [`Model/ContextTransport.lean`](../Ix/Theory/Model/ContextTransport.lean) | +| Local substitution, let-inference traces and closing inferred types | [`Consistency/LocalSubstitution.lean`](../Ix/Kernel/Verify/Consistency/LocalSubstitution.lean), [`LetInference.lean`](../Ix/Kernel/Verify/Consistency/LetInference.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Safe definition self-reference and block dependency order | [`DefinitionOrder.lean`](../Ix/Kernel/DefinitionOrder.lean), [`Consistency/DefinitionOrder.lean`](../Ix/Kernel/Verify/Consistency/DefinitionOrder.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | From d315b4632e3a67a4cd238d16f89ea874ea9ea080 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 08:14:32 -0400 Subject: [PATCH 27/30] Preserve local scopes and state through general inference --- .../Check/UniverseInstantiationPolicy.lean | 259 +---------- Ix/Kernel/Verify/Consistency.lean | 13 + Ix/Kernel/Verify/Consistency/Audit.lean | 92 +++- .../Consistency/InferenceLocalState.lean | 404 ++++++++++++++++++ Ix/Kernel/Verify/Consistency/LocalScope.lean | 196 +++++++++ Ix/Kernel/Verify/Consistency/LocalState.lean | 282 ++++++++++++ Ix/Kernel/Verify/LocalScope.lean | 171 ++++++++ Ix/Kernel/Verify/UniverseInternOnly.lean | 319 ++++++++++++++ docs/kernel-verification.md | 15 + 9 files changed, 1497 insertions(+), 254 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/InferenceLocalState.lean create mode 100644 Ix/Kernel/Verify/Consistency/LocalScope.lean create mode 100644 Ix/Kernel/Verify/Consistency/LocalState.lean create mode 100644 Ix/Kernel/Verify/LocalScope.lean create mode 100644 Ix/Kernel/Verify/UniverseInternOnly.lean diff --git a/Ix/Kernel/Verify/Check/UniverseInstantiationPolicy.lean b/Ix/Kernel/Verify/Check/UniverseInstantiationPolicy.lean index 5fde07bc6..ef83c47a4 100644 --- a/Ix/Kernel/Verify/Check/UniverseInstantiationPolicy.lean +++ b/Ix/Kernel/Verify/Check/UniverseInstantiationPolicy.lean @@ -1,4 +1,5 @@ import Ix.Kernel.Verify.Check.InferencePolicy +import Ix.Kernel.Verify.UniverseInternOnly /-! # Inference-policy frame for universe instantiation @@ -9,10 +10,9 @@ but its operational noninterference fact does not: the walk can throw while substituting a universe, and otherwise changes only its private memo table and the kernel intern table. -This module proves that unconditional operational fact directly over the -production walker. It covers memo hits, every expression constructor, the -constant-universe array loop, recursive child failures, interning, and memo -writes on both outcomes. +The shared exact intern-table frame proves this operational fact for memo +hits, every expression constructor, the constant-universe array loop, +recursive child failures, interning, and memo writes on both outcomes. -/ namespace Ix.Kernel @@ -30,251 +30,14 @@ theorem map {x : TcM .anon alpha} (hx : x.PreservesInferOnly) rw [← bind_pure_comp] exact bind hx fun value => pure (f value) -private def StatePreservesInferOnly - (x : StateT sigma (TcM .anon) alpha) : Prop := - ∀ memo, (x.run memo).PreservesInferOnly - -private theorem statePure (value : alpha) : - StatePreservesInferOnly - (Pure.pure value : StateT sigma (TcM .anon) alpha) := by - intro memo - simp only [StateT.run_pure] - exact TcM.PreservesInferOnly.pure _ - -private theorem stateBind {x : StateT sigma (TcM .anon) alpha} - {f : alpha → StateT sigma (TcM .anon) beta} - (hx : StatePreservesInferOnly x) - (hf : ∀ value, StatePreservesInferOnly (f value)) : - StatePreservesInferOnly (x >>= f) := by - intro memo - simp only [StateT.run_bind] - apply TcM.PreservesInferOnly.bind (hx memo) - intro pair - exact hf pair.1 pair.2 - -private theorem stateGet : - StatePreservesInferOnly - (MonadState.get : StateT sigma (TcM .anon) sigma) := by - intro memo - simp only [StateT.run_get] - exact TcM.PreservesInferOnly.pure _ - -private theorem stateModify (f : sigma → sigma) : - StatePreservesInferOnly - (_root_.modify f : StateT sigma (TcM .anon) PUnit) := by - intro memo - simp only [StateT.run_modify] - exact TcM.PreservesInferOnly.pure _ - -private theorem stateLift {x : TcM .anon alpha} - (hx : x.PreservesInferOnly) : - StatePreservesInferOnly - (monadLift x : StateT sigma (TcM .anon) alpha) := by - intro memo - simp only [StateT.run_monadLift] - apply TcM.PreservesInferOnly.bind hx - intro value - exact TcM.PreservesInferOnly.pure _ - -private theorem stateForInArray - (items : Array alpha) (initial : beta) - (step : alpha → beta → - StateT sigma (TcM .anon) (ForInStep beta)) - (hstep : ∀ item state, - StatePreservesInferOnly (step item state)) : - StatePreservesInferOnly (forIn items initial step) := by - rcases items with ⟨items⟩ - simp only [List.forIn_toArray] - induction items generalizing initial with - | nil => - simp - exact statePure initial - | cons item rest ih => - rw [List.forIn_cons] - apply stateBind (hstep item initial) - intro action - cases action with - | done result => exact statePure result - | yield next => exact ih next - -private theorem stateInternMemo (key : Address) (result : KExpr .anon) : - StatePreservesInferOnly (do - let interned ← monadLift (TcM.intern result) - _root_.modify fun memo : Std.HashMap Address (KExpr .anon) => - memo.insert key interned - Pure.pure interned) := by - apply stateBind (stateLift (runIntern _)) - intro interned - apply stateBind (stateModify _) - intro _ - exact statePure interned - -/-- Universe instantiation cannot change the inference-policy bit. The -statement is unconditional because collision freedom is relevant to the -walker's semantic result, not to which `TcState` fields it can mutate. -/ -theorem instantiateUnivParams (e : KExpr .anon) - (us : Array (KUniv .anon)) : +/-- The exact intern-only frame supplies policy preservation on both +outcomes, without collision or semantic premises. -/ +theorem instantiateUnivParams (e : KExpr .anon) (us : Array (KUniv .anon)) : (TcM.instantiateUnivParams e us).PreservesInferOnly := by - unfold TcM.instantiateUnivParams - split - · exact pure e - · have hinner : ∀ (source : KExpr .anon), - StatePreservesInferOnly (TcM.instUnivInner source us) := by - intro source - induction source with - | var idx name info => - simp only [TcM.instUnivInner] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind (stateModify _) - intro _ - exact statePure (KExpr.var idx name info) - | fvar id name info => - simp only [TcM.instUnivInner] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind (stateModify _) - intro _ - exact statePure (KExpr.fvar id name info) - | sort u info => - simp only [TcM.instUnivInner] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind (stateLift (ofExcept (substUniv u us))) - intro resultUniv - apply stateBind (statePure (KExpr.mkSort resultUniv)) - intro result - exact stateInternMemo (KExpr.sort u info).addr result - | const id levels info => - rw [TcM.instUnivInner] - simp (config := { proj := false }) only [] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind - (stateForInArray levels (Array.mkEmpty levels.size) - (fun level current => do - let instantiated ← - monadLift (TcM.ofExcept (substUniv level us)) - let next := current.push instantiated - Pure.pure PUnit.unit - Pure.pure (ForInStep.yield next)) - (by - intro level current - apply stateBind - (stateLift (ofExcept (substUniv level us))) - intro instantiated - exact statePure - (ForInStep.yield (current.push instantiated)))) - intro newLevels - apply stateBind (statePure (KExpr.mkConst id newLevels)) - intro result - exact stateInternMemo (KExpr.const id levels info).addr result - | app f a info ihf iha => - rw [TcM.instUnivInner] - simp (config := { proj := false }) only [] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind ihf - intro resultF - apply stateBind iha - intro resultA - apply stateBind (statePure (KExpr.mkApp resultF resultA)) - intro result - exact stateInternMemo (KExpr.app f a info).addr result - | lam name bi ty body info ihty ihbody => - rw [TcM.instUnivInner] - simp (config := { proj := false }) only [] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind ihty - intro resultTy - apply stateBind ihbody - intro resultBody - apply stateBind - (statePure (KExpr.mkLam name bi resultTy resultBody)) - intro result - exact stateInternMemo (KExpr.lam name bi ty body info).addr result - | all name bi ty body info ihty ihbody => - rw [TcM.instUnivInner] - simp (config := { proj := false }) only [] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind ihty - intro resultTy - apply stateBind ihbody - intro resultBody - apply stateBind - (statePure (KExpr.mkAll name bi resultTy resultBody)) - intro result - exact stateInternMemo (KExpr.all name bi ty body info).addr result - | letE name ty value body nondep info ihty ihvalue ihbody => - rw [TcM.instUnivInner] - simp (config := { proj := false }) only [] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind ihty - intro resultTy - apply stateBind ihvalue - intro resultValue - apply stateBind ihbody - intro resultBody - apply stateBind - (statePure - (KExpr.mkLet name resultTy resultValue resultBody nondep)) - intro result - exact stateInternMemo - (KExpr.letE name ty value body nondep info).addr result - | prj id field value info ih => - rw [TcM.instUnivInner] - simp (config := { proj := false }) only [] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind ih - intro resultValue - apply stateBind - (statePure (KExpr.mkPrj id field resultValue)) - intro result - exact stateInternMemo (KExpr.prj id field value info).addr result - | nat value blob info => - simp only [TcM.instUnivInner] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind (stateModify _) - intro _ - exact statePure (KExpr.nat value blob info) - | str value blob info => - simp only [TcM.instUnivInner] - apply stateBind stateGet - intro memo - split - · exact statePure _ - · apply stateBind (stateModify _) - intro _ - exact statePure (KExpr.str value blob info) - have hrun := hinner e ({} : Std.HashMap Address (KExpr .anon)) - unfold StateT.run' - exact map hrun Prod.fst + intro before + have changed := TcM.InternOnly.instantiateUnivParams e us before + cases run : TcM.instantiateUnivParams e us before <;> rw [run] at changed <;> + obtain ⟨table, exactState⟩ := changed <;> rw [exactState] end TcM.PreservesInferOnly - end Ix.Kernel diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 7fc2f2804..4a475c854 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -21,6 +21,8 @@ import Ix.Kernel.Verify.Consistency.BinderOpening import Ix.Kernel.Verify.Consistency.LocalOpening import Ix.Kernel.Verify.Consistency.LocalSubstitution import Ix.Kernel.Verify.Consistency.LetInference +import Ix.Kernel.Verify.Consistency.LocalScope +import Ix.Kernel.Verify.Consistency.InferenceLocalState import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.RecursiveCache @@ -96,6 +98,17 @@ Successful let inference yields its full operational trace in both policies, including computed sort exposure and conversion. This trace transports the recursive body's typing to the original let and its substituted type before the final cheap-beta pass. +Fresh local extensions compose through nested scopes. Cleanup restores the +ordered declarations and every lookup on both success and failure, without +requiring equal hash-map representations. Let traces recover the modeled +context present after validation; the inference cache shell preserves caller +contexts whenever the uncached branch does. A maintained structural invariant +derives fresh opening from the counter bound. Every uncached constructor, +both cache partitions and the final write preserve it on success and failure, +under the recursive inference, reduction, conversion and projection contracts. +Universe instantiation unconditionally changes only the intern table. +The installed production loader must still establish counter preservation; +the general mutual proof must supply the recursive and semantic contracts. The safe-definition guard excludes self-reference for both modes and arbitrary universe arities. Successful definition-block execution computes an order of diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 5fe044e67..2614c04f6 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -13,6 +13,8 @@ import Ix.Kernel.Verify.Consistency.DefinitionOrder import Ix.Kernel.Verify.Consistency.LocalOpening import Ix.Kernel.Verify.Consistency.LocalSubstitution import Ix.Kernel.Verify.Consistency.LetInference +import Ix.Kernel.Verify.Consistency.LocalScope +import Ix.Kernel.Verify.Consistency.InferenceLocalState import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -51,6 +53,7 @@ private def atomicRoots : Array Lean.Name := #[ ``ForallInferenceTrace.output, ``LambdaInferenceTrace.output, ``BinderInference.sound, ``inferUncached_monomorphic_const_scoped, ``ApplicationInferenceTrace.output, ``LetInferenceTrace.of_success, ``LetInferenceTrace.beforeBeta_typing, + ``LetInferenceTrace.restores, ``infer_localContext, ``BinderInference.soundWithSynthesis, ``BinderInference.synthesis, ``DefinitionBodySupport.sound ] @@ -207,7 +210,12 @@ private def binderWalkerRoots : Array Lean.Name := #[ ``openLet_local_sound, ``openBinder_local_sound, ``readLocalExpr?_liftSpec, ``readLocalExpr?_substSpec, ``subst_readLocalExpr?, ``readLocalExpr?_abstractFVarsSpec, ``abstractFVars_readLocalExpr?, - ``KExpr.abstractFVarsSpec_size, ``closeLetType_readLocalExpr? + ``KExpr.abstractFVarsSpec_size, ``closeLetType_readLocalExpr?, + ``LocalContext.Equiv.truncate, ``LocalContext.truncate_push, + ``LocalContext.truncate_push_le, ``LocalContext.Extension.restore, + ``withLctxScope_restores, ``withLctxScope_error_restores, + ``openLet_extends, ``openBinder_extends, + ``PreservesLocalExtension.inferKey, ``PreservesLocalExtension.withLctxScope ] private def localValueRoots : Array Lean.Name := #[ @@ -217,7 +225,79 @@ private def localValueRoots : Array Lean.Name := #[ ``LocalContextValues.index_none, ``LocalContextValues.pushLet, ``LocalContextValues.pushBinder, ``LocalModelTyping.closed, ``readLocalExpr?_readable, ``readLocalExpr?_instantiateLocal, - ``readLocalExpr?_letResidual + ``readLocalExpr?_letResidual, ``LocalContext.Equiv.push, ``LocalContextValues.congr +] + +private def localScopeFrameRoots : Array Lean.Name := #[ + ``LocalContext.Equiv.refl, ``LocalContext.Equiv.symm, ``LocalContext.Equiv.trans, + ``LocalContext.Equiv.size, ``LocalContext.Equiv.find?, ``LocalContext.Equiv.wf, + ``LocalContext.Extension.trans, ``LocalContext.Extension.size_le, + ``PreservesLocalExtension.pure, ``PreservesLocalExtension.throw, + ``PreservesLocalExtension.bind, ``PreservesLocalExtension.runIntern, + ``PreservesLocalExtension.withInferOnly +] + +private def localStateFrameRoots : Array Lean.Name := #[ + ``TcM.InternOnly.pure, + ``TcM.InternOnly.throw, + ``TcM.InternOnly.bind, + ``TcM.InternOnly.runIntern, + ``TcM.InternOnly.ofExcept, + ``TcM.InternOnly.map, + ``LocalContext.IdsBelow.mono, + ``LocalContext.IdsBelow.equiv, + ``LocalContext.IdsBelow.fresh, + ``LocalStateFrame.refl, + ``LocalStateFrame.trans, + ``LocalStateFrame.invariant, + ``LocalStateExtension.refl, + ``LocalStateExtension.trans, + ``LocalStateExtension.of_frame, + ``FramesLocalState.preserves, + ``FramesLocalState.pure, + ``FramesLocalState.throw, + ``FramesLocalState.runIntern, + ``FramesLocalState.of_internOnly, + ``FramesLocalState.bind, + ``PreservesLocalState.bind, + ``FramesLocalState.get, + ``FramesLocalState.modify, + ``FramesLocalState.intern, + ``FramesLocalState.withInferOnly, + ``FramesLocalState.cacheInferResult, + ``FramesLocalState.isEagerReduce, + ``FramesLocalState.prims, + ``FramesLocalState.lazyIngressAddr, + ``FramesLocalState.tryGetConst, + ``FramesLocalState.getConst +] + +private def localStateMapRoots : Array Lean.Name := #[ + ``LocalContext.IdsBelow.empty, + ``LocalContext.IdsBelow.push, + ``LocalStateInvariant.ofValues +] + +private def localStateWalkerRoots : Array Lean.Name := #[ + ``LocalStateExtension.restore, + ``PreservesLocalState.withLctxScope, + ``PreservesLocalState.openLet, + ``PreservesLocalState.openBinder, + ``FramesLocalState.ctxAddrForLbr, + ``FramesLocalState.inferKey, + ``FramesLocalState.lookupVar +] + +private def localStateOperationalRoots : Array Lean.Name := #[ + ``TcM.InternOnly.instantiateUnivParams, + ``FramesLocalState.instantiateUnivParams, + ``FramesLocalState.ensureSortWhnf, + ``FramesLocalState.ensureSortDirect, + ``FramesLocalState.ensureForallWhnf, + ``FramesLocalState.ensureForallDirect, + ``inferUncached_framesLocalState, + ``FramesLocalState.inferWith, + ``infer_framesLocalState ] /-- Production roots must not acquire a checker-soundness assumption @@ -300,19 +380,19 @@ def roots : Array RootAllowance := #[ ] ++ (stringListRoots ++ #[``LocalValues.pushLet_extends, ``LocalValues.pushBinder_lifts, ``LocalValues.Below.pushLet]).map (fun root => { root, standardAxioms := #[``propext], forbiddenDependencies := forbiddenProduction -}) ++ (localIndexRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ +}) ++ (localIndexRoots ++ localScopeFrameRoots ++ localStateFrameRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ internFrameRoots ++ #[``DefinitionOrder.ready_independent, ``DefinitionOrder.order?_sound, ``DefinitionOrder.member_of_read, ``LocalValues.Below.pushBinder]).map (fun root => { root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction -}) ++ (contextRoots ++ localValueRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ +}) ++ (contextRoots ++ localValueRoots ++ localStateMapRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ internMapRoots ++ #[``DefinitionOrder.order?_rank, ``DefinitionOrder.acyclic_rank]).map (fun root => { root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction -}) ++ (binderWalkerRoots ++ cacheKeyRoots ++ cacheInvariantKeyRoots ++ stringExpansionRoots).map (fun root => { +}) ++ (binderWalkerRoots ++ localStateWalkerRoots ++ cacheKeyRoots ++ cacheInvariantKeyRoots ++ stringExpansionRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative], forbiddenDependencies := forbiddenProduction -}) ++ (atomicRoots ++ instantiationRoots ++ recursiveCacheRoots ++ +}) ++ (atomicRoots ++ localStateOperationalRoots ++ instantiationRoots ++ recursiveCacheRoots ++ #[``InferenceCacheInvariant.infer]).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], forbiddenDependencies := forbiddenProduction diff --git a/Ix/Kernel/Verify/Consistency/InferenceLocalState.lean b/Ix/Kernel/Verify/Consistency/InferenceLocalState.lean new file mode 100644 index 000000000..04f9a9b0b --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/InferenceLocalState.lean @@ -0,0 +1,404 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalState + +/-! +# Local-state preservation by general inference + +Every uncached constructor and both inference-cache partitions preserve +caller locals and the allocation-counter bound, including partial failures. +Scope bodies may append fresh declarations; actual cleanup restores the +incoming context. Universe instantiation changes only the intern table, and +constant lookup uses the maintained loader-counter contract. + +Recursive inference, reduction, conversion and projection remain contracts +of the mutual execution proof. These structural effects do not assert the +semantic validity of computed or cached types. The production ingress +loader must separately establish its counter contract. +-/ + +namespace Ix.Kernel.Consistency +namespace FramesLocalState + +theorem get : FramesLocalState (get : TcM .anon (TcState .anon)) := fun _ _ => .refl _ + +theorem modify (f : TcState .anon → TcState .anon) + (frame : ∀ before, LocalStateFrame before (f before)) : + FramesLocalState (modify f : TcM .anon PUnit) := fun before _ => frame before + +theorem intern (term : KExpr .anon) : FramesLocalState (TcM.intern term) := + runIntern (internExprM term) + +theorem withInferOnly {action : TcM .anon α} (body : FramesLocalState action) : + FramesLocalState (TcM.withInferOnly action) := by + intro before valid + rw [withInferOnly_eq] + have inner := body {before with inferOnly := true} + ⟨valid.coherent, valid.allocated, valid.loader⟩ + cases run : action {before with inferOnly := true} <;> + rw [run] at inner <;> exact ⟨inner.counter, inner.context, inner.loader⟩ + +theorem ctxAddrForLbr (lbr : UInt64) : FramesLocalState (TcM.ctxAddrForLbr (m := .anon) lbr) := by + unfold TcM.ctxAddrForLbr + apply bind get + intro state + split + · exact pure _ + · dsimp only + split + · exact pure _ + · apply bind (modify + (fun later => {later with ctxAddrCache := + (later.ctxAddrCache.insert (state.ctxId, lbr) (TcM.ctxAddrForLbrUncached state lbr))}) + (fun _ => ⟨Nat.le_refl _, .refl _, rfl⟩)) + intro _ + exact pure _ + +theorem inferKey (term : KExpr .anon) : FramesLocalState (TcM.inferKey term) := + bind (ctxAddrForLbr term.lbr) (fun _ => pure _) + +theorem cacheInferResult (inferOnly : Bool) (key : Address × Address) (type : KExpr .anon) + (methods : Methods .anon) : + FramesLocalState ((RecM.cacheInferResult inferOnly key type).run methods) := by + intro before _ + simp only [ReaderT.run, cacheInferResult_eq] + cases inferOnly <;> exact ⟨Nat.le_refl _, .refl _, rfl⟩ + +theorem lookupVar (index : UInt64) : FramesLocalState (TcM.lookupVar (m := .anon) index) := by + unfold TcM.lookupVar + apply bind get + intro state + dsimp only + split + · exact throw _ + · exact runIntern _ + +theorem isEagerReduce (term : KExpr .anon) : FramesLocalState (TcM.isEagerReduce term) := by + unfold TcM.isEagerReduce + generalize term.collectSpine = pair + rcases pair with ⟨head, args⟩ + dsimp only + split + · exact pure _ + · split + · apply bind get + intro state + exact pure _ + · exact pure _ + +theorem prims (methods : Methods .anon) : FramesLocalState ((RecM.prims (m := .anon)).run methods) := by + unfold RecM.prims + simp only [ReaderT.run_bind] + exact bind get (fun _ => pure _) + +theorem lazyIngressAddr (addr : Address) : FramesLocalState (TcM.lazyIngressAddr (m := .anon) addr) := by + intro before valid + unfold TcM.lazyIngressAddr + cases loader : before.lazyFault with + | none => exact .refl _ + | some fault => + dsimp only + by_cases already : before.faultedAddrs.contains addr = true + · rw [if_pos already]; exact .refl _ + · rw [if_neg already] + have counter := valid.loader fault loader addr before.env + cases run : fault addr before.env <;> rw [run] at counter <;> + exact ⟨counter, .refl _, loader.symm⟩ + +theorem tryGetConst (id : KId .anon) : FramesLocalState (TcM.tryGetConst id) := by + unfold TcM.tryGetConst + apply bind get + intro state + cases found : state.env.get? id with + | some constant => exact pure _ + | none => + apply bind get + intro checked + apply bind (lazyIngressAddr id.addr) + intro _ + apply bind get + intro loaded + cases found : loaded.env.get? id with + | some constant => exact pure _ + | none => + cases checked.lazyFault.isSome + · exact pure _ + · exact throw _ + +theorem getConst (id : KId .anon) : FramesLocalState (TcM.getConst id) := by + unfold TcM.getConst + apply bind (tryGetConst id) + intro result + cases result + · exact throw _ + · exact pure _ + +theorem ensureSortWhnf {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) (type : KExpr .anon) : + FramesLocalState ((RecM.ensureSortWhnf type).run methods) := by + unfold RecM.ensureSortWhnf + simp only [ReaderT.run_bind] + apply bind (whnf type) + intro result + cases result <;> first | exact pure _ | exact throw _ + +theorem ensureSortDirect {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) (type : KExpr .anon) : + FramesLocalState ((RecM.ensureSortDirect type).run methods) := by + cases type <;> simp only [RecM.ensureSortDirect] + all_goals first | exact pure _ | exact ensureSortWhnf whnf _ + +theorem ensureForallWhnf {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) (type : KExpr .anon) : + FramesLocalState ((RecM.ensureForallWhnf type).run methods) := by + unfold RecM.ensureForallWhnf + simp only [ReaderT.run_bind] + apply bind (whnf type) + intro result + cases result <;> first | exact pure _ | exact throw _ + +theorem ensureForallDirect {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) (type : KExpr .anon) : + FramesLocalState ((RecM.ensureForallDirect type).run methods) := by + cases type <;> simp only [RecM.ensureForallDirect] + all_goals first | exact pure _ | exact ensureForallWhnf whnf _ + +end FramesLocalState + +/-- Every uncached inference branch restores caller locals under the local +state contracts of its recursive calls and lookup/projection helpers. -/ +theorem inferUncached_framesLocalState + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {methods : Methods .anon} + (recursive : ∀ term, FramesLocalState ((inferRec term).run methods)) + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (conversion : ∀ left right, FramesLocalState ((RecM.isDefEqCall left right).run methods)) + (projection : ∀ id field major type, + FramesLocalState ((RecM.inferProj id field major type).run methods)) + (inferOnly : Bool) (term : KExpr .anon) : + FramesLocalState ((RecM.inferUncached inferRec inferOnly term).run methods) := by + cases term with + | var index name info => simpa [RecM.inferUncached] using FramesLocalState.lookupVar index + | fvar id name info => + unfold RecM.inferUncached + simp only [ReaderT.run_bind] + apply FramesLocalState.bind FramesLocalState.get + intro state + split + · exact FramesLocalState.pure _ + · exact FramesLocalState.throw _ + | sort level info => + simpa [RecM.inferUncached, TcM.intern] using + FramesLocalState.runIntern (internExprM (KExpr.mkSort (KUniv.mkSucc level))) + | const id levels info => + unfold RecM.inferUncached + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply FramesLocalState.bind (FramesLocalState.getConst id) + intro constant + split + · exact FramesLocalState.throw _ + · exact FramesLocalState.instantiateUnivParams constant.ty levels + | nat value raw info => + unfold RecM.inferUncached + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply FramesLocalState.bind (FramesLocalState.prims methods) + intro primitives + simpa using FramesLocalState.intern (.mkConst primitives.nat #[]) + | str value raw info => + unfold RecM.inferUncached + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply FramesLocalState.bind (FramesLocalState.prims methods) + intro primitives + simpa using FramesLocalState.intern (.mkConst primitives.string #[]) + | prj id field major info => + unfold RecM.inferUncached + simp only [ReaderT.run_bind] + exact FramesLocalState.bind (recursive major) (projection id field major) + | app function argument info => + unfold RecM.inferUncached + simp only [ReaderT.run_bind] + apply FramesLocalState.bind (recursive function) + intro functionType + apply FramesLocalState.bind (FramesLocalState.ensureForallDirect whnf functionType) + intro pair + rcases pair with ⟨domain, codomain⟩ + cases inferOnly with + | true => exact FramesLocalState.runIntern _ + | false => + apply FramesLocalState.bind (recursive argument) + intro argumentType + apply FramesLocalState.bind (FramesLocalState.isEagerReduce argument) + intro eager + cases eager with + | false => + simp only [Bool.false_eq_true, if_false] + apply FramesLocalState.bind (conversion argumentType domain) + intro equal + cases equal with + | true => exact FramesLocalState.runIntern _ + | false => + apply FramesLocalState.bind FramesLocalState.get + intro state + intro before valid + exact .refl _ + | true => + simp only [if_true] + change FramesLocalState ((do + modify fun state : TcState .anon => {state with eagerReduce := true} + let equal ← RecM.isDefEqCall argumentType domain + modify fun state : TcState .anon => {state with eagerReduce := false} + if !equal then + throw (.appTypeMismatch argumentType domain (← get).ctx.size) + TcM.runIntern (subst codomain argument 0) : + RecM .anon (KExpr .anon)).run methods) + simp only [ReaderT.run_bind] + apply FramesLocalState.bind (FramesLocalState.modify + (fun state => {state with eagerReduce := true}) (fun _ => ⟨Nat.le_refl _, .refl _, rfl⟩)) + intro _ + apply FramesLocalState.bind (conversion argumentType domain) + intro equal + apply FramesLocalState.bind (FramesLocalState.modify + (fun state => {state with eagerReduce := false}) (fun _ => ⟨Nat.le_refl _, .refl _, rfl⟩)) + intro _ + cases equal with + | true => exact FramesLocalState.runIntern _ + | false => + apply FramesLocalState.bind FramesLocalState.get + intro state + intro before valid + exact .refl _ + | lam name bi domain body info => + unfold RecM.inferUncached + have scope : FramesLocalState ((RecM.withLctxScope (m := .anon) do + let (opened, fresh) ← TcM.openBinder name bi domain body + let bodyType ← inferRec opened + let reduced ← TcM.runIntern (cheapBetaReduce bodyType) + let abstracted ← TcM.runIntern (abstractFVars reduced #[fresh]) + TcM.intern (.mkAll RecM.anonN RecM.anonBi domain abstracted)).run methods) := by + apply PreservesLocalState.withLctxScope + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply PreservesLocalState.bind (PreservesLocalState.openBinder name bi domain body) + intro pair + rcases pair with ⟨opened, fresh⟩ + apply PreservesLocalState.bind (recursive opened).preserves + intro bodyType + apply PreservesLocalState.bind (FramesLocalState.runIntern _).preserves + intro reduced + apply PreservesLocalState.bind (FramesLocalState.runIntern _).preserves + intro abstracted + simpa using (FramesLocalState.intern (.mkAll RecM.anonN RecM.anonBi domain abstracted)).preserves + cases inferOnly with + | true => exact scope + | false => + simp only [Bool.not_false, if_true, ReaderT.run_bind] + exact FramesLocalState.bind (recursive domain) fun domainType => + FramesLocalState.bind (FramesLocalState.ensureSortDirect whnf domainType) fun _ => scope + | all name bi domain body info => + unfold RecM.inferUncached + simp only [ReaderT.run_bind] + apply FramesLocalState.bind (recursive domain) + intro domainType + apply FramesLocalState.bind (FramesLocalState.ensureSortDirect whnf domainType) + intro domainLevel + apply PreservesLocalState.withLctxScope + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply PreservesLocalState.bind (PreservesLocalState.openBinder name bi domain body) + intro pair + rcases pair with ⟨opened, fresh⟩ + apply PreservesLocalState.bind (recursive opened).preserves + intro bodyType + apply PreservesLocalState.bind (FramesLocalState.ensureSortDirect whnf bodyType).preserves + intro bodyLevel + simpa using (FramesLocalState.intern (.mkSort (.mkIMax domainLevel bodyLevel))).preserves + | letE name domain value body nonDep info => + unfold RecM.inferUncached + have scope : FramesLocalState ((RecM.withLctxScope (m := .anon) do + let (opened, fresh) ← TcM.openLet name domain value body + let bodyType ← inferRec opened + let abstracted ← TcM.runIntern (abstractFVars bodyType #[fresh]) + let substituted ← TcM.runIntern (subst abstracted value 0) + TcM.runIntern (cheapBetaReduce substituted)).run methods) := by + apply PreservesLocalState.withLctxScope + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply PreservesLocalState.bind (PreservesLocalState.openLet name domain value body) + intro pair + rcases pair with ⟨opened, fresh⟩ + apply PreservesLocalState.bind (recursive opened).preserves + intro bodyType + apply PreservesLocalState.bind (FramesLocalState.runIntern _).preserves + intro abstracted + apply PreservesLocalState.bind (FramesLocalState.runIntern _).preserves + intro substituted + exact (FramesLocalState.runIntern _).preserves + cases inferOnly with + | true => exact scope + | false => + simp only [Bool.not_false, if_true, ReaderT.run_bind] + apply FramesLocalState.bind (recursive domain) + intro domainType + apply FramesLocalState.bind (FramesLocalState.ensureSortDirect whnf domainType) + intro level + apply FramesLocalState.bind (recursive value) + intro valueType + apply FramesLocalState.bind (conversion valueType domain) + intro equal + cases equal with + | true => exact scope + | false => exact FramesLocalState.throw _ + +namespace FramesLocalState + +/-- Both cache partitions and the actual outer write preserve the local +frame of the uncached action. The statement also covers failed inference. -/ +theorem inferWith {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} + {methods : Methods .anon} (term : KExpr .anon) + (uncached : ∀ inferOnly, + FramesLocalState ((RecM.inferUncached inferRec inferOnly term).run methods)) : + FramesLocalState ((RecM.inferWith inferRec term).run methods) := by + unfold RecM.inferWith + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply bind get + intro state + apply bind (inferKey term) + intro key + apply bind get + intro checked + split + · exact pure _ + · have miss : FramesLocalState ((do + let type ← RecM.inferUncached inferRec state.inferOnly term + RecM.cacheInferResult state.inferOnly key type + Pure.pure type).run methods) := by + simp only [ReaderT.run_bind] + exact bind (uncached state.inferOnly) fun type => + bind (cacheInferResult state.inferOnly key type methods) fun _ => pure type + split + · simp only [ReaderT.run_bind] + apply bind get + intro checkedOnly + split + · exact pure _ + · exact miss + · exact miss + +end FramesLocalState + +/-- The production one-layer inference body restores locals and maintains +the allocation bound in both policies, including hits and partial errors. +Only recursive inference, reduction, conversion and projection contracts +remain for the mutual execution proof. -/ +theorem infer_framesLocalState {methods : Methods .anon} + (recursive : ∀ term, FramesLocalState (methods.infer term)) + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (conversion : ∀ left right, FramesLocalState ((RecM.isDefEqCall left right).run methods)) + (projection : ∀ id field major type, + FramesLocalState ((RecM.inferProj id field major type).run methods)) + (term : KExpr .anon) : FramesLocalState ((RecM.infer term).run methods) := + FramesLocalState.inferWith term fun inferOnly => + inferUncached_framesLocalState (inferRec := RecM.inferCall) (methods := methods) + recursive whnf conversion projection inferOnly term + +end Ix.Kernel.Consistency + diff --git a/Ix/Kernel/Verify/Consistency/LocalScope.lean b/Ix/Kernel/Verify/Consistency/LocalScope.lean new file mode 100644 index 000000000..a83224b34 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LocalScope.lean @@ -0,0 +1,196 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.LocalScope +import Ix.Kernel.Verify.Consistency.LetInference +import Ix.Kernel.Verify.Consistency.CacheInvariant + +/-! +# Restoring model locals at production scope boundaries + +Actual scope cleanup restores every caller lookup after a body that only +extends the local context, on both success and failure. Let inference uses +this fact to restore the modeled context present after value validation. +The recursive execution proof must establish the body extension invariant. +-/ + +namespace Ix.Kernel.Consistency +open Theory Theory.Model +universe u v + +/-- Observable context restoration transports the semantic invariant. -/ +theorem LocalContextValues.congr {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} {context : Model.Context β} + {left right : LocalContext .anon} + (agreement : LocalContextValues.{u,v} resolve entries values left context) + (same : LocalContext.Equiv left right) : + LocalContextValues.{u,v} resolve entries values right context := by + refine ⟨same.wf agreement.coherent, ?_, ?_⟩ + · intro id decl found + exact agreement.complete id decl ((same.find? id).trans found) + · intro id value found + obtain ⟨decl, A, hit, typeRead, typed, valueRead⟩ := agreement.lookup id value found + exact ⟨decl, A, (same.find? id).symm.trans hit, typeRead, typed, valueRead⟩ + +/-- Actual scope cleanup restores the incoming context after an arbitrary +successful body which only extended its local declarations. -/ +theorem withLctxScope_restores {action : RecM .anon α} {methods : Methods .anon} + {before after : TcState .anon} {result : α} + (extended : ∀ state, action.run methods before = .ok result state → + before.lctx.Extension state.lctx) + (run : (RecM.withLctxScope action).run methods before = .ok result after) : + after.lctx.Equiv before.lctx := by + rw [withLctxScope_eq] at run + cases bodyRun : action.run methods before with + | error error state => rw [bodyRun] at run; contradiction + | ok value state => + rw [bodyRun] at run + cases run + exact (extended state bodyRun).restore + +/-- The same restoration applies to the partial state returned on failure. -/ +theorem withLctxScope_error_restores {action : RecM .anon α} {methods : Methods .anon} + {before after : TcState .anon} {error : TcError .anon} + (extended : ∀ state, action.run methods before = .error error state → + before.lctx.Extension state.lctx) + (run : (RecM.withLctxScope action).run methods before = .error error after) : + after.lctx.Equiv before.lctx := by + rw [withLctxScope_eq] at run + cases bodyRun : action.run methods before with + | ok value state => rw [bodyRun] at run; contradiction + | error failure state => + rw [bodyRun] at run + cases run + exact (extended state bodyRun).restore + +theorem openLet_extends {name : Mode.anon.F Name} {type value body opened : KExpr .anon} + {fresh : FVarId} {before after : TcState .anon} + (absent : before.lctx.index[(⟨before.env.nextFVarId⟩ : FVarId)]? = none) + (run : TcM.openLet name type value body before = .ok (opened, fresh) after) : + before.lctx.Extension after.lctx := by + rw [openLet_eq] at run + split at run + · cases run; exact .push _ (.refl _) absent + · contradiction + +theorem openBinder_extends {name : Mode.anon.F Name} {bi : Mode.anon.F Lean.BinderInfo} + {type body opened : KExpr .anon} {fresh : FVarId} {before after : TcState .anon} + (absent : before.lctx.index[(⟨before.env.nextFVarId⟩ : FVarId)]? = none) + (run : TcM.openBinder name bi type body before = .ok (opened, fresh) after) : + before.lctx.Extension after.lctx := by + rw [openBinder_eq] at run + split at run + · cases run; exact .push _ (.refl _) absent + · contradiction + +/-- Let inference restores the context present after value validation. The +body's local-extension premise is the recursive execution invariant. -/ +theorem LetInferenceTrace.restores {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} {context : Model.Context β} + {inferRec : KExpr .anon → RecM .anon (KExpr .anon)} {methods : Methods .anon} + {inferOnly : Bool} {name : Mode.anon.F Name} {type value body result : KExpr .anon} + {before after : TcState .anon} + (trace : LetInferenceTrace inferRec methods inferOnly name type value body before result after) + (agreement : LocalContextValues.{u,v} resolve entries values trace.validated.lctx context) + (below : values.Below trace.validated.env.nextFVarId) + (extended : trace.openedState.lctx.Extension trace.bodyState.lctx) : + after.lctx.Equiv trace.validated.lctx ∧ + LocalContextValues.{u,v} resolve entries values after.lctx context := by + have opened := openLet_extends (agreement.index_none below.absent) trace.openRun + have restored : after.lctx.Equiv trace.validated.lctx := by + rw [show after.lctx = trace.bodyState.lctx.truncate trace.validated.lctx.size from + congrArg TcState.lctx trace.stateEq] + exact (opened.trans extended).restore + exact ⟨restored, agreement.congr restored.symm⟩ + +/-- Neither successful nor failed execution removes or changes an incoming +local declaration. Extra fresh declarations are restored by enclosing scopes. -/ +def PreservesLocalExtension (action : TcM .anon α) : Prop := + ∀ before, match action before with + | .ok _ after | .error _ after => before.lctx.Extension after.lctx + +namespace PreservesLocalExtension + +theorem pure (value : α) : PreservesLocalExtension (Pure.pure value) := fun _ => .refl _ + +theorem throw (error : TcError .anon) : + PreservesLocalExtension (throw error : TcM .anon α) := fun _ => .refl _ + +theorem bind {action : TcM .anon α} {next : α → TcM .anon γ} + (first : PreservesLocalExtension action) + (rest : ∀ value, PreservesLocalExtension (next value)) : + PreservesLocalExtension (action >>= next) := by + intro before + have intermediate := first before + change match EStateM.bind action next before with + | .ok _ after | .error _ after => before.lctx.Extension after.lctx + cases run : action before with + | error error after => + rw [EStateM.bind, run] + simpa only [run] using intermediate + | ok value after => + rw [run] at intermediate + rw [EStateM.bind, run] + dsimp only + have final := rest value after + cases finished : next value after <;> + rw [finished] at final <;> exact intermediate.trans final + +theorem runIntern (action : InternM .anon α) : + PreservesLocalExtension (TcM.runIntern action) := fun _ => .refl _ + +theorem inferKey (term : KExpr .anon) : PreservesLocalExtension (TcM.inferKey term) := by + intro before + obtain ⟨key, keyed, run⟩ := inferKey_total term before + rw [run] + change before.lctx.Extension keyed.lctx + rw [inferKey_lctx run] + exact .refl _ + +theorem withInferOnly {action : TcM .anon α} (body : PreservesLocalExtension action) : + PreservesLocalExtension (TcM.withInferOnly action) := by + intro before + rw [withInferOnly_eq] + have inner := body {before with inferOnly := true} + cases run : action {before with inferOnly := true} <;> + simpa only [run] using inner + +theorem withLctxScope {action : RecM .anon α} {methods : Methods .anon} + (body : PreservesLocalExtension (action.run methods)) : + PreservesLocalExtension ((RecM.withLctxScope action).run methods) := by + intro before + rw [withLctxScope_eq] + have inner := body before + cases run : action.run methods before <;> rw [run] at inner <;> + exact .equiv (.refl _) inner.restore.symm + +end PreservesLocalExtension + +/-- The actual inference cache shell preserves the caller's local context +whenever its uncached branch does. Both eligible partitions and the outer +write are handled directly from execution. -/ +theorem infer_localContext + {before after : TcState .anon} {term result : KExpr .anon} {methods : Methods .anon} + (uncached : ∀ key keyed type finished, + TcM.inferKey term before = .ok key keyed → + RecM.inferUncached RecM.inferCall before.inferOnly term methods keyed = + .ok type finished → + finished.lctx.Equiv keyed.lctx) + (run : RecM.infer term methods before = .ok result after) : + after.lctx.Equiv before.lctx := by + obtain ⟨key, keyed, keyRun⟩ := inferKey_total term before + rcases observeInferenceCache keyRun with ⟨hit, _, _⟩ | ⟨miss, _, _⟩ + · rw [hit.run methods] at run + cases run + rw [inferKey_lctx hit.keyRun] + exact .refl _ + · obtain ⟨finished, bodyRun, written⟩ := infer_uncached_success_state miss run + have bodySame := uncached miss.key miss.keyed result finished miss.keyRun bodyRun + have same : after.lctx = finished.lctx := by + rw [written] + cases before.inferOnly <;> rfl + simpa only [same, miss.localContext] using bodySame + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/LocalState.lean b/Ix/Kernel/Verify/Consistency/LocalState.lean new file mode 100644 index 000000000..57e90e0ab --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LocalState.lean @@ -0,0 +1,282 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalScope +import Ix.Kernel.Verify.UniverseInternOnly + +/-! +# Maintained structural local state + +Coherent lookups and the allocation-counter bound justify freshness at each +actual binder opening. The installed lazy loader must preserve that bound +by never rewinding the counter. Interning preserves the state; successful opening +extends it under the production overflow guard; scope cleanup restores the +caller context while retaining the larger allocation counter. The same +contracts cover partial failure states and compose through monadic binds. + +This is the structural local component of the general semantic state +invariant. It does not establish inference, reduction or cache meaning. +-/ + +namespace Ix.Kernel.LocalContext + +private local instance : LawfulBEq FVarId where + eq_of_beq := by + intro left right equal + cases left + cases right + congr 1 + exact eq_of_beq equal + rfl {a} := by + cases a with + | mk x => show (x == x) = true; exact beq_self_eq_true x + +/-- Every indexed local was allocated before the actual next identifier. -/ +def IdsBelow (context : LocalContext m) (next : UInt64) : Prop := + ∀ (id : FVarId) (position : Nat), context.index[id]? = some position → + id.id.toNat < next.toNat + +namespace IdsBelow + +theorem empty (next : UInt64) : IdsBelow ({} : LocalContext m) next := by + intro id position found + simp at found + +theorem mono {context : LocalContext m} {next later : UInt64} + (bound : context.IdsBelow next) (order : next.toNat ≤ later.toNat) : context.IdsBelow later := by + intro id position found + exact Nat.lt_of_lt_of_le (bound id position found) order + +theorem equiv {left right : LocalContext m} {next : UInt64} + (bound : left.IdsBelow next) (same : left.Equiv right) : right.IdsBelow next := by + intro id position found + exact bound id position ((same.index id).trans found) + +theorem fresh {context : LocalContext m} {next : UInt64} (bound : context.IdsBelow next) : + context.index[(⟨next⟩ : FVarId)]? = none := by + cases found : context.index[(⟨next⟩ : FVarId)]? with + | none => rfl + | some position => exact False.elim (Nat.lt_irrefl _ (bound _ _ found)) + +theorem push {context : LocalContext m} {next : UInt64} + (bound : context.IdsBelow next) (decl : LocalDecl m) + (room : next.toNat + 1 < UInt64.size) : + (context.push ⟨next⟩ decl).IdsBelow (next + 1) := by + have increment : (next + 1).toNat = next.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt room] + intro id position found + simp only [LocalContext.push, Std.HashMap.getElem?_insert] at found + rw [increment] + split at found + next equal => + have equal : (⟨next⟩ : FVarId) = id := eq_of_beq equal + subst id + exact Nat.lt_succ_self _ + next different => exact Nat.lt_trans (bound _ _ found) (Nat.lt_succ_self _) + +end IdsBelow +end Ix.Kernel.LocalContext + +namespace Ix.Kernel.Consistency +open Theory Theory.Model +universe u v + +/-- The installed lazy loader never rewinds the allocation counter. The +production ingress loader must establish this property on both outcomes. -/ +def LoaderCounterMonotone (loader : Option (Address → EStateM String (KEnv .anon) Bool)) : Prop := + ∀ fault, loader = some fault → ∀ addr before, + match fault addr before with + | .ok _ after | .error _ after => before.nextFVarId.toNat ≤ after.nextFVarId.toNat + +/-- Structural component of the general state invariant: local lookup is +coherent, every live identifier precedes the allocation counter, and lazy +loading never rewinds that counter. -/ +structure LocalStateInvariant (state : TcState .anon) : Prop where + coherent : state.lctx.WF + allocated : state.lctx.IdsBelow state.env.nextFVarId + loader : LoaderCounterMonotone state.lazyFault + +/-- A scoped operation can allocate fresh identifiers but restores all +incoming local declarations and lookups. -/ +structure LocalStateFrame (before after : TcState .anon) : Prop where + counter : before.env.nextFVarId.toNat ≤ after.env.nextFVarId.toNat + context : after.lctx.Equiv before.lctx + loader : after.lazyFault = before.lazyFault + +namespace LocalStateFrame + +theorem refl (state : TcState .anon) : LocalStateFrame state state := ⟨Nat.le_refl _, .refl _, rfl⟩ + +theorem trans {before middle after : TcState .anon} + (first : LocalStateFrame before middle) (second : LocalStateFrame middle after) : + LocalStateFrame before after := + ⟨Nat.le_trans first.counter second.counter, second.context.trans first.context, + second.loader.trans first.loader⟩ + +theorem invariant {before after : TcState .anon} + (frame : LocalStateFrame before after) (valid : LocalStateInvariant before) : + LocalStateInvariant after := + ⟨frame.context.symm.wf valid.coherent, + (valid.allocated.equiv frame.context.symm).mono frame.counter, + by rw [frame.loader]; exact valid.loader⟩ + +end LocalStateFrame + +/-- A body may leave fresh local declarations for its enclosing scope to +remove. Both returned states, including failures, must satisfy this effect. -/ +structure LocalStateExtension (before after : TcState .anon) : Prop where + valid : LocalStateInvariant after + counter : before.env.nextFVarId.toNat ≤ after.env.nextFVarId.toNat + context : before.lctx.Extension after.lctx + loader : after.lazyFault = before.lazyFault + +namespace LocalStateExtension + +theorem refl {state : TcState .anon} (valid : LocalStateInvariant state) : + LocalStateExtension state state := ⟨valid, Nat.le_refl _, .refl _, rfl⟩ + +theorem trans {before middle after : TcState .anon} + (first : LocalStateExtension before middle) (second : LocalStateExtension middle after) : + LocalStateExtension before after := + ⟨second.valid, Nat.le_trans first.counter second.counter, first.context.trans second.context, + second.loader.trans first.loader⟩ + +theorem of_frame {before after : TcState .anon} (valid : LocalStateInvariant before) + (frame : LocalStateFrame before after) : LocalStateExtension before after := + ⟨frame.invariant valid, frame.counter, .equiv (.refl _) frame.context.symm, frame.loader⟩ + +theorem restore {before after : TcState .anon} (effect : LocalStateExtension before after) : + LocalStateFrame before {after with lctx := after.lctx.truncate before.lctx.size} := + ⟨effect.counter, effect.context.restore, effect.loader⟩ + +end LocalStateExtension + +theorem LocalStateInvariant.ofValues {β : Type u} {resolve : Address → Option (ConstRef β)} + {entries : Model.Environment β} {values : LocalValues β} {context : Model.Context β} + {state : TcState .anon} + (agreement : LocalContextValues.{u,v} resolve entries values state.lctx context) + (bound : values.Below state.env.nextFVarId) + (loader : LoaderCounterMonotone state.lazyFault) : LocalStateInvariant state := by + refine ⟨agreement.coherent, ?_, loader⟩ + intro id position found + obtain ⟨decl, hit⟩ := agreement.coherent.sound found + have lookup : state.lctx.find? id = some decl := by + simp [LocalContext.find?, found, hit] + obtain ⟨value, read⟩ := agreement.complete id decl lookup + exact bound id value read + +/-- Prefix preservation under the structural local-state invariant. -/ +def PreservesLocalState (action : TcM .anon α) : Prop := + ∀ before, LocalStateInvariant before → match action before with + | .ok _ after | .error _ after => LocalStateExtension before after + +/-- Scoped preservation under the same invariant. The ending invariant is +derived from the restored context and monotone counter. -/ +def FramesLocalState (action : TcM .anon α) : Prop := + ∀ before, LocalStateInvariant before → match action before with + | .ok _ after | .error _ after => LocalStateFrame before after + +namespace FramesLocalState + +theorem preserves {action : TcM .anon α} (framed : FramesLocalState action) : + PreservesLocalState action := by + intro before valid + have frame := framed before valid + cases run : action before <;> rw [run] at frame <;> exact .of_frame valid frame + +theorem pure (value : α) : FramesLocalState (Pure.pure value) := fun _ _ => .refl _ + +theorem throw (error : TcError .anon) : FramesLocalState (throw error : TcM .anon α) := + fun _ _ => .refl _ + +theorem runIntern (action : InternM .anon α) : FramesLocalState (TcM.runIntern action) := + fun _ _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + +theorem of_internOnly {action : TcM .anon α} (only : action.InternOnly) : + FramesLocalState action := by + intro before _ + have changed := only before + cases run : action before <;> rw [run] at changed <;> + obtain ⟨table, exactState⟩ := changed <;> rw [exactState] <;> + exact ⟨Nat.le_refl _, .refl _, rfl⟩ + +theorem instantiateUnivParams (type : KExpr .anon) (levels : Array (KUniv .anon)) : + FramesLocalState (TcM.instantiateUnivParams type levels) := + of_internOnly (TcM.InternOnly.instantiateUnivParams type levels) + +theorem bind {action : TcM .anon α} {next : α → TcM .anon γ} + (first : FramesLocalState action) (rest : ∀ value, FramesLocalState (next value)) : + FramesLocalState (action >>= next) := by + intro before valid + have intermediate := first before valid + change match EStateM.bind action next before with + | .ok _ after | .error _ after => LocalStateFrame before after + cases run : action before with + | error error after => rw [EStateM.bind, run]; simpa only [run] using intermediate + | ok value after => + rw [run] at intermediate + rw [EStateM.bind, run] + dsimp only + have final := rest value after (intermediate.invariant valid) + cases finished : next value after <;> rw [finished] at final <;> exact intermediate.trans final + +end FramesLocalState + +namespace PreservesLocalState + +theorem bind {action : TcM .anon α} {next : α → TcM .anon γ} + (first : PreservesLocalState action) (rest : ∀ value, PreservesLocalState (next value)) : + PreservesLocalState (action >>= next) := by + intro before valid + have intermediate := first before valid + change match EStateM.bind action next before with + | .ok _ after | .error _ after => LocalStateExtension before after + cases run : action before with + | error error after => rw [EStateM.bind, run]; simpa only [run] using intermediate + | ok value after => + rw [run] at intermediate + rw [EStateM.bind, run] + dsimp only + have final := rest value after intermediate.valid + cases finished : next value after <;> rw [finished] at final <;> exact intermediate.trans final + +/-- Scope cleanup turns a prefix-preserving body into a framed computation, +including the body's partially updated failure state. -/ +theorem withLctxScope {action : RecM .anon α} {methods : Methods .anon} + (body : PreservesLocalState (action.run methods)) : + FramesLocalState ((RecM.withLctxScope action).run methods) := by + intro before valid + rw [withLctxScope_eq] + have inner := body before valid + cases run : action.run methods before <;> rw [run] at inner <;> exact inner.restore + +theorem openLet (name : Mode.anon.F Name) (type value body : KExpr .anon) : + PreservesLocalState (TcM.openLet name type value body) := by + intro before valid + rw [openLet_eq] + by_cases room : before.env.nextFVarId.toNat + 1 < UInt64.size + · rw [if_pos room] + have increment : (before.env.nextFVarId + 1).toNat = before.env.nextFVarId.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt room] + exact ⟨⟨valid.coherent.push valid.allocated.fresh, valid.allocated.push _ room, valid.loader⟩, + by change before.env.nextFVarId.toNat ≤ (before.env.nextFVarId + 1).toNat + rw [increment]; omega, .push _ (.refl _) valid.allocated.fresh, rfl⟩ + · rw [if_neg room]; exact .refl valid + +theorem openBinder (name : Mode.anon.F Name) (bi : Mode.anon.F Lean.BinderInfo) + (type body : KExpr .anon) : PreservesLocalState (TcM.openBinder name bi type body) := by + intro before valid + rw [openBinder_eq] + by_cases room : before.env.nextFVarId.toNat + 1 < UInt64.size + · rw [if_pos room] + have increment : (before.env.nextFVarId + 1).toNat = before.env.nextFVarId.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt room] + exact ⟨⟨valid.coherent.push valid.allocated.fresh, valid.allocated.push _ room, valid.loader⟩, + by change before.env.nextFVarId.toNat ≤ (before.env.nextFVarId + 1).toNat + rw [increment]; omega, .push _ (.refl _) valid.allocated.fresh, rfl⟩ + · rw [if_neg room]; exact .refl valid + +end PreservesLocalState +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/LocalScope.lean b/Ix/Kernel/Verify/LocalScope.lean new file mode 100644 index 000000000..9102152d6 --- /dev/null +++ b/Ix/Kernel/Verify/LocalScope.lean @@ -0,0 +1,171 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.LocalContext + +/-! +# Observable local contexts and fresh extensions + +Scope restoration preserves the ordered declarations and every index lookup. +Hash-map representation need not be identical after insertion and erasure. +Fresh extensions compose through nested pushes and scope truncation. +-/ + +namespace Ix.Kernel.LocalContext + +private local instance : LawfulBEq FVarId where + eq_of_beq := by + intro left right equal + cases left + cases right + congr 1 + exact eq_of_beq equal + rfl {a} := by + cases a with + | mk x => show (x == x) = true; exact beq_self_eq_true x + +/-- The ordered declarations and every observable index lookup agree. +Physical hash-map representation is deliberately not part of the relation. -/ +structure Equiv (left right : LocalContext m) : Prop where + decls : left.decls = right.decls + index : ∀ id : FVarId, left.index[id]? = right.index[id]? + +namespace Equiv + +theorem refl (context : LocalContext m) : Equiv context context := ⟨rfl, fun _ => rfl⟩ + +theorem symm {left right : LocalContext m} (same : Equiv left right) : Equiv right left := + ⟨same.decls.symm, fun id => (same.index id).symm⟩ + +theorem trans {first second third : LocalContext m} + (left : Equiv first second) (right : Equiv second third) : Equiv first third := + ⟨left.decls.trans right.decls, fun id => (left.index id).trans (right.index id)⟩ + +theorem size {left right : LocalContext m} (same : Equiv left right) : left.size = right.size := + congrArg Array.size same.decls + +theorem find? {left right : LocalContext m} (same : Equiv left right) (id : FVarId) : + left.find? id = right.find? id := by + simp only [LocalContext.find?, same.index, same.decls] + +theorem wf {left right : LocalContext m} (same : Equiv left right) (valid : left.WF) : right.WF := by + constructor + intro id position found + rw [← same.index] at found + obtain ⟨decl, hit⟩ := valid.sound found + exact ⟨decl, same.decls ▸ hit⟩ + +theorem push {left right : LocalContext m} (same : Equiv left right) + (id : FVarId) (decl : LocalDecl m) : Equiv (left.push id decl) (right.push id decl) := by + constructor + · simp only [LocalContext.push, same.decls] + · intro queried + simp only [LocalContext.push, Std.HashMap.getElem?_insert, same.decls, same.index] + +private theorem truncate_go {left right : LocalContext m} (same : Equiv left right) + (len fuel : Nat) : Equiv + (LocalContext.truncate.go len left.decls left.index fuel) + (LocalContext.truncate.go len right.decls right.index fuel) := by + induction fuel generalizing left right with + | zero => exact same + | succ fuel ih => + simp only [LocalContext.truncate.go, same.decls] + split + · apply ih (left := ⟨right.decls.pop, left.index.erase right.decls.back!.1⟩) + (right := ⟨right.decls.pop, right.index.erase right.decls.back!.1⟩) + exact ⟨rfl, fun id => by simp only [Std.HashMap.getElem?_erase, same.index]⟩ + · exact ⟨rfl, same.index⟩ + +theorem truncate {left right : LocalContext m} (same : Equiv left right) (len : Nat) : + Equiv (left.truncate len) (right.truncate len) := by + unfold LocalContext.truncate + simpa only [same.decls] using truncate_go same len (left.decls.size - len) + +end Equiv + +/-- Popping a fresh push restores the old declarations and all old lookups. -/ +theorem truncate_push {context : LocalContext m} {id : FVarId} + (fresh : context.index[id]? = none) (decl : LocalDecl m) : + Equiv ((context.push id decl).truncate context.size) context := by + rw [LocalContext.truncate_pred_eval (by simp [LocalContext.push, LocalContext.size])] + constructor + · simp [LocalContext.push] + · intro queried + simp only [LocalContext.push, Array.back!_push, Std.HashMap.getElem?_erase, + Std.HashMap.getElem?_insert] + split + next equal => + have equal : id = queried := eq_of_beq equal + subst queried + exact fresh.symm + next different => rfl + +/-- A fresh final push can also be removed while restoring an older scope. -/ +theorem truncate_push_le {context : LocalContext m} {id : FVarId} {len : Nat} + (fresh : context.index[id]? = none) (decl : LocalDecl m) (bound : len ≤ context.size) : + Equiv ((context.push id decl).truncate len) (context.truncate len) := by + unfold LocalContext.truncate + simp only [LocalContext.push, Array.size_push] + have fuel : context.decls.size + 1 - len = (context.decls.size - len) + 1 := by + change len ≤ context.decls.size at bound + omega + rw [fuel, LocalContext.truncate.go, if_pos (by + simp only [Array.size_push] + change len < context.size + 1 + omega)] + simp only [Array.back!_push, Array.pop_push] + apply Equiv.truncate_go (left := ⟨context.decls, (context.index.insert id context.decls.size).erase id⟩) + (right := context) + refine ⟨rfl, ?_⟩ + intro queried + simp only [Std.HashMap.getElem?_erase, Std.HashMap.getElem?_insert] + split + next equal => + have equal : id = queried := eq_of_beq equal + subst queried + exact fresh.symm + next different => rfl + +/-- A context is extended only by fresh pushes and by observable context +equivalence. Nested scope cleanup can therefore be composed without exposing +hash-map implementation details. -/ +inductive Extension : LocalContext m → LocalContext m → Prop + | refl (context : LocalContext m) : Extension context context + | push {before current : LocalContext m} {id : FVarId} (decl : LocalDecl m) + (previous : Extension before current) (fresh : current.index[id]? = none) : + Extension before (current.push id decl) + | equiv {before current after : LocalContext m} + (previous : Extension before current) (same : Equiv current after) : Extension before after + +namespace Extension + +theorem trans {before middle after : LocalContext m} + (first : Extension before middle) (second : Extension middle after) : Extension before after := by + induction second with + | refl => exact first + | push decl _ fresh ih => exact .push decl ih fresh + | equiv _ same ih => exact .equiv ih same + +theorem size_le {before after : LocalContext m} (extended : Extension before after) : + before.size ≤ after.size := by + induction extended with + | refl => exact Nat.le_refl _ + | push decl previous fresh ih => + simp only [LocalContext.size, LocalContext.push, Array.size_push] at * + omega + | equiv previous same ih => rw [← same.size]; exact ih + +theorem restore {before after : LocalContext m} (extended : Extension before after) : + Equiv (after.truncate before.size) before := by + induction extended with + | refl => + simpa [LocalContext.truncate, LocalContext.size, LocalContext.truncate.go] using + Equiv.refl before + | push decl previous fresh ih => exact (truncate_push_le fresh decl previous.size_le).trans ih + | equiv previous same ih => exact (same.symm.truncate _).trans ih + +end Extension + +end Ix.Kernel.LocalContext diff --git a/Ix/Kernel/Verify/UniverseInternOnly.lean b/Ix/Kernel/Verify/UniverseInternOnly.lean new file mode 100644 index 000000000..a69f39661 --- /dev/null +++ b/Ix/Kernel/Verify/UniverseInternOnly.lean @@ -0,0 +1,319 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Monad + +/-! +# Exact state effects of universe instantiation + +The production memoized walker changes only its private scratch map and the +expression intern table. This exact frame holds for cache hits, all syntax +constructors, the level-array loop, and partial failures. It needs no hash or +semantic assumptions, and supports both the named policy proof and the direct +set-model state proof. + +The structural walker proof is shared from the earlier inference-policy +development in `Check/UniverseInstantiationPolicy.lean`. +-/ + +namespace Ix.Kernel + +/-- The action changes only the expression intern table, on success and on +failure. Its result may depend on that table; this contract concerns effects. -/ +def TcM.InternOnly (action : TcM .anon α) : Prop := + ∀ before, match action before with + | .ok _ after | .error _ after => + ∃ table, after = {before with env := {before.env with intern := table}} + +namespace TcM.InternOnly + +theorem pure (value : α) : (Pure.pure value : TcM .anon α).InternOnly := + fun before => ⟨before.env.intern, rfl⟩ + +theorem throw (error : TcError .anon) : (throw error : TcM .anon α).InternOnly := + fun before => ⟨before.env.intern, rfl⟩ + +theorem bind {action : TcM .anon α} {next : α → TcM .anon γ} + (first : action.InternOnly) (rest : ∀ value, (next value).InternOnly) : + (action >>= next).InternOnly := by + intro before + have intermediate := first before + change match EStateM.bind action next before with + | .ok _ after | .error _ after => + ∃ table, after = {before with env := {before.env with intern := table}} + cases run : action before with + | error error after => rw [EStateM.bind, run]; simpa only [run] using intermediate + | ok value after => + rw [run] at intermediate + obtain ⟨table, changed⟩ := intermediate + rw [EStateM.bind, run] + dsimp only + have final := rest value after + cases finished : next value after <;> rw [finished] at final <;> + obtain ⟨newTable, changedAgain⟩ := final <;> + exact ⟨newTable, by rw [changedAgain, changed]⟩ + +theorem runIntern (action : InternM .anon α) : (TcM.runIntern action).InternOnly := + fun before => ⟨(action before.env.intern).2, rfl⟩ + +theorem ofExcept (value : Except (TcError .anon) alpha) : + (TcM.ofExcept value).InternOnly := by + cases value with + | ok value => exact pure value + | error err => exact throw err + +theorem map {x : TcM .anon alpha} (hx : x.InternOnly) + (f : alpha → beta) : (f <$> x).InternOnly := by + rw [← bind_pure_comp] + exact bind hx fun value => pure (f value) + +private def StateInternOnly + (x : StateT sigma (TcM .anon) alpha) : Prop := + ∀ memo, (x.run memo).InternOnly + +private theorem statePure (value : alpha) : + StateInternOnly + (Pure.pure value : StateT sigma (TcM .anon) alpha) := by + intro memo + simp only [StateT.run_pure] + exact TcM.InternOnly.pure _ + +private theorem stateBind {x : StateT sigma (TcM .anon) alpha} + {f : alpha → StateT sigma (TcM .anon) beta} + (hx : StateInternOnly x) + (hf : ∀ value, StateInternOnly (f value)) : + StateInternOnly (x >>= f) := by + intro memo + simp only [StateT.run_bind] + apply TcM.InternOnly.bind (hx memo) + intro pair + exact hf pair.1 pair.2 + +private theorem stateGet : + StateInternOnly + (MonadState.get : StateT sigma (TcM .anon) sigma) := by + intro memo + simp only [StateT.run_get] + exact TcM.InternOnly.pure _ + +private theorem stateModify (f : sigma → sigma) : + StateInternOnly + (_root_.modify f : StateT sigma (TcM .anon) PUnit) := by + intro memo + simp only [StateT.run_modify] + exact TcM.InternOnly.pure _ + +private theorem stateLift {x : TcM .anon alpha} + (hx : x.InternOnly) : + StateInternOnly + (monadLift x : StateT sigma (TcM .anon) alpha) := by + intro memo + simp only [StateT.run_monadLift] + apply TcM.InternOnly.bind hx + intro value + exact TcM.InternOnly.pure _ + +private theorem stateForInArray + (items : Array alpha) (initial : beta) + (step : alpha → beta → + StateT sigma (TcM .anon) (ForInStep beta)) + (hstep : ∀ item state, + StateInternOnly (step item state)) : + StateInternOnly (forIn items initial step) := by + rcases items with ⟨items⟩ + simp only [List.forIn_toArray] + induction items generalizing initial with + | nil => + simp + exact statePure initial + | cons item rest ih => + rw [List.forIn_cons] + apply stateBind (hstep item initial) + intro action + cases action with + | done result => exact statePure result + | yield next => exact ih next + +private theorem stateInternMemo (key : Address) (result : KExpr .anon) : + StateInternOnly (do + let interned ← monadLift (TcM.intern result) + _root_.modify fun memo : Std.HashMap Address (KExpr .anon) => + memo.insert key interned + Pure.pure interned) := by + apply stateBind (stateLift (runIntern _)) + intro interned + apply stateBind (stateModify _) + intro _ + exact statePure interned + +/-- Universe instantiation changes only the actual expression intern table. +The statement is unconditional: collision freedom constrains the returned +syntax, while this theorem covers the walker's state effects. -/ +theorem instantiateUnivParams (e : KExpr .anon) + (us : Array (KUniv .anon)) : + (TcM.instantiateUnivParams e us).InternOnly := by + unfold TcM.instantiateUnivParams + split + · exact pure e + · have hinner : ∀ (source : KExpr .anon), + StateInternOnly (TcM.instUnivInner source us) := by + intro source + induction source with + | var idx name info => + simp only [TcM.instUnivInner] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind (stateModify _) + intro _ + exact statePure (KExpr.var idx name info) + | fvar id name info => + simp only [TcM.instUnivInner] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind (stateModify _) + intro _ + exact statePure (KExpr.fvar id name info) + | sort u info => + simp only [TcM.instUnivInner] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind (stateLift (ofExcept (substUniv u us))) + intro resultUniv + apply stateBind (statePure (KExpr.mkSort resultUniv)) + intro result + exact stateInternMemo (KExpr.sort u info).addr result + | const id levels info => + rw [TcM.instUnivInner] + simp (config := { proj := false }) only [] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind + (stateForInArray levels (Array.mkEmpty levels.size) + (fun level current => do + let instantiated ← + monadLift (TcM.ofExcept (substUniv level us)) + let next := current.push instantiated + Pure.pure PUnit.unit + Pure.pure (ForInStep.yield next)) + (by + intro level current + apply stateBind + (stateLift (ofExcept (substUniv level us))) + intro instantiated + exact statePure + (ForInStep.yield (current.push instantiated)))) + intro newLevels + apply stateBind (statePure (KExpr.mkConst id newLevels)) + intro result + exact stateInternMemo (KExpr.const id levels info).addr result + | app f a info ihf iha => + rw [TcM.instUnivInner] + simp (config := { proj := false }) only [] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind ihf + intro resultF + apply stateBind iha + intro resultA + apply stateBind (statePure (KExpr.mkApp resultF resultA)) + intro result + exact stateInternMemo (KExpr.app f a info).addr result + | lam name bi ty body info ihty ihbody => + rw [TcM.instUnivInner] + simp (config := { proj := false }) only [] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind ihty + intro resultTy + apply stateBind ihbody + intro resultBody + apply stateBind + (statePure (KExpr.mkLam name bi resultTy resultBody)) + intro result + exact stateInternMemo (KExpr.lam name bi ty body info).addr result + | all name bi ty body info ihty ihbody => + rw [TcM.instUnivInner] + simp (config := { proj := false }) only [] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind ihty + intro resultTy + apply stateBind ihbody + intro resultBody + apply stateBind + (statePure (KExpr.mkAll name bi resultTy resultBody)) + intro result + exact stateInternMemo (KExpr.all name bi ty body info).addr result + | letE name ty value body nondep info ihty ihvalue ihbody => + rw [TcM.instUnivInner] + simp (config := { proj := false }) only [] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind ihty + intro resultTy + apply stateBind ihvalue + intro resultValue + apply stateBind ihbody + intro resultBody + apply stateBind + (statePure + (KExpr.mkLet name resultTy resultValue resultBody nondep)) + intro result + exact stateInternMemo + (KExpr.letE name ty value body nondep info).addr result + | prj id field value info ih => + rw [TcM.instUnivInner] + simp (config := { proj := false }) only [] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind ih + intro resultValue + apply stateBind + (statePure (KExpr.mkPrj id field resultValue)) + intro result + exact stateInternMemo (KExpr.prj id field value info).addr result + | nat value blob info => + simp only [TcM.instUnivInner] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind (stateModify _) + intro _ + exact statePure (KExpr.nat value blob info) + | str value blob info => + simp only [TcM.instUnivInner] + apply stateBind stateGet + intro memo + split + · exact statePure _ + · apply stateBind (stateModify _) + intro _ + exact statePure (KExpr.str value blob info) + have hrun := hinner e ({} : Std.HashMap Address (KExpr .anon)) + unfold StateT.run' + exact map hrun Prod.fst + +end TcM.InternOnly + +end Ix.Kernel diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 6c35b426d..1a25849d7 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -150,6 +150,20 @@ increasing sequence of strongly inaccessible cardinals. final scope cleanup. It requires no precomputed execution tree. Under the local-state and finite walker invariants, the trace transports the recursive body's typing to the original let and its substituted type before cheap beta. +- Local scope restoration preserves the ordered declarations and every index + lookup without requiring equal hash-map representations. Fresh extensions + compose, and actual scope cleanup restores the caller's context on success + and failure. The let trace recovers `LocalContextValues` after validation; + the inference cache shell preserves caller contexts whenever its uncached + body does. `LocalStateInvariant` derives freshness from the live identifier + bound, and `infer_framesLocalState` preserves it for all constructors and + both policies, including hits, writes and failure states. Recursive + inference, reduction, conversion and projection remain contracts of the + mutual execution proof. The installed production lazy loader must establish + its counter-preservation contract. `TcM.InternOnly.instantiateUnivParams` + proves the actual universe walker's exact intern-table-only effect without + collision assumptions; the named inference-policy proof shares this result. + These structural frames do not establish computed-type or cache semantics. - `InferenceCacheInvariant` covers every entry in both production maps, with separate full-checking and inference-only meanings. Hits obtain stored facts directly; each insertion establishes its own fact and preserves all other @@ -417,6 +431,7 @@ The VM pilot is preserved in the frozen archive and excluded from the host gate. | Dependent binders and function bodies | [`Consistency/BinderInference.lean`](../Ix/Kernel/Verify/Consistency/BinderInference.lean), [`Application.lean`](../Ix/Kernel/Verify/Consistency/Application.lean), [`BinderOpening.lean`](../Ix/Kernel/Verify/Consistency/BinderOpening.lean), [`Context.lean`](../Ix/Kernel/Verify/Consistency/Context.lean), [`Model/Checking.lean`](../Ix/Theory/Model/Checking.lean) | | Let-bound values, local allocation and shared context coherence | [`Consistency/LocalValues.lean`](../Ix/Kernel/Verify/Consistency/LocalValues.lean), [`LocalOpening.lean`](../Ix/Kernel/Verify/Consistency/LocalOpening.lean), [`Verify/LocalContext.lean`](../Ix/Kernel/Verify/LocalContext.lean), [`Model/ContextTransport.lean`](../Ix/Theory/Model/ContextTransport.lean) | | Local substitution, let-inference traces and closing inferred types | [`Consistency/LocalSubstitution.lean`](../Ix/Kernel/Verify/Consistency/LocalSubstitution.lean), [`LetInference.lean`](../Ix/Kernel/Verify/Consistency/LetInference.lean) | +| Observable local-context restoration and inference frames | [`Verify/LocalScope.lean`](../Ix/Kernel/Verify/LocalScope.lean), [`Consistency/LocalScope.lean`](../Ix/Kernel/Verify/Consistency/LocalScope.lean) | | Production environment fragment and relative axiom policy | [`Consistency/Environment.lean`](../Ix/Kernel/Verify/Consistency/Environment.lean), [`Production.lean`](../Ix/Kernel/Verify/Consistency/Production.lean) | | Safe definition self-reference and block dependency order | [`DefinitionOrder.lean`](../Ix/Kernel/DefinitionOrder.lean), [`Consistency/DefinitionOrder.lean`](../Ix/Kernel/Verify/Consistency/DefinitionOrder.lean) | | Foundation assumptions, theorem contracts, and provenance | [Consistency model guide](theory.md) | From 126586ba5c43f569095f97115a7ccd050094f27f Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 08:59:38 -0400 Subject: [PATCH 28/30] Make anonymous ingress total and preserve checker state Replace Lean's unbounded conversion loops with source-derived finite work bounds and reject cycles in active sharing expansions. Validate reachable sharing graphs before Rust conversion, memoizing completed expression DAGs. Prove the actual loader changes only declarations, blocks and intern tables on success and failure, then establish the driver's structural local-state invariant without an assumed loader effect. Discharge projection inference's separate state contract using its recursive inference and reduction contracts. Audit all 59 new projection/ingress roots with exact dependency allowances. Validation: full check-kernel --with-model gate; 847 Rust kernel tests passed (8 ignored); release Clippy and formatting; nine new native Lean regressions. Conversion semantics and general mutual checker soundness remain open. --- Ix/Kernel/Ingress.lean | 20 +- Ix/Kernel/IngressBudget.lean | 80 +++ Ix/Kernel/Verify/Consistency.lean | 13 +- Ix/Kernel/Verify/Consistency/Audit.lean | 79 ++- .../Verify/Consistency/IngressLocalState.lean | 38 ++ .../Consistency/ProjectionLocalState.lean | 232 +++++++++ Ix/Kernel/Verify/IngressState.lean | 484 ++++++++++++++++++ Tests/Ix/Kernel/IngressState.lean | 72 +++ Tests/Main.lean | 4 +- crates/kernel/src/ingress.rs | 162 ++++++ docs/kernel-verification.md | 23 +- 11 files changed, 1191 insertions(+), 16 deletions(-) create mode 100644 Ix/Kernel/IngressBudget.lean create mode 100644 Ix/Kernel/Verify/Consistency/IngressLocalState.lean create mode 100644 Ix/Kernel/Verify/Consistency/ProjectionLocalState.lean create mode 100644 Ix/Kernel/Verify/IngressState.lean create mode 100644 Tests/Ix/Kernel/IngressState.lean diff --git a/Ix/Kernel/Ingress.lean b/Ix/Kernel/Ingress.lean index f459ddbd4..f893f82f7 100644 --- a/Ix/Kernel/Ingress.lean +++ b/Ix/Kernel/Ingress.lean @@ -2,6 +2,7 @@ module public import Ix.Kernel.Monad public import Ix.Ixon +public import Ix.Kernel.IngressBudget /-! Mirror: crates/kernel/src/ingress.rs (the Ixon → kernel, anonymous-mode half) @@ -11,7 +12,7 @@ Anon ingress uses only `Ixon.Constant` data — never `ConstantMeta`, deterministically from `(block, idx, [cidx])` via `serConstant` commitment, which agrees with the addresses the compiler stores in `env.consts`. -Expression conversion is an explicit stack machine (Init-scale terms overflow +Expression conversion is a bounded explicit stack machine (Init-scale terms overflow default runtime stacks under structural recursion; Rust runs the recursive meta-mode converter on 2 GB stacks — the anon machine here is iterative). `share` nodes expand transparently against the constant's sharing table, with @@ -19,6 +20,8 @@ a share-index-keyed conversion cache (Lean has no stable pointers; a deserialized subterm is only re-entered via `share`, so this captures exactly the hits Rust's pointer-keyed cache sees). Universe conversion caches by universe-table index for the same reason. Every constructed node is interned. +Total range loops use source-derived work bounds. Active sharing expansions +reject cycles before revisiting an unfinished entry. Integrity: `getConstVerified` checks `blake3(rawBytes) == addr` at materialization. Rust's `Env::get` does this on its main path; the @@ -148,7 +151,8 @@ inductive UFrame where def ingressUnivTree (root : Ixon.Univ) : IngressM (KUniv .anon) := do let mut stack : Array UFrame := #[.process root] let mut values : Array (KUniv .anon) := #[] - while !stack.isEmpty do + for _ in [0:ingressUnivWork [root]] do + if stack.isEmpty then break let frame := stack.back! stack := stack.pop match frame with @@ -176,6 +180,8 @@ def ingressUnivTree (root : Ixon.Univ) : IngressM (KUniv .anon) := do let b := values.back!; values := values.pop let a := values.back!; values := values.pop values := values.push (← IngressM.internU (.mkIMax a b)) + if !stack.isEmpty then + throw "ingressUnivTree: conversion work budget exhausted" match values.back? with | some v => return v | none => throw "ingressUnivTree: empty result stack" @@ -248,7 +254,9 @@ def ingressExpr (ixonEnv : Ixon.Env) (ctx : IngressCtx) (root : Ixon.Expr) : ConvM (KExpr .anon) := do let mut stack : Array EFrame := #[.process root] let mut values : Array (KExpr .anon) := #[] - while !stack.isEmpty do + let mut active : Std.HashSet UInt64 := {} + for _ in [0:ingressExprWorkBudget root ctx.sharing] do + if stack.isEmpty then break let frame := stack.back! stack := stack.pop match frame with @@ -260,6 +268,9 @@ def ingressExpr (ixonEnv : Ixon.Env) (ctx : IngressCtx) (root : Ixon.Expr) : else let some expansion := ctx.sharing[idx.toNat]? | throw s!"invalid Share index {idx}" + if active.contains idx then + throw s!"cyclic Share index {idx}" + active := active.insert idx stack := stack.push (.cacheShare idx) |>.push (.process expansion) | .var idx => values := values.push (← liftM (IngressM.internE (.mkVar idx ()))) @@ -338,6 +349,9 @@ def ingressExpr (ixonEnv : Ixon.Env) (ctx : IngressCtx) (root : Ixon.Expr) : | .cacheShare idx => let v := values.back! modify fun s => { s with exprCache := s.exprCache.insert idx v } + active := active.erase idx + if !stack.isEmpty then + throw "ingressExpr: conversion work budget exhausted" match values.back? with | some v => if values.size != 1 then diff --git a/Ix/Kernel/IngressBudget.lean b/Ix/Kernel/IngressBudget.lean new file mode 100644 index 000000000..db72589b3 --- /dev/null +++ b/Ix/Kernel/IngressBudget.lean @@ -0,0 +1,80 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +module + +public import Ix.Ixon + +/-! +# Finite work bounds for anonymous ingress + +These tail-recursive counters visit the serialized source trees without +expanding sharing references. The expression bound reserves one expansion +and completion frame for every sharing-table entry. Conversion maintains an +active-sharing set and a completed-entry cache, so a cyclic expansion is +rejected and an entry need only be expanded once. + +The counters and the production range loops are total Lean definitions. +Their numeric bounds are computed from input syntax, not supplied by a +caller or justified by a termination axiom. +-/ + +public section +@[expose] section + +namespace Ix.Kernel + +/-- Logical work-list measure; it is erased from the executable counter. -/ +noncomputable def ingressExprPendingSize : List Ixon.Expr → Nat + | [] => 0 + | e :: rest => sizeOf e + ingressExprPendingSize rest + +/-- Count the explicit conversion frames for the source trees without +expanding share references. The counter walk itself uses a tail-recursive +work list, so input depth does not consume the native call stack. -/ +def ingressExprWork (pending : List Ixon.Expr) (total : Nat := 0) : Nat := + match pending with + | [] => total + | e :: rest => match e with + | .app f a => ingressExprWork (f :: a :: rest) (total + 2) + | .lam _ ty body | .all _ _ ty body => ingressExprWork (ty :: body :: rest) (total + 2) + | .letE _ ty value body => ingressExprWork (ty :: value :: body :: rest) (total + 2) + | .prj _ _ value => ingressExprWork (value :: rest) (total + 2) + | _ => ingressExprWork rest (total + 1) +termination_by ingressExprPendingSize pending +decreasing_by + all_goals simp [ingressExprPendingSize] + all_goals first | omega | skip + all_goals rename_i expr; cases expr <;> simp <;> omega + +/-- All sharing-table expansions, each with its cache-completion frame. -/ +def ingressSharingWork (sharing : Array Ixon.Expr) : Nat := + sharing.foldl (fun total expr => ingressExprWork [expr] (total + 1)) 0 + +def ingressExprWorkBudget (root : Ixon.Expr) (sharing : Array Ixon.Expr) : Nat := + ingressExprWork [root] (ingressSharingWork sharing) + +/-- Logical universe work-list measure, also erased from the runtime walk. -/ +noncomputable def ingressUnivPendingSize : List Ixon.Univ → Nat + | [] => 0 + | u :: rest => sizeOf u + ingressUnivPendingSize rest + +def ingressUnivWork (pending : List Ixon.Univ) (total : Nat := 0) : Nat := + match pending with + | [] => total + | u :: rest => match u with + | .succ inner => ingressUnivWork (inner :: rest) (total + 2) + | .max a b | .imax a b => ingressUnivWork (a :: b :: rest) (total + 2) + | _ => ingressUnivWork rest (total + 1) +termination_by ingressUnivPendingSize pending +decreasing_by + all_goals simp [ingressUnivPendingSize] + all_goals first | omega | skip + all_goals rename_i level; cases level <;> simp <;> omega + +end Ix.Kernel + +end +end diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 4a475c854..3ffff8e47 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -23,6 +23,8 @@ import Ix.Kernel.Verify.Consistency.LocalSubstitution import Ix.Kernel.Verify.Consistency.LetInference import Ix.Kernel.Verify.Consistency.LocalScope import Ix.Kernel.Verify.Consistency.InferenceLocalState +import Ix.Kernel.Verify.Consistency.ProjectionLocalState +import Ix.Kernel.Verify.Consistency.IngressLocalState import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.RecursiveCache @@ -105,10 +107,15 @@ context present after validation; the inference cache shell preserves caller contexts whenever the uncached branch does. A maintained structural invariant derives fresh opening from the counter bound. Every uncached constructor, both cache partitions and the final write preserve it on success and failure, -under the recursive inference, reduction, conversion and projection contracts. +under the recursive inference, reduction and conversion contracts. Projection +inference's parameter and dependent-field loops, Prop checks and lookups +preserve the same state from those recursive inference and reduction contracts. Universe instantiation unconditionally changes only the intern table. -The installed production loader must still establish counter preservation; -the general mutual proof must supply the recursive and semantic contracts. +The actual anonymous loader preserves all checker-owned environment fields, +including the counter and caches, through conversion, declaration publication +and errors. The lazy driver's initial state establishes the structural local +invariant without a loader-effect assumption. The general mutual proof must +still supply the recursive and semantic contracts. The safe-definition guard excludes self-reference for both modes and arbitrary universe arities. Successful definition-block execution computes an order of diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 2614c04f6..25a5d199f 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -15,6 +15,8 @@ import Ix.Kernel.Verify.Consistency.LocalSubstitution import Ix.Kernel.Verify.Consistency.LetInference import Ix.Kernel.Verify.Consistency.LocalScope import Ix.Kernel.Verify.Consistency.InferenceLocalState +import Ix.Kernel.Verify.Consistency.ProjectionLocalState +import Ix.Kernel.Verify.Consistency.IngressLocalState import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -297,7 +299,71 @@ private def localStateOperationalRoots : Array Lean.Name := #[ ``FramesLocalState.ensureForallDirect, ``inferUncached_framesLocalState, ``FramesLocalState.inferWith, - ``infer_framesLocalState + ``infer_framesLocalState, + ``FramesLocalState.peelProjForall, ``FramesLocalState.instantiateProjParamStep, + ``FramesLocalState.instantiateProjParams, ``FramesLocalState.inductiveAppBinderStep, + ``FramesLocalState.inductiveAppBinders, ``FramesLocalState.inductiveAppResultIsProp, + ``FramesLocalState.inductiveAppIsProp, ``FramesLocalState.inferProjFieldStep, + ``FramesLocalState.inferProjFieldsLoopStep, ``FramesLocalState.inferProjFields, + ``FramesLocalState.inferProj, ``infer_framesLocalState_of_whnf +] + +private def ingressFrameRoots : Array Lean.Name := #[ + ``KEnv.IngressFrame.refl, + ``KEnv.IngressFrame.trans, + ``KEnv.IngressFrame.counter, + ``KEnv.IngressFrame.insert, + ``KEnv.IngressFrame.insertBlock, + ``KEnv.IngressFrame.foldl, + ``KEnv.IngressFrame.insertEntriesState, + ``KEnv.IngressFrame.insertMutsEntriesState, + ``IngressM.FramesState.pure, + ``IngressM.FramesState.throw, + ``IngressM.FramesState.get, + ``IngressM.FramesState.modifyGet, + ``IngressM.FramesState.liftExcept, + ``IngressM.FramesState.bind, + ``IngressM.FramesState.internE, + ``IngressM.FramesState.internU, + ``IngressM.FramesState.forInList, + ``IngressM.FramesState.forInArray, + ``IngressM.FramesState.forInList', + ``ConvM.FramesState.pure, + ``ConvM.FramesState.throw, + ``ConvM.FramesState.get, + ``ConvM.FramesState.modify, + ``ConvM.FramesState.bind, + ``ConvM.FramesState.lift, + ``ConvM.FramesState.forInList, + ``ConvM.FramesState.forInArray +] + +private def ingressMapRoots : Array Lean.Name := #[ + ``IngressM.FramesState.forInRange, + ``IngressM.FramesState.forInRange', + ``IngressM.FramesState.guardReserved, + ``IngressM.FramesState.insertStandaloneEntries, + ``IngressM.FramesState.insertMutsEntries, + ``ConvM.FramesState.forInRange +] + +private def ingressLevelRoots : Array Lean.Name := #[ + ``IngressM.FramesState.ingressUnivTree, + ``ConvM.FramesState.ingressUnivIdx, + ``ConvM.FramesState.ingressUnivArgs +] + +private def ingressOperationalRoots : Array Lean.Name := #[ + ``IngressM.FramesState.ingressDefnAnon, + ``IngressM.FramesState.ingressRecursorAnon, + ``IngressM.FramesState.ingressAnonInductive, + ``IngressM.FramesState.ingressAnonStandalone, + ``IngressM.FramesState.prepareAnonBlock, + ``IngressM.FramesState.ingressAnonBlockWithTrace, + ``IngressM.FramesState.ingressAnonBlock, + ``IngressM.FramesState.ingressAnonAddrShallow, + ``ConvM.FramesState.ingressExpr, + ``LoaderCounterMonotone.ingressAnonAddrShallow ] /-- Production roots must not acquire a checker-soundness assumption @@ -380,26 +446,29 @@ def roots : Array RootAllowance := #[ ] ++ (stringListRoots ++ #[``LocalValues.pushLet_extends, ``LocalValues.pushBinder_lifts, ``LocalValues.Below.pushLet]).map (fun root => { root, standardAxioms := #[``propext], forbiddenDependencies := forbiddenProduction -}) ++ (localIndexRoots ++ localScopeFrameRoots ++ localStateFrameRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ +}) ++ (localIndexRoots ++ localScopeFrameRoots ++ localStateFrameRoots ++ ingressFrameRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ internFrameRoots ++ #[``DefinitionOrder.ready_independent, ``DefinitionOrder.order?_sound, ``DefinitionOrder.member_of_read, ``LocalValues.Below.pushBinder]).map (fun root => { root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction -}) ++ (contextRoots ++ localValueRoots ++ localStateMapRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ +}) ++ (contextRoots ++ localValueRoots ++ localStateMapRoots ++ ingressMapRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ internMapRoots ++ #[``DefinitionOrder.order?_rank, ``DefinitionOrder.acyclic_rank]).map (fun root => { root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction }) ++ (binderWalkerRoots ++ localStateWalkerRoots ++ cacheKeyRoots ++ cacheInvariantKeyRoots ++ stringExpansionRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative], forbiddenDependencies := forbiddenProduction -}) ++ (atomicRoots ++ localStateOperationalRoots ++ instantiationRoots ++ recursiveCacheRoots ++ +}) ++ ingressLevelRoots.map (fun root => { + root, standardAxioms := standard, nativeAxioms := #[levelNative], + forbiddenDependencies := forbiddenProduction +}) ++ (atomicRoots ++ localStateOperationalRoots ++ ingressOperationalRoots ++ instantiationRoots ++ recursiveCacheRoots ++ #[``InferenceCacheInvariant.infer]).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], forbiddenDependencies := forbiddenProduction }) ++ (productionRoots ++ cacheInvariantDriverRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := productionNative, forbiddenDependencies := forbiddenProduction -}) ++ #[``InferenceCacheInvariant.newLazyAnon, +}) ++ #[``LocalStateInvariant.newLazyAnon, ``InferenceCacheInvariant.newLazyAnon, ``InferenceCacheInvariant.initialAnonCheckLoopState].map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative, diff --git a/Ix/Kernel/Verify/Consistency/IngressLocalState.lean b/Ix/Kernel/Verify/Consistency/IngressLocalState.lean new file mode 100644 index 000000000..38dc4fe10 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/IngressLocalState.lean @@ -0,0 +1,38 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalState +import Ix.Kernel.Verify.IngressState +import Ix.Kernel.Driver + +/-! +# Production loader establishes the structural local invariant + +The actual anonymous loader preserves every checker-owned environment field +on both outcomes. In particular, it cannot rewind the fresh-variable counter. +The lazy driver's initial state therefore establishes the structural local +invariant without a separate callback-effect assumption. Declaration meaning, +intern coherence and semantic cache preservation remain separate obligations. +-/ + +namespace Ix.Kernel.Consistency + +theorem LoaderCounterMonotone.ingressAnonAddrShallow (env : Ixon.Env) (verify : Bool) : + LoaderCounterMonotone (some fun addr => ingressAnonAddrShallow env addr verify) := by + intro fault installed addr before + cases installed + dsimp only + have frame := IngressM.FramesState.ingressAnonAddrShallow env addr verify before + cases run : _root_.Ix.Kernel.ingressAnonAddrShallow env addr verify before <;> rw [run] at frame <;> + exact Nat.le_of_eq (congrArg UInt64.toNat frame.counter.symm) + +/-- The structural local invariant is established by the actual lazy driver, +including its concrete loader. It needs no loader-effect premise. -/ +theorem LocalStateInvariant.newLazyAnon (env : Ixon.Env) (verify : Bool) : + LocalStateInvariant (TcState.newLazyAnon env verify) := + ⟨LocalContext.WF.empty, LocalContext.IdsBelow.empty _, + LoaderCounterMonotone.ingressAnonAddrShallow env verify⟩ + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/ProjectionLocalState.lean b/Ix/Kernel/Verify/Consistency/ProjectionLocalState.lean new file mode 100644 index 000000000..ad85a37a2 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/ProjectionLocalState.lean @@ -0,0 +1,232 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.InferenceLocalState + +/-! +# Local-state preservation by projection inference + +The production parameter and field traversals preserve the caller's locals, +allocation bound and installed loader, on both success and partial failure. +The proof includes inductive result-sort classification, dependent field +substitution and Prop elimination checks. Recursive inference and direct +WHNF remain the smaller method contracts; lookup and universe-instantiation +effects are derived from the maintained local-state invariant. + +This closes the projection premise of the general inference state frame. +Projection typing and the model interpretation of inductive declarations +remain separate semantic obligations. +-/ + +namespace Ix.Kernel.Consistency.FramesLocalState + +private theorem forInList {methods : Methods .anon} (items : List α) (initial : β) + (step : α → β → RecM .anon (ForInStep β)) + (framed : ∀ item value, FramesLocalState ((step item value).run methods)) : + FramesLocalState ((forIn items initial step).run methods) := by + induction items generalizing initial with + | nil => exact pure _ + | cons item rest ih => + rw [List.forIn_cons] + simp only [ReaderT.run_bind] + apply bind (framed item initial) + intro next + cases next with + | done value => exact pure _ + | yield value => exact ih value + +private theorem forInRange {methods : Methods .anon} (range : Std.Legacy.Range) (initial : α) + (step : Nat → α → RecM .anon (ForInStep α)) + (framed : ∀ index value, FramesLocalState ((step index value).run methods)) : + FramesLocalState ((forIn range initial step).run methods) := by + rw [Std.Legacy.Range.forIn_eq_forIn_range'] + exact forInList _ _ _ framed + +theorem peelProjForall {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (type : KExpr .anon) (error : String) : + FramesLocalState ((RecM.peelProjForall type error).run methods) := by + cases type <;> simp only [RecM.peelProjForall, ReaderT.run_bind] + case all => exact pure _ + all_goals + apply bind (whnf _) + intro result + cases result <;> first | exact pure _ | exact throw _ + +theorem instantiateProjParamStep {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (args : Array (KExpr .anon)) (index : Nat) (type : KExpr .anon) : + FramesLocalState ((RecM.instantiateProjParamStep args index type).run methods) := by + unfold RecM.instantiateProjParamStep + simp only [ReaderT.run_bind] + apply bind (peelProjForall whnf _ _) + intro pair + split + · exact bind (runIntern _) (fun _ => pure _) + · exact throw _ + +theorem instantiateProjParams {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (args : Array (KExpr .anon)) (numParams : Nat) (type : KExpr .anon) : + FramesLocalState ((RecM.instantiateProjParams args numParams type).run methods) := + forInRange _ _ _ (instantiateProjParamStep whnf args) + +theorem inductiveAppBinderStep {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (type : KExpr .anon) : + FramesLocalState ((RecM.inductiveAppBinderStep type).run methods) := by + unfold RecM.inductiveAppBinderStep + simp only [ReaderT.run_bind] + apply bind (whnf type) + intro result + cases result <;> first | exact pure _ | exact throw _ + +theorem inductiveAppBinders {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (binders : Nat) (type : KExpr .anon) : + FramesLocalState ((RecM.inductiveAppBinders binders type).run methods) := + forInRange _ _ _ (fun _ => inductiveAppBinderStep whnf) + +theorem inductiveAppResultIsProp {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (type : KExpr .anon) : + FramesLocalState ((RecM.inductiveAppResultIsProp type).run methods) := by + unfold RecM.inductiveAppResultIsProp + simp only [ReaderT.run_bind] + exact bind (whnf type) fun sortType => bind (ensureSortDirect whnf sortType) fun _ => pure _ + +theorem inductiveAppIsProp {methods : Methods .anon} + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (id : KId .anon) (levels : Array (KUniv .anon)) (binders : Nat) : + FramesLocalState ((RecM.inductiveAppIsProp id levels binders).run methods) := by + unfold RecM.inductiveAppIsProp + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply bind (tryGetConst id) + intro constant + split + · simp only [ReaderT.run_bind, pure_bind, ReaderT.run_monadLift] + apply bind (instantiateUnivParams _ levels) + intro instantiated + exact bind (inductiveAppBinders whnf binders instantiated) (inductiveAppResultIsProp whnf) + · exact fun before _ => .refl _ + +theorem inferProjFieldStep {methods : Methods .anon} + (recursive : ∀ term, FramesLocalState (methods.infer term)) + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (id : KId .anon) (field : UInt64) (value : KExpr .anon) + (prop : Bool) (index : Nat) (type : KExpr .anon) : + FramesLocalState ((RecM.inferProjFieldStep id field value prop index type).run methods) := by + unfold RecM.inferProjFieldStep + simp only [ReaderT.run_bind] + apply bind (peelProjForall whnf _ _) + intro pair + rcases pair with ⟨domain, body⟩ + split + · cases prop with + | false => exact pure _ + | true => + simp only [if_true, ReaderT.run_bind] + apply bind (recursive domain) + intro domainType + apply bind (ensureSortDirect whnf domainType) + intro level + split + · exact throw _ + · exact pure _ + · have tail : FramesLocalState ((do + let projection ← TcM.intern (.mkPrj id index.toUInt64 value) + let result ← TcM.runIntern (subst body projection 0) + return ForInStep.yield result : RecM .anon (ForInStep (KExpr .anon))).run methods) := by + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + exact bind (intern _) fun _ => bind (runIntern _) fun _ => pure _ + cases prop with + | false => exact tail + | true => + simp only [if_true, ReaderT.run_bind] + apply bind (recursive domain) + intro domainType + apply bind (ensureSortDirect whnf domainType) + intro level + split + · exact throw _ + · exact tail + +theorem inferProjFieldsLoopStep {methods : Methods .anon} + (recursive : ∀ term, FramesLocalState (methods.infer term)) + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (id : KId .anon) (field : UInt64) (value : KExpr .anon) + (prop : Bool) (index : Nat) (state : Option (KExpr .anon) × KExpr .anon) : + FramesLocalState ((RecM.inferProjFieldsLoopStep id field value prop index state).run methods) := by + unfold RecM.inferProjFieldsLoopStep + simp only [ReaderT.run_bind] + exact bind (inferProjFieldStep recursive whnf id field value prop index state.2) + fun next => by cases next <;> exact pure _ + +theorem inferProjFields {methods : Methods .anon} + (recursive : ∀ term, FramesLocalState (methods.infer term)) + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (id : KId .anon) (field : UInt64) (value : KExpr .anon) + (prop : Bool) (type : KExpr .anon) : + FramesLocalState ((RecM.inferProjFields id field value prop type).run methods) := by + unfold RecM.inferProjFields + simp only [ReaderT.run_bind] + apply bind (forInRange _ _ _ (inferProjFieldsLoopStep recursive whnf id field value prop)) + intro pair + cases pair.1 <;> first | exact pure _ | exact throw _ + +theorem inferProj {methods : Methods .anon} + (recursive : ∀ term, FramesLocalState (methods.infer term)) + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (id : KId .anon) (field : UInt64) (value type : KExpr .anon) : + FramesLocalState ((RecM.inferProj id field value type).run methods) := by + unfold RecM.inferProj + simp only [ReaderT.run_bind] + apply bind (whnf type) + intro reduced + generalize reduced.collectSpine = pair + rcases pair with ⟨head, args⟩ + dsimp only + split + · split + · exact throw _ + · simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply bind (tryGetConst _) + intro constant + split + · simp only [pure_bind] + split + · exact fun before _ => .refl _ + · simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply bind (inductiveAppIsProp whnf _ _ _) + intro prop + apply bind (tryGetConst _) + intro constructor + cases constructor with + | none => exact fun before _ => .refl _ + | some constant => + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply bind (instantiateUnivParams constant.ty _) + intro instantiated + apply bind (instantiateProjParams whnf args _ instantiated) + intro parameterized + exact inferProjFields recursive whnf id field value prop parameterized + · exact fun before _ => .refl _ + · exact throw _ + +end Ix.Kernel.Consistency.FramesLocalState + +namespace Ix.Kernel.Consistency + +/-- Projection inference is discharged by the same smaller inference table +and direct reduction contract as the rest of the production inference body. -/ +theorem infer_framesLocalState_of_whnf {methods : Methods .anon} + (recursive : ∀ term, FramesLocalState (methods.infer term)) + (whnf : ∀ term, FramesLocalState ((RecM.whnf term).run methods)) + (conversion : ∀ left right, FramesLocalState (methods.isDefEq left right)) + (term : KExpr .anon) : FramesLocalState ((RecM.infer term).run methods) := + infer_framesLocalState recursive whnf conversion (FramesLocalState.inferProj recursive whnf) term + +end Ix.Kernel.Consistency + diff --git a/Ix/Kernel/Verify/IngressState.lean b/Ix/Kernel/Verify/IngressState.lean new file mode 100644 index 000000000..ebf5ae6c4 --- /dev/null +++ b/Ix/Kernel/Verify/IngressState.lean @@ -0,0 +1,484 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Ingress + +/-! +# Exact state effects of anonymous ingress + +Conversion and publication may change loaded declarations, block membership +and intern tables. Every other checker-owned environment field, including +all inference and reduction caches and the fresh-variable counter, is +preserved on both success and partial failure. The proof follows the actual +finite conversion loops, their scratch caches and cyclic-sharing rejection. + +Source interpretation, address integrity and finite intern collision bounds +remain separate semantic obligations. +-/ + +namespace Ix.Kernel + +/-- Ingress owns the loaded declarations, block index and intern table. -/ +def KEnv.IngressFrame (before after : AnonEnv) : Prop := + ∃ consts blocks intern, after = {before with consts, blocks, intern} + +namespace KEnv.IngressFrame + +theorem refl (state : AnonEnv) : KEnv.IngressFrame state state := + ⟨state.consts, state.blocks, state.intern, rfl⟩ + +theorem trans {before middle after : AnonEnv} + (first : KEnv.IngressFrame before middle) (second : KEnv.IngressFrame middle after) : KEnv.IngressFrame before after := by + obtain ⟨consts, blocks, intern, first⟩ := first + obtain ⟨newConsts, newBlocks, newIntern, second⟩ := second + refine ⟨newConsts, newBlocks, newIntern, ?_⟩ + rw [second, first] + +theorem counter {before after : AnonEnv} (frame : KEnv.IngressFrame before after) : + after.nextFVarId = before.nextFVarId := by + obtain ⟨_, _, _, rfl⟩ := frame + rfl + +theorem insert (before : AnonEnv) (id : KId .anon) (constant : KConst .anon) : + KEnv.IngressFrame before (before.insert id constant) := + ⟨_, before.blocks, before.intern, rfl⟩ + +theorem insertBlock (before : AnonEnv) (id : KId .anon) (members : Array (KId .anon)) : + KEnv.IngressFrame before (before.insertBlock id members) := + ⟨before.consts, _, before.intern, rfl⟩ + +theorem foldl (items : List α) (before : AnonEnv) (step : AnonEnv → α → AnonEnv) + (framed : ∀ state item, KEnv.IngressFrame state (step state item)) : + KEnv.IngressFrame before (items.foldl step before) := by + induction items generalizing before with + | nil => exact .refl _ + | cons item rest ih => exact (framed before item).trans (ih (step before item)) + +end KEnv.IngressFrame + +def IngressM.FramesState (action : IngressM α) : Prop := + ∀ before, match action before with + | .ok _ after | .error _ after => KEnv.IngressFrame before after + +namespace IngressM.FramesState + +theorem pure (value : α) : IngressM.FramesState (Pure.pure value) := fun _ => .refl _ +theorem throw (error : String) : IngressM.FramesState (throw error : IngressM α) := fun _ => .refl _ +theorem get : IngressM.FramesState (get : IngressM AnonEnv) := fun _ => .refl _ + +theorem modifyGet (f : AnonEnv → α × AnonEnv) + (frame : ∀ before, KEnv.IngressFrame before (f before).2) : + IngressM.FramesState (MonadStateOf.modifyGet f : IngressM α) := fun before => frame before + +theorem liftExcept (result : Except String α) : IngressM.FramesState (IngressM.liftExcept result) := by + cases result <;> first | exact pure _ | exact throw _ + +theorem bind {action : IngressM α} {next : α → IngressM β} + (first : IngressM.FramesState action) (rest : ∀ value, IngressM.FramesState (next value)) : IngressM.FramesState (action >>= next) := by + intro before + have frame := first before + change match EStateM.bind action next before with + | .ok _ after | .error _ after => KEnv.IngressFrame before after + cases run : action before with + | error error after => rw [EStateM.bind, run]; simpa only [run] using frame + | ok value after => + rw [run] at frame + rw [EStateM.bind, run] + dsimp only + have final := rest value after + cases finished : next value after <;> rw [finished] at final <;> exact frame.trans final + +theorem internE (expr : KExpr .anon) : IngressM.FramesState (IngressM.internE expr) := + fun before => ⟨before.consts, before.blocks, _, rfl⟩ + +theorem internU (level : KUniv .anon) : IngressM.FramesState (IngressM.internU level) := + fun before => ⟨before.consts, before.blocks, _, rfl⟩ + +theorem forInList (items : List α) (initial : β) (step : α → β → IngressM (ForInStep β)) + (framed : ∀ item value, IngressM.FramesState (step item value)) : IngressM.FramesState (forIn items initial step) := by + induction items generalizing initial with + | nil => exact pure _ + | cons item rest ih => + rw [List.forIn_cons] + apply bind (framed item initial) + intro next + cases next with + | done value => exact pure _ + | yield value => exact ih value + +theorem forInRange (range : Std.Legacy.Range) (initial : α) + (step : Nat → α → IngressM (ForInStep α)) + (framed : ∀ index value, IngressM.FramesState (step index value)) : IngressM.FramesState (forIn range initial step) := by + rw [Std.Legacy.Range.forIn_eq_forIn_range'] + exact forInList _ _ _ framed + +theorem forInArray (items : Array α) (initial : β) (step : α → β → IngressM (ForInStep β)) + (framed : ∀ item value, IngressM.FramesState (step item value)) : + IngressM.FramesState (forIn items initial step) := by + rcases items with ⟨items⟩ + simp only [List.forIn_toArray] + exact forInList _ _ _ framed + +theorem forInList' (items : List α) (initial : β) + (step : (item : α) → item ∈ items → β → IngressM (ForInStep β)) + (framed : ∀ item member value, IngressM.FramesState (step item member value)) : + IngressM.FramesState (forIn' items initial step) := by + induction items generalizing initial with + | nil => exact pure _ + | cons item rest ih => + rw [List.forIn'_cons] + apply bind (framed item (by simp) initial) + intro next + cases next with + | done value => exact pure _ + | yield value => exact ih value _ (fun _ _ _ => framed _ _ _) + +theorem forInRange' (range : Std.Legacy.Range) (initial : α) + (step : (index : Nat) → index ∈ range → α → IngressM (ForInStep α)) + (framed : ∀ index member value, IngressM.FramesState (step index member value)) : + IngressM.FramesState (forIn' range initial step) := by + rw [Std.Legacy.Range.forIn'_eq_forIn'_range'] + exact forInList' _ _ _ (fun _ _ _ => framed _ _ _) + +theorem ingressUnivTree (root : Ixon.Univ) : IngressM.FramesState (_root_.Ix.Kernel.ingressUnivTree root) := by + unfold _root_.Ix.Kernel.ingressUnivTree + apply bind (forInRange _ _ _ ?_) + · intro state + dsimp only + split + · exact fun _ => .refl _ + · split + · exact pure _ + · exact throw _ + · intro index pair + rcases pair with ⟨stack, values⟩ + dsimp only + split + · exact pure _ + · generalize stack.back! = frame + cases frame with + | process level => + cases level <;> first + | exact pure _ + | exact bind (internU _) (fun _ => pure _) + | succ | max | imax => exact bind (internU _) (fun _ => pure _) + +end IngressM.FramesState + +def ConvM.FramesState (action : ConvM α) : Prop := ∀ memo, IngressM.FramesState (action.run memo) + +namespace ConvM.FramesState + +theorem pure (value : α) : ConvM.FramesState (Pure.pure value) := by + intro memo + exact IngressM.FramesState.pure _ + +theorem throw (error : String) : ConvM.FramesState (throw error : ConvM α) := by + intro memo + exact IngressM.FramesState.throw _ + +theorem get : ConvM.FramesState (get : ConvM ConvState) := by + intro memo + exact IngressM.FramesState.pure _ + +theorem modify (f : ConvState → ConvState) : ConvM.FramesState (_root_.modify f : ConvM PUnit) := by + intro memo + exact IngressM.FramesState.pure _ + +theorem bind {action : ConvM α} {next : α → ConvM β} + (first : ConvM.FramesState action) (rest : ∀ value, ConvM.FramesState (next value)) : + ConvM.FramesState (action >>= next) := by + intro memo + simp only [StateT.run_bind] + exact IngressM.FramesState.bind (first memo) (fun pair => rest pair.1 pair.2) + +theorem lift {action : IngressM α} (frame : IngressM.FramesState action) : + ConvM.FramesState (monadLift action : ConvM α) := by + intro memo + simp only [StateT.run_monadLift] + exact IngressM.FramesState.bind frame (fun _ => IngressM.FramesState.pure _) + +theorem forInList (items : List α) (initial : β) (step : α → β → ConvM (ForInStep β)) + (framed : ∀ item value, ConvM.FramesState (step item value)) : ConvM.FramesState (forIn items initial step) := by + induction items generalizing initial with + | nil => exact pure _ + | cons item rest ih => + rw [List.forIn_cons] + apply bind (framed item initial) + intro next + cases next with + | done value => exact pure _ + | yield value => exact ih value + +theorem forInRange (range : Std.Legacy.Range) (initial : α) + (step : Nat → α → ConvM (ForInStep α)) + (framed : ∀ index value, ConvM.FramesState (step index value)) : ConvM.FramesState (forIn range initial step) := by + rw [Std.Legacy.Range.forIn_eq_forIn_range'] + exact forInList _ _ _ framed + +theorem forInArray (items : Array α) (initial : β) (step : α → β → ConvM (ForInStep β)) + (framed : ∀ item value, ConvM.FramesState (step item value)) : ConvM.FramesState (forIn items initial step) := by + rcases items with ⟨items⟩ + simp only [List.forIn_toArray] + exact forInList _ _ _ framed + +theorem ingressUnivIdx (ctx : IngressCtx) (index : UInt64) : + ConvM.FramesState (_root_.Ix.Kernel.ingressUnivIdx ctx index) := by + unfold _root_.Ix.Kernel.ingressUnivIdx + apply bind get + intro memo + split + · exact pure _ + · split + · apply bind (lift (IngressM.FramesState.ingressUnivTree _)) + intro level + exact bind (modify _) (fun _ => pure _) + · exact fun memo before => .refl _ + +theorem ingressUnivArgs (ctx : IngressCtx) (indices : Array UInt64) : + ConvM.FramesState (_root_.Ix.Kernel.ingressUnivArgs ctx indices) := by + unfold _root_.Ix.Kernel.ingressUnivArgs + apply bind (forInArray _ _ _ ?_) + · intro result + exact pure _ + · intro index state + exact bind (ingressUnivIdx ctx index) (fun _ => pure _) + +theorem ingressExpr (env : Ixon.Env) (ctx : IngressCtx) (root : Ixon.Expr) : + ConvM.FramesState (_root_.Ix.Kernel.ingressExpr env ctx root) := by + unfold _root_.Ix.Kernel.ingressExpr + apply bind (forInRange _ _ _ ?_) + · intro state + dsimp only + split + · exact fun _ _ => .refl _ + · split + · split + · exact fun _ _ => .refl _ + · exact pure _ + · exact throw _ + · intro index state + rcases state with ⟨stack, values, active⟩ + dsimp only + split + · exact pure _ + · generalize stack.back! = frame + cases frame with + | process expr => + cases expr with + | share idx => + apply bind get + intro memo + split + · exact pure _ + · split + · split + · exact fun _ _ => .refl _ + · exact pure _ + · exact fun _ _ => .refl _ + | var idx => exact bind (lift (IngressM.FramesState.internE _)) (fun _ => pure _) + | sort idx => + exact bind (ingressUnivIdx ctx idx) fun _ => + bind (lift (IngressM.FramesState.internE _)) (fun _ => pure _) + | ref idx levels | recur idx levels => + dsimp only + split + · exact bind (ingressUnivArgs ctx levels) fun _ => + bind (lift (IngressM.FramesState.internE _)) (fun _ => pure _) + · exact fun _ _ => .refl _ + | nat idx => + dsimp only + split + · split + · exact bind (lift (IngressM.FramesState.internE _)) (fun _ => pure _) + · exact fun _ _ => .refl _ + · exact fun _ _ => .refl _ + | str idx => + dsimp only + split + · split + · split + · exact bind (lift (IngressM.FramesState.internE _)) (fun _ => pure _) + · exact fun _ _ => .refl _ + · exact fun _ _ => .refl _ + · exact fun _ _ => .refl _ + | prj idx field value => + dsimp only + split + · exact pure _ + · exact fun _ _ => .refl _ + | app | lam | all | letE => exact pure _ + | appDone | lamDone | allDone | letDone | prjDone => + exact bind (lift (IngressM.FramesState.internE _)) (fun _ => pure _) + | cacheShare idx => exact bind (modify _) (fun _ => pure _) + +end ConvM.FramesState + +namespace KEnv.IngressFrame + +theorem insertEntriesState (before : AnonEnv) (entries : Array Entry) : + KEnv.IngressFrame before (_root_.Ix.Kernel.insertEntriesState before entries) := + foldl _ _ _ (fun state entry => insert state entry.1 entry.2) + +theorem insertMutsEntriesState (before : AnonEnv) (entries : Array Entry) : + KEnv.IngressFrame before (_root_.Ix.Kernel.insertMutsEntriesState before entries) := by + unfold _root_.Ix.Kernel.insertMutsEntriesState + dsimp only + split + · exact (insertBlock _ _ _).trans (insertEntriesState _ _) + · exact insertEntriesState _ _ + +end KEnv.IngressFrame + +namespace IngressM.FramesState + +theorem guardReserved (entries : Array Entry) : + IngressM.FramesState (_root_.Ix.Kernel.guardReserved entries) := by + unfold _root_.Ix.Kernel.guardReserved + apply bind (forInArray _ _ _ ?_) + · intro _; exact pure _ + · intro entry state + rcases entry with ⟨id, constant⟩ + dsimp only + split <;> exact fun _ => .refl _ + +theorem insertStandaloneEntries (entries : Array Entry) : + IngressM.FramesState (_root_.Ix.Kernel.insertStandaloneEntries entries) := by + unfold _root_.Ix.Kernel.insertStandaloneEntries + apply bind (guardReserved entries) + intro _ + apply modifyGet + intro before + dsimp only + rw [← Array.foldl_toList] + exact KEnv.IngressFrame.foldl _ _ _ fun state entry => + (KEnv.IngressFrame.insert state entry.1 entry.2).trans + (KEnv.IngressFrame.insertBlock _ _ _) + +theorem insertMutsEntries (entries : Array Entry) : + IngressM.FramesState (_root_.Ix.Kernel.insertMutsEntries entries) := by + unfold _root_.Ix.Kernel.insertMutsEntries + exact bind (guardReserved entries) fun _ => modifyGet _ fun before => + KEnv.IngressFrame.insertMutsEntriesState before entries + +theorem ingressDefnAnon (env : Ixon.Env) (defn : Ixon.Definition) + (id : KId .anon) (constant : Ixon.Constant) (block : KId .anon) + (mutCtx : Array (KId .anon)) (hints : Option Lean.ReducibilityHints) : + IngressM.FramesState (_root_.Ix.Kernel.ingressDefnAnon env defn id constant block mutCtx hints) := by + unfold _root_.Ix.Kernel.ingressDefnAnon + apply bind (ConvM.FramesState.ingressExpr _ _ _ {}) + intro typed + exact bind (ConvM.FramesState.ingressExpr _ _ _ typed.2) (fun _ => pure _) + +theorem ingressRecursorAnon (env : Ixon.Env) (recursor : Ixon.Recursor) + (id : KId .anon) (constant : Ixon.Constant) (block : KId .anon) + (mutCtx : Array (KId .anon)) : + IngressM.FramesState (_root_.Ix.Kernel.ingressRecursorAnon env recursor id constant block mutCtx) := by + unfold _root_.Ix.Kernel.ingressRecursorAnon + apply bind (ConvM.FramesState.ingressExpr _ _ _ {}) + intro typed + apply bind (forInArray _ _ _ ?_) + · intro _; exact pure _ + · intro rule state + exact bind (ConvM.FramesState.ingressExpr _ _ _ _) (fun _ => pure _) + +theorem ingressAnonInductive (env : Ixon.Env) (ind : Ixon.Inductive) + (id : KId .anon) (constant : Ixon.Constant) (block : KId .anon) + (index : UInt64) (ctorAddrs : Array Address) (mutCtx : Array (KId .anon)) : + IngressM.FramesState + (_root_.Ix.Kernel.ingressAnonInductive env ind id constant block index ctorAddrs mutCtx) := by + unfold _root_.Ix.Kernel.ingressAnonInductive + split + · exact fun _ => .refl _ + · apply bind (ConvM.FramesState.ingressExpr _ _ _ {}) + intro typed + apply bind (forInRange' _ _ _ ?_) + · intro _; exact pure _ + · intro position member state + exact bind (ConvM.FramesState.ingressExpr _ _ _ _) (fun _ => pure _) + +theorem ingressAnonStandalone (env : Ixon.Env) (addr : Address) (constant : Ixon.Constant) : + IngressM.FramesState (_root_.Ix.Kernel.ingressAnonStandalone env addr constant) := by + unfold _root_.Ix.Kernel.ingressAnonStandalone + dsimp only + split + · exact bind (ingressDefnAnon _ _ _ _ _ _ _) fun entries => + bind (insertStandaloneEntries entries) fun _ => pure _ + · exact bind (ingressRecursorAnon _ _ _ _ _ _) fun entries => + bind (insertStandaloneEntries entries) fun _ => pure _ + · apply bind (ConvM.FramesState.ingressExpr _ _ _ {}) + intro typed + simp only [pure_bind] + exact bind (insertStandaloneEntries _) fun _ => pure _ + · apply bind (ConvM.FramesState.ingressExpr _ _ _ {}) + intro typed + simp only [pure_bind] + exact bind (insertStandaloneEntries _) fun _ => pure _ + · exact fun _ => .refl _ + +theorem prepareAnonBlock (env : Ixon.Env) (constant : Ixon.Constant) (addr : Address) : + IngressM.FramesState (_root_.Ix.Kernel.prepareAnonBlock env constant addr) := by + unfold _root_.Ix.Kernel.prepareAnonBlock + split + · dsimp only + apply bind (forInRange' _ _ _ ?_) + · intro _; exact pure _ + · intro index member state + split + · apply bind + · split <;> exact fun _ => .refl _ + · intro _ + exact bind (ingressDefnAnon _ _ _ _ _ _ _) (fun _ => pure _) + · apply bind + · split <;> exact fun _ => .refl _ + · intro _ + exact bind (ingressRecursorAnon _ _ _ _ _ _) (fun _ => pure _) + · apply bind + · split <;> exact fun _ => .refl _ + · intro _ + apply bind (forInRange' _ _ _ ?_) + · intro _ + exact bind (ingressAnonInductive _ _ _ _ _ _ _ _) (fun _ => pure _) + · intro position present state + split <;> exact fun _ => .refl _ + · exact fun _ => .refl _ + +theorem ingressAnonBlockWithTrace (env : Ixon.Env) (constant : Ixon.Constant) (addr : Address) : + IngressM.FramesState (_root_.Ix.Kernel.ingressAnonBlockWithTrace env constant addr) := by + unfold _root_.Ix.Kernel.ingressAnonBlockWithTrace + exact bind (prepareAnonBlock env constant addr) fun trace => + bind (insertMutsEntries trace.allEntries) fun _ => pure _ + +theorem ingressAnonBlock (env : Ixon.Env) (constant : Ixon.Constant) (addr : Address) : + IngressM.FramesState (_root_.Ix.Kernel.ingressAnonBlock env constant addr) := by + unfold _root_.Ix.Kernel.ingressAnonBlock + exact bind (ingressAnonBlockWithTrace env constant addr) fun _ => pure _ + +/-- The actual lazy callback changes only ingress-owned fields, for every +input and both outcomes. No callback-specific frame is assumed. -/ +theorem ingressAnonAddrShallow (env : Ixon.Env) (addr : Address) (verify : Bool) : + IngressM.FramesState (_root_.Ix.Kernel.ingressAnonAddrShallow env addr verify) := by + unfold _root_.Ix.Kernel.ingressAnonAddrShallow + apply bind (liftExcept _) + intro found + cases found with + | none => exact pure _ + | some constant => + dsimp only + split + · apply bind get + intro before + split + · exact pure _ + · apply bind (liftExcept _) + intro block + cases block with + | none => exact fun _ => .refl _ + | some blockConstant => exact bind (ingressAnonBlock _ _ _) fun _ => pure _ + · exact bind (ingressAnonStandalone _ _ _) fun _ => pure _ + +end IngressM.FramesState + +end Ix.Kernel diff --git a/Tests/Ix/Kernel/IngressState.lean b/Tests/Ix/Kernel/IngressState.lean new file mode 100644 index 000000000..a5e470018 --- /dev/null +++ b/Tests/Ix/Kernel/IngressState.lean @@ -0,0 +1,72 @@ +module + +public import LSpec +public import Ix.Kernel.Ingress + +/-! Cyclic sharing and finite conversion regressions for anonymous ingress. -/ + +namespace Tests.Kernel.IngressState + +open LSpec Ix.Kernel + +private def context (sharing : Array Ixon.Expr) : IngressCtx := + { sharing, refs := #[], univs := #[.zero], mutCtx := #[] } + +private def cacheKey : Address × Address := + (Address.blake3 "ingress-frame-key".toUTF8, emptyCtxAddr) + +private def cachedType : KExpr .anon := .mkSort .mkZero + +private def before : AnonEnv := + { nextFVarId := 77 + inferCache := ({} : Std.HashMap _ _).insert cacheKey cachedType + inferOnlyCache := ({} : Std.HashMap _ _).insert cacheKey cachedType + whnfCache := ({} : Std.HashMap _ _).insert cacheKey cachedType } + +private def keptState (after : AnonEnv) : Bool := + after.nextFVarId == 77 && after.inferCache[cacheKey]? == some cachedType && + after.inferOnlyCache[cacheKey]? == some cachedType && after.whnfCache[cacheKey]? == some cachedType + +private def rejects (root : Ixon.Expr) (sharing : Array Ixon.Expr) (message : String) : Bool := + match (ingressExpr {} (context sharing) root).run {} before with + | .error error after => error == message && keptState after + | .ok .. => false + +private def accepts (root : Ixon.Expr) (sharing : Array Ixon.Expr) (expected : KExpr .anon) : Bool := + match (ingressExpr {} (context sharing) root).run {} before with + | .ok (term, _) after => term == expected && keptState after + | .error .. => false + +private def sharingTests : TestSeq := + test "ingress: reject direct sharing cycle and preserve checker state" + (rejects (.share 0) #[.share 0] "cyclic Share index 0") + ++ test "ingress: reject mutual sharing cycle" + (rejects (.share 0) #[.share 1, .share 0] "cyclic Share index 0") + ++ test "ingress: reject nested cycle after partial interning" + (rejects (.share 0) #[.app (.var 0) (.share 0)] "cyclic Share index 0") + ++ test "ingress: forward and repeated sharing remain accepted" + (accepts (.app (.share 0) (.share 0)) #[.share 1, .var 0] + (.mkApp (.mkVar 0 ()) (.mkVar 0 ()))) + ++ test "ingress: unused cyclic sharing does not affect a valid root" + (accepts (.var 0) #[.share 0] (.mkVar 0 ())) + ++ test "ingress: invalid sharing index remains an error" + (rejects (.share 2) #[.var 0] "invalid Share index 2") + +private def conversionTests : TestSeq := + test "ingress: nested binders and lets fit the computed work bound" + (accepts (.leanLam (.sort 0) (.letE false (.sort 0) (.var 0) (.var 1))) #[] + (.mkLam () () cachedType (.mkLet () cachedType (.mkVar 0 ()) (.mkVar 1 ()) false))) + ++ test "ingress: deep source work count uses an explicit stack" + (let root := (List.range 2048).foldl (fun body _ => Ixon.Expr.leanLam (.sort 0) body) (.var 0) + match (ingressExpr {} (context #[]) root).run {} before with + | .ok (term, _) after => term.lbr == 0 && keptState after + | .error .. => false : Bool) + ++ test "ingress: universe traversal preserves simplification and checker state" + (let level : Ixon.Univ := .imax (.succ (.var 0)) (.max .zero (.succ .zero)) + match ingressUnivTree level before with + | .ok result after => result == ixonUnivToK level && keptState after + | .error .. => false : Bool) + +public def suite : List TestSeq := [sharingTests, conversionTests] + +end Tests.Kernel.IngressState diff --git a/Tests/Main.lean b/Tests/Main.lean index 1837ab852..d73af7625 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -47,6 +47,7 @@ import Tests.Ix.Kernel.InitScale import Tests.Ix.Kernel.TutorialTc import Tests.Ix.Kernel.CheckerRoundtrip import Tests.Ix.Kernel.IngressMetaTests +import Tests.Ix.Kernel.IngressState import Tests.Ix.Kernel.Pins import Tests.Ix.Kernel.AccelDiff import Tests.Ix.CanonM @@ -111,7 +112,8 @@ def primarySuites : Std.HashMap String (List LSpec.TestSeq) := .ofList [ ++ Tests.Kernel.Fixtures.suite ++ Tests.Kernel.WhnfTests.suite ++ Tests.Kernel.InferDefEq.suite ++ Tests.Kernel.CheckTests.suite ++ Tests.Kernel.Consistency.suite - ++ Tests.Kernel.Roundtrip.unitTests ++ Tests.Kernel.IngressMeta.unitTests), + ++ Tests.Kernel.Roundtrip.unitTests ++ Tests.Kernel.IngressMeta.unitTests + ++ Tests.Kernel.IngressState.suite), ] /-- Ignored test suites - expensive, run only when explicitly requested. These require significant RAM -/ diff --git a/crates/kernel/src/ingress.rs b/crates/kernel/src/ingress.rs index 76ddbc869..80860391d 100644 --- a/crates/kernel/src/ingress.rs +++ b/crates/kernel/src/ingress.rs @@ -649,6 +649,77 @@ fn univ_args_decor_at( // Expression ingress (iterative) // ============================================================================ +/// Reject cycles in the reachable sharing graph before the converter's +/// transparent Share and application-spine loops can revisit an expansion. +/// Completed expression pointers avoid rewalking ordinary in-memory DAGs. +fn validate_acyclic_sharing( + root: &Arc, + sharing: &[Arc], +) -> Result<(), String> { + if sharing.is_empty() { + return Ok(()); + } + enum Frame<'a> { + Enter(&'a Arc), + FinishExpr(usize), + FinishShare(u64), + } + let mut stack = vec![Frame::Enter(root)]; + let mut complete = FxHashSet::default(); + let mut active = FxHashSet::default(); + while let Some(frame) = stack.pop() { + match frame { + Frame::FinishExpr(key) => { + complete.insert(key); + }, + Frame::FinishShare(index) => { + active.remove(&index); + }, + Frame::Enter(expr) => { + let key = Arc::as_ptr(expr) as usize; + if complete.contains(&key) { + continue; + } + stack.push(Frame::FinishExpr(key)); + match expr.as_ref() { + IxonExpr::Share(index) => { + let expansion = sharing + .get( + usize::try_from(*index) + .map_err(|_e| format!("Share index {index} exceeds usize"))?, + ) + .ok_or_else(|| format!("invalid Share index {index}"))?; + if !active.insert(*index) { + return Err(format!("cyclic Share index {index}")); + } + stack.push(Frame::FinishShare(*index)); + stack.push(Frame::Enter(expansion)); + }, + IxonExpr::App(left, right) + | IxonExpr::Lam(_, left, right) + | IxonExpr::All(_, _, left, right) => { + stack.push(Frame::Enter(right)); + stack.push(Frame::Enter(left)); + }, + IxonExpr::Let(_, ty, value, body) => { + stack.push(Frame::Enter(body)); + stack.push(Frame::Enter(value)); + stack.push(Frame::Enter(ty)); + }, + IxonExpr::Prj(_, _, value) => stack.push(Frame::Enter(value)), + IxonExpr::Sort(_) + | IxonExpr::Var(_) + | IxonExpr::Ref(_, _) + | IxonExpr::Rec(_, _) + | IxonExpr::Nat(_) + | IxonExpr::Str(_) => {}, + } + }, + } + } + Ok(()) +} + enum ExprFrame { Process { expr: Arc, @@ -725,6 +796,7 @@ fn ingress_expr( stats: &mut ConvertStats, ) -> Result, String> { bump_convert_stat!(stats, expr_roots); + validate_acyclic_sharing(root_expr, ctx.sharing)?; let mut stack: Vec> = vec![ExprFrame::Process { expr: root_expr.clone(), arena_idx: root_arena }]; let mut values: Vec> = Vec::new(); @@ -4861,6 +4933,96 @@ mod tests { use ix_common::env::{self, BinderInfo}; use ixon::metadata::CallSiteEntry; + fn ingress_shared_anon( + root: &Arc, + sharing: &[Arc], + ) -> Result, String> { + let names = FxHashMap::default(); + let ctx = Ctx:: { + sharing, + refs: &[], + univs: &[], + mut_ctx: vec![], + arena: &DEFAULT_ARENA, + names: &names, + lvls: vec![], + univ_patches: FxHashMap::default(), + meta_univs: &[], + synth_counter: Cell::new(0), + }; + ingress_expr( + root, + 0, + &ctx, + &mut InternTable::new(), + &IxonEnv::new(), + &mut ExprCache::default(), + &mut UnivCache::default(), + &mut ConvertStats::default(), + ) + } + + #[test] + fn ingress_sharing_rejects_self_cycle() { + let share = IxonExpr::share(0); + assert_eq!( + ingress_shared_anon(&share, std::slice::from_ref(&share)).unwrap_err(), + "cyclic Share index 0" + ); + } + + #[test] + fn ingress_sharing_rejects_mutual_cycle() { + assert_eq!( + ingress_shared_anon( + &IxonExpr::share(0), + &[IxonExpr::share(1), IxonExpr::share(0)] + ) + .unwrap_err(), + "cyclic Share index 0" + ); + } + + #[test] + fn ingress_sharing_rejects_cycle_below_application() { + let expansion = IxonExpr::app(IxonExpr::var(0), IxonExpr::share(0)); + assert_eq!( + ingress_shared_anon(&IxonExpr::share(0), &[expansion]).unwrap_err(), + "cyclic Share index 0" + ); + } + + #[test] + fn ingress_sharing_accepts_forward_and_repeated_references() { + let root = IxonExpr::app(IxonExpr::share(0), IxonExpr::share(0)); + let result = + ingress_shared_anon(&root, &[IxonExpr::share(1), IxonExpr::var(0)]) + .unwrap(); + assert_eq!( + result, + KExpr::::app(KExpr::var(0, ()), KExpr::var(0, ())) + ); + } + + #[test] + fn ingress_sharing_ignores_unreachable_cycles_and_memoizes_dags() { + let mut root = IxonExpr::var(0); + for _ in 0..28 { + root = IxonExpr::app(root.clone(), root); + } + let result = ingress_shared_anon(&root, &[IxonExpr::share(0)]).unwrap(); + assert_eq!(result.lbr(), 1); + } + + #[test] + fn ingress_sharing_rejects_out_of_range_reference() { + assert_eq!( + ingress_shared_anon(&IxonExpr::share(2), &[IxonExpr::var(0)]) + .unwrap_err(), + "invalid Share index 2" + ); + } + fn mk_name(s: &str) -> Name { let mut n = Name::anon(); for part in s.split('.') { diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index 1a25849d7..f8773818f 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -156,14 +156,29 @@ increasing sequence of strongly inaccessible cardinals. and failure. The let trace recovers `LocalContextValues` after validation; the inference cache shell preserves caller contexts whenever its uncached body does. `LocalStateInvariant` derives freshness from the live identifier - bound, and `infer_framesLocalState` preserves it for all constructors and + bound, and `infer_framesLocalState_of_whnf` preserves it for all constructors and both policies, including hits, writes and failure states. Recursive - inference, reduction, conversion and projection remain contracts of the - mutual execution proof. The installed production lazy loader must establish - its counter-preservation contract. `TcM.InternOnly.instantiateUnivParams` + inference, reduction and conversion remain contracts of the mutual execution + proof. Projection inference's parameter/field loops, Prop checks and lookups + derive their state effects from the same recursive inference and reduction + contracts. `TcM.InternOnly.instantiateUnivParams` proves the actual universe walker's exact intern-table-only effect without collision assumptions; the named inference-policy proof shares this result. These structural frames do not establish computed-type or cache semantics. +- `IngressM.FramesState.ingressAnonAddrShallow` proves that the actual anonymous + loader changes only declarations, block membership and intern tables on + either outcome. Conversion, lazy lookup and block publication preserve every + checker-owned field, including the fresh-variable counter and all caches. + `LocalStateInvariant.newLazyAnon` consequently establishes the structural + invariant for the concrete driver without assuming its loader's effect. + Lean's expression and universe converters now use finite range loops whose + work counts come from the source syntax. An active sharing set rejects + cycles; the Rust converter checks the reachable sharing graph before its + traversal. Forward references and unused cyclic entries remain accepted. + Regressions cover cycles, partial-failure state, repeated/forward sharing, + deep inputs and universe simplification. The state proof does not establish + conversion's semantic reading or prove that the computed bound suffices for + every acyclic input; those remain distinct refinement obligations. - `InferenceCacheInvariant` covers every entry in both production maps, with separate full-checking and inference-only meanings. Hits obtain stored facts directly; each insertion establishes its own fact and preserves all other From 76112e2bfec6f621933e6f45a866c7b576c4c5e7 Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 10:19:22 -0400 Subject: [PATCH 29/30] Close local-state preservation through the recursive checker Prove that public inference, reduction and conversion preserve the caller's local declarations and installed loader on success and failure, while maintaining coherent lookup and a monotone fresh-variable bound. Induction on production's finite method tables discharges all recursive frame premises. Cover the actual reduction and conversion helpers, bounded workers, binder and let scopes, speculation, cache updates and cleanup. Add checked proof composition and register exact full-dependency allowances for all 279 new theorem roots. No production or Rust implementation changes. Validation: strict IxKernelConsistency build (717 audited roots), full check-kernel --with-model gate, and git diff --check pass. General semantic checker soundness and the remaining IxVM milestones are still open. --- Ix/Kernel/Verify/Consistency.lean | 18 +- Ix/Kernel/Verify/Consistency/Audit.lean | 300 +++++- .../Verify/Consistency/DefEqLocalState.lean | 894 +++++++++++++++++ .../Verify/Consistency/LocalStateEffects.lean | 315 ++++++ .../Verify/Consistency/LocalStateTactic.lean | 152 +++ .../Consistency/RecursiveLocalState.lean | 88 ++ .../Verify/Consistency/WhnfLocalState.lean | 896 ++++++++++++++++++ docs/kernel-verification.md | 16 +- 8 files changed, 2665 insertions(+), 14 deletions(-) create mode 100644 Ix/Kernel/Verify/Consistency/DefEqLocalState.lean create mode 100644 Ix/Kernel/Verify/Consistency/LocalStateEffects.lean create mode 100644 Ix/Kernel/Verify/Consistency/LocalStateTactic.lean create mode 100644 Ix/Kernel/Verify/Consistency/RecursiveLocalState.lean create mode 100644 Ix/Kernel/Verify/Consistency/WhnfLocalState.lean diff --git a/Ix/Kernel/Verify/Consistency.lean b/Ix/Kernel/Verify/Consistency.lean index 3ffff8e47..02a765d47 100644 --- a/Ix/Kernel/Verify/Consistency.lean +++ b/Ix/Kernel/Verify/Consistency.lean @@ -25,6 +25,7 @@ import Ix.Kernel.Verify.Consistency.LocalScope import Ix.Kernel.Verify.Consistency.InferenceLocalState import Ix.Kernel.Verify.Consistency.ProjectionLocalState import Ix.Kernel.Verify.Consistency.IngressLocalState +import Ix.Kernel.Verify.Consistency.RecursiveLocalState import Ix.Kernel.Verify.Consistency.Application import Ix.Kernel.Verify.Consistency.BinderInference import Ix.Kernel.Verify.Consistency.RecursiveCache @@ -106,16 +107,25 @@ requiring equal hash-map representations. Let traces recover the modeled context present after validation; the inference cache shell preserves caller contexts whenever the uncached branch does. A maintained structural invariant derives fresh opening from the counter bound. Every uncached constructor, -both cache partitions and the final write preserve it on success and failure, -under the recursive inference, reduction and conversion contracts. Projection +both cache partitions and the final write preserve it on success and failure. +Projection inference's parameter and dependent-field loops, Prop checks and lookups preserve the same state from those recursive inference and reduction contracts. +The full reduction and conversion layers now discharge their direct helpers, +including finite workers, legacy depth restoration, binder/let scopes, +speculation, cache updates and cleanup. Induction on the actual `methodsN` +depth closes all six structural contracts without recursive-method premises. +Public inference, conversion, WHNF and sort/forall exposure select the proved +table from current fuel and preserve the caller's local declarations, monotone +fresh-variable bound and installed loader on either outcome. Universe instantiation unconditionally changes only the intern table. The actual anonymous loader preserves all checker-owned environment fields, including the counter and caches, through conversion, declaration publication and errors. The lazy driver's initial state establishes the structural local -invariant without a loader-effect assumption. The general mutual proof must -still supply the recursive and semantic contracts. +invariant without a loader-effect assumption. The general mutual semantic proof +must still establish the meaning of inference, reduction, conversion, cache +entries and loaded declarations; structural state preservation alone does not +establish those facts. The safe-definition guard excludes self-reference for both modes and arbitrary universe arities. Successful definition-block execution computes an order of diff --git a/Ix/Kernel/Verify/Consistency/Audit.lean b/Ix/Kernel/Verify/Consistency/Audit.lean index 25a5d199f..fca836cf8 100644 --- a/Ix/Kernel/Verify/Consistency/Audit.lean +++ b/Ix/Kernel/Verify/Consistency/Audit.lean @@ -17,6 +17,7 @@ import Ix.Kernel.Verify.Consistency.LocalScope import Ix.Kernel.Verify.Consistency.InferenceLocalState import Ix.Kernel.Verify.Consistency.ProjectionLocalState import Ix.Kernel.Verify.Consistency.IngressLocalState +import Ix.Kernel.Verify.Consistency.RecursiveLocalState import Ix.Kernel.Verify.Audit.Basic /-! Exact full-dependency boundaries for the direct model-refinement roots. @@ -366,6 +367,297 @@ private def ingressOperationalRoots : Array Lean.Name := #[ ``LoaderCounterMonotone.ingressAnonAddrShallow ] +private def recursiveStateFrameRoots : Array Lean.Name := #[ + ``FramesLocalState.ofWF, + ``FramesLocalState.tryCatch, + ``FramesLocalState.tryFinally, + ``FramesLocalState.map, + ``FramesLocalState.modifyGet, + ``FramesLocalState.tick, + ``FramesLocalState.stepTrace, + ``FramesLocalState.bumpStats, + ``FramesLocalState.isLetVar, + ``FramesLocalState.tryGetBlock, + ``FramesLocalState.runBounded, + ``FramesLocalState.forInList, + ``FramesLocalState.forInArray, + ``FramesLocalState.withCheapRecursionDepth, + ``FramesLocalState.whnfRec, + ``FramesLocalState.whnfModeRec, + ``FramesLocalState.whnfCoreFlagsRec, + ``FramesLocalState.inferOnlyRec, + ``FramesLocalState.tryOptional, + ``FramesLocalState.pureRec, + ``FramesLocalState.throwRec, + ``FramesLocalState.throwExceptRec, + ``FramesLocalState.getRec, + ``FramesLocalState.liftRec, + ``FramesLocalState.liftSelf, + ``FramesLocalState.mapRec, + ``FramesLocalState.bindRead, + ``FramesLocalState.tryProbe, + ``FramesLocalState.bindRec, + ``FramesLocalState.bindTcM, + ``FramesLocalState.tryFinallyRec, + ``FramesLocalState.tryCatchRec, + ``FramesLocalState.tryCatchExceptRec, + ``FramesLocalState.modifyRec, + ``FramesLocalState.forInListTcM, + ``FramesLocalState.isNatBinArithAddr, + ``FramesLocalState.isNatBinPredAddr, + ``FramesLocalState.boolLitValue, + ``FramesLocalState.isNatStuckRecursorAddr, + ``FramesLocalState.saveDepth, + ``FramesLocalState.enterDispatch, + ``FramesLocalState.exitDispatch, + ``FramesLocalState.callIsDefEq, + ``FramesLocalState.isNatLiteralRecursorApp, + ``FramesLocalState.natRecLiteralParts, + ``FramesLocalState.isStuckNatPredicateProbe, + ``FramesLocalState.discoverBlockInductives, + ``FramesLocalState.cacheIsRec, + ``FramesLocalState.eraseCachedIsRec, + ``FramesLocalState.isNatSuccSpine, + ``FramesLocalState.recordNatSuccStuck, + ``FramesLocalState.whnfNatReducerArg, + ``FramesLocalState.inferDecidableProp, + ``FramesLocalState.whnfWithNatSuccModeMissCharge, + ``FramesLocalState.isDefEqCall, + ``FramesLocalState.inferOnlyCall, + ``FramesLocalState.withEquiv, + ``FramesLocalState.allDefEqSpineArgsList, + ``FramesLocalState.isNatLike, + ``FramesLocalState.isNatZero, + ``FramesLocalState.isBoolTrue, + ``FramesLocalState.boolTrueReductionAllowed, + ``FramesLocalState.isDelta, + ``FramesLocalState.classifyDeltaHead, + ``FramesLocalState.isRegular, + ``FramesLocalState.defRankId, + ``FramesLocalState.rankDeltaHead, + ``FramesLocalState.allDefEqSpineArgs, + ``FramesLocalState.tryDefEqWhnfApp, + ``FramesLocalState.tryDefEqApp +] + +private def recursiveStateExprRoots : Array Lean.Name := #[ + ``FramesLocalState.lookupLetVal, + ``FramesLocalState.whnfKey, + ``FramesLocalState.mkNatSucc, + ``FramesLocalState.mkNatAdd, + ``FramesLocalState.natToConstructor, + ``FramesLocalState.evalNatOffsetLiteralFuel, + ``FramesLocalState.natOffsetFuel, + ``FramesLocalState.finishAppResult, + ``FramesLocalState.strLitListToConstructor, + ``FramesLocalState.natOffset, + ``FramesLocalState.natOffsetOrZero, + ``FramesLocalState.evalNatOffsetLiteral, + ``FramesLocalState.natOffsetDecompose, + ``FramesLocalState.natOffsetRebuild, + ``FramesLocalState.strLitToConstructor, + ``FramesLocalState.internIntLit, + ``FramesLocalState.applyIotaArg, + ``FramesLocalState.applyIotaArgs, + ``FramesLocalState.isTransientNatLiteralWork, + ``FramesLocalState.cleanupNatOffsetMajor, + ``FramesLocalState.projectDecidableFinValMinor, + ``FramesLocalState.tryReduceFinValDecidableRec, + ``FramesLocalState.tryReduceProjectionDefinition, + ``FramesLocalState.bitvecOfNatArgs, + ``FramesLocalState.charOfNatExpr, + ``FramesLocalState.tryReduceStringLiteral, + ``FramesLocalState.tryReduceString, + ``FramesLocalState.tryProjReduceTail, + ``FramesLocalState.tryProjPrepare, + ``FramesLocalState.tryProjReduce, + ``FramesLocalState.tryProjAppReduce, + ``FramesLocalState.tryProjAppReduceFinished, + ``FramesLocalState.finishStructEtaFields, + ``FramesLocalState.finishStructEtaResult, + ``FramesLocalState.verifyKSynthCandidate, + ``FramesLocalState.selectKSynthCandidate, + ``FramesLocalState.tryReduceNatSuccPeelMiss, + ``FramesLocalState.tryReduceNatSuccPeelAfterKey, + ``FramesLocalState.tryReduceNatSuccPeel, + ``FramesLocalState.tryReduceNatSuccAfterWhnf, + ``FramesLocalState.isNatSuccIhStep, + ``FramesLocalState.tryReduceNatSuccLinearRec, + ``FramesLocalState.tryReduceNatSuccIterStep, + ``FramesLocalState.tryReduceNatSuccIter, + ``FramesLocalState.tryReduceNatPredicate, + ``FramesLocalState.tryReduceNatWithSuccMode, + ``FramesLocalState.tryReduceNat, + ``FramesLocalState.tryNatOffsetStuck, + ``FramesLocalState.buildNatDecidableTrue, + ``FramesLocalState.buildNatDecidableFalse, + ``FramesLocalState.tryNormalizeIntDecidable, + ``FramesLocalState.tryQuotReduce, + ``FramesLocalState.tryEvalNatValueForPredFuel, + ``FramesLocalState.tryEvalNatValueForPred, + ``FramesLocalState.tryReduceBitvecToNat, + ``FramesLocalState.bitvecToNatExpr, + ``FramesLocalState.tryReduceBitvecUlt, + ``FramesLocalState.tryReduceBitvecLtProp, + ``FramesLocalState.tryReduceBitvec, + ``openLetWithFV_eq, + ``PreservesLocalState.openLetWithFV, + ``FramesLocalState.defEqCtxKey, + ``FramesLocalState.quickBinder, + ``FramesLocalState.tryDefEqWhnfLet, + ``FramesLocalState.tryEtaStructFields, + ``FramesLocalState.natSuccOf, + ``FramesLocalState.quickDefEq, + ``FramesLocalState.finishDefEqLazyDeltaStep, + ``FramesLocalState.trySameHeadSpineCached, + ``FramesLocalState.tryDefEqWhnfStructural, + ``FramesLocalState.isDefEqNatAfterLiteral, + ``FramesLocalState.isDefEqNat, + ``FramesLocalState.tryDefEqWhnfNat, + ``FramesLocalState.tryDefEqOffsetAfterCandidates, + ``FramesLocalState.tryDefEqOffsetAfterZeroMiss, + ``FramesLocalState.tryDefEqOffsetAfterLiteral, + ``FramesLocalState.tryDefEqOffset, + ``FramesLocalState.tryStringLitExpansion, + ``FramesLocalState.tryDefEqWhnfStringAfterGuard, + ``FramesLocalState.tryDefEqWhnfString, + ``FramesLocalState.compareEtaExpansion, + ``FramesLocalState.finishLazyDeltaReductionStep +] + +private def recursiveStateMapRoots : Array Lean.Name := #[ + ``FramesLocalState.forInRange, + ``FramesLocalState.pushLocal, + ``FramesLocalState.pushLet, + ``FramesLocalState.popLocal, + ``FramesLocalState.restoreDepthGo, + ``FramesLocalState.restoreDepth, + ``FramesLocalState.peelMajorForalls, + ``FramesLocalState.scanMajorInductiveStep, + ``FramesLocalState.scanMajorInductive, + ``FramesLocalState.getMajorInductiveId, + ``FramesLocalState.computeIsRecParamStepAfterWhnf, + ``FramesLocalState.computeIsRecParamStep, + ``FramesLocalState.computeIsRecFieldStepAfterWhnf, + ``FramesLocalState.computeIsRecFieldStep, + ``FramesLocalState.computeIsRecCtor, + ``FramesLocalState.computeIsRec, + ``FramesLocalState.computedIsRecClassify, + ``FramesLocalState.computedIsRecMiss, + ``FramesLocalState.computedIsRec, + ``FramesLocalState.isStructLike, + ``FramesLocalState.whnfWithNatSuccModePrefix, + ``FramesLocalState.trySameHeadSpine, + ``FramesLocalState.trySameHeadSpineSpeculative, + ``FramesLocalState.isUnitLikeInductive +] + +private def recursiveStateOperationalRoots : Array Lean.Name := #[ + ``FramesLocalState.unfoldConstValue, + ``FramesLocalState.tryDeltaUnfold, + ``FramesLocalState.tryReduceNativeMarker, + ``FramesLocalState.applyIotaRule, + ``FramesLocalState.tryApplyIotaCtor, + ``FramesLocalState.finishStructEtaAfterSort, + ``FramesLocalState.tryStructEtaAfterInductive, + ``FramesLocalState.tryStructEtaIota, + ``FramesLocalState.synthCtorWhenK, + ``FramesLocalState.tryIotaCtorOrStructEta, + ``FramesLocalState.tryIotaAfterCleanup, + ``FramesLocalState.tryIotaAfterMajorWhnf, + ``FramesLocalState.tryIotaWithFlags, + ``FramesLocalState.deltaUnfoldOne, + ``FramesLocalState.tryReduceDecidable, + ``FramesLocalState.tryReduceNative, + ``FramesLocalState.whnfCoreWithFlagsStep, + ``FramesLocalState.whnfCoreWithFlagsUncached, + ``FramesLocalState.whnfCoreWithFlagsNonLeaf, + ``FramesLocalState.whnfCoreWithFlags, + ``FramesLocalState.whnfCore, + ``FramesLocalState.whnfCoreForDefEq, + ``FramesLocalState.whnfNoDeltaReducersStep, + ``FramesLocalState.whnfNoDeltaImplStep, + ``FramesLocalState.whnfNoDeltaImplUncached, + ``FramesLocalState.whnfNoDeltaImplNonLeaf, + ``FramesLocalState.whnfNoDeltaImpl, + ``FramesLocalState.whnfNoDelta, + ``FramesLocalState.whnfNoDeltaForDefEq, + ``FramesLocalState.whnfWithNatSuccModeStep, + ``FramesLocalState.whnfWithNatSuccModeUncached, + ``FramesLocalState.whnfWithNatSuccModeNonLeaf, + ``FramesLocalState.whnfWithNatSuccMode, + ``FramesLocalState.whnf, + ``FramesLocalState.etaExpansionBaseLoop, + ``FramesLocalState.whnfIsBoolTrue, + ``FramesLocalState.defEqLazyDeltaStepAfterSameHeadMiss, + ``FramesLocalState.defEqLazyDeltaStepWithLeftDelta, + ``FramesLocalState.defEqLazyDeltaStepWithRightDelta, + ``FramesLocalState.defEqLazyDeltaStepWithEqualRank, + ``FramesLocalState.defEqLazyDeltaStepAfterProjectionMiss, + ``FramesLocalState.classifyPropTypeUncached, + ``FramesLocalState.isPropType, + ``FramesLocalState.tryProofIrrel, + ``FramesLocalState.isDefEqWhnfAfterUnit, + ``FramesLocalState.tryDefEqUnit, + ``FramesLocalState.isDefEqWhnfAfterStructEta, + ``FramesLocalState.tryEtaExpansionAfterGuard, + ``FramesLocalState.tryEtaExpansion, + ``FramesLocalState.tryDefEqWhnfEtaAfterGuard, + ``FramesLocalState.tryDefEqWhnfEta, + ``FramesLocalState.normalizeEtaStructSource, + ``FramesLocalState.etaExpansionBase, + ``FramesLocalState.tryEtaStructAfterTypes, + ``FramesLocalState.tryEtaStructAfterConstructor, + ``FramesLocalState.tryEtaStructAfterNormalization, + ``FramesLocalState.tryEtaStruct, + ``FramesLocalState.tryDefEqWhnfStructEta, + ``FramesLocalState.isDefEqWhnfAfterString, + ``FramesLocalState.isDefEqWhnfAfterEta, + ``FramesLocalState.isDefEqWhnfAfterNat, + ``FramesLocalState.isDefEqWhnfAfterStructural, + ``FramesLocalState.isDefEqWhnf, + ``FramesLocalState.etaExpansionBaseAfterValue, + ``FramesLocalState.etaExpansionBaseAfterProjection, + ``FramesLocalState.lazyDeltaReductionStepWithLeftDelta, + ``FramesLocalState.lazyDeltaReductionStepWithRightDelta, + ``FramesLocalState.lazyDeltaReductionStepAfterSameHeadMiss, + ``FramesLocalState.lazyDeltaReductionStepWithEqualRank, + ``FramesLocalState.lazyDeltaReductionStepWithBothDelta, + ``FramesLocalState.tryUnfoldProjApp, + ``FramesLocalState.defEqLazyDeltaStepAfterDeltaClassification, + ``FramesLocalState.defEqLazyDeltaStepAfterAcceleratorMiss, + ``FramesLocalState.defEqLazyDeltaStepAfterNatMiss, + ``FramesLocalState.defEqLazyDeltaStepAfterOffsetMiss, + ``FramesLocalState.defEqLazyDeltaStep, + ``FramesLocalState.runDefEqLazyDelta, + ``FramesLocalState.lazyDeltaReductionStepAfterActive, + ``FramesLocalState.lazyDeltaReductionStepAfterClassification, + ``FramesLocalState.lazyDeltaReductionStep, + ``FramesLocalState.lazyDeltaProjReduction, + ``FramesLocalState.tryStructuralCongruence, + ``FramesLocalState.isDefEqAfterLazyDeltaStopped, + ``FramesLocalState.isDefEqInnerAfterProofIrrelevance, + ``FramesLocalState.isDefEqInnerAfterNoDeltaPass, + ``FramesLocalState.isDefEqInnerAfterCorePass, + ``FramesLocalState.isDefEqInnerAfterStringExpansion, + ``FramesLocalState.isDefEqInnerAfterBoolTrue, + ``FramesLocalState.isDefEqInnerAfterFirstBoolGuardMiss, + ``FramesLocalState.isDefEqInnerAfterQuick, + ``FramesLocalState.isDefEqInner, + ``FramesLocalState.isDefEqAfterRootCacheMiss, + ``FramesLocalState.isDefEqAfterDirectCacheMiss, + ``FramesLocalState.isDefEq, + ``MethodsLocalState.methodsN, + ``FramesLocalState.runRec, + ``TcM.whnf_framesLocalState, + ``TcM.whnfCore_framesLocalState, + ``TcM.whnfNoDelta_framesLocalState, + ``TcM.infer_framesLocalState, + ``TcM.isDefEq_framesLocalState, + ``TcM.ensureSort_framesLocalState, + ``TcM.ensureForall_framesLocalState +] + /-- Production roots must not acquire a checker-soundness assumption or invoke the independent certificate validator to establish acceptance. -/ private def forbiddenProduction : Array Lean.Name := #[ @@ -446,22 +738,22 @@ def roots : Array RootAllowance := #[ ] ++ (stringListRoots ++ #[``LocalValues.pushLet_extends, ``LocalValues.pushBinder_lifts, ``LocalValues.Below.pushLet]).map (fun root => { root, standardAxioms := #[``propext], forbiddenDependencies := forbiddenProduction -}) ++ (localIndexRoots ++ localScopeFrameRoots ++ localStateFrameRoots ++ ingressFrameRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ +}) ++ (localIndexRoots ++ localScopeFrameRoots ++ localStateFrameRoots ++ recursiveStateFrameRoots ++ ingressFrameRoots ++ cacheFrameRoots ++ letSubstitutionRoots ++ cacheInvariantFrameRoots ++ internFrameRoots ++ #[``DefinitionOrder.ready_independent, ``DefinitionOrder.order?_sound, ``DefinitionOrder.member_of_read, ``LocalValues.Below.pushBinder]).map (fun root => { root, standardAxioms := #[``propext, ``Quot.sound], forbiddenDependencies := forbiddenProduction -}) ++ (contextRoots ++ localValueRoots ++ localStateMapRoots ++ ingressMapRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ +}) ++ (contextRoots ++ localValueRoots ++ localStateMapRoots ++ recursiveStateMapRoots ++ ingressMapRoots ++ cacheMapRoots ++ cacheInvariantMapRoots ++ scopedRoots ++ stringRoots ++ internMapRoots ++ #[``DefinitionOrder.order?_rank, ``DefinitionOrder.acyclic_rank]).map (fun root => { root, standardAxioms := standard, forbiddenDependencies := forbiddenProduction -}) ++ (binderWalkerRoots ++ localStateWalkerRoots ++ cacheKeyRoots ++ cacheInvariantKeyRoots ++ stringExpansionRoots).map (fun root => { +}) ++ (binderWalkerRoots ++ localStateWalkerRoots ++ recursiveStateExprRoots ++ cacheKeyRoots ++ cacheInvariantKeyRoots ++ stringExpansionRoots).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative], forbiddenDependencies := forbiddenProduction }) ++ ingressLevelRoots.map (fun root => { root, standardAxioms := standard, nativeAxioms := #[levelNative], forbiddenDependencies := forbiddenProduction -}) ++ (atomicRoots ++ localStateOperationalRoots ++ ingressOperationalRoots ++ instantiationRoots ++ recursiveCacheRoots ++ +}) ++ (atomicRoots ++ localStateOperationalRoots ++ recursiveStateOperationalRoots ++ ingressOperationalRoots ++ instantiationRoots ++ recursiveCacheRoots ++ #[``InferenceCacheInvariant.infer]).map (fun root => { root, standardAxioms := standard, nativeAxioms := #[expressionNative, levelNative], forbiddenDependencies := forbiddenProduction diff --git a/Ix/Kernel/Verify/Consistency/DefEqLocalState.lean b/Ix/Kernel/Verify/Consistency/DefEqLocalState.lean new file mode 100644 index 000000000..52a4b5c18 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/DefEqLocalState.lean @@ -0,0 +1,894 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.WhnfLocalState + +/-! +# Structural local-state preservation for production conversion + +Every direct definitional-equality phase preserves the local declarations, +fresh-variable bound and installed loader on success and error. The binder +and let cases first extend the context with the actual guarded allocation, +then restore it through production scope cleanup. Finite spine and structure +eta workers use induction; recursive method calls use the predecessor table. +Cache and equivalence-manager operations preserve this structural state, +without asserting the semantic correctness of their entries or answers. +-/ + +namespace Ix.Kernel.Consistency + +theorem openLetWithFV_eq (name : Mode.anon.F Name) (type value body : KExpr .anon) + (before : TcState .anon) : + TcM.openLetWithFV name type value body before = + if before.env.nextFVarId.toNat + 1 < UInt64.size then + let fresh : FVarId := ⟨before.env.nextFVarId⟩ + let internedLocal := before.env.intern.internExpr (KExpr.mkFVar fresh name) + let opened := instantiateRev body #[internedLocal.1] internedLocal.2 + .ok (opened.1, internedLocal.1, fresh) {before with + env := {before.env with + nextFVarId := before.env.nextFVarId + 1 + intern := opened.2} + lctx := before.lctx.push fresh (.ldecl name type value)} + else .error (.other "free-variable id space exhausted") before := by + unfold TcM.openLetWithFV + change EStateM.bind TcM.freshFVarId _ before = _ + rw [EStateM.bind, TcM.freshFVarId] + by_cases room : before.env.nextFVarId.toNat + 1 < UInt64.size + · simp only [room, if_true] + rfl + · simp only [room, if_false] + +theorem PreservesLocalState.openLetWithFV + (name : Mode.anon.F Name) (type value body : KExpr .anon) : + PreservesLocalState (TcM.openLetWithFV name type value body) := by + intro before valid + rw [openLetWithFV_eq] + by_cases room : before.env.nextFVarId.toNat + 1 < UInt64.size + · rw [if_pos room] + have increment : (before.env.nextFVarId + 1).toNat = before.env.nextFVarId.toNat + 1 := by + rw [UInt64.toNat_add, show (1 : UInt64).toNat = 1 from rfl, Nat.mod_eq_of_lt room] + exact ⟨⟨valid.coherent.push valid.allocated.fresh, valid.allocated.push _ room, valid.loader⟩, + by change before.env.nextFVarId.toNat ≤ (before.env.nextFVarId + 1).toNat + rw [increment]; omega, .push _ (.refl _) valid.allocated.fresh, rfl⟩ + · rw [if_neg room]; exact .refl valid + +namespace FramesLocalState + +attribute [local local_state_frame] FramesLocalState.ctxAddrForLbr + +attribute [local irreducible] TcM.intern TcM.runIntern + RecM.whnf RecM.whnfCore RecM.whnfNoDelta RecM.whnfCoreForDefEq + RecM.whnfNoDeltaForDefEq RecM.strLitToConstructor + +@[local_state_frame] theorem isDefEqCall {methods : Methods .anon} + (recursive : MethodsLocalState methods) (left right : KExpr .anon) : + FramesLocalState ((RecM.isDefEqCall left right).run methods) := recursive.isDefEq left right + +@[local_state_frame] theorem inferOnlyCall {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.inferOnlyCall term).run methods) := withInferOnly (recursive.infer term) + +@[local_state_frame] theorem defEqCtxKey (left right : KExpr .anon) : + FramesLocalState (TcM.defEqCtxKey left right) := ctxAddrForLbr _ + +@[local_state_frame] theorem withEquiv (update : EquivManager → α × EquivManager) : + FramesLocalState (TcM.withEquiv (m := .anon) update) := by + unfold TcM.withEquiv + apply bind + · apply modifyGet + exact fun _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + · intro manager + local_state + +@[local_state_frame] theorem quickBinder {methods : Methods .anon} + (recursive : MethodsLocalState methods) (name : Mode.anon.F Name) + (bi : Mode.anon.F Lean.BinderInfo) (type1 body1 type2 body2 : KExpr .anon) : + FramesLocalState ((RecM.quickBinder name bi type1 body1 type2 body2).run methods) := by + unfold RecM.quickBinder + local_state + apply PreservesLocalState.withLctxScope + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply PreservesLocalState.bind (PreservesLocalState.openBinder name bi type1 body1) + rintro ⟨opened, fresh⟩ + apply FramesLocalState.preserves + local_state + +@[local_state_frame] theorem tryDefEqWhnfLet {methods : Methods .anon} + (recursive : MethodsLocalState methods) (name : Mode.anon.F Name) + (type1 value1 body1 type2 value2 body2 : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfLet name type1 value1 body1 type2 value2 body2).run methods) := by + unfold RecM.tryDefEqWhnfLet + local_state + apply PreservesLocalState.withLctxScope + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply PreservesLocalState.bind (PreservesLocalState.openLetWithFV name type1 value1 body1) + rintro ⟨opened, fv, fresh⟩ + apply FramesLocalState.preserves + local_state + +@[local_state_frame] theorem allDefEqSpineArgsList {methods : Methods .anon} + (recursive : MethodsLocalState methods) (pairs : List (KExpr .anon × KExpr .anon)) : + FramesLocalState ((RecM.allDefEqSpineArgsList pairs).run methods) := by + induction pairs with + | nil => exact pure _ + | cons pair pairs ih => + rcases pair with ⟨left, right⟩ + rw [RecM.allDefEqSpineArgsList] + local_state + +@[local_state_frame] theorem tryEtaStructFields {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ind : KId .anon) (params : Nat) + (term : KExpr .anon) (args : Array (KExpr .anon)) (fuel field : Nat) : + FramesLocalState ((RecM.tryEtaStructFields ind params term args fuel field).run methods) := by + induction fuel generalizing field with + | zero => exact pure _ + | succ fuel ih => + rw [RecM.tryEtaStructFields] + local_state + +@[local_state_frame] theorem etaExpansionBaseLoop {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ind : KId .anon) (params : Nat) + (args : Array (KExpr .anon)) (fuel field : Nat) (base : Option (KExpr .anon)) : + FramesLocalState ((RecM.etaExpansionBaseLoop ind params args fuel field base).run methods) := by + induction fuel generalizing field base with + | zero => + rw [RecM.etaExpansionBaseLoop] + exact pure _ + | succ fuel ih => + rw [RecM.etaExpansionBaseLoop] + simp only [RecM.etaExpansionBaseAfterProjection] + local_state + all_goals unfold RecM.etaExpansionBaseAfterValue + all_goals local_state + + +@[local_state_frame] theorem isNatLike {methods : Methods .anon} + (e : KExpr .anon) : + FramesLocalState ((RecM.isNatLike e).run methods) := by + unfold RecM.isNatLike + local_state + +attribute [local irreducible] RecM.isNatLike + +@[local_state_frame] theorem isNatZero {methods : Methods .anon} + (e : KExpr .anon) : + FramesLocalState ((RecM.isNatZero e).run methods) := by + unfold RecM.isNatZero + local_state + +attribute [local irreducible] RecM.isNatZero + +@[local_state_frame] theorem natSuccOf {methods : Methods .anon} + (e : KExpr .anon) : + FramesLocalState ((RecM.natSuccOf e).run methods) := by + unfold RecM.natSuccOf + local_state + +attribute [local irreducible] RecM.natSuccOf + +@[local_state_frame] theorem isBoolTrue {methods : Methods .anon} + (e : KExpr .anon) : + FramesLocalState ((RecM.isBoolTrue e).run methods) := by + unfold RecM.isBoolTrue + local_state + +attribute [local irreducible] RecM.isBoolTrue + +@[local_state_frame] theorem boolTrueReductionAllowed {methods : Methods .anon} + (e : KExpr .anon) : + FramesLocalState ((RecM.boolTrueReductionAllowed e).run methods) := by + unfold RecM.boolTrueReductionAllowed + local_state + +attribute [local irreducible] RecM.boolTrueReductionAllowed + +@[local_state_frame] theorem whnfIsBoolTrue {methods : Methods .anon} + (recursive : MethodsLocalState methods) (e : KExpr .anon) : + FramesLocalState ((RecM.whnfIsBoolTrue e).run methods) := by + unfold RecM.whnfIsBoolTrue + local_state + +attribute [local irreducible] RecM.whnfIsBoolTrue + +@[local_state_frame] theorem isDelta {methods : Methods .anon} + (id : KId .anon) : + FramesLocalState ((RecM.isDelta id).run methods) := by + unfold RecM.isDelta + local_state + +attribute [local irreducible] RecM.isDelta + +@[local_state_frame] theorem classifyDeltaHead {methods : Methods .anon} + (e : KExpr .anon) : + FramesLocalState ((RecM.classifyDeltaHead e).run methods) := by + unfold RecM.classifyDeltaHead + local_state + +attribute [local irreducible] RecM.classifyDeltaHead + +@[local_state_frame] theorem isRegular {methods : Methods .anon} + (id : KId .anon) : + FramesLocalState ((RecM.isRegular id).run methods) := by + unfold RecM.isRegular + local_state + +attribute [local irreducible] RecM.isRegular + +@[local_state_frame] theorem defRankId {methods : Methods .anon} + (id : KId .anon) : + FramesLocalState ((RecM.defRankId id).run methods) := by + unfold RecM.defRankId + local_state + +attribute [local irreducible] RecM.defRankId + +@[local_state_frame] theorem rankDeltaHead {methods : Methods .anon} + (head : Option (KId .anon)) : + FramesLocalState ((RecM.rankDeltaHead head).run methods) := by + unfold RecM.rankDeltaHead + local_state + +attribute [local irreducible] RecM.rankDeltaHead + +@[local_state_frame] theorem quickDefEq {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.quickDefEq a b).run methods) := by + unfold RecM.quickDefEq + local_state + +attribute [local irreducible] RecM.quickDefEq + +@[local_state_frame] theorem finishDefEqLazyDeltaStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa wb : KExpr .anon) : + FramesLocalState ((RecM.finishDefEqLazyDeltaStep wa wb).run methods) := by + unfold RecM.finishDefEqLazyDeltaStep + local_state + +attribute [local irreducible] RecM.finishDefEqLazyDeltaStep + +@[local_state_frame] theorem defEqLazyDeltaStepAfterSameHeadMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa0 wb0 : KExpr .anon) : + FramesLocalState ((RecM.defEqLazyDeltaStepAfterSameHeadMiss wa0 wb0).run methods) := by + unfold RecM.defEqLazyDeltaStepAfterSameHeadMiss + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepAfterSameHeadMiss + +@[local_state_frame] theorem defEqLazyDeltaStepWithLeftDelta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa wb : KExpr .anon) : + FramesLocalState ((RecM.defEqLazyDeltaStepWithLeftDelta wa wb).run methods) := by + unfold RecM.defEqLazyDeltaStepWithLeftDelta + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepWithLeftDelta + +@[local_state_frame] theorem defEqLazyDeltaStepWithRightDelta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa wb : KExpr .anon) : + FramesLocalState ((RecM.defEqLazyDeltaStepWithRightDelta wa wb).run methods) := by + unfold RecM.defEqLazyDeltaStepWithRightDelta + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepWithRightDelta + +@[local_state_frame] theorem allDefEqSpineArgs {methods : Methods .anon} + (recursive : MethodsLocalState methods) (pairs : Array (KExpr .anon × KExpr .anon)) : + FramesLocalState ((RecM.allDefEqSpineArgs pairs).run methods) := by + unfold RecM.allDefEqSpineArgs + local_state + +attribute [local irreducible] RecM.allDefEqSpineArgs + +@[local_state_frame] theorem trySameHeadSpine {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.trySameHeadSpine a b).run methods) := by + unfold RecM.trySameHeadSpine + local_state + +attribute [local irreducible] RecM.trySameHeadSpine + +@[local_state_frame] theorem trySameHeadSpineSpeculative {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.trySameHeadSpineSpeculative a b).run methods) := by + unfold RecM.trySameHeadSpineSpeculative + local_state + +attribute [local irreducible] RecM.trySameHeadSpineSpeculative + +@[local_state_frame] theorem trySameHeadSpineCached {methods : Methods .anon} + (recursive : MethodsLocalState methods) (speculative : Bool) (left right : KExpr .anon) : + FramesLocalState ((RecM.trySameHeadSpineCached speculative left right).run methods) := by + unfold RecM.trySameHeadSpineCached + local_state + +attribute [local irreducible] RecM.trySameHeadSpineCached + +@[local_state_frame] theorem defEqLazyDeltaStepWithEqualRank {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa0 wb0 : KExpr .anon) + (aHead bHead : Option (KId .anon)) : + FramesLocalState ((RecM.defEqLazyDeltaStepWithEqualRank wa0 wb0 aHead bHead).run methods) := by + unfold RecM.defEqLazyDeltaStepWithEqualRank + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepWithEqualRank + +@[local_state_frame] theorem defEqLazyDeltaStepAfterProjectionMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa0 wb0 : KExpr .anon) + (aHead bHead : Option (KId .anon)) (aDelta bDelta : Bool) : + FramesLocalState ((RecM.defEqLazyDeltaStepAfterProjectionMiss wa0 wb0 aHead bHead aDelta bDelta).run methods) := by + unfold RecM.defEqLazyDeltaStepAfterProjectionMiss + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepAfterProjectionMiss + +@[local_state_frame] theorem tryDefEqWhnfApp {methods : Methods .anon} + (recursive : MethodsLocalState methods) (f1 a1 f2 a2 : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfApp f1 a1 f2 a2).run methods) := by + unfold RecM.tryDefEqWhnfApp + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfApp + +@[local_state_frame] theorem tryDefEqWhnfStructural {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfStructural a b).run methods) := by + unfold RecM.tryDefEqWhnfStructural + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfStructural + +@[local_state_frame] theorem classifyPropTypeUncached {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ty : KExpr .anon) : + FramesLocalState ((RecM.classifyPropTypeUncached ty).run methods) := by + unfold RecM.classifyPropTypeUncached + local_state + +attribute [local irreducible] RecM.classifyPropTypeUncached + +@[local_state_frame] theorem isPropType {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ty : KExpr .anon) : + FramesLocalState ((RecM.isPropType ty).run methods) := by + unfold RecM.isPropType + local_state + +attribute [local irreducible] RecM.isPropType + +@[local_state_frame] theorem tryProofIrrel {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryProofIrrel a b).run methods) := by + unfold RecM.tryProofIrrel + local_state + +attribute [local irreducible] RecM.tryProofIrrel + +@[local_state_frame] theorem isDefEqWhnfAfterUnit {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqWhnfAfterUnit a b).run methods) := by + unfold RecM.isDefEqWhnfAfterUnit + local_state + +attribute [local irreducible] RecM.isDefEqWhnfAfterUnit + +@[local_state_frame] theorem isUnitLikeInductive {methods : Methods .anon} + (indId : KId .anon) : + FramesLocalState ((RecM.isUnitLikeInductive indId).run methods) := by + unfold RecM.isUnitLikeInductive + local_state + +attribute [local irreducible] RecM.isUnitLikeInductive + +@[local_state_frame] theorem tryDefEqUnit {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqUnit a b).run methods) := by + unfold RecM.tryDefEqUnit + local_state + +attribute [local irreducible] RecM.tryDefEqUnit + +@[local_state_frame] theorem isDefEqWhnfAfterStructEta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqWhnfAfterStructEta a b).run methods) := by + unfold RecM.isDefEqWhnfAfterStructEta + local_state + +attribute [local irreducible] RecM.isDefEqWhnfAfterStructEta + +@[local_state_frame] theorem isDefEqNatAfterLiteral {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqNatAfterLiteral a b).run methods) := by + unfold RecM.isDefEqNatAfterLiteral + local_state + +attribute [local irreducible] RecM.isDefEqNatAfterLiteral + +@[local_state_frame] theorem isDefEqNat {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqNat a b).run methods) := by + unfold RecM.isDefEqNat + local_state + +attribute [local irreducible] RecM.isDefEqNat + +@[local_state_frame] theorem tryDefEqWhnfNat {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfNat a b).run methods) := by + unfold RecM.tryDefEqWhnfNat + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfNat + +@[local_state_frame] theorem tryDefEqOffsetAfterCandidates {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqOffsetAfterCandidates a b).run methods) := by + unfold RecM.tryDefEqOffsetAfterCandidates + local_state + +attribute [local irreducible] RecM.tryDefEqOffsetAfterCandidates + +@[local_state_frame] theorem tryDefEqOffsetAfterZeroMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqOffsetAfterZeroMiss a b).run methods) := by + unfold RecM.tryDefEqOffsetAfterZeroMiss + local_state + +attribute [local irreducible] RecM.tryDefEqOffsetAfterZeroMiss + +@[local_state_frame] theorem tryDefEqOffsetAfterLiteral {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqOffsetAfterLiteral a b).run methods) := by + unfold RecM.tryDefEqOffsetAfterLiteral + local_state + +attribute [local irreducible] RecM.tryDefEqOffsetAfterLiteral + +@[local_state_frame] theorem tryDefEqOffset {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqOffset a b).run methods) := by + unfold RecM.tryDefEqOffset + local_state + +attribute [local irreducible] RecM.tryDefEqOffset + +@[local_state_frame] theorem tryStringLitExpansion {methods : Methods .anon} + (recursive : MethodsLocalState methods) (t s : KExpr .anon) : + FramesLocalState ((RecM.tryStringLitExpansion t s).run methods) := by + unfold RecM.tryStringLitExpansion + local_state + +attribute [local irreducible] RecM.tryStringLitExpansion + +@[local_state_frame] theorem tryDefEqWhnfStringAfterGuard {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfStringAfterGuard a b).run methods) := by + unfold RecM.tryDefEqWhnfStringAfterGuard + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfStringAfterGuard + +@[local_state_frame] theorem tryDefEqWhnfString {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfString a b).run methods) := by + unfold RecM.tryDefEqWhnfString + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfString + +@[local_state_frame] theorem compareEtaExpansion {methods : Methods .anon} + (recursive : MethodsLocalState methods) (t s : KExpr .anon) (name : Mode.anon.F Name) + (bi : Mode.anon.F Lean.BinderInfo) (ty : KExpr .anon) : + FramesLocalState ((RecM.compareEtaExpansion t s name bi ty).run methods) := by + unfold RecM.compareEtaExpansion + local_state + +attribute [local irreducible] RecM.compareEtaExpansion + +@[local_state_frame] theorem tryEtaExpansionAfterGuard {methods : Methods .anon} + (recursive : MethodsLocalState methods) (t s : KExpr .anon) : + FramesLocalState ((RecM.tryEtaExpansionAfterGuard t s).run methods) := by + unfold RecM.tryEtaExpansionAfterGuard + local_state + +attribute [local irreducible] RecM.tryEtaExpansionAfterGuard + +@[local_state_frame] theorem tryEtaExpansion {methods : Methods .anon} + (recursive : MethodsLocalState methods) (t s : KExpr .anon) : + FramesLocalState ((RecM.tryEtaExpansion t s).run methods) := by + unfold RecM.tryEtaExpansion + local_state + +attribute [local irreducible] RecM.tryEtaExpansion + +@[local_state_frame] theorem tryDefEqWhnfEtaAfterGuard {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfEtaAfterGuard a b).run methods) := by + unfold RecM.tryDefEqWhnfEtaAfterGuard + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfEtaAfterGuard + +@[local_state_frame] theorem tryDefEqWhnfEta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfEta a b).run methods) := by + unfold RecM.tryDefEqWhnfEta + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfEta + +@[local_state_frame] theorem normalizeEtaStructSource {methods : Methods .anon} + (recursive : MethodsLocalState methods) (t : KExpr .anon) : + FramesLocalState ((RecM.normalizeEtaStructSource t).run methods) := by + unfold RecM.normalizeEtaStructSource + local_state + +attribute [local irreducible] RecM.normalizeEtaStructSource + +@[local_state_frame] theorem etaExpansionBase {methods : Methods .anon} + (recursive : MethodsLocalState methods) (inductId : KId .anon) (numParams numFields : Nat) + (args : Array (KExpr .anon)) : + FramesLocalState ((RecM.etaExpansionBase inductId numParams numFields args).run methods) := by + unfold RecM.etaExpansionBase + local_state + +attribute [local irreducible] RecM.etaExpansionBase + +@[local_state_frame] theorem tryEtaStructAfterTypes {methods : Methods .anon} + (recursive : MethodsLocalState methods) (inductId : KId .anon) (numParams numFields : Nat) + (tNorm : KExpr .anon) (sArgs : Array (KExpr .anon)) : + FramesLocalState ((RecM.tryEtaStructAfterTypes inductId numParams numFields tNorm sArgs).run methods) := by + unfold RecM.tryEtaStructAfterTypes + local_state + +attribute [local irreducible] RecM.tryEtaStructAfterTypes + +@[local_state_frame] theorem tryEtaStructAfterConstructor {methods : Methods .anon} + (recursive : MethodsLocalState methods) (inductId : KId .anon) + (numParams numFields : Nat) (tNorm s : KExpr .anon) + (sArgs : Array (KExpr .anon)) : + FramesLocalState ((RecM.tryEtaStructAfterConstructor inductId numParams numFields tNorm s sArgs).run methods) := by + unfold RecM.tryEtaStructAfterConstructor + local_state + +attribute [local irreducible] RecM.tryEtaStructAfterConstructor + +@[local_state_frame] theorem tryEtaStructAfterNormalization {methods : Methods .anon} + (recursive : MethodsLocalState methods) (tNorm s : KExpr .anon) : + FramesLocalState ((RecM.tryEtaStructAfterNormalization tNorm s).run methods) := by + unfold RecM.tryEtaStructAfterNormalization + local_state + +attribute [local irreducible] RecM.tryEtaStructAfterNormalization + +@[local_state_frame] theorem tryEtaStruct {methods : Methods .anon} + (recursive : MethodsLocalState methods) (t s : KExpr .anon) : + FramesLocalState ((RecM.tryEtaStruct t s).run methods) := by + unfold RecM.tryEtaStruct + local_state + +attribute [local irreducible] RecM.tryEtaStruct + +@[local_state_frame] theorem tryDefEqWhnfStructEta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqWhnfStructEta a b).run methods) := by + unfold RecM.tryDefEqWhnfStructEta + local_state + +attribute [local irreducible] RecM.tryDefEqWhnfStructEta + +@[local_state_frame] theorem isDefEqWhnfAfterString {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqWhnfAfterString a b).run methods) := by + unfold RecM.isDefEqWhnfAfterString + local_state + +attribute [local irreducible] RecM.isDefEqWhnfAfterString + +@[local_state_frame] theorem isDefEqWhnfAfterEta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqWhnfAfterEta a b).run methods) := by + unfold RecM.isDefEqWhnfAfterEta + local_state + +attribute [local irreducible] RecM.isDefEqWhnfAfterEta + +@[local_state_frame] theorem isDefEqWhnfAfterNat {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqWhnfAfterNat a b).run methods) := by + unfold RecM.isDefEqWhnfAfterNat + local_state + +attribute [local irreducible] RecM.isDefEqWhnfAfterNat + +@[local_state_frame] theorem isDefEqWhnfAfterStructural {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqWhnfAfterStructural a b).run methods) := by + unfold RecM.isDefEqWhnfAfterStructural + local_state + +attribute [local irreducible] RecM.isDefEqWhnfAfterStructural + +@[local_state_frame] theorem isDefEqWhnf {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqWhnf a b).run methods) := by + unfold RecM.isDefEqWhnf + local_state + +attribute [local irreducible] RecM.isDefEqWhnf + +@[local_state_frame] theorem etaExpansionBaseAfterValue {methods : Methods .anon} + (recursive : MethodsLocalState methods) (inductId : KId .anon) (numParams : Nat) + (args : Array (KExpr .anon)) (fuel fieldIdx : Nat) + (base : Option (KExpr .anon)) (value : KExpr .anon) : + FramesLocalState ((RecM.etaExpansionBaseAfterValue inductId numParams args fuel fieldIdx base value).run methods) := by + unfold RecM.etaExpansionBaseAfterValue + local_state + + +@[local_state_frame] theorem etaExpansionBaseAfterProjection {methods : Methods .anon} + (recursive : MethodsLocalState methods) (inductId : KId .anon) (numParams : Nat) + (args : Array (KExpr .anon)) (fuel fieldIdx : Nat) + (base : Option (KExpr .anon)) (value : KExpr .anon) : + FramesLocalState ((RecM.etaExpansionBaseAfterProjection inductId numParams args fuel fieldIdx base value).run methods) := by + unfold RecM.etaExpansionBaseAfterProjection + local_state + + +@[local_state_frame] theorem tryDefEqApp {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryDefEqApp a b).run methods) := by + unfold RecM.tryDefEqApp + local_state + +attribute [local irreducible] RecM.tryDefEqApp + +@[local_state_frame] theorem finishLazyDeltaReductionStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.finishLazyDeltaReductionStep a b).run methods) := by + unfold RecM.finishLazyDeltaReductionStep + local_state + +attribute [local irreducible] RecM.finishLazyDeltaReductionStep + +@[local_state_frame] theorem lazyDeltaReductionStepWithLeftDelta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.lazyDeltaReductionStepWithLeftDelta a b).run methods) := by + unfold RecM.lazyDeltaReductionStepWithLeftDelta + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStepWithLeftDelta + +@[local_state_frame] theorem lazyDeltaReductionStepWithRightDelta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.lazyDeltaReductionStepWithRightDelta a b).run methods) := by + unfold RecM.lazyDeltaReductionStepWithRightDelta + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStepWithRightDelta + +@[local_state_frame] theorem lazyDeltaReductionStepAfterSameHeadMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a0 b0 : KExpr .anon) : + FramesLocalState ((RecM.lazyDeltaReductionStepAfterSameHeadMiss a0 b0).run methods) := by + unfold RecM.lazyDeltaReductionStepAfterSameHeadMiss + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStepAfterSameHeadMiss + +@[local_state_frame] theorem lazyDeltaReductionStepWithEqualRank {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a0 b0 : KExpr .anon) + (aId bId : KId .anon) : + FramesLocalState ((RecM.lazyDeltaReductionStepWithEqualRank a0 b0 aId bId).run methods) := by + unfold RecM.lazyDeltaReductionStepWithEqualRank + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStepWithEqualRank + +@[local_state_frame] theorem lazyDeltaReductionStepWithBothDelta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) + (aHead bHead : Option (KId .anon)) : + FramesLocalState ((RecM.lazyDeltaReductionStepWithBothDelta a b aHead bHead).run methods) := by + unfold RecM.lazyDeltaReductionStepWithBothDelta + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStepWithBothDelta + +@[local_state_frame] theorem tryUnfoldProjApp {methods : Methods .anon} + (recursive : MethodsLocalState methods) (e : KExpr .anon) : + FramesLocalState ((RecM.tryUnfoldProjApp e).run methods) := by + unfold RecM.tryUnfoldProjApp + local_state + +attribute [local irreducible] RecM.tryUnfoldProjApp + +@[local_state_frame] theorem defEqLazyDeltaStepAfterDeltaClassification {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa0 wb0 : KExpr .anon) + (aHead bHead : Option (KId .anon)) (aDelta bDelta : Bool) : + FramesLocalState ((RecM.defEqLazyDeltaStepAfterDeltaClassification wa0 wb0 aHead bHead aDelta bDelta).run methods) := by + unfold RecM.defEqLazyDeltaStepAfterDeltaClassification + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepAfterDeltaClassification + +@[local_state_frame] theorem defEqLazyDeltaStepAfterAcceleratorMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa0 wb0 : KExpr .anon) : + FramesLocalState ((RecM.defEqLazyDeltaStepAfterAcceleratorMiss wa0 wb0).run methods) := by + unfold RecM.defEqLazyDeltaStepAfterAcceleratorMiss + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepAfterAcceleratorMiss + +@[local_state_frame] theorem defEqLazyDeltaStepAfterNatMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa0 wb0 : KExpr .anon) : + FramesLocalState ((RecM.defEqLazyDeltaStepAfterNatMiss wa0 wb0).run methods) := by + unfold RecM.defEqLazyDeltaStepAfterNatMiss + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepAfterNatMiss + +@[local_state_frame] theorem defEqLazyDeltaStepAfterOffsetMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (state : KExpr .anon × KExpr .anon) : + FramesLocalState ((RecM.defEqLazyDeltaStepAfterOffsetMiss state).run methods) := by + unfold RecM.defEqLazyDeltaStepAfterOffsetMiss + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStepAfterOffsetMiss + +@[local_state_frame] theorem defEqLazyDeltaStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (state : KExpr .anon × KExpr .anon) : + FramesLocalState ((RecM.defEqLazyDeltaStep state).run methods) := by + unfold RecM.defEqLazyDeltaStep + local_state + +attribute [local irreducible] RecM.defEqLazyDeltaStep + +@[local_state_frame] theorem runDefEqLazyDelta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa wb : KExpr .anon) : + FramesLocalState ((RecM.runDefEqLazyDelta wa wb).run methods) := by + unfold RecM.runDefEqLazyDelta + local_state + +attribute [local irreducible] RecM.runDefEqLazyDelta + +@[local_state_frame] theorem lazyDeltaReductionStepAfterActive {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a0 b0 : KExpr .anon) + (aHead bHead : Option (KId .anon)) (aDelta bDelta : Bool) : + FramesLocalState ((RecM.lazyDeltaReductionStepAfterActive a0 b0 aHead bHead aDelta bDelta).run methods) := by + unfold RecM.lazyDeltaReductionStepAfterActive + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStepAfterActive + +@[local_state_frame] theorem lazyDeltaReductionStepAfterClassification {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a0 b0 : KExpr .anon) + (aHead bHead : Option (KId .anon)) (aDelta bDelta : Bool) : + FramesLocalState ((RecM.lazyDeltaReductionStepAfterClassification a0 b0 aHead bHead aDelta bDelta).run methods) := by + unfold RecM.lazyDeltaReductionStepAfterClassification + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStepAfterClassification + +@[local_state_frame] theorem lazyDeltaReductionStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a0 b0 : KExpr .anon) : + FramesLocalState ((RecM.lazyDeltaReductionStep a0 b0).run methods) := by + unfold RecM.lazyDeltaReductionStep + local_state + +attribute [local irreducible] RecM.lazyDeltaReductionStep + +@[local_state_frame] theorem lazyDeltaProjReduction {methods : Methods .anon} + (recursive : MethodsLocalState methods) (structId : KId .anon) (field : UInt64) + (a0 b0 : KExpr .anon) : + FramesLocalState ((RecM.lazyDeltaProjReduction structId field a0 b0).run methods) := by + unfold RecM.lazyDeltaProjReduction + local_state + +attribute [local irreducible] RecM.lazyDeltaProjReduction + +@[local_state_frame] theorem tryStructuralCongruence {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.tryStructuralCongruence a b).run methods) := by + unfold RecM.tryStructuralCongruence + local_state + +attribute [local irreducible] RecM.tryStructuralCongruence + +@[local_state_frame] theorem isDefEqAfterLazyDeltaStopped {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa wb : KExpr .anon) : + FramesLocalState ((RecM.isDefEqAfterLazyDeltaStopped wa wb).run methods) := by + unfold RecM.isDefEqAfterLazyDeltaStopped + local_state + +attribute [local irreducible] RecM.isDefEqAfterLazyDeltaStopped + +@[local_state_frame] theorem isDefEqInnerAfterProofIrrelevance {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa wb : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInnerAfterProofIrrelevance wa wb).run methods) := by + unfold RecM.isDefEqInnerAfterProofIrrelevance + local_state + +attribute [local irreducible] RecM.isDefEqInnerAfterProofIrrelevance + +@[local_state_frame] theorem isDefEqInnerAfterNoDeltaPass {methods : Methods .anon} + (recursive : MethodsLocalState methods) (wa wb : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInnerAfterNoDeltaPass wa wb).run methods) := by + unfold RecM.isDefEqInnerAfterNoDeltaPass + local_state + +attribute [local irreducible] RecM.isDefEqInnerAfterNoDeltaPass + +@[local_state_frame] theorem isDefEqInnerAfterCorePass {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInnerAfterCorePass a b).run methods) := by + unfold RecM.isDefEqInnerAfterCorePass + local_state + +attribute [local irreducible] RecM.isDefEqInnerAfterCorePass + +@[local_state_frame] theorem isDefEqInnerAfterStringExpansion {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInnerAfterStringExpansion a b).run methods) := by + unfold RecM.isDefEqInnerAfterStringExpansion + local_state + +attribute [local irreducible] RecM.isDefEqInnerAfterStringExpansion + +@[local_state_frame] theorem isDefEqInnerAfterBoolTrue {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInnerAfterBoolTrue a b).run methods) := by + unfold RecM.isDefEqInnerAfterBoolTrue + local_state + +attribute [local irreducible] RecM.isDefEqInnerAfterBoolTrue + +@[local_state_frame] theorem isDefEqInnerAfterFirstBoolGuardMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInnerAfterFirstBoolGuardMiss a b).run methods) := by + unfold RecM.isDefEqInnerAfterFirstBoolGuardMiss + local_state + +attribute [local irreducible] RecM.isDefEqInnerAfterFirstBoolGuardMiss + +@[local_state_frame] theorem isDefEqInnerAfterQuick {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInnerAfterQuick a b).run methods) := by + unfold RecM.isDefEqInnerAfterQuick + local_state + +attribute [local irreducible] RecM.isDefEqInnerAfterQuick + +@[local_state_frame] theorem isDefEqInner {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEqInner a b).run methods) := by + unfold RecM.isDefEqInner + local_state + +attribute [local irreducible] RecM.isDefEqInner + +@[local_state_frame] theorem isDefEqAfterRootCacheMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) (aKey bKey : EqKey) + (cacheKey : Address × Address × Address) (cheapMode : Bool) : + FramesLocalState ((RecM.isDefEqAfterRootCacheMiss a b aKey bKey cacheKey cheapMode).run methods) := by + unfold RecM.isDefEqAfterRootCacheMiss + local_state + +attribute [local irreducible] RecM.isDefEqAfterRootCacheMiss + +@[local_state_frame] theorem isDefEqAfterDirectCacheMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) (eqCtx : Address) + (aKey bKey : EqKey) (cacheKey : Address × Address × Address) + (cheapMode : Bool) : + FramesLocalState ((RecM.isDefEqAfterDirectCacheMiss a b eqCtx aKey bKey cacheKey cheapMode).run methods) := by + unfold RecM.isDefEqAfterDirectCacheMiss + local_state + +attribute [local irreducible] RecM.isDefEqAfterDirectCacheMiss + +@[local_state_frame] theorem isDefEq {methods : Methods .anon} + (recursive : MethodsLocalState methods) (a b : KExpr .anon) : + FramesLocalState ((RecM.isDefEq a b).run methods) := by + unfold RecM.isDefEq + local_state + +attribute [local irreducible] RecM.isDefEq + +end FramesLocalState +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/LocalStateEffects.lean b/Ix/Kernel/Verify/Consistency/LocalStateEffects.lean new file mode 100644 index 000000000..2bae99425 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LocalStateEffects.lean @@ -0,0 +1,315 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.InferenceLocalState +import Ix.Kernel.Verify.Monad + +/-! +# Local-state effects of reduction and conversion control flow + +Both outcomes preserve the caller's local declarations, allocation bound and +installed loader. These rules cover caught failures, cleanup, finite loops, +keys, fuel and policy scopes. Recursive callback frames describe a strictly +smaller method table. The reduction and conversion proofs compose these rules +to close each finite production table. +-/ + +namespace Ix.Kernel.Consistency + +namespace FramesLocalState + +theorem ofWF {action : TcM .anon α} + (framed : ∀ before, TcM.WF + (fun after => LocalStateInvariant after ∧ LocalStateFrame before after) + before action (fun _ _ => True)) : FramesLocalState action := by + intro before valid + have result := framed before ⟨valid, .refl _⟩ + cases run : action before <;> rw [run] at result <;> exact result.1.2 + +theorem tryCatch {action : TcM .anon α} {handler : TcError .anon → TcM .anon α} + (body : FramesLocalState action) (caught : ∀ error, FramesLocalState (handler error)) : + FramesLocalState (tryCatch action handler) := by + intro before valid + have first := body before valid + change match EStateM.tryCatch action handler before with + | .ok _ after | .error _ after => LocalStateFrame before after + cases run : action before with + | ok value after => + rw [EStateM.tryCatch, run] + simpa only [run] using first + | error error middle => + rw [run] at first + rw [EStateM.tryCatch, run] + change match handler error middle with + | .ok _ after | .error _ after => LocalStateFrame before after + have next := caught error middle (first.invariant valid) + cases finished : handler error middle <;> rw [finished] at next <;> exact first.trans next + +private theorem tryFinally_eq (action : TcM .anon α) (cleanup : TcM .anon β) + (before : TcState .anon) : + tryFinally action cleanup before = + match action before with + | .ok value middle => + match cleanup middle with + | .ok _ after => .ok value after + | .error error after => .error error after + | .error error middle => + match cleanup middle with + | .ok _ after => .error error after + | .error cleanupError after => .error cleanupError after := by + unfold tryFinally + change EStateM.map (fun value : α × β => value.1) + (tryFinally' action (fun _ => cleanup)) before = _ + unfold EStateM.map MonadFinally.tryFinally' EStateM.instMonadFinally + cases run : action before <;> simp only [run] <;> cases finished : cleanup _ <;> rfl + +theorem tryFinally {action : TcM .anon α} {cleanup : TcM .anon β} + (body : FramesLocalState action) (clean : FramesLocalState cleanup) : + FramesLocalState (tryFinally action cleanup) := by + intro before valid + rw [tryFinally_eq] + have first := body before valid + cases run : action before <;> rw [run] at first <;> dsimp only <;> + have next := clean _ (first.invariant valid) <;> + cases finished : cleanup _ <;> rw [finished] at next <;> exact first.trans next + +theorem map (f : α → β) {action : TcM .anon α} (body : FramesLocalState action) : + FramesLocalState (f <$> action) := by + simpa only [map_eq_pure_bind] using bind body (fun value => pure (f value)) + +theorem modifyGet {f : TcState .anon → α × TcState .anon} + (framed : ∀ before, LocalStateFrame before (f before).2) : + FramesLocalState (MonadStateOf.modifyGet f : TcM .anon α) := + fun before _ => framed before + +theorem tick : FramesLocalState (TcM.tick (m := .anon)) := by + apply ofWF + intro before + apply TcM.WF.mono (TcM.tick.wf (fun state valid => + ⟨⟨valid.1.coherent, valid.1.allocated, valid.1.loader⟩, + ⟨valid.2.counter, valid.2.context, valid.2.loader⟩⟩)) + · intros; trivial + · intros; trivial + +theorem stepTrace (tag : String) (payload : Unit → String) : + FramesLocalState (TcM.stepTrace (m := .anon) tag payload) := by + unfold TcM.stepTrace + apply bind get + intro state + split <;> exact pure _ + +theorem bumpStats (update : TcState .anon → TcState .anon) + (framed : ∀ before, LocalStateFrame before (update before)) : + FramesLocalState (TcM.bumpStats update) := by + unfold TcM.bumpStats + apply bind get + intro state + split + · exact modify update framed + · exact pure _ + +theorem isLetVar (index : UInt64) : FramesLocalState (TcM.isLetVar (m := .anon) index) := by + unfold TcM.isLetVar + apply bind get + intro state + dsimp only + split <;> exact pure _ + +theorem lookupLetVal (index : UInt64) : FramesLocalState (TcM.lookupLetVal (m := .anon) index) := by + unfold TcM.lookupLetVal + apply bind get + intro state + dsimp only + split + · exact pure _ + · split + · exact pure _ + · exact bind (runIntern _) (fun _ => pure _) + +theorem whnfKey (term : KExpr .anon) : FramesLocalState (TcM.whnfKey term) := + bind (ctxAddrForLbr term.lbr) (fun _ => pure _) + +theorem tryGetBlock (id : KId .anon) : FramesLocalState (TcM.tryGetBlock id) := by + unfold TcM.tryGetBlock + apply bind get + intro state + split + · exact pure _ + · exact bind (lazyIngressAddr id.addr) fun _ => bind get fun _ => pure _ + +theorem runBounded {methods : Methods .anon} + {step : σ → RecM .anon (RecM.BoundedStep σ α)} + (framed : ∀ state, FramesLocalState ((step state).run methods)) : + ∀ fuel state, FramesLocalState ((RecM.runBounded step fuel state).run methods) + | 0, _ => throw _ + | fuel + 1, state => by + rw [RecM.runBounded, ReaderT.run_bind] + apply bind (framed state) + intro next + cases next with + | next value => exact runBounded framed fuel value + | done value => exact pure _ + +theorem forInList {methods : Methods .anon} (items : List α) (initial : β) + (step : α → β → RecM .anon (ForInStep β)) + (framed : ∀ item value, FramesLocalState ((step item value).run methods)) : + FramesLocalState ((forIn items initial step).run methods) := by + induction items generalizing initial with + | nil => exact pure _ + | cons item rest ih => + rw [List.forIn_cons, ReaderT.run_bind] + apply bind (framed item initial) + intro next + cases next with + | done value => exact pure _ + | yield value => exact ih value + +theorem forInRange {methods : Methods .anon} (range : Std.Legacy.Range) (initial : α) + (step : Nat → α → RecM .anon (ForInStep α)) + (framed : ∀ index value, FramesLocalState ((step index value).run methods)) : + FramesLocalState ((forIn range initial step).run methods) := by + rw [Std.Legacy.Range.forIn_eq_forIn_range'] + exact forInList _ _ _ framed + +theorem forInArray {methods : Methods .anon} (items : Array α) (initial : β) + (step : α → β → RecM .anon (ForInStep β)) + (framed : ∀ item value, FramesLocalState ((step item value).run methods)) : + FramesLocalState ((forIn items initial step).run methods) := by + rcases items with ⟨items⟩ + rw [List.forIn_toArray] + exact forInList _ _ _ framed + +theorem withCheapRecursionDepth {methods : Methods .anon} {action : RecM .anon α} + (body : FramesLocalState (action.run methods)) : + FramesLocalState ((RecM.withCheapRecursionDepth action).run methods) := by + unfold RecM.withCheapRecursionDepth + simp only [ReaderT.run_bind] + apply bind + · apply modify; exact fun _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + · intro _ + change FramesLocalState (_root_.tryFinally (action.run methods) + (_root_.modify fun state => {state with cheapRecursionDepth := state.cheapRecursionDepth - 1})) + apply tryFinally body + apply modify; exact fun _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + +end FramesLocalState + +structure MethodsLocalState (methods : Methods .anon) : Prop where + whnf : ∀ term, FramesLocalState (methods.whnf term) + whnfCore : ∀ term, FramesLocalState (methods.whnfCore term) + whnfMode : ∀ term mode, FramesLocalState (methods.whnfMode term mode) + whnfCoreFlags : ∀ term flags, FramesLocalState (methods.whnfCoreFlags term flags) + infer : ∀ term, FramesLocalState (methods.infer term) + isDefEq : ∀ left right, FramesLocalState (methods.isDefEq left right) + +namespace FramesLocalState + +theorem whnfRec {methods : Methods .anon} (recursive : MethodsLocalState methods) + (term : KExpr .anon) : FramesLocalState ((RecM.whnfRec term).run methods) := recursive.whnf term + +theorem whnfModeRec {methods : Methods .anon} (recursive : MethodsLocalState methods) + (term : KExpr .anon) (mode : NatSuccMode) : + FramesLocalState ((RecM.whnfModeRec term mode).run methods) := recursive.whnfMode term mode + +theorem whnfCoreFlagsRec {methods : Methods .anon} (recursive : MethodsLocalState methods) + (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.whnfCoreFlagsRec term flags).run methods) := recursive.whnfCoreFlags term flags + +theorem inferOnlyRec {methods : Methods .anon} (recursive : MethodsLocalState methods) + (term : KExpr .anon) : FramesLocalState ((RecM.inferOnlyRec term).run methods) := + withInferOnly (recursive.infer term) + +theorem tryOptional {methods : Methods .anon} {action : RecM .anon α} + (body : FramesLocalState (action.run methods)) : + FramesLocalState ((RecM.tryOptional action).run methods) := by + unfold RecM.tryOptional RecM.try? + exact tryCatch (bind body (fun value => pure (some value))) (fun _ => pure none) + +end FramesLocalState +end Ix.Kernel.Consistency + +namespace Ix.Kernel.Consistency.FramesLocalState + +theorem pureRec {methods : Methods .anon} (value : α) : + FramesLocalState ((Pure.pure value : RecM .anon α).run methods) := pure value + +theorem throwRec {methods : Methods .anon} (error : TcError .anon) : + FramesLocalState ((MonadExceptOf.throw error : RecM .anon α).run methods) := throw error + +theorem throwExceptRec {methods : Methods .anon} (error : TcError .anon) : + FramesLocalState ((MonadExcept.throw error : RecM .anon α).run methods) := throw error + +theorem getRec {methods : Methods .anon} : + FramesLocalState ((MonadState.get : RecM .anon (TcState .anon)).run methods) := get + +theorem liftRec {methods : Methods .anon} {action : TcM .anon α} + (body : FramesLocalState action) : + FramesLocalState ((monadLift action : RecM .anon α).run methods) := body + +theorem liftSelf {action : TcM .anon α} (body : FramesLocalState action) : + FramesLocalState (monadLift action : TcM .anon α) := body + +theorem mapRec {methods : Methods .anon} (f : α → β) {action : RecM .anon α} + (body : FramesLocalState (action.run methods)) : + FramesLocalState ((f <$> action).run methods) := map f body + +theorem bindRead {methods : Methods .anon} {next : Methods .anon → RecM .anon α} + (body : FramesLocalState ((next methods).run methods)) : + FramesLocalState (((read : RecM .anon (Methods .anon)) >>= next).run methods) := body + +theorem tryProbe {methods : Methods .anon} {action : RecM .anon α} + (body : FramesLocalState (action.run methods)) : + FramesLocalState ((RecM.try? action).run methods) := tryOptional body + +theorem bindRec {methods : Methods .anon} {action : RecM .anon α} {next : α → RecM .anon β} + (body : FramesLocalState (action.run methods)) + (rest : ∀ value, FramesLocalState ((next value).run methods)) : + FramesLocalState ((action >>= next).run methods) := bind body rest + +theorem bindTcM {methods : Methods .anon} {action : TcM .anon α} + {next : α → RecM .anon β} + (body : FramesLocalState action) + (rest : ∀ value, FramesLocalState ((next value).run methods)) : + FramesLocalState ((do let value ← action; next value : RecM .anon β).run methods) := by + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + exact bind body rest + +theorem tryFinallyRec {methods : Methods .anon} {action : RecM .anon α} {cleanup : RecM .anon β} + (body : FramesLocalState (action.run methods)) + (clean : FramesLocalState (cleanup.run methods)) : + FramesLocalState ((_root_.tryFinally action cleanup).run methods) := by + change FramesLocalState (_root_.tryFinally (action.run methods) (cleanup.run methods)) + exact tryFinally body clean + +theorem tryCatchRec {methods : Methods .anon} {action : RecM .anon α} + {handler : TcError .anon → RecM .anon α} + (body : FramesLocalState (action.run methods)) + (caught : ∀ error, FramesLocalState ((handler error).run methods)) : + FramesLocalState ((MonadExceptOf.tryCatch action handler).run methods) := tryCatch body caught + +theorem tryCatchExceptRec {methods : Methods .anon} {action : RecM .anon α} + {handler : TcError .anon → RecM .anon α} + (body : FramesLocalState (action.run methods)) + (caught : ∀ error, FramesLocalState ((handler error).run methods)) : + FramesLocalState ((MonadExcept.tryCatch action handler).run methods) := tryCatch body caught + +theorem modifyRec {methods : Methods .anon} {f : TcState .anon → TcState .anon} + (framed : ∀ before, LocalStateFrame before (f before)) : + FramesLocalState ((_root_.modify f : RecM .anon PUnit).run methods) := modify f framed + +theorem forInListTcM (items : List α) (initial : β) (step : α → β → TcM .anon (ForInStep β)) + (framed : ∀ item value, FramesLocalState (step item value)) : + FramesLocalState (forIn items initial step) := by + induction items generalizing initial with + | nil => exact pure _ + | cons item rest ih => + rw [List.forIn_cons] + apply bind (framed item initial) + intro next + cases next with + | done value => exact pure _ + | yield value => exact ih value + +end Ix.Kernel.Consistency.FramesLocalState diff --git a/Ix/Kernel/Verify/Consistency/LocalStateTactic.lean b/Ix/Kernel/Verify/Consistency/LocalStateTactic.lean new file mode 100644 index 000000000..c76b11214 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/LocalStateTactic.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalStateEffects +import Lean.LabelAttribute + +/-! +# Proof search for structural local-state effects + +The tactic composes proved frame rules, unfolds finite monadic control flow, +and applies named helper lemmas or local induction premises. It only introduces +explicit quantifiers; it never unfolds a frame into an unconstrained outcome. +All generated proof terms are checked by Lean. Recursive source workers still +need induction, and recursive method calls need the smaller table's frame. +-/ + +namespace Ix.Kernel.Consistency + +register_label_attr local_state_frame + +private def frameHead : Lean.Expr → Option Lean.Name + | .forallE _ _ body _ => frameHead body + | .mdata _ body => frameHead body + | type => do + if !type.getAppFn.isConstOf ``FramesLocalState then none else do + let action ← type.getAppArgs.back? + let action ← if action.getAppFn.isConstOf ``ReaderT.run then + action.getAppArgs[action.getAppArgs.size - 2]? + else some action + match action.getAppFn with + | .const name _ => some name + | .fvar id => some id.name + | _ => none + +open Lean Elab Tactic in +elab "local_frame_goal" : tactic => do + unless (← Lean.instantiateMVars (← getMainTarget)).consumeMData.getAppFn.isConstOf ``FramesLocalState do + throwError "expected a local-state computation frame" + +open Lean Elab Tactic in +elab "local_relation_goal" : tactic => do + unless (← Lean.instantiateMVars (← getMainTarget)).consumeMData.getAppFn.isConstOf ``LocalStateFrame do + throwError "expected a relation between checker states" + +open Lean Elab Tactic in +elab "local_frame_head " head:ident : tactic => do + unless frameHead (← Lean.instantiateMVars (← getMainTarget)) == some head.getId.eraseMacroScopes do + throwError "different computation head" + +open Lean Elab Tactic in +elab "local_frame_intro" : tactic => do + unless (← Lean.instantiateMVars (← getMainTarget)).consumeMData.isForall do + throwError "expected an explicit universal quantifier" + evalTactic (← `(tactic| intro)) + +open Lean Elab Tactic Meta in +elab "local_frame_assumption" : tactic => withMainContext do + let goal ← getMainGoal + for decl in ← getLCtx do + unless decl.isImplementationDetail do + let saved ← saveState + try + if (← withReducible (goal.apply decl.toExpr)).isEmpty then + replaceMainGoal [] + return + catch _ => pure () + saved.restore + throwError "no local premise closes this frame" + +open Lean Elab Tactic Meta in +elab "local_frame_lemma" : tactic => withMainContext do + let goal ← getMainGoal + let some head := frameHead (← Lean.instantiateMVars (← goal.getType)) | + throwError "expected a named computation" + for name in (← labelled `local_state_frame).reverse do + if frameHead (← getConstInfo name).type != some head then continue + let saved ← saveState + try + let goals ← withReducible (goal.apply (← mkConstWithFreshMVarLevels name)) + for subgoal in goals do + subgoal.withContext subgoal.assumption + replaceMainGoal [] + return + catch _ => saved.restore + throwError "no registered lemma closes this frame" + +macro "local_state" : tactic => `(tactic| + with_reducible repeat' first + | assumption + | local_frame_assumption + | (local_relation_goal; exact ⟨Nat.le_refl _, .refl _, rfl⟩) + | local_frame_intro + | (local_frame_goal; first + | local_frame_lemma + | apply FramesLocalState.bindRead + | exact FramesLocalState.pureRec _ + | exact FramesLocalState.throwRec _ + | exact FramesLocalState.throwExceptRec _ + | exact FramesLocalState.getRec + | (local_frame_head MonadLiftT.monadLift; apply FramesLocalState.liftRec) + | (local_frame_head MonadLiftT.monadLift; apply FramesLocalState.liftSelf) + | (with_reducible apply FramesLocalState.bindRec) + | (with_reducible apply FramesLocalState.bind) + | (local_frame_head Pure.pure; exact FramesLocalState.pure _) + | (local_frame_head MonadExceptOf.throw; exact FramesLocalState.throw _) + | exact FramesLocalState.intern _ + | exact FramesLocalState.runIntern _ + | exact FramesLocalState.get + | exact FramesLocalState.instantiateUnivParams _ _ + | exact FramesLocalState.prims _ + | exact FramesLocalState.tryGetConst _ + | exact FramesLocalState.getConst _ + | exact FramesLocalState.tryGetBlock _ + | exact FramesLocalState.inferKey _ + | exact FramesLocalState.whnfKey _ + | exact FramesLocalState.tick + | exact FramesLocalState.isLetVar _ + | exact FramesLocalState.lookupLetVal _ + | exact FramesLocalState.stepTrace _ _ + | exact FramesLocalState.whnfRec (by assumption) _ + | exact FramesLocalState.whnfModeRec (by assumption) _ _ + | exact FramesLocalState.whnfCoreFlagsRec (by assumption) _ _ + | exact FramesLocalState.inferOnlyRec (by assumption) _ + | exact MethodsLocalState.infer (by assumption) _ + | apply FramesLocalState.modifyRec + | apply FramesLocalState.modify + | apply FramesLocalState.bumpStats + | apply FramesLocalState.bindRec + | apply FramesLocalState.bind + | apply FramesLocalState.map + | apply FramesLocalState.mapRec + | apply FramesLocalState.forInList + | apply FramesLocalState.forInRange + | apply FramesLocalState.forInArray + | apply FramesLocalState.forInListTcM + | apply FramesLocalState.tryFinallyRec + | apply FramesLocalState.tryCatchRec + | apply FramesLocalState.tryCatchExceptRec + | apply FramesLocalState.tryFinally + | apply FramesLocalState.tryCatch + | apply FramesLocalState.runBounded + | apply FramesLocalState.withCheapRecursionDepth + | apply FramesLocalState.withInferOnly + | apply FramesLocalState.tryOptional + | apply FramesLocalState.tryProbe + | split + | dsimp only + | dsimp only [ReaderT.run_bind, ReaderT.run_monadLift])) + +end Ix.Kernel.Consistency diff --git a/Ix/Kernel/Verify/Consistency/RecursiveLocalState.lean b/Ix/Kernel/Verify/Consistency/RecursiveLocalState.lean new file mode 100644 index 000000000..4a4931a89 --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/RecursiveLocalState.lean @@ -0,0 +1,88 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.DefEqLocalState +import Ix.Kernel.Verify.Consistency.ProjectionLocalState + +/-! +# Structural local-state preservation for the complete recursive knot + +Induction on the actual production method-table depth closes the six mutually +dependent state contracts. Public entries select that table from the current +recursive fuel, exactly as `TcM.runRec` does. There are no recursive-method or +loader-effect premises beyond the maintained initial local-state invariant. + +The result preserves local declarations, monotone fresh allocation and the +installed loader on both outcomes. Reduction, conversion and inference still +need their separate semantic correctness proofs for general consistency. +-/ + +namespace Ix.Kernel.Consistency + +/-- Every finite production table satisfies the complete structural contract. +The successor case uses only the strictly smaller table's callbacks. -/ +theorem MethodsLocalState.methodsN (depth : Nat) : + MethodsLocalState (_root_.Ix.Kernel.methodsN (m := .anon) depth) := by + induction depth with + | zero => + exact { + whnf := fun _ => FramesLocalState.throw _ + whnfCore := fun _ => FramesLocalState.throw _ + whnfMode := fun _ _ => FramesLocalState.throw _ + whnfCoreFlags := fun _ _ => FramesLocalState.throw _ + infer := fun _ => FramesLocalState.throw _ + isDefEq := fun _ _ => FramesLocalState.throw _ } + | succ depth recursive => + exact { + whnf := FramesLocalState.whnf recursive + whnfCore := FramesLocalState.whnfCore recursive + whnfMode := FramesLocalState.whnfWithNatSuccMode recursive + whnfCoreFlags := FramesLocalState.whnfCoreWithFlags recursive + infer := infer_framesLocalState_of_whnf recursive.infer + (FramesLocalState.whnf recursive) recursive.isDefEq + isDefEq := FramesLocalState.isDefEq recursive } + +/-- Running from arbitrary current fuel uses a proved finite table, including +the exhausted-depth table and every error-side partial state. -/ +theorem FramesLocalState.runRec {action : RecM .anon α} + (framed : ∀ methods, MethodsLocalState methods → FramesLocalState (action.run methods)) : + FramesLocalState (TcM.runRec action) := by + intro before valid + exact framed (_root_.Ix.Kernel.methodsN before.recFuel.toNat) + (MethodsLocalState.methodsN before.recFuel.toNat) before valid + +end Ix.Kernel.Consistency + +namespace Ix.Kernel.TcM + +open Consistency + +theorem whnf_framesLocalState (term : KExpr .anon) : FramesLocalState (whnf term) := + FramesLocalState.runRec fun _ recursive => FramesLocalState.whnf recursive term + +theorem whnfCore_framesLocalState (term : KExpr .anon) : FramesLocalState (whnfCore term) := + FramesLocalState.runRec fun _ recursive => FramesLocalState.whnfCore recursive term + +theorem whnfNoDelta_framesLocalState (term : KExpr .anon) : FramesLocalState (whnfNoDelta term) := + FramesLocalState.runRec fun _ recursive => FramesLocalState.whnfNoDelta recursive term + +theorem infer_framesLocalState (term : KExpr .anon) : FramesLocalState (infer term) := + FramesLocalState.runRec fun _ recursive => + infer_framesLocalState_of_whnf recursive.infer + (FramesLocalState.whnf recursive) recursive.isDefEq term + +theorem isDefEq_framesLocalState (left right : KExpr .anon) : + FramesLocalState (isDefEq left right) := + FramesLocalState.runRec fun _ recursive => FramesLocalState.isDefEq recursive left right + +theorem ensureSort_framesLocalState (term : KExpr .anon) : FramesLocalState (ensureSort term) := + FramesLocalState.runRec fun _ recursive => + FramesLocalState.ensureSortDirect (FramesLocalState.whnf recursive) term + +theorem ensureForall_framesLocalState (term : KExpr .anon) : FramesLocalState (ensureForall term) := + FramesLocalState.runRec fun _ recursive => + FramesLocalState.ensureForallDirect (FramesLocalState.whnf recursive) term + +end Ix.Kernel.TcM diff --git a/Ix/Kernel/Verify/Consistency/WhnfLocalState.lean b/Ix/Kernel/Verify/Consistency/WhnfLocalState.lean new file mode 100644 index 000000000..584d7dfae --- /dev/null +++ b/Ix/Kernel/Verify/Consistency/WhnfLocalState.lean @@ -0,0 +1,896 @@ +/- +Copyright (c) 2026 Argument Computer Corporation. +SPDX-License-Identifier: MIT OR Apache-2.0 +-/ + +import Ix.Kernel.Verify.Consistency.LocalStateTactic + +/-! +# Structural local-state preservation for production reduction + +The actual full, structural and no-delta WHNF drivers preserve the caller's +local declarations and installed loader and never decrease the fresh-variable +counter, on success and error. The proofs cover primitive reduction, String +expansion, projection, iota, recursor classification, caches, finite workers, +and cleanup. Only calls through the recursive method table require a frame +premise; every direct reduction helper is discharged here. + +This is the structural state component of consistency. It does not assert +the semantic validity of a cached expression, reduction, or loaded declaration. +-/ + +namespace Ix.Kernel.Consistency + +namespace FramesLocalState + +-- Apply the proved intern effects without expanding the intern implementation +-- while elaborating a long sequence of requests. +attribute [local irreducible] TcM.intern TcM.runIntern + +@[local_state_frame] theorem mkNatSucc {methods : Methods .anon} + (pred : KExpr .anon) : + FramesLocalState ((RecM.mkNatSucc pred).run methods) := by + unfold RecM.mkNatSucc + local_state + +@[local_state_frame] theorem mkNatAdd {methods : Methods .anon} + (left right : KExpr .anon) : + FramesLocalState ((RecM.mkNatAdd left right).run methods) := by + unfold RecM.mkNatAdd + local_state + +@[local_state_frame] theorem isNatBinArithAddr {methods : Methods .anon} + (addr : Address) : + FramesLocalState ((RecM.isNatBinArithAddr addr).run methods) := by + unfold RecM.isNatBinArithAddr + local_state + +@[local_state_frame] theorem isNatBinPredAddr {methods : Methods .anon} + (addr : Address) : + FramesLocalState ((RecM.isNatBinPredAddr addr).run methods) := by + unfold RecM.isNatBinPredAddr + local_state + +@[local_state_frame] theorem boolLitValue {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.boolLitValue term).run methods) := by + unfold RecM.boolLitValue + local_state + +@[local_state_frame] theorem isNatStuckRecursorAddr {methods : Methods .anon} + (addr : Address) : + FramesLocalState ((RecM.isNatStuckRecursorAddr addr).run methods) := by + unfold RecM.isNatStuckRecursorAddr + local_state + + +@[local_state_frame] theorem unfoldConstValue {methods : Methods .anon} (head value : KExpr .anon) + (levels : Array (KUniv .anon)) : + FramesLocalState ((RecM.unfoldConstValue head value levels).run methods) := by + unfold RecM.unfoldConstValue + local_state + +@[local_state_frame] theorem natToConstructor {methods : Methods .anon} (value : Nat) : + FramesLocalState ((RecM.natToConstructor (m := .anon) value).run methods) := by + unfold RecM.natToConstructor + local_state + +@[local_state_frame] theorem tryDeltaUnfold {methods : Methods .anon} (term : KExpr .anon) : + FramesLocalState ((RecM.tryDeltaUnfold term).run methods) := by + unfold RecM.tryDeltaUnfold + local_state + +@[local_state_frame] theorem pushLocal (type : KExpr .anon) : FramesLocalState (TcM.pushLocal type) := + fun _ _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + +@[local_state_frame] theorem pushLet (type value : KExpr .anon) : FramesLocalState (TcM.pushLet type value) := + fun _ _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + +@[local_state_frame] theorem popLocal : FramesLocalState (TcM.popLocal (m := .anon)) := + fun _ _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + +@[local_state_frame] theorem saveDepth : FramesLocalState (TcM.saveDepth (m := .anon)) := + fun _ _ => .refl _ + +@[local_state_frame] theorem enterDispatch : FramesLocalState (RecM.enterDispatch (m := .anon)) := by + apply ofWF + intro before + unfold RecM.enterDispatch + apply TcM.WF.bind + (Q₁ := fun observed after => observed = before ∧ after = before) + (TcM.WF.get fun _ => ⟨rfl, rfl⟩) + rintro observed after ⟨rfl, rfl⟩ + dsimp only + split + · exact TcM.WF.throw (fun _ => trivial) + · exact TcM.WF.set (fun valid => + ⟨⟨valid.1.coherent, valid.1.allocated, valid.1.loader⟩, + ⟨valid.2.counter, valid.2.context, valid.2.loader⟩⟩) (fun _ => trivial) + +@[local_state_frame] theorem exitDispatch : FramesLocalState (RecM.exitDispatch (m := .anon)) := + fun _ _ => ⟨Nat.le_refl _, .refl _, rfl⟩ + +@[local_state_frame] theorem callIsDefEq {methods : Methods .anon} (recursive : MethodsLocalState methods) + (left right : KExpr .anon) : + FramesLocalState ((RecM.callIsDefEq left right).run methods) := by + unfold RecM.callIsDefEq + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + apply bind enterDispatch + intro _ + change FramesLocalState (_root_.tryFinally (methods.isDefEq left right) (RecM.exitDispatch (m := .anon))) + exact tryFinally (recursive.isDefEq left right) exitDispatch + +@[local_state_frame] theorem evalNatOffsetLiteralFuel {methods : Methods .anon} (fuel : Nat) (term : KExpr .anon) : + FramesLocalState ((RecM.evalNatOffsetLiteralFuel fuel term).run methods) := by + induction fuel generalizing term with + | zero => exact pure _ + | succ fuel ih => + rw [RecM.evalNatOffsetLiteralFuel] + local_state + +@[local_state_frame] theorem natOffsetFuel {methods : Methods .anon} (fuel : Nat) (term : KExpr .anon) : + FramesLocalState ((RecM.natOffsetFuel fuel term).run methods) := by + induction fuel generalizing term with + | zero => exact pure _ + | succ fuel ih => + have literal := evalNatOffsetLiteralFuel (methods := methods) fuel + rw [RecM.natOffsetFuel] + rcases spine : term.collectSpine with ⟨head, args⟩ + dsimp only + cases head <;> dsimp only + all_goals try exact pure _ + simp only [ReaderT.run_bind] + apply bind (prims methods) + intro primitives + split + · exact bind (ih _) (fun _ => pure _) + · split + · apply bind (literal _) + intro result + cases result with + | none => exact pure _ + | some value => exact bind (ih _) (fun _ => pure _) + · exact pure _ + +@[local_state_frame] theorem finishAppResult {methods : Methods .anon} (term : KExpr .anon) + (args : Array (KExpr .anon)) (consumed : Nat) : + FramesLocalState ((RecM.finishAppResult term args consumed).run methods) := by + unfold RecM.finishAppResult + local_state + +@[local_state_frame] theorem tryReduceNativeMarker {methods : Methods .anon} (recursive : MethodsLocalState methods) + (primitives : Primitives .anon) (isBool : Bool) (id : KId .anon) (levels : Array (KUniv .anon)) : + FramesLocalState ((RecM.tryReduceNativeMarker primitives isBool id levels).run methods) := by + unfold RecM.tryReduceNativeMarker + local_state + + +@[local_state_frame] theorem strLitListToConstructor {methods : Methods .anon} + (charOfNat cons : KExpr .anon) (chars : List Char) (tail : KExpr .anon) : + FramesLocalState ((RecM.strLitListToConstructor charOfNat cons chars tail).run methods) := by + induction chars generalizing tail with + | nil => exact pure _ + | cons char chars ih => + rw [RecM.strLitListToConstructor] + simp only [ReaderT.run_bind, ReaderT.run_monadLift] + exact bind (intern _) fun _ => bind (intern _) fun _ => + bind (intern _) fun _ => bind (intern _) ih + +@[local_state_frame] theorem natOffset {methods : Methods .anon} + (term : KExpr .anon) (depth : Nat) : + FramesLocalState ((RecM.natOffset term depth).run methods) := by + unfold RecM.natOffset + local_state + +@[local_state_frame] theorem natOffsetOrZero {methods : Methods .anon} + (term : KExpr .anon) (depth : Nat) : + FramesLocalState ((RecM.natOffsetOrZero term depth).run methods) := by + unfold RecM.natOffsetOrZero + local_state + +@[local_state_frame] theorem evalNatOffsetLiteral {methods : Methods .anon} + (term : KExpr .anon) (depth : Nat) : + FramesLocalState ((RecM.evalNatOffsetLiteral term depth).run methods) := by + unfold RecM.evalNatOffsetLiteral + local_state + +@[local_state_frame] theorem natOffsetDecompose {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.natOffsetDecompose term).run methods) := by + unfold RecM.natOffsetDecompose + local_state + +@[local_state_frame] theorem natOffsetRebuild {methods : Methods .anon} + (base : Option (KExpr .anon)) (offset : Nat) : + FramesLocalState ((RecM.natOffsetRebuild base offset).run methods) := by + unfold RecM.natOffsetRebuild + local_state + +@[local_state_frame] theorem strLitToConstructor {methods : Methods .anon} + (value : String) : + FramesLocalState ((RecM.strLitToConstructor value).run methods) := by + unfold RecM.strLitToConstructor + with_reducible refine bindRec (prims methods) ?_ + intro p + refine bindTcM (intern (.mkConst p.charType #[])) ?_ + intro charType + refine bindTcM (intern (.mkConst p.charOfNat #[])) ?_ + intro charOfNat + refine bindTcM (intern (.mkConst p.stringOfList #[])) ?_ + intro stringMk + refine bindTcM (intern (.mkConst p.listNil #[.mkZero])) ?_ + intro listNil + refine bindTcM (intern (KExpr.mkApp listNil charType)) ?_ + intro nil + refine bindTcM (intern (.mkConst p.listCons #[.mkZero])) ?_ + intro listCons + refine bindTcM (intern (KExpr.mkApp listCons charType)) ?_ + intro cons + refine bindRec (strLitListToConstructor charOfNat cons value.toList.reverse nil) ?_ + intro list + exact liftRec (intern (KExpr.mkApp stringMk list)) + +@[local_state_frame] theorem internIntLit {methods : Methods .anon} + (value : _root_.Int) : + FramesLocalState ((RecM.internIntLit value).run methods) := by + unfold RecM.internIntLit + local_state + +@[local_state_frame] theorem applyIotaArg {methods : Methods .anon} + (term arg : KExpr .anon) (transient : Bool) : + FramesLocalState ((RecM.applyIotaArg term arg transient).run methods) := by + unfold RecM.applyIotaArg + local_state + +@[local_state_frame] theorem applyIotaArgs {methods : Methods .anon} + (term : KExpr .anon) (args : Array (KExpr .anon)) (transient : Bool) : + FramesLocalState ((RecM.applyIotaArgs term args transient).run methods) := by + unfold RecM.applyIotaArgs + local_state + +@[local_state_frame] theorem applyIotaRule {methods : Methods .anon} + (rule : RecRule .anon) (levels : Array (KUniv .anon)) + (recursor : IotaInfo .anon) (spine args : Array (KExpr .anon)) (fields : Nat) (transient : Bool) : + FramesLocalState ((RecM.applyIotaRule rule levels recursor spine args fields transient).run methods) := by + unfold RecM.applyIotaRule + local_state + +@[local_state_frame] theorem tryApplyIotaCtor {methods : Methods .anon} + (recursor : IotaInfo .anon) (levels : Array (KUniv .anon)) + (spine args : Array (KExpr .anon)) (index fields : Nat) (transient : Bool) : + FramesLocalState ((RecM.tryApplyIotaCtor recursor levels spine args index fields transient).run methods) := by + unfold RecM.tryApplyIotaCtor + local_state + +@[local_state_frame] theorem isNatLiteralRecursorApp {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.isNatLiteralRecursorApp term).run methods) := by + unfold RecM.isNatLiteralRecursorApp + local_state + +@[local_state_frame] theorem isTransientNatLiteralWork {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.isTransientNatLiteralWork term).run methods) := by + unfold RecM.isTransientNatLiteralWork + local_state + +@[local_state_frame] theorem cleanupNatOffsetMajor {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.cleanupNatOffsetMajor term).run methods) := by + unfold RecM.cleanupNatOffsetMajor + local_state + +@[local_state_frame] theorem projectDecidableFinValMinor {methods : Methods .anon} + (id : KId .anon) (field : UInt64) (minor : KExpr .anon) : + FramesLocalState ((RecM.projectDecidableFinValMinor id field minor).run methods) := by + unfold RecM.projectDecidableFinValMinor + local_state + +@[local_state_frame] theorem tryReduceFinValDecidableRec {methods : Methods .anon} + (id : KId .anon) (field : UInt64) + (head : KExpr .anon) (args : Array (KExpr .anon)) : + FramesLocalState ((RecM.tryReduceFinValDecidableRec id field head args).run methods) := by + unfold RecM.tryReduceFinValDecidableRec + local_state + +@[local_state_frame] theorem tryReduceProjectionDefinition {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.tryReduceProjectionDefinition term).run methods) := by + unfold RecM.tryReduceProjectionDefinition + local_state + +@[local_state_frame] theorem natRecLiteralParts {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.natRecLiteralParts term).run methods) := by + unfold RecM.natRecLiteralParts + local_state + +@[local_state_frame] theorem isStuckNatPredicateProbe {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.isStuckNatPredicateProbe term).run methods) := by + unfold RecM.isStuckNatPredicateProbe + local_state + +@[local_state_frame] theorem bitvecOfNatArgs {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.bitvecOfNatArgs term).run methods) := by + unfold RecM.bitvecOfNatArgs + local_state + +@[local_state_frame] theorem charOfNatExpr {methods : Methods .anon} + (value : Nat) : + FramesLocalState ((RecM.charOfNatExpr value).run methods) := by + unfold RecM.charOfNatExpr + local_state + +@[local_state_frame] theorem tryReduceStringLiteral {methods : Methods .anon} + (primitives : Primitives .anon) (id : KId .anon) (value : String) : + FramesLocalState ((RecM.tryReduceStringLiteral primitives id value).run methods) := by + unfold RecM.tryReduceStringLiteral + local_state + +@[local_state_frame] theorem tryReduceString {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.tryReduceString term).run methods) := by + unfold RecM.tryReduceString + local_state + +@[local_state_frame] theorem discoverBlockInductives {methods : Methods .anon} + (block : KId .anon) : + FramesLocalState ((RecM.discoverBlockInductives block).run methods) := by + unfold RecM.discoverBlockInductives + local_state + +@[local_state_frame] theorem tryProjReduceTail {methods : Methods .anon} + (id : KId .anon) (field : UInt64) (value : KExpr .anon) : + FramesLocalState ((RecM.tryProjReduceTail id field value).run methods) := by + unfold RecM.tryProjReduceTail + local_state + +@[local_state_frame] theorem tryProjPrepare {methods : Methods .anon} + (recursive : MethodsLocalState methods) (value : KExpr .anon) : + FramesLocalState ((RecM.tryProjPrepare value).run methods) := by + rw [RecM.tryProjPrepare_eq] + local_state + +@[local_state_frame] theorem tryProjReduce {methods : Methods .anon} + (recursive : MethodsLocalState methods) (id : KId .anon) (field : UInt64) (value : KExpr .anon) : + FramesLocalState ((RecM.tryProjReduce id field value).run methods) := by + rw [RecM.tryProjReduce_eq] + local_state + +@[local_state_frame] theorem tryProjAppReduce {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.tryProjAppReduce term flags).run methods) := by + unfold RecM.tryProjAppReduce + local_state + +@[local_state_frame] theorem tryProjAppReduceFinished {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.tryProjAppReduceFinished term flags).run methods) := by + unfold RecM.tryProjAppReduceFinished + local_state + + +@[local_state_frame] theorem restoreDepthGo (saved fuel : Nat) : + FramesLocalState (TcM.restoreDepth.go (m := .anon) saved fuel) := by + induction fuel with + | zero => exact pure _ + | succ fuel ih => + rw [TcM.restoreDepth.go] + local_state + +@[local_state_frame] theorem restoreDepth (saved : Nat) : + FramesLocalState (TcM.restoreDepth (m := .anon) saved) := by + unfold TcM.restoreDepth + local_state + +@[local_state_frame] theorem peelMajorForalls {methods : Methods .anon} + (recursive : MethodsLocalState methods) (fuel : Nat) (type : KExpr .anon) : + FramesLocalState ((RecM.peelMajorForalls fuel type).run methods) := by + induction fuel generalizing type with + | zero => exact pure _ + | succ fuel ih => + rw [RecM.peelMajorForalls] + local_state + +@[local_state_frame] theorem scanMajorInductiveStep {methods : Methods .anon} + (next : KExpr .anon → RecM .anon (KId .anon)) + (framed : ∀ type, FramesLocalState ((next type).run methods)) (type : KExpr .anon) : + FramesLocalState ((RecM.scanMajorInductiveStep next type).run methods) := by + unfold RecM.scanMajorInductiveStep + local_state + +@[local_state_frame] theorem scanMajorInductive {methods : Methods .anon} + (recursive : MethodsLocalState methods) (fuel : Nat) (type : KExpr .anon) : + FramesLocalState ((RecM.scanMajorInductive fuel type).run methods) := by + induction fuel generalizing type with + | zero => exact throw _ + | succ fuel ih => + rw [RecM.scanMajorInductive, ReaderT.run_bind] + exact bind (whnfRec recursive type) (scanMajorInductiveStep _ ih) + +@[local_state_frame] theorem getMajorInductiveId {methods : Methods .anon} + (recursive : MethodsLocalState methods) (type : KExpr .anon) (skip : UInt64) : + FramesLocalState ((RecM.getMajorInductiveId type skip).run methods) := by + unfold RecM.getMajorInductiveId + local_state + +@[local_state_frame] theorem computeIsRecParamStepAfterWhnf {methods : Methods .anon} + (type reduced : KExpr .anon) : + FramesLocalState ((RecM.computeIsRecParamStepAfterWhnf type reduced).run methods) := by + unfold RecM.computeIsRecParamStepAfterWhnf + local_state + +@[local_state_frame] theorem computeIsRecParamStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (type : KExpr .anon) : + FramesLocalState ((RecM.computeIsRecParamStep type).run methods) := by + unfold RecM.computeIsRecParamStep + local_state + +@[local_state_frame] theorem computeIsRecFieldStepAfterWhnf {methods : Methods .anon} + (blocks : Array Address) (reduced : KExpr .anon) : + FramesLocalState ((RecM.computeIsRecFieldStepAfterWhnf blocks reduced).run methods) := by + unfold RecM.computeIsRecFieldStepAfterWhnf + local_state + +@[local_state_frame] theorem computeIsRecFieldStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (blocks : Array Address) (type : KExpr .anon) : + FramesLocalState ((RecM.computeIsRecFieldStep blocks type).run methods) := by + unfold RecM.computeIsRecFieldStep + local_state + +@[local_state_frame] theorem computeIsRecCtor {methods : Methods .anon} + (recursive : MethodsLocalState methods) (type : KExpr .anon) + (params : Nat) (blocks : Array Address) : + FramesLocalState ((RecM.computeIsRecCtor type params blocks).run methods) := by + unfold RecM.computeIsRecCtor + local_state + +@[local_state_frame] theorem computeIsRec {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ctors : Array (KId .anon)) + (params : Nat) (blocks : Array Address) : + FramesLocalState ((RecM.computeIsRec ctors params blocks).run methods) := by + unfold RecM.computeIsRec + local_state + +@[local_state_frame] theorem cacheIsRec {methods : Methods .anon} + (ind : KId .anon) (value : Bool) : + FramesLocalState ((RecM.cacheIsRec ind value).run methods) := by + unfold RecM.cacheIsRec + local_state + +@[local_state_frame] theorem eraseCachedIsRec {methods : Methods .anon} (ind : KId .anon) : + FramesLocalState ((RecM.eraseCachedIsRec ind).run methods) := by + unfold RecM.eraseCachedIsRec + local_state + +@[local_state_frame] theorem computedIsRecClassify {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ind : KId .anon) (ctors : Array (KId .anon)) + (params : Nat) (blocks : Array Address) : + FramesLocalState ((RecM.computedIsRecClassify ind ctors params blocks).run methods) := by + unfold RecM.computedIsRecClassify + local_state + +@[local_state_frame] theorem computedIsRecMiss {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ind : KId .anon) (params : UInt64) + (ctors : Array (KId .anon)) (block : KId .anon) : + FramesLocalState ((RecM.computedIsRecMiss ind params ctors block).run methods) := by + unfold RecM.computedIsRecMiss + local_state + +@[local_state_frame] theorem computedIsRec {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ind : KId .anon) : + FramesLocalState ((RecM.computedIsRec ind).run methods) := by + unfold RecM.computedIsRec + local_state + +@[local_state_frame] theorem isStructLike {methods : Methods .anon} + (recursive : MethodsLocalState methods) (ind : KId .anon) : + FramesLocalState ((RecM.isStructLike ind).run methods) := by + unfold RecM.isStructLike + local_state + +@[local_state_frame] theorem finishStructEtaFields {methods : Methods .anon} + (ind : KId .anon) (major : KExpr .anon) (fuel field : Nat) (result : KExpr .anon) : + FramesLocalState ((RecM.finishStructEtaFields ind major fuel field result).run methods) := by + induction fuel generalizing field result with + | zero => exact pure _ + | succ fuel ih => + rw [RecM.finishStructEtaFields] + local_state + +@[local_state_frame] theorem finishStructEtaResult {methods : Methods .anon} + (ind : KId .anon) (major rhs : KExpr .anon) (fields : UInt64) + (prefixArgs trailing : Array (KExpr .anon)) : + FramesLocalState ((RecM.finishStructEtaResult ind major rhs fields prefixArgs trailing).run methods) := by + unfold RecM.finishStructEtaResult + local_state + +@[local_state_frame] theorem finishStructEtaAfterSort {methods : Methods .anon} + (levels : Array (KUniv .anon)) (spine : Array (KExpr .anon)) + (recursor : IotaInfo .anon) (rule : RecRule .anon) (ind : KId .anon) + (major sort : KExpr .anon) : + FramesLocalState ((RecM.finishStructEtaAfterSort levels spine recursor rule ind major sort).run methods) := by + unfold RecM.finishStructEtaAfterSort + local_state + +@[local_state_frame] theorem tryStructEtaAfterInductive {methods : Methods .anon} + (recursive : MethodsLocalState methods) (levels : Array (KUniv .anon)) (spine : Array (KExpr .anon)) + (recursor : IotaInfo .anon) (rule : RecRule .anon) (ind : KId .anon) : + FramesLocalState ((RecM.tryStructEtaAfterInductive levels spine recursor rule ind).run methods) := by + unfold RecM.tryStructEtaAfterInductive + local_state + +@[local_state_frame] theorem tryStructEtaIota {methods : Methods .anon} + (recursive : MethodsLocalState methods) (id : KId .anon) (recursor : IotaInfo .anon) + (levels : Array (KUniv .anon)) (spine : Array (KExpr .anon)) : + FramesLocalState ((RecM.tryStructEtaIota id recursor levels spine).run methods) := by + unfold RecM.tryStructEtaIota + local_state + +@[local_state_frame] theorem verifyKSynthCandidate {methods : Methods .anon} + (recursive : MethodsLocalState methods) (type : KExpr .anon) (ctor : KId .anon) (levels : Array (KUniv .anon)) + (args : Array (KExpr .anon)) (params : Nat) : + FramesLocalState ((RecM.verifyKSynthCandidate type ctor levels args params).run methods) := by + unfold RecM.verifyKSynthCandidate + local_state + +@[local_state_frame] theorem selectKSynthCandidate {methods : Methods .anon} + (recursive : MethodsLocalState methods) (type : KExpr .anon) (head : KId .anon) (levels : Array (KUniv .anon)) + (args : Array (KExpr .anon)) (ind : KId .anon) (params : Nat) : + FramesLocalState ((RecM.selectKSynthCandidate type head levels args ind params).run methods) := by + unfold RecM.selectKSynthCandidate + local_state + +@[local_state_frame] theorem synthCtorWhenK {methods : Methods .anon} + (recursive : MethodsLocalState methods) (major : KExpr .anon) (id : KId .anon) + (recursor : IotaInfo .anon) (levels : Array (KUniv .anon)) : + FramesLocalState ((RecM.synthCtorWhenK major id recursor levels).run methods) := by + unfold RecM.synthCtorWhenK + local_state + +@[local_state_frame] theorem tryIotaCtorOrStructEta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (id : KId .anon) (recursor : IotaInfo .anon) + (levels : Array (KUniv .anon)) (spine : Array (KExpr .anon)) + (major : KExpr .anon) (transient : Bool) : + FramesLocalState ((RecM.tryIotaCtorOrStructEta id recursor levels spine major transient).run methods) := by + unfold RecM.tryIotaCtorOrStructEta + local_state + +@[local_state_frame] theorem tryIotaAfterCleanup {methods : Methods .anon} + (recursive : MethodsLocalState methods) (flags : WhnfFlags) (id : KId .anon) (recursor : IotaInfo .anon) + (levels : Array (KUniv .anon)) (spine : Array (KExpr .anon)) + (major : KExpr .anon) (transient : Bool) : + FramesLocalState ((RecM.tryIotaAfterCleanup flags id recursor levels spine major transient).run methods) := by + unfold RecM.tryIotaAfterCleanup + local_state + +@[local_state_frame] theorem tryIotaAfterMajorWhnf {methods : Methods .anon} + (recursive : MethodsLocalState methods) (flags : WhnfFlags) (id : KId .anon) (recursor : IotaInfo .anon) + (levels : Array (KUniv .anon)) (spine : Array (KExpr .anon)) + (major : KExpr .anon) : + FramesLocalState ((RecM.tryIotaAfterMajorWhnf flags id recursor levels spine major).run methods) := by + unfold RecM.tryIotaAfterMajorWhnf + local_state + +@[local_state_frame] theorem tryIotaWithFlags {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.tryIotaWithFlags term flags).run methods) := by + unfold RecM.tryIotaWithFlags + local_state + + +@[local_state_frame] theorem deltaUnfoldOne {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.deltaUnfoldOne term).run methods) := by + unfold RecM.deltaUnfoldOne + local_state + +@[local_state_frame] theorem isNatSuccSpine {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.isNatSuccSpine term).run methods) := by + unfold RecM.isNatSuccSpine + local_state + +@[local_state_frame] theorem recordNatSuccStuck {methods : Methods .anon} + (visited : Array (Address × Address)) : + FramesLocalState ((RecM.recordNatSuccStuck visited).run methods) := by + unfold RecM.recordNatSuccStuck + local_state + +@[local_state_frame] theorem tryReduceNatSuccPeelMiss {methods : Methods .anon} + (reduced current : KExpr .anon) (offset : Nat) + (visited : Array (Address × Address)) (key : Address × Address) : + FramesLocalState ((RecM.tryReduceNatSuccPeelMiss reduced current offset visited key).run methods) := by + unfold RecM.tryReduceNatSuccPeelMiss + local_state + +@[local_state_frame] theorem tryReduceNatSuccPeelAfterKey {methods : Methods .anon} + (reduced current : KExpr .anon) (offset : Nat) + (visited : Array (Address × Address)) (key : Address × Address) : + FramesLocalState ((RecM.tryReduceNatSuccPeelAfterKey reduced current offset visited key).run methods) := by + unfold RecM.tryReduceNatSuccPeelAfterKey + local_state + +@[local_state_frame] theorem tryReduceNatSuccPeel {methods : Methods .anon} + (reduced current : KExpr .anon) (offset : Nat) + (visited : Array (Address × Address)) : + FramesLocalState ((RecM.tryReduceNatSuccPeel reduced current offset visited).run methods) := by + unfold RecM.tryReduceNatSuccPeel + local_state + +@[local_state_frame] theorem tryReduceNatSuccAfterWhnf {methods : Methods .anon} + (reduced : KExpr .anon) (offset : Nat) + (visited : Array (Address × Address)) : + FramesLocalState ((RecM.tryReduceNatSuccAfterWhnf reduced offset visited).run methods) := by + unfold RecM.tryReduceNatSuccAfterWhnf + local_state + +@[local_state_frame] theorem isNatSuccIhStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (step : KExpr .anon) : + FramesLocalState ((RecM.isNatSuccIhStep step).run methods) := by + unfold RecM.isNatSuccIhStep + local_state + +@[local_state_frame] theorem tryReduceNatSuccLinearRec {methods : Methods .anon} + (recursive : MethodsLocalState methods) (arg : KExpr .anon) (offset : Nat) : + FramesLocalState ((RecM.tryReduceNatSuccLinearRec arg offset).run methods) := by + unfold RecM.tryReduceNatSuccLinearRec + local_state + +@[local_state_frame] theorem tryReduceNatSuccIterStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (state : KExpr .anon × Nat × Array (Address × Address)) : + FramesLocalState ((RecM.tryReduceNatSuccIterStep state).run methods) := by + unfold RecM.tryReduceNatSuccIterStep + local_state + +@[local_state_frame] theorem tryReduceNatSuccIter {methods : Methods .anon} + (recursive : MethodsLocalState methods) (arg : KExpr .anon) : + FramesLocalState ((RecM.tryReduceNatSuccIter arg).run methods) := by + unfold RecM.tryReduceNatSuccIter + local_state + +@[local_state_frame] theorem whnfNatReducerArg {methods : Methods .anon} + (recursive : MethodsLocalState methods) (arg : KExpr .anon) : + FramesLocalState ((RecM.whnfNatReducerArg arg).run methods) := by + unfold RecM.whnfNatReducerArg + local_state + +@[local_state_frame] theorem tryReduceNatPredicate {methods : Methods .anon} + (recursive : MethodsLocalState methods) (addr : Address) (args : Array (KExpr .anon)) : + FramesLocalState ((RecM.tryReduceNatPredicate addr args).run methods) := by + unfold RecM.tryReduceNatPredicate + local_state + +@[local_state_frame] theorem tryReduceNatWithSuccMode {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (mode : NatSuccMode) : + FramesLocalState ((RecM.tryReduceNatWithSuccMode term mode).run methods) := by + unfold RecM.tryReduceNatWithSuccMode + local_state + +@[local_state_frame] theorem tryReduceNat {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.tryReduceNat term).run methods) := by + unfold RecM.tryReduceNat + local_state + +@[local_state_frame] theorem tryNatOffsetStuck {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.tryNatOffsetStuck term).run methods) := by + unfold RecM.tryNatOffsetStuck + local_state + +@[local_state_frame] theorem buildNatDecidableTrue {methods : Methods .anon} + (primitives : Primitives .anon) (prop : KExpr .anon) + (args : Array (KExpr .anon)) (proofFn : KId .anon) (level : KUniv .anon) : + FramesLocalState ((RecM.buildNatDecidableTrue primitives prop args proofFn level).run methods) := by + unfold RecM.buildNatDecidableTrue + local_state + +@[local_state_frame] theorem buildNatDecidableFalse {methods : Methods .anon} + (primitives : Primitives .anon) (prop : KExpr .anon) + (args : Array (KExpr .anon)) (proofFn : KId .anon) (level : KUniv .anon) : + FramesLocalState ((RecM.buildNatDecidableFalse primitives prop args proofFn level).run methods) := by + unfold RecM.buildNatDecidableFalse + local_state + +@[local_state_frame] theorem inferDecidableProp {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.inferDecidableProp term).run methods) := by + unfold RecM.inferDecidableProp + local_state + +@[local_state_frame] theorem tryNormalizeIntDecidable {methods : Methods .anon} + (recursive : MethodsLocalState methods) (addr : Address) (args : Array (KExpr .anon)) : + FramesLocalState ((RecM.tryNormalizeIntDecidable addr args).run methods) := by + unfold RecM.tryNormalizeIntDecidable + local_state + +@[local_state_frame] theorem tryReduceDecidable {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.tryReduceDecidable term).run methods) := by + unfold RecM.tryReduceDecidable + local_state + +@[local_state_frame] theorem tryQuotReduce {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.tryQuotReduce term).run methods) := by + unfold RecM.tryQuotReduce + local_state + + +@[local_state_frame] theorem tryEvalNatValueForPredFuel {methods : Methods .anon} + (recursive : MethodsLocalState methods) (fuel : Nat) (term : KExpr .anon) : + FramesLocalState ((RecM.tryEvalNatValueForPredFuel fuel term).run methods) := by + induction fuel generalizing term with + | zero => exact pure _ + | succ fuel ih => + rw [RecM.tryEvalNatValueForPredFuel] + local_state + +@[local_state_frame] theorem tryEvalNatValueForPred {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (depth : Nat) : + FramesLocalState ((RecM.tryEvalNatValueForPred term depth).run methods) := by + unfold RecM.tryEvalNatValueForPred + local_state + +@[local_state_frame] theorem tryReduceBitvecToNat {methods : Methods .anon} + (recursive : MethodsLocalState methods) (value : KExpr .anon) : + FramesLocalState ((RecM.tryReduceBitvecToNat value).run methods) := by + unfold RecM.tryReduceBitvecToNat + local_state + +@[local_state_frame] theorem bitvecToNatExpr {methods : Methods .anon} + (recursive : MethodsLocalState methods) (width value : KExpr .anon) : + FramesLocalState ((RecM.bitvecToNatExpr width value).run methods) := by + unfold RecM.bitvecToNatExpr + local_state + +@[local_state_frame] theorem tryReduceBitvecUlt {methods : Methods .anon} + (recursive : MethodsLocalState methods) (width left right : KExpr .anon) : + FramesLocalState ((RecM.tryReduceBitvecUlt width left right).run methods) := by + unfold RecM.tryReduceBitvecUlt + local_state + +@[local_state_frame] theorem tryReduceBitvecLtProp {methods : Methods .anon} + (recursive : MethodsLocalState methods) (prop : KExpr .anon) : + FramesLocalState ((RecM.tryReduceBitvecLtProp prop).run methods) := by + unfold RecM.tryReduceBitvecLtProp + local_state + +@[local_state_frame] theorem tryReduceBitvec {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.tryReduceBitvec term).run methods) := by + unfold RecM.tryReduceBitvec + local_state + +@[local_state_frame] theorem tryReduceNative {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.tryReduceNative term).run methods) := by + unfold RecM.tryReduceNative + local_state + + +@[local_state_frame] theorem whnfCoreWithFlagsStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.whnfCoreWithFlagsStep term flags).run methods) := by + unfold RecM.whnfCoreWithFlagsStep + local_state + +@[local_state_frame] theorem whnfCoreWithFlagsUncached {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.whnfCoreWithFlagsUncached term flags).run methods) := by + unfold RecM.whnfCoreWithFlagsUncached + local_state + +@[local_state_frame] theorem whnfCoreWithFlagsNonLeaf {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.whnfCoreWithFlagsNonLeaf term flags).run methods) := by + unfold RecM.whnfCoreWithFlagsNonLeaf + local_state + +@[local_state_frame] theorem whnfCoreWithFlags {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) : + FramesLocalState ((RecM.whnfCoreWithFlags term flags).run methods) := by + unfold RecM.whnfCoreWithFlags + local_state + +@[local_state_frame] theorem whnfCore {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.whnfCore term).run methods) := by + unfold RecM.whnfCore + local_state + +@[local_state_frame] theorem whnfCoreForDefEq {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.whnfCoreForDefEq term).run methods) := by + unfold RecM.whnfCoreForDefEq + local_state + +@[local_state_frame] theorem whnfNoDeltaReducersStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (flags : WhnfFlags) (mode : NatSuccMode) (term : KExpr .anon) : + FramesLocalState ((RecM.whnfNoDeltaReducersStep flags mode term).run methods) := by + unfold RecM.whnfNoDeltaReducersStep + local_state + +@[local_state_frame] theorem whnfNoDeltaImplStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (flags : WhnfFlags) (mode : NatSuccMode) (term : KExpr .anon) : + FramesLocalState ((RecM.whnfNoDeltaImplStep flags mode term).run methods) := by + unfold RecM.whnfNoDeltaImplStep + local_state + +@[local_state_frame] theorem whnfNoDeltaImplUncached {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) (mode : NatSuccMode) : + FramesLocalState ((RecM.whnfNoDeltaImplUncached term flags mode).run methods) := by + unfold RecM.whnfNoDeltaImplUncached + local_state + +@[local_state_frame] theorem whnfNoDeltaImplNonLeaf {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) (mode : NatSuccMode) : + FramesLocalState ((RecM.whnfNoDeltaImplNonLeaf term flags mode).run methods) := by + unfold RecM.whnfNoDeltaImplNonLeaf + local_state + +@[local_state_frame] theorem whnfNoDeltaImpl {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (flags : WhnfFlags) (mode : NatSuccMode) : + FramesLocalState ((RecM.whnfNoDeltaImpl term flags mode).run methods) := by + unfold RecM.whnfNoDeltaImpl + local_state + +@[local_state_frame] theorem whnfNoDelta {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.whnfNoDelta term).run methods) := by + unfold RecM.whnfNoDelta + local_state + +@[local_state_frame] theorem whnfNoDeltaForDefEq {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.whnfNoDeltaForDefEq term).run methods) := by + unfold RecM.whnfNoDeltaForDefEq + local_state + +@[local_state_frame] theorem whnfWithNatSuccModeStep {methods : Methods .anon} + (recursive : MethodsLocalState methods) (mode : NatSuccMode) (state : KExpr .anon × Std.HashSet Address) : + FramesLocalState ((RecM.whnfWithNatSuccModeStep mode state).run methods) := by + unfold RecM.whnfWithNatSuccModeStep + local_state + +@[local_state_frame] theorem whnfWithNatSuccModeUncached {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (mode : NatSuccMode) : + FramesLocalState ((RecM.whnfWithNatSuccModeUncached term mode).run methods) := by + unfold RecM.whnfWithNatSuccModeUncached + local_state + +@[local_state_frame] theorem whnfWithNatSuccModePrefix {methods : Methods .anon} + (term : KExpr .anon) : + FramesLocalState ((RecM.whnfWithNatSuccModePrefix term).run methods) := by + unfold RecM.whnfWithNatSuccModePrefix + local_state + +@[local_state_frame] theorem whnfWithNatSuccModeMissCharge {methods : Methods .anon} + : + FramesLocalState ((RecM.whnfWithNatSuccModeMissCharge (m := .anon)).run methods) := by + unfold RecM.whnfWithNatSuccModeMissCharge + local_state + +@[local_state_frame] theorem whnfWithNatSuccModeNonLeaf {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (mode : NatSuccMode) : + FramesLocalState ((RecM.whnfWithNatSuccModeNonLeaf term mode).run methods) := by + unfold RecM.whnfWithNatSuccModeNonLeaf + local_state + +@[local_state_frame] theorem whnfWithNatSuccMode {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) (mode : NatSuccMode) : + FramesLocalState ((RecM.whnfWithNatSuccMode term mode).run methods) := by + unfold RecM.whnfWithNatSuccMode + local_state + +@[local_state_frame] theorem whnf {methods : Methods .anon} + (recursive : MethodsLocalState methods) (term : KExpr .anon) : + FramesLocalState ((RecM.whnf term).run methods) := by + unfold RecM.whnf + local_state + +end FramesLocalState +end Ix.Kernel.Consistency diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index f8773818f..dd3190d2a 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -156,12 +156,16 @@ increasing sequence of strongly inaccessible cardinals. and failure. The let trace recovers `LocalContextValues` after validation; the inference cache shell preserves caller contexts whenever its uncached body does. `LocalStateInvariant` derives freshness from the live identifier - bound, and `infer_framesLocalState_of_whnf` preserves it for all constructors and - both policies, including hits, writes and failure states. Recursive - inference, reduction and conversion remain contracts of the mutual execution - proof. Projection inference's parameter/field loops, Prop checks and lookups - derive their state effects from the same recursive inference and reduction - contracts. `TcM.InternOnly.instantiateUnivParams` + bound. `MethodsLocalState.methodsN` now closes all six structural contracts + by induction on the actual production table depth. Its full reduction and + conversion layers cover direct helpers, finite workers, legacy depth + restoration, speculation, binder/let scopes, caches and cleanup. Inference + includes every constructor, projection parameter/field loops and both cache + policies. Public `TcM.infer`, `TcM.isDefEq`, full/structural/no-delta WHNF and + sort/forall exposure use the proved table selected by current fuel. They + preserve the caller's local declarations, monotone fresh-variable bound and + installed loader on success and failure, with no recursive-frame premise. + `TcM.InternOnly.instantiateUnivParams` proves the actual universe walker's exact intern-table-only effect without collision assumptions; the named inference-policy proof shares this result. These structural frames do not establish computed-type or cache semantics. From e596f0b15d2924f7f272ab951b62b67728581b3a Mon Sep 17 00:00:00 2001 From: "John C. Burnham" Date: Mon, 14 Sep 2026 10:40:57 -0400 Subject: [PATCH 30/30] Verify termination-checked recursion survives dependency guards Distinguish source recursion from a cyclic reference in an elaborated safe kernel declaration. Add structural, well-founded and mutual Lean recursion fixtures, export each complete dependency closure without partial output, and require successful checking by both host kernels with matching targets. Check that every requested definition remains present and is actually checked. Register the positive regressions in tc-unit and a focused tc-safe-recursion suite, and clarify the kernel-level scope of the guard in the documentation. Production code and theorem trust boundaries are unchanged. Validation: lake test --wfail -- tc-safe-recursion and the full lake test --wfail -- tc-unit pass. git diff --check passes. --- Tests/Ix/Kernel/SafeRecursion.lean | 98 ++++++++++++++++++++++++++++++ Tests/Main.lean | 4 +- docs/kernel-verification.md | 7 ++- 3 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 Tests/Ix/Kernel/SafeRecursion.lean diff --git a/Tests/Ix/Kernel/SafeRecursion.lean b/Tests/Ix/Kernel/SafeRecursion.lean new file mode 100644 index 000000000..36d66a714 --- /dev/null +++ b/Tests/Ix/Kernel/SafeRecursion.lean @@ -0,0 +1,98 @@ +module + +public import Tests.Ix.Kernel.AnonDiff + +/-! +Termination-checked source recursion must survive export and both host +kernels' safe-definition dependency guards. These positive cases complement +the raw Ixon self-reference and mutual-cycle rejection tests. +-/ + +public section + +namespace Tests.Kernel.SafeRecursion + +open LSpec Ix.Kernel + +namespace Fixtures + +def countStruct : Nat → Nat + | 0 => 0 + | n + 1 => countStruct n + 1 +termination_by structural n => n + +def countWellFounded (n : Nat) : Nat := + if h : n = 0 then 0 else countWellFounded (n - 1) + 1 +termination_by n +decreasing_by omega + +mutual + def even : Nat → Bool + | 0 => true + | n + 1 => odd n + termination_by structural n => n + + def odd : Nat → Bool + | 0 => false + | n + 1 => even n + termination_by structural n => n +end + +end Fixtures + +private def checkCase (env : Lean.Environment) (label : String) + (seeds : List Lean.Name) : IO Nat := do + for seed in seeds do + let some (.defnInfo declaration) := env.find? seed + | throw <| IO.userError s!"missing elaborated definition {seed}" + unless declaration.safety == .safe do + throw <| IO.userError s!"{seed} is not a safe definition" + if declaration.type.getUsedConstantsAsSet.contains seed || + declaration.value.getUsedConstantsAsSet.contains seed then + throw <| IO.userError s!"elaboration retained a direct self-reference in {seed}" + let constants := AnonDiff.closureOf env seeds + let directory ← IO.FS.createTempDir + let path := directory / s!"safe-recursion-{label}.ixe" + try + let status ← Ix.CompileM.rsCompileEnvBytesFFI constants path.toString false + unless status.ungrounded.isEmpty do + throw <| IO.userError s!"compilation omitted {status.ungrounded.size} declarations" + let bytes ← IO.FS.readBinFile path + let source ← IO.ofExcept (Ixon.deEnv bytes) + let leanRows ← IO.ofExcept (checkEnvAnon source { verifyHashes := true }) + let rustRows ← Ix.KernelCheck.rsCheckAnonFFI path.toString true "" + if leanRows.isEmpty || leanRows.size != rustRows.size then + throw <| IO.userError s!"target coverage differs: Lean {leanRows.size}, Rust {rustRows.size}" + -- Require successful checking, not merely agreement between two rejections. + for row in leanRows do + if let some error := row.err? then + throw <| IO.userError s!"Lean rejected {row.addr}: {error}" + for (address, error) in rustRows do + if let some error := error then + throw <| IO.userError s!"Rust rejected {address}: {error.message}" + unless leanRows.any (fun row => toString row.addr == address) do + throw <| IO.userError s!"Rust checked an unmatched address {address}" + -- Each requested definition must actually be present and checked. + for seed in seeds do + let some address := source.getAddr? (Ix.Name.fromLeanName seed) + | throw <| IO.userError s!"export omitted {seed}" + unless leanRows.any (fun row => row.addr == address) && + rustRows.any (fun row => row.1 == toString address) do + throw <| IO.userError s!"no checking result for {seed}" + return leanRows.size + finally + IO.FS.removeDirAll directory + +def suite : List TestSeq := + [([("structural", [``Fixtures.countStruct]), + ("well-founded", [``Fixtures.countWellFounded]), + ("mutual", [``Fixtures.even, ``Fixtures.odd])].foldl (init := .done) + fun tests (label, seeds) => tests ++ + .individualIO s!"safe recursion survives both kernels: {label}" none (do + let env ← get_env! + let checked ← checkCase env label seeds + return (true, checked, 0, none)) .done)] + +end Tests.Kernel.SafeRecursion + +end diff --git a/Tests/Main.lean b/Tests/Main.lean index d73af7625..76aa770e8 100644 --- a/Tests/Main.lean +++ b/Tests/Main.lean @@ -48,6 +48,7 @@ import Tests.Ix.Kernel.TutorialTc import Tests.Ix.Kernel.CheckerRoundtrip import Tests.Ix.Kernel.IngressMetaTests import Tests.Ix.Kernel.IngressState +import Tests.Ix.Kernel.SafeRecursion import Tests.Ix.Kernel.Pins import Tests.Ix.Kernel.AccelDiff import Tests.Ix.CanonM @@ -108,12 +109,13 @@ def primarySuites : Std.HashMap String (List LSpec.TestSeq) := .ofList [ ("primitive-address-parity", Tests.Ix.Kernel.BuildPrimitives.paritySuite ++ Tests.Ix.Kernel.BuildPrimOrigs.paritySuite), ("decompile-unit", Tests.Decompile.unitSuite), + ("tc-safe-recursion", Tests.Kernel.SafeRecursion.suite), ("tc-unit", Tests.Kernel.Unit.suite ++ Tests.Kernel.Substrate.suite ++ Tests.Kernel.Fixtures.suite ++ Tests.Kernel.WhnfTests.suite ++ Tests.Kernel.InferDefEq.suite ++ Tests.Kernel.CheckTests.suite ++ Tests.Kernel.Consistency.suite ++ Tests.Kernel.Roundtrip.unitTests ++ Tests.Kernel.IngressMeta.unitTests - ++ Tests.Kernel.IngressState.suite), + ++ Tests.Kernel.IngressState.suite ++ Tests.Kernel.SafeRecursion.suite), ] /-- Ignored test suites - expensive, run only when explicitly requested. These require significant RAM -/ diff --git a/docs/kernel-verification.md b/docs/kernel-verification.md index dd3190d2a..f93a74352 100644 --- a/docs/kernel-verification.md +++ b/docs/kernel-verification.md @@ -192,7 +192,12 @@ increasing sequence of strongly inaccessible cardinals. preserves validity. The remaining successful-body preservation obligation is explicit. These structural laws have a parameterized cache meaning; the general mutual semantic proof must instantiate it and discharge that obligation. -- Safe definitions cannot cite themselves in their types or values. Definition +- Stored safe definitions cannot cite their own global addresses in their + types or values. This is a kernel-level dependency check: Lean's elaborator + translates termination-checked source recursion into recursor applications + (including well-founded recursion through `WellFounded.fix`), which remain + supported. Recursive calls supplied as local arguments do not create a + self-reference to the definition's address. Definition blocks compute a dependency order for their safe members before checking any member. `DefinitionOrder.block_wellFounded` and `block_no_cycle` derive the absence of every internal safe-definition cycle from actual block success.

pC2Jw)DOa%0s8f#w8N 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

v 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%0D{5&j(jw4)F%zpdbnJnXlUtFRH0!^-}AH? zG5CjH$(3PCQG_A8!Gpfsb7g1;WhpHB{nX^sk-lX{aWZtim;}ih-_SZE&tGNPdK+<` zGyMoOT__R2rVCyzwtqfT&jh_K>ISk31K z!hAS+Il4`3xS+A|nm#O`df7k`%q+uZuT(C0k>wS}mCvix!*OWzeqd%DY7sFQQ>Y9- zgltdP_b}`N`P@MeU^uyhB6lA-!c^QrHgj!B;wzo6Drn}-M(@y&2YL`Y#5S&A$XAgh zeWdg+-0A4qqKZL5JT(!mj5VWJO!fSO+1D&|D@ei%*#?q-Wd zkeI8W?E6^!dj> zZ8~{DHf^$jdRf+>E2x=z_|Xop_F8=ottPZMXiIv0CHeukJm}kesUUKuT9Xp^cpmj@` zi?CluVr&&D9%;#_#1n&r0qQdOXUGWItIeT0!cvmdQt!x7#N$`FyTmbnxV|?RQBwZt z&^E0GE%f!eC3iIPI)Xc583Qh7h|596YtJnw0IFkA`h zsTpo$#$=jiU&x;RCK3Ng?+)!C=WF{?9T)bidF=-``={#?iBr=)vYXAa#w&M4Fx=V3 zx@lo2ouT&nsgIk?eCXH4I1!XpmLEpq$_VSG8>X6Ja7vJ8%I_QTQsBsk{tWgHAAquHn^Qq{@VnovLxFE$j(Sj;5eh-2?aVP-ZM%9%L{o>NjE4NNcY$OV z-}6oad@n}tf$JNpW8lEv@*jXU_Ey)cNpXM9^p%%2IBLq2j4bzEw`6zww7zV-DZN6! z#>{YbY*7A}(f4G7+A4%XB}a{YJeP#3l1M0dy0#nkX3)dmEsRUbWS{5|!!Ga=W5?r5 zXzka^#o{p&O`9@&L!BIIHs1B|*18_`dwMGR)RFIPGKL0Af-5B-9V!N2#9TWyBq>S5suz&fMj{DtK^2+*cI}A(0;Av^Z&XKPt&wJdIJmIUYZnE!OA@%MMzrRqw zQ>!;~s(kt3gZ!zE(`#; zzXB!Rql9C0keYrEFw(n(pwZ$R7NY)^K_nW=8yBT1nltz{qI1@>hiI(%*35G|aM=}` zc#SNj?(>DE$fDZ1RImU2o`A}az?d`ih=zaX7T5e81Qq!*Rvj&qbMMo2%uu| zmG9uSMCtP+bKP5ZyT+L&jzi81ngsh-;FKfBu_z)_VuKuAW0V6{U@|Dlm{J(*-P~m{ zyK^JmdyxE&$@S)N16P!NVNFP;4GBI~2DynIt)X6^&;xSW*OF0zm0 z@GmZilbh>-YRjjhGH*)#1eOMhn!OYSmy6ohqxeLfCIaR*w5d!Y6ZQUkpx((qK)zVl z-7DxARI(E7V};weH1FsFzv!^#tvuV%I&8~h7X8!A5D}%Ll$bwprbr&tF62HF<=^l! zawjJlB1w21S$M&K|A!``8q;0{F7E(mXJZ`8XUlh~$kMLt-~OjQ_c z+R**yL1|Vj=vt}IYpZDV<8YZHu3KOnnY=EFXF*Wbi>RbS3jrZBJRZbu_;+N3=(qPP zYwyu~Fmf)b=fUz_Z_v>m8Rh#i=wDd|(+bMXLsHW_a3qDj<@f#%+kt?-qoF%7>N`Tj zUJJlQvM>2f#4SW+2@kPlHc|j9lBq`u-4abhN!b1uC~)u}!oxM@K19a^ zrV!m(aM+X*-los{m27`2P%KGbWim;$5id1dY9eBKFr+Yj4VCt1y{iNOSCj16;E~lr z+}a{rWU5tE1mJZ70!tr;Kj`KIROvWMFnOy>krguV(*2K0T|-oH&UEks%6|xW(BUDW z+J$HdxiKfI7DqtKBVvx z_&eOFEop^<;@?Rs#g4>W%--yRodg41~;(B9~HluMw@;4V-Ecv z6Q7Rg|Ii-{HxvKU^$cVxezyx6P0R;xH14k4i50u!p__<+nH@#(=6?aN=t;VL-Vq%k z(8A>exL$AE0r*fZMZnw#fjNW&=ujx2c7n%{j2vgdcmcxI{E%)Fy4#;dr zIubcAe)av&&mrTlfS_Jd_?3J>?Po_y_@u$@3YjEJAInA>D=#kpwm6;)9sPiF2Phes zX#xVgoM|~-H0g?bfX9F5ymwlHdbtg=9ltohx%l^k=Pan_WAaBV_&@77xNb5|sD8Si zXGSdX$@_7&PC|jRIC9dc+X|m?Hsr{>jE6iaZC6+RH0Y)(%BJ0_zfw%USnjJ@$c<21 zxDUR<@-m!5FpUjuW4ZH)l};a8L{!GmW?3a+Mx+!XY=nh_7pv0BQ%Yc{<3n)rQuZt; zhmv?3`1AU8$EsIsR;=^xb#eY~g)VlEK!StCqD9DBfU&8DJMA>Pkp@=r3l%%;g^-Qi zMOP4SyiVQQynz1+gkh7Hq_YJU=vA2{=w#XAOQdd^qm<25+QR{jDdOGbTSXG3ULL8Q z62D2)s*mKFju_bGguNl52sxy$H}!o#_P~ox!#$C7OXGRk%cYK#tqpaKU_^sXmaie8 z!;&^{lNfRxQ~1-kmEHYIy~ zeBFr;@tZA((ygpCLz`Du}Zut-^&nVp=}&*5cvujQCO`g{imRmPXbbLC|LA zz7Hx$f;0d^v;P#0$Jg3f^HqW04#Pb>2bM2Y1ngSb9}`TF4+Cc+#BNk4^cE>3?X0MJ zMSM@wbA8{(%Yb0qbi!p*pLZ>w5f%UNPiO+Tz6H9pbSmLT6La(;eil@sufZ|tMZX7I z2!PFt6?cfUVyQpYbxx8nEi|PvMn^6VT5cK3PGDM-Y7yQObo4iYF{Hqr1he|%{{t6l zJxGc_ThqUZ^N35;_k1}oi63|U!coD37pmFHl5J792HB%1;W8mOC<#9JkMaY&fFR&q zE;x;-HCZ$Q=(hSEFmYR{&q@2LBH)6)+;8u_W(B%9b1G#&f)8M{) zVOz>A1*V>b`ed9H^ja*ocy{Y*V=o6H^va{a{=pi@zS})SKc2R7#h!m!lensvzMcAx z_OQ5+5(i1CHR>`pW|hZlQ0piF1Jg8D^fXp>VBCk?GxNcp^h|F5KIDR@SCi$93;f1Yr}@hFu;Px8Ng-I=~j5CP-z^PP^=0s+v| zp}64Kt_^o-*??rf5u|J*&QYBZ+HL6*8Bc$I}p;8ZTh{7C=7dfG0j;U z{B(`1#NQyC%uLbIsoV^3C(-y5UY1HUT`DzeH)q3;L)IWrjRdJ7xSap5Z)#M!iAmVL@eg!}~49PJq0c zi9EbK)=#zUw&(~Vat@D?0fNiV8OdK^&3;H~e#tq8?KmQMod2z+o{pIhkYHI(euxz} zR}CWzgN=kjTHR%34q4(a3Lsz-3br$}{SyWFeDel~n?}Ebz_9@$Tyk)^$!~=4&z;OT zOu&B6Qq}?oVrttXg*B|Q{;3aQ~o0@@OwwE`b_u)LCX+l1L zg#|iK;}Tu0Elv^_Rl89?027^Eim|1sVC>06f`KiI$}+fXF|C3{45GnJkd|(?999u; z>XNuIk%YUtTA`}(F)UHmTVF;owJnl({dcZ1g49m?@ZW}K{)blp3`8COqxWBaD`VTG zN^l;*;fE$B6r1DNWC^ij69!af1U$)VlKzHL%PQf%@@>#1h1DnlUR``vcQ)U#~yP#r7RQhyYTv zPk*D?0I`^I zxYjmbsID(1B7f?IAHB*QSy$7lQG+!pRZJnm@xLI!=lxucY)sHQL!f9tQ6i6>h5d39wOdHZ3k=bcX7R}<*dxg)c|f{VmOTlQ05GCv3=lu z@Ec{Y%vA2S7VGdqyRvc*m@l{?|-g-hCUu=Z-;4cH47~YfZ9a!>^F2^+c6_=bw6y>cD?EuOX zW1k9!<~I zRpneMc;VOb!l+OqNqViIGZOoq-__Ku>b~*6M9#E~)*&-lroqS)$b0qOuWP<3-Oh=Q z@bDytty>IBKX;Tg*1W|t;r296r&oZCMqn-Cc$q#i};-GRT z&Cwr~E~B%fheb9#Q@ZQ6&?;0j1CZl5t_66%SKN7cf=wBS>}2J(va~VvHTAnT)=##z zBdG>336RUCk``h;Xa~h-XHm10$oFxs3(h;IGF7$zBMsibQ)QMOz9tEStuD7Bn{2E^q5y~ z!}ijw^#xjGh20MistZAB%?b!BA75IQ>1>ptD2MPP_pzH_O)EpR?lxF#BDEA5TW;VLCV_J z&w|BAQq#40?6%J*)yz&oKZw&;PDvEG5xFJORyGR_0!A8=^aG>6AA;fV!>+yc-)-aD z`dXi^b#`Lk6e7Jr(MOL!3J5?Gz@z)hs*L zTWDoMC*QNL$YqdGXvJq8b?1kUd9RLXtk!q;oJFq>LV2g59sBCSUoya`+DZ0-IftLt z9nwsc&a~XW6cK7>SqA$SLZb@*$+$x*B@**_j8wN}>O zCp~z^g<8>Ym0<3C|3GVt!vS;gxYeI7i4VwS!)=_H95VpWtg;yZc$O$A6DyD@eqTTa zKva0{Zp=sUlb)Sai|UqMb)&JLjsRcerB4E-xsCbKCSOm+Dg1B$4ioBT|AhZewP;$R zak1v4PPVL%m-4`RSMXgKyG^ZAiwVj4{(h@0)3#UB%&?!ITTDfdQ05MU7h=Y~e~6ct zireWL^E20k3sLT{jg~H6ee^`zqML>T@t}~I=-Lpft%f}077=dhgTkr6JPo}t{41H} zzi@B>Yg7#qWKT^>ml6t%{u&S z+^J5i7o(u%EvkbrYra$zi(|`$gDzPQc~#^GN|cUuc5|G@Bv*(jBo6;jzqhqpqU3IS zftnkic2|Jgm?T(3-$`?$#vGfJb;{0?%5Mv{%NIjEk>T-_p^hIf5fTYW{L<_lYtT^H znVpRlVH9h9I0t~pvxw&xN_X4`78F0v6XekS87XxJr2Df&eU)$CY~UOok*^tmaMqZ- z=>A&MQxZphJ9RjqW z>YHEN(8{;fYsS<(FqJl{i!o2^Q)e8Kay2%HF2)o3$!qIc&{Kcc0S!`SC1V#6L##o% zeIZD@+8JPN=oQ|>hb<4*8E^^^6~ zu2+XCmR{MZTR;ek2CF&TQQPq*)1=Ew&*X=;XbtbCs+03p60!TjtE-gUw63MMVR%jO$X2ZI+3`=Liaq=Y4JJ(KyzJ^Df>EPZeLcsY@6G zyafoLB_OIrJqAEO-#PAzSQB-ov|DXgcKB$%ILF#qU`O=*G(Yy`_!;+3A(1*o68V1sAEnQ<)$f6*w}Nj(L=$Ga>fN73J@R_%uc|f}A!4g}RD9f*AN|ZvP&6JzB^nvF zwb+_p>v3LWG75;ufw}CJ!@K+G_(XPu_XOrkjcy8M7V<{94Z|TlcQzBA!(t_3S!03w zF;X{C`tP5#B&tD983hxkRCP;tNKU+RT+%BJ7P=>4OjI9$o_dG!YVX1uKhGH9arkd~ zL|n&i*(SmEDv1!SHjn*cQ)~_58+)&&QuEFdC24j>3*%ZF2;$EygLucisnWS&d}DRA zAMVTU@Mw{_GzQHJ?fh}d09z4iXJCR~=ParE-J-6Y*HdzmQrM1(7K@P<`+lzPJEB4$pmVx`{u9 z1$~x-j+r44Ii0hg@uAj4cV?1vLp=1mXS$C`(Jj)dCj{sFk(0NEEiApp)*!Ayx|Teq zksJ-U<^I{69Q&%c>Z*Kp6RbzapJtk=?jI-}#x^(3iO>H2m*N|}r?@l5n`K5Q57>jU z5N($CGf0Unt?)@Pnwvk9ro5CI2(8v>EjBA+aZQ4wnPvYi`2bVV&7UnO!LiHDSg59& zf{8uPosSbb5&P^Pj-x1C2`)XLgH835sw;JXz{N75)2ksLdRCK7%P8qOB&~#h*WpMgp`9E$B7IQ31Yvm;^K33|fIi3^H~;HT!ejukDvMJLyHPi9{xJL$e#F4rec*FZ&ZuMwpF z_Imq=oXhEn4SsrbXu37VT44F?f3yM+TyWj@Qgvhlk%?l=gZi;BX&TkOSt$u4oP4aX zu+hO$4JUy^sd+_P%7H}ue^myTQB^?BAwVC&y!lnh#Wf6zd$Ko_U;yUV%xx$VwcdYM z@?5w;n|~_#8Ou&J3p?@)*O}nxr%DaVU!MG}End#wmouFEp_Wctc-74UG%mV0sxMNd zN(txo?}H)zBYp!F%(wJ^3d@szVE$1jo4wPe^><0dtp>+zgXXj;r)s5TTr?y)>K=`y zmhlmGN3|Nj7)!6*zw5$=JIK>kBZvGfjCWk*MQ7mCC*ZG%c>iWChVQX6UsUama@z|t zCw-7FQ`1SDn_dmbm~w&UxJT)hHU-86$Gp4l>=h+>B?Ek4yZf2&et3j%4%9t0-KH)F zK(nHpK=4Qfxk0Qyy$Fw=pcH)t%@jTkHe`s*l+?0gcLn?SIdAF1bqUTxwnLpip#G9r z<2`kSjP1-3^6L4g<9mh9vC*l*MM%t# zhlXJ2->U-&xND|=RtJ~OucD_Q7V{qy{uI(+_eB=;JaQr4$bycgd1QNm6@_v8%bcYQ zCz>hdSt0_?NlM6Sr=Tzd>z!?quO8UwaiZNd0TaW+@sfR>;-&ww#IJxb_1SLyps#XS z;w~RW%>SwO9SD8{7xsGK+9^_G*reP+!{V)R*8aRhJ`CgXo=Af7eC;6V4&$|qI(W42 z*&#={isab}iUqc!RJd02;jC$H2El#1MD~F&6WP9_-itn<$<)SM6hnUGFeexRN5U~a zr=ZHi`7V-IH~sGnrbg!#X)!1C`53ClSD{A^h5}sE{;y9aQ=fdCX?PZHZw*k? z;ULDeG6CKYrZ^VeS$vDGh*dddWKjDCkk@@f>!9;hYqvpUaa3Sp%0BD2!EI^u^jf25 z*$HC=x=GcIb)EzIYS}_N(nwC?eF%;oJpB(8MLqm9CH(ITU&;UUD+^afr+=~XPLU*gVq0h>b3h~bK4W52i7Z#3DfcfL$3r5Gnzixg_8C) z7084bb-T&pkMu6RAzMCtWfR{soerWcqWmsZO!VDOke4VQVu8!m+w#GYCp3cyQ})b7 zjVpeNGE3jy4F7inQ>D4KdOZ;4(VdVg*a9O8zN>vK8|CzCQ<3Jlp;$p3!~$0c+jBDh zo9}>cU@76|FXNWMJGB}m{z*lz?VPV}Y!0H7S}rnsHtpRvR_0;Lbif2&r{)*7xe>YV z1lK$zx~m~oyMKpEu(e#?5EhK#@iwReW?QQ8YcGtD>Z*vc!z`Tz3eKtUgCyNE2Uz!A-TiZLZAbM6u9e<5`T$KAnzgXa3iLxB6IPC8zeXSPT@g;kta53M1 z3bKI7MX7T>O)LyKV}7Bn-2HnQNOX*Gu*lrz;_5w0b?UOgE+gspy)rklhv+lJ$)1L& zgp(x=tE~Dja`~2wG*H@ayLvKv!{d_-MpkqR<=Kw&9tBq|^1llw|B-HH=)@0j*(&MO%Xrd%{@=l$5Pf`Sog10^Bg zls!+XLHR^9J#(uQ4m!7sI25r}Vxu|&A}0f?rtJp@bOhc~FQg*&-7my2Rl>!8-E@c~ zAF-F2kc40*5ho&>F?kykP&4%0&8<6=R{UPNS7_I{cUa4*6P}}Pk4HRgio!w3%9fZMeGu;K5yJr(_Eq#7LU)5J(M2|+2 zoGLRoao0Z1jnR^^k`ALx8bp-SLC^nmogJmp=)u@Q;nwakdw&FL+l6hm5i{2YU)1cY z9u`SIc5%3-o52&KgP^%twp9Zib0QZp=wvm{a;c&5F=ZR%uFTAClaXhe}Ya1?fa*!A;D>UKKQ~_h; z_&rG`$;RReSYN=UH~&=2Ew)pqNKd+-sdN1;NGw^};yH`A?c6uRBoWtD_3Y~MSUaOY zj|Ql3NDHYq9Z;x63XWJ@_z?xmKRLcj^_mME|j1T}gv!$;M3vw8>jsi(tDyMQ8? z5=~J07;ROfraFTSe9_F8?KL7+v$sG2XQky^o#@hR(;TFCz35lGV8$&RpPbK-J#2O( zz(y_g*RU{2P>-{;T|n+bWdW3i_BGxxg zqPc~WHH#g2c5 zIu)5?4XQy~ z2j^m{d|C)8)wsBBM*&gFURw6FdoyZ1_X#Lqh#DFtv*04b^ufC12?Q#J>J0tj@aSF6 zN?P#J!+*N`||85;bk z?pwOHjnh`f>~*}T_&AmShpzoc>f`ARNlK{mAF#Hn5BcrHg>44RQP6P(vD}tZX&+x4 zR0>G6Q02l(o3K8WTC3}J;T~f5+YMqA!rJ=%>q-`8Y6ZQ8?`JWcnt1{SZNic@1P*N> z2NuV9)-2^UkJczx6OaQO>mDXq6cRzr7=@RE3Rx3}7CEw^ASLW8x;PZSUU>$MDBidx0;MJ=5u896kd7CW>;W($}qNlt&t7UXFE zotnY!=62{}FN z%rVJB`*cArO`Pu>N-(I65W4LQN)X|Zo30pW5+Ylg6maND4Brw37l~sX_Tw7gjngb@ zH=HMgBDxx#Gq=n6AP}md8G}mY`ZVb--P{>V%0TIfA**yuT$8#;L0%(*n~m6&B^=Gf zBbqrB{tR2E%^YzKy5$#AgE8V9M?=LG6zxdE&wbImF%^{io>-)dhQIilStZ=|S-UoJ zS&b4#z;*LT5*oDYK(mU}klk?~0|^R>NMzcF2#eWw-c>qK=3X4GLo!ZN7|S_qt8JZL zi{4?^W2!Oj#?-4fEA)i{v>+SQAy#bfNA4@f$>tAHWc6VrrrDP^F|xV#n$Oyd7~hN! zkY@{uL|CT%vH?B&f;C_yuKNBTw0(K?8dWRw`?P){)DlfN$;cJ>4p0hs-m#ldV2Y`p zKlUQKLyxTBbAz|F)@OI47vf+0fjUGWOqp+TSN2Uc0LUs>UKf+~kBDMF7 z7`q=r6s+bi7W@S3OM_IyEME;=0qRO}X2WcknnfEMzvL=_!#{ypl>MMJX^i)k;T}uIdMN&3wa~u%Pkkqm(j^jB(8U2EQ~&ChCIh!l z8-hDsBOCYv^=@wo+}DoDcb)I+X4;x{)&g~_I4X4gxDk9PXn^wQK}p+c>Yb&SfdBe0 zo6Qcbz>d|_h+(KmHd?lE*5_w90=A$JfnmskHp;D4GP^grLG8WwOHs4dmzW)+%?6nA zdU~n!;jDhhi#UPQOQRaxm37Il&7n|`M>jevVi zNz(R6zor|)cm^&5EN<>SrLSv9%nf}iONZuulZA2j5xsl?kok+%HAk8(d&tV(k`IdK zniF%iw6^Fd;w;G;_74-a=tVp*M6B|K7^k?@cwY>5$wDsS{4{k2wW8VvcpW=K*9{IB z_Iw;cB^-Vxwyzd!YI^o)4`Spg_Q^5)j%CaH4W22Tkgdty1Q#R$6H7UN(z%CQ?_g;N zsTY{t7_M)|JCS3Uo_{A@b4d@ea2;(1PB?#yrD46YrI>`zTS+jH+1z-2k%q|yI=mqD zbOWB8-<}l!2LMJeYOl}^Z?e1M_XGgy>#<{?TnNODwsW+`oG3ikETS z@W+uMn6%xGVNZgIcgMcKVB~T zL!Vd_{aRD(CJg?S{sx9?s0eG*fGsQY*tRFGWY98qCjL6?gRrn=zB8NgYEjk~D3 z49!N-$0U1oTUb}QCB9&KN+`Y$s9I_vPPO`GH)}_?6}@ft!1wiV`S#!oi`UtpUs?A) z(90hp0O$^=&ERWb*KAMPb0TJMXa?Yw7YyEt6f4LQgRejN!B!)rRm6dE7X@80H10B+ z$*l5DR-yGOx}pxl`r175)|!(Ph_Nfm%@5syNv4lP($&o89L-jAEU=~`bE-ln~*ENaC!T{*Ru^GI?Ra7Z{w8q~&qt_FU-zPWS${HG+) z_vjKd|QxMc8Z?%g5U;JuT zmiN0+&?Tm>nH)}q%O`40l^&hAOq32v-Omz_F>wS8zo$G}N#qBU)B}Xh*p)ba&mPjR z98AR95|_l}+F~m^2U?>KDR+H+2Ue+aC$X;ftEeCOVbDox${P*RzMEajVxfxk7g^5I zt}!F_NRLGx2_vjTJWM+{lCFcj@MmBxyIjq>NPxJUe|8@?4#D><^Z1JVpPZDG)Nq(3 zk|p1{!3)d&<*;9!t-fdUI^W1}o3Zc1gRIZr*R78V#M`NHd!(Lzp>W!#{ZuFmV{9n? zR2M%v>cP+o3vh&`c+pbr7 zsWS;q|2mv)6M?%uQ7MY&re&R58VPIFh)7ffr0Qt8?f21Za@GWK*Xzq5en$YzAWw@^ zhYOrj>fAN@I^fDxiN-(t5f&W@xeWB`ZI`<1G_2d=8#K^5{gcLa;JUqk*m_rycSVbh zmw-$@?kOOvE95aCkbQ~nlLQM=Ni?Tcz16^)(Y7ew?Nd$dn0z(AL>R)=K4-yIMhVhkGI>jZar^bhEzehx0iTSC9= zQ@&~s-LQ{C?N(pzu28DDM)%UD34unGIaKJV-RewD;k zsNDD|{pbF&7?AZu*e=C%3myQ&Yscpe%7Jna486>@0F+bDA$oOJS38(mInVo|)~dUk zeAv@Wb#ku*WG5At!Y5WI5SgZMqvHR)(6N#{{kL9c&3x@D=vXZP3<@vjd-g8S-SF=~ z=?=6!l<}#u^Txa)U-$H=&)m;!ecm)4m%si#{>pO;hS|k{>p;G~sB$6Q&Pm;;|E6}J zsu;=X=*szZMaKqkwkkM98QpXkNL+8!!b3Nev>v>*_V@edHWrOZm(Cg1_C*GNfg7i? z_%=1pU#e_}{u3#<)>YP!9VVXg^ds9~Untcv`XoJ`syF+$mk)hg$BpKGn@-;h=MQvh zHWBVSme^N*dFHr11w2@9BO8be!bX{dTOiX{&qXb#CY>>S6j`=)g}b5tlo;7g%G2hM z-v$4b*&vs1!AU%(z^($7H51A?^1B9?W-qtB8Ww;<)|58L!l11Z9ne?Y+`igDkl#GL zS93(^+E2>2^aeNeYplsBbZa(vGg^4`)9kh==34dPCD!T&-!}Q+-yFF4YV@%$E?R%% zd^D0ai%{ZxSCFST*_=ik(1U4gcRdYFoImDTe>>*6w0h(-xJeQot9-6Pv#q7UP$uao zl(4GP4uA_%*)&GWV7{@fsYyg2NF}1~qe%G52Xnrh;SIZ?bFG&J>G@Z1L z8&?aLXs+@F$#FpoeOnAo&y4vxNR*CW${P7HP;dCeOQk*+^*FA`cyL-Gef6+5?m+xsnwe26-e*pp5Ltx#o?wFI_fVJ5FJK z_+?&>=YH5b3G)X(#y`=4LsSiq>8{ecjXQ*Ga2_J>mB*Yp`};Nh@$+}yqGwy9IIo^ zu`&(n$hlr`aDB82GK5bxRB17sw=B_F&w<+MDSG7XRzY^#GU|dB`P#l(2M4X~zwaR7 zR=mc%gMXA>IzazPKGe$mVGV(LlRlW1Qe0>KI5WN-j2hH6oP@sNC`3mWG2ZPu9{X{(Vw%Jno(&atbv~7v5?}nHE4BKDT5e z7!7#5osZ7f@JoRF>lZ(JEw!=w5;*<26nB<9Xy`VN*ShpId*fJZvcmxj{ zsj%8!gZ^&=UQK?$c%KGsr7@oB_A5kzzWerH74Z6#F4^nR3xMxk1V%z`TOIV#X^eIP zf0JHJC1Ygsai6`OBsMWHf+Kw_{DKTK^jJtg1&SA(Ld1`uMJEf4I&rrD9u?idNXR2GyHz%p@--1Zx-M9bzccX%G*YHH8G7Y1dq7*g1DJWPZwGwB*y2vN6*61^I z-4-t&!8ao&1=G~q(4TKkiIkt$1A_<|pQ0J<#X?^SejV_Z9>U8BS|f60C<|y4>uz=w zvk>{v?Sw`cv`pF|RfnDpOz%%UIQwaW2|H|V_8^|bRl>r1sKc>A*@K848n%sGO_}l>lE$r@SwSTdfrUP z{^=KoXr7=m6v8tRu@|4woWNmHV8G9@N1|US{PBC7OYB+u#pgQ#3gRLhYm*@Oa$2S4 zJe`)xL`s_n9_O-{qh%7@g6;K`?q$6nuyC{<{9Ss|Yjf2&ViGJ!2 z*e6qTV%*^Ns#TMmRIB-Ql#AZmR%$)3XTc_ z6>Mh%9>o)SMkHU2v`Hjk?a#;gTYLWeq0aB?9rmiF_Rm4Y<_RNHmm13?k*q`RWchl; zV%b`OzK3wY#67tVnVPbsl5;A#J(A*Cv-@4E^f@R4e6~GmqpWfMDj~&qjkI5jDXQYn z%!ShZ)d!2A@pn#bt*qtyL#8SY0);fa(Ph7>qG^UFKoZsJMuI1d@*i{{q8B+?UZa*H zobeq?M=GF*Gb3t<;EkMu%uvz2N4s}3dS_tWB2XRh)NPkjB4uFXy$~s9Xlj`x=Y&H z8DTEruqfvZN2D6YBH(QmN}dL<-wS%<)I8x==fnMts`Gjqz#HO9g>0AzN$xUR7jJ(a z^;u)O>`cj+c}^OJv)O%QFuIlKv3R7WVP{45Ul1UOFd9DD5Sy((d~eX53x-%ZSLdL!C`QR;O-E}H~GEqIrpCTJ9Vq> zUsKgJ-7~fK+H0-e-Osa!xZ~@nPK2s28Cm-Z;w$E7*=L&MwsGoW?F6!nw5>4R!(XSTAGlX1gRXqcI3GE?^JV%Sr9(9@WX~U39vFuNDJcK3`~%(m1;p6`?!Xi;Oe0CXu2AnXQFl0sa|QLNI^f1>abi(cR9PMxkU3ZZ{x#v z`YI?mz)lCvfKb+?)>l9kTHn+jF{@*O^z(xl?W6S-uhNb<0#_$WaCoJFymKyJ}Sp!IZUS7>FMFKCZLW& z(9AeP{qEW5M;kPvhy}bjrn|zhd#+qS#t^b_jixcGNU)NNNtiNUJ&*SIk8$EZ6fa{d zW}qnv^<+*@LlSR8IqZp=mJg5KKg{JBJVqY}6Ptv+DwlYP3;Q&+Z*dEG(YKfN~tB3Fo!n)UI7?^&znBVCc*eL8OQXkln?ZV5>h(D4Uy&Grwv@8nXEmNJI&X&w(}6p_HI(Dm%$wnou0D*DUZ~Hd5=<=%H2SJU*9aEcS^JiI137X!$1Vt zcdpLuvTHVcEn6gK+V;z|o3TBk9F`>J`5?M(;Vzi|MPtN5lnhmFbzz!*&pwY*F8_Qa zG5}0$71wMza2Ag*LJN~EUoD#-sozUtd~2dLnag+0T50fw>AMe|fU04dTAK8qYX}Pb zw=f`>OvJenbw_-+$q|e_xdzn93R=3m;$a?_{79igdPphv6*n<0UZ31YkEQqi`x*(xyae)IMrbo`xBECKfGpl@c&Z z@a^)=+#Xr`nY>&)1rSN-A@+-EPNtp=j7!`eISb4@g`x@Q0?YFG^}db^id;steiy=s zsD2m0KvwVfBEdJMSnK-1N>cMuX)lS22x{KbYt z)h&EBnFGLCw0hy{xC}xNC1YtoFfZ#|CctrIf9A_3gl&voHV;^_1aiO;M5m#h`Wp#o7sS9d$H9PfGM#( z=3;RfF@XcYo8<#6lak$B+v6jU&%W=DOJxB>HWGqT&Z-L6;rc5QdRT(9Ji&m}6U^t*`5fAeV!NYHRCB_Bab+ z)gDeXVODRLYCz`zl%kD6#57?c(2d+Ux{7^gFs_V!Cj^MwML>TvZBN&pHn;B%KZfKq z(r9hv<$(G_x5Hzzhp8|(JU+XHJcL=Fdb0iGCW)}$XaQ6?|98%Px6OnVimCfqr(}0e zYs?ha3ap-QT0BlpO59(zWYM4ZQ?T$0E}oot>wp8QAZ&*~lMm(tP5chO2RsX!O{^|E z$}dZrYZ*7m@sUjrBl9r3d$nRvGZIvhIo0;V& zY_?Q0PX@KbpHq))hV!}Ao@OfUd z5E`Y_ zjJW|^dZy<(M~H%9#cxNujfYMN=hv#VzGq>_o_m0OyE4>&wLE5Y*FU z9cAg*d0RFmj4t>FOc-Z6o-!DknKsAkKq2woz*z!2oC}F{hdTSC5WHZ*doe3d0CysS zlKSM(m8GM+JA;76Ht+7y>(#Cl`4Dt3uLTJ7k!Z_1fru{nbkBIFeCCe_`jzYrj&+K? zu4VdI#U*4Cz}{t`kjq`?uB6>h=R);mLQr!5s{UfMoNpKkBey%YC=U^p3us2Q~ZW?q(2C#lSxdge;$q^gFY4jPgde`b}N( zyKqW2x#19h*=fUJH_<>3w@+VQ+A92)?(f33h#LLTvLDyXoHE#R?_Pn zqO&?sCSez6AQt#obk@k)H*sSf&IjsCDS#YKIrEh(LjjGY0W;YwOCdL(iRowd@_K%G z@nUuVp%5Q0o5JB7uA#YizyDPDu#r*vKA*ndXT=_u3=@MQiYQ96%aZvNOCpLdRcwY) zC#>whOzGvG9bp)G{>}Nx(RyJ9cE~SveNjQTBT3?4v`}6kVGOJC=&=tR+jA^;I0*$^ z=M2&YF8%3$`wC$hG5^E)>c)^iwY_wE*{!c$3p+nWR1Y($J(2;D=Qfos=NdfZ(5Zb8M3cWvVGgS4Slkc* z2q_`5H)SC6gY~30EC+2m)KS7x5&^ZdnB&Pb&lC=c$#)J3se(3$TaZI|*o8Pg=ele4 z2S<;Q9cqc-0}3Y^%1dupKDrDOy#I8RNpT7^@-IT!blTO*wi4h|xBr%M6rPOYp+4T^D3uzGW@x|?snM#1O z%m5f|*Obo7{mnB>pKv!BM&plAYP#O*@g7BE!8675ae*C6#98}D(jjWOQoQ@JNwQdTsrJnkd7C< z6=p<=?oeoY-z=uzrM3r6-A5GK0`kS$9y)vD7^bX;%YTjzS1M5wIOpE1{eL>Y{;zMD zhH_3i6UM2sDJ8-(sCHbngTF# z00ay1hJBH_YL>5AnnWqRyBb5D?l6%OKCZl1a9nn?-G0ZIjPZsZSlg%^laSgoX&>T z6@l-wt9*N}`qDouZt1V$w+q|E3-~DSV!dPc*RQTK$J~oiiv^$P;Pq^XP3@_*+EeWE z!VkNq5zD0eRYP}H+$Bod7r~Z@uac{{e?Cf{p|9cHMV; zvIfS5y2DI)Hbz{8>l&My1j|n?I_^QwfrJ6=*x#mO#~X&Q|MrX?u#Af1O0tA`5lp?& zXH+_i5cg>|nxrhgEA#BG`#-z9aP06R)Xikycpj0}n0e6BdiUbK%}@AqztC#U*vT8} zK;1l$j~qVDMVw-|)`t_e^ZI*RQ~KwkHU>a7S{WAYfialIbS6_mivO08YLs!GHAn+D zHlEGu8qh`s?{1@sC-Zx_s6F31l}T;(5uX)R zYTTOPlU3TGi=H$zkUs^84hx;{`9Gk2%Rh1!gaVU845*9;r-P9zWIdWc$WRv|JZ(uY z9a4e&=oQROc})*U)Z?=LjM|ULq%jKnfEEZAr+#Ma3uoj|nAX-(6x-mQ_~U+2pn|4d z6J1S1O=6Zk6xnJz)CI*uI?Y}0VL{vDIW6k?B9?SbqH_?jEC9j}j%DEe0nIHRLB0u2 zJjzqdI_EtPIRp)Xd<)&{cL_G7>@h*LHBw=l-W}%i(ax6NKRra$-B=bZmOWp%##yO3 zg)5=IJ;Wn2P|$ABoL0!$_bNeQ5bk|K^RI8N&r?xk60ERR2o=`SmW%aq(NiSeH(f86 z;OVf4+}S@Wryq?rmcgx2`2GMo7t~zN|L5E;^I|v0U&96)vxwj0N{t<8+PAdV2I%-O zvA{7BY`9gzX&bw;as@A6RfV8XPRV}9F(`fX-=gW&x52`|R-tSQu{2vc7PwQci3Tq0 zY~U%jD#jzG&GaD}B0FkwCf&RAO;!fLrG4bFD_N_mh5o{~*486a@~JP--SoweFI-C1 zx3#8Gx^$;ogS;PTEJgetg7~+sY#KKdA<*9M&&t#)+Ka-X!=DdYjw=`1fKWwww-F1& z25+baLkn)CGPh;Xd;lO79$;*IB=gUPMHdRkn3bS?vd1={f$2Gw_4;Jj<#D{eKldmm z2{TBYi#8O>i(+UgX4zEXW&{bnwf!B7YG&ITt_4Rj6E{BJygHo@*{wq3^N4%?h4ZsY zq-X<^eq48E>RFz-H9=*@J9C=~KIx*wGdQDCeb5OR<614*7lQ=K%K1t!|8i|?ZF@&8OR z=_6VAu9P6^ZYXnn6o@TT&_#s8o$q%0qJr5F@+VIWdbmdiT%zJ7Ow^~wrPO4%hH;Xi z@_3!SLoix8$hN1y-gG8OJ)$um4|&7!IJiDvPyg)|Z{=Bk-+EiEFPwhh2iRt<^5E1t zUS;;o7piB?=&QrAmF1U`TUojS*9sf;G*FA79?(8Uuxb7n`@qq{wlFkbUvkdLR+?5_ zT0vr&FhlRw))Op$_sjt3nKcR^Gn{LYKB~O5p$<|HN#beMC1DCrO|<-Qv)>@Hv&rCi z_QC?h#C9yWNu^pgB9x()`hc_m5~Ky*f3*P7%OU6rozHsuxvRaG%f#koaOFQNz^BBA*e22I7$W%*B?NdlyiS5X3CLN zATCvziozlsQ^2P*n`rVA?+U&yE)a)R@`7YQqKeCz@O>j>J>AM#ZzgWnV1njIn0hI} z7VA$*hIV<##@Im2bwSqmbqT&lmj9V&71OiI!yBtvmPWv-UD#(^Mcjz%6L1<=0(i2%vJML@zEoH;V;Q{fYte?E4KP&mUkmEPzxvR-jqDVBhh zD6~l28^Lf8-a+5jmz4f}kM?aU>WM_$5E61w6q!OK6Fl4{BT-UfPmushQ(NT@;dPm} zrIT#P7WJo@{~zHdav6}!NvZ(q85Mu)5gV(Ze9e82ziG>emCQgJDir^pO(8lIN8qqz*0?d0-g zu(5H?u+Oen%H?nU7)52syufFE-yxGVy}TeA;{UZ14z;F7jSuLhrP${=p37})fr6Tf zuD9M+8_VQ6+5HiU>k-21B8D3Y%j2Nh=`!}{6>H=epI{W+-(sm(s}9LsGcs+0tkZHt z4@Bx`I25ddvHt2^i{<0}rSID{C>mkWB%v_(X!oaNlmH|xOK0KuUq0m1v?c73s6S;( z9cW`5p&&q0O*ZY>*<)MQCA)<*+I;`b@ZlP>snhmoLy(xFEX1s~962*x98L8=9NG?BikU^?)1LgM+$25=RKX>G-;$cYc~hP( zBT|lgLR*Vw*`Ck5n~{os6=&!w4>ot(v>9-Yp&-ofip;<8KVi}Lgtm80UJwNe+NcDG z20@RBNd7)1G9`tu%hn(AZfdDjP!?#;oU30du0g!ZG)Kuj@@#Nla$}hd>tmCa(0#qW zUqS3vF(hyJOCC|ESAu`ZV@g*#=7-gYMp$NGH`G-_o{ue^xi|LD@CoiyqP4)=Z){3Q ztK7wk#}4uG9eI{=!rn)lC6h2+ zEX}~jMjz`oOCA=#R*?!q2^>X|37*N4G;w6)+}dg z`L6A<97DM7gfb(cI<1tr>?U4_2w&3`&^8_gTx(7T8qarCfNk*;dU%uf6bbYomh?z7 zmlg+n))kzA=2vds{7Z%)0#JeUg?l(9`-#M->XkaVr9;O4d*g_T5gHocH)Mtu%45iO zd9oS?7NZ}#WXrcM5un-#isRkyP2uqJqdxx7UORqx`^Xzd(JQaV6#FA??;9Hw%Qkh# z9LLmXvKIk4-#jf-q41z$kkI~1`nRLN%0Wwad@tNG&3CiXr+<-(z$PYS42s3)@}Zkn z5zO09e7fNC?S31EC4Bf_q+bT%bLTNEXqm`$V&%_yHvGl;D7WH>%L!srX7>V~uhjy! zw?nie!n5-v!hY4HLg81fy;O&lY1P$8v>IJ;<%23+c6$)uCsFkuFJ%MsThL~IdPEZb`AF5-{JW<)ZS_&iXT?jKQ?sdr01^M5g@%8ikr35%U47|ssYc?C zAvN2C*XlOMqj@<6vzj7C&PQ_-Qcx}ahdhkxNz^ju0A+qMcrKvoMwyFQqlRmxGdW(lZa{?z58N2`m2;#PiE%RFpoLQ zvAAbU=U;6h67IeGt1ZhU;swL4j5VGmaOTmbtI6I%OZ;jC!YUA4Pj_WvgJ=&-k>Lvo zUB17?oug05bW~9PW&aO_p=^mwvm=-0wPG!|^RM6iFE1Moda8KEB6a3KTiHmPa8)07 z8NBTJ0#Hdpo5Hg0&H;3mRGX`nC-ZBBlIRs50H}xlOucrB!+Qe>{@`w<{R~nPd)NQ8 z0i;ajf!&leRl0V)>#LARUCj)j!H%0=T8E67^`5ML#ND%ezW9XYIi%Jbajo&+euC6N z9PyZ}tu|^$)*Q+EMK%_Jk^f9Xf3i9x=V*^AKCnHDO_=Hmdqb&oIH z_VgVO352vMv(GNBzvZo>4VUBGhII@#+zw)F`$ty+to>Sdk9~y7`VrLFqf6Zzu3l9< zD#-bQ;Zy?q@6n1f-&%gvPeBpPI`v^k`_kJ4*ITj0r<(+m?=!$uEVf+;-@M2Q{-uG7 zeO>AQw0%gZ#R0-Uj?e0%&&dpKBKD*VP-|@K{=L`xN71jy%35c@ zs#zi}*_ETOPUR;ix;PSm1TWX%X3yVU;6!y6H#DiC$b=H@KtA%{mhrz>9}s1tn3yn^ zneO&@{fCd}t6pK`?9{KLxrS0@xI*<_56vgTR~>Uq(+!`Ehf-fSrvIn1@tCb;`g1(a zy1^_I!<-N)fd=YM&Er+&a3of(|%i@U^QL4yz5 zT6r*pl{(!55#qbrdN!C>22>rWkqAgV+@-Vmw|VHmZ9A!^bwrm}*&X!(rmE0%AEo&N zit6n)`IegVRXyvIJ#z!9M1*wjMI2t1vZeW_-+<9}*7px-w*fpF9dlwb5tqN1qh_ZF zr~@+T%Ppk{F~PUCWpI;G`B+KaOoR^vNPQuRdughVQ-lyb9`Uf}=is@#9`8bPX@0k3 zrp{J2ev3XLI-*7LtxEVX^IQ5vfQ3fUilK0po$gp7VEVbDE`Tg^vQm|HaaL4D7L0xZ zsj$NRZD!cK#Oa!xo!l*MJjG8kaE>zC&dDl3)aGvJUXBBOD0{??{|lLUAaPf**NTtL z!s9974=oz8o&(^M@sK4k$u4*v@z3W4!bjm`Rd~+SPhAW=NSwKR zVz=+Yz0qZGn>6A)v3`}w2no}Fm*J8GxwSDNFVtFUBURL)F&NEo`#8$>{F&KUI{xK) zwn9VyDdn}8M25WDsmUviT(0@)=4qBkF3p$P^9lRA+^krS$-)qi&!DMi(`k% zqO|-_r7sBG9tc(Tg2-#wNokCF0^A+q3MQ*{gO}?BTj0GN;YG!ZzWBm4ADR|iqyRVn zeJqs3GT{=fo}U?X=MxK`Eqz?i$)5PUO)HrmT7GD>f;)}0=!fz9YLxA?=7%bOK@eW0 zd!DBQmTf{uLiq?)b&T|S|FDzRS!^-e!pHH9V|@O3?5PmXJTN*vbibD9vptX@P#Ilh zvEWk%R4?zuCIPHRL+i#kFh{`NPbuPkKu&hxni-lgn)!PR_G0Fj`L}olu|o66@QdzL=I@Vq_n?Hh1C1k2eicNPpx`=Qe+F)0IUCa(sn8A|Uu#Kc0n-yX#~@<6+;H(%w0iOd3! z>|vcvR+ZMR&-hm1L-QPN>Kc$Z$XlAdc{ko8WjYWxusLO@vL0iA{iWa2qRJ7i4=dnz z3BM|gnXLNR%4*_lJIuxsLQ#8mnn!@;az2AM4gbgkWu!#jo-gGvnUbqeF8ELVfz&ek zyy9p9sQR#qFfpz*bHM5zfRouV=66-KJSTq4eZ6E z$gvfz#=*GGkW@$;A8#K#jhJ8Y$(}M0)%U;9-irH(yj-GntKDP{OLw{-Y275J#1H77p_r~%wxP(XaPqk3Jpy^ zx1%bR_#CV?_pxKX8O~!dpOsb)B^sJMrD-0+%G@R!Z$|U6&y?yhez1gYTK=l0m6XB7 z>iibmb?B$XTHm2p3bQhd^cj9*uN$_cJmsDEcA?2QT zQ-|Veg72ppSlltZIU5%V%#tcibLHpRb^qW*N7;rd_*TM%G`3QcQI59A03kl7(R(&b^1-kK{#10Nel1usIGo2RatZ6VE>q7*qK}iI6%~uTZqJZc z+-j%bu#tto$n253~ zLA@fhWp#iMZJc|q`4BaiAbN382cP;BMS~5aGT*4HX&+9=tm#xQZwZvv{mG{9qJP~v z>MgKU{WFdAS0yD@!=o%Mx#70;McWv~L2fV%nOdq%wE6&gSzw!obS;lIZn-7lVXWzqeJd-_y%cc+x5QC|JS+WqyCL6q zyPeB-9Kg z`NF#{yUQVinOFgmdOe*YR*pE&A|bK#GP%<|pz|?!r&v$i6H`SqOoHKv8hZi$A(x_{ ziw}B4ifr7Q@eh$U__0$NNsYJc{)}Q{DpZ}WmW zZ)CcEJ9wQF*)}ST%enfxvNJ`7B@g7sR!|FQ*Uh$&)>Ma3ot)Sosy+bEZL2~I$2o2E zh&tLqxs5#9Npy`ww5fa^qH1ew5Z%O8ot}mAtMarYvn#_iHDT=ht}|O++m14m+}Yi3 z6?@u`lzG{hkMRz@wz(M%{kq_ndg1NDQvEa?Gf5q$dYEsnc9qvfMc|?nL6N-JDT{On zrtfc=z2xq4)HM|IM9y49{0m{(i`?c4fiAg6BqiBGhzmWhEg8iJOHSaI7%FT4sSXnZ zAODDehnIZh^);T2m+4^1m|6CS`dV?8dTgi0&9ZyD-rkm)?kKR>fsv&_u#PGsaU9P1 z_v84K*fLv|`ztp>}7U2NFf0<@|~(UKJl zmn&&im4uW zD3F5a0sA^UF}Hhg?LtiYbxeivJ6`o=mlT|vZ*zJ9LVU9r-4j{4$52)QoUjR-grunx z%(r_y2QN*9S>{O>*`?;Ah4T4GR5)dh2ck_Lxv2mELJ+>GTMs8=w)rv>Ooa&1X2^$& z+0s0A`@-+tZaX@^C`)ZdpdIC}iW~-<=8*^v)vFe552FejZNOkEwV7Pa+|suri^g8d zYf$Yksp-uj(3h8>y&_wQXy2a$_Au?Ers^9EVX3t1fX7q~_D!r8@LD{iWyI5UdflR4 zc_Mi_0FQ)=b$wpisP?KhEJZ}GRm+1dZa@nIj;dJVtJXSic)9bo_}aR`H95GVGU{zq zPfa;d80FX2PiUM&q^&XUTy!X8`DaG%WyiBdRH&2iEo8&Y%|AmogB+(Wp#K)n_nLAB zhsu{>&!zcDHCjmDY?s@~^NC81M~CkjpEZvoez~MF&(`T?bxV_DuIG;P+%aqq1&n;r z1}qZIi&i}vA>|DGVpiwW3lm-PyM#Q`YpzqxOF_uQ{UHTJJHQx={hu+bu(J&=eX`jT zVz7|N#O}DYynxwX==F;C81?FoYIv~xJSr54$}f%}Lc8Rv4bVVjvzayd#P%EvkgH`r zL}<$Z_?~WRIOua-!1qU;E+{xCQ{04UUH+^oNAwtb8II9ZSYG+?M$9sB%crW4(_Xjb zuvyqD13Xslby|fQQpzE=fH%y4SL;}$PiO9Hak^({@2Q~@6z&EzWcN%YAI!c3FfdUg zv*)-O7@VkWLuz##^V1gb%PA?}0OkzLv&6@!G+IoCrUFx>4YipzXqI`E0eaD@wX+Dr z1H&Vcb@5@|iv_-*r(mmP!g?%<(c>Ib_mldf#!Z{$Sp$BNRE($+8s^Hj(iXF2P*K6o z(%C%z>GX477)=dy>~H`948vNa62B6snThiZ_<1`#^7ZKPzYE$Ol<+qG95s6%xBQA16g|Mx|RA@rnB5KGN zuZt;KddQ5$&_5jMev-lP=CI)O+2vuJQ^id6p}b&PQB7cX;e0I;TOtG-J`FB=UwrT6##t{(F<3HzlJ&!lVJEj{~bD+9VQT7OpWuf5hz{ z=Sh)}+a(WE0-@z<7wZdNfPJf`dYcsyIa{;^{PbtIb#OcIMdHhCuT2xQh2yM!`!K+#EzJBYR ze67E+tY(XO^fbAHmd6aqJ1RFfL`Zg1y*WTe|Du1dbO?jNLUUR ziMWfb@JBvcm+LjNJGyj~sQp4*M9P31HoFhnbP6D{d0GPjAp(TZU+!CPvGI~w8SO_r zLd-P&)xRC^T&Ua;fs(=^TDtL>Hlpdze;7@3Zt3KHl zNx2g3tJd8P@g2r|#hG8vep3Dvz;$z3x(rQmRGBHkX6k}MmqR7hPX^5XBxGrUuL`}{ z`~%;A-BtXab*LZlq{H^{^1bns^xb=-Q@=mgg^2A8v@k`add^LM%?2W^>`*^)Op_F* z_7>VOWEA#Do9VH-WOlu0aCJYg;cHga*5bIcYTqt+VA9FO&)?Qxw_>yXM?BK>eJI|9 z_pbvZe+l^gQf-EX=u$5cTDydrI%dta;VM|Zmur)rT+pQXVmF*4m}$e^)cLTd)$*kC z(X`*Lqf4Pk9556mwf?8zD+7KW^QnV&LASRZwwD67TgMDrs@RC{$NIqy!VmrRtI9vG zp!L8k&wHgoulF=g#C&ff62BOk5&Q2s{iTTc`(-)3qZJ_d00>5k?ra=pKjJ5j^v-@T z5C@{1z$tv7&wKqsx?oiI8PnvxQfA6^xzFf@4{0BE(%e13Vmj~QJj&OKxk)svbq;)C zn&}6-f3&{i5Z$h!b;JUz#!*xpMGGF+K`Cf*8iR+Ab1THwu(114M_v2ndQEr77WmPO z9q_@s{f<~jG%8v!%s(_xILsd$W)SS_C(#e}P>%#={m@o9eUw&q@jV^wRIOD_EvzLT z7|FGEq%jSniE#)K#)0Au*PE3T?vHZ%^u#YhI@ZDBLTq+9<3enDHKUqua;;spmDBM% z>&(*D6YrC_G;i(JkPUo$USPTa1^g8B=A2jbk*kdyG^@XJR(sYtN;YLBt0RFEB!T8#yTGFctoV|uSP-YdfU?DcWq zE6kEzz$ZqAxcZGWz=oHx&$~JJ4P*($`5UYx>~#j|O>dv!AN(2p)q9?p>zC3u!#7k~ zHm<7Ub`&|?eOs z$_n^>z1vV$mRl2IC4;WurbdpZW{p|`@uPrk$fKe}A;CNz5uuPo)=@E;{hf< znrG?r!X0(DN-%CB%{VXo?W6v=!`jy6mD{Ta1qKqH(Ed#xzgi4^CT$HXC11+hH5xIv z-sBmDD56{doHcQ&@=os;M}i_Y43b1yp|xYU`C=RqOm>cFPPN}Wr`RjW^C{_bT$EDb zdCiJ4sIX^255^Cbg+VnUfxq8b+P{6j%&sg@cW?>TowS>8WaT`_JncOXkhTecyZ1`tXUBuj9Y4?uO3D9Or2orVbRwlM^|4uN!`a8k=>0cAfAL9S~ zU=ayiQSP^UkNU=URaOwy#>@38Sfm0q*{gKMUuycrVI?C~Sw*?k#la$(zCZ{{wo!0ZR-Pd(GX5Nk2pN$ebv=lJT~>GLq0p0|(~ zxCzap939Z~7@^q}BaaK&Ten)iF>yGlQn!xxUkshC&}l3P8uDYu8Y1)ywmi zMj>^tj!D?yG@3ON%R2X#`5DZ-&}kO;ho^Uls}yTg4#BoURTa}d zfi0G7)bhS2fe-HzOU;?^{x@y(q8UJ#6@3(q35{4VAvA(G?^%8;?qaUaruNZOLi`< zf3gpM%^3Jn`p(eQXY&WPuHNR4wGQDN$;;61lfysW?mH*v>Z0U5DEzGq)St!jNzw%m ztmlGVCpUFx;?>;T_+R0cP}fO^a3$6gUV}m(kM`doG#+&t@t)w-x+*y>cy7nZ-x#8ah(iw$g?W1;rG}}8N@3e84 zg@f(IPWC9O9`}B~-Hv$1_cNR1K~4(smoMHzIkW01nGvT*Ogvjue|e)d%|TZ#m5@c0 z9cPHs{>>aj)u2fJjv^JGRJ0ayqa6`{h8JWsi6?ExUc_gAkvQR{jVEp-pA*sS?oLBI zcNtMdc^VO`3_ke{YCHXoCcg7wB%bGMy9!4wBEc1UU(FNs{8`gCjaKs<3vX9uY=)a( zMG*{NB%$V%zAAv`ki%7Xc=a?hRU};mY=4N}-zjFqE88YshH>VDe|7_CYrV-K-Vf$| zZ9@xtAZSs=SP~UpZy*{m@^}?DIMWGCu*Y6-R$(%GW2#w}#(^}(ir zZOrWTD~D&Sl~7vaT4y*rj8zzXHY*zR_p+g_OA*}4ul$qIylU9?{b7Uix7RD#H)HlB zzpshs1XOZee3R(28Ds?{&lc$M2ajNpA`{tQ_X@(W24J;YB)r2TensBE6C_UaBM zP$$G+YX&AU2jgVQf!9ni!me0a4fjoA+LE3d(wO8*=?SlGv#MV#q?sOf?qFXcq(5 zt@QZG9qp!-sM+PnN%{2x?S5?=V#ch-(sc%s=0urDTynzhUp4A<&doEO{ye;))-@H* zFdIKX(1&q=Z)591rw`$2E&bs7oDXe*TC6Lgc4m#suVtQw$2BwQiuGj6diLxOX0^n2 zf}SpgBplh2+PyukBuR#T!{a4;N)XUIpMi4$^mLyl=y@7QQ>af)DRP@;lSkpM#MXBu zNfJ5ngR$cC>?baaXeheu*bkeiinNs zTXsPCgv5#hRu9*7Efl8UW2m1Oep$?ixwhO4T0O-Leu?I1;gQzpXUpEz% zE?xa;H3%{_FVOe_WmDSnS$1#CwkQ=NyV?5X-6+rmJ&Kac3Sc|!H)j||KhaXZ;u?b7 z3^P&A_}C4hNby;eB|bk`SCsh5=VFu}pAM4hTirjOc?TrgW+;6VZHr#diZFF7KfchATBYg?ysF#OG)f$@mmCX)Q-#UsGD(&`I3+eqfz8P*kTMbYNu=M{K$1mBE z3Bb+Jva2^Ki{kSyzrKZtfPu^Vj#pJNZH_wPvUHA}J~$roeTCFFFRVyVSj*NE!Upo= zQq|NG#@drexV~;ECnlmbsX4f84?tER)uSdVT$l~KN z^ao&-?^MZ>=-A!5~#h|qw;g=QOK8E}pryCG%!_=CD-dDihvR2NH0Qh_oHkEq6`m`p4TeU%r{HCLjjozMO z3k)u6X%m!fk=r>!BlZK@>+~gAE3SJ3J&twN-DV^3-sY~KP;ijoWHAF0>JfY9y526; z!`lhVMqLhIgGLy=7FvSQ-p!tikU)4$aT5kfj;r-NSCw(1d1LXp!HWEeVYA@FV_#R zn>tihrpLM@w2R@Zr-BDiQvHB?ub%+jL66DFHBvVhcXfkr;&5q!kE;r;7!o7VWR?g( z{wDo*%cUgGH{r21F{tgSR$=kBoK5Y&rx*GG12L$aS`X=%=*cnIWm%9@Qim*(c*nU( z;EulXk_5+~|0p2B8TRIOx;oTd&?0+MV6H%JFf7&$B`pt=P{ikTP42 zo^MzDxz(%;Rr%r>_G>1`E7*dW7AcwDk8^X$M%T4&@Q%^7vcZy0JB z-xDt)9RZ0oppLpU;}e2#S5jZqd+hN_tI_ajfS`SUg7rm`^ME%pg_$j{Cz`PEloo!- z96(k@f;|tkLrPrfnjks2Ee8cW`Kch4ARy}1e8v~vo<;C1^Y!PWtT<|Hp1h%B7??G1 zek!+sDzvrlAX=ov6JciB{Fy!SYw;iKVD6nOP$&d=Yxl3Ktv7A4{G|_)*YBq-p#-bU z^W`p>&=^v3^Cn==N>$bENuCD_;>$`aZw{nA_jMa%MhSg^GJpBvLhuYzmf@`Kz23Sn zcK^)>7*)k>^5RtRfL{TaJXmWrnz}U4l~+x6Q(tI^P<{R}@uIQ4{V5FBZ0 zwax-MX-XaxtNewX4Oo}Ls4VuEhKgj2woIYr%9C1FN3=n&I}lbt1W<0>7rv=&IEF@o zsev)T>s-z#+y!Cq3@$bg;YAITje*vq25D(*fHejPr&qr0^78=(GR(X(?3Eiy(g3Cl)3Ihw?dGs$2@Xh9u548^s;i6b@U&}{$tu9Ju3h=9(z3&!ttCC zU0HrFIa|kP)gGm;nG+WIqgBtfen#;oX!VP#0!XfsNm#kQjHM#VyEq{;wQ2%}<>={C~0n}yrk7PG$!}||*;GE-H zw#`9{cY|ix4={2M#;=;2t6$hC8$btwF_=Tu`q+_)DBk4qpGgsI&$J3l0>FQO(m2Cf zuSw1035?VI7H9o`=z8bq%z|d&H@0otn%K5&XJR{(iEZ1qZBJ}Fnb>x|XWnz}z2`e? z-G83-ti5*k?%h>g)&1MuRloc!>n#A5lhC*KxoV~EeZ8@UZ{zh>hF!xSG8_6t(jXOh zy5Z-;ML=i{(vQ#+X7C~0Yl~^TA9jX1f2H|>S8Rq&pM)_5O*JE4)XjTdmu&HgF=fS`yR0>H>g@{f zKPE{qQ<_Y;YSvP#o6O{97!nAR()30b!b45$P}kcBRSLsH9>-eG8OXnpoY8T={%kb-?=mEJQy(dAIheHN9TBO{DxwRf7+V z(3)n+OKK_{tQi_l4dtvI9fnfG?V}ax?H;wqE^pr8R>kVs9e& z9=b{c3~xRMf30g36M6q)Rx(G~vK|%G;9*$GeWNn-MUBX3cce86c+1wG>W#0HjX7pk z(fn%GE`ju}lL%Y*dS~r!rfC&wO$rVrf(WvAQ+A<{<^CwfCn~JT03QfvwTOkzhS8$i zi)1cbDKC1mC~QR__>J6`b7so}Ty53%Xrnw}E^ykG+Z+>eT{0+gZ;1Lh zUvf^*qznxw1hZf7Z!7?bfkK2keRZbBVS(N3n?gIG<-Mmxx+cA5(yu;j46cwIalL;5 zEu^Z1+`DL zN_A$u&_|!|tG-j)E9DZ-N8%}!!TRmDjcWu^1gqS5pMoye?(GZcAIHv~^^-f+89tOw z3el3~Nc_Qo147I2G}~KQ&sk+>)F@UgmSYK^BKDcH31wqz<%@o!!O{hvh&5=7KeS;d!3gNq+<`q0H4HB=%}? zHOSTy810yusp80TiM^TD7N#+(1cVg?Z4AP*QSW?EOuJb1v8hrI&$lID|Acsdk?*}c zpX_MkZu}ycYOH>}nDmk=uXea(+R(x_n8Dq1F#^5hiWF4!gY^K!BDr{<5Z1Q5_A)=c z)Z=&jdg%OsQ4elh;0xHhP>kQ2FIuE>Qu;{PHKy9Ae)t*xT3$`h3Mih zq>)#L7@^_YNJYK%O9kGzcJ%ptkNTk+?z5E|3xV3rR9#)PUNa{4PeWvxJo#mc*P6g0 zQqh^_e{%_6FB?w5vUQM94Wqx|ZWF{!EWt0u_@H~$!YUyxs(DznX!uD-IhE2rscs(; zCl~Z1F?mWf0XCTqBZF`rXD1u_d}GS){$Pya;8X%IiMZ$dzL~e_ z%fCLv4_K?;U#drtm0QCN;wlo64@{3OIlu$6pU>;kD_o)DE|n;osz^N76VS_LsGRwm ztSwYFE_G8}=9l z+XNOm6iV6!<^caYL@LCvokxPfHFY|ZVjlCdSwzGTs}=*inla!Gf8tAx4HaAwtc@7g zx=-o6M4Z_4sHD-v;dVvZK%rKXEMxM63QNq!i<6#690JZVAX_gFl<~j^OcThS6U*GO z9iIXvqMq~Tyg$eSe!qiqxdzzl1Z60K=t%8F83JDH{_5lj-Vnz-6@hGl$GTs{PCYx!xI>+@Hs%y;>yPFW-B&`4vxguo5lO#!yAQ3R2E z%~L+>WV^C&_?^6?5GyO4N|oIaGAWHjf@5B5h57eVR7d@fcQMy_9YH3tihnZ)lxTLJ+Sb)@TEu?Cca9V+Qn^wh4qf;~R+#{37oZT>?jHV=mW68W}E&W%nAx1Qj`;kwVPWIP}zqt#JL@|m>1U*NNALeNDLDqzsT z%tC9C?1wGoM(7kRjv+a2qqse}IWFLw@;4 z-bMK<{A)#gQ?#0;9D9{G)JXqtHk;zAxHnj&Do0TLjcpcE8@yqE#Oqb!DgPT2B2Q); z0ZKARKV7V++t)ExyWn5IE^fRa*2O^=Nlqv5JBciCWIxqwaFqg$LoSpukfRY*I?ULc;z1Vj zQ6QpQB=@%tRMxXJ{4Ei2ol*0Kk$^e)W^HdUGz{xeC1#WoF@BM^zV+ zo+mug#CjmQ%3GEMbgXxG0(~BA%DU_gpD8Br{qg!d)BEvZ`So>5*!y*Nt?>Ta^!t8< zZ>(uV<~?zXZ)dqpm>F2HwpzOut$aw+l!y;06FLZSTK#w;|2Y!gm$O44od?61k!*1} z)og5iw&%x4afVEDt0AQuR(|brKzF0Y(MsIBbTqL;H-|tw;a2OX-|lx*Bo3Z>^{f-y zf-ZR2Zkche^Qsb~B-Hy^K(UB+@-9;ureE%J&fhPfmfmbIfuKvZj8by?BqS2ChW73T zG~?ER?Ca=5gsX+1>jA>J7kEhnEp&M|AhtUGNyx96-rsLFm+iT}THmzqoiY8J#jAr9 zT54e7ZpSB->EDz)dgDRhm;O-TTrJcN+sqU-BrSn@WRT%7@a&#cNomsNnG^U6 zVfFFb)qYpQM}R(}}H3=}%SV8|YLzsf%TU zYtIa7-i`4~zfzMrma8A?o&}`AL6k_#?AjQDa!bUtY1>VTFJcmgx|~sAz;k5J3Z$$k zDX_H&NRKjG8;C&9;=*&WU5+9224btMG$Vf!}?^w#su8oxPCUl{xE^VYP zN^nCvLs2)Or;>*S-qpXl`#wD07Bb(MY};gS;NRP;3#}W0B3x4?&X^zLvEMZ!EX8m- zwVYS7{QG10?+1&z94)@r2);)yKP^!A?g+jcS%DBa-hRVnrIy{mAPmR~bbs_-8>(W=yy2H@JNfm;ezy$3ty}fOjx$LJlGs>y}?U3n7PqsJZLtI ztz5?=^D#gfOG4ME4^@1^b1UKoFQ=-Fw@o-&b(5)Czo#-IGV5-wzW~{OM2b3wj6Qe7 znxPzBGK@M7g@+_%@kPqc?Q{IWK8VN|1MyQ)M$6kD#ddXSJ3hZ;w&7-aZX^!9GRGP; zMqIhLXp+w{YAj0Jz&*COi*PHKGe652dP{z(t*@u-PM#;o3}1`3D4j)Vs!@W+Ev3ce zKuZmf)a78*gOp9q>R&?3Z}PLo1KR1#)TJT#=v z(J!INRCjq~K&>z&knyv-1+!ky2&`?0>9hn{(dQm5@?LklF`bUx2$O@_H=8nba`i~( zDQhD5CWF5(rkkmNkyJJ+huOuUer!Z$k<0YmbrWL3eXpVR94pSxoiiN-0FZZxR!hVVxi3Vv9k8LcY+sXxw#NoU<>3p5bUR58TaQEc)Wp zP*YHDoi3w_+~peml@R144iP~|kYU#|5~cK#h<-7ld6diJCPYBqyQrI%SuCQ1a)7$P z8m4ZpL$ZMD9Q)QkgJkE|)-yyGt{gFcLGZ?MoORq43u37)2?z081QmylctSUF+S^&w zZ13{Oyb$W@gZsMcGg?rJWD`c?`GQSgQkKMm z$;C0Zv{#@$@BZ2zry#cIKHFR3LOIBFESp{Ho;I}_8`qaou8@$?^BRIy59pDmQ$vfl zFH}K)FuQ+a8o6K@`8+x4kv@#1RQ50s+HhT8(F7FzUY;Z+{VB-nw%;I_HrE&pzs*fn zlC@ww(2)%7Jp?HXX4169hjAov!(|%YD_`sEvc2lK{3!OsWM$dDj7{$vB9iX5y@;B; z3UF(olHtM9+CLWKO-sQvR9gn51p1;F2mJ=3Q)(FiSvRBDvE4?6D2h_}BpB3)Vd|RH z6->$)Cps^pS2)E@p>>R65f^o)fw}iaxCAi|+x(9G@l$WUj2Zo|<$f(2^7Lw)CY{x{ z$ZXw8&hAKvn;4snNN*_8@-mkzFFj60aQMyfd_q6WA(bxn1Q`+{vV|~;&;rGQ0+-=B zHSFB{8Hq<*Fq;B-75UyEc3kHM!KJ#?d25Kg3d3i#N8$ZqhL&8D2hrtxk~yb=JId^J z`<$iYT9e@+AKD!0vsDsMp2ia@{)RpAixuaOv9S#?%TPZI6T`|Hg>u_Y_IA^AYk!43 z-fJ&#LY@@lIRek1^VLXWBb+$uk4jo5<$yU3@G>Rj8lApsJJD^amPn7^BZ6CVlc<_zoMvpjboP1>X#deB!zZI&Kf>qI~a<)LQ{*tnU)uZkWqsT ze8Ds?E6Z-`=p+;26O@8%mFdCl3p)ElD^lRFIc68p*EV5Fl|>@sMF{JQF>#r0S(oO4 z{h7}*CBQOtLYT!QM*#9F7)IumSmX?O<`5Y40KaZ?+w;Sax5gYrWaaO6bNt{XH3BAE zQ!4_epR`@gbQnYszF#i{-yXAeql4vU^iO{(LvM1b)*M~k=w>9|ft`q7GgxF`frC0H z11W88EgFJ9C5cWGRx^$2XzANul+PfAykO?fKsv!WI8GRKKEIyxB=y@_AI7z*A?X*p zEU>lN3Rv?8xxwR#uGhIXw75>6Xz)c)T2h7_uoWkfp(Pr}AmKbj1nfm{+an_IsMW(G zejrcsSz(aB>7MQ>sK^4MP^}8rR7e7xb;A};-ZcHVeWF5TxlAWZ*&GPtcDAf`_WY0x zuv=!(jT`d3+(#2WGrvioK{j=ecex4c;&XX7NggyjNAzr_;7{JX3 zgL-AHFchF9x45X`)5_3;T6*AF+ZBU_c4=l-qk+IYwK6khI!B@PQGCUX?X|fH`C4P{ zh&YRdHm-wHZUuk|3xdNad+VUsbTQn+)nW9yfK08%t&pncgEF-gPYB>w!kjfm$%C{ z)NZTWEyO>A@byOSxYOcV&M?fb=AmT@RUo!6%g9%;PQ$K4+P_eRemmH=PovzR_u|i0 zT)S$w$bdHldfgmJ8q^b%aJ@bZ&Cl`7us^jP44c3S&=%nbanzOONY?)h^UDErIo)Lj zz#ypjCot)_!1dw#Q%AkdF+nmj)wRr<=wz=d_D_s*9c6iA%+va{dW|Y0d*aCiX@9pQ zT^8L(1K?R5IKcg!0ml&psm+nc3kO|p#MRGQd2fDnqUW~}M-bQqoGqdl+%(Ozz>ZEQ ztV+@NPZl%QC0zU@3QoG6VgEzk4NyVv{lG>T({38m(sgbPmgD%#fRD=of3?BCxP#iT z*h{iiWQhSs*2Yf7FO65YN~J?^ppezYTq8}vf}oI@oJ|W*WG9-|>sA7Ie-0rmp;PXU zkRs-0gFc9bgZkwF5-7|d|A^V^PI)2|j9NvC)33&aHX_4HuR_PTDt`F-I86Z^QJ<)JkI1twkbjUi3rUP>sBdTc^ z5|yh}Jca3jJwUH~ARql!?Q}4F!fcMDk|PzW`xJ22$Ru5}1ywNhdrP^Bhm|A==d4d8 zasxShqKdX(RZya3CuBabZ>%%yzT3Ba}1i*C^*#VnVD$5!(6sdb|sM*aCVphq?wOX&O zAYA5hA1IIVzl_JG6(+#!SL;cd_)wmrv(7uuY0&M)&wZ@dV(VaVx?sO20t@OrRcx(Mh4gWgHa10;5skO!{Ul>*C@%(9D{mer@IjH_NW~_I@SURG%9Is1~4%Q2K2#>$?`M{ zyL*V_z1HkkE39Xg7#m8ER6R$52u&a@-$j{FcwAVI3tOyyFIvN>6i!5chL+M)f z(I@ilOy1t|auNdiaPmvIvyNqHB>rcN>v2$r5O-P~>`XT18Ypo+U1igPzAJh|=Y~+h zmDNHz;mU?U!M!+8@A@!2yGH!3YG;~rsJ42<4WdnHwf(aawFbS^9)3ubV!HKAT}Q*^ z>4ROvnxcco-~r#?*PQ=&lof^;q&Mj#A8Sm?m+j6x7|W0GR{)Ns_MKfBcDZCnwN})ISrE zMAZ7vApk_I^OK%VX~WsjBr}?SNcmD-Ov!pt&+3xe@LB4hjH{qScFX+30{@ZvN2c@t zt5CFFx|aVGsz&c3piHQ-ieEUUg$Ny8g}D0H4UW)`xoESZo28~ghDmuies@7r#={HS z@r73Bm~V4r?5ytGo@}S4vK4JvM?FX*OWjQjS5?Iy2t8#ea3Wv^DgD8|KBm;wPFgK5 z@6Gii#@>nE{<%hpaBD1Dn+mRHCeVcVF|k{T09x4gQNvFH{O_nBv#2$)V1#HW$`($@5h zzP;9oiO&qH&TeD|y|;tKgpOeuh|owBJI@xWK;7~v0`yii`iBQg z|HScwAOzP7uQ!sJ%C!?z+btujb8K2Au2O|#8ZHw@ITh%Lz?I=#!YblI%sNW-$cGpH z6Xx2cDI(>%xHr2@2)6-S4||K zEL`rIJup4Y!1Th4)yI9p$#%v3!BZP8gxfGpKek$bN>St3N>)N*8yoEemtWifbLZ)C z-;|r$nYFboG7O~8(0?S(EH*(9Dx{3ZN|HvRC0}iAPc?IV#2@z|CLW&7vVoNM+4bn` z9eE9uC*g&+bLK1(d$94#Y=lM0QxacfY2<_zWF+L1vgOuS(h7#Y-_35HE4Tt%D5sp- zSHUO8nco^oX)!5D?7q%{eUt%^>5;Uhgx6F&*6W685o~Jw*hwAw**wKYnm;}yObJVN!RYskgLd#mp zrrVOJJZd~CMR9irkPNLaKJf<_xs-Nzc>qz1xY(J0{T6apPvS_x5|ZX&kj!?+_5=1} z$TXTyV|z#`9ge3$?KQG(f$o=eUW|V~2(@Z`(PbI5l=AhPCS;W-sPK6dEoVHLKD$Nh z6Fv=7jbs54n$)67?~9VPZprpX2L>6cU&fFY4OT2Cop;zwC#VgxyKOfOS+M#5$`&xk zTiIvqt$hIB(xQ$zvq+&K@lIaiP)Fgy|mMU*n-I-k6U*(@7_2XWw}Yu9W;JIMb;Om+3)$&{IY3F+LtdXO)(6|~Uni~4A0;A{E)^Y@t>Qh4HDsj%0!a(Nes5k>Kk38`tSI%$9oOa;M%YkJRhSuqYX~_qz;AP;Zk^R+945wI>g5CYCaz1&i$mlTB4JFO=iXqg!1q(8 z9{H=-(eJ;5;Jw?Km)miA)X`G*sf+%`qdn?l&BeOvecUOlE_4uCQ`s&YsC@^6=TE?y zveCH$_9zb%gL>@OP{!!xL}?PI zzrEot3%`Hz2p0xTHrUtFDlo{yx9iUFZs-|smXZk7e&RkFHckLOK|(lMPiMO#)N5uIAz-YR-QUY_hVq^N6k za=_WXV1l_rFA%$}j>6TAm9&L1(hd}kfy8;zjI@r}WzZcI=ibytL<9TQ(s1nE0XEwX z?^#UFh&duoK8V+!zDlG(jR+ca6VmgV>bl_5=}&m9DSW|oiPncm7FZizit)3T`Xe#9 z7q{;S+mD=qD*zm+1yM^G+9?F#KI>U9vIGUV7E}2O?(5;m*5wz3Zk|JlG99n7(?F`C zlp#X?*wjSky^38Gw(O9$+a*-Mmw|2ZzG-?w>$2lefD1_)8nwxhID+IF99)K*jvNY` zieYl8Yu>+1;xUwGgmCWSYaQmx&mJ4qmaTPT#jlGi+1Z-CtQ4)TsoXx(YaEVI|pL`Ree-u+i4I?;MhQ9l}&o@#|_Yk?hQVOz4RlxK78V&#>+cM-FA|_%#bLGhEj!xCY zD8hU6rsHW!MkK|W>1U)rdtiijwmW@Ri%NkM<$Is8#ZN4;aWPDNmUlfw>ABDt4iC^+u;tO0I z{?;#l(ySY{G^tF#fi_K-6o(*>_p`n3>ZCat+T(({X0wQEMv(7cmMTg~{BR5pbSA*L zM0m3MVR+zd!Met0W>Ewr)0uH`AIQXQ8aX2#Z5_0|>a^6f7f7#Bjf+P4R5L$fyhO3d z%8@w11s(K(@=wrvZ&KHD`zF!}G0F%p+lGW<+vOD%C za**MU!Tu6IbXAwl6OZ)W+~?a^I=|qgRR*&BxjExuZeTKMem+DV?$W_N8f#;n)684O zy$BqmRYIF@I_}lDUu*+%G@gVORFtMEAWBS$?cPT0DIvU~^AQk+r5eAVjNDYaz7#+5 zPy(SCz^V=d0dW*zJ+=#mUIo9~R8%>Qcj-C@k5lT8#J`|TXzA~MqAMz6`$LSsP%Un+ z$60xH`aI)#Ja3b_A=7WRgy;skXn1nkqPD}%X^6IOuq1#C&&N?A!mDnOFt7;|Ms*oo zOa56G2m9f3mbspj=b?rC1Dd~kq;cM2G@A6;u;V9TJM28YYmAOmR{U}6cNadrkK~`G zQB|5&RbzOQK;a*h7Z$P2w-@|UwK8UEs@}1>gEJ}-=reiUFzB z(@n+Fd-xv|vfbmi`A~P|l!b(w-++NFFE`xuh|!-hGjt(2TCT#ZHQW}aCWW?Jt~jQW zucCX8SU&yImrXOnuea`+*Arp%I7D1pe9{;Z^0 z$Mm{NYuwZVar8de5TfqdJspPBG)(JAbNCWzB%aVI@)dVgn%WBsZ3+z?6WbawWe?a! z5-JtBnWChN!v8>I>1%25-Gn%` z3}s%KoZ-Sm#~m99YrdISJl{aOFc7vk0ceonsz&jT7k^rT(0?2<7>rRXd{lniF$7Jl zquACJljp%eSm~$^_Xho`=)5`;c8RM+k1Gj>u#8Y)7J#Be{u@KmbO!pjw?@#P*WDqT z^@p1~G(f7>qhxmP@+fVmY!$8d=`6MZIOIW^RF2RBPex~;$F90Vuiy!-k`qm{!GSlS zC6CJ@28Pc?8op?K>R6j3&C{%_kQDO(5z|k(^=_xeJND#YF$#}t$i+hY8@)&Z2FZQ3 z+qQs{XbS%37#<*ea*Y+5P}+=_gntxrmV;rJi+rrQVb70Xr9u24sc2STOSu_m&Q5cQ z2`xE98Lu%3rAHPgwWh0lI$Pz+k3-vc4~ z4}Ey1?#`#W9kagMU>liL9pbm9jqV_hCuUm@#&%MlMOC&0@&Q&>ZP9qHk0Z=wHcY)3 zJ{nr_tM-2wq?DqaR>PtawG;_VyDD^bGaBmivO2tV^JqEJRW}CGYECyWD%O*D1g|NC zt!Hs}KwNiEdwdH~cZ4B}*_Jisykc<^9$|Wn@Be0y^O)~Fq3$dcZ;wq56?$2`)6Z6y z`!8xeicr{0En!LNnu^a&sGkWwI=D+jx zOxvKV5}~q|w~bR;Izo_@>ekI<^>o<8n-k3!n^sMH(AY6?58VG8G(Y}NgrNHq)0Xtz zfQd&DD2KF^+3g(v;)2gvYk7vaLiA;wBKs^pB&gPB?2r5FNA+cs`|eGBrRas%?Ef$8FAA810c;j znoenO5?b2+KLBY$Zw&{=eyc(fYH~^Pvc$kI3;>XJEyf9Ht* z5LCrfwGaXpjV04~Jt&+~6r4U~PLB`Q5`;l7jE?Ivq4tAW101!j?ek)*X+8jR(86Yax=y4V1!%ig_qp^Uf_#1 zPwncfO7s~63duEAp5;iGO=dy?5!nK-!AYd=;1iMiULS$S%s-m_m+EyIpiIsS?#P5k z|Dn`Z|3#?*SAks)b@h%JbmxZ5t^lB^bQ8etOToCt^fnb@&o{+D3X(JFmi!cw4Db24 zD1z*|C>gDbEb0njrt2^Ya=0wY9+I83Ups*w%tdsM8DjpK1wcK%Ub?oBRm~P2zXZkS zth$U#VB%g19GDh}^A*8|_{-f8P-u(Ai#4ulFPu3cj-xT`oG}glX-MNHctKcMw_Jp` z&|1Z06KD}1S%{neLm)wxqb{k40qQU_F(BJijI3-eW&G=0hTv)Ub+S1KzL*n|9&JC7 zD9$3PZctpg!@3yEl@~FBRsFzu1il+-*HtMV(ElQq#ZMUh*!9FjYE>Ag3;WSnkk=`o zJv?T$dPsRH2zZ*iSxrl{$=HVa^XKDfGcBB33b3W^uutioyMvp-B)WgXk8+AgOOyJ7 z+3q$6ePY_UiN&kPDw6~wBfqBj0I{MD?-n zWKj+t@Oz9Zl#G=lHvR>@SVO;Gu5G!P4H3F#M0fU$8=a^4hqQ%7;OK*ZZu~|N<+%O7 zj0d+n06@k&KN_-zP-e7E>H)eh>A!H(wevqhq7G%3J|4N}Z?xu>_y1H4wJU(}sCi@PShAlpgn>^HIU-2Jv|~+gDsHbH zQ^bj79;lFVulOaTdi&$@^$m^iDXY`4w>^?EzrA2k>&kdV(QH0SNSdm`L_!YiM+2;T zNK!G5dAv4J82xbkvZyHm@vmg$(q0DJQ=zK@M7w&y69+buV(GQEv7gCfeH(pKC?$(i zEps6mDJ9vQgLSJ{BZwYl-2WRw;$j%Hy9_Y&p~t|sYC8G7GYA3W)qChVNEqYJj%r0v z4Y+5hKkIccSP?pUjkd!=HaTQ;O7c5no-(<|iy(}12`47>sU%kLA=bbXRwP#T!KMW_ zA+O;Kr=3OAuSJmoi+(~qdM9-{5IteGN9qNzjdvrq*-|IB{AmdmwdCgL+N9SLhz<*= zWv3R+u3wB-^>8mIyaD+p=e7sC$?Wt9ok}L>oYG4Yr%ksrlf)sF#^?HL>35z}9=jEZ zA*rQfB-zlOLHZySr;@g_ttln{JixySx|GXte=DgO&HX%Hp?ob4ZHL7qbIj@F3<69fYMe1Gfbh9A zR@z}T*c{XUaY$-+z*hijq3vS;)<58O7oxv|A+P#F9W4abirD65!0YN9-F-NDWUTN} z3|N56);UXemkbj+`c6Cl^GSdI%VzvXF&N$$%oQ>GcR4u0(b1@K&sdD`JwmXTTJ(s} z7_}%7FiLgVv%3PR);b6giG zVpBgbPW`$@2#Q$lluJFS%9It-n6CxGD5RT7tWA&*z>a{|zGVB{q^K3$u_Yus}+1&M89dq#PAG>BoQS*Z?^Q%NO%()RsSbs~;tr#- zKdzotGW4@ObY*K+U^hEjy;0-EuMXt7bC+cbn)$*e8=FfKDF_$J8F_A8aVWaoxd{yN zqZgZ1_D~*+9?V$-Mv#`PlK)UEmYe@ddF5d2JTUic)zOgT z2^wrMmhc|$-RiR4)SF|^gw`{Ggo9yJ@I>?ki*^ehguJ6{ogwZtOKOKTb#TY@`tHYY zI8x$56S3f%TPNKta|W7%aG{8#^ACR6P6M2 z4ChuW^`OyBn5e1HejZvRY-DA`h$~aBJM<0XvE?x-Fbud0zh^btIfOuZIApNDb%6u6 zw%hNIB@dwgx=)#DKbT-NnAGmXQCHCEU47Xg^{c^`CwlT0xx(8ax^Ru3*}JAy!%I}e zFhCRD^sj%Uy>_Xr{^oqsqEJJ}!`&O|r?*ef*e${Tg(AOWuIQ*3lg|y)k@t&>A(DZv z!*MN20%j#_hTV0=K(Ac?(r7iy^x3OvN8WW9dB@I>vu1@HLY{muADAlr-9jz)m2k(2 zja4_6p&8^)1wz$Vr6KFI*Pg@3@8_Ph3-r(l^lWUm>9TpzZs|_m0nU{%=ZqdfoP9MJ zaisJ0?w!9rnHF{|H-WMCTf=D|;s%S*ZwEuU+ZC7ha%9`6ZbbAn200k$D^!R%WXx8&r5~Ru@VPPENfq& z88}vp&@?lz{r)w6WcNRf=LFf=9E1b?Enc?Gg|uDM&QsJoS680Kr(>A^Bnyr_sUCvy zW6%anN-0;MGj~Pc`0dzU;A4jI`|TC-b7TJd*X&$q8jlU0E_g+TL^{+<`)UC)61Kj< z%0Pw)j6axp6v#&<`-%q zVV5nWosL-z)3bgbe=Z{x;C2gMKVRHHo0c`GV5(qs$5!Z4Wzsd8ZRxrmB(^z})*}Bj^E`iKo;kli?-c~JZ4VH?aef=TZFCj|FJo!f6(HiNqgF~lyB_%s(#k=n*oce@ z&-YKGb=v6uV7u{yRm+KW%n>>gf7&5-CV9Vhe2x1g)g>_fCKUL3t85PaXnOm-j49_` zEbH;9YMh=Osv3^X@k4olJ?g@zBX$iN8Yo z3NV>=4-PS(A3Vh$V~zInD3drgxhW|>i1{OtXsw4zdaAf|I`(<^_K{qlnlVVI%ivYe z9?+x9Qa!$sY@ht;!O+03IFF{IV65XIQp19PLjzS3}= zNft1(SDKSnWzNtzMAkHqVHVxeHgA4xqzQ-Ji;i`6JPtCf!xYPVFK#1c^5rgjLrp}x z?Ce;7VkIHM`>yN3BL%#VrQg{Y<0}&BZ4_xqRMV>0ke6Q`Hz0e~g{~j1;@gP=37p?w z>O$rbG^y>B{~>%(*`a<&jb3#3y5Q$7%LP9Y+UNxiG->|*^04Ex*LL7^QLoxWo#ZXY z$;~9_JQEC*5GFy;ru6cFE53zMeX(Y3z8dt2u27{Aa4!)s)Ay_9n`0=ZWg7tCdKX(^JRmKt@8N!`|R z7^%*2nlJ*XDuat}7APjZ_fIR=T;=T!_p7%4uwndVvBtK@DOQ7yOGc>ORHMNv8zjU!xD}cn zulZyA3dWZKg-X##Ep<9IzzJseXgUFD2Zak6GRRaXvMmekL~nRfWcD6|59pWE3VU}H zpV#l-*GZq}Bj3c$)$vay`gh7h?UB&&5q#2`R;`+!^Ki)S@G8SFprdcRI@ zzd8=SRrE(X*gJZFOU8%t#$SW{YFjuigW(3Kc`#ZK5&fYN`|2n<|)#HIs@`j zHJ2KU`oV!U49^H!8o`srRA^9-zsHzHv?u^FD{vDnK@Jl@C2GU}s}vjgWuGuBBP2h+ zCJBqVhRnOB04Tokk(N(0Q;WhdX2-)k^#yP2i@aw;%OU#8j-OZfxrN+%F^6q#kqatE zv}LO~jsfR})ulfMqa6PM+Zt>i?MRzXLsRyH%y(G%SjA-p9IhE0n_T|9URQ)_t!kZQ z3&JQRowRt>sKXjm&FId8AVY@LXlxDUz6X@wV)8~~(jj^pm9+*2_sU{K%~NE?A8n=S z?j-Eg^k*gxr_e*HoKp$|drb(d@j|>2dy;kED@|9a)H|+$6yq$HNpP!jD6LHnmZScY zg8<=lNyp|Tk0*^k=a8#6@ep%`z+Zm0V!7r@3Kc7O!XU#Kq#LzA@#i?smiyVuU}C63 z+qQV3(Cn~mKGs+JaLI(>y;RX@)K=?EE80i;t9h+){l(PR9} zXpTFmLU)^lL{C>RWYhgy`V@}9Q;AOk^y!8a^>dw|S7Zu*K>BmLK-j<<7w4@efNb7{ zZIy;pui|O!KRAV-dYI*&xSAw_QCoF@Q~#o_0O^UrAjnV?4BVSg6QrsY6%VplKm&sW zk8xJTSI3t-GIWQ;d6HIW2EF9_tuWQ1G6Yof0Y4l|6#Jr!)}r028s8%2$zTr^b z*M5JY-TgjQU+TC&%ip^%S=MwlKk2MeHD-yWxggufI|$3PMVXSTg2q7*tu6k|IgjFxf9~IUmQ!G1i=32Rn&QzH-t@SM2yzLyTa{Lq z@aw0uVrv)v_S>F>Q(tr471p(s)A>=XZu4}I`(BT=28QC4Hs>n5hV`uC91^(-xx~YD zb=|ndSdWG~&82_E*GsHja?%{tj$H&;rz^9~CoC0Vg)FE1NO<{RK8%I`ttr*)G0MP_&RqbZQbvx zvgyQ0!c0XyEQ?krceEos5T=0<0kV}3g8k{vx`(p<`1>^{2M)GaO~ZFyM!W(h6YF?n zv~%~I3ilKimJGEk#EhlUQMO24X5c`vt->1A>0Uf9W{I^XP;gzelVG#Xg1eY{new!H961jxRtd<^uPA~>qXy7<6_RdJWjuhU!vi0PB6ovPe3hY&ckN~fbp@Rz zL!Q$EGs_*a+3SR2XcMbjjddW5FLPytH^Si9i6^)6oY#pY$b)`|tAIDD&sQEF zFFEp>WI6IitOt#1| zTOx!NiD*_gYs^gQB&c~=kf*Q?w859oga`_CKe zPT<`bSy&E$2P7LSi0I^(ixrY21mupO04Y=W=*B0(2&W#q=kSIciViV4fkIaR9XF~| z%ek)Qq$#=ojF)PW^TO+Ji`vk4J7_|moOrTaPjml}KUa&t%fNj>Nl)GE7)@oV^nyb`$CH|4eMY_|)Q zO=vM{Z?_A!LFiMb=9vf#<_<{dhC}QvS0qnHn{2kiNv{<`)pj4jg|0)rtin+IMd-Xz zU?OFw(>vxTdiF~A3LK6SFSi`F*9>}i?YxThJnf>fB=_7cgbc9^`&{!LH8d!JAEEo& zJ_B}}&+foOjAsoRdc&(UP|fZDF)bC~QVrjhAH-w33zUUvy9<>e!s4?GVOKKH%sv}f z1r@8^j*_t1y)oj6hA+EV&=3~^GfBUWa9dBh+pO3cCB?pQx3tSU4AHvYhx|`j=KmFK zXBWgVsZp^I8dAU|fG1~pdSg`5p}457tLMolhCx2 z{g%b8%WIFnu}}L2*V)AF4&(=}`O6syM>$$;j|XDE9SMP!L`=)to?)iH0CK%A$5UFa z<=wle#r&j#w*;n!K_R*%PV6C@GWIxf3u>Sxz2TGpuJufv+haU0&8Uku1#5HII!J_g|c6nxHj31(+% z{3&H(w`YqAtfb1Yu~q?!Ij-7Fj@8zba1(ox-(9iTTvoj#C+$hiqA+r$g8LFQ5gjV9 z1VL64Vvs_UYH0uj!%M~TR_(d4+v+P@O^!l4%zT&Cb^!!SOO36Lap*?$DU~ zTm_Gpf1h~qvIHSt*Y3d~h}i7E0llY*%NcYWj$+sB&*~tLQe5VtKAW@TLvBqQ6qzgg^~1qBy92^yLl<9y#1u|>;fk#oAHA2Mc=i}ZPey7Y4^ zpYiyAN_-LGs(9cpdo#oe%m1LlpMJxLP5xCc#W09!<%cX@m6jn%?Iqgh+Tr4Kuox6#_nIC1Nn5F!k~`sp&VOcs zIR%b>15Lw%$K-M4_cJ#MME(ULRWWVOx2nl@(DNJ)h|>z03Tausk{S<#U=Hm{61CB( zY~gpPQ4r?&r~Q5+wtkSTn} zH%-_NznsV4&7KZNhZvju`#P!Sv^V2?v@AC3$oOk4aRVLF;a^Z{l(g=18YrshQP+Sd zvW}erix-l6(+mD)e}%S9j~5l&JQ5fT%~blLQF8U7w?$1(ge=VYPru46P9>H6Wf=BT z&stpv-|V9M#`I}W+g)>kYb{((;bY3R+e-K>L+@)CE9@Q@7}s<-IvP?ovB%X>EZw{D zdiHJ5Qp-Rw394c$4>fdotutqEMu9~LJIWvv+g+p_O6j&Gi0M8qskoYEV2&h*Qg}SS z`vQ18A%NGIS?`-tZCi$L_*HNEt_$nIJVIAo5+8q3(_@7@JWaJmLS>6roq=L}iu1Fo z?qtn$x}MzuXgZSJ0c;8$y{5?@;Bsoy57Q;Bu6lumNkda9A z{6CbvV|Zjyw>27c+_7z|W81dXv8|46r;~JSyW*r{+qP{xxB5NLIrsa{pZnbZHFnir zbI!eLj=km>aV)9R5@LK?W0kF}r%Y$gb<6*i9hZ*~ewhEYcX$ETO`$U54x?EyleVeY zh}Fg)Z81YNP=zgpZ1GO#Crtl@;yJTo*V}k9JbYp{)UOCv$?h+OpS%7LZq<65-s~r+ zErOR(C0Hq4M~+oD;jEiS?l2n0b}&GgBt(xjhi}d8y%{IQROQU(GrI?K>b!L`KCg;?&2jc&Ixi92Ro!-t*f}R9}xpZgD21!P&LQU(w0n4 zuR~Fl;Pp+wCX-6*Ml1P^AmCMB@<#$e0F;)K=<14rNC?Y83x$|vck-TORZ_cWML|`- zeU51~bwD3N4+h1bQIb+MBk@c1^g~pl-Do^pnU)j@gH56xo)88)P37{RJDY zwSwVxzYq#P@5RRMPUoOWfJbyU5V*Iytv<62Rad_X($y+c%_~Y{J3pvmK3WPL&Rr3U z75IICP!NX=)+?;h(U&^B;hWAcrvIR^|AYP=JGWZcs4HuGS`UNAH%p=y0tFX<=M1l3 zfaKU%PUtu3J>zZI4>TER~D#!x? zI$k5C3oD*(mOreZlaPFf<#ubAmr9X{IW_n@fRZCkd2 z_w&OYn&TuETaER0)6`~{bc}p^8$Vx~xBTiCW4qp$-s9*AU5pP>(he^dVNl$jR1RDyRq4L@a|~ef2>u&lX|+coe4kjgPz^E`gb0d%)Rwbd0O`yt8=6&1%<&=-#3O16DtZGQz7`n zfI20cuw6PW+9!V5@k-ii!8+0!tA~8GxSHO*p5mI6@yZppiC`y0^qtJ`-u0HjHuSFM zrO;L49l@Wo%2sw%I!Y|PiKqG*YfEEGDw=kcYf~%$XGMPA=NBVvT^a1Z#7lC|8EB`o zc-)}z48;HnWv(}GROW7Yd=!UD*3IP8XpKVIT zN8x)2*q<32_6q8Gs2}!<*glop2RG5TaCpGE-Sl^OK$`_JHk(4y4IZFy=u*{&ref(9 zDrZJ}ND;CvB`bI(^8p}S z_Qbet6X2kW7=1hTg_ro03{G&e*9$G}T3<&;aqg?14{JkMW@1&idp3QYOL6oOLnN8< zCb13{*UgW2;Vh$~TyT=gA#O?dw<`RPuRD8Ln_CMNLo&MjHeaV5ds$6>05a;mFTZxa z#Y^;J@&(!O<`^D4d!FDiSlnhUo5(E7$tGTV>1dkOGZljK_oBTl_N&9RJ!%TVCf~f2ZcVHorfH!iaz1f_$KV z^#x%-#0+a0#m(Cku}7t}_8t=tvK`t`tBdms$-r4FR-qmYXG{8VXY@Zz97f1^BiMYQ zY+cZ`h`VzT0u_V&uCOS7qa5c|kjO4p8dlBD=C@+v@uLh5%-TvWGPG!#;MywSw)od^ zdUu$9qPCquLZ;y)lc?bl5fv&PWtT3(e2ZA*Xi864(x#<^&~XlpoITWKqw!}|~d?R9;jRPTKR}*MvEb{2B?{bU?pV5|V;Zs<9 z6IWeF$7cR;S`L~e5Ww=fwu4t}v)<9u;Ct0J0SAQ zmt>%?DH6kdBPR4vxM%Qf6?)tfcfe@_8l~luTn?oodd0AO7TMq;tmXJVX5#LPGF+c} zw`^dSSnv-kmtC`iXp+F^i~6mfWJTn}ZF*x({HiEGmJM~XZtc6)vd%D#kiS*wWFXO8 zAGET1(nzmsdm_aZNJrv6es0C-D@e9X;QRNhO}j#a9la+qkKuY=Hwr$%W4gK9rJ{SR zoDw9b1;Bm;vF~dN!_CHKhfB;PB?rGd^Tt&4nJ)!>+PN2Lb;Vh3X(5&L&q$TMz`klV z@LjEW?s(A}DQuYKY1ZAvM-;PP=T>d~?q2qDY}^XtEvL?HIoOyR@&RuauDfpJC_fj} z8_fVK(zI-i@}0a1Bz>p_k3_mQfH1^itU}P^C;*pnaLr_ivq^TU!y-gT9T>ab#YBeO zXTw!<_{S{HkgQsutzZ5y9LGp~@GP=w+Kye_G4x3W%~;$H(~b}vnk=>y()G$O-aLY# z&F}|KX56t5K}5TzRCU}QtHNA3iFL~hqEX$>m1Cd(&DPke$ohr2G1pz{!~RMH2n4n1 z_3``Pmz3S@tJy$P`GPtmwHbD)&&!dMVSt7ZR@DWYN3Vol+}mlp0ji4YYwYE5xq|om z`xy(*vf_PQ4fR+_<~D6@FU9J7baQx!22MByHK#DL9#gvDgNcN0F`V;i5EVLv4@Z`> zA{Nd6{o}sF{FG6y2vN4GJ(k}VU;#6+Nf_N!y>Z65Cf1_4{YWU(rfiXe%tw2yck#|u z+d4negI&NpekbEWAV0OX@r$Ke(6`FG&M9RRg4Njs+?sjmO<|J@#_{>nJAbn@U08QN z;`P{`LTloWxzJW^$wDGP525{)O|_%&kEi+9b&~+QZbFzHy!DG$AkPwJ@?41rMs*pH}hXctdlZkIQnhOn4#5&Y`-5N9f93anxHR|RhL_*t zczeXRq3(Aw@y`7K70oL%1ielTGWoe*eQ-6|UR3piz4r@(4 zk@w=!I6wb1q^B-%EX`pGA`x~lHv-<ceu*L&h#~Zj{60UD-!+5jhVu=F+5DF6g)P)}q9)7HN1T(2_N^ zXVGBlV5nd?tt%^+2WuaO#Al{HFZ3IEa$98veu~v8TK$~AB34_{f=7;4>xc*T^Zja{_aa7!@{T@3>}!eGFBT_#i)BGn$7%EhO30 zL$0u3<77B1!_gp~+F$;@Ir(<~H{*hh;PZbmF57QnHg4Wa>k{8PR_EdN@qR)JES zC+MF*eY1^({iXomfF_EVv?rdAVmK-;j1A>f&TMaU=i0?3sM(^$XZXc>7Qi$@tgemf z1Uf6nY^a9AA#h@#HQ;#~7g+SM9RVW$ihdE76a1)9sO=GQU9mTd<6oo90c@0su@Tw> zyviId;K_2Cgl_Rkw@WOk93^xD`*+z^9s_J4QRBS>V7O{wqH>?=$zZr%D|$T2;q5wr z>uOi(a00(B6XI;&9lxATR0D=Sz;}ff5`X&bE1v5-G4~h*cDpgcX2`IsK85B$9Si-7 zHozm_U&el$l#V0M?-0H+4f51f_(oojN<^TbibzcCDmwlQ`u>A~+sywIu?pa~e9 z7x#e25V(e1Eqx=-w6S0#>6cCr-npnyVpKssZ-=iX5^c~vH(HcyQEi}#F!!v&<_0;U zd`Il|$OE#0l&qYgkDoUdqW2Zh87sn>pfPrY78XnE@-|lZ;iToF2yJUuAGH*pERrX- zczKN)dH7!cq1rgQKifh1?;*K;$>1|UjS!@vqnNmkWJTaE-dM^M){KgxgBife3)!_H z@VY<27OW-e{w+3FKVv&+9le!`Fe9nT(yW%mk=@w$Gd1EBXy%`ZKNS*qcEjsyVm-fY zq=mJ!|C_Ha`T2AL@7;Sq(U;>1er#icRjYDoFS>+lE!AYG`9;0T3$l^F! z?1(OAB^2pnJ0DHx0nTycF}2x^%q=hxYhVu~ZvSq>Yd81W#y7*8gh$b=evP*_MR1d; zd*XEv-@r1Djn>hgi;8V<@OAyN^9NeBHly|eI2@p-P|4Rl!OgcbStXY?{c)vR?jRAm zJ#HX@j1^g*x&6Po_5x@BbKV1Qq9YC)npiGr9oYzHahw97+BooPme#>%ku((CLK0<< z>D=Ll{s_vc(AZP;FRg(5OZz|mZAWQFs(v@N89Uz%ZcNn8p(Ul|ehA`lKbv&yZZKDdT zrob5HiO$$`&OtJBt_48c-@yNye0dux;Et~4mmy0GM8S(cNZ2mYS`G+Hs!_XxO?qQi zpG$mHNh)w{eAYhufL~qN5Ek=76*HZRQ5tn`XjU6rhFVUfrUB(xQLP5r+2;yjie|?O zlK8(JY`-h*JXilCT{@kIA<$#52+I3Sr*MaVHi!<`6q+Rv%W?>uX8#!Q1S4r`f56b_ z6~@7!7f)Q&wBrfqTkyZ^=LR-=%^a1&Ms7B zPF>@{0QH}5vWS7B$;1QP2!`wxu)7*b=p;5G-CEW;M)(~1i{98WnA5 z7m$_|8)z-!J40d3CjrbAI3&Jr!fW=jSpa?1?!@cO#@f?zopndN)oE$^35zm}29fj{ zcvgJ>JBbiu$`#0qBAE; zyO_J)Y|tR064aE*Ma5aR5!3P&JA;tKd+;y>3Thbm-UKNv3XbAa)U6mrnYvyz!uUI2 z#wvgt20oqW_ll8Fw{h1Qnngykv#zz45-4*}Qdx};#8>nLJ{+D^Ft|ylrh^mDNmjwU z9|;dC^qb`(7^gT2&S$lfXLGFHJWzfysX9>|_~MnkT91aTj{z6^wy0*QSdib?c?c}* zb{iy(5d$wONJlP6AR)^VoMC)F8zjyXrrRov?q zhU5$i*u0=Y1zY3RI7q_uZ}FQ`{tXG06FpUKuA2yr=>o=Q{McwXvX zsaOa&29ziNJ!gc?R7ph#gI)Mtc=j2_1+Y75<%w0u+px{e z0{@!^s?og(BUq(_Aw+gj5);f#Y8^s0{+9SVpq)uwH%mFa-};=K4mfD9qjxgm@(92D ze&y%;;(_?<{r>7x0he%nubr|)0--`uq)vj5MtOwF!TDbH>F_bHW-@Ve>9VEVZPZ#IsCO z>n9^^EMcFw&9_I22uM@Ks2D52YJ)!NvwxQl`454fFVN+Uiz#e6%78EIl&D&P7X(l9 zKIhrBxS|J(&-484p~79oziFld}#XVem6g2 z1_9#Bv-@Qj8p_u9cXcj&*>tR|nsFr9MnF1bJpT}#F-(vzc|PL4es|~xh=HiQBD0Jw zABVvm{6dhkar5E5M9JV~w6~x6AVWNtVfTRtK^9+xeRz>w6?*PKXk-+h81 zyE`wcS%7!Em@mu2FlEo^@e$v46UdI9D#*K{4=JGXZ)6>auJE5IM1C}O|1F;Cs zAcG?-4*W-6v{^9wH&3R1jML@0QCNJf!u%j_yWJf|o23#;dj>efN%_q&NOwxgn%vf% z-i5M}44J-#G$~3^PHv`F@ev4tLN(#k-|~kICfi@RM(7o`=WtgPbtC(dX@BNHd@zMK z_oOabQNNc=cajP4J{(xMS^s=?DN!>tizC8oS4M|3K z!>tkF=#pev8%0_k1|5?^zpZJq(p*RkIh7gG?y-ve^tqi0Al%WL;tRIjTGg)&2lJm0 zuc?WWII-4bzZb(3he?LAnkSKwQY@iswtbm@MSpkY`fz}m#^l437v=??o+Z#wLEZ)} zhdNok+KX2S9ptdWuG@R*sLc(r+AaM2IrgbVlBS z&9xO_jmp&_i*$1_sf-E$1w2=_&4xwGPf#Whjh@#F?nyh(JSZ@2|BRItLm_pr=_62P5`ep?$yOI<0mnsV#^=bp z-zamccYtGLJ=S$kb9QQp9<%a`_8`c7-=^ zZzT1h^Dpio_v#{elVW;(KvknLOtY(!p_js>=z*r3qg0qGrt&~Vd&v$jcaMJ6@W&pJ z0g8g;P+`kRG=3U$?36nV#lDU9d1_7rx#aqlGFpqPy}+1Ck)X0BtWw1NSaz4BULhlb z;favk&=QCMGKwmjpw{-RChMeZzKWNl5VrfD-lrE4ND$pVmH|_{%8WAf~>fKSZ~;`k-woHV#DXSTEd8`l7b;yRzzi~AGmX}oOt^8 z$tM}d?PL^PT(8ps5V2;aI2!nM0zK|jCf4XO%dD%K_!SYg5^Ok@6SXxu&)OE%B%2u% zK9J)I)dFlSJ)w z+|9jn79SyaB|73HRNipbIg};!)SQnc3megY7?7~CCDC05qBEh;Ip`5Gsg~?u zL8trkt}l#MX2*^{^9^QP4HlOM6hk;q|8#M_qj@G_`tc94YDl(Vs%4<|v^5S25kRCC zXr@?kI4R31epssDWJU^fn~(blH!VfOxOcgN(L~~2rLRnz>y+=L0Wc{^=7*MNb6qwc zIxkIo`7%BBfg|RHO69o*^P_#NP90dm(UwdWK#^WJ8~m=FW)izjnZ@z>QI$)gz z;}$!K423Y=y3>Qq&Zx^d=ytZIvSrBQ5r1b!@arBa)*!uYNrcnam$gL^AArzFI*)YM>e#y& zs|(wrDV;w1R2p2>C~7U(<_`joUj&eX9&W1v^V%j}&$`j`f(A~*J@Ci!1*1A_NzMdT zj|d8L3j_EJ8oD@?NtI<*PW3x3DuoC*ny9E%V&2%dGsluJyNH6r2zoy%ug{6`cAW>{ zx(Ir)xfwrZ8^gB4Fh6;N!CmZlgGp@&upJ$wcg*;8y`Yl^zeDnMbLC&K(T1YWEN~8@ zY;IQIgpYPYnG(a$gBW;tF*gj&p06C~PtLTKqxkXx;l9rf9&|u>rWdqh2vKWIHPu%* zU74eR*z%fYfJUrOb^8)DIrv&SC5SOP8zh*|;aOu(MHo`1Cp4ksOT-roqTwyhn^e5d z)OV}Wl=T?@pI{nn6x|Wl7k!*m8E|DBMy+5tDO?kp2L0%Szn~Y3;xfOLbrdo4EHt(} zu+@6KZA=DGhz|PlY144WVU!-CT$`U2!*p@d{qq06WB#ZQ7jG!SXhCOIPOX5AYF*qj zT3K{OP$x}cbI`dY_SiSEtRdDB9@DtXb%bAw*uirtM za2}ILT}*|O;_}O`G9EN0tcePZ((3Kz4y^N9BY%|;^iuxxb^3Vu9cqa2-jJmA7AYF3 z8p*JgqS=penKzltCaTYL9_8=V?+24FOI#W{jwxW%FG0||fxXoj=J0Jw>1uCTgcI~= z4^P5{(Qv|)lz#_jsBhJjbn`H#1kMFOYDG^S=qd^g%UT^|36hZHVcgrIZ%66)1 zBNLeKy6=k|F+NH#X3a=bTnNjtB3gw;JX}UCw5O1a4kXxI_qU$9~$fD-eFKy^^=_Ska83*|Vu8}0C zAtu-Z)!$i#1;xr)Qkpux_tr4j8j{f|6Skw6=CyFr*^o!}&)F|z6*%_?0Q32mL+}I~ zW-OqiYex}cLR1B9LfS`wn8(EIAe5nHywyHy1#|G=hcQ7_EP&HmE-*_0qT{Aw8CX_- zJ+@~=eufc%5qd&PmYW1Skbqtsj)!KImC4g$6Z7xpBL6{K2#B}NGE$5M84}N%u76r3 zFuFxKT0(px!Y^VMx1AV;MRHtoq|StT)y`EtVG$X=Aa(vKxwLZMZ*x3Hg+O``l8O_N zLZe_oKp{(mc)WP3UApAdd)l=6J8E$lw^O)Qs)B+j;6i2P6r)?pm;^fSWQC|7;{^wl zH0D`Avh#nrc__i@9Ysb^=I|CVT+QI9sEXwRC!2!7QdG(>#v?95VHq$|5LRgn`_{~F zW9rTt9QXKK%@$1hE7pl{2&WgOg|X1zLjx^^=`i*d=)*Ce^Ek*wk}~lmjFb^>(pP=( zJ$EC3+d53D_e#~rq0X|cg4mmvme(3O>{<7wwo+H(OZQ3Za7oJolWEL`c z;CX^1YUCA$W>Hk!uyv87@n&4V^- zRWd@L^PqU$X7TsM=b!AK5Nj*41%o26q~jVw81obRrlh!ae;t1`X}KjD1z%Q0nYK6X z%kxqvfwfOb9K|CJvBY{`@BCU!K;*}p;yop1J5v^{qNe3oNE0)*%EOjwdnhv!3vhHx zA$ByUD>7O!`YyKLlX(l*RR6~1Mj?-@7Lh-5ea*2aZ10UHkLga>M=|B_M?5`xnWZx#85c1<%{&>I zevddwjA(K~Wf*(mO3@_c&5o?KStXQx44R|_w6#)_bS`lXx>0WJg(g{04eA=#3d75p zxJkEP^k#MvWjXO(z*@Mf&V}YF({p>)?&)fcm2k+7_bFjmMVE-L?wqP16o|JST9dZ3iTs zg(g#0`eVBKd}?|!5|U?awdyja5sT{~8KY8Go3+DGNfa>m20$bo)4_&wt0$BfcgWGUP z6(g#0Q7qJ+go&#I+@zcL#Hk?h#7$ov-*`fG$DwU)f?t7`-SGdaQPyoHe!Mp35lM z@=qBz_iZ74Y;NcFU(+(Gagru$a)&kxgg6cO^u zK7aBX5^n}8by88vG}p@bq|sno2%er5G?|P!g487b;I6%eYirHe@y}h9%!kOIdUZb& zLhq;5lnJOTkqBx_+T)?Sx5=YdG{!4zQ01>6T1Pg6K?Wpa+RGOTieqx>6q$C}V z=F9~urWK*;-dlqh;QXot?c;QC1#PgR3|`B$&W>SDRy78#w43C=E^m~UFSLilr-BxU zJ>I>JR{fV$!6%kn-+;;$S-JWusck#5!n)`R{5YCgJlQsv4TBRAx3+QYbce@op#uu2ySu*0<|-I>c2-r9XBE@!i^bt1 z@XN16f()`c@D!?3_U9Q@1mx)LXYX8OL*b#)`F+)_&8jnP^l3ZCzP{;UTIWYvzkA=k zNSsWnez+6-ER5-8z`HdXo$^Frw{{v=1=|9{3PxhcaH2(;sWr{=orT1J54*fAbDuL* z>hYYQzI*&|EK4C?z7c+qjlP%>-J*@%Qn3-PQXf{GS0dR8Ywe)h48{rT?D^1sp-d|O z$X-*%K2D*?t*&cI3-OeiA571-RSBM3g(0l6c}8sCZ;=9ki1;m^XhO7oe_`+|YVwH; z*BrR=*j0<(t$aLx#9qVFK5V|oZ01u|OWyd%fB>UZdLKcO$S-|vrPv-Hw%FDb%_#P4 zF}5pMmA<-V+K>)n7UED;7zb&`N~ zw9$31PT7ppS}uLtzT={yaBg?wdwRKr-UG5Nc|L zQpYG14^Bk4VQ1f|3 zXf2L|7>tcO!JrS8@~xnTHHh*8JVVDndRx$y8IU}U$C87A=%ZID>FYqLo%dR*=+!cv zB7x9x{OYReY6c)7Lt@gC>sk1 z7-poN!e3MuYW1tgBw@i>-;>~I7qnGmD;Bs@2Y)$GoSM71NU)qVfQ^7KEsn1-kkw9C zdlYg>g2#nSE3rEPpzXrik7~W(`n9cM?*O>9gepwx>)Gn|TX-#g|ykSyn^noS^8t=^LX% z8gnH{C-(nj<*X<6A+wt~9rM!WBSsCozx9OEP*d7C+E%U3&9UcCrpvor>9wHZ!ND5g zKm(M+w<~hMuVT%1Nwwd>S$~tpU)Iq)rH{b$GbSPLcA#8;%buTqZ8<+@m4vQrwQ5dg z%|aIYOBO@EG`*LiYh_!(dk`ITX+;4Hya5ZBC@}DwY`?N$^}SXq`7 z691eh)LCwNQmiKm!&)Vk!pJmDn%x+&O!w%i2gP|NT8^@9HDy>LRmgK~@=lYGGmed) znkSjKqkjOeNBU3XuPE*L=UA&53WrjeF`_tg0(v$Qy3e`DVR3^sp0$P!V}=DlT+crS z{Xo*;(UOn0`gu`yxY6tuBa6c=(~<%s9DN`x5F0Hifz|>f7QzLe2U^k5z8rT_+|4^J zbR9-&TDv?VCy-%tM%E>X$(jKgE^!Sf?<&hi7WJ`yT-up9a2$J=#^;aSTn4QZEL~v& z6qN;vA;qRt}wcOws2DW)Tqo#@& zz-m--v?eP0BNjmh(|zQ%CU8Mey3(awD$@EzCPWL0laDHez)`w1ALC&q@Wm-if_zr| z+oXvZ0X_=!aT8SB5fm6qeB_kjL+KH47`he|1>+N1p_9QE+Bhb38Cwya?&<7xI*?Fi zdo~LBqnEBzZR$4GuBe$nNzE{ChpM#o?mG-hdA8qD6+0}>a=hoyfjj<6ddCbn2AV^#elIMUqptS^Plw!{}}*)7r(3V(`t=rF3nRc}Io0gH|^Z zQ;DmhRFjjONdC(6+~l-M&5LqxH_uV*voFFuCZ((c%Y0|?NE8_YaX1gOY7raEDOFjW z#xMnz;aZmjkCYwlP-{=S_8T$}odWI0u>d5aSzEbh3HOyd&NiGC=VcPomKDziicw%@N`^*MhnqD>*`cFrxA(u_6n z6c^CD!3BOg6#Ntd{1@%Tf&okMIucUFROS--pJTziH11Iz z)(9&J8Kp^z=^a)1fuo(4pTr>ew>^z!PT*5InVbuYz}^s7bmf{zBiVDy{u{5`A}+RCS)V11hT9i?p8?ZWkE*5SCB2-y%r}T6=mdTz$v1 zsDBq_f%Y>MW={SyX=YBr(~JgoY^a1bt&6gyl)bTK@MzGi6djq3Qqn%-1Qd*u3FUUw zsGBVQa_ZS6QRg8f7la`*hQT-0X~1XdUE)1ZIslOOt(O#*%~YJU{LG3VVH zNMa|5Cbfc(&Vju3OV8HI#Fnb(%%!JfT2qYtzmEVBxB{>p^+LmD5c7#tL+!T%wM!uV zg8H0zI0KJ(8Mt%`^& zXaR*7mOhd$ct6(}gb{vRI&Gam^mdROVC^(>&xQ(Zmxv{S-ACJY5~XWN7h^abX%nmlgD9O25Fmwll;7>GL#;1*(AYX~LC z#A;FLEWgDEn@zlEO4mt>V%gTXfx0I#7(y$Qv#vEBBz&Xup7`TKCj2ktXy?Z$Xg59h zfywSQWald*$W%J|q%R(S34%wm3V<^Y4xYFk65_loHWVi@QRmXM(5@*wA6}aHM3YeK z-tAHi_zPGRA1_o9Krio^58%4%`HQTqW{@V9yLrC_)+}a=+o;TxRU%V7V*+NTBT$xU zgu}4m(LaNAUgP->$ouucO}7{hK(`3+Gao%4eBU-)hMw zu0TP?37OLCB|@dtTbuiE7Vv@DV6Jw7G(lY$^sWXzO4PFFeq43=zV5s2Z^?d5`Em;M zt~v`ghAQKNquF0p?xoKtvb@1PlqnO@icfSPI?wr5L~v^{wi9%%eYk4=Rs4j~oQfgi zlgaLbRF|ohx2UcSi3+sGWeW^6p>PQsS%R*_vG_0=C05-*A|!CX11Y6H{zRFFG!amL z=a5b}_VFX_iJO1N*$!+rp*|?mb-D{3x^7KT+9g>^1sGU}%+BM`%~JXDs0MPviy{he zw*=oImPM?U!w5K6fm>3_I=D}e1T1HvMmQTNzrPAJps+c_e|K^wPO@VaA%rjo=QfCy zNeV!i*#e4ET2onO9(T?(qU4n!ogMeLK4=T$Ma`HD8D7rr@*mvb@)(FU!U60B_Mf2DuT9Qj#d(RoTpSrgHW(vD3q67Mv~Ui_<+W$!3@rKF3y|7_nvRJh2f;CBG^h)Uyhtuv<6zf?)f!CI6RR?JRL z@>R2=B7?okCl}B77lhtdu3B)|??=sM46GJ0tI;Rh}$ z^=vuxHBISMeIa8#?5)kl#ju=P{z#h|tY?B1d8O+U1BHn@M5_{YDc?%d@*HH8t|Iz~ zZQMG()dg@}FTfX9wY@n$k#oFw z0pxU%xd_tzJU|u)QZnp91un(Ro?O_EYMLE1NNFhZTe`6v_!I^lvGHE9ssrM zq@QE;vmCRZjZx1|9LN(z)gd(dgZW6Bd`vm}Jvv{6bqX+0nEa2=wIxh`p3 zP2XBo?oTu+EbSW_R@b0ifx|TUgnMlnXOyLO#c$N*_6pbaMUZkhf!~Fc8EKb5K8T!6 z#HS1fzpX>W_$LRRqNbok8K@o>_i%Kc{1SG(sIqLlXP1#iq71+^hAOKbA?e9EbwMER zFR{`~w_JqDPMCVU$7HMOxR~f=s+Pm*%Bny7wtx`bb-S=W^h~QW0j5E<&{j^4QhL9m zQa&m;RgR}jg1~A?$8u$}R7hj}zzZdHinIAhcLKdYVY4-^>KtwfRh*+^b-DKfC^+PY zuTRK3^x}1Yv-B0b8<(F`6)_MtO~%7;Bzd15mXUoDUs14$)0Ck>D`qGB{hLNTt~545 zAdpAr$4jqlL4`CHi;D1GMrghkmiq5kYEMF%@GtIPRcxh8npLp}ZUrFy1;LqH388Lx zvv~e(Ytq2cl`tD0tHOwSbDO?7y4*s&DF8#unyzmPzAYfvBa-)QQHRq$m(}%&1YP5Ipt^sRzG$oIwP*j7Hj#X= zsNynxE;Am21Kwxl?u>^>Rc%8Je2Td+yXx>qHs7fWga$^#x6xJ`$~H=(a*sTIIh~Mp zyY0QR+W}ZKbpW5kv`yaAU$Q~Ld2uu7ffB=|2^u!Y(P6L+`i1lT9>+$KM?zX1Ljk0SFm&h#QHPJo$BhQFn~^Mo&zi zt3+m1{Z_|+$##r|5ob^=epji|$yVm7G3qzNwQ=M~OwboM)!vESm0u0(;=cC9I&Rn^ z@(4A8@70VO0^#epi&jnOnk7GvR!3K^TqMgYxoPs8>T_NM-?)DZwmXpt0A*77ksdf= zX?{gmq88g9eCH8t0PmafHWbxbxduNAHbZnwLZU3uVxAHUqK}&ysmYx>_AqHPs^N2w zO}V*1oVtAr90qthmUlS4J;_=KOW4IzXhP;jHgO&y*WYJ;z(=Md*QVUKObzC?lv`$u zQQCi;Z|d!|{XWoWxio$yFJD{!ge|v^W`vhJ!7)~^oRh?Hj)mj16po{r;4DdodVTBm z-TJWcucVf9v{gDcU)W?(UFxhoxkCJSjf$>}MLdES$TkPdLV>1;?_+C3m;rM|?1!X~ zKH?@$fq450Xkj;e7w@cL4AA^#;b|r5BR| zBgMdy(Y1OSXrcbOeNw0g^Eof3k&V`xyekqs!zxlc&Za}4a!t4?bmZf0Sdx2r7m_8i zO01Lf+DoG%8a>hVfU97mP>)rr0trZ&dKE*HLO*rCeAI=MY@gwa6xAI{r$Itt7;q%pSzlPWr{y}D11+P)guj%9uH=5{H zomiI2xiJMCTRw5Jda-DiWxvVkyVmb+^4blHFZgBshA*f^^#(r#Ytq%66=HZFRfgV| zk>SotTA>-oMH*~TN_X0Ck~pT-?M|1U!K!Q{u(?EE=k@m*xfkLe#yloaMLN1H&B+;C z(KwJZy6h#P=kDEtpHzjsQ4$b~^O9Z)Aoht|zM^%@y$CPdwJ~7Z%Xs1zmWc{>3eNc_ z9-iYM$m+S?4MDykAH%W-fe6C}RocHT@U%g+IV60^YBz?v0=Uj`7S;Q=y73-+x zd#uBFRxaW(kFWm*WC1M9FcC-x*!ME^)V9=A^Kw@CSxfXHGBzaC48c%n;N(%rOmT$w zl04opSKg6$qb<2RRK+Kj546SB3GMR8T5u>db`t(qHD=Nh<{(226Gj+u&cV_^I(dF! z+NbUg!j$0iw>4dJ-OmS%^Y4 z!53b$c>b7ZdMEgDs;okn!H@cxL3hTUYsA%May6-9h8$Ng7<9aZsK_Xf`PB1NC`NkH zK!H`W)DJP28eRIt-&5>)f>|RLTpdF4hBN_>&1@OAD!s45xn)_djle$gXJ=I#3I@D{ zkK6Z+m0_SBFy#Rol~3&t+}p@zfKbbp1m)1q-==V^VVzJpCp|B?kKqTm=L}*BFp=pI zV1M(kT~ud1DQlsPb`;Zq1(KR<&pN^BR+uVk69rd**jXbx9D2BsY{u#s^e1%BS5+m#P` z4z_|&;m!NC!d9&;!0oZi<5n4GsXNOHUyMbpd;K+gZ)ZUBKx10$(T-m5diePW#K@&|q{qDV zu9BI(UEaWq$@8~NJ=?h0vw9CL4AAplwr*tC!sW=H#a zLty!#BqBsJ+GjvSO3pR~E}V--oBDwQX&H3to>vp7I+v9`R_M;KZt-!rV4<3{a}ht& z6Z6$@BUr169azSZQIwBH{2L)5f$o__b^tO9;hTU#5=2oyOK7)n9dXy)sGWcp@3d%d z_YZox=D5IhK~x%;%>9&6$`S-9jL;O}6Qu&p_lryA#`9$(*;%IZLJ&ce)w{><&D*}K zW+(N=q$a2bG*ng8)TZLFLZ4RKDkH%d!-?U_{Ew5Gf}`GM;L)MfbEy(0f2u*{GOcN$1lN`{0N)Os)D!lH*=U= zEkURzP@ezEf(UOE2ArRfN!Zeeo+qSYxp4dx$3yuE0TwLh$Pg~c{svm-mjB)k=+~Xi zZG_%NdWzd7R{nf4kPZ7suaEN+Ua%VhXt@^&eYp_k|kpZmj~$bf5#PQ>qHbRh%SGP49O@rSgSDLJ^5)5 z*BN#PSG}TPJSkeCH&n>I(57B6{Jv->96`qm9soO*$52@tJb59z2an zAJ43c+p(Wb+XuAQBO?9$8OcQfual83LMtj#Ms1wD`?Eff_|O)quMu)5Ug<*QymNyf zx3?*DOTf-omB8h-^;SbA!$vn72~LAv-4fw4vbmLHPSW}1H%J5y-Qg@r!{ZH13FK5f z=lT`oMLg&2M+5Nf@E@OWjL}jjJHy|E9HGtoGe2qI(gyb>*SnxCXVj6CXdbKX=ArKM zyo}x7^Dk^26K{{vg6xv_KrF4@ZVL(blehltc0lXg0go7!TpZRhiD7S>9{0a z2mTT71r7C!vD+021DURM+7H%;D4n34#OEMEhUmcAmexG4Jm*7ZD$_4;N}sjycnj>) zO))Mgr;jsyz76u6j`)!>Go#^1}yYr-9m>=_?n;hIPN^imEN~afKh; zuL{S?SsQjUyc8l?Mi!^DX>G5cx_^Kay+*U%P|G`{GF)ESEv;)mp{5hYzUc+`9-R-; z26o-x0b^6@Em}#M-b)&GbDXbEArw^ZH9`W=%mzM^n<-sWlUO#$yVjGXze(LWskBp% zFlasW(gGiX6M~cT35yT(qdKS1ROY&Txz?wHp-*GNryUwD%wzI zZ-AfFt7GYECZYG3vG=#X->gl7$E)~jebEEN1ibg*<5+mwlqT!}H8NpMgh&1XgO<@4 zigK*b&uu@sz#rF_r61(KI>8;`FU_g>K%O{=5$C990~M%2v7UZO{9IjUlUc6PhB(oj zP`4qy>E)@!`ehAD+&BKCPtTp?xw03^7~&Cp_6hds}{Dd7qD)5rNm-`AdL>R6EN9(C|LDM^a6DjD6WFrU#7O+bAGjc z;jpH-Ywru&kSgDlAQd8jSaP_-w%6t6VKFM{MitHF;ntTd9rL?@H&Ap`my_aM7kuK+ zg&_woTKq=@B5Ztk&A{It#Q4NoWBol=36Yyq@SqulibJ?XkJ;ZLG;2p;Ud#LlTC}ki zY}&GIXlG@L6IA(ypZ$f~%6T|WQ#~RaBtx@*6}7}l#2v@R5S54viE_0e8D5CkH3Q%8g5mAy);IWpYaU zdBY%J7Uqej^t#Su^(r_>i*^ZHx+VQ1z!KmD)ktI5cz#6thGFmGkg?@Vp#!2dk&3~< zwNnS}7++S4k7+s;Y&HFuOgqW?I{MBa?_8U6R{JIohEK4PrRd+iaZ}P|~v9GQE zIO8MYncx>1K@+pu00`00G$}g zet{9U9Ituw~WXMdh+y4%RulQZ7SZdhM8+#_;^NRFxAr=2B&L zp%nb+9?CE2)xM%`J`BE$Z=5_Se(@)ls3)LeJNS~c^PRw`kv)V=Mb8^mtJ1eRhkQXa z=@c$?D4utg*458c4?oE)vu39Mc!A6joOg3Yw1AN`2TsoAF2tInpO_>kcG<@5QffPB zb~DTkD_4ls|xS}u_gU^vuy;c3T%V$GD427r-5SJK6n+?Cqjy6F{I!UUSCEj46(r+!_s87s03l zN&jKw44V{yRIAyU63^fnl>JgHVyFO2md38EbA!) zyqciwBG0fYm<@Ca&rnbTAyiWq`hm+zLSQ5ma}t}2lan3yQBXTxqTRf0rI*DSmI6fO{nj&p|V?O?}7tYMUj-cz&X$?)j zVpL;p*~hFOD1V(u4Uif znP13lb_H2>HlLKU+ry5D&u?2y6)a_$PcI(TO!r8G%JoOI$HxXzZoE2^Sxcj`+YU3caE zgMk@)--iL2xLS+7Dy$0OOvmab;#1i`&EcDPk_Fgzb~M5K8)d z4RLS{_AhTWNBz6_XevxS8pqo)GEUR}dMmYE6!Ze;{=kND7?(o{k7ciZ z^MqFOQM}_6r`xNgvpO%Ahqt4@?0|Trj~6lN-;YP$pR_w%{s1nKd0so(-~EB}fKX>Q z@D6I5Rrdw8MgYSl@o4^Jq<~CF;*nln%yO5m$w*w;s75~Bb%-JZgY0B{Su>4MsGs7kUje+Db^s5OIYc((OJ!lthdsLiw>hf)Z{RD-~ zL9DQ9nDOP*L-(#HbqkZ-f67Gq^t6dN2cttCq-v=?3vZ$VdXqp6#cwbiCiO7BK*B$A z7Eww7byb3Ir{U-eVVS}0qv_}h6|k=f8n=KpjEE^aV%yHBkjLMySa&EKr$(yFVku$= z^c;mun$-WAxRz5B(fSimJ7R4*GtinKjYg|<;$HLyFcLG zX_(?5sUAsd>A(oL7nP|iAGYxbWRX7?vO3O2P$xKiuZd7|#Zvm(RbdT}cr<(xpCVjK zm$QY%QajbP5tpR{LN%d5Z|PGW2a9vb!aJp5Pio}>(qe=f{_mkC)IP=UW)QD+0&ui& z?|VCpbYvOSFsM!sdw&vWK#0i1t;DfG?XQF5xx4$k6z_UgIvjNG1VLKAeQ&gz`T|?u z&>4j9WWg$vu@yM#Q3^B5ZkR)PJP+apX=NS ziUH;bz^KhN+8`zAsCl_62-~v$gk0q)|2vQsAg^pbpDK3e%KYPSEKG9s3DREjP6SBN z-*C#S+vZ7zoJoqJ56G2z7-Os9fy3eqbejRS<$oUiKg$5~Mk$&rqbW0qap7PKp>_(#wc%Ru?T3}s+` z4lyaESd+!>@(N6AYo84%TNi-)#E)7n%Tnq=uC^F`0=IPTjCBgNgoDH-c5S&?4S=Xy z9O4BF!9$tJ!sHv$j!A2vY?h{o=l@~BK*jo6Kl@WRd{exg=`cEN{;oO~H~EWlko|gF z{=Qoq-*190Bj&tzwk;wN_#WDQ_kjk*6oeb}!op-j9(;t=-%YXa<~$c))sYXh47_HW zI|1@3qhd{Ji)2Mn4`<3-v_4aaEAx8@4y_S3yex*vXjcy!v!AG&+u6|BY7<{0ZAtm$ z7$5HnL}XGzfDNt7932nc(XOy7xa zs!h!f(mES8AV#qIZ;dhF6UFAj~N6l4c>evYi2tch6c0yjNgdi?0aegpMS_($N+I=Kg>u5AhmJJu zVt=L$2^Gv|%v8{VM|t-L!MZ)jDkC8mP)jP1JVns<>eoAOU889pNx_ve=F;Grw^ARm zy);C(fvx8n)f79KnLmBj9TwEyX)nac!Ah7Q=D*|7{~aHP8pw+X>IdnT2I)bFM+}c# zL?G@uUWXM@pawEGpdE%Krwl_!Pmkd0RZZ1;xrgI>jlHj8*$HjfL$?dGsty7WMv+WR z&L#^Q-~> zX-U+Nlff49>sFP1IKjX&p&w|neAZ%$C!oVxyh$Ac?~lh%t$3!72TDUki{J(l~dpuBw z6}~FJ%zlq>ZYEkPu3Xm2a**7JhI7AE{Uy; zwRaQCStpNp9~uj$*PyNSKAZD@5G{#>eWFE1S)2r5WP-4o3FW z@VH;HbZSJD`i&o*iCE*5SS1$+>>NuO1uFUvDbZIBZS`%l`)sX+r@-a{WN=J0uKLsU z(`A<0isNNVe<^2qdLI%#M?Hc*gf8ibqQ+om(Lt`T{bb=HwA<6sOd%vy4P6B?p}(Um z!De2^2##PIw<}_`dmHlu*8J9e_b+1C_#waGkY0e|a>EP|5sT2CWZOAL=fj_dC#dry&*$yOsC8}yFYa~St$VN`haDwgoD#2B(LZGZ zdZqY}-Z5P?vPjorNfk_m&>lSFyMV|OSJ!fe;D%XY&o4MFJ;pC;elRvJfXjXwVQwys zN>PhJP$!MU8$nGA*h=)*R2)hzC3o@_Epz&Al9!p3eR?Yrg7+>NfHNWiYX~6?7lJx zIl&FXq=(u!1ni1MT7!d)eSk6A_dt(?OG1P=;Re(_%Sk`(>Txu6#;ajk$fldF087Ts ztBprP5|dUcb~zjoJ8}YnPL^H56Ldm?(xdv0N(`<8K6XVdW+cw%15W-4-_C6USU;hx zZ56T3HQ$xA*6=OPnM{7S`V>W!Dnym1HOuX!6>8{nwG}$?NZ-fj zcMv|vIxm;EE&9wYTfaqnOcAoNUX|hdhQ;P2G#ljzZ|&#A=sIjU;gR@pJ2{YIw(7l% zRKjiQ*+<5JeT`2AhGnC`-Em;sRAFQAMC8>h;x8jlG+5DJU>j_Wsmp2Xgw^XG^`{yA ziy9N#2BIygTdkuUx9gp>4>!G4p=c~`3*!MOp-a1$ND)~jOy(MRz~kWI0X$W- zh8zppkjcxYd*OGOJNsVF7d51?1v(K|CwC0hFQOX6B!00j7*H6^ z!YxD!J!ospn}R1Wp9Cw|n?0RzJ7XW6vYs>dbQ8=XnJTFL%F^0Si_KIA(B#$$`}r~T z?~mJ=`?|g4LqCxT;|Q1kaJI$meQ;ymyO&MxzW<(h&57}!i%XV_|kF@;#@WK9b zC*5uq_q`FTaM5JWO{KVCiZjhJrR?k8b zq1%Z+;sw%>pDJ*#iXo-uTj>yx6J6O|-Fj30l(iHodsKd%!YLA$g!!Xn??OOfwkr%D zs0vK>tH|W*((W`bm<1XHU#Q!va2o>(*FM$zd#yqL>D6Go0;PHzp6pcaF&udll{ZQw5M~{iz#Fs=lPzIiK35cR%$$rsOXL zYx=bWp0uNTH{B7$keZkgbv{o640#))0-m7tf%;v^b5Ai%r;LEYW}hb%@dsX1Xq*X5 zc!JO3D_n@KT#4obXX4O)VcU<=HL_FqyAa*aii9L7j`PU?U7*FGN`S#7C-}A1oUIV! z?MYk7tN2`im8M>r6BBK+CtGnrcv~nI5W$rIGSycv#td zy`^%2Jg%moBMyQog$|O^%~HG33{#Hqu?d4QAu&&{jNq@JA!?cGv~<4KSk`!zDYy{{ zfpHaf^>Z;66x9MQ;9g07Q$1L5#uDPZ=QZJ1xfH&gP zL?6=a50rH+6X|bNuK=2excC!mdD!O_zO3-iCwFpp?D><`eMdTbICoON)bwOQQD}#7 zzK)P%s!It>AVL4UxedfDlan>jl8u*t_4If?;HEMM`hlJTHS82mwz*Y}70 zt{ku(x)eUeVv*GRtTPDaCxkBT^R|-3!M`WQy zpou|TX?2ZPlpg~=kmGylF=z!hc9f166Lplik7odR1{P${yRL9ctGE&A2Y;&I2X_RB zd;H!7$%|6^?OC`!$KiM_p?f}F9z{L0jgUsoIxG}^C_KR~p;$+Weo6`ld|MBmZnH{YtJqSdu!X%TzMHCXR}qqshx z&g(kcWhjEyd~oNIbzeAie9dd#Vg3ewQ1=B?l~7Gf)s~qkB&bWdR__K*HvuWCq+)Aj zqBb1K0mf#sJdEHQQqW4vZKp67|5U0&(R*V1t*oI%!e_7U3#sOY*`#mHJJ38~3T;n7 zv!I3__$gI~|8y$gbta%?2w*cyrJx`hF`rtNF?9-!b%(T=t_;w!$PzUv z#~dL8lpov~+?$^v;ItNjO?xK(9z9hgNjmPjN_9OaEqe(iVM55#)!H#!U-eqiyJ`Y? z2BKW06Un5SxDfcS==Wjog79Ef~vc^E34*=;J5rU~1AU?C>-BF`0fGUZz+KF`$7H}Mx)m4%zb5a*e!`vdXmrOO05<>C?u2Zo(E48^d{@=C zn#N%hqIzL%P&Q&6kOF&H)VQ`LgRzQqplW5SB1$63)Wr8&S<>(M_!av%=6k-j(qTP$ zRS`!)G2%j|K^MO@tH~8TT9U45X&~k&|Ls!gk$)zUvzUDWTqUI#q~=L@`|XL!D0%U? znI>F*FNTO#rCDr$kLtVD(9e2tlra-AA8@Afh6cVnzSPR2h@b zUoTXBjKL1%(ccZDnQCG0u;O%+tm}z`?iAomy-eXFnAkkq4xwljbQ%%OeK@^!hlpOJ zA2 z6Lp(|-&w@(VkWwc^f{!;d++v|Q)&1C z+xY(-q)Oj=(#-*peQLjLaSq==PF1Ep)Y4)4qtYS+#;eY*GHK{2*$PKT zch`B5hY8rSa|H=VLLq#i$BmoA&e2aU4FZ;!($))j{{kwdjEGjl#tfNc2j+T zrcKD>qJF^S#9|X#D{nYwZMxilD;~it@PS_nEn%kYR0MA$8#OG{a!jNI^CLu)Pzo@7 z0#?H>-VnZZ#oU`@G~>N*Lbogar-F{t1hLKxi{U-~Daxcs9m=|E*NkN$V&(t(g%BPq zc}rR*Dl--y%^R26Ug?AB_5K^{90EhGpw_%|wZgt^O84c!Hpbi|ib7r`S}IWJFmc(2 z?0w*A)(1zZL0YoG4=EgGXt7r`)BeF;Y|+K3#O=M98b(|O$Bmi}3meHO_m&*)tXw5s zu3EEM?4=0a3d9zGc7B?ai634Z6Xp#DGnQ*|k7ru+P|2A)sTTg`oa{>(M6z||Qwl13SCN15Ip)Fq%gmA$+a94wk~5jo3dWCCvdK=%lNazAS%U$mhAqWgFhz8iX^(x25Enu<=1RZDm8@_@w}f{2hSdDX zV82*|(JU=}x;#}Tg@m?C@UqpTq}gQQhT=n!OfYAlMMk4Y)ueQ@sJ`)y5XA&n3UZls zID#3oH2AKMXYu5VB>kIFYXKn4#BUGuCxDCENwdd+dTpHc|075!<3{~_J{cssj22k` zJ;-@{qF{Jwp^Bzm0|yk?1vqvcfI#fmbr|b8>^S>MxPmMR7Ov0S!^#0>*hniE*00)h zf^ydh(_#&O@*0U6Si%i_lpcg7VLm~bN&`cl z&|}0BnoH`z5A+4n{ApnIjz9+BARiPV=lE;3`iy(6`8-wP20v)=3`w(K#oCEu;Ww9) zE9)OKWeEE(N-Q5B3)Fl)7$;dte|n6)isk^{zf)BPUJJ9in35MSb!gMr7)C4Wpy%Ie z3X6tY)?LdZ7dN2A{U}Ji6J8q zu2oTEG)$A07jCEmc!O? zCA+%6#?@dAp>?WAv&I(5+aTsl;rL^sO~4vIU%N@<0pezVh|Q=j2wk&UWO=w@h`E;n zEf;SWv<~TIuTqFBAXcO{&b4!}`Sana=W}QR-S2hdnK5VQ38Q$fjyEz>lm-n6u{4F) z430$xSypIqa2ba(WQsc!ED(JcpUN=tMQ!U7r@^G{3wn)s^DE{I?$Th7C-Cj-?nkcw zqxED@#e1!v#u!7S#$Fj~$mr(S_hCAT94;q{RnK9kx@8|99yAT1QDIguYGK`v!?$7$ zNBn`eD@We}FHP_sW1T!%o$I9Qbd0tjDJL*3T1neN3fAa+9{CVqm?K6mrNOt_ip3v_ zIejlPW%7pa!E^@_p)S=2?hWrUL(!(j_**t~7D}68a2700YK4Qg7Cz&;B>_CnJ6b&{6in$ zZV-A5Cco1}3LZFwARO(W@gPz{t*vt0=iBS`BTa3Tw0^BB1LkvtO0Ie!yYIU%K43xF z)k%GVu4tio9bPT%YK8cXeTHhhK84Rln2g4RhNChhDirPfda#Bf8u}>j+m4O*}Gv?Q~Cw&5AR z?56Uv@qxT9=|MjjcrnsTR%jmdidy?N-=DZzhU16qh`v#Q*XXAzOM#>fs65C@;;ouO zt8@&)^&zwMLr_NLecpp?&3|v%w21MivU{m=aHwT%bJ*JOM!M{Hdh7@W#d-DvTEj-z ztBJjeVRc*^vq*>%;H5+XksTUgF-9$6=}a~HoF5_4H!>9NoEgrxOJRPqhSDqg)eP!B=0&QT@-)je@oY52g;|b z&R3ah4JOc_)(+)N?mf{BnGn`IZIOasBI7(FCrgxJeRb91`iU)NN$>dwAHF6#@@M`+ z4m;8RmapME@|RzNE-M{HBX%aaqiSRxz%N|CfI4LkT*uX0ZlArG$f7{qCwNJ(xHz=LBuJu0F(=aGeW{d1GFkR2$%GXb> zlMhD?=+cLvpUJX)N%sI1eu4@0jDPuf&K3mF>Y^$6mo?L&*4V+RquCE}3~Z?Qh|D8V zY6ZI_O+HS+7zvz`*g$?D?z$Mh{dl&w=wt8be7T0&dV)gI#^q{dQ@`S&t!!Sts#-=> zEF!kb=9L%LwOl866veaaEd9aUc?ddv*%1gVDdGfV+}}=YzR_7u@H)>YB90_-ZarG< zqUWiA>o26`HQ!M|CxQ0{_?`bP|1{L^x&4)Y&^BU*X(?Cr@H?wpkYU+uu?Q;+?Imy< zkn0MU1!UBxfyINYFZMnV6}IE2v1xxb^XMAg4Ms$_gm1h!&X4KFU~GF~akJNm_$r0NyCzz7MbmGPY5==S_7zLi5YdN9T~MCQva0&geHO5T zw1&cH6+vbl0>!J_`Do?<=mz^(q=sc2l@j(;I#f=UlfhyJScJF2KJG?e3p*6dSw7FN zg*0e8a`9!3sDpYOzZU))ace6lm5YU&2(v31x^l{tS^98vH+@4;sC(ej|6lV5W@rXK z$T1-*Xm^mNao4)F2`Y#PHzBD%!sT#Yw#jUh){?5tDE4q`faEh5sY`iKC3;9SfWgXn z(|#|4%K!bY_`p9^oftl%IKwuY#OqpyeI~MQWnABgF4~C-BhfyR94>Ysrg#!0J|nRv zF1~2YJwRXj_J6BCP*(u;M{uC?Qu;Q*!t-3tD_~Zuo!ZbPVK&9JoaZI|!~!?ACGELmy@se8=|&>&bK*>Vsw{P%o6;4$nTo z;ze5R2-0??p#LJ|x{OMt7m(8{O9M%H!Xwyx8&Tt3Z|BYVl@c>=GZc2tv0=UcofB2W* ziMrjc$D1-8$1vnd1EuroR2M~&LFA=@eYo?D)o*c0`%4Ik>XSxMq)&_1?kejrh)+D$eK|9hvE4>X!|3j;C z{)L`k?E*0Wl0U)i1H1=|PBt8LaoQ7|a%Y}MYD0D;KIUkdP7vO%IHcJZ$!!Fdpqy`> z0QwYwdyK^y*a2{lCvdZR8hgm?=6$+BuaI*aV=Q9TF*gYH51<<2m03?w}u!*Jr&GIX&AVn@LaAD%JOXnuxJ>%6R)P(ay?A%|xU5rX1A0Ap?a0z_#F#4FH@XLpv zY-l=SHX~1LCy!~j3+jq%kpopsal>Epn|h{YX=-HHb~L}%rzrNJ`VXD#5&R!IS$z{; zaIytot{91iuWTxMg@kQhRIu*;opHC2pH%V0QUOtK(FQa zYxi^ldzHa&%0mIppBMnE1Ei(wK$j#UJsVJasy%sJfU_!&%N2B#00+6=+x1t-Wto*a zQCp6Bwqoa~ph9JlsVd@)1GLfnXWy`e;wd`IkU_r-wb?P4*x6caQJ?v2^ikQ zQc+XMq4N~S#!VN{MXt1gs(LC1S%Lifx=R1iIO(WVW0Cs4%SYx(AV)7PG-_4b^xBaG zhU)HdB9YQej@e*PSshANwKy7+qp8wJ84VvRN@+aA@yP!{_r${3DKTtN^qvo~lUVo1 zr4KaJ*gtP|!+vu0&+LDUl-z8gs`rMFRkaGzb?m~ zZVobCPhNj%{r-DGAu&O<{~-C<2$hjCeq z&xg^b6&WRy)|{U*RQrmfLus~Cvq+&=t23^yJrV%M&DR>#!Lj}3x^%sF(DOVq#TLmz z#E9D>1J}H}`l^KD@*2abx{A$Fxp^f&*e*Ei`!K#>}DZEC%( zPr@3uAgXG(1*4ekeSl}dHZZGyg-F7RF{JF8uf@i0*G+_L83JL?vmivrZWk^)8SF$G z*HIMOeZ3c$i}5dk9&YMU3IEq|vom}^3vq!ix6j~h1g}l2w3Cz9IcGxmXkNFS$Cs%D z&ePd|bv4+Y(Ju#3%>PBND=@c z922olYvs%8X7`g$E{N}&R)>J>-4CNHO+FgtNYG)c!MP9(zZhNIOs2-BM%Slbu!cgX zS0y6|ehgywWBYFv{R-Joo?IttGhuN#zpECR15$mdE>b3f%<-*|ljiZGESTNX-QH8v zqCa^yt~oG^dRGy5^s^}tfN7&8vKjWPR8nkX3;MvMx7sPeo>QLd{Rpw&0rdUwB;~AR z;?jdIDmn&n7g&b4WWTA*5Xnca7^MS(_+5al3|v;Wyn_U41|KE6sw9Bwoo~+mt?iG zj^%~wXr0X)Hbw-2P{Qy=^l8UGn-9a+doMy90s4ABV6tyr@5Sb#gr0Ba*bPIuYzhQ* z)NcZKT?k{2fS-{Kg}j0wQP$iL$DozN$BA-0n%iq5`(A8-9 z*g9!XTLyLfX&eklG^k8KW>|whDFZUY653t!mIi!}ARMz2WOG|Nv@Ac0qM|JIX*4+O zG!xAtTOF08)#hxC)ujU76mUEKtMI2Q)BMm=0&h~{)Jmo}8<`)ef2IEkFSQ^&UGUi(s=RG)zn3CQP0f7r_Q;wKKazmZLJ z$+vu#5=09;nH~ZCBmSO#hbwzPn?`tNDif$!F0zq@X(6)|biu|YkPS2{8G>fD!&=sP zQY-i|MDhgz*yoYi?)a5cS&^Eewqix$NHol2q&B!nbB~yV0*z%XkBTCiv>#1#iW&o$ zf~5%l!EPt|try!e%kN^pr z(i@6TanFM=5MWeak^d>9xu7@JvO3=sQzsB9W2k*Ez&w_{zU=94@yRDUWmjEDFoMn zvpbHjZ)wypD+6VTp{&Xa9opue(O`3tyEzC2dz_XxQ25qpYGXQj@Wrj|g zSTTd#{RJScnlk{G)Wahhx1dON%&{+@#hr@BrFy~=3)UYC`$VNKf2gjq)-nT{DhAJp zh%5lMu7w)9e%3IVH?S{*s}T(rXHlptn;W5@szejtrno~1!i|bj7^cZ$tZ*^rO7ai0 zDk|>>MUTs(1z6&3WBbb&DgL9cdfnOTQ=z@hkwm>Vmkfd4!585_jA$Q?6rBoqDYe%G z-eZ}`k&K~;)kyFTT-bc0rx201jqmz{K}`V!V8rAQ-ec|PG|bT)QnaJIS=csLFpBVR z5^vkt^9eN^7MgzGm2JBTv>?fPN{+G$rOhJ5c7-1gw>q}d0O?y>K+E#wN(wrst^44E_ZE!U+bair?G)6lspBiFXwJNmCur9KWh>Qlel zCg1&FH>F{EJfIQeO9;>ZV=&}CA^{>6jRUJ(T-hG}1b2UESyi3$`q|*#GRtb%qapT| z{-5(rM)+3=Pwu00uNXB*%uyQ+MH94B&seTvt&Y@8?)q56i&QMaRHbMhsm>?U;$o$S zYr(h{a`CYLy3qN@lnV&_Wy(jEZuGA!UFjHtqF9`$Qp0LMWQy8lb+gbyfuk(y*@{%= zBX2$S-@{Zr85{iH5f(mIei$tKPrSYbTbP%itB4pE&S$!YT&*`lMr*_>y*w6$WF62w z60BJt_rjjXMp!@@Ua7GW2)!mxg{QQOSyLsgZ>~|0FV)+W!@5f0Zf*bB`wp_Fc_fnr zHKt?PQ5=qR>+L%PDkYfS0rpm`bxn9iE~j^qow~-M7Qm7f!9(_266e?0B%jlne{I`fvn7oPx+cvu;D={+>vf zuP7EgE%|Vj$~=m=%P!9qP^l-}M_eg)+(#WDPTWW2JRSJA6$SryBSuVtiDv`P2X(oI z^xc*K8PwDH?jJcLFw6(@!#}%*SDV1o9qqC+EjKx&7?w!d&f|f;_bBy%+?({UHvD9E zWZJasjY@Dn57Dmd&BPt|iZV6u=UuYLEl5rDtl;lxyx^<<^#pp)o}C5%N}sJW_0nn} z=vzNMKhyJpY5Dl_LsUtsxGyO(EIu3`i)_9u)9y_ot0Nt(F`kyWtK$9gJ?@I(syfO<0x$UM-(TyVsM* zBA62hA_Ug>z{n1GM}1_Ll5FgieYJbfl|mv6e&0%py{)|?&)GZOK+l*<80>mpmGp9_ z+FQZ(6aG@3in^;!s`EwdEKy4qKQIl(Le7(zI=I@Iqg(6OfR!fLaf7{Y-4es~L+ajs1xl^GI<@k~dYi4HSWFhVgV->C z$wNs0%Z%(9b%C1h%U$kD>DLrB?X+$meON$zg|CN^)U}0gV^ay~l4`;AIfb~WYIYzG zs2{0Mv&1`T$=ftxR{yhaPy9E!p0nF}>IA~sjo-8h9O1W}0t8vmeoI}Xrqyj)zlc0< zd%Z@l&GF#^8uxxL$%fdB2C&K?A;qvn)0=i~r@yFiKebtedn8E6@Wb?Tkj!erj!c)P zF<*B6*=*6z=M<%*-M2{04NzUviG(seMg%-6t>?bE*b+bbY9K^nD}p!&SJ6Hkk*=r= zmLk&3zMD)Zg{ZX`GlBQbjrcbVbAjbkce&+kKJBlfv?BiLy@8uGH{NmGSQR{6c$<*FxAR9A+9s9iL_>DKFA&(| z3z+Py`s=Qia!6jv=hu=o!Ya?Q&{%JF3*OKygpBCp*+ED!rViCEX2w1R#8(#B+huT= zjv;TPFRU%$(3O!L=^LwNk7X{cnCW4Fs*>puN*?hR-;}G|K}JHWarGfmi3p)%eXBk2 zsvwNZ(k*A*rEGql3OcU_>D$|?;%X$s2wk;#?i$zPkOL0Cs_jn2YUdoLvo0Ow6I;*v z$AfIIeEx^9nbK2TT;7LX7UQG0Bh2<9%YHtl>Fg(wAH5Bv{DFPCE-kJ zdZapHDPX2sCFuh{;abnGDVT4Xdk&QO1_ACcFY&bHuP|+-2m^Pw6*=Mi9n`A=IsRhh zOXPXJ;2JBApIBtmq+YNy*%*d>HPPo(eM z!PD-bga3oFZwjoeTe|I79jjy8>?9rANyqBgM#r{o8y)S~wry+2>e#vaJLkVR|Gh8w zWxvh6)~p&eX3aIntXd}jgViX1;U2@Yg3y_suknpN95p`N%TZM(46Yw90ke*)?xF0g zVty&NkSBPhG|6aFpNG^(fPQjqZf=N9KOWw@{$8Pq=y;av(pteoj!e^_<+js zX<;qNX%GE3DqOQCypmj%66esfud9yoqf6*2-P_%eQZIsrVbQd+j}teQ2TtVcxFi`v zDkIx`<`fEN4C%=&l}pkqlevPhE7*#@X z(ieNj($IS+WNbBdf$EVfXRIhMsV@hCNlw@BB}79m_@A-VcODVvm2CFE?wtE*o{m1d z+{=hmVjoQb3Hb`0LeR54COLSQba>-uQ|-vsGMo(NBJk|?4vi|cvvAyBPGUFYu0~>h zfL)CsDf4$bWDkA_IM~p-y}9Z9x&8+0~7xZH5#D!ngC;&=o>qk7n(*geNxu=m(h_>#^!Q|-3Uf-KX(!!3Xw(wleK{g!wP%zCoV~+1wDBL3-PD(49MFt<@q`eFBd@ci6Yxt%8k8L6 z7!C$jBd}@Y(Wu-wv;CcN(%X|bpWTB5d=+&nUKU`?b|!oz8f})i5n@VqZFCx<)pkb1 zaO4?~ttj!uyOe2?Cct*Fe$b6~@@FHJR}G&)3%p4?miN$7c(1;@yf%IG?pSJurzlgs zUmz*KHt%7tOvm3YHPUJ&jDvx$V1p-(;}QSZ;iDV-Sxvf2J!ZU~#2NFmcJ4lkl+CwJ z8mbxNhBagDS)y!VE&AYt9Dendmji?gM42Uu(+2-Vh-?R|31d39<+)t{-;jw4G~{lO z=DyZG8p3|JiL^?mN#)Iqu{559ng(R~4nIpHkbs zv6OocJt3C7^LEz{xc+^sC7Rk`1xF$M-qk`(XPy%ol}^;_!*1tH$=gRU+^8nN+?f=yx@b1igXG<;%85 zk!prLn7h)s#e|v{>24I;A=u^s+V67uGTHbf=}I85zR`j5l8XL2p$ zs(9lJY2vpV{(HpWNvNW$Wm=Cy_j}@Qxq(1G<@Z&)ZNM#v?deA+-fIMvb-rslSt^$IdYG=rqenuw!qxy`JE!ot^m5f& zaKmh)%3hGpFHEN&fe^C-%daB9ygv3=dCd3gBI?h7{tbTKCuiGzr`_#i1tJy;1uYb@ zmNVhy9gm@DwiIfhj4K6G4?W1un#lH?qt+4)VppSb+34AV(2Z*X;xo)l06@gKksWA7 zMt-ybA>S5OL~TN$!1sFH+)YQeS;XOFd{Px-IkJMTsk#xwwCAn{%dagolWuWHx`J1R zjJF_cE`_BX+u#PCi5-AhG&rtpBT7rAGN!VO+{fd;NtF_y7qB*U`)YV?p2ygbrFX+A zR3NNG_h*VYPmLn-m(lz}s%xI^jFSO7VwdOmv8vQ{8Lk)JXlz}dLOBfbGSu!6mq1)l zltPqL;o=&%g-8S|q6`TegD>$G?5Sh;P7w|ZhcD6;<+k_xJMM%F+V;wB6_aINnCns? zZP0OTjV0$5w>pZ6F|EE!*8Ac7AUa4MR6nO=8Uet%_38T!ovpw&5L*G?EqrGiPPalo z+VIj7!E5Agb%8w9?04S-rr>XXO8s>8R~wlq`)5mpidSYTD&OCM=D|}oxxZv|{eYhY zJrACG_zCNdaZv*dk2xHcO~3=N0!*3Sx};>bI^MHrcm`VB3YDOzprl(S#ZA0@JR093 zHXl>>CkPFRnvW&?Z3?5y&A$+mzHxj$hS5(HAepbvZrl~=Yp0m53_8c;e5ERNRgMhS zC6-Lo*Fz&;xE>{TtQ^uOq=(=8EBC=YB9d%kJ*4_EqUA_+RjXhs zAP2@W4r)rD*-Uamd(CrU>XfiSnaNTu4_DGcbA!{f3!qWYF9$OUp$X=oDgOOFDr#OG zC!IAEr!%gkDeRzSIRXelD49NlQ+XDqBC}t?)cC6xBmk30i6YWu^U-7HCngP*ML*0? zEr7OCv-GRM=chGKDrsdF+7)^fgM7sVuZJWrkyO>=s3260wj+D~sr&rXd4D;0KWc^x zF>^6WTnIOgII|B;1a}9#4gy9#CA=F=Pj zawt5>As*{oGyug?Vr;qxtr7rb*)d1k_>{N;DZe}Yv>6`}`;Yc}zT@V$eAsSmSV98Y zR#Wr+UKat;-8rH{&TaOQ7W z&*>Bg3YH_P`;hJ#&qjk2og&r}djg$d$ zFEU{4-54?hnLtC#n@NhIH0y9h<1gcr(?vBsE#tI$>xrUQQU1Ov5n&rEyD5~zHA~IIQyL=vtP=%@)6|TMfNV(z(l!Lq;MWhrTJ>uDddw2kRf9O+9 zp42a!d?G?o;ffm#mEm8B^kaC-i=(#FQ_6sQcIzClj*J{#UD`+PKq8il$1wpC9%5;M zyD_*9HLyRaMAd0%XAztvjl&}tDU{_~(#)=QrtDfq(R3(`-NAJBoiWGZ>Rk+KxhKgW zd6iH?*73h|!Q0Yar~guU>poM|uu1ynseiyOx%_W0BWS#Kg0#I7v+wmF(4H%lI6brq z7GZg@&K0TB7saUV&()Lc*NTN4gg7=TTFRh2&f+B@Lvo~~>cMpSIg5J<%+Pg%JAYZd z>bS8n_B~IIZW0 zKs|-4Pc^m0ih*$(#wy=NRV3T)cP7DqV_fWRF3e1mZL*!Gn5s1p9*hH+jGJ zb>*WF5;y(Gq(*8rH-yqOJZI!Wc$!7OwwY-6##hg!(r^Kpo8j07U9-i;f2qOUfnEvf zQ>mb6hE~<$sX!VT;oiTKKX7I&yusotMAWIwdcoz3fjv=yepFL3@OZ9b?YbLlj(-}W zyOJc9(e@5V=QhOj^=fSn-tHnx>jK3G}r;QyuURTO2i&oJsBQN$2}J z_Rnena^k-P!ksrTWt^VCw}pS{emnmy?H2^Rp;lh79&XVI_}#&{13|)fPoR2UOu?%e zzzc8ns`G|@b^APMCV&y}rvXQedauc(oW~4j%M}Wq13Fk=PMK#e@A44?+ox6T8R}nb zuL}}eLyY(w{Uhx+0^t8tn%I7xI>0LgL!*tQS1X#Z4T(+87g5K&=s$`KS4@k>fFD0R zi{hE0`-kOX|55gn0X7a{2O8ap6ybV@Yor#NR(#lPCS-;L1V*dNsovWdJaj5$OL+YU`SXUYsPt!#x$+yddbJfyfgf8-RQj& z|Nrv$2|0lGmj{q8JOl^RwNr~+afOuuQr4oy!b(@tI1dauh7c-O8fT$2iOU27ZmQy9 zYOeU-gztU;51uqOluh;JK13t%F1nr=vKHAx$Vb#7S|~1o54jq?*JdV>u3J9)7G#Aq zkP~uI2vCZNJb)v7SSipJ91r;}vnPm1G|C87f!d(D`JYCSD^WX;vAOa{)*TJPr0|w7sk-ORk}dn47+yz~PaPRl3-C z@iJ;b2zN_)TBjt+owyoO0~Xpj9*m7lIaC#@K3e}X{GUD%gO66uAba^cZ_#c0xA~pt zcH9^l`#y|OB`k=RDcTbFTPEJi%|SNwVi=S7g9l?AH%p`37kwhzo*{1 z8Kh&1m#`6OE6T^hbL1p#gvP_fw3va{;G2q=-is636xTvoF1l}w0hPi)gxv1oQMe%} z+ZWvqe0kNU7Cvp_WTiRf6TLhpE3TG{PB4IrhEZx)Nkx^j(Ws!g3po5ek+enV%Ydx= z%#xr7Ois=0xTzCRx6M)txExj!A)BLtq3ZV$#xN{|VyXI3uPj=Ka#TY|iDr^P^8@S3 zMp>~5G!V`AdQ61$*hXUMkNYz(O*pxiL$lVNG?)fFY0dY)=JWBtF(S}uvr!o3uhPA8 z)j!bZ-2rdd1qgL_h3bR|XBn$Tg@*0J`H!}$8gfH}mT z3|R#{4y#)ZOMpK5uUw1&n~y+8XLfi{p$)6SgcMOAi1crywHNRFFR1yq@{&q zPJH7*=2_i*&{IRB3@dYgrN1e74VoYMwm*;j9bZ{DL}DPQw`=U{P~kpozdV@ zBSnlpV})rnG45%Y9@?)*TZf%HelJhJ+qY4`&Db*~Agfu|ec-XNiGI@Ams9effiMht zaRuJwxa1Ej+4bbAl7yf#+*jQynz0v;Fjl+H8zb_M-_`gH_$eIufsto6z!*V4;;0L` z{G$cBq(qa22{XVO_?+HBvYmeR;~1#IWWlQ)XmYCpoPOOA=N*Z-hu>b$f=PEPIW9)?C&`emC#a*(?U0hU>v2=>G`H5Jo;m=>)_dKrj&z z*V1cVq>V3N_M}0*_tJTYh*5kMzn`*L4%lRv`@5 z#u!(5$y=?YSqu|5SjszOZ=ft8g+LS&*}_f;Rg>aaPu`r{br;*YC!f zso#U-b1bmPZ>pb|DepC9SeYyu-7EtGh|F1Uslb=JY}O2Rz+pj zDN?+&^7+D&)>QrT%CDfw?|Te4-jaoTRR30{fVu||Wc2^Sgah8PJ)D<;uEl7Bq@8g$le-2mAF@;6v3(R6aDh0z1A zM>fk>@jiU8Zrpp{rg(7snJiyQz!y3>G6{SU(aay>d#QfMk*fR+Wut9^!5-qSC~H}N z=$>qqzHZi)YD|DX-{@<_=2sy+sLA--r0S~eB9nY_Y>df(*!jo9Yv>T86la5Ho3iN_xqQyC^aj5VHv(x=y6;$_1` zr)4ndug(otr(t4ZzQzfXrjz;r)u|_{LWLp{a+=c9F0Jv@r7HzVb>?SQ&o}J6+t%k< z{N`iKZVDO0?6{IBjIa=+3DzrOzA74&CV|C;XfML9FV+%Tgj%G|`$yyYc6^(;fj^Y>)Xr%}dx-w$Dyp@05 zP6lSxwcqg9?S2n7w^Z-EdgnZ$m(RBW>&bj_t{%Vb;i(M2UlWvMrhTj<3Jl&drMiL- zQAdYr4ghvF!bv9C(9|+=Lh6efbaV78)sj&>q>2S2qjhemKamzOHQ)K^yh2ZSrv-3! zOWi)s1CjqUVwX|(fSGuVsR%={zQyK2lchT)Df(APw4DM1Xv*jq|fcSz*kfp_Jf@L0jc&`w0BOKGTx1HbSw+@=zb7%kW zjD1g8Uj-8}T3Etq6wDJGaMsszbXY1kL@7ZwjXm}@b_=#CcAHJqP=3scWj)K*yB+`B zy+=7hx3&=o1#M(}o|@1-8;{)n+ljLUF7lt{WW-!6)*|A1PAbp_+Xnl^y5ghxG9e)z zn!o0kAOr@tkqNoJKuUOzl*b9jO@O_VXx@Air3T1Mro#7yAhFO&C}!*ley6}ETX^pF z{|%MMblc+##*>>##CIKE`?fT@M)vxgfo*Vn|D!ElW!d{K=Bq~SEEx~lIs15YV1eUe zT}jX3GTq%Egg|mW;I7BDhH-`%+hYeg@55u~XOz&rigboar$nIG*;%$TlCGkVN9sKc z!U#beP$brTYeX9le|u{=uFGTRXvL=xrfbj{YWwQ8Cs#3hi6NKo`qry^7-Bn*=h7ck zj%DC(oA8My$M>NJrhvl=iLA~+-jZxdQPFO|N&ik&jpBEMrp+Nz_L^|j&JUj)sK1_@ za+}Bgc8Ua#J+5g}w{M9sJ`qPmrcp8pYN1R1ci|hq#0f{PoD|DDJ=1#B4arq3?XpL3 z%M>s+1k7EUlg* zT?OkArD)z=?B_T0+}9#+U84}w*zP;-0%~40`9cX`xDZm2ts)B5W`V!L%Y>PerC?R% zt%@SdBo-C$Z+Ny~vOdAbEk1m%dm?{`PK_upK~5!9v5!R1A5%^)TM0kanEUJ8oXTfA z#Tb^bB~&Ne+7bWiJs9V`*7KV>I+Q@(u<(#+B>$sAYN%hhua3COnpPKhX+DP{OwJ!0 zM;9-Jp)E%h`k|(B1UTwJHaVu_yC$eaU>^wveOxZ9uOGO5blMsIzr3tB5F;cV7@gX~S}Po{Kd1ux=5Y z$79?;y{CvAR>LVrA?NsbA`Nhz``Qu~CLgZsmwFmk2(HB6pW2oX<&e(bq8;_fg@-c0 z0`f(^7v+tFncEszw_9jQy%GjRi0WvJ3s0W?J# zH6)|pJZVeP9+UgoAiQ@I@!H38^+q`l8;G>eyG8;##QUzm=HcO2_8A!7Q)DLFLp^QWx%b|w6#BF%#MXkQhx=TgGeEbWo?0G zw`SuMM37*8d}@^WDIMOGeTHkQ(gq%*B*h25j6KR9G$Q(oyPbGU%8Tb?Y-- zF)S=TA!jk)y2c?s!;g3YxxClH#Vc)?^_8ThV86`8S+pUz*pj$#|4QNbmyg!DT&P8^ z9J}v@qHW11A2AWSjndpVg^-n7z~{UiSgZUID}|+0V6JH1T}9y35&bHGUmrHLC(cB7 z1-%Hhv6aU&bwyAzkH2m7vhMAn9BiqLZ9a^fzr@3#Pde(%QRJsw;$B^~XUENij^#=6 zGegJG{SVV~FNmgmle8fKp$#T1BIBx-I}aiQsN zj^)%g$CE!CUp*B;jP7LJJqxkD*A{T~=)R*+CV!SPP59*AwY~p8iQ3li#SZxmW4b#F zLV^*OL(s<)pH~{0jeKg&3f;t1;*)h|d4*>SU8p1{f7nCDyf)%?+#&`~Mcw%Rl^2vc z-12@NfY!_BP)+K*dD$piuwoaJd-flN$gWd3*=-niYQ)o(0gm|Mx#l8^Yve`FO%FHV z8eLNm{|5uavSW6S-A~sigaAp|evVOARqs>xV!Zgx`dK2(zh;Cj$!ODIPL+o6NrfYY524cZD zP*`?<$)28^zU|2`(u8+mdaUc}+DC@$N6F#vljJj0$p002+%j8aev&}Oxr=+UHhdQ6 z{kKQqzY+fDNX!(<^E&-7C#+l}5DCc8N>?fybDH8&E_vD{pQS`JU~mwG!GlqJR7^#p z_x}M50nZ%@QrRm&Wcsva)v0s!Dq^#58` zKxv`-&Od3PKQ^MilB&sF(p=-jM7>pcgZy;fF{dsS05aL5Ku_#w5aW8+qqjlJn>#_d z`nCtiiv0GO)?PsILrLdZ#_x+%ZlECVW@+c^XYHS@+AGBNv6!-X)WM0Ce*R6iWQcG{ z6S%*0Igjq%NB-)TPoDm*CeMnejq}Gl74}z#P|D_Mb5JI>g$&lVI#4vPbID^hp*e|f zgAlnZV(ykqllYP581aV#gnXeW$@slqHl?B{j65=Qs#emO_2D72*EVHHI}cFh%g^4y zCpIy9MlbGv$e6Zt`T&gv+=-_gNGfwtk&^l<{9JxSgj%A92Q` zVLq_B6+l2DM%H2EvuCqTJTQ^nTDdEAJ1s0l_3m+kqf>^vZLTsJ1NA(1wQiDIh{rq+ zRrPc{@$Vko7I51^$bHD(W0cJ_Evhoiw}MI^0^N&sN(|&z)!{L~uDv`gy!U^z;m>6pJ@eXEq~oN<}O}8K>xmOG>H?WTZuxIua)wKf~Qa zQoO$&GZ8*%qrOOjPJoxda1R8L-=G)TI~5NAgioH<0<#d^10ab32$xriomJW(S9br` zaWlYkM?Fp6@Z}0LocFUH#wjieGd7D+!j!Z=y1#LtOqX(>M(%13BgMS za3T0$1C+kfK^TZ6%1BFxf%&@{O9dvr>*l9d7-W1J^2Ls8s95PPgeJ&eCYRq55Di}g z0uBIHXH)7&&bmcR-D!l0PW<(Hc?1LTkNvm(JeDDryB~$! zqc1?tNo|SQd37gzA}DWm9@q28@0j|xzTm$*Jf~m^FUdB*09B#MEm}7LyHsdUrLm>e zK+T(U6ddI%>0z}TY~77ULGH1?UY^G$M0ejE|1@Z!=pMZFMAm5tey@h*|`-Ow1dsUF%= zgy%kC9Q4MOR>n%1+QMZ_4tm)O8-y+*ZGCr~!vL1|s7)TeMO~Lb$DlRLu|%sr52Bnv z9i7?>=PmA98!AzmKVl&hpjLG*U*7y_w(mtxu$*htI)zs30>_N#3K9|N0sQMFvxffV z)T~C98|9`4(|6WefL3 z8?CpL#`cd}+7{?kJ^X|!(_u3th#12^?nib@4FZP0PJ(FiCASS zGuv-KEsHEK0{cy=ad+ftmBcY)^e-2=%DDBaQt)aL|2Sa>TJ{$hgPS-`SzISJ8nj@! zB;wXCr;)h`u9tj^9x=I`UgmycNq8bv)ddDb-j)Euxh8vEPV%+*$`OhocWkm%!_?Wa`TVAIZq{Tx)r(zb~Cmhk`_e z?Z{=`%afrR19A1ewzD)V8g``7O9IW|()jEt@*mlfE9xIDBj1M*Sc5k z7X5J&Ui;cf$k7zG>7G)zx8#Yo6=ck_60(i^P$c@T;pxV^MxNA@FaG>qv~Jm|&Zw{B zG9SG*K}N*5G`lEZiQ7beRo$%WYu2KXc@1sHVpLDWcH=uqnM>&^>JT;_F}bL#6TR?3 zr3sHI1}r^zxmiMIw&a5g>FRo;DS&Wu3I6FoP=a-d zcBqgniE@5c+abjbJAd@(K`BDxP^pwEYOgf@{gOx6pD=ex4bTcOcKA_uZ?1>8pV^%ti_-rP;fu8e78QOC_><&}1uZGsUmLNJ6AUGAkIbHOggZC<7g5jccs9&bx(-arOmoH2G z0AO*HO%NwmGtN7yiB67kHzQBR{6K(~65_O45lC7ioluRQ!XQRx4WF~hbgBjbaWE}@ z&MQ8wI26Yp6#zxL|H{G~ib5QUegfBgdWm-(7H%|1TNlbcw{Ro9=?KLe9 zCHleuFh`Vj$(tHJdhCWK{QZ$dX&krs?;*|S@)uS*6qRpefS9rv)Hjb%yhezW_x?rK z5};$jzGK0z<3+QETpJ~TWmvj_(#6+LL{i7XmfV|{asXjTh-eM{z+a4J_p+YSxb!1G z(Pw$Ob*WZss4OfNPSpfSvBICH^{5kN5pJ#6GDwSD8FBKCUYF}>x^qJ-4%UT>=l*{bOu zKgyJ;eUwyRD2j41w%dg)%^sM3#$lB*CTx&Q)~iYVxV%*fl~s$HD(B{*^NexVhCRv^ zYD3r`v5uFJxAknm*rdby8JmJ?5-~Z%9|0JI7;uSJf5WjDu&qw%t$R^S*307wJAi?{ zDU`?kW%QEn9l#gz-h~d=^tR`IW;#ki0xVREUc^&ggHVptICUbq6ruec{+NKQo&MhQ z+tXvArVGna&q?$*c}Dr{Xh5YlJEP_=%Ti2<=mMltdYP;;xj3(h*5!T?XHb%{_Z&X^ zHel~VFdeQ!^)al99zd03FNAAJo~-;!@+i)rPP$6xT0#M8LwAu{LwLOYdveUSUew%TpeJ z-<==G-@2>(w#u4+qE z>Ra2ingt1l_RI40SH{lE5TQ(NbM|GIvp&4qM%hcnLD{fI4)2lM_Hr!a?sB!#)dKsW zNMfk15%EIGZ`$FWtB}G5rszEmy^O{bSleUXry{Yp;Q#rIRmDBb(`KwQO=v12dG;@u9cp=teR)fiE4P~iZgQe}?(kOV%pt|W9bVtpy z&;ADI{mbi8stlkF)9$mJs*FrB9jTFUS&+R&-V3u=+J1_n1^d3SRzC)|R{-2pLnI}` zL@lCMnKsDn%o0D<8NDS)s;6RVvg1jaF4-=MXXM4$sw|%(+f`t3p+|{llvkfcx`CDD z{|^14@)XdP<=u&aB2y5*vOHNmaAR??eq2c?W|`R`s|HPa@Jig^LZ=;rdQXSnd)LjZ zdFS~jaV5v?P(&ZGK64zLQ8tO^3WD%p#oUgY`;Y!dp_>_H8^zPvuRHC6+5I;VlPM6L zDOMH5!Z$-F^#o#?&cDNgF_-po^pdv}2PJRH(1j@uZl*FH@B@j_(d=+@DLh@}BdfS& zeq~8zQ(1gD*3MS4LeSDV)3C5>I-qEq_y)7DGhn%Rmp|=ZH0zi*?U*;|cu`k&$5Ua# z0Z7Cq?~|pemMnJwSX(5*7})P}9M@-0!jluc2qxClN|jl7Xpi8-Vs0Q9$jn^W%<$&{U8u``G)!Sh^;&wQp5_6a!Q{P6_q)0oQ&aq zGscnbzR)dVa8F?Nyq5u8{#@U2E9nUobOj1J0oSy_GAB5PU$LeV#tU z;9aX}VIKwYOV2!oUo_1h)z-~cH?tc9vc4DHS6VIpD%6>%TqMtfPY6u$q9PxukO^Rp z?``L1N2sdi8}4k`hWghWD)Emibk=E$+Kq#bilJ_YxaEhZIq(##zHtR`&FOI8q6`+rF#O>su>vPv8#4lffkCYe>uy% zo|bMUm4Si^KtUPc+E4eRoEu-_O#*bo0SlqaAMw1nRFy5Yd$edmea!4=kUijYS|n8i zs5jaSPu0a-mje8B`rKzpGgo=?`A<@2L5w7wo`|y``^m#DPX5}P+T%e@pBK%GfqzU% zCJ0=7xy&#PG4JD44!_V*=Du-_tW4~I&Oc= z0T_-igrZ}|qD~BV-E6iY{t2p?l^m!M6977nB!tclO9%tus< zVztE-jvlp-8DKsa@4PCv&m*|sg14{CH(k+=+_23ay3y?RdcC_J&mCfohnTDr#@n!N zAG5R^b+whl)xhE^QNtb!Tymb$E#w2YBk7NkuDV?s{ifIT{&M#8=IiStmnOJ5>p|6j z$Qz1?Etg=__+8zgs7%L#R6?XJPoYjITVYEZW3Q)!u@%a!U(o z6ZV2it65bDs1E_P>xgpry}VXeLwkk;MZgBnLz_-p-M8j~8`p3z{HqJvW{2#7xVZr1 zoRxk31J6KEDh)3*B6%H7x+DP_o^6fQRJ$5V*`Jj@c#}CXhO4CEs&0mKM0qkz~$M$Dr~HWi)Es?#18=I4ju(%7bj zoBpfY+&10wrN}VN@&?>!%R+m78Bew@des73?MbLw#QfBqOnBO~Z14~1$O8Sf@6)F( zs2N1y9RY{IUjY8xBt59i*pN^6`>9M#)vt*$zGtb}$m(YeMGlX())sOj@#rzb58(?f zP5DAzH8^S1<=~UGi$hYH3as*N8yO~BkQ1?gyT3dHp2Q|u3uJ=kRjWdwRWtCbgsUF~ z(%AsdtIPGPE44T!%$(XhLHAz5Bln)DhFyui~Xk>qvyV#?%Ami89ai(tHj~B2h=-^2N*J@8k zga>g$u%acWeYmTxYc}ZvQL(@Gi0z0su$Vsn=Nx}0NQQpd`UL*P((#dfGt&`Rai69> z!_rP@Zsd>F_D>zi7AN;|7EM!{A+*_GEiEWRGOJ70aW>h+-@a|=c)C$9`)G3W^w?Gj zh5;I$m94{DO@7(NnV;&UuWOBdcxog`w-uVx5xa$S$(-=PE(hce4=Z39;$zhUYM*Q0 zmRCBA|H6!9G4G(HBXoa8eGOmwxW0?kCBOZ#ic@RqFD3_Eq*}GD3#iWucBJF{BZN=@ z4jVD8qez864osRgFFz(9nmd!+lj3HcY2n)Ou|BUgZULL4{^5 zC1`N9`^R_%1G9FFRn}9}2%2z7M`O<1!CL5D-w0BCwcR!V-OEh>lKPq;4FTNi^h=aahEpX@8s@Ek zeOqp-kCsDJq7GU(Kd{Zwe?!Bde;$&p9&QuO-=~V2SOgm>t zA8nQM>QF`XJU5H2hkI<5zuyV3-pG*>bS}$0UtDgsN*bf$*}wtgyuMr zmD83h9pm3nrOE0F>8$M?#>Mo2g*4p^pI-Wtcam@D0Sn#BeA0BXo+-;Ml(DTwC3bU2!J8iBo82)y~Db$y8LS7eroxvk&Q=O}!85AYK1sKo4 zCXUkdVrWZ;!P!DZxP?;1#JqB@xv3@x0wgB~Sv#MzBV6%jUWdhW2h4nhYJ67q`XSe7_i5No zRv=D3pzifcu0qON*i~<~tib+{D>KJPJz!1$36G$9??L7ID5f0#J#RL+ zm)FreH*YDV`z937kMO8dQ2_$++l(K0yewA7Ziz0>DMktW#z=*mEt+=Ouw=7kI?oPX zBj?@87x*44POk3Kn^UWGrQ8Uk8H}q`~-G%ZG44en_ z=~)yukaSt#jv*_a7%RKt-{J85f|MZbRVQm2Yd2U-p#H#^n;vr`}$wWsH@f_ag9z{)DQiRXl!VukVQE`IBQud4U?s^Xw~;guzRLk`RJ@Ra=Xr|8O+T z@n%s+fvv#W{%cZ`!VdSCH*dt+(N5RZ+j^%;hJ6u%s%d?70qH;eDsUEA$AE+hRf`A+ zz}ii#BWtn-2>c1{`%I#q>`3HTvtSwE?$=y8U9JWE>b%FaW?mZgVC*hp6n@UK%-OdAx-gmO2Z(z!U9fN^ZZ7+%Tw&Y(^n5+5e9?k&|Q(Oo;hky6QTqdMAfVOhep zpVWsR<=8e!x)4cm{b<-;^Yg8j_qvQEP6W{(i34&Btd-tY{IHItpQ`|VU)rIlwe7-P z*r3iZXJq{wuZ|X^rX3B})XJ&0HWm_#d+jYcB1tdVPLRrO){>IxpR&6$2_%!km360+ z7>D)wZE7&}3eMoXf+kO`yPK{V9nB79#9d5gfvyixk+O=FIZa53m2QU2Q}4y4p24Mr z1B)uOw#TVr(1&DgAPWSkIc30dC-w>^;_fWrc4LS=!^s=?w=lYupdq zOO#vo-E|e&sKU_IjqqPG(W5W~iCP6X-4;gQv=_iCuJA)KRLP4y z8RJh}j)B=*iyLn)rX=;>i?4@-2Z@O$Z}VcEGU@z{2+12^*Eh$h_9oYmKla?`d8|`+ zQY)rtg76HcZoS%o3D(8ib!wjty0XUN6+8-qfH~f{-hs`;X2du0jDfnY;Z%StP4XyD zNIhrd%A)L)+vBBgtc1f3-;NG@t^Px-D@u{s^P8#32xRwvpdlKHE6l6gMVL%cr5XrL zZpw1SO{-&@79LmS47VgMPBL1feVB5{NPQosCU$=xb968~rNADPZX^1h)~4Yc5yBGu zWx{&2Az%}&(yKAynuf;(;Hm1b9Ei;}3-r!!t#d2I?W5E8@p>0SG>B*SYE)^RAP}Lp zFCMvZHj56-&ERomz;KrcP)=vt`{AFAiJ?L_u8mE`3(;Oc!n?NLzJwC<4{6|A!D9D3 zyCIY4E}{@l!%yS(k?^Z`Tvw3j2p>`C@hqdfUH9dN*!xXIhu8;Al93^?2f_T~Z%Mzx zR_tGq*Fb9$b)l0uMYq2xr4CzBKVqtO?z9kVM5b_B^Zo~A?-X5G6Lk%DY;NvD2~9vDvY0r@xcudEW8=;~n44ce5|nm^Ig2Rkc^0vv=)Pz+*4E1$i`- z`f5JgA`vREf3~d;&1-4`00u$S!x!n$CpM&q>}e7q!bI5Fws28a4Qc8^=E24jCA-_F zuPcbffI-UY`knnv2xa;`c7;@Xf%V0~R z8(QMG5dRHzEienju?KSmF7rlH&*9V&WiOET(zK4E99o$;U1*{0!#c&nk~CVJnlG67 zb?tIL|C0gia!eR-c+kiSOOA^-Y(&Qiv#Zh zvi?7dgB7&YDX-5-C2x#2)^90GWw_x!irqI$eN2~O2d_|ed{kIT*#Jg`>c>Yn1xo0 z^&-nm!sV^Uuf4##{r@Eeq*ZZT)VY8_$kcV30D@0rX;X1*5zx15NMbR_>at;&e}@~& zTFLHBa&{w4w?(4(u?LfWE)FHcpNj)~Ft)3i6>Q6|@+dl(3^#c$LRcn`*6s|4mbMEU z#Fi8FLBW}9UQ6Foj(!ut|Vx~$P-|x`Wp_bLlkgznf z92$J-Q=+#7Q3~3>tp)LHV2jS7BLpCC{hnQRs`VVuv+bT|qeo&krBxYZ1!yFar%+AD=0{`RMPz~rus9qMr!wLqQ3PT|d2{ZWzI85SNk#D zhrVsLIV7xf9P#CkzFg-+?!%+Pz4nQ*DquFu!2NH1C$s-7`gE%uu+cc)V|&v$s8ukKI;SJKbI2TvmfUc(|djA=Dv!3Z3!I z3OaS#b2N359bB;Es+1Tn&$*Bo&**j}d)0t6vm zq?FOTf2)?&9OMl;9?OI>=$AuYUX%aZ^Z;MMeUwrie95jf)3 zExPh0Wy7Hlkrw4%e^pR$`bkXoKUrhP8#=?0TN$V8Q3+hgbP(MB*UAtLq=x|!ILjhi zJMn0Pe3KrYv`**k^WxK;nqUwh)om2xBoX7yD^L%$FbmLejoSZR$qHbGSGV2ox%fv? zynIe+Y!7%KO2_4R4C3_XFNj}+xy2=7WiQ~6;2Kl;;$#lGM%s>{0b(d&SnTJWCS`O~ zDApPd!Y8Y)i@dHgq&E7k4$Bgli$@YXp=*JoCVFa6*qv=PSiW z;-c@ND`VT1F#du4h&`WahrT*i#!Y!(U-(9z-swc&PswMDRoaqaL|Ad^b|h(L>Yf3&wSPZ5hr53*|hV73wxA#k*~76Z6);6ueznqa&3o z;-+&l8f_p(Qor0#hKsSB8uxr!7uA7XuPquv%T_Z?DDSjeL`eJegT>dsu;=-Sv4gL@2bDdv2mO0#Rm;kB!`u(T8@}fhs#O&DT^vNc2DfZIz=h!Z-r-whhV%t3 zK`EZQ+yMz9D2OuJ0?zZvJRZtE=uE;?MZ~PG5@XdPT!TAw4?|cc3=(eLq*UUx>L2c= zTejSQ9Qb#77T&tco*@slo3djjPg-HnDh6cpGse&$T7rFp$h((lU;I4WcmFt-APY$a z?b;O|VV(lTfBN6J{l~xWrH|dlGx{p&sSVC+83gkoV~M+_D;34y*n)A0j@?9$2Xvc1 zAyF*0p;@B~coR(5>(AmA9f#MDzSyB>#KsAc?cQX_dVvftTJam@Ig>mHLbRI3RI|c{jCI zHn2c~cH0Mx^^K_*RP0O%9J_w`xL*75qwe|jZQ-Ei$H&bpVfXvgyx`yawVLiD!P1Y* z1^OATybigq1_!qGR1DqRv&OeryO1C$2yn9^dycUK1qg5@kgY#gbC)y(U=F*xcTX)h zN#GnvAlb#G_=^hCm$1}@_9nw~N)SNZA_EBg%393^c-0TZlH}4N(S% zBRoQ!7g=LaXY_^4P;7k?jn44u-7#9Xij){ai#sI=mo%=%vUm~?Nwf(eT_Es9s64k# z?@1$G|JG?aOz|?DVI)Zy?ZyP#GMYujpGPt8^{b>Wg5-Z zyi^<)Q03*{#Pg(AXQ{C}t^$499F?T_?1FB%d0|$8V&iG}qf!##bsZ!u+-wvk?*`(1 zIB02JWp#Kcwy)$x9sqz-O&Yuy=5p{<8gZ}%TES9Etz8IqXX3_KzYeGtlPD9$Z+zO^ zXU7B5FScn3)y~QyPfr(1x>*z*wD3sq@tQgCs$C$~5CpuIA>q1kr+NWGUw$z|D|wA{ z*rp{h)Xz?>^Zg~uYs62SMF(K)v%qnQUDbn>mwp_lGA}7bAuiOKdB$(7*vCl@`^_OWL93pB4J6`a26|zvf~JlLK;Ap=o_7 z)QA9rB`3~)lpO+iyTQ8U_)aID8hfy%I-EGfU}IF_II#GTDpM+~WAK1!JY;ju1LFr- zPCb6iSd)o0I*Zqk6-7w!dK%I3d?;IRzDU<(F^iEBZF$*5FqLY}>v&p~z~;&aThWGv zD#Hc!^I9|NZw$}~8l<#W0+K-K1F9@dC!*$)mWK)L-X-P?EU4=-YtL2c>qL(eH@1qU zSOiN55fsAVX0xjWIOX>0EN01(NkC$TK~gADE)&IrleIRWluklRGJND0e$0t@Q?Exf z1kQGi6f^N36wKoJIve&F$CO`P$qd(O*Q7V}MQQmIU!$g8&wWr7*J35kBPGC^7cc9H z?OuWn<}_1<7?W2lCqXMUd-aB?}(_68QRV<82+e=+Tn7 z{f8yACL=djCt6Xk_9=;i?rQmnY#R93Unxrr)>ixm=UNJtx=X$u{ESQL!0Z=67FIRK zrW?c+FfsJ1Z<06@r`7$jM`zu$rbbrM)8hsW?4fzaENyK+h)xP@+UL3%tPN{1EZv;W z$;kZQ+^a36;I>70a0^_h(_h8*Ks+pXab_ki0O6d~SUVwxm+LDag`!%L3CP|UQiIEh zger>TQu7}~aEZ`1vUR1DNP?e3JR{DbjbQn`B)JfnDb`_U6|9g&MNEi^wG7}!aS4i_ ztYOHb$VIE|KxnqZ3!v>KNxMpvf~aYQj5W_=UX6V`82_v^)y!LZ9-d=K;6OLA(}_V( z%DBoGRm{icef@;TFAH8ZpX#_S z=9HJ))6h`u*!=Et=}TAtv#+XZ)$l%3?1saL``(`&Q31iY!96pE1f3+E)8({V;Sz5>65DG!=g<#ijr9~W&L%FDA1b`=(%$NbQix{l9E)Q5@T#KaI-G`=)!`P@Rs>x>u=iQ^2=)Mv1@ zV$JXvjL`s3!Vb*!6g1A=2Wz%XcXQ47!rd)&D^%s2%#0jyHEMzqlL6&TNPS8-eb@Hb zsH`hSy-3ye^k*E`-qibL+1bzsO%cc`L9Jzk&uH_Je~rSTTCVi@;mS}lg4~01EYXIhb@-K z)`!xs+CB4%PZgz%QEyC*dY*1duW%gOS?`2QG$ko2314#Ahz2T?zchUfe`}2r_9^P2 zMP!YDh%||H6@z(x$9b=2Yp;f&fy^70k;mwlVfQ(T^uud64?RK(5FRiR-vSw*QllS? zzPRpiE8VR$m_Hf5)vlFBRJOZ$n*r2SlKU7yu?Jr5};?^Y3d^VK5p2uRtF~e z=Q0gZtN9U)pn4#LLTHI`lDZ%Qma(cVbmTFJ?$Z21u@>ouSi$FgXo?2dvAS%h%|Q9& zX6cmYY@$?xCn>5V=*!^G1em}+-ws5tOHmvxu54xKY;#1yP z8W%l<$IV>W7ws;oB4>o&sWq0aw@nFQ`cvCRdQ z&8?yLbN2?T+`WdN^rc1Hn5Qh0AyaTAtN_?f*JjUtVNheRfCnMgF&H7=CmUsoS=|e` z1I#KH80)d`u))_%TPb@MKvJ1MP1;kgdlcb_AC~v4Z zlI6^@LRR-9!AFrWsf3BFC7WS3{l>~C8oKkS=s|$L^|62G4j7$@W)MP6RRWUxNQ2k%upS zRr91v7~6sRYJ}iqOSbJ96hbK8Og-qusND>}=j|G8_}byeX?30ix# zu`%*n8TJ|bEc&?eUAt!ro9J2?;2@3ll~&v6%c%_XYKBJK*bv<03AE@(sEtbGxm)*j zmCEvGQ^P=`NW-65+6cXh@5nc+SP=_4x+1$^=%Dks{l(ia-A;B@$xSF&o~!X}O?zWs{uK z=fX6>$bY;t-k>k~75{cO#6;_lzFWk0+PpM!4z;t*3UgJt-W!TgXA$&X@~HuZ+~AdQ z7|`Z!$9GzJKmdlgc0RfH={5!EwuQkgWbL68C&v3OR;vHf8RE-@^q5E}F2A-G>uX4s z_6_W^!E%u0>H(|;IE#lmYG4%Nl- zbhb_|u}Rd37)I)Of|Wva)yZWUMH1!fCVCIs4ZzJ4}#y7l`hg?eL%ir z$9vVcfDVmD}ZcLwc5PY$;*DSRKojr{v}4tfb| z(vsKsazgXqboxa~8cR94=3fj+0n>{3dL$s@5>tVxAN z?!w(OQ9AG9%m$v{0=*6B&J5O!#ILMV=(IOjHaiN6MxGXt+rz_jvvea|(!_hPDm7Al z$Zj(Em4NPyD8*l9&+wDvt}^g@5$-AR0Q;+56WvgqPK+hlzjNuBSx!BS9*cDypowE_ zsRF0J0Zm%7+=ZlPq)dmp**>4LYJjo^GFf>#K4rO%e9GE;`B#?7DJk8duH!$jN+3)O z2&?^sH4T2k8vlb8o_xZ@|ACeN2P^u7-S>UMg8zf<9)H5H|ACeK2TS{evG;t!RR4pK z9HkCyV-#r48F;-pYs^ncl_6 z#_Mn}fLMr>cUC9)mX}DyuEto}C?E=mSIflwC0ej`14-rdU_DZs$L?*i#)VSS#Q1nr z=;vv{Q8149=sS6i@&Z2bov>o)4|dXfJUAq1XaYG}$fWgEA}Bs9woRWwNEf9K=Fxg}uHv*V#|I#G)V~_=9awiPee0-x?wf~fdX^EP4N>78 zSuip*ncI}(t;>Si59MDQKj3hugI*yomXcA28HP(!GRG7Z03 zyH!&6*`GG3$H6ll+CO?CUF7uD&oEJvo$PpqwypMKD4c8WIo>G*f3cynq9JQ9;jqt! zTU0-Ex{*pnaLcsihiVVaW>4_VlmM8qjUz|=a>_BPwzsmOYqI5F&j}K zg(?CR_(;=>IivQQM4_r7k(*N9-F0;dHqDCpl8pVEZ+^6M`yDLE^JN#=X1m6ij6^?Q zVwvnd_5lsHj)W+N31w{deEca`Pb%8AF0!R4i$FeCpZ&&|t^lzvtMcw2ik?5?-(A?U z!11Y&sCZW8p-M;N{@^-on#KcPt1+vL6&@M~Qq!}WXhbd>+9_4d07ySDWcvu!(vaC92gWyqCo4R!n#+(FD;&9-yf3I zUY0gLo*v(Z1xssx?&0rxIYTC!Ft3P%!v(>|mYUk`oZgjq5*A7_4JpSnx3QbxEk+q| z-5CctdvI+Ywn7)xHz9ATFpoB|-Llw0zLDfH2qUwOjLTlL77=)!jV0tx#M)h_#izg2 znEv66o=OJTk`irDTGWS1(Z?x`P+-#SML^|d_9qZwH}`(qrDa{HTCuoUc)hMN&+q;2 zgydWmZM6d(g;TpzRL4>E#ta*J#_6T=RX=`A^&>&$KKZ;^@50)%Z!@KKtt;Wc&T?Ro z?mk;|QrS+FWMAw#vOt_d8UF+mk$+okHr=Ve zK!Q3od{)nr7}A~#z{y{|y~7gTqFHJ@i}g+77(ubJL5qtZ*?HxOd*o5~$7_3%4zf7$ zelcOpv}K7b%y!?FRX(KVxrCif5@thb^ zaZ#vCe`}!8vj9%$Ho5n789B+6CsS*vv`tACnd1<0;fwL{8BYujd^hzNs0T1`5HdVl38%Y{w?}DE9p*{HZLtb=6DNE#(DB2M7H1IDKT3@N)0uM8n^zm3zUg^h%KEN zU4+LClt~Hz%ACylSLPAl^+=4g0J1cAhAwJU@?l3qK_S zdict9csGn7RC<@3M%n;L4glYTd*n*zYiV9+Fuo8Hm)9R7!YrZG;z@LIgs&0o=@8^? zT$EPqoU2=zAwN?rTI0|HiBFv_sSRr;222Hoi{wPK532U`gbBl|3%kpd=M4RqH5jSo zRLXXKsL*pgw3W*@?L^ymmdI2!g*&;CP>}o2@s{8B;;RNkHjW#Qwg(F!>zSg-DGVi{ zgb_FUG10OWNmK1B%^`Miiw3bur>thcO;MvLTDsbZ=KOm43LM{AmQwNy952XUks}S) z@)pR@vGo_@hVI?zw%3DVZ%$q!Ra0P47_w%%?mkAw-^Zv;U%^0h6iMZmh41_eOJm#| zP$mY`)uJ%QAp!xQP+VIh?;09%u zWt04Z2I$iB0E@Sm9wq;h8r!dohL;!I>Y620YjMGloGkE86CcNP5(q9Z_CpfNBI| z!Ur^f1;#QR4%Ho>A54$&?DjOaN046ViI$m4qm59OcxAEHiQHpvDSKQ@Ufp-BgvZY) z*khsWtw*b-)RE#$$g5{&j)RvAFocB)3&R=EoOL^r3`QPBLgs}=XwurXcvP+y{4-F_ zlEI*M<=erb(FQN(+=E@wXN-yz7c#&Y2}~{9?5Len_?BH8i7YZT)wfx|B3xMK99wd} zSrK87f1HTwFeleL9Q+jm`ZS_A`}XORftNcO1%q6>SyZYiZ2(Lib-@ybN@rz!7*a68 zzEnx*U50O(>qLg(26Ji^NlHqw!RAm?dv}DGl9STvj>$o&YRCXzhO0Nc^fKeL$`}bz zl0oCFo86n5U$eR1rTf*(@tyfE&xd&~&7sB%tYc<$OW{*e>qkZBtIfCZUFyBAvv5Zx zIgX}eb4dgYegf+~qBejO+7YE^Uh+w< z0a3fnIvdo~-(Vsw*Y3`9nBi0BbI~`>LP)mC(rpqSbQ)tLp#anZ(7`r+Fava}661DK zbQd^i4+lrhvg1?eS%G58q|;O3v&E5f91UIqs04j9t*1_tO2SS&JRT5S;Hz-k0F=&Q zH66(bWVu~;!^=A8D6z%-JJgZfe7T`-4!?=F6@GzzRUcuD{rdy+Jy~Q(?9(Rm3v7lM zDFX31R7CbE-idT0fl6uQ{xz*kQ=mgMK9a~*|EKu}2ZS4Zj$%3L;DAME>y`x(AWVS7 z>8;krk)8dv{rDA9R35r*7`ezSM5hhT($j5_G>^v*=Ff0Nc`BaVz3&dSXV_hm!>mG4 zrS;A7#L?}m`9}Pk$p_ld=)XrPqJ6$DPz9odD0-(Fu-Kb3^kKoLM~Gr!d}KVc zHE1k;g*u2ZEi?Gxh@Mg|nFiFRJ`yc>C=7+X$iO{iM`Yc~BTrFw++^$G?nFF$#53f6 z#qrnZ8%|QKkrzTPBccUhZ!*NYl)v`l9Z)v{j^e|_+#iAAOS%BVC;2CQ7^oQySgpU) zk_0f1)09N`^#B({{<#r3bp9Ku)=&YEDj2EdQIpI`jHc=* zamWsJGX`v*Ec{R8gsxtDqT0)EtS>h4h|w8Wx@(&K&zBm|lyToYVWhc&a~w@WaR@!h z)`fHZU5+LDuyNVj2Mz>8!BP-64Uang;3fZ92M+VyS#4xm8o@GJsA?f(C2 z2RllaFbls1NcO$o!bqk1kYx!@v9W+f$MK;6e=`gH+9Tb5@+<*h>-+2h9A14uXUPd+ zN~c(3#6qatmF!pMBfA;QTP&i_sKB&6P`$$y`t$ zPSuI5jq@9fFI?!2faftVn5j{^#99 zH9<_NEMiRLa;Waf?KMSG>`IxPwWNtF8wvjukGoPH**{2|-MMH4e0+oZg(j2I^WC>F zhpRM$_QnT&UE5KL=uj$q8vG2BCX`OZZiKDkAqvpWtM<2&_g~}g73wZ|y5*=ZFvI6emt)4OgJPNVA>or)<=h?-@ zqvS`+p20J-J3Otf83B^tC?X*lNPH0ax@}Y0Xn@pKi@Y@bt+S`7PvCj_pMr284eV=?BY;CE-tDN2MI@B@q=Xn&iHR zIY^nsZTb61kUcv)!>mDmGW8tn?8|MT#7exlJVcsNu0m-SesetU%bf2Pq}iY=zBmri z!D_akrPJI%J2 z9W^($)X&9>Au;+P$gr~CHV*c=huS#WfeKlYSoG(WL2!pp7QIBamh&Sq1W=1c%_&L( z2&Q24O|rUDGr+s+4Yic!3LgNUjI27%ANe|!iG;&Ta#>cU;4sfaEPKSGmaLI$g?pI8D2 z6AuHbdL^_&Ms@}wM_o0dBFbNx=5P#tTMH=Z4%8(`>LE$P4}Z+Nl~~;D$r9qr#{B{p zWaWUZSRc~je&7lbu_Wr0S^mB0hnCBzah1&B=Q+8{=5g|dh)-Qd+Ms?Q!L^V@^YPkW z@?JND-nid+s6ANF`ce5QTGa=S-!Sn1ae+^{UL zLv&zv-Q!usgr(mWT@1LDC=eq~g$}%1^3X@%Gq02)ijxVjsUBU`CXpA@ih~MyTb_uO zR|c)v?a9_Qr96MVR-F&HMRbx^fyx)Tb}WuS=;uI%gn7kct|!$#!1h#0r2JsGxJh>A z;FORk(SGtqx0e!=M+ThA{TPaO+3Ii{;dam$b~zHQetk<9nGLx8S0->JYD2sQiiDc{ z|3v;8$)zU4=d#ChLd??m%=o8hKT7_8BqO5Lxc{3Z_VRy|{Q6%c&RcJC`Mm+RJ*0;{ zZBVnsxSmjx_%VBY(*cr`0nSLk#0qq$gJZib3G5xAe=@$KxirEB+-nO9U>JBzUu@RaN6jQn}RWy2GZX?{o}!NG&460Cn=?>>ZF-A@f&Bo}A`o0$eK76QpE%(i(ZHV7ICzSc} zkWU*&ZwE087mMDu8tA-#%JS+5zHGIw!+xvH<6KE}g|R0mG$nU8l`PjpeWtZskZ9H3 zN`vC@dDHCd9*XFR8lyB^~_)y(82lLUhXFVs8Me6IiRe0qHEZ;Ba4#6X~o_GCObgq~?&LtV@Vk zm$_*KGRCIq{?hot`I3P)j?RBERt15XKeb+oKk;t};n_8$?LSc{#tnvH$KbPdnjEG_ zPaH_zPs|P{>(5u%H@-h0W_>O#am76W&T-E7$!Y2E;v5c5nyg8XJ`3}yJlTVP>dUws z>9o)a0S1_$4v=Rw!6(zBYlK@$Xy%$Gg+J(lIxTo$drD`w%yp=P>mh&dh)&YRD_-@ zKQJBL5o($kEfFC{$$F-kQC;)z%NpU|oWD<{9dL*EdtT0z0r|@*z)jS)fJgKwWE%~7 z)G>UHCM#=3Rndsp?$IFf9qR6Hn3`Q~QX5hXB8~tW6bEyR6bia1AL7Rd7d}WSqxj>I zZusptva!iPItLVO+@uP_ONAZTbNE z9{&nPulW^SXP=29dBEZDeQJ_4Uv*QHm_Y&G|?cnplts17irRNdbcNG#i0i~!CT zJ|Q!tm~F97a1kX}B&U0A`AS7;vcbKxsY=T9>a%JBjL6tmISSm!u`G=DHR|6T(z0qtfO?gKTCJk;2V(%mQ)X-1^8+Ny?yP~se zqppO^4FXOw6O_f7fxtX~Rivr45DY zD4_j(kvf9JlkD1IBj%nzA(^HCskTxD<^Aipz(M^*$_v4$jM@y8<|1{}2ecWXvsNjS zSDYzS@(g9#B6Uno(CTpXB5iCAv9=c2J#fF}{*3dt*Yr6ah*=de-e09nGDV8tY%P?a zkdjGMh+-3g6^%5T_auc9_~lB$Tq@;0mZIjj9o&i@bcYHXE;-U6dXLU~wn^ zoOo`UOW~(~ldR~Wmn5@uSWY3OZVfvH@%v3VF|x)}dQqQJaL#WuN?FFiR_+R0Y#y(k zVkgkss8D`~H}Ch*s8DwYKQrbu`KdG&sB|i8kvi>D>CQ7yDf!&LO2y|`#b|#E%0e+=jNCe0t_!bI_AjPjdMwg8a? z#hcTJi4hz3r{awO`Ar7;8Ky1;S9~gV6DNboqQN)}!OvobrsDm`a!P+U9#lakg{EDH zY^&8&q7TbRKI%xCIq=refcdLAP&8 zzJbSva#}x2(?YOx?Zo2!Vn!K?_#TMd(kNQbX0|h1iNV!tPZbcO9$5qU~bB~E@ZCq{EkcV zgw+i-=hob)h_DJ-@$)b~7Alpc0YSDGv+gB6s{x4)mi1&=W#dudYx%>l5d+(o?ahep(>cpNKmIfhc&SKR&BE4xvBAiU$m`*#at zU}?P4VUMvf&=?QiOt$7Suk+Qmd1GFP$4_VwdE=6}wM`1tfAc zO#`}=Wq3|SM}1V^pM<*I>R&apU7=J~ORH_ck{6w&hEum~`*;;=R{-eOzr|y1{iB}b zCfKi%m~O^vaa}t$wrev!g~`jV-d9M{LANBvQ*0bg*=i)B z&O)C50)|QgtG<&yNKD)F!zQE&tXw2e=keaom)*eLoqeKX^N z(4HWOI(ZUKc=cV`h9W|~2kcoB@fsQJAiX8HX(Ba3!1X(U+*!b8(x42R$? zLcOjc#IqN{XCZ^}MB_RGn=K=q#=YsaXP3Q@!MNasOZ}{Y==}G*`|rbL6q}xXm;huY zm)GQm9gfLK18FoSMs5^1GMv?F=u&}H15^oxnWC~xWv>{CvhVSqBeSz07$WpxD1zo3 zY|~Kl@9CXt4Z$4R?nyNDh*h!F5T+NumksX<4Cg(Sq0Lx#v zO@G>;W*03dCkQo%ujn$GNy-S3U9Pqpx}VavjW6}kHfj9;chG&99wb08qJfnN$BVyM zjgZG|=g)#Bh&KgOEOZ2gw%kMFORVcQ|X@W9+7IDxX@8qO__f{LPc^l; zenze5Zi()PlsC7t(-8PeiEeHDd#<;!?}C4@C$PUZ>n-Y=KeDm(CV#zQmg@=@nbWw> zGe=K%z9TghWm75@F^vQLgYSLr_P1`AawY1oZo~bm^Hb+!MI)WCJb63}?{{-y&yXVfbc*5~!#tce{k|fWr+1tX^NhTIrOvBN~4A9nTSFz7R zd+y~@ndj&ju2??TDczg5+(h0(h?9}bLdkp@;4HK$uGny2doa1%spyg9;0t)!8F%8J z-A%nelHGwDq#5;I`m4<)7=q5}L}s2e>iiO7WJgTFiUX5{tuX6{2?2d3ZGZ)BL5)jD zzK`}G14a=q!8av$w!W>X;o-8%ue_3d`0 zKhI6FKU!B@GwQ-;5bO+>MI|q5k9C^%bmzLv)!ykUMXop)eV1jWA{(KT*CP0OzmxaaPq;beR=ZjQ zRUe2i1iu!?An7XQ$rcPEu=K0xRsz(&9JvT$+%2L8;?Gv`@0a%LREGEM0~eACC}A9P zHP0SlDc2S7qspj4y$UzE-e6oIE|<=LY0@2~7!mym{4U<7dy!nA5AOFn1W3ZVmnI@x zgjuaBp?=b8$^mZ*N$7x)%buI~T^CbtDG*(0`q)$+XW$p&F2`|d;h+aO?~Q)E(ANeP zU|7Js!Km#nYGbW43q-vm2rl-^VtvJFlk4@hSP#@4kIvt!|0p5$**H zFU+9rOryK51K-=$xLfG(@8|8){ldR@zHFWN0^#*Oysg3Tx?qoKKdhfQ%{aXwh}iA4 z61UPJcUc<~_QWAFba*3W=shqNXEW<;cB^Kt*5FXYv%FiIgh;tbf9dUf)-?L&%b*Bt zlbqP;10rwEIVz(9nB7jKc5fC1R$YY>*lgI?e&!PM3RV&7di?m56DHR+Y_^e|P22V> zlx@*uv{bsFqELptJQe1!8Z1W{OpnatmEYNeqrW7FQJdS zkm$LxQ6_k$qVSG;HKWo_Ow2bSpR9>73|yADEd5;DjPc{EATP28Y0GReK#Ws&4!N}s z6f0H6G+}TPke?tpCXQL+f|%*qD>A~k)Sn)i{obwJ@ZommN^?(1RlQjJ1Ky;VyK*+? zNAUK`>J=)Q#_4at(7GTkyo>9vD2C|T)CU+=u5~5L8OiEY7I8j$ZawrnacPNTnuSJ4 z_+IwV^c&r{WEd4gxxHLwa5f~m&;j6nxl9t}$wSbh0O8g%Sz2{gVJwV7#ihESv<5EZ za;{@^gacGO9nGN`6OY_%!=L^%UIYnQEk}3@g9%?n5>29)vNUZIB4kJL(8tU7F02^| zGlwV`cK?_Mr(zkZ6^&&*$&M_qu zq=AN;F$^XXoG0rJM5hMs_nuJtJn^;j!*DW_p2lB`R>pPy7iJE@em=0kD_4r@+yx4LH-v_f8F4-&*ctLv)8cuEqFyXgK>qgoi^l${mEonJe&T5p?xf+m1}ssJnF;|* zlZ06877e)(Z`3Is(;1$2<#&WY_z`GtO{H1rft;IR>-vY6ZOEZ*0%H$^2AL_f`nW3` zzH)G^fUhi0JjyBYqQfLwp0qYn+e)-%)QVv}90Swt{$7y#y4Ksv&K)|M9(GuU=B;3UV~1GSVJnZ!0=(zc+$6gO~Tl&Zdpy zhD!i2!;~bXr|WdLlx|>A84$ z=UTC==P^$lj?;%2LG|?!ddHkLp-dX$5mxm2u2TCIV2SZ0R4}Zbs|m2DMS$0OjrGT@ zn1!OEQ+F0wtwL)iy*c9idZ+-pXwoYs2v`ovqdTIz#~MO(b98+ylf-%;qJ-lSErVTFWr4tw}2gTDJb=(0d%p46# z$wLmZswAn%onuZ)YnGAAiT;Z47|BouYx2UWS2)q1Kqz63cMYry4Aw$nw;hs5Lu2o$ zGDE_qrpeLB3{$BHFP(Wj#Ub`BGe0puL=VsJ1&VcO#cY&P9}=jN5ymx3Nwkb9p3<;; z(Mk0RYwYI5ZirC$?ZTXXM@TuJ@x9$>N=McQgrAhcIdwv>!9?!%ro{7)^kvnehoRHr zh5hI;e<%#JK~6Zwu@18g&R-^+6cbaGm8D4#yvMLM_|AXkHn1W?siLSYMt%oNdc9tW z>#0zY*xl7^+@^8-q~&D5Nfu6D=R=@SgQ?0Z?C1kLUpRgX?6^j_@%6VPwCC(%8LFQ6_ z#sRi?e{V{kq28^7pv>bMKr``RZ=%B7-W(T>6H}Nb?kIQPYzMuJ<1DTPK&^7#M0@G) zA^2dO8}EKJlV!F>PwN)^nYc2;Dz+G2Vosgh(@ufnRceIjNs!2HI!S$eo%D7aP=2H?72|G zC@fj2QGw6tS~>6W5^8j=H-Zq!OKtEop$M8K(sF96a7$CVRsLK_f>*;gq(t)-+Tju z2J`_k!O`~aW5mFUBFDg$$SK7VA^xPa6vO&bq^nS~l)9<1@W=#tI0LXl-Xz_}+7iyC zmGFHvsLM{dj#m2%=~r);pm-Lc?`kZ4axHzZ^n{9okQ{Z&_EuWv)5AouQ+J_a1alTc z^Tt+z8Cek#+SL9iN}MgZm+YG$vc8?*5Td%upCO6}|pI)O`%5xm&Oyy;k&zA@ZMopQgG*6;*S zrQ$7BfE!wTY)Zu=!VGIYSU53-9xuO|-RjF17<#OQfFE1~(>Z6BGOyFJHp0B>Cpz?} zSasIFxdc7GCB{1tg4fvO!&GFz4EwpwR@jtcL& z&pq4vG#Br?-$2H4C(mCFJQU+~H!yGU#++oI;YOP-d8Qn6H>ECN5`Ml~H& zQ{S*DqrOW4&SviQ2fXK}v2Eww{`$Q)#{2%Ar09sNsO;o0@gGwVAw}4pVvgf z?L?&?0#f1kC$6n!;!dp;iD~e*yGP+EQ8Lg}Gl3}n4*eXayB%q%lQ^dtdI^nLMqPm> zqL2$mx!;TLpszL4Ili&U?HizMPyi6K7v8bBAM?eCvbG6?)DO}ttCX&( zDHG)sHoc*@R_3k)1VfSads1UN;z#L&WGgshH8Gc$36H!Z|v(#*MF?~ zL%E)hTt?ZS5hgmjLXBds?DX0c$`LkEN+Rb8?jMna-k~8am3yGH;8h<<=Y@J zBJa&B2bZNKGJtcYc!?}VbWwpYGv}VKKLl4u*keMktea7UC_T$!zQld}`K+Dtv?O~w zK3Qsk)`q=Y70KQD&9bnXS0@;RCehy!{0X7@P|eSI9n5QkP1{^rQ)8B z>ec7HuC9rtois$eJ&hJFr3W_ycuv{W9!GltuJ6gu$tj!M^}P==z$v6i)E1!w=h@xd zMU({L_04S-Gp5c9yjjZLmN#$7_6^R76dS^DwJ)u}8%%$>;FBSh_hZBF$trlJa_TnC z>!3_mxG~Y z4G^RU=UE;}tBvgih9r2@lC+2U7O|S|s)z4$`@j5MUcLs{knEXoQpYRj79)kp^vWmoo z5@iV5-WS-GC(w}r(1OlqPh`0_U;L1^UD0(}L5I1K;O5)Eti6dl)(Mv}r+f;uTT&Ph zm)X2-wJ**q(n?p^<%hRClv9ozp5`h*OtlkFhJ-A$4F%#k3+%y2dI;r@qeMk(5Qg}O zBW9$cqrl~j4S$KpW87G@iE`wH&v~%@t|GF@1*#Gfw7U7SshHMMX&Qy>RPFk5v%oyi z2Hyo?4?@bk`X_!jcj@!vTe1Lg8z*Kmsg00GhmhDTM#*7`ox|QIte=^mS_?|7s@60uTGRy+cfLQ(*C43{y8 znL~P5n<07{16{XFN;h;fA*QHq$u~dn7T)lB zkD1%Dro_f?=>yb?xag}OY!>PWTRd`Xhfg>f44tuoCF4+D2NnGE26aJRd++Cf{eMee zLysbW$K`$n(MZL=A~!Aiij4kEJWz7B9v3R&%5)PmWTZiiY&2Pa2IklUTX%BL`f_U| zCABCX-q-Hxi-h!E8hUjMl;>0SW&$Nazfse4OG%Xs4#s_`tz#B0KU=W00yjg867GpL z4wC4>Z(}m#hm7^gW%KMnr92|_3PnVYG+H`g@y>X-ShV2NO|V5)m{O9*nU1++LB+QO zNDHp@as*z)FXXM$V%E@YPF%ZzexdqruVX}|5K~nFH4WZFmS^fah}^AOu)bWCcN@2> zpiXhh<)G1J7W0VoAbu@*DOW!FLXO&MfC2bIt_r6!7Z#QJC7itHxFTb(Q#Y+>Vk)|xnmy18rOrM?-sl`158QDX{i$O9G z&e*6HS75I3!S#99bt_w9%aN!N=1CxKWl)GOl3mx5|92IW$At_k?eD}`dc_+_f?Cn} zewdS5Vs88|Sd0Nb@$y>B0$Fv&5LW%Qmv~JJSDlPe^-A$J0nuS*>#`nrpkFeQGgjdq za}~mVH!?|3bId-?Qfx**5o>h z9iK)~V(qvTU*xzfS`n)EDZn|1R(q8gVKg9|w!EodDa+sg*^3uE$CnG%*$eBOCN?nB z-f2z_#2xWQ=eo}x@&*ZJ%k|P)`_|A$6?XUh970JI80~Aeyp6 z+s2@MwXPJVaVRQ2W@F>6sSaq-7qzEex@q~a-#?$lG2(cprfF`MwX*7KY8Y@f!}4t! zCoE$|Cl(;hiug1E(yNs*Z3ZJ>&RwB(-#AhW>L`5i_EmVtI$>XHcr|}jqoY5Q5EJ&- zzX3ETY^Rjr=bc=Ma;=uVJKoy+%!$A}Pl^CXI>F~UunDS^dqln6T<&TSLR)jkB60 zcoNW<{IuoJIHrkSJMan(DaVweq5~|%8|>^ zp-x>Ue(iniM~aQfhD&f{ATN+}OdBR96vGk;Rx^e-5l{|Uk2Vo;N?uWq;Lj)Vy?ruz znAIOH_+_|G8Pj496t{GdgF%l# z=Z{{eT-BQk`ikL(@dNTQ`MOEHUEB%YsQL!IfvX_fBz<6Uzp|5(SPgif5PB63{|Izc zuXis|PFmh|f`R(yFtJ(&@dBx2=T#L&a{7|4MMnLuCxqV=!DfROEZWLGhWZoS&?8aZ z6BM~dT26gEp$x+K{8~c@R6md8Dqsjg8FLnzz>TXT6+V5jeTIu{Hripuz>|BZm4z@~ z*F(w<6XK;v%GyH}d@bzHj*2TlI2z@!0*%}^^ZVLZQc55k4A`}7=n}n_7Gs_eVeqX;2?tcdCtzs$BhN%n| zw|R&`GHAYuR-80nk?hCt!+{>HBk9E2(g$KjNqg#c-(2ATLG%>7dE%jmx#_hxI_UXm zWA`;HQ~>{4{d-Hh!dwekh87Zc?)!G^^WAFa;8YuoU&!w3#P}!Zh+C>?du($5$9coHG zc7HyJ&K3m6*4FkCYGFFrSfO(jigASrm}le>Ipe)v8SWlun6N4zBU8~PcDJtm;Mcr!{i|Poyf;Q)KambX3O*DHFfAr z0!wQ+#<=3(iwNy7A*}AY-KW6%fp+9}$3$Z?hj4Bp+h$zFpDkplG`-}jsjRnmdu?8t z4ilNf^qz&^a0rtmKQq~E6`1Wsq&8U+0lz`sS6g7ep+M|+Ued~R1;jpgYmCy%$<4}Nz1i#3!x=|XEjt`+ZyGu1!iV20v z#uYUTHz2-g%_p0(C4WrkaO|KVcf3n;(D<<8o#UH-rjlRrn zzF~>C2^Zz$hEwknnc{8QB&5MRtdiVGaGYOC32Wu{W<(w`yofB-@=zZ=#X>#3{)qh} zNci6B>U5`=XEwH`;n`#hLrt$6oj2yFSK{?Bln7 zrwJlDQBK{R3-FZWu*4hD=>G1^j;W?cV6AqEQ_$nWla}iCRF+L`2z^5m|CVJwOu{f< zdcT4;nHP_xuMIEJ9vIy7)(~uti2JU`)H^J+zc3l!aCh8!;w}Q4X{Fh% z$hjio`v|cFjMgbb`45pNI87m|O_0JdOkwcm?Qr?H>FjaMz<)v6!6A3NP86|DReAVl zY(E+Z0Yl|E^S?$LyzWYeB3`0L-DM>Y$^I=P#14`t=7>s;k>i(xpU0g+Ct=T=Ks+Zu zCwSQ#@yj5u{8z#{xhSHy$y-wfpe%z~OSl-*n{XlPF68gGv1dQ12ci6eSTkC8W&o%-K@KA^;eV>AZX>|$^ zEcGfEap)LcrKI0#J+G)dO6+7`%T?r3TS!P6!x17tv z@uvq)@FK6E+hxlL%;O;K&OH2*V!D~`{61HZ-!y&jA9lFSKi^4WE7L2dal3Yn$U_40 zjD_8y30_Ke67vIwt+8X1qtH>+cjuo_5T1+okoB2Z+(}5ne0lxy+Tb8O&57@vZEzaC z5%cF+a(7mhHMJ&%rVRvj$&%2Iv_NkAO;M5@rtAYivHgja@-=pkZkgG@=jo+bWPMU%5Y2!eE8lpgU& zh?L54#Swkk@E7SJWY*ouFAG{^AYRtatWGy!Vko$|McaowKaZDT1q6JFZJrBq#+K_8 zZ-M`m3+n+3kw`&R)`yvix1cpdN)@?W+1(`jj^rjc#D^lR9j-Y1NocLfuLeMt7y6)d z=mu@;TP}DM%o*HGVL0g8F>1x7(^vL`>yu;pPA}4UPaS_ZkS(7)PGvGsbjFNN=5Hkx z3pw;mBksWLM_%K?CYz&}m0{r;>cr0Km(M-N@DRSeE}KM!UTTi7XS7a2FYgwi$Gi@# zT9D;^7qW|);8ekP_GO2XW_OFehzh?IIz~m$2n+e}fQY}3n}g^WW{5#}SCwlSqQAWz zdWup&sI%8wI)LR$~*Yo42}v0^l3+<5gnB1JkmGR|QP67=qrGia;oFn)P zFe=8u`_PqvA&ene#}x`O+FFzmz&S7v1p@X_nulh{@lti>Q^hpej9$bEJXC4I_KBNA zl`x&d^_8Ir)n<*_rR|J7pl%ho>HW*WfSQlGtdbVyPLWqC{M5twK%gc=^Fl=jdo%C@ z4RI{&w)!{oe0jt7-%4)I=7Th94e5PySK-r6hWcX~#H^2Z;f?*&|PBv^lgD z)e66~Y3ho3x7Um23P&IyJmWYfH#@T%8LEstje2O!^ijmrEAnHF2=>%O8r5U%MyJP_ zf7R5w+M>(=zhz>!IFEC)YfqXM=Mm_7T8-NVCcI#5dmQI{x|x?hMmD=b_d5D|1o; zOU-Xu-uQA2Mm*-{njVdbi0t&2RbOK%SL$?|2(^yXwY`5(2{0u2ne(ce#DhSUm%{3o zDHela#to&=OqlqocA8QTHWK9}8S$CPep(T4W?Cn(i+o>P%{y8~67aGW^B#c-gsbO7 z=da2^*4x*h*LGHH%|})!4lh^#J`22^sbz_EU@GHVHTr|NjxJF4U)bBa&O5!%#g;k# z970>dQZr=iHG0Fq?Y{DI59cr|{C!=9fWfqAP~>~a1iMEICeo7)zFfr&vq`8!pIcr# zkz_=^@p%G^ou3;HKjB!oq~CQ#yV>=3si>m9404G!e!n%+_t)p7vHrL?4?_6%VPH`N z|4@esps9jMk4qgW&v<+lqlaPskFyf)D82+HHu4Cdl2Mxp^x9Id&nuXpJ8$nznx!H@`W|2scQ}}8}e+Pa#v60 z76XEvu(UXF4_dAmIuY3wRIDupQpbtKBW zLD1sqK4_3~{yr7UAIH6|_dtSFjF}h~%Lw-GuJNInmISHW&4muU86x<mou$@HQ9`Od> zB2!M%|GLfigq5%TC34NV8fX2@WBPa#Kbj5)fz9-Y(+FsJZhGy!l|$BwM>B#&$0H3W zWfj(+RoKx9?`naA*%Bp>7IN`|e%jwl zUvliBV120{U0@pBU~3HcvH$x7m&V-0SYK-#`sXbX5y4t!xD!R8(F6R3ye-l#|32dJ zH&QFT8Eb+h-oc}E^V_DX`{x3x58N1D=HOAQL%$5PR`TCWU>k@O0}wkE0#FJ z+z7DeYYA)54ZPW*2T1ZV)z?Nh?-CA&$2hic75bp2=2sG$wK%O5tRt4yE%pbC3GsAS z{cvTUJ<}b|xU-*(d;?z+xmm2RZO~ox68&L40RDZ1KLD9>_Gh{+KJx5U3B8lZ)42++ z%lq}Cz{mBF|7Z4*$OEjCL3qU(X8|m=ixxlru+erii*Hk?Y?~+*18EOd(N9Hbc>;=- zWh}r};QLzXjj&S^;OyfbS*33b7w)1DepCnOPQ1{rq!J z5|3Bn`#tG)N8;CjH@0M_Xg~`-yhQ^6v=+(d!P6<t{BvdUz@oII^T$~PS+BgB#zd0sqrk0- z*Xa8vTNy?(A|`NsPnFr~73Ir0KEMRjuc&6)b6M}>% z`(LyCZ}Xj)C+A-?nYcc2OH7yulm@~HM2|E(PtV+ z8&%U^eKIre7?3kROCV=ttN(FUV_A!?YtYon4{y=rF34-z=PJQB=SW%7xo^Z>)CC5V z+5%)&@qj|Ju>ItRRLS%pYd*YUj~~3>c(5mB1j1i2y%W)5UdgMV&Rh zp@8B!__SuWm=^T#y`~35pmGh{-o^sg?igvr>6`$lTVvK;nq3IrJSb# zPR1S(54%HG*N+>JYd`!!LbNNqwmrC-Bb@$B*(%pm7X(9z1!UOi>U|;A4$N7cNYQbjfn=CLJFG{$6B|L!|HSH z)dnfZK&(aEP@&?ckWvXcSC39+SWEz?OAo1sgx-5(*qF{mEM4=8`~}fZuNcha{v*fZ z7{JP0(hIscMl?$=y9W<*&#%w+lRb?wj6?*t7H!>j4xSfUQ&(jL1yj(J8d^CUb^Y5dax0}*!?o9xsZ6+qh?{n<&qqJx`tBXP$6V6l@CR>^<*ycB z=P*6(OzM0{XF(4^br#oM6w5j_lc^_1;V?F5!UB_~?gK-@S|X z*sUu(vmi}A5=(<+%>(v;G|i%-QUC?b-nnaI(=;9-P9&1mOmeywL(I#7{AkMBHm)#EI1!EKLfv-s z^bglVCQxxM=}fVG=Uto2K*gI#*vTVs)SPqCXRk=Lw+iUdvI;MbHik@@@m5cZ%pLZHrt%gFAZp4MhbAn0V9%n+gl6gcw!-Pm0IaSzMsxXW* z>F}OJArnvBv2@DZ>{CZJ67hDm1QGu!;KZ5N{8I7#&*t`e97Ms+gBv72X?cyhcAE^{ zj+hPTz8II7HoeOT9M064IwyU_I7Ik`^hXq%o;MPAi>vGSe*VkvuDMrqV7^{Ut9>5s-V`@E za3k>j9Tc0Slnq6kOLFtoZV6Gs%p&l<&$`&Sso- zJO|3j93kMf>~|if-eLegA&y~pu$wGhFjlk6=*pf!%cZM_n zlB`no>TwjS$@mGi@J#1tXi8iRA&W8@>(}su%(IeLr!ZHa9pBa%{;NvTozE&|+|$Ks83oNl9{IQ!vhV}6xHzePSzN$*&KJYvBGpME?rMfwlY z#k$YYf%iS0hX$2L`is2X>-i`^Yhaf*NY?{Jee5KxG)f*zfHD`hyK@h{{aFN#IHw1vlO z*S?Th4|FWFj}6uXWQl{8*5xf7?%H@OAA`s^Ap?ABuaytF78}>J=Sbb#STR96-e*Oh z8r?EzCiEdBkF=WDv%X7_Iv%|6=NXKUn6%K1fp@+lF^u@qGFniiYtUZ%gK)keYP5YF z6?p8zDv%nB^HAYHa%??)ATQp{Kwer`|MAkAgUp?3U5gAa(2NBOk!a{@_LaoZc3z(Z zo6wpG9hSVuQNdeyOS?4N2)o-#0vAHrh_{45ksC~Ak{Q0Xi7bY6gjsi1p1PtJevAm1 zx}-RO2^lS_Mp5KOl<)6SuMgq8zZVDo3INy+{yqp?>;k}6BSP8Gw-6BeUeACAobXGH zXmA$9zwvMZe^ziLl5Fi?dD*xc9o4YJ1yK*ThoQAFx2EpZEM0M|+aaN3PsV+w^n z317$t-xqf#St!X0Pt^bhYw>*s2e2*ly$HAf0lY4w!7g~64Ldum%4@KhkEC0LMgHDp zB}u6d>JgA?$c-leZ;&P;Q*}sM7yPq^A)!0z`vl?Pz&khtH{)chP+)BEy2SzDD%uM* z*6vtSnJ`M`agj)fH%Tky3i}Be82}h)hv16`Vd~$CH&gs5J=}W`H&Jb;{$bMFjLp}# zt^m>>0nx5O-)%%(!uV{CVdv^na|Sir2K-23-&E0ELX;TiVWr;C!gJ8~$VAkFK>$C{ zmZ-%18Dc~69pL$L5+x(1<6Dd9kdnlC6>3~hI{gDc&eSpQC6o9;>cY|v1`ETy=t^Ys zQ5VktlXq!22;BMvOJozWalXIovx=4{7gsU-xA3d@F4fi>2GA$ z;_sg3VuFI5ur*j=4@w*v`X-qb;Lupn;;cJj2rJ;7=?SJpT2dG~OVZXe2l>6FLoF8-$A58;}Rh1u?{CoXR zZPQ5Mv^bOnFFx%EJ;YFHjhN@={0kWIIDPbS~A)#?CmCN;x;YR z(UR5BLzA!UGgKVSE4c*2(zOnFldU;)d)X*Kn3_m@Fm_l<1Ko7b*Y*XDcdyh+O<>2x z5xOZMQFUw{65yO?(a4W^8q!SDzMaiqx_6bCpPKViDDU~o<9u^3iWUo^(V*->Un2D< zi*TfgT2f|o3UH$W3t9J*K^2eF zMIVpOU-bYw3pN{EIe8ag`n_fol{SB;ktn?RN$dO_)Sk+z@ko$b>+incd~`=)Ktb`^3Pr*RT%3QtcUOV@VAyf-wHlo z3`$&<`WA9ujulZUS1jB(`qOz~MY(3-l^PnC{SFFSS(9v+hZvcZ+T$NuE}U6@5q@6h zj{Ok@sczNu(X&@H^NxODtjc8JrG)RDOG_$38a8G>g4oI}rif6>buSV*xWP4<5d;`vYj8ePTd^RM0}Wv+Ec9 z%qXfa0GmaEK!)J8$)knT1WIiy`9x4uHSv{UThw`(gTtsGE(CWn+-Gnc6$wVQSw~J{ z>%pgyg5UKm9;9vVk)!IR1ODp}adjZqWG~)S6ks)}V-T3h5iZ0|KP0n_r3SG2CHX@L zXDzq_8NkF_7yIsy%RxslPQ?WmK?=c6w{Py60``L3$cSYEX4LK-J-ws_ox3_v;wgR~ zC405;ed%63x2vxXf?z!f|j;{!49e~}>qHG+A)^gFh7FZ7t3bzFfM1$=8c zL0FEWuyguqp=AP0pPuzl508c)u~D1!Ik3uN$Tns3?p79+Ks>W<(F3p!W3OY}s*~en z0+A$kjgmL8Qe*phR7h;5qBu^&IT{I!z*^Zvs`ZtzVT`zR9JrV*^>`w~&X@^DtWDlc zPwoq)&TbZwK>T{#T7S3VLctlG2Zgry`_BI9AN+dF%dew5C?#%_%eG|fY%#K6s8p~t z8NWtOk98NkOroCY5a-boAndHmYOyb|bUOaddetP71bESh@0 z+ba`fHaO%*!lqXUzq>>sQnc2464hLi3gC3*$}#D2(_al*dcEP%t_2%6WW2o>fn$edRDcQhL83lU+#pzpa0Nu!izmqrPUB1SR1cLkQ!ec% z(;k~vH(AN+U57Sh4HQ)datXbpV(dtKh^7+Yr+L7WOto$CGMoo?iW3lf;m+GXQ8eQ4 zl5UKvH&@AvuV-PRutT)Z9k8C@uatZqyW8dS@qJq+<>jWorWVfe?{QOK1=FHI)mCWv zxf7VDxgd?C&uc9!vy+Xk%2Yn2WjX|(uSN#7qFfi?bfhexLGo6DQj$3f3Hfe&uvf4L z>k3IqYkZmO7DhJ@760eV0&0t~iE~A*$Pw0atE2$+^sd54=l#lC(y0Oe--e6hir1*oV;1+a8t( z36vXIgc_Au!eLsCdUP}^POd+?wDOE`2=fiiCe_06+kC8`{Ic!ldtDW*8p57$<-Gih zmw4o9iXr?C!6(s81J{ux$UAPh8aDVIHOt{{m8Rx8P4-^s{iY4UW)5duc#xshgk_=^zrPd7`;AV?;(hwAv zt|LD=_nj9HN$xRGgmdPE+`j#_%h%~=TEDJtix-F0PmBLb%hws1C>v11rC2Hj{uA~o zS{a+9qDF6eKMJ8h2OQcH0JU&z8D*0FaA;205LJ^%Kr(y;nUbw+T{7E9w;>o^u-6Pp z4!Ufm_~`DVfsm-ThSb6Oh$zAC6@Tchm>tu?y{Ly=lyb+0z0R2%tea^iSvwmJd#+@< z9v3;x5J19G@?y9Xpq=8Ob3$b|?kz!v`*pZcpiEv|2mcfsnne%(>nk;eAMhR^P$$4A zGPVcB29*umG|5;6KC#(*h$NJ&&)4f)TNwvvk`Ao*h@eeGXGaF>t^kw{H7n%GLDB2d zG?M(uZH&Ftm~;eMj1(Pd`v)G5QQW=kt?0<>TjkhIcwtw%7c_`2jJ+*oa_KI3B0AcX z5H;o*Tpyv?TAlGK8doRVfmT-bWXK)c?>OLrb$XFiP_+>nBx;h1AbqD_(2f4YD`CG1L2mV>AauS7zGD+t^4r zS;jA_&`gJI;=)PU{vOdquB<308L(C)wscT(^n>0`muwK5fra^YO-tM(+e|v#$3A_e zB!5DGQz2gy9w<{^tPm`~rSwyFh4@Veglie|9mcdPJIYuO{V^W2Xf&FcK{CEtiE*p} zBy(wYn;4BPt0^i%!T3gOMD*li$;O$T`K5KF$DQRR@H+SRz%8?9zTq=YHFMec6BI(YhdBRJ@s z&mKI;F{0zpU0Cb7jvh>8euEG$_*9EoxFL*rL$^Q%Vh=wU2W)zxVysxYvihuUVI9{n zj&QNc0O-g^*5qg>OKC`GsjT?xnLcwp6g`_Cj3R+j^_Nuaqou?i-(VfEPaizS^yIE( zX`Q@K8sT}N9Ewg;vH6FPlvDaIf|lcAf#SC%W= zTzzWIO$EAWJj)*EKriDh9U+40y0^RsNBcauH5}`(P_7@l0e{a~!(7npH0_mi=-or{ zN*v}vr_{!ccqHw5bpIW+@@puC?b9|x^!@zdAJlh~#=F%X$xB~a&VapH{Eqhbq!nl} zZ`7_}*K@^qm%CNxQ-~rr{>Mgbq(0pZSHeU8z=G7Jl|dy#Y@dxKpfLU{d>&% zUx0`jeDv-kcm+!fgp+bjM(z6Nbyw#2e<`U2Qc{3024e%HnM%xq8ym>~R7XQYGT111}khVcGuP!vV&I`N<$F~;*4H6@ONXD&D zjY%uc2UUqC6Xf`r*eo((#(E+{&h_r}db_C_)sNHAxCl8)aJUT>SB+iOG!z8~N^5Hs zv?wj#C)Yq}l_~B-yQ4xoJ6sHaUkSXD5(4U_o(LzzlG}}dg}R(i1I)V|gAN66Mj6#} zq#yTW=~|+8D#eSVN%^?ao5KW9Z^orLLzNWRlk>aB6^gHVe4@rP@XV{O?Aj15^*^wv z8-1@(h~lu1o=`++wGTP1XBq>PSu0Ah(o3gZ!^=ub%2z`7t|$dkdZ9!ZS?%n9{OWBz z;LX#zWLe3GWY;{^4;%dXgPJ=bC+m((Xp@`hJz7#rj&85Yi0b1HY_W#5@`w*@C=#Wf z>FWBwqgKJ&n=|2?n&NwCD>~4DNy0}t zyWn)JbWW~u*X=bgg6XPv-{#~WN4#n}kK9m^fPOdY<0qj4Up&BpX+z~*u0N8oh&|U5e6;afAS94PXd!~VM z?KzE32xH4@f=b%+PdE@)3>i_>E`3?p9Tdxi&zkmd$bm)MoLPGw6TqGWvWn0yxynIPIWaC zf(~2^oS$Sg#oLFXE9syUaoZ)Kk{1S$Tb2Fe2)AZOi$>ner#W?2Pr_Hi;(gMgD7NK{ zMtafXjK44A3RI9xZIIMS{1tp;cT(1aAHVO_8vOUh{X1bbw`0|C(^O4{3Hn2e;*hVf z!N!`r&YjG-Z0kK#>9pd-;#)_SLZ3E@?-!wviT5~YtP6BC4Peg#bk+VOG$OKnfV0XT zQh*}_?T->(v+nK>`4N1~Ki9RLFvaaPl}aTXyAt8obBN7dE7)nQT;o;wYq94&Ri*Ok z+PA9ZLM7UA$udB#wkp%&;q@-Zyq@JK2Ku)2Bctzv+QNxAI@N{4jIL;Uahy2B*Ge48 z{=!2{Vf0IeKjgP}?EPp)kuySdf@K6{NmO5M@%1xl&YymT+z5QG;m!n}JwK`KkeU+r z9L3_}VH8CWZm#g!OgycrF;#1to-y|uZwRi>^JYb;zufeTJYVMiLe4+=F&AH*OTMru zXgtTZRwjZ$)U>Pu=YoC?MyuYAa@Hw9D9OrbHgB+W9XBM9iFbuwDC#Lxm#QUus=n$e z2P;Nu8zcEMA1CyFMkMBLt~d;p?+E3sR;SF5aPm9;D_Vc$)MViFB(b!ho0~ws9-Z>J ztw+4nYN6`js6|-+sfvhlsscv{Z+7(6$2rO>5w)f1R!8)^;FE&ljwWOmGV}U?Iy5`w zTkzJO%Vh6wxh6<=!oMBSbV%x~ejoYivt!jwvSk!vnYS7~V$uz?*1)}kW?{p*fSK%j;P=?1@#{a;p>1)Qd24c}4#&U}b(UZQ<-o+T z7H*&M!)ma;0Qmj^7V|(r;xB;r4``hO0#JW}*Tw%#p#B0w)j(kFKL9Ycc>AmyRt<&< z__;_3n@K3EQB8n2865)zG8YL)8Q6{5EbW}u(d0ERw4mshm_xTSnjxH(BuU!M2sti5AD0yrvF$a17K)+ULCp}o?Z5njdL4i98ny#y z$9N)}M};D_F7c#|nR|&L6fW&JRLHzUaSo4xRc`>tBntGYz>N4l($_AxVj*0Jn$EMMK;ik{^GF1}UH^VfyZ0CWq8P!>LupfG(g|6@`1otvA?1yK_FLdBc9 zbvk65x4EweC&@*y*D>?o7-{8Hh!uVFgu`AdGxA3)ogdhE{T;U1TNDTw^Zj^1A4k=X zs3>|Wg3gQs@J{F_@r~h)M9l|h*~QTKBpuRrhF4QjNcPI&7rb$iW=rOr3|w2ugn3Xq zw4{~IDkW0I`TOgY3TrmGUV;UhA)Cy8wj!7=?;~FC8~9NoH6p{Hr^0g zS5x=vl*WG#lAWO=Tm`qn`V-esv(-hz;hhb;p!iVk@9ga47)d%C^3^~16d5?=a$UBv(ogu#!UW}_siaz{IbB2>!cHwJ7 zRD>dDlECaAM^}X2jS^(Qx}NbkM3zKWs=_d!X8I@%rxHe;_m=)inD>X0w#UGG;=iZ( zAd6J9I|n+ldU9lL!vj^u^tK^FmmDy9Kr}^10J-BJ$NDMtA=H8sPswPGqgS)`o9hAN z@9U8BDCFh=TwO~gnh#jS-=E3hw}t7>3pWKYy6mh6LkE%1pWstRCj@pjeiI&#*)~JJ zr1GxywxA-ESZ)+7iY6QZO_E zFI}Yy^Yt$7AnZIl%LCnL3MQYI`#iA9tS(JPrte4DRlewkOvT2~Y=UmQvEBE4&3##? zX$Lj3qYfB+ocjjYZvT2N#~5OxDdc=!PM}?CaXGCCei8IXy;>akTKU(4#f3!F?)=zR2q8cR#@P0BQJuxs^Sgd;D2!i>5o71d zG!UTVh5?)(VSBqVib3Tro@u@+ZN)_5Gr$bF!8H75)^L{~sNQz0Q~$kVk>nt3NnYCr zj@>F6?T_+<$;-BEpGKk2U@J!#!JP2KM@Qqq&{@P`!=29??-^r8fkcj2$ERG}25~DS zQcon7olJrf1q<1*cJLA*)XrIS*J|zu=xAAb|vk?{7YK9vmY-akMMXR%L)-AL9 zZs_eR8G5sxu9=Y>J6X?bm=n2Sje4mc;Mcg{p(4(&PuEPZ$<17$2~m)(dLD2Z30=ZP zbMrCy7h6`{@OX{@1ugF{@fS$w?5vJ@sX2=d_&O=TpZ&2}*ucRMf8@8=F(v8#da$8UkcUcpD*b`)>!Oz0O}Ef3+1jmN}1!3t?)u%L*j@ zP+rQQH#Ul$&E&xSBAn5HW!2n5P2DJa`Fh@b3^W$sMld=*YSJg!n8>q{a-L_{ZG~+@qoBC+r(~245ql95c z%#Qyh%T!>pbRPvKOGcT0$+Dpdm@IYvCd>aUX#ZLuPZHdsp#zBq9pg~d(o4Pil96yK z$VyaE8DYS=pjvfG^YDZHqf)GDbQ;l<{zlHcN_a9 zIs`O9Ot=-_IF=aOX1|36HfV{|2Ju!bkLG10`f?d;f? z7!%vJZBCqtZQItwoY=M}xjW~ad)NKhYgIpA)%*2E?cMzrv}X+D5^z)Yj0f4ARmXUe zja?dQCDT%((y<49<5Bv)G4u{pG}8I)K_$qIj>r#@K>F6RFM*@JL?KiG_hqz9a$df# z7MlrFl1(0fx?nKJwA&o(L#;AI)RGepC&q0QpPVGwOSBR7EGd20YaA|t_VD)anI2iN zLM$@DQHj(85@2ZQt}B*F&QxoA%mKD3G!H9NY2x){T9(5yXoE996@V9%Cp*+xDnYYnJw^r$fV|c&f4=VkiYMAXz&pdEzR931CoSR02z>#BH!s zSeZ8{@!;_BbcqJen#VK`wNe(-Ml2BG3$;?F{PARhyn6yslk8BLzLw2Az_Qd906kxv z`KQx$?EA|7#$HFvG-uKiVs8TzS3;sH7Qbq=86N{5+nd6$2XyYA(BVn8x~rX!22VLd zEzX0O8tBtYScD;^u&g3*Zjj;fx1gzSs?^zy&%#9A(~$wy-NF~PHhC#w3YgIPtt3E$ z7Yrroxbm3h&l(JJ+j>vgJDgqsJ>3=VTkQGnH9pIYrco(f=QKXc6~{x=4(kIMF_n_0 z0Q|=qhnW}2Pzc(BAMU6eh1^+8Jn_s(b36qvL;S<9x7wCmqs90beCS0rA(Bqozu&AX zFj#TaZZRE1_?5QaKedcCCUv*P<+y&8P4)3`f9bYpQF1i5k90jvrT52|Sb=x;ca4t+;Jv_)ADESz z+=F(crDxDRMAK{5b@gGmi=2zKSP{w26??S0lmjcmw^l2m>o%SfvOeMdnf{#1;1sXP zQS$B1;e7IP2|blimNNdie$*#UnVGkhjcaSntt4gYF6|u#nWk9pI4Yq0F~@1unEovN zykHq@+gy_XoI~3C0cEhqANBRJZenOcoQ|s<-Sgl+fEtItvtXpdk<27^SQEO3SlAB? zGUul7EBn~xm%s9~%k?>(ND=}o-HZ<_a~ikk-l4}d!CIGxj3^7gkj|%;%=-s4+F5}L zWc9fWF3LFL3l-ngStZ#(y;)Qcx$n7DYqt^Dza97b_&|+gMCI4{?LZv&`&l3FT+nc(jF;R9FY3nb@>!*2sg)h7rKn-iEN`_Q(KPXW#O0vE?tY8G<>tT4I=jCaU%rl~qz(6awglA7wxp_x2*ptAP?Re^^+E8ilT;=fDSa^? zt}c@%>kA}&YUwoqI;`9sF0pI(awaGh5RA-*j1FNSCJ*|oambB=<0+;55YG8g_EZa{ z&%hVZTNjRjQhcwbbOMK`wLFyTfJ-ZY{$b+9lIe4Yn)DM64T(?<6TN4OFHcgI(CF8N z&jaiRew|R!-vr%0s<0freLILnufor6e0zeka9O|GOcEkL)nAbCvMpjNOJ z%R5MSocuqxT*c!0nhzlez5`N2kZ5^C|C)M!M%X@B(_M6M(XSW-%*VD;m9A*<_t>k~ z?x7k#P%9H^x4+&yrV3`mj1DSxGcdC##|+lnj5;NV+D03$@ZP-bkW?lK8$5<_%k&`8aDgm2eQM%6QE}KnIx}stL5^BG_p7gK9!A*Zp0S`P-XC7!B4iRjRtou0MRs zu*LkKRb2dDxM@&ouL;#2HOVc80Yv{JiY6r0ElwMYZHCxtKPw`J1}QFfxO?`7ePs3^ zNvhi(b`I{MbnJ2v8+( zD0|9!5&oNsS60SUOKghq6UQsED{JiI4K^HDg)Sm;6zNl272qOD@b0b^K>B1=Wqj*# zvuGR}#|@I29HLD=oX@&Hzd5BahF@e~($hr51e4v?1C7O#xdXF|S(kow{ zYD6_-Yz6xS)j`F0I(==W&s?lU-cWM{enYk+69nVFrY!ihuU{g=8|v4LW7{GbEe*zL z0rL)Ovbket3$^K7PM+P{x~8g(qE#lJJYH^bXp#rx7+~3M+$mwKKE0$JKWTK>a6oMI z;HIvrd&1)#U`jK`wNV85Ri7k+g=Wi^6QfB3bC&|be8E4T^Gz?)EflV7A=b<@hZWya z%&XA)l__;{ed_0G)HSSJO64K`y3t_Yt`rkto#ajl8_8+ECu<;jH8V%TJ@HM z9jfg7%U;FC9&XzUe`{tpLHrQniY+SBZbMkKYuz{u9HBCJ>WZP>ytgxkdp7~FhM&*t zR1i-YB?V4;Y({vBC4s`YX)_fK(CiTtOg#YxgTwMR^bm ze2!}3I8U=#$qpTYFjlEA36;`jCPfOSB7{hdy&^#6j-Q~)Vq&9B6LF?XQ5$AZSZ}*) zP*3AT+byKh5eCFa)@2MGSwNRmg4|5U8f24=jnncco5%f5_kQK{wq`VzUa==|*#!*{ ztGaNKxZjM{6W|;|>{^Vikd~iGr~L_4(UgKPT@@$_%9!_)TgWYDu_K1CF=F>}5qv4- zIClqAJCBpwl7tC`RWhiDcyc0G#JrwGtE-7+sm#gQ_Jlk%<9<5mFW(=LwcPpcE!EGJ zt_TC^lFY12@$gP8#KtLtW(wMFQy;;w>G!$G^AQb;SP@@qwlgbtIhyAPEwLscVpSqu z?czhp?M#;X{T84*5ajHBtNG&9`1mwkVrLp^)W#&WOayS5nFn+@*08J^k0(Qf?SfE2 zC`U00F9u*SBsPERU)rB%-5d#abJlJ~%Xe&+g@-PG6=%ENvD4-8IUVf*hwsv~boT_xR_v#o4QkdHLUXYs}?riPK+LTY3pxrQW|@VvP(cm8@)6voA1}28cwAv=GOMF-fRw z#vB|HFO;7h$dr04O#EhUJ)tnWfJMpd1|(odqT@D7JoxzCiMHgh_BZ@-M-kwfUze4@ ziC06gGoIvrErx0w<-1AqxG!_hb4Fd9-ok?)CdO&(X*wLSi8*U2bT(4hoR=|yBQVVh zq|tn?5p(X3c*I9cx76CK`k@o1QQeeDXA-?QstFXcLbo=EtCdf8QUWjIij)1M_f%#~ zPQQ&v0Y|Fd@r$ylvafCkAuclJ&ym%p*+bmd2l(4^XPXLsc};BoL^iHnHF2tnzE%SOr}>= zThPL6Zel)&CwHl12>K+l7hVV>)fS3}c1^pDfBAuP$&J{xCK%`vKc}N}5}q2`g_JEl zy#k<{G4#?3+sPw}6)WPYyN3OCS<&`V;q0@jRaau(srpw6emEBiw^}rrr=jnou?`b1 zcym~_ZA0jVy59Hi%8re)cks>FGkIG6+4fC{lfW``myHluDSzCabG1k`SV&{uFKaC} zzDWY^X1fD*Gh_z7tiw8zYdGG~J9+Fw26`0t}B~Ka|S*pN-#$&8b*$ClLg3mmmt|Z-Zqc zR7_!0$`1-tM%DR+9M6WR@;4WgroU|B#>x2q<{YDxkNgS;AIfnyC;B@RFEQBwwyzZd z{~>X2&PzWLbRn&5zf7adcs2!?EYP5t6*Z2QuoC!%kk3mgM`oAYHB(|7UveK0`VSeA z>&cXy9U-rhsq!-?$YuejbCDA^?QMR9?{%2tp8hq>a3?|73{&4eXdcr<2;l0{x{u9$cErE2C&dmJ;gsS7+6DvjP$$D5+#gyC?ex zXl)KYeYDWiv=bES9NxIVc+Pz+QNW^Vrv5My+pRc6Z5bh~o3*iBl4XQFXVi8_3A>{tJTr4B|fgBxU^M*d|(3BX($eKH5~rh|)+YbE>;p$BdEn>tX4?B?WbXFNY*D;*KW~ zj0|j&eKY$dAXao-xPOn_NZP-Ii!DIoBY>qBHbJg(ZjWjXqP>!T&R$|B`%MFY6Q?Es z<^b&h%t1@D2;Kw2Y&&%yOkx~exS9z#2WLDX=^E87awxV+x^E8Jej974R(NAkOJd~yrtA8mO|sPJT*Ve7;ApN1{wW3pg~npgN*qd z?C(CsDX6#C%#WrtPgq?%hPm8 z+7kJD^h-zCSu1m8^<+ZkOfGRpzQ8!!;&2Yn#9v_!`ja{09&CY&yd1F~YcDu~@vNGN zS#`D@v*qOrSWF@?S?_?%D+os9VZ>vj-J5A%{fL^v!Av#?DRie-{N9n=;a2{T&)m~G zb_{9KF!{FZ(Ku%b7}g@i0dr=h#d0bcSq|Z}2D=zZPOxI4LvYK^X4{w3M<_HX%$ec2 zD!d#KXQytdRORpNsaI@07Y4zomX7tG@og&|@(k85gtrQFkZ?Dx?J{Kq!4+z*XVMj+ z?g@e_CfwTuHRoViHMy|r#5n9FBN$a`N(h@ za@f4p0OV};X?n